Module List
***********

   This is it!  The top-level list of the over 4500 installed (documented)
modules on bitbucket, as of Mon Mar 26 15:39:27 PST 2001.

   Texinfo source for this file was generated by krishna running
pod2texi.pl.  This info file itself was created 26 March 2001.

Module Index
************

   This is the full index of the installed (documented) modules on
bitbucket, as of Mon Mar 26 15:39:27 PST 2001.

AI Menu
*******

   This is the documentation for modules associated with the main module
AI.

AOL Menu
********

   This is the documentation for modules associated with the main module
AOL.

ASP Menu
********

   This is the documentation for modules associated with the main module
ASP.

Ace Menu
********

   This is the documentation for modules associated with the main module
Ace.

AddressBook Menu
****************

   This is the documentation for modules associated with the main module
AddressBook.

Affix Menu
**********

   This is the documentation for modules associated with the main module
Affix.

Agent Menu
**********

   This is the documentation for modules associated with the main module
Agent.

Algorithm Menu
**************

   This is the documentation for modules associated with the main module
Algorithm.

AltaVista Menu
**************

   This is the documentation for modules associated with the main module
AltaVista.

Apache Menu
***********

   This is the documentation for modules associated with the main module
Apache.

App Menu
********

   This is the documentation for modules associated with the main module
App.

AppConfig Menu
**************

   This is the documentation for modules associated with the main module
AppConfig.

AppleII Menu
************

   This is the documentation for modules associated with the main module
AppleII.

Archive Menu
************

   This is the documentation for modules associated with the main module
Archive.

Array Menu
**********

   This is the documentation for modules associated with the main module
Array.

AsciiDB Menu
************

   This is the documentation for modules associated with the main module
AsciiDB.

Astro Menu
**********

   This is the documentation for modules associated with the main module
Astro.

Async Menu
**********

   This is the documentation for modules associated with the main module
Async.

Audio Menu
**********

   This is the documentation for modules associated with the main module
Audio.

AudioCD Menu
************

   This is the documentation for modules associated with the main module
AudioCD.

Authen Menu
***********

   This is the documentation for modules associated with the main module
Authen.

Aviation Menu
*************

   This is the documentation for modules associated with the main module
Aviation.

Aw Menu
*******

   This is the documentation for modules associated with the main module
Aw.

AxKit Menu
**********

   This is the documentation for modules associated with the main module
AxKit.

B Menu
******

   This is the documentation for modules associated with the main module B.

BIND Menu
*********

   This is the documentation for modules associated with the main module
BIND.

BSD Menu
********

   This is the documentation for modules associated with the main module
BSD.

BTRIEVE Menu
************

   This is the documentation for modules associated with the main module
BTRIEVE.

Barcode Menu
************

   This is the documentation for modules associated with the main module
Barcode.

Be Menu
*******

   This is the documentation for modules associated with the main module
Be.

Befunge Menu
************

   This is the documentation for modules associated with the main module
Befunge.

BingoX Menu
***********

   This is the documentation for modules associated with the main module
BingoX.

Bio Menu
********

   This is the documentation for modules associated with the main module
Bio.

Bit Menu
********

   This is the documentation for modules associated with the main module
Bit.

Bone Menu
*********

   This is the documentation for modules associated with the main module
Bone.

Boulder Menu
************

   This is the documentation for modules associated with the main module
Boulder.

Bundle Menu
***********

   This is the documentation for modules associated with the main module
Bundle.

Business Menu
*************

   This is the documentation for modules associated with the main module
Business.

C Menu
******

   This is the documentation for modules associated with the main module C.

CGI Menu
********

   This is the documentation for modules associated with the main module
CGI.

CGI3 Menu
*********

   This is the documentation for modules associated with the main module
CGI3.

CIDR Menu
*********

   This is the documentation for modules associated with the main module
CIDR.

CIPP Menu
*********

   This is the documentation for modules associated with the main module
CIPP.

CONFIG Menu
***********

   This is the documentation for modules associated with the main module
CONFIG.

CPAN Menu
*********

   This is the documentation for modules associated with the main module
CPAN.

CSS Menu
********

   This is the documentation for modules associated with the main module
CSS.

Cache Menu
**********

   This is the documentation for modules associated with the main module
Cache.

Calendar Menu
*************

   This is the documentation for modules associated with the main module
Calendar.

Carp Menu
*********

   This is the documentation for modules associated with the main module
Carp.

CfgTie Menu
***********

   This is the documentation for modules associated with the main module
CfgTie.

Chart Menu
**********

   This is the documentation for modules associated with the main module
Chart.

Chatbot Menu
************

   This is the documentation for modules associated with the main module
Chatbot.

Chemistry Menu
**************

   This is the documentation for modules associated with the main module
Chemistry.

Chess Menu
**********

   This is the documentation for modules associated with the main module
Chess.

Circa Menu
**********

   This is the documentation for modules associated with the main module
Circa.

Cisco Menu
**********

   This is the documentation for modules associated with the main module
Cisco.

Class Menu
**********

   This is the documentation for modules associated with the main module
Class.

ClearCase Menu
**************

   This is the documentation for modules associated with the main module
ClearCase.

Compress Menu
*************

   This is the documentation for modules associated with the main module
Compress.

Config Menu
***********

   This is the documentation for modules associated with the main module
Config.

ConfigReader Menu
*****************

   This is the documentation for modules associated with the main module
ConfigReader.

Conjury Menu
************

   This is the documentation for modules associated with the main module
Conjury.

ControlX10 Menu
***************

   This is the documentation for modules associated with the main module
ControlX10.

Convert Menu
************

   This is the documentation for modules associated with the main module
Convert.

Crypt Menu
**********

   This is the documentation for modules associated with the main module
Crypt.

Curses Menu
***********

   This is the documentation for modules associated with the main module
Curses.

Cz Menu
*******

   This is the documentation for modules associated with the main module
Cz.

D Menu
******

   This is the documentation for modules associated with the main module D.

DBD Menu
********

   This is the documentation for modules associated with the main module
DBD.

DBI Menu
********

   This is the documentation for modules associated with the main module
DBI.

DBIx Menu
*********

   This is the documentation for modules associated with the main module
DBIx.

DBM Menu
********

   This is the documentation for modules associated with the main module
DBM.

DB_File Menu
************

   This is the documentation for modules associated with the main module
DB_File.

DCE Menu
********

   This is the documentation for modules associated with the main module
DCE.

DDL Menu
********

   This is the documentation for modules associated with the main module
DDL.

DFA Menu
********

   This is the documentation for modules associated with the main module
DFA.

DNS Menu
********

   This is the documentation for modules associated with the main module
DNS.

Data Menu
*********

   This is the documentation for modules associated with the main module
Data.

Date Menu
*********

   This is the documentation for modules associated with the main module
Date.

DateTime Menu
*************

   This is the documentation for modules associated with the main module
DateTime.

Db Menu
*******

   This is the documentation for modules associated with the main module
Db.

DbFramework Menu
****************

   This is the documentation for modules associated with the main module
DbFramework.

Decision Menu
*************

   This is the documentation for modules associated with the main module
Decision.

Devel Menu
**********

   This is the documentation for modules associated with the main module
Devel.

Device Menu
***********

   This is the documentation for modules associated with the main module
Device.

Digest Menu
***********

   This is the documentation for modules associated with the main module
Digest.

Dir Menu
********

   This is the documentation for modules associated with the main module
Dir.

Document Menu
*************

   This is the documentation for modules associated with the main module
Document.

Dunce Menu
**********

   This is the documentation for modules associated with the main module
Dunce.

Emacs Menu
**********

   This is the documentation for modules associated with the main module
Emacs.

Email Menu
**********

   This is the documentation for modules associated with the main module
Email.

Embedix Menu
************

   This is the documentation for modules associated with the main module
Embedix.

English Menu
************

   This is the documentation for modules associated with the main module
English.

Env Menu
********

   This is the documentation for modules associated with the main module
Env.

Envy Menu
*********

   This is the documentation for modules associated with the main module
Envy.

Error Menu
**********

   This is the documentation for modules associated with the main module
Error.

Event Menu
**********

   This is the documentation for modules associated with the main module
Event.

Exception Menu
**************

   This is the documentation for modules associated with the main module
Exception.

Exporter Menu
*************

   This is the documentation for modules associated with the main module
Exporter.

ExtUtils Menu
*************

   This is the documentation for modules associated with the main module
ExtUtils.

FAQ Menu
********

   This is the documentation for modules associated with the main module
FAQ.

FCGI Menu
*********

   This is the documentation for modules associated with the main module
FCGI.

FFI Menu
********

   This is the documentation for modules associated with the main module
FFI.

Festival Menu
*************

   This is the documentation for modules associated with the main module
Festival.

File Menu
*********

   This is the documentation for modules associated with the main module
File.

FileHandle Menu
***************

   This is the documentation for modules associated with the main module
FileHandle.

FileSys Menu
************

   This is the documentation for modules associated with the main module
FileSys.

Filesys Menu
************

   This is the documentation for modules associated with the main module
Filesys.

Filter Menu
***********

   This is the documentation for modules associated with the main module
Filter.

Finance Menu
************

   This is the documentation for modules associated with the main module
Finance.

Font Menu
*********

   This is the documentation for modules associated with the main module
Font.

FormMagick Menu
***************

   This is the documentation for modules associated with the main module
FormMagick.

Frontier Menu
*************

   This is the documentation for modules associated with the main module
Frontier.

Function Menu
*************

   This is the documentation for modules associated with the main module
Function.

Fwctl Menu
**********

   This is the documentation for modules associated with the main module
Fwctl.

GD Menu
*******

   This is the documentation for modules associated with the main module
GD.

GIFgraph Menu
*************

   This is the documentation for modules associated with the main module
GIFgraph.

GNOME Menu
**********

   This is the documentation for modules associated with the main module
GNOME.

GPS Menu
********

   This is the documentation for modules associated with the main module
GPS.

GSSAPI Menu
***********

   This is the documentation for modules associated with the main module
GSSAPI.

Games Menu
**********

   This is the documentation for modules associated with the main module
Games.

Gedcom Menu
***********

   This is the documentation for modules associated with the main module
Gedcom.

Geo Menu
********

   This is the documentation for modules associated with the main module
Geo.

Geography Menu
**************

   This is the documentation for modules associated with the main module
Geography.

Getargs Menu
************

   This is the documentation for modules associated with the main module
Getargs.

Getopt Menu
***********

   This is the documentation for modules associated with the main module
Getopt.

Glade Menu
**********

   This is the documentation for modules associated with the main module
Glade.

GnuPG Menu
**********

   This is the documentation for modules associated with the main module
GnuPG.

Gnus Menu
*********

   This is the documentation for modules associated with the main module
Gnus.

GoXML Menu
**********

   This is the documentation for modules associated with the main module
GoXML.

Graph Menu
**********

   This is the documentation for modules associated with the main module
Graph.

GraphViz Menu
*************

   This is the documentation for modules associated with the main module
GraphViz.

Graphics Menu
*************

   This is the documentation for modules associated with the main module
Graphics.

Gtk Menu
********

   This is the documentation for modules associated with the main module
Gtk.

HP200LX Menu
************

   This is the documentation for modules associated with the main module
HP200LX.

HPUX Menu
*********

   This is the documentation for modules associated with the main module
HPUX.

HTML Menu
*********

   This is the documentation for modules associated with the main module
HTML.

HTTP Menu
*********

   This is the documentation for modules associated with the main module
HTTP.

HTTPD Menu
**********

   This is the documentation for modules associated with the main module
HTTPD.

Hardware Menu
*************

   This is the documentation for modules associated with the main module
Hardware.

Hash Menu
*********

   This is the documentation for modules associated with the main module
Hash.

Heap Menu
*********

   This is the documentation for modules associated with the main module
Heap.

Hook Menu
*********

   This is the documentation for modules associated with the main module
Hook.

HtDig Menu
**********

   This is the documentation for modules associated with the main module
HtDig.

HyperWave Menu
**************

   This is the documentation for modules associated with the main module
HyperWave.

I18N Menu
*********

   This is the documentation for modules associated with the main module
I18N.

IETF Menu
*********

   This is the documentation for modules associated with the main module
IETF.

IMAP Menu
*********

   This is the documentation for modules associated with the main module
IMAP.

INSPEC Menu
***********

   This is the documentation for modules associated with the main module
INSPEC.

IO Menu
*******

   This is the documentation for modules associated with the main module
IO.

IPC Menu
********

   This is the documentation for modules associated with the main module
IPC.

IPChains Menu
*************

   This is the documentation for modules associated with the main module
IPChains.

Ima Menu
********

   This is the documentation for modules associated with the main module
Ima.

Image Menu
**********

   This is the documentation for modules associated with the main module
Image.

Imager Menu
***********

   This is the documentation for modules associated with the main module
Imager.

Inline Menu
***********

   This is the documentation for modules associated with the main module
Inline.

Jcode Menu
**********

   This is the documentation for modules associated with the main module
Jcode.

Kite Menu
*********

   This is the documentation for modules associated with the main module
Kite.

LEGO Menu
*********

   This is the documentation for modules associated with the main module
LEGO.

LISP Menu
*********

   This is the documentation for modules associated with the main module
LISP.

LWP Menu
********

   This is the documentation for modules associated with the main module
LWP.

LaTeX Menu
**********

   This is the documentation for modules associated with the main module
LaTeX.

Language Menu
*************

   This is the documentation for modules associated with the main module
Language.

Lib Menu
********

   This is the documentation for modules associated with the main module
Lib.

LibWeb Menu
***********

   This is the documentation for modules associated with the main module
LibWeb.

Lingua Menu
***********

   This is the documentation for modules associated with the main module
Lingua.

Linux Menu
**********

   This is the documentation for modules associated with the main module
Linux.

Lip Menu
********

   This is the documentation for modules associated with the main module
Lip.

List Menu
*********

   This is the documentation for modules associated with the main module
List.

LiveGeez Menu
*************

   This is the documentation for modules associated with the main module
LiveGeez.

Locale Menu
***********

   This is the documentation for modules associated with the main module
Locale.

LockFile Menu
*************

   This is the documentation for modules associated with the main module
LockFile.

Log Menu
********

   This is the documentation for modules associated with the main module
Log.

Logfile Menu
************

   This is the documentation for modules associated with the main module
Logfile.

MARC Menu
*********

   This is the documentation for modules associated with the main module
MARC.

MIDI Menu
*********

   This is the documentation for modules associated with the main module
MIDI.

MIME Menu
*********

   This is the documentation for modules associated with the main module
MIME.

MLDBM Menu
**********

   This is the documentation for modules associated with the main module
MLDBM.

MMM Menu
********

   This is the documentation for modules associated with the main module
MMM.

MOP Menu
********

   This is the documentation for modules associated with the main module
MOP.

MP3 Menu
********

   This is the documentation for modules associated with the main module
MP3.

MPEG Menu
*********

   This is the documentation for modules associated with the main module
MPEG.

MQSeries Menu
*************

   This is the documentation for modules associated with the main module
MQSeries.

MRP Menu
********

   This is the documentation for modules associated with the main module
MRP.

MSDOS Menu
**********

   This is the documentation for modules associated with the main module
MSDOS.

MVS Menu
********

   This is the documentation for modules associated with the main module
MVS.

Mac Menu
********

   This is the documentation for modules associated with the main module
Mac.

Mail Menu
*********

   This is the documentation for modules associated with the main module
Mail.

Math Menu
*********

   This is the documentation for modules associated with the main module
Math.

MemHandle Menu
**************

   This is the documentation for modules associated with the main module
MemHandle.

Memoize Menu
************

   This is the documentation for modules associated with the main module
Memoize.

Metadata Menu
*************

   This is the documentation for modules associated with the main module
Metadata.

Modem Menu
**********

   This is the documentation for modules associated with the main module
Modem.

Module Menu
***********

   This is the documentation for modules associated with the main module
Module.

Mon Menu
********

   This is the documentation for modules associated with the main module
Mon.

Mortal Menu
***********

   This is the documentation for modules associated with the main module
Mortal.

Msql Menu
*********

   This is the documentation for modules associated with the main module
Msql.

MySQL Menu
**********

   This is the documentation for modules associated with the main module
MySQL.

NIS Menu
********

   This is the documentation for modules associated with the main module
NIS.

NNML Menu
*********

   This is the documentation for modules associated with the main module
NNML.

Net Menu
********

   This is the documentation for modules associated with the main module
Net.

NetAddr Menu
************

   This is the documentation for modules associated with the main module
NetAddr.

NetPacket Menu
**************

   This is the documentation for modules associated with the main module
NetPacket.

NetServer Menu
**************

   This is the documentation for modules associated with the main module
NetServer.

Netscape Menu
*************

   This is the documentation for modules associated with the main module
Netscape.

Network Menu
************

   This is the documentation for modules associated with the main module
Network.

News Menu
*********

   This is the documentation for modules associated with the main module
News.

No Menu
*******

   This is the documentation for modules associated with the main module
No.

Number Menu
***********

   This is the documentation for modules associated with the main module
Number.

OLE Menu
********

   This is the documentation for modules associated with the main module
OLE.

OO Menu
*******

   This is the documentation for modules associated with the main module
OO.

OS2 Menu
********

   This is the documentation for modules associated with the main module
OS2.

OS390 Menu
**********

   This is the documentation for modules associated with the main module
OS390.

Object Menu
***********

   This is the documentation for modules associated with the main module
Object.

Ogg Menu
********

   This is the documentation for modules associated with the main module
Ogg.

OpenCA Menu
***********

   This is the documentation for modules associated with the main module
OpenCA.

OpenInteract Menu
*****************

   This is the documentation for modules associated with the main module
OpenInteract.

OurNet Menu
***********

   This is the documentation for modules associated with the main module
OurNet.

P4 Menu
*******

   This is the documentation for modules associated with the main module
P4.

PApp Menu
*********

   This is the documentation for modules associated with the main module
PApp.

PDF Menu
********

   This is the documentation for modules associated with the main module
PDF.

PDL Menu
********

   This is the documentation for modules associated with the main module
PDL.

PGP Menu
********

   This is the documentation for modules associated with the main module
PGP.

PML Menu
********

   This is the documentation for modules associated with the main module
PML.

PNGgraph Menu
*************

   This is the documentation for modules associated with the main module
PNGgraph.

POE Menu
********

   This is the documentation for modules associated with the main module
POE.

PPM Menu
********

   This is the documentation for modules associated with the main module
PPM.

Palm Menu
*********

   This is the documentation for modules associated with the main module
Palm.

Parallel Menu
*************

   This is the documentation for modules associated with the main module
Parallel.

Params Menu
***********

   This is the documentation for modules associated with the main module
Params.

Parse Menu
**********

   This is the documentation for modules associated with the main module
Parse.

Passwd Menu
***********

   This is the documentation for modules associated with the main module
Passwd.

Paw Menu
********

   This is the documentation for modules associated with the main module
Paw.

Penguin Menu
************

   This is the documentation for modules associated with the main module
Penguin.

Perf Menu
*********

   This is the documentation for modules associated with the main module
Perf.

PerlPoint Menu
**************

   This is the documentation for modules associated with the main module
PerlPoint.

Perlbug Menu
************

   This is the documentation for modules associated with the main module
Perlbug.

Persistence Menu
****************

   This is the documentation for modules associated with the main module
Persistence.

Persistent Menu
***************

   This is the documentation for modules associated with the main module
Persistent.

PlotCalendar Menu
*****************

   This is the documentation for modules associated with the main module
PlotCalendar.

Pod Menu
********

   This is the documentation for modules associated with the main module
Pod.

PostScript Menu
***************

   This is the documentation for modules associated with the main module
PostScript.

Proc Menu
*********

   This is the documentation for modules associated with the main module
Proc.

Project Menu
************

   This is the documentation for modules associated with the main module
Project.

Psh Menu
********

   This is the documentation for modules associated with the main module
Psh.

Puppet Menu
***********

   This is the documentation for modules associated with the main module
Puppet.

Qtk Menu
********

   This is the documentation for modules associated with the main module
Qtk.

Quantum Menu
************

   This is the documentation for modules associated with the main module
Quantum.

R3 Menu
*******

   This is the documentation for modules associated with the main module
R3.

RADIUS Menu
***********

   This is the documentation for modules associated with the main module
RADIUS.

RAS Menu
********

   This is the documentation for modules associated with the main module
RAS.

RCU Menu
********

   This is the documentation for modules associated with the main module
RCU.

RDBAL Menu
**********

   This is the documentation for modules associated with the main module
RDBAL.

RDFStore Menu
*************

   This is the documentation for modules associated with the main module
RDFStore.

RFC Menu
********

   This is the documentation for modules associated with the main module
RFC.

RIPEMD160 Menu
**************

   This is the documentation for modules associated with the main module
RIPEMD160.

RPC Menu
********

   This is the documentation for modules associated with the main module
RPC.

RTF Menu
********

   This is the documentation for modules associated with the main module
RTF.

Regex Menu
**********

   This is the documentation for modules associated with the main module
Regex.

Regexp Menu
***********

   This is the documentation for modules associated with the main module
Regexp.

Register Menu
*************

   This is the documentation for modules associated with the main module
Register.

Remedy Menu
***********

   This is the documentation for modules associated with the main module
Remedy.

RevML Menu
**********

   This is the documentation for modules associated with the main module
RevML.

SDL Menu
********

   This is the documentation for modules associated with the main module
SDL.

SETI Menu
*********

   This is the documentation for modules associated with the main module
SETI.

SGI Menu
********

   This is the documentation for modules associated with the main module
SGI.

SGML Menu
*********

   This is the documentation for modules associated with the main module
SGML.

SNMP Menu
*********

   This is the documentation for modules associated with the main module
SNMP.

SOAP Menu
*********

   This is the documentation for modules associated with the main module
SOAP.

SPOPS Menu
**********

   This is the documentation for modules associated with the main module
SPOPS.

SQL Menu
********

   This is the documentation for modules associated with the main module
SQL.

SWISH Menu
**********

   This is the documentation for modules associated with the main module
SWISH.

Safe Menu
*********

   This is the documentation for modules associated with the main module
Safe.

Scalar Menu
***********

   This is the documentation for modules associated with the main module
Scalar.

Schedule Menu
*************

   This is the documentation for modules associated with the main module
Schedule.

Search Menu
***********

   This is the documentation for modules associated with the main module
Search.

SecurID Menu
************

   This is the documentation for modules associated with the main module
SecurID.

Secure Menu
***********

   This is the documentation for modules associated with the main module
Secure.

Semi Menu
*********

   This is the documentation for modules associated with the main module
Semi.

Server Menu
***********

   This is the documentation for modules associated with the main module
Server.

Seshat Menu
***********

   This is the documentation for modules associated with the main module
Seshat.

Set Menu
********

   This is the documentation for modules associated with the main module
Set.

Silly Menu
**********

   This is the documentation for modules associated with the main module
Silly.

Simran Menu
***********

   This is the documentation for modules associated with the main module
Simran.

Sirc Menu
*********

   This is the documentation for modules associated with the main module
Sirc.

Slay Menu
*********

   This is the documentation for modules associated with the main module
Slay.

Socket Menu
***********

   This is the documentation for modules associated with the main module
Socket.

Solaris Menu
************

   This is the documentation for modules associated with the main module
Solaris.

Sort Menu
*********

   This is the documentation for modules associated with the main module
Sort.

Spectrum Menu
*************

   This is the documentation for modules associated with the main module
Spectrum.

Speech Menu
***********

   This is the documentation for modules associated with the main module
Speech.

Spreadsheet Menu
****************

   This is the documentation for modules associated with the main module
Spreadsheet.

Stat Menu
*********

   This is the documentation for modules associated with the main module
Stat.

Statistics Menu
***************

   This is the documentation for modules associated with the main module
Statistics.

StatsView Menu
**************

   This is the documentation for modules associated with the main module
StatsView.

Stone Menu
**********

   This is the documentation for modules associated with the main module
Stone.

String Menu
***********

   This is the documentation for modules associated with the main module
String.

Sub Menu
********

   This is the documentation for modules associated with the main module
Sub.

Sybase Menu
***********

   This is the documentation for modules associated with the main module
Sybase.

Symbol Menu
***********

   This is the documentation for modules associated with the main module
Symbol.

Symphero Menu
*************

   This is the documentation for modules associated with the main module
Symphero.

Sys Menu
********

   This is the documentation for modules associated with the main module
Sys.

SyslogScan Menu
***************

   This is the documentation for modules associated with the main module
SyslogScan.

Taco Menu
*********

   This is the documentation for modules associated with the main module
Taco.

Tcl Menu
********

   This is the documentation for modules associated with the main module
Tcl.

TeX Menu
********

   This is the documentation for modules associated with the main module
TeX.

Template Menu
*************

   This is the documentation for modules associated with the main module
Template.

Term Menu
*********

   This is the documentation for modules associated with the main module
Term.

Test Menu
*********

   This is the documentation for modules associated with the main module
Test.

Text Menu
*********

   This is the documentation for modules associated with the main module
Text.

Thesaurus Menu
**************

   This is the documentation for modules associated with the main module
Thesaurus.

Thread Menu
***********

   This is the documentation for modules associated with the main module
Thread.

Tie Menu
********

   This is the documentation for modules associated with the main module
Tie.

Time Menu
*********

   This is the documentation for modules associated with the main module
Time.

Tk Menu
*******

   This is the documentation for modules associated with the main module
Tk.

Tree Menu
*********

   This is the documentation for modules associated with the main module
Tree.

UDDI Menu
*********

   This is the documentation for modules associated with the main module
UDDI.

UNIVERSAL Menu
**************

   This is the documentation for modules associated with the main module
UNIVERSAL.

URI Menu
********

   This is the documentation for modules associated with the main module
URI.

URI2 Menu
*********

   This is the documentation for modules associated with the main module
URI2.

Unicode Menu
************

   This is the documentation for modules associated with the main module
Unicode.

Unix Menu
*********

   This is the documentation for modules associated with the main module
Unix.

User Menu
*********

   This is the documentation for modules associated with the main module
User.

VCP Menu
********

   This is the documentation for modules associated with the main module
VCP.

VCS Menu
********

   This is the documentation for modules associated with the main module
VCS.

VMS Menu
********

   This is the documentation for modules associated with the main module
VMS.

VRML Menu
*********

   This is the documentation for modules associated with the main module
VRML.

VcsTools Menu
*************

   This is the documentation for modules associated with the main module
VcsTools.

Verilog Menu
************

   This is the documentation for modules associated with the main module
Verilog.

Video Menu
**********

   This is the documentation for modules associated with the main module
Video.

VoiceXML Menu
*************

   This is the documentation for modules associated with the main module
VoiceXML.

WML Menu
********

   This is the documentation for modules associated with the main module
WML.

WWW Menu
********

   This is the documentation for modules associated with the main module
WWW.

Watchdog Menu
*************

   This is the documentation for modules associated with the main module
Watchdog.

Weather Menu
************

   This is the documentation for modules associated with the main module
Weather.

WebCache Menu
*************

   This is the documentation for modules associated with the main module
WebCache.

WebFS Menu
**********

   This is the documentation for modules associated with the main module
WebFS.

WebFetch Menu
*************

   This is the documentation for modules associated with the main module
WebFetch.

Wharf Menu
**********

   This is the documentation for modules associated with the main module
Wharf.

Win32 Menu
**********

   This is the documentation for modules associated with the main module
Win32.

Win32API Menu
*************

   This is the documentation for modules associated with the main module
Win32API.

Wizard Menu
***********

   This is the documentation for modules associated with the main module
Wizard.

WordNet Menu
************

   This is the documentation for modules associated with the main module
WordNet.

X11 Menu
********

   This is the documentation for modules associated with the main module
X11.

X500 Menu
*********

   This is the documentation for modules associated with the main module
X500.

XBase Menu
**********

   This is the documentation for modules associated with the main module
XBase.

XML Menu
********

   This is the documentation for modules associated with the main module
XML.

XMLNews Menu
************

   This is the documentation for modules associated with the main module
XMLNews.

XTM Menu
********

   This is the documentation for modules associated with the main module
XTM.

Xmms Menu
*********

   This is the documentation for modules associated with the main module
Xmms.

YAPE Menu
*********

   This is the documentation for modules associated with the main module
YAPE.

ex Menu
*******

   This is the documentation for modules associated with the main module
ex.

perlrpcgen Menu
***************

   This is the documentation for modules associated with the main module
perlrpcgen.

pod Menu
********

   This is the documentation for modules associated with the main module
pod.

Perl extension for Fuzzy Logic
******************************

NAME
====

   AI::Fuzzy - Perl extension for Fuzzy Logic

SYNOPSIS
========

     use AI::Fuzzy;

     my $f = new AI::Fuzzy::Label;

     $f->addlabel("baby",        -1,   1, 2.5);
     $f->addlabel("toddler",      1, 1.5, 3.5);
     $f->addlabel("little kid",   2,   7,  12);
     $f->addlabel("kid",          6,  10,  14);
     $f->addlabel("teenager",    12,  16,  20);
     $f->addlabel("young adult", 18,  27,  35);
     $f->addlabel("adult",       25,  50,  75);
     $f->addlabel("senior",      60,  80, 110);
     $f->addlabel("relic",      100, 150, 200);

     for (my $x = 0; $x<50; $x+=4) {
         print "$x years old => " . $f->label($x) . "\n";
     }

   __END__

DESCRIPTION
===========

   AI::Fuzzy really consists of two modules - AI::Fuzzy::Label and
AI::Fuzzy::Set.

   A fuzzy set is simply a mathematical set to which members can
*partially* belong. For example, a particular shade of gray may partially
belong to the set of dark colors, whereas black would have full
membership, and lemon yellow would have almost no membership.

   A fuzzy labeler classifies a particular crisp value by examining the
degree to which it belongs to several sets, and selecting the most
appropriate. For example, it can decide whether to call water at 60
degrees Farenheight "cold", "cool", or "warm". A fuzzy label might be one
of these labels, or a fuzzy set describing to what degree each of the
labels describes the particular value in question.

Fuzzy Sets
----------

   AI::Fuzzy:Set has these methods:

     $fs = B<new> AI::Fuzzy::Set;

     # here, "Bob" is unquestionably tall.. the others less so.
     $fs_tall_people = B<new> AI::Fuzzy::Set( Lester=>34, Bob=>100, Max=>86 );

     # $x will be 86
     $x = B<membership> $fs_tall_people, "Max";

     # get list of members, sorted from least membership to greatest:
     @shortest_first = B<members> $fs_tall_people;

Fuzzy Labels
------------

   A Fuzzy::Label label has four attributes: the text of the label (it can
be any scalar, really), and three numbers: low, mid, high if you imagine a
cartesian plane (remember graph paper in algebra?)  of all possible
values, the label applies to a particular range.  the graph might look
something like this:

     |Y               * (mid, 1)
     	  |               /  \
     	  |             /    \
     	  |           /       \
     	  |         /          \
     	 -|-------*-------------*------- X
     	           (low,0)      (high,0)

   the Y value is applicability of the label for a given X value

   the mid number is the "pure" value. eg, orange is at 0 or 360 degrees
on the color wheel. the label applies 100% at the mid point.

   the low and high numbers are the two points at which the label ceases
to apply.

   note that labels can overlap, and that the mid number isn't always in
the exact center, so the slope of the two sides may vary...

   $fl = new AI::FuzzyLabel;

   $fl->addlabel( "hot", 77, 80, 100 );     # what I consider hot. :) (in
Farenheit, of course!)

   $a = $fl->applicability($label, $value);     # $a is now the degree to
which $label applies to $value

   $l = $fl->label ($value);     # applies a label to $value

   @l = $fl->label($value);     # returns a list of labels and their
applicability values

   @l = new AI::Fuzzy::Set( $fl->label($value) );     # same thing, but
now it's an object

   @range = $fl->range();     # returns a list of labels, sorted by their
midpoints     # eg: ("cold", "cool", "lukewarm", "warm", "hot")

AUTHOR
======

   Michal Wallace  (sabren@manifestation.com)

SEE ALSO
========

   Move along, nothing to "see also" here...

AI::Gene::Sequence
******************

NAME
====

     AI::Gene::Sequence

SYNOPSIS
========

   A base class for storing and mutating genetic sequences.

     package Somegene;
     use AI::Gene::Sequence;
     our @ISA = qw(AI::Gene::Sequence);

     my %things = ( a => [qw(a1 a2 a3 a4 a5)],
     	       b => [qw(b1 b2 b3 b4 b5)],);

     sub generate_token {
      my $self = shift;
      my ($type, $prev) = @_;
      if ($type) {
        $prev = ${ $things{$type} }[rand @{ $things{$type} }];
      }
      else {
        $type = ('a','b')[rand 2];
        $prev = ${$things{$type}}[rand @{$things{$type}}];
      }
      return ($type, $prev);
     }

     sub valid_gene {
       my $self = shift;
       return 0 if $_[0] =~ /(.)\1/;
       return 1;
     }

     sub seed {
       my $self = shift;
       $self->[0] = 'ababab';
       @{$self->[1]} = qw(A1 B1 A2 B2 A3 B3);
     }

     sub render {
       my $self = shift;
       return join(' ', @{$self->[1]});
     }

     # elsewhere
     package main;

     my $gene = Somegene->new;
     $gene->seed;
     print $gene->render, "\n";
     $gene->mutate(5);
     print $gene->render, "\n";
     $gene->mutate(5);
     print $gene->render, "\n";

DESCRIPTION
===========

   This is a class which provides generic methods for the creation and
mutation of genetic sequences.  Various mutations are provided as is a way
to ensure that genes created by mutations remain useful (for instance, if
a gene gives rise to code, it can be tested for correct syntax).

   If you do not need to keep check on what sort of thing is currently
occupying a slot in the gene, you would be better off using the
AI::Gene::Simple class instead as this will be somewhat faster.  The
interface to the mutations is the same though, so if you need to change in
future, then it will not be too painful.

   This module should not be confused with the *bioperl* modules which are
used to analyse DNA sequences.

   It is intended that the methods in this code are inherited by other
modules.

Anatomy of a gene
-----------------

   A gene is a sequence of tokens, each a member of some group of simillar
tokens (they can of course all be members of a single group).  This module
encodes genes as a string representing token types, and an array
containing the tokens themselves, this allows for arbitary data to be
stored as a token in a gene.

   For instance, a regular expression could be encoded as:

     $self = ['ccartm',['a', 'b', '|', '[A-Z]', '\W', '*?'] ]

   Using a string to indicate the sort of thing held at the corresponding
part of the gene allows for a simple test of the validity of a proposed
gene by using a regular expression.

Using the module
----------------

   To use the genetic sequences, you must write your own implementations
of the following methods:

generate_token
valid_gene
   You may also want to override the following methods:

new
clone
render_gene
Mutation methods
----------------

   Mutation methods are all named `mutate_*'.  In general, the first
argument will be the number of mutations required, followed by the
positions in the genes which should be affected, followed by the lengths
of sequences within the gene which should be affected.  If positions are
not defined, then random ones are chosen.  If lengths are not defined, a
length of 1 is assumed (ie. working on single tokens only), if a length of
0 is requested, then a random length is chosen.

   Also, if a mutation is suggested but would result in an invalid
sequence, then the mutation will not be carried out.  If a mutation is
attempted which could corrupt your gene (copying from a region beyond the
end of the gene for instance) then it will be silently skipped.  Mutation
methods all return the number of mutations carried out (not the number of
tokens affected).

   These methods all expect to be passed positive integers, undef or zero,
other values could (and likely will) do something unpredictable.

`mutate([num, ref to hash of probs & methods])'
     This will call at random one of the other mutation methods.  It will
     repeat itself num times.  If passed a reference to a hash as its
     second argument, it will use that to decide which mutation to attempt.

     This hash should contain keys which fit $1 in `mutate_(.*)' and
     values indicating the weight to be given to that method.  The module
     will normalise this nicely, so you do not have to.  This lets you
     define your own mutation methods in addition to overriding any you do
     not like in the module.

`mutate_insert([num, pos])'
     Inserts a single token into the string at position pos.  The token
     will be randomly generated by the calling object's generate_token
     method.

`mutate_overwrite([num, pos1, pos2, len])'
     Copies a section of the gene (starting at *pos1*, length len) and
     writes it back into the gene, overwriting current elements, starting
     at *pos2*.

`mutate_reverse([num, pos, len])'
     Takes a sequence within the gene and reverses the ordering of the
     elements within that sequence.  Starts at position pos for length len.

`mutate_shuffle([num, pos1, pos2, len])'
     This takes a sequence (starting at *pos1* length len)  from within a
     gene and moves it to another position (starting at *pos2*).  Odd
     things might occur if the position to move the sequence into lies
     within the section to be moved, but the module will try its hardest
     to cause a mutation.

`mutate_duplicate([num, pos1, pos2, length])'
     This copies a portion of the gene starting at *pos1* of length length
     and then splices it into the gene before *pos2*.

`mutate_remove([num, pos, length]))'
     Deletes length tokens from the gene, starting at pos. Repeats num
     times.

`mutate_minor([num, pos])'
     This will mutate a single token at position pos in the gene into one
     of the same type (as decided by the object's generate_token method).

`mutate_major([num, pos])'
     This changes a single token into a token of any token type.  Token at
     postition pos.  The token is produced by the object's generate_token
     method.

`mutate_switch([num, pos1, pos2, len1, len2])'
     This takes two sequences within the gene and swaps them into each
     other's position.  The first starts at *pos1* with length *len1* and
     the second at *pos2* with length *len2*.  If the two sequences
     overlap, then no mutation will be attempted.

   The following methods are also provided, but you will probably want to
overide them for your own genetic sequences.

`generate_token([token type, current token])'
     This is used by the mutation methods when changing tokens or creating
     new ones.  It is expected to return a list consisting of a single
     character to indicate the token type being produced and the token
     itself.  Where it makes sense to do so the token which is about to be
     modifed is passed along with the token type.  If the calling methods
     require a token of any type, then no arguments will be passed to this
     method.

     The provided version of this method returns a random character from
     'a'..'z' as both the token type and token.

`valid_gene(string [, posn])'
     This is used to determine if a proposed mutation is allowed.  This
     method is passed a string of the whole gene's token types, it will
     also be passed a position in the gene where this makes sense (for
     instance, if only one token is to change).  It is expected to return
     a true value if a change is acceptable and a false one if it is not.

     The provided version of this method always returns true.

clone()
     This returns a copy of the gene as a new object.  If you are using
     nested genes, or other references as your tokens, then you may need
     to produce your own version which will deep copy your structure.

new
     This returns an empty gene, into which you can put things.  If you
     want to initialise your gene, or anything useful like that, then you
     will need another one of these.

render_gene
     This is useful for debugging, returns a serialised summary of the
     gene.

AUTHOR
======

   This module was written by Alex Gough (`alex@rcon.org').

SEE ALSO
========

   For an illustration of the use of this module, see Regexgene.pm,
Musicgene.pm, spamscan.pl and music.pl from the gziped distribution.

COPYRIGHT
=========

   Copyright (c) 2000 Alex Gough <`alex@rcon.org'>. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

BUGS
====

   This is very slow if you do not need to check that your mutations
create valid genes, but fast if you do, thems the breaks.  There is a
AI::Gene::Simple class instead if this bothers you.

   Some methods will do odd things if you pass them weird values, so try
not to do that.  So long as you stick to passing positive integers or
undef to the methods then they should recover gracefully.

   While it is easy and fun to write genetic and evolutionary algorithms
in perl, for most purposes, it will be much slower than if they were
implemented in another more suitable language.  There are some problems
which do lend themselves to an approach in perl and these are the ones
where the time between mutations will be large, for instance, when
composing music where the selection process is driven by human whims.

AI::Gene::Simple
****************

NAME
====

     AI::Gene::Simple

SYNOPSIS
========

   A base class for storing and mutating genetic sequences.

     package Somegene;
     use AI::Gene::Simple;
     our @ISA = qw (AI::Gene::Simple);

     sub generate_token {
       my $self = shift;
       my $prev = $_[0] ? $_[0] + (1-rand(1)) : rand(1)*10;
       return $prev;
     }

     sub calculate {
       my $self = shift;
       my $x = $_[0];
       my $rt=0;
       for (0..(scalar(@{$self->[0]}) -1)) {
         $rt += $self->[0][$_] * ($x ** $_);
       }
       return $rt;
     }

     sub seed {
       my $self = shift;
       $self->[0][$_] = rand(1) * 10 for (0..$_[0]);
       return $self;
     }

     # ... then elsewhere

     package main;

     my $gene = Somegene->new;
     $gene->seed(5);
     print $gene->calculate(2), "\n";
     $gene->mutate_minor;
     print $gene->calculate(2), "\n";
     $gene->mutate_major;
     print $gene->calculate(2), "\n";

DESCRIPTION
===========

   This is a class which provides generic methods for the creation and
mutation of genetic sequences.  Various mutations are provided but the
resulting mutations are not checked for a correct syntax.  These classes
are suitable for genes where it is only necessary to know what lies at a
given position in a gene.  If you need to ensure a gene maintains a
sensible grammar, then you should use the AI::Gene::Sequence class
instead, the interfaces are the same though so you will only need to
modify your overiding classes if you need to switch from one to the other.

   A suitable use for this module might be a series of coefficients in a
polynomial expansion or notes to be played in a musical score.

   This module should not be confused with the *bioperl* modules which are
used to analyse DNA sequences.

   It is intended that the methods in this code are inherited by other
modules.

Anatomy of a gene
-----------------

   A gene is a linear sequence of tokens which tell some unknown system
how to behave.  These methods all expect that a gene is of the form:

     [ [ 'token0', 'token1', ...  ], .. other elements ignored ]

Using the module
----------------

   To use the genetic sequences, you must write your own implementations
of the following methods along with some way of turning your encoded
sequence into something useful.

generate_token
   You may also want to override the following methods:

new
clone
render_gene
   The calling conventions for these methods are outlined below.

Mutation methods
----------------

   Mutation methods are all named `mutate_*'.  In general, the first
argument will be the number of mutations required, followed by the
positions in the genes which should be affected, followed by the lengths
of sequences within the gene which should be affected.  If positions are
not defined, then random ones are chosen.  If lengths are not defined, a
length of 1 is assumed (ie. working on single tokens only), if a length of
0 is requested, then a random length is chosen.

   If a mutation is attempted which could corrupt your gene (copying from
a region beyond the end of the gene for instance) then it will be silently
skipped.  Mutation methods all return the number of mutations carried out
(not the number of tokens affected).

`mutate([num, ref to hash of probs & methods])'
     This will call at random one of the other mutation methods.  It will
     repeat itself num times.  If passed a reference to a hash as its
     second argument, it will use that to decide which mutation to attempt.

     This hash should contain keys which fit $1 in `mutate_(.*)' and
     values indicating the weight to be given to that method.  The module
     will normalise this nicely, so you do not have to.  This lets you
     define your own mutation methods in addition to overriding any you do
     not like in the module.

`mutate_insert([num, pos])'
     Inserts a single token into the string at position pos.  The token
     will be randomly generated by the calling object's generate_token
     method.

`mutate_overwrite([num, pos1, pos2, len])'
     Copies a section of the gene (starting at *pos1*, length len) and
     writes it back into the gene, overwriting current elements, starting
     at *pos2*.

`mutate_reverse([num, pos, len])'
     Takes a sequence within the gene and reverses the ordering of the
     elements within that sequence.  Starts at position pos for length len.

`mutate_shuffle([num, pos1, pos2, len])'
     This takes a sequence (starting at *pos1* length len)  from within a
     gene and moves it to another position (starting at *pos2*).  Odd
     things might occur if the position to move the sequence into lies
     within the section to be moved, but the module will try its hardest
     to cause a mutation.

`mutate_duplicate([num, pos1, pos2, length])'
     This copies a portion of the gene starting at *pos1* of length length
     and then splices it into the gene before *pos2*.

`mutate_remove([num, pos, length]))'
     Deletes length tokens from the gene, starting at pos. Repeats num
     times.

`mutate_minor([num, pos])'
     This will mutate a single token at position pos in the gene into one
     of the same type (as decided by the object's generate_token method).

`mutate_major([num, pos])'
     This changes a single token into a token of any token type.  Token at
     postition pos.  The token is produced by the object's generate_token
     method.

`mutate_switch([num, pos1, pos2, len1, len2])'
     This takes two sequences within the gene and swaps them into each
     other's position.  The first starts at *pos1* with length *len1* and
     the second at *pos2* with length *len2*.  If the two sequences
     overlap, then no mutation will be attempted.

   The following methods are also provided, but you will probably want to
overide them for your own genetic sequences.

`generate_token([current token])'
     This is used by the mutation methods when changing tokens or creating
     new ones.  It is expected to return a single token.  If a minor
     mutation is being attempted, then the method will also be passed the
     current token.

     The provided version of this method returns a random character from
     'a'..'z' as both the token type and token.

clone()
     This returns a copy of the gene as a new object.  If you are using
     nested genes, or other references as your tokens, then you may need
     to produce your own version which will deep copy your structure.

new
     This returns an empty gene, into which you can put things.  If you
     want to initialise your gene, or anything useful like that, then you
     will need another one of these.

render_gene
     This is useful for debugging, returns a serialised summary of the
     gene.

AUTHOR
======

   This module was written by Alex Gough (`alex@rcon.org').

SEE ALSO
========

   If you are encoding something which must maintain a correct syntax
(executable code, regular expressions, formal poems) then you might be
better off using AI::Gene::Sequence .

COPYRIGHT
=========

   Copyright (c) 2000 Alex Gough <`alex@rcon.org'>. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

BUGS
====

   Some methods will do odd things if you pass them weird values, so try
not to do that.  So long as you stick to passing positive integers or
undef to the methods then they should recover gracefully.

   While it is easy and fun to write genetic and evolutionary algorithms
in perl, for most purposes, it will be much slower than if they were
implemented in another more suitable language.  There are some problems
which do lend themselves to an approach in perl and these are the ones
where the time between mutations will be large, for instance, when
composing music where the selection process is driven by human whims.

An implementation of a Perceptron
*********************************

NAME
====

   AI::Perceptron - An implementation of a Perceptron

SYNOPSIS
========

   use AI::Perceptron;

DESCRIPTION
===========

   This module is meant to show how a single node of a neural network
works to beginners in the field.

   The only mode of training the weights supported at this point in time
is the Stochastic Approximation of the Gradient-Descent model.

CONSTRUCTOR
===========

new( [%args] )
     Creates a new perceptron with the following properties:

          Inputs => number of inputs (scalar)
          N      => learning rate    (scalar)
          W      => array ref of weights (applied to the inputs)

     The Number of elements in W must be equal to the number of inputs
     *plus one*.  This is because W[0] is the Perceptron's threshold (so
     W[1] corresponds to the first input's weight).

     Default values are: 1, 0.05, and [random], respectively.

METHODS
=======

weights( [@W] )
     Sets/gets the perceptron's weights.  This is useful between training
     sessions to see if the weights are actually changing.  Note again that
     W[0] is the Perceptron's threshold.

train( $n, $training_examples )
     This uses the Stochastic Approximation of the Gradient-Descent model
     to adjust the perceptron's weights in such a way to achieve the
     desired outputs given in the training examples.

     Note that this training method may undo previous trainings!

SEE ALSO
========

   `Statistics::LTU', the ASCII model contained in Perceptron.pm.

REFERENCES
==========

   U<Machine Learning>, by Tom M. Mitchell

AUTHOR
======

   Steve Purkis <`spurkis@epn.nu'>

COPYRIGHT
=========

   Copyright (c) 1999, 2000 Steve Purkis.  All rights reserved.  This
package is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

A Perl servlet engine
*********************

NAME
====

   AO - A Perl servlet engine

SYNOPSIS
========

   For an Apache deployment, add the following to httpd.conf:

     # load Apache 'adapter' and start up engine
     PerlModule Apache::AO

     # tell Apache to delegate handling
     <Location />
       SetHandler perl-script
       PerlHandler Apache::AO
     </Location>

DESCRIPTION
===========

   AO is a servlet engine for Perl. In other words, it provides an
environment in which web components (servlets) written in Perl can be
executed.

   While the servlet concept originated with Java, its component model is
quite natural for Perl as well. By writing servlet applications and
deploying them in a servlet engine, application authors can spare
themselves the effort of writing commonly needed web application
infrastructure components for each new project. Furthermore, servlet
applications can be made more portable between deployment environments;
applications written to the Servlet API should be deployable in any
servlet engine using any process model with only a few configuration
changes and no application code changes.

Servlet API
-----------

   The Servlet API is the key to writing portable web applications. This
'seam' provides decoupling between the deployment environment
(Apache/mod_perl web server, multiprocess/single thread) and the
application environment (handle request, generate response). Furthermore,
it provides access to the web environment portably between web servers.
Applications written to the Servlet API are insulated from changes in
vendor or platform and are able to portably take advantage of standard web
infrastructure services offered by any servlet engine.

Servlet Engine
--------------

   The servlet engine itself works with a web server to negotiate network
services, HTTP/S protocol handling, and MIME formatting. It also manages
web applications and servlets throughout their lifecycles. Perhaps most
importantly, it provides web infrastructure services such as security,
session management, configuration, and logging to servlet applications.
The servlet engine may also provide an environment in which web
applications can be distributed over processes and machines.

FEATURES
========

   AO provides a Perl web application environment with several standard
infrastructure services:

Configuration
     The servlet engine is configured via an XML file, server.xml. The
     main controller of the engine is represented as a *ContextManager*,
     and each web application deployed into the engine is represented as a
     Context. Various Interceptors and *Loggers* can be configured
     globally and per-context to provide infrastructure and application
     services.

     Web applications themselves are configured by their own XML files,
     web.xml, as described in the Servlet Specification. Application
     attributes, security, servlets, and the mapping of servlets to the
     application's URI namespace are described here on a per-application
     basis.

     See `AO::Config::Server' in this node and `AO::Config::Context' in
     this node for more information on configuration.

Session Management
     AO establishes a session for each web client interacting with the
     engine and maps each HTTP request to a session. Information of a
     transitory nature can be persisted for the life of a session using the
     session persistence framework; DBI and filesystem implementations are
     provided.

     See `AO::Interceptor::SessionManager' in this node,
     `AO::SessionManager::BaseSessionManager' in this node and
     `AO::Interceptor::Session' in this node for more information on
     session management.

Security
     AO provides security for web applications by implementing both
     authentication and authorization checks. The security administrator
     can define security policy domains (realms) in which various security
     roles are granted access to parts of the URI namespace, and security
     technology domains which each use a specific mechanism for
     authenticating users and verifying their assignment to a particular
     role via the access control framework; a DBI implementation is
     provided.

     See `AO::Interceptor::Access' in this node and
     `AO::Interceptor::RealmBase' in this node for more information on
     security.

Logging
     AO provides a flexible logging interface based on that of syslog;
     given a base log level, the servlet engine will log only events of
     that severity or greater. Syslog and Apache implementations are
     provided, and others can be created using the logging framework.

     See `AO::Logger::BaseLogger' in this node for more information on
     logging.

An Example
----------

   A client program, such as a web browser, makes an HTTP request of a web
server. The request is handed off to the servlet engine, which creates or
restores the session corresponding to the client program, performs
security checks if appropriate, determines which servlet to invoke and
calls the servlet, passing objects representing the request and response.
The servlet engine may run within the web server process, in another
process on the same host, or on a different host altogether.

   The servlet extracts data from the request object, performs its
application logic, and sends data back to the engine via the response
object. The engine passes the response data back to the web server and
performs any necessary cleanup operations (persisting session state, for
example). The web server sends an HTTP response to the client to conclude
the transaction.

INSTALLATION
============

   AO has only been tested under Linux. The AO code itself is all Perl and
thus should work in any environment with a working perl interpreter. The
framework requires a small number of CPAN modules, and the standard and
extended set of interceptors require several more.

   At this time, AO only provides a web server adapter for
Apache/mod_perl. It is anticipated that a FastCGI adapter will be
implemented in the near future.

   AO is installed in the standard MakeMaker fashion:

     perl Makefile.PL
     make
     make test
     make install

   No scripts or config files are installed, just the AO libraries. You'll
need to place server.xml manually (see below).

CONFIGURATION
=============

   The servlet engine and each web application are configured with XML
files. Furthermore, the web server must be configured to communicate with
the servlet engine as appropriate.

   The following points of configuration are common to all AO deployments:

base directory
     By default, the AO base directory will be web-server specific.
     However, `$ENV{AO_HOME}' can always be used to specify an alternate
     base directory (for example, `/home/bcm/work/ao').

server.xml
     AO will search for server.xml inside its base directory, in the
     following order: `./conf/server.xml', `./etc/server.xml',
     `./server.xml'. $ENV{AO_CONFIG} can be used to specify an exact
     location (for example, `/home/bcm/work/server.xml'); in this case, AO
     will not search through the above subdirectories.

     See `AO::Config::Server' in this node for a complete description of
     configuring server.xml. An example can be found at `etc/server.xml'.

web.xml
     For each context configured within server.xml, AO will look for
     web.xml inside `<context doc_base>/WEB-INF'.

     See `AO::Config' in this node for a complete description of
     configuring web.xml. Examples can be found at
     `share/examples/WEB-INF/web.xml' and `share/admin/WEB-INF/web.xml'.

Apache/mod_perl
---------------

   The following points of configuration are specific to the
Apache/mod_perl environment:

base directory
     By default, the AO base directory is the Apache server root.
     `$ENV{AO_HOME}' can be used to specify an alternate base directory as
     described above.

httpd.conf
     Apache has to be told to load the `Apache::AO' adapter module and to
     use it as the handler for all relevant Location/Directory/Files
     blocks. `WEB-INF' directories should be protected by denying access
     to them.

     If environment variables are to be used to influence AO's
     configuration, they must be set before `Apache::AO' is loaded. Either
     set them in the shell before starting the web server, or use a BEGIN
     block before loading the module.

     See `etc/ao.conf' for an example snippet of Apache configuration code.

ARCHITECTURE
============

   The architecture of the AO servlet engine is actually quite
straightforward. On a per-request basis, a controller accepts normalized
requests from a web server adapter, identifies the appropriate servlet and
delegates service to it, and routes the servlet's response back to the web
server adapter. The servlet itself is the gateway to the logic of the
application layer. Furthermore, event handlers are given the opportunity
to react at various points during the service process and during the
lifecycle of the engine and its web applications.

Adapters
--------

   These are the components that communicate between the web server and
the servlet engine. There is no actual adapter class, since each web
server and/or process model may require vastly different strategies for
adapting. If similarities appear as more adapters are developed, this
decision may be revisited.

   The responsibilities of an adapter are to instantiate a context
manager; process the engine's configuration; and to drive the context
manager's lifecycle.

   See `Apache::AO' in this node for more information on the Apache
adapter.

Context Manager
---------------

   The control and sequencing functions of the engine are allocated to the
*ContextManager*. Its responsibilities are to maintain the list of web
applications (Contexts) deployed into the engine, and add, reload or
remove web applications as necessary; to provide a starting point for the
engine itself; and to shepherd the various internal objects through the
process of servicing an individual request.

   See `AO::ContextManager' in this node for more information.

Contexts
--------

   Each web application is represented internally by a Context. These
objects aren't terribly interesting in their own right; they are basically
bundles of attributes and associations to other objects. It is using the
context that the engine and interceptors can execute context-specific
behavior during lifecycle and requext servicing (security constraints are
a good example), and it is from the context that servlets get all their
knowledge of the servlet environment.

   See `AO::Context' in this node for more information.

Interceptors
------------

   The processes of startup, request servicing and shutdown offer a lot of
room for customization of the engine's behavior. The AO architecture is
built around the notion of Interceptors that modify the behavior of the
core engine. Each Interceptor has the opportunity to respond to engine
lifecycle and/or request handling events.

   The standard behavior of the engine is implemented with Interceptors as
well. This allows an additional level of flexibility beyond the 'plug in
your own session persistence implementation' level. The session management
framework can be removed or replaced with a completely custom framework,
as desired.

   Note: the order in which interceptors are declared in server.xml is
very important. Since there is no way for an interceptor to signal that no
more interceptors should be given the ability to handle a particular
event, a later interceptor can possibly undo or overwrite an earlier
interceptor's work. It's yet to be seen if this is a liability or a
simplification.

   See `AO::BaseInterceptor' in this node for more information.

Lifecycle Events
----------------

   A *ContextInterceptor* acts on events in the lifecycle of the engine
and of each context. Each of the following events is called on each
context interceptor:

engine_init
     Called when the context manager is initialized by the adapter.
     Typically where global resources are initialized, such as database
     connections, etc.

context_init
     Called after the instantiation of a context, in order to prepare it
     for service. Typically where the context configuration is processed,
     servlets are preloaded, etc.

add_context
     Called when a context is added to the context manager's list.

remove_context
     Called when a context is removed from the context manager's list.

context_shutdown
     Called when a context is removed from service. Typically used to
     release resources used by that context only; for instance, to remove
     all active sessions for the context.

engine_shutdown
     Called when the context manager is about to end service. Typically
     used to release global resources, such as database connections.

   See `AO::Interceptor::ContextInterceptor' in this node for more
information about interceptors that act on lifecycle events.

Service Events
--------------

   A *RequestInterceptor* acts on events during the servicing of each
request. Each of the following events is called on each reequest
interceptor:

context_map
     Called to determine to which context the request was directed.

request_map
     Called to determine which servlet will service the request. Also used
     by the standard security mechanism to determine if the request must be
     authenticated.

authenticate
     Called to check the validity of submitted credentials.

authorize
     Called to check if the previously authenticated user is in the
     security role specified by the context's security configuration.

pre_service
     Called just before the servlet takes control of the request.

post_service
     Called just after the servlet has serviced the request.

   See `AO::Interceptor::RequestInterceptor' in this node for more
information about interceptors that act on service events.

Service
-------

   This is the actual point at which the servlet engine relinquishes
control and the servlet takes over; in other words, it is the entry point
for the servlet application.

   See `AO::Servlet::BaseServlet' in this node for more information about
servlets.

AUTHOR
======

   Brian Moseley, bcm@maz.org

Perl extension for interfacing with AOL's AIM service
*****************************************************

NAME
====

   AOL::TOC - Perl extension for interfacing with AOL's AIM service

SYNOPSIS
========

     use AOL::TOC;
     $toc = AOL::TOC::new($toc_server, $login_server, $port,
            $screenname, $password);
     $toc->connect();

DESCRIPTION
===========

   This module implements SFLAP, which I presume to be AOL's
authenticiation protocol, and TOC, which is the actual "meat" of the AIM
protocol.

INTERFACE
=========

connect
-------

   connects to the AIM server

register_callback
-----------------

   This function takes two arguments, the EVENT and the subroutine
reference.  Callbacks are similar to the ones found in Net::IRC. The
module defines several AIM "events": ERROR, CLOSED, SIGN_ON, IM_IN,
CHAT_IN, UPDATE_BUDDY.  These events can be bound to subroutines.

dispatch
--------

   This flushes all messages to the server, and retreives all current
messages.

add_buddy
---------

   Takes one arguement, the nick of the buddy.  This adds a buddy to your
buddy list.

send_im
-------

   Takes two arguments, the name of the buddy and the name of the message,
and sends the IM.

get_info
--------

   Takes one argument, the name of the buddy, and returns the info.

chat_join
---------

   Takes one argument, the name of the chat room to join

chat_send
---------

   Takes two arguments, the name of the chat room, and the message.

AUTHOR
======

   xjharding@newbedford.k12.ma.us cleaned it up and added DOC
james@foo.org was the original author

SEE ALSO
========

   Net::AIM, a new module, but it doesn't have the features of this one

a Module for ASP (PerlScript) Programming
*****************************************

NAME
====

   ASP - a Module for ASP (PerlScript) Programming

SYNOPSIS
========

     use strict;
     use ASP qw(:strict);

     print "Testing, testing.<BR><BR>";
     my $item = param('item');

     if($item eq 'Select one...') {
         die "Please select a value from the list.";
     }

     print "You selected $item.";
     exit;

DESCRIPTION
===========

   This module is based on Matt Sergeant's excellent Win32::ASP module,
which can be found at <`http://www.fastnetltd.ndirect.co.uk/Perl'>.  After
using Mr. Sergeant's module, I took on the task of customizing and
optimizing it for my own purposes. Feel free to use it if you find it
useful.

NOTES
=====

   This module is designed to work with both ASP PerlScript on IIS4, as
well as mod_perl/Apache::ASP on *nix platforms. Apache::ASP already
provides some of the functionality provided by this module; because of
this (and to avoid redundancy), ASP.pm attempts to detect its environment.
Differences between Apache and MS ASP are noted.

   Both of the print() and warn() standard perl funcs are overloaded to
output to the browser. print() is also available via the
$ASP::ASPOUT->print() method call.

   $Request->ServerVariables are only stuffed into %ENV on Win32
platforms, as Apache::ASP already provides this.

   ASP.pm also exports the $ScriptingNamespace symbol (Win32 only).  This
symbol allows PerlScript to call subs/functions written in another script
language. For example:

     <%@ language=PerlScript %>
     <%
         use ASP qw(:strict);
         print $ScriptingNamespace->SomeSub("arg1");
     %>
     <SCRIPT language=VBScript runat=server>
     Function SomeSub (str)
         SomeSub = SomethingThatReturnsSomething()
     End Function
     </SCRIPT>

USE
===

use ASP qw(:basic);
-------------------

   Exports basic subs: Print, Warn, die, exit, param, param_count. Same as
`use ASP;'

use ASP qw(:strict);
--------------------

   Allows the use of the ASP objects under `use strict;'.

   NOTE: This is not the only way to accomplish this, but I think it's the
cleanest, most convenient way.

use ASP qw(:all);
-----------------

   Exports all subs except those marked 'not exported'.

use ASP ();
-----------

   Overloads print() and warn() and provides the $ASP::ASPOUT object.

FUNCTION REFERENCE
==================

warn LIST
---------

   warn (or more specifically, the __WARN__ signal) has been re-routed to
output to the browser.

   FYI: When implemented, this tweak led to the removal of the prototypes
Matt placed on his subs.

Warn LIST
---------

   `Warn' is an alias for the ASP::Print method described below. The
overloading of warn as described above does not currently work in
Apache::ASP, so this is provided.

print LIST
----------

   print is overloaded to write to the browser by default. The inherent
behavior of print has not been altered and you can still use an alternate
filehandle as you normally would. This allows you to use print just as you
would in CGI scripts. The following statement would need no modification
between CGI and ASP PerlScript:

     print param('URL'), " was requested by ", $ENV{REMOTE_HOST}, "\n";

Print LIST
----------

   Prints a string or comma separated list of strings to the browser. Use
as if you were using print in a CGI application. Print gets around ASP's
limitations of 128k in a single $Response->Write() call.

   NB: print calls Print, so you could use either, but print more closely
resembles perl.

DebugPrint LIST
---------------

   Output is displayed between HTML comments so the output doesn't
interfere with page aesthetics.

HTMLPrint LIST
--------------

   The same as Print except the output is HTML-encoded so that any HTML
tags appear as sent, i.e. < becomes &lt;, > becomes &gt; etc.

die LIST
--------

   Prints the contents of LIST to the browser and then exits. die
automatically calls $Response->End for you, it also executes any cleanup
code you have added with `AddDeathHook'.

exit
----

   Exits the current script. $Response->End is called automatically for
you.  Any cleanup code added with `AddDeathHook' is also called.

escape LIST
-----------

   Escapes (URL-encodes) a list. Uses ASP object method
$Server->URLEncode().

unescape LIST
-------------

   Unescapes a URL-encoded list. Algorithms ripped from CGI.pm method of
the same name.

escapeHTML LIST
---------------

   Escapes a list of HTML. Uses ASP object method $Server->HTMLEncode().

   If passed an array reference, escapeHTML will return a reference to the
escaped array.

unescapeHTML LIST
-----------------

   Unescapes an HTML-encoded list.

   If passed an array reference, unescapeHTML will return a reference to
the un-escaped array.

param EXPR [, EXPR]
-------------------

   Simplifies parameter access and makes switch from GET to POST
transparent.

   Given the following querystring:

     myscript.asp?x=a&x=b&y=c

     param()      returns ('x', 'y')
     param('y')   returns 'c'
     param('x')   returns ('a', 'b')
     param('x',1) returns 'a'
     param('x',2) returns 'b'

   NOTE: Under Apache::ASP, param() simply passes the arguments to
CGI::param() because Apache::ASP doesn't support the $obj->{Count}
property used in this function.

param_count EXPR
----------------

   Returns the number of times EXPR appears in the request (Form or
QueryString).

   For example, if URL is

     myscript.asp?x=a&x=b&y=c

   then

     param_count('x');

   returns 2.

   NOTE: Under Apache::ASP, param_count() performs some manipulation using
CGI::param() because Apache::ASP doesn't support the $obj->{Count}
property used in this function.

AddDeathHook LIST
-----------------

   Allows cleanup code to be executed when you die or exit.  Useful for
closing database connections in the event of a fatal error.

     <%
     my $conn = Win32::OLE-new('ADODB.Connection');
     $conn->Open("MyDSN");
     $conn->BeginTrans();
     ASP::AddDeathHook( sub { $Conn->Close if $Conn; } );
     %>

   Death hooks are not executed except by explicitly calling the die() or
exit() methods provided by ASP.pm.

   AddDeathHook is not exported.

AUTHOR
======

   Tim Hammerquist <`tim@dichosoft.com'>

HISTORY
=======

Version 1.07
     Added Warn() because warn() overloading doesn't appear to work under
     Apache::ASP.

     Was forced to clear @DeathHooks array after calling _END() because of
     the persistent state of Apache::ASP holding over contents across
     executions.

     Removed BinaryWrite(), SetCookie(), and Autoload functionality.

Version 1.00
     The escapeHTML() and unescapeHTML() functions now accept array refs
     as well as lists, as Win32::ASP::HTMLEncode() was supposed to.
     Thanks to Matt Sergeant for the fix.

Version 0.97
     Optimized and debugged.

Version 0.77
     Overloaded warn() and subsequently removed prototypes.

     Exported $ScriptingNamespace object.

     Added methods escape(), unescape(), escapeHTML(), unescapeHTML().
     Thanks to Bill Odom for pointing these out!

     Re-implemented SetCookie and BinaryWrite functions.

Version 0.11
     Optimized and debugged.

SEE ALSO
========

   ASP::NextLink(3)

Perl implementation of the NextLink ASP component
*************************************************

NAME
====

   ASP::NextLink - Perl implementation of the NextLink ASP component

SYNOPSIS
========

     require ASP::NextLink;
     $nl = new ASP::NextLink('linkfile.ext');

     $current = $nl->GetListIndex;
     for $idx (1..$nl->GetListCount) {
     	my $url =	$nl->GetNthURL($idx);
     	my $desc =	$nl->GetNthDescription($idx);
     	if ($idx == $current) {
     		print qq(<A href="$url">$desc</A><BR>);
     	}
     	else {
     		print qq(<B>$desc</B>);
     	}
     }

DESCRIPTION
===========

   ASP::NextLink is a Perl implementation of MSWC.NextLink, ASP's
content-linking component for use with Apache::ASP.

NOTES
=====

   ASP::NextLink is NOT functionally equivalent to MSWC.NextLink.  Whereas
each method of MSWC.NextLink takes a file argument, ASP::NextLink takes a
file argument ONLY in the constructor ( ASP::NextLink->new("linkfile") ).
new() parses the linkfile given; the information derived from this
linkfile is subsequently available only through the object returned by
new().

   Attempts to call object methods on a class and attempts to call class
methods on an object will both trigger an exception.

   However, in the interest of portability of algorithms to ASP::NextLink,
indexes passed to the GetNth*() methods remain 1-based, as they are in
MSWC.NextLink.

USE
===

require ASP::NextLink;
----------------------

METHOD REFERENCE
================

new( linkfile )
---------------

   The new() class method accepts a virtual or relative path.  (Paths
handed to new() are run through the $Server->MapPath() method.)  new()
returns a reference to an ASP::NextLink object.

     my $linkfile = "/links.txt";
     my $nl = ASP::NextLink->new( $linkfile );

   From now we will refer to the object returned by new() as $nl.

GetListCount()
--------------

   Returns the number of links (lines containing tab-separated fields) in
link file.

     my $count = $nl->GetListCount();

GetListIndex()
--------------

   Index of the current page in the link file.

GetPreviousURL()
----------------

   URL of the previous page in the link file.

GetPreviousDescription()
------------------------

   Description of the previous page in the link file.

GetNextURL()
------------

   URL of the next page in the link file.

GetNextDescription()
--------------------

   Description of the next page in the link file.

GetNthURL( n )
--------------

   URL of the nth page in the link file.  NOTE: Index is 1-based, NOT
zero-based.

GetNthDescription( n )
----------------------

   Description of the nth page in the link file.  NOTE: Index is 1-based,
NOT zero-based.

AUTHOR
======

   Tim Hammerquist <`cafall@voffice.net'>

HISTORY
=======

Version 0.11
     First functional release

SEE ALSO
========

   ASP(3)

Object-Oriented Access to ACEDB Databases
*****************************************

NAME
====

   Ace - Object-Oriented Access to ACEDB Databases

SYNOPSIS
========

     use Ace;
     # open a remote database connection
     $db = Ace->connect(-host => 'beta.crbm.cnrs-mop.fr',
                        -port => 20000100);

     # open a local database connection
     $local = Ace->connect(-path=>'~acedb/my_ace');

     # simple queries
     $sequence  = $db->fetch(Sequence => 'D12345');
     $count     = $db->count(Sequence => 'D*');
     @sequences = $db->fetch(Sequence => 'D*');
     $i         = $db->fetch_many(Sequence=>'*');  # fetch a cursor
     while ($obj = $i->next) {
        print $obj->asTable;
     }

     # complex queries
     $query = <<END;
     find Annotation Ready_for_submission ; follow gene ;
     follow derived_sequence ; >DNA
     END
     @ready_dnas= $db->fetch(-query=>$query);

     $ready = $db->fetch_many(-query=>$query);
     while ($obj = $ready->next) {
         # do something with obj
     }

     # database cut and paste
     $sequence = $db->fetch(Sequence => 'D12345');
     $local_db->put($sequence);
     @sequences = $db->fetch(Sequence => 'D*');
     $local_db->put(@sequences);

     # Get errors
     print Ace->error;
     print $db->error;

DESCRIPTION
===========

   AcePerl provides an interface to the ACEDB object-oriented database.
Both read and write access is provided, and ACE objects are returned as
similarly-structured Perl objects.  Multiple databases can be opened
simultaneously.

   You will interact with several Perl classes: *Ace*, *Ace::Object*,
*Ace::Iterator*, *Ace::Model*.  *Ace* is the database accessor, and can be
used to open both remote Ace databases (running aceserver or
gifaceserver), and local ones.

   *Ace::Object* is the superclass for all objects returned from the
database.  *Ace* and *Ace::Object* are linked: if you retrieve an
Ace::Object from a particular database, it will store a reference to the
database and use it to fetch any subobjects contained within it.  You may
make changes to the *Ace::Object* and have those changes written into the
database.  You may also create *Ace::Object*s from scratch and store them
in the database.

   *Ace::Iterator* is a utility class that acts as a database cursor for
long-running ACEDB queries.  *Ace::Model* provides object-oriented access
to ACEDB's schema.

   Internally, *Ace* uses the *Ace::Local* class for access to local
databases and *Ace::AceDB* for access to remote databases.  Ordinarily you
will not need to interact directly with either of these classes.

CREATING NEW DATABASE CONNECTIONS
=================================

connect() - multiple argument form
----------------------------------

     # remote database
     $db = Ace->connect(-host  =>  'beta.crbm.cnrs-mop.fr',
                        -port  =>  20000100);

     # local (non-server) database
     $db = Ace->connect(-path  =>  '/usr/local/acedb);

   Use Ace::connect() to establish a connection to a networked or local
AceDB database.  To establish a connection to an AceDB server, use the
*-host* and/or *-port* arguments.  For a local server, use the *-port*
argument.  The database must be up and running on the indicated host and
port prior to connecting to an AceDB server.  The full syntax is as
follows:

     $db = Ace->connect(-host  =>  $host,
                        -port  =>  $port,
     		       -path  =>  $database_path,
     		       -program =>$local_connection_program
                        -class =>  $object_class,
     		       -timeout => $timeout,
     		       -query_timeout => $query_timeout);

   The connect() method uses a named argument calling style, and
recognizes the following arguments:

*-host*, *-port*
     These arguments point to the host and port of an AceDB server.
     AcePerl will use its internal compiled code to establish a connection
     to the server unless explicitly overridden with the *-program*
     argument.

*-path*
     This argument indicates the path of an AceDB directory on the local
     system.  It should point to the directory that contains the *wspec*
     subdirectory.  User name interpolations (~acedb) are OK.

*-user*
     Name of user to log in as (when using socket server *only*).  If not
     provided, will attempt an anonymous login.

*-pass*
     Password to log in with (when using socket server).

*-program*
     By default AcePerl will use its internal compiled code calls to
     establish a connection to Ace servers, and will launch a *tace*
     subprocess to communicate with local Ace databases.  The *-program*
     argument allows you to customize this behavior by forcing AcePerl to
     use a local program to communicate with the database.  This argument
     should point to an executable on your system.  You may use either a
     complete path or a bare command name, in which case the PATH
     environment variable will be consulted.  For example, you could force
     AcePerl to use the *aceclient* program to connect to the remote host
     by connecting this way:

          $db = Ace->connect(-host => 'beta.crbm.cnrs-mop.fr',
                             -port => 20000100,
                             -program=>'aceclient');

*-class*
     The optional *-class* argument points to the class you would like to
     return from database queries.  It is provided for your use if you
     subclass Ace::Object.  For example, if you have created a subclass of
     Ace::Object called Ace::Object::Graphics, you can have the database
     return this subclass by default by connecting this way:

          $db = Ace->connect(-host => 'beta.crbm.cnrs-mop.fr',
                             -port => 20000100,
          	             -class=>'Ace::Object::Graphics');

*-timeout*
     If no response from the server is received within $timeout seconds,
     the call will return an undefined value.  Internally timeout sets an
     alarm and temporarily intercepts the ALRM signal.  You should be aware
     of this if you use ALRM for your own purposes.

     NOTE: this feature is temporarily disabled (as of version 1.40)
     because it is generating unpredictable results when used with
     Apache/mod_perl.

*-query_timeout*
     If any query takes longer than $query_timeout seconds, will return an
     undefined value.  This value can only be set at connect time, and
     cannot be changed once set.

   If arguments are omitted, they will default to the following values:

     -host          localhost
     -port          200005;
     -path          no default
     -program       tace
     -class         Ace::Object
     -timeout       25
     -query_timeout 120

   If you prefer to use a more Smalltalk-like message-passing syntax, you
can open a connection this way too:

     $db = connect Ace -host=>'beta.crbm.cnrs-mop.fr',-port=>20000100;

   The return value is an Ace handle to use to access the database, or
undef if the connection fails.  If the connection fails, an error message
can be retrieved by calling Ace->error.

   You may check the status of a connection at any time with ping().  It
will return a true value if the database is still connected.  Note that
Ace will timeout clients that have been inactive for any length of time.
Long-running clients should attempt to reestablish their connection if
ping() returns false.

     $db->ping() || die "not connected";

   You may perform low-level calls using the Ace client C API by calling
db().  This fetches an Ace::AceDB object.  See THE LOW LEVEL C API for
details on using this object.

   $low_level = $db->db();

connect() - single argument form
--------------------------------

     $db = Ace->connect('sace://stein.cshl.org:1880')

   Ace->connect() also accepts a single argument form using a URL-type
syntax.  The general syntax is:

     protocol://hostname:port/path

   The *:port* and */path* parts are protocol-dependent as described above.

   Protocols:

sace://hostname:port
     Connect to a socket server at the indicated hostname and port.
     Example:

          sace://stein.cshl.org:1880

     If not provided, the port defaults to 2005.

rpcace://hostname:port
     Connect to an RPC server at the indicated hostname and RPC service
     number.  Example:

          rpcace://stein.cshl.org:400000

     If not provided, the port defaults to 200005

tace:/path/to/database
     Open up the local database at /path/to/database using tace.  Example:

          tace:/~acedb/elegans

/path/to/database
     Same as the previous.

close() Method
--------------

   You can explicitly close a database by calling its close() method:

     $db->close();

   This is not ordinarily necessary because the database will be
automatically close when it - and all objects retrieved from it - go out
of scope.

RETRIEVING ACEDB OBJECTS
========================

   Once you have established a connection and have an Ace databaes handle,
several methods can be used to query the ACE database to retrieve objects.
You can then explore the objects, retrieve specific fields from them, or
update them using the *Ace::Object* methods.  Please see Ace/Object.

fetch() method
--------------

     $count   = $db->fetch($class,$name_pattern);
     $object  = $db->fetch($class,$name);
     @objects = $db->fetch($class,$name_pattern,[$count,$offset]);
     @objects = $db->fetch(-name=>$name_pattern,
                           -class=>$class
     			  -count=>$count,
     			  -offset=>$offset,
                           -fill=>$fill,
     			  -filltag=>$tag,
     	                  -total=>\$total);
     @objects = $db->fetch(-query=>$query);

   Ace::fetch() retrieves objects from the database based on their class
and name.  You may retrieve a single object by requesting its name, or a
group of objects by fetching a name pattern.  A pattern contains one or
more wildcard characters, where "*" stands for zero or more characters,
and "?" stands for any single character.

   This method behaves differently depending on whether it is called in a
scalar or a list context, and whether it is asked to search for a name
pattern or a simple name.

   When called with a class and a simple name, it returns the object
referenced by that time, or undef, if no such object exists.  In an array
context, it will return an empty list.

   When called with a class and a name pattern in a list context, fetch()
returns the list of objects that match the name.  When called with a
pattern in a scalar context, fetch() returns the number of objects that
match without actually retrieving them from the database.  Thus, it is
similar to count().

   In the examples below, the first line of code will fetch the Sequence
object whose database ID is *D12345*.  The second line will retrieve all
objects matching the pattern *D1234**.  The third line will return the
count of objects that match the same pattern.

     $object =  $db->fetch(Sequence => 'D12345');
     @objects = $db->fetch(Sequence => 'D1234*');
     $cnt =     $db->fetch(Sequence =>'D1234*');

   A variety of communications and database errors may occur while
processing the request.  When this happens, undef or an empty list will be
returned, and a string describing the error can be retrieved by calling
Ace->error.

   When retrieving database objects, it is possible to retrieve a "filled"
or an "unfilled" object.  A filled object contains the entire contents of
the object, including all tags and subtags.  In the case of certain
Sequence objects, this may be a significant amount of data.  Unfilled
objects consist just of the object name.  They are filled in from the
database a little bit at a time as tags are requested.  By default,
fetch() returns the unfilled object.  This is usually a performance win,
but if you know in advance that you will be needing the full contents of
the retrieved object (for example, to display them in a tree browser) it
can be more efficient to fetch them in filled mode. You do this by calling
fetch() with the argument of *-fill* set to a true value.

   The *-filltag* argument, if provided, asks the database to fill in the
subtree anchored at the indicated tag.  This will improve performance for
frequently-accessed subtrees.  For example:

     @objects = $db->fetch(-name    => 'D123*',
                           -class   => 'Sequence',
                           -filltag => 'Visible');

   This will fetch all Sequences named D123* and fill in their Visible
trees in a single operation.

   Other arguments in the named parameter calling form are *-count*, to
retrieve a certain maximum number of objects, and *-offset*, to retrieve
objects beginning at the indicated offset into the list.  If you want to
limit the number of objects returned, but wish to learn how many objects
might have been retrieved, pass a reference to a scalar variable in the
*-total* argument.  This will return the object count.  This example shows
how to fetch 100 Sequence objects, starting at Sequence number 500:

     @some_sequences = $db->fetch('Sequence','*',100,500);

   The next example uses the named argument form to fetch 100 Sequence
objects starting at Sequence number 500, and leave the total number of
Sequences in $total:

     @some_sequences = $db->fetch(-class  => 'Sequence',
     	                       -count  => 100,
     	                       -offset => 500,
     	                       -total  => \$total);

   Notice that if you leave out the *-name* argument the "*" wildcard is
assumed.

   You may also pass an arbitrary Ace query string with the *-query*
argument.  This will supersede any name and class you provide.  Example:

     @ready_dnas= $db->fetch(-query=>
         'find Annotation Ready_for_submission ; follow gene ;
          follow derived_sequence ; >DNA');

   If your request is likely to retrieve very many objects, fetch() many
consume a lot of memory, even if *-fill* is false.  Consider using
*fetch_many()* instead (see below).

aql() method
------------

     $count   = $db->aql($aql_query);
     @objects = $db->aql($aql_query);

   Ace::aql() will perform an AQL query on the database.  In a scalar
context it returns the number of rows returned.  In an array context it
returns a list of rows.  Each row is an anonymous array containing the
columns returned by the query as an Ace::Object.

   If an AQL error is encountered, will return undef or an empty list and
set Ace->error to the error message.

   Note that this routine is not optimized - there is no iterator defined.
All results are returned synchronously, leading to large memory
consumption for certain queries.

put() method
------------

     $cnt = $db->put($obj1,$obj2,$obj3);

   This method will put the list of objects into the database, overwriting
like-named objects if they are already there.  This can be used to copy an
object from one database to another, provided that the models are
compatible.

   The method returns the count of objects successfully written into the
database.  In case of an error, processing will stop at the last object
successfully written and an error message will be placed in Ace->error();

parse() method
--------------

     $object = $db->parse('data to parse');

   This will parse the Ace tags contained within the "data to parse"
string, convert it into an object in the databse, and return the resulting
Ace::Object.  In case of a parse error, the undefined value will be
returned and a (hopefully informative) description of the error will be
returned by Ace->error().

   For example:

     $author = $db->parse(<<END);
     Author : "Glimitz JR"
     Full_name "Jonathan R. Glimitz"
     Mail	"128 Boylston Street"
     Mail	"Boston, MA"
     Mail	"USA"
     Laboratory GM
     END

   This method can also be used to parse several objects, but only the
last object successfully parsed will be returned.

parse_longtext() method
-----------------------

     $object = $db->parse($title,$text);

   This will parse the long text (which may contain carriage returns and
other funny characters) and place it into the database with the given
title.  In case of a parse error, the undefined value will be returned and
a (hopefully informative) description of the error will be returned by
Ace->error(); otherwise, a LongText object will be returned.

   For example:

     $author = $db->parse_longtext('A Novel Inhibitory Domain',<<END);
     We have discovered a novel inhibitory domain that inhibits
     many classes of proteases, including metallothioproteins.
     This inhibitory domain appears in three different gene families studied
     to date...
     END

parse_file() method
-------------------

     @objects = $db->parse_file('/path/to/file');
     @objects = $db->parse_file('/path/to/file',1);

   This will call parse() to parse each of the objects found in the
indicated .ace file, returning the list of objects successfully loaded
into the database.

   By default, parsing will stop at the first object that causes a parse
error.  If you wish to forge on after an error, pass a true value as the
second argument to this method.

   Any parse error messages are accumulated in Ace->error().

list() method
-------------

     @objects = $db->list(class,pattern,[count,offset]);
     @objects = $db->list(-class=>$class,
                          -name=>$name_pattern,
                          -count=>$count,
                          -offset=>$offset);

   This is a deprecated method.  Use fetch() instead.

count() method
--------------

     $count = $db->count($class,$pattern);
     $count = $db->count(-query=>$query);

   This function queries the database for a list of objects matching the
specified class and pattern, and returns the object count.  For large sets
of objects this is much more time and memory effective than fetching the
entire list.

   The class and name pattern are the same as the list() method above.

   You may also provide a *-query* argument to instead specify an
arbitrary ACE query such as "find Author COUNT Paper > 80".  See find()
below.

find() method
-------------

     @objects = $db->find($query_string);
     @objects = $db->find(-query => $query_string,
                          -offset=> $offset,
                          -count => $count
                          -fill  => $fill);

   This allows you to pass arbitrary Ace query strings to the server and
retrieve all objects that are returned as a result.  For example, this
code fragment retrieves all papers written by Jean and Danielle
Thierry-Mieg.

     @papers = $db->find('author IS "Thierry-Mieg *" ; >Paper');

   You can find the full query syntax reference guide plus multiple
examples at http://probe.nalusda.gov:8000/acedocs/index.html#query.

   In the named parameter calling form, *-count*, *-offset*, and *-fill*
have the same meanings as in fetch().

fetch_many() method
-------------------

     $obj = $db->fetch_many($class,$pattern);

     $obj = $db->fetch_many(-class=>$class,
                            -name =>$pattern,
                            -fill =>$filled,
                            -chunksize=>$chunksize);

     $obj = $db->fetch_many(-query=>$query);

   If you expect to retrieve many objects, you can fetch an iterator
across the data set.  This is friendly both in terms of network bandwidth
and memory consumption.  It is simple to use:

     $i = $db->fetch_many(Sequence,'*');  # all sequences!!!!
     while ($obj = $i->next) {
        print $obj->asTable;
     }

   The iterator will return undef when it has finished iterating, and
cannot be used again.  You can have multiple iterators open at once and
they will operate independently of each other.

   Like fetch(), *fetch_many()* takes an optional *-fill* (or *-filled*)
argument which retrieves the entire object rather than just its name.
This is efficient on a network with high latency if you expect to be
touching many parts of the object (rather than just retrieving the value
of a few tags).

   *fetch_many()* retrieves objects from the database in groups of a
certain maximum size, 40 by default.  This can be tuned using the optional
*-chunksize* argument.  Chunksize is only a hint to the database.  It may
return fewer objects per transaction, particularly if the objects are
large.

   You may provide raw Ace query string with the *-query* argument.  If
present the *-name* and *-class* arguments will be ignored.

find_many() method
------------------

   This is an alias for fetch_many().  It is now deprecated.

keyset() method
---------------

     @objects = $db->keyset($keyset_name);

   This method returns all objects in a named keyset.  Wildcard characters
are accepted, in which case all keysets that match the pattern will be
retrieved and merged into a single list of unique objects.

grep() method
-------------

     @objects = $db->grep($grep_string);
     $count   = $db->grep($grep_string);
     @objects = $db->grep(-pattern => $grep_string,
                          -offset=> $offset,
                          -count => $count,
                          -fill  => $fill,
     			 -total => \$total,
                          -long  => 1,
     			);

   This performs a "grep" on the database, returning all object names or
text that contain the indicated grep pattern.  In a scalar context this
call will return the number of matching objects.  In an array context, the
list of matching objects are retrieved.  There is also a named-parameter
form of the call, which allows you to specify the number of objects to
retrieve, the offset from the beginning of the list to retrieve from,
whether the retrieved objects should be filled initially.  You can use
*-total* to discover the total number of objects that match, while only
retrieving a portion of the list.

   By default, grep uses a fast search that only examines class names and
lexiques.  By providing a true value to the *-long* parameter, you can
search inside LongText and other places that are not usually touched on,
at the expense of much more CPU time.

   Due to "not listable" objects that may match during grep, the list of
objects one can retrieve may not always match the count.

model() method
--------------

     $model = $db->model('Author');

   This will return an *Ace::Model* object corresponding to the indicated
class.

new() method
------------

     $obj = $db->new($class,$name);
     $obj = $db->new(-class=>$class,
                     -name=>$name);

   Create a new object in the database with the indicated class and name
and return a pointer to it.  Will return undef if the object already
exists in the database.  The object isn't actually written into the
database until you call Ace::Object::commit().

raw_query() method
------------------

     $r = $db->raw_query('Model');

   Send a command to the database and return its unprocessed output.  This
method is necessary to gain access to features that are not yet
implemented in this module, such as model browsing and complex queries.

classes() method
----------------

     @classes = $db->classes();
     @all_classes = $db->classes(1);

   This method returns a list of all the object classes known to the
server.  In a list context it returns an array of class names.  In a
scalar context, it the number of classes defined in the database.

   Ordinarily *classes()* will return only those classes that are exposed
to the user interface for browsing, the so-called "visible" classes.  Pass
a true argument to the call to retrieve non-visible classes as well.

class_count() method
--------------------

     %classes = $db->class_count()

   This returns a hash in which the keys are the class names and the
values are the total number of objects in that class.  All classes are
returned, including invisible ones.  Use this method if you need to count
all classes simultaneously.  If you only want to count one or two classes,
it may be more efficient to call *count($class_name)* instead.

   This method transiently uses a lot of memory.  It should not be used
with Ace 4.5 servers, as they contain a memory leak in the counting
routine.

status() method
---------------

     %status = $db->status;
     $status = $db->status;

   Returns various bits of status information from the server.  In an
array context, returns a hash.  In a scalar context, returns a hash
reference.  The keys in the hash are as follows:

     version       Ace server version number
     date          Ace server link date
     directory     Path to database directory
     blocks        Number of disk blocks used by database
     classes       Number of defined classes
     keys          Number of defined keys
     memory        Memory usage, in kb
     write         Whether write access has been granted

date_style() method
-------------------

     $style = $db->date_style();
     $style = $db->date_style('ace');
     $style = $db->date_style('java');

   For historical reasons, AceDB can display dates using either of two
different formats.  The first format, which I call "ace" style, puts the
year first, as in "1997-10-01".  The second format, which I call "java"
style, puts the day first, as in "01 Oct 1997 00:00:00" (this is also the
style recommended for Internet dates).  The default is to use the latter
notation.

   *date_style()* can be used to set or retrieve the current style.
Called with no arguments, it returns the current style, which will be one
of "ace" or "java."  Called with an argument, it will set the style to one
or the other.

timestamps() method
-------------------

     $timestamps_on = $db->timestamps();
     $db->timestamps(1);

   Whenever a data object is updated, AceDB records the time and date of
the update, and the user ID it was running under.  Ordinarily, the
retrieval of timestamp information is suppressed to conserve memory and
bandwidth.  To turn on timestamps, call the *timestamps()* method with a
true value.  You can retrieve the current value of the setting by calling
the method with no arguments.

   Note that activating timestamps disables some of the speed
optimizations in AcePerl.  Thus they should only be activated if you
really need the information.

auto_save()
-----------

   Sets or queries the *auto_save* variable.  If true, the "save" command
will be issued automatically before the connection to the database is
severed.  The default is true.

   Examples:

     $db->auto_save(1);
     $flag = $db->auto_save;

error() method
--------------

     Ace->error;

   This returns the last error message.  Like UNIX errno, this variable is
not reset between calls, so its contents are only valid after a method
call has returned a result value indicating a failure.

   For your convenience, you can call error() in any of several ways:

     print Ace->error();
     print $db->error();  # $db is an Ace database handle
     print $obj->error(); # $object is an Ace::Object

   There's also a global named $Ace::Error that you are free to use.

THE LOW LEVEL C API
===================

   Internally Ace.pm makes C-language calls to libace to send query
strings to the server and to retrieve the results.  The class that exports
the low-level calls is named Ace::AceDB.

   The following methods are available in Ace::AceDB:

new($host,$port,$query_timeout)
     Connect to the host $host at port $port. Queries will time out after
     $query_timeout seconds.  If timeout is not specified, it defaults to
     120 (two minutes).

     If successful, this call returns an Ace::AceDB connection object.
     Otherwise, it returns undef.  Example:

          $acedb = Ace::AceDB->new('localhost',200005,5)
                   || die "Couldn't connect";

     The Ace::AceDB object can also be accessed from the high-level Ace
     interface by calling the ACE::db() method:

          $db = Ace->new(-host=>'localhost',-port=>200005);
          $acedb = $db->db();

query($request)
     Send the query string $request to the server and return a true value
     if successful.  You must then call read() repeatedly in order to fetch
     the query result.

read()
     Read the result from the last query sent to the server and return it
     as a string.  ACE may return the result in pieces, breaking between
     whole objects.  You may need to read repeatedly in order to fetch the
     entire result.  Canonical example:

          $acedb->query("find Sequence D*");
          die "Got an error ",$acedb->error() if $acedb->status == STATUS_ERROR;
          while ($acedb->status == STATUS_PENDING) {
             $result .= $acedb->read;
          }

status()
     Return the status code from the last operation.  Status codes are
     exported by default when you use Ace.pm.  The status codes you may
     see are:

          STATUS_WAITING    The server is waiting for a query.
          STATUS_PENDING    A query has been sent and Ace is waiting for
                            you to read() the result.
          STATUS_ERROR      A communications or syntax error has occurred

error()
     Returns a more detailed error code supplied by the Ace server.  Check
     this value when STATUS_ERROR has been returned.  These constants are
     also exported by default.  Possible values:

          ACE_INVALID
          ACE_OUTOFCONTEXT
          ACE_SYNTAXERROR
          ACE_UNRECOGNIZED

     Please see the ace client library documentation for a full description
     of these error codes and their significance.

encore()
     This method may return true after you have performed one or more
     read() operations, and indicates that there is more data to read.  You
     will not ordinarily have to call this method.

BUGS
====

   1. The ACE model should be consulted prior to updating the database.

   2. There is no automatic recovery from connection errors.

   3. Debugging has only one level of verbosity, despite the best of
intentions.

   4. Performance is poor when fetching big objects, because of many
object references that must be created.  This could be improved.

   5. When called in an array context at("tag[0]") should return the
current tag's entire column.  It returns the current subtree instead.

   6. There is no way to add comments to objects.

   7. When timestamps are active, many optimizations are disabled.

   8. Item number eight is still missing.

SEE ALSO
========

   See Ace/Object, Ace/Local,
Ace/Model, Ace/Sequence,
Ace/Sequence/Multi.

AUTHOR
======

   Lincoln Stein <lstein@cshl.org> with extensive help from Jean
Thierry-Mieg <mieg@kaa.crbm.cnrs-mop.fr>

   Copyright (c) 1997-1998 Cold Spring Harbor Laboratory

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

Subroutines for AceBrowser
**************************

NAME
====

   Ace::Browser::AceSubs - Subroutines for AceBrowser

SYNOPSIS
========

     use Ace;
     use Ace::Browser::AceSubs;
     use CGI qw(:standard);

     my $obj = GetAceObject() || AceMissing();
     AceHeader();

     print start_html('AceBrowser Report');
     print Header();
     print TypeSelector($obj);
     print h1("Report for $obj");
     print Footer();

     See L<Ace::Graphics::Panel> and L<Ace::Graphics::Glyph>.

DESCRIPTION
===========

   This glyph draws a series of filled rectangles connected by up-angled
connectors or "hats".  The rectangles indicate exons; the hats are
introns.  The direction of transcription is indicated by a small arrow at
the end of the glyph, rightward for the + strand.

   The feature must respond to the exons() and optionally introns()
methods, or it will default to the generic display.  Implied introns (not
returned by the introns() method) are drawn in a contrasting color to
explicit introns.

OPTIONS
-------

   In addition to the common options, the following glyph-specific option
is recognized:

     Option                Description                    Default
     ------                -----------                    -------

     -implied_intron_color The color to use for gaps      gray
                           not returned by the introns()
                           method.

     -draw_arrow           Whether to draw arrowhead      true
                           indicating direction of
                           transcription.

BUGS
====

   Please report them.

SEE ALSO
========

   See Ace/Sequence, Ace/Sequence/Feature,
see Ace/Graphics/Panel,
Ace/Graphics/Track,
Ace/Graphics/Glyph/anchored_arrow,
Ace/Graphics/Glyph/arrow,
`Ace::Graphics::Glyph::box' in this node, see
Ace/Graphics/Glyph/primers,
Ace/Graphics/Glyph/segments,
`Ace::Graphics::Glyph::toomany' in this node, see
Ace/Graphics/Glyph/transcript,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

   Copyright (c) 2001 Cold Spring Harbor Laboratory

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

A dummy feature object used for generating panel key tracks
***********************************************************

NAME
====

   Ace::Graphics::Fk - A dummy feature object used for generating panel
key tracks

SYNOPSIS
========

   None.  Used internally by Ace::Graphics::Panel.

DESCRIPTION
===========

   None.  Used internally by Ace::Graphics::Panel.

SEE ALSO
========

   See Ace/Sequence,Ace/Sequence/Feature,
see Ace/Graphics/Track,
Ace/Graphics/Glyph, GD,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

   Copyright (c) 2001 Cold Spring Harbor Laboratory

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

Base class for Ace::Graphics::Glyph objects
*******************************************

NAME
====

   Ace::Graphics::Glyph - Base class for Ace::Graphics::Glyph objects

SYNOPSIS
========

   See Ace/Graphics/Panel.

DESCRIPTION
===========

   Ace::Graphics::Glyph is the base class for all glyph objects.  Each
glyph is a wrapper around an Ace::Sequence::Feature object, knows how to
render itself on an Ace::Graphics::Panel, and has a variety of
configuration variables.

   End developers will not ordinarily work directly with
Ace::Graphics::Glyph, but may want to subclass it for customized displays.

METHODS
=======

   This section describes the class and object methods for
Ace::Graphics::Glyph.

CONSTRUCTORS
------------

   Ace::Graphics::Glyph objects are constructed automatically by an
Ace::Graphics::GlyphFactory, and are not usually created by end-developer
code.

$glyph = Ace::Graphics::Glyph->new(-feature=>$feature,-factory=>$factory)
     Given a sequence feature, creates an Ace::Graphics::Glyph object to
     display it.  The -feature argument points to the
     Ace::Sequence::Feature object to display.  -factory indicates an
     Ace::Graphics::GlyphFactory object from which the glyph will fetch all
     its run-time configuration information.

     A standard set of options are recognized.  See `OPTIONS' in this node.

OBJECT METHODS
--------------

   Once a glyph is created, it responds to a large number of methods.  In
this section, these methods are grouped into related categories.

   Retrieving glyph context:

$factory = $glyph->factory
     Get the Ace::Graphics::GlyphFactory associated with this object.  This
     cannot be changed once it is set.

$feature = $glyph->feature
     Get the sequence feature associated with this object.  This cannot be
     changed once it is set.

   Retrieving glyph options:

$fgcolor = $glyph->fgcolor
$bgcolor = $glyph->bgcolor
$fontcolor = $glyph->fontcolor
$fillcolor = $glyph->fillcolor
     These methods return the configured foreground, background, font and
     fill colors for the glyph in the form of a GD::Image color index.

$width = $glyph->width
     Return the maximum width allowed for the glyph.  Most glyphs will be
     smaller than this.

$font = $glyph->font
     Return the font for the glyph.

$option = $glyph->option($option)
     Return the value of the indicated option.

$index = $glyph->color($color)
     Given a symbolic or #RRGGBB-form color name, returns its GD index.

   Retrieving information about the sequence:

$start = $glyph->start
$end   = $glyph->end
     These methods return the start and end of the glyph in base pair
     units.

$offset = $glyph->offset
     Returns the offset of the segment (the base pair at the far left of
     the image).

$length = $glyph->length
     Returns the length of the sequence segment.

   Retrieving formatting information:

$top = $glyph->top
$left = $glyph->left
$bottom = $glyph->bottom
$right = $glyph->right
     These methods return the top, left, bottom and right of the glyph in
     pixel coordinates.

$height = $glyph->height
     Returns the height of the glyph.  This may be somewhat larger or
     smaller than the height suggested by the GlyphFactory, depending on
     the type of the glyph.

$scale = $glyph->scale
     Get the scale for the glyph in pixels/bp.

$height = $glyph->labelheight
     Return the height of the label, if any.

$label = $glyph->label
     Return a human-readable label for the glyph.

   These methods are called by Ace::Graphics::Track during the layout
process:

$glyph->move($dx,$dy)
     Move the glyph in pixel coordinates by the indicated delta-x and
     delta-y values.

($x1,$y1,$x2,$y2) = $glyph->box
     Return the current position of the glyph.

   These methods are intended to be overridden in subclasses:

$glyph->calculate_height
     Calculate the height of the glyph.

$glyph->calculate_left
     Calculate the left side of the glyph.

$glyph->calculate_right
     Calculate the right side of the glyph.

$glyph->draw($gd,$left,$top)
     Optionally offset the glyph by the indicated amount and draw it onto
     the GD::Image object.

$glyph->draw_label($gd,$left,$top)
     Draw the label for the glyph onto the provided GD::Image object,
     optionally offsetting by the amounts indicated in $left and $right.

   These methods are useful utility routines:

$pixels = $glyph->map_pt($bases);
     Map the indicated base position, given in base pair units, into
     pixels, using the current scale and glyph position.

$glyph->filled_box($gd,$x1,$y1,$x2,$y2)
     Draw a filled rectangle with the appropriate foreground and fill
     colors, and pen width onto the GD::Image object given by $gd, using
     the provided rectangle coordinates.

$glyph->filled_oval($gd,$x1,$y1,$x2,$y2)
     As above, but draws an oval inscribed on the rectangle.

OPTIONS
-------

   The following options are standard among all Glyphs.  See individual
glyph pages for more options.

     Option      Description               Default
     ------      -----------               -------

     -fgcolor    Foreground color		black

     -outlinecolor				black
     	      Synonym for -fgcolor

     -bgcolor    Background color          white

     -fillcolor  Interior color of filled  turquoise
     	      images

     -linewidth  Width of lines drawn by	1
     		    glyph

     -height     Height of glyph		10

     -font       Glyph font		gdSmallFont

     -label      Whether to draw a label	false

SUBCLASSING Ace::Graphics::Glyph
================================

   By convention, subclasses are all lower-case.  Begin each subclass with
a preamble like this one:

     package Ace::Graphics::Glyph::crossbox;

     use strict;
     use vars '@ISA';
     @ISA = 'Ace::Graphics::Glyph';

   Then override the methods you need to.  Typically, just the draw()
method will need to be overridden.  However, if you need additional room
in the glyph, you may override calculate_height(), calculate_left() and
calculate_right().  Do not directly override height(), left() and right(),
as their purpose is to cache the values returned by their calculating
cousins in order to avoid time-consuming recalculation.

   A simple draw() method looks like this:

     sub draw {
      my $self = shift;
      $self->SUPER::draw(@_);
      my $gd = shift;

     # and draw a cross through the box
     my ($x1,$y1,$x2,$y2) = $self->calculate_boundaries(@_);
     my $fg = $self->fgcolor;
     $gd->line($x1,$y1,$x2,$y2,$fg);
     $gd->line($x1,$y2,$x2,$y1,$fg);
      }

   This subclass draws a simple box with two lines criss-crossed through
it.  We first call our inherited draw() method to generate the filled box
and label.  We then call calculate_boundaries() to return the coordinates
of the glyph, disregarding any extra space taken by labels.  We call
fgcolor() to return the desired foreground color, and then call
$gd->line() twice to generate the criss-cross.

   For more complex draw() methods, see Ace::Graphics::Glyph::transcript
and Ace::Graphics::Glyph::segments.

BUGS
====

   Please report them.

SEE ALSO
========

   See Ace/Sequence, Ace/Sequence/Feature,
see Ace/Graphics/Panel,
Ace/Graphics/Track,
Ace/Graphics/Glyph/anchored_arrow,
Ace/Graphics/Glyph/arrow,
`Ace::Graphics::Glyph::box' in this node, see
Ace/Graphics/Glyph/primers,
Ace/Graphics/Glyph/segments,
`Ace::Graphics::Glyph::toomany' in this node, see
Ace/Graphics/Glyph/transcript,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

   Copyright (c) 2001 Cold Spring Harbor Laboratory

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

The "anchored_arrow" glyph
**************************

NAME
====

   Ace::Graphics::Glyph::anchored_arrow - The "anchored_arrow" glyph

SYNOPSIS
========

     See L<Ace::Graphics::Panel> and L<Ace::Graphics::Glyph>.

DESCRIPTION
===========

   This glyph draws an arrowhead which is anchored at one or both ends
(has a vertical base) or has one or more arrowheads.  The arrowheads
indicate that the feature does not end at the edge of the picture, but
continues.  For example:

     |-----------------------------|          both ends in picture
      <----------------------|                    left end off picture
          |---------------------------->      right end off picture
      <------------------------------------>      both ends off picture

OPTIONS
-------

   No additional options are recognized.  =head1 BUGS

   Please report them.

SEE ALSO
========

   See Ace/Sequence, Ace/Sequence/Feature,
see Ace/Graphics/Panel,
Ace/Graphics/Track,
Ace/Graphics/Glyph/anchored_arrow,
Ace/Graphics/Glyph/arrow,
`Ace::Graphics::Glyph::box' in this node, see
Ace/Graphics/Glyph/primers,
Ace/Graphics/Glyph/segments,
`Ace::Graphics::Glyph::toomany' in this node, see
Ace/Graphics/Glyph/transcript,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

   Copyright (c) 2001 Cold Spring Harbor Laboratory

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

The "arrow" glyph
*****************

NAME
====

   Ace::Graphics::Glyph::arrow - The "arrow" glyph

SYNOPSIS
========

     See L<Ace::Graphics::Panel> and L<Ace::Graphics::Glyph>.

DESCRIPTION
===========

   This glyph draws arrows.  Depending on options, the arrows can be
labeled, be oriented vertically or horizontally, or can contain major and
minor ticks suitable for use as a scale.

OPTIONS
-------

   In addition to the common options, the following glyph-specific options
are recognized:

     Option      Description               Default
     ------      -----------               -------

     -tick       Whether to draw major       0
                 and minor ticks.
     	      0 = no ticks
     	      1 = major ticks
     	      2 = minor ticks

     -parallel   Whether to draw the arrow   true
     	      parallel to the sequence
     	      or perpendicular to it.

     -northeast  Whether to draw the         true
     	      north or east arrowhead
     	      (depending on orientation)

     -southwest  Whether to draw the         true
     	      south or west arrowhead
     	      (depending on orientation)

   Set -parallel to false to display a point-like feature such as a
polymorphism, or to indicate an important location.  If the feature start
== end, then the glyph will draw a single arrow at the designated location:

     ^
     |

   Otherwise, there will be two arrows at the start and end:

     ^              ^
     |              |

BUGS
====

   Please report them.

SEE ALSO
========

   See Ace/Sequence, Ace/Sequence/Feature,
see Ace/Graphics/Panel,
Ace/Graphics/Track,
Ace/Graphics/Glyph/anchored_arrow,
Ace/Graphics/Glyph/arrow,
`Ace::Graphics::Glyph::box' in this node, see
Ace/Graphics/Glyph/primers,
Ace/Graphics/Glyph/segments,
`Ace::Graphics::Glyph::toomany' in this node, see
Ace/Graphics/Glyph/transcript,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

   Copyright (c) 2001 Cold Spring Harbor Laboratory

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

The group glyph
***************

NAME
====

   Ace::Graphics::Glyph::group - The group glyph

SYNOPSIS
========

   none

DESCRIPTION
===========

   This is an internal glyph type, used by Ace::Graphics::Track for moving
sets of glyphs around as a group.  This glyph is created automatically
when processing a set of features passed to Ace::Graphics::Panel->new as
an array ref.

OPTIONS
-------

   In addition to the common options, the following glyph-specific options
are recognized:

     Option      Description               Default
     ------      -----------               -------

     -connect    Whether to connect members  false
                 of the group by a dashed
                 line.

BUGS
====

   Please report them.

SEE ALSO
========

   See Ace/Sequence, Ace/Sequence/Feature,
see Ace/Graphics/Panel,
Ace/Graphics/Track,
Ace/Graphics/Glyph/anchored_arrow,
Ace/Graphics/Glyph/arrow,
`Ace::Graphics::Glyph::box' in this node, see
Ace/Graphics/Glyph/primers,
Ace/Graphics/Glyph/segments,
`Ace::Graphics::Glyph::toomany' in this node, see
Ace/Graphics/Glyph/transcript,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

   Copyright (c) 2001 Cold Spring Harbor Laboratory

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

The "line" glyph
****************

NAME
====

   Ace::Graphics::Glyph::line - The "line" glyph

SYNOPSIS
========

     See L<Ace::Graphics::Panel> and L<Ace::Graphics::Glyph>.

DESCRIPTION
===========

   This glyph draws a line parallel to the sequence segment.

OPTIONS
-------

   This glyph takes only the standard options.

BUGS
====

   Please report them.

SEE ALSO
========

   See Ace/Sequence, Ace/Sequence/Feature,
see Ace/Graphics/Panel,
Ace/Graphics/Track,
Ace/Graphics/Glyph/anchored_arrow,
Ace/Graphics/Glyph/arrow,
`Ace::Graphics::Glyph::box' in this node, see
Ace/Graphics/Glyph/primers,
Ace/Graphics/Glyph/segments,
`Ace::Graphics::Glyph::toomany' in this node, see
Ace/Graphics/Glyph/transcript,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

   Copyright (c) 2001 Cold Spring Harbor Laboratory

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

The "STS primers" glyph
***********************

NAME
====

   Ace::Graphics::Glyph::primers - The "STS primers" glyph

SYNOPSIS
========

     See L<Ace::Graphics::Panel> and L<Ace::Graphics::Glyph>.

DESCRIPTION
===========

   This glyph draws two arrows oriented towards each other and connected
by a line of a contrasting color.  The length of the arrows is immaterial,
but the length of the glyph itself corresponds to the length of the scaled
feature.

OPTIONS
-------

   In addition to the common options, the following glyph-specific options
are recognized:

     Option      Description               Default
     ------      -----------               -------

     -connect    Whether to connect the      false
                 two arrowheads by a line.

     -connect_color  The color to use for the    fgcolor
                 connecting line.

BUGS
====

   Please report them.

SEE ALSO
========

   See Ace/Sequence, Ace/Sequence/Feature,
see Ace/Graphics/Panel,
Ace/Graphics/Track,
Ace/Graphics/Glyph/anchored_arrow,
Ace/Graphics/Glyph/arrow,
`Ace::Graphics::Glyph::box' in this node, see
Ace/Graphics/Glyph/primers,
Ace/Graphics/Glyph/segments,
`Ace::Graphics::Glyph::toomany' in this node, see
Ace/Graphics/Glyph/transcript,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

   Copyright (c) 2001 Cold Spring Harbor Laboratory

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

The "discontinuous segments" glyph
**********************************

NAME
====

   Ace::Graphics::Glyph::segments - The "discontinuous segments" glyph

SYNOPSIS
========

     See L<Ace::Graphics::Panel> and L<Ace::Graphics::Glyph>.

DESCRIPTION
===========

   This glyph draws a sequence feature that consists of multiple
discontinuous segments, such as the exons on a transcript or a gapped
alignment.  The representation is a series of filled rectangles connected
by line segments.

   The features passed to it must either respond to the
Bio::SequenceFeatureI-style subSeqFeatures() method, or the
AcePerl/Das-style segments() or merged_segments() methods.

OPTIONS
-------

   Only the common options are recognized. There are no glyph-specific
options.

BUGS
====

   Please report them.

SEE ALSO
========

   See Ace/Sequence, Ace/Sequence/Feature,
see Ace/Graphics/Panel,
Ace/Graphics/Track,
Ace/Graphics/Glyph/anchored_arrow,
Ace/Graphics/Glyph/arrow,
`Ace::Graphics::Glyph::box' in this node, see
Ace/Graphics/Glyph/primers,
Ace/Graphics/Glyph/segments,
`Ace::Graphics::Glyph::toomany' in this node, see
Ace/Graphics/Glyph/transcript,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

   Copyright (c) 2001 Cold Spring Harbor Laboratory

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

The "gene" glyph
****************

NAME
====

   Ace::Graphics::Glyph::transcript - The "gene" glyph

SYNOPSIS
========

     See L<Ace::Graphics::Panel> and L<Ace::Graphics::Glyph>.

DESCRIPTION
===========

   This glyph draws a series of filled rectangles connected by up-angled
connectors or "hats".  The rectangles indicate exons; the hats are
introns.  The direction of transcription is indicated by a small arrow at
the end of the glyph, rightward for the + strand.

   The feature must respond to the exons() and optionally introns()
methods, or it will default to the generic display.  Implied introns (not
returned by the introns() method) are drawn in a contrasting color to
explicit introns.

OPTIONS
-------

   In addition to the common options, the following glyph-specific option
is recognized:

     Option                Description                    Default
     ------                -----------                    -------

     -implied_intron_color The color to use for gaps      gray
                           not returned by the introns()
                           method.

     -draw_arrow           Whether to draw arrowhead      true
                           indicating direction of
                           transcription.

BUGS
====

   Please report them.

SEE ALSO
========

   See Ace/Sequence, Ace/Sequence/Feature,
see Ace/Graphics/Panel,
Ace/Graphics/Track,
Ace/Graphics/Glyph/anchored_arrow,
Ace/Graphics/Glyph/arrow,
`Ace::Graphics::Glyph::box' in this node, see
Ace/Graphics/Glyph/primers,
Ace/Graphics/Glyph/segments,
`Ace::Graphics::Glyph::toomany' in this node, see
Ace/Graphics/Glyph/transcript,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

   Copyright (c) 2001 Cold Spring Harbor Laboratory

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

Create Ace::Graphics::Glyphs
****************************

NAME
====

   Ace::Graphics::GlyphFactory - Create Ace::Graphics::Glyphs

SYNOPSIS
========

     use Ace::Graphics::GlyphFactory;

     my $factory = Ace::Graphics::GlyphFactory($glyph_name,@options);

DESCRIPTION
===========

   The Ace::Graphics::GlyphFactory class is used internally by
Ace::Graphics::Track and Ace::Graphics::Glyph to hold the options
pertaining to a set of related glyphs and creating them on demand.  This
class is not ordinarily useful to the end-developer.

METHODS
=======

   This section describes the class and object methods for
Ace::Graphics::GlyphFactory.

CONSTRUCTORS
------------

   There is only one constructor, the new() method.  It is ordinarily
called by Ace::Graphics::Track, in the make_factory() subroutine.

$factory = Ace::Graphics::GlyphFactory->new($glyph_name,@options)
     The new() method creates a new factory object.  The object will create
     glyphs of type $glyph_name, and using the options specified in
     @options.  Generic options are described in Ace/Graphics/Panel,
     and specific options are described in each of the
     Ace::Graphics::Glyph::* manual pages.  =back

OBJECT METHODS
--------------

   Once a track is created, the following methods can be invoked:

$glyph = $factory->glyph($feature)
     Given a sequence feature, creates an Ace::Graphics::Glyph object to
     display it.  The various attributes of the glyph are set from the
     options provided at factory creation time.

$option = $factory->option($option_name [,$new_option])
     Given an option name, returns its value.  If a second argument is
     provided, sets the option to the new value and returns its previous
     one.

$index = $factory->fgcolor
     Returns the desired foreground color for the glyphs in the form of an
     GD::Image color index.  This may be the one of the special colors
     gdBrushed and gdStyled.  This is only useful while the enclosing
     Ace::Graphics::Panel object is rendering the object.  In other
     contexts it returns undef.

$scale = $factory->scale([$scale])
     Get or set the scale, in pixels/bp, for the glyph.  This is
     ordinarily set by the Ace::Graphics::Track object just prior to
     rendering, and called by each glyphs' map_pt() method when performing
     the rendering.

$color = $factory->bgcolor([$color])
     Get or set the background color for the glyphs.

$color = $factory->fillcolor([$color])
     Get or set the fill color for the glyphs.

$font = $factory->font([$font])
     Get or set the font to use for rendering the glyph.

$color = $factory->fontcolor
     Get the color for the font (to set it, use fgcolor()).  This is subtly
     different from fgcolor() itself, because it will never return a styled
     color, such as gdBrushed.

$panel = $factory->panel([$panel])
     Get or set the panel that contains the GD::Image object used by this
     factory.

$index = $factory->translate($color)
@rgb = $factory->rgb($index)
     These are convenience procedures that are passed through to the
     enclosing Panel object and have the same effect as the like-named
     methods in that class.  See Ace/Graphics/Panel.

BUGS
====

   Please report them.

SEE ALSO
========

   See Ace/Sequence, Ace/Sequence/Feature,
see Ace/Graphics/Panel,
Ace/Graphics/Track, Ace/Graphics/Glyph,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

   Copyright (c) 2001 Cold Spring Harbor Laboratory

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

PNG graphics of Ace::Sequence::Feature objects
**********************************************

NAME
====

   Ace::Graphics::Panel - PNG graphics of Ace::Sequence::Feature objects

SYNOPSIS
========

     use Ace::Sequence;
     use Ace::Graphics::Panel;

     my $db     = Ace->connect(-host=>'brie2.cshl.org',-port=>2005) or die;
     my $cosmid = Ace::Sequence->new(-seq=>'Y16B4A',
     				  -db=>$db,-start=>-15000,-end=>15000) or die;

     my @transcripts = $cosmid->transcripts;

     my $panel = Ace::Graphics::Panel->new(
     				      -segment => $cosmid,
     				      -width  => 800
     				     );

     $panel->add_track(arrow => $cosmid,
      		  -bump => 0,
      		  -tick=>2);

     $panel->add_track(transcript => \@transcripts,
      		    -fillcolor =>  'wheat',
      		    -fgcolor   =>  'black',
                       -key       => 'Curated Genes',
      		    -bump      =>  +1,
      		    -height    =>  10,
      		    -label     =>  1);

     my $boxes = $panel->boxes;
     print $panel->png;

DESCRIPTION
===========

   The Ace::Graphics::Panel class provides drawing and formatting services
for Ace::Sequence::Feature objects or Das::Segment::Feature objects.

   Typically you will begin by creating a new Ace::Graphics::Panel object,
passing it the width of the visual display and the length of the segment.

   You will then call add_track() one or more times to add sets of related
features to the picture.  When you have added all the features you desire,
you may call png() to convert the image into a PNG-format image, or
boxes() to return coordinate information that can be used to create an
imagemap.

   Note that this modules depends on GD.

METHODS
=======

   This section describes the class and object methods for
Ace::Graphics::Panel.

CONSTRUCTORS
------------

   There is only one constructor, the new() method.

$panel = Ace::Graphics::Panel->new(@options)
     The new() method creates a new panel object.  The options are a set
     of tag/value pairs as follows:

          Option      Value                                Default
          ------      -----                                -------

          -length     Length of sequence segment, in bp    0

          -segment    An Ace::Sequence or Das::Segment     none
                      object, used to derive length if
          	      not provided

          -offset     Base pair to place at extreme left   $segment->start
          	      of image.

          -width      Desired width of image, in pixels    600

          -spacing    Spacing between tracks, in pixels    5

          -pad_top    Additional whitespace between top    0
          	      of image and contents, in pixels

          -pad_bottom Additional whitespace between top    0
          	      of image and bottom, in pixels

          -pad_left   Additional whitespace between left   0
          	      of image and contents, in pixels

          -pad_right  Additional whitespace between right  0
          	      of image and bottom, in pixels

          -keycolor   Background color for the key printed 'cornsilk'
                      at bottom of panel (if any)

          -keyspacing Spacing between key glyphs in the    10
                      key printed at bottom of panel
                      (if any)

     Typically you will pass new() an object that implements the
     Bio::RangeI interface, providing a length() method, from which the
     panel will derive its scale.

          $panel = Ace::Graphics::Panel->new(-segment => $sequence,
          				     -width   => 800);

     new() will return undef in case of an error. If the specified glyph
     name is not a valid one, new() will throw an exception.

OBJECT METHODS
--------------

$track = $panel->add_track($glyph,$features,@options)
     The add_track() method adds a new track to the image.

     Tracks are horizontal bands which span the entire width of the panel.
     Each track contains a number of graphical elements called "glyphs",
     each corresponding to a sequence feature. There are different glyph
     types, but each track can only contain a single type of glyph.
     Options passed to the track control the color and size of the glyphs,
     whether they are allowed to overlap, and other formatting attributes.
     The height of a track is determined from its contents and cannot be
     directly influenced.

     The first two arguments are the glyph name and an array reference
     containing the list of features to display.  The order of the
     arguments is irrelevant, allowing either of these idioms:

          $panel->add_track(arrow => \@features);
          $panel->add_track(\@features => 'arrow');

     The glyph name indicates how each feature is to be rendered.  A
     variety of glyphs are available, and the number is growing.
     Currently, the following glyphs are available:

          Name        Description
          ----        -----------

          box	      A filled rectangle, nondirectional.

          arrow	      An arrow; can be unidirectional or bidirectional.
          	      It is also capable of displaying a scale with
          	      major and minor tickmarks, and can be oriented
          	      horizontally or vertically.

          segments    A set of filled rectangles connected by solid lines.
          	      Used for interrupted features, such as gapped
          	      alignments.

          transcript  Similar to segments, but the connecting line is
          	      a "hat" shape, and the direction of transcription
          	      is indicated by a small arrow.

          primers     Two inward pointing arrows connected by a line.
          	      Used for STSs.

          toomany     A "cloud", to indicate too many features to show
          	      individually.  This is a placeholder that will be
          	      replaced by something more clever, such as a histogram
          	      or density plot.

          group	      A group of related features connected by a dashed line.
          	      This is used internally by the Track class and should
          	      not be called explicitly.

     If the glyph name is omitted from add_track(), the "box" glyph will be
     used by default.

     The @options array is a list of name/value pairs that control the
     attributes of the track.  The options are in turn passed to the
     glyphs.  Each glyph has its own specialized subset of options, but
     some are shared by all glyphs:

          Option      Description               Default
          ------      -----------               -------

          -fgcolor    Foreground color		black

          -outlinecolor				black
          	      Synonym for -fgcolor

          -bgcolor    Background color          white

          -fillcolor  Interior color of filled  turquoise
          	      images

          -linewidth  Width of lines drawn by	1
          		    glyph

          -height     Height of glyph		10

          -font       Glyph font		gdSmallFont

          -label      Whether to draw a label	false

          -bump	      Bump direction		0

          -connect_groups                       false
                      Connect groups by a
          	      dashed line (see below)

          -key        Show this track in the    undef
                      key

     Colors can be expressed in either of two ways: as symbolic names such
     as "cyan" and as HTML-style #RRGGBB triples.  The symbolic names are
     the 140 colors defined in the Netscape/Internet Explorer color cube,
     and can be retrieved using the Ace::Graphics::Panel->color_names()
     method.

     The background color is used for the background color of the track
     itself.  The foreground color controls the color of lines and strings.
     The interior color is used for filled objects such as boxes.

     The -label argument controls whether or not the ID of the feature
     should be printed next to the feature.  It is accepted by most, but
     not all of the glyphs.

     The -bump argument controls what happens when glyphs collide.  By
     default, they will simply overlap (value 0).  A -bump value of +1 will
     cause overlapping glyphs to bump downwards until there is room for
     them.  A -bump value of -1 will cause overlapping glyphs to bump
     upwards.

     The -key argument declares that the track is to be shown in a key
     appended to the bottom of the image.  The key contains a picture of a
     glyph and a label describing what the glyph means.  The label is
     specified in the argument to -key.

     add_track() returns an Ace::Graphics::Track object.  You can use this
     object to add additional features or to control the appearance of the
     track with greater detail, or just ignore it.  Tracks are added in
     order from the top of the image to the bottom.  To add tracks to the
     top of the image, use unshift_track().

     Typical usage is:

          $panel->add_track( thistle    => \@genes,
          		    -fillcolor =>  'green',
          		    -fgcolor   =>  'black',
          		    -bump      =>  +1,
          		    -height    => 10,
          		    -label     => 1);

$track = unshift_track($glyph,$features,@options)
     unshift_track() works like add_track(), except that the new track is
     added to the top of the image rather than the bottom.

     *Adding groups of features:* It is not uncommon to add a group of
     features which are logically connected, such as the 5' and 3' ends of
     EST reads.  To group features into sets that remain on the same
     horizontal position and bump together, pass the sets as an anonymous
     array.  To connect the groups by a dashed line, pass the
     -connect_groups argument with a true value.  For example:

          $panel->add_track(segments => [[$abc_5,$abc_3],
          				 [$xxx_5,$xxx_3],
          				 [$yyy_5,$yyy_3]],
          		    -connect_groups => 1);

$gd = $panel->gd
     The gd() method lays out the image and returns a GD::Image object
     containing it.  You may then call the GD::Image object's png() or
     jpeg() methods to get the image data.

$png = $panel->png
     The png() method returns the image as a PNG-format drawing, without
     the intermediate step of returning a GD::Image object.

$boxes = $panel->boxes
@boxes = $panel->boxes
     The boxes() method returns the coordinates of each glyph, useful for
     constructing an image map.  In a scalar context, boxes() returns an
     array ref.  In an list context, the method returns the array directly.

     Each member of the list is an anonymous array of the following format:

          [ $feature, $x1, $y1, $x2, $y2 ]

     The first element is the feature object; either an
     Ace::Sequence::Feature, a Das::Segment::Feature, or another Bioperl
     Bio::SeqFeatureI object.  The coordinates are the topleft and
     bottomright corners of the glyph, including any space allocated for
     labels.

ACCESSORS
---------

   The following accessor methods provide access to various attributes of
the panel object.  Called with no arguments, they each return the current
value of the attribute.  Called with a single argument, they set the
attribute and return its previous value.

   Note that in most cases you must change attributes prior to invoking
gd(), png() or boxes().  These three methods all invoke an internal
layout() method which places the tracks and the glyphs within them, and
then caches the result.

     Accessor Name      Description
     -------------      -----------

     width()	      Get/set width of panel
     spacing()	      Get/set spacing between tracks
     length()	      Get/set length of segment (bp)
     pad_top()	      Get/set top padding
     pad_left()	      Get/set left padding
     pad_bottom()	      Get/set bottom padding
     pad_right()	      Get/set right padding

INTERNAL METHODS
----------------

   The following methods are used internally, but may be useful for those
implementing new glyph types.

@names = Ace::Graphics::Panel->color_names
     Return the symbolic names of the colors recognized by the panel
     object.  In a scalar context, returns an array reference.

@rgb = $panel->rgb($index)
     Given a GD color index (between 0 and 140), returns the RGB triplet
     corresponding to this index.  This method is only useful within a
     glyph's draw() routine, after the panel has allocated a GD::Image and
     is populating it.

$index = $panel->translate($color)
     Given a color, returns the GD::Image index.  The color may be
     symbolic, such as "turquoise", or a #RRGGBB triple, as in #F0E0A8.
     This method is only useful within a glyph's draw() routine, after the
     panel has allocated a GD::Image and is populating it.

$panel->set_pen($width,$color)
     Changes the width and color of the GD drawing pen to the values
     indicated.  This is called automatically by the GlyphFactory fgcolor()
     method.

BUGS
====

   Please report them.

SEE ALSO
========

   See Ace/Sequence,Ace/Sequence/Feature,
see Ace/Graphics/Track,
Ace/Graphics/Glyph, GD,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

   Copyright (c) 2001 Cold Spring Harbor Laboratory

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

PNG graphics of Ace::Sequence::Feature objects
**********************************************

NAME
====

   Ace::Graphics::Track - PNG graphics of Ace::Sequence::Feature objects

SYNOPSIS
========

     use Ace::Sequence;
     use Ace::Graphics::Panel;

     my $db     = Ace->connect(-host=>'brie2.cshl.org',-port=>2005) or die;
     my $cosmid = Ace::Sequence->new(-seq=>'Y16B4A',
     				  -db=>$db,-start=>-15000,-end=>15000) or die;

     my @transcripts = $cosmid->transcripts;

     my $panel = Ace::Graphics::Panel->new(
     				      -segment => $cosmid,
     				      -width  => 800
     				     );

     my $track = $panel->add_track('transcript'
      		                -fillcolor =>  'wheat',
     				-fgcolor   =>  'black',
     				-bump      =>  +1,
     				-height    =>  10,
     				-label     =>  1);
     foreach (@transcripts) {
        $track->add_feature($_);
     }

     my $boxes = $panel->boxes;
     print $panel->png;

DESCRIPTION
===========

   The Ace::Graphics::Track class is used by Ace::Graphics::Panel to lay
out a set of sequence features using a uniform glyph type. You will
ordinarily work with panels rather than directly with tracks.

METHODS
=======

   This section describes the class and object methods for
Ace::Graphics::Panel.

CONSTRUCTORS
------------

   There is only one constructor, the new() method.  It is ordinarily
called by Ace::Graphics::Panel, and not in end-developer code.

$track = Ace::Graphics::Track->new($glyph_name,$features,@options)
     The new() method creates a new track object from the provided glyph
     name and list of features.  The arguments are similar to those in
     Ace::Graphics::Panel->new().

     If successful new() will return a new Ace::Graphics::Track.
     Otherwise, it will return undef.

     If the specified glyph name is not a valid one, new() will throw an
     exception.

OBJECT METHODS
--------------

   Once a track is created, the following methods can be invoked.

$track->add_feature($feature)
     This adds a new feature to the track.  The feature can either be a
     single object that implements the Bio::SeqFeatureI interface (such as
     an Ace::Sequence::Feature or Das::Segment::Feature), or can be an
     anonymous array containing a set of related features.  In the latter
     case, the track will attempt to keep the features in the same
     horizontal band and will not allow any other features to overlap.

$track->add_group($group)
     This behaves the same as add_feature(), but requires that its argument
     be an array reference containing a list of grouped features.

$track->draw($gd,$left,$top)
     Render the track on a previously-created GD::Image object.  The $left
     and $top arguments indicate the position at which to start rendering.

$boxes = $track->boxes($left,$top)
@boxes = $track->boxes($left,$top)
     Return an array of array references indicating glyph coordinates for
     each of the render features.  $left and $top indicate the offset for
     the track on the image plane.  In a scalar context, this method
     returns an array reference of glyph coordinates.  In a list context,
     it returns the list itself.

     See Ace::Graphics::Panel->boxes() for the format of the result.

ACCESSORS
---------

   The following accessor methods provide access to various attributes of
the track object.  Called with no arguments, they each return the current
value of the attribute.  Called with a single argument, they set the
attribute and return its previous value.

   Note that in most cases you must change attributes before the track's
layout() method is called.

     Accessor Name      Description
     -------------      -----------

     scale()	      Get/set the track scale, measured in pixels/bp
     lineheight()	      Get/set the height of each glyph, pixels
     width()	      Get/set the width of the track
     bump()	      Get/set the bump direction

INTERNAL METHODS
----------------

   The following methods are used internally, but may be useful for those
implementing new glyph types.

$glyphs = $track->layout
     Layout the features, and return an anonymous array of
     Ace::Graphics::Glyph objects that have been created and correctly
     positioned.

     Because layout is an expensive operation, calling this method several
     times will return the previously-cached result, ignoring any changes
     to track attributes.

$height = $track->height
     Invokes layout() and returns the height of the track.

$glyphs = $track->glyphs
     Returns the glyph cache.  Returns undef before layout() and a
     reference to an array of glyphs after layout().

$factory = $track->make_factory(@options)
     Given a set of options (argument/value pairs), returns a
     Ace::Graphics::GlyphFactory for use in creating the glyphs with the
     desired settings.

BUGS
====

   Please report them.

SEE ALSO
========

   See Ace/Sequence,Ace/Sequence/Feature,
see Ace/Graphics/Panel,
Ace/Graphics/GlyphFactory,
Ace/Graphics/Glyph,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

   Copyright (c) 2001 Cold Spring Harbor Laboratory

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

Iterate Across an ACEDB Query
*****************************

NAME
====

   Ace::Iterator - Iterate Across an ACEDB Query

SYNOPSIS
========

     use Ace;
     $db = Ace->connect(-host => 'beta.crbm.cnrs-mop.fr',
                        -port => 20000100);

     $i  = $db->fetch_many(Sequence=>'*');  # fetch a cursor
     while ($obj = $i->next) {
        print $obj->asTable;
     }

DESCRIPTION
===========

   The Ace::Iterator class implements a persistent query on an Ace
database.  You can create multiple simultaneous queries and retrieve
objects from each one independently of the others.  This is useful when a
query is expected to return more objects than can easily fit into memory.
The iterator is essentially a database "cursor."

new() Method
------------

     $iterator = Ace::Iterator->new(-db        => $db,
                                    -query     => $query,
                                    -filled    => $filled,
                                    -chunksize => $chunksize);

   An Ace::Iterator is returned by the Ace accessor's object's
fetch_many() method. You usually will not have cause to call the new()
method directly.  If you do so, the parameters are as follows:

-db
     The Ace database accessor object to use.

-query
     A query, written in Ace query language, to pass to the database.  This
     query should return a list of objects.

-filled
     If true, then retrieve complete objects from the database, rather than
     empty object stubs.  Retrieving filled objects uses more memory and
     network bandwidth than retrieving unfilled objects, but it's
     recommended if you know in advance that you will be accessing most or
     all of the objects' fields, for example, for the purposes of
     displaying the objects.

-chunksize
     The iterator will fetch objects from the database in chunks controlled
     by this argument.  The default is 40.  You may want to tune the
     chunksize to optimize the retrieval for your application.

next() method
-------------

     $object = $iterator->next;

   This method retrieves the next object from the query, performing
whatever database accesses it needs.  After the last object has been
fetched, the next() will return undef.  Usually you will call next()
inside a loop like this:

     while (my $object = $iterator->next) {
        # do something with $object
     }

   Because of the way that object caching works, next() will be most
efficient if you are only looping over one iterator at a time.  Although
parallel access will work correctly, it will be less efficient than serial
access.  If possible, avoid this type of code:

     my $iterator1 = $db->fetch_many(-query=>$query1);
     my $iterator2 = $db->fetch_many(-query=>$query2);
     do {
        my $object1 = $iterator1->next;
        my $object2 = $iterator2->next;
     } while $object1 && $object2;

SEE ALSO
========

   See Ace, Ace/Model, Ace/Object,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org> with extensive help from Jean
Thierry-Mieg <mieg@kaa.crbm.cnrs-mop.fr>

   Copyright (c) 1997-1998 Cold Spring Harbor Laboratory

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

use giface, tace or gifaceclient to open a local connection to an Ace database
******************************************************************************

NAME
====

   Ace::Local - use giface, tace or gifaceclient to open a local
connection to an Ace database

SYNOPSIS
========

     use Ace::Local
     my $ace = Ace::Local->connect(-path=>'/usr/local/acedb/elegans');
     $ace->query('find author Se*');
     die "Query unsuccessful" unless $ace->status;
     $ace->query('show');
     while ($ace->encore) {
       print $ace->read;
     }

DESCRIPTION
===========

   This class is provided for low-level access to local (non-networked)
Ace databases via the *giface* program.  You will generally not need to
access it directly.  Use Ace.pm instead.

   For the sake of completeness, the method can also use the *aceclient*
program for its access.  However the Ace::AceDB class is more efficient
for this purpose.

METHODS
=======

connect()
---------

     $accessor = Ace::Local->connect(-path=>$path_to_database);

   Connect to the database at the indicated path using *giface* and return
a connection object (an "accessor").  *Giface* must be on the current
search path.  Multiple accessors may be open simultaneously.

   Arguments include:

*-path*
     Path to the database (location of the "wspec/" directory).

*-program*
     Used to indicate the location of the desired *giface* or
     *gifaceclient* executable.  You may also use *tace* or *aceclient*,
     but in that case the asGIF() functionality will nog work.  Can be used
     to override the search path.

*-host*
     Used when invoking *gifaceclient*.  Indicates the host to connect to.

*-port*
     Used when invoking *gifaceclient*.  Indicates the port to connect to.

*-nosync*
     Ordinarily Ace::Local synchronizes with the tace/giface prompt,
     throwing out all warnings and copyright messages.  If this is set,
     Ace::Local will not do so.  In this case you must call the low_read()
     method until it returns undef in order to synchronize.

query()
-------

     $status = $accessor->query('query string');

   Send the query string to the server and return a true value if
successful.  You must then call read() repeatedly in order to fetch the
query result.

read()
------

   Read the result from the last query sent to the server and return it as
a string.  ACE may return the result in pieces, breaking between whole
objects.  You may need to read repeatedly in order to fetch the entire
result.  Canonical example:

     $accessor->query("find Sequence D*");
     die "Got an error ",$accessor->error() if $accessor->status == STATUS_ERROR;
     while ($accessor->status == STATUS_PENDING) {
        $result .= $accessor->read;
     }

low_read()
----------

   Read whatever data's available, or undef if none.  This is only used by
the ace.pl replacement for giface/tace.

status()
--------

   Return the status code from the last operation.  Status codes are
exported by default when you use Ace.pm.  The status codes you may see are:

     STATUS_WAITING    The server is waiting for a query.
     STATUS_PENDING    A query has been sent and Ace is waiting for
                       you to read() the result.
     STATUS_ERROR      A communications or syntax error has occurred

error()
-------

   May return a more detailed error code supplied by Ace.  Error checking
is not fully implemented.

encore()
--------

   This method will return true after you have performed one or more
read() operations, and indicates that there is more data to read.
encore() is functionally equivalent to:

     $encore = $accessor->status == STATUS_PENDING;

   In fact, this is how it's implemented.

auto_save()
-----------

   Sets or queries the *auto_save* variable.  If true, the "save" command
will be issued automatically before the connection to the database is
severed.  The default is true.

   Examples:

     $accessor->auto_save(1);
     $flag = $accessor->auto_save;

SEE ALSO
========

   See Ace, Ace/Object, Ace/Iterator,
see Ace/Model,

AUTHOR
======

   Lincoln Stein <lstein@w3.org> with extensive help from Jean
Thierry-Mieg <mieg@kaa.crbm.cnrs-mop.fr>

   Copyright (c) 1997-1998, Lincoln D. Stein

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

Get information about AceDB models
**********************************

NAME
====

   Ace::Model - Get information about AceDB models

SYNOPSIS
========

     use Ace;
     my $db = Ace->connect(-path=>'/usr/local/acedb/elegans');
     my $model = $db->model('Author');
     print $model;
     $name = $model->name;
     @tags = $model->tags;
     print "Paper is a valid tag" if $model->valid_tag('Paper');

DESCRIPTION
===========

   This class is provided for access to AceDB class models.  It provides
the model in human-readable form, and does some limited but useful parsing
on your behalf.

   Ace::Model objects are obtained either by calling an Ace database
handle's model() method to retrieve the model of a named class, or by
calling an Ace::Object's model() method to retrieve the object's
particular model.

METHODS
=======

new()
-----

     $model = Ace::Model->new($model_data);

   This is a constructor intended only for use by Ace and Ace::Object
classes.  It constructs a new Ace::Model object from the raw string data
in models.wrm.

name()
------

     $name = $model->name;

   This returns the class name for the model.

tags()
------

     @tags = $model->tags;

   This returns a list of all the valid tags in the model.

valid_tag()
-----------

     $boolean  = $model->valid_tag($tag);

   This returns true if the given tag is part of the model.

path()        @path = $model->path($tag)
----------------------------------------

   Returns the path to the indicated tag, returning a list of intermediate
tags.  For example, in the C elegans ?Locus model, the path for
'Compelementation_data" will return the list ('Type','Gene').

asString()
----------

     print $model->asString;

   asString() returns the human-readable representation of the model with
comments stripped out.  Internally this method is called to automatically
convert the model into a string when appropriate.  You need only to start
performing string operations on the model object in order to convert it
into a string automatically:

     print "Paper is unique" if $model=~/Paper ?Paper UNIQUE/;

SEE ALSO
========

   See Ace,

AUTHOR
======

   Lincoln Stein <lstein@w3.org> with extensive help from Jean
Thierry-Mieg <mieg@kaa.crbm.cnrs-mop.fr>

   Copyright (c) 1997-1998, Lincoln D. Stein

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Manipulate  Ace Data Objects
****************************

NAME
====

   Ace::Object - Manipulate  Ace Data Objects

SYNOPSIS
========

     # open database connection and get an object
     use Ace;
     $db = Ace->connect(-host => 'beta.crbm.cnrs-mop.fr',
                        -port => 20000100);
     $sequence  = $db->fetch(Sequence => 'D12345');

     # Inspect the object
     $r    = $sequence->at('Visible.Overlap_Right');
     @row  = $sequence->row;
     @col  = $sequence->col;
     @tags = $sequence->tags;

     # Explore object substructure
     @more_tags = $sequence->at('Visible')->tags;
     @col       = $sequence->at("Visible.$more_tags[1]")->col;

     # Follow a pointer into database
     $r     = $sequence->at('Visible.Overlap_Right')->fetch;
     $next  = $r->at('Visible.Overlap_left')->fetch;

     # Classy way to do the same thing
     $r     = $sequence->Overlap_right;
     $next  = $sequence->Overlap_left;

     # Pretty-print object
     print $sequence->asString;
     print $sequence->asTabs;
     print $sequence->asHTML;

     # Update object
     $sequence->replace('Visible.Overlap_Right',$r,'M55555');
     $sequence->add('Visible.Homology','GR91198');
     $sequence->delete('Source.Clone','MBR122');
     $sequence->commit();

     # Rollback changes
     $sequence->rollback()

     # Get errors
     print $sequence->error;

DESCRIPTION
===========

   *Ace::Object* is the base class for objects returned from ACEDB
databases. Currently there is only one type of *Ace::Object*, but this may
change in the future to support more interesting object-specific behaviors.

   Using the *Ace::Object* interface, you can explore the internal
structure of an *Ace::Object*, retrieve its content, and convert it into
various types of text representation.  You can also fetch a representation
of any object as a GIF image.

   If you have write access to the databases, add new data to an object,
replace existing data, or kill it entirely.  You can also create a new
object de novo and write it into the database.

   For information on connecting to ACEDB databases and querying them, see
Ace.

ACEDB::OBJECT METHODS
=====================

   The structure of an Ace::Object is very similar to that of an Acedb
object.  It is a tree structure like this one (an Author object):

     Thierry-Mieg J->Full_name ->Jean Thierry-Mieg
                      |
                     Laboratory->FF
                      |
                     Address->Mail->CRBM duCNRS
                      |        |     |
                      |        |    BP 5051
                      |        |     |
                      |        |    34033 Montpellier
                      |        |     |
                      |        |    FRANCE
                      |        |
                      |       E_mail->mieg@kaa.cnrs-mop.fr
                      |        |
                      |       Phone ->33-67-613324
                      |        |
                      |       Fax   ->33-67-521559
                      |
                     Paper->The C. elegans sequencing project
                             |
                            Genome Project Database
                             |
                            Genome Sequencing
                             |
                             How to get ACEDB for your Sun
                             |
                            ACEDB is Hungry

   Each object in the tree has two pointers, a "right" pointer to the node
on its right, and a "down" pointer to the node beneath it.  Right pointers
are used to store hierarchical relationships, such as
Address->Mail->E_mail, while down pointers are used to store lists, such
as the multiple papers written by the Author.

   Each node in the tree has a type and a name.  Types include integers,
strings, text, floating point numbers, as well as specialized biological
types, such as "dna" and "peptide."  Another fundamental type is "tag,"
which is a text identifier used to label portions of the tree.  Examples
of tags include "Paper" and "Laboratory" in the example above.

   In addition to these built-in types, there are constructed types known
as classes.  These types are specified by the data model.  In the above
example, "Thierry-Mieg J" is an object of the "Author" class, and "Genome
Project Database" is an object of the "Paper" class.  An interesting
feature of objects is that you can follow them into the database,
retrieving further information.  For example, after retrieving the "Genome
Project Database" Paper from the Author object, you could fetch more
information about it, either by following *its* right pointer, or by using
one of the specialized navigation routines described below.

new() method
------------

     $object = new Ace::Object($class,$name,$database);
     $object = new Ace::Object(-class=>$class,
                               -name=>$name,
                               -db=>database);

   You can create a new Ace::Object from scratch by calling the new()
routine with the object's class, its identifier and a handle to the
database to create it in.  The object won't actually be created in the
database until you add() one or more tags to it and commit() it (see
below).  If you do not provide a database handle, the object will be
created in memory only.

   Arguments can be passed positionally, or as named parameters, as shown
above.

   This routine is usually used internally.  See also add_row(),
add_tree(), delete() and replace() for ways to manipulate this object.

name() method
-------------

     $name = $object->name();

   Return the name of the Ace::Object.  This happens automatically
whenever you use the object in a context that requires a string or a
number.  For example:

     $object = $db->fetch(Author,"Thierry-Mieg J");
     print "$object did not write 'Pride and Prejudice.'\n";

class() method
--------------

     $class = $object->class();

   Return the class of the object.  The return value may be one of
"float," "int," "date," "tag," "txt," "dna," "peptide," and "scalar."
(The last is used internally by Perl to represent objects created
programatically prior to committing them to the database.)  The class may
also be a user-constructed type such as Sequence, Clone or Author.  These
user-constructed types usually have an initial capital letter.

db() method
-----------

     $db = $object->db();

   Return the database that the object is associated with.

isClass() method
----------------

     $bool = $object->isClass();

   Returns true if the object is a class (can be fetched from the
database).

isTag() method
--------------

     $bool = $object->isTag();

   Returns true if the object is a tag.

tags() method
-------------

     @tags = $object->tags();

   Return all the top-level tags in the object as a list.  In the Author
example above, the returned list would be
('Full_name','Laboratory','Address','Paper').

   You can fetch tags more deeply nested in the structure by navigating
inwards using the methods listed below.

right() and down() methods
--------------------------

     $subtree = $object->right;
     $subtree = $object->right($position);
     $subtree = $object->down;
     $subtree = $object->down($position);

   *right()* and *down()* provide a low-level way of traversing the tree
structure by following the tree's right and down pointers.  Called without
any arguments, these two methods will move one step.  Called with a
numeric argument >= 0 they will move the indicated number of steps (zero
indicates no movement).

     $full_name = $object->right->right;
     $full_name = $object->right(2);

     $city = $object->right->down->down->right->right->down->down;
     $city = $object->right->down(2)->right(2)->down(2);

   If $object contains the "Thierry-Mieg J" Author object, then the first
series of accesses shown above retrieves the string "Jean Thierry-Mieg"
and the second retrieves "34033 Montpellier."  If the right or bottom
pointers are NULL, these methods will return undef.

   In addition to being somewhat awkard, you will probably never need to
use these methods.  A simpler way to retrieve the same information would
be to use the at() method described in the next section.

   The right() and down() methods always walk through the tree of the
current object.  They do not follow object pointers into the database.
Use fetch() (or the deprecated *pick()* or *follow()* methods) instead.

at() method
-----------

     $subtree    = $object->at($tag_path);
     @values     = $object->at($tag_path);

   at() is a simple way to fetch the portion of the tree that you are
interested in.  It takes a single argument, a simple tag or a path.  A
simple tag, such as "Full_name", must correspond to a tag in the column
immediately to the right of the root of the tree.  A path such as
"Address.Mail" is a dot-delimited path to the subtree.  Some examples are
given below.

     ($full_name)   = $object->at('Full_name');
     @address_lines = $object->at('Address.Mail');

   The second line above is equivalent to:

     @address = $object->at('Address')->at('Mail');

   Called without a tag name, at() just dereferences the object, returning
whatever is to the right of it, the same as $object->right

   If a path component already has a dot in it, you may escape the dot
with a backslash, as in:

     $s=$db->fetch('Sequence','M4');
     @homologies = $s->at('Homol.DNA_homol.yk192f7\.3';

   This also demonstrates that path components don't necessarily have to
be tags, although in practice they usually are.

   at() returns slightly different results depending on the context in
which it is called.  In a list context, it returns the column of values to
the right of the tag.  However, in a scalar context, it returns the
subtree rooted at the tag.  To appreciate the difference, consider these
two cases:

     $name1   = $object->at('Full_name');
     ($name2) = $object->at('Full_name');

   After these two statements run, $name1 will be the tag object named
"Full_name", and $name2 will be the text object "Jean Thierry-Mieg", The
relationship between the two is that $name1->right leads to $name2.  This
is a powerful and useful construct, but it can be a trap for the unwary.
If this behavior drives you crazy, use this construct:

   $name1   = $object->at('Full_name')->at();

   For finer control over navigation, path components can include optional
indexes to indicate navigation to the right of the current path component.
Here is the syntax:

     $object->at('tag1[index1].tag2[index2].tag3[index3]...');

   Indexes are zero-based.  An index of [0] indicates no movement relative
to the current component, and is the same as not using an index at all.
An index of [1] navigates one step to the right, [2] moves two steps to
the right, and so on.  Using the Thierry-Mieg object as an example again,
here are the results of various indexes:

     $object = $db->fetch(Author,"Thierry-Mieg J");
     $a = $object->at('Address[0]')   --> "Address"
     $a = $object->at('Address[1]')   --> "Mail"
     $a = $object->at('Address[2]')   --> "CRBM duCNRS"

   In an array context, the last index in the path does something very
interesting.  It returns the entire column of data K steps to the right of
the path, where K is the index.  This is used to implement so-called
"tag[2]" syntax, and is very useful in some circumstances.  For example,
here is a fragment of code to return the Thierry-Mieg object's full
address without having to refer to each of the intervening "Mail",
"E_Mail" and "Phone" tags explicitly.

     @address = $object->at('Address[2]');
     --> ('CRBM duCNRS','BP 5051','34033 Montpellier','FRANCE',
          'mieg@kaa.cnrs-mop.fr,'33-67-613324','33-67-521559')

   Similarly, "tag[3]" will return the column of data three hops to the
right of the tag.  "tag[1]" is identical to "tag" (with no index), and
will return the column of data to the immediate right.  There is no
special behavior associated with using "tag[0]" in an array context; it
will always return the subtree rooted at the indicated tag.

   Internal indices such as "Homol[2].BLASTN", do not have special
behavior in an array context.  They are always treated as if they were
called in a scalar context.

   Also see *col()* and get().

get() method
------------

     $subtree    = $object->get($tag);
     @values     = $object->get($tag);
     @values     = $object->get($tag, $position);
     @values     = $object->get($tag => $subtag, $position);

   The get() method will perform a breadth-first search through the object
(columns first, followed by rows) for the tag indicated by the argument,
returning the column of the portion of the subtree it points to.  For
example, this code fragment will return the value of the "Fax" tag.

     ($fax_no) = $object->get('Fax');
          --> "33-67-521559"

   The list versus scalar context semantics are the same as in at(), so if
you want to retrieve the scalar value pointed to by the indicated tag,
either use a list context as shown in the example, above, or a
dereference, as in:

     $fax_no = $object->get('Fax');
         --> "Fax"
     $fax_no = $object->get('Fax')->at;
         --> "33-67-521559"

   An optional second argument to get(), $position, allows you to navigate
the tree relative to the retrieved subtree.  Like the *at()* navigational
indexes, $position must be a number greater than or equal to zero.  In a
scalar context, $position moves rightward through the tree.  In an array
context, $position implements "tag[2]" semantics.

   For example:

     $fax_no = $object->get('Fax',0);
          --> "Fax"

     $fax_no = $object->get('Fax',1);
          --> "33-67-521559"

     $fax_no = $object->get('Fax',2);
          --> undef  # nothing beyond the fax number

     @address = $object->get('Address',2);
          --> ('CRBM duCNRS','BP 5051','34033 Montpellier','FRANCE',
               'mieg@kaa.cnrs-mop.fr,'33-67-613324','33-67-521559')

   It is important to note that get() only traverses tags.  It will not
traverse nodes that aren't tags, such as strings, integers or objects.
This is in keeping with the behavior of the Ace query language "show"
command.

   This restriction can lead to confusing results.  For example, consider
the following object:

     Clone: B0280  Position    Map            Sequence-III  Ends   Left   3569
                                                                   Right  3585
                               Pmap           ctg377        -1040  -1024
                   Positive    Positive_locus nhr-10
                   Sequence    B0280
                   Location    RW
                   FingerPrint Gel_Number     0
                               Canonical_for  T20H1
                                              K10E5
                               Bands          1354          18

   The following attempt to fetch the left and right positions of the
clone will fail, because the search for the "Left" and "Right" tags cannot
traverse "Sequence-III", which is an object, not a tag:

     my $left = $clone->get('Left');    # will NOT work
     my $right = $clone->get('Right');  # neither will this one

   You must explicitly step over the non-tag node in order to make this
query work.  This syntax will work:

     my $left = $clone->get('Map',1)->get('Left');   # works
     my $left = $clone->get('Map',1)->get('Right');  # works

   Or you might prefer to use the tag[2] syntax here:

     my($left,$right) = $clone->get('Map',1)->at('Ends[2]');

   Although not frequently used, there is a form of get() which allows you
to stack subtags:

     $locus = $object->get('Positive'=>'Positive_locus');

   Only on subtag is allowed.  You can follow this by a position if wish
to offset from the subtag.

     $locus = $object->get('Positive'=>'Positive_locus',1);

search() method
---------------

   This is a deprecated synonym for get().

Autogenerated Access Methods
----------------------------

     $scalar = $object->Name_of_tag;
     $scalar = $object->Name_of_tag($position);
     @array  = $object->Name_of_tag;
     @array  = $object->Name_of_tag($position);
     @array  = $object->Name_of_tag($subtag=>$position);

   The module attempts to autogenerate data access methods as needed.  For
example, if you refer to a method named "Fax" (which doesn't correspond to
any of the built-in methods), then the code will call the get() method to
find a tag named "Fax" and return its contents.

   Unlike get(), this method will *always step into objects*.  This means
that:

     $map = $clone->Map;

   will return the Sequence_Map object pointed to by the Clone's Map tag
and not simply a pointer to a portion of the Clone tree.  Therefore
autogenerated methods are functionally equivalent to the following:

     $map = $clone->get('Map')->fetch;

   The scalar context semantics are also slightly different.  In a scalar
context, the autogenerated function will *always* move one step to the
right.

   The list context semantics are identical to get().  If you want to
dereference all members of a multivalued tag, you have to do so manually:

     @papers = $author->Paper;
     foreach (@papers) {
       my $paper = $_->fetch;
       print  $paper->asString;
     }

   You can provide an optional positional index to rapidly navigate
through the tree or to obtain tag[2] behavior.  In the following examples,
the first two return the object's Fax number, and the third returns all
data two hops to the right of Address.

     $object   = $db->fetch(Author => 'Thierry-Mieg J');
     ($fax_no) = $object->Fax;
     $fax_no   = $object->Fax(1);
     @address  = $object->Address(2);

   You may also position at a subtag, using this syntax:

     $representative = $object->Laboratory('Representative');

   Both named tags and positions can be combined as follows:

     $lab_address = $object->Laboratory(Address=>2);

   ** Note that the semantics of the autogenerated methods have changed
subtly between version 1.57 (the last stable release) and version 1.62.
In earlier versions, calling an autogenerated method in a scalar context
returned the subtree rooted at the tag.  In the current version, an
implicit right() and dereference is performed.

fetch() method
--------------

     $new_object = $object->fetch;
     $new_object = $object->fetch($tag);

   Follow object into the database, returning a new object.  This is the
best way to follow object references.  For example:

     $laboratory = $object->at('Laboratory')->fetch;
     print $laboratory->asString;

   Because the previous example is a frequent idiom, the optional $tag
argument allows you to combine the two operations into a single one:

     $laboratory = $object->fetch('Laboratory');

follow() method
---------------

     @papers        = $object->follow('Paper');
     @filled_papers = $object->follow(-tag=>'Paper',-filled=>1);

   The follow() method will follow a tag into the database, dereferencing
the column to its right and returning the objects resulting from this
operation.  Beware!  If you follow a tag that points to an object, such as
the Author "Paper" tag, you will get a list of all the Paper objects.  If
you follow a tag that points to a scalar, such as "Full_name", you will
get an empty string.  In a scalar context, this method will return the
number of objects that would have been followed.

   The full named-argument form of this call accepts the arguments *-tag*
(mandatory) and *-filled* (optional).  The former points to the tag to
follow.  The latter accepts a boolean argument.  A true argument will
return "filled" objects, increasing network and memory usage, but possibly
boosting performance if you have a high database access latency.

   For backward compatability, if follow() is called without any
arguments, it will act like fetch().

pick() method
-------------

   Deprecated method.  This has the same semantics as fetch(), which
should be used instead.

col() method
------------

     @column = $object->col;
     @column = $object->col($position);

   *col()* flattens a portion of the tree by returning the column one hop
to the right of the current subtree. You can provide an additional
positional index to navigate through the tree using "tag[2]" behavior.
This example returns the author's mailing address:

     @mailing_address = $object->at('Address.Mail')->col();

   This example returns the author's entire address including mail, e-mail
and phone:

     @address = $object->at('Address')->col(2);

   It is equivalent to any of these calls:

     $object->at('Address[2]');
     $object->get('Address',2);
     $object->Address(2);

   Use whatever syntax is most comfortable for you.

   In a scalar context, *col()* returns the number of items in the column.

row() method
------------

     @row=$object->row();
     @row=$object->row($position);

   *row()* will return the row of data to the right of the object.  The
first member of the list will be the object itself.  In the case of the
"Thierry-Mieg J" object, the example below will return the list
('Address','Mail','CRBM duCNRS').

     @row = $object->Address->row();

   You can provide an optional position to move rightward one or more
places before retrieving the row.  This code fragment will return
('Mail','CRBM duCNRS'):

     @row = $object->Address->row(1);

   In a scalar context, *row()* returns the number of items in the row.

asString() method
-----------------

     $object->asString;

   asString() returns a pretty-printed ASCII representation of the object
tree.

asTable() method
----------------

     $object->asTable;

   asTable() returns the object as a tab-delimited text table.

asAce() method
--------------

     $object->asAce;

   asAce() returns the object as a tab-delimited text table in ".ace"
format.

asHTML() method
---------------

     $object->asHTML;
     $object->asHTML(\&tree_traversal_code);

   asHTML() returns an HTML 3 table representing the object, suitable for
incorporation into a Web browser page.  The callback routine, if provided,
will have a chance to modify the object representation before it is
incorporated into the table, for example by turning it into an HREF link.
The callback takes a single argument containing the object, and must
return a string-valued result.  It may also return a list as its result,
in which case the first member of the list is the string representation of
the object, and the second member is a boolean indicating whether to prune
the table at this level.  For example, you can prune large repetitive
lists.

   Here's a complete example:

     sub process_cell {
       my $obj = shift;
       return "$obj" unless $obj->isObject || $obj->isTag;

     my @col = $obj->col;
     my $cnt = scalar(@col);
     return ("$obj -- $cnt members",1);  # prune
            if $cnt > 10                 # if subtree to big

     # tags are bold
     return "<B>$obj</B>" if $obj->isTag;

     # objects are blue
     return qq{<FONT COLOR="blue">$obj</FONT>} if $obj->isObject;
        }

     $object->asHTML(\&process_cell);

asXML() method
--------------

     $result = $object->asXML;

   asXML() returns a well-formed XML representation of the object.  The
particular representation is still under discussion, so this feature is
primarily for demonstration.

asGIF() method
--------------

     ($gif,$boxes) = $object->asGIF();
     ($gif,$boxes) = $object->asGIF(-clicks=>[[$x1,$y1],[$x2,$y2]...]
     	                         -dimensions=>[$width,$height],
     				 -display => $display_type,
     				 -view    => $view_type
     	                         );

   asGIF() returns the object as a GIF image.  The contents of the GIF
will be whatever xace would ordinarily display in graphics mode, and will
vary for different object classes.

   You can optionally provide asGIF with a *-clicks* argument to simulate
the action of a user clicking on the image.  The click coordinates should
be formatted as an array reference that contains a series of two-element
subarrays, each corresponding to the X and Y coordinates of a single mouse
click.  There is currently no way to pass information about middle or
right mouse clicks, dragging operations, or keystrokes.  You may also
specify a *-dimensions* to control the width and height of the returned
GIF.  Since there is no way of obtaining the preferred size of the image
in advance, this is not usually useful.

   The optional *-display* argument allows you to specify an alternate
display for the object.  For example, Clones can be displayed either with
the PMAP display or with the TREE display.  If not specified, the default
display is used.

   The optional *-view* argument allows you to specify an alternative view
for MAP objects only.  If not specified, you'll get the default view.

   asGIF() returns a two-element array.  The first element is the GIF
data.  The second element is an array reference that indicates special
areas of the image called "boxes."  Boxes are rectangular areas that
surround buttons, and certain displayed objects.  Using the contents of
the boxes array, you can turn the GIF image into a client-side image map.
Unfortunately, not everything that is clickable is represented as a box.
You still have to pass clicks on unknown image areas back to the server
for processing.

   Each box in the array is a hash reference containing the following keys:

     'coordinates'  => [$left,$top,$right,$bottom]
     'class'        => object class or "BUTTON"
     'name'         => object name, if any
     'comment'      => a text comment of some sort

   *coordinates* points to an array of points indicating the top-left and
bottom-right corners of the rectangle.  class indicates the class of the
object this rectangle surrounds.  It may be a database object, or the
special word "BUTTON" for one of the display action buttons.  name
indicates the name of the object or the button.  comment is some piece of
information about the object in question.  You can display it in the
status bar of the browser or in a popup window if your browser provides
that facility.

asDNA() and asPeptide() methods
-------------------------------

     $dna = $object->asDNA();
     $peptide = $object->asPeptide();

   If you are dealing with a sequence object of some sort, these methods
will return strings corresponding to the DNA or peptide sequence in FASTA
format.

add_row() method
----------------

     $result_code = $object->add_row($tag=>$value);
     $result_code = $object->add_row($tag=>[list,of,values]);
     $result_code = $object->add(-path=>$tag,
     				-value=>$value);

   add_row() updates the tree by adding data to the indicated tag path.
The example given below adds the value "555-1212" to a new Address entry
named "Pager".  You may call add_row() a second time to add a new value
under this tag, creating multi-valued entries.

     $object->add_row('Address.Pager'=>'555-1212');

   You may provide a list of values to add an entire row of data.  For
example:

     $sequence->add_row('Assembly_tags'=>['Finished Left',38949,38952,'AC3']);

   Actually, the array reference is not entirely necessary, and if you
prefer you can use this more concise notation:

     $sequence->add_row('Assembly_tags','Finished Left',38949,38952,'AC3');

   No check is done against the database model for the correct data type
or tag path.  The update isn't actually performed until you call commit(),
at which time a result code indicates whether the database update was
successful.

   You may create objects that reference other objects this way:

     $lab = new Ace::Object('Laboratory','LM',$db);
     $lab->add_row('Full_name','The Laboratory of Medicine');
     $lab->add_row('City','Cincinatti');
     $lab->add_row('Country','USA');

     $author = new Ace::Object('Author','Smith J',$db);
     $author->add_row('Full_name','Joseph M. Smith');
     $author->add_row('Laboratory',$lab);

     $lab->commit();
     $author->commit();

   The result code indicates whether the addition was syntactically
correct.  add_row() will fail if you attempt to add a duplicate entry
(that is, one with exactly the same tag and value).  In this case, use
replace() instead.  Currently there is no checking for an attempt to add
multiple values to a single-valued (UNIQUE) tag.  The error will be
detected and reported at commit() time however.

   The add() method is an alias for add_row().

add_tree()
----------

     $result_code = $object->add_tree($tag=>$ace_object);
     $result_code = $object->add_tree(-tag=>$tag,-tree=>$ace_object);

   The add_tree() method will insert an entire Ace subtree into the object
to the right of the indicated tag.  This can be used to build up complex
Ace objects, or to copy portions of objects from one database to another.
The first argument is a tag path, and the second is the tree that you wish
to insert.  As with add_row() the database will only be updated when you
call commit().

   When inserting a subtree, you must be careful to remember that
everything to the *right* of the node that you are pointing at will be
inserted; not the node itself.  For example, given this Sequence object:

     Sequence AC3
       DB_info     Database    EMBL
       Assembly_tags   Finished Left   1   4   AC3
                       Clone left end      1   4   AC3
                       Clone right end     5512    5515    K07C5
                                           38949   38952   AC3
                       Finished Right      38949   38952   AC3

   If we use at('Assembly_tags') to fetch the subtree rooted on the
"Assembly_tags" tag, it is the tree to the right of this tag, beginning
with "Finished Left", that will be inserted.

   Here is an example of copying the "Assembly_tags" subtree from one
database object to another:

     $remote = Ace->connect(-port=>200005)  || die "can't connect";
     $ac3 = $remote->fetch(Sequence=>'AC3') || die "can't get AC7";
     my $assembly = $ac3->at('Assembly_tags');

     $local = Ace->connect(-path=>'~acedb') || die "can't connect";
     $AC3copy = Ace::Object->new(Sequence=>'AC3copy',$local);
     $AC3copy->add_tree('Assembly_tags'=>$tags);
     $AC3copy->commit || warn $AC3copy->error;

   Notice that this syntax will not work the way you think it should:

     $AC3copy->add_tree('Assembly_tags'=>$ac3->at('Assembly_tags'));

   This is because call at() in an array context returns the column to the
right of the tag, not the tag itself.

   Here's an example of building up a complex structure from scratch using
a combination of add() and add_tree():

     $newObj = Ace::Object->new(Sequence=>'A555',$local);
     my $assembly = Ace::Object->new(tag=>'Assembly_tags');
     $assembly->add('Finished Left'=>[10,20,'ABC']);
     $assembly->add('Clone right end'=>[1000,2000,'DEF']);
     $assembly->add('Clone right end'=>[8000,9876,'FRED']);
     $assembly->add('Finished Right'=>[1000,3000,'ETHEL']);
     $newObj->add_tree('Assembly_tags'=>$assembly);
     $newObj->commit || warn $newObj->error;

delete() method
---------------

     $result_code = $object->delete($tag_path,$value);
     $result_code = $object->delete(-path=>$tag_path,
                                    -value=>$value);

   Delete the indicated tag and value from the object.  This example
deletes the address line "FRANCE" from the Author's mailing address:

     $object->delete('Address.Mail','FRANCE');

   No actual database deletion occurs until you call commit().  The
delete() result code indicates whether the deletion was successful.
Currently it is always true, since the database model is not checked.

   =head2 replace() method

     $result_code = $object->replace($tag_path,$oldvalue,$newvalue);
     $result_code = $object->replace(-path=>$tag_path,
     				    -old=>$oldvalue,
     				    -new=>$newvalue);

   Replaces the indicated tag and value with the new value.  This example
changes the address line "FRANCE" to "LANGUEDOC" in the Author's mailing
address:

     $object->delete('Address.Mail','FRANCE','LANGUEDOC');

   No actual database changes occur until you call commit().  The delete()
result code indicates whether the replace was successful.  Currently is
true if the old value was identified.

commit() method
---------------

     $result_code = $object->commit;

   Commits all add(), replace() and delete() operations to the database.
It can also be used to write a completely new object into the database.
The result code indicates whether the object was successfully written.  If
an error occurred, further details can be found in the Ace->error() error
string.

rollback() method
-----------------

     $object->rollback;

   Discard all adds, deletions and replacements, returning the object to
the state it was in prior to the last commit().

   rollback() works by deleting the object from Perl memory and fetching
the object anew from AceDB.  If someone has changed the object in the
database while you were working with it, you will see this version, ot the
one you originally fetched.

   If you are creating an entirely new object, you must add at least one
tag in order to enter the object into the database.

kill() method
-------------

     $result_code = $object->kill;

   This will remove the object from the database immediately and
completely.  It does not wait for a commit(), and does not respond to a
rollback().  If successful, you will be left with an empty object that
contains just the class and object names.  Use with care!

   In the case of failure, which commonly happens when the database is not
open for writing, this method will return undef.  A description of the
problem can be found by calling the error() method.

date_style() method
-------------------

     $object->date_style('ace');

   This is a convenience method that can be used to set the date format
for all objects returned by the database.  It is exactly equivalent to

     $object->db->date_style('ace');

   Note that the text representation of the date will change for all
objects returned from this database, not just the current one.

isRoot() method
---------------

     print "Top level object" if $object->isRoot;

   This method will return true if the object is a "top level" object,
that is the root of an object tree rather than a subtree.

model() method
--------------

     $model = $object->model;

   This method will return the object's model as an Ace::Model object, or
undef if the object does not have a model. See Ace/Model,
for details.

timestamp() method
------------------

     $stamp = $object->timestamp;

   The *timestamp()* method will retrieve the modification time and date
from the object.  This works both with top level objects and with
subtrees.  Timestamp handling must be turned on in the database, or
*timestamp()* will return undef.

   The returned timestamp is actually a UserSession object which can be
printed and explored like any other object.  However, there is currently
no useful information in UserSession other than its name.

comment() method
----------------

     $comment = $object->comment;

   This returns the comment attached to an object or object subtree, if
any.  Comments are Comment objects and have the interesting property that
a single comment can refer to multiple objects.  If there is no comment
attached to the current subtree, this method will return undef.

   Currently you cannot create a new comment in AcePerl or edit an old one.

error() method          $error = $object->error;
------------------------------------------------

   Returns the error from the previous operation, if any.  As in
Ace::error(), this string will only have meaning if the previous operation
returned a result code indicating an error.

factory() method
----------------

   WARNING - THIS IS DEFUNCT AND NO LONGER WORKS.  USE THE Ace->class()
METHOD INSTEAD

     $package = $object->factory;

   When a root Ace object instantiates its tree of tags and values, it
creates a hierarchical structure of Ace::Object objects.  The factory()
method determines what class to bless these subsidiary objects into.  By
default, they are Ace::Object objects, but you can override this method in
a child class in order to create more specialized Ace::Object classes.
The method should return a string corresponding to the package to bless
the object into.  It receives the current Ace::Object as its first
argument.

debug() method
--------------

     $object->debug(1);

   Change the debugging mode.  A zero turns of debugging messages.
Integer values produce debug messages on standard error.  Higher integers
produce progressively more verbose messages.

SEE ALSO
========

   See Ace, Ace/Model, Ace/Object,
see Ace/Local, Ace/Sequence,
see Ace/Sequence/Multi,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org> with extensive help from Jean
Thierry-Mieg <mieg@kaa.crbm.cnrs-mop.fr>

   Copyright (c) 1997-1998, Lincoln D. Stein

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

Examine ACeDB Sequence Objects
******************************

NAME
====

   Ace::Sequence - Examine ACeDB Sequence Objects

SYNOPSIS
========

     # open database connection and get an Ace::Object sequence
     use Ace::Sequence;

     $db  = Ace->connect(-host => 'stein.cshl.org',-port => 200005);
     $obj = $db->fetch(Predicted_gene => 'ZK154.3');

     # Wrap it in an Ace::Sequence object
     $seq = Ace::Sequence->new($obj);

     # Find all the exons
     @exons = $seq->features('exon');

     # Find all the exons predicted by various versions of "genefinder"
     @exons = $seq->features('exon:genefinder.*');

     # Iterate through the exons, printing their start, end and DNA
     for my $exon (@exons) {
       print join "\t",$exon->start,$exon->end,$exon->dna,"\n";
     }

     # Find the region 1000 kb upstream of the first exon
     $sub = Ace::Sequence->new(-seq=>$exons[0],
                               -offset=>-1000,-length=>1000);

     # Find all features in that area
     @features = $sub->features;

     # Print its DNA
     print $sub->dna;

     # Create a new Sequence object from the first 500 kb of chromosome 1
     $seq = Ace::Sequence->new(-name=>'CHROMOSOME_I',-db=>$db,
     			      -offset=>0,-length=>500_000);

     # Get the GFF dump as a text string
     $gff = $seq->gff;

     # Limit dump to Predicted_genes
     $gff_genes = $seq->gff(-features=>'Predicted_gene');

     # Return a GFF object (using optional GFF.pm module from Sanger)
     $gff_obj = $seq->GFF;

DESCRIPTION
===========

   *Ace::Sequence*, and its allied classes Ace/Sequence/Feature,
and Ace/Sequence/FeatureList,
provide a convenient interface to the ACeDB
Sequence classes and the GFF sequence feature file format.

   Using this class, you can define a region of the genome by using a
landmark (sequenced clone, link, superlink, predicted gene), an offset
from that landmark, and a distance.  Offsets and distances can be positive
or negative.  This will return an *Ace::Sequence* object.  Once a region
is defined, you may retrieve its DNA sequence, or query the database for
any features that may be contained within this region.  Features can be
returned as objects (using the *Ace::Sequence::Feature* class), as GFF
text-only dumps, or in the form of the GFF class defined by the Sanger
Centre's GFF.pm module.

   This class builds on top of Ace, and Ace/Object.
Please see their manual pages before consulting this one.

Creating New Ace::Sequence Objects, the new() Method
====================================================

     $seq = Ace::Sequence->new($object);

     $seq = Ace::Sequence->new(-source  => $object,
                               -offset  => $offset,
                               -length  => $length,
     			   -refseq  => $reference_sequence);

     $seq = Ace::Sequence->new(-name    => $name,
     			   -db      => $db,
                               -offset  => $offset,
                               -length  => $length,
     			   -refseq  => $reference_sequence);

   In order to create an *Ace::Sequence* you will need an active *Ace*
database accessor.  Sequence regions are defined using a "source"
sequence, an offset, and a length.  Optionally, you may also provide a
"reference sequence" to establish the coordinate system for all inquiries.
Sequences may be generated from existing *Ace::Object* sequence objects,
from other *Ace::Sequence* and *Ace::Sequence::Feature* objects, or from a
sequence name and a database handle.

   The class method named new() is the interface to these facilities.  In
its simplest, one-argument form, you provide new() with a
previously-created *Ace::Object* that points to Sequence or sequence-like
object (the meaning of "sequence-like" is explained in more detail below.)
The new() method will return an *Ace::Sequence* object extending from the
beginning of the object through to its natural end.

   In the named-parameter form of new(), the following arguments are
recognized:

-source
     The sequence source.  This must be an *Ace::Object* of the "Sequence"
     class, or be a sequence-like object containing the SMap tag (see
     below).

-offset
     An offset from the beginning of the source sequence.  The retrieved
     *Ace::Sequence* will begin at this position.  The offset can be any
     positive or negative integer.  Offets are *0-based*.

-length
     The length of the sequence to return.  Either a positive or negative
     integer can be specified.  If a negative length is given, the returned
     sequence will be complemented relative to the source sequence.

-refseq
     The sequence to use to establish the coordinate system for the
     returned sequence.  Normally the source sequence is used to establish
     the coordinate system, but this can be used to override that choice.
     You can provide either an *Ace::Object* or just a sequence name for
     this argument.  The source and reference sequences must share a common
     ancestor, but do not have to be directly related.  An attempt to use a
     disjunct reference sequence, such as one on a different chromosome,
     will fail.

-name
     As an alternative to using an *Ace::Object* with the *-source*
     argument, you may specify a source sequence using *-name* and *-db*.
     The *Ace::Sequence* module will use the provided database accessor to
     fetch a Sequence object with the specified name. new() will return
     undef is no Sequence by this name is known.

-db
     This argument is required if the source sequence is specified by name
     rather than by object reference.

   If new() is successful, it will create an *Ace::Sequence* object and
return it.  Otherwise it will return undef and return a descriptive
message in Ace->error().  Certain programming errors, such as a failure to
provide required arguments, cause a fatal error.

Reference Sequences and the Coordinate System
---------------------------------------------

   When retrieving information from an *Ace::Sequence*, the coordinate
system is based on the sequence segment selected at object creation time.
That is, the "+1" strand is the natural direction of the *Ace::Sequence*
object, and base pair 1 is its first base pair.  This behavior can be
overridden by providing a reference sequence to the new() method, in which
case the orientation and position of the reference sequence establishes
the coordinate system for the object.

   In addition to the reference sequence, there are two other sequences
used by *Ace::Sequence* for internal bookeeping.  The "source" sequence
corresponds to the smallest ACeDB sequence object that completely encloses
the selected sequence segment.  The "parent" sequence is the smallest
ACeDB sequence object that contains the "source".  The parent is used to
derive the length and orientation of source sequences that are not
directly associated with DNA objects.

   In many cases, the source sequence will be identical to the sequence
initially passed to the new() method.  However, there are exceptions to
this rule.  One common exception occurs when the offset and/or length
cross the boundaries of the passed-in sequence.  In this case, the ACeDB
database is searched for the smallest sequence that contains both
endpoints of the *Ace::Sequence* object.

   The other common exception occurs in Ace 4.8, where there is support
for "sequence-like" objects that contain the `SMap' ("Sequence Map") tag.
The `SMap' tag provides genomic location information for arbitrary object
- not just those descended from the Sequence class.  This allows ACeDB to
perform genome map operations on objects that are not directly related to
sequences, such as genetic loci that have been interpolated onto the
physical map.  When an `SMap'-containing object is passed to the
*Ace::Sequence* new() method, the module will again choose the smallest
ACeDB Sequence object that contains both end-points of the desired region.

   If an *Ace::Sequence* object is used to create a new *Ace::Sequence*
object, then the original object's source is inherited.

Object Methods
==============

   Once an *Ace::Sequence* object is created, you can query it using the
following methods:

asString()
----------

     $name = $seq->asString;

   Returns a human-readable identifier for the sequence in the form
*Source/start-end*, where "Source" is the name of the source sequence, and
"start" and "end" are the endpoints of the sequence relative to the source
(using 1-based indexing).  This method is called automatically when the
*Ace::Sequence* is used in a string context.

source_seq()
------------

     $source = $seq->source_seq;

   Return the source of the *Ace::Sequence*.

parent_seq()
------------

     $parent = $seq->parent_seq;

   Return the immediate ancestor of the sequence.  The parent of the
top-most sequence (such as the CHROMOSOME link) is itself.  This method is
used internally to ascertain the length of source sequences which are not
associated with a DNA object.

   NOTE: this procedure is a trifle funky and cannot reliably be used to
traverse upwards to the top-most sequence.  The reason for this is that it
will return an *Ace::Sequence* in some cases, and an *Ace::Object* in
others.  Use get_parent() to traverse upwards through a uniform series of
*Ace::Sequence* objects upwards.

refseq([$seq])
--------------

     $refseq = $seq->refseq;

   Returns the reference sequence, if one is defined.

     $seq->refseq($new_ref);

   Set the reference sequence. The reference sequence must share the same
ancestor with $seq.

start()
-------

     $start = $seq->start;

   Start of this sequence, relative to the source sequence, using 1-based
indexing.

end()
-----

     $end = $seq->end;

   End of this sequence, relative to the source sequence, using 1-based
indexing.

offset()
--------

     $offset = $seq->offset;

   Offset of the beginning of this sequence relative to the source
sequence, using 0-based indexing.  The offset may be negative if the
beginning of the sequence is to the left of the beginning of the source
sequence.

length()
--------

     $length = $seq->length;

   The length of this sequence, in base pairs.  The length may be negative
if the sequence's orientation is reversed relative to the source sequence.
Use abslength() to obtain the absolute value of the sequence length.

abslength()
-----------

     $length = $seq->abslength;

   Return the absolute value of the length of the sequence.

strand()
--------

     $strand = $seq->strand;

   Returns +1 for a sequence oriented in the natural direction of the
genomic reference sequence, or -1 otherwise.

reversed()
----------

   Returns true if the segment is reversed relative to the canonical
genomic direction.  This is the same as $seq->strand < 0.

dna()
-----

     $dna = $seq->dna;

   Return the DNA corresponding to this sequence.  If the sequence length
is negative, the reverse complement of the appropriate segment will be
returned.

   ACeDB allows Sequences to exist without an associated DNA object (which
typically happens during intermediate stages of a sequencing project.  In
such a case, the returned sequence will contain the correct number of "-"
characters.

name()
------

     $name = $seq->name;

   Return the name of the source sequence as a string.

get_parent()
------------

     $parent = $seq->parent;

   Return the immediate ancestor of this *Ace::Sequence* (i.e., the
sequence that contains this one).  The return value is a new
*Ace::Sequence* or undef, if no parent sequence exists.

get_children()
--------------

     @children = $seq->get_children();

   Returns all subsequences that exist as independent objects in the ACeDB
database.  What exactly is returned is dependent on the data model.  In
older ACeDB databases, the only subsequences are those under the catchall
Subsequence tag.  In newer ACeDB databases, the objects returned
correspond to objects to the right of the S_Child subtag using a tag[2]
syntax, and may include Predicted_genes, Sequences, Links, or other
objects.  The return value is a list of *Ace::Sequence* objects.

features()
----------

     @features = $seq->features;
     @features = $seq->features('exon','intron','Predicted_gene');
     @features = $seq->features('exon:GeneFinder','Predicted_gene:hand.*');

   features() returns an array of *Sequence::Feature* objects.  If called
without arguments, features() returns all features that cross the sequence
region.  You may also provide a filter list to select a set of features by
type and subtype.  The format of the filter list is:

     type:subtype

   Where type is the class of the feature (the "feature" field of the GFF
format), and subtype is a description of how the feature was derived (the
"source" field of the GFF format).  Either of these fields can be absent,
and either can be a regular expression.  More advanced filtering is not
supported, but is provided by the Sanger Centre's GFF module.

   The order of the features in the returned list is not specified.  To
obtain features sorted by position, use this idiom:

     @features = sort { $a->start <=> $b->start } $seq->features;

feature_list()
--------------

     my $list = $seq->feature_list();

   This method returns a summary list of the features that cross the
sequence in the form of a `Ace::Feature::List' in this node object.  From
the `Ace::Feature::List' in this node object you can obtain the list of
feature names and the number of each type.  The feature list is obtained
from the ACeDB server with a single short transaction, and therefore has
much less overhead than features().

   See `Ace::Feature::List' in this node for more details.

transcripts()
-------------

   This returns a list of Ace::Sequence::Transcript objects, which are
specializations of Ace::Sequence::Feature.  See
Ace/Sequence/Transcript, for details.

clones()
--------

   This returns a list of Ace::Sequence::Feature objects containing
reconstructed clones.  This is a nasty hack, because ACEDB currently
records clone ends, but not the clones themselves, meaning that we will
not always know both ends of the clone.  In this case the missing end has
a synthetic position of -99,999,999 or +99,999,999.  Sorry.

gff()
-----

     $gff = $seq->gff();
     $gff = $seq->gff(-abs      => 1,
                      -features => ['exon','intron:GeneFinder']);

   This method returns a GFF file as a scalar.  The following arguments
are optional:

-abs
     Ordinarily the feature entries in the GFF file will be returned in
     coordinates relative to the start of the *Ace::Sequence* object.
     Position 1 will be the start of the sequence object, and the "+"
     strand will be the sequence object's natural orientation.  However if
     a true value is provided to *-abs*, the coordinate system used will
     be relative to the start of the source sequence, i.e. the native ACeDB
     Sequence object (usually a cosmid sequence or a link).

     If a reference sequence was provided when the *Ace::Sequence* was
     created, it will be used by default to set the coordinate system.
     Relative coordinates can be reenabled by providing a false value to
     *-abs*.

     Ordinarily the coordinate system manipulations automatically "do what
     you want" and you will not need to adjust them.  See also the abs()
     method described below.

-features
     The *-features* argument filters the features according to a list of
     types and subtypes.  The format is identical to the one described for
     the features() method.  A single filter may be provided as a scalar
     string.  Multiple filters may be passed as an array reference.

   See also the GFF() method described next.

GFF()
-----

     $gff_object = $seq->gff;
     $gff_object = $seq->gff(-abs      => 1,
                      -features => ['exon','intron:GeneFinder']);

   The GFF() method takes the same arguments as gff() described above, but
it returns a *GFF::GeneFeatureSet* object from the GFF.pm module.  If the
GFF module is not installed, this method will generate a fatal error.

absolute()
----------

     $abs = $seq->absolute;
     $abs = $seq->absolute(1);

   This method controls whether the coordinates of features are returned
in absolute or relative coordinates.  "Absolute" coordinates are relative
to the underlying source or reference sequence.  "Relative" coordinates
are relative to the *Ace::Sequence* object.  By default, coordinates are
relative unless new() was provided with a reference sequence.  This
default can be examined and changed using absolute().

automerge()
-----------

     $merge = $seq->automerge;
     $seq->automerge(0);

   This method controls whether groups of features will automatically be
merged together by the features() call.  If true (the default), then the
left and right end of clones will be merged into "clone" features,
introns, exons and CDS entries will be merged into
Ace::Sequence::Transcript objects, and similarity entries will be merged
into Ace::Sequence::GappedAlignment objects.

db()
----

     $db = $seq->db;

   Returns the Ace, database accessor associated with this
sequence.

SEE ALSO
========

   See Ace, Ace/Object,
Ace/Sequence/Feature,
Ace/Sequence/FeatureList, `GFF' in this node

AUTHOR
======

   Lincoln Stein <lstein@cshl.org> with extensive help from Jean
Thierry-Mieg <mieg@kaa.crbm.cnrs-mop.fr>

   Many thanks to David Block <dblock@gene.pbi.nrc.ca> for finding and
fixing the nasty off-by-one errors.

   Copyright (c) 1999, Lincoln D. Stein

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

Examine Sequence Feature Tables
*******************************

NAME
====

   Ace::Sequence::Feature - Examine Sequence Feature Tables

SYNOPSIS
========

     # open database connection and get an Ace::Object sequence
     use Ace::Sequence;

     # get a megabase from the middle of chromosome I
     $seq = Ace::Sequence->new(-name   => 'CHROMOSOME_I,
                               -db     => $db,
     			      -offset => 3_000_000,
     			      -length => 1_000_000);

     # get all the homologies (a list of Ace::Sequence::Feature objs)
     @homol = $seq->features('Similarity');

     # Get information about the first one
     $feature = $homol[0];
     $type    = $feature->type;
     $subtype = $feature->subtype;
     $start   = $feature->start;
     $end     = $feature->end;
     $score   = $feature->score;

     # Follow the target
     $target  = $feature->info;

     # print the target's start and end positions
     print $target->start,'-',$target->end, "\n";

DESCRIPTION
===========

   *Ace::Sequence::Feature* is a subclass of Ace/Sequence/Feature,
specialized for returning information about
particular features in a GFF format feature table.

OBJECT CREATION
===============

   You will not ordinarily create an *Ace::Sequence::Feature* object
directly.  Instead, objects will be created in response to a feature()
call to an *Ace::Sequence* object.  If you wish to create an
*Ace::Sequence::Feature* object directly, please consult the source code
for the new() method.

OBJECT METHODS
==============

   Most methods are inherited from *Ace::Sequence*.  The following methods
are also supported:

seqname()
          $object = $feature->seqname;

     Return the ACeDB Sequence object that this feature is attached to.
     The return value is an *Ace::Object* of the Sequence class.  This
     corresponds to the first field of the GFF format and does not
     necessarily correspond to the *Ace::Sequence* object from which the
     feature was obtained (use source_seq() for that).

source()
method()
subtype()
          $source = $feature->source;

     These three methods are all synonyms for the same thing.  They return
     the second field of the GFF format, called "source" in the
     documentation.  This is usually the method or algorithm used to
     predict the feature, such as "GeneFinder" or "tRNA" scan.  To avoid
     ambiguity and enhance readability, the method() and subtype() synonyms
     are also recognized.

feature()
type()
          $type = $feature->type;

     These two methods are also synonyms.  They return the type of the
     feature, such as "exon", "similarity" or "Predicted_gene".  In the GFF
     documentation this is called the "feature" field.  For readability,
     you can also use type() to fetch the field.

abs_start()
          $start = $feature->abs_start;

     This method returns the absolute start of the feature within the
     sequence segment indicated by seqname().  As in the *Ace::Sequence*
     method, use start() to obtain the start of the feature relative to its
     source.

abs_start()
          $start = $feature->abs_start;

     This method returns the start of the feature relative to the sequence
     segment indicated by seqname().  As in the *Ace::Sequence* method,
     you will more usually use the inherited start() method to obtain the
     start of the feature relative to its source sequence (the
     *Ace::Sequence* from which it was originally derived).

abs_end()
          $start = $feature->abs_end;

     This method returns the end of the feature relative to the sequence
     segment indicated by seqname().  As in the *Ace::Sequence* method,
     you will more usually use the inherited end() method to obtain the end
     of the feature relative to the *Ace::Sequence* from which it was
     derived.

score()
          $score = $feature->score;

     For features that are associated with a numeric score, such as
     similarities, this returns that value.  For other features, this
     method returns undef.

strand()
          $strand = $feature->strand;

     Returns the strandedness of this feature, either "+1" or "-1".  For
     features that are not stranded, returns 0.

reversed()
          $reversed = $feature->reversed;

     Returns true if the feature is reversed relative to its source
     sequence.

frame()
          $frame = $feature->frame;

     For features that have a frame, such as a predicted coding sequence,
     returns the frame, either 0, 1 or 2.  For other features, returns
     undef.

group()
info()
target()
          $info = $feature->info;

     These methods (synonyms for one another) return an Ace::Object
     containing other information about the feature derived from the 8th
     field of the GFF format, the so-called "group" field.  The type of the
     Ace::Object is dependent on the nature of the feature.  The
     possibilities are shown in the table below:

          Feature Type           Value of Group Field
          ------------            --------------------

          note                   A Text object containing the note.

          similarity             An Ace::Sequence::Homology object containing
                                 the target and its start/stop positions.

          intron                 An Ace::Object containing the gene from
          exon                   which the feature is derived.
          misc_feature

          other                  A Text object containing the group data.

asString()
          $label = $feature->asString;

     Returns a human-readable identifier describing the nature of the
     feature.  The format is:

          $type:$name/$start-$end

     for example:

          exon:ZK154.3/1-67

     This method is also called automatically when the object is treated in
     a string context.

SEE ALSO
========

   See Ace, Ace/Object, Ace/Sequence,
see Ace/Sequence/Homol,
Ace/Sequence/FeatureList, `GFF' in this node

AUTHOR
======

   Lincoln Stein <lstein@cshl.org> with extensive help from Jean
Thierry-Mieg <mieg@kaa.crbm.cnrs-mop.fr>

   Copyright (c) 1999, Lincoln D. Stein

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

Lightweight Access to Features
******************************

NAME
====

   Ace::Sequence::FeatureList - Lightweight Access to Features

SYNOPSIS
========

     # get a megabase from the middle of chromosome I
     $seq = Ace::Sequence->new(-name   => 'CHROMOSOME_I,
                               -db     => $db,
     			      -offset => 3_000_000,
     			      -length => 1_000_000);

     # find out what's there
     $list = $seq->feature_list;

     # Scalar context: count all the features
     $feature_count = $list->types;

     # Array context: list all the feature types
     @feature_types = $list->types;

     # Scalar context, 1 argument.  Count this type
     $gene_cnt = $list->types('Predicted_gene');
     print "There are $gene_cnt genes here.\n";

     # Array context, 1 argument.  Get list of subtypes
     @subtypes = $list->types('Predicted_gene');

     # Two arguments. Count type & subtype
     $genefinder_cnt = $list->types('Predicted_gene','genefinder');

DESCRIPTION
===========

   *Ace::Sequence::FeatureList* is a small class that provides statistical
information about sequence features.  From it you can obtain summary
counts of the features and their types within a selected region.

OBJECT CREATION
===============

   You will not ordinarily create an *Ace::Sequence::FeatureList* object
directly.  Instead, objects will be created by calling a *Ace::Sequence*
object's feature_list() method.  If you wish to create an
*Ace::Sequence::FeatureList* object directly, please consult the source
code for the new() method.

OBJECT METHODS
==============

   There are only two methods in *Ace::Sequence::FeatureList*.

type()
     This method has five distinct behaviors, depending on its context and
     the number of parameters.  Usage should be intuitive

          Context       Arguments       Behavior
          -------       ---------       --------

          scalar         -none-         total count of features in list
          array          -none-         list feature types (e.g. "exon")
          scalar          type          count features of this type
          array           type          list subtypes of this type
          -any-       type,subtype      count features of this type & subtype

     For example, this code fragment will count the number of exons present
     on the list:

          $exon_count = $list->type('exon');

     This code fragment will count the number of exons found by
     "genefinder":

          $predicted_exon_count = $list->type('exon','genefinder');

     This code fragment will print out all subtypes of "exon" and their
     counts:

          for my $subtype ($list->type('exon')) {
              print $subtype,"\t",$list->type('exon',$subtype),"\n";
          }

asString()
          print $list->asString;

     This dumps the list out in tab-delimited format.  The order of columns
     is type, subtype, count.

SEE ALSO
========

   See Ace, Ace/Object, Ace/Sequence,
see Ace/Sequence/Feature, `GFF' in
this node

AUTHOR
======

   Lincoln Stein <lstein@w3.org> with extensive help from Jean
Thierry-Mieg <mieg@kaa.crbm.cnrs-mop.fr>

   Copyright (c) 1999, Lincoln D. Stein

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

Gapped alignment object
***********************

NAME
====

   Ace::Sequence::GappedAlignment - Gapped alignment object

SYNOPSIS
========

     # open database connection and get an Ace::Sequence object
     use Ace::Sequence;

     # get a megabase from the middle of chromosome I
     $seq = Ace::Sequence->new(-name   => 'CHROMOSOME_I,
                               -db     => $db,
     			      -offset => 3_000_000,
     			      -length => 1_000_000);

     # get all the gapped alignments
     @alignments = $seq->alignments('EST_GENOME');

     # get the aligned segments from the first one
     @segs = $alignments[0]->segments;

     # get the position of the first aligned segment on the
     # source sequence:
     ($s_start,$s_end) = ($segs[0]->start,$segs[0]->end);

     # get the target position for the first aligned segment
     ($t_start,$t_end) = ($segs[0]->target->start,$segs[0]->target->end);

DESCRIPTION
===========

   Ace::Sequence::GappedAlignment is a subclass of Ace::Sequence::Feature.
It inherits all the methods of Ace::Sequence::Feature, but adds the
ability to retrieve the positions of the aligned segments.  Each segment
is an Ace::Sequence::Feature, from which you can retrieve the source and
target coordinates.

OBJECT CREATION
===============

   You will not ordinarily create an *Ace::Sequence::GappedAlignment*
object directly.  Instead, objects will be created in response to a
alignments() call to an *Ace::Sequence* object.

OBJECT METHODS
==============

   Most methods are inherited from *Ace::Sequence::Feature*.  The
following methods are also supported:

segments()
          @segments = $gene->segments;

     Return a list of Ace::Sequence::Feature objects corresponding to
     similar segments.

relative()
          $relative = $gene->relative;
          $gene->relative(1);

     This turns on and off relative coordinates.  By default, the exons and
     intron features will be returned in the coordinate system used by the
     gene.  If relative() is set to a true value, then coordinates will be
     expressed as relative to the start of the gene.  The first exon will
     (usually) be 1.

SEE ALSO
========

   See Ace, Ace/Object, Ace/Sequence,
see Ace/Sequence/Homol,
Ace/Sequence/Feature,
Ace/Sequence/FeatureList, `GFF' in this node

AUTHOR
======

   Lincoln Stein <lstein@cshl.org> with extensive help from Jean
Thierry-Mieg <mieg@kaa.crbm.cnrs-mop.fr>

   Copyright (c) 1999, Lincoln D. Stein

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

Temporary Sequence Homology Class
*********************************

NAME
====

   Ace::Sequence::Homol - Temporary Sequence Homology Class

SYNOPSIS
========

     # Get all similarity features from an Ace::Sequence
     @homol = $seq->features('Similarity');

     # sort by score
     @sorted = sort { $a->score <=> $b->score } @homol;

     # the last one has the highest score
     $best = $sorted[$#sorted];

     # fetch its associated Ace::Sequence::Homol
     $homol = $best->target;

     # print out the sequence name, DNA, start and end
     print $homol->name,' ',$homol->start,'-',$homol->end,"\n";
     print $homol->asDNA;

DESCRIPTION
===========

   *Ace::Sequence::Homol* is a subclass of Ace/Object,
(not Ace/Sequence) which is specialized for returning
information about a DNA or protein homology.  This is a temporary
placeholder for a more sophisticated homology class which will include
support for alignments.

OBJECT CREATION
===============

   You will not ordinarily create an *Ace::Sequence::Homol* object
directly.  Instead, objects will be created in response to an info() or
group() method call on a similarity feature in an *Ace::Sequence::Feature*
object.  If you wish to create an *Ace::Sequence::Homol* object directly,
please consult the source code for the new() method.

OBJECT METHODS
==============

   Most methods are inherited from *Ace::Object*.  The following methods
are also supported:

start()
          $start = $homol->start;

     Returns the start of the area that is similar to the
     *Ace::Sequence::Feature* from which his homology was derived.
     Coordinates are relative to the target homology.

end()
          $end = $homol->end;

     Returns the end of the area that is similar to the
     *Ace::Sequence::Feature* from which his homology was derived.
     Coordinates are relative to the target homology.

asString()
          $label = $homol->asString;

     Returns a human-readable identifier describing the nature of the
     feature.  The format is:

          $name/$start-$end

     for example:

          HUMGEN13/1-67

     This method is also called automatically when the object is treated in
     a string context.

SEE ALSO
========

   See Ace, Ace/Object, Ace/Sequence,
see Ace/Sequence/FeatureList,
Ace/Sequence/Feature, `GFF' in this node

AUTHOR
======

   Lincoln Stein <lstein@w3.org> with extensive help from Jean
Thierry-Mieg <mieg@kaa.crbm.cnrs-mop.fr>

   Copyright (c) 1999, Lincoln D. Stein

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

Combine Feature Tables from Multiple Databases
**********************************************

NAME
====

   Ace::Sequence::Multi - Combine Feature Tables from Multiple Databases

SYNOPSIS
========

     use Ace::Sequence::Multi;

     # open reference database
     $ref = Ace->connect(-host=>'stein.cshl.org',-port=>200009);

     # open some secondary databases
     $db1 = Ace->connect(-host=>'stein.cshl.org',-port=>200010);
     $db2 = Ace->connect(-path=>'/usr/local/acedb/mydata');

     # Make an Ace::Sequence::Multi object
     $seq = Ace::Sequence::Multi->new(-name   => 'CHROMOSOME_I,
                                      -db     => $ref,
     			             -offset => 3_000_000,
     			             -length => 1_000_000);

     # add the secondary databases
     $seq->add_secondary($db1,$db2);

     # get all the homologies (a list of Ace::Sequence::Feature objs)
     @homol = $seq->features('Similarity');

     # Get information about the first one -- goes to the correct db
     $feature = $homol[0];
     $type    = $feature->type;
     $subtype = $feature->subtype;
     $start   = $feature->start;
     $end     = $feature->end;
     $score   = $feature->score;

     # Follow the target
     $target  = $feature->info;

     # print the target's start and end positions
     print $target->start,'-',$target->end, "\n";

DESCRIPTION
===========

   *Ace::Sequence::Multi* transparently combines information stored about
a sequence in a reference database with features tables from any number of
annotation databases.  The resulting object can be used just like an
Ace::Sequence object, except that the features remember their database of
origin and go back to that database for information.

   This class will only work properly if the reference database and all
annotation databases share the same cosmid map.

OBJECT CREATION
===============

   You will use the new() method to create new Ace::Sequence::Multi
objects.  The arguments are identical to the those in the Ace::Sequence
parent class, with the addition of an option *-secondary* argument, which
points to one or more secondary databases from which to fetch annotation
information.

-source
     The sequence source.  This must be an *Ace::Object* of the "Sequence"
     class, or be a sequence-like object containing the SMap tag (see
     below).

-offset
     An offset from the beginning of the source sequence.  The retrieved
     *Ace::Sequence* will begin at this position.  The offset can be any
     positive or negative integer.  Offets are *0-based*.

-length
     The length of the sequence to return.  Either a positive or negative
     integer can be specified.  If a negative length is given, the returned
     sequence will be complemented relative to the source sequence.

-refseq
     The sequence to use to establish the coordinate system for the
     returned sequence.  Normally the source sequence is used to establish
     the coordinate system, but this can be used to override that choice.
     You can provide either an *Ace::Object* or just a sequence name for
     this argument.  The source and reference sequences must share a common
     ancestor, but do not have to be directly related.  An attempt to use a
     disjunct reference sequence, such as one on a different chromosome,
     will fail.

-name
     As an alternative to using an *Ace::Object* with the *-source*
     argument, you may specify a source sequence using *-name* and *-db*.
     The *Ace::Sequence* module will use the provided database accessor to
     fetch a Sequence object with the specified name. new() will return
     undef is no Sequence by this name is known.

-db
     This argument is required if the source sequence is specified by name
     rather than by object reference.  It must be a previously opened
     handle to the reference database.

-secondary
     This argument points to one or more previously-opened annotation
     databases.  You may use a scalar if there is only one annotation
     database.  Otherwise, use an array reference.  You may add and delete
     annotation databases after the object is created by using the
     add_secondary() and delete_secondary() methods.

   If new() is successful, it will create an *Ace::Sequence::Multi* object
and return it.  Otherwise it will return undef and return a descriptive
message in Ace->error().  Certain programming errors, such as a failure to
provide required arguments, cause a fatal error.

OBJECT METHODS
==============

   Most methods are inherited from *Ace::Sequence*.  The following
additional methods are supported:

secondary()
          @databases = $seq->secondary;

     Return a list of the secondary databases currently in use, or an empty
     list if none.

add_secondary()
          $seq->add_secondary($db1,$db2,...)

     Add one or more secondary databases to the list of annotation
     databases.  Duplicate databases will be silently ignored.

delete_secondary()
          $seq->delete_secondary($db1,$db2,...)

     Delete one or more secondary databases from the list of annotation
     databases.  Databases not already in use will be silently ignored.

SEE ALSO
========

   See Ace, Ace/Object, Ace/Sequence,
see Ace/Sequence/Homol,
Ace/Sequence/FeatureList,
Ace/Sequence/Feature, `GFF' in this node

AUTHOR
======

   Lincoln Stein <lstein@w3.org> with extensive help from Jean
Thierry-Mieg <mieg@kaa.crbm.cnrs-mop.fr>

   Copyright (c) 1999, Lincoln D. Stein

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

Simple "Gene" Object
********************

NAME
====

   Ace::Sequence::Transcript - Simple "Gene" Object

SYNOPSIS
========

     # open database connection and get an Ace::Object sequence
     use Ace::Sequence;

     # get a megabase from the middle of chromosome I
     $seq = Ace::Sequence->new(-name   => 'CHROMOSOME_I,
                               -db     => $db,
     			      -offset => 3_000_000,
     			      -length => 1_000_000);

     # get all the transcripts
     @genes = $seq->transcripts;

     # get the exons from the first one
     @exons = $genes[0]->exons;

     # get the introns
     @introns = $genes[0]->introns

     # get the CDSs (NOT IMPLEMENTED YET!)
     @cds = $genes[0]->cds;

DESCRIPTION
===========

   Ace::Sequence::Gene is a subclass of Ace::Sequence::Feature.  It
inherits all the methods of Ace::Sequence::Feature, but adds the ability
to retrieve the annotated introns and exons of the gene.

OBJECT CREATION
===============

   You will not ordinarily create an *Ace::Sequence::Gene* object
directly.  Instead, objects will be created in response to a transcripts()
call to an *Ace::Sequence* object.

OBJECT METHODS
==============

   Most methods are inherited from *Ace::Sequence::Feature*.  The
following methods are also supported:

exons()
          @exons = $gene->exons;

     Return a list of Ace::Sequence::Feature objects corresponding to
     annotated exons.

introns()
          @introns = $gene->introns;

     Return a list of Ace::Sequence::Feature objects corresponding to
     annotated introns.

cds()
          @cds = $gene->cds;

     Return a list of Ace::Sequence::Feature objects corresponding to
     coding sequence.  THIS IS NOT YET IMPLEMENTED.

relative()
          $relative = $gene->relative;
          $gene->relative(1);

     This turns on and off relative coordinates.  By default, the exons and
     intron features will be returned in the coordinate system used by the
     gene.  If relative() is set to a true value, then coordinates will be
     expressed as relative to the start of the gene.  The first exon will
     (usually) be 1.

SEE ALSO
========

   See Ace, Ace/Object, Ace/Sequence,
see Ace/Sequence/Homol,
Ace/Sequence/Feature,
Ace/Sequence/FeatureList, `GFF' in this node

AUTHOR
======

   Lincoln Stein <lstein@cshl.org> with extensive help from Jean
Thierry-Mieg <mieg@kaa.crbm.cnrs-mop.fr>

   Copyright (c) 1999, Lincoln D. Stein

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

Abstract class for using AddressBooks
*************************************

NAME
====

   AddressBook - Abstract class for using AddressBooks

SYNOPSIS
========

     use AddressBook;
     $a = AddressBook->new(source => "LDAP:localhost");
     $b = AddressBook->new(source => "DBI:CSV:f_dir=/tmp/data");
     $c = AddressBook->new(source => "PDB");

     $a->search(name => "hersh");
     $entry = $a->read;
     $b->add($entry);

     $entry = AddressBook::Entry->new(attr=>{name => "dleigh"});
     $c->write($entry);

     AddressBook::sync(master=>$a,slave=>$c);

DESCRIPTION
===========

   AddressBook provides a unified interface to access various databases
for keeping track of contacts.  Included with this module are several
backends:

     AddressBook::DB::LDAP
     AddressBook::DB::LDIF
     AddressBook::DB::DBI
     AddressBook::DB::PDB
     AddressBook::DB::Text
     AddressBook::DB::HTML

   More will be added in the future.

new 	    Create a new AddressBook object.
-----------------------------------------

     AddressBook->new(source=$source,\%args)

   See the appropriate backend documentation for constructor details.

sync
----

     AddressBook::sync(master=>$master_db, slave=>$slave_db)
     AddressBook::sync(master=>$master_db, slave=>$slave_db,debug=>1)

   Synchronizes the "master" and "slave" databases.  The "master" database
type must be one that supports random-access methods.  The "slave"
database type must be one that supports sequential-access methods.

   When the 'debug' option is true, debug messages will be printed to
stdout.  The msg_function paramater, if included, should be a subroutine
reference which will be called with a status message is the argument.

  1. For each record in the slave, look for a corresponding record in the
     master, using the key_fields of each.

          If no match is found, the entry is added to the master.

          If multiple matches are found, an error occurrs.

          If one match is found, then:

               If the records match, nothing is done.

               If the records do not match, then:

                    If the slave record's timestamp is newer, the master's
                    entry is merged (see below) with the slave entry's
                    data.

                    If the master record's timestamp is newer, nothing is
                    done.

  2. The slave database is truncated.

  3. Each record of the master is added to the slave

        The 'merging' of the master and slave entries involves taking each
attribute in the slave's entry and replacing the corresponding attribute
in the master's entry.  Note that attributes that are deleted only on the
slave are therefore effectively ignored during synchronization.

   Similarly, deletions made on the slave database are effectively ignored
during synchronization.

search
------

     $abook->search(attr=>\%filter);
     while ($entry=$abook->read) {
       print $entry->dump;
     }

   \%filter is a list of cannonical attribute/value pairs.

read
----

     $entry=$abook->read;

   Returns an AddressBook::Entry object

update
------

     $abook->update(filter=>\%filter,entry=>$entry)

   \%filter is a list of cannonical attriute/value pairs used to identify
the entry to be updated.

   $entry is an AddressBook::Entry object

add
---

     $abook->add($entry)

   $entry is an AddressBook::Entry object

delete
------

     $abook->delete($entry)

   $entry is an AddressBook::Entry object

truncate
--------

     $abook->truncate

   Removes all records from the database.

get_attribute_names
-------------------

     @names = $abook->get_attribute_names;

   Returns a list of valid backend-specific attribute names

get_cannonical_attribute_names
------------------------------

     @names = $abook->get_cannonical_attribute_names;

   Returns a list of valid cannonical attribute names

AUTHOR
======

   Mark A. Hershberger, <mah@everybody.org> David L. Leigh,
<dleigh@sameasiteverwas.net>

SEE ALSO
========

     The perl-abook home page at http://perl-abook.sourceforge.net

   See AddressBook/Config, AddressBook/Entry,

   See AddressBook/DB/LDAP,
AddressBook/DB/LDIF, AddressBook/DB/DBI,
see AddressBook/DB/PDB,
AddressBook/DB/Text, AddressBook/DB/HTML,

AddressBook configuration object
********************************

NAME
====

   AddressBook::Config - AddressBook configuration object

SYNOPSIS
========

   The AddressBook::Config object contains the list of cannonical
attribute names, their respective backend database equivalents, attribute
metadata, and backend database attributes.

     $config = AddressBook::Config->new(config_file=>$filename);

   AddressBook::Config looks for a configuration file in
/etc/AddressBook.conf if no config_file parameter is present.

DESCRIPTION
===========

   Configuration is read from an XML configuration file which follows this
DTD:

     <?xml version="1.0"?>
     <!DOCTYPE AddressBook_config [
       <!ELEMENT fields (field)>
       <!ELEMENT field  (db)>
       <!ELEMENT db (EMPTY)>
       <!ELEMENT databases (LDAP,LDIF,DBI,PDB,Text,HTML)>
       <!ELEMENT LDAP (EMPTY)>
       <!ELEMENT LDIF (EMPTY)>
       <!ELEMENT DBI (EMPTY)>
       <!ELEMENT PDB (EMPTY)>
       <!ELEMENT Text (EMPTY)>
       <!ELEMENT HTML (EMPTY)>

     <!ATTLIST field 	name 		CDATA 	#REQUIRED
                   	order 		CDATA 	#IMPLIED
                   	type 		(text|textblock|phone|email|url|lurl|boolean) #IMPLIED
                   	values 		CDATA 	#IMPLIED
                   	non_multiple 	CDATA 	#IMPLIED
                   	read_only 	CDATA 	#IMPLIED
                   	calculate 	CDATA 	#IMPLIED
                   	calc_order 	CDATA 	#IMPLIED>

     <!ATTLIST db 	name 		CDATA 	#REQUIRED
                 	type 		CDATA 	#REQUIRED
                 	order 		CDATA 	#IMPLIED
                 	calculate 	CDATA 	#IMPLIED
                 	calc_order 	CDATA 	#IMPLIED>

     <!ATTLIST LDAP      key_fields 	CDATA 	#IMPLIED
     			hostname        CDATA   #IMPLIED
                      	objectclass 	CDATA 	#IMPLIED
                      	base 		CDATA 	#IMPLIED
                      	dn_calculate 	CDATA 	#IMPLIED
                      	username 	CDATA 	#IMPLIED
                      	password 	CDATA 	#IMPLIED>

     <!ATTLIST LDIF      key_fields 	CDATA 	#IMPLIED
     			filename        CDATA   #IMPLIED
                      	objectclass 	CDATA 	#IMPLIED
                      	base 		CDATA 	#IMPLIED
                      	dn_calculate 	CDATA 	#IMPLIED>

     <!ATTLIST DBI       key_fields 	CDATA 	#IMPLIED
                      	table 		CDATA 	#IMPLIED
     			dsn             CDATA   #IMPLIED>

     <!ATTLIST PDB       write_format 	CDATA 	#IMPLIED
     			intra_attr_sep  CDATA   #IMPLIED
                      	form_format 	CDATA 	#IMPLIED>

     <!ATTLIST HTML      key_fields 	CDATA 	#IMPLIED
     			filename        CDATA   #IMPLIED
                      	phone_display 	CDATA 	#IMPLIED>
       ]>

   For example,

     <AddressBook_config>
       <fields>
         <field name="firstname" type="text" order="1">
           <db type="LDAP" name="givenname" />
           <db type="HTML" name="First Name" order="2" />
         </field>
         <field name="lastname" type="text" order="2">
           <db type="LDAP" name="sn" />
           <db type="HTML" name="Last Name" order="1" />
         </field>
         <field name="fullname" type="text" order="3"
                calculate="$firstname . ' ' . $lastname">
           <db type="LDAP" name="cn" />
           <db type="HTML" name="Full Name" />
         </field>
       </fields>
       <databases>
         <LDAP objectclass="inetOrgPerson"
               base="o=abook"
               dn_calculate="'cn='.$cn"
               username="cn=Manager,o=abook"
               password="secret"
               key_fields="cn"
         />
       </databases>
     </AddressBook_config>

   This defines three attributes with cannonical names "firstname",
"lastname", and "fullname".  These are accessed in the LDAP backend
context as "givenname", "sn" and "cn", and in the HTML backend context as
"First Name", "Last Name" and "Full Name" respectively.

   The default attribute ordering  is "firstname", "lastname", "fullname",
however the HTML backend overrides this and in that context attributes are
ordered: "lastname", "firstname", "fullname".   All other meta-attributes
may be similarily overriden by specific backends

   "fullname" is a calculated attribute.  Calculation strings may
reference the names of other attributes by "$<attr_name>".

   Backend databases may also be named and then tied to a source type by
using the 'driver' attribute.  This technique is useful for defining
multiple backends of the same type.  For example,

     <AddressBook_config>
       <fields>
         <field name="firstname" >
           <db type="ldap_server_1" name="givenname" />
           <db type="ldap_server_2" name="givenname" />
         </field>
         <field name="lastname" >
           <db type="ldap_server_1" name="sn" />
           <db type="ldap_server_2" name="sn" />
         </field>
       </fields>
       <databases>
         <ldap_server_1 driver="LDAP"
                        hostname="server_1"
                        objectclass="inetOrgPerson"
                        base="o=abook"
                        dn_calculate="'cn='.$cn"
                        username="cn=Manager,o=abook"
                        password="secret"
                        key_fields="cn"
         />
         <ldap_server_2 driver="LDAP"
                        hostname="server_2"
                        objectclass="inetOrgPerson"
                        base="o=abook"
                        dn_calculate="'cn='.$cn"
                        username="cn=Manager,o=abook"
                        password="secret"
                        key_fields="cn"
         />
       </databases>
     </AddressBook_config>

   See the various backend man pages for information on the <database>
configuration attributes.  See also the sample configuration files in the
'examples' directory.

getMeta      %meta = %{$config->getMeta(attr=>$attr)}   %meta = %{$config->getMeta(attr=>$attr,db=>$db)}
--------------------------------------------------------------------------------------------------------

   Returns an attribute metadata hash

AUTHOR
======

   David L. Leigh, <dleigh@sameasiteverwas.net>

SEE ALSO
========

   See AddressBook, AddressBook/Entry,

Perl extension for reading and writing bbdb files
*************************************************

NAME
====

   bbdb - Perl extension for reading and writing bbdb files

SYNOPSIS
========

     use BBDB;
     my $x = new BBDB();
     $x->decode($string);
     my $str = $x->encode();
     # At this point, subject to the BUGS below
     # $str is the same as $string

     my $allR = BBDB::simple('/home/henry/.bbdb');
     map { print $_->part('first')} @$allR;   # print out all the first names

DESCRIPTION
===========

Data Format
-----------

   The following is the data layout for a BBDB record.  I have created a
sample record with my own data.  Each field is just separated by a space.
I have added comments to the right

     ["Henry"                             The first name - a string
     "Laxen"                              The last name - a string
     ("Henry, Enrique")                   Also Known As - comma separated list
     "Elegant Solution"                   Business name - a string
     (["home" 415 789 1159 0]             Phone number field - US style
      ["fax" 415 789 1156 0]              Phone number field - US style
      ["mazatlan" "011-5269-164195"]      Phone number field - International style
     )
     (["mailing" "PMB 141"                Address field - There are 3 fields for
       "524 San Anselmo Ave." ""           for the street address, then one each
       "San Anselmo" "CA" (94960 2614)"     for City, State, and Zip Code
      ]
      ["mazatlan" "Reino de Navarra #757" Address field - Note that there is no
       "Frac. El Cid" ""                   field for Country.  That is unfortunate
       "Mazatlan" "Sinaloa, Mexico"        The zip code field is quoted if its
       ("CP" "82110")                      not an integer
      ]
      )
     ("nadine.and.henry@pobox.com"        The net addresses - a list of strings
      "maztravel@maztravel.com")
     ((creation-date . "1999-09-02")      The notes field - a list of alists
      (timestamp . "1999-10-17")
      (notes . "Always split aces and eights")
      (birthday "6/15")
     )
     nil                                  The cache vector - always nil
     ]

   After this is decoded it will be returned as a reference to a BBDB
object.  The internal structure of the BBDB object mimics the lisp
structure of the BBDB string.  It consists of a reference to an array with
9 elements The Data::Dumper output of the above BBDB string would just
replaces all of the ()s with []s.  It can be accessed by using the
`$bbdb-'part('all')> method.

Methods
-------

new()
     called whenever you want to create a new BBDB object.         my
     $bbdb = new BBDB();

part(name [value])
     Called to get or set all or part of a BBDB object.  The parts of the
     object are:

          all first last aka company phone address net notes

     any other value in the name argument results in death.  Some of these
     parts, namely phone, address, net, and notes have an internal
     structure and are returned as references to arrays.  The others are
     returned just as strings.  The optional second argument sets the part
     of this BBDB object to the value you provided.  There is no
     consistency checking at this point, so be sure the value you are
     setting this to is correct.

          my $first = $bbdb->part('first');    # get the value of the first field
          $bbdb->part('last','Laxen');         # set the value of the last field
          my $everything = $bbdb->part('all'); # get the whole record

BBDB::simple(file_name,[array_ref_of_bbdb])
     This is a "simple" interface for reading or writing an entire BBDB
     file. If called with one argument, it returns a reference to an array
     of BBDB objects.  Each object contains the data from the file.  Thus
     the number of BBDB entries equals `scalar(@$bbdb)' if you use:

          $bbdb = BBDB::simple('/home/henry/.bbdb');

     If called with two arguments, the first is the filename to create, and
     the second is a reference to an array of BBDB objects, such as was
     returned in the one argument version.  The objects are scanned for
     unique user defined fields, which are written out as the 2nd line in
     the BBDB file, and then the individual records are written out.

decode(string)
     Takes a string as written in a BBDB file of a single BBDB record and
     decodes it into its PERL representation.  Returns undef if it
     couldn't decode the record for some reason, otherwise returns true.

          $bbdb->decode($entry);

encode()
     This is the inverse of decode.  Takes an internal PERL version of a
     BBDB records and returns a string which is a lisp version of the data
     that BBDB understands.  There are some ambiguities, noted in BUGS
     below.

          my $string = $bbdb->encode();

Debugging
---------

   If you find that some records in your BBDB file are failing to be
recognized, trying setting `$BBDB::debug = 1;' to turn on debugging.  We
will then print out to STDERR the first field of the record that we were
unable to recognize.  Very handy for complicated BBDB records.

AUTHOR
======

   Henry Laxen <nadine.and.henry@pobox.com> http://www.maztravel.com/perl

SEE ALSO
========

   BBDB texinfo documentation

BUGS
====

   Phone numbers and zip codes may be converted from strings to integers
if they are decoded and encoded.  This should not affect the operation of
BBDB.  Also a null last name is converted from "" to nil, which also
doesn't hurt anything.

   You might ask why I use arrays instead of hashes to encode the data in
the BBDB file.  The answer is that order matters in the bbdb file, and
order isn't well defined in hashes.  Also, if you use hashes, at least in
the simple minded way, you can easily find yourself with legitimate
duplicate keys.

Backend for AddressBook to use in databases
*******************************************

NAME
====

   AddressBook::DB::DBI - Backend for AddressBook to use in databases

SYNOPSIS
========

     use AddressBook;
     $a = AddressBook->new(source => "DBI:CSV:f_dir=/tmp/csv",
     			table=>"a_csv",
     			);

DESCRIPTION
===========

   The DBI perl library module is required in order to use this package.

   AddressBook::DB::DBI supports both sequential and random access backend
database methods.

   The DBI backend has so far only been tested against the CSV database
driver.

   AddressBook::DB::DBI behavior can be modified using the following
options:

table
     Required parameter

key_fields
     A list of DBI field names (not cannonical names) which can be used to
     uniquely identify a database record.

dsn
     See constructor details below

new
---

   The database driver and driver arguments may be specified in in the
constructor in one of two ways:

  1. As part of the "source" parameter, for example:

          $a = AddressBook->new(source => "DBI:CSV:f_dir=/tmp/csv",
          			table=>"a_csv",
          			);

  2. In a "dsn" parameter, for example:

          $a = AddressBook->new(source => "DBI",
          			dsn=>"CSV:f_dir=/tmp/csv",
          			table=>"a_csv",
          			);

     Like all AddressBook database constructor parameters, the "dsn" and
     "table" may also be specified in the configuration file.

Timestamps
----------

   For syncronization purposes, all records are timestamped depending on
the database driver type:

CSV
     All records are timestamped with the modification data of the CSV
     file.

AUTHOR
======

   Mark A. Hershberger, <mah@everybody.org> David L. Leigh,
<dleigh@sameasiteverwas.net>

SEE ALSO
========

   See AddressBook, AddressBook/Config,
see AddressBook/Entry.

   DBI DBD::CSV

Backend for AddressBook to print entries in HTML format
*******************************************************

NAME
====

   AddressBook::DB::HTML - Backend for AddressBook to print entries in
HTML format

SYNOPSIS
========

     use AddressBook;
     $a = AddressBook->new(source => "HTML");
     $a->write($entry);

DESCRIPTION
===========

   AddressBook::DB::HTML currently supports only the sequential write
method.

   Behavior can be modified using the following options:

write_format
     The write_format string is eval'd to determine how the entry is
     written.  The default write_format string is:

          'table(Tr([map{td(["$_:",$attributes{$_}])} keys %attributes]))'

     This displays the entry in a table with attribute names on the left
     and values on the right.  As can be seen, CGI.pm tag-generating
     functions can be used in format strings. The "%attributes" hash is
     available for use.  The keys of %attributes are HTML backend
     attribute names, and the values are the corresponding attribute
     values.  Specific attributes can also be referenced by name using a
     scalar with the same name as the attribute.   For example,

          'Name: $Name'

     Assuming that "Name" is a valid HTML attribute, this format string
     will display entry names.  This is equivalent to:

          'Name: $attributes{Name}'

     The HTML backend recognizes the string "keys %attributes", and
     substitues an expression which ensures that the "order"
     meta-attribute is obeyed.

form_format
     The form_format string is eval'd to construct an html entry form.
     The default form_format string is:

          table(Tr({-valign=>"TOP"},[map{td([$_,$attributes{$_}])} keys %attributes]))

     Which generates a table of fields with labels on the left.  The input
     type is based on the attribute type, eg. "text" attributes appear as
     text input fields, "boolean" attributes appear as checkbox inputs,
     etc...  The default values of the entry fields are the current values
     of the entry's attributes.

intra_attr_sep
     The string to use in joining multiple instances of the same
     attribute.  The default is "<br>"

AUTHOR
======

   Mark A. Hershberger, <mah@everybody.org> David L. Leigh,
<dleigh@sameasiteverwas.net>

SEE ALSO
========

   See AddressBook, AddressBook/Config,
see AddressBook/Entry.

Backend for AddressBook to use LDAP.
************************************

NAME
====

   AddressBook::DB::LDAP - Backend for AddressBook to use LDAP.

SYNOPSIS
========

     use AddressBook;
     $a = AddressBook->new(source => "LDAP:hostname/ou=People,dc=example,dc=com",
                           username => "user", password => "pass");
     $a->add($entry) || die $a->code;

DESCRIPTION
===========

   The Net::LDAP library module is required in order to use this package.

   AddressBook::DB::LDAP supports random access backend database methods.

   Behavior can be modified using the following options:

key_fields
     A list of LDAP attribute names (not cannonical names) which can be
     used to uniquely identify an entry.

hostname
     The LDAP host to which to connect.

base
     The base for LDAP queries.

objectclass
     The objectclass for AddressBook entries.

username
     An LDAP dn to use for accessing the server.

password
dn_calculate
     A perl expression which, when eval'd returns a valid LDAP "dn"
     (omitting the "base" part of the dn).  Other attributes may be
     referenced as "$<attr>".

     For example, if LDAP entries have a dn like: "cn=John
     Doe,mail=jdoe@mail.com", then use the following:

          dn_calculate="'cn=' . $cn . ',mail=' . $mail"

   Any of these options may be specified in the constructor, or in the
configuration file.

new
---

     $a = AddressBook->new(source => "LDAP");
     $a = AddressBook->new(source => "LDAP:localhost/ou=People,dc=example,dc=com");
     $a = AddressBook->new(source => "LDAP",
     			hostname=>"localhost",
     			base=>"o=test"
     			);

   Any or all options may be specified in the constructor, or in the
configuration file.

Timestamps
----------

   For syncronization purposes, all records are timestamped using the
"modifytimestamp" LDAP attribute.  If the record has no "modifytimestamp",
"createtimestamp" is used.  If there is no "createtimestamp", the current
time is used.

AUTHOR
======

   Mark A. Hershberger, <mah@everybody.org> David L. Leigh,
<dleigh@sameasiteverwas.net>

SEE ALSO
========

   See AddressBook, AddressBook/Config,
see AddressBook/Entry.

   Net::LDAP

Backend for AddressBook to use LDIF files.
******************************************

NAME
====

   AddressBook::DB::LDIF - Backend for AddressBook to use LDIF files.

SYNOPSIS
========

     use AddressBook;
     $a = AddressBook->new(source => "LDIF",
     			filename => "/tmp/ldif")

DESCRIPTION
===========

   AddressBook::DB::LDIF supports sequential backend database methods.

   AddressBook::DB::LDIF behavior can be modified using the following
options:

key_fields
     A list of LDIF attribute names (not cannonical names) which can be
     used to uniquely identify an entry.

base
     The LDAP base for all entries

objectclass
     The LDAP objectclass for entries

dn_calculate
     A perl expression which, when eval'd returns a valid LDAP "dn"
     (omitting the "base" part of the dn).  Other attributes may be
     referenced as "$<attr>".

     For example, if LDIF entries have a dn like: "cn=John
     Doe,mail=jdoe@mail.com", then use the following:

          dn_calculate="'cn=' . $cn . ',mail=' . $mail"

   Any of these options can be specified in the constructor, or in the
configuration file.

new
---

   The LDIF file is specified using the "filename" parameter:

     $a = AddressBook->new(source => "LDIF",
     			filename => "/tmp/ldif")

   The filename may also be specified in the configuration file.

Timestamps
----------

   For syncronization purposes, all records are timestamped with the
modification date of the LDIF file.

AUTHOR
======

   David L. Leigh, <dleigh@sameasiteverwas.net>

SEE ALSO
========

   See AddressBook, AddressBook/Config,
see AddressBook/Entry.

   Net::LDAP

Backend for AddressBook to use PDB (PalmOS) Databases.
******************************************************

NAME
====

   AddressBook::DB::PDB - Backend for AddressBook to use PDB (PalmOS)
Databases.

SYNOPSIS
========

     use AddressBook;
     $a = AddressBook->new(source => "PDB",port=>"/dev/pilot");
     $b = AddressBook->new(source => "PDB",pdb=>$pdb);
     $c = AddressBook->new(source => "PDB",dlp=>$dlp);

DESCRIPTION
===========

   The PDA::Pilot library module is required in order to use this package.
PDA::Pilot is available as part of the pilot-link distribution, which is
available at http://www.gnu-designs.com/pilot-link

   AddressBook::DB::PDB supports sequential backend database methods.
AddressBook::DB::PDB behavior can be modified using the following options:

key_fields
     A list of PDB field names (not cannonical names) which can be used to
     uniquely identify a database record.  Ideally the "id" field of PDB
     records would be used here, but currently it is not.  "Name,First
     name" is recommended.

phone_display
     A perl statment which, when eval'd, returns a comma-delimited list of
     "phone labels".  Valid phone labels are:
     Work,Home,Fax,Other,E-Mail,Main,Pager,Mobile.  The result of the
     eval'd phone_display will be used to determine which phone label is
     default shown in the PalmOS address list.  The first label in the
     comma-delimited list is used unless the record has no value for that
     label, in which case the second label is used unless it also has no
     value, in which case the third is used, and so on....

     In the phone_display string, other attributes may be referenced as
     "$<attr>".

     For example, if you want the priority of default phone lables to be
     "Work,Home,E-Mail" for all records in the "Business" category, and
     the priority to be "Home,Work,E-Mail" for all records in all other
     categories, you could use the following:

          phone_display = "($category eq 'Business')
                           ? 'Work,Home,E-Mail'
                           : 'Home,Work,E-Mail'"

intra_attr_sep_char
     The character to use when joining multi-valued fields.  The default
     is ' & '.

   Any of these options can be specified in the constructor, or in the
configuration file.

new
---

     $a = AddressBook->new(source => "PDB");
     $a = AddressBook->new(source => "PDB",
                           port => "/dev/pilot");

   If a "pdb" parameter is supplied, it will be used as a reference to an
already created PDA::Pilot::DLP::DBPtr object.  Otherwise, if a "port" is
supplied, the user will be prompted to press the hotsync button to
establish the connection.

Timestamps
----------

   For syncronization purposes, all records which have the "modified" flag
set are timestamped with the current time.  All records with have the
"modified" flag unset are timestamped with "0" (very, very old).

Deleted Records
===============

   PDB records which have the "deleted" flag set are removed as part of
the initialization process.  The "archive" flag is ignored.

Categories
==========

   For convienience, a record's category is treated like any other
attribute.  New categories are created as necessary.  Moving a record to a
new category will achieve the expected result during synchronization.
However, because renaming a category does not cause affected records to be
marked as "modified", category renaming operations will be lost during
synchronization.

AUTHOR
======

   David L. Leigh, <dleigh@sameasiteverwas.net>

SEE ALSO
========

   See AddressBook, AddressBook/Config,
see AddressBook/Entry.

   PDA::Pilot

Backend for AddressBook to print entries in a simple text format
****************************************************************

NAME
====

   AddressBook::DB::Text - Backend for AddressBook to print entries in a
simple text format

SYNOPSIS
========

     use AddressBook;
     $a = AddressBook->new(source => "Text",filename=>"/tmp/abook.text");
     $a->write($entry);

DESCRIPTION
===========

   AddressBook::DB::Text currently supports only the sequential write
method.

new
---

     $a = AddressBook->new(source => "Text");
     $a = AddressBook->new(source => "Text",filename => "/tmp/abook.text");

   If no filename parameter is specified in the constructor, or in the
configuration file, STDOUT is used.

AUTHOR
======

   Mark A. Hershberger, <mah@everybody.org> David L. Leigh,
<dleigh@sameasiteverwas.net>

SEE ALSO
========

   See AddressBook, AddressBook/Config,
see AddressBook/Entry.

An entry in the AddressBook
***************************

NAME
====

   AddressBook::Entry - An entry in the AddressBook

SYNOPSIS
========

   An AddressBook::Entry object contains an addressbook entry's attributes,
attribute metadata, and information about how to translate the attributes
between different backend databases.  An Entry's attributes can be
accessed  using either cannonical attribute names, or database-specific
names.

DESCRIPTION
===========

   The following examples assume  a configuration file which maps the
cannonical attribute named "lastname" to the ldap attribute named "sn" and
the cannonical attribute named "firstname" to the ldap attribute named
"givenname".  For example,

     <field name="lastname">
       <db type="LDAP" name="sn">
     </field>
     <field name="firstname">
       <db type="LDAP" name="givenname">
     </field>

   Each of the following pairs of commands will give the same result:

   $entry=AddressBook::Entry->new(attr=> {
  lastname=>Doe,                                    firstname => John
                                   });
$entry=AddressBook::Entry->new(db=>LDAP, 				 attr=>{
                 sn=>Doe,                                    givenname =>
John                                         });

     $entry->add(attr=>{lastname=>Doe,firstname=>John})
     $entry->add(attr=>{sn=Doe,givenname=John},db=>LDAP)

     $entry->replace(attr=>{firstname=>Jane})
     $entry->replace(attr=>{givenname=>Jane},db=>LDAP)

     $entry->delete(attrs=>[firstname,lastname])
     $entry->delete(attrs=>[givenname,sn],db=>LDAP)

   Reading and writing an entry from a backend database:

     $db = AddressBook->new(source=>LDAP);
     $entry = $db->read;
     $db->write($entry);

   Generating values in calculated fields:

   $entry->calculate;

   Comparing entries:

     AddressBook::Entry::Compare($entry1,$entry2);

   Dumping an entry:

     $entry->dump;

   Note: Each attribute contains a reference to an array of values.

new
---

     $entry=AddressBook->new();
     $entry=AddressBook::Entry->new(attr=>\%attr);
     $entry=AddressBook::Entry->new(attr=>\%attr,db=>$db)

   Create and optionally load an entry object.

   All of the following parameters are optional:

%attr
     An optional hash containing the attributes to add to the entry.  The
     attribute values may be scalars or array references.

$config
     An AddressBook::Config reference.  If supplied, this configuration
     will be used and any  $config_file paramater is ignored.

$config_file
     The configuration file to use instead of the default
     (/etc/AddressBook.conf).

$db
     Can be used to specify that the keys of %attr are those for a
     specific backend.

add
---

     $entry->add(attr=>\%attr);
     $entry->add(attr=>\%attr,db=>$db);

   Adds attributes to the entry object.  New data is added to attributes
which already exist

%attr
     Required hash containing the attributes to add to the entry.  The
     attribute values may be specified as scalars or array references.

$db
     Can be used to specify that the keys of %attr are those for a
     specific backend.

replace
-------

     $entry->replace(attr=>\%attr);
     $entry->replace(attr=>\%attr,db=>$db);

   Adds attributes to the entry object.  New data is added to attributes
which already exist

%attr
     Required hash containing the attributes to add to the entry.  The
     attribute values may be specified as scalars or array references.

$db
     Can be used to specify that the keys of %attr are those for a
     specific backend.

delete
------

     $entry->delete(attrs=>\@attrs)
     $entry->delete(attrs=>\@attrs,db=>$db)

   Remove attributes from the Entry.

@attrs
     Required array containing the attributes to delete from the entry.

$db
     Can be used to specify that the keys of %attr are those for a
     specific backend.

get
---

     $attr_ref = $entry->get();
     $attr_ref = $entry->get(db=>$db);
     $attr_ref = $entry->get(db=>$db,values_only=>1);

   Get attributes from the Entry.  Returns a hash with cannonical
attribute names as keys.

$values_only
     Unless "values_only" is specified, each value in the result is a hash
     with a "value" key pointing to the attribute value array, and a
     "meta" key pointing to the attribute metadata hash.  If "values_only"
     is specified, each value in the result points to the attribute value
     array.

$db
     Can be used to specify that the keys of %attr are those for a
     specific backend.

calculate
---------

     $entry->calculate

   Computes all calculated attributes.  Does so in the order specified by
the calc_order attribute metadata value.

compare
-------

     AddressBook::Entry::compare($entry1,$entry2)

   Returns true if all attributes in both entries match, false otherwise.

fill
----

     $entry->fill(db=>$db);
     $entry->fill(db=>$db,defaults=>1);

   Ensures that the Entry includes all attributes for a specific backend
database.  New attributes are added with null values.  If the "defaults"
parameter is specified, new attributes are added with values as specified
by the attribute "default" metadata specified in the config file.

chop
----

     $entry->chop

   Removes null valued attributes from an Entry.

dump
----

     print $entry->dump

   Returns the (cannonical) attribute names and values.  Primarily used for
debugging purposes.

AUTHOR
======

   Mark A. Hershberger, <mah@everybody.org> David L. Leigh,
<dleigh@sameasiteverwas.net>

SEE ALSO
========

   See AddressBook, AddressBook/Config,

Perl extension for converting from infix notation to postfix notation.
**********************************************************************

NAME
====

   Affix::Infix2Postfix - Perl extension for converting from infix
notation to postfix notation.

SYNOPSIS
========

     use Affix::Infix2Postfix;

     $inst=Affix::Infix2Postfix->new(
       'ops'=>[
     	  {op=>'+'},
     	  {op=>'-'},
     	  {op=>'*'},
     	  {op=>'/'},
     	  {op=>'-',type=>'unary',trans=>'u-'},
     	  {op=>'func',type=>'unary'},
     	 ],
     	  'grouping'=>[qw( \( \) )],
     	  'func'=>[qw( sin cos exp log )],
     	  'vars'=>[qw( x y z)]
     	 );
     $rc=$inst->translate($str)
     || die "Error in '$str': ".$inst->{ERRSTR}."\n";

DESCRIPTION
===========

   Infix2Postfix as the name suggests converts from infix to postfix
notation. The reason why someone would like to do this is that postfix
notation is generally much easier to do in computers. For example take an
expression like: a+b+c*d. For us humans it's pretty easy to do that
calculation.  But it's actually much better for computers to get a string
of operations such as: a b + c d * +, where the variable names mean put
variable on stack.

AUTHOR
======

   addi@umich.edu

SEE ALSO
========

   perl(1).

the Transportable Agent Perl module
***********************************

NAME
====

   Agent - the Transportable Agent Perl module

SYNOPSIS
========

     use Agent;

     my $a = new Agent( Name => 'path_to_agent.pa', %args );

     $a->run();

DESCRIPTION
===========

   Agent Perl is meant to be a multi-platform interface for writing and
using transportable perl agents.

A Perl Agent
     Is any chunk of Perl code that can accomplish some user-defined
     objective by communicating with other agents, and manipulating any
     data it obtains.

     A Perl Agent consists of a knowledge base (variables), a reasoning
     procedure (code), and access to one or more languages coupled with
     methods of communication.  These languages remain largely undefined,
     or rather, user-defined; support for KQML/KIF is under development.

Developing An Agent
     Note that the developer must devise the reasoning procedure and
     knowledge base described above.  Agent Perl does not place any
     restrictions on what you may do; it only tries to make the 'doing'
     part easier.

     An agent is written as an inheriting sub-class of *Agent*.  Each
     agent's class should be stored in a '.pa' file (perl agent), and must
     contain an `agent_main()' method.  All agents are objects.  See the
     examples for more details, and learn how Agent.pm works so you won't
     step on its toes!

CONVENTIONS
===========

   Arguments to subroutines are passed in hashes unless otherwise noted.

   Capital-a *Agent* refers to `Agent.pm' unless the context is obvious.
Lowercase *agent* refers to an agent.

CONSTRUCTOR
===========

new()
     Creates a new agent object.  You must tell new() where to get the
     agent by passing in one of the following arguments (in a hash):

     *Stored*: The agent stored in a Tom object.

     File: An IO::Handle (or any subclass) file handle from which the
     agent can be read.

     Name: The agent's name.  This prompts new to search @INC and './' for
     the agent's '.pa' source file.

     Code: The agent's source code.

     These are listed in order of precedence.  To handle security issues,
     new() also groks this argument:

     *Compartment*: A Safe Compartment within which the agent will be
     registered, and later executed.  See the Safe pod for details.

     Developers should note that these keywords are reserved.  Any
     additional arguments are passed to the agent being created.

METHODS
=======

store()
     Returns the agent object in stringified form, suitable for network
     transfer or storage.

run()
     Executes the agent.  If the Thread argument is passed and your system
     has Thread.pm, run() tries to execute the agent in an asynchronous
     thread via Thread's async() command (see the Thread pod for more
     details).  Additional arguments are passed to the agent being run.

identity()
     Returns a unique string identifying the agent *in its present state*.

SEE ALSO
========

   `Agent::Message' and `Agent::Transport' for agent developers.

AUTHOR
======

   Steve Purkis <`spurkis@engsoc.carleton.ca'>

COPYRIGHT
=========

   Copyright (c) 1997, 1998 Steve Purkis.  All rights reserved.  This
package is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

THANKS
======

   James Duncan for the Tom module and *many* ideas; the people of the
Perl5-Agents mailing list for their support.

the Transportable Agent Perl module
***********************************

NAME
====

   Agent::Message - the Transportable Agent Perl module

SYNOPSIS
========

     use Agent;

     my $msg = new Agent::Message(
     	Body      => [ 'foo bar', 'baz' ],
     	Transport => TCP,
     	Address   => '127.0.0.1:24368'
     );

     $msg->send;

DESCRIPTION
===========

   This module is meant to standardize agent communications over a number
of different transport mediums (see *Agent::Transport*).

CONSTRUCTOR
===========

new( [%args] )
     new makes a nice new Message object with all the arguments you pass
     it.  It understands the following parameters:

          Body => $body,
               [  Transport => $medium,
          Address => $destination,
          SendNow => $true_false   ]

     This instantiates the class with only one destination (multiple
     destinations are possible - see below).  If SendNow is true, the
     message is dispatched ASAP.

METHODS
=======

$msg->body( [@value] )
     Sets/gets the body of the message.

$msg->add_dest( $transport, $addr1 [, $addr2 ...] )
     Adds the destination address to the list of destinations within said
     medium; adds the medium if need be.

$msg->del_dest( $transport, $addr1 [, $addr2 ...] )
     Removes the destination address from the list of destinations within
     said medium.  If last destination in medium, removes medium also.

$msg->del_transport( $transport )
     Removes the specified transport medium and all of its destinations.

$msg->send( %args )
     Sends the message body in all transport mediums.  Passes `\%args' to
     all transport mediums when sending.  Returns an array of results
     returned by each transport medium the message was sent in.

BUGS
====

   $msg->del_dest and $msg->del_transport don't work; I'm too lazy.

SEE ALSO
========

   `Agent', `Agent::Transport', the example agents.

AUTHOR
======

   Steve Purkis <`spurkis@engsoc.carleton.ca'>

COPYRIGHT
=========

   Copyright (c) 1998 Steve Purkis. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

THANKS
======

   Whoever invented mail.

the Transportable Agent Perl module
***********************************

NAME
====

   Agent::Transport - the Transportable Agent Perl module

SYNOPSIS
========

     use Agent;

     my $t = new Agent::Transport(
     	Medium => $name,
     	Address => $addr
     	...
     );
     ...
     my $data = $t->recv( [%args] );

DESCRIPTION
===========

   This package provides a standard interface to different transport
mediums.  `Agent::Transport' does not contain any transport code itself;
it contains a constructor, and code that autoloads the appropriate
transport methods.

CONSTRUCTOR
===========

new( %args )
     new() must be passed at least a *Medium*.  The *Address* argument is
     strongly recomended (and should be required in most cases), as it's
     best not to let the system make assumptions.  new() decides which
     Transport package to use base upon the `Medium' specified.  `Address'
     is the destination in that medium.  Any other arguments will be
     documented in the Agent::Transport subclasses (such as
     Agent::Transport::TCP).

STANDARD API METHODS
====================

   These methods are implemented in all transport subclasses.

$t->recv()
     recv attempts to retrieve a message (from said address, over said
     transport medium).  Returns the data if called in a scalar context,
     or a list containing ($data, $from_address) if called in an array
     context.  Returns nothing (i.e. sv_null or an empty list) if
     unsuccessful.

$t->transport()
     Returns the transport medium over which the object communicates.

$t->address()
     Returns the primary address at which the object can be reached.

$t->aliases()
     Returns a list of addresses at which the object can be reached.

STANDARD SUBROUTINES
====================

send( %args )
     send too must be passed a *Medium* and an *Address*.  In addition, it
     also needs a Message as either an anonymous array or a reference to an
     array.

valid_address( %args )
     This checks to see if the *Address* provided is valid within the
     *Medium* specified by checking the syntax of the address.  It does
     not check to see whether or not said address exists.  Returns the
     address if successful, or nothing otherwise.

SEE ALSO
========

   See Agent, `Agent::Transport::*' in this node

AUTHOR
======

   Steve Purkis <`spurkis@engsoc.carleton.ca'>

COPYRIGHT
=========

   Copyright (c) 1998 Steve Purkis. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

THANKS
======

   The perl5-agents mailing list.

the Transportable Agent Perl module
***********************************

NAME
====

   Agent::Transport - the Transportable Agent Perl module

SYNOPSIS
========

     use Agent::Transport;

     # for receiving messages:
     $tcp = new Agent::Transport(
     	Medium => 'TCP',
     	Address => '1.2.3.4:1234'
     );

     # for sending:
     use Agent::Message;

     $msg = new Agent::Message(
     	Medium => 'TCP',
     	Body => [ @body ],
     	Address => '1.2.3.4:1234'
     );
     $msg->send;

DESCRIPTION
===========

   This package provides an interface to the TCP[/IP] transport medium for
agent developers to make use of.

ADDRESS FORMAT
==============

This package groks the following standard tcp/ip formats:
          aaa.bbb.ccc.ddd:port
          host.domain:port

CONSTRUCTOR
===========

new( %args )
     If the *Cycle* argument is passed and if new() cannot capture the port
     specified, it will cycle through port numbers until a free port is
     found.  If new is not passed an *Address* at all, it assumes
     '127.0.0.1:24368', and sets *Cycle* to 1.

METHODS & SUBS
==============

   This module contains all of the Agent::Transport standard methods.  Some
non-standard features have also been introduced:

$self->accept( %args )
     This method is analagous to the accept() function call and is
     introduced to allow agent programmers to make full use of
     bi-directional sockets.  It simply opens an incoming connection and
     returns that object, thus allowing you to use a single connection for
     multiple messages (see IO::Socket for details).  Unfortunately,
     you'll have to design your own protocol.

     Passing a 'From' argument as a referenced scalar, causes accept() to
     put *what it thinks* the remote address is into this variable.

$self->alias()
     Returns $self->address() only.  It should really do hostname lookups.

$self->recv( %args )
     Passing a 'From' argument as a referenced scalar, causes recv() to put
     *what it thinks* the remote address is into this variable.  Otherwise,
     recv() functions as described in *Agent::Transport*.

send( %args )
     If you pass send() a 'KeepAlive' argument containing a reference to a
     scalar, it will set this scalar to the remote *socket filehandle*.
     This is meant to be used in conjunction with accept(), and is useful
     if you would like to have an extended conversation with the remote
     host.

NOTES
=====

   This module only binds to a specified address.  If you have multiple
interface addresses (ie: eth0 & eth1), and you want to listen on more than
one, you have to bind each seperately.

SEE ALSO
========

   `Agent' `Agent::Transport'

AUTHOR
======

   Steve Purkis <`spurkis@engsoc.carleton.ca'>

COPYRIGHT
=========

   Copyright (c) 1998 Steve Purkis. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

THANKS
======

   Various people from the perl5-agents mailing list.

Compute `intelligent' differences between two files / lists
***********************************************************

NAME
====

   Algorithm::Diff - Compute `intelligent' differences between two files /
lists

SYNOPSIS
========

     use Algorithm::Diff qw(diff LCS traverse_sequences);

     @lcs    = LCS( \@seq1, \@seq2 );

     @lcs    = LCS( \@seq1, \@seq2, $key_generation_function );

     $lcsref = LCS( \@seq1, \@seq2 );

     $lcsref = LCS( \@seq1, \@seq2, $key_generation_function );

     @diffs = diff( \@seq1, \@seq2 );

     @diffs = diff( \@seq1, \@seq2, $key_generation_function );

     traverse_sequences( \@seq1, \@seq2,
                        { MATCH => $callback,
                          DISCARD_A => $callback,
                          DISCARD_B => $callback,
                        } );

     traverse_sequences( \@seq1, \@seq2,
                        { MATCH => $callback,
                          DISCARD_A => $callback,
                          DISCARD_B => $callback,
                        },
                        $key_generation_function );

INTRODUCTION
============

   (by Mark-Jason Dominus)

   I once read an article written by the authors of diff; they said that
they hard worked very hard on the algorithm until they found the right one.

   I think what they ended up using (and I hope someone will correct me,
because I am not very confident about this) was the `longest common
subsequence' method.  in the LCS problem, you have two sequences of items:

     a b c d f g h j q z

     a b c d e f g i j k r x y z

   and you want to find the longest sequence of items that is present in
both original sequences in the same order.  That is, you want to find a
new sequence S which can be obtained from the first sequence by deleting
some items, and from the secend sequence by deleting other items.  You
also want S to be as long as possible.  In this case S is

     a b c d f g j z

   From there it's only a small step to get diff-like output:

     e   h i   k   q r x y
     +   - +   +   - + + +

   This module solves the LCS problem.  It also includes a canned function
to generate diff-like output.

   It might seem from the example above that the LCS of two sequences is
always pretty obvious, but that's not always the case, especially when the
two sequences have many repeated elements.  For example, consider

     a x b y c z p d q
     a b c a x b y c z

   A naive approach might start by matching up the a and b that appear at
the beginning of each sequence, like this:

     a x b y c         z p d q
     a   b   c a b y c z

   This finds the common subsequence `a b c z'.  But actually, the LCS is
`a x b y c z':

     a x b y c z p d q
     	a b c a x b y c z

USAGE
=====

   This module provides three exportable functions, which we'll deal with
in ascending order of difficulty: `LCS', diff, and `traverse_sequences'.

`LCS'
-----

   Given references to two lists of items, LCS returns an array containing
their longest common subsequence.  In scalar context, it returns a
reference to such a list.

     @lcs    = LCS( \@seq1, \@seq2 );
     $lcsref = LCS( \@seq1, \@seq2 );

   `LCS' may be passed an optional third parameter; this is a CODE
reference to a key generation function.  See `' in this node.

     @lcs    = LCS( \@seq1, \@seq2, $keyGen );
     $lcsref = LCS( \@seq1, \@seq2, $keyGen );

   Additional parameters, if any, will be passed to the key generation
routine.

diff
----

     @diffs     = diff( \@seq1, \@seq2 );
     $diffs_ref = diff( \@seq1, \@seq2 );

   diff computes the smallest set of additions and deletions necessary to
turn the first sequence into the second, and returns a description of
these changes.  The description is a list of *hunks*; each hunk represents
a contiguous section of items which should be added, deleted, or replaced.
The return value of diff is a list of hunks, or, in scalar context, a
reference to such a list.

   Here is an example:  The diff of the following two sequences:

     a b c e h j l m n p
     b c d e f j k l m r s t

   Result:

     [
       [ [ '-', 0, 'a' ] ],

     [ [ '+', 2, 'd' ] ],

     [ [ '-', 4, 'h' ] ,
       [ '+', 4, 'f' ] ],

     [ [ '+', 6, 'k' ] ],

     [ [ '-', 8, 'n' ],
       [ '-', 9, 'p' ],
       [ '+', 9, 'r' ],
       [ '+', 10, 's' ],
       [ '+', 11, 't' ],
     ]
      ]

   There are five hunks here.  The first hunk says that the a at position
0 of the first sequence should be deleted (-).  The second hunk says that
the d at position 2 of the second sequence should be inserted (+).  The
third hunk says that the h at position 4 of the first sequence should be
removed and replaced with the f from position 4 of the second sequence.
The other two hunks similarly.

   diff may be passed an optional third parameter; this is a CODE
reference to a key generation function.  See `' in this node.

   Additional parameters, if any, will be passed to the key generation
routine.

`traverse_sequences'
--------------------

   `traverse_sequences' is the most general facility provided by this
module; diff and `LCS' are implemented as calls to it.

   Imagine that there are two arrows.  Arrow A points to an element of
sequence A, and arrow B points to an element of the sequence B.
Initially, the arrows point to the first elements of the respective
sequences.  `traverse_sequences' will advance the arrows through the
sequences one element at a time, calling an appropriate user-specified
callback function before each advance.  It willadvance the arrows in such
a way that if there are equal elements `$A[$i]' and `$B[$j]' which are
equal and which are part of the LCS, there will be some moment during the
execution of `traverse_sequences' when arrow A is pointing to `$A[$i]' and
arrow B is pointing to `$B[$j]'.  When this happens, `traverse_sequences'
will call the MATCH callback function and then it will advance both arrows.

   Otherwise, one of the arrows is pointing to an element of its sequence
that is not part of the LCS.  `traverse_sequences' will advance that arrow
and will call the `DISCARD_A' or the `DISCARD_B' callback, depending on
which arrow it advanced.  If both arrows point to elements that are not
part of the LCS, then `traverse_sequences' will advance one of them and
call the appropriate callback, but it is not specified which it will call.

   The arguments to `traverse_sequences' are the two sequences to
traverse, and a callback which specifies the callback functions, like this:

     traverse_sequences( \@seq1, \@seq2,
                        { MATCH => $callback_1,
                          DISCARD_A => $callback_2,
                          DISCARD_B => $callback_3,
                        } );

   Callbacks are invoked with at least the indices of the two arrows as
their arguments.  They are not expected to return any values.  If a
callback is omitted from the table, it is not called.

   If arrow A reaches the end of its sequence, before arrow B does,
`traverse_sequences' will call the `A_FINISHED' callback when it advances
arrow B, if there is such a function; if not it will call `DISCARD_B'
instead.  Similarly if arrow B finishes first.  `traverse_sequences'
returns when both arrows are at the ends of their respective sequences.
It returns true on success and false on failure.  At present there is no
way to fail.

   `traverse_sequences' may be passed an optional fourth parameter; this
is a CODE reference to a key generation function.  See `' in this node.

   Additional parameters, if any, will be passed to the key generation
function.

KEY GENERATION FUNCTIONS
========================

   diff, `LCS', and `traverse_sequences' accept an optional last parameter.
This is a CODE reference to a key generating (hashing) function that should
return a string that uniquely identifies a given element.  It should be
the case that if two elements are to be considered equal, their keys
should be the same (and the other way around).  If no key generation
function is provided, the key will be the element as a string.

   By default, comparisons will use "eq" and elements will be turned into
keys using the default stringizing operator '""'.

   Where this is important is when you're comparing something other than
strings. If it is the case that you have multiple different objects that
should be considered to be equal, you should supply a key generation
function. Otherwise, you have to make sure that your arrays contain unique
references.

   For instance, consider this example:

     package Person;

     sub new
     {
       my $package = shift;
       return bless { name => '', ssn => '', @_ }, $package;
     }

     sub clone
     {
       my $old = shift;
       my $new = bless { %$old }, ref($old);
     }

     sub hash
     {
       return shift()->{'ssn'};
     }

     my $person1 = Person->new( name => 'Joe', ssn => '123-45-6789' );
     my $person2 = Person->new( name => 'Mary', ssn => '123-47-0000' );
     my $person3 = Person->new( name => 'Pete', ssn => '999-45-2222' );
     my $person4 = Person->new( name => 'Peggy', ssn => '123-45-9999' );
     my $person5 = Person->new( name => 'Frank', ssn => '000-45-9999' );

   If you did this:

     my $array1 = [ $person1, $person2, $person4 ];
     my $array2 = [ $person1, $person3, $person4, $person5 ];
     Algorithm::Diff::diff( $array1, $array2 );

   everything would work out OK (each of the objects would be converted
into a string like "Person=HASH(0x82425b0)" for comparison).

   But if you did this:

     my $array1 = [ $person1, $person2, $person4 ];
     my $array2 = [ $person1, $person3, $person4->clone(), $person5 ];
     Algorithm::Diff::diff( $array1, $array2 );

   $person4 and $person4->clone() (which have the same name and SSN) would
be seen as different objects. If you wanted them to be considered
equivalent, you would have to pass in a key generation function:

     my $array1 = [ $person1, $person2, $person4 ];
     my $array2 = [ $person1, $person3, $person4->clone(), $person5 ];
     Algorithm::Diff::diff( $array1, $array2, \&Person::hash );

   This would use the 'ssn' field in each Person as a comparison key, and
so would consider $person4 and $person4->clone() as equal.

   You may also pass additional parameters to the key generation function
if you wish.

AUTHOR
======

   This version by Ned Konz, perl@bike-nomad.com

CREDITS
=======

   Versions through 0.59 (and much of this documentation) were written by:

   Mark-Jason Dominus, mjd-perl-diff@plover.com

   This version borrows the documentation and names of the routines from
Mark-Jason's, but has all new code in Diff.pm.

   This code was adapted from the Smalltalk code of Mario Wolczko
<mario@wolczko.com>, which is available at
ftp://st.cs.uiuc.edu/pub/Smalltalk/MANCHESTER/manchester/4.0/diff.st

   The algorithm is that described in *A Fast Algorithm for Computing
Longest Common Subsequences*, CACM, vol.20, no.5, pp.350-353, May 1977,
with a few minor improvements to improve the speed.

Compute `intelligent' differences between two files / lists but use the old (<=0.59) interface.
***********************************************************************************************

NAME
====

   Algorithm::DiffOld - Compute `intelligent' differences between two
files / lists but use the old (<=0.59) interface.

NOTE
====

   This has been provided as part of the Algorithm::Diff package by Ned
Konz.  This particular module is *ONLY* for people who *HAVE* to have the
old interface, which uses a comparison function rather than a key
generating function.

   Because each of the lines in one array have to be compared with each of
the lines in the other array, this does M*N comparisions. This can be very
slow. I clocked it at taking 18 times as long as the stock version of
Algorithm::Diff for a 4000-line file. It will get worse quadratically as
array sizes increase.

SYNOPSIS
========

     use Algorithm::DiffOld qw(diff LCS traverse_sequences);

     @lcs    = LCS( \@seq1, \@seq2, $comparison_function );

     $lcsref = LCS( \@seq1, \@seq2, $comparison_function );

     @diffs = diff( \@seq1, \@seq2, $comparison_function );

     traverse_sequences( \@seq1, \@seq2,
                        { MATCH => $callback,
                          DISCARD_A => $callback,
                          DISCARD_B => $callback,
                        },
                        $comparison_function );

COMPARISON FUNCTIONS
====================

   Each of the main routines should be passed a comparison function. If you
aren't passing one in, *use Algorithm::Diff instead*.

   These functions should return a true value when two items should compare
as equal.

   For instance,

     @lcs    = LCS( \@seq1, \@seq2, sub { my ($a, $b) = @_; $a eq $b } );

   but if that is all you're doing with your comparison function, just use
Algorithm::Diff and let it do this (this is its default).

   Or:

     sub someFunkyComparisonFunction
     {
     	my ($a, $b) = @_;
     	$a =~ m{$b};
     }

     @diffs = diff( \@lines, \@patterns, \&someFunkyComparisonFunction );

   which would allow you to diff an array @lines which consists of text
lines with an array @patterns which consists of regular expressions.

   This is actually the reason I wrote this version - there is no way to
do this with a key generation function as in the stock Algorithm::Diff.

Calculate the transitive closure.
*********************************

NAME
====

   Algorithms::Graphs::TransitiveClosure - Calculate the transitive
closure.

SYNOPSIS
========

     use Algorithms::Graphs::TransitiveClosure qw /floyd_warshall/;

     my $graph = [[1, 0, 0, 0], [0, 1, 1, 1], [0, 1, 1, 0], [1, 0, 1, 1]];
     floyd_warshall $graph;
     print "There is a path from 2 to 0.\n" if $graph -> [2] -> [0];

     my $graph2 = {one   => {one => 1},
                   two   => {two => 1, three => 1, four => 1},
                   three => {two => 1, three => 1},
                   four  => {one => 1, four  => 1}};
     floyd_warshall $graph2;
     print "There is a path from three to one.\n" if
         $graph2 -> {three} -> {one};

DESCRIPTION
===========

   This is an implementation of the well known *Floyd-Warshall* algorithm.
[1,2]

   The subroutine floyd_warshall takes a directed graph, and calculates
its transitive closure, which will be returned. The given graph is
actually modified, so be sure to pass a copy of the graph to the routine
if you need to keep the original graph.

   The subroutine takes graphs in one of the two following formats:

floyd_warshall ARRAYREF
     The graph *G = (V, E)* is described with a list of lists, `$graph',
     representing *V x V*. If there is an edge between vertices $i and $j
     (or if `$i == $j'), then `$graph -> [$i] -> [$j] == 1'. For all other
     pairs `($k, $l)' from *V x V*, `$graph -> [$k] -> [$l] == 0'.

     The resulting `$graph' will have `$graph -> [$i] -> [$j] == 1' iff
     `$i == $j' or there is a path in G from $i to $j, and `$graph -> [$i]
     -> [$j] == 0' otherwise.

floyd_warshall HASHREF
     The graph *G = (V, E)*, with labeled vertices, is described with a
     hash of hashes, `$graph', representing *V x V*. If there is an edge
     between vertices `$label1' and `$label2' (or if `$label1 eq $label2'),
     then `$graph -> {$label1} -> {$label2} == 1'. For all other pairs
     `($label3, $label4)' from *V x V*, `$graph -> {$label3} -> {$label4}'
     does not exist.

     The resulting `$graph' will have `$graph -> {$label1} -> {$label2} ==
     1' iff `$label1 eq $label2' or there is a path in G from `$label1' to
     `$label2', and `$graph -> {$label1} -> {$label2}' does not exist
     otherwise.

EXAMPLES
========

     my $graph = [[1, 0, 0, 0],
                  [0, 1, 1, 1],
                  [0, 1, 1, 0],
                  [1, 0, 1, 1]];
     floyd_warshall $graph;
     foreach my $row (@$graph) {print "@$row\n"}

     1 0 0 0
     1 1 1 1
     1 1 1 1
     1 1 1 1

     my $graph = {one   => {one => 1},
                  two   => {two => 1, three => 1, four => 1},
                  three => {two => 1, three => 1},
                  four  => {one => 1, three => 1, four => 1}};
     floyd_warshall $graph;
     foreach my $l1 (qw /one two three four/) {
         print "$l1: ";
         foreach my $l2 (qw /one two three four/) {
             next if $l1 eq $l2;
             print "$l2 " if $graph -> {$l1} -> {$l2};
         }
         print "\n";
     }

     one:
     two: one three four
     three: one two four
     four: one two three

COMPLEXITY
==========

   The running time of the algorithm is cubed in the number of vertices of
the graph. The author of this package is not aware of any faster
algorithms, nor of a proof if this is optimal. Note than in specific
cases, when the graph can be embedded on surfaces of bounded genus, or in
the case of sparse connection matrices, faster algorithms than cubed in
the number of vertices exist.

   The space used by this algorithm is at most quadratic in the number of
vertices, which is optimal as the resulting transitive closure can have a
quadratic number of edges. In case when the graph is represented as a list
of lists, the quadratic bound will always be achieved, as the list of
lists already has that size. The hash of hashes however will use space
linear to the size of the resulting transitive closure.

LITERATURE
==========

   The Floyd-Warshall algorithm is due to Floyd [2], and based on a
theorem of Warshall [3]. The implemation of this package is based on an
implementation of Floyd-Warshall found in Cormen, Leiserson and Rivest [1].

REFERENCES
==========

[1]
     Thomas H. Cormen, Charles E. Leiserson and Ronald L. Rivest:
     *Introduction to Algorithms*. Cambridge: MIT Press, *1990*.  ISBN
     0-262-03141-8.

[2]
     Robert W. Floyd: "Algorithm 97 (SHORTEST PATH)".  *Communications of
     the ACM*, 5(6):345, *1962*.

[3]
     Stephan Warshall: "A theorem on boolean matrices."  *Journal of the
     ACM*, 9(1):11-12, *1962*.

HISTORY
=======

     $Date: 1999/03/01 19:51:11 $

     $Log: TransitiveClosure.pm,v $
     Revision 1.3  1999/03/01 19:51:11  abigail
     Renamed primary namespace to Algorithm::

     Revision 1.2  1998/03/23 04:00:37  abigail
     Fixed order of loop variables in the ARRAYREF case.
     It's k, i, j, not i, j, k.

     Revision 1.1  1998/03/22 06:54:42  abigail
     Initial revision

AUTHOR
======

   This package was written by Abigail.

COPYRIGHT
=========

   Copyright 1998 by Abigail.

LICENSE
=======

   This package is free and open software.

   You may use, copy, modify, distribute and sell this package or any
modifications there of in any form you wish, provided you do not do any of
the following:

     - claim that any of the original code was written by someone
       else than the original author(s).
     - restrict someone in using, copying, modifying, distributing or
       selling this program or module or any modifications of it.

   THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

Perl extension for m-differece detection.
*****************************************

NAME
====

   MDiff - Perl extension for m-differece detection.

SYNOPSIS
========

     use Algorithm::MDiff;

DESCRIPTION
===========

   m-difference is a comparason I designed myself-with the help of the
monks at http://www.perlmonks.org.  I'm sure the idea has been around, but
_I_ decided to call it m-difference.  :)

   Two strings are m-different if at least m of the characters in the
strings differ; that is, if m=3, then there are at least 3 indicies (i, j,
k) such that str1[i] != str2[i], str1[j] != str2[j] and str1[k] != str2[k].

EXPORTED FUNCTION
=================

     is_mdiff($m, $str1, $str2);  # returns a 0 or a 1

AUTHOR
======

   Jettero Heller <jettero@voltar.org>

SEE ALSO
========

   perl(1).

Object oriented Markov chain generator
**************************************

NAME
====

   Algorithm::MarkovChain - Object oriented Markov chain generator

SYNOPSIS
========

     use Algorithm::MarkovChain;

     my $chain = Algorithm::MarkovChain::->new();

     # learn about things from @symbols
     $chain->seed(symbols => \@symbols,
                  longest => 6);

     # attempt to tell me something about the sky
     my @newness = $chain->spew(length   => 20,
                                complete => [ qw( the sky is ) ]);

DESCRIPTION
===========

   Algorithm::MarkovChain is an implementation of the Markov Chain
algorithm within an object container.

METHODS
=======

Algorithm::MarkovChain::->new() or $obj->new()
----------------------------------------------

   Creates a new instance of the Algorithm::MarkovChain class.

   Takes one optional parameter: `recover_symbols'

   `recover_symbols' has meaning if your symbols differ from their true
values when stringifyed.  With this option enabled steps are taken to
ensure that the original values for symbols are returned by the *spew*
method.

$obj->seed()
------------

   Seeds the markov chains from an example symbol stream.

   Takes two parameters, one required symbols, one optional `longest'

   symbols presents the symbols to seed from

   `longest' sets an upper limit on the longest chain to construct.
(defaults to 4)

$obj->spew()
------------

   Uses the constructed chains to produce symbol streams

   Takes four optional parameters complete, length, `longest_subchain',
`force_length' and `stop_at_terminal'

   complete provides a starting point for the generation of output.  Note:
the algorithm will discard elements of this list if it does not find a
starting chain that matches it, this is infinite-loop avoidance.

   length specifies the minimum number of symbols desired (default is 30)

   `stop_at_terminal' directs the spew to stop chaining at the first
terminal point reached

   `force_length' ensures you get exactly length symbols returned (note
this overrides the behaviour of `stop_at_terminal')

TODO
====

Documentation
     I need to explain Markov Chains, and flesh out the examples some more.

Serialization interface
     Currently seeding the chain list is very intensive, and so there
     should be a useful way to serialize objects of Algorithm::MarkovChain.

     With the current implementation there are no private object variables,
     so it's possible to cheat and just freeze the raw object, but I
     wouldn't want for people to rely on that.

Fix bugs/respond to feature requests
     Just email me <richardc@unixbeard.net> and we'll sort something out...

BUGS
====

   Hopefully not, though if they probably arise from my not understanding
Markov chaining as well as I thought I did when coding commenced.

   That or they're jst stupid mistakes :)

AUTHOR
======

   Richard Clamp <richardc@unixbeard.net>

SEE ALSO
========

   perl(1).

Draw samples from a set
***********************

NAME
====

   Algorithm::Numerical::Sample - Draw samples from a set

SYNOPSIS
========

     use Algorithm::Numerical::Sample  qw /sample/;

     @sample = sample (-set         => [1 .. 10000],
                       -sample_size => 100);

     $sampler = Algorithm::Numerical::Sample::Stream -> new;
     while (<>) {$sampler -> data ($_)}
     $random_line = $sampler -> extract;

DESCRIPTION
===========

   This package gives two methods to draw fair, random samples from a set.
There is a procedural interface for the case the entire set is known, and
an object oriented interface when the a set with unknown size has to be
processed.

A: `sample (set => ARRAYREF [,sample_size => EXPR])'
----------------------------------------------------

   The sample function takes a set and a sample size as arguments.  If the
sample size is omitted, a sample of 1 is taken. The keywords set and
`sample_size' may be preceeded with an optional -.  The function returns
the sample list, or a reference to the sample list, depending on the
context.

B: `Algorithm::Numerical::Sample::Stream'
-----------------------------------------

   The class `Algorithm::Numerical::Sample::Stream' has the following
methods:

new
     This function returns an object of the
     `Algorithm::Numerical::Sample::Stream' class.  It will take an
     optional argument of the form `sample_size => EXPR', where EXPR
     evaluates to the sample size to be taken. If this argument is missing,
     a sample of size 1 will be taken.  The keyword `sample_size' may be
     preceeded by an optional dash.

`data (LIST)'
     The method data takes a list of parameters which are elements of the
     set we are sampling. Any number of arguments can be given.

extract
     This method will extract the sample from the object, and reset it to
     a fresh state, such that a sample of the same size but from a
     different set, can be taken. extract will return a list in list
     context, or the first element of the sample in scalar context.

CORRECTNESS PROOFS
==================

Algorithm A.
------------

   Crucial to see that the sample algorithm is correct is the fact that
when we sample n elements from a set of size N that the `t + 1'st element
is choosen with probability `(n - m)/(N - t)', when already m elements
have been choosen. We can immediately see that we will never pick too many
elements (as the probability is 0 as soon as `n == m'), nor too few, as
the probability will be 1 if we have k elements to choose from the
remaining k elements, for some k. For the proof that the sampling is
unbiased, we refer to [3].  (Section 3.4.2, Exercise 3).

Algorithm B.
------------

   It is easy to see that the second algorithm returns the correct number
of elements. For a sample of size n, the first n elements go into the
reservoir, and after that, the reservoir never grows or shrinks in size;
elements only get replaced.  A detailed proof of the fairness of the
algorithm appears in [3].  (Section 3.4.2, Exercise 7).

LITERATURE
==========

   Both algorithms are discussed by Knuth [3] (Section 3.4.2).  The first
algoritm, *Selection sampling technique*, was discovered by Fan, Muller
and Rezucha [1], and independently by Jones [2]. The second algorithm,
*Reservoir sampling*, is due to Waterman.

REFERENCES
==========

[1]
     C. T. Fan, M. E. Muller and I. Rezucha, *J. Amer. Stat. Assoc.* 57
     (1962), pp 387 - 402.

[2]
     T. G. Jones, *CACM* 5 (1962), pp 343.

[3]
     D. E. Knuth: *The Art of Computer Programming*, Volume 2, Third
     edition.  Reading: Addison-Wesley, 1997. ISBN: 0-201-89684-2.

HISTORY
=======

     $Date: 1999/08/09 08:01:05 $

     $Log: Sample.pm,v $
     Revision 1.3  1999/08/09 08:01:05  abigail
     Changed *all* occurences of Algorithms to Algorithm.

     Revision 1.2  1999/03/01 21:06:07  abigail
     Changed package to Algorithm::*

     Revision 1.1  1998/04/29 03:05:57  abigail
     Initial revision

AUTHOR
======

   This package was written by Abigail.

COPYRIGHT
=========

   Copyright 1998, 1999 by Abigail.

LICENSE
=======

   This package is free and open software.

   You may use, copy, modify, distribute and sell this package or any
modifications there of in any form you wish, provided you do not do any of
the following:

     - claim that any of the original code was written by someone
       else than the original author(s).
     - restrict someone in using, copying, modifying, distributing or
       selling this program or module or any modifications of it.

   THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

Shuffle a list.
***************

NAME
====

   Algorithm::Numerical::Shuffle - Shuffle a list.

SYNOPSIS
========

     use Algorithm::Numerical::Shuffle qw /shuffle/;

     @shuffled = shuffle (1, 2, 3, 4, 5, 6, 7);

     $in_situ = [qw /one two three four five six/];
     shuffle $in_situ;

DESCRIPTION
===========

   shuffle performs a one pass, fair shuffle on a list. If the list is
passed as a reference to an array, the shuffle is done in situ.

   The subroutine returns the list in list context, and a reference to the
list in scalar context.

COMPLEXITY
==========

   The running time of the algorithm is linear in the size of the list.
For an in situ shuffle, the memory overhead is constant; otherwise, linear
extra memory is used.

LITERATURE
==========

   The algorithm used is discussed by Knuth [3]. It was first published by
Fisher and Yates [2], and later by Durstenfeld [1].

CAVEAT
======

   Salfi [4] points to a big caveat. If the outcome of a random generator
is solely based on the value of the previous outcome, like a linear
congruential method, then the outcome of a shuffle depends on exactly
three things: the shuffling algorithm, the input and the seed of the
random generator. Hence, for a given list and a given algorithm, the
outcome of the shuffle is purely based on the seed. Many modern computers
have 32 bit random numbers, hence a 32 bit seed. Hence, there are at most
2^32 possible shuffles of a list, foreach of the possible algorithms.  But
for a list of n elements, there are n! possible permutations.  Which means
that a shuffle of a list of 13 elements will not generate certain
permutations, as 13! > 2^32.

REFERENCES
==========

[1]
     R. Durstenfeld: *CACM*, 7, 1964. pp 420.

[2]
     R. A. Fisher and F. Yates: *Statistical Tables*. London, 1938.
     Example 12.

[3]
     D. E. Knuth: *The Art of Computer Programming*, Volume 2, Third
     edition.  Section 3.4.2, Algorithm P, pp 145. Reading:
     Addison-Wesley, 1997.  ISBN: 0-201-89684-2.

[4]
     R. Salfi: *COMPSTAT 1974*. Vienna: 1974, pp 28 - 35.

HISTORY
=======

     $Date: 2000/03/08 05:57:40 $

     $Log: Shuffle.pm,v $
     Revision 1.4  2000/03/08 05:57:40  abigail
     Fixed bug that prevented in situ shuffling.
     Changed the wording of the license once again. (MIT/X style)

     Revision 1.3  1999/03/01 20:54:06  abigail
     Changed package name to Algorithm::*
     Changed license.

     Revision 1.2  1998/09/09 20:48:12  abigail
     - Make shuffle() work with empty lists.
     - Changed license to Artistic only.

     Revision 1.1  1998/04/23 17:58:07  abigail
     Initial revision

AUTHOR
======

   This package was written by Abigail.

COPYRIGHT
=========

   Copyright 1998, 1999, 2000 by Abigail.

LICENSE
=======

   This program is copyright 1998-2000 by Abigail.

   Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Handy and fast permutation with object oriented interface
*********************************************************

NAME
====

   Algorithm::Permute - Handy and fast permutation with object oriented
interface

SYNOPSIS
========

     use Algorithm::Permute;

     $p = new Algorithm::Permute(['a'..'d']);
     while (@res = $p->next) {
       print join(", ", @res), "\n";
     }

DESCRIPTION
===========

   This handy module makes performing permutation in Perl easy and fast,
although perhaps its algorithm is not the fastest on the earth.  Currently
it only supports permutation n of n objects.

   No exported functions. This version is not backward compatible with the
previous one, version 0.01. The old interface is no longer supported.

METHODS
=======

new [@list]
     Returns a permutor object for the given items.

next
     Returns a list of the items in the next permutation.  The order of
     the resulting permutation is the same as of the previous version of
     `Algorithm::Permute'.

peek
     Returns the list of items which *will be returned* by next(), but
     *doesn't advance the sequence*. Could be useful if you wished to skip
     over just a few unwanted permutations.

reset
     Resets the iterator to the start. May be used at any time, whether the
     entire set has been produced or not. Has no useful return value.

COMPARISON
==========

   I've collected some Perl routines and modules which implement
permutation, and do some simple benchmark. The result, which is of course
predictable, and obvious, is the following.

   Permutation of *eight* scalars:

     Abigail's: 14 wallclock secs (13.21 usr +  0.49 sys = 13.70 CPU)
     Algorithm::Permute: 3 wallclock secs ( 2.96 usr +  0.02 sys =  2.98 CPU)
     List::Permutor:  9 wallclock secs ( 8.98 usr +  0.02 sys =  9.00 CPU)
        MJD's: 56 wallclock secs (55.54 usr +  0.18 sys = 55.72 CPU)
     perlfaq4: 65 wallclock secs (64.71 usr +  0.22 sys = 64.93 CPU)

   Permutation of *nine* scalars (the Abigail's routine is commented out,
because it stores all of the result in memory, swallows all of my
machine's memory):

     Algorithm::Permute: 14 wallclock secs (14.13 usr + 0.07 sys = 14.20 CPU)
     List::Permutor: 67 wallclock secs (65.78 usr +  0.47 sys = 66.25 CPU)
        MJD's: 530 wallclock secs (516.57 usr +  2.10 sys = 518.67 CPU)
     perlfaq4: 498 wallclock secs (490.49 usr +  1.65 sys = 492.14 CPU)

   The benchmark script is included in the bench directory. I understand
that speed is not everything. So here is the list of URLs of the
alternatives, in case you hate this module.

   * Mark Jason Dominus' technique is discussed in chapter 4 Perl
     Cookbook, so you  can get it from O'Reilly:
     ftp://ftp.oreilly.com/published/oreilly/perl/cookbook

   * Abigail's: http://www.foad.org/~abigail/Perl

   * List::Permutor: http://www.cpan.org/modules/by-module/List

   * The classic way, usually used by Lisp hackers: perldoc perlfaq4

HISTORY
=======

   *  September 2, 2000 - version 0.02. Major interface changes, now using
     object oriented interface similar to `List::Permutor''s. More
     efficient memory usage. Internal tweaking gives speed improvement -
     the list elements are no longer swapped, but only the indexes.

   * October 3, 1999 - Alpha release, version 0.01

AUTHOR
======

   Edwin Pratomo, *ed.pratomo@computer.org*. The object oriented interface
is taken from Tom Phoenix's `List::Permutor'.

ACKNOWLEDGEMENT
===============

   Yustina Sri Suharini - my fiance, for providing the permutation problem
to me.

SEE ALSO
========

   * *Data Structures, Algorithms, and Program Style Using C* -  Korsh and
     Garrett

   * *Algorithms from P to NP, Vol. I* - Moret and Shapiro

Implementation of Select And Insert sorting algorithm in C
**********************************************************

NAME
====

   Algorithm::SISort - Implementation of Select And Insert sorting
algorithm in C

SYNOPSIS
========

     use Algorithm::SISort qw(Sort Sort_inplace);

     @sorted_list = Sort {$_[0] <=> $_[1]} @unsorted_list;
     # ... or ...
     Sort_inplace {$_[0] <=> $_[1]} @unsorted_list;

DESCRIPTION
===========

   This module implements a sorting algorithm I saw in BIT 28 (1988) by
István Beck and Stein Krogdahl. This implmentation is mainly intended to
try out the Inline module by Brian Ingerson. The algorithim is a
combination of *Straight Insertion Sort* and *Selection Sort*. While
*Insertion Sort* and *Selection Sort* both are of complexity O(n**2),
*Select and Insert Sort* should have complexitiy O(n**1.5).

   This module defines the functions Sort and `Sort_inplace', which have
signatures similar to the internal sort function. The difference is that a
codref defining a comparison is always required and that the two values to
compare are always passed in `@_' and not as `$a' and $b. (Although I
might change that later.)

   Sort returns a sorted copy if the array, but `Sort_inplace' sorts the
array in place (as the name suggests) and returns the number of
comparisons done.  (Note that the sorting is always done in place, Sort
just copies the array before calling the internal sort routine.)

BUGS
====

   This is the first serious (i.e. not "Hello World") C-extension I've
done, so I suspect I've screwed around with the refcounts of the list
entries. Until I've confirmed that there are no memory leaks, I caution
people not to use this piece of code in any production system.

   Any bug-reports, comments and patches are very welcome at my email
address below.

SEE ALSO
========

   See Inline, Inline/C, and *A Select And
Insert Sorting Algorithm* by István Beck and Stein Krogdahl in *BIT 28
(1988), 726-735*.

AUTHOR
======

   Hrafnkell F. Hlodversson, keli@shebang.dk

COPYRIGHT
=========

   Copyright 2001, Hrafnkell F Hlodversson

   All Rights Reserved.  This module is free software. It may be used,
redistributed and/or modified under the terms of the Perl Artistic License.

   See http://www.perl.com/perl/misc/Artistic.html

declare symbolic aliases for perl data
**************************************

NAME
====

   alias - declare symbolic aliases for perl data

   attr  - auto-declare hash attributes for convenient access

   const - define compile-time scalar constants

SYNOPSIS
========

     use Alias qw(alias const attr);
     alias TEN => $ten, Ten => \$ten, Ten => \&ten,
           Ten => \@ten, Ten => \%ten, TeN => \*ten;
     {
        local @Ten;
        my $ten = [1..10];
        alias Ten => $ten;   # local @Ten
     }

     const pi => 3.14, ten => 10;

     package Foo;
     use Alias;
     sub new { bless {foo => 1, _bar => [2, 3]}, $_[0] }
     sub a_method {
        my $s = attr shift;
        # $foo, @_bar are now local aliases for
        # $_[0]{foo}, @{$_[0]{_bar}} etc.
     }

     sub b_method {
       local $Alias::KeyFilter = "_";
       local $Alias::AttrPrefix = "main::";
       my $s = attr shift;
       # local @::_bar is now available, ($foo, $::foo are not)
     }

     sub c_method {
       local $Alias::KeyFilter = sub { $_ = shift; return (/^_/ ? 1 : 0) };
       local $Alias::AttrPrefix = sub {
                                        $_ = shift;
     				       s/^_(.+)$/main::$1/;
     				       return $_
     				     };
       my $s = attr shift;
       # local @::bar is now available, ($foo, $::foo are not)
     }

DESCRIPTION
===========

   Provides general mechanisms for aliasing perl data for convenient
access.

   This module works by putting some values on the symbol table with
user-supplied names.  Values that are references will get dereferenced into
their base types.  This means that a value of `[1,2,3]' with a name of
"foo" will be made available as `@foo', not `$foo'.

   The exception to this rule is the default behavior of the attr function,
which will not dereference values which are blessed references (aka
objects).  See `$Alias::Deref' in this node for how to change this default
behavior.

Functions
---------

alias
     Given a list of name => value pairs, declares aliases in the callers
     namespace. If the value supplied is a reference, the alias is created
     for the underlying value instead of the reference itself (there is no
     need to use this module to alias references-they are automatically
     "aliased" on assignment).  This allows the user to alias most of the
     basic types.

     If the value supplied is a scalar compile-time constant, the aliases
     become read-only. Any attempt to write to them will fail with a run
     time error.

     Aliases can be dynamically scoped by pre-declaring the target
     variable as local.  Using attr for this purpose is more convenient,
     and recommended.

attr
     Given a hash reference, aliases the values of the hash to the names
     that correspond to the keys.  It always returns the supplied value.
     The aliases are local to the enclosing block. If any of the values
     are unblessed references, they are available as their dereferenced
     types.  Thus the action is similar to saying:

          alias %{$_[0]}

     but, in addition, also localizes the aliases, and does not dereference
     objects.  Dereferencing of objects can be forced by setting the
     `Deref' option.  See `$Alias::Deref' in this node.

     This can be used for convenient access to hash values and hash-based
     object attributes.

     Note that this makes available the semantics of local subroutines and
     methods.  That makes for some nifty possibilities.  We could make
     truly private methods by putting anonymous subs within an object.
     These subs would be available within methods where we use attr, and
     will not be visible to the outside world as normal methods.  We could
     forbid recursion in methods by always putting an empty sub in the
     object hash with the same key as the method name. This would be
     useful where a method has to run code from other modules, but cannot
     be certain whether that module will call it back again.

     The default behavior is to create aliases for all the entries in the
     hash, in the callers namespace.  This can be controlled by setting a
     few options.  See `Configuration Variables' in this node for details.

const
     This is simply a function alias for alias, described above.  Provided
     on demand at use time, since it reads better for constant
     declarations.  Note that hashes and arrays cannot be so constrained.

Configuration Variables
-----------------------

   The following configuration variables can be used to control the
behavior of the attr function.  They are typically set after the `use
Alias;' statement.  Another typical usage is to localize them in a block
so that their values are only effective within that block.

$Alias::KeyFilter
     Specifies the key prefix used for determining which hash entries will
     be interned by attr.  Can be a CODE reference, in which case it will
     be called with the key, and the boolean return value will determine if
     that hash entry is a candidate attribute.

$Alias::AttrPrefix
     Specifies a prefix to prepend to the names of localized attributes
     created by attr.  Can be a CODE reference, in which case it will be
     called with the key, and the result will determine the full name of
     the attribute.  The value can have embedded package delimiters ("::"
     or "'"), which cause the attributes to be interned in that namespace
     instead of the callers own namespace. For example, setting it to
     "main::" makes `use strict 'vars';' somewhat more palatable (since we
     can refer to the attributes as `$::foo', etc., without actually
     declaring the attributes).

$Alias::Deref
     Controls the implicit dereferencing behavior of attr.  If it is set to
     "" or 0, attr will not dereference blessed references.  If it is a
     true value (anything but "", 0, or a CODE reference), all references
     will be made available as their dereferenced types, including values
     that may be objects.  The default is "".

     This option can be used as a filter if it is set to a CODE reference,
     in which case it will be called with the key and the value (whenever
     the value happens to be a reference), and the boolean return value
     will determine if that particular reference must be dereferenced.

Exports
-------

alias
attr
EXAMPLES
========

   Run these code snippets and observe the results to become more familiar
with the features of this module.

     use Alias qw(alias const attr);
     $ten = 10;
     alias TEN => $ten, Ten => \$ten, Ten => \&ten,
     	  Ten => \@ten, Ten => \%ten;
     alias TeN => \*ten;  # same as *TeN = *ten

     # aliasing basic types
     $ten = 20;
     print "$TEN|$Ten|$ten\n";   # should print "20|20|20"
     sub ten { print "10\n"; }
     @ten = (1..10);
     %ten = (a..j);
     &Ten;                       # should print "10"
     print @Ten, "|", %Ten, "\n";

     # this will fail at run time
     const _TEN_ => 10;
     eval { $_TEN_ = 20 };
     print $@ if $@;

     # dynamically scoped aliases
     @DYNAMIC = qw(m n o);
     {
        my $tmp = [ qw(a b c d) ];
        local @DYNAMIC;
        alias DYNAMIC => $tmp, PERM => $tmp;

     $DYNAMIC[2] = 'zzz';
     # prints "abzzzd|abzzzd|abzzzd"
     print @$tmp, "|", @DYNAMIC, "|", @PERM, "\n";

     @DYNAMIC = qw(p q r);
     # prints "pqr|pqr|pqr"
     print @$tmp, "|", @DYNAMIC, "|", @PERM, "\n";
         }

     # prints "mno|pqr"
     print @DYNAMIC, "|", @PERM, "\n";

     # named closures
     my($lex) = 'abcd';
     $closure = sub { print $lex, "\n" };
     alias NAMEDCLOSURE => \&$closure;
     NAMEDCLOSURE();            # prints "abcd"
     $lex = 'pqrs';
     NAMEDCLOSURE();            # prints "pqrs"

     # hash/object attributes
     package Foo;
     use Alias;
     sub new {
       bless
     	{ foo => 1,
           bar => [2,3],
           buz => { a => 4},
           privmeth => sub { "private" },
           easymeth => sub { die "to recurse or to die, is the question" },
         }, $_[0];
     }

     sub easymeth {
       my $s = attr shift;    # localizes $foo, @bar, %buz etc with values
       eval { $s->easymeth }; # should fail
       print $@ if $@;

     # prints "1|2|3|a|4|private|"
     print join '|', $foo, @bar, %buz, $s->privmeth, "\n";
         }

     $foo = 6;
     @bar = (7,8);
     %buz = (b => 9);
     Foo->new->easymeth;       # this will not recurse endlessly

     # prints "6|7|8|b|9|"
     print join '|', $foo, @bar, %buz, "\n";

     # this should fail at run-time
     eval { Foo->new->privmeth };
     print $@ if $@;

NOTES
=====

   It is worth repeating that the aliases created by alias and const will
be created in the callers namespace (we can use the `AttrPrefix' option to
specify a different namespace for attr).  If that namespace happens to be
localized, the aliases created will be local to that block.  attr
localizes the aliases for us.

   Remember that references will be available as their dereferenced types.

   Aliases cannot be lexical, since, by neccessity, they live on the
symbol table.

   Lexicals can be aliased. Note that this provides a means of reversing
the action of anonymous type generators \, [] and `{}'.  This allows us to
anonymously construct data or code and give it a symbol-table presence
when we choose.

   Any occurrence of `::' or `'' in names will be treated as package
qualifiers, and the value will be interned in that namespace.

   Remember that aliases are very much like references, only we don't have
to dereference them as often.  Which means we won't have to pound on the
dollars so much.

   We can dynamically make subroutines and named closures with this scheme.

   It is possible to alias packages, but that might be construed as abuse.

   Using this module will dramatically reduce noise characters in
object-oriented perl code.

BUGS
====

   `use strict 'vars';' is not very usable, since we depend so much on the
symbol table.  You can declare the attributes with `use vars' to avoid
warnings.  Setting $Alias::AttrPrefix to "main::" is one way to avoid `use
vars' and frustration.

   Tied variables cannot be aliased properly, yet.

VERSION
=======

   Version 2.32       30 Apr 1999

AUTHOR
======

   Gurusamy Sarathy                gsar@umich.edu

   Copyright (c) 1995-99 Gurusamy Sarathy. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1)

Perl extension for AltaVista Search Software Development Kit
************************************************************

NAME
====

   AltaVista::SearchSDK - Perl extension for AltaVista Search Software
Development Kit

SYNOPSIS
========

     use AltaVista::SearchSDK;

   avs_adddate(idx, yr, mo, da, startloc)

   avs_addfield(idx, pFname, startloc, endloc)

   avs_addliteral(idx, pWord, loc)

   avs_addvalue(idx, valtype, value, loc)

   avs_addword(idx, pWords, loc, pNumWords)

   avs_buildmode(idx)

   avs_buildmode_ex(idx, ntiers)

   avs_close(idx)

   avs_compact(idx, bMore_p)

   avs_compactionneeded(idx)

   avs_compact_minor(idx, bMore_p)

   avs_count(idx, pWordPrefix, pCountsHdl)

   avs_count_close(CountsHdl)

   avs_count_getcount(CountsHdl)

   avs_countnext(CountsHdl)

   avs_count_getword(CountsHdl)

   avs_default_options(pOptions)

   avs_define_valtype(name, minval, maxval, valtype_p)

   avs_deletedocid(idx, pDocId, pCount)

   avs_enddoc(idx)

   avs_errmsg(code)

   avs_getindexmode(idx)

   avs_getindexversion(idx)

   avs_getindexversion_counts_v(countsHdl)

   avs_getindexversion_search_v(searchHdl)

   avs_getsearchresults(searchHdl, resultNum)

   avs_getsearchterms(psearchHdl, termNum, term, count)

   avs_lookup_valtype(name)

   avs_makestable(idx)

   avs_open(path, mode, pIdx)

   avs_querymode(idx)

   avs_release_valtypes()

   avs_search(idx, pQuery, pBoolQuery, pOptions, pDocsFound,
pDocsReturned, pTermCount, pSearchHdl)

   avs_search_close(pSearchHdl)

   avs_search_ex(idx, pQuery, pBoolQuery, pOptions, searchsince,
pDocsFound, pDocsReturned, pTermCount, pSearchHdl)

   avs_search_genrank(idx, pBoolQuery, pRankTerms, pRankSetup, pOptions,
searchsince, pDocsFound, pDocsReturned, pSearchHdl)

   avs_search_getdata(searchHdl)

   avs_search_getdatalen(searchHdl)

   avs_search_getdate(psearchHdl, year, month, day)

   avs_search_getdocid(searchHdl)

   avs_search_getdocidlen(searchHdl)

   avs_search_getrelevance(psearchHdl)

   avs_setdocdata(idx, pDocData, len)

   avs_setdocdate(idx, year, month, day)

   avs_setdocdatetime(idx, year, month, day, hour, minute, second)

   avs_setparseflags(idx, parseflags)

   avs_setrankval(idx, valtype, value)

   avs_startdoc(idx, pDocId, flags, pStartLoc)

   avs_timer(current)

   avs_version()

   avs_create_options(limit, timeout, flags)

DESCRIPTION
===========

   This set of extensions provides wrappers for all the C functionality of
the AltaVista Search software development kit (SDK) except for a few
functions that did not make sense to export to perl.

   All the functions of the 97 Rev B kit are available as advertised,
except for the following:

avs_add_ms_callback UNIMPLEMENTED
     It makes no sense to implement this function, since it would require
     being able to pass a C function handle through perl.

avs_addrankterms UNIMPLEMENTED
     Internal function

avs_newdoc UNIMPLEMENTED
     No easy way to provide filter function

avs_search_getdata_copy UNIMPLEMENTED
     No need for this function

avs_search_getdocid_copy UNIMPLEMENTED
     No need for this function

avs_search_getrelevance RETURN ARGUMENT
     Relevance is returned as a string representation of the float

PREREQUITES
===========

   Perl 5.004, the AltaVista SearchSDK 97 Rev B

INSTALLATION
============

   To install this module, move into the directory where this file is
located.  First copy avs.h and libavs97b.a from your AltaVista SearchSDK
source hierarchy into this directory. Then type the following:

     perl Makefile.PL
     make
     make test
     make install

   This will install the module into the Perl library directory.

AUTHOR
======

   James M. Turner <james@csmonitor.com>

   Copything (C) 1998 The Christian Science Publishing Society.  All
rights reserved

   This program is free software, you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1), AltaVista Search SDK documentation.

BUGS
====

   This beta version has been tested in a live environment for certain
conditions, but has by no means been extensively tested.  In particular,
it has not been tested on anything but Solaris 2.5 on an Ultra.  Please
let me know if you get it work under other platforms or operating systems.

provide framework for multiple DBMs
***********************************

NAME
====

   AnyDBM_File - provide framework for multiple DBMs

   NDBM_File, DB_File, GDBM_File, SDBM_File, ODBM_File - various DBM
implementations

SYNOPSIS
========

     use AnyDBM_File;

DESCRIPTION
===========

   This module is a "pure virtual base class"-it has nothing of its own.
It's just there to inherit from one of the various DBM packages.  It
prefers ndbm for compatibility reasons with Perl 4, then Berkeley DB (See
DB_File), GDBM, SDBM (which is always there-it comes with
Perl), and finally ODBM.   This way old programs that used to use NDBM via
dbmopen() can still do so, but new ones can reorder @ISA:

     BEGIN { @AnyDBM_File::ISA = qw(DB_File GDBM_File NDBM_File) }
     use AnyDBM_File;

   Having multiple DBM implementations makes it trivial to copy database
formats:

     use POSIX; use NDBM_File; use DB_File;
     tie %newhash,  'DB_File', $new_filename, O_CREAT|O_RDWR;
     tie %oldhash,  'NDBM_File', $old_filename, 1, 0;
     %newhash = %oldhash;

DBM Comparisons
---------------

   Here's a partial table of features the different packages offer:

     odbm    ndbm    sdbm    gdbm    bsd-db
     			 ----	 ----    ----    ----    ------
      Linkage comes w/ perl   yes     yes     yes     yes     yes
      Src comes w/ perl       no      no      yes     no      no
      Comes w/ many unix os   yes     yes[0]  no      no      no
      Builds ok on !unix      ?       ?       yes     yes     ?
      Code Size               ?       ?       small   big     big
      Database Size           ?       ?       small   big?    ok[1]
      Speed                   ?       ?       slow    ok      fast
      FTPable                 no      no      yes     yes     yes
      Easy to build          N/A     N/A      yes     yes     ok[2]
      Size limits             1k      4k      1k[3]   none    none
      Byte-order independent  no      no      no      no      yes
      Licensing restrictions  ?       ?       no      yes     no

[0]
     on mixed universe machines, may be in the bsd compat library, which
     is often shunned.

[1]
     Can be trimmed if you compile for one access method.

[2]
     See DB_File.  Requires symbolic links.

[3]
     By default, but can be redefined.

SEE ALSO
========

   dbm(3), ndbm(3), DB_File(3), see Perldbmfilter (perl.info),

Automagically loads modules for fully qualified functions
*********************************************************

NAME
====

   AnyLoader - Automagically loads modules for fully qualified functions

SYNOPSIS
========

     use AnyLoader;

     Carp::croak("This is going to hurt the Perl community more than it ".
                 "is going to hurt you!");

DESCRIPTION
===========

   AnyLoader will automagically load the module and import the function
for any fully qualified function call.  Essentially, this means you can
just call functions without worrying about loading the module first.

   In the example above, AnyLoader does the equivalent of "require Carp"
before the call to Carp::carp().  This should be useful for the many cases
where one does:

     if($error) {
         require Carp;
         Carp::croak($error);
     }

   to avoid loading Carp at startup.

   AnyLoader is package scoped.

Restricting what gets loaded.
-----------------------------

   You might not want to let *every* package be AnyLoaded, so ways of
qualifying what gets loaded are provided.  A list of modules can be given
to `use AnyLoader' and only those modules will be AnyLoaded.

     use AnyLoader qw(Data::Dumper Carp);

     Data::Dumper::Dumper($foo);         # This works.
     LWP::Simple::get($url);             # This doesn't.

   If you wish to shut off AnyLoader, `no AnyLoader' will do so for the
current package.  `no AnyLoader' also takes a list of modules.  These
modules are those which are specifically not to be loaded.

     # AnyLoad anything but LWP and URI::URL.
     no AnyLoader qw(LWP URI::URL);

   The lists and effects are cumulative and package scoped (*not lexical*).

BUGS and CAVEATS
================

   The effects should really be lexically scoped, but I don't think I can
pull that off.

   This module requires on the "Use of inherited AUTOLOAD for non-method"
deprecated feature.

   $SIG{__WARN__} had to be used to suppress a warning about the
deprecated feature.

   Defines UNIVERSAL::AUTOLOAD which may interfere with other modules.

   Despite what you'd think, AnyLoader *will* work with modules which
employ an autoloader.

AUTHORS
=======

   Arnar M. Hrafnkelsson <addi@umich.edu> and Michael G Schwern
<schwern@pobox.com>

LICENSE
=======

   Copyright (c) 2000 Arnar M. Hrafnkelsson and Michael G Schwern.  All
Rights Reserved.

   You may distribute under the same license as Perl itself.

SEE ALSO
========

   See Autouse,

Perl extension for ao cross-platform audio library
**************************************************

NAME
====

   Ao - Perl extension for ao cross-platform audio library

SYNOPSIS
========

     use Ao;

     $ao_id1 = Ao::get_driver_id('oss');
     %ao_info = %{Ao::get_driver_info($ao_id1)};
     $ao_endian = Ao::is_big_endian();
     $ao_dev1 = Ao::open($ao_id);
     Ao::play($ao_dev1, $buffer, $len);
     Ao::close($ao_dev1);

     $ao_id2 = Ao::get_driver_id('wav');
     %ao_options = ('file' => 'out.wav');
     $ao_dev2 = Ao::open($ao_id2, 16, 44100, 2, %ao_options);
     $ao_dev2->play($buffer, $len);
     $ao_dev2->close();

DESCRIPTION
===========

   This is a simple object-oriented wrapper around the ao audio library.
Use Ao::get_driver_id to obtain an integer id from a short driver name.
Currently supported drivers are oss, irix, solaris, esd, alsa and wav.

   A small hash of driver info (with fields name, short_name, author and
comments) can be obtained with Ao::get_driver_info.

   Ao::is_big_endian can be used to test the byte-order of the machine.

   Open a device with

     Ao::open($driver_id, $bits_per_sample, $rate, $channels, %options)

   where the default values are 16 bits at 44100 Hz stereo, and no
options.  options is a hash of named parameters to pass to the specific
driver.  The wav driver defaults to writing output to the file output.wav
- you can change this by passing the file option.  Other options can be
found in the ao documentation.

   Play to a device with

     Ao::play($device, $buffer, $len)

   where $device is the device returned from Ao::open, $buffer is a
pointer to a buffer of sound input, and $len is the length of the buffered
sound to play.  To obtain sound input you will need to use a separate
module such as Ogg::Vorbis.

   When you are done, close the device with Ao::close($device).

Exported constants
==================

     AO_ALSA
     AO_BEOS
     AO_DRIVERS
     AO_ESD
     AO_IRIX
     AO_NULL
     AO_OSS
     AO_RAW
     AO_SOLARIS
     AO_WAV
     AO_WIN32

AUTHOR
======

   Alex Shinn, foof@debian.org

SEE ALSO
========

   perl(1), Ogg::Vorbis(3pm), and the README distributed with ao.

Perl interface to the Apache server API
***************************************

NAME
====

   Apache - Perl interface to the Apache server API

SYNOPSIS
========

     use Apache ();

DESCRIPTION
===========

   This module provides a Perl interface the Apache API.  It is here
mainly for mod_perl, but may be used for other Apache modules that wish to
embed a Perl interpreter.  We suggest that you also consult the
description of the Apache C API at http://www.apache.org/docs/.

THE REQUEST OBJECT
==================

   The request object holds all the information that the server needs to
service a request.  Apache *Perl*Handler*s will be given a reference to the
request object as parameter and may choose to update or use it in various
ways.  Most of the methods described below obtain information from or
update the request object.  The perl version of the request object will be
blessed into the Apache package, it is really a `request_rec*' in disguise.

Apache->request([$r])
     The Apache->request method will return a reference to the request
     object.

     *Perl*Handler*s can obtain a reference to the request object when it
     is passed to them via `@_'.  However, scripts that run under
     Apache::Registry, for example, need a way to access the request
     object.  Apache::Registry will make a request object available to
     these scripts by passing an object reference to `Apache->request($r)'.
     If handlers use modules such as CGI::Apache that need to access
     `Apache->request', they too should do this (e.g. *Apache::Status*).

$r->as_string
     Returns a string representation of the request object.  Mainly useful
     for debugging.

$r->main
     If the current request is a sub-request, this method returns a blessed
     reference to the main request structure.  If the current request is
     the main request, then this method returns undef.

$r->prev
     This method returns a blessed reference to the previous (internal)
     request structure or undef if there is no previous request.

$r->next
     This method returns a blessed reference to the next (internal) request
     structure or undef if there is no next request.

$r->last
     This method returns a blessed reference to the last (internal) request
     structure.  Handy for logging modules.

$r->is_main
     Returns true if the current request object is for the main request.
     (Should give the same result as `!$r->main', but will be more
     efficient.)

$r->is_initial_req
     Returns true if the current request is the first internal request,
     returns false if the request is a sub-request or internal redirect.

SUB REQUESTS
============

   Apache provides a sub-request mechanism to lookup a uri or filename,
performing all access checks, etc., without actually running the response
phase of the given request.  Notice, we have dropped the `sub_req_' prefix
here.  The `request_rec*' returned by the lookup methods is blessed into
the *Apache::SubRequest* class.  This way, `destroy_sub_request()' is
called automatically during `Apache::SubRequest->DESTROY' when the object
goes out of scope.  The *Apache::SubRequest* class inherits all the
methods from the Apache class.

$r->lookup_uri($uri)
          my $subr = $r->lookup_uri($uri);
          my $filename = $subr->filename;

          unless(-e $filename) {
              warn "can't stat $filename!\n";
          }

$r->lookup_file($filename)
          my $subr = $r->lookup_file($filename);

$subr->run
          if($subr->run != OK) {
              $subr->log_error("something went wrong!");
          }

CLIENT REQUEST PARAMETERS
=========================

   In this section we will take a look at various methods that can be used
to retrieve the request parameters sent from the client.  In the following
examples, $r is a request object blessed into the Apache class, obtained
by the first parameter passed to a handler subroutine or *Apache->request*

$r->method( [$meth] )
     The $r->method method will return the request method.  It will be a
     string such as "GET", "HEAD" or "POST".  Passing an argument will set
     the method, mainly used for internal redirects.

$r->method_number( [$num] )
     The $r->method_number method will return the request method number.
     The method numbers are defined by the M_GET, M_POST,... constants
     available from the *Apache::Constants* module.  Passing an argument
     will set the method_number, mainly used for internal redirects and
     testing authorization restriction masks.

$r->bytes_sent
     The number of bytes sent to the client, handy for logging, etc.

$r->the_request
     The request line sent by the client, handy for logging, etc.

$r->proxyreq
     Returns true if the request is proxy http.  Mainly used during the
     filename translation stage of the request, which may be handled by a
     `PerlTransHandler'.

$r->header_only
     Returns true if the client is asking for headers only, e.g. if the
     request method was HEAD.

$r->protocol
     The $r->protocol method will return a string identifying the protocol
     that the client speaks.  Typical values will be "HTTP/1.0" or
     "HTTP/1.1".

$r->hostname
     Returns the server host name, as set by full URI or Host: header.

$r->request_time
     Returns the time that the request was made.  The time is the local
     unix time in seconds since the epoch.

$r->uri( [$uri] )
     The $r->uri method will return the requested URI minus optional query
     string, optionally changing it with the first argument.

$r->filename( [$filename] )
     The $r->filename method will return the result of the *URI ->
     filename* translation, optionally changing it with the first argument
     if you happen to be doing the translation.

$r->path_info( [$path_info] )
     The $r->path_info method will return what is left in the path after
     the *URI -> filename* translation, optionally changing it with the
     first argument if you happen to be doing the translation.

$r->args( [$query_string] )
     The $r->args method will return the contents of the URI *query
     string*.  When called in a scalar context, the entire string is
     returned.  When called in a list context, a list of parsed key =>
     value pairs are returned, i.e. it can be used like this:

          $query = $r->args;
          %in    = $r->args;

     $r->args can also be used to set the *query string*. This can be
     useful when redirecting a POST request.

$r->headers_in
     The $r->headers_in method will return a %hash of client request
     headers.  This can be used to initialize a perl hash, or one could use
     the $r->header_in() method (described below) to retrieve a specific
     header value directly.

     Will return a HASH reference blessed into the Apache::Table class
     when called in a scalar context with no "key" argument. This requires
     Apache::Table.

$r->header_in( $header_name, [$value] )
     Return the value of a client header.  Can be used like this:

          $ct = $r->header_in("Content-type");
          $r->header_in($key, $val); #set the value of header '$key'

$r->content
     The $r->content method will return the entity body read from the
     client, but only if the request content type is
     `application/x-www-form-urlencoded'.  When called in a scalar
     context, the entire string is returned.  When called in a list
     context, a list of parsed key => value pairs are returned.  *NOTE*:
     you can only ask for this once, as the entire body is read from the
     client.

$r->read($buf, $bytes_to_read, [$offset])
     This method is used to read data from the client, looping until it
     gets all of `$bytes_to_read' or a timeout happens.

     An offset may be specified to place the read data at some other place
     than the beginning of the string.

     In addition, this method sets a timeout before reading with
     `$r->soft_timeout'.

$r->get_remote_host
     Lookup the client's DNS hostname. If the configuration directive
     *HostNameLookups* is set to off, this returns the dotted decimal
     representation of the client's IP address instead. Might return undef
     if the hostname is not known.

$r->get_remote_logname
     Lookup the remote user's system name.  Might return undef if the
     remote system is not running an RFC 1413 server or if the
     configuration directive *IdentityCheck* is not turned on.

   More information about the client can be obtained from the
*Apache::Connection* object, as described below.

$c = $r->connection
     The $r->connection method will return a reference to the request
     connection object (blessed into the *Apache::Connection* package).
     This is really a `conn_rec*' in disguise.  The following methods can
     be used on the connection object:

    $c->remote_host
          If the configuration directive *HostNameLookups* is set to on:
          then the first time `$r->get_remote_host' is called the server
          does a DNS lookup to get the remote client's host name.  The
          result is cached in `$c->remote_host' then returned. If the
          server was unable to resolve the remote client's host name this
          will be set to "". Subsequent calls to `$r->get_remote_host'
          return this cached value.

          If the configuration directive *HostNameLookups* is set to off:
          calls to `$r->get_remote_host' return a string that contains the
          dotted decimal representation of the remote client's IP address.
          However this string is not cached, and `$c->remote_host' is
          undefined. So, it's best to to call `$r->get_remote_host'
          instead of directly accessing this variable.

    $c->remote_ip
          The dotted decimal representation of the remote client's IP
          address.  This is set by the server when the connection record
          is created so is always defined.

          You can also set this value by providing an argument to it. This
          is helpful if your server is behind a squid accelerator proxy
          which adds a X-Forwarded-For header.

    $c->local_addr
          A packed SOCKADDR_IN in the same format as returned by
          `pack_sockaddr_in', see Socket, containing the port
          and address on the local host that the remote client is
          connected to.  This is set by the server when the connection
          record is created so it is always defined.

    $c->remote_addr
          A packed SOCKADDR_IN in the same format as returned by
          `pack_sockaddr_in', see Socket, containing the port
          and address on the remote host that the server is connected to.
          This is set by the server when the connection record is created
          so it is always defined.

          Among other things, this can be used, together with
          `$c->local_addr', to perform RFC1413 ident lookups on the remote
          client even when the configuration directive *IdentityCheck* is
          turned off.

          Can be used like:

               use Net::Ident qw (lookupFromInAddr);
               ...
               my $remoteuser = lookupFromInAddr ($c->local_addr,
                                                  $c->remote_addr, 2);

          Note that the lookupFromInAddr interface does not currently
          exist in the *Net::Ident* module, but the author is planning on
          adding it soon.

    $c->remote_logname
          If the configuration directive *IdentityCheck* is set to on:
          then the first time `$r->get_remote_logname' is called the
          server does an RFC 1413 (ident) lookup to get the remote users
          system name. Generally for UNI* systems this is their login. The
          result is cached in `$c->remote_logname' then returned.
          Subsequent calls to `$r->get_remote_host' return the cached
          value.

          If the configuration directive *IdentityCheck* is set to off:
          then `$r->get_remote_logname' does nothing and
          `$c->remote_logname' is always undefined.

    $c->user( [$user] )
          If an authentication check was successful, the authentication
          handler caches the user name here. Sets the user name to the
          optional first argument.

    $c->auth_type
          Returns the authentication scheme that successfully authenticate
          `$c->user', if any.

    $c->aborted
          Returns true if the client stopped talking to us.

    $c->fileno( [$direction] )
          Returns the client file descriptor. If $direction is 0, the
          input fd is returned. If $direction is not null or ommitted, the
          output fd is returned.

          This can be used to detect client disconnect without doing any
          I/O, e.g. using IO::Select.

SERVER CONFIGURATION INFORMATION
================================

   The following methods are used to obtain information from server
configuration and access control files.

$r->dir_config( $key )
     Returns the value of a per-directory variable specified by the
     PerlSetVar directive.

          # <Location /foo/bar>
          # PerlSetVar  Key  Value
          # </Location>

          my $val = $r->dir_config('Key');

     Keys are case-insensitive.

     Will return a HASH reference blessed into the Apache::Table class
     when called in a scalar context with no "key" argument. See
     Apache::Table.

$r->dir_config->get( $key )
     Returns the value of a per-directory array variable specified by the
     `PerlAddVar' directive.

          # <Location /foo/bar>
          # PerlAddVar  Key  Value1
          # PerlAddVar  Key  Value2
          # </Location>

          my @val = $r->dir_config->get('Key');

     Alternatively in your code you can extend the setting with:

          $r->dir_config->add(Key => 'Value3');

     Keys are case-insensitive.

     Will return a HASH reference blessed into the Apache::Table class
     when called in a scalar context with no "key" argument. See
     Apache::Table.

$r->requires
     Returns an array reference of hash references, containing information
     related to the require directive.  This is normally used for access
     control, see `Apache::AuthzAge' in this node for an example.

$r->auth_type
     Returns a reference to the current value of the per directory
     configuration directive *AuthType*. Normally this would be set to
     Basic to use the basic authentication scheme defined in RFC 1945,
     *Hypertext Transfer Protocol - HTTP/1.0*. However, you could set to
     something else and implement your own authentication scheme.

$r->auth_name
     Returns a reference to the current value of the per directory
     configuration directive *AuthName*.  The AuthName directive creates
     protection realm within the server document space. To quote RFC 1945
     "These realms allow the protected resources on a server to be
     partitioned into a set of protection spaces, each with its own
     authentication scheme and/or authorization database." The client uses
     the root URL of the server to determine which authentication
     credentials to send with each HTTP request. These credentials are
     tagged with the name of the authentication realm that created them.
     Then during the authentication stage the server uses the current
     authentication realm, from `$r->auth_name', to determine which set of
     credentials to authenticate.

$r->document_root
     Returns a reference to the current value of the per server
     configuration directive *DocumentRoot*. To quote the Apache server
     documentation, "Unless matched by a directive like Alias, the server
     appends the path from the requested URL to the document root to make
     the path to the document."  This same value is passed to CGI scripts
     in the DOCUMENT_ROOT environment variable.

$r->allow_options
     The `$r->allow_options' method can be used for checking if it is OK
     to run a perl script.  The *Apache::Options* module provides the
     constants to check against.

          if(!($r->allow_options & OPT_EXECCGI)) {
              $r->log_reason("Options ExecCGI is off in this directory",
          		      $filename);
          }

$r->get_server_port
     Returns the port number on which the server is listening.

$s = $r->server
     Return a reference to the server info object (blessed into the
     *Apache::Server* package).  This is really a `server_rec*' in
     disguise.  The following methods can be used on the server object:

$s = Apache->server
     Same as above, but only available during server startup for use in
     <Perl> sections, *PerlScript* or *PerlModule*.

$s->server_admin
     Returns the mail address of the person responsible for this server.

$s->server_hostname
     Returns the hostname used by this server.

$s->port
     Returns the port that this servers listens too.

$s->is_virtual
     Returns true if this is a virtual server.

$s->names
     Returns the wild-carded names for ServerAlias servers.

$s->dir_config( $key )
     Alias for Apache::dir_config.

$s->warn
     Alias for Apache::warn.

$s->log_error
     Alias for Apache::log_error.

$s->uid
     Returns the numeric user id under which the server answers requests.
     This is the value of the User directive.

$s->gid
     Returns the numeric group id under which the server answers requests.
     This is the value of the Group directive.

$s->loglevel
     Get or set the value of the current LogLevel. This method is added by
     the Apache::Log module, which needs to be pulled in.

          use Apache::Log;
          print "LogLevel = ", $s->loglevel;
          $s->loglevel(Apache::Log::DEBUG);

     If using Perl 5.005+, the following constants are defined (but not
     exported):

          Apache::Log::EMERG
          Apache::Log::ALERT
          Apache::Log::CRIT
          Apache::Log::ERR
          Apache::Log::WARNING
          Apache::Log::NOTICE
          Apache::Log::INFO
          Apache::Log::DEBUG

$r->get_handlers( $hook )
     Returns a reference to a list of handlers enabled for $hook. $hook is
     a string representing the phase to handle. The returned list is a list
     of references to the handler subroutines.

          $list = $r->get_handlers( 'PerlHandler' );

$r->set_handlers( $hook, [\&handler, ... ] )
     Sets the list if handlers to be called for $hook. $hook is a string
     representing the phase to handle. The list of handlers is an anonymous
     array of code references to the handlers to install for this request
     phase. The special list [ \&OK ] can be used to disable a particular
     phase.

          $r->set_handlers( PerlLogHandler => [ \&myhandler1, \&myhandler2 ] );
          $r->set_handlers( PerlAuthenHandler => [ \&OK ] );

$r->push_handlers( $hook, \&handler )
     Pushes a new handler to be called for $hook. $hook is a string
     representing the phase to handle. The handler is a reference to a
     subroutine to install for this request phase. This handler will be
     called before any configured handlers.

          $r->push_handlers( PerlHandler => \&footer);

SETTING UP THE RESPONSE
=======================

   The following methods are used to set up and return the response back
to the client.  This typically involves setting up $r->status(), the
various content attributes and optionally some additional $r->header_out()
calls before calling $r->send_http_header() which will actually send the
headers to the client.  After this a typical application will call the
$r->print() method to send the response content to the client.

$r->send_http_header( [$content_type] )
     Send the response line and all headers to the client.  Takes an
     optional parameter indicating the content-type of the response, i.e.
     'text/html'.

     This method will create headers from the $r->content_xxx() and
     $r->no_cache() attributes (described below) and then append the
     headers defined by $r->header_out (or $r->err_header_out if status
     indicates an error).

$r->get_basic_auth_pw
     If the current request is protected by Basic authentication, this
     method will return 0, otherwise -1.  The second return value will be
     the decoded password sent by the client.

          ($ret, $sent_pw) = $r->get_basic_auth_pw;

$r->note_basic_auth_failure
     Prior to requiring Basic authentication from the client, this method
     will set the outgoing HTTP headers asking the client to authenticate
     for the realm defined by the configuration directive `AuthName'.

$r->handler( [$meth] )
     Set the handler for a request.  Normally set by the configuration
     directive `AddHandler'.

          $r->handler( "perl-script" );

$r->notes( $key, [$value] )
     Return the value of a named entry in the Apache notes table, or
     optionally set the value of a named entry.  This table is used by
     Apache modules to pass messages amongst themselves. Generally if you
     are writing handlers in mod_perl you can use Perl variables for this.

          $r->notes("MY_HANDLER" => OK);
          $val = $r->notes("MY_HANDLER");

     Will return a HASH reference blessed into the Apache::Table class
     when called in a scalar context with no "key" argument. This requires
     Apache::Table.

$r->pnotes( $key, [$value] )
     Like $r->notes, but takes any scalar as an value.

          $r->pnotes("MY_HANDLER" => [qw(one two)]);
          my $val = $r->pnotes("MY_HANDLER");
          print $val->[0];     # prints "one"

     Advantage over just using a Perl variable is that $r->pnotes gets
     cleaned up after every request.

$r->subprocess_env( $key, [$value] )
     Return the value of a named entry in the Apache `subprocess_env'
     table, or optionally set the value of a named entry. This table is
     used by mod_include.  By setting some custom variables inside a perl
     handler it is possible to combine perl with mod_include nicely.  If
     you say, e.g. in a PerlHeaderParserHandler

          $r->subprocess_env(MyLanguage => "de");

     you can then write in your .shtml document:

          <!--#if expr="$MyLanguage = en" -->
          English
          <!--#elif expr="$MyLanguage = de" -->
          Deutsch
          <!--#else -->
          Sorry
          <!--#endif -->

     Will return a HASH reference blessed into the Apache::Table class
     when called in a scalar context with no "key" argument. This requires
     Apache::Table.

$r->content_type( [$newval] )
     Get or set the content type being sent to the client.  Content types
     are strings like "text/plain", "text/html" or "image/gif".  This
     corresponds to the "Content-Type" header in the HTTP protocol.
     Example of usage is:

          $previous_type = $r->content_type;
          $r->content_type("text/plain");

$r->content_encoding( [$newval] )
     Get or set the content encoding.  Content encodings are string like
     "gzip" or "compress".  This correspond to the "Content-Encoding"
     header in the HTTP protocol.

$r->content_languages( [$array_ref] )
     Get or set the content languages.  The content language corresponds
     to the "Content-Language" HTTP header and is an array reference
     containing strings such as "en" or "no".

$r->status( $integer )
     Get or set the reply status for the client request.  The
     *Apache::Constants* module provide mnemonic names for the status
     codes.

$r->status_line( $string )
     Get or set the response status line.  The status line is a string like
     "200 Document follows" and it will take precedence over the value
     specified using the $r->status() described above.

$r->headers_out
     The $r->headers_out method will return a %hash of server response
     headers.  This can be used to initialize a perl hash, or one could use
     the $r->header_out() method (described below) to retrieve or set a
     specific header value directly.

     Will return a HASH reference blessed into the Apache::Table class
     when called in a scalar context with no "key" argument. This requires
     Apache::Table.

$r->header_out( $header, $value )
     Change the value of a response header, or create a new one.  You
     should not define any "Content-XXX" headers by calling this method,
     because these headers use their own specific methods.  Example of use:

          $r->header_out("WWW-Authenticate" => "Basic");
          $val = $r->header_out($key);

$r->err_headers_out
     The $r->err_headers_out method will return a %hash of server response
     headers.  This can be used to initialize a perl hash, or one could use
     the $r->err_header_out() method (described below) to retrieve or set
     a specific header value directly.

     The difference between headers_out and err_headers_out is that the
     latter are printed even on error, and persist across internal
     redirects (so the headers printed for ErrorDocument handlers will
     have them).

     Will return a HASH reference blessed into the Apache::Table class
     when called in a scalar context with no "key" argument. This requires
     Apache::Table.

$r->err_header_out( $header, [$value] )
     Change the value of an error response header, or create a new one.
     These headers are used if the status indicates an error.

          $r->err_header_out("Warning" => "Bad luck");
          $val = $r->err_header_out($key);

$r->no_cache( $boolean )
     This is a flag that indicates that the data being returned is volatile
     and the client should be told not to cache it.

$r->print( @list )
     This method sends data to the client with `$r->write_client', but
     first sets a timeout before sending with `$r->soft_timeout'. This
     method is called instead of CORE::print when you use print() in your
     mod_perl programs.

     This method treats scalar references specially. If an item in @list
     is a scalar reference, it will be dereferenced before printing. This
     is a performance optimization which prevents unneeded copying of
     large strings, and it is subtly different from Perl's standard
     print() behavior.

     Example:

          $foo = \"bar"; print($foo);

     The result is "bar", not the "SCALAR(0xDEADBEEF)" you might have
     expected. If you really want the reference to be printed out, force
     it into a scalar context by using `print(scalar($foo))'.

$r->send_fd( $filehandle )
     Send the contents of a file to the client.  Can for instance be used
     like this:

          open(FILE, $r->filename) || return 404;
          $r->send_fd(FILE);
          close(FILE);

$r->internal_redirect( $newplace )
     Redirect to a location in the server namespace without telling the
     client. For instance:

          $r->internal_redirect("/home/sweet/home.html");

$r->internal_redirect_handler( $newplace )
     Same as *internal_redirect*, but the handler from $r is preserved.

$r->custom_response($code, $uri)
     This method provides a hook into the *ErrorDocument* mechanism,
     allowing you to configure a custom response for a given response code
     at request-time.

     Example:

          use Apache::Constants ':common';

          sub handler {
              my($r) = @_;

          if($things_are_ok) {
          	    return OK;
          }

          #<Location $r->uri>
          #ErrorDocument 401 /error.html
          #</Location>

          $r->custom_response(AUTH_REQUIRED, "/error.html");

          #can send a string too
          #<Location $r->uri>
          #ErrorDocument 401 "sorry, go away"
          #</Location>

          #$r->custom_response(AUTH_REQUIRED, "sorry, go away");

          return AUTH_REQUIRED;
              }

SERVER CORE FUNCTIONS
=====================

$r->soft_timeout($message)
$r->hard_timeout($message)
$r->kill_timeout
$r->reset_timeout
     (Documentation borrowed from http_main.h)

     There are two functions which modules can call to trigger a timeout
     (with the per-virtual-server timeout duration); these are hard_timeout
     and soft_timeout.

     The difference between the two is what happens when the timeout
     expires (or earlier than that, if the client connection aborts) -- a
     soft_timeout just puts the connection to the client in an "aborted"
     state, which will cause http_protocol.c to stop trying to talk to the
     client, but otherwise allows the code to continue normally.
     hard_timeout(), by contrast, logs the request, and then aborts it
     completely -- longjmp()ing out to the accept() loop in http_main.
     Any resources tied into the request resource pool will be cleaned up;
     everything that is not will leak.

     soft_timeout() is recommended as a general rule, because it gives your
     code a chance to clean up.  However, hard_timeout() may be the most
     convenient way of dealing with timeouts waiting for some external
     resource other than the client, if you can live with the restrictions.

     When a hard timeout is in scope, critical sections can be guarded
     with block_alarms() and unblock_alarms() -- these are declared in
     alloc.c because they are most often used in conjunction with routines
     to allocate something or other, to make sure that the cleanup does
     get registered before any alarm is allowed to happen which might
     require it to be cleaned up; they * are, however, implemented in
     http_main.c.

     kill_timeout() will disarm either variety of timeout.

     reset_timeout() resets the timeout in progress.

$r->post_connection($code_ref)
$r->register_cleanup($code_ref)
     Register a cleanup function which is called just before $r->pool is
     destroyed.

          $r->register_cleanup(sub {
              my $r = shift;
              warn "registered cleanup called for ", $r->uri, "\n";
          });

     Cleanup functions registered in the parent process (before forking)
     will run once when the server is shut down:

          #PerlRequire startup.pl
          warn "parent pid is $$\n";
          Apache->server->register_cleanup(sub { warn "server cleanup in $$\n"});

     The *post_connection* method is simply an alias for
     *register_cleanup*, as this method may be used to run code after the
     client connection is closed, which may not be a cleanup.

CGI SUPPORT
===========

   We also provide some methods that make it easier to support the CGI
type of interface.

$r->send_cgi_header()
     Take action on certain headers including *Status:*, *Location:* and
     *Content-type:* just as mod_cgi does, then calls
     $r->send_http_header().  Example of use:

          $r->send_cgi_header(<<EOT);
          Location: /foo/bar
          Content-type: text/html

          EOT

ERROR LOGGING
=============

   The following methods can be used to log errors.

$r->log_reason($message, $file)
     The request failed, why??  Write a message to the server errorlog.

          $r->log_reason("Because I felt like it", $r->filename);

$r->log_error($message)
     Uh, oh.  Write a message to the server errorlog.

          $r->log_error("Some text that goes in the error_log");

$r->warn($message)
     For pre-1.3 versions of apache, this is just an alias for log_error.
     With 1.3+ versions of apache, this message will only be send to the
     error_log if *LogLevel* is set to warn or higher.

UTILITY FUNCTIONS
=================

Apache::unescape_url($string)
     Handy function for unescapes.  Use this one for filenames/paths.  Use
     unescape_url_info for the result of submitted form data.

Apache::unescape_url_info($string)
     Handy function for unescapes submitted form data.  In opposite to
     unescape_url it translates the plus sign to space.

Apache::perl_hook($hook)
     Returns true if the specified callback hook is enabled:

          for (qw(Access Authen Authz ChildInit Cleanup Fixup
                  HeaderParser Init Log Trans Type))
          {
              print "$_ hook enabled\n" if Apache::perl_hook($_);
          }

GLOBAL VARIABLES
================

$Apache::Server::Starting
     Set to true when the server is starting.

$Apache::Server::ReStarting
     Set to true when the server is starting.

SEE ALSO
========

   perl(1), Apache::Constants(3), Apache::Registry(3), Apache::Debug(3),
Apache::Options(3), CGI::Apache(3)

   Apache C API notes at `http://www.apache.org/docs/'

AUTHORS
=======

   Perl interface to the Apache C API written by Doug MacEachern with
contributions from Gisle Aas, Andreas Koenig, Eric Bartley, Rob Hartill,
Gerald Richter, Salvador Ortiz and others.

Active Server Pages for Apache with mod_perl
********************************************

NAME
====

     Apache::ASP - Active Server Pages for Apache with mod_perl

SYNOPSIS
========

     SetHandler perl-script
     PerlHandler Apache::ASP
     PerlSetVar Global /tmp/asp

DESCRIPTION
===========

   Apache::ASP provides an Active Server Pages port to the Apache Web
Server with Perl scripting only, and enables developing of dynamic web
applications with session management and embedded perl code.  There are
also many powerful extensions, including XML taglibs, XSLT rendering, and
new events not originally part of the ASP API!

   <table><tr><td>

   <b>Apache::ASP's features include:</b>

   <ul> <li> Natural and Powerful Scripting SYNTAX <li> Rich OBJECTS
Developer API <li> Web Application EVENTS Model <li> Modular SSI
Decomposition, Code Sharing <li> User SESSIONS, NFS Web Cluster Friendly
<li> XML/XSLT Rendering & Custom Tag Technology <li> CGI Compatibility
<li> PERLSCRIPT Compatibility <li> Great Open Source SUPPORT </ul>

   </table>

   This module works under the Apache Web Server with the mod_perl module
enabled. See http://www.apache.org and http://perl.apache.org for further
information.

   This is a portable solution, similar to ActiveState's PerlScript for
NT/IIS ASP.  Work has been done and will continue to make ports to and
from this implementation as smooth as possible.

   For Apache::ASP downloading and installation, please read the INSTALL
section.  For installation troubleshooting check the FAQ and the SUPPORT
sections.

   For database access, ActiveX, scripting languages, and other
miscellaneous issues please read the FAQ section.

WEBSITE
=======

   The Apache::ASP web site is at http://www.apache-asp.org/ which you can
also find in the ./site directory of the source distribution.

INSTALL
=======

   The latest Apache::ASP can be found at your nearest CPAN, and also:

     http://download.sourceforge.net/mirrors/CPAN/modules/by-module/Apache/
     ftp://ftp.duke.edu/pub/perl/modules/by-module/Apache/
     http://www.perl.com/CPAN-local/modules/by-module/Apache/

   As a perl user, you should make yourself familiar with the CPAN.pm
module, and how it may be used to install Apache::ASP, and other related
modules.

   Once you have downloaded it, Apache::ASP installs easily using the make
or nmake commands as shown below.  Otherwise, just copy ASP.pm to
$PERLLIB/site/Apache

     > perl Makefile.PL
     > make
     > make test
     > make install

     * use nmake for win32

   Please note that you must first have the Apache Web Server & mod_perl
installed before using this module in a web server environment.  The
offline mode for building static html may be used with just perl.

Need Help
---------

   Often, installing the mod_perl part of the Apache server can be the
hardest part.  If this is the case for you, check out the FAQ and SUPPORT
sections for further help.

RedHat Issues
-------------

   If you have a RedHat Linux server with an RPM style Apache + mod_perl,
seriously consider building a static version of the httpd server yourself,
not DSO.  DSO is marked as experimental for mod_perl, and often does not
work, resulting in "no request object" error messages.

Quick Start
-----------

   Once you have successfully built the Apache Web Server with mod_perl,
copy the ./site/eg/ directory from the Apache::ASP installation to your
Apache document tree and try it out!  You must put "AllowOverride All" in
your httpd.conf <Directory> config section to let the .htaccess file in the
./site/eg installation directory do its work.  If you want a starter
config file for Apache::ASP, just look at the .htaccess file in the
./site/eg/ directory.

   You will know that Apache::ASP is working normally if you can run the
scripts in ./site/eg/ without any errors.

CONFIG
======

   You may use a generic <Location> directive in your httpd.conf Apache
configuration file to make Apache::ASP start ticking.  Configure the
optional setting if you want, the defaults are fine to get started.  The
settings are documented below.  Make sure Global is set to where your web
applications global.asa is if you have one!

     <Location /asp/>
      SetHandler perl-script
      PerlHandler Apache::ASP
      PerlSetVar Global /tmp
     </Location>

   NOTE: do not use this for the examples in ./site/eg.  To get the
examples working, check out the Quick Start section of INSTALL

   You may also use the <Files ~ (\.asp)> tag in the httpd.conf Apache
configuration file or .htaccess, which allows a developer to mix other
file types in the application, static or otherwise.  This method is more
natural for ASP coding, with mixed media per directory.

Core
----

Global
     Global is the nerve center of an ASP application, in which the
     global.asa may reside, which defines the web application's event
     handlers.

     This directory is pushed onto @INC, you will be able to "use" and
     "require" files in this directory, so perl modules developed for this
     application may be dropped into this directory, for easy use.

     Unless StateDir is configured, this directory must be some writeable
     directory by the web server.  $Session and $Application object state
     files will be stored in this directory.  If StateDir is configured,
     then ignore this paragraph, as it overrides the Global directory for
     this purpose.

     Includes, specified with <!-#include file=somefile.inc-> or
     $Response->Include() syntax, may also be in this directory, please
     see section on includes for more information.

          PerlSetVar Global /tmp

GlobalPackage
     Perl package namespace that all scripts, includes, & global.asa
     events are compiled into.  By default, GlobalPackage is some obscure
     name that is uniquely generated from the file path of the Global
     directory, and global.asa file.  The use of explicitly naming the
     GlobalPackage is to allow scripts access to globals and subs defined
     in a perl module that is included with commands like:

          in perl script: use Some::Package;
          in apache conf: PerlModule Some::Package

          PerlSetVar GlobalPackage Some::Package

UniquePackages
     default 0.  Set to 1 to emulate pre-v.10 ASP script compilation
     behavior, which compiles each script into its own perl package.

     Before v.10, ASP scripts were compiled into their own perl package
     namespace.  This allowed ASP scripts in the same ASP application to
     defined subroutines of the same name without a problem.

     As of v.10, ASP scripts in a web application are compiled into the
     *same* perl package by default, so these scripts, their includes, and
     the global.asa events all share common globals & subroutines defined
     by each other.  The problem for some developers was that they would
     at times define a subroutine of the same name in 2+ scripts, and one
     subroutine definition would redefine the other one because of the
     namespace collision.

          PerlSetVar UniquePackages 0

DynamicIncludes
     default 0.  SSI file includes are normally inlined in the calling
     script, and the text gets compiled with the script as a whole.  With
     this option set to TRUE, file includes are compiled as a separate
     subroutine and called when the script is run.  The advantage of
     having this turned on is that the code compiled from the include can
     be shared between scripts, which keeps the script sizes smaller in
     memory, and keeps compile times down.

          PerlSetVar DynamicIncludes 0

IncludesDir
     no defaults.  If set, this directory will also be used to look for
     includes when compiling scripts.  By default the directory the script
     is in, and the Global directory are checked for includes.

     This extension was added so that includes could be easily shared
     between ASP applications, whereas placing includes in the Global
     directory only allows sharing between scripts in an application.

          PerlSetVar IncludesDir .

State Management
----------------

NoState
     default 0, if true, neither the $Application nor $Session objects will
     be created.  Use this for a performance increase.  Please note that
     this setting takes precedence over the AllowSessionState and
     AllowApplicationState settings.

          PerlSetVar NoState 0

AllowSessionState
     Set to 0 for no session tracking, 1 by default If Session tracking is
     turned off, performance improves, but the $Session object is
     inaccessible.

          PerlSetVar AllowSessionState 1

     Note that if you want to dissallow session creation for certain non
     web browser user agents, like search engine spiders, you can use an
     init handler like:

          PerlInitHandler "sub { $_[0]->dir_config('AllowSessionState', 0) }"

AllowApplicationState
     Default 1.  If you want to leave $Application undefined, then set this
     to 0, for a performance increase of around 2-3%.  Allowing use of
     $Application is less expensive than $Session, as there is more work
     for the StateManager associated with $Session garbage collection so
     this parameter should be only used for extreme tuning.

          PerlSetVar AllowApplicationState 1

StateDir
     default $Global/.state.  State files for ASP application go to this
     directory.  Where the state files go is the most important
     determinant in what makes a unique ASP application.  Different
     configs pointing to the same StateDir are part of the same ASP
     application.

     The default has not changed since implementing this config directive.
     The reason for this config option is to allow operating systems with
     caching file systems like Solaris to specify a state directory
     separately from the Global directory, which contains more permanent
     files.  This way one may point StateDir to /tmp/myaspapp, and make
     one's ASP application scream with speed.

          PerlSetVar StateDir ./.state

StateManager
     default 10, this number specifies the numbers of times per
     SessionTimeout that timed out sessions are garbage collected.  The
     bigger the number, the slower your system, but the more precise
     Session_OnEnd's will be run from global.asa, which occur when a timed
     out session is cleaned up, and the better able to withstand Session
     guessing hacking attempts.  The lower the number, the faster a normal
     system will run.

     The defaults of 20 minutes for SessionTimeout and 10 times for
     StateManager, has dead Sessions being cleaned up every 2 minutes.

          PerlSetVar StateManager 10

StateDB
     default SDBM_File, this is the internal database used for state
     objects like $Application and $Session.  Because an %sdbm_file hash
     has a limit on the size of a record / key value pair, usually 1024
     bytes, you may want to use another tied database like DB_File.

     With lightweight $Session and $Application use, you can get away with
     SDBM_File, but if you load it up with complex data like
     $Session{key} = { # very large complex object } you might max out the
     1024 limit.

     Currently StateDB can only be: SDBM_File, DB_File Please let me know
     if you would like to add any more to this list.

     As of version .18, you may change this setting in a live production
     environment, and new state databases created will be of this format.
     With a prior version if you switch to a new StateDB, you would want to
     delete the old StateDir, as there will likely be incompatibilities
     between the different database formats, including the way garbage
     collection is handled.

          PerlSetVar StateDB SDBM_File

StateCache
     Default 0, set to 1 for lock files that are acquired for $Application
     and an internal database used for session management to be cached and
     held open between requests, for up to a 10% performance gain.  Per
     ASP application this is will keep up to 2 extra file handles open per
     httpd process, one for the internal database, and one for
     $Application.

     The only problem with this caching is that you can only delete the
     StateDir if you have first shutdown the web server, as the lock files
     will not be recreated between requests.  Not that you should be
     deleting your StateDir anyway, but if you are, there is more to worry
     about.

          PerlSetVar StateCache 0

StateSerializer
     default Data::Dumper, you may set this to Storable for faster
     serialization and storage of data into state objects.  This is
     particularly useful when storing large objects in $Session and
     $Application, as the Storable.pm module has a faster implementation
     of freezing and thawing data from and to perl structures.  Note that
     if you are storing this much data in your state databases, you may
     want to use DB_File since it does not have the default 1024 byte limit
     that SDBM_File has on key/value lengths.

     This configuration setting may be changed in production as the state
     database's serializer type is stored in the internal state manager
     which will always use Data::Dumper & SDBM_File to store data.

          PerlSetVar StateSerializer Data::Dumper

Sessions
--------

CookiePath
     URL root that client responds to by sending the session cookie.  If
     your asp application falls under the server url "/asp", then you
     would set this variable to /asp.  This then allows you to run
     different applications on the same server, with different user
     sessions for each application.

          PerlSetVar CookiePath /

SessionTimeout
     Default 20 minutes, when a user's session has been inactive for this
     period of time, the Session_OnEnd event is run, if defined, for that
     session, and the contents of that session are destroyed.

          PerlSetVar SessionTimeout 20

SecureSession
     default 0.  Sets the secure tag for the session cookie, so that the
     cookie will only be transmitted by the browser under https
     transmissions.

          PerlSetVar SecureSession 1

ParanoidSession
     default 0.  When true, stores the user-agent header of the browser
     that creates the session and validates this against the session
     cookie presented.  If this check fails, the session is killed, with
     the rationale that there is a hacking attempt underway.

     This config option was implemented to be a smooth upgrade, as you can
     turn it off and on, without disrupting current sessions.  Sessions
     must be created with this turned on for the security to take effect.

     This config option is to help prevent a brute force cookie search from
     being successful. The number of possible cookies is huge, 2^128, thus
     making such a hacking attempt VERY unlikely.  However, on the off
     chance that such an attack is successful, the hacker must also
     present identical browser headers to authenticate the session, or the
     session will be destroyed.  Thus the User-Agent acts as a backup to
     the real session id.  The IP address of the browser cannot be used,
     since because of proxies, IP addresses may change between requests
     during a session.

     There are a few browsers that will not present a User-Agent header.
     These browsers are considered to be browsers of type "Unknown", and
     this method works the same way for them.

     Most people agree that this level of security is unnecessary, thus it
     is titled paranoid :)

          PerlSetVar ParanoidSession 0

SessionSerialize
     default 0, if true, locks $Session for duration of script, which
     serializes requests to the $Session object.  Only one script at a
     time may run, per user $Session, with sessions allowed.

     Serialized requests to the session object is the Microsoft ASP way,
     but is dangerous in a production environment, where there is risk of
     long-running or run-away processes.  If these things happen, a
     session may be locked for an indefinite period of time.  A user STOP
     button should safely quit the session however.

          PerlSetVar SessionSerialize 0

Cookieless Sessions
-------------------

SessionQueryParse
     default 0, if true, will automatically parse the $Session session id
     into the query string of each local URL found in the $Response
     buffer.  For this setting to work therefore, buffering must be
     enabled.  This parsing will only occur when a session cookie has not
     been sent by a browser, so the first script of a session enabled
     site, and scripts viewed by web browsers that have cookies disabled
     will trigger this behavior.

     Although this runtime parsing method is computationally expensive,
     this cost should be amortized across most users that will not need
     this URL parsing.  This is a lazy programmer's dream.  For something
     more efficient, look at the SessionQuery setting.  For more
     information about this solution, please read the SESSIONS section.

          PerlSetVar SessionQueryParse 0

SessionQueryParseMatch
     default 0, set to a regexp pattern that matches all URLs that you
     want to have SessionQueryParse parse in session ids.  By default
     SessionQueryParse only modifies local URLs, but if you name your URLs
     of your site with absolute URLs like http://localhost then you will
     need to use this setting.  So to match http://localhost URLs, you
     might set this pattern to ^http://localhost.  Note that by setting
     this config, you are also setting SessionQueryParse.

          PerlSetVar SessionQueryParseMatch ^https?://localhost

SessionQuery
     default 0, if set, the session id will be initialized from the
     $Request->QueryString if not first found as a cookie.  You can use
     this setting coupled with the

          $Server->URL($url, \%params)

     API extension to generate local URLs with session ids in their query
     strings, for efficient cookieless session support.  Note that if a
     browser has cookies disabled, every URL to any page that needs access
     to $Session will need to be created by this method, unless you are
     using SessionQueryParse which will do this for you automatically.

          PerlSetVar SessionQuery 0

SessionQueryMatch
     default 0, set to a regexp pattern that will match URLs for
     $Server->URL() to add a session id to.  SessionQuery normally allows
     $Server->URL() to add session ids just to local URLs, so if you use
     absolute URL references like http://localhost/ for your web site,
     then just like with SessionQueryParseMatch, you might set this pattern
     to ^http://localhost

     If this is set, then you don't need to set SessionQuery, as it will
     be set automatically.

          PerlSetVar SessionQueryMatch ^http://localhost

Developer Environment
---------------------

UseStrict
     default 0, if set to 1, will compile all scripts, global.asa and
     includes with "use strict;" inserted at the head of the file, saving
     you from the painful process of strictifying code that was not strict
     to begin with.

     Because of how essential "use strict" programming is in a mod_perl
     environment, this default might be set to 1 one day, but this will be
     up for discussion before that decision is made.

     Note too that errors triggered by "use strict" are now captured as
     part of the normal Apache::ASP error handling when this configuration
     is set, otherwise "use strict" errors will not be handled properly, so
     using UseStrict is better than your own "use strict" statements.

     PerlSetVar UseStrict 1

Debug
     1 for server log debugging, 2 for extra client html output Use 1 for
     production debugging, use 2 for development.  Turn off if you are not
     debugging.

          PerlSetVar Debug 2

DebugBufferLength
     Default 100, set this to the number of bytes of the buffered output's
     tail you want to see when an error occurs and Debug 2 or MailErrorsTo
     is set, and when BufferingOn is enabled.

     With buffering the script output will not naturally show up when the
     script errors, as it has been buffered by the $Response object.  It
     helps to see where in the script output an error halted the script,
     so the last bytes of the buffered output are included with the rest of
     the debugging information.

     For a demo of this functionality, try the ./site/eg/syntax_error.htm
     script, and turn buffering on.

PodComments
     default 1.  With pod comments turned on, perl pod style comments and
     documentation are parsed out of scripts at compile time.  This make
     for great documentation and a nice debugging tool, and it lets you
     comment out perl code and html in blocks.  Specifically text like
     this:

          =pod
          text or perl code here
          =cut

     will get ripped out of the script before compiling.  The =pod and =cut
     perl directives must be at the beginning of the line, and must be
     followed by the end of the line.

          PerlSetVar PodComments 1

CollectionItem
     Enables PerlScript syntax like:

          $Request->Form('var')->Item;
          $Request->Form('var')->Item(1);
          $Request->Form('var')->Count;

     Old PerlScript syntax, enabled with

          use Win32::OLE qw(in valof with OVERLOAD);

     is like native syntax

          $Request->Form('var');

     Only in Apache::ASP, can the above be written as:

          $Request->{Form}{var};

     which you would do if you _really_ needed the speed.

XML / XSLT
----------

XMLSubsMatch
     default not defined, set to some regexp pattern that will match all
     XML and HTML tags that you want to have perl subroutines handle.  The
     is Apache::ASP's custom tag technology, and can be used to create
     powerful extensions to your XML and HTML rendering.

     Please see XML/XSLT section for instructions on its use.

          PerlSetVar XMLSubsMatch ^my:

XMLSubsStrict
     default 0, when set XMLSubs will only take arguments that are
     properly formed XML tag arguments like:

          <my:sub arg1="value" arg2="value"/>

     By default, XMLSubs accept arbitrary perl code as argument values:

          <my:sub arg1=1+1 arg2=&perl_sub()/>

     which is not always wanted or expected.  Set XMLSubsStrict to 1 if
     this is the case.

XSLT
     default not defined, if set to a file, ASP scripts will be regarded
     as XML output and transformed with the given XSL file with XML::XSLT.
     This XSL file will also be executed as an ASP script first, and its
     output will be the XSL data used for the transformation.  This XSL
     file will be executed as a dynamic include, so may be located in the
     current directory, Global, or IncludesDir.

     Please see the XML/XSLT section for an explanation of its use.

          PerlSetVar XSLT template.xsl

XSLTMatch
     default .*, if XSLT is set by default all ASP scripts will be XSL
     transformed by the specified XSL template.  This regexp setting will
     tell XSLT which file names to match with doing XSL transformations,
     so that regular HTML ASP scripts and XML ASP scripts can be configured
     with the same configuration block.  Please see ./site/eg/.htaccess
     for an example of its use.

          PerlSetVar XSLTMatch \.xml$

XSLTCacheSize
     default 0, if set greater than 0, will cache that many XML and XSL
     parsed objects and their transformations' output.  XML::XSLT
     transformations are computationally expensive, requiring first XML
     DOM objects be created from the XML & XSL outputs, and then the final
     XSLT rendering is non-trivial too, so every effort is made to cache
     various steps in the process for enormous speed benefits if the same
     XML / XSL combination is being hit on the same web server process.

     Efforts will be made in the future to provide a mechanism for
     pre-caching these computations at server startup prefork so that they
     may be shared with the child Apache httpds.

     This setting requires that Tie::Cache be first installed.

          PerlSetVar XSLTCacheSize 100

Miscellaneous
-------------

AuthServerVariables
     default 0. If you are using basic auth and would like
     $Request->ServerVariables set like AUTH_TYPE, AUTH_USER, AUTH_NAME,
     REMOTE_USER, & AUTH_PASSWD, then set this and Apache::ASP will
     initialize these values from Apache->*auth* commands.  Use of these
     environment variables keeps applications cross platform compatible as
     other servers set these too when performing basic 401 auth.

          PerlSetVar AuthServerVariables 0

BufferingOn
     default 1, if true, buffers output through the response object.
     $Response object will only send results to client browser if a
     $Response->Flush() is called, or if the asp script ends.  Lots of
     output will need to be flushed incrementally.

     If false, 0, the output is immediately written to the client, CGI
     style.  There will be a performance hit server side if output is
     flushed automatically to the client, but is probably small.

     I would leave this on, since error handling is poor, if your asp
     script errors after sending only some of the output.

          PerlSetVar BufferingOn 1

StatINC
     default 0, if true, reloads perl libraries that have changed on disk
     automatically for ASP scripts.  If false, the www server must be
     restarted for library changes to take effect.

     A known bug is that any functions that are exported, e.g. confess
     Carp qw(confess), will not be refreshed by StatINC.  To refresh
     these, you must restart the www server.

     This setting should be used in development only because it is so slow.
     For a production version of StatINC, see StatINCMatch.

          PerlSetVar StatINC 1

StatINCMatch
     default undef, if defined, it will be used as a regular expression to
     reload modules that match as in StatINC.  This is useful because
     StatINC has a very high performance penalty in production, so if you
     can narrow the modules that are checked for reloading each script
     execution to a handful, you will only suffer a mild performance
     penalty.

     The StatINCMatch setting should be a regular expression like:
     Struct|LWP which would match on reloading Class/Struct.pm, and all
     the LWP/.* libraries.

     If you define StatINCMatch, you do not need to define StatINC.

          PerlSetVar StatINCMatch .*

StatScripts
     default 1, if set to 0, changed scripts, global.asa, and includes
     will not be reloaded.  Coupled with Apache mod_perl startup and
     restart handlers executing Apache::ASP->Loader() for your application
     this allows your application to be frozen, and only reloaded on the
     next server restart or stop/start.

     There are a few advantages for not reloading scripts and modules in
     production.  First there is a slight performance improvement by not
     having to stat() the script, its includes and the global.asa every
     request.

     From an application deployment standpoint, you also gain the ability
     to deploy your application as a snapshot taken when the server starts
     and restarts.  This provides you with the reassurance that during a
     production server update from development sources, you do not have to
     worry with sources being used for the wrong libraries and such, while
     they are all being copied over.

     Finally, though you really should not do this, you can work on a live
     production application, with a test server reloading changes, but
     your production server does see the changes until you restart or
     stop/start it.  This saves your public from syntax errors while you
     are just doing a quick bug fix.

          PerlSetVar StatScripts 1

SoftRedirect
     default 0, if true, a $Response->Redirect() does not end the script.
     Normally, when a Redirect() is called, the script is ended
     automatically.  SoftRedirect 1, is a standard way of doing redirects,
     allowing for html output after the redirect is specified.

          PerlSetVar SoftRedirect 0

Filter
     On/Off, default Off.  With filtering enabled, you can take advantage
     of full server side includes (SSI), implemented through Apache::SSI.
     SSI is implemented through this mechanism by using Apache::Filter.  A
     sample configuration for full SSI with filtering is in the
     ./site/eg/.htaccess file, with a relevant example script
     ./site/eg/ssi_filter.ssi.

     You may only use this option with modperl v1.16 or greater installed
     and PERL_STACKED_HANDLERS enabled.  Filtering may be used in
     conjunction with other handlers that are also "filter aware".  If in
     doubt, try building your mod_perl with

          perl Makefile.PL EVERYTHING=1

     With filtering through Apache::SSI, you should expect near a a 20%
     performance decrease.

          PerlSetVar Filter Off

CgiHeaders
     default 0.  When true, script output that looks like HTTP / CGI
     headers, will be added to the HTTP headers of the request.  So you
     could add:   Set-Cookie: test=message

     <html>...  to the top of your script, and all the headers preceding a
     newline will be added as if with a call to $Response->AddHeader().
     This functionality is here for compatibility with raw cgi scripts,
     and those used to this kind of coding.

     When set to 0, CgiHeaders style headers will not be parsed from the
     script response.

          PerlSetVar CgiHeaders 0

Clean
     default 0, may be set between 1 and 9.  This setting determine how
     much text/html output should be compressed.  A setting of 1 strips
     mostly white space saving usually 10% in output size, at a
     performance cost of less than 5%.  A setting of 9 goes much further
     saving anywhere 25% to 50% typically, but with a performance hit of
     50%.

     This config option is implemented via HTML::Clean.  Per script
     configuration of this setting is available via the $Response->{Clean}
     property, which may also be set between 0 and 9.

          PerlSetVar Clean 0

CompressGzip
     default 0, if true will gzip compress HTML output on the fly if
     Compress::Zlib is installed, and the client browser supports it.
     Depending on the HTML being compressed, the client may see a 50% to
     90% reduction in HTML output.  I have seen 40K of HTML squeezed down
     to just under 6K.  This will come at a 5%-20% hit to CPU usage per
     request compressed.

     Note there are some cases when a browser says it will accept gzip
     encoding, but then not render it correctly.  This behavior has been
     seen with IE5 when set to use a proxy but not using a proxy, and the
     URL does not end with a .html or .htm.  No work around has yet been
     found for this case so use at your own risk.

          PerlSetVar CompressGzip 1

FormFill
     default 0, if true will auto fill HTML forms with values from
     $Request->Form().  This functionality is provided by use of
     HTML::FillInForm.  For more information please see "perldoc
     HTML::FillInForm", and the example ./site/eg/formfill.asp.

     This feature can be enabled on a per form basis at runtime with
     $Response->{FormFill} = 1

          PerlSetVar FormFill 1

TimeHiRes
     default 0, if set and Time::HiRes is installed, will do sub second
     timing of the time it takes Apache::ASP to process a request.  This
     will not include the time spent in the session manager, nor modperl
     or Apache, and is only a rough approximation at best.

     If Debug is set also, you will get a comment in your HTML output that
     indicates the time it took to process that script.

     If system debugging is set with Debug -1 or -2, you will also get
     this time in the Apache error log with the other system messages.

Mail Administration
-------------------

   Apache::ASP has some powerful administrative email extensions that let
you sleep at night, knowing full well that if an error occurs at the web
site, you will know about it immediately.  With these features already
enabled, it was also easy to provide the $Server->Mail(\%mail) API
extension which you can read up about in the OBJECTS section.

MailHost
     The mail host is the smtp server that the below Mail* config
     directives will use when sending their emails.  By default Net::SMTP
     uses smtp mail hosts configured in Net::Config, which is set up at
     install time, but this setting can be used to override this config.

     The mail hosts specified in the Net::Config file will be used as
     backup smtp servers to the MailHost specified here, should this
     primary server not be working.

          PerlSetVar MailHost smtp.yourdomain.com.foobar

MailFrom
     Default NONE, set this to specify the default mail address placed in
     the From: mail header for the $Server->Mail() API extension, as well
     as MailErrorsTo and MailAlertTo.

          PerlSetVar MailFrom youremail@yourdomain.com.foobar

MailErrorsTo
     No default, if set, ASP server errors, error code 500, that result
     while compiling or running scripts under Apache::ASP will
     automatically be emailed to the email address set for this config.
     This allows an administrator to have a rapid response to user
     generated server errors resulting from bugs in production ASP
     scripts.  Other errors, such as 404 not found will be handled by
     Apache directly.

     An easy way to see this config in action is to have an ASP script
     which calls a die(), which generates an internal ASP 500 server error.

     The Debug config of value 2 and this setting are mutually exclusive,
     as Debug 2 is a development setting where errors are displayed in the
     browser, and MailErrorsTo is a production setting so that errors are
     silently logged and sent via email to the web admin.

          PerlSetVar MailErrorsTo youremail@yourdomain.com

MailAlertTo
     The address configured will have an email sent on any ASP server
     error 500, and the message will be short enough to fit on a text
     based pager.  This config setting would be used to give an
     administrator a heads up that a www server error occurred, as opposed
     to MailErrorsTo would be used for debugging that server error.

     This config does not work when Debug 2 is set, as it is a setting for
     use in production only, where Debug 2 is for development use.

          PerlSetVar MailAlertTo youremail@yourdomain.com

MailAlertPeriod
     Default 20 minutes, this config specifies the time in minutes over
     which there may be only one alert email generated by MailAlertTo.
     The purpose of MailAlertTo is to give the admin a heads up that there
     is an error at the www server.  MailErrorsTo is for to aid in speedy
     debugging of the incident.

          PerlSetVar MailAlertPeriod 20

File Uploads
------------

FileUploadMax
     default 0, if set will limit file uploads to this size in bytes.
     This is currently implemented by setting $CGI::POST_MAX before
     handling the file upload.  Prior to this, a developer would have to
     hardcode a value for $CGI::POST_MAX to get this to work.

          PerlSetVar 100000

FileUploadTemp
     default 0, if set will leave a temp file on disk during the request,
     which may be helpful for processing by other programs, but is also a
     security risk in that other users on the operating system could
     potentially read this file while the script is running.

     The path to the temp file will be available at
     $Request->{FileUpload}{$form_field}{TempFile}.  The regular use of
     file uploads remains the same with the <$filehandle> to the upload at
     $Request->{Form}{$form_field}.  Please see the CGI section for more
     information on file uploads, and the $Request section in OBJECTS.

          PerlSetVar FileUploadTemp 0

SYNTAX
======

   ASP embedding syntax allows one to embed code in html in 2 simple ways.
The first is the <% xxx %> tag in which xxx is any valid perl code.  The
second is <%= xxx %> where xxx is some scalar value that will be inserted
into the html directly.  An easy print.

     A simple asp page would look like:

     <!-- sample here -->
     <html>
     <body>
     For loop incrementing font size: <p>
     <% for(1..5) { %>
     	<!-- iterated html text -->
     	<font size="<%=$_%>" > Size = <%=$_%> </font> <br>
     <% } %>
     </body>
     </html>
     <!-- end sample here -->

   Notice that your perl code blocks can span any html.  The for loop
above iterates over the html without any special syntax.

EVENTS
======

   The ASP platform allows developers to create Web Applications.  In
fulfillment of real software requirements, ASP allows event-triggered
actions to be taken, which are defined in a global.asa file.  The
global.asa file resides in the Global directory, defined as a config
option , and may define the following actions:

     Action			Event
     ------			------
             Script_OnStart *	Beginning of Script execution
             Script_OnEnd *		End of Script execution
             Script_OnFlush *	Before $Response being flushed to client.
     Application_OnStart	Beginning of Application
     Application_OnEnd	End of Application
     Session_OnStart		Beginning of user Session.
     Session_OnEnd		End of user Session.

     * These are API extensions that are not portable, but were
       added because they are incredibly useful

   These actions must be defined in the $Global/global.asa file as
subroutines, for example:

     sub Session_OnStart {
         $Application->{$Session->SessionID()} = started;
     }

   Sessions are easy to understand.  When visiting a page in a web
application, each user has one unique $Session.  This session expires,
after which the user will have a new $Session upon revisiting.

   A web application starts when the user visits a page in that
application, and has a new $Session created.  Right before the first
$Session is created, the $Application is created.  When the last user
$Session expires, that $Application expires also.

Script_OnStart & Script_OnEnd
-----------------------------

   The script events are used to run any code for all scripts in an
application defined by a global.asa.  Often, you would like to run the
same code for every script, which you would otherwise have to add by hand,
or add with a file include, but with these events, just add your code to
the global.asa, and it will be run.

   There is one caveat.  Code in Script_OnEnd is not guaranteed to be run
when the user hits a STOP button, since the program execution ends
immediately at this event.  To always run critical code, use the API
extension:

     $Server->RegisterCleanup()

Session_OnStart
---------------

   Triggered by the beginning of a user's session, Session_OnStart gets
run before the user's executing script, and if the same session recently
timed out, after the session's triggered Session_OnEnd.

   The Session_OnStart is particularly useful for caching database data,
and avoids having the caching handled by clumsy code inserted into each
script being executed.

Session_OnEnd
-------------

   Triggered by a user session ending, Session_OnEnd can be useful for
cleaning up and analyzing user data accumulated during a session.

   Sessions end when the session timeout expires, and the StateManager
performs session cleanup.  The timing of the Session_OnEnd does not occur
immediately after the session times out, but when the first script runs
after the session expires, and the StateManager allows for that session to
be cleaned up.

   So on a busy site with default SessionTimeout (20 minutes) and
StateManager (10 times) settings, the Session_OnEnd for a particular
session should be run near 22 minutes past the last activity that Session
saw.  A site infrequently visited will only have the Session_OnEnd run
when a subsequent visit occurs, and theoretically the last session of an
application ever run will never have its Session_OnEnd run.

   Thus I would not put anything mission-critical in the Session_OnEnd,
just stuff that would be nice to run whenever it gets run.

Script_OnFlush
--------------

   API extension. This event will be called prior to flushing the
$Response buffer to the web client.  At this time, the
$Response->{BinaryRef} buffer reference may be used to modify the buffered
output at runtime to apply global changes to scripts output without having
to modify all the scripts.

     sub Script_OnFlush {
       my $ref = $Response->{BinaryRef};
       $$ref =~ s/\s+/ /sg; # to strip extra white space
     }

   Check out the ./site/eg/global.asa for an example of its use.

Application_OnStart
-------------------

   This event marks the beginning of an ASP application, and is run just
before the Session_OnStart of the first Session of an application.  This
event is useful to load up $Application with data that will be used in all
user sessions.

Application_OnEnd
-----------------

   The end of the application is marked by this event, which is run after
the last user session has timed out for a given ASP application.

OBJECTS
=======

   The beauty of the ASP Object Model is that it takes the burden of CGI
and Session Management off the developer, and puts them in objects
accessible from any ASP script & include.  For the perl programmer, treat
these objects as globals accessible from anywhere in your ASP application.

     Currently the Apache::ASP object model supports the following:

       Object	 -	Function
       ------		--------
       $Session	 -	user session state
       $Response	 -	output to browser
       $Request	 -	input from browser
       $Application -	application state
       $Server	 -	general support methods

   These objects, and their methods are further defined in the following
sections.

$Session Object
---------------

   The $Session object keeps track of user and web client state, in a
persistent manner, making it relatively easy to develop web applications.
The $Session state is stored across HTTP connections, in database files in
the Global or StateDir directories, and will persist across web server
restarts.

   The user session is referenced by a 128 bit / 32 byte MD5 hex hashed
cookie, and can be considered secure from session id guessing, or session
hijacking.  When a hacker fails to guess a session, the system times out
for a second, and with 2**128 (3.4e38) keys to guess, a hacker will not be
guessing an id any time soon.

   If an incoming cookie matches a timed out or non-existent session, a
new session is created with the incoming id.  If the id matches a
currently active session, the session is tied to it and returned.  This is
also similar to the Microsoft ASP implementation.

   The $Session reference is a hash ref, and can be used as such to store
data as in:

     $Session->{count}++;	# increment count by one
     %{$Session} = ();	# clear $Session data

   The $Session object state is implemented through MLDBM, and a user
should be aware of the limitations of MLDBM.  Basically, you can read
complex structures, but not write them, directly:

     $data = $Session->{complex}{data};     # Read ok.
     $Session->{complex}{data} = $data;     # Write NOT ok.
     $Session->{complex} = {data => $data}; # Write ok, all at once.

   Please see MLDBM for more information on this topic.  $Session can also
be used for the following methods and properties:

$Session->{CodePage}
     Not implemented.  May never be until someone needs it.

$Session->{LCID}
     Not implemented.  May never be until someone needs it.

$Session->{SessionID}
     SessionID property, returns the id for the current session, which is
     exchanged between the client and the server as a cookie.

$Session->{Timeout} [= $minutes]
     Timeout property, if minutes is being assigned, sets this default
     timeout for the user session, else returns the current session
     timeout.

     If a user session is inactive for the full timeout, the session is
     destroyed by the system.  No one can access the session after it
     times out, and the system garbage collects it eventually.

$Session->Abandon()
     The abandon method times out the session immediately.  All Session
     data is cleared in the process, just as when any session times out.

$Session->Lock()
     API extension. If you are about to use $Session for many consecutive
     reads or writes, you can improve performance by explicitly locking
     $Session, and then unlocking, like:

          $Session->Lock();
          $Session->{count}++;
          $Session->{count}++;
          $Session->{count}++;
          $Session->UnLock();

     This sequence causes $Session to be locked and unlocked only 1 time,
     instead of the 6 times that it would be locked otherwise, 2 for each
     increment with one to read and one to write.

     Because of flushing issues with SDBM_File and DB_File databases, each
     lock actually ties fresh to the database, so the performance savings
     here can be considerable.

     Note that if you have SessionSerialize set, $Session is already
     locked for each script invocation automatically, as if you had called
     $Session->Lock() in Script_OnStart.  Thus you do not need to worry
     about $Session locking for performance.  Please read the section on
     SessionSerialize for more info.

$Session->UnLock()
     API Extension. Unlocks the $Session explicitly.  If you do not call
     this, $Session will be unlocked automatically at the end of the
     script.

$Response Object
----------------

   This object manages the output from the ASP Application and the client
web browser.  It does not store state information like the $Session object
but does have a wide array of methods to call.

$Response->{BinaryRef}
     API extension. This is a perl reference to the buffered output of the
     $Response object, and can be used in the Script_OnFlush global.asa
     event to modify the buffered output at runtime to apply global
     changes to scripts output without having to modify all the scripts.
     These changes take place before content is flushed to the client web
     browser.

          sub Script_OnFlush {
            my $ref = $Response->{BinaryRef};
            $$ref =~ s/\s+/ /sg; # to strip extra white space
          }

     Check out the ./site/eg/global.asa for an example of its use.

$Response->{Buffer}
     Default 1, when TRUE sends output from script to client only at the
     end of processing the script.  When 0, response is not buffered, and
     client is sent output as output is generated by the script.

$Response->{CacheControl}
     Default "private", when set to public allows proxy servers to cache
     the content.  This setting controls the value set in the HTTP header
     Cache-Control

$Response->{Charset}
     This member when set appends itself to the value of the Content-Length
     HTTP header.  If $Response->{Charset} = 'ISO-LATIN-1' is set, the
     corresponding header would look like:

          Content-Type: text/html; charset=ISO-LATIN-1

$Response->{Clean} = 0-9;
     API extension. Set the Clean level, default 0, on a per script basis.
     Clean of 1-9 compresses text/html output.  Please see the Clean
     config option for more information.

$Response->{ContentType} = "text/html"
     Sets the MIME type for the current response being sent to the client.
     Sent as an HTTP header.

$Response->{Expires} = $time
     Sends a response header to the client indicating the $time in SECONDS
     in which the document should expire.  A time of 0 means immediate
     expiration.  The header generated is a standard HTTP date like: "Wed,
     09 Feb 1994 22:23:32 GMT".

$Response->{ExpiresAbsolute} = $date
     Sends a response header to the client with $date being an absolute
     time to expire.  Formats accepted are all those accepted by
     HTTP::Date::str2time(), e.g.

          "Wed, 09 Feb 1994 22:23:32 GMT"     -- HTTP format
          "Tuesday, 08-Feb-94 14:15:29 GMT"   -- old rfc850 HTTP format

          "08-Feb-94"       -- old rfc850 HTTP format
          "09 Feb 1994"     -- proposed new HTTP format

          "Feb  3  1994"    -- Unix 'ls -l' format
          "Feb  3 17:03"    -- Unix 'ls -l' format

$Response->{FormFill} = 0|1
     If true, HTML forms generated by the script output will be auto
     filled with data from $Request->Form.  This feature requires
     HTML::FillInForm to be installed.  Please see the FormFill CONFIG for
     more information.

     This setting overrides the FormFill config at runtime for the script
     execution only.

$Response->{IsClientConnected}
     Not implemented, but returns 1 currently for portability.  This is
     value is not yet relevant, and may not be until apache 1.3.6, which
     will be tested shortly.  Apache versions less than 1.3.6 abort the
     perl code immediately upon the client dropping the connection.

$Response->{PICS}
     If this property has been set, a PICS-Label HTTP header will be sent
     with its value.  For those that do not know, PICS is a header that is
     useful in rating the internet.  It stands for Platform for Internet
     Content Selection, and you can find more info about it at:
     http://www.w3.org

$Response->{Status} = $status
     Sets the status code returned by the server.  Can be used to set
     messages like 500, internal server error

$Response->AddHeader($name, $value)
     Adds a custom header to a web page.  Headers are sent only before any
     text from the main page is sent, so if you want to set a header after
     some text on a page, you must turn BufferingOn.

$Response->AppendToLog($message)
     Adds $message to the server log.  Useful for debugging.

$Response->BinaryWrite($data)
     Writes binary data to the client.  The only difference from
     $Response->Write() is that $Response->Flush() is called internally
     first, so the data cannot be parsed as an html header.  Flushing
     flushes the header if has not already been written.

     If you have set the $Response->{ContentType} to something other than
     text/html, cgi header parsing (see CGI notes), will be automatically
     be turned off, so you will not necessarily need to use BinaryWrite
     for writing binary data.

     For an example of BinaryWrite, see the binary_write.htm example in
     ./site/eg/binary_write.htm

     Please note that if you are on Win32, you will need to call binmode
     on a file handle before reading, if its data is binary.

$Response->Clear()
     Erases buffered ASP output.

$Response->Cookies($name, [$key,] $value)
     Sets the key or attribute of cookie with name $name to the value
     $value.  If $key is not defined, the Value of the cookie is set.  ASP
     CookiePath is assumed to be / in these examples.

          $Response->Cookies('name', 'value');
           --> Set-Cookie: name=value; path=/

          $Response->Cookies("Test", "data1", "test value");
          $Response->Cookies("Test", "data2", "more test");
          $Response->Cookies(
          	"Test", "Expires",
          	&HTTP::Date::time2str(time+86400)
          	);
          $Response->Cookies("Test", "Secure", 1);
          $Response->Cookies("Test", "Path", "/");
          $Response->Cookies("Test", "Domain", "host.com");
           -->	Set-Cookie:Test=data1=test%20value&data2=more%20test;	\
          		expires=Fri, 23 Apr 1999 07:19:52 GMT;		\
          		path=/; domain=host.com; secure

     The latter use of $key in the cookies not only sets cookie attributes
     such as Expires, but also treats the cookie as a hash of key value
     pairs which can later be accesses by

          $Request->Cookies('Test', 'data1');
          $Request->Cookies('Test', 'data2');

     Because this is perl, you can (NOT PORTABLE) reference the cookies
     directly through hash notation.  The same 5 commands above could be
     compressed to:

          $Response->{Cookies}{Test} =
          	{
          		Secure	=> 1,
          		Value	=>
          			{
          				data1 => 'test value',
          				data2 => 'more test'
          			},
          		Expires	=> 86400, # not portable, see above
          		Domain	=> 'host.com',
          		Path    => '/'
          	};

     and the first command would be:

          # you don't need to use hash notation when you are only setting
          # a simple value
          $Response->{Cookies}{'Test Name'} = 'Test Value';

     I prefer the hash notation for cookies, as this looks nice, and is
     quite perlish.  It is here to stay.  The Cookie() routine is very
     complex and does its best to allow access to the underlying hash
     structure of the data.  This is the best emulation I could write
     trying to match the Collections functionality of cookies in IIS ASP.

     For more information on Cookies, please go to the source at
     http://home.netscape.com/newsref/std/cookie_spec.html

$Response->Debug(@args)
     API Extension. If the Debug config option is set greater than 0, this
     routine will write @args out to server error log.  refs in @args will
     be expanded one level deep, so data in simple data structures like
     one-level hash refs and array refs will be displayed.  CODE refs like

          $Response->Debug(sub { "some value" });

     will be executed and their output added to the debug output.  This
     extension allows the user to tie directly into the debugging
     capabilities of this module.

     While developing an app on a production server, it is often useful to
     have a separate error log for the application to catch debugging
     output separately.  One way of implementing this is to use the Apache
     ErrorLog configuration directive to create a separate error log for a
     virtual host.

     If you want further debugging support, like stack traces in your
     code, consider doing things like:

          $Response->Debug( sub { Carp::longmess('debug trace') };
          $SIG{__WARN__} = \&Carp::cluck; # then warn() will stack trace

     The only way at present to see exactly where in your script an error
     occurred is to set the Debug config directive to 2, and match the
     error line number to perl script generated from your ASP script.

     However, as of version 0.10, the perl script generated from the asp
     script should match almost exactly line by line, except in cases of
     inlined includes, which add to the text of the original script, pod
     comments which are entirely yanked out, and <% # comment %> style
     comments which have a \n added to them so they still work.

     If you would like to see the HTML preceding an error while
     developing, consider setting the BufferingOn config directive to 0.

$Response->End()
     Sends result to client, and immediately exits script.  Automatically
     called at end of script, if not already called.

$Response->ErrorDocument($code, $uri)
     API extension that allows for the modification the Apache
     ErrorDocument at runtime.  $uri may be a on site document, off site
     URL, or string containing the error message.

     This extension is useful if you want to have scripts set error codes
     with $Response->{Status} like 401 for authentication failure, and to
     then control from the script what the error message looks like.

     For more information on the Apache ErrorDocument mechanism, please
     see ErrorDocument in the CORE Apache settings, and the
     Apache->custom_response() API, for which this method is a wrapper.

$Response->Flush()
     Sends buffered output to client and clears buffer.

$Response->Include($filename, @args)
     This API extension calls the routine compiled from asp script in
     $filename with the args @args.  This is a direct translation of the
     SSI tag

          <!--#include file=$filename args=@args-->

     Please see the SSI section for more on SSI in general.

     This API extension was created to allow greater modularization of
     code by allowing includes to be called with runtime arguments.  Files
     included are compiled once, and the anonymous code ref from that
     compilation is cached, thus including a file in this manner is just
     like calling a perl subroutine.

$Response->Redirect($url)
     Sends the client a command to go to a different url $url.  Script
     immediately ends.

$Response->TrapInclude($file, @args)
     Calls $Response->Include() with same arguments as passed to it, but
     instead traps the include output buffer and returns it as as a perl
     scalar ref.  This allows one to postprocess the output buffer before
     sending to the client.

          my $string_ref = $Response->TrapInclude('file.inc');
          $$string_ref =~ s/\s+/ /sg; # squash whitespace like Clean 1
          print $$string_ref;

     The scalar is returned as a referenece to save on what might be a
     large string copy.  You may dereference the scalar with the
     $$string_ref notation.

$Response->Write($data)
     Write output to the HTML page.  <%=$data%> syntax is shorthand for a
     $Response->Write($data).  All final output to the client must at some
     point go through this method.

$Request Object
---------------

   The request object manages the input from the client browser, like
posts, query strings, cookies, etc.  Normal return results are values if
an index is specified, or a collection / perl hash ref if no index is
specified.  WARNING, the latter property is not supported in ActiveState
PerlScript, so if you use the hashes returned by such a technique, it will
not be portable.

   A normal use of this feature would be to iterate through the form
variables in the form hash...

     $form = $Request->Form();
     for(keys %{$form}) {
     	$Response->Write("$_: $form->{$_}<br>\n");
     }

   Please see the ./site/eg/server_variables.htm asp file for this method
in action.

   Note that if a form POST or query string contains duplicate values for
a key, those values will be returned through normal use of the $Request
object:

     @values = $Request->Form('key');

   but you can also access the internal storage, which is an array
reference like so:

     $array_ref = $Request->{Form}{'key'};
     @values = @{$array_ref};

   Please read the PERLSCRIPT section for more information on how things
like $Request->QueryString() & $Request->Form() behave as collections.

$Request->{TotalBytes}
     The amount of data sent by the client in the body of the request,
     usually the length of the form data.  This is the same value as
     $Request->ServerVariables('CONTENT_LENGTH')

$Request->BinaryRead($length)
     Returns a scalar whose contents are the first $length bytes of the
     form data, or body, sent by the client request.  This data is the raw
     data sent by the client, without any parsing done on it by
     Apache::ASP.

$Request->ClientCertificate()
     Not implemented.

$Request->Cookies($name [,$key])
     Returns the value of the Cookie with name $name.  If a $key is
     specified, then a lookup will be done on the cookie as if it were a
     query string.  So, a cookie set by:

          Set-Cookie: test=data1=1&data2=2

     would have a value of 2 returned by $Request->Cookies('test','data2').

     If no name is specified, a hash will be returned of cookie names as
     keys and cookie values as values.  If the cookie value is a query
     string, it will automatically be parsed, and the value will be a hash
     reference to these values.

     When in doubt, try it out.  Remember that unless you set the Expires
     attribute of a cookie with $Response->Cookies('cookie', 'Expires',
     $xyz), the cookies that you set will only last until you close your
     browser, so you may find your self opening & closing your browser a
     lot when debugging cookies.

     For more information on cookies in ASP, please read
     $Response->Cookies()

$Request->FileUpload($form_field, $key)
     API extension.  The FileUpload interface to file upload data is
     stabilized.  The internal representation of the file uploads is a
     hash of hashes, one hash per file upload found in the
     $Request->Form() collection.  This collection of collections may be
     queried through the normal interface like so:

          $Request->FileUpload('upload_file', 'ContentType');
          $Request->FileUpload('upload_file', 'FileHandle');
          $Request->FileUpload('upload_file', 'BrowserFile');
          $Request->FileUpload('upload_file', 'Mime-Header');
          $Request->FileUpload('upload_file', 'TempFile');

          * note that TempFile must be use with the UploadTempFile
            configuration setting.

     The above represents the old slow collection interface, but like all
     collections in Apache::ASP, you can reference the internal hash
     representation more easily.

          my $fileup = $Request->{FileUpload}{upload_file};
          $fileup->{ContentType};
          $fileup->{BrowserFile};
          $fileup->{FileHandle};
          $fileup->{Mime-Header};
          $fileup->{TempFile};

$Request->Form($name)
     Returns the value of the input of name $name used in a form with POST
     method.  If $name is not specified, returns a ref to a hash of all
     the form data.

     File upload data will be loaded into $Request->Form('file_field'),
     where the value is the actual file name of the file uploaded, and the
     contents of the file can be found by reading from the file name as a
     file handle as in:

          while(read($Request->Form('file_field_name'), $data, 1024)) {};

     For more information, please see the CGI / File Upload section, as
     file uploads are implemented via the CGI.pm module.  An example can
     be found in the installation samples ./site/eg/file_upload.asp

$Request->QueryString($name)
     Returns the value of the input of name $name used in a form with GET
     method, or passed by appending a query string to the end of a url as
     in http://localhost/?data=value.  If $name is not specified, returns
     a ref to a hash of all the query string data.

$Request->ServerVariables($name)
     Returns the value of the server variable / environment variable with
     name $name.  If $name is not specified, returns a ref to a hash of
     all the server / environment variables data.  The following would be
     a common use of this method:

          $env = $Request->ServerVariables();
          # %{$env} here would be equivalent to the cgi %ENV in perl.

$Application Object
-------------------

   Like the $Session object, you may use the $Application object to store
data across the entire life of the application.  Every page in the ASP
application always has access to this object.  So if you wanted to keep
track of how many visitors there where to the application during its
lifetime, you might have a line like this:

     $Application->{num_users}++

   The Lock and Unlock methods are used to prevent simultaneous access to
the $Application object.

$Application->Lock()
     Locks the Application object for the life of the script, or until
     UnLock() unlocks it, whichever comes first.  When $Application is
     locked, this guarantees that data being read and written to it will
     not suddenly change on you between the reads and the writes.

     This and the $Session object both lock automatically upon every read
     and every write to ensure data integrity.  This lock is useful for
     concurrent access control purposes.

     Be careful to not be too liberal with this, as you can quickly create
     application bottlenecks with its improper use.

$Application->UnLock()
     Unlocks the $Application object.  If already unlocked, does nothing.

$Application->GetSession($sess_id)
     This NON-PORTABLE API extension returns a user $Session given a
     session id.  This allows one to easily write a session manager if
     session ids are stored in $Application during Session_OnStart, with
     full access to these sessions for administrative purposes.

     Be careful not to expose full session ids over the net, as they could
     be used by a hacker to impersonate another user.  So when creating a
     session manager, for example, you could create some other id to
     reference the SessionID internally, which would allow you to control
     the sessions.  This kind of application would best be served under a
     secure web server.

     The ./site/eg/global_asa_demo.asp script makes use of this routine to
     display all the data in current user sessions.

$Application->SessionCount()
     This NON-PORTABLE method returns the current number of active
     sessions, in the application.  This method is not implemented as part
     of the ASP object model, but is implemented here because it is
     useful.  In particular, when accessing databases with license
     requirements, one can monitor usage effectively through accessing
     this value.

     This is a new feature as of v.06, and if run on a site with previous
     versions of Apache::ASP, the count may take a while to synch up.  To
     ensure a correct count, you must delete all the current state files
     associated with an application, usually in the $Global/.state
     directory.

$Server Object
--------------

   The server object is that object that handles everything the other
objects do not.  The best part of the server object for Win32 users is the
CreateObject method which allows developers to create instances of ActiveX
components, like the ADO component.

$Server->{ScriptTimeout} = $seconds
     Not implemented. May never be.  Please see the Apache Timeout
     configuration option, normally in httpd.conf.

$Server->Config($setting)
     API extension.  Allows a developer to read the CONFIG settings, like
     Global, GlobalPackage, StateDir, etc.  Currently implemented as a
     wrapper around

          Apache->dir_config($setting)

$Server->CreateObject($program_id)
     Allows use of ActiveX objects on Win32.  This routine returns a
     reference to an Win32::OLE object upon success, and nothing upon
     failure.  It is through this mechanism that a developer can utilize
     ADO.  The equivalent syntax in VBScript is

          Set object = Server.CreateObject(program_id)

     For further information, try 'perldoc Win32::OLE' from your favorite
     command line.

$Server->Execute($file, @args)
     New method from ASP 3.0, this does the same thing as

          $Response->Include($file, @args)

     and internally is just a wrapper for such.  Seems like we had this
     important functionality before the IIS/ASP camp!

$Server->GetLastError()
     Not implemented, will likely not ever be because this is dependent on
     how IIS handles errors and is not relevant in Apache.

$Server->HTMLEncode($string)
     Returns an HTML escapes version of $string. &, ", >, <, are each
     escapes with their HTML equivalents.  Strings encoded in this nature
     should be raw text displayed to an end user, as HTML tags become
     escaped with this method.                                 "

$Server->MapPath($url);
     Given the url $url, absolute, or relative to the current executing
     script, this method returns the equivalent filename that the server
     would translate the request to, regardless or whether the request
     would be valid.

     Only a $url that is relative to the host is valid.  Urls like "." and
     "/" are fine arguments to MapPath, but http://localhost would not be.

     To see this method call in action, check out the sample
     ./site/eg/server.htm script.

$Server->Mail(\%mail, %smtp_args);
     With the Net::SMTP and Net::Config modules installed, which are part
     of the perl libnet package, you may use this API extension to send
     email.  The \%mail hash reference that you pass in must have values
     for at least the To, From, and Subject headers, and the Body of the
     mail message.

     You could send an email like so:

          $Server->Mail({
          		To => 'somebody@yourdomain.com.foobar',
          		From => 'youremail@yourdomain.com.foobar',
          		Subject => 'Subject of Email',
          		Body =>
          		 'Body of message. '.
          		 'You might have a lot to say here!',
          		Organization => 'Your Organization',
          	       });

     Any extra fields specified for the email will be interpreted as
     headers for the email, so to send an HTML email, you could set
     'Content-Type' => 'text/html' in the above example.

     If you have MailFrom configured, this will be the default for the
     From header in your email.  For more configuration options like the
     MailHost setting, check out the CONFIG section.

     The return value of this method call will be boolean for success of
     the mail being sent.

     If you would like to specially configure the Net::SMTP object used
     internally, you may set %smtp_args and they will be passed on when
     that object is initialized.  "perldoc Net::SMTP" for more into on
     this topic.

$Server->Transfer($file)
     New method from ASP 3.0.  Transfers control to another script.  The
     Response buffer will not be cleared automatically, so if you want
     this to serve as a faster $Response->Redirect(), you will need to
     call $Response->Clear() before calling this method.

     This new script will take over current execution and the current
     script will not continue to be executed afterwards.  It differs from
     Execute() because the original script will not pick up where it left
     off.

$Server->URLEncode($string)
     Returns the URL-escaped version of the string $string. +'s are
     substituted in for spaces and special characters are escaped to the
     ascii equivalents.  Strings encoded in this manner are safe to put in
     urls... they are especially useful for encoding data used in a query
     string as in:

          $data = $Server->URLEncode("test data");
          $url = "http://localhost?data=$data";

          $url evaluates to http://localhost?data=test+data, and is a
          valid URL for use in anchor <a> tags and redirects, etc.

$Server->RegisterCleanup($sub)
          non-portable extension

     Sets a subroutine reference to be executed after the script ends,
     whether normally or abnormally, the latter occurring possibly by the
     user hitting the STOP button, or the web server being killed.  This
     subroutine must be a code reference created like:

          $Server->RegisterCleanup(sub { $main::Session->{served}++; });
            or
          sub served { $main::Session->{served}++; }
          $Server->RegisterCleanup(\&served);

     The reference to the subroutine passed in will be executed.  Though
     the subroutine will be executed in anonymous context, instead of the
     script, all objects will still be defined in main::*, that you would
     reference normally in your script.  Output written to $main::Response
     will have no affect at this stage, as the request to the www client
     has already completed.

     Check out the ./site/eg/register_cleanup.asp script for an example of
     this routine in action.

$Server->URL($url, \%params)
     Will return a URL with %params serialized into a query string like:

          $url = $Server->URL('test.asp', { test => value });

     which would give you a URL of test.asp?test=value

     Used in conjunction with the SessionQuery* settings, the returned URL
     will also have the session id inserted into the query string, making
     this a critical part of that method of implementing cookieless
     sessions.  For more information on that topic please read on the
     setting in the CONFIG section, and the SESSIONS section too.

SSI
===

   SSI is great!  One of the main features of SSI is to include other
files in the script being requested.  In Apache::ASP, this is implemented
in a couple ways, the most crucial of which is implemented in the file
include.  Formatted as

     <!--#include file=filename.inc-->

   ,the .inc being merely a convention, text from the included file will
be inserted directly into the script being executed and the script will be
compiled as a whole.  Whenever the script or any of its includes change,
the script will be recompiled.

   Includes go a great length to promote good decomposition and code
sharing in ASP scripts, but they are still fairly static.  As of version
.09, includes may have dynamic runtime execution, as subroutines compiled
into the global.asa namespace.  The first way to invoke includes
dynamically is

     <!--#include file=filename.inc args=@args-->

   If @args is specified, Apache::ASP knows to execute the include at
runtime instead of inlining it directly into the compiled code of the
script.  It does this by compiling the script at runtime as a subroutine,
and caching it for future invocations.  Then the compiled subroutine is
executed and has @args passed into its as arguments.

   This is still might be too static for some, as @args is still hardcoded
into the ASP script, so finally, one may execute an include at runtime by
utilizing this API extension

     $Response->Include("filename.inc", @args);

   which is a direct translation of the dynamic include above.

   Although inline includes should be a little faster, runtime dynamic
includes represent great potential savings in httpd memory, as includes
are shared between scripts keeping the size of each script to a minimum.
This can often be significant saving if much of the formatting occurs in
an included header of a www page.

   By default, all includes will be inlined unless called with an args
parameter.  However, if you want all your includes to be compiled as subs
and dynamically executed at runtime, turn the DynamicIncludes config
option on as documented above.

   That is not all!  SSI is full featured.  One of the things missing
above is the

     <!--#include virtual=filename.cgi-->

   tag.  This and many other SSI code extensions are available by
filtering Apache::ASP output through Apache::SSI via the Apache::Filter
and the Filter config options.  For more information on how to wire
Apache::ASP and Apache::SSI together, please see the Filter config option
documented above.  Also please see Apache::SSI for further information on
the capabilities it offers.

EXAMPLES
========

   Use with Apache.  Copy the ./site/eg directory from the ASP installation
to your Apache document tree and try it out!  You have to put
"AllowOverride All" in your <Directory> config section to let the
.htaccess file in the ./site/eg installation directory do its work.

   IMPORTANT (FAQ): Make sure that the web server has write access to that
directory.  Usually a

     chmod -R 0777 eg

   will do the trick :)

SESSIONS
========

   Cookies are used by default for user $Session support ( see OBJECTS ).
In order to track a web user and associate server side data with that
client, the web server sets, and the web client returns a 32 byte session
id identifier cookie.  This implementation is very secure and  may be used
in secure HTTPS transactions, and made stronger with SecureSession and
ParanoidSession settings (see CONFIG ).

   However good cookies are for this kind of persistent state management
between HTTP requests, they have long been under fire for security risks
associated with JavaScript security exploits and privacy abuse by large
data tracking companies.

   Because of these reasons, web users will sometimes turn off their
cookies, rendering normal ASP session implementations powerless, resulting
in a new $Session generated every request.  This is not good for ASP style
sessions.

Cookieless Sessions
-------------------

     *** See WARNING Below ***

   So we now have more ways to track sessions with the SessionQuery*
CONFIG settings, that allow a web developer to embed the session id in URL
query strings when use of cookies is denied.  The implementations work
such that if a user has cookies turned on, then cookies will be used, but
for those users with cookies turned off, the session ids will be parsed
into document URLs.

   The first and easiest method that a web developer may use to implement
cookieless sessions are with SessionQueryParse* directives which enable
Apache::ASP to the parse the session id into document URLs on the fly.
Because this is resource inefficient, there is also the SessionQuery*
directives that may be used with the $Server->URL($url,\%params) method to
generate custom URLs with the session id in its query string.

   To see an example of these cookieless sessions in action, check out the
./site/eg/cookieless_session.asp example.

     *** WARNING ***

   If you do use these methods, then be VERY CAREFUL of linking offsite
from a page that was accessed with a session id in a query string.  This
is because this session id will show up in the HTTP_REFERER logs of the
linked to site, and a malicious hacker could use this information to
compromise the security of your site's $Sessions, even if these are run
under a secure web server.

   In order to shake a session id off an HTTP_REFERER for a link taking a
user offsite, you must point that link to a redirect page that will
redirect a user, like so:

     <%
        # "cross site scripting bug" prevention
        my $sanitized_url =
     	$Server->HTMLEncode($Response->QueryString('OffSiteUrl'));
     %>
     <html>
     <head>
     <meta http-equiv=refresh content='0;URL=<%=$sanitized_url%>'>
     </head>
     <body>
     	Redirecting you offsite to
     	<a href=<%=$sanitized_url%> >here</a>...
     </body>
     </html>

   Because the web browser visits a real page before being redirected with
the <meta> tag, the HTTP_REFERER will be set to this page.  Just be sure
to not link to this page with a session id in its query string.

   Unfortunately a simple $Response->Redirect() will not work here,
because the web browser will keep the HTTP_REFERER of the original web
page if only a normal redirect is used.

XML/XSLT
========

Custom Tags with XMLSubsMatch
-----------------------------

   Before XML, there was the need to make HTML markup smarter.
Apache::ASP gives you the ability to have a perl subroutine handle the
execution of any predefined tag, taking the tag descriptors, and the text
contained between, as arguments of the subroutine.  This custom tag
technology can be used to extend a web developer's abilities to add
dynamic pieces without having to visibly use <% %> style code entries.

   So, lets say that you have a table that you want to insert for an
employee with contact info and the like, you could set up a tag like:

     <my:employee name="Jane" last="Doe" phone="555-2222">
       Jane Doe has been here since 1998.
     </my:employee>

   To render it with a custom tag, you would tell the Apache::ASP parser
to render the tag with a subroutine:

     PerlSetVar XMLSubsMatch my:employee

   Any colons, ':', in the XML custom tag will turn into '::', a perl
package separator, so the my:employee tag would translate to the
my::employee subroutine, or the employee subroutine in the my package.

   Then you would create the my::employee subroutine in the my perl
package or whereever like so

     sub my::employee {
       my($attributes, $body) = @_;
       $Response->Include('employee.inc', $attributes, $body);
     }

     <!-- # employee.inc file somewhere else -->
     <% my($attributes, $body) = @_; %>
     <table>
     <% for('name', 'last', 'phone') { %>
       <tr>
         <td><b><%=ucfirst $_ %></b>:</td>
         <td><%= $attributes->{$_} %></td>
       </tr>
     <% } %>
     <tr><td colspan=2><%= $body %></td></tr>
     </table>
     <!-- # end employee.inc file -->

   The $Response->Include() would then delegate the rendering of the
employee to the employee.inc ASP script include.

   Though XML purists would not like this custom tag technology to be
related to XML, the reality is that a careful site engineer could render
full XML documents with this technology, applying all the correct styles
that one might otherwise do with XSLT.

   Custom tags defined in this way can be used as XML tags are defined
with both a body and without as it

     <my:employee>...</my:employee>

   and just

     <my:employee/>

   These tags are very powerful in that they can also enclose normal ASP
logic, like:

     <my:employee>
       <!-- normal ASP logic -->
       <% my $birthday = &HTTP::Date::time2str(time - 25 * 86400 * 365); %>

     <!-- ASP inserts -->
     This employee has been online for <%= int(rand()*600)+1 %>
     seconds, and was born near <%= $birthday %>.
       </my:employee>

   For an example of this custom XML tagging in action, please check out
the ./site/eg/xml_subs.asp script.  Note the one limitation that currently
exists is that tags of the same name may not be used in each other, but
otherwise customs tags may be used in other custom tags.

XSLT Tranformations
-------------------

   XML is good stuff, but what can you use it for? The principle is that
by having data and style separated in XML and XSL files, you can reformat
your data more easily in the future, and you can render your data in
multiple formats, just as easily as for your web site, so you might render
your site to a PDA, or a cell phone just as easily as to a browser, and all
you have to do is set up the right XSL stylesheets to do the
transformation (XSLT).

   In the first release of XML/XSLT support, ASP scripts may be the source
of XML data that the XSL file transforms, and the XSL file itself will be
first executed as an ASP script also.  The XSLT transformation is handled
by XML::XSLT, a perl module, and you can see an example of it in action at
the ./site/eg/xslt.xml XML script.  Because both the XML and XSL
datasources are executed first

   To specify a XSL stylesheet, use the setting:

     PerlSetVar XSLT template.xsl

   where template.xsl could be any file.  By default this will XSLT
transform all ASP scripts so configured, but you can separate xml scripts
from the rest with the setting:

     PerlSetVar XSLTMatch xml$

   where all files with the ending xml would undergo a XSLT transformation.
XSLT tranformations are slow however, so to cache XSLT transformations
from XML scripts with consistent output, turn on caching:

     PerlSetVar XSLTCacheSize 100

   which would allow for the output of 100 transformations to be cached.
If the XML data is consistently different as it might be if it were
database driven, then the caching will have little effect, but for mostly
static pages like real XML docs, this will be a huge win.

   Note that XSLT depends on the installation of XML::XSLT, which in turn
depends on XML::DOM, and XML::Parser.  The caching feature depends on
Tie::Cache being installed.

Reference OSS Implementations
-----------------------------

   For their huge ground breaking XML efforts, these other XML OSS
projects need mention:

     Cocoon - XML-based web publishing, in Java
     http://xml.apache.org/cocoon/

     AxKit - XML web publishing with Apache & mod_perl
     http://www.axkit.org/

     XML::XSLT - Core engine that Apache::ASP uses for XSLT
     http://xmlxslt.sourceforge.net/

CGI
===

   CGI has been the standard way of deploying web applications long before
ASP came along.  CGI.pm is a very useful module that aids developers in
the building of these applications, and Apache::ASP has been made to be
compatible with function calls in CGI.pm.  Please see cgi.htm in the
./site/eg directory for a sample ASP script written almost entirely in CGI.

   As of version 0.09, use of CGI.pm for both input and output is seamless
when working under Apache::ASP.  Thus if you would like to port existing
cgi scripts over to Apache::ASP, all you need to do is wrap <% %> around
the script to get going.  This functionality has been implemented so that
developers may have the best of both worlds when building their web
applications.

   Following are some special notes with respect to compatibility with CGI.
Use of CGI.pm in any of these ways was made possible through a great
amount of work, and is not guaranteed to be portable with other perl ASP
implementations, as other ASP implementations will likely be more limited.

Query Object Initialization
     You may create a CGI.pm $query object like so:

          use CGI;
          my $query = new CGI;

     As of Apache::ASP version 0.09, form input may be read in by CGI.pm
     upon initialization.  Before, Apache::ASP would consume the form
     input when reading into $Request->Form(), but now form input is
     cached, and may be used by CGI.pm input routines.

CGI headers
     Not only can you use the CGI.pm $query->header() method to put out
     headers, but with the CgiHeaders config option set to true, you can
     also print "Header: value\n", and add similar lines to the top of
     your script, like:

          Some-Header: Value
          Some-Other: OtherValue

          <html><body> Script body starts here.

     Once there are no longer any cgi style headers, or the there is a
     newline, the body of the script begins. So if you just had an asp
     script like:

          print join(":", %{$Request->QueryString});

     You would likely end up with no output, as that line is interpreted
     as a header because of the semicolon.  When doing basic debugging, as
     long as you start the page with <html> you will avoid this problem.

print()ing CGI
     CGI is notorious for its print() statements, and the functions in
     CGI.pm usually return strings to print().  You can do this under
     Apache::ASP, since print just aliases to $Response->Write().  Note
     that $| has no affect.

          print $query->header();
          print $query->start_form();

File Upload
     CGI.pm is used for implementing reading the input from file upload.
     You may create the file upload form however you wish, and then the
     data may be recovered from the file upload by using $Request->Form().
     Data from a file upload gets written to a file handle, that may in
     turn be read from.  The original file name that was uploaded is the
     name of the file handle.

          my $filehandle = $Request->Form('file_upload_field_name');
          print $filehandle; # will get you the file name
          my $data;
          while(read($filehandle, $data, 1024)) {
          	# data from the uploaded file read into $data
          };

     Please see the docs on CGI.pm (try perldoc CGI) for more information
     on this topic, and ./site/eg/file_upload.asp for an example of its
     use.

     There is a $Request->FileUpload() API extension that you can use to
     get more data about a file upload, so that the following properties
     are available for querying:

          my $file_upload = $Request->{FileUpload}{upload_field};
          $file_upload->{BrowserFile}
          $file_upload->{FileHandle}
          $file_upload->{ContentType}

          # only if FileUploadTemp is set
          $file_upload->{TempFile}

          # whatever mime headers are sent with the file upload
          # just "keys %$file_upload" to find out
          $file_upload->{?Mime-Header?}

     Please see the $Request section in OBJECTS for more information.

PERLSCRIPT
==========

   Much work has been done to bring compatibility with ASP applications
written in PerlScript under IIS.  Most of that work revolved around
bringing a Win32::OLE Collection interface to many of the objects in
Apache::ASP, which are natively written as perl hashes.

   New as of verionsion 2.05 is new functionality enabled with the
CollectionItem setting, to giver better support to more recent PerlScript
syntax.  This seems helpful when porting from an IIS/PerlScript code base.
Please see the CONFIG section for more info.

   The following objects in Apache::ASP respond as Collections:

     $Application
     	$Session
     	$Request->FileUpload *
     	$Request->FileUpload('upload_file') *
     	$Request->Form
     	$Request->QueryString
     	$Request->Cookies
     	$Response->Cookies
     	$Response->Cookies('some_cookie')

     * FileUpload API Extensions

   And as such may be used with the following syntax, as compared with the
Apache::ASP native calls.  Please note the native Apache::ASP interface is
compatible with the deprecated PerlScript interface.

     C = PerlScript Compatibility	N = Native Apache::ASP

     ## Collection->Contents($name)
     [C] $Application->Contents('XYZ')
     [N] $Application->{XYZ}

     ## Collection->SetProperty($property, $name, $value)
     [C] $Application->Contents->SetProperty('Item', 'XYZ', "Fred");
     [N] $Application->{XYZ} = "Fred"

     ## Collection->GetProperty($property, $name)
     [C] $Application->Contents->GetProperty('Item', 'XYZ')
     [N] $Application->{XYZ}

     ## Collection->Item($name)
     [C] print $Request->QueryString->Item('message'), "<br>\n\n";
     [N] print $Request->{QueryString}{'message'}, "<br>\n\n";

     ## Working with Cookies
     [C] $Response->SetProperty('Cookies', 'Testing', 'Extra');
     [C] $Response->SetProperty('Cookies', 'Testing', {'Path' => '/'});
     [C] print $Request->Cookies(Testing) . "<br>\n";
     [N] $Response->{Cookies}{Testing} = {Value => Extra, Path => '/'};
     [N] print $Request->{Cookies}{Testing} . "<br>\n";

   Several incompatibilities exist between PerlScript and Apache::ASP:

     > Collection->{Count} property has not been implemented.
     > VBScript dates may not be used for Expires property of cookies.
     > Win32::OLE::in may not be used.  Use keys() to iterate over.
     > The ->{Item} property does not work, use the ->Item() method.

FAQ
===

   The following are some frequently asked questions about Apache::ASP.

Installation
------------

Apache errors on the PerlHandler directive ?
     You do not have mod_perl correctly installed for Apache.  The
     PerlHandler directive in Apache *.conf files is an extension enabled
     by mod_perl and will not work if mod_perl is not correctly installed.

     Common user errors are not doing a 'make install' for mod_perl, which
     installs the perl side of mod_perl, and not starting the right httpd
     after building it.  The latter often occurs when you have an old
     apache server without mod_perl, and you have built a new one without
     copying over to its proper location.

     To get mod_perl, go to http://perl.apache.org

Error: no request object (Apache=SCALAR(0x???????):)
     Your Apache + mod_perl build is not working properly, and is likely a
     RedHat Linux RPM DSO build.  Make sure you statically build your
     Apache + mod_perl httpd, recompiled fresh from the sources.

I am getting a tie or MLDBM / state error message, what do I do?
     Make sure the web server or you have write access to the eg directory,
     or to the directory specified as Global in the config you are using.
     Default for Global is the directory the script is in (e.g. '.'), but
     should be set to some directory not under the www server document
     root, for security reasons, on a production site.

     Usually a

          chmod -R -0777 eg

     will take care of the write access issue for initial testing purposes.

     Failing write access being the problem, try upgrading your version of
     Data::Dumper and MLDBM, which are the modules used to write the state
     files.

Sessions
--------

How can I use $Session to store complex data structures.
     Very carefully.  Please read the $Session documentation in the
     OBJECTS section.  You can store very complex objects in $Session, but
     you have to understand the limits, and the syntax that must be used
     to make this happen.

     In particular, stay away from statements that that have more than one
     level of indirection on the left side of an assignment like:

          $Session->{complex}{object} = $data;

How can I keep search engine spiders from killing the session manager?
     If you want to dissallow session creation for certain non web browser
     user agents, like search engine spiders, you can use an init handler
     like:

          PerlInitHandler "sub { $_[0]->dir_config('NoState', 1) }"

     This will configure your environment before Apache::ASP executes and
     sees the configuration settings.  You can use the mod_perl API in
     this way to configure Apache::ASP at runtime.

Insecure dependency in eval while running with - T switch ?
     If you are running your mod_perl with "PerlTaintCheck On", which is
     recommended if you are highly concerned about security issues, you
     may get errors like "Insecure dependency ... with - T switch".

     Apache::ASP automatically untaints data internally so that you may
     run scripts with PerlTaintCheck On, but if you are using state
     objects like $Session or $Application, you must also notify MLDBM,
     which Apache::ASP uses internally, to also untaint data read from
     disk, with this setting:

          $MLDBM::RemoveTaint = 1;

     You could put the above line in your global.asa, which is just like a
     perl module, outside any event handlers you define there.

How can I use $Session to store a $dbh database handle ?
     You cannot use $Session to store a $dbh handle.  This can be awkward
     for those coming from the IIS/NT world, where you could store just
     about anything in $Session, but this boils down to a difference
     between threads vs. processes.

     Database handles often have per process file handles open, which
     cannot be shared between requests, so though you have stored the $dbh
     data in $Session, all the other initializations are not relevant in
     another httpd process.

     All is not lost! Apache::DBI can be used to cache database
     connections on a per process basis, and will work for most cases.

Development
-----------

How is database connectivity handled?
     Database connectivity is handled through perl's DBI & DBD interfaces.
     Please see http://www.symbolstone.org/technology/perl/DBI/ for more
     information.  In the UNIX world, it seems most databases have cross
     platform support in perl.

     DBD::ODBC is often your ticket on Win32.  On UNIX, commercial vendors
     like OpenLink Software (http://www.openlinksw.com/) provide the nuts
     and bolts for ODBC.

     Database connections can be cached per process with Apache::DBI.

What is the best way to debug an ASP application ?
     There are lots of perl-ish tricks to make your life developing and
     debugging an ASP application easier.  For starters, you will find
     some helpful hints by reading the $Response->Debug() API extension,
     and the Debug configuration directive.

How are file uploads handled?
     Please see the CGI section.  File uploads are implemented through
     CGI.pm which is loaded at runtime only for this purpose.  This is the
     only time that CGI.pm will be loaded by Apache::ASP, which implements
     all other cgi-ish functionality natively.  The rationale for not
     implementing file uploads natively is that the extra 100K in memory
     for CGI.pm shouldn't be a big deal if you are working with bulky file
     uploads.

How do I access the ASP Objects in general?
     All the ASP objects can be referenced through the main package with
     the following notation:

          $main::Response->Write("html output");

     This notation can be used from anywhere in perl, including routines
     registered with $Server->RegisterCleanup().

     You use the normal notation in your scripts, includes, and global.asa:

          $Response->Write("html output");

Can I print() in ASP?
     Yes.  You can print() from anywhere in an ASP script as it aliases to
     the $Response->Write() method.  Using print() is portable with
     PerlScript when using Win32::ASP in that environment.

Do I have access to ActiveX objects?
     Only under Win32 will developers have access to ActiveX objects
     through the perl Win32::OLE interface.  This will remain true until
     there are free COM ports to the UNIX world.  At this time, there is
     no ActiveX for the UNIX world.

Can I script in VBScript or JScript ?
     Yes, but not with this perl module.  For ASP with other scripting
     languages besides perl, you will need to go with a commercial vendor
     in the UNIX world.  ChiliSoft at http://www.chilisoft.com/ has one
     such solution.  Of course on NT, you get this for free with IIS.

Support and Production
----------------------

How do I get things I want done?!
     If you find a problem with the module, or would like a feature added,
     please mail support, as listed in the SUPPORT section, and your needs
     will be promptly and seriously considered, then implemented.

What is the state of Apache::ASP?  Can I publish a web site on it?
     Apache::ASP has been production ready since v.02.  Work being done on
     the module is on a per need basis, with the goal being to eventually
     have the ASP API completed, with full portability to ActiveState
     PerlScript and MKS PScript.  If you can suggest any changes to
     facilitate these goals, your comments are welcome.

TUNING
======

   A little tuning can go a long way, and can make the difference between
a web site that gets by, and a site that screams with speed.  With
Apache::ASP, you can easily take a poorly tuned site running at 5
hits/second to 25+ hits/second just with the right configuration.

   Documented below are some simple things you can do to make the most of
your site.

   For more tips & tricks on tuning Apache and mod_perl, please see the
tuning documents at:

     Stas Bekman's mod_perl guide
     http://perl.apache.org/guide/

     Vivek Khera's mod_perl performance tuning
     http://perl.apache.org/tuning/

$Application & $Session State
-----------------------------

   Use NoState 1 setting if you don't need the $Application or $Session
objects. State objects such as these tie to files on disk and will incur a
performance penalty.

   If you need the state objects $Application and $Session, and if running
an OS that caches files in memory, set your "StateDir" directory to a
cached file system.  On WinNT, all files may be cached, and you have no
control of this.  On Solaris, /tmp is cached and would be a good place to
set the "StateDir" config setting to.  When cached file systems are used
there is little performance penalty for using state files.  Linux tends to
do a good job caching its file systems, so pick a StateDir for ease of
system administration.

   On Win32 systems, where mod_perl requests are serialized, you can
freely use SessionSerialize to make your $Session requests faster, and you
can achieve similar performance benefits for $Application if you call
$Application->Lock() in your global.asa's Script_OnStart.

High MaxRequests
----------------

   Set your max requests per child thread or process (in httpd.conf) high,
so that ASP scripts have a better chance being cached, which happens after
they are first compiled.  You will also avoid the process fork penalty on
UNIX systems.  Somewhere between 100 - 1000 is probably pretty good.

Low MaxClients
--------------

   Set your MaxClients low, such that if you have that many httpd servers
running, which will happen on busy site, your system will not start
swapping to disk because of excessive RAM usage.

Precompile Modules
------------------

   For those modules that your Apache::ASP application uses, make sure
that they are loaded in your sites startup.pl file, or loaded with
PerlModule in your httpd.conf, so that your modules are compiled pre-fork
in the parent httpd.

Precompile Scripts
------------------

   Precompile your scripts by using the Apache::ASP->Loader() routine
documented below.  This will at least save the first user hitting a script
from suffering compile time lag.  On UNIX, precompiling scripts upon
server startup allows this code to be shared with forked child www
servers, so you reduce overall memory usage, and use less CPU compiling
scripts for each separate www server process.  These savings could be
significant.  On my PII300, it takes a couple seconds to compile 28
scripts upon server startup, with an average of 50K RAM per compiled
script, and this savings is passed on to the child httpd servers.

   Apache::ASP->Loader() can be called to precompile scripts and even
entire ASP applications at server startup.  Note also that in modperl, you
can precompile modules with the PerlModule config directive, which is
highly recommended.

     Apache::ASP->Loader($path, $pattern, %config)

   This routine takes a file or directory as its first argument.  If a
file, that file will be compiled.  If a directory, that directory will be
recursed, and all files in it whose file name matches $pattern will be
compiled.  $pattern defaults to .*, which says that all scripts in a
directory will be compiled by default.

   The %config args, are the config options that you want set that affect
compilation.  These options include Debug, Global, GlobalPackage,
DynamicIncludes, StatINC, and StatINCMatch.  If your scripts are later run
with different config options, your scripts may have to be recompiled.

   Here is an example of use in a *.conf file:

     <Perl>
     Apache::ASP->Loader(
     	'c:/proj/site', "(asp|htm)\$",
     	Global => '/proj/perllib',
     	Debug => 1, # see output when starting apache

     # OPTIONAL configs if you use them in your apache configuration
     # these settings affect how the scripts are compiled and loaded
     GlobalPackage => SomePackageName,
     DynamicIncludes => 1,
     StatINC => 1,
     );
      </Perl>

   This config section tells the server to compile all scripts in
c:/proj/site that end in asp or htm, and print debugging output so you can
see it work.  It also sets the Global directory to be /proj/perllib, which
needs to be the same as your real config since scripts are cached uniquely
by their Global directory.  You will probably want to use this on a
production server, unless you cannot afford the extra startup time.

   To see precompiling in action, set Debug to 1 for the Loader() and for
your application in general and watch your error_log for messages
indicating scripts being cached.

No .htaccess or StatINC
-----------------------

   Don't use .htaccess files or the StatINC setting in a production system
as there are many more files touched per request using these features.
I've seen performance slow down by half because of using these.  For
eliminating the .htaccess file, move settings into *.conf Apache files.

   Instead of StatINC, try using the StatINCMatch config, which will check
a small subset of perl libraries for changes.  This config is fine for a
production environment, and if used well might only incur a 10-20%
performance penalty.

Turn off Debugging
------------------

   Turn debugging off by setting Debug to 0.  Having the debug config
option on slows things down immensely.

RAM Sparing
-----------

   If you have a lot (1000's+) of scripts, and limited memory, set NoCache
to 1, so that compiled scripts are not cached in memory.  You lose about
10-15% in speed for small scripts, but save at least 10K RAM per cached
script.  These numbers are very rough.  If you use includes, you can
instead try setting DynamicIncludes to 1, which will share compiled code
for includes between scripts by turning an <!-#include file..-> into a
$Response->Include().

SEE ALSO
========

   perl(1), mod_perl(3), Apache(3), MLDBM(3), HTTP::Date(3), CGI(3),
Win32::OLE(3)

KEYWORDS
========

   Apache, ASP, perl, apache, mod_perl, asp, Active Server Pages, perl,
asp, web application, ASP, session management, Active Server, scripting,
dynamic html, asp, perlscript, Unix, Linux, Solaris, Win32, WinNT, cgi
compatible, asp, response, ASP, request, session, application, server,
Active Server Pages

NOTES
=====

   Many thanks to those who helped me make this module a reality.  ASP +
Apache, web development could not be better!  Kudos go out to:

     :) Doug MacEachern, for moral support and of course mod_perl
     :) Ryan Whelan, for boldly testing on Unix in the early infancy of ASP
     :) Lupe Christoph, for his immaculate and stubborn testing skills
     :) Bryan Murphy, for being a PerlScript wiz
     :) Francesco Pasqualini, for bringing ASP to CGI
     :) Michael Rothwell, for his love of Session hacking
     :) Lincoln Stein, for his blessed CGI.pm module
     :) Alan Sparks, for knowing when size is more important than speed
     :) Jeff Groves, who put a STOP to user stop button woes
     :) Matt Sergeant, for his great tutorial on PerlScript and love of ASP
     :) Ken Williams, for great teamwork bringing full SSI to the table
     :) Darren Gibbons, the biggest cookie-monster I have ever known.
     :) Doug Silver, for finding most of the bugs.
     :) Marc Spencer, who brainstormed dynamic includes.
     :) Greg Stark, for endless enthusiasm, pushing the module to its limits.
     :) Richard Rossi, for his need for speed & boldly testing dynamic includes.
     :) Bill McKinnon, who understands the finer points of running a web site.
     :) Russell Weiss, for being every so "strict" about his code.
     :) Paul Linder, who is Mr. Clean... not just the code, its faster too !
        Boy was that just the beginning.  Work with him later facilitated better
        session management and XMLSubsMatch custom tag technology.
     :) Tony Merc Mobily, inspiring tweaks to compile scripts 10 times faster
     :) Russell Weiss again, for finding the internal session garbage collection
        behaving badly with DB_File sensitive i/o flushing requirements.
     :) Dmitry Beransky, for sharable web application includes, ASP on the big.
     :) Adi, who thought to have full admin control over sessions
     :) Matt Arnold, for the excellent graphics !
     :) Remi Fasol + Serge Sozonoff who inspired cookieless sessions.
     :) Matt Sergeant, again, for ever the excellent XML critique.
     :) Stas Bekman, for his beloved guide, and keeping us all worldly.
     :) Gerald Richter, for his Embperl, collaboration and competition!
     :) Geert Josten, for his wonderful work on XML::XSLT
     :) Craig Samuel, at LRN, for his faith in open source for his LCEC.
     :) Vee McMillen, for OSS patience & understanding.
     :) Ged Haywood, for his great help on the list & professionally.
     :) Brian Wheeler, for keeping up with the Apache::Filter times.

SUPPORT
=======

MAILING LIST ARCHIVE
--------------------

   The mod_perl mailing list archives are located at:

     http://forum.swarthmore.edu/epigone/modperl
     http://www.geocrawler.com/lists/3/web/182/0/
     http://www.egroups.com/group/modperl/

   and allow searching for previously asked Apache::ASP and mod_perl
questions.  Often times what may seem to be an Apache::ASP issue is really
a mod_perl issue.

EMAIL
-----

   Please send any questions or comments to the Apache mod_perl mailing
list at modperl@apache.org with at least Apache::ASP in the subject line.
Note that answers to these questions will be archived at the above mailing
archives, and you may be able to find your answer there.

COMMERCIAL
----------

   We are considering a commercial support offering for Apache::ASP, with
varying levels of service, ranging from 24x7 incident support packages,
high priority module development, web application tuning and basic
guaranteed email support.

   If you are interested in any of the above commercial support offerings,
please email asp@chamas.com and we will pursue an official support channel
if there is enough interest.

SITES USING
===========

   What follows is a list of public sites that are using Apache::ASP.  If
you use the software for your site, and would like to show your support of
the software by being listed, please send your URL to me at
joshua@chamas.com and I'll be sure to add it to the list.

     Alumni.NET
     	http://www.alumni.net

     Anime Wallpapers dot com
     http://www.animewallpapers.com/

     Chamas Enterprises Inc.
     http://www.chamas.com

     http://www.condo-mart.com
     Condo-Mart Web Service

     Direct.it
     http://www.direct.it/

     Discountclick.com
     http://www.discountclick.com/

     HCST
     http://www.hcst.net

     International Telecommunication Union
     http://www.itu.int

     Integra
     http://www.integra.ru/

     Internetowa Gielda Samochodowa
     http://www.gielda.szczecin.pl

     Money FM
     http://www.moneyfm.gr

     Motorsport.com
     http://www.motorsport.com

     Multiple Listing Service of Greater Cincinnati
     http://www.cincymls.com

     NodeWorks - web link monitoring
     http://www.nodeworks.com

     OnTheWeb Services
     http://www.ontheweb.nu

     Provillage
     http://www.provillage.com

     Prices for Antiques
     http://www.p4a.com

     redhat.com | support
     http://www.redhat.com/apps/support/

     Samara.RU
     http://portal.samara.ru/

     Sex Shop Online
     http://www.sex.shop.pl

     Spotlight
     http://www.spotlight.com.au

     USCD Electrical & Computer Engineering
     http://ece-local.ucsd.edu

     Watthai Net Syndey Australia
     http://watthai.net

RESOURCES
=========

   Here are some important resources listed related to the use of
Apache::ASP for publishing web applications:

     mod_perl Apache web module
     http://perl.apache.org

     mod_perl Guide
     http://perl.apache.org/guide/

     mod_perl book
     http://www.modperl.com

     Perl Programming Language
     http://www.perl.com

     Apache Web Server
     http://www.apache.org

     PerlMonth Online Magazine
     http://www.perlmonth.com

     Apache & mod_perl Reference Cards
     http://www.refcards.com/

     Perl DBI Database Access
     http://www.symbolstone.org/technology/perl/DBI/

TODO
====

   There is no specific time frame in which these things will be
implemented.  Please let me know if any of these is of particular interest
to you, and I will give it higher priority.

WILL BE DONE
------------

     + Database storage of $Session & $Application, so web clusters
       may scale better than the current NFS/CIFS StateDir implementation
       allows, maybe via Apache::Session.

MAY BE DONE
-----------

     + VBScript, ECMAScript interpreters
     + allow use of Apache::Session for session management
     + BerkeleyDB2 integration for state management, maybe getting
       shared memory to work.
     + asp.pl, CGI method of doing asp
     + Dumping state of Apache::ASP during an error, and being
       able to go through it with the perl debugger.
     + $Request->ClientCertificate()

CHANGES
=======

$VERSION = 2.07; $DATE="11/26/2000";
          + = improvement; - = bug fix

          -+-+ Session Manager
           empty state group directories are not removed, thus alleviating
           one potential race condition.  This impacted performance
           on idle sites severely as there were now 256 directories
           to check, so made many performance enhancements to the
           session manager.  The session manager is built to handle
           up to 20,000 client sessions over a 20 minute period.  It
           will slow the system down as it approaches this capacity.

          One such enhancement was session-ids now being 11 bytes long
          so that its .lock file is only 16 characters in length.
          Supposedly some file systems lookup files 16 characters or
          less in a fast hashed lookup.  This new session-id has
          4.4 x 10^12 possible values.  I try to keep this space as
          large as possible to prevent a brute force attack.

          Another enhancement was to limit the group directories
          to 64 by only allowing the session-id prefix to be [0-3][0-f]
          instead of [0-f][0-f], checking 64 empty directories on an
          idle site takes little time for the session manager, compared
          to 256 which felt significant from the client end, especially
          on Win32 where requests are serialized.

          If upgrading to this version, you would do well to delete
          empty StateDir group directories while your site is idle.
          Upgrading during an idle time will have a similar effect,
          as old Apache::ASP versions would delete empty directories.

          -$Application->GetSession($session_id) now creates
           an session object that only lasts until the next
           invocation of $Application->GetSession().  This is
           to avoid opening too many file handles at once,
           where each session requires opening a lock file.

          +added experimental support for Apache::Filter 1.013
           filter_register call

          +make test cases for $Response->Include() and
           $Response->TrapInclude()

          +Documented CollectionItem config.

          +New $Request->QueryString('multiple args')->Count()
           interface implemented for CollectionItem config.
           Also $Request->QueryString('multiple args')->Item(1) method.
           Note ASP collections start counting at 1.

          --fixed race condition, where multiple processes might
           try creating the same state directory at the same time, with
           one winning, and one generating an error.  Now, web process
           will recheck for directory existence and error if
           it doesn't.

          -global.asa compilation will be cached correctly, not
           sure when this broke.  It was getting reloaded every request.

          -StateAllWrite config, when set creates state files
           with a+rw or 0666 permissions, and state directories
           with a+rwx or 0777 permissions.  This allows web servers
           running as different users on the same machine to share a
           common StateDir config.  Also StateGroupWrite config
           with perms 0770 and 0660 respectively.

          -Apache::ASP->Loader() now won't follow links to
           directories when searching for scripts to load.

          +New RegisterIncludes config which is on by default only
           when using Apache::ASP->Loader(), for compiling includes
           when precompiling scripts.

          +Apache::ASP::CompileInclude path optimized, which underlies
           $Response->Include()

          +$Request->QueryString->('foo')->Item() syntax enabled
           with CollectionItem config setting.  Default syntax
           supported is $Request->QueryString('foo') which is
           in compatible.  Other syntax like $Request->{Form}{foo}
           and $Request->Form->Item('foo') will work in either case.

          +New fix suggested for missing Apache reference in
           Apache::ASP handler startup for RedHat RPMs.  Added
           to error message.

          --Backup flock() unlocking try for QNX will not corrupt the
           normal flock() LOCK_UN usage, after trying to unlock a file
           that doesn't exist.  This bug was uncovered from the below
           group deletion race condition that existed.

          -Session garbage collection will not delete new group
           directories that have just been created but are empty.
           There was a race condition where a new group directory would
           be created, but then deleted by a garbage collector before
           it could be initialized correctly with new state files.

          +Better random session-id checksums for $Session creation.
           per process srand() initialization, because srand()
           may be called once prefork and never called again.
           Call without arguments to rely on perl's decent rand
           seeding.  Then when calling rand() in Secret() we have
           enough random data, that even if someone else calls srand()
           to something fixed, should not mess things up terribly since
           we checksum things like $$ & time, as well as perl memory
           references.

          +XMLSubs installation make test.

          -Fix for multiline arguments for XMLSubs

$VERSION = 2.03; $DATE="08/01/2000";
          +License change to GPL.  See LICENSE section.

          +Setup of www.apache-asp.org site, finally!

          -get rid of Apache::ASP->Loader() warning message for perl 5.6.0

$VERSION = 2.01; $DATE="07/22/2000";
          +$data_ref = $Response->TrapInclude('file.inc') API
           extension which allows for easy post processing of
           data from includes

          +./site/eg/source.inc syntax highlighting improvements

          +XMLSubsMatch compile time parsing performance improvement

$VERSION = 2.00; $DATE="07/15/2000";
          -UniquePackages config works again, broke a couple versions back

          +better error handling for methods called on $Application
           that don't exist, hard to debug before

$VERSION = 1.95; $DATE="07/10/2000";
          !!!!! EXAMPLES SECURITY BUG FOUND & FIXED !!!!!

          --FIXED: distribution example ./site/eg/source.asp now parses
           out special characters of the open() call when reading local
           files.

          This bug would allow a malicious user possible writing
          of files in the same directory as the source.asp script.  This
          writing exploit would only have effect if the web server user
          has write permission on those files.

          Similar bug announced by openhack.org for minivend software
          in story at:
            http://www.zdnet.com/eweek/stories/general/0,11011,2600258,00.html

          !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

          -$0 now set to transferred file, when using $Server->Transfer

          -Fix for XMLSubsMatch parsing on cases with 2 or more args passed
           to tag sub that was standalone like
             <Apps:header type="header" title="Moo" foo="moo" />

$VERSION = 1.93; $DATE="07/03/2000";
          -sub second timing with Time::HiRes was adding <!-- -->
           comments by HTML by default, which would possibly
           break specific programs looking for precise HTML output.
           Now this behavior must be explicitly turned on with
           the TimeHiRes config setting.

          These comments will only appear in HTML only if
          Debug is enabled as well.

          Timed log entries will only occur if
          system debugging is enabled, with Debug -1 or -2

$VERSION = 1.91; $DATE="07/02/2000";
          +Documented XMLSubsMatch & XSLT* configuration
           settings in CONFIG section.

          +XSLT XSL template is now first executed as an
           ASP script just like the XML scripts.  This is
           just one step away now from implementing XSP logic.

          +$Server->Execute and $Server->Transfer API extensions
           implemented.  Execute is the same as $Request->Include()
           and $Server->Transfer is like an apache internal redirect
           but keeps the current ASP objects for the next script.

          Added examples, transfer.htm, and modified dynamic_includes.htm.

          +Better compile time error debugging with Debug 2 or -2.
           Will hilite/link the buggy line for global.asa errors,
           include errors, and XML/XSLT errors just like with
           ASP scripts before.

          +Nice source hiliting when viewing source for the example
           scripts.

          +Runtime string writing optimization for static HTML going
           through $Response.

          +New version numbering just like everyone else.  Starting at 1.91
           since I seem to be off by a factor of 10, last release would have
           been 1.9.

$VERSION = 0.19; $DATE="NOT RELEASED";
          +XMLSubsMatch and XSLT* settings documented in
           the XML/XSLT section of the site/README.

          -XMLSubsMatch will strip parens in a pattern match
           so it does not interfere with internal matching use.

          +XSLT integration allowing XML to be rendered by XSLT
           on the fly.  XSLT specifies XSL file to transform XML.
           XSLTMatch is a regexp that matches XML file names, like \.xml$,
           which will be transformed by XSLT setting, default .*

           XSLTCacheSize when specified uses Tie::Cache to cached XML DOMs
           internally and cache XSLT transformations output per XML/XSL
           combination.  XML DOM objects can take a lot of RAM, so use
           this setting judiciously like setting to 100.  Definitely
           experiment with this value.

          +More client info in the error mail feature, including
           client IP, form data, query string, and HTTP_* client headers

          +With Time::HiRes loaded, and Debug set to non 0,
           will add a <!-- Apache::ASP served request in xx.xx seconds -->
           to text/html output, similar to Cocoon, per user request
           Will also add this to the system debug error log output
           when Debug is < 0

          -bug fix on object initialization optimization earlier
           in this release, that was introduced for faster event
           handler execution.

          +Apache::ASP::Parse() takes a file name, scalar, or
           scalar ref for arguments of data to parse for greater
           integration ability with other applications.

          +PodComments optimization, small speed increase at
           compilation time.

          +String optimization on internal rendering that avoids
           unnecessary copying of static html, by using refs.  Should
           make a small difference on sites with large amounts of
           static html.

          +CompressGzip setting which, when Compress::Zlib is installed,
           will compress text/html automatically going out to the web
           browser if the client supports gzip encoding.

          ++Script_OnFlush event handler, and auxiliary work optimizing
           asp events in general.  $Response->{BinaryRef} created which
           is a reference to outgoing output, which can be used
           to modify the data at runtime before it goes out to the client.

          +Some code optimizations that boost speed from 22 to 24
           hits per second when using Sessions without $Application,
           on a simple hello world benchmark on a WinNT PII300.

          ++Better SessionManagement, more aware of server farms that
           don't have reliable NFS locking.  The key here is to have only
           one process on one server in charge of session garbage collection
           at any one time, and try to create this situation with a snazzy
           CleanupMaster routine.  This is done by having a process register
           itself in the internal database with a server key created at
           apache start time.  If this key gets stale, another process can
           become the master, and this period will not exceed the period
           SessionTimeout / StateManager.

          ** Work on session manager sponsored by LRN, http://www.lrn.com.  **
          ** This work was used to deploy a server farm in production with  **
          ** NFS mounted StateDir. Thanks to Craig Samuel for his belief in **
          ** open source. :)                                                **

          Future work for server farm capabilities might include breaking
          up the internal database into one of 256 internal databases
          hashed by the first 2 chars of the session id.  Also on the plate
          is Apache::Session like abilities with locking and/or data storage
          occuring in a SQL database.  The first dbs to be done will include
          MySQL & Oracle.

          +Better session security which will create a new session id for an
           incoming session id that does not match one already seen.  This will
           help for those with Search engines that have bookmarked
           pages with the session ids in the query strings.  This breaks away
           from standard ASP session id implementation which will automatically
           use the session id presented by the browser, now a new session id will
           be returned if the presented one is invalid or expired.

          -$Application->GetSession will only return a session if
           one already existed.  It would create one before by default.

          +Script_OnFlush global.asa event handler, and $Response->{BinaryRef}
           member which is a scalar reference to the content about to be flushed.
           See ./site/eg/global.asa for example usage, used in this case to
           insert font tags on the fly into the output.

          +Highlighting and linking of line error when Debug is set to 2 or -2.

          --removed fork() call from flock() backup routine? How did
            that get in there?  Oh right, testing on Win32. :(
            Very painful lesson this one, sorry to whom it may concern.

          +$Application->SessionCount support turned off by default
           must enable with SessionCount config option.  This feature
           puts an unnecessary load on busy sites, so not default
           behavior now.

          ++XMLSubsMatch setting that allows the developer to
           create custom tags XML style that execute perl subroutines.
           See ./site/eg/xml_subs.asp

          +MailFrom config option that defaults the From: field for
           mails sent via the Mail* configs and $Server->Mail()

          +$Server->Mail(\%mail, %smtp_args) API extension

          +MailErrorsTo & MailAlertTo now can take comma
           separated email addresses for multiple recipients.

          -tracking of subroutines defined in scripts and includes so
           StatINC won't undefine them when reloading the GlobalPackage,
           and so an warning will be logged when another script redefines
           the same subroutine name, which has been the bane of at least
           a few developers.

          -Loader() will now recompile dynamic includes that
           have changed, even if main including script has not.
           This is useful if you are using Loader() in a
           PerlRestartHandler, for reloading scripts when
           gracefully restarting apache.

          -Apache::ASP used to always set the status to 200 by
           default explicitly with $r->status().  This would be
           a problem if a script was being used to as a 404
           ErrorDocument, because it would always return a 200 error
           code, which is just wrong.  $Response->{Status} is now
           undefined by default and will only be used if set by
           the developer.

          Note that by default a script will still return a 200 status,
          but $Response->{Status} may be used to override this behavior.

          +$Server->Config($setting) API extension that allows developer
           to access config settings like Global, StateDir, etc., and is a
           wrapper around Apache->dir_config($setting)

          +Loader() will log the number of scripts
           recompiled and the number of scripts checked, instead
           of just the number of scripts recompiled, which is
           misleading as it reports 0 for child httpds after
           a parent fork that used Loader() upon startup.

          -Apache::ASP->Loader() would have a bad error if it didn't load
           any scripts when given a directory, prints "loaded 0 scripts" now

$VERSION = 0.18; $DATE="02/03/2000";
          +Documented SessionQuery* & $Server->URL() and
           cleaned up formatting some, as well as redoing
           some of the sections ordering for better readability.
           Document the cookieless session functionality more
           in a new SESSIONS section.  Also documented new
           FileUpload configs and $Request->FileUpload collection.
           Documented StatScripts.

          +StatScripts setting which if set to 0 will not reload
           includes, global.asa, or scripts when changed.

          +FileUpload file handles cleanup at garbage collection
           time so developer does not have to worry about lazy coding
           and undeffing filehandles used in code.  Also set
           uploaded filehandles to binmode automatically on Win32
           platforms, saving the developer yet more typing.

          +FileUploadTemp setting, default 0, if set will leave
           a temp file on disk during the request, which may be
           helpful for processing by other programs, but is also
           a security risk in that others could potentially read
           this file while the script is running.

          The path to the temp file will be available at
          $Request->{FileUpload}{$form_field}{TempFile}.
          The regular use of file uploads remains the same
          with the <$filehandle> to the upload at
          $Request->{Form}{$form_field}.

          +FileUploadMax setting, default 0, currently an
           alias for $CGI::POST_MAX, which determines the
           max size for a file upload in bytes.

          +SessionQueryParse only auto parses session-ids
           into links when a session-id COOKIE is NOT found.
           This feature is only enabled then when a user has
           disabled cookies, so the runtime penalty of this
           feature won't drag down the whole site, since most
           users will have cookies turned on.

          -StatINC & StatINCMatch will not undef Fnctl.pm flock
           functions constants like O_RDWR, because the code references
           are not well trackable.  This would result in sporadic 500 server
           errors when a changed module was reloaded that imported O_* flock
           functions from Fnctl.

          +SessionQueryParse & SessionQueryParseMatch
           settings that enable auto parsing session ids into
           URLs for cookieless sessions.  Will pick up URLs in
           <a href>, <area href>, <form action>, <frame src>,
           <iframe src>, <img src>, <input src>, <link href>
           $Response->Redirect($URL) and the first URL in
           script tags like <script>*.location.href=$URL</script>

          These settings require that buffering be enabled, as
          Apache::ASP will parse through the buffer to parse the URLs.

          With SessionQueryParse on, it will just parse non-absolute
          URLs, but with SessionQueryParseMatch set to some server
          url regexp, like ^http://localhost , will also parse
          in the session id for URLs that match that.

          When testing, the performance hit from this parsing
          a script dropped from 12.5 hits/sec on my WinNT box
          to 11.7 hits per second for 1K of buffered output.
          The difference is .007 of my PII300's processing power
          per second.

          For 10K of output then, my guess is that this speed
          of script, would be slowed to 6.8 hits per second.
          This kind of performance hit would also slow a
          script running at 40 hits per second on a UNIX box
          to 31 hits/sec for 1K, and to 11 hits/sec for 10K parsed.

          Your mileage may vary and you will have to test the difference
          yourself.  Get yourself a valid URL with a session-id in
          it, and run it through ab, or Socrates, with SessionQuery
          turned on, and then with SessionQueryParse set to see
          the difference.  SessionQuery just enables of session id
          setting from the query string but will not auto parse urls.

          -If buffering, Content-Length will again be set.
           It broke, probably while I was tuning in the past
           couple versions.

          +UseStrict setting compiles all scripts including
           global.asa with "use strict" turned on for catching
           more coding errors.  With this setting enabled,
           use strict errors die during compilation forcing
           Apache::ASP to try to recompile the script until
           successful.

          -Object use in includes like $Response->Write()
           no longer error with "use strict" programming.

          +SessionQuery config setting with $Server->URL($url, { %params } )
           alpha API extensions to enable cookieless sessions.

          +Debugging not longer produces internal debugging
           by default.  Set to -1,-2 for internal debugging
           for Debug settings 1 & 2.

          +Both StateSerializer & StateDB can be changed
           without affecting a live web site, by storing
           the configurations for $Application & $Session
           in an internal database, so that if $Session was
           created with SDBM_File for the StateDB (default),
           it will keep this StateDB setting until it ends.

          +StateSerializer config setting.  Default Data::Dumper,
           can also be set to Storable.  Controls how data is
           serialized before writing to $Application & $Session.

          +Beefed up the make test suite.

          +Improved the locking, streamlining a bit of the
           $Application / $Session setup process.  Bench is up to
           22 from 21 hits / sec on dev NT box.

          +Cut more fat for faster startup, now on my dev box
           I get 44 hits per sec Apache::ASP vs. 48 Embperl
           vs. 52 CGI via Apache::Registry for the HelloWorld Scripts.

          -Improved linking for the online site documentation,
           where a few links before were bad.

$VERSION = 0.17; $DATE="11/15/99";
          ++20%+ faster startup script execution, as measured by the
           HelloWorld bench.  I cut a lot of the fat out of
           the code, and is now at least 20% faster on startup
           both with and without state.

          On my dev (NT, apache 1.3.6+mod_perl) machine, I now get:

          42 hits per sec on Apache::ASP HelloWorld bench
          46 hits per sec on Embperl (1.2b10) and
          51 hits per sec for CGI Apache::Registry scripts

          Before Apache::ASP was clocking some 31 hits per sec.
          Apache::ASP also went from 75 to 102 hits per second
          on Solaris.

          +PerlTaintCheck On friendly.  This is mod_perl's way
           of providing -T taint checking.  When Apache::ASP
           is used with state objects like $Session or $Application,
           MLDBM must also be made taint friendly with:

          $MLDBM::RemoveTaint = 1;

          which could be put in the global.asa.  Documented.

          +Added $Response->ErrorDocument($error_code, $uri_or_string)
           API extension which allows for setting of Apache's error
           document at runtime.  This is really just a wrapper
           for Apache->custom_response() renamed so it syncs with
           the Apache ErrorDocument config setting.  Updated
           documentation, and added error_document.htm example.

          =OrderCollections setting was added, but then REMOVED
           because it was not going to be used.  It bound
           $Request->* collections/hashes to Tie::IxHash, so that data
           in those collections would be read in the order the
           browser sent it, when eaching through or with keys.

          -global.asa will be reloaded when changed.  This broke
           when I optimized the modification times with (stat($file))[9]
           rather than "use File::stat; stat($file)->mtime"

          -Make Apache::ASP->Loader() PerlRestartHandler safe,
           had some unstrict code that was doing the wrong thing.

          -IncludesDir config now works with DynamicIncludes.

          +DebugBufferLength feature added, giving control to
           how much buffered output gets shown when debugging errors.

          ++Tuning of $Response->Write(), which processes all
           static html internally, to be almost 50% faster for
           its typical use, when BufferingOn is enabled, and
           CgiHeaders are disabled, both being defaults.

          This can show significant speed improvements for tight
          loops that render ASP output.

          +Auto linking of ./site/eg/ text to example scripts
           at web site.

          +$Application->GetSession($session_id) API extension, useful
           for managing active user sessions when storing session ids
           in $Application.  Documented.

          -disable use of flock() on Win95/98 where it is unimplemented

          -@array context of $Request->Form('name') returns
           undef when value for 'name' is undefined.  Put extra
           logic in there to make sure this happens.

$VERSION = 0.16; $DATE="09/22/99";
          -$Response->{Buffer} and PerlSetVar BufferingOn
           configs now work when set to 0, to unbuffer output,
           and send it out to the web client as the script generates it.

          Buffering is enabled by default, as it is faster, and
          allows a script to error cleanly in the middle of execution.

          +more bullet proof loading of Apache::Symbol, changed the
           way Apache::ASP loads modules in general.  It used to
           check for the module to load every time, if it hadn't loaded
           successfully before, but now it just tries once per httpd,
           so the web server will have to be restarted to see new installed
           modules.  This is just for modules that Apache::ASP relies on.

          Old modules that are changed or updated with an installation
          are still reloaded with the StatINC settings if so configured.

          +ASP web site wraps <font face="courier new"> around <pre>
           tags now to override the other font used for the text
           areas.  The spacing was all weird in Netscape before
           for <pre> sections.

          -Fixed Content-Length calculation when using the Clean
           option, so that the length is calculated after the HTML
           is clean, not before.  This would cause a browser to
           hang sometimes.

          +Added IncludesDir config option that if set will also be
           used to check for includes, so that includes may easily be
           shared between applications.  By default only Global and
           the directory the script is in are checked for includes.

          Also added IncludesDir as a possible configuration option
          for Apache::ASP->Loader()

          -Re-enabled the Application_OnStart & OnEnd events, after
           breaking them when implementing the AllowApplicationState
           config setting.

          +Better pre-fork caching ... StatINC & StatINCMatch are now
           args for Apache::ASP->Loader(), so StatINC symbols loading
           may be done pre-fork and shared between httpds.  This lowers
           the child httpd init cost of StatINC.  Documented.

          +Made Apache::ASP Basic Authorization friendly so authentication
           can be handled by ASP scripts.  If AuthName and AuthType Apache
           config directives are set, and a $Response->{Status} is set to
           401, a user will be prompted for username/password authentication
           and the entered data will show up in ServerVariables as:
             $env = $Request->ServerVariables
             $env->{REMOTE_USER} = $env->{AUTH_USER} = username
             $env->{AUTH_PASSWD} = password
             $env->{AUTH_NAME}   = your realm
             $env->{AUTH_TYPE}   = 'Basic'

          This is the same place to find auth data as if Apache had some
          authentication handler deal with the auth phase separately.

          -MailErrorsTo should report the right file now that generates
           the error.

$VERSION = 0.15; $DATE="08/24/1999";
          --State databases like $Session, $Application are
           now tied/untied to every lock/unlock triggered by read/write
           access.  This was necessary for correctness issues, so that
           database file handles are flushed appropriately between writes
           in a highly concurrent multi-process environment.

          This problem raised its ugly head because under high volume,
          a DB_File can become corrupt if not flushed correctly.
          Unfortunately, there is no way to flush SDBM_Files & DB_Files
          consistently other than to tie/untie the databases every access.

          DB_File may be used optionally for StateDB, but the default is
          to use SDBM_File which is much faster, but limited to 1024 byte
          key/value pairs.

          For SDBM_Files before, if there were too many concurrent
          writes to a shared database like $Application, some of the
          writes would not be saved because another process
          might overwrite the changes with its own.

          There is now a 10 fold performance DECREASE associated
          with reading from and writing to files like $Session
          and $Application.  With rough benchmarks I can get about
          100 increments (++) now per second to $Session->{count}, where
          before I could get 1000 increments / second.

          You can improve this if you have many reads / writes happening
          at the same time, by placing locking code around the group like

          	$Session->Lock();
          	$Session->{count}++;
          	$Session->{count}++;
          	$Session->{count}++;
          	$Session->UnLock();

          This method will reduce the number of ties to the $Session database
          from 6 to 1 for this kind of code, and will improve the performance
          dramatically.

          Also, instead of using explicit $Session locking, you can
          create an automatic lock on $Session per script by setting
          SessionSerialize in your config to 1.  The danger here is
          if you have any long running scripts, the user will have
          to wait for it to finish before another script can be run.

          To see the number of lock/unlocks or ties/unties to each database
          during a script execution, look at the last lines of debug output
          to your error log when Debug is set to 1.  This can help you
          performance tweak access to these databases.

          +Updated documentation with new config settings and
           API extensions.

          +Added AllowApplicationState config option which allows
           you to leave $Application undefined, and will not
           execute Application_OnStart or Application_OnEnd.
           This can be a slight performance increase of 2-3% if
           you are not using $Application, but are using $Session.

          +Added $Session->Lock() / $Session->UnLock() API routines
           necessary additions since access to session is not
           serialized by default like IIS ASP.  Also prompted
           by change in locking code which retied to SDBM_File
           or DB_File each lock.  If you $Session->Lock / UnLock
           around many read/writes, you will increase performance.

          +Added StateCache config which, if set will cache
           the file handle locks for $Application and an internal
           database used for tracking $Session info.  This caching can
           make an ASP application perform up to 10% faster,
           at a cost of each web server process holding 2 more
           cached file handles open, per ASP application using
           this configuration.  The data written to or read from
           these state databases is not cached, just the locking
           file handles are held open.

          -Added in much more locking in session manager
           and session garbage collector to help avoid collisions
           between the two.  There were definite windows that the
           two would collide in, during which bad things could
           happen on a high volume site.

          -Fixed some warnings in DESTROY and ParseParams()

$VERSION = 0.14; $DATE="07/29/1999";
          -CGI & StatINC or StatINCMatch would have bad results
           at times, with StatINC deleting dynamically compiled
           CGI subroutines, that were imported into other scripts
           and modules namespaces.

          A couple tweaks, and now StatINC & CGI play nice again ;)
          StatINCMatch should be safe to use in production with CGI.
          This affects in particular environments that use file upload,
          since CGI is loaded automatically by Apache::ASP to handle
          file uploads.

          This fix should also affect other seemingly random
          times when StatINC or StatINCMatch don't seem to do
          the right thing.

          +use of ASP objects like $Response are now "use strict"
           safe in scripts, while UniquePackages config is set.

          +Better handling of "use strict" errors in ASP scripts.
           The error is detected, and the developer is pointed to the
           Apache error log for the exact error.

          The script with "use strict" errors will be recompiled again.  Its seems
          though that "use strict" will only throw its error once, so that a script
          can be recompiled with the same errors, and work w/o any use strict
          error messaging.

$VERSION = 0.12; $DATE="07/01/1999";
          -Compiles are now 10 +times faster for scripts with lots of big
           embedded perl blocks <% #perl %>

          Compiles were slow because of an old PerlScript compatibility
          parsing trick where $Request->QueryString('hi')->{item}
          would be parsed to $Request->QueryString('hi') which works.
          I think the regexp that I was using had O(n^2) characteristics
          and it took a really big perl block to 10 +seconds to parse
          to understand there was a problem :(

          I doubt anyone needed this compatibility, I don't even see
          any code that looks like this in the online PerlScript examples,
          so I've commented out this parsing trick for now.  If you
          need me to bring back this functionality, it will be in the
          form of a config setting.

          For information on PerlScript compatibility, see the PerlScript
          section in the ASP docs.

          -Added UniquePackages config option, that if set brings back
           the old method of compiling each ASP script into its own
           separate package.  As of v.10, scripts are compiled by default
           into the same package, so that scripts, dynamic includes & global.asa
           can share globals.  This BROKE scripts in the same ASP Application
           that defined the same sub routines, as their subs would redefine
           each other.

          UniquePackages has scripts compiled into separate perl packages,
          so they may define subs with the same name, w/o fear of overlap.
          Under this settings, scripts will not be able to share globals.

          -Secure field for cookies in $Response->Cookies() must be TRUE to
           force cookie to be secure.  Before, it just had to be defined,
           which gave wrong behavior for Secure => 0.

          +$Response->{IsClientConnected} set to one by default.  Will
           work out a real value when I upgrade to apache 1.3.6.  This
           value has no meaning before, as apache aborts the perl code
           when a client drops its connection in earlier versions.

          +better compile time debugging of dynamic includes, with
           Debug 2 setting

          +"use strict" friendly handling of compiling dynamic includes
           with errors

$VERSION = 0.11; $DATE="06/24/1999";
          +Lots of documentation updates

          +The MailHost config option is the smtp server used for
           relay emails for the Mail* config options.

          +MailAlertTo config option used for sending a short administrative
           alert for an internal ASP error, server code 500.  This is the
           compliment to MailErrorsTo, but is suited for sending a to a
           small text based pager.  The email sent by MailErrorsTo would
           then be checked by the web admin for quick response & debugging
           for the incident.

          The MailAlertPeriod config specifies the time in minutes during
          which only one alert will be sent, which defaults to 20.

          +MailErrorsTo config options sends the results of a 500 error
           to the email address specified as if Debug were set to 2.
           If Debug 2 is set, this config will not be on, as it is
           for production use only.  Debug settings less than 2 only
           log errors to the apache server error log.

          -StatINCMatch / StatINC can be used in production and work
           even after a server graceful restart, which is essential for
           a production server.

          -Content-Length header is set again, if BufferingOn is set, and
           haven't $Response->Flush()'d.  This broke when I introduce
           the Script_OnEnd event handler.

          +Optimized reloading of the GlobalPackage perl module upon changes,
           so that scripts and dynamic includes don't have to be recompiled.
           The global.asa will still have to be though.  Since we started
           compiling all routines into a package that can be named with
           GlobalPackage, we've been undeffing compiled scripts and includes
           when the real GlobalPackage changed on disk, as we do a full sweep
           through the namespace.  Now, we skip those subs that we know to
           be includes or scripts.

          -Using Apache::Symbol::undef() to undefine precompiled scripts
           and includes when reloading those scripts.  Doing just an undef()
           would sometimes result in an "active subroutine undef" error.
           This bug came out when I started thrashing the StatINC system
           for production use.

          +StatINCMatch setting created for production use reloading of
           perl modules.  StatINCMatch allows StatINC reloading of a
           subset of all the modules defined in %INC, those that match
           $module =~ /$StatINCMatch/, where module is some module name
           like Class/Struct.pm

          +Reoptimized pod comment parsing.  I slowed it down to sync
           lines numbers in the last version, but found another corner I could cut.

$VERSION = 0.10; $DATE="05/24/1999";
          += improvement; - = bug fix

          +Added index.html file to ./eg to help people wade through
           the examples.  This one has been long overdue.

          +Clean config option, or setting $Response->{Clean} to 1 - 9,
           uses HTML::Clean to compress text/html output of ASP scripts.
           I like the Clean 1 setting which is lightweight, stripping
           white space for about 10% compression, at a cost of less than
           a 5% performance penalty.

          +Using pod style commenting no longer confuses the line
           numbering.  ASP script line numbers are almost exactly match
           their compiled perl version, except that normal inline includes
           (not dynamic) insert extra text which can confuse line numbering.
           If you want perl error line numbers to entirely sync with your
           ASP scripts, I would suggest learning how to use dynamic includes,
           as opposed to inline includes.

          -Wrapped StatINC reloading of libs in an eval, and capturing
           error for Debug 2 setting.  This makes changing libs with StatINC
           on a little more friendly when there are errors.

          -$Request->QueryString() now stores multiple values for the
           same key, just as $Request->Form() has since v.07.  In
           wantarray() context like @vals = $Request->QueryString('dupkey'),
           @vals will store whatever values where associated with dupkey
           in the query string like (1,2) from: ?dupkey=1&dupkey=2

          +The GlobalPackage config directive may be defined
           to explicitly set the perl module that all scripts and global.asa
           are compiled into.

          -Dynamic includes may be in the Global directory, just like
           normal includes.

          +Perl script generated from asp scripts should match line
           for line, seen in errors, except when using inline (default)
           includes, pod comments, or <% #comment %> perl comments, which
           will throw off the line counts by adding text, removing
           text, or having an extra newline added, respectively.

          -Script_OnEnd may now send output to the browser.  Before
           $main::Response->End() was being called at the end of the
           main script preventing further output.

     ++All scripts are compiled as routines in a namespace uniquely
     defined by the global.asa of the ASP application.  Thus,   scripts,
     includes, and global.asa routines will share   all globals defined in
     the global.asa namespace.   This means   that globals between scripts
     will be shared, and globals   defined in a global.asa will be
     available to scripts.

          Scripts used to have their own namespace, thus globals
          were not shared between them.

          +a -o $output_dir switch on the ./cgi/asp script allows
           it to execute scripts and write their output to an output
           directory.  Useful for building static html sites, based on
           asp scripts.  An example use would be:

          asp -b -o out *.asp

          Without an output directory, script output is written to STDOUT

$VERSION = 0.09; $DATE="04/22/1999";
          +Updated Makefile.PL optional modules output for CGI & DB_File

          +Improved docs on $Response->Cookies() and $Request->Cookies()

          +Added PERFORMANCE doc to main README, and added sub section
           on precompiling scripts with Apache::ASP->Loader()

          +Naming of CompileIncludes switched over to DynamicIncludes
           for greater clarity.

          +Dynamic includes can now reference ASP objects like $Session
           w/o the $main::* syntax.  These subs are no longer anonymous
           subs, and are now compiled into the namespace of the global.asa package.

          +Apache::ASP->Loader() precompiles dynamic includes too. Making this work
           required fixing some subtle bugs / dependencies in the compiling process.

          +Added Apache::ASP->Loader() similar to Apache::RegistryLoader for
           precompiling ASP scripts.  Precompile a whole site at server
           startup with one function call.

          +Prettied the error messaging with Debug 2.

          +$Response->Debug(@args) debugging extension, which
           allows a developer to hook into the module's debugging,
           and only have @args be written to error_log when Debug is greater
           than 0.

          -Put write locking code around State writes, like $Session
           and $Application.  I thought I fixed this bug a while ago.

          -API change: converted $Session->Timeout() and $Session->SessionID()
           methods into $Session->{Timeout} and $Session->{SessionID} properties.
           The use of these properties as methods is deprecated, but
           backwards compatibility will remain.  Updated ./eg/session.asp
           to use these new properties.

          +Implemented $Response->{PICS} which if set sends out a PICS-Label
           HTTP header, useful for ratings.

          +Implemented $Response->{CacheControl} and $Response->{Charset} members.
           By default, CacheControl is 'private', and this value gets sent out
           every request as HTTP header Cache-Control.  Charset appends itself
           onto the content type header.

          +Implemented $Request->BinaryRead(), $Request->{TotalBytes},
           documented them, and updated ./eg/form.asp for an example usage.

          +Implemented $Response->BinaryWrite(), documented, and created
           and example in ./eg/binary_write.htm

          +Implemented $Server->MapPath() and created example of its use
           in ./eg/server.htm

          -$Request->Form() now reads file uploads correctly with
           the latest CGI.pm, where $Request->Form('file_field') returns
           the actual file name uploaded, which can be used as a file handle
           to read in the data.  Before, $Request->Form('file_field') would
           return a glob that looks like *Fh::filename, so to get the file
           name, you would have to parse it like =~ s/^\*Fh\:\://,
           which you no longer have to do.  As long as parsing was done as
           mentioned, the change should be backwards compatible.

          +Updated  +enhanced documentation on file uploads.  Created extra
           comments about it as an FAQ, and under $Response->Form(), the latter
           being an obvious place for a developer to look for it.

          +Updated ./eg/file_upload.asp to show use of non file form data,
           with which we had a bug before.

          +Finished retieing *STDIN to cached STDIN contents, so that
           CGI input routines may be used transparently, along side with
           use of $Request->Form()

          +Cleaned up and optimized $Request code

          +Updated documentation for CGI input & file uploads.  Created
           file upload FAQ.

          +Reworked ./eg/cgi.htm example to use CGI input routines
           after doing a native read of STDIN.

          ++Added dynamic includes with <!--include file=file args=@args-->
           extension.  This style of include is compiled as an anonymous sub &
           cached, and then executed with @args passed to the subroutine for
           execution.  This is include may also be rewritten as a new API
           extension: $Response->Include('file', @args)

          +Added ./eg/compiled_includes.htm example documenting new dynamic includes.

          +Documented SSI: native file includes, and the rest with filtering
           to Apache::SSI

          +Turned the documentation of Filter config to value of Off so
           people won't cut and paste the On config by default.

          +Added SecureSession config option, which forces session cookie to
           be sent only under https secured www page requests.

          +Added StateDB config option allows use of DB_File for $Session, since
           default use of SDBM_File is limited.  See StateDB in README.

          +file include syntax w/o quotes supported like <!--#include file=test.inc-->

          +Nested includes are supported, with includes including each other.
           Recursive includes are detected and errors out when an include has been
           included 100 times for a script.  Better to quit early than
           have a process spin out of control. (PORTABLE ? probably not)

          +Allow <!--include file=file.inc--> notation w/o quotes around file names

          -PerlSetEnv apache conf setting now get passed through to
           $Request->ServerVariables. This update has ServerVariables
           getting data from %ENV instead of $r->cgi_env

          +README FAQ for PerlHandler errors

$VERSION = 0.08; $DATE="02/06/1999";
          ++SSI with Apache::Filter & Apache::SSI, see config options & ./eg files
           Currently filtering only works in the direction Apache::ASP -> Apache::SSI,
           will not work the other way around, as SSI must come last in a set of filters

          +SSI file includes may reference files in the Global directory, better
           code sharing

          - <% @array... %> no longer dropped from code.

          +perl =pod comments are stripped from script before compiling, and associated
           PodComments configuration options.

          +Command line cgi/asp script takes various options, and allows execution
           of multiple asp scripts at one time.  This script should be used for
           command line debugging.  This is also the beginning of building
           a static site from asp scripts with the -b option, suppressing headers.

          +$Response->AddHeader('Set-Cookie') works for multiple cookies.

          -$Response->Cookies('foo', '0') works, was dropping 0 because of boolean test

          -Fixed up some config doc errors.

$VERSION = 0.07; $DATE="01/20/1999";
          -removed SIG{__WARN__} handler, it was a bad idea.

          -fixes file locking on QNX, work around poor flock porting

          +removed message about Win32::OLE on UNIX platforms from Makefile.PL

          -Better lock garbage collection.  Works with StatINC seamlessly.

          -Multiple select forms now work in array context with $Response->Form()
          	@values = $Response->Form('multi');

          -Better CGI.pm compatibility with $r->header_out('Content-type'),
           improved garbage collection under modperl, esp. w/ file uploads

$VERSION = 0.06; $DATE="12/21/1998";
          +Application_OnStart & Application_OnEnd event handlers support.

          -Compatible with CGI.pm 2.46 headers()

          -Compatible with CGI.pm $q = new CGI({}), caveat: does not set params

          +use strict; followed by use of objects like $Session is fine.

          -Multiple cookies may be set per script execution.

          +file upload implemented via CGI.pm

          ++global.asa implemented with events Session_OnStart and Session_OnEnd
           working appropriately.

          +StateDir configuration directive implemented.
           StateDir allows the session state directory to be specified separately
           from the Global directory, useful for operating systems with caching file
           systems.

          +StateManager config directive.  StateManager specifies how frequently
           Sessions are cleaned up, with 10 (default) meaning that old Sessions
           will be cleaned up 10 times per SessionTimeout period (default 20 minutes).

          +$Application->SessionCount() implemented, non-portable method.
          	: returns the number of currently active sessions

          -STOP button fix.  Users may hit STOP button during script
           execution, and Apache::ASP will cleanup with a routine registered
           in Apache's $r->register_cleanup.  Works well supposedly.

          +PerlScript compatibility work, trying to make ports smoother.
          	: Collection emulator, no ->{Count} property
          	: $.*(.*)->{Item} parsed automatically,
          	  shedding the ->{Item} for Collection support (? better way ?)
          	: No VBScript dates support, just HTTP RFC dates with HTTP::Date
          	: Win32::OLE::in not supported, just use "keys %{$Collection}"

          +./cgi/asp script for testing scripts from the command line
          	: will be upgraded to CGI method of doing asp
          	: is not "correct" in anyway, so not documented for now
          	  but still useful

          +strips DOS carriage returns from scripts automatically, so that
           programs like FrontPage can upload pages to UNIX servers
           without perl choking on the extra \r characters.

$VERSION = 0.05; $DATE="10/19/1998";
          +Added PERFORMANCE doc, which includes benchmarks  +hints.

          +Better installation warnings and errors for other modules required.

          -Turned off StatINC in eg/.htaccess, as not everyone installs Devel::Symdump

          -Fixed AUTOLOAD state bug, which wouldn't let you each through state
           objects, like %{$Session}, or each %$Session, (bug introduced in v.04)

          +Parses ASP white space better.  HTML output matches author's intent
           by better dealing with white space surrounding <% perl blocks %>

          -Scalar insertion code <%=$foo%> can now span many lines.

          +Added include.t test script for includes.

          +Script recompiles when included files change.

          +Files can be included in script with
           SSI <!--#include file="filename"--> syntax, needs to be
           done in ASP module to allow compilation of included code and html
           into script.  Future chaining with Apache::SSI will allow static
           html includes, and other SSI directives

$VERSION = 0.04; $DATE="10/14/1998";
          +Example script eg/cgi.htm demonstrating CGI.pm use for output.

          +Optimized ASP parsing, faster and more legible executing code
          	: try 'die();' in code with setting PerlSetVar Debug 2

          +Cleaned up code for running with 'use strict'

          -Fixed directory handle leak on Solaris, from not closing after opendir()

          +StatINC overhaul.  StatINC setting now works as it should, with
           the caveat that exported functions will not be refreshed.

          +NoState setting optimization, disallows $Application & $Session

          +$Application->*Lock() functions implemented

          -SoftRedirect setting for those who want scripts to keep running
           after a Redirect()

          +SessionSerialize setting to lock session while script is running
          	: Microsoft ASP style session locking
          	: For a session, scripts execute one at a time
          	: NOT recommended use, please see note.

          -MLDBM can be used for other things without messing up internal use
          	: before if it was used with different DB's and serializers,
          	  internal state could be lost.

          --State file locking.  Corruption worries, and loss of data no more.

          +CGI header support, developer can use CGI.pm for *output*, or just print()
          	: print "Set-Cookie: test=cookie\n", and things will just work
          	: use CGI.pm for output
          	: utilizes $r->send_cgi_header(), thanks Doug!

          +Improved Cookie implementation, more flexible and complete
          	- Domain cookie key now works
          	: Expire times now taken from time(), and relative time in sec
          	: Request->Cookies() reading more flexible, with wantarray()
          	  on hash cookie values, %hash = $Request->Cookie('test');

          -make test module naming correction, was t.pm, now T.pm for Unix

          +POD / README cleanup, formatting and HTML friendly.

$VERSION = 0.03; $DATE="09/14/1998";
          +Installation 'make test' now works

          +ActiveX objects on Win32 implemented with $Server->CreateObject()

          +Cookies implemented: $Response->Cookies() & $Request->Cookies()

          -Fixed $Response object API, converting some methods to object members.
           Deprecated methods, but backwards compatible.

          +Improved error messaging, debug output

          +$, influences $Response->Write(@strings) behavior

          +perl print() works, sending output to $Response object

          +$Response->Write() prints scalars, arrays, and hashes.  Before only scalars.

          +Begin implementation of $Server object.

          +Implemented $Response->{Expires} and $Response->{ExpiresAbsolute}

          +Added "PerlSetVar StatINC" config option

          +$0 is aliased to current script filename

          +ASP Objects ($Response, etc.) are set in main package
           Thus notation like $main::Response->Write() can be used anywhere.

$VERSION = 0.02; $DATE="07/12/1998";
          ++Session Manager, won't break under denial of service attack

          +Fleshed out $Response, $Session objects, almost full implementation.

          +Enormously more documentation.

          -Fixed error handling with Debug = 2.

          -Documentation fixed for pod2man support.  README now more man-like.

          -Stripped \r\n dos characters from installation files

          -755 mode set for session state directory when created

          -Loads Win32/OLE properly, won't break with UNIX

$VERSION = 0.01; $DATE="06/26/1998";
          Syntax Support
          --------------
          Initial release, could be considered alpha software.
          Allows developers to embed perl in html ASP style.

          <!-- sample here -->
          <html>
          <body>
          <% for(1..10) { %>
          	counting: <%=$_%> <br>
          <% } %>
          </body>
          </html>

          ASP Objects
          -----------
          $Session, $Application, $Response, $Request objects available
          for use in asp pages.

          $Session & $Application data is preserved using SDBM files.

          $Session id's are tracked through the use of cookies.

          Security
          --------
          Timeouts any attempt to use a session id that doesn't already
          exist.  Should stop hackers, since there is no wire speed guessing
          cookies.

LICENSE
=======

   Copyright (c) 1998-2000, Joshua Chamas, Chamas Enterprises Inc.  All
rights reserved.

   Apache::ASP is a perl native port of Active Server Pages for Apache and
mod_perl.  This software is licensed under the GPL.

   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.

   For the full text of the GPL, see the license file in the distribution
of this software, visit the GPL site at
http://www.gnu.org/copyleft/gpl.html or write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

   For general licensing questions, please see the SUPPORT section.

   To contact us about licensing terms, please email asp@chamas.com.

Adds some or all of the hostname and port to the URI
****************************************************

NAME
====

   Apache::AddHostPath - Adds some or all of the hostname and port to the
URI

SYNOPSIS
========

     # in httpd.conf
     PerlTransHandler Apache::AddHostPath

DESCRIPTION
===========

   This module transforms the requested URI based on the hostname and port
number from the http request header.  It allows you to manage an arbitrary
number of domains and/or sub-domains all pointed to the same document
root, but for which you want a combination of shared and distinct files.

   Essentially the module implements Apache's URI translation phase by
attempting to use some or all of the URL hostname and port number as the
base of the URI.  It simply does file and directory existence tests on a
series of URIs (from most-specific to least-specific) and sets the URI to
the most specific match.

   If the requested is:

     URL: http://www.alpha.cvsroot.org:8080/index.html
     URI: /index.html

   Apache::AddHostPath would go through the following list of possible
paths and set the new URI based on the first match which passes a -f or -d
existence test:

     $docRoot/org/cvsroot/alpha/www/8080/index.html
     $docRoot/org/cvsroot/alpha/www/index.html
     $docRoot/org/cvsroot/alpha/index.html
     $docRoot/org/cvsroot/index.html
     $docRoot/org/index.html
     $docRoot/index.html

   For example if you have three domains cvsroot.org, ransommoney.com, and
inputsignal.com using the same apache instance and DocumentRoot (without
using VirtualHosts). If you assume that the DocumentRoot contains the
following files and directories:

     images/
     images/bg.gif
     org/
     org/cvsroot/
     org/cvsroot/images/logo.gif
     com/
     com/images/
     com/images/bg.gif
     com/ransommoney/
     com/ransommoney/images/
     com/ransommoney/images/logo.gif
     com/ransommoney/images/bg.gif
     com/inputsignal/
     com/inputsignal/images/
     com/inputsignal/images/logo.gif

   Apache::AddHostPath would transform the following requested URL/URIs as
follows:

     Input URL:  http://cvsroot.org/images/bg.gif
     Input URI:  /images/bg.gif
     Output URI: /images/bg.gif

     Input URL:  http://cvsroot.org/images/logo.gif
     Input URI:  /images/logo.gif
     Output URI: /org/cvsroot/images/logo.gif

     Input URL:  http://ransommoney.com/images/bg.gif
     Input URI:  /images/bg.gif
     Output URI: /com/ransommoney/images/bg.gif

     Input URL:  http://inputsignal.com/images/bg.gif
     Input URI:  /images/bg.gif
     Output URI: /com/images/bg.gif

   It also correctly handles extra path info to CGI scripts.  For example
if you add the following files and dirs to the above example:

     cgi-bin/
     cgi-bin/magic.pl
     org/cvsroot/cgi-bin/
     org/cvsroot/cgi-bin/magic.pl

   Apache::AddHostPath would transform the following requested URL/URIs as
follows:

     Input URL: http://cvsroot.org/cgi-bin/magic.pl/param1/param2
     Input URI: /cgi-bin/magic.pl/param1/param2
     Output URI: /org/cvsroot/cgi-bin/magic.pl/param1/param2

     Input URL: http://ransommoney.com/cgi-bin/magic.pl/param1
     Input URI: /cgi-bin/magic.pl/param1
     Output URI: /cgi-bin/magic.pl/param1

   You can debug this URI translation by setting your Apache LogLevel to
"debug".  This will show add messages to your error log showing every URI
combination tested and which one it ended up using.

   This module adds powerful yet simplistic inheritance capabilities to a
multi-domain server.  A number of domains could be set to a single flat
document root initially. Then individual files could be overridden for a
hostname, or set of hostnames, simply by creating the appropriate
directory structures and specific files while leaving the rest of the
domain untouched.

AUTHOR
======

   Robert C W Jenks, rjenks@cvsroot.org

SEE ALSO
========

   perl(1). `mod_perl' in this node

COPYRIGHT
=========

   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.

Simple mod_perl Photo Album
***************************

NAME
====

   Apache::Album - Simple mod_perl Photo Album

SYNOPSIS
========

   Add to httpd.conf

     <Location /albums>
       SetHandler perl-script
       PerlHandler Apache::Album
     #   PerlSetVar  AlbumDir            /albums_loc
     #   PerlSetVar  ThumbNailUse        Width
     #   PerlSetVar  ThumbNailWidth      100
     #   PerlSetVar  ThumbNailAspect     2/11
     #   PerlSetVar  ThumbSubDir         thumbs
     #   PerlSetVar  DefaultBrowserWidth 640
     #   PerlSetVar  NumberOfColumns     0
     #   PerlSetVar  OutsideTableBorder  0
     #   PerlSetVar  InsideTablesBorder  0
     #   PerlSetVar  BodyArgs            BGCOLOR=white
     #   PerlSetVar  Footer              "<EM>Optional Footer Here</EM>"
     #   PerlSetVar  EditMode            0
     #   PerlSetVar  AllowFinalResize    0
     #   PerlSetVar  FinalResizeDir      thumbs
     #   PerlSetVar  ReverseDirs         0
     #   PerlSetVar  ReversePics         0
     </Location>

ABSTRACT
========

   This is a simple photo album.  You simply copy some gif's/jpeg's to a
directory, create an optional text block (in a file called caption.txt) to
go at the top, and the module does the rest.  It does however require that
PerlMagick be installed.

   Default settings in the httpd.conf file may be overriden by using
.htaccess files.

INSTALLATION
============

     perl Makefile.PL
     make
     make install

   (no test necessary)

CONFIGURATION
=============

   The configuration can be a little tricky, so here is a little more
information.  It's important to realize that there are two separate, but
related directories.  One is where the physical pictures reside, the other
is where the "virtual" albums reside.

   Consider a filesystem called /albums exists and it is this filesystem
that will house the images.  Also consider that multiple people will have
albums there, so you would create a directory for each user:

     /albums/jdw/albums_loc
     /albums/travis/albums_loc

   Then in your httpd.conf file you would have the following entry to
allow pictures in those directories to be viewed:

     Alias /jdw /albums/jdw/

   At this point you could view a full sized picture under the directory
/albums/jdw/albums_loc as the url /jdw/albums_loc.

   To have an album that creates thumbnails/captions of those pictures you
would need an entry like:

     <Location /jdw/albums>
      SetHandler perl-script
      AllowOverride None
      Options None
      PerlHandler Apache::Album
      PerlSetVar  AlbumDir /jdw/albums_loc
      PerlSetVar  Footer   "<a href=\"mailto:woody@bga.com\">Jim Woodgate</a>"
     </Location>

   Note how AlbumDir points to the url where the files exist, and the url
you use to access the album will be just like that url, only substituting
albums for albums_loc.

   If anyone knows of a way to accomplish this same thing, but using a
DirectoryIndex instead, please let me know.  I tried and could not get it
to work!

DESCRIPTION
===========

   This module sets up a virtual set of photo albums starting at the
Location definition.  This virtual directory is mapped to a physical
directory under `AlbumDir'.  Under `AlbumDir' create a sub-directory for
each photo album, and copy image files into each subdirectory.  You must
also make the permissions for each subdirectory so that the id which runs
Apache can write to the directory.

   At this point, if you have PerlMagick installed, you can go to
*http://your.site/albums/album_name* Apache::Album will create thumbnails
for each of the images, and send the caption.txt file along with the
thumbnails to the client's browser.  The thumbnails are links to the full
sized images.

The caption.txt file
     The caption.txt file consists of two parts.  The first part is
     text/html that will be placed at the top of the html document.  The
     second part is a mapping of filenames to captions.  The module will do
     some simple mangling of the image file names to create the caption.
     But if it finds a mapping in the caption.txt file, that value is used
     instead.  The value __END__ signifies the end of the first section and
     the beginning of the second.

          For example:

          Image   -> Bob_and_Jenny.jpg
          Caption -> Bob and Jenny       (the auto-generated caption)

          override in caption.txt
          Bob_and_Jenny.jpg: This is me with my sister <EM>Jenny</EM>.

     Here is a sample caption.txt file:

          <H1>My Birthday Party</H1>

          <center>This is me at my Birthday Party!.</center>

          __END__
          pieinface.gif: Here's me getting hit the face with a pie.
          john5.jpg: This is <A HREF="mailto:johndoe@nowhere.com">John</A>

ThumbNail Types
     `ThumbNailUse' can either be set to "width" or "aspect".  If
     `ThumbNailUse' is set to "width", thumbnails that need to be created
     will be `ThumbNailWidth' wide, and the height will be modified to
     keep the same aspect as the original image.

     If `ThumbNailUse' is set to "aspect", thumbnails that need to be
     created will be transformed by the value of `ThumbNailAspect'.
     `ThumbNailAspect' can be either a floating point number like 0.25 or
     it can be a ratio like 2 / 11.

     If an image file is updated, the corresponding thumbnail file will be
     updated the next time the page is accessed.  In practice I have found
     that Netscape will used the cached images even if they are updated.  I
     normally have to flush the cache and reload to see the new images.

     At any time you can `rm -f tn__*' in the `AlbumDir'/album_name/
     directory, the next time the page is loaded all the thumbnails will be
     regenerated.  (Naturally image names that start with tn__ should be
     renamed before placing them in the album directory.)

ThumbSubDir
     If you want your thumbnails to be in a different directory than the
     original pictures, set ThumbSubDir which is the subdirectory the
     thumbnails will be created in and viewed from.  (This could also be
     used to allow multiple sets of thumbnails).

DefaultBrowserWidth
     A general number of how wide you want the final table to be, not an
     absolute number.  If the next image would take it past this "invisible
     line", a new row is started.

NumberOfColumns
     Instead of using DefaultBrowserWidth and a guess at the number of
     pixels, NumberOfColumns can be set to the maximum number of columns in
     a table.  The default is 0 (which causes DefaultBrowserWidth to be
     used instead).

BodyArgs
     This entire string is passed in the <BODY> tag.  Useful for setting
     background images, background color, link colors, etc.  If set in the
     httpd.conf file, you must put quotes around the value, and escape any
     quotes in the value.  If this value is set in the .htaccess file, this
     is not necessary:

          In httpd.conf: PerlSetVar BodyArgs "BACKGROUND=gray.gif text=\"#FFFFFF\""
          In .htaccess : PerlSetVar BodyArgs BACKGROUND=gray.gif text="#FFFFFF"

OutsideTableBorder
     This variable's value is passed to the outer table's BORDER attribute.

InsideTablesBorder
     This variables's value is passed to all the inner table's BORDER
     attributes.  Note that the name of the `InnerTablesBorder' has an 's'
     in it, as it modifes all the inner tables.

Footer
     This text/html will placed at the bottom of the page after all the
     thumbnails, but before the end of the page.  Useful for links back to
     a home page, mailto: tag, etc.

EditMode
     Allows the user to create new albums and upload pictures.  Obviously
     there are security implications here, so if EditMode is turned on that
     location should probably have some kind of security.  Albums can share
     the same AlbumDir, so you can have something like:

     /albums      - ReadOnly version, no security /albums_edit - Allow new
     album creation and picture uploads,                require
     authentication

     both using the same AlbumDir.

AllowFinalResize
     If this is set to true, the user will have 3 additional options when
     viewing the full sized picture.  The thumbnail can still be selected
     to view the full picture, or Sm (Small), Med (Medium), or Lg(Large)
     can be selected to bring the picture down to fit better in a 640x480,
     800x600, or 1024x758 screen.

ReverseDirs
     When viewing albums, they will be sorted by name.  If this is set to
     true the order will be reversed.  (Useful if you want to use things
     like dates/months as the directory names, this will put the most
     recent albums first.

ReversePics
     When viewing pictures, they will be sorted by name.  If this is set to
     true, the order of the pictures will be reversed.

OTHER FEATURES
==============

   For people with lots of bandwidth and memory, Apache::Album can
generate a single page with all the full sized pictures (or all the
Small(sm), Medium(med) or Large(lg) pictures if AllowFinalResize is turned
on).  This is enabled by passing ?all_full_images=sm|med|lg|full to the
url of an album, for example:

   `http://your.web.server/albums/specific_album/?all_full_images=sm'

   Will create a page with all the picutres in an album, but none will be
larger than 640x480.  The pictures will have captions as if the pictures
were being viewed one at a time.

LIMITATIONS
===========

   PerlMagick is a limiting factor.  If PerlMagick can't load the image,
no thumbnail will be created.

COPYRIGHT
=========

   Copyright (c) 1998-2000 Jim Woodgate. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

AUTHOR
======

   Jim Woodgate woody@bga.com

SEE ALSO
========

   perl(1), see Image/Magick,(3).

Expose archive files through the Apache web server.
***************************************************

NAME
====

   Apache::Archive - Expose archive files through the Apache web server.

SYNOPSIS
========

     <Files ~ "\.(tar|tgz|tar\.gz)">
     SetHandler perl-script
     PerlHandler Apache::Archive
     </Files>

DESCRIPTION
===========

   Apache::Archive is a mod_perl extension that allows the Apache HTTP
server to expose tar and tar.gz archives on the fly. When a client
requests such an archive file, the server will return a page displaying
information about the file that allows the user to view or download
individual files from within the archive.

   *Please read the BUGS section before using this on any production
server*

REQUIREMENTS
============

   Apache::Archive requires *mod_perl 1.11* or later, and *Archive::Tar
0.2* or later. Note that *Archive::Tar* itself requires *Compress::Zlib*.
*Apache 1.3.6* or later is recommended. Earlier versions may well work too.

HTTPD CONFIGURATION PARAMETERS
==============================

   Apache::Archive is a straightforward replacement for Apache's normal
handler routine. There are currently three optional parameters that alter
the way Apache::Archive functions. All of these are set using the
PerlSetVar directive.

Months
     This should be a comma seperated list of month names for
     Apache::Archive to use when generating dates. This allows you to use
     names other than English ones, or to use numbers. If this option is
     not specified it will default English three letter abbreviations.

Template
     This is the location of a template file that Apache::Archive should
     use to generate the information page for the archive. If none is
     specified then it will use a built in default. See the section below
     for how to create a template file.

SizeLimit
     This should be a number representing size in Kb. Once Apache has
     handled any archive file larger than this number, that Apache process
     will terminate. This is because Perl does not return allocated memory
     to the kernel, and processes tend to grow to the size of the largest
     file opened. Since Archive::Tar 0.2, tar files do not have to be held
     entirely in memory so this is less of a problem. If set to 0 or not
     set, this feature is disabled. You may also want to consider using
     Apache::SizeLimit if you OS supports it.

   EXAMPLE

     <Files ~ "\.(tar|tgz|tar\.gz)">
     SetHandler perl-script
     PerlHandler Apache::Archive
     PerlSerVar Months '1,2,3,4,5,6,7,8,9,10,11,12'
     PerlSetVar Template /any/path/template.html
     PerlSetVar SizeLimit 5000
     </Files>

TEMPLATE CONFIGURATION FILE
===========================

   Apache::Archive can read in an HTML file containing special tags and
use that as a template for its output. The configuration file should be
readable by the httpd process. It does not need to be in the document
root. The template file must contain a special section delimited by
##StartData and ##EndData. This section httpd process. It does not need to
be in the document root. The template file must contain a special section
delimited by ##StartData and ##EndData. This section is repeated once for
each component file in the archive, with any special tags being
substituted with values of the current component file. A list of possible
tags and what they are substituted with is shown below.

   The first four tags provide information on the tar file itself, and can
be used anywhere in the template file.

   *##ArchiveName*

   The name of the archive file currently being viewed.

   *##ArchiveDate*

   The last modification date of the archive file currently being viewed.

   *##ArchiveSize*

   The size of the archive file currently being viewed.

   *##ArchiveLink*

   An absolute URL that allows the user to download the archive file.

   *##StartData*

   A file in the archive. This tag should be place on a line by itself.

   *##EndData*

   Marks the end of the repeated section. This tag should be placed on a
line by itself.

   The next four tags provide information about one of the component files
in the archive. These tags should only be used between the ##StartData and
##EndData tags.

   *##FileName*

   The name of the archived file.

   *##FileDate*

   The last modification date of the file.

   *##FileSize*

   The size of the file.

   *##FileLink*

   An absolute URL that allows the user to download the file.

   This example is the template used by default.

     <HTML><BODY BGCOLOR="#cccccc">
     <H2>
     <A HREF=##ArchiveLink>##ArchiveName</A>
     </H2>
     ##ArchiveDate<BR>
     ##ArchiveSize<BR>
     This is the contents of the archive:
     <P>
     <TABLE border=4 cellpadding=6 cellspacing=2>
     <TR>
     <TH>View item</TH><TH>Name</TH><TH>Date</TH><TH>Size</TH>
     </TR>
     ##StartData
     <TR>
     	<TD><A HREF=##FileLink>View File</A></TD>
     	<TD>##FileName</TD><TD>##FileDate</TD>
     	<TD>##FileSize</TD>
     </TR>
     ##EndData
     </TABLE></BODY></HTML>

BUGS
====

MEMORY LEAK
     There is a problem with memory leakage. This is greatly reduced with
     Archive::Tar 0.2 and later. Still, if you have a busy site, I advise
     checking memory consumption, and experimenting with the SizeLimit
     variable, or with Apache::SizeLimit. Expect processes to be 10Mb and
     more.

No error checking on template file
     If you create a faulty template file, the server will attempt to use
     it regardless and may behave unpredictably.

Tar files within tar files
     If an archive contains other archives, the sub-archives are not
     passed through the Apache::Archive handler - they are simply treated
     as regular files. This is not really a bug per se, more a missing
     feature.

No support for .zip files
     This will be added later.

AUTHOR
======

   J. Peterson, jon@snowdrift.org

COPYRIGHT
=========

   Copyright 1998-1999, J. Peterson

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   If you have questions or problems regarding use or installation of this
module please feel free to email me directly.

SEE ALSO
========

   Apache, Archive::Tar, Compress::Zlib, Apache::SizeLimit

Perl Authentication and Authorization via cookies
*************************************************

NAME
====

   Apache::AuthCookie - Perl Authentication and Authorization via cookies

SYNOPSIS
========

   Make sure your mod_perl is at least 1.24, with StackedHandlers,
MethodHandlers, Authen, and Authz compiled in.

     # In httpd.conf or .htaccess:
     PerlModule Sample::AuthCookieHandler
     PerlSetVar WhatEverPath /
     PerlSetVar WhatEverLoginScript /login.pl

     # The following line is optional - it allows you to set the domain
     # scope of your cookie.  Default is the current domain.
     PerlSetVar WhatEverDomain .yourdomain.com

     # Use this to only send over a secure connection
     PerlSetVar WhatEverSecure 1

     # Usually documents are uncached - turn off here
     PerlSetVar WhatEverCache 1

     # These documents require user to be logged in.
     <Location /protected>
      AuthType Sample::AuthCookieHandler
      AuthName WhatEver
      PerlAuthenHandler Sample::AuthCookieHandler->authenticate
      PerlAuthzHandler Sample::AuthCookieHandler->authorize
      require valid-user
     </Location>

     # These documents don't require logging in, but allow it.
     <FilesMatch "\.ok$">
      AuthType Sample::AuthCookieHandler
      AuthName WhatEver
      PerlFixupHandler Sample::AuthCookieHandler->recognize_user
     </FilesMatch>

     # This is the action of the login.pl script above.
     <Files LOGIN>
      AuthType Sample::AuthCookieHandler
      AuthName WhatEver
      SetHandler perl-script
      PerlHandler Sample::AuthCookieHandler->login
     </Files>

DESCRIPTION
===========

   *Apache::AuthCookie* allows you to intercept a user's first
unauthenticated access to a protected document. The user will be presented
with a custom form where they can enter authentication credentials. The
credentials are posted to the server where AuthCookie verifies them and
returns a session key.

   The session key is returned to the user's browser as a cookie. As a
cookie, the browser will pass the session key on every subsequent
accesses. AuthCookie will verify the session key and re-authenticate the
user.

   All you have to do is write a custom module that inherits from
AuthCookie.  Your module is a class which implements two methods:

`authen_cred()'
     Verify the user-supplied credentials and return a session key.  The
     session key can be any string - often you'll use some string
     containing username, timeout info, and any other information you need
     to determine access to documents, and append a one-way hash of those
     values together with some secret key.

`authen_ses_key()'
     Verify the session key (previously generated by `authen_cred()',
     possibly during a previous request) and return the user ID.  This user
     ID will be fed to `$r->connection->user()' to set Apache's idea of
     who's logged in.

   By using AuthCookie versus Apache's built-in AuthBasic you can design
your own authentication system.  There are several benefits.

  1. The client doesn't *have* to pass the user credentials on every
     subsequent access.  If you're using passwords, this means that the
     password can be sent on the first request only, and subsequent
     requests don't need to send this (potentially sensitive) information.
     This is known as "ticket-based" authentication.

  2. When you determine that the client should stop using the
     credentials/session key, the server can tell the client to delete the
     cookie.  Letting users "log out" is a notoriously impossible-to-solve
     problem of AuthBasic.

  3. AuthBasic dialog boxes are ugly.  You can design your own HTML login
     forms when you use AuthCookie.

  4. You can specify the domain of a cookie using PerlSetVar commands.  For
     instance, if your AuthName is `WhatEver', you can put the command

          PerlSetVar WhatEverDomain .yourhost.com

     into your server setup file and your access cookies will span all
     hosts ending in `.yourhost.com'.

        This is the flow of the authentication handler, less the details
of the redirects. Two REDIRECT's are used to keep the client from
displaying the user's credentials in the Location field. They don't really
change AuthCookie's model, but they do add another round-trip request to
the client.

     *  The session key that the client gets can be anything you want.  For
        example, encrypted information about the user, a hash of the
        username and password (similar in function to Digest
        authentication), or the user name and password in plain text
        (similar in function to HTTP Basic authentication).

     The only requirement is that the authen_ses_key function that you
     create must be able to determine if this session_key is valid and
     map it back to the originally authenticated user ID.

   `Apache::AuthCookie' has several methods you should know about.  Here
is the documentation for each. =)

   * authenticate()

     This method is one you'll use in a server config file (httpd.conf,
     .htaccess, ...) as a PerlAuthenHandler.  If the user provided a
     session key in a cookie, the `authen_ses_key()' method will get
     called to check whether the key is valid.  If not, or if there is no
     key provided, we redirect to the login form.

   * authorize()

     This will step through the require directives you've given for
     protected documents and make sure the user passes muster.  The
     `require valid-user' and `require user joey-jojo' directives are
     handled for you.  You can implement custom directives, such as
     `require species hamster', by defining a method called `hamster()' in
     your subclass, which will then be called.  The method will be called
     as `$r->hamster($r, $args)', where $args is everything on your
     require line after the word `hamster'.  The method should return OK
     on success and FORBIDDEN on failure.

     Currently users must satisfy ALL of the require directives.  I have
     heard that other Apache modules let the user satisfy ANY of the
     require directives.  I don't know which is correct, I haven't found
     any Apache docs on the matter.  If you need one behavior or the other,
     be careful.  I may change it if I discover that ANY is correct.

   * authen_cred()

     You must define this method yourself in your subclass of
     `Apache::AuthCookie'.  Its job is to create the session key that will
     be preserved in the user's cookie.  The arguments passed to it are:

          sub authen_cred ($$\@) {
            my $self = shift;  # Package name (same as AuthName directive)
            my $r    = shift;  # Apache request object
            my @cred = @_;     # Credentials from login form

          ...blah blah blah, create a session key...
          return $session_key;
           }

     The only limitation on the session key is that you should be able to
     look at it later and determine the user's username.  You are
     responsible for implementing your own session key format.  A typical
     format is to make a string that contains the username, an expiration
     time, whatever else you need, and an MD5 hash of all that data
     together with a secret key.  The hash will ensure that the user
     doesn't tamper with the session key.  More info in the Eagle book.

   * authen_ses_key()

     You must define this method yourself in your subclass of
     Apache::AuthCookie.  Its job is to look at a session key and determine
     whether it is valid.  If so, it returns the username of the
     authenticated user.

          sub authen_ses_key ($$$) {
            my ($self, $r, $session_key) = @_;
            ...blah blah blah, check whether $session_key is valid...
            return $ok ? $username : undef;
          }

   * login()

     This method handles the submission of the login form.  It will call
     the `authen_cred()' method, passing it $r and all the submitted data
     with names like `"credential_#"', where # is a number.  These will be
     passed in a simple array, so the prototype is `$self->authen_cred($r,
     @credentials)'.  After calling `authen_cred()', we set the user's
     cookie and redirect to the URL contained in the `"destination"'
     submitted form field.

   * login_form()

     This method is responsible for displaying the login form. The default
     implementation will make an internal redirect and display the URL you
     specified with the `PerlSetVar WhatEverLoginForm' configuration
     directive. You can overwrite this method to provide your own
     mechanism.

   * logout()

     This is simply a convenience method that unsets the session key for
     you.  You can call it in your logout scripts.  Usually this looks like
     `$r->auth_type->logout($r);'.

   * send_cookie($session_key)

     By default this method simply sends out the session key you give it.
     If you need to change the default behavior (perhaps to update a
     timestamp in the key) you can override this method.

   * recognize_user()

     If the user has provided a valid session key but the document isn't
     protected, this method will set `$r->connection->user' anyway.  Use
     it as a PerlFixupHandler, unless you have a better idea.

   * key()

     This method will return the current session key, if any.  This can be
     handy inside a method that implements a require directive check (like
     the species method discussed above) if you put any extra information
     like clearances or whatever into the session key.

UPGRADING FROM VERSION 1.4
==========================

   There are a few interface changes that you need to be aware of when
migrating from version 1.x to 2.x.  First, the authen() and authz()
methods are now deprecated, replaced by the new authenticate() and
authorize() methods.  The old methods will go away in a couple versions,
but are maintained intact in this version to ease the task of upgrading.
The use of these methods is essentially the same, though.

   Second, when you change to the new method names (see previous
paragraph), you must change the action of your login forms to the location
/LOGIN (or whatever URL will call your module's login() method).  You may
also want to change their METHOD to POST instead of GET, since that's much
safer and nicer to look at (but you can leave it as GET if you bloody well
want to, for some god-unknown reason).

   Third, you must change your login forms (see `THE LOGIN SCRIPT' in this
node below) to indicate how requests should be redirected after a
successful login.

   Fourth, you might want to take advantage of the new logout() method,
though you certainly don't have to.

EXAMPLE
=======

   For an example of how to use Apache::AuthCookie, you may want to check
out the test suite, which runs AuthCookie through a few of its paces.  The
documents are located in t/eg/, and you may want to peruse t/real.t to see
the generated httpd.conf file (at the bottom of real.t) and check out what
requests it's making of the server (at the top of real.t).

THE LOGIN SCRIPT
================

   You will need to create a login script (called login.pl above) that
generates an HTML form for the user to fill out.  You might generate the
page using an Apache::Registry script, or an HTML::Mason component, or
perhaps even using a static HTML page.  It's usually useful to generate it
dynamically so that you can define the 'destination' field correctly (see
below).

   The following fields must be present in the form:

  1. The ACTION of the form must be /LOGIN (or whatever you defined in your
     server configuration as handled by the ->login() method - see example
     in the SYNOPSIS section).

  2. The various user input fields (username, passwords, etc.) must be
     named 'credential_0', 'credential_1', etc. on the form.  These will
     get passed to your authen_cred() method.

  3. You must define a form field called 'destination' that tells
     AuthCookie where to redirect the request after successfully logging
     in.  Typically this value is obtained from `$r->prev->uri'.  See the
     login.pl script in t/eg/.

        In addition, you might want your login page to be able to tell the
difference between a user that sent an incorrect auth cookie, and a user
that sent no auth cookie at all.  These typically correspond,
respectively, to users who logged in incorrectly or aren't allowed to
access the given page, and users who are trying to log in for the first
time.  To help you differentiate between the two, *AuthCookie* will set
`$r->subprocess_env('AuthCookieReason')' to either `bad_cookie' or
`no_cookie'.  You can examine this value in your login form by examining
`$r->prev->subprocess_env('AuthCookieReason')' (because it's a
sub-request).

   Of course, if you want to give more specific information about why
access failed when a cookie is present, your `authen_ses_key()' method can
set arbitrary entries in `$r->subprocess_env'.

THE LOGOUT SCRIPT
=================

   If you want to let users log themselves out (something that can't be
done using Basic Auth), you need to create a logout script.  For an
example, see t/eg/logout.pl.  Logout scripts may want to take advantage of
AuthCookie's logout() method, which will set the proper cookie headers in
order to clear the user's cookie.  This usually looks like
`$r->auth_type->logout($r);'.

   Note that if you don't necessarily trust your users, you can't count on
cookie deletion for logging out.  You'll have to expire some server-side
login information too.  AuthCookie doesn't do this for you, you have to
handle it yourself.

ABOUT SESSION KEYS
==================

   Unlike the sample AuthCookieHandler, you have you verify the user's
login and password in `authen_cred()', then you do something like:

     my $date = localtime;
     my $ses_key = MD5->hexhash(join(';', $date, $PID, $PAC));

   save `$ses_key' along with the user's login, and return `$ses_key'.

   Now `authen_ses_key()' looks up the `$ses_key' passed to it and returns
the saved login.  I use Oracle to store the session key and retrieve it
later, see the ToDo section below for some other ideas.

KNOWN LIMITATIONS
=================

   If the first unauthenticated request is a POST, it will be changed to a
GET after the user fills out the login forms, and POSTed data will be lost.

TO DO
-----

   * There ought to be a way to solve the POST problem in the LIMITATIONS
     section.  It involves being able to re-insert the POSTed content into
     the request stream after the user authenticates.

     It might be nice if the logout method could accept some parameters
     that could make it easy to redirect the user to another URI, or
     whatever.  I'd have to think about the options needed before I
     implement anything, though.

AUTHOR
======

   Ken Williams, ken@forum.swarthmore.edu

   Originally written by Eric Bartley, bartley@purdue.edu

SEE ALSO
========

   `perl(1)' in this node, `mod_perl(1)' in this node, `Apache(1)' in this
node.

An AuthCookie module backed by a DBI database.
**********************************************

NAME
====

   Apache::AuthCookieDBI - An AuthCookie module backed by a DBI database.

VERSION
=======

     $Revision: 1.18 $

SYNOPSIS
========

     # In httpd.conf or .htaccess
     PerlModule Apache::AuthCookieDBI
     PerlSetVar WhatEverPath /
     PerlSetVar WhatEverLoginScript /login.pl

     # Optional, to share tickets between servers.
     PerlSetVar WhatEverDomain .domain.com

     # These must be set
     PerlSetVar WhatEverDBI_DSN "DBI:mysql:database=test"
     PerlSetVar WhatEverDBI_SecretKeyFile /etc/httpd/acme.com.key

     # These are optional, the module sets sensible defaults.
     PerlSetVar WhatEverDBI_User "nobody"
     PerlSetVar WhatEverDBI_Password "password"
     PerlSetVar WhatEverDBI_UsersTable "users"
     PerlSetVar WhatEverDBI_UserField "user"
     PerlSetVar WhatEverDBI_PasswordField "password"
     PerlSetVar WhatEverDBI_CryptType "none"
     PerlSetVar WhatEverDBI_GroupsTable "groups"
     PerlSetVar WhatEverDBI_GroupField "grp"
     PerlSetVar WhatEverDBI_GroupUserField "user"
     PerlSetVar WhatEverDBI_EncryptionType "none"
     PerlSetVar WhatEverDBI_SessionLifetime 00-24-00-00

     # Protected by AuthCookieDBI.
     <Directory /www/domain.com/authcookiedbi>
     	AuthType Apache::AuthCookieDBI
     	AuthName WhatEver
     	PerlAuthenHandler Apache::AuthCookieDBI->authenticate
     	PerlAuthzHandler Apache::AuthCookieDBI->authorize
     	require valid-user
     	# or you can require users:
     	require user jacob
     	# You can optionally require groups.
     	require group system
     </Directory>

     # Login location.  *** DEBUG *** I still think this is screwy
     <Files LOGIN>
     	AuthType Apache::AuthCookieDBI
     	AuthName WhatEver
     	SetHandler perl-script
     	PerlHandler Apache::AuthCookieDBI->login
     </Files>

DESCRIPTION
===========

   This module is an authentication handler that uses the basic mechanism
provided by Apache::AuthCookie with a DBI database for ticket-based
protection.  It is based on two tokens being provided, a username and
password, which can be any strings (there are no illegal characters for
either).  The username is used to set the remote user as if Basic
Authentication was used.

   On an attempt to access a protected location without a valid cookie
being provided, the module prints an HTML login form (produced by a CGI or
any other handler; this can be a static file if you want to always send
people to the same entry page when they log in).  This login form has
fields for username and password.  On submitting it, the username and
password are looked up in the DBI database.  The supplied password is
checked against the password in the database; the password in the database
can be plaintext, or a crypt() or md5_hex() checksum of the password.  If
this succeeds, the user is issued a ticket.  This ticket contains the
username, an issue time, an expire time, and an MD5 checksum of those and
a secret key for the server.  It can optionally be encrypted before
returning it to the client in the cookie; encryption is only useful for
preventing the client from seeing the expire time.  If you wish to protect
passwords in transport, use an SSL-encrypted connection.  The ticket is
given in a cookie that the browser stores.

   After a login the user is redirected to the location they originally
wished to view (or to a fixed page if the login "script" was really a
static file).

   On this access and any subsequent attempt to access a protected
document, the browser returns the ticket to the server.  The server
unencrypts it if encrypted tickets are enabled, then extracts the
username, issue time, expire time and checksum.  A new checksum is
calculated of the username, issue time, expire time and the secret key
again; if it agrees with the checksum that the client supplied, we know
that the data has not been tampered with.  We next check that the expire
time has not passed.  If not, the ticket is still good, so we set the
username.

   Authorization checks then check that any "require valid-user" or
"require user jacob" settings are passed.  Finally, if a "require group
foo" directive was given, the module will look up the username in a groups
database and check that the user is a member of one of the groups listed.
If all these checks pass, the document requested is displayed.

   If a ticket has expired or is otherwise invalid it is cleared in the
browser and the login form is shown again.

APACHE CONFIGURATION DIRECTIVES
===============================

   All configuration directives for this module are passed in PerlSetVars.
These PerlSetVars must begin with the AuthName that you are describing,
so if your AuthName is PrivateBankingSystem they will look like:

     PerlSetVar PrivateBankingSystemDBI_DSN "DBI:mysql:database=banking"

   See also `Apache::Authcookie' in this node for the directives required
for any kind of Apache::AuthCookie-based authentication system.

   In the following descriptions, replace "WhatEver" with your particular
AuthName.  The available configuration directives are as follows:

`WhatEverDBI_DSN'
     Specifies the DSN for DBI for the database you wish to connect to
     retrieve user information.  This is required and has no default value.

`WhatEverDBI_User'
     The user to log into the database as.  This is not required and
     defaults to undef.

`WhatEverDBI_Password'
     The password to use to access the database.  This is not required and
     defaults to undef.

`WhatEverDBI_UsersTable'
     The table that user names and passwords are stored in.  This is not
     required and defaults to 'users'.

`WhatEverDBI_UserField'
     The field in the above table that has the user name.  This is not
     required and defaults to 'user'.

`WhatEverDBI_PasswordField'
     The field in the above table that has the password.  This is not
     required and defaults to 'password'.

`WhatEverDBI_CryptType'
     What kind of hashing is used on the password field in the database.
     This can be 'none', 'crypt', or 'md5'.  This is not required and
     defaults to 'none'.

`WhatEverDBI_GroupsTable'
     The table that has the user / group information.  This is not
     required and defaults to 'groups'.

`WhatEverDBI_GroupField'
     The field in the above table that has the group name.  This is not
     required and defaults to 'grp' (to prevent conflicts with the SQL
     reserved word 'group').

`WhatEverDBI_GroupUserField'
     The field in the above table that has the user name.  This is not
     required and defaults to 'user'.

`WhatEverDBI_SecretKeyFile'
     The file that contains the secret key (on the first line of the
     file).  This is required and has no default value.  This key should
     be owned and only readable by root.  It is read at server startup
     time.  The key should be long and fairly random.  If you want, you
     can change it and restart the server, (maybe daily), which will
     invalidate all prior-issued tickets.

`WhatEverDBI_EncryptionType'
     What kind of encryption to use to prevent the user from looking at
     the fields in the ticket we give them.  This is almost completely
     useless, so don't switch it on unless you really know you need it.
     It does not provide any protection of the password in transport; use
     SSL for that.  It can be 'none', 'des', 'idea', 'blowfish', or
     'blowfish_pp'.

     This is not required and defaults to 'none'.

`WhatEverDBI_SessionLifetime'
     How long tickets are good for after being issued.  Note that presently
     Apache::AuthCookie does not set a client-side expire time, which
     means that most clients will only keep the cookie until the user
     quits the browser.  However, if you wish to force people to log in
     again sooner than that, set this value.  This can be 'forever' or a
     life time specified as:

          DD-hh-mm-ss -- Days, hours, minute and seconds to live.

     This is not required and defaults to '00-24-00-00' or 24 hours.

DATABASE SCHEMAS
================

   For this module to work, the database tables must be laid out at least
somewhat according to the following rules:  the user field must be a
primary key so there is only one row per user; the password field must be
NOT NULL.  If you're using MD5 passwords the password field must be 32
characters long to allow enough space for the output of md5_hex().  If
you're using crypt() passwords you need to allow 13 characters.

   An minimal CREATE TABLE statement might look like:

     CREATE TABLE users (
     	user VARCHAR(16) PRIMARY KEY,
     	password VARCHAR(32) NOT NULL
     )

   For the groups table, the access table is actually going to be a join
table between the users table and a table in which there is one row per
group if you have more per-group data to store; if all you care about is
group membership though, you only need this one table.  The only
constraints on this table are that the user and group fields be NOT NULL.

   A minimal CREATE TABLE statement might look like:

     CREATE TABLE groups (
     	grp VARCHAR(16) NOT NULL,
     	user VARCHAR(16) NOT NULL
     )

COPYRIGHT
=========

   Copyright (C) 2000 SF Interactive, Inc.  All rights reserved.

LICENSE
=======

   This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or (at
your option) any later version.

   This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
License for more details.

   You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

AUTHOR
======

   Jacob Davies

     <jacob@sfinteractive.com>
     <jacob@well.com>

SEE ALSO
========

   Apache::AuthCookie(1)

Perl Authentication and Authorization or session management via cookies or URL munging
**************************************************************************************

NAME
====

   Apache::AuthCookieURL - Perl Authentication and Authorization or
session management via cookies or URL munging

SYNOPSIS
========

   In httpd.conf

     # Your module that overrides AuthCookieURL methods
     PerlModule My::AuthCookieURLHandler

     # Or to use simple session generation w/o persistence
     #PerlModule Apache::AuthCookieURL

     ## Some settings -- "Whatever" is set by AuthName ##
     # most can be set within <directory> sections

     # Send expires with cookie
     PerlSetVar WhateverExpires +90d

     # Other cookie settings
     #PerlSetVar WhateverDomain some.domain

     # This can only be set to "/" if using URL sessions
     #PerlSetVar WhateverPath /path
     #PerlSetVar WhateverSecure 1

     # Login script to call
     PerlSetVar WhateverLoginScript /login.pl

     # Or for just session management without a login script
     #PerlSetVar WhateverLoginScript NONE

     # Debugging options
     #PerlSetVar AuthCookieURLDebug 5

     # Disable cookies (only URL based sessions)
     #PerlSetVar WhateverNoCookie 1

     # Define a string that indicates to AuthCookieURL
     # what a session looks like
     # This can only be in main config
     #PerlSetVar SessionPrefix Session-

     # This block enables URL session handling
     PerlTransHandler  Apache::AuthCookieURLHandler->URLsession

     ErrorDocument 302 /MISSING
     ErrorDocument 301 /MISSING
     <Location /MISSING>
         SetHandler perl-script
         PerlHandler Apache::AuthCookieURLHandler->error_document
     </Location>

     <Location /protected>
         AuthType Apache::AuthCookieURLHandler
         AuthName Whatever
         PerlAuthenHandler Apache::AuthCookieURLHandler->authenticate
         PerlAuthzHandler Apache::AuthCookieURLHandler->authorize
         require valid-user
     </Location>

     # provide open access to some areas below
     <Location /protected/open>
         PerlSetVar DisableAuthCookieURL 1
     </Location>

     # or if the entire directory tree was protected
     <Location /images>
         PerlSetVar DisableAuthCookieURL 1
     </Location>

     # Make sure the login script can be run
     <Files login.pl>
          Options +ExecCGI
          SetHandler perl-script
          PerlHandler Apache::Registry
     </Files>

     # LOGIN is the action defined by the login.pl script

     <Files LOGIN>
          AuthType Apache::AuthCookieURLHandler
          AuthName Whatever
          SetHandler perl-script
          PerlHandler Apache::AuthCookieURLHandler->login
     </Files>

     # Note: If protecting the entire web site (from root down) then
     # the action *must* be C</LOGIN> as the module looks for this string.

     # better to just invalidate the session, of course
     <Files LOGOUT>
          AuthType Apache::AuthCookieURLHandler
          PerlSetVar WhateverLogoutURI /
          AuthName Whatever
          SetHandler perl-script
          PerlHandler Apache::AuthCookieURLHandler->logout
     </Files>

DESCRIPTION
===========

   ** Warning: beta software.  This should be used for testing purposes
only.  That said, there are a few people using it and I've been using it
for a few months without problem.  The interface may change (or disappear)
without notice.  Please report any problems or comments back to Bill
Moseley <moseley@hank.org>.

   This module is a modification of Ken Williams
<ken@forum.swarthmore.edu> Apache::AuthCookie.  Please see perldoc
Apache::AuthCookie for complete instructions.  As this is intended to be a
drop-in replacement for Apache::AuthCookie you may wish to install and
test with Ken's Apache::AuthCookie before trying AuthCookieURL.

   Basically, this module allows you to catch any unauthenticated access
and redirect to a login script that you define.  The login script posts
credentials (e.g. username and password) and your module can then validate
and provide a session key.  The session key is sent in a cookie, and also
in a munged URL and a redirect is issued and the process starts all over.

   Typically, you will write your own module that will override methods in
Apache::AuthCookieURL.  These methods are described completely in Ken's
Apache::AuthCookie.  Your methods will be used to generate and validate
session keys.  You can use Apache::AuthCookieURL without overriding its
methods and then AuthCookieURL can be used as a simple session manager.

   With this module you should be able to enable session management for an
entire site using <Location />, and then allow access to, say, the images
directory, and also require password access to other locations.  One issue
at this point is that the session key is stripped from URLs in a Trans
handler.  So you would need to use cookies to use different session keys
for different parts of your web tree.

   Apache::AuthCookieURL adds the following features to Apache::AuthCookie.

   * URL munging

     If the PerlTransHandler is enabled in httpd.conf the session key will
     also be placed in the URL.  The session will be removed from the URL
     if cookies are enabled on the next request.  Typically, someone
     visiting your site with cookies enabled will never see the munged URL.

     To make URL sessions work you must use relative links in your
     documents so the client/browser knows to place the session key on all
     links.  CGI scripts can also access the session information via the
     environment.

   * Simple Session Management

     If the login script is set to `NONE' with PerlSetVar
     WhateverLoginScript NONE then Apache::AuthCookeURL acts like a simple
     session manager:  your module will provide a new session key if one
     is not provided with the request, or if the one provided is invalid.

   * Really Simple Session Management

     Apache::AuthCookieURL provides default authen_cred() and
     authen_ses_key() methods that generates a (questionably) random
     session key.  This means you can use AuthCookieURL directly without
     subclassing for really simple session management without any
     persistence of session keys.

   Unless you are not subclassing this module (and using the default
methods provide), your own module must define two methods: authen_cred()
and authen_ses_key(), and then subclass by including Apache::AuthCookieURL
in your module's @ISA array.  Again, please see Apache::AuthCookie for
complete documentation.

   * authen_cred()

     This method verifies the credentials (e.g. username/password) and
     returns a session key.  If the credentials are not acceptable then
     you can return a list, with the second element being an error message
     that is placed in a cookie.  This allows your login script to display
     a failure reason.  This method is needed since a redirect is done
     before your login script is executed again.  Of course, this requires
     that the client has cookies enabled.

     Another method is to return a session key that is really an error
     code and generate messages based on that returned session (error)
     code.

   * authen_ses_key()

     This method's job is to validate and convert a session key into a
     username and return it.  AuthCookieURL places the returned value into
     $ENV{REMOTE_USER}.

CONFIGURATION SETTINGS
======================

   Configuration settings are set with the PerlSetVar directive:

     PerlSetVar WhateverExpires +90d

   "Whatever" is whatever the current AuthName is set.  I think I might
remove this and instead just use the settings as Apache dir_merge returns
them.  In other words, if you want a setting to override a global setting,
then use it within a <directory>, <file>, or <location> section.

   * AuthCookieURLDebug

     Sets the debugging level.  Since some debugging info is generated in
     the Trans handler this needs to be set in the main httpd config.
     Default is 0.

     Example: PerlSetVar AuthCookieURLDebug 5

   * SessionPrefix

     SessionPrefix sets the prefix used by the Trans handler to recognize
     the session in the URL (thus needs to be set in the main config), and
     to create the session ID.  Default is 'Session-'.

     Example: PerlSetVar SessionPrefix ID-

   * WhateverCache

     UNLESS set then $r->no_cache(1) will be called when processing the
     login and logout requests.  Defaults to unset and thus
     $r->no_cache(1) IS called.

     Example: PerlSetVar WhateverCache 1

   * WhateverLogoutURI

     Sets where you are redirected after requesting the logout URL (see
     SYNOPSIS).  Defaults to '/'.

     Example: PerlSetVar WhateverLogoutURI /gone.html

   * DisableAuthCookieURL

     This causes the Authen and Authz handlers to return OK.  In other
     words,

          <Location /protected/notprotected>
              PerlSetVar DisableAuthCookieURL 1
          </Location>

     Allows full access to the notprotected directory.

   * WhateverLoginScript

     This sets the Login script to be executed when authorization is
     required (no valid session key was sent by cookie or URL).  This
     login script can be a CGI script, Apache::Registry script, or a
     mod_perl handler.

     If set to `NONE' then AuthCookieURL will be in simple session
     management mode.  AuthCookieURL->login will be called which calls
     authen_cred() to generate a session key.  authen_cred() should just
     return a session key without checking the credentials.

     If you do not override AuthCookieURL::authen_cred(), then
     AuthCookieURL::authen_cred() simply returns this for a session key.

          return time . $$ . int rand $$;

     Example: PerlSetVar WhateverLoginScript /login.pl          PerlSetVar
     WhateverLoginScript NONE

   * WhateverNoCookie

     Turns off cookies.

     Example: PerlSetVar WhateverNoCookie 1

   * Whatever(Path|Expires|Domain|Secure)

     These all control the values sent in cookies.  Path, if used, must be
     '/' if using URL-based sessions.

     Example: PerlSetVar WhateverPath /

ENVIRONMENT AND NOTES
=====================

   Apache::AuthCookieURL sets some environment variables and Apache notes:

   authen_ses_key() returns a value that is placed in $ENV{REMOTE_USER}.
authen_ses_key() normally converts the session key into a username.

   $ENV{SESSION} contains the current session key

   $ENV{AuthCookieURLReason} contains the reason authentication failed.
Either 'no_session_provided' or 'bad_session_provided'.

   $r->notes( 'URI_Session' ) is the session extracted from the URI

   $r->notes('Session_prefix') is the prefix used with the session keys,
of course.

   $r->notes( 'SESSION' ) is the full session, including the prefix.

WARNING
=======

   URL munging has security issues.  Session keys can get written to
access logs, cached by browsers, leak outside your site, and are broken if
your pages use absolute links to other pages on-site.

TO DO
=====

   Apache::AuthCookieURL uses error documents to try to fixup any
redirects.  The obvious example is when a request is made for a directory
without a trailing slash and Apache issues a redirect.  (Actually,
AuthCookieURL tries to detect this case and rewrite the URL before Apache
redirects.)  I wish I knew a better way to fixup Location: headers in
redirects without sub-requesting every request.  There's no way to catch a
CGI script or module that might issue a Location: header or REDIRECT.  I
guess that's left for Apache 2.0 when all output can be filtered.

REQUIRED
========

   mod_perl 1.24, Apache::Cookie

AUTHOR
======

   Bill Moseley <moseley@hank.org> made minor changes to Ken Williams'
<ken@forum.swarthmore.edu> Apache::AuthCookie.

   Thanks very much to Ken for Apache::AuthCookie.

VERSION
=======

     $Revision: 1.3 $

SEE ALSO
========

   See Apache/AuthCookie,

Authentication and Authorization via Perl's DBI
***********************************************

NAME
====

   Apache::AuthDBI - Authentication and Authorization via Perl's DBI

SYNOPSIS
========

     # Configuration in httpd.conf or startup.pl:

     PerlModule Apache::AuthDBI

     # Authentication and Authorization in .htaccess:

     AuthName DBI
     AuthType Basic

     PerlAuthenHandler Apache::AuthDBI::authen
     PerlAuthzHandler  Apache::AuthDBI::authz

     PerlSetVar Auth_DBI_data_source   dbi:driver:dsn
     PerlSetVar Auth_DBI_username      db_username
     PerlSetVar Auth_DBI_password      db_password
     #DBI->connect($data_source, $username, $password)

     PerlSetVar Auth_DBI_pwd_table     users
     PerlSetVar Auth_DBI_uid_field     username
     PerlSetVar Auth_DBI_pwd_field     password
     # authentication: SELECT pwd_field FROM pwd_table WHERE uid_field=$user
     PerlSetVar Auth_DBI_grp_field     groupname
     # authorization: SELECT grp_field FROM pwd_table WHERE uid_field=$user

     require valid-user
     require user   user_1  user_2 ...
     require group group_1 group_2 ...

   The AuthType is limited to Basic. You may use one or more valid require
lines.  For a single require line with the requirement 'valid-user' or
with the requirements 'user user_1 user_2 ...' it is sufficient to use
only the authentication handler.

DESCRIPTION
===========

   This module allows authentication and authorization against a database
using Perl's DBI. For supported DBI drivers see:

     http://www.symbolstone.org/technology/perl/DBI/

   Authentication:

   For the given username the password is looked up in the cache. If the
cache is not configured or if the user is not found in the cache, or if
the given password does not match the cached password, it is requested
from the database.

   If the username does not exist and the authoritative directive is set
to 'on', the request is rejected. If the authoritative directive is set to
'off', the control is passed on to next module in line.

   If the password from the database for the given username is empty and
the nopasswd directive is set to 'off', the request is rejected. If the
nopasswd directive is set to 'on', any password is accepted.

   Finally the passwords (multiple passwords per userid are allowed) are
retrieved from the database. The result is put into the environment
variable REMOTE_PASSWORDS. Then it is compared to the password given. If
the encrypted directive is set to 'on', the given password is encrypted
using perl's crypt() function before comparison. If the encrypted
directive is set to 'off' the plain-text passwords are compared.

   If this comparison fails the request is rejected, otherwise the request
is accepted and the password is put into the environment variable
REMOTE_PASSWORD.

   The SQL-select used for retrieving the passwords is as follows:

     SELECT pwd_field FROM pwd_table WHERE uid_field = user

   If a pwd_whereclause exists, it is appended to the SQL-select.

   This module supports in addition a simple kind of logging mechanism.
Whenever the handler is called and a log_string is configured, the
log_field will be updated with the log_string. As log_string - depending
upon the database - macros like TODAY can be used.

   The SQL-select used for the logging mechanism is as follows:

     UPDATE pwd_table SET log_field = log_string WHERE uid_field = user

   Authorization:

   When the authorization handler is called, the authentication has
already been done. This means, that the given username/password has been
validated.

   The handler analyzes and processes the requirements line by line. The
request is accepted if the first requirement is fulfilled.

   In case of 'valid-user' the request is accepted.

   In case of one or more user-names, they are compared with the given
user-name until the first match.

   In case of one or more group-names, all groups of the given username are
looked up in the cache. If the cache is not configured or if the user is
not found in the cache, or if the requested group does not match the
cached group, the groups are requested from the database. A comma
separated list of all these groups is put into the environment variable
REMOTE_GROUPS. Then these groups are compared with the required groups
until the first match.

   If there is no match and the authoritative directive is set to 'on' the
request is rejected.

   In case the authorization succeeds, the environment variable
REMOTE_GROUP is set to the group name, which can be used by user scripts
without accessing the database again.

   The SQL-select used for retrieving the groups is as follows (depending
upon the existence of a grp_table):

     SELECT grp_field FROM pwd_table WHERE uid_field = user
     SELECT grp_field FROM grp_table WHERE uid_field = user

   This way the group-information can either be held in the main users
table, or in an extra table, if there is an m:n relationship between users
and groups.  From all selected groups a comma-separated list is build,
which is compared with the required groups. If you don't like normalized
group records you can put such a comma-separated list of groups (no
spaces) into the grp_field instead of single groups.

   If a grp_whereclause exists, it is appended to the SQL-select.

   Cache:

   The module maintains an optional cash for all passwords/groups. See the
method setCacheTime(n) on how to enable the cache. Every server has it's
own cache. Optionally the cache can be put into a shared memory segment,
so that it can be shared among all servers. See the CONFIGURATION section
on how to enable the usage of shared memory.

   In order to prevent the cache from growing indefinitely a
CleanupHandler can be initialized, which skips through the cache and
deletes all outdated entries.  This can be done once per request after
sending the response, hence without slowing down response time to the
client. The minimum time between two successive runs of the CleanupHandler
is configurable (see the CONFIGURATION section). The default is 0, which
runs the CleanupHandler after every request.

     =head1 LIST OF TOKENS

   * Auth_DBI_data_source (Authentication and Authorization)

     The data_source value has the syntax 'dbi:driver:dsn'. This parameter
     is passed to the database driver for processing during connect. The
     data_source parameter (as well as the username and the password
     parameters) may be a tilde ('~') separated list of several
     data_sources. All of these triples will be used until a successful
     connect is made. This way several backup-servers can be configured.
     if you want to use the environment variable DBI_DSN instead of a
     data_source, do not specify this parameter at all.

   * Auth_DBI_username (Authentication and Authorization)

     The username argument is passed to the database driver for processing
     during connect. This parameter may be a tilde ('~') separated list.
     See the data_source parameter above for the usage of a list.

   * Auth_DBI_password (Authentication and Authorization)

     The password argument is passed to the database driver for processing
     during connect. This parameter may be a tilde ('~')  separated list.
     See the data_source parameter above for the usage of a list.

   * Auth_DBI_pwd_table (Authentication and Authorization)

     Contains at least the fields with the username and the (possibly
     encrypted) password. The username should be unique.

   * Auth_DBI_uid_field (Authentication and Authorization)

     Field name containing the username in the Auth_DBI_pwd_table.

   * Auth_DBI_pwd_field (Authentication only)

     Field name containing the password in the Auth_DBI_pwd_table.

   * Auth_DBI_pwd_whereclause (Authentication only)

     Use this option for specifying more constraints to the SQL-select.

   * Auth_DBI_grp_table (Authorization only)

     Contains at least the fields with the username and the groupname.

   * Auth_DBI_grp_field (Authorization only)

     Field-name containing the groupname in the Auth_DBI_grp_table.

   * Auth_DBI_grp_whereclause (Authorization only)

     Use this option for specifying more constraints to the SQL-select.

   * Auth_DBI_log_field (Authentication only)

     Field name containing the log string in the Auth_DBI_pwd_table.

   * Auth_DBI_log_string (Authentication only)

     String to update the Auth_DBI_log_field in the Auth_DBI_pwd_table.
     Depending upon the database this can be a macro like 'TODAY'.

   * Auth_DBI_authoritative  < on / off> (Authentication and Authorization)

     Default is 'on'. When set 'on', there is no fall-through to other
     authentication methods if the authentication check fails. When this
     directive is set to 'off', control is passed on to any other
     authentication modules. Be sure you know what you are doing when you
     decide to switch it off.

   * Auth_DBI_nopasswd  < on / off > (Authentication only)

     Default is 'off'. When set 'on' the password comparison is skipped if
     the password retrieved from the database is empty, i.e. allow any
     password. This is 'off' by default to ensure that an empty
     Auth_DBI_pwd_field does not allow people to log in with a random
     password. Be sure you know what you are doing when you decide to
     switch it on.

   * Auth_DBI_encrypted  < on / off > (Authentication only)

     Default is 'on'. When set to 'on', the password retrieved from the
     database is assumed to be crypted. Hence the incoming password will
     be crypted before comparison. When this directive is set to 'off',
     the comparison is done directly with the plain-text entered password.

   * Auth_DBI_encryption_salt < password / userid > (Authentication only)

     When crypting the given password AuthDBI uses per default the
     password selected from the database as salt. Setting this parameter
     to 'userid', the module uses the userid as salt.

   * Auth_DBI_uidcasesensitive  < on / off > (Authentication and
     Authorization)

     Default is 'on'. When set 'off', the entered userid is converted to
     lower case.  Also the userid in the password select-statement is
     converted to lower case.

   * Auth_DBI_pwdcasesensitive  < on / off > (Authentication only)

     Default is 'on'. When set 'off', the entered password is converted to
     lower case.

   * Auth_DBI_placeholder < on / off > (Authentication and Authorization)

     Default is 'off'.  When set 'on', the select statement is prepared
     using a placeholder for the username.  This may result in improved
     performance for databases supporting this method.

CONFIGURATION
=============

   The module should be loaded upon startup of the Apache daemon.  Add the
following line to your httpd.conf:

     PerlModule Apache::AuthDBI

   A common usage is to load the module in a startup file via the
PerlRequire directive. See eg/startup.pl for an example.

   There are three configurations which are server-specific and which can
be done in a startup file:

     Apache::AuthDBI->setCacheTime(0);

   This configures the lifetime in seconds for the entries in the cache.
Default is 0, which turns off the cache. When set to any value n > 0, the
passwords/groups of all users will be cached for at least n seconds. After
finishing the request, a special handler skips through the cache and
deletes all outdated entries (entries, which are older than the CacheTime).

     Apache::AuthDBI->setCleanupTime(-1);

   This configures the minimum time in seconds between two successive runs
of the CleanupHandler, which deletes all outdated entries from the cache.
The default is -1, which disables the CleanupHandler. Setting the interval
to 0 runs the CleanupHandler after every request. For a heavily loaded
server this should be set to a value, which reflects a compromise between
scanning a large cache possibly containing many outdated entries and
between running many times the CleanupHandler on a cache containing only
few entries.

     Apache::AuthDBI->initIPC(50000);

   This enables the usage of shared memory for the cache. Instead of every
server maintaining it's own cache, all servers have access to a common
cache. This should minimize the database load considerably for sites
running many servers.  The number indicates the size of the shared memory
segment in bytes. This size is fixed, there is no dynamic allocation of
more segments. As a rule of thumb multiply the estimated maximum number of
simultaneously cached users by 100 to get a rough estimate of the needed
size. Values below 500 will be overwritten with the default 50000.

   To enable debugging the variable $Apache::AuthDBI::DEBUG must be set.
This can either be done in startup.pl or in the user script. Setting the
variable to 1, just reports about a cache miss. Setting the variable to 2
enables full debug output.

PREREQUISITES
=============

   Note that this module needs mod_perl-1.08 or higher, apache_1.3.0 or
higher and that mod_perl needs to be configured with the appropriate
call-back hooks:

     PERL_AUTHEN=1 PERL_AUTHZ=1 PERL_CLEANUP=1 PERL_STACKED_HANDLERS=1

SECURITY
========

   In some cases it is more secure not to put the username and the
password in the .htaccess file. The following example shows a solution to
this problem:

   httpd.conf:

     <Perl>
     my($uid,$pwd) = My::dbi_pwd_fetch();
     $Location{'/foo/bar'}->{PerlSetVar} = [
         [ Auth_DBI_username  => $uid ],
         [ Auth_DBI_password  => $pwd ],
     ];
     </Perl>

SEE ALSO
========

   See Apache, `mod_perl' in this node, `DBI' in this node

AUTHORS
=======

   * mod_perl by Doug MacEachern <modperl@apache.org>

   * DBI by Tim Bunce <dbi-users@isc.org>

   * Apache::AuthDBI by Edmund Mergl <E.Mergl@bawue.de>

COPYRIGHT
=========

   The Apache::AuthDBI module is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

mod_perl LDAP Access Control and Authentication Module
******************************************************

NAME
====

   Apache::AuthLDAP - mod_perl LDAP Access Control and Authentication
Module

SYNOPSIS
========

     <Directory /foo/bar>
     # Authentication Realm and Type (only Basic supported)
     AuthName "Foo Bar Authentication"
     AuthType Basic

     # Any of the following variables can be set.  Defaults are listed
     # to the right.
     PerlSetVar BaseDN o=Foo,c=Bar        # Default:  Empty String ("")
     PerlSetVar LDAPServer ldap.foo.com   # Default: localhost
     PerlSetVar LDAPPort 389              # Default: 389 (standard LDAP port)
     PerlSetVar UIDAttr uid               # Default: uid

     PerlAuthenHandler Apache::AuthLDAP

     # Require lines can be any of the following:
     #
     require valid-user             # Any Valid LDAP User
     require user uid1 uid2 uid2    # Allow Any User in List
     require ldapattrib val1 val2   # Allow Any User w/ Entry Containing
                                    # Matching Attribute and Value
     </Directory>

     These directives can also be used in a .htaccess file.

DESCRIPTION
===========

   This perl module is designed to work with mod_perl and my Net::LDAPapi
module (http://www.wwa.com/~donley/).

   This version of the module does not support access control based on
LDAP groups, but the next release will.  It does support a handy access
control based on attribute and value pairs.  This can be used to restrict
access to people whose LDAP entries contain a given department number,
etc...

   I welcome feedback on this module and the Net::LDAPapi module.

AUTHOR
======

   Clayton Donley <donley@wwa.com>

COPYRIGHT
=========

   Copyright (c) 1998 Clayton Donley

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

mod_perl module that uses the Net::LDAP module for user authentication for Apache
*********************************************************************************

NAME
====

   Apache::AuthNetLDAP - mod_perl module that uses the Net::LDAP module
for user authentication for Apache

SYNOPSIS
========

     AuthName "LDAP Test Auth"
     AuthType Basic

     #only set the next two if you need to bind as a user for searching
     #PerlSetVar BindDN "uid=user1,ou=people,o=acme.com" #optional
     #PerlSetVar BindPWD "password" #optional
     PerlSetVar BaseDN "ou=people,o=acme.com"
     PerlSetVar LDAPServer ldap.acme.com
     PerlSetVar LDAPPort 389
     #PerlSetVar UIDAttr uid
     PerlSetVar UIDAttr mail

     require valid-user

     PerlAuthenHandler Apache::AuthNetLDAP

DESCRIPTION
===========

   This module authenticates users via LDAP using the Net::LDAP module.
This module is Graham Barr's "pure" Perl LDAP API.

   It also uses all of the same parameters as the Apache::AuthPerLDAP, but
I have added two extra parameters.

   The parameters are:

PerlSetVar BindDN
     Used to set initial LDAP user.

PerlSetVar BindPWD
     Used to set initial LDAP password.

PerlSetVar BaseDN
     This sets the search base used when looking up a user in an LDAP
     server.

PerlSetVar LDAPServer
     This is the hostname of the LDAP server you wish to use.

PerlSetVar LDAPPort
     This is the port the LDAP server is listening on.

PerlSetVar UIDAttr
     The attribute used to lookup the user.

Uses for UIDAttr
----------------

   For example if you set the UIDAttr to uid, then the LDAP search filter
will lookup a user using the search filter:

   Normally you will use the uid attribute, but you may want (need) to use
a different attribute depending on your LDAP server or to synchronize with
different applications. For example some versions of Novell's LDAP servers
that I've encountered stored the user's login name in the cn attribute (a
really bad idea). And the Netscape Address Book uses a user's email
address as the login id.

INSTALLATION
============

   It's a pretty straightforward install if you already have mod_perl and
Net::LDAP already installed.

   After you have unpacked the distribution type:

   perl Makefile.PL make make install

   Then in your httpd.conf file or .htaccess file, in either a <Directory>
or <Location> section put:

     AuthName "LDAP Test Auth"
     AuthType Basic

     #only set the next two if you need to bind as a user for searching
     #PerlSetVar BindDN "uid=user1,ou=people,o=acme.com" #optional
     #PerlSetVar BindPWD "password" #optional
     PerlSetVar BaseDN "ou=people,o=acme.com"
     PerlSetVar LDAPServer ldap.acme.com
     PerlSetVar LDAPPort 389
     PerlSetVar UIDAttr uid

     require valid-user

     PerlAuthenHandler Apache::AuthNetLDAP

HOMEPAGE
========

     Module Home:http://courses.unt.edu/mewilcox/

AUTHOR    	Mark Wilcox mewilcox@unt.edu
=======================================

SEE ALSO    Net/LDAP,
=====================================

ACKNOWLEDGMENTS
===============

     Graham Barr for writing Net::LDAP module.
     Henrik Strom for writing the Apache::AuthPerLDAP module which I derived this from.
     The O'Reilly "Programming Modules for Apache with Perl and C" (http://www.modperl.com).

WARRANTY AND LICENSE You can distribute and modify in accordance to the same license as Perl. Though I would like to know how you are using the module or if you are using the module at all.
=============================================================================================================================================================================================

   Like most of the stuff on the 'net, I got this copy to work for me
without destroying mankind, you're mileage may vary.

mod_perl PerLDAP Authentication Module
**************************************

NAME
====

   Apache::AuthPerLDAP - mod_perl PerLDAP Authentication Module

SYNOPSIS
========

     <Directory /foo/bar>
     # Authentication Realm and Type (only Basic supported)
     AuthName "Foo Bar Authentication"
     AuthType Basic

     # Any of the following variables can be set.
     # Defaults are listed to the right.
     PerlSetVar BaseDN o=Foo,c=Bar        # Default: ""  (empty String)
     PerlSetVar LDAPServer ldap.foo.com   # Default: localhost
     PerlSetVar LDAPPort 389              # Default: 389 (standard LDAP port)
     PerlSetVar UIDAttr uid               # Default: uid
     require valid-user

     PerlAuthenHandler Apache::AuthPerLDAP

     </Directory>

     These directives can also be used in a .htaccess file.

DESCRIPTION
===========

   AuthPerLDAP provides Basic Authentication, with username/password
lookups against an LDAP server, using Netscape's PerLDAP kit.

   It is heavily based on Clayton Donley's Apache::AuthLDAP module, but
uses the newer Netscape PerLDAP (Mozilla::LDAP), which in turn uses the
Netscape Directory SDK for C. Thus Donley's original Net::LDAPapi module
and library is no longer required.

   It requires mod_perl and PerLDAP (v1.2 or later).  Building mod_perl
with:

   perl Makefile.PL PERL_AUTHEN=1 PERL_STACKED_HANDLERS=1
PERL_GET_SET_HANDLERS

   works for me. If this module is the only Apache/Perl module you are
going to use, you probably don't need anything but the PERL_AUTHEN hook
enabled.

   Unlike Donley's Apache::AuthLDAP module, AuthPerLDAP is only used for
authentication, and thus only supports the require-user directive.  If a
user enters the correct username and password, the authentication is
considered to be OK.

TODO
====

   * Find out more about these messages in the error_log: "child pid 5244
     exit signal Segmentation Fault (11)"

   * Further testing.

   * More detailed documentation.

   * Some examples of how to setup and use this module.

CREDITS
=======

   Apache::AuthPerLDAP is greatly inspired by the original Apache::AuthLDAP
written by Clayton Donley.

   Adoption to PerLDAP was done by reading the PerLDAP source and
documentation provided by Netscape Corp. and Leif Hedstrom, found at
www.perldap.org.

   The new book published by O'Reilly & Associates, and authored by
Lincoln Stein and Doug MacEachern helped clarify many mod_perl issues I
previously had problems with: "Writing Apache Modules with Perl and C"
(www.modperl.com).

   Andreas K. Sorensen provided usefull Perl wisdom during debugging.

AUTHOR
======

   Henrik Strom <henrik@computer.org>

COPYRIGHT
=========

   Copyright (c) 1999 Henrik Strom

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   mod_perl(1), *Mozilla::LDAP::Conn*, *Apache::AuthenCache*.

Cookie based access module.
***************************

NAME
====

   Apache::AuthTicket - Cookie based access module.

SYNOPSIS
========

     # in httpd.conf
     PerlModule Apache::AuthTicket
     PerlSetVar FooTicketDB DBI:mysql:database=mschout;host=testbed
     PerlSetVar FooTicketDBUser test
     PerlSetVar FooTicketDBPassword secret
     PerlSetVar FooTicketTable tickets:ticket_hash:ts
     PerlSetVar FooTicketUserTable myusers:usename:passwd
     PerlSetVar FooTicketPasswordStyle cleartext
     PerlSetVar FooTicketSecretTable ticket_secrets:sec_data:sec_version
     PerlSetVar FooTicketExpires 15
     PerlSetVar FooTicketLogoutURI /foo/index.html
     PerlSetVar FooTicketLoginHandler /foologin
     PerlSetVar FooTicketIdleTimeout 1
     PerlSetVar FooPath /
     PerlSetVar FooDomain .foo.com
     PerlSetVar FooSecure 1
     PerlSetVar FooLoginScript /foologinform

     <Location /foo>
         AuthType Apache::AuthTicket
         AuthName Foo
         PerlAuthenHandler Apache::AuthTicket->authenticate
         PerlAuthzHandler Apache::AuthTicket->authorize
         require valid-user
     </Location>

     <Location /foologinform>
         AuthType Apache::AuthTicket
         AuthName Foo
         SetHandler perl-script
         Perlhandler Apache::AuthTicket->login_screen
     </Location>

     <Location /foologin>
         AuthType Apache::AuthTicket
         AuthName Foo
         SetHandler perl-script
         PerlHandler Apache::AuthTicket->login
     </Location>

     <Location /foo/logout>
         AuthType Apache::AuthTicket
         AuthName Foo
         SetHandler perl-script
         PerlHandler Apache::AuthTicket->logout
     </Location>

DESCRIPTION
===========

   This module provides ticket based access control.  The theory behind
this is similar to the system described in the eagle book.

   This module works using HTTP cookies to check if a user is authorized
to view a page.  *Apache::AuthCookie* is used as the underlying mechanism
for managing cookies.

   This module was designed to be as extensible as possible.  Its quite
likely that you will want to create your own subclass of
*Apache::AuthTicket* in order to customize various aspects of this module
(show your own versions of the forms, override database methods etc).

   This system uses cookies to authenticate users.  When a user is
authenticated through this system, they are issued a cookie consisting of
the time, the username of the user, the expriation time of the cookie, a
"secret" version (described later), and a cryptographic signature.  The
cryptographic signature is generated using the MD5 algorithm on the cookie
data and a "secret" key that is read from a database.  Each secret key
also has a version number associated with it.  This allows the site
administrator to issue a new secret periodically without invalidating the
current valid tickets.   For example, the site administrator might
periodically insert a new secret key into the databse periodically, and
flush secrets that are more than 2 days old.  Since the ticket issued to
the user contains the secret version, the authentication process will
still allow tickets to be authorized as long as the corresponding secrets
exist in the ticket secrets table.

   The actual contents and length of secret data is left to the site
administrator. A good choice might be to read data from /dev/random,
unpack it into a hex string and save that.

   This system should be reasonably secure becuase the IP address of the
end user is incorporated into the cryptographic signature. If the ticket
were intercepted, then an attacker would have to steal the user's IP
address in order to be able to use the ticket.  Plus, since the tickets
can expire automatically, we can be sure that the ticket is not valid for
a long period of time.  Finally, by using the *Secure* mode of
*Apache::AuthCookie*, the ticket is not passed over unencrypted
connections.  In order to attack this system, an attacker would have to
exploit both the MD5 algorightm as well as SSL. Chances are, by the time
the user could break both of these, the ticket would no longer be valid.

CONFIGURATION
=============

   There are two things you must do in order to configure this module:

     1) configure your mod_perl apache server
     2) create the necessary database tables.

Apache Configuration - httpd.conf
---------------------------------

   There are two ways that this module could be configured.  Either by
using a function call in startup.pl, or by configuring each handler
explicitly in httpd.conf.  If you decide to mix and match using calls to
Apache::AuthTicket->configure() with directives in httpd.conf, then
remember that the following precedence applies:

     o If a directive is specified in httpd.conf, it will be used.
     o else if a directive is specified by configure(), then the
       configure() value will be used.
     o else a default value will be used.

   Default values are subject to change in later versions, so you are
better of explicitly configuring all values and not relying on any
defaults.

   There are four blocks that need to be entered into httpd.conf.  The
first of these is the block specifying your access restrictions.  This
block should look somrthing like this:

     <Location /foo>
         AuthType Apache::AuthTicket
         AuthName Foo
         PerlAuthenHandler Apache::AuthTicket->authenticate
         PerlAuthzHandler Apache::AuthTicket->authorize
         require valid-user
     </Location>

   The remaining blocks control how to display the login form, and the
login and logout urls.  These blocks should look similar to this:

     <Location /foologinform>
         AuthType Apache::AuthTicket
         AuthName Foo
         SetHandler perl-script
         Perlhandler Apache::AuthTicket->login_screen
     </Location>

     <Location /foologin>
         AuthType    Apache::AuthTicket
         AuthName    Foo
         SetHandler  perl-script
         PerlHandler Apache::AuthTicket->login
     </Location>

     <Location /foo/logout>
         AuthType Apache::AuthTicket
         AuthName Foo
         SetHandler perl-script
         PerlHandler Apache::AuthTicket->logout
     </Location>

Apache Configuration - startup.pl
---------------------------------

   Any *Apache::AuthTicket* configuration items can be set in startup.pl.
You can configure an AuthName like this:

     Apache::AuthTicket->configure(String auth_name, *Hash config)

   Note that when configuring this way you dont prefix the configuration
items with the AuthName value like you do when using PerlSetVar directives.

   Note: You must still include *Apache::AuthCookie* configuration
directives in httpd.conf when configuring the server this way.  These
items include:

     PerlSetVar FooPath /
     PerlSetVar FooDomain .foo.com
     PerlSetVar FooSecure 1
     PerlSetVar FooLoginScript /foologinform

   example:  Apache::AuthTicket->configure('Foo', {      TicketDB
 => 'DBI:mysql:database=test;host=foo',      TicketDBUser        =>
'mschout',      TicketDBPassword    => 'secret',      TicketTable
=> 'tickets:ticket_hash:ts',      TicketUserTablei    =>
'myusers:usename:passwd',      TicketPasswordStyle => 'cleartext',
TicketSecretTable   => 'ticket_secrets:sec_data:sec_version',
TicketExpires       => '15',      TicketLogoutURI     => '/foo/index.html',
    TicketLoginHandler  => '/foologin',      TicketIdleTimeout   => 5  });

   Valid configuration items are:

TicketDB
     This directive specifys the DBI URL string to use when connecting to
     the database.  Also, you might consider overloading the *dbi_connect*
     method to handle setting up your db connection if you are creating a
     subclass of this module.

     example: dbi:Pg:dbname=test

TicketDBUser
     This directive specifys the username to use when connecting to the
     databse.

TicketDBPassword
     This directive specifys the password to use when connecting to the
     databse.

TicketTable
     This directive specifys the ticket hash table as well as the column
     name for the hash.

     Format: table_name:ticket_column_name:timestamp_column

     Example: tickets:ticket_hash:ts

TicketUserTable
     This directive specifys the users table and the username and password
     column names.

     Format: table_name:username_column:password_column

     Example: users:usrname:passwd

TicketPasswordStyle
     This directive specifys what type of passwords are stored in the
     database.  The default is to use cleartext passwords.  Currently
     supported password styles are:

    cleartext
          This password style is just plain text passwords.  When using
          this password style, the supplied user password is simply
          compared with the password stored in the database.

    md5
          This password style generates an MD5 hex hash of the supplied
          password before comparing it against the password stored in the
          database.  Passwords should be stored in the database by passing
          them through Digest::MD5->md5_hex().

    crypt
          This password style uses traditional crypt() to encrypt the
          supplied password before comparing it to the password saved in
          the database.

TicketSecretTable
     This directive specifys the server secret table as well as the names
     of the secret data column and the version column.

     Format: table_name:data_column:version_column

     Example: ticketsecrets:sec_data:sec_version

TicketExpires
     This directive specifys the number of minutes that tickets should
     remain valid for.  If a user exceeds this limit, they will be forced
     to log in again.

TicketIdleTimeout
     This directive specifys the number of minutes of inactivity before a
     ticket is considered invalid.  Setting this value to 5 for example
     would force a re-login if no requests are recieved from the user in a
     5 minute period.

     The default for this value is 0, which disables this feature.  If
     this number is larger than TicketExpires, then this setting will have
     no effect.

TicketLogoutURI
     This directive specifys the URL that the user should be sent to after
     they are successfully logged out (this is done via a redirect).

     Example: /logged_out_message.html

Database Configuration
----------------------

   Three database tables are needed for this module:

*users table*
     This table stores the actual usernames and passwords of the users.
     This table needs to contain at least a username and password column.
     This table is confgured by the TicketUserTable directive.

          example:

          CREATE TABLE users (
              usename VARCHAR(32) NOT NULL,
              passwd  VARCHAR(32) NOT NULL
          );

*tickets table*
     This table stores the ticket hash for each ticket.  This information
     must be stored locally so that users can be forcefully logged out
     without worrying if the HTTP cookie doesn't get deleted.

          example:

          CREATE TABLE tickets (
             ticket_hash CHAR(32) NOT NULL,
             ts          INT NOT NULL,
             PRIMARY KEY (ticket_hash)
          );

*secrets table*
     This table contains the server secret and a numeric version for the
     secret.  This table is configured by the TicketSecretTable directive.

          example:

          CREATE TABLE ticketsecrets (
              sec_version  SERIAL,
              sec_data     TEXT NOT NULL
          );

METHODS
=======

   This is not a complete listing of methods contained in
*Apache::AuthTicket*.  Rather, it is a listing of methods that you might
want to overload if you were subclassing this module.  Other methods that
exist in the module are probably not useful to you.

   Feel free to examine the source code for other methods that you might
choose to overload.

void make_login_screen($r, String action, String destination)
     This method creats the "login" screen that is shown to the user.  You
     can overload this method to create your own login screen.  The log in
     screen only needs to contain a hidden field called "destination" with
     the contents of *destination* in it, a text field named
     *credential_0* and a password field named *credential_1*.  You are
     responsible for sending the http header as well as the content.  See
     *Apache::AuthCookie* for the description of what each of these fields
     are for.

     action contains the action URL for the form.  You must set the action
     of your form to this value for it to function correctly.

     *Apache::AuthTicket* also provides a mechanism to determine why the
     login for is being displayed.  This can be used in conjunction with
     *Apache::AuthCookie*'s "AuthCookieReason" setting to determine why
     the user is being asked to log in.  *Apache::AuthCookie* sets
     $r->prev->subprocess_env("AuthCookieReason") to either "no_cookie" or
     "bad_cookie" when this page is loaded.  If the value is "no_cookie"
     then the user is being asked to log in for the first time, or they
     are logging in after they previously logged out.  If this value is
     "bad_cookie" then *Apache::AuthTicket* is asking them to re-login for
     some reason.  To determine what this reason is, you must examine
     $r->prev->subprocess_env("AuthTicketReason").  *AuthTicketReason* can
     take the following values:

    malformed_ticket
          This value means that the ticket is malformed.  In other words,
          the ticket does not contain all of the required information that
          should be present.

    invalid_hash
          This value means that the hash contained in the ticket does not
          match any values in the tickets database table.  This might
          happen if you are periodically clearing out old tickets from the
          database and the user presents a ticket that has been deleted.

    expired_ticket
          This value means that the ticket has expired and the user must
          re-login to be issued a new ticket.

    missing_secret
          This value means that the server secret could not be loaded.

    idle_timeout
          This value means that the user has exceeded the
          TicketIdleTimeout minutes of inactivity, and the user must
          re-login.

    tampered_hash
          This value indicates that the ticket data does not match its
          cryptographic signature, and the ticket has most likely been
          tampered with.  The user is forced to re-login at this point.

     You can use these values in your *make_login_screen()* method to
     display a message stating why the user must login (e.g.: "you have
     exceeded 5 minutes of inactivity and you must re-login").

DBI::db dbi_connect()
     This method connects to the TicketDB data source. You might overload
     this method if you have a common DBI connection function. For example:

          sub dbi_connect {
              my ($this) = @_;
              return Foo::dbi_connect();
          }

     Note that you can also adjust the DBI connection settings by setting
     TicketDB, TicketDBUser, and TicketDBPassword in httpd.conf.

BUGS
====

   None known, but that doesn't mean there aren't any.  If you find a bug
in this software, please let me know.

CREDITS
=======

   The idea for this module came from the Ticket Access system in the
eagle book, along with several ideas discussed on the mod_perl mailing
list.

   Thanks to Ken Williams for his wonderful *Apache::AuthCookie* module,
and for putting in the necessary changes to *Apache::AuthCookie* to make
this module work!

AUTHOR
======

   Michael Schout <mschout@gkg.net>

SEE ALSO
========

   See Perl (perl.info), `mod_perl' in this node, see Apache,
see Apache/AuthCookie,

Authentication caching used in conjuction with a primary authentication module (Apache::AuthenDBI, Apache::AuthenLDAP, etc.)
****************************************************************************************************************************

NAME
====

   Apache::AuthenCache - Authentication caching used in conjuction with a
primary authentication module (Apache::AuthenDBI, Apache::AuthenLDAP, etc.)

SYNOPSIS
========

     # In your httpd.conf
     PerlModule Apache::AuthenCache

     # In httpd.conf or .htaccess:
     AuthName Name
     AuthType Basic

     PerlAuthenHandler Apache::AuthenCache <Primary Authentication Module> Apache::AuthenCache::manage_cache

     require valid-user # Limited to valid-user

     # Optional parameters
     # Defaults are listed to the right.
     PerlSetVar AuthenCache_CacheTime     900 # Default: indefinite
     PerlSetVar AuthenCache_CaseSensitive Off # Default: On
     PerlSetVar AuthenCache_Encrypted     Off # Default: On
     PerlSetVar AuthenCache_NoPasswd      On  # Default: Off

DESCRIPTION
===========

   *Apache::AuthenCache* implements a caching mechanism in order to speed
up authentication and to reduce the usage of system resources. It must be
used in conjunction with a regular mod_perl authentication module (it was
designed with AuthenDBI and AuthenLDAP in mind).  For a list of mod_perl
authentication modules see:

   http://www.cpan.org/modules/by-module/Apache/apache-modlist.html

   When a request that requires authorization is received,
AuthenCache::handler looks up the REMOTE_USER in a shared-memory cache
(using IPC::Cache) and compares the cached password to the sent password.
A new cache is created for the first request or if the cache has expired.
If the passwords match, the handler returns OK and clears the downstream
Authen handlers from the stack. Otherwise, it returns DECLINED and allows
the next PerlAuthenHandler in the chain to be called.

   After the primary authentication handler completes with an OK,
AuthenCache::manage_cache adds the new user to the cache.

CONFIGURATION OPTIONS
=====================

   The following variables can be defined within the configuration of
Directory, Location, or Files blocks or within .htaccess files.

   This directive contains the number of seconds before the cache is
expired. Default is an indefinite time limit.

PREREQUISITES
=============

   mod_perl 1.11_01 is required. IPC::Cache is also required.

SEE ALSO
========

   crypt(3c), httpd(8), mod_perl(1)

AUTHORS
=======

   Jason Bodnar <jason@shakabuku.org> Christian Gilmore
<cgilmore@tivoli.com>

COPYRIGHT
=========

   Copyright (C) 1998-2001, Jason Bodnar

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Authentication via Perl's DBI
*****************************

NAME
====

   Apache::AuthenDBI - Authentication via Perl's DBI

SYNOPSIS
========

     # Configuration in httpd.conf or srm.conf:

     PerlModule Apache::AuthenDBI

     # Authentication in .htaccess:

     AuthName DBI
     AuthType Basic

     #authenticate via DBI
     PerlAuthenHandler Apache::AuthenDBI

     PerlSetVar Auth_DBI_data_source   dbi:driver:dsn
     PerlSetVar Auth_DBI_username      db_username
     PerlSetVar Auth_DBI_password      db_password
     #DBI->connect($data_source, $username, $password)

     PerlSetVar Auth_DBI_pwd_table     users
     PerlSetVar Auth_DBI_uid_field     username
     PerlSetVar Auth_DBI_pwd_field     password
     #SELECT pwd_field FROM pwd_table WHERE uid_field=$user

     require valid-user

   The AuthType is limited to Basic. The require directive is limited to
'valid-user' and 'user user_1 user_2 ...'. For group support see
AuthzDBI.pm.

DESCRIPTION
===========

   This module allows authentication against a database using Perl's DBI.
For supported DBI drivers see:

     http://www.symbolstone.org/technology/perl/DBI/

   For the given username the password is looked up in the cache. If it is
not found in the cache, it is requested from the database.

   If the username does not exist and the authoritative directive is set
to 'on', the request is rejected. If the authoritative directive is set to
'off', the control is passed on to next module in line.

   If the password for the given username is empty and the nopasswd
directive is set to 'off', the request is rejected. If the nopasswd
directive is set to 'on', any password is accepted.

   Finally the passwords (multiple passwords per userid are allowed)
retrieved from the database are compared to the password given. If the
encrypted directive is set to 'on', the given password is encrypted using
perl's crypt() function before comparison. If the encrypted directive is
set to 'off' the plain-text passwords are compared.

   If this comparison fails the request is rejected, otherwise the request
is accepted.

   The SQL-select used for retrieving the passwords is as follows:

     SELECT pwd_field FROM pwd_table WHERE uid_field = user

   If a pwd_whereclause exists, it is appended to the SQL-select.

   At the end a CleanupHandler is initialized, which skips through the
password cache and deletes all outdated entries. This is done after
sending the response, hence without slowing down response time to the
client. The default cache_time is set to 0, which disables the cache,
because any user would be deleted immediately from the cache.

   This module supports in addition a simple kind of logging mechanism.
Whenever the handler is called and a log_string is configured, the
log_field will be updated with the log_string. As log_string - depending
upon the database - macros like TODAY can be used.

   The SQL-select used for the logging mechanism is as follows:

     UPDATE pwd_table SET log_field = log_string WHERE uid_field = user

     =head1 LIST OF TOKENS

   * Auth_DBI_data_source

     The data_source value should begin with 'dbi:driver_name:'. This value
     (with the 'dbi:...:' prefix removed) is passed to the database driver
     for processing during connect.

   * Auth_DBI_username

     The username argument is passed to the database driver for processing
     during connect.

   * Auth_DBI_password

     The password argument is passed to the database driver for processing
     during connect.

   * Auth_DBI_pwd_table

     Contains at least the fields with the username and the (encrypted)
     password.  The username should be unique.

   * Auth_DBI_uid_field

     Field name containing the username in the Auth_DBI_pwd_table.

   * Auth_DBI_pwd_field

     Field name containing the password in the Auth_DBI_pwd_table.

   * Auth_DBI_pwd_whereclause

     Use this option for specifying more constraints to the SQL-select.

   * Auth_DBI_log_field

     Field name containing the log string in the Auth_DBI_pwd_table.

   * Auth_DBI_log_string

     String to update the Auth_DBI_log_field in the Auth_DBI_pwd_table.
     Depending upon the database this can be a macro like 'TODAY'.

   * Auth_DBI_authoritative  < on / off>

     Default is 'on'. When set 'on', there is no fall-through to other
     authentication methods if the authentication check fails. When this
     directive is set to 'off', control is passed on to any other
     authentication modules. Be sure you know what you are doing when you
     decide to switch it off.

   * Auth_DBI_nopasswd  < on / off >

     Default is 'off'. When set 'on' the password comparison is skipped if
     the Auth_DBI_pwd_field is empty, i.e. allow any password. This is
     'off' by default to ensure that an empty Auth_DBI_pwd_field does not
     allow people to log in with a random password. Be sure you know what
     you are doing when you decide to switch it on.

   * Auth_DBI_encrypted  < on / off >

     Default is 'on'. When set 'on', the value in the Auth_DBI_pwd_field
     is assumed to be crypted using perl's crypt() function and the
     incoming password is crypted before comparison. When this directive
     is set to 'off', the comparison is done directly with the plain-text
     entered password.

   * Auth_DBI_uidcasesensitive  < on / off >

     Default is 'on'. When set 'off', the entered userid is converted to
     lower case.  Also the userid in the password select-statement is
     converted to lower case.

   * Auth_DBI_pwdcasesensitive  < on / off >

     Default is 'on'. When set 'off', the entered password is converted to
     lower case.

   * Auth_DBI_cache_time

     Default is 0 = off. When set to any value n > 0, the passwords of all
     users will be cached for n seconds. After finishing the request, a
     special handler skips through the cache and deletes all outdated
     entries (entries, which are older than the cache_time).

   * Auth_DBI_placeholder < on / off > Default is 'off'.  When set 'on',
     the select statement is prepared using a placeholder for the
     username.  This may result in improved performance for databases
     supporting this method.

CONFIGURATION
=============

   The module should be loaded upon startup of the Apache daemon.  Note
that this needs mod_perl-1.08 or higher, apache_1.3.0 or higher and that
mod_perl needs to be configured with

     PERL_AUTHEN=1 PERL_CLEANUP=1 PERL_STACKED_HANDLERS=1.

   Add the following line to your httpd.conf or srm.conf:

     PerlModule Apache::AuthenDBI

PREREQUISITES
=============

   For Apache::AuthenDBI you need to enable the appropriate call-back
hooks when making mod_perl:

     perl Makefile.PL PERL_AUTHEN=1 PERL_CLEANUP=1 PERL_STACKED_HANDLERS=1.

SECURITY
========

   In some cases it is more secure not to put the username and the
password in the .htaccess file. The following example shows a solution to
this problem:

   httpd.conf:

     <Perl>
     my($uid,$pwd) = My::dbi_pwd_fetch();
     $Location{'/foo/bar'}->{PerlSetVar} = [
         [ Auth_DBI_username  => $uid ],
         [ Auth_DBI_password  => $pwd ],
     ];
     </Perl>

SEE ALSO
========

   See Apache, `mod_perl' in this node, `DBI' in this node

AUTHORS
=======

   * mod_perl by Doug MacEachern <modperl@apache.org>

   * DBI by Tim Bunce <dbi-users@isc.org>

   * Apache::AuthenDBI by Edmund Mergl <E.Mergl@bawue.de>

COPYRIGHT
=========

   The Apache::AuthenDBI module is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

mod_perl LDAP Authentication Module
***********************************

NAME
====

   Apache::AuthenLDAP - mod_perl LDAP Authentication Module

SYNOPSIS
========

     <Directory /foo/bar>
     # Authentication Realm and Type (only Basic supported)
     AuthName "Foo Bar Authentication"
     AuthType Basic

     # Any of the following variables can be set.
     # Defaults are listed to the right.
     PerlSetVar AuthenBaseDN o=Foo,c=Bar  # Default: Empty String ("")
     PerlSetVar LDAPServer   ldap.foo.com # Default: localhost
     PerlSetVar LDAPPort     389          # Default: 389 (standard LDAP port)
     PerlSetVar UidattrType  userid       # Default: uid

     PerlAuthenHandler Apache::AuthenLDAP

     require valid-user                   # Any Valid LDAP User
                                          # Matching Attribute and Value
     </Directory>

DESCRIPTION
===========

   *Apache::AuthenLDAP* is designed to work with mod_perl and Net::LDAP.
This module authenticates a user against an LDAP backend. It can be
combined with Apache::AuthzLDAP to provide LDAP authorization as well.

CONFIGURATION OPTIONS
=====================

   The following variables can be defined within the configuration of
Directory, Location, or Files blocks or within .htaccess files.

AuthenBaseDN
     The base distinguished name with which to query LDAP. By default, the
     AuthenBaseDN is empty.

LDAPServer
     The hostname for the LDAP server to query. By default, LDAPServer is
     set to localhost.

LDAPPort
     The port on which the LDAP server is listening. By default, LDAPPort
     is set to 389.

UidAttrType
     The attribute type name that contains the user's identification. By
     default, UidAttrType is set to uid.

NOTES
=====

   This module has hooks built into it to handle Apache::AuthenCache
version 0.04 and higher passing notes to avoid bugs in the set_handlers()
method in mod_perl versions prior to 1.26.

AUTHORS
=======

   Jason Bodnar, Christian Gilmore <cgilmore@tivoli.com>

See ALSO
========

   httpd(8), ldap(3), mod_perl(1), slapd(8C)

COPYRIGHT   Copyright (C) 2001, International Business Machines Corporation and others. All Rights Reserved.   This module is free software; you can redistribute it and/or modify it under the terms of the IBM Public License.
================================================================================================================================================================================================================================

mod_perl NIS Authentication module
**********************************

NAME
====

   Apache::AuthenNIS - mod_perl NIS Authentication module

SYNOPSIS
========

     <Directory /foo/bar>
     # This is the standard authentication stuff
     AuthName "Foo Bar Authentication"
     AuthType Basic

     PerlAuthenHandler Apache::AuthenNIS

     # Standard require stuff, NIS users or groups, and
     # "valid-user" all work OK
     require user username1 username2 ...
     require group groupname1 groupname2 ... # [Need Apache::AuthzNIS]
     require valid-user

     # The following is actually only needed when authorizing
     # against NIS groups. This is a separate module.
     PerlAuthzHandler Apache::AuthzNIS

     </Directory>

     These directives can also be used in the <Location> directive or in
     an .htaccess file.

DESCRIPTION
===========

   This perl module is designed to work with mod_perl and the Net::NIS
module by Rik Haris (*rik.harris@fulcrum.com.au*).  It is a direct
adaptation (i.e. I modified the code) of Michael Parker's
(*parker@austx.tandem.com*) Apache::AuthenSmb module.

   The module uses Net::NIS::yp_match to retrieve the "passwd" entry from
the passwd.byname map, using the supplied username as the search key.  It
then uses crypt() to verify that the supplied password matches the
retrieved hashed password.

Apache::AuthenNIS vs. Apache::AuthzNIS
--------------------------------------

   I've taken "authentication" to be meaningful only in terms of a user and
password combination, not group membership.  This means that you can use
Apache::AuthenNIS with the *require user* and *require valid-user*
directives.  In the NIS context I consider *require group* to be an
"authorization" concern.  I.e., Group authorization consists of
establishing whether the already authenticated user is a member of one of
the indicated groups in the *require group* directive.  This process may
be handled by *Apache::AuthzNIS*.

   I welcome any feedback on this module, esp. code improvements, given
that it was written hastily, to say the least.

AUTHOR
======

   Demetrios E. Paneras <dep@media.mit.edu>

COPYRIGHT
=========

   Copyright (c) 1998 Demetrios E. Paneras, MIT Media Laboratory.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

mod_perl passwd Authentication module
*************************************

NAME
====

   Apache::AuthenPasswd - mod_perl passwd Authentication module

SYNOPSIS
========

     <Directory /foo/bar>
     # This is the standard authentication stuff
     AuthName "Foo Bar Authentication"
     AuthType Basic

     PerlAuthenHandler Apache::AuthenPasswd

     # Standard require stuff, /etc/passwd users or /etc/group groups, and
     # "valid-user" all work OK
     require user username1 username2 ...
     require group groupname1 groupname2 ... # [Need Apache::AuthzPasswd]
     require valid-user

     # The following is actually only needed when authorizing
     # against /etc/group. This is a separate module.
     PerlAuthzHandler Apache::AuthzPasswd

     </Directory>

     These directives can also be used in the <Location> directive or in
     an .htaccess file.

DESCRIPTION
===========

   This perl module is designed to work with mod_perl. It is a direct
adaptation (i.e. I modified the code) of Michael Parker's
(*parker@austx.tandem.com*) Apache::AuthenSmb module.

   The module uses getpwnam to retrieve the *passwd* entry from the
*/etc/passwd* file, using the supplied username as the search key.  It
then uses crypt() to verify that the supplied password matches the
retrieved hashed password.

Apache::AuthenPasswd vs. Apache::AuthzPasswd
--------------------------------------------

   I've taken "authentication" to be meaningful only in terms of a user and
password combination, not group membership.  This means that you can use
Apache::AuthenPasswd with the *require user* and *require valid-user*
directives.  In the /etc/passwd and /etc/group context I consider *require
group* to be an "authorization" concern.  I.e., group authorization
consists of establishing whether the already authenticated user is a member
of one of the indicated groups in the *require group* directive.  This
process may be handled by *Apache::AuthzPasswd*.  Admittedly, AuthzPasswd
is a misnomer, but I wanted to keep AuthenPasswd and AuthzPasswd related,
if only by name.

   I welcome any feedback on this module, esp. code improvements, given
that it was written hastily, to say the least.

AUTHOR
======

   Demetrios E. Paneras <dep@media.mit.edu>

COPYRIGHT
=========

   Copyright (c) 1998 Demetrios E. Paneras, MIT Media Laboratory.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

mod_perl Authen Handler
***********************

NAME
====

   *Apache::AuthenPasswdSrv* - mod_perl Authen Handler

SYNOPSIS
========

     PerlAuthenHandler Apache::AuthenPasswdSrv->handler()

REQUIRES
========

   Perl5.004_04, mod_perl 1.15

DESCRIPTION
===========

   *Apache::AuthenPasswdSrv* is a mod_perl Authentication handler that
checks a users credentials against a domain socket server.  The included
server, *passwd_srv.pl*, checks a username and password against an NIS
database using Net::NIS and ypmatch.  This release is very alpha.  The
server protocol is not documented and transaction format will change.  The
system has been running under light load at my office for about a month
now, and no problems are know with the current release.

TODO
====

*Module Configuration*
     Break out module configuration into PerlSetVar statements.

*NIS Server Configuration*
     Figure out MakeMaker enough to auto-configure paths in password
     server.

Documentation
     Write up Server Protocol documentation.  Write a better POD file for
     the module.

*Module/Server Structure*
     Build class structure for password service client.  Add security so
     client/server can be used with standard IP sockets.  Build class
     structure for server.  Build other example servers.

ACKNOWLEDGEMENTS
================

   Thanks to Premier1 Internet Service, Inc. for allowing me to work on
this module during work hours and paying me to muck with Perl.

AUTHOR
======

   Jeffrey Hulten, jeffh@premier1.net

SEE ALSO
========

   mod_perl(1).

Authentication via a Radius server
**********************************

NAME
====

   Apache::AuthenRadius - Authentication via a Radius server

SYNOPSIS
========

     # Configuration in httpd.conf

     PerlModule Apache::AuthenRadius

     # Authentication in .htaccess

     AuthName Radius
     AuthType Basic

     # authenticate via Radius
     PerlAuthenHandler Apache::AuthenRadius

     PerlSetVar Auth_Radius_host radius.foo.com
     PerlSetVar Auth_Radius_port 1647
     PerlSetVar Auth_Radius_secret MySharedSecret
     PerlSetVar Auth_Radius_timeout 5

     require valid-user

DESCRIPTION
===========

   This module allows authentication against a Radius server.

LIST OF TOKENS
==============

   * Auth_Radius_host

     The Radius server host: either its name or its dotted quad IP number.
     The parameter is passed as the PeerHost option to
     IO::Socket::INET->new.

   * Auth_Radius_port

     The port on which the Radius server is listening: either its service
     name or its actual port number. This parameter defaults to "1647"
     which is the official service name for Radius servers. The parameter
     is passed as the PeerPort option to IO::Socket::INET->new.

   * Auth_Radius_secret

     The shared secret for connection to the Radius server.

   * Auth_Radius_timeout

     The timeout in seconds to wait for a response from the Radius server.

CONFIGURATION
=============

   The module should be loaded upon startup of the Apache daemon.  Add the
following line to your httpd.conf:

     PerlModule Apache::AuthenRadius

PREREQUISITES
=============

   For AuthenRadius you need to enable the appropriate call-back hook when
making mod_perl:

     perl Makefile.PL PERL_AUTHEN=1

SEE ALSO
========

   See Apache, `mod_perl' in this node, `Authen::Radius' in
this node

AUTHORS
=======

   * mod_perl by Doug MacEachern <dougm@osf.org>

   * Authen::Radius by Carl Declerck <carl@miskatonic.inbe.net>

   * Apache::AuthenRadius by Daniel Sully
     <daniel-cpan-authenradius@electricrain.com>

COPYRIGHT
=========

   The Apache::AuthenRadius module is free software; you can redistribute
it and/or modify it under the same terms as Perl itself.

Authentication via a SecurID server
***********************************

NAME
====

   Apache::AuthenSecurID - Authentication via a SecurID server

SYNOPSIS
========

     # Configuration in httpd.conf

     PerlModule Apache::AuthenSecurID

     # Authentication in .htaccess

     AuthName SecurID
     AuthType Basic

     # authenticate via SecurID
     PerlAuthenHandler Apache::AuthenSecurID

     PerlSetVar Auth_SecurID_VAR_ACE /ace/config/directory
     PerlSetVar AuthCookie Name_of_Authentication_Cookie
     PerlSetVar AuthCookiePath /path/of/authentication/cookie

     require valid-user

DESCRIPTION
===========

   This module allows authentication against a SecurID server.  If
authentication is successful it sets a cookie with a MD5 hash token.  The
token expires at midnight local time.

LIST OF TOKENS
==============

   * Auth_SecurID_VAR_ACE

     The location of the `sdconf.rec' file.  It defaults to the directory
     `/var/ace' if this variable is not set.

   * AuthCookie

     The name of the of cookie to be set for the authenticaion token.  It
     defaults to the `SecurID' if this variable is not set.

   * AuthCookiePath

     The path of the of cookie to be set for the authenticaion token.  It
     defaults to / if this variable is not set.

CONFIGURATION
=============

   The module should be loaded upon startup of the Apache daemon.  Add the
following line to your httpd.conf:

     PerlModule Apache::AuthenSecurID

PREREQUISITES
=============

   For AuthenSecurID you need to enable the appropriate call-back hook
when making mod_perl:

     perl Makefile.PL PERL_AUTHEN=1

SEE ALSO
========

   See Apache, `mod_perl' in this node, `Authen::SecurID' in
this node

AUTHORS
=======

   * mod_perl by Doug MacEachern <dougm@osf.org>

   * Authen::ACE by Dave Carrigan <Dave.Carrigan@iplenergy.com>

   * Apache::AuthenSecurID by David Berk <dberk@lump.org>

COPYRIGHT
=========

   The Apache::AuthenSecurID module is free software; you can redistribute
it and/or modify it under the same terms as Perl itself.

mod_perl NT Authentication module
*********************************

NAME
====

   Apache::AuthenSMB - mod_perl NT Authentication module

SYNOPSIS
========

     <Directory /foo/bar>
     # This is the standard authentication stuff
     AuthName "Foo Bar Authentication"
     AuthType Basic

     # Variables you need to set, you must set at least
     # the myPDC variable, the DOMAIN defaults to WORKGROUP
     PerlSetVar myPDC workgroup-pdc
     PerlSetVar myBDC workgroup-bdc
     PerlSetVar myDOMAIN WORKGROUP

     PerlAuthenHandler Apache::AuthenSmb

     # Standard require stuff, only user and
     # valid-user work currently
     require valid-user
     </Directory>

     These directives can be used in a .htaccess file as well.

     If you wish to use your own PerlAuthzHandler then the require
     directive should follow whatever handler you use.

DESCRIPTION
===========

   This perl module is designed to work with mod_perl and the Authen::Smb
module by Patrick Michael Kane (See CPAN).  You need to set your PDC, BDC,
and NT domain name for the script to function properly.  You MUST set a
PDC, if no BDC is set it defaults to the PDC, if no DOMAIN is set it
defaults to WORKGROUP.

   If you are using this module please let me know, I'm curious how many
people there are that need this type of functionality.

AUTHOR
======

   Michael Parker <parkerm@null.net>

COPYRIGHT
=========

   Copyright (c) 1998 Michael Parker, Tandem Computers.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

authenticates via another URL
*****************************

NAME
====

   Apache::AuthenURL - authenticates via another URL

SYNOPSIS
========

     #in .htaccess
     AuthName MyHTTPAuth
     AuthType Basic
     PerlAuthenHandler Apache::AuthenCache Apache::AuthenURL::handler Apache::AuthenCache::manage_cache

     PerlSetVar AuthenURL_method HEAD		# a valid LWP method
     PerlSetVar AuthenURL_url https://somehost
     PerlSetVar AuthenCache_cache_time

     Options Indexes FollowSymLinks ExecCGI

     require valid-user

DESCRIPTION
===========

   I wrote this module to work around the lack of DCE support for Solaris
x86.  DCE authentication in my application is handled using Gradient's DCE
plug-in for Netscape Enterprise Server. The request is encrypted using SSL.

ACKNOWLEDGEMENTS
================

   The cache code was heavily borrowed from Apache::AuthenDBI by Edmund
Mergl <E.Mergl@bawue.de>, but now has been stripped out in favor of the
more general solution in Apache::AuthenCache by Jason Bodnar
<jason@shakabuku.org>.

SEE ALSO
========

   mod_perl(1), Apache::AuthenCache(3), LWP(3)

AUTHOR
======

   John Groenveld <groenveld@acm.org>

COPYRIGHT
=========

   This package is Copyright (C) 1998 by John Groenveld. It may be copied,
used and redistributed under the same terms as perl itself.

mod_perl Cache Authorization Module
***********************************

NAME
====

   Apache::AuthzCache - mod_perl Cache Authorization Module

SYNOPSIS
========

     <Directory /foo/bar>
     # Authorization Realm and Type (only Basic supported)
     AuthName "Foo Bar Authentication"
     AuthType Basic

     # Any of the following variables can be set.
     # Defaults are listed to the right.
     PerlSetVar AuthzCache_CaseSensitive Off       # Default: On
     PerlSetVar AuthzCache_Timeout       60        # Default: Empty String ("")

     PerlAuthzHandler Apache::AuthzCache <Primary Authorization Module> Apache::AuthzCache::manage_cache

     require group "My Group" GroupA "Group B"     # Authorize user against
                                                   # multiple groups
     </Directory>

DESCRIPTION
===========

   *Apache::AuthzCache* is designed to work with a mod_perl authorization
module to provide caching of group membership for site users. For a list
of mod_perl authorization modules see:

   http://www.cpan.org/modules/by-module/Apache/apache-modlist.html

   When a request that requires authorization is received,
Apache::AuthzCache looks up the REMOTE_USER in a shared-memory cache
(using IPC::Cache) and compares the list of groups in the cache against
the groups enumerated within the "require" configuration directive. If a
match is found, the handler returns OK and clears the downstream Authz
handlers from the stack. Otherwise, it returns DECLINED and allows the next
PerlAuthzHandler in the chain to be called.

   After the primary authorization handler completes with an OK,
Apache::AuthzCache::manage_cache adds the new group (listed in
REMOTE_GROUP) to the cache.

CONFIGURATION OPTIONS
=====================

   The following variables can be defined within the configuration of
Directory, Location, or Files blocks or within .htaccess files.

AuthzCache_CaseSensitive
     If this directive is set to 'Off', group matches will be case
     insensitive.

AuthzCache_Timeout
     The time with which a user's entry within the cache will remain,
     measured in minutes.

NOTES
=====

   This module requires that the primary authorization handler set the
REMOTE_GROUP environment variable with the group to which the user
successfully was authorized.

   This module also has a workaround to the bugs in the set_handlers()
method of mod_perl versions prior to 1.26. If mod_perl-1.26 or higher is
detected, AuthzCache will use set_handlers to clear the downstream Authz
handlers from the stack. Otherwise, it will write notes to downstream
handlers.

   At the time of publication, the only primary authorization handler
established to both set the REMOTE_GROUP and read the notes left by
AuthzCache is Apache::AuthzLDAP.

AUTHORS
=======

   Christian Gilmore <cgilmore@tivoli.com>

See ALSO
========

   httpd(8)

COPYRIGHT
=========

   Copyright (C) 2001, International Business Machines Corporation and
others. All Rights Reserved.

   This module is free software; you can redistribute it and/or modify it
under the terms of the IBM Public License.

Authorization via Perl's DBI
****************************

NAME
====

   Apache::AuthzDBI - Authorization via Perl's DBI

SYNOPSIS
========

     # Configuration in httpd.conf or srm.conf:

     PerlModule Apache::AuthzDBI

     # Authorization in .htaccess:

     AuthName DBI
     AuthType Basic

     #authorize via DBI
     PerlAuthzHandler Apache::AuthzDBI

     PerlSetVar Auth_DBI_data_source   dbi:driver:dsn
     PerlSetVar Auth_DBI_username      db_username
     PerlSetVar Auth_DBI_password      db_password
     #DBI->connect($data_source, $username, $password)

     PerlSetVar Auth_DBI_pwd_table     users
     PerlSetVar Auth_DBI_uid_field     username
     PerlSetVar Auth_DBI_grp_field     groupname
     #SELECT grp_field FROM pwd_table WHERE uid_field=$user

     require user   user_1  user_2 ...
     require group group_1 group_2 ...

   The AuthType is limited to Basic. You may use one or more valid require
lines. For a single require line with the tokens valid-user or with
distinct user names it is sufficient to use only the AuthenDBI module.
This module needs Apache::AuthenDBI, it can not be used stand-alone !

DESCRIPTION
===========

   This module allows authorization against a database using Perl's DBI.
For supported DBI drivers see:

     http://www.symbolstone.org/technology/perl/DBI/

   When the authorization handler is called, the authentication has
already been done. This means, that the given username/password has been
validated.

   The handler analyzes and processes the requirements line by line. The
request is accepted if the first requirement is fulfilled.

   In case of 'valid-user' the request is accepted.

   In case of one or more user-names, they are compared with the given
user-name until the first match.

   In case of one or more group-names, all groups of the given user-name
are looked up in the cache. If the user is not found in the cache, the
groups are requested from the database. A $; separated list of all these
groups is put into the environment variable REMOTE_GROUPS. Then these
groups are compared with the required groups until the first match.

   If there is no match and the authoritative directive is set to 'on' the
request is rejected.

   In case the authorization succeeds, the environment variable
REMOTE_GROUP is set to the group name, so scripts that are protected by
AuthzDBI don't need to bang on the database server again to get the group
name.

   The SQL-select used for retrieving the groups is as follows (depending
upon the existence of a grp_table):

     SELECT grp_field FROM pwd_table WHERE uid_field = user
     SELECT grp_field FROM grp_table WHERE uid_field = user

   This way you can have the group-information either in the main users
table, or you can use an extra table, if you have an m:n relationship
between users and groups. From all selected groups a comma-separated list
is build, which is compared with the required groups. If you don't like
normalized group records you can put such a comma-separated list of groups
(no spaces) into the grp_field instead of single groups.

   If a grp_whereclause exists, it is appended to the SQL-select.

   At the end a CleanupHandler is initialized, which skips through the
groups cache and deletes all outdated entries. This is done after sending
the response, hence without slowing down response time to the client. The
default cache_time is set to 0, which disables the cache, because any user
will be deleted immediately from the cache.

LIST OF TOKENS
==============

   * Auth_DBI_data_source

     The data_source value should begin with 'dbi:driver_name:'. This
     value (with the 'dbi:...:' prefix removed) is passed to the database
     driver for processing during connect.

   * Auth_DBI_username

     The username argument is passed to the database driver for processing
     during connect.

   * Auth_DBI_password

     The password argument is passed to the database driver for processing
     during connect.

   * Auth_DBI_grp_table

     Contains at least the fields with the username and the groupname.

   * Auth_DBI_uid_field

     Field-name containing the username in the Auth_DBI_grp_table.

   * Auth_DBI_grp_field

     Field-name containing the groupname in the Auth_DBI_grp_table.

   * Auth_DBI_grp_whereclause

     Use this option for specifying more constraints to the SQL-select.

   * Auth_DBI_authoritative  < on / off>

     Default is 'on'. When set 'on', there is no fall-through to other
     authorization methods if the authorization check fails. When this
     directive is set to 'off', control is passed on to any other
     authorization modules. Be sure you know what you are doing when you
     decide to switch it off.

   * Auth_DBI_uidcasesensitive  < on / off >

     Default is 'on'. When set 'off', the entered userid is converted to
     lower case.  Also the userid in the password select-statement is
     converted to lower case.

   * Auth_DBI_cache_time

     Default is 0 = off. When set to any value n > 0, the groups of all
     users will be cached for n seconds. After finishing the request, a
     special handler skips through the cache and deletes all outdated
     entries (entries, which are older than the cache_time).

   * Auth_DBI_expeditive

     Default is 'off'. When set to 'on', the result of an authorization
     failure is an 'Access Forbidden' code instead of 'Authentication
     Required'. This is less convenient in a few cases because it doesn't
     allow users to 'switch identities' w/o closing the browser, but is
     formally more correct and allows support persons to easily diagnose
     whether the problem is in authentication (wrong password) or in
     authorization (wrong permissions).

   * Auth_DBI_placeholder < on / off > Default is 'off'.  When set 'on',
     the select statement is prepared using a placeholder for the
     username.  This may result in improved performance for databases
     supporting this method.

CONFIGURATION
=============

   The module should be loaded upon startup of the Apache daemon.  It
needs the AuthenDBI module for the authentication part.  Note that this
needs mod_perl-1.08 or higher, apache_1.3.0 or higher and that mod_perl
needs to be configured with

     PERL_AUTHEN=1 PERL_AUTHZ=1 PERL_CLEANUP=1 PERL_STACKED_HANDLERS=1.

   Add the following lines to your httpd.conf or srm.conf:

     PerlModule Apache::AuthenDBI
     PerlModule Apache::AuthzDBI

PREREQUISITES
=============

   For Apache::AuthzDBI you need to enable the appropriate call-back hooks
when making mod_perl:

     perl Makefile.PL PERL_AUTHEN=1 PERL_AUTHZ=1 PERL_CLEANUP=1 PERL_STACKED_HANDLERS=1.

SEE ALSO
========

   See Apache, `mod_perl' in this node, `DBI' in this node

AUTHORS
=======

   * mod_perl by Doug MacEachern <modperl@apache.org>

   * <dbiDBI by Tim Bunce <dbi-users@isc.org>

   * Apache::AuthzDBI by Edmund Mergl <E.Mergl@bawue.de>

COPYRIGHT
=========

   The Apache::AuthzDBI module is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

mod_perl LDAP Authorization Module
**********************************

NAME
====

   Apache::AuthzLDAP - mod_perl LDAP Authorization Module

SYNOPSIS
========

     <Directory /foo/bar>
     # Authorization Realm and Type (only Basic supported)
     AuthName "Foo Bar Authentication"
     AuthType Basic

     # Any of the following variables can be set.
     # Defaults are listed to the right.
     PerlSetVar AuthenBaseDN    o=Foo,c=Bar        # Default: Empty String ("")
     PerlSetVar AuthzBaseDN     o=Tivoli Systems   # Default: none
     PerlSetVar GroupAttrType   gid                # Default: cn
     PerlSetVar LDAPServer      ldap.foo.com       # Default: localhost
     PerlSetVar LDAPPort        389                # Default: 389
     PerlSetVar MemberAttrType  uid                # Default: member
     PerlSetVar MemberAttrValue dn                 # Default: cn
     PerlSetVar NestedGroups    On                 # Default: off
     PerlSetVar UidattrType     userid             # Default: uid

     PerlAuthzHandler Apache::AuthzLDAP

     require group "My Group" GroupA "Group B"     # Authorize user against
                                                   # multiple groups
     </Directory>

DESCRIPTION
===========

   *Apache::AuthzLDAP* is designed to work with mod_perl and Net::LDAP.
This module authorizes a user against an LDAP backend. It can be combined
with Apache::AuthenLDAP to provide LDAP authentication as well.

CONFIGURATION OPTIONS
=====================

   The following variables can be defined within the configuration of
Directory, Location, or Files blocks or within .htaccess files.

AuthenBaseDN
     The base distinguished name with which to query LDAP for purposes of
     authentication. By default, the AuthenBaseDN is blank.

AuthzBaseDN
     The base distinguished name with which to query LDAP for purposes of
     authorization. By default, the AuthzBaseDN is blank.

GroupAttrType
     The attribute type name that contains the group's identification. By
     default, GroupAttrType is set to cn.

MemberAttrType
     The attribute type name that contains the group member's
     identification. By default, MemberAttrType is set to member.

MemberAttrValue
     The attribute value contained within the MemberAttrType above. By
     default, MemberAttrValue is set to cn.

NestedGroups
     When the NestedGroups value is on, a recursive group search occurs
     until the user is found in a group or the deepest group's member list
     does not contain any groups. By default, NestedGroups is set to off.

UidAttrType
     The attribute type name that contains the user's identification. By
     default, UidAttrType is set to uid.

NOTES
=====

   This module has hooks built into it to handle Apache::AuthzCache
version 0.02 and higher passing notes to avoid bugs in the set_handlers()
method in mod_perl versions prior to 1.26.

AUTHORS
=======

   Jason Bodnar, Christian Gilmore <cgilmore@tivoli.com>

See ALSO
========

   httpd(8), ldap(3), mod_perl(1), slapd(8C)

COPYRIGHT
=========

   Copyright (C) 2001, International Business Machines Corporation and
others. All Rights Reserved.

   This module is free software; you can redistribute it and/or modify it
under the terms of the IBM Public License.

mod_perl NIS Group Authorization module
***************************************

NAME
====

   Apache::AuthzNIS - mod_perl NIS Group Authorization module

SYNOPSIS
========

     <Directory /foo/bar>
     # This is the standard authentication stuff
     AuthName "Foo Bar Authentication"
     AuthType Basic

     # The following is actually only needed when you will authenticate
     # via NIS passwd as well as authorize via NIS group.
     # Apache::AuthenNIS is a separate module.
     PerlAuthenHandler Apache::AuthenNIS

     # Standard require stuff, NIS users or groups, and
     # "valid-user" all work OK
     require user username1 username2 ...
     require group groupname1 groupname2 ...
     require valid-user

     PerlAuthzHandler Apache::AuthzNIS

     </Directory>

     These directives can also be used in the <Location> directive or in
     an .htaccess file.

DESCRIPTION
===========

   This perl module is designed to work with mod_perl, the Net::NIS module
by Rik Haris (*rik.harris@fulcrum.com.au*), and the Apache::AuthenNIS
module by Demetrios E. Paneras (*dep@media.mit.edu*).  It is a direct
adaptation (i.e. I modified the code) of Michael Parker's
(*parker@austx.tandem.com*) Apache::AuthenSmb module (which also included
an authorization routine).

   The module calls *Net::NIS::yp_match* using each of the *require group*
elements as keys to the the *group.byname* map, until a match with the
(already authenticated) user is found.

   For completeness, the module also handles *require user* and *require
valid-user* directives.

Apache::AuthenNIS vs. Apache::AuthzNIS
--------------------------------------

   I've taken "authentication" to be meaningful only in terms of a user and
password combination, not group membership.  This means that you can use
Apache::AuthenNIS with the *require user* and *require valid-user*
directives.  In the NIS context I consider *require group* to be an
"authorization" concern.  I.e., Group authorization consists of
establishing whether the already authenticated user is a member of one of
the indicated groups in the *require group* directive.  This process may
be handled by *Apache::AuthzNIS*.

   I welcome any feedback on this module, esp. code improvements, given
that it was written hastily, to say the least.

AUTHOR
======

   Demetrios E. Paneras <dep@media.mit.edu>

COPYRIGHT
=========

   Copyright (c) 1998 Demetrios E. Paneras, MIT Media Laboratory.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl replacment for mod_autoindex and mod_dir Apache module
***********************************************************

NAME
====

   Apache::AutoIndex - Perl replacment for mod_autoindex and mod_dir
Apache module

SYNOPSIS
========

     PerlModule Apache::Icon
     PerlModule Apache::AutoIndex
     (PerlModule Image::Magick) optionnal
     PerlTransHandler Apache::AutoIndex::transhandler
     PerlHandler Apache::AutoIndex

DESCRIPTION
===========

   This module can replace completely mod_dir and mod_autoindex standard
directory handling modules shipped with apache.  It can currently live
right on top of those modules, but I suggest simply making a new httpd
without these modules compiled-in.

   To start using it on your site right away, simply preload Apache::Icon
and Apache::AutoIndex either with:

     PerlModule Apache::Icon
     PerlModule Apache::AutoIndex

   in your httpd.conf file or with:

     use Apache::Icon ();
     use Apache::AutoIndex;

     in your require.pl file.

   Then it's simply adding

     PerlTransHandler Apache::Autoindex::transhandler
     PerlHandler Apache::AutoIndex

   somewhere in your httpd.conf but outside any Location/Directory
containers.

VIRTUAL HOSTS
-------------

   If used in a server using virtual hosts, since mod_perl doesn't have
configuration merging routine for virtual hosts, you'll have to put the
PerlHandler and PerlTransHandler directives in each and every
<VHOST></VHOST> section you wish to use Apache::AutoIndex with.

DIRECTIVES
==========

   It uses all of the Configuration Directives defined by mod_dir and
mod_autoindex.

   Since the documentation about all those directives can be found on the
apache website at:

     http://www.apache.org/docs/mod/mod_autoindex.html
     http://www.apache.org/docs/mod/mod_dir.html

   I will only list modification that might have occured in this perl
version.

SUPPORTED DIRECTIVES
--------------------

   * AddDescription

   * DirectoryIndex

   * FancyIndexing - should use IndexOptions FancyIndexing since 1.3.2

   * IndexOptions  - All directives are currently supported. And a few
     were added

   * HeaderName  - It can now accept a list of files instead of just one

   * ReadmeName  - It can now accept a list of files instead of just one

   * IndexIgnore

   * IndexOrderDefault

NEW DIRECTIVES
--------------

   * IndexOptions

     Thumbnails - Lisitng will now include thumbnails for pictures.
     Defaults to false.

     ShowPermissions - prints file permissions. Defaults to false.

   * PerlSetVar IndexHtmlBody 'expression'

     This is an expression that should producea complete <BODY> tag when
     eval'ed.  One example could be :

          PerlSetVar IndexHtmlBody '<BODY BACKGROUND=\"$ENV{BACKGROUND}\">'

   * PerlSetVar IndexHtmlTable value

     This is a string that will be inserted inside the table tag of the
     listing like so : <TABLE $value>

   * PerlSetVar IndexHtmlHead value

     This should be the url (absolute/relative) of a ressource that would
     be inserted right after the <BODY> tag and before anything else is
     written.

   * PerlSetVar IndexHtmlFoot value

     This should be the url (absolute/relative) of a ressource that would
     be inserted right before the </BODY> tag and after everything else is
     written.

   * PerlSetVar IndexDebug [0|1]

     If set to 1, the listing displayed will print usefull (well, to me)
     debugging information appended to the bottom. The default is 0.

UNSUPPORTED DIRECTIVES
----------------------

   * - Hopefully none :-)

THUMBNAILS
==========

   Since version 0.07, generation of thumbnails is possible.  This means
that listing a directory that contains images can be listed with little
reduced thumbnails beside each image name instead of the standard 'image'
icon.

   To enable this you simply need to preload Image::Macick in Apache.  The
IndexOption option Thumbnails controls thumbnails generation for specific
directories like any other IndexOption directive.

USAGE
-----

   The way thumbnails are generated/produced can be configured in many
ways, but here is a general overview of the procedure.

   For each directory containing pictures, there will be a .thumbnails
directory in it that will hold the thumbnails.  Each time the directory is
accessed, and if thumbnail generation is active, small thumbnails will be
produced, shown beside each image name, instaed of the normal , generic,
image icon.

   That can be done in 2 ways.  In the case the image is pretty small, no
actual thumbnail will be created.  Instead the image will be resized with
the HEIGHT and WIDTH attributes of the IMG tag.

   If the image is big enough, it is resized with Image::Magick and saved
in the .thumbnails directory for the next requests.

   Change in the configuration of the indexing options will correctly
refresh the thumbnails stored.  Also if an original image is modified, the
thumbnail will be modified accordingly.  Still, the browser might screw
things up if it preserves the cached images.

   The behaviour of the Thumbnail generating code can be customized with
these PerlSetVar variables:

DIRECTIVES
----------

   * IndexCacheDir dir

     This is the name of the directory in wich generated thumbnails will
     be created.  Make sure the user under wich the webserver runs has
     read and write privileges.  Defaults to .thumbnails

   * IndexCreateDir 0|1

     Specifies that when a cache directory isn't found, should an attempt
     to create it be done.  Defaults to 1(true), meaning if possible,
     missing cache directories will be created.

   * ThumbMaxFilesize bytes

     This value fixes the size of an image at wich thumbnail processing
     isn't even attempted.  Since trying to process a few very big images
     could bring a server down to it's knees.  Defaults to 500,000

   * ThumbMinFilesize bytes

     This value fixes the size of an image at wich thumbnail processing
     isn't actually done.  Since trying to process already very small
     images could would be an overkill, the image is simply resized withe
     the size attributes of the IMG tag.  Defaults to 5,000.

   * ThumbMaxWidth pixels

     This value fixes the x-size of an image at wich thumbnail processing
     isn't actually done.  Since trying to process already very small
     images could would be an overkill, the image is simply resized withe
     the size attributes of the IMG tag.  Defaults to 4 times the default
     icon width.

   * ThumbMaxHeight pixels

     This value fixes the y-size of an image at wich thumbnail processing
     isn't actually done.  Since trying to process already very small
     images could would be an overkill, the image is simply resized withe
     the size attributes of the IMG tag.  Defaults to 4 times the default
     icon height

   * ThumbScaleWidth scaling-factor

     This value fixes an x-scaling factor between 0 and 1 to resize the
     images with.  The image ratio will be preserved only if there is no
     scaling factor for the other axis of the image.

   * ThumbScaleHeight scaling-factor

     This value fixes an y-scaling factor between 0 and 1 to resize the
     images with.  The image ratio will be preserved only if there is no
     scaling factor for the other axis of the image.

   * ThumbWidth pixels

     This value fixes a fixed x-dimension to resize the image with.  The
     image ratio will be preserved only if there is no fixed scaling
     factor for the other axis of the image.  This has no effect if a
     scaling factor is defined.

   * ThumbHeight pixels

     This value fixes a fixed x-dimension to resize the image with.  The
     image ratio will be preserved only if there is no fixed scaling
     factor for the other axis of the image.  This has no effect if a
     scaling factor is defined.

TODO
====

   The transhandler problem should be fixed.

   Some minor changes to the thumbnails options will still have the
thumbnails re-generated.  This should be avoided by checking the
attributes of the already existing thumbnail.

   Some form of garbage collection should be performed or cache
directories will fill up.

   Find new things to add...

SEE ALSO
========

   perl(1), see Apache,(3), see Apache/Icon,(3),
see Image/Magick,(3) .

SUPPORT
=======

   Please send any questions or comments to the Apache modperl mailing
list <modperl@apache.org> or to me at <gozer@ectoplasm.dyndns.com>

NOTES
=====

   This code was made possible by :

Doug MacEachern
     <dougm@pobox.com>  Creator of Apache::Icon, and of course, mod_perl.

Rob McCool
     who produced the final mod_autoindex.c I copied, hrm.., well,
     translated to perl.

The mod_perl mailing-list
     at <modperl@apache.org> for all your mod_perl related problems.

AUTHOR
======

   Philippe M. Chiasson <gozer@ectoplasm.dyndns.com>

COPYRIGHT
=========

   Copyright (c) 1999 Philippe M. Chiasson. All rights reserved. This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

base class for all processors
*****************************

NAME
====

   Apache::AxKit::Language - base class for all processors

DESCRIPTION
===========

   This base class principally provides the get_mtime function for
determining the modification time of the stylesheet. Other modules are
free to override this function - possibly to provide facilities for
determining the minimum mtime of an XML-based stylesheet that includes
external entities.

Matt's non-xslt template processor
**********************************

NAME
====

   Apache::AxKit::Language::NotXSLT - Matt's non-xslt template processor

SYNOPSIS
========

     PerlTypeHandler Apache::AxKit::XMLFinder
     PerlHandler Apache::AxKit::StyleFinder
     PerlSetVar StylesheetMap "application/x-notxslt => \
     		Apache::AxKit::Language::NotXSLT"

DESCRIPTION
===========

   This module implements an XML template system that looks a bit like
XSLT, but isn't. Hence the name. It uses XML::XPath, and should be fast
enough to use on small web sites dynamically, rather than using static
transformation.

AUTHOR
======

   Matt Sergeant, matt@sergeant.org

SEE ALSO
========

   XML::XPath(1).

An XML Stylesheet Language
**************************

NAME
====

   Apache::AxKit::Language::XPathScript - An XML Stylesheet Language

SYNOPSIS
========

     AxAddStyleMap "application/x-xpathscript => \
           Apache::AxKit::Language::XPathScript"

DESCRIPTION
===========

   This documentation has been removed. The definitive reference for
XPathScript is now at http://axkit.org/docs/xpathscript/guide.dkb in
DocBook format.

eXtensible Server Pages
***********************

NAME
====

   Apache::AxKit::Language::XSP - eXtensible Server Pages

DESCRIPTION
===========

   XSP implements a tag-based dynamic language that allows you to develop
your own tags, examples include sendmail and sql taglibs.

DESIGN PATTERNS
===============

   Writing your own taglibs can be tricky, because you're using an event
based API to write out Perl code. These patterns represent the things you
may want to achieve when authoring a tag library.

   *1. Your tag is a wrapper around other things.*

   Example:

     <mail:sendmail>...</mail:sendmail>

   Solution:

   Start a new block, so that you can store lexical variables, and declare
any variables relevant to your tag:

   in parse_start:

     if ($tag eq 'sendmail') {
       return '{ my ($to, $from, $sender);';
     }

   Often it will also be relevant to execute that code when you see the end
tag:

   in parse_end:

     if ($tag eq 'sendmail') {
       return 'Mail::Sendmail::sendmail(
               to => $to,
               from => $from,
               sender => $sender
               ); }';
     }

   Note there the closing of that original opening block.

   *2. Your tag indicates a parameter for a surrounding taglib.*

   Example:

     <mail:to>...</mail:to>

   Solution:

   Having declared the variable as above, you simply set it to the empty
string, with no semi-colon:

   in parse_start:

     if ($tag eq 'to') {
       return '$to = ""';
     }

   Then in parse_char:

   sub parse_char {   my ($e, $text) = @_;   $text =~ s/^\s*//;   $text =~
s/\s*$//;

     return '' unless $text;

     $text =~ s/\|/\\\|/g;
     return ". q|$text|";
     }

   Note there's no semi-colon at the end of all this, so we add that:

   in parse_end:

     if ($tag eq 'to') {
       return ';';
     }

   All of this black magic allows other taglibs to set the thing in that
variable using expressions.

   *3. You want your tag to return a scalar (string) that does the right
thing depending on context. For example, generates a Text node in one
place or generates a scalar in another context.*

   Solution:

   use start_expr(), append_to_script(), end_expr().

   Example:

     <example:get-datetime format="%Y-%m-%d %H:%M:%S"/>

   in parse_start:

     if ($tag eq 'get-datetime') {
       start_expr($e, $tag); # creates a new { ... } block
       my $local_format = lc($attribs{format}) || '%a, %d %b %Y %H:%M:%S %z';
       return 'my ($format); $format = q|' . $local_format . '|;';
     }

   in parse_end:

     if ($tag eq 'get-datetime') {
       append_to_script($e, 'use Time::Object; localtime->strftime($format);');
       end_expr($e);
       return '';
     }

   Explanation:

   This is more complex than the first 2 examples, so it warrants some
explanation. I'll go through it step by step.

     start_expr(...)

   This tells XSP that this really generates a <xsp:expr> tag. Now we don't
really generate that tag, we just execute the handler for it. So what
happens is the <xsp:expr> handler gets called, and it looks to see what
the current calling context is. If its supposed to generate a text node,
it generates some code to do that. If its supposed to generate a scalar, it
does that too. Ultimately both generate a do {} block, so we'll summarise
that by saying the code now becomes:

     do {

   (the end of the block is generated by end_expr()).

   Now the next step (ignoring the simple gathering of the format
variable), is a return, which appends more code onto the generated perl
script, so we get:

     do {
       my ($format); $format = q|%a, %d %b %Y %H:%M:%S %z|;

   Now we immediately receive an end_expr, because this is an empty element
(we'll see why we formatted it this way in #5 below). The first thing we
get is:

     append_to_script($e, 'use Time::Object; localtime->strftime($format);');

   This does exactly what it says, and the script becomes:

     do {
       my ($format); $format = q|%a, %d %b %Y %H:%M:%S %z|;
       use Time::Object; localtime->strftime($format);

   Finally, we call:

     end_expr($e);

   which closes the do {} block, leaving us with:

     do {
       my ($format); $format = q|%a, %d %b %Y %H:%M:%S %z|;
       use Time::Object; localtime->strftime($format);
     }

   Now if you execute that in Perl, you'll see the do {} returns the last
statement executed, which is the `localtime-'strftime()> bit there, thus
doing exactly what we wanted.

   Note that start_expr, end_expr and append_to_script aren't exported by
default, so you need to do:

     use Apache::AxKit::Language::XSP
           qw(start_expr end_expr append_to_script);

   *4. Your tag can take as an option either an attribute, or a child tag.*

   Example:

     <util:include-uri uri="http://server/foo"/>

   or

     <util:include-uri>
       <util:uri><xsp:expr>$some_uri</xsp:expr></util:uri>
     </util:include-uri>

   Solution:

   There are several parts to this. The simplest is to ensure that
whitespace is ignored. We have that dealt with in the example parse_char
above. Next we need to handle that variable. Do this by starting a new
block with the tag, and setting up the variable:

   in parse_start:

     if ($tag eq 'include-uri') {
       my $code = '{ my ($uri);';
       if ($attribs{uri}) {
         $code .= '$uri = q|' . $attribs{uri} . '|;';
       }
       return $code;
     }

   Now if we don't have the attribute, we can expect it to come in the
`<util:uri'> tag:

   in parse_start:

     if ($tag eq 'uri') {
       return '$uri = ""'; # note the empty string!
     }

   Now you can see that we're not explicitly setting $uri, that's because
the parse_char we wrote above handles it by returning '. q|$text|'. And if
we have a `<xsp:expr'> in there, that's handled automagically too.

   Now we just need to wrap things up in the end handlers:

   in parse_end:

     if ($tag eq 'uri') {
       return ';';
     }
     if ($tag eq 'include-uri') {
       return 'Taglib::include_uri($uri); # execute the code
               } # close the block
       ';
     }

   *5. You want to return a scalar that does the right thing in context,
but also can take a parameter as an attribute or a child tag.*

   Example:

     <esql:get-column column="user_id"/>

   vs

     <esql:get-column>
       <esql:column><xsp:expr>$some_column</xsp:expr></esql:column>
     </esql:get-column>

   Solution:

   This is a combination of patterns 3 and 4. What we need to do is change
#3 to simply allow our variable to be added as in #4 above:

   in parse_start:

     if ($tag eq 'get-column') {
       start_expr($e, $tag);
       my $code = 'my ($col);'
       if ($attribs{col}) {
         $code .= '$col = q|' . $attribs{col} . '|;';
       }
       return $code;
     }
     if ($tag eq 'column') {
       return '$col = ""';
     }

   in parse_end:

     if ($tag eq 'column') {
       return ';';
     }
     if ($tag eq 'get-column') {
       append_to_script($e, 'Full::Package::get_column($col)');
       end_expr($e);
       return '';
     }

   *6. You have a conditional tag*

   Example:

     <esql:no-results>
       No results!
     </esql:no-results>

   Solution:

   The problem here is that taglibs normally recieve character/text events
so that they can manage variables. With a conditional tag, you want
character events to be handled by the core XSP and generate text events.
So we have a switch for that:

     if ($tag eq 'no-results') {
       $e->manage_text(0);
       return 'if (AxKit::XSP::ESQL::get_count() == 0) {';
     }

   Turning off manage_text with a zero simply ensures that immediate
children text nodes of this tag don't fire text events to the tag library,
but instead get handled by XSP core, thus creating text nodes (and doing
the right thing, generally).

<xsp:expr> (and start_expr, end_expr) Notes
===========================================

   *Do not* consider adding in the 'do {' ... '}' bits yourself. Always
leave this to the start_expr, and end_expr functions. This is because the
implementation could change, and you really don't know better than the
underlying XSP implementation. You have been warned.

XSP util: taglib.
*****************

NAME
====

   Apache::AxKit::Language::XSP::Util - XSP util: taglib.

SYNOPSIS
========

   Add the util: namespace to your XSP `<xsp:page'> tag:

     <?xml-stylesheet href="." type="application/x-xsp"?>>
     <xsp:page
          language="Perl"
          xmlns:xsp="http://www.apache.org/1999/XSP/Core"
          xmlns:util="http://www.apache.org/1999/XSP/Util"
     >

   And add this taglib to AxKit (via httpd.conf or .htaccess):

     AxAddXSPTaglib Apache::AxKit::Language::XSP::Util

DESCRIPTION
===========

   The XSP util: taglib seeks to add a short list of basic utility
functions to the eXtesible Server Pages library. It trivializes the
inclusion of external fragments and adds a few other useful bells and
whistles.

Tag Structure
-------------

   Most of of the tags require some sort of "argument" to be passed (e.g.
`<util:include-file'> requires the name of the file that is to be read).
Unless otherwise noted, all tags allow you to pass this information either
as an attribute of the current  element or as the text node of an
appropriately named child.

   Thus, both:

     <util:include-file name="foo.xml" />

   and

     <util:include-file>
     <util:name>foo.xml</util:name>
     </util:include-file>

   are valid.

Tag Reference
-------------

`<util:include-file'>
     Provides a way to include an XML fragment from a local file into the
     current parse tree. Requires a name argument. The path may be relative
     or absolute.

`<util:include-uri'>
     Provides a way to include an XML fragment from a (possibly) remote
     URI.  Requires an href argument.

`<util:get-file-contents'>
     Provides a way to include a local file *as plain text*. Requires a
     name argument. The path may be relative or absolute.

`<util:include-expr'>
     Provides a way to include an XML fragment from a scalar variable. Note
     that this tag may *only* pass the required  *expr* argument as a
     child node. Example:

          <util:include-expr>
          <util:expr>$xml_fragment</util:expr>
          </util:include-expr>

`<util:time'>
     Returns a formatted time/date string. Requires a format argument.
     The format is defined using the standard strftime() syntax.

AUTHOR
======

   Kip Hampton, khampton@totalcinema.com

SEE ALSO
========

   AxKit.

Fragment plugin
***************

NAME
====

   Apache::AxKit::Plugins::Fragment - Fragment plugin

DESCRIPTION
===========

   This module provides direct web access to XML fragments, using an XPath
syntax. By simply providing a querystring containing an XPath query, this
module will set the XML to be parsed to be the XML nodes returned by the
query. The nodes will be wrapped in either <resultset>...</resultset> or
you can specify the outer tag using:

     PerlSetVar XPathFragmentElement foo

   to wrap it in <foo>...</foo>.

USAGE
=====

   Simply add this module to the plugin list before StyleFinder:

     PerlHandler Apache::AxKit::Plugins::Fragment \
     		AxKit

   Then request a URL as follows:

     http://server/myfile.xml?/some/xpath/query

   Queries that match the regular expression: ^\w+= are ignored, as are
any invalid XPath queries.

   Note that it's important to write your stylesheet to make use of this
capability! If you intend to use this Fragment plugin, you can't assume
that your stylesheet will just magically work. It will have to not make
assumptions about the XML being passed into it. The apply_templates()
method of XPathScript is extremely useful here, as is the xpath query
'name(/child::node())' which identifies the top level element's name.
Here's how I got around this with my first experiments with this:

     <!-- Main document body -->
     <% if (findvalue('name(/child::node())') eq 'page') { %>
     	<%= apply_templates('/page/body/section') %>
     <% } else { %>
     	<%= apply_templates('/') %>
     <% } %>

   Which checks that the top level element is called 'page', otherwise it
simply does apply_templates() on all the nodes.

allow passthru=1 in querystring
*******************************

NAME
====

   Apache::AxKit::Plugins::Passthru - allow passthru=1 in querystring

DESCRIPTION
===========

   This module allows AxKit to pass through raw XML without processing if
the request contained the option `passthru=1' in the querystring.

   Simply add this module as a handler before the main AxKit handler:

     PerlHandler Apache::AxKit::Plugins::Passthru \
     		AxKit

   Then simply by referencing your xml files as follows:

     http://xml.server.com/myfile.xml?passthru=1

   You will recieve the raw XML in myfile.xml, rather than it being
pre-processed by AxKit.

   This module is also an example of how this can be done, should you wish
to build your own passthru type module that makes the decision to pass
through based on some other parameter, such as the user agent in use.

base Provider class
*******************

NAME
====

   Apache::AxKit::Provider - base Provider class

SYNOPSIS
========

   Override the base Provider class and enable it using:

     AxProvider MyClass

     # alternatively use:
     # PerlSetVar AxProvider MyClass

DESCRIPTION
===========

   The Provider class is used to read in the data source for the given URL.
The default Provider is Provider::File, which reads from the filesystem,
although obviously you can read from just about anywhere.

   Should you wish to override the default Provider, these are the methods
you need to implement:

process()
---------

   Determine whether or not to process this URL. For example, you don't
want to process a directory request, or if the resource doesn't exist.
Return 1 to tell AxKit to process this URL, or die with a Declined
exception (with a reason) if you do not wish to process this URL.

mtime()
-------

   Return the last modification time in days before the current time.

get_styles()
------------

   Extract the stylesheets from the XML resource. Should return an array
ref of styles. The style entries are hashes refs with required keys 'href'
and 'type'.

get_fh()
--------

   This method should return an open filehandle, or die if that's not
possible.

get_strref()
------------

   This method returns a reference to a scalar containing the contents of
the stylesheet, or die if that's not possible. At least one of get_fh or
get_strref must work.

key()
-----

   This method should return a "key" value that is unique to this URL.

get_ext_ent_handler()
---------------------

   This should return a sub reference that can be used instead of
XML::Parser's default external entity handler. See the XML::Parser
documentation for what this sub should do (or look at the code in the File
provider).

exists()
--------

   Return 1 if the resource exists (and is readable).

Choose stylesheets based on a browser cookie
********************************************

NAME
====

   Apache::AxKit::StyleChooser::Cookie - Choose stylesheets based on a
browser cookie

SYNOPSIS
========

     PerlHandler Apache::AxKit::StyleChooser::Cookie \
                 AxKit

DESCRIPTION
===========

   This module checks for the presence of a cookie named
'axkit_preferred_style' and sets the preferred style accordingly.

   Remember, use the title attribute in your stylesheet PI to define a
matching style.

AUTHOR
======

   Kip Hampton, kip@hampton.ws

SEE ALSO
========

   AxKit.

Choose stylesheet using file suffix
***********************************

NAME
====

   Apache::AxKit::StyleChooser::FileSuffix - Choose stylesheet using file
suffix

DESCRIPTION
===========

   This module lets you pick a stylesheet based on the filename suffix. To
use it, simply add this module to the list of PerlTypeHandlers:

     PerlTypeHandler Apache::AxKit::StyleChooser::FileSuffix
     SetHandler perl-script
     PerlHandler AxKit

   Then simply by referencing your xml files as follows:

     http://xml.server.com/myfile.xml.printable

   You will recieve the alternate stylesheets with title "printable". See
the HTML 4.0 specification for more details on stylesheet choice.

   Note that this installation is different from the other StyleChoosers,
because the file we're requesting here doesn't actually exist.

   Thanks to Salve J. Nilsen <sjn@foo.no> for this module.

Choose stylesheet using PATH_INFO
*********************************

NAME
====

   Apache::AxKit::StyleChooser::PathInfo - Choose stylesheet using
PATH_INFO

DESCRIPTION
===========

   This module lets you pick a stylesheet based on the extra PATH_INFO. To
use it, simply add this module to the list of PerlHandlers prior to AxKit:

     PerlHandler Apache::AxKit::StyleChooser::PathInfo \
     		AxKit

   Then simply by referencing your xml files as follows:

     http://xml.server.com/myfile.xml/printable

   You will recieve the alternate stylesheets with title "printable". See
the HTML 4.0 specification for more details on stylesheet choice.

Choose stylesheet using querystring
***********************************

NAME
====

   Apache::AxKit::StyleChooser::QueryString - Choose stylesheet using
querystring

DESCRIPTION
===========

   This module lets you pick a stylesheet based on the querystring. To use
it, simply add this module to the list of PerlHandlers prior to the main
AxKit handler:

     PerlHandler Apache::AxKit::StyleChooser::QueryString \
     		AxKit

   Then simply by referencing your xml files as follows:

     http://xml.server.com/myfile.xml?style=printable

   You will recieve the alternate stylesheets with title "printable". See
the HTML 4.0 specification for more details on stylesheet choice.

Choose stylesheets based on the user agent.
*******************************************

NAME
====

   Apache::AxKit::StyleChooser::UserAgent - Choose stylesheets based on
the user agent.

SYNOPSIS     In your .conf or .htaccess file(s):          PerlHandler Apache::AxKit::StyleChooser::UserAgent \                 AxKit
====================================================================================================================================

     PerlSetVar AxUAStyleMap "lynx     => Lynx,\
                              explorer => MSIE,\
                              opera    => Opera,\
                              netscape => Mozilla"

DESCRIPTION
===========

   This module sets the internal preferred style based on the user agent
string presented by the connecting client.

   Remember, use the title attribute in your stylesheet PI to define a
matching style.

AUTHOR
======

   Kip Hampton, khampton@totalcinema.com

SEE ALSO
========

   AxKit.

Execute module based on <?xml-stylesheet?>
******************************************

NAME
====

   Apache::AxKit::StyleFinder - Execute module based on <?xml-stylesheet?>

DESCRIPTION
===========

   This module is completely deprecated to the point of not working.

DEPRECATED!!!
*************

NAME
====

   Apache::AxKit::StyleProvider - DEPRECATED!!!

DESCRIPTION
===========

   This module is deprecated. Please do not derive from it or use it.

Detects XML files
*****************

NAME
====

   Apache::AxKit::XMLFinder - Detects XML files

DESCRIPTION
===========

   This module is deprecated to the point of no longer working. Please see
AxKit, instead.

Use CIPP embedded HTML Pages with mod_perl
******************************************

NAME
====

   Apache::CIPP - Use CIPP embedded HTML Pages with mod_perl

SYNOPSIS
========

     <Location ~ ".*\.cipp" >

     # Advise Apache to use Apache::CIPP as the request
     # handler for this Location
     SetHandler "perl-script"
     PerlHandler Apache::CIPP

     # directory for caching of preprocessed CIPP programs
     # (this must be writable by the webserver user)
     PerlSetVar 	cache_dir	/tmp/cipp_cache

     # what language do you prefer for error messages?
     # (EN=English, DE=German)
     PerlSetVar	lang		EN

     # debugging infos to error log?
     PerlSetVar	debug		1

     # used databases
     # (comma separated, whitespace is ignored)
     PerlSetVar	databases	"zyn, foo"

     # default database
     PerlSetVar	default_db	zyn

     # configuration for the database named 'zyn'
     # (please refer to the DBI documentation for details)
     PerlSetVar	db_zyn_data_source      dbi:mysql:zyn
     PerlSetVar	db_zyn_user             my_username1
     PerlSetVar	db_zyn_password         my_password1
     PerlSetVar	db_zyn_auto_commit      1

     # configuration for the database named 'foo'
     PerlSetVar	db_foo_data_source      dbi:Oracle:foo
     PerlSetVar	db_foo_user             my_username2
     PerlSetVar	db_foo_password         my_password2
     PerlSetVar	db_foo_auto_commit      0

     </Location>

DESCRIPTION
===========

   This module enables you to use the powerful CIPP HTML embedding
language together with the Apache webserver.  It is based on mod_perl and
works as a request handler.  So you can transparently use CIPP pages
everywhere on your webserver.

WHAT IS CIPP?
=============

   CIPP is a Perl module for translating CIPP sources to pure Perl
programs. CIPP defines a HTML embedding language also called CIPP which
has powerful features for CGI and database developers.

   Many standard CGI and database operations (and much more) are covered
by CIPP, so the developer does not need to code them again and again.

   CIPP is not part of this distribution, please download it from CPAN.

SIMPLE CIPP EXAMPLE
===================

   To give you some imagination of what you can do with CIPP: here is a
(really) simple example of using CIPP in a HTML source to retrieve some
information from a database. Think this as a HTML page which is "executed"
on the fly by your Apache webserver.  Note: there is no code to connect to
the database. This is done implicitely. The configuration is taken from
the Apache configuration file(s).

     # print table of users who match the given parameter

     <?INTERFACE INPUT="$search_name">

     <HTML>
     <HEAD><TITLE>tiny litte CIPP example</TITLE></HEAD>
     <BODY>
     <H1>Users matching '$search_name'</H1>
     <P>

     <TABLE BORDER=1>
     <TR><TD>Name</TD><TD>Adress</TD><TD>Phone</TD></TR>
     <?SQL SQL="select name, adress, phone
                from   people
     	     where  name like '%' || ? || '%'"
           PARAMS="$search_name"
     	MY VAR="$n, $a, $p">
       <TR><TD>$n</TD><TD>$a</TD><TD>$p</TD></TR>
     <?/SQL>
     </TABLE>

     </BODY>
     </HTML>

CONFIGURATION
=============

   Place the configuration options listed in the SYNOPSIS into your Apache
configuration file(s) (e.g. httpd.conf). The SYNOPSIS example configures
all files with the suffix .cipp to be handled by Apache::CIPP. Please
refer to the Apache documentation for details about configuring your
webserver.

   The CIPP PDF documentation contains some more explantation of the
Apache::CIPP configuration parameters. Also CGI::CIPP explains them
briefly. You can download the documentation and CGI::CIPP from CPAN.

DOWNLOAD Apache::CIPP
=====================

   Apache::CIPP and friends can be downloaded from CPAN

     $CPAN/modules/by-authors/id/J/JR/JRED/

INSTALLING Apache::CIPP
=======================

     perl Makefile.PL
     make
     make test
     make install

AUTHOR
======

   Joern Reder <joern@dimedis.de>

COPYRIGHT
=========

   Copyright 1998-1999 Joern Reder, All Rights Reserved

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1), CIPP(3pm), CGI::CIPP(3pm), CIPP::Manual(3pm)

mod_perl interface into HTML::Clean
***********************************

NAME
====

   Apache::Clean - mod_perl interface into HTML::Clean

SYNOPSIS
========

   httpd.conf:

     <Location /someplace>
        SetHandler perl-script
        PerlHandler Apache::Clean

     PerlSetVar  CleanLevel 3
      </Location>

   Apache::Clean is Filter aware, meaning that it can be used within
Apache::Filter framework without modification.  Just include the directives

     PerlModule Apache::Filter
     PerlSetVar Filter On

   and modify the PerlHandler directive accordingly...

DESCRIPTION
===========

   Apache::Clean uses HTML::Clean to tidy up large, messy HTML, saving
bandwidth.  It is particularly useful with Apache::Compress for ultimate
savings.

   The only current configuration directive is CleanLevel, which defaults
to 3.  Apache::Clean will only tidy up whitespace (via $h->strip) and will
not perform other options of HTML::Clean (such as browser compatibility).
See the HTML::Clean manpage for details.

   Only documents with a content type of "text/html" are affected - all
others are passed through unaltered.

NOTES
=====

   Verbose debugging is enabled by setting $Apache::Clean::DEBUG=1 or
greater.  To turn off all debug information, set your apache LogLevel
directive above info level.

   This is alpha software, and as such has not been tested on multiple
platforms or environments.  It requires PERL_LOG_API=1, PERL_FILE_API=1,
and maybe other hooks to function properly.

FEATURES/BUGS
=============

     No unknown bugs or features at this time...

SEE ALSO
========

   perl(1), mod_perl(3), Apache(3), Apache::Filter(3),
Apache::Compress(3), HTML::Clean(3)

AUTHOR
======

   Geoffrey Young <geoff@cpan.org>

COPYRIGHT
=========

   Copyright (c) 2001, Geoffrey Young.  All rights reserved.

   This module is free software.  It may be used, redistributed and/or
modified under the same terms as Perl itself.

Auto-compress web files with Gzip
*********************************

NAME
====

   Apache::Compress - Auto-compress web files with Gzip

SYNOPSIS
========

     PerlModule Apache::Compress

     # Compress regular files
     <FilesMatch "\.blah$">
      PerlHandler Apache::Compress
     </FilesMatch>

     # Compress output of Perl scripts
     PerlModule Apache::Filter
     <FilesMatch "\.pl$">
      PerlSetVar Filter on
      PerlHandler Apache::RegistryFilter Apache::Compress
     </FilesMatch>

DESCRIPTION
===========

   This module lets you send the content of an HTTP response as
gzip-compressed data.  Certain browsers (Netscape, IE) can request content
compression via the `Content-Encoding' header.  This can speed things up
if you're sending large files to your users through slow connections.

   Browsers that don't request gzipped data will receive regular
noncompressed data.

   This module is compatibile with Apache::Filter, so you can compress the
output of other content-generators.

TO DO
=====

   Compress::Zlib provides a facility for buffering output until there's
enough data for efficient compression.  Currently we don't take advantage
of this facility, we simply compress the whole content body at once.  We
could achieve better memory usage if we changed this (at a small cost to
the compression ratio).  See Eagle book, p.185.

AUTHOR
======

   Ken Williams, ken@forum.swarthmore.edu

   Partially based on the work of several modules, like Doug MacEachern's
Apache::Gzip (in the Eagle book but not on CPAN), Andreas Koenig's
Apache::GzipChain, and an unreleased module by Geoffrey Young and Philippe
Chiasson.

SEE ALSO
========

   perl(1), mod_perl(1), Apache::Filter(3)

Constants defined in apache header files
****************************************

NAME
====

   Apache::Constants - Constants defined in apache header files

SYNOPSIS
========

     use Apache::Constants;
     use Apache::Constants ':common';
     use Apache::Constants ':response';

DESCRIPTION
===========

   Server constants used by apache modules are defined in *httpd.h* and
other header files, this module gives Perl access to those constants.

EXPORT TAGS
===========

common
     This tag imports the most commonly used constants.

          OK
          DECLINED
          DONE
          NOT_FOUND
          FORBIDDEN
          AUTH_REQUIRED
          SERVER_ERROR

response
     This tag imports the common response codes, plus these response codes:

          DOCUMENT_FOLLOWS
          MOVED
          REDIRECT
          USE_LOCAL_COPY
          BAD_REQUEST
          BAD_GATEWAY
          RESPONSE_CODES
          NOT_IMPLEMENTED
          CONTINUE
          NOT_AUTHORITATIVE

     *CONTINUE* and *NOT_AUTHORITATIVE* are aliases for *DECLINED*.

methods
     This are the method numbers, commonly used with the Apache
     *method_number* method.

          METHODS
          M_CONNECT
          M_DELETE
          M_GET
          M_INVALID
          M_OPTIONS
          M_POST
          M_PUT
          M_TRACE
          M_PATCH
          M_PROPFIND
          M_PROPPATCH
          M_MKCOL
          M_COPY
          M_MOVE
          M_LOCK
          M_UNLOCK

options
     These constants are most commonly used with the Apache
     *allow_options* method:

          OPT_NONE
          OPT_INDEXES
          OPT_INCLUDES
          OPT_SYM_LINKS
          OPT_EXECCGI
          OPT_UNSET
          OPT_INCNOEXEC
          OPT_SYM_OWNER
          OPT_MULTI
          OPT_ALL

satisfy
     These constants are most commonly used with the Apache *satisfies*
     method:

          SATISFY_ALL
          SATISFY_ANY
          SATISFY_NOSPEC

remotehost
     These constants are most commonly used with the Apache
     *get_remote_host* method:

          REMOTE_HOST
          REMOTE_NAME
          REMOTE_NOLOOKUP
          REMOTE_DOUBLE_REV

http
     This is the full set of HTTP response codes: (NOTE: not all
     implemented here)

          HTTP_OK
          HTTP_MOVED_TEMPORARILY
          HTTP_MOVED_PERMANENTLY
          HTTP_METHOD_NOT_ALLOWED
          HTTP_NOT_MODIFIED
          HTTP_UNAUTHORIZED
          HTTP_FORBIDDEN
          HTTP_NOT_FOUND
          HTTP_BAD_REQUEST
          HTTP_INTERNAL_SERVER_ERROR
          HTTP_NOT_ACCEPTABLE
          HTTP_NO_CONTENT
          HTTP_PRECONDITION_FAILED
          HTTP_SERVICE_UNAVAILABLE
          HTTP_VARIANT_ALSO_VARIES

server
     These are constants related to server version:

          MODULE_MAGIC_NUMBER
          SERVER_VERSION
          SERVER_BUILT

config
     These are constants related to configuration directives:

          DECLINE_CMD

types
     These are constants related to internal request types:

          DIR_MAGIC_TYPE

override
     These constants are used to control and test the context of
     configuration directives.

          OR_NONE
          OR_LIMIT
          OR_OPTIONS
          OR_FILEINFO
          OR_AUTHCFG
          OR_INDEXES
          OR_UNSET
          OR_ALL
          ACCESS_CONF
          RSRC_CONF

args_how
          RAW_ARGS
          TAKE1
          TAKE2
          TAKE12
          TAKE3
          TAKE23
          TAKE123
          ITERATE
          ITERATE2
          FLAG
          NO_ARGS

AUTHORS
=======

   Doug MacEachern, Gisle Aas and h2xs

mod_perl extension for uniform application generation.
******************************************************

NAME
====

   Apache::ContentHandler - mod_perl extension for uniform application
generation.

SYNOPSIS
========

   use Apache::ContentHandler;

   @ISA = 'Apache::ContentHandler';

   sub handler {   my $r = shift;   my $algometer = new
Apache::Algometer($r);   my $result = $algometer->run;   return $result; }

   sub _init {   my $self = shift || die 'need $self';
$self->SUPER::_init(@_);

     # overrides
     $self->{title}     = 'Project Algometer';
     $self->{subtitle}  = "Version $VERSION";
     $self->{default_action} = 'hello';
     # other variable definitions
     }

   sub hello {   return '<P>Hello World</P>'; }

DESCRIPTION
===========

   Apache::ContentHandler is a generic framework for creating mod_perl
based applications. It provides a basic event mechanism and a subclassable
framework for customizing actions.

AUTHOR
======

   Ryan Davis, Zen Spider Software <ryand-ch@zenspider.com>

PUBLIC METHODS
==============

   * $ch = Apache::ContentHandler->new
          Creates a new ContentHandler. You should not override this, override
          _init instead.

   * $hc->run

     The main application structure. Provides for a standard header, body,
     and footer. You probably do not want to override this, override the
     individual methods instead.

PROTECTED METHODS
=================

   * _init

     Private: called by new. Override to put your application specific
     variables here.

   * $val = $self->arg($key)

     Returns a CGI/mod_perl parameter for the key $key.

   * @keys = $self->args

     Returns a list of all of the mod_perl/cgi parameters.

   * $s = $hc->header

     Returns a string containing the preheader, an HTML title, and a
     postheader. You probably do not want to override this unless you want
     a different type of title.

   * $s = $hc->work

     Runs a method corresponding to the $action parameter, or the default
     action, and returns the content as the body of the document. If the
     $action does not exist, then it puts up a page stating that. This
     makes rapid prototyping very easy and quick.

   * $s = $hc->footer

     Returns a string containing the prefooter, and postfooter. This used
     to have a standard footer as well, but I found it annoying.

   * $s = $hc->errors

     Returns a dictionary list detailing the contents of the error hash, if
     any.

   * $s = $hc->preheader

     Returns the contents of the preheader. Override to add something
     before the title.

   * $s = $hc->postheader

     Returns the contents of the postheader. Override to add something
     after the title.

   * $s = $hc->prework

     Returns the contents of the prework. Override to add something before
     the body.

   * $s = $hc->postwork

     Returns the contents of the postwork. Override to add something after
     the body.

   * $s = $hc->prefooter

     Returns the contents of the prefooter. Override to add something
     before the footer.

   * $s = $hc->postfooter

     Returns the contents of the postfooter. Override to add something
     after the footer.

   * $s = $hc->reportError

     Sends an email to the addresses listed in error_email, detailing an
     error with as much debugging content as possible. Used for fatal
     conditions.

   * $s = $hc->dbi

     Returns a DBI connection. Override _init and add values for
     dbi_driver, dbi_user, and dbi_password to make this connection.

   * $s = $hc->sqlToTable

     Returns an HTML representation of a SQL statement in table form.

   * $s = $hc->sqlToArrays

     Returns an array representing a SQL query.

   * $s = $hc->sqlToHashes

     Returns a hash representing a SQL query.

   * $s = $hc->query1

     Returns a single value from a SQL query. The query must return a
     single column and row (ie SELECT name FROM users WHERE id=42).

HTTP Cookies Class
******************

NAME
====

   Apache::Cookie - HTTP Cookies Class

SYNOPSIS
========

     use Apache::Cookie ();
     my $cookie = Apache::Cookie->new($r, ...);

DESCRIPTION
===========

   The Apache::Cookie module is a Perl interface to the cookie routines in
*libapreq*.  The interface is based on Lincoln Stein's CGI::Cookie module.

METHODS
=======

   This interface is identical the to CGI::Cookie interface with one
exception noted below.  Refer the to CGI::Cookie documentation while these
docs are "under construction."

new
---

   Just like CGI::Cookie::new, but requires an Apache request object:

     my $cookie = Apache::Cookie->new($r,
                          -name    =>  'foo',
                          -value   =>  'bar',
                          -expires =>  '+3M',
                          -domain  =>  '.capricorn.com',
                          -path    =>  '/cgi-bin/database',
                          -secure  =>  1
                         );

bake
----

   Put cookie in the oven to bake.  (Add a *Set-Cookie* header to the
outgoing headers table.)

     $cookie->bake;

parse
-----

   This method parses the given string if present, otherwise, the incoming
*Cookie* header:

     my $cookies = $cookie->parse; #hash ref

     my %cookies = $cookie->parse;

     my %cookies = $cookie->parse($cookie_string);

fetch
-----

   Fetch and parse the incoming *Cookie* header:

     my $cookies = Apache::Cookie->fetch; #hash ref

     my %cookies = Apache::Cookie->fetch;

as_string
---------

   Format the cookie object as a string:

     #same as $cookie->bake
     $r->err_headers_out->add("Set-Cookie" => $cookie->as_string);

name
----

   Get or set the name of the cookie:

     my $name = $cookie->name;

     $cookie->name("Foo");

value
-----

   Get or set the values of the cookie:

     my $value = $cookie->value;
     my @values = $cookie->value;

     $cookie->value("string");
     $cookie->value(\@array);

domain
------

   Get or set the domain for the cookie:

     my $domain = $cookie->domain;
     $cookie->domain(".cp.net");

path
----

   Get or set the path for the cookie:

     my $path = $cookie->path;
     $cookie->path("/");

expires
-------

   Get or set the expire time for the cookie:

     my $expires = $cookie->expires;
     $cookie->expires("+3h");

secure
------

   Get or set the secure flag for the cookie:

     my $secure = $cookie->secure;
     $cookie->secure(1);

SEE ALSO
========

   Apache(3), Apache::Request(3)

AUTHOR
======

   Doug MacEachern

Run the interactive Perl debugger under mod_perl
************************************************

NAME
====

   Apache::DB - Run the interactive Perl debugger under mod_perl

SYNOPSIS
========

     <Location /perl>
      PerlFixupHandler +Apache::DB

     SetHandler perl-script
     PerlHandler +Apache::Registry
     Options +ExecCGI
      </Location>

DESCRIPTION
===========

   Perl ships with a very useful interactive debugger, however, it does
not run "out-of-the-box" in the Apache/mod_perl environment.  Apache::DB
makes a few adjustments so the two will cooperate.

FUNCTIONS
=========

init
     This function initializes the Perl debugger hooks without actually
     starting the interactive debugger.  In order to debug a certain piece
     of code, this function must be called before the code you wish debug
     is compiled.  For example, if you want to insert debugging symbols
     into code that is compiled at server startup, but do not care to debug
     until request time, call this function from a PerlRequire'd file:

          #where db.pl is simply:
          # use Apache::DB ();
          # Apache::DB->init;
          PerlRequire conf/db.pl

          #where modules are loaded
          PerlRequire conf/init.pl

handler
     This function will start the interactive debugger.  It will invoke
     *Apache::DB::init* if needed.  Example configuration:

          <Location /my-handler>
           PerlFixupHandler Apache::DB
           SetHandler perl-script
           PerlHandler My::handler
          </Location>

CAVEATS
=======

-X
     The server must be started with the -X to use Apache::DB.

filename/line info
     The filename of Apache::Registry scripts is not displayed.

SEE ALSO
========

   perldebug(1)

AUTHOR
======

   Doug MacEachern

Initiate a persistent database connection
*****************************************

NAME
====

   Apache::DBI - Initiate a persistent database connection

SYNOPSIS
========

     # Configuration in httpd.conf or startup.pl:

     PerlModule Apache::DBI  # this comes before all other modules using DBI

   Do NOT change anything in your scripts. The usage of this module is
absolutely transparent !

DESCRIPTION
===========

   This module initiates a persistent database connection.

   The database access uses Perl's DBI. For supported DBI drivers see:

     http://www.symbolstone.org/technology/perl/DBI/

   When loading the DBI module (do not confuse this with the Apache::DBI
module) it looks if the environment variable GATEWAY_INTERFACE starts with
'CGI-Perl' and if the module Apache::DBI has been loaded. In this case
every connect request will be forwarded to the Apache::DBI module. This
looks if a database handle from a previous connect request is already
stored and if this handle is still valid using the ping method. If these
two conditions are fulfilled it just returns the database handle. The
parameters defining the connection have to be exactly the same, including
the connect attributes ! If there is no appropriate database handle or if
the ping method fails, a new connection is established and the handle is
stored for later re-use. There is no need to remove the disconnect
statements from your code. They won't do anything because the Apache::DBI
module overloads the disconnect method.

   The Apache::DBI module still has a limitation: it keeps database
connections persistent on a per process basis. The problem is, if a user
accesses several times a database, the http requests will be handled very
likely by different servers. Every server needs to do its own connect. It
would be nice, if all servers could share the database handles. Currently
this is not possible, because of the distinct name-space of every process.
Also it is not possible to create a database handle upon startup of the
httpd and then inheriting this handle to every subsequent server. This
will cause clashes when the handle is used by two processes at the same
time.

   With this limitation in mind, there are scenarios, where the usage of
Apache::DBI is depreciated. Think about a heavy loaded Web-site where every
user connects to the database with a unique userid. Every server would
create many database handles each of which spawning a new backend process.
In a short time this would kill the web server.

   Another problem are timeouts: some databases disconnect the client
after a certain time of inactivity. The module tries to validate the
database handle using the ping-method of the DBI-module. This method
returns true as default.  If the database handle is not valid and the
driver has no implementation for the ping method, you will get an error
when accessing the database. As a work-around you can try to replace the
ping method by any database command, which is cheap and safe or you can
deactivate the usage of the ping method (see CONFIGURATION below).

   Here is generalized ping method, which can be added to the driver
module:

   {   package DBD::xxx::db; # ====== DATABASE ======     use strict;

     sub ping {
         my($dbh) = @_;
         my $ret = 0;
         eval {
             local $SIG{__DIE__}  = sub { return (0); };
             local $SIG{__WARN__} = sub { return (0); };
             # adapt the select statement to your database:
             $ret = $dbh->do('select 1');
         };
         return ($@) ? 0 : $ret;
     }
     }

   Transactions: a standard DBI script will automatically perform a
rollback whenever the script exits. In the case of persistent database
connections, the database handle will not be destroyed and hence no
automatic rollback occurs. At a first glance it seems even to be possible,
to handle a transaction over multiple requests. But this should be
avoided, because different requests are handled by different servers and a
server does not know the state of a specific transaction which has been
started by another server. In general it is good practice to perform an
explicit commit or rollback at the end of every script. In order to avoid
inconsistencies in the database in case AutoCommit is off and the script
finishes without an explicit rollback, the Apache::DBI module uses a
PerlCleanupHandler to issue a rollback at the end of every request. Note,
that this CleanupHandler will only be used, if the initial data_source
sets AutoCommit = 0. It will not be used, if AutoCommit will be turned
off, after the connect has been done.

   This module plugs in a menu item for Apache::Status. The menu lists the
current database connections. It should be considered incomplete because of
the limitations explained above. It shows the current database connections
for one specific server, the one which happens to serve the current
request.  Other servers might have other database connections. The
Apache::Status module has to be loaded before the Apache::DBI module !

CONFIGURATION
=============

   The module should be loaded upon startup of the Apache daemon.  Add the
following line to your httpd.conf or startup.pl:

     PerlModule Apache::DBI

   It is important, to load this module before any other modules using DBI
!

   A common usage is to load the module in a startup file via the
PerlRequire directive. See eg/startup.pl for an example.

   There are two configurations which are server-specific and which can be
done upon server startup:

     Apache::DBI->connect_on_init($data_source, $username, $auth, \%attr)

   This can be used as a simple way to have apache servers establish
connections on process startup.

     Apache::DBI->setPingTimeOut($data_source, $timeout)

   This configures the usage of the ping method, to validate a connection.
Setting the timeout to 0 will always validate the database connection
using the ping method (default). Setting the timeout < 0 will de-activate
the validation of the database handle. This can be used for drivers, which
do not implement the ping-method. Setting the timeout > 0 will ping the
database only if the last access was more than timeout seconds before.

   For the menu item 'DBI connections' you need to call Apache::Status
BEFORE Apache::DBI ! For an example of the configuration order see
startup.pl.

   To enable debugging the variable $Apache::DBI::DEBUG must be set. This
can either be done in startup.pl or in the user script. Setting the
variable to 1, just reports about a new connect. Setting the variable to 2
enables full debug output.

PREREQUISITES
=============

   Note that this module needs mod_perl-1.08 or higher, apache_1.3.0 or
higher and that mod_perl needs to be configured with the appropriate
call-back hooks:

     PERL_CHILD_INIT=1 PERL_STACKED_HANDLERS=1.

SEE ALSO
========

   See Apache, `mod_perl' in this node, `DBI' in this node

AUTHORS
=======

   * mod_perl by Doug MacEachern <modperl@apache.org>

   * DBI by Tim Bunce <dbi-users@isc.org>

   * Apache::AuthenDBI by Edmund Mergl <E.Mergl@bawue.de>

COPYRIGHT
=========

   The Apache::DBI module is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

Logs access information in a DBI database
*****************************************

NAME
====

   Apache::DBILogConfig - Logs access information in a DBI database

SYNOPSIS
========

     # In httpd.conf
     PerlLogHandler Apache::DBILogConfig
     PerlSetVar DBILogConfig_data_source DBI:Informix:log_data
     PerlSetVar DBILogConfig_username    informix
     PerlSetVar DBILogConfig_password    informix
     PerlSetVar DBILogConfig_table	     mysite_log
     PerlSetVar DBILogConfig_log_format  "%b=bytes_sent %f=filename %h=remote_host %r=request %s=status"

DESCRIPTION
===========

   This module replicates the functionality of the standard Apache module,
mod_log_config, but logs information in a DBI-compliant database instead
of a file.

LIST OF TOKENS
==============

DBILogConfig_data_source
     A DBI data source with a format of "DBI::driver:database"

DBILogConfig_username
     Username passed to the database driver when connecting

DBILogConfig_password
     Password passed to the database driver when connecting

DBILogConfig_table
     Table in the database for logging

DBILogConfig_log_format
     A string consisting of formats seperated by white space that define
     the data to be looged (see FORMATS below)

FORMATS
=======

   A format consists of a string with the following syntax:

   *%[conditions][{parameter}]format=field*

format
------

   Formats specify the type of data to be logged. The following formats
are accepted:

b Bytes sent
f Filename
e Environment variable (specified by parameter)
h Remote host
a Remote IP Address
i Header in the client request (specified by parameter)
l Remote log name (from identd)
n Contents of a note from another module (specified by parameter)
o Header from the reply (specified by parameter)
p Server port
P Apache child PID
r First line of the request
s Request status
t Time in common log format (default) or strftime() (parameter)
T Time taken to serve request
u Remote user from auth
U URL
v Server hostname
field
-----

   A database column to log the data to

parameter
---------

   For formats that take a parameter

   Example: %{DOCUMENT_ROOT}e

conditions
----------

   Conditions are a comma-seperated list of status codes. If the status of
the request being logged equals one of the status codes in the condition
the data specified by the format will be logged. By placing a '!' in front
of the conditions, data will be logged if the request status does not
match any of the conditions.

   Example: %!200,304,302s=status will log the status of all requests that
did not return some sort of normal status

DEBUGGING
=========

   Debugging statements will be written to the error log if LOGLEVEL is
set to 'warn' or higher

PREREQUISITES
=============

   * mod_perl >= 1.11_01 with PerlLogHandler enabled

   * DBI

   * Date::Format

INSTALLATION
============

   To install this module, move into the directory where this file is
located and type the following:

     perl Makefile.PL
     make
     make test
     make install

   This will install the module into the Perl library directory.

   Once installed, you will need to modify your web server's configuration
as above.

AUTHOR
======

   Copyright (C) 1998, Jason Bodnar <jcbodnar@mail.utexas.edu>. All rights
reserved.

   This module is free software; you may redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1), mod_perl(3)

Tracks what's being transferred in a DBI database
*************************************************

NAME
====

   Apache::DBILogger - Tracks what's being transferred in a DBI database

SYNOPSIS
========

     # Place this in your Apache's httpd.conf file
     PerlLogHandler Apache::DBILogger

     PerlSetVar DBILogger_data_source    DBI:mysql:httpdlog
     PerlSetVar DBILogger_username       httpduser
     PerlSetVar DBILogger_password       secret
     PerlSetvar DBILogger_table          requests

     Create a database with a table named B<requests> like this:

   CREATE TABLE requests (   server varchar(127) DEFAULT " NOT NULL,
bytes mediumint(9) DEFAULT '0' NOT NULL,   user varchar(15) DEFAULT " NOT
NULL,   filename varchar(200) DEFAULT " NOT NULL,   remotehost
varchar(150) DEFAULT " NOT NULL,   remoteip varchar(15) DEFAULT " NOT NULL,
 status smallint(6) DEFAULT '0' NOT NULL,   timeserved datetime DEFAULT
'0000-00-00 00:00:00' NOT NULL,   contenttype varchar(50) DEFAULT " NOT
NULL,   urlpath varchar(200) DEFAULT " NOT NULL,   referer varchar(250)
DEFAULT " NOT NULL,   useragent varchar(250) DEFAULT " NOT NULL,
usertrack varchar(100) DEFAULT " NOT NULL,   KEY server_idx (server),
KEY timeserved_idx (timeserved) );

   Its recommended that you include

   use Apache::DBI; use DBI; use Apache::DBILogger;

   in your startup.pl script. Please read the Apache::DBI documentation for
further information.

DESCRIPTION
===========

   This module tracks what's being transfered by the Apache web server in a
SQL database (everything with a DBI/DBD driver).  This allows to get
statistics (of almost everything) without having to parse the log files
(like the Apache::Traffic module, just in a "real" database, and with a
lot more logged information).

   Apache::DBILogger will track the cookie from 'mod_usertrack' if it's
there.

   After installation, follow the instructions in the synopsis and restart
the server.

   The statistics are then available in the database. See the section
VIEWING STATISTICS for more details.

PREREQUISITES
=============

   You need to have compiled mod_perl with the LogHandler hook in order to
use this module. Additionally, the following modules are required:

     o DBI
     o Date::Format

INSTALLATION
============

   To install this module, move into the directory where this file is
located and type the following:

     perl Makefile.PL
     make
     make test
     make install

   This will install the module into the Perl library directory.

   Once installed, you will need to modify your web server's configuration
file so it knows to use Apache::DBILogger during the logging phase.

VIEWING STATISTICS
==================

   Please see the bin/ directory in the distribution for a statistics
script.

   Some funny examples on what you can do might include:

hit count and total bytes transfered from the virtual server www.company.com
          select count(id),sum(bytes) from requests
          where server="www.company.com"

hit count and total bytes from all servers, ordered by number of hits
          select server,count(id) as hits,sum(bytes) from requests
          group by server order by hits desc

count of hits from macintosh users
          select count(id) from requests where useragent like "%Mac%"

hits and total bytes in the last 30 days     select count(id),sum(bytes) from requests where     server="www.company.com" and TO_DAYS(NOW()) -     TO_DAYS(timeserved) <= 30
     This is pretty unoptimal.  It would be faster to calculate the dates
     in perl and write them in the sql query using f.x. Date::Format.

hits and total bytes from www.company.com on mondays.
          select count(id),sum(bytes) from requests where
          server="www.company.com" and dayofweek(timeserved) = 2

   It's often pretty interesting to view the referer info too.

   See your sql server documentation of more examples. I'm a happy mySQL
user, so I would continue on

   http://www.tcx.se/Manual_chapter/manual_toc.html

LOCKING ISSUES
==============

   MySQL 'read locks' the table when you do a select. On a big table (like
a large httpdlog) this might take a while, where your httpds can't insert
new logentries, which will make them 'hang' until the select is done.

   One way to work around this is to create another table (f.x.
requests_insert) and get the httpd's to insert to this table.

   Then run a script from crontab once in a while which does something
like this:

     LOCK TABLES requests WRITE, requests_insert WRITE
     insert into requests select * from requests_insert
     delete from requests_insert
     UNLOCK TABLES

   You can use the moverows.pl script from the bin/ directory.

   Please note that this won't work if you have any unique id field!
You'll get duplicates and your new rows won't be inserted, just deleted.
Be careful.

TRAPS
=====

   I've experienced problems with 'Packets too large' when using
Apache::DBI, mysql and DBD::mysql 2.00 (from the Msql-mysql 1.18x
packages).  The DBD::mysql module from Msql-mysql 1.19_17 seems to work
fine with Apache::DBI.

   You might get problems with Apache 1.2.x. (Not supporting
post_connection?)

SUPPORT
=======

   This module is supported via the mod_perl mailinglist
(modperl@apache.org, subscribe by sending a mail to
modperl-request@apache.org).

   I would like to know which databases this module have been tested on,
so please mail me if you try it.

   The latest version can be found on your local CPAN mirror or at
`ftp://ftp.netcetera.dk/pub/perl/'

AUTHOR
======

   Copyright (C) 1998, Ask Bjoern Hansen <ask@netcetera.dk>. All rights
reserved. This module is free software; you may redistribute it and/or
modify it under the same terms as Perl itself.

SEE ALSO
========

   perl(1), mod_perl(3)

authenticates and authorizes via a DBI connection
*************************************************

NAME
====

   Apache::DBILogin - authenticates and authorizes via a DBI connection

SYNOPSIS
========

     #in .htaccess
     AuthName MyAuth
     AuthType Basic
     PerlAuthenHandler Apache::DBILogin::authen
     PerlSetVar Auth_DBI_data_source dbi:Oracle:SQLNetAlias
     PerlAuthzHandler Apache::DBILogin::authz

     allow from all
     require group connect resource dba
     satisfy all

     #in startup.pl
     package Apache::DBILogin;

     # is_member function for authz handler
     #  expects a request object, database handle, and the group you which to test
     #  returns a valid response code
     sub is_member {
         my ($r, $dbh, $group) = @_;

         my $sth;
         eval {
             # no, Oracle doesn't support binding in SET ROLE statement
             $sth = $dbh->prepare("SET ROLE $group") or die $DBI::errstr;
         };
         return SERVER_ERROR if ( $@ );

         return ( defined $sth->execute() ) ? OK : FORBIDDEN;
     }

DESCRIPTION
===========

   Apache::DBILogin allows authentication and authorization against a
multi-user database.

   It is intended to facilitate web-based transactions against a database
server as a particular database user. If you wish authenticate against a
passwd table instead, please see Edmund Mergl's Apache::AuthDBI module.

   Group authorization is handled by your Apache::DBILogin::is_member()
function which you must define if you enable the authz handler.

   The above example uses Oracle roles to assign group membership. A role
is a set of database privileges which can be assigned to users.
Unfortunately, roles are vendor specific. Under Oracle you can test
membership with "SET ROLE role_name" statement. You could also query the
data dictionary, DBA_ROLE_PRIVS, but under Oracle that requires explicit
privilege.  Documentation patches for other databases are welcome.

ENVIRONMENT
===========

   Applications may access the clear text password as well as the
data_source via the environment variables *HTTP_MODPERL_DBILOGIN_PASSWORD*
and *HTTP_MODPERL_DBILOGIN_DATA_SOURCE*.

     #!/usr/bin/perl -wT

     use strict;
     use CGI;
     use DBI;
     my $name = $ENV{REMOTE_USER};
     my $password = $ENV{HTTP_DBILOGIN_PASSWORD};
     my $data_source = $ENV{HTTP_DBILOGIN_DATA_SOURCE};
     my $dbh = DBI->connect($data_source, $name, $password)
     	or die "$DBI::err: $DBI::errstr\n";
     ...

SECURITY
========

   The database user's clear text passwd is made available in the server's
environment. Do you trust your developers?

BUGS
====

   Probably lots, I'm not the best programmer in the world.

NOTES
=====

   Feel free to email me with comments, suggestions, flames. Its the only
way I'll become a better programmer.

SEE ALSO
========

   mod_perl(1), Apache::DBI(3), and Apache::AuthDBI(3)

AUTHOR
======

   John Groenveld <groenveld@acm.org>

Hook Devel::DProf into mod_perl
*******************************

NAME
====

   Apache::DProf - Hook Devel::DProf into mod_perl

SYNOPSIS
========

     #in httpd.conf
     PerlModule Apache::DProf

DESCRIPTION
===========

   The Apache::DProf module will run a Devel::DProf profiler inside each
child server and write the *tmon.out* file in the directory
*$ServerRoot/logs/dprof/$$* when the child is shutdown.  Next time the
parent server pulls in Apache::DProf (via soft or hard restart), the
*$ServerRoot/logs/dprof* is cleaned out before new profiles are written
for the new children.

WHY
===

   It is possible to profile code run under mod_perl with only the
Devel::DProf module available on CPAN.  You must have apache version 1.3b3
or higher.  When the server is started, Devel::DProf installs an END block
to write the *tmon.out* file, which will be run when the server is
shutdown.  Here's how to start and stop a server with the profiler enabled:

     % setenv PERL5OPT -d:DProf
     % httpd -X -d `pwd` &
     ... make some requests to the server here ...
     % kill `cat logs/httpd.pid`
     % unsetenv PERL5OPT
     % dprofpp

   There are downsides to this approach:

   - Setting and unsetting PERL5OPT is a pain.

   - Server startup code will be profiled as well, which we are not
really concerned with, we're interested in runtime code, right?

   - It will not work unless the server is run in non-forking -X mode

   These limitations are due to the assumption by Devel::DProf that the
code you are profiling is running under a standard Perl binary (the one
you run from the command line).  `Devel::Dprof' relies on the Perl -d
switch for intialization of the Perl debugger, which happens inside
`perl_parse()' function call.  It also relies on Perl's special END
subroutines for termination when it writes the raw profile to *tmon.out*.
Under the standard command line Perl interpreter, these END blocks are run
when the `perl_run()' function is called.  Also, Devel::DProf will not
profile any code if it is inside a forked process.  Each time you run a
Perl script from the command line, the `perl_parse()' and `perl_run()'
functions are called, Devel::DProf works just fine this way.

   Under mod_perl, the `perl_parse()' and `perl_run()' functions are
called only once, when the parent server is starting.  Any END blocks
encountered during server startup or outside of Apache::Registry scripts
are suspended and run when the server is shutdown via apache's child exit
callback hook.  The parent server only runs Perl startup code, all request
time code is run in the forked child processes.  If you followed the
previous paragraph, you should be able to see, Devel::DProf does not fit
into the mod_perl model too well.  The Apache::DProf module exists to make
it fit without modifying the Devel::DProf module or Perl itself.

   The *Apache::DProf* module also requires apache version 1.3b3 or higher
and `PerlChildInitHandler' enabled.  It is configured simply by adding
this line to your httpd.conf file:

     PerlModule Apache::DProf

   When the Apache::DProf module is pulled in by the parent server, it
will push a `PerlChildInitHandler' via the Apache push_handlers method.
When a child server is starting the `Apache::DProf::handler' subroutine
will called.  This handler will create a directory `dprof/$$' relative to
*ServerRoot* where Devel::DProf will create it's *tmon.out* file.  Then,
the handler will initialize the Perl debugger and pull in Devel::DProf who
will then install it's hooks into the debugger and start it's profile
timer.  The END subroutine installed by Devel::DProf will be run when the
child server is shutdown and the *$ServerRoot/dprof/$$/tmon.out* file will
be generated and ready for dprofpp.

AUTHOR
======

   Doug MacEachern

SEE ALSO
========

   Devel::DProf(3), Apache::DB(3), mod_perl(3), Apache(3)

Utilities for debugging embedded perl code
******************************************

NAME
====

   Apache::Debug - Utilities for debugging embedded perl code

SYNOPSIS
========

     use Apache::Debug ();

     Apache::Debug::dump($r, SERVER_ERROR, "Uh Oh!");

DESCRIPTION
===========

   This module sends what may be helpful debugging info to the client
rather that the error log.

Debug Apache::DBI modules
*************************

NAME
====

   Apache::DebugDBI - Debug Apache::DBI modules

SYNOPSIS
========

     # Configuration in httpd.conf or srm.conf:

     PerlModule Apache::DebugDBI # this comes after all other Apache modules

DESCRIPTION
===========

   This module turns on debugging output in the Apache::DBI modules.

AUTHORS
=======

   Apache::DebugDBI by Edmund Mergl <E.Mergl@bawue.de>

COPYRIGHT
=========

   The Apache::DebugDBI module is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

log various bits of per-request data
************************************

NAME
====

   Apache::DebugInfo - log various bits of per-request data

SYNOPSIS
========

   There are two ways to use this module...

     1) using Apache::DebugInfo to control debugging automatically

     httpd.conf:

     PerlInitHandler Apache::DebugInfo
     PerlSetVar      DebugInfo On

     PerlSetVar      DebugPID On
     PerlSetVar      DebugHeadersIn On
     PerlSetVar      DebugDirConfig On
     PerlSetVar      DebugHeadersOut On
     PerlSetVar      DebugNotes On
     PerlSetVar      DebugPNotes On
     PerlSetVar      DebugGetHandlers On
     PerlSetVar      DebugTimestamp On
     PerlSetVar      DebugMarkPhases On

     PerlSetVar      DebugFile     "/path/to/debug_log"
     PerlSetVar      DebugIPList   "1.2.3.4 1.2.4."
     PerlSetVar      DebugTypeList ".html .cgi"

     2) using Apache::DebugInfo on the fly

     in handler or script:

     use Apache::DebugInfo;

     my $r = shift;

     my $debug = Apache::DebugInfo->new($r);

     # set the output file
     $debug->file("/path/to/debug_log");

     # get the ip addresses for which output is enabled
     my $ip_list = $debug->ip;

     # dump $r->headers_in right now
     $debug->headers_in;

     # log $r->headers_out after the response goes to the client
     $debug->headers_in('PerlCleanupHandler');

     # log all the $r->pnotes at Fixup and at Cleanup
     $debug->pnotes('PerlCleanupHandler','PerlFixupHandler');

DESCRIPTION
===========

   Apache::DebugInfo gives the programmer the ability to monitor various
bits of per-request data.

   You can enable Apache::DebugInfo as a PerlInitHandler, in which case it
chooses what request phase to display the appropriate data.  The output of
data can be controlled by setting various variables to On:

     DebugInfo          - enable Apache::DebugInfo handler

     DebugPID           - dumps apache child pid during request init
     DebugHeadersIn     - dumps request headers_in during request init
     DebugDirConfig     - dumps PerlSetVar and PerlAddVar during request init
     DebugGetHandlers   - dumps enabled request handlers during init

     DebugHeadersOut    - dumps request headers_out during request cleanup
     DebugNotes         - dumps request notes during request cleanup
     DebugPNotes        - dumps request pnotes during request cleanup

     DebugTimestamp     - prints localtime at the start of each request
     DebugMarkPhases    - prints the name of the request phase when the
                          phase is entered, prior to any other handlers

   Alternatively, you can control output activity on the fly by calling
Apache::DebugInfo methods directly (see METHODS below).

   Additionally, the following optional variables hold special arguments:

     DebugFile          - absolute path of file that will store the info
                          don't forget to make the file writable by
                          whichever user Apache runs as (likely nobody)
                          defaults to STDERR (which is likely error_log)

     DebugIPList        - a space delimited list of IP address for which
                          debugging is enabled
                          this can be a partial IP - 1.2.3 will match
                          1.2.3.5 and 1.2.3.6
                          if absent, defaults to all remote ip addresses

     DebugTypeList      - a space delimited list of file extensions for
                          which debugging is enabled (.cgi, .html...)
                          if absent, defaults to all types

METHODS
=======

   Apache::DebugInfo provides an object oriented interface to allow you to
call the various methods from either a module, handler, or an
Apache::Registry script.

   Constructor:   new($r)        - create a new Apache::DebugInfo object
                requires a valid Apache request object

   Methods:   The following methods can be called without any arguments,
in which   case the associated data is output immediately.  Optionally,
each   can be called with a list (either explicitly or as an array) of
Perl*Handlers, which will log the data during the appropriate   phase:

     headers_in()   - display incoming HTTP headers

     headers_out()  - display outgoing HTTP headers

     notes()        - display strings set by $r->notes

     pnotes()       - display variables set by $r->pnotes

     pid()          - display the apache child process PID

     get_handlers() - display variables set by PerlSetVar and PerlAddVar

     dir_config()   - display the enabled handlers for this request

     timestamp()    - display the current system time

     mark_phases()  - display the phase before executing any other
                      handlers. if given the argument 'All',
                      mark_phases  will display the entry into all
                      phases after the current phase.  calling with
                      no arguments outputs the current phase
                      immediately.

     There are also the following methods available for manipulating
     the behavior of the above methods:

     file($file)    - get or set the output file
                      accepts an absolute filename as an argument
                      returns the output filehandle
                      defaults to, but overrides DebugFile above

     ip($list)      - get or set the ip list
                      accepts a space delimited list as an argument
                      defaults to, but overrides DebugIPList above

     type($list)    - get or set the file type list
                      accepts a space delimited list as an argument
                      defaults to, but overrides DebugTypeList above

NOTES
=====

   Setting DebugInfo to Off has no effect on the ability to make direct
method calls.

   Verbose debugging is enabled by setting the variable
$Apache::DebugInfo::DEBUG=1 to or greater.  To turn off all messages set
LogLevel above info.

   This is alpha software, and as such has not been tested on multiple
platforms or environments.  It requires PERL_INIT=1, PERL_CLEANUP=1,
PERL_LOG_API=1, PERL_FILE_API=1, PERL_STACKED_HANDLERS=1, and maybe other
hooks to function properly.

FEATURES/BUGS
=============

   Once a debug handler is added to a given request phase, it can no
longer be controlled by ip() or type(). file(), however, takes affect on
invocation.  This is because the matching is done when the Perl*Handler is
added to the stack, while the output file is used when the Perl*Handler is
actually executed.

   Calling Apache::DebugInfo methods with 'PerlHandler' as an argument has
been disabled - doing so gets your headers and script printed to the
browser, so I thought I'd save the unaware from potential pitfalls.

   Phase misspellings, like 'PelrInitHandler' pass through without
warning, in case you were wondering where your output went...

   The get_handlers and mark_phases methods are incomplete, mainly due to
oversights in the mod_perl API.  Currently (as of mod_perl 1.2401), they
cannot function properly on the following callbacks:   PerlInitHandler As
such, they have been disabled until forthcoming corrections to the API can
be implemented.  PerlHeaderParserHandlers and PerlPostRequestHandlers
function normally.

   The output uri is whatever the uri was when new() was called (either on
the fly or in Apache::DebugInfo::handler).  Thus if the uri has undergone
translation since the new() call the original, not the new, uri will be
output.  This feature can be easily remedied, but having a changing uri in
the output may be confusing when debugging.  Future behavior will be
influenced by user feedback.

SEE ALSO
========

   perl(1), mod_perl(1), Apache(3)

AUTHOR
======

   Geoffrey Young <geoff@cpan.org>

COPYRIGHT
=========

   Copyright (c) 2000, Geoffrey Young.  All rights reserved.

   This module is free software.  It may be used, redistributed and/or
modified under the same terms as Perl itself.

call PerlHandlers with the ease of Registry scripts
***************************************************

NAME
====

   Apache::Dispatch - call PerlHandlers with the ease of Registry scripts

SYNOPSIS
========

   httpd.conf:

     PerlModule Apache::Dispatch
     PerlModule Bar

     DispatchExtras Pre Post Error
     DispatchStat On
     DispatchISA "My::Utils"
     DispatchAUTOLOAD Off

     <Location /Foo>
       SetHandler perl-script
       PerlHandler Apache::Dispatch

     DispatchPrefix Bar
     DispatchFilter Off
       </Location>

DESCRIPTION
===========

   Apache::Dispatch translates $r->uri into a class and method and runs it
as a PerlHandler.  Basically, this allows you to call PerlHandlers as you
would Regsitry scripts without having to load your httpd.conf with a
slurry of <Location> tags.

EXAMPLE
=======

     in httpd.conf

     PerlModule Apache::Dispatch
     PerlModule Bar

     <Location /Foo>
       SetHandler perl-script
       PerlHandler Apache::Dispatch

     DispatchPrefix Bar
         </Location>

     in browser:
       http://localhost/Foo/baz

     the results are the same as if your httpd.conf looked like:
       <Location /Foo>
         SetHandler perl-script
         PerlHandler Bar->dispatch_baz
       </Location>

   but with the additional security of protecting the class name from the
browser and keeping the method name from being called directly.  Because
any class under the Bar:: hierarchy can be called, one <Location>
directive is able to handle all the methods of Bar, Bar::Baz, etc...

CONFIGURATION DIRECTIVES
========================

     DispatchPrefix
       The base class to be substituted for the $r->location part of the
       uri.

     DispatchLocation
       Using Apache::Dispatch from a <Directory> directive, either
       directly or from a .htaccess file, will _require_ the use of
       DispatchLocation, which defines the starting location from which
       Apache::Dispatch will start class->method() translation.
       For example:

     httpd.conf
       DocumentRoot /usr/local/apache/htdocs
       <Directory /usr/local/apache/htdocs/>
         ...
       <Directory>

     .htaccess (in /usr/local/apache/htdocs/Foo)
        SetHandler perl-script
        PerlHandler Apache::Dispatch
        DispatchPrefix Baz
        DispatchLocation /Foo

     This allows a request to /Foo/Bar/biff to properly map to
     Baz::Bar->biff().

     While intended specifically for <Directory> configurations, one
     could use DispatchLocation to further obscure uri translations
     within <Location> sections as well by changing the part of
     the uri that is substitued with your module.

     DispatchExtras
       An optional list of extra processing to enable per-request.  If
       the main handler is not a valid method call, the request is
       declined prior to the execution of any of the extra methods.

     Pre   - eval()s Foo->pre_dispatch($r) prior to dispatching the
             uri.  The $@ of the eval is not checked in any way.

     Post  - eval()s Foo->post_dispatch($r) after dispatching the
             uri.  The $@ of the eval is not checked in any way.

     Error - If the main handler returns other than OK then
             Foo->error_dispatch($r, $@) is called and return status
             of it is returned instead.  Unlike the pre and post
             processing routines above, error_dispatch is not wrapped
             in an eval, so if it dies, the Apache::Dispatch dies,
             and Apache will process the error using ErrorDocument,
             custom_response(), etc.
             With error_dispatch() disabled, the return status of the
             the main handler is returned to the client.

     DispatchRequire
       An optional directive that enables require()ing of the module that
       is the result of the uri to class->method translation.  This allows
       your configuration to be a bit more dynamic, but also decreases
       security somewhat.  And don't forget that you really should be
       pre-loading frequently used modules in the parent process to reduce
       overhead - DispatchRequire is a directive of conveinence.

     On    - require() the module

     Off   - Do not require() the module (Default)

     DispatchStat
       An optional directive that enables reloading of the module that is
       the result of the uri to class->method translation, similar to
       Apache::Registry, Apache::Reload, or Apache::StatINC.

     On    - Test the called package for modification and reload on
             change

     Off   - Do not test or reload the package (Default)

     ISA   - Test the called package, and all other packages in the
             called package's @ISA, and reload on change

     DispatchAUTOLOAD
       An optional directive that enables unknown methods to use
       AutoLoader.  It may be applied on a per-server or per-location
       basis and defaults to Off.  Please see the special section on
       AUTOLOAD below.

     On    - Allow for methods to be defined in AUTOLOAD method

     Off   - Turn off search for AUTOLOAD method (Default)

       DispatchISA
         An optional list of parent classes you want your dispatched class
         to inherit from.

     DispatchFilter
       If you have Apache::Filter 1.013 or above installed, you can take
       advantage of other Apache::Filter aware modules.  Please see the
       section on FILTERING below.  In keeping with Apache::Filter
       standards, PerlSetVar Filter has the same effect as DispatchFilter
       but with lower precedence.

     On    - make the output of your module Apache::Filter aware

     Off   - do not use Apache::Filter (Default)

SPECIAL CODING GUIDELINES
=========================

   Migrating to Apache::Dispatch is relatively painless - it requires only
a few minor code changes.  The good news is that once you adapt code to
work with Dispatch, it can be used as a conventional mod_perl method
handler, requiring only a few considerations.  Below are a few things that
require attention.

   In the interests of security, all handler methods must be prefixed with
'dispatch_', which is added to the uri behind the scenes.  Unlike ordinary
mod_perl handlers, for Apache::Dispatch there is no default method (with a
tiny exception - see NOTES below).

   Apache::Dispatch uses object oriented calls behind the scenes.  This
means that you either need to account for your handler to be called as a
method handler, such as

     sub dispatch_bar {
       my $self  = shift;  # your class
       my $r     = shift;
     }

   or get the Apache request object directly via

     sub dispatch_bar {
       my $r     = Apache->request;
     }

   If you want to use the handler unmodified outside of Apache::Dispatch,
you must do three things:

     prototype your handler:

     sub dispatch_baz ($$) {
       my $self  = shift;
       my $r     = shift;
     }

     change your httpd.conf entry:

     <Location /Foo>
       SetHandler perl-script
       PerlHandler Bar->dispatch_baz
     </Location>

     pre-load your module:
       PerlModule Bar
         or
       PerlRequire startup.pl
       # where startup.pl contains
       # use Bar;

   That's it - now the handler can be swapped in and out of Dispatch
without further modification.  See the Eagle book on method handlers for
more details.

FILTERING
=========

   Apache::Dispatch provides for output filtering using Apache::Filter
1.013 and above.

     <Location /Foo>
       SetHandler perl-script
       PerlHandler Apache::Dispatch Apache::Compress

     DispatchPrefix Bar
     DispatchFilter On
       </Location>

   Your handler need do nothing special to make its output the start of
the chain - Apache::Dispatch registers itself with Apache::Filter and
hides the task from your handler.  Thus, any dispatched handler is
automatically Apache::Filter ready without the need for additional code.

   The only caveat is that you must use the request object that is passed
to the handler and not get it directly using Apache->request.

AUTOLOAD
========

   Support for AUTOLOAD has been made optional, but requires special care.
Please take the time to read the camel book on using AUTOLOAD with can()
and subroutine declarations (3rd ed pp326-329).

   Basically, you declare the methods you want AUTOLOAD to capture by name
at the top of your script.  This is necessary because can() will return
true if your class (or any parent class) contains an AUTOLOAD method, but
$AUTOLOAD will only be populated for declared method calls.  Hence,
without a declaration you won't be able to get at the name of the method
you want to AUTOLOAD.

   DispatchISA introduced some convenience, but some headaches as well -
if you inherit from a class that uses AutoLoader then ALL method calls are
true.  And as just explained, AUTOLOAD() will not know what the called
method was.  This may represent a problem if you aren't aware that, say,
CGI.pm uses AutoLoader and spend a few hours trying to figure out why all
of a sudden every URL under Dispatch is bombing.

   If you decide to use DispatchISA it is HIGHLY SUGGESTED that you do so
with DispatchAUTOLOAD Off (which is the default behavior).

NOTES
=====

   If you define a dispatch_index() method calls to /Foo will default to
it.  Unfortunately, this implicit translation only happens at the highest
level - calls to /Foo/Bar will translate to Foo->Bar() (that is, unless
Foo::Bar is your DispatchPrefix, in which case it will work but
/Foo/Bar/Baz will not, etc).  Explicit calls to /Foo/index follow the
normal dispatch rules.

   If the uri can be dispatched but contains anything other than
[a-zA-Z0-9_/-] Apache::Dispatch declines to handle the request.

   Like everything in perl, the package names are case sensitive.

   Warnings have been left on, so if you set an invalid class with
DispatchISA you will see a message like:   Can't locate package Foo::Bar
for @Bar::Baz::ISA at   .../Apache/Dispatch.pm line 277.

   Verbose debugging is enabled by setting $Apache::Dispatch::DEBUG=1.
Very verbose debugging is enabled at 2.  To turn off all debug information
set your Apache LogLevel directive above info level.

   This is alpha software, and as such has not been tested on multiple
platforms or environments for security, stability or other concerns.  It
requires PERL_DIRECTIVE_HANDLERS=1, PERL_LOG_API=1, PERL_HANDLER=1, and
maybe other hooks to function properly.

FEATURES/BUGS
=============

   If a module fails reload under DispatchStat, Apache::Dispatch declines
the request.  This might change to SERVER_ERROR in the future...

SEE ALSO
========

   perl(1), mod_perl(1), Apache(3), Apache::Filter(3), Apache::Reload(3),
Apache::StatINC(3)

AUTHOR
======

   Geoffrey Young <geoff@cpan.org>

COPYRIGHT
=========

   Copyright 2001 Geoffrey Young - all rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Watch HTTP transaction via headers
**********************************

NAME
====

   Apache::DumpHeaders - Watch HTTP transaction via headers

SYNOPSIS
========

     #httpd.conf or some such
     PerlLogHandler  Apache::DumpHeaders
     PerlSetVar      DumpHeaders_File -
     PerlSetVar      DumpHeaders_IP "1.2.3.4 1.2.3.5"
     #PerlSetVar     DumpHeaders_Conditional 1
     #PerlSetVar     DumpHeaders_Percent 5

DESCRIPTION
===========

   This module is used to watch an HTTP transaction, looking at the client
and servers headers.

   With Apache::ProxyPassThru configured, you are able to watch your
browser talk to any server besides the one with this module living inside.

PARAMETERS
==========

   This module is configured with PerlSetVar's. All the "only dump if ..."
options are "AND" conditions. If not all of them matches we won't dump the
headers.

   If you need some more complicated logic you could use the
DumpHeaders_Conditional parameter alone and have another module do the
"dump or dump not" logic with r->notes("DumpHeaders").

DumpHeaders_File
----------------

   Required parameter to specify which file you want to dump the headers
to.

DumpHeaders_IP
--------------

   Optional parameter to specify which one or more IP addresses you want
to dump traffic from.

DumpHeaders_Conditional
-----------------------

   If this is set to a true value we'll only dump the headers if another
module have set r->notes("DumpHeaders") to a true value.

DumpHeaders_Percent
-------------------

   If this is set, we'll only dump the specified percent of the requests.

SUPPORT
=======

   The latest version of this module can be found at CPAN and at `http:'
in this node. Send questions and suggestions to the modperl mailinglist
(see `http:' in this node for information) or directly to the author (see
below).

SEE ALSO
========

   mod_perl(3), Apache(3), Apache::ProxyPassThru(3)

AUTHOR
======

   Ask Bjoern Hansen <ask@develooper.com>.

   Originally by Doug MacEachern.

process embedded perl in HTML in the OutputChain
************************************************

NAME
====

   Apache::EmbperlChain - process embedded perl in HTML in the OutputChain

SYNOPSIS
========

   In the configuration of your apache add something like

     PerlModule Apache::EmbperlChain
     <Files *.html>
     SetHandler perl-script
     PerlHandler Apache::OutputChain Apache::EmbperlChain Apache::PassFile
     </Files>

   This will cause all html files to be processed by Embperl.

   Now this:

     <Location /foo>
     SetHandler perl-script
     PerlHandler Apache::OutputChain Apache::GzipChain Apache::EmbperlChain My::OwnHandler
     </Location>

   Any request in the /foo subtree will be processed by My::OwnHandler.
The output of that will then be filtered by EmbperlChain, which will
process any embedded Perl commands. That output will then be compressed by
GzipChain, which will deliver compressed content to the client.

STATUS
======

   This is beta software, and the output chain mechanism itself is also
beta.

   You currently cannot mix perl's own print statements that print to
STDOUT and the print or `write_client' methods in Apache.pm. If you do
that, you will very likely encounter empty documents and probably core
dumps too. Since Apache::OutputChain uses perl's print statement, you'll
want to stick to that too.

DESCRIPTION
===========

   This module calls HTML::Embperl to process any output from another perl
handler.

   The module seems to work without influencing the other handlers.

   EmbperlChain processes every single buffer content it receives via the
output chain separately. Therefore care must be taken to print valid
embedded perl chunks in the content handler. It is recommended that you
use as few print statements as possible in conjunction with the
EmbperlChain. The Apache::PassFile module is an example of an efficient
file reader for this purpose.

   When EmbperlChain is the last handler in the chain, the following
optimization is performed: all input from the producer is buffered in
memory, and fed to HTML::Embperl in one call at the end of request. The
resulting output is sent directly to the browser by HTML::Embperl, for an
additional performance gain.

   If the 'Last-Modified' HTTP header is set (by an earlier handler in the
chain), EmbperlChain uses it to enable Embperl's caching mechanism.

PREREQUISITES
=============

   HTML::Embperl, Apache::OutputChain

AUTHOR
======

   Eric Cholet, cholet@logilune.com

   Documentation shamelessly copied from Apache::GzipChain by Andreas
Koenig.

SEE ALSO
========

   Apache::GzipChain, Apache::SSIChain

Utils for Apache:C/Perl glue
****************************

NAME
====

   Apache::ExtUtils - Utils for Apache:C/Perl glue

SYNOPSIS
========

     use Apache::ExtUtils ();

DESCRIPTION
===========

   Under constuction, all here subject to change.

AUTHOR
======

   Doug MacEachern

fake request object for debugging
*********************************

NAME
====

   Apache::FakeRequest - fake request object for debugging

SYNOPSIS
========

     use Apache::FakeRequest;
     my $request = Apache::FakeRequest->new(method_name => 'value', ...);

DESCRIPTION
===========

   *Apache::FakeRequest* is used to set up an empty Apache request object
that can be used for debugging.  The *Apache::FakeRequest* methods just
set internal variables of the same name as the method and return the value
of the internal variables.  Initial values for methods can be specified
when the object is created.  The print method prints to STDOUT.

   Subroutines for Apache constants are also defined so that using
*Apache::Constants* while debugging works, although the values of the
constants are hard-coded rather than extracted from the Apache source code.

     #!/usr/bin/perl

     use Apache::FakeRequest ();
     use mymodule ();

     my $request = Apache::FakeRequest->new('get_remote_host'=>'foobar.com');
     mymodule::handler($request);

AUTHORS
=======

   Doug MacEachern, with contributions from Andrew Ford
<A.Ford@ford-mason.co.uk>.

advanced functions for manipulating files at the server side
************************************************************

NAME
====

   Apache::File - advanced functions for manipulating files at the server
side

SYNOPSIS
========

     use Apache::File ();

DESCRIPTION
===========

   Apache::File does two things: it provides an object-oriented interface
to filehandles similar to Perl's standard IO::File class. While the
Apache::File module does not provide all the functionality of IO::File,
its methods are approximately twice as fast as the equivalent IO::File
methods. Secondly, when you use Apache::File, it adds several new methods
to the Apache class which provide support for handling files under the
HTTP/1.1 protocol.

Apache::File methods
====================

new()
     This method creates a new filehandle, returning the filehandle object
     on success, undef on failure. If an additional argument is given, it
     will be passed to the open() method automatically.

          use Apache::File ();
          my $fh = Apache::File->new;

          my $fh = Apache::File->new($filename) or die "Can't open $filename $!";

open()
     Given an Apache::File object previously created with new(), this
     method opens a file and associates it with the object. The open()
     method accepts the same types of arguments as the standard Perl open()
     function, including support for file modes.

          $fh->open($filename);

          $fh->open(">$out_file");

          $fh->open("|$program");

close()
     The close() method is equivalent to the Perl builtin close function,
     returns true upon success, false upon failure.

          $fh->close or die "Can't close $filename $!";

tmpfile()
     The tmpfile() method is responsible for opening up a unique temporary
     file. It is similar to the tmpnam() function in the POSIX module, but
     doesn't come with all the memory overhead that loading POSIX does. It
     will choose a suitable temporary directory (which must be writable by
     the Web server process). It then generates a series of filenames using
     the current process ID and the $TMPNAM package global. Once a unique
     name is found, it is opened for writing, using flags that will cause
     the file to be created only if it does not already exist. This
     prevents race conditions in which the function finds what seems to be
     an unused name, but someone else claims the same name before it can be
     created.

     As an added bonus, tmpfile() calls the register_cleanup() method
     behind the scenes to make sure the file is unlinked after the
     transaction is finished.

     Called in a list context, tmpfile() returns the temporary file name
     and a filehandle opened for reading and writing. In a scalar context
     only the filehandle is returned.

          my($tmpnam, $fh) = Apache::File->tmpfile;

          my $fh = Apache::File->tmpfile;

Apache Methods added by Apache::File
====================================

   When a handler pulls in Apache::File, the module adds a number of new
methods to the Apache request object. These methods are generally of
interest to handlers that wish to serve static files from disk or memory
using the features of the HTTP/1.1 protocol that provide increased
performance through client-side document caching.

$r->discard_request_body()
     This method tests for the existence of a request body and if present,
     simply throws away the data. This discarding is especially important
     when persistent connections are being used, so that the request body
     will not be attached to the next request. If the request is malformed,
     an error code will be returned, which the module handler should
     propagate back to Apache.

          if ((my $rc = $r->discard_request_body) != OK) {
             return $rc;
          }

$r->meets_conditions()
     In the interest of HTTP/1.1 compliance, the meets_conditions() method
     is used to implement "conditional GET" rules. These rules include
     inspection of client headers, including If-Modified-Since,
     If-Unmodified-Since, If-Match and If-None-Match.

     As far as Apache modules are concerned, they need only check the
     return value of this method before sending a request body. If the
     return value is anything other than OK, the module should return from
     the handler with that value. A common return value other than OK is
     HTTP_NOT_MODIFIED, which is sent when the document is already cached
     on the client side, and has not changed since it was cached.

          if((my $rc = $r->meets_conditions) != OK) {
             return $rc;
          }
          #else ... go and send the response body ...

$r->mtime()
     This method returns the last modified time of the requested file,
     expressed as seconds since the epoch. The last modified time may also
     be changed using this method, although update_mtime() method is better
     suited to this purpose.

          my $date_string = localtime $r->mtime;

$r->set_content_length()
     This method sets the outgoing Content-length header based on its
     argument, which should be expressed in byte units. If no argument is
     specified, the method will use the size returned by $r->filename. This
     method is a bit faster and more concise than setting Content-length in
     the headers_out table yourself.

          $r->set_content_length;
          $r->set_content_length(-s $r->finfo); #same as above
          $r->set_content_length(-s $filename);

$r->set_etag()
     This method is used to set the outgoing ETag header corresponding to
     the requested file. ETag is an opaque string that identifies the
     currrent version of the file and changes whenever the file is
     modified. This string is tested by the meets_conditions() method if
     the client provide an If-Match or If-None-Match header.

          $r->set_etag;

$r->set_last_modified()
     This method is used to set the outgoing Last-Modified header from the
     value returned by $r->mtime. The method checks that the specified time
     is not in the future. In addition, using set_last_modified() is faster
     and more concise than setting Last-Modified in the headers_out table
     yourself.

     You may provide an optional time argument, in which case the method
     will first call the update_mtime() to set the file's last modification
     date. It will then set the outgoing Last-Modified header as before.

          $r->update_mtime((stat $r->finfo)[9]);
          $r->set_last_modified;
          $r->set_last_modified((stat $r->finfo)[9]); #same as the two lines above

$r->update_mtime()
     Rather than setting the request record mtime field directly, you can
     use the update_mtime() method to change the value of this field. It
     will only be updated if the new time is more recent than the current
     mtime. If no time argument is present, the default is the last
     modified time of $r->filename.

          $r->update_mtime;
          $r->update_mtime((stat $r->finfo)[9]); #same as above
          $r->update_mtime(time);

Alter the output of previous handlers
*************************************

NAME
====

   Apache::Filter - Alter the output of previous handlers

SYNOPSIS
========

     #### In httpd.conf:
     PerlModule Apache::Filter
     # That's it - this isn't a handler.

     <Files ~ "*\.blah">
      SetHandler perl-script
      PerlSetVar Filter On
      PerlHandler Filter1 Filter2 Filter3
     </Files>

     #### In Filter1, Filter2, and Filter3:
     $r = $r->filter_register();  # Required
     my $fh = $r->filter_input(); # Optional (you might not need the input FH)
     while (<$fh>) {
       s/ something / something else /;
       print;
     }

     #### or, alternatively:
     $r = $r->filter_register();
     my ($fh, $status) = $r->filter_input(); # Get status information
     return $status unless $status == OK;
     while (<$fh>) {
       s/ something / something else /;
       print;
     }

DESCRIPTION
===========

   In basic operation, each of the handlers Filter1, Filter2, and Filter3
will make a call to $r->filter_input(), which will return a filehandle.
For Filter1, the filehandle points to the requested file.  For Filter2,
the filehandle contains whatever Filter1 wrote to STDOUT.  For Filter3, it
contains whatever Filter3 wrote to STDOUT.  The output of Filter3 goes
directly to the browser.

   Note that the modules Filter1, Filter2, and Filter3 are listed in
forward order, in contrast to the reverse-order listing of
Apache::OutputChain.

   When you've got this module, you can use the same handler both as a
stand-alone handler, and as an element in a chain.  Just make sure that
whenever you're chaining, all the handlers in the chain are
"Filter-aware," i.e. they each call $r->filter_register() exactly once,
before they start printing to STDOUT.  There should be almost no overhead
for doing this when there's only one element in the chain.

   Currently the following public modules are Filter-aware.  Please tell
me of others you know about.

     Apache::Registry (using Apache::RegistryFilter, included here)
     Apache::SSI
     Apache::ASP
     HTML::Mason
     Apache::SimpleReplace

METHODS
=======

   Apache::Filter is a subclass of Apache, so all Apache methods are
available.

   This module doesn't create an Apache handler class of its own - rather,
it adds some methods to the Apache:: class.  Thus, it's really a mix-in
package that just adds functionality to the $r request object.

   * $r = $r->filter_register()

     Every Filter-aware module must call this method exactly once, so that
     Apache::filter can properly rotate its filters from previous handlers,
     and so it can know when the output should eventually go to the
     browser.

   * $r->filter_input()

     This method will give you a filehandle that contains either the file
     requested by the user ($r->filename), or the output of a previous
     filter.  If called in a scalar context, that filehandle is all you'll
     get back.  If called in a list context, you'll also get an Apache
     status code (OK, NOT_FOUND, or FORBIDDEN) that tells you whether
     $r->filename was successfully found and opened.  If it was not, the
     filehandle returned will be undef.

   * $r->changed_since($time)

     Returns true or false based on whether the current input seems like it
     has changed since `$time'.  Currently the criteria to figure this out
     is this: if the file pointed to by `$r->finfo' hasn't changed since
     the time given, and if all previous filters in the chain are
     deterministic (see below), then we return false.  Otherwise we return
     true.

     This method is meant to be useful in implementing caching schemes.

     A caution: always call the `changed_since()' and `deterministic()'
     methods *AFTER* the `filter_register()' method.  This is because
     Apache::Filter uses a crude counting method to figure out which
     handler in the chain is currently executing, and calling these
     routines out of order messes up the counting.

   * $r->deterministic(1|0);

     As of version 0.07, the concept of a "deterministic" filter is
     supported.  A deterministic filter is one whose output is entirely
     determined by the contents of its input file (whether the
     $r->filename file or the output of another filter), and doesn't
     depend at all on outside factors.  For example, a filter that
     translates all its output to upper-case is deterministic, but a
     filter that adds a date stamp to a page, or looks things up in a
     database which may vary over time, is not.

     Why is this a big deal?  Let's say you have the following setup:

          <Files ~ "\.boffo$">
           SetHandler perl-script
           PerlSetVar Filter On
           PerlHandler Apache::FormatNumbers Apache::DoBigCalculation
           # The above are fake modules, you get the idea
          </Files>

     Suppose the FormatNumbers module is deterministic, and the
     DoBigCalculation module takes a long time to run.  The
     DoBigCalculation module can now cache its results, so that when an
     input file is unchanged on disk, its results will remain known when
     passed through the FormatNumbers module, and the DoBigCalculation
     module will be able to used cached results from a previous run.

     The guts of the modules would look something like this:

          sub Apache::FormatNumbers::handler {
             my $r = shift;
             $r->content_type("text/html");
             my ($fh, $status) = $r->filter_input();
             return $status unless $status == OK;
             $r->deterministic(1); # Set to true; default is false

             # ... do some formatting, print to STDOUT
             return OK;
          }

          sub Apache::DoBigCalculation::handler {
             my $r = shift;
             $r->content_type("text/html");
             my ($fh, $status) = $r->filter_input();
             return $status unless $status == OK;

             # This module implements a caching scheme by using the
             # %cache_time and %cache_content hashes.
             my $time = $cache_time{$r->filename};
             my $output;
             if ($r->changed_since($time)) {
                 # Read from <$fh>, perform a big calculation on it, and print to STDOUT
             } else {
                 print $cache_content{$r->filename};
             }

             return OK;
          }

     A caution: always call the `changed_since()' and `deterministic()'
     methods *AFTER* the `filter_register()' method.  This is because
     Apache::Filter uses a crude counting method to figure out which
     handler in the chain is currently executing, and calling these
     routines out of order messes up the counting.

HEADERS
=======

   In previous releases of this module, it was dangerous to call
$r->send_http_header(), because a previous/postvious filter might also try
to send headers, and then you'd have duplicate headers getting sent.  In
current releases you can simply send the headers.  If the current filter
is the last filter, the headers will be sent as usual, and otherwise
send_http_header() is a no-op.

NOTES
=====

   You'll notice in the SYNOPSIS that I say `"PerlSetVar Filter On"'.  That
information isn't actually used by this module, it's used by modules which
are themselves filters (like Apache::SSI).  I hereby suggest that filtering
modules use this parameter, using it as the switch to detect whether they
should call $r->filter_register.  However, it's often not necessary -
there is very little overhead in simply calling $r->filter_register even
when you don't need to do any filtering, and $r->filter_input can be a
handy way of opening the $r->filename file.

   VERY IMPORTANT: if one handler in a stacked handler chain uses
`Apache::Filter', then THEY ALL MUST USE IT.  This means they all must
call $r->filter_register exactly once.  Otherwise `Apache::Filter' couldn't
capture the output of the handlers properly, and it wouldn't know when to
release the output to the browser.

   The output of each filter (except the last) is accumulated in memory
before it's passed to the next filter, so memory requirements are large
for large pages.  Apache::OutputChain only needs to keep one item from
print()'s argument list in memory at a time, so it doesn't have this
problem, but there are others (each chunk is filtered independently, so
content spanning several chunks won't be properly parsed).  In future
versions I might find a way around this, or cache large pages to disk so
memory requirements don't get out of hand.  We'll see whether it's a
problem.

   A couple examples of filters are provided with this distribution in the
t/ subdirectory: UC.pm converts all its input to upper-case, and Reverse.pm
prints the lines of its input reversed.

   Finally, a caveat: in version 0.09 I started explicitly setting the
Content-Length to undef.  This prevents early filters from incorrectly
setting the content length, which will almost certainly be wrong if there
are any filters after it.  This means that if you write any filters which
set the content length, they should do it after the $r->filter_register
call.

TO DO
=====

   Add a buffered mode to the final output, so that we can send a proper
Content-Length header. [gozer@hbesoftware.com (Philippe M. Chiasson)]

BUGS
====

   This uses some funny stuff to figure out when the currently executing
handler is the last handler in the chain.  As a result, code that
manipulates the handler list at runtime (using push_handlers and the like)
might produce mayhem.  Poke around a bit in the code before you try
anything.  Let me know if you have a better idea.

   As of 0.07, Apache::Filter will automatically return DECLINED when
$r->filename points to a directory.  This is just because in most cases
this is what you want to do (so that mod_dir can take care of the
request), and because figuring out the "right" way to handle directories
seems pretty tough - the right way would allow a directory indexing
handler to be a filter, which isn't possible now.  Also, you can't
properly pass control to a non-mod_perl indexer like mod_autoindex.
Suggestions are welcome.

   I haven't considered what will happen if you use this and you haven't
turned on PERL_STACKED_HANDLERS.  So don't do it.

AUTHOR
======

   Ken Williams (ken@forum.swarthmore.edu)

COPYRIGHT
=========

   Copyright 1998,1999,2000 Ken Williams.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1).

Generate Graphs in an Apache handler.
*************************************

NAME
====

   Apache::GD::Graph - Generate Graphs in an Apache handler.

SYNOPSIS
========

   In httpd.conf:

     <Location /chart>
     SetHandler	perl-script
     PerlHandler	+Apache::GD::Graph
     # These are optional.
     #PerlSetVar	Expires		30	# days default.
     #PerlSetVar	CacheSize	5242880	# 5 megs default.
     #PerlSetVar	ImageType	png	# Default.
     # The default image type that graphs should be.
     # png is default, gif requires <= GD 1.19.
     # Any type supported by the installed version of GD will work.
     #
     # The next specifies the quality of generated JPEG images, best not to
     # specify this one and let GD figure it out.
     #PerlSetVar	JpegQuality	75 # 0 to 100
     # TTFFontPath tells GD::Text where to look for true type fonts. The
     # example here is the default value used.
     #PerlSetVar	TTFFontPath	/usr/ttfonts:/var/ttfonts:/usr/X11R6/lib/X11/fonts/ttf/:/usr/X11R6/lib/X11/fonts/truetype/:/usr/share/fonts/truetype
     </Location>

   Then send requests to:

     http://www.server.com/chart?type=lines&x_labels=[1st,2nd,3rd,4th,5th]&
     data1=[1,2,3,4,5]&data2=[6,7,8,9,10]&dclrs=[blue,yellow,green]>

   Options can also be sent as x-www-form-urlencoded data (ie., a form).
This works better for large data sets, and allows simple charting forms to
be set up. IE, for example, does not allow query strings larger than a
kilobyte.  Parameters in the query string take precedence over a form if
specified.

INSTALLATION
============

   Like any other CPAN module, if you are not familiar with CPAN modules,
see: http://www.cpan.org/doc/manual/html/pod/perlmodinstall.html

   MAKE SURE TO RESTART YOUR APACHE SERVER using `apachectl graceful' after
upgrading this or any other Apache Perl module.

DESCRIPTION
===========

   The primary purpose of this module is to allow a very easy to use,
lightweight and fast charting capability for static pages, dynamic pages
and CGI scripts, with the chart creation process abstracted and placed on
any server.

   For example, embedding a pie chart can be as simple as:

     <img src="http://www.some-server.com/chart?type=pie&
     x_labels=[greed,pride,wrath]&data1=[10,50,20]&dclrs=[green,purple,red]"
     alt="pie chart of a few deadly sins">
     <!-- Note that all of the above options are optional except for data1!  -->

   And it gets cached both server side, and along any proxies to the
client, and on the client's browser cache. Not to mention, chart
generation is very fast.

   Of course, more complex things will be better done directly in your own
Perl handlers, but this module allows a non-Perl environment to have
access to the capabilities of GD::Graph.

   Another solution is to use ASP scripting with Microsoft Excel, which of
course requires a Windows NT server and I have no idea how easy this is to
do, or how fast.

   There are also many other ways to connect programs with charting
capabilities, such as GNUPlot, or rrdtool to a web server. These may or
may not be faster/more featureful etc.

TIPS
====

   Most more complicated things depend on knowing the GD::Graph interface.

   Firstly, *make sure you are not using any spaces!* If you want to pass
a space in a parameter in a URL-encoded string, use `%20', in a form use a
+.

   Make sure to use `cache=0' or `PerlSetVar CacheSize 0' when debugging,
otherwise you will spend hours being very confused.

FONTS
=====

   GD::Graph has some options that take a font description, such as
title_font, legend_font, etc. (these map to the appropriate set_FOO
methods in GD::Graph, see that manpage). See the TTFFontPath variable
under SYNOPSIS for how to set the search path for fonts. MAKE SURE your
fonts are readable by the user the Apache server runs under, this is
usually "www-data" or "nobody". Otherwise your fonts will mysteriously
fail with no notice.

   Sizes can be specified by using a list with the name and size. For
example, if arial.ttf can be found somewhere in your TTFFontPath, you can
do:

     ...title_font=(arial.ttf,20)

   To get a title using font Arial, in 20 points.

   Note that GD::Text does not parse out the names of fonts and such, you
have to give it an actual filename, in the right case. So if using the
Microsoft Windows core fonts, Arial Bold would be `arialbd.ttf'. Here's an
example:

     http://server/chart?data1=[1,2,3,4,5]&title_font=(arialbd.ttf,20)&title=Just%20A%20Line

IMAGES
======

   You can place a logo in any corner of the graph using the logo,
`logo_resize' and `logo_position' options. See GD/Graph.
If you just want a background image that is resized to fit your graph, see
the background_image option herein.

TEXT/CAPTIONS
=============

   The following GD::Graph options control placing text on the graph:
title, x_label and y_label. See GD/Graph, for those and
related options. In addition, this modules allows you to use the captionN
option(s), to draw arbitrary strings on the graph. See below.

IMPLEMENTATION
==============

   This module is implemented as a simple Apache mod_perl handler that
generates and returns a png format graph (using Martien Verbruggen's
GD::Graph module) based on the arguments passed in via a query string. It
responds with the content-type "image/png" (or whatever is set via
`PerlSetVar ImageType'), and sends a Expires: header of 30 days (or
whatever is set via `PerlSetVar Expires', or expires in the query string,
in days) ahead.

   In addition, it keeps a server-side cache in the file system using
DeWitt Clinton's File::Cache module, whose size can be specified via
`PerlSetVar CacheSize' in bytes.

OPTIONS
=======

type
     Type of graph to generate, can be lines, bars, points, linespoints,
     area, mixed, pie. For a description of these, see `GD::Graph(3)' in
     this node. Can also be one of the 3d types if GD::Graph3d is
     installed, or anything else with prefix GD::Graph::.

width
     Width of graph in pixels, 400 by default.

height
     Height of graph in pixels, 300 by default.

expires
     Date of Expires header from now, in days. Same as `PerlSetVar
     Expires'.

image_type
     Same as `PerlSetVar ImageType'. "png" by default, but can be anything
     supported by GD.

     If not specified via this option or in the config file, the image
     type can also be deduced from a single value in the 'Accept' header
     of the request.

jpeg_quality
     Same as `PerlSetVar JpegQuality'. A number from 0 to 100 that
     determines the jpeg quality and the size. If not set at all, the GD
     library will determine the optimal setting. Changing this value
     doesn't seem to do much as far as line graphs go, but YMMV.

background_image
     Set an image as the background for the graph. You are responsible for
     choosing a sane image to go with your graph, the background should be
     either transparent or the same color you will use. This is the same
     as using the logo parameter with an image of the same size as the
     graph, except this option will resize the image if necessary, making
     it more convenient for this purpose. The file or URL can be of any
     type your copy of GD supports.

captionN
     Draws a character string using a TrueType font at an arbitrary
     location.  Takes an array of
     `($fgcolor,$fontname,$ptsize,$angle,$x,$y,$string)' where $fgcolor is
     the foreground color, $fontname is the name of a TTF font see `' in
     this node , $ptsize is the point size, $x and $y are the coordinates,
     and $string is the actual characters to draw.

     N is an integer from 1 onward, like for the dataN option. This lets
     you specify multiple strings to draw.

     This follows exactly the GD stringTTF method, see GD.

     Angle is in degrees, you will primarily use angle 0 for normal
     left-to-right text. $x and $y are pixel coordinates from the upper
     left corner. $fontname is the name of a true-type font that will be
     found in the font path (see FONTS).  Example:

          http://isis/chart?data1=[1,2,3,4,5]&caption1=(1,arial.ttf,9,0,30,30,Hello)

cache
     Boolean value which determines whether or not the image will get
     cached server-side (for client-side caching, use the "expires"
     parameter). It is true (1) by default. Setting `PerlSetVar CacheSize
     0' in the config file will achieve the same affect as `cache=0' in
     the query string.

to_file
     The graph will not be sent back, but instead saved to the file
     indicated on the server. Apache will need permission to write to that
     directory. The result will not be cached. This is basically the same
     as making an RPC call to a Perl process to make a graph and store it
     to a file.

no_axes
     This sets x_labels to an empty lists and sets y_number_format to "",
     effectively disabling axes labels.

   For the following, look at the plot method in `GD::Graph(3)' in this
node.

x_labels
     Labels used on the X axis, the first array given to the plot method of
     GD::Graph. If unspecified or undef, no labels will be drawn.

dataN
     Values to plot, where N is a number starting with 1. Can be given any
     number of times with N increasing.

   ALL OTHER OPTIONS are passed to the corresponding set_<option> method,
or the set(<option hash>) method using the following rules for the values:

undef
     Becomes a real undef.

[one,two,3]
     Becomes an array reference.

(one,two,3)
     This becomes a list, you can pass lists to set_SOMETHING methods of
     GD::Graph, if there is no corresponding set_ method, the list will be
     silently converted to an anonymous array and used in an ordinary
     option.

*{one,1,two,2}*
     Becomes a hash reference.

http://somewhere/file.png
     Is pulled into a file and the file name is passed to the respective
     option.  (Can be any scheme besides http:// that LWP::Simple
     supports.)

*[undef,something,undef] or {key,undef}*
     You can create an array or hash with undefs.

*['foo',bar] or 'baz' or {'key','value'}*
     Single and double quoted strings are supported, either as singleton
     values or inside arrays and hashes.

     DON'T USE SPACES, this is a common mistake. A space in a URL-encoded
     string is %20, or a + in a form.

     Nested structures are still not supported, maybe later.

AUTHOR
======

   Rafael Kitover (caelum@debian.org)

COPYRIGHT
=========

   This program is Copyright (c) 2000 by Rafael Kitover. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

ACKNOWLEDGEMENTS
================

   This module owes its existance, obviously, to the availability of the
wonderful GD::Graph module from Martien Verbruggen <mgjv@comdyn.com.au>.

   Thanks to my employer, Gradience, Inc., for allowing me to work on
projects as free software.

   Thanks to Vivek Khera (khera@kciLink.com) and Scott Holdren
<scott@monsterlabs.com> for the bug fixes.

BUGS
====

   Probably a few.

   We should probably just let people set up their own PerlFixupHandlers
for errors, but this makes it more difficult to set up. At least, it
should be an option.

TODO
====

   Boxed captions.  Variable mapping of x-labels to data points.  If
possible, a comprehensive test suite.  Make it faster?

SEE ALSO
========

   See Perl (perl.info), GD/Graph, GD,

Limit Apache httpd processes
****************************

NAME
====

   Apache::GTopLimit - Limit Apache httpd processes

SYNOPSIS
========

   This module allows you to kill off Apache httpd processes if they grow
too large or have too little of shared memory.  You can choose to set up
the process size limiter to check the process size on every request:

     # in your startup.pl:
     use Apache::GTopLimit;

     # Control the life based on memory size
     # in KB, so this is 10MB
     $Apache::GTopLimit::MAX_PROCESS_SIZE = 10000;

     # Control the life based on Shared memory size
     # in KB, so this is 4MB
     $Apache::GTopLimit::MIN_PROCESS_SHARED_SIZE = 4000;

     # watch what happens
     $Apache::GTopLimit::DEBUG = 1;

     # in your httpd.conf:
     PerlFixupHandler Apache::GTopLimit
     # you can set this up as any Perl*Handler that handles
     # part of the request, even the LogHandler will do.

   Or you can just check those requests that are likely to get big or
unshared.  This way of checking is also easier for those who are mostly
just running Apache::Registry scripts:

     # in your CGI:
     use Apache::GTopLimit;
       # Max Process Size in KB
     Apache::GTopLimit->set_max_size(10000);

   and/or

     use Apache::GTopLimit;
        # Min Shared process Size in KB
     Apache::GTopLimit->set_min_shared_size(4000);

   Since accessing the process info might add a little overhead, you may
want to only check the process size every N times.  To do so, put this in
your startup.pl or CGI:

     $Apache::GTopLimit::CHECK_EVERY_N_REQUESTS = 2;

   This will only check the process size every other time the process size
checker is called.

   Note: The *MAX_PROCESS_SIZE* and *MIN_PROCESS_SHARED_SIZE* are
standalone, and each will be checked if only set. So if you set both - the
process can be killed if it grows beyond the limit or its shared memory
goes below the limit.

DESCRIPTION
===========

   This module will run on platforms supported by *GTop.pm* a Perl
interface to libgtop (which in turn needs *libgtop* : See
http://home-of-linux.org/gnome/libgtop/ ).

   This module was written in response to questions on the mod_perl mailing
list on how to tell the httpd process to exit if:

   * its memory size goes beyond a specified limit

   * its shared memory size goes below a specified limit

Limiting memory size
--------------------

   Actually there are two big reasons your httpd children will grow.
First, it could have a bug that causes the process to increase in size
dramatically, until your system starts swapping.  Second, your process just
does stuff that requires a lot of memory, and the more different kinds of
requests your server handles, the larger the httpd processes grow over
time.

   This module will not really help you with the first problem.  For that
you should probably look into Apache::Resource or some other means of
setting a limit on the data size of your program.  BSD-ish systems have
setrlimit() which will croak your memory gobbling processes.  However it
is a little violent, terminating your process in mid-request.

   This module attempts to solve the second situation where your process
slowly grows over time.  The idea is to check the memory usage after every
request, and if it exceeds a threshold, exit gracefully.

   By using this module, you should be able to discontinue using the
Apache configuration directive *MaxRequestsPerChild*, although for some
folks, using both in combination does the job.  Personally, I just use the
technique shown in this module and set my *MaxRequestsPerChild* value to
6000.

Limiting shared memory size
---------------------------

   We want the reverse the above limit for a shared memory limitation and
kill the process when its hs too little of shared memory.

   When the same memory page is being shared between many processes, you
need less physical memory relative to the case where the each process will
have its own copy of the memory page.

   If your OS supports shared memory you will get a great benefit when you
deploy this feature. With mod_perl you enable it by preloading the modules
at the server startup. When you do that, each child uses the same memory
page as the parent does, after it forks. The memory pages get unshared
when a child modifies the page and it can no longer be shared, that's when
the page is being copied to the child's domain and then modified as it
pleased to. When this happens a child uses more real memory and less
shared.

   Because of Perl's nature memory pages get unshared pretty fast, when
the code is being executed and it's internal data is being modified.
That's why as the child gets older the size of the shared memory goes down.

   You can tune your server to kill off the child when its shared memory
is too low, but it demands a constant retuning of the configuration
directives if you do any heavy updates in the code the server executes.
This module allows you to save up the time to make this tuning and
retuning, by simply specifying the minimum size of the shared memory for
each process. And when it crosses the line, to kill it off.

AUTHOR
======

   Stas Bekman <sbekman@iname.com>:

   An almost complete rewrite of Apache::SizeLimit toward using GTop
module (based on crossplatfom glibtop). The moment glibtop will be ported
on all the platforms Apache::SizeLimit runs at (I think only Solaris is
missing) Apache::SizeLimit will become absolete.

   Doug Bagley wrote the original Apache::SizeLimit

CHANGES
=======

   See external file 'Changes'.

A Bloated Gateway Module
************************

NAME
====

   Apache::Gateway - A Bloated Gateway Module

SYNOPSIS
========

   Example Apache configuration:

     <Location /CPAN/>
     SetHandler perl-script
     PerlHandler Apache::Gateway
     PerlSetVar GatewayConfig /etc/apache/gateway/CPAN
     PerlSetupEnv Off
     </Location>

   Example GatewayConfig file:

     GatewayRoot /CPAN/

     <LocationMatch ".*">
     Site    ftp://ftp.perl.org/pub/perl/CPAN/
     MuxSite ftp://ftp.cdrom.com/pub/perl/CPAN/
     MuxSite ftp://ftp.digital.com/pub/plan/perl/CPAN/
     Site 	  ftp://ftp.orst.edu/pub/packages/CPAN/
     Site 	  ftp://ftp.funet.fi/pub/languages/perl/CPAN/
     </LocationMatch>

     ClockBroken ftp://ftp.cdrom.com	EET	PST8PDT
     ClockBroken ftp://ftp.digital.com	EET	PST8PDT
     ClockBroken ftp://ftp.orst.edu	EET	PST8PDT
     ClockBroken ftp://ftp.perl.org	CST	CST6CDT

   See the examples directory for commented examples.

DESCRIPTION
===========

   The `Apache::Gateway' module implements a gateway with assorted
optional features.

FEATURES
========

Standard Gateway Features
     `Apache::Gateway' services requests using `LWP' and, hence, can
     gateway to any protocol that `LWP' understands.  It also makes
     foreign URIs appear to be local URIs.

     `Apache::Gateway' does not include a cache, but it can be used in
     combination with a proxy cache to cache what the gateway retrieves.
     For example, Apache can provide caching for the gateway by setting up
     a proxy cache virtual host and a gateway virtual host and then using
     the proxy to access the gateway.

Automatic Failover with Mirrored Instances
     Multiple mirrors can provide an instance.  Requests which fail will
     automatically be retried with the next mirror.  This capability is
     very useful when some mirrors are busy or erratic.

Multiplexing
     Like the CPAN multiplexer, `Apache::Gateway' can multiplex requests
     amongst several mirrors.

Pattern-dependent Gatewaying
     The origin server to contact can vary depending upon the URL.  This
     capability is particularly useful when dealing with partial mirrors.
     A common situation is that some files may be available at all mirrors,
     but less commonly used files will only be available at a few mirrors.

FTP Directory Gatewaying
     (Need to think of a better name for this feature.)  Remote FTP
     directory listings can be modified to refer to the gateway.  This
     feature is somewhat similar to the ProxyPassReverse directive.

     This feature was especially complicated and problematical.  It has now
     been removed.

Timestamp Correction
     `Apache::Gateway' can try to correct incorrect timestamps generated
     by popular mirroring software.  In particular, it can try to
     compensate for the way the Perl *mirror* program sets timestamps.

CONFIGURATION
=============

   Most configuration is done in the GatewayConfig files.  The regular
Apache configuration files only need to include the handler directives and
set the `GatewayConfig' filename.  Environment variables are not used, so
`PerlSetupEnv' can be Off.

   GatewayConfig directives purposely look like Apache config directives
so that the syntax will be familiar.  However, GatewayConfig directives
are not Apache config directives.  They cannot be used in Apache config
files (and vice versa)!

GatewayRoot path
     Sets the root of the gatewayed area on the local server.  Generally
     matches the Location setting in the Apache config files.  Defaults to
     "/".

GatewayTimeout timeout
     Passes timeout (in seconds) to `LWP::UserAgent'.

LocationMatch regexp
     Begins a LocationMatch section.  Works similarly to the ApacheLocation
     match directive except that the pattern is a Perl regexp.  Note: there
     are no Location or other style sections, only LocationMatch.

     LocationMatch sections are tried in order until a regexp is matched.

Site URI
     Sets an upstream server to contact for this URI.  In case of failure,
     requests are automatically retried with successive sites in the order
     they appear.  Failures can include anything from the upstream server
     being down or flaky to a file not being present because the upstream
     mirror is out of synch with its primary site.

MuxSite URI
     Sets an upstream server to contact for this URI.  Adjacent MuxSite
     servers are tried in round robin order.

     For example, here again is the default portion of the sample
     GatewayConfig file above:

          <LocationMatch ".*">
          Site    ftp://ftp.perl.org/pub/perl/CPAN/
          MuxSite ftp://ftp.cdrom.com/pub/perl/CPAN/
          MuxSite ftp://ftp.digital.com/pub/plan/perl/CPAN/
          Site 	  ftp://ftp.orst.edu/pub/packages/CPAN/
          Site 	  ftp://ftp.funet.fi/pub/languages/perl/CPAN/
          </LocationMatch>

     With the Site and MuxSite directives here, the first request will be
     forwarded to ftp.perl.org.  If it fails, the request will be retried
     with cdrom, digital, orst, and funet, in that order.  The next
     request for that process will be tried with ftp.perl.org first again.
     If it fails, retries then go to digital, cdrom, orst, and finally
     funet.

     A good general strategy for packages with multiple mirrors might be
     to specify one or two nearby sites to try first.  Then specify some
     multiplexed sites slightly further away in case the nearby sites
     fail.  Finally, fall back to the primary site if all else fails.

ClockBroken server-URL upstream^2-TZ upstream-TZ
     When caching is employed and requests can be gatewayed to multiple
     mirrors, timestamp correctness becomes more important.  Unfortunately,
     timestamps on mirrored files are usually wrong.  For example, the
     popular Perl *mirror* program is generally configured to match
     timestamps using the local timezone both locally and on the server it
     is mirroring.  This strategy is only guaranteed to work if both
     servers are in the same timezone.

     Example:   ClockBroken ftp://ftp.cdrom.com	EET	PST8PDT

     cdrom gets files from funet, which seems always to use the EET
     timezone (which is two hours off from GMT) for purposes of mirroring.
     cdrom, however, uses the PST8PDT timezone, so that 00:00 on funet
     differs from 00:00 on cdrom by 9 or 10 hours, depending upon whether
     or not Daylight Savings Time is in effect.  The example ClockBroken
     line corrects for this disparity.

     Note: timezones are those understood by Time::Zone.

FUNCTIONS
=========

   The following internal functions are documented (mostly useful for
hackers):

$gw = Apache::Gateway->new( [$ua] )
     Construct a new Apache::Gateway object describing a gateway.  If a
     LWP::UserAgent is not provided, a new one will be created.  Note: the
     user agent is modified for seach request; it is not constant and is
     probably not shareable.

$gw->user_agent( [$ua] )
     Get/set the user agent.

$gw->request( [$r] )
     Get/set the Apache request currently being gatewayed.  To send the
     request, see the send_request method.

$gw->location_config( [$config] )
     Get/set the configuration information for this gateway location.  Can
     be overridden to provide dynamic per location information

clear_headers_for_redirect($r)
     Clear request headers in $r in preparation for a redirect.

canonicalized_server_URL($scheme, $hostname, $port, $default_port)
     Return semicanonicalized server URL (without trailing slash).

server_name_from_URL($url)
     Return the (somewhat canonicalized) "server name" portion of the URL.
     The "server name" is defined as the leading scheme://authority portion
     of the URL.

server_name($r)
     Return the (somewhat canonicalized) "server name" portion of the URL
     of this server.  The "server name" is defined as the leading
     scheme://authority portion of the URL.  Currently assumes server
     access is via HTTP.

diff_TZ($origin_TZ, $mirror_TZ)
     Get the usual time difference (in seconds) between the two time zones.
     Will yield the wrong results in the midst of a change to/from daylight
     savings time.  Specifically, as used in this module, this function
     will return the wrong results when applied to files retrieved by the
     mirror during the two hours of the year when one server is in Daylight
     Savings Time and the other is not.

$gw->update_via_header_field($response)
     Update Via header in HTTP::Response with information about this hop.
     Hop information combines protocol information from the message with
     server information from the Apache server.  The server name returned
     is hardcoded as '`apache''.

     Eventually, options should be provided to control hostname suppression
     and comment customization.

copy_header_to_Apache_request($r, $headers)
     Copy the headers from an `HTTP::Headers' object to an
     `Apache::Request'.  Hope that the Apache request object will later
     print out the headers in "Good Practice" order (there appears to be no
     way of controlling this).

     The only tricky item is the Content-Type header, which needs special
     handling.

redirect($allow_abort);
     Try a redirect.  We do this via `LWP::UserAgent' because
     `internal_redirect_handler' does not provide hooks for detecting and
     recovering from errors.

$gw->site( [$site] )
     Get/set the site tried.  Can be used to determine which upstream
     server actually fields a request.

$gw->try_URI($allow_abort)
     Try the site $gw->site.  Ideally, we could use
     `Apache::internal_redirect_handler' to try the redirects.  However,
     it provides no hook for detecting an error and aborting output.
     That's not mod_perl's fault-Apache source would need to be modified
     to support such a hook.

try_sites($allow_last_site_abort, @site)
     Try sites in order until one succeeds.  $allow_last_site_abort
     indicates if the last site can/should be aborted after examing the
     head for its error code.  All other sites always allow premature
     abortion.

     Abortion is needed because only one request can be allowed to run to
     completion and produce a message body.

$gw->site_list
     Get the list of sites to try for this request.  Can be overridden to
     customize the list of sites to try.

     By default, this method looks through the LocationMatch sections in
     the GatewayConfig file in order and returns the sites in the first
     section matched.

$gw->send_request( [$r] )
     Send the Apache request to the upstream server.  Optionally sets it
     first.

CAVEATS
=======

   `Apache::Gateway' is a big, complicated module that loads many other
modules.  As such, it pushes mod_perl to its limits, especially when used
with DSO/APXS.

   The current version of `LWP' (5.35) only supports If-Modified-Since for
file and ftp URLs.  Thus, gatewaying to ftp servers will actually be
better than gatewaying to http servers for cached responses.

BUGS
====

   A ProxyRemote-like capability is needed for origin servers which must
be accessed through a proxy.

   A ProxyPassReverse analogue might be useful, too.

   `Apache::Gateway' assumes it is being accessed using HTTP.  Ought to
handle cases where this gateway is accessed using https (SSL).

   There is no way to tell LWP to use a proxy.

   The Server response header field should contain information about the
origin server, not this server.  Unfortunately, Apache overrides any
existing origin server information in this field.

AUTHOR
======

   Charles C. Fu, ccwf@bacchus.com

SEE ALSO
========

   perl(1), Apache(3pm), LWP(3pm).

compress HTML (or anything) in the OutputChain
**********************************************

NAME
====

   Apache::GzipChain - compress HTML (or anything) in the OutputChain

SYNOPSIS
========

   In the configuration of your apache add something like

     <Files *.html>
     SetHandler perl-script
     PerlHandler Apache::OutputChain Apache::GzipChain Apache::PassFile
     </Files>

STATUS
======

   *This module is alpha software. Occasional SEGV have been observed.
Use with caution!*

   You currently cannot mix perl's own print statements that print to
STDOUT and the print or `write_client' methods in Apache.pm. If you do
that, you will very likely encounter empty documents and probably core
dumps too.

DESCRIPTION
===========

   This module compresses any output from another perl handler if and only
if the browser understands gzip encoding. To determine if the browser is
able to understand us we check both its *Accept-Encoding* header and its
*User-Agent* header. We check the latter because too few browsers send the
*Accept-Encoding* header currently. Instead I have set up an enquiry form
at http://www.kulturbox.de/perl/test/content-encoding-gzip where many
users already have checked their browsers' abilities and left a message.
Thus we can test a regular expression against the *User-Agent* header.

   The module seems to work without influencing the other handlers. The
only thing that can be noticed by the other handler is that the response
header 'Content-Encoding' has been set. If GzipChain decides not to do any
compression, it just declines and doesn't even register itself for the
output chain.

   GzipChain compresses every single buffer content it receives via the
output chain separately according to the GZIP specification (RFC 1952).
The compression ratio therefore suffers if the other module sends its data
in very small chunks. It is recommended that you use as few print
statements as possible in conjunction with the GzipChain.  The
Apache::PassFile module is an example of an efficient file reader for this
purpose.

PREREQUISITES
=============

   Compress::Zlib, Apache::OutputChain

AUTHOR
======

   Andreas Koenig, koenig@kulturbox.de based on code by Jan Pazdziora,
adelton@fi.muni.cz

Framework to run complex CGI tasks on an Apache server
******************************************************

NAME
====

   Apache::HeavyCGI - Framework to run complex CGI tasks on an Apache
server

SYNOPSIS
========

     use Apache::HeavyCGI; # see eg/ directory of the distribution
                           # for a complete example/template

WARNING UNSUPPORTED ALPHA CODE RELEASED FOR DEMO ONLY
=====================================================

   The release of this software is only for evaluation purposes to people
who are actively writing code that deals with Web Application Frameworks.
This package is probably just another Web Application Framework and may be
worth using or may not be worth using. As of this writing (July 1999) it
is by no means clear if this software will be developed further in the
future. The author has written it over many years and is deploying it in
several places, e.g.  http://www.stadtplandienst.de,
http://netlexikon.akademie.de and really soon on http://pause.perl.org
too. It has turned out to be useful for him. YMMV.

   There is no official support for this software. If you find it useful
or even if you find it useless, please mail the author directly.

   But please make sure you remember: THE RELEASE IS FOR DEMONSTRATION
PURPOSES ONLY.

DESCRIPTION
===========

   The Apache::HeavyCGI framework is intended to provide a couple of
simple tricks that make it easier to write complex CGI solutions. It has
been developed on a site that runs all requests through a single mod_perl
handler that in turn uses CGI.pm or Apache::Request as the query
interface. So Apache::HeavyCGI is - as the name implies - not merely for
multi-page CGI scripts (for which there are other solutions), but it is
for the integration of many different pages into a single solution. The
many different pages can then conveniently share common tasks.

   The approach taken by Apache::HeavyCGI is a components-driven one with
all components being pure perl. So if you're not looking for yet another
embedded perl solution, and aren't intimidated by perl, please read on.

Stacked handlers suck
---------------------

   If you have had a look at stacked handlers, you might have noticed that
the model for stacking handlers often is too primitive. The model supposes
that the final form of a document can be found by running several passes
over a single entity, each pass refining the entity, manipulating some
headers, maybe even passing some notes to the next handler, and in the
most advanced form passing pnotes between handlers. A lot of Web pages may
fit into that model, even complex ones, but it doesn't scale well for
pages that result out of a structure that's more complicated than adjacent
items. The more complexity you add to a page, the more overhead is
generated by the model, because for every handler you push onto the stack,
the whole document has to be parsed and recomposed again and headers have
to be re-examined and possibly changed.

Why not subclass Apache
-----------------------

   Inheritance provokes namespace conflicts. Besides this, I see little
reason why one should favor inheritance over a using relationship.  The
current implementation of Apache::HeavyCGI is very closely coupled with
the Apache class anyway, so we could do inheritance too. No big deal I
suppose. The downside of the current way of doing it is that we have to
write

     my $r = $obj->{R};

   very often, but that's about it. The upside is, that we know which
manpage to read for the different methods provided by `$obj-'{R}>,
`$obj-'{CGI}>, and $obj itself.

Composing applications
----------------------

   Apache::HeavyCGI takes an approach that is more ambitious for handling
complex tasks. The underlying model for the production of a document is
that of a puzzle. An HTML (or XML or SGML or whatever) page is regarded as
a sequence of static and dynamic parts, each of which has some influence
on the final output. Typically, in today's Webpages, the dynamic parts are
filled into table cells, i.e. contents between some `<TD></TD>' tokens.
But this is not necessarily so. The static parts in between typically are
some HTML markup, but this also isn't forced by the model. The model
simply expects a sequence of static and dynamic parts. Static and dynamic
parts can appear in random order. In the extreme case of a picture you
would only have one part, either static or dynamic. HeavyCGI could handle
this, but I don't see a particular advantage of HeavyCGI over a simple
single handler.

   In addition to the task of generating the contents of the page, there
is the other task of producing correct headers. Header composition is an
often neglected task in the CGI world. Because pages are generated
dynamically, people believe that pages without a Last-Modified header are
fine, and that an If-Modified-Since header in the browser's request can go
by unnoticed. This laissez-faire principle gets in the way when you try to
establish a server that is entirely driven by dynamic components and the
number of hits is significant.

Header Composition, Parameter Processing, and Content Creation
--------------------------------------------------------------

   The three big tasks a CGI script has to master are Headers, Parameters
and the Content. In general one can say, content creation SHOULD not start
before all parameters are processed. In complex scenarios you MUST expect
that the whole layout may depend on one parameter.  Additionally we can
say that some header related data SHOULD be processed very early because
they might result in a shortcut that saves us a lot of processing.

   Consequently, Apache::HeavyCGI divides the tasks to be done for a
request into four phases and distributes the four phases among an
arbitrary number of modules. Which modules are participating in the
creation of a page is the design decision of the programmer.

   The perl model that maps (at least IMHO) ideally to this task
description is an object oriented approach that identifies a couple of
phases by method names and a couple of components by class names. To
create an application with Apache::HeavyCGI, the programmer specifies the
names of all classes that are involved. All classes are singleton classes,
i.e. they have no identity of their own but can be used to do something
useful by working on an object that is passed to them.  Singletons have an
@ISA relation to Class/Singleton, which can be
found on CPAN. As such, the classes can only have a single instance which
can be found by calling the `CLASS->instance' method. We'll call these
objects after the mod_perl convention handlers.

   Every request maps to exactly one Apache::HeavyCGI object. The
programmer uses the methods of this object by subclassing. The HeavyCGI
constructor creates objects of the AVHV type (pseudo-hashes).  If the
inheriting class needs its own constructor, this needs to be an AVHV
compatible constructor. A description of AVHV can be found in
Fields. An Apache::HeavyCGI object usually is constructed with the
new method and after that the programmer calls the dispatch method on this
object. HeavyCGI will then perform various initializations and then ask
all nominated handlers in turn to perform the header method and in a
second round to perform the parameter method. In most cases it will be the
case that the availability of a method can be determined at compile time
of the handler. If this is true, it is possible to create an execution
plan at compile time that determines the sequence of calls such that no
runtime is lost to check method availability. Such an execution plan can
be created with the Apache/HeavyCGI/ExePlan,
module. All of the called methods will get the
HeavyCGI request object passed as the second parameter.

   There are no fixed rules as to what has to happen within the header and
parameter method. As a rule of thumb it isf recommended to determine and
set the object attributes LAST_MODIFIED and EXPIRES (see below) within the
header() method. It is also recommended to inject the
Apache/HeavyCGI/IfModified, module as the last
header handler, so that the application can abort early with an Not
Modified header. I would recommend that in the header phase you do as
little as possible parameter processing except for those parameters that
are related to the last modification date of the generated page.

Terminating the handler calls or triggering errors.
---------------------------------------------------

   Sometimes you want to stop calling the handlers, because you think that
processing the request is already done. In that case you can do a

     die Apache::HeavyCGI::Exception->new(HTTP_STATUS => status);

   at any point within prepare() and the specified status will be returned
to the Apache handler. This is useful for example for the
Apache::HeavyCGI::IfModified module which sends the response headers and
then dies with HTTP_STATUS set to Apache::Constants::DONE.  Redirectors
presumably would set up their headers and set it to
Apache::Constants::HTTP_MOVED_TEMPORARILY.

   Another task for Perl exceptions are errors: In case of an error within
the prepare loop, all you need to do is

     die Apache::HeavyCGI::Exception->new(ERROR=>[array_of_error_messages]);

   The error is caught at the end of the prepare loop and the anonymous
array that is being passed to $@ will then be appended to
`@{$self->{ERROR}}'. You should check for $self->{ERROR} within your
layout method to return an appropriate response to the client.

Layout and Text Composition
---------------------------

   After the header and the parameter phase, the application should have
set up the object that is able to characterize the complete application
and its status. No changes to the object should happen from now on.

   In the next phase Apache::HeavyCGI will ask this object to perform the
`layout' method that has the duty to generate an Apache::HeavyCGI::Layout
(or compatible) object. Please read more about this object in
Apache/HeavyCGI/Layout. For our HeavyCGI object
it is only relevant that this Layout object can compose itself as a string
in the as_string() method. As a layout object can be composed as an
abstraction of a layout and independent of request-specific contents, it
is recommended to cache the most important layouts. This is part of the
reponsibility of the programmer.

   In the next step HeavyCGI stores a string representation of current
request by calling the as_string() method on the layout object and passing
itself to it as the first argument. By passing itself to the Layout object
all the request-specific data get married to the layout-specific data and
we reach the stage where stacked handlers usually start, we get at a
composed content that is ready for shipping.

   The last phase deals with setting up the yet unfinished headers,
eventually compressing, recoding and measuring the content, and delivering
the request to the browser. The two methods finish() and deliver() are
responsible for that phase. The default deliver() method is pretty
generic, it calls finish(), then sends the headers, and sends the content
only if the request method wasn't a HEAD. It then returns Apache's
constant DONE to the caller, so that Apache won't do anything except
logging on this request. The method finish is more apt to being
overridden. The default finish() method sets the content type to
text/html, compresses the content if the browser understands compressed
data and Compress::Zlib is available, it also sets the headers Vary,
Expires, Last-Modified, and Content-Length. You most probably will want to
override the finish method.

   head2 Summing up
+------------------+                                         | sub handler
{...} |  +-------------------+                 | (sub init {...})  |
|Your::Class         |--defines----->|                   |  |ISA
Apache::HeavyCGI|                 | sub layout {...}  |
+-------------------+                 | sub finish {...}  |
                        +------------------+

     +-------------------+
     | sub new {...}     |
      +--------------------+                 | sub dispatch {...}|
      |Apache::HeavyCGI    |---defines------>| sub prepare {...} |
      +--------------------+                 | sub deliver {...} |
     +-------------------+

     +----------------------+               +--------------------+
     |Handler_1 .. Handler_N|               | sub header {...}   |
     |ISA Class::Singleton  |---define----->| sub parameter {...}|
     +----------------------+               +--------------------+

     +----+
     |Your|
     |Duty|
      +----------------------------+----------------------------------------+----+
      |Apache                      | calls Your::Class::handler()           |    |
      +----------------------------+----------------------------------------+----+
      |                            | nominates the handlers,                |    |
      |Your::Class::handler()      | constructs $self,                      | ** |
      |                            | and calls $self->dispatch              |    |
      +----------------------------+----------------------------------------+----+
      |                            |        $self->init     (does nothing)  | ?? |
      |                            |        $self->prepare  (see below)     |    |
      |Apache::HeavyCGI::dispatch()| calls  $self->layout   (sets up layout)| ** |
      |                            |        $self->finish   (headers and    | ** |
      |                            |                         gross content) |    |
      |                            |        $self->deliver  (delivers)      | ?? |
      +----------------------------+----------------------------------------+----+
      |Apache::HeavyCGI::prepare() | calls HANDLER->instance->header($self) | ** |
      |                            | and HANDLER->instance->parameter($self)| ** |
      |                            | on all of your nominated handlers      |    |
      +----------------------------+----------------------------------------+----+

Object Attributes
=================

   As already mentioned, the HeavyCGI object is a pseudo-hash, i.e. can be
treated like a HASH, but all attributes that are being used must be
predeclared at compile time with a `use fields' clause.

   The convention regarding attributes is as simple as it can be:
uppercase attributes are reserved for the Apache::HeavyCGI class, all
other attribute names are at your disposition if you write a subclass.

   The following attributes are currently defined. The module author's
production environment has a couple of attributes more that seem to work
well but most probably need more thought to be implemented in a generic
way.

CAN_GZIP
     Set by the can_gzip method. True if client is able to handle gzipped
     data.

CAN_PNG
     Set by the can_png method. True if client is able to handle PNG.

CAN_UTF8
     Set by the can_utf8 method. True if client is able to handle UTF8
     endoded data.

CGI
     An object that handles GET and POST parameters and offers the method
     param() and upload() in a manner compatible with Apache::Request.
     Needs to be constructed and set by the user typically in the
     contructor.

CHARSET
     Optional attribute to denote the charset in which the outgoing data
     are being encoded. Only used within the finish method. If it is set,
     the finish() method will set the content type to text/html with this
     charset.

CONTENT
     Scalar that contains the content that should be sent to the user
     uncompressed. During te finish() method the content may become
     compressed.

DOCUMENT_ROOT
     Unused.

ERROR
     Anonymous array that accumulates error messages. HeavyCGI doesn't
     handle the error though. It is left to the user to set up a proper
     response to the user.

EXECUTION_PLAN
     Object of type Apache/HeavyCGI/ExePlan.
     It is recommended to compute the object at
     startup time and always pass the same execution plan into the
     constructor.

EXPIRES
     Optional Attribute set by the expires() method. If set, HeavyCGI will
     send an Expires header. The EXPIRES attribute needs to contain an
     Apache/HeavyCGI/Date, object.

HANDLER
     If there is an EXECUTION_PLAN, this attribute is ignored. Without an
     EXECUTION_PLAN, it must be an array of package names. HeavyCGI treats
     the packages as Class::Singleton classes. During the prepare() method
     HeavyCGI calls HANDLER->instance->header($self) and
     HANDLER->instance->parameter($self) on all of your nominated handlers.

LAST_MODIFIED
     Optional Attribute set by the last_modified() method. If set, HeavyCGI
     will send a Last-Modified header of the specified time, otherwise it
     sends a Last-Modified header of the current time. The attribute needs
     to contain an Apache/HeavyCGI/Date,
     object.

MYURL
     The URL of the running request set by the myurl() method. Contains an
     URI::URL object.

R
     The Apache Request object for the running request. Needs to be set up
     in the constructor by the user.

REFERER
     Unused.

SERVERROOT_URL
     The URL of the running request's server-root set by the
     serverroot_url() method. Contains an URI::URL object.

SERVER_ADMIN
     Unused.

TIME
     The time when this request started set by the time() method. Please
     note, that the time() system call is considerable faster than the
     method call to Apache::HeavyCGI::time. The advantage of calling using
     the TIME attribute is that it is self-consistent (remains the same
     during a request).

TODAY
     Today's date in the format 9999-99-99 set by the today() method, based
     on the time() method.

Performance
-----------

   Don't expect Apache::HeavyCGI to serve 10 million page impressions a
day. The server I have developed it for is a double processor machine with
233 MHz, and each request is handled by about 30 different handlers: a few
trigonometric, database, formatting, and recoding routines. With this
overhead each request takes about a tenth of a second which in many
environments will be regarded as slow. On the other hand, the server is
well respected for its excellent response times. YMMV.

BUGS
====

   The fields pragma doesn't mix very well with Apache::StatINC. When
working with HeavyCGI you have to restart your server quite often when you
change your main class. I believe, this could be fixed in fields.pm, but I
haven't tried. A workaround is to avoid changing the main class, e.g. by
delegating the layout() method to a different class.

AUTHOR
======

   Andreas Koenig <andreas.koenig@anima.de>. Thanks to Jochen Wiedmann for
heavy debates about the code and crucial performance enhancement
suggestions. The development of this code was sponsered by
www.speed-link.de.

represent a date as both unix time and HTTP time
************************************************

NAME
====

   Apache::HeavyCGI::Date - represent a date as both unix time and HTTP
time

SYNOPSIS
========

     my $date = Apache::HeavyCGI::Date->new;

     $date->unix(time);   # set
     print $date->unix;   # get
     print $date->http;   # get as http
     print $date;         # same thing due to overloading

DESCRIPTION
===========

   This class implements a simple dual value date variable. There are only
two accessor methods that let you set and get dates. unix() sets and gets
the UNIX time, and http() gets and sets the HTTP time.  Whenever a time is
set the other time gets undefined. Retrieving an undefined time triggers a
conversion from the other time. That way the two times are always synced.

PREREQUISITES
=============

   The class uses HTTP::Date internally.

AUTHOR
======

   andreas koenig <andreas.koenig@anima.de>

inspect the Pseudohash as Hash with Data::Dumper
************************************************

NAME
====

   Apache::HeavyCGI::Debug - inspect the Pseudohash as Hash with
Data::Dumper

SYNOPSIS
========

     push @layout, "<BR><PRE>",
                   $self->instance_of("Apache::HeavyCGI::Debug"),
                   "</PRE><BR>\n";

DESCRIPTION
===========

   Can be used to inspect the application object within an output page.
The Class is just implemented as an illustration.

exception class for Apache::HeavyCGI
************************************

NAME
====

     Apache::HeavyCGI::Exception - exception class for Apache::HeavyCGI

SYNOPSIS
========

     die Apache::HeavyCGI::Exception->new(HTTP_STATUS => status);
     die Apache::HeavyCGI::Exception->new(ERROR => [error, ...]);

DESCRIPTION
===========

   The execution of the Apache::HeavyCGI::prepare method is protected by
an eval. Within that block the above mentioned exceptions can be thrown.
For a discussion of the semantics of these errors, see
Apache/HeavyCGI.

   You need not require the Apache::HeavyCGI::Error module, it is already
required by Apache::HeavyCGI.

Creates an execution plan for Apache::HeavyCGI
**********************************************

NAME
====

   Apache::HeavyCGI::ExePlan - Creates an execution plan for
Apache::HeavyCGI

SYNOPSIS
========

     use Apache::HeavyCGI::ExePlan;
     my $plan = Apache::HeavyCGI::ExePlan->new(
        METHODS => ["header", "parameter"],
        CLASSES => ["my_application::foo", "my_application::bar", ... ]
        DEBUG    => 1
     );

     $plan->walk;

DESCRIPTION
===========

   When an execution plan object is instantiated, it immediately visits
all specified classes, collects the singleton objects for these classes,
and checks if the classes define the specified methods. It creates an
array of objects and methods or an array of code references.

   The walk method walks through the execution plan in the stored order
and sends each singleton object the appropriate method and passes the
application object as the first argument.

   Normally, every application has its own execution plan. If the
execution plan is calculated at load time of the application class, all
objects of this class can share a common execution plan, thus speeding up
the requests. Consequently it is recommended to have an initialization in
all applications that instantiates an execution plan and passes it to all
application objects in the constructor.

   head1 BUGS

   It's not a bug, it's a feature: if new methods and classes are
dynamically created in an application, the execution plan object won't
take note.

Within Apache::HeavyCGI return 304
**********************************

NAME
====

   Apache::HeavyCGI::IfModified - Within Apache::HeavyCGI return 304

SYNOPSIS
========

     require Apache::HeavyCGI::IfModified;
     push @{$mgr->{HANDLER}},
         "Apache::HeavyCGI::IfModified"; # $mgr is an Apache::HeavyCGI object

DESCRIPTION
===========

   If-modified-since is tricky. We have pages with very differing last
modification. Some are modified NOW, some are old, most are MADE now but
would have been just the same many hours ago.

   Because it's the recipe that is used for the composition of a page, it
may well be that a page that has never been generated before, nonetheless
has a Last-Modified date in the past. The Last-Modified header acts as a
weak validator for cache activities, and the older a document appears to
be, the longer the cache will store it for us by default. When the cache
revisits us after it has got a valid Last-Modified header, it will use an
If-Modified-Since header and if we carefully determine our own
Last-Modified time, we can spare a lot of processing by returning a Not
Modified response instead of working.

   IfModified should be one of the last handlers in any Apache::HeavyCGI
environment, at least it must be processed after all the handlers that
might set the LAST_MODIFIED date.

Represent a page layout in an array
***********************************

NAME
====

   Apache::HeavyCGI::Layout - Represent a page layout in an array

SYNOPSIS
========

     my $layout = Apache::HeavyCGI::Layout->new(@array);

     $layout->prejoin;  # make the array more compact

     my @array = $layout->content;
     my $string = $layout->as_string($object);

DESCRIPTION
===========

   The constructor new() takes as an argument an array of elements.
Elements may be strings and objects in any order.

   The content() method returns the array of elements.

   The prejoin() method joins adjacent string elements, leaving at most
one string element between objects in the array.

   The as_string() method takes an object, say $mgr, as an argument and
joins all elements of the array such that all chunks that represent an
object are called with

     $chunk->as_string($mgr)

   and all chunks that represent a string are fillers in between. Objects
that do not understand the as_string method are just filled in as strings,
leaving room for debugging or overloading or whatever.

Pass X-Forwarded-For Header through as remote_ip
************************************************

NAME
====

   Apache::HeavyCGI::SquidRemoteAddr - Pass X-Forwarded-For Header through
as remote_ip

SYNOPSIS
========

     PerlPostReadRequestHandler  Apache::HeavyCGI::SquidRemoteAddr

DESCRIPTION
===========

   Author Vivek Khera, taken from his mod_perl_tuning document.

Allow queries without a questionmark
************************************

NAME
====

   Apache::HeavyCGI::UnmaskQuery - Allow queries without a questionmark

SYNOPSIS
========

     <Perl>
     require Apache::HeavyCGI::UnmaskQuery;
     $PerlPostReadRequestHandler = "Apache::HeavyCGI::UnmaskQuery";
     </Perl>

     -or-

     PerlModule Apache::HeavyCGI::UnmaskQuery
     PerlPostReadRequestHandler Apache::HeavyCGI::UnmaskQuery

DESCRIPTION
===========

   This Apache Handler can be used from apache 1.3 (when post_read_request
was introduced) upwards to turn a request that looks like an ordinary
static request to the unsuspecting observer into a query that can be
handled by the CGI or Apache::Request module or by the $r->args method.

   The reason why you might want to do this lies in the fact that many
cache servers in use today (1999) are configured wrongly in that they
disallow caching of URIs with a questionmark in them. By composing URIs
with a semicolon instead of a questionmark, these cache servers can be
tricked into working correctly.

   Thus this handler replaces the first semicolon in any request for an
URI with a questionmark (unless that URI does already contain a
questionmark). As this is being done in the very early stage of apache's
handling phase, namely in a PerlPostReadRequestHandler, all subsequent
phases can be tricked into seeing the request as a query.

   Unfortunately the last paragraph is not completely true. Apache 1.3.4
is not allowing `%2F' (a slash in ASCII) and `%00' (a binary 0) in the
path section of the HTTP URI, only in the *searchoart* section. Apparently
the URL is parsed before the during read_request....

     Breakpoint 1, 0x80b9d05 in ap_unescape_url ()
     (gdb) bt
     #0  0x80b9d05 in ap_unescape_url ()
     #1  0x80b5a56 in ap_some_auth_required ()
     #2  0x80b5fb0 in ap_process_request ()
     #3  0x80adbcd in ap_child_terminate ()
     #4  0x80add58 in ap_child_terminate ()
     #5  0x80adeb3 in ap_child_terminate ()
     #6  0x80ae490 in ap_child_terminate ()
     #7  0x80aecc3 in main ()
     (gdb) c

   So if any parameter needs to contain a slash or a binary 0, we must
resort to a different escape method. Now it's turning ridiculous quickly.
I believe, this is a bug in apache and must be fixed there. But what if
the apche group doesn't listen to us?

   Easy answer: don't escape slashes if you want to use this technique.
Don't dare to need binary nulls in your parameters. Until it is figured
out if apache group sees this as a bug or not.

Create and modify Apache .htaccess files
****************************************

NAME
====

   Apache::Htaccess - Create and modify Apache .htaccess files

SYNOPSIS
========

     use Apache::Htaccess;

     my $obj = Apache::Htaccess->new("htaccess");
     die($Apache::Htaccess::ERROR) if $Apache::Htaccess::ERROR;

     $obj->global_requires(@groups);

     $obj->add_global_require(@groups);

     $obj->directives(CheckSpelling => 'on');

     $obj->add_directive(CheckSpelling => 'on');

     $obj->requires('admin.cgi',@groups);

     $obj->add_require('admin.cgi',@groups);

     $obj->save();
     die($Apache::Htaccess::ERROR) if $Apache::Htaccess::ERROR;

DESCRIPTION
===========

   This module provides an OO interface to Apache .htaccess files.
Currently the ability exists to read and write simple htaccess files.

AUTHOR
======

   Matt Cashner <matt@cre8tivegroup.com>

COPYRIGHT
=========

   All code is copyright (c) 2000 by The Creative Group. It may be
distributed under the terms of Perl itself.

METHODS
=======

new()
-----

     my $obj = Apache::Htaccess->new($path_to_htaccess);

   Creates a new Htaccess object either with data loaded from an existing
htaccess file or from scratch

save()
------

     $obj->save();

   Saves the htaccess file to the filename designated at object creation.
This method is automatically called on object destruction.

global_requires()
-----------------

     $obj->global_requires(@groups);

   Sets the global group requirements. If no params are provided, will
return a list of the current groups listed in the global require. Note: as
of 0.3, passing this method a parameter list causes the global requires
list to be overwritten with your parameters. see `add_global_require()' in
this node.

add_global_require()
--------------------

     $obj->add_global_require(@groups);

   Sets a global require (or requires) nondestructively. Use this if you
just want to add a few global requires without messing with all of the
global requires entries.

requires()
----------

     $obj->requires($file,@groups);

   Sets a group requirement for a file. If no params are given, returns a
list of the current groups listed in the files require directive.  Note:
as of 0.3, passing this method a parameter list causes the requires list
to be overwritten with your parameters. see `add_require()' in this node.

add_require()
-------------

     $obj->add_require($file,@groups);

   Sets a require (or requires) nondestructively. Use this if you just
want to add a few requires without messing with all of the requires
entries.

directives()
------------

     $obj->directives(CheckSpelling => 'on');

   Sets misc directives not directly supported by the API. If no params
are given, returns a list of current directives and their values. Note: as
of 0.2, passing this method a parameter list causes the directive list to
be overwritten with your parameters. see `add_directive()' in this node.

add_directive()
---------------

     $obj->add_directive(CheckSpelling => 'on');

   Sets a directive (or directives) nondestructively. Use this if you just
want to add a few directives without messing with all of the directive
entries.

HISTORY
=======

     $Log: Htaccess.pm,v $
     Revision 1.13  2000/09/29 16:22:46  matt
     fixed bug in parser that caused global_reqs to be dumped. ARGH

     Revision 1.12  2000/09/29 15:51:04  matt
     added global ERROR variable, changed global_require() to global_requires()

     Revision 1.11  2000/09/29 15:36:53  matt
     think i finally squashed the undef problem with requires()

     Revision 1.10  2000/09/29 15:20:36  matt
     made global_requires destructive and created add_global_require(), added better error responses to new() and save()

     Revision 1.9  2000/09/29 14:31:35  matt
     added new methods to the synopsis

     Revision 1.8  2000/09/29 14:25:46  matt
     made requires nondestructive and added add_require()

     Revision 1.7  2000/09/29 12:50:11  matt
     made directives() destructive and created the add_directive method()

     Revision 1.6  2000/09/27 18:43:23  matt
     added more return values. its amazing the little things i forget

     Revision 1.5  2000/09/27 18:30:34  matt
     fixed silly pod problem

     Revision 1.4  2000/09/27 18:23:46  matt
     added useful return values to save().

     Revision 1.3  2000/09/27 18:19:34  matt
     parse now works and can parse htaccess files the module has created (or very similar files). added more docs

     Revision 1.2  2000/09/27 14:19:26  matt
     deparse now working, additional docs added

     Revision 1.1  2000/09/26 21:20:24  matt
     first nonfunctional version :)  data structures are set up and accessor methods to those structures are ready. input and output of the file (note: the useful sections) are not yet written.

Manage Apache authentication group files
****************************************

NAME
====

   Apache::Htgroup - Manage Apache authentication group files

SYNOPSIS
========

     use Apache::Htgroup;
     $htgroup = Apache::Htgroup->load($path_to_groupfile);
     &do_something if $htgroup->ismember($user, $group);
     $htgroup->adduser($user, $group);
     $htgroup->deleteuser($user, $group);
     $htgroup->save;

Important notes about versions 1.x
==================================

   There has been a change to the API since the 0.9 version. The 0.9
version sucked a lot, and this should be a big improvement in a lot of
ways. Please feel free to contact me and yell at me about these changes if
you like. If there are enough complaints, I'll try to make it backward
compatible. However, given a little work, I think you'll find the new
version superior in every way.

DESCRIPTION
===========

   Manage Apache htgroup files

   Please note that this is not a mod_perl module. Please also note that
there is another module that does similar things (HTTPD::UserManage) and
that this is a more simplistic module, not doing all the things that one
does.

   Please also note that, in contrast to Version 0.9, changes to the
object are only saved to disk when you call the save method.

load
          $htgroup = Apache::Htgroup->load($path_to_groupfile);
               $htgroup = Apache::Htgroup->new();

     Returns an Apache::Htgroup object.

     Calling new() without an argument creates an empty htgroup object
     which you can save to a file once you're done with it.

adduser
          $htgroup->adduser( $username, $group );

     Adds the specified user to the specified group.

deleteuser
          $htgroup->deleteuser($user, $group);

     Removes the specified user from the group.

groups
          $groups = $htgroup->groups;

     Returns a (reference to a) hash of the groups. The key is the name of
     the group. Each value is a hashref, the keys of which are the group
     members. I suppose there may be some variety of members method in the
     future, if anyone thinks that would be useful.

     It is expected that this method will not be called directly, and it
     is provided as a convenience only.

     Please see the section below about internals for an example of the
     data structure.

reload
          $self->reload;

     If you have not already called save(), you can call reload() and get
     back to the state of the object as it was loaded from the original
     file.

save
          $htgroup->save;
               $htgroup->save($file);

     Writes the current contents of the htgroup object back to the file.
     If you provide a $file argument, save will attempt to write to that
     location.

ismember
          $foo = $htgroup->ismember($user, $group);

     Returns true if the username is in the group, false otherwise

Internals
=========

   Although this was not the case in earlier versions, the internal data
structure of the object looks something like the following:

     $obj = { groupfile => '/path/to/groupfile',
              groups => { group1 => { 'user1' => 1,
                                      'user2' => 1,
                                      'user3' => 1
                                    },
                          group2 => { 'usera' => 1,
                                      'userb' => 1,
                                      'userc' => 1
                                    },
                        }
            };

   Note that this data structure is subject to change in the future, and
is provided mostly so that I can remember what the heck I was thinking
when I next have to look at this code.

Adding groups
=============

   A number of folks have asked for a method to add a new group. This is
unnecessary. To add a new group, just start adding users to a new group,
and the new group will magically spring into existance.

ToDo
====

   Need to add a decent test suite, but apart from that, I think that this
is pretty good.

AUTHOR
======

   Rich Bowen, rbowen@rcbowen.com

HISTORY
=======

     $Log: Htgroup.pm,v $
     Revision 1.14  2001/02/24 21:27:50  rbowen
     Added space between "group:" and the first user, as per the documentation.

     Revision 1.13  2001/02/23 04:13:12  rbowen
     Apparently Perl 5.005_02 was getting grumpy about my use of $Revision: 1.14 $
     to set the VERSION number. Fixed.

     Revision 1.12  2001/02/23 03:16:58  rbowen
     Fixed bug in reload that was effectively breaking everything else.
     It would let you build files from scratch, but not load existing
     files correctly. Added test suite also, which should help

     Revision 1.11  2001/02/21 03:14:04  rbowen
     Fixed reload to work as advertised. groups now calls reload internally
     the first time you call it.

     Version 0.9 -> 1.10 contains a number of important changes.
     As mentioned above, the API has changed, as well as the internal
     data structure. Please read the documentation very carefully.

Manage Unix crypt-style password file.
**************************************

NAME
====

   Apache::Htpasswd - Manage Unix crypt-style password file.

SYNOPSIS
========

     use Apache::Htpasswd;

     $foo = new Apache::Htpasswd("path-to-file");

     # Add an entry
     $foo->htpasswd("zog", "password");

     # Change a password
     $foo->htpasswd("zog", "new-password", "old-password");

     # Change a password without checking against old password
     # The 1 signals that the change is being forced.

     $foo->htpasswd("zog", "new-password", 1);

     # Check that a password is correct
     $pwdFile->htCheckPassword("zog", "password");

     # Fetch an encrypted password
     $foo->fetchPass("foo");

     # Delete entry
     $foo->htDelete("foo");

     # If something fails, check error
     $foo->error;

     # Write in the extra info field
     $foo->writeInfo("login", "info");

     # Get extra info field for a user
     $foo->fetchInfo("login");

DESCRIPTION
===========

   This module comes with a set of methods to use with htaccess password
files. These files (and htaccess) are used to do Basic Authentication on a
web server.

   The passwords file is a flat-file with login name and their associated
crypted password. You can use this for non-Apache files if you wish, but
it was written specifically for .htaccess style files.

FUNCTIONS
---------

htaccess->new("path-to-file");
     "path-to-file" should be the path and name of the file containing the
     login/password information.

error;
     If a method returns an error, or a method fails, the error can be
     retrived by calling error()

htCheckPassword("login", "password");
     Finds if the password is valid for the given login.

     Returns 1 if passes.  Returns 0 if fails.

htpasswd("login", "password");
     This will add a new user to the password file.  Returns 1 if succeeds.
     Returns undef on failure.

htDelete("login")
     Delete users entry in password file.

     Returns 1 on success Returns undef on failure.

htpasswd("login", "new-password", "old-password");
     If the *old-password* matches the *login's* password, then it will
     replace it with *new-password*. If the *old-password* is not correct,
     will return 0.

htpasswd("login", "new-password", 1);
     Will replace the password for the login. This will force the password
     to be changed. It does no verification of old-passwords.

     Returns 1 if succeeds Returns undef if fails

fetchPassword("login");
     Returns *encrypted* password if succeeds.  Returns 0 if login is
     invalid.  Returns undef otherwise.

fetchInfo("login");
     Returns additional information if succeeds.  Returns 0 if login is
     invalid.  Returns undef otherwise.

writeInfo("login", "info");
     Will replace the additional information for the login.  Returns 0 if
     login is invalid.  Returns undef otherwise.

CryptPasswd("password", "salt");
     Will return an encrypted password using 'crypt'. If *salt* is
     ommitted, a salt will be given by the subroutine using the first 2
     character of $0.

INSTALLATION
============

   You install Apache::Htpasswd, as you would install any perl module
library, by running these commands:

     perl Makefile.PL
     make
     make test
     make install
     make clean

DOCUMENTATION
=============

   POD style documentation is included in the module.  These are normally
converted to manual pages and installed as part of the "make install"
process.  You should also be able to use the 'perldoc' utility to extract
and read documentation from the module files directly.

AVAILABILITY
============

   The latest version of Apache::Htpasswd should always be available from:

     $CPAN/modules/by-authors/id/K/KM/KMELTZ/

   Visit <URL:http://www.perl.com/CPAN/> to find a CPAN site near you.

VERSION
=======

   $Revision: 1.3 $ $Date: 2000/04/04 15:00:13 $

CHANGES
=======

   $Log: Htpasswd.pm,v $

   Revision 1.4  2001/02/23 08:23:46 kevin Added support for extra info
fields

   Revision 1.3  2000/04/04 15:00:15 meltzek Made file locking safer to
avoid race conditions. Fixed typo in docs.

   Revision 1.2  1999/01/28 22:43:45  meltzek Added slightly more verbose
error croaks. Made sure error from htCheckPassword is only called when
called directly, and not by $self.

   Revision 1.1  1998/10/22 03:12:08  meltzek Slightly changed how files
lock.  Made more use out of carp and croak.  Made sure there were no ^M's
as per Randal Schwartz's request.

BUGS
====

   None knows at time of writting.

AUTHOR INFORMATION
==================

   Copyright 1998..2001, Kevin Meltzer.  All rights reserved.  It may be
used and modified freely, but I do request that this copyright notice
remain attached to the file.  You may modify this module as you wish, but
if you redistribute a modified version, please attach a note listing the
modifications you have made.

   This is released under the same terms as Perl itself.

   Address bug reports and comments to: perlguy@perlguy.com

   The author makes no warranties, promises, or gaurentees of this
software. As with all software, use at your own risk.

SEE ALSO
========

   See Apache/Htgroup,

Lookup icon images
******************

NAME
====

   Apache::Icon - Lookup icon images

SYNOPSIS
========

     use Apache::Icon ();
     my $icon = Apache::Icon->new($subr);
     my $img = $icon->find || $icon->default;
     my $alt = $icon->alt;

DESCRIPTION
===========

   This module rips out the icon guts of mod_autoindex and provides a Perl
interface for looking up icon images.  The motivation is to piggy-back the
existing AddIcon and related directives for mapping file extensions and
names to icons, while keeping things as small and fast as mod_autoindex
does.

METHODS
=======

new
     Create a new *Apache::Icon* object with the given *Apache::SubRequest*
     object.  Example:

          for my $entry (sort $dh->read) {
          	next if $entry eq '.';
          	my $subr = $r->lookup_file($entry);
              my $icon = Apache::Icon->new($subr);
          	...

find
     Lookup icon image associated with the subrequest.

          my $img = $icon->find;

default
     Lookup the default icon images.

          my $img = $icon->default; #DefaultIcon (unknown.gif)
          my $img = $icon->default("^^DIRECTORY^^"); #folder.gif
          my $img = $icon->default("^^BLANKICON^^"); #blank.gif

alt
     Lookup the text alternative specified by the AddAlt directive.

          my $alt = $icon->alt || $img;

DIRECTIVES
==========

   Refer to the *mod_autoindex* documentation for directives listed here
with no description.

IconDouble
     This directive can be set to On or *Off*.  The default is On if
     *mod_autoindex* is configured with the server, *Off* otherwise.  When
     the directive is On, *mod_icon* directive handlers will return
     *DECLINE_CMD* after processing which allows *mod_autoindex* to also
     handle the various Icon and *Alt* directives.

AddIcon
AddIconByType
AddIconByEncoding
AddAlt
AddAltByType
AddAltByEncoding
DefaultIcon
SEE ALSO
========

   Apache::AutoIndex(3)

AUTHOR
======

   Doug MacEachern

   C code based on mod_autoindex by the Apache Group

Utilities for mod_perl/mod_include integration
**********************************************

NAME
====

   Apache::Include - Utilities for mod_perl/mod_include integration

SYNOPSIS
========

     <!--#perl sub="Apache::Include" arg="/perl/ssi.pl" -->

DESCRIPTION
===========

   The *Apache::Include* module provides a handler, making it simple to
include Apache::Registry scripts with the mod_include perl directive.

   Apache::Registry scripts can also be used in mod_include parsed
documents using 'virtual include'.

METHODS
=======

Apache::Include->virtual($uri)
     The `virtual' method may be called to include the output of a given
     uri in your Perl scripts.  Example:

          use Apache::Include ();

          print "Content-type: text/html\n\n";

          print "before include\n";

          my $uri = "/perl/env.pl";

          Apache::Include->virtual($uri);

          print "after include\n";

SEE ALSO
========

   perl(1), mod_perl(3), mod_include

AUTHOR
======

   Doug MacEachern

Store keywords as a personal profile in a cookie.
*************************************************

NAME
====

   Apache::Keywords - Store keywords as a personal profile in a cookie.

CONTENTS
========

   The package Apache::Keywords contains:

     Makefile.PL
     lib/Apache/Keywords.pm
     README
     MANIFEST

PREREQUISITES
=============

   You need Apache::Constants and Apache::Cookie to use Apache::Keywords.

INSTALLATION
============

     tar zxf Apache-Keywords-0.1.tar.gz
     perl Makefile.PL
     make
     make install

SYNOPSIS
========

   In a dynamic mod_perl source-file:

     use Apache::Keywords;

     # Create a keywords object
     $k = new Apache::Keywords;

     # Set different parameters
     $k->name('PersonalProfile');
     $k->expires('+1M');
     $k->path("/");
     $k->domain('xxx.com');

     # Get parameters
     print $k->expires;
     print $k->path;
     ...

     # Add new keywords to the profile
     $k->new_keywords($r,"horse, dog");
     # Special version for Apache::ASP
     $k->new_keywords_asp($Request,"cars, motorcycles");

     # Return the content of the cookie profile
     $hashref = $k->profile($r);
     print $hashref->{'horse'};
     %hash = %$hashref;
     # Special version for Apache::ASP
     $k->profile_asp($Request);

   In a the .htaccess for apache static-files, e.g. .html-files:
<Files ~ (\.html)>         SetHandler perl-script         PerlFixupHandler
Apache::Keywords         PerlSetVar KeywordsName "PersonalProfile"
PerlSetVar KeywordsExpires "+1M"         PerlSetVar KeywordsPath "/"
 PerlSetVar KeywordsDomain "xxx.com"     </Files>

DESCRIPTION
===========

   An Apache::Keywords class object will generate/update a cookie. The
cookie contains a personal profile, e.g. counts the different keywords
that are added to it. The module could be configured as a
"PerlFixupHandler" for a static file in mod_perl, e.g. HTML-files. It
could also be used in web scripts, like mod_perl scripts that uses
Apache::ASP or Apache::Registry. In the static version, Apache::Keywords
fetches the keywords from phrases like <META NAME="keywords"
CONTENT="cars, motorcycles">.

METHODS
=======

   The following methods could be use in dynamic web scripts:

$k = new Apache::Keywords;
     Make a new Apache::Keywords object and return it.

$k->name(<name>);
     Sets the name of the cookie that is used for the personal profile.
     Without argument, the function returns the name of the cookie.

$k->expires(<expiration time>);
     Sets the cookie parameter for expiration. Without argument, the
     function returns the expiration time already set.

$k->path(<path>);
     Sets the path to be associated with the cookie. Without argument, the
     function returns the path already set.

$k->domain(<domain name>);
     Sets the domain name to be associated with the cookie.  Without
     argument, the function returns the domain name already set.

$k->new_keywords($r,<string with keywords>);
     Add the new keywords of this HTTP-call. The argument is a string with
     the different words separated with space. $r is the Apache mod_perl
     request object.

$k->new_keywords_asp($Request,<string with keywords>);
     A special version of new_keywords() suited for Apache::ASP. The
     $Request object is special for Apache::ASP.

$k->profile;
     Return the profile in a hash reference, e.g. profile->{'horse'} == 3,
     profile->{'dog'} == 2.

$k->profile_asp
     A special version of profile() suited for Apache::ASP. The $Request
     is special for Apache::ASP.

AUTHOR
======

   Copyright 2000 Magnus Cedergren, mace@lysator.liu.se

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl transparent language support for Apache modules and mod_perl scripts
*************************************************************************

NAME
====

   Apache::Language - Perl transparent language support for Apache modules
and mod_perl scripts

SYNOPSIS
========

     In YourModule.pm:

     sub handler {
     my $r = shift;
     use Apache::Language;
     my $lang = Apache::Language->new($extra_args);
     #$lang is now a hash ref that will automacigally pick the right language

     print $lang->{'Error01'} if exists $lang->{'Error01'};

     foreach ( keys %$lang ){
       print "$_ is " . $lang->{$_};
       }

     [...]
     }

DESCRIPTION
===========

   The goal of this module is to provide a simple way for mod_perl module
writers to include support for multiple language requests.

   This is version 0.03, and it's a complete rewrite from the ground-up of
the previous release.  It's still backward-compatible with the other
releases, but now it's much more advanced.

   An Apache::Language object acts like a language-aware hash.  It stores
key/language/values triplets. Using the Accept-Language: field sent by the
web-client, it can pick the best fit language for that specific client.
It's usage is transparent and should prove to be quite convenient (and
hopefully, efficient).

   The method used to store/fetch information is now completely modular
and will allow easy creation of new storage methods thru a simple API (see
the API section).

BASIC USAGE EXAMPLE
-------------------

   This section will describe the easiest way to start using
Apache::Language.

   Apache::Language is used to create a hash that will contain
key/language/value triplets.  Say you are building a module that prints a
few error messages, but since your users speak 3 different languages, you'd
like your module to be nice to them and print the messages in their native
language.

   For this approach to work, a few things are needed.  First, the client
software (Netscape/IE/lynx, etc.) should send an Accept-Language: header
telling the webserver what languages it's user understands.  This might
sound simple, but as a web-surfer, did you set that language setting in
your browser?  Most likely, you didn't.  So the first step is to correctly
configure your browser and try to make sure your users/visitors will have
done the same, or they might not get what you want them to read.

   Secondly, you must store the messages you want to display in each
avaliable languages.  For this example, we will use the default
LanguageHandler Apache::Language::PlainFile that ships with this
distribution.  To do that, suppose your module is named Apache::MyModule
and it's stored in a file named MyModule.pm.  You will only need to edit a
file named MyModule.dic in the same place your module is stored.  The
format of that file is : (for more information see
Apache/Language/PlainFile,(3)).

     error01:en

     Error Message 01

     error01:fr

     Message d'erreur 01

     error02:en

     Error Message 02

   Once that file contains your error messages, you're all set.  Just add
this to the top of your module:

     use Apache::Language
     my $lang = Apache::Language::new($extra_args)

   Then $lang will be a language-enabled hash reference that you can use
like this:

     print $lang->{error01}

   That line will print your error message 01 in the best language for the
client that your module served. Of course, there are a lot more things you
can do with Apache::Language.  All these features are explained below.

DETAILLED USAGE
===============

   The key to using Apache::Language is to understand the the data
retrieving/storing is now done in a manner similar to mod_perl content
handlers.  That's why I called them Language Handlers.  A language handler
is a perl module that is specialized in storing/fetching
key/language/values triplets.

   Apache::Language simply manages those modules and makes interaction
with other modules painless.  For every request, Apache::Language
maintains a stack of the LanguageHandlers configured for that request's
location.  Asking each of them in order to try finding a value for the
requested key that would satisfy the client acceptable languages.

   That way you can have a number of language handlers, one looking up in
a system-wide dictionnary, one looking up in a module-specific dictionnary
and one looking up a RDBM.  Each of them would be queried until an
acceptable response is found.  This makes maintaining language definitions
pretty versatile and configurable.

   With this package is shipped 2 basic LanguageHandlers:
Apache/Language/PlainFile, and
Apache/Language/DBI.  Check out their respective man
pages for more specific information.  And more of those LanguageHandlers
will be shipped in future versions and if you need a specific language
handling module, simply write your own.  Read the API section for more
information about writing your own LanguageHandlers and check the 2
mentionned above, they are nice examples.

CONFIGURATION DIRECTIVES
========================

   There are a some configurations directives you can use to customize how
Apache::Language handles requests.

LanguageHandler
     This is the main directive.  It sets the language handlers for a
     specific location.  It's usage is like IndexOptions.  Meaning it
     supports +/- notations.

     With a list of handlers without any +/- signs it simply sets the
     handler stack for the current location to those.

     With a list of handlers all with +/- signs, it merges them with the
     parent configuration:

          LanguageHandler Apache::Language::handler1 Apache::Language::handler2
          <Location /test/>
          LanguageHandler +Apache::Language::handler3 -Apache::Language::handler2
          </Location>

     Will result in a handler stack of [Apache::Language::Handler1 ,
     Apache::Language::Handler3] for requests in the /test/ directory

     2 things to note though:

     The default handler (Apache::Language::PlainFile) will always be the
     last handler in the stack.

     If a module isn't found, it will be tried again with
     Apache::Language:: prepended to it, so you can write LanguageHandler
     handler2 instead of LanguageHandler Apache::Language::handler2

LanguageForced
     This directive is given a list of languages that should exclusively
     be tried to please the client.  This a way to mark a certain
     <Location> as specifically danish, for example.  If no definition is
     found for that language, the standard 'sorry, no language definition
     found' message is printed.

LanguageDefault
     Provided with a list of languages, this directives sets the default
     languages it should try to send if none of the languages requested by
     the client can be found.

DefaultLanguage
     This is a not an Apache::Language directive, but in the absence of a
     LanguageDefault directive, that setting will be used to set the
     default languages

LanguageDebug
     This will set the level of debugging information sent to the
     apachelog.  Values ranges from 0-4. 4 being *very* noisy and 0 very
     quiet.  0 will still warn you about fatal errors.  A setting of -1
     simply doesn't log anything. Nothing.

     There are also a few other debugging options avaliable

     LanguageDebug Prefix=( LanguageDebug Postfix=) LanguageDebug
     NotFoundPrefix=[[[ LanguageDebug NotFoundPostfix=]]]

     They will prefix/postfix language tokens with the specified
     delimiters with special symbols, usefull for debugging

STATUS Handler
==============

   If you have the Apache::Status module loaded before Apache::Language, a
custom status module will be installed.  Usually accessed thru
/perl-status, it will give you an Apache::Language menu with quite a few
bits of interesting information about Apache::Language status.

API
===

   The Apache::Language API is pretty simple and might evolve in future
versions.  The first argument to all function calls will be the class name
of the handler.

   The API was developped to provide for: 1. abstraction of the data
storage/retrieval and 2.  an easy way for other developpers to write new
containers without having to modify the whole package.

   If you want to write your own Language::Handler, read on.  You might
also find more interesting information by looking at the couple of
LanguageHandlers distributed as part of the Apache::Language package.  I
also think that new LanguageHandlers should be named under the
Apache::Language::* namaspace for simplicity.  As of this writing I am
have quite a few other LanguageHandlers on the way, so if you are planning
on writing a new one, get in touch with me before, maybe I already have
some work done I'd be happy to send you.

   There is one thing that you must understand before writing your own
LanguageHandler.  It's how Apache::Language caches information about
LanguageHandlers.  For performance reasons, and since most mod_perl
scripts/modules will want to have their own language definitions,
information is cached on a per-Module/script basis.  This means that
suppose the module Apache::MyHandler uses Apache::Language, all
LanguageHandlers serving requests for Apache::MyHandler will be given
access to a cache ($data) that's specific to Apache::MyHandler and to
another cache that's specific to Apache::MyHandler and the current
LanguageHandler.  In the case that a certain handler doesn't want this
degree of encapsulation (i.e. a dictionnary of common used error messages,
system wide) it's free to maintain it's own cache (in it's namespace) and
disregard the Module & Handler specific cache.  That cache is merely
provided so LanguageHandler writers won't have to deal with per Module
cache themselves.  But you can do without it.

   This is what a small dump of the cache might look like : (For the
visual types)

   #Cached information for the mod_perl Handler Apache::MyHandler1 $VAR1 =
'Apache::MyHandler1'; $VAR2 = bless( {      #current LanguageHandler stack
    'Handlers' => [                      'Apache::Language::Handler1',
                 'Apache::Language::Handler2'                    ],
'Request' => [Apache $r object]      #Filename of the Calling package
'Filename' => '/usr/lib/perl5/Apache/MyHandler1.pm',      #Language
requested by the client      'Lang' => [                  'en',
     'fr-ca',                  'fr'                ],       #Package name
of the Calling package      'Package' => 'Apache::MyHandler1',
#Specific data for LanguageHandler Apache::Language::Handler1
'Apache::Language::Handler1' => {           #Is the LanguageHandler a
listable one?            'listable' => 1,           'DATA' => {  #this is
the $cfg object passed to the handler                        #it's
completely private to the Language::Handler                       'dbname'
=> 'DBI::Pg',                       'query' => 'select value from language
where key=? and lang=?'                      },            #Is the
LanguageHandler a storable one?            'storable' => 1            },
    #Specific data for LanguageHandler Apache::Language::Handler2
'Apache::Language::Handler2' => {           #Is the LanguageHandler a
listable one?            'listable' => 0,           'DATA' => {  #this is
the $cfg object passed to the handler                        #it's
completely private to the Language::Handler
'option1' => 'read/write',                       'debug'   => 1
        },           #Is the LanguageHandler a storable one?
'storable' => 1           },      'Config' =>  [Opaque structure for
directory configuration]

     }, 'Apache::Language' );

   #Cached information for the mod_perl Handler Apache::MyHandler2 $VAR3 =
'Apache::MyHandler2'; $VAR4 = bless( {      #current LanguageHandler stack
    'Handlers' => [                      'Apache::Language::Handler2'
              ],      'Request' => [Apache $r object]      #Filename of
the Calling package      'Filename' =>
'/usr/lib/perl5/Apache/MyHandler1.pm',      #Language requested by the
client      'Lang' => [                  'en',                  'fr-ca',
              'fr'                ],      #Package name of the Calling
package      'Package' => 'Apache::MyHandler1',

     #Specific data for LanguageHandler Apache::Language::Handler2
     'Apache::Language::Handler2' => {
          #Is the LanguageHandler a listable one?
          'listable' => 0,
          'DATA' => {  #this is the $cfg object passed to the handler
                       #it's completely private to the Language::Handler
                      'dbname' => 'DBI::mysql',
                      'query' => 'select value from language2 where key=? and lang=?'
                    },
          #Is the LanguageHandler a storable one?
          'storable' => 1
          },
     'Config' =>  [Opaque structure for directory configuration]
        }, 'Apache::Language' );

API data structures
-------------------

   All functions calls to LanguageHandlers are passed these 2 data
structures as the second and third arguments.  The first argument always
being the class name of the LanguageHandler.

   $data

   This is the data associated with the particular http request.  It's
also unique to the currently served Module, so it can be used to store
some information, but since Apache::Language stores a few things of itself
there, be carefull to use keys unique to your module (i.e.
$data->{"Apache::Language::YourHandler::key"} = "private data") It's an
Apache::Language object with the following calls avaliable:

lang()
     returns a preference-sorted list of the language the clients
     requested.

handlers()
     returns the current LanguageHandler stack (list)

request()
     returns the current request (Apache::Request)

package()
     returns the name of the package handling the request

filename()
     returns the filename of the package handling the request

extra_args()
     returns a reference to a list of what was passed to the new
     constructor

   *$cfg*

   This is a private storage space for the current Handler.  Handlers can
store whatever they want there.  That data will be preserved for this
Handler/(Calling module/package) pair.  Look in
Apache::Language::PlainFile for a good exapmle of using that.

Required API functions
----------------------

initialize ($data, $cfg)
     This is called for the first request so a LanguageHandler can do it's
     initialization.  This will also be called each time a call to the
     modified() function informs Apache::Language that something has
     changed.

     It has the opportnity to examine the requesting conditions and if it
     chooses not to be involved in the handling of that specific
     requesting Module, it should return anything but L_OK.  That way it
     will be removed from the LanguageHandler stack for that Module and
     therefore will not be called for that Module anymore

modified ($data, $cfg)
     This is called for each request to know if the datasource changed and
     should be re-initialized.  It should return true if something is
     modified and re-initialization is needed.

fetch ($data, $cfg, $key, $lang)
     This function can be called in 2 ways.  First if there $lang is
     defined, the LanguageHandler is requested to produce that exact
     language version for the key $key. This happends if a user requested
     a specific language with $lang->{key/lang} or to find an entry for
     the default language if everything else failed to produce a value.
     It should return undef if unknown.

     Second, if $lang is undefined, this means that the Handler should try
     to return the best possible match for the current request.
     $data->lang will return the list of language the client understands,
     sorted preferred first.  But since language-tags allow for variants
     and dialects, it's now always easy for a module to determine what
     language it should pick if it knows 'en-us' and 'en' and the clients
     understands 'en-ca' and 'de'.

Everything else
     If a call is made to an unknown routine, Apache::Language will try to
     call it on each Handler in the current handler stack until someone
     can deal with that function call.  The call is made with ($data,
     $cfg, @args) as arguments.   @args being the arguments passed to that
     function by the calling user.  Remember that to get at the new()
     arguments, you just have to do a @args = @{$data->extra_args()};

     To simplyfy some things, there is the helper function
     $data->best_lang described below.

Helper API Functions
--------------------

$data->best_lang(@avaliable_language)
     This is the generic best-language picking routine.  This function
     given the list of known languages to the handler, returns the best
     language based on the client's request.

     For example, a simple handler could handle queries like this:

          sub fetch {
             my ($class, $data, $cfg, $key, $lang) = @_;
             #the language information is kept in the $cfg hash

          #if a specific language is asked for:
          return $cfg->{$key}{$lang} if $lang;

          #we must choose the right language ourself.
          #(keys % {$cfg->{$key}}) produces the list of languages in wich $key is known
          my $variant = $data->best_lang(keys % {$cfg->{$key}});

          #$variant now holds the best pick for us, or undef if nothing matches..
          return $cfg->{$key}{$variant} if $variant;

          #give up
          return undef;
           }

Optionnal API Functions (store)
-------------------------------

   store ($data, $cfg ,$key, $lang, $value)

   If this function is present, the handler will be makred as 'storable'
and any assignments to the language hash will call this function.  Storing
in a language hash should be done by providing a key/language pair as key
to the hash (ie. $lang->{key01/en-us} = "string").  This should return
L_OK on success and L_ERROR in case of an error.

Optionnal API Functions (firstkey/nextkey)
------------------------------------------

   This are functions necessary to make the Language hash listable (i.e.
keys and each).  The tricky thing is that since LanguageHandlers are
stackable and often each have a change at the request, listing a specific
language hash is ambiguious.  The way it's handled is straightforward.
The first listable module that returns something else than undef on the
call to firstkey is the chosen one.  It will be used to list the hash
until it's nextkey function returns undef, and all subsequent list request
will be handled by that module.

   It should be noted that I don't really know what might happend in the
case of recursive/re-entrant lists, so if you don't want to spend time
fixing it yourself, be carefull about that.

   These functions follow exactly the same rules as the generic TIEHASH
mechanism.  So, for more information see Perltie (perl.info),

firstkey ($data, $cfg)
     This will be called first when a list request is encountered.  It
     should return the first key of the hash and set up things for the
     nextkey calls.

nextkey ($data, $cfg, $lastkey)
     This will be called once the listing of the language hash has
     started.  Make sure it will eventually return undef to mark the end
     of the list or else you will end up in an infinite loop.

TODO
====

   * Find and correct bugs.

   * Find new features to add.

SEE ALSO
========

   perl(1), see Apache,(3), see Apache/Language/Constants,
(3), and all `Apache::Language::*' in this node.

SUPPORT
=======

   Please send any questions or comments to the Apache modperl mailing
list <modperl@apache.org> or to me at <gozer@ectoplasm.dyndns.com>

NOTES
=====

   This code was made possible by :

   * Doug MacEachern <dougm@pobox.com>  Creator of mod_perl.  That should
     mean enough.

   * Andreas Koenig <koenig@kulturbox.de> The one I got the idea from in
     the first place.

   * The mod_perl mailing-list at <modperl@apache.org> for all your
     mod_perl related problems.

AUTHOR
======

   Philippe M. Chiasson <gozer@ectoplasm.dyndns.com>

VERSION
=======

   This is revision $Id: Language.pod,v 1.2 1999/04/18 22:02:37 gozer Exp $

COPYRIGHT
=========

   Copyright (c) 1999 Philippe M. Chiasson. All rights reserved. This
program is free software, you can redistribute it and/or modify it under
the same terms as Perl itself.

Apache::Language constants for use by LanguageHandlers
******************************************************

NAME
====

   Apache::Language::Constants - Apache::Language constants for use by
LanguageHandlers

SYNOPSIS
========

     use Apache::Language::Constants;

DESCRIPTION
===========

   These are constants LanguageHandlers can use to return status
information to Apache::Language.  The constants and their respective
signification are as follow:

L_OK
     Return with this value whenever something correctly ends

L_ERROR
     Return with this value whenever something bad has happened.  By bad,
     I mean something that will prevent you to complete the required task
     and that some form of error should be generated in the logs.

L_DECLINED
     return with this value in the initialize routine to indicate you are
     not interested in being called to answer queries for that package.
     How you decide this is up to you.

   Remember to return undef when a search retrieves nothing and all will
be ok.

SEE ALSO
========

   perl(1), see Apache,(3), see Apache/Language,
(3).

SUPPORT
=======

   Please send any questions or comments to the Apache modperl mailing
list <modperl@apache.org> or to me at <gozer@ectoplasm.dyndns.com>

AUTHOR
======

   Philippe M. Chiasson <gozer@ectoplasm.dyndns.com>

COPYRIGHT
=========

   Copyright (c) 1999 Philippe M. Chiasson. All rights reserved. This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

DBI interface for Apache::Language
**********************************

NAME
====

   Apache::Language::DBI - DBI interface for Apache::Language

SYNOPSIS
========

     <Location /under/language/control/>
     PerlSetVar Language::DBI::Datasource  DBI:Pg:dbname=database;host=database.host
     PerlSetVar Language::DBI::Username webserver
     PerlSetVar Language::DBI::Password unguessable
     PerlSetVar Language::DBI::TableName language [default]
     Language::DBI::TableKey		key 	[column for the key]
     Language::DBI::TableLang		lang	[column for the lang]
     Language::DBI::TableValue 	value [column for the value]
     LanguageHandler Apache::Language::DBI
     </Location>

DESCRIPTION
===========

   This LanguageHandler implements a per-location DBI dictionnary.  It
looks-up a given table for a matching language/key pair and returns the
best possible match.

   The configurable directives are pretty self-explanatory.

TODO
====

   Some sort of caching could be done.

SEE ALSO
========

   perl(1), see Apache,(3), see Apache/Language,
(3) See Apache/Language/Constants,
(3), and all `Apache::Language::*' in this node.

SUPPORT
=======

   Please send any questions or comments to the Apache modperl mailing
list <modperl@apache.org> or to me at <gozer@ectoplasm.dyndns.com>

NOTES
=====

   This code was made possible by :

   * Doug MacEachern <dougm@pobox.com>  Creator of mod_perl.  That should
     mean enough.

   * Andreas Koenig <koenig@kulturbox.de> The one I got the idea from in
     the first place.

   * The mod_perl mailing-list at <modperl@apache.org> for all your
     mod_perl related problems.

AUTHOR
======

   Philippe M. Chiasson <gozer@ectoplasm.dyndns.com>

COPYRIGHT
=========

   Copyright (c) 1999 Philippe M. Chiasson. All rights reserved. This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Default LanguageHandler under Apache::Language
**********************************************

NAME
====

   Apache::Language::PlainFile - Default LanguageHandler under
Apache::Language

SYNOPSIS
========

     Since it's the default handler, it never needs to be activated.

DESCRIPTION
===========

   This is the default LanguageHandler under Apache::Language.  It
searches language definitions for a specific script/module in a file with
a corresponding name.  For a script, it's the scriptname with a .dic
added.  For a module, simply replace the .pm with a .dic

   That file must reside in the same directory as the script/module it
describes, and be readable by the web-server process.  The format of that
file is as follows:

   language-tag:Key

   Content for 'language' version of 'Key'

   language-tag:Key

   [...]

   The only really important thing is to make sure that entries are
separated with completely blank lines.

TODO
====

   Nothing for now.

SEE ALSO
========

   perl(1), see Apache,(3), see Apache/Language,
(3) See Apache/Language/Constants,
(3), and all `Apache::Language::*' in this node.

SUPPORT
=======

   Please send any questions or comments to the Apache modperl mailing
list <modperl@apache.org> or to me at <gozer@ectoplasm.dyndns.com>

NOTES
=====

   This code was made possible by :

   * Doug MacEachern <dougm@pobox.com>  Creator of mod_perl.  That should
     mean enough.

   * Andreas Koenig <koenig@kulturbox.de> The one I got the idea from in
     the first place.

   * The mod_perl mailing-list at <modperl@apache.org> for all your
     mod_perl related problems.

AUTHOR
======

   Philippe M. Chiasson <gozer@ectoplasm.dyndns.com>

COPYRIGHT
=========

   Copyright (c) 1999 Philippe M. Chiasson. All rights reserved. This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

LanguageHandler for SmartWorker Applications
********************************************

NAME
====

   Apache::Language::SW - LanguageHandler for SmartWorker Applications

SYNOPSIS
========

     sub new
     {
        my $classname = shift;
     	   my $self = $classname->SUPER::new(@_);
        $self->{Language} = new Apache::Language($self);
        [...]
     }

        [...]
        -text => $self->{Language}{"keyName1"},
        [...]

        #outside a FormPanel
        $Panel->addElement(x,y,$self->{Language}->getLanguagePicker());

        #inside a FormPanel
        $Panel->addElement(x,y,$self->{Language}->getLanguagePicker("formPanel1));
        [...]

DESCRIPTION
===========

   This is the new way to handle Language in SW::Applications.  The
interface is a tied hash, so you can use the object returned by
Apache::Language like any other hash reference.

   There are also a few function calls you can make on it, like the
getLanguagePicker() sub that returns a Language picker panel ready to
insert in your application.

   The only restriction with this module is that it uses the 'Lang' key to
find wanted languages.  So it sets it in the Session/Data stuff.  So don't
do this:

     $self->{Lang} = "I love perl";
     or
     $self->setSessionValue("Lang","I love perl");
     ok ?

     But you can look at it if you want to know what language are requested by the user,
     but I advise against it.

METHODS
=======

     getLanguagePicker - Returns a formpanel with a correct language picker for the current user.

     Arguments : if already in form context, call it with the name of the formpanel you are adding it to.

AUTHOR
======

   Philippe M. Chiasson HBE	gozer@hbe.ca Sept  9/99

REVISION HISTORY
================

     $Log$

SEE ALSO
========

   perl(1).

   Apache::Language(3).

   Apache::Language::*(3).

Layer content tree over one or more others.
*******************************************

NAME
====

   Apache::Layer - Layer content tree over one or more others.

SYNOPSIS
========

     #httpd.conf
     PerlTransHandler Apache::Layer

     # anywhere you can configure a location
     <Location /project/images>
         PerlSetVar apache_layer_location /project/images
         PerlSetVar apache_layer_path     /dir1/root;/dir2/root
     </Location>

DESCRIPTION
===========

   This module is designed to allow multiple content trees to be layered
on top of each other within the Apache server.

   I developed this module because we produce lots of web sites where a
high proportion of the site content is common.  But where specific pages /
images are tailored to the specific project.  This module allows us to
layer a sparse directory tree on top of the main complete tree without
requiring redirects.

   The essence is that it will cause Apache to deliver content from a
series of directories in turn.

   In some ways Apache::Layer is similar to Apache::Stage however it does
not require redirects.

COMMON PROBLEMS
===============

   Apache::Layer is relatively simple.  The most common problem is not
setting the apache_layer_location parameter correctly.  As a rule this
parameter should ALWAYS match the parameter within the location i.e.
<Location /parameter>.

AUTHOR
======

   Simon Matthews <sam@peritas.com>

REVISION
========

   $Revision: 1.7 $

COPYRIGHT
=========

   Copyright (C) 1998 Simon Matthews.  All Rights Reserved.

   This module is free software; you can distribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   Apache::Stage

Module for tracking memory leaks in mod_perl code
*************************************************

NAME
====

   Apache::Leak - Module for tracking memory leaks in mod_perl code

SYNOPSIS
========

     use Apache::Leak;

     leak_test {
     	my $obj = Foo->new;
     	$obj->thingy;
     };
     #now look in error_log for results

DESCRIPTION
===========

   "Under Construction."

SEE ALSO
========

   Devel::Leak

AUTHOR
======

   Doug MacEachern Leak.xs derived from Nick Ing-Simmons' Devel::Leak

Interface to Apache logging
***************************

NAME
====

   Apache::Log - Interface to Apache logging

SYNOPSIS
========

     use Apache::Log ();
     my $rlog = $r->log;
     $rlog->debug("You only see this if `LogLevel' is set to `debug'");

     my $slog = $r->server->log;

DESCRIPTION
===========

   The Apache::Log module provides an interface to Apache's *ap_log_error*
and *ap_log_rerror* routines.

emerg
alert
crit
error
warn
notice
info
debug
AUTHOR
======

   Doug MacEachern

SEE ALSO
========

   mod_perl(3), Apache(3).

Interface to Apache's logging routines
**************************************

NAME
====

   Apache::LogFile - Interface to Apache's logging routines

SYNOPSIS
========

     #in httpd.conf
     PerlModule Apache::LogFile
     PerlLogFile |perl/mylogger.pl My::Logger

     #in a Perl script
     print My::Logger "a message to the Log"

DESCRIPTION
===========

   The *PerlLogFile* directive can be used to hook a Perl filehandle to a
piped logger or to a file open for appending.  If the first character of
the filename is a |, the file handle is opened as a pipe to the given
program.  The file or program can be relative to the *ServerRoot*.

   The method interface was written before mod_perl directive handlers were
introduced, but it still works so the documentation remains below:

   The new method should be called by a server startup script or module.

   The last argument to new is optional, it is simply a name that can be
used to retrive the filehandle via the handle method.

     #in a startup file
     use Apache::LogFile ();
     Apache::LogFile->new("|perl/mylogger.pl", "MyLogger");

     #in a request-time file
     use Apache::LogFile ();
     my $fh = Apache::LogFile->handle("MyLogger");
     print $fh "a message to the log";

   If this argument is not present, the filename will be used the handle
key, which can also be retrived via the handle method.  The new method
will return a reference to the filehandle if you wish to store it
elsewhere, e.g.:

     $MyLog::Pipe = Apache::LogFile->new("|perl/mylogger.pl");

     $MyLog::Append = Apache::LogFile->new("logs/my_log");

AUTHOR
======

   Doug MacEachern

SEE ALSO
========

   Apache(3), mod_perl(3)

Generate streamable directories of MP3 files
********************************************

NAME
====

   Apache::MP3 - Generate streamable directories of MP3 files

SYNOPSIS
========

     # httpd.conf or srm.conf
     AddType audio/mpeg     mp3 MP3
     AddType audio/playlist m3u M3U

     # httpd.conf or access.conf
     <Location /songs>
       SetHandler perl-script
       PerlHandler Apache::MP3
     </Location>

     # Or use the Apache::MP3::Sorted subclass to get sortable directory listings
      <Location /songs>
      SetHandler perl-script
      PerlHandler Apache::MP3::Sorted
      </Location>

     # Or use the Apache::MP3::Playlist subclass to get persistent playlists
      <Location /songs>
      SetHandler perl-script
     PerlHandler Apache::MP3::Playlist
      </Location>

   A *demo version* can be browsed at http://www.modperl.com/Songs/.

DESCRIPTION
===========

   This module makes it possible to browse a directory hierarchy
containing MP3 files, sort them on various fields, download them, stream
them to an MP3 decoder like WinAmp, and construct playlists.  The display
is configurable and subclassable.

   NOTE: This version of Apache::MP3 is substantially different from the
pre-2.0 version described in The Perl Journal.  Specifically, the format
to use for HREF links has changed.  See *Linking* for details.

Installation
------------

   This section describes the installation process.

  1. Prequisites This module requires mod_perl and MP3::Info, both of
     which are available on CPAN.

  2. Configure MIME types Apache must be configured to recognize the mp3
     and MP3 extensions as MIME type audio/mpeg.  Add the following to
     httpd.conf or srm.conf:

          AddType audio/mpeg mp3 MP3
          AddType audio/playlist m3u M3U

  3. Install icons and stylesheet This module uses a set of icons and a
     cascading stylesheet to generate its song listings.  By default, the
     module expects to find them at the url /apache_mp3.  Create a
     directory named apache_mp3 in your document root, and copy into it
     the contents of the `apache_mp3' directory from the Apache-MP3
     distribution.

     You may change the location of this directory by setting the BaseDir
     configuration variable.  See the Customizing section for more details.

  4. Set Apache::MP3 to be the handler for the MP3 directory In httpd.conf
     or access.conf, create a <Location> or <Directory> section, and make
     Apache::MP3 the handler for this directory.  This example assumes you
     are using the URL /Songs as the directory where you will be storing
     song files:

          <Location /Songs>
            SetHandler perl-script
            PerlHandler Apache::MP3
          </Location>

     If you would prefer an MP3 file listing that allows the user to sort
     it in various ways, set the handler to use the Apache::MP3::Sorted
     subclass instead.  A further elaboration is Apache::MP3::Playlist,
     which uses cookies to manage a persistent playlist for the user.

  5. Load MP3::Info in the Perl Startup file (optional) For the purposes
     of faster startup and memory efficiency, you may load the MP3::Info
     module at server startup time.  If you have a mod_perl "startup"
     file, enter these lines:

          use MP3::Info;
          use Apache::MP3;

  6. Set up MP3 directory Create a directory in the web server document
     tree that will contain the MP3 files to be served.  The module
     recognizes and handles subdirectories appropriately.  I suggest
     organizing directories hierarchically by artist and/or album name.

     If you place a file named "cover.jpg" in any of the directories, that
     image will be displayed at the top of the directory listing.  You can
     use this to display cover art.

     If you place a list of .mp3 file names in a file with the .m3u
     extension, it will be treated as a playlist and displayed to the user
     with a distinctive icon.  Selecting the playlist icon will download
     the playlist and stream its contents.  The playlist must contain
     relative file names, but may refer to subdirectories, as in this
     example:

          # file: folk_favorites.m3u
          Never_a_Moment_s_Thought_v2.mp3
          Peter Paul & Mary - Leaving On A Jet Plane.mp3
          Simon and Garfunkel/Simon And Garfunkel - April Come She Will.mp3

  7. Set up an information cache directory (optional) In order to generate
     its MP3 listing, Apache::MP3 must open each sound file, extract its
     header information, and close it.  This is time consuming,
     particularly when recursively generating playlists across multiple
     directories.  To speed up this process, Apache::MP3 has the ability
     cache MP3 file information in a separate directory area.

     To configure this, choose a directory that the Web server has write
     access for, such as /usr/tmp.  Then add a configuration variable like
     the following to the <Location> directive:

          PerlSetVar  CacheDir       /usr/tmp/mp3_cache

     If the designated directory does not exist, Apache::MP3 will attempt
     to create it, limited of course by the Web server's privileges.  You
     may need to create the mp3_cache directory yourself if /usr/tmp is not
     world writable.

        Open up the MP3 URL in your favorite browser.  You should be able
to see directory listings, and download and stream your songs.  If things
don't seem to be working, checking the server error log for messages.

CUSTOMIZING
===========

   Apache::MP3 can be customized in three ways: (1) by changing
per-directory variables; (2) changing settings in the Apache::MP3
cascading stylesheet; and (3) subclassing Apache::MP3 or
Apache::MP3::Sorted.

Per-directory configuration variables
-------------------------------------

   Per-directory variables are set by PerlSetVar directives in the
Apache::MP3 <Location> or <Directory> section.  For example, to change the
icon displayed next to subdirectories of MP3s, you would use PerlSetVar to
change the DirectoryIcon variable:

     PerlSetVar DirectoryIcon big_cd.gif

   This following table summarizes the configuration variables.  A more
detailed explanation of each follows in the subsequent sections.

   Table 1: Configuration Variables

     Name                  Value	        Default
     ----                  -----            -------
     GENERAL OPTIONS
     AllowDownload	       yes|no		yes
     AllowStream	       yes|no		yes
     AllowPlayLocally      yes|no           yes
     CheckStreamClient     yes|no		no
     ReadMP3Info	       yes|no		yes
     StreamTimeout         integer          0

     DIRECTORY OPTOINS
     BaseDir	       URL		/apache_mp3
     CacheDir              path             -none-
     HelpURL               URL              apache_mp3_help.gif:614x498
     StreamBase            URL              -none-

     DISPLAY OPTIONS
     ArrowIcon	       URL		right_arrow.gif
     CoverImage            filename         cover.jpg
     DescriptionFormat     string           -see below-
     DirectoryIcon	       URL		cd_icon_small.gif
     PlaylistIcon          URL              playlist.gif
     Fields                list             title,artist,duration,bitrate
     HomeLabel	       string		"Home"
     LongList	       integer		10
     PathStyle             Staircase|Arrows Staircase
     SongIcon	       URL		sound.gif
     SubdirColumns	       integer		3
     Stylesheet	       URL		apache_mp3.css
     TitleIcon	       URL		cd_icon.gif

General Configuration Variables
-------------------------------

AllowDownload *yes|no*
     You may wish for users to be able to stream songs but not download
     them to their local disk.  If you set AllowDownload to "no",
     Apache::MP3 will not generate a download link for MP3 files.  It will
     also activate some code that makes it inconvenient (but not
     impossible) for users to download the MP3s.

     The module recognizes the arguments "yes", "no", "true" and "false".
     The default is "yes".

     Note that this setting only affects MP3 files.  Other files, including
     cover art and playlists, can still be downloaded.

AllowStream *yes|no*
     If you set AllowStream to "no", users will not be able to stream songs
     or generate playlists.  I am not sure why one would want this feature,
     but it is included for completeness.  The default is "yes."

AllowPlayLocally *yes|no*
     If you set AllowPlayLocally to "yes", then the playlists generated by
     the module will point to the physical files when handling requests
     from a user that happens to be working on the same machine.  This is
     more efficient, and allows the user to pause playback, fast forward,
     and so on.  Otherwise, the module will treat local users and remote
     users the same.  The default is "no".

CheckStreamClient *yes|no*
     Setting CheckStreamClient to "yes" enables code that checks whether
     the client claims to be able to accept streaming MPEG data.  This
     check isn't foolproof, but supports at least the most popular MP3
     decoders (WinAmp, RealPlayer, xmms, mpg123).  It also makes it harder
     for users to download songs by pretending to be a streaming player.

     The default is "no".

ReadMP3Info *yes|no*
     This controls whether to extract field information from the MP3
     files.  The default is "yes".

     If "no" is specified, all fields in the directory listing will be
     blank except for filename and description, which will both be set to
     the physical filename of the MP3 file.

StreamTimeout integer
     For demo mode, you can specify a stream timeout in seconds.
     Apache::MP3 will cease streaming the file after the time specified.
     Because this feature uses the average bitrate of the song, it may be
     off by a second or two when streaming variable bitrate MP3s.

Configuration Variables Affecting Paths and Directories
-------------------------------------------------------

BaseDir URL
     The BaseDir variable sets the URL in which Apache::MP3 will look for
     its icons and stylesheet.  You may use any absolute local or remote
     URL. Relative URLs are not accepted.

     The default is "/apache_mp3."

CacheDir path
     This variable sets the directory path for Apache::MP3's cache of MP3
     file information.  This must be an absolute path in the physical file
     system and be writable by Apache.

HelpURL *URL:widthxheight*
     The URL of the page to display when the user presses the "Quick Help
     Summary" link at the bottom of the page.  In the current
     implementation, the module pops up a plain window containing a
     marked-up GIF of a typical page. You can control the size of this page
     by adding ":WxH" to the end of the URL, where W and H are the width
     and height, respectively.

     Default: apache_mp3_help.gif:614x498

     Note: I prepared this image on an airplane, so it isn't as clean as I
     would like.  Volunteers to make a better help page are welcomed!

StreamBase URL
     A URL to use as the base for streaming.  The default is to use the
     same host for both directory listings and streaming.  This may be of
     use for transparent reverse proxies or for situations in which you
     want one server to generate the index, and the other to service the
     stream requests.

     Example:

     If the song requested is
     http://www.foobar.com/Songs/Madonna_live.m3u?stream=1

     and StreamBase is set to *http://streamer.myhost.net*, then the URL
     placed in the playlist will be

          http://streamer.myhost.net/Songs/Madonna_live.m3u?stream=1

     The path part of the URL is simply appended to StreamBase.  If you
     want to do more sophisticated URL processing, use *mod_rewrite* or
     equivalent.

Configuration Variables Affecting the Visual Display
----------------------------------------------------

ArrowIcon URL
     Set the icon used for the arrows displayed between the components of
     the directory path at the top of the directory listing.

CoverImage filename
     Before displaying a subdirectory, Apache::MP3 will look inside the
     directory for an image file.  This feature allows you to display
     digitized album covers or other customized icons.  The default is
     "cover.jpg", but the image file name can be changed with CoverImage.
     If the file does not exist, the image specified by TitleIcon will be
     displayed instead.

DescriptionFormat string
     The "Description" field, which is used both in the Description column
     of the directory index and in the metadata sent to the player during
     streaming, has a default format of title-artist-album.  The
     description is constructed in such a way that the hyphen is omitted if
     the corresponding field of the song's MP3 tag is empty.

     You can customize this behavior by providing a DescriptionFormat
     string.  These strings combine constant characters with %x format
     codes in much the way that sprintf() does.  For example, the directive
     shown below will create descriptions similar to *[Madonna] Like a
     Virgin (1980)*.

          PerlSetVar DescriptionFormat "[%a] %t (%y)"

     The full list of format codes follows:

     Table 2: DescriptionFormat Field Codes

          Code         Description
          ----         -----------

          %a	       Artist name
          %c	       Comment
          %d	       Duration, in format 00m00s
          %f	       Name of physical file (minus path)
          %g	       Genre
          %l	       Album name
          %m	       Minutes portion of duration, usually used with %s
          %n	       Track number
          %q	       Sample rate, in kHz
          %r	       Bitrate, in kbps
          %s	       Seconds portion of duration, usually used with %m
          %S	       Duration, expressed as total seconds
          %t	       Title
          %y	       Year

DirectoryIcon URL
     Set the icon displayed next to subdirectories in directory listings,
     "cd_icon_small.gif" by default.

PlaylistIcon URL
     Set the icon displayed next to playlists in the playlist listings,
     "playlist.gif" by default.

Fields *title,artist,duration,bitrate*
     Specify what MP3 information fields to display in the song listing.
     This should be a list delimited by commas, "|" symbols, or any other
     non-word character.

     The following are valid fields:

     Table 3: Field Names For use with the Fields Configuration Variable

          Field        Description
          -----        -----------

          album	 The album
          artist       The artist
          bitrate      The bitrate, expressed in kbps
          comment      The comment field
          duration     Duration of the song in hour, minute, second format
          description	 Description as specified by DescriptionFormat
          filename	 The physical name of the .mp3 file
          genre        The genre
          min          The minutes portion of the duration
          seconds      Total duration of the song in seconds
          sec          The seconds portion of the duration
          samplerate   The sampling rate, in KHz
          title        The title of the song
          track	 The track number
          year         The album year

     Note that MP3 rip and encoding software differ in what fields they
     capture and the exact format of such fields as the title and album.
     Field names are case insensitive.

     Previous versions of this module used "kbps" instead of "bitrate".
     This has been changed.

HomeLabel string
     This is the label for the link used to return to the site's home
     page.  You may use plain text or any fragment of HTML, such as an
     <IMG> tag.

LongList integer
     The number of lines in the list of MP3 files after which it is
     considered "long".  In long lists, the control buttons are placed at
     the top as well as at the bottom of the table.  Defaults to 10.

PathStyle *Staircase|Arrows*
     Controls the style with which the parent directories are displayed.
     The options are "Staircase" (the default), which creates a
     staircase-style display (each child directory is on a new line and
     offset by 0.3 em).  The other is "Arrows", in which the entire
     directory list is on a single line and separated by graphic arrows.
     Try them both and choose the one you prefer.

SongIcon URL
     Set the icon displayed at the beginning of each line of the MP3 file
     list, "sound.gif" by default.

SubdirColumns integer
     The number of columns in which to display subdirectories (the small
     "CD icons").  Default 3.

PlaylistColumns integer
     The number of columns in which to display playlists. Default 3.

Stylesheet URL
     Set the URL of the cascading stylesheet to use, "apache_mp3.css" by
     default.  If the URL begins with a slash it is treated as an absolute
     URL.  Otherwise it is interpreted as relative to the BaseDir
     directory.

TitleIcon URL
     Set the icon displayed next to the current directory's name in the
     absence of a coverimage, "cd_icon.gif" by default.  In this, and the
     other icon-related directives, relative URLs are treated as relative
     to BaseDir.

Stylesheet-Based Configuration
------------------------------

   You can change the appearance of the page by changing the cascading
stylesheet that accompanies this module, *apache_mp3.css*.  The following
table describes the tags that can be customized:

   Table 4: Stylesheet Class Names

     Class Name           Description
     ----------           ----------

     BODY                 General defaults
     H1                   Current directory path
     H2                   "CD Directories" and "Song List" headings
     TR.title             Style for the top line of the song listing
     TR.normal            Style for odd-numbered song listing lines
     TR.highlight         Style for even-numbered song listing lines
     .directory           Style for the title of the current directory
     .subdirectory        Style for the title of subdirectories
     P                    Ordinary paragraphs
     A                    Links
     INPUT                Fill-out form fields

Subclassing this Module
-----------------------

   For more extensive customization, you can subclass this module.  The
Apache::MP3::Sorted module illustrates how to do this.

   Briefly, your module should inherit from Apache::MP3 (or
Apache::MP3::Sorted) either by setting the `@ISA' package global or, in
Perl 5.6 and higher, with the `use base' directive.  Your module can then
override existing methods and define new ones.

   This module uses the mod_perl method invocation syntax for handler
invocation.  Because of this, if you override the handler() method, be
sure to give it a prototype of ($$).  If you override new(), be sure to
place the Apache::Request object in an instance variable named 'r'.  See
the MP3.pm module for details.

   One implication of using the method invocation syntax is that the
Apache::MP3 object is created at server configuration time.  This means
that you cannot tweak the code and simply restart the server, but must
formally stop and relaunch the server every time you change the code or
install a new version.  This disadvantage is balanced by a savings in
memory consumption and performance.

   See The Apache::MP3 API below for more information on overriding
Apache::MP3 methods.

Linking to this module
======================

   You may wish to create links to MP3 files and directories manually.
The rules for creating HREFs are different from those used in earlier
versions of Apache::MP3, a decision forced by the fact that the playlist
format used by popular MP3 decoders has changed.

   The following rules apply:

Download an MP3 file
     Create an HREF using the unchanged name of the MP3 file.  For example,
     to download the song at /songs/Madonna/like_a_virgin.mp3, use:

          <a href="/Songs/Madonna/like_a_virgin.mp3">Like a Virgin</a>

Stream an MP3 file
     Replace the MP3 file's extension with .m3u and add the query string
     "play=1".  Apache::MP3 will generate a playlist for the streaming MP3
     decoder to load.  Example:

          <a href="/Songs/Madonna/like_a_virgin.m3u?play=1">
                  Like a streaming Virgin</a>

Stream a directory
     Append "/playlist.m3u?Play+All=1" to the end of the directory name:

          <a href="/Songs/Madonna/playlist.m3u?Play+All=1">Madonna Lives!</a>

     The capitalization of "Play All" is significant.  Apache::Mp3 will
     generate a playlist containing all MP3 files within the directory.

Stream a directory heirarchy recursively
     Append "/playlist.m3u?Play+All+Recursive=1" to the end of the
     directory name:

          <a href="/Songs/HipHop/playlist.m3u?Play+All+Recursive=1">Rock me</a>

     The capitalization of "Play All Recursive" is significant.
     Apache::MP3 will generate a playlist containing all MP3 files within
     the directory and all its subdirectories.

Shuffle and stream a directory
     Append "/playlist.m3u?Shuffle+All=1" to the end of the directory name:

          <a href="/Songs/HipHop/playlist.m3u?Shuffle+All">Rock me</a>

     Apache::MP3 will generate a playlist containing all MP3 files within
     the directory and all its subdirectories, and then randomize its
     order.

Shuffle an entire directory heirarchy recursively
     Append "/playlist.m3u?Shuffle+All+Recursive=1" to the end of the
     directory name:

          <a href="/Songs/HipHop/playlist.m3u?Shuffle+All+Recursive=1">Rock me</a>

     Apache::MP3 will generate a playlist containing all MP3 files within
     the directory and all its subdirectories, and then randomize its
     order.

Play a set of MP3s within a directory
     Append "/playlist.m3u?Play+Selected=1;file=file1;file=file2..." to the
     directory name:

          <a
          href="/Songs/Madonna/playlist.m3u?Play+Selected=1;file=like_a_virgin.mp3;file=evita.mp3">
          Two favorites</a>

     Again, the capitalization of "Play Selected" counts.

Display a sorted directory
     Append "?sort=field" to the end of the directory name, where field is
     any of the MP3 field names:

          <a href="/Songs/Madonna/?sort=duration">Madonna lives!</a>

The Apache::MP3 API
===================

   The Apache::MP3 object is a blessed hash containing a single key, r,
which points at the current request object.  This can be retrieved
conveniently using the r() method.

   Apache::MP3 builds up its directory listing pages in pieces, using a
hierarchical scheme.  The following diagram summarizes which methods are
responsible for generating the various parts.  It might help to study it
alongside a representative HTML page:

     list_directory()
     -------------------------  page top --------------------------------
        directory_top()

     <CDICON> <DIRECTORY> -> <DIRECTORY> -> <DIRECTORY>
     [Shuffle All] [Stream All]

     list_subdirs()

     subdir_list_top()
     ------------------------------------------------------------
     <CD Directories (6)>

     subdir_list()
           <cdicon> <title>   <cdicon> <title>  <cdicon> <title>
           <cdicon> <title>   <cdicon> <title>  <cdicon> <title>

     subdir_list_bottom()  # does nothing
     ------------------------------------------------------------

     list_playlists()

     playlist_list_top()
     ------------------------------------------------------------
     <CD Playlists (6)>

     playlist_list()
           <cdicon> <title>   <cdicon> <title>  <cdicon> <title>
           <cdicon> <title>   <cdicon> <title>  <cdicon> <title>

     playlist_list_bottom()  # does nothing
     ------------------------------------------------------------

     list_mp3s()
          mp3_list_top()
          ------------------------------------------------------------
          <Song List (4)>

     mp3_list()
         mp3_list_top()
           mp3_table_header()
              <Select>                  Title          Kbps

     format_song() # called for each row
        <icon>[] [fetch][stream]  Like a virgin  128
        <icon>[] [fetch][stream]  American Pie   128
        <icon>[] [fetch][stream]  Santa Evita     96
        <icon>[] [fetch][stream]  Boy Toy        168

     mp3_list_bottom()
       [Play Selected] [Shuffle All] [Play All]

     directory_bottom()
      -------------------------  page bottom -----------------------------

Method Calls
------------

   This section lists each of the Apache::MP3 method calls briefly.

$response_code = handler($request)
     This is a the standard mod_perl handler() subroutine.  It creates a
     new Apache::MP3 object, and then invokes its run() method.

$mp3 = Apache::MP3->new(@args)
     This is a constructor.  It stores the passed args in a hash and
     returns a new Apache::MP3 object.  If a single argument is passed it
     assumes that it is an Apache::Request object and stores it under the
     key "r".  You should not have to modify this method.

$request = $mp3->r()
     Return the stored request object.

$boolean = $mp3->is_local()
     Returns true if the requesting client is on the same machine as the
     server.

$response_code = $mp3->run()
     This is the method that interprets the CGI parameters and dispatches
     to the routines that draw the directory listing, generate playlists,
     and stream songs.

$response_code = $mp3->process_directory($dir)
     This is the top-level method for generating the directory listing.  It
     performs various consistency checks on the passed directory URL and
     returns an Apache response code.  The list_directory() method actually
     does most of the formatting work.

$response_code = $mp3->download_file($file)
     This method is called to download a file (not stream it).  It is
     passed the URL of the requested file and returns an Apache response
     code.  It checks whether downloads are allowed and if so allows Apache
     to take its default action.

$response_code = $mp3->stream($file)
     This method is called to stream an MP3 file.  It is passed the URL of
     the requested file and returns an Apche response code.  It checks
     whether streaming is allowed and then passes the request on to
     send_stream().

$mp3->send_playlist($urls,$shuffle)
     This method generates a playlist that is sent to the browser.  It is
     called from various places.  `$urls' is an array reference containing
     the MP3 URLs to incorporate into the playlist, and `$shuffle' is a
     flag indicating that the order of the playlist should be randomized
     prior to sending it.  No return value is returned.

$mp3_info = $mp3->find_mp3s($recurse)
     This method searches for all MP3 files in the currently requested
     directory.  `$recurse', if true, causes the method to recurse through
     all subdirectories.  The return value is a hashref in which the keys
     are the URLs of the found MP3s, and the values are hashrefs containing
     the MP3 tag fields recovered from the files ("title", etc.).

@urls = $mp3->sort_mp3s($mp3_info)
     This method sorts the hashref of MP3 files returned from find_mp3s(),
     returning an array.  The implementation of this method in Apache::MP3
     sorts by physical file name only.  Apache::MP3::Sorted has a more
     sophisticated implementation.

@mp3s = $mp3->load_playlist($playlist)
     This method loads a playlist file (.m3u) from disk and returns a list
     of MP3 files contained in the playlist.

$mp3->playlist_list_bottom($playlists)
     This method generates the footer at the bottom of the list of
     playlists given by `$playlists'. Currently it does nothing.

$mp3->playlist_list($playlists)
     This method displays the playlists given by `$playlists' in a nicely
     formatted table.

$html = $mp3->format_playlist($playlist)
     This method formats the indicated playlist by creating a fragment of
     HTML containing the playlist icon, the stream links and the playlist
     name. It returns a HTML fragment used by playlist_list().

$response_code = $mp3->list_directory($dir)
     This is the top level formatter for directory listings.  It is passed
     the URL of a directory and returns an Apache response code.

$mp3->directory_top($dir)
     This method lists the top part of the directory, including the title,
     the directory navigation list, and the big CD Icon in the upper left.

$mp3->generate_navpath_staircase($dir)
     This method generates the list of parent directories, displaying them
     as links so that the user can navigate.  It takes the URL of the
     current directory and returns no result.

$mp3->generate_navpath_arrows($dir)
     This method does the same, except that the parent directories are
     displayed on a single line, separated by arrows.

$mp3->directory_bottom($dir)
     This method generates the bottom part of the directory listing,
     including the module attribution and help information.

$mp3->subdir_list_top($directories)
     This method generates the heading at the top of the list of
     subdirectories.  `$directories' is an arrayref containing the
     subdirectories to display.

$mp3->subdir_list_bottom($directories)
     This method generates the footer at the bottom of the list of
     subdirectories given by `$directories'.  Currently it does nothing.

$mp3->subdir_list($directories)
     This method invokes sort_subdirs() to sort the subdirectories given by
     `$directories' and displays them in a nicely-formatted table.

@directories = $mp3->sort_subdirs($directories)
     This method sorts the subdirectories given in `$directories' and
     returns a sorted list (not an arrayref).

$html = $mp3->format_subdir($directory)
     This method formats the indicated subdirectory by creating a fragment
     of HTML containing the little CD icon, the shuffle and stream links,
     and the subdirectory's name.  It returns an HTML fragment used by
     subdir_list().

$mp3->get_help
     This subroutine generates the "Quick Help Summary" link at the bottom
     of the page.

$mp3->list_subdirs($subdirectories)
     This is the top-level subroutine for listing subdirectories (the part
     of the page in which the little CD icons appears).  `$subdirectories'
     is an array reference containing the subdirectories to display

$mp3->list_playlists($playlists)
     This is the top-level subroutine for listing playlists. `$playlists'
     is an array reference containing the playlists to display.

$mp3->list_mp3s($mp3s)
     This is the top-level subroutine for listing MP3 files.  `$mp3s' is a
     hashref in which the key is the path of the MP3 file and the value is
     a hashref containing MP3 tag info about it.  This generates the
     buttons at the top of the table and then calls mp3_table_header() and
     mp3_list_bottom().

$mp3->mp3_table_header
     This creates the first row (table headers) of the list of MP3 files.

$mp3->mp3_list_bottom($mp3s)
     This method generates the buttons at the bottom of the MP3 file
     listing. `$mp3s' is a hashref containing information about each file.

$mp3->mp3_list($mp3s)
     This routine sorts the MP3 files contained in `$mp3s' and invokes
     format_song() to format it for the table.

@buttons = $mp3->control_buttons
     Return the list of buttons printed at the bottom of the MP3 file
     listing.

$arrayref = $mp3->format_song($song,$info,$count)
     This method is called with three arguments.  `$song' is the path to
     the MP3 file, $info is a hashref containing tag information from the
     song, and $count is an integer containing the song's position in the
     list (which currently is unusued).  The method invokes
     format_song_controls() and format_song_fields() to generate a list of
     elements to be incorporated into cells of the table, and returns an
     array reference.

@array = $mp3->format_song_controls($song,$info,$count)
     This method is called with the same arguments as format_song().  It
     returns a list (not an arrayref) containing the "control" elements of
     one row of the MP3 list.  The control elements are all the doo-dads on
     the left-hand side of the display, including the music icon, the
     checkbox, and the [fetch] and [stream] links.

@array = $mp3->format_song_fields($song,$info,$count)
     This method is called with the same arguments as format_song().  It
     returns a list (not an arrayref) containing the rest of a row of the
     MP3 file display.  This will include the title, artist, and so forth,
     depending on the values of the Fields configuration. variable.

($directories,$mp3s) = $mp3->read_directory($dir)
     This method reads the directory in $dir, generating an arrayref
     containing the subdirectories and a hashref containing the MP3 files
     and their information, which are returned as a two-element list.

$hashref = $mp3->fetch_info($file)
     This method fetches the MP3 information for $file and returns a
     hashref containing the MP3 tag information as well as some synthesized
     fields.  The synthesized fields are track, which contains the same
     information as tracknum; description, which contains the title, album
     and artist merged together; and *duration*, which contains the
     duration of the song expressed as hours, minutes and seconds.  Other
     fields are taken directly from the MP3 tag, but are downcased (for
     convenience to other routines).

Apache::MP3->path_escape($scalarref)
     This is a limited form of CGI::escape which does not escape the slash
     symbol ("/").  This allows URIs that correspond to directories to be
     escaped safely.  The escape is done inplace on the passed scalar
     reference.

@fields = $mp3->fields
     Return the fields to display for each MP3 file.  Reads the Fields
     configuration variable, or uses a default list.

$hashref = $mp3->read_cache($file)
     Reads the cache for MP3 information about the indicated file.  Returns
     a hashref of the same format used by fetch_info().

$boolean = $mp3->write_cache($file,$info)
     Writes MP3 information to cache.  $file and $info are the path to the
     file and its MP3 tag information, respectively.  Returns a boolean
     indicating the success of the operation.

$result_code = $mp3->send_stream($file,$uri)
     The send_stream() method generates an ICY (shoutcast) header for the
     indicated file (given by physical path $file and URI $uri) and
     streams it to the client.  It returns an Apache result code indicating
     the success of the operation.

$boolean = $mp3->download_ok
     Returns true if downloading files is allowed.

$boolean = $mp3->stream_ok
     Returns true if streaming files is allowed.

$boolean = $mp3->check_stream_client
     Returns true if the module should check the browser/MP3 player for
     whether it accepts streaming.

$boolean = $mp3->is_stream_client
     Returns true if this MP3 player can accept streaming.  Note that this
     is not a foolproof method because it checks a variety of
     non-standardized headers and user agent names!

$boolean = $mp3->read_mp3_info
     Returns true if the module should read MP3 info (true by default).

$seconds = $mp3->stream_timeout
     Returns the number of seconds after which streaming should time out.
     Used for "demo mode".

$lines = $mp3->file_list_is_long
     Returns the number of lines in the MP3 file listing after which the
     list is considered to be "long".  When a long list is encountered, the
     module places the control buttons at both the top and bottom of the
     MP3 file table, rather than at the bottom only.  This method

$html = $mp3->home_label
     Returns a fragment of HTML to use as the "Home" link in the list of
     parent directories.

$style = $mp3->path_style
     Returns the style of the list of parent directories.  Either "arrows"
     or "staircase".

$path = $mp3->cache_dir
     Returns the directory for use in caching MP3 tag information

$int = $mp3->subdir_columns
     Returns the number of columns to use in displaying subdirectories
     (little CD icons).

$dir = $mp3->default_dir
     Returns the base directory used for resolving relative paths in the
     directories to follow.

miscellaneous directories and files
     The following methods return the values of their corresponding
     configuration variables, resolved against the base directory, if need
     be:

          stylesheet()   URI to the stylesheet file
          parent_icon()	URI to the icon to use to move up in directory
                              hierarchy (no longer used)
          cd_icon        URI for the big CD icon printed in the upper left corner
          cd_list_icon   URI for the little CD icons in the subdirectory listing
          playlist_icon  URI for the playlist icon
          song_icon	URI for the music note icons printed for each MP3 file
          arrow_icon	URI for the arrow used in the navigation bar
          help_url	URI of the document to display when user asks for help

$boolean = $mp3->skip_directory($dir)
     This method is called during directory listings.  It returns true if
     the directory should not be displayed.  Currently it skips directories
     beginning with a dot and various source code management directories.
     You may subclass this to skip over other directories.

BUGS
====

   Although it is pure Perl, this module relies on an unusual number of
compiled modules.  Perhaps for this reason, it appears to be sensitive to
certain older versions of modules.

Can't find Apache::File at run time
-----------------------------------

   David Wheeler <dwheeler@salon.com> has reported problems relating to
Apache::File, in which the module fails to run, complaining that it can't
find Apache::File in @INC.  This affects Apache/1.3.12 mod_perl/1.24.
Others have not yet reported this problem.  This can be worked around by
replacing all occurrences of Apache::File with IO::File.

Random segfaults in httpd children
----------------------------------

   Before upgrading to Apache/1.3.6 mod_perl/1.24, I would see random
segfaults in the httpd children when using this module.  This problem
disappeared when I installed a newer mod_perl.

   If you experience this problem, I have found that one workaround is to
load the MP3::Info module at server startup time using the mod_perl
perl.startup script made the problem go away.  This is an excerpt from my
perl.startup file:

     # the !/usr/local/bin/perl
     ...
     use Apache::Registry ();
     use Apache::Constants();
     use MP3::Info;
     use Apache::MP3;
     use CGI();
     use CGI::Carp ();

Can't use -d $r->finfo
----------------------

   Versions of mod_perl prior to 1.22 crash when using the idiom -d
$r->finfo (or any other idiom).  Since there are many older versions still
out there, I have replaced $r->finfo with $r->filename and marked their
locations in comments.  To get increased performance, change back to
$r->finfo.

Misc
----

   In the directory display, the alignment of subdirectory icon with the
subdirectory title is a little bit off.  I want to move the title a bit
lower using some stylesheet magic.  Can anyone help?

SEE ALSO
========

   See Apache/MP3/Sorted, Apache/MP3/Playlist,
see MP3/Info, Apache,

ACKNOWLEDGEMENTS
================

   Tim Ayers <tayers@bridge.com> found and fixed a misfeature in the way
that playlists were sorted.

   Chris Nandor identified various bugs in the module and provided patches.

AUTHOR
======

   Copyright 2000, Lincoln Stein <lstein@cshl.org>.

   This module is distributed under the same terms as Perl itself.  Feel
free to use, modify and redistribute it as long as you retain the correct
attribution.

Manage directories of MP3 files with sorting and persistent playlists
*********************************************************************

NAME
====

   Apache::MP3::Playlist - Manage directories of MP3 files with sorting
and persistent playlists

SYNOPSIS
========

     # httpd.conf or srm.conf
     AddType audio/mpeg    mp3 MP3

     # httpd.conf or access.conf
     <Location /songs>
       SetHandler perl-script
       PerlHandler Apache::MP3::Playlist
       PerlSetVar  SortField     Title
       PerlSetVar  Fields        Title,Artist,Album,Duration
     </Location>

DESCRIPTION
===========

   Apache::MP3::Playlist subclasses Apache::MP3::Sorted to allow the user
to build playlists across directories.  Playlists are stored in cookies
and are persistent for the life of the browser.  See Apache/MP3,
and Apache/MP3/Sorted, for details on
installing and using.

CUSTOMIZATION
=============

   The "playlist" class in the `apache_mp3.css' cascading stylesheet
defines the color of the playlist area and associated buttons.

METHODS
=======

   Apache::MP3::Playlist overrides the following methods:

     run(), directory_bottom(), control_buttons() and directory_top().

   It adds several new methods:

$result = $mp3->process_playlist
     Process buttons that affect the playlist.

$hashref = $mp3->lookup_descriptions(@uris)
     Look up the description fields for the MP3 files indicated by the list
     of URIs (not paths) and return a hashref.

@list = $mp3->playlist([@list])
     Get or set the current stored playlist.  In a list context returns the
     list of URIs of stored MP3 files.  In a scalar context returns an
     array reference.  Pass a list of URIs to set the playlist.

Linking to this module
======================

   The following new linking conventions apply:

Add MP3 files to the user's playlist
     Append "/playlist.m3u?Add+to+Playlist;file=file1;file=file2..." to the
     name of the directory that contains the files:

          <a
          href="/Songs/Madonna/playlist.m3u?Add+to+Playlist=1;file=like_a_virgin.mp3;file=evita.mp3">
          Two favorites</a>

Add all MP3 files in a directory to the user's playlist:
     Append "/playlist.m3u?Add+All+to+Playlist" to the name of the
     directory that contains the files:

          <a
          href="/Songs/Madonna/playlist.m3u?Add+All+to+Playlist=1">
          Madonna'a a Momma</a>

Delete some MP3 files from the user's playlist:
     Append
     "/playlist.m3u?Clear+Selected=1;playlist=1;file=file1;file=file2..."
     to the name of the current directory.

     NOTE: the file names must be absolute URLs, not relative URLs.  This
     is because the playlist spans directories.  By the same token, the
     current directory does not have to contain the removed song(s).
     Example:

          <a
          href="/Songs/Springsteen/playlist.m3u?Clear+Selected=1;
               playlist=1;file=/Songs/Madonna/like_a_virgin.mp3">
          No longer a virgin, alas</a>

Clear user's playlist:
     Append "/playlist.m3u?Clear+All=1;playlist=1" to the name of the
     current directory.

     Example:

          <a href="/Songs/Springsteen/playlist.m3u?Clear+All=1;playlist=1">
            A virgin playlist</a>

Stream the playlist
     Append "/playlist.m3u?Play+All=1;playlist=1" to the name of the
     current directory.

     Example:

          <a href="/Songs/Madonna/playlist.m3u?Play+All=1;playlist=1">
             Stream me!</a>

Stream the playlist in random order
     As above, but use "Shuffle+All" rather than "Play+All".

Stream part of the playlist
     Append
     "/playlist.m3u?Play+Selected=1;playlist=1;file=file1;file=file2..."
     to the name of the current directory.

     NOTE: the files must be full URLs.  It is not strictly necessary for
     them to be on the current playlist, so this allows you to stream
     playlists of arbitrary sets of MP3 files.

     Example:

          <a
          href="/Songs/playlist.m3u?Play+Selected=1;
               playlist=1;file=/Songs/Madonna/like_a_virgin.mp3;
               file=/Songs/Madonna/working_girl.mp3;
               file=/Songs/Beatles/let_it_be.mp3">
          Madonna and John, together again for the first time</a>

BUGS
====

   This module uses client-side cookies to mantain the playlist.  This
limits the number of songs that can be placed in the playlist to about 50
songs.

ACKNOWLEDGEMENTS
================

   Chris Nandor came up with the idea for the persistent playlist and
implemented it using server-side DBM files.  I reimplemented it using
client-side cookies, which simplifies maintenance and security, but limits
playlists in size.

AUTHOR
======

   Copyright 2000, Lincoln Stein <lstein@cshl.org>.

   This module is distributed under the same terms as Perl itself.  Feel
free to use, modify and redistribute it as long as you retain the correct
attribution.

SEE ALSO
========

   See Apache/MP3/Sorted, Apache/MP3,
see MP3/Info, Apache,

Generate sorted streamable directories of MP3 files
***************************************************

NAME
====

   Apache::MP3::Sorted - Generate sorted streamable directories of MP3
files

SYNOPSIS
========

     # httpd.conf or srm.conf
     AddType audio/mpeg    mp3 MP3

     # httpd.conf or access.conf
     <Location /songs>
       SetHandler perl-script
       PerlHandler Apache::MP3::Sorted
       PerlSetVar  SortFields    Album,Title,-Duration
       PerlSetVar  Fields        Title,Artist,Album,Duration
     </Location>

DESCRIPTION
===========

   Apache::MP3::Sorted subclasses Apache::MP3 to allow for sorting of MP3
listings by various criteria.  See Apache/MP3, for
details on installing and using.

CUSTOMIZING
===========

   This class adds one new Apache configuration variable, SortFields.
This is a list of the names of the fields to sort by default when the MP3
file listing is first displayed, after which the user can change the sort
field by clicking on the column headers.

SortFields field
     The value of SortFields may contain the names of any of the fields in
     the listing, such as Title, or *Album* Duration.  By default, the
     sort direction will be alphabetically or numerically ascending.
     Reverse this by placing a "-" in front of the field name (for
     symmetry, you can also prepend a "+" to signify normal ascending
     order).  After the initial sort, the user can change the sort order by
     clicking on the column headings of the file listing table.

     Examples:

          PerlSetVar SortFields  Album,Title    # sort ascending by album, then title
          PerlSetVar SortFields  +Artist,-Kbps  # sort ascending by artist, descending by kbps

     When constructing a playlist from a recursive directory listing,
     sorting will be global across all directories.  If no sort order is
     specified, then the module reverts to sorting by file and directory
     name.  A good value for SortFields is to sort by Artist,Album and
     track:

          PerlSetVar SortFields Artist,Album,Track

     Alternatively, you might want to sort by Description, which
     effectively sorts by title, artist and album.

     The following are valid fields:

          Field        Description

          album	 The album
          artist       The artist
          bitrate      Streaming rate of song in kbps
          comment      The comment field
          description	 Description, as controlled by DescriptionFormat
          duration     Duration of the song in hour, minute, second format
          filename	 The physical name of the .mp3 file
          genre        The genre
          samplerate   Sample rate, in KHz
          seconds      Duration of the song in seconds
          title        The title of the song
          track	 The track number

     Field names are case insensitive.

METHODS
=======

   Apache::MP3::Sorted overrides the following methods:

     sort_mp3s()  mp3_table_header()   mp3_list_bottom()

   It adds one new method:

$field = $mp3->sort_fields
     Returns a list of the names of the fields to sort on by default.

BUGS
====

   Let me know.

AUTHOR
======

   Copyright 2000, Lincoln Stein <lstein@cshl.org>.

   This module is distributed under the same terms as Perl itself.  Feel
free to use, modify and redistribute it as long as you retain the correct
attribution.

ACKNOWLEDGEMENTS
================

   Tim Ayers <tayers@bridge.com> conceived and implemented the multiple
field sorting system.

SEE ALSO
========

   See Apache/MP3, MP3/Info, Apache,

convert server output to uppercase
**********************************

NAME
====

   Apache::MakeCapital - convert server output to uppercase

SYNOPSIS
========

   In the conf/access.conf file of your Apache installation, add lines like

     <Files *.html>
     SetHandler perl-script
     PerlHandler Apache::OutputChain Apache::MakeCapital Apache::PassHtml
     </Files>

DESCRIPTION
===========

   This is a module to show the use of module *Apache::OutputChain*.  The
function handler simply inserts this module into the chain, calling

     Apache::OutputChain::handler($r, __PACKAGE__);

   This is the initialization stage. The second parameter in the call to
*Apache::OutputChain::handler* must be a name of this class, so that
*Apache::OutputChain* will know, whom to put into the chain.

   The package also must define function PRINT, that will be called in the
chain. In this example, it capitalized all output being sent. It will mess
up the links (A HREF's) so is really just for illustration ;-)

AUTHOR
======

   (c) 1997-1998 Jan Pazdziora, adelton@fi.muni.cz,
http://www.fi.muni.cz/~adelton/ at Faculty of Informatics, Masaryk
University, Brno, Czech Republic

mod_perl mime encoding sniffer for XML files
********************************************

NAME
====

   Apache::MimeXML - mod_perl mime encoding sniffer for XML files

SYNOPSIS
========

   Simply add this line to srm.conf or httpd.conf:

     PerlTypeHandler +Apache::MimeXML

   Alternatively add it only for certain files or directories using the
standard Apache methods. There is about a 30% slowdown for files using
this module, so you probably want to restrict it to certain XML locations
only.

DESCRIPTION
===========

   An XML Content-Type sniffer. This module reads the encoding attribute
in the xml declaration and returns an appropriate content-type heading. If
no encoding declaration is found it returns utf-8 or utf-16 depending on
the specific encoding.

CONFIGURATION
=============

   There are a few small configuration options for this module, allowing
you to set various parameters.

XMLMimeType
-----------

   Allows you to set the mime type for XML files:

     PerlSetVar XMLMimeType application/xml

   That changes the mime type from the default text/xml to
application/xml. You can use this on a per-directory basis.

XMLUtf16EncodingBE
------------------

   Allows you to set the encoding of big-endian (read: normal) utf 16
(unicode) documents. The default is 'utf-16'

     PerlSetVar XMLUtf16EncodingBE utf-16-be

XMLUtf16EncodingLE
------------------

   Allows you to set the encoding of little-endian utf-16 encoded
documents. The default is 'utf-16-le'

     PerlSetVar XMLUtf16EncodingLE utf-16-wierd

Use From Other Modules
======================

   If you want to use Apache::MimeXML's detection routines from other
modules, you can manually call the check_for_xml() or check_for_xml_file()
functions yourself. check_for_xml_file() takes a single parameter of a
filename, and check_for_xml() can take either an XML string, or an open
filehandle of some sort. The functions returns the encoding if they find
that the parameter contains XML, otherwise they return nothing:

     my $encoding;
     if ($encoding =
         Apache::MimeXML::check_for_xml_file($filename)) {
         print "$filename is XML in the $encoding encoding\n";
     }

AUTHOR
======

   Matt Sergeant matt@sergeant.org

LICENCE
=======

   This module is distributed under the same terms as perl itself

Associates a scalar with a mmap'd file
**************************************

NAME
====

   Apache::Mmap - Associates a scalar with a mmap'd file

SYNOPSIS
========

     use Apache::Mmap qw(mmap munmap);

     $mappedfile = mmap 'example.html';
     print $$mappedfile;
     munmap 'example.html';

     open( FILE, "jrandomfile" ) or die "Can't open file: $!";
     tie $scalar, 'Apache::Mmap',
         *FILE, 0, Apache::Mmap::PROT_READ, Apache::Mmap::MAP_SHARED;
     print "jrandomfile contents:\n$scalar\n";
     untie $scalar;

DESCRIPTION
===========

   `Apache::Mmap' provides a facility for using the `mmap(2)' system call
to have the OS map a file into a process' address space.

   Two interfaces are provided:

   * `mmap' and `munmap' methods which provide a persistant caching
     mechanisim similar to that provided by `Apache::DBI' for database
     handles.

   * A set of methods which implement the TIESCALAR interface allowing a
     scalar variable to be tied to a mapped region of memory.  Reading or
     writing to the tied scalar accesses the mapped buffer.

Simple Interface
================

   The simple interface provides two functions, `mmap' and `munmap', to
manipulate a mapped area.  The mapped area is accessed using the scalar
reference returned by `mmap'.

`mmap'
------

   The `mmap' function takes the name of a file to map into memory as its
argument.  An optional second argument may be given to specify what
protections should be set on the mapped region.  This argument should be
one of *"r"* (the default), *"w"*, or *"rw"*.  If the file is successfully
mapped a reference to a scalar will be returned.  Remember that you need
to prepend an `$' to dereference the scalar and get the contents:

     $mapped = mmap '/tmp/foo', "rw";
     print "/tmp/foo:\n", $$mapped, "\n";
     $$mapped = "New contents\n";

   The Apache::Mmap module keeps track of all of the files mapped using
the `mmap' function.  If you call `mmap' with a file which is alredy
mapped a reference to the already mapped scalar will be returned.

`munmap'
--------

   Calling `munmap' with a filename removes the association between memory
and existing mmapped file.  If `munmap' is called with a file which is not
currently mapped, undef will be returned.  If the file is successfully
unmapped 1 will be returned.  Keep in mind that you should be careful
unmapping a file if you have multiple copies of the reference returned by
`mmap'.

Tie Interface
=============

   *To be written.  Look at how Apache::Mmap::mmap does it.*

Apache::Mmap::handler
=====================

   A handler method is provided by the Apache::Mmap module suitable for
use under mod_perl with Apache.  To use the handler, add something similar
to the following to your `access.conf' file:

     <Location /mmapped.html>
     SetHandler perl-script
     PerlHandler Apache::Mmap
     </Location>

   replacing */mmaped.html* as apropriate.  Your performance may vary.
See the benchmarking scripts in the `eg' directory of the distribution.

Warning Mapping with Offsets
============================

   Some platforms (Solaris for example) require files to be mapped on
memory page boundaries.  If you map with an offset, the offset must be on
a page boundary (e.g. with 4k pages, if you wanted to map with an offset
of 6k into the file, you would need to map starting at an offset of 4k and
look 2k in from the beginning of the mapped region (I hope that made
sense)).

   A future version will provide access to the `getpagesize()' system call
on platforms where it is available (SYSV and 4.4BSD).  You may also look
into the `Sys::Sysconf' module which provides access to `_SC' macros from
system header files for use with `POSIX::sysconf'.  Some platforms (again,
Solaris) provide an `_SC_PAGESIZE' constant.

TODO
====

   Keep track of the mode a file was mapped as for caching purposes.  Warn
if a different mode is specified, or remap as requested?

   Implement some sort of locking (flock, SysV semaphores, . . .) on the
mapped area.

   Add support for the msync(2) and mlock(2) system calls.

   Add support for madvise(2) on platforms supporting it.

   Add hook to getpagesize(2) for platforms which require mappings at
offsets to be on page boundaries.

   Add some way of specifying if the file's size should be truncated to
the length of the last scalar inserted on unmapping.  Likewise figure out
a good way to extend the file/mapped region if needed.

   Look into using the Storable module for sharing hashes and arrays (like
IPC::Shareable module does for shm).

   Make sure things work on more architectures/os's than Sparc/Solaris
2.5.1 and i586/Linux 2.0.30.

AUTHOR
======

   Mike Fletcher, lemur1@mindspring.com

   This module is based on (and incorporates some code from) Malcolm
Beattie's *Mmap-alpha2* module.

SEE ALSO
========

   mmap(2), perltie(1), perl(1), Malcolm Beattie's *Mmap* module.

Associates a file handle with a mmaped file
*******************************************

NAME
====

   Apache::Mmap::Handle - Associates a file handle with a mmaped file

SYNOPSIS
========

     use Apache::Mmap::Handle ();

     tie *MMAP, 'Apache::Mmap::Handle', $filename, 'r';
     print while( <MMAP> );
     untie *MMAP;

DESCRIPTION
===========

   `Apache::Mmap::Handler' implements the TIEHANDLE interface to allow
tieing a filehandle to a file which has been mapped into memory using the
`Apache::Mmap' module.

AUTHOR
======

   Mike Fletcher, lemur1@mindspring.com

SEE ALSO
========

   Apache::Mmap module, mmap(2), perltie(1), perl(1).

Interface to Apache C module structures
***************************************

NAME
====

   Apache::Module - Interface to Apache C module structures

SYNOPSIS
========

     use Apache::Module ();

DESCRIPTION
===========

   This module provides an interface to the list of apache modules
configured with your httpd and their `module *' structures.

METHODS
=======

top_module
     This method returns a pointer the first module in Apache's internal
     list of modules.

          Example:

          my $top_module = Apache::Module->top_module;

          print "Configured modules: \n";

          for (my $modp = $top_module; $modp; $modp = $modp->next) {
          	print $modp->name, "\n";
          }

find($module_name)
     This method returns a pointer to the module structure if found, under
     otherwise.

          Example:

          for (qw(proxy perl include cgi)) {
              if(my $modp = Apache::Module->find($_)) {
          	 print "$_ module is configured\n";
                  print "with enabled commands: \n";

          for (my $cmd = $modp->cmds; $cmd; $cmd = $cmd->next) {
              print "   ", $cmd->name, "\n";
          }
               }
               else {
          print "$_ module is not configured\n";
               }
           }

handlers
     Returns a pointer to the module response handler table.

     Example:

          print "module ", $modp->name, " handles:\n";

          for (my $hand = $modp->handlers; $hand; $hand = $hand->next) {
          	print $hand->content_type, "\n";
          }

Other Stuff
     There's more you can do with this module, I will document it later.
     For now, see Apache::ModuleDoc and Apache::ShowRequest for examples.

AUTHOR
======

   Doug MacEachern

SEE ALSO
========

   Apache::ModuleDoc(3), Apache::ShowRequest(3), Apache(3), mod_perl(3).

Self documentation for Apache C modules
***************************************

NAME
====

   Apache::ModuleDoc - Self documentation for Apache C modules

SYNOPSIS
========

     <Location /manual/mod>
      SetHandler perl-script
      PerlHandler Apache::ModuleDoc
     </Location>

DESCRIPTION
===========

   This modules provides a documentation template for Apache C modules.
The Location for which this module is configured should be where the
standard Apache module documentation lives.  If a request URI relative to
that Location is a module name (not the .html file), *Apache::ModuleDoc*
will do it's work, otherwise it will `DECLINE' to handle the request.

AUTHOR
======

   Doug MacEachern

SEE ALSO
========

   Apache::Module(3), Apache(3), mod_perl(3)

Provide motd (Message of the Day) functionality to a webserver
**************************************************************

NAME
====

   Apache::Motd - Provide motd (Message of the Day) functionality to a
webserver

SYNOPSIS
========

     in your httpd.conf

     <Directive /path/>
       PerlHeaderParserHandler Apache::Motd
       PerlSetVar MessageFile   /path/to/motd/message
       PerlSetVar CookieName     CookieName [default: seenMOTD]
       PerlSetVar ExpireCookie   CookieExpirationTime [default: +1d]
       PerlSetVar RedirectInSecs N [default: 10]
       PerlSetVar SupportCookieLess (1|0) [default: 1]

DESCRIPTION
===========

   This Apache Perl module provides a web administrator the ability to
configure a webserver with motd (Message of the Day) functionality, just
like you find on UNIX systems. This allows custom messages to appear when
visitors enter a website or a section of the website, without the need to
modify any webpages or web application code!  The message can be a "Message
of the Day", "Terms of Use", "Server Going Down in N Hours", etc. When
applied in the main server configuration (i.e. non
<Location|Directory|Files> directives), any webpage accessed on the
webserver will redirect the visitor to the custom message momentarily.
Then after N seconds, will be redirected to their originally requested
URI, at the same time setting a cookie so that subsequent requests will
not be directed to the custom message.  A link to the requested URI can
also be provided, so that the user has the option of proceeding without
having to wait the entire redirect time. (See motd.txt example provided in
this distribution)

   The intention of this module is to provide an alternate and more
efficient method of notifying your web users of potential downtime or
problems affecting your webserver and/or webservices.

CONFIGURATION
=============

   The module can be placed in <Location>, <Directory>, <Files> and main
server configuration areas.

MessageFile
     The absolute path to the file that contains the custom message.

          i.e. MessageFile /usr/local/apache/motd.txt

     If the file is not found in the specified directory all requests will
     not be directed to the motd.  Therefore you can rename,delete this
     file from the specified location to disable the motd without having
     to edit the httpd.conf entry and/or restart the web server.

     See *MessageFile Format* for a description how the message should be
     used.

RedirectInSecs (default: 10 seconds)
     This sets the wait time (in seconds) before the visitor is redirected
     to the initally requested URI

CookieName (default: seenMOTD)
     Set the name of the cookie name

ExpireCookie (default: +1d, 1 day)
     Set the expiration time for the cookie

SupportCookieLess (default: 1)
     This option is set by default to handle clients that do not support
     cookies or that have cookies turned off. It performs an external
     redirect to the requested $uri along with a `ct=1' query_string to
     test if the client accepts cookies. If the external redirect
     successfully sets the cookie, the user is presented with the motd,
     otherwise the user is not directed to the motd but to the $uri.

     Future versions will correctly support non-cookie clients via URL
     munging.

     Setting this option to 0 is ideally used for when you are totally
     certain that all your visitors will accept cookies. This is usually
     much faster since it elminates the external redirect. ***Use with
     caution. Cookieless clients will get the motd message and *only* the
     motd if this option is false.

     Example:

     <Location />
      PerlHeaderParserHandler Apache::Motd
      PerlSetVar MessageFile /proj/www/motd.txt
      PerlSetVar CookieName TermUsage
      PerlSetVar RedirectInSecs 5
     </Location>

     The example above, sets a server wide message (/proj/www/motd.txt) that
     sets a cookie called TermUsage which expires in one day (default value)
     and redirects the user to the original URI in 5 seconds.

Message File Format
===================

   The text file should at least include the folowing tag variables.  These
tags provide neccessary information to allow redirection to the original
request and the time (in secs) before the redirection take place.

VAR_URI
     This tag will be replaced with the requested URI.

     Recommended usage:

     <a href="<VAR_URI>">click here to proceed</a>

     The above example provides a link to the original requested URI, so
     that a user can click and bypass the time redirect.

VAR_REDIRECT
     This tag will be replaced with the value set in RedirectInSecs.
     Which can be used in the meta tag for redirection.

   Example:

     ...
     <head>
     <meta http-equiv="refresh" content="<VAR_REDIRECT>;URL=<VAR_URI>">
     ...
     </head>
     ...

   The custom message should at least contain a redirect (using a meta
tag) and a link to allow users to bypass the redirect time (for impatient
users and as a courtesy). Omitting these will result in the page not
redirecting the user to the initially requested page.

NOTES
=====

   *Bypassing Motd*

   <Directory> and <Location> configuration settings propogate to
sub-directories and sub-locations matches. One way to turn off the motd on
a motd'd sub-directories and locations is to do the following:

     <Location />
      PerlHeaderParserHandler Apache::Motd
     </Location>

     ## Bypass motd on locations under /foo
     <Location /foo>
      PerlHeaderParserHandler Apache::Motd:OK
     </Location>

     **Example courtesy of Jerrad Pierce

   Logging

   There are two times Apache::Motd logs non-error messages to the apache
error_logs. One instance is when the motd is displayed and the other is
when the motd is bypassed because cookies were rejected.

     ## motd displayed sample entry
     [Wed Dec 13 14:17:57 2000] [error] Motd::Display for URI: /requested/doc.html from $remote_ip

     ## motd is bypassed sample entry
     [Wed Dec 13 14:17:57 2000] [error] Motd::Bypassed by $remote_ip

   These entries can by used to gather statistics about how many times the
motd is being encountered and how many times it's being bypassed.

BUGS
====

Minimal Support for cookie-less clients
     Browsers that have their cookies turned off or that do not support
     them will not see the motd. I hope to implement a URL-based solution
     so that Apache::Motd will support these browsers correctly. So in the
     meantime, you must find other ways of relaying your urgent messages
     to your visitors.

No error checking on the custom message
     The template is not checked for the neccessary information required
     for the redirection to work properly, i.e. usage of <VAR_URI> and
     <VAR_REDIRECT>.  Therefore not using the available tags as described
     will result in unpredictable behavior.

REQUIREMENTS
============

     L<mod_perl>, L<Apache::Cookie>

CREDITS
=======

   Fixes, Bug Reports, Optimizations and Ideas have been generously
provided by:

   Jerrad Pierce <jpierce@cpan.org>  - no-cache pragma on motd file  -
motd bypass on sub-directories and location matches  - no-cookie browser
problem bug report

AUTHOR
======

     Carlos Ramirez <carlos@quantumfx.com>

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   If you have questions or problems regarding use or installation of this
module please feel free to email me directly.

build options access
********************

NAME
====

   Apache::MyConfig - build options access

SYNOPSIS
========

     use Apache::MyConfig;
     die unless $Apache::MyConfig::Setup{PERL_FILE_API};

DESCRIPTION
===========

   *Apache::MyConfig* module provides access to the various hooks and
features set when mod_perl is built.  This circumvents the need to set up
a live server just to find out if a certain callback hook is available.

   Itterate through %Apache::MyConfig::Setup to get obtain build
information then see Appendix B of the Eagle book for more detail on each
key.

Initiate a persistent database connection to Mysql
**************************************************

NAME
====

   Apache::Mysql - Initiate a persistent database connection to Mysql

SYNOPSIS
========

     use Apache::Mysql;

     $dbh = Apache::Mysql->connect(...);

DESCRIPTION
===========

   This module supplies a persistent database connection to Mysql. You
will need to have mysqlperl installed on your system. You should really
use Apache::DBI instead of this module (this module was written when
DBI::Mysql had problems, which have since been corrected).

   This is the first version of the first module I have ever written, so
expect errors! Any feedback or suggestions are gratefully received.

   All you really need is to replace Mysql with Apache::Mysql.  When
connecting to a database the module looks if a database handle from a
previous connect request is already stored. If not, a new connection is
established and the handle is stored for later re-use. The destroy method
has been intentionally left empty.

SEE ALSO
========

   Apache(3), Mysql(3)

AUTHORS    MySQL and mysqlperl by Michael (Monty) Widenius <month@tcx.se>   mod_perl by Doug MacEachern <dougm@osf.org>  Apache::Mysql by Neil Jensen <njensen@habaneros.com>
=============================================================================================================================================================================

A NNTP interface for mod_perl enabled Apache web server.
********************************************************

NAME
====

   *Apache::NNTPGateway* - A NNTP interface for mod_perl enabled Apache
web server.

SYNOPSIS
========

     You must be using mod_perl, see http://perl.apache.org/ for details.

     For the correct work your apache configuration would contain apache
     directives look like these:

     In httpd.conf (or any other apache configuration file):

     <Location "/path/to/newsgroup">
        SetHandler		perl-script
        PerlHandler		Apache::NNTPGateway
        PerlSetVar		NTTPGatewayNewsGroup "newsgroup"
        PerlSetVar		NTTPGateway... (see L<CONFIGURATION> Directives)
     </Location>

DESCRIPTION
===========

     This module implements a per group interface to NNTP (Usenet)
     News-Groups, it allow users to list, read, post, followup ... articles
     in a given newsgroup/newsserver depending of configuration. This is
     not a replacement for a real powerful newsreader client but just
     pretend to be a simple, useful mapping of some news articles into a
     web space.

ACTIONS
-------

     Here is the list of all actions that can be performed on the current newsgroup.

list
          List articles, all articles from the current newsgroup or only unread
          articles if the user/client allready did a B<catchup>.

catchup
          Mark all current articles as read. This use a Cookie.

last
          Read the last article available from the newsserver.

read
          Read article by ID.

followup
          Post a followup to an article.

post
          Post an new article to the current newsgroup.

CONFIGURATION
=============

     Except some very few optional adjustements in the module source
     itself all configuration is done with B<PerlSetVar> directives in
     Apache configurations files.

Directives
----------

     All following features of this PerlHandler, will be set in the apache
     configuration files. For this you can use PerlSetVar apache
     directive.

NNTPGatewayNewsGroup
          (string, B<mandatory>)

          The newsgroup used for the current NNTPGateway location. Not setting
          this will make NNTPGateway fail.

NNTPGatewayStop
          (boolean, I<optional>)

          Tell to completely disable NNTPGateway, useful for temporary maintainance.

NNTPGatewayDefaultAction
          (ACTION name, I<optional>) Default value: B<last>

          Default action used when nothing specified. (see L<ACTIONS>).

NNTPGatewayNewsServer
          (string, I<optional>)

          When using correctly configured perl modules B<Net::Domain>,
          B<Net::Config> on a correctly configured system this should not be
          changed, in theory NNTPGateway could be able to handle multiples
          news server but this is greatly nor recommended (see L<BUGS>) unless
          you really know what you are doing.

NNTPGatewayOrganization
          (string, B<recommended>) Default value: B<The Disoganized Corp>

          Set the Organization header when posting articles.

NNTPGatewayTitle
          (string, I<optional>)

          Title displayed in NNTPGateway pages.

NNTPGatewayStyleSheet
          (string, I<optional>)

          Set the style sheet used in NNTPGateway pages, or none. There are
          some few classes in the generated HTML, check the source to use them
          in your style sheet.

NNTPGatewayAnonymousPostAllowed
          (boolean, I<optional>) Default value: B<off>

          Allow anonymous posting in the current group.

NNTPGatewayAnonymousPosters
          (list, I<optional>) Default value: B<anonymous=Anonymous>

          A list of pair email=Name that could be used for anonymous
          posts. I'm B<Absolutely> not responsible for any abuse of this
          feature, this is up to the webmaster to control it's usage.

          Ex:
          C<PerlSetVar NNTPGatewayAnonymousPosters "anon=The Unknown Soldier,president=The Big Boss">

NNTPGatewayNonLocalPostOk
          (boolean, I<optional>) Default value: B<off>

          Allow user who do not have local (to the same web server machine -
          checked with getpwnam) login account to post articles, in B<non>
          anonymous post mode the users should have been identified themselves
          anyway (with identd or server auth).

NNTPGatewayUsersNamesCaseInsensitive
          (boolean, I<optional>) Default value: B<off>

          Check users names in a case insensitive manner.

NNTPGatewayDisabledActions
          (ACTIONS list, I<optional>) Default value: B<none>

          List of L<ACTIONS> that are B<not> allowed to be performed by users for
          the current config. (see L<ACTIONS>).

NNTPGatewayTemplatesDir
          (string, L<optional>) Default value: B<lib/templates/NNTPGateway/>

          ServerRoot relative Directory where to find HTML templates files (not yet Implemented).

          =item NNTPGatewayDebug

          (boolean, I<optional>) Default value: B<off>

          Set this to debug NNTPGateway.

SECURITY
========

     If you B<allow> Anonymous posting absolutely no security checks are
     performed unless you protect access to the Location this handler is
     located on, but that is not the job of this module.

     If you B<deny> Anonymous posting, the handler will check
     B<remote_ident> (via Identd) or B<remote_user> and will check if
     they are valid username by checking C<getpwnam()> (a list of some
     generic usernames such as: root, anonymous ... are not considered as
     valid too, even if they are), if directive
     B<NNTPGatewayNonLocalPostOk> had not been set, if they are not they
     are rejected, if they are they could post and the From header will
     be set to that username. That is the only security check the handler
     will do, it is up to other apaches modules to correctly protect the
     Location and set valid usernames (enable identd or loggin via
     AuthNIS or anything else).

     Furthermore the webmaster could disable the use of some actions such
     as post, followup ...

BUGS
====

     The connection to the nntp server is handled in a global variable so
     that the connection is common to all requests in the current apache
     child process. Due to that, when the module is used with 2 differents
     configs (in 2 <Location xxx>) setting 2 differents newsservers and
     that 2 requests are made in the same child with these 2 configs (or
     more) ... the second request could re-use a NNTP connection (open
     during the 1st request) already open to the B<first> server. I do not
     want to make the nntp object a local variable, because the connection
     is a long process ... But anyway, I have some few ideas of how to
     solve the problem, but as I am lazy and my configuration do not have
     this problem I am waiting for pressure from eventual module users
     ...;-)

Changes
=======

v0.8
          * Cookie domain better handled for catchup.
          * NNTPGatewayNewsGroupTest removed. Set up a new Location and set
            NNTPGatewayNewsGroup to the test group and NNTPGatewayDebug on to
            acheive the same fonctionnality.
          * Some more directives to control users checking
            (NNTPGatewayUsersNamesCaseInsensitive, NNTPGatewayNonLocalPostOk).
          * Some handling of Cache-Control.
          * Made this module ready for my first CPAN contribution ;-)
          ** Cleaning source code.
          ** Cleaning Documentation.
          ** CPAN Enabled distrib (Makefile.PL, .tar.gz dist, README file, CPAN
             ID ...).

v0.7
          * The configuration directive B<NNTPGatewayCatchupCookieName> do not exists anymore.
          * Disconnections to news server start to be better handled.

          =item v0.6

          First public release

TODO
====

   * Safe sharing of the NNTP global.

   *      Using an HTML Template system (maybe HTML::Template) instead of hard coded html.

   *      Improving the LANG selection stuff (maybe adding a new configuration directive?)

   *      Improving the C<check_user()> stuff for more security.

   *      more stuff ...

SEE ALSO
========

     perl(1), mod_perl(3), Apache(3), Net::NNTP(3), Net::Domain(3),
     Net::Config(3), rfc977

COPYRIGHT
=========

     The application and accompanying modules are Copyright CENA Toulouse.
     It is free software and can be used, copied and redistributed at the
     same terms as perl itself.

AUTHOR
======

     heddy Boubaker <boubaker@cena.fr>

     Home page:
     http://www.tls.cena.fr/~boubaker/WWW/Apache-NNTPGateway.shtml

Run OWA applications under Apache/mod_perl
******************************************

NAME
====

   Apache::OWA - Run OWA applications under Apache/mod_perl

SYNOPSIS
========

   Runs Oracle PL/SQL apllications written using Oracle's PL/SQL Web
Toolkit under Apache/mod_perl.

REQUIREMENTS
============

   DBI, DBD::Oracle, Apache::DBI, Apache::Request (libapreq), Oracle
PL/SQL Web Toolkit (any version should work)

DESCRIPTION
===========

   Example configuration.

     <Location /scott/>
        SetHandler perl-script
        PerlHandler Apache::OWA;
        PerlSetVar DAD oracle:scott:tiger
     </Location>

   This configuration means that calling
"http://server/scott/print_cgi_env" executes the pl/sql procedure
"scott.print_cgi_env".

   Other configuration options:

     PerlSetVar SCHEMA oas_public
        This lets you execute procedures under a different schema (user)
        than the ones specified in the DAD-string.

     PerlSetVar DEBUG 1
        0 - No debugging. This is the default.
        1 - Light debugging and verbose errors sent to the browser.
            Useful while developing procedures.
        2 - Heavy debugging of Apache::OWA inetrnal stuff.

     PerlAuthenHandler Apache::OWA
        This invokes my special authentication handler that can do a few clever
        things. Then it passes control on to the content-handler, so if you
        use this you don't need to specify "PerlHandler Apache::OWA". It
        might also be useful in combination with "PerlSetVar SCHEMA".

     PerlSetVar DB_AUTH true
        Uses database uername and password to authenticate. If no DAD-string
        is set, it can also use the supplied username and password to execute
        your PL/SQL application.

     PerlSetVar DB_PROC_AUTH schema.function
        Uses an arbitrary PL/SQL procedure or function to authenticate.
        The procedure should take the username and password as arguments
        and return 0 for success and more than 0 for failure.

     PerlSetVar NEVER_USE_WEIRD_TYPES 1
        Only set this if you know that you never use multi-value CGI variables
        that need to be mapped to PL/SQL Table datatypes. Finding these datatypes
        is some extra work and will slow down executions a little bit.

   For further documentation see the README.

AUTHOR
======

   Svante Sormark, svinto@ita.chalmers.se.  Latest version available from
http://www.ita.chalmers.se/~svinto/apache

   Contibutions from:

     Slava Kalashnikov <slava@intes.odessa.ua>

     Gunnar Hellekson <g.hellekson@trilux.com> and
     Erich Morisse <e.morisse@trilux.com> of Trilux Internet Group, Ltd.

COPYRIGHT
=========

   The Apache::OWS module is free software; you can redistribute it and/or
modify it under the same terms as Perl or Apache.

SEE ALSO
========

   See Apache, `mod_perl' in this node, `DBI' in this node,
`DBD::Oracle' in this node, see Apache/DBI,

OPT_* defines from httpd_core.h
*******************************

NAME
====

   Apache::Options - OPT_* defines from httpd_core.h

SYNOPSIS
========

     use Apache::Options;

DESCRIPTION
===========

   The *Apache::Options* module will export the following bitmask
constants:

     OPT_NONE
     OPT_INDEXES
     OPT_INCLUDES
     OPT_SYMLINKS
     OPT_EXECCGI
     OPT_UNSET
     OPT_INCNOEXEC
     OPT_SYM_OWNER
     OPT_MULTI
     OPT_ALL

   These constants can be used to check the return value from
Apache->request->allow_options() method.

   This module is simply a stub which imports from Apache/Constants,
just as if you had said `use Apache::Constants
':options';'.

SEE ALSO
========

   See Apache, Apache/Constants,

chain stacked Perl handlers
***************************

NAME
====

   Apache::OutputChain - chain stacked Perl handlers

SYNOPSIS
========

   You need reasonably new version of Apache httpd, compiled with mod_perl
with PERL_STACKED_HANDLERS enabled. In the conf/access.conf file of your
Apache installation, add lines like

     <Files *.html>
     SetHandler perl-script
     PerlHandler Apache::OutputChain Apache::SSIChain Apache::PassHtml
     </Files>

   Also, this module can be used as a base for other Apache::*Chain
handlers - inherit from it to get the chaining features.

DESCRIPTION
===========

   This module allows chaining perl of handlers in Apache, which allows you
to make filter modules that take output from previous handlers, make some
modifications, and pass the output to the next handler or out to browser.

   Normal handler modules specify functions handler that do the job -
authenticate, log, or send back the response. With chaining modules, the
handler function only registers the handler into chain. It is done by tie
of STDOUT. The module then catches output of other handlers in its
function PRINT, that gets called whenever something is printed to tied
handle, can modify or otherwise process the output and send it further on.

   The `PerlHandler' above shows the typical configuration: first,
*Apache::OutputChain* starts the chaining feature. Then, there is a list
of chaining modules, in reverse order. Here shown is *Apache::SSIChain*;
if you would also want to gzip the output, you would write something like

     Apache::OutputChain Apache::GzipChain Apache::SSIChain

   Note that you probably want to do SSI first and gzip the result, that's
why the modules are written in that (reverse) order in the configuration
file.

   As the last in the chaining chain, there should be some module that
actually produces the data: *Apache::PassHtml*, *Apache::PassFile*,
*Apache::PassExec*, or even Apache::Registry.

INTERNALS
=========

   I will try to explain how this feature is achieved, because I hope you
could help me to make it better and mature.

   When the handler function is called, it checks if it gets a reference
to a class. If this is true, then this function was called from some other
handler that wants to be put into the chain. If not, it's probably an
initialization (first call) of this package (*Apache::OutputChain*) and we
will supply name of this package.  Note that other chaining modules should
call inherited handler from their own handlers.

   Now we check, where is STDOUT tied. If it is Apache, we are the first
one trying to be put into the chain. If it is not, there is somebody in
the chain already. We call tie on the STDOUT, steal it from anybody who
had it before - either Apache or the other class.

   When later anybody prints into STDOUT, it will call function PRINT of
the first class in the chain (the last one that registered). If there is
not other class behind, the print method of Apache will be called. If this
is not the last user defined handler in the chain, we will call PRINT
method of the next class.

VERSION
=======

   0.07

AUTHOR
======

   (c) 1997-1999 Jan Pazdziora, adelton@fi.muni.cz,
http://www.fi.muni.cz/~adelton/ at Faculty of Informatics, Masaryk
University, Brno, Czech Republic

SEE ALSO
========

   Apache::GzipChain(3) by Andreas Koenig for solution that gzips the
output on the fly; Apache::SSIChain(3) for SSI parsing module; mod_perl(1)
by Doug MacEachern for the great Perl in Apache project.

   Apache::MakeCapital(3) for a simple example of inheriting from this
module.

   www.apache.org, www.perl.com.

authenticates via a PH database
*******************************

NAME
====

   Apache::PHLogin - authenticates via a PH database

SYNOPSIS
========

     #in .htaccess
     AuthName MyPHLoginAuth
     AuthType Basic
     PerlAuthenHandler Apache::PHLogin::handler

     PerlSetVar PHLogin_host ph.psu.edu
     PerlSetVar PHLogin_port 105
     PerlSetVar PHLogin_timeout 5

     Options Indexes FollowSymLinks ExecCGI

     require valid-user

DESCRIPTION
===========

   The PH(CCSO) Nameserver is a database commonly used as an online
phonebook server for organizations. See
http://people.qualcomm.com/ppomes/ph.html for details. This module uses
the Net::PH module by Graham Barr <gbarr@pobox.com> and Alex Hristov
<hristov@slb.com>.

SEE ALSO
========

   mod_perl(1), Apache::AuthenCache(3), Net::PH(3)

AUTHOR
======

   John Groenveld <groenveld@acm.org>

COPYRIGHT
=========

   This package is Copyright (C) 1998 by John Groenveld. It may be copied,
used and redistributed under the same terms as perl itself.

Application framework using mod_perl and HTML::Template
*******************************************************

NAME
====

   Apache::PageKit - Application framework using mod_perl and
HTML::Template

SYNOPSIS
========

   In httpd.conf

     SetHandler perl-script
     PerlSetVar PKIT_ROOT /path/to/pagekit/files

     PerlHandler +Apache::PageKit
     <Perl>
           Apache::PageKit::startup("/path/to/pagekit/files");
     </Perl>

   In MyPageKit/Common.pm

     package MyPageKit::Common;

     use base 'Apache::PageKit::Model';

     sub pkit_dbi_connect {
       return DBI->connect("DBI:mysql:db","user","passwd");
     }

     sub pkit_session_setup {
       my $model = shift;
       my $dbh = $model->dbh;
       return {
     	session_lock_class => 'MySQL',
     	session_store_class => 'MySQL',
     	session_args => {
     			Handle => $dbh,
     			LockHandle => $dbh,
     			},
     	};
     }

     sub pkit_auth_credential {
       my ($pk, @credentials) = @_;

     # create a session key from @credentials
     # your code here.........

     return $ses_key;
       }

     sub pkit_auth_session_key {
       my ($pk, $ses_key) = @_;

     # check whether $ses_key is valid, if so return user id in $user_id
     # your code here.........

     return $ok ? $user_id : undef;
       }

DESCRIPTION
===========

   PageKit is an mod_perl based application framework that uses
HTML::Template and XML to separate code, design, and content. Includes
session management, authentication, form validation, co-branding, and a
content management system.

   Its goal is to solve all the common problems of web programming, and to
make the creation and maintenance of dynamic web sites fast, easy and
enjoyable.

   You have to write a module named MyPageKit::Common that inherits from
Apache::PageKit::Model and provides methods common across the site.  For
example, if you wish to support authentication, it must include the two
methods pkit_auth_credential and pkit_auth_session_key.

   For more information, visit http://www.pagekit.org/ or
http://sourceforge.net/projects/pagekit/

OBJECTS
=======

   Each `$pk' object contains the following objects:

$pk->{apr}
     An Apache/Request, object.  This gets the
     request parameters and can also be used to set the default values in
     HTML form when fill_in_form is set.

$pk->{config}
     An Apache/PageKit/Config, object, which
     loads and accesses global, server and page attributes.

$pk->{content}
     An Apache/PageKit/Content, object,
     which accesses the content stored in the XML files.

$pk->{model}
     An `MyPageKit::Common' in this node class object, derived from
     Apache/PageKit/Model.

$pk->{session}
     Returns a reference to a hash tied to Apache/PageKit/Session.

$pk->{view}
     An Apache/PageKit/View, object, which
     interfaces with the HTML::Template templates.

Features
========

Model/View/Content/Controller approach to design
     The Model is the user provided classes, which encapsulate the
     business logic behind the web site.

     The View is a set of HTML/Template, templates.
     See Apache/PageKit/View, acts as a bridge
     between the templates and the controller.

     The Content is stored in XML files in the Content/xml directory.  You
     may also store the content in the HTML::Template templates, if you
     don't need to seperate the View from the Content.

     The Controller is a subclass of Apache/PageKit,
     which reads the client request, accesses the back
     end, and uses Apache/PageKit/View, to fill
     in the data needed by the templates.

Seperation of Perl from HTML
     By using HTML/Template, this application
     enforces an important divide - design and programming.  Designers can
     edit HTML without having to deal with any Perl, while programmers can
     edit the Perl code with having to deal with any HTML.

Seperation of Content from Design with XML
     By using the `<CONTENT_VAR>' and `<CONTENT_LOOP>' elements, you can
     autofill the corresponding `<CONTENT_VAR>' and `<CONTENT_LOOP>' tags
     in the template.

     This is an easy way of using XML with HTML::Template that doesn't
     require the use of stylesheets.

Page based attributes
     The attributes of each Page are stored in the Config/Config.xml file.
     This makes it easy to change Pages across the site.  See
     Apache/PageKit/Config, provides a wrapper
     around this XML file.

     For example, to require a login for a page, all you have to do is
     change the  require_login attribute of the XML `<PAGE>' tag to *yes*,
     instead of modifying the Perl code or moving the script to a
     protected directory.

Automatic Dispatching of URIs
     Apache::PageKit translates `$r->uri' into a class and method in the
     user provided classes.  In the example in the synopsis, the URI
     `/account/update' will map to
     `MyPageKit::PageCode::account->page_update'.

Easy error handling.
     Both warnings and fatal errors can be displayed on the screen for
     easy debugging in a development environment, or e-mailed to the site
     adminstrator in a production environment, as specified in the Apache
     `ServerAdmin' configuration directive.

     You have to require Apache/PageKit/Error,
     to turn on error handling.

Session Management
     Provides easy access to a hash tied to Apache/PageKit/Session.

Authentication
     Restricts access to pages based on the require_login attribute.  If
     require_login is set to recent, then PageKit requires that session is
     currently active in the last recent_login_timeout seconds.

Form Validation
     Uses HTML/FormValidator, to provide easy
     form validation.  Highlights fields in red that user filled
     incorrectly by using the `<PKIT_ERRORFONT NAME="FIELD_NAME">
     </PKIT_ERRORFONT>' tag.  To use, pass an input profile to the
     validate method of Apache/PageKit/Model,
     from your perl code option.

Sticky HTML Forms
     Uses HTML/FillInForm, to implement Sticky CGI
     Forms.

     One useful application is after a user submits an HTML form without
     filling out a required field.  PageKit will display the HTML form
     with all the form elements containing the submitted info.

Multiple Views/Co-branding
     Any page can have multiple views, by using the pkit_view request
     parameter.  One example is Printable pages.  Another is having the
     same web site branded differently for different companies.

Components
     PageKit can easily share HTML templates across multiple pages using
     components.  In addition, you may specify Perl code that gets called
     every time a component is used by adding a component_*component_id*
     method to the Perl module specified by `component_dispatch_prefix'.

Language Localization
     You may specify language properties by the `xml:lang' attribute for
     <CONTENT_VAR> and <CONTENT_LOOP> tags in the XML content files.

     The language displayed is based on the user's preference, defaulting
     to the browser settings.

METHODS
=======

   The following methods are available to the user as Apache::PageKit API.

prepare_page
     This executes all of the back-end business logic need for preparing
     the page, including executing the page and component code.

prepare_view
     This fills in the view template with all of the data from the back-end

print_view
     Called as a last step to output filled in view template.

startup
     This function should be called at server startup from your httpd.conf
     file:

          <Perl>
                Apache::PageKit::startup("/path/to/pagekit/files");
          </Perl>

     Where the first (and only) argument is the root directory of the
     PageKit application.  It loads /path/to/pagekit/files/Model into the
     perl search path so that PageKit can make calls into
     MyPageKit::Common and other Model classes.  It also loads the Config
     and Content XML files and pre-parses the View template files.

MARKUP TAGS
===========

   Most tags get "compiled" into <TMPL_VAR>, <TMPL_LOOP>, <TMPL_IF>,
<TMPL_UNLESS>, and <TMPL_ELSE> tags.  See the HTML/Template,
manpage for description of these tags.

<PKIT_COMPONENT NAME="component_id">
     Calls the component code (if applicable) and includes the template for
     the component *component_id*.

     Note that components get dynamically loaded at runtime.  For example
     you can do the following:

          <MODEL_LOOP NAME="foo">
            <PKIT_COMPONENT NAME="<MODEL_VAR NAME="bar">">
          </MODEL_LOOP>

<PKIT_ERRORFONT NAME="FIELD_NAME"> </PKIT_ERRORFONT>
     This tag highlights fields in red that Apache/PageKit/Model,
     reported as being filled in incorrectly.

<PKIT_LOOP NAME="BREAD_CRUMB"> </PKIT_LOOP>
     Displays a bread crumb trail (a Yahoo-like horizontal navigation that
     looks like Top > Category > Sub Category > Current Page ) for pages
     that have `bread_crumb' set to *yes*.

     Template should contain code that looks like

          <PKIT_LOOP NAME="BREAD_CRUMB">
            <PKIT_UNLESS NAME="__LAST__"><a href="/<PKIT_VAR NAME="page">"></PKIT_UNLESS><PKIT_VAR NAME="NAME"><PKIT_UNLESS NAME="__LAST__"></a></PKIT_UNLESS>
            <PKIT_UNLESS NAME="__LAST__"> &gt; </PKIT_UNLESS>
          </PKIT_LOOP>

<PKIT_VAR NAME="LAST_CRUMB">
     Returns the last crumb (typically the page that the user is currently
     viewing).

          <PKIT_VAR NAME="LAST_CRUMB">

     This is particularly useful in the HTML title bar.

<PKIT_VAR NAME="LOGINOUT_LINK">
     If user is logged in, provides link to log out.  If user is not
     logged in, provides link to log in.

<PKIT_LOOP NAME="MESSAGE"> </PKIT_LOOP>
     Displays messages passed to `$model->pkit_message' method.

     Template should contain something that looks like

          <PKIT_LOOP NAME="MESSAGE">
             <PKIT_IF NAME="IS_ERROR"><font color="#ff0000"></PKIT_IF>
             <PKIT_VAR NAME="MESSAGE">
             <PKIT_IF NAME="IS_ERROR"></font></PKIT_IF>
             <p>
          </PKIT_LOOP>

     This code will display error message seperated by the HTML `<p>' tag,
     highlighting error messages in red.

<PKIT_VAR NAME="SELFURL">
     The URL of the current page, including CGI parameters.  Appends a '&'
     or '?' at the end to allow additionial parameters.

<PKIT_IF NAME="VIEW:*view*"> </PKIT_IF>
     Set to true if pkit_view request parameter equals *view*.

OPTIONS
=======

   Global, server and page configuration variables are described in the
Apache/PageKit/Config, perldoc page.  In
addition you can set up the session management in `MyPageKit::Common' in
this node.

REQUEST PARAMETERS
==================

   These are parameters that are specified in GET requests and POST
requests where *Content-type* is one of
*application/x-www-form-urlencoded* or *multipart/form-data*.

pkit_credential_#
     Login data, typically userid/login/email (pkit_credential_0) and
     password (pkit_credential_1).

pkit_done
     The page to return to after the user has finished logging in or
     creating a new account.

pkit_lang
     Sets the user's preferred language, using a ISO 639 identifier.

pkit_login_page
     This parameter is used to specify the page that user attempted to
     login from.  If the login fails, this page is redisplayed.

pkit_remember
     If set to true upon login, will save user's cookie so that they are
     still logged in next time they restart their browser.

pkit_view
     Used to implement multiple views/co-branding.  For example, if set to
     print, will search for templates in the `View/print' directory before
     using templates in the `View/Default' directory, and sets the
     `pkit_view:print' parameter in the view to true.

FREQUENTLY ASKED QUESTIONS
==========================

   Please look in here before you send me an email.

   1) I get a segmentation fault when I start the PageKit enabled Apache
server.

   PageKit requires XML::Parser, which is incompatible with the expat
library included in Apache.  You'll have to configure Apache with
`--disable-rule=expat'.

   For more information see http://axkit.org/faq.xml under "I install
AxKit and Apache segfaults when it starts".

SEE ALSO
========

   See Apache/PageKit/Config,
Apache/PageKit/Content,
Apache/PageKit/Error, Apache/PageKit/Model,
see Apache/PageKit/View,
Apache/Request, HTML/FillInForm,
see HTML/Template,
HTML/FormValidator,

VERSION
=======

   This document describes Apache::PageKit module version 0.96

NOTES
=====

   Requires mod_perl, XML::Parser, HTML::Clean, HTML::FillInForm,
HTML::FormValidator, and HTML::Template.

   I wrote these modules because I needed an application framework that
was based on mod_perl and seperated HTML from Perl.  HTML::Embperl,
Apache::ASP and HTML::Mason are frameworks that work with mod_perl, but
embed Perl code in HTML.  The development was inspired in part by
Webmacro, which is an open-source Java servlet framework that seperates
Code from HTML.

   The goal is of these modules is to develop a framework that provides
most of the functionality that is common across dynamic web sites,
including session management, authorization, form validation, component
design, error handling, and content management.

   If you have used (or are considering using) these modules to build a
web site, please drop me a line with the URL of your web site.  My e-mail
is tj@anidea.com.  Thanks!

BUGS
====

   This framework is in alpha stage.  The interface may change in later
releases.

   Please submit any bug reports, comments, or suggestions to
tjmather@anidea.com, or join the Apache::PageKit mailing list at
http://lists.sourceforge.net/mailman/listinfo/pagekit-users

TODO
====

   Associate sessions with authenticated user ID.

   Add web based editing tools allowing authorized user to edit View,
Content and Configuration files

   Add more tests to the test suite.

   Make content sharable across pages.

   Move Apache::PageKit::Error to seperate distribtuion, use CGI::Carp?

   Add <PKIT_SELFURL_WITHOUT param1 param2> tag.

AUTHOR
======

   T.J. Mather (tjmather@anidea.com)

CREDITS
=======

   Fixes, Bug Reports, Docs have been generously provided by:

     Stu Pae
     Chris Burbridge

   Thanks!

COPYRIGHT
=========

   Copyright (c) 2000, AnIdea Corporation.  All rights Reserved.  PageKit
is a trademark of AnIdea Corporation.

LICENSE
=======

   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 Ricoh Source Code Public
License for more details.

   You can redistribute this module and/or modify it only under the terms
of the Ricoh Source Code Public License.

   You should have received a copy of the Ricoh Source Code Public License
along with this program; if not, obtain one at
http://www.pagekit.org/license

Reads and provides configuration data.
**************************************

NAME
====

   Apache::PageKit::Config - Reads and provides configuration data.

SYNOPSIS
========

   This is a wrapper class to the global, server and page configuration
settings stored in the pagekit_root/Config/Config.xml file.

METHODS
=======

new
     Constructor method, takes configuration directory and server as
     arguments.

          my $config = Apache::PageKit::Config->new(config_dir => $config_dir,
          					server => $server);

     If server is not specified, defaults to 'Default'.

parse_xml
     Load settings from pagekit_root/Config/Config.xml.

          $config->parse_xml;

get_global_attr
          $config->get_global_attr('fill_in_form');

     Gets the global fill_in_form attribute.

get_server_attr
          $config->get_server_attr('cookie_domain');

     Gets the cookie_domain attribute for the server associated with
     $config.

get_page_attr
          $config->get_page_attr($page_id,'use_bread_crumb');

     Gets the value of the use_bread_crumb attribute of `$page_id'.

CONFIGURATION VARIABLES
=======================

Global Attributes
-----------------

   These settings are global in the sense that they apply over all pages
and servers.  They are attributes of the <GLOBAL> tag in Config.xml

cache_dir
     Specifies the directory where the HTML::Template file cache and the
     content cache files are stored.  Defaults to `/tmp'.

cookies_not_set_page
     This is the page that gets displayed if the user attempts to log in,
     but their cookies are not enabled.  Defaults to login_page.

default_page
     Default page user gets when no page is specified.  Defaults to index.

login_page
     Page that gets displayed when user attempts to log in.  Defaults to
     login.

model_base_class
     Specifies the base Model class that typically contains code that used
     across entire the web application, including methods for
     authentication and connecting to the database.

     If you have multiple PageKit applications running on the same mod_perl
     server, then you'll need to specify a unique model_base_class for
     each application.

     Defaults to `MyPageKit::Common' in this node.

model_dispatch_prefix
     This prefixes the class that the contains the model code.  Defaults
     to MyPageKit::MyModel.

     Methods in this class take an Apache::PageKit::Model object as their
     only argument.

not_found_page
     Error page when page cannot be found.  Defaults to default_page.

post_max
     Maximum size of file uploads.  Defaults to 100,000,000 (100 MB).

recent_login_timeout
     Seconds that user's session has to be inactive before a user is asked
     to verify a password on pages with the require_login attribute set to
     recent.  Defaults to 3600 (1 hour).

session_expires
     Sets the expire time for the cookie that stores the session id on the
     user's computer.  If it is not set, then the expire time on the
     cookie will not be set, and the cookie will expire when the user
     closes their browser.

          session = "+3h"

uri_prefix
     Prefix of URI that should be trimmed before dispatching to the Model
     code.

verify_page
     Verify password form.  Defaults to login_page.

Server Attributes
-----------------

   These options are global over all pages, but are local to each server
configuration (e.g. production, staging, development).  They are located
in the <SERVERS> tag of Config.xml

cookie_domain
     Domain for that cookies are issued.  Note that you must have at least
     two periods in the cookie domain.

files_match
          files_match = "\.html?$"

     Declines requests that match value.

html_clean_level
     Sets optimization level for HTML/Clean.  If set to
     0, disables use of HTML/Clean.  Levels range from
     1 to 9.  Level 1 includes only simple fast optimizations.  Level 9
     includes all optimizations.  Defaults to level 9.

reload
     If set to *yes*, check for new content and config xml files on each
     request.  Should be set to no on production servers.  Default is no.

search_engine_headers
     If set to *yes*, sends *Content-Length* and *Last-Modified* headers
     on pages that don't require a login.  Some search engines might that
     these headers be set in order to index a page.

     META: I'm not sure if this works or is necessary with search engines.
     Please send me any comments or suggestions.

     Default is no.

Page Attributes
---------------

   These options are local to each page on the site, but are global across
each server.  The are located in the <PAGES> tag of Config.xml.

page_id (required)
     Page ID for this page.

browser_cache
     If set to no, sends an Expires = -1 header to disable client-side
     caching on the browser.

error_page
     If a submitted form includes invalid data, then this is the page that
     is displayed.

error_page_run_code
     If set to *yes*, then page_code on error_page is run.  Defaults to no.

fill_in_form
     When set to *yes*, automatically fills in HTML forms with values from
     the `$apr' (see Apache/Request) object.  If set to
     *auto*, fills in HTML forms when it detects a <form> tag.  Default is
     *auto*.

internal_title
     Title of page displayed on Content Management System. (Forthcoming)

new_credential
     Should be set to *yes* for pages that process credentials and update
     the database, such as pages that process new registration and forms
     that set a new login and/or password.

     If set to *yes*, then it reissues the cookie that contains the
     credentials and authenticates the user.

parent_id
     Parent page id - used for navigation bar.

request_param_in_tmpl
     If set to yes, then <MODEL_VAR> tags in template automatically get
     filled in with corresponding request values.  Defaults to no.

require_login
     If set to *yes*, page requires a login.  If set to recent, page
     requires a login and that the user has been active in the last
     recent_login_timeout seconds.  Default is no.

template_cache
     If set to normal, enables cache option of HTML/Template,
     for the Page and Include templates.

     If set to shared, enables `shared_cache' option of
     HTML/Template.

uri_match
     Value should be a regular expression.  Servers requests whose URL
     (after the host name) match the regular expression.  For example,
     `^member\/\d*$' matches http://yourdomain.tld/member/4444.

use_bread_crumb
     If set to *yes*, creates bread crumb trail in location specified by
     `<PKIT_LOOP NAME="BREAD_CRUMB"> </PKIT_LOOP>' in the template.

use_template
     If set to *yes*, uses HTML::Template files.  If set to no page code
     is responsible for sending output.  Default is *yes*.

AUTHOR
======

   T.J. Mather (tjmather@anidea.com)

COPYRIGHT
=========

   Copyright (c) 2000, AnIdea Corporation.  All rights Reserved.  PageKit
is a trademark of AnIdea Corporation.

LICENSE
=======

   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 Ricoh Source Code Public
License for more details.

   You can redistribute this module and/or modify it only under the terms
of the Ricoh Source Code Public License.

   You should have received a copy of the Ricoh Source Code Public License
along with this program; if not, obtain one at
http://www.pagekit.org/license

Parses and stores content in XML files.
***************************************

NAME
====

   Apache::PageKit::Content - Parses and stores content in XML files.

DESCRIPTION
===========

   The module loads data from XML files stored in the Content/XML directory
under the PageKit root directory.  Upon server startup, it parses the XML
files and stores the data structures in Content/Cache directory.  It then
loads the data from the cache when a page is requested.

SYNOPSIS
========

   Load content into cache, called when web server starts.

     my $content = Apache::PageKit::Content->new(content_dir => $content_dir,
     					default_lang => $default_lang,
     					reload => 'yes');
     $content->parse_all;

   Load content from cache into view object.

     my $content = Apache::PageKit::Content->new(content_dir => $content_dir,
     					default_lang => $default_lang,
     					lang_arrayref => $lang_arrayref,
     					reload => 'yes');
     my $param_hashref = $content->get_param_hashref($page_id, $iso_lang);

METHODS
=======

   The following methods are available to the user:

parse_all
     Load content into cache, called when web server starts.

          my $content = Apache::PageKit::Content->new(content_dir => $content_dir,
          					default_lang => $default_lang,
          					reload => 'yes');
          $content->parse_all;

get_param_hashref
     Load content from cache, returns hash reference containing parameters
     that can be loaded into HTML::Template.

          my $content = Apache::PageKit::Content->new(content_dir => $content_dir,
          					default_lang => $default_lang,
          					lang_arrayref => $lang_arrayref,
          					reload => 'yes');
          my $param_hashref = $content->get_param_hashref($page_id, $iso_lang);

XML Tags
========

   The following tags are allowed in the Content XML files:

<PAGE>
     This tag contains <CONTENT_VAR> and <CONTENT_LOOP> tags for the
     content of the page specified by <I>id</I>.

          <PAGE id="welcome" cache="yes">
            <CONTENT_VAR NAME="title" xml:lang="en">Title in English</CONTENT_VAR>
          </PAGE>

     If the <I>cache</I> attribute is set to <I>yes</I>, then content will
     be stored in memory instead of a cache file for all languages.  If
     <I>cache</I> is set to <I>default</I>, then the content will be
     stored in memory for the default application.  The default setting
     for <I>cache</I> is <I>no</i>, which stores the content in cache
     files.

<CONTENT_VAR>
     Corresponds to <CONTENT_VAR> tag in HTML::Template file.

          <CONTENT_VAR NAME="title" xml:lang="en"><![CDATA[Title in English]]></CONTENT_VAR>
          <CONTENT_VAR NAME="title" xml:lang="es"><![CDATA[Titulo en Espanol]]></CONTENT_VAR>

<CONTENT_ITEM> and <CONTENT_LOOP>
     Corresponds to <CONTENT_LOOP> tag in HTML::Template file.

          <CONTENT_LOOP NAME="news">
            <CONTENT_ITEM>
              <CONTENT_VAR NAME = "date">August 28th, 2000</CONTENT_VAR>
              <CONTENT_VAR NAME = "title">Release of PageKit 0.02</CONTENT_VAR>
              <CONTENT_VAR NAME = "description">Added XML support for attributes and content</CONTENT_VAR>
            </CONTENT_ITEM>
            <CONTENT_ITEM>
              <CONTENT_VAR NAME = "date">August 24th, 2000</CONTENT_VAR>
              <CONTENT_VAR NAME = "title">Release of PageKit 0.01</CONTENT_VAR>
              <CONTENT_VAR NAME = "description">Initial Release</CONTENT_VAR>
            </CONTENT_ITEM>
          </CONTENT_LOOP>

     This example is from the content file for the front page of the
     pagekit website at http://www.pagekit.org/

<NAV_TITLE>
     Sets the title used in `<PKIT_LOOP NAME="BREAD_CRUMB"> </PKIT_LOOP>'
     and `<PKIT_VAR NAME="LAST_CRUMB">'.

          <NAV_TITLE xml:lang="de">Oberseite</NAV_TITLE>
          <NAV_TITLE xml:lang="en">Home</NAV_TITLE>
          <NAV_TITLE xml:lang="es">Tapa</NAV_TITLE>
          <NAV_TITLE xml:lang="fr">Dessus</NAV_TITLE>

AUTHOR
======

   T.J. Mather (tjmather@anidea.com)

BUGS
====

   Embeded <CONTENT_LOOP>'s in the XML file have not been tested.

COPYRIGHT
=========

   Copyright (c) 2000, AnIdea Corporation.  All rights Reserved.  PageKit
is a trademark of AnIdea Corporation.

LICENSE
=======

   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 Ricoh Source Code Public
License for more details.

   You can redistribute this module and/or modify it only under the terms
of the Ricoh Source Code Public License.

   You should have received a copy of the Ricoh Source Code Public License
along with this program; if not, obtain one at
http://www.pagekit.org/license

Web based editing tools for View templates
******************************************

NAME
====

   Apache::PageKit::Edit - Web based editing tools for View templates

SYNOPSIS
========

   This class is a wrapper class to HTML::Template.  It simplifies the
calls to output a new template, stores the parameters to be used in a
template, and fills in CGI forms using HTML/FillInForm,
and resolves <PKIT_*> tags.

SEE ALSO
========

   See Apache/PageKit, HTML/FillInForm,
see HTML/Template,

AUTHOR
======

   T.J. Mather (tjmather@anidea.com)

COPYRIGHT
=========

   Copyright (c) 2000, AnIdea Corporation.  All rights Reserved.  PageKit
is a trademark of AnIdea Corporation.

LICENSE
=======

   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 Ricoh Source Code Public
License for more details.

   You can redistribute this module and/or modify it only under the terms
of the Ricoh Source Code Public License.

   You should have received a copy of the Ricoh Source Code Public License
along with this program; if not, obtain one at
http://www.pagekit.org/license

Error Handling under mod_perl
*****************************

NAME
====

   Apache::PageKit::Error - Error Handling under mod_perl

SYNOPSIS
========

   In your Apache configuration file:

     PerlModule Apache::PageKit::Error
     PerlSetVar PKIT_ERROR_HANDLER email

DESCRIPTION
===========

   Redirects warnings and fatal errors to screen or e-mail by using
`__WARN__' and __DIE__ signal handlers.  Includes detailed information
including error message, call stack, uri, host, remote host, remote user,
referrer, and handler.

   If `PKIT_ERROR_HANDLER' is set to display, errors will be displayed on
the screen for easy debugging.  This should be used in a development
environment only.

   If `PKIT_ERROR_HANDLER' is set to email, errors will be e-mailed to the
site adminstrator as specified in the Apache `ServerAdmin' configuration
directive.  This should be used on a production site.

AUTHOR
======

   T.J. Mather (tjmather@anidea.com)

COPYRIGHT
=========

   Copyright (c) 2000, AnIdea Corporation.  All rights Reserved.  PageKit
is a trademark of AnIdea Corporation.

LICENSE
=======

   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 Ricoh Source Code Public
License for more details.

   You can redistribute this module and/or modify it only under the terms
of the Ricoh Source Code Public License.

   You should have received a copy of the Ricoh Source Code Public License
along with this program; if not, obtain one at
http://www.pagekit.org/license

Base Model Class
****************

NAME
====

   Apache::PageKit::Model - Base Model Class

DESCRIPTION
===========

   This class provides a base class for the Modules implementing the
backend business logic for your web site.

   This module also contains a wrapper to HTML/FormValidator.
It validates the form data from the
Apache/Request, object contained in the
Apache/PageKit, object.

   When deriving classes from Apache::PageKit::Model, keep in mind that
all methods and hash keys that begin with pkit_ are reserved for future
use.

SYNOPSIS
========

   Method in derived class.

     sub my_method {
       my $model = shift;

     # get database handle, session
     my $dbh = $model->dbh;
     my $session = $model->session;

     # get inputs (from request parameters)
     my $foo = $model->input_param('bar');

     # do some processing

     ...

     # set outputs in template
     $model->output_param(result => $result);
       }

METHODS
=======

   The following methods are available to the user as
Apache::PageKit::Model API.

input_param
     Gets requested parameter from the request object `$apr'.

          my $value = $model->input_param($key);

     If called without any parameters, gets all available input parameters:

          my @keys = $model->input_param;

     Can also be used to set parameter that Model gets as input.  For
     example you can set the userID when the user gets authenticated:

          $model->input_param(pkit_user => $userID);

pkit_input_hashref
     This method fetches all of the parameters from the request object
     `$apr', returning a reference to a hash containing the parameters as
     keys, and the parameters' values as values.  Note a multivalued
     parameters is returned as a reference to an array.

          $params = $model->pkit_input_hashref;

output_param
     This is similar to the `HTML::Template|HTML::Template' in this node
     method.  It is used to set <MODEL_*> template variables.

          $model->output_param(USERNAME => "John Doe");

     Sets the parameter USERNAME to "John Doe".  That is `<MODEL_VAR
     NAME="USERNAME">' will be replaced with "John Doe".

     It can also be used to set multiple parameters at once by passing a
     hash:

          $model->output_param(firstname => $firstname,
                       lastname => $lastname);

     Alternatively you can pass a hash reference:

          $model->output_param({firstname => $firstname,
                       lastname => $lastname});

     Note, to set the bread crumb for the <PKIT_LOOP NAME="BREAD_CRUMB">
     tag, use the following code:

          $model->output_param(pkit_bread_crumb =>
          		       [
          			{ pkit_page => 'toplink', pkit_name='Top'},
          			{ pkit_page => 'sublink', pkit_name='Sub Class'},
          			{ pkit_name => 'current page' },
          		       ]
          		      );

pkit_query
     Basically a wrapper to the `"query()"', see HTML/Template,
     method of HTML::Template:

          my $type = $model->pkit_query(name => 'foo');

content_param
     Similar to output_param but sets content variables associated with
     the <CONTENT_VAR> and <CONTENT_LOOP> tags.

apr
     Returns the Apache/Request, object.

          my $apr = $model->apr;

dbh
     Returns a database handle, as specified by the
     `MyPageKit::Model::dbi_connect' method.

          my $dbh = $model->dbh;

session
     Returns a hash tied to <Apache::PageKit::Session>

          my $session = $model->session;

pkit_message
     Displays a special message to the user.  The message can displayed
     using the `<PKIT_LOOP NAME="MESSAGE"> </PKIT_LOOP>' code.

     You can add a message from the Model code:

          $model->pkit_message("Your listing has been deleted.");

     To add an error message (typically highlighted in red), use

          $model->pkit_message("You did not fill out the required fields.",
                       is_error => 1);

pkit_internal_redirect
     Resets the page_id. This is usually used "redirect" to different
     template.

          $model->pkit_internal_redirect($page_id);

pkit_redirect
     Redirect to another URL.

          $model->pkit_redirect("http://www.pagekit.org/");

     Redirects user to the PageKit home page.

pkit_validate_input
     Takes an hash reference containing a HTML/FormValidator,
     input profile and returns true if the request
     parameters are valid.

          # very simple validation, just check to see if name field was filled out
          my $input_profile = {required => [ qw ( name ) ]};
          # validate user input
          unless($model->pkit_validate_input($input_profile)){
            # user must have not filled out name field,
            # i.e. $apr->param('name') = $model->input_param('name') is
            # not set, so go back to original form
            $model->pkit_internal_redirect('orig_form');
            return;
          }

   The following methods should be defined in your base module as defined
by model_base_class in Config.xml:

pkit_dbi_connect
     Returns database handler, $dbh, which can be accessed by rest of Model
     through `$model->dbh'.

pkit_session_setup
     Returns hash reference to session setup arguments.

pkit_auth_credential
     Verifies the user-supplied credentials and return a session key.  The
     session key can be any string - often you'll use the user ID and a
     MD5 hash of a a secret key, user ID, password.

pkit_auth_session_key
     Verifies the session key (previously generated by `auth_credential')
     and return the user ID.  This user ID will be fed to
     `$model->input_param('pkit_user')'.

SEE ALSO
========

   See Apache/PageKit, HTML/FormValidator,

AUTHOR
======

   T.J. Mather (tjmather@anidea.com)

COPYRIGHT
=========

   Copyright (c) 2000, AnIdea Corporation.  All rights Reserved.  PageKit
is a trademark of AnIdea Corporation.

LICENSE
=======

   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 Ricoh Source Code Public
License for more details.

   You can redistribute this module and/or modify it only under the terms
of the Ricoh Source Code Public License.

   You should have received a copy of the Ricoh Source Code Public License
along with this program; if not, obtain one at
http://www.pagekit.org/license

Session Handling
****************

NAME
====

   Apache::PageKit::Session - Session Handling

DESCRIPTION
===========

   An adaptation of Apache/Session, to work with
Apache/PageKit,

SYNOPSIS
========

Addtional Attributes for TIE
----------------------------

lazy
     By Specifing this attribute, you tell Apache::Session to not do any
     access to the object store, until the first read or write access to
     the tied hash. Otherwise the tie function will make sure the hash
     exist or creates a new one.

create_unknown
     Setting this to one causes Apache::Session to create a new session
     when the specified session id does not exists. Otherwise it will die.

Store
     Specify the class for the object store. (The Apache::Session::Store
     prefix is optional) Only for Apache::Session 1.5x.

Lock
     Specify the class for the lock manager. (The Apache::Session::Lock
     prefix is optional) Only for Apache::Session 1.5x.

Generate
     Specify the class for the id generator. (The
     Apache::Session::Generate prefix is optional) Only for
     Apache::Session 1.5x.

     Defaults to MD5.

Serialize
     Specify the class for the data serializer. (The
     Apache::Session::Serialize prefix is optional) Only for
     Apache::Session 1.5x.

     Defaults to Storable.

   Example using attrubtes to specfiy store and object classes instead of
a derived class:

     use Apache::PageKit::Session;

     tie %session, 'Apache::PageKit::Session', undef,
        {
        Store => 'MySQL',
        Lock => 'MySQL',
        Handle => $dbh,
        LockHandle => $dbh
        };

   NOTE: Apache::PageKit::Session will require the necessary perl modules
for you.

Addtional Methods
-----------------

setid
     Set the session id for futher accesses.

getid
     Get the session id. The difference to using $session{_session_id} is,
     that in lazy mode, getid will not create a new session id, if it
     doesn't exists.

cleanup
     Writes any pending data, releases all locks and deletes all data from
     memory.

AUTHORS
=======

   This module was adapted from HTML::Embperl::Session by T.J. Mather
<tjmather@anidea.com>.

   Gerald Richter <richter@dev.ecos.de> is the current maintainer of
HTML::Embperl::Session.

   This class was written by Jeffrey Baker (jeffrey@kathyandjeffrey.net)
but it is taken wholesale from a patch that Gerald Richter
(richter@ecos.de) sent me against Apache::Session.

Bridge between Apache::PageKit and HTML::Template
*************************************************

NAME
====

   Apache::PageKit::View - Bridge between Apache::PageKit and
HTML::Template

SYNOPSIS
========

   This class is a wrapper class to HTML::Template.  It simplifies the
calls to output a new templat, and fills in CGI forms using
HTML/FillInForm, and resolves <MODEL_*>, <CONTENT_*> and
<PKIT_*> tags.

METHODS
=======

   The following methods are available to the user as
Apache::PageKit::View API.

new
          my $view = new Apache::PageKit::View;

     Constructor for new object.

prepare_component
          $view->prepare_component(34);

     Calles the code for the component with id 34 and fills in the
     component template.

prepare_output
     Resolves `<PKIT_*>' tags and fills in HTML forms using
     HTML/FillInForm.

output_ref
     Returns a reference to the output of the parsed template.

SEE ALSO
========

   See Apache/PageKit, HTML/FillInForm,
see HTML/Template,

AUTHOR
======

   T.J. Mather (tjmather@anidea.com)

COPYRIGHT
=========

   Copyright (c) 2000, AnIdea Corporation.  All rights Reserved.  PageKit
is a trademark of AnIdea Corporation.

LICENSE
=======

   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 Ricoh Source Code Public
License for more details.

   You can redistribute this module and/or modify it only under the terms
of the Ricoh Source Code Public License.

   You should have received a copy of the Ricoh Source Code Public License
along with this program; if not, obtain one at
http://www.pagekit.org/license

Object-oriented Perl extension for parsing Apache log files
***********************************************************

NAME
====

   Apache::ParseLog - Object-oriented Perl extension for parsing Apache
log files

SYNOPSIS
========

     use Apache::ParseLog;
     $base = new Apache::ParseLog();
     $transferlog = $base->getTransferLog();
     %dailytransferredbytes = $transferlog->bytebydate();
     ...

DESCRIPTION
===========

   Apache::ParseLog provides an easy way to parse the Apache log files,
using object-oriented constructs. The data obtained using this module are
generic enough that it is flexible to use the data for your own
applications, such as CGI, simple text-only report generater, feeding
RDBMS, data for Perl/Tk-based GUI application, etc.

FEATURES
========

  1. *Easy and Portable Log-Parsing Methods*

     Because all of the work (parsing logs, constructing regex, matching
     and assigning to variables, etc.) is done inside this module, you can
     easily create log reports (unless your logs need intense scrutiny).
     Read on this manpage as well as the `"EXAMPLES"' in this node section
     to see how easy it is to create log reports with this module.

     Also, this module does not require C compiler, and it can (should)
     run on any platforms supported by Perl.

  2. *Support for LogFormat/CustomLog*

     The Apache Web Server 1.3.x's new LogForamt/CustomLog feature (with
     mod_log_config) is supported.

     The log format specified with Apache's `LogFormat' directive in the
     httpd.conf file will be parsed and the regular expressions will be
     created dynamically inside this module, so re-writing your existing
     code will be minimal when the log format is changed.

  3. *Reports on Unique Visitor Counts*

     Tranditionally, the hit count is calculated based on the number of
     files requested by visitors (the simplest is the the total number of
     lines of the log file calculated as the "total hit").

     As such, the hit count obviously can be misleading in the sense of
     "how many visitors have actually visited my site?", especially if the
     pages of your site contain many images (because each image is counted
     as one hit).

     Apache::ParseLog provides the methods to obtain such traditional data,
     because those data also are very important for monitoring your web
     site's activities. However, this module also provides the methods to
     obtain the *unique visitor counts*, i.e., the actual number of
     "people" (well, IP or hostname) who visited your site, by date, time,
     and date and time.

     See the `"LOG OBJECT METHODS"' in this node for details about those
     methods.

  4. *Pre-Compiled Regex*

     The new pre-compiled regex feature introduced by Perl 5.005 is used
     (if you have the version installed on your machine).

     For the pre-compiled regex and the new quote-like assignment operator
     (qr), see perlop(1) and perlre(1) manpages.

CONSTRUCTOR
===========

   To construct an Apache::ParseLog object,new() method is available just
like other modules.

   The new() constructor returns an Apache::ParseLog base object with
which to obtain basic server information as well as to construct *log
objects*.

New Method
----------

   *`new([$path_to_httpd_conf[, $virtual_host]]);'*

   With the new() method, an Apache::ParseLog object can be created in
three different ways.

  1. `$base = new Apache::ParseLog();'

     This first method creates an empty object, which means that the
     fields of the object are undefined (undef); i.e., the object does not
     know what the server name is, where the log files are, etc. It is
     useful when you need to parse log files that are not created on the
     local Apache server (e.g., the log files FTP'd from elsewhere).

     You have to use the config() method (see below) to call any other
     methods.

  2. `$base = new Apache::ParseLog($httpd_conf);'

     This is the second way to create an object with necessary information
     extracted from the *$httpd_conf*. *$httpd_conf* is a scalar string
     containing the absolute path to the httpd.conf file; e.g.,

          $httpd_conf = "/usr/local/httpd/conf/httpd.conf";

     This method tries to extract the information from *$httpd_conf*,
     specified by the following Apache directives: `ServerName', Port,
     `ServerAdmin', `TransferLog', `ErrorLog', `AgentLog', `RefererLog',
     and any user-defined `CustomLog' along with `LogFormat'.

     If any of the directives cannot be found or commented out in the
     *$httpd_conf*, then the field(s) for that directive(s) will be empty
     (undef), and corresponding methods that use the particular fields
     return an empty string when called, or error out (for *log object
     methods*, refer to the section below).

  3. `$base = new Apache::ParseLog($httpd_conf, $virtual_host);'

     This method creates an object just like the second method, but for the
     VirtualHost specified by $virtual_host *only*. The Apache directives
     and rules not specified within the <VitualHost xxx> and </VirtualHost>
     tags are parsed from the "regular" server section in the httpd.conf
     file.

     Note that the *$httpd_conf* must be specified in order to create an
     object for the $virtual_host.

BASE OBJECT METHODS
===================

   This section describes the methods available for the base object created
by the new() construct described above.

   Unless the object is created with an empty argument, the
Apache::ParseLog module parses the basic information configured in the
httpd.conf file (as passed as the first argument). The object uses the
information to construct the *log object*.

   The available methods are (return values are in parentheses):

     $base->config([%fields]); # (object)
     $base->version(); # (scalar)
     $base->serverroot(); # (scalar)
     $base->servername(); # (scalar)
     $base->httpport(); # (scalar)
     $base->serveradmin(); # (scalar)
     $base->transferlog(); # (scalar)
     $base->errorlog(); # (scalar)
     $base->agentlog(); # (scalar)
     $base->refererlog(); # (scalar)
     $base->customlog(); # (array)
     $base->customlogLocation($name); # (scalar)
     $base->customlogExists($name); # (scalar boolean, 1 or 0)
     $base->customlogFormat($name); # (scalar)
     $base->getTransferLog(); # (object)
     $base->getErrorLog(); # (object)
     $base->getRefererLog(); # (object)
     $base->getAgentLog(); # (object)
     $base->getCustomLog(); # (object)

   * `config(%fields]);'

          $base = $base->config(field1 => value1,
                                field2 => valud2,
                                fieldN => valueN);

     This method configures the Apache::ParseLog object. Possible fields
     are:

          Field Name                     Value
          ---------------------------------------------------------
          serverroot  => absolute path to the server root directory
          servername  => name of the server, e.g., "www.mysite.com"
          httpport    => httpd port, e.g., 80
          serveradmin => the administrator, e.g., "admin@mysite.com"
          transferlog => absolute path to the transfer log
          errorlog    => absolute path to the error log
          agentlog    => absolute path to the agent log
          refererlog  => absolute path to the referer log

     This method should be called after the empty object is created
     (new(), see above). However, you can override the value(s) for any
     fields by calling this method even if the object is created with
     defined *$httpd_conf* and $virtual_host. (Convenient if you don't
     have any httpd server running on your machine but have to parse the
     log files transferred from elsewhere.)

     Any fields are optional, but at least one field should be specified
     (otherwise why use this method?).

     When this method is called from the empty object, and not all the
     fields are specified, the empty field still will be empty (thereby
     not being able to use some corresponding methods).

     When this method is called from the already configured object (with
     `new($httpd_conf[, $virtual_host])'), the fields specified in this
     config() method will override the existing field values, and the rest
     of the fields inherit the pre-existing values.

     *NOTE 1:* This method *returns a newly configured object*, so make
     sure to use the assignment operator to create the new object (see
     examples below).

     *NOTE 2:* You *cannot* (re)configure `CustomLog' values. It is to
     alleviate the possible broken log formats, which would render the
     parsed results unusable.

     Example 1

          # Create an empty object first
          $base = new Apache::ParseLog();
          # Configure the transfer and error fields only, for the files
          # transferred from your Web site hosting service
          $logs = "/home/webmaster/logs";
          $base = $base->config(transferlog => "$logs/transfer_log",
                                errorlog    => "$logs/error_log");

     Example 2

          # Create an object with $httpd_conf
          $base = new Apache::ParseLog("/usr/local/httpd/conf/httpd.conf");
          # Overrides some fields
          $logs = "/usr/local/httpd/logs";
          $base = $base->config(transferlog => "$logs/old/trans_199807",
                                errorlog    => "$logs/old/error_199807",
                                agentlog    => "$logs/old/agent_199807",
                                refererlog  => "$logs/old/refer_199807");

   * `serverroot();'

          print $base->serverroot(), "\n";

     Returns a scalar containing the root of the Web server as specified
     in the httpd.conf file, or undef if the object is not specified.

   * `servername();'

          print $base->servername(), "\n";

     Returns a scalar containing the name of the Web server, or undef if
     server name is not specified.

   * `httpport();'

          print $base->httpport(), "\n";

     Returns a scalar containing the port number used for the httpd, or
     undef if not specified. (By default, httpd uses port 80.)

   * `serveradmin();'

          print $base->serveradmin(), "\n";

     Returns a scalar containing the name of the server administrator, or
     undef if not specified.

   * `transferlog();'

          die "$!\n" unless -e $base->transferlog();

     Returns a scalar containing the absolute path to the transfer log
     file, or undef if not specified.

   * `errorlog();'

          die "$!\n" unless -e $base->errorlog();

     Returns a scalar containing the absolute path to the error log file,
     or undef if not specified.

   * `agentlog();'

          die "$!\n" unless -e $base->agentlog();

     Returns a scalar containing the absolute path to the agent log file,
     or undef if not specified.

   * `refererlog();'

          die "$!\n" unless -e $base->refererlog();

     Returns a scalar containing the absolute path to the referer log file,
     or undef if not specified.

   * `customlog();'

          @customlog = $base->customlog();

     Returns an array containing "nicknames" of the custom logs defined in
     the *$httpd_conf*.

   * `customlogLocation($log_nickname);'

          print $base->customlogLocation($name), "\n";

     Returns a scalar containing the absolute path to the custom log $name.
     If the custom log $name does not exist, it will return undef.

     This method should be used for debugging purposes only, since you can
     call `getCustomLog()' to parse the logs, making it unnecessary to
     manually open the custom log file in your own script.

   * `customlogExists($log_nickname);'

          if ($base->customlogExists($name)) {
              $customlog = $base->getCustomLog($name);
          }

     Returns 1 if the custom log $name (e.g., common, *combined*) is
     defined in the *$httpd_conf* file and the log file exists, or 0
     otherwise.

     You do not have to call this method usually because this is internally
     called by the `getCustomLog($name)' method.

   * `customlogFormat($log_nickname);'

          print $base->customlogFormat($name), "\n";

          Returns a scalar containing the string of the "LogFormat" for the
          custom log I<$name>, as specified in I<$httpd_conf>. This method
          is meant to be used internally, as well as for debugging purpose.

   * `getTransferLog();'

          $transferlog = $base->getTransferLog();

     Returns an object through which to access the information parsed from
     the `TransferLog' file. See the `"LOG OBJECT METHODS"' in this node
     below for methods to access the log information.

   * `getRefererLog();'

          $refererlog = $base->getRefererLog();

     Returns an object through which to access the information parsed from
     the `RefererLog' file. See the `"LOG OBJECT METHODS"' in this node
     below for methods to access the log information.

   * `getAgentLog();'

          $agentlog = $base->getAgentLog();

     This method returns an object through which to access the information
     parsed from the `AgentLog' file. See the `"LOG OBJECT METHODS"' in
     this node below for methods to access the log information.

   * `getErrorLog();'

          $errorlog = $base->getErrorLog();

     This method returns an object through which to access the information
     parsed from the `ErrorLog' file. See the `"LOG OBJECT METHODS"' in
     this node below for methods to access the log information.

   * `getCustomLog($log_nickname);'

          $customlog = $base->getCustomLog($name);

     This method returns an object through which to access the information
     parsed from the `CustomLog' file $name. See the `"LOG OBJECT
     METHODS"' in this node below for methods for methods to access the
     log information.

LOG OBJECT METHODS
==================

   This section describes the methods available for the log object created
by any of the following base object methods: *getTransferLog()*,
*getErrorLog()*, *getRereferLog()*, *getAgentLog()*, and
*getCustomLog($log_nickname)*.

   This section is devided into six subsections, each of which describes
the available methods for a certain log object.

   Note that all the methods for `TransferLog', `RefererLog', and
`AgentLog' can be used for the object created with `getCustomLog($name)'.

TransferLog/CustomLog Methods
-----------------------------

   The following methods are available for the `TransferLog' object
(created by `getTransferLog()' method), as well as the `CustomLog' object
that logs appropriate arguments to the corresponding `LogFormat'.

   * `hit();'

          %hit = $logobject->hit();

     Returns a hash containing at least a key 'Total' with the total hit
     count as its value, and the file extensions (i.e., html, jpg, gif,
     cgi, pl, etc.) as keys with the hit count for each key as values.

   * `host();'

          %host = $logobject->host();

     Returns a hash containing host names (or IPs if names are unresolved)
     of the visitors as keys, and the hit count for each key as values.

   * `topdomain();'

          %topdomain = $logobject->topdomain();

     Returns a hash containing topdomain names (com, net, etc.) of the
     visitors as keys, and the hit count for each key as values.

     Note that if the hostname is unresolved and remains as an IP address,
     the visitor will not be counted toward the (and the next
     `secdomain()') returned value of this method.

   * `secdomain();'

          %secdomain = $logobject->secdomain();

     Returns a hash containing secondary domain names (xxx.com, yyy.net,
     etc.) as keys, and the hit count for each key as values.

     For the unresolved IPs, the same rule applies as the above
     `topdomain()' method.

   * `login();'

          %login = $logobject->login();

     Returns a hash containing login names (authenticated user logins) of
     the visitors as keys, and the hit count for each key as values.

     Log entries for non-authenticated files have a character "-" as the
     login name.

   * `user();'

          %user = $logobject->user();

     Returns a hash containing user names (for access-controlled
     directories, refer to the access.conf file of the Apache server) of
     the visitors as keys, and the hit count for each key as values.

     Non-access-controlled log entries have a character "-" as the user
     name.

   * `hitbydate();'

          %hitbydate = $logobject->hitbydate();

     Returns a hash containing date (mm/dd/yyyy) when visitors visited the
     particular file (html, jpg, etc.) as keys, and the hit count for each
     key as values.

   * `hitbytime();'

          %hitbytime = $logobject->hitbytime();

     Returns a hash containing time (00-23) each file was visited as keys,
     and the hit count for each key as values.

   * `hitbydatetime();'

          %hitbydatetime = $logobject->hitbydatetime();

     Returns a hash containing date/time (mm/dd/yyyy-hh) as keys, and the
     hit count for each key as values.

   * `visitorbydate();'

          %visitorbydate = $logobject->visitorbydate();

     Returns a hash containing date (mm/dd/yyyy) as keys, and the unique
     visitor count for each key as values.

   * `visitorbytime();'

          %visitorbytime = $logobject->visitorbytime();

     Returns a hash containing time (00-23) as keys, and the unique visitor
     count for each key as values.

   * `visitorbydatetime();'

          %visitorbydatetime = $logobject->visitorbydatetime();

     Returns a hash containing date/time (mm/dd/yyyy-hh) as keys, and the
     unique visitor count for each key as values.

   * `method();'

          %method = $logobject->method();

     Returns a hash containing HTTP method (GET, POST, PUT, etc.)  as
     keys, and the hit count for each key as values.

   * `file();'

          %file = $logobject->file();

     Returns a hash containing the file names relative to the
     `DocumentRoot' of the server as keys, and the hit count for each key
     as values.

   * `querystring();'

          %querystring = $logobject->querystring();

     Returns a hash containing the query string as keys, and the hit count
     for each key as values.

   * `proto();'

          %proto = $logobject->proto();

     Returns a hash containing the protocols used (HTTP/1.0, HTTP/1.1,
     etc.)  as keys, and the hit count for each key as values.

   * `lstatus();'

          %lstatus = $logobject->lstatus();

     Returns a hash containing HTTP codes and messages (e.g. "404 Not
     Found") for the last status (i.e., when the httpd finishes processing
     that request) as keys, and the hit count for each key as values.

   * `byte();'

          %byte = $logobject->byte();

     Returns a hash containing at least a key 'Total' with the total
     transferred bytes as its value, and the file extensions (i.e., html,
     jpg, gif, cgi, pl, etc.) as keys, and the transferred bytes for each
     key as values.

   * `bytebydate();'

          %bytebydate = $logobject->bytebydate();

     Returns a hash containing date (mm/dd/yyyy) as keys, and the hit
     count for each key as values.

   * `bytebytime();'

          %bytebytime = $logobject->bytebytime();

     Returns a hash containing time (00-23) as keys, and the hit count for
     each key as values.

   * `bytebydatetime();'

          %bytebydatetime = $logobject->bytebydatetime();

     Returns a hash containing date/time (mm/dd/yyyy-hh) as keys, and the
     hit count for each key as values.

ErrorLog Methods
----------------

   Until the Apache version 1.2.x, each error log entry was just an error,
meaning that there was no distinction between "real" errors (e.g., File
Not Found, malfunctioning CGI, etc.) and non-significant errors (e.g.,
kill -1 the httpd processes, etc.).

   Starting from the version 1.3.x, the Apache httpd logs the "type" of
each error log entry, namely "error", "notice" and "warn".

   If you use Apache 1.2.x, the `errorbyxxx()', `noticebyxxx()', and
`warnbyxxx()' should not be used, because those methods for that are for
1.3.x only will merely return an empty hash.  The `allbyxxx()' methods
will return desired results.

   The following methods are available for the `ErrorLog' object (created
by `getErrorLog()' method).

   * `count();'

          %errors = $errorlogobject->count();

     Returns a hash containing count for each type of messages logged in
     the error log file.

     The keys and values are: 'Total' (total number of errors), 'error'
     (total number of errors of type "error"), 'notice' total number of
     errors of type "notice"),  'warn' (total number of errors of type
     "warn"), 'dated' (total number of error entries with date logged),
     and 'nodate' (total number of error entires with no date logged).  So:

          print "Total Errors: ", $errors{'Total'}, "\n";
          print "Total 1.3.x Errors: ", $errors{'error'}, "\n";
          print "Total 1.3.x Notices: ", $errors{'notice'}, "\n";
          print "Total 1.3.x Warns: ", $errors{'warn'}, "\n";
          print "Total Errors with date: ", $errors{'dated'}, "\n";
          print "Total Errors with no date: ", $errors{'nodate'}, "\n";

     Note that with the `ErrorLog' file generated by Apache version before
     1.3.x, the value for 'error', 'notice', and 'warn' will be zero.

   * `allbydate();'

          %allbydate = $errorlogobject->allbydate();

     Returns a hash containing date (mm/dd/yyyy) when the error was logged
     as keys, and the number of error occurrances as values.

   * `allbytime();'

          %allbytime = $errorlogobject->allbytime();

     Returns a hash containing time (00-23) as keys and the number of
     error occurrances as values.

   * `allbydatetime();'

          %allbydatetime = $errorlogobject->allbydatetime();

     Returns a hash containing date/time (mm/dd/yyyy-hh) as keys and the
     number of error occurrances as values.

   * `allmessage();'

          %allmessage = $errorlogobject->allmessage();

     Returns a hash containing error messages as keys and the number of
     occurrances as values.

   * `errorbydate();'

          %errorbydate = $errorlogobject->errorbydate();

     Returns a hash containing date (mm/dd/yyyy) as keys and the number of
     error occurrances as values. For the Apache 1.3.x log only.

   * `errorbytime();'

          %errorbytime = $errorlogobject->errorbytime();

     Returns a hash containing time (00-23) as keys and the number of
     error occurrances as values. For the Apache 1.3.x log only.

   * `errorbydatetime();'

          %errorbydatetime = $errorlogobject->errorbydatetime();

     Returns a hash containing date/time (mm/dd/yyyy-hh) as keys and the
     number of error occurrances as values. For the Apache 1.3.x log only.

   * `errormessage();'

          %errormessage = $errorlogobject->errormessage();

     Returns a hash containing error messages as keys and the number of
     occurrances as values. For the Apache 1.3.x log only.

   * `noticebydate();'

          %noticebydate = $errorlogobject->noticebydate();

     Returns a hash containing date (mm/dd/yyyy) as keys and the number of
     error occurrances as values. For the Apache 1.3.x log only.

   * `noticebytime();'

          %noticebytime = $errorlogobject->noticebytime();

     Returns a hash containing time (00-23) as keys and the number of
     error occurrances as values. For the Apache 1.3.x log only.

   * `noticebydatetime();'

          %noticebydatetime = $errorlogobject->noticebydatetime();

     Returns a hash containing date/time (mm/dd/yyyy-hh) as keys and the
     number of error occurrances as values. For the Apache 1.3.x log only.

   * `noticemessage();'

          %noticemessage = $errorlogobject->noticemessage();

     Returns a hash containing notice messages as keys and the number of
     occurrances as values. For the Apache 1.3.x log only.

   * `warnbydate();'

          %warnbydate = $errorlogobject->warnbydate();

     Returns a hash containing date (mm/dd/yyyy) as keys and the number of
     error occurrances as values. For the Apache 1.3.x only.

   * `warnbytime();'

          %warnbytime = $errorlogobject->warnbytime();

     Returns a hash containing time (00-23) as keys and the number of
     error occurrances as values. For the Apache 1.3.x only.

   * `warnbydatetime();'

          %warnbydatetime = $errorlogobject->warnbydatetime();

     Returns a hash containing date/time (mm/dd/yyyy-hh) as keys and the
     number of error occurrances as values. For the Apache 1.3.x only.

   * `warnmessage();'

          %warnmessage = $errorlogobject->warnmessage();

     Returns a hash containing warn messages as keys and the number of
     occurrances as values. For the Apache 1.3.x only.

RefererLog/CustomLog Methods
----------------------------

   The following methods are available for the `RefererLog' object
(created by `getRefererLog()' method), as well as the `CustomLog' object
that logs `%{Referer}i' to the corresponding `LogFormat'.

   * `referer();'

          %referer = $logobject->referer();

     Returns a hash containing the name of the web site the visitor comes
     from as keys, and the hit count for each key as values.

     Note that the returned data from this method contains *only* the site
     name of the referer, e.g. "www.altavista.digital.com", so if you want
     to obtain the full details of the referer as well as the referred
     files, use `refererdetail()' method described below.

   * `refererdetail();'

     Returns a hash containing the full URL of the referer as keys, and the
     hit count for each key as values.

     The standard log format for the `RefererLog' is <*referer* -> URL>.
     With the `CustomLog' object, the object attempts to use the URL first,
     and if the URL is not logged, then the relative path, and then the
     absolute path to create the key for the returned data *%referer*. If
     none of the URL, relative or absolute paths are logged, the object
     will use only the referer URL itself (without refererd files) as the
     key.

AgentLog/CustomLog Methods
--------------------------

   This subsection describes the methods available for the `AgentLog'
object (created by `getAgentLog()' method), as well as the `CustomLog'
object that logs `%{User-agent}i' to the corresponding `LogFormat'.

   * `uagent();'

          %uagent = $logobject->uagent();

     Returns a hash containing the user agent (the "full name", as you see
     in the log file itself) as keys, and the hit count for each key as
     values.

   * `uaversion();'

          %uaversion = $logobject->uaversion();

     Returns a hash containing the most basic and simple information about
     the user agent (the first column in the agent log file, e.g.
     "`Mozilla/4.06'") as keys, and the hit count for each key as values.
     Useful to collect the information about the parser engine and its
     version, to determine which specs of HTML and/or JavaScript to
     deploy, for example.

   * `browser();'

          %browser = $logobject->browser();

     Returns a hash containing the actual browsers (as logged in the file)
     as keys, and the hit count for each key as values.

     For example, Netscape Navigator/Communicator will (still) be reported
     as "`Mozilla/*version*'", Microsoft Internet Explorer  as "`MSIE
     *version*'", and so on.

   * `platform();'

          %platform = $logobject->platform();

     Returns a hash containing the names of OS (and possibly its version,
     hardware architecture, etc.) as keys, and the hit count for each key
     as values.

     For example, Solaris 2.6 on UltraSPARC will be reported as "`SunOS
     5.6 sun4u'",

   * `browserbyos();'

          %browserbyos = $logobject->browserbyos();

     Returns a hash containing the browser names with OS (in the form,
     *browser (OS)*) as keys, and the hit count for each key as values.

CustomLog Methods
-----------------

   This subsection describes the methods available only for the `CustomLog'
object. See each method for what Apache directive is used for each
returned result.

   * `addr();'

          %addr = $logobject->addr();

     Returns a hash containing the IP addresses of the *web site* (instead
     of the `ServerName') visited as keys, and the hit count for each key
     as values. (LogFormat `%a')

   * `filename();'

          %filename = $logobject->filename();

     Returns a hash containing the absolute paths to the files as keys, and
     the hit count for each key as values. (LogFormat `%f')

   * `hostname();'

          %hostname = $logobject->hostname();

     Returns a hash containing the hostnames of the visitors as keys, and
     the hit count for each key as values. (LogFormat `%v')

   * `ostatus();'

          %ostatus = $logobject->ostatus();

     Returns a hash containing HTTP codes and messages (e.g. "404 Not
     Found") for the original status (i.e., when the httpd starts
     processing that request) as keys, and the hit count for each key as
     values.

   * port();

          %port = $logobject->port();

     Returns a hash containing the port used for the transfer as keys, and
     the hit count for each key as values (there will probably be the only
     one key-value pair value for each server). (LogFormat `%p')

   * `proc();'

          %proc = $logobject->proc();

     Returns a hash containing the process ID of the server used for each
     file transfer as keys, and the hit count for each key as values.
     (LogFormat `%P')

   * `sec();'

          %sec = $logobject->sec();

     Returns a hash containing the file names (either relative paths,
     absolute paths, or the URL, depending on your log format) as keys,
     and the maximum seconds it takes to finish the process as values.
     Thus, note that the values are not accumulated results, but rather
     the highest number of seconds it took to process the file.
     (LogFormat %T)

   * `url();'

          %url = $logobject->url();

     Returns a hash containing the URLs (path relative to the
     `DocumentRoot'> as keys, and the hit count for each key as values.
     (LogFormat `%U')

Special Method
--------------

   The special method described below, `getMethods()', can be used with
any of the *log objects* to extract the methods available for the calling
object.

   * `getMethods();'

          @object_methods = $logobject->getMethods();

     Returns an array containing the names of the available methods for
     that log object. Each of the elements in the array is the name of one
     of the methods described in this section.

     By using this method, you can write a *really* simple Apache log
     parsing and reporting script, like so:

          #!/usr/local/bin/perl
          $|++; # flush buffer
          use Apache::ParseLog;
          # Construct the Apache::ParseLog object
          $base = new Apache::ParseLog("/usr/local/httpd/conf/httpd.conf");
          # Get the CustomLog object for "my_custom_log"
          $customlog = $base->getCustomLog("my_custom_log");
          # Get the available methods for the CustomLog object
          @methods = $customlog->getMethods();
          # Iterate through the @methods
          foreach $method (@methods) {
              print "$method log report\n";
              # Get the returned value for each method
              %{$method} = $customlog->$method();
              # Iterate through the returned hash
              foreach (sort keys %{$method}) {
                  print "$_: ${$method}{$_}\n";
              }
              print "\n";
          }
          exit;

MISCELLANEOUS
=============

   This section describes some miscellaneous methods that might be useful.

   * `Version();'

     Returns a scalar containing the version of the Apache::ParseLog
     module.

Exported Methods
----------------

   This subsection describes *exported* methods provided by the
Apache::ParseLog module. (For the information about exported methods, see
Exporter(3).)

   Note that those exported modules can be used (called) just like local
(main package) subroutines.

   * `countryByCode();'

          %countryByCode = countryByCode();

     Returns a hash containing a hashtable of country-code top-level domain
     names as keys and country names as values. Useful for creating a
     report on "hits" by countries.

   * `statusByCode();'

          %statusByCode = statusByCode();

     Returns a hash containing a hashtable of status code of the Apache
     HTTPD server, as defined by RFC2068, as keys and meanings as values.

   * `sortHashByValue(%hash);'

          @sorted_keys = sortHashByValue(%hash);

     Returns an array containing keys of the *%hash* *numerically* sorted
     by the values of the *%hash*, by the descending order.

     Example

          # Get the custom log object
          $customlog = $log->getCustomLog("combined");
          # Get the log report on "file"
          %file = $customlog->file();
          # Sort the %file by hit counts, descending order
          @sorted_keys = sortHashByValue(%hash);
          foreach (@sorted_keys) {
              print "$_: $file{$_}\n"; # print <file>: <hitcount>
          }

EXAMPLES
========

   The most basic, easiest way to create reports is presented as an
example in the `getMethods()' section above, but the format of the output
is pretty crude and less user-friendly.

   Shown below are some other examples to use Apache::ParseLog.

Example 1: Basic Report
-----------------------

   The example code below checks the `TransferLog' and `ErrorLog'
generated by the Apache 1.2.x, and prints the reports to STDOUT.  (To run
this code, all you have to do is to change the *$conf* value.)

     #!/usr/local/bin/perl
     $|++;
     use Apache::ParseLog;

     $conf = "/usr/local/httpd/conf/httpd.conf";
     $base = new Apache::ParseLog($conf);

     print "TransferLog Report\n\n";
     $transferlog = $base->getTransferLog();

     %hit = $transferlog->hit();
     %hitbydate = $transferlog->hitbydate();
     print "Total Hit Counts: ", $hit{'Total'}, "\n";
     foreach (sort keys %hitbydate) {
         print "$_:\t$hitbydate{$_}\n"; # <date>: <hit counts>
     }
     $hitaverage = int($hit{'Total'} / scalar(keys %hitbydate));
     print "Average Daily Hits: $hitaverage\n\n";

     %byte = $transferlog->byte();
     %bytebydate = $transferlog->bytebydate();
     print "Total Bytes Transferred: ", $byte{'Total'}, "\n";
     foreach (sort keys %bytebydate) {
         print "$_:\t$bytebydate{$_}\n"; # <date>: <bytes transferred>
     }
     $byteaverage = int($byte{'Total'} / scalar(keys %bytebydate));
     print "Average Daily Bytes Transferred: $byteaverage\n\n";

     %visitorbydate = $transferlog->visitorbydate();
     %host = $transferlog->host();
     print "Total Unique Visitors: ", scalar(keys %host), "\n";
     foreach (sort keys %visitorbydate) {
         print "$_:\t$visitorbydate{$_}\n"; # <date: <visitor counts>
     }
     $visitoraverage = int(scalar(keys %host) / scalar(keys %visitorbydate));
     print "Average Daily Unique Visitors: $visitoraverage\n\n";

     print "ErrorLog Report\n\n";
     $errorlog = $base->getErrorLog();

     %count = $errorlog->count();
     %allbydate = $errorlog->allbydate();
     print "Total Errors: ", $count{'Total'}, "\n";
     foreach (sort keys %allbydate) {
         print "$_:\t$allbydate{$_}\n"; # <date>: <error counts>
     }
     $erroraverage = int($count{'Total'} / scalar(keys %allbydate));
     print "Average Daily Errors: $erroraverage\n\n";

     exit;

Example 2: Referer Report
-------------------------

   The `RefererLog' (or `CustomLog' with referer logged) contains the
referer for every single file requested. It means that everytime a page
that contains 10 images is requested, 11 lines are added to the
`RefererLog', one line for the actual referer (where the visitor comes
from), and the other 10 lines for the images with the *just refererd* page
containing the 10 images as the referer, which is probably a little too
much more than what you want to know.

   The example code below checks the `CustomLog' that contains referer,
(among other things), and reports the names of the referer sites that are
not the local server itself.

     #!/usr/local/bin/perl
     $|++;
     use Apache::ParseLog;

     $conf = "/usr/local/httpd/conf/httpd.conf";
     $base = new Apache::ParseLog($conf);

     $localserver = $base->servername();

     $log = $base->getCustomLog("combined");
     %referer = $log->referer();
     @sortedkeys = sortHashByValue(%referer);

     print "External Referers Report\n";
     foreach (@sortedkeys) {
         print "$_:\t$referer{$_}\n" unless m/$localserver/i or m/^\-/;
     }

     exit;

Example 3: Access-Controlled User Report
----------------------------------------

   Let's suppose that you have a directory tree on your site that is
access-controlled by `.htaccess' or the like, and you want to check how
frequently the section is used by the users.

     #!/usr/local/bin/perl
     $|++;
     use Apache::ParseLog;

     $conf = "/usr/local/httpd/conf/httpd.conf";
     $base = new Apache::ParseLog($conf);

     $log = $base->getCustomLog("common");
     %user = $log->user();

     print "Users Report\n";
     foreach (sort keys %user) {
         print "$_:\t$user{$_}\n" unless m/^-$/;
     }

     exit;

SEE ALSO
========

   perl(1), perlop(1), perlre(1), Exporter(3)

BUGS
====

   The reports on lesser-known browsers returned from the `AgentLog'
methods are not always informative.

   The data returned from the referer() method for `RefererLog' may be
irrelvant if the referred files are not accessed via HTTP (i.e., the
referer does not start with "http://" string).

   If the base object is created with the *$virtualhost* specified, unless
the `ServerAdmin' and `ServerName' are specified within the <VirtualHost
xxx> ... </VirtualHost>, those values specified in the global section of
the httpd.conf are not shared with the *$virtualhost*.

TO DO
=====

   Increase the performance (speed).

VERSION
=======

   Apache::ParseLog 1.01 (10/01/1998).

AUTHOR
======

   Apache::ParseLog was written and is maintained by Akira Hangai
(akira@discover-net.net)

   For the bug reports, comments, suggestions, etc., please email me.

COPYRIGHT
=========

   Copyright 1998, Akira Hangai. All rights reserved.

   This program is free software; You can redistribute it and/or modify it
under the same terms as Perl itself.

DISCLAIMER
==========

   This package is distributed in the hope that it will be useful for many
web administrators/webmasters who are too busy to write their own programs
to analyze the Apache log files. However, this package is so distributed
WITHOUT ANY WARRANTY in that any use of the data generated by this package
must be used at the user's own discretion, and the author shall not be
held accountable for any results from the use of this package.

run CGI and catch its output
****************************

NAME
====

   Apache::PassExec - run CGI and catch its output

SYNOPSIS
========

   In the conf/access.conf file of your Apache installation add lines

     <Files *.html>
     SetHandler perl-script
     PerlHandler Apache::OutputChain Apache::GzipChain Apache::PassExec
     </Files>

DESCRIPTION
===========

   Runs a script (process) and fetches its output, passes it to next
chained handlers.

AUTHOR
======

   (c) 1997-1998 Andreas Koenig, Jan Pazdziora

print a file to STDOUT
**********************

NAME
====

   Apache::PassFile - print a file to STDOUT

SYNOPSIS
========

   In the conf/access.conf file of your Apache installation add lines

     <Files *.html>
     SetHandler perl-script
     PerlHandler Apache::OutputChain Apache::GzipChain Apache::PassFile
     </Files>

DESCRIPTION
===========

   This handler implements nothing but a quite efficient cat(1) in perl.
While it innocently prints to STDOUT it may well be the case that STDOUT
has been tied, and that's the only reason why this module is needed. Once
we can stack any apache modules on top of each other, this module becomes
obsolete.

   PassFile reads files from disk in chunks of size BUFFERSIZE.
BUFFERSIZE is a global variable that can be set via the BUFFERSIZE method.
The default value is 16384.

CONFIGURATION
=============

   Per default the module sets the `Last Modified' header. It requires
HTTP::Date in order to do so. You can suppress that by setting

     PerlSetVar no_mtime true

AUTHOR
======

   (c) 1997 Jan Pazdziora, adelton@fi.muni.cz, at Faculty of Informatics,
Masaryk University, Brno (small performance changes by Andreas Koenig)

print out the html file
***********************

NAME
====

   Apache::PassHtml - print out the html file

SYNOPSIS
========

   In the conf/access.conf file of your Apache installation add lines

     <Files *.html>
     SetHandler perl-script
     PerlHandler Apache::OutputChain Apache::MakeCapital Apache::PassHtml
     </Files>

DESCRIPTION
===========

   This is simple script to show the use of module *Apache::OutputChain*.
It will pick up a html file and send it to the output, STDOUT. We assume
that the output is tied either to Apache (by default), or some
user-defined perl handler. We need to read and write to STDOUT in perl
since Apache will not pass its output into perl handlers.

AUTHOR
======

   (c) 1997-1998 Jan Pazdziora

A data debugging tool for the XS programmer
*******************************************

NAME
====

   Apache::Peek - A data debugging tool for the XS programmer

SYNOPSIS
========

     use Apache::Peek;
     Dump( $a );
     Dump( $a, 5 );
     DumpArray( 5, $a, $b, ... );
     	mstat "Point 5";

DESCRIPTION
===========

   Apache::Peek contains functions which allows raw Perl datatypes to be
manipulated from a Perl script.  This is used by those who do XS
programming to check that the data they are sending from C to Perl looks
as they think it should look.  The trick, then, is to know what the raw
datatype is supposed to look like when it gets to Perl.  This document
offers some tips and hints to describe good and bad raw data.

   It is very possible that this document will fall far short of being
useful to the casual reader.  The reader is expected to understand the
material in the first few sections of Perlguts (perl.info).

   Apache::Peek supplies a `Dump()' function which can dump a raw Perl
datatype, and `mstat("marker")' function to report on memory usage (if
perl is compiled with corresponding option).  The function DeadCode()
provides statistics on the data "frozen" into inactive CV.  Apache::Peek
also supplies `SvREFCNT()', `SvREFCNT_inc()', and `SvREFCNT_dec()' which
can query, increment, and decrement reference counts on SVs.  This
document will take a passive, and safe, approach to data debugging and for
that it will describe only the `Dump()' function.

   Function `DumpArray()' allows dumping of multiple values (useful when
you need to analize returns of functions).

   The global variable $Devel::Peek::pv_limit can be set to limit the
number of character printed in various string values.  Setting it to 0
means no limit.

EXAMPLES
========

   The following examples don't attempt to show everything as that would
be a monumental task, and, frankly, we don't want this manpage to be an
internals document for Perl.  The examples do demonstrate some basics of
the raw Perl datatypes, and should suffice to get most determined people
on their way.  There are no guidewires or safety nets, nor blazed trails,
so be prepared to travel alone from this point and on and, if at all
possible, don't fall into the quicksand (it's bad for business).

   Oh, one final bit of advice: take Perlguts (perl.info),
with you.  When you return we expect to see it well-thumbed.

A simple scalar string
----------------------

   Let's begin by looking a simple scalar which is holding a string.

     use Apache::Peek 'Dump';
     $a = "hello";
     Dump $a;

   The output:

     SV = PVIV(0xbc288)
       REFCNT = 1
       FLAGS = (POK,pPOK)
       IV = 0
       PV = 0xb2048 "hello"\0
       CUR = 5
       LEN = 6

   This says `$a' is an SV, a scalar.  The scalar is a PVIV, a string.
Its reference count is 1.  It has the `POK' flag set, meaning its current
PV field is valid.  Because POK is set we look at the PV item to see what
is in the scalar.  The \0 at the end indicate that this PV is properly
NUL-terminated.  If the FLAGS had been IOK we would look at the IV item.
CUR indicates the number of characters in the PV.  LEN indicates the
number of bytes requested for the PV (one more than CUR, in this case,
because LEN includes an extra byte for the end-of-string marker).

A simple scalar number
----------------------

   If the scalar contains a number the raw SV will be leaner.

     use Apache::Peek 'Dump';
     $a = 42;
     Dump $a;

   The output:

     SV = IV(0xbc818)
       REFCNT = 1
       FLAGS = (IOK,pIOK)
       IV = 42

   This says `$a' is an SV, a scalar.  The scalar is an IV, a number.  Its
reference count is 1.  It has the `IOK' flag set, meaning it is currently
being evaluated as a number.  Because IOK is set we look at the IV item to
see what is in the scalar.

A simple scalar with an extra reference
---------------------------------------

   If the scalar from the previous example had an extra reference:

     use Apache::Peek 'Dump';
     $a = 42;
     $b = \$a;
     Dump $a;

   The output:

     SV = IV(0xbe860)
       REFCNT = 2
       FLAGS = (IOK,pIOK)
       IV = 42

   Notice that this example differs from the previous example only in its
reference count.  Compare this to the next example, where we dump $b
instead of `$a'.

A reference to a simple scalar
------------------------------

   This shows what a reference looks like when it references a simple
scalar.

     use Apache::Peek 'Dump';
     $a = 42;
     $b = \$a;
     Dump $b;

   The output:

     SV = RV(0xf041c)
       REFCNT = 1
       FLAGS = (ROK)
       RV = 0xbab08
     SV = IV(0xbe860)
       REFCNT = 2
       FLAGS = (IOK,pIOK)
       IV = 42

   Starting from the top, this says $b is an SV.  The scalar is an RV, a
reference.  It has the `ROK' flag set, meaning it is a reference.  Because
ROK is set we have an RV item rather than an IV or PV.  Notice that Dump
follows the reference and shows us what $b was referencing.  We see the
same `$a' that we found in the previous example.

   Note that the value of RV coincides with the numbers we see when we
stringify $b. The addresses inside RV() and IV() are addresses of `X***'
structure which holds the current state of an SV. This address may change
during lifetime of an SV.

A reference to an array
-----------------------

   This shows what a reference to an array looks like.

     use Apache::Peek 'Dump';
     $a = [42];
     Dump $a;

   The output:

     SV = RV(0xf041c)
       REFCNT = 1
       FLAGS = (ROK)
       RV = 0xb2850
     SV = PVAV(0xbd448)
       REFCNT = 1
       FLAGS = ()
       IV = 0
       NV = 0
       ARRAY = 0xb2048
       ALLOC = 0xb2048
       FILL = 0
       MAX = 0
       ARYLEN = 0x0
       FLAGS = (REAL)
     Elt No. 0 0xb5658
     SV = IV(0xbe860)
       REFCNT = 1
       FLAGS = (IOK,pIOK)
       IV = 42

   This says `$a' is an SV and that it is an RV.  That RV points to
another SV which is a PVAV, an array.  The array has one element, element
zero, which is another SV. The field FILL above indicates the last element
in the array, similar to `$#$a'.

   If `$a' pointed to an array of two elements then we would see the
following.

     use Apache::Peek 'Dump';
     $a = [42,24];
     Dump $a;

   The output:

     SV = RV(0xf041c)
       REFCNT = 1
       FLAGS = (ROK)
       RV = 0xb2850
     SV = PVAV(0xbd448)
       REFCNT = 1
       FLAGS = ()
       IV = 0
       NV = 0
       ARRAY = 0xb2048
       ALLOC = 0xb2048
       FILL = 0
       MAX = 0
       ARYLEN = 0x0
       FLAGS = (REAL)
     Elt No. 0  0xb5658
     SV = IV(0xbe860)
       REFCNT = 1
       FLAGS = (IOK,pIOK)
       IV = 42
     Elt No. 1  0xb5680
     SV = IV(0xbe818)
       REFCNT = 1
       FLAGS = (IOK,pIOK)
       IV = 24

   Note that `Dump' will not report all the elements in the array, only
several first (depending on how deep it already went into the report tree).

A reference to a hash
---------------------

   The following shows the raw form of a reference to a hash.

     use Apache::Peek 'Dump';
     $a = {hello=>42};
     Dump $a;

   The output:

     SV = RV(0xf041c)
       REFCNT = 1
       FLAGS = (ROK)
       RV = 0xb2850
     SV = PVHV(0xbd448)
       REFCNT = 1
       FLAGS = ()
       NV = 0
       ARRAY = 0xbd748
       KEYS = 1
       FILL = 1
       MAX = 7
       RITER = -1
       EITER = 0x0
     Elt "hello" => 0xbaaf0
     SV = IV(0xbe860)
       REFCNT = 1
       FLAGS = (IOK,pIOK)
       IV = 42

   This shows `$a' is a reference pointing to an SV.  That SV is a PVHV, a
hash. Fields RITER and EITER are used by ``each' in this node'.

Dumping a large array or hash
-----------------------------

   The `Dump()' function, by default, dumps up to 4 elements from a
toplevel array or hash.  This number can be increased by supplying a
second argument to the function.

     use Apache::Peek 'Dump';
     $a = [10,11,12,13,14];
     Dump $a;

   Notice that `Dump()' prints only elements 10 through 13 in the above
code.  The following code will print all of the elements.

     use Apache::Peek 'Dump';
     $a = [10,11,12,13,14];
     Dump $a, 5;

A reference to an SV which holds a C pointer
--------------------------------------------

   This is what you really need to know as an XS programmer, of course.
When an XSUB returns a pointer to a C structure that pointer is stored in
an SV and a reference to that SV is placed on the XSUB stack.  So the
output from an XSUB which uses something like the T_PTROBJ map might look
something like this:

     SV = RV(0xf381c)
       REFCNT = 1
       FLAGS = (ROK)
       RV = 0xb8ad8
     SV = PVMG(0xbb3c8)
       REFCNT = 1
       FLAGS = (OBJECT,IOK,pIOK)
       IV = 729160
       NV = 0
       PV = 0
       STASH = 0xc1d10       "CookBookB::Opaque"

   This shows that we have an SV which is an RV.  That RV points at another
SV.  In this case that second SV is a PVMG, a blessed scalar.  Because it
is blessed it has the OBJECT flag set.  Note that an SV which holds a C
pointer also has the `IOK' flag set.  The STASH is set to the package name
which this SV was blessed into.

   The output from an XSUB which uses something like the T_PTRREF map,
which doesn't bless the object, might look something like this:

     SV = RV(0xf381c)
       REFCNT = 1
       FLAGS = (ROK)
       RV = 0xb8ad8
     SV = PVMG(0xbb3c8)
       REFCNT = 1
       FLAGS = (IOK,pIOK)
       IV = 729160
       NV = 0
       PV = 0

A reference to a subroutine
---------------------------

   Looks like this:

     SV = RV(0x798ec)
       REFCNT = 1
       FLAGS = (TEMP,ROK)
       RV = 0x1d453c
     SV = PVCV(0x1c768c)
       REFCNT = 2
       FLAGS = ()
       IV = 0
       NV = 0
       COMP_STASH = 0x31068  "main"
       START = 0xb20e0
       ROOT = 0xbece0
       XSUB = 0x0
       XSUBANY = 0
       GVGV::GV = 0x1d44e8   "MY" :: "top_targets"
       FILEGV = 0x1fab74     "_<(eval 5)"
       DEPTH = 0
       PADLIST = 0x1c9338

   This shows that

     the subroutine is not an XSUB (since START and ROOT are non-zero, and
     XSUB is zero);

     that it was compiled in the package main;

     under the name `MY::top_targets';

     inside a 5th eval in the program;

     it is not currently executed (see DEPTH);

     it has no prototype (`PROTOTYPE' field is missing).

EXPORTS
=======

   `Peek', `mstats', `DeadCode' by default. Additionally available
SvREFCNT, SvREFCNT_inc, SvREFCNT_dec.

BUGS
====

   Readers have been known to skip important parts of Perlguts (perl.info),
causing much frustration for all.

SEE ALSO
========

   See Perlguts (perl.info), and Perlguts (perl.info),
again.

Run unaltered CGI scripts under mod_perl
****************************************

NAME
====

   Apache::PerlRun - Run unaltered CGI scripts under mod_perl

SYNOPSIS
========

     #in httpd.conf

     Alias /cgi-perl/ /perl/apache/scripts/
     PerlModule Apache::PerlRun

     <Location /cgi-perl>
     SetHandler perl-script
     PerlHandler Apache::PerlRun
     Options +ExecCGI
     #optional
     PerlSendHeader On
     ...
     </Location>

DESCRIPTION
===========

   This module's handler emulates the CGI environment, allowing
programmers to write scripts that run under CGI or mod_perl without
change.  Unlike Apache::Registry, the *Apache::PerlRun* handler does not
cache the script inside of a subroutine.  Scripts will be "compiled" every
request.  After the script has run, it's namespace is flushed of all
variables and subroutines.

   The Apache::Registry handler is much faster than *Apache::PerlRun*.
However, *Apache::PerlRun* is much faster than CGI as the fork is still
avoided and scripts can use modules which have been pre-loaded at server
startup time.  This module is meant for "Dirty" CGI Perl scripts which
relied on the single request lifetime of CGI and cannot run under
Apache::Registry without cleanup.

CAVEATS
=======

   If your scripts still have problems running under the *Apache::PerlRun*
handler, the *PerlRunOnce* option can be used so that the process running
the script will be shutdown.  Add this to your httpd.conf:

     <Location ...>
     PerlSetVar PerlRunOnce On
     ...
     </Location>

SEE ALSO
========

   perl(1), mod_perl(3), Apache::Registry(3)

AUTHOR
======

   Doug MacEachern

run Perl scripts in an Apache::Filter chain
*******************************************

NAME
====

   Apache::PerlRunFilter - run Perl scripts in an Apache::Filter chain

SYNOPSIS
========

     #in httpd.conf

     PerlModule Apache::PerlRunFilter

     # Run the output of scripts through Apache::SSI
     <Files ~ "\.pl$">
      SetHandler perl-script
      PerlHandler Apache::PerlRunFilter Apache::SSI
      PerlSetVar Filter on
     </Files>

     # Generate some Perl code using templates, then execute it
     <Files ~ "\.tmpl$">
      SetHandler perl-script
      PerlHandler YourModule::GenCode Apache::PerlRunFilter
      PerlSetVar Filter on
     </Files>

DESCRIPTION
===========

   This module is a subclass of Apache::PerlRun, and contains all of its
functionality.  The only difference between the two is that this module
can be used in conjunction with the Apache::Filter module, whereas
Apache::PerlRun cannot.

   It only takes a tiny little bit of code to make the filtering stuff
work, so perhaps it would be more appropriate for the code to be
integrated right into Apache::PerlRun.  As it stands, I've had to
duplicate a bunch of PerlRun's code here (in the handler routine), so bug
fixes & feature changes must be made both places.

CAVEATS
=======

   Note that this is not an exact replacement for Apache::Registry - it
doesn't do any of the code-caching stuff that Registry does.  It shouldn't
be too hard a task, but for now Registry is still based on old code, and
Doug's plan is to make future versions of Registry by subclassing PerlRun
(see Apache::RegistryNG).  Since this is the case, I figured I'd hold off
on doing any Registry work until things have moved forward a bit.

SEE ALSO
========

   perl(1), mod_perl(3), Apache::PerlRun(3)

AUTHOR
======

   Ken Williams <ken@forum.swarthmore.edu>

XS implementation of Apache::PerlRun/Apache::Registry
*****************************************************

NAME
====

   Apache::PerlRunXS - XS implementation of
Apache::PerlRun/Apache::Registry

SYNOPSIS
========

     #in httpd.conf

     Alias /perl/ /perl/apache/scripts/
     PerlModule Apache::PerlRunXS

     <Location /perl>
     SetHandler perl-script
     PerlHandler Apache::RegistryXS
     Options +ExecCGI
     #optional
     PerlSendHeader On
     ...
     </Location>

DESCRIPTION
===========

   This XS implementation of Apache::PerlRun and Apache::Registry will
some day replace the Perl versions.

SEE ALSO
========

   perl(1), mod_perl(3), Apache::Registry(3)

AUTHOR
======

   Doug MacEachern

Utilities for work with <Perl> sections
***************************************

NAME
====

   Apache::PerlSections - Utilities for work with <Perl> sections

SYNOPSIS
========

     use Apache::PerlSections ();

DESCRIPTION
===========

   It is possible to configure you server entirely in Perl using <Perl>
sections in httpd.conf.  This module is here to help you with such a task.

METHODS
=======

dump
     This method will dump out all the configuration variables mod_perl
     will be feeding the the apache config gears.  The output is suitable
     to read back in via eval.

     Example:

          <Perl>

          use Apache::PerlSections ();

          $Port = 8529;

          $Location{"/perl"} = {
              SetHandler => "perl-script",
              PerlHandler => "Apache::Registry",
              Options => "ExecCGI",
          };

          @DocumentIndex = qw(index.htm index.html);

          $VirtualHost{"www.foo.com"} = {
              DocumentRoot => "/tmp/docs",
              ErrorLog => "/dev/null",
              Location => {
          	 "/" => {
          	     Allowoverride => 'All',
          	     Order => 'deny,allow',
          	     Deny  => 'from all',
          	     Allow => 'from foo.com',
          	 },
              },
          };

          print Apache::PerlSections->dump;

          </Perl>

     This will print something like so:

          package Apache::ReadConfig;
          #scalars:

          $Port = 8529;

          #arrays:

          @DocumentIndex = (
            'index.htm',
            'index.html'
          );

          #hashes:

          %Location = (
            '/perl' => {
              PerlHandler => 'Apache::Registry',
              SetHandler => 'perl-script',
              Options => 'ExecCGI'
            }
          );

          %VirtualHost = (
            'www.foo.com' => {
              Location => {
                '/' => {
                  Deny => 'from all',
                  Order => 'deny,allow',
                  Allow => 'from foo.com',
                  Allowoverride => 'All'
                }
              },
              DocumentRoot => '/tmp/docs',
              ErrorLog => '/dev/null'
            }
          );

          1;
          __END__

store
     This method will call the dump method, writing the output to a file,
     suitable to be pulled in via require.

     Example:

          Apache::PerlSections->store("httpd_config.pl");

          require 'httpd_config.pl';

SEE ALSO
========

   mod_perl(1), Data::Dumper(3), Devel::Symdump(3)

AUTHOR
======

   Doug MacEachern

Allows versioning of modules among directories or v-hosts.
**********************************************************

NAME
====

     Apache::PerlVINC - Allows versioning of modules among directories or v-hosts.

SYNOPSIS
========

   #example httpd.conf:

   <VirtualHost dave.domain.com>

     # include the module. this line must be here.
     PerlModule Apache::PerlVINC

     # set the include path
     PerlINC /home/dave/site/files/modules
     # make sure VINC reloads the modules
     PerlFixupHandler Apache::PerlVINC
     # aptionally have VINC unload versioned modules
     PerlCleanupHandler Apache::PerlVINC

     # reloads Stuff::Things for all requests
     PerlVersion Stuff/Things.pm

     <Location /Spellcheck>
       SetHandler perl-script
       PerlHandler Spellcheck

     # reload version of this module found in PerlINC line
     PerlVersion Spellcheck.pm
       </Location>

   </VirtualHost>

   <VirtualHost steve.domain.com>

     PerlModule Apache::PerlVINC

     <Location /Spellcheck>
       SetHandler perl-script
       PerlHandler Spellcheck
       PerlFixupHandler Apache::PerlVINC
       # only reload for requests in /Spellcheck

     PerlINC /home/steve/site/files/modules
     PerlVersion Spellcheck.pm  # makes PerlVINC load this version
       </Location>

   </VirtualHost>

DESCRIPTION
===========

   With this module you can run two copies of a module without having to
worry about which version is being used. Suppose you have two `VirtualHost'
or Location that want to each use their own version of `Spellcheck.pm'.
Durning the FixUp phase, `Apache::PerlVINC' will tweak `@INC' and reload
`Spellcheck'. Optionally, it will unload that version if you specify
`Apache::PerlVINC' as a PerlCleanUpHandler.

   As you can guess, this module slows things down a little because it
unloads and reloads on a per-request basis. Hence, this module should only
be used in a development environment, not a mission critical one.

DIRECTIVES
==========

PerlINC
     Takes only one argument: the path to be prepended to `@INC'. In v0.1,
     this was stored internally as an array. This is no longer the case.
     However, it still works somewhat as expected in that subsequent calls
     to PerlINC will not overwrite the previous ones, provided they are
     not in the same config section (see BUGS). They will both be
     prepended to `@INC'. Note that `@INC' is not changed for the entire
     request, so dont count on that path being in `@INC' for your scripts.

PerlVersion
     This directives specifies the files you want reloaded. Depending on
     where this directive sits, files will be loaded (and perhaps
     unloaded). Ie. if this sits in a Location section, the files will
     only be reloaded on requests to that location.  If this lies in a
     server section, all requests to the server or v-host will have these
     files reloaded.

BUGS AND LIMITATIONS
====================

   Under some setups, `PerlModule''ing PerlVINC will cause the server to
silently crash on startup. Upgrading `Apache::ExtUtils' to v/1.04 might
fix the problem. As of this writing, the current version of mod_perl
(1.24) does not contain this version of `Apache::ExtUtils'. Until the next
version is released, you will have to obtain it from the latest cvs
snapshot.

   If the PerlINC directive is used twice in the same config section, the
first call will be overwritten. Ie.

     PerlINC /qwe
     PerlINC /poi

     <Location /asdf/>
       PerlINC /zxc
     </Location>

   For requests outside of /asdf/, @INC will contain /poi. Inside /asdf/
@INC will contain /zxc and /poi. This is kinda sucky, I know, and I hope
to fix for the next release.

AUTHORS
=======

     Doug MacEachern <dougm@pobox.com>
     Dave Moore <dave@epals.com>

COPYRIGHT
=========

   This library is free software. You can redistribute it and/or modify it
under the same terms as Perl itself.

Apache mod_perl PerlHandler for nicer output perl files in the client's browser.
********************************************************************************

NAME
====

   *Apache::PrettyPerl* - Apache mod_perl PerlHandler for nicer output
perl files in the client's browser.

SYNOPSIS
========

   You must be using mod_perl. See http://perl.apache.org for details.
For the correct work your apache configuration would contain apache
directives look like these:

     # in httpd.conf (or any other apache configuration file)

     AddType	text/html	.pl	.pm

     <Files ~ "\.p[lm]$">
       SetHandler		perl-script
       PerlHandler		Apache::PerttyPerl
       PerlSetVar		TabSize 	8	# optional
       PerlSetVar		AllowDownload	On	# optional
     </Files>

   There is only example of apache configuration. Most probably you should
like place <Files> directive inside <Directory> directive.  Otherwise will
be handled all perl files, including CGI and mod_perl scripts.

DESCRIPTION
===========

   This is apache handler that converts perl files on the fly into syntax
highlighted HTML. So your perl scripts/modules will be look nicer. Also
possibly download original perl file (without syntax highlight).

CONFIGURATION DIRECTIVES
========================

   All features of the this PerlHandler, will be setting in the apache
confihuration files. For this you can use PerlSetVar apache directive. For
example:

     PerlSetVar	TabSize	8   # inside <Files>, <Location>, ...
     			    # apache directives

TabSize
     Setting size of the tab (\t) symbol. Default is 8.

AllowDownload
     If it setting to On at the end of the page will be displayed Download
     link, which allow download original file. Default is Off.

SEE ALSO
========

   perl(1), mod_perl(3), Apache(3)

AUTHOR
======

   Roman Kosenko

Contact info
------------

   E-mail:	ra@amk.lg.ua

   Home page: http://amk.lg.ua/~ra/PrettyPerl

Copyright
---------

   Copyright (c) 2000 Roman Kosenko.  All rights reserved.  This package
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

A very simple apache mod_perl PerlHandler for text files
********************************************************

NAME
====

   Apache::PrettyText - A very simple apache mod_perl PerlHandler for text
files

SYNOPSIS
========

   To modify your Apache server to dynamically format .txt files so they
look nicer in the client's browser, put the following directives into
httpd.conf, or in any VirtualHost section and restart the server.

   Optional: Insert a <Perl> section that changes
$Apache::PrettyText::TabWidth to your site's standard or set to 0 to
disable detabbing.  If you don't set it, the default is 4.

     <Perl>
     $Apache::PrettyText::TabWidth = 4;
     </ Perl> ## <-- Omit the space if you copy this example.

     <Files ~ "\.txt$">
     SetHandler perl-script
     PerlHandler Apache::PrettyText
     </Files>

   You must be using mod_perl. See http://perl.apache.org for details.

DESCRIPTION
===========

   This is a simple Apache handler written in Perl that converts text
files on the fly into a basic HTML format:

   * surrounded by <PRE> tags

   * tabs converted to spaces (optional)

   * white background

   * hilited URLs

   * first line of text file = <TITLE>

   Also serves as a good template to help you write your own simple

   handler.  I wrote this as an exercise because I found no good examples.

INSTALLATION
============

   If you're reading this in pod or man, it's already installed.  If
you're reading the source code in PrettyText.pm, you can copy this file
under the name "PrettyText.pm" into this location:

     /usr/lib/perl5/site_perl/Apache/

   ... or its equivalent on your computer.

   A helpful tip: you can include the entire contents of the PrettyText.pm
file or of your own version of it into a <Perl> section within httpd.conf.
This can be very helpful if you'd like to use this module as a template
for your own.

   To syntax-check your code under those circumstances, use:

     perl -cx httpd.conf

   ... which will read just the perl code between #!...perl and __END__ in
the httpd.conf file.

AUTHOR
======

     Chris Thorman <chris@thorman.com>
     Ignition, Inc.
     http://ignitiondesign.com

   Thanks to Vivek Khera, Doug MacEachern, Jeffrey William Baker for
suggestions and corrections.

COPYRIGHT
=========

   Available for use by anyone under the GNU General Public License.  Not
really supported, but further comments, suggestions, and corrections are
heartily solicited.

SEE ALSO
========

   Apache(3), mod_perl, http://perl.apache.org/src/contrib

Perl interface to mod_proxy
***************************

NAME
====

   Apache::Proxy - Perl interface to mod_proxy

SYNOPSIS
========

     use Apache::Proxy ();

DESCRIPTION
===========

     my $status = Apache::Proxy->pass($r, "http://perl.apache.org/");
     my $hashfile = Apache::Proxy->proxy_hash($r, $url);

AUTHOR
======

   Doug MacEachern, Ilya Obshadko

SEE ALSO
========

   perl(1).

Small backend to get information from doc server to mod_perl server
*******************************************************************

NAME
====

   Apache::Proxy::Info - Small backend to get information from doc server
to mod_perl server

SYNOPSIS
========

     PerlModule Apache::Proxy::Info
     PerlTransHandler Aache::Proxy::Info

DESCRIPTION
===========

   This is a simple combination of a small C module for apache and another
one in Perl for mod_perl

   In lots of cases , you end up with a lightweight docserver in front of
a heavyweight mod_perl enabled server.  This is a good thing for speed and
performance (see http://perl.apache.org/guide).

   The problem this combination tries to solve is that the mod_perl server
doesn't know anything about the client connection, since it's only talking
to a doc server.

   Install the C module in the doc server like so

   cd apache-src ./configure -with-plenty-of-options
-add-module=/path/to/mod_proxy_add_info.c

   And you just need to put the Perl module in the mod_perl server perl
Makefile.PL make && make test && make install

   And in httpd.conf PerlModule Apache::Proxy::Info PerlTransHandler
Apache::Proxy::Info;

   Currently 3 pieces of information are passed thru

   $r->connection->remote_ip() $ENV{'HTTPS'} $r->header_in('Host');

   Enjoy!

AUTHOR
======

   Philippe M. Chiasson <gozer@hbesoftware.com>

SEE ALSO
========

   perl(1).

implement ProxyPass in perl
***************************

NAME
====

   Apache::ProxyPass - implement ProxyPass in perl

SYNOPSIS
========

     #httpd.conf or some such
      PerlSetVar ProxyPass_filename /xxx/proxy.conf

   <Location /foo>   SetHandler perl-script   PerlHandler Apache::ProxyPass
</Location>

   #proxy.conf looks like

     /foo/apache http://www.apache.org
     /foo/perl http://www.perl.com

DESCRIPTION
===========

   Implement the apache mod_proxy module in perl.  Based on
Apache::ProxyPassThru

AUTHOR
======

   Michael Smith <mjs@iii.co.uk>

Skeleton for vanilla proxy
**************************

NAME
====

   Apache::ProxyPassThru - Skeleton for vanilla proxy

SYNOPSIS
========

     #httpd.conf or some such
     PerlTransHandler  Apache::ProxyPassThru
     PerlSetVar        ProxyPassThru_DumpHeaders 1

DESCRIPTION
===========

   This module uses libwww-perl as it's web client, feeding the response
back into the Apache API request_rec structure.  `PerlHandler' will only
be invoked if the request is a proxy request, otherwise, your normal
server configuration will handle the request.

   If used with the Apache::DumpHeaders module it lets you view the
headers from another site you are accessing.

PARAMETERS
==========

   This module is configured with PerlSetVar's.

ProxyPassThru_DumpHeaders
-------------------------

   If this is set to a true value we'll set r->notes("DumpHeaders") to
"proxypassthru" to get the request logged in the log. This is usually what
you want.

   Makes it easy to have Apache::DumpHeaders only dump headers from your
proxied requests.

SUPPORT
=======

   The latest version of this module can be found at CPAN and at `http:'
in this node. Send questions and suggestions to the modperl mailinglist
(see `http:' in this node for information) or directly to the author (see
below).

SEE ALSO
========

   mod_perl(3), Apache(3), LWP::UserAgent(3)

AUTHOR
======

   Ask Bjoern Hansen <ask@develooper.com>.

   Originally by Doug MacEachern.

mod_perl URL-rewriting proxy
****************************

NAME
====

   Apache::ProxyRewrite - mod_perl URL-rewriting proxy

SYNOPSIS
========

     <Location    />
     SetHandler   perl-script
     PerlHandler  Apache::ProxyRewrite

     PerlSetVar   ProxyTo           http://www.tivoli.com
     PerlSetVar   ProxyAuthInfo     "BASIC aGb2c3ewenQ6amF4szzmY3b="
     PerlSetVar   ProxyAuthRedirect On
     PerlSetVar   ProxyRewrite      "https://www.tivoli.com/secure => /secure"
     </Location>

     <Location    /secure>
     SetHandler   perl-script
     PerlHandler  Apache::ProxyRewrite

     PerlSetVar   ProxyTo           https://www.tivoli.com/secure
     PerlSetVar   ProxyAuthInfo     "BASIC aGb2c3ewenQ6amF4szzmY3b="
     PerlSetVar   ProxyAuthRedirect Off
     PerlSetVar   ProxyRewrite      "http://www.tivoli.com/ => /"
     </Location>

DESCRIPTION
===========

   *Apache::ProxyRewrite* acts as a reverse-proxy that will rewrite URLs
embedded in HTML documents per apache configuration directives.

   This module was written to allow multiple backend services with
discrete URLs to be presented as one service and to allow the proxy to do
authentication on the client's behalf.

CONFIGURATION OPTIONS
=====================

   The following variables can be defined within the configration of
Directory, Location, or Files blocks.

ProxyTo
     The URL for which ProxyRewrite will proxy its requests.

ProxyAuthInfo
     Authorization information for proxied requests. This string must
     conform to the credentials string defined in section 11 of RFC 2068.

ProxyAuthRedirect
     If the credentials supplied in the ProxyAuthInfo directive are
     insufficient and if ProxyAuthRedirect is set to On, the proxy server
     will redirect the client directly to the backend host. If
     ProxyAuthRedirect is set to Off (the default), the proxy server will
     challenge the client on the remote server's behalf.

ProxyRewrite
     A hash of URLs to rewrite. A note on hashes in configuration
     directives from the "Writing Apache Modules with Perl and C" book
     page 287:

          The only trick is to remember to put double quotes around the
          configuration value if it contains whitespace and not to allow
          your text editor to wrap it to another line. You can use
          backslash as a continuation character if you find long lines a
          pain to read.

NOTES
=====

*Automatic mappings*
     ProxyRewrite automatically adds a mapping for the remote relative URI
     and the current location. An example:

          ServerName   proxyhost

          <Location    /foo>
          PerlSetVar   ProxyTo   http://server1/A
          </Location>

     The request for http://proxyhost/foo/B is proxied to
     http://server1/A/B. Within the response from server1 is an embedded
     URI /A/C. This URI is rewritten to /foo/C before being returned to
     the client.

*Embedded Languages*
     Embedded languages such as Javascript are not parsed for embedded
     URLs. The problem is NP-Complete. The best choice is to surround all
     embedded languages in HTML comments to avoid possible parsing
     problems.

*Parser Notes*
     The parser takes a single pass through each HTML document. This
     method is extremely efficient, but it has possible drawbacks with
     poorly constructed HTML. All known drawbacks have been eliminated,
     but more may exist. Please contact the author if you have any trouble
     with parsed output.

*Special Thanks*
     A special thanks goes to my co-authors of absent, from which much of
     the rewriting code comes, Dave Korman and Avi Rubin. Absent is a
     system for secure remote access to an organization's internal web
     from outside its firewall. To learn more about absent, go to
     http://www.research.att.com/projects/absent/.

AUTHOR
======

   Christian Gilmore <cgilmore@tivoli.com>

SEE ALSO
========

   httpd(8), mod_perl(1)

COPYRIGHT
=========

   Copyright (C) 2001, International Business Machines Corporation and
others. All Rights Reserved.

   This module is free software; you can redistribute it and/or modify it
under the terms of the IBM Public License.

mod_perl header/footer/proxy module
***********************************

NAME
====

   Apache::ProxyStuff - mod_perl header/footer/proxy module

SYNOPSIS
========

     <Location /foo>
      SetHandler      perl-script
      PerlHandler     Apache::ProxyStuff
      PerlSetVar      HeaderFile      http://www.bar.com:81/includes/header.html
      PerlSetVar      FooterFile      http://www.bar.com:81/includes/footer.html
      PerlSetVar      MetaDescription "some description"
      PetlSetVar      MetaContent     "some content""
      PerlSetVar      BodyAttributes  "TOPMARGIN=0 LEFTMARGIN=0 MARGINHEIGHT=0 MARGINWIDTH=0"
      PerlSetVar      ProxyPrefix     http://www.foo.com
     </Location>

DESCRIPTION
===========

   Apache::ProxyStuff is module for adding headers and footers to content
proxied from other web servers. Rather than sandwiching the content
between the header and footer it "stuffs" the header and footer into their
correct places in the content - header after the <BODY> tag and footer
before the </BODY> tag. This allows you to give content living on
established servers a common look and feel without making changes to the
pages. (ProxyStuff will add <BODY> and </BODY> tags appropriately when the
document does not contain them. This allows even syntacticly incorrect
pages to have a common header and footer.)

   ProxyStuff also allows you to add meta tags to the <HEAD> section,
attributes to the <BODY> tag and manipulate links, image refs and form
actions as needed.

PARAMETERS
==========

   * HeaderFile

     HeaderFile specifies the URL of an HTML page that will be used as the
     header for proxied content. It will be added after the first <BODY>
     tag.

     Example: PerlSetVar HeaderFile http://www.bar.com/includes/header.html

   * FooterFile

     FooterFile specifies the URL of an HTML page that will be used as the
     footer for proxied content. It will be added before the </BODY> tag.

     Example: PerlSetVar FooterFile http://www.bar.com/includes/footer.html

   * ProxyPrefix

     ProxyPrefix specifies a URL which will be prepended to the URI of the
     request. The new URL is the location of the content to be proxied. If
     /proxy/content.html is requested and ProxyPrefix is set to
     http://www.foo.com, the content will be proxied from
     http://www.foo.com/proxy/content.html.

     Example: PerlSetVar ProxyPrefix http://www.foo.com

   * MetaDescription

     MetaDescription allows you to add a description meta tag to the
     <HEAD> section of the requested document.

     Example: PerlSetVar MetaDescription "ProxyStuff Home Page"

   * MetaContent

     MetaContent allows you to add a content meta tag to the <HEAD>
     section of the requested document.

     Example: PerlSetVar MetaContent "Apache, mod_perl, proxying"

   * BodyAttributes

     BodyAttributes allows you to add or modify attributes in the <BODY>
     tag in the proxied content. If you specify an attribute that exists
     in the <BODY> tag of the proxied page, the attribute that was in the
     page will be overwritten with the one you specified. If your
     attribute does not exist in the original <BODY> tag it will simply be
     added to the tag.

     Example: PerlSetVar BodyAttributes 'BGCOLOR="#FFFFFF" VLINK="BLUE"'

   * StripHost

     If StripHost is turned on, ProxyStuff will assume that the hostname
     of the server providing the content is the first part of the URI. For
     example, if the URI of the request is /foo/some/content.html and
     ProxyPrefix is set to http://www.foo.com then /foo will be stripped
     from the URI and a proxy request will be made to
     http://www.foo.com/some/content.html.

     (This is useful if your site is divided up into unique sections with
     their own headers/footers and each section has content proxied from
     multiple servers - /foo/hr, /bar/hr and /baz/hr.)

     Example: PerlSetVar StripHost Yes

   * AddHost2AHref

   * AddHost2ImgSrc

   * AddHost2FormAction

     AddHost2AHref, AddHost2ImgSrc and AddHost2FormAction are often used
     in conjunction with StripHost when your proxied content contains
     absolute links. ProxyStuff will add the provided text to the
     beginning of HREFs, SRCs and ACTIONs so these URLs are correctly
     mapped to ProxyStuff directories.

     For example, you set up <Location /foo> to use ProxyStuff.
     ProxyPrefix is set to http://www.foo.com, StripHost is turned on and
     AddHost2AHref, AddHost2ImgSrc and AddHost2FormAction are all set to
     foo. A user requests /foo/some/content.html. ProxyStuff removes /foo
     and requests http://www.foo.com/some/content.html. The page returned
     contains links such as <A HREF="/some/content.html">Link</A>.
     ProxyStuff will turn the link into <A
     HREF="/foo/some/content.html">Link</A> so when a user clicks on the
     link, the request will be handled by Apache::ProxyStuff.

     Example: PerlSetVar AddHost2Href foo

PREREQUISITES
=============

   Apache::ProxyStuff requires mod_perl, LWP and HTML::TokeParser.

AUTHOR
======

   Jason Bodnar <jason@shakabuku.org>

COPYRIGHT
=========

   Copyright (C) 2000, Jason Bodnar, Tivoli Systems

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl extension for mod_perl to handle random locations.
*******************************************************

NAME
====

   Apache::RandomLocation - Perl extension for mod_perl to handle random
locations.

SYNOPSIS
========

     You can use this in your Apache *.conf files to activate this module.

     <Location /scripts/random-image>
     SetHandler perl-script
     PerlSetVar BaseURL /images/
     PerlSetVar ConfigFile /usr/local/apache/etc/sponsors.txt
     PerlHandler Apache::RandomLocation
     </Location>

     <Location /scripts/CPAN>
     SetHandler perl-script
     PerlSetVar Type mirror
     PerlSetVar ConfigFile /usr/local/apache/etc/cpan_mirrors.txt
     PerlHandler Apache::RandomLocation
     </Location>

DESCRIPTION
===========

   Given a list of locations in ConfigFile, this module will instruct the
browser to redirect to one of them. The locations in ConfigFile are listed
one per line, with lines beginning with # being ignored.  How the
redirection is handled depends on the variable Type.

   If Type is undefined or set to file, the locations are assumed to be
files. *BaseUrl*, which can be a full or partial URL, gives the location
of these files. This can be used to implement, for example, a banner in an
HTML page: <IMG SRC="/scripts/random-image">. The file chosen is random.
Since after one call this image gets cached by the client, to generate
multiple random images on the same page, you could append different bogus
paths after the calling URL, as in <IMG SRC="/scripts/random-image/1"> and
<IMG SRC="/scripts/random-image/2">.

   In this case, if *BaseURL* indicates the local server is being used,
ConfigFile can contain a perl regular expression (enclosed by /, as in
*/\.gif$/*) which will be used to match files in  *BaseURL*.  If
ConfigFile is not defined, all files in *BaseUrl* will be read. If
*BaseUrl* is undefined, the top level directory of the local server is
assumed.

   If type is set to *mirror*, the locations in ConfigFile are assumed to
be mirror sites of some set of files, giving both the host name and the
directory path (eg, ftp.mirror.edu/path/to/dir).  In this mode the module
acts like the CPAN muliplexer code of http://www.perl.com/CPAN; for
example, http://my.host.edu/scripts/CPAN/src/latest.tar.gz will redirect
to a nearby CPAN mirror to retrieve the file `src/latest.tar.gz'.  Also
like the CPAN multiplexer, a call to the URL
http://my.host.edu/scripts/CPAN (without any trailing slash) will bring up
a form from which one can manually choose a site to go to.

   In this case, redirection is made to a random mirror site whose country
code in the domain name matches that of the client. If no such mirror
exists, a random mirror with country code matching *(com|edu|net|org|us)*
is selected. For these purposes, clients with country codes *com*, *edu*,
*org*, *net*, and *us* are considered equivalent. If a particular mirror
site should be considered as having a different country code in this
regard, add the desired code (separated by a space) to the end of the line
containing the address of the mirror in ConfigFile. If the address of a
mirror does not begin with *http://*, the *ftp://* protocol is assumed.

   Information on the locations is stored in a hash, which survives in
each child's memory for the life of the child. This hash is uniquely
associated with the given Location directive in *.conf, so that multiple
uses of Apache::RandomLocation modules on one server with different
Location directives is possible.

   Like Apache's configuration files, if any changes are made in
ConfigFile, the server must be restarted in order that the changes take
immediate effect; otherwise, one must wait for the child processes to die
in order that the new configuration file be read in.

Examples
========

   These directives in access.conf:

     <Location /scripts/random-image>
     SetHandler perl-script
     PerlSetVar BaseURL /images/
     PerlSetVar ConfigFile /usr/local/apache/etc/sponsors.txt
     PerlHandler Apache::RandomLocation
     </Location>

   with the following file /usr/local/apache/etc/sponsors.txt:

     apache.jpeg
     mod_perl.jpeg
     /\.gif$/

   will use the image files apache.jpeg, mod_perl.jpeg, and any gif image
in the server location /images. A random image will then be selected with
a call to http://your.server.name/scripts/random-image.

   These directives in access.conf:

     <Location /scripts/CPAN>
     SetHandler perl-script
     PerlSetVar Type mirror
     PerlSetVar ConfigFile /usr/local/apache/etc/cpan_mirrors.txt
     PerlHandler Apache::RandomLocation
     </Location>

   with the following file /usr/local/apache/etc/cpan_mirrors.txt:

     ftp.funet.fi/pub/languages/perl/CPAN
     ftp.metronet.com/pub/perl
     http://www.perl.com/CPAN
     ftp.utilis.com/pub/perl/CPAN ca

   can be used to redirect clients to a (hopefully) nearby random CPAN
mirror: a call to http://your.server.name/scripts/CPAN/src/latest.tar.gz
will grab the file latest.tar.gz under the $CPAN src/ directory of the
mirror. The ftp:// protocol is assumed for all sites except www.perl.com,
where http:// is used. For the purpose of matching the country code of the
client with that of the mirrors, ftp.utilis.com is to be considered as
having the country code of "ca".

   If a LocationMatch directive is given as, for example,

     <LocationMatch "/(physics|chemistry|biology)/random-image">
       SetHandler perl-script
       PerlSetVar BaseURL ~/images/
       PerlSetVar ConfigFile ~/images/config.txt
       PerlHandler Apache::RandomLocation
     </LocationMatch>

   then the tilde character will be interpreted as the corresponding home
directory (relative to *DocumentRoot*). For example, with *DocumentRoot*
equal to */usr/local/apache/htdocs*, a request to */biology/random-image*
will use a *BaseURL* of */usr/local/apache/htdocs/biology/images/* and a
ConfigFile of </usr/local/apache/htdocs/biology/images/config.txt>.

AUTHORS
=======

   Matthew Darwin, matthew@davin.ottawa.on.ca

   Randy Kobes, randy@theory.uwinnipeg.ca

   The mirror redirection code is based on the CPAN multiplexer code of
Tom Christiansen and a similar script by Ulrich Pfeifer.

SEE ALSO
========

   perl(1), Apache(3), mod_perl(3)

COPYRIGHT
=========

   Copyright 1998, Matthew Darwin, Randy Kobes

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Redirect requests to different directories based on the existence of a user in one or more database tables
**********************************************************************************************************

NAME
====

   Apache::RedirectDBI - Redirect requests to different directories based
on the existence of a user in one or more database tables

SYNOPSIS
========

   # in httpd.conf

   PerlModule Apache::DBI Apache::RedirectDBI

   <Location /path/to/virtual/directory>     SetHandler perl-script
PerlHandler Apache::RedirectDBI     PerlAuthenHandler Apache::AuthenDBI

     PerlSetVar Auth_DBI_data_source     dbi:Oracle:CERT
     # :
     # and other Auth_DBI_* variables
     # :

     PerlSetVar RedirectDBI_data_source dbi:Oracle:CERT
     PerlSetVar RedirectDBI_username    nobody
     PerlSetVar RedirectDBI_password    nobody
     PerlSetVar RedirectDBI_location    /path/to/virtual/directory
     PerlSetVar RedirectDBI_default     /path/to/virtual/directory.1
     PerlSetVar RedirectDBI_table2uri   "t1 /directory.2 t2 /directory.3"

     AuthName "Realm"
     AuthType Basic
     Require  valid-user
     </Location>

DESCRIPTION
===========

   `Apache::RedirectDBI' allows you to create a virtual path in your
document hierarchy.

   All requests for access to this virtual path should require a username
and password to access. When the user attempts to access this virtual path
their username is looked up in one or more database tables. The table in
which the username is found in determines the physical path from which
files are served.

   Files are served to the user *without* the URL changing, so they never
know that they have been redirected elsewhere.

   The user is redirected to a default location if they are not in any of
the database tables.

CONFIGURATION
=============

   First, define the virtual location that a user will see. You must also
create other directories from which files will be served.

   For example, specify /dir as the virtual directory, and have
$DOCROOT/dir.1, $DOCROOT/dir.2 and $DOCROOT/dir.3 as three possible
directories that files will be served from, depending on the table that
lists the user.

     <Location /dir>
         ...
     </Location>

     The different configuration directives in httpd.conf have the following
     meanings;

RedirectDBI_data_source
     A DBI identifier for the data source that contains the tables that
     will be used to determine which directory to send the user to.

RedirectDBI_username
     The username to use when connecting to the data source.

RedirectDBI_password
     The password to use when connecting to the data source.

RedirectDBI_location
     The same path as used in the <Location ...> section of this
     configuration.

RedirectDBI_default
     Path (relative to the document root) from which files will be served
     if the user does not exist in any of the database files.

RedirectDBI_table2uri
     A string containing white space seperated elements. Each element is
     part of a pair. The first element in each pair is the name of the
     table in the data source that contains a list of usernames. The
     second element is the directory (relative to the document root) from
     which files will be served if the user is in this table.

CREATING YOUR TABLES
====================

   The tables listed in the RedirectDBI_table2uri string must contain one
or more columns. One of these columns must be called name, and must
contain the usernames.

   These tables do not necessarily have to be real tables. If the backend
database supports it then they could be views. This allows for a lot of
flexibility in specifying the criteria for the inclusion of a user in the
table.

BUGS AND LIMITATIONS
====================

   * The column that contains the usernames must be called name. If your
     tables do not have a column with this name, create a view of the table
     that renames the appropriate column to name and use the view when
     configuring this module.

   * If the same username exists in more than one of the listed tables, the
     location for the first table they are found in is used. Tables are
     searched in the same order as they are listed in the configuration
     file.

   * It is assumed that the database connection to read the tables will
     always succeed.

SEE ALSO
========

   perl(1), Apache(3), Apache::DBI(3)

AUTHORS
=======

Mike Smith (mjs@iii.co.uk)
     Original Apache module

Nik Clayton (nik@freebsd.org)
     Original CGI scripts which this replaces, and this documentation.

Properly set redirect status for loggers
****************************************

NAME
====

   Apache::RedirectLogFix - Properly set redirect status for loggers

SYNOPSIS
========

   PerlLogHandler Apache::RedirectLogFix

DESCRIPTION
===========

   Due the nature of how mod_perl handles redirects, the status code is
not properly logged.  This module works around that bug until mod_perl can
deal with this.

block request based upon referer header
***************************************

NAME
====

   Apache::RefererBlock - block request based upon referer header

SYNOPSIS
========

   In your Apache configuration file, add something like

     PerlModule Apache::RefererBlock
     PerlFixupHandler Apache::RefererBlock
     RefBlockMimeTypes image/gif image/jpeg
     RefBlockAllowed http://www.mydomaine.com http://mydomaine.com
     RefBlockRedirect http://www.badguyse.com http://www.badguyse.com/images/bigpicture.gif
     RefBlockRedirect http://www.realbadguyse.com http://www.xxx.xxx/samples/tts.jpg
     RefBlockDebug On

   All directives are optional.

DESCRIPTION
===========

   Apache::RefererBlock will examine each request. If the MIME type of the
requested file is one of those listed in RefBlockMimeTypes, it will check
the request's "Referer" header.  If the referrer starts with one of the
strings listed in RefBlockAllowed, access is granted.  Otherwise, if
there's a RefBlockRedirect directive for the referrer, a redirect is
issued.  Otherwise, a "Forbidden" (403) error is returned.

   Requests with an empty Referer header will be granted, to accomodate
old browsers.

AVAILABILITY
============

   The latest version can be fetched from
<http://www.logilune.com/eric/RefererBlock.html>.

AUTHOR
======

   Eric Cholet, <cholet@logilune.com>

COPYRIGHT
=========

   Copyright (c) 1998 Eric Cholet.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Run unaltered CGI scrips under mod_perl
***************************************

NAME
====

   Apache::Registry - Run unaltered CGI scrips under mod_perl

SYNOPSIS
========

     #in httpd.conf

     Alias /perl/ /perl/apache/scripts/ #optional
     PerlModule Apache::Registry

     <Location /perl>
       SetHandler perl-script
       PerlHandler Apache::Registry
       Options ExecCGI
     </Location>

DESCRIPTION
===========

   URIs in the form of `http://www.host.com/perl/file.pl' will be compiled
as the body of a perl subroutine and executed.  Each server process or
'child' will compile the subroutine once and store it in memory. It will
recompile it whenever the file is updated on disk.  Think of it as an
object oriented server with each script implementing a class loaded at
runtime.

   The file looks much like a "normal" script, but it is compiled or
'evaled' into a subroutine.

   Here's an example:

     my $r = Apache->request;
     $r->content_type("text/html");
     $r->send_http_header;
     $r->print("Hi There!");

   This module emulates the CGI environment, allowing programmers to write
scripts that run under CGI or mod_perl without change.  Existing CGI
scripts may require some changes, simply because a CGI script has a very
short lifetime of one HTTP request, allowing you to get away with "quick
and dirty" scripting.  Using mod_perl and Apache::Registry requires you to
be more careful, but it also gives new meaning to the word "quick"!

   Be sure to read all mod_perl related documentation for more details,
including instructions for setting up an environment that looks exactly
like CGI:

     print "Content-type: text/html\n\n";
     print "Hi There!";

   Note that each httpd process or "child" must compile each script once,
so the first request to one server may seem slow, but each request there
after will be faster.  If your scripts are large and/or make use of many
Perl modules, this difference should be noticeable to the human eye.

SECURITY
========

   Apache::Registry::handler will preform the same checks as mod_cgi
before running the script.

ENVIRONMENT
===========

   The Apache function `exit' overrides the Perl core built-in function.

   The environment variable GATEWAY_INTERFACE is set to `CGI-Perl/1.1'.

COMMANDLINE SWITCHES IN FIRST LINE
==================================

   Normally when a Perl script is run from the command line or under CGI,
arguments on the `#!' line are passed to the perl interpreter for
processing.

   Apache::Registry currently only honors the -w switch and will turn on
warnings using the $^W global variable.  Another common switch used with
CGI scripts is -T to turn on taint checking.  This can only be enabled
when the server starts with the configuration directive:

     PerlTaintCheck On

   However, if taint checking is not enabled, but the -T switch is seen,
Apache::Registry will write a warning to the error_log.

DEBUGGING
=========

   You may set the debug level with the $Apache::Registry::Debug bitmask

     1 => log recompile in errorlog
     2 => Apache::Debug::dump in case of $@
     4 => trace pedantically

CAVEATS
=======

   Apache::Registry makes things look just the CGI environment, however,
you must understand that this *is not CGI*.  Each httpd child will compile
your script into memory and keep it there, whereas CGI will run it once,
cleaning out the entire process space.  Many times you have heard "always
use -w, always use -w and 'use strict'".  This is more important here than
anywhere else!

   Your scripts cannot contain the __END__ or __DATA__ token to terminate
compilation.

SEE ALSO
========

   perl(1), mod_perl(3), Apache(3), Apache::Debug(3)

AUTHORS
=======

   Andreas J. Koenig and Doug MacEachern

run Perl scripts in an Apache::Filter chain
*******************************************

NAME
====

   Apache::RegistryFilter - run Perl scripts in an Apache::Filter chain

SYNOPSIS
========

     #in httpd.conf

     PerlModule Apache::RegistryFilter

     # Run the output of scripts through Apache::SSI
     <Files ~ "\.pl$">
      PerlSetVar Filter on
      SetHandler perl-script
      PerlHandler Apache::RegistryFilter Apache::SSI
     </Files>

     # Generate some Perl code using templates, then execute it
     <Files ~ "\.tmpl$">
      PerlSetVar Filter on
      SetHandler perl-script
      PerlHandler YourModule::GenCode Apache::RegistryFilter
     </Files>

DESCRIPTION
===========

   This module is a subclass of Apache::RegistryNG, and contains all of its
functionality.  The only difference between the two is that this module
can be used in conjunction with the Apache::Filter module, whereas
Apache::RegistryNG cannot.

   For information on how to set up filters, please see the codumentation
for Apache::Filter.

INCOMPATIBILITIES
=================

   At this point the only changes you might have to make to your Registry
scripts are quite minor and obscure.  That is, unless I haven't thought of
something.  Please let me know if any other changes are needed.

   * Don't call send_fd()

     If you call Apache's $r->send_fd($filehandle) method, the output will
     be sent directly to the browser instead of filtered through the filter
     chain.  This is okay if your script is the last filter in the chain,
     but clearly it won't work otherwise.

CAVEATS
=======

   This is a subclass of Apache::RegistryNG, not Apache::Registry (which
is not easily subclassible).  Apache::RegistryNG is supposed to be
functionally equivalent to Apache::Registry, but it's a little less
well-tested.

SEE ALSO
========

   perl(1), mod_perl(3), Apache::Filter(3)

AUTHOR
======

   Ken Williams <ken@forum.swarthmore.edu>

Diff Apache::Registry script padlists
*************************************

NAME
====

   Apache::RegistryLexInfo - Diff Apache::Registry script padlists

SYNOPSIS
========

     Alias /lexinfo /same/path/as/for/apache/registry/scripts

     PerlModule Apache::RegistryLexInfo
     <Location /lexinfo>
      SetHandler perl-script
      PerlHandler Apache::RegistryLexInfo->handler
      Options +ExecCGI
     </Location>

DESCRIPTION
===========

   *Apache::RegistryLexInfo* is a subclass of *Apache::RegistryNG* which
takes snapshots of the handler padlist before and after it is run.  The
differences (if any) and the before/after snapshots are printed to the
HTTP stream after the script has run.

SEE ALSO
========

   The Apache::Status StatusLexInfo option.

   Apache::RegistryNG(3), B::LexInfo(3)

AUTHOR
======

   Doug MacEachern

Compile Apache::Registry scripts at server startup
**************************************************

NAME
====

   Apache::RegistryLoader - Compile Apache::Registry scripts at server
startup

SYNOPSIS
========

     #in PerlScript

     use Apache::RegistryLoader ();

     my $r = Apache::RegistryLoader->new;

     $r->handler($uri, $filename);

     $r->handler($uri, $filename, $virtual_hostname);

DESCRIPTION
===========

   This modules allows compilation of Apache::Registry scripts at server
startup.  The script's handler routine is compiled by the parent server,
of which children get a copy.  The *Apache::RegistryLoader* handler method
takes arguments of `uri' and the filename.  URI to filename translation
normally doesn't happen until HTTP request time, so we're forced to roll
our own translation.

   If filename is omitted and a trans routine was not defined, the loader
will try using the *uri* relative to *ServerRoot*.  Example:

     #in httpd.conf
     ServerRoot /opt/www/apache
     Alias /perl/ /opt/www/apache/perl

     #in PerlScript
     use Apache::RegistryLoader ();

     #/opt/www/apache/perl/test.pl
     #is the script loaded from disk here:
     Apache::RegistryLoader->new->handler("/perl/test.pl");

   To make the loader smarter about the uri->filename translation, you may
provide the new method with a trans function to translate the uri to
filename.

   The following example will pre-load all files ending with `.pl' in the
*perl-scripts/* directory relative to *ServerRoot*.  The example code
assumes the Location URI `/perl' is an Alias to this directory.

     {
         use Cwd ();
         use Apache::RegistryLoader ();
         use DirHandle ();
         use strict;

     my $dir = Apache->server_root_relative("perl-scripts/");

     my $rl = Apache::RegistryLoader->new(trans => sub {
     	 my $uri = shift;
         $uri =~ s:^/perl/:/perl-scripts/:;
     	 return Apache->server_root_relative($uri);
     });

     my $dh = DirHandle->new($dir) or die $!;

     for my $file ($dh->read) {
     	 next unless $file =~ /\.pl$/;
     	 $rl->handler("/perl/$file");
     }
      }

AUTHORS
=======

   Doug MacEachern

   Stas Bekman (Rewrote the handler() to report and handle all the possible
erroneous conditions)

SEE ALSO
========

   Apache::Registry(3), Apache(3), mod_perl(3)

Reload changed modules
**********************

NAME
====

   Apache::Reload - Reload changed modules

SYNOPSIS
========

   In httpd.conf:

     PerlInitHandler Apache::Reload
     PerlSetVar ReloadAll Off

   Then your module:

     package My::Apache::Module;

     use Apache::Reload;

     sub handler { ... }

     1;

DESCRIPTION
===========

   This module is two things. First it is an adaptation of Randal
Schwartz's Stonehenge::Reload module that attempts to be a little more
intuitive and makes the usage easier. Stonehenge::Reload was written by
Randal to make specific modules reload themselves when they changed.
Unlike Apache::StatINC, Stonehenge::Reload only checked the change time of
modules that registered themselves with Stonehenge::Reload, thus reducing
stat() calls. Apache::Reload also offers the exact same functionality as
Apache::StatINC, and is thus designed to be a drop-in replacement.
Apache::Reload only checks modules that register themselves with
Apache::Reload if you explicitly turn off the StatINC emulation method
(see below). Like Apache::StatINC, Apache::Reload must be installed as an
Init Handler.

StatINC Replacement
-------------------

   To use as a StatINC replacement, simply add the following configuration
to your httpd.conf:

     PerlInitHandler Apache::Reload

Register Modules Implicitly
---------------------------

   To only reload modules that have registered with Apache::Reload, add
the following to the httpd.conf:

     PerlInitHandler Apache::Reload
     PerlSetVar ReloadAll Off
     # ReloadAll defaults to On

   Then any modules with the line:

     use Apache::Reload;

   Will be reloaded when they change.

Register Modules Explicitly
---------------------------

   You can also register modules explicitly in your httpd.conf file that
you want to be reloaded on change:

     PerlInitHandler Apache::Reload
     PerlSetVar ReloadAll Off
     PerlSetVar ReloadModules "My::Foo My::Bar Foo::Bar::Test"

   Note that these are split on whitespace, but the module list must be in
quotes, otherwise Apache tries to parse the parameter list.

Special "Touch" File
--------------------

   You can also set a file that you can touch() that causes the reloads to
be performed. If you set this, and don't touch() the file, the reloads
don't happen. This can be a great boon in a live environment:

     PerlSetVar ReloadTouchFile /tmp/reload_modules

   Now when you're happy with your changes, simply go to the command line
and type:

     touch /tmp/reload_modules

   And your modules will be magically reloaded on the next request. This
option works in both StatINC emulation mode and the registered modules
mode.

PSUEDOHASHES
============

   The short summary of this is: Don't use psuedohashes. Use an array with
constant indexes. Its faster in the general case, its more guaranteed, and
generally, it works.

   The long summary is that I've done some work to get this working with
modules that use psuedo hashes, but its still broken in the case of a
single module that contains multiple packages that all use psuedohashes.

   So don't do that.

AUTHOR
======

   Matt Sergeant, matt@sergeant.org

SEE ALSO
========

   Apache::StatINC, Stonehenge::Reload

Methods for dealing with client request data
********************************************

NAME
====

   Apache::Request - Methods for dealing with client request data

SYNOPSIS
========

     use Apache::Request ();
     my $apr = Apache::Request->new($r);

DESCRIPTION
===========

   *Apache::Request* is a subclass of the Apache class, which adds methods
for parsing GET requests and POST requests where *Content-type* is one of
*application/x-www-form-urlencoded* or *multipart/form-data*. See the
libapreq(3) manpage for more details.

Apache::Request METHODS
=======================

new
---

   Create a new *Apache::Request* object with an Apache request_rec object:

     my $apr = Apache::Request->new($r);

   All methods from the Apache class are inherited.

   The following attributes are optional:

POST_MAX
     Limit the size of POST data.  *Apache::Request::parse* will return an
     error code if the size is exceeded:

          my $apr = Apache::Request->new($r, POST_MAX => 1024);
          my $status = $apr->parse;

          if ($status) {
              my $errmsg = $apr->notes("error-notes");
              ...
              return $status;
          }

DISABLE_UPLOADS
     Disable file uploads.  *Apache::Request::parse* will return an error
     code if a file upload is attempted:

          my $apr = Apache::Request->new($r, DISABLE_UPLOADS => 1);
          my $status = $apr->parse;

          if ($status) {
              my $errmsg = $apr->notes("error-notes");
              ...
              return $status;
          }

instance
--------

   The instance() class method allows Apache::Request to be a singleton.
This means that whenever you call Apache::Request->instance() within a
single request you always get the same Apache::Request object back.  This
solves the problem with creating the Apache::Request object twice within
the same request - the symptoms being that the second Apache::Request
object will not contain the form parameters because they have already been
read and parsed.

     my $apr = Apache::Request->instance($r, DISABLE_UPLOADS => 1);

   Note that `instance()' call will take the same parameters as the above
call to new(), however the parameters will only have an effect the first
time `instance()' is called within a single request. Extra parameters will
be ignored on subsequent calls to `instance()' within the same request.

   Subrequests receive a new Apache::Request object when they call
instance() - the parent request's Apache::Request object is not copied
into the subrequest.

   Also note that it is unwise to use the parse() method when using
`instance()' because you may end up trying to call it twice, and detecting
errors where there are none.

parse
-----

   The parse method does the actual work of parsing the request.  It is
called for you by the accessor methods, so it is not required but can be
useful to provide a more user-friendly message should an error occur:

   my $r = shift;     my $apr = Apache::Request->new($r);

   my $status = $apr->parse;     unless ($status == OK) {
$apr->custom_response($status, $apr->notes("error-notes")); 	return
$status;     }

param
-----

   Get or set request parameters:

     my $value = $apr->param('foo');
     my @values = $apr->param('foo');
     my @params = $apr->param;
     $apr->param('foo' => [qw(one two three)]);

upload
------

   Returns a single *Apache::Upload* object in a scalar context or all
*Apache::Upload* objects in an array context:

     my $upload = $apr->upload;
     my $fh = $upload->fh;
     my $lines = 0;
     while(<$fh>) {
         ++$lines;
         ...
     }

   An optional name parameter can be passed to return the *Apache::Upload*
object associated with the given name:

     my $upload = $apr->upload($name);

Apache::Upload METHODS
======================

name
----

   The name of the filefield parameter:

     my $name = $upload->name;

filename
--------

   The filename of the uploaded file:

     my $filename = $upload->filename;

fh
--

   The filehandle pointing to the uploaded file:

     my $fh = $upload->fh;
     while (<$fh>) {
     	...
     }

size
----

   The size of the file in bytes:

     my $size = $upload->size;

info
----

   The additional header information for the uploaded file.  Returns a
hash reference tied to the Apache::Table class.  An optional key argument
can be passed to return the value of a given header rather than a hash
reference.  Examples:

     my $info = $upload->info;
     while (my($key, $val) = each %$info) {
     	...
     }

     my $val = $upload->info("Content-type");

type
----

   Returns the *Content-Type* for the given *Apache::Upload* object:

     my $type = $upload->type;
     #same as
     my $type = $upload->info("Content-Type");

next
----

   As an alternative to using the *Apache::Request* upload method in an
array context:

     for (my $upload = $apr->upload; $upload; $upload = $upload->next) {
     	...
     }

     #functionally the same as:

     for my $upload ($apr->upload) {
     	...
     }

SEE ALSO
========

   libapreq(3)

CREDITS
=======

   This interface is based on the original pure Perl version by Lincoln
Stein.

AUTHOR
======

   Doug MacEachern

pass form and cookie data around in pnotes
******************************************

NAME
====

   Apache::RequestNotes - pass form and cookie data around in pnotes

SYNOPSIS
========

   httpd.conf:

     PerlInitHandler Apache::RequestNotes
     PerlSetVar MaxPostSize 1024
     PerlSetVar DisableUploads On

     MaxPostSize is in bytes and defaults to 1024, thus is optional.
     DisableUploads defaults to On, and likewise is optional.

DESCRIPTION
===========

   Apache::RequestNotes provides a simple interface allowing all phases of
the request cycle access to cookie or form input parameters in a
consistent manner.  Behind the scenes, it uses libapreq functions to parse
request data and puts references to the data objects in pnotes.

EXAMPLE
=======

   httpd.conf:

     PerlInitHandler Apache::RequestNotes

   some Perl*Handler or Registry script:

     my $input      = $r->pnotes('INPUT');   # Apache::Table reference
     my $uploads    = $r->pnotes('UPLOADS'); # Apache::Upload array ref
     my $cookies    = $r->pnotes('COOKIES'); # hash reference

     # GET and POST data
     my $foo        = $input->get('foo');

     # uploaded files
     foreach my $upload (@$uploads) {
       my $name     = $upload->name'
       my $fh       = $upload->fh;
       my $size     = $upload->size;
     }

     # cookie data
     my $bar        = $cookies->{'bar'};

   After using Apache::RequestNotes:   o $cookies contains a reference to
a hash with the names and values     of all cookies sent back to your
domain and path.

     o $input contains a reference to an Apache::Table object and can be
       accessed via Apache::Table methods - if a form contains both GET
       and POST data, both are available via $input.

     o $uploads contains a reference to an array containing all the
       Apache::Upload objects for the request, which can be used to
       access uploaded file information.

   Once Apache::RequestNotes has been called, all other phases can have
access to the form input and cookie data without parsing it themselves.
This relieves some strain, especially when the GET or POST data is
required by numerous handlers along the way.

NOTES
=====

   It should be noted that Apache::Request 0.3103 and above now offers the
Apache::Request->instance() method, which offers the ability to access the
same Apache::Request object over and over again.  While the availability
of instance() does absorb the problems that prompted Apache::RequestNotes,
namely the ability to read from POST more than once, you still have to
parse the various data yourself.  Thus, the utility of
Apache::RequestNotes is now simply the ability to have a common API for
all your handlers to use.

   Apache::RequestNotes can really be called from just about any request
phase.  Thus, if you need to postpone data parsing until after uri
translation, using RequestNotes as a PerlFixupHandler should work just
fine.  Keep in mind that Apache::RequestNotes returns OK, which would
preclude it's use in conjuction with other PerlTransHandlers and
PerlTypeHandlers (but it doesn't really belong there anyway).

   MaxPostSize applies to file uploads as well as POST data, so if you
plan on uploading files bigger than 1K, you will need to the override the
default value.

   $Apache::RequestNotes:err is set if libapreq reports a problem parsing
the form data, thus it can be used to verify whether $input and $uploads
contain valid objects.  Apache::RequestNotes will _not_ return
SERVER_ERROR in the event libapreq encounters an error.  This may change
in future releases.

   Verbose debugging is enabled by setting the variable
$Apache::RequestNotes::DEBUG to 1 or greater. To turn off all debug
information, set your apache LogLevel above info level.

   This is alpha software, and as such has not been tested on multiple
platforms or environments.  It requires PERL_INIT=1, PERL_LOG_API=1, and
maybe other hooks to function properly. Doug MacEachern's libapreq is also
required - you can get it from CPAN under the Apache tree.

FEATURES/BUGS
=============

   Since POST data cannot be read more than once per request, it is
improper to both use this module and try to gather form data again via
CGI.pm or by reading it yourself from a cgi script or handler later in the
request cycle.  Unlike versions of RequestNotes prior to 0.06, however,
you can call Apache::Request->instance($r) without impunity -
Apache::Request->new($r) is off limits, though.

SEE ALSO
========

   perl(1), mod_perl(1), Apache(3), Apache::Request(3), libapreq(1),
Apache::Table(3)

AUTHOR
======

   Geoffrey Young <geoff@cpan.org>

COPYRIGHT
=========

   Copyright (c) 2000, Geoffrey Young.  All rights reserved.

   This module is free software.  It may be used, redistributed and/or
modified under the same terms as Perl itself.

Limit resources used by httpd children
**************************************

NAME
====

   Apache::Resource - Limit resources used by httpd children

SYNOPSIS
========

     PerlModule Apache::Resource
     #set child memory limit in megabytes
     #default is 64 Meg
     PerlSetEnv PERL_RLIMIT_DATA 32:48

     #linux does not honor RLIMIT_DATA
     #RLIMIT_AS (address space) will work to limit the size of a process
     PerlSetEnv PERL_RLIMIT_AS 32:48

     #set child cpu limit in seconds
     #default is 360 seconds
     PerlSetEnv PERL_RLIMIT_CPU 120

     PerlChildInitHandler Apache::Resource

DESCRIPTION
===========

   *Apache::Resource* uses the *BSD::Resource* module, which uses the C
function setrlimit to set limits on system resources such as memory and
cpu usage.

   Any *RLIMIT* operation available to limit on your system can be set by
defining that operation as an environment variable with a `PERL_' prefix.
See your system setrlimit manpage for available resources which can be
limited.

   The following limit values are in megabytes: DATA, `RSS', `STACK',
`FSIZE', `CORE', `MEMLOCK'; all others are treated as their natural unit.

   If the value of the variable is of the form `S:H', S is treated as the
soft limit, and H is the hard limit.  If it is just a single number, it is
used for both soft and hard limits.

DEFAULTS
========

   To set reasonable defaults for all RLIMITs, add this to your httpd.conf:

     PerlSetEnv PERL_RLIMIT_DEFAULTS On
     PerlModule Apache::Resource

AUTHOR
======

   Doug MacEachern

SEE ALSO
========

   BSD::Resource(3), setrlimit(2)

An Apache mod_perl reverse proxy
********************************

NAME
====

   Apache::ReverseProxy - An Apache mod_perl reverse proxy

SYNOPSIS
========

     # In Apache config file
     <Location />
     SetHandler perl-script
     PerlHandler Apache::ReverseProxy
     PerlSetVar ReverseProxyConfig /usr/local/apache/conf/rproxy.conf
     </Location>

   # In rproxy.conf  / http://www.cpan.org/

DESCRIPTION
===========

   This is a reverse proxy module for Apache with mod_perl.  It is intended
to replace Apache::ProxyPass.  Given a list of URI mappings, this module
will translate an incoming URI, retrieve the contents for the translated
URI, and return the contents to the original requestor.  This module
allows you to specify exact matching (instead of regular expression
matching) and handles query string translations.

CONFIGURATION
=============

   You will need to set the ReverseProxyConfig perl variable in Apache to
the path of the reverse proxy mapping file.  For example:

     <Location />
     SetHandler perl-script
     PerlHandler Apache::ReverseProxy
     PerlSetVar ReverseProxyConfig /usr/local/apache/conf/rproxy.conf

     # Optional configuration items:
     #PerlSetVar ReverseProxyChain http://proxy.mycompany.com:8888/
     #PerlSetVar ReverseProxyNoChain mycompany.com
     </Location>

   *ReverseProxyChain* specifies a proxy server to use.  This is sometimes
called *proxy chaining* when one proxy server uses another proxy server.
The *ReverseProxyNoChain* directive can specify a domain to not use proxy
chaining on.

   Reverse proxy configuration files have three fields, each separated by
white space.  The first field is the uri to look for, the second field is
the replacement uri, and the third field is optional and allows you to
specify comma separated options for the mapping.  The only option that is
currently supported is the *exact* parameter, which will make the reverse
proxy use exact matching for the first parameter instead of using regular
expressions.  This feature is convenient when the first parameter contains
characters that may need to be escaped or quotemeta'ed.  Exact options are
evaluated first.  If there isn't an exact match, regular expression
matches are performed.  Configuration files may contain comments, which
start with a pound sign.  For example:

     /news/ http://www.news.com/
     / http://www.perl.com/
     /stats http://localhost/stats exact
     # /stats maps exactly to http://localhost/stats
     # /stats/b maps to http://www.perl.com/stats/b
     /french/news http://www.news.com/?language=french
     # /french/news/index -> http://www.news.com/index?language=french
     # /french/news/index?a=b -> http://www.news.com/index?language=french&a=b

TO-DO
=====

     1. Cookie header translation.
     2. Verbose/debug logging.

REQUIREMENTS
============

     This module requires LWP, available at:
     http://www.cpan.org/modules/by-module/LWP/

AUTHOR
======

     Clinton Wong, clintdw@netcom.com

COPYRIGHT
=========

     Copyright (c) 1999 Clinton Wong. Additional modifications copyright
     (c) 2000 David Jao. All rights reserved.
     This program is free software; you can redistribute it
     and/or modify it under the same terms as Perl itself.

     This module is based on Apache::ProxyPass, by Michael
     Smith <mjs@iii.co.uk>, which is based on Apache::ProxyPassThru.

proxy that works by rewriting requested documents with no client proxy config needed.
*************************************************************************************

NAME
====

   Apache::RewritingProxy - proxy that works by rewriting requested
documents with no client proxy config needed.

SYNOPSIS
========

   # Configuration in httpd.conf

   <Location /foo> SetHandler perl-script PerlHandler
Apache::RewritingProxy Options ExecCGI PerlSendHeader On </Location>

   requests to /foo/http://domain.dom/ will return the resource located at
http://domain.dom with all links pointing to /foo/http://otherlink.dom

DESCRIPTION
===========

   This module allows proxying of web sites without any configuration
changes on the client's part.  The client is simply pointed to a URL using
this module and it fetches the resource and rewrites all links to continue
using this proxy.

INSTALLATION
============

   perl Makefile.PL; make; make install;

REQUIREMENTS
============

   You need the following modules installed for this module to work:

     LWP::UserAgent
     HTML::TokeParser
     URI::URL
     Of course, mod_perl and Apache would also help greatly.

TODO
====

   Make cookies work

   Fix occasional query string munging for redirected requests

   Add caching or incorporate some other caching mechanism

   Enable this module to at least print scripts that occur within comments

   Add an external script to enable this to be called as a cgi or a
mod_perl module (for testing)

SEE ALSO
========

   mod_perl(3), Apache(3), LWP::UserAgent(3)

AUTHOR
======

   Apache::RewritingProxy by Ken Hagan <ken.hagan@louisville.edu>

COPYRIGHT
=========

   The Apache::RewritingProxy module is free software; you can redistribute
it and/or modify it under the same terms as Perl itself.

Override apache signal handlers with Perl's
*******************************************

NAME
====

   Apache::SIG - Override apache signal handlers with Perl's

SYNOPSIS
========

     PerlFixupHandler Apache::SIG

DESCRIPTION
===========

   When a client drops a connection and apache is in the middle of a
write, a timeout will occur and httpd sends a *SIGPIPE*.  When apache's
SIGPIPE handler is used, Perl may be left in the middle of it's eval
context, causing bizarre errors during subsequent requests are handled by
that child.  When Apache::SIG is used, it installs a different SIGPIPE
handler which rewinds the context to make sure Perl is back to normal
state, preventing these bizarre errors.

   If you would like to log when a request was cancelled by a SIGPIPE in
your Apache access_log, you can declare Apache::SIG as a handler (any
Perl*Handler will do, as long as it is run before PerlHandler, e.g.
PerlFixupHandler), and you must also define a custom LogFormat in your
httpd.conf, like so:

   PerlFixupHandler Apache::SIG LogFormat "%h %l %u %t \"%r\" %s %b
%{SIGPIPE}e"

   If the server has noticed that the request was cancelled via a SIGPIPE,
then the log line will end with 1, otherwise it will just be a dash.

CAVEATS
=======

   The signal handler in this package uses the subprocess_env table of the
main request object to supply the 'SIGPIPE' "environment variable" to the
log handler. If you already use the key 'SIGPIPE' in your subprocess_env
table, then you can redefine the key like this:

   $Apache::SIG::PipeKey = 'my_SIGPIPE';

   and log it like this:

   LogFormat "%h %l %u %t \"%r\" %s %b %{my_SIGPIPE}e"

AUTHORS
=======

   Doug MacEachern and Doug Bagley

SEE ALSO
========

   perlvar(1)

Provide SOAP server functionality with simple configuration
***********************************************************

NAME
====

   Apache::SOAP - Provide SOAP server functionality with simple
configuration

SYNOPSIS
========

httpd.conf (Location), directory-based access
          <Location /mod_soap>
            SetHandler perl-script
            PerlHandler Apache::SOAP
            PerlSetVar dispatch_to "/Your/Path/To/Deployed/Modules, Module::Name, Module::method"
            PerlSetVar options "compress_threshold => 10000"
          </Location>

httpd.conf (Files), file-based access
          <FilesMatch "\.soap$">
            SetHandler perl-script
            PerlHandler Apache::SOAP
            PerlSetVar dispatch_to "/Your/Path/To/Deployed/Modules, Module::Name, Module::method"
            PerlSetVar options "compress_threshold => 10000"
          </FilesMatch>

.htaccess, directory-based access
          SetHandler perl-script
          PerlHandler Apache::SOAP
          PerlSetVar dispatch_to "/Your/Path/To/Deployed/Modules, Module::Name, Module::method"
          PerlSetVar options "compress_threshold => 10000"

DESCRIPTION
===========

   This Apache Perl module provides the ability to add support for SOAP
(Simple Object Access Protocol) protocol with easy configuration (either
in .conf or in .htaccess file). This functionality should give you
lightweight option for hosting SOAP services and greatly simplify
configuration aspects. This module inherites functionality from
SOAP::Transport::HTTP::Apache component of SOAP::Lite module.

   =head1 CONFIGURATION

   The module can be placed in <Location>, <Directory>, <Files>,
<FilesMatch> directives in main server configuration areas or directly in
.htaccess file.

   All parameters should be quoted and can be separated with commas or
spaces for lists ("a, b, c") and with 'wide arrows' and commas for hash
parameters ("key1 => value1, key2 => value2").

   All options that you can find in SOAP::Transport::HTTP::Apache component
are available for configuration. Here is the description of most important
ones.

dispatch_to (LIST)
     Specifies path to directory that contains Perl modules you'd like to
     give access to, or just list of modules (for preloaded modules).

          PerlSetVar dispatch_to "/Your/Path/To/Deployed/Modules, Module::Name, Module::method"

options (HASH)
     Specifies list of options for your module, for example threshold for
     compression. Future versions will support more options. See
     SOAP::Transport::HTTP documentation for other options.

          PerlSetVar options "compress_threshold => 10000"

DEPENDENCIES
============

     SOAP::Lite
     mod_perl

SEE ALSO
========

     SOAP::Transport::HTTP::Apache for implementation details,
     SOAP::Lite for general information, and
     F<examples/server/mod_soap.htaccess> for .htaccess example

COPYRIGHT
=========

   Copyright (C) 2000-2001 Paul Kulchenko. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Paul Kulchenko (paulclinger@yahoo.com)

Implement Server Side Includes in Perl
**************************************

NAME
====

   Apache::SSI - Implement Server Side Includes in Perl

SYNOPSIS
========

   In httpd.conf:

     <Files *.phtml>  # or whatever
     SetHandler perl-script
     PerlHandler Apache::SSI
     </Files>

   You may wish to subclass Apache::SSI for your own extensions.  If so,
compile mod_perl with PERL_METHOD_HANDLERS=1 (so you can use
object-oriented inheritance), and create a module like this:

     package MySSI;
     use Apache::SSI ();
     @ISA = qw(Apache::SSI);

     #embedded syntax:
     #<!--#something param=value -->
     sub ssi_something {
        my($self, $attr) = @_;
        my $cmd = $attr->{param};
        ...
        return $a_string;
     }

      Then in httpd.conf:

     <Files *.phtml>
      SetHandler perl-script
      PerlHandler MySSI
     </Files>

DESCRIPTION
===========

   Apache::SSI implements the functionality of mod_include for handling
server-parsed html documents.  It runs under Apache's mod_perl.

   In my mind, there are two main reasons you might want to use this
module: you can sub-class it to implement your own custom SSI directives,
and/or you can parse the output of other mod_perl handlers, or send the
SSI output through another handler (use Apache::Filter to do this).

   Each SSI directive is handled by an Apache::SSI method with the prefix
"ssi_".  For example, <!-#printenv-> is handled by the ssi_printenv method.
attribute=value pairs inside the SSI tags are parsed and passed to the
method in a hash reference.

   'Echo' directives are handled by the ssi_echo method, which delegates
lookup to methods with the prefix "echo_".  For instance, <!-#echo
var=DOCUMENT_NAME-> is handled by the echo_DOCUMENT_NAME method.

   You can customize behavior by inheriting from Apache::SSI and
overriding 'ssi_*' and 'echo_*' methods, or writing new ones.

SSI Directives
--------------

   This module supports the same directives as mod_include.  At least,
that's the goal. =)  For methods listed below but not documented, please
see mod_include's online documentation at http://www.apache.org/ .

   * config

   * echo

   * exec

   * fsize

   * flastmod

   * include

   * printenv

   * set

   * perl

     There are two ways to call a Perl function, and two ways to supply it
     with arguments.  The function can be specified either as an anonymous
     subroutine reference, or as the name of a function defined elsewhere:

          <!--#perl sub="sub { localtime() }"-->
          <!--#perl sub="time::now"-->

     If the 'sub' argument matches the regular expression /^\s*sub[^\w:]/,
     it is assumed to be a subroutine reference.  Otherwise it's assumed to
     be the name of a function.  In the latter case, the string "main::"
     will be prepended to the function name if the name doesn't contain
     "::" (this forces the function to be in the main package, or a package
     you specify).  Note that it's a pretty bad idea to put your code in
     the main package, so I only halfheartedly endorse this feature.

     In general, it will be slower to use anonymous subroutines, because
     each one has to be eval()'ed and there is no caching.  For best
     results, pre-load any code you need in the parent process, then call
     it by name.

     If you're calling a subroutine like "&Package::SubPack::handler", you
     can omit the "handler" portion, making your directive like this:

          <!--#perl sub="Package::Subpack"-->

     If you want to supply a list of arguments to the function, you use
     either the "arg" or the "args" parameter:

          <!--#perl sub="sub {$_[0] * 7}" arg=7-->
          <!--#perl sub=holy::matrimony arg=Hi arg=Lois-->
          <!--#perl sub=holy::matrimony args=Hi,Lois-->

     The "args" parameter will simply split on commas, meaning that
     currently there's no way to embed a comma in arguments passed via the
     "args" parameter.  Use the "arg" parameter for this.

     If you give a key-value pair and the key is not 'sub', 'arg', 'args',
     or 'pass_request' (see below), then your routine will be passed both
     the key and the value.  This lets you pass a hash of key-value pairs
     to your function:

          <!--#perl sub=holy::matrimony groom=Hi bride=Lois-->
          Will call &holy::matrimony('groom', 'Hi', 'bride', 'Lois');

     As of version 1.95, we pass the current Apache request object ($r) as
     the first argument to the function.  To turn off this behavior, give
     the key-value pair 'pass_request=no', or put 'PerlSetVar
     SSIPerlPass_Request no' in your server's config file.

     See `http://perl.apache.org/src/mod_perl.html' for more information
     on Perl SSI calls.

   * if

   * elif

   * else

   * endif

     These four directives can be used just like in `mod_include', with
     one important difference: the boolean expression is evaluated using
     Perl's eval().  This means you use `==' or eq instead of = to test
     equality.  It also means you can use pre-loaded Perl subroutines in
     the conditions:

          <!--#if expr="&Movies::is_by_Coen_Brothers($MOVIE)"-->
           This movie is by the Coen Brothers.
          <!--#else-->
           This movie is not by the Coen Brothers.
          <!--#endif-->

     It can't handle very sophistocated Perl though, because it manually
     looks for variables (of the form $var or ${var}, just like
     `mod_include'), and will get tripped up on expressions like
     $object->method or $hash{'key'}.  I'll welcome any suggestions for
     how to allow arbitrary Perl expressions while still filling in Apache
     variables.

CHAINING HANDLERS
=================

   There are two fairly simple ways for this module to exist in a stacked
handler chain.  The first uses `Apache::Filter', and your httpd.conf would
look something like this:

     PerlModule Apache::Filter
     PerlModule Apache::SSI
     PerlModule My::BeforeSSI
     PerlModule My::AfterSSI
     <Files ~ "\.ssi$">
      SetHandler perl-script
      PerlSetVar Filter On
      PerlHandler My::BeforeSSI Apache::SSI My::AfterSSI
     </Files>

   The `"PerlSetVar Filter On"' directive tells the three stacked handlers
that they should use their filtering mode.  It's mandatory.

   The second uses `Apache::OutputChain', and your httpd.conf would look
something like this:

     PerlModule Apache::OutputChain
     PerlModule Apache::SSIChain
     PerlModule My::BeforeSSI
     PerlModule My::AfterSSI
     <Files ~ "\.ssi$">
      SetHandler perl-script
      PerlHandler Apache::OutputChain My::AfterSSI Apache::SSIChain My::BeforeSSI
     </Files>

   Note that the order of handlers is reversed in the two different
methods.  One reason I wrote `Apache::Filter' is to get the order to be
more intuitive.  Another reason is that `Apache::SSI' itself can be used
in a handler stack using `Apache::Filter', whereas it needs to be wrapped
in `Apache::SSIChain' to be used with `Apache::OutputChain'.

   Please see the documentation for `Apache::OutputChain' and
`Apache::Filter' for more specific information.  And look at the note in
CAVEATS too.

CAVEATS
=======

   * When chaining handlers via Apache::Filter, if you use <!-#include
...-> or <!-#exec cgi=...->, then Apache::SSI must be the last filter in
the chain.  This is because Apache::SSI uses $r->lookup_uri(...)->run to
include the files, and this sends the output through C's stdout rather
than Perl's STDOUT.  Thus Apache::Filter can't catch it and filter it.

   If Apache::SSI is the last filter in the chain, or if you stick to
simpler SSI directives like <!-#fsize->, <!-#flastmod->, etc. you'll be
fine.

   * Currently, the way <!-#echo var=whatever-> looks for variables is to
first try $r->subprocess_env, then try %ENV, then the five extra
environment variables mod_include supplies.  Is this the correct order?

TO DO
=====

   Revisit http://www.apache.org/docs/mod/mod_include.html and see what
else there I can implement.

   It would be nice to have a "PerlSetVar ASSI_Subrequests 0|1" option that
would let you choose between executing a full-blown subrequest when
including a file, or just opening it and printing it.

   I'd like to know how to use Apache::test for the real.t test.

SEE ALSO
========

   mod_include, mod_perl(3), Apache(3), HTML::Embperl(3), Apache::ePerl(3),
Apache::OutputChain(3)

AUTHOR
======

   Ken Williams ken@forum.swarthmore.edu

   Concept based on original version by Doug MacEachern dougm@osf.org .
Implementation different.

COPYRIGHT
=========

   Copyright 1998 Swarthmore College.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

do SSI on other modules' output
*******************************

NAME
====

   Apache::SSIChain - do SSI on other modules' output

SYNOPSIS
========

   In the conf/access.conf file of your Apache installation add lines like

     <Files *.html>
     SetHandler perl-script
     PerlHandler Apache::OutputChain Apache::SSIChain Apache::PassHtml
     </Files>

DESCRIPTION
===========

   This module uses *Apache::SSI* and *Apache::OutputChain* modules to
create a filtering module that takes output from other modules
(*Apache::PassHtml*, *Apache::PassExec*), parses SSI tags and sends the
result to Apache, or maybe to other module (*Apache::GzipChain* by Andreas
Koenig):

     <Files *.html>
     SetHandler perl-script
     PerlHandler Apache::OutputChain Apache::GzipChain Apache::SSIChain Apache::PassHtml
     </Files>

   Or you can do SSI on CGI's:

     <Files *.cgi>
     PerlSendHeader On
     SetHandler perl-script
     PerlHandler Apache::OutputChain Apache::SSIChain Apache::PassExec
     Options ExecCGI
     </Files>

   or even on modules processed by Apache::Registry:

     <Files *.pl>
     PerlSendHeader On
     SetHandler perl-script
     PerlHandler Apache::OutputChain Apache::SSIChain Apache::Registry
     Options ExecCGI
     </Files>

VERSION
=======

   0.07

AUTHOR
======

   (c) 1998-1999 Jan Pazdziora, adelton@fi.muni.cz,
http://www.fi.muni.cz/~adelton/ at Faculty of Informatics, Masaryk
University, Brno, Czech Republic

SEE ALSO
========

   Apache::SSI(3); Apache::GzipChain(3); mod_perl(1); www.apache.org,
www.perl.com.

Layered document (sandwich) maker
*********************************

NAME
====

   Apache::Sandwich - Layered document (sandwich) maker

SYNOPSIS
========

     SetHandler  perl-script
     PerlHandler Apache::Sandwich
     PerlSetVar SandwichHandler default-handler

DESCRIPTION
===========

   The *Apache::Sandwich* module allows you to add a per-directory custom
"header" and/or "footer" content to a given uri.  Only works with "GET"
requests.  Output of combined parts is forced to *text/html*.  The handler
for the sandwiched document is specified by the SandwichHandler
configuration variable.  If it is not set, "default-handler" is used.

   The basic concept is that the concatenation of the HEADER and FOOTER
parts with the sandwiched file inbetween constitute a complete valid HTML
document.

   Here's a configuration example:

     #in httpd.conf or .htaccess

     <Location /foo>
      #any request for /foo and it's document tree
      #are run through our Apache::Sandwich::handler
      SetHandler  perl-script
      PerlHandler Apache::Sandwich

     #we send this file first
     PerlSetVar HEADER "/my_header.html"

     #requested uri (e.g. /foo/index.html) is sent in the middle

     #we send output of this mod_perl script last
     PerlSetVar FOOTER "/perl/footer.pl"
      </Location>

   With the above example, one must be careful not to put graphics within
the same directory, otherwise they will be Sandwiched also.

   Here's another example which only Sandwiches the files we want (using
Apache 1.3 syntax).  In this example, all *.brc files are sandwiched using
the defined HEADER and FOOTER parts, with the file itself assumed to be a
plain text file (or static HTML file).  All *.sbrc files are similarly
sandwiched, except that the file itself is assumed to be an "shtml" file,
i.e., it is given to the SSI handler for server side includes to be
processed.

     # filter *.brc files through Sandwich maker, but define
     # HEADER/FOOTER per section below

     <FilesMatch "\.brc$">
      SetHandler  perl-script
      PerlHandler Apache::Sandwich
     </FilesMatch>

     <FilesMatch "\.sbrc$">
      SetHandler  perl-script
      PerlHandler Apache::Sandwich
      PerlSetVar SandwichHandler server-parsed
     </FilesMatch>

     # now specify the header and footer for each major section
     #
     <Location /misc>
       PerlSetVar HEADER "/misc/HEADER.shtml ADS.shtml"
       PerlSetVar FOOTER "/misc/FOOTER.html"
     </Location>

     <Location /getting_started>
       PerlSetVar HEADER "/getting_started/HEADER.shtml ADS.shtml"
       PerlSetVar FOOTER "/misc/FOOTER.html"
     </Location>

   Note that in this example, the file `ADS.shtml' is included from the
same directory as the requested file.

   The files referenced in the HEADER and FOOTER variables are fetched
using the "GET" method and may be of any type file the server can process.

Sandwiching mod_perl Programs
-----------------------------

   The helper function insert_parts() can be used to make your CGI
programs look like the rest of your pages.  A simple script would be:

     #! /usr/local/bin/perl
     use strict;

     use CGI;
     use Apache::Sandwich;

     use vars qw($query);

     $query = new CGI or die "Something failed";

     print $query->header();
     Apache::Sandwich::insert_parts('HEADER');

     print $query->p("Hello, world!");

     Apache::Sandwich::insert_parts('FOOTER');

KNOWN BUGS
==========

   Headers printed by mod_perl scripts used as a HEADER, FOOTER or
in-the-middle uri need to use CGI.pm version 2.37 or higher or headers
will show up in the final document (browser window).  Suggested
work-around (if you don't want to upgrade CGI.pm):

     if($ENV{MOD_PERL} and Apache->request->is_main) {
        #send script headers
        print "Content-type: text/html\n\n";
     } else {
        #we're part of a sub-request, don't send headers
     }

   Setting $Apache::Sandwich::Debug to 1 will log debugging information
into the Apache ErrorLog.

AUTHOR
======

   Doug MacEachern.  Modifications and cleanup by Vivek Khera.

Perl interface to the Apache scoreboard structure
*************************************************

NAME
====

   Apache::Scoreboard - Perl interface to the Apache scoreboard structure

SYNOPSIS
========

     use Apache::Scoreboard ();

     #inside httpd
     my $image = Apache::Scoreboard->image;

     #outside httpd
     my $image = Apache::Scoreboard->fetch("http://localhost/scoreboard");

DESCRIPTION
===========

   Apache keeps track of server activity in a structure known as the
*scoreboard*.  There is a slot in the scoreboard for each child server,
containing information such as status, access count, bytes served and cpu
time.  This same information is used by *mod_status* to provide current
server statistics in a human readable form.

METHODS
=======

image
     This method returns an object for accessing the scoreboard structure
     when running inside the server:

          my $image = Apache::Scoreboard->image;

fetch
     This method fetches the scoreboard structure from a remote server,
     which must contain the following configuration:

          PerlModule Apache::Scoreboard
          <Location /scoreboard>
             SetHandler perl-script
             PerlHandler Apache::Scoreboard::send
             order deny,allow
             deny from all
             #same config you have for mod_status
             allow from 127.0.0.1 ...
          </Location>

     If the remote server is not configured to use mod_perl or simply for a
     smaller footprint, see the *apxs* directory for *mod_scoreboard_send*:

          LoadModule scoreboard_send_module libexec/mod_scoreboard_send.so

          <Location /scoreboard>
             SetHandler scoreboard-send-handler
             order deny,allow
             deny from all
             allow from 127.0.0.1 ...
          </Location>

     The image can then be fetched via http:

          my $image = Apache::Scoreboard->fetch("http://remote-hostname/scoreboard");

fetch_store
retrieve
     The fetch_store method is used to fetch the image once from and
     remote server and save it to disk.  The image can then be read by
     other processes with the retrieve function.  This way, multiple
     processes can access a remote scoreboard with just a single request
     to the remote server.  Example:

          Apache::Scoreboard->fetch_store($url, $local_filename);

          my $image = Apache::Scoreboard->retrieve($local_filename);

parent
     This method returns a reference to the first parent score entry in the
     list, blessed into the *Apache::ParentScore* class:

          my $parent = $image->parent;

     Iterating over the list of scoreboard slots is done like so:

          for (my $parent = $image->parent; $parent; $parent = $parent->next) {
              my $pid = $parent->pid; #pid of the child

          my $server = $parent->server; #Apache::ServerScore object

          ...
           }

pids
     Returns an array reference of all child pids:

          my $pids = $image->pids;

The Apache::ParentScore Class
-----------------------------

pid
     The parent keeps track of child pids with this field:

          my $pid = $parent->pid;

server
     Returns a reference to the corresponding *Apache::ServerScore*
     structure:

          my $server = $parent->server;

next
     Returns a reference to the next *Apache::ParentScore* object in the
     list:

          my $p = $parent->next;

The Apache::ServerScore Class
-----------------------------

status
     This method returns the status of child server, which is one of:

          "_" Waiting for Connection
          "S" Starting up
          "R" Reading Request
          "W" Sending Reply
          "K" Keepalive (read)
          "D" DNS Lookup
          "L" Logging
          "G" Gracefully finishing
          "." Open slot with no current process

access_count
     The access count of the child server:

          my $count = $server->access_count;

request
     The first 64 characters of the HTTP request:

          #e.g.: GET /scoreboard HTTP/1.0
          my $request = $server->request;

client
     The ip address or hostname of the client:

          #e.g.: 127.0.0.1
          my $client = $server->client;

bytes_served
     Total number of bytes served by this child:

          my $bytes = $server->bytes_served;

conn_bytes
     Number of bytes served by the last connection in this child:

          my $bytes = $server->conn_bytes;

conn_count
     Number of requests served by the last connection in this child:

          my $count = $server->conn_count;

times
     In a list context, returns a four-element list giving the user and
     system times, in seconds, for this process and the children of this
     process.

          my($user, $system, $cuser, $csystem) = $server->times;

     In a scalar context, returns the overall CPU percentage for this
     server:

          my $cpu = $server->times;

start_time
     In a list context this method returns a 2 element list with the
     seconds and microseconds since the epoch, when the request was
     started.  In scalar context it returns floating seconds like
     Time::HiRes::time()

          my($tv_sec, $tv_usec) = $server->start_time;

          my $secs = $server->start_time;

stop_time
     In a list context this method returns a 2 element list with the
     seconds and microseconds since the epoch, when the request was
     finished.  In scalar context it returns floating seconds like
     Time::HiRes::time()

          my($tv_sec, $tv_usec) = $server->stop_time;

          my $secs = $server->stop_time;

req_time
     Returns the time taken to process the request in microseconds:

          my $req_time = $server->req_time;

SEE ALSO
========

   Apache::VMonitor(3), GTop(3)

AUTHOR
======

   Doug MacEachern

A persistence framework for session data
****************************************

NAME
====

   Apache::Session - A persistence framework for session data

SYNOPSIS
========

     use Apache::Session::MySQL;

     my %session;

     #make a fresh session for a first-time visitor
     tie %session, 'Apache::Session::MySQL';

     #stick some stuff in it
     $session{visa_number} = "1234 5678 9876 5432";

     #get the session id for later use
     my $id = $session{_session_id};

     #...time passes...

     #get the session data back out again during some other request
     my %session;
     tie %session, 'Apache::Session::MySQL', $id;

     &validate($session{visa_number});

     #delete a session from the object store permanently
     tied(%session)->delete;

DESCRIPTION
===========

   Apache::Session is a persistence framework which is particularly useful
for tracking session data between httpd requests.  Apache::Session is
designed to work with Apache and mod_perl, but it should work under CGI
and other web servers, and it also works outside of a web server
altogether.

   Apache::Session consists of five components: the interface, the object
store, the lock manager, the ID generator, and the serializer.  The
interface is defined in Session.pm, which is meant to be easily
subclassed.  The object store can be the filesystem, a Berkeley DB, a
MySQL DB, an Oracle DB, or a Postgres DB. Locking is done by lock files,
semaphores, or the locking capabilities of MySQL and Postgres.
Serialization is done via Storable, and optionally  ASCII-fied via MIME or
pack().  ID numbers are generated via MD5.  The reader is encouraged to
extend these capabilities to meet his own requirements.

   A derived class of Apache::Session is used to tie together the three
components.  The derived class inherits the interface from
Apache::Session, and specifies which store and locker classes to use.
Apache::Session::MySQL, for instance, uses the MySQL storage class and
also the MySQL locking class. You can easily plug in your own object store
or locker class.

INTERFACE
=========

   The interface to Apache::Session is very simple: tie a hash to the
desired class and use the hash as normal.  The constructor takes two
optional arguments.  The first argument is the desired session ID number,
or undef for a new session.  The second argument is a hash of options that
will be passed to the object store and locker classes.

tieing the session
------------------

   Get a new session using DBI:

     tie %session, 'Apache::Session::MySQL', undef,
        { DataSource => 'dbi:mysql:sessions' };

     Restore an old session from the database:

     tie %session, 'Apache::Session::MySQL', $session_id,
        { DataSource => 'dbi:mysql:sessions' };

Storing and retrieving data to and from the session
---------------------------------------------------

   Hey, how much easier could it get?

     $session{first_name} = "Chuck";
     $session{an_array_ref} = [ $one, $two, $three ];
     $session{an_object} = new Some::Class;

Reading the session ID
----------------------

   The session ID is the only magic entry in the session object, but
anything beginning with a "_" is considered reserved for future use.

     my $id = $session{_session_id};

Permanently removing the session from storage
---------------------------------------------

     tied(%session)->delete;

BEHAVIOR
========

   Apache::Session tries to behave the way the author believes that you
would expect.  When you create a new session, Session immediately saves
the session to the data store, or calls die() if it cannot.  It also
obtains an exclusive lock on the session object.  If you retrieve an
existing session, Session immediately restores the object from storage, or
calls die() in case of an error.  Session also obtains an non-exclusive
lock on the session.

   As you put data into the session hash, Session squirrels it away for
later use.  When you untie() the session hash, or it passes out of scope,
Session checks to see if anything has changed. If so, Session gains an
exclusive lock and writes the session to the data store.  It then releases
any locks it has acquired.

   Note that Apache::Session does only a shallow check to see if anything
has changed.  If nothing changes in the top level tied hash, the data will
not be updated in the backing store.  You are encouraged to timestamp the
session hash so that it is sure to be updated.

   When you call the delete() method on the session object, the object is
immediately removed from the object store, if possible.

   When Session encounters an error, it calls die().  You will probably
want to wrap your session logic in an eval block to trap these errors.

LOCKING AND TRANSACTIONS
========================

   By default, most Apache::Session implementations only do locking to
prevent data corruption.  The locking scheme does not provide transactional
consistency, such as you might get from a relational database.  If you
desire transactional consistency, you must provide the Transaction
argument with a true value when you tie the session hash.  For example:

     tie %s, 'Apache::Session::File', $id {
        Directory     => '/tmp/sessions',
        LockDirectory => '/var/lock/sessions',
        Transaction   => 1
     };

   Note that the Transaction argument has no practical effect on the MySQL
and Postgres implementations.  The MySQL implementation only supports
exclusive locking, and the Postgres implementation uses the transaction
features of that database.

IMPLEMENTATION
==============

   The way you implement Apache::Session depends on what you are trying to
accomplish.  Here are some hints on which classes to use in what situations

STRATEGIES
==========

   Apache::Session is mainly designed to track user session between http
requests.  However, it can also be used for any situation where data
persistence is desirable.  For example, it could be used to share global
data between your httpd processes.  The following examples are short
mod_perl programs which demonstrate some session handling basics.

Sharing data between Apache processes
-------------------------------------

   When you share data between Apache processes, you need to decide on a
session ID number ahead of time and make sure that an object with that ID
number is in your object store before starting you Apache.  How you
accomplish that is your own business.  I use the session ID "1".  Here is
a short program in which we use Apache::Session to store out database
access information.

     use Apache;
     use Apache::Session::File;
     use DBI;

     use strict;

     my %global_data;

     eval {
         tie %global_data, 'Apache::Session::File', 1,
            {Directory => '/tmp/sessiondata'};
     };
     if ($@) {
        die "Global data is not accessible: $@";
     }

     my $dbh = DBI->connect($global_data{datasource},
        $global_data{username}, $global_data{password}) || die $DBI::errstr;

     undef %global_data;

     #program continues...

     As shown in this example, you should undef or untie your session hash
     as soon as you are done with it.  This will free up any locks associated
     with your process.

Tracking users with cookies
---------------------------

   The choice of whether to use cookies or path info to track user IDs is
a rather religious topic among Apache users.  This example uses cookies.
The implementation of a path info system is left as an exercise for the
reader.

     use Apache::Session::MySQL;
     use Apache;

     use strict;

     #read in the cookie if this is an old session

     my $r = Apache->request;
     my $cookie = $r->header_in('Cookie');
     $cookie =~ s/SESSION_ID=(\w*)/$1/;

     #create a session object based on the cookie we got from the browser,
     #or a new session if we got no cookie

     my %session;
     tie %session, 'Apache::Session::MySQL', $cookie, {
          DataSource => 'dbi:mysql:sessions', #these arguments are
          UserName   => 'mySQL_user',         #required when using
          Password   => 'password',           #MySQL.pm
          LockDataSource => 'dbi:mysql:sessions',
          LockUserName   => 'mySQL_user',
          LockPassword   => 'password'
     };

     #Might be a new session, so lets give them their cookie back

     my $session_cookie = "SESSION_ID=$session{_session_id};";
     $r->header_out("Set-Cookie" => $session_cookie);

     #program continues...

SEE ALSO
========

   Apache::Session::MySQL, Apache::Session::Postgres,
Apache::Session::File, Apache::Session::DB_File

   The O Reilly book "Apache Modules in Perl and C", by Doug MacEachern and
Lincoln Stein, has a chapter on keeping state.

AUTHORS
=======

   Jeffrey Baker <jwbaker@acm.org> is the author of Apache::Session.

   Erik Rantapaa <rantapaa@fanbuzz.com> found errors in both Lock::File
and Store::File

   Bart Schaefer <schaefer@zanshin.com> notified me of a bug in Lock::File.

   Chris Winters <cwinters@intes.net> contributed the Sybase code.

   Michael Schout <mschout@gkg.net> fixed a commit policy bug in 1.51.

   Andreas J. Koenig <andreas.koenig@anima.de> contributed valuable CPAN
advice and also Apache::Session::Tree and Apache::Session::Counted.

   Gerald Richter <richter@ecos.de> had the idea for a tied hash interface
and provided the initial code for it.  He also uses Apache::Session in his
Embperl module and is the author of Apache::Session::Embperl

   Jochen Wiedmann <joe@ipsoft.de> contributed patches for bugs and
improved performance.

   Steve Shreeve <shreeve@uci.edu> squashed a bug in 0.99.0 whereby a
cleared hash or deleted key failed to set the modified bit.

   Peter Kaas <Peter.Kaas@lunatech.com> sent quite a bit of feedback with
ideas for interface improvements.

   Randy Harmon <rjharmon@uptimecomputers.com> contributed the original
storage-independent object interface with input from:

     Bavo De Ridder <bavo@ace.ulyssis.student.kuleuven.ac.be>
     Jules Bean <jmlb2@hermes.cam.ac.uk>
     Lincoln Stein <lstein@cshl.org>

Session management via a File::CounterFile
******************************************

NAME
====

   Apache::Session::Counted - Session management via a File::CounterFile

SYNOPSIS
========

     tie %s, 'Apache::Session::Counted', $sessionid, {
                                    Directory => <root of directory tree>,
                                    DirLevels => <number of dirlevels>,
                                    CounterFile => <filename for File::CounterFile>,
                                    AlwaysSave => <boolean>
                                                     }

DESCRIPTION
===========

   This session module is based on Apache::Session, but it persues a
different notion of a session, so you probably have to adjust your
expectations a little.

   The dialog that is implemented within an HTTP based application is a
nonlinear chain of events. The user can decide to use the back button at
any time without informing the application about it. A proper session
management must be prepared for this and must maintain the state of every
single event. For handling the notion of a session and the notion of a
registered user, the application has to differentiate carefully between
global state of user data and a user's session related state. Some data
may expire after a day, others may be regarded as unexpirable. This module
is solely responsible for handling session related data. Saving
unexpirable user related data must be handled by the calling application.

   In Apache::Session::Counted, a session-ID only lasts from one request
to the next at which point a new session-ID is computed by the
File::CounterFile module. Thus what you have to treat differently than in
Apache::Session are those parts that rely on the session-ID as a fixed
token per user. Accordingly, there is no option to delete a session. The
remove method is simply disabled as old session data will be overwritten
as soon as the counter is reset to zero.

   The usage of the module is via a tie as described in the synopsis. The
arguments have the following meaning:

Directory, DirLevels
     Works similar to filestore but as most file systems are slow on large
     directories, works in a tree of subdirectories.

CounterFile
     A filename to be used by the File::CounterFile module. By changing
     that file or the filename periodically, you can achieve arbitrary
     patterns of key generation.

AlwaysSave
     A boolean which, if true, forces storing of session data in any case.
     If false, only a STORE, DELETE or CLEAR trigger that the session file
     will be written when the tied hash goes out of scope. This has the
     advantage that you can retrieve an old session without storing its
     state again.

HostID
     A string that serves as an identifier for the host we are running on.
     This string will become part of the session-ID and must not contain a
     colon. This can be used in a cluster environment so that a load
     balancer or other interested parties can retrieve the session data
     again.

HostURL
     A callback that returns the service URL that can be called to get at
     the session data from another host. This is needed in a cluster
     environment. Two arguments are passed to this callback: HostID and
     Session-ID. The URL must return the serialized data in Storable's
     nfreeze format. The Apache::Session::Counted module can be used to set
     such an URL up. If HostURL is not defined, the default is

          sprintf "http://%s/?SESSIONID=%s", <host>, <session-ID>;

What this model buys you
------------------------

storing state selectively
     You need not store session data for each and every request of a
     particular user. There are so many CGI requests that can easily be
     handled with two hidden fields and do not need any session support on
     the server side, and there are others where you definitely need
     session support. Both can appear within the same application.
     Apache::Session::Counted allows you to switch session writing on and
     off during your application without effort. (In fact, this advantage
     is shared with the clean persistence model of Apache::Session)

keeping track of transactions
     As each request of a single user remains stored until you restart the
     counter, there are all previous states of a single session close at
     hand. The user presses the back button 5 times and changes a decision
     and simply opens a new branch of the same session. This can be an
     advantage and a disadvantage. I tend to see it as a very strong
     feature. Your milage may vary.

counter
     You get a counter for free which you can control just like
     File::CounterFile (because it *is* File::CounterFile).

cleanup
     Your data storage area cleans up itself automatically. Whenever you
     reset your counter via File::CounterFile, the storage area in use is
     being reused. Old files are being overwritten in the same order they
     were written, giving you a lot of flexibility to control session
     storage time and session storage disk space.

performance
     The notion of daisy-chained sessions simplifies the code of the
     session handler itself quite a bit and it is likely that this
     simplification results in an improved performance (not tested yet due
     to lack of benchmarking apps for sessions). There are less file stats
     and less sections that need locking, but without real world figures,
     it's hard to tell what's up.

   As with other modules in the Apache::Session collection, the tied hash
contains a key <_session_id>. You must be aware that the value of this
hash entry is not the same as the one you passed in when you retrieved the
session (if you retrieved a session at all). So you have to make sure that
you send your users a new session-id in each response, and that this is
never the old one.

   As an implemenation detail it may be of interest to you, that the
session ID in Apache::Session::Counted consists of two or three parts: an
optional host alias given by the HostID paramter, followed by a colon.
Then an ordinary number which is a simple counter which is followed by an
underscore. And finally a session-ID like the one in Apache::Session. The
number part is used as an identifier of the session and the ID part is
used as a password. The number part is easily predictable, but the second
part is reasonable unpredictable.  We use the first part for
implementation details like storage on the disk and the second part to
verify the ownership of that token.

PREREQUISITES
=============

   Apache::Session::Counted needs Apache::Session and File::CounterFile,
all available from the CPAN. The HostID and HostURL paramters for a
cluster solution need LWP installed.

EXAMPLES
========

   The following example resets the counter every 24 hours and keeps the
totals of every day as a side effect:

     my(@t) = localtime;
     tie %session, 'Apache::Session::Counted', $sid,
     {
      Directory => ...,
      DirLevels => ...,
      CounterFile => sprintf("/some/dir/%04d-%02d-%02d", $t[5]+1900,$t[4]+1,$t[3])
     };

   The same effect can be accomplished with a fixed filename and an
external cronjob that resets the counter like so:

     use File::CounterFile;
     $c=File::CounterFile->new("/usr/local/apache/data/perl/sessiondemo/counter");
     $c->lock;
     $c-- while $c>0;
     $c->unlock;

AUTHOR
======

   Andreas Koenig <andreas.koenig@anima.de>

COPYRIGHT
=========

   This software is copyright(c) 1999,2000 Andreas Koenig. It is free
software and can be used under the same terms as perl, i.e. either the GNU
Public Licence or the Artistic License.

Session persistence via DBI
***************************

NAME
====

   Apache::Session::DBI - Session persistence via DBI

SYNOPSIS
========

DESCRIPTION
===========

   Apache::Session::DBI is wrapper for the Apache::Session::DBIStore and
Apache::Session::PosixFileLocker modules.  Please consult the documentation
for those modules.

Session persistence via DBI with  ASCII  encoding of session data.
******************************************************************

NAME
====

   Apache::Session::DBIBase64Store - Session persistence via DBI with
ASCII encoding of session data.

SYNOPSIS
========

     package MySession;

     use Apache::Session;
     use Apache::Session::DBIBase64Store;
     use Apache::Session::NullLocker;

     @ISA = ( Apache::Session );

     sub get_object_store {
     	my $self = shift;

     return new Apache::Session::DBIBase64Store $self;
         }

     sub get_lock_manager {
     	my $self = shift;

     return new Apache::Session::NullLocker $self;
         }

DESCRIPTION
===========

   Apache::Session::DBIBase64Store is a session data persistent store for
`Apache::Session|Apache::Session' in this node. This module should be used
instead of DBIStore in database that don't support binary data in table
fields (like PostgreSQL for instance).

   This store also store the creation time of the session and the timestamp
of the last update.

SCHEMA
======

   This modules expect a table created with the following schema :

     CREATE TABLE sessions (
     	id	    CHAR(32) PRIMARY KEY,
     	length	    INT,
     	a_session   TEXT,
     	created	    TIMESTAMP DEFAULT 'now()',
     	last_update TIMESTAMP DEFAULT 'now()'
     	locked_by   INT
     );

   The previous SQL statement is valid for PostgreSQL. Adapt for your
specific DBMS.

   NOTE: The id length can be fine tuned for specific application. By
default, `Apache::Session|Apache::Session' in this node uses 16 char
length ID, but I usually use 128 bits ID (32 chars).

CONFIGURATION
=============

   This package can either use an already open DBH handle or it can be
told the DataSource, UserName and Password to open its own database
connection.

   In the first case use something like this (using the `SYNOPSIS|' in
this node example):

     my $dbh = DBI->connect( $DSN, $USER, $PASSWORD, { AutoCommit => 0,
     						      RaiseError => 1,} );
     tie %sesssion, 'MySession', undef, { dbh => $dbh };

   In the second case use something like this :

     tie %session, 'MySession', undef, { DataSource => $DSN,
     					UserName   => $USERNAME,
     					Password   => $PASSWORD,
     				        };

   In the case where you give this module a DBH handle to use, rather than
to manage its own. The module will commit the transaction after each
insert, update or delete. Be warned if you are not using AutoCommit mode.

CREDITS
=======

   This module is largely based on
`Apache::Session::DBIStore|Apache::Session::DBIStore' in this node by
Jeffrey William Baker (jeffrey@kathyandjeffrey.net).

AUTHOR
======

   Copyright (c) 1999 Francis J. Lacoste and iNsu Innovations Inc.  All
rights reserved.

   Parts Copyright (c) 1998,1999 Jeffrey William Baker
(jeffrey@kathyandjeffrey.net)

   This program is free software; you can redistribute it and/or modify it
under the terms as perl itself.

SEE ALSO
========

   Apache::Session(3) Apache::Session::DBIStore(3) DBI(3)

Session persistence via DBI
***************************

NAME
====

   Apache::Session::DBIStore - Session persistence via DBI

SYNOPSIS
========

DESCRIPTION
===========

   Apache::Session::DBIStore is a backing store module for Apache::Session.
Session data is stored in a DBI-accessible database.

SCHEMA
======

   To use this module, you will need these columns in a table called
'sessions':

     id char(16)
     length int(11)
     a_session text

   Where the a_session column needs to be able to handle arbitrarily long
binary data.

CONFIGURATION
=============

   When using DBI, the module must know what datasource, username, and
password to use when connecting to the database.  These values can be set
for all sessions by using package globals, or for each individual session
using the options hash (see Apache::Session documentation).  The options
are:

   Package globals:

$Apache::Session::DBIStore::DataSource
$Apache::Session::DBIStore::UserName
$Apache::Session::DBIStore::Password
   Corresponding options:

DataSource
UserName
Password
   Example with options:

     tie %hash, 'Apache::Session::DBI', $id, {
         DataSource => 'dbi:driver:database',
         UserName   => 'database_user',
         Password   => 'K00l'
     };

     Example with package globals:

     $Apache::Session::DBIStore::DataSource = 'dbi:driver:database';
     $Apache::Session::DBIStore::UserName   = 'database_user';
     $Apache::Session::DBIStore::Password   = 'K00l';

     tie %hash, 'Apache::Session::DBI', $id;

An implementation of Apache::Session
************************************

NAME
====

   Apache::Session::DB_File - An implementation of Apache::Session

SYNOPSIS
========

     use Apache::Session::DB_File;

     tie %hash, 'Apache::Session::DB_File', $id, {
        FileName      => 'sessions.db',
        LockDirectory => '/var/lock/sessions',
     };

DESCRIPTION
===========

   This module is an implementation of Apache::Session.  It uses the
DB_File backing store and the File locking scheme.  You must specify the
filename of the database file and the directory for locking in arguments
to the constructor.  See the example, and the documentation for
Apache::Session::Store::DB_File and Apache::Session::Lock::File.

AUTHOR
======

   This module was written by Jeffrey William Baker <jwbaker@acm.org>.

SEE ALSO
========

   See Apache/Session/File,
Apache/Session/Flex, Apache/Session/MySQL,
see Apache/Session/Postgres,
see Apache/Session,

works with HTML::Embperl
************************

NAME
====

   Apache::Session::Embperl - works with HTML::Embperl

DESCRIPTION
===========

   An adaptation of Apache::Session to work with HTML::Embperl

SYNOPSIS
========

Addtional Attributes for TIE
----------------------------

lazy
     By Specifing this attribute, you tell Apache::Session to not do any
     access to the object store, until the first read or write access to
     the tied hash. Otherwise the tie function will make sure the hash
     exist or creates a new one.

create_unknown
     Setting this to one causes Apache::Session to create a new session
     when the specified session id does not exists. Otherwise it will die.

object_store
     Specify the class for the object store. (The Apache::Session:: prefix
     is optional)

lock_manager
     Specify the class for the lock manager. (The Apache::Session:: prefix
     is optional)

   Example using attrubtes to specfiy store and object classes instead of
a derived class:

     use Apache::Session ;

     tie %session, 'Apache::Session', undef,
        {
        object_store => 'DBIStore',
        lock_manager => 'SysVSemaphoreLocker',
        DataSource => 'dbi:Oracle:db'
        };

   NOTE: Apache::Session will require the nessecary additional perl
modules for you.

Addtional Methods
-----------------

setid
     Set the session id for futher accesses.

getid
     Get the session id. The difference to using $session{_session_id} is,
     that in lazy mode, getid will not create a new session id, if it
     doesn't exists.

cleanup
     Writes any pending data, releases all locks and deletes all data from
     memory.

AUTHORS
=======

   This class was written by Jeffrey Baker (jeffrey@kathyandjeffrey.net)
but it is taken wholesale from a patch that Gerald Richter
(richter@ecos.de) sent me against Apache::Session

An implementation of Apache::Session
************************************

NAME
====

   Apache::Session::File - An implementation of Apache::Session

SYNOPSIS
========

     use Apache::Session::File;

     tie %hash, 'Apache::Session::File', $id, {
        Directory => '/tmp/sessions',
        LockDirectory   => '/var/lock/sessions',
     };

DESCRIPTION
===========

   This module is an implementation of Apache::Session.  It uses the File
backing store and the File locking scheme.  You must specify the directory
for the object store and the directory for locking in arguments to the
constructor. See the example, and the documentation for
Apache::Session::Store::File and Apache::Session::Lock::File.

AUTHOR
======

   This module was written by Jeffrey William Baker <jwbaker@acm.org>.

SEE ALSO
========

   See Apache/Session/DB_File,
Apache/Session/Flex, Apache/Session/MySQL,
see Apache/Session/Postgres,
see Apache/Session,

Specify everything at runtime
*****************************

NAME
====

   Apache::Session::Flex - Specify everything at runtime

SYNOPSIS
========

     use Apache::Session::Flex;

     tie %hash, 'Apache::Session::Flex', $id, {
        Store     => 'DB_File',
        Lock      => 'Null',
        Generate  => 'MD5',
        Serialize => 'Storable'
     };

     # or

     tie %hash, 'Apache::Session::Flex', $id, {
        Store     => 'Postgres',
        Lock      => 'Null',
        Generate  => 'MD5',
        Serialize => 'Base64'
     };

     # you decide!

DESCRIPTION
===========

   This module is an implementation of Apache::Session.  Unlike other
implementations, it allows you to specify the backing store, locking
scheme, ID generator, and data serializer at runtime.  You do this by
passing arguments in the usual Apache::Session style (see SYNOPSIS).  You
may use any of the modules included in this distribution, or a module of
your own making.  If you wish to use a module of your own making, you
should make sure that it is available under the Apache::Session package
namespace.

USAGE
=====

   You pass the modules you want to use as arguments to the constructor.
The Apache::Session::Whatever part is appended for you: you should not
supply it.  For example, if you wanted to use MySQL as the backing store,
you should give the argument `Store =' 'MySQL'>, and not `Store ='
'Apache::Session::Store::MySQL'>.  There are four modules that you need to
specify.  Store is the backing store to use.  Lock is the locking scheme.
Generate is the ID generation module.  Serialize is the data serialization
module.

   There are many modules included in this distribution.  For each role,
they are:

     Store:
        MySQL
        Postgres
        DB_File
        File

     Lock:
        Null
        MySQL
        Semaphore

     Generate:
        MD5

     Serialize:
        Storable
        Base64
        UUEncode

     In addition to the arguments needed by this module, you must provide whatever
     arguments are expected by the backing store and lock manager that you are
     using.  Please see the documentation for those modules.

AUTHOR
======

   This module was written by Jeffrey William Baker <jwbaker@acm.org>.

SEE ALSO
========

   See Apache/Session/File,
Apache/Session/DB_File,
Apache/Session/MySQL,
Apache/Session/Postgres, Apache/Session,

Use MD5 to create random object IDs
***********************************

NAME
====

   Apache::Session::Generate::MD5 - Use MD5 to create random object IDs

SYNOPSIS
========

     use Apache::Session::Generate::MD5;

     $id = Apache::Session::Generate::MD5::generate();

DESCRIPTION
===========

   This module fulfills the ID generation interface of Apache::Session.
The IDs are generated using a two-round MD5 of a random number, the time
since the epoch, the process ID, and the address of an anonymous hash.
The resultant ID number is highly entropic on Linux and other platforms
that have good random number generators.  You are encouraged to
investigate the quality of your system's random number generator if you
are using the generated ID numbers in a secure environment.

   This module can also examine session IDs to ensure that they are,
indeed, session ID numbers and not evil attacks.  The reader is encouraged
to consider the effect of bogus session ID numbers in a system which uses
these ID numbers to access disks and databases.

   This modules takes one argument in the usual Apache::Session style.  The
argument is IDLength, and the value, between 0 and 32, tells this module
where to truncate the session ID.  Without this argument, the session ID
will be 32 hexadecimal characters long, equivalent to a 128-bit key.

AUTHOR
======

   This module was written by Jeffrey William Baker <jwbaker@acm.org>.

SEE ALSO
========

   See Apache/Session,

Store client sessions via IPC::Shareable
****************************************

NAME
====

   Apache::Session::IPC - Store client sessions via IPC::Shareable

SYNOPSIS
========

   use Apache::Session::IPC

DESCRIPTION
===========

   This is an IPC storage subclass for Apache::Session.  Client state is
stored in a shared memory block.  Try `perldoc Session' for more info.

INSTALLATION
============

Getting started
---------------

   Build, test, and install IPC::Shareable, from CPAN.  If you don't have
IPC on your system, you can't use this module.

   Build and install Apache::Session

Environment
-----------

   Apache::Session::IPC does not define any environment variables beyond
those of Apache::Session.  See that package for details.

USAGE
=====

   This package complies with the API defined by Apache::Session.  For
details, please see that package's documentation.

   The default for autocommit in Apache::Session::IPC is 0, which means
that you will need to either call $session->store() when you are done or
set autocommit to 1 via the open() and new() functions.

NOTES
=====

   Performance of IPC on my test system (Linux 2.0.34) is boy-howdy slow.
DBI is approx. 80 times faster.  Also, IPC::Shareable will eventually fall
over under heavy load.  Try to use one of the other subclasses unless your
system's IPC is vastly better than what I have seen.

AUTHORS
=======

   Jeffrey Baker <jeff@godzilla.tamu.edu>, author and maintainer.

   Redistribute under the Perl Artistic License.

Provides mutual exclusion using flock
*************************************

NAME
====

   Apache::Session::Lock::File - Provides mutual exclusion using flock

SYNOPSIS
========

     use Apache::Session::Lock::File;

     my $locker = new Apache::Session::Lock::File;

     $locker->acquire_read_lock($ref);
     $locker->acquire_write_lock($ref);
     $locker->release_read_lock($ref);
     $locker->release_write_lock($ref);
     $locker->release_all_locks($ref);

     $locker->clean($dir, $age);

DESCRIPTION
===========

   Apache::Session::Lock::File fulfills the locking interface of
Apache::Session.  Mutual exclusion is achieved through the use of temporary
files and the flock function.

CONFIGURATION
=============

   The module must know where to create its temporary files.  You must
pass an argument in the usual Apache::Session style.  The name of the
argument is LockDirectory and its value is the path where you want the
lockfiles created.  Example:

     tie %s, 'Apache::Session::Blah', $id, {LockDirectory => '/var/lock/sessions'}

   If you do not supply this argument, temporary files will be created in
/tmp.

NOTES
=====

   This module does not unlink temporary files, because it interferes with
proper locking.  THis can cause problems on certain systems (Linux) whose
file systems (ext2) do not perform well with lots of files in one
directory.  To prevent this you should use a script to clean out old files
from your lock directory.  The meaning of old is left as a policy decision
for the implementor, but a method is provided for implementing that
policy.  You can use the clean method of this module to remove files
unmodified in the last $age seconds.  Example:

     my $l = new Apache::Session::Lock::File;
     $l->clean('/var/lock/sessions', 3600) #remove files older than 1 hour

AUTHOR
======

   This module was written by Jeffrey William Baker <jwbaker@acm.org>.

SEE ALSO
========

   See Apache/Session,

Provides mutual exclusion using MySQL
*************************************

NAME
====

   Apache::Session::Lock::MySQL - Provides mutual exclusion using MySQL

SYNOPSIS
========

     use Apache::Session::Lock::MySQL;

     my $locker = new Apache::Session::Lock::MySQL;

     $locker->acquire_read_lock($ref);
     $locker->acquire_write_lock($ref);
     $locker->release_read_lock($ref);
     $locker->release_write_lock($ref);
     $locker->release_all_locks($ref);

DESCRIPTION
===========

   Apache::Session::Lock::MySQL fulfills the locking interface of
Apache::Session.  Mutual exclusion is achieved through the use of MySQL's
GET_LOCK and RELEASE_LOCK functions.  MySQL does not support the notion of
read and write locks, so this module only supports exclusive locks.  When
you request a shared read lock, it is instead promoted to an exclusive
write lock.

CONFIGURATION
=============

   The module must know how to connect to your MySQL database to acquire
locks.  You must provide a datasource name, a user name, and a password.
These options are passed in the usual Apache::Session style, and are very
similar to the options for Apache::Session::Store::MySQL.  Example:

     tie %hash, 'Apache::Session::MySQL', $id, {
         LockDataSource => 'dbi:mysql:database',
         LockUserName   => 'database_user',
         LockPassword   => 'K00l'
     };

   Instead, you may pass in an already opened DBI handle to your database.

     tie %hash, 'Apache::Session::MySQL', $id, {
         LockHandle => $dbh
     };

AUTHOR
======

   This module was written by Jeffrey William Baker <jwbaker@acm.org>.

SEE ALSO
========

   See Apache/Session,

Does not actually provides mutual exclusion
*******************************************

NAME
====

   Apache::Session::Lock::Null - Does not actually provides mutual
exclusion

SYNOPSIS
========

     use Apache::Session::Lock::Null;

     my $locker = new Apache::Session::Lock::Null;

     $locker->acquire_read_lock($ref);
     $locker->acquire_write_lock($ref);
     $locker->release_read_lock($ref);
     $locker->release_write_lock($ref);
     $locker->release_all_locks($ref);

DESCRIPTION
===========

   Apache::Session::Lock::Null fulfills the locking interface of
Apache::Session, without actually doing any work.  This is the module to
use if you want maximum performance and don't actually need locking.

AUTHOR
======

   This module was written by Jeffrey William Baker <jwbaker@acm.org>.

SEE ALSO
========

   See Apache/Session,

Provides mutual exclusion through sempahores
********************************************

NAME
====

   Apache::Session::Lock::Semaphore - Provides mutual exclusion through
sempahores

SYNOPSIS
========

     use Apache::Session::Lock::Semaphore;

     my $locker = new Apache::Session::Lock::Semaphore;

     $locker->acquire_read_lock($ref);
     $locker->acquire_write_lock($ref);
     $locker->release_read_lock($ref);
     $locker->release_write_lock($ref);
     $locker->release_all_locks($ref);

DESCRIPTION
===========

   Apache::Session::Lock::Sempahore fulfills the locking interface of
Apache::Session.  Mutual exclusion is achieved through system semaphores
and the IPC::Semaphore module.

CONFIGURATION
=============

   The module must know how many semaphores to use, and what semaphore key
to use.  The number of semaphores has an impact on performance.  More
semaphores meansless lock contention.  You should use the maximum number
of sempahores that your platform will allow.  On stock NetBSD, OpenBSD,
and Solaris systems, this is probably 16.  On Linux 2.2, this is 32.  This
module tries to guess the number based on your operating system, but it is
safer to configure it yourself.

   To set the number of semaphores, you need to pass an argument in the
usual Apache::Session style.  The name of the argument is NSems, and the
value is an integer power of 2.  For example:

     tie %s, 'Apache::Session::Blah', $id, {NSems => 16};

   You may also need to configure the semaphore key that this package
uses.  By default, it uses key 31818.  You can change this using the
argument SemaphoreKey:

     tie %s, 'Apache::Session::Blah', $id, {NSems => 16, SemaphoreKey => 42};

PROBLEMS
========

   There are a few problems that people frequently encounter when using
this package.

   If you get an invalid argument message, that usually means that the
system is unhappy with the number of semaphores that you requested.  Try
decreasing the number of semaphores.  The semaphore blocks that this
package creates are persistent until the system is rebooted, so if you
request 8 sempahores one time and 16 sempahores the next, it won't work.
Use the system commands ipcs and ipcrm to inspect and remove unwanted
semphore blocks.

AUTHOR
======

   This module was written by Jeffrey William Baker <jwbaker@acm.org>.

SEE ALSO
========

   See Apache/Session,

An implementation of Apache::Session
************************************

NAME
====

   Apache::Session::MySQL - An implementation of Apache::Session

SYNOPSIS
========

     use Apache::Session::MySQL;

     #if you want Apache::Session to open new DB handles:

     tie %hash, 'Apache::Session::MySQL', $id, {
        DataSource => 'dbi:mysql:sessions',
        UserName   => $db_user,
        Password   => $db_pass,
        LockDataSource => 'dbi:mysql:sessions',
        LockUserName   => $db_user,
        LockPassword   => $db_pass
     };

     #or, if your handles are already opened:

     tie %hash, 'Apache::Session::MySQL', $id, {
        Handle     => $dbh,
        LockHandle => $dbh
     };

DESCRIPTION
===========

   This module is an implementation of Apache::Session.  It uses the MySQL
backing store and the MySQL locking scheme.  See the example, and the
documentation for Apache::Session::Store::MySQL and
Apache::Session::Lock::MySQL for more details.

AUTHOR
======

   This module was written by Jeffrey William Baker <jwbaker@acm.org>.

SEE ALSO
========

   See Apache/Session/File,
Apache/Session/Flex, Apache/Session/DB_File,
see Apache/Session/Postgres,
see Apache/Session,

An implementation of Apache::Session
************************************

NAME
====

   Apache::Session::Oracle - An implementation of Apache::Session

SYNOPSIS
========

     use Apache::Session::Oracle;

     #if you want Apache::Session to open new DB handles:

     tie %hash, 'Apache::Session::Oracle', $id, {
        DataSource => 'dbi:Oracle:sessions',
        UserName   => $db_user,
        Password   => $db_pass,
        Commit     => 1
     };

     #or, if your handles are already opened:

     tie %hash, 'Apache::Session::Oracle', $id, {
        Handle => $dbh,
        Commit => 1
     };

DESCRIPTION
===========

   This module is an implementation of Apache::Session.  It uses the Oracle
backing store and no locking.  See the example, and the documentation for
Apache::Session::Store::Oracle for more details.

USAGE
=====

   The special Apache::Session argument for this module is Commit.  You
MUST provide the Commit argument, which instructs this module to either
commit the transaction when it is finished, or to simply do nothing.  This
feature is provided so that this module will not have adverse interactions
with your local transaction policy, nor your local database handle caching
policy.  The argument is mandatory in order to make you think about this
problem.

   This module also respects the LongReadLen argument, which specifies the
maximum size of the session object.  If not specified, the default maximum
is 8 KB.

AUTHOR
======

   This module was written by Jeffrey William Baker <jwbaker@acm.org>.

SEE ALSO
========

   See Apache/Session/File,
Apache/Session/Flex, Apache/Session/DB_File,
see Apache/Session/Postgres,
see Apache/Session,

An implementation of Apache::Session
************************************

NAME
====

   Apache::Session::Postgres - An implementation of Apache::Session

SYNOPSIS
========

     use Apache::Session::Postgres;

     #if you want Apache::Session to open new DB handles:

     tie %hash, 'Apache::Session::Postgres', $id, {
        DataSource => 'dbi:Pg:dbname=sessions',
        UserName   => $db_user,
        Password   => $db_pass,
        Commit     => 1
     };

     #or, if your handles are already opened:

     tie %hash, 'Apache::Session::Postgres', $id, {
        Handle => $dbh,
        Commit => 1
     };

DESCRIPTION
===========

   This module is an implementation of Apache::Session.  It uses the
Postgres backing store and no locking.  See the example, and the
documentation for Apache::Session::Store::Postgres for more details.

USAGE
=====

   The special Apache::Session argument for this module is Commit.  You
MUST provide the Commit argument, which instructs this module to either
commit the transaction when it is finished, or to simply do nothing.  This
feature is provided so that this module will not have adverse interactions
with your local transaction policy, nor your local database handle caching
policy.  The argument is mandatory in order to make you think about this
problem.

AUTHOR
======

   This module was written by Jeffrey William Baker <jwbaker@acm.org>.

SEE ALSO
========

   See Apache/Session/File,
Apache/Session/Flex, Apache/Session/DB_File,
see Apache/Session/Postgres,
see Apache/Session,

Use Storable and MIME::Base64 to zip up persistent data
*******************************************************

NAME
====

   Apache::Session::Serialize::Base64 - Use Storable and MIME::Base64 to
zip up persistent data

SYNOPSIS
========

     use Apache::Session::Serialize::Base64;

     $zipped = Apache::Session::Serialize::Base64::serialize($ref);
     $ref = Apache::Session::Serialize::Base64::unserialize($zipped);

DESCRIPTION
===========

   This module fulfills the serialization interface of Apache::Session.
It serializes the data in the session object by use of Storable's
`nfreeze()' and `thaw()' functions, and MIME::Base64's `encode_bas64' and
`decode_base64'.  The serialized data is ASCII text, suitable for storage
in backing stores that don't handle binary data gracefully, such as
Postgres.

AUTHOR
======

   This module was written by Jeffrey William Baker <jwbaker@acm.org>.

SEE ALSO
========

   See Apache/Session/Serialize/Storable,
see Apache/Session,

Use Storable to zip up persistent data
**************************************

NAME
====

   Apache::Session::Serialize::Storable - Use Storable to zip up
persistent data

SYNOPSIS
========

     use Apache::Session::Serialize::Storable;

     $zipped = Apache::Session::Serialize::Storable::serialize($ref);
     $ref = Apache::Session::Serialize::Storable::unserialize($zipped);

DESCRIPTION
===========

   This module fulfills the serialization interface of Apache::Session.
It serializes the data in the session object by use of Storable's
`nfreeze()' and `thaw()' functions.  The result is a binary object ready
for storage.

AUTHOR
======

   This module was written by Jeffrey William Baker <jwbaker@acm.org>.

SEE ALSO
========

   See Apache/Session/Serialize/Base64,
see Apache/Session,

Use Storable to zip up persistent data and unpack/pack to put into Sybase-compatible image field
************************************************************************************************

NAME
====

   Apache::Session::Serialize::Sybase - Use Storable to zip up persistent
data and unpack/pack to put into Sybase-compatible image field

SYNOPSIS
========

     use Apache::Session::Serialize::Sybase;

     $zipped = Apache::Session::Serialize::Sybase::serialize($ref);
     $ref = Apache::Session::Serialize::Sybase::unserialize($zipped);

DESCRIPTION
===========

   This module fulfills the serialization interface of Apache::Session by
taking the data from Apache::Session::Serialize::Storable and modifying it
to work with Sybase IMAGE fields. Note that you do not need to quote these
values before inserting into the database, and that if you are using
DBI::Sybase, you cannot use the data in a placeholder. If you use
Apache::Session::Sybase as your session class, this will all get taken
care of.

AUTHOR
======

   Apache::Session::Serialize::Storable was written by Jeffrey William
Baker <jwbaker@acm.org>; the Sybase-specific data manipulation was written
by Mark Landry <mdlandry@lincoln.midcoast.com> for use in an earlier
version of Apache::Session::DBI::Sybase and placed here by Chris Winters
<chris@cwinters.com>.

SEE ALSO
========

   See Apache/Session/Serialize/Storable,
see Apache/Session/Sybase,

Use Storable and pack() to zip up persistent data
*************************************************

NAME
====

   Apache::Session::Serialize::UUEncode - Use Storable and pack() to zip
up persistent data

SYNOPSIS
========

     use Apache::Session::Serialize::UUEncode;

     $zipped = Apache::Session::Serialize::UUEncode::serialize($ref);
     $ref = Apache::Session::Serialize::UUEncode::unserialize($zipped);

DESCRIPTION
===========

   This module fulfills the serialization interface of Apache::Session. It
serializes the data in the session object by use of Storable's `nfreeze()'
and `thaw()' functions, and Perl's pack() and `unpack()'.  The serialized
data is ASCII text, suitable for storage in backing stores that don't
handle binary data gracefully, such as Postgres.

AUTHOR
======

   This module was written by Jeffrey William Baker <jwbaker@acm.org>.

SEE ALSO
========

   See Apache/Session/Serialize/Storable,
see Apache/Session/Serialize/Base64,
see Apache/Session,

Use DB_File to store persistent objects
***************************************

NAME
====

   Apache::Session::Store::DB_File - Use DB_File to store persistent
objects

SYNOPSIS
========

     use Apache::Session::Store::DB_File;

     my $store = new Apache::Session::Store::DB_File;

     $store->insert($ref);
     $store->update($ref);
     $store->materialize($ref);
     $store->remove($ref);

DESCRIPTION
===========

   This module fulfills the storage interface of Apache::Session.  The
serialized objects are stored in a Berkeley DB file using the DB_File Perl
module.  If DB_File works on your platform, this module should also work.

OPTIONS
=======

   This module requires one argument in the usual Apache::Session style.
The name of the option is FileName, and the value is the full path of the
database file to be used as the backing store.  If the database file does
not exist, it will be created.  Example:

     tie %s, 'Apache::Session::DB_File', undef,
        {FileName => '/tmp/sessions'};

AUTHOR
======

   This module was written by Jeffrey William Baker <jwbaker@acm.org>.

SEE ALSO
========

   See Apache/Session, DB_File,

Store persistent data on the filesystem
***************************************

NAME
====

   Apache::Session::Store::File - Store persistent data on the filesystem

SYNOPSIS
========

     use Apache::Session::Store::File;

     my $store = new Apache::Session::Store::File;

     $store->insert($ref);
     $store->update($ref);
     $store->materialize($ref);
     $store->remove($ref);

DESCRIPTION
===========

   This module fulfills the storage interface of Apache::Session.  The
serialized objects are stored in files on your filesystem.

OPTIONS
=======

   This module requires one argument in the usual Apache::Session style.
The name of the option is Directory, and the value is the full path of the
directory where you wish to place the files.  Example

     tie %s, 'Apache::Session::File', undef,
        {Directory => '/tmp/sessions'};

NOTES
=====

   All session objects are stored in the same directory.  Some
filesystems, such as Linux's ext2fs, have O(n) performance where n is the
number of files in a directory.  Other filesystems, like Sun's UFS, and
Linux's reiserfs, do not have this problem.  You should consider your
filesystem's performance before using this module to store many objects.

AUTHOR
======

   This module was written by Jeffrey William Baker <jwbaker@acm.org>.

SEE ALSO
========

   See Apache/Session,

Store persistent data in a MySQL database
*****************************************

NAME
====

   Apache::Session::Store::MySQL - Store persistent data in a MySQL
database

SYNOPSIS
========

     use Apache::Session::Store::MySQL;

     my $store = new Apache::Session::Store::MySQL;

     $store->insert($ref);
     $store->update($ref);
     $store->materialize($ref);
     $store->remove($ref);

DESCRIPTION
===========

   Apache::Session::Store::MySQL fulfills the storage interface of
Apache::Session.  Session data is stored in a MySQL database.

SCHEMA
======

   To use this module, you will need at least these columns in a table
called 'sessions':

     id char(32)     # or however long your session IDs are.
     a_session text

   To create this schema, you can execute this command using the mysql
program:

     CREATE TABLE sessions (
        id char(32) not null primary key,
        a_session text
     );

   If you use some other command, ensure that there is a unique index on
the table's id column.

CONFIGURATION
=============

   The module must know what datasource, username, and password to use when
connecting to the database.  These values can be set using the options hash
(see Apache::Session documentation).  The options are:

DataSource
UserName
Password
   Example:

     tie %hash, 'Apache::Session::MySQL', $id, {
         DataSource => 'dbi:mysql:database',
         UserName   => 'database_user',
         Password   => 'K00l'
     };

   Instead, you may pass in an already-opened DBI handle to your database.

     tie %hash, 'Apache::Session::MySQL', $id, {
         Handle => $dbh
     };

AUTHOR
======

   This modules was written by Jeffrey William Baker <jwbaker@acm.org>

SEE ALSO
========

   See Apache/Session,

Store persistent data in a Oracle database
******************************************

NAME
====

   Apache::Session::Store::Oracle - Store persistent data in a Oracle
database

SYNOPSIS
========

     use Apache::Session::Store::Oracle;

     my $store = new Apache::Session::Store::Oracle;

     $store->insert($ref);
     $store->update($ref);
     $store->materialize($ref);
     $store->remove($ref);

DESCRIPTION
===========

   Apache::Session::Store::Oracle fulfills the storage interface of
Apache::Session. Session data is stored in a Oracle database.

SCHEMA
======

   To use this module, you will need at least these columns in a table
called 'sessions':

     id varchar2(32)     # or however long your session IDs are.
     a_session long

   To create this schema, you can execute this command using the sqlplus
program:

     CREATE TABLE sessions (
        id varchar2(32) not null primary key,
        a_session long
     );

   If you use some other command, ensure that there is a unique index on
the table's id column.

CONFIGURATION
=============

   The module must know what datasource, username, and password to use when
connecting to the database.  These values can be set using the options hash
(see Apache::Session documentation).  The options are DataSource, UserName,
and Password.

   Example:

     tie %hash, 'Apache::Session::Oracle', $id, {
         DataSource => 'dbi:Oracle:database',
         UserName   => 'database_user',
         Password   => 'K00l'
     };

   Instead, you may pass in an already-opened DBI handle to your database.

     tie %hash, 'Apache::Session::Oracle', $id, {
         Handle => $dbh
     };

   The last option is LongReadLen, which specifies the maximum size of the
session object.  If not supplied, the default maximum size is 8 KB.

AUTHOR
======

   This modules was written by Jeffrey William Baker <jwbaker@acm.org>

   A fix for the commit policy was contributed by Michael Schout
<mschout@gkg.net>

SEE ALSO
========

   See Apache/Session, `Apache::Session::Store::DBI' in
this node

Store persistent data in a Postgres database
********************************************

NAME
====

   Apache::Session::Store::Postgres - Store persistent data in a Postgres
database

SYNOPSIS
========

     use Apache::Session::Store::Postgres;

     my $store = new Apache::Session::Store::Postgres;

     $store->insert($ref);
     $store->update($ref);
     $store->materialize($ref);
     $store->remove($ref);

DESCRIPTION
===========

   Apache::Session::Store::Postgres fulfills the storage interface of
Apache::Session. Session data is stored in a Postgres database.

SCHEMA
======

   To use this module, you will need at least these columns in a table
called 'sessions':

     id char(32)     # or however long your session IDs are.
     a_session text  # This has an ~8 KB limit :(

   To create this schema, you can execute this command using the psql
program:

     CREATE TABLE sessions (
        id char(32) not null primary key,
        a_session text
     );

   If you use some other command, ensure that there is a unique index on
the table's id column.

CONFIGURATION
=============

   The module must know what datasource, username, and password to use when
connecting to the database.  These values can be set using the options hash
(see Apache::Session documentation).  The options are:

DataSource
UserName
Password
   Example:

     tie %hash, 'Apache::Session::Postgres', $id, {
         DataSource => 'dbi:Pg:dbname=database',
         UserName   => 'database_user',
         Password   => 'K00l'
     };

   Instead, you may pass in an already-opened DBI handle to your database.

     tie %hash, 'Apache::Session::Postgres', $id, {
         Handle => $dbh
     };

AUTHOR
======

   This modules was written by Jeffrey William Baker <jwbaker@acm.org>

   A fix for the commit policy was contributed by Michael Schout
<mschout@gkg.net>

SEE ALSO
========

   See Apache/Session, `Apache::Session::Store::DBI' in
this node

Store persistent data in a Sybase database
******************************************

NAME
====

   Apache::Session::Store::Sybase - Store persistent data in a Sybase
database

SYNOPSIS
========

     use Apache::Session::Store::Sybase;

     my $store = new Apache::Session::Store::MySQL;

     $store->insert( $ref );
     $store->update( $ref );
     $store->materialize( $ref );
     $store->remove( $ref );

DESCRIPTION
===========

   Apache::Session::Store::Sybase fulfills the storage interface of
Apache::Session.  Session data is stored in a Sybase database.

SCHEMA
======

   To use this module, you will need at least these columns in a table
called 'sessions':

     id        CHAR(32)     # or however long your session IDs are.
     a_session IMAGE

   To create this schema, you can execute this command using the isql or
sqsh programs:

     CREATE TABLE sessions (
        id         CHAR(32) not null primary key,
        a_session  IMAGE
     )
     go

   If you use some other command, ensure that there is a unique index on
the id column of the table

CONFIGURATION
=============

   The module must know what datasource, username, and password to use when
connecting to the database.  These values can be set using the options hash
(see Apache::Session documentation).  The options are:

DataSource
UserName
Password
   Example:

     tie %hash, 'Apache::Session::Sybase', $id, {
         DataSource => 'dbi:Sybase:database=db;server=server',
         UserName   => 'database_user',
         Password   => 'K00l',
         Commit     => 1,
     };

   Instead, you may pass in an already-opened DBI handle to your database.

     tie %hash, 'Apache::Session::Sybase', $id, {
         Handle => $dbh
     };

   Additional arguments you can pass to the backing store are:

Commit - whether we should commit any changes; if you pass in an already-open database handle that has AutoCommit set to a true value, you do not need to set this. If you let Apache::Session::Store::Sybase create your database, handle, you must set this to a true value, otherwise, your changes will not be saved
textsize - the value we should pass to the 'set textsize ' command that sets the max size of the IMAGE field. Default is 32K (at least in Sybase ASE 11.9.2).
AUTHOR
======

   This module was based on Apache/Session/Store/Oracle,
which was written by Jeffrey William Baker
<jwbaker@acm.org>; it was modified by Chris Winters <chris@cwinters.com>
to work with Apache::Session 1.5+ with changes from earlier version of
Apache::Session::DBI::Sybase from Mark Landry
<mdlandry@lincoln.midcoast.com>.

SEE ALSO
========

   See Apache/Session,

An implementation of Apache::Session
************************************

NAME
====

   Apache::Session::Sybase - An implementation of Apache::Session

SYNOPSIS
========

     use Apache::Session::Sybase;

     # if you want Apache::Session to open new DB handles:

     tie %hash, 'Apache::Session::Sybase', $id, {
        DataSource => 'dbi:Sybase:database=sessions;server=SYBASE',
        UserName   => $db_user,
        Password   => $db_pass,
        Commit     => 1,
     };

     # or, if your handle is already opened:

     tie %hash, 'Apache::Session::Sybase', $id, {
        Handle     => $dbh,
        Commit     => 0,
     };

DESCRIPTION
===========

   This module is an implementation of Apache::Session.  It uses the
Sybase backing store and the Null locking scheme.  See the example, and
the documentation for Apache::Session::Store::Sybase (also for the
parameters that get passed to the backing store along with the schema
necessary to save the sessions) and Apache::Session::Lock::Null for more
details.

AUTHOR
======

   This module was based on Apache/Session/MySQL,
which was written by Jeffrey William Baker
<jwbaker@acm.org>; it was modified by Chris Winters <chris@cwinters.com>.

SEE ALSO
========

   See Apache/Session,

Store client sessions in a global hash
**************************************

NAME
====

   Apache::Session::Win32 - Store client sessions in a global hash

SYNOPSIS
========

   use Apache::Session::Win32

DESCRIPTION
===========

   This is a Win32 storage subclass for Apache::Session.  Client state is
stored in a global hash.  Since Win32 Apache is multithreaded instead of
multiprocess, this actually works and is extremely quick.  Try `perldoc
Session' for more info.

INSTALLATION
============

   Follow the installation instructions from Apache::Session.

Environment
-----------

   Apache::Session::Win32 does not define any environment variables beyond
those defined by Apache::Session.

USAGE
=====

   This package complies with the API defined by Apache::Session.  For
details, please see that package's documentation.

   This package installs an entry on the Apache::Status menu which will
let you monitor sessions in real-time.

AUTHORS
=======

   Jeffrey Baker <jeff@godzilla.tamu.edu>, author and maintainer.

   Redistribute under the Perl Artistic License.

Standard theme generation, including sidebars and navigation bars
*****************************************************************

NAME
====

   Apache::SetWWWTheme - Standard theme generation, including sidebars and
navigation bars

SYNOPSIS
========

   Within the httpd.conf or other apache configuration file:

   <Location /some/subtree>  SetHandler perl-script  PerlHandler
Apache::SetWWWTheme  PerlSetVar CONFIG_FILE /WWWroot/configfile
</Location>

REQUIREMENTS
============

   This module requires the Apache server, available from
http://www.apache.org; the Apache mod_perl module, which is available from
http://perl.apache.org, and the *module HTML::WWWTheme*, by Chad Hogan
(version 1.06 or greater) which may be found at CPAN.

DESCRIPTION
===========

   The SetWWWTheme module provides a server-based look-and-feel
configuration for an entire webtree. This module allows the server to
introduce a common navigation side-bar. It also provides mechanisms to
control the background color and background picture for a web page.

   This is implemented in a layered fashion. The module first reads the
server directives. This sets defaults, and decides what users may have
control over. Server directives may only be set by the webmasters.
Following these, the module reads local directives. These directives are
specified in a file, and will affect all files in that same directory, as
well as subdirectories underneath it. They are set at the user-level, and
so they are subject to the constraints imposed by the server directives.
Finally, the module parses the individual HTML files. Within a file, an
HTML authour may override the settings given in the local directives.
Again, these are subject to the constraints of the server directives.

   Please note that you are not required to change anything in your pages.
Your unmodified HTML will work just fine with this module. You are
required to make changes only if you wish to take advantage of the
features offered.

Server-level configuration
     At the server level, the webmaster has full access to all directives.
     These tags are specified in a file that is set in the httpd.conf
     file. If a webmaster would like his/her subtree to use the module, a
     <LOCATION> tag is used to activate the module. A PerlSetVar is used
     to tell the module the name of the configuration file. Here is an
     example:

          <Location />
          SetHandler perl-script
          PerlHandler Apache::SetWWWTheme
          PerlSetVar CONFIG_FILE /WWW/ServerConfig
          </Location>

     This example will use the module for the entire document tree. The
     CONFIG_FILE variable is used by the module to look for the file that
     controls the defaults for the entire site. Please note that
     CONFIG_FILE takes the full path to the file name on the file-system -
     do not list this file relative to the document root.

     The creation of printable versions of pages has been greatly
     simplified.  No longer is any configuration required - the page is
     automatically generated using a GET method.  Adding "?printable" to a
     URI will cause the page to be displayed in a printable manner, for
     example.

     The server-level configuration is primarily to set defaults. It is
     also to set restrictions on the configurability of the rest of the
     site. The server-level configuration decides whether or not
     individual authours will be permitted to, for example, change the
     background colour and background image of their web pages.

     Once again, the server configuration may make use of all of the
     following directives. The server then decides which of these the
     users may override.

     Local configuration

     Any authour may create a text file containing directives. The name of
     this file is set by the server directive @LOCALCONFIGFILE, with a
     default of LookAndFeelConfig. This file will affect all HTML files
     within that directory, as well as any subdirectories.  These
     directives are subject to the restrictions placed by the server-level
     configuration. This file is intended to be used to set common
     settings for a tree. For example, one may wish to set the background
     colour for an entire tree to white. Then a @BGCOLOR=#FFFFFF;
     directive in the local config file.  file will set this. Directives
     that are explicitly set override the server settings (if allowed).
     Otherwise, the server's settings persist.

     Individual file configuration

     This is the final level of configuration. Any authour may embed
     directives within a comment tag in an HTML file, as long as this tag
     appears before the <BODY> tag. Directives that are explicitly set
     override the local configuration and/or server settings (if allowed).
     Otherwise, the local settings and the server settings persist.

Module directives
     Directives consist of a series of tags within a text file, or within
     an html comment block before the <BODY> tag. Valid directive tags are
     always terminated with a semicolon. For tags that accept lists as
     values, elements are separated by commas.  Semicolons may be escaped
     within a tag.  Any semicolon preceded by a backslash will be
     considered text, and will not terminate the directive.  The final
     text will have the escaped semicolon replaced with a bare semicolon.

          @DIRECTIVE=Some string of text\; semicolons are escaped.;

     The above directive would set a value of "Some string of text;
     semicolons are escaped."

@ALINK
     HTML and local configuration subject to server configuration This tag
     is used to set the HTML BODY setting "alink". This is the active link
     color. It is subject to the setting of the @ALLOWBODYMOD tag. If
     @ALLOWBODYMOD is set to a non-zero value, @ALINK will set this
     attribute in the page. Here is an example:

          @ALINK=#FF00FF;

@ALLOWBODYMOD
     Server configuration only This tag is used to allow or disallow users
     from changing BODY elements. These include "alink", "vlink", "link",
     "text", "bgcolor", and "background" items using the directives
     @ALINK, @VLINK, @LINK,  @TEXT, @BGCOLOR and @BGPICTURE respectively.
     If it is set to a non-zero value, the user's directives will be read
     and used. Otherwise, user settings will be ignored, and only the
     server configuration values will be used in creating the <BODY> tag
     for the page. Here is an example:

          @ALLOWBODYMOD=1;

@ALLOWBGCOLOR `Deprecated' in this node
     Server configuration only This tag is used to allow or disallow users
     from changing the background colours of their pages. By default it is
     set to 0, meaning that users are not allowed to change their
     background colours. If it is not set to a non-zero value, only the
     server's @BGCOLOR directives will be used. This directive is
     deprecated. Administrators should use  @ALLOWBODYMOD instead. Here is
     an example:

          @ALLOWBGCOLOR=0;

@ALLOWBGPICTURE `Deprecated' in this node
     Server configuration only This tag is used to allow or disallow users
     from changing the background picture of their pages. By default it is
     set to 0, meaning that users are not allowed to change their
     background colours. If it is not set to a non-zero value, only the
     server's @BGPICTURE directives will be used. This directive is
     deprecated. Administrators should use  @ALLOWBODYMOD instead Here is
     an example:

          @ALLOWBGPICTURE=0;

@ALLOWNOSIDEBAR `Deprecated' in this node
     Server configuration only. *Use @ALLOWSIDEBARTOGGLE instead*.  This
     tag is used to allow or disallow users from turning on/off the left
     sidebar.  By default, it is set to 0, meaning that users are not
     allowed to toggle the sidebar.  If is not set to a true value (1 is
     recommended), only the server's @NOSIDEBAR directives will be used.
     Here is an example:

          @ALLOWNOSIDEBAR=0;

@ALLOWSIDEBARTOGGLE
     Server configuration only This tag is used to allow or disallow users
     from turning on/off the left sidebar. By default it is set to 0,
     meaning that users are not allowed to toggle the sidebar. If it is
     not set to a true value (1 is recommended), only the server's
     @NOSIDEBAR directives will be used. Here is an example:

          @ALLOWSIDEBARTOGGLE=0;

          =item @ALLOWSIDEBARMOD

     Server configuration only This tag is set to allow users to modify the
     characteristics of the sidebar. If this flag is set to anything
     non-zero, users may change the title at the top of the sidebar with
     the @SIDEBARTOP directive, the menu title above the menulinks with
     @SIDEBARMENUTITLE, the menu links with the @SIDEBARMENULINKS.  Users
     are also allowed to change the title of the "More links" section to
     something else.  They may also then switch the sidebar search box on
     or off with @SIDEBARSEARCHBOX. Here is an example:

          @ALLOWSIDEBARMOD=0;

@BGCOLOR
     HTML and local configuration subject to server configuration This tag
     may be used to set the background colour of a page (or a group of
     pages, in the case of local and server configuration). @BGCOLOR is
     subject to the server directive @ALLOWBGCOLOR. If @ALLOWBGCOLOR is not
     set to a non-zero value by server directives, the @BGCOLOR directive
     will have no effect whatsoever when used in local and HTML
     configuration. @BGCOLOR will always work when used in a server
     configuration. Here is an example:

     @BGCOLOR=#FFFFCC;

@BGPICTURE
     HTML and local configuration subject to server configuration This tag
     may be used to set the background image of a page (or a group of
     pages, in the case of a local and server configuration. @BGPICTURE is
     subject to the server directive @ALLOWBGPICTURE. If @ALLOWBGPICTURE
     is not set to a non-zero value by server directives, the @BGPICTURE
     directive will have no effect whatsoever when used in local and HTML
     configuration. @BGPICTURE will always work when used in a server
     configuration. Here is an example:

          @BGPICTURE=/images/paperbackground.gif;

@BLANKGIF
     Server configuration only This tag is used to specify the location of
     the blank.gif image file.  This image is a 1x1 transparent gif that
     is used to space the tables properly. This should be set to the path
     of the image file with respect to the server's document root. So, if
     the apache document root is /WWW and the file is
     /WWW/images/blank.gif then the proper use of this tag would be:

          @BLANKGIF=/images/blank.gif;

@BOTTOMBAR
     Valid in HTML, local configuration, and server configuration.  This
     tag is used to toggle a navigation bar at the bottom of the page.
     This bottom navigation bar contains the links defined with the
     @TOPBOTTOMLINKS directive.  If @BOTTOMBAR is set to something
     non-zero, it will appear in the document.

          @BOTTOMBAR=1;

@INFO
     Valid in HTML, local configuration, and server configuration This tag
     is used to customize the "More links" section in the left sidebar. To
     use this tag, supply a comma-separated list of valid HTML links
     terminated with a semi-colon. The links supplied will appear in the
     "More Links" section. Here is an example:

          @INFO=<A HREF="http://www.sun.com">Sun</a>,
          <A HREF="http://www.slashdot.org">Slashdot</a>;

@LINK
     Valid in HTML, local configuration, and server configuration This tag
     is used to set the HTML BODY setting "link". This is the normal link
     color. It is subject to the setting of the @ALLOWBODYMOD tag. If
     @ALLOWBODYMOD is set to a non-zero value, @LINK will set this
     attribute in the page. Here is an example:

          @LINK=#FFFFFF;

@LOCALCONFIGFILE
     Valid only in server configuration.  This directive tells the module
     what file to look for when it looks for local configuration files.
     The default is LookAndFeelConfig.  It may be set to any valid
     filename.

          @LOCALCONFIGFILE=LOOKANDFEEL;

@MORELINKSTITLE
     Valid in HTML, local configuration, and server configuration, subject
     to the server's configuration (@ALLOWSIDEBARMOD must be on in the
     server's configuration in order for local and HTML directives to be
     obeyed).

@NAVBAR
     Valid in HTML, local configuration, and server configuration This tag
     gives the switch setting for the top and bottom navigation bars. The
     top and bottom navigation bars are also known as the
     "previous/up/next" bars. If this is set to 0, the top and bottom bars
     are not shown. If this is set to a non-zero value (1 is recommended)
     then the bars will be shown. If this switch is non-zero, it is
     recommended that the @NEXTLINK, @UPLINK, and @LASTLINK directives be
     set. Here is an example:

          @NAVBAR=0;

@NEXTLINK, @LASTLINK, @UPLINK
     Valid in HTML, local configuration, and server configuration These
     tags control the behaviour of the top navigation bar. These tags
     should be set in conjunction with the @NAVBAR directive. They should
     contain valid text and linking information. Here is an example:

          @NEXTLINK=<A HREF="/pages/page3.html">Page 3</a>;
          @UPLINK=<A HREF="/pages/toc.html">Table of contents</a>;
          @LASTLINK=<A HREF="/pages/page1.html">Page 1</a>;

@NOSIDEBAR
     HTML and local configuration subject to server configuration This tag
     may be used to turn off the left sidebar by setting it to a non-zero
     value. This tag is subject to the server directive  @ALLOWNOSIDEBAR.
     If the server configuration has not set the  @ALLOWNOSIDEBAR to a
     non-zero value, the @NOSIDEBAR directive will have no effect
     whatsoever. Here is an example:

          @NOSIDEBAR=1;

@SIDEBARCOLOR
     HTML and local configuration subject to server configuration This tag
     is used to set the color of the sidebar. Local and HTML configuration
     is subject to the server directive @ALLOWSIDEBARMOD. Here is an
     example:

          @SIDEBARCOLOR=#CCCCCC;

@SIDEBARWIDTH
     HTML and local configuration subject to server configuration.  This
     tag is used to set the width of the sidebar in pixels.  Local and
     HTML configuration is subject to the server directive
     @ALLOWSIDEBARMOD.

          @SIDEBARWIDTH=150;

@SEARCHTEMPLATE
     HTML and local configuration subject to server configuration This tag
     is used to set the searchbox template.  It should be a fully-contained
     HTML chunk that interfaces to the apropriate cgi binary (or whatever
     you want).

          @SEARCHTEMPLATE=
          <B>Search JAC</B><BR><HR>
          <DIV align="center">
          <form method="POST" action="/cgi-bin/isearch">
          <input name="SEARCH_TYPE" type=hidden  value="ADVANCED">
          <input name="HTTP_PATH" type=hidden value="/WWW">
          <input name="DATABASE" type=hidden value="webindex">
          <input name="FIELD_1" type=hidden value="FULLTEXT">
          <input name="WEIGHT_1" type=hidden value= "1">
          <input name="ELEMENT_SET" type=hidden value="TITLE">
          <input name="MAXHITS" type=hidden value="50">
          <input name="ISEARCH_TERM" size="14" border="0">
          </form>
          </DIV>
          <H6><a href="http://www.yoursite.edu/search.html">More searching....</a></h6>;

     Don't forget to terminate the template with a semicolon!

@SIDEBARMENULINKS
     HTML and local configuration subject to server configuration This tag
     is used to set the main menulinks. It is effective in local and HTML
     configuration if and only if the server configuration has set
     @ALLOWSIDEBARMOD. It takes a comma-separated list of links, terminated
     by a semicolon. Here is an example:

          @SIDEBARMENULINKS=<A HREF="/WWW/stuff">Some Directory</A>,
          <A HREF="/WWW/morestuff">Another Directory</A>;

@SIDEBARMENUTITLE
     HTML and local configuration subject to server configuration This tag
     is used to set the title above the menulinks. It is effective in
     local and HTML configuration if and only if the server configuration
     has set @ALLOWSIDEBARMOD to a non-zero value. Here is an example of
     its use:

          @SIDEBARMENUTITLE=My Divisions;

@SIDEBARSEARCHBOX
     HTML and local configuration subject to server configuration This tag
     is a switch that determines whether or not the sidebar will contain
     the search box. If it is set to a non-zero value, the search box will
     appear on the sidebar. It is effective in local and HTML
     configuration if and only if the server configuration has set
     @ALLOWSIDEBARMOD to a non-zero value. Here is an example of its use:

          @SIDEBARSEARCHBOX=0;

@SIDEBARTOP
     HTML and local configuration subject to server configuration This tag
     is used to set the title at the top of the sidebar. It is effective
     in local and HTML configuration if and only if the server
     configuration has set @ALLOWSIDEBARMOD to a non-zero value. Here is an
     example of its use:

          @SIDEBARTOP=<A HREF="/">Joint Astronomy Centre</a>;

@TEXT
     HTML and local configuration subject to server configuration This tag
     is used to set the HTML BODY setting "text". This is the normal text
     color. It is subject to the setting of the @ALLOWBODYMOD tag. If
     @ALLOWBODYMOD is set to a non-zero value, @TEXT will set this
     attribute in the page. Here is an example:

          @TEXT=#000000;

@TOPBAR
     This tag is valid in HTML, local, and server configuration.  It is
     used to toggle the existence of a top navigation bar that contains
     the links specified in the @TOPBOTTOMLINKS directive.  It is similar
     to the @BOTTOMBAR directive, except it works at the top of the page.
     Setting @TOPBAR to a non-zero value will turn this navigation tool on
     in the final produced document.

          @TOPBAR=1;

@TOPBOTTOMLINKS
     This is valid in HTML, local, and server configuration.  It is a
     comma-separated list of navigation links that will be place in the
     top and bottom bars as toggled by the @TOPBAR and @BOTTOMBAR
     directives.

          @TOPBOTTOMLINKS=<A HREF="/">JAC</a>, <A HREF="/JCMT">JCMT</a>;

@VLINK
     This tag is used to set the HTML BODY setting "vlink". This is the
     visited-link color. It is subject to the setting of the @ALLOWBODYMOD
     tag. If @ALLOWBODYMOD is set to a non-zero value, @VLINK will set this
     attribute in the page. Here is an example:

          @VLINK=#FF00FF;

SEE ALSO
========

   See HTML/WWWTheme,

AUTHOR
======

   Copyright (C) 2000 Chad Hogan (chogan@uvastro.phys.uvic.ca).  Copyright
(C) 2000 Joint Astronomy Centre

   All rights reserved.  Apache::SetWWWTheme 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.

   Apache::SetWWWTheme 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 Apache::SetWWWTheme; see the file gpl.txt.  If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.

Show phases and module participation
************************************

NAME
====

   Apache::ShowRequest - Show phases and module participation

SYNOPSIS
========

     <Location /show>
      SetHandler perl-script
      PerlHandler Apache::ShowRequest
     </Location>

DESCRIPTION
===========

   This module will run a request using the given PATH_INFO as the uri.
Each request phase will be run in order, along with each module handler.
The module response code will be printed or undef if the module does not
participate in the given phase.  Apache::ShowRequest stops running module
handlers for the given phase just as Apache would.  For example, if any
returns a code other than OK or *DECLINED*.  Or, phases which only allow
one module to return OK, e.g. URI translate.  The content response phase
is not run, but possible modules are listed as defined.

AUTHOR
======

   Doug MacEachern

SEE ALSO
========

   Apache::Module(3), Apache(3), mod_perl(3)

a simple template framework
***************************

NAME
====

   Apache::SimpleReplace - a simple template framework

SYNOPSIS
========

   httpd.conf:

     <Location /someplace>
        SetHandler perl-script
        PerlHandler Apache::SimpleReplace

     PerlSetVar  TEMPLATE "/templates/format1.html"
     PerlSetVar  REPLACE "the content goes here"
      </Location>

   Apache::SimpleReplace is Filter aware, meaning that it can be used
within an Apache::Filter framework without modification.  Just include the
directive

   PerlSetVar Filter On

   and modify the PerlHandler directive accordingly.  As of version 0.06,
Apache::SimpleReplace requires Apache::Filter 1.013 or better - users of
Apache::Filter 1.011 or less should use version 0.05.

DESCRIPTION
===========

   Apache::SimpleReplace provides a simple way to insert content within an
established template for uniform content delivery.  While the end result
is similar to Apache::Sandwich, Apache::SimpleReplace offers several
advantages.

     o It does not use separate header and footer files, easing the
       pain of maintaining syntactically correct HTML in seperate files.

     o It is Apache::Filter aware, thus it can both accept content from
       other content handlers as well as pass its changes on to others
       later in the chain.

EXAMPLE
=======

   /usr/local/apache/templates/format1.html:

     <html>
         <head><title>your template</title></head>
                 <title>your template</title>
         <body bgcolor="#778899">
                 some headers, banners, whatever...
                 <p>
     the content goes here
                 </p>
                 <p>some footers, modification dates, whatever...
         </body>
     </html>

     httpd.conf:

     <Location /someplace>
        SetHandler perl-script
        PerlHandler Apache::SimpleReplace Apache::SSI

     PerlSetVar  TEMPLATE "templates/format1.html"
     PerlSetVar  REPLACE "the content goes here"
     PerlSetVar  Filter On
       </Location>

   Now, a request to http://localhost/someplace/foo.html will insert the
contents of foo.html in place of "the content goes here" in the
format1.html template and pass those results to Apache::SSI The result is
a nice and tidy way to control any custom headers, footers, background
colors, or images in a single html file.

NOTES
=====

   As of 0.02, TEMPLATE is no longer relative to the ServerRoot.

   REPLACE defaults to "|", though it may be any character or string you
like - metacharacters are disabled in the search, so sorry, no regex for
now...

   Verbose debugging is enabled by setting $Apache::SimpleReplace::DEBUG=1
or greater.  To turn off all debug information, set your apache LogLevel
directive above info level.

   This is alpha software, and as such has not been tested on multiple
platforms or environments.  It requires PERL_LOG_API=1, PERL_FILE_API=1,
and maybe other hooks to function properly.

FEATURES/BUGS
=============

   If Apache::SimpleReplace finds more than one match for REPLACE in the
template, it will insert the request for the first occurrence only.  All
other replacement strings will just be stripped from the template.

   Currently, Apache::SimpleReplace will return DECLINED if the
content-type of the request is not 'text/html'.

SEE ALSO
========

   perl(1), mod_perl(3), Apache(3), Apache::Filter(3)

AUTHOR
======

   Geoffrey Young <geoff@cpan.org>

COPYRIGHT
=========

   Copyright (c) 2000, Geoffrey Young.  All rights reserved.

   This module is free software.  It may be used, redistributed and/or
modified under the same terms as Perl itself.

Because size does matter.
*************************

NAME
====

   Apache::SizeLimit - Because size does matter.

SYNOPSIS
========

   This module allows you to kill off Apache httpd processes if they grow
too large.  You can choose to set up the process size limiter to check the
process size on every request:

     # in your startup.pl:
     use Apache::SizeLimit;
     $Apache::SizeLimit::MAX_PROCESS_SIZE = 10000; # in KB, so this is 10MB

     # in your httpd.conf:
     PerlFixupHandler Apache::SizeLimit
     # you can set this up as any Perl*Handler that handles part of the
     # request, even the LogHandler will do.

   Or you can just check those requests that are likely to get big, such as
CGI requests.  This way of checking is also easier for those who are mostly
just running CGI.pm/Registry scripts:

     # in your CGI:
     use Apache::SizeLimit;
     &Apache::SizeLimit::setmax(10000);	# Max Process Size in KB

   Since checking the process size can take a few system calls on some
platforms (e.g. linux), you may want to only check the process size every
N times.  To do so, put this in your startup.pl or CGI:

     $Apache::SizeLimit::CHECK_EVERY_N_REQUESTS = 2;

   This will only check the process size every other time the process size
checker is called.

DESCRIPTION
===========

   This module is highly platform dependent, please read the CAVEATS
section.

   This module was written in response to questions on the mod_perl mailing
list on how to tell the httpd process to exit if it gets too big.

   Actually there are two big reasons your httpd children will grow.
First, it could have a bug that causes the process to increase in size
dramatically, until your system starts swapping.  Second, your process just
does stuff that requires a lot of memory, and the more different kinds of
requests your server handles, the larger the httpd processes grow over
time.

   This module will not really help you with the first problem.  For that
you should probably look into Apache::Resource or some other means of
setting a limit on the data size of your program.  BSD-ish systems have
setrlimit() which will croak your memory gobbling processes.  However it
is a little violent, terminating your process in mid-request.

   This module attempts to solve the second situation where your process
slowly grows over time.  The idea is to check the memory usage after every
request, and if it exceeds a threshold, exit gracefully.

   By using this module, you should be able to discontinue using the Apache
configuration directive *MaxRequestsPerChild*, although for some folks,
using both in combination does the job.  Personally, I just use the
technique shown in this module and set my MaxRequestsPerChild value to
6000.

CAVEATS
=======

   This module is platform dependent, since finding the size of a process
is pretty different from OS to OS, and some platforms may not be supported.

   Currently supported OSes:

linux
     For linux we read the process size out of /proc/self/status.  This is
     a little slow, but usually not too bad. If you are worried about
     performance, try only setting up the the exit handler inside CGIs
     (with the `setmax' function), and see if the CHECK_EVERY_N_REQUESTS
     option is of benefit.

solaris 2.6 and above
     For solaris we simply retrieve the size of /proc/self/as, which
     contains the address-space image of the process, and convert to KB.

     NOTE: This is only known to work for solaris 2.6 and above. Evidently
     the /proc filesystem has changed between 2.5.1 and 2.6. Can anyone
     confirm or deny?

     Uses BSD::Resource::getrusage() to determine process size.  This is
     pretty efficient (a lot more efficient than reading it from the /proc
     fs anyway).

AIX?
     Uses BSD::Resource::getrusage() to determine process size.

   If your platform is not supported, and if you can tell me how to check
for the size of a process under your OS (in KB), then I will add it to the
list.  The more portable/efficient the solution, the better, of course.

TODO
====

   Possibly provide a perl make/install so that the SizeLimit.pm is
created at build time with only the code you need on your platform.

   If Apache was started in non-forking mode, should hitting the size limit
cause the process to exit?

AUTHOR
======

   Doug Bagley <doug+modperl@bagley.org>, channeling Procrustes.

   Brian Moseley <ix@maz.org>: Solaris 2.6 support

Hook Devel::SmallProf into mod_perl
***********************************

NAME
====

   Apache::SmallProf - Hook Devel::SmallProf into mod_perl

SYNOPSIS
========

     <IfDefine PERLSMALLPROF>

     <Perl>
      use Apache::DB ();
      Apache::DB->init;
     </Perl>

     <Location />
      PerlFixupHandler Apache::SmallProf
     </Location>
      </IfDefine>

DESCRIPTION
===========

   Devel::SmallProf is a line-by-line code profiler.  Apache::SmallProf
provides this profiler in the mod_perl environment.  Profiles are written
to *ServerRoot/logs/smallprof* and unlike *Devel::SmallProf* the profile is
split into several files based on package name.

   The *Devel::SmallProf* documentation explains how to analyize the
profiles, e.g.:

     % sort -nrk 2  logs/smallprof/CGI.pm.prof | more
             1 0.104736       629:     eval "package $pack; $$auto";
             2 0.002831       647:       eval "package $pack; $code";
             5 0.002002       259:    return $self->all_parameters unless @p;
             5 0.000867       258:    my($self,@p) = self_or_default(@_);
             ...

SEE ALSO
========

   Devel::SmallProf(3), Apache::DB(3), Apache::DProf(3)

AUTHOR
======

   Devel::SmallProf - Ted Ashton Apache::SmallProf derived from
Devel::SmallProf - Doug MacEachern

Manage A Staging Directory
**************************

NAME
====

   Apache::Stage - Manage A Staging Directory

SYNOPSIS
========

     <Location /STAGE>
       # this location is served by normal apache. It's recommended to
       # restrict access to this location to registered authors of this
       # site, but a restriction isn't necessary
       ErrorDocument 403 /stage-redir
       ErrorDocument 404 /stage-redir
     </Location>

     <Location /stage-redir>
       # the name of this location must match the ErrorDocument redirects
       # above

     # PerlSetVar apache_stage_regex " ^ (/STAGE/[^/]*) (.*) $ "

     # This regex has to split a staged URI into two parts. It is
     # evaluated with the /ox switch in effect, so this will NOT be a
     # per-directory variable. The first part will be thrown away and
     # just the second part will be served if the original URI cannot
     # be accessed. In case of 301 and 302 redirects the first part
     # will be prepended again. The default regex is defined as above
     # which means that URIS will be split into "/STAGE/anyuser" and
     # the rest.

     SetHandler perl-script
     PerlHandler Apache::Stage
     Options ExecCGI

     </Location>

DESCRIPTION
===========

   A staging place is a place where an author of an HTML document checks
the look and feel of a document before it's uploaded to the final
location. A staging place doesn't need to be a separate server, nor need
it be a mirror of the "real" tree, and not even a tree of symbolic links.
A sparse directory tree that holds nothing but the staged files will do.

   Apache::Stage implements a staging directory that needs a minimum of
space.  Per default the path for the per-user staging directory is
hardcoded as

     /STAGE/any-user-name

   The code cares for proper internal and external redirects for any
documents that are not in the stage directory tree. This means that all
graphics are displayed as they will be later after the staged files will
have been published. The following table describes what has been tested:

     Location              Redirect to       Comment

     /STAGE/u1/            /                 Homepage. Internal Redirect.

     /STAGE/u2/dir1        /dir1/            Really /dir1/index.html

     /STAGE/u3/dir2        /dir2/            Directory has no index.html
                                             Options Indexes is off, thus
                                             "Forbidden"

     /STAGE/u4/dir2/foo    /dir2/foo         Internal redirect.

     /STAGE/u5/bar         -                 Exists really, no redirect
                                             necessary

     /STAGE/u6             -                 Fails unless location exists

   The entries described in SYNOPSIS in the access.conf or an equivalent
place define the name of the staging directory, the name of an internal
location that catches the exception when a document is not in the staging
directory, and the regular expression that transforms the staging URI into
the corresponding public URI.

   With this setup only ErrorDocument 403 and 404 will be served by
Apache::Stage. If you need coexistence with different ErrorDocument
handlers, you will either have to disable them for /STAGE or integrate the
code of Apache::Stage into an if/else branch based on the path.

AUTHOR
======

   Andreas König <koenig@kulturbox.de>

Reload %INC files when updated on disk
**************************************

NAME
====

   Apache::StatINC - Reload %INC files when updated on disk

SYNOPSIS
========

     #httpd.conf or some such
     #can be any Perl*Handler
     PerlInitHandler Apache::StatINC

DESCRIPTION
===========

   When Perl pulls a file via require, it stores the filename in the
global hash %INC.  The next time Perl tries to require the same file, it
sees the file in %INC and does not reload from disk.  This module's
handler iterates over %INC and reloads the file if it has changed on disk.

   Note that StatINC operates on the current context of `@INC'.  Which
means, when called as a Perl*Handler it will not see `@INC' paths added or
removed by Apache::Registry scripts, as the value of `@INC' is saved on
server startup and restored to that value after each request.  In other
words, if you want StatINC to work with modules that live in custom `@INC'
paths, you should modify `@INC' when the server is started.  Besides, 'use
lib' in startup scripts, you can also set the PERL5LIB variable in the
httpd's environment to include any non-standard 'lib' directories that you
choose.  For example, you might use a script called 'start_httpd' to start
apache, and include a line like this:

     PERL5LIB=/usr/local/foo/myperllibs; export PERL5LIB

   When you have problems with modules not being reloaded, please refer to
the following lines in 'perlmodlib':

   "Always use -w. Try to `use strict;' (or `use strict qw(...);').
Remember that you can add `no strict qw(...);' to individual blocks of
code that need less strictness. Always use -w. Always use -w!  Follow the
guidelines in the perlstyle(1) manual."

   Warnings when running under mod_perl is enabled with 'PerlWarn On' in
your httpd.conf.

   It will most likely help you to find the problem. Really.

OPTIONS
=======

StatINC_UndefOnReload
     Normally, StatINC will turn of warnings to avoid "Subroutine
     redefined" warnings when it reloads a file.  However, this does not
     disable the Perl mandatory warning when re-defining constant
     subroutines (see perldoc perlsub).  With this option On, StatINC will
     invoke the *Apache::Symbol* *undef_functions* method to avoid these
     mandatory warnings:

          PerlSetVar StatINC_UndefOnReload On

StatINC_Debug
     You can make StatINC tell when it reloads a module by setting this
     option to on.

          PerlSetVar StatINC_Debug 1

     The only used debug level is currently 1.

SEE ALSO
========

   mod_perl(3)

AUTHOR
======

   Currently maintained by Ask Bjoern Hansen <ask@netcetera.dk>.  Written
by Doug MacEachern.

Embedded interpreter status information
***************************************

NAME
====

   Apache::Status - Embedded interpreter status information

SYNOPSIS
========

     <Location /perl-status>
     SetHandler  perl-script
     PerlHandler Apache::Status
     </Location>

DESCRIPTION
===========

   The *Apache::Status* module provides some information about the status
of the Perl interpreter embedded in the server.

   Configure like so:

     <Location /perl-status>
     SetHandler  perl-script
     PerlHandler Apache::Status
     </Location>

   Other modules can "plugin" a menu item like so:

     Apache::Status->menu_item(
        'DBI' => "DBI connections", #item for Apache::DBI module
        sub {
            my($r,$q) = @_; #request and CGI objects
            my(@strings);
            push @strings,  "blobs of html";
            return \@strings;     #return an array ref
        }
     ) if Apache->module("Apache::Status"); #only if Apache::Status is loaded

   WARNING: Apache::Status must be loaded before these modules via the
PerlModule or PerlRequire directives.

OPTIONS
=======

StatusOptionsAll
     This single directive will enable all of the options described below.

          PerlSetVar StatusOptionsAll On

StatusDumper
     When browsing symbol tables, the values of arrays, hashes ans calars
     can be viewed via Data::Dumper if this configuration variable is set
     to On:

          PerlSetVar StatusDumper On

StatusPeek
     With this option On and the *Apache::Peek* module installed,
     functions and variables can be viewed ala Devel::Peek style:

          PerlSetVar StatusPeek On

StatusLexInfo
     With this option On and the *B::LexInfo* module installed, subroutine
     lexical variable information can be viewed.

          PerlSetVar StatusLexInfo On

StatusDeparse
     With this option On and B::Deparse version 0.59 or higher (included
     in Perl 5.005_59+), subroutines can be "deparsed".

          PerlSetVar StatusDeparse On

     Options can be passed to B::Deparse::new like so:

          PerlSetVar StatusDeparseOptions "-p -sC"

     See the B::Deparse manpage for details.

StatusTerse
     With this option On, text-based op tree graphs of subroutines can be
     displayed, thanks to B::Terse.

          PerlSetVar StatusTerse On

StatusTerseSize
     With this option On and the *B::TerseSize* module installed,
     text-based op tree graphs of subroutines and their size can be
     displayed.  See the *B::TerseSize* docs for more info.

          PerlSetVar StatusTerseSize On

StatusTerseSizeMainSummary
     With this option On and the *B::TerseSize* module installed, a
     "Memory Usage" will be added to the Apache::Status main menu.  This
     option is disabled by default, as it can be rather cpu intensive to
     summarize memory usage for the entire server.  It is strongly
     suggested that this option only be used with a development server
     running in -X mode, as the results will be cached.

          PerlSetVar StatusTerseSizeMainSummary On

StatusGraph
     When StatusDumper is enabled, another link "OP Tree Graph" will be
     present with the dump if this configuration variable is set to On:

          PerlSetVar StatusGraph

     This requires the B module (part of the Perl compiler kit) and
     B::Graph (version 0.03 or higher) module to be installed along with
     the dot program.

     Dot is part of the graph visualization toolkit from AT&T:
     `http://www.research.att.com/sw/tools/graphviz/').

     WARNING: Some graphs may produce very large images, some graphs may
     produce no image if B::Graph's output is incorrect.

Dot
     Location of the dot program for StatusGraph, if other than /usr/bin
     or /usr/local/bin

GraphDir
     Directory where StatusGraph should write it's temporary image files.
     Default is $ServerRoot/logs/b_graphs

PREREQUISITES
=============

   The *Devel::Symdump* module, version *2.00* or higher.

SEE ALSO
========

   perl(1), Apache(3), Devel::Symdump(3), Data::Dumper(3), B(3),
B::Graph(3)

AUTHOR
======

   Doug MacEachern

Storing data in Apache.
***********************

NAME
====

   Apache::Storage - Storing data in Apache.

SYNOPSIS
========

     use Apache::Storage;

DESCRIPTION
===========

   Ever wanted to store information in Apache so the additional requests
could gain access to it?

   For example, you create an object which is fairly expensive and you
don't want to have to recreate each time, or say you just have some
information you are storing in a reference that you want requests that
follow you to see.

   This module is for you.

   It has three functions described below. They allow you to store and
retrieve information from the Apache process. The functions are fairly
simple and should make it pretty easy for you to do so without to much
hassle.

   All of this works with subrequests, so unlike pnotes, you don't need to
worry about loosing data if your request is subrequested by an outside
Apache module.

   You can also use the ApacheStorage directive inside of Apache to prime
data into the Apache::Storage.

FUNCTIONS
---------

   Note

   Keep in mind that data is only stored on the Apache process itself.
Different child processes all have their own storage. Don't assume you will
get the same Apache child process when reconnecting.

   Make sure you put a "PerlModule Apache::Storage" in your httpd.conf
file. Apache make core if you do not do this.

set_storage
     Set functions can be called in two ways. They can be called with a
     key and a reference. The reference will then be available by calling
     it through a get function.  You can also pass in hash reference. The
     contents of this hash will be mapped into storage based on it
     original key pair. Nothing is returned by either of these functions

get_storage
     Get functions can be calling in two ways. They can either be called
     with a single key, where they will return a single hash

get_storage_dump
     This gives you a hash of the entire contents of what is being stored
     currently.

Apache Directives
-----------------

ApacheStore
     Takes two arguments, a key and a value. The value is evaled.

ApacheStorageInit
     Takes no values, and only needs to be used if you don't have at least
     one ApacheStore call.

Example
=======

httpd.conf
     <VirtualHost 10.0.2.25:80>

          ServerAdmin root@tangent.org

          DocumentRoot /usr/local/apache/htdocs

          ServerName slash.tangent.org

          ErrorLog logs/error_log

          CustomLog logs/access_log common

          ApacheStoreINIT

     </VirtualHost>

     <VirtualHost 10.0.2.25:80>

          ServerAdmin root@tangent.org

          DocumentRoot /usr/local/apache/htdocs

          ServerName slash2.tangent.org

          ErrorLog logs/error_log

          CustomLog logs/access_log common

          ApacheStore foo "[qw(skdjf slkdjf lskdjf)]"

     </VirtualHost>

LICENSE
=======

   See the file LICENSE that this comes with.

SEE ALSO
========

   perl(3).  mod_perl(3).

HOME
====

   http://tangent.org/Apache-Storage/

Author
======

   Brian Aker, brian@tangent.org

   Seattle, WA.

Perl extension for creating persistant database connections to sybase using Apache and Sybperl.
***********************************************************************************************

NAME
====

   Apache::Sybase::CTlib - Perl extension for creating persistant database
connections to sybase using Apache and Sybperl.

SYNOPSIS
========

   use Apache::Sybase::CTlib;

   Apache::Sybase::CTlib->connect_on_init("user", "password", "server",
"db");

DESCRIPTION
===========

   This module allows Apache/Modperl/Sybperl users to connect to sybase
data servers, and maintain persistant connections. The advantage should be
clear, as this avoids the overhead of creating a connection, gathering
data, and then destroying the connection with every query.

   Place the above commands in your startup file for apache:

   In httpd.conf

   PerlRequire /apache/startup.pl

   In /apache/startup.pl

   use Apache::Sybase::CTlib;

   Apache::Sybase::CTlib->connect_on_init("user", "password", "server",
"db");

   Passing db (database name) to the module will allow you to specify a
database to start in (the module will execute "use database" after the
connection is established). This is an optional parameter.

AUTHOR
======

   Mark A. Downing, mdowning@rdatasys.com http://www.wm7d.net/

SEE ALSO
========

   perl(1).

Things for symbol things
************************

NAME
====

   Apache::Symbol - Things for symbol things

SYNOPSIS
========

     use Apache::Symbol ();

     @ISA = qw(Apache::Symbol);

DESCRIPTION
===========

   *perlsub/Constant Functions* says:

     If you redefine a subroutine which was eligible for inlining you'll get
     a mandatory warning.  (You can use this warning to tell whether or not a
     particular subroutine is considered constant.)  The warning is
     considered severe enough not to be optional because previously compiled
     invocations of the function will still be using the old value of the
     function.

   *mandatory warning* means there is _no_ way to avoid this warning no
matter what tricks you pull in Perl.  This is bogus for us mod_perl users
when restarting the server with *PerlFreshRestart* on or when
Apache::StatINC pulls in a module that has changed on disk.

   You can, however, pull some tricks with XS to avoid this warning,
*Apache::Symbol::undef* does just that.

ARGUMENTS
=========

   `undef_functions' takes two arguments: skip and `only_undef_exports'.

   skip is a regular expression indicating the function names to skip.

   Use the `only_undef_exports' flag to undef only those functions which
are listed in `@EXPORT', `@EXPORT_OK', `%EXPORT_TAGS', or
`@EXPORT_EXTRAS'.  `@EXPORT_EXTRAS' is not used by the Exporter, it is
only exists to communicate with `undef_functions'.

   As a special case, if none of the EXPORT variables are defined ignore
`only_undef_exports'.  This takes care of trivial modules that don't use
the Exporter.

ARGUMENTS
=========

   `undef_functions' takes two arguments: skip and `only_undef_exports'.

   skip is a regular expression indicating the function names to skip.

   Use the `only_undef_exports' flag to undef only those functions which
are listed in `@EXPORT', `@EXPORT_OK', `%EXPORT_TAGS', or
`@EXPORT_EXTRAS'.  `@EXPORT_EXTRAS' is not used by the Exporter, it is
only exists to communicate with `undef_functions'.

   As a special case, if none of the EXPORT variables are defined ignore
`only_undef_exports'.  This takes care of trivial modules that don't use
the Exporter.

PLAYERS
=======

   This module and the undefining of functions is optional, if you wish to
have this functionality enabled, there are one or more switches you need
to know about.

PerlRestartHandler
     Apache::Symbol defines a PerlRestartHandler which can be useful in
     conjuction with `PerlFreshRestart On' as it will avoid subroutine
     redefinition messages.  Configure like so:

          PerlRestartHandler Apache::Symbol

Apache::Registry
     By placing the SYNOPSIS bit in you script, Apache::Registry will
     undefine subroutines in your script before it is re-compiled to avoid
     "subroutine re-defined" warnings.

Apache::StatINC
     See Apache::StatINC's docs.

APACHE_SYMBOL_UNIVERSAL
     If this environment variable is true when Symbol.pm is compiled, it
     will define UNIVERSAL::undef_functions, which means all classes will
     inherit *Apache::Symbol::undef_functions*.

Others
     Module such as *HTML::Embperl* and *Apache::ePerl* who compile and
     script cache scripts ala Apache::Registry style can use
     `undef_functions' with this bit of code:

          if($package->can('undef_functions')) {
          	$package->undef_functions;
          }

     Where `$package' is the name of the package in which the script is
     being re-compiled.

SEE ALSO
========

   perlsub(1), Devel::Symdump(3)

AUTHOR
======

   Doug MacEachern

Symbol table snapshots
**********************

NAME
====

   Apache::Symdump - Symbol table snapshots

SYNOPSIS
========

     PerlLogHandler Apache::Symdump

DESCRIPTION
===========

   Apache:Symdump uses Devel::Symdump to record snapshots of the Perl
symbol table in ServerRoot/logs/symdump.$$.$n Where $$ is the process id
and $n is incremented each time the handler is run.  The diff utility can
be used to compare snapshots and get an idea of what might be making a
process grow.  Normally, new symbols come from modules or scripts that
were not preloaded, the Perl method cache, etc.

     % diff -u symdump.$$.0 symdump.$$.1

CAVEATS
=======

   Apache::Symdump does not cleanup up its snapshot files, do so simply by:

     % rm logs/symdump.* logs/incdump.*

SEE ALSO
========

   Devel::Symdump(3), Apache::Leak(3)

AUTHOR
======

   Doug MacEachern

Perl interface to the Apache table structure
********************************************

NAME
====

   Apache::Table - Perl interface to the Apache table structure

SYNOPSIS
========

     use Apache::Table ();

     my $headers_out = $r->headers_out;
     while(my($key,$val) = each %$headers_out) {
     ...
     }

     my $table = $r->headers_out;
     $table->set(From => 'dougm@perl.apache.org');

   mod_perl needs to be compiled with at least one of the following
options:

     DYNAMIC=1
     PERL_TABLE_API=1
     EVERYTHING=1

DESCRIPTION
===========

   This module provides tied interfaces to Apache data structures.

CLASSES
-------

Apache::Table
     The Apache::Table class provides methods for interfacing with the
     Apache table structure.  The following Apache class methods, when
     called in a scalar context with no "key" argument, will return a HASH
     reference blessed into the Apache::Table class and where HASH is tied
     to Apache::Table:

          headers_in
          headers_out
          err_headers_out
          notes
          dir_config
          subprocess_env

METHODS
-------

get
     Corresponds to the `ap_table_get' function.

          my $value = $table->get($key);

          my $value = $headers_out->{$key};

set
     Corresponds to the `ap_table_set' function.

          $table->set($key, $value);

          $headers_out->{$key} = $value;

unset
     Corresponds to the `ap_table_unset' function.

          $table->unset($key);

          delete $headers_out->{$key};

clear
     Corresponds to the `ap_table_clear' function.

          $table->clear;

          %$headers_out = ();

add
     Corresponds to the `ap_table_add' function.

          $table->add($key, $value);

merge
     Corresponds to the `ap_table_merge' function.

          $table->merge($key, $value);

AUTHOR
======

   Doug MacEachern

SEE ALSO
========

   Apache(3), mod_perl(3)

mod_perl handler for Taco
*************************

NAME
====

   Apache::Taco.pm - mod_perl handler for Taco

SYNOPSIS
========

   This module defines a mod_perl handler (running under the Apache web
server) that serves Taco pages.

     # In Apache's srm.conf (or similar), setup so
     # files ending in .taco get handled by Apache::Taco
     <Files ~ "\.taco$">
      SetHandler perl-script
      PerlHandler Apache::Taco
      PerlSetVar TacoRelayHost whatever.you.want/no_taco  # for SSI
     </Files>

DESCRIPTION
===========

   This module lets you serve Taco files over the World Wide Web.  It lets
you write Taco modules that take advantage of mod_perl's speed and power.

PerlSetVar parameters
---------------------

   When this handler runs, it takes several different parameters that can
alter its behavior.  To set any of these parameters, use the PerlSetVar
command in an appropriate Apache config file.  This may be any of
httpd.conf, srm.conf, etc., or a .htaccess file:

     PerlSetVar TacoService joes_cars

   See the mod_perl documentation for more information about PerlSetVar.

   * TacoService <service name>

     Use this to set the service that a request will run under.  See
     Taco::ServiceRegistry.pm for more information about services.

   * TacoCGI <true or false>

     If set to true, Taco will interpret the file as Perl code.  The Perl
     code will have access to all of Taco's internal functions.

   * TacoRelayHost < URL prefix >

     By default, Apache::Taco will just read in the file pointed to by the
     URL and interpret it as a Taco template.  This prevents server-side
     includes, however.  If you want to use server-side includes, you
     should use either the TacoRelayHost parameter or the TacoFilterMod
     parameter.

     If your server is configured with the following:

          PerlSetVar TacoRelayHost http://whatever.host.edu/no_taco

     and Apache::Taco gets a request at http://taco.host.edu/page.taco, it
     will request the URL http://whatever.host.edu/no_taco/page.taco, and
     then interpret the content of that page as a Taco template.

   * TacoFilterMod < Perl module (class) >

     If you'd rather implement SSI (or any other text processing) yourself
     in a Perl module, you can use the TacoFilterMod parameter:

          PerlSetVar TacoFilterMod  MyPackage::filter

     The MyPackage::filter class needs to define a new() method and an
     output() method, because it will be called like this:

          # Pass the filename and the current Apache::Request object
          my $p = MyPackage::filter->new($filename, $G::r);
          $template->set_text( $p->output );
          $template->output($buffer);

     It's possible that the TacoFilterMod capability can be better
     implemented by using an Apache::OutputChain, but I don't know much
     about that yet.

   * TacoDebug <true or false>

     When this parameter is set to 'true', Apache::Taco will print a few
     debug statements to Apache's error log.

SEE ALSO
========

   Taco(3), Apache(3), mod_perl(1), and the mod_perl web site at
http://perl.apache.org/

AUTHOR
======

   Ken Williams (ken@forum.swarthmore.edu)

   Copyright (c) 1998 Swarthmore College. All rights reserved.

Allocate temporary filenames for the duration of a request
**********************************************************

NAME
====

   Apache::TempFile - Allocate temporary filenames for the duration of a
request

SYNOPSIS
========

     use Apache::TempFile qw(tempname)
     my($name) = tempname();
     open(FILE,">$name");
     print FILE "Testing\n";
     close(FILE);

DESCRIPTION
===========

   This module provides names for temporary files and ensures that they are
removed when the current request is completed.

FUNCTIONS
=========

tempname
     This routine returns a unique temporary filename and arranges for that
     file to be removed when the current request is completed. If an
     extension is supplied as an argument that it will be appended to the
     filename which is generated.

          my($name) = Apache::TempFile::tempname();
          my($name) = Apache::TempFile::tempname("html");

AUTHOR
======

   Tom Hughes, tom@compton.demon.co.uk

SEE ALSO
========

   Apache(3), mod_perl(3)

Apache/mod_perl interface to the Template Toolkit
*************************************************

NAME
====

   Apache::Template - Apache/mod_perl interface to the Template Toolkit

SYNOPSIS
========

     # add the following to your httpd.conf
     PerlModule          Apache::Template

     # set various configuration options, e.g.
     TT2Trim             On
     TT2PostChomp        On
     TT2EvalPerl         On
     TT2IncludePath      /usr/local/tt2/templates
     TT2IncludePath      /home/abw/tt2/lib
     TT2PreProcess       config header
     TT2PostProcess      footer
     TT2Error            error

     # now define Apache::Template as a PerlHandler, e.g.
     <Files *.tt2>
     	SetHandler	perl-script
         PerlHandler     Apache::Template
     </Files>

     <Location /tt2>
     	SetHandler	perl-script
         PerlHandler     Apache::Template
     </Location>

DESCRIPTION
===========

   The Apache::Template module provides a simple interface to the Template
Toolkit from Apache/mod_perl.  The Template Toolkit is a fast, powerful
and extensible template processing system written in Perl.  It implements
a general purpose template language which allows you to clearly separate
application logic, data and presentation elements.  It boasts numerous
features to facilitate in the generation of web content both online and
offline in "batch mode".

   This documentation describes the Apache::Template module, concerning
itself primarily with the Apache/mod_perl configuration options (e.g. the
httpd.conf side of things) and not going into any great depth about the
Template Toolkit itself.  The Template Toolkit includes copious
documentation which already covers these things in great detail.  See
Template, for further information.

CONFIGURATION
=============

   Most of the Apache::Template configuration directives relate directly
to their Template Toolkit counterparts, differing only in having a 'TT2'
prefix, mixed capitalisation and lack of underscores to space individual
words.  This is to keep Apache::Template configuration directives in
keeping with the preferred Apache/mod_perl style.

   e.g.

     Apache::Template  =>  Template Toolkit
     --------------------------------------
     TT2Trim	          TRIM
     TT2IncludePath        INCLUDE_PATH
     TT2PostProcess        POST_PROCESS
     ...etc...

   In some cases, the configuration directives are named or behave
slightly differently to optimise for the Apache/mod_perl environment or
domain specific features.  For example, the TT2Tags configuration
directive can be used to set TAG_STYLE and/or START_TAG and END_TAG and as
such, is more akin to the Template Toolkit TAGS directive.

   e.g.

     TT2Tags	    html
     TT2Tags	    <!--  -->

   The configuration directives are listed in full below.  Consult
Template, for further information on their effects within the
Template Toolkit.

TT2Tags
     Used to set the tags used to indicate Template Toolkit directives
     within source templates.  A single value can be specified to indicate
     a TAG_STYLE, e.g.

          TT2Tags	    html

     A pair of values can be used to indicate a START_TAG and END_TAG.

          TT2Tags	    <!--    -->

     Note that, unlike the Template Toolkit START_TAG and END_TAG
     configuration options, these values are automatically escaped to
     remove any special meaning within regular expressions.

          TT2Tags	    [*  *]	# no need to escape [ or *

     By default, the start and end tags are set to `[%' and `%]'
     respectively.  Thus, directives are embedded in the form: [% INCLUDE
     my/file %].

TT2PreChomp
     Equivalent to the PRE_CHOMP configuration item.  This flag can be set
     to have removed any whitespace preceeding a directive, up to and
     including the preceeding newline.  Default is 'Off'.

          TT2PreChomp	    On

TT2PostChomp
     Equivalent to the POST_CHOMP configuration item.  This flag can be set
     to have any whitespace after a directive automatically removed, up to
     and including the following newline.  Default is 'Off'.

          TT2PostChomp    On

TT2Trim
     Equivalent to the TRIM configuration item, this flag can be set to
     have all surrounding whitespace stripped from template output.
     Default is 'Off'.

          TT2Trim	    On

TT2AnyCase
     Equivalent to the ANY_CASE configuration item, this flag can be set
     to allow directive keywords to be specified in any case.  By default,
     this setting is 'Off' and all directive (e.g. 'INCLUDE', 'FOREACH',
     etc.) should be specified in UPPER CASE only.

          TT2AnyCase	    On

TT2Interpolate
     Equivalent to the INTERPOLATE configuration item, this flag can be set
     to allow simple variables of the form `$var' to be embedded within
     templates, outside of regular directives.  By default, this setting is
     'Off' and variables must appear in the form [% var %], or more
     explicitly, [% GET var %].

          TT2Interpolate  On

TT2IncludePath
     Equivalent to the INCLUDE_PATH configuration item.  This can be used
     to specify one or more directories in which templates are located.
     Multiple directories may appear on each TT2IncludePath directive line,
     and the directive may be repeated.  Directories are searched in the
     order defined.

          TT2IncludePath  /usr/local/tt2/templates
          TT2InludePath   /home/abw/tt2   /tmp/tt2

     Note that this only affects templates which are processed via
     directive such as INCLUDE, PROCESS, INSERT, WRAPPER, etc.  The full
     path of the main template processed by the Apache/mod_perl handler is
     generated (by Apache) by appending the request URI to the
     DocumentRoot, as per usual.  For example, consider the following
     configuration extract:

          DocumentRoot    /usr/local/web/ttdocs
          [...]
          TT2IncludePath  /usr/local/tt2/templates

          <Files *.tt2>
          	SetHandler	perl-script
              PerlHandler     Apache::Template
          </Files>

     A request with a URI of '/foo/bar.tt2' will cause the handler to
     process the file '/usr/local/web/ttdocs/foo/bar.tt2' (i.e.
     DocumentRoot + URI).  If that file should include a directive such as
     [% INCLUDE foo/bar.tt2 %] then that template should exist as the file
     '/usr/local/tt2/templates/foo/bar.tt2' (i.e. TT2IncludePath +
     template name).

TT2Absolute
     Equivalent to the ABSOLUTE configuration item, this flag can be
     enabled to allow templates to be processed (via INCLUDE, PROCESS,
     etc.) which are specified with absolute filenames.

          TT2Absolute	    On

     With the flag enabled a template directive of the form:

          [% INCLUDE /etc/passwd %]

     will be honoured.  The default setting is 'Off' and any attempt to
     load a template by absolute filename will result in a 'file' exception
     being throw with a message indicating that the ABSOLUTE option is not
     set.  See Template, for further discussion on
     exception handling.

TT2Relative
     Equivalent to the RELATIVE configuration item.  This is similar to the
     TT2Absolute option, but relating to files specified with a relative
     filename, that is, starting with './' or '../'

          TT2Relative On

     Enabling the option permits templates to be specifed as per this
     example:

          [% INCLUDE ../../../etc/passwd %]

     As with TT2Absolute, this option is set 'Off', causing a 'file'
     exception to be thrown if used in this way.

TT2Delimiter
     Equivalent to the DELIMTER configuration item, this can be set to
     define an alternate delimiter for separating multiple TT2IncludePath
     options.  By default, it is set to ':', and thus multiple directories
     can be specified as:

          TT2IncludePath  /here:/there

     Note that Apache implicitly supports space-delimited options, so the
     following is also valid and defines 3 directories, /here, /there and
     /anywhere.

          TT2IncludePath  /here:/there /anywhere

     If you're unfortunate enough to be running Apache on a Win32 system
     and you need to specify a ':' in a path name, then set the
     TT2Delimiter to an alternate value to avoid confusing the Template
     Toolkit into thinking you're specifying more than one directory:

          TT2Delimiter    ,
          TT2IncludePath  C:/HERE D:/THERE E:/ANYWHERE

TT2PreProcess
     Equivalent to PRE_PROCESS, this option allows one or more templates to
     be named which should be processed before the main template.  This can
     be used to process a global configuration file, add canned headers,
     etc.  These templates should be located in one of the TT2IncludePath
     directories, or specified absolutely if the TT2Absolute option is set.

          TT2PreProcess   config header

TT2PostProcess
     Equivalent to POST_PROCESS, this option allow one or more templates to
     be named which should be processed after the main template, e.g. to
     add standard footers.  As per TTPreProcess, these should be located in
     one of the TT2IncludePath directories, or specified absolutely if the
     TT2Absolute option is set.

          TT2PostProcess  copyright footer

TT2Process
     This is equivalent to the PROCESS configuration item.  It can be used
     to specify one or more templates to be process instead of the main
     template.  This can be used to apply a standard "wrapper" around all
     template files processed by the handler.

          TT2Process	    mainpage

     The original template (i.e. whose path is formed from the DocumentRoot
     + URI, as explained in the `TT2IncludePath|TT2IncludePath' in this
     node item above) is preloaded and available as the 'template'
     variable.  This a typical TT2Process template might look like:

          [% PROCESS header %]
          [% PROCESS $template %]
          [% PROCESS footer %]

     Note the use of the leading '$' on template to defeat the auto-quoting
     mechanism which is applied to INCLUDE, PROCESS, etc., directives.  The
     directive would otherwise by interpreted as:

          [% PROCESS "template" %]

TT2Default
     This is equivalent to the DEFAULT configuration item.  This can be
     used to name a template to be used in place of a missing template
     specified in a directive such as INCLUDE, PROCESS, INSERT, etc.  Note
     that if the main template is not found (i.e. that which is mapped from
     the URI) then the handler will decline the request, resulting in a 404
     - Not Found.  The template specified should exist in one of the
     directories named by TT2IncludePath.

          TT2Default	    nonsuch

TT2Error
     This is equivalent to the ERROR configuration item.  It can be used
     to name a template to be used to report errors that are otherwise
     uncaught.  The template specified should exist in one of the
     directories named by TT2IncludePath.  When the error template is
     processed, the 'error' variable will be set to contain the relevant
     error details.

          TT2Error	    error

TT2EvalPerl
     This is equivalent to the EVAL_PERL configuration item.  It can be
     enabled to allow embedded [% PERL %] ... [% END %] sections within
     templates.  It is disabled by default and any PERL sections
     encountered will raise 'perl' exceptions with the message 'EVAL_PERL
     not set'.

          TT2EvalPerl	    On

TT2LoadPerl
     This is equivalent to the LOAD_PERL configuration item which allows
     regular Perl modules to be loaded as Template Toolkit plugins via the
     USE directive.  It is set 'Off' by default.

          TT2LoadPerl	    On

TT2Recursion
     This is equivalent to the RECURSION option which allows templates to
     recurse into themselves either directly or indirectly.  It is set
     'Off' by default.

          TT2Recursion    On

TT2PluginBase
     This is equivalent to the PLUGIN_BASE option.  It allows multiple
     Perl packages to be specified which effectively form a search path
     for loading Template Toolkit plugins.  The default value is
     'Template::Plugin'.

          TT2PluginBase   My::Plugins  Your::Plugins

TT2AutoReset
     This is equivalent to the AUTO_RESET option and is enabled by default.
     It causes any template BLOCK definitions to be cleared before each
     main template is processed.

          TT2AutoReset    Off

TT2CacheSize
     This is equivalent to the CACHE_SIZE option.  It can be used to limit
     the number of compiled templates that are cached in memory.  The
     default value is undefined and all compiled templates will be cached
     in memory.  It can be set to a specified numerical value to define
     the maximum number of templates, or to 0 to disable caching
     altogether.

          TT2CacheSize    64

TT2CompileExt
     This is equivalent to the COMPILE_EXT option.  It can be used to
     specify a filename extension which the Template Toolkit will use for
     writing compiled templates back to disk, thus providing cache
     persistance.

          TT2CompileExt   .ttc

TT2CompileDir
     This is equivalent to the COMPILE_DIR option.  It can be used to
     specify a root directory under which compiled templates should be
     written back to disk for cache persistance.  Any TT2IncludePath
     directories will be replicated in full under this root directory.

          TT2CompileDir   /var/tt2/cache

TT2Debug
     This is equivalent to the DEBUG option which enables Template Toolkit
     debugging.  The main effect is to raise additional warnings when
     undefined variables are used but is likely to be expanded in a future
     release to provide more extensive debugging capabilities.

          TT2Debug	    On

TT2Headers
     Allows you to specify which HTTP headers you want added to the
     response.  Current permitted values are: 'modified' (Last-Modified),
     'length' (Content-Length) or 'all' (all the above).

          TT2Headers	    all

TT2Params
     Allows you to specify which parameters you want defined as template
     variables.  Current permitted values are 'uri', 'env' (hash of
     environment variables), 'params' (hash of CGI parameters), 'pnotes'
     (the request pnotes hash), 'cookies' (hash of cookies) or 'all'.

          TT2Params	    uri env params

     When set, these values can then be accessed from within any template
     processed:

          The URI is [% uri %]

          Server name is [% env.SERVER_NAME %]

          CGI params are:
          <table>
          [% FOREACH key = params.keys %]
             <tr>
          	 <td>[% key %]</td>  <td>[% params.$key %]</td>
             </tr>
          [% END %]
          </table>

TT2ServiceModule
     The modules have been designed in such a way as to make it easy to
     subclass the Template::Service::Apache module to create your own
     custom services.

     For example, the regular service module does a simple 1:1 mapping of
     URI to template using the request filename provided by Apache, but
     you might want to implement an alternative scheme.  You might prefer,
     for example, to map multiple URIs to the same template file, but to
     set some different template variables along the way.

     To do this, you can subclass Template::Service::Apache and redefine
     the appropriate methods.  The template() method performs the task of
     mapping URIs to templates and the params() method sets up the template
     variable parameters.  Or if you need to modify the HTTP headers, then
     headers() is the one for you.

     The TT2ServiceModule option can be set to indicate the name of your
     custom service module.  The following trivial example shows how you
     might subclass Template::Service::Apache to add an additional
     parameter, in this case as the template variable 'message'.

          <perl>
          package My::Service::Module;
          use base qw( Template::Service::Apache );

          sub params {
          	my $self = shift;
              my $params = $self->SUPER::params(@_);
              $params->{ message } = 'Hello World';
              return $params;
          }
          </perl>

          PerlModule          Apache::Template
          TT2ServiceModule    My::Service::Module

BUGS, LIMITATIONS AND FUTURE ENHANCEMENTS
=========================================

Multiple Concurrent Configurations
----------------------------------

   The biggest current limitation is that it's not possible to run multiple
Template Toolkit configurations within the same Apache/mod_perl server
process.  For example, it would be nice to be able to do something like
this:

     PerlModule		Apache::Template

     TT2PostChomp	On
     TT2IncludePath	/usr/local/tt2/shared

     <Location /tom>
     	TT2IncludePath	/home/tom/tt2
     	TT2EvalPerl	On
     </Location>

     <Location /dick>
     	TT2IncludePath	/home/dick/tt2
     	TT2Trim		On
     	TT2PostChomp	Off
     </Location>

   Here, all URI's starting '/tom' should have an effective TT2IncludePath
of:

     TT2IncludePath  /usr/local/tt2/shared /home/tom/tt2

   and those starting '/dick' should be:

     TT2IncludePath  /usr/local/tt2/shared /home/dick/tt2

   Similarly, different options such as TT2PostChomp, TT2EvalPerl, etc.,
should enabled/disabled appropriately for different locations.

   This should be possible using the DIR_MERGE facility, and also
SERVER_MERGE for handling multiple virtual hosts.  It should also be
relatively easy to generate the required Template Toolkit configurations
to support this (having multiple Template::Providers chained together in
different ways would be the obvious way to implement different
TT2IncludePath settings, for example).

   Alas, my extended experimentation with DIR_MERGE and SERVER_MERGE left
my brain scrambled.  It seems to be the case that they both get called
twice at each merge point instead of just once.  I have no idea why this
is the case and it seems to be contrary to the advertised behaviour.
After spending far too long trying to figure it out, I gave up and decided
to leave that feature for a later version.

   Any insight into this matter that anyone can provide would be
gratefully accepted.  I've left the code intact, above.  Simply remove the
'not_used_' prefixes from the DIR/SERVER_CREATE/MERGE subs above and
rebuild to see the problem in action.

Headers and Parameters
----------------------

   I'm in two minds about whether it's better to use full names to specify
TT2Headers, e.g.

     TT2Headers	Content-Length Last-Modified

   or short keyword forms for brevity:

     TT2Header	length modified

   The latter is less typing, but the former are more "offical".  In an
ideal module, we'd do a regex match on /(Content-)?Length/i, for example,
but at present we just stuff 'length' in a hash and don't bother.

   Oh, and I need to add E-Tag as well.  That was in Darren's Grover
module, but I forgot to add it here.  Darn, I know I'm being lazy because
I could have added it in the time it took me to type this.

AUTHOR
======

   Andy Wardley <abw@kfs.org>

   This module has been derived in part from the 'Grover' module by Darren
Chamberlain (darren@boston.com).  Darren kindly donated his code for
integration into the Apache::Template module.

VERSION
=======

   This is version 0.2 of the Apache::Template module.

COPYRIGHT
=========

     Copyright (C) 1996-2001 Andy Wardley.  All Rights Reserved.
     Copyright (C) 1998-2001 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   For further information about the Template Toolkit, see Template,
or http://www.template-toolkit.org/

Apache/Perl module for speed-based content negotiation
******************************************************

NAME
====

   Apache::Throttle - Apache/Perl module for speed-based content
negotiation

SYNOPSIS
========

     PerlTransHandler   Apache::Throttle

     # See the Apache::Throttle::Log manpage for options...
     PerlFixUpHandler   Apache::Throttle::Log

DESCRIPTION
===========

   Apache::Throttle is made up of two separate modules.

   Apache::Throttle is responsible for negotiating the content of certain
requests based on the speed of the connection.  It does this by checking
each request to see if it passes the following criteria:

   * it is a directory,

   * it does not end in a /,

   * and it contains a file named .throttle.

   If the request passes, Apache::Throttle will open the .throttle file
and read a number from it.  This is the time (in seconds) that the
requested file should take to send, ideally.  It then takes the sizes of
each of the files in the directory (ignoring any that start with a period)
and calculates the speed required to send the file to the client in under
the specified number of seconds.  Finally, it predicts the speed of the
current connection and maps the request to point to the largest file that
can still be sent in the ideal time.

   This implementation allows you to create a virtual copy of a file
simply by dropping the different versions of the file into a directory in
your HTML tree with same name that you want the file to have.  These files
can be named anything you want, although they should end in the same
extension for MIME-type mapping to work properly.  A script, `throttleimg'
in this node, is provided which automatically sets up this directory
structure from an existing GIF or JPEG image.

   Apache::Throttle::Log is responsible for measuring the speed that other
requests are transmitted at and calculating the average transmittion speed
for each connection.  This information is used by Apache::Throttle by
default, but it can also be accessed by other modules.  See
Apache/Throttle/Log, for more information.

OPTIONS
=======

   This option can be set with the PerlSetVar operative in one of your
Apache configuration files.

ThrottleDebug
     Prints extra debugging information to the error log.

PredictSub
     Sets the subroutine called to predict a connection's speed.  This
     defaults to Apache::Throttle::Log::predict_speed.  If the package
     that the specified subroutine is in can be determined, it will be
     required automatically.

IDEAS
=====

   This doesn't only work with images.  It can also be used to send
different quality audio files, animations, etc.  You can even use a
directory named index.html if you want, with two different HTML pages for
high- and low-bandwidth users.  The possibilities are endless.  If you
think you've used this is a way no one has though of before, mail me.  I'd
love to hear about it.

AUTHOR
======

   Don Schwarz <dons@xnet.com>

SEE ALSO
========

   See Apache/Throttle/Log, `throttleimg' in this
node, `mod_perl' in this node

COPYRIGHT
=========

   Copyright (c) 1998 Don Schwarz. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Apache/Perl module to determine average speed
*********************************************

NAME
====

   Apache::Throttle::Log - Apache/Perl module to determine average speed

SYNOPSIS
========

     <Location /images>
       PerlSetVar       MaxUsers     100
       PerlSetVar       MinSize      100000
       PerlSetVar       MinDuration  0.1
       PerlSetVar       IDSub        Website::Session::session_id
       PerlTypeHandler  Apache::Throttle::Log
     </Location>

DESCRIPTION
===========

   Apache::Throttle::Log measures the speed that requests are transmitted
at and can calculate the average transmittion speed for a connection.

   It isn't particularly accurate yet, but seems to be close enough for
most applications.  If you know of a better way to measure the speed feel
free to send me suggestions, patches, etc.

OPTIONS
=======

   These options can be set with the PerlSetVar operative in one of your
Apache configuration files.

ThrottleDebug
     Prints extra debugging information to the error log.

MaxUsers
     Clear the speed hash when it reaches the specified number of users.
     I'm still looking for a better way of doing this.  If anyone has any
     suggestions, feel free to tell me.  This option is strongly
     recommended.

LogTypes
     Only log requests with a MIME-type that matches this regular
     expression.  This is useful for only logging "^image/" if you plan to
     serve images and the speeds for other large, compressable files are
     throwing off your averages.  It's probably much more efficient to
     keep all your images under one directory and just put a <Location>
     container around the handler definition though.

MinSize
     The minimum size in bytes that a request has to be for it to be
     logged.

MinDuration
     The minimum time in seconds that a request has to take for it to be
     logged.

StoreSpeeds
     The number of speeds to store for each connection.  These are averaged
     together to predict the speed of the next request.

ContinueChecking
     If this is set to a true value, Apache::Throttle::Log will continue
     logging requests from a user forever.  If unspecified or set false,
     however, it will only log as many requests as StoreSpeeds is set to,
     and then DECLINED requests from the same user.  This should be used
     when speeds are fairly constant and Apache::Throttle is putting a
     strain on your webserver.

IDSub
     This specifies the subroutine that Apache::Throttle::Log will get the
     hash key from.  The subroutine will be called with one argument: the
     Apache request object, and will be expected to return a scalar.  This
     scalar will be used as the hash key to store the connection
     information.  Defaults to the remote IP address for the request.

AUTHOR
======

   Don Schwarz <dons@xnet.com>

SEE ALSO
========

   See Apache/Throttle, `mod_perl' in this node

COPYRIGHT
=========

   Copyright (c) 1998 Don Schwarz. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

an Apache (mod_perl) TransHandler
*********************************

NAME
====

   Apache::TimedRedirect - an Apache (mod_perl) TransHandler

SYNOPSIS
========

     use Apache::TimedRedirect;

     requires TimePeriod be installed (go to nearest CPAN)
     requires Apache have mod_perl installed.

     httpd.conf entry...
     **** NOTE ***
     CANNOT be inside <LOCATION></LOCATION> tags
     PerlTransHandler Apache::TimedRedirect
     PerlSetVar B<redirecturl> http://www.somewhere.far/
     PerlSetVar B<timewindow> 'hr {6am-8pm}'
     PerlSetVar B<uriregex> foo|bar|do or maybe \..*(foo)>
     PerlSetVar B<log> 1
     PerlSetVar B<excludeip> 127.0.0.0

DESCRIPTION
===========

   Apache::TimedRedirect is a mod_perl TransHandler module that allows the
configuration of a timed redirect. In other words if someone enters a a
website  and the URI matches a regex AND it is within a certain time
period they will be redirected somewhere else.

   It was first created to 'politely' redirect visitors away from database
driven sections of a website while the databases were being refreshed.

PerlSetVar's
------------

   *redirecturl* - the place where visitors are sent if *timewindow* and
*uriregex* are true.

   *timewindow* - the time period(s) at which redirect should place. The
format is detailed in Time::Period manpage.

   *uriregex* a perl regex describing the URI constraints for redirection

   log log info via STDERR .

   *excludeip* host IP address (XXX.XXX.XXX.XXX) of a host that is allowed
to bypass redirection. This is a literal ip not a regex.

   Remember that this is embedding itself in the your Apache webserver so
you should test before committing to production. We have used it with
Apache 1.3.0, 1.2.5 with mod_perl 1.12 and 1.15 in medium traffic sites
(400k-500k hits weekly).

AUTHOR
======

   Peter G. Marshall, mitd@mitd.com Thanks to Patrick Ryan for
Time::Period that made this a snap.

   Copyright (c) 1998 Peter G. Marshall. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself

SEE ALSO
========

   `perl(1)' in this node, `Time::Period(3)' in this node, `mod_perl(1)'
in this node

Tracks hits and bytes transferred on a per-user basis
*****************************************************

NAME
====

   Apache::Traffic - Tracks hits and bytes transferred on a per-user basis

SYNOPSIS
========

     # Place this in your Apache's httpd.conf file
     PerlLogHandler Apache::Traffic

DESCRIPTION
===========

   This module tracks the total number of hits and bytes transferred per
day by the Apache web server, on a per-user basis.  This allows for
real-time statistics without having to parse the log files.

   After installation, add this to your Apache's httpd.conf file and
restart the server:

     PerlLogHandler	Apache::Traffic

   The statistics are then available through the 'traffic' script, which
is included in this distribution.  See the section VIEWING STATISTICS for
more details.

PREREQUISITES
=============

   You need to have compiled mod_perl with the LogHandler hook in order to
use this module. Additionally, the following modules are required:

     o IPC::Shareable
     o IPC::SysV
     o DB_File
     o Date::Parse

   Your OS must also support SysV IPC (shared memory and semaphores).  If
this is not the case, this module will be useless to you.

INSTALLATION
============

   To install this module, move into the directory where this file is
located and type the following:

     perl Makefile.PL
     make
     make test
     make install

   This will install the module into the Perl library directory.

   Once installed, you will need to modify your web server's configuration
file so it knows to use Apache::Traffic during the logging phase:

     PerlLogHandler Apache::Traffic

   Restart your web server.

   As of this writing, there is a problem with IPC::Shareable which will
cause segmentation faults in httpd processes if Apache::Traffic is run
long enough (at least this is the case under Linux).  This distribution
contains a patch named 'share.patch', which will fix the problem.

   If Apache::Traffic does not appear to work correctly (look in your
server's error_log for problems), make sure the semaphore and shared
memory segments are not already allocated for another purpose.  If this is
the case, you can change the constants SHMKEY, SEMKEY, and DBPATH at the
top of the Apache::Traffic module, and reinstall.

HOW IT WORKS
============

   Each time a request is served, the Apache::Traffic log handler is
called which increments the byte and hit totals for the owner of the
resource.

   The owner of the resource is determined in the following way:

     o If the Perl variable Owner has been set for the directory, its
       value is used.  For example:

     <Directory /home/root/www/mark>
       PerlSetVar Owner mark
     </Directory>

     This would declare user mark as the owner of everything under
     the specified directory.  The value can be either the username
     or UID of the user.

     This value can also be a fake user (i.e. a username which is
     not present in the passwd file).  In this case, the username is
     stored (rather than the UID).

     o If the request is to a virtual host, the owner of the document
       root is used.

     o If neither of the above methods work, the owner of the file
       is used.

   The hit and byte total information is stored in shared memory to
minimize processing.  On the first request of each day, all previous data
in shared memory is automatically moved to permanent storage.  This means
that no more than one day's worth of information is ever stored in shared
memory, and prevents performance degradation as data accumulates.  This
separation of data is transparent from the end-user perspective.

   If you would rather not have the data moved into the dbm file, you can
set USE_DBM to 0 at the top of the Traffic.pm module and reinstall.

   Shared memory segments are not preserved through reboots.  If you
reboot your machine multiple times a day, Apache::Traffic will be of
questionable value to you.  I run Linux, so of course, I only reboot when
I've upgraded the OS. ;-)  This area may be improved in the future (at
least for orderly shutdowns).

VIEWING STATISTICS
==================

   A script named 'traffic' is included in this distribution, which allows
you to view the totals for a given user.  Note that this script will not
run properly until Apache::Traffic has recorded at least one page request.

   The basic syntax for the script is:

     traffic [options] [username]

   If username is not specified, the effective UID of the person running
the script is used.  By default, only data for the current day is
displayed.

   The following options are supported:

     -start=starting_date

     Specifies the starting date that you wish to see data for.  The
     date specifications can take any format supported by the
             Date::Parse module.  If -end is not specified, all data between
             -start and the current day is displayed.

     -end=ending_date

     Specifies the ending date that you wish to see data for.

     -days=num_days

     Specifies the number of days you want to see information for
             relative to the value of -start (or the current day if -start
             is not specified).  The value can be either positive
             or negative.

     -user=username

     Specifies the user you want to see data for.  Multiple
             -user specifications are allowed.  The users can also be
             specified as non-option arguments.  Both UIDs and usernames
             are allowed.

     -all

     Displays all data present within the given time period.

       -reverse

     If present, the information is sorted in descending order based
     on date.

     -units=unit

     Specifies the unit to display transfer totals in.  Acceptable
             values are 'Bytes', "Kilobytes', 'Megabytes', or 'Gigabytes'.
             Only the first character of the unit need be specified.  The
             default is Bytes.

     -summary

     If -summary is present, aggregate totals for the period
             being viewed are displayed, rather than daily totals.

     -n

     If the -n option is present, the report displays UIDs rather than
     converting them to usernames.  In the case of a "fake" user,
             the username will still be displayed (which is a way to tell
             is a user is fake or not).

     -remove

     If the -remove option is present, all data within the specified
             time period is permanently removed.  Only root is allowed to
     perform this operation (see the SECURITY NOTES section though).
             The operation must be confirmed prior to being carried out.

ACCESSING INFORMATION DIRECTLY
==============================

   If the supplied traffic script is not sufficient for your needs, you
may access the raw data directly.  The following functions are available
for import into your scripts.

     fetch([START], [END], [WANTUID], [ALL], [USER LIST])

     This function retrieves all data between START and END times,
             inclusive, for the users specified in USER LIST. Both START and
             END should be UTC timestamps.  The function automatically
             normalizes the timestamps to be on day boundaries.

     If WANTUID is true, usernames are not looked up.  If ALL is true,
             data for all users is returned and USER_LIST is ignored.
             If ALL is true, data for all users is returned and
             USER_LIST is ignored.

     On success, the function returns a complex hash reference, which
             contains the requested data:

     use Apache::Traffic qw( fetch remove error );

     $ref = fetch(time, time, 0, 0, 'maurice');
     foreach $day (%$ref) {
       foreach $user (%{ $ref->{$day} }) {
                         print scalar gmtime $day, " $user\n";
                         print "  BYTES: $ref->{$day}{$user}{bytes}\n";
                         print "   HITS: $ref->{$day}{$user}{hits}\n\n";
                       }
     }

     Note that the timestamps are stored internally in GM time,
             although START and END should be in local time.  We do this
             so we don't have to worry about daylight savings.

     The function returns undef on error, in which case you can call
     the error() function to determine what went wrong.

     remove([START], [END])

     This function removes all data between the START and END times,
     inclusive.

     The fuction returns true on success and undef on error, in which
     case you can call the error() function to determine what went
     wrong.

     error()

     Returns a string describing the last error condition encountered.

SECURITY NOTES
==============

   By default, the shared memory segments, semaphores, and DBM file are
created with permissions of 0644.  However, these resources must be owned
by whatever user the server runs as (normally user 'nobody').  This means
that your users could create CGI scripts to play with the data.  For this
reason, the information maintained by Apache::Traffic should not be relied
upon for auditing purposes, and is intended mainly for use in friendly
environments.

AUTHOR
======

   Copyright (C) 1997, Maurice Aubrey <maurice@hevanet.com>. All rights
reserved.

   This module is free software; you may redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1), mod_perl(3)

An Apache+mod_perl Trans Handler
********************************

NAME
====

   Apache::TransLDAP - An Apache+mod_perl Trans Handler

SYNOPSIS
========

     PerlSetVar LDAPServer ldaphost.my.org   # Default: localhost
     PerlSetVar LDAPPort   389               # Default: 389
     PerlSetVar LDAPBase   o=My,c=US         # Default: Empty String
     PerlSetVar UIDAttr    uid               # Default: uid
     PerlSetVar URIAttr    labeledURI        # Default: labeledURI

     PerlTransHandler Apache::TransLDAP

DESCRIPTION
===========

   This module is designed to work with mod_perl and my Net::LDAPapi
module (http://www.wwa.com/~donley/).  Future versions will use PerLDAP.

   This is mostly an example of how a Trans handler can be implemented in
Perl.  Be sure to enable Trans handlers when configuring and installing
mod_perl.

   I welcome feedback on this module and any others I've developed.

AUTHOR
======

   Clayton Donley <donley@wwa.com> http://www.wwa.com/~donley/

COPYRIGHT
=========

   Copyright (c) 1998 Clayton Donley - All Rights Reserved

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

URI component parsing and unparsing
***********************************

NAME
====

   Apache::URI - URI component parsing and unparsing

SYNOPSIS
========

     use Apache::URI ();
     my $uri = $r->parsed_uri;

     my $uri = Apache::URI->parse($r, "http://perl.apache.org/");

DESCRIPTION
===========

   This module provides an interface to the Apache *util_uri* module and
the *uri_components* structure.

METHODS
=======

Apache::parsed_uri
     Apache will have already parsed the requested uri components, which
     can be obtained via the *parsed_uri* method defined in the Apache
     class.  This method returns an object blessed into the *Apache::URI*
     class.

          my $uri = $r->parsed_uri;

parse
     This method will parse a URI string into uri components which are
     stashed in the *Apache::URI* object it returns.

          my $uri = Apache::URI->parse($r, "http://www.foo.com/path/file.html?query+string");

     This method is considerably faster than using URI::URL:

          timethese(5000, {
          	C => sub { Apache::URI->parse($r, $test_uri) },
          	Perl => sub { URI::URL->new($test_uri) },
          });

          Benchmark: timing 5000 iterations of C, Perl...
            C:  1 secs ( 0.62 usr  0.04 sys =  0.66 cpu)
            Perl:  6 secs ( 6.21 usr  0.08 sys =  6.29 cpu)

unparse
     This method will join the uri components back into a string version.

          my $string = $uri->unparse;

scheme
          my $scheme = $uri->scheme;

hostinfo
          my $hostinfo = $uri->hostinfo;

user
          my $user = $uri->user;

password
          my $password = $uri->password;

hostname
          my $hostname = $uri->hostname;

port
          my $port = $uri->port;

path
          my $path = $uri->path;

rpath
     Returns the path minus path_info.

          my $path = $uri->rpath;

query
          my $query = $uri->query;

fragment
          my $fragment = $uri->fragment;

AUTHOR
======

   Doug MacEachern

SEE ALSO
========

   perl(1).

A Lightweight Publishing System for Apache
******************************************

NAME
====

   Apache::UploadSvr - A Lightweight Publishing System for Apache

SYNOPSIS
========

DESCRIPTION
===========

   This module implements a small publishing system for a web server with
authentication, simple security, preview, directory viewer and an interface
to delete files. The whole system is actually running software on
www.kulturbox.de at the time of publishing (i.e. Summer 1998).

   The author is looking for somebody to take this code over for
maintainance.

CONFIGURATION
=============

   httpd.conf:

     PerlSetVar Auth_DBI_data_source dbi:mSQL:authen
     PerlSetVar Auth_DBI_pwd_table   usertable
     PerlSetVar Auth_DBI_grp_table   grouptable
     PerlSetVar Auth_DBI_uid_field   user
     PerlSetVar Auth_DBI_grp_field   group
     PerlSetVar Auth_DBI_pwd_field   password
     PerlSetVar stageuri /STAGE
     PerlSetVar Apache_UploadSvr_Usermgr "Apache::UploadSvr::User"
     PerlSetVar Apache_UploadSvr_myuri /perl/user/up
     PerlSetVar Apache_UploadSvr_transdir /usr/local/apache/trans
     PerlSetVar Apache_UploadSvr_trashdir /usr/local/apache/trash

     <Files "...">
       PerlSetVar DirCache .dircache
       SetHandler perl-script
       PerlHandler Apache::UploadSvr::Directory
       AuthName stadtplandienst
       AuthType Basic
       PerlAuthenHandler Apache::AuthenDBI
       require valid-user
     </Files>

     <Location /perl/user/up>
       PerlHandler Apache::UploadSvr
     </Location>

   Change the permissions for the whole document tree to give the server
write access.

SECURITY
========

EXPORT
======

BUGS
====

COPYRIGHT
=========

   The application and accompanying modules are Copyright KULTURBOX,
Berlin.  It is free software and can be used, copied and redistributed at
the same terms as perl itself.

AUTHOR
======

   Andreas Koenig <koenig@kulturbox.de>

Identify users and permissions Apache::UploadSvr
************************************************

NAME
====

   Apache::UploadSvr::User - Identify users and permissions
Apache::UploadSvr

SYNOPSIS
========

   Apache::UploadSvr::User->new($mgr);

DESCRIPTION
===========

   This class implements a mapping between user-ID and user attributes.
The backend is provided by a mSQL-1 database with the following structure:

     CREATE TABLE usertable (
       user CHAR(12) NOT NULL PRIMARY KEY,
       email CHAR(64),
       firstname CHAR(32),
       lastname CHAR(32),
       fullname CHAR(64),
       salut CHAR(4),
       lastlogin CHAR(10),
       introduced CHAR(10),
       password CHAR(13),
       changedon CHAR(10),
       changedby CHAR(10)
     )

   user corresponds to the username with which the users identify in the
authentication stage. email is their email address where the transaction
tickets are delivered to. `lastname' is their family name.  <fullname> is
whatever the fullname is composed of in the local culture.  `salut' is the
salutation like `Herr' or `Mister'. `lastlogin' is the timestamp that is
updated with every request. `introduced' is the timestamp when the user
got registered (not used in this uploadserver).  password is the crypted
password in the default upload server. If the authentication handler uses
a different table, then this field is not needed. `changedon' and
`changedby' are not used in this application, they are only used as
interesting facts for the administrator.

     CREATE TABLE perms (
       user CHAR(12),
       permitted CHAR(32)
     )

   This table has a 1 to N mapping of users to directories they have write
access to.

   The constructor ->new takes as a single argument an Apache::UploadSvr
object and returns an object that has the above described fields as object
attributes. The attribute `permitted' is computed from the `perms' table
so that its value is an anonymous list of the directories the user has
write permission to. A typical structure of such an object would be:

     bless( {
       'introduced' => 875601758,
       'password' => 'rtthXtbR5tjit',
       'fullname' => 'Andreas J. König',
       'changedby' => 'andreas',
       'lastname' => 'König',
       'changedon' => 875601758,
       'email' => 'k',
       'firstname' => 'Andreas',
       'salut' => 'Herr',
       'lastlogin' => '0903739665',
       'permitted' => [
                        '/'
                      ],
       'user' => 'andreas'
     }, 'Apache::UploadSvr::User' )

   The method ->has_perms($obj) returns true if the current user has write
access to a file or dircetory. What counts here are database entries, not
file system permissions.

CONFIGURATION
=============

SECURITY
========

BUGS
====

AUTHOR
======

   Andreas Koenig <koenig@kulturbox.de>

COPYRIGHT, LICENSE
==================

   These programs or modules are Copyright (C) 1997-1998 Kulturbox,
Berlin, Germany.

   They are free software; you can redistribute them, use and/or modify
them under the same terms as Perl itself.

Emulate the mod_usertrack apache module
***************************************

NAME
====

   Apache::Usertrack - Emulate the mod_usertrack apache module

SYNOPSIS
========

     PerlFixupHandler Apache::Usertrack

     PerlSetVar Usertrack On

PREREQUISITES
=============

   This module uses the Time::HiRes module.

DESCRIPTION
===========

   To be written. :-)

BUGS / TODO
===========

   We don't do expire stuff yet.

   Documentation.

   Support for systems without gettimeofday.

   Patches are most welcome! :-)  See mod_usertrack.c in the
<apachedist>/src/modules/standard/ directory for 'the original' it's quite
simpel C code!

AUTHOR
======

   Copyright (C) 1998, Ask Bjoern Hansen <ask@netcetera.dk>. All rights
reserved. This module is free software; you may redistribute it and/or
modify it under the same terms as Perl itself.

SEE ALSO
========

   perl(1), mod_perl(3)

Interface to Apache C util functions
************************************

NAME
====

   Apache::Util - Interface to Apache C util functions

SYNOPSIS
========

     use Apache::Util qw(:all);

DESCRIPTION
===========

   This module provides a Perl interface to some of the C utility functions
available in Perl.  The same functionality is avaliable in libwww-perl, but
the C versions are faster:

     use Benchmark;
     timethese(1000, {
         C => sub { my $esc = Apache::Util::escape_html($html) },
         Perl => sub { my $esc = HTML::Entities::encode($html) },
     });

     Benchmark: timing 1000 iterations of C, Perl...
             C:  0 secs ( 0.17 usr  0.00 sys =  0.17 cpu)
          Perl: 15 secs (15.06 usr  0.04 sys = 15.10 cpu)

     use Benchmark;
     timethese(10000, {
         C => sub { my $esc = Apache::Util::escape_uri($uri) },
         Perl => sub { my $esc = URI::Escape::uri_escape($uri) },
     });

     Benchmark: timing 10000 iterations of C, Perl...
             C:  0 secs ( 0.55 usr  0.01 sys =  0.56 cpu)
          Perl:  2 secs ( 1.78 usr  0.01 sys =  1.79 cpu)

FUNCTIONS
=========

escape_html
     This routine replaces unsafe characters in $string with their entity
     representation.

          my $esc = Apache::Util::escape_html($html);

escape_uri
     This function replaces all unsafe characters in the $string with their
     escape sequence and returns the result.

          my $esc = Apache::Util::escape_uri($uri);

unescape_uri
     This function decodes all %XX hex escape sequences in the given URI.

          my $unescaped = Apache::Util::unescape_uri($safe_uri);

unescape_uri_info
     This function is similar to unescape_uri() but is specialized to
     remove escape sequences from the query string portion of the URI. The
     main difference is that it translates the "+" character into spaces
     as well as recognizing and translating the hex escapes.

     Example:

          $string = $r->uri->query;
          my %data = map { Apache::Util::unescape_uri_info($_) }
                       split /[=&]/, $string, -1;

          This would correctly translate the query string
          ``name=Fred+Flintstone&town=Bedrock'' into the hash:

          data => 'Fred Flintstone',
          town => 'Bedrock'

parsedate
     Parses an HTTP date in one of three standard forms:

          Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, updated by RFC 1123

          Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036

          Sun Nov  6 08:49:37 1994       ; ANSI C's asctime() format

     Example:

          my $secs = Apache::Util::parsedate($date_str);

ht_time
     Format a time string.

     Examples:

          my $str = Apache::Util::ht_time(time);

          my $str = Apache::Util::ht_time(time, "%d %b %Y %T %Z");

          my $str = Apache::Util::ht_time(time, "%d %b %Y %T %Z", 0);

size_string
     Converts the given file size into a formatted string. The size given
     in the string will be in units of bytes, kilobytes, or megabytes,
     depending on the size.

          my $size = Apache::Util::size_string -s $r->finfo;

validate_password
     Validate a plaintext password against a smashed one.  Use either
     crypt() (if available), ap_MD5Encode() or ap_SHA1Encode depending
     upon the format of the smashed input password.

     Returns true if they match, false otherwise.

          if (Apache::Util::validate_password("slipknot", "aXYx4GnaCrDQc")) {
              print "password match\n";
          }
          else {
              print "password mismatch\n";
          }

AUTHOR
======

   Doug MacEachern

SEE ALSO
========

   perl(1).

Visual System and Apache Server Monitor
***************************************

NAME
====

   Apache::VMonitor - Visual System and Apache Server Monitor

SYNOPSIS
========

     # mod_status should be compiled in (it is by default)
     ExtendedStatus On

     # Configuration in httpd.conf
     <Location /sys-monitor>
       SetHandler perl-script
       PerlHandler Apache::VMonitor
     </Location>

     # startup file or <Perl> section:
     use Apache::VMonitor();
     $Apache::VMonitor::Config{BLINKING} = 1;
     $Apache::VMonitor::Config{REFRESH}  = 0;
     $Apache::VMonitor::Config{VERBOSE}  = 0;
     $Apache::VMonitor::Config{SYSTEM}   = 1;
     $Apache::VMonitor::Config{APACHE}   = 1;
     $Apache::VMonitor::Config{PROCS}    = 1;
     $Apache::VMonitor::Config{MOUNT}    = 1;
     $Apache::VMonitor::Config{FS_USAGE} = 1;
     $Apache::VMonitor::Config{SORT_BY}  = 'size';

     $Apache::VMonitor::PROC_REGEX = join "\|", qw(httpd mysql squid);

DESCRIPTION
===========

   This module emulates the reporting functionalities of top(), mount(),
df() and ifconfig() utilities. It has a visual alert capabilities and
configurable automatic refresh mode. All the sections can be shown/hidden
dynamically through the web interface.

   The are two main modes:

   * Multi processes mode

     All system processes and information are shown. See the detailed
     description of the sub-modes below.

   * Single process mode

     An indepth information about a single process is shown.

     If the chosen process is an Apache/mod_perl process, the following
     info is displayed:

     Process type (child or parent), status of the process (starting,
     reading, sending waiting and etc), how long the current request is
     processed or last was processed.

     Bytes transferred and requests served perl child and per slot.

     Cpu times used by process: total, utime, stime, cutime, cstime.

     For all processes:

     General process info:

     UID, GID, State, TTY, Command line args

     Memory Usage: Size, Share, VSize, RSS

     Memory Segments Usage: text, shared lib, date and stack.

     Memory Maps: start-end, offset, device_major:device_minor, inode,
     perm, library path.

     Loaded libraries sizes.

   Other available modes within 'Multi processes mode'.

refresh mode
     From within a displayed monitor (by clicking on a desired refresh
     value) or by setting of *$Apache::VMonitor::Config{REFRESH}* to a
     number of seconds between refreshes you can control the refresh rate.
     e.g:

          $Apache::VMonitor::Config{REFRESH} = 60;

     will cause the report to be refreshed every single minute.

     Note that 0 (zero) turns automatic refreshing off.

top(1) emulation (system)
     Just like top() it shows current date/time, machine uptime, average
     load, all the system CPU and memory usage: CPU Load, Mem and Swap
     usage.

     The top() section includes a swap space usage visual alert
     capability. The color of the swap report will be changed:

          1) 5Mb < swap < 10 MB             color: light red
          2) 20% < swap (swapping is bad!)  color: red
          3) 70% < swap (swap almost used!) color: red + blinking

     Note that you can turn off blinking with:

          $Apache::VMonitor::Config{BLINKING} = 0;

     The module doesn't alert when swap is being used just a little (<5Mb),
     since it happens most of the time, even when there is plenty of free
     RAM.

     If you don't want the system section to be displayed set:

          $Apache::VMonitor::Config{SYSTEM} = 0;

     The default is to display this section.

top(1) emulation (Apache/mod_perl processes)
     Then just like in real top() there is a report of the processes, but
     it shows all the relevant information about httpd processes only! The
     report includes the status of the process (starting, reading, sending
     waiting and etc), process' id, time since current request was started,
     last request processing time, size, shared, virtual and resident size.
     It shows the last client's IP and Request (only 64 chars, as this is
     the maximum length stored by underlying Apache core library).

     You can sort the report by any column, see the `CONFIGURATION|' in
     this node section for details.

     At the end there is a calculation of the total memory being used by
     all httpd processes as reported by kernel, plus a result of an attempt
     to approximately calculate the real memory usage when sharing is in
     place. How do I calculate this:

     1. For each process sum up the difference between shared and system
     memory.

     2. Now if we add the share size of the process with maximum shared
     memory, we will get all the memory that actually is being used by all
     httpd processes but the parent process.

     Please note that this might be incorrect for your system, so you use
     this number on your own risk. I have verified this number, by writing
     it down and then killing all the servers. The system memory went down
     by approximately this number. Again, use this number wisely!

     If you don't want the Apache section to be displayed set:

          $Apache::VMonitor::Config{APACHE} = 0;

     The default is to display this section.

top(1) emulation (any processes)
     This section, just like the Apache/mod_perl processes section,
     displays the information in a top(1) fashion. You use a regular
     expression for processes you want to see.

     For each group of matched processes, just like with
     Apache/mod_processes a total size and estimation of the real memory
     taken into account the shared memory, is displayed.

     If you want the Apache section to be displayed a REGEX for processes
     to match. e.g if you want to see http, `mysql' and `squid' processes,
     set:

          $Apache::VMonitor::PROC_REGEX = join "\|", qw(httpd mysql squid);

     and

          $Apache::VMonitor::Config{PROCS} = 1;

     The default is not to display this section.

mount(1) emulation
     This section reports about mounted filesystems, the same way as if you
     have called mount() with no parameters.

     If you want the mount() section to be displayed set:

          $Apache::VMonitor::Config{MOUNT} = 1;

     The default is NOT to display this section.

df(1) emulation
     This section completely reproduces the df() utility. For each mounted
     filesystem it reports the number of total and available blocks (for
     both superuser and user), and usage in percents.

     In addition it reports about available and used filenodes in numbers
     and percents.

     This section has a capability of visual alert which is being triggered
     when either some filesystem becomes more than 90% full or there are
     less 10% of free filenodes left. When that happens the filesystem
     related line will go bold and red and a mounting point will blink if
     the blinking is turned on. You can the blinking off with:

          $Apache::VMonitor::Config{BLINKING} = 0;

     If you don't want the df() section to be displayed set:

          $Apache::VMonitor::Config{FS_USAGE} = 0;

     The default is to display this section.

abbreviations and hints
     The monitor uses many abbreviations, which might be knew for you. If
     you enable the VERBOSE mode with:

          $Apache::VMonitor::Config{VERBOSE} = 1;

     this section will reveal all the full names of the abbreviations at
     the bottom of the report.

     The default is NOT to display this section.

CONFIGURATION
=============

   To enable this module you should modify a configuration in httpd.conf,
if you add the following configuration:

     <Location /sys-monitor>
       SetHandler perl-script
       PerlHandler Apache::VMonitor
     </Location>

   The monitor will be displayed when you request
http://localhost/sys-monitor or alike.

   You can control the behavior of this module by configuring the
following variables in the startup file or inside the *<Perl*> section.

   Module loading:

     use Apache::VMonitor();

   Monitor reporting behavior:

     $Apache::VMonitor::Config{BLINKING} = 1;
     $Apache::VMonitor::Config{REFRESH}  = 0;
     $Apache::VMonitor::Config{VERBOSE}  = 0;

   Control over what sections to display:

     $Apache::VMonitor::Config{SYSTEM}   = 1;
     $Apache::VMonitor::Config{APACHE}   = 1;
     $Apache::VMonitor::Config{PROCS}    = 1;
     $Apache::VMonitor::Config{MOUNT}    = 1;
     $Apache::VMonitor::Config{FS_USAGE} = 1;

   Control the sorting of the mod_perl processes report. You can sort them
by one of the following columns: "pid", "mode", "elapsed", "lastreq",
"served", "size", "share", "vsize", "rss", "client", "request".

     $Apache::VMonitor::Config{SORT_BY}  = 'size';

   A regex to match processes for 'PROCS' section:

     $Apache::VMonitor::PROC_REGEX = join "\|", qw(httpd mysql squid);

   Read the `DESCRIPTION|' in this node section for a complete explanation
of each of these variables.

DYNAMIC RECONFIGURATION
=======================

   `Apache::VMonitor' allows you to dynamically turn on and off all the
sections and enter a verbose mode that explains each section and the used
abbreviations. These dynamic settings stored in the URI and not on the
server side.

PREREQUISITES
=============

   You need to have *Apache::Scoreboard* installed and configured in
httpd.conf, which in turn requires mod_status to be installed. You also
have to enable the extended status, for this module to work properly. In
httpd.conf add:

     ExtendedStatus On

   You also need *Time::HiRes* and *GTop* to be installed.

   And of course you need a running mod_perl enabled apache server.

BUGS
====

TODO
====

   I want to include a report about open file handlers per process to
track file handlers leaking. It's easy to do that by just reading them
from `/proc/$pid/fd' but you cannot do that unless you are root. `libgtop'
doesn't have this capability - if you come up with solution, please let me
know. Thanks!

SEE ALSO
========

   See Apache, `mod_perl' in this node, see
Apache/Scoreboard, GTop,

AUTHORS
=======

   Stas Bekman <stas@stason.org>

COPYRIGHT
=========

   The Apache::VMonitor module is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

a monitor for hanging processes
*******************************

NAME
====

   Apache::Watchdog::RunAway - a monitor for hanging processes

SYNOPSIS
========

     stop_monitor();
     start_monitor();
     start_detached_monitor();

     $Apache::Watchdog::RunAway::TIMEOUT = 0;
     $Apache::Watchdog::RunAway::POLLTIME = 60;
     $Apache::Watchdog::RunAway::DEBUG = 0;
     $Apache::Watchdog::RunAway::LOCK_FILE = "/tmp/safehang.lock";
     $Apache::Watchdog::RunAway::LOG_FILE = "/tmp/safehang.log";
     $Apache::Watchdog::RunAway::SCOREBOARD_URL = "http://localhost/scoreboard";

DESCRIPTION
===========

   A module that monitors hanging Apache/mod_perl processes. You define
the time in seconds after which the process to be counted as hanging. You
also control the polling time between check to check.

   When the process is considered as 'hanging' it will be killed and the
event logged into a log file. The log file is being opened on append, so
you can basically defined the same log file that uses Apache.

   You can start this process from startup.pl or through any other method.
(e.g. a crontab). Once started it runs indefinitely, untill killed.

   You cannot start a new monitoring process before you kill the old one.
The lockfile will prevent you from doing that.

   Generally you should use the `amprapmon' program that bundled with this
module's distribution package, but you can write your own code using the
module as well. See the amprapmon manpage for more info about it.

   Methods:

   * stop_monitor()

     Stop the process based on the PID in the lock file. Remove the lock
     file.

   * start_monitor()

     Starts the monitor in the current process. Create the lock file.

   * start_detached_monitor()

     Starts the monitor in a forked process. (used by `amprapmon'). Create
     the lock file.

WARNING
=======

   This is an alpha version of the module, so use it after a testing on
development machine.

   The most critical parameter is the value of
*$Apache::Watchdog::RunAway::TIMEOUT* (see `CONFIGURATION|' in this node),
since the processes will be killed without waiting for them to quit (since
they hung).

CONFIGURATION
=============

   Install and configure `Apache::Scoreboard' module

     <Location /scoreboard>
        SetHandler perl-script
        PerlHandler Apache::Scoreboard::send
        order deny,allow
     #    deny from all
     #    allow from ...
     </Location>

   Configure the Apache::Watchdog::RunAway parameters:

     $Apache::Watchdog::RunAway::TIMEOUT = 0;

   The time in seconds after which the process is considered hanging. 0
means deactivated. The default is 0 (deactivated).

     $Apache::Watchdog::RunAway::POLLTIME = 60;

   Polling intervals in seconds. The default is 60.

     $Apache::Watchdog::RunAway::DEBUG = 0;

   Debug mode (0 or 1). The default is 0.

     $Apache::Watchdog::RunAway::LOCK_FILE = "/tmp/safehang.lock";

   The process lock file location. The default is */tmp/safehang.lock*

     $Apache::Watchdog::RunAway::LOG_FILE = "/tmp/safehang.log";

   The log file location. Since it flocks the file, you can safely use the
same log file that Apache uses, so you will get the messages about killed
processes in file you've got used to. The default is */tmp/safehang.log*

     $Apache::Watchdog::RunAway::SCOREBOARD_URL = "http://localhost/scoreboard";

   Since the process relies on scoreboard URL configured on any of your
machines (the URL returns a binary image that includes the status of the
server and its children), you must specify it. This enables you to run the
monitor on one machine while the server can run on the other machine. The
default is URI is *http://localhost/scoreboard*.

   Start the monitoring process either with:

     start_detached_monitor()

   that starts the monitor in a forked process or

     start_monitor()

   that starts the monitor in the current process.

   Stop the process with:

   stop_monitor()

   The distribution arrives with `amprapmon' program that provides an rc.d
like or apachectl interface.

   Instead of using a Perl interface you can start it from the command
line:

     amprapmon start

   or from the *startup.pl* file:

     system "amprapmon start";

   or

     system "amprapmon stop";
     system "amprapmon start";

   or

     system "amprapmon restart";

   As mentioned before, once started it sholdn't be killed. So you may
leave only the `system "amprapmon start";' in the *startup.pl*

   You can start the `amprapmon' program from crontab as well.

TUNING
======

   The most important part of configuration is choosing the right timeout
(aka $Apache::Watchdog::RunAway::TIMEOUT) parameter. You should try this
code that hangs and see the process killed after a timeout if the monitor
is running.

     my $r = shift;
     $r->send_http_header('text/plain');
     print "PID = $$\n";
     $r->rflush;
     while(1){
       $r->print("\0");
       $r->rflush;
       $i++;
       sleep 1;
     }

TROUBLESHOOTING
===============

   The module relies on correctly configured `/scoreboard' location URI.
If it cannot fetch the URI, it queitly assumes that server is stopped. So
either check manually that the `/scoreboard' location URI is working or
use the above test script that hangs to make sure it works.

   Enable debug mode for more information.

PREREQUISITES
=============

   You need to have *Apache::Scoreboard* installed and configured in
httpd.conf.

BUGS
====

   Was ist dieses?

SEE ALSO
========

   See Apache, `mod_perl' in this node, see
Apache/Scoreboard,

AUTHORS
=======

   Stas Bekman <sbekman@iname.com>

COPYRIGHT
=========

   Apache::Watchdog::RunAway is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

Allows for SNMP calls to be embedded in HTML
********************************************

NAME
====

   Apache::WebSNMP - Allows for SNMP calls to be embedded in HTML

SYNOPSIS
========

     <html>
     <body>
     <snmp>
     	host=zoom.google.org
     	community=public
     	connect
     	interface=ifDescr.2
     	mac=ifPhysAddress.2
     	query
     </snmp>
     The interface <b>descriptor</b> for the ethernet card is <snmp> print(interface) </snmp>
      	and its <b>mac address</b> is <snmp> print(mac) </snmp>
     </body>
     </html>

DESCRIPTION
===========

   The WebSNMP module allows one to embed SNMP commands directly into HTML
code.

REQUIRES
========

   This module requires the perl SNMP module, available at the CPAN site.

USAGE
=====

   The module allows for three different kinds of statements, surrounded
by <snmp> and </snmp> html tags.  The three types of statements consist of
configurations, variable assignments, and commands.  A brief description
of each type of statement follows:

Configuration
=============

   The configuration statements allow the user the set which host to poll
for SNMP information, as well as the SNMP community that the get
statements will draw from.  This essentially takes the form of assigning
values to the reserved variables host and *community*.  All variables are
assigned with the following syntax: 	varible_name=value

   Note: there must not be any intervening whitespace between the '=' and
the name and value.  Thus to set the SNMP host to machine.domain.net, we
would issue the configuration statement:

     <snmp>host=machine.domain.net</snmp>

   If not specified, the default host is localhost, and the default
community is public.

Variable Assignments
====================

   Variables are used as temporary holding locations for information
returned from SNMP calls.  The decision to use variables was made to
obviate the necessity of making a different SNMP get call for each
separate piece of information.  Variable assignments follow the simple
format listed above, where the variable and the value, this time the
symbolic name of a SNMP object identifier, are separated only by an equals
sign (no whitespace).  In this case, the user may also append an optional
extension to the value.  Most OIDs require some form of extension (for
example, the 'system' OIDs usually require an extension of 0, while
interface OIDs require the interface number as an extension).  The
extension is merely appended to the OID value contained in the named
variable.  For example: 	description=ifDescr[.extension] The OIDs
currently implemented are a subset of the IETF Management MIB.  Support is
available for the system, interface, ip, tcp, udp, icmp, and at modules.
A list of the currently supported OIDs, and their symbolic equivalents, is
given below:

     # system
     'sysDescr'	=> "1.3.6.1.2.1.1.1",
     'sysObjectID'	=> "1.3.6.1.2.1.1.2",
     'sysUpTime'	=> "1.3.6.1.2.1.1.3",
     'sysContact'	=> "1.3.6.1.2.1.1.4",
     'sysName'	=> "1.3.6.1.2.1.1.5",
     'sysLocation'	=> "1.3.6.1.2.1.1.6",
     'sysServices'	=> "1.3.6.1.2.1.1.7",
     # interface
     'ifIndex'	=> "1.3.6.1.2.1.2.2.1.1",
     'ifDescr'	=> "1.3.6.1.2.1.2.2.1.2",
             	'ifType'        => "1.3.6.1.2.1.2.2.1.3",
             	'ifMtu'         => "1.3.6.1.2.1.2.2.1.4",
             	'ifSpeed'       => "1.3.6.1.2.1.2.2.1.5",
             	'ifPhysAddress' => "1.3.6.1.2.1.2.2.1.6",
             	'ifAdminStatus' => "1.3.6.1.2.1.2.2.1.7",
             	'ifOperStatus'  => "1.3.6.1.2.1.2.2.1.8",
             	'ifLastChange'  => "1.3.6.1.2.1.2.2.1.9",
             	'ifInOctets'    => "1.3.6.1.2.1.2.2.1.10",
             	'ifInUcastPkts' => "1.3.6.1.2.1.2.2.1.11",
             	'ifInNUcastPkts'=> "1.3.6.1.2.1.2.2.1.12",
             	'ifInDiscards'  => "1.3.6.1.2.1.2.2.1.13",
             	'ifInErrors'    => "1.3.6.1.2.1.2.2.1.14",
             	'ifInUnknownProtos' => "1.3.6.1.2.1.2.2.1.15",
             	'ifOutOctets'   => "1.3.6.1.2.1.2.2.1.16",
             	'ifOutUcastPkts' => "1.3.6.1.2.1.2.2.1.17",
             	'ifOutNUcastPkts' => "1.3.6.1.2.1.2.2.1.18",
             	'ifOutDiscards' => "1.3.6.1.2.1.2.2.1.19",
             	'ifOutErrors'   => "1.3.6.1.2.1.2.2.1.20",
             	'ifOutQLen'     => "1.3.6.1.2.1.2.2.1.21",
             	'ifSpecific'    => "1.3.6.1.2.1.2.2.1.22",
     # ip
     'ipForwarding'	=> "1.3.6.1.2.4.1",
             	'ipDefaultTTL'  => "1.3.6.1.2.4.2",
             	'ipInReceives'  => "1.3.6.1.2.4.3",
             	'ipInHdrErrors' => "1.3.6.1.2.4.4",
             	'ipInAddrErrors' => "1.3.6.1.2.4.5",
             	'ipForwDatagrams' => "1.3.6.1.2.4.6",
             	'ipInUnknownProtos' => "1.3.6.1.2.4.7",
             	'ipInDiscards'  => "1.3.6.1.2.4.8",
             	'ipInDelivers'  => "1.3.6.1.2.4.9",
             	'ipOutRequests' => "1.3.6.1.2.4.10",
             	'ipOutDiscards' => "1.3.6.1.2.4.11",
             	'ipOutNoRoutes' => "1.3.6.1.2.4.12",
             	'ipReasmTimeout' => "1.3.6.1.2.4.13",
             	'ipReasmReqds'  => "1.3.6.1.2.4.14",
             	'ipReasmOKs'    => "1.3.6.1.2.4.15",
             	'ipReasmFails'  => "1.3.6.1.2.4.16",
             	'ipFragOKs'     => "1.3.6.1.2.4.17",
             	'ipFragFails'   => "1.3.6.1.2.4.18",
             	'ipFragCreates' => "1.3.6.1.2.4.19",
             	'ipAdEntAddr'   => "1.3.6.1.2.4.20.1.1",
             	'ipAdEntIfIndex' => "1.3.6.1.2.4.20.1.2",
             	'ipAdEntNetMask' => "1.3.6.1.2.4.20.1.3",
             	'ipAdEntBcastAddr' => "1.3.6.1.2.4.20.1.4",
             	'ipAdEntEntReasmMaxSize' => "1.3.6.1.2.4.20.1.5",
             	'ipRouteDest'   => "1.3.6.1.2.4.21.1.1",
     'ipRouteIfIndex' => "1.3.6.1.2.4.21.1.2",
     'ipRouteMetric1' => "1.3.6.1.2.4.21.1.3",
             	'ipRouteMetric2' => "1.3.6.1.2.4.21.1.4",
     'ipRouteMetric3' => "1.3.6.1.2.4.21.1.5",
             	'ipRouteMetric4' => "1.3.6.1.2.4.21.1.6",
     'ipRouteNextHop' => "1.3.6.1.2.4.21.1.7",
             	'ipRouteType'   => "1.3.6.1.2.4.21.1.8",
     'ipRouteProto'  => "1.3.6.1.2.4.21.1.9",
             	'ipRouteAge'    => "1.3.6.1.2.4.21.1.10",
     'ipRouteMask'   => "1.3.6.1.2.4.21.1.11",
             	'ipRouteMetric5' => "1.3.6.1.2.4.21.1.12",
     'ipRouteInfo'   => "1.3.6.1.2.4.21.1.13",
     'ipNetToMediaIfIndex' => "1.3.6.1.2.1.4.22.1.1",
             	'ipNetToMediaPhysAddress' => "1.3.6.1.2.1.4.22.1.2",
             	'ipNetToMediaNetAddress' => "1.3.6.1.2.1.4.22.1.3",
             	'ipNetToMediaType' => "1.3.6.1.2.1.4.22.1.4",
             	'ipRoutingDiscards' => "1.3.6.1.2.4.23",
     # tcp
     'tcpRtoAlgorithm' => '1.3.6.1.2.1.6.1',
             	'tcpRtoMin' 	=> '1.3.6.1.2.1.6.2',
             	'tcpRtoMax' 	=> '1.3.6.1.2.1.6.3',
             	'tcpMaxConn'	=> '1.3.6.1.2.1.6.4',
             	'tcpActiveOpens' => '1.3.6.1.2.1.6.5',
             	'tcpPassiveOpens' => '1.3.6.1.2.1.6.6',
             	'tcpAttemptFails' => '1.3.6.1.2.1.6.7',
             	'tcpEstabResets' => '1.3.6.1.2.1.6.8',
             	'tcpCurrEstab' 	=> '1.3.6.1.2.1.6.9',
             	'tcpInSegs' 	=> '1.3.6.1.2.1.6.10',
             	'tcpOutSegs' 	=> '1.3.6.1.2.1.6.11',
             	'tcpRetransSets' => '1.3.6.1.2.1.6.12',
             	'tcpConnState' 	=> '1.3.6.1.2.1.6.13.1.1',
             	'tcpConnLocalAddress' => '1.3.6.1.2.1.6.13.1.2',
             	'tcpConnLocalPort' => '1.3.6.1.2.1.6.13.1.3',
             	'tcpConnRemAddress' => '1.3.6.1.2.1.6.13.1.4',
             	'tcpConnRemPort' => '1.3.6.1.2.1.6.13.1.5',
             	'tcpInErrs' 	=> '1.3.6.1.2.1.6.14',
             	'tcpOutRsts' 	=> '1.3.6.1.2.1.6.15',
     # udp
     'udpInDatagrams' => '1.3.6.1.2.1.7.1',
             	'udpNoPorts' 	=> '1.3.6.1.2.1.7.2',
             	'udpInErrors' 	=> '1.3.6.1.2.1.7.3',
             	'udpOutDatagrams' => '1.3.6.1.2.1.7.4',
             	'udpLocalAddress' => '1.3.6.1.2.1.7.5.1.1',
             	'udpLocalPort'  => '1.3.6.1.2.1.7.5.1.2',
     # at
     'atIfIndex'	=> '1.3.6.1.2.1.3.1.1.1',
             	'atPhysAddressIfIndex' => '1.3.6.1.2.1.3.1.1.2',
             	'atNetAddress'  => '1.3.6.1.2.1.3.1.1.3',
     # icmp
     'icmpInMsgs'	=> '1.3.6.1.2.1.5.1',
             	'icmpInErrors' 	=> '1.3.6.1.2.1.5.2',
            	 	'icmpInDestUnreachs' => '1.3.6.1.2.1.5.3',
             	'icmpInTimeExcds' => '1.3.6.1.2.1.5.4',
             	'icmpInParmProbs' => '1.3.6.1.2.1.5.5',
             	'icmpInSrcQuenchs' => '1.3.6.1.2.1.5.6',
             	'icmpInRedirects' => '1.3.6.1.2.1.5.7',
            		'icmpInEchos' 	=> '1.3.6.1.2.1.5.8',
             	'icmpInEchoReps' => '1.3.6.1.2.1.5.9',
             	'icmpInTimestamps' => '1.3.6.1.2.1.5.10',
             	'icmpInTimestampsReps' => '1.3.6.1.2.1.5.11',
             	'icmpInAddrMasks' => '1.3.6.1.2.1.5.12',
             	'icmpInAddrMaskReps' => '1.3.6.1.2.1.5.13',
             	'icmpOutMsgs' 	=> '1.3.6.1.2.1.5.14',
             	'icmpOutErrors' => '1.3.6.1.2.1.5.15',
             	'icmpOutDestUnreachs' => '1.3.6.1.2.1.5.16',
             	'icmpOutTimeExcds' => '1.3.6.1.2.1.5.17',
             	'icmpOutParmProbs' => '1.3.6.1.2.1.5.18',
             	'icmpOutSrcQuenchs' => '1.3.6.1.2.1.5.19',
             	'icmpOutRedirects' => '1.3.6.1.2.1.5.20',
             	'icmpOutEchos' 	=> '1.3.6.1.2.1.5.21',
             	'icmpOutEchoReps' => '1.3.6.1.2.1.5.22',
             	'icmpOutTimestampsReps' => '1.3.6.1.2.1.5.23',
             	'icmpOutTimestampsReps' => '1.3.6.1.2.1.5.24',
             	'icmpOutAddrMasks' => '1.3.6.1.2.1.5.25',
            	 	'icmpOutAddrMaskReps' => '1.3.6.1.2.1.5.26',

   For example, to get the number of outbound and inbound errors on the
'second' ethernet interface, we would assign the ifOutErrors and
ifInErrors OIDs to variables.  Thus:

     <snmp> errorin=ifInErrors.2 errorout=ifOutErrors.2 </snmp>

   Note that more than one command can be nested inside a single set of
<snmp> tags, as long as they are separated by whitespace.

Commands
========

   The following command statements are currently available:

   connect initiates a connection with the SNMP host defined with the host
configuration statement.  This statement can be can be utilized multiple
times in order to connect to several different machines, however any
queries sent will be sent to the current connection.

   query actually initiates the SNMP get for the information you have
requested in your variables, contacting the host defined by the host
configuration command, and storing the data in the proper variable.

   *print(variable_name)* simply prints the information returned to a
variable after a query command.

EXAMPLE
=======

   To put all this together, let us take a simple example:  we wish to
retrieve information concerning the ethernet interface on a host named
'host.domain.net'.  Primarily we are concerned with the administrative
status, mac address, and bytes transferred in and out of the interface.
We would begin with the following block:

     <snmp>
             host=host.domain.net
             community=public
             	connect
     </snmp>

   This block defines the host and the SNMP community, and actually makes
the connection to the host.  This block can be placed anywhere within your
HTML document, as long as it comes before your SNMP queries.  Next, we
must define the information that we wish to obtain:

     <snmp>
     	description=ifDescr.2
     	mac=ifPhysAddress.2
     	inbytes=ifInOctets.2
     	outbytes=ifOutOctets.2
     	query
     </snmp>

   This block instantiates four variables: description, mac, inbytes, and
outbytes, in which the information we wish to obtain will be stored.  The
extension commands tell the program that we are interested in interface 2.
Finally, the query statement performs the SNMP get on the connected host.
All that remains is to print out our data.  Let us put it in tabular
format:

     <table>
     	<tr>
     		<td>
     			Description
     		</td>
     		<td>
     			Mac Address
     		</td>
     		<td>
     			Bytes In
     		</td>
     		<td>
     			Bytes Out
     		</td>
     	</tr>
                     <tr>
                             <td>
                                     print(description)
                             </td>
                             <td>
                                     print(mac)
                             </td>
                             <td>
                                     print(inbytes)
                             </td>
                             <td>
                                     print(outbytes)
                             </td>
                     </tr>
     </table>
     This block merely prints out our information as an HTML table.  Mission accomplished.

AUTHOR
======

   Chris Rigby

SYNOPSIS
========

     use Apache::XPP;
     my $xpp = Apache::XPP->new( Apache->request );
     $xpml->run;

REQUIRES
========

     Apache
     Apache::Constants
     File::stat
     FileHandle
     HTTP::Request
     HTTP::Date
     LWP::UserAgent

EXPORTS
=======

   Nothing

DESCRIPTION
===========

   Apache::XPP is an HTML parser which on run time compiles and runs
embedded perl code.

CLASS VARIABLES
===============

`$Apache::XPP::main_class'
     XPP sub-classes must set $Apache::XPP::main_class to the name of the
     sub-class. This will allow xinclude/include to work properly.

$debug
     Activates debugging output.  All debugging output is sent to STDERR.

     At present there are only 4 levels of debugging :  0 - no debugging
     (default)  1 - some debugging  2 - verbose debugging  3 - adds some
     Data::Dumper calls

`$debuglines'
     Optionally, you can activate the $debuglines, which will cause all
     debugging output to include the line numbers (in this file) of the
     debugging.

METHODS
=======

handler ( $r )
     The Apache handler hook. This is the entry point for the Apache
     module.  It takes the Apache request object ($r) as its parameter and
     builds a new XPP object to handle the request. In order to support
     the procedural nature of include() and xinclude() a global is
     defined. If you subclass Apache::XPP replace the value of the global
     `"$Apache::XPP::main_class"' in this node with your class name.

new ( \%params | $filename )
     Creates a new XPP object. Valid parameter keys are:

        * source    - A block of xpp code to be parsed

        * filename  - A filename/url specifying a code block

     All other parameters will be stashed in the xpp object.

`preparse' (  )
     Pre-Parses the object's code, converting TAGS to text and xpp code.
     This method passes a reference to the xpp source to each preparser
     returned by the preparse class's `parses' method.  (The preparse
     class is returned by the `preparseclass' method).

parse (  )
     Parses the object's xpp source code, populating the object's code
     attribute with a subroutine reference which when run (with the run
     method), will result in the printing of the xpp page.

run ( @arguments )
     Runs the XPP code (set by the parse method), passing any arguments
     supplied to the code.  This should have the effect of printing the
     xpp page to STDOUT.

`returnrun' ( @arguments )
     Calls run with @arguments as specified, catching all output destined
     for STDOUT, and returning the results as a string.

load ( $filename )
     Returns the code specified by $filename.  If $filename begins with a
     url specifier (e.g. http://), LWP::UserAgent will be used to retrieve
     the file.  If $filename begins with a '/', it will be treated as a
     rooted filename.  Otherwise the filename will be as a file relative
     to XPPIncludeDir

qualify ( $filename )
     Qualifies the passed name to a fully rooted filename by using either
     `incdir' or `docroot'.

`incdir' (  )
     Returns the include directory from which include and `xinclude' will
     retrieve source from by default.  See include, `xinclude', and load
     for more documentation on this process.

`docroot' (  )
     Returns the document root directory from which all rooted filenames
     will be retrieved in include, and `xinclude'.

r (  )
     Returns the Apache request object

include ( $filename )
     Static, unbuffered, unparsed content include. It can be used within
     an xpml script by simply saying

          include $filename;

     See the load method for more information

`xinclude' ( $filename, @options )
     Dynamic, parsed, buffered content include. It can be used within an
     xpml script by simply saying

          xinclude $filename;

debug ( $debuglevel [, $debuglines ]
     Manipulates debug level.  See $debug above.

     N.B. - at present these flags are global, not per object.  Method
     works as static or dynamic.

include( $inc_location )
     Returns the plaintext of the include file $inc_location.

xinclude( $inc_location, @ARGS )
     Returns the XPP parsed text of the include file $inc_location,
     passing @ARGS to the page as arguments.

REVISION HISTORY
================

   $Log: XPP.pm,v $ Revision 1.23  2000/09/08 22:26:44  david added,
changed, revised, and otherwise cleaned up a lot of POD cleaned up new()
- removed dependence on MD5 (uses conventional checksum) 	- folded
nearly duplicate header and footer code into a loop incdir() 	- now
uses Apache->server_root_relative() instead of $ENV{SERVER_ROOT} debug()
- new method to manipulate $debug and $debuglines globals Apache::XPP::Tie
class now uses $debug settings of Apache::XPP class

     "This would go great with gwack-a-mole!" - Z.B.

   Revision 1.22  2000/09/08 00:42:45  dougw Took out rscope stuff.

   Revision 1.21  2000/09/07 23:42:23  greg fixed POD

   Revision 1.20  2000/09/07 23:30:40  dougw Fixed over.

   Revision 1.19  2000/09/07 20:15:54  david new(), r() - makes previous
bug fix less agressive, yet more thorough.

   Revision 1.18  2000/09/07 19:49:01  david r() - fixed peculiar (and
elusive) bug where DirectoryIndex accessed pages (and potentially any page
using a subrequest) caused a segmentation fault with cached pages.

   Revision 1.17  2000/09/07 18:48:11  dougw Small update

   Revision 1.16  2000/09/07 18:45:14  dougw Version update

   Revision 1.15  2000/09/06 23:42:50  dougw Modified POD to be consistent
with BingoX

SEE ALSO
========

   perl(1).

KNOWN BUGS
==========

   None

TODO
====

   precompile

COPYRIGHT
=========

     Copyright (c) 2000, Cnation Inc. All Rights Reserved. This module is free
     software. It may be used, redistributed and/or modified under the terms
     of the GNU Lesser General Public License as published by the Free Software
     Foundation.

     You should have received a copy of the GNU Lesser General Public License
     along with this library; if not, write to the Free Software Foundation, Inc.,
     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

AUTHORS
=======

   Greg Williams <greg@cnation.com> Doug Weimer <dougw@cnation.com>

THANKS TO
=========

Chris Nandor <pudge@pobox.com> for his help on the regex core.

XPP Cache manegment module
**************************

NAME
====

   Apache::XPP::Cache - XPP Cache manegment module

SYNOPSIS
========

     use Apache::XPP::Cache;
     $cache	= Apache::XPP::Cache->new( %options );
     $cache	= Apache::XPP::Cache->is_cached( %options );

REQUIRES
========

   Apache::XPP

EXPORTS
=======

   Nothing

DESCRIPTION
===========

   Apache::XPP::Cache is an interface to both Store and Expire caching
modules.

METHODS
=======

new( $name, $group, \%instance_data, [ $storetype, @store_options ], [ $expiretype, @expire_options ] )
     Creates a new Cache object using the specified Store and Expire types.

`install_module' ( ('Store'|'Expiry'), $name )
     Installs the $name store or expiry module, and returns the associated
     class name.

is_expired (  )
     Returns a true value if the current cache has expired, otherwise
     returns false.

content (  )
     Returns the content of the current cache.

r (  )
     Returns the Apache request object

AUTOLOAD ( )
     Calling $obj->meth() returns $obj->{'meth'}.  Calling
     $obj->meth($val) sets $obj->{'meth'} = $val.

REVISION HISTORY
================

     $Log: Cache.pm,v $
     Revision 1.8  2000/09/15 22:02:37  dougw
     Took out $AUTOLOAD

     Revision 1.7  2000/09/15 21:35:22  dougw
     Autoload changed to use Apache::XPP's autoload. This didn't make it into
     the previous check in.

     Revision 1.6  2000/09/13 21:02:11  dougw
     David cleaned up the loop in new() so it isn't 2 identical loops. r() and
     AUTOLOAD() are now just forwarders to Apache::XPP::r and Apache::XPP::AUTOLOAD

     Revision 1.5  2000/09/07 19:03:19  dougw
     over fix

     Revision 1.4  2000/09/07 18:40:38  dougw
     Pod updates.

AUTHORS
=======

   Doug Weimer <dougw@cnation.com> Greg Williams <greg@cnation.com>

SEE ALSO
========

     l<perl(1)>.
     l<Apache::XPP>

Cache expiry superclass
***********************

NAME
====

   Apache::XPP::Cache::Expiry - Cache expiry superclass

SYNOPSIS
========

   ...

REQUIRES
========

   Nothing

EXPORTS
=======

   Nothing

DESCRIPTION
===========

   Apache::XPP::Cache::Expiry provides a barebones AUTOLOAD for XPP's
Cache-Expiry classes.

METHDOS
=======

r (  )
     Returns the Apache request object

REVISION HISTORY
================

     $Log: Expiry.pm,v $
     Revision 1.6  2000/09/11 20:12:23  david
     Various minor code efficiency improvements.

     Revision 1.5  2000/09/07 19:02:41  dougw
     Pod, over fix

     Revision 1.4  2000/09/07 18:50:01  dougw
     Fixed pod error

     Revision 1.3  2000/09/07 18:44:52  dougw
     POD updates.

AUTHORS
=======

   Greg Williams <greg@cnation.com>

SEE ALSO
========

   perl(1).  Apache::XPP Apache::XPP::Cache

Duration based cache expiry.
****************************

NAME
====

   Apache::XPP::Cache::Expiry::Duration - Duration based cache expiry.

SYNOPSIS
========

   ...

REQUIRES
========

   Apache::XPP::Cache::Expiry

EXPORTS
=======

   Nothing

DESCRIPTION
===========

   Apache::XPP::Cache::Expiry::Duration handles the expiring of caches
based on a duration of time on behalf of Apache::XPP::Cache.

METHODS
=======

new ( $name, $group, \%instance_data, $duration )
     Creates a new Duration expiry object. The contents of %instance_data
     will be placed in the object as instance data (for Apache request
     object, etc.).

is_expired ( $store_object )
     Returns TRUE if the cache (whose store is passed as an argument) has
     expired, FALSE otherwise.

REVISION HISTORY
================

     $Log: Duration.pm,v $
     Revision 1.5  2000/09/11 20:12:23  david
     Various minor code efficiency improvements.

     Revision 1.4  2000/09/07 19:02:56  dougw
     over fix

     Revision 1.3  2000/09/07 18:53:13  dougw
     Added VERSION/REVISION, pod changes.

AUTHORS
=======

   Greg Williams <greg@cnation.com>

SEE ALSO
========

   perl(1).

Cache store superclass
**********************

NAME
====

   Apache::XPP::Cache::Store - Cache store superclass

SYNOPSIS
========

   ...

REQUIRES
========

   Carp

EXPORTS
=======

   Nothing

DESCRIPTION
===========

   Apache::XPP::Cache::Store provides a barebones AUTOLOAD for XPP's
Cache-Store classes.

METHDOS
=======

r (  )
     Returns the Apache request object

REVISION HISTORY
================

     $Log: Store.pm,v $
     Revision 1.5  2000/09/11 20:12:23  david
     Various minor code efficiency improvements.

     Revision 1.4  2000/09/07 19:02:14  dougw
     Pod, over fix.

     Revision 1.3  2000/09/07 18:50:52  dougw
     Pod fixes

AUTHORS
=======

   Greg Williams <greg@cnation.com>

SEE ALSO
========

   perl(1).  Apache::XPP Apache::XPP::Cache

flatfile cache store
********************

NAME
====

   Apache::XPP::Cache::Store::File - flatfile cache store

SYNOPSIS
========

   ...

REQUIRES
========

   Apache::XPP::Cache::Store FileHandle File::stat

EXPORTS
=======

   Nothing

DESCRIPTION
===========

   Apache::XPP::Cache::Store::File handles the storing of data in flat
file form on behalf of Apache::XPP::Cache.

METHODS
=======

new ( $name, $group, \%instance_data, \$content )
     Creates a new File store object. The contents of %instance_data will
     be placed in the object as instance data (for Apache request object,
     etc.).

location ( $name, $group )
     Returns the fully qualified filename to the store file for the
     specified name/group pair.  Files are stored by their $name in the
     directory $group. If the directory $group does not exist, it will be
     created with permissions of 0777 (use the umask function to change
     these permissions to more desirable ones).

`cachedir' (  )
     Returns the directory in which file caches are stored.

content ( [ \$content ] )
     Sets the store object's content to $content and returns TRUE.  If
     $content is omitted, returns the content of the store object.

is_expired (  )
     Removes the store file.

mtime (  )
mtime ( $name, $group )
     Returns the modification time of the specified store.

REVISION HISTORY
================

     $Log: File.pm,v $
     Revision 1.7  2000/09/13 21:00:52  dougw
     Small change to line 165.

     Revision 1.6  2000/09/11 20:12:23  david
     Various minor code efficiency improvements.

     Revision 1.5  2000/09/07 19:01:57  dougw
     Pod fixin's

AUTHORS
=======

   Greg Williams <greg@cnation.com>

SEE ALSO
========

   perl(1).  Apache::XPP Apache::XPP:Cache

XPP TAG Parser
**************

NAME
====

   Apache::XPP::PreParse - XPP TAG Parser

SYNOPSIS
========

     use Apache::XPP::PreParse;
     $preparsers	= Apache::XPP::PreParse->parsers;
     foreach (@{ $preparsers }) {
     	$preparsers->( \$text );
     }

REQUIRES
========

   Nothing

EXPORTS
=======

   Nothing

DESCRIPTION
===========

   Apache::XPP::PreParse handles pre parsing of an xpp page to convert
'tags' into valid XPML. Tags are meant as a shortcut for code that might
otherwise be burdensome or confusing for and xpml author, such as ref
checking before calling a method: <xpp method="cities_popup_menu"
obj="$app"> might be converted to: <?xpp if (ref($app)) { print
$app->cities_popup_menu; } ?>.

METHODS
=======

`parsers' (  )
     Returns a new parser object

`add_parser' ( \&parser )
     Adds a parser to the list of registered pre-parsers.

`parse_tag' ( $tag )
     Given an xpp TAG $tag, will return an array with two elements.  The
     first element is an array reference of the order of keys in the tag.
     The second element is a hash reference to the key-value pairs.

`dtag' ( \$text, $tag, $subref )
     This is for processing tags with a start tag and seperate end tag.
     All the data in between is sent to $subref->( $params, $data) where
     $params is a hashref containing all the key value pairs in the start
     tag and $data is the data contained in between the opening and
     closing tag.

`parse_stag'
     Called by stag to parse the matched tag with the supplied rules.

`stag' ( \$text, $match, \@replace_rules )
     Given a string to match, uses the replace rules to replace tags that
     contain the $match with it's equivalent. See examples below for
     syntax of replace rules.

`parser_xppcomment'
     Used to comment out blocks of xpml code.

     Ex:  <XPPCOMMENT>   <title><?= $obj->title() ?></title>  </XPPCOMMENT>

`parser_xppcache'
     Cache a block of code using a specific expire/store module. Pass the
     caches name, group, expire, and store. See `xppcachetut.pod' in this
     node for more information.

     Ex:  <XPPCACHE name="mycache" group="cachegroup" store="File"
     expire="Duration, 10s">   ....   </XPPCACHE>

`parser_appmethod'
     Assign or print an object method. Ref checks the object before using
     it. Assigns the result to the value of the as tag parameter. If this
     param isn't present the result is printed.

     Ex:  <XPP app app="$obj" attr="bleh" as="$var">  <XPP app app="$obj"
     attr="bleh">

`parser_print'
     Prints the result of an object method.

     Ex:  <XPP print obj="$obj" attr="bleh">

`parser_xppxinclude'
     Calls xinclude with the passed filename and options.

     Ex:  <XPP xinclude filename="include.xmi" options="$obj1, $obj2">

`parser_xppforeach'
     Places the included block within a foreach loop. Assigning each
     element of the array to 'as.' If 'as' is not present it uses $_.

     Ex:  <XPPFOREACH array="@ary" as="$val">  <XPPFOREACH array="@ary">

REVISION HISTORY
================

   $Log: PreParse.pm,v $ Revision 1.17  2000/09/14 23:01:30  dougw Fixed
stag pod.

   Revision 1.16  2000/09/13 00:32:04  dougw Pod for tag methods.

   Revision 1.15  2000/09/11 20:15:33  david Sent AUTOLOAD to
Apache::XPP::AUTOLOAD.

   Revision 1.14  2000/09/07 19:03:19  dougw over fix

   Revision 1.13  2000/09/07 18:48:36  dougw Took out some use vars

   Revision 1.12  2000/09/07 18:45:42  dougw Version Update.

   Revision 1.11  2000/09/07 00:05:38  dougw POD fixes.

SEE ALSO
========

   perl(1).  tagtut

KNOWN BUGS
==========

   None

TODO
====

   ...

COPYRIGHT
=========

     Copyright (c) 2000, Cnation Inc. All Rights Reserved. This module is free
     software. It may be used, redistributed and/or modified under the terms
     of the GNU Lesser General Public License as published by the Free Software
     Foundation.

     You should have received a copy of the GNU Lesser General Public License
     along with this library; if not, write to the Free Software
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

AUTHORS
=======

   Greg Williams <greg@cnation.com> Doug Weimer <dougw@cnation.com>

Generate an httpd.conf file
***************************

NAME
====

   Apache::httpd_conf - Generate an httpd.conf file

SYNOPSIS
========

     use Apache::httpd_conf ();

     Apache::httpd_conf->write(Port => 8888);

DESCRIPTION
===========

   The Apache::httpd_conf module will generate a tiny httpd.conf file,
which pulls itself back in via a <Perl> section.  Any additional arguments
passed to the write method will be added to the generated httpd.conf file,
and will override those defaults set in the <Perl> section.  This module
is handy mostly for starting httpd servers to test mod_perl scripts and
modules.

AUTHOR
======

   Doug MacEachern

SEE ALSO
========

   mod_perl(3), Apache::PerlSections(3)

An e-commerce framework.
************************

NAME
====

   Apache::iNcom - An e-commerce framework.

SYNOPSIS
========

     - Configure Apache and mod_perl
     - Create databases
     - Install Apache::iNcom
     - Design your e-commerce site.
     - Wait for incomes.

DESCRIPTION
===========

   Apache::iNcom is an e-commerce framework. It is not a ready-to-run
merchant systems. It is an integration of different components needed for
e-commerce into a coherent whole.

   The primary design goals of the framework are flexibility and security.
Most merchant systems will make assumptions in the way your catalog's
data, customer's data are structured or on how your order process works.
Most also imposes severe restrictions on how the user will interface to
your electronic catalog. This is precisely the kind of constraints that
Apache::iNcom was designed to avoid.

   Apache::iNcom provides the following infrastructure :

     - Session Management
     - Cart Management
     - Input Validation
     - Order management
     - User management
     - << Easy >> database access
     - Internationalization
     - Error handling

   Most of the base functionalities of Apache::iNcom are realized by
leveraging standard and well known modules like DBI(3) for generic SQL
database access, HTML::Embperl(3) for dynamic page generation,
Apache::Session(3) for session management, mod_perl(3) for Apache
integration and Locale::Maketext(3) for localization.

   Here are its assumptions :

     - Data is in a SQL database which supports transactions.
     - Interface is in HTML.
     - Session is managed through cookies.

REQUIREMENTS
============

     - DBI              1.13
     - mod_perl         1.21
     - libapreq	       0.31
     - HTML::Embperl    1.2b10
     - Apache::Session  1.03   + generate_id patch
     - MIME::Base64
     - Locale::Maketext 0.17   + currency patch
     - apache	       1.3.6 or later
     - Database which supports transactions. (tested with PostgreSQL 6.5.x)

CONFIGURATION
=============

   Apache::iNcom is configured using standard the Apache directives
PerlSetVar. Activating Apache::iNcom for a particular virtual host is a
simple as

     <VirtualHost 192.168.1.1>
     	PerlInitHandler Apache::iNcom
     	PerlSetVar INCOM_URL_PREFIX /incom/
     	PerlSetVar INCOM_ROOT	    pages
     </VirtualHost>

   This will make all URL starting with `/incom/' served dynamically by
Apache::iNcom.

   Additionnaly different modules used by Apache::iNcom will be configured
by profile files. Consult the appropriate module documentation for details.

GENERAL DIRECTIVES
------------------

INCOM_URL_PREFIX
     This is the prefix that must match for the URI to be serve by
     Apache::iNcom. THIS PREFIX MUST ENDS WITH A SLASH (/). To make all
     files Apache::iNcom page, use / as prefix. This wouldn't work well for
     images and other binary files though. Use only / as prefix, if binary
     files are served by another server.

INCOM_ROOT
     This is the path to the directory where Apache::iNcom requests will be
     mapped. For example, if you have a INCOM_URL_PREFIX of `/incom/' and
     a INCOM_ROOT of `/home/incom/site/pages', the request
     `/incom/index.html' will be mapped to
     `/home/incom/site/pages/index.html'. Default is to use the server's
     document root.

INCOM_INDEX
     This is page that will be used when accessing directory. Defaults to
     `index.html'

INCOM_TEMPLATE_PATH
     Colon separated list of directory to search when using the `Include()'
     function. (See Apache::iNcom::Request(3) for more information). Non
     absolute paths are relative to the server's root.

DATABASE DIRECTIVES
-------------------

INCOM_DBI_DSN
     The DBI(3) URL to use to open a database connection.

INCOM_DBI_USER
     Username to use for the database connection.

INCOM_DBI_PASSWD
     Password to use for the database connection.

INCOM_DBI_TRACE
     Sets the tracing level for the connection.

INCOM_DBI_LOG
     File where the DBI(3) trace output will go.

INCOM_SEARCH_PROFILE
     DBIx::SearchProfiles(3) profile file that will be used to configure
     the $DB object accessible in Apache:iNcom pages. If non-absolute, it
     is relative to the server's root. Defaults to
     `conf/search_profiles.pl' relative to the server's root.

     See DBIx::SearchProfiles(3) for details on the format of this file.

     To turn off the use of the search profiles set this directive to
     `NONE'.

PROFILES DIRECTIVES
-------------------

INCOM_INPUT_PROFILE
     Sets the input profile that will be used to initialize the $Validator
     object. Defaults to `conf/input_profiles.pl' relative to server's
     root.

     See HTML::FormValidator(3) for details on the format of this file.

     To turn off the creation of an input profile set this directive to
     `NONE'.

INCOM_PRICING_PROFILE
     Sets the pricing profile that will be used to initialize the $Cart
     object. Defaults to `conf/pricing_profile.pl' relative to server's
     root.

     See Apache::iNcom::CartManager(3) for details on the format of this
     file.

     If you don't need the cart management feature, set this directive to
     `NONE'.

INCOM_ORDER_PROFILE
     Sets the order profiles file that will be used to initialize the
     $Order object. Defaults to `conf/order_profiles.pl' relative to
     server's root.

     See Apache::iNcom::OrderManager(3) for details on the format of this
     file.

     If you don't need this feature, you can set this directive to `NONE'.

USERDB DIRECTIVES
-----------------

INCOM_USERDB_PROFILE
     Name of the profile to use for the user database. Defaults to
     `userdb'. See DBIx::UserDB(3) for more information. To disable the
     use of a DBIx::UserDB object, sets this directives to `NONE'.

INCOM_GROUPDB_PROFILE
     Name of the profile to use for the group database access. Defaults to
     `groupdb'. See DBIx::UserDB(3) for more information.

INCOM_SCRAMBLE_PASSWORD
     Turn on or off scrambling of user's password in the UserDB.

LOCALIZATION DIRECTIVES
-----------------------

INCOM_DEFAULT_LANGUAGE
     The language of the files without a language extension. Defaults to
     `en'.

INCOM_LOCALE
     The package uses to create Locale::Maketext(3) instance. If this is
     set, an instance appropriate for the user's locale will be available
     through the $Locale object.

SESSION DIRECTIVES
------------------

INCOM_SESSION_SERIALIZE_ACCESS
     Set this to 1 to serialize access through session. This will make sure
     that only one session's request is processed at a time. You should set
     this to 1 if your site uses frameset.

INCOM_SESSION_SECURE
     Sets this to true if you want the cookie that contains the session id
     to be only transmitted over SSL connections. Be aware that setting
     this variable to true will require that all Apache::iNcom transactions
     be conducted over SSL.

INCOM_SESSION_DOMAIN
     The domain to which the Apache::iNcom session's cookie will be
     transmitted. You can use this, if you are using a server farm for
     example.

INCOM_SESSION_PATH
     The path under which the session id is valid. Defaults to
     INCOM_URL_PREFIX.

INCOM_SESSION_EXPIRES
     The time for which the use session is valid. Defaults is for a browser
     session. (Once the user exists its browser session will become
     invalid).

ERROR HANDLING DIRECTIVES
-------------------------

INCOM_ERROR_PROFILE
     The error profile that will be used for displaying server error.

INCOM_ERROR_ROOT
     The directory which contains error pages. If a non absolute path is
     specified, it is relative to the server's root.

SESSION HANDLING
================

   On the user's first request, a new session is created. Each and every
other request will be part of a session which will used to track the
user's cart and other such things.

   The session id is returned to the user in a cookie. COOKIES MUST BE
ENABLED for Apache::iNcom to function. Fortunately, Apache::iNcom detects
if the user has cookies turned off and will send the user an error.

   Cookies are used for security and confidentiality. The session id is a
truly random 128bits number, which is make it very much unguessable.  That
means that you can't try to stomp into another user's session.  That is a
good thing since having access to the session id means having access to a
whole bunch of informations. (What information is application specific.)
IP address aren't used to restrict the session access because of the
various problems with proxies and other Internet niceties.

   Now, what has this to do with cookies ? Well, using URL rewriting was
originally considered, but then two big issues cralwed in : proxies and
the Referer header. Having the session id embedded in the URL means that
our precious session id will be stored in various log files across
multiple server (web server, proxy server, etc) This is a bad thing. Also,
must request contains a Referer header which means that the session id is
likely to leak to third party sites which are linked from your site (or
not, Netscape used to send the header even if the user only typed in the
new URL while viewing your page). This is another bad thing, and this is
why we are using cookies.

APACHE::INCOM PAGES
===================

   Apache::iNcom pages are HTML::Embperl pages with some extra variables
and functions available. See Apache::iNcom::Request(3) for details.  You
may also which to consult the HTML::Embperl documentation for syntax.
Additionnaly, the normal $req_rec object in the page is an instance of
Apache::Request(3) so that you can handle multipart upload.

DATABASE CONNECTIVITY
=====================

   The database connection is opened once per request and shared by all
modules that must use it. Database access is mediated through the use of
the DBIx::SearchProfiles(3) module.

   Connections are opened in commit on request mode. The database
connection is commit after the page is executed. If an error occurs, the
transaction will be rolled back. The application may elect to commit part
of the transaction earlier.

CART MANAGEMENT
===============

   See Apache::iNcom::CartManager(3) for details.

ORDER MANAGEMENT
================

   See Apache::iNcom::OrderManager(3) for details.

USER MANAGEMENT
===============

   User management is handled through the DBIx::UserDB(3) module.

LOCALIZATION
============

   Apache::iNcom is designed to make it easy to adapt your e-commerce
application to multiple locale.

   The framework uses Locale::Maketext(3) for message formatting.

   All pages may have a localized version available. The localized should
have an extension describing its language. (.en for English, .fr for
French, .de for German, etc.)

   The user locale will be negotiated through the Accep-Language header
which is part of the HTTP protocol. It can also be set explicitely by
sending the user to a special link (since not many users took the time to
configure their browser for language negotiation).

   The URL :

     I<INCOM_URL_PREFIX>/incom_set_lang/I<LANG>

   This will set the language to use in the user's session.

SECURITY
========

   Apache::iNcom has been with security has one of its primary design goal.

  1. Session ID are 128bits truly random number.

  2. Session ID are transmitted only by cookies to assure confidentiality.

  3. There are no user transmitted magic variables. Form data doesn't act
     upon the framework. All actions are triggered by the application and
     not the user. All form data that should be used for action are
     determined by the application through the various profiles. This
     means that you won't be burned by a magic feature that sprung without
     you knowing it.

  4. Regular access control of Apache can be used. Also see the ACLs
     mechanism offered by the DBIx::UserDB(3) for access control with finer
     resolution than URL or file based.

  5. SSL can (and should) be used to assure confidentiality.

  6. Executable content (pages) that shouldn't be directly accessible from
     the user (include file, error pages, etc) can be kept in separate
     directory which aren't accessible directly.

        The major (current) security limitations is that the application
programmer is trusted. Apache::iNcom pages have complete control over the
Apache server environment in which they run. Keep this in mind when
running multiple sites. Future version will use the Safe(3) module to
improve on this.

MULTIPLE CATALOGS
=================

   Multiple e-commerce sites can easily be run by using the VirtualHost
capability of apache.

PERFORMANCE AND SCALABILITY
===========================

   No state is kept between requests which makes it easy to scale the load
on Apache::iNcom across multiple server.

   mod_perl general tips for improving performance should be applied. See
the mod_perl guide for details (http://perl.apache.org/guide/).

ERROR HANDLING
==============

   Error are handled in a way similar to the ErrorDocument functionality.
The error profile is an file which should eval to an hash reference. Keys
are error number and values are the file that should be returned on error.
The pages are assumed to be relative to the INCOM_ERROR_ROOT directory, or
if unspecified the INCOM_ROOT.

   If a localized version of the page exists, that one will be use. The
page will be executed as a normal Apache::iNcom pages. Error are keyed
either by the HTTP response code (404,403,500, etc) or by an arbitrary key
for application specific error. In order to return an arbitrary error, you
set the pnote *INCOM_ERROR* in the page before returning an error.

     Example: $req_rec->pnotes( "INCOM_ERROR", "validation_failed" );
     	     die "validation_failed";

   The page linked to the "validation_failed" key in the error profile
will be used.

   The "no_cookies" key is used to find the error page to return in case
the user has turned off cookies.

   In the case of an error handler trigerred by an error in an
HTML::Embperl page. The error page will received in the @param array the
error messages emitted by HTML::Embperl.

AUTHOR
======

   Copyright (c) 1999 Francis J. Lacoste and iNsu Innovations Inc.  All
rights reserved.

   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.

SEE ALSO
========

   Apache::iNcom::Request(3) Apache::iNcom::CartManager(3)
Apache::iNcom::OrderManager(3) DBIx::SearchProfiles(3) DBIx::UserDB(3)
Locale::Maketext(3) HTML::Embperl

Object responsible for managing the user shopping cart.
*******************************************************

NAME
====

   Apache::iNcom::CartManager - Object responsible for managing the user
shopping cart.

SYNOPSIS
========

     $Cart->order( \%item );
     my $items = $Cart->items;
     $Cart->empty;

DESCRIPTION
===========

   This is the part of the Apache::iNcom framework that is responsible for
managing the user shopping cart. It keep tracks of the ordered items and
is also responsible for the pricing of the order. It this is module that
computes taxes, discount, price, shipping, etc.

DESIGN RATIONALE
================

   Well not completly since all these operations are delegated to user
implemented functions implemented in a pricing profile. The idea behind it
is to make policy external to the framework. One thing that varies
considerably between different applications is the pricing, discount,
taxes, etc. So this is left to the implementation of the application
programmer.

PRICING PROFILE
===============

   The pricing profile is a file which is C{eval}-ed at runtime. (It is
also reloaded whenever it changes on disk. It should return an hash
reference which may contains the following key :

item_price
     The function should return the price of the item. The function is
     passed only one parameter : the item which we should compute the
     price.

          Ex:	item_price => sub {
          	my $item = shift;
          	my $data = $DB->template_get( "product", $item->{code} );
          	return $data->{price};
          }

item_discount
     The function should return the discounts that apply for that
     particular item. It can return zero or more discounts. It returning
     more that one discount return a an array reference. Discount are
     substracted from the item price so don't return a percentage.

          Ex:	item_discount => sub {
          	my $item = shift;

          # Discount are relative to item and quantity
          my $data = $DB->template_get( "discount", $item->{code},
          			      $item->{quantity} );
          return unless $data; # No discount

          # Discount is proportional to the price
          return $item->{price} * $data->{discount};
              }

     The subtotal of the cart is equal to the sum of

          ($item->{price} - $item->{discount}) * $item->{quantity}

shipping
     This function determines the shipping charges that will be added to
     the subtotal. The function receives as arguments the subtotal of the
     cart and an array ref to the cart's items. It should return zero or
     more shipping charges that will be added to the subtotal. If returning
     more that one charges, return an array reference.

          Ex: shipping => sub {
          	    # Flat fee based shipping charges
          	    if ( $Session{shipping} eq "ONE_NIGHT" ) {
          		return 45;
          	    } else {
          		return 15;
          	    }
          	}

discount
     That function determines discount that will be substracted from the
     subtotal. Function is called with 3 arguments, the subtotal of the
     cart, the shipping charges and an array reference to the cart's items.
     Again the function may elect to return zero or more discounts and
     should return an array reference if returning more that one discounts.

          Ex: discount => sub {
          	my $subtotal = shift;
          	my $user = $Request->user;
          	return unless $user->{discount};

          return $subtotal * $user->{discount};
              }

taxes
     That functions determines the taxes charges that will be added to the
     order. It should return zero or more taxes. If the functions returns
     more that one taxes, it should return an array reference. The
     functions receives 4 arguments, the cart's subtotal, the shipping
     charges, the discount and the cart's items as an array reference.

          Ex: taxes => sub {
          	my ( $sub, $ship, $disc ) = @_;

          # We only charges taxes to Quebec's resident. All our
          # items are taxable and is shipping.
          if ( ${$Request->user}->{province} eq "QC" ) {
              my $taxable = $sub + $ship - $disc;
              my $gst = $taxable * 0.07
              my $gsp = ($taxable + $gst) * 0.075

          return [ $gst, $gsp ];
          	} else {
          return undef;
          	}
              }

   If one of these functions is left undefined. The framework will create
one on the fly which will return 0. (No taxes, no discount, no shipping
charges, item is free, etc).

   All those functions are defined and execute in the namespace of the
pages which will use the $Cart object. This means that those functions
have access to the standard Apache::iNcom globals ($Request, %Session,
$Localizer, $Locale, etc ). DONT ABUSE IT. Also, don't call any methods on
the $Cart object or you'll die of infinite recursion.

WHAT IS AN ITEM
===============

   An item is simply an hash with some reserved key names. All other keys
are ignored by the CartManager. Each item with the same (non reserved) key
values is assumed to be identic in terms of price, discount, etc.

   This design was chosen to handle the infinite variety of item
attributes (color, size, variant, ...). The framework doesn't need
knowledge of those, only the application specific part. (The pricing
functions.)

   These are reserved names and can't be used as item attributes :
quantity, price, discount, subtotal

INITIALIZATION
==============

   An object is automatically initialized on each request by the
Apache::iNcom framework. It is accessible through the $Cart global
variable in Apache::iNcom pages.

METHODS
=======

order ( \%item, ... )
---------------------

   This method will add all the specified items (hash reference) to the
Cart. The quantity ordered should be specified in the quantity attribute.
(If unspecified, it is assumed to be one). If an identical item is already
in the cart, the quantity will be added.

   Use a negative quantity to remove from the quantity ordered. If the new
quantity is lower or equal to zero it will be removed.

   Use a quantity of 0 to remove an item.

empty
-----

   Removes all items from the cart.

is_empty
--------

   Return true if no items are in the cart.

items
-----

   Return all the ordered items as an array. Each item have the following
attribute set :

quantity
     The quantity of the item ordered.

price
     The price of that item.

discount
     The discounts applied to this item.

subtotal
     That item subtotal.

subtotal
--------

   Returns the cart subtotal. (This is before global discount, shipping
charges and taxes.)

taxes
-----

   Returns the taxes that will be added to the order.

total
-----

   Returns the order total. (subtotal + shipping charges - discounts +
taxes ).

discount
--------

   Returns the overall discount that applied to this order.

shipping
--------

   Returns the shipping charges for this order.

item_price ( \%item )
---------------------

   Returns the price of the item specified. If no quantity is specified, a
quantity of 1 is assumed. This method doesn't modify the cart.

item_discount ( \%item )
------------------------

   Returns the discounts associated with the specified item. It no
quantity is specified, a quantity of 1 is assumed. This method doesn't
modify the cart.

item_pricing ( \%item )
-----------------------

   Returns the item as it would be added to the cart. quantity, price,
discount and subtotal will be set in the returned item. This method
doesn't modify the cart.

AUTHOR
======

   Copyright (c) 1999 Francis J. Lacoste and iNsu Innovations Inc.  All
rights reserved.

   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.

SEE ALSO
========

   Apache::iNcom(3) Apache::iNcom::Request(3)
Apache::iNcom::OrderManager(3)

Object responsible for the localization of the generated request.
*****************************************************************

NAME
====

   Apache::iNcom::Localizer - Object responsible for the localization of
the generated request.

SYNOPSIS
========

     my $file	= $Localizer->find_localized_file( $filename );
     my $bundle	= $Localizer->get_handle( "Site_L10N" );

DESCRIPTION
===========

   This module is used for localization in the Apache::iNcom framework.
It should be used for operation which are locale sensitive. (Messages
display, currency and date formatting, etc.)

INITIALIZATION
==============

   An object is automatically initialized on each request by the
Apache::iNcom framework. The list of preferred languages is determined by
using the Accept-Language HHTP header. The default language is set to the
one specified in the configuration. It is accessible through the
$Localizer gobal variable in the Apache::iNcom pages.

METHODS
=======

default_lang
------------

   Get or set the default language.

preferred_lang
--------------

   Get or set the user's preferred language.

preferred_langs
---------------

   Get or set the user's preferred languages in order of preferences.

get_handle ( $base_package )
----------------------------

   This method will initialize a Locale::Maketext object of the
$base_package using the user's list of preferred languages. This object
should be used for localization of messages and such. See that module
documentation for details (or the article about it The Perl Journal #8).

find_localized_file ( $filename )
---------------------------------

   This method will try to find a properly localized version of the
$filename. Localized version of the file name should have the same name
with the language extension appended. If the file without extension
exists, it is assumed to be in the default language.

     Ex: file.txt	-> English
     	file.txt.fr	-> French
     	file.txt.es	-> Spanish
     	file.txt.fr-CA	-> French Canadian

AUTHOR
======

   Copyright (c) 1999 Francis J. Lacoste and iNsu Innovations Inc.  All
rights reserved.

   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.

SEE ALSO
========

   Locale::Maketext(3) Apache::iNcom(3) Apache::iNcom::Request(3)
I18N::LangTags(3)

Module responsible for order management.
****************************************

NAME
====

   Apache::iNcom::OrderManager - Module responsible for order management.

SYNOPSIS
========

     my $order = $Order->checkout( "order", $Cart, %fdat );
     my $report $Order->order_report( $order );

DESCRIPTION
===========

   This is the part of the Apache::iNcom framework that is responsible for
managing the order process. Once the user is ready to check out, the
OrderManager rides in. This module enters the user's order in the database
according to an order profile. It can also generate order reports and such.

   It is in that module that future development will place links with
CyberCash (tm) and other online payment systems.

DATABASE
========

   The order should be entered in two tables. One table table contains the
global order informations : order no, client's information, status, total,
taxes, etc., and another table contains the ordered items.

   To make order customizable, the OrderManager uses DBIx::SearchProfiles
to insert the information. That design is similar to DBIx::UserDB in that
only a few fields are required by the framework and the schema can easily
be adapted for application specific needs.

   The mandatory fields in the main table are the order_no field, which
should be a primary key on the table, and the status field.  The status
field is used to track the order process.

   You may also want to add monetary fields for total, subtotal and for
the taxes, shipping and discount informations since that will always be
available in the order.

   The mandatory fields in the items table is order_no which links the
items to the order table. What will be inserted in that table are the cart
items, so you may want to use the following fields : price, subtotal,
quantity and fields for the discount information.

ORDER PROFILES
==============

   The order profiles is a file which is C{eval}-ed at runtime. (It is
also reloaded whenever it changes on disk. It should return an hash
reference which contains the name of a profile associated with an hash
reference which may contains the following items :

order_template
     The record template that will be used to insert the order
     informations.

order_item_template
     The record template that will be used to insert order items.

order_no
     The template query that will be used to generate order number.

taxes_fields
     The field names that should be given to the order's taxes. This is an
     array reference which defaults to [taxes0, taxes1, taxes2...] if there
     is more than one taxes or [ taxes ] if there is only one taxes.

shipping_fields
     The field names that should be given to the order's shipping charges.
     This is an array reference which defaults to [ shipping0, shipping1,
     shipping2...] if there more than one shipping charges or [ shipping ]
     if only one is present.

discount_fields
     The field names that should be given to the order's discounts.  This
     is an array reference which defaults to [discount0, discount1,
     discount2...] if there more than one discount or [ discount ] if only
     one is present.

item_discount_fields
     The field names that should be given to the items' discounts.  This
     is an array reference which defaults to [discount0, discount1,
     discount2...] if there more than one discount or [ discount ] if only
     one is present.

     Example of an order profile :

     {
     	order =>
     	{
     	    order_template	    => "order",
     	    order_item_template	    => "order_items",
     	    order_no		    => "order_no",
     	    taxes_fields	    => [qw( gst gsp ) ],
     	},
     }

INITIALIZATION
==============

   An object is automatically initialized on each request by the
Apache::iNcom framework. It is accessible through the $Order global
variable in Apache::iNcom pages.

METHODS
=======

checkout ( $name, $cart, $order_data )
--------------------------------------

   This method enter the user order in the database. It takes the following
parameters :

$name
     The name of the order profile to use.

$cart
     The cart that contains the user's order.

$order_data
     An hash reference which contains other informations that should be
     stored with the order. (Like customer's name and address for example.)

   The cart is emptied if the checkout is successful. NOTE: This is the
only method in the framework that will do an explicit commit to make sure
that the order is correctly entered in the database.

   The method returns an hash references which contains the order
informations.

order_report ( $order, $template )
----------------------------------

   This method will generate an order report for a particular order. The
first parameter is the order as returned by checkout, the second is the
template file that should be used. This is a standard Apache::iNcom pages.
The report will be generated in the namespace of the calling page, so
standard Apache::iNcom globals will be accessible. DONT ABUSE IT. Also the
order for which the report is generated will be accessible through the
%order global hash.

AUTHOR
======

   Copyright (c) 1999 Francis J. Lacoste and iNsu Innovations Inc.  All
rights reserved.

   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.

SEE ALSO
========

   Apache::iNcom(3) Apache::iNcom::Request(3) Apache::iNcom::CartManager(3)

Manages the Apache::iNcom request's informations.
*************************************************

NAME
====

   Apache::iNcom::Request - Manages the Apache::iNcom request's
informations.

SYNOPSIS
========

     my $user = $Request->user

     etc.

DESCRIPTION
===========

   This module is responsible for managing the environment in which the
Apache::iNcom page will execute. It setups all the objects that will be
accessible to the pages through globals and also provides the page with a
bunch of utility functions. It also provides a bunch of methods for
managing the information associated with the request.

INITIALIZATION
==============

   An object is automatically initialized on each request by the
Apache::iNcom framework. It is accessible through the $Request global
variable in Apache::iNcom pages.

logged_in
---------

   Returns true if the request is associated with a UserDB's user.

user
----

   Returns the UserDB's user associated with the current request.

current
-------

   Returns the name of the current page relative to INCOM_PREFIX.

previous
--------

   Returns the name of the previous page fetched by the user.

browser
-------

   Returns the user agent string sent by the user's browser.

remote_host
-----------

   Returns the hostname of the user. This can be an IP address is hostname
resolution is turn off.

remote_ip
---------

   Returns the ip address of the user.

login ( $username, $password )
------------------------------

   Invokes the login methods of the UserDB and if the login succeeded, the
user will be associated with the current Session, and its informations
will be available on each subsequent requests until the user logout.

logout
------

   Removes the association between the user and the request.

APACHE::INCOM PAGE GLOBALS
==========================

   Here is a list of the global variables that are defined in the page when
it is executing.

$Request
     An Apache::iNcom::Request object which can used to query information
     about the current request.

$DB
     A DBIx::SearchProfiles object initialized with as requested by the
     Apache::iNcom configuration.

$Cart
     An Apache::iNcom::CartManager object initialized with the configured
     pricing profile.

$Order
     An Apache::iNcom::OrderManager object initialized with the configured
     order profiles.

%Session
     A hash which associated with the current client. Values in that hash
     will persist across request until the user close its browser or
     INCOM_SESSION_EXPIRES time has elapsed.

%UserSession
     A hash which associated with the user currently logged. Values in that
     hash will persist across request as long as the client is logged in
     and will be cleared once the user logs out.

$UserDB
     A DBIx::UserDB object which should be used for user management.

$Validator
     An HTML::Validator object initialized with the configured input
     profiles.

$Localizer
     An Apache::iNcom::Localizer object initialized with the user requested
     language.

$Locale
     A Locale::Maketext object initialized with the proper locale. The
     Locale::Maketext subclass used is specified in the INCOM_LOCALE
     configuration directives.

APACHE::INCOM PAGE FUNCTIONS
============================

   Here is list of the helper functions that are defined in the context of
the executing page and that can be used.

Localize ( ... )
----------------

   This acts as a wrapper around $Locale->maketext. It should be used to
format messages in a localized format for the user.

Currency ( ... )
----------------

   This acts as a wrapper around $Locale->currency. It should be used to
format amount of money for display.

Include ( $file_or_param_ref )
------------------------------

   This is a function which is like HTML::Embperl::Execute in that it
includes another page in the current one. The difference is that this
included page will be executed in the name space of the current so that
all global variables remains accessible. Also, this functions checks for
the presence of a localized version of the file and checks in the
INCOM_TEMPLATE_PATH if the path is not absolute.

TextInclude ( file )
--------------------

   This is a function is like `Include' except that it is not interpreted
for embedded perl.

QueryArgs ( [ $fdat ], [ $odat ], [ $idat ] )
---------------------------------------------

   This function is similar to the [$ hidden $] directive in HTML::Embperl
but instead of generating hidden input fields, it returns the form data as
a query string.

$fdat
     The form data to output. Defaults to the %fdat hash.

$odat
     Override data. Fields present in that hash will override the one in
     %fdat.

$idat
     Ignored data. Fields present in that hash will be ignored and not
     output in the resulting query string.

     Usage example :

     <a href="search.html?[- QueryArgs() -]">Next</a>

AUTHOR
======

   Copyright (c) 1999 Francis J. Lacoste and iNsu Innovations Inc.  All
rights reserved.

   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.

SEE ALSO
========

   Apache::iNcom(3) Apache::iNcom::OrderManager(3)
Apache::iNcom::CartManager(3) DBIx::SearchProfiles(3) DBIx::UserDB(3)
Locale::Maketext(3) HTML::Embperl

Apache::Session implementation for Apache::iNcom
************************************************

NAME
====

   Apache::iNcom::Session - Apache::Session implementation for
Apache::iNcom

SYNOPSIS
========

   use Apache::iNcom::Session;

DESCRIPTION
===========

   This is a subclass of Apache::Session used by the iNcom framework.
This Apache::Session implementation used the DBIBase64Store and NullLocker
for handling session persistence.

   The other special thing about this implementation is that session IDs
are 128bits long and generated using the /dev/urandom device if available.

   This is a security feature to make session id very hard to guess.

AUTHOR
======

   Copyright (c) 1999 Francis J. Lacoste and iNsu Innovations Inc.  All
rights reserved.

   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.

SEE ALSO
========

   Apache::iNcom(3) Apache::Session(3) Apache::Session::DBIBase64Store(3)
Apache::Session::NullLocker(3)

Manage locks for iNcom's sessions.
**********************************

NAME
====

   Apache::iNcom::SessionLocker - Manage locks for iNcom's sessions.

SYNOPSIS
========

     package MySession;

     sub get_lock_manager {
     	my $self = shift;

     return new Apache::iNcom::SessionLocker;
         }

DESCRIPTION
===========

   Apache::iNcom::SessionLocker will serialize access to the sessions if
the configuration directive INCOM_SESSION_SERIALIZE_ACCESS is set.

   A maximum of 5 seconds is waited for lock.

SCHEMA
======

   This modules expect a table created with the following schema :

     CREATE TABLE sessions (
     	id	    CHAR(32) PRIMARY KEY,
     	length	    INT,
     	a_session   TEXT,
     	created	    TIMESTAMP DEFAULT 'now()',
     	last_update TIMESTAMP DEFAULT 'now()',
     	locked_by   INT
     );

   The previous SQL statement is valid for PostgreSQL. Adapt for your
specific DBMS.

AUTHOR
======

   Copyright (c) 1999 Francis J. Lacoste and iNsu Innovations Inc.  All
rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the terms as perl itself.

SEE ALSO
========

   Apache::Session(3) Apache::Session::DBIStore(3) DBI(3)

mod_perl authentication handler that use the UserDB.
****************************************************

NAME
====

   Apache::iNcom::UserDBAuthen - mod_perl authentication handler that use
the UserDB.

SYNOPSIS
========

     PerlRequire	Apache::iNcom:UserDBAuthen

     AuthType Basic
     AuthName "iNcom Users"

     PerlAuthenHandler	Apache::iNcom::UserDBAuthen

     require valid-user

DESCRIPTION
===========

   This module integrates the DBIx::UserDB modules used by the
Apache::iNcom with the apache authentication phase.

   This module can either try to authenticate the user by trying to
login() on the standard DBIx::UserDB object. Or it can set the username
associated with the connection based on the login status set in the
Apache::iNcom session.

CONFIGURATION
=============

   This module takes on configuration directive `INCOM_AUTH_SESSION'.  Set
it to true to sync the Apache authentication status with the one in the
Apache::iNcom session.

   If this directive is set to false or left undefined. The module will
authenticate the user against the default Apache::iNcom DBIx::UserDB
object.

   The DBIx::UserDB used in the process is configured via the normal
Apache::iNcom directives.

AUTHOR
======

   Copyright (c) 1999 Francis J. Lacoste and iNsu Innovations Inc.  All
rights reserved.

   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.

SEE ALSO
========

   Apache::iNcom(3) DBIx::UserDB(3) Apache::iNcom::UserDBAuthz(3)

mod_perl authorization handler that use the UserDB.
***************************************************

NAME
====

   Apache::iNcom::UserDBAuthz - mod_perl authorization handler that use
the UserDB.

SYNOPSIS
========

     PerlRequire	Apache::iNcom:UserDBAuthz

     AuthType Basic
     AuthName "iNcom Users"

     PerlAuthenHandler	Apache::iNcom::UserDBAuthen
     PerlAuthzHandler	Apache::iNcom::UserDBAuthz

     require valid-user

     require user foo

     require group bar

     require user foo and write

     require group baz; exec on test

     require valid-user, admin code

DESCRIPTION
===========

   This module integrates the DBIx::UserDB module used by the
Apache::iNcom framework with the apache authorization phase.

   This module will set the authorization on the authenticated user by
checking the DBIx::UserDB ACL.

CONFIGURATION
=============

   The DBIx::UserDB used is configured via the normal Apache::iNcom
directives.

REQUIREMENTS DIRECTIVES
=======================

   This module will let the user if ANY require directives match. This
means that different require ar ORed together.

   In a require directive, different clause can be ANDed together by
separating them by and, comma (,) or semi-colon (;).

   Here are the different expression that are understood by the module.

valid-user
     This requirements will pass everytime the user was authenticated
     successfully.

user <username>
     This requirement will succeed if the user's username is identical.

group <groupname>
     This requirement will suceed if the user is a member of that group.

<privilege>
     This requirement will succeed if the user has the specified privilege
     on the current URL. The INCOM_URL_PREFIX is stripped from the URL.
     The privilege is checked by using the allowed method of the UserDB.

<privilege> [on] <target>
     This requirement will succeed if the user has the specified privilege
     on the specified target. The privilege is checked by using the
     allowed method of the UserDB.

AUTHOR
======

   Copyright (c) 1999 Francis J. Lacoste and iNsu Innovations Inc.  All
rights reserved.

   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.

SEE ALSO
========

   Apache::iNcom(3) DBIx::UserDB(3) Apache::iNcom::UserDBAuthen(3)

Generate compiler and linker flags for libapreq
***********************************************

NAME
====

   Apache::libapreq - Generate compiler and linker flags for libapreq

SYNOPSIS
========

     #Makefile
     CCOPTS = `perl -MApache::libapreq -e ccopts`
     LDOPTS = `perl -MApache::libapreq -e ldopts`

DESCRIPTION
===========

   The *libapreq* package installs libraries and include files into Perl
architecture dependent locations.

FUNCTIONS
=========

ccopts
     Simply invokes:

          print "-I$Config{installsitearch}/auto/libapreq/include"

ldopts
     Simply invokes:

          print "-L$Config{installsitearch}/auto/libapreq -lapreq"

AUTHOR
======

   Doug MacEachern

   my $src = Apache::src->new;

   for my $path ($src->find) {     my $mmn =
$src->module_magic_number($path);     my $v   = $src->httpd_version($path);
   next unless $v;     print "path = $path ($mmn,$v)\n";     my $dir =
$src->prompt("Configure with $path?"); }

Methods for locating and parsing bits of Apache source code
***********************************************************

NAME
====

   Apache::src - Methods for locating and parsing bits of Apache source
code

SYNOPSIS
========

     use Apache::src ();
     my $src = Apache::src->new;

DESCRIPTION
===========

   This module provides methods for locating and parsing bits of Apache
source code.

METHODS
=======

new
     Create an object blessed into the *Apache::src* class.

          my $src = Apache::src->new;

dir
     Top level directory where source files are located.

          my $dir = $src->dir;
          -d $dir or die "can't stat $dir $!\n";

main
     Apache's source tree was reorganized during development of version
     1.3.  So, common header files such as `httpd.h' are in different
     directories between versions less than 1.3 and those equal to or
     greater.  This method will return the right directory.

     Example:

          -e join "/", $src->main, "httpd.h" or die "can't stat httpd.h\n";

find
     Searches for apache source directories, return a list of those found.

     Example:

          for my $dir ($src->find) {
             my $yn = prompt "Configure with $dir ?", "y";
             ...
          }

inc
     Print include paths for MakeMaker's INC argument to `WriteMakefile'.

     Example:

          use ExtUtils::MakeMaker;

          use Apache::src ();

          WriteMakefile(
              'NAME'    => 'Apache::Module',
              'VERSION' => '0.01',
              'INC'     => Apache::src->new->inc,
          );

module_magic_number
     Return the *MODULE_MAGIC_NUMBER* defined in the apache source.

     Example:

          my $mmn = $src->module_magic_number;

httpd_version
     Return the server version.

     Example:

          my $v = $src->httpd_version;

otherldflags
     Return other ld flags for MakeMaker's dynamic_lib argument to
     `WriteMakefile'. This might be needed on systems like AIX that need
     special flags to the linker to be able to reference mod_perl or httpd
     symbols.

     Example:

          use ExtUtils::MakeMaker;

          use Apache::src ();

          WriteMakefile(
              'NAME'        => 'Apache::Module',
              'VERSION'     => '0.01',
              'INC'         => Apache::src->new->inc,
              'dynamic_lib' => {
          	 'OTHERLDFLAGS' => Apache::src->new->otherldflags,
              },
          );

AUTHOR
======

   Doug MacEachern

Facilitates testing of Apache::* modules
****************************************

NAME
====

   Apache::Test - Facilitates testing of Apache::* modules

SYNOPSIS
========

     # In Makefile.PL
     use Apache::test;
     my %params = Apache::test->get_test_params();
     Apache::test->write_httpd_conf(%params, include => $more_directives);
     *MY::test = sub { Apache::test->MM_test(%params) };

     # In t/*.t script (or test.pl)
     use Apache::test qw(skip_test have_httpd);
     skip_test unless have_httpd;
     (Some more methods of Doug's that I haven't reviewed or documented yet)

DESCRIPTION
===========

   This module helps authors of Apache::* modules write test suites that
can query an actual running Apache server with mod_perl and their modules
loaded into it.  Its functionality is generally separated into methods
that go in a Makefile.PL to configure, start, and stop the server, and
methods that go in one of the test scripts to make HTTP queries and manage
the results.

METHODS
=======

get_test_params()
-----------------

   This will ask the user a few questions about where the httpd binary is,
and what user/group/port should be used when running the server.  It will
return a hash of the information it discovers.  This hash is suitable for
passing to the `write_httpd_conf()' method.

write_httpd_conf(%params)
-------------------------

   This will write a basic httpd.conf file suitable for starting a HTTP
server during the 'make test' stage.  A hash of key/value pairs that
affect the written file can be passed as arguments.  The following keys
are recognized:

   * conf_file

     The path to the file that will be created.  Default is 't/httpd.conf'.

   * port

     The port that the Apache server will listen on.

   * user

     The user that the Apache server will run as.

   * group

     The group that the Apache server will run as.

   * include

     Any additional text you want added at the end of the config file.
     Typically you'll have some `PerlModule' and `Perl*Handler' directives
     to pass control to the module you're testing.  The `blib/'
     directories will be added to the `@INC' path when searching for
     modules, so that's nice.

MM_test(%params)
----------------

   This method helps write a Makefile that supports running a web server
during the 'make test' stage.  When you execute 'make test', 'make' will
run 'make start_httpd', 'make run_tests', and 'make kill_httpd' in
sequence.  You can also run these commands independently if you want.

   Pass the hash of parameters returned by get_test_params() as an
argument to `MM_test()'.

   To patch into the ExtUtils::MakeMaker wizardry (voodoo?), typically
you'll do the following in your Makefile.PL:

     *MY::test = sub { Apache::test->MM_test(%params) };

fetch
-----

     Apache::test->fetch($request);
     Apache::test->fetch($user_agent, $request);

   Call this method in a test script in order to fetch a page from the
running web server.  If you pass two arguments, the first should be an
LWP::UserAgent object, and the second should specify the request to make
of the server.  If you only pass one argument, it specifies the request to
make.

   The request can be specified either by a simple string indicating the
URI to fetch, or by a hash reference, which gives you more control over
the request.  The following keys are recognized in the hash:

   * uri

     The URI to fetch from the server.  If the URI does not begin with
     "http", we prepend "http://localhost:$PORT" so that we make requests
     of the test server.

   * method

     The request method to use.  Default is 'GET'.

   * content

     The request content body.  Typically used to simulate HTML fill-out
     form submission for POST requests.  Default is null.

   * headers

     A hash of headers you want sent with the request.  You might use this
     to send cookies or provide some application-specific header.

   If you don't provide a 'headers' parameter and you set the 'method' to
'POST', then we assume that you're trying to simulate HTML form submission
and we add a 'Content_Type' header with a value of
'application/x-www-form-urlencoded'.

   In a scalar context, fetch() returns the content of the web server's
response.  In a list context, fetch() returns the content and the
HTTP::Response object itself.  This can be handy if you need to check the
response headers, or the HTTP return code, or whatever.

static_modules
--------------

     Example: $mods = Apache::test->static_modules('/path/to/httpd');

   This method returns a hashref whose keys are all the modules statically
compiled into the given httpd binary.  The corresponding values are all 1.

EXAMPLES
========

   No good examples yet.  Example submissions are welcome.  In the
meantime, see `http:' in this node , which I'm retrofitting to use
Apache::test.

TO DO
=====

   The MM_test method doesn't try to be very smart, it just writes the
text that seems to work in my configuration.  I am morally against using
the 'make' command for installing Perl modules (though of course I do it
anyway), so I haven't looked into this very much.  Send bug reports or
better (patches).

   I've got lots of code in my Apache::AuthCookie module (etc.) that
assists in actually making the queries of the running server.  I plan to
add that to this module, but first I need to compare what's already here
that does the same stuff.

KUDOS
=====

   To Doug MacEachern for writing the first version of this module.

   To caelum@debian.org (Rafael Kitover) for contributing the code to
parse existing httpd.conf files for -enable-shared=max and DSOs.

CAVEATS
=======

   Except for making sure that the mod_perl distribution itself can run
'make test' okay, I haven't tried very hard to keep compatibility with
older versions of this module.  In particular MM_test() has changed and
probably isn't usable in the old ways, since some of its assumptions are
gone.  But none of this was ever documented, and MM_test() doesn't seem to
actually be used anywhere in the mod_perl disribution, so I don't feel so
bad about it.

AUTHOR
======

   Doug MacEachern (original version)

   Ken Williams (latest changes and this documentation)

Perl5 extension for managing global application configuration information.
**************************************************************************

NAME
====

   App::Config - Perl5 extension for managing global application
configuration information.

SYNOPSIS
========

     use App::Config;
     my $cfg = App::Config->new();

     $cfg->define("foo");            # very simple variable definition

     $cfg->set("foo", 123);          # trivial set/get examples
     $fval = $cfg->get("foo");

     $cfg->foo(456);                 # direct variable access

     $cfg->cfg_file(".myconfigrc");  # read config file
     $cfg->cmd_line(\@ARGV);         # process command line

OVERVIEW
========

   App::Config is a Perl5 module to handle global configuration variables
for perl programs.  The advantages of using such a module over the
standard "global variables" approach include:

   * Reduction of clutter in the main namespace.

   * Default values can be specified.

   * Multiple names (aliases) can refer to the same variable.

   * Configuration values can be set directly from config files and/or
     command line arguments.

   * Data values can be automatically validated by pattern matching (e.g.
     "\d+" to accept digits only) or through user-supplied routines.

   * User-defined routines can be called automatically when configuration
     values are changed.

PREREQUISITES
=============

   App::Config requires Perl version 5.004 or later.  If you have an older
version of Perl, please upgrade to latest version.  Perl 5.004 is known to
be stable and includes new features and bug fixes over previous versions.
Perl itself is available from your nearest CPAN site (see
http://www.perl.com/CPAN).

INSTALLATION
============

   To install this module type the following:

     perl Makefile.PL
     make
     make install

   The 'make install' will install the module on your system.  You may need
root access to perform this task.  If you install the module in a local
directory (for example, by executing "perl Makefile.PL LIB=~/lib" in the
above - see `perldoc MakeMaker' for full details), you will need to ensure
that the PERL5LIB environment variable is set to include the location, or
add a line to your scripts explicitly naming the library location:

     use lib '/local/path/to/lib';

DESCRIPTION
===========

USING THE App::Config MODULE
----------------------------

   To import and use the App::Config module the following line should
appear in your Perl script:

     use App::Config;

     App::Config is implemented using object-oriented methods.  A new App::Config
     object is created and initialised using the App::Config->new() method.
     This returns a reference to a new App::Config object.

         my $cfg = App::Config->new();

   This will create a reference to a new App::Config with all configuration
options set to their default values.  You can initialise the object by
passing a hash array reference containing configuration options:

     $cfg = App::Config->new( {
     	CASE      => 1,
     	FILEPARSE => \&my_parser,
     	ERROR     => \&my_error,
     } );

   The following configuration options may be specified.  Some of these use
default values as may be specified in the GLOBAL configuration option.

CASE
     Determines if the variable names are treated case sensitively.  Any
     non-zero value makes case significant when naming variables.  By
     default, CASE is set to 0 and thus "Variable", "VARIABLE" and
     "VaRiAbLe" are all treated as "variable".

ERROR
     Specifies a user-defined error handling routine.  A format string is
     passed as the first parameter, followed by any additional values, as
     per printf(3C).

FILEPARSE
     Specifies a user-defined routine for parsing a configuration file.
     The function is called by `cfg_file()' and is passed a reference to
     the App::Config object and the name of the file to parse.  The routine
     should update any variable values directly.  The return value is
     expected to be 1 to indicate success or 0 to indicate failure.  This
     value is returned directly from `cfg_file()';

     Pseudo-Code Example:

          $cfg = App::Config->new( { FILEPARSE => \&my_parser } );

          sub my_parser {
          	my $cfg  = shift;
          	my $file = shift;

          # open file, read lines, etc.
          # ...
          $cfg->set($variable, $value);  # set variable value
          # close file, etc.

          return 1;
              }

LINEPARSE
     Instead of providing a routine to parse the entire config file,
     LINEPARSE can be used to define a function to handle each line of the
     config file.  The `cfg_file()' routine reads the file and passes each
     line to the LINEPARSE function, where defined.

     Four parameters are passed to the LINEPARSE function:

        * a reference to the App::Config object

        * the config filename

          The function should return 1 to indicate that the line has been
          successfully parsed, or 0 to indicate that no action was taken
          and the default line parser should now be used for this line.

        * the current line number within the file, and

        * the line of text itself (the filename and line number are useful
          for reporting errors).

     Note that `cfg_file()' does some elementary pre-processing before
     calling the LINEPARSE function.  See `READING A CONFIGURATION FILE'
     in this node for more details.

CMDPARSE
     Specifies a user-defined routine for parsing the command line.  The
     function is called by cmd_line() and is passed a reference to the
     App::Config object and a reference to a list of command line
     arguments (usually @ARGV).

     The function is required to set variable values directly and return 1
     or 0 to indicate success or failure, as is described in the FILEPARSE
     section above.

ARGPARSE
     Just as a LINEPARSE routine can be defined to parse each line of a
     config file, an ARGPARSE routine can also be specified to parse each
     command line argument.  The function is called from cmd_line() and is
     passed a reference to the App::Config object through which variable
     values can be manipulated.  Other parameters passed are the command
     line argument in question (e.g.  `"-v"'), the name of the variable to
     which it corresponds (e.g. `"verbose"') and a reference to the
     remaining argument list.  The function is expected to modify the
     argument list if necessary, shifting off additional parameters where
     required.

     A pseudo-code example is shown:

          my $cfg = App::Config->new( { ARGPARSE => \&my_arg_parse, } );

          sub my_arg_parse {
          	my $cfg     = shift;
          	my $arg     = shift;
          	my $var     = shift;
          	my $argvref = shift;

          VAR: {
              $var eq 'verbose' && do {
          	$cfg->set($var, 1);
          	last VAR;
              };

          # this time, look at $arg instead of $var
          $arg eq '-f' && do {
          		$cfg->set($var, shift(@$argvref));  # should error check
          		last VAR;
          };

          # not interested in anything else
          # (let default parser have a go)
          return 0;
          	}

          # we processed it so return 1
          return 1;
              }

CMDENV
     The CMDENV option is used to specify the name of an environment
     variable which may contain default command line options.  If defined,
     the variable is examined by the cmd_line() routine where it is split
     into whitespace separated tokens and parsed along with the rest of
     the command line options.  Environment variable options are processed
     before any real command line options.

     Note that the variable is split on whitespace and does not take into
     account quoted whitespace.  Thus 'foo "bar baz" qux' will be split
     into the tokens 'foo', '"bar', 'baz"' and 'qux'.  This will be fixed
     in a future release.

     From the Unix shell:

          $ SPLATOPTS="-z -f foobar"

     Perl App::Config usage:

          my $cfg = App::Config->new( { CMDENV => "SPLATOPTS" } );

          $cfg->cmd_line(\@ARGV);   # parses ("-z", "-f", "foobar", @ARGV)

ENDOFARGS
     The ENDOFARGS option can be used to specify the marker that signifies
     the end of the command line argument list.  Typically, and by
     default, this is '-'.  Any arguments appearing in the command line
     after this token will be ignored.

          my $cfg = App::Config->new( { ENDOFARGS => "STOP" } );

          @args = qw(-f -g -h STOP -i -am -ignored);
          $cfg->cmd_line(\@args);

          # @args now contains qw(-i -am -ignored)

GLOBAL
     The GLOBAL option allows default values to be set for the ARGCOUNT,
     EXPAND, CMDARG and VALIDATE options for all variables.  `DEFINING
     VARIABLES' in this node below describes these options in detail.

     The CMDARG global option, when set to any true value, specifies that
     the command line option for any variable should be of the form
     "-variable".  Any aliases specified for a variable can also be used
     in this way.  e.g.

          my $cfg = App::Config->new({
          	    GLOBAL => { ARGCOUNT => 1, CMDARG => 1 }
          	});

          $cfg->define("foo", {
          	    ALIAS  => 'bar'
          	});

     The GLOBAL ARGCOUNT parameter specifies that the foo variable expects
     an argument.  An ARGCOUNT option specified in the define() method
     call would override this default.  The GLOBAL CMDARG option specifies
     that the 'foo' variable should be specified on the command line as
     '-foo'.  The ALIAS name for foo can also be specified as such: '-bar'.

DEFINING VARIABLES
------------------

   The define() function is used to pre-declare a variable and specify its
configuration.

     $cfg->define("foo");

   In the simple example above, a new variable called "foo" is defined.  A
reference to a hash array may also be passed to specify configuration
information for the variable:

     $cfg->define("foo", {
     	    DEFAULT   => 99,
     	    ALIAS     => 'metavar1',
     	});

   The following configuration options may be specified

DEFAULT
     The DEFAULT value is used to initialise the variable.  The variable
     remains set to this value unless otherwise changed via set(),
     `cfg_file()' or `cmd_line()'.

ALIAS
     The ALIAS option allows a number of alternative names to be specified
     for this variable.  A single alias should be specified as a string,
     multiple aliases as a reference to an array.  e.g.:

          $cfg->define("foo", {
          	    ALIAS  => 'metavar1',
          	});

     or

          $cfg->define("bar", {
          	    ALIAS => [ 'metavar2', 'metalrod', 'boozer' ],
          	});

     In the first example, `$cfg->set("metavar1")' (or any other
     variable-related function) is equivalent to `$cfg->set("foo")'.
     Likewise for the second example, with all 3 aliases defined.

CMDARG
     When processing a list of command line arguments, flags may be used to
     refer to certain variable values.  For example, -v is a common flag
     indicating verbose mode.  The 'verbose' variable might be defined as
     such:

          $cfg->define("verbose", {
          	    CMDARG => '-v',
          	});

     If the `cmd_line()' function detects -v in the command line arguments,
     it will update the 'verbose' value.  See also the ARGCOUNT option
     below which influences the variable values that are set by the
     command line processing function.

     A variable may have more than one related command line argument.
     These can be specified by passing a reference to an array of
     arguments:

          $cfg->define("verbose", {
          	    CMDARG => [ '-v', '-V' ],
          	});

     If the GLOBAL CMDARG variable is set (see GLOBAL in `DESCRIPTION' in
     this node above) then the default CMDARG for each variable will be
     its name (and any aliases) prefixed by a dash, e.g. '-verbose'.  Any
     CMADRG value specifically set will override this default.

ARGCOUNT
     Some variables are intended to be simple flags that have a false/true
     (zero/non-zero) value (e.g. the 'verbose' example above) while others
     may require mandatory arguments (e.g. specifying a file: `"-f
     filename"').  The ARGCOUNT value is used to determine if an
     additional argument is expected (`ARGCOUNT => 1') or not (`ARGCOUNT
     => 0').

     When ARGCOUNT is 1, `cfg_file()' passes the rest of the config line
     (after the opening variable name has been removed) as the argument
     value and `cmd_line()' passes the next argument from the command line
     argument list (usually @ARGV).  When ARGCOUNT is 0, both functions
     pass the value 1 to set the variable to a true state.  The default
     ARGCOUNT value is 0.

     If the GLOBAL ARGCOUNT variable is set (see GLOBAL in `DESCRIPTION'
     in this node above) then this value will be used as the default
     ARGCOUNT for each variable unless otherwise specified.

     NOTE: Although any non-zero value can be used to indicate the
     presence of an additional argument, this option may be extended in
     the future to handle multiple arguments.  The behaviour associated
     with any value other than 1 or 0 may change in subsequent versions.

EXPAND
     Variable values specified in a configuration file (see `READING A
     CONFIGURATION FILE' in this node) may contain environment variables,
     other App::Config variables and/or users' home directories specified
     in tilde notation (e.g. ~abw).  The EXPAND option specifies if these
     variables should be replaced with their relevant values.  By default
     EXPAND is set to 1 (expansion) but can be set to 0 to disable the
     feature.

     If the GLOBAL EXPAND variable is set (see GLOBAL in <DESCRIPTION>
     above) then this value will be used as the default EXPAND for each
     variable unless otherwise specified.

     Items are expanded according to the following rules:

        * A directory element specified in tilde notation is expanded to
          the full directory path it represents (e.g. ~abw/lib =>
          /user/abw/lib).  A tilde by itself expands to the home directory
          of the current user (e.g.  ~/lib => /users/abw/lib).  If a
          non-existant user is specified or it is not possible to
          determine the home directory of the user, the tilde notation is
          left unexpanded (e.g. ~nosuchuser/lib).

        * A variable enclosed in braces and prefixed with a dollar symbol
          (e.g.  ${HOME}) is assumed to be an environment variable and is
          expanded as such.  A non-existant variable will be replaced by
          an empty string, as is typical in UNIX shell expansion (e.g.
          ${DUD}/lib => /lib).

        * A variable enclosed in parenthesis and prefixed with a dollar
          symbol (e.g.  $(ROOT)) is assumed to refer to another variable
          defined in the current App::Config object.  Case sensitivity is
          applied as per the current CASE setting and non-existant
          variables are replaced by an empty string as per environment
          variables (e.g. $(mipspelt)/lib => /lib).

        * A variable prefixed with a dollar and with no enclosing braces or
          parenthesis (e.g. $root/lib) is first interpreted as an
          App::Config variable and if not resolved, as an environment
          variable.  If the variable cannot be evaluated in either context
          it is ignored and the original text is left unmodified.

VALIDATE
     Each variable may have a sub-routine or regular expression defined
     which is used to validate the intended value that is set by
     `cfg_file()' and `cmd_line()'.

     If VALIDATE is defined as a simple string, it is applied as a regular
     expression to the value read from the config file or command line.  If
     the regex matches, the value is set.  If not, a warning message is
     generated.

     VALIDATE may also be defined as a reference to a sub-routine which
     takes as its arguments the name of the variable and its intended
     value.  The sub-routine should return 1 or 0 to indicate that the
     value is valid or invalid, respectively.  An invalid value will cause
     a warning error message to be generated.

     If the GLOBAL VALIDATE variable is set (see GLOBAL in `DESCRIPTION'
     in this node above) then this value will be used as the default
     VALIDATE for each variable unless otherwise specified.

ACTION
     The ACTION option allows a sub-routine to be bound to a variable that
     is executed whenever the variable is set.  The ACTION is passed a
     reference to the App::Config object, the name of the variable and the
     value of the variable.

     The ACTION routine may be used, for example, to post-process variable
     data, update the value of some other dependant variable, generate a
     warning message, etc.

     Example:

          sub my_notify {
          	my $cfg = shift;
          	my $var = shift;
          	my $val = shift;

          print "$variable set to $value\n";
              }

     Be aware that calling `$cfg->set()' to update the variable from within
     the ACTION function will cause a recursive loop as the ACTION
     function is repeatedly called.  This is probably a bug, certainly a
     limitation.

READING AND MODIFYING VARIABLE VALUES
-------------------------------------

   App::Config defines two methods to manipulate variable values:

     set($variable, $value);
     get($variable);

   Both functions take the variable name as the first parameter and set()
takes an additional parameter which is the new value for the variable.
set() returns 1 or 0 to indicate successful or unsuccessful update of the
variable value.  If there is an ACTION routine associated with the named
variable, the value returned will be passed back from set().  The get()
function returns the current value of the variable.

   Once defined, variables may be accessed directly as object methods where
the method name is the same as the variable name.  i.e.

     $cfg->set("verbose", 1);

   is equivalent to

     $cfg->verbose(1);

   Without parameters, the current value of the variable is returned.  If
a parameter is specified, the variable is set to that value and the
original value (before modification) is returned.

     $cfg->age(28);
     $cfg->age(29);  # sets 'age' to 29, returns 28

READING A CONFIGURATION FILE
----------------------------

   App::Config can be used to read configuration files and automatically
update variable values based on the contents of the file.

     $cfg->cfg_file("$HOME/.myapprc");

   The `cfg_file()' function reads each line of the specified configuration
file and processes them according to the following rules:

   * Any lines ending with a backslash '\' are treated as continuation
     lines.  The following line is appended to the current line (and any
     subsequent continuation lines) before any further processing.

   * Any blank lines or lines starting with a '#' (i.e. comments) are
     ignored.

   * Leading and trailing whitespace is ignored.

   * The line is separated at the first whitespace character or at the
     first `'='' character (surrounding whitespace is ignored).

   * A variable by itself with no corresponding value will be treated as a
     simple flag if it's ARGCOUNT is 0.  In this case, the value for the
     variable will be set to 1.

   The following example demonstrates a typical configuration file:

     # simple flag (same as " verbose 1" or "verbose = 1")
     verbose

     # the following lines are all equivalent
     file     /tmp/foobar
     file  =  /tmp/foobar
     file=/tmp/foo

PARSING THE COMMAND LINE
------------------------

   By specify CMDARG values for defined variables, the `cmd_line()'
function can be used to read the command line parameters and automatically
set variables.

   When an command line argument matches a CMDARG value, the variable it
relates to is updated.  If the variable has an ARGCOUNT of 0, it will be
assigned the value 1 (i.e. the flag is set).  A variable with an ARGCOUNT
of 1 will be set with the next value in the arguments.  Users familiar with
getopt(3C) will recognise this as equivalent to adding a colon after an
option letter (e.g. `"f:"').  An error is generated if the argument starts
with a '-'.  The special option "-" may be used to delimit the end of the
options.  `cmd_line()' stops processing if it finds this option.

   Example variable definition:

     $cfg->define("verbose", {
     	    CMDARG   => '-v',
     	    ARGCOUNT => 0,      # default anyway
     	});
     $cfg->define("file", {
     	    CMDARG   => '-f',
     	    ARGCOUNT => 1,      # expects an argument
     	});

   Command-line options:

     -v -f foobar

   Variable values after calling `cmd_line(\@ARGV)':

     verbose: 1
     file:    foobar

KNOWN BUGS AND LIMITATIONS
==========================

   The following list represents known limitations or bugs in App::Config
or ways in which it may be improved in the future.  Please contact the
author if you have any suggestions or comments.

   * An ACTION sub-routine may not update its variable via the $cfg->set()
     method.  This causes the ACTION function to be re-executed, starting a
     recursive loop.

   * More extensive variable validation (not using user-defined functions),
     perhaps by defining standard classes (e.g. numeric, filename, list,
     etc).  Variable validation may be also extended to allow manipulation
     of the data as well (e.g. splitting a string into a list).

   * Further extend command line parsing.  Maybe allow regexes to be
     specified for matches (e.g. `"-v(erbose)"') and handle different
     command line characters other than '-' (e.g. `+flag @file').  This
     may also tie in with long (-) and short (-) options and defining
     recognised 'classes' of options.

   * ARGCOUNT should be able to indicate nargs > 1 and have cmd_line
     extract them accordingly.  Perhaps have types, e.g. boolean, single,
     multiple.  The validate function could additionally take an array ref
     which contains code refs or regex's to match each arg.  Should also
     be able to handle multiple options that can be specified separately,
     e.g. `-I/usr/include' `-I/user/abw/include'.

   * An ACCESS parameter could specify which actions may update a variable:
     set(), cfg_file() and/or cmd_line().

   * Allow variables to have related environment variables which are
     parsed by an env_vars() function.

AUTHOR
======

   Andy Wardley, `<abw@cre.canon.co.uk>'

   Web Technology Group, Canon Research Centre Europe Ltd.

   App::Config is based in part on the ConfigReader module, v0.5, by Andrew
Wilcox (currently untraceable).

   Thanks to all the people who have reported bugs and made suggestions.
Special thanks to those who sent patches:

Firestone <fireston@lexmark.com>
     GLOBAL arguments

Blair Zajac <blair@gps.caltech.edu>
     getpw*() check for Win32 compatibility

REVISION
========

   $Revision: 1.9 $

COPYRIGHT
=========

   Copyright (C) 1997,98 Canon Research Centre Europe Ltd.  All Rights
Reserved.

   This module is free software; you can redistribute it and/or modify it
under the term of the Perl Artistic License.

SEE ALSO
========

Andy Wardley's Home Page
     http://www.kfs.org/~abw/

Canon Research Centre Europe

printf(3C)
     The man page for the printf() function, for a description of the
     format parameter to the ERROR routine.
     http://www.cre.canon.co.uk/perl/

The ConfigReader module.
     The module which provided inspiration and ideas for the development of
     App::Config.

Perl module for installing, managing and uninstalling software packages.
************************************************************************

NAME
====

   App::Manager - Perl module for installing, managing and uninstalling
software packages.

SYNOPSIS
========

     use App::Manager; # use appman instead

DESCRIPTION
===========

   Oh well ;) Not written yet! The manager program (appman) has documented
commandlien switches, though.

AUTHOR
======

   Marc Lehmann <pcg@goof.com>.

SEE ALSO
========

   perl(1).

Perl5 module for reading configuration files and parsing command line arguments.
********************************************************************************

NAME
====

   AppConfig - Perl5 module for reading configuration files and parsing
command line arguments.

SYNOPSIS
========

     use AppConfig;

     # create a new AppConfig object
     my $config = AppConfig->new(\%cfg);

     # define a new variable
     $config->define($varname => \%varopts);

     # create/define combined
     my $config = AppConfig->new(\%cfg,
     	    $varname => \%varopts, $varname => \%varopts, ...);

     # set/get the value
     $config->set($varname, $value);
     $config->get($varname);

     # shortcut form
     $config->varname($value);
     $config->varname();

     # read configuration file
     $config->file($file);

     # parse command line options
     $config->args(\@ARGV);

     # advanced command line options with Getopt::Long
     $config->getopt(\@ARGV);

OVERVIEW
========

   AppConfig is a Perl5 module for managing application configuration
information.  It maintains the state of any number of variables and
provides methods for parsing configuration files and command line
arguments.

   Variables values may be set via configuration files.  Variables may be
flags (On/Off), take a single value, or take multiple values stored as a a
list or hash.  The number of arguments a variable expects is determined by
its configuration when defined.

     # flags
     verbose
     nohelp
     debug = On

     # single value
     home  = /home/abw/

     # multiple list value
     file = /tmp/file1
     file = /tmp/file2

     # multiple hash value
     book  camel = Programming Perl
     book  llama = Learning Perl

   The '-' prefix can be used to reset a variable to its default value and
the '+' prefix can be used to set it to 1

     -verbose
     +debug

   Variable, environment variable and tilde (home directory) expansions
can be applied (selectively, if necessary) to the values read from
configuration files:

     home = ~                    # home directory
     nntp = ${NNTPSERVER}        # environment variable
     html = $home/html           # internal variables
     img  = $html/images

   Configuration files may be arranged in blocks as per the style of Win32
"INI" files.

     [file]
     site = kfs
     src  = ~/websrc/docs/$site
     lib  = ~/websrc/lib
     dest = ~/public_html/$site

     [page]
     header = $lib/header
     footer = $lib/footer

   Variables may also be set by parsing command line arguments.

     myapp -verbose -site kfs -file f1 -file f2

   AppConfig provides a simple method (args()) for parsing command line
arguments.  A second method (getopt()) allows more complex argument
processing by delegation to Johan Vroman's Getopt::Long module.

PREREQUISITES
=============

   AppConfig requires Perl 5.004 or later.

   The AppConfig::Getopt module uses Getopt::Long for advanced command-line
option processing and requires version 2.17 or later.  There is also a
simple internal module (AppConfig::Args) for command line parsing that
does not have the flexibility of AppConfig::Getopt but is smaller and
incurs less overhead.  The Getopt::Long module is not required when this is
used.  The Makefile.PL specifies Getopt::Long version 2.17 as a
pre-requisite.  If you wish to use AppConfig without Getopt::Long then
comment out the following line in the Makefile.PL:

     #    'PREREQ_PM'      => { 'Getopt::Long' => 2.17 },

   No action is necessary if you already have Getopt::Long 2.17 or later
installed.  Getopt::Long is available from any CPAN site (see below).

   All AppConfig::* and other modules (e.g. Getopt::Long) are dynamically
loaded by the AppConfig module as and when required.

OBTAINING AND INSTALLING THE AppConfig MODULE BUNDLE
====================================================

   The AppConfig module bundle is available from CPAN.  As the 'perlmod'
manual page explains:

     CPAN stands for the Comprehensive Perl Archive Network.
     This is a globally replicated collection of all known Perl
     materials, including hundreds of unbundled modules.

     [...]

     For an up-to-date listing of CPAN sites, see
     http://www.perl.com/perl/ or ftp://ftp.perl.com/perl/ .

   Within the CPAN archive, AppConfig is in the category:

     12) Option, Argument, Parameter and Configuration File Processing

   The module is available in the following directories:

     /modules/by-module/AppConfig/AppConfig-<version>.tar.gz
     /authors/id/ABW/AppConfig-<version>.tar.gz

   AppConfig is distributed as a single gzipped tar archive file:

     AppConfig-<version>.tar.gz

   Note that "<version>" represents the current AppConfig Revision number,
of the form "2.00".  See the REVISION section below to determine the
current version number for AppConfig.

   Unpack the archive to create a AppConfig installation directory:

     gunzip AppConfig-<version>.tar.gz
     tar xvf AppConfig-<version>.tar

   'cd' into that directory, make, test and install the modules:

     cd AppConfig-<version>
     perl Makefile.PL
     make
     make test
     make install

   The 't' sub-directory contains a number of test scripts that are run
when a 'make test' is run.

   The 'make install' will install the module on your system.  You may need
administrator privileges to perform this task.  If you install the module
in a local directory (for example, by executing "perl Makefile.PL
LIB=~/lib" in the above - see `perldoc MakeMaker' for full details), you
will need to ensure that the PERL5LIB environment variable is set to
include the location, or add a line to your scripts explicitly naming the
library location:

     use lib '/local/path/to/lib';

   The 'examples' sub-directory contains some simple examples of using the
AppConfig modules.

DESCRIPTION
===========

USING THE AppConfig MODULE
--------------------------

   To import and use the AppConfig module the following line should appear
in your Perl script:

     use AppConfig;

   To import constants defined by the AppConfig module, specify the name of
one or more of the constant or tag sets as parameters to use:

     use AppConfig qw(:expand :argcount);

   See `CONSTANT DEFINITIONS' in this node below for more information on
the constant tagsets defined by AppConfig.

   AppConfig is implemented using object-oriented methods.  A new
AppConfig object is created and initialised using the new() method.  This
returns a reference to a new AppConfig object.

   my $config = AppConfig->new();

   This will create and return a reference to a new AppConfig object.

   In doing so, the AppConfig object also creates an internal reference to
an AppConfig::State object in which to store variable state.  All
arguments passed into the AppConfig constructor are passed directly to the
AppConfig::State constructor.

   The first (optional) parameter may be a reference to a hash array
containing configuration information.

     my $config = AppConfig->new({
     	    CASE   => 1,
     	    ERROR  => \&my_error,
     	    GLOBAL => {
     		    DEFAULT  => "<unset>",
     		    ARGCOUNT => ARGCOUNT_ONE,
     		},
     	});

   See AppConfig/State, for full details of the
configuration options available.  These are, in brief:

CASE
     Used to set case sensitivity for variable names (default: off).

CREATE
     Used to indicate that undefined variables should be created
     automatically (default: off).

GLOBAL
     Reference to a hash array of global values used by default when
     defining variables.  Valid global values are DEFAULT, ARGCOUNT,
     EXPAND, VALIDATE and ACTION.

PEDANTIC
     Used to indicate that command line and configuration file parsing
     routines should return immediately on encountering an error.

ERROR
     Used to provide a error handling routine.  Arguments as per printf().

   Subsequent parameters may be variable definitions.  These are passed to
the define() method, described below in `DEFINING VARIABLES' in this node.

     my $config = AppConfig->new("foo", "bar", "baz");
     my $config = AppConfig->new({ CASE => 1 }, qw(foo bar baz));

   Note that any unresolved method calls to AppConfig are automatically
delegated to the AppConfig::State object.  In practice, it means that it
is possible to treat the AppConfig object as if it were an
AppConfig::State object:

     # create AppConfig
     my $config = AppConfig->new('foo', 'bar');

     # methods get passed through to internal AppConfig::State
     $config->foo(100);
     $config->set('bar', 200);
     $config->define('baz');
     $config->baz(300);

DEFINING VARIABLES
------------------

   The define() method (delegated to AppConfig::State) is used to
pre-declare a variable and specify its configuration.

     $config->define("foo");

   Variables may also be defined directly from the AppConfig new()
constructor.

     my $config = AppConfig->new("foo");

   In both simple examples above, a new variable called "foo" is defined.
A reference to a hash array may also be passed to specify configuration
information for the variable:

     $config->define("foo", {
     	    DEFAULT   => 99,
     	    ALIAS     => 'metavar1',
     	});

   Configuration items specified in the GLOBAL option to the module
constructor are applied by default when variables are created.  e.g.

     my $config = AppConfig->new({
     	    GLOBAL => {
     		    DEFAULT  => "<undef>",
     		    ARGCOUNT => ARGCOUNT_ONE,
     		}
     	});

     $config->define("foo");
     $config->define("bar", { ARGCOUNT => ARGCOUNT_NONE } );

   is eqivalent to:

     my $config = AppConfig->new();

     $config->define("foo", {
     		DEFAULT  => "<undef>",
     		ARGCOUNT => ARGCOUNT_ONE,
     	    });

     $config->define("bar",
     		DEFAULT  => "<undef>",
     		ARGCOUNT => ARGCOUNT_NONE,
     	    });

   Multiple variables may be defined in the same call to define().
Configuration hashes for variables can be omitted.

     $config->define("foo", "bar" => { ALIAS = "boozer" }, "baz");

   See AppConfig/State) for full details of the
configuration options available when defining variables.  These are, in
brief:

DEFAULT
     The default value for the variable (default: undef).

ALIAS
     One or more (list reference or "list|like|this") alternative names
     for the variable.

ARGCOUNT
     Specifies the number and type of arguments that the variable expects.
     Constants in :expand tag set define ARGCOUNT_NONE - simple on/off flag
     (default), ARGCOUNT_ONE - single value, ARGCOUNT_LIST - multiple
     values accessed via list reference, ARGCOUNT_HASH - hash table,
     "key=value", accessed via hash reference.

ARGS
     Used to provide an argument specification string to pass to
     Getopt::Long via AppConfig::Getopt.  E.g. "=i", ":s", "=s@".  This
     can also be used to implicitly set the ARGCOUNT value (`/^!/' =
     ARGCOUNT_NONE, `/@/' = ARGCOUNT_LIST, `/%/ = ARGCOUNT_HASH,
     C</[=:].*/' = ARGCOUNT_ONE)

EXPAND
     Specifies which variable expansion policies should be used when
     parsing configuration files.  Constants in :argcount tag set define
     EXPAND_NONE - no expansion (default), EXPAND_VAR - expand `$var' or
     `$(var)' as other AppConfig variables, EXPAND_UID - expand `~uid' as
     user's home directory, EXPAND_ENV - expand `${var}' as environment
     variable, EXPAND_ALL - do all expansions.  May be logically or'd.

VALIDATE
     Regex which the intended variable value should match or code reference
     which returns 1 to indicate successful validaton (variable may now be
     set).

ACTION
     Code reference to be called whenever variable value changes.

COMPACT FORMAT DEFINITION
-------------------------

   Variables can be specified using a compact format.  This is identical to
the specification format of Getopt::Long and is of the form:

     "name|alias|aliasLess_Than_Special_Sequenceargopts<gt>"

   The first element indicates the variable name and subsequent ALIAS
values may be added, each separated by a vertical bar '|'.

   The <argopts<gt> element indicates the ARGCOUNT value and may be one of
the following;

     !                  ARGCOUNT_NONE
     =s                 ARGCOUNT_ONE
     =s@                ARGCOUNT_LIST
     =s%                ARGCOUNT_HASH

   The "=s" element

   Additional constructs supported by Getopt::Long may be specified instead
of the "=s" element (e.g. "=f").  The entire <argopts> element is stored
in the ARGS parameter for the variable and is passed intact to
Getopt::Long when the getopt() method is called.

   The following examples demonstrate use of the comapct format, with their
equivalent full specifications:

     $config->define("foo|bar|baz!");

     $config->define(
     	    "foo" => {
     		ALIAS    => "bar|baz",
     		ARGCOUNT => ARGCOUNT_NONE,
     	    });

     $config->define("name=s");

     $config->define(
     	    "name" => {
     		ARGCOUNT => ARGCOUNT_ONE,
     	    });

     $config->define("file|filelist|f=s@");

     $config->define(
     	    "file" => {
     		ALIAS    => "filelist|f",
     		ARGCOUNT => ARGCOUNT_LIST,
     	    });

     $config->define("user|u=s%");

     $config->define(
     	    "user" => {
     		ALIAS    => "f",
     		ARGCOUNT => ARGCOUNT_HASH,
     	    });

   Additional configuration options may be specified by hash reference, as
per normal.  The compact definition format will override any configuration
values provided for ARGS and ARGCOUNT.

     $config->define("file|filelist|f=s@", { VALIDATE = \&check_file() } );

READING AND MODIFYING VARIABLE VALUES
-------------------------------------

   AppConfig defines two methods (via AppConfig::State) to manipulate
variable values

     set($variable, $value);
     get($variable);

   Once defined, variables may be accessed directly as object methods where
the method name is the same as the variable name.  i.e.

     $config->set("verbose", 1);

   is equivalent to

     $config->verbose(1);

   Note that AppConfig defines the following methods:

     new();
     file();
     args();
     getopt();

   And also, through delegation to AppConfig::State:

     define()
     get()
     set()
     varlist()

   If you define a variable with one of the above names, you will not be
able to access it directly as an object method.  i.e.

     $config->file();

   This will call the file() method, instead of returning the value of the
'file' variable.  You can work around this by explicitly calling get() and
set() on a variable whose name conflicts:

     $config->get('file');

   or by defining a "safe" alias by which the variable can be accessed:

     $config->define("file", { ALIAS => "fileopt" });
     or
     $config->define("file|fileopt");

     ...
     $config->fileopt();

   Without parameters, the current value of the variable is returned.  If
a parameter is specified, the variable is set to that value and the result
of the set() operation is returned.

     $config->age(29);        # sets 'age' to 29, returns 1 (ok)
     print $config->age();    # prints "29"

   The varlist() method can be used to extract a number of variables into
a hash array.  The first parameter should be a regular expression used for
matching against the variable names.

     my %vars = $config->varlist("^file");   # all "file*" variables

   A second parameter may be specified (any true value) to indicate that
the part of the variable name matching the regex should be removed when
copied to the target hash.

     $config->file_name("/tmp/file");
     $config->file_path("/foo:/bar:/baz");

     my %vars = $config->varlist("^file_", 1);

     # %vars:
     #    name => /tmp/file
     #    path => "/foo:/bar:/baz"

READING CONFIGURATION FILES
---------------------------

   The AppConfig module provides a streamlined interface for reading
configuration files with the AppConfig::File module.  The file() method
automatically loads the AppConfig::File module and creates an object to
process the configuration file(s).  Variables stored in the internal
AppConfig::State are automatically updated with values specified in the
configuration file.

     $config->file($filename);

   Multiple files may be passed to file() and should indicate the file name
or be a reference to an open file handle or glob.

     $config->file($filename, $filehandle, \*STDIN, ...);

   The file may contain blank lines and comments (prefixed by '#') which
are ignored.  Continutation lines may be marked by ending the line with a
'\'.

     # this is a comment
     callsign = alpha bravo camel delta echo foxtrot golf hipowls \
                india juliet kilo llama mike november oscar papa  \
     	       quebec romeo sierra tango umbrella victor whiskey \
     	       x-ray yankee zebra

   Variables that are simple flags and do not expect an argument (ARGCOUNT
= ARGCOUNT_NONE) can be specified without any value.  They will be set with
the value 1, with any value explicitly specified (except "0" and "off")
being ignored.  The variable may also be specified with a "no" prefix to
implicitly set the variable to 0.

     verbose                              # on  (1)
     verbose = 1                          # on  (1)
     verbose = 0                          # off (0)
     verbose off                          # off (0)
     verbose on                           # on  (1)
     verbose mumble                       # on  (1)
     noverbose                            # off (0)

   Variables that expect an argument (ARGCOUNT = ARGCOUNT_ONE) will be set
to whatever follows the variable name, up to the end of the current line.
An equals sign may be inserted between the variable and value for clarity.

     room = /home/kitchen
     room   /home/bedroom

   Each subsequent re-definition of the variable value overwrites the
previous value.

     print $config->room();               # prints "/home/bedroom"

   Variables may be defined to accept multiple values (ARGCOUNT =
ARGCOUNT_LIST).  Each subsequent definition of the variable adds the value
to the list of previously set values for the variable.

     drink = coffee
     drink = tea

   A reference to a list of values is returned when the variable is
requested.

     my $beverages = $config->drinks();
     print join(", ", @$beverages);      # prints "coffee, tea"

   Variables may also be defined as hash lists (ARGCOUNT = ARGCOUNT_HASH).
Each subsequent definition creates a new key and value in the hash array.

     alias l="ls -CF"
     alias h="history"

   A reference to the hash is returned when the variable is requested.

     my $aliases = $config->alias();
     foreach my $k (keys %$aliases) {
     	print "$k => $aliases->{ $k }\n";
     }

   The '-' prefix can be used to reset a variable to its default value and
the '+' prefix can be used to set it to 1

     -verbose
     +debug

   Variable, environment variable and tilde (home directory) expansions
Variable values may contain references to other AppConfig variables,
environment variables and/or users' home directories.  These will be
expanded depending on the EXPAND value for each variable or the GLOBAL
EXPAND value.

   Three different expansion types may be applied:

     bin = ~/bin          # expand '~' to home dir if EXPAND_UID
     tmp = ~abw/tmp       # as above, but home dir for user 'abw'

     perl = $bin/perl     # expand value of 'bin' variable if EXPAND_VAR
     ripl = $(bin)/ripl   # as above with explicit parens

     home = ${HOME}       # expand HOME environment var if EXPAND_ENV

   See AppConfig/State, for more information on
expanding variable values.

   The configuration files may have variables arranged in blocks.  A block
header, consisting of the block name in square brackets, introduces a
configuration block.  The block name and an underscore are then prefixed
to the names of all variables subsequently referenced in that block.  The
block continues until the next block definition or to the end of the
current file.

     [block1]
     foo = 10             # block1_foo = 10

     [block2]
     foo = 20             # block2_foo = 20

PARSING COMMAND LINE OPTIONS
----------------------------

   There are two methods for processing command line options.  The first,
args(), is a small and efficient implementation which offers basic
functionality.  The second, getopt(), offers a more powerful and complete
facility by delegating the task to Johan Vroman's Getopt::Long module.
The trade-off between args() and getopt() is essentially one of speed/size
against flexibility.  Use as appropriate.  Both implement on-demand loading
of modules and incur no overhead until (unless) used.

   The args() method is used to parse simple command line options.  It
automatically loads the AppConfig::Args module and creates an object to
process the command line arguments.  Variables stored in the internal
AppConfig::State are automatically updated with values specified in the
arguments.

   The method should be passed a reference to a list of arguments to parse.
The @ARGV array is used if args() is called without parameters.

     $config->args(\@myargs);
     $config->args();               # uses @ARGV

   Arguments are read and shifted from the array until the first is
encountered that is not prefixed by '-' or '-'.  At that point, the method
returns 1 to indicate success, leaving the remaining arguments remaining
in the list.

   Each argument should be the name or alias of a variable prefixed by '-'
or '-'.  Arguments that are not prefixed as such (and are not an
additional parameter to a previous argument) will cause a warning to be
raised.  If the PEDANTIC option is set, the method will return 0
immediately.  With PEDANTIC unset (default), the method will continue to
parse the rest of the arguments, returning 0 when done.

   If the variable is a simple flag (ARGCOUNT = ARGCOUNT_NONE) then it is
set to the value 1.  The variable may be prefixed by "no" to set its value
to 0.

     myprog -verbose --debug -notaste     # $config->verbose(1)
                                          # $config->debug(1)
                                          # $config->taste(0)

   Variables that expect an additional argument (ARGCOUNT != 0) will be
set to the value of the argument following it.

     myprog -f /tmp/myfile                # $config->file('/tmp/file');

   Variables that expect multiple values (ARGCOUNT = ARGCOUNT_LIST or
ARGCOUNT_HASH) will have sucessive values added each time the option is
encountered.

     myprog -file /tmp/foo -file /tmp/bar # $config->file('/tmp/foo')
                                          # $config->file('/tmp/bar')

     # file => [ '/tmp/foo', '/tmp/bar' ]

     myprog -door "jim=Jim Morrison" -door "ray=Ray Manzarek"
                                     # $config->door("jim=Jim Morrison");
                                     # $config->door("ray=Ray Manzarek");

     # door => { 'jim' => 'Jim Morrison', 'ray' => 'Ray Manzarek' }

   See AppConfig/Args, for further details on
parsing command line arguments.

   The getopt() method provides a way to use the power and flexibility of
the Getopt::Long module to parse command line arguments and have the
internal values of the AppConfig object updates automatically.

   The first (non-list reference) parameters may contain a number of
configuration string to pass to Getopt::Long::Configure.  A reference to a
list of arguments may additionally be passed or @ARGV is used by default.

     $config->getopt();                       # uses @ARGV
     $config->getopt(\@myargs);
     $config->getopt(qw(auto_abbrev debug));  # uses @ARGV
     $config->getopt(qw(debug), \@myargs);

   See Getopt::Long for details of the configuartion options available.

   The getopt() method constructs a specification string for each internal
variable and then initialises Getopt::Long with these values.  The
specification string is constructed from the name, any aliases (delimited
by a vertical bar '|') and the value of the ARGS parameter.

     $config->define("foo", {
     	ARGS  => "=i",
     	ALIAS => "bar|baz",
     });

     # Getopt::Long specification: "foo|bar|baz=i"

   Errors and warning generated by the Getopt::Long module are trapped and
handled by the AppConfig error handler.  This may be a user-defined
routine installed with the ERROR configuration option.

   Please note that the AppConfig::Getopt interface is still experimental
and may not be 100% operational.  This is almost undoubtedly due to
problems in AppConfig::Getopt rather than Getopt::Long.

CONSTANT DEFINITIONS
====================

   A number of constants are defined by the AppConfig module.  These may be
accessed directly (e.g. AppConfig::EXPAND_VARS) or by first importing them
into the caller's package.  Constants are imported by specifying their
names as arguments to `use AppConfig' or by importing a set of constants
identified by its "tag set" name.

     use AppConfig qw(ARGCOUNT_NONE ARGCOUNT_ONE);

     use AppConfig qw(:argcount);

   The following tag sets are defined:

:expand
     The ':expand' tagset defines the following constants:

          EXPAND_NONE
          EXPAND_VAR
          EXPAND_UID
          EXPAND_ENV
          EXPAND_ALL       # EXPAND_VARS | EXPAND_UIDS | EXPAND_ENVS
          EXPAND_WARN

     See AppConfig::File for full details of the use of these constants.

:argcount
     The ':argcount' tagset defines the following constants:

          ARGCOUNT_NONE
          ARGCOUNT_ONE
          ARGCOUNT_LIST
          ARGCOUNT_HASH

     See AppConfig::State for full details of the use of these constants.

AUTHOR
======

   Andy Wardley, `<abw@cre.canon.co.uk>', http://www.kfs.org/~abw/

   Web Technology Group, Canon Research Centre Europe Ltd.

REVISION
========

   $Revision: 1.52 $

COPYRIGHT
=========

   Copyright (C) 1998 Canon Research Centre Europe Ltd.  All Rights
Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   AppConfig::State, AppConfig::File, AppConfig::Args, AppConfig::Getopt,
Getopt::Long

Perl5 module for reading command line arguments.
************************************************

NAME
====

   AppConfig::Args - Perl5 module for reading command line arguments.

SYNOPSIS
========

     use AppConfig::Args;

     my $state   = AppConfig::State->new(\%cfg);
     my $cfgargs = AppConfig::Args->new($state);

     $cfgargs->parse(\@args);            # read args

OVERVIEW
========

   AppConfig::Args is a Perl5 module which reads command line arguments and
uses the options therein to update variable values in an AppConfig::State
object.

   AppConfig::File is distributed as part of the AppConfig bundle.

DESCRIPTION
===========

USING THE AppConfig::Args MODULE
--------------------------------

   To import and use the AppConfig::Args module the following line should
appear in your Perl script:

     use AppConfig::Args;

   AppConfig::Args is used automatically if you use the AppConfig module
and create an AppConfig::Args object through the parse() method.

   AppConfig::File is implemented using object-oriented methods.  A new
AppConfig::Args object is created and initialised using the new() method.
This returns a reference to a new AppConfig::File object.  A reference to
an AppConfig::State object should be passed in as the first parameter:

   my $state   = AppConfig::State->new();     my $cfgargs =
AppConfig::Args->new($state);

   This will create and return a reference to a new AppConfig::Args object.

PARSING COMMAND LINE ARGUMENTS
------------------------------

   The parse() method is used to read a list of command line arguments and
update the STATE accordingly.  A reference to the list of arguments should
be passed in.

     $cfgargs->parse(\@ARGV);

   If the method is called without a reference to an argument list then it
will examine and manipulate @ARGV.

   If the PEDANTIC option is turned off in the AppConfig::State object, any
parsing errors (invalid variables, unvalidated values, etc) will generate
warnings, but not cause the method to return.  Having processed all
arguments, the method will return 1 if processed without warning or 0 if
one or more warnings were raised.  When the PEDANTIC option is turned on,
the method generates a warning and immediately returns a value of 0 as soon
as it encounters any parsing error.

   The method continues parsing arguments until it detects the first one
that does not start with a leading dash, '-'.  Arguments that constitute
values for other options are not examined in this way.

FUTURE DEVELOPMENT
==================

   This module was developed to provide backwards compatibility (to some
degree) with the preceeding App::Config module.  The argument parsing it
provides is basic but offers a quick and efficient solution for those
times when simple option handling is all that is required.

   If you require more flexibility in parsing command line arguments, then
you should consider using the AppConfig::Getopt module.  This is loaded
and used automatically by calling the AppConfig getopt() method.

   The AppConfig::Getopt module provides considerably extended
functionality over the AppConfig::Args module by delegating out the task
of argument parsing to Johan Vromans' Getopt::Long module.  For advanced
command-line parsing, this module (either Getopt::Long by itself, or in
conjunction with AppConfig::Getopt) is highly recommended.

AUTHOR
======

   Andy Wardley, `<abw@cre.canon.co.uk>'

   Web Technology Group, Canon Research Centre Europe Ltd.

REVISION
========

   $Revision: 1.50 $

COPYRIGHT
=========

   Copyright (C) 1998 Canon Research Centre Europe Ltd.  All Rights
Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   AppConfig, AppConfig::State, AppConfig::Getopt, Getopt::Long

Perl5 module for reading configuration files.
*********************************************

NAME
====

   AppConfig::File - Perl5 module for reading configuration files.

SYNOPSIS
========

     use AppConfig::File;

     my $state   = AppConfig::State->new(\%cfg1);
     my $cfgfile = AppConfig::File->new($state, $file);

     $cfgfile->parse($file);            # read config file

OVERVIEW
========

   AppConfig::File is a Perl5 module which reads configuration files and
use the contents therein to update variable values in an AppConfig::State
object.

   AppConfig::File is distributed as part of the AppConfig bundle.

DESCRIPTION
===========

USING THE AppConfig::File MODULE
--------------------------------

   To import and use the AppConfig::File module the following line should
appear in your Perl script:

     use AppConfig::File;

   AppConfig::File is used automatically if you use the AppConfig module
and create an AppConfig::File object through the file() method.

   AppConfig::File is implemented using object-oriented methods.  A new
AppConfig::File object is created and initialised using the
AppConfig::File->new() method.  This returns a reference to a new
AppConfig::File object.  A reference to an AppConfig::State object should
be passed in as the first parameter:

   my $state   = AppConfig::State->new();     my $cfgfile =
AppConfig::File->new($state);

   This will create and return a reference to a new AppConfig::File object.

READING CONFIGURATION FILES
---------------------------

   The parse() method is used to read a configuration file and have the
contents update the STATE accordingly.

     $cfgfile->parse($file);

   Multiple files maye be specified and will be read in turn.

     $cfgfile->parse($file1, $file2, $file3);

   The method will return an undef value if it encounters any errors
opening the files.  It will return immediately without processing any
further files.  By default, the PEDANTIC option in the AppConfig::State
object, $self->{ STATE }, is turned off and any parsing errors (invalid
variables, unvalidated values, etc) will generated warnings, but not cause
the method to return.  Having processed all files, the method will return
1 if all files were processed without warning or 0 if one or more warnings
were raised.  When the PEDANTIC option is turned on, the method generates a
warning and immediately returns a value of 0 as soon as it encounters any
parsing error.

   Variables values in the configuration files may be expanded depending on
the value of their EXPAND option, as determined from the App::State object.
See AppConfig/State, for more information on
variable expansion.

CONFIGURATION FILE FORMAT
-------------------------

   The file may contain blank lines and comments (prefixed by '#') which
are ignored.  Continutation lines may be marked by ending the line with a
'\'.

     # this is a comment
     callsign = alpha bravo camel delta echo foxtrot golf hipowls \
                india juliet kilo llama mike november oscar papa  \
     	       quebec romeo sierra tango umbrella victor whiskey \
     	       x-ray yankee zebra

   Variables that are simple flags and do not expect an argument (ARGCOUNT
= ARGCOUNT_NONE) can be specified without any value.  They will be set with
the value 1, with any value explicitly specified (except "0" and "off")
being ignored.  The variable may also be specified with a "no" prefix to
implicitly set the variable to 0.

     verbose                              # on  (1)
     verbose = 1                          # on  (1)
     verbose = 0                          # off (0)
     verbose off                          # off (0)
     verbose on                           # on  (1)
     verbose mumble                       # on  (1)
     noverbose                            # off (0)

   Variables that expect an argument (ARGCOUNT = ARGCOUNT_ONE) will be set
to whatever follows the variable name, up to the end of the current line.
An equals sign may be inserted between the variable and value for clarity.

     room = /home/kitchen
     room   /home/bedroom

   Each subsequent re-definition of the variable value overwrites the
previous value.

     print $config->room();               # prints "/home/bedroom"

   Variables may be defined to accept multiple values (ARGCOUNT =
ARGCOUNT_LIST).  Each subsequent definition of the variable adds the value
to the list of previously set values for the variable.

     drink = coffee
     drink = tea

   A reference to a list of values is returned when the variable is
requested.

     my $beverages = $config->drinks();
     print join(", ", @$beverages);      # prints "coffee, tea"

   Variables may also be defined as hash lists (ARGCOUNT = ARGCOUNT_HASH).
Each subsequent definition creates a new key and value in the hash array.

     alias l="ls -CF"
     alias h="history"

   A reference to the hash is returned when the variable is requested.

     my $aliases = $config->alias();
     foreach my $k (keys %$aliases) {
     	print "$k => $aliases->{ $k }\n";
     }

   The '-' prefix can be used to reset a variable to its default value and
the '+' prefix can be used to set it to 1

     -verbose
     +debug

   Variable, environment variable and tilde (home directory) expansions
Variable values may contain references to other AppConfig variables,
environment variables and/or users' home directories.  These will be
expanded depending on the EXPAND value for each variable or the GLOBAL
EXPAND value.

   Three different expansion types may be applied:

     bin = ~/bin          # expand '~' to home dir if EXPAND_UID
     tmp = ~abw/tmp       # as above, but home dir for user 'abw'

     perl = $bin/perl     # expand value of 'bin' variable if EXPAND_VAR
     ripl = $(bin)/ripl   # as above with explicit parens

     home = ${HOME}       # expand HOME environment var if EXPAND_ENV

   See AppConfig/State, for more information on
expanding variable values.

   The configuration files may have variables arranged in blocks.  A block
header, consisting of the block name in square brackets, introduces a
configuration block.  The block name and an underscore are then prefixed
to the names of all variables subsequently referenced in that block.  The
block continues until the next block definition or to the end of the
current file.

     [block1]
     foo = 10             # block1_foo = 10

     [block2]
     foo = 20             # block2_foo = 20

AUTHOR
======

   Andy Wardley, `<abw@cre.canon.co.uk>'

   Web Technology Group, Canon Research Centre Europe Ltd.

REVISION
========

   $Revision: 1.52 $

COPYRIGHT
=========

   Copyright (C) 1998 Canon Research Centre Europe Ltd.  All Rights
Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   AppConfig, AppConfig::State

Perl5 module for processing command line arguments via delegation to Getopt::Long.
**********************************************************************************

NAME
====

   AppConfig::Getopt - Perl5 module for processing command line arguments
via delegation to Getopt::Long.

SYNOPSIS
========

     use AppConfig::Getopt;

     my $state  = AppConfig::State->new(\%cfg);
     my $getopt = AppConfig::Getopt->new($state);

     $getopt->parse(\@args);            # read args

OVERVIEW
========

   AppConfig::Getopt is a Perl5 module which delegates to Johan Vroman's
Getopt::Long module to parse command line arguments and update values in
an AppConfig::State object accordingly.

   AppConfig::Getopt is distributed as part of the AppConfig bundle.

DESCRIPTION
===========

USING THE AppConfig::Getopt MODULE
----------------------------------

   To import and use the AppConfig::Getopt module the following line
should appear in your Perl script:

     use AppConfig::Getopt;

   AppConfig::Getopt is used automatically if you use the AppConfig module
and create an AppConfig::Getopt object through the getopt() method.

   AppConfig::Getopt is implemented using object-oriented methods.  A new
AppConfig::Getopt is implemented using object-oriented methods.  A new
AppConfig::Getopt object is created and initialised using the new() method.
This returns a reference to a new AppConfig::Getopt object.  A reference to
an AppConfig::State object should be passed in as the first parameter:

   my $state  = AppConfig::State->new();     my $getopt =
AppConfig::Getopt->new($state);

   This will create and return a reference to a new AppConfig::Getopt
object.

PARSING COMMAND LINE ARGUMENTS
------------------------------

   The parse() method is used to read a list of command line arguments and
update the state accordingly.

   The first (non-list reference) parameters may contain a number of
configuration strings to pass to Getopt::Long::Configure.  A reference to
a list of arguments may additionally be passed or @ARGV is used by default.

     $getopt->parse();                       # uses @ARGV
     $getopt->parse(\@myargs);
     $getopt->parse(qw(auto_abbrev debug));  # uses @ARGV
     $getopt->parse(qw(debug), \@myargs);

   See Getopt::Long for details of the configuartion options available.

   A Getopt::Long specification string is constructed for each variable
defined in the AppConfig::State.  This consists of the name, any aliases
and the ARGS value for the variable.

   These specification string are then passed to Getopt::Long, the
arguments are parsed and the values in the AppConfig::State updated.

   See AppConfig for information about using the AppConfig::Getopt module
via the getopt() method.

AUTHOR
======

   Andy Wardley, `<abw@cre.canon.co.uk>'

   Web Technology Group, Canon Research Centre Europe Ltd.

ACKNOWLEDGMENTS
===============

   Many thanks are due to Johan Vromans for the Getopt::Long module.  He
was kind enough to offer assistance and access to early releases of his
code to enable this module to be written.

REVISION
========

   $Revision: 1.51 $

COPYRIGHT
=========

   Copyright (C) 1998 Canon Research Centre Europe Ltd.  All Rights
Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   AppConfig, AppConfig::State, AppConfig::Args, Getopt::Long

Perl5 module for reading configuration files.
*********************************************

NAME
====

   AppConfig::MyFile - Perl5 module for reading configuration files.

SYNOPSIS
========

     use AppConfig;

     my $appconfig = AppConfig->new(\%cfg);
     $appconfig->myfile($file, [$file...])

OVERVIEW
========

   AppConfig::MyFile is a Perl5 module which...

DESCRIPTION
===========

USING THE AppConfig::File MODULE
--------------------------------

   To import and use the AppConfig::File module the following line should
appear in your Perl script:

     use AppConfig::File;

     my $appconfig = AppConfig->new();
     $appconfig->myfile($file);

AUTHOR
======

   Andy Wardley, `<abw@cre.canon.co.uk>'

   Web Technology Group, Canon Research Centre Europe Ltd.

REVISION
========

   $Revision$

COPYRIGHT
=========

   Copyright (C) 1998 Canon Research Centre Europe Ltd.  All Rights
Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   AppConfig, AppConfig::State

Perl5 module for maintaining the state of an application configuration.
***********************************************************************

NAME
====

   AppConfig::State - Perl5 module for maintaining the state of an
application configuration.

SYNOPSIS
========

     use AppConfig::State;

     my $state = AppConfig::State->new(\%cfg);

     $state->define("foo");            # very simple variable definition
     $state->define("bar", \%varcfg);  # variable specific configuration
     $state->define("foo|bar=i@");     # compact format

     $state->set("foo", 123);          # trivial set/get examples
     $state->get("foo");

     $state->foo();                    # shortcut variable access
     $state->foo(456);                 # shortcut variable update

OVERVIEW
========

   AppConfig::State is a Perl5 module to handle global configuration
variables for perl programs.  It maintains the state of any number of
variables, handling default values, aliasing, validation, update callbacks
and option arguments for use by other AppConfig::* modules.

   AppConfig::State is distributed as part of the AppConfig bundle.

DESCRIPTION
===========

USING THE AppConfig::State MODULE
---------------------------------

   To import and use the AppConfig::State module the following line should
appear in your Perl script:

     use AppConfig::State;

   The AppConfig::State module is loaded automatically by the new()
constructor of the AppConfig module.

   AppConfig::State is implemented using object-oriented methods.  A new
AppConfig::State object is created and initialised using the new() method.
This returns a reference to a new AppConfig::State object.

   my $state = AppConfig::State->new();

   This will create a reference to a new AppConfig::State with all
configuration options set to their default values.  You can initialise the
object by passing a reference to a hash array containing configuration
options:

     $state = AppConfig::State->new( {
     	CASE      => 1,
     	ERROR     => \&my_error,
     } );

   The new() constructor of the AppConfig module automatically passes all
parameters to the AppConfig::State new() constructor.  Thus, any global
configuration values and variable definitions for AppConfig::State are
also applicable to AppConfig.

   The following configuration options may be specified.

CASE
     Determines if the variable names are treated case sensitively.  Any
     non-zero value makes case significant when naming variables.  By
     default, CASE is set to 0 and thus "Variable", "VARIABLE" and
     "VaRiAbLe" are all treated as "variable".

CREATE
     By default, CREATE is turned off meaning that all variables accessed
     via set() (which includes access via shortcut such as
     `$state->variable($value)' which delegates to set()) must previously
     have been defined via define().  When CREATE is set to 1, calling
     set($variable, $value) on a variable that doesn't exist will cause it
     to be created automatically.

     When CREATE is set to any other non-zero value, it is assumed to be a
     regular expression pattern.  If the variable name matches the regex,
     the variable is created.  This can be used to specify configuration
     file blocks in which variables should be created, for example:

          $state = AppConfig::State->new( {
          	CREATE => '^define_',
          } );

     In a config file:

          [define]
          name = fred           # define_name gets created automatically

          [other]
          name = john           # other_name doesn't - warning raised

     Note that a regex pattern specified in CREATE is applied to the real
     variable name rather than any alias by which the variables may be
     accessed.

PEDANTIC
     The PEDANTIC option determines what action the configuration file
     (AppConfig::File) or argument parser (AppConfig::Args) should take on
     encountering a warning condition (typically caused when trying to set
     an undeclared variable).  If PEDANTIC is set to any true value, the
     parsing methods will immediately return a value of 0 on encountering
     such a condition.  If PEDANTIC is not set, the method will continue
     to parse the remainder of the current file(s) or arguments, returning
     0 when complete.

     If no warnings or errors are encountered, the method returns 1.

     In the case of a system error (e.g. unable to open a file), the method
     returns undef immediately, regardless of the PEDANTIC option.

ERROR
     Specifies a user-defined error handling routine.  When the handler is
     called, a format string is passed as the first parameter, followed by
     any additional values, as per printf(3C).

DEBUG
     Turns debugging on or off when set to 1 or 0 accordingly.  Debugging
     may also be activated by calling _debug() as an object method
     (`$state->_debug(1)') or as a package function
     (`AppConfig::State::_debug(1)'), passing in a true/false value to set
     the debugging state accordingly.  The package variable
     $AppConfig::State::DEBUG can also be set directly.

     The _debug() method returns the current debug value.  If a new value
     is passed in, the internal value is updated, but the previous value is
     returned.

     Note that any AppConfig::File or App::Config::Args objects that are
     instantiated with a reference to an App::State will inherit the DEBUG
     (and also PEDANTIC) values of the state at that time.  Subsequent
     changes to the AppConfig::State debug value will not affect them.

GLOBAL
     The GLOBAL option allows default values to be set for the DEFAULT,
     ARGCOUNT, EXPAND, VALIDATE and ACTION options for any subsequently
     defined variables.

          $state = AppConfig::State->new({
          	GLOBAL => {
          	    DEFAULT  => '<undef>',     # default value for new vars
          	    ARGCOUNT => 1,             # vars expect an argument
          	    ACTION   => \&my_set_var,  # callback when vars get set
          	}
          });

     Any attributes specified explicitly when a variable is defined will
     override any GLOBAL values.

     See `DEFINING VARIABLES' in this node below which describes these
     options in detail.

DEFINING VARIABLES
------------------

   The define() function is used to pre-declare a variable and specify its
configuration.

     $state->define("foo");

   In the simple example above, a new variable called "foo" is defined.  A
reference to a hash array may also be passed to specify configuration
information for the variable:

     $state->define("foo", {
     	    DEFAULT   => 99,
     	    ALIAS     => 'metavar1',
     	});

   Any variable-wide GLOBAL values passed to the new() constructor in the
configuration hash will also be applied.  Values explicitly specified in a
variable's define() configuration will override the respective GLOBAL
values.

   The following configuration options may be specified

DEFAULT
     The DEFAULT value is used to initialise the variable.

          $state->define("drink", {
          	    DEFAULT => 'coffee',
          	});

          print $state->drink();        # prints "coffee"

ALIAS
     The ALIAS option allows a number of alternative names to be specified
     for this variable.  A single alias should be specified as a string.
     Multiple aliases can be specified as a reference to an array of
     alternatives or as a string of names separated by vertical bars, '|'.
     e.g.:

          $state->define("name", {
          	    ALIAS  => 'person',
          	});
          or
          $state->define("name", {
          	    ALIAS => [ 'person', 'user', 'uid' ],
          	});
          or
          $state->define("name", {
          	    ALIAS => 'person|user|uid',
          	});

          $state->user('abw');     # equivalent to $state->name('abw');

ARGCOUNT
     The ARGCOUNT option specifies the number of arguments that should be
     supplied for this variable.  By default, no additional arguments are
     expected for variables (ARGCOUNT_NONE).

     The ARGCOUNT_* constants can be imported from the AppConfig module:

          use AppConfig ':argcount';

          $state->define('foo', { ARGCOUNT => ARGCOUNT_ONE });

     or can be accessed directly from the AppConfig package:

          use AppConfig;

          $state->define('foo', { ARGCOUNT => AppConfig::ARGCOUNT_ONE });

     The following values for ARGCOUNT may be specified.

    ARGCOUNT_NONE (0)
          Indicates that no additional arguments are expected.  If the
          variable is identified in a confirguration file or in the
          command line arguments, it is set to a value of 1 regardless of
          whatever arguments follow it.

    ARGCOUNT_ONE (1)
          Indicates that the variable expects a single argument to be
          provided.  The variable value will be overwritten with a new
          value each time it is encountered.

    ARGCOUNT_LIST (2)
          Indicates that the variable expects multiple arguments.  The
          variable value will be appended to the list of previous values
          each time it is encountered.

    ARGCOUNT_HASH (3)
          Indicates that the variable expects multiple arguments and that
          each argument is of the form "key=value".  The argument will be
          split into a key/value pair and inserted into the hash of values
          each time it is encountered.

ARGS
     The ARGS option can also be used to specify advanced command line
     options for use with AppConfig::Getopt, which itself delegates to
     Getopt::Long.  See those two modules for more information on the
     format and meaning of these options.

          $state->define("name", {
          	    ARGS => "=i@",
          	});

EXPAND
     The EXPAND option specifies how the AppConfig::File processor should
     expand embedded variables in the configuration file values it reads.
     By default, EXPAND is turned off (EXPAND_NONE) and no expansion is
     made.

     The EXPAND_* constants can be imported from the AppConfig module:

          use AppConfig ':expand';

          $state->define('foo', { EXPAND => EXPAND_VAR });

     or can be accessed directly from the AppConfig package:

          use AppConfig;

          $state->define('foo', { EXPAND => AppConfig::EXPAND_VAR });

     The following values for EXPAND may be specified.  Multiple values
     should be combined with vertical bars , '|', e.g. `EXPAND_UID |
     EXPAND_VAR').

    EXPAND_NONE
          Indicates that no variable expansion should be attempted.

    EXPAND_VAR
          Indicates that variables embedded as $var or $(var) should be
          expanded to the values of the relevant AppConfig::State
          variables.

    EXPAND_UID
          Indicates that '~' or '~uid' patterns in the string should be
          expanded to the current users ($<), or specified user's home
          directory.

    EXPAND_ENV
          Inidicates that variables embedded as ${var} should be expanded
          to the value of the relevant environment variable.

    EXPAND_ALL
          Equivalent to `EXPAND_VARS | EXPAND_UIDS | EXPAND_ENVS').

    EXPAND_WARN
          Indicates that embedded variables that are not defined should
          raise a warning.  If PEDANTIC is set, this will cause the read()
          method to return 0 immediately.

VALIDATE
     Each variable may have a sub-routine or regular expression defined
     which is used to validate the intended value for a variable before it
     is set.

     If VALIDATE is defined as a regular expression, it is applied to the
     value and deemed valid if the pattern matches.  In this case, the
     variable is then set to the new value.  A warning message is generated
     if the pattern match fails.

     VALIDATE may also be defined as a reference to a sub-routine which
     takes as its arguments the name of the variable and its intended
     value.  The sub-routine should return 1 or 0 to indicate that the
     value is valid or invalid, respectively.  An invalid value will cause
     a warning error message to be generated.

     If the GLOBAL VALIDATE variable is set (see GLOBAL in `DESCRIPTION'
     in this node above) then this value will be used as the default
     VALIDATE for each variable unless otherwise specified.

          $state->define("age", {
          	    VALIDATE => '\d+',
          	});

          $state->define("pin", {
          	    VALIDATE => \&check_pin,
          	});

ACTION
     The ACTION option allows a sub-routine to be bound to a variable as a
     callback that is executed whenever the variable is set.  The ACTION is
     passed a reference to the AppConfig::State object, the name of the
     variable and the value of the variable.

     The ACTION routine may be used, for example, to post-process variable
     data, update the value of some other dependant variable, generate a
     warning message, etc.

     Example:

          $state->define("foo", { ACTION => \&my_notify });

          sub my_notify {
          	my $state = shift;
          	my $var   = shift;
          	my $val   = shift;

          print "$variable set to $value";
              }

          $state->foo(42);        # prints "foo set to 42"

     Be aware that calling `$state->set()' to update the same variable
     from within the ACTION function will cause a recursive loop as the
     ACTION function is repeatedly called.

DEFINING VARIABLES USING THE COMPACT FORMAT
-------------------------------------------

   Variables may be defined in a compact format which allows any ALIAS and
ARGS values to be specified as part of the variable name.  This is designed
to mimic the behaviour of Johan Vromans' Getopt::Long module.

   Aliases for a variable should be specified after the variable name,
separated by vertical bars, '|'.  Any ARGS parameter should be appended
after the variable name(s) and/or aliases.

   The following examples are equivalent:

     $state->define("foo", {
     	    ALIAS => [ 'bar', 'baz' ],
     	    ARGS  => '=i',
     	});

     $state->define("foo|bar|baz=i");

READING AND MODIFYING VARIABLE VALUES
-------------------------------------

   AppConfig::State defines two methods to manipulate variable values:

     set($variable, $value);
     get($variable);

   Both functions take the variable name as the first parameter and set()
takes an additional parameter which is the new value for the variable.
set() returns 1 or 0 to indicate successful or unsuccessful update of the
variable value.  If there is an ACTION routine associated with the named
variable, the value returned will be passed back from set().  The get()
function returns the current value of the variable.

   Once defined, variables may be accessed directly as object methods where
the method name is the same as the variable name.  i.e.

     $state->set("verbose", 1);

   is equivalent to

     $state->verbose(1);

   Without parameters, the current value of the variable is returned.  If
a parameter is specified, the variable is set to that value and the result
of the set() operation is returned.

     $state->age(29);        # sets 'age' to 29, returns 1 (ok)

INTERNAL METHODS
----------------

   The interal (private) methods of the AppConfig::State class are listed
below.

   They aren't intended for regular use and potential users should consider
the fact that nothing about the internal implementation is guaranteed to
remain the same.  Having said that, the AppConfig::State class is intended
to co-exist and work with a number of other modules and these are
considered "friend" classes.  These methods are provided, in part, as
services to them.  With this acknowledged co-operation in mind, it is safe
to assume some stability in this core interface.

   The _varname() method can be used to determine the real name of a
variable from an alias:

     $varname->_varname($alias);

   Note that all methods that take a variable name, including those listed
below, can accept an alias and automatically resolve it to the correct
variable name.  There is no need to call _varname() explicitly to do alias
expansion.  The _varname() method will fold all variables names to lower
case unless CASE sensititvity is set.

   The _exists() method can be used to check if a variable has been
defined:

     $state->_exists($varname);

   The _default() method can be used to reset a variable to its default
value:

     $state->_default($varname);

   The _expand() method can be used to determine the EXPAND value for a
variable:

     print "$varname EXPAND: ", $state->_expand($varname), "\n";

   The _argcount() method returns the value of the ARGCOUNT attribute for a
variable:

     print "$varname ARGCOUNT: ", $state->_argcount($varname), "\n";

   The _validate() method can be used to determine if a new value for a
variable meets any validation criteria specified for it.  The variable
name and intended value should be passed in.  The methods returns a
true/false value depending on whether or not the validation succeeded:

     print "OK\n" if $state->_validate($varname, $value);

   The _pedantic() method can be called to determine the current value of
the PEDANTIC option.

     print "pedantic mode is ", $state->_pedantic() ? "on" ; "off", "\n";

   The _debug() method can be used to turn debugging on or off (pass 1 or 0
as a parameter).  It can also be used to check the debug state, returning
the current internal value of $AppConfig::State::DEBUG.  If a new debug
value is provided, the debug state is updated and the previous state is
returned.

     $state->_debug(1);               # debug on, returns previous value

   The _dump_var($varname) and _dump() methods may also be called for
debugging purposes.

     $state->_dump_var($varname);    # show variable state
     $state->_dump();                # show internal state and all vars

AUTHOR
======

   Andy Wardley, `<abw@cre.canon.co.uk>'

   Web Technology Group, Canon Research Centre Europe Ltd.

REVISION
========

   $Revision: 1.52 $

COPYRIGHT
=========

   Copyright (C) 1998 Canon Research Centre Europe Ltd.  All Rights
Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   AppConfig, AppConfig::File, AppConfig::Args, AppConfig::Getopt

subclass of AppConfig which provides standard options
*****************************************************

NAME
====

   AppConfig::Std - subclass of AppConfig which provides standard options

SYNOPSIS
========

     use AppConfig::Std;

     $config = AppConfig::Std->new();

     # all AppConfig methods supported
     $config->define('foo');            # define variable foo
     $config->set('foo', 25);           # setting a variable
     $val = $config->get('foo');        # getting variable
     $val = $config->foo();             # shorthand for getting

     $config->args(\@ARGV);             # parse command-line
     $config->file(".myconfigrc")       # read config file

DESCRIPTION
===========

   *AppConfig::Std* is a Perl5 module which provides a set of standard
configuration variables and command-line switches.  It is implemented as a
subclass of AppConfig, which provides a general mechanism for handling
global configuration variables.

   The features provided by AppConfig::Std are:

   * Standard command-line arguments: -help, -doc, -version, -verbose, and
     -debug.  These are described below.

   * The ARGCOUNT default is set to 1. This means that by default all
     switches are expected to take a value. To change this, set the
     ARGCOUNT parameter when defining the variable:

          $config->define('verbose', { ARGCOUNT => 0 } );

   Please read the copious documentation for AppConfig to find out what
else you can do with this module.

STANDARD OPTIONS
================

   The module adds five standard configuration variables and command-line
switches. You can define additional variables as you would with AppConfig.

HELP
----

   The *-help* switch will result in a short help message.  This is
generated using Pod::Usage, which displays the OPTIONS section of your
pod. The script will exit with an exit value of 0.

DOC
---

   The *-doc* switch will result in the entire documentation being
formatted to the screen.  This is also done with Pod::Usage.  The script
will exit with an exit value of 0.

VERSION
-------

   The *-version* switch will display the version of the invoking script.
This assumes that you have defined $VERSION in your script with something
like the following:

     use vars qw( $VERSION );
     $VERSION = sprintf("%d.%02d", q$Revision: 1.3 $ =~ /(\d+)\.(\d+)/);

   The script will exit with an exit value of 0.

DEBUG
-----

   The *-debug* switch just sets the debug variable.  This is useful for
displaying information in debug mode:

     $foobar->dump() if $config->debug;

VERBOSE
-------

   The *-verbose* switch just sets the verbose variable.  This is useful
for displaying verbose information as a script runs:

     print STDERR "Running foobar\n" if $config->verbose;

TODO
====

   Please let me know if you have ideas for additional switches, or other
modifications. Things currently being mulled:

   * Support brief switches, such as -h as well as *-help*.

   * Test-suite.

   * Include a sample script called *mkscript*, which would create a
     template script along with Makefile.PL, MANIFEST, etc.  Kinda of a
     h2xs for scripts.

EXAMPLE
=======

   The following is the outline of a simple script which illustrates use
of the AppConfig::Std module:

     #!/usr/bin/perl -w
     use strict;
     use AppConfig::Std;

     use vars qw( $VERSION );
     $VERSION = '1.0';

     my $config = AppConfig::Std->new();

     # parse command-line and handle std switches
     $config->args(\@ARGV);

     exit 0;

     __END__

     =head1 NAME

     standard pod format documentation

   The pod documentation is expected to have the NAME, SYNOPSIS,
DESCRIPTION, and OPTIONS sections. See the documentation for pod2man for
more details.

SEE ALSO
========

AppConfig
     Andy Wardley's module for unifying command-line switches and
     cofiguration files into the notion of configuration variables.
     AppConfig::Std requires version 1.52+ of the module, which is
     available from CPAN:

          http://www.cpan.org/modules/by-module/AppConfig/

Pod::Usage
     Brad Appleton's module for extracting usage information out of a
     file's pod. This is used for the *-doc* and *-help* switches.
     Available from CPAN:

          http://www.cpan.org/modules/by-module/Pod/

perlpod
     Documentation from the perl distribution which describes the pod
     format.

pod2man
     Particularly the section in the documentation titled *Anatomy of a
     Proper Man Page*.  AppConfig::Std uses Pod::Usage, which assumes
     well-formed pod.

AUTHOR
======

   Neil Bowers <neilb@cre.canon.co.uk>

COPYRIGHT
=========

   Copyright (c) 1998-2001 Canon Research Centre Europe. All rights
reserved.

   This script is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl5 module defining platform-specific information and methods for other AppConfig::* modules.
***********************************************************************************************

NAME
====

   AppConfig::Sys - Perl5 module defining platform-specific information
and methods for other AppConfig::* modules.

SYNOPSIS
========

     use AppConfig::Sys;
     my $sys = AppConfig::Sys->new();

     @fields = $sys->getpwuid($userid);
     @fields = $sys->getpwnam($username);

OVERVIEW
========

   AppConfig::Sys is a Perl5 module provides platform-specific information
and operations as required by other AppConfig::* modules.

   AppConfig::Sys is distributed as part of the AppConfig bundle.

DESCRIPTION
===========

USING THE AppConfig::State MODULE
---------------------------------

   To import and use the AppConfig::Sys module the following line should
appear in your Perl script:

     use AppConfig::Sys;

   AppConfig::Sys is implemented using object-oriented methods.  A new
AppConfig::Sys object is created and initialised using the
AppConfig::Sys->new() method.  This returns a reference to a new
AppConfig::Sys object.

     my $sys = AppConfig::Sys->new();

   This will attempt to detect your operating system and create a
reference to a new AppConfig::Sys object that is applicable to your
platform.  You may explicitly specify an operating system name to override
this automatic detection:

     $unix_sys = AppConfig::Sys->new("Unix");

   Alternatively, the package variable $AppConfig::Sys::OS can be set to an
operating system name.  The valid operating system names are: Win, VMS,
Mac, OS2 and Unix.  They are not case-specific.

AppConfig::Sys METHODS
----------------------

   AppConfig::Sys defines the following methods:

getpwnam()
     Calls the system function getpwnam() if available and returns the
     result.  Returns undef if not available.  The can_getpwnam() method
     can be called to determine if this function is available.

getpwuid()
     Calls the system function getpwuid() if available and returns the
     result.  Returns undef if not available.  The can_getpwuid() method
     can be called to determine if this function is available.

AUTHOR
======

   Andy Wardley, `<abw@cre.canon.co.uk>'

   Web Technology Group, Canon Research Centre Europe Ltd.

REVISION
========

   $Revision: 1.50 $

COPYRIGHT
=========

   Copyright (C) 1998 Canon Research Centre Europe Ltd.  All Rights
Reserved.

   This module is free software; you can redistribute it and/or modify it
under the term of the Perl Artistic License.

SEE ALSO
========

   AppConfig, AppConfig::File

Block-level access to Apple II disk image files
***********************************************

NAME
====

   AppleII::Disk - Block-level access to Apple II disk image files

SYNOPSIS
========

     use AppleII::Disk;
     my $disk = AppleII::Disk->new('image.dsk');
     my $data = $disk->read_block(1);  # Read block 1
     $disk->write_block(1, $data);     # And write it back :-)

DESCRIPTION
===========

   `AppleII::Disk' provides block-level access to the Apple II disk image
files used by most Apple II emulators.  (For information about Apple II
emulators, try the Apple II Emulator Page at `http:' in this node.)  For a
higher-level interface, use the AppleII/ProDOS,
module.

   `AppleII::Disk' provides the following methods:

$disk = AppleII::Disk->new($filename, [$mode])
     Constructs a new `AppleII::Disk' object.  $filename is the name of
     the image file.  The optional $mode is a string specifying how to
     open the image.  It can consist of the following characters (*case
     sensitive*):

          r  Allow reads (this is actually ignored; you can always read)
          w  Allow writes
          d  Disk image is in DOS 3.3 order
          p  Disk image is in ProDOS order

     If you don't specify 'd' or 'p', then the format is guessed from the
     filename.  '.PO' and '.HDV' files are ProDOS order, and anything else
     is assumed to be DOS 3.3 order.

     If you specify 'w' to allow writes, then the image file is created if
     it doesn't already exist.

$size = $disk->blocks([$newsize])
     Gets or sets the size of the disk in blocks.  `$newsize' is the new
     size of the disk in blocks.  If `$newsize' is omitted, then the size
     is not changed.  Returns the size of the disk image in blocks.

     This refers to the *logical* size of the disk image.  Blocks outside
     the physical size of the disk image read as all zeros.  Writing to
     such a block will expand the image file.

     When you create a new image file, you must use blocks to set its size
     before writing to it.

$contents = $disk->read_block($block)
     Reads one block from the disk image.  $block is the block number to
     read.

$contents = $disk->read_blocks(\@blocks)
     Reads a sequence of blocks from the disk image.  `\@blocks' is a
     reference to an array of block numbers.

$contents = $disk->read_sector($track, $sector)
     Reads one sector from the disk image.  $track is the track number,
     and `$sector' is the DOS 3.3 logical sector number.  This is
     currently implemented only for DOS 3.3 order images.

$disk->write_block($block, $contents, [$pad])
     Writes one block to the disk image.  $block is the block number to
     write.  $contents is the data to write.  The optional `$pad' is a
     character to pad the block with (out to 512 bytes).  If `$pad' is
     omitted or null, then $contents must be exactly 512 bytes.

$disk->write_blocks(\@blocks, $contents, [$pad])
     Writes a sequence of blocks to the disk image.  `\@blocks' is a
     reference to an array of block numbers to write.  $contents is the
     data to write.  It is broken up into 512 byte chunks and written to
     the blocks.  The optional `$pad' is a character to pad the data with
     (out to a multiple of 512 bytes).  If `$pad' is omitted or null, then
     $contents must be exactly 512 bytes times the number of blocks.

$disk->write_sector($track, $sector, $contents, [$pad])
     Writes one sector to the disk image.  $track is the track number, and
     `$sector' is the DOS 3.3 logical sector number.  $contents is the
     data to write.  The optional `$pad' is a character to pad the sector
     with (out to 256 bytes).  If `$pad' is omitted or null, then
     $contents must be exactly 256 bytes.  This is currently implemented
     only for DOS 3.3 order images.

$padded = AppleII::Disk->pad_block($data, [$pad, [$length]])
     Pads $data out to $length bytes with `$pad'.  Returns the padded
     string; the original is not altered.  Dies if $data is longer than
     $length.  The default `$pad' is "\0", and the default $length is 512
     bytes.

     If `$pad' is the null string (not undef), just checks to make sure
     that $data is exactly $length bytes and returns the original string.
     Dies if $data is not exactly $length bytes.

     `pad_block' can be called either as `AppleII::Disk->pad_block' or
     `$disk->pad_block'.

AUTHOR
======

   Christopher J. Madsen <`ac608@yfn.ysu.edu'>

Access files on Apple II ProDOS disk images
*******************************************

NAME
====

   AppleII::ProDOS - Access files on Apple II ProDOS disk images

SYNOPSIS
========

     use AppleII::ProDOS;
     my $vol = AppleII::ProDOS->open('image.dsk'); # Open an existing disk
     print $vol->catalog;                  # List files in volume directory
     my $file = $vol->get_file('Startup'); # Read file from disk
     $vol->path('Subdir');                 # Move into a subdirectory
     $vol->put_file($file);                # And write it back there

DESCRIPTION
===========

   `AppleII::ProDOS' provides high-level access to ProDOS volumes stored
in the disk image files used by most Apple II emulators.  (For information
about Apple II emulators, try the Apple II Emulator Page at `http:' in
this node.)  It uses the AppleII/Disk, module to
handle low-level access to image files.

   All the following classes have two constructors.  Constructors named
open are for creating an object to represent existing data in the image
file.  Constructors named new are for creating a new object to be added to
an image file.

`AppleII::ProDOS'
-----------------

   `AppleII::ProDOS' is the primary interface to ProDOS volumes.  It
provides the following methods:

$vol = AppleII::ProDOS->new($volume, $size, $filename, [$mode])
     Constructs a new image file and an `AppleII::ProDOS' object to access
     it.  $volume is the volume name.  $size is the size in blocks.
     $filename is the name of the image file.  The optional $mode is a
     string specifying how to open the image (see the open method for
     details).  You always receive read and write access.

$vol = AppleII::ProDOS->open($filename, [$mode])
     Constructs an `AppleII::ProDOS' object to access an existing image
     file.  $filename is the name of the image file.  The optional $mode is
     a string specifying how to open the image.  It can consist of the
     following characters (*case sensitive*):

          r  Allow reads (this is actually ignored; you can always read)
          w  Allow writes
          d  Disk image is in DOS 3.3 order
          p  Disk image is in ProDOS order

$vol = AppleII::ProDOS->open($disk)
     Constructs an `AppleII::ProDOS' object to access an existing image
     file.  $disk is the `AppleII::Disk' object representing the image
     file.

$bitmap = $vol->bitmap
     Returns the volume bitmap as an `AppleII::ProDOS::Bitmap' object.

$dir = $vol->dir
     Returns the current directory as an AppleII::ProDOS::Directory object.

$disk = $vol->disk
     Returns the `AppleII::ProDOS::Disk' object which represents the image
     file.

$disk = $vol->disk_size
     Returns the size of the volume in blocks.  This is the logical size of
     the ProDOS volume, which is not necessarily the same as the actual
     size of the image file.

$name = $vol->name
     Returns the volume name.

$path = $vol->path([$newpath])
     Gets or sets the current path.  `$newpath' is the new pathname, which
     may be either relative or absolute.  `..' may be used to specify the
     parent directory, but this must occur at the beginning of the path
     (`../../dir' is valid, but `../dir/..' is not).  If c<$newpath>> is
     omitted, then the current path is not changed.  Returns the current
     path as a string beginning and ending with /.

$catalog = $vol->catalog
$file = $vol->get_file($filename)
$entry = $vol->new_dir($name)
$vol->put_file($file)
     These methods are passed to the current directory.  See
     `AppleII::ProDOS::Directory' for details.

`AppleII::ProDOS::Directory'
----------------------------

   `AppleII::ProDOS::Directory' represents a ProDOS directory. It provides
the following methods:

$dir = AppleII::ProDOS::Directory->new($name, $disk, $blocks, $bitmap, [$parent, $parentNum])
     Constructs a new `AppleII::ProDOS::Directory' object.  $name is the
     name of the directory.  $disk is the `AppleII::Disk' to create it on.
     `$blocks' is a block number or an array of block numbers to store
     the directory in.  $bitmap is the `AppleII::ProDOS::Bitmap'
     representing the volume bitmap.  For a subdirectory, `$parent' must
     be the block number in the parent directory where the subdirectory is
     listed, and `$parentNum' is the entry number in that block (with 1
     being the first entry).

$dir = AppleII::ProDOS->open($disk, $block, $bitmap)
     Constructs an `AppleII::ProDOS::Directory' object to access an
     existing directory in the image file.  $disk is the `AppleII::Disk'
     object representing the image file.  $block is the block number where
     the directory begins.  $bitmap is the `AppleII::ProDOS::Bitmap'
     representing the volume bitmap.

$catalog = $dir->catalog
     Returns the directory listing in ProDOS format with free space
     information.

@entries = $dir->entries
     Returns the contents of the directory as a list of
     `AppleII::ProDOS::DirEntry' objects.

$entry = $dir->find_entry($filename)
     Returns the `AppleII::ProDOS::DirEntry' object for $filename, or
     undef if the specified file does not exist.

$file = $dir->get_file($filename)
     Retrieves a file from the directory.  $filename may be either a
     filename or an `AppleII::ProDOS::DirEntry' object.  Returns a new
     `AppleII::ProDOS::File' object.

@entries = $dir->list_matches($pattern, [$filter])
     Returns a list of the `AppleII::ProDOS::DirEntry' objects matching
     the regexp `$pattern'.  If `$filter' is specified, it is either a
     subroutine reference or one of the strings 'DIR' or '!DIR'.  'DIR'
     matches only directories, and '!DIR' matches only regular files.  If
     `$filter' is a subroutine, it is called (as `\&$filter($entry)') for
     each entry.  It should return true if the entry is acceptable (the
     entry's name must still match `$pattern').  Returns the null list if
     there are no matching entries.

$entry = $dir->new_dir($name)
     Creates a new subdirectory in the directory.  $name is the name of
     the new subdirectory.  Returns the `AppleII::ProDOS::DirEntry' object
     representing the new subdirectory entry.

$entry = $dir->open_dir($dirname)
     Opens a subdirectory of the directory.  `$dirname' may be either a
     subdirectory name or an `AppleII::ProDOS::DirEntry' object.  Returns
     a new `AppleII::ProDOS::Directory' object.

$dir->put_file($file)
     Stores a file in the directory.  $file must be an
     `AppleII::ProDOS::File' object.

$dir->add_entry($entry)
     Adds a new entry to the directory.  $entry is an
     `AppleII::ProDOS::DirEntry' object.

$dir->read_disk
     Rereads the directory contents from the image file.  You can use this
     to undo changes to a directory before they have been written to the
     image file.

$dir->write_disk
     Writes the current directory contents to the image file.  You must use
     this if you alter the directory contents in any way except the
     high-level methods `new_dir' and put_file, which do this
     automatically.

`AppleII::ProDOS::DirEntry'
---------------------------

   `AppleII::ProDOS::DirEntry' provides access to directory entries.  It
provides the following methods:

$entry = AppleII::ProDOS::DirEntry->new([$num, $entry])
     Constructs a new `AppleII::ProDOS::DirEntry' object.  $num is the
     entry number in the directory, and $entry is the packed directory
     entry.  If $num and $entry are omitted, then a blank directory entry
     is created.  This is a low-level function; you shouldn't need to
     explicitly construct DirEntry objects.

$packed_entry = $entry->packed($key_block)
     Return the directory entry in packed format.  `$key_block' is the
     starting block number of the directory containing this entry.

$access = $entry->access([$new])
     Gets or sets the access attributes.  This is a bitfield with the
     following entries:

          0x80  File can be deleted
          0x40  File can be renamed
          0x20  File has changed since last backup
          0x02  File can be written to
          0x01  File can be read

     Normal values are 0xC3 or 0xE3 for an unlocked file, and 0x01 for a
     locked file.

$auxtype = $entry->auxtype([$new])
     Gets or sets the auxiliary type.  This is a number between 0x0000 and
     0xFFFF.  Its meaning depends on the filetype.

$creation_date = $entry->created([$date])
     Gets or sets the creation date and time in ProDOS format.

$modification_date = $entry->modified([$date])
     Gets or sets the modification date and time in ProDOS format.

$name = $entry->name([$new])
     Gets or sets the filename.

$type = $entry->type([$new])
     Gets or sets the filetype.  This is a number between 0x00 and 0xFF.
     Use `parse_type' to convert it to a more meaningful abbreviation.

$type = $entry->short_type Returns the standard abbreviation for the filetype.  It is equivalent to calling `AppleII::ProDOS::parse_type($entry->type)'.
   The following methods allow access to read-only fields.  They can be
used to initialize a DirEntry object created with new, but raise an
exception if the field already has a value.

$block = $entry->block([$new])
     Gets or sets the key block for the file.

$used = $entry->blks_used([$new])
     Gets or sets the number of blocks used by the file.

$entry_num = $entry->num([$new])
     Gets or sets the entry number in the directory.

$size = $entry->size([$new])
     Gets or sets the size of the file in bytes.

$storage = $entry->storage([$new])
     Gets or sets the storage type.

NOTE
====

   This is the point where I ran out of steam in documentation writing.
:-)  If I get at least one email from someone who'd actually read the rest
of this documentation, I'll try to finish it.

`AppleII::ProDOS::File'
-----------------------

   `AppleII::ProDOS::File' represents a file's data and other attributes.

`AppleII::ProDOS::Bitmap'
-------------------------

   `AppleII::ProDOS::Bitmap' represents the volume bitmap.

`AppleII::ProDOS::Index'
------------------------

   `AppleII::ProDOS::Index' represents an index block.

BUGS
====

   * This document isn't finished yet.  I haven't been working on it
     recently, so I decided I might as well just release what I have.  If
     somebody writes me, I'm more likely to finish.  (That's a hint,
     folks.)

   * Mixed case filenames (ala GS/OS) are not supported.  All filenames are
     converted to upper case.

AUTHOR
======

   Christopher J. Madsen <`ac608@yfn.ysu.edu'>

module for manipulation of tar archives.
****************************************

NAME
====

   Tar - module for manipulation of tar archives.

SYNOPSIS
========

     use Archive::Tar;

     Archive::Tar->create_archive ("my.tar.gz", 9, "/this/file", "/that/file");
     print join "\n", Archive::Tar->list_archive ("my.tar.gz"), "";

     $tar = Archive::Tar->new();
     $tar->read("origin.tar.gz",1);
     $tar->add_files("file/foo.c", "file/bar.c");
     $tar->add_data("file/baz.c","This is the file contents");
     $tar->write("files.tar");

DESCRIPTION
===========

   This is a module for the handling of tar archives.

   Archive::Tar provides an object oriented mechanism for handling tar
files.  It provides class methods for quick and easy files handling while
also allowing for the creation of tar file objects for custom
manipulation.  If you have the Compress::Zlib module installed,
Archive::Tar will also support compressed or gzipped tar files.

Class Methods
-------------

   The class methods should be sufficient for most tar file interaction.

create_archive ($file, $compression, @filelist)
     Creates a tar file from the list of files provided.  The first
     argument can either be the name of the tar file to create or a
     reference to an open file handle (e.g. a GLOB reference).

     The second argument specifies the level of compression to be used, if
     any.  Compression of tar files requires the installation of the
     Compress::Zlib module.  Specific levels or compression may be
     requested by passing a value between 2 and 9 as the second argument.
     Any other value evaluating as true will result in the default
     compression level being used.

     The remaining arguments list the files to be included in the tar file.
     These files must all exist.  Any files which don\'t exist or can\'t be
     read are silently ignored.

     If the archive creation fails for any reason, create_archive will
     return undef.  Please use the error method to find the cause of the
     failure.

list_archive ($file, ['property', 'property',...])
list_archive ($file)
     Returns a list of the names of all the files in the archive.  The
     first argument can either be the name of the tar file to create or a
     reference to an open file handle (e.g. a GLOB reference).

     If `list_archive()' is passed an array reference as its second
     argument it returns a list of hash references containing the requested
     properties of each file.  The following list of properties is
     supported: name, size, mtime (last modified date), mode, uid, gid,
     linkname, uname, gname, devmajor, devminor, prefix.

     Passing an array reference containing only one element, 'name', is
     special cased to return a list of names rather than a list of hash
     references.

extract_archive ($file)
     Extracts the contents of the tar file.  The first argument can either
     be the name of the tar file to create or a reference to an open file
     handle (e.g. a GLOB reference).  All relative paths in the tar file
     will be created underneath the current working directory.

     If the archive extraction fails for any reason, extract_archive will
     return undef.  Please use the error method to find the cause of the
     failure.

new ($file)
new ()
     Returns a new Tar object. If given any arguments, new() calls the
     read() method automatically, parsing on the arguments provided
     `read()' in this node.

     If new() is invoked with arguments and the read method fails for any
     reason, new() returns undef.

Instance Methods
----------------

read ($ref, $compressed)
     Read the given tar file into memory. The first argument can either be
     the name of a file or a reference to an already open file handle
     (e.g. a GLOB reference).  The second argument indicates whether the
     file referenced by the first argument is compressed.

     The second argument is now optional as Archive::Tar will automatically
     detect compressed archives.

     The read will replace any previous content in `$tar'!

add_files(@filenamelist)
     Takes a list of filenames and adds them to the in-memory archive.  On
     MacOS, the path to the file is automatically converted to a Unix like
     equivalent for use in the archive, and the file\'s modification time
     is converted from the MacOS epoch to the Unix epoch.  So tar archives
     created on MacOS with *Archive::Tar* can be read both with *tar* on
     Unix and applications like *suntar* or *Stuffit Expander* on MacOS.
     Be aware that the file\'s type/creator and resource fork will be lost,
     which is usually what you want in cross-platform archives.

add_data ($filename, $data, $opthashref)
     Takes a filename, a scalar full of data and optionally a reference to
     a hash with specific options. Will add a file to the in-memory
     archive, with name $filename and content $data. Specific properties
     can be set using `$opthashref', The following list of properties is
     supported: name, size, mtime (last modified date), mode, uid, gid,
     linkname, uname, gname, devmajor, devminor, prefix.  (On MacOS, the
     file\'s path and modification times are converted to Unix
     equivalents.)

remove (@filenamelist)
     Removes any entries with names matching any of the given filenames
     from the in-memory archive. String comparisons are done with eq.

write ($file, $compressed)
     Write the in-memory archive to disk.  The first argument can either be
     the name of a file or a reference to an already open file handle (be a
     GLOB reference).  If the second argument is true, the module will use
     Compress::Zlib to write the file in a compressed format.  If
     Compress:Zlib is not available, the write method will fail.  Specific
     levels of compression can be chosen by passing the values 2 through 9
     as the second parameter.

     If no arguments are given, write returns the entire formatted archive
     as a string, which could be useful if you\'d like to stuff the
     archive into a socket or a pipe to gzip or something.  This
     functionality may be deprecated later, however, as you can also do
     this using a GLOB reference for the first argument.

extract(@filenames)
     Write files whose names are equivalent to any of the names in
     `@filenames' to disk, creating subdirectories as necessary. This
     might not work too well under VMS.  Under MacPerl, the file\'s
     modification time will be converted to the MacOS zero of time, and
     appropriate conversions will be done to the path.  However, the length
     of each element of the path is not inspected to see whether it\'s
     longer than MacOS currently allows (32 characters).

     If extract is called without a list of file names, the entire
     contents of the archive are extracted.

list_files(['property', 'property',...])
list_files()
     Returns a list of the names of all the files in the archive.

     If list_files() is passed an array reference as its first argument it
     returns a list of hash references containing the requested properties
     of each file.  The following list of properties is supported: name,
     size, mtime (last modified date), mode, uid, gid, linkname, uname,
     gname, devmajor, devminor, prefix.

     Passing an array reference containing only one element, 'name', is
     special cased to return a list of names rather than a list of hash
     references.

get_content($file)
     Return the content of the named file.

replace_content($file,$content)
     Make the string $content be the content for the file named $file.

CHANGES
=======

Version 0.20
     Added class methods for creation, extraction and listing of tar files.
     No longer maintain a complete copy of the tar file in memory.  Removed
     the data() method.

Version 0.10
     Numerous changes. Brought source under CVS.  All changes now recorded
     in ChangeLog file in distribution.

Version 0.08
     New developer/maintainer.  Calle has carpal-tunnel syndrome and cannot
     type a great deal. Get better as soon as you can, Calle.

     Added proper support for MacOS.  Thanks to Paul J. Schinder
     <schinder@leprss.gsfc.nasa.gov>.

Version 0.071
     Minor release.

     Arrange to chmod() at the very end in case it makes the file read
     only.  Win32 is actually picky about that.

     SunOS 4.x tar makes tarfiles that contain directory entries that
     don\'t have typeflag set properly.  We use the trailing slash to
     recognise directories in such tar files.

Version 0.07
     Fixed (hopefully) broken portability to MacOS, reported by Paul J.
     Schinder at Goddard Space Flight Center.

     Fixed two bugs with symlink handling, reported in excellent detail by
     an admin at teleport.com called Chris.

     Primitive tar program (called ptar) included with distribution. Usage
     should be pretty obvious if you\'ve used a normal tar program.

     Added methods get_content and replace_content.

     Added support for paths longer than 100 characters, according to
     POSIX. This is compatible with just about everything except GNU tar.
     Way to go, GNU tar (use a better tar, or GNU cpio).

     NOTE: When adding files to an archive, files with basenames longer
       than 100 characters will be silently ignored. If the prefix part
        of a path is longer than 155 characters, only the last 155
     characters will be stored.

Version 0.06
     Added list_files() method, as requested by Michael Wiedman.

     Fixed a couple of dysfunctions when run under Windows NT. Michael
     Wiedmann reported the bugs.

     Changed the documentation to reflect reality a bit better.

     Fixed bug in format_tar_entry. Bug reported by Michael Schilli.

Version 0.05
     Quoted lots of barewords to make `use strict;' stop complaining under
     perl version 5.003.

     Ties to Compress/Zlib, put in. Will warn if it
     isn\'t available.

     $tar->write() with no argument now returns the formatted archive.

Version 0.04
     Made changes to write_tar so that Solaris tar likes the resulting
     archives better.

     Protected the calls to readlink() and symlink(). AFAIK this module
     should now run just fine on Windows NT.

     Add method to write a single entry to disk (extract)

     Added method to add entries entirely from scratch (add_data)

     Changed name of add() to add_file()

     All calls to croak() removed and replaced with returning undef and
     setting Tar::error.

     Better handling of tarfiles with garbage at the end.

Provide an interface to ZIP archive files.
******************************************

NAME
====

   Archive::Zip - Provide an interface to ZIP archive files.

SYNOPSIS
========

     use Archive::Zip qw( :ERROR_CODES :CONSTANTS );

     my $zip = Archive::Zip->new();
     my $member = $zip->addDirectory( 'dirname/' );
     $member = $zip->addString( 'This is a test', 'stringMember.txt' );
     $member->desiredCompressionMethod( COMPRESSION_DEFLATED );
     $member = $zip->addFile( 'xyz.pl', 'AnotherName.pl' );

     die 'write error' if $zip->writeToFileNamed( 'someZip.zip' ) != AZ_OK;

     $zip = Archive::Zip->new();
     die 'read error' if $zip->read( 'someZip.zip' ) != AZ_OK;

     $member = $zip->memberNamed( 'stringMember.txt' );
     $member->desiredCompressionMethod( COMPRESSION_STORED );

     die 'write error' if $zip->writeToFileNamed( 'someOtherZip.zip' ) != AZ_OK;

DESCRIPTION
===========

   The Archive::Zip module allows a Perl program to create, manipulate,
read, and write Zip archive files.

   Zip archives can be created, or you can read from existing zip files.
Once created, they can be written to files, streams, or strings.

   Members can be added, removed, extracted, replaced, rearranged, and
enumerated.  They can also be renamed or have their dates, comments, or
other attributes queried or modified.  Their data can be compressed or
uncompressed as needed.  Members can be created from members in existing
Zip files, or from existing directories, files, or strings.

   This module uses the `Compress::Zlib|Compress::Zlib' in this node
library to read and write the compressed streams inside the files.

EXPORTS
=======

:CONSTANTS
     Exports the following constants:

     FA_MSDOS FA_UNIX GPBF_ENCRYPTED_MASK GPBF_DEFLATING_COMPRESSION_MASK
     GPBF_HAS_DATA_DESCRIPTOR_MASK COMPRESSION_STORED COMPRESSION_DEFLATED
     IFA_TEXT_FILE_MASK IFA_TEXT_FILE IFA_BINARY_FILE
     COMPRESSION_LEVEL_NONE COMPRESSION_LEVEL_DEFAULT
     COMPRESSION_LEVEL_FASTEST COMPRESSION_LEVEL_BEST_COMPRESSION

:MISC_CONSTANTS
     Exports the following constants (only necessary for extending the
     module):

     FA_AMIGA FA_VAX_VMS FA_VM_CMS FA_ATARI_ST FA_OS2_HPFS FA_MACINTOSH
     FA_Z_SYSTEM FA_CPM FA_WINDOWS_NTFS
     GPBF_IMPLODING_8K_SLIDING_DICTIONARY_MASK
     GPBF_IMPLODING_3_SHANNON_FANO_TREES_MASK
     GPBF_IS_COMPRESSED_PATCHED_DATA_MASK COMPRESSION_SHRUNK
     DEFLATING_COMPRESSION_NORMAL DEFLATING_COMPRESSION_MAXIMUM
     DEFLATING_COMPRESSION_FAST DEFLATING_COMPRESSION_SUPER_FAST
     COMPRESSION_REDUCED_1 COMPRESSION_REDUCED_2 COMPRESSION_REDUCED_3
     COMPRESSION_REDUCED_4 COMPRESSION_IMPLODED COMPRESSION_TOKENIZED
     COMPRESSION_DEFLATED_ENHANCED
     COMPRESSION_PKWARE_DATA_COMPRESSION_LIBRARY_IMPLODED

:ERROR_CODES
     Explained below. Returned from most methods.

     AZ_OK AZ_STREAM_END AZ_ERROR AZ_FORMAT_ERROR AZ_IO_ERROR

OBJECT MODEL
============

Inheritance
-----------

     Exporter
        Archive::Zip                            Common base class, has defs.
            Archive::Zip::Archive               A Zip archive.
            Archive::Zip::Member                Abstract superclass for all members.
                Archive::Zip::StringMember      Member made from a string
                Archive::Zip::FileMember        Member made from an external file
                    Archive::Zip::ZipFileMember Member that lives in a zip file
                    Archive::Zip::NewFileMember Member whose data is in a file
                Archive::Zip::DirectoryMember   Member that is a directory

ERROR CODES
===========

   Many of the methods in Archive::Zip return error codes.  These are
implemented as inline subroutines, using the `use constant' pragma.  They
can be imported into your namespace using the `:CONSTANT' tag:

     use Archive::Zip qw( :CONSTANTS );
     ...
     die "whoops!" if $zip->read( 'myfile.zip' ) != AZ_OK;

AZ_OK (0)
     Everything is fine.

AZ_STREAM_END (1)
     The read stream (or central directory) ended normally.

AZ_ERROR (2)
     There was some generic kind of error.

AZ_FORMAT_ERROR (3)
     There is a format error in a ZIP file being read.

AZ_IO_ERROR (4)
     There was an IO error.

COMPRESSION
===========

   Archive::Zip allows each member of a ZIP file to be compressed (using
the Deflate algorithm) or uncompressed. Other compression algorithms that
some versions of ZIP have been able to produce are not supported.

   Each member has two compression methods: the one it's stored as (this
is always COMPRESSION_STORED for string and external file members), and
the one you desire for the member in the zip file.  These can be
different, of course, so you can make a zip member that is not compressed
out of one that is, and vice versa.  You can inquire about the current
compression and set the desired compression method:

     my $member = $zip->memberNamed( 'xyz.txt' );
     $member->compressionMethod();    # return current compression
     # set to read uncompressed
     $member->desiredCompressionMethod( COMPRESSION_STORED );
     # set to read compressed
     $member->desiredCompressionMethod( COMPRESSION_DEFLATED );

   There are two different compression methods:

COMPRESSION_STORED
     file is stored (no compression)

COMPRESSION_DEFLATED
     file is Deflated

Compression Levels
------------------

   If a member's desiredCompressionMethod is COMPRESSION_DEFLATED, you can
choose different compression levels. This choice may affect the speed of
compression and decompression, as well as the size of the compressed
member data.

     $member->desiredCompressionLevel( 9 );

   The levels given can be:

  1. or COMPRESSION_LEVEL_NONE This is the same as saying

          $member->desiredCompressionMethod( COMPRESSION_STORED );

  2. .. 9 1 gives the best speed and worst compression, and 9 gives the
     best compression and worst speed.

  3. COMPRESSION_LEVEL_FASTEST This is a synonym for level 1.

  4. COMPRESSION_LEVEL_BEST_COMPRESSION This is a synonym for level 9.

  5. COMPRESSION_LEVEL_DEFAULT This gives a good compromise between speed
     and compression, and is currently equivalent to 6 (this is in the
     zlib code).

     This is the level that will be used if not specified.

Archive::Zip methods
====================

   The Archive::Zip class (and its invisible subclass
Archive::Zip::Archive) implement generic zip file functionality.

   Creating a new Archive::Zip object actually makes an
Archive::Zip::Archive object, but you don't have to worry about this
unless you're subclassing.

Constructor
-----------

new( [$fileName] )
     Make a new, empty zip archive.

          my $zip = Archive::Zip->new();

     If an additional argument is passed, new() will call read() to read
     the contents of an archive:

          my $zip = Archive::Zip->new( 'xyz.zip' );

     If a filename argument is passed and the read fails for any reason,
     new will return undef. For this reason, it may be better to call read
     separately.

Utility Methods
---------------

   These Archive::Zip methods may be called as functions or as object
methods. Do not call them as class methods:

     $zip = Archive::Zip->new();
     $crc = Archive::Zip::computeCRC32( 'ghijkl' );    # OK
     $crc = $zip->computeCRC32( 'ghijkl' );            # also OK

     $crc = Archive::Zip->computeCRC32( 'ghijkl' );    # NOT OK

Archive::Zip::computeCRC32( $string [, $crc] )
     This is a utility function that uses the Compress::Zlib CRC routine
     to compute a CRC-32.

     You can get the CRC of a string:

          $crc = Archive::Zip::computeCRC32( $string );

     Or you can compute the running CRC:

          $crc = 0;
          $crc = Archive::Zip::computeCRC32( 'abcdef', $crc );
          $crc = Archive::Zip::computeCRC32( 'ghijkl', $crc );

Archive::Zip::setChunkSize( $number )
     Change chunk size used for reading and writing.  Currently, this
     defaults to 32K.  This is not exportable, so you must call it like:

          Archive::Zip::setChunkSize( 4096 );

     or as a method on a zip (though this is a global setting).  Returns
     old chunk size.

Archive::Zip::setErrorHandler( \&subroutine )
     Change the subroutine called with error strings.  This defaults to
     \&Carp::carp, but you may want to change it to get the error strings.

     This is not exportable, so you must call it like:

          Archive::Zip::setErrorHandler( \&myErrorHandler );

     If no error handler is passed, resets handler to default.

     Returns old error handler.

     Note that if you call Carp::carp or a similar routine or if you're
     chaining to the default error handler from your error handler, you
     may want to increment the number of caller levels that are skipped
     (do not just set it to a number):

          $Carp::CarpLevel++;

Accessors
---------

members()
     Return a copy of my members array

          my @members = $zip->members();

numberOfMembers()
     Return the number of members I have

memberNames()
     Return a list of the (internal) file names of my members

memberNamed( $string )
     Return ref to member whose filename equals given filename or undef

membersMatching( $regex )
     Return array of members whose filenames match given regular
     expression in list context.  Returns number of matching members in
     scalar context.

          my @textFileMembers = $zip->membersMatching( '.*\.txt' );
          # or
          my $numberOfTextFiles = $zip->membersMatching( '.*\.txt' );

diskNumber()
     Return the disk that I start on.  Not used for writing zips, but
     might be interesting if you read a zip in.  This had better be 0, as
     Archive::Zip does not handle multi-volume archives.

diskNumberWithStartOfCentralDirectory()
     Return the disk number that holds the beginning of the central
     directory.  Not used for writing zips, but might be interesting if
     you read a zip in.  This had better be 0, as Archive::Zip does not
     handle multi-volume archives.

numberOfCentralDirectoriesOnThisDisk()
     Return the number of CD structures on this disk.  Not used for
     writing zips, but might be interesting if you read a zip in.

numberOfCentralDirectories()
     Return the number of CD structures in the whole zip.  Not used for
     writing zips, but might be interesting if you read a zip in.

centralDirectorySize()
     Returns central directory size, as read from an external zip file.
     Not used for writing zips, but might be interesting if you read a zip
     in.

centralDirectoryOffsetWRTStartingDiskNumber()
     Returns the offset into the zip file where the CD begins.  Not used
     for writing zips, but might be interesting if you read a zip in.

zipfileComment( [$string] )
     Get or set the zipfile comment.  Returns the old comment.

          print $zip->zipfileComment();
          $zip->zipfileComment( 'New Comment' );

Member Operations
-----------------

   Various operations on a zip file modify members.  When a member is
passed as an argument, you can either use a reference to the member
itself, or the name of a member. Of course, using the name requires that
names be unique within a zip (this is not enforced).

removeMember( $memberOrName )
     Remove and return the given member, or match its name and remove it.
     Returns undef if member name doesn't exist in this Zip.  No-op if
     member does not belong to this zip.

replaceMember( $memberOrName, $newMember )
     Remove and return the given member, or match its name and remove it.
     Replace with new member.  Returns undef if member name doesn't exist
     in this Zip.

          my $member1 = $zip->removeMember( 'xyz' );
          my $member2 = $zip->replaceMember( 'abc', $member1 );
          # now, $member2 (named 'abc') is not in $zip,
          # and $member1 (named 'xyz') is, having taken $member2's place.

extractMember( $memberOrName [, $extractedName ] )
     Extract the given member, or match its name and extract it.  Returns
     undef if member doesn't exist in this Zip.  If optional second arg is
     given, use it as the name of the extracted member. Otherwise, the
     internal filename of the member is used as the name of the extracted
     file or directory.

     All necessary directories will be created.

     Returns AZ_OK on success.

extractMemberWithoutPaths( $memberOrName [, $extractedName ] )
     Extract the given member, or match its name and extract it.  Does not
     use path information (extracts into the current directory).  Returns
     undef if member doesn't exist in this Zip.  If optional second arg is
     given, use it as the name of the extracted member (its paths will be
     deleted too).  Otherwise, the internal filename of the member (minus
     paths) is used as the name of the extracted file or directory.

     Returns AZ_OK on success.

addMember( $member )
     Append a member (possibly from another zip file) to the zip file.
     Returns the new member.  Generally, you will use addFile(),
     addDirectory(), addString(), or read() to add members.

          # Move member named 'abc' to end of zip:
          my $member = $zip->removeMember( 'abc' );
          $zip->addMember( $member );

addFile( $fileName [, $newName ] )
     Append a member whose data comes from an external file, returning the
     member or undef.  The member will have its file name set to the name
     of the external file, and its desiredCompressionMethod set to
     COMPRESSION_DEFLATED.  The file attributes and last modification time
     will be set from the file.

     If the name given does not represent a readable plain file or
     symbolic link, undef will be returned.

     The text mode bit will be set if the contents appears to be text (as
     returned by the -T perl operator).

     The optional second argument sets the internal file name to something
     different than the given $fileName.

addString( $stringOrStringRef [, $name] )
     Append a member created from the given string or string reference.
     The name is given by the optional second argument.  Returns the new
     member.

     The last modification time will be set to now, and the file
     attributes will be set to permissive defaults.

          my $member = $zip->addString( 'This is a test', 'test.txt' );

addDirectory( $directoryName [, $fileName ] )
     Append a member created from the given directory name.  The directory
     name does not have to name an existing directory.  If the named
     directory exists, the file modification time and permissions are set
     from the existing directory, otherwise they are set to now and
     permissive default permissions.  The optional second argument sets
     the name of the archive member (which defaults to $directoryName)

     Returns the new member.

contents( $memberOrMemberName [, $newContents ] )
     Returns the uncompressed data for a particular member, or undef.

          print "xyz.txt contains " . $zip->contents( 'xyz.txt' );

     Also can change the contents of a member:

          $zip->contents( 'xyz.txt', 'This is the new contents' );

writeToFileNamed( $fileName )
     Write a zip archive to named file.  Returns AZ_OK on success.

     Note that if you use the same name as an existing zip file that you
     read in, you will clobber ZipFileMembers.  So instead, write to a
     different file name, then delete the original.

          my $status = $zip->writeToFileNamed( 'xx.zip' );
          die "error somewhere" if $status != AZ_OK;

writeToFileHandle( $fileHandle [, $seekable] )
     Write a zip archive to a file handle.  Return AZ_OK on success.

     The optional second arg tells whether or not to try to seek backwards
     to re-write headers.  If not provided, it is set by testing
     seekability. This could fail on some operating systems, though.

          my $fh = IO::File->new( 'someFile.zip', 'w' );
          $zip->writeToFileHandle( $fh );

     If you pass a file handle that is not seekable (like if you're writing
     to a pipe or a socket), pass a false as the second argument:

          my $fh = IO::File->new( '| cat > somefile.zip', 'w' );
          $zip->writeToFileHandle( $fh, 0 );   # fh is not seekable

read( $fileName )
     Read zipfile headers from a zip file, appending new members.  Returns
     AZ_OK or error code.

          my $zipFile = Archive::Zip->new();
          my $status = $zipFile->read( '/some/FileName.zip' );

MEMBER OPERATIONS
=================

Class Methods
-------------

   Several constructors allow you to construct members without adding them
to a zip archive.

   These work the same as the addFile(), addDirectory(), and addString()
zip instance methods described above, but they don't add the new members
to a zip.

Archive::Zip::Member->newFromString( $stringOrStringRef [, $fileName] )
     Construct a new member from the given string. Returns undef on error.

          my $member = Archive::Zip::Member->newFromString( 'This is a test',
                                                           'xyz.txt' );

newFromFile( $fileName )
     Construct a new member from the given file. Returns undef on error.

          my $member = Archive::Zip::Member->newFromFile( 'xyz.txt' );

newDirectoryNamed( $directoryName )
     Construct a new member from the given directory.  Returns undef on
     error.

          my $member = Archive::Zip::Member->newDirectoryNamed( 'CVS/' );

Simple accessors
----------------

   These methods get (and/or set) member attribute values.

versionMadeBy()
     Gets the field from my member header.

fileAttributeFormat( [$format] )
     Gets or sets the field from the member header.  These are `FA_*'
     values.

versionNeededToExtract()
     Gets the field from my member header.

bitFlag()
     Gets the general purpose bit field from my member header.  This is
     where the `GPBF_*' bits live.

compressionMethod()
     Returns my compression method. This is the method that is currently
     being used to compress my data.

     This will be COMPRESSION_STORED for added string or file members, or
     any of the `COMPRESSION_*' values for members from a zip file.
     However, this module can only handle members whose data is in
     COMPRESSION_STORED or COMPRESSION_DEFLATED format.

desiredCompressionMethod( [$method] )
     Get or set my desiredCompressionMethod This is the method that will
     be used to write.  Returns prior desiredCompressionMethod.

     Only COMPRESSION_DEFLATED or COMPRESSION_STORED are valid arguments.

     Changing to COMPRESSION_STORED will change my desiredCompressionLevel
     to 0; changing to COMPRESSION_DEFLATED will change my
     desiredCompressionLevel to COMPRESSION_LEVEL_DEFAULT.

desiredCompressionLevel( [$method] )
     Get or set my desiredCompressionLevel This is the method that will be
     used to write.  Returns prior desiredCompressionLevel.

     Valid arguments are 0 through 9, COMPRESSION_LEVEL_NONE,
     COMPRESSION_LEVEL_DEFAULT, COMPRESSION_LEVEL_BEST_COMPRESSION, and
     COMPRESSION_LEVEL_FASTEST.

     0 or COMPRESSION_LEVEL_NONE will change the desiredCompressionMethod
     to COMPRESSION_STORED. All other arguments will change the
     desiredCompressionMethod to COMPRESSION_DEFLATED.

fileName()
     Get or set my internal filename.  Returns the (possibly new) filename.

     Names will have backslashes converted to forward slashes, and will
     have multiple consecutive slashes converted to single ones.

lastModFileDateTime()
     Return my last modification date/time stamp in MS-DOS format.

lastModTime()
     Return my last modification date/time stamp, converted to unix
     localtime format.

          print "Mod Time: " . scalar( localtime( $member->lastModTime() ) );

setLastModFileDateTimeFromUnix()
     Set my lastModFileDateTime from the given unix time.

          $member->setLastModFileDateTimeFromUnix( time() );

internalFileAttributes()
     Return the internal file attributes field from the zip header.  This
     is only set for members read from a zip file.

externalFileAttributes()
     Return member attributes as read from the ZIP file.  Note that these
     are NOT UNIX!

unixFileAttributes( [$newAttributes] )
     Get or set the member's file attributes using UNIX file attributes.
     Returns old attributes.

          my $oldAttribs = $member->unixFileAttributes( 0666 );

     Note that the return value has more than just the file permissions,
     so you will have to mask off the lowest bits for comparisions.

localExtraField( [$newField] )
     Gets or sets the extra field that was read from the local header.
     This is not set for a member from a zip file until after the member
     has been written out.

     The extra field must be in the proper format.

cdExtraField( [$newField] )
     Gets or sets the extra field that was read from the central directory
     header.

     The extra field must be in the proper format.

extraFields()
     Return both local and CD extra fields, concatenated.

fileComment( [$newComment] )
     Get or set the member's file comment.

hasDataDescriptor()
     Get or set the data descriptor flag.  If this is set, the local
     header will not necessarily have the correct data sizes. Instead, a
     small structure will be stored at the end of the member data with
     these values.

     This should be transparent in normal operation.

crc32()
     Return the CRC-32 value for this member.  This will not be set for
     members that were constructed from strings or external files until
     after the member has been written.

crc32String()
     Return the CRC-32 value for this member as an 8 character printable
     hex string.  This will not be set for members that were constructed
     from strings or external files until after the member has been
     written.

compressedSize()
     Return the compressed size for this member.  This will not be set for
     members that were constructed from strings or external files until
     after the member has been written.

uncompressedSize()
     Return the uncompressed size for this member.

isEncrypted()
     Return true if this member is encrypted.  The Archive::Zip module
     does not currently create or extract encrypted members.

isTextFile( [$flag] )
     Returns true if I am a text file.  Also can set the status if given
     an argument (then returns old state).  Note that this module does not
     currently do anything with this flag upon extraction or storage.
     That is, bytes are stored in native format whether or not they came
     from a text file.

isBinaryFile()
     Returns true if I am a binary file.  Also can set the status if given
     an argument (then returns old state).  Note that this module does not
     currently do anything with this flag upon extraction or storage.
     That is, bytes are stored in native format whether or not they came
     from a text file.

extractToFileNamed( $fileName )
     Extract me to a file with the given name.  The file will be created
     with default modes.  Directories will be created as needed.

     Returns AZ_OK on success.

isDirectory()
     Returns true if I am a directory.

Low-level member data reading
-----------------------------

   It is possible to use lower-level routines to access member data
streams, rather than the extract* methods and contents().

   For instance, here is how to print the uncompressed contents of a
member in chunks using these methods:

     my ( $member, $status, $bufferRef );
     $member = $zip->memberNamed( 'xyz.txt' );
     $member->desiredCompressionMethod( COMPRESSION_STORED );
     $status = $member->rewindData();
     die "error $status" if $status != AZ_OK;
     while ( ! $member->readIsDone() )
     {
         ( $bufferRef, $status ) = $member->readChunk();
         die "error $status" if $status != AZ_OK;
         # do something with $bufferRef:
         print $$bufferRef;
     }
     $member->endRead();

readChunk( [$chunkSize] )
     This reads the next chunk of given size from the member's data stream
     and compresses or uncompresses it as necessary, returning a reference
     to the bytes read and a status.  If size argument is not given,
     defaults to global set by Archive::Zip::setChunkSize.  Status is
     AZ_OK on success. Returns `( \$bytes, $status)'.

          my ( $outRef, $status ) = $self->readChunk();
          print $$outRef if $status != AZ_OK;

rewindData()
     Rewind data and set up for reading data streams or writing zip files.
     Can take options for `inflateInit()' or `deflateInit()', but this
     isn't likely to be necessary.  Subclass overrides should call this
     method.  Returns AZ_OK on success.

endRead()
     Reset the read variables and free the inflater or deflater.  Must be
     called to close files, etc.

     Returns AZ_OK on success.

readIsDone()
     Return true if the read has run out of data or errored out.

contents()
     Return the entire uncompressed member data or undef in scalar context.
     When called in array context, returns `( $string, $status )'; status
     will be AZ_OK on success:

          my $string = $member->contents();
          # or
          my ( $string, $status ) = $member->contents();
          die "error $status" if $status != AZ_OK;

     Can also be used to set the contents of a member (this may change the
     class of the member):

          $member->contents( "this is my new contents" );

extractToFileHandle( $fh )
     Extract (and uncompress, if necessary) my contents to the given file
     handle.  Return AZ_OK on success.

Archive::Zip::FileMember methods
================================

   The Archive::Zip::FileMember class extends Archive::Zip::Member.  It is
the base class for both ZipFileMember and NewFileMember classes.  This
class adds an `externalFileName' and an fh member to keep track of the
external file.

externalFileName()
     Return my external filename.

fh()
     Return my read file handle.  Automatically opens file if necessary.

Archive::Zip::ZipFileMember methods
===================================

   The Archive::Zip::ZipFileMember class represents members that have been
read from external zip files.

diskNumberStart()
     Returns the disk number that my local header resides in. Had better
     be 0.

localHeaderRelativeOffset()
     Returns the offset into the zip file where my local header is.

dataOffset()
     Returns the offset from the beginning of the zip file to my data.

AUTHOR
======

   Ned Konz, perl@bike-nomad.com

COPYRIGHT
=========

   Copyright (c) 2000 Ned Konz. All rights reserved.  This program is free
software; you can redistribute it and/or modify it under the same terms as
Perl itself.

SEE ALSO
========

   See Compress/Zlib,

methods for adding/extracting trees using Archive::Zip
******************************************************

NAME
====

   Archive::Zip::Tree - methods for adding/extracting trees using
Archive::Zip

SYNOPSIS
========

     use Archive::Zip;
     use Archive::Zip::Tree;
     my $zip = Archive::Zip->new();
     # add all readable files and directories below . as xyz/*
     $zip->addTree( '.', 'xyz' );
     # add all readable plain files below /abc as /def/*
     $zip->addTree( '/abc', '/def', sub { -f && -r } );
     # add all .c files below /tmp as stuff/*
     $zip->addTreeMatching( '/tmp', 'stuff', '\.c$' );
     # add all .o files below /tmp as stuff/* if they aren't writable
     $zip->addTreeMatching( '/tmp', 'stuff', '\.o$', sub { ! -w } );
     # and write them into a file
     $zip->writeToFile('xxx.zip');

     # now extract the same files into /tmpx
     $zip->extractTree( 'stuff', '/tmpx' );

METHODS
=======

$zip->addTree( $root, $dest [,$pred] )
     $root is the root of the tree of files and directories to be added

     $dest is the name for the root in the zip file (undef or blank means
     to use relative pathnames)

     `$pred' is an optional subroutine reference to select files: it is
     passed the name of the prospective file or directory using $_, and if
     it returns true, the file or directory will be included.  The default
     is to add all readable files and directories.

     For instance, using

          my $pred = sub { /\.txt/ };
          $zip->addTree( '.', '.', $pred );

     will add all the .txt files in and below the current directory, using
     relative names, and making the names identical in the zipfile:

          original name           zip member name
          ./xyz                   xyz
          ./a/                    a/
          ./a/b                   a/b

     To use absolute pathnames, just pass them in:

     $zip->addTree( '/a/b', '/a/b' );

          original name           zip member name
          /a/                     /a/
          /a/b                    /a/b

     To translate relative to absolute pathnames, just pass them in:

     $zip->addTree( '.', '/c/d' );

          original name           zip member name
          ./xyz                   /c/d/xyz
          ./a/                    /c/d/a/
          ./a/b                   /c/d/a/b

     To translate absolute to relative pathnames, just pass them in:

     $zip->addTree( '/c/d', 'a' );

          original name           zip member name
          /c/d/xyz                a/xyz
          /c/d/a/                 a/a/
          /c/d/a/b                a/a/b

     Returns AZ_OK on success.

     Note that this will not follow symbolic links to directories.

     Note also that this does not check for the validity of filenames.

$zip->addTreeMatching( $root, $dest, $pattern [,$pred] )
     $root is the root of the tree of files and directories to be added

     $dest is the name for the root in the zip file (undef means to use
     relative pathnames)

     $pattern is a (non-anchored) regular expression for filenames to match

     $pred is an optional subroutine reference to select files: it is
     passed the name of the prospective file or directory in $_, and if it
     returns true, the file or directory will be included.  The default is
     to add all readable files and directories.

     To add all files in and below the current dirctory whose names end in
     `.pl', and make them extract into a subdirectory named `xyz', do this:

          $zip->addTreeMatching( '.', 'xyz', '\.pl$' )

     To add all writable files in and below the dirctory named `/abc'
     whose names end in `.pl', and make them extract into a subdirectory
     named `xyz', do this:

          $zip->addTreeMatching( '/abc', 'xyz', '\.pl$', sub { -w } )

     Returns AZ_OK on success.

     Note that this will not follow symbolic links to directories.

$zip->extractTree( $root, $dest )
     Extracts all the members below a given root. Will translate that root
     to a given dest pathname.

     For instance,

          $zip->extractTree( '/a/', 'd/e/' );

     when applied to a zip containing the files:  /a/x /a/b/c /d/e

     will extract:  /a/x to d/e/x  /a/b/c to d/e/b/c

     and ignore /d/e

AUTHOR
======

   Ned Konz, perl@bike-nomad.com

COPYRIGHT
=========

   Copyright (c) 2000 Ned Konz. All rights reserved.  This program is free
software; you can redistribute it and/or modify it under the same terms as
Perl itself.

SEE ALSO
========

   See Compress/Zlib, Archive/Zip,

Provide an O-O interface to an ARGV
***********************************

NAME
====

   Argv - Provide an O-O interface to an ARGV

SYNOPSIS
========

     use Argv;

     # A roundabout way of getting perl's version.
     my $pl = Argv->new(qw(perl -v));
     $pl->exec;

     # Run /bin/cat, showing how to provide "predigested" options.
     Argv->new('/bin/cat', [qw(-u -n)], @ARGV)->system;

     # A roundabout way of globbing.
     my $echo = Argv->new(qw(echo M*));
     $echo->glob;
     my $globbed = $echo->qx;
     print "'echo M*' globs to: $globbed";

     # A demonstration of the builtin xargs-like behavior.
     my @files = split(/\s+/, $globbed);
     my $ls = Argv->new(qw(ls -d -l), @files);
     $ls->parse(qw(d l));
     $ls->dbglevel(1);
     $ls->qxargs(1);
     my @long = $ls->qx;
     $ls->dbglevel(0);
     print @long;

     # A demonstration of how to use option sets in a wrapper program.
     @ARGV = qw(Who -a -y foo -r);	# hack up an @ARGV
     my $who = Argv->new(@ARGV);		# instantiate
     $who->dbglevel(1);			# set verbosity
     $who->optset(qw(UNAME FOO WHO));	# define 3 option sets
     $who->parseUNAME(qw(a m n p));	# parse these to set UNAME
     $who->parseFOO(qw(y=s z));		# parse -y and -z to FOO
     $who->parseWHO('r');		# for the 'who' cmd
     warn "got -y flag in option set FOO\n" if $who->flagFOO('y');
     print Argv->new('uname', $who->optsUNAME)->qx;
     $who->prog(lc $who->prog);		# force $0 to lower case
     $who->exec(qw(WHO));		# exec the who cmd

   More advanced examples can be lifted from the test script or the
./examples subdirectory.

RAISON D'ETRE
=============

   This module presents an O-O approach to command lines, allowing you to
instantiate an 'argv object', manipulate it, and eventually run it, e.g.:

     my $ls = Argv->new('ls', ['-l']));
     my $rc = $ls->system;	# or $ls->exec or $ls->qx

   Which raises the immediate question - what value does this mumbo-jumbo
add over Perl's native support, e.g.:

     my $rc = system(qw(ls -l));

   The answer comes in a few parts:

   * STRUCTURE

     First, Argv recognizes the underlying property of an arg vector, which
     is that it begins with a program name potentially followed by options,
     then operands. An Argv object factors a raw argv into these three
     groups, provides accessor methods to allow operations on each group
     independently, and can then put them back together for execution.

   * OPTION SETS

     Second, Argv encapsulates and extends Getopt::Long to allow parsing
     of the argv's options into different *option sets*. This is useful in
     the case of wrapper programs which may, for instance, need to parse
     out one set of flags to direct the behavior of the wrapper itself,
     extract a different set and pass them to program X, another for
     program Y, then exec program Z with the remainder.  Doing this kind
     of thing on a basic @ARGV using indexing and splicing is do-able but
     leads to spaghetti code and potential off-by-one errors.

   * EXTRA FEATURES

     The *execution methods* `system, exec, and qx' extend their Perl
     builtin analogues in a few ways, for example:

       1. An xargs-like capability without shell intervention.

       2. UNIX-like exec() behavior on Windows.

       3. Automatic quoting of `system()' on Win32 and `qx()' everywhere

       4. Automatic globbing (primarily for Windows)

       5. Automatic chomping.

       6. Pathname normalization.
          All of these behaviors can be toggled, either as class or
instance attributes. See EXECUTION ATTRIBUTES below.

DESCRIPTION
===========

   An Argv object treats a command line as 3 separate entities: the
program, the options, and the args. The options may be futher subdivided
into user-defined *option sets* by use of the `optset' method. When one of
the *execution methods* is called, the parts are reassmbled into a single
list and passed to the underlying Perl execution function.

   Compare this with the way Perl works natively, keeping the 0th element
of the argv in $0 and the rest in `@ARGV'.

   By default there's one option set, known as the *anonymous option set*,
whose name is the null string. All parsed options go there.  The advanced
user can define more option sets, parse options into them according to
Getopt::Long-style descriptions, query or set the parsed values, and then
reassemble them in any way desired at exec time.  Declaring an option set
automatically generates a set of methods for manipulating it (see below).

   All argument-parsing within Argv is done via Getopt::Long.

AUTOLOADING
===========

   Argv employs the same technique made famous by the Shell module to
allow any command name to be used as a method. E.g.

     $obj->date->exec;

   will run the 'date' command. Internally this is translated into

     $obj->argv('date')->exec;

FUNCTIONAL INTERFACE
====================

   Because the extensions to `system/exec/qx' described here may be useful
in writing portable programs, they're made available for export as
traditional functions. Thus:

     use Argv qw(system exec qv);

   will override the Perl builtins. There's no way to override the
operator `qx()' so an alias `qv()' is provided.

CONSTRUCTOR
===========

     my $obj = Argv->new(@list)

   The `@list' is what will be parsed/executed/etc by subsequent method
calls. During initial construction, the first element of the list is
separated off as the program; the rest is lumped together as part of the
args until and unless option parsing is done, in which case matched
options are shifted into collectors for their various *option sets*. You
can also create a "predigested" instance by passing any or all of the
prog, opt, or arg parts as array refs. E.g.

     Argv->new([qw(cvs ci)], [qw(-l -n)], qw(file1 file2 file3));

   Predigested options are placed in the default (anonymous) option set.

   The constructor can be used as a class or instance method. In the
latter case the new object is a deep (full) clone of its progenitor.  In
fact 'clone' is aliased to 'new', allowing clones to be created via:

     my $copy = $orig->clone;

   The first argument to new() or clone() can be a hash-ref, which will be
used to set *execution attributes* at construction time. I.e.:

     my $obj = Argv->new({autochomp => 1, stderr => 0}, @ARGV);

   you may choose to add the command line later:

     my $obj = Argv->new;
     $obj->prog('cat');
     $obj->args('/etc/motd');

   Or

     my $obj = Argv->new({autochomp=>1});
     my $motd = $obj->argv(qw(cat /etc/motd))->qx;

   Or (using the autoloading interface)

     my $motd = $obj->cat('/etc/motd')->qx;

METHODS
=======

INSTANCE METHODS
----------------

   * prog()

     Returns or sets the name of the program (the `"argv[0]"'). This can be
     a list, e.g. `qw(rcs co)' or an array reference.

   * opts()

     Returns or sets the list of operands (aka arguments). As above, it may
     be passed a list or an array reference. This is simply the member of
     the class of optsNAME() methods (see below) whose <NAME> is null;
     it's part of the predefined *anonymous option set*.

   * args()

     Returns or sets the list of operands (aka arguments).  If called in a
     void context and without args, the effect is to set the list of
     operands to `()'.

   * optset(<list-of-set-names>);

     For each name NAME in the parameter list, an *option set* of that
     name is declared and 3 new methods are registered dynamically:
     `parse*NAME*(), opts*NAME*(), and flagNAME()'. These methods are
     described below: note that the *anonymous option set* (see *OPTION
     SETS*) is predefined, so the methods `parse(), opts(), and flag()' are
     always available.  Most users won't need to define any other sets.
     Note that option-set names are forced to upper case. E.g.:

          $obj->optset('FOO');

   * parseNAME(...option-descriptions...)

     Takes a list of option descriptions and uses
     Getopt::Long::GetOptions() to parse them out of the current argv *and
     into option set NAME*.  The opt-descs are exactly as supported by
     parseFOO() are exactly the same as those described for Getopt::Long,
     except that no linkage argument is allowed. E.g.:

          $obj->parseFOO(qw(file=s list=s@ verbose));

   * optsNAME()

     Returns or sets the list of options in the *option set NAME*.

   * flagNAME()

     Sets or gets the value of a flag in the appropriate optset, e.g.:

          print "blah blah blah\n" if $obj->flagFOO('verbose');
          $obj->flagFOO('verbose' => 1);

   * extract

     Takes an *optset* name and a list of option descs; creates the named
     optset, extracts any of the named options, places them in the
     specified optset, and returns them.

   * quote(@list)

     Protects the argument list against exposure to a shell by quoting each
     element. This method is invoked automatically by the system method on
     Windows platforms, where the underlying system primitive always uses
     a shell, and by the *qx* method on all platforms since it invokes a
     shell on all platforms.

     The automatic use of quote can be turned off via the *autoquote*
     method (see).

     IMPORTANT: this method quotes its argument list *in place*. In other
     words, it may modify its arguments.

   * glob

     Expands the argument list using the Perl glob builtin. Primarily
     useful on Windows where the invoking shell does not do this for you.

     Automatic use of glob on Windows can be enabled via the *autoglob*
     method (vide infra).

EXECUTION METHODS
-----------------

   The three methods below are direct analogues of the Perl builtins.
They simply reassemble a command line from the prog, *opts*, and args
parts according to the option-set rules described below and invoke their
builtin equivalent on it.

   * system([<optset-list>])

     Reassembles the argv and invokes system(). Return value and value of
     $?, $!, etc. are just as described in *perlfunc/"system"*

     Arguments to this method determine which of the parsed option-sets
     will be used in the executed argv. If passed no arguments,
     `$obj->system' uses the value of the 'dfltsets' attribute as the list
     of desired sets.  The default value of 'dfltsets' is the anonymous
     option set.

     An option set may be requested by passing its name (with an optional
     leading '+') or explicitly rejected by using its name with a leading
     '-'. Thus, given the existence of option sets *ONE, TWO, and THREE*,
     the following are legal:

          $obj->system;			# use the anonymous set only
          $obj->system('+');			# use all option sets
          $obj->system(qw(ONE THREE);		# use sets ONE and THREE

     The following sequence would also use sets ONE and THREE.

          $obj->dfltsets({ONE => 1, THREE => 1});
          $obj->system;

     while this would use all parsed options:

          $obj->dfltsets({'+' => 1});
          $obj->system;

     and this would set the default to none class-wide, and then use it:

          $obj->dfltsets({'-' => 1});
          $obj->system;

     By default the `$obj->system' method autoquotes its arguments *iff*
     the platform is Windows and the arguments are a list, because in this
     case a shell is always used. This behavior can be toggled with
     `$obj->autoquote'.  *Note: if and when Perl 5.6 fixes this "bug",
     Argv will be changed to examine the value of $]*.

   * exec()

     Similar to system above, but never returns. On Windows, it blocks
     until the new process finishes for a more UNIX-like behavior than the
     exec implemented by the C runtime library on Windows, if the
     *execwait* attribute is set. This is actually implemented as

          exit $obj->system(LIST);

     and thus all system shell-quoting issues apply

     Option sets are handled as described in system above.

   * qx()

     Same semantics as described in *perlfunc/"qx"* but has the capability
     to process only a set number of arguments at a time to avoid exceeding
     the shell's line-length limit. This value is settable with the
     *qxargs* method.

     Also, if *autoquote* is set the arguments are quoted to protect them
     against the platform-standard shell *on all platforms*.

     Option sets are handled as described in system above.

EXECUTION ATTRIBUTES
--------------------

   The behavior of the *execution methods* `system, exec, and qx' is
governed by a set of *execution attributes*, which are in turn manipulated
via a set of eponymous methods. These methods are auto-generated and thus
share certain common characteristics:

   * Translucency

     They can all be invoked as class or instance methods.  If used as an
     instance method the attribute is set only on that object; if used on
     the class it sets or gets the default for all instances which haven't
     overridden it.  This is inspired by the section on *translucent
     attributes* in Tom Christiansen's *perltootc* tutorial.

   * Class Defaults

     Each attribute has a default which may be overridden with an
     environment variable by prepending the class name, e.g.
     ARGV_QXARGS=256 or ARGV_STDERR=0;

   * Context Sensitivity

     The attribute value is always a scalar. If a value is passed it
     becomes the new value of the attribute and the object or class is
     returned. If no value is passed *and there is a valid return
     context*, the current value is returned. In a void context with no
     parameter, the attribute value is set to 1.

   * Stickiness

     A subtlety: if an *execution attribute* is set in a void context, that
     attribute is *"sticky"*, i.e. it retains its state until explicitly
     changed. But if *a new value is provided* and the context is not void,
     the new value is *temporary*. It lasts until the next *execution
     method* (`system, exec, or qx') invocation, after which the previous
     value is restored. This feature allows locutions like this:

          $obj->cmd('date')->stderr(1)->system;

     Assuming that the $obj object already exists and has a set of
     attributes; we can override one of them at execution time.  More
     examples:

          $obj->stdout(1);          # set attribute, sticky
          $obj->stdout;             # same as above
          $foo = $obj->stdout;      # get attribute value
          $obj2 = $obj->stdout(1);  # set to 1 (temporary), return $obj

   * autochomp

     All data returned by the `qx' method is chomped first. Unset by
     default.

   * autofail

     When set, the program will exit immediately if the system or `qx'
     methods detect a nonzero status. Unset by default.

     Autofail may also be given a code-ref, in which case that function
     will be called upon error. This provides a basic "exception-handling"
     system:

          $obj->autofail(sub { print "caught an exception\n"; exit 17 });

     Any failed executions by $obj will call `handler()'. Alternatively,
     if the reference provided is an array-ref, the first element of that
     array is assumed to be a code-ref as above and the rest of the array
     is passed as args to the function on failure.

   * syfail,qxfail

     Similar to `autofail' but apply only to `system()' or `qx()'
     respectively. Unset by default.

   * autoglob

     If set, the `glob()' function is applied to the operands
     (`$obj->args') on Windows only. Unset by default.

   * autoquote

     If set, the operands are automatically quoted against shell expansion
     before `system()' on Windows and `qx()' on all platforms (since `qx'
     always invokes a shell, and `system()' always does so on Windows).
     Set by default.

   * dbglevel

     Sets the debug level. Level 0 (the default) is no debugging, 1 prints
     each command before executing it, and higher levels offer
     progressively more output.

   * dfltsets

     Sets and/or returns the default set of *option sets* to be used in
     building up the command line at execution time.  The default-default
     is the *anonymous option set*. *Note: this method takes a *hash
     reference* as its optional argument and returns a hash ref as well*.
     The selected sets are represented by the hash keys; the values are
     meaningless.

   * execwait

     If set, `$obj->exec' on Windows blocks until the new process is
     finished for a more consistent UNIX-like behavior than the traditional
     Win32 Perl port. Perl just uses the Windows exec() routine, which runs
     the new process in the background. Set by default.

   * inpathnorm

     If set, normalizes pathnames to their native format just before
     executing. This is set by default on Windows only, thus converting
     /x/y/z to \x\y\z.

   * outpathnorm

     If set, normalizes pathnames returned by the `qx' method from
     \-delimited to /-delimited. This is NOT set by default; even when set
     it's a no-op except on Windows.

   * noexec

     Analogous to the -n flag to make; prints what would be executed
     without executing anything.

   * qxargs

     You can set a maximum number of arguments to be processed at a time,
     allowing you to blithely invoke e.g. `$obj->qx' on a list of any size
     without fear of exceeding your shell's limits. A per-platform default
     is set; this method allows it to be changed. A value of 0 suppresses
     the behavior.

   * syxargs

     Analogous to *qxargs* but applies to `system()' and is turned off by
     default. The reason is that `qx()' is typically used to read data
     whereas `system()' is more often used to make stateful changes.
     Consider that "ls foo bar" produces the same result if broken up into
     "ls foo" and "ls bar" but the same cannot be said for "mv foo bar".

   * stdout

     Setting this attribute to 0, e.g:

          $obj->stdout(0);

     causes STDOUT to be closed during invocation of any of the *execution
     methods* `system, exec, and qx', and restored when they finish. A
     fancy (and portable) way of saying `1>/dev/null' without needing a
     shell. A value of 2 is the equivalent of `1>&2'.

   * stderr

     As above, for STDERR. A value of 1 is the equivalent of `2>&1':

          @alloutput = $obj->stderr(1)->qx;

   * attropts

     The attributes above can be set via method calls (e.g.
     `$obj->dbglevel(1)') or environment variables (ARGV_DBGLEVEL=1). Use
     of the <$obj->attropts> method allows them to be parsed from the
     command line as well, e.g. *myscript -/dbglevel 1*. If invoked as a
     class method it causes options of the same names as the methods above
     to be parsed (and removed) from the current `@ARGV' and set as class
     attributes.  As an instance method it parses and potentially depletes
     the current argument vector of that object, and sets instance
     attributes only. E.g.:

          Argv->attropts;

     would cause the script to parse the following command line:

          script -/noexec 1 -/dbglevel=2 -flag1 -flag2 arg1 arg2 arg3 ...

     so as to remove the `-/noexec 1 -/dbglevel 2' and set the two class
     attrs.  The `-/' prefix is chosen to prevent conflicts with "real"
     flags. Abbreviations are allowed as long as they're unique within the
     set of -/ flags. Whereas

          $obj->attropts;

     would parse the current value of `$obj->args' and run

          $obj->foo(1);

     for every instance of `-/foo=1' found there.

PORTING
=======

   This module is known to work on Solaris 2.5-7 and Windows NT 4.0SP3-5,
and with perl 5.004_04 and 5.005_03.  As these two platforms are quite
different, there should be no *major* portability issues, but please send
bug reports or patches to the address below.

BUGS
====

   Argv uses `Getopt::Long::Configure()' to modify configurable parameters
in order to do some advanced option parsing with Getopt::Long.
Unfortunately, older versions of Getopt::Long offer no way to set those
parameters back the way they were; they can only be set to their default
values. Therefore, when using Getopt::Long 2.23 or above Argv will restore
prior settings but with older versions it will reset them to their
defaults instead.  This may lead to confusing behavior if the using code
also calls `Getopt::Long::Configure()'.

AUTHOR
======

   David Boyce <dsb@world.std.com>

COPYRIGHT
=========

   Copyright (c) 1999,2000 David Boyce. All rights reserved.  This Perl
program is free software; you may redistribute and/or modify it under the
same terms as Perl itself.

SEE ALSO
========

   perl(1), Getopt::Long(3), IPC::ChildSafe(3)

Perl extension for comparing arrays.
************************************

NAME
====

   Array::Compare - Perl extension for comparing arrays.

SYNOPSIS
========

     use Array::Compare;

     my $comp1 = Array::Compare->new;
     $comp->Sep('|');
     $comp->Skip({3 => 1, 4 => 1});
     $comp->WhiteSpace(0);
     $comp->Case(1);

     my $comp2 = Array::Compare->new(Sep => '|', WhiteSpace => 0, Case => 1,
                                     Skip => {3 => 1, 4 => 1});

     my @arr1 = 0 .. 10;
     my @arr2 = 0 .. 10;

     $comp1->compare(\@arr1, \@arr2);
     $comp2->compare(\@arr1, \@arr2);

DESCRIPTION
===========

   If you have two arrays and you want to know if they are the same or
different, then Array::Compare will be useful to you.

   All comparisons are carried out via a comparator object. In the
simplest usage, you can create and use a comparator object like this:

     my @arr1 = 0 .. 10;
     my @arr2 = 0 .. 10;

     my $comp = Array::Compare->new;

     if ($comp->compare(\@arr1, \@arr2) {
       print "Arrays are the same\n";
     } else {
       print "Arrays are different\n";
     }

   Notice that you pass references to the two arrays to the comparision
method.

   Internally the comparator compares the two arrays by using join to turn
both arrays into strings and comparing the strings using eq. In the joined
strings, the elements of the original arrays are separated with the `^G'
character. This can cause problems if your array data contains `^G'
characters as it is possible that two different arrays can be converted to
the same string.

   To avoid this, it is possible to override the default separator
character, either by passing and alternative to the new function

     my $comp = Array::Compare->new(Sep => '|');

   or by changing the seperator for an existing comparator object

     $comp->Sep('|');

   In general you should choose a separator character that won't appear in
your data.

   You can also control whether or not whitespace within the elements of
the arrays should be considered significant when making the comparison.
The default is that all whitespace is significant. The alternative is for
all consecutive white space characters to be converted to a single space
for the pruposes of the comparison. Again, this can be turned on when
creating a comparator object:

     my $comp = Array::Compare->new(WhiteSpace => 0);

   or by altering an existing object:

     $comp->WhiteSpace(0);

   You can also control whether or not the case of the data is significant
in the comparison. The default is that the case of data is taken into
account. This can be changed in the standard ways when creating a new
comparator object:

     my $comp = Array::Compare->new(Case => 0);

   or by altering an existing object:

     $comp->Case(0);

   In addition to the simple comparison described above (which returns true
if the arrays are the same and false if they're different) there is also a
full comparison which returns a list of elements which are different.  If
the arrays are the same it returns an empty list. In scalar context the
full comparison returns the length of this list (i.e. the number of
elements that differ). You can access the full comparision in two ways.
Firstly, there is a `DefFull' attribute. If this is `true' then a full
comparison if carried out whenever the compare method is called.

     my $comp = Array::Compare->new(DefFull => 1);
     $comp->compare(\@arr1, \@arr2); # Full comparison

     $comp->DefFull(0);
     $comp->compare(\@arr1, \@arr2); # Simple comparison

     $comp->DefFull(1);
     $comp->compare(\@arr1, \@arr2); # Full comparison again

   Secondly, you can access the full comparison method directly

     $comp->full_compare(\@arr1, \@arr2);

   For symmetry, there is also a direct method to use to call the simple
comparison.

     $comp->simple_compare(\@arr1, \@arr2);

   The final complication is the ability to skip elements in the
comparison.  If you know that two arrays will always differ in a
particular element but want to compare the arrays *ignoring* this element,
you can do it with Array::Compare without taking array slices. To do this,
a comparator object has an optional attribute called Skip which is a
reference to a hash. The keys in this hash are the indexes of the array
elements and the values should be any true value for elements that should
be skipped.

   For example, if you want to compare two arrays, ignoring the values in
elements two and four, you can do something like this:

     my %skip = (2 => 1, 4 => 1);
     my @a = (0, 1, 2, 3, 4, 5);
     my @b = (0, 1, X, 3, X, 5);

     my $comp = Array::Compare->new(Skip => \%skip);

     $comp->compare(\@a, \@b);

   This should return *true*, as we are explicitly ignoring the columns
which differ.

   Of course, having created a comparator object with no skip hash, it is
possible to add one later:

     $comp->Skip({1 => 1, 2 => 1});

   or:

     my %skip = (1 => 1, 2 => 2);
     $comp->Skip(\%skip);

   To reset the comparator so that no longer skips elements, set the skip
hash to an empty hash.

     $comp->Skip({});

   You can also check to see if one array is a permutation of another, i.e.
they contain the same elements but in a different order.

     if ($comp->perm(\@a, \@b) {
       print "Arrays are perms\n";
     else {
       print "Nope. Arrays are completely different\n";
     }

   In this case the values of `WhiteSpace' and Case are still used, but
Skip is ignored for, hopefully, obvious reasons.

AUTHOR
======

   Dave Cross <dave@mag-sol.com>

SEE ALSO
========

   perl(1).

Lazily tie files to arrays for reading
**************************************

NAME
====

   Array::FileReader - Lazily tie files to arrays for reading

SYNOPSIS
========

     use Array::FileReader;
     tie @foo, Array::FileReader, "some.file";
     print $foo[30];

DESCRIPTION
===========

   Plenty of times I've wanted to run up and down a file like this:

     @foo = <FILE>;
     for (0..100) {
         print $foo[$_];
     }
     print $foo[10], $foo[20], $foo[30];

   Of course, this is hugely inefficient since you have to load the entire
file into an array in memory. Array::FileReader removes the inefficiency
by only storing the line offsets in memory, and only discovering the line
offsets when a line is called for. For instance, `$foo[4]' will only load
4 numbers into memory, and then `$foo[30]' will load another 26.

   Because the file offsets are discovered when needed, there's no good way
of getting the size of the file - you just have to pad through them all,
which is slow.

   The module was designed to speed up Mark-Jason Dominus'
`Algorithm::Diff|Algorithm::Diff' in this node module when finding
differences between two very large files. In fact, it makes things less
efficient, since the first thing that module does is find the size of the
arrays.  It just goes to show, doesn't it?

AUTHOR
======

   Simon Cozens, <simon@cpan.org>

SEE ALSO
========

   See Algorithm/Diff, Tie/MmapArray,

a Module for handling arrays using IntSpan techniques
*****************************************************

NAME
====

   Array::IntSpan - a Module for handling arrays using IntSpan techniques

SYNOPSIS
========

     use Array::IntSpan;

     my $foo = Array::IntSpan->new([0, 59, 'F'], [60, 69, 'D'], [80, 89, 'B']);

     print "A score of 84% results in a ".$foo->lookup(84).".\n";
     unless (defined($foo->lookup(70))) {
       print "The grade for the score 70% is currently undefined.\n";
     }

     $foo->set_range(70, 79, 'C');
     print "A score of 75% now results in a ".$foo->lookup(75).".\n";

     $foo->set_range(0, 59, undef);
     unless (defined($foo->lookup(40))) {
       print "The grade for the score 40% is now undefined.\n";
     }

     $foo->set_range(87, 89, 'B+');
     $foo->set_range(85, 100, 'A');
     $foo->set_range(100, 1_000_000, 'A+');

DESCRIPTION
===========

   `Array::IntSpan' brings the speed advantages of `Set::IntSpan' (written
by Steven McDougall) to arrays.  Uses include manipulating grades, routing
tables, or any other situation where you have mutually exclusive ranges of
integers that map to given values.

   `Array::IntSpan::IP' is also provided with the distribution.  It lets
you use IP addresses in any of three forms (dotted decimal, network
string, and integer) for the indices into the array.  See the POD for that
module for more information.

Installation instructions
-------------------------

   Standard `Make::Maker' approach or just copy `Array/IntSpan.pm' into
`site/lib/Array/IntSpan.pm' and `Array/IntSpan/IP.pm' into
`site/lib/Array/IntSpan/IP.pm'.

METHODS
=======

new
---

   The new method takes an optional list of array elements.  The elements
should be in the form `[start_index, end_index, value]'.  They should be
in sorted order and there should be no overlaps.  The internal method
`_check_structure' will be called to verify the data is correct.  If you
wish to avoid the performance penalties of checking the structure, you can
use Data::Dumper to dump an object and use that code to reconstitute it.

set_range
---------

   This method takes three parameters - the `start_index', the
`end_index', and the value.  If you wish to erase a range, specify undef
for the value.  It properly deals with overlapping ranges and will replace
existing data as appropriate.  If the new range lies after the last
existing range, the method will execute in O(1) time.  If the new range
lies within the existing ranges, the method executes in O(n) time, where n
is the number of ranges.  The code is not completely optimized and will
make up to three calls to splice if the new range intersects with existing
ranges.  It does not consolidate contiguous ranges that have the same
value.

   If you have a large number of inserts to do, it would be beneficial to
sort them first.  Sorting is O(n lg(n)), and since appending is O(1), that
will be considerably faster than the O(n^2) time for inserting n unsorted
elements.

   The method returns 0 if there were no overlapping ranges and 1 if there
were.

lookup
------

   This method takes as a single parameter the index to look up.  If there
is an appropriate range, the method will return the associated value.
Otherwise, it returns undef.

AUTHOR
======

   Toby Everett, teverett@alascom.att.com

a Module for arrays using IP addresses as indices
*************************************************

NAME
====

   Array::IntSpan::IP - a Module for arrays using IP addresses as indices

SYNOPSIS
========

     use Array::IntSpan::IP;

     my $foo = Array::IntSpan::IP->new(['123.45.67.0',   '123.45.67.255', 'Network 1'],
                                       ['123.45.68.0',   '123.45.68.127', 'Network 2'],
                                       ['123.45.68.128', '123.45.68.255', 'Network 3']);

     print "The address 123.45.68.37 is on network ".$foo->lookup("\173\105\150\45").".\n";
     unless (defined($foo->lookup(((123*256+45)*256+65)*256+67))) {
       print "The address 123.45.65.67 is not on a known network.\n";
     }

     print "The address 123.45.68.177 is on network ".$foo->lookup("123.45.68.177").".\n";

     $foo->set_range('123.45.68.128', '123.45.68.255', 'Network 4');
     print "The address 123.45.68.177 is now on network ".$foo->lookup("123.45.68.177").".\n";

DESCRIPTION
===========

   `Array::IntSpan::IP' brings the advantages of `Array::IntSpan' to IP
address indices.  Anywhere you use an index in `Array::IntSpan', you can
use an IP address in one of three forms in `Array::IntSpan::IP'.  The
three accepted forms are:

Dotted decimal
     This is the standard human-readable format for IP addresses.  The
     conversion checks that the octets are in the range 0-255.  Example:
     `'123.45.67.89''.

Network string
     A four character string representing the octets in network order.
     Example: `"\173\105\150\131"'.

Integer
     A integer value representing the IP address. Example:
     `((123*256+45)*256+67)*256+89' or `2066563929'.

   Note that the algorithm has no way of distinguishing between the
integer values 1000 through 9999 and the network string format.  It will
presume network string format in these instances.  For instance, the
integer `1234' (representing the address `'0.0.4.210'') will be
interpreted as `"\61\62\63\64"', or the IP address `'49.50.51.52''.  This
is unavoidable since Perl does not strongly type integers and strings
separately and there is no other information available to distinguish
between the two in this situation.  I do not expect that this will be a
problem in most situations. Most users will probably use dotted decimal or
network string notations, and even if they do use the integer notation the
likelyhood that they will be using the addresses `'0.0.3.232'' through
`'0.0.39.15'' as indices is relatively low.

METHODS
=======

ip_as_int
---------

   The class method `Array::IntSpan::IP::ip_as_int' takes as its one
parameter the IP address in one of the three formats mentioned above and
returns the integer notation.

AUTHOR
======

   Toby Everett, teverett@alascom.att.com

Lookup strings in arrays or hash tables with abbreviation.
**********************************************************

NAME
====

   *Array::Lookup* - Lookup strings in arrays or hash tables with
abbreviation.

SYNOPSIS
========

     use Array::Lookup;

     $value = lookup $key, \@keywords, \&notfound, \&toomany;

     $value = lookup $key, \%keywords, \&notfound, \&toomany;

     lookup_error $key, $keywords, $err, $msg;

DESCRIPTION
===========

lookup
------

   Lookup `*$key*' in the table `*@keywords*' and return the unambiguously
matching keyword, if any.  If the second argument is given as a hash
array, `*%keywords*', then lookup a matching key, with abbreviation, and
return the value corresponding to the unambiguously matching key.

   If there are no matches, invoke `*&notfound*' like this:

     &$notfound( $key, \@keywords, '');

   If there are two or more matches, invoke `*&toomany*' like this:

     &$toomany( $key, \@keywords, \@matches);

   If either subroutine is omitted or null, then no special action is taken
except that undef is returned for the failed lookup.

   Note that the third argument, the array of ambiguous matches, allows a
common subroutine to be used for both error conditions and still
distinguish the error.

   See `"lookup_error"' in this node for a standard method of handling
lookup failures.

lookup_error
------------

   Handle an error for the `*lookup*' subroutine.  The arguments:

$key
     The search key which failed the lookup.

$keywords
     The hash or array reference containing the keywords none of which
     matched the $key.

$err
     A flag indicating if the lookup failed because of no matches at all
     ("), or if the lookup failed because of too many matches
     (`\@matches');

$msg
     A format string used to format and print the error message.  It should
     contain two printf substitution sequences: %s.  The first will be
     substituted with the failed lookup key; the second with one of the
     phrases: `"not found"' or `"is ambiguous"', depending upon `*$err*'.

     If `*$msg*' is omitted or null, a default message will be used:

          "lookup failed: %s %s; use one of:\n"

     followed by a listing of the strings in the `*$keywords*' array.

EXAMPLES
========

Using arrays
------------

     use Array::Lookup;
     ...
     @keywords = qw(quit find get set show);
     ...
     $command = <STDIN>;
     $command = lookup $command, \@keywords,
     	sub { lookup_error @_, "Unknown command '%s'; use one of:\n"; },
     	sub { lookup_error @_, "Command '%s' %s; use one of:\n"; };

Using hashes
------------

     use Array::Lookup;
     ...
     %Commands = ( 'quit' => \&quit,  'get' => \&get,  'set' => \&set,
     	          'find' => \&find,  'show' => \&show );
     ...
     $input = <STDIN>;
     $command_sub = lookup $input, \%Commands,
     	sub { lookup_error @_, "Unknown command '%s'; use one of:\n"; },
     	sub { lookup_error @_, "Command '%s' %s; use one of:\n"; };

SEE ALSO
========

   See Array/PrintCols,

AUTHOR
======

   Alan K. Stebbens <aks@sgi.com>

Print or format array elements in vertically sorted columns.
************************************************************

NAME
====

   print_cols, format_cols - Print or format array elements in vertically
sorted columns.

SYNOPSIS
========

   `use Array::PrintCols;'

   `print_cols \@*array*;'

   `print_cols \@*array*, $*colspec*;'

   `print_cols \@*array*, $*colspec*, $*total_width*;'

   `print_cols \@*array*, $*colspec*, $*total_width*, $indent;'

   $output = `format_cols' <same arguments as `print_cols'>;

   `$Array::PrintCols::PreSorted = 0;'

DESCRIPTION
===========

   This module exports two subroutine names: `print_cols' and
`format_cols'.

   The `print_cols' subroutine prints the items of `@*array*' in multiple,
alphabetically sorted vertical columns.  One, two, or three optional
arguments may be given to `print_cols' to control the width and number of
the columns, the total width of the output, and indentation.  Reasonable
defaults apply in the absence of the optional arguments (or when given as
the empty string or zero).  Generally, the minimum width column is used
when possible.

   If `$*colspec*' is given as a non-negative number, it is treated as the
minimum width of the column; the actual width will be the maximum of this
value and the lengths of all array items.

   If `$*colspec*' is given as a negative number, its absolute value value
is used to determine the total number of columns.  However, it cannot
exceed the total number of columns possible based on the maximum length of
all the array elements.

   If a third argument is supplied, it is used as the total width of the
output.  The default for this value is the value of the environment
variable `$ENV{'COLUMNS'}', if defined, or 80.

   If the fourth argument is given, it is used as the indent for all lines
printed, which subtracts from the total width of the output.  This value
defaults to zero (ie: no indention of the output).

   The variable `$Array::PrintCols::PreSorted' controls whether or not the
`print_cols' subroutine will expect its array argument to already be
sorted.  If this variable is nil or zero, `print_cols' will cause print
out a sorted copy of the input array.

   The routine `format_cols' is called exactly like `print_cols' but
returns the formatted result as a string, rather than printing it.

EXAMPLES
========

     use Array::PrintCols;

     @commands = sort qw( use list put get set quit help server );

     # print in three columns with an indention of 1.
     print_cols \@commands, -3, 0, 1;

     # print the formatted result data to the result file
     print RESULTFILE format_cols \@result_data;

AUTHOR
======

   Copyright (C) 1995-1998  Alan K. Stebbens <aks@sgi.com>

   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.

BUGS
====

   With Perl, you cannot default intervening arguments by leaving them
empty; you must supply a zero or empty-string (").

Set up array elements as aliases
********************************

NAME
====

   Array::RefElem - Set up array elements as aliases

SYNOPSIS
========

     use Array::RefElem qw(av_store av_push hv_store);

     av_store(@a, 1, $a);
     av_push(@a, $a);
     hv_store(%h, $key, $a);

DESCRIPTION
===========

   This module give direct access to some of the internal perl routines
that let you store things in arrays and hashes.  The following functions
are available:

av_store(@array, $index, $value)
     Stores $value inside @array at the indicated $index.  After this call
     $array[$index] and $value will denote the same thing.

av_push(@array, $value)
     Push $value onto the @array.  After this call $array[-1] and $value
     will denote the same thing.

hv_store(%hash, $key, $value);
     Store $value in the %hash with the given $key. After this call
     $hash{$key} and $value will denote the same thing.

SEE ALSO
========

   See Perlguts (perl.info),

COPYRIGHT
=========

   Copyright 2000 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Convert an array into N-sized array of arrays
*********************************************

NAME
====

   Array::Reform - Convert an array into N-sized array of arrays

SYNOPSIS
========

     use Array::Reform;

     @sample = ( 1 .. 10 );
     $rowsize = 3;

     Array::Reform->reform( $rowsize, \@sample );
         =>
            (
               [              1,              2,              3            ],
               [              4,              5,              6            ],
               [              7,              8,              9            ],
               [              10            ]
             );

DESCRIPTION
===========

   Ever had a list of things you needed to neetly format into a set of
HTML table rows? Well, look no further my friend. For the low, low price
of 0.00 you too can reform you data into a neet set of lists and produce
tables from it.

AUTHOR
======

   lhoward at www.perlmonks.org wrote this. I merely uploaded it. many
thanks to adam and swiftone for their solutions (also on Perl Monks).  A
bit of rewriting and some error checking done by crystalflame, also on
Perl Monks.

SEE ALSO
========

   http://www.perlmonks.org -- quick answers to your Perl questions.

Tie class for a simple ASCII database
*************************************

NAME
====

   AsciiDB::TagFile - Tie class for a simple ASCII database

SYNOPSIS
========

     # Bind the hash to the class
     $tieObj = tie %hash, 'AsciiDB::TagFile',
            DIRECTORY => $directory,
            SUFIX => $sufix,
     	LOCK => $bool,
     	READONLY => $bool,
     	CACHESIZE => $cacheSize,
     	FILEMODE => $mode,
            SCHEMA => {
     		ORDER => $arrayRef
     		KEY => {
     			ENCODE => $subRef,
     			DECODE => $subRef
     		}
     	};

     # Save to disk all changed records
     $tieObj->sync();

     # Remove all records from memory (and save them if needed)
     $tieObj->purge();

     # Remove all records from memory (and save them if needed)
     #	iif there are more than $cacheSize records in memory
     $tieObj->purge($cacheSize);

     # Get all record keys
     @array = keys %hash;

     # Check if a record exists
     exists $hash{$recordKey}

     # Get a field
     $scalar = $hash{$recordKey}{$fieldName};

     # Assign to a field
     $hash{$recordKey}{$fieldName} = $value;

DESCRIPTION
===========

   The *AsciiDB::TagFile* provides a hash-table-like interface to a simple
ASCII database.

   The ASCII database stores each record in into a file:

     $directory/recordKey1$sufix
     $directory/recordKey2$sufix
     ...
     $directory/recordKeyI<N>$sufix

   And a record has this format:

     [fieldName1]: value1
     [fieldName2]: value2
     ...
     [fieldNameI<N>]: value2

   After you've tied the hash you can access this database as access a
hash of hashes:

     $hash{recordKey1}{fieldName1} = ...

   To bind the %hash to the class AsciiDB::TagFile you have to use the tie
function:

     tie %hash, 'AsciiDB::TagFile', PARAM1 => $param1, ...;

   The parameters are:

DIRECTORY
     The directory where the records will be stored or readed from.  The
     default value is the current directory.

SUFIX
     The records are stored as files. The file name of a record is the key
     plus this sufix (if supplied).

     For example, if the record with key 'josear' and sufix '.record', will
     be stored into file: 'josear.record'.

     If this parameter is not supplied the records won't have a sufix.

LOCK
     If you set this parameter to 1 TagFile will perform basic locking.
     Record files will be share locked before reading them, and exclusive
     locked when syncing (writing) them.

     This basic locking only guarantees that a record file is always
     written correctly, but as TagFile keep records in memory you can
     still suffer consistency problems reading fields.

     The default value is 0, i.e. the database won't be locked.

READONLY
     If you set this parameter to 1 the database will be read only and all
     changes will be discarted.

     The default value is 0, i.e. the database can be changed.

CACHESIZE
     Records loaded from disk (or simply created) are keeped in memory till
     the tied hash is deleted. You can limit the number of records in
     memory setting this option to a value ($cacheSize).

     All records are purged from memory if their count reach $cacheSize.

     You can purge the records manually using the purge() method.

     Of course, the $caseSize should be a positive number, and you can use
     the 0 value to turn off the caching (useful when testing).

     The default value for CACHESIZE is 'infinite' (more or less...)

FILEMODE
     Filemode assigned to new created files.

     If this parameter is not supplied the new created files will have the
     default permissions.

SCHEMA
     This parameter is a hash reference that contains the database
     definition.

     With ORDER you can specify in which order fields will be saved into
     the file.

     For example,

          SCHEMA => {
          	ORDER => [ 'fieldHi', 'field2There', 'fieldWorld' ]
          }

     will save the record this way:

          [fieldHi]: ...
          [fieldThere]: ...
          [fieldWorld]: ...

     NOTE: this parameter is MANDATORY, and you have to specify all the
     fields. *If you forget to list a field it will not be saved*.

     With KEY,ENCODE and KEY,DECODE you can define an special encoding for
     keys when used as filenames.

     For example, if using this SCHEMA:

          SCHEMA => {
                  ORDER => ['a', 'b', 'c'],
                  KEY => {
                          ENCODE => sub { $_[0] =~ s{/}{_SLASH_}g; $_[0] },
                          DECODE => sub { $_[0] =~ s{_SLASH_}{/}g; $_[0] },
                  }
          }

     a record with the key 's1/s2' will be saved into filename
     's1_SLASH_s2'.  The DECODE subroutine is used to traslate back to the
     original key.

     NOTE: You should use this feature if you allow filesystem
     metacharacters (as '/', used in Unix to split path components) in
     your keys.

   The data will be saved to disk when the hash is destroyed (and garbage
collected by perl), so if you need for safety to write the updated data
you can call the sync method to do it.

EXAMPLES
========

     $dbObj = tie %tietag, 'AsciiDB::TagFile',
            DIRECTORY => 'data',
            SUFIX => '.tfr',
            FILEMODE => 0644,
            SCHEMA => { ORDER => ['name', 'address'] };

     $tietag{'jose'}{'name'} = 'Jose A. Rodriguez';
     $tietag{'jose'}{'address'} = 'Granollers, Barcelona, SPAIN';
     $tietag{'cindy'}{'name'} = 'Cindy Crawford';
     $tietag{'cindy'}{'address'} = 'YouBetIwouldLikeToKnowIt';

     my $key;
     foreach $key (keys %tietag) {
     	print $tietag{$key}{'name'}, "\t", $tietag{$key}{'address'},
     		"\n";
     }

Astronomical coordinate transformations
***************************************

NAME
====

   Astro::Coord - Astronomical coordinate transformations

SYNOPSIS
========

     use Astro::Coord;

     ($l, $b) = fk4gal($ra, $dec);
     ($az, $el) = eqazel($ha, $dec, $latitude);

DESCRIPTION
===========

   Astro::Coord contains an assorted set Perl routines for coordinate
conversions, such as hour angle to elevation and J2000 to B1950.

AUTHOR
======

   Chris Phillips  phillips@jive.nfra.nl

FUNCTIONS
=========

pol2r
          ($x, $y, $z) = pol2r($polar1, $polar2);

          Converts a position in polar coordinates into rectangular coordinates
            $polar1, $polar2   The polar coordinates to convert (turns)
            $x, $y, $z         The rectangular coordinates

r2pol
          ($polar1, $polar2) = r2pol($x, $y, $z);

          Converts a position in rectangular coordinates into polar coordinates
            $x, $y, $y         The rectangular coordinates to convert
            $polar1, $polar2   The polar coordinates (turns);
          Returns undef if too few or too many arguments are passed.

xy2azel
          ($az, $el) = xy2azel($x, $y);

          Converts a telescope position in X,Y coordinates into Az,El coordinates
            $x, $y     The X and Y coordinates (turns)
            $az, $el    The azimuth and elevation (turns)

azel2xy
          ($x, $y) = azel2xy($az, $el);

          Converts a position in Az,El coordinates into X,Y coordinates
            $az, $el    The azimuth and elevation (turns)
            $x, $y      The X and Y coordinate (turns)

eqazel
          ($ha, $dec) = eqazel($az, $el, $latitude);
          ($az, $el) = eqazel($ha, $dec, $latitude);

          Converts HA/Dec coordinates to Az/El and vice versa.
            $ha, $dec     Hour angle and declination of source (turns)
            $az, $el      Azimuth and elevation of source (turns)
            $latitude     Latitude of the observatory (turns)
          Note:
           The ha,dec and az,el conversion is symmetrical

fk4fk5r
          @fk5 = fk4fk5r(@fk4);

          Converts an FK4 (B1950) position to the equivalent FK5 (J2000) position.
          Note: Convert equitoral positions to/from 3-vectors using pol2r and r2pol.
            @fk4       fk4 position (as a 3-vector, turns)
            @fk5       fk5 position (as a 3-vector, turns)

          Returns undef if too few or two many arguments are passed.

fk5fk4r
          @fk4 = fk5fk4r(@fk5);

          Converts an FK5 (J2000) position to the equivalent FK4 (B1950) position.
          Note: Convert equitoral positions to/from 3-vectors using pol2r and r2pol.
            @fk5     fk5 position (as a 3-vector, turns)
            @fk4     fk4 position (as a  3-vector, turns)

fk4galr
          @gal = fk4galr(@fk4)

          Converts an FK4 position (B1950.0) to the IAU 1958 Galactic
          coordinate system
          Note: convert equitoral positions to/from 3-vectors using pol2r and r2pol.
            @fk4     fk4 position to convert (as a 3-vector, turns)
            @gal     Galactic position (as a 3-vector, turns)
          Returns undef if too few or two many arguments are passed.
          Reference : Blaauw et al., 1960, MNRAS, 121, 123.

galfk4r
          @fk4 = galfk4r(@gal)

          Converts an IAU 1958 Galactic position to the FK4 coordinate system (B1950)
          Notes: Convert equitoral positions to/from 3-vectors using pol2r and r2pol.
            @gal      Galactic position (as a 3-vector, turns)
            @fk4      fk4 position (as a  3-vector, turns)
          Returns undef if too few or two many arguments are passed.
          Reference : Blaauw et al., 1960, MNRAS, 121, 123.

fk4fk5
          ($JRA, $JDec) = fk4fk5($BRA, $BDec);

          Converts an FK4 (B1950) position to the equivalent FK5 (J2000) position.
            **LOW PRECISION**
            $BRA,$BDec     fk4/B1950 position (turns)
            $JRA,$Dec      fk5/J2000 position (turns)

fk5fk4
          ($BRA, $BDec) = fk5fk4($JRA, $JDec);

          Converts an FK5 (J2000) position to the equivalent FK4 (B1950) position.
            **LOW PRECISION**
            $JRA,$Dec      fk5/J2000 position (turns)
            $BRA,$BDec     fk4/B1950 position (turns)

fk4gal
          ($l, $b) = fk4gal($ra, $dec);

          Converts an FK4 position (B1950) to the IAU 1958 Galactic
          coordinate system
            ($ra, $dec)  fk4 position to convert (turns)
            ($l, $b)     Galactic position (turns)
          Reference : Blaauw et al., 1960, MNRAS, 121, 123.

galfk4
          ($ra, $dec) = galfk4($l, $b);

          Converts an IAU 1958 Galactic coordinate system position
          to FK4  (B1950).
            ($l, $b)    Galactic position (turns)
           ($ra, $dec)  fk4 position to convert (turns)
           Reference : Blaauw et al., 1960, MNRAS, 121, 123.

ephem_vars
          ($omega, $rma, $mlanom, $F, $D, $eps0) = ephem_vars($jd)

          Given the Julian day ($jd) this routine calculates the ephemeris
          values required by the prcmat and nutate routines

          The returned values are :
            $omega  - Longitude of the ascending node of the Moons mean orbit on
                      the ecliptic, measured from the mean equinox of date.
            $rma    - Mean anomaly of the Sun.
            $mlanom - Mean anomaly of the Moon.
            $F      - L - omega, where L is the mean longitude of the Moon.
            $D      - Mean elongation of the Moon from the Sun.
            $eps0   - Mean obilquity of the ecliptic.

nutate
          ($deps, $dpsi, @nu) = nutate($omega, $F, $D, $rma, $mlanom, $eps0);

          To calculate the nutation in longitude and obliquity according to
          the 1980 IAU Theory of Nutation including terms with amplitudes
          greater than 0.01 arcsecond.  The nutation matrix is used to
          compute true place from mean place: true vector = N x mean place
          vector where the three components of each vector are the direction
          cosines wrt the mean equinox and equator.

          /   1          -dpsi.cos(eps)    -dpsi.sin(eps)  \
                |                                                  |
            N = |  dpsi.cos(eps)      1               -deps        |
                |                                                  |
          \ dpsi.sin(eps)    deps                 1        /

          The required inputs are : (NOTE: these are the values returned by ephem_vars)
            $omega  - Longitude of the ascending node of the Moons mean orbit on
                      the ecliptic, measured from the mean equinox of date.
            $rma    - Mean anomaly of the Sun.
            $mlanom - Mean anomaly of the Moon.
            $F      - L - omega, where L is the mean longitude of the Moon.
            $D      - Mean elongation of the Moon from the Sun.
            $eps0   - Mean obilquity of the ecliptic.

          The returned values are :
            $deps - nutation in obliquity
            $dpsi - nutation in longitude (scalar)
            @nu   - nutation matrix (array [3][3])

precsn
          @gp = precsn($jd_start, $jd_stop);

          To calculate the precession matrix P for dates AFTER 1984.0 (JD =
          2445700.5) Given the position of an object referred to the equator
          and equinox of the epoch $jd_start its position referred to the
          equator and equinox of epoch $jd_stop can be calculated as follows :

          1) Express the position as a direction cosine 3-vector (V1)
             (use pol2r to do this).
          2) The corresponding vector V2 for epoch jd_end is V2 = P.V1

          The required inputs are :
            $jd_start - The Julian day of the current epoch of the coordinates.
            $jd_end   - The Julian day at the required epoch for the conversion.

          The returned values are :
            @gp - The required precession matrix (array [3][3])

coord_convert
          ($output_left, $output_right) = coord_convert($input_left, $input_right,
                                                        $input_mode, $output_mode,
                                                        $mjd, $longitude, $latitude,
          						$ref0);

          A routine for converting between any of the following coordinate systems :
                Coordinate system                               input/output mode
                -----------------                               -----------------
            X, Y (East-West mounted)                                    0
            Azimuth, Elevation                                          1
            Hour Angle, Declination                                     2
            Right Ascension, Declination (date, J2000 or B1950)       3,4,5
            Galactic (B1950)                                            6

          The last four parameters in the call ($mjd, $longitude, $latitude
          and $ref0) are not always required for the coordinate conversion.
          In particular if the conversion is between two coordinate systems
          which are fixed with respect to the celestial sphere (RA/Dec J2000,
          B1950 or Galactic), or two coordinate systems which are fixed with
          respect to the antenna (X/Y and Az/El) then these parameters are not
          used (NOTE: they must always be passed, even if they only hold 0 or
          undef as the routine will return undef if it is not passed 8
          parameters).  The RA/Dec date system is defined with respect to the
          celestial sphere, but varies with time.  The table below shows which
          of $mjd, $longitude, $latitude and $ref0 are used for a given
          conversion.  If in doubt you should determing the correct values for
          all input parameters, no checking is done in the routine that the
          passed values are sensible.

          Conversion                 $mjd $longitude $latitude $ref0
            ------------------------------------------------------------------------
            Galactic,             Galactic,
            RA/Dec J2000,B1950 <->RA/Dec J2000, B1950  N       N         N       N

          Galactic,
          RA/Dec J2000,B1950 <->RA/Dec date          Y       N         N       N

          Galactic,
          RA/Dec J2000,B1950,<->HA/Dec               Y       Y         N       N
          date

          Galactic,
          RA/Dec J2000,B1950,<->X/Y, Az/El           Y       Y         Y       Y
          date

          X/Y, Az/El         <->X/Y, Az/El           N       N         N       N

          X/Y, Az/El         <->HA/Dec               N       N         Y       Y

          NOTE :  The method used for refraction correction is asymptotic at
          	  an elevation of 0 degrees.

          The required inputs are :
            $input_left   - The left/longitude input coordinate (turns)
            $input_right  - The right/latitude input coordinate (turns)
            $input_mode   - The mode of the input coordinates (0-6)
            $output_mode  - The mode to convert the coordinates to.
            $mjd          - The time as modified Julian day (if necessary) at
                            which to perform the conversion
            $longitude    - The longitude of the location/observatory (if necessary)
                            at which to perform the conversion (turns)
            $latitude     - The latitude of the location/observatory (if necessary)
                            at which to perform the conversion (turns)
            $ref0         - The refraction constant (if in doubt use 0.00005).

          The returned values are :
            $output_left  - The left/longitude output coordinate (turns)
            $output_right - The right/latitude output coordinate (turns)

haset_ewxy
          $haset = haset_ewxy($declination, $latitude, %limits);

          This routine takes the $declination of the source, and the $latitude of the
          EWXY mounted antenna and calculates the hour angle at which the source
          will set.  It is then trivial to calculate the time until the source
          sets, simply by subtracting the current hour angle of the source from
          the hour angle at which it sets.

          The required inputs are :
            $declination - The declination of the source (turns)
            $latitude    - The latitude of the observatory (turns)
            %limits     - A reference to a hash holding the EWXY antenna limits
                           The following keys must be defined XLOW, XLOW_KEYHOLE,
          		   XHIGH, XHIGH_KEYHOLE, YLOW, YLOW_KEYHOLE, YHIGH,
          		   YHIGH_KEYHOLE (all values shoule be in turns)

          The returned value is :
            $haset       - The hour angle (turns) at which a source at this
                           declination sets for an EWXY mounted antenna with the
                           given limits at the given latitude

          NOTE: returns undef if %limits hash is missing any of the required keys

ewxy_tlos
          $tlos = ewxy_tlos($hour_angle, $declination, $latitude, %limits);

          This routine calculates the time left on-source (tlos) for a source
          at $hour_angle, $declination for an EWXY mount antenna at $latitude.

          The required inputs are :
            $hour_angle  - The current hour angle of the source (turns)
            $declination - The declination of the source (turns)
            $latitude    - The latitude of the observatory (turns)
            \%limits     - A reference to a hash holding the EWXY antenna limits
                           The following keys must be defined XLOW, XLOW_KEYHOLE,
          		   XHIGH, XHIGH_KEYHOLE, YLOW, YLOW_KEYHOLE, YHIGH,
          		   YHIGH_KEYHOLE (all values should be in turns)

          The returned value is :
            $tlos        - The time left on-source (turns)

haset_azel
          $haset = haset_azel($declination, $latitude, %limits);

          This routine takes the $declination of the source, and the
          $latitude of the Az/El mounted antenna and calculates the hour
          angle at which the source will set.  It is then trivial to
          calculate the time until the source sets, simply by subtracting the
          current hour angle of the source from the hour angle at which it
          sets.  This routine assumes that the antenna is able to rotate
          through 360 degrees in azimuth.

          The required inputs are :
            $declination - The declination of the source (turns)
            $latitude    - The latitude of the observatory (turns)
            \%limits     - A reference to a hash holding the Az/El antenna limits
                           The following keys must be defined ELLOW (all values should
                           be in turns)

          The returned value is :
            $haset       - The hour angle (turns) at which a source at this
                           declination sets for an Az/El mounted antenna with the
                           given limits at the given latitude

          NOTE: returns undef if the %limits hash is missing any of the required keys

azel_tlos
          $tlos = azel_tlos($hour_angle, $declination, $latitude, \%limits);

          This routine calculates the time left on-source (tlos) for a source
          at $hour_angle, $declination for an Az/El mount antenna at $latitude.

          The required inputs are :
            $hour_angle  - The current hour angle of the source (turns)
            $declination - The declination of the source (turns)
            $latitude    - The latitude of the observatory (turns)
            %limits     - A reference to a hash holding the Az/El antenna limits
                           The following keys must be defined ELLOW (all values
                           should be in turns)

          The returned value is :
            $tlos        - The time left on-source (turns)

antenna_rise
          $ha_set = antenna_rise($declination, $latitude, $mount, \%limits);

          Given the $declination of the source, the $latitude of the antenna,
          the type of the antenna $mount and a reference to a hash holding
          information on the antenna limits, this routine calculates the hour
          angle at which the source sets for the antenna.  The hour angle at
          which it rises is simply the negative of that at which it sets.
          These values in turn can be used to calculate the LMST at which the
          source rises/sets and from that the UT at which the source
          rises/sets on a given day, or to calculate the native coordinates
          at which the source rises/sets.

          If you want to calculate source rise times above arbitrary elevation,
          use the routine rise.

          The required inputs are :
            $declination - The declination of the source (turns)
            $latitude    - The latitude of the observatory (turns)
            $mount       - The type of antenna mount, 0 => EWXY mount, 1 => Az/El,
                           any other number will cause the routine to return
          	           undef
            %limits     - A reference to a hash holding the antenna limits
                           For an EWXY antenna there must be keys for all the
                           limits (i.e.  XLOW, XLOW_KEYHOLE, XHIGH, XHIGH_KEYHOLE,
                           YLOW, YLOW_KEYHOLE, YHIGH, YHIGH_KEYHOLE).  For an Az/El
          	           antenna there must be a key for ELLOW (all values should
                           be in turns).

          The returned values are :
            $ha_set  - The hour angle at which the source sets (turns).  The hour
                       angle at which the source rises is simply the negative of this
                       value.

Miscellaneous astronomical routines
***********************************

NAME
====

   Astro::Misc - Miscellaneous astronomical routines

SYNOPSIS
========

     use Astro::Misc;

     $U = calc_U($flux, $dist, $freq);
     ($dist1, $dist2)= kindist($ra, $dec, $vel, $epoch, $model);

DESCRIPTION
===========

   Astro::Misc contains an assorted set Perl routines for doing various
astronomical calculations.

AUTHOR
======

   Chris Phillips  phillips@jive.nfra.nl

FUNCTIONS
=========

read_possm
          Read_possm interprets the output file from the AIPS POSSM task.
          the task may be called repeatably if there is more than one POSSM
          output in the file. The file must be open before calling
          read_possm, using the FileHandle module. The data from the possm
          plot is returned in a hash. Some of the header values are returned
          as scalar values while the actual plot values are returned as
          references to arrays. The scalar values returned are:
            SOURCE, DATE, BANDWIDTH, TYPE (='A&P'||'R&I')
          The array references are: CHANNEL,
            VELOCITY, FREQUENCY, AMPLITUDE, PHASE, ANTENNA
          The global variable $Astro::Misc:oldpossm (default=0) controls whether
          old or new style possm plots are read.  For oldpossm=1, one of
          VELOCITY or FREQUENCY will be a reference to an empty list (but the
          hash value IS defined).

          Usage:    use FileHandle
                    my $fh = FileHandle->new();
                    my %ahash = ();
                    open($fh, 'possmfile');
                    read_possm($fh, %ahash);

          Returns:  0 on success (but not hit eof)
                    1 on success (and hit eof)
                    2 on premature eof

          Examples of hash usage:
               $hash{SOURCE}         # Source name
               @{$hash{VELOCITY}}    # Array of velocity values
               ${$hash{PHASE}}[4]    # The fifth phase value

read_lovas
          Read_lovas read the Lovas "Recommended Rest Frequencies for Observed
          Interstellar Molecular Microwave Transitions - 1991 Revision"
          (J. Phys. Chem. Ref. Data, 21, 181-272, 1992). Alpha quality!!

          my @lovas = read_lovas($fname);
          my @lovas = read_lovas($fname, $minfreq, $maxfreq);

calc_U
          $U = calc_U($flux, $dist, $freq);

          Calculate U (Excitation Parameter) for an UCHII region
          Based on Eqn 8 in Schraml and Mezger, 1969
            $flux        Integrated Source Flux Density (Jy)
            $dist        Distance to source (kpc)
            $freq        Frequency of observation
          Note:
           Uses the global variable $Astro::Misc::temp for electron temperature
           Default is 10000K

calc_Nl
          $Nl = calc_Nl($U);

          Calculate the Lyman continuum photon flux given U, the Excitation
          Parameter for an UCHII region
            $U is the Excitation Parameter (from calc_U)

lum2spectral
          $spectral_type = lum2spectral($luminosity);

          Calculate the spectral type of a ZAMS star from its luminosity
          Based on Panagia, 1973, ApJ, 78, 929.
            $luminosity   Star luminosity (normalised to Lsun)
          Returns undef if luminosity is out of range (O4 - B3)

Nl2spectral
          $spectral = Nl2spectral($Nl);

          Calculate the spectral type of a ZAMS star from its flux of
          Lyman Continuum Photons (Nl)
          Based on Panagia, 1973, ApJ, 78, 929
            $Nl     Flux of Lyman Continuum Photons
          Returns undef if luminosity is out of range (O4 - B3)

kindist
          ($dist1, $dist2)= kindist($ra, $dec, $vel, $epoch, $model);

          Calculate the kinematic distance to an object
            $dist1, $dist2  Near/Far distance (kpc)
            $ra             RA of object (turns)
            $dec            Dec of object (turns)
            $vel            LSR Velocity (km/s)
            $epoch          Epoch of coords (J2000/J/B1950/B)
            $model          Model to use (1 or 2)

          Note:
           Model 1 is based on Brand and Blitz, 1993, A&A, 275, 67-90.
           Model 2 has unknown origin.

Information about the phase of the moon
***************************************

NAME
====

   MoonPhase - Information about the phase of the moon

SYNOPSIS
========

   use MoonPhase;

     ( $MoonPhase,
       $MoonIllum,
       $MoonAge,
       $MoonDist,
       $MoonAng,
       $SunDist,
       $SunAng ) = phase($seconds_since_1970);

     @phases  = phasehunt($seconds_since_1970);

DESCRIPTION
===========

   MoonPhase calculates information about the phase of the moon at a given
time.

FUNCTIONS
=========

phase()
-------

     ( $MoonPhase,
       $MoonIllum,
       $MoonAge,
       $MoonDist,
       $MoonAng,
       $SunDist,
       $SunAng )  = phase($seconds_since_1970);

     $MoonPhase = phase($seconds_since_1970);

   The argument is the time for which the phase is requested, expressed as
a time returned by the time function. If `$seconds_since_1970' is omitted,
it does `phase(time)'.

   Return value in scalar context is $MoonPhase, the terminator phase
angle as a percentage of a full circle (i.e., 0 to 1).

*Return values in array context:*
$MoonPhase:
     the terminator phase angle as a percentage of a full circle (i.e., 0
     to 1)

$MoonIllum:
     the illuminated fraction of the Moon's disc

$MoonAge:
     the Moon's age in days and fraction

$MoonDist:
     the distance of the Moon from the centre of the Earth

$MoonAng:
     the angular diameter subtended by the Moon as seen by an observer at
     the centre of the Earth.

$SunDist:
     the distance from the Sun in km

$SunAng:
     the angular size of Sun in degrees

   Example:

     ( $MoonPhase,
       $MoonIllum,
       $MoonAge,
       $MoonDist,
       $MoonAng,
       $SunDist,
       $SunAng ) = phase();

     print "MoonPhase  = $MoonPhase\n";
     print "MoonIllum  = $MoonIllum\n";
     print "MoonAge    = $MoonAge\n";
     print "MoonDist   = $MoonDist\n";
     print "MoonAng    = $MoonAng\n";
     print "SunDist    = $SunDist\n";
     print "SunAng     = $SunAng\n";>

   could print something like this:

     MoonPhase  = 0.598939375319023
     MoonIllum  = 0.906458030827876
     MoonAge    = 17.6870323368022
     MoonDist   = 372479.357420033
     MoonAng    = 0.534682403555093
     SunDist    = 152078368.820205
     SunAng     = 0.524434538105092

phasehunt()
-----------

     @phases = phasehunt($seconds_since_1970);

   Finds time of phases of the moon which surround the given date.  Five
phases are found, starting and ending with the new moons which bound the
current lunation.

   The argument is the time, expressed as a time returned by the time
function. If `$seconds_since_1970' is omitted, it does `phasehunt(time)'.

   Example:

     @phases = phasehunt();
     print "New Moon      = ", scalar(localtime($phases[0])), "\n";
     print "First quarter = ", scalar(localtime($phases[1])), "\n";
     print "Full moon     = ", scalar(localtime($phases[2])), "\n";
     print "Last quarter  = ", scalar(localtime($phases[3])), "\n";
     print "New Moon      = ", scalar(localtime($phases[4])), "\n";

   could print something like this:

     New Moon      = Wed Jun 24 06:51:47 1998
     First quarter = Wed Jul  1 21:42:19 1998
     Full moon     = Thu Jul  9 19:02:47 1998
     Last quarter  = Thu Jul 16 18:15:18 1998
     New Moon      = Thu Jul 23 16:45:01 1998

ABOUT THE ALGORITHMS
====================

   The algorithms used in this program to calculate the positions of Sun
and Moon as seen from the Earth are given in the book *Practical Astronomy
With  Your  Calculator*  by  *Peter  Duffett-Smith,   Second   Edition,
Cambridge University Press, 1981*.  Ignore the word "Calculator" in the
title;  this  is  an  essential  reference  if  you're  interested  in
developing  software  which  calculates  planetary  positions, orbits,
eclipses, and  the  like.   If  you're  interested  in  pursuing  such
programming, you should also obtain:

   *Astronomical  Formulae for Calculators* by *Jean Meeus, Third Edition,
Willmann-Bell, 1985*.  A must-have.

   *Planetary  Programs  and  Tables  from  -4000  to  +2800*  by  *Pierre
Bretagnon  and Jean-Louis Simon, Willmann-Bell, 1986*.  If you want the
utmost  (outside  of  JPL)  accuracy  for  the  planets,  it's   here.

   *Celestial BASIC* by *Eric Burgess, Revised Edition, Sybex, 1985*.  Very
cookbook oriented, and many of the algorithms are hard to dig  out  of the
turgid BASIC code, but you'll probably want it anyway.

   Many of these references can be obtained from Willmann-Bell, P.O.  Box
35025,  Richmond,  VA 23235, USA.  Phone: (804) 320-7016.  In addition to
their own publications, they stock most of the standard  references for
mathematical and positional astronomy.

LICENCE
=======

   This  program is in the public domain: "Do what thou wilt shall be the
whole of the law".

AUTHORS
=======

   the moontool.c:

     A Moon for the Sun
     Release 2.0
     Designed and implemented by John Walker in December 1987,
     revised and updated in February of 1988.

   Perl transcription:

     Raino Pikkarainen, 1998
     raino.pikkarainen@saunalahti.fi

perl interface to SLAlib positional astronomy library
*****************************************************

NAME
====

   Astro::SLA - perl interface to SLAlib positional astronomy library

SYNOPSIS
========

     use SLA;
     use SLA qw(:constants :sla);

     slaFk45z($ra, $dec, 1950.0, $ra2000, $dec2000);
     slaCldj($yy, $mn, $dd, $mjd, $status);

     ($lst, $mjd) = lstnow($long);
     ($lst, $mjd) = ut2lst_tel($yy,$mn,$dd,$hh,$mm,$ss,'JCMT');

DESCRIPTION
===========

   This modules provides a perl interface to the C version of the SLALIB
astrometry library written by Pat Wallace.

   In general the single precision routines have not been implemented
since perl can work in double precision.

   The SLALIB constants (as provided in slamac.h) are available.

   In addition small utility subroutines are provided that do useful tasks
(from the author's point of view) - specifically routines for calculating
the Local Sidereal Time. It may be that this part of the module should be
moved into an accompanying module - Astro::SLA::Extras.

Routines
========

   There are 3 distinct groups of routines that can be imported into the
namespace via tags:

sla - import just the SLALIB routines
constants - import the SLALIB constants
funcs - import the extra routines
   Each group will be discussed in turn.

sla
---

   All the double precision SLA routines are implemented except for
slaPxy, slaDmat, slaSvd, slaSvdcov, slaSvdsol (I may do these some other
time - although they should be done in `PDL').

   The implemented routines are:

     sla524 slaAddet slaAfin slaAirmas slaAmp slaAmpqk slaAop
     slaAoppa slaAoppat slaAopqk slaAtmdsp slaAv2m slaBear
     slaCaf2r slaCaldj slaCalyd slaCc2s slaCc62s slaCd2tf
     slaCldj slaClyd slaCr2af slaCr2tf slaCs2c6 slaDaf2r
     slaDafin slaDat slaDav2m slaDbear slaDbjin slaDc62s
     slaDcc2s slaDcmpf slaDcs2c slaDd2tf slaDe2h slaDeuler
     slaDfltin slaDh2e slaDimxv slaDjcal slaDjcl slaDm2av
     slaDmoon slaDmxm slaDmxv slaDpav slaDr2af slaDr2tf
     slaDrange slaDranrm slaDs2c6 slaDs2tp slaDsep slaDtf2d
     slaDtf2r slaDtp2s slaDtp2v slaDtps2c slaDtpv2c slaDtt
     slaDv2tp slaDvdv slaDvn slaDvxv slaE2h slaEarth slaEcleq
     slaEcmat slaEcor slaEg50 slaEpb slaEpb2d slaEpco slaEpj
     slaEpj2d slaEqecl slaEqeqx slaEqgal slaEtrms slaEuler
     slaEvp slaFk425 slaFk45z slaFk54z slaFloatin slaGaleq
     slaGalsup slaGe50 slaGeoc slaGmst slaGmsta slaGresid slaH2e
     slaImxv slaInvf slaKbj slaM2av slaMap slaMappa slaMapqk
     slaMapqkz slaMoon slaMxm slaMxv slaNut slaNutc slaOap
     slaOapqk slaObs slaPa slaPav slaPcd slaPda2h slaPdq2h
     slaPlanel slaPlanet slaPlante slaPm slaPolmo slaPrebn
     slaPrec slaPreces slaPrecl slaPrenut slaPvobs slaRandom
     slaRange slaRanorm slaRcc slaRdplan slaRefco slaRefcoq
     slaRefv slaRefz slaRverot slaRvgalc slaRvlg slaRvlsrd
     slaRvlsrk slaS2tp slaSep slaSubet slaSupgal slaTp2s slaTp2v
     slaTps2c slaTpv2c slaUnpcd slaV2tp slaVdv slaVxv slaWait
     slaXy2xy slaZd

   Also, slaGresid and slaRandom are not in the C library (although they
are in the Fortran version).  slaWait is implemented using the perl
'select(ready file descriptors)' command.

   In general single precision routines are simply aliases of the double
precision equivalents.

   For more information on the SLALIB routines consult the Starlink
documentation (Starlink User Note 67 (SUN/67)). This document is available
from the Starlink web site (http://star-www.rl.ac.uk/) [SUN67 avialable
from: http://star-www.rl.ac.uk/cgi-bin/htxserver/sun67.htx/sun67.html]]

Constants
---------

   Constants supplied by this module (note that they are implemented via
the Constant, pragma):

DPI - Pi

D2PI - 2 * Pi

D1B2PI - 1 / (2 * Pi)

D4PI - 4 * Pi

D1B4PI - 1 / (4 * Pi)
DPISQ - Pi ** 2 (Pi squared)
DSQRPI - sqrt(Pi)

DPIBY2 - Pi / 2: 90 degrees in radians

DD2R - Pi / 180: degrees to radians

DR2D - 180/Pi:  radians to degrees

DAS2R - pi/(180*3600): arcseconds to radians

DR2AS - 180*3600/pi: radians to arcseconds

DH2R - pi/12: hours to radians

DR2H - 12/pi: radians to hours

DS2R - pi / (12*3600): seconds of time to radians

DR2S - 12*3600/pi: radians to seconds of time

D15B2PI - 15/(2*pi): hours to degrees * radians to turns
Extra functions (using the 'funcs' tag)
---------------------------------------

lstnow_tel
     Return current LST (in radians) and MJD for a given telescope.  The
     telescope identifiers should match those present in slaObs.  The
     supplied telescope name is converted to upper case.

          ($lst, $mjd) = lstnow_tel($tel);

     Aborts if telescope name is unknown.

lstnow
     Return current LST (in radians) and MJD (days) Longitude should be
     negative if degrees west and in radians.

          ($lst, $mjd) = lstnow($long);

ut2lst
     Given the UT time, calculate the Modified Julian date and the local
     sidereal time (radians) for the specified longitude.

          ($lst, $mjd) = ut2lst(yy, mn, dd, hh, mm, ss, long)

     Longitude should be negative if degrees west and in radians.

ut2lst_tel
     Given the UT time, calculate the Modified Julian date and the local
     sidereal time (radians) for the specified telescope.

          ($lst, $mjd) = ut2lst_tel(yy, mn, dd, hh, mm, ss, tel)

AUTHOR
======

   Tim Jenness (t.jenness@jach.hawaii.edu)

REQUIREMENTS
============

   This module has been tested with the May 1998 release of SLALIB.  The C
version of the library is required for this module to be built.

COPYRIGHT
=========

   This module is copyright (C) 1998,1999 Tim Jenness and PPARC.  All
rights reserved.  This program is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

   The SLALIB library (C version) is proprietary.  Please contact Patrick
Wallace (ptw@tpsoft.demon.co.uk) if you would like to obtain a copy.

Time based astronomical routines
********************************

NAME
====

   Astro::Time - Time based astronomical routines

SYNOPSIS
========

     use Astro::Time;

     $dayno = cal2dayno($day, $month, $year);
     print "It's a leap year!\n" if (leap($year));
     $lmst = mjd2lst($mjd, $longitude, $dUT1);
     $turns = str2turn($string, 'H');
     $str = turn2str($turn, 'D', $sig);

DESCRIPTION
===========

   Astro::Time contains an assorted set Perl routines for time based
conversions, such as conversion between calendar dates and Modified Julian
day and conversion of UT to local sidereal time. Include are routines for
conversion between numerical and string representation of angles.

AUTHOR
======

   Chris Phillips  phillips@jive.nfra.nl

FUNCTIONS
=========

turn2str
          $str = turn2str($turn, $mode, $sig);
          $str = turn2str($turn, $mode, $sig, $strsep);

          Convert fraction of a turn into string representation
            $turn   Angle in turns
            $mode   Mode of string to convert to:
                     'H' for hours
                     'D' for degrees
            $sig    number of significant figures
            $strsep String separator (override for default $Astro::Time::StrSep)
          Note:
          The behavior can be modified by the following two variables:
           $Astro::Time::ZeroStr   Minimum number of leading digits (zero padded
                                   if needed)
           $Astro::Time::StrSep    (Overridden by optional fourth argument)
             Deliminator used in string (Default ':')
             This may also equal one of a number of special values:
               'HMS'           12H45M12.3S or 170D34M56.2S
               'hms'           12h45m12.3s or 170d34m56.2s
               'deg'           170d34'56.2"

deg2str
          $str=deg2str($deg, $mode, $sig);

          Convert degrees into string representation
            $deg   angle in degrees
            $mode  mode of string to convert to:
                    'H' for hours
                    'D' for degrees
            $sig   number of significant figures
          See note for turn2str

rad2str
          $str=rad2str($rad, $mode, $sig);

          Convert radians into string representation
            $rad    angle in radians
            $mode   mode of string to convert to:
                     'H' for hours
                     'D' for degrees
            $sig is number of significant figures
          See note for turn2str

str2turn
          $turns = str2turn($string,$mode);

          Convert angle from string representation into fraction of a turn
            $string    a : or space delimited angle
            $mode      type of angle
                        'H' if $string is in hours,min,sec
                        'D' if $string is in deg,arcmin,arcsec
          The format of $string can be fairly flexible e.g.:
             12.2
             12:34
             12:34:45.1
            -23 34 12.3
            -34 34.3

          Note: You cannot mix spaces and :

str2deg
          $degrees=str2deg($string,$mode);

          Convert angle from string representation into degrees
            $string   a : or space delimited angle
            $mode     'H' if $string is in hours,min,sec
                      'D' if $string is in deg,arcmin,arcsec
          See note for str2turn

str2rad
          $radians=str2rad($string,$mode);

          Convert angle from string representation into radians
            $string   a : or space delimited angle
            $mode     'H' if $string is in hours,min,sec
                      'D' if $string is in deg,arcmin,arcsec
          See note for str2turn

hms2time
          ($time) = hms2time($hour, $minute, $second);
          ($time) = hms2time($hour, $minute, $second, $mode);

          Returns the day fraction given hours minutes and seconds (or degrees)
            $time        Day fraction
            $hour        Hours
            $minutes     Minutes
            $second      Seconds
            $mode        'H' or 'D' to interpret as hours or degrees (default
                         hours)

time2hms
          ($sign, $hour, $minute, $second) = time2hms($time, $mode, $sig);

          Returns hours (or degrees), minutes and seconds given the day fraction
            $sign      Sign of angle ('+' or '-')
            $hour      Hours
            $minutes   Minutes
            $second    Seconds
            $time      Day fraction
            $mode      Return degrees or Hours?
                        'H' for hours
                        'D' for degrees
            $sig       Number of significant digits for $second

deg2rad
          $rad=deg2rad($deg);
           Convert degrees to radians

rad2deg
          $deg=rad2deg($rad);
           Convert radians to degrees

turn2rad
          $rad=turn2rad($turn);
           Convert turns to radians

rad2turn
          $turn=rad2turn($rad);
           Convert radians to turns

turn2deg
          $deg=turn2deg($turn);
           Convert turns to radians

deg2turn
          $turn=deg2turn($deg);
           Convert degrees to turns

cal2dayno
          $dayno = cal2dayno($day, $month, $year);

          Returns the day number corresponding to $day of $month in $year.

dayno2cal
          ($day, $month) = dayno2cal($dayno, $year);

          Return the $day and $month corresponding to $dayno of $year.

leap
          $isleapyear = leap($year);

          Returns true if $year is a leap year.
            $year    year in full

yesterday
          ($dayno, $year) = yesterday($dayno, $year);
          ($day, $month, $year) = yesterday($day, $month, $year);

          Winds back the day number by one, taking account of year wraps.
            $dayno       Day number of year
            $year        Year
            $month       Month
            $day         Day of month

tomorrow
          ($dayno, $year) = tomorrow($dayno, $year);
          ($day, $month, $year) = tomorrow($day, $month, $year);

          Advances the day number by one, taking account of year wraps.
            $dayno       Day number of year
            $year        Year
            $month       Month
            $day         Day of month

mjd2cal
          ($day, $month, $year, $ut) = mjd2cal($mjd);

          Converts a modified Julian day number into calendar date (universal
          time). (based on the slalib routine sla_djcl).
             $mjd     Modified Julian day (JD-2400000.5)
             $day     Day of the month.
             $month   Month of the year.
             $year    Year
             $ut      UT day fraction

cal2mjd
          $mjd = cal2mjd($day, $month, $year, $ut);

          Converts a calendar date (universal time) into modified Julian day
          number.
             $day     Day of the month.
             $month   Month of the year.
             $year    Year
             $ut      UT dayfraction
             $mjd     Modified Julian day (JD-2400000.5)

mjd2dayno
          ($dayno, $year, $ut) = mjd2dayno($mjd);

          Converts a modified Julian day number into year and dayno (universal
          time).
             $mjd     Modified Julian day (JD-2400000.5)
             $year    Year
             $dayno   Dayno of year

dayno2mjd
          $mjd = dayno2mjd($dayno, $year, $ut);

          Converts a dayno and year to modified Julian day
             $mjd     Modified Julian day (JD-2400000.5)
             $year    Year
             $dayno   Dayno of year

now2mjd
          $mjd = now2mjd()

jd2mjd
          $mjd = jd2mjd($jd);

          Converts a Julian day to Modified Julian day
             $jd      Julian day
             $mjd     Modified Julian day

mjd2jd
          $jd = mjd2jd($mjd);

          Converts a Modified Julian day to Julian day
             $mjd     Modified Julian day
             $jd      Julian day

gst
          $gst = gmst($mjd);
          $gmst = gmst($mjd, $dUT1);
          $gtst = gmst($mjd, $dUT1, $eqenx);

          Converts a modified Julian day number to Greenwich sidereal time
            $mjd     modified Julian day (JD-2400000.5)
            $dUT1    difference between UTC and UT1 (UT1 = UTC + dUT1) (seconds)
            $eqenx   Equation of the equinoxes (not yet supported)
            $gst     Greenwich sidereal time (turns)
            $gmst    Greenwich mean sidereal time (turns)
            $gtst    Greenwich true sidereal time (turns)

mjd2lst
          $lst = mjd2lst($mjd, $longitude);
          $lmst = mjd2lst($mjd, $longitude, $dUT1);
          $ltst = mjd2lst($mjd, $longitude, $dUT1, $eqenx);

          Converts a modified Julian day number into local sidereal time (lst),
          local mean sidereal time (lmst) or local true sidereal time (ltst).
          Unless high precisions is required dUT1 can be omitted (it will always
          be in the range -0.5 to 0.5 seconds).
            $mjd         Modified Julian day (JD-2400000.5)
            $longitude   Longitude for which the LST is required (turns)
            $dUT1        Difference between UTC and UT1 (UT1 = UTC + dUT1)(seconds)
            $eqenx       Equation of the equinoxes (not yet supported)
            $lst         Local sidereal time (turns)
            $lmst        Local mean sidereal time (turns)
            $ltst        Local true sidereal time (turns)

cal2lst
          $lst = cal2lst($day, $month, $year, $ut, $longitude);
          $lmst = cal2lst($day, $month, $year, $ut, $longitude, $dUT1);
          $ltst = cal2lst($day, $month, $year, $ut, $longitude, $dUT1, $eqenx);

          Wrapper to mjd2lst using calendar date rather than mjd

dayno2lst
          $lst = dayno2lst($dayno, $year, $ut, $longitude);
          $lmst = dayno2lst($dayno, $year, $ut, $longitude, $dUT1);
          $ltst = dayno2lst($dayno, $year, $ut, $longitude, $dUT1, $eqenx);

          Wrapper to mjd2lst using calendar date rather than mjd

rise
          ($lst_rise, $lst_set) = rise($ra, $dec, $obslat, $el_limit);

          Return the lst rise and set time of the given source
            $lst_rise, $lst_set  Rise and set time (turns)
            $ra, $dec            RA and Dec of source (turns)
            $obslat              Latitude of observatory (turns)
            $el_limit            Elevation limit of observatory
                                                   (turns, 0 horizontal)
          Returns 'Circumpolar'  if source circumpolar
          Returns  undef         if source never rises

          Uses the formula:
            cos $z_limit = sin $obslat * sin $dec + cos $obslat * cos $dec
                           * cos $HA
            where:
             $z_limit is the zenith angle limit corresponding to $el_limit
             $HA is the Hour Angle of the source
          NOTE: For maximum accuracy source coordinated should be precessed to
               the current date.

lst2mjd
          $mjd = lst2mjd($lmst, $dayno, $year, $longitude);
          $mjd = lst2mjd($lmst, $dayno, $year, $longitude, $dUT1);

          This routine calculates the modified Julian day number corresponding
          to the local mean sidereal time $lmst at $longitude, on a given UT
          day number ($dayno).  Unless high precision is required dUT1 can be
          omitted.

          The required inputs are :
            $lmst      - The local mean sidereal time (turns)
            $dayno     - The UT day of year for which to do the conversion
            $year      - The year for which to do the conversion
            $longitude - The longitude of the observatory (turns)
            $dUT1      - Difference between UTC and UT1 (UT1 = UTC + dUT1)
                                                                        (seconds)
            $mjd         The modified Julian day corresponding to $lmst on $dayno

Asynchronous evaluation of Perl code (with optional timeouts)
*************************************************************

NAME
====

   Async - Asynchronous evaluation of Perl code (with optional timeouts)

SYNOPSIS
========

     my $proc = Async->new(sub { any perl code you want executed });

     if ($proc->ready) {
       # the code has finished executing
       if ($proc->error) {
         # something went wrong
       } else {
         $result = $proc->result;  # The return value of the code
       }
     }

     # or:
     $result = $proc->result('force completion');  # wait for it to finish

DESCRIPTION
===========

   Async executes some code in a separate process and retrieves the
result.  Since the code is running in a separate process, your main
program can continue with whatever it was doing while the separate code is
executing.  This separate code is called an `asynchronous computation'.
When your program wants to check to see if the asynchronous computation is
complete, it can call the `ready()' method, which returns true if so, and
false if it is still running.

   After the asynchronous computation is complete, you should call the
error() method to make sure that everything went all right.  error() will
return undef if the computation completed normally, and an error message
otherwise.

   Data returned by the computation can be retrieved with the result()
method.  The data must be a single string; any non-string value returned
by the computation will be stringized. (See AsyncData below for how to
avoid this.)  If the computation has not completed yet, result() will
return an undefined value.

   result() takes an optional parameter, $force.  If $force is true, then
the calling process will wait until the asynchronous computation is
complete before returning.

`AsyncTimeout'
--------------

     use Async;
     $proc = AsyncTimeout->new(sub {...}, $timeout, $special);

   `Async::Timeout' implements a version of Async that has an automatic
timeout.  If the asynchronous computation does not complete before
$timeout seconds have elapsed, it is forcibly terminated and returns a
special value `$special'.  The default special value is the string "Timed
out\n".

   All the other methods for `AsyncTimeout' are exactly the same as for
Async.

`AsyncData'
-----------

     use Async;
     $proc = AsyncData->new(sub {...});

   `AsyncData' is just like Async except that instead of returning a
string, the asynchronous computation may return any scalar value.  If the
scalar value is a reference, the result() method will yield a refernce to
a copy of this data structure.

   The `AsyncData' module requires that Storable be installed.
`AsyncData::new' will die if Storable is unavailable.

   All the other methods for `AsyncData' are exactly the same as for Async.

WARNINGS FOR THE PROGRAMMER
===========================

   The asynchronous computation takes place in a separate process, so
nothing it does can affect the main program.  For example, if it modifies
global variables, changes the current directory, opens and closes
filehandles, or calls die, the parent process will be unaware of these
things.  However, the asynchronous computatin does inherit the main
program's file handles, so if it reads data from files that the main
program had open, that data will not be availble to the main program;
similarly the asynchronous computation can write data to the same file as
the main program if it inherits an open filehandle for that file.

ERRORS
======

   The  errors that are reported by the error() mechanism are: those that
are internal to Async itself:

     Couldn't make pipe: (reason)
     Couldn't fork: (reason)
     Read error: (reason)

   If your asynchronous computation dies for any reason, that is not
considered to be an `error'; that is the normal termination of the
process.  Any messages written to `STDERR' will go to the computation's
`STDERR', which is normally inherited from the main program, and the
result() will be the empty string.

EXAMPLE
=======

     use Async;
     sub long_running_computation {
        # This function simulates a computation that takes a long time to run
        my ($x) = @_;
        sleep 5;
        return $x+2;  # Eureka!
     }

     # Main program:
     my $proc = Async->new(sub {long_running_computation(2)}) or die;
     # The long-running computation is now executing.
     #

     while (1) {
       print "Main program:  The time is now ", scalar(localtime), "\n";
       my $e;
       if ($proc->ready) {
         if ($e = $proc->error) {
     	print "Something went wrong.  The error was: $e\n";
         } else {
     	print "The result of the computation is: ", $proc->result, "\n";
         }
         undef $proc;
       }
       # The result is not ready; we can go off and do something else here.
       sleep 1; # One thing we could do is to take nap.
     }

AUTHOR
======

   Mark-Jason Dominus `mjd-perl-async+@plover.com'.

Perl class to deal with simultaneous asynchronous calls
*******************************************************

NAME
====

   Async::Group - Perl class to deal with simultaneous asynchronous calls

SYNOPSIS
========

     use Async::Group ;
     use strict ;

     sub sub1
      {
        print "Dummy subroutine \n";
        my $dummy = shift ;
        my $cb = shift ;

     &$cb(1);
       }

     sub allDone
      {
        print "All done, result is ", shift ,"\n" ;
      }
     my $a = Async::Group->new(name => 'aTest', test => 1) ;

     $a->run(set => [ sub {&sub1( callback => sub {$a->callDone(@_)} )},
                     sub {&sub1( callback => sub {$a->callDone(@_)} )} ],
            callback => \&allDone
           )

     # or another way which avoids the clumsy nested subs
     my $cb = $a->getCbRef();
     $a->run(set => [ sub {&sub1( callback => $cb)},
                      sub {&nsub1( callback => $cb )} ],
            callback => \&allDone
           )

DESCRIPTION
===========

   If you sometimes have to launch several asynchronous calls in parrallel
and want to call one call-back function when all these calls are finished,
this module may be for you.

   Async::Group is a class which enables you to call several asynchronous
routines.  Each routine may have their own callback. When all the routine
are over (i.e.  all their callback were called), Async::Group will call
the global callback given by the user.

   Note that one Async::Group objects must be created for each group of
parrallel calls. This object may be destroyed (or will vanish itself) once
the global callback is called.

   Note also that Async::Group does not perform any fork or other system
calls.  It just run the passed subroutines and keep count of the call-back
functions called by the aforementionned subroutines. When all these subs
are finished, it calls another call-back (passed by the user) to perform
whatever function required by the user.

   Using fork or threads or whatever is left to the user.

Methods
=======

new( set => [sub, sub, ...], [test => 1] )
------------------------------------------

   Creates a new Async::Group object.

   parameters are :  - name: name of the group. The name has no special
meaning but it can be    helpfull for debugging.   - test:  will print on
STDERR  what's going on

run ('set'    => [ sub { } ,... ], 'callback' => sub{ ...} )
------------------------------------------------------------

     - set: array ref of a set of subroutine reference that will be called in
       parrallel
     - callback : global user callback function

callDone(result, [string])
--------------------------

   Function to be called back each time an asynchronous call is finished.

   When all function calls are over (i.e. all call-back were performed)
all the returned results are logically 'anded', the passed strings are
concatenated and the resulting result is passed to the global user
call-back function passed with the run() method.

getCbRef()
----------

   Syntactic sugar to avoid nested subs when defining the set of routines
that must be run in parrallel. This function will return a sub ref that
can be used as a callback function by the user's routine.

   So you may call run() with the following sequence :

     my $cb = $a->getCbRef();
     $a->run(set => [ sub {&sub1( callback => $cb)},
                      sub {&nsub1( callback => $cb )} ],
            callback => \&allDone
           )

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998 Dominique Dumont. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   perl(1)

perform exit processing for a program or object
***********************************************

NAME
====

   atexit, *AtExit* - perform exit processing for a program or object

SYNOPSIS
========

     use AtExit;

     sub cleanup {
         my @args = @_;
         print "cleanup() executing: args = @args\n";
     }

     ## Register subroutines to be called when this program exits

     $_ = atexit(\&cleanup, "This call was registered first");
     print "first call to atexit() returned $_\n";

     $_ = atexit("cleanup", "This call was registered second");
     print "second call to atexit() returned $_\n";

     $_ = atexit("cleanup", "This call should've been unregistered by rmexit");
     rmexit($_)  or  warn "couldnt' unregister exit-sub $_!";

     if (@ARGV == 0) {
        ## Register subroutines to be called when this lexical scope is exited
        my $scope1 = AtExit->new( \&cleanup, "Scope 1, Callback 1" );
        {
           ## Do the same for this nested scope
           my $scope2 = AtExit->new;
           $_ = $scope2->atexit( \&cleanup, "Scope 2, Callback 1" );
           $scope1->atexit( \&cleanup, "Scope 1, Callback 2");
           $scope2->atexit( \&cleanup, "Scope 2, Callback 2" );
           $scope2->rmexit($_) or warn "couldn't unregister exit-sub $_!";

     print "*** Leaving Scope 2 ***\n";
          }
          print "*** Finished Scope 2 ***\n";
          print "*** Leaving Scope 1 ***\n";
      }
      print "*** Finished Scope 1 ***\n"  if (@ARGV == 0);

     END {
         print "*** Now performing program-exit processing ***\n";
     }

DESCRIPTION
===========

   The *AtExit* module provides ANSI-C style exit processing modeled after
the atexit function in the standard C library (see `atexit(3C)' in this
node).  Various exit processing routines may be registered by calling
atexit and passing it the desired subroutine along with any desired
arguments. Then, at program-exit time, the subroutines registered with
atexit are invoked with their given arguments in the reverse order of
registration (last one registered is invoked first).  Registering the same
subroutine more than once will cause that subroutine to be invoked once
for each registration.

   An *AtExit* object can be created in any scope. When invoked as a
function, atexit registers callbacks to be executed at *program-exit*
time. But when invoked as an object-method (using the
`$object->method_name' syntax), callbacks registered with an *AtExit*
object are executed at *object-destruction time*! The rules for order of
execution of the registered subroutines are the same for objects during
object-destruction, as for the program during program-termination.

   The atexit function/method should be passed a subroutine name or
reference, optionally followed by the list of arguments with which to
invoke it at program/object exit time.  Anonymous subroutine references
passed to atexit act as "closures" (which are described in Perlref (perl.info)).
If a subroutine name is specified (as opposed to a
subroutine reference) then, unless the subroutine name has an explicit
package prefix, it is assumed to be the name of a subroutine in the
caller's current package.  A reference to the specified subroutine is
obtained, and, if invocation arguments were specified, it is "wrapped up"
in a closure which invokes the subroutine with the specified arguments.
The resulting subroutine reference is added to the front of the list of
exit-handling subroutines for the program (atexit) or the *AtExit* object
(`$exitObject->atexit') and the reference is then returned to the caller
(just in case you might want to unregister it later using *rmexit*. If the
given subroutine could not be registered, then the value zero is returned.

   The *rmexit* function/method should be passed one or more subroutine
references, each of which was returned by a previous call to atexit. For
each argument given, *rmexit* will look in the list of exit-handling
subroutines for the program (*rmexit*) or the *AtExit* object
(`$exitObject->rmexit') and remove the first matching entry from the list.
If no arguments are given, *then all program or object exit-handlers are
unregistered!* The value returned will be the number of subroutines that
were successfully unregistered.

   At object destruction time, the `DESTROY{}' subroutine in the *AtExit*
module iterates over the subroutine references in the *AtExit* object and
invokes each one in turn (each subroutine is removed from the front of the
queue immediately before it is invoked).  At program-exit time, the
`END{}' block in the *AtExit* module iterates over the subroutines in the
array returned by the *exit_subs* method and invokes each one in turn
(each subroutine is removed from the front of the queue immediately before
it is invoked).  Note that in both cases (program-exit, and
object-destruction) the subroutines in this queue are invoked in
first-to-last order (the reverse order in which they were registered with
atexit).

Adding and removing callbacks during exit/destruction time.
-----------------------------------------------------------

   The method *ignore_when_exiting* specifies how exit-callback
registration and unregistration will be handled during program-exit or
object-destruction time, while exit-callbacks are in process of being
invoked.

   When invoked as a class method (e.g., `AtExit->ignore_when_exiting'),
*ignore_when_exiting* corresponds to the handling of calls to atexit and
*rmexit* during program-termination. But when invoked as an object method
(e.g., `$exitObject->ignore_when_exiting'), then *ignore_when_exiting*
corresponds to the handling of calls to atexit and *rmexit* during
*object-destruction* for the particular object.

   By default, *ignore_when_exiting* returns a non-zero value, which
causes atexit to *ignore* any calls made to it during this time (a value
of zero will be returned). This behavior is consistent with that of the
standard C library function of the same name. If desired however, the user
may enable the registration of subroutines by atexit during this time by
invoking *ignore_when_exiting* and passing it an argument of 0, "", or
undef (for example, `AtExit->ignore_when_exiting(0)' or
`$exitObject->ignore_when_exiting(0)', Just remember that any subroutines
registered with atexit be placed at the *front* of the queue of
yet-to-be-invoked exit-processing subroutines for the program (atexit) or
the *AtExit* object (`$exitObject->atexit').

   Regardless of when it is invoked, *rmexit* will always attempt to
unregister the given subroutines (even when called during program/object
exit processing).  Keep in mind however that if it is invoked during
program/object exit then it will fail to unregister any subroutines that
have *already been invoked* (since those subroutine calls have already
been removed from the corresponding list of exit-handling subroutines).

   The method *is_exiting* may consulted examined to determine if routines
registered using atexit are currently in the process of being invoked. It
will be non-zero if they are and zero otherwise. When invoked as a class
method (e.g., `AtExit->is_exiting'), the return value will correspond to
program-exit processing; but when invoked as an object method (e.g.,
`$exitObject->is_exiting') the return value will correspond to
object-destruction processing for the given object.

   If, for any reason, the list of registered callback needs to be directly
accessed or manipulated, the *exit_subs* function will return a reference
to the list of program-exit callbacks. When invoked as a method,
*exit_subs* will return a reference to the list of object-destruction
callbacks for the corresponding object.

EXPORTS
=======

   For backward compatibility, atexit and *rmexit* are exported by
default. Note however that *exit_subs*, *is_exiting*, and
*ignore_when_exiting* are not exported by default, and should be invoked
as class methods (e.g. `AtExit->is_exiting') if they are to manipulate
program-exit information (rather than object-destruction) and not
explicitly imported.

CAVEATS
=======

Program-termination and Object-destruction
==========================================

   The usual Perl way of doing program/module-exit processing is through
the use of `END{}' blocks (see `"Package Constructors and Destructors"',
see Perlmod (perl.info)).  The *AtExit* module implements its
program-exit processing with with an `END{}' block that invokes all the
subroutines registered by atexit in the array whose referenced is returned
by `exit_subs'.

   For an object, object-destruction processing is implemented by having
the DESTROY method for the object invoke all the subroutines registered by
`$exitObject->atexit'. This occurs when the object loses it's last
reference, which is not necessarily at program end time.

   For objects defined in the global context, if any other `END{}' block
processing is specified in the user's code or in any other packages it
uses, then the order in which the exit processing takes place is subject
to Perl's rules for the order in which objects loose their last references
and `END{}' blocks are processed. This may affect when subroutines
registered with atexit are invoked with respect to other exit processing
that is to be performed. In particular, if *rmexit* is invoked from within
an `END{}' block that executes after the *AtExit* object was destroyed,
then the corresponding subroutine will not be registered and will never be
invoked by the *AtExit* module's destructor code.

`END{}' block processing order
==============================

   `END{}' blocks, including those in other packages, get called in the
reverse order in which they appear in the code. (atexit subroutines get
called in the reverse order in which they are registered.) If a package
gets read via "use", it will act as if the `END{}' block was defined at
that particular part of the "main" code.  Packages read via "require" will
be executed after the code of "main" has been parsed and will be seen last
so will execute first (they get executed in the context of the package in
which they exist).

   It is important to note that `END{}' blocks and object destruction only
get called on normal termination (which includes calls to die or
*Carp::croak*). They do not get called when the program terminates
*abnormally* (due to a signal for example) unless special arrangements
have been made by the programmer (e.g. using a signal handler - see
`"%SIG{expr}"', see Perlvar (perl.info)).

SEE ALSO
========

   `atexit(3C)' in this node describes the atexit function for the
standard C library (the actual Unix manual section in which it appears may
differ from platform to platform - try sections 3C, 3, 2C, and 2).  Further
information on anonymous subroutines ("closures") may be found in
Perlref (perl.info).  For more information on `END{}' blocks, see
`"Package Constructors and Destructors"', see Perlmod (perl.info).
See `"%SIG{expr}"', see Perlvar (perl.info),
for handling abnormal program termination.

AUTHOR
======

   Andrew Langmead <aml@world.std.com> (initial draft).

   Brad Appleton <bradapp@enteract.com> (Version 1.02 and 2.00).

   Michael A. Chase <mchase@ix.netcom.com> (Version 2.00).

Perl interface to libcdaudio (cd + cddb)
****************************************

NAME
====

   Audio::CD - Perl interface to libcdaudio (cd + cddb)

SYNOPSIS
========

     use Audio::CD ();
     my $cd = Audio::CD->init;

DESCRIPTION
===========

   Audio::CD provides a Perl interface to libcdaudio by Tony Arcieri,
available from http://cdcd.undergrid.net/

   Several classes provide glue for the libcdaudio functions and data
structures.

Audio::CD Class
===============

init
     Initialize the Audio::CD object:

          my $cd = Audio::CD->init;

stat
     Stat the *Audio::CD* object, returns an *Audio::CD::Info* object.

          my $info = $cd->stat;

cddb
     Returns an *Audio::CDDB* object.

          my $cddb = $cd->cddb;

play
     Play the given cd track (defaults to 1).

          $cd->play(1);

stop
     Stop the cd.

          $cd->stop;

pause
     Pause the cd.

          $cd->pause;

resume
     Resume the cd.

          $cd->resume;

eject
     Eject the cd.

          $cd->eject;

close
     Close the cd tray.

          $cd->close;

play_frames
          $cd->play_frames($startframe, $endframe);

play_track_pos
          $cd->play_track_pos($strarttrack, $endtrack, $startpos);

play_track
          $cd->play_track($strarttrack, $endtrack);

track_advance
          $cd->track_advance($endtrack, $minutes, $seconds);

advance
          $cd->advance($minutes, $seconds);

get_volume
     Returns an *Audio::CD::Volume* object.

          my $vol = $cd->get_volume;

set_volume
          $cd->set_volume($vol);

Audio::CDDB Class
=================

discid
          my $id = $cddb->discid;

lookup
     Does a cddb lookup and returns an Audio::CD::Data object.

          my $data = $cddb->lookup;

Audio::CD::Data Class

    artist
               my $artist = $data->artist;

    title
               my $title = $data->title;

    genre
               my $genre = $data->genre;

    tracks
          Returns an array reference of *Audio::CD::Track* objects.

Audio::CD::Track Class
======================

name
          my $name = $track->name;

Audio::CD::Info Class
=====================

mode
     Returns the CD mode, one of PLAYING, PAUSED, COMPLETED, NOSTATUS;

          my $track = $info->mode;
          print "playing" if $info->mode == Audio::CD::PLAYING;

total_tracks
     Returns the total number of tracks on the cd.

          my $track = $info->total_tracks;

track_time
     Returns the current track play time:

          my($minutes, $seconds) = $info->track_time;

time
     Returns the current disc play time:

          my($minutes, $seconds) = $info->time;

length
     Returns the disc length time:

          my($minutes, $seconds) = $info->length;

tracks
     Returns an array reference of *Audio::CD::Info::Track* objects.

Audio::CD::Info::Track Class
============================

length
     Returns the track length time:

          my($minutes, $seconds) = $tinfo->length;

pos
     Returns the track position on the CD:

          my($minutes, $seconds) = $tinfo->pos;

type
     Returns the track type (either TRACK_AUDIO or TRACK_DATA):

          if ($tinfo->type == Audio::CD::TRACK_AUDIO) {
            print "audio track\n";
          } elsif ($tinfo->type == Audio::CD::TRACK_DATA) {
            print "data track\n";
          }

is_audio
     Returns true if the track is an audio track; equivalent to the test:

          $tinfo->type == Audio::CD::TRACK_AUDIO ? 1 : 0

is_data
     Returns true if the track is a data track; equivalent to the test:

          $tinfo->type == Audio::CD::TRACK_DATA ? 1 : 0

SEE ALSO
========

   Xmms(3)

AUTHOR
======

   Perl interface by Doug MacEachern

   libcdaudio and cddb_lookup.c by Tony Arcieri

Modules for reading & writing Syntrillium CoolEdit Pro .ses files.
******************************************************************

NAME
====

   Audio::CoolEdit - Modules for reading & writing Syntrillium CoolEdit
Pro .ses files.

SYNOPSIS
========

     use Audio::CoolEdit;

     my $cool = new Audio::CoolEdit;

     my $test_out = './test';

     my $details =	{
     		'bits_sample'	=> 16,
     		'sample_rate'	=> 44100,
     		};

     my $write = $cool -> write( $test_out, $details );

     $write -> add_file(	{
     			'file'		=> './t/testout.wav',
     			'title'		=> "song 1",
     			} );

     $write -> add_file(	{
     			'file'		=> './t/testout.wav',
     			'title'		=> "song 2",
     			} );

     $write -> finish();

     my $read = $cool -> read( $test_out );

     print Data::Dumper->Dump([ $read -> dump() ]);

DESCRIPTION
===========

   Syntrillium's CoolEdit Pro (http://www.syntrillium.com) is a MSWin32
based multitrack capable sound editor.  This module reads/ writes the .ses
(session) file format enabling you to place audio files in a vitual track
at a given offset.  The write module is a lot more developed than the read
module as this has been developed to be used with Audio::Mix

NOTES
=====

   All sample positions used are in byte offsets (see Audio/Tools/Time,
for conversion utilities)

AUTHOR
======

   Nick Peskett - nick@soup.demon.co.uk

SEE ALSO
========

     L<Audio::CoolEdit::Read>

     L<Audio::CoolEdit::Write>

     L<Audio::Tools>

     L<Audio::Mix>

METHODS
=======

new
---

   Returns a blessed Audio::CoolEdit object.

     my $cool = new Audio::CoolEdit;

write
-----

   Returns a blessed Audio::CoolEdit::Write object.

     my $details =	{
     		'bits_sample'	=> 16,
     		'sample_rate'	=> 44100,
     		};
     my $write = $cool -> write( './test', $details );

   See Audio/CoolEdit/Write, for methods.

read
----

   Returns a blessed Audio::CoolEdit::Read object.

     my $read = $cool -> read( './test.ses' );

   See Audio/CoolEdit/Read, for methods.

Methods for reading Syntrillium CoolEdit Pro .ses files.
********************************************************

NAME
====

   Audio::CoolEdit::Read - Methods for reading Syntrillium CoolEdit Pro
.ses files.

SYNOPSIS
========

     use Audio::CoolEdit;

     my $cool = new Audio::CoolEdit;

     my $read = $cool -> read( './testfile.ses' );

NOTES
=====

   This module shouldn't be used directly, a blessed object can be
returned from Audio/CoolEdit.

AUTHOR
======

   Nick Peskett - nick@soup.demon.co.uk

SEE ALSO
========

     L<Audio::CoolEdit>

     L<Audio::CoolEdit::Write>

METHODS
=======

dump
----

   The only method, returns a complex reference to a hash with all sorts
of stuff in it. :-)

     print Data::Dumper->Dump([ $cool -> dump() ]);

Methods for writing Syntrillium CoolEdit Pro .ses files.
********************************************************

NAME
====

   Audio::CoolEdit::Write - Methods for writing Syntrillium CoolEdit Pro
.ses files.

SYNOPSIS
========

     use Audio::CoolEdit;

     my $cool = new Audio::CoolEdit;

     my $details =	{
     		'bits_sample'	=> 16,
     		'sample_rate'	=> 44100,
     		};

     my $write = $cool -> write( './test', $details );

NOTES
=====

   This module shouldn't be used directly, a blessed object can be
returned from Audio/CoolEdit.

AUTHOR
======

   Nick Peskett - nick@soup.demon.co.uk

SEE ALSO
========

     L<Audio::CoolEdit>

     L<Audio::CoolEdit::Read>

METHODS
=======

file_name
---------

   Returns the filename of the session file to be written.

     my $file = $write -> file_name();

add_file
--------

   Adds a wav file to the current ses file.  Takes a reference to a hash
as the only parameter.  This hash should at least contain a path to the
wav file.

     use Audio::Tools::Fades;
     my $fade_type = 'trig';
     my $fade_length = 20000;
     my $fades = new Audio::Tools::Fades;
     my $fade_sub = $fades -> fade( $fade_length, 0, $fade_type );

     my $record =	{
     			'file'		=> './t/testout.wav',
     			'offset'	=> 0,
     			'title'		=> "song 1",
     			'fade'		=> {
     					   'in'	=>	{
     							'type'	=> $fade_type,
     							'fade'	=> $fade_sub,
     							'start'	=> 0,
     							'end'	=> $fade_length,
     							},
     					   },
     		};

     $write -> add_file( $record );

   Parameters are; (* optional)

     file	=> path to wav file
     offset*	=> offset in bytes to place the file.
     start*	=> the byte offset to start the file at.
     end*	=> the byte offset to stop the file at.
     length*	=> length of data in bytes
     title*	=> title of file
     fade*	=> this should be a reference to a hash

   If you don't supply length or offset you will need to install the
Audio::Wav module so the file can be analysed.

   The fade hash should be in the following format; see
Audio/Tools/Fades,

     in/out	=>	{
     		type	=> linear/ exp/ invexp/ trig/ invtrig
     		fade	=> return from Audio::Tools::Fades -> fade method,
     		start	=> fade starts (bytes),
     		end	=> fade ends (bytes),
     		}

add_cue
-------

   Adds a cuepoint to the current file.

     $write -> add_cue( $byte_offset, 'Name', 'Description' );

finish
------

   Finish & write the current file.

     $write -> finish();

Perl interface to *NIX digital audio device.
********************************************

NAME
====

   Audio::DSP - Perl interface to *NIX digital audio device.

SYNOPSIS
========

     use Audio::DSP;

     ($buf, $chan, $fmt, $rate) = (4096, 1, 8, 8192);

     $dsp = new Audio::DSP(buffer   => $buf,
                           channels => $chan,
                           format   => $fmt,
                           rate     => $rate);

     $seconds = 5;
     $length  = ($chan * $fmt * $rate * $seconds) / 8;

     $dsp->init() || die $dsp->errstr();

     # Record 5 seconds of sound
     for (my $i = 0; $i < $length; $i += $buf) {
         $dsp->read() || die $dsp->errstr();
     }

     # Play it back
     for (;;) {
         $dsp->write() || last;
     }

     $dsp->close();

DESCRIPTION
===========

   Audio::DSP is built around the OSS (Open Sound System) API and allows
perl to interface with a digital audio device. It provides, among other
things, an `initialization|"item_init"' in this node method which opens
and handles ioctl messaging on the audio device file. Audio::DSP also
provides some `rudimentary methods|"Dealing with data in memory"' in this
node for the storage and manipulation of audio data in memory.

   In order to use Audio::DSP, you'll need to have the necessary OSS
drivers/libraries installed. OSS is available for many popular Unices, and
a GPLed version (with which this extension was initially developed and
tested) is distributed with with the Linux kernel.

CONSTRUCTOR
===========

new([params])
     Returns blessed Audio::DSP object. Parameters:

    device
          Name of audio device file. Default is '/dev/dsp'.

    buffer
          Length of buffer, in bytes, for reading from/writing to the
          audio device file.  Default is 4096.

    rate
          Sampling rate in bytes per second. This parameter affects, among
          other things, the highest frequency in the sampled signal, which
          must be less than half the sample rate. Compact discs use a
          44100 samples per second sampling rate.

          Default sample rate is 8192.

    format
          Sample format. This parameter affects not only the size and the
          byte-order of a sample, but also its dynamic range.

          Sample format may be directly specified as an integer (e.g. 8 or
          16) or as one of the format `constants|"CONSTANTS"' in this node
          defined in soundcard.h and exported by Audio::DSP on use. The
          latter is preffered; an integer value of 16 (for example)
          corresponds to little endian signed 16 (AFMT_S16_LE), which
          format may or may not work with your card. So be careful.

          If the format constant is passed as a string (e.g. 'AFMT_U8'
          rather than AFMT_U8), it will work, but *this feature is
          deprecated*. It has been retained for backward-compatibility,
          but do not assume that it will be present in future versions.

          Default sample format is AFMT_U8.

    channels
          1 (mono) or 2 (stereo). Default is 1.

    file
          File from which to read raw sound data to be stored in memory.

          No effort is made to interpret the type of file being read. It's
          up to you to set the appropriate rate, channel, and format
          parameters if you wish to write the sound data to your audio
          device without damaging your hearing.

METHODS
=======

Opening and closing the device
------------------------------

init([params])
     Opens and initializes audio device file. Parameters
     `device|"item_device"' in this node, `buffer|"item_buffer"' in this
     node, `rate|"item_rate"' in this node, `format|"item_format"' in this
     node, and `channels|"item_channels"' in this node are shared with the
     constructor, and will override them. Additional parameters:

    mode
          Integer mode in which to open audio device file. Specifying the
          modes 'O_RDWR', 'O_RDONLY', and 'O_WRONLY' as strings will work,
          but *this feature is deprecated*. Use the Fcntl.pm constants to
          obtain the approriate integer mode values instead.

          The default value is O_RDWR.

     Example:

          $dsp->init(mode => O_RDONLY) || die $dsp->errstr();

     Returns true on success, false on error.

open([mode])
     Opens audio device file, does not send any ioctl messages. Default
     mode is O_RDWR.

     Example:

          $dsp->open(O_RDONLY) || die $dsp->errstr();

     Returns true on success, false on error.

close()
     Closes audio device file. Returns true on success, false on error.

Dealing with data in memory
---------------------------

audiofile($filename)
     Reads data from specified file and stores it in memory. If there is
     sound data stored already in memory, the file data will be
     concatenated onto the end of it.

     No effort is made to interpret the type of file being read. It's up
     to you to set the appropriate rate, channel, and format parameters if
     you wish to write the sound data to your audio device without
     damaging your hearing.

          $dsp->audiofile('foo.raw') || die $dsp->errstr();

     Returns true on success, false on error.

read()
     Reads buffer length of data from audio device file and appends it to
     the audio data stored in memory. Returns true on success, false on
     error.

write()
     Writes buffer length of sound data currently stored in memory,
     starting at the current `play mark|"item_setmark"' in this node
     offset, to audio device file. `Play mark|"item_setmark"' in this node
     is incremented one buffer length. Returns true on success, false on
     error or if the `play mark|"item_setmark"' in this node exceeds the
     length of audio data stored in memory.

clear()
     Clears audio data currently stored in memory, sets play mark to zero.
     No return value.

data()
     Returns sound data stored in memory.

          open RAWFILE, '>foo.raw';
          print RAWFILE $dsp->data();
          close RAWFILE;

datacat($data)
     Concatenates argument (a string) to audio data stored in memory.
     Returns length of audio data currently stored.

datalen()
     Returns length of audio data currently stored in memory.

setbuffer([$length])
     Sets read/write buffer if argument is provided.

     Returns buffer length currently specified.

setmark([$mark])
     Sets play mark if argument is provided. The play mark indicates how
     many bites of audio data stored in memory have been written to the
     audio device file since the mark was last set to zero. This lets the
     `write()|"item_write"' in this node method know what to write.

     Returns current play mark.

Reading/writing data directly to/from the device
------------------------------------------------

   These methods are provided mainly for the purposes of anyone wishing to
delve into hard-disk recording.

dread([$length])
     Reads length of data from audio device file and returns it. If length
     is not supplied, a "buffer length" of data (as specified when the
     `constructor|"item_new"' in this node/`init()|"item_init"' in this
     node method was called) is read.  If there is an error reading from
     the device file, a false value is returned.

dwrite($data)
     Writes data directly to audio device. Returns true on success, false
     on error.

I/O Control
-----------

   The device must be opened with `init()|"item_init"' in this node or
`open()|"item_open"' in this node before calling any of the following
methods.

   It is important to set sampling parameters in the following order:
`setfmt()|"item_setfmt"' in this node, `channels()|"item_channels"' in
this node, `speed()|"item_speed"' in this node. Setting sampling rate
(speed) before number of channels does not work with all devices,
according to OSS documentation. The safe alternative is to call
`init()|"item_init"' in this node with the appropriate parameters.

post()
     Sends SNDCTL_DSP_POST ioctl message to audio device file. Returns
     true on success, false on error.

reset()
     Sends SNDCTL_DSP_RESET ioctl message to audio device file. Returns
     true on success, false on error.

sync()
     Sends SNDCTL_DSP_SYNC ioctl message to audio device file. Returns
     true on success, false on error.

setfmt($format)
     Sends SNDCTL_DSP_SETFMT ioctl message to audio device file, with
     sample format as argument. Returns sample format to which the device
     was actually set if successful, false on error. You should check the
     return value even on success to ensure the requested sample format
     was in fact set for the device.

          my $format = AFMT_S16_LE; # signed 16-bit, little-endian
          my $rv     = $dsp->setfmt($format) || die $dsp->errstr;

          die "Failed to set requested sample format"
              unless ($format == $rv);

channels($channels)
     Sends SNDCTL_DSP_CHANNELS ioctl message to audio device file, with
     number of channels as argument. Returns number of channels to which
     the device was actually set if successful, false on error. You should
     check the return value even on success to ensure the requested number
     of channels were in fact set for the device.

          my $chan = 2; # stereo
          my $rv   = $dsp->channels($chan) || die $dsp->errstr;

          die "Failed to set requested number of channels"
              unless ($chan == $rv);

speed($rate)
     Sends SNDCTL_DSP_SPEED ioctl message to audio device file, with
     sample rate as argument. Returns sample rate to which the device was
     actually set if successful, false on error. You should check the
     return value even on success to ensure the requested sample rate was
     in fact set for the device.

          my $rate = 44100; # CD-quality sample rate
          my $rv   = $dsp->speed($rate) || die $dsp->errstr;

          die "Failed to set requested sample rate"
              unless ($rate == $rv);

setduplex()
     Sends SNDCTL_DSP_SETDUPLEX ioctl message to audio device file.
     Returns true on success, false on error.

Misc
----

errstr()
     Returns last recorded error.

Deprecated methods
------------------

   The following methods exist for transitional compatibility with version
0.01 and may not be available in future versions.

   The preferred alternative to the set* methods below is either to:

  1. close the device and call `init()|"item_init"' in this node with the
     appropriate parameters or:

  2. call the appropriate I/O control methods after having
     closed/re-opened the device, or after having called
     `reset()|"item_reset"' in this node
        The second should only be performed if you know what you are
doing. It is important, for example, to set sampling parameters in the
following order: `setfmt()|"item_setfmt"' in this node,
`channels()|"item_channels"' in this node, `speed()|"item_speed"' in this
node. Setting sampling rate (speed) before number of channels does not
work with all devices, according to OSS documentation.

getformat($format)
     Returns true if specified `sample format|"item_format"' in this node
     is supported by audio device. A false value may indicate the format
     is not supported, but it may also mean that the SNDCTL_DSP_GETFMTS
     ioctl failed (the `init()|"item_init"' in this node method must be
     called before this method), etc.  Be sure to check the last `error
     message|"item_errstr"' in this node in this case.

     Deprecated. If you wish to check if a given format is supported by the
     device, instead call `getfmts()|"item_getfmts"' in this node method,
     then AND the return value with the format for which you wish to check.

          my $format = AFMT_S16_LE;
          my $mask   = $dsp->getfmts;

          print "Format is supported!\n"
              if ($format & $mask);

queryformat()
     Returns currently used format of initialized audio device. Unlike the
     `setformat()|"item_setformat"' in this node method, queryformat
     "asks" the audio device directly which format is being used.

     Deprecated. If you wish to find the format to which the device is
     currently set, instead call `setfmt()|"item_setfmt"' in this node
     with AFMT_QUERY as an argument and check the return value.

          my $format = $dsp->setfmt(AFMT_QUERY);
          print "Device set to format $format.\n";

setchannels([$channels])
     Deprecated. See introduction to this section for alternative methods.

     Sets number of channels if argument is provided. If the audio device
     file is open, the number of channels will not actually be changed
     until you call `close()|"item_close"' in this node and
     `init()|"item_init"' in this node again.

     Returns number of channels currently specified.

setdevice([$device_name])
     Deprecated. See introduction to this section for alternative methods.

     Sets audio device file if argument is provided. If the device is
     open, it will not actually be changed until you call
     `close()|"item_close"' in this node and `init()|"item_init"' in this
     node again.

     Returns audio device file name currently specified.

setformat([$bits])
     Deprecated. See introduction to this section for alternative methods.

     Sets sample format if argument is provided. If the audio device file
     is open, the sample format will not actually be changed until you call
     `close()|"item_close"' in this node and `init()|"item_init"' in this
     node again.

     Returns sample format currently specified.

setrate([$rate])
     Deprecated. See introduction to this section for alternative methods.

     Sets sample rate if argument is provided. If the audio device file is
     open, the sample rate will not actually be changed until you call
     `close()|"item_close"' in this node and `init()|"item_init"' in this
     node again.

     Returns sample rate currently specified.

CONSTANTS
=========

   The following audio-format constants are exported by Audio::DSP on use:

AFMT_MU_LAW
     logarithmic mu-Law

AFMT_A_LAW
     logarithmic A-Law

AFMT_IMA_ADPCM
     4:1 compressed (IMA)

AFMT_U8
     8 bit unsigned

AFMT_S16_LE
     16 bit signed little endian (Intel - used in PC soundcards)

AFMT_S16_BE
     16 bit signed big endian (PPC, Sparc, etc)

AFMT_S8
     8 bit signed

AFMT_U16_LE
     16 bit unsigned little endian

AFMT_U16_BE
     16 bit unsigned bit endian

AFMT_MPEG
     MPEG (not currently supported by OSS)

NOTES
=====

   Audio::DSP does not provide any methods for converting the raw audio
data stored in memory into other formats (that's another project
altogether).  You can, however, use the `data()|"item_data"' in this node
method to dump the raw audio to a file, then use a program like sox to
convert it to your favorite format. If you are interested in writing .wav
files, you may want to take a look at Nick Peskett's Audio::Wav module.

AUTHOR
======

   Seth David Johnson, seth@pdamusic.com

SEE ALSO
========

   Open Sound System homepage:

     http://www.opensound.com/

   Open Sound System - Audio programming:

     http://www.opensound.com/pguide/audio.html

   OSS Programmer's guide (PDF):

     http://www.opensound.com/pguide/oss.pdf

   A GPLed version of OSS distributed with the Linux kernel was used in the
development of Audio::DSP. See "The Linux Sound Subsystem":

     http://www.linux.org.uk/OSS/

   To my knowledge, the Advanced Linux Sound Architecture (ALSA) API is
supposed to remain compatible with the OSS API on which this extension is
built. ALSA homepage:

     http://www.alsa-project.org/

   perl(1).

COPYRIGHT
=========

   Copyright (c) 1999-2000 Seth David Johnson.  All Rights Reserved. This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Perl extension for libmikmod.
*****************************

NAME
====

   Audio::MikMod - Perl extension for libmikmod.

SYNOPSIS
========

     use Audio::MikMod qw(:all);
     use Time::HiRes;

     MikMod_RegisterAllDrivers();
     MikMod_RegisterAllLoaders();
     MikMod_Init();

     my $module = Player_Load('filename', 64, 0);
     Player_Start($module);

     while(Player_Active()) {
     	usleep(10000);
     	MikMod_Update();
     }

     Player_Stop();
     Player_Free($module);
     MikMod_Exit();

DESCRIPTION
===========

   This module provides an interface to the libmikmod library for playing
MOD, IT, XM, S3M, MTM, 669, STM, ULT, FAR, MED, AMF, DSM, IMF, GDM, and
STX tracker files. In addition, manipulation of WAV samples is supported.

   Please see the extensive libmikmod info documentation included with
that package.

   libmikmod is required, and can be obtained at http://mikmod.darkorb.net/

AUTHOR
======

   Daniel Sully <daniel-cpan-mikmod@electricrain.com>

SEE ALSO
========

   info mikmod, perl(1).

Module for fading cross-fading wav audio files.
***********************************************

NAME
====

   Audio::Mix - Module for fading cross-fading wav audio files.

SYNOPSIS
========

     my $settings =	{
     		'out_dir'	=> '.',
     		'hints'		=> {
     				   'dir'	=> '.',
     				    'mode'	=> 'write',
     				   },
     		'fade_time'	=> 15,
     		'default_fade'	=> 'linear',
     		};

     my $wav = Audio::Mix -> new( $settings );

     my $xfade = 	{
     		'out_type'	=> 'cooledit',
     		'read_dir'	=> './t',
     		'out_file'	=> 'xfade',
     		'dao_file'	=> 1,
     		};

     $wav -> mix( $xfade );

DESCRIPTION
===========

Perl Wav/ CoolEdit Fader/ Cross-Fader
-------------------------------------

   The purpose of this module is to provide a way to apply fades to
uncompressed Microsoft .wav files. Not being a c programmer, the fades are
done completely in perl, making a minutes fade on a stereo  44.1 Khz,
16bit file take a considerable amount of time. The primary reason I wrote
this module was because I needed a programmatic way to mix songs together
for subsequent burning to a CDR. After spending many hours watching
countdowns while my perl loop faded files in & out I contacted
Syntrillium, makers of the excellent multitrack sound editor 'Cooledit
Pro' asking for details of their file format, so I could have the perl
program read the attributes of each .wav file, sort them by tempo, arrange
the fading curves and write all this to a small Cooledit 'session' file
for subsequent preview/ tweaking. I personally use the Cooledit mode for a
number of reasons;

   * You can listen to the results in minutes rather than hours.

   * You can view all the waveforms together and visually see the
non-destructive fades that will be applied

   * It handles clipping (when the digital volume becomes larger than the
bit size will allow), my program just warns you when it happens and does
nothing about it :-(

   Among the reasons I have left the perl .wav mixing routines is for
people who may be using a non mswin32 platform or cannot justify the price
of Cooledit. Also I'm kind of hoping that a c whizz will become interested
and contact me about writing a super cool c mixing engine in this curious
XS thing I've been hearing so much about :-) While on the subject of
different platforms, I pretty sure that this version will not work on big
endian processors as I'm not doing anything about network orders etc yet,
as it started to make my head hurt!  (see Audio/Tools/ByteOrder)

Why?
====

   The concept behind this module is that each .wav file can be marked up
to give the arrangement decider (for want of a better name) clues as to
the best way to mix a song into the final output. You can start out marking
up the actual file with cuepoints and at a later stage when tweaking the
mix you can place a hint file in a given directory and these settings will
take precedence over the settings marked up in the .wav file. I'm planning
to add a feature that will encode the information in the hint file into
the .wav file. This should be able to be done fairly quickly as this
information usually resides after the sound data block.

   The Cross Fader is given either an input directory that it collects its
.wav files from or a list of fully qualified paths.

   The two methods for marking up files are;

Markup Methods
==============

Cuepoints within the .wav file.
-------------------------------

   Markups should be entered with the command in the name field & the
option in the description field. I've only used cooledit to mark these
files so I'm not sure how the program would behave with cuepoints created
in another audio editing program.

   To edit cuepoints (in cooledit) choose

     View -> Cue Edit

   * type the command in the Name & the option in Description.

   Within a .wav file, Cooledit uses the CUE block to define offsets for
each cue, but it uses LIST block to store the name & description
information. This LIST block type is known as an Associated Data List
(adtl). This method of encoding cue point names & descriptions is not
universally accepted as a good thing, but I couldn't find an alternative
method.

Entries in a hint file.
-----------------------

   If a correspondingly named .hint file exists in the hints directory
then this information will be used in preference to the markups within the
.wav file. You can set the hint directory to be the same as the .wav input
directory but this has little use when dealing with read only sources
(such as CDR).

   The hint file should have each command on a separate line with the
option on the same line after a tab. All times should be in sample format,
offset from 0 (being the start of the file).

   Hints can also exist in the .wav input directory, but if this is the
case they have lower priority than the ones in the hint directory.

Markup Types.
=============

Start/ End Points
-----------------

   command: start/ end

   *options:* none

   These markers determine at which point the song will start/ end. Fades
are started/ finished from these points

Significant points
------------------

   command: sig

   *options:* first/ last

   A significant point in a song will be used as the position the next/
previous song aligns it's first/ last point to. In general it's good
practice to try and make these points sit at the first beat of the bar (or
at least on a beat). In this way even if two songs tempos do not match
exactly at the significant point for each song it should fall on the same
beat.  I've found that significant points sound good at the centre of a
fade in/ out

Fades
-----

   See Audio/Tools/Fades,

   command: fade_in/ fade_out

   *options:* linear/ trig/ invtrig/ exp/ invexp

   Currently the module only supports a fade in from either the start of
the file or from a start tag or a fade out to the end of the file or a end
tag.

   The different fade types are;

   * linear - Smooth linear fade

   * trig/ invtrig - Trigonomic fade. My favourite. looks suspiciously
like a quarter of a circle. Inv is the inverse, i.e. starts slowly, gets
louder/ quiter the nearer the end it gets

   * exp/ invexp - Exponential fade. An extreme fade that follows x
squared. Gets loud/ quite quickly and finishes slowly. invexp as above

AUTHOR
======

   Nick Peskett - nick@soup.demon.co.uk

SEE ALSO
========

   See Audio/Tools/ByteOrder,

   See Audio/Tools/Fades,

   See Audio/Wav,

   See Audio/CoolEdit,

METHODS
=======

new
---

   Returns a blessed Audio::Mix object.

     my $settings =	{
     		'out_dir'	=> '.',
     		'fade_time'	=> 15,
     		'default_fade'	=> 'linear',
     		'hints'		=> {
     				   'dir'	=> '.',
     				   'mode'	=> 'write',
     				   },
     		};

     my $wav = Audio::Mix -> new( $settings );

   Where; (all are optional)

   out_dir		=> the directory the mix will be created in.

   fade_time	=> the default length of a fade in seconds.

   default_fade	=> the default fade type

   auto_fade	=> if this is true (1) then unmarked-up file will have
the default 		   fade applied for the default length. The
significant point will 		   be in the centre.

   hints		=> a reference to a hash containing;

     {
     dir	=> path to read hints from
     mode	=> read, write or blank for neither
     }

mix
---

   Creates a mix of a number of given files.

     my $xfade = 	{
     		'out_type'	=> 'cooledit',
     		'read_dir'	=> './t',
     		'out_file'	=> 'xfade',
     		'dao_file'	=> 1,
     		};

     $wav -> mix( $xfade );

   Where; (* are optional) - You should have either read_dir or read_files

   out_type*	=> either cooledit or wav (so far).

   read_dir*	=> a directory where the source wav files can be found.

   read_files*	=> a reference to an array of full paths to source
wav files.

   out_file*	=> the filename to write to (without extension),
defaults to 'mix'.

   dao_file*	=> 1 to write a Goldenhawk cue file (see
Audio::Tools::Time).

a frontend to mpg123 version 0.59r and beyond.
**********************************************

NAME
====

   Audio::Play::MPG123 - a frontend to mpg123 version 0.59r and beyond.

SYNOPSIS
========

     use Audio::Play::MPG123;

     $player = new Audio::Play::MPG123;
     $player->load("kult.mp3");
     print $player->artist,"\n";
     $player->poll(1) until $player->state == 0;

     $player->load("http://x.y.z/kult.mp3");

     # see also mpg123sh from the tarball

DESCRIPTION
===========

   This is a frontend to the mpg123 player. It works by starting an
external mpg123 process with the `-R' option and feeding commands to it.

   While the standard mpg123 player can be used to play back mp3's using
this module you will encounter random deadlocks, due to bugs in its
communication code. Also, many features (like `statfreq') only work with
the included copy of mpg123, so better use that one before deciding that
this module is broken.

   (In case you wonder, the mpg123 author is not interested in including
these fixes and enhancements into mpg123).

METHODS
-------

   Most methods can be either BLOCKING (they wait until they get an answer,
which usually takes half a mpeg frame of playing time), NONBLOCKING (the
functions return as soon as they send their message, which is usallly
instant) or CACHING (the method returns some cached data which only gets
refreshed by an asynchronous STAT event or an explicit call to state).

new [parameter => value, ...]
     This creates a new player object and also starts the mpg123 process.
     New supports the following parameters:

          mpg123args      an arrayreg with additional arguments for the mpg123 process

load(<path or url>) [BLOCKING]
     Immediately loads the specified file (or url, http:// and file:///
     forms supported) and starts playing it. If you really want to play a
     file with a name starting with `file://' or `http://' then consider
     prefixing all your paths with `file:///'. Returns a true status when
     the song could be started, false otherwise.

stat [BLOCKING]
     This can be used to poll the player for it's current state (playing
     mode, frame position &c). As every other function that requires
     communication with mpg123, it might take up to one frame delay until
     the answer returns.  Using `statfreq' and infrequent calls to poll is
     often a better strategy.

pause [BLOCKING]
     Pauses or unpauses the song. state (or paused) can be used to find
     out about the current mode.

paused [CACHING]
     Returns the opposite of state, i.e. zero when something is playing
     and non-zero when the player is stopped or paused.

jump [BLOCKING]
     Jumps to the specified frame of the song. If the number is prefixed
     with "+" or "-", the jump is relative, otherweise it is absolute.

stop [BLOCKING]
     Stops the currently playing song and unloads it.

statfreq(rate) [NONBLOCKING]
     Sets the rate at which automatic frame updates are sent by mpg123. 0
     turns it off, everything else is the average number of frames between
     updates.  This can be a floating pount value, i.e.

          $player->statfreq(0.5/$player->tpf);

     will set two updates per second (one every half a second).

state [CACHING]
     Returns the current state of the player:

          0  stopped, not playing anything
          1  paused, song loaded but not playing
          2  playing, song loaded and playing

poll(<wait>) [BLOCKING or NONBLOCKING]
     Parses all outstanding events and status information. If wait is zero
     it will only parse as many messages as are currently in the queue, if
     it is one it will wait until at least one event occured.

     This can be used to wait for the end of a song, for example. This
     function should be called regularly, since mpg123 will stop playing
     when it can't write out events because the perl program is no longer
     listening...

title artist album year comment genre url type layer samplerate mode mode_extension bpf channels copyrighted error_protected title artist album year comment genre emphasis bitrate extension [CACHING]
     These accessor functions return information about the loaded song.
     Information about the artist, album, year, comment or genre might not
     be available and will be returned as undef.

tpf [CACHING]
     Returns the "time per frame", i.e. the time in seconds for one frame.
     Useful with the jump-method:

          $player->jump (60/$player->tpf);

     Jumps to second 60.

IN
     Returns the input filehandle from the mpg123 player. This can be used
     for selects() or poll().

AUTHOR
======

   Marc Lehmann <pcg@goof.com>.

SEE ALSO
========

   perl(1).

Perl interface to libsndfile, a sound I/O library
*************************************************

NAME
====

     Audio::SoundFile - Perl interface to libsndfile, a sound I/O library

SYNOPSIS
========

     use Audio::SoundFile;
     use Audio::SoundFile::Header;

     $header = new Audio::SoundFile::Header(...);
     $reader = new Audio::SoundFile::Reader(...);
     $writer = new Audio::SoundFile::Writer(...);
     ...

DESCRIPTION
===========

   This module provides interface to libsndfile, available from

     http://www.zip.com.au/~erikd/libsndfile/

   With this library, you will be able to read, write, and manipulate
sound data of more than 10 formats.

   Also, in addition to read/write interface using usual Perl scalar, this
module provides interface using PDL object directly. Since PDL provides
efficient method to handle large bytestream, sound processing is much
faster if this module and PDL is used in pair.

   For rest of the details, please consult each module's document.

NOTES
=====

   I have only tested the code with .au and .wav formats.

AUTHORS / CONTRIBUTORS
======================

   Taisuke Yamada <tai@imasy.or.jp>

COPYRIGHT
=========

   Copyright (C) 2001. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Interface to handle sound format information
********************************************

NAME
====

     Audio::SoundFile::Header - Interface to handle sound format information

SYNOPSIS
========

     use Audio::SoundFile::Header;

     $header = new Audio::SoundFile::Header(
        samplerate  => 44100,
        channels    => 1,
        format      => SF_FORMAT_WAV | SF_FORMAT_PCM,
     );

     die "Invalid format information" unless $header;
     die "Invalid format information" unless $header->set(channels => 2);
     die "Invalid format information" unless $header->format_check;

DESCRIPTION
===========

   This module provides abstract interface to handle sound format
information. It manages format information defined by sndfile.h in
libsndfile library.

   Currently, following methods are provided:

$header = new Audio::SoundFile::Header(%format_info);
     Constructor.

     Returns a class instance which is initialized by given format
     information. This automatically does sanity check of the info, and
     returns undef if the format structure is invalid.

$value = $header->get($name);
     Returns a value that corresponds with given parameter name.

$value = $header->set($name => $value, $name => $value, ...);
     Sets a value for given parameter name.

     If new format structure is invalid (contradicting parameters, etc),
     it discards all information passed, and returns an error. Original
     structure is retained in that case.

     Returns true on success, otherwise false.

$bool = $header->format_check;
     Runs sanity check on the format structure.  Returns true if format is
     valid, otherwise false.

AUTHORS / CONTRIBUTORS
======================

   Taisuke Yamada <tai@imasy.or.jp>

COPYRIGHT
=========

   Copyright (C) 2001. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Reader class for various sound formats
**************************************

NAME
====

     Audio::SoundFile::Reader - Reader class for various sound formats

SYNOPSIS
========

     use IO::Seekable;
     use Audio::SoundFile;

     $reader = new Audio::SoundFile::Reader($source, \$header);

     $length = $reader->bread_raw(\$buffer, $wanted);
     $length = $reader->bread_pdl(\$buffer, $wanted);

     $reader->fseek(1024, SEEK_SET);
     $reader->fseek(1024, SEEK_CUR);
     $reader->fseek(1024, SEEK_END);

     $reader->close;

DESCRIPTION
===========

   This module provides an interface to read various sound formats
supported by libsndfile.

   In addition to usual I/O interface, it provides direct interface to
create PDL object without making a copy of data in pure-Perl space. This
is an advantage on both speed and memory, and is a recommended way to
manipulate sound data.

   Currently supported methods are:

$reader = new Audio::SoundFile::Reader($source, \$header);
     Constructor.  Returns input stream object that reads from given
     source.

     Also assigns header information read from the source to passed scalar
     reference.

$reader->close;
     Closes input stream.  This object will be unusable after this method
     is called.

$offset = $reader->fseek($offset, $whence);
     Moves next reading position to a point where specified by $offset and
     $whence. Note $offset is not a length in bytes, but a number of
     frames to skip (frame is a block of data containing data of all
     channels at given moment).

     Return value (which should be a new position in number of frames) is
     currently unreliable.

$offset = $reader->bseek($offset, $whence);
     Moves next reading position to a point where specified by $offset and
     $whence. Note $offset is not a length in bytes, but a number of
     blocks to skip (block is a bulk of data containing data of single
     channel at given moment).

     Return value (which should be a new position in number of blocks) is
     currently unreliable.

$length = $reader->bread_raw(\$buffer, $wanted);
     Reads $wanted blocks of data, and stores it to $buffer as a Perl
     scalar. Content of $buffer is not guranteed on error.

     Returns length of the data actually stored, or 0 (or lesser value) on
     error.

$length = $reader->bread_pdl(\$buffer, $wanted);
     Reads $wanted blocks of data, and stores it to $buffer as a PDL
     object. Content of $buffer is not guranteed on error.

     Returns length of the data actually stored, or 0 (or lesser value) on
     error.

NOTES
=====

   If you mix bseek/bread and fseek/fread, things might get confusing due
to shift in internal offset - please do it with your responsibility.

AUTHORS / CONTRIBUTORS
======================

   Taisuke Yamada <tai@imasy.or.jp>

COPYRIGHT
=========

   Copyright (C) 2001. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Writer class for various sound formats
**************************************

NAME
====

     Audio::SoundFile::Writer - Writer class for various sound formats

SYNOPSIS
========

     use Audio::SoundFile;
     use Audio::SoundFile::Header;

     $header = new Audio::SoundFile::Header(...);
     $writer = new Audio::SoundFile::Writer($target, $header);

     $length = $writer->bwrite_raw($buffer);
     $length = $writer->bwrite_pdl($buffer);

     $writer->fseek(1024, SEEK_SET); # seek by frame
     $writer->fseek(1024, SEEK_CUR); # seek by frame
     $writer->fseek(1024, SEEK_END); # seek by frame

     $writer->bseek(1024, SEEK_SET); # seek by block
     $writer->bseek(1024, SEEK_CUR); # seek by block
     $writer->bseek(1024, SEEK_END); # seek by block

     $writer->close;

DESCRIPTION
===========

   This module provides an interface to write various sound formats
supported by libsndfile.

   In addition to usual I/O interface, it provides direct interface to
write PDL object without making a copy of data in pure-Perl space. This is
an advantage on both speed and memory, and is a recommended way to handle
sound data.

   Currently supported methods are:

$writer = new Audio::SoundFile::Writer($target, $header);
     Constructor.  Returns output stream object that writes to given target
     in a format specified by $header.

$writer->close;
     Closes output stream.  This object will be unusable after this method
     is called.

$offset = $writer->fseek($offset, $whence);
     Moves next writing position to a point where specified by $offset and
     $whence. Note $offset is not a length in bytes, but a number of
     frames to skip (frame is a block of data containing data of all
     channels at given moment).

     Return value (which should be a new position in number of frames) is
     currently unreliable.

$offset = $writer->bseek($offset, $whence);
     Moves next writing position to a point where specified by $offset and
     $whence. Note $offset is not a length in bytes, but a number of
     blocks to skip (block is a bulk of data containing data of one
     channel at given moment).

     Return value (which should be a new position in number of blocks) is
     currently unreliable.

$length = $write->bwrite_raw($buffer, $wanted);
     Writes $wanted blocks of data from $buffer, which should be a Perl
     scalar.

     Returns length of the data actually written, or -1 on error.

$length = $reader->bwrite_pdl($buffer, $wanted);
     Writes $wanted blocks of data from $buffer, which should be a PDL
     object.

     Returns length of the data actually written, or -1 on error.

NOTES
=====

   If you mix bseek/bwrite and fseek/fwrite, things might get confusing
due to shift in internal offset - please do it with your responsibility.

AUTHORS / CONTRIBUTORS
======================

   Taisuke Yamada <tai@imasy.or.jp>

COPYRIGHT
=========

   Copyright (C) 2001. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Common Tools for Audio::Wav, Audio::Mix & Audio::CoolEdit
*********************************************************

NAME
====

   Audio::Tools - Common Tools for Audio::Wav, Audio::Mix & Audio::CoolEdit

DESCRIPTION
===========

   The modules in this package are ByteOrder, Time & Fades.

   They are all independent and the only use, so far, for Audio::Tools is
a place to hold the documentation.

   ByteOrder is currently the unpacking rules for little endian machines,
I've seperated this from the other modules for ease of porting to big
endian machines.

   Fades is a collection of algorithms for fading in/ out audio files.

   Time is a collection of tools for conversion between time, samples &
bytes among other things.

AUTHOR
======

   Nick Peskett - nick@soup.demon.co.uk

SEE ALSO
========

   See Audio/Tools/ByteOrder,

   See Audio/Tools/Time,

   See Audio/Tools/Fades,

   See Audio/Wav,

   See Audio/Mix,

   See Audio/CoolEdit,

Unpacking rules for little endian machines.
*******************************************

NAME
====

   Audio::Tools::ByteOrder - Unpacking rules for little endian machines.

SYNOPSIS
========

     use Audio::Tools::ByteOrder;
     my $pack_order = new Audio::Tools::ByteOrder;
     my $pack_type = $pack_order -> pack_type(),
     my $pack_length = $pack_order -> pack_length(),

DESCRIPTION
===========

   This is currently the unpacking rules for little endian machines,

AUTHOR
======

   Nick Peskett - nick@soup.demon.co.uk

SEE ALSO
========

   See Audio/Tools,

METHODS
=======

new
---

   Returns a blessed Audio::Tools::ByteOrder object.

     my $pack_order = new Audio::Tools::ByteOrder;

pack_type
---------

   Returns a reference to a hash containing the pack types for various
data formats.

     my $pack_type = $pack_order -> pack_type(),

pack_length
-----------

   Returns a reference to a hash containing the packed lengths for various
data formats.

     my $pack_length = $pack_order -> pack_length(),

Fading in & out algorithms.
***************************

NAME
====

   Audio::Tools::Fades - Fading in & out algorithms.

DESCRIPTION
===========

   Fades is a collection of algorithms for fading in/ out audio files.

SYNOPSIS
========

     use Audio::Tools::Fades;

     my $up_to = 5;
     my @names = qw( in out );
     my $volume = 1;

     my $fades = new Audio::Tools::Fades;

     foreach my $type ( qw( linear exp invexp trig invtrig ) ) {
     	for my $direction ( 0, 1 ) {
     		my $fade = $fades -> fade( $up_to, $direction, $type );
     		print "fade $names[$direction] type: $type;\n\t";
     		for my $sample ( 0 .. $up_to ) {
     			printf ' %2d->%2.2f', $sample, &$fade( $sample, $volume );
     		}
     		print "\n";
     	}
     }

AUTHOR
======

   Nick Peskett - nick@soup.demon.co.uk

SEE ALSO
========

   See Audio/Wav,

   See Audio/Mix,

   See Audio/CoolEdit,

METHODS
=======

new
---

   Returns a blessed Audio::Tools::Fades object.

     my $fades = new Audio::Tools::Fades;

fade
----

   Returns a reference to a subroutine that is initialised to the length
of samples the fade is to last for.  The subroutine returned takes the
current sample offset & the current sample value as parameters.  In the
example I have used sample value 1 so you can see the effect of the fade.

     my $fade = $fades -> fade( $length, $direction, $type );
     for my $sample ( 0 .. $length ) {
     	printf ' %2d->%2.2f', $sample, &$fade( $sample, 1 );
     }
     print "\n";

   Where;

     $length		= length of fade
     $direction	= 0 for in, 1 for out
     $type is one of;
     	linear	= smooth gradient
     	exp	= exponential (gets loud quickly)
     	invexp	= inverse exponential (gets loud slowly)
     	trig	= trigonomic, roughly in between linear & exp
     	invtrig	= inverse trigonomic

time / sample / byte conversion tools.
**************************************

NAME
====

   Audio::Tools::Time - time / sample / byte conversion tools.

DESCRIPTION
===========

   Tools for converting bytes into samples, samples into time etc.

SYNOPSIS
========

     my $time = new Audio::Tools::Time 44100, 16, 2;
     my $bytes = $time -> nice_bytes( 11025 );
     my $sample = $time -> bytes_to_samples( $bytes );
     my $secs = $time -> samples_to_seconds( $sample );
     my( $mins, $secs, $fract_secs )
     	= $time -> split_time( $secs );
     my $dao_time = $time -> dao_time( $secs );

AUTHOR
======

   Nick Peskett - nick@soup.demon.co.uk

SEE ALSO
========

   See Audio/Wav,

   See Audio/Mix,

   See Audio/CoolEdit,

METHODS
=======

new
---

   Returns a blessed Audio::Tools::Time object.

     my $time = new Audio::Tools::Time sample_rate, bits_per_sample, channels;

   Where;

     sample_rate	= number of samples per second (44100 is cd quality)
     bits_per_sample	= number of bits per samples (16 is cd quality)
     channels	= number of channels of sound (stereo is 2)

samples_to_bytes
----------------

   Converts a sample offset to it's byte offset.

     my $bytes = $time -> samples_to_bytes( $sample );

bytes_to_samples
----------------

   Converts a byte offset to it's sample offset.

     my $sample = $time -> bytes_to_samples( $bytes );

samples_to_seconds
------------------

   Converts a sample offset to it's position as floating point seconds.

     my $secs = $time -> samples_to_seconds( $sample );

bytes_to_seconds
----------------

   Converts a byte offset to it's position as floating point seconds.

     my $secs = $time -> bytes_to_seconds( $samples );

seconds_to_samples
------------------

   Converts a position in seconds (can be floating point) to it's sample
offset.

     my $sample = $time -> seconds_to_samples( $secs );

seconds_to_bytes
----------------

   Converts a position in seconds (can be floating point) to it's byte
offset.

     my $sample = $time -> seconds_to_bytes( $secs );

nice_bytes
----------

   Rounds down a byte offset to a appropriate byte offset for the current
settings.

     $bytes = $time -> nice_bytes( $bytes );

split_time
----------

   Converts a floating point seconds position to minutes, seconds &
fractional seconds.

     my( $mins, $secs, $fract_secs )
     	= $time -> split_time( $secs );

dao_time
--------

   Converts a floating point seconds position to a string containing the
format used by disk-at-once & CDRWin.  (`http:' in this node)

     my $dao_time = $time -> dao_time( $secs );

nice_time
---------

   Converts a floating point seconds position into a string that verbosely
describes the time. If $terse is true then the output will only show the
most significant value (to one decimal place if hour or minute).

     print $time -> nice_time( 90 );
     # returns "1 min, 30 secs"
     print $time -> nice_time( 90, 1 );
     # returns "1.5 mins"

dao_cue_file
------------

   Writes a cue file in the format used by disk-at-once & CDRWin.
(`http:' in this node)

     $time -> dao_cue_file( $breaks, './audio.wav', './output.cue' );

   Where $breaks is a reference to an array of byte offsets.

block_align
-----------

   Returns the current block alignment, ie 44.1khz 16 bit stereo: 1 sample
= 4 bytes

     my block_align = $time -> block_align();

Modules for reading & writing Microsoft Wav files.
**************************************************

NAME
====

   Audio::Wav - Modules for reading & writing Microsoft Wav files.

SYNOPSIS
========

     use Audio;

     my $buffer = 512;

     my $wav = new Audio::Wav;

     my $read = $wav -> read( 'testout.wav' );

     my $write = $wav -> write( 'testcopy.wav', $read -> details() );

     my $total = 0;

     my $length = $read -> length();
     while ( $total < $length ) {
     	my $left = $length - $total;
     	$buffer = $left unless $left > $buffer;
     	my $data = $read -> read_raw( $buffer );
     	last unless defined( $data );
     	$write -> write_raw( $data, $buffer );
     	$total += $buffer;
     }

     $write -> finish();

NOTES
=====

   All sample positions used are in byte offsets (see Audio/Tools/Time,
for conversion utilities)

DESCRIPTION
===========

   These modules provide a method of reading & writing uncompressed
Microsoft Wav files.  It was developed on mswin32 so I'm not sure if this
version has the correct byte order for big endian machines.

AUTHOR
======

   Nick Peskett - nick@soup.demon.co.uk

SEE ALSO
========

     L<Audio::Tools>

     L<Audio::Wav::Read>

     L<Audio::Wav::Write>

METHODS
=======

new
---

   Returns a blessed Audio::Wav object.

     my $wav = new Audio::Wav;

write
-----

   Returns a blessed Audio::Wav::Write object.

     my $details =	{
     		'bits_sample'	=> 16,
     		'sample_rate'	=> 44100,
     		'channels'	=> 2,
     		};

     my $write = $wav -> write( 'testout.wav', $details );

   See Audio/Wav/Write, for methods.

read
----

   Returns a blessed Audio::Wav::Read object.

     my $read = $wav -> read( 'testout.wav' );

   See Audio/Wav/Read, for methods.

Module for reading Microsoft Wav files.
***************************************

NAME
====

   Audio::Wav::Read - Module for reading Microsoft Wav files.

SYNOPSIS
========

     use Audio::Wav;
     my $wav = new Audio::Wav;
     my $read = $wav -> read( 'filename.wav' );
     my $details = $read -> details();

DESCRIPTION
===========

   Reads Microsoft Wav files.

AUTHOR
======

   Nick Peskett - nick@soup.demon.co.uk

SEE ALSO
========

   See Audio/Wav,

   See Audio/Wav/Write,

NOTES
=====

   This module shouldn't be used directly, a blessed object can be
returned from Audio/Wav.

METHODS
=======

file_name
---------

   Returns the file name.

     my $file = $read -> file_name();

get_info
--------

   Returns information contained within the wav file.

     my $info = $read -> get_info();

   Returns a reference to a hash containing; (for example, a file marked
up for use in Audio::Mix)

     {
               keywords => 'bpm:126 key:a',
               name => 'Mission Venice',
               artist => 'Nightmares on Wax'
             };

get_cues
--------

   Returns the cuepoints marked within the wav file.

     my $cues = $read -> get_cues();

   Returns a reference to a hash containing; (for example, a file marked
up for use in Audio::Mix) (position is byte offset)

     {
               1 => {
                      label => 'sig',
                      position => 764343,
                      note => 'first'
                    },
               2 => {
                      label => 'fade_in',
                      position => 1661774,
                      note => 'trig'
                    },
               3 => {
                      label => 'sig',
                      position => 18033735,
                      note => 'last'
                    },
               4 => {
                      label => 'fade_out',
                      position => 17145150,
                      note => 'trig'
                    },
               5 => {
                      label => 'end',
                      position => 18271676
                    }
             }

read_raw
--------

   Reads raw packed bytes from the current audio data position in the file.

     my $data = $self -> read_raw( $byte_length );

read
----

   Returns the current audio data position sample across all channels.

     my @channels = $self -> read();

   Returns an array of unpacked samples.  Each element is a channel i.e (
left, right ).  The numbers will be in the range;

     where $samp_max = ( 2 ** bits_per_sample ) / 2
     -$samp_max to +$samp_max

position
--------

   Returns the current audio data position (as byte offset).

     my $byte_offset = $read -> position();

move_to
-------

   Moves the current audio data position to byte offset.

     $read -> move_to( $byte_offset );

length
------

   Returns the number of bytes of audio data in the file.

     my $audio_bytes = $read -> length();

details
-------

   Returns a reference to a hash of lots of details about the file.  Too
many to list here, try it with Data::Dumper.....

     use Data::Dumper;
     my $details = $read -> details();
     print Data::Dumper->Dump([ $details ]);

Module for writing Microsoft Wav files.
***************************************

NAME
====

   Audio::Wav::Write - Module for writing Microsoft Wav files.

SYNOPSIS
========

     use Audio::Wav;

     my $wav = new Audio::Wav;

     my $sample_rate = 44100;
     my $bits_sample = 16;

     my $details =	{
     		'bits_sample'	=> $bits_sample,
     		'sample_rate'	=> $sample_rate,
     		'channels'	=> 1,
     		};

     my $write = $wav -> write( 'testout.wav', $details );

     &add_sine( 200, 1 );

     sub add_sine {
     	my $hz = shift;
     	my $length = shift;
     	my $pi = ( 22 / 7 ) * 2;
     	$length *= $sample_rate;
     	my $max_no =  ( 2 ** $bits_sample ) / 2;
     	for my $pos ( 0 .. $length ) {
     		$time = $pos / $sample_rate;
     		$time *= $hz;
     		my $val = sin $pi * $time;
     		my $samp = $val * $max_no;
     		$write -> write( $samp );
     	}
     }

     $write -> finish();

DESCRIPTION
===========

   Currently only writes to a file.

AUTHOR
======

   Nick Peskett - nick@soup.demon.co.uk

SEE ALSO
========

   See Audio/Wav,

   See Audio/Wav/Read,

NOTES
=====

   This module shouldn't be used directly, a blessed object can be
returned from Audio/Wav.

METHODS
=======

finish
------

   Finishes off & closes the current wav file.

     $write -> finish();

add_cue
-------

   Adds a cue point to the wav file.

     $write -> add_cue( $byte_offset, "label", "note"  );

file_name
---------

   Returns the current filename (silly, I know).

     my $file = $write -> file_name();

write
-----

   Adds a sample to the current file.

     $write -> write( @sample_channels );

   Each element in @sample_channels should be in the range of;

     where $samp_max = ( 2 ** bits_per_sample ) / 2
     -$samp_max to +$samp_max

write_raw
---------

   Adds a some pre-packed data to the current file.

     $write -> write_raw( $data, $data_length );

   Where;

     $data is the packed data
     $data_length (optional) is the length in bytes of the data

Module for basic Audio CD control
*********************************

NAME
====

   AudioCD - Module for basic Audio CD control

SYNOPSIS
========

     use AudioCD;
     # see below

DESCRIPTION
===========

   See `AudioCD::Mac' for more information.  Right now, this module has
support only for MacPerl.  Please feel free to write other modules for
Your Favorite Platform and let me know about it.

AUTHOR
======

   Chris Nandor `<pudge@pobox.com>' http://pudge.net/

   Copyright (c) 1998 Chris Nandor.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.  Please see the Perl Artistic License.

VERSION
=======

v0.20, Wednesday, December 9, 1998
     Renamed to `AudioCD', added controls for Audio CD.

v0.10, Thursday, October 8, 1998
     First version, made for Mac OS to get CDDB TOC data.

SEE ALSO
========

   `CDDB.pm'

MacPerl extension for controlling Audio CDs
*******************************************

NAME
====

   AudioCD::Mac - MacPerl extension for controlling Audio CDs

SYNOPSIS
========

     #!perl -w
     use AudioCD;
     use strict;
     my $cd = new AudioCD;

     $cd->volume(255);
     $cd->play(2);
     print "Now playing\n" if $cd->status == CD_PLAY;
     printf "Volume is %d\n", $cd->volume;
     sleep(5);

     $cd->pause;
     print "Now paused\n" if $cd->status == CD_PAUSE;
     sleep(5);

     $cd->volume(100);
     $cd->continue;
     print "Now playing\n" if $cd->status == CD_PLAY;
     printf "Volume is %d\n", $cd->volume;
     sleep(5);

     my @info = $cd->info;
     printf "Currently at track %d, %.2d:%.2d\n", @info[0..2];

     $cd->stop;
     my $status = $cd->status;
     print "Now stopped\n" if
         ($status == CD_FINISH || $status == CD_STOP);

     if (do 'CDDB.pm') {  # sold separately
         my $cddb = new CDDB;
         my @cddb_info = $cddb->calculate_id( $cd->cddb_toc );
         my @discs = $cddb->get_discs(@cddb_info[0, 3, 4]);
         print "You were probably listening to $discs[0]->[2]\n";
     }

     $cd->eject;

DESCRIPTION
===========

   This is the MacPerl module to be used by the `AudioCD' module.  Other
modules can be written for other platforms, but this one is Mac specific,
calling Mac OS APIs to control the CD player.

FUNCTIONS
=========

   All functions except for new are methods that need to be called via the
`AudioCD' object.  All functions attempt to return undef and set $^E on
failure, and unless otherwise specified, return 1 on success.

   Note that the data returned from the Mac OS APIs is often in BCD format,
but the functions that return track and time data convert it to decimal.

new
     Should be called from `AudioCD', not `AudioCD::Mac', but should work
     either way.  Returns the object.

status
     Returns the current status of the CD, one of: CD_PLAY, CD_PAUSE,
     CD_MUTE, CD_FINISH, CD_ERR, CD_STOP, CD_OFFLINE.

info
     Returns an array of information about the CD, with two sets of times,
     one for the current track, one for the disc.  The first item in the
     list is the current track number.

          #  0          1       2        3         4       5        6
          ($t_number, $t_min, $t_sec, $t_frames, $a_min, $a_sec, $a_frames)
              = $cd->info;

play([TRACK])
     If called without a track number, will start from the first track if
     stopped, or continue if paused.  Otherwise will start at specified
     track number, and continue until the CD is finished.

stop
     Stops the CD.  Time settings will likely be left at last play point,
     not at beginning of CD.

pause
     Will pause the CD if it is playing, or continue playing if paused.

continue
     Will continue playing if paused.

eject
     Will unmount the volumes on the drive if any, and then eject the tray.

volume([LEFT_VOLUME [, RIGHT_VOLUME]])
     Sets the left and right channels to a valume from 0 to 255.  Returns
     the left and right channel volumes, unless the two have the same
     value and the method is called in a scalar context, in which case it
     returns just one value.

     If `RIGHT_VOLUME' is not supplied, it will be set to the same value as
     supplied in `LEFT_VOLUME'.  If not values are supplied, the current
     volume value(s) will be returned, and will remain unchanged.

cd_toc
     Returns the table of contents in an anonymous array, where each
     element is another anonymous array, containing the track number [0]
     and the track's starting time offset from the beginning of the CD in
     minutes [1], seconds [2], and frames [3].

cddb_toc
     Returns the same as above, but in a format suitable for passing to
     the `CDDB' module.

last_track
     Ideally, returns the last audio track number on the CD.  If this
     turns out to be wrong, let me know.

TODO
====

Change interface to work well with others (Tuomas' Linux code)
Add support for multiple drives, multiple volumes on drive
Add support for moving forward/backward in tracks, and scanning
Add support for modes (stereo/mono/etc., random/program/repeat/etc.)
Add support to add/extract data in the CD Remote Programs file
Need good test suite ... don't know how this should work, since I won't have good data to test against.  Maybe I should just play some tracks, change the volume, print out the number of tracks and have the user say whether or not it passes.
AUTHOR
======

   Chris Nandor `<pudge@pobox.com>' http://pudge.net/

   Copyright (c) 1998 Chris Nandor.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.  Please see the Perl Artistic License.

   Special thanks to Matthias Neeracher for help with MacPerl XS and C,
and Glenn Howes <grhowes@kagi.com> for his code examples that helped me
understand this stuff.

     http://www.xnet.com/~grhowes/html/helpful.html

   For more info, check out Technote DV22:

     http://developer.apple.com/technotes/dv/dv_22.html

HISTORY
=======

v0.25, Thursday, December 11, 1998
     Significant clean up of Perl and XS code, lots of misc. changes.

     Hopefully fixed cd_toc to give all the right values.

     Fixed eject problems.

          "no pointer is a pointer, too" -- Matthias Neeracher

v0.20, Wednesday, December 9, 1998
     Renamed to `AudioCD', added controls for Audio CD.

v0.10, Thursday, October 8, 1998
     First version, made for Mac OS to get CDDB TOC data.

VERSION
=======

   v0.25, Thursday, December 11, 1998

SEE ALSO
========

   CDDB.pm.

Perl extension for accessing a SecurID ACE server
*************************************************

NAME
====

   Authen::ACE - Perl extension for accessing a SecurID ACE server

SYNOPSIS
========

     use Authen::ACE;
     $ace = new Ace([config => /config/directory])
     $ace->Check(code, username);
     $ace->PIN(PIN, [cancel]);
     $ace->Next(code);
     $ace->Auth([username]);

DESCRIPTION
===========

   Authen::ACE provides a client interface to a Security Dynamics SecurID
ACE server. SecurID authentication can be added to any Perl application
using Authen::ACE.

   Instantiation of an object into the Authen::ACE class will establish a
connection to the ACE server; destruction of the object will close the
connection. Programs can then use the Check/PIN/Next methods to authorize
a user. TTY programs can also use the Auth method, which handles all
authorization tasks normally done by Check/PIN/Next.

METHODS
=======

new
          $ace = new Ace(["config" => "/config/directory"])

     Creates a new Authen::ACE object. The config parameter specifies the
     location of the `sdconf.rec' file. It defaults to the value of the
     `VAR_ACE' environment variable, or the directory `/var/ace' if this
     variable isn't set.

Check
          ($result,$info) = $ace->Check(code, username)

     This is the primary user authentication function. code is the
     PIN+token (or just the token if the user has no PIN), and username is
     the user's name, as it is listed in the ACE database.

     Check returns a two-element list. The first element contains the
     results of the check; the second element contains extra,
     result-specific information.

     Possible results for $result are

    ACM_OK
          The check succeeded. $info contains the shell specified for this
          user.

    ACM_ACCESS_DENIED
          The check failed. No other information is included.

    ACM_NEXT_CODE_REQUIRED
          The check succeeded, but requires a second token to finish the
          authentication. $info contains the number of seconds the server
          will waits for the next code. Authen::ACE::Next should be called
          with the next code upon receiving this result.

    ACM_NEW_PIN_REQUIRED
          A new PIN is required. $info is a ref to an anonymous hash with
          the following elements

         system_pin
               The system generated PIN.

         min_pin_len
               The minimum PIN length.

         max_pin_len
               The maximum PIN length.

         alphanumeric
               True is the PIN is allowed to be alphanumeric

         user_selectable
               Will have one of the values *CANNOT_CHOOSE_PIN*,
               *MUST_CHOOSE_PIN*, *USER_SELECTABLE*, which mean that the
               user must accept the system generated PIN, must choose his
               own PIN, or can do either.

               If the user accepts the system PIN or chooses his own, then
               a call should be made to Authen::ACE::PIN with the selected
               PIN. If the user rejects the system PIN, then a call should
               be made to Authen::ACE::PIN with the value of the *cancel*
               parameter set to 1.

Next
          ($result,$info) = $ace->Next(code)

     This method should be called after receiving a ACM_NEXT_CODE_REQUIRED
     result from Check. code should be the next to display on the user's
     token. Return value is the same as for Authen::ACE::Check, except
     that there will never be a ACM_NEW_PIN_REQUIRED or
     ACM_NEXT_CODE_REQUIRED result.

PIN
          $result = $ace->PIN(pin, [cancel]);

     This method should be called after receiving a ACM_NEW_PIN_REQUIRED
     result from Check. *pin* should be the new PIN, while *cancel* should
     be set to one if the user wishes to cancel the new PIN operation.
     Authen::ACE::PIN will return a result of either
     *ACM_NEW_PIN_ACCEPTED* or *ACM_NEW_PIN_REJECTED*.

Auth
          ($result,$info) = $ace->Auth([username]);

     This method is a convenience method which will handle calling Check,
     and reading a new PIN or requesting the next token if required. It
     should only be called if the running process is attached to a tty.
     username will be determined by the real PID of the process running
     the program if it isn't passed as a parameter.

     The return value is the same as for Authen::ACE::Check, except that
     there will never be a ACM_NEW_PIN_REQUIRED or ACM_NEXT_CODE_REQUIRED
     result.

AUTHOR
======

   Dave Carrigan <Dave.Carrigan@iplenergy.com>

   Copyright (C) 1997 Dave Carrigan, Interprovincial Pipe Line Inc. This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1), ACE/Server Administration Manual, ACE/Server Client API Guide

A Basic challenge/response authentication scheme.
*************************************************

NAME
====

   Authen::Challenge::Basic - A Basic challenge/response authentication
scheme.

SYNOPSIS
========

     use Authen::Challenge::Basic;

     $server = Authen::Challenge->new ('Secret' => 'known2us',
     				  'Timeout' => 30,
     				  'Sync' => 10);

     $client = Authen::Challenge->new ('Secret' => 'known2us',
     				  'Timeout' => 30,
     				  'Sync' => 10);

     $challenge = $server->Challenge;
     $response = $client->Response($challenge);

     if ($server->Validate($challenge, $response)) {
     	print "Hi master\n";
     }
     else {
     	print "Impostor!\n";
     }

DESCRIPTION
===========

   Authen::Challenge::Basic provides a simple MD5-based challenge/response
protocol allowing for mutual peer authentication in a session. The
protocol includes timing information, so it is possible to introduce time
constraints in the session to help prevent attacks that rely on adjusting
the clock in one of the peers.

   This protocol requires a shared secret to be known only to the peers.
The compromise of this secret also compromises this protocol, so it should
be treated as a trusted password for that matter.

   Challenge/response sessions are not 'replayable' provided that the
attacker ignores the shared secret. The sessions are also associated to
the instance that produced the challenge. This means that it can only be
Validate()'d by the instance that produced the challenge in the first
place.

   The built-in random number generator from perl is used in this module.
Hooks for better random number generators are planned soon to increase the
relative strength of this protocol. In any case, the main security
dependencies for this module are MD5 itself and the secrecy of the shared
secret.

   The following functions are provided by this class.

   new()

   Creates a new instance of a challenge/response endpoint. It has three
parameters that influence its behavior. Those can be seen next

     $server = Authen::Challenge::Basic->new ('Secret' => 'known2us',
     					 'Timeout' => 30,
     					 'Sync' => 10);

   'Secret' is used to indicate the shared secret to use in this session.

   'Timeout' specifies the lifespan, in seconds, for this transaction.
This means that a succesful Validate() must occur within this many seconds
to have a chance to be acknowledged. Reducing this value too much can
cause problems as a slight ammount of load can make the session fail. 30
seconds is a reasonable default for many uses. If left unspecified, no
timeout is enforced.

   'Sync' indicates how strict are we with regard to the clock in our
peer. The parameter contains the maximum offset in seconds between the
clocks of the peers. The more strict we are (ie, the smaller the number),
the less tolerant we are. If left unspecified, we'll allow any ammount of
drift. It's specified in seconds.

   Challenge()

   Issues a new challenge. The object creating this challenge stores
information about it that allows for later recognition and validation.
The Challenge() is a typical function of the server, though a double
Challenge/Response scenario allows mutual authentication such as in the
following scheme:

     Client				Server
     (1)		  C1	---------------------->
     (2)			<----------------------  R(C1), C2
     (3)		R(C2)   ---------------------->

   On stage (2), the Client is authenticated to the server. On stage (3),
both are mutually authenticated.

   This method is usually invoked like

     $challenge = $server->Challenge;

   $challenge will contain a printable string that must be passed to the
peer in order for a response to be received.

   Response()

   This method takes a challenge and generates the required response. This
is usually invoked as

     $response = $client->Response($challenge);

   Where $challenge contains a Challenge generated by a call to
Challenge().  $response will contain a printable string that must be
returned to the peer in order for it to be validated.

   Validate()

   This method verifies the correctness of the Challenge/Response session
by insuring that:

     (a) The challenge was indeed generated from this instance
     and is pending validation
     (b) The time interval for the validation is acceptable
     (c) The shared secret was used by the peer to create the
     response

   Usually this method is invoked like this

     $r = $server->Validate($challenge, $response);

   It returns a true value to indicate a correct session where (a), (b) and
(c) hold true or false otherwise.

CAVEATS
=======

   Note that this module helps insure that the peers were who they said
they where provided that the shared secret is not known to any third
parties.  If this is not true, then anything could happen.

   Also, after the initial authentication, a network connection can be
stolen or hijacked, rendering all of the tests useless.

AUTHOR
======

   Luis E. Munoz <lem@cantv.net>

Frequently-Asked Questions about Authen::PAM.
*********************************************

NAME
====

   pam_faq - Frequently-Asked Questions about Authen::PAM.

SYNOPSIS
========

   perldoc pam_faq

VERSION
=======

   This document is currently at version 0.01, as of *April 21, 2000*

DESCRIPTION
===========

1. Can I authenticate a user non interactively?
-----------------------------------------------

   Yes, you can although not in a very clean way. The PAM library has a
mechanism, in a form of a conversation function, to send and receive text
data from the user. For details of the format of the conversation function
consult the Authen::PAM manual.  This function receives a list of
code/string pairs. There are two codes (PAM_TEXT_INFO and PAM_ERROR_MSG)
for displaying the associated string to the user and two codes
(PAM_ECHO_ON and PAM_ECHO_OFF) for getting input from the user. As you can
see the codes are rather general and you can not be completely sure when
you are asked for a user name and when for a password. However, the common
practice is that PAM_ECHO_ON is used for a user name and PAM_ECHO_OFF is
used for a password. So, what you can do is to write your own conversation
function which ignores the PAM_TEXT_INFO and PAM_ERROR_MSG codes and
returns the user name for the code PAM_ECHO_ON and the password for the
code PAM_ECHO_OFF. If you pass the user name in the initialization function
then usually you will not be asked for it. Here is a simple example how to
do this:

     use Authen::PAM;

     $service = "passwd";
     $username = "foo";
     $password = "bar";

     sub my_conv_func {
       my @res;
       while ( @_ ) {
           my $code = shift;
           my $msg = shift;
           my $ans = "";

     $ans = $username if ($code == PAM_PROMPT_ECHO_ON() );
     $ans = $password if ($code == PAM_PROMPT_ECHO_OFF() );

     push @res, (PAM_SUCCESS(),$ans);
         }
         push @res, PAM_SUCCESS();
         return @res;
       }

     ref($pamh = new Authen::PAM($service, $username, \&my_conv_func)) ||
     	 die "Error code $pamh during PAM init!";

     $pamh->pam_authenticate;

   The Authen::PAM module comes with a default conversation function which
you can find in the file `PAM.pm'.

2. Can I change a password non interactively?
---------------------------------------------

   All the discussion of the previous question also applies here.  There
is however one serious complication. When changing a password it is quite
possible that the PAM library will send you at lest two PAM_ECHO_OFF
prompts - one for the old password and one or two for the new one.
Therefore, the first thing you should do is to see what sequence of
prompts is produced by your service. Then the conversation function should
include some state variable to distinguish the different prompts. Here is
an example:

     use Authen::PAM;

     $service = "passwd";
     $username = "foo";
     $oldpassword = "bar_old";
     $newpassword = "bar_new";

     sub my_conv_func {
       my @res;
       while ( @_ ) {
           my $code = shift;
           my $msg = shift;
           my $ans = "";

     $ans = $username if ($code == PAM_PROMPT_ECHO_ON() );
     if ($code == PAM_PROMPT_ECHO_OFF() ) {
       $ans = $oldpassword if ($state == 0);
       $ans = $newpassword if ($state == 1);
       $ans = $newpassword if ($state == 2);

     $state++;
             }

     push @res, (PAM_SUCCESS(),$ans);
         }
         push @res, PAM_SUCCESS();
         return @res;
       }

     ref($pamh = new Authen::PAM($service, $username, \&my_conv_func)) ||
     	 die "Error code $pamh during PAM init!";

     $state = 0;
     $pamh->pam_chauthtok;

     =head2 3. Is there a conversation function which translates the PAM
     requests to HTML form?

   So far I am not aware of any. However if you known that there exists or
want to write one you can contact me.

   The idea of implementing such web interface is that when the
conversation function is called it constructs a HTML page from the input
codes and strings. The major problem with this approach is that the HTTP
protocol is stateless. To overcome this difficulty you should write some
daemon program which interacts with the PAM library and keeps the current
state of the conversation.

SEE ALSO
========

   Authen-PAM

AUTHOR
======

   Nikolay Pelov nikip@iname.com

COPYRIGHT
=========

   Copyright (c) 1998-2000 Nikolay Pelov. All rights reserved. This file
is part of the Authen::PAM library. This library is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

Perl extension for Kerberos 4
*****************************

NAME
====

   Authen::Krb4 - Perl extension for Kerberos 4

SYNOPSIS
========

   use Authen::Krb4;

DESCRIPTION
===========

   Authen::Krb4 is an object oriented extension to Perl 5 which implements
several user-level Kerberos 4 functions.  With this module, you can create
Kerberized clients and servers written in Perl.  It is compatible with
both AFS and MIT Kerberos.

VARIABLES & FUNCTIONS
---------------------

   NOTE: No methods or variables are exported, so each variable and
function should be preceded by 'Authen::Krb4::'

error
     Contains the error code of the most recent Kerberos function call.

get_phost(alias)
     Returns the instance name of the host 'alias'

get_lrealm(n)
     Returns the nth realm of the host machine.  n is zero by default.

realmofhost(host)
     Returns the realm of the machine 'host'.

mk_req(service,instance,realm,checksum)
     Returns an Authen::Krb4::Ticket object for the specified service,
     instance, and realm.  It will return undef if there was an error.

rd_req(ticket,service,instance,fn)
     Returns an Authen::Krb4::AuthDat object, which contains information
     obtained from the ticket, or undef upon failure.  Ticket is a
     variable of the class Authen::Krb4::Ticket, which can be obtained
     from mk_req().  fn is a path to the appropriate srvtab.  /etc/srvtab
     will be used if fn is null.

get_cred(service,instance,realm)
     Search the caller's ticket file for a ticket for the service and
     instance in the given realm.  Returns a Authen::Krb4::Creds object,
     or undef upon failure.  This method can be used to extract a ticket's
     session key.

get_key_sched(session)
     Returns the key schedule for the session key 'session', which can be
     obtained from rd_req() or get_cred().  The key schedule is an
     Authen::Krb4::KeySchedule object.

mk_priv(in,schedule,key,sender,receiver)
     Encrypts the data stored in 'in' and returns the encrypted data.
     sender and receiver should be in standard internet format, which can
     be achieved using the inet_aton and sockaddr_in functions in the
     Socket module.

rd_priv(in,schedule,key,sender,receiver)
     Decrypts the variable 'in' and returns the original data.  Other
     parameters are as described in mk_priv()

sendauth(options,fh,service,inst,realm,checksum,laddr,faddr,version)
     Obtains a ticket for the specified service, instance, and realm, and
     writes it to the socket 'fh'.  Use recvauth to read the ticket on the
     server.  'laddr' is the packed network address of the client, and
     'faddr' is the packed network address of the server.  'options' can
     be any of the following:

          Authen::Krb4::KOPT_DONT_MK_REQ
          Authen::Krb4::KOPT_DO_MUTUAL
          Authen::Krb4::KOPT_DONT_CANON

     Use KOPT_DO_MUTUAL if you plan to do any encryption.  This function
     returns a list containing the service ticket, the credentials, and
     the key schedule.

recvauth(options,fh,service,inst,faddr,laddr,fn)
     Reads a ticket/authenticator pair from the socket 'fh'.  'options'
     can be set as described above.  'faddr' is the packed network address
     of the client, and 'laddr' is the packed network address of the
     server.  This function returns a list containing the ticket, an
     AuthDat object, the key schedule, and the version string.

get_pw_in_tkt(user,inst,realm,service,srealm,lifetime,password)
     Tries to get an initial ticket for 'user' using 'password'.  This
     function is especially useful for verifying a user's password. See
     the Kerberos documentation for details.

get_svc_in_tkt(user,inst,realm,service,srealm,lifetime,srvtab)
     Tries to get an initial ticket for 'user' using the private key
     stored in 'srvtab'.

read_service_key(user,inst,realm,kvno,srvtab)
     Extracts the private key from a srvtab and returns it.  Use a kvno of
     0 to extract the first matching entry.

dest_tkt()
     Destroys the ticket file, much like kdestroy.

get_err_txt(n)
     Returns a string containing a textual description of the kerberos
     error number n.

CLASSES & METHODS
-----------------

   There are four classes in the Authen::Krb4 module, Ticket, AuthDat,
Creds, and KeySchedule.  They are all simply abstractions of Kerberos 4
structures.  You almost never need to worry about creating new objects-the
functions which return these objects create them for you (is this the best
thing to do?).  The one exception is when you need to construct a Ticket
object for rd_req().  See below for details.

Ticket
     Contains a ticket for a specified service, instance, and realm.

new(dat)
     Returns a new Ticket object containing the data in 'dat'.  You must
     create a new Ticket object on the server side for passing to rd_req().

dat
     The data contained in the ticket.  Looks like junk to the naked eye.

length
     The length of the data contained in 'dat'.

AuthDat
     Contains the contents of the AUTH_DAT structure returned by rd_req().
     See below for the goodies.

pname
     Returns the principal's name.

pinst
     Returns the principal's instance.

prealm
     Returns the principal's realm.

session
     The session key.  Pass this to get_key_sched() to obtain a key
     schedule for encryption.

k_flags
     Flags from the ticket.

checksum
     The checksum from the ticket.  See mk_req().

life
     Life of the ticket.

time_sec
     The time the ticket was issued.  localtime() can convert this to a
     nicer format.

address
     The address in the ticket.  Useful for mutual authentication.

reply
     Reply to send to the client (not implemented yet).

Creds
     Contains information retreived from your ticket file.

service
     The service name.

instance
     The instance

realm
     The realm

session
     Returns the session key.  Pass this to get_key_sched() to obtain a key
     schedule for encryption.

lifetime
     The lifetime of the ticket.

kvno
     The key version number.

ticket
     The ticket itself.

issue_date
     The date the ticket was issued.

pname
     The name of the principal.

pinst
     The instance of the principal.

KeySchedule
     You don't need to fool around with this.

AUTHOR
======

   Jeff Horwitz <jeff@smashing.org>

SEE ALSO
========

   perl(1).

Perl extension for Kerberos 5
*****************************

NAME
====

   Authen::Krb5 - Perl extension for Kerberos 5

SYNOPSIS
========

   use Authen::Krb5;

   Authen::Krb5::init_context(); Authen::Krb5::init_ets();

DESCRIPTION
===========

   Authen::Krb5 is an object oriented interface to the Kerberos 5 API.
Both the implementation and documentation are nowhere near complete, and
may require previous experience with Kerberos 5 programming.  Most of the
functions here are documented in detail in the Kerberos 5 API
documentation.

FUNCTIONS
---------

error(n)
     Returns the error code from the most recent Authen::Krb5 call.  If
     provided with an error code 'n', this function will return a textual
     description of the error.

init_context()
     Initializes a context for the application.  Returns a
     Authen::Krb5::Context object, or undef if there was an error.  Should
     be called along with init_ets at the beginning of a script.

init_ets()
     Initializes the Kerberos error tables.  Should be called along with
     init_context at the beginning of a script.

get_default_realm()
     Returns the default realm of your host.

get_host_realm(host)
     Returns the realm of the specified host.

get_krbhst(realm)
     Returns a list of the Kerberos servers from the specified realm.

build_principal_ext(p)
     Not like the actual krb5_build_principal_ext.  This is legacy code
     from Malcolm's code, which I'll probably change in future releases.
     In any case, it creates a 'server' principal for use in getting a
     TGT.  Pass it the principal for which you would like a TGT.

parse_name(name)
     Converts a string representation of a principal to a principal
     object.  You can use this to create a principal from your username.

sname_to_principal(hostname,sname,type)
     Generates a server principal from the given hostname, service, and
     type.  Type can be one of the following: NT_UNKNOWN, NT_PRINCIPAL,
     NT_SRV_INST, NT_SRV_HST, NT_SRV_XHST, NT_UID.  See the Kerberos
     documentation for details.

cc_resolve(name)
     Returns a credentials cache identifier which corresponds to the given
     name.  'name' must be in the form TYPE:RESIDUAL.  See the Kerberos
     documentation for more information.

cc_default_name()
     Returns the name of the default credentials cache, which may be
     equivalent to KRB5CCACHE.

cc_default()
     Returns a Authen::Krb5::Ccache object representing the default
     credentials cache.

kt_resolve(name)
     Returns a Authen::Krb5::Keytab object representing the specified
     keytab name.

get_in_tkt_with_password(client,server,password,cc)
     Attempt to get an initial ticket for the client.  'client' is a
     principal object for which you want an initial ticket.  'server' is a
     principal object for the service (usually krbtgt/REALM@REALM).
     'password' is the password for the client, and 'cc' is a
     Authen::Krb5::Ccache object representing the current credentials
     cache.  Returns a Kerberos error code.

mk_req(auth_context,ap_req_options,service,hostname,in,cc)
     Obtains a ticket for a specified service and returns a KRB_AP_REQ
     message suitable for passing to rd_req.  'auth_context' is the
     Authen::Krb5::AuthContext object you want to use for this connection,
     'ap_req_options' is an OR'ed representation of the possible options
     (see Kerberos docs), 'service' is the name of the service for which
     you want a ticket (like 'host'), hostname is the hostname of the
     server, 'in' can be any user-specified data that can be verified at
     the server end, and 'cc' is your credentials cache object.

rd_req(auth_context,in,server,keytab)
     Parses a KRB_AP_REQ message and returns its contents in a
     Authen::Krb5::Ticket object.  'auth_context' is the connection's
     Authen::Krb5::AuthContext object, 'in' is the KRB_AP_REQ message
     (usually from mk_req), and server is the expected server's name for
     the ticket.  'keytab' is a Authen::Krb5::Keytab object for the keytab
     you want to use.  Specify 'undef' or leave off to use the default
     keytab.

mk_priv(auth_context,in)
     Encrypts 'in' using parameters specified in auth_context, and returns
     the encrypted data.  Requires use of a replay cache.

rd_priv(auth_context,in)
     Decrypts 'in' using parameters specified in auth_context, and returns
     the decrypted data.

sendauth(auth_context,fh,version,client,server,options,in,in_creds,cc)
     Obtains and sends an authenticated ticket from a client program to a
     server program using the filehandle 'fh'.  'version' is an
     application-defined version string that recvauth compares to its own
     version string.  'client' is the client principal, e.g.
     username@REALM.  'server' is the service principal to which you are
     authenticating, e.g. service.hostname@REALM.  The only useful option
     right now is AP_OPTS_MUTUAL_REQUIRED, which forces sendauth to
     perform mutual authentication with the server.  'in' is a string that
     will be received by recvauth and verified by the server-it's up to the
     application.  'in_creds' is not yet supported, so just use 'undef'
     here.  'cc' should be set to the current credentials cache.  sendauth
     returns true on success and undefined on failure.

recvauth(auth_context,fh,version,server,keytab)
     Receives authentication data from a client using the sendauth
     function through the filehandle 'fh'.  'version' is as described in
     the sendauth section.  'server' is the server principal to which the
     client will be authenticating.  'keytab' is a Authen::Krb5::Keytab
     object specifying the keytab to use for this service.  recvauth
     returns a Authen::Krb5::Ticket object on success or undefined on
     failure.

genaddrs(auth_context,fh,flags)
     Uses the open socket filehandle 'fh' to generate local and remote
     addresses for auth_context.  Flags should be one of the following,
     depending on the type of address you want to generate (flags can be
     OR'ed):

     KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR
     KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR
     KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR
     KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR

gen_portaddr(addr,port)
     Generates a local port address that can be used to name a replay
     cache.  'addr' is a Authen::Krb5::Address object, and port is a port
     number in network byte order.  For generateing a replay cache name,
     you should supply the local address of the client and the socket's
     local port number.  Returns a Authen::Krb5::Address object containing
     the address.

gen_replay_name(addr,string)
     Generate a unique replay cache name.  'addr' is a
     Authen::Krb5::Address object created by gen_portaddr.  'string' is
     used as a unique identifier for the replay cache.  Returns the replay
     cache name.

get_server_rcache(name)
     Returns a Authen::Krb5::Rcache object using the replay cache name
     'name.'

CLASSES & METHODS
-----------------

Authen::Krb5::Principal
     Kerberos 5 princpal object.

    o realm
          Returns the realm of the principal.

    o type
          Returns the type of the principal.

    o data
          Returns a list containing the components of the principal
          (everything before the realm).

Authen::Krb5::Ccache
     Kerberos 5 credentials cache object.

    o initialize(p)
          Creates/refreshes a credentials cache for the primary principal
          'p'.  If the cache already exists, its contents are destroyed.

    o get_name
          Returns the name of the credentials cache.

    o get_principal
          Returns the primary principal of the credentials cache.

    o destroy
          Destroys the credentials cache and releases all resources it
          used.

Authen::Krb5::AuthContext
     Kerberos 5 auth_context object.

    o new
          Allocates memory for a new Authen::Krb5::AuthContext object and
          returns it.

    o setaddrs(localaddr,remoteaddr)
          Sets the local and remote addresses for the AuthContext object.
          'localaddr' and 'remoteaddr' are Authen::Krb5::Address objects,
          usually of type ADDRTYPE_INET.

    o getaddrs()
          Returns a list containing the local and the remote address of the
          AuthContext object.

    o setrcache(rc)
          Sets the replay cache for auth_context.  'rc' is a
          Authen::Krb5::Rcache object generated by get_server_rcache.

Authen::Krb5::Ticket
     Kerberos 5 ticket object.

    o server
          Returns the server stored in the ticket.

    o enc_part2
          Returns a Authen::Krb5::EncTktPart object representation of the
          ticket data.  See below.

Authen::Krb5::EncTktPart
     Object representation of the krb5_enc_tkt_part structure.

    o client
          The client principal contained in the ticket.

AUTHOR
======

   Jeff Horwitz (jeff@laserlink.net)

ACKNOWLEDGEMENTS
================

   Based on the original work by Doug MacEachern and Malcolm Beattie.  Code
contributions from Scott Hutton (shutton@indiana.edu).

SEE ALSO
========

   perl(1), kerberos(1).

access to Wietse Venema's TCP Wrappers library
**********************************************

NAME
====

   Authen::Libwrap - access to Wietse Venema's TCP Wrappers library

SYNOPSIS
========

     use Authen::Libwrap qw( hosts_ctl STRING_UNKNOWN );

     # we know the remote username (using identd)
     $rc = hosts_ctl(	"programname",
     			"hostname.domain.com",
     			"10.1.1.1",
     			"username" );
     );
     print "Access is ", $rc ? "granted" : "refused", "\n";

     # we don't know the remote username
     $rc = hosts_ctl(	"programname",
     			"hostname.domain.com",
     			"10.1.1.1",
     			STRING_UNKNOWN );
     );
     print "Access is ", $rc ? "granted" : "refused", "\n";

DESCRIPTION
===========

   The Authen::Libwrap module allows you to access the hosts_ctl()
function from the popular TCP Wrappers security package.  This allows
validation of network access from perl programs against the system-wide
`hosts.allow' file.

   If any of the parameters to hosts_ctl() are not known (i.e. username
due to lack of an identd server), the constant STRING_UNKNOWN should be
passed to the function.

EXPORTS
=======

     Nothing unless you ask for it.

     hosts_ctl( $daemon, $hostname, $ip_address, $username );

CONSTANTS
=========

     STRING_UNKNOWN

BUGS
====

   Calls to hosts_ctl() which a line in `hosts.allow' that uses the "twist"
option will terminate the running perl program.  This is not a bug in
Authen::Libwrap per se - libwrap uses exec(3) to replace the running
process with the specified program, so there's nothing to return to.

   Some operating systems ship with a default catch-all rule in
`hosts.allow' that uses the twist option.  You may have to modify this
configuration to use Authen::Libwrap effectively.

AUTHOR
======

   James FitzGibbon, <james@ehlo.com>

SEE ALSO
========

   perl(1), hosts_access(3), hosts_access(5), hosts_options(5)

Perl interface to PAM library
*****************************

NAME
====

   Authen::PAM - Perl interface to PAM library

SYNOPSIS
========

     use Authen::PAM;

     $res = pam_start($service_name, $user, $pamh);
     $res = pam_start($service_name, $user, \my_conv_func, $pamh);
     $res = pam_end($pamh, $pam_status);

     $res = pam_authenticate($pamh, $flags);
     $res = pam_setcred($pamh, $flags);
     $res = pam_acct_mgmt($pamh, $flags);
     $res = pam_open_session($pamh, $flags);
     $res = pam_close_session($pamh, $flags);
     $res = pam_chauthtok($pamh, $flags);

     $error_str = pam_strerror($pamh, $errnum);

     $res = pam_set_item($pamh, $item_type, $item);
     $res = pam_get_item($pamh, $item_type, $item);

     if (HAVE_PAM_ENV_FUNCTIONS()) {
         $res = pam_putenv($pamh, $name_value);
         $val = pam_getenv($pamh, $name);
         %env = pam_getenvlist($pamh);
     }

     if (HAVE_PAM_FAIL_DELAY()) {
         $res = pam_fail_delay($pamh, $musec_delay);
         $res = pam_set_item($pamh, PAM_FAIL_DELAY(), \my_fail_delay_func);
     }

DESCRIPTION
===========

   The *Authen::PAM* module provides a Perl interface to the *PAM*
library. The only difference with the standard PAM interface is that
instead of passing a pam_conv struct which has an additional context
parameter appdata_ptr, you must only give an address to a conversation
function written in Perl (see below).  If you use the 3 argument version
of pam_start then a default conversation function is used
(Authen::PAM::pam_default_conv).

   The $flags argument is optional for all functions which use it except
for pam_setcred. The $pam_status argument is also optional for pam_end
function. Both of these arguments will be set to 0 if not given.

   The names of some constants from the PAM library have changed over the
time. You can use any of the known names for a given constant although it
is advisable to use the latest one.

   When this module supports some of the additional features of the PAM
library (e.g. pam_fail_delay) then the corresponding HAVE_PAM_XXX constant
will have a value 1 otherwise it will return 0.

   For compatibility with older PAM libraries I have added the constant
HAVE_PAM_ENV_FUNCTIONS which is true if your PAM library has the functions
for handling environment variables (pam_putenv, pam_getenv,
pam_getenvlist).

Object Oriented Style
---------------------

   If you prefer to use an object oriented style for accessing the PAM
library here is the interface:

     use Authen::PAM qw(:constants);

     $pamh = new Authen::PAM($service_name, $user);
     $pamh = new Authen::PAM($service_name, $user, \my_conv_func);

     ref($pamh) || die "Error code $pamh during PAM init!";

     $res = $pamh->pam_authenticate($flags);
     $res = $pamh->pam_setcred($flags);
     $res = $pamh->pam_acct_mgmt($flags);
     $res = $pamh->pam_open_session($flags);
     $res = $pamh->pam_close_session($flags);
     $res = $pamh->pam_chauthtok($flags);

     $error_str = $pamh->pam_strerror($errnum);

     $res = $pamh->pam_set_item($item_type, $item);
     $res = $pamh->pam_get_item($item_type, $item);

     $res = $pamh->pam_putenv($name_value);
     $val = $pamh->pam_getenv($name);
     %env = $pamh->pam_getenvlist;

   The constructor new will call the pam_start function and if successfull
will return an object reference. Otherwise the $pamh will contain the
error number returned by pam_start.  The pam_end function will be called
automatically when the object is no longer referenced.

Examples
--------

   Here is an example of using PAM for changing the password of the current
user:

     use Authen::PAM;

     $login_name = getpwuid($<);

     pam_start("passwd", $login_name, $pamh);
     pam_chauthtok($pamh);
     pam_end($pamh);

   or the same thing but using OO style:

     $pamh = new Authen::PAM("passwd", $login_name);
     $pamh->pam_chauthtok;
     $pamh = 0;  # Force perl to call the destructor for the $pamh

Conversation function format
----------------------------

   When starting the PAM the user must supply a conversation function.  It
is used for interaction between the PAM modules and the user. The argument
of the function is a list of pairs ($msg_type, $msg) and it must return a
list with the same number of pairs ($resp_retcode, $resp) with replies to
the input messages. For now the $resp_retcode is not used and must be
always set to 0. In addition the user must append to the end of the
resulting list the return code of the conversation function (usually
PAM_SUCCESS).

   Here is a sample form of the PAM conversation function:

     sub my_conv_func {
         my @res;
         while ( @_ ) {
             my $msg_type = shift;
             my $msg = shift;

     print $msg;

     # switch ($msg_type) { obtain value for $ans; }

     push @res, (0,$ans);
           }
           push @res, PAM_SUCCESS();
           return @res;
       }

COMPATIBILITY
=============

   This module was tested with the following versions of the Linux-PAM
library: 0.50, 0.56, 0.59 and 0.65.

   The following constant names: PAM_AUTHTOKEN_REQD, PAM_CRED_ESTABLISH,
PAM_CRED_DELETE, PAM_CRED_REINITIALIZE, PAM_CRED_REFRESH are used by some
older version of the Linux-PAM library and are not exported by default. If
you really want them, then load the module with

     use Authen::PAM qw(:DEFAULT :old);

   This module still does not support some of the new Linux-PAM functions
such as pam_system_log.

SEE ALSO
========

   PAM Application developer's Manual

AUTHOR
======

   Nikolay Pelov nikip@iname.com

COPYRIGHT
=========

   Copyright (c) 1998-2000 Nikolay Pelov. All rights reserved. This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Create and verify strong PIN numbers
************************************

NAME
====

   Authen::PIN - Create and verify strong PIN numbers

SYNOPSIS
========

     use Authen::PIN;

     my $pinset = new Authen::PIN ('PPPCCP123HHHHHHHV',
     				$start 		# Optional
     				);

     $pinset->set($start);		# Preferred
     $pinset->inc($inc);
     $pinset->pin($pass_through, $serial);

   # OR

     $pinset->pin($serial);	# undef $pass_through

DESCRIPTION
===========

   This module provides an interface to create crypto-strong PIN numbers
for applications such as calling cards that require a number that is
difficult to guess and that might convey hidden information.

   It is based on templates, that define how the resulting PIN number will
be constructed by combining the following components:

*Pass through values*
     This is represented in the template with the letter 'P'. It is copied
     as is to the resulting PIN. Digits are passed to the template from
     left to right. If the supplied value in the call to `->pin' is too
     short, it will be left-padded with zeros.

Counters
     Represented in the template with the letter 'C'. This is a regular
     counter that starts at the value passed to `->set' or $start (if
     specified) and is incremented for each call to `->pin' by whatever
     value was passed to `->inc' (or 1 by default).

Hashes
     These are represented by the letter 'H'. When calling `->pin($pass,
     $serial)', the concatenation of `$pass' and `$serial' are passed
     through the MD5 function and the result converted to a string of
     digits. This string is replaced, from left to right, into the
     supplied template. There is a limit in the number of digits that a
     hash can generate. Using more than 20 or so digits is discouraged as
     this might result in PIN numbers that are not strong enough. In
     practice, a PIN number with such a large number of digits is probably
     of little use.

*Verification digit*
     It is represented with the 'V' character in the template. When found,
     a checksum of the PIN constructed so far will be calculated and placed
     at the current position. This is usually used as the last digit in the
     PIN template, to allow for a digit that allows for the simple discard
     of bogus PIN number, avoiding more expensive database operations in a
     complete application. The algorythm used for this checksum, is the
     same used by credit cards, as implemented by Business::Creditcard.

*Literal digits*
     Digits in the range 0-9 are copied to the resulting PIN.

AUTHOR
======

   Luis E. Munoz <lem@cantv.net>

CHANGES
=======

  1. Fri Jan 12 15:51:03 2001     original version; created by h2xs 1.19

  2. Thu Mar 01 18:15:00 2001     modified to use Number::Encode to
     achieve a more robust PIN digit     distribution

WARRANTY
========

   This code has the same warranty that Perl itself.

SEE ALSO
========

   perl(1), Digest::MD5.

Perl extension for accessing protected password database
********************************************************

NAME
====

   Authen::Prot - Perl extension for accessing protected password database

SYNOPSIS
========

     use Authen::Prot;

     Authen::Prot::setprpwent();

     $pw = Authen::Prot->getprpwent();

     $pw = Authen::Prot->getprpwuid(0);

     $pw = Authen::Prot->getprpwnam('daemon');

     print "$pw->ufld_fd_name\n";

     $pw->ufld_fd_slogin(time);

     $pw->putprpwnam();

     $crypt = Authen::Prot::bigcrypt('test', 'test'); # not avail on DEC/OSF

     Authen::Prot::endprpwent();

DESCRIPTION
===========

   The Authen::Prot module provides access to the protected password
database via the getprpwent, getprpwuid, getprpwnam, getprpwaid,
setprpwent, endprpwent, and putprpwnam system calls available on those
Unix systems using the Protected Password database written by SecureWare
Inc. (c).

METHODS
-------

   The availability of some of the methods below will depend on how the
Protected Password database has been implemented on your system.

$crypt = Authen::Prot::bigcrypt($key, $salt)
     Encrypted $key using the bigcrypt(3) system call if available and
     returns the result. Not available on DEC/OSF, via this package yet.

$pw = Authen::Prot::getprpwent()
     This method returns a reference to a blessed Authen::Prot object.  You
     may then use this reference to retrieve values of fields in the
     protected password database. When this method is first called it
     returns the first entry in the database, on each subsequent call it
     returns the next entry. See getprpwent(3) for further information on
     which records are returned.

$pw = Authen::Prot::getprpwuid($uid)
     This method returns a reference to a blessed Authen::Prot object if an
     entry with a uid of that passed is found, otherwise it will return
     undef.  You may then use this reference to retrieve values of fields
     in the protected password database.  See getprpwuid(3) for further
     information on how records are returned.

$pw = Authen::Prot::getprpwaid($aid)
     This method returns a reference to a blessed Authen::Prot object if an
     entry with a aid of that passed is found, otherwise it will return
     undef.  You may then use this reference to retrieve values of fields
     in the protected password database.  See getprpwaid(3) for further
     information on how records are returned.

$pw = Authen::Prot::getprpwnam($name)
     This method returns a reference to a blessed Authen::Prot object if an
     entry with a login name of that passed is found, otherwise it will
     return undef.  You may then use this reference to retrieve values of
     fields in the protected password database.  See getprpwnam(3) for
     further information on how records are returned.

Authen::Prot::setprpwent()
     Calling setprpwent effectively rewinds the pointer into the protected
     password databases so that a subsequent call to getprpwent will return
     the first record.  See setprpwent(3) for further information on the
     function of this method.

Authen::Prot::endprpwent()
     Calling endprpwent effectively closes the protected password database.
     See endprpwent(3) for further information on the function of this
     method.

$pw->putprpwnam()
     This method commits a Prot object to the protected password database.
     Setting $pw->uflg_fg_name to 0 will delete the corresponding entry.
     See putprpwnam(3) for further information on the function of this
     method.

$pw->pr_struct_field_name() / $pw->pr_struct_field_name($value)
     The fields available from the methods described above, depend on the
     definition of the pr_struct structure in the `/usr/include/prot.h' on
     your system, and the information available I have to interpret them.
     This module will attempt to parse your `prot.h' file and generate a XS
     function for each field available on your system.  The pr_struct
     typically consists of four structures given the name of ufld, sfld,
     uflg and sflg for User fields, System fields, User flags and System
     flags respectively.

     To allow for the syntax differences between C and Perl the field names
     have been re-written replacing the struct . with a _ in Perl.  For
     example the User field login name would be referenced

     in C as:

          ufld.fd_name

     and in Perl as:

          $pw->ufld_fd_name

COPYRIGHT
=========

   The Protected Password database library by SecureWare Inc. (c) is
classified as containing Confidential information so I am unable to
include the field descriptions in this document.  Please refer to the man
pages referenced below and to the `/usr/include/prot.h' header file for
further information.

EXAMPLES
========

   The test.pl file provides examples of the methods available via this
extension common to most platforms.

AUTHOR
======

   Paul Gampe <paulg@apnic.net>.

   I would appreciate it if you could send me an email if you starting
using this package, so I can notify you of updates, and get an idea of
what platforms it is compatible with.

FILES
=====

   `/usr/include/prot.h'

COPYRIGHT
=========

   Copyright (c) 1997-98 Paul Gampe. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

   IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

   THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS
PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO
OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.

SEE ALSO
========

   getprpwent(3), getprpwuid(3), getprpwnam(3), getprpwaid(3),
setprpwent(3), endprpwent(3), putprpwnam(3), perl(1).

SASL Authentication base class
******************************

NAME
====

   Authen::SASL - SASL Authentication base class

SYNOPSIS
========

     use Authen::SASL;

     $sasl = Authen::SASL->new('CRAM-MD5', password => $pass);

DESCRIPTION
===========

   SASL is a generic mechanism for authentication used by several network
protocols. *Authen::SASL* provides an implementation that all protocols
should be able to share.

   There are many different encryption methods that can be used with SASL.
These are implemented as sub-classes of *Authen::SASL*.  For example the
package that implements the CRAM-MD5 SASL is called
Authen::SASL::CRAM_MD5. Note that the - is eplaced with an _.
Authen::SASL::CRAM_MD5 also inherits from *Authen::SASL*.  This means that
the following two statements give identical results

     $sasl = Authen::SASL->new('CRAM-MD5', password => $pass);

     $sasl = Authen::SASL::CRAM_MD5->new(password => $pass);

   the difference being that the frst one will load the
Authen::SASL::CRAM_MD5 package for you when this code is run for the first
time. If you use the second method then you must require the package
yourself.

METHODS
=======

SEE ALSO
========

   `Authen::SASL::CRAM_MD5|Authen::SASL::CRAM_MD5' in this node

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

   Please report any bugs, or post any suggestions, to the perl-ldap
mailing list <perl-ldap-dev@lists.sourceforge.net>

COPYRIGHT
=========

   Copyright (c) 1998-2000 Graham Barr. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Perl extension to authenticate against an SMB server
****************************************************

NAME
====

   Authen::Smb - Perl extension to authenticate against an SMB server

SYNOPSIS
========

     use Authen::Smb;
     my $authResult = Authen::Smb::authen('myUser',
                                          'myPassword',
                                          'myPDC',
                                          'myBDC',
                                          'myNTDomain');

     if ( $authResult == Authen::Smb::NO_ERROR ) {
       print "User successfully authenticated.\n";
     } else {
       print "User not authenticated with error level $authResult\n";
     }

DESCRIPTION
===========

   Authen::Smb allows you to authenticate a user against an NT domain.
You can specify both a primary and a backup server to use for
authentication.  The NT names of the machines should be used for
specifying servers.

   An authentication request will return one of four values:

   NTV_NO_ERROR (0) NTV_SERVER_ERROR (1) NTV_PROTOCOL_ERROR (2)
NTV_LOGON_ERROR (3)

   NTV_NO_ERROR is the only return value possible for a successful
authentication.  All other return values indicate failure, of one sort or
another.

EXPORT_OK constants
===================

     NTV_LOGON_ERROR
     NTV_NO_ERROR
     NTV_PROTOCOL_ERROR
     NTV_SERVER_ERROR

AUTHOR
======

   Patrick Michael Kane, modus@pr.es.to Based on the smbval library from
the samba package

SEE ALSO
========

   perl(1).

Perl extension for authentication using tacacs+ server
******************************************************

NAME
====

   Authen::TacacsPlus - Perl extension for authentication using tacacs+
server

SYNOPSIS
========

     use Authen::TacacsPlus;

     $tac = new Authen::TacacsPlus(Host=>$server,
     			Key=>$key,
     			[Port=>'tacacs'],
     			[Timeout=>15]);

     $tac->authen($username,$passwords);

     Authen::TacacsPlus::errmsg();

     $tac->close();

DESCRIPTION
===========

   Authen::TacacsPlus allows you to authenticate using tacacs+ server.

     $tac = new Authen::TacacsPlus(Host=>$server,
      	                Key=>$key,
                           [Port=>'tacacs'],
                           [Timeout=>15]);

   Opens new session with tacacs+ server on host $server, encrypted with
key $key. Undefined object is returned if something wrong (check errmsg()).

     Authen::TacacsPlus::errmsg();

   Returns last error message.

     $tac->authen($username,$password,$authen_type);

   Tries an authentication with $username and $password. 1 is returned if
authenticaton succeded and 0 if failed (check errmsg() for reason).

   $authen_type is an optional argument that specifies what type of
authentication to perform. Allowable options are:
Authen::TacacsPlus::TAC_PLUS_AUTHEN_TYPE_ASCII (default)
Authen::TacacsPlus::TAC_PLUS_AUTHEN_TYPE_PAP
Authen::TacacsPlus::TAC_PLUS_AUTHEN_TYPE_CHAP

   ASCII uses Tacacs+ version 0, and will authenticate against the "login"
or "global" password on the Tacacs+ server. If no authen_type is
specified, it defaults to this type of authentication.

   PAP uses Tacacs+ version 1, and will authenticate against the "pap" or
"global" password on the Tacacs+ server.

   CHAP uses Tacacs+ version 1, and will authenticate against the "chap"
or "global" password on the Tacacs+ server. With CHAP, the password if
formed by the concatenation of   chap id + chap challenge + chap response

   Ther is example code in test.pl

     $tac->close();

   Closes session with tacacs+ server.

EXAMPLE
=======

     use Authen::TacacsPlus;

     $tac = new Authen::TacacsPlus(Host=>'foo.bar.ru',Key=>'9999');
     unless ($tac){
             print "Error: ",Authen::TacacsPlus::errmsg(),"\n";
             exit(1);
     }
     if ($tac->authen('john','johnpass')){
             print "Granted\n";
     } else {
             print "Denied: ",Authen::TacacsPlus::errmsg(),"\n";
     }
     $tac->close();

AUTHOR
======

   Mike Shoyher, msh@corbina.net, msh@apache.lexa.ru

   Mike McCauley, mikem@open.com.au

BUGS
====

   only authentication is supported

   only one session may be active (you have to close one session before
opening another one)

SEE ALSO
========

   perl(1).

Perl extension for implementing ticket authentication
*****************************************************

NAME
====

   Authen::Ticket - Perl extension for implementing ticket authentication

SYNOPSIS
========

     PerlHandler Authen::Ticket

   or

     PerlAccessHandler Authen::Ticket
     ErrorDocument     403  http://ticket.tamu.edu/TicketMaster/

DESCRIPTION
===========

   Authen::Ticket provides the mod_perl framework for using the
Authen::Ticket::Server and Authen::Ticket::Client classes as Apache
handlers.

   To create custom handlers, derive a class (My::Authen) from
Authen::Ticket:

     package My::Authen;
     use vars (qw/@ISA/);
     @ISA = (qw/Authen::Ticket/);

   In addition to My::Authen, the server and client classes are also
required:

     package My::Authen::Server;
     use vars (qw/@ISA/);
     @ISA = (qw/Authen::Ticket::Server/);

     sub authenticate {
       my($self, $u) = @_;
       my $t = { };

     # do stuff
     return $t;   # hash ref to ticket contents
       }

     package My::Authen::Client;
     use vars (qw/@ISA/);
     @ISA = (qw/Authen::Ticket::Client/);

   See the documentation for each of Authen::Ticket::Server and
Authen::Ticket::Client for a list of methods that may be implemented.

AUTHOR
======

   James G. Smith <jgsmith@tamu.edu>

COPYRIGHT
=========

   Copyright (c) 1999, Texas A&M University.  All rights reserved.

   Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

     1. Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
     2. Redistributions in binary form must reproduce the above
        copyright notice, this list of conditions and the following
        disclaimer in the documentation and/or other materials
        provided with the distribution.
     3. Neither the name of the University nor the names of its
        contributors may be used to endorse or promote products
        derived from this software without specific prior written
        permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTERS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

SEE ALSO
========

   perl(1), Authen::Ticket::Client(3), Authen::Ticket::Server(3).

Authentication code for the client website
******************************************

NAME
====

   Authen::Ticket::Client - Authentication code for the client website

DESCRIPTION
===========

   Authen::Ticket::Client contains the basic tools required to decode and
reconstruct the information in a ticket.  See Authen::Ticket for the
mod_perl access handler using Authen::Ticket::Client.

METHODS
=======

decode_cookie($class, $ticket)
     This subroutine returns the decoded version of the ticket.  This is
     the place to put decryption of the cookie or other checks that do not
     depend on understanding the information within the ticket.  The
     default version decodes from base 64.  The return value is the decoded
     string representation of the ticket.

deconstruct_cookie($class, $ticket)
     This subroutine breaks the ticket apart into field values.  The return
     value is a hash reference containing the key/value pairs.  This
     subroutine should only be concerned with ensuring a properly
     constructed ticket.

initialize()
     This subroutine may be used to perform particular class initialization
     beyond the defaults provided by Ticket::Authen::Client->new.  Any
     configuration variables for the httpd configuration file should be
     placed in the %__PACKAGE__::DEFAULTS hash.

AUTHOR
======

   James G. Smith, <jgsmith@tamu.edu>

COPYRIGHT
=========

   Copyright (c) 1999, Texas A&M University.  All rights reserved.

   Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

     1. Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
     2. Redistributions in binary form must reproduce the above
        copyright notice, this list of conditions and the following
        disclaimer in the documentation and/or other materials
        provided with the distribution.
     3. Neither the name of the University nor the names of its
        contributors may be used to endorse or promote products
        derived from this software without specific prior written
        permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTERS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

SEE ALSO
========

   perl(1), Authen::Ticket(3), Authen::Ticket::Server(3)

Perl extension for implementing ticket authentication.
******************************************************

NAME
====

   Authen::Ticket::Server - Perl extension for implementing ticket
authentication.

DESCRIPTION
===========

   Authen::Ticket::Server is an abstract class which provides the skeleton
upon which a full ticket issuing master authentication server may be built.
With appropriate subroutine definitions, the resulting class may provided
authentication for either trusted or untrusted client sites.

   The class may be used to implement a ticket server either as a mod_perl
handler (see Authen::Ticket) or as a CGI script (using the object methods).

   If the server class is a sub-class of Authen::Ticket::Signature (or
comparable class), the ticket will automatically be signed.

SERVER OBJECT
=============

   Authen::Ticket::Server provides an object encapsulating most of the
information required to authenticate a user and generate tickets.  The
following values are contained in the object:

     $server = new Authen::Ticket::Server;
     $$server{_r}     -> Apache request object iff running under mod_perl
     $$server{stdout} -> object to print to for HTML pages
     $$server{query}  -> CGI-like object for generating HTML and accessing
                         form data
     $$server{request_uri}

     $$server{TicketDomain}  -> domain for which ticket is valid
     $$server{TicketExpires} -> default ticket lifetime

   The class constructor will work with sub-classes without modification.
Sub-class initialization should be placed in the initialize subroutine.

SUB-CLASSING
============

   A sub-class is required to override any of the methods mentioned in this
documentation (e.g., authentication method, HTML forms).  Two variables
are required in the sub-class package.

@ISA
     This array determines the classes the sub-class will inherit from.
     For a fully functioning server, this must include
     Authen::Ticket::Server.  If the tickets are to be signed,
     Authen::Ticket::Signature is recommended.

%DEFAULTS
     This hash contains the default values (or undef) for the configuration
     options required by the sub-class.  These are set in the httpd
     configuration with the PerlSetVar directive.  These are available in
     the $self hash reference.

Example
          package My::Ticket::Server;

          @ISA = (qw/Authen::Ticket::Server Authen::Ticket::Signature/);

          %DEFAULTS = (
            TicketUserDatabase => 'mysql:users',
            TicketDatabaseUser => undef,
            TicketDatabasePassword => undef,
            TicketUserFields   => 'table:userfield:passwordfield',
          );

GENERAL METHODS
===============

   The following methods need not be redefined in any sub-classes.

$server = new Authen::Ticket::Server([$r], [%options])
     This will return an initialized server object.  If $r is a reference
     and the code is running under mod_perl, then $$server{_r} will be set
     to $r.  Otherwise, all the arguments are taken to belong to a hash
     defining the default configuration.

     This method is used in Authen::Ticket->handler and is useful in CGI
     scripts implementing a ticket server.  However, the preferred use of
     the Authen::Ticket modules is in a mod_perl environment.

SUB-CLASS FUNCTIONS
===================

   The following conventions are used in these sections:

     $server -> server object
     $u      -> hashref of user authentication information
     $t      -> hashref of ticket information
     $s      -> additional information for inclusion in a message

SUB-CLASS REQUIRED FUNCTIONS
============================

   Any sub-class of Authen::Ticket::Server must define the following
subroutines:

$t = $server->authenticate($u)
     This subroutine returns a hashref of information to be placed in the
     ticket if the user is authenticated.  If the person is not
     authenticated, it should return undef.

     The following values are added to $t by $server->handler after
     authenticated returns successfully:

          fields -> comma separated list of fields in %$t
          uid    -> $u->{user}
          ip     -> browser IP information depending on $u->{security}
          expiry -> expiration time of the ticket

     The default implementation will place a warning in the log file (if
     running under mod_perl) and refuse authentication.

SUB-CLASS RECOMMENDED FUNCTIONS
===============================

   Any sub-class of Authen::Ticket::Server should define the following
subroutines:

$q = $server->get_query_object
     This subroutine returns an object used to retrieve form values and
     format HTML.  This must be CGI or another class that implements the
     CGI interface (e.g., a sub-class of CGI).

     The default implementation will return a valid CGI object of type
     $CGI::DefaultClass.

     This routine is used in the object constructor to initialize part of
     the object.

$o = $server->get_stdout_object
     This subroutine returns an object to be used as STDOUT.  This must
     support the $o->print() syntax.

     The default implementation will return the object to which STDOUT is
     tied (usually Apache->request object).

     This routine is used in the object constructor to initialize part of
     the object.

$u = $server->get_userinfo
     This subroutine returns a hash reference to the information on the
     authenticating person.  Some massaging of the data may take place.
     This routine transfers data from the input form to an internal
     representation for further processing.

     The following fields are expected for correct authentication:

          user     -> username
          password -> password
          duration -> lifetime of the ticket
          security -> {weak,medium,strong} extent to which the browser IP is used

     The default implementation will pull the above values from the query
     object.

$c = $server->construct_cookie(%$t)
     This subroutine returns an intermediate value for the ticket.  This
     routine may combine the values in %$t in any manner deemed necessary
     as long as the client website can deconstruct them.

$c = $server->encode_cookie($c)
     This subroutine encodes the cookie.  This may involve encryption or
     other transforms.  However, Authen::Ticket::Signature provides the
     code for signing tickets.

     The default implementation base_64 encodes the cookie.

SUB-CLASS MISCELLANEOUS FUNCTIONS
=================================

   Any sub-class of Authen::Ticket::Server may define the following
subroutines:

$server->no_cookie_error_message($s)
     This subroutine returns an HTML page to be sent to the browser when
     the ticket server has detected a lack of support for cookies.

$server->no_user_password_error_message($s)
     This subroutine returns an HTML page to be sent to the browser when
     the server needs the authentication information from the user.  The
     optional $s parameter will contain any error messages from the
     previous authentication attempt if there was one.  $uri is the URI of
     the page the server will return to when the user has successfully
     authenticated.

$server->go_to_uri_message
     This subroutine returns an HTML page to be sent to the browser when
     the user has successfully authenticated.  This page does not need to
     redirect the browser to $uri.  $uri is provided to help those
     browsers that cannot redirect themselves automatically.

AUTHOR
======

   James G. Smith <jgsmith@tamu.edu>

COPYRIGHT
=========

   Copyright (c) 1999, Texas A&M University.  All rights reserved.

   Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

     1. Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
     2. Redistributions in binary form must reproduce the above
        copyright notice, this list of conditions and the following
        disclaimer in the documentation and/or other materials
        provided with the distribution.
     3. Neither the name of the University nor the names of its
        contributors may be used to endorse or promote products
        derived from this software without specific prior written
        permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTERS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

SEE ALSO
========

   perl(1), Authen::Ticket(3), Authen::Ticket::Client(3).

   Authen::Ticket::Signature - Support for signing authentication tickets

SYNOPSIS
========

   As key server:

     <Location "/keys">
       SetHandler perl-script
       PerlSetHandler Authen::Ticket::Signature
       PerlSetVar  TicketSignaturePublicKey http://keys.my.com/keys/${id}
       PerlSetVar  TicketSignatureId        General
     </Location>

   As part of ticket server:

     package My::Ticket::Server;

     @ISA = (qw/Authen::Ticket::Server Authen::Ticket::Signature/);

   As part of ticket client:

     package My::Ticket::Client;

     @ISA = (qw/Authen::Ticket::Client Authen::Ticket::Signature/);

DESCRIPTION
===========

   Authen::Ticket::Signature provides the framework for signing and
verifying tickets.  The El Gamal algorithm is included in the code as a
good default signing algorithm.  The default key length is 512 bits.

   If IPC::Shareable is available, keys are cached in shared memory across
processes.  This is a virtual requirement for a multiprocess Apache ticket
server since all tickets should be signed by the same key.  This is only a
memory issue for client websites if several keys might need to be cached
simultaneously.

   Different keys may be cached with each having an identifying name.  This
name is used to retrieve the public portion of the key from the key server.
The key to be retrieved for use in signing or verification is determined
by the server configuration.

METHODS
=======

   Adding Authen::Ticket::Signature to the @ISA array for the ::Client or
::Server class will add the following methods to that class.  Any may be
overridden, though only generate_key, sign_ticket, and verify_ticket are
recommended.  All numbers are expected to be objects of type OpenSSL::BN.

handler
     This routine provides the key server functionality.  Only public keys
     may be requested.  The path-info part of the request is the name of a
     key.  For example, if http://my.com/keys is the location of the key
     server, then http://my.com/keys/general will return the public key of
     the default key for signing tickets.

$self->get_public_key
     This routine will return the public key as appropriate according to
     the server configuration.  If the key is not available in memory, an
     attempt will be made to fetch the key either from a remote server or
     the file system.

     A public key is a hash reference with the various parts of the key.
     This is algorithm dependent.  The El Gamal routine will return the
     following hashref:

          { 'y' => $y, 'p' => $p, 'g' => $g }

     This is returned by the key server as the string "y:$y;p:$p;g:$g" with
     the values in hexadecimal.

$self->get_private_key
     This routine will return the private key as appropriate according to
     the server configuration.  If the required key is not available in
     cache, it will be generated.  Since the private key is only to be
     used on the machine it is generated on, it does not make sense to
     fetch the private key from any particular location.

     A private key is a hash reference with the various parts of the key.
     This is algorithm dependent.  The El Gamal routine will return the
     following hashref:

          { 'x' => $x, 'p' => $p, 'g' => $g }

$self->generate_key( $key_length )
     This routine must return the private and public key parts with a
     nominal key length of $key_length.  See the get_{private,public}_key
     routines for the format of the key parts.  The actual value returned
     is an array of the format:

          ( { private_key }, { public_key } )

$self->sign_ticket( $ticket )
     This routine should attach a signature to $ticket and return the
     resulting value.  The format used must be understood by
     $self->verify_ticket.  The $ticket will have already been passed
     through $self->construct_ticket and $self->encode_ticket.

$self->verify_ticket( $ticket )
     This routine should verify the signature on the $ticket and return the
     encoded ticket without the signature (this would be the value that was
     passed to sign_ticket).  The following must hold true:

          $self->verify_ticket($self->sign_ticket($ticket)) eq $ticket

WHY EL GAMAL?
=============

   This code was produced and is maintained within the United States of
America.  As many are aware, export restrictions on cryptographic products
exist.  This section explains what algorithm was chosen and why it should
not violate any export regulations.

   The El Gamal algorithms are not under any patent or licensing
restrictions and may thus be used freely, though with export restrictions
in mind.

   The default algorithm in Authen::Ticket::Signature is El Gamal.  The
supplied code IS NOT INTENDED to be used to encrypt messages.  Other parts
of the algorithm may be used for encryption, but the signature portions are
not intended to encrypt and decrypt data.  However, [Schneier 532] points
out the ability to send subliminal messages using the signature algorithms.

SHARED MEMORY
=============

   The code tries to use IPC::Shareable if it is already loaded.  Apache
can go into an endless spin with children being dieing and being created
if the IPC::Shareable code causes a segfault during child initialization.
This can happen when a previously created shared memory segment has not
been properly disposed of and also cannot be connected to.

   If IPC::Shareable is not loaded during the server startup, the
Authen::Ticket::Signature code will not try to use it.  Therefore, you
must load IPC::Shareable before loading Authen::Ticket::Signature or any
class derived from it.

AUTHOR
======

   James G. Smith, <jgsmith@tamu.edu>

   Portions of code are based on [Orwant 552-554] and [Stein 320].

COPYRIGHT
=========

   Copyright (c) 1999, Texas A&M University.  All rights reserved.

   Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

     1. Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
     2. Redistributions in binary form must reproduce the above
        copyright notice, this list of conditions and the following
        disclaimer in the documentation and/or other materials
        provided with the distribution.
     3. Neither the name of the University nor the names of its
        contributors may be used to endorse or promote products
        derived from this software without specific prior written
        permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTERS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

SEE ALSO
========

   perl(1), Authen::Ticket(3), Authen::Ticket::Server(3),
Authen::Ticket::Client(3)

   Orwant, Jon, et. al. *Mastering Agorithms with Perl*, O'Reilly &
Associates, 1999.

   Schneier, Bruce *Applied Cryptography*, 2nd ed., John Wiley & Sons,
1996.

   Stein, Lincoln, & Doug MacEachern. *Writing Apache Modules with Perl
and C*, O'Reilly & Associates, 1999.

Authentication via an IMAP server
*********************************

NAME
====

   Apache::AuthenIMAP - Authentication via an IMAP server

SYNOPSIS
========

     # Configuration in httpd.conf

     PerlModule Apache::AuthenIMAP

     # Authentication in .htaccess

     AuthName IMAP
     AuthType Basic

     # authenticate via IMAP
     PerlAuthenHandler Apache::AuthenIMAP

     PerlSetVar Auth_IMAP_host imaphost.domain.foo

     require user fred

   The AuthType is limited to Basic. The require directive is limited to
'valid-user' and 'user user_1 user_2 ...'.

DESCRIPTION
===========

   This module allows authentication against an IMAP server.

LIST OF TOKENS
==============

   * Auth_IMAP_host

     The IMAP server host: either its name or its dotted quad IP number.
     This is passed as the PeerAddr option to IO::Socket::INET->new.

   * Auth_IMAP_port

     The port on which the IMAP server is listening: either its service
     name or its actual port number. This parameter defaults to "imap"
     which is the official service name for IMAP servers. The parameter is
     passed as the PeerPort option to IO::Socket::INET->new.

CONFIGURATION
=============

   The module should be loaded upon startup of the Apache daemon.  Add the
following line to your httpd.conf:

     PerlModule Apache::AuthenIMAP

PREREQUISITES
=============

   For AuthenIMAP you need to enable the appropriate call-back hook when
making mod_perl:

     perl Makefile.PL PERL_AUTHEN=1

SEE ALSO
========

   See Apache, `mod_perl' in this node

AUTHORS
=======

   * mod_perl by Doug MacEachern <dougm@osf.org>

   * Apache::AuthenIMAP by Malcolm Beattie <mbeattie@sable.ox.ac.uk>

COPYRIGHT
=========

   The Apache::AuthenIMAP module is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

load subroutines only on demand
*******************************

NAME
====

   AutoLoader - load subroutines only on demand

SYNOPSIS
========

     package Foo;
     use AutoLoader 'AUTOLOAD';   # import the default AUTOLOAD subroutine

     package Bar;
     use AutoLoader;              # don't import AUTOLOAD, define our own
     sub AUTOLOAD {
         ...
         $AutoLoader::AUTOLOAD = "...";
         goto &AutoLoader::AUTOLOAD;
     }

DESCRIPTION
===========

   The AutoLoader module works with the AutoSplit module and the `__END__'
token to defer the loading of some subroutines until they are used rather
than loading them all at once.

   To use AutoLoader, the author of a module has to place the definitions
of subroutines to be autoloaded after an `__END__' token.  (See
Perldata (perl.info).)  The AutoSplit module can then be run
manually to extract the definitions into individual files
`auto/funcname.al'.

   AutoLoader implements an AUTOLOAD subroutine.  When an undefined
subroutine in is called in a client module of AutoLoader, AutoLoader's
AUTOLOAD subroutine attempts to locate the subroutine in a file with a
name related to the location of the file from which the client module was
read.  As an example, if `POSIX.pm' is located in
`/usr/local/lib/perl5/POSIX.pm', AutoLoader will look for perl subroutines
POSIX in `/usr/local/lib/perl5/auto/POSIX/*.al', where the `.al' file has
the same name as the subroutine, sans package.  If such a file exists,
AUTOLOAD will read and evaluate it, thus (presumably) defining the needed
subroutine.  AUTOLOAD will then goto the newly defined subroutine.

   Once this process completes for a given function, it is defined, so
future calls to the subroutine will bypass the AUTOLOAD mechanism.

Subroutine Stubs
----------------

   In order for object method lookup and/or prototype checking to operate
correctly even when methods have not yet been defined it is necessary to
"forward declare" each subroutine (as in `sub NAME;').  See `"SYNOPSIS"',
see Perlsub (perl.info).  Such forward declaration creates
"subroutine stubs", which are place holders with no code.

   The AutoSplit and AutoLoader modules automate the creation of forward
declarations.  The AutoSplit module creates an 'index' file containing
forward declarations of all the AutoSplit subroutines.  When the
AutoLoader module is 'use'd it loads these declarations into its callers
package.

   Because of this mechanism it is important that AutoLoader is always
used and not required.

Using AutoLoader's AUTOLOAD Subroutine
--------------------------------------

   In order to use AutoLoader's AUTOLOAD subroutine you must explicitly
import it:

     use AutoLoader 'AUTOLOAD';

Overriding AutoLoader's AUTOLOAD Subroutine
-------------------------------------------

   Some modules, mainly extensions, provide their own AUTOLOAD subroutines.
They typically need to check for some special cases (such as constants)
and then fallback to AutoLoader's AUTOLOAD for the rest.

   Such modules should not import AutoLoader's AUTOLOAD subroutine.
Instead, they should define their own AUTOLOAD subroutines along these
lines:

     use AutoLoader;
     use Carp;

     sub AUTOLOAD {
         my $sub = $AUTOLOAD;
         (my $constname = $sub) =~ s/.*:://;
         my $val = constant($constname, @_ ? $_[0] : 0);
         if ($! != 0) {
             if ($! =~ /Invalid/ || $!{EINVAL}) {
                 $AutoLoader::AUTOLOAD = $sub;
                 goto &AutoLoader::AUTOLOAD;
             }
             else {
                 croak "Your vendor has not defined constant $constname";
             }
         }
         *$sub = sub { $val }; # same as: eval "sub $sub { $val }";
         goto &$sub;
     }

   If any module's own AUTOLOAD subroutine has no need to fallback to the
AutoLoader's AUTOLOAD subroutine (because it doesn't have any AutoSplit
subroutines), then that module should not use AutoLoader at all.

Package Lexicals
----------------

   Package lexicals declared with my in the main block of a package using
AutoLoader will not be visible to auto-loaded subroutines, due to the fact
that the given scope ends at the `__END__' marker.  A module using such
variables as package globals will not work properly under the AutoLoader.

   The vars pragma (see `"vars"', see Perlmod (perl.info)) may
be used in such situations as an alternative to explicitly qualifying all
globals with the package namespace.  Variables pre-declared with this
pragma will be visible to any autoloaded routines (but will not be
invisible outside the package, unfortunately).

AutoLoader vs. SelfLoader
-------------------------

   The AutoLoader is similar in purpose to SelfLoader: both delay the
loading of subroutines.

   SelfLoader uses the `__DATA__' marker rather than `__END__'.  While
this avoids the use of a hierarchy of disk files and the associated
open/close for each routine loaded, SelfLoader suffers a startup speed
disadvantage in the one-time parsing of the lines after `__DATA__', after
which routines are cached.  SelfLoader can also handle multiple packages
in a file.

   AutoLoader only reads code as it is requested, and in many cases should
be faster, but requires a mechanism like AutoSplit be used to create the
individual files.  See ExtUtils/MakeMaker, will
invoke AutoSplit automatically if AutoLoader is used in a module source
file.

CAVEATS
=======

   AutoLoaders prior to Perl 5.002 had a slightly different interface.  Any
old modules which use AutoLoader should be changed to the new calling
style.  Typically this just means changing a require to a use, adding the
explicit `'AUTOLOAD'' import if needed, and removing AutoLoader from
`@ISA'.

   On systems with restrictions on file name length, the file corresponding
to a subroutine may have a shorter name that the routine itself.  This can
lead to conflicting file names.  The AutoSplit package warns of these
potential conflicts when used to split a module.

   AutoLoader may fail to find the autosplit files (or even find the wrong
ones) in cases where `@INC' contains relative paths, and the program does
chdir.

SEE ALSO
========

   See SelfLoader, - an autoloader that doesn't use external
files.

split a package for autoloading
*******************************

NAME
====

   AutoSplit - split a package for autoloading

SYNOPSIS
========

     autosplit($file, $dir, $keep, $check, $modtime);

     autosplit_lib_modules(@modules);

DESCRIPTION
===========

   This function will split up your program into files that the AutoLoader
module can handle. It is used by both the standard perl libraries and by
the MakeMaker utility, to automatically configure libraries for
autoloading.

   The `autosplit' interface splits the specified file into a hierarchy
rooted at the directory $dir. It creates directories as needed to reflect
class hierarchy, and creates the file `autosplit.ix'. This file acts as
both forward declaration of all package routines, and as timestamp for the
last update of the hierarchy.

   The remaining three arguments to `autosplit' govern other options to
the autosplitter.

$keep
     If the third argument, $keep, is false, then any pre-existing `*.al'
     files in the autoload directory are removed if they are no longer
     part of the module (obsoleted functions).  $keep defaults to 0.

$check
     The fourth argument, $check, instructs `autosplit' to check the module
     currently being split to ensure that it does include a use
     specification for the AutoLoader module, and skips the module if
     AutoLoader is not detected.  $check defaults to 1.

$modtime
     Lastly, the $modtime argument specifies that `autosplit' is to check
     the modification time of the module against that of the
     `autosplit.ix' file, and only split the module if it is newer.
     $modtime defaults to 1.

   Typical use of AutoSplit in the perl MakeMaker utility is via the
command-line with:

     perl -e 'use AutoSplit; autosplit($ARGV[0], $ARGV[1], 0, 1, 1)'

   Defined as a Make macro, it is invoked with file and directory
arguments; `autosplit' will split the specified file into the specified
directory and delete obsolete `.al' files, after checking first that the
module does use the AutoLoader, and ensuring that the module is not
already currently split in its current form (the modtime test).

   The `autosplit_lib_modules' form is used in the building of perl. It
takes as input a list of files (modules) that are assumed to reside in a
directory lib relative to the current directory. Each file is sent to the
autosplitter one at a time, to be split into the directory *lib/auto*.

   In both usages of the autosplitter, only subroutines defined following
the perl *__END__* token are split out into separate files. Some routines
may be placed prior to this marker to force their immediate loading and
parsing.

Multiple packages
-----------------

   As of version 1.01 of the AutoSplit module it is possible to have
multiple packages within a single file. Both of the following cases are
supported:

     package NAME;
     __END__
     sub AAA { ... }
     package NAME::option1;
     sub BBB { ... }
     package NAME::option2;
     sub BBB { ... }

     package NAME;
     __END__
     sub AAA { ... }
     sub NAME::option1::BBB { ... }
     sub NAME::option2::BBB { ... }

DIAGNOSTICS
===========

   AutoSplit will inform the user if it is necessary to create the
top-level directory specified in the invocation. It is preferred that the
script or installation process that invokes AutoSplit have created the
full directory path ahead of time. This warning may indicate that the
module is being split into an incorrect path.

   AutoSplit will warn the user of all subroutines whose name causes
potential file naming conflicts on machines with drastically limited (8
characters or less) file name length. Since the subroutine name is used as
the file name, these warnings can aid in portability to such systems.

   Warnings are issued and the file skipped if AutoSplit cannot locate
either the *__END__* marker or a "package Name;"-style specification.

   AutoSplit will also emit general diagnostics for inability to create
directories or files.

Perl extension for translating U.S. METAR, TAF and PIREP textual reports into plain English.
********************************************************************************************

NAME
====

   Aviation::Report - Perl extension for translating U.S. METAR, TAF and
PIREP textual reports into plain English.

SYNOPSIS
========

     use strict;
     use Aviation::Report;

     print decode_METAR_TAF(report, style);
     print decode_PIREP(report, style);

DESCRIPTION
===========

   Translates U.S. METAR, TAF and PIREP text reports into plain English.
Although the syntax of these reports is standardized, it is not as obvious
as it first appears to make correct translations.

   The style option controls the final appearance. A style of 0 emits only
plain English, while 1 includes the original tokens for reference purposes.

AUTHOR
======

   James Briggs <71022.3700@compuserve.com>

SEE ALSO
========

   METAR.pm by Jeremy Zawodny

Perl extension for the ActiveWorks C Application Development Kit
****************************************************************

NAME
====

   Aw - Perl extension for the ActiveWorks C Application Development Kit

SYNOPSIS
========

   use Aw; require Aw::Adapter; require Aw::Event;

   my $adapter = new Aw::Adapter  ( "3.0", ) ; my $event = new Aw::Event;

DESCRIPTION
===========

     A Java like interface to the CADK thru Perl.

Exported Constants
==================

   Everything in the CADK include files should be exported as constants.

AUTHOR
======

   Daniel Yacob Mekonnen,  `Yacob@RCN.Com|mailto:Yacob@RCN.Com' in this
node

SEE ALSO
========

   perl(1). ActiveWorks Supplied Documentation

ActiveWorks Adapter Module.
***************************

NAME
====

   Aw::Adapter - ActiveWorks Adapter Module.

SYNOPSIS
========

   require Aw::Adapter;

   my $adapter = new Aw::Adapter;

DESCRIPTION
===========

   Enhanced interface for the Aw.xs Adapter methods.

AUTHOR
======

   Daniel Yacob Mekonnen,  `Yacob@RCN.Com|mailto:Yacob@RCN.Com' in this
node

SEE ALSO
========

   perl(1).  Aw(3).

ActiveWorks Client Module.
**************************

NAME
====

   Aw::Client - ActiveWorks Client Module.

SYNOPSIS
========

   require Aw::Client;

   my $client = new Aw::Client;

DESCRIPTION
===========

   Enhanced interface for the Aw.xs Client methods.

AUTHOR
======

   Daniel Yacob Mekonnen,  `Yacob@RCN.Com|mailto:Yacob@RCN.Com' in this
node

SEE ALSO
========

   perl(1).  Aw(3).

ActiveWorks Client Module.
**************************

NAME
====

   Aw::Client - ActiveWorks Client Module.

SYNOPSIS
========

   require Aw::Client;

   my $client = new Aw::Client;

DESCRIPTION
===========

   Demonstative module that allows for a blessed hash to act as a client.

AUTHOR
======

   Daniel Yacob Mekonnen,  `Yacob@RCN.Com|mailto:Yacob@RCN.Com' in this
node

SEE ALSO
========

   perl(1).  Aw(3).

ActiveWorks Connection Descriptor Module.
*****************************************

NAME
====

   Aw::ConnectionDescriptor - ActiveWorks Connection Descriptor Module.

SYNOPSIS
========

   require Aw::ConnectionDescriptor;

   my $cd = new Aw::ConnectionDescriptor;

DESCRIPTION
===========

   Enhanced interface for the Aw.xs Connection Descriptor methods.

AUTHOR
======

   Daniel Yacob Mekonnen,  `Yacob@RCN.Com|mailto:Yacob@RCN.Com' in this
node

SEE ALSO
========

   perl(1).  Aw(3).

ActiveWorks Event Module.
*************************

NAME
====

   Aw::Event - ActiveWorks Event Module.

SYNOPSIS
========

   require Aw::Event;

   my $event = new Aw::Event;

DESCRIPTION
===========

   Enhanced interface for the Aw.xs Event methods.

AUTHOR
======

   Daniel Yacob Mekonnen,  `Yacob@RCN.Com|mailto:Yacob@RCN.Com' in this
node

SEE ALSO
========

   perl(1).  Aw(3).

ActiveWorks License Module.
***************************

NAME
====

   Aw::License - ActiveWorks License Module.

SYNOPSIS
========

   require Aw::License;

   my $typeDef = new Aw::License;

DESCRIPTION
===========

   Enhanced interface for the Aw.xs License methods.

AUTHOR
======

   Daniel Yacob Mekonnen,  `Yacob@RCN.Com|mailto:Yacob@RCN.Com' in this
node

SEE ALSO
========

   perl(1).  Aw(3).

ActiveWorks Log Module.
***********************

NAME
====

   Aw::Log - ActiveWorks Log Module.

SYNOPSIS
========

   require Aw::Log;

   my $typeDef = new Aw::Log;

DESCRIPTION
===========

   Enhanced interface for the Aw.xs Log methods.

AUTHOR
======

   Daniel Yacob Mekonnen,  `Yacob@RCN.Com|mailto:Yacob@RCN.Com' in this
node

SEE ALSO
========

   perl(1).  Aw(3).

ActiveWorks TypeDef Module.
***************************

NAME
====

   Aw::TypeDef - ActiveWorks TypeDef Module.

SYNOPSIS
========

   require Aw::TypeDef;

   my $typeDef = new Aw::TypeDef;

DESCRIPTION
===========

   Enhanced interface for the Aw.xs TypeDef methods.

AUTHOR
======

   Daniel Yacob Mekonnen,  `Yacob@RCN.Com|mailto:Yacob@RCN.Com' in this
node

SEE ALSO
========

   perl(1).  Aw(3).

ActiveWorks Connection Descriptor Module.
*****************************************

NAME
====

   Aw::Util - ActiveWorks Connection Descriptor Module.

SYNOPSIS
========

   require Aw::Util;

   my $cd = new Aw::Util;

DESCRIPTION
===========

   Enhanced interface for the Aw.xs Connection Descriptor methods.

AUTHOR
======

   Daniel Yacob Mekonnen,  `Yacob@RCN.Com|mailto:Yacob@RCN.Com' in this
node

SEE ALSO
========

   perl(1).  Aw(3).

an XML Delivery Toolkit for Apache
**********************************

NAME
====

   AxKit - an XML Delivery Toolkit for Apache

DESCRIPTION
===========

   AxKit provides the user with an application development environment for
mod_perl, using XML, Stylesheets and a few other tricks. See
http://axkit.org/ for details.

SYNOPSIS
========

   In httpd.conf:

     # we add custom configuration directives
     # so this *must* be in httpd.conf outside of
     # all request based conditionals
     PerlModule AxKit

   Then in any Apache configuration section (Files, Location, Directory,
.htaccess):

     # Install AxKit main parts
     SetHandler perl-script
     PerlHandler AxKit

     # Setup style type mappings
     AxAddStyleMap text/xsl Apache::AxKit::Language::Sablot
     AxAddStyleMap application/x-xpathscript \
             Apache::AxKit::Language::XPathScript

     # Optionally set a hard coded cache directory
     # make sure this is writable by nobody
     AxCacheDir /opt/axkit/cachedir

     # turn on debugging (1 - 10)
     AxDebugLevel 5

   Now simply create xml files with stylesheet declarations:

     <?xml version="1.0"?>
     <?xml-stylesheet href="test.xsl" type="text/xsl"?>
     <test>
         This is my test XML file.
     </test>

   And for the above, create a stylesheet in the same directory as the
file called "test.xsl" that compiles the XML into something usable  by the
browser. If you wish to use other languages than XSLT, you can, provided a
module exists for that language.

BUILD PROBLEMS
==============

   If you have trouble compiling AxKit, or apache fails to start after
installing, it's possible to use AxKit without the built in configuration
directives (which have been known to generate segfaults).  To do this
install as follows:

     perl Makefile.PL NO_DIRECTIVES=1
     make
     make test
     make install UNINST=1

   This removes the custom configuration directives. Note that the
UNINST=1 is required to make sure that old AxKit files are removed from
the binary directory (since it has no binary component any more). Now you
can change the directives to ordinary PerlSetVar directives:

     PerlSetVar AxStyleMap "text/xsl => Apache::AxKit::Language::XSLT, \
         application/x-xpathscript => Apache::AxKit::Language::XPathScript"

     PerlSetVar AxCacheDir /opt/axkit/cache

   It's worth noting that the PerlSetVar option is available regardless of
whether you compile with NO_DIRECTIVES set, although it is marginally
slower to use PerlSetVar.

   Also note that if you go back to using the compiled directives, you
must again install with UNINST=1.

CONFIGURATION DIRECTIVES
========================

   AxKit installs a number of new first class configuration directives for
you to use in Apache's httpd.conf or .htaccess files. These provide very
fine grained control over how AxKit performs transformations and sends its
output to the user.

   Each directive below is listed along with how to use that directive with
NO_DIRECTIVES=1 (i.e. via PerlSetVar).

AxCacheDir
----------

   This option takes a single argument, and sets the directory that the
cache module stores its files in. These files are an MD5 hash of the file
name and some other information. Make sure the directory you specify is
writable by either the nobody user or the nobody group (or whatever user
your Apache servers run as). It is probably best to not make these
directories world writable!

     AxCacheDir /tmp/axkit_cache

   or

     PerlSetVar AxCacheDir /tmp/axkit_cache

AxDebugLevel
------------

   If present this makes AxKit send output to Apache's error log. The
valid range is 0-10, with 10 producing more output. We recommend not to
use this option on a live server.

     AxDebugLevel 5

   or

     PerlSetVar AxDebugLevel 5

AxGzipOutput
------------

   This allows you to use the Compress::Zlib module to gzip output to
browsers that support gzip compressed pages. It uses the Accept-Encoding
HTTP header and some information about User agents who can support this
option but don't correctly send the Accept-Encoding header. This option
allows either On or Off values (default being Off). This is very much
worth using on sites with mostly static pages because it reduces outgoing
bandwidth significantly.

     AxGzipOutput On

   or

     PerlSetVar AxGzipOutput 1

AxTranslateOutput
-----------------

   This option enables output character set translation. The default method
is to detect the appropriate character set from the user agent's
Accept-Charset HTTP header, but you can also hard-code an output character
set using AxOutputCharset (see below).

     AxTranslateOutput On

   or

     PerlSetVar AxTranslateOutput 1

AxOutputCharset
---------------

   Fix the output character set, rather than using either UTF-8 or the
user's preference from the Accept-Charset HTTP header. If this option is
present, all output will occur in the chosen character set. The conversion
uses the iconv library, which is part of GNU glibc and/or most modern
Unixes. It is recommended to not use this option if you can avoid it. This
option is only enable if you also enable AxTranslateOutput.

     AxOutputCharset iso-8859-1

   or

     PerlSetVar AxOutputCharset iso-8859-1

AxErrorStylesheet
-----------------

   If an error occurs during processing that throws an exception, the
exception handler will try and find an ErrorStylesheet to use to process
XML of the following format:

     <error>
         <file>/usr/htdocs/xml/foo.xml</file>
         <msg>Something bad happened</msg>
         <stack_trace>
             <bt level="0">
                 <file>/usr/lib/perl/site/AxKit.pm</file>
                 <line>342</line>
             </bt>
         </stack_trace>
     </error>

   There may potentially be multiple bt tags. If an exception occurs when
the error stylesheet is transforming the above XML, then a SERVER ERROR
will occur and an error written in the Apache error log.

     AxErrorStylesheet text/xsl /stylesheets/error.xsl

   or

     PerlSetVar AxErrorStylesheet "text/xsl => /stylesheets/error.xsl"

AxAddXSPTaglib
--------------

   XSP supports two types of tag libraries. The simplest type to understand
is merely an XSLT or XPathScript (or other transformation language)
stylesheet that transforms custom tags into the "raw" XSP tag form.
However there is another kind, that is faster, and these taglibs transform
the custom tags into pure code which then gets compiled. These taglibs
must be loaded into the server using the AxAddXSPTaglib configuration
directive.

     # load the SQL taglib
     AxAddXSPTaglib Apache::AxKit::Language::XSP::SQL
     AxAddXSPTaglib Apache::AxKit::Language::XSP::Util

   or

     PerlSetVar AxAddXSPTaglibs \
         Apache::AxKit::Language::XSP::SQL \
         Apache::AxKit::Language::XSP::Util

AxStyle
-------

   A default stylesheet title to use. This is useful when a single XML
resource maps to multiple choice stylesheets. One possible way to use this
is to symlink the same file in different directories with .htaccess files
specifying different AxStyle directives.

     AxStyle "My custom style"

   or

     PerlSetVar AxPreferredStyle "My custom style"

AxMedia
-------

   Very similar to the previous directive, this sets the media type. It is
most useful in a .htaccess file where you might have an entire directory
for the media "handheld".

     AxMedia tv

   or

     PerlSetVar AxPreferredMedia tv

AxAddStyleMap
-------------

   This is one of the more important directives. It is responsible for
mapping module stylesheet MIME types to stylesheet processor modules (the
reason we do this is to make it easy to switch out different modules for
the same functionality, for example different XSLT processors).

     AxAddStyleMap text/xsl Apache::AxKit::Language::Sablot
     AxAddStyleMap application/x-xpathscript \
         Apache::AxKit::Language::XPathScript
     AxAddStyleMap application/x-xsp \
         Apache::AxKit::Language::XSP

   or

     PerlSetVar AxStyleMap \
        "text/xsl => Apache::AxKit::Language::Sablot, \
         application/x-xpathscript => Apache::AxKit::Language::XPathScript, \
         application/x-xsp => Apache::AxKit::Language::XSP"

AxResetStyleMap
---------------

   Since the style map will continue deep into your directory tree, it may
occasionally be useful to reset the style map (I don't have an example
usage of this at this time).

     # option takes no arguments.
     AxResetStyleMap

   or

     PerlSetVar AxStyleMap ""

   Note that the PerlSetVar version of resetting the style map does not
work with the custom directive version of AxAddStyleMap and vice versa.

AxAddProcessor
--------------

   This directive maps all XML files to a particular stylesheet to be
processed with. You can do this in a <Files> directive if you need to do
it by file extension:

     <Files *.dkb>
     AxAddProcessor text/xsl /stylesheets/docbook.xsl
     </Files>

   Multiple directives for the same set of files make for a chained set of
stylesheet processing instructions, where the output of one processing
stage goes into the input of the next. This is especially useful for XSP
processing, where the output of the XSP processor will likely not be HTML
(or WAP or whatever your chosen output format is):

     <Files *.xsp>
     # use "." to indicate that XSP gets processed by itself.
     AxAddProcessor application/x-xsp .
     AxAddProcessor text/xsl /stylesheets/to_html.xsl
     </Files>

   There is no PerlSetVar equivalent of this directive.

AxAddDocTypeProcessor
---------------------

   This allows you to map all XML files conforming to a particular XML
public identifier in the document's DOCTYPE declaration, to the specified
stylesheet(s):

     AxAddDocTypeProcessor text/xsl /stylesheets/docbook.xsl \
             "-//OASIS//DTD DocBook XML V4.1.2//EN"

   There is no PerlSetVar equivalent of this directive.

AxAddDTDProcessor
-----------------

   This allows you to map all XML files that specify the given DTD file or
URI in the SYSTEM identifier to be mapped to the specified stylesheet(s):

     AxAddDTDProcessor text/xsl /stylesheets/docbook.xsl \
             /dtds/docbook.dtd

   There is no PerlSetVar equivalent of this directive.

AxAddRootProcessor
------------------

   This allows you to map all XML files that have the given root element
to be mapped to the specified stylesheet(s):

     AxAddRootProcessor text/xsl /stylesheets/book.xsl book

   Namespaces are fully supported via the following syntax:

     AxAddRootProcessor text/xsl /stylesheets/homepage.xsl \
         {http://myserver.com/NS/homepage}homepage

   This syntax was taken from James Clark's Introduction to Namespaces
article.

   There is no PerlSetVar equivalent of this directive.

AxResetProcessors
-----------------

   This allows you to reset the processor mappings at from the current
directory level down.

     AxResetProcessors

   From this directory down you can completely redefine how certain types
of files get processed by AxKit.

<AxMediaType>
-------------

   This is a configuration directive block. It allows you to have finer
grained control over the mappings, by specifying that the mappings (which
have to be specified using the 4 directives above) contained within the
block are only relevant when the requested media type is as specified in
the block parameters:

     <AxMediaType screen>
     AxAddProcessor text/xsl /stylesheets/webpage_screen.xsl
     </AxMediaType>

     <AxMediaType handheld>
     AxAddProcessor text/xsl /stylesheets/webpage_wap.xsl
     </AxMediaType>

     <AxMediaType tv>
     AxAddProcessor text/xsl /stylesheets/webpage_tv.xsl
     </AxMediaType>

   There is no PerlSetVar equivalent of this directive block.

<AxStyleName>
-------------

   This configuration directive block is very similar to the above, only
it specifies alternate stylesheets by name, which can be then requested
via a StyleChooser:

     <AxMediaType screen>
         AxAddProcessor text/xsl /styles/webpage_screen.xsl
         <AxStyleName printable>
             AxAddProcessor text/xsl /styles/webpage_printable.xsl
         </AxStyleName>
     </AxMediaType>

   This and the above directive block can be nested, and can also be
contained within <Files> directives to give you even more control over how
your XML is transformed.

   There is no PerlSetVar equivalent of this directive block.

CUSTOMISING AXKIT
=================

   There are some configuration directives that are specifically reserved
for customising how AxKit works. These directives allow you to specify a
new class to replace the one being used for certain operations.

   These directives all take as a single argument, the name of a module to
load in place of the default. They are:

     AxConfigReader
     AxProvider
     AxCacheModule

   The ConfigReader module returns information about various configuration
options. Currently it takes most of its information from the above
mentioned configuration directives, or from PerlSetVar.

   The Provider module is the means by which AxKit gets its resources from.
The default Provider simply picks up files from the filesystem, but
alternate providers could pull the information from a DBMS, or perhaps
create some XML structure for directories. There currently exists one
alternate Provider module, which allows AxKit to work as a recipient for
Apache::Filter output. This module is Apache::AxKit::Provider::Filter.

   The Cache module is responsible for storing cache data for later
retrieval.

   Implementing these is non trivial, and it is highly recommended to join
the AxKit-devel mailing list before venturing to do so, and to also
consult the source for the current default modules. Details of joining the
mailing list are at http://axkit.org/mailinglist.xml

KNOWN BUGS
==========

   There are currently some incompatibilities between the versions of expat
loaded by Apache when compiled with RULE_EXPAT=yes (which is a default,
unfortunately), and XML::Parser's copy of expat. This can cause sporadic
segmentation faults in Apache's httpd processes. The solution is to
recompile Apache with RULE_EXPAT=no. If you have a recent mod_perl and use
mod_perl's Makefile.PL to compile Apache for you, this option will be
enabled automatically for you.

   There are a number of known bugs in XSP at this time. This is being
re-written to use SAX2, and so we are not focusing on fixing these bugs
until the re-write is further down the line.

AUTHOR and LICENSE
==================

   AxKit is developed by AxKit.com Ltd. See http://axkit.com/ for more
details.

   AxKit is licensed under either the GNU GPL Version 2, or the Perl
Artistic License.

   Copyright AxKit.com, 2000.

MORE DOCUMENTATION
==================

   For more documentation on things like XPathScript, XSP and XSLT, and a
quick getting started guide, please visit our community web site at
http://axkit.org/

SEE ALSO
========

   See Apache/AxKit/Plugins/Fragment,
Apache/AxKit/Plugins/Passthru,
Apache/AxKit/StyleChooser/QueryString,
see
Apache/AxKit/StyleChooser/UserAgent,
Apache/AxKit/StyleChooser/PathInfo,
see
Apache/AxKit/StyleChooser/FileSuffix,
see
Apache/AxKit/StyleChooser/Cookie,
`Apache::AxKit::MediaChooser::WAPCheck' in this node, see
Apache/AxKit/Provider,
`Apache::AxKit::Provider::Filter' in this node,
`Apache::AxKit::Provider::File' in this node,
`Apache::AxKit::Provider::Scalar' in this node

   (and probably others I have forgotten about)

An Extended SQL taglib for AxKit eXtensible Server Pages
********************************************************

NAME
====

   AxKit::XSP::ESQL - An Extended SQL taglib for AxKit eXtensible Server
Pages

SYNOPSIS
========

   Add the esql: namespace to your XSP `<xsp:page'> tag:

     <xsp:page
          language="Perl"
          xmlns:xsp="http://apache.org/xsp/core/v1"
          xmlns:esql="http://apache.org/xsp/SQL/v2"
     >

   And add this taglib to AxKit (via httpd.conf or .htaccess):

     AxAddXSPTaglib AxKit::XSP::ESQL

DESCRIPTION
===========

   This tag library provides extensive support for executing SQL statements
from within XSP. This tag library is the same as the Cocoon ESQL taglib.

TAG REFERENCE
=============

   Note that below we use the esql: prefix as a convention, however you can
use whatever prefix you like provided it is mapped to the appropriate
namespace.

`<esql:connection'>
-------------------

     parent: none

   This is the required 'wrapper' element that declares your connection.

`<esql:driver'>
---------------

     parent: <esql:connection>

   The contents of this element define the DBI driver to be used. For
example, Pg, Sybase, Oracle.

`<esql:dburl'>
--------------

     parent: <esql:connection>

   The name of this tag is a hang-over from the Cocoon (Java) version. In
the AxKit version this is simply anything that goes after the driver in
the connection string. So for PostgreSQL you might have in here
`dbname=axkit', to connect to the "axkit" database. The full connect
string is constructed as follows:

     "dbi:$driver" . ($dburl ? ":$dburl" : "")

   See your DBD driver documentation for more details on what is valid for
the connection string.

`<esql:username'>
-----------------

     parent: <esql:connection>

   The username to connect to the database with.

`<esql:password'>
-----------------

     parent: <esql:connection>

   The password to use to connect to the database.

`<esql:execute-query'>
----------------------

     parent: <esql:connection>

   This tag is a 'wrapper' tag around queries. You may have as many queries
as you like within a single `<esql:connection'> tag.

`<esql:skip-rows'>
------------------

     parent: <esql:execute-query>

   The contents of this tag (which may be an <xsp:expr>) define a number of
rows to skip forward in the result set.

`<esql:max-rows'>
-----------------

     parent: <esql:execute-query>

   The maximum number of rows to return.

`<esql:query'>
--------------

     parent: <esql:execute-query>

   The contents of this tag define the query to be executed.

`<esql:parameter'>
------------------

     parent: <esql:query>

   This tag can be put in your SQL query everywhere you might put a ? in
your SQL in DBI. ESQL is intelligent enough to create a cached statement
when you do this, and only execute your code when necessary. You put an
expression (or another taglib) within the parameter tag (see the example
below).

`<esql:results'>
----------------

     parent: <esql:execute-query>

   The contents of this tag are "executed" whenever the query returns some
results.

`<esql:row-results'>
--------------------

     parent: <esql:results>

   The contents of this tag are "executed" for each row of the results

`<esql:get-columns'>
--------------------

     parent: <esql:row-results>

   This tag gets all of the columns in the current row, and outputs them
as `<column_name'>`value</column_name'>. If you specify an attribute
`tag-case="upper"', all columns are upper case. Alternatively, "lower"
gives you all tags in lower case. An ancestor attribute is also allowed,
see "Nested Results" below for more details.

get-*
-----

     parent: <esql:row-results>

   These are:

     get-column
     get-string
     get-boolean
     get-double
     get-float
     get-int
     get-long
     get-short

   (and more below)

   Each of these takes either an attribute column="name", or a child tag,
`<esql:column'> which gives the column name. Alternatively either the
attribute or child element can be an integer (starting at 1) specifying
the column number.

   Also allowed is an ancestor attribute, which is an integer (default 0),
which indicates how far up the nested results you go. See Nested Results
below.

`<esql:get-date'>, `<esql:get-time'>, `<esql:get-timestamp'>
------------------------------------------------------------

     parent: <esql:row-results>

   These tags are the same as get-* above, except they also take a
`format="..."' attribute, which contains a strftime formatting string.

`<esql:get-xml'>
----------------

     parent: <esql:row-results>

   Again the same as get-* above. This tag assumes the contents of the
column are valid XML, and appends that XML into the result tree.

`<esql:get-row-position'>
-------------------------

     parent: <esql:row-results>

   Gets the current row number. Optional `ancestor' attribute.

`<esql:get-column-name'>
------------------------

     parent: <esql:row-results>

   Gets the column name indicated by the numbered column in the
`column="..."' attribute, or the child `<esql:column'> element. The
attribute/child can actually be a string (name), but then what is the
point of that?

`<esql:get-column-label'>
-------------------------

     parent: <esql:row-results>

   Gets the label of the column. This is a hang-over from the Cocoon java
implementation where sadly nobody seems to know what label is compared
with name. In this case, get-column-name is always lower case, whereas
get-column-label is returned in the case that the DBD driver returns it as.

`<esql:get-column-type-name'>
-----------------------------

     parent: <esql:row-results>

   Returns the TYPE_NAME of the column indicated as other get-* elements.
See the DBI docs for more details.

`<esql:no-results'>
-------------------

     parent: <esql:execute-query>

   The contents of this element are executed when the SQL returned no rows.

`<esql:update-results'>
-----------------------

     parent: <esql:execute-query>

   The contents of this element are executed when the SQL was an update
statement. The number of rows updated are in the $rv variable.

Nested Results
==============

   With the ESQL taglib it is quite possible to do nested results. This is
a way to emulate outer joins, or just better organise things. See below
for an example of this.

   When using nested results, you can use the ancestor attribute on any of
the get-* elements to get results from higher up the ancestry of results.

Errors
======

   Unlike the original Cocoon version of this taglib, we let you handle
errors however you choose to, using the exception taglib. If an error
occurs, ESQL will throw an exception. If you don't capture this exception
it will propogate up to the core of AxKit, and either give a 500 internal
server error, or execute the AxErrorStylesheet if one is defined. See
AxKit.

EXAMPLE
=======

     <esql:connection>
     <esql:driver>Pg</esql:driver>
     <esql:dburl>dbname=axkit</esql:dburl>
     <esql:username>postgres</esql:username>
     <esql:password></esql:password>
     <esql:execute-query>
       <esql:query>
         select id,name from department_table where foo =
         <esql:parameter><xsp:expr>4 + 5</xsp:expr></esql:parameter>
       </esql:query>
       <esql:results>
         <header>header info</header>
         <esql:row-results>
           <department>
             <id><esql:get-int column="id"/></id>
             <name><esql:get-string column="name"/></name>
             <esql:connection>
               <esql:driver>org.postgresql.Driver</esql:driver>
               <esql:dburl>jdbc:postgresql://localhost/test</esql:dburl>
               <esql:username>test</esql:username>
               <esql:password>test</esql:password>
               <esql:execute-query>
                 <esql:query>select name from user_table where department_id = <esql:parameter type="int"><esql:get-int ancestor="1" column="id"/></esql:parameter></esql:query>
                 <esql:results>
                   <esql:row-results>
                     <user><esql:get-string column="name"/></user>
                   </esql:row-results>
                 </esql:results>
                 <esql:no-results>
                   <user>No employees</user>
                 </esql:no-results>
               </esql:execute-query>
             </esql:connection>
           </department>
         </esql:row-results>
         <footer>footer info</footer>
       </esql:results>
       <esql:no-results>
         <department>No departments</department>
       </esql:no-results>
     </esql:execute-query>
     </esql:connection>

AUTHOR
======

   Matt Sergeant, matt@axkit.com. Original Cocoon taglib by Donald Ball

COPYRIGHT
=========

   Copyright 2001 AxKit.com Ltd. You may use this module under the same
terms as AxKit itself.

SEE ALSO
========

   See AxKit, `DBI' in this node, see
Apache/AxKit/Language/XSP, the AxKit.org pages
at http://axkit.org/

Exceptions taglib for eXtensible Server Pages
*********************************************

NAME
====

   AxKit::XSP::Exception - Exceptions taglib for eXtensible Server Pages

SYNOPSIS
========

   Add the sendmail: namespace to your XSP `<xsp:page'> tag:

     <xsp:page
          language="Perl"
          xmlns:xsp="http://apache.org/xsp/core/v1"
          xmlns:except="http://axkit.org/NS/xsp/exception/v1"
     >

   And add this taglib to AxKit (via httpd.conf or .htaccess):

     AxAddXSPTaglib AxKit::XSP::Exception

DESCRIPTION
===========

   Allows you to catch exceptions thrown by either your own code, or other
taglibs.

EXAMPLE
=======

   This example shows all the tags in action:

     <except:try>
      <mail:send-mail>...</mail:send-mail>
      <except:catch>
       <p>An Error occured: <except:message/></p>
      </except:catch>
     </except:try>

AUTHOR
======

   Matt Sergeant, matt@axkit.com

COPYRIGHT
=========

   Copyright (c) 2001 AxKit.com Ltd. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   AxKit

A namespace wrapper for accessing HTTP request paramaters.
**********************************************************

NAME
====

   AxKit::XSP::Param - A namespace wrapper for accessing HTTP request
paramaters.

SYNOPSIS
========

   Add the param: namespace to your XSP `<xsp:page'> tag:

     <xsp:page
          language="Perl"
          xmlns:xsp="http://apache.org/xsp/core/v1"
          xmlns:sendmail="http://axkit.org/NS/xsp/param/v1"
     >

   And add the taglib to AxKit (via httpd.conf or .htaccess):

     AxAddXSPTaglib AxKit::XSP::Param

DESCRIPTION
===========

   The XSP param: tag library implements a simple way to access HTTP
request parameters (query string and posted form data) by field name.

   Thus, the value submitted from this text box

     <input type="text" name="username"/>

   is available after POSTing as

     <param:username/>

   The same is true for information passed through the query string.

   The best way to describe this taglib's use is with a few examples:

   *Simple inline text insertion* -

     <p>
       Greetings, <param:username />, welcome to our site!
     </p>

   *As the contents of another element* -

     <custom-element><param:param_name /></custom-element>

   *As the attribute value for another elememnt* -

     <input type="hidden" name="foo">
       <xsp:attribute name="value"><param:foo/></xsp:attribute>
     </input>

   Note that if the specified parameter field does not exist no error is
thrown. So, this:

     <input type="hidden" name="secret_data">
       <xsp:attribute name="value"><param:bogus_name/></xsp:attribute>
     </input>

   Will result in following after proccessing:

     <input type="hidden" name="secret_data" value="">

Tag Reference
-------------

   There are no named functions for this tag library.

AUTHOR
======

   Kip Hampton, khampton@totalcinema.com

COPYRIGHT
=========

   Copyright (c) 2001 Kip Hampton. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   AxKit

Simple SMTP mailer tag library for AxKit eXtesible Server Pages.
****************************************************************

NAME
====

   AxKit::XSP::Sendmail - Simple SMTP mailer tag library for AxKit
eXtesible Server Pages.

SYNOPSIS
========

   Add the sendmail: namespace to your XSP `<xsp:page'> tag:

     <xsp:page
          language="Perl"
          xmlns:xsp="http://apache.org/xsp/core/v1"
          xmlns:sendmail="http://axkit.org/NS/xsp/sendmail/v1"
     >

   And add this taglib to AxKit (via httpd.conf or .htaccess):

     AxAddXSPTaglib AxKit::XSP::Sendmail

DESCRIPTION
===========

   The XSP sendmail: taglib adds a simple SMTP mailer to XSP via Milivoj
Ivkovic's platform-neutral Mail::Sendmail module. In addition, all email
addresses are validated before sending using Maurice Aubrey's Email::Valid
package. This taglib is identical to the Cocoon taglib of the same name,
albeit in a different namespace..

Tag Reference
=============

`<sendmail:send-mail'>
----------------------

   This is the required 'wrapper' element for the sendmail taglib branch.

`<sendmail:smtphost'>
---------------------

   The this element sets the outgoing SMTP server for the current message.
If ommitted, the default set in Mail::Sendmail's %mailcfg hash will be
used instead.

`<sendmail:from'>
-----------------

   Defines the 'From' field in the outgoing message. If ommited, this
field defaults to value set in Mail::Sendmail's %mailcfg hash. Run
`perldoc Mall:Sendmail' for more detail.

`<sendmail:to'>
---------------

   Defines a 'To' field in the outgoing message. Multiple instances are
allowed.

`<sendmail:cc'>
---------------

   Defines a 'Cc' field in the outgoing message. Multiple instances are
allowed.

`<sendmail:bcc'>
----------------

   Defines a 'Bcc' field in the outgoing message. Multiple instances are
allowed.

`<sendmail:body'>
-----------------

   Defines the body of the outgoing message.

EXAMPLE
=======

   my $mail_message = 'I'm a victim of circumstance!';

     <sendmail:send-mail>
       <sendmail:from>curly@localhost</sendmail:from>
       <sendmail:to>moe@spreadout.org</sendmail:to>
       <sendmail:cc>larry@porcupine.com</sendmail:cc>
       <sendmail:bcc>shemp@alsoran.net</sendmail:cc>
       <sendmail:body><xsp:expr>$mail_message</xsp:expr></sendmail:body>
     </sendmail:send-mail>

ERRORS
======

   When sending email fails, or an address is invalid, this taglib will
throw an exception, which you can catch with the AxKit exceptions taglib.

AUTHOR
======

   Kip Hampton, khampton@totalcinema.com

COPYRIGHT
=========

   Copyright (c) 2001 Kip Hampton. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   AxKit, Mail::Sendmail, Email::Valid

XSP util: taglib.
*****************

NAME
====

   AxKit::XSP::Util - XSP util: taglib.

SYNOPSIS
========

   Add the util: namespace to your XSP `<xsp:page'> tag:

     <xsp:page
          language="Perl"
          xmlns:xsp="http://apache.org/xsp/core/v1"
          xmlns:util="http://apache.org/xsp/util/v1"
     >

   And add this taglib to AxKit (via httpd.conf or .htaccess):

     AxAddXSPTaglib AxKit::XSP::Util

DESCRIPTION
===========

   The XSP util: taglib seeks to add a short list of basic utility
functions to the eXtesible Server Pages library. It trivializes the
inclusion of external fragments and adds a few other useful bells and
whistles.

TAG STRUCTURE
=============

   Most of of the tags require some sort of "argument" to be passed (e.g.
`<util:include-file'> requires the name of the file that is to be read).
Unless otherwise noted, all tags allow you to pass this information either
as an attribute of the current  element or as the text node of an
appropriately named child.

   Thus, both:

     <util:include-file name="foo.xml" />

   and

     <util:include-file>
     <util:name>foo.xml</util:name>
     </util:include-file>

   are valid.

TAG REFERENCE
=============

`<util:include-file'>
---------------------

   Provides a way to include an XML fragment from a local file into the
current parse tree. Requires a name argument. The path may be relative or
absolute.

`<util:include-uri'>
--------------------

   Provides a way to include an XML fragment from a (possibly) remote URI.
Requires an href argument.

`<util:get-file-contents'>
--------------------------

   Provides a way to include a local file *as plain text*. Requires a name
argument. The path may be relative or absolute.

`<util:include-expr'>
---------------------

   Provides a way to include an XML fragment from a scalar variable. Note
that this tag may *only* pass the required  *expr* argument as a child
node. Example:

     <util:include-expr>
     <xsp:expr>$xml_fragment</xsp:expr>
     </util:include-expr>

`<util:time'>
-------------

   Returns a formatted time/date string. Requires a format attribute.  The
format is defined using the standard strftime() syntax.

AUTHOR
======

   Kip Hampton, khampton@totalcinema.com

SEE ALSO
========

   AxKit.

The Perl Compiler
*****************

NAME
====

   B - The Perl Compiler

SYNOPSIS
========

     use B;

DESCRIPTION
===========

   The B module supplies classes which allow a Perl program to delve into
its own innards. It is the module used to implement the "backends" of the
Perl compiler. Usage of the compiler does not require knowledge of this
module: see the O module for the user-visible part. The B module is of use
to those who want to write new compiler backends. This documentation
assumes that the reader knows a fair amount about perl's internals
including such things as SVs, OPs and the internal symbol table and syntax
tree of a program.

OVERVIEW OF CLASSES
===================

   The C structures used by Perl's internals to hold SV and OP information
(PVIV, AV, HV, ..., OP, SVOP, UNOP, ...) are modelled on a class hierarchy
and the B module gives access to them via a true object hierarchy.
Structure fields which point to other objects (whether types of SV or
types of OP) are represented by the B module as Perl objects of the
appropriate class. The bulk of the B module is the methods for accessing
fields of these structures. Note that all access is read-only: you cannot
modify the internals by using this module.

SV-RELATED CLASSES
------------------

   B::IV, B::NV, B::RV, B::PV, B::PVIV, B::PVNV, B::PVMG, B::BM, B::PVLV,
B::AV, B::HV, B::CV, B::GV, B::FM, B::IO. These classes correspond in the
obvious way to the underlying C structures of similar names. The
inheritance hierarchy mimics the underlying C "inheritance". Access
methods correspond to the underlying C macros for field access, usually
with the leading "class indication" prefix removed (Sv, Av, Hv, ...). The
leading prefix is only left in cases where its removal would cause a clash
in method name. For example, GvREFCNT stays as-is since its abbreviation
would clash with the "superclass" method REFCNT (corresponding to the C
function SvREFCNT).

B::SV METHODS
-------------

REFCNT
FLAGS
B::IV METHODS
-------------

IV
IVX

needs64bits
packiv
B::NV METHODS
-------------

NV
NVX
B::RV METHODS
-------------

RV
B::PV METHODS
-------------

PV
B::PVMG METHODS
---------------

MAGIC
SvSTASH
B::MAGIC METHODS
----------------

MOREMAGIC
PRIVATE
TYPE
FLAGS
OBJ
PTR
B::PVLV METHODS
---------------

TARGOFF
TARGLEN
TYPE
TARG
B::BM METHODS
-------------

USEFUL
PREVIOUS
RARE
TABLE
B::GV METHODS
-------------

is_empty
     This method returns TRUE if the GP field of the GV is NULL.

NAME
STASH
SV
IO
FORM
AV
HV
EGV
CV
CVGEN
LINE
FILE
FILEGV
GvREFCNT
FLAGS
B::IO METHODS
-------------

LINES
PAGE
PAGE_LEN
LINES_LEFT
TOP_NAME
TOP_GV
FMT_NAME
FMT_GV
BOTTOM_NAME
BOTTOM_GV
SUBPROCESS
IoTYPE
IoFLAGS
B::AV METHODS
-------------

FILL
MAX
OFF
ARRAY
AvFLAGS
B::CV METHODS
-------------

STASH
START
ROOT
GV
FILE
DEPTH
PADLIST
OUTSIDE
XSUB
XSUBANY
CvFLAGS
B::HV METHODS
-------------

FILL
MAX
KEYS
RITER
NAME
PMROOT
ARRAY
OP-RELATED CLASSES
------------------

   B::OP, B::UNOP, B::BINOP, B::LOGOP, B::LISTOP, B::PMOP, B::SVOP,
B::PADOP, B::PVOP, B::CVOP, B::LOOP, B::COP.  These classes correspond in
the obvious way to the underlying C structures of similar names. The
inheritance hierarchy mimics the underlying C "inheritance". Access
methods correspond to the underlying C structre field names, with the
leading "class indication" prefix removed (op_).

B::OP METHODS
-------------

next
sibling
name
     This returns the op name as a string (e.g. "add", "rv2av").

ppaddr
     This returns the function name as a string (e.g. "PL_ppaddr[OP_ADD]",
     "PL_ppaddr[OP_RV2AV]").

desc
     This returns the op description from the global C PL_op_desc array
     (e.g. "addition" "array deref").

targ
type
seq
flags
private
B::UNOP METHOD
--------------

first
B::BINOP METHOD
---------------

last
B::LOGOP METHOD
---------------

other
B::LISTOP METHOD
----------------

children
B::PMOP METHODS
---------------

pmreplroot
pmreplstart
pmnext
pmregexp
pmflags
pmpermflags
precomp
B::SVOP METHOD
--------------

sv
gv
B::PADOP METHOD
---------------

padix
B::PVOP METHOD
--------------

pv
B::LOOP METHODS
---------------

redoop
nextop
lastop
B::COP METHODS
--------------

label
stash
file
cop_seq
arybase
line
FUNCTIONS EXPORTED BY B
=======================

   The B module exports a variety of functions: some are simple utility
functions, others provide a Perl program with a way to get an initial
"handle" on an internal object.

main_cv
     Return the (faked) CV corresponding to the main part of the Perl
     program.

init_av
     Returns the AV object (i.e. in class B::AV) representing INIT blocks.

main_root
     Returns the root op (i.e. an object in the appropriate B::OP-derived
     class) of the main part of the Perl program.

main_start
     Returns the starting op of the main part of the Perl program.

comppadlist
     Returns the AV object (i.e. in class B::AV) of the global comppadlist.

sv_undef
     Returns the SV object corresponding to the C variable sv_undef.

sv_yes
     Returns the SV object corresponding to the C variable sv_yes.

sv_no
     Returns the SV object corresponding to the C variable sv_no.

amagic_generation
     Returns the SV object corresponding to the C variable
     amagic_generation.

walkoptree(OP, METHOD)
     Does a tree-walk of the syntax tree based at OP and calls METHOD on
     each op it visits. Each node is visited before its children. If
     `walkoptree_debug' (q.v.) has been called to turn debugging on then
     the method `walkoptree_debug' is called on each op before METHOD is
     called.

walkoptree_debug(DEBUG)
     Returns the current debugging flag for `walkoptree'. If the optional
     DEBUG argument is non-zero, it sets the debugging flag to that. See
     the description of `walkoptree' above for what the debugging flag
     does.

walksymtable(SYMREF, METHOD, RECURSE)
     Walk the symbol table starting at SYMREF and call METHOD on each
     symbol visited. When the walk reached package symbols "Foo::" it
     invokes RECURSE and only recurses into the package if that sub
     returns true.

svref_2object(SV)
     Takes any Perl variable and turns it into an object in the
     appropriate B::OP-derived or B::SV-derived class. Apart from functions
     such as main_root, this is the primary way to get an initial "handle"
     on a internal perl data structure which can then be followed with the
     other access methods.

ppname(OPNUM)
     Return the PP function name (e.g. "pp_add") of op number OPNUM.

hash(STR)
     Returns a string in the form "0x..." representing the value of the
     internal hash function used by perl on string STR.

cast_I32(I)
     Casts I to the internal I32 type used by that perl.

minus_c
     Does the equivalent of the -c command-line option. Obviously, this is
     only useful in a BEGIN block or else the flag is set too late.

cstring(STR)
     Returns a double-quote-surrounded escaped version of STR which can be
     used as a string in C source code.

class(OBJ)
     Returns the class of an object without the part of the classname
     preceding the first "::". This is used to turn "B::UNOP" into "UNOP"
     for example.

threadsv_names
     In a perl compiled for threads, this returns a list of the special
     per-thread threadsv variables.

AUTHOR
======

   Malcolm Beattie, `mbeattie@sable.ox.ac.uk'

Autogenerated data about Perl ops, used to generate bytecode
************************************************************

NAME
====

   B::Asmdata - Autogenerated data about Perl ops, used to generate
bytecode

SYNOPSIS
========

     use Asmdata;

DESCRIPTION
===========

   See `ext/B/B/Asmdata.pm'.

AUTHOR
======

   Malcolm Beattie, `mbeattie@sable.ox.ac.uk'

Assemble Perl bytecode
**********************

NAME
====

   B::Assembler - Assemble Perl bytecode

SYNOPSIS
========

     use Assembler;

DESCRIPTION
===========

   See `ext/B/B/Assembler.pm'.

AUTHOR
======

   Malcolm Beattie, `mbeattie@sable.ox.ac.uk'

Walk basic blocks
*****************

NAME
====

   B::Bblock - Walk basic blocks

SYNOPSIS
========

     perl -MO=Bblock[,OPTIONS] foo.pl

DESCRIPTION
===========

   This module is used by the B::CC back end.  It walks "basic blocks".  A
basic block is a series of operations which is known to execute from start
to finish, with no possiblity of branching or halting.

AUTHOR
======

   Malcolm Beattie, `mbeattie@sable.ox.ac.uk'

Perl compiler's bytecode backend
********************************

NAME
====

   B::Bytecode - Perl compiler's bytecode backend

SYNOPSIS
========

     perl -MO=Bytecode[,OPTIONS] foo.pl

DESCRIPTION
===========

   This compiler backend takes Perl source and generates a
platform-independent bytecode encapsulating code to load the internal
structures perl uses to run your program. When the generated bytecode is
loaded in, your program is ready to run, reducing the time which perl
would have taken to load and parse your program into its internal
semi-compiled form. That means that compiling with this backend will not
help improve the runtime execution speed of your program but may improve
the start-up time.  Depending on the environment in which your program
runs this may or may not be a help.

   The resulting bytecode can be run with a special byteperl executable or
(for non-main programs) be loaded via the `byteload_fh' function in the B
module.

OPTIONS
=======

   If there are any non-option arguments, they are taken to be names of
objects to be saved (probably doesn't work properly yet).  Without extra
arguments, it saves the main program.

*-ofilename*
     Output to filename instead of STDOUT.

*-afilename*
     Append output to filename.

-
     Force end of options.

-f
     Force optimisations on or off one at a time. Each can be preceded by
     *no-* to turn the option off (e.g. *-fno-compress-nullops*).

*-fcompress-nullops*
     Only fills in the necessary fields of ops which have been optimised
     away by perl's internal compiler.

*-fomit-sequence-numbers*
     Leaves out code to fill in the op_seq field of all ops which is only
     used by perl's internal compiler.

*-fbypass-nullops*
     If op->op_next ever points to a NULLOP, replaces the op_next field
     with the first non-NULLOP in the path of execution.

*-fstrip-syntax-tree*
     Leaves out code to fill in the pointers which link the internal syntax
     tree together. They're not needed at run-time but leaving them out
     will make it impossible to recompile or disassemble the resulting
     program.  It will also stop `goto label' statements from working.

*-On*
     Optimisation level (n = 0, 1, 2, ...). -O means *-O1*.  *-O1* sets
     *-fcompress-nullops* *-fomit-sequence numbers*.  *-O6* adds
     *-fstrip-syntax-tree*.

-D
     Debug options (concatenated or separate flags like `perl -D').

*-Do*
     Prints each OP as it's processed.

*-Db*
     Print debugging information about bytecompiler progress.

*-Da*
     Tells the (bytecode) assembler to include source assembler lines in
     its output as bytecode comments.

*-DC*
     Prints each CV taken from the final symbol tree walk.

-S
     Output (bytecode) assembler source rather than piping it through the
     assembler and outputting bytecode.

-m
     Compile as a module rather than a standalone program. Currently this
     just means that the bytecodes for initialising main_start, main_root
     and `curpad' are omitted.

EXAMPLES
========

     perl -MO=Bytecode,-O6,-o,foo.plc foo.pl

     perl -MO=Bytecode,-S foo.pl > foo.S
     assemble foo.S > foo.plc

   Note that `assemble' lives in the B subdirectory of your perl library
directory. The utility called perlcc may also be used to help make use of
this compiler.

     perl -MO=Bytecode,-m,-oFoo.pmc Foo.pm

BUGS
====

   Plenty. Current status: experimental.

AUTHOR
======

   Malcolm Beattie, `mbeattie@sable.ox.ac.uk'

Perl compiler's C backend
*************************

NAME
====

   B::C - Perl compiler's C backend

SYNOPSIS
========

     perl -MO=C[,OPTIONS] foo.pl

DESCRIPTION
===========

   This compiler backend takes Perl source and generates C source code
corresponding to the internal structures that perl uses to run your
program. When the generated C source is compiled and run, it cuts out the
time which perl would have taken to load and parse your program into its
internal semi-compiled form. That means that compiling with this backend
will not help improve the runtime execution speed of your program but may
improve the start-up time.  Depending on the environment in which your
program runs this may be either a help or a hindrance.

OPTIONS
=======

   If there are any non-option arguments, they are taken to be names of
objects to be saved (probably doesn't work properly yet).  Without extra
arguments, it saves the main program.

*-ofilename*
     Output to filename instead of STDOUT

-v
     Verbose compilation (currently gives a few compilation statistics).

-
     Force end of options

*-uPackname*
     Force apparently unused subs from package Packname to be compiled.
     This allows programs to use eval "foo()" even when sub foo is never
     seen to be used at compile time. The down side is that any subs which
     really are never used also have code generated. This option is
     necessary, for example, if you have a signal handler foo which you
     initialise with `$SIG{BAR} = "foo"'.  A better fix, though, is just
     to change it to `$SIG{BAR} = \&foo'. You can have multiple -u
     options. The compiler tries to figure out which packages may possibly
     have subs in which need compiling but the current version doesn't do
     it very well. In particular, it is confused by nested packages (i.e.
     of the form `A::B') where package A does not contain any subs.

-D
     Debug options (concatenated or separate flags like `perl -D').

*-Do*
     OPs, prints each OP as it's processed

*-Dc*
     COPs, prints COPs as processed (incl. file & line num)

*-DA*
     prints AV information on saving

*-DC*
     prints CV information on saving

*-DM*
     prints MAGIC information on saving

-f
     Force optimisations on or off one at a time.

*-fcog*
     Copy-on-grow: PVs declared and initialised statically.

*-fno-cog*
     No copy-on-grow.

*-On*
     Optimisation level (n = 0, 1, 2, ...). -O means *-O1*.  Currently,
     *-O1* and higher set *-fcog*.

*-llimit*
     Some C compilers impose an arbitrary limit on the length of string
     constants (e.g. 2048 characters for Microsoft Visual C++).  The
     *-llimit* options tells the C backend not to generate string literals
     exceeding that limit.

EXAMPLES
========

     perl -MO=C,-ofoo.c foo.pl
     perl cc_harness -o foo foo.c

   Note that `cc_harness' lives in the B subdirectory of your perl library
directory. The utility called perlcc may also be used to help make use of
this compiler.

     perl -MO=C,-v,-DcA,-l2048 bar.pl > /dev/null

BUGS
====

   Plenty. Current status: experimental.

AUTHOR
======

   Malcolm Beattie, `mbeattie@sable.ox.ac.uk'

Perl compiler's optimized C translation backend
***********************************************

NAME
====

   B::CC - Perl compiler's optimized C translation backend

SYNOPSIS
========

     perl -MO=CC[,OPTIONS] foo.pl

DESCRIPTION
===========

   This compiler backend takes Perl source and generates C source code
corresponding to the flow of your program. In other words, this backend is
somewhat a "real" compiler in the sense that many people think about
compilers. Note however that, currently, it is a very poor compiler in
that although it generates (mostly, or at least sometimes) correct code,
it performs relatively few optimisations.  This will change as the
compiler develops. The result is that running an executable compiled with
this backend may start up more quickly than running the original Perl
program (a feature shared by the C compiler backend-see B::C) and may also
execute slightly faster. This is by no means a good optimising
compiler-yet.

OPTIONS
=======

   If there are any non-option arguments, they are taken to be names of
objects to be saved (probably doesn't work properly yet).  Without extra
arguments, it saves the main program.

*-ofilename*
     Output to filename instead of STDOUT

-v
     Verbose compilation (currently gives a few compilation statistics).

-
     Force end of options

*-uPackname*
     Force apparently unused subs from package Packname to be compiled.
     This allows programs to use eval "foo()" even when sub foo is never
     seen to be used at compile time. The down side is that any subs which
     really are never used also have code generated. This option is
     necessary, for example, if you have a signal handler foo which you
     initialise with `$SIG{BAR} = "foo"'.  A better fix, though, is just
     to change it to `$SIG{BAR} = \&foo'. You can have multiple -u
     options. The compiler tries to figure out which packages may possibly
     have subs in which need compiling but the current version doesn't do
     it very well. In particular, it is confused by nested packages (i.e.
     of the form `A::B') where package A does not contain any subs.

*-mModulename*
     Instead of generating source for a runnable executable, generate
     source for an XSUB module. The boot_Modulename function (which
     DynaLoader can look for) does the appropriate initialisation and runs
     the main part of the Perl source that is being compiled.

-D
     Debug options (concatenated or separate flags like `perl -D').

*-Dr*
     Writes debugging output to STDERR just as it's about to write to the
     program's runtime (otherwise writes debugging info as comments in its
     C output).

*-DO*
     Outputs each OP as it's compiled

*-Ds*
     Outputs the contents of the shadow stack at each OP

*-Dp*
     Outputs the contents of the shadow pad of lexicals as it's loaded for
     each sub or the main program.

*-Dq*
     Outputs the name of each fake PP function in the queue as it's about
     to process it.

*-Dl*
     Output the filename and line number of each original line of Perl
     code as it's processed (`pp_nextstate').

*-Dt*
     Outputs timing information of compilation stages.

-f
     Force optimisations on or off one at a time.

*-ffreetmps-each-bblock*
     Delays FREETMPS from the end of each statement to the end of the each
     basic block.

*-ffreetmps-each-loop*
     Delays FREETMPS from the end of each statement to the end of the group
     of basic blocks forming a loop. At most one of the freetmps-each-*
     options can be used.

*-fomit-taint*
     Omits generating code for handling perl's tainting mechanism.

*-On*
     Optimisation level (n = 0, 1, 2, ...). -O means *-O1*.  Currently,
     *-O1* sets *-ffreetmps-each-bblock* and *-O2* sets
     *-ffreetmps-each-loop*.

EXAMPLES
========

     perl -MO=CC,-O2,-ofoo.c foo.pl
     perl cc_harness -o foo foo.c

   Note that `cc_harness' lives in the B subdirectory of your perl library
directory. The utility called perlcc may also be used to help make use of
this compiler.

     perl -MO=CC,-mFoo,-oFoo.c Foo.pm
     perl cc_harness -shared -c -o Foo.so Foo.c

BUGS
====

   Plenty. Current status: experimental.

DIFFERENCES
===========

   These aren't really bugs but they are constructs which are heavily tied
to perl's compile-and-go implementation and with which this compiler
backend cannot cope.

Loops
-----

   Standard perl calculates the target of "next", "last", and "redo" at
run-time. The compiler calculates the targets at compile-time.  For
example, the program

     sub skip_on_odd { next NUMBER if $_[0] % 2 }
     NUMBER: for ($i = 0; $i < 5; $i++) {
         skip_on_odd($i);
         print $i;
     }

   produces the output

     024

   with standard perl but gives a compile-time error with the compiler.

Context of ".."
---------------

   The context (scalar or array) of the ".." operator determines whether
it behaves as a range or a flip/flop. Standard perl delays until runtime
the decision of which context it is in but the compiler needs to know the
context at compile-time. For example,

     @a = (4,6,1,0,0,1);
     sub range { (shift @a)..(shift @a) }
     print range();
     while (@a) { print scalar(range()) }

   generates the output

     456123E0

   with standard Perl but gives a compile-time error with compiled Perl.

Arithmetic
----------

   Compiled Perl programs use native C arithemtic much more frequently
than standard perl. Operations on large numbers or on boundary cases may
produce different behaviour.

Deprecated features
-------------------

   Features of standard perl such as $[ which have been deprecated in
standard perl since Perl5 was released have not been implemented in the
compiler.

AUTHOR
======

   Malcolm Beattie, `mbeattie@sable.ox.ac.uk'

Walk Perl syntax tree, printing debug info about ops
****************************************************

NAME
====

   B::Debug - Walk Perl syntax tree, printing debug info about ops

SYNOPSIS
========

     perl -MO=Debug[,OPTIONS] foo.pl

DESCRIPTION
===========

   See `ext/B/README'.

AUTHOR
======

   Malcolm Beattie, `mbeattie@sable.ox.ac.uk'

Perl compiler backend to produce perl code
******************************************

NAME
====

   B::Deparse - Perl compiler backend to produce perl code

SYNOPSIS
========

   *perl* *-MO=Deparse*[*,-u*PACKAGE][*,-p*][*,-q*][*,-l*][*,-s**LETTERS*]
    *prog.pl*

DESCRIPTION
===========

   B::Deparse is a backend module for the Perl compiler that generates
perl source code, based on the internal compiled structure that perl
itself creates after parsing a program. The output of B::Deparse won't be
exactly the same as the original source, since perl doesn't keep track of
comments or whitespace, and there isn't a one-to-one correspondence
between perl's syntactical constructions and their compiled form, but it
will often be close. When you use the -p option, the output also includes
parentheses even when they are not required by precedence, which can make
it easy to see if perl is parsing your expressions the way you intended.

   Please note that this module is mainly new and untested code and is
still under development, so it may change in the future.

OPTIONS
=======

   As with all compiler backend options, these must follow directly after
the '-MO=Deparse', separated by a comma but not any white space.

-l
     Add '#line' declarations to the output based on the line and file
     locations of the original code.

-p
     Print extra parentheses. Without this option, B::Deparse includes
     parentheses in its output only when they are needed, based on the
     structure of your program. With -p, it uses parentheses (almost)
     whenever they would be legal. This can be useful if you are used to
     LISP, or if you want to see how perl parses your input. If you say

          if ($var & 0x7f == 65) {print "Gimme an A!"}
          print ($which ? $a : $b), "\n";
          $name = $ENV{USER} or "Bob";

     `B::Deparse,-p' will print

          if (($var & 0)) {
              print('Gimme an A!')
          };
          (print(($which ? $a : $b)), '???');
          (($name = $ENV{'USER'}) or '???')

     which probably isn't what you intended (the `'???'' is a sign that
     perl optimized away a constant value).

-q
     Expand double-quoted strings into the corresponding combinations of
     concatenation, uc, ucfirst, lc, lcfirst, quotemeta, and join. For
     instance, print

          print "Hello, $world, @ladies, \u$gentlemen\E, \u\L$me!";

     as

          print 'Hello, ' . $world . ', ' . join($", @ladies) . ', '
                . ucfirst($gentlemen) . ', ' . ucfirst(lc $me . '!');

     Note that the expanded form represents the way perl handles such
     constructions internally - this option actually turns off the reverse
     translation that B::Deparse usually does. On the other hand, note that
     `$x = "$y"' is not the same as `$x = $y': the former makes the value
     of $y into a string before doing the assignment.

-uPACKAGE
     Normally, B::Deparse deparses the main code of a program, all the subs
     called by the main program (and all the subs called by them,
     recursively), and any other subs in the main:: package. To include
     subs in other packages that aren't called directly, such as AUTOLOAD,
     DESTROY, other subs called automatically by perl, and methods (which
     aren't resolved to subs until runtime), use the -u option. The
     argument to -u is the name of a package, and should follow directly
     after the 'u'. Multiple -u options may be given, separated by commas.
     Note that unlike some other backends, B::Deparse doesn't (yet) try
     to guess automatically when -u is needed - you must invoke it
     yourself.

-s*LETTERS*
     Tweak the style of B::Deparse's output. The letters should follow
     directly after the 's', with no space or punctuation. The following
     options are available:

    C
          Cuddle `elsif', else, and continue blocks. For example, print

               if (...) {
                    ...
               } else {
                    ...
               }

          instead of

               if (...) {
                    ...
               }
               else {
                    ...
               }

          The default is not to cuddle.

    i*NUMBER*
          Indent lines by multiples of *NUMBER* columns. The default is 4
          columns.

    T
          Use tabs for each 8 columns of indent. The default is to use
          only spaces.  For instance, if the style options are *-si4T*, a
          line that's indented 3 times will be preceded by one tab and
          four spaces; if the options were *-si8T*, the same line would be
          preceded by three tabs.

    vSTRING.
          Print STRING for the value of a constant that can't be determined
          because it was optimized away (mnemonic: this happens when a
          constant is used in void context). The end of the string is
          marked by a period.  The string should be a valid perl
          expression, generally a constant.  Note that unless it's a
          number, it probably needs to be quoted, and on a command line
          quotes need to be protected from the shell. Some conventional
          values include 0, 1, 42, ", 'foo', and 'Useless use of constant
          omitted' (which may need to be *-sv"'Useless use of constant
          omitted'."* or something similar depending on your shell). The
          default is '???'.  If you're using B::Deparse on a module or
          other file that's require'd, you shouldn't use a value that
          evaluates to false, since the customary true constant at the end
          of a module will be in void context when the file is compiled as
          a main program.

USING B::Deparse AS A MODULE
============================

Synopsis
--------

     use B::Deparse;
     $deparse = B::Deparse->new("-p", "-sC");
     $body = $deparse->coderef2text(\&func);
     eval "sub func $body"; # the inverse operation

Description
-----------

   B::Deparse can also be used on a sub-by-sub basis from other perl
programs.

new
---

     $deparse = B::Deparse->new(OPTIONS)

   Create an object to store the state of a deparsing operation and any
options. The options are the same as those that can be given on the
command line (see `' in this node); options that are separated by commas
after *-MO=Deparse* should be given as separate strings. Some options,
like -u, don't make sense for a single subroutine, so don't pass them.

coderef2text
------------

     $body = $deparse->coderef2text(\&func)
     $body = $deparse->coderef2text(sub ($$) { ... })

   Return source code for the body of a subroutine (a block, optionally
preceded by a prototype in parens), given a reference to the sub. Because
a subroutine can have no names, or more than one name, this method doesn't
return a complete subroutine definition - if you want to eval the result,
you should prepend "sub subname ", or "sub " for an anonymous function
constructor. Unless the sub was defined in the main:: package, the code
will include a package declaration.

BUGS
====

   See the 'to do' list at the beginning of the module file.

AUTHOR
======

   Stephen McCamant <smccam@uclink4.berkeley.edu>, based on an earlier
version by Malcolm Beattie <mbeattie@sable.ox.ac.uk>, with contributions
from Gisle Aas, James Duncan, Albert Dvornik, Hugo van der Sanden,
Gurusamy Sarathy, and Nick Ing-Simmons.

Disassemble Perl bytecode
*************************

NAME
====

   B::Disassembler - Disassemble Perl bytecode

SYNOPSIS
========

     use Disassembler;

DESCRIPTION
===========

   See `ext/B/B/Disassembler.pm'.

AUTHOR
======

   Malcolm Beattie, `mbeattie@sable.ox.ac.uk'

a module to evaluate the readability of Perl code
*************************************************

NAME
====

   B::Fathom - a module to evaluate the readability of Perl code

SYNOPSIS
========

     perl -MO=Fathom <script>

   or

     perl -MO=Fathom,-v <script>

   where <script> is the name of the Perl program that you want to
evaluate.

   -v activates verbose mode, which currently reports which subs have been
skipped over because they seem to be imported.  One can also indicate
`-vN', where N is some number greater than zero, to provide *even more*
verbose diagnostics.  The specifics of these modes may change in future
releases.  See comments in the code for further information.

   There is also an OO interface, which can be used as follows:

     my $fathom  = B::Fathom->new('-v');
     my $score   = $fathom->fathom(\&foo);

   See METHODS below for a more complete explanation of the OO interface.

DESCRIPTION
===========

   `B::Fathom' is a backend to the Perl compiler; it analyzes the syntax
of your Perl code, and estimates the readability of your program.

   Currently, this module's idea of `readability' is based on methods used
for analyzing readability of English prose.  Further extensions are
intended.

METHODS
=======

   There is a simple object-oriented interface to B::Fathom.  It consists
of two methods:

new(@args)
     This method constructs a new compiler object.  The optional @args
     indicate compiler options; see SYNOPSIS for a list.

fathom(@subrefs)
     This method grades the subroutines referred to by @subrefs, and
     returns their score as a string.

CAVEATS
=======

   Because of the nature of the compiler, `Fathom' has to do some guessing
about the syntax of your program.  See the comments in the module for
specifics.

   `Fathom' doesn't work very well on modules yet.

AUTHOR
======

   Kurt Starsinic <`kstar@cpan.org'>

COPYRIGHT
=========

     Copyright (c) 1998, 1999, 2000 Kurt Starsinic.
     This module is free software; you may redistribute it
     and/or modify it under the same terms as Perl itself.

A compiler backend to find variables that set sawampersand
**********************************************************

NAME
====

   B::FindAmpersand - A compiler backend to find variables that set
sawampersand

SYNOPSIS
========

     perl -MO=FindAmpersand file.pl

DESCRIPTION
===========

   The Devel::SawAmpersand can tell you if Perl has set `sawampersand',
but it doesn't tell you where.  Sure, you can grep, but what if you don't
know where to grep?

AUTHOR
======

   Doug MacEachern

Create your own op trees.
*************************

NAME
====

   B::Generate - Create your own op trees.

SYNOPSIS
========

     use B::Generate;
     # Do nothing, slowly.
       CHECK {
         my $null = new B::OP("null",0);
         my $enter = new B::OP("enter",0);
         my $cop = new B::COP(0, "hiya", 0);
         my $leave = new B::LISTOP("leave", 0, $enter, $null);
         $leave->children(3);
         $enter->sibling($cop);
         $enter->next($cop);
         $cop->sibling($null);
         $null->next($leave);
         $cop->next($leave);

     # Tell Perl where to find our tree.
     B::main_root($leave);
     B::main_start($enter);
           }

WARNING
=======

   ! WARNING ! WARNING ! WARNING ! WARNING ! WARNING ! WARNING ! WARNING !
WARNING

   `B::Generate' is alpha-quality software. Large parts of it don't work.
Even the parts that do work should give you the willies.

   Patches welcome.

DESCRIPTION
===========

   Malcolm Beattie's B module allows you to examine the Perl op tree at
runtime, in Perl space; it's the basis of the Perl compiler. But what it
doesn't let you do is manipulate that op tree: it won't let you create new
ops, or modify old ones. Now you can.

   Well, if you're intimately familiar with Perl's internals, you can.

   `B::Generate' turns B's accessor methods into get-set methods.  Hence,
instead of merely saying

     $op2 = $op->next;

   you can now say

     $op->next($op2);

   to set the next op in the chain. It also adds constructor methods to
create new ops. This is where it gets really hairy.

     new B::OP     ( type, flags )
     new B::UNOP   ( type, flags, first )
     new B::BINOP  ( type, flags, first, last )
     new B::LOGOP  ( type, flags, first, other )
     new B::LISTOP ( type, flags, first, last )
     new B::COP    ( flags, name, first )

   In all of the above constructors, type is either a numeric value
representing the op type (62 is the addition operator, for instance) or
the name of the op. (`"add"')

   first, last and other are ops to be attached to the current op; these
should be B::OP objects. If you haven't created the ops yet, don't worry;
give a false value, and fill them in later:

     $x = new B::UNOP("negate", 0, undef);
     # ... create some more ops ...
     $x->first($y);

   Finally, you can set the main root and the starting op by passing ops
to the `B::main_root' and `B::main_start' functions.

   This module can obviously be used for all sorts of fun purposes. The
best one will be in conjuction with source filters; have your source
filter parse an input file in a foreign language, create an op tree for it
and get Perl to execute it. Then email me and tell me how you did it.  And
why.

OTHER METHODS
-------------

$b_sv->sv
     Returns a real SV instead of a B::SV. For instance:

          $b_sv = $svop->sv;
          if ($b_sv->sv == 3) {
              print "SVOP's SV has an IV of 3\n"
          }

     You can't use this to set the SV. That would be scary.

$op->dump
     Runs `Perl_op_dump' on an op; this is roughly equivalent to B::Debug,
     but not quite.

$b_sv->dump
     Runs `Perl_sv_dump' on an SV; this is exactly equivalent to `<
     Data::Dumper::dump($b_sv-'sv) >>

EXPORT
------

   None.

AUTHOR
======

   Simon Cozens, `simon@cpan.org'

SEE ALSO
========

   See B, `perlguts', `op.c'

Perl compiler backend to produce graphs of OP trees
***************************************************

NAME
====

   B::Graph - Perl compiler backend to produce graphs of OP trees

SYNOPSIS
========

     perl -MO=Graph,-text prog.pl >graph.txt

     perl -MO=Graph,-vcg prog.pl >graph.vcg
     xvcg graph.vcg

     perl -MO=Graph,-dot prog.pl | dot -Tps >graph.ps

DESCRIPTION
===========

   This module is a backend to the perl compiler (B::*) which, instead of
outputting bytecode or C based on perl's compiled version of a program,
writes descriptions in graph-description languages specifying graphs that
show the program's structure. It currently generates descriptions for the
VCG tool (`http://www.cs.uni-sb.de/RW/users/sander/html/gsvcg1.html') and
Dot (part of the graph visualization toolkit from AT&T:
`http://www.research.att.com/sw/tools/graphviz/'). It also can produce
plain text output (which is more useful for debugging the module itself
than anything else, though you might be able to make cut the nodes out and
make a mobile or something similar).

OPTIONS
=======

   Like any other compiler backend, this module needs to be invoked using
the O module to run correctly:

     perl -MO=Graph,-opt,-opt,-opt program.pl
     OR
     perl -MO=Graph,-opt,obj -e 'BEGIN {$obj = ["hi"]}; print $obj'
     OR EVEN
     perl -e 'use O qw(Graph -opt obj obj); print "hi!\n";'

   `Obj' is the name of a perl variable whose contents will be examined.
It can't be a my() variable, and it shouldn't have a prefix symbol
('$@^*'), though you can specify a package - the name will be used to look
up a GV, whose various fields will lead to the scalar, array, and other
values that correspond to the named variable. If no object is specified,
the whole main program, including the CV that points to its pad, will be
displayed.

   Each of the the opts can come from one of the following (each set is
mutually exclusive; case and underscores are insignificant):

-text, -vcg, -dot
-----------------

   Produce output of the appropriate type. The default is '-text', which
isn't useful for much of anything (it does draw some nice ASCII boxes,
though).

-addrs, -no_addrs
-----------------

   Each of the nodes on the graph produced corresponds to a C structure
that has an address and includes pointers to other structures. The module
uses these addresses to decide how to draw edges, but it makes the graph
more compact if they aren't printed. The default is '-no_addrs'.

-compile_order, -run_order
--------------------------

   The collection of OPs that perl compiles a script into has two different
layers of structure. It has a tree structure which corresponds roughly to
the synactic nesting of constructs in the source text, and a roughly
linked-list representation, essentially a postorder traversal of this
tree, which is used at runtime to decide what to do next.  The graph can
be drawn to emphasize one structure or the other. The former,
'compile_order', is the default, as it tends to lead to graphs with aspect
ratios close to those of standard paper.

-SVs, -no_SVs
-------------

   If OPs represent a program's compiled code, SVs represent its data. This
includes literal numbers and strings (IVs, NVs, PVs, PVIVs, and PVNVs),
regular arrays, hashes, and references (AVs, HVs, and RVs), but also the
structures that correspond to individual variables (special HVs for symbol
tables and GVs to represent values within them, and special AVs that hold
my() variables (as well as compiler temporaries)), structures that keep
track of code (CVs), and a variety of others. The default is to display
all these too, to give a complete picture, but if you aren't in a holistic
mood, you can make them disappear.

-ellipses, -rhombs
------------------

   The module tries to give the nodes representing SVs a different shape
from those of OPs. OPs are usually rectangular, so two obvious shapes for
SVs are ellipses and rhombuses (stretched diamonds). This option currently
only makes a difference for VCG (ellipse is the default).

-stashes, -no_stashes
---------------------

   The hashes that perl uses to represent symbol tables are called
'stashes'.  Since every GV has a pointer back to its stash, it's virtually
inevitable for the links in a graph to lead to the main stash.
Unfortunately stashes, especially the main one, can be quite big, and lead
to forests of other structures - there's one GV and another SV for each
magic variable, plus all of @INC and %ENV, and so on. To prevent
information overload, then, the display of stashes is disabled by default.

-fileGVs, -no_fileGVs
---------------------

   Another kind graph element that can be annoying are the pointers from
every GV and COP (a kind of OP that occurs for every statement) to the GV
that represents the file from which that code came (used for error
messages). By default, these links aren't shown, to keep them from
cluttering the graph. Also, perl's internal interfaces changed in a recent
version, so in perl 5.005_63 or later you can't see the fileGVs at all.

-SEQs, -no_SEQs
---------------

   As it is visited in the peephole optimization phase, each OP gets a
sequence number, which is currently used by anything (except the peephole
optimizer, to avoid visiting OPs twice). If you want to see these, ask for
them. (COPs have their own sequence numbers too, but they're more
interesting to look at - for instance, they're used to bound the lifetimes
of lexicals).

-types, -no_types
-----------------

   B::Graph always gives the type of each OP symbolically ('entersub'), but
it can also print the numeric value of the type field, if you want.  The
default is no_types.

-float, -no_float
-----------------

   Almost every OP has an op_next and an op_sibling pointer, and B::Graph
colors them distinctively (pink and light blue, respectively). Because of
this, it isn't strictly necessary to 'anchor' the arrow on a line in the
OP's box saying 'op_next'. The float option lets the graph layout engine
start these arrows wherever it wants, which can sometimes lead to a more
pleasing layout, at the expense of being less obvious. The default is not
to float.

-targlinks, -no_targlinks
-------------------------

   Lexical (my()) variables and temporary values used by individual OPs
are stored in 'pads', per-code arrays linked to the CV. OPs store indexes
into these arrays in the 'op_targ' field, but B::Graph can often also draw
links directly from the OP to the SV that stores the name of the variable.
These links don't correspond to any real pointers, however, and they can
make the graph more complicated, so they are disabled by default.

WHAT DOES THIS ALL MEAN?
========================

SvFLAGS abbreviations
---------------------

     Pb     SVs_PADBUSY   reserved for tmp or my already
     Pt     SVs_PADTMP    in use as tmp
     Pm     SVs_PADMY     in use a "my" variable
     T      SVs_TEMP      string is stealable?
     O      SVs_OBJECT    is "blessed"
     Mg     SVs_GMG       has magical get method
     Ms     SVs_SMG       has magical set method
     Mr     SVs_RMG       has random magical methods
     I      SVf_IOK       has valid public integer value
     N      SVf_NOK       has valid public numeric (float) value
     P      SVf_POK       has valid public pointer (string) value
     R      SVf_ROK       has a valid reference pointer
     F      SVf_FAKE      glob or lexical is just a copy
     L      SVf_OOK       has valid offset value (mnemonic: lvalue)
     B      SVf_BREAK     refcnt is artificially low
     Ro     SVf_READONLY  may not be modified
     i      SVp_IOK       has valid non-public integer value
     n      SVp_NOK       has valid non-public numeric value
     p      SVp_POK       has valid non-public pointer value
     S      SVp_SCREAM    has been studied?
     V      SVf_AMAGIC    has magical overloaded methods

op_flags abbreviations
----------------------

     V      OPf_WANT_VOID    Want nothing (void context)
     S      OPf_WANT_SCALAR  Want single value (scalar context)
     L      OPf_WANT_LIST    Want list of any length (list context)
     K      OPf_KIDS         There is a firstborn child.
     P      OPf_PARENS       This operator was parenthesized.
                              (Or block needs explicit scope entry.)
     R      OPf_REF          Certified reference.
                              (Return container, not containee).
     M      OPf_MOD          Will modify (lvalue).
     T      OPf_STACKED      Some arg is arriving on the stack.
     *      OPf_SPECIAL      Do something weird for this op (see op.h)

BUGS
====

   VCG has a problem with boxes that have more than about 55 arrows coming
out of them, so with large arrays and hashes B::Graph will stop outputting
edges and some boxes may be disconnected.

AUTHOR
======

   Stephen McCamant <smcc@CSUA.Berkeley.EDU>

SEE ALSO
========

   `dot(1)' in this node, `xvcg(1)' in this node, `perl(1)' in this node,
`perlguts(1)' in this node.

   If you like B::Graph, you might also be interested in Gisle Aas's
PerlGuts Illustrated, at `http://gisle.aas.no/perl/illguts/'.

Package used by B::JVM to emit Java Bytecode
********************************************

NAME
====

   B::JVM::Emit -  Package used by B::JVM to emit Java Bytecode

SYNOPSIS
========

     use B::JVM::Jasmin::Emit;

     my $emitter = new B::JVM::Emit(FILEHANDLE);

     # ...
     $emitter->DIRECTIVE_NAME([@ARGS]);
     #  ...
     $emitter->OPCODE_NAME([@ARGS]);
     #  ...
     $emitter->OPCODE_NAME([@ARGS]);

DESCRIPTION
===========

   This class is used Java bytcodes on a file handle.  Until someone
actually creates a module that truely emits Java bytecodes, the
interesting stuff is all happening in the subclass,
`B::JVM::Jasmin::Emit|B::JVM::Jasmin::Emit' in this node.  The method
names used here were built up from the `jasmin|jasmin' in this node syntax.
There was no reason for this other than the implementor was most familar
with that manner of thinking about Java bytecode.  However, the set should
cover every opcode available.

   The user of this module must send opcodes in the order desired and is
responsible for emitting a sensible JVM program.  All this module provides
is a consistent way to emit JVM opcodes from Perl, since there is no
universal assembler syntax.  Someone who wants to emit opcodes need only
subclass this module and implement all the methods.

AUTHOR
======

   Bradley M. Kuhn, bkuhn@ebb.org, http://www.ebb.org/bkuhn

COPYRIGHT
=========

   Copyright (C) 1999, Bradley M. Kuhn, All Rights Reserved.

LICENSE
=======

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the LICENSE file that was
shipped with this distribution.

SEE ALSO
========

   perl(1), B::JVM::Jasmin(3), B::JVM::Jasmin::Emit(3)

DETAILED DOCUMENTATION
======================

B::JVM::Emit Package Variables
------------------------------

$VERSION
     Version number of B::JVM::Emit.  For now, it should always match the
     version of B::JVM::Jasmin

Modules used by B::JVM::Emit
----------------------------

Carp
     Used for error reporting

Methods in B::JVM::Emit
-----------------------

B::JVM::Emit::new
     usage: B::JVM::Emit::new(FILEHANDLE)

     Creates a new object of the class.  It assumes that FILEHANDLE is a
     lexically scoped file handle open for writing.

B::JVM::Emit::_clearMethod
     usage: $emitter->_clearMethod()

     Clears  the current method name.

B::JVM::Emit::_setCurrentMethod
     usage: B::JVM::Emit::_setCurrentMethod(METHOD_NAME)

     Sets the current name of the method being emitted.

B::JVM::Emit::inMethod
     usage: $emitter->inMethod()

     Returns true (in particular, the current method name) if we are
     currently in method, and returns false otherwise.

B::JVM::Emit::_setClassName
     usage: B::JVM::Emit::_setClassName(CLASS_NAME)

     Sets the  name of the class being emitted.

Perl Backend module for generating JVM code via Jasmin Assembler
****************************************************************

NAME
====

   B::JVM::Jasmin - Perl Backend module for generating JVM code via Jasmin
Assembler

SYNOPSIS
========

     use B::JVM::Jasmin;

     compile(KEEP_INTERMEDIATE_FILES_FLAG, [MAIN_CLASS_NAME]);

     OR

     perl -MO=JVM::Jasmin,KEEP_INTERMEDIATE_FILES_FLAG, [MAIN_CLASS_NAME] file.plx

DESCRIPTION
===========

   The B::JVM::Jasmin module is a Perl backend module that generates Jasmin
assembler code (which can then be compiled into JVM code with jasmin(1))
for a Perl program.

AUTHOR
======

   Bradley M. Kuhn, bkuhn@ebb.org, http://www.ebb.org/bkuhn

COPYRIGHT
=========

   Copyright (C) 1999, Bradley M. Kuhn, All Rights Reserved.

LICENSE
=======

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the LICENSE file that was
shipped with this distribution.

SEE ALSO
========

   perl(1), jasmin(1).

DETAILED DOCUMENTATION
======================

B::JVM::Jasmin Package Variables
--------------------------------

$VERSION
     Version number of B::JVM::Jasmin

@ISA
     Canonical @ISA array, currently only derives from Exporter

@EXPORT
     Canonical @EXPORT array

@EXPORT_OK
     Canonical @EXPORT_OK array

$STATE
     Reference to a B::JVM::Jasmin::CompileState object for the current
     state of this compiler

Modules used by B::JVM::Jasmin
------------------------------

B
     Of course, we must use the B module to overide its functions and
     interface with O.

Methods in B::JVM::Jasmin
-------------------------

B::JVM::Jasmin::compile
     usage: B::JVM::Jasmin::compile(KEEP_INTERMEDIATE_FILES_FLAG,
     [MAIN_CLASS_NAME])

     This is the default method that O.pm will call when this backend is
     used.  The first argument is a flag that indicates whether or not to
     keep the intermediate temporary files that are generated by the
     compilation process.  The second argument

B::JVM::Jasmin::WalkOPTree
     usage: B::JVM::Jasmin::compile($op, $level)

     This method walks the op-tree and does pre and post processing on the
     op codes.  In some cases, the pre-processing will call WalkOPTree for
     any sub-ops that exist.

B::OP::JVMJasminPre
     This method handles pre-processing on plain OPs.  Note that for all
     these OPs, there are no recursive calls to WalkOPTree, since plain
     OPs should never have sub-OPs (I think :).

     The following OPs are currently supported:

    enter
          Currently, nothing is done on an "enter" OP.  This may change in
          the future, but I haven't seen a use for them (yet :).

    pushmark
          On an "pushmark" OP, the LIST_MARK is pushed onto the JVM
          operand stack.  This indicates to other OPs that expect a list
          that the list ends here.

    null
          A empty operation.  Just send a "nop".

B::OP::JVMJasminPost
     Currently, there is no post processing done on plain OPs.

B::LISTOP::JVMJasminPre
     Pre-processing on LISTOPs requires that any we recursively call
     `WalkOPTree', since LISTOPs can have children.

     The following LISTOPs are currently supported:

    leave
          A "leave" LISTOP will be the parent of a number of OPs.
          Therefore, we  process all the sub-OPs *in order* on the
          pre-processing step.

    print
          For a "print" LISTOP, we need to process the kids in reverse
          order, save pushing the `LIST_MARK', which must happen first
          (the "print" post-processing depends on the mark being there).
          As in many instances, Perl appears to its own stack like a queue
          at times, and this causes problems, since we are using the JVM
          operand stack.  In other words, for a "print" LISTOP, the Perl
          stack looks like this (left is top):

          LIST_MARK, "1", "2\n"

          However, this would print the string "12\n", not "2\n1".  It's
          as if Perl first finds the mark, and then processes from the
          mark to the end of the stack as a queue!  (This behavior is
          probably documented somewhere else, but I just discovered it
          serendipitously (perhaps I should read documentation more :)).
          So, to process a "print" statement, we grab the "pushmark" OP
          first, process that, and then call `WalkOPTree' recursively in
          reverse for the rest of the sub-OPs.

    list
          On a "list" LISTOP, there is no need to "pushmark" (I think :).
          When the "list" LISTOP completes (at least from analyzing perl
          -Dts output) the mark simply disappears.  It doesn't appear to
          be there for any other operation but the "list" LISTOP itself.
          If this isn't correct, this code will need to be corrected.

          In addition, the list is reversed on the JVM operand stack, just
          as is done with the "print" LISTOP.

          No post-processing is needed (I think :), because the "list"
          LISTOP just sets up arguments for another OP.

    scope
          A "scope" LISTOP will be the parent of a number of OPs.
          Therefore, we process all the sub-OPs *in order* on the
          pre-processing step.  May processing may be needed, but I
          haven't discovered that it is yet.

B::LISTOP::JVMJasminPost
     Post-processing on LISTOPs is often required, since the sub-OPs often
     set up arguments for processing.

     The following LISTOPs currently have post-processing done:

    print
          At this point, the pre-processing should have set up the
          arguments to "print" on the JVM operand stack.  A `LIST_MARK'
          should mark the end of the argument list on the JVM operand
          stack.  A temporary variable is used to store the return value
          of the print statement.  It is and'ed with each
          `Functions.print' call return.

          At the end, we build a `StackElement' containing a Scalar that
          represents the final integer return value of the print statement.

B::COP::JVMJasminPre
     The following COPs are currently supported:

    nextstate
          The "nextstate" COP clears the JVM operand stack.  It finds the
          `STATE_MARK', which indicates where and remaining data ends.

          The `STATE_MARK' is left on the stack.

B::COP::JVMJasminPost
B::SVOP::JVMJasminPre
     The following SVOPs are currently supported:

    const
          On a "const" SVOP, a Scalar and a `StackElement' to hold it must
          be built.  This is done by grabbing the `cstring()' of the PV
          associated with the SV we are given.  I don't know if every SV
          supports the PV() method, my thought is that it doesn't and this
          will need to be rewritten to handle other types of SVs.

          All this is done in pre-processing, no post-processing is
          necessary; the `StackElement' need only be left on the stack for
          whatever OP needs it.

B::SVOP::JVMJasminPost
     No post-processing is currently required for SVOPs.

B::BINOP::JVMJasminPre
     Pre-processing on BINOPs requires that any we recursively call
     `WalkOPTree', for the two sub-ops

     The following BINOPs are currently supported:

    sassign
          To pre-process an "sassign" BINOP, we need only process the two
          sub-OPs.  We do so in, so that in post-processing, we can assume
          that the left-hand-side of the assignment is first on the stack,
          and the right-hand-side is the second down element on the stack.

          The post-processing actually does the assignment.

    concat
          To pre-process a "concat" BINOP, we need only process the two
          sub-OPs.  We do so in order.  Post processing would be easier if
          it was done in reverse order (since the top of the JVM operand
          stack would be the result we need to keep), but it is imperative
          we go in order for cascading operations to have the proper
          semantics.

    seq and sne
          To pre-process a "seq" and "sne" BINOPs, we need to process the
          two sub-OPs.  We do so in order.  Post processing would be
          easier if it was done in reverse order (since the top of the JVM
          operand stack would be the result we need to keep), but it is
          imperative we go in order for cascading operations to have the
          proper semantics.

B::BINOP::JVMJasminPost
     Currently, post-processing occurs on the following BINOPs:

    sassign
          On post-processing, the "sassign" BINOP expects there to be two
          `StackElement's on the JVM operand stack.  The top is the
          left-hand-side of the "sassign", and below that (on the operand
          stack) is the right-hand-side of the "sassign".  Both Scalar
          quantities will be wrapped in `StackElements'.

          So, both `StackElement's are converted into Scalar.  To do this,
          the function TurnStackElementsToScalars is called, and told to
          leave the stack elements in an array.  The array that is
          returned is used set up the Scalars for assignment.

          Then, to to perform the actual assignment, `assignFromScalar' is
          used.

          Finally, note as well that the left-hand-side `StackElement' is
          saved, as this should be the "return value" of the "sassign".
          It is left on the JVM operand stack at the end.

    concat
          On post-processing, the "concat" BINOP expects there to be two
          `StackElement's on the JVM operand stack.  The top is the
          right-operand of the "concat", and below that (on the operand
          stack) is the left-operand of the "concat".  Both Scalar
          quantities will be wrapped in `StackElements'.

          So, both `StackElement's are converted into Scalar.  To do this,
          the function TurnStackElementsToScalars is called, and is told
          to leave the stack elements in an array.  The array that is
          returned is used set up the Scalars for concatenation.

          Then, to perform the actual concatenation, `Scalar.concat'
          function is used.

          Finally, note as well that the left-operand `StackElement' is
          saved, as this should be the "return value" of the "concat".  It
          is left on the JVM operand stack at the end.

    seq and sne
          On post-processing, the "seq" and "sne" BINOPs expect there to
          be two `StackElement's on the JVM operand stack.  The top is the
          right-operand of the "seq", and below that (on the operand
          stack) is the left-operand of the "seq".  Both Scalar quantities
          will be wrapped in `StackElements'.

          So, both `StackElement's are converted into Scalar.  To do this,
          the function TurnStackElementsToScalars is called, and is told
          to leave the stack elements in an array.  The array that is
          returned is used set up the Scalars for comparison.

          Then, to perform the actual comparison, `Scalar.seq' function is
          used.

          Then, we use that return value to create a new Scalar, wrapped
          in a `StackElement', which is left on the stack at the end.

B::UNOP::JVMJasminPre
     Pre-processing on UNOPs requires that any we recursively call
     `WalkOPTree', for the two sub-ops

     The following UNOPs are currently supported:

    null
          On "null" UNOPs, we simply process the sub-OP.  More interesting
          stuff happens in the post-processing.

B::UNOP::JVMJasminPost
     Post-processing on UNOPs is required because some flags needed to be
     checked.  The results of the UNOP's child may require manipulation
     based on these flags.

     The following UNOPs currently require post-processing:

    null
          On a "null" UNOP, we need to check to see if the OPf_MOD flag is
          on.  If it is not, then we need to make a copy of the Scalar
          result (wrapped in a `StackElement' on the stack.  We canno
          inadvertently modify the l-value of a variable, so we make the
          copy.

          If OPf_MOD is on, we need an l-value on the stack anyway, so
          things can be left alone.

B::GVOP::JVMJasminPre
     The following GVOPs are currently supported:

    gvsv
          To pre-process a "gvsv" GVOP, we must find the correct Scalar
          object.

          First, the `DEF_STASH' is put on the JVM operand stack.  Then,
          if this is not a variable in "main" namespace, we use that
          `DEF_STASH' to find the proper `Stash' (this part not yet
          working FIXME).  Once the required `Stash' is found, the proper
          GV is obtained, using methods from the `Stash' class).  The
          Scalar is retrieved from that GV.  The Scalar is then wrapped in
          a `StackElement' object.

B::GVOP::JVMJasminPost
     Post-processing is not currently required on any GVOPs.

B::LOGOP::JVMJasminPre
     Pre-processing on LOGOPs requires that any we recursively call
     `WalkOPTree', for the 3 sub-OPs.

     The following LOGOPs are currently supported:

    cond_expr
          For an "cond_expr" LOGOP, we should have exactly three sub-OPs.
          This is a basic "if-else" structure (I think :).  The first
          sub-OP will be the condition, the second sub-OP will be the
          block that should be executed if the condition is false, and the
          third is the block that should be executed if the condition is
          true.

          So, we process each OP, and surround it with the logic that is
          required to carry out the conditional.

B::LOGOP::JVMJasminPost
     Currently, post-processing occurs on the following LOGOPs:

    ""
ClearOperandStackToStateMark
     usage: `ClearOperandStackToStateMark($emitter, $curMethod,
     $leaveStateMark);'

     This subroutine emits the required code to clear the JVM operand
     stack until a `StackElement' which is a state mark is reached.  It
     emits the code using the given `$emitter' and to the method,
     `$curMethod'.

     If `$leaveStateMark' is defined and true, then the `STATE_MARK' is
     left on the stack, otherwise the `STATE_MARK' is removed.

TurnStackElementsToScalars
     usage: `TurnStackElementsToScalars($emitter, $curMethod, $count,
     $leaveArray);'

     This subroutine emits the required code to take $count `StackElement's
     off the stack and turn them back into Scalars.

     It is completely required, that this function be called only if the
     top $count elements on the JVM operand stack be `StackElement'
     objects who have valid elements.

     To do this, an array of Scalars is built.  A loop runs, getting the
     Scalar elements from the `StackElement's on the stack.

     If `$leaveArray' is defined and true, then the variable name of the
     array is simply returned.  The array variable returned as yet to be
     freed.

     If `$leaveArray' not defined or is false, then, another loop runs to
     push all the Scalars back onto the stack *in the same order*.  The
     array varable is not returned (an empty string is returned instead).
     The array variable will be freed in this case.

Internal package used by B::JVM::Jasmin to keep state of compilation
********************************************************************

NAME
====

   B::JVM::Jasmin::CompileState - Internal package used by B::JVM::Jasmin
to keep state of compilation

SYNOPSIS
========

     use B::JVM::Jasmin::CompileState;

     my $state = new B::JVM::Jasmin::CompileState([HASHREF]);

DESCRIPTION
===========

   This class is used to store the internal state of the compiler as it
runs.  Certain global information must be accounted for, and instead of
making a bunch of global variables, I thought it would be better to keep
track of this via a sub-package.

AUTHOR
======

   Bradley M. Kuhn, bkuhn@ebb.org, http://www.ebb.org/bkuhn

COPYRIGHT
=========

   Copyright (C) 1999, Bradley M. Kuhn, All Rights Reserved.

LICENSE
=======

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the LICENSE file that was
shipped with this distribution.

SEE ALSO
========

   perl(1), jasmin(1), B::JVM::Jasmin(3).

DETAILED DOCUMENTATION
======================

B::JVM::Jasmin::CompileState Package Variables
----------------------------------------------

$VERSION
     Version number of B::JVM::Jasmin::CompileState.  It should always
     match the version of B::JVM::Jasmin

@ISA
     Canonical @ISA array, derives from nothing

Modules used by B::JVM::Jasmin::CompileState
--------------------------------------------

Carp
     Used for error reporting

File::Spec::Functions
     Used to do some operations on files

IO::File
     used for creating lexically scoped file handles

B::JVM::Jasmin::Emit
     Needed for creating emitter objects for output

Methods in B::JVM::Jasmin::CompileState
---------------------------------------

B::JVM::Jasmin::CompileState::new
     usage: B::JVM::Jasmin::CompileState::new(HASHREF)

     Creates a new object of the class.  First, it checks for the validity
     of the keys of the given initialization package (valid keys are kept
     in  @validUserParameters), and if everything checks out, it sets up a
     few defaults if none were given and returns the blessed object.

     Accepted User Parameters:

    mainClassName
          The name to be used for the Java class that will correspond to
          the "main::" package.  Defaults to "Main" if none is given.

    currentPackage
          This is the current package being compiled.  Should be updated
          by the user using the setCurrentPackage method.  There is really
          no need to initialize it until compilation starts.
          Consequently, the value defaults to undef.

    outputDirectory
          A directory to use for creation of output files.  Defaults to
          the current working directory.

    keepIntermediateFiles
          If true, intermediate files that are generated during the
          compilation process are kept for user inspection.

B::JVM::Jasmin::CompileState::createNewFile
     usage: $obj->createNewFile($packageName, [$className])

     Creates a new file entry in the compiler state object and opens a new
     file handle for use when writing out jasmin files.  If the file has
     already been created, nothing is done.  This is typically called
     whenever a new package is discovered, so that a seperate class file
     can be generated for that package (class) in True Java Style (TM) :)

B::JVM::Jasmin::CompileState::emit
     usage: $obj->emit([PACAKGE_NAME])

     returns the emitter object associated with the given package,
     PACAKGE_NAME.  If PACKAGE_NAME is missing, then the emitter object of
     the currentPackage is returned

B::JVM::Jasmin::CompileState::setCurrentMethod
     usage: $obj->setCurrentMethod($methodName)

     Set the current method to be $methodName

B::JVM::Jasmin::CompileState::setCurrentPackage
     usage: $obj->setCurrentPackage($packageName)

     Set the current package to be $packageName

B::JVM::Jasmin::CompileState::clearCurrentMethod
     usage: $obj->clearCurrentMethod()

     Clear the current method name stored

B::JVM::Jasmin::CompileState::getCurrentMethod
     usage: $obj->getCurrentMethod()

     Return the current method

B::JVM::Jasmin::CompileState::DESTORY
     usage: $obj->DESTROY()

     Default destructor for the object

Package used by B::JVM::Jasmin to emit Jasmin syntaxed                         file
***********************************************************************************

NAME
====

   B::JVM::Jasmin::Emit -  Package used by B::JVM::Jasmin to emit Jasmin
syntaxed                         file

SYNOPSIS
========

     use B::JVM::Jasmin::Emit;

     my $emitter = new B::JVM::Emit(FILEHANDLE);

     # ...
     $emitter->DIRECTIVE_NAME([@ARGS]);
     #  ...
     $emitter->OPCODE_NAME([@ARGS]);
     #  ...
     $emitter->OPCODE_NAME([@ARGS]);

DESCRIPTION
===========

   This class is used emit JVM assembler code in Jasmin syntax.  Each
method one can use is either an opcode or a directive supported by Jasmin
syntax.

AUTHOR
======

   Bradley M. Kuhn, bkuhn@ebb.org, http://www.ebb.org/bkuhn

COPYRIGHT
=========

   Copyright (C) 1999, Bradley M. Kuhn, All Rights Reserved.

LICENSE
=======

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the LICENSE file that was
shipped with this distribution.

SEE ALSO
========

   perl(1), B::JVM::Jasmin(3), B::JVM::Emit(3).

DETAILED DOCUMENTATION
======================

B::JVM::Jasmin::Emit Package Variables
--------------------------------------

$VERSION
     Version number of B::JVM::Jasmin::Emit.  For now, it should always
     match the version of B::JVM::Jasmin

@EXPORT_OK
     All the methods that one can grab from B::JVM::Jasmin::Emit

@EXPORT
     We don't export anything by default.

Modules used by B::JVM::Jasmin::Emit
------------------------------------

Carp
     Used for error reporting

B::JVM::Utils
     Used to get needed utility functions, such as ExtractMethodData and
     IsValidMethodString

Methods in B::JVM::Jasmin::Emit
-------------------------------

B::JVM::Jasmin::Emit::new
     usage: B::JVM::Emit::new(FILEHANDLE, [SOURCE_FILE_NAME])

     Creates a new object of the class.  It assumes that FILEHANDLE is a
     lexically scoped file handle open for writing, and that
     SOURCE_FILE_NAME that should be used for a source directive.
     SOURCE_FILE_NAME is optional, but may annoys someone firing up your
     code in the Java debugger.

B::JVM::Emit::Jasmin::_clearMethodData()
     usage: $jasminEmitter->_clearMethodData()

     Clear out the method data elements of the Jasmin emitter

B::JVM::Emit::Jasmin::source
     usage: B::JVM::Emit::Jasmin::source(SOURCE_FILE_NAME)

     Emits the source file name directive.

B::JVM::Emit::Jasmin::comment
     usage: `B::JVM::Emit::Jasmin::comment($methodName, $commentString)'

     Puts `$commentString' in a comment in the file, in the code for method
     `$metohdName'.

B::JVM::Emit::Jasmin::super
     usage: B::JVM::Emit::Jasmin::super(CLASS_NAME)

     sends class directive, using  CLASS_NAME, to the output file

B::JVM::Emit::Jasmin::class
     usage: B::JVM::Emit::Jasmin::class(ACCESS_SPEC, CLASS_NAME)

     sends class directive, using CLASS_NAME to the ACCESS_SPEC, to the
     output file

B::JVM::Emit::Jasmin::interface
     usage: B::JVM::Emit::Jasmin::interface(ACCESS_SPEC, INTERFACE_NAME)

     sends interface directive, using INTERFACE_NAME to the ACCESS_SPEC,
     to the output file

B::JVM::Emit::Jasmin::implements
     usage: B::JVM::Emit::Jasmin::implements(CLASS_NAME)

     sends implements directive, using CLASS_NAME to the output file

B::JVM::Emit::Jasmin::labelCreate
     usage: `$emitter-'labelCreate($methodName, $labelNameRequested)>

     In method, $methodName, creates a new label, whose name will
     "resemble" $labelNameRequested.  This label is not actually sent to
     the output, that must be done later with
     `$emitter-'labelSend($methodName, $value)>.

     Note that the value returned from this method is the actual label name
     assigned and will only "resemble" (i.e., not match exactly) the
     `$labelNameRequested'.

B::JVM::Emit::Jasmin::labelSend
     usage: `$emitter-'labelSend($methodName, $labelName)>

     Send a label, `$labelName', to the output of method, `$methodName'.

     This label must be valid label previously returned from
     `$emitter-'labelCreate($methodName, $someValue)>.

B::JVM::Emit::Jasmin::field
     usage: B::JVM::Emit::Jasmin::field(ACCESS_SPEC, FIELD_NAME, TYPE,
     [VALUE])

     sends field directive, using the arguments given, to the output file

B::JVM::Emit::Jasmin::methodStart
     usage: $emitter->methodStart(METHOD_NAME, ACCESS_SPEC, [STACK_SIZE])

     sends method directive and other directives needed to start up a new
     method.  Also sets the current method for the emitter.  STACK_SIZE is
     optional.  However, a stack size is always set to a default value
     (currently 256), because if it is not set, a number of problems occur
     with the stack.

B::JVM::Emit::Jasmin::methodCreateLocal
     usage: $emitter->methodCreateLocal(METHOD_NAME, VARIABLE_NAME_REQUEST,
                                       VARIABLE_TYPE, [LABEL1], [LABEL2])

     Creates a local of type VARIABLE_TYPE, with a given name in method,
     METHOD_NAME.  If LABEL1 is given, LABEL2 must be given, and vice
     versa.

     If the labels are given, then the variable is only valid between
     those two labels in the resulting assembler source.

     methodCreateLocal attempts to give a variable name that "resembles"
     VARIABLE_NAME_REQUEST.  If the labels are given, it is guaranteed
     that the variable name will "resemble" the VARIABLE_NAME_REQUEST.

     If the labels are not given, it is very likely that an old local
     variable of the same type will be returned.

     The actual variable name given will be returned.  It is imperative
     that the user of methodCreateLocal use this variable name, and not
     VARIABLE_NAME_REQUEST, for obvious reasons.

B::JVM::Emit::Jasmin::methodFreeLocal
     usage: $emitter->methodFreeLocal(METHOD_NAME VARIABLE_NAME)

     Indicates that the local, VARIABLE_NAME, in method, METHOD_NAME, is no
     longer in use.  It is not required that locals be freed in this
     manner, however, many, many locals can be allocated unnecessarily if
     this is not done.

B::JVM::Emit::Jasmin::methodEnd
     usage: `$emitter-'methodEnd($method, [$debug])>

     Finishes up a method, `$method', that is currently being emitted.  If
     $debug is defined and is true, then ".line" directives will be put
     into the output for debugging purposes.

B::JVM::Emit::Jasmin::astore
     usage: $emitter->astore([METHOD, VARIABLE])

     Emits an "astore" instruction, using the VARIABLE name in METHOD
     given, if one is given.  If VARIABLE is given, it is looked up in
     variables created with B::JVM::Emit::Jasmin::methodCreateLocal() for
     the given method, METHOD.

B::JVM::Emit::Jasmin::invokevirtual
     usage: $emitter->invokevirtual(METHOD_IN, METHOD_INVOKED)

     Emits an "invokevirtual" instruction to invoke METHOD_INVOKED in the
     code for METHOD_IN

B::JVM::Emit::Jasmin::ifne
     usage: `$emitter-'ifne($methodName, $labelName)>

     Emits an "ifne" instruction with argument, `$labelName' in the code
     for method, `$methodName'.

     This label, `$labelName' must be valid label previously returned from
     `$emitter-'labelCreate($methodName, $someValue)>.

B::JVM::Emit::Jasmin::ifeq
     usage: `$emitter-'ifeq($methodName, $labelName)>

     Emits an "ifeq" instruction with argument, `$labelName' in the code
     for method, `$methodName'.

     This label, `$labelName' must be valid label previously returned from
     `$emitter-'labelCreate($methodName, $someValue)>.

B::JVM::Emit::Jasmin::aload
     usage: $emitter->aload([METHOD, VARIABLE])

     Emits an "aload" instruction, using the VARIABLE name in METHOD
     given, if one is given.  If VARIABLE is given, it is looked up in
     variables created with B::JVM::Emit::Jasmin::methodCreateLocal() for
     the given method, METHOD.

B::JVM::Emit::Jasmin::invokestatic
     usage: $emitter->invokevirtual(METHOD_IN, METHOD_INVOKED)

     Emits an "invokestatic" instruction to invoke METHOD_INVOKED in the
     code for METHOD_IN

B::JVM::Emit::Jasmin::iconst
     usage: $emitter->iconst(METHOD, VALUE)

     Emits an "iconst" instruction, using the value of VALUE for the
     constant, in the method named METHOD.

B::JVM::Emit::Jasmin::istore
     usage: $emitter->istore([METHOD, VARIABLE])

     Emits an "istore" instruction, using the VARIABLE name in METHOD
     given, if one is given.  If VARIABLE is given, it is looked up in
     variables created with B::JVM::Emit::Jasmin::methodCreateLocal() for
     the given method, METHOD.

B::JVM::Emit::Jasmin::iload
     usage: $emitter->iload([METHOD, VARIABLE])

     Emits an "iload" instruction, using the VARIABLE name in METHOD
     given, if one is given.  If VARIABLE is given, it is looked up in
     variables created with B::JVM::Emit::Jasmin::methodCreateLocal() for
     the given method, METHOD.

B::JVM::Emit::Jasmin::iand
     usage: $emitter->iand([METHOD])

     Emits an "iand" instruction, in METHOD given, if one is given.

B::JVM::Emit::Jasmin::pop
     usage: $emitter->pop([METHOD])

     Emits an "pop" instruction, in METHOD given, if one is given.

B::JVM::Emit::Jasmin::getstatic
     usage: $emitter->getstatic(METHOD_IN, FIELD, TYPE)

     Emits an "getstatic" instruction for the field, FIELD, of type, TYPE
     in the code for METHOD_IN

B::JVM::Emit::Jasmin::ldc
     usage: $emitter->ldc(METHOD_IN, VALUE)

     Emits an "ldc" instruction with the value of VALUE, in the method
     METHOD_IN.

B::JVM::Emit::Jasmin::newObject
     usage: $emitter->newObject(METHOD_IN, CLASS)

     Emits an "new" instruction for the class, CLASS in the body for the
     method, METHOD_IN.  CLASS must be a valid class name.

B::JVM::Emit::Jasmin::invokespecial
     usage: $emitter->invokespecial(METHOD_IN, METHOD_INVOKED)

     Emits an "invokespecial" instruction to invoke METHOD_INVOKED in the
     code for METHOD_IN

B::JVM::Emit::Jasmin::dup
     usage: `$emitter-'dup($method)>

     Emits an "dup" instruction in the code for the method, `$method'

B::JVM::Emit::Jasmin::swap
     usage: `$emitter-'swap($method)>

     Emits an "swap" instruction in the code for the method, `$method'

B::JVM::Emit::Jasmin::gotoLabel
     usage: `$emitter-'gotoLabel($methodName, $labelName)>

     Emits an "goto" instruction with argument, `$labelName' in the code
     for method, `$methodName'.

     This label, `$labelName' must be valid label previously returned from
     `$emitter-'labelCreate($methodName, $someValue)>.

B::JVM::Emit::Jasmin::returnVoid
     usage: $emitter->returnVoid(METHOD_IN)

     Emits an "return" instruction in the code for method, METHOD_IN.

B::JVM::Emit::Jasmin::iinc
     usage: `$emitter-'iinc($method, $variable, $amount)>

     Emits an "iinc" instruction, using the `$variable' name in the method,
     `$method'.  The variable, `$variable' must have one previously
     returned from `methodCreateLocal($method, ...)' that has not been
     freed with `methodFreeLocal($method, ...)' yet.

     `$amount' is the integer amount to increment `$variable' by.

B::JVM::Emit::Jasmin::bipush
     usage: `$emitter-'bipush($method, $value)>

     Emits an "bipush" instruction, into the method, `$method' using the
     value of $value.  Note that an "iconst" or an "iconst_m1" instruction
     is emitted if the $value is the range where "iconst" will work.

B::JVM::Emit::Jasmin::aastore
     usage: `$emitter-'aastore($method)>

     Emits an "aastore" instruction, into the method, `$method'.

B::JVM::Emit::Jasmin::isub
     usage: `$emitter-'isub($method)>

     Emits an "isub" instruction, into the method, `$method'.

B::JVM::Emit::Jasmin::nop
     usage: `$emitter-'nop($method)>

     Emits a "nop" instruction, into the method, `$method'.

B::JVM::Emit::Jasmin::aaload
     usage: `$emitter-'aaload($method)>

     Emits an "aaload" instruction, into the method, `$method'.

B::JVM::Emit::Jasmin::anewarray
     usage: `$emitter-'anewarray($method, $type)>

     Emits an "anewarray" instruction, into the method, `$method'.  The
     new array will be of type $type.  The method will fail if $type is
     not a valid JVM type identifier.

Utility functions for B::JVM
****************************

NAME
====

   B::JVM::Utils -  Utility functions for B::JVM

SYNOPSIS
========

     use B::JVM::Utils qw(method1 method2);

DESCRIPTION
===========

   This package is a set of utilties that are useful when compiling Perl
to the JVM architecture.  They are a hodgepodge of utilties that don't
really fit anywhere else.

AUTHOR
======

   Bradley M. Kuhn, bkuhn@ebb.org, http://www.ebb.org/bkuhn

COPYRIGHT
=========

   Copyright (C) 1999, Bradley M. Kuhn, All Rights Reserved.

LICENSE
=======

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the LICENSE file that was
shipped with this distribution.

SEE ALSO
========

   perl(1), B::JVM::Jasmin(3), B::JVM::Emit(3).

DETAILED DOCUMENTATION
======================

B::JVM::Jasmin::Utils Package Variables
---------------------------------------

$VERSION
     Version number of B::JVM::Utils.  For now, it should always match the
     version of B::JVM::Jasmin

@EXPORT_OK
     All the methods that one can grab from B::JVM::Utils.

@EXPORT
     We don't export anything by default.

Modules used by B::JVM::Utils
-----------------------------

Carp
     Used for error reporting

Methods in B::JVM::Utils
------------------------

B::JVM::ExtractMethodData
     usage: B::JVM::ExtractMethodData(METHOD_STRING)

     Takes a string that is believed to a valid method string for a JVM
     method, and if it is a valid method string, returns a hash reference
     that looks like:   { methodName => NAME_OF_THE_METHOD,     returnType
     => TYPE_ID_OF_RETURN_TYPE,     argumentTypes => [
     ARGUMENT_1_RETURN_TYPE_ID,
     ARGUMENT_1_RETURN_TYPE_ID,                        ... ] } An
     undefined value is returned if the method string is not valid.

B::JVM::Utils::IsValidMethodString
     usage: B::JVM::Utils::IsValidMethodString(METHOD_STRING)

     Takes a string that is believed to a valid method name for a JVM
     method, and returns a true iff. the METHOD_STRING is a valid JVM
     method name

B::JVM::Utils
     usage: B::JVM::Utils:IsValidTypeIdentifier(TYPE_ID)

     Takes a string that is believed to a valid type identifitier name on
     the JVM, and returns a true iff. the TYPE_ID is a valid JVM type
     identifier

Show information about subroutine lexical variables
***************************************************

NAME
====

   B::LexInfo - Show information about subroutine lexical variables

SYNOPSIS
========

     use B::ShowLex ();
     my $lexi = B::ShowLex->new;

DESCRIPTION
===========

   Perl stores lexical variable names and values inside a *padlist* within
the subroutine.  Certain lexicals will maintain certain attributes after
the the variable "goes out of scope".  For example, when a scalar is
assigned a string value, this value remains after the variable has gone
out of scope, but is overridden the next time it is assigned to.  Lexical
Arrays and Hashes will retain their storage space for the maximum number
of entries stored at any given point in time.

   This module provides methods to record this information, which can be
dumped out as-is or to compare two "snapshots".  The information learned
from these snapshots can be valuable in a number of ways.

METHODS
=======

new
     Create a new *B::LexInfo* object:

          my $lexi = B::LexInfo->new;

cvlexinfo
     Create a padlist snapshot from a single subroutine:

          my $info = $lexi->cvlexinfo('Foo::bar');

stash_cvlexinfo
     Create a list of padlist snapshots for each subroutine in the given
     package:

          my $info = $lexi->stash_cvlexinfo('Foo');

dumper
     Return a reference to a stringified padlist snapshot:

          print ${ $lexi->dumper($info) }

diff
     Compare two padlist snapshots and return the difference:

          my $before = $lexi->stash_cvlexinfo(__PACKAGE__);
          ... let some code run
          my $after = $lexi->stash_cvlexinfo(__PACKAGE__);

          my $diff = B::LexInfo->diff($before, $after);
          print $$diff;

     NOTE: This function relies on the *diff -u* command.  You might need
     to configure *$B::LexInfo::TmpDir* and/or *$B::LexInfo::DiffCmd* to
     values other than the defaults in *LexInfo.pm*.

cvrundiff
     Take a padlist snapshot of a subroutine, run the subroutine with the
     given arguments, take another snapshot and return a diff of the
     snapshots.

          my $diff = $lexi->cvrundiff('Foo::bar', "arg1", $arg2);
          print $$diff;

     Complete example:

          package Foo;
          use B::LexInfo ();

          sub bar {
              my($string) = @_;
          }

          my $lexi = B::LexInfo->new;
          my $diff = $lexi->cvrundiff('Foo::bar', "a string");
          print $$diff;

     Produces:

          --- /tmp/B_LexInfo_1848.before  Mon Jun 28 19:48:41 1999
          +++ /tmp/B_LexInfo_1848.after   Mon Jun 28 19:48:41 1999
          @@ -2,8 +2,10 @@
             {
               'Foo::bar' => {
                 '$string' => {
          -        'TYPE' => 'NULL',
          -        'NULL' => '0x80efd58'
          +        'TYPE' => 'PV',
          +        'LEN' => 9,
          +        'PV' => 'a string',
          +        'CUR' => 8
                 },
                 '__SPECIAL__1' => {
                   'TYPE' => 'NULL',

SNAPSHOT INFO
=============

   Snapshots are built using Perl structures and stringified using
Data::Dumper.  Hash key order is sorted and preserved if you you the
Tie::IxHash module installed.  Entry names are that of the variable itself
or *__SPECIAL__$n* for entries that are used by Perl internally.  The
key/value pairs for each entry depends on the variable type and state.
Docs on that to come, in the meantime, study:
http://gisle.aas.no/perl/illguts/

SEE ALSO
========

   B(3), Apache::RegistryLexInfo(3), Devel::Peek(3)

AUTHOR
======

   Doug MacEachern

Perl lint
*********

NAME
====

   B::Lint - Perl lint

SYNOPSIS
========

   perl -MO=Lint[,OPTIONS] foo.pl

DESCRIPTION
===========

   The B::Lint module is equivalent to an extended version of the -w
option of *perl*. It is named after the program *lint* which carries out a
similar process for C programs.

OPTIONS AND LINT CHECKS
=======================

   Option words are separated by commas (not whitespace) and follow the
usual conventions of compiler backend options. Following any options
(indicated by a leading -) come lint check arguments. Each such argument
(apart from the special all and none options) is a word representing one
possible lint check (turning on that check) or is *no-foo* (turning off
that check). Before processing the check arguments, a standard list of
checks is turned on. Later options override earlier ones. Available
options are:

context
     Produces a warning whenever an array is used in an implicit scalar
     context. For example, both of the lines

          $foo = length(@bar);
          $foo = @bar;
          will elicit a warning. Using an explicit B<scalar()> silences the
          warning. For example,

          $foo = scalar(@bar);

*implicit-read* and *implicit-write*
     These options produce a warning whenever an operation implicitly
     reads or (respectively) writes to one of Perl's special variables.
     For example, *implicit-read* will warn about these:

          /foo/;

     and *implicit-write* will warn about these:

          s/foo/bar/;

     Both *implicit-read* and *implicit-write* warn about this:

          for (@a) { ... }

*dollar-underscore*
     This option warns whenever $_ is used either explicitly anywhere or
     as the implicit argument of a print statement.

*private-names*
     This option warns on each use of any variable, subroutine or method
     name that lives in a non-current package but begins with an
     underscore ("_"). Warnings aren't issued for the special case of the
     single character name "_" by itself (e.g. $_ and @_).

*undefined-subs*
     This option warns whenever an undefined subroutine is invoked.  This
     option will only catch explicitly invoked subroutines such as `foo()'
     and not indirect invocations such as `&$subref()' or `$obj->meth()'.
     Note that some programs or modules delay definition of subs until
     runtime by means of the AUTOLOAD mechanism.

*regexp-variables*
     This option warns whenever one of the regexp variables $', $& or $'
     is used. Any occurrence of any of these variables in your program can
     slow your whole program down. See Perlre (perl.info), for
     details.

all
     Turn all warnings on.

none
     Turn all warnings off.

NON LINT-CHECK OPTIONS
======================

*-u Package*
     Normally, Lint only checks the main code of the program together with
     all subs defined in package main. The -u option lets you include
     other package names whose subs are then checked by Lint.

BUGS
====

   This is only a very preliminary version.

AUTHOR
======

   Malcolm Beattie, mbeattie@sable.ox.ac.uk.

Show lexical variables used in functions or files
*************************************************

NAME
====

   B::Showlex - Show lexical variables used in functions or files

SYNOPSIS
========

     perl -MO=Showlex[,SUBROUTINE] foo.pl

DESCRIPTION
===========

   When a subroutine name is provided in OPTIONS, prints the lexical
variables used in that subroutine.  Otherwise, prints the file-scope
lexicals in the file.

AUTHOR
======

   Malcolm Beattie, `mbeattie@sable.ox.ac.uk'

Measure size of Perl OPs and SVs
********************************

NAME
====

   B::Size - Measure size of Perl OPs and SVs

SYNOPSIS
========

     use B::Size ();

DESCRIPTION
===========

   See B::TerseSize

SEE ALSO
========

   B::TerseSize(3), Apache::Status(3)

AUTHOR
======

   Doug MacEachern

Helper module for CC backend
****************************

NAME
====

   B::Stackobj - Helper module for CC backend

SYNOPSIS
========

     use B::Stackobj;

DESCRIPTION
===========

   See `ext/B/README'.

AUTHOR
======

   Malcolm Beattie, `mbeattie@sable.ox.ac.uk'

Walk Perl syntax tree, printing terse info about ops
****************************************************

NAME
====

   B::Terse - Walk Perl syntax tree, printing terse info about ops

SYNOPSIS
========

     perl -MO=Terse[,OPTIONS] foo.pl

DESCRIPTION
===========

   See `ext/B/README'.

AUTHOR
======

   Malcolm Beattie, `mbeattie@sable.ox.ac.uk'

Printing info about ops and their (estimated) size
**************************************************

NAME
====

   B::TerseSize - Printing info about ops and their (estimated) size

SYNOPSIS
========

     perl -MO=TerseSize[,OPTIONS] foo.pl

DESCRIPTION
===========

   The *B::Size* and *B::TerseSize* modules attempt to measure the size of
Perl op codes.  The output of *B::TerseSize* is similar to that of
B::Terse, but includes the size of each OP in the tree and the PADLIST
(subroutine lexical variables).  The module can be run just as other
compiler backends or used via *Apache::Status* (version 2.02 and higher).

   If the *Apache::Status* StatusTerseSize option is enabled, there will
be a main menu item added, "Memory Usage".  Clicking on this link will
cause *B::TerseSize* to produce a summary of package memory usage.  This
summary can take quite a while to produce, as each package subroutine
syntax tree will be walked, adding up the information.  This information
will be cached, so running httpd in -X (non-forking mode) is a good choice.

   When browsing the Apache::Status "Symbol Table Dump", a "Memory Usage"
link will be at the bottom of each page.  These summaries also include
measurements of package global variables.

   The Apache::Status symbol table browser will also provide an option to
dump a subroutine tree along with the other subroutine options.

CAVEATS
=======

   The memory measurements are only an estimate.  But, chances are, if a
measurement is not accurate, it is smaller than the actual size.

   The "execution order" option under Apache::Status can only be run once
unless you are using Perl 5.6.0+ or apply the *patches/b_clearsym_60.pat*
to older Perls.

SEE ALSO
========

   B(3), B::Size(3), B::LexInfo(3), Apache::Status(3)

AUTHOR
======

   Doug MacEachern based in part on B::Terse by Malcolm Beattie

Simplified version of B::Graph for demonstration
************************************************

NAME
====

   B::Tree - Simplified version of B::Graph for demonstration

SYNOPSIS
========

     perl -MO=Tree program | dot -Tps > tree.ps

DESCRIPTION
===========

   This is a very cut-down version of `B::Graph'; it generates minimalist
tree graphs of the op tree of a Perl program, merely connecting the op
nodes and labelling each node with the type of op.

   It was written as an example of how to write compiler modules for
"Professional Perl", but I've found it extremely useful for creating
simple op tree graphs for use in presentations on Perl internals.

   It requires the CPAN `GraphViz' module and the GraphViz package from
`http://www.research.att.com/sw/tools/graphviz/'. It takes no options.

AUTHOR
======

   Simon Cozens, `simon@cpan.org'

SEE ALSO
========

   See GraphViz, B/Graph,

Generates cross reference reports for Perl programs
***************************************************

NAME
====

   B::Xref - Generates cross reference reports for Perl programs

SYNOPSIS
========

   perl -MO=Xref[,OPTIONS] foo.pl

DESCRIPTION
===========

   The B::Xref module is used to generate a cross reference listing of all
definitions and uses of variables, subroutines and formats in a Perl
program.  It is implemented as a backend for the Perl compiler.

   The report generated is in the following format:

     File filename1
       Subroutine subname1
     	Package package1
     	  object1        C<line numbers>
     	  object2        C<line numbers>
     	  ...
     	Package package2
     	...

   Each File section reports on a single file. Each Subroutine section
reports on a single subroutine apart from the special cases
"(definitions)" and "(main)". These report, respectively, on subroutine
definitions found by the initial symbol table walk and on the main part of
the program or module external to all subroutines.

   The report is then grouped by the Package of each variable, subroutine
or format with the special case "(lexicals)" meaning lexical variables.
Each object name (implicitly qualified by its containing Package) includes
its type character(s) at the beginning where possible. Lexical variables
are easier to track and even included dereferencing information where
possible.

   The `line numbers' are a comma separated list of line numbers (some
preceded by code letters) where that object is used in some way.  Simple
uses aren't preceded by a code letter. Introductions (such as where a
lexical is first defined with my) are indicated with the letter "i".
Subroutine and method calls are indicated by the character "&".
Subroutine definitions are indicated by "s" and format definitions by "f".

OPTIONS
=======

   Option words are separated by commas (not whitespace) and follow the
usual conventions of compiler backend options.

`-oFILENAME'
     Directs output to FILENAME instead of standard output.

-r
     Raw output. Instead of producing a human-readable report, outputs a
     line in machine-readable form for each definition/use of a
     variable/sub/format.

`-D[tO]'
     (Internal) debug options, probably only useful if -r included.  The t
     option prints the object on the top of the stack as it's being
     tracked. The O option prints each operator as it's being processed in
     the execution order of the program.

BUGS
====

   Non-lexical variables are quite difficult to track through a program.
Sometimes the type of a non-lexical variable's use is impossible to
determine. Introductions of non-lexical non-scalars don't seem to be
reported properly.

AUTHOR
======

   Malcolm Beattie, mbeattie@sable.ox.ac.uk.

Parser class for BIND configuration files
*****************************************

NAME
====

   BIND::Conf_Parser - Parser class for BIND configuration files

SYNOPSIS
========

     # Should really be a subclass
     use BIND::Conf_Parser;
     $p = BIND::Conf_Parser->new;
     $p->parse_file("/etc/named.conf");
     $p->parse_fh(STDIN);
     $p->parse("server 10.0.0.1 { bogus yes; };");

     # For one-shot parsing
     BIND::Conf_Parser->parse_file("/etc/named.conf")
     BIND::Conf_Parser->parse_fh(STDIN);
     BIND::Conf_Parser->parse("server 10.0.0.1 { bogus yes; };");

DESCRIPTION
===========

   `BIND::Conf_Parser' implements a virtual base class for parsing BIND
(Berkeley Internet Name Domain) server version 8 configuration files
("named.conf").  The parsing methods shown in the synopsis perform
syntactic analysis only.  As each meaningful semantic 'chunk' is parsed, a
callback method is invoked with the parsed information.  The following
methods are the public entry points for the base class:

$p = BIND::Conf_Parser->new
     The object constructor takes no arguments.

$p->parse_file( $filename )
     The given filename is parsed in its entirety.

$p->parse_fh( $fh [, $filename] )
     The given filehandle is parsed in its entirety.  An optional filename
     may be given for inclusion in any error messages that are generated
     during the parsing.  If it is not included a default of "a file
     handle" will be used.

$p->parse( $statements [, $filename] );
     The given scalar is parsed in its entirety.  Partial statements will
     be treated as a syntax error.  An optional filename may be given for
     inclusion in any error messages that are generated during the parsing.
     If it is not included a default of "a scalar" will be used.

   For conveniance, the last three methods may also be called as class
methods (that is, with the class name instead of a constructed object
reference), in which case they will call new() method and use the
resulting object.  All three return the object used, whether passed in or
constructed at call-time.

   In order to make the parser useful, you must make a subclass where you
override one or more of the following methods as appropriate:

$self->handle_logging_category( $name, \@names )
$self->handle_logging_channel( $name, \%options )
$self->handle_key( $name, $algo, $secret )
$self->handle_acl( $name, $addrmatchlist )
$self->handle_option( $option, $argument )
$self->handle_server( $name, \%options )
$self->handle_trusted_key( $domain, \@key_definition)
$self->handle_empty_zone( $name, $class, \%options )
$self->handle_zone( $name, $class, $type, \%options )
$self->handle_control( $socket_type, \@type_specific_data )
   The exact format of the data passed to the above routines is not
currently documented outside of the source to the class, but should be
found to be fairly natural.

USAGE
=====

   A typical usage would run something like:

     # Define a subclass
     package Parser;

     use BIND::Conf_Parser;
     use vars qw(@ISA);
     @ISA = qw(BIND::Conf_Parser);

     # implement handle_* methods for config file statements that
     # we're interested in
     sub handle_option {
         my($self, $option, $argument) = @_;
         return unless $option eq "directory";
         $named_dir = $argument;
     }

     sub handle_zone {
         my($self, $name, $class, $type, $options) = @_;
         return unless $type eq "master" && $class eq "in";
         $files{$name} = $options->{file};
     }

     # later, back at the ranch...
     package main;
     Parser->parse_file("/etc/named.conf");

   WARNING: if the subclass is defined at the end of the main program
source file, the assignment to *@ISA* may need to be wrapped in a BEGIN
block, ala

     BEGIN {
         @ISA = qw(BIND::Conf_Parser);
     }

BUGS
====

   `BIND::Conf_Parser' does not perform all the syntactic checks performed
by the parser in `named' itself.  For example, port numbers are not
verified to be positive intergers in the range 0 to 65535.

   The parse() method cannot be called multiple times with parts of
statements.

   Comments are not passed to a callback method.

   Some callbacks are invoked before the semicolon that terminates the
corresponding syntactic form is actually recognized.  It is therefore
possible for a syntax error to not be detected until after a callback is
invoked for the presumably completly parsed form.  No attempt is made to
delay the invocation of callbacks to the completion of toplevel statements.

NOTE
====

   This version of `BIND::Conf_Parser' corresponds to BIND version 8.2.2
and understands the statements, options, and forms of that version.  Since
the BIND developers have only made upward compatible changes to the
syntax, `BIND::Conf_Parser' will correctly parse valid config files for
previous versions of BIND.

   A `BIND::Conf_Parser' object is a blessed anonymous hash.  In an
attempt to prevent modules trampling on each other I propose that any
subclass that requires persistant state between calls to the callback
routines (handle_foo()) and other subclass methods should prefix its keys
names with its own name separated by _'s. For example, a hypothetical
`BIND::Conf_Parser::Keys' module would keep data under keys that started
with 'bind_conf_parser_keys_', e.g., 'bind_conf_parser_keys_key_count'.
The 'state' key is reserved for use by application specific one-shot
parsers (this is expected to encompass most uses of `BIND::Conf_Parser').
`BIND::Conf_Parser' reserves for itself all keys beginning with an
underbar.

COPYRIGHT
=========

   Copyright 1998-1999 Philip Guenther. All rights reserved.

   This library is free software; you can redistribute it and/or This
program is free software; redistribution and modification in any form is
explicitly permitted provided that all versions retain this copyright
notice and the following disclaimer.

   This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.

Module to aid in the creation of ipfw-based firewalls
*****************************************************

NAME
====

   BSD::Ipfwgen - Module to aid in the creation of ipfw-based firewalls

SYNOPSIS
========

     use BSD::Ipfwgen;

     outside qw(**interface list**);
     leaf qw(**interface list**);

     consolidate qw(**network list**);
     us qw(**network list**);
     not_us qw(**network list**);
     to_us qw(**network list**);
     from_us qw(**network list**);
     symmetric qw(**network list**);

     count_by_interface();
     count_by_address qw(**network list**);
     count_by_udp qw(**port list**);
     count_by_tcp qw(**port list**);

     no_looping()
     no_spoofing_us()
     no_spoofing_by_us()
     no_leaf_spoofing()

     tcp_from_rules($port, $rules);
     tcp_to_rules($port, $rules);
     udp_from_rules($port, $rules);
     udp_to_rules($port, $rules);

     from_net_rules($network, $rules);
     to_net_rules($network, $rules);

     to_me_rules($rules)
     not_to_me_rules($rules)
     from_me_rules($rules)
     not_from_me_rules($rules)

     in_interface_rules($interface, $rules);
     out_interface_rules($interface, $rules);

     drop_unwanted qw(**network list**);

     generate qw(**options**)

     **port list** is a list of integers.  80, 23, etc.
     **network list** is a list of network address.  207.33.90.32/27 etc.
     **interface list** is a list of interface names.  de0, fxp1 etc
     **options** is a list of the valid options: DEFAULT-ACCEPT, INSECURE
     $rules is a newline separated set of L<ipfw> rules.

DESCRIPTION
===========

   Ipfwgen is designed to make writing complex firewalls easier and safer.
It handles generating some of the harder rulesets: anti-spoofing,
anti-looping, and anti land-attack.

   Ipfwgen does not try to reduce the complexity of firewall building.
What it does do is allow you to write a perl program which generates a
firewal.  It's expected that the firewalls generated by Ipfwgen will be
examined by a human and installed manually.

   Ipfwgen commands must be given in a particular sequence.  First are the
declaritive commands: *outside*, *leaf*, *consolidate*, *us*, *not_us*,
and symmetric.

   Then the rule-specification commands: almost everything else.  Ipfwgen
keeps an internal database of the rules that are in progress.  After all
the rule-specification commands are done, then the firewall gets compiled.

   The generate command compiles the specifications into actuall `ipfw' in
this node commands and dumps them on STDOUT.

DECLARATIVE COMMANDS
====================

   The declaritive commands must preceed all others.

*outside*(INTERFACEs)
     Specifies that an interface is connected to the Internet at large and
     that the packets coming in from that interface should not be from
     "us".

*leaf*(INTERFACEs)
     Specifies that an interface leads to a network with no other
     connections.  Routing to a leaf can be assumed to be symmetric.

*consolidate*(NETWORKSs)
     Specifies that addresses within the network specified should be
     ignored and that the network address should be used instead when a
     list of IP addresses for the firewall system is needed.  This is
     primarily used to avoid needing to list a large number of IP
     addresses on web servers with many virtual hosts.

*us*(NETWORKs)
     Specifies network ranges that comprise the address space that is
     routed by "us".  The *us* command implies that we are the only source
     of routes for the addresses specifed.

*not_us*(NETWORKs)
     Specifies networks that are within "us" but should not be.  For
     example, "us" may claim to include 209.66.121.0/24, but in reality,
     the first few addresses aren't ours.  This situation can be handled
     using "not_us".

*to_us*(NETWORKs)
     Specifies networks that we may legitimately receive traffic on behalf
     of.  Don't filter it when incomming at the edges.

*from_us*(NETWORKs)
     Specifies networks that we may legitimately send traffic on behalf
     of.  Don't filter it when outgoing at the edges.

symmetric(NETWORKs)
     Specifies that the routes to a network are expected to be symmetric.

COUNTING SPECIFICATIONS
=======================

   These are all optional.

*count_by_interface*()
     Requests that traffic be counted by interface.  Both incoming and
     outgoing will be counted.

*count_by_address*(NETWORKs)
     Requests that traffic be tracked on a per NETWORK bases.

*count_by_udp*(PORTs)
     Requests that traffic be tracked on a per PORT basis for udp.

*count_by_tcp*(PORTs)
     Requests that traffic be tracked on a per PORT basis for udp.

SPOOFING AND LOOPING
====================

   Ipfwgen makes an attempt to generate all the anti-looping and
anti-spoofing rules.  These are all optional, but anti land-attack rules
will be added automatically.

*no_looping*()
     Specifies that obvious packet loops should be prevented.  For example,
     do not route packets meant for us out and outside interface.

*no_spoofing_us*()
     Specifies that if there is an "outside" interface, the packets
     arriving on it should be checked to make sure that they don't claim
     to come from ourselves.

*no_spoofing_by_us*()
     Specifies that we should only route packets out our "outside"
     interface that came from us.

*no_leaf_spoofing*()
     Only accept packets from a leaf interface that come from and address
     that routes over the leaf interface.  Do not accept any packets from
     anyone that claim to be from addresses that route over a leaf
     interface unless that came in over the leaf interface.

FILTER BY ADDRESSES RULES
=========================

   These are all optional.

*from_net_rules*(network,rules)
     Apply the specified ruleset to packets that came from an address with
     the network specified.

*to_net_rules*(network,rules)
     Apply the specified ruleset to packets that are destined for an
     address with the network specified.

*drop_unwanted*(networks)
     A quick way to list the networks that you do not with to communicate
     with.

FITLER BY PORT
==============

   These are all optional.

*tcp_from_rules*(port,rules)
     Apply the rules specified to tcp packets that came from the specified
     port.

*tcp_to_rules*(port,rules)
     Apply the rules specified to tcp packets that are destined for the
     specified port.

*udp_from_rules*(port,rules)
     Apply the rules specified to udp packets that came from the specified
     port.

*udp_to_rules*(port,rules)
     Apply the rules specified to udp packets that are destined for the
     specified port.

ORIGINATION AND TERMINATION
===========================

   These are all optional.  These filters will be generated anyway to
handle the anti land-attack rules.

*to_me_rules*(rules)
     Apply the specified rules to packets that are destined for this
     machine.

*not_to_me_rules*(rules)
     Apply the specified rules to packets that are not destined for this
     machine.

*from_me_rules*(rules)
     Apply the specified rules to packets that are sent from this machine.

*not_from_me_rules*(rules)
     Apply the specified rules to packets that came from some other
     machine.

FILTER BY INTERFACE
===================

   These are all optional, but these filters will be generated anyway to
do the anti-looping and anti-spoofing rules.

*in_interface_rules*(interface,rules)
     Apply the specified rules to packets that arrived on the specified
     interface.

*out_interface_rules*(interface,rules)
     Apply the specified rules to packets that are departing over the
     specified interface.

GENERATE OPTIONS
================

   Once the rules have been declared, they must be compiled into actual
firewall commands.  The command to compile them is generate(options).  The
generate command should be given last.

   The compiled rules are dumped on STDOUT.  They are not automatically
executed.  Running generate() cannot harm your system.  Running the output
from a program that includes generate() can harm your system so be careful!

   The following options are understood.

DEFAULT-ACCEPT
     Specifies that unless packets are specifically rejected, they should
     be accepted.  The default is that packets that are not specifically
     accpeted are rejected.

INSECURE
     When building the firewall, add in a rule to accept all packets as a
     temporary measure.  When the firewall is completely built, remove the
     rule.  This creates a window of opportunity for attack.  On the other
     hand, it helps prevent accididental computer death when rebuilding
     the firewall.  It's a good idea to use INSECURE while testing your
     firewall, but not to use it for final deployment.

LOG_DENIES
     Specifies that in general, when packets are denied, they should be
     logged.  Some rules will still not log: the anti-looping rules tend
     to deny a lot of packets and logging those is both boring and
     wasteful.  Rules that are defined by hand will that use =deny will
     log the denies if this is set.

RULE LANGUAGE
=============

   Whenever a command argument includes filtering rules, the rules are
expected to be passed in as a single string with the individual rules
separated with newlines.

META RULES
----------

   Ipfwgen rule generation can be modified with special "rules".

=label name
     Specifies a skipto target label.    Don't worry about the numbering
     of the rules.  Add a label wherever needed.  Some labels are already
     defined so don't be alarmed if you get an un-expected duplicate.

=rulenum num
     If possible, set the current rule number to num.

=gap [size]
     Make a gap in the rule numbering by rounding up to the next multiple
     of size.

=countby num
     When incrementing rule numbers, increment by num.

META ACTIONS
------------

   In addtion to the standard actions defined by `ipfw' in this node,
there are some new ones defined by Ipfwgen.

=skiprule
     Specifies that the action for this filter rule is to skip over the
     following rule.

=skipto label
     Specifies that the action for this filter rule is to skip to the rule
     after where the label is specified.

=deny
     Specifies that the action for this filter rule is to deny the packet.
     Packets denied using =deny will be logged if the generate option
     LOG_DENIES is specified.

=deny_log
     Specifies that the action for this filter is to deny the packet.  Just
     plain *deny log* can be used insted.

=deny_no_log
     Specifies that the action for this filter is to deny the packet.  Just
     plain deny can be used instead.

META SPECIFIERS
---------------

   Ipfwgen provides a shorthand way to specify certain things.

=ME
     The =ME specifier will be replaced by the IP address of the firewall
     system.  If the firewall system has more than one IP address the rule
     will be replicated as necessary to put them all in.  =skiprule still
     works.

=US
     The =US specifier will be replaced by the network defined by the
     *us*() command.  If more than one network was defined, then the rule
     with the =US specifier will be replicated as necessary to put them all
     in.  =skiprule still works.

=TOUS
     The =US specifier will be replaced by the network defined by the
     *to_us*() command.  If more than one network was defined, then the
     rule with the =US specifier will be replicated as necessary to put
     them all in.  =skiprule still works.

=FROMUS
     The =FROMUS specifier will be replaced by the network defined by the
     *from_us*() command.  If more than one network was defined, then the
     rule with the =US specifier will be replicated as necessary to put
     them all in.  =skiprule still works.

=IN
     The =IN specifier will be replaced by the interfaces that the firewall
     system has.  This will likely require replicating the rule with the
     specifier.  =skiprule still works.

=host:hostname
     The =host:hostname specifier will be replaced with the IP address of
     the hosthame given.  Only one IP address will be substituted in so do
     not use this with hosts that have multiple IP addresses.  The
     =host:hostname specifier is the only specifier that can be used more
     than once in a rule and the only one that can be combined with other
     specifiers.

=IF0
     FreeBSD treats the first interface a specially.  The =IF0 specifier
     will be replaced by the name of the first interface.  =IF0 can be
     combined with other meta specifiers.

SEQUENCE
========

   The rules generated by Ipfwgen are processed in the following sequence:

  1. Counting rules.  Count packets in by interfaces; count packets out by
     interface; count packets from udp ports; count packets to udp ports;
     count packets from tcp ports; count packets to tcp pots; count
     packets from and to particular networks.

  2. Apply filters on packets that are from the firewall system
     (*to_me_rules*).  Apply filters on packets that are not from the
     firewall system (*not_to_me_rules*).

  3. Apply filters on packets that are to the firewall system
     (*from_me_rules*).  Apply filters on packets that are not to the
     firewall system (*not_from_me_rules*).

  4. Apply filters for packets that came in via a particular interface.
     (*in_interface_rules*).  This includes loop prevention on
     point-to-point interfaces.  This also includes preventing others from
     spoofing us and leaf nodes from spoofing anyone.

  5. Apply filters for packets that are going out via a particular
     interface (*out_interface_rules*).  This includes loop prevention on
     outside interfaces and on broadcast networks.  This also includes
     preventing us from spoofing others.

  6. Accept packets that are part of established TCP connections.

  7. Apply filters for packets that are coming from a particular network
     (*from_net_rules*).  This includes preventing anyone from spoofing
     traffic from leaf nodes.

  8. Apply filters for packets that are going to a particular network
     (*to_net_rules*).  This includes dropping unwanted networks.

  9. Apply filters for packets that are coming from a particular udp port.

 10. Apply filters for packets that are going to a particular udp port.

 11. Apply filters for packets that are coming from a particular tcp port.

 12. Apply filters for packets that are going to a particular tcp port.

 13. Accept or deny the rest as per the DEFAULT-ACCEPT option.

EXAMPLE
=======

     #/usr/local/bin/perl -w

     use strict;
     use BSD::Ipfwgen;
     use IO::Handle;

     outside 'fxp0';
     leaf 'etha32';
     consolidate '209.66.121.128/25';
     us qw(
     	140.174.82.0/24
     	207.33.232.0/22
     	207.33.184.0/22
     	207.33.240.0/21
     	209.157.64.0/19
     	140.174.154.0/24
     	207.33.66.0/24
     	209.66.121.0/24
         );
     not_us qw(
     	209.66.121.0/29
     );
     symmetric qw(
     	209.66.121.0/27
         );

     count_by_interface();
     count_by_tcp qw(80 119 21 53 25 871 513 23 6667);
     count_by_address qw();
     drop_unwanted qw(
     	192.168.0.0:255.255.0.0
     	172.16.0.0:255.240.0.0
     	10.0.0.0:255.0.0.0
         );

     no_looping();
     no_spoofing_us();
     no_spoofing_by_us();
     no_leaf_spoofing();

     to_me_rules <<'';
     	=deny udp from not 140.174.82.0/26 to any 111,2049 # portmap, NFS
     	=deny tcp from not 140.174.82.0/26 to any 111 # portmap

     from_me_rules <<'';
     	=deny udp from any 111,2049 to not 140.174.82.0/26 # portmap, NFS
     	=deny tcp from any 111 to not 140.174.82.0/26 # portmap

     to_net_rules ('=host:mac84', <<'');
     	=skiprule tcp from 140.174.82.32/27 to =host:mac84 6000 # mac84
     	=deny tcp from any to =host:mac84 6000

     generate qw(INSECURE DEFAULT-ACCEPT);

REQUIREMENTS
============

   Ipfwgen generates commands that work with FreeBSD 2.2.5's firewall
program: `ipfw' in this node.  Ipfwgen makes use of features that were
only recently added to ipfw: skipto, xmit, recv.

BUGS
====

   Ipfwgen cannot currently deal non-exclusive thru traffic.  For ISPs
this means that it cannot deal with customers that have redundent
connections.  Fixing this is not terribly hard.

   The firewalls generated by Ipfwgen are often not optimal.  If anyone
wishes to write an optimizer, that would be great!

   The firewalls generated by Ipfwgen can be hard to read.

   Ipfwgen expects the netmasks on point to point links to be accurate.
Nothing else really cares about such netmasks so this may lead to some
problems.

   Some of the internal structures aren't very enlightened.  For example,
everything having to do with get_netmask() and mark_addresses() could be
redone for clarity and speed.

COPYRIGHT
=========

   Copyright (C) 1998, David Muir Sharnoff.   All rights reserved.
License hearby granted for anyone to use this module at their own risk.
Please feed useful changes back to muir@idiom.com.

Perl extension for accessing interval timers
********************************************

NAME
====

   BSD::Itimer - Perl extension for accessing interval timers

SYNOPSIS
========

     use BSD::Itimer;
     my($interval_sec, $interval_usec, $current_sec, $current_usec) =
       getitimer(ITIMER_REAL);
     my($interval_sec, $interval_usec, $current_sec, $current_usec) =
       setitimer(ITIMER_REAL, $interval_sec, $interval_usec,
     	      $current_sec, $current_usec));

DESCRIPTION
===========

   This module provides access to the interval timers many operating
systems provide from perl.  Interval timers conceptually have microsecond
resolution (hardware typically limits actual granularity), with the
ability to reschedule the timer on a fixed repeating interval.  There are
usually several timers available with a different concept of "time".

OVERVIEW
========

   The interval timer is accessed by two exported functions, getitimer and
setitimer.  Most Unix systems have three interval timers available for
program use.  The current BSD::Itimer implementation knows about the
following timers, where implemented:

   *ITIMER_REAL* - This timer decrements in real time.  A SIGALRM is
delivered when this timer expires.

   *ITIMER_VIRTUAL* - This timer decrements in real time when the calling
process is running.  Delivers SIGVTALRM when it expires.

   *ITIMER_PROF* - This timer runs when the calling process is running,
and when the operating system is operating on behalf of the calling
process.  A SIGPROF is delivered when the timer expires.

   *ITIMER_REALPROF* - This timer is available under Solaris only.
Consult the setitimer(2) manual page for more information.

   Interval timers are represented as four item integer lists.  The first
two integers comprise the second and microsecond parts of the timer's
repeat interval.  The second pair represent the second and microsecond
parts of the current timer value.

   The getitimer function expects a single argument naming the timer to
fetch.  It returns a four element list, or an empty list on failure.

   The setitimer function expects a argument naming the timer to set, and
a four element list representing the interval.  It returns the previous
setting of the timer, or an empty list on failure.  Setting a timer's
repeat interval to 0 will cancel the timer after its next delivery.
Setting it's current value to 0 will immediately cancel the timer.

SEE ALSO
========

   perl(1), setitimer(2)

AUTHOR
======

   Daniel Hagerty <hag@linnaean.org>

COPYRIGHT
=========

   Copyright (c) 1999 Daniel Hagerty. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

BUGS
====

   Could use a friendly interface.

BSD process resource limit and priority functions
*************************************************

NAME
====

   BSD::Resource - BSD process resource limit and priority functions

SYNOPSIS
========

     use BSD::Resource;

     #
     # the process resource consumption so far
     #

     ($usertime, $systemtime,
      $maxrss, $ixrss, $idrss, $isrss, $minflt, $majflt, $nswap,
      $inblock, $oublock, $msgsnd, $msgrcv,
      $nsignals, $nvcsw, $nivcsw) = getrusage($ru_who);

     $rusage = getrusage($ru_who);

     #
     # the process resource limits
     #

     ($nowsoft, $nowhard) = getrlimit($resource);

     $rlimit = getrlimit($resource);

     $success = setrlimit($resource, $newsoft, $newhard);

     #
     # the process scheduling priority
     #

     $nowpriority = getpriority($pr_which, $pr_who);

     $success = setpriority($pr_which, $pr_who, $priority);

     # The following is not a BSD function.
     # It is a Perlish utility for the users of BSD::Resource.

     $rlimits = get_rlimits();

DESCRIPTION
===========

getrusage
---------

     ($usertime, $systemtime,
      $maxrss, $ixrss, $idrss, $isrss, $minflt, $majflt, $nswap,
      $inblock, $oublock, $msgsnd, $msgrcv,
      $nsignals, $nvcsw, $nivcsw) = getrusage($ru_who);

     $rusage = getrusage($ru_who);

     # $ru_who argument is optional; it defaults to RUSAGE_SELF

     $rusage = getrusage();

   The $ru_who argument is either `RUSAGE_SELF' (the current process) or
`RUSAGE_CHILDREN' (all the child processes of the current process) or it
maybe left away in which case `RUSAGE_SELF' is used.

   The `RUSAGE_CHILDREN' is the total sum of all the so far *terminated*
(either successfully or unsuccessfully) child processes: there is no way
to find out information about child processes still running.

   On some systems (those supporting both getrusage() and the POSIX
threads) there is also `RUSAGE_THREAD'. The BSD::Resource supports the
`RUSAGE_THREAD' if it is present but understands nothing more about the
POSIX threads themselves.  Similarly for `RUSAGE_BOTH': some systems
support retrieving the sums of the self and child resource consumptions
simultaneously.

   In list context getrusage() returns the current resource usages as a
list. On failure it returns an empty list.

   The elements of the list are, in order:
index	name		meaning usually (quite system dependent)

     0	utime		user time
     1	stime		system time
         	 2	maxrss		maximum shared memory or current resident set
     3	ixrss		integral shared memory
     4	idrss		integral or current unshared data
     5	isrss		integral or current unshared stack
     6	minflt		page reclaims
     7	majflt		page faults
         	 8	nswap		swaps
     9	inblock		block input operations
     	10	oublock		block output operations
     	11	msgsnd		messages sent
     	12	msgrcv		messaged received
     	13	nsignals	signals received
     	14	nvcsw		voluntary context switches
     	15	nivcsw		involuntary context switches

   In scalar context getrusage() returns the current resource usages as a
an object. The object can be queried via methods named exactly like the
middle column, name, in the above table.

     $ru = getrusage();
     print $ru->stime, "\n";

     $total_context_switches = $ru->nvcsw + $ru->nivcsw;

   For a detailed description about the values returned by getrusage()
please consult your usual C programming documentation about getrusage()
and also the header file `<sys/resource.h>'.  (In *Solaris*, this might be
`<sys/rusage.h>').

   Note 1: officially *HP-UX* does not support getrusage() at all but for
the time being, it does seem to.

   Note 2: Because not all kernels are BSD and also because of the sloppy
support of getrusage() by many vendors many of the values may not be
updated.

   For example *Solaris 1* claims in `<sys/rusage.h>' that the `ixrss' and
the `isrss' fields are always zero.

   In *SunOS 5.5 and 5.6* the getrusage() leaves most of the fiels zero
and therefore getrusage() is not even used, instead of that the */proc*
interface is used.  The mapping is not perfect: the maxrss field is really
the current resident size instead of the maximum, the idrss is really the
current heap size instead of the integral data, the isrss is really the
current stack size instead of the integral stack.  The ixrss has no
sensible counterpart at all so it stays zero.

getrlimit
---------

     ($nowsoft, $nowhard) = getrlimit($resource);

     $rlimit = getrlimit($resource);

   The $resource argument can be one of

     $resource		usual meaning		usual unit

     RLIMIT_CPU		CPU time		seconds

     RLIMIT_FSIZE		file size		bytes

     RLIMIT_DATA		data size		bytes
             RLIMIT_STACK		stack size		bytes
             RLIMIT_CORE		coredump size		bytes
             RLIMIT_RSS		resident set size	bytes
         	RLIMIT_MEMLOCK		memory locked data size	bytes

     RLIMIT_NPROC		number of processes	1

     RLIMIT_NOFILE		number of open files	1
     RLIMIT_OFILE		number of open files	1
             RLIMIT_OPEN_MAX		number of open files	1

     RLIMIT_AS		(virtual) address space	bytes
             RLIMIT_VMEM		virtual memory (space)	bytes

     RLIMIT_TCACHE		maximum number of	1
     			cached threads

     RLIMIT_AIO_MEM		maximum memory locked	bytes
     			for POSIX AIO
     RLIMIT_AIO_OPS		maximum number		1
     			for POSIX AIO ops

   *What limits are available depends on the operating system*.  See below
for `get_rlimits()' on how to find out which limits are available, for the
exact documentation consult the documentation of your operatgiing system.
The two groups (`NOFILE', C`OFILE', <OPEN_MAX>) and (`AS', `VMEM') are
aliases within themselves.

   Two meta-resource-symbols might exist

     RLIM_NLIMITS
     RLIM_INFINITY

   `RLIM_NLIMITS' being the number of possible (but not necessarily fully
supported) resource limits, see also the get_rlimits() call below.
`RLIM_INFINITY' is useful in setrlimit(), the `RLIM_INFINITY' is
represented as -1.

   In list context `getrlimit()' returns the current soft and hard resource
limits as a list.  On failure it returns an empty list.

   Processes have soft and hard resource limits.  On crossing the soft
limit they receive a signal (for example the `SIGXCPU' or `SIGXFSZ',
corresponding to the `RLIMIT_CPU' and `RLIMIT_FSIZE', respectively).  The
processes can trap and handle some of these signals, please see `Signals',
see Perlipc (perl.info).  After the hard limit the processes
will be ruthlessly killed by the `KILL' signal which cannot be caught.

   NOTE: the level of 'support' for a resource varies. Not all the systems

     a) even recognise all those limits
     b) really track the consumption of a resource
     c) care (send those signals) if a resource limit is exceeded

   Again, please consult your usual C programming documentation.

   One notable exception for the better: officially *HP-UX* does not
support getrlimit() at all but for the time being, it does seem to.

   In scalar context getrlimit() returns the current soft and hard
resource limits as an object. The object can be queried via methods `cur'
and max, the current and maximum resource limits for the `$resource',
respectively.

getpriority
-----------

     $nowpriority = getpriority($pr_which, $pr_who);

     # the default $pr_who is 0 (the current $pr_which)

     $nowpriority = getpriority($pr_which);

     # the default $pr_which is PRIO_PROCESS (the process priority)

     $nowpriority = getpriority();

   getpriority() returns the current priority. NOTE: getpriority() can
return zero or negative values completely legally. On failure
getpriority() returns undef (and $! is set as usual).

   The priorities returned by getpriority() are in the (inclusive) range
`PRIO_MIN'...`PRIO_MAX'.  The $pr_which argument can be any of
PRIO_PROCESS (a process) `PRIO_USER' (a user), or `PRIO_PGRP' (a process
group). The $pr_who argument tells which process/user/process group, 0
signifying the current one.

   Usual values for `PRIO_MIN', `PRIO_MAX', are -20, 20. A negative value
means better priority (more impolite process), a positive value means
worse priority (more polite process).

   NOTE: in *AIX* if the BSD compatibility library is not installed or not
found by the installation procedure of the BSD::Resource the `PRIO_MIN' is
0 (corresponding to -20) and `PRIO_MAX' is 39 (corresponding to 19, the
BSD priority 20 is unreachable).

setrlimit
---------

     $success = setrlimit($resource, $newsoft, $newhard);

   setrlimit() returns true on success and undef on failure.

   NOTE: A normal user process can only lower its resource limits.  Soft
or hard limit `RLIM_INFINITY' means as much as possible, the real hard
limits are normally buried inside the kernel and are *very*
system-dependent.

setpriority
-----------

     $success = setpriority($pr_which, $pr_who, $priority);

     # NOTE! If there are two arguments the second one is
     # the new $priority (not $pr_who) and the $pr_who is
     # defaulted to 0 (the current $pr_which)

     $success = setpriority($pr_which, $priority);

     # The $pr_who defaults to 0 (the current $pr_which) and
     # the $priority defaults to half of the PRIO_MAX, usually
     # that amounts to 10 (being a nice $pr_which).

     $success = setpriority($pr_which);

     # The $pr_which defaults to PRIO_PROCESS,

     $success = setpriority();

   setpriority() is used to change the scheduling priority.  A positive
priority means a more polite process/process group/user; a negative
priority means a more impoite process/process group/user.  The priorities
handled by setpriority() are [`PRIO_MIN',`PRIO_MAX'].  A normal user
process can only lower its priority (make it more positive).

   NOTE: A successful call returns 1, a failed one 0.

times
-----

     use BSD::Resource qw(times);

     ($user, $system, $child_user, $child_system) = times();

   The BSD::Resource module offers a times() implementation that has
usually slightly better time granularity than the times() by Perl core.
The time granularity of the latter is usually 1/60 seconds while the
former may achieve submilliseconds.

   NOTE: The current implementation uses two getrusage() system calls: one
with RUSAGE_SELF and one with RUSAGE_CHILDREN.  Therefore the operation is
not `atomic': the times for the children are recorded a little bit later.

   NOTE: times() is not imported by default by BSD::Resource.    You need
to tell that you want to use it.

   *NOTE: This is not a real BSD function.*

get_rlimits
-----------

     $rlimits = get_rlimits();

   *NOTE: This is not a real BSD function. It is a convenience function.*

   get_rlimits() returns a reference to hash which has the names of the
available resource limits as keys and their indices (those which are
needed as the first argument to getrlimit() and setrlimit()) as values.
For example:

     $r = get_rlimits();
     print "ok.\n" if ($r->{'RLIM_STACK'} == RLIM_STACK);

ERRORS
======

   *      Your vendor has not defined BSD::Resource macro RLIMIT_...

     The code tried to call getrlimit/setrlimit for a resource limit that
     your operating system vendor/supplier does not support.  Portable code
     should use get_rlimits() to check which resource limits are defined.

EXAMPLES
========

     # the user and system times so far by the process itself

     ($usertime, $systemtime) = getrusage();

     # ditto in OO way

     $ru = getrusage();

     $usertime   = $ru->utime;
     $systemtime = $ru->stime;

     # get the current priority level of this process

     $currprio = getpriority();

VERSION
=======

   Release 1.08

AUTHOR
======

   Jarkko Hietaniemi, `jhi@iki.fi'

Perl extension to manipulate BTRIEVE SAVE records.
**************************************************

NAME
====

     BTRIEVE::SAVE - Perl extension to manipulate BTRIEVE SAVE records.

SYNOPSIS
========

     use BTRIEVE::SAVE
     my $btr = BTRIEVE::SAVE->new('cc057.std','cc057.dar');
     $btr->parse_file();
     my $recs = $btr->{'array'};
     for (@$recs) {
         my($rhfixed,$rfixed,$rvar)=@{$_->{values}};
         print $rhfixed->{'Title'}."\n";
     }

     # Often the first record is some kind of header.  Generally one
         # treats header records differently from those that follow. E.g.,
         # they often have counts of the following records that must be
         # adjusted if we are gonna kill or add records.  Here we leave it
         # alone.

     my $output = "";
     $header=shift @$recs;

     my $data = $header->fixed.$header->var;
     $output .= $header->counted_rec($data);

     foreach my $rec (@$recs) {
         my($rhfixed,$rfixed,$rvar)=@{$rec->{values}};
         $rhfixed->{'Title'} =~s/^\s*the/The/;
         $output .=$rec->counted_rec_hash();
     }
     $output .="\cZ"; # now $output is a legal Btrieve save record.
     # For large records, one may want to do everything incrementally.

     open OUT,">>cc057.das"
               or die "Could not open cc057.das for append: $!\n";
     binmode OUT;
     my $incbtr = BTRIEVE->new('cc057.std','cc057.dar');
     my $header = $incbtr->next_rec();
     my $data = $header->fixed.$header->var;
     print OUT $header->counted_rec($data);

     while (defined( my $rec=$incbtr->next_rec) ) {
         my($rhfixed,$rfixed,$rvar)=@{$rec->{values}};
         $rhfixed->{'Title'} =~s/^\s*the/The/;
         print OUT $rec->counted_rec_hash();
     }
     print OUT "\cZ";
     close OUT or die "Could not close cc057.das: $!\n";

DESCRIPTION
===========

   BTRIEVE::SAVE is a Perl 5 module for reading in, manipulating, and
outputting Pervasive's save file format for its Btrieve products.

   BTRIEVE::SAVE uses BTRIEVE::SAVE::REC which abstracts an individual
record in the entire file.

   You must have a config file for your save file: this allows
BTRIEVE::SAVE::REC to analyse the fixed parts and find the variable parts
of each BTRIEVE::SAVE record.

Downloading and Installing
--------------------------

Download
     Download the latest version from
     http://www.cpan.org/modules/by-module/BTRIEVE. The module is provided
     in standard CPAN distribution format. It will extract into a directory
     BTRIEVE-version with any necessary subdirectories.  Change into the
     BTRIEVE top directory.

Unix Install
          perl Makefile.PL
          make
          make test
          make install

Win9x/WinNT/Win2000 Install
          perl Makefile.PL
          perl test.pl
          perl install.pl

Test
     Once you have installed BTRIEVE::SAVE, you can check if Perl can find
     it. Change to some other directory and execute from the command line:

          perl -e "use BTRIEVE::SAVE"

     If you do not get any response that means everything is OK! If you get
     an error like *Can't locate method "use" via package BTRIEVE::SAVE*
     then Perl is not able to find BTRIEVE/SAVE.pm-double check that the
     file copied it into the right place during the install.

Todo
----

   * Support for the other 12 documented btrieve data types.

   * Help for adding the names column in the config file.

   * More detailed warnings/sanity checks on the config file and save file.

Notes
-----

   Please let us know if you run into any difficulties using
BTRIEVE::SAVE-we'd be happy to try to help. Also, please contact us if you
notice any bugs, or if you would like to suggest an
improvement/enhancement. Email addresses are listed at the bottom of this
page. Lane is probably the most interested in making this work, so may be
your best initial bet.

BTRIEVE::SAVE::REC structure.
-----------------------------

   A save file record on disk looks like:

     __________________________________________
     |   Fixed,          | Fixed,   |           |
     Count[, ] |   indexed.        | left-over|  Variable |\r\n
     |___________________|__________|___________|

   The Count is the number of "boxed bytes" (excluding the count itself,
the following comma or space, and the final two bytes at the end). Count is
an unpadded ascii integer, like "524".

   Count is followed by either a comma or a space. BTRIEVE::SAVE::REC
writes a comma, but reads either comma or space.

   The boxes are binary data. BTRIEVE::SAVE::REC will not interpret the
(fixed, left-over) or variable boxes, and will parse the (fixed, indexed)
data into a hash based on a template and names determined from the config
file.

   The last two boxes may be empty; if the sum of the lengths is equal to
the fixed_length defined in the config file the (fixed, left-over) box
will have no bytes. Variable will be non-empty if and only if Count >
fixed_length.

   The number of bytes covered by the first two fields is equal to
fixed_length.  (In theory the (fixed, indexed) and (fixed, left-over)
could be intermixed, with possible overlaps.  Has anyone seen this?  Docs
saying that Pervasive won't support this?)

   The final two bytes are unix return and newline bytes.

   A save file is a bunch of save file records concatenated with no
intervening bytes followed by "\cZ".

   Each BTRIEVE::SAVE::REC has admin information in its {opt} key and data
in its {values} key.

     {opt} has keys:
       {fixed_defs} keys a ref to an array of hashes with keys:
         {len}      - length in bytes of the field
         {name}     - the user-defined name of that field, found from an
                      extra column in the config file. The config file
                      cannot use "ZZ" as a field name; one of the {name}s
                      is always set to "ZZ" to handle fixed length
                      information which is unaccounted for by btrieve's
                      keys.
         {type}     - Btrieve's idea of the type of that field.

     The array of hashes is in the order that the defining lines occur
     in the config file.

     {template} - pack template used for extracting values
     {names}    - ref to array of names as in fixed_defs.
                  This is not strictly necessary.

     {len}      - total length of the fixed part of the record.  This
                  must be at least equal to the sum of the {len}'s in
                  the {fixed_defs}.

     {values} is a ref to an array
         [$rhfixed,$rfixed,$rvar]

         where $rhfixed is a ref to a hash with keys from the {opt}{names}
         and values the unpacked version of the btrieve-defined
         fixed portion of the record.

         "ZZ" will always be the last element in {names};

     $rhfixed->{'ZZ'} will include all the bytes of the btrieve fixed
     part of the record that are not accounted for by the config
     file. (This means it can be empty.)  $rfixed is a reference to
     the btrieve-defined fixed portion of the record and $rvar is a
     reference to the btrieve-defined variable portion of the record.

     Parsing and definitions of the {fixed_defs} appears to assume that
     all keys are consecutive and that any fixed-length information not
     accounted for by key defs occurs at the end.

     If you come across non-consecutive keys in a -stat file, make up
     extra key fields to cover the missing parts. This will make
     BTRIEVE::SAVE::REC happy.

     If folk actually see these kinds of keys, please alert us.  We can
     document this as a limitation. (We also take patches....). We are
     also interested if folk find examples of overlapping key defs.

BTRIEVE::SAVE structure.
------------------------

   Each BTRIEVE::SAVE record has keys:

     {opt} with keys:
          {file}      - a file name that BTRIEVE::SAVE will read from.
          {handle}    - a stored filehandle that BTRIEVE::SAVE will use,
     		     based on the {file}
          {increment} - how many records to attempt to read at a time
                        in parse_file().
          {proto_rec} - A BTRIEVE::SAVE::REC with empty {values}, used
                        for filling in elements of BTRIEVE::SAVE->{array}.
          {config}    - The config file used to define the {proto_rec}
                        and all elements of the {array}

     {array} which is a ref to an array (0-based) of BTRIEVE::SAVE::RECs
             with structure determined by {opt}{proto_rec}.

METHODS
=======

   Here is a list of the methods in BTRIEVE::SAVE and ::REC that are
available to you for reading in, manipulating and outputting BTRIEVE::SAVE
data.

new(),newconfig()
-----------------

     Creates a new BTRIEVE::SAVE object; also used for ::REC.

     $x = BTRIEVE::SAVE->new('cc057.std');
     $x = BTRIEVE::SAVE->new('cc057.std','cc057.dat');

     $rec = BTRIEVE::SAVE::REC->new($ranames,$rtemplate,
                                    $packed_length,$rhfixed_defs);
     $rec = BTRIEVE::SAVE::REC->newconfig('cc057.std');

   BTRIEVE::SAVE has an optional config file first parameter and an
optional file parameter to create and populate the object with data from a
file. If a file is specified it will read in the entire file. If you wish
to read in only portions of the file see openbtr(), nextbtr(), and
closebtr() below or use next_rec() and BTRIEVE::SAVE::RECs directly.

   BTRIEVE::SAVE::REC allows creation with defined state with new() and
also from a config file with newconfig(). See the last EXAMPLE below for a
definition of the format of the config file.

config()
--------

   Installs a prototypical BTRIEVE::SAVE::REC in the BTRIEVE::SAVE object
based on the contents of the config file.

     $x= BTRIEVE::SAVE->new();
     $x->config('cc057.std');

openbtr()
---------

   Openbtr sets up incremental reading for a BTRIEVE SAVE file. It takes a
hashref with key 'file' (name of the btrieve file). Increment defines how
many records to read in and is taken from the object or defaulted to 1.

     $x = BTRIEVE::SAVE->new('cc057.std');
     $x->openbtr({file=>"cc057.dat",increment=>"2"});
     $x->openbtr({file=>"cc057.dat"});

nextbtr()
---------

   Once a file is open nextbtr() can be used to read in the next group of
records. The increment can be passed to change the amount of records read
in if necessary. An increment of -1 will read in the rest of the file.

     $x->nextbtr();
     $x->nextbtr(10);
     $x->nextbtr(-1);

   nextbtr() will return the amount of records read in.

     $y=$x->nextbtr();
     print "$y more records read in!";

closebtr()
----------

   If you are finished reading in records from a file you should close it
immediately.

     $x->closebtr();

parse_file()
------------

   Parse_file reads in a file, possibly incrementally. It APPENDS the
record to the BTRIEVE::SAVE {array} field. It returns the number of
records read.

     $y=$x->parse_file();
     print "$y records read!\n";

next_rec()
----------

   Next_rec returns a new BTRIEVE::SAVE::REC record with the same
structure as {proto_rec} and {values} based on the bits in the next record.

     my $rec=$x->next_rec;

next_recbits()
--------------

   Next_recbits returns the data in the next record on-disk. It
side-effects the position of the file pointer implied by the handle.

     my $string_rec = $x->next_recbits

output()
--------

   Output dumps all records in {array} to a file (if passed one) in
Btrieve's save file format.  It returns a string version of this if there
is no file passed.

     $x->output(">cc057.das");
     my $btr_save_string = $x->output();

as_string()
-----------

   As_string returns a string version in Btrieve's save file format of
{array}.

     my $btr_save_string = $x->as_string();

save_to_rdb()
-------------

   Save_to_rdb takes an rdb filename, save filename, error file name, and
config file name.  Also takes the field name for unindexed fixed info and
var info, and strings to translate into from tab and newline characters.
Writes an rdb file using the save file and config information; warns and
writes to the rdb formatted error file if there are problems in the data.

     $btr->save_to_rdb('f.rdb','f.sav','ferr.sav',
     		           'ZZ','VAR','<TAB>','<RET>');

rdb_to_save()
-------------

   Rdb_to_save takes an rdb filename, save filename, error file name, and
config file name.  Also takes the field name for unindexed fixed info and
var info, and strings to translate into tab and newline characters. Writes
an rdb file using the rdb file and config information; warns and writes to
the save formatted error file if there are problems in the data.

     $btr->rdb_to_save('f.rdb','f.sav','ferr.rdb',
     		           'ZZ','VAR','<TAB>','<RET>');

BTRIEVE::SAVE::REC METHODS
==========================

copy_struct()
-------------

   Copy_struct takes a record and returns a new BTRIEVE::SAVE::REC with
empty {values} and the same {opt}s.

     my $new_rec=$rec->copy_struct();

parse_string()
--------------

   Parse_string takes a string representation of a btrieve record
(typically from next_recbits) and returns a new record with the same
{opt}s and appropriate {values}. Parse_string makes sure that all optional
fields (ZZ and the var field) are initialised to empty strings if
undefined.

     my $curr_rec=$rec->parse-string($string_rec);

counted_rec()
-------------

   Counted_rec takes a string version of a record and returns a string
that can represent this on-disk in Btrieve's save file format.

     my $save_rec = $rec->counted_rec($string_rec);

counted_rec_hash()
------------------

   Counted_rec_hash will take the hash and variable information in
{values} and return a legal string in Btrieve's save file format.

     my $save_rec = $rec->counted_rec_hash();

fixed()
-------

   Fixed will return a string representation of the fixed string
information in {values}.

     my $fix_string = $rec->fixed;

var()
-----

   Var will return a string representation of the var string information
in {values}.

     my $var_string = $rec->var;

data()
------

   Data will return a string representation of a record using the hash and
variable information in {values}.

     my $data = $rec->data();

fix_hash_to_string()
--------------------

   Fix_hash_to_string returns the fixed part of a record based on its hash
{values}.  If you want to get access to the raw fixed part, use fixed().

     my $fixed = $rec->fix_hash_to_string();

EXAMPLES
========

   Here are a few examples to fire your imagination.

   * Input. This example will read in a tab-delimited file and output a
     Btrieve save file. Last field is variable.

          #!/usr/bin/perl
          use BTRIEVE::SAVE; # ::REC comes along for the ride.
          my $proto_rec = BTRIEVE::SAVE::REC->newconfig("config.std");

          open F,"import.tab"
                     or die "Could not open import.tab for read: $!\n";
          open OUT,">output.dat"
                     or die "Could not open output.dat for write: $!\n";
          binmode OUT;
          while (<F>) {
          	  chomp;
          	  my @fields= split(/\t/);
          	  my $var = pop @fields;
          	  my $data = (join "",@fields).$var;
          	  print OUT $proto_rec->counted_rec($data);
           }
           print OUT "\cZ";

          close F;
          close OUT;

   * Feeling paranoid? I know I am.

     Let's say somebody comes to you with a large tab delimited file, a
     BTRIEVE config file (forced on her by external software), and a
     burning desire that her data become one with BTRIEVE.

     And she added data to the file by hand over the last 3 years. And she
     is not quite sure that she got the right lengths for the indexes.

     Fortunately her tab-delimited file is in /rdb format so at least the
     field names are available. She tells you that the last, very
     important, field is variable length. The order of names in the rdb
     file is different than that in the save file spec, and you won't write
     a filter to fix that (go figure).

     /Rdb files look like:

          Author	   Title                Opinion_of_AACR2
          ------	   ------               ----------------
          Fred	   Fred's holidays      Better than chocolate
          James	   James' elbows        Larger than several trucks

          See
          http://www2.linuxjournal.com/lj-issues/issue67/3294.html
          for details on /rdb which is a cool idea.

          $ grep '<VAR>\|<RET>' file.rdb |wc -l
            0
          $ cat rdb_btr.pl
          #!/usr/bin/perl
          print "Usage: rdb_btr.pl <rdbfile><conf><savefile><error rdbfile>"
                  unless scalar @ARGV ==4;
          my ($rdb,$config,$save,$err) = @ARGV;
          my $btr = BTRIEVE::SAVE->new($config);
          $btr->rdb_to_save($rdb,$save,$err,
          		           'ZZ','Opinion_of_AACR2','<TAB>','<RET>');

          $ rdb_btr.pl file.rdb file.std file.sav file.err
            Paranoia 2: Lengths do not match for Title at line 6.
            Paranoia 1: Number of fields do not match rdb spec at line 300.
          $ wc -l file.err
            4
          $ etbl file.err
          (Time passes as you edit the relevant lines' problems.)
          $ rdb_btr.pl file.err file.std file2.sav file2.err
          $ wc -l file2.err
            2
          $ perl -ne 'print unless /^\cZ$/' file.sav | cat - file2.sav > clean.sav

          *Whew*

   * Someone hands you a BTRIEVE file. Having paid the tax to Pervasive you
     have a command line utility "butil" with many options, including
     -load, -save, -stat and -clone.

     You want to get the file out into /rdb tab-delimited form so you only
     need -save and -stat.

          $ butil -save file.btr file.dat
          $ butil -stat file.btr > file.std

          (Edit file.std to add an extra column thusly:)

          (Leave what's above here alone...)
          Record Length = 171
          Record Length = <whatever you want the fixed length to be.>

          (...leave the next alone until the Key defs below.
          Some columns elided for space.)

          Key         Pos..     Type        Null V..    ACS
              Segment      Len..       Flags       Uniq..
            0    1      1    4  Zstring         - .. 8   --
            1    1      5    4  Integer  MD     - .. 8   --

          (..and what's after alone.)

          Add an extra column:

          Key         Pos..    Type         Null V..    ACS
              Segment      Len..        Flags      Uniq..    Langname
            0    1      1    4  Zstring         --.. 8  --   Author
            1    1      5    4  Integer  MD     --.. 8  --   dbcn

          $ cat btr_rdb.pl
          #!/usr/bin/perl
          print "Usage: btr_rdb.pl <rdbfile><conf><savefile><error savefile>"
                  unless scalar @ARGV ==4;
          my ($rdb,$config,$save,$err) = @ARGV;
          my $btr = BTRIEVE::SAVE->new($config);
          $btr->save_to_rdb($rdb,$save,$err,
          		           'ZZ','VAR','<TAB>','<RET>');

          $ rdb_btr.pl file.rdb file.std file.sav file.err
          $ wc file.err
            0       1       1 file.err
          $

AUTHORS
=======

   Chuck Bearden cbearden@rice.edu

   Bill Birthisel wcbirthisel@alum.mit.edu

   Derek Lane dereklane@pobox.com

   Charles McFadden chuck@vims.edu

   Ed Summers esummers@odu.edu

SEE ALSO
========

   perl(1), www.pervasive.com, "Btrieve Complete" by Jim Kyle
(Addison-Wesley 1995).

COPYRIGHT
=========

   Copyright (C) 2000, Bearden, Birthisel, Lane, McFadden, Summers.  All
rights reserved.  Copyright (C) 2000, Duke University, Lane. All rights
reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself. Feb 15 2000.

Generate CODE 128 bar codes
***************************

NAME
====

   Barcode::Code128 - Generate CODE 128 bar codes

SYNOPSIS
========

     use Barcode::Code128;

     $code = new Barcode::Code128;

REQUIRES
========

   Perl 5.004, Carp, Exporter, GD

EXPORTS
=======

   By default, nothing.  However there are a number of constants that
represent special characters used in the CODE 128 symbology that you may
wish to include.  For example if you are using the EAN-128 or UCC-128
code, the string to encode begins with the FNC1 character.  To encode the
EAN-128 string "00 0 0012345 555555555 8", you would do the following:

     use Barcode::Code128 'FNC1';
     $code = new Barcode::Code128;
     $code->text(FNC1.'00000123455555555558');

   To have this module export one or more of these characters, specify
them on the use statement or use the special token ':all' instead to
include all of them.  Examples:

     use Barcode::Code128 qw(FNC1 FNC2 FNC3 FNC4 Shift);
     use Barcode::Code128 qw(:all);

   Here is the complete list of the exportable characters.  They are
assigned to high-order ASCII characters purely arbitrarily for the
purposes of this module; the values used do not reflect any part of the
CODE 128 standard.  Warning: Using the `CodeA', `CodeB', `CodeC',
`StartA', `StartB', `StartC', and Stop codes may cause your barcodes to be
invalid, and be rejected by scanners.  They are inserted automatically as
needed by this module.

     CodeA      0xf4        CodeB      0xf5         CodeC      0xf6
     FNC1       0xf7        FNC2       0xf8         FNC3       0xf9
     FNC4       0xfa        Shift      0xfb         StartA     0xfc
     StartB     0xfd        StartC     0xfe         Stop       0xff

DESCRIPTION
===========

   Barcode::Code128 generates bar codes using the CODE 128 symbology.  The
typical use this is for generating a PNG file with the `png()' method
which uses the GD package by Lincoln Stein.  When this PNG file is
printed, it can be scanned by most modern hand-held bar code readers.  The
application which drove the invention of this module places the PNG file
on a web page which the user must print out and submit along with
supporting documents.  The bar code helps the receiving agency record when
it has been received.

   Since the GD module is required you will need to install it before
installing this module.  You can obtain it from the CPAN (Comprehensive
Perl Archive Network) repository of your choice under the directory
`authors/id/LDS'.  Visit http://www.perl.com/ for more information about
CPAN.  The GD home page is: http://stein.cshl.org/WWW/software/GD/GD.html

METHODS
=======

$object = new Barcode::Code128
     Creates a new barcode object.

$object->png($text)
$object->png($text, $x, $y)
     Generate a PNG file and return it.  Typically you will either print
     the result to standard output or save it to a file.  The contents of
     the return value from this method are a binary file, so if you are
     working on an operating system that makes a distinction between text
     and binary files be sure to call binmode(FILEHANDLE) before writing
     the PNG to it.  Example:

          open(PNG, ">code128.png") or die "Can't write code128.png: $!\n";
          binmode(PNG);
          print PNG $object->png("CODE 128");
          close(PNG);

     Note: All of the arguments to this function are optional.  If you have
     previously specified $text to the barcode(), encode(), or text()
     methods, you do not need to specify it again.  The $x and `$y'
     variables specify the size of the barcode within PNG file in pixels.
     The overall image will be an extra 20 pixels taller to accomodate the
     plaintext rendering of the encoded message (in black on a transparent
     background).  If size(s) are not specified, they will be set to the
     minimum size, which is the length of the barcode plus 40 pixels
     horizontally, and 15% of the length of the barcode vertically.

$object->barcode($text)
     Computes the bar code for the specified text.  The result will be a
     string of '#' and space characters representing the dark and light
     bands of the bar code.  You can use this if you have an alternate
     printing system besides the `png()' method.

     Note: The $text parameter is optional. If you have previously
     specified $text to the encode() or text() methods, you do not need to
     specify it again.

Housekeeping Functions
----------------------

   The rest of the methods defined here are only for internal use, or if
you really know what you are doing.  Some of them may be useful to authors
of classes that inherit from this one, or may be overridden by subclasses.
If you just want to use this module to generate bar codes, you can stop
reading here.

$object->encode
$object->encode($text)
     Do the encoding.  If $text is supplied, will automatically call the
     text() method to set that as the text value first.

$object->text($text)
$text = $object->text
     Set or retrieve the text for this barcode.  This will be called
     automatically by encode() or barcode() so typically this will not be
     used directly by the user.

$object->start($code)
     If the code (see code()) is already defined, then adds the CodeA,
     CodeB, or CodeC character as appropriate to the encoded message inside
     the object.  Typically for internal use only.

$object->stop()
     Computes the check character and appends it along with the Stop
     character, to the encoded string.  Typically for internal use only.

$object->code($code)
$code = $object->code
     Set or retrieve the code for this barcode.  $code may be 'A', 'B', or
     'C'.  Typically for internal use only.  Not particularly meaningful
     unless called during the middle of encoding.

CLASS VARIABLES
===============

   None.

DIAGNOSTICS
===========

Image width $x is too small for bar code
     You have specified an image width that does not allow enough space for
     the bar code to be displayed.  The minimum allowable is the size of
     the bar code itself plus 40 pixels.  If in doubt, just omit the width
     value when calling `png()' and it will use the minimum.

Image height $y is too small for bar code
     You have specified an image height that does not allow enough space
     for the bar code to be displayed.  The minimum allowable is 15% of the
     width of the bar code.  If in doubt, just omit the height value when
     calling `png()' and it will use the minimum.

Unable to create $x x $y PNG image
     An error occurred when initializing a GD::Image object for the
     specified size.  Perhaps $x and `$y' are too large for memory?

No encoded text found
     This message from barcode() typically means that there was no text
     message supplied either during the current method call or in a
     previous method call on the same object.

No text defined
     This message from encode() typically means that there was no text
     message supplied either during the current method call or in a
     previous method call on the same object.

Unable to find encoding for "$text"
     Part or all of the message could not be encoded.  This may mean that
     the message contained characters not encodable in the CODE 128
     character set, such as a character with an ASCII value higher than 127
     (except the special control characters defined in this module).

Sanity Check Overflow
     This is a serious error in encode() that indicates a serious problem
     attempting to encode the requested message.  This means that an
     infinite loop was generated.  If you get this error please contact
     the author.

Unable to switch from "$old_code" to "$new_code"
     This is a serious error in start() that indicates a serious problem
     occurred when switching between the codes (A, B, or C) of CODE 128.
     If you get this error please contact the author.

Unable to start with "$new_code"
     This is a serious error in start() that indicates a serious problem
     occurred when starting encoding in one of the codes (A, B, or C) of
     CODE 128.  If you get this error please contact the author.

Unknown code "$new_code" (should be A, B, or C)
     This is a serious error in code() that indicates an invalid argument
     was supplied.  Only the codes (A, B, or C) of CODE 128 may be
     supplied here.  If you get this error please contact the author.

BUGS
====

   At least some Web browsers do not seem to handle PNG files with
transparent backgrounds correctly.  As a result your barcodes may have a
grey background behind the text version of the message.

AUTHOR
======

   William R. Ward, wrw@bayview.com

SEE ALSO
========

   perl(1), GD

Perl extension for decoding :CueCat(tm) scans
*********************************************

NAME
====

   Barcode::Cuecat - Perl extension for decoding :CueCat(tm) scans

SYNOPSIS
========

     use Barcode::Cuecat;

     my $bc = new Barcode::Cuecat();

     $bc->scan($garbage);
     my $type = $bc->type();	# Get the type of barcode
     my $code = $bc->code();	# The actual number scanned
     my $serial = $bc->serial();	# The serial of the :CueCat

DESCRIPTION
===========

   This module is an attempt to ease the adoption of :CueCat(tm) into
general purpose applications. The term :CueCat(tm) seems to be a trademark
of a company called Digital Convergence. The code in this module is based
on code that has been found in numerous sites. I have not found a
reference to an author, so I cannot give proper credit for it. Some
references point to Larry Wall, so if this code is actually yours, I hope
you don't mind some repackaging of it :).

   As for the legality of this code, I received my :CueCat over the mail,
outside the United States. I had to pay the shipping for this device, even
when I did not request it. According to the laws of the country where this
code is being written, I have each and every right to reverse engineer or
otherwise do whatever I please with this device. This module is one
example of what can I excercise under my legal rights. This code, of
course, carries the same warranties and can be used under the same terms
as Perl itself.

   The functions supported by this module are below:

`->new($string)'
     Creates a Barcode::Cuecat object. $string is optional. If supplied,
     this saves you from invoking `->scan()'.

`->scan($string)'
     Initializes the object with a newly scanned string.

`->type()'
     Returns the type of barcode decoded. For known :CueCat numbers, this
     will be ':C1'.

`->code()'
     Returns the actual number decoded in the barcode. Codes in the
     proprietary :CueCat format are converted automatically to a sequence
     of digits.

`->serial()'
     Returns the serial number of the :CueCat(tm) scanner. Keep in mind
     that this information is meaningless after declawing the device.

EXPORT
------

   None by default.

AUTHOR
======

   Luis E. Munoz <lem@cantv.net>. Thanks to Larry Wall <larry@wall.org>
for the compact original code. Thanks to Brian Blakley <bblakley@mp5.net>
for feedback.

SEE ALSO
========

   perl(1).

manipulate @INC dynamically for independent installation path
*************************************************************

NAME
====

   BaseLib - manipulate @INC dynamically for independent installation path

SYNOPSIS
========

     use BaseLib qw(BASEDIR LIBDIR);

   or just,

     use BaseLib;

DESCRIPTION
===========

   If you have a set of application with certain file structure under a
base directory, e.g. `pim', and it has a private modules directory called
`lib-perl', and it's intalled under `/usr/local'. For the application to
work, the scripts may need to say:

     use lib '/usr/local/pim/lib-perl';

   Someday, you need to move the application to, say,
`/vhost/www.some.host.com', so you need to change the use statement all
over the scripts to:

     use lib '/vhost/www.some.host.com/pim/lib-perl';

   If you do this a lot and get tired of changing the line for every
different installation path, or, you don't want to bother people using
your application to cange the line to meet their conditions, then you
might need this module.

   Now your scripts can say:

     use BaseLib qw(pim lib-perl);

   where `pim' and `lib-perl' are the BASEDIR and LIBDIR arguments
respectively.

   So there's no need to worry about different installation layout,
wherever the `pim' base directory is put under. The BASEDIR argument is
required while LIBDIR is optional (defaults to lib).

   As addition, you can use *BaseLib*'s global package variable,
*$BaseDir* to refer to the full path to `pim'. For example, assuming the
application is installed under `/usr/local', then

     print "Data dir: $BaseLib::BaseDir/data\n";

   will print,

     Data dir: /usr/local/pim/data

   Yes, you must qualify it with the package name since the variable is not
exportable. This may change in the future.

NOTE
====

   Please consider this module, the code and its interface, as in ALPHA
stage.  Expect any change in the future versions.

CAVEATS
=======

   I only tested it in the following environment:

     * Perl 5.005_03
     * Linux

   It's unlikely to work on systems don't recognize / as path separator.

   *BaseLib* will find the last occurence of *BASEDIR* string. If you mean
the base directory as `/usr/local/myapp', while the script uses the module
locates in `/usr/local/myapp/bin/sample/myapp/test/script.pl', then the
full path to the application base directory ends in
`/usr/local/myapp/bin/sample/myapp'.

   In mod_perl environment there's a high risk for conflict on the
`$BaseLib::BaseDir' if *BaseLib* is used by more than one application in
the same host.

   But any improvements/suggestions for wider support are welcome. A simple
comment on this module will do as well.

AUTHOR
======

   This module is written by Hasanuddin Tamir <hasant@trabas.com>.

   Copyright (C) 2000 *Trabas*.  All rights reserved.

   This software is freeware.  You may redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   See Lib, FindBin,

get and set MIME file attributes
********************************

NAME
====

   Be::Attribute - get and set MIME file attributes

SYNOPSIS
========

     use Be::Attribute;
     $node  = Be::Attribute::GetBNode("/my/file/here");
     @attrs = Be::Attribute::ListAttrs($node);
     for $i (@attrs) {
       print "$i - ", Be::Attribute::ReadAttr($node, $i), "\n";
     }
     Be::Attribute::CloseNode($node);

DESCRIPTION
===========

   Get (or set) MIME file attributes.

USAGE
=====

   lookit the synopsis. look at example.pl. Look at the .xs code.  Read
the Node webpage.

AUTHOR
======

   Tom Spindler, dogcow@globalcenter.net

SEE ALSO
========

   http://www.be.com/documentation/be_book/The%20Storage%20Kit/Node.html

do a Query for a given filesystem.
**********************************

NAME
====

   Be::Query - do a Query for a given filesystem.

SYNOPSIS
========

     use Be::Query;
     @files = Be::Query::Query($filesystem, $query);

DESCRIPTION
===========

   do a Query for a given filesystem

USAGE
=====

     @files = Be::Query::Query("/boot", "name=lib*.so");

   $filesystem is a path anywhere in the target filesystem; $query is a
query construction, of the form attribute op value [connector attribute op
value]

   Such as (name = fido) || (size >= 500)

   See the below URLs for more information on constructing queries.

AUTHOR
======

   Tom Spindler, dogcow@globalcenter.net

SEE ALSO
========

http://www.be.com/documentation/be_book/The%20Storage%20Kit/Query.html#14835:Zhead2:ZTheZPredicate,ZAttributes,ZandZIndices
and
http://www.be.com/documentation/be_book/The%20Storage%20Kit/Query.html29556:Zhead3:ZConstructingZaZPredicate
give help on how to construct queries. (Sorry for the annoying URLs.)

Perl extension for interpreting befunge.
****************************************

NAME
====

   Befunge::Interpreter - Perl extension for interpreting befunge.

SYNOPSIS
========

     use Befunge::Interpreter;

DESCRIPTION
===========

     Befunge::Interpreter is a fully Befunge-93 compliant
             Befunge interpreter written in Perl.

     The usage is easy.

     use Befunge::Interpreter;
     $interpreter = new Befunge::Interpreter;
     $interpreter->get_befunge("hello.bf");
     $intrepreter->process_befunge();

     That is all, so far.

TO-DO
=====

     I have to add lots of stuff, update to Funge-98 spec...

BUGS
====

     I don't know of any

CONTACT
=======

     Any problems contact xjharding@newbedford.k12.ma.us

benchmark running times of Perl code
************************************

NAME
====

   Benchmark - benchmark running times of Perl code

SYNOPSIS
========

     timethis ($count, "code");

     # Use Perl code in strings...
     timethese($count, {
     	'Name1' => '...code1...',
     	'Name2' => '...code2...',
     });

     # ... or use subroutine references.
     timethese($count, {
     	'Name1' => sub { ...code1... },
     	'Name2' => sub { ...code2... },
     });

     # cmpthese can be used both ways as well
     cmpthese($count, {
     	'Name1' => '...code1...',
     	'Name2' => '...code2...',
     });

     cmpthese($count, {
     	'Name1' => sub { ...code1... },
     	'Name2' => sub { ...code2... },
     });

     # ...or in two stages
     $results = timethese($count,
         {
     	    'Name1' => sub { ...code1... },
     	    'Name2' => sub { ...code2... },
         },
     	'none'
     );
     cmpthese( $results ) ;

     $t = timeit($count, '...other code...')
     print "$count loops of other code took:",timestr($t),"\n";

     $t = countit($time, '...other code...')
     $count = $t->iters ;
     print "$count loops of other code took:",timestr($t),"\n";

DESCRIPTION
===========

   The Benchmark module encapsulates a number of routines to help you
figure out how long it takes to execute some code.

   timethis - run a chunk of code several times

   timethese - run several chunks of code several times

   cmpthese - print results of timethese as a comparison chart

   timeit - run a chunk of code and see how long it goes

   countit - see how many times a chunk of code runs in a given time

Methods
-------

new
     Returns the current time.   Example:

          use Benchmark;
          $t0 = new Benchmark;
          # ... your code here ...
          $t1 = new Benchmark;
          $td = timediff($t1, $t0);
          print "the code took:",timestr($td),"\n";

debug
     Enables or disable debugging by setting the `$Benchmark::Debug' flag:

          debug Benchmark 1;
          $t = timeit(10, ' 5 ** $Global ');
          debug Benchmark 0;

iters
     Returns the number of iterations.

Standard Exports
----------------

   The following routines will be exported into your namespace if you use
the Benchmark module:

timeit(COUNT, CODE)
     Arguments: COUNT is the number of times to run the loop, and CODE is
     the code to run.  CODE may be either a code reference or a string to
     be eval'd; either way it will be run in the caller's package.

     Returns: a Benchmark object.

timethis ( COUNT, CODE, [ TITLE, [ STYLE ]] )
     Time COUNT iterations of CODE. CODE may be a string to eval or a code
     reference; either way the CODE will run in the caller's package.
     Results will be printed to STDOUT as TITLE followed by the times.
     TITLE defaults to "timethis COUNT" if none is provided. STYLE
     determines the format of the output, as described for timestr() below.

     The COUNT can be zero or negative: this means the *minimum number of
     CPU seconds* to run.  A zero signifies the default of 3 seconds.  For
     example to run at least for 10 seconds:

          timethis(-10, $code)

     or to run two pieces of code tests for at least 3 seconds:

          timethese(0, { test1 => '...', test2 => '...'})

     CPU seconds is, in UNIX terms, the user time plus the system time of
     the process itself, as opposed to the real (wallclock) time and the
     time spent by the child processes.  Less than 0.1 seconds is not
     accepted (-0.01 as the count, for example, will cause a fatal runtime
     exception).

     Note that the CPU seconds is the minimum time: CPU scheduling and
     other operating system factors may complicate the attempt so that a
     little bit more time is spent.  The benchmark output will, however,
     also tell the number of $code runs/second, which should be a more
     interesting number than the actually spent seconds.

     Returns a Benchmark object.

timethese ( COUNT, CODEHASHREF, [ STYLE ] )
     The CODEHASHREF is a reference to a hash containing names as keys and
     either a string to eval or a code reference for each value.  For each
     (KEY, VALUE) pair in the CODEHASHREF, this routine will call

          timethis(COUNT, VALUE, KEY, STYLE)

     The routines are called in string comparison order of KEY.

     The COUNT can be zero or negative, see timethis().

     Returns a hash of Benchmark objects, keyed by name.

timediff ( T1, T2 )
     Returns the difference between two Benchmark times as a Benchmark
     object suitable for passing to timestr().

timestr ( TIMEDIFF, [ STYLE, [ FORMAT ] ] )
     Returns a string that formats the times in the TIMEDIFF object in the
     requested STYLE. TIMEDIFF is expected to be a Benchmark object
     similar to that returned by timediff().

     STYLE can be any of 'all', 'none', 'noc', 'nop' or 'auto'. 'all' shows
     each of the 5 times available ('wallclock' time, user time, system
     time, user time of children, and system time of children). 'noc'
     shows all except the two children times. 'nop' shows only wallclock
     and the two children times. 'auto' (the default) will act as 'all'
     unless the children times are both zero, in which case it acts as
     'noc'.  'none' prevents output.

     FORMAT is the `printf(3)' in this node-style format specifier
     (without the leading '%') to use to print the times. It defaults to
     '5.2f'.

Optional Exports
----------------

   The following routines will be exported into your namespace if you
specifically ask that they be imported:

clearcache ( COUNT )
     Clear the cached time for COUNT rounds of the null loop.

clearallcache ( )
     Clear all cached times.

cmpthese ( COUT, CODEHASHREF, [ STYLE ] )
cmpthese ( RESULTSHASHREF )
     Optionally calls timethese(), then outputs comparison chart.  This
     chart is sorted from slowest to fastest, and shows the percent speed
     difference between each pair of tests.  Can also be passed the data
     structure that timethese() returns:

          $results = timethese( .... );
          cmpthese( $results );

     Returns the data structure returned by timethese() (or passed in).

countit(TIME, CODE)
     Arguments: TIME is the minimum length of time to run CODE for, and
     CODE is the code to run.  CODE may be either a code reference or a
     string to be eval'd; either way it will be run in the caller's
     package.

     TIME is not negative.  countit() will run the loop many times to
     calculate the speed of CODE before running it for TIME.  The actual
     time run for will usually be greater than TIME due to system clock
     resolution, so it's best to look at the number of iterations divided
     by the times that you are concerned with, not just the iterations.

     Returns: a Benchmark object.

disablecache ( )
     Disable caching of timings for the null loop. This will force
     Benchmark to recalculate these timings for each new piece of code
     timed.

enablecache ( )
     Enable caching of timings for the null loop. The time taken for COUNT
     rounds of the null loop will be calculated only once for each
     different COUNT used.

timesum ( T1, T2 )
     Returns the sum of two Benchmark times as a Benchmark object suitable
     for passing to timestr().

NOTES
=====

   The data is stored as a list of values from the time and times
functions:

     ($real, $user, $system, $children_user, $children_system, $iters)

   in seconds for the whole loop (not divided by the number of rounds).

   The timing is done using time(3) and times(3).

   Code is executed in the caller's package.

   The time of the null loop (a loop with the same number of rounds but
empty loop body) is subtracted from the time of the real loop.

   The null loop times can be cached, the key being the number of rounds.
The caching can be controlled using calls like these:

     clearcache($key);
     clearallcache();

     disablecache();
     enablecache();

   Caching is off by default, as it can (usually slightly) decrease
accuracy and does not usually noticably affect runtimes.

EXAMPLES
========

   For example,

     use Benchmark;$x=3;cmpthese(-5,{a=>sub{$x*$x},b=>sub{$x**2}})

   outputs something like this:

     Benchmark: running a, b, each for at least 5 CPU seconds...
     	    a: 10 wallclock secs ( 5.14 usr +  0.13 sys =  5.27 CPU) @ 3835055.60/s (n=20210743)
     	    b:  5 wallclock secs ( 5.41 usr +  0.00 sys =  5.41 CPU) @ 1574944.92/s (n=8520452)
     	  Rate    b    a
     b 1574945/s   -- -59%
     a 3835056/s 144%   --

   while

     use Benchmark;
     $x=3;
     $r=timethese(-5,{a=>sub{$x*$x},b=>sub{$x**2}},'none');
     cmpthese($r);

   outputs something like this:

     Rate    b    a
        b 1559428/s   -- -62%
        a 4152037/s 166%   --

INHERITANCE
===========

   Benchmark inherits from no other class, except of course for Exporter.

CAVEATS
=======

   Comparing eval'd strings with code references will give you inaccurate
results: a code reference will show a slightly slower execution time than
the equivalent eval'd string.

   The real time timing is done using time(2) and the granularity is
therefore only one second.

   Short tests may produce negative figures because perl can appear to
take longer to execute the empty loop than a short test; try:

     timethis(100,'1');

   The system time of the null loop might be slightly more than the system
time of the loop with the actual code and therefore the difference might
end up being < 0.

SEE ALSO
========

   See Devel/DProf, - a Perl code profiler

AUTHORS
=======

   Jarkko Hietaniemi <`jhi@iki.fi'>, Tim Bunce <`Tim.Bunce@ig.co.uk'>

MODIFICATION HISTORY
====================

   September 8th, 1994; by Tim Bunce.

   March 28th, 1997; by Hugo van der Sanden: added support for code
references and the already documented 'debug' method; revamped
documentation.

   April 04-07th, 1997: by Jarkko Hietaniemi, added the run-for-some-time
functionality.

   September, 1999; by Barrie Slaymaker: math fixes and accuracy and
efficiency tweaks.  Added cmpthese().  A result is now returned from
timethese().  Exposed countit() (was runfor()).

Perl extension for Berkeley DB version 2
****************************************

NAME
====

   BerkDB - Perl extension for Berkeley DB version 2

SYNOPSIS
========

     use BerkDB;

     $env = new BerkDB::Env [OPTIONS] ;

     $db  = tie %hash, 'BerkDB::Hash', [OPTIONS] ;
     $db  = new BerkDB::Hash [OPTIONS] ;

     $db  = tie %hash, 'BerkDB::Btree', [OPTIONS] ;
     $db  = new BerkDB::Btree [OPTIONS] ;

     $hash{$key} = $value ;
     $value = $hash{$key} ;
     each %hash ;
     keys %hash ;
     values %hash ;

     $status = $db->db_get()
     $status = $db->db_put() ;
     $status = $db->db_del() ;
     $status = $db->db_sync() ;
     $hash_ref = $db->db_stat() ;

     ($flag, $old_offset, $old_length) = $db->partial_set($offset, $length) ;
     ($flag, $old_offset, $old_length) = $db->partial_clear() ;

     $cursor = $db->db_cursor() ;
     $status = $cursor->c_get() ;
     $status = $cursor->c_put() ;
     $status = $cursor->c_del() ;

     $txn = $env->txn_begin() ;
     $status = $txn->txn_prepare()
     $status = $txn->txn_commit()
     $status = $txn->txn_abort()
     $status = $txn->txn_checkpoint()
     $status = $txn->txn_id()
     $status = $txn->txn_stat()

     $BerkDB::Error
     $BerkDB::db_version

DESCRIPTION
===========

   *NOTE: This document is still under construction, so it is likely to be
incomplete.*

   This Perl module provides an interface to most of the functionality
available in Berkeley DB version 2.

   The reader is expected to be familiar with the Berkeley DB
documentation. The db_appinit, db_cursor, db_open and db_txn man pages are
particularly relevant.

ENVIRONMENT CLASS
=================

   The equivalent of the Berkeley DB function `db_appinit'. It is only
needed when you want to make use of locking, logging or transactions.

Synopsis
--------

     $env = new BerkDB::Env [OPTIONS]
              [ -Home         => $path, ]
              [ -Config       => { name => value, name => value }, ]
              [ -ErrFile      => filename or filehandle, ]
              [ -ErrPrefix    => "string", ]
              [ -Flags        => number, ]
              [ -Verbose      => boolean, ]
              [ -LockMax      => number, ]
              [ -LogMax       => number, ]
              [ -TxnMax       => number, ]

   Where the OPTIONS consist of any of the following:

-Home
-Config
-ErrFile
-ErrPrefix
-Flags
     The Flags option can consist of one of more of the following or'ed
     together.

          DB_CREATE
          DB_INIT_LOCK
          DB_INIT_LOG
          DB_INIT_MPOOL
          DB_INIT_TXN
          DB_MPOOL_PRIVATE
          DB_NOMMAP
          DB_RECOVER
          DB_RECOVER_FATAL
          DB_THREAD
          DB_TXN_NOSYNC
          DB_USE_ENVIRON
          DB_USE_ENVIRON_ROOT

-Verbose
-LockMax
-LogMax
-TxnMax
Methods
-------

   The environment class has the following methods:

txn_begin
          $txn = $env->txn_begin() ;

errPrefix
          $db->errPrefix("string") ;

THE HASH CLASS
==============

   The equivalent of db_open with type DB_HASH. Two forms

     $db = new BerkDB::Hash
                 [ -Filename      => "filename" ]
                 [ -Flags         => ]
                 [ -Property      => ]
                 [ -Mode          => ]
                 [ -Cachesize     => ]
                 [ -Lorder        => ]
                 [ -Pagesize      => ]
                 [ -Env           => ]
                 [ -Txn           => ]
                 [ -Ffactor       => ]
                 [ -Nelem         => ]
                 [ -Hash          => ]

     and this

     $db = tie %hash, 'BerkDB::Hash', OPTIONS

   where OPTIONS are the same as for the new constructor. In addition to
the standard set of options (see `COMMON OPTIONS' in this node)
BerkDB::Hash supports these:

-Property
     Used to specify additional flags.

          DB_DUP

-Ffactor
-Nelem
-Hash
Methods
-------

   See `COMMON DATABASE METHODS' in this node.

A Simple Hash Example
---------------------

     use strict ;
     use BerkDB ;

     my %hash ;
     my $filename = "database" ;
     tie %hash, 'BerkDB::Hash',
                 -Filename  => $filename,
                 -Flags     => DB_CREATE,
         or die "Cannot open file $filename: $! $BerkDB::Error\n" ;

     $hash{"fred"} = "barney" ;
     $hash{"joe"} = "harry" ;

     untie %hash ;

THE BTREE CLASS
===============

Methods
-------

   See `COMMON DATABASE METHODS' in this node.

   Btree supports one extra method

     $ref = $db->db_stat() ;

THE RECNO CLASS
===============

   Not implemented yet.

COMMON OPTIONS
==============

   All database access class constructors support the common set of
parameters defined below.

-Filename
     The database filename. If no filename is specified, the database will
     be created in-memory, and removed once the program terminates.

-Flags
     Specify how the database will be opened/created. The valid flags are:

          DB_CREATE
          DB_NOMMAP
          DB_RDONLY
          DB_THREAD
          DB_TRUNCATE

     The default is none.

-Mode
     Determines the file protection when the database is created. Defaults
     to 0666.

-Cachesize
-Lorder
-Pagesize
-Env
     When working under a Berkeley DB environment, this parameter

     Defaults to no environment.

-Txn
COMMON DATABASE METHODS
=======================

   All the database interfaces support a common set of methods.

$status = $db->db_get($key, $value [, $flags])
----------------------------------------------

$status = $db->db_put($key, $value [, $flags])
----------------------------------------------

$status = $db->db_del($key [, $flags])
--------------------------------------

$status = $db->db_sync()
------------------------

$cursor = $db->db_cursor()
--------------------------

   Creates a cursor object. See `CURSORS' in this node for details of the
methods available when working with cursore.

$fd = $db->db_fd()
------------------

($flag, $old_offset, $old_length) = $db->partial_set($offset, $length) ;
------------------------------------------------------------------------

($flag, $old_offset, $old_length) = $db->partial_clear() ;
----------------------------------------------------------

   When the "tie" interface is used, reading from and writing to the
database is achieved via the tied hash.

CURSORS
=======

   A cursor is created with the `db_cursor'

$status = $cursor->c_get($key, $value [,$flags])
------------------------------------------------

$status = $cursor->c_put($key, $value [,$flags])
------------------------------------------------

$status = $cursor->c_del($key, [,$flags])
-----------------------------------------

TRANSACTIONS
============

EXAMPLES
========

   todo.

HISTORY   See the Changes file.
===============================

AVAILABILITY   The most recent version of *BerkDB* can always be found on CPAN (see `CPAN', see Perlmod (perl.info), for details), in the directory `modules/by-module/BerkDB'.
=========================================================================================================================================================================================

   The official web site for Berkeley DB is `http://www.sleepycat.com/db'.
The ftp equivalent is `ftp.sleepycat.com:/pub'.

COPYRIGHT
=========

   Copyright (c) 1997 Paul Marquess. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

   Although *BerkDB* is covered by the Perl license, the library it makes
use of, namely Berkeley DB version 2, is not. Berkeley DB has its own
copyright and its own license. Please take the time to read it.

   The license for Berkeley DB version 2, and how it relates to BerkDB
does need some extra clarification. Here are are few words taken from the
Berkeley DB FAQ regarding the version 2 license:

   The major difference is that the license for DB 2.0, when
downloaded from the net, requires that the software that     uses DB 2.0
be freely redistributable.

   That means that if you want to use BerkDB, and you have changed either
the source for Berkeley DB or Perl, then the changes must be freely
available.

   In the case of Perl, the term source refers to the complete source code
for Perl (e.g. sv.c, toke.c, perl.h) and any external modules that you are
using (e.g. BerkDB, Tk).

   Note that any Perl scripts that you write are your property - this
includes scripts that make use of BerkDB. Neither the Perl license or the
Berkeley DB license place any restriction on what you have to do with them.

   If you are in any doubt about the license situation, contact either the
Berkeley DB authors or the author of BerkDB. See `"AUTHOR"' in this node
for details.

AUTHOR
======

   Paul Marquess <pmarquess@bfsec.bt.co.uk<gt>.

   Questions about Berkeley DB may be addressed to <db@sleepycat.com<gt>.

SEE ALSO
========

   perl(1), DB_File, Berkeley DB.

Perl extension for Berkeley DB version 2 or 3
*********************************************

NAME
====

   BerkeleyDB - Perl extension for Berkeley DB version 2 or 3

SYNOPSIS
========

     use BerkeleyDB;

     $env = new BerkeleyDB::Env [OPTIONS] ;

     $db  = tie %hash, 'BerkeleyDB::Hash', [OPTIONS] ;
     $db  = new BerkeleyDB::Hash [OPTIONS] ;

     $db  = tie %hash, 'BerkeleyDB::Btree', [OPTIONS] ;
     $db  = new BerkeleyDB::Btree [OPTIONS] ;

     $db  = tie %hash, 'BerkeleyDB::Recno', [OPTIONS] ;
     $db  = new BerkeleyDB::Recno [OPTIONS] ;

     $db  = tie %hash, 'BerkeleyDB::Queue', [OPTIONS] ;
     $db  = new BerkeleyDB::Queue [OPTIONS] ;

     $db  = new BerkeleyDB::Unknown [OPTIONS] ;

     $status = BerkeleyDB::db_remove [OPTIONS]

     $hash{$key} = $value ;
     $value = $hash{$key} ;
     each %hash ;
     keys %hash ;
     values %hash ;

     $status = $db->db_get()
     $status = $db->db_put() ;
     $status = $db->db_del() ;
     $status = $db->db_sync() ;
     $status = $db->db_close() ;
     $hash_ref = $db->db_stat() ;
     $status = $db->db_key_range();
     $type = $db->type() ;
     $status = $db->status() ;
     $boolean = $db->byteswapped() ;

     ($flag, $old_offset, $old_length) = $db->partial_set($offset, $length) ;
     ($flag, $old_offset, $old_length) = $db->partial_clear() ;

     $cursor = $db->db_cursor([$flags]) ;
     $newcursor = $cursor->c_dup([$flags]);
     $status = $cursor->c_get() ;
     $status = $cursor->c_put() ;
     $status = $cursor->c_del() ;
     $status = $cursor->c_count() ;
     $status = $cursor->status() ;
     $status = $cursor->c_close() ;

     $cursor = $db->db_join() ;
     $status = $cursor->c_get() ;
     $status = $cursor->c_close() ;

     $status = $env->txn_checkpoint()
     $hash_ref = $env->txn_stat()
     $status = $env->setmutexlocks()

     $txn = $env->txn_begin() ;
     $status = $txn->txn_prepare()
     $status = $txn->txn_commit()
     $status = $txn->txn_abort()
     $status = $txn->txn_id()

     $BerkeleyDB::Error
     $BerkeleyDB::db_version

     # DBM Filters
     $old_filter = $db->filter_store_key  ( sub { ... } ) ;
     $old_filter = $db->filter_store_value( sub { ... } ) ;
     $old_filter = $db->filter_fetch_key  ( sub { ... } ) ;
     $old_filter = $db->filter_fetch_value( sub { ... } ) ;

     # deprecated, but supported
     $txn_mgr = $env->TxnMgr();
     $status = $txn_mgr->txn_checkpoint()
     $hash_ref = $txn_mgr->txn_stat()
     $txn = $txn_mgr->txn_begin() ;

DESCRIPTION
===========

   *NOTE: This document is still under construction. Expect it to be
incomplete in places.*

   This Perl module provides an interface to most of the functionality
available in Berkeley DB versions 2 and 3. In general it is safe to assume
that the interface provided here to be identical to the Berkeley DB
interface. The main changes have been to make the Berkeley DB API work in
a Perl way. Note that if you are using Berkeley DB 2.x, the new features
available in Berkeley DB 3.x are not available via this module.

   The reader is expected to be familiar with the Berkeley DB
documentation. Where the interface provided here is identical to the
Berkeley DB library and the... TODO

   The *db_appinit*, *db_cursor*, *db_open* and *db_txn* man pages are
particularly relevant.

   The interface to Berkeley DB is implemented with a number of Perl
classes.

ENV CLASS
=========

   The *BerkeleyDB::Env* class provides an interface to the Berkeley DB
function *db_appinit* in Berkeley DB 2.x or *db_env_create* and
*DBENV->open* in Berkeley DB 3.x. Its purpose is to initialise a number of
sub-systems that can then be used in a consistent way in all the databases
you make use of the environment.

   If you don't intend using transactions, locking or logging, then you
shouldn't need to make use of *BerkeleyDB::Env*.

Synopsis
--------

     $env = new BerkeleyDB::Env
              [ -Home         => $path, ]
              [ -Server       => $name, ]
              [ -CacheSize    => $number, ]
              [ -Config       => { name => value, name => value }, ]
              [ -ErrFile      => filename or filehandle, ]
              [ -ErrPrefix    => "string", ]
              [ -Flags        => number, ]
              [ -LockDetect   => number, ]
              [ -Verbose      => boolean, ]

   All the parameters to the BerkeleyDB::Env constructor are optional.

-Home
     If present, this parameter should point to an existing directory. Any
     files that *aren't* specified with an absolute path in the sub-systems
     that are initialised by the BerkeleyDB::Env class will be assumed to
     live in the *Home* directory.

     For example, in the code fragment below the database "fred.db" will be
     opened in the directory "/home/databases" because it was specified as
     a relative path, but "joe.db" will be opened in "/other" because it
     was part of an absolute path.

          $env = new BerkeleyDB::Env
                   -Home         => "/home/databases"
          ...

          $db1 = new BerkeleyDB::Hash
          	     -Filename = "fred.db",
          	     -Env => $env
          ...

          $db2 = new BerkeleyDB::Hash
          	     -Filename = "/other/joe.db",
          	     -Env => $env
          ...

-Server
     If present, this parameter should be the hostname of a server that is
     running the Berkeley DB RPC server. All databases will be accessed
     via the RPC server.

-Cachesize
     If present, this parameter sets the size of the environments shared
     memory buffer pool.

-Config
     This is a variation on the `-Home' parameter, but it allows finer
     control of where specific types of files will be stored.

     The parameter expects a reference to a hash. Valid keys are:
     *DB_DATA_DIR*, *DB_LOG_DIR* and *DB_TMP_DIR*

     The code below shows an example of how it can be used.

          $env = new BerkeleyDB::Env
                   -Config => { DB_DATA_DIR => "/home/databases",
                                DB_LOG_DIR  => "/home/logs",
                                DB_TMP_DIR  => "/home/tmp"
                              }
          ...

-ErrFile
     Expects either the name of a file or a reference to a filehandle. Any
     errors generated internally by Berkeley DB will be logged to this
     file.

-ErrPrefix
     Allows a prefix to be added to the error messages before they are sent
     to *-ErrFile*.

-Flags
     The Flags parameter specifies both which sub-systems to initialise,
     as well as a number of environment-wide options.  See the Berkeley DB
     documentation for more details of these options.

     Any of the following can be specified by OR'ing them:

     *DB_CREATE*

     If any of the files specified do not already exist, create them.

     *DB_INIT_CDB*

     Initialise the Concurrent Access Methods

     *DB_INIT_LOCK*

     Initialise the Locking sub-system.

     *DB_INIT_LOG*

     Initialise the Logging sub-system.

     *DB_INIT_MPOOL*

     Initialise the ...

     *DB_INIT_TXN*

     Initialise the ...

     *DB_MPOOL_PRIVATE*

     Initialise the ...

     *DB_INIT_MPOOL* is also specified.

     Initialise the ...

     *DB_NOMMAP*

     Initialise the ...

     *DB_RECOVER*

     *DB_RECOVER_FATAL*

     *DB_THREAD*

     *DB_TXN_NOSYNC*

     *DB_USE_ENVIRON*

     *DB_USE_ENVIRON_ROOT*

-LockDetect
     Specifies what to do when a lock conflict occurs. The value should be
     one of

     *DB_LOCK_DEFAULT*

     *DB_LOCK_OLDEST*

     *DB_LOCK_RANDOM*

     *DB_LOCK_YOUNGEST*

-Verbose
     Add extra debugging information to the messages sent to *-ErrFile*.

Methods
-------

   The environment class has the following methods:

$env->errPrefix("string") ;
     This method is identical to the *-ErrPrefix* flag. It allows the
     error prefix string to be changed dynamically.

$txn = $env->TxnMgr()
     Constructor for creating a *TxnMgr* object.  See `"TRANSACTIONS"' in
     this node for more details of using transactions.

     This method is deprecated. Access the transaction methods using the
     *txn_* methods below from the environment object directly.

$env->txn_begin()
     TODO

$env->txn_stat()
     TODO

$env->txn_checkpoint()
     TODO

$env->status()
     Returns the status of the last BerkeleyDB::Env method.

$env->setmutexlocks()
     Only available in Berkeley Db 3.0 or greater. Calls
     *db_env_set_mutexlocks* when used with Berkeley DB 3.1.x. When used
     with Berkeley DB 3.0 or 3.2 and better it calls
     *DBENV->set_mutexlocks*.

Examples
--------

   TODO.

THE DATABASE CLASSES
====================

   *BerkeleyDB* supports the following database formats:

BerkeleyDB::Hash
     This database type allows arbitrary key/value pairs to be stored in
     data files. This is equivalent to the functionality provided by other
     hashing packages like DBM, NDBM, ODBM, GDBM, and SDBM. Remember
     though, the files created using BerkeleyDB::Hash are not compatible
     with any of the other packages mentioned.

     A default hashing algorithm, which will be adequate for most
     applications, is built into BerkeleyDB. If you do need to use your
     own hashing algorithm it is possible to write your own in Perl and
     have *BerkeleyDB* use it instead.

BerkeleyDB::Btree
     The Btree format allows arbitrary key/value pairs to be stored in a
     B+tree.

     As with the BerkeleyDB::Hash format, it is possible to provide a user
     defined Perl routine to perform the comparison of keys. By default,
     though, the keys are stored in lexical order.

BerkeleyDB::Recno
     TODO.

BerkeleyDB::Queue
     TODO.

BerkeleyDB::Unknown
     This isn't a database format at all. It is used when you want to open
     an existing Berkeley DB database without having to know what type is
     it.

   Each of the database formats described above is accessed via a
corresponding *BerkeleyDB* class. These will be described in turn in the
next sections.

BerkeleyDB::Hash
================

   Equivalent to calling *db_open* with type DB_HASH in Berkeley DB 2.x and
calling *db_create* followed by *DB->open* with type DB_HASH in Berkeley
DB 3.x.

   Two forms of constructor are supported:

     $db = new BerkeleyDB::Hash
                 [ -Filename      => "filename", ]
                 [ -Subname       => "sub-database name", ]
                 [ -Flags         => flags,]
                 [ -Property      => flags,]
                 [ -Mode          => number,]
                 [ -Cachesize     => number,]
                 [ -Lorder        => number,]
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
                 # BerkeleyDB::Hash specific
                 [ -Ffactor       => number,]
                 [ -Nelem         => number,]
                 [ -Hash          => code reference,]
                 [ -DupCompare    => code reference,]

   and this

     [$db =] tie %hash, 'BerkeleyDB::Hash',
                 [ -Filename      => "filename", ]
                 [ -Subname       => "sub-database name", ]
                 [ -Flags         => flags,]
                 [ -Property      => flags,]
                 [ -Mode          => number,]
                 [ -Cachesize     => number,]
                 [ -Lorder        => number,]
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
                 # BerkeleyDB::Hash specific
                 [ -Ffactor       => number,]
                 [ -Nelem         => number,]
                 [ -Hash          => code reference,]
                 [ -DupCompare    => code reference,]

   When the "tie" interface is used, reading from and writing to the
database is achieved via the tied hash. In this case the database operates
like a Perl associative array that happens to be stored on disk.

   In addition to the high-level tied hash interface, it is possible to
make use of the underlying methods provided by Berkeley DB

Options
-------

   In addition to the standard set of options (see `COMMON OPTIONS' in
this node) BerkeleyDB::Hash supports these options:

-Property
     Used to specify extra flags when opening a database. The following
     flags may be specified by logically OR'ing together one or more of the
     following values:

     *DB_DUP*

     When creating a new database, this flag enables the storing of
     duplicate keys in the database. If *DB_DUPSORT* is not specified as
     well, the duplicates are stored in the order they are created in the
     database.

     *DB_DUPSORT*

     Enables the sorting of duplicate keys in the database. Ignored if
     *DB_DUP* isn't also specified.

-Ffactor
-Nelem
     See the Berkeley DB documentation for details of these options.

-Hash
     Allows you to provide a user defined hash function. If not specified,
     a default hash function is used. Here is a template for a user-defined
     hash function

          sub hash
          {
              my ($data) = shift ;
              ...
              # return the hash value for $data
          	return $hash ;
          }

          tie %h, "BerkeleyDB::Hash",
              -Filename => $filename,
          	-Hash     => \&hash,
          	...

     See `""' in this node for an example.

-DupCompare
     Used in conjunction with the *DB_DUPOSRT* flag.

          sub compare
          {
          	my ($key, $key2) = @_ ;
              ...
              # return  0 if $key1 eq $key2
              #        -1 if $key1 lt $key2
              #         1 if $key1 gt $key2
              return (-1 , 0 or 1) ;
          }

          tie %h, "BerkeleyDB::Hash",
              -Filename   => $filename,
          	-Property   => DB_DUP|DB_DUPSORT,
          	-DupCompare => \&compare,
          	...

Methods
-------

   BerkeleyDB::Hash only supports the standard database methods.  See
`COMMON DATABASE METHODS' in this node.

A Simple Tied Hash Example
--------------------------

     use strict ;
     use BerkeleyDB ;
     use vars qw( %h $k $v ) ;

     my $filename = "fruit" ;
     unlink $filename ;
     tie %h, "BerkeleyDB::Hash",
                 -Filename => $filename,
     		-Flags    => DB_CREATE
         or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;

     # Add a few key/value pairs to the file
     $h{"apple"} = "red" ;
     $h{"orange"} = "orange" ;
     $h{"banana"} = "yellow" ;
     $h{"tomato"} = "red" ;

     # Check for existence of a key
     print "Banana Exists\n\n" if $h{"banana"} ;

     # Delete a key/value pair.
     delete $h{"apple"} ;

     # print the contents of the file
     while (($k, $v) = each %h)
       { print "$k -> $v\n" }

     untie %h ;

   here is the output:

     Banana Exists

     orange -> orange
     tomato -> red
     banana -> yellow

   Note that the like ordinary associative arrays, the order of the keys
retrieved from a Hash database are in an apparently random order.

Another Simple Hash Example
---------------------------

   Do the same as the previous example but not using tie.

     use strict ;
     use BerkeleyDB ;

     my $filename = "fruit" ;
     unlink $filename ;
     my $db = new BerkeleyDB::Hash
                 -Filename => $filename,
     		-Flags    => DB_CREATE
         or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;

     # Add a few key/value pairs to the file
     $db->db_put("apple", "red") ;
     $db->db_put("orange", "orange") ;
     $db->db_put("banana", "yellow") ;
     $db->db_put("tomato", "red") ;

     # Check for existence of a key
     print "Banana Exists\n\n" if $db->db_get("banana", $v) == 0;

     # Delete a key/value pair.
     $db->db_del("apple") ;

     # print the contents of the file
     my ($k, $v) = ("", "") ;
     my $cursor = $db->db_cursor() ;
     while ($cursor->c_get($k, $v, DB_NEXT) == 0)
       { print "$k -> $v\n" }

     undef $cursor ;
     undef $db ;

Duplicate keys
--------------

   The code below is a variation on the examples above. This time the hash
has been inverted. The key this time is colour and the value is the fruit
name.  The *DB_DUP* flag has been specified to allow duplicates.

     use strict ;
     use BerkeleyDB ;

     my $filename = "fruit" ;
     unlink $filename ;
     my $db = new BerkeleyDB::Hash
                 -Filename => $filename,
     		-Flags    => DB_CREATE,
     		-Property  => DB_DUP
         or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;

     # Add a few key/value pairs to the file
     $db->db_put("red", "apple") ;
     $db->db_put("orange", "orange") ;
     $db->db_put("green", "banana") ;
     $db->db_put("yellow", "banana") ;
     $db->db_put("red", "tomato") ;
     $db->db_put("green", "apple") ;

     # print the contents of the file
     my ($k, $v) = ("", "") ;
     my $cursor = $db->db_cursor() ;
     while ($cursor->c_get($k, $v, DB_NEXT) == 0)
       { print "$k -> $v\n" }

     undef $cursor ;
     undef $db ;

   here is the output:

     orange -> orange
     yellow -> banana
     red -> apple
     red -> tomato
     green -> banana
     green -> apple

Sorting Duplicate Keys
----------------------

   In the previous example, when there were duplicate keys, the values are
sorted in the order they are stored in. The code below is identical to the
previous example except the *DB_DUPSORT* flag is specified.

     use strict ;
     use BerkeleyDB ;

     my $filename = "fruit" ;
     unlink $filename ;
     my $db = new BerkeleyDB::Hash
                 -Filename => $filename,
     		-Flags    => DB_CREATE,
     		-Property  => DB_DUP | DB_DUPSORT
         or die "Cannot open file $filename: $! $BerkeleyDB::Error\n" ;

     # Add a few key/value pairs to the file
     $db->db_put("red", "apple") ;
     $db->db_put("orange", "orange") ;
     $db->db_put("green", "banana") ;
     $db->db_put("yellow", "banana") ;
     $db->db_put("red", "tomato") ;
     $db->db_put("green", "apple") ;

     # print the contents of the file
     my ($k, $v) = ("", "") ;
     my $cursor = $db->db_cursor() ;
     while ($cursor->c_get($k, $v, DB_NEXT) == 0)
       { print "$k -> $v\n" }

     undef $cursor ;
     undef $db ;

   Notice that in the output below the duplicate values are sorted.

     orange -> orange
     yellow -> banana
     red -> apple
     red -> tomato
     green -> apple
     green -> banana

Custom Sorting Duplicate Keys
-----------------------------

   Another variation

   TODO

Changing the hash
-----------------

   TODO

Using db_stat
-------------

   TODO

BerkeleyDB::Btree
=================

   Equivalent to calling *db_open* with type DB_BTREE in Berkeley DB 2.x
and calling *db_create* followed by *DB->open* with type DB_BTREE in
Berkeley DB 3.x.

   Two forms of constructor are supported:

     $db = new BerkeleyDB::Btree
                 [ -Filename      => "filename", ]
                 [ -Subname       => "sub-database name", ]
                 [ -Flags         => flags,]
                 [ -Property      => flags,]
                 [ -Mode          => number,]
                 [ -Cachesize     => number,]
                 [ -Lorder        => number,]
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
                 # BerkeleyDB::Btree specific
                 [ -Minkey        => number,]
                 [ -Compare       => code reference,]
                 [ -DupCompare    => code reference,]
                 [ -Prefix        => code reference,]

   and this

     [$db =] tie %hash, 'BerkeleyDB::Btree',
                 [ -Filename      => "filename", ]
                 [ -Subname       => "sub-database name", ]
                 [ -Flags         => flags,]
                 [ -Property      => flags,]
                 [ -Mode          => number,]
                 [ -Cachesize     => number,]
                 [ -Lorder        => number,]
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
                 # BerkeleyDB::Btree specific
                 [ -Minkey        => number,]
                 [ -Compare       => code reference,]
                 [ -DupCompare    => code reference,]
                 [ -Prefix        => code reference,]

Options
-------

   In addition to the standard set of options (see `COMMON OPTIONS' in
this node) BerkeleyDB::Btree supports these options:

-Property
     Used to specify extra flags when opening a database. The following
     flags may be specified by logically OR'ing together one or more of the
     following values:

     *DB_DUP*

     When creating a new database, this flag enables the storing of
     duplicate keys in the database. If *DB_DUPSORT* is not specified as
     well, the duplicates are stored in the order they are created in the
     database.

     *DB_DUPSORT*

     Enables the sorting of duplicate keys in the database. Ignored if
     *DB_DUP* isn't also specified.

Minkey
     TODO

Compare
     Allow you to override the default sort order used in the database. See
     `"Changing the sort order"' in this node for an example.

          sub compare
          {
          	my ($key, $key2) = @_ ;
              ...
              # return  0 if $key1 eq $key2
              #        -1 if $key1 lt $key2
              #         1 if $key1 gt $key2
              return (-1 , 0 or 1) ;
          }

          tie %h, "BerkeleyDB::Hash",
              -Filename   => $filename,
          	-Compare    => \&compare,
          	...

Prefix
          sub prefix
          {
          	my ($key, $key2) = @_ ;
              ...
              # return number of bytes of $key2 which are
              # necessary to determine that it is greater than $key1
              return $bytes ;
          }

          tie %h, "BerkeleyDB::Hash",
              -Filename   => $filename,
          	-Prefix     => \&prefix,
          	...
          =item DupCompare

          sub compare
          {
          	my ($key, $key2) = @_ ;
              ...
              # return  0 if $key1 eq $key2
              #        -1 if $key1 lt $key2
              #         1 if $key1 gt $key2
              return (-1 , 0 or 1) ;
          }

          tie %h, "BerkeleyDB::Hash",
              -Filename   => $filename,
          	-DupCompare => \&compare,
          	...

Methods
-------

   BerkeleyDB::Btree supports the following database methods.  See also
`COMMON DATABASE METHODS' in this node.

   All the methods below return 0 to indicate success.

$status = $db->db_key_range($key, $less, $equal, $greater [, $flags])
     Given a key, $key, this method returns the proportion of keys less
     than $key in `$less', the proportion equal to $key in `$equal' and the
     proportion greater than $key in `$greater'.

     The proportion is returned as a double in the range 0.0 to 1.0.

A Simple Btree Example
----------------------

   The code below is a simple example of using a btree database.

     use strict ;
     use BerkeleyDB ;

     my $filename = "tree" ;
     unlink $filename ;
     my %h ;
     tie %h, 'BerkeleyDB::Btree',
     		-Filename   => $filename,
     	        -Flags      => DB_CREATE
       or die "Cannot open $filename: $!\n" ;

     # Add a key/value pair to the file
     $h{'Wall'} = 'Larry' ;
     $h{'Smith'} = 'John' ;
     $h{'mouse'} = 'mickey' ;
     $h{'duck'}  = 'donald' ;

     # Delete
     delete $h{"duck"} ;

     # Cycle through the keys printing them in order.
     # Note it is not necessary to sort the keys as
     # the btree will have kept them in order automatically.
     foreach (keys %h)
       { print "$_\n" }

     untie %h ;

   Here is the output from the code above. The keys have been sorted using
Berkeley DB's default sorting algorithm.

     Smith
     Wall
     mouse

Changing the sort order
-----------------------

   It is possible to supply your own sorting algorithm if the one that
Berkeley DB used isn't suitable. The code below is identical to the
previous example except for the case insensitive compare function.

     use strict ;
     use BerkeleyDB ;

     my $filename = "tree" ;
     unlink $filename ;
     my %h ;
     tie %h, 'BerkeleyDB::Btree',
     		-Filename   => $filename,
     	        -Flags      => DB_CREATE,
     		-Compare    => sub { lc $_[0] cmp lc $_[1] }
       or die "Cannot open $filename: $!\n" ;

     # Add a key/value pair to the file
     $h{'Wall'} = 'Larry' ;
     $h{'Smith'} = 'John' ;
     $h{'mouse'} = 'mickey' ;
     $h{'duck'}  = 'donald' ;

     # Delete
     delete $h{"duck"} ;

     # Cycle through the keys printing them in order.
     # Note it is not necessary to sort the keys as
     # the btree will have kept them in order automatically.
     foreach (keys %h)
       { print "$_\n" }

     untie %h ;

   Here is the output from the code above.

     mouse
     Smith
     Wall

   There are a few point to bear in mind if you want to change the
ordering in a BTREE database:

  1. The new compare function must be specified when you create the
     database.

  2. You cannot change the ordering once the database has been created.
     Thus you must use the same compare function every time you access the
     database.

Using db_stat
-------------

   TODO

BerkeleyDB::Recno
=================

   Equivalent to calling *db_open* with type DB_RECNO in Berkeley DB 2.x
and calling *db_create* followed by *DB->open* with type DB_RECNO in
Berkeley DB 3.x.

   Two forms of constructor are supported:

     $db = new BerkeleyDB::Recno
                 [ -Filename      => "filename", ]
                 [ -Subname       => "sub-database name", ]
                 [ -Flags         => flags,]
                 [ -Property      => flags,]
                 [ -Mode          => number,]
                 [ -Cachesize     => number,]
                 [ -Lorder        => number,]
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
                 # BerkeleyDB::Recno specific
                 [ -Delim           => byte,]
                 [ -Len             => number,]
                 [ -Pad             => byte,]
                 [ -Source          => filename,]

   and this

     [$db =] tie @arry, 'BerkeleyDB::Recno',
                 [ -Filename      => "filename", ]
                 [ -Subname       => "sub-database name", ]
                 [ -Flags         => flags,]
                 [ -Property      => flags,]
                 [ -Mode          => number,]
                 [ -Cachesize     => number,]
                 [ -Lorder        => number,]
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
                 # BerkeleyDB::Recno specific
                 [ -Delim           => byte,]
                 [ -Len             => number,]
                 [ -Pad             => byte,]
                 [ -Source          => filename,]

A Recno Example
---------------

   Here is a simple example that uses RECNO (if you are using a version of
Perl earlier than 5.004_57 this example won't work - see `Extra RECNO
Methods' in this node for a workaround).

     use strict ;
     use BerkeleyDB ;

     my $filename = "text" ;
     unlink $filename ;

     my @h ;
     tie @h, 'BerkeleyDB::Recno',
     		-Filename   => $filename,
     	        -Flags      => DB_CREATE,
     		-Property   => DB_RENUMBER
       or die "Cannot open $filename: $!\n" ;

     # Add a few key/value pairs to the file
     $h[0] = "orange" ;
     $h[1] = "blue" ;
     $h[2] = "yellow" ;

     push @h, "green", "black" ;

     my $elements = scalar @h ;
     print "The array contains $elements entries\n" ;

     my $last = pop @h ;
     print "popped $last\n" ;

     unshift @h, "white" ;
     my $first = shift @h ;
     print "shifted $first\n" ;

     # Check for existence of a key
     print "Element 1 Exists with value $h[1]\n" if $h[1] ;

     untie @h ;

   Here is the output from the script:

     The array contains 5 entries
     popped black
     shifted white
     Element 1 Exists with value blue
     The last element is green
     The 2nd last element is yellow

BerkeleyDB::Queue
=================

   Equivalent to calling *db_create* followed by *DB->open* with type
*DB_QUEUE* in Berkeley DB 3.x. This database format isn't available if you
use Berkeley DB 2.x.

   Two forms of constructor are supported:

     $db = new BerkeleyDB::Queue
                 [ -Filename      => "filename", ]
                 [ -Subname       => "sub-database name", ]
                 [ -Flags         => flags,]
                 [ -Property      => flags,]
                 [ -Mode          => number,]
                 [ -Cachesize     => number,]
                 [ -Lorder        => number,]
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
                 # BerkeleyDB::Queue specific
                 [ -Len             => number,]
                 [ -Pad             => byte,]
                 [ -ExtentSize    => number, ]

   and this

     [$db =] tie @arry, 'BerkeleyDB::Queue',
                 [ -Filename      => "filename", ]
                 [ -Subname       => "sub-database name", ]
                 [ -Flags         => flags,]
                 [ -Property      => flags,]
                 [ -Mode          => number,]
                 [ -Cachesize     => number,]
                 [ -Lorder        => number,]
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]
                 # BerkeleyDB::Queue specific
                 [ -Len             => number,]
                 [ -Pad             => byte,]

BerkeleyDB::Unknown
===================

   This class is used to open an existing database.

   Equivalent to calling *db_open* with type *DB_UNKNOWN* in Berkeley DB
2.x and calling *db_create* followed by *DB->open* with type *DB_UNKNOWN*
in Berkeley DB 3.x.

   The constructor looks like this:

     $db = new BerkeleyDB::Unknown
                 [ -Filename      => "filename", ]
                 [ -Subname       => "sub-database name", ]
                 [ -Flags         => flags,]
                 [ -Property      => flags,]
                 [ -Mode          => number,]
                 [ -Cachesize     => number,]
                 [ -Lorder        => number,]
                 [ -Pagesize      => number,]
                 [ -Env           => $env,]
                 [ -Txn           => $txn,]

An example
----------

COMMON OPTIONS
==============

   All database access class constructors support the common set of
options defined below. All are optional.

-Filename
     The database filename. If no filename is specified, a temporary file
     will be created and removed once the program terminates.

-Subname
     Specifies the name of the sub-database to open.  This option is only
     valid if you are using Berkeley DB 3.x.

-Flags
     Specify how the database will be opened/created. The valid flags are:

     *DB_CREATE*

     Create any underlying files, as necessary. If the files do not already
     exist and the *DB_CREATE* flag is not specified, the call will fail.

     *DB_NOMMAP*

     Not supported by BerkeleyDB.

     *DB_RDONLY*

     Opens the database in read-only mode.

     *DB_THREAD*

     Not supported by BerkeleyDB.

     *DB_TRUNCATE*

     If the database file already exists, remove all the data before
     opening it.

-Mode
     Determines the file protection when the database is created. Defaults
     to 0666.

-Cachesize
-Lorder
-Pagesize
-Env
     When working under a Berkeley DB environment, this parameter

     Defaults to no environment.

-Txn
     TODO.

COMMON DATABASE METHODS
=======================

   All the database interfaces support the common set of methods defined
below.

   All the methods below return 0 to indicate success.

$status = $db->db_get($key, $value [, $flags])
----------------------------------------------

   Given a key ($key) this method reads the value associated with it from
the database. If it exists, the value read from the database is returned
in the $value parameter.

   The $flags parameter is optional. If present, it must be set to one of
the following values:

DB_GET_BOTH
     When the DB_GET_BOTH flag is specified, *db_get* checks for the
     existence of both the $key and $value in the database.

DB_SET_RECNO
     TODO.

   In addition, the following value may be set by logically OR'ing it into
the $flags parameter:

DB_RMW
     TODO

$status = $db->db_put($key, $value [, $flags])
----------------------------------------------

   Stores a key/value pair in the database.

   The $flags parameter is optional. If present it must be set to one of
the following values:

DB_APPEND
     This flag is only applicable when accessing a BerkeleyDB::Recno
     database.

     TODO.

DB_NOOVERWRITE
     If this flag is specified and $key already exists in the database,
     the call to *db_put* will return *DB_KEYEXIST*.

$status = $db->db_del($key [, $flags])
--------------------------------------

   Deletes a key/value pair in the database associated with $key.  If
duplicate keys are enabled in the database, *db_del* will delete all
key/value pairs with key $key.

   The $flags parameter is optional and is currently unused.

$status = $db->db_sync()
------------------------

   If any parts of the database are in memory, write them to the database.

$cursor = $db->db_cursor([$flags])
----------------------------------

   Creates a cursor object. This is used to access the contents of the
database sequentially. See `CURSORS' in this node for details of the
methods available when working with cursors.

   The $flags parameter is optional. If present it must be set to one of
the following values:

DB_RMW
     TODO.

($flag, $old_offset, $old_length) = $db->partial_set($offset, $length) ;
------------------------------------------------------------------------

   TODO

($flag, $old_offset, $old_length) = $db->partial_clear() ;
----------------------------------------------------------

   TODO

$db->byteswapped()
------------------

   TODO

$db->type()
-----------

   Returns the type of the database. The possible return code are DB_HASH
for a BerkeleyDB::Hash database, DB_BTREE for a BerkeleyDB::Btree database
and DB_RECNO for a BerkeleyDB::Recno database. This method is typically
used when a database has been opened with BerkeleyDB::Unknown.

$ref = $db->db_stat()
     Returns a reference to an associative array containing information
     about the database. The keys of the associative array correspond
     directly to the names of the fields defined in the Berkeley DB
     documentation. For example, in the DB documentation, the field
     *bt_version* stores the version of the Btree database. Assuming you
     called *db_stat* on a Btree database the equivalent field would be
     accessed as follows:

          $version = $ref->{'bt_version'} ;

     If you are using Berkeley DB 3.x, this method will work will all
     database formats. When DB 2.x is used, it only works with
     BerkeleyDB::Btree.

$status = $db->status()
-----------------------

   Returns the status of the last $db method called.

CURSORS
=======

   A cursor is used whenever you want to access the contents of a database
in sequential order.  A cursor object is created with the `db_cursor'

   A cursor object has the following methods available:

$newcursor = $cursor->c_dup($flags)
-----------------------------------

   Creates a duplicate of `$cursor'. This method needs Berkeley DB 3.0.x
or better.

   The $flags parameter is optional and can take the following value:

DB_POSITION
     When present this flag will position the new cursor at the same place
     as the existing cursor.

$status = $cursor->c_get($key, $value, $flags)
----------------------------------------------

   Reads a key/value pair from the database, returning the data in $key
and $value. The key/value pair actually read is controlled by the $flags
parameter, which can take one of the following values:

DB_FIRST
     Set the cursor to point to the first key/value pair in the database.
     Return the key/value pair in $key and $value.

DB_LAST
     Set the cursor to point to the last key/value pair in the database.
     Return the key/value pair in $key and $value.

DB_NEXT
     If the cursor is already pointing to a key/value pair, it will be
     incremented to point to the next key/value pair and return its
     contents.

     If the cursor isn't initialised, DB_NEXT works just like DB_FIRST.

     If the cursor is already positioned at the last key/value pair,
     *c_get* will return *DB_NOTFOUND*.

DB_NEXT_DUP
     This flag is only valid when duplicate keys have been enabled in a
     database.  If the cursor is already pointing to a key/value pair and
     the key of the next key/value pair is identical, the cursor will be
     incremented to point to it and their contents returned.

DB_PREV
     If the cursor is already pointing to a key/value pair, it will be
     decremented to point to the previous key/value pair and return its
     contents.

     If the cursor isn't initialised, DB_PREV works just like DB_LAST.

     If the cursor is already positioned at the first key/value pair,
     *c_get* will return *DB_NOTFOUND*.

DB_CURRENT
     If the cursor has been set to point to a key/value pair, return their
     contents.  If the key/value pair referenced by the cursor has been
     deleted, *c_get* will return *DB_KEYEMPTY*.

DB_SET
     Set the cursor to point to the key/value pair referenced by $key and
     return the value in $value.

DB_SET_RANGE
     This flag is a variation on the DB_SET flag. As well as returning the
     value, it also returns the key, via $key.  When used with a
     BerkeleyDB::Btree database the key matched by *c_get* will be the
     shortest key (in length) which is greater than or equal to the key
     supplied, via $key. This allows partial key searches.  See ??? for an
     example of how to use this flag.

DB_GET_BOTH
     Another variation on DB_SET. This one returns both the key and the
     value.

DB_SET_RECNO
     TODO.

DB_GET_RECNO
     TODO.

   In addition, the following value may be set by logically OR'ing it into
the $flags parameter:

DB_RMW
     TODO.

$status = $cursor->c_put($key, $value, $flags)
----------------------------------------------

   Stores the key/value pair in the database. The position that the data is
stored in the database is controlled by the $flags parameter, which must
take one of the following values:

DB_AFTER
     When used with a Btree or Hash database, a duplicate of the key
     referenced by the current cursor position will be created and the
     contents of $value will be associated with it - $key is ignored.  The
     new key/value pair will be stored immediately after the current
     cursor position.  Obviously the database has to have been opened with
     *DB_DUP*.

     When used with a Recno ... TODO

DB_BEFORE
     When used with a Btree or Hash database, a duplicate of the key
     referenced by the current cursor position will be created and the
     contents of $value will be associated with it - $key is ignored.  The
     new key/value pair will be stored immediately before the current
     cursor position.  Obviously the database has to have been opened with
     *DB_DUP*.

     When used with a Recno ... TODO

DB_CURRENT
     If the cursor has been initialised, replace the value of the key/value
     pair stored in the database with the contents of $value.

DB_KEYFIRST
     Only valid with a Btree or Hash database. This flag is only really
     used when duplicates are enabled in the database and sorted duplicates
     haven't been specified.  In this case the key/value pair will be
     inserted as the first entry in the duplicates for the particular key.

DB_KEYLAST
     Only valid with a Btree or Hash database. This flag is only really
     used when duplicates are enabled in the database and sorted duplicates
     haven't been specified.  In this case the key/value pair will be
     inserted as the last entry in the duplicates for the particular key.

$status = $cursor->c_del([$flags])
----------------------------------

   This method deletes the key/value pair associated with the current
cursor position. The cursor position will not be changed by this
operation, so any subsequent cursor operation must first initialise the
cursor to point to a valid key/value pair.

   If the key/value pair associated with the cursor have already been
deleted, *c_del* will return *DB_KEYEMPTY*.

   The $flags parameter is not used at present.

$status = $cursor->c_del($cnt [, $flags])
-----------------------------------------

   Stores the number of duplicates at the current cursor position in
*$cnt*.

   The $flags parameter is not used at present. This method needs Berkeley
DB 3.1 or better.

$status = $cursor->status()
---------------------------

   Returns the status of the last cursor method as a dual type.

Cursor Examples
---------------

   TODO

   Iterating from first to last, then in reverse.

   examples of each of the flags.

JOIN
====

   Join support for BerkeleyDB is in progress. Watch this space.

   TODO

TRANSACTIONS
============

   TODO.

DBM Filters
===========

   A DBM Filter is a piece of code that is be used when you always want to
make the same transformation to all keys and/or values in a DBM database.
All of the database classes (BerkeleyDB::Hash, BerkeleyDB::Btree and
BerkeleyDB::Recno) support DBM Filters.

   There are four methods associated with DBM Filters. All work
identically, and each is used to install (or uninstall) a single DBM
Filter. Each expects a single parameter, namely a reference to a sub.  The
only difference between them is the place that the filter is installed.

   To summarise:

filter_store_key
     If a filter has been installed with this method, it will be invoked
     every time you write a key to a DBM database.

filter_store_value
     If a filter has been installed with this method, it will be invoked
     every time you write a value to a DBM database.

filter_fetch_key
     If a filter has been installed with this method, it will be invoked
     every time you read a key from a DBM database.

filter_fetch_value
     If a filter has been installed with this method, it will be invoked
     every time you read a value from a DBM database.

   You can use any combination of the methods, from none, to all four.

   All filter methods return the existing filter, if present, or undef in
not.

   To delete a filter pass undef to it.

The Filter
----------

   When each filter is called by Perl, a local copy of $_ will contain the
key or value to be filtered. Filtering is achieved by modifying the
contents of $_. The return code from the filter is ignored.

An Example - the NULL termination problem.
------------------------------------------

   Consider the following scenario. You have a DBM database that you need
to share with a third-party C application. The C application assumes that
all keys and values are NULL terminated. Unfortunately when Perl writes to
DBM databases it doesn't use NULL termination, so your Perl application
will have to manage NULL termination itself. When you write to the
database you will have to use something like this:

     $hash{"$key\0"} = "$value\0" ;

   Similarly the NULL needs to be taken into account when you are
considering the length of existing keys/values.

   It would be much better if you could ignore the NULL terminations issue
in the main application code and have a mechanism that automatically added
the terminating NULL to all keys and values whenever you write to the
database and have them removed when you read from the database. As I'm
sure you have already guessed, this is a problem that DBM Filters can fix
very easily.

     use strict ;
     use BerkeleyDB ;

     my %hash ;
     my $filename = "filt.db" ;
     unlink $filename ;

     my $db = tie %hash, 'BerkeleyDB::Hash',
     		-Filename   => $filename,
     	        -Flags      => DB_CREATE
       or die "Cannot open $filename: $!\n" ;

     # Install DBM Filters
     $db->filter_fetch_key  ( sub { s/\0$//    } ) ;
     $db->filter_store_key  ( sub { $_ .= "\0" } ) ;
     $db->filter_fetch_value( sub { s/\0$//    } ) ;
     $db->filter_store_value( sub { $_ .= "\0" } ) ;

     $hash{"abc"} = "def" ;
     my $a = $hash{"ABC"} ;
     # ...
     undef $db ;
     untie %hash ;

   Hopefully the contents of each of the filters should be
self-explanatory. Both "fetch" filters remove the terminating NULL, and
both "store" filters add a terminating NULL.

Another Example - Key is a C int.
---------------------------------

   Here is another real-life example. By default, whenever Perl writes to
a DBM database it always writes the key and value as strings. So when you
use this:

     $hash{12345} = "something" ;

   the key 12345 will get stored in the DBM database as the 5 byte string
"12345". If you actually want the key to be stored in the DBM database as
a C int, you will have to use pack when writing, and unpack when reading.

   Here is a DBM Filter that does it:

     use strict ;
     use BerkeleyDB ;
     my %hash ;
     my $filename = "filt.db" ;
     unlink $filename ;

     my $db = tie %hash, 'BerkeleyDB::Btree',
     		-Filename   => $filename,
     	        -Flags      => DB_CREATE
       or die "Cannot open $filename: $!\n" ;

     $db->filter_fetch_key  ( sub { $_ = unpack("i", $_) } ) ;
     $db->filter_store_key  ( sub { $_ = pack ("i", $_) } ) ;
     $hash{123} = "def" ;
     # ...
     undef $db ;
     untie %hash ;

   This time only two filters have been used - we only need to manipulate
the contents of the key, so it wasn't necessary to install any value
filters.

Using BerkeleyDB with MLDBM
===========================

   Both BerkeleyDB::Hash and BerkeleyDB::Btree can be used with the MLDBM
module. The code fragment below shows how to open associate MLDBM with
BerkeleyDB::Btree. To use BerkeleyDB::Hash just replace BerkeleyDB::Btree
with BerkeleyDB::Hash.

     use strict ;
     use BerkeleyDB ;
     use MLDBM qw(BerkeleyDB::Btree) ;
     use Data::Dumper;

     my $filename = 'testmldbm' ;
     my %o ;

     unlink $filename ;
     tie %o, 'MLDBM', -Filename => $filename,
                      -Flags    => DB_CREATE
                     or die "Cannot open database '$filename: $!\n";

     See the MLDBM documentation for information on how to use the module
     and for details of its limitations.

EXAMPLES
========

   TODO.

HINTS & TIPS
============

Sharing Databases With C Applications
-------------------------------------

   There is no technical reason why a Berkeley DB database cannot be
shared by both a Perl and a C application.

   The vast majority of problems that are reported in this area boil down
to the fact that C strings are NULL terminated, whilst Perl strings are
not. See `An Example -- the NULL termination problem.' in this node in the
DBM FILTERS section for a generic way to work around this problem.

The untie Gotcha
----------------

   TODO

COMMON QUESTIONS
================

   This section attempts to answer some of the more common questions that
I get asked.

Relationship with DB_File
-------------------------

   Before Berkeley DB 2.x was written there was only one Perl module that
interfaced to Berkeley DB. That module is called DB_File. Although DB_File
can be build with Berkeley DB 1.x, 2.x or 3.x, it only provides an
interface to the functionality available in Berkeley DB 1.x. That means
that it doesn't support transactions, locking or any of the other new
features available in DB 2.x or 3.x.

How do I store Perl data structures with BerkeleyDB?
----------------------------------------------------

   See `Using BerkeleyDB with MLDBM' in this node.

HISTORY
=======

   See the Changes file.

AVAILABILITY
============

   The most recent version of *BerkeleyDB* can always be found on CPAN
(see `CPAN', see Perlmod (perl.info), for details), in the
directory `modules/by-module/BerkeleyDB'.

   The official web site for Berkeley DB is `http://www.sleepycat.com'.

COPYRIGHT
=========

   Copyright (c) 1997-2001 Paul Marquess. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

   Although *BerkeleyDB* is covered by the Perl license, the library it
makes use of, namely Berkeley DB, is not. Berkeley DB has its own
copyright and its own license. Please take the time to read it.

   Here are few words taken from the Berkeley DB FAQ (at
`http://www.sleepycat.com') regarding the license:

     Do I have to license DB to use it in Perl scripts?

     No. The Berkeley DB license requires that software that uses
     Berkeley DB be freely redistributable. In the case of Perl, that
     software is Perl, and not your scripts. Any Perl scripts that you
     write are your property, including scripts that make use of Berkeley
     DB. Neither the Perl license nor the Berkeley DB license
     place any restriction on what you may do with them.

   If you are in any doubt about the license situation, contact either the
Berkeley DB authors or the author of BerkeleyDB.  See `"AUTHOR"' in this
node for details.

AUTHOR
======

   Paul Marquess <Paul.Marquess@btinternet.com>.

   Questions about Berkeley DB may be addressed to <db@sleepycat.com>.

SEE ALSO
========

   perl(1), DB_File, Berkeley DB.

bicycle power-output calculator with command-line and Tk interface
******************************************************************

NAME
====

   BikePower - bicycle power-output calculator with command-line and Tk
interface

SYNOPSIS
========

     use Tk;
     use BikePower;
     $top = new MainWindow;
     BikePower::tk_interface($top);

   or

     use BikePower;
     BikePower::output();

DESCRIPTION
===========

   *BikePower* calculates power output and power consumption for
bicycling. You give it things like riding speed, body weight, hill grade,
and wind speed. The module returns power output and power consumption,
broken out in various ways.

   This module is meant for inclusion in own programs. There are two perl
scripts in the distribution, *bikepwr* and *tkbikepwr*, for use as
stand-alone programs.

CONSTRUCTOR
===========

   A new BikePower object is constructed with

     $bpwr = new BikePower [options];

   Here is a list of possible options, which are supplied in a
key-value-notion (e.g.

     $bpwr = new BikePower '-no-ini' => 1, 'V_first' => 20;

   ).

-no-ini
     If set to true, do not use the defaults from ~/.bikepower.pl.

-no-default
     If set to true, do not use any defaults (all parameters are left
     undefined).

imperial
     Metric/imperial flag. If set, use imperial rather than metric units.

T_a
     Temperature in °C.

given
     Resolve for v (velocity), P (power) or C (consumption).

first_C
     First consumption (Cal/hr) in table or other output.

first_V
     First velocity (km/h) in table or other output.

first_P
     First power output (Watts) in table or other output.

V_incr
     Velocity increment in table.

P_incr
     Power increment in table.

C_incr
     Consumed_power increment in table.

N_entry
     Number of entries in table, default: 10.

C_a
     Air resistance coefficient.

A1
     Linear coefficient of air resistance.

A2
     Quadratic coefficient of air resistance.

A_c
     Frontal area of the cyclist in meters^2.

T
     Transmission efficiency of bicycle drivetrain.

E
     Efficiency of human in cycling.

H
     Velocity of headwind [meters/second].

R
     Coefficient of rolling friction.

G
     Grade of hill.

Wc
     Weight of cyclist [kg].

Wm
     Weight of machine and clothing [kg].

BM_rate
     Basal metabolism rate [Watts/kg of body weight].

cross_wind
     The wind given is a cross wind.

METHODS
=======

calc
     Resolve for velocity, power output or consumption (as stated in the
     "given" parameter) for the first_V, first_P or first_C parameter. The
     calculated values may be get with $bpwr->velocity, $bwpr->power or
     $bpwr->consumption.

output
     Calculate and print a table with the supplied values.

INI FILE
========

   The easiest way to create the ini file is to use *tkbikepwr* and
clicking on the menu item "Save as default". The ini file is evaled as a
perl script and should contain the variable $x as a reference to a hash.
For example:

     $x = {
            'V_incr' => 2,
            'C_a' => '0.9',
            'A_c' => '0.4925155 (upright)',
            'Wm' => 19,
            'E' => '0.249',
            'G' => '0',
            'H' => '0',
            'first_C' => 500,
            'C_incr' => 100,
            'A1' => '0',
            'R' => '0.0066 (26 x 1.375)',
            'T_a' => 20,
            'T' => '0.95',
            'first_P' => 50,
            'given' => 'v',
            'Wc' => 68,
            'BM_rate' => '1.4',
            'P_incr' => 50,
            'cross_wind' => '0',
            'first_V' => 16,
            'N_entry' => 10
          };

TODO
====

     + better POD!

SEE ALSO
========

   `BikePower::Tk(3)|BikePower::Tk' in this node, `bikepwr(1)|bikepwr' in
this node, `tkbikepwr(1)|tkbikepwr' in this node

AUTHOR
======

   Slaven Rezic (eserte@cs.tu-berlin.de)

   Original program bike_power.c by Ken Roberts (roberts@cs.columbia.edu),
Dept of Computer Science, Columbia University, New York and co-author Mark
Grennan (markg@okcforum.org).

   Copyright (c) 1997,1998,1999 Slaven Rezic. All rights reserved.  This
package is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Common methods used by many application classes.
************************************************

NAME
====

   Argon - Common methods used by many application classes.

SYNOPSIS
========

   package MyApplication;  @MyApplication::ISA = qw(BingoX::Argon); use
BingoX::Argon;

     # $BR - Blessed Reference
     # $SV - Scalar Value
     # @AV - Array Value
     # $HR - Hash Ref
     # $AR - Array Ref
     # $SR - Stream Ref

     # $proto - BingoX::Carbon object OR sub-class
     # $object - BingoX::Carbon object

     $BR = $proto->new()
     $BR = $app->r()
     $BR = $app->dbh()
     $BR = $app->cgi()
     $BR = $app->conf()
           $app->include()
           $app->xinclude()
     $HR = $app->display_classes()
     $BR = $app->get()
     $AR = $app->list()
     $SR = $app->stream()

REQUIRES
========

   Apache::XPP

EXPORTS
=======

   Nothing

DESCRIPTION
===========

   BingoX::Argon is an application superclass that handles basic tasks
like returning display objects, handling xincludes, and caching request
and cgi objects.

   I'm hoping it won't do too much else: Display classes have to do
SOMETHING, don't they?

CLASS VARIABLES
===============

   * %display_classes

     This is how Argon will know what classes it can call.  The keys are
     the name of the function and the value is the class name.

     For example:   %display_classes = (thingees =>
     'Application::Display::Thingee');

     You can then call get_ , list_ , or stream_thingees(), passing a
     hashref of the data fields by which you want to limit your search.

METHODS
=======

CONSTRUCTORS
------------

new ( [ \%data ] )
     Creates a new Application object.

OBJECT METHODS
--------------

r (  )
     returns the Display object's Apache request object. Or if for some
     reason the object doesn't have one, it creates a new one.

`available_display_classes' (  )
     Static method returns the subclass's \%display_classes.

`data_class' (  )
     Static method returns data class defined for application subclass.
     If none is assigned, guess. :-)

dbh (  )
     Caches and returns a reference to the app's Data Class dbh.

cgi (  )
     Returns the current CGI object or creates a new one.

`conf' (  )
     Caches and returns a Conf object.  Overload this if you want to use a
     static Conf module.

`query_url' ( )
     Returns the path of the user's location.

param ( $name )
     Returns cgi params.

escape ( $name )
     Returns cgi escape.

delete ( $name )
     Deletes from the cgi params.

include ( $template )
     Forwarding method:

     Calls Apache/XPP,->include() and passes it the
     $template.

`xinclude' ( $template [, $obj ] )
     Forwarding method:

     Includes $obj in the $template.  Calls `Apache::XPP-' in this
     nodexinclude()> and passes it the default array.

AUTOLOAD (  )
     This will first look in instance data, then go through the sub class's
     %display_classes field and see if it's in %display_classes reference.
     If it is, it will try and get it using passed params.

     Returns undef on error.

REVISION HISTORY
================

     $Log: Argon.pm,v $
     Revision 2.8  2000/12/12 18:48:01  useevil
      - updated version for new release:  1.92

     Revision 2.7  2000/10/20 17:23:18  gefilte
     Removed Data::Dumper requirement.  (Only loaded if $debug is on.)

     Revision 2.6  2000/10/20 00:28:24  zhobson
     Added some useful debug messages to AUTOLOAD

     Revision 2.5  2000/09/19 23:40:00  dweimer
     Version update 1.91

     Revision 2.4  2000/08/31 21:54:18  greg
     Added COPYRIGHT information.
     Added file COPYING (LGPL).
     Cleaned up POD.
     Moved into BingoX namespace.
     References to Bingo::XPP now point to Apache::XPP.

     "To the first approximation, syntactic sugar is trivial to implement.
      To the second approximation, the first approximation is totally bogus."
        -Larry Wall

     Revision 2.3  2000/08/01 00:38:28  thai
      - added cgi accessor methods:
        query_url()
        param()
        escape()
        delete()

     Revision 2.2  2000/07/12 19:28:21  thai
      - fixed POD, cleaned up code

     Revision 2.1  2000/05/19 01:22:56  thai
      - cleaned up code
      - is the top level class for all Bingo Applications

     Revision 2.0  2000/05/02 00:54:33  thai
      - committed as 2.0

THOUGHTS, LYRICS, POEMS, CANTRIPS, RHYMES
=========================================

   "Ray, when someone asks you if you're a god, you say YES!"

     -Winston

SEE ALSO
========

   perl(1).

KNOWN BUGS
==========

   None

COPYRIGHT
=========

     Copyright (c) 2000, Cnation Inc. All Rights Reserved. This module is free
     software. It may be used, redistributed and/or modified under the terms
     of the GNU Lesser General Public License as published by the Free Software
     Foundation.

     You should have received a copy of the GNU Lesser General Public License
     along with this library; if not, write to the Free Software Foundation, Inc.,
     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

AUTHOR
======

   Colin Bielen <colin@cnation.com>

An object oriented database abstraction superclass
**************************************************

NAME
====

   BingoX::Carbon - An object oriented database abstraction superclass

SYNOPSIS
========

   use BingoX::Carbon ( [ ':cache_all', ] [ ':no_dynmeth' ] );

     # $BR - Blessed Reference
     # $SV - Scalar Value
     # @AV - Array Value
     # $HR - Hash Ref
     # $AR - Array Ref
     # $SR - Stream Ref

     # $proto - BingoX::Carbon object OR sub-class
     # $object - BingoX::Carbon object

   CONSTRUCTORS

     $BR = $proto->new( $dbh, \%data );
     $BR = $proto->get( $dbh, $ID );
     $BR = $object->duplicate;

   STREAM CONSTRUCTOR METHODS

     $SR = $proto->stream_obj( $dbh, \%params, [\@fields,] [\@sort] );
     $SR = $proto->stream_hash( $dbh, \%params, [\@fields,] [\@sort] );
     $SR = $proto->stream_array( $dbh, \%params, [\@fields,] [\@sort] );

   LIST CONSTRUCTOR METHODS

     $AR = $proto->list_obj( $dbh, \%params, [\@fields,] [\@sort] );
     $AR = $proto->list_hash( $dbh, \%params, [\@fields,] [\@sort] );
     $AR = $proto->list_array( $dbh, \%params, [\@fields,] [\@sort] );

   RELATION METHODS

     $SV = $object->relate( $fobject | \@fobjects | (\@fids, $fclass, $fcolumn) );
     $SV = $object->unrelate( $fobject | \@fobjects | (\@fids, $fclass, $fcolumn) );
     $SV = $object->isrelated( $fobject );
     $AR = $object->list_related( $fclass [, \@fields] [, \@sort] );
     $SR = $object->stream_related( $fclass [, \@fields] [, \@sort] );
     $SV = $proto->unrelate_all( $fclass )

   DATABASE MANIUPLATION METHODS

     $BR = $object->modify( \%new_data );
     $SV = $proto->modify( $dbh, \%params, \%new_data );
     $SV = $object->rm;
     $SV = $proto->rm( $dbh, \%params );

   CLASS DATA ACCESSOR METHODS

     $SV = $proto->table( $dbh );
     $SV = $proto->identity( $dbh );
     $AR = $proto->primary_keys( $dbh );
     $HR = $proto->def_fields( $dbh );
     $AR = $proto->field_order( $dbh );
     $SV = $proto->identity( $dbh );
     $SV = $proto->sequence( $dbh );
     $SV = $proto->seqcol( $dbh );

   DATABASE/SQL METHODS

     $SR = $proto->sql_select( $dbh );
     @AV = $proto->format_select( $dbh, \%params, \@fields, \@sort [,$alias] );
     @AV = $proto->format_conditions( $dbh, \%params [,$alias] );

REQUIRES
========

   DBI, Carp, strict, Date::Parse, BingoX::Time

EXPORTS
=======

   Nothing

DESCRIPTION
===========

   BingoX::Carbon provides a database abstraction in which each row of
data is represented by an object blessed into a class representing the
table.  Each Carbon Class represents a table or view in the database.  The
database and classes are described by variables in said classes.  After
Carbon classes have been set up to represent tables in a database,
creating, retrieving and modifying data is simply a matter of method calls
against Carbon objects and classes.  For a tutorial on setting up a Carbon
project, see `carbontut' in this node packaged with BingoX.

DATABASE SUPPORT
================

   Currently, Carbon has been tested and is known to work with *Sybase*,
*Oracle*, and *PostgreSQL*.  Carbon should with minimal change be able to
support many other databases.

   Due to Carbon's extensive use of transactions, it will not currently
work with database engines that do not support transactions - most notably
MySQL.

   We tried to keep Carbon/BingoX as database agnostic as possible, but
had to put some database specific code to support such things as Sybase's
Indentity columns, Oracles Sequences, the different date formats, and
Oracles use of all caps.

   If you would like to help Carbon support MySQL or other database
engines, feel free to send patches or contact us for help.

CLASS VARIABLES
===============

REQUIRED
--------

   Classes that inherit from BingoX::Carbon must have the following class
variables:

   * $table

     A scalar that contains the table name the class represents.

   * @primary_keys

     An array containing the primary key colulmn names.

   * @field_order

     An array containing all the table's column names in perferred order
     of use.  Was formerly  used for order of display, but has since been
     replaced by the BingoX Display namespace modules.

OPTIONAL
--------

   * $identity

     A scalar that contains the name of the column which is a Sybase
     IDENTITY column.  There can be only one identity column per table.

   * $seqcol

     A scalar that contains the name of the column which should be
     populated by a sequence.

   * $sequence

     A scalar that contains the name of the sequence object in the
     database which new() will poll to determine what to populate $seqcol
     with.

   * %relations

     A hash containing relational data. The keys to the hash are class
     names of foreign objects. The values are class names that represents
     the referential class for any object blessed in the class of the key.

     e.g. :

          %relations = ( ClassOne => 'ClassOne_ClassTwo' );

   * %foreign_keys

     A hash containing relational data present in referential classes.
     The keys to the hash are class names representing the classes
     referred to.  The values are the names of the columns which contain
     the foreign key to the referred table.

     e.g. :

          %foreign_keys = ( ClassOne => 'one', ClassTwo => 'two' );

   * $title_field

     The column which should be used to display the object in a list.

   * %content_fields

     This hash lets Carbon classes have virtual columns to hold large
     amounts of content data. The keys of this hash are virtual colum
     names whose values are Carbon classnames that handle those content
     columns.

     e.g. :

          %content_fields = ( content	=> 'Class::Data::Content' );

   * %date_fields

     The keys of this hash are column names from the fieldorder array that
     have a database type of date.  Putting those columns in here make
     sure that you will get Unix time when asking for those columns.

     e.g. :

          %date_fields = ( showdate	=> 1 );

METHODS
=======

CONSTRUCTORS AND STATIC METHODS
-------------------------------

import (  )
     Called from 'use BingoX::Carbon;'

     Possible arguments are as follows:

   * :cache_all

     flag will put all data into the object at time of construction.  The
     default action is to store only primary_keys in the object until data
     is needed, but this approach proved very inefficient in certain
     situations.

   * :no_dynmeth

     flag will stop the creation of methods in calling class for all the
     elements of the class' fieldorder.

   * :full_dynmeth

     flag will avoid using 'forwarder' methods and instead use full
     dynamic methods - each with it's own code resembling AUTOLOAD.  By
     default, forwarder methods are used and all call _old_school_autoload

     Any other element, not starting with the ':' character will be
     interpreted as a method name with which to create an access method in
     the calling class.

new ( [ $dbh, ] \%data )
     Constructs a new object with the data in the hashref passed to it.
     You must supply a value for all primary key columns, unless the
     database provides a method for autogenerating this value.  If an ID
     isn't specified the ID will be the next number in the database
     sequence :

     Sybase

     Class data $identity contains name of column which is a Sybase
     IDENTITY.  The IDENTITY field will be omitted from the insert
     statement so Sybase can autogenerate it.  New will then select
     @@identity to retreive the result of triggering IDENTITY.  Because it
     does this within a single statement, it will get the correct value.

     Oracle, Postgres

     Class data $sequence contains name of Sequence object in database, and
     class data $seqcol contains name of column where BingoX::Carbon will
     insert the value returned by triggering $sequence.

get ( [ $dbh, ] \%params )
     Constructs an object from the database using the parameters passed.
     NOTE: Passing one scalar variable as an ID to get has been deprecated!
     get will assume the parameters { $self->primary_keys->[0] => shift() }
     if a scalar is passed in place of \%params. Future version of
     BingoX::Carbon will not support this!

     For instructions on the format of \%params, see
     `"item_format_conditions"' in this node.

modify ( \%new_data )
     Object method:

     Modify instance data with \%new_data and sync with database.  Returns
     $self if success, undef if failure.

modify ( $dbh, \%params, \%new_data )
     Static method:

     Modify all rows satisfied by conditions in \%params with \%new_data
     Returns true if success, undef if failure.

     N.B. - You CAN NOT modify non-columnar information (i.e.,
     relationships or extra-tabular "content" fields) for multiple rows
     simultaneously.

     For instructions on the format of \%params, see
     `"item_format_conditions"' in this node.

`duplicate' ( [ $dbh, ] [ $object ] )
     Returns a duplicate object, differing only by the primary key.

rm ( )
     Object method:

     Deletes the object and all database records associated with it.

rm ( $dbh, \%params )
     Static method:

     Deletes all database rows satisfied by the conditions in \%params.

     For instructions on the format of \%params, see
     `"item_format_conditions"' in this node.

DATA LIST CONSTRUCTOR METHODS
-----------------------------

`list_obj' ( [ $dbh, ] \%params, \@fields, \@sort )
     Returns an arrayref of objects meeting all specifications in \%params.

     For instructions on the format of \%params, see
     `"item_format_conditions"' in this node.

`list_hash' ( [ $dbh, ] \%params, \@fields, \@sort )
     Returns an arrayref of hashrefs meeting all specifications in \%params

     For instructions on the format of \%params, see
     `"item_format_conditions"' in this node.

`list_array' ( [ $dbh, ] \%params, \@fields, \@sort )
     Returns an arrayref of arrayrefs meeting all specifications in
     \%params. Data is sorted in the order of $class->deffields.

     For instructions on the format of \%params, see
     `"item_format_conditions"' in this node.

DATA STREAM CONSTRUCTOR METHODS
-------------------------------

`stream_obj' ( [ $dbh, ] \%params, \@fields, \@sort )
     Returns an code reference which, when dereferenced, will continue to
     return objects meeting all specifications in \%params until all
     matching rows have been returned, then it will return undef.  Will
     optionally limit itself to the fields specified in \@fields, and
     optionally sorted in the order of \@sort.

     For instructions on the format of \%params, see
     `"item_format_conditions"' in this node.

`stream_hash' ( [ $dbh, ] \%params, \@fields, \@sort )
     Returns an code reference which, when dereferenced, will continue to
     return a hashref meeting all specifications in \%params until all
     matching rows have been returned, then it will return undef.  Will
     optionally limit itself to the fields specified in \@fields, and
     optionally sorted in the order of \@sort.

     For instructions on the format of \%params, see
     `"item_format_conditions"' in this node.

`stream_array' ( [ $dbh, ] \%params, \@fields, \@sort )
     Returns an code reference which, when dereferenced, will continue to
     return an arrayref meeting all specifications in \%params until all
     matching rows have been returned, then it will return undef. Will
     optionally limit itself to the fields specified in \@fields, and
     optionally sorted in the order of \@sort.

     For instructions on the format of \%params, see
     `"item_format_conditions"' in this node.

RELATIONAL METHODS
------------------

relate ( $OBJ )
relate ( \@OBJECTS )
relate ( \@IDS, $ID_CLASS, $ID_COLUMN )
     Relates object to $OBJ, all objects in \@OBJECTS, or objects
     represented by \@IDS from the $ID_CLASS class in the $ID_COLUMN
     column of the database. Returns the number of objects passed that
     have been related to the object.

`unrelate' ( $OBJ )
`unrelate' ( \@OBJECTS )
`unrelate' ( \@IDS, $ID_CLASS, $ID_COLUMN )
     Unrelates object from $OBJ, all objects in \@OBJECTS, or objects
     represented by \@IDS from the $ID_CLASS class in the $ID_COLUMN
     column of the database. Returns the number of objects that no longer
     are related to the object.

`unrelate_all' ( $fclass [ , $unary_rev ] )
     Unrelates all related objects in class $fclass from current object.
     Optional $unary_rev does reverse operation for unary relationships

     i.e.:

          unrelates "parent" objects from current

`isrelated' ( $OBJ )
     Returns a true value if $OBJ is related to the object, false
     otherwise.

`list_related' ( $class [, \@fields] [, \@sort] [, $unary_rev_flag ] )
     Returns an arrayref of objects of $class related to the object.

`stream_related' ( $class [, \@fields] [, \@sort] [, $unary_rev_flag ] )
     Returns an code reference which, when dereferenced, will continue to
     return objects of $class related to the object until all matching
     rows have been returned, then it will return undef.

     _related_subquery_conditions ( $fclass [, $unary_rev ] )
     	- $fclass is the "foreign" class (related class)
     	- in scalar context, returns \%fparams (see unrelate_all())
     	- in array context, returns (\%fparams, \@fcolumns, \@columns) (see _related_conditions())
     		%fparams  : parameters of query (can be passed to format_conditions())
     		@fcolumns : relevant columns in foreign class
     		@columns  : relevant columns in this class

     _related_conditions ( $fclass [, $unary_rev ] )
     	- $fclass is the "foreign" class (related class)
     	- generates conditions suitable for using with stream_obj()
     	- used only by stream_related() and list_related()

`get_relation_info' ( ('I' | 'S'), $OBJ )
`get_relation_info' ( ('I' | 'S'), \@OBJECTS )
`get_relation_info' ( ('I' | 'S'), \@IDS, $ID_CLASS, $ID_COLUMN )
     Returns as the first element the relational class on which the second
     data element is associated. If the first argument is an 'I' (INSERT),
     the second element is a hashref suitable to pass to new or modify. If
     the first argument is an 'S' (SELECT), returns a hashref suitable to
     pass to get, list_*, stream_*, etc. This method is primarily used by
     methods relate, unrelate, isrelated, and related.

CLASS DATA ACCESSOR METHODS
---------------------------

table ( [ $dbh ] )
     Returns class defined table name

`identity' ( [ $dbh ] )
     Returns class defined identity column as a string.

sequence ( [ $dbh ] )
     Returns class defined sequence used by this table as a string.

`seqcol' ( [ $dbh ] )
     Returns class defined seqcol used by this table as a string.

`def_fields' (  )
     Returns class defined fields as a hash reference

`field_order' (  )
     Returns class defined field order as an anonymous array

`relations' (  )
     Returns class defined relations as a hash reference

`foreign_keys' (  )
     Returns class defined foreign_keys as a hash reference

`cpkey' (  )
     Returns a string representing a single composite primary key joined
     by $self->pkd.

     OPTIMIZE

`cpkey_params' ($cpkey)
     Returns a params hash from the cpkey string passed.

`title_field' (  )
     Returns class defined title_field as a string.

`title_size' (  )
     Returns class defined title_size as a string.

`content_fields' (  )
     Returns class defined content fields order as an hashref

`date_fields' (  )
     Returns class defined date fields order as an hashref

`primary_keys' ( [ $dbh ] )
     Returns class defined primary keys as an array ref.  NOTE: The use of
     the class variable $primary_key has been deprecated!  primary_keys
     will construct an array ref with $primary_key if it is used.  Future
     verson of BingoX::Carbon will not support this!

dbh ( )
     Returns class database handler object.  Keeps a global which gets
     removed with a $r->register_cleanup.

`cached_dbh' ( [ $dbh ] )
     Returns the cached database handle if it has been set.  Optionally
     sets the cached database handle to $dbh.

`purge_dbh' (  )
     Clears the database handle cache variable.

error_handler (  )
     Carps @_ if debugging is activated prints stack backtrace if $debug >
     2 always returns undef (if you choose to overload this method, please
     make sure you return undef)

errors (  )
     Returns $self->{'_errors'} if called as an object method.  Returns
     $errstr of the called class otherwise.

`data_class' (  )
     Returns the data class

`data_class_name' (  )
     Returns the rightmost part of the data_class_name name (thats the
     text right of the ::)

`connectdb' ( )
     *** NEEDS ERROR HANDLER ****

     Called as a static method, it just returns the DBH Object.

`pkd' ( )
     Returns a constant for the primary key delimiter.

date_format ( )
     Returns a constant, the strftime template for what date strings are
     to be displayed as.

`str2time' ( $string )
     This is method is used to parse your default date format into a format
     that str2time understands, such as:

          Date: 961221               (yymmdd)
          Date: 12-21-96             (mm-dd-yy)    ( '-', '.' or '/' )
          Date: 12-June-96           (dd-month-yy) ( '-', '.' or '/' )
          Date: June 12 96 00:00PM   (month dd yy hh:mmPM)
          Date: June 12 96 00::00:00 (month dd yy hh:mm::ss)

     If time is not passed then time defaults to 00:00:00.

SQL GENERATION METHODS
----------------------

`sql_select' ( [ $dbh, ] $SELECT [, \@bindings] )
     Excutes the prepared select statement and returns an arrayref of
     objects. The @bindings array contains values of SQL placeholders if
     used. Returns a code reference that will return a hashref when
     dereferenced.

`format_select' ( [ $dbh, ] \%params, \@fields, \@sort [, $alias ] )
     Returns formatted SQL 'SELECT' statement, selecting @fields that meet
     all specifications in %params, sorted by @sort.  Also returns
     bindings of all dynamic placeholders in SQL statement.  Optionally,
     $alias may specify the table alias to be used in the statment ("
     WHERE alias.name = 'myname'"). Sub-values should be surrounded by ##,
     ie "name LIKE ##me##", for conditions involving: ( LIKE, NOT, <, >,
     SELECT ) Finally, and sort terms may be reversed (made descending) by
     prepending them with a '-'. (e.g., to sort by 'col1' ascending and
     'col2' descending, pass 'qw(col1 -col2)'.)

     For instructions on the format of \%params, see
     `"item_format_conditions"' in this node.

`format_conditions' ( [ $dbh, ] \%params [, $alias ] )
     Returns formatted sql 'WHERE' block, and an array of values to be
     bound (passed to DBI->execute().)  Optionally, $alias may specify the
     table alias to be used in the statment (" WHERE alias.name =
     'myname'").  The keys of %params are the fields you are trying to
     match; the values of %params are specified as follows :

   * equality condition

     To test one equality, simply pass the value you wish to match as the
     value.

     e.g. :

          { $field => 12 }
          { $field => 'twelve' }

   * inequalities or multiple equalities (LIKE, NOT, <, >, IN, BETWEEN)

     Sub-values should be surrounded by ##, ie "name LIKE ##me##", for
     conditions involving: ( LIKE, NOT, <, > ).

     To use IN or BETWEEN (with or without NOT), params should contain
     something similar to ( $field => [ $type, @LIST ] ) where $type is
     '[NOT ]IN' or '[NOT ]BETWEEN' and  @LIST is the set of values for the
     statement.

   * NULL/NOT NULL conditions

     To test for a NULL condition or NOT NULL condition, pass 'IS NULL' or
     'IS NOT NULL' (respectively) as the value.

     e.g. :

          { $field => 'IS NOT NULL' }

   * subqueries

     When using a SELECT statement in an IN block, the argument
     immediately following the select statement should be the arrayref
     containing any bindings for that statement.  This means that you may
     use the output of format_conditions as the input for a subquery :

          $conditions = $obj_class1->format_conditions(
                 $dbh,
                 {
                    $field => [
                                 'IN',
                                 $obj_class2->format_conditions( $dbh, $field => $value )
                              ]
                 }
          );

   * multiple values

     To match multiple conditions, pass an arrayref (that does not begin
     with 'IN' or 'BETWEEN'!)  containing a list of conditions (any of the
     conditions above.)  You MUST delimit each condition with either '&&'
     (for AND) or '||' (for OR), and you may also use '(' or ')' to
     separate logical conditions.

     e.g. :

          { $field => [ 1, '||', '(', 2, '&&', 3, ')' ] }

AUTOLOAD
--------

AUTOLOAD
     AUTOLOAD method - returns requested field data from object.  If that
     requested data has not been cached, it is retrieved from the
     database, cached, and returned.  If data is passed then field value is
     modified in the database and instance data, and value is returned.

          _create_access_method($name)
          	- dynamically creates accessor method for method $name
          	- called by AUTOLOAD() or import()

          _create_forwarder_method($name)
          	- dynamically creates accessor method for method $name
          	- called by AUTOLOAD() or import()

          _old_school_autoload
          	- this is what AUTOLOAD() used to be (this is your father's AUTOLOAD)
          	- loading BingoX::Carbon with the ':no_dynmeth' tag will assign
          		$class::AUTOLOAD to this method

          _content> ( $content_class, $column, $content )

          Object Method:
          	If $content (optional) is passed, the content will either be reomoved
          	or modified in the db. If no content is passed, then the content will
          	be selected from the db.

`int_to_bitmap' ( $int )
     Returns a 32-bit bit-string which corresponds to the integer $int.

`bitmap_to_int' ( $bitmap )
     Returns an integer that corresponds to the (at most) 32-bit
     bit-string $bitmap.

`get_list_hash' (  )
`get_list_hash' ( [ $dbh ] [, \%params ] )
     If used as a static method then you must pass $dbh.

     Returns a hash ref of all the objects in the class it was called
     against.  The hash is built from the `cpkey', and the `title_field',
     substr()'d to the `title_size' or by default 80 chars.

     OPTIMIZE

     initializes content methods

     initializes date methods.  Makes a lot of assumptions.  The main date
     format is in Sybase.  If not it assumes that the date format is in a
     string format as that of strftime.

REVISION HISTORY
================

     $Log: Carbon.pm,v $
     Revision 2.34  2000/12/12 19:05:00  gefilte
     new(), modify() - fixed incorrect usage of cpkey(), which caused relational code to fail.

     Revision 2.33  2000/12/12 18:49:36  useevil
      - removed $pkey from cpkey, because its not used
      - updated version for new release:  1.92

     Revision 2.32  2000/11/15 19:33:09  useevil
      - new(), modify(), and _date_meth_init() now calls time2str() instead
        of stringifying the object, and date_format() now works

     Revision 2.31  2000/09/26 21:17:38  zhobson
     Fixed bugs in connectdb() and dataclass() that conspired to prevent projects from
     specifying a connectarray in their own namespace (like @Foo::Data::connectarray)

     Revision 2.30  2000/09/20 20:48:27  dweimer
     Doh! fixed some typo's

     Revision 2.29  2000/09/20 20:46:14  dweimer
     Merged David's changes.
     His comments:
     Cleaned up some debugging code.  All stray carp() calls now call error_handler().  error_handler() itself cleaned up.

     Revision 2.28  2000/09/19 23:49:38  dweimer
     content() - no longer converts linebreaks into HTML break tags (must have seemed useful at the time...)
     Changed error_handler so that it clucks if debug is > 2.

     Revision 2.27  2000/09/19 23:42:42  dweimer
     Version update 1.91

     Revision 2.26  2000/09/13 18:16:00  david
     new(), modify()
     	- now only open a transaction if necessary (multiple statements required)

     RATIONALE - This will allow you to use a new() or modify() call when you have an active stream open, so long as the new() or modify() call does not require changes made to a relationship or to a content_field.

     Revision 2.25  2000/09/13 02:21:32  david
     Some minor POD changes
     Now only requires Data::Dumper if $debug is on.
     new(), modify(), rm(), _content()
     	- Made all database transaction code more conventional (in the perl/DBI sense.)
     modify()
     	- static method mode now works again (broken by Carbonium code in rev. 2.1)
     	- will now return an error if you attempt to use statically to change contentfields or relationships
     	- no longer truncates trailing spaces (if you want to do that, do it yourself!)

     Revision 2.24  2000/09/08 03:08:15  adam
      - added cpkey_params method
      - changed cpkey (removed wantarray stuf)

     Revision 2.23  2000/09/07 20:00:58  thai
      - updated POD documentation to show all REQUIRED classes

     Revision 2.22  2000/09/07 19:57:29  thai
      - added data_class_name()
      - changed DateTime::Date usage to BingoX::Time

     Revision 2.21  2000/09/06 23:18:02  greg
     removed old POD, and make new POD more coherent and descriptive.

     Revision 2.20  2000/09/02 00:15:17  thai
      - fixed POD documentation for date_format()

     Revision 2.19  2000/09/01 23:26:30  thai
      - added:
         date_format() - the date format you want returned from the date object
     	str2time() - used to parse date from the database

     Revision 2.18  2000/08/31 22:53:12  greg
     added COPYING and MANIFEST files

     Revision 2.17  2000/08/31 21:54:18  greg
     Added COPYRIGHT information.
     Added file COPYING (LGPL).
     Cleaned up POD.
     Moved into BingoX namespace.
     References to Bingo::XPP now point to Apache::XPP.

     "To the first approximation, syntactic sugar is trivial to implement.
      To the second approximation, the first approximation is totally bogus."
     	-Larry Wall

     Revision 2.16  2000/08/10 21:08:41  thai
      - changed get_list_hash() to work a lot better
      - changed cpkey() to use wantarray and $cpkey for when you want only the
        primary keys
      - changed occurrances where you split the $cpkey to use $self->cpkey( $cpkey )

     Revision 2.15  2000/08/09 21:24:34  thai
      - added title_size()

     Revision 2.14  2000/08/07 23:08:41  thai
      - will return content fields with <BR> for (\r\n)|[\n\r]

     Revision 2.13  2000/08/07 17:58:30  thai
      - fixed bug in _content() where it tried to deference an undefined
        array ref

     Revision 2.12  2000/08/03 20:45:15  thai
      - addd pkd() method to handle the pkds

     Revision 2.11  2000/07/14 19:12:25  dougw
     Should fix the datefields and contentfields error. They were returning an arrayref and the meth_inits tried
     to dereference it as a hash. DOH!

     Revision 2.10  2000/07/13 22:12:44  thai
      - changed methods so they are more consistent
          deffields() is now def_fields()
     	 fieldorder() is now field_order()
     	 contentfields() is now content_fields()
     	 datefields() is now date_fields()
     	 dataclass() is now data_class()
        of course the other methods still work, but please use the new ones

     Revision 2.9  2000/07/12 19:29:02  thai
      - fixed POD, cleaned up code

     Revision 2.8  2000/07/11 01:18:40  zack
     removed explicit reference to Datatime::Date::Sybase from _date_meth_init()

     Revision 2.7  2000/07/11 00:05:39  zack
     in cached_dbh(), only use Apache->register_cleanup() if mod_perl
     is running

     Revision 2.6  2000/07/10 22:39:16  zack
     - added the ability to provide a selection to get_list_hash()

     Revision 2.5  2000/07/07 01:34:54  dougw
      - Took out Caching for _content methods until we decide on a method to
        cache them other than just class name.

     Revision 2.4  2000/06/24 03:17:56  dougw
      - Modified _content to handle param passing when updating and retrieving
        a content field. Made sure content_meth_init and date_meth_init check
        to see if a method exists before mucking with other namespaces

     Revision 2.3  2000/05/31 02:39:20  greg
     changed use of s/.*:// to substr(...) in AUTOLOAD for efficiency.

     Revision 2.2  2000/05/24 20:45:11  thai
      - tried to weed out as much of the DateTime::Date::Sybase code as
        possible.  Still uses DateTime::Date, and only DateTime::Date::Sybase
        in _date_meth_init()

     Revision 2.1  2000/05/19 01:24:42  thai
      - cleaned up code
      - is now part of the Bingo user space
      - added code from Carbonium

     Revision 2.0  2000/05/02 00:54:33  thai
      - committed as 2.0

     Revision 1.58  2000/03/17 19:01:36  colin
     - changed format_conditions() so that it allows "IS " statements to work
       (was formerly only matching "IS NOT" statements)

     Revision 1.57  2000/03/09 02:01:07  dougw
     Allows nulled numerics and values.
     Changed the push lines in &new and &modify to allow above.

     Revision 1.56  2000/03/08 23:24:36  zack
     Facilitated NULL updates

     Revision 1.55  2000/02/10 20:05:11  greg
     memory saver - now creates forwarder methods instead of full dynamic methods

     Revision 1.54  2000/02/10 08:56:40  greg
     lots of new TODO and TO BE INVESTIGATED items to think about or implement...

     Revision 1.53  2000/02/10 07:24:24  greg
     now doesn't pass empty string column names in sql to DBI...

     Revision 1.52  1999/12/30 04:40:18  thai
      - bug in format_conditions where if the param field was
        not in deffields, then it would "next" leaving behind
        the remnants of the joined condition "AND" or "OR"
        I pop'd the @query array to eliminate that

     Revision 1.51  1999/12/29 01:44:53  david
     More documentation improvements and additions.
     Fixed format_conditions() so BBEdit balances tags correctly. (loathe BBedit :-)

     Revision 1.50  1999/12/28 22:38:10  david
     new() now makes identity/sequence decisions based on actual driver type of $dbh.
     Better documentation of new().

     Revision 1.49  1999/11/21 02:19:24  adam
      - format_conditions() - you can now use 'is not' as well as 'not'

     Revision 1.48  1999/11/10 23:27:59  greg
     Cleaned up documentation and code. Documentation and debugging information
     now more accurately reflects what is actually happening in Carbon.

     Revision 1.47  1999/10/28 05:52:25  david
     AUTOLOAD(), _create_access_method(), _old_school_autoload()
     	- revised accessor code for efficiency (made an 8% improvement!)
     	- added private POD and lots of other useful comments

     I've wanted to do this for awhile...just never got around to it until now.

     Revision 1.46  1999/10/22 21:11:25  thai
      - fixed some typos in the warns and POD.

     Revision 1.45  1999/10/08 21:51:53  derek
     Fixed an error with over-sanitization in format_contditions.

     Revision 1.44  1999/10/08 21:01:48  david
     Merged 'oracle' branch (excluding r1.36.2.5-r1.36.2.7, merged previously
     into r1.41), adding Oracle support to Carbon, as well as some other
     improvements (listed below in revision history.)

     Oracle support in sql_select() still needs refining.

     Revision 1.36.2.8  1999/10/01 09:19:38  david
     Removed silly ($primary_keys >= 2) condition from new().
     	(If you don't know what it is, you probably don't care.)

     format_conditions() - added means to specify order and logic of parameters
     	(NEEDS DOCUMENTATION)

     _create_access_method() - changed warning of $AUTOLOAD to $name

     Revision 1.36.2.4  1999/09/21 21:45:05  colin
     Dave changed part of sql_select back so it works now. Huzzah!

     Revision 1.36.2.3  1999/09/21 19:46:30  colin
     changed format_select(): the actuall select statement use lowercase SQL
     commands because uppercase ones don't work on views :P

     Revision 1.36.2.2  1999/09/21 18:49:57  david
     sql_select() - Minor fix to Oracleizing code -- now works for columns not in fieldorder.

     Revision 1.36.2.1  1999/09/10 07:46:51  david
     INITIAL ORACLE SUPPORT
     	Added seqcol() and sequence() class variables and corresponding static methods
     		$seqcol   - name of column which sequence applies to (like $identity)
     		$sequence - name of sequence object in the database
     	new() - will use nextval of $sequence to populate $seqcol (if no data supplied for that column)
     	- removed $DATABASE::database kluge (Sybase seems to need it -- don't forget!)
     	sql_select() - creates different closure for Oracle which does case matching
     		(Oracle columns return uppercase and are case-insensitive, Carbon is case-sensitive.)
     Tested
     	new() - seems to work as expected with sequences or without
     	modify() - works correctly as object method, as well as through accessor methods
     	rm() - works as object method
     	accessor methods - work
     To do :
     	test modify() and rm() in static form
     	test relationships
     	document changes to new() in POD

     I imagine most everything should work, since the change was made at sql_select()
     -- the main point of database read access.  All methods which write to the database
        should work normally, since Oracle is case-insensitive.  Still, more testing
        should be done.

     Furthermore, the algorithm I used to make sql_select() work is slow, and can probably
     be greatly improved.  Still, it's a start, and should preserve our API functionality.

     Revision 1.43  1999/10/08 01:13:29  david
     rm() (static) - sanity prevents you from removing entire table if params is empty
     Restructured stream/list_related :
     	_related() broken into _related_conditions() and _related_subquery_conditions()
     	stream_related() now calls sql_select() using result of related_conditions()
     	list_related() now calls stream_related() (like list_obj() calls stream_obj()

     unrelate() - now uses list_obj() instead of stream_obj() to get objects to unrelate
     	(this may bite us later, but for now it makes unrelate() "transaction-friendly")

     unrelate_all() - new method will unrelate all objects of a named class from an object
     	(uses new _related_subquery_conditions() to form its parameters to call rm() with)

     "Think it'll work?"
     "It'll take a miracle..."

     Revision 1.42  1999/10/07 23:39:02  greg
     fixed sql BETWEEN syntax

     Revision 1.41  1999/09/29 20:52:03  david
     Merged in changes from r1.36.2.5 through r1.36.2.7 :
     Support for multiple conditions/field in SELECTs.

     Revision 1.36.2.7  1999/09/29 00:27:46  david
     Removed spurious warn left behind in last commit.

     "Do as I say, not as I do."

     Revision 1.36.2.6  1999/09/28 23:08:31  david
     format_conditions() - added support for multiple conditions/field

     Revision 1.36.2.5  1999/09/24 00:48:19  david
     Fixed bug in format_conditions() - it didn't let you have a condition value of 0.

     Revision 1.40  1999/09/28 00:39:25  greg
      - Added blesses, and class Carbon::Stream to support streams as objects - this isn't
        heavily test yet.
      - Changed cmps (ref($stream) eq 'CODE') to (ref($stream)) to support new stream class.
      - Lots of other small bug fixes.

     Revision 1.39  1999/09/25 21:31:16  david
     table() - no longer prepends table names with the value of $DATABASE::database

     Revision 1.38  1999/09/25 20:14:39  david
     modify() - added [@wherevals] bind information to debugging output
     format_conditions() - bug fix : did not allow conditions with 0 values
     **************************************************************************
     sql_select() - REMOVED CALL TO DBI->TRACE.
     		PEPPLER FIXED DBD::Sybase "Bind Placeholder" BUG
     **************************************************************************
     Just be nice to people, and they do nice things for you. :-)

     Revision 1.37  1999/09/10 07:41:38  david
     Bug fix :
     	The first time you called an accessor method and AUTOLOAD() creates a dynamic
     	method, if you called it with content (i.e., to modify the object attribute)
     	that content would not be forwarded to the new accessor method by AUTOLOAD().
     	This is now fixed.

     (See the diff? Real tiny fix. :-)

     Revision 1.36  1999/09/10 03:22:22  david
     Bug Fixes
     	new() - can now insert a NULL into a non-IDENTITY primary key column which has
     	        a default (sort of kludgy -- basically it allows this if there are multiple
     	        primary keys.
     		    the SELECT MAX() thing should probably go the way of the Dodoe.)
     	- changed default sort parameters (ORDER BY) to primary_keys() instead of fieldorder()
     		(Many people have complained about this.  let me know if you disagree with it.)
     Miscellanea
     	- Changed all calls for DBI::errstr to $dbh->errstr or $sth->errstr
     	modify() - changed @update_values to @update_fields, and @values to @update_values
     		(basically, this just uses the same naming as new(), for consistency.)
     debugging improvments
     	- AUTOLOAD now reports what it was called as
     	- new(), modify(), and rm() now display which class is calling them
     documentation
     	- updated KNOWN BUGS section, added TO DO LIST section

     "We don't code bugs here!"

     Revision 1.35  1999/07/14 23:43:22  david
     Changed relations() method to not return %foreign_keys ref
     Added foreign_keys() method to replace functionality of relations() method
     Changed calls to relations() which should be calls to foreign_keys()

     Revision 1.34  1999/07/13 23:10:20  greg
     Added method _old_school_autoload so calling $obj->SUPER::method() works with
     dynamic methods. _create_access_method sets *Carbon::AUTOLOAD to
     \&_old_school_autoload when called with 'AUTOLOAD' (so as not to duplicate
     code).

     Revision 1.33  1999/07/02 03:36:27  david
     Changed a bunch of 'carp()' calls to $self->error_handler

     get() - fixed weird bug where extra arguments were forwarded to closure, signaling
             termination of embedded $sth

     format_relations/conditions()
         - no longer require $dbh be first parameter (though it will still work)
         - commented out useless code to determine i f value is numeric
             (this was a throwback to our pre-placeholder-binding days)

     Unary relation fixes :
     _related()
         - renamed from related()
         - fixed unary relations for *_related methods()
         - added $unary_rev_flag to reverse unary operations (needs POD!)
     relate/unrelate()
         - fixed unary relations (reversed operands of grep operation, binaries don't care!)

     Unary relationships now work as undocumented.  That is, they work the way we
     discussed they would work.  But they still need to be documented! ;=}

     Revision 1.32  1999/07/01 18:59:03  greg
     Made changes to modify to add sanity, and efficiency.

     Revision 1.31  1999/07/01 02:22:11  david
     mget() - extra 'my $params = shift;' caused wildly unpredictable results...

     BAD, NASTY, EVIL DARTH GREG BUG!

     Revision 1.30  1999/06/30 00:53:22  greg
     fixed bugs that were found when integrating with Conf with this version of Carbon.
     added workaround for sybase losing track of the current database - needs to be fixed.

     Revision 1.29  1999/06/25 22:23:42  david
     - Some minor POD corrections
     new()
         - Started changing new() to support inserting into identity fields (not finished)
         - Added minor debugging
     sanity - changed most verifications of (ref $params) to (ref $params eq 'HASH')
     get() - cleans up coderef before exiting
     modify() - added static method usage
     rm() - added static method usage
     - unanchored /##(.+?)##/ regular expression in modify() and format_conditions()
       (so they will actually work)
     list/stream_obj() - adds primary_keys to \@fields if excluded

     Revision 1.28  1999/06/23 22:42:00  greg
     -import: Removed silliness; now you can pass options to classes that inherit
       from Carbon
     -format_contitions: now bindings in 'IN' are passes as an array and not an
       array ref
     -related: took advantage of new syntax for format_conditions
     -get_relation_into: added sanity and warnings

     Revision 1.27  1999/06/22 23:19:59  greg
     - submit: added sanity
     - rm: now removes hash data before undefining reference to object
     - format_conditions: added better support for 'IN' and 'BETWEEN'
     Rewrote relation methods relate and unrelate. Added list_related,
     stream_related, and isrelated based on the get_relation_info and
     related methods

     Revision 1.26  1999/06/15 18:41:31  greg
     import: changed to recognize all options starting with ':' as options,
     	all others as methods. Added ':no_dynmeth' as import option to
     	specify methods should not be generated dynamically, but left to
     	AUTOLOAD
     Changed method AUTOLOAD, and added method _create_access_method to
     	generate dynamic methods

     Revision 1.25  1999/06/11 19:29:09  greg
     Fixed cache_all option that broke with the introduction of the list_* and
     stream_* methods.

     Revision 1.24  1999/06/10 23:03:45  greg
     Added space to SQL statements using WHERE blocks returned by format_conditions.

     Revision 1.23  1999/06/10 21:13:13  greg
     Changed $Carbon::VERSION variable to contain the CVS revision number
     import - changed to use a class variable to control cache_all functionality
     new - Added sanity
     get/mget - changed to wrapper methods around the list_obj method
     _format_conditions - changed to public method format_conditions
     list - changed to wrapper method around list_obj and list_hash methods
     deffields - changed to construct a hash from the class fieldorder
     sql_select - Returns a coderef to stream hash data (no longer blesses objects)
     format_select - new method to construct and return a complete SELECT statement

     Added methods stream_obj, stream_hash, stream_array, list_obj, list_hash, list_array
     Removed scrolling_list, chop_blanks, escape
     Cleaned up code. Removed lots of warn statements.
     Updated POD to reflect new and changed methods.

     --
     "There is no conspiracy. Nobody is in charge. It's a headless blunder
     operating under the illusion of a master plan."    --Worth (Cube)

     Revision 1.22  1999/06/09 23:26:41  thai
      - moved the revision logs to the bottom.

     Revision 1.21  1999/05/08 20:16:23  adam
      - sql_select - added sanity to ensure that all retrieved objects have
        primary keys.  Otherwise it creates bad objects.  It only does this
        if there's no $nobless flag.  Added comments around it.
      - There may be a better way of checking.  Probably before the select.
      - identity - podified identity method.
      - AUTOLOAD - commented autoload sanity ensuring that the primary key
        isn't autoloaded.  Maybe theres a better way to do this, like checking
        right when you enter autoload. The object should always have a primary key.
      - new - updated pod to account for identity field.

     Revision 1.20  1999/05/07 22:25:46  greg
      - import - Added ability to specify caching of all data at object construction
                 at time of require. To cache all data: use Carbon qw(cache_all);
                 This will redefine the mget function from where objects are gotten
                 (also from get, although get is just a convenient wrapper around mget)

     Revision 1.19  1999/05/07 16:47:37  greg
      - Changed names of variables set by return values of _format_conditions
        to make more sense.
      - Added a bit of sanity to what _format_conditions does when something
        isn't quite right.

     Revision 1.18  1999/05/06 22:30:13  adam
      - new() - Now properly handles identities.  It now puts the insert and
        select @@identity in the same prepare to ensure it is getting the
        correct identity value.

     Revision 1.17  1999/05/06 06:30:55  adam
      - Handles identity columns.
      - Changed new to look for identity information in class and use it
        if it can.
      - Added identity method which looks for $identity in the class.
      - Split up insert statement in new to work with inserts of just the
        identity field.

     Revision 1.16  1999/05/05 06:32:59  adam
      - Added if debug.

     Revision 1.15  1999/05/05 05:56:38  adam
      - Added if ($debug);

     Revision 1.14  1999/05/03 17:11:45  fred
      - added a line to chop_blancs to unescape single quotes.

     Revision 1.13  1999/04/30 00:56:49  thai
      - added more verbage to AUTOLOAD to explain how it returns $obj->name if
        its not already cached.
      - made a change in _format_conditions; ($value =~ /LIKE|NOT|IN|<|>/) to
        ($value =~ /^(LIKE|NOT|IN|<|>)/)

     Revision 1.12  1999/04/29 20:39:22  thai
      - removed $dbh = shift, because it doesn't need it.

     Revision 1.11  1999/04/15 19:44:56  greg
      - Silly me ;) New should return $self, not $dbh <G>

     Revision 1.10  1999/04/15 19:34:13  greg
      - Changed the instance data method dbh uses from 'dbh' to '_dbh'. Changed method
      - new to add dbh to the instance data.

     Revision 1.9  1999/04/13 17:04:37  thai
      - removed $fields->[1] from list(), so that it now returns only an array
        ref of hashes or objs.
      - removed $name from AUTOLOAD at (@{ $self->primary_keys }), causing infinite
        loops.

     Revision 1.8  1999/04/10 20:17:09  adam
      - AUTOLOAD - changed if (defined... to if (exists...

     Revision 1.7  1999/04/10 00:34:10  colin
      - new - changed the select max bit so that if there are no records, it makes it 1.

     Revision 1.6  1999/04/09 22:55:02  greg
      - Tiny work around in case primary_keys doesn't return an array ref.

     Revision 1.5  1999/04/09 22:41:58  greg
      - Added more POD. Removed duplicate primary_keys method.

     Revision 1.4  1999/04/09 20:21:29  greg
      - Removed some debugging information, and turned off all debugging.

     Revision 1.3  1999/04/09 20:10:54  greg
      - Ton of new changes. Multiple primary keys, multiple database support, relations.
      - This was rushed a little, so there may be bugs...

     Revision 1.2  1999/03/12 23:56:40  thai
      - added DBI->trace to modify().

     Revision 1.38  1999/03/12 22:16:36  thai
      - added cvs headers.

SEE ALSO
========

   perl(1).

KNOWN BUGS
==========

   new() currently does not report failure if inserting with Sybase
IDENTITY columns fails, because of an anomoly in the way DBI handles
multiple result sets.  You can tell if a new() has failed if the value of
the IDENTITY column is < 1.

TODO
====

   * REWRITE RELATIONAL CODE!!!

   * ability to redirect debugging to a file instead of STDERR

   * write test suite testing ALL documented carbon features

   * document unary many-many relationships

     (works, presently undocumented)

   * one-many relationships

   * multirow inserts (multinew?)

TO BE INVESTIGATED
==================

   * carbon profiling

     carbon could use it's own debugging information to profile projects,
     and generate statistics based on that information. it could
     optionally store the profiling data to a sepearte table for later
     perusing... fields to store would be global incremented unique number
     with PID, action (select, modify, etc), sql statement, timestamp.

   * join class

     dynamically create a class based on a join between carbon classes.
     class data from all joined classes would need to be stored to be able
     to modify data.

   * read only objects (useful in view objects)

   * view classes

     store class data in such a way that modifying through the view
     wouldn't break (one table at a time, or store info on how to modify
     the actual carbon class for the view tables).

   * virtual classes

     get rid of empty classes! carbon has worked to well, and there are far
     to many empty classes lying around. either generate classes at compile
     time, or pretending that the classes exist at run time (using some
     sort of Carbon object ($carbon->class->method). Using a carbon object
     would need to fill in class @ISA arrays so that calls to the class
     could be caught.

   * Change class data to be more flexible - containing meta data

COPYRIGHT
=========

     Copyright (c) 2000, Cnation Inc. All Rights Reserved. This module is free
     software. It may be used, redistributed and/or modified under the terms
     of the GNU Lesser General Public License as published by the Free Software
     Foundation.

     You should have received a copy of the GNU Lesser General Public License
     along with this library; if not, write to the Free Software Foundation, Inc.,
     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

AUTHORS
=======

     David Pisoni <david@cnation.com>
     Greg Williams <greg@cnation.com>
     Thai Nguyen <thai@cnation.com>

Generic BingoX Admin module
***************************

NAME
====

   BingoX::Chromium - Generic BingoX Admin module

SYNOPSIS
========

   use BingoX::Chromium;

     # $BR - Blessed Reference
     # $SV - Scalar Value
     # @AV - Array Value
     # $HR - Hash Ref
     # $AR - Array Ref
     # $SR - Stream Ref

     # $proto - BingoX::Chromium object OR sub-class
     # $object - BingoX::Chromium object

   CONSTRUCTORS

     $BR = $proto->new( $r, [ $conf ] );

   DISPLAY METHODS

     $SV = $proto->postmodify_handler();
     $SV = $proto->postadd_handler();
     $SV = $object->display_list();
     $SV = $object->display_view();
     $SV = $object->display_modify();
     $SV = $object->display_search();				- Not Implimented Yet!
     $SV = $object->display_row( $field );
     $SV = $object->display_list_buttons();
     $SV = $object->display_modify_buttons();
     $SV = $object->displat_start_html();
     $SV = $object->hidden_fields();

   DATA METHODS

     $SV = $object->save_data();
     $HR = $object->get_data( [ $data, ] [ $fields ] );
     $SV = $object->sanity();
     $BR = $proto->dbh();
     $BR = $object->db_obj();
     $HR = $object->get_list_hash();

   CLASS VARIABLE METHODS

     $SV = $proto->db_class();
     $SV = $proto->db_class_name();
     $SV = $proto->adminuri();
     $SV = $proto->classdesc();
     $SV = $proto->qfd();
     $SV = $proto->pkd();
     $SV = $proto->prefix();
     $SV = $proto->cpkey_params($pcpkey);
     $AR = $proto->fieldlist();
     $HR = $proto->ui();
     $AR = $proto->parents();
     $AR = $proto->children();
     $HR = $proto->fields();
     $SV = $proto->fieldname( $field );
     $SV = $proto->fieldtype( $field );
     $HR = $proto->fieldhtmloptions( $field );
     $SV = $proto->fieldrelclass( $field );
     $SV = $proto->fieldrelclasstype( $field );
     $HR = $proto->fieldoptions( $field );
     $HR = $proto->fieldsanity( $field );

   OBJECT METHODS

     $SV = $object->flow();
     $SV = $object->cpkey();
     $SV = $object->pcpkey();
     $SV = $object->parent_class();
     $BR = $object->cgi();
     $SV = $object->uri();
     $SV = $object->displaymode();
     $SV = $object->section();
     $BR = $object->conf();
     $BR = $object->r();

   HTML DISPLAY METHODS

     $SV = $object->HTML_date( $fieldname );
     $SV = $object->HTML_view( $fieldname );
     $SV = $object->HTML_hidden( $fieldname );
     $SV = $object->HTML_text( $fieldname );
     $SV = $object->HTML_textarea( $fieldname );
     $SV = $object->HTML_popup( $fieldname );		- Not Finished!
     $SV = $object->HTML_scrolling( $fieldname );
     $SV = $object->HTML_checkbox( $fieldname );
     $SV = $object->HTML_file( $fieldname );

REQUIRES
========

   Time::Object, Apache, CGI, Carp

EXPORTS
=======

   Nothing

DESCRIPTION
===========

     BingoX::Chromium provides the generic API for BingoX admin classes.
     BingoX::Chromium uses admin objects that wrap Carbon data objects

CLASS VARIABLES
===============

   Classes that inherit from BingoX::Chromium should have the following
class variables:

   * @fieldlist

     The order in which to display fields (if one so chose to display them
     ;)

   * %fields

     A hash whose keys are colums (same as in the fieldlist array) and
     whose values are complex arrays. Each array index is described below.

    [0] Descriptive Title
          A string describing the field

    [1] HTML Entity Type
          A string that contains one of the following HTML etity types:

               view
               text
               textarea
               datetime
               popup
               reference
               FIXME: more!!!

    [2] HTML Options
          A hash reference containing options for creating the HTML form
          field for this field.

    [3] Related Classes
          FIXME: I dunno

    [4] Field Options
          A hash reference containing special options for this field. The
          options include:

               not_null - this field cannot be NULL

    [5] Sanity Methods
          This is a list reference. Each item in the list is either a
          string with a sanity method name, or a list ref containing the
          method name, then any parameters that need to be passed to it.
          An example:

               [
                'sane_foo',
                ['sane_bar', 'baz'],
               ]

          For more info, see `"SANITY METHODS"' in this node.

   * $adminuri

     An optional class variable, corresponds to the `adminuri()' method.
     FIXME: Can someone who knows more about this elaborate?

   * $classdesc

     A simple one- or two-word description of the class being administered.

METHODS
=======

handler ( $r )
     Apache handler gets a new display object object of the class *it was
     called as* and calls flow against it.

CONSTRUCTORS
------------

new ( $r [, $conf [, $mode ] ] )
     Given an apache request object, returns an Admin object of the class
     *it was called as*.  It also sets the db_class, db_class_name, cgi,
     uri, displaymode (from $q), and section (from $q).

FLOW
----

flow (  )
     Decides what display method (or save_data) to call based on the
     displaymode, and submit_type (found in the query object).

     ?? Is this the best order to check ??

`postmodify_handler' ( $method_name, [ $method_name_args ] )
     This method decides what happens after you leave the "Modify" screen.
     It normally works by passing a method that gets called, but it's
     meant to be overloaded as a hook when flow() finishes saving data (or
     if you hit Cancel).  That way you can save something and go somewhere
     else besides display_view().  It currently will always call $method
     against $self, so no static methods, please...

`postadd_handler' ( $method_name, [ $method_name_args ] )
     Behaves exactly like postmodify_handler() (see above), but is called
     after the user exits the "Add a new <whatever>" screen.

DISPLAY METHODS
---------------

`display_list' (  )
     Prints an HTML page meant for listing all objects in class.

`display_list_buttons' (  )
     Displays the buttons for display_list().  Easy to overload if you
     want more buttons!

`display_modify_buttons' (  )
     Displays the buttons for display_modify().  Easy to overload if you
     want more buttons!  Just like display_list buttons.

`display_view' (  )
     Prints an HTML page meant for viewing an object.  Itterates through
     fieldlist calling display_row for each element.

`display_view_buttons' ( )
     Displays the buttons for display_view().  Easy to overload if you
     want more buttons!  Just like display_list buttons.

`display_admin_name' (  )
     Returns class defined Class description as a string.

`hidden_fields' (  )
     A stub called by display_view() and display_modify() that you can
     overload in your subclass if you want the view or modify/add screens
     to have a custom title.

`hidden_fields' ( \%fields )
     A stub called by display_view() and display_modify() that you can
     overload in your subclass if you want the view or modify/add screens
     to have extra hidden fields.

     Or you can pass it a hash ref of hidden fields, were key = field name
     and value = field value

display_start_html( \%params )
     Accessor method to $self->cgi->start_html(); Put into params exactly
     what you'd put in  CGI::start_html().  Overload this in your admin
     class if you want to set any special BG,text,link colors, or anything
     else you want to pass to start_html()

`display_search' (  )
     Prints an HTML page meant for limiting what appears on the
     display_list page.

     Not Implimented Yet.

`display_row' ( $field )
     Takes a column (field) name and prints a 2 columned table row where
     the left column has the fields descriptive name
     ($self->fieldname($field)) and the right column has the output of
     that fields method ($self->$field)

DATA METHODS
------------

`save_data' (  )
     Goes through the process of calling sanity, then get_data (to get the
     data out of the query object) and then db_obj->modify.

get_data ( [ $data, ] [ $fields ] )
     Takes the fields hash (returned by $self->fields()) and the CGI
     object and returns a data hashref which can be sent to Carbon's new
     or modify You can optionaly pass a $data hash and a $fields hash
     which it will use.

     OPTIMIZE

sanity (  )
     Populates the _errors data instance in the case that the data does
     not conform to what is allowed to be entered into the database.

`cpkey' ( [ $db_obj ] )
     Returns a string representing a single composite primary key joined
     by $self->qfd.

`cpkey_params' ($cpkey)
     Returns a params hash from the cpkey string passed.

`pcpkey' (  )
     Returns a cpkey with a class name + $qfd in front of it.

dbh (  )
     Returns the object's database handle.

     OPTIMIZE  Needs work.  Doesn't appear to use Carboniums dbh method
     thus thus doesn't use cached dbh.

`get_list_hash' ( [ $selection ] )
     *** NEEDS TO BE REMOVED ***

     Returns a hash ref of all the objects in the class it was called
     against.  The hash is built from the `pcpkey', and the data class'
     `title_field', substr()'d to the data class' `title_size' or by
     default 80 chars.

     OPTIMIZE

`db_obj' (  )
     Retrieves and caches encapsolated DATA object based on whats in the
     query obect.   Looks for pcpkey query param first and then for each
     primary key individually.

     OPTIMIZE

CLASS VARIABLE METHODS
----------------------

`db_class' (  )
     Returns class defined db_class as a string.

`db_class_name' (  )
     Returns the rightmost part of the db_class name (thats the text right
     of the ::)

`ui' (  )
     This method is a fallback method for the user interface for
     BingoX::Chromium.  ui() contains the default colors for the forms
     created by BingoX::Chromium.  To create a custom color scheme for a
     specific class or entire admin area create a ui() method in either
     the Admin class or the subclass and modify the details to your
     preference.

children (  )
     Returns class defined children as an arrayref.

`parents' (  )
     Returns class defined parents as an arrayref.

`parent_class' (  )
     Returns cached parent class

`adminuri' (  )
     Returns class defined URI as a string.

`classdesc' (  )
     Returns class defined Class description as a string.

`adminclass' (  )
     NEEDS POD

`fieldlist' (  )
     Returns the class defined fieldlist as an arrayref.

fields (  )
     Returns class defined fields hashref.

`fieldname' ( $field )
     Takes a column name and returns a string with that field's pretty
     name as defined in the class defined field hash.  This is the [0]
     element of that keys array value.

`fieldtype' ( $field )
     Takes a column name and returns a string with that field's HTML type
     as defined in the class defined field hash.  This is the [1] element
     of that keys array value.

`fieldhtmloptions' ( $field )
     Takes a column name and returns a hashref with that field's HTML
     options as defined in the class defined field hash.  This is the [2]
     element of that keys array value.

`fieldrelclass' ( $field )
     Takes a column name and returns a string with that field's related
     class (if it exists) as defined in the class defined field hash.
     This is the [3] element of that keys array value.

`fieldrelclasstype' ( $field )
     Takes a column name and returns a string with that field's related
     class (if it exists) as defined in the class defined field hash.
     This is the [3] element of that keys array value.

`fieldoptions' ( $field )
     Takes a column name and returns a hashref with that field's options
     information as defined in the class defined field hash.  This is the
     [4] element of that keys array value.

`fieldsanity' ( $field )
     Takes a column name and returns a listref with that field's sanity
     information as defined in the class defined field hash.  This is the
     [5] element of that keys array value.

OBJECT METHODS
--------------

`uri' (  )
     Returns the cached uri object.

cgi (  )
     Returns the cached cgi object.

`conf' (  )
     Returns the cached conf object (set in new).

section (  )
     Returns the cached section (set in new).

`displaymode' (  )
     Returns the cached uri displaymode (set in new).

r (  )
     Object Method: Returns Apache Request object.

selection ( [ \%hash ] )
     Returns a hash reference containing the parameters that specify the
     current selection. If a new value is passed, it sets the selection to
     that value.

HTML DISPLAY METHODS
--------------------

`qfieldname' ( $fieldname )
     Object Method:

     Returns the fieldname to be used in the FORM INPUT NAME field.  When
     overloading Administration field variables, use this to get the INPUT
     TYPE NAME.

     ie.  <INPUT TYPE="text" NAME="$self->qfieldname('username')">

`main_index' (  )
     Object Method:

     Returns the Main Index Path.

`HTML_time' ( $fieldname [, $qoptions ] )
     Object Method:

     Generic Hours Form Tag.  Called by AUTOLOAD.  Gets the default field
     params based on the fieldname and returns a set of date form fields
     or in viewable format if the displaymode is 'view'.

`HTML_day' ( $fieldname [, $qoptions ] )
     Object Method:

     Generic Day Form Tag.  Called by AUTOLOAD.  Gets the default field
     params based on the fieldname and returns a set of date form fields
     or in viewable format if the displaymode is 'view'.

`HTML_month' ( $fieldname [, $qoptions ] )
     Object Method:

     Generic Month Form Tag.  Called by AUTOLOAD.  Gets the default field
     params based on the fieldname and returns a set of date form fields
     or in viewable format if the displaymode is 'view'.

`HTML_year' ( $fieldname [, $qoptions ] )
     Object Method:

     Generic Year Form Tag.  Called by AUTOLOAD.  Gets the default field
     params based on the fieldname and returns a set of date form fields
     or in viewable format if the displaymode is 'view'.

`HTML_date' ( $fieldname [, $qoptions ] )
     Object Method:

     Generic form field method called by AUTOLOAD.  Gets the default field
     params based on the fieldname and returns a set of date form fields
     or in viewable format if the displaymode is 'view'.

     *Needs to be less Sybase Dependant and handle Time*

`HTML_view' ( $fieldname )
     Object Method:

     Generic form field method called by AUTOLOAD.  Gets the default field
     params based on the fieldname and returns the value in viewable
     format.

`HTML_hidden' ( $fieldname [, $qoptions ] )
     Object Method:

     Generic form field method called by AUTOLOAD.  Gets the default field
     params based on the fieldname and returns the value as a hidden input
     field.

`HTML_text' ( $fieldname [, $qoptions ] )
     Object Method:

     Generic form field method called by AUTOLOAD.  Gets the default field
     params based on the fieldname and returns the value in a text input
     field or in viewable format if the displaymode is 'view'.

`HTML_textarea' ( $fieldname [, $qoptions ] )
     Object Method:

     Generic form field method called by AUTOLOAD.  Gets the default field
     params based on the fieldname and returns the value in a text input
     field or in viewable format if the displaymode is 'view'.

`HTML_popup' ( $fieldname [, $qoptions ] )
     Object Method:

     Generic form field method called by AUTOLOAD.  Gets the default field
     params based on the fieldname and returns the value in a popup field
     or in viewable format if the displaymode is 'view'.

     Note: Not used yet because its not easy to populate the vaules &
     labels fields. USually always overloaded in the subclasses.

     OPTIMIZE

`HTML_radio' ( $fieldname [, $qoptions ] )
     Object Method:

     Generic form field method called by AUTOLOAD.  Gets the default field
     params based on the fieldname and returns the value in a group of
     radio buttons or in viewable format if the displaymode is 'view'.

`HTML_scrolling' ( $fieldname [, $qoptions ] )
     Object Method:

     Generic form field method called by AUTOLOAD.  Gets the default field
     params based on the fieldname and returns the value in a scrolling
     list field or in viewable format if the displaymode is 'view'.

     Note: Not used yet because its not easy to populate the vaules &
     labels fields. USually always overloaded in the subclasses.

     OPTIMIZE

`HTML_checkbox' ( $fieldname [, $qoptions ] )
     Object Method:

     Generic form field method called by AUTOLOAD.  Gets the default field
     params based on the fieldname and returns the value in a checkbox
     field or in viewable format if the displaymode is 'view'.

     Note: Not used yet because its not easy to populate the vaules &
     labels fields. USually always overloaded in the subclasses.

`HTML_file' ( $fieldname [, $qoptions ] )
     Object Method:

     Generic form field method called by AUTOLOAD.  Gets the default field
     params based on the fieldname and returns the value in a form file
     upload field or in viewable format if the displaymode is 'view'.

SANITY METHODS
--------------

   These methods can be overridden at any level to provide customized
sanity checking. These methods always return an error message on failure,
and an empty string on success.

`sane_regex' ( $data, $regex [, $error ] )
     If $data matches the regular expression in `$regex', returns an empty
     string. Otherwise, returns $error or a default error message.

`sane_maxlength' ( $data, $length )
     Makes sure that $data is no more than $length characters long. Returns
     an error message on failure, an empty string on success.

`sane_minlength' ( $data, $length )
     Makes sure that $data is at least $length characters long. Returns an
     error message on failure, an empty string on success.

AUTOLOAD (?????)
     AUTOLOAD method - Figures out what method was being called by
     stripping the fully qualified portion of $AUTOLOAD out as $name.
     This method is expected to be a column name (an element of
     fieldlist).  It then figures out what that columns fieldtype is from
     fieldtype($name).  It then calls that type of HTML display method and
     passed $name to it.

REVISION HISTORY
================

     $Log: Chromium.pm,v $
     Revision 2.28  2000/12/12 18:51:57  useevil
      - updated version for new release:  1.92

     Revision 2.27  2000/10/20 00:24:15  zhobson
     Minor changes to synopsis of new() in the docs

     Revision 2.26  2000/10/17 00:57:47  dweimer
     - corrected POD for main_index()
     - changed main_index()

     Revision 2.25  2000/09/20 21:03:27  dweimer
     Merged one last portion from the old tree.

     Revision 2.24  2000/09/20 21:00:22  dweimer
     Merged David's changes.
     His comment:
     handler() method now sets up Apache response settings instead of display_*() methods.

     Revision 2.23  2000/09/20 00:31:59  zhobson
     Fixed a scope warning in flow() (used "my $other_class" twice in the same scope)

     Revision 2.22  2000/09/19 23:40:59  dweimer
     Version update 1.91

     Revision 2.21  2000/09/13 20:58:27  adam
      - in get_data, changed how dates are handled if SHOW_24HOURS is off

     Revision 2.20  2000/09/12 16:03:35  david
     Made Data::Dumper optional -- only called when $debug is activated.  Changed all of its calls to Data::Dumper::Dumper().
     Caused handler to return result of flow(), flow ends up returning results of display_*(), display_*() methods now return Apache response constants.

     Revision 2.19  2000/09/08 22:06:24  colin
      - get_data - if the field is a date it makes sure there is at least
        the year in the query object.  Before it would break if you had a year
        in your %fields hash, but were not submitting that datefield in your
        add or modify form.  get_data would blindly try and build a date.

     Revision 2.18  2000/09/08 21:31:23  thai
      - cleaned up the code

     Revision 2.17  2000/09/08 05:19:38  thai
      - turned off debug

     Revision 2.16  2000/09/08 03:19:09  adam
      GENERAL
        Added parent/child relationship functionality, where each class can
        specify parent and child classes.  These are used to display buttons
        at the bottom of the display list screens to access your parents or
        children based on the selected item in the list.

     - updated POD
     - new
         - now accepts a CGI as an optional 4th param.
         - sets the selection from the $q->param('parent_pcpkey');
         - sets the parent_class object var from the $q->param('parent_pcpkey')
     - flow
         - checks to see if you are entering from a parent or child and sets
           $q->param('parent_pcpkey') with whats passed.
         - Gets the desired child or parent admin object and calls flow against it.
         - added debugging
     - changed all occurances of $q->startform to try and print $self->adminuri
       as the ACTION.  If there is no adminuri it uses uri as before.
     - display_list
         - displays information at the top of the page about what parent you
           came from (if there is a parent)
     - all forms now include hidden for parent_pcpkey
     - display_list_buttoms
     - displays buttons to view the display list page of any child or
              parent classes you might have.
     - pcpkey
       - renamed qkey to pcpkey
       - changed all occurances of qkey to pcpkey
     - cpkey
       - cpkey now just calls cpkey against the db_obj
     - cpkey_params
       - calls cpkey_params against your data_class
     - added children and parents class var accessor methods
     - HTML_popup
       - if your displaymode is add and you have a parent_pcpkey it attempts to
         select the parent in the pop-up menu.

     Revision 2.15  2000/09/07 22:49:03  thai
      - changed line 1200 to use BingoX::Time

     Revision 2.14  2000/09/07 20:00:02  thai
      - changed all occurances of DateTime::Date to BingoX::Time

     Revision 2.13  2000/08/31 21:54:18  greg
     Added COPYRIGHT information.
     Added file COPYING (LGPL).
     Cleaned up POD.
     Moved into BingoX namespace.
     References to Bingo::XPP now point to Apache::XPP.

     "To the first approximation, syntactic sugar is trivial to implement.
      To the second approximation, the first approximation is totally bogus."
     	-Larry Wall

     Revision 2.12  2000/08/10 21:10:55  thai
      - added qkey() to get the prefix and the cpkey
      - changed occurrances where primary keys were being iterated to use
        cpkey()
      - added prefix() method to return the correct prefix combination

     Revision 2.11  2000/08/09 21:25:03  thai
      - changed get_list_hash() to be more Carbon friendly

     Revision 2.10  2000/08/07 23:10:25  thai
      - added main_index() method to return the main index url
      - changed regex pattern for HTML_textarea()

     Revision 2.9  2000/08/07 17:59:32  thai
      - added remove and modify to the display_list_buttons() method
        and to flow

     Revision 2.8  2000/08/03 20:48:09  thai
      - addd qfd() method to handle qfds
      - fixed bug in HTML_date() that would create a new date object when
        displaymode was 'view'
      - the sub pkd() now calls data_class->pkd()

     Revision 2.7  2000/08/01 00:43:51  thai
      - changed db_obj->errstr to dbh->errstr on line 305
      - moved all the $qfieldname stuff to the qfieldname() method
      - removed the fieldtype eq 'custom' from line 1174 in get_data()

     Revision 2.6  2000/07/14 19:27:05  dougw
     save_data returns undef if it can't ref get_data's return value, should be a hashref.
     Small typo fix, hidden_fields returns a string as it should.

     Revision 2.5  2000/07/12 19:30:17  thai
      - fixed POD, cleaned up code

     Revision 2.4  2000/07/07 01:20:43  dougw
      - Added 1 instead of Turned On for the check box value. Who ever thought
        of that?  Changed the comparisons for hashrefs. Beware !%$hashref is
        different than ref $hashref ne 'HASH'

     Revision 2.3  2000/05/31 02:39:20  greg
     changed use of s/.*:// to substr(...) in AUTOLOAD for efficiency.

     Revision 2.2  2000/05/24 20:47:25  thai
      - added more sanity when dereferencing, @{ $code->() || [ ] }
      - added warning when creating new date objects fail

     Revision 2.1  2000/05/19 01:25:11  thai
      - cleaned up code
      - is now part of the Bingo user space

     Revision 2.0  2000/05/02 00:54:33  thai
      - committed as 2.0

     Revision 1.38  2000/03/21 02:00:23  dougw
     Fixed a bug introduced recently that broke adding new object when
     the identity key was in the fields list. This is so wierd. (zack)

     Revision 1.37  2000/03/17 21:09:00  dougw
     Allowed hidden values to be used in HTML_date for -TYPE=>'view'
     Fixed checkbox undef error

     Revision 1.36  2000/03/15 22:26:17  zack
     Added HTML_radio() and modified new() to allow passing a display mode.

     Revision 1.35  2000/03/15 19:25:43  colin
     -HTML_popup now sorts options alphabetically

     Revision 1.34  2000/03/14 21:45:08  dougw
     Fixed get_data->save_data problems (thanks dave).
     Removed spurious comments.

     Revision 1.33  2000/03/14 20:58:10  dougw
     Modified HTML_popup to allow a NULL selection. Use the fieldoption -null_label
     to specify what you want the option to be named. The option must not have the
     -not_null option set for obvious reasons.

     Revision 1.32  2000/03/10 01:57:54  colin
     made display_list()'s hash sorter even cooler (thanks doug)

     Revision 1.31  2000/03/10 01:18:02  colin
     -display_list() now sorts its entries alphabetically.

     Revision 1.30  2000/03/09 18:58:23  colin
     -fixed a bug in HTML_date() where $qfieldname was being used as a global.
     -fixed similar bugs in HTML_day(),HTML_month(),and HTML_year()
     -one can now pass a hashref to hidden_fields(). If one wanted to.

     Revision 1.29  2000/03/09 00:45:32  colin
     -(thai) fixed a bug in HTML_date() where it wasn't passing fieldnames to its helper methods.
     -HTML_date() now checks the -TYPE it's passed in fieldoptions

     Revision 1.28  2000/03/08 03:09:32  thai
      - parsed out HTML_date() to HTML_day(), HTML_month(), HTML_year(),
        and HTML_time()

     Revision 1.27  2000/02/25 20:24:17  colin
     corrected some minor ui bugs in display_list() and display_modify()

     Revision 1.26  2000/02/18 23:38:56  colin
     - altered sanity() so that it now accepts a passed \%data hashref instead
       of looking for things in the query object. this way the data is already
       formatted and we don't have to format data again (especially useful because
       we don't have to re-sort all the date fields, etc)

     Revision 1.25  2000/02/17 23:37:43  colin
     -get_data() now gives meaningful error messages when users enter invalid info in date fields

     Revision 1.24  2000/02/17 03:46:27  dougw
     Small modifications to take advantage of DateTime changes.
     Using $obj instead of $obj->time_local;

     Revision 1.23  2000/02/11 18:52:00  colin
     - (doug) HTML_* methods now use DateTime to manage date info.
     - (colin) Changed ui() so that a) it caches the hasref if called as an object method and b)
       allows you to override default settings (and add others) when calling the method, as
       opposed to calling SUPER::ui() and then re-setting the resulting hashref.

     Revision 1.22  2000/02/08 03:34:31  zack
     - documented the %fields class variable
     - added not_null to field options (index [4])
     - implemented flexible sanity checking
       - added sane_regex()
       - added sane_minlength() and sane_maxlength()
     - updated docs for fieldoptions() and fieldsanity()
     - HTML_textarea(): 'WRAP' defaults to 'VIRTUAL'

     Revision 1.21  2000/02/04 19:48:28  derek
      - Fixed two instances where $ui wasn't being accessed to include font tags

     Revision 1.20  2000/02/04 19:28:45  derek
      - Changed Cancel button on View page to Return to List and modified flow
        to reflect the change
      - Added tons of CGI HTML code to make the Chromium interface look better
      - Added ui method that has defaults for colors and fonts that are used
        in the newly designed skin-like interfaces
      - Added Greg's adminclass method to return the project specific admin
        super class
      - Fixed display bug in HTML_textarea where content fields weren't being
        broken up into paragraphs in View mode
      - Added flow to display_row method to check for content fields and break
        them into two rows for the key/value pair

     Revision 1.19  2000/02/03 03:42:35  zack
     Documentation fixes and updates

     Revision 1.18  2000/01/31 02:00:19  adam
      - dbh was using a GLOBAL flag to see if had already set the
       $r->register_cleanup.  That was bad since the global was living beyond
       each hit.  In the end, the DBH wasn't being cleared after every hit.
       So now it uses the Apache notes to store the flag.
     - display_row() - oops...  thats not the variable name!

     "The best laid plans..."

     Revision 1.17  2000/01/30 04:30:46  adam
      - using an HTMl fieldtype of 'row' makes display_row() not print table
       tags, it just prints the results of the method $_().

     Revision 1.16  2000/01/27 22:12:17  colin
     Added cgi() and marked CGI_obj() as deprecated (evil music here).
     Added some \%qoptions to HTML_file

     Revision 1.15  2000/01/27 01:17:14  colin
     - finished HTML_file(). Also, due to popular request, display_modify() now uses
       $q->start_multipart_form() instead of $q->startform().
     - Well, it actually wasn't a *popular* request, but when the email went out asking
       if anyone had problems with it there was no response.
     Ever. And that's good enough for me!

     Revision 1.14  2000/01/25 20:55:48  colin
     added:
     postmodify_handler()
     postadd_handler()
     hidden_fields()
     display_list_buttons()
     display_modify_buttons()

     HooHah!

     Revision 1.13  2000/01/24 22:19:39  dougw
     Adam added adminuri

     Revision 1.12  2000/01/24 22:11:03  colin
     added some Center tags.

     Revision 1.11  2000/01/21 22:08:24  colin
     added display_start_html().

     Revision 1.9  2000/01/21 21:35:26  colin
     took out an extra warn(). my bad.

     Revision 1.6  2000/01/12 22:43:35  adam
      - removed Carbon::debug

     Revision 1.5  2000/01/11 02:30:19  zack
     HTML_textarea() now accepts a -WRAP option (default 'NONE')
     HTML_checkbox() works with "add" functionality

     Revision 1.4  1999/12/21 00:51:57  zack
     implemented selections. added selection()

     Revision 1.3  1999/12/05 04:05:38  greg
     new - fixed _db_class to be generic instead of hard coded to 'Mogwai'
     dbh - now handles the cleanup of cached dbh instead of Data

     Revision 1.2  1999/12/04 23:48:08  greg
     fixed POD errors

     Revision 1.1.1.1  1999/12/03 20:10:40  adam
     START

SEE ALSO
========

   perl(1).

KNOWN BUGS
==========

   None

TODO
====

   * HTML_checkbox - needs work

   * HTML_checkboxes (for multiple checkboxes)

   * HTML_radio

   * HTML_file - needs work

   * HTML_popup - should support getting a hashref or a coderef as the
     LABELS or VALUES

   * HTML_date - Only supports PST (hardcoded text)

   * HTML_date - should it be some DateTime dependant? Is there a way to
     make it more universal?

   * HTML_date - Needs to be able to show hours and minutes in a flexable
     way.

   * HTML_date - Needs ability to display time in 24 hour time. (Fix in
     get_data as well).

   * display_modify, view, list - need class data to control HTML options
     like title, table sizes etc...

   * get_data - needs to be able to get times as well as dates in 24hr and
     12hr formats.

   * %fields - figure out how fields hash would pass other options to HTML
     methods

   * %fields - figure out how to structure relationship info (many2many
     vs. many2one)

   * %fields - figure out how to structure sanity information in hash

   * Should flow be broken up into different methods based on displaymode.

   * Flow should be controllable with class data.  ie. to View before
     Modify.  Search before List.

   * display_search() - needs to be added.

   * Apache error page (nicer then Server Error)

   * New class variable for adminpath (Where that thing can be
     administered).

   * Add seperator method (for drawing HRs) between column edit things.

   * HTML_scrolling (or any method that relates) - Can link to that
     methods view page for that object.

   * HTML methods should use options hash from fields hash.

   * HTML_popup - doesn't totally work because I don't know how one 2 many
     carbon relationships     work.  I am also not sure if I want to
     structure the class data the way I did.  It also     doesn't support
     composite primary keys (how would it?)

   * need HTML_popupwindow method which lets users select related items
     from a js pop-up window.     (See Derek's Code or CyberStore Code)

   * have AUTLOAD create dynamic methods

   * dbh() - doesn't use Carboniums dbh.  Doesn't cache dbh object.
     Should just     call Carboniums dbh. (or uses object's dbh.)

COPYRIGHT
=========

     Copyright (c) 2000, Cnation Inc. All Rights Reserved. This module is free
     software. It may be used, redistributed and/or modified under the terms
     of the GNU Lesser General Public License as published by the Free Software
     Foundation.

     You should have received a copy of the GNU Lesser General Public License
     along with this library; if not, write to the Free Software Foundation, Inc.,
     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

AUTHORS
=======

     Adam Pisoni <adam@cnation.com>

Cobalt display parent class containing generic methods
******************************************************

NAME
====

   BingoX::Cobalt - Cobalt display parent class containing generic methods

SYNOPSIS
========

   use BingoX::Cobalt;

     # $BR - Blessed Reference
     # $SV - Scalar Value
     # @AV - Array Value
     # $HR - Hash Ref
     # $AR - Array Ref
     # $SR - Stream Ref

     # $proto - BingoX::Cobalt object OR sub-class
     # $object - BingoX::Cobalt object

   CONSTRUCTORS

     $BR = $proto->new( [ $app, $dbh, ] $data_object );
     $BR = $proto->get( [ $dbh, ] \%params );

   STREAM CONSTRUCTOR METHODS

     $SR = $proto->stream_obj( $app [, $dbh, ] @_ );
     $SR = $proto->stream_hash( [ $dbh, ] @_ );
     $SR = $proto->stream_array( [ $dbh, ] @_ );

   LIST CONSTRUCTOR METHODS

     $AR = $proto->list_obj( $app [, $dbh, ] @_ );
     $AR = $proto->list_hash( [ $dbh, ] @_ );
     $AR = $proto->list_array( [ $dbh, ] @_ );

   RELATION METHODS

     $SR = $object->stream_related( $rel_display_class [, \@fields] [, \@sort] [, $unary_rev_flag ] );
     $AR = $object->list_related( $rel_display_class [, \@fields] [, \@sort] [, $unary_rev_flag ] );

   OBJECT METHODS

     $BR = $object->db_obj(  );
     $BR = $object->dbh(  );
     $BR = $object->app(  );
     $BR = $proto->r(  );
     $BR = $proto->cgi(  );
     $BR = $proto->conf(  );

   PARSER METHODS

     $SV = $object->include( @_ );
     $SV = $object->xinclude( @_ );

   CLASS DATA ACCESSOR METHODS

     $SV = $proto->data_class(  );
     $HR = $proto->display_fields(  );
     $AR = $proto->display_order(  );

REQUIRES
========

   BingoX::Time, CGI, Carp, strict

EXPORTS
=======

   Nothing

DESCRIPTION
===========

   Cobalt provides the generic API for BingoX display classes.  Cobalt
uses display objects that wrap Carbon data objects (Cobalt mono Carbide?).

CLASS VARIABLES
===============

   Classes that inherit from Cobalt should have the following class
variables:

REQUIRED
--------

   * @display_order

     The order in which to display fields (if one so chose to display them
     ;)

OPTIONAL
--------

   * $data_class

     The name of the data class that corresponds to the display class. If
     this value is not defined, it will default to the name of the display
     class, with the first instance of "::Display::" changed to "::Data::".

   * %display_fields

     A total mystery. If this variable is not defined, eack key is an
     field from the `@display_order' variable, and each value is 1.

METHODS
=======

CONSTRUCTORS
------------

new ( [ $app ] [, $dbh ], $data_obj )
     Given a data object, returns a Display object of the class *it was
     called as*.  This means you could concievably provide a data object
     of a totally inapproriate type, and this method will not compain
     about it.

get ( [ $app ] [, $dbh, ] \%params )
     Returns a display object.

STREAM METHODS
--------------

`stream_obj' ( $app [, $dbh ], @_ )
     Returns an stream (CODE ref) that will return objects (See list_obj)
     If you don't know how to use streams, use list_obj() instead.

`stream_hash' ( [ $dbh, ] @_ )
     Forwards to $class->data_class->stream_hash

`stream_array' ( [ $dbh, ] @_ )
     Forwards to $class->data_class->stream_array

LIST METHODS
------------

`list_obj' ( $app [, $dbh, ] @_ )
     Returns an array ref of Display objects. Used mainly by Apache::XPP
     (the BingoX default parser) coders. Everyone  else is probably using
     $self->data_class->list_obj().

`list_hash' ( [ $dbh, ] @_ )
     Forwards to $class->data_class->list_hash

`list_array' ( [ $dbh, ] @_ )
     Forwards to $class->data_class->list_array

`show_obj' ( $app [, $dbh ] [, \%params ] [, $template ] )
     Behaves just like list_obj() or stream_obj() but will xinclude each
     object in a passed $template. Normally called by AUTOLOAD (via a
     show_* call), but you can call it explicitly if you like. Pass $app
     and $dbh if it's called statically.

RELATION METHODS
----------------

`stream_related' ( $rel_display_class [, \@fields] [, \@sort] [, $unary_rev_flag ] )
     Returns a stream of related display objects from the
     $rel_display_class class.

list_related( $rel_display_class [, \@fields] [, \@sort] [, $unary_rev_flag ] )
     Returns an array ref of related display objects from the
     $rel_display_class class.

OBJECT METHODS
--------------

`db_obj' (  )
     Returns the Data object for the Display Class that it was called
     from, with the constraint being: map $q->param( $_ ) @{
     $data_class->primary_keys }

`hour_menu' ( $name [, $default ] [, $24hr ] )
     Returns a Popup Menu with Hours.

`min_menu' ( $name [, $default ] )
     Returns a Popup Menu with Minutes.

`am_pm_menu' ( $name [, $default ] )
     Returns a Popup Menu with AM/PM menus.

`day_menu' ( $name [, $default ] )
     Returns a Popup Menu with the Days of the Month.

`month_menu' ( $name [, $default ] )
     Returns a Popup Menu with the Months of the Year.

`year_menu' ( $name [, $default ] )
     Returns a Popup Menu with a list of Years up to 20 years from now.

`errors_list' (  )
     Returns list of errors in list format.

`alink' ( \%params, $text | \@text )
     Returns a hyper link with the params passed to it, -HREF, -JAVASCRIPT.

`submit' ( $name, %params )
     Returns a Submit Button with the params passed to it, -NAME, -VALUE,
     -JAVASCRIPT.

`image_button' ( $name, %params )
     Returns a hyper link with the params passed to it, -HREF, -SRC,
     -BORDER, -ALT, -JAVASCRIPT.

`textfield' ( $name, %params )
     Returns a Text Field with the params passed to it, -VALUE, -SIZE,
     -OVERRIDE.

hidden ( $name, %params )
     Returns a Hidden Field with the params passed to it, -VALUE.

`popup_menu' ( $name, %params )
     Returns a Popup Menu with the params passed to it, -VALUES, -LABELS,
     -OVERRIDE.

`checkbox' ( $name, %params )
     Returns a Checkbox with the params passed to it, -VALUE, -LABEL,
     -OVERRIDE.

`checkbox_group' ( $name, %params )
     Returns a Checkbox Button Group with the params passed to it,
     -VALUES, -LABELS, OVERRIDE.

`radio_group' ( $name, %params )
     Returns a Radio Button Group with the params passed to it, -NAME,
     -VALUES, -LABELS, -DEFAULT, -OVERRIDE.

`get_default' (  )
     Gets the default value for the field name requested.

app (  )
     Returns the object's Application Object.

dbh (  )
     Returns the object's database handle.

r (  )
     Returns Apache Request object.

cgi (  )
     Returns the display object's internal CGI object (or makes a new one)

`conf' (  )
     Returns the conf object.

date (  )
     Returns the display object's internal date object (or makes a new one)

PARSER METHODS
--------------

` include ' ( @_ )
     Forwards to $app->include

` xinclude ' ( @_ )
     Forwards to $app->xinclude

CLASS VARIABLE METHODS
----------------------

`adminuri' (  )
     Returns class defined URI as a string.

`data_class' (  )
     Returns the data class for the current display class (from the class
     variable `$data_class').

`display_fields' (  )
     Returns the class variable %{"${class}::display_fields"} as a hash
     reference.

`display_order' (  )
     Returns the class variable @{"${class}::display_order"} as an array
     reference.

`title_field' (  )
     Returns the title field for the current display class (from the class
     variable `data_class').

`date_fields' (  )
     Returns the date fields for the current display class (from the class
     variable `data_class').

`content_fields' (  )
     Returns the content fields for the current display class (from the
     class variable `data_class').

`relations' (  )
     Returns the relations for the current display class (from the class
     variable `data_class').

`primary_keys' (  )
     Returns the primary keys for the current display class (from the class
     variable `data_class').

`foreign_keys' (  )
     Returns the foreign keys for the current display class (from the class
     variable `data_class').

`cpkey' (  )
     Returns the cpkey for the current display class (from the class
     variable `db_obj').

_get_default ( $name )
     Returns the default (exitisting) value for a form field.

REVISION HISTORY
================

     $Log: Cobalt.pm,v $
     Revision 2.15  2000/12/12 18:53:36  useevil
      - updated version for new release:  1.92

     Revision 2.14  2000/10/20 00:26:40  zhobson
     stream_* now returns blessed streams a la Carbon

     Revision 2.13  2000/10/17 00:49:55  dweimer
     - added adminuri()

     Revision 2.12  2000/09/19 23:41:46  dweimer
     Version update 1.91

     Revision 2.11  2000/09/12 00:49:17  david
     Fixed several accessor methods to be pure object methods.

     Revision 2.10  2000/09/07 20:00:34  thai
      - changed all occurrances of DateTime::Date to BingoX::Time

     Revision 2.9  2000/08/31 21:54:18  greg
     Added COPYRIGHT information.
     Added file COPYING (LGPL).
     Cleaned up POD.
     Moved into BingoX namespace.
     References to Bingo::XPP now point to Apache::XPP.

     "To the first approximation, syntactic sugar is trivial to implement.
      To the second approximation, the first approximation is totally bogus."
     	-Larry Wall

     Revision 2.8  2000/08/08 22:19:51  thai
      - there were two foreign_keys() when one should be relations()

     Revision 2.7  2000/08/03 20:49:13  thai
      - added methods:
      	title_field()
     	date_fields()
     	primary_keys()
     	foreign_keys()
     	cpkey()
     	relations()
     	content_fields()

     Revision 2.6  2000/08/01 00:44:43  thai
      - changed $debug to undef

     Revision 2.5  2000/07/13 22:20:04  thai
      - added new methods:
     		date/time menus
     		HTML form methods
     		get_default()
     		_get_default()
     		date()
      - changed methods:
     		db_obj() will now iterate through primary keys
     		cgi() will try to get the cgi object from the app()
     		r() will try to get r from the app()
     		conf() will try to get conf from the app()
     		dbh() will try to get dbh from the app()

     Revision 2.4  2000/07/12 19:29:39  thai
      - fixed POD, cleaned up code

     Revision 2.3  2000/06/24 03:16:37  dougw
     Added return undef to stream_related

     Revision 2.2  2000/05/31 02:39:20  greg
     changed use of s/.*:// to substr(...) in AUTOLOAD for efficiency.

     Revision 2.1  2000/05/19 01:25:25  thai
      - cleaned up code
      - is now part of the Bingo user space

     Revision 2.0  2000/05/02 00:54:33  thai
      - committed as 2.0

     Revision 1.9  2000/04/26 23:46:19  dougw
     AUTOLOAD now checks for $self::data_class before using $self->data_class
     this fixes a problem caused when a Display class that doesn't have a
     corresponding data_class calls use on a data class.

     Revision 1.8  2000/03/27 22:12:11  zack
     display_order() and display_fields() were using the data class
     instead of the display class, so they were always returning
     emtpy lists. Wow.

     Revision 1.7  2000/03/20 22:22:02  colin
     added show_obj()

     Revision 1.6  2000/03/15 20:14:15  zack
     Allow passing of cache/sort arrayrefs (a la stream_*) to get()

     Revision 1.5  2000/03/14 21:05:36  thai
      - returns undef if data_class->list_obj() returns undef

     Revision 1.4  2000/03/14 01:40:54  thai
      - fixed list_obj() to deref whats returned from data_class->list_obj()
        or [ ], it would fail miserably if not

     Revision 1.3  2000/03/07 23:43:13  zack
     Modified data_Class() so the class field is no longer required.
     Updated documentation

     Revision 1.2  2000/02/03 03:08:23  zack
     Fixed some documentation errors and inaccuracies, documented $data_class

     Revision 1.1  1999/11/04 20:51:15  greg
     First commit of generic Display class for the bingo model.

REVISION HISTORY (Xwing: Display.pm)
====================================

     Revision 1.4  1999/10/28 21:58:35  thai
      - added more methods to handle many FORM elements
      - image_button methods added for process, destroy,
        recalculate, and so on...

     Revision 1.3  1999/10/28 00:32:12  greg
     Combined with a more complete Display class (from Gonzo). This should be moved
     into the bingo project, and kept as one distinct thing...

     Revision 1.2  1999/10/20 23:41:53  greg
     Added method r to return the Apache request object.

     Revision 1.1  1999/10/12 00:02:07  thai
      - initial commit
      - partially functional, just does nothing

     I guess you could say its a "GNDN"

SEE ALSO
========

   perl(1).

KNOWN BUGS
==========

   None

TODO
====

   Nothing yet... anybody have suggestions?

COPYRIGHT
=========

     Copyright (c) 2000, Cnation Inc. All Rights Reserved. This module is free
     software. It may be used, redistributed and/or modified under the terms
     of the GNU Lesser General Public License as published by the Free Software
     Foundation.

     You should have received a copy of the GNU Lesser General Public License
     along with this library; if not, write to the Free Software Foundation, Inc.,
     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

AUTHORS
=======

     Colin Bielen <colin@cnation.com>
     Greg Williams <greg@cnation.com>

Time display parent class containing generic methods
****************************************************

NAME
====

   BingoX::Time - Time display parent class containing generic methods

SYNOPSIS
========

   use BingoX::Time;

   CONSTRUCTORS

     $BR = $proto->new( [ $time ] [, $data_object ] );

   OBJECT METHODS

     $date->month_full;
     $date->month_full2abrv;

     $date->months_list;
     $date->months_full_list;

     $date->months;
     $date->months_pad;
     $date->months_full;
     $date->months_full_pad;
     $date->month_abrv;

     $date->int_months;
     $date->int_months_full;

     $date->last_day;
     $date->last_days;

     $date->is_leap_year;

     $date->hours24;
     $date->hours;
     $date->minutes;

REQUIRES
========

     strict
     Date::Parse
     Date::Language
     Date::Language::English
     Time::Object

EXPORTS
=======

   localtime, gmtime

DESCRIPTION
===========

   Time provides an OO interface to Time/Dates, ala Time::Object.

METHODS
=======

new ( [ $time ] [, $islocal ] )
     This is a Time::Object overloaded constructor that can take as values
     the time in seconds, or defaults to 'time'.  It can also take the
     $islocal flag, which tells _mktime() to use localtime (1) or gmtime
     (0).  It always returns a BingoX Time Object.

     _mktime(  )

     This is a Time::Object overloaded constructor that take as values the
     time in seconds, and the $islocal flag, which tells it to use
     localtime (1) or gmtime (0).  It returns a BingoX Time Object or
     Time::Object depending on whether it was called from a sub class.  If
     it was called as a 'wantarray' it will return the contents returned
     localtime, or gmtime depending on the $islocal flag.

`str2time' ( $string )
     This is method is used to parse your default date format into a format
     that str2time understands, such as:

          Date: 961221               (yymmdd)
          Date: 12-21-96             (mm-dd-yy)    ( '-', '.' or '/' )
          Date: 12-June-96           (dd-month-yy) ( '-', '.' or '/' )
          Date: June 12 96 00:00PM   (month dd yy hh:mmPM)
          Date: June 12 96 00::00:00 (month dd yy hh:mm::ss)

     If time is not passed then time defaults to 00:00:00.

`time2str' ( $format )
     For compatibility for the older DateTime::Date modules.  Passes the
     $format to strftime.

`time_local' (  )
     For compatibility for the older DateTime::Date modules.  Returns
     $self->epoch.

`month_full' (  )
     Returns the full month string based on the integer month.

`month_full2abrv' (  )
     Returns the abbreviated (3 char) month string based on the full month
     name.

`months_list' (  )
     Returns an array ref of abbreviated months.

`months_full_list' (  )
     Returns an array ref of months.

`months' (  )
     Returns a hash ref of abbreviated months.  With the keys being the
     true month value (1 .. 12).

`months_full' (  )
     Returns a hash ref of full month names.  With the keys being the true
     month value (1 .. 12).

`month_abrv' (  )
     Returns a hash ref of abbreviated months.  With the keys being the
     full month name.

`int_months' (  )
     Returns a hash ref of abbreviated months.  With the keys being the
     integer month value (0 .. 12).

`int_months_full' (  )
     Returns a hash ref of full month names.  With the keys being the
     integer month value (0 .. 12).

`last_day' ( [ $mon ] [, $year ] )
     Returns the last day of the of the month and year passed.  If nothing
     is passed then it uses the objects month and year.  Month is the
     integer month 0 .. 11, and year is the 4 digit year.

`last_days' (  )
     Returns a hash ref of the last day for each month.  The keys are the
     integer months (0 .. 11).

`is_leap_year' (  )
     Returns true if the year is a leap year.

`hours24' (  )
     Returns an array ref of hours in 24hr time.

hours (  )
     Returns an array ref of hours in 12hr time.  Padded with zeros.

minutes (  )
     Returns an array ref of minutes (0 .. 60).  Padded with zeros.

REVISION HISTORY
================

     $Log: Time.pm,v $
     Revision 1.10  2000/12/12 18:54:34  useevil
      - updated version for new release:  1.92

     Revision 1.9  2000/11/15 19:38:50  useevil
      - added str2time()
      - fixed bug in new() where $time was always defined

     Revision 1.8  2000/10/17 00:49:04  dweimer
     Merged over thai's commit, comment below:

     - added time2str() and time_local() for former users of DateTime::Date

     Revision 1.7  2000/09/19 23:42:07  dweimer
     Version update 1.91

     Revision 1.6  2000/09/13 20:10:42  thai
      - added use Data::Language::English

     Revision 1.5  2000/09/13 18:17:21  david
     Data::Dumper only loaded if $debug is on.

     Revision 1.4  2000/09/08 05:18:53  thai
      - added:
          month_full()
          month_full2abrv()
      - updated the POD documentation

     Revision 1.3  2000/09/08 00:56:09  thai
      - fixed the POD errors per Smeg's request

     Revision 1.2  2000/09/07 22:27:32  thai
      - added:
          last_day()
          last_days()
          is_leap_year()

     Revision 1.1  2000/09/07 18:27:57  thai
      - has ousted DateTime::Date as the default date/time class
      - sub classes Time::Object

SEE ALSO
========

   Time::Object, perl(1).

KNOWN BUGS
==========

   None

TODO
====

   Nothing yet... anybody have suggestions?

COPYRIGHT
=========

   Copyright (c) 2000, Cnation Inc. All Rights Reserved. This module is
free software. It may be used, redistributed and/or modified under the
terms of the GNU Lesser General Public License as published by the Free
Software Foundation.

   You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

AUTHORS
=======

     Thai Nguyen <thai@cnation.com>

Handler for AlignIO Formats
***************************

NAME
====

   Bio::AlignIO - Handler for AlignIO Formats

SYNOPSIS
========

     use Bio::AlignIO;

     $in  = Bio::AlignIO->new(-file => "inputfilename" , '-format' => 'fasta');
     $out = Bio::AlignIO->new(-file => ">outputfilename" , '-format' => 'pfam');
     # note: we quote -format to keep older perl's from complaining.

     while ( my $aln = $in->next_aln() ) {
     	$out->write_aln($aln);
     }

   or

     use Bio::AlignIO;

     $in  = Bio::AlignIO->newFh(-file => "inputfilename" , '-format' => 'fasta');
     $out = Bio::AlignIO->newFh('-format' => 'pfam');

     # World's shortest Fasta<->pfam format converter:
     print $out $_ while <$in>;

DESCRIPTION
===========

   Bio::AlignIO is a handler module for the formats in the AlignIO set (eg,
Bio::AlignIO::fasta). It is the officially sanctioned way of getting at
the alignment objects, which most people should use.

   The idea is that you request a stream object for a particular format.
All the stream objects have a notion of an internal file that is read from
or written to. A particular AlignIO object instance is configured for
either input or output. A specific example of a stream object is the
Bio::AlignIO::fasta object.

   Each stream object has functions

     $stream->next_aln();

   and

     $stream->write_aln($aln);

   also

     $stream->type() # returns 'INPUT' or 'OUTPUT'

   As an added bonus, you can recover a filehandle that is tied to the
AlignIO object, allowing you to use the standard <> and print operations
to read and write sequence objects:

     use Bio::AlignIO;

     $stream = Bio::AlignIO->newFh(-format => 'Fasta'); # read from standard input

     while ( $aln = <$stream> ) {
     	# do something with $aln
     }

   and

     print $stream $aln; # when stream is in output mode

   This makes the simplest ever reformatter

     #!/usr/local/bin/perl

     $format1 = shift;
     $format2 = shift || die "Usage: reformat format1 format2 < input > output";

     use Bio::AlignIO;

     $in  = Bio::AlignIO->newFh(-format => $format1 );
     $out = Bio::AlignIO->newFh(-format => $format2 );
     #note: you might want to quote -format to keep older perl's from complaining.

     print $out $_ while <$in>;

   AlignIO.pm is patterned on the module SeqIO.pm and shares most the
SeqIO.pm features.  One significant difference currently is that
AlignIO.pm only handles IO for a single alignment at a time (SeqIO.pm
handles IO for multiple sequences in a single stream.)  The principal
reason for this is that whereas simultaneously handling multiple sequences
is a common requirement, simultaneous handling of multiple alignments is
not. Capability for IO for more than one multiple alignment (which may be
of use for certain applications such as IO for Pfam libraries) may be
included in the future.  For this reason we keep the name "next_aln()" for
the alignment input routine, even though currently only one alignment is
read (or written) at a time and the name "read_aln()" might be more
appropriate.

CONSTRUCTORS
============

Bio::AlignIO->new()
-------------------

     $seqIO = Bio::AlignIO->new(-file => 'filename',   -format=>$format);
     $seqIO = Bio::AlignIO->new(-fh   => \*FILEHANDLE, -format=>$format);
     $seqIO = Bio::AlignIO->new(-format => $format);

   The new() class method constructs a new Bio::AlignIO object.  The
returned object can be used to retrieve or print BioAlign objects. new()
accepts the following parameters:

-file
     A file path to be opened for reading or writing.  The usual Perl
     conventions apply:

          'file'       # open file for reading
          '>file'      # open file for writing
          '>>file'     # open file for appending
          '+<file'     # open file read/write
          'command |'  # open a pipe from the command
          '| command'  # open a pipe to the command

-fh
     You may provide new() with a previously-opened filehandle.  For
     example, to read from STDIN:

          $seqIO = Bio::AlignIO->new(-fh => \*STDIN);

     Note that you must pass filehandles as references to globs.

     If neither a filehandle nor a filename is specified, then the module
     will read from the @ARGV array or STDIN, using the familiar <>
     semantics.

-format
     Specify the format of the file.  Supported formats include:

          fasta       FASTA format
          pfam        pfam format
          selex       selex (hmmer) format
          stockholm   stockholm format
          prodom      prodom (protein domain) format
          clustalw    clustalw (.aln) format
          msf         msf (GCG) format
          mase        mase (seaview) format

     Currently only those formats which were implemented in SimpleAlign.pm
     have been incorporated in AlignIO.pm.  Specifically, mase, stockholm
     and prodom have only been implemented for input. Clustalw format has
     only been implemented for output.

     If no format is specified and a filename is given, then the module
     will attempt to deduce it from the filename.  If this is unsuccessful,
     Fasta format is assumed.

     The format name is case insensitive.  'FASTA', 'Fasta' and 'fasta' are
     all supported.

Bio::AlignIO->newFh()
---------------------

     $fh = Bio::AlignIO->newFh(-fh   => \*FILEHANDLE, -format=>$format);
     $fh = Bio::AlignIO->newFh(-format => $format);
     # etc.

   This constructor behaves like new(), but returns a tied filehandle
rather than a Bio::AlignIO object.  You can read sequences from this
object using the familiar <> operator, and write to it using print().  The
usual array and $_ semantics work.  For example, you can read all sequence
objects into an array like this:

     @sequences = <$fh>;

   Other operations, such as read(), sysread(), write(), close(), and
printf() are not supported.

OBJECT METHODS
==============

   See below for more detailed summaries.  The main methods are:

$alignment = $AlignIO->next_aln()
---------------------------------

   Fetch an alignment from a formatted file.

$AlignIO->write_aln($aln)
-------------------------

   Write the specified alignment to a file..

TIEHANDLE(), READLINE(), PRINT()
--------------------------------

   These provide the tie interface.  See Perltie (perl.info),
for more details.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org               - General discussion
     http://bio.perl.org/MailList.html   - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Peter Schattner
========================

   Email: schattner@alum.mit.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
---

     Title   : new
     Usage   : $stream = Bio::AlignIO->new(-file => $filename, -format => 'Format')
     Function: Returns a new seqstream
     Returns : A Bio::AlignIO::Handler initialised with the appropriate format
     Args    : -file => $filename
               -format => format
               -fh => filehandle to attach to

newFh
-----

     Title   : newFh
     Usage   : $fh = Bio::AlignIO->newFh(-file=>$filename,-format=>'Format')
     Function: does a new() followed by an fh()
     Example : $fh = Bio::AlignIO->newFh(-file=>$filename,-format=>'Format')
               $sequence = <$fh>;   # read a sequence object
               print $fh $sequence; # write a sequence object
     Returns : filehandle tied to the Bio::AlignIO::Fh class
     Args    :

fh
--

     Title   : fh
     Usage   : $obj->fh
     Function:
     Example : $fh = $obj->fh;      # make a tied filehandle
               $sequence = <$fh>;   # read a sequence object
               print $fh $sequence; # write a sequence object
     Returns : filehandle tied to the Bio::AlignIO::Fh class
     Args    :

_load_format_module
-------------------

     Title   : _load_format_module
     Usage   : *INTERNAL AlignIO stuff*
     Function: Loads up (like use) a module at run time on demand
     Example :
     Returns :
     Args    :

next_aln
--------

     Title   : next_aln
     Usage   : $aln = stream->next_aln
     Function: reads the next $aln object from the stream
     Returns : a Bio::Seq sequence object
     Args    :

write_aln
---------

     Title   : write_aln
     Usage   : $stream->write_aln($aln)
     Function: writes the $aln object into the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::Seq object

close
-----

     Title   : close
     Usage   : $seqio->close()
     Function: Closes the file handle associated with this seqio system
     Example :
     Returns :
     Args    :

_print
------

     Title   : _print
     Usage   : $obj->_print(@lines)
     Function:
     Example :
     Returns : writes output

_readline
---------

     Title   : _readline
     Usage   : $obj->_readline($newval)
     Function:
     Example :
     Returns : reads a line of input

_filehandle
-----------

     Title   : _filehandle
     Usage   : $obj->_filehandle($newval)
     Function:
     Example :
     Returns : value of _filehandle
     Args    : newvalue (optional)

_guess_format
-------------

     Title   : _guess_format
     Usage   : $obj->_guess_format($filename)
     Function:
     Example :
     Returns : guessed format of filename (lower case)
     Args    :

bl2seq sequence input/output stream
***********************************

NAME
====

   Bio::AlignIO::bl2seq - bl2seq sequence input/output stream

SYNOPSIS
========

   Do not use this module directly.  Use it via the Bio::AlignIO class, as
in:

     use Bio::AlignIO;

     $in  = Bio::AlignIO->new(-file => "inputfilename" , '-format' => 'bl2seq');
     $aln = $in->next_aln();

DESCRIPTION
===========

   This object can create Bio::SimpleAlign sequence alignment objects (of
2 sequences) from bl2seq BLAST reports.

   A nice feature of this module is that- in combination with
StandAloneBlast.pm or remote blasting - it can be used to align 2
sequences and make a SimpleAlign object from them which can then be
manipulated using any SimpleAlign.pm methods, eg:

     #Get 2 sequences
     $str = Bio::SeqIO->new(-file=>'t/amino.fa' , '-format' => 'Fasta', );
     my $seq3 = $str->next_seq();
     my $seq4 = $str->next_seq();

     # Run bl2seq on them
     $factory = Bio::Tools::StandAloneBlast->new('program' => 'blastp',
     					       'outfile' => 'bl2seq.out');
     my $bl2seq_report = $factory->bl2seq($seq3, $seq4);

     # Use AlignIO.pm to create a SimpleAlign object from the bl2seq report
     $str = Bio::AlignIO->new(-file=> 'bl2seq.out','-format' => 'bl2seq');
     $aln = $str->next_aln();

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org               - General discussion
     http://bio.perl.org/MailList.html   - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Peter Schattner
========================

   Email: schattner@alum.mit.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_aln
--------

     Title   : next_aln
     Usage   : $aln = $stream->next_aln()
     Function: returns the next alignment in the stream.
     Returns : SimpleAlign object - returns 0 on end of file
     	    or on error
     Args    : NONE

write_aln
---------

     Title   : write_aln
     Usage   : $stream->write_aln(@aln)
     Function: writes the $aln object into the stream in bl2seq format
     Returns : 1 for success and 0 for error
     Args    : Bio::SimpleAlign object

clustalw sequence input/output stream
*************************************

NAME
====

   Bio::AlignIO::clustalw - clustalw sequence input/output stream

SYNOPSIS
========

   Do not use this module directly.  Use it via the Bio::AlignIO class.

DESCRIPTION
===========

   This object can transform Bio::SimpleAlign objects to and from clustalw
flat file databases.

FEEDBACK
========

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHORS - Peter Schattner
=========================

   Email: schattner@alum.mit.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_aln
--------

     Title   : next_aln
     Usage   : $aln = $stream->next_aln()
     Function: returns the next alignment in the stream
     Returns : SimpleAlign object
     Args    : NONE

write_aln
---------

     Title   : write_aln
     Usage   : $stream->write_aln(@aln)
     Function: writes the clustalw-format object (.aln) into the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::SimpleAlign object

fasta sequence input/output stream
**********************************

NAME
====

   Bio::AlignIO::fasta - fasta sequence input/output stream

SYNOPSIS
========

   Do not use this module directly.  Use it via the Bio::AlignIO class.

DESCRIPTION
===========

   This object can transform Bio::SimpleAlign objects to and from fasta
flat file databases.

FEEDBACK
========

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHORS - Peter Schattner
=========================

   Email: schattner@alum.mit.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_aln
--------

     Title   : next_aln
     Usage   : $aln = $stream->next_aln()
     Function: returns the next alignment in the stream.
     Returns : SimpleAlign object - returns 0 on end of file
     	    or on error
     Args    : NONE

write_aln
---------

     Title   : write_aln
     Usage   : $stream->write_aln(@aln)
     Function: writes the $aln object into the stream in fasta format
     Returns : 1 for success and 0 for error
     Args    : Bio::SimpleAlign object

mase sequence input/output stream
*********************************

NAME
====

   Bio::AlignIO::mase - mase sequence input/output stream

SYNOPSIS
========

   Do not use this module directly.  Use it via the Bio::AlignIO class.

DESCRIPTION
===========

   This object can transform Bio::SimpleAlign objects to and from mase flat
file databases.

FEEDBACK
========

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHORS - Peter Schattner
=========================

   Email: schattner@alum.mit.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_aln
--------

     Title   : next_aln
     Usage   : $aln = $stream->next_aln()
     Function: returns the next alignment in the stream.
     Returns : SimpleAlign object
     Args    : NONE

write_aln
---------

     Title   : write_aln
     Usage   : $stream->write_aln(@aln)
     Function: writes the $aln object into the stream in mase format  ###Not yet implemented!###
     Returns : 1 for success and 0 for error
     Args    : Bio::SimpleAlign object

msf sequence input/output stream
********************************

NAME
====

   Bio::AlignIO::msf - msf sequence input/output stream

SYNOPSIS
========

   Do not use this module directly.  Use it via the Bio::AlignIO class.

DESCRIPTION
===========

   This object can transform Bio::SimpleAlign objects to and from msf flat
file databases.

FEEDBACK
========

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHORS - Peter Schattner
=========================

   Email: schattner@alum.mit.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_aln
--------

     Title   : next_aln
     Usage   : $aln = $stream->next_aln()
     Function: returns the next alignment in the stream. Tries to read *all* MSF
              It reads all non whitespace characters in the alignment
              area. For MSFs with weird gaps (eg ~~~) map them by using
              $al->map_chars('~','-')
     Returns : SimpleAlign object
     Args    : NONE

write_aln
---------

     Title   : write_aln
     Usage   : $stream->write_aln(@aln)
     Function: writes the $aln object into the stream in MSF format
     Returns : 1 for success and 0 for error
     Args    : Bio::SimpleAlign object

pfam sequence input/output stream
*********************************

NAME
====

   Bio::AlignIO::pfam - pfam sequence input/output stream

SYNOPSIS
========

   Do not use this module directly.  Use it via the Bio::AlignIO class.

DESCRIPTION
===========

   This object can transform Bio::SimpleAlign objects to and from pfam flat
file databases.

FEEDBACK
========

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHORS - Peter Schattner
=========================

   Email: schattner@alum.mit.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_aln
--------

     Title   : next_aln
     Usage   : $aln = $stream->next_aln()
     Function: returns the next alignment in the stream
     Returns : SimpleAlign object
     Args    : NONE

write_aln
---------

     Title   : write_aln
     Usage   : $stream->write_aln(@aln)
     Function: writes the $aln object into the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::SimpleAlign object

prodom sequence input/output stream
***********************************

NAME
====

   Bio::AlignIO::prodom - prodom sequence input/output stream

SYNOPSIS
========

   Do not use this module directly.  Use it via the Bio::AlignIO class.

DESCRIPTION
===========

   This object can transform Bio::SimpleAlign objects to and from prodom
flat file databases.

FEEDBACK
========

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHORS - Peter Schattner
=========================

   Email: schattner@alum.mit.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_aln
--------

     Title   : next_aln
     Usage   : $aln = $stream->next_aln()
     Function: returns the next alignment in the stream.
     Returns : SimpleAlign object
     Args    : NONE

write_aln
---------

     Title   : write_aln
     Usage   : $stream->write_aln(@aln)
     Function: writes the $aln object into the stream in prodom format  ###Not yet implemented!###
     Returns : 1 for success and 0 for error
     Args    : Bio::SimpleAlign object

selex sequence input/output stream
**********************************

NAME
====

   Bio::AlignIO::selex - selex sequence input/output stream

SYNOPSIS
========

   Do not use this module directly.  Use it via the Bio::AlignIO class.

DESCRIPTION
===========

   This object can transform Bio::SimpleAlign objects to and from selex
flat file databases.

FEEDBACK
========

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHORS - Peter Schattner
=========================

   Email: schattner@alum.mit.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_aln
--------

     Title   : next_aln
     Usage   : $aln = $stream->next_aln()
     Function: returns the next alignment in the stream. Tries to read *all* selex
              It reads all non whitespace characters in the alignment
              area. For selexs with weird gaps (eg ~~~) map them by using
              $al->map_chars('~','-')
     Returns : SimpleAlign object
     Args    : NONE

write_aln
---------

     Title   : write_aln
     Usage   : $stream->write_aln(@aln)
     Function: writes the $aln object into the stream in selex format
     Returns : 1 for success and 0 for error
     Args    : Bio::SimpleAlign object

stockholm sequence input/output stream
**************************************

NAME
====

   Bio::AlignIO::stockholm - stockholm sequence input/output stream

SYNOPSIS
========

   Do not use this module directly.  Use it via the Bio::AlignIO class.

DESCRIPTION
===========

   This object can transform Bio::SimpleAlign objects to and from
stockholm flat file databases.

FEEDBACK
========

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHORS - Peter Schattner
=========================

   Email: schattner@alum.mit.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_aln
--------

     Title   : next_aln
     Usage   : $aln = $stream->next_aln()
     Function: returns the next alignment in the stream.
     Returns : SimpleAlign object
     Args    : NONE

write_aln
---------

     Title   : write_aln
     Usage   : $stream->write_aln(@aln)
     Function: writes the $aln object into the stream in stockholm format  ###Not yet implemented!###
     Returns : 1 for success and 0 for error
     Args    : Bio::SimpleAlign object

A generic object for annotations
********************************

NAME
====

   Bio::Annotation - A generic object for annotations

SYNOPSIS
========

     # get an annotation somehow in $ann

     # description is a simple, one line description
     print "Description is ",$ann->description, "\n";

     foreach $genename ( $self->each_gene_name() ) {
     	print "gene name: $genename\n";
     }

     foreach $comment ( $ann->each_Comment ) {
        # $comment is a Bio::Annotation::Comment object
        print "Comment: ", $comment->text(), "\n";
     }

     foreach $link ( $ann->each_DBLink ) {
        # link is a Bio::Annotation::DBLink object
        print "Link to ",$link->primary_id, " in database", $link->database, "\n";
     }

     foreach $ref ( $ann->each_Reference ) {
        # link is a Bio::Annotation::Reference object
        print "Reference title ", $ref->title , "\n";
     }

     #
     # Making an annotation object from scratch
     #

     $ann = Bio::Annotation->new();

     $ann->description("Description text");
     print "Annotation description is ", $ann->description, "\n";

DESCRIPTION
===========

   The object represents generic biological annotation of an object. It
has the ability to provide

     a brief, one line description
     free text comments
     links to other biological objects
     references to literature

   It does not have the following abilities

     The basis (experimental/non experimental/homology)
        of the annotation. This is considered to be part of
        the object which owns the annotation. This is
        because the type of relevant basis is usually
        dependent on the object

     The previous revisions of the object
        This should be a property of whatever database this
        object comes from

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email birney@ebi.ac.uk

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
---

     Title   : new
     Usage   : $annotation = Bio::Annotation->new( '-description' => 'a description line');
     Function: Makes a new Annotation object. The main thing
               you will want to do with this is add comment objects and
               dblink objects, with calls like

     $annotation->add_Comment($comment);
     $annotation->add_DBLink($dblink);

     Example :
     Returns : a new Bio::Annotation Object
     Args    : hash, potentially with one field, -description

description
-----------

     Title   : description
     Usage   : $obj->description($newval)
     Function:
     Example :
     Returns : value of description
     Args    : newvalue (optional)

add_gene_name
-------------

     Title   : add_gene_name
     Usage   : $self->add_gene_name($name1[,$name2,...])
     Function: adds a reference object
     Example :
     Returns :
     Args    : a string, or a list of strings

remove_gene_name
----------------

     Title   : remove_gene_name
     Usage   : $self->remove_gene_name($index)
     Function: removes a particular gene name
     Example :
     Returns :
     Args    : index of the name to remove

each_gene_name
--------------

     Title   : each_gene_name
     Usage   : foreach $genename ( $self->each_gene_name() ) {
                   print "seq has gene name $genename\n";
               }
     Function: gets the array of gene names
     Example :
     Returns : an array of strings
     Args    :

add_Reference
-------------

     Title   : add_Reference
     Usage   : $self->add_Reference($ref1[,$ref2,...])
     Function: adds a reference object
     Example :
     Returns :
     Args    : a Bio::Annotation::Reference or derived object

remove_Reference
----------------

     Title   : remove_Reference
     Usage   : $self->remove_Reference($index)
     Function: removes a reference object
     Example :
     Returns :
     Args    : index number from references array

each_Reference
--------------

     Title   : each_Reference
     Usage   : foreach $ref ( $self->each_Reference() )
     Function: gets an array of reference
     Example :
     Returns : an array of Bio::Annotation::Reference or derived objects
     Args    :

add_Comment
-----------

     Title   : add_Comment
     Usage   : $self->add_Comment($ref)
     Function: adds a Comment object
     Example :
     Returns :
     Args    : a Bio::Annotation::Comment or derived object

remove_Comment
--------------

     Title   : remove_Comment
     Usage   : $self->remove_Comment($index)
     Function: removes a comment object
     Example :
     Returns :
     Args    : index number from comments array

each_Comment
------------

     Title   : each_Comment
     Usage   : foreach $ref ( $self->each_Comment() )
     Function: gets an array of Comment of objects
     Example :
     Returns : an array of Bio::Annotation::Comment or derived objects
     Args    : none

add_DBLink
----------

     Title   : add_DBLink
     Usage   : $self->add_DBLink($ref)
     Function: adds a link object
     Example :
     Returns :
     Args    : a Bio::Annotation::DBLink or derived object

remove_DBLink
-------------

     Title   : remove_DBLink
     Usage   : $self->remove_DBLink($index)
     Function: removes a DBLink object
     Example :
     Returns :
     Args    : index number from links array

each_DBLink
-----------

     Title   : each_DBLink
     Usage   : foreach $ref ( $self->each_DBlink() )
     Function: gets an array of DBlink of objects
     Example :
     Returns : an array of Bio::Annotation::DBlink or derived objects
     Args    :

A comment object, holding text
******************************

NAME
====

   Bio::Annotation::Comment - A comment object, holding text

SYNOPSIS
========

     $comment = Bio::Annotation::Comment->new();
     $comment->text("This is the text of this comment");
     $annotation->add_Comment($comment);

DESCRIPTION
===========

   A holder for comments in annotations, just plain text. This is a very
simple object, and justifably so.

CONTACT
=======

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
---

     Title   : new
     Usage   : $comment = Bio::Annotation::Comment->new( '-text' => 'some text for this comment');
     Function: This returns a new comment object, optionally with
               text filed
     Example :
     Returns : a Bio::Annotation::Comment object
     Args    : a hash with -text optionally set

text
----

     Title   : text
     Usage   : $value = $self->text($newval)
     Function: get/set for the text field. A comment object
               just holds a single string which is accessible through
               this method
     Example :
     Returns : value of text
     Args    : newvalue (optional)

DESCRIPTION of Object
*********************

NAME
====

   Bio::Annotation::DBLink - DESCRIPTION of Object

SYNOPSIS
========

     $link1 = new Bio::Annotation::DBLink(-database => 'TSC',
                                          -primary_id => 'TSC0000030'
     				     );

     #or

     $link2 = new Bio::Annotation::DBLink();
     $link2->database('dbSNP');
     $link2->primary_id('2367');

     # $feat is Bio::Annotation object, Bio::SeqFeature::Generic inherits it
     $feat->add_DBLink($link2);

DESCRIPTION
===========

   Provides an object which represents a link from one onbject to something
in another database without proscribing what is in the other database

CONTACT
=======

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

database
--------

     Title   : database
     Usage   : $self->database($newval)
     Function: set/get on the database string. Databases are just
               a string here which can then be interpretted elsewhere
     Example :
     Returns : value of database
     Args    : newvalue (optional)

primary_id
----------

     Title   : primary_id
     Usage   : $self->primary_id($newval)
     Function: set/get on the primary id (a string)
               The primary id is the main identifier used for this object in
               the database. Good examples would be accession numbers. The id
               is meant to be the main, stable identifier for this object
     Example :
     Returns : value of primary_id
     Args    : newvalue (optional)

optional_id
-----------

     Title   : optional_id
     Usage   : $self->optional_id($newval)
     Function: get/set for the optional_id (a string)
               optional id is a slot for people to use as they wish. The main
               issue is that some databases do not have a clean single string
               identifier scheme. It is hoped that the primary_id can behave like
               a reasonably sane "single string identifier" of objects, and people
               can use/abuse optional ids to their heart's content to provide
               precise mappings.
     Example :
     Returns : value of optional_id
     Args    : newvalue (optional)

comment
-------

     Title   : comment
     Usage   : $self->comment($newval)
     Function: get/set of comments (comment object)
               Sets or gets comments of this dblink, which is sometimes relevant
     Example :
     Returns : value of comment (Bio::Annotation::Comment)
     Args    : newvalue (optional)

Specialised DBLink object for Literature References
***************************************************

NAME
====

   Bio::Annotation::Reference - Specialised DBLink object for Literature
References

SYNOPSIS
========

     $reg = Bio::Annotation::Reference->new( -title => 'title line',
     					    -location => 'location line',
     					    -authors => 'author line',
     					    -medline => 998122 );

DESCRIPTION
===========

   Object which presents a literature reference. This is considered to be
a specialised form of database link. The additional methods provided are
all set/get methods to store strings commonly associated with references,
in particular title, location (ie, journal page) and authors line.

   There is no attempt to do anything more than store these things as
strings for processing elsewhere. This is mainly because parsing these
things suck and generally are specific to the specific format one is
using. To provide an easy route to go format -> object -> format without
losing data, we keep them as strings. Feel free to post the list for a
better solution, but in general this gets very messy very fast...

CONTACT
=======

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
---

     Title   : new
     Usage   : $ref = Bio::Annotation::Reference->new( -title => 'title line',
     						   -authors => 'author line',
     						   -location => 'location line',
     						   -medline => 9988812);
     Function:
     Example :
     Returns : a new Bio::Annotation::Reference object
     Args    : a hash with optional title, authors, location, medline, start and end
               attributes

start
-----

     Title   : start
     Usage   : $self->start($newval)
     Function: Gives the reference start base
     Example :
     Returns : value of start
     Args    : newvalue (optional)

rp
--

     Title   : rp
     Usage   : $self->rp($newval)
     Function: Gives the RP line. No attempt is made to parse this line.
     Example :
     Returns : value of rp
     Args    : newvalue (optional)

authors
-------

     Title   : authors
     Usage   : $self->authors($newval)
     Function: Gives the author line. No attempt is made to parse the author line
     Example :
     Returns : value of authors
     Args    : newvalue (optional)

location
--------

     Title   : location
     Usage   : $self->location($newval)
     Function: Gives the location line. No attempt is made to parse the location line
     Example :
     Returns : value of location
     Args    : newvalue (optional)

title
-----

     Title   : title
     Usage   : $self->title($newval)
     Function: Gives the title line (if exists)
     Example :
     Returns : value of title
     Args    : newvalue (optional)

medline
-------

     Title   : medline
     Usage   : $self->medline($newval)
     Function: Gives the medline number
     Example :
     Returns : value of medline
     Args    : newvalue (optional)

pubmed
------

     Title   : pubmed
     Usage   : $refobj->pubmed($newval)
     Function: Get/Set the PubMed number, if it is different from the MedLine
               number.
     Example :
     Returns : value of medline
     Args    : newvalue (optional)

database
--------

     Title   : database
     Usage   :
     Function: Overrides DBLink database to be hard coded to 'MEDLINE', unless
               the database has been set explicitely before.
     Example :
     Returns :
     Args    :

primary_id
----------

     Title   : primary_id
     Usage   :
     Function: Overrides DBLink primary_id to provide medline number
     Example :
     Returns :
     Args    :

optional_id
-----------

     Title   : optional_id
     Usage   :
     Function: Overrides DBLink optional_id to provide the PubMed number.
     Example :
     Returns :
     Args    :

Database object interface to ACeDB servers
******************************************

NAME
====

   Bio::DB::Ace - Database object interface to ACeDB servers

SYNOPSIS
========

     $db = Bio::DB::Ace->new( -server => 'myace.server.com', port => '120000');

     $seq = $db->get_Seq_by_id('MUSIGHBA1'); # Unique ID

     # or ...

     $seq = $db->get_Seq_by_acc('J00522'); # Accession Number

DESCRIPTION
===========

   This provides a standard BioPerl database access to Ace, using Lincoln
Steins excellent AcePerl module. You need to download and install the
aceperl module from

     http://stein.cshl.org/AcePerl/

   before this interface will work.

   This interface is designed at the moment to work through a
aceclient/aceserver type mechanism

INSTALLING ACEPERL
==================

   Download the latest aceperl tar file, gunzip/untar and cd into the
directory.  This is a standard CPAN-style directory, so if you go

     Perl Makefile.PL
     make
     <become root>
     make install

   Then you will have installed Aceperl. Use the PREFIX mechanism to
install elsewhere.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org              - General discussion
     http://bioperl.org/MailList.shtml  - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email birney@sanger.ac.uk

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

get_Seq_by_id
-------------

     Title   : get_Seq_by_id
     Usage   : $seq = $db->get_Seq_by_id($uid);
     Function: Gets a Bio::Seq object by its unique identifier/name
     Returns : a Bio::Seq object
     Args    : $id : the id (as a string) of the desired sequence entry

get_Seq_by_acc
--------------

     Title   : get_Seq_by_acc
     Usage   : $seq = $db->get_Seq_by_acc($acc);
     Function: Gets a Bio::Seq object by its accession number
     Returns : a Bio::Seq object
     Args    : $acc : the accession number of the desired sequence entry

_aceobj
-------

     Title   : _aceobj
     Usage   : $ace = $db->_aceobj();
     Function: Get/Set on the acedb object
     Returns : Ace object
     Args    : New value of the ace object

Abstract interface for a sequence database
******************************************

NAME
====

   Bio::DB::BioSeqI - Abstract interface for a sequence database

SYNOPSIS
========

     #
     # get a database object somehow using a concrete class
     #

     $seq = $db->get_Seq_by_id('ROA1_HUMAN');

     #
     # $seq is a Bio::Seq object
     #

DESCRIPTION
===========

   This is a pure interface class - in other words, all this does is define
methods which other (concrete) classes will actually implement.

   The Bio::DB::BioSeqI class defines what methods a generic database class
should have. At the moment it is just the ability to make Bio::Seq objects
from a name (id) or a accession number.

CONTACT
=======

   Ewan Birney originally wrote this class.

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

get_Seq_by_id
-------------

     Title   : get_Seq_by_id
     Usage   : $seq = $db->get_Seq_by_id('ROA1_HUMAN')
     Function: Gets a Bio::Seq object by its name
     Returns : a Bio::Seq object
     Args    : the id (as a string) of a sequence
     Throws  : "id does not exist" exception

get_Seq_by_acc
--------------

     Title   : get_Seq_by_acc
     Usage   : $seq = $db->get_Seq_by_acc('X77802');
     Function: Gets a Bio::Seq object by accession number
     Returns : A Bio::Seq object
     Args    : accession number (as a string)
     Throws  : "acc does not exist" exception

Database object interface to GDB HTTP query
*******************************************

NAME
====

   Bio::DB::GDB - Database object interface to GDB HTTP query

SYNOPSIS
========

     $gdb = new Bio::DB::GDB;

     $info = $gdb->get_info(-type=>'marker',
     			     -id=>'D1S243'); # Marker name

     print "genbank id is ", $info->{'gdbid'},
      "\nprimers are (fwd, rev) ", join(",", @{$info->{'primers'}}),
      "\nproduct length is ", $info->{'length'}, "\n";

DESCRIPTION
===========

   This class allows connections to the Genome Database (GDB) and queries
to retrieve any database objects. See http://www.gdb.org/ or any mirror
for details.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists. Your participation is much appreciated.

     bioperl-l@bioperl.org              - General discussion
     http://bioperl.org/MailList.shtml  - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Jason Stajich
======================

   Email jason@chg.mc.duke.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

ua
--

     Title   : ua
     Usage   : my $ua = $self->ua or
               $self->ua($ua)
     Function: Get/Set a LWP::UserAgent for use
     Returns : reference to LWP::UserAgent Object
     Args    : $ua - must be a LWP::UserAgent

get_params       Title   : get_params  Usage   : my %params = $self->get_params($mode)  Function: Returns key,value pairs to be passed to query             for mode ('marker', 'gene')  Returns : a key,value pair hash  Args    : 'marker' or 'gene' mode for retrieval
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

get_info
--------

     Title   : get_info
     Usage   : my $info = $self->get_info(-type => 'marker',
     				      -id   => 'D1S234');
     Function: Returns key,value pairs specific
     Returns : a key,value pair hash
     Args    : -type => 'marker' or 'gene' mode for retrieval
               -id   => unique id to query for

get_request
-----------

     Title   : get_request
     Usage   : my $url = $self->get_request
     Function: HTTP::Request
     Returns :
     Args    : %qualifiers = a hash of qualifiers (ids, format, etc)

Database object interface to GenBank
************************************

NAME
====

   Bio::DB::GenBank - Database object interface to GenBank

SYNOPSIS
========

     $gb = new Bio::DB::GenBank;

     $seq = $gb->get_Seq_by_id('MUSIGHBA1'); # Unique ID

     # or ...

     $seq = $gb->get_Seq_by_acc('J00522'); # Accession Number

     # or ... best when downloading very large files, prevents
     # keeping all of the file in memory

     # also don't want features, just sequence so let's save bandwith
     # and request Fasta sequence
     $gb = new Bio::DB::GenBank(-retrievaltype => 'tempfile' ,
     			       -format => 'Fasta');
     my $seqio = $gb->get_Stream_by_acc(['AC013798', 'AC021953'] );
     while( my $clone =  $seqio->next_seq ) {
       print "cloneid is ", $clone->
     }

DESCRIPTION
===========

   Allows the dynamic retrieval of Sequence objects (Bio::Seq) from the
GenBank database at NCBI, via an Entrez query.

   WARNING: Please do NOT spam the Entrez web server with multiple
requests.  NCBI offers Batch Entrez for this purpose.  Batch Entrez
support will likely be supported in a future version of DB::GenBank.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists. Your participation is much appreciated.

     bioperl-l@bioperl.org              - General discussion
     http://bioperl.org/MailList.shtml  - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Aaron Mackey, Jason Stajich
====================================

   Email amackey@virginia.edu Email jason@chg.mc.duke.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

get_params
----------

     Title   : get_params
     Usage   : my %params = $self->get_params($mode)
     Function: Returns key,value pairs to be passed to NCBI database
               for either 'batch' or 'single' sequence retrieval method
     Returns : a key,value pair hash
     Args    : 'single' or 'batch' mode for retrieval

Routines Bio::DB::WebDBSeqI from Bio::DB::RandomAccessI
=======================================================

get_Seq_by_id
-------------

     Title   : get_Seq_by_id
     Usage   : $seq = $db->get_Seq_by_id('ROA1_HUMAN')
     Function: Gets a Bio::Seq object by its name
     Returns : a Bio::Seq object
     Args    : the id (as a string) of a sequence
     Throws  : "id does not exist" exception

get_Seq_by_acc
--------------

     Title   : get_Seq_by_acc
     Usage   : $seq = $db->get_Seq_by_acc($acc);
     Function: Gets a Seq object by accession numbers
     Returns : a Bio::Seq object
     Args    : the accession number as a string
     Note    : For GenBank, this just calls the same code for get_Seq_by_id()
     Throws  : "id does not exist" exception

Routines implemented by Bio::DB::NCBIHelper
===========================================

get_request
-----------

     Title   : get_request
     Usage   : my $url = $self->get_request
     Function: HTTP::Request
     Returns :
     Args    : %qualifiers = a hash of qualifiers (ids, format, etc)

get_Stream_by_batch
-------------------

     Title   : get_Stream_by_batch
     Usage   : $seq = $db->get_Stream_by_batch($ref);
     Function: Retrieves Seq objects from Entrez 'en masse', rather than one
               at a time.  For large numbers of sequences, this is far superior
               than get_Stream_by_[id/acc]().
     Example :
     Returns : a Bio::SeqIO stream object
     Args    : $ref : either an array reference, a filename, or a filehandle
               from which to get the list of unique ids/accession numbers.

get_Stream_by_id
----------------

     Title   : get_Stream_by_id
     Usage   : $stream = $db->get_Stream_by_id( [$uid1, $uid2] );
     Function: Gets a series of Seq objects by unique identifiers
     Returns : a Bio::SeqIO stream object
     Args    : $ref : a reference to an array of unique identifiers for
                      the desired sequence entries

get_Stream_by_acc
-----------------

     Title   : get_Stream_by_acc
     Usage   : $seq = $db->get_Stream_by_acc([$acc1, $acc2]);
     Function: Gets a series of Seq objects by accession numbers
     Returns : a Bio::SeqIO stream object
     Args    : $ref : a reference to an array of accession numbers for
                      the desired sequence entries
     Note    : For GenBank, this just calls the same code for get_Stream_by_id()

   1; __END__

Database object interface to GenPept
************************************

NAME
====

   Bio::DB::GenPept - Database object interface to GenPept

SYNOPSIS
========

     $gb = new Bio::DB::GenPept;

     $seq = $gb->get_Seq_by_id('195055'); # Unique ID

     # or ...

     $seq = $gb->get_Seq_by_acc('DEECTH'); # Accession Number

     my $seqio = $gb->get_Stream_by_id(['195055', 'DEECTH']);
     while( my $seq = $seqio->next_seq ) {
     	print "seq is is ", $seq->display_id, "\n";
     }

DESCRIPTION
===========

   Allows the dynamic retrieval of Sequence objects (Bio::Seq) from the
GenPept database at NCBI, via an Entrez query.

   WARNING: Please do NOT spam the Entrez web server with multiple
requests.  NCBI offers Batch Entrez for this purpose.  Batch Entrez
support will likely be supported in a future version of DB::GenPept.

   Currently the only return format supported by NCBI Entrez for GenPept
database is GenPept format, so any format specification passed to GenPept
will be ignored still be forced to GenPept format (which is just GenBank
format).

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists. Your participation is much appreciated.

     bioperl-l@bioperl.org              - General discussion
     http://bioperl.org/MailList.shtml  - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Aaron Mackey, Jason Stajich
====================================

   Email amackey@virginia.edu Email jason@chg.mc.duke.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

get_params
----------

     Title   : get_params
     Usage   : my %params = $self->get_params($mode)
     Function: Returns key,value pairs to be passed to NCBI database
               for either 'batch' or 'single' sequence retrieval method
     Returns : a key,value pair hash
     Args    : 'single' or 'batch' mode for retrieval

default_format
--------------

     Title   : default_format
     Usage   : my $format = $self->default_format
     Function: Returns default sequence format for this module
     Returns : string
     Args    : none

Routines from Bio::DB::WebDBSeqI and Bio::DB::RandomAccessI
===========================================================

get_Seq_by_id
-------------

     Title   : get_Seq_by_id
     Usage   : $seq = $db->get_Seq_by_id('ROA1_HUMAN')
     Function: Gets a Bio::Seq object by its name
     Returns : a Bio::Seq object
     Args    : the id (as a string) of a sequence
     Throws  : "id does not exist" exception

get_Stream_by_acc
-----------------

     Title   : get_Stream_by_acc
     Usage   : $seq = $db->get_Seq_by_acc($acc);
     Function: Gets a series of Seq objects by accession numbers
     Returns : a Bio::SeqIO stream object
     Args    : $ref : a reference to an array of accession numbers for
                      the desired sequence entries
     Note    : For GenBank, this just calls the same code for get_Stream_by_id()

Routines implemented by Bio::DB::NCBIHelper
===========================================

get_request
-----------

     Title   : get_request
     Usage   : my $url = $self->get_request
     Function: HTTP::Request
     Returns :
     Args    : %qualifiers = a hash of qualifiers (ids, format, etc)

get_Stream_by_batch
-------------------

     Title   : get_Stream_by_batch
     Usage   : $seq = $db->get_Stream_by_batch($ref);
     Function: Retrieves Seq objects from Entrez 'en masse', rather than one
               at a time.  For large numbers of sequences, this is far superior
               than get_Stream_by_[id/acc]().
     Example :
     Returns : a Bio::SeqIO stream object
     Args    : $ref : either an array reference, a filename, or a filehandle
               from which to get the list of unique ids/accession numbers.

get_Stream_by_id
----------------

     Title   : get_Stream_by_id
     Usage   : $stream = $db->get_Stream_by_id( [$uid1, $uid2] );
     Function: Gets a series of Seq objects by unique identifiers
     Returns : a Bio::SeqIO stream object
     Args    : $ref : a reference to an array of unique identifiers for
                      the desired sequence entries

get_Stream_by_acc (2)
---------------------

     Title   : get_Stream_by_acc
     Usage   : $seq = $db->get_Seq_by_acc($acc);
     Function: Gets a series of Seq objects by accession numbers
     Returns : a Bio::SeqIO stream object
     Args    : $ref : a reference to an array of accession numbers for
                      the desired sequence entries
     Note    : For GenBank, this just calls the same code for get_Stream_by_id()

request_format
--------------

     Title   : request_format
     Usage   : my $format = $self->request_format;
               $self->request_format($format);
     Function: Get/Set sequence format retrieval
     Returns : string representing format
     Args    : $format = sequence format

A collection of routines useful for queries to NCBI databases.
**************************************************************

NAME
====

   Bio::DB::NCBIHelper - A collection of routines useful for queries to
NCBI databases.

SYNOPSIS
========

     Do not use this module directly.
     # get a Bio::DB::NCBIHelper object somehow
     my $seqio = $db->get_Stream_by_acc(['MUSIGHBA1']);
     foreach my $seq ( $seqio->next_seq ) {
      # process seq
     }

DESCRIPTION
===========

   Provides a single place to setup some common methods for querying NCBI
web databases.  This module is just centralizes the methods for
constructing a URL for querying NCBI GenBank and NCBI GenPept and the
common HTML stripping done in `postprocess_data' in this node().

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists. Your participation is much appreciated.

     bioperl-l@bioperl.org              - General discussion
     http://bioperl.org/MailList.shtml  - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Jason Stajich
======================

   Email jason@chg.mc.duke.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

get_params
----------

     Title   : get_params
     Usage   : my %params = $self->get_params($mode)
     Function: Returns key,value pairs to be passed to NCBI database
               for either 'batch' or 'single' sequence retrieval method
     Returns : a key,value pair hash
     Args    : 'single' or 'batch' mode for retrieval

default_format
--------------

     Title   : default_format
     Usage   : my $format = $self->default_format
     Function: Returns default sequence format for this module
     Returns : string
     Args    : none

get_request
-----------

     Title   : get_request
     Usage   : my $url = $self->get_request
     Function: HTTP::Request
     Returns :
     Args    : %qualifiers = a hash of qualifiers (ids, format, etc)

get_Stream_by_batch
-------------------

     Title   : get_Stream_by_batch
     Usage   : $seq = $db->get_Stream_by_batch($ref);
     Function: Retrieves Seq objects from Entrez 'en masse', rather than one
               at a time.  For large numbers of sequences, this is far superior
               than get_Stream_by_[id/acc]().
     Example :
     Returns : a Bio::SeqIO stream object
     Args    : $ref : either an array reference, a filename, or a filehandle
               from which to get the list of unique ids/accession numbers.

postprocess_data
----------------

     Title   : postprocess_data
     Usage   : $self->postprocess_data ( 'type' => 'string',
     				     'location' => \$datastr);
     Function: process downloaded data before loading into a Bio::SeqIO
     Returns : void
     Args    : hash with two keys - 'type' can be 'string' or 'file'
                                  - 'location' either file location or string
                                               reference containing data

request_format
--------------

     Title   : request_format
     Usage   : my ($req_format, $ioformat) = $self->request_format;
               $self->request_format("genbank");
               $self->request_format("fasta");
     Function: Get/Set sequence format retrieval. The get-form will normally not
               be used outside of this and derived modules.
     Returns : Array of two strings, the first representing the format for
               retrieval, and the second specifying the corresponding SeqIO format.
     Args    : $format = sequence format

Abstract interface for a sequence database
******************************************

NAME
====

   Bio::DB::RandomAccessI - Abstract interface for a sequence database

SYNOPSIS
========

     #
     # get a database object somehow using a concrete class
     #

     $seq = $db->get_Seq_by_id('ROA1_HUMAN');

     #
     # $seq is a Bio::Seq object
     #

DESCRIPTION
===========

   This is a pure interface class - in other words, all this does is define
methods which other (concrete) classes will actually implement.

   The Bio::DB::RandomAccessI class defines what methods a generic
database class should have. At the moment it is just the ability to make
Bio::Seq objects from a name (id) or a accession number.

CONTACT
=======

   Ewan Birney originally wrote this class.

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

get_Seq_by_id
-------------

     Title   : get_Seq_by_id
     Usage   : $seq = $db->get_Seq_by_id('ROA1_HUMAN')
     Function: Gets a Bio::Seq object by its name
     Returns : a Bio::Seq object
     Args    : the id (as a string) of a sequence
     Throws  : "id does not exist" exception

get_Seq_by_acc
--------------

     Title   : get_Seq_by_acc
     Usage   : $seq = $db->get_Seq_by_acc('X77802');
     Function: Gets a Bio::Seq object by accession number
     Returns : A Bio::Seq object
     Args    : accession number (as a string)
     Throws  : "acc does not exist" exception

Abstract Interface for Sequence databases
*****************************************

NAME
====

   Bio::DB::SeqI - Abstract Interface for Sequence databases

SYNOPSIS
========

     # get a Bio::DB::SeqI somehow

     $seq = $seqdb->get_Seq_by_id('some-id');
     $seq = $seqdb->get_Seq_by_acc('some-accession-number');

     @ids = $seqdb->get_all_ids();
     $stream = $seqdb->get_PrimarySeq_stream();
     while((my $seq = $stream->next_seq()) {
        # $seq is a PrimarySeqI compliant object
     }

DESCRIPTION
===========

   Abstract interface for a sequence database

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     vsns-bcd-perl@lists.uni-bielefeld.de          - General discussion
     vsns-bcd-perl-guts@lists.uni-bielefeld.de     - Technically-oriented discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email birney@ebi.ac.uk

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

Methods inherieted from Bio::DB::RandomAccessI
==============================================

get_Seq_by_id
-------------

     Title   : get_Seq_by_id
     Usage   : $seq = $db->get_Seq_by_id('ROA1_HUMAN')
     Function: Gets a Bio::Seq object by its name
     Returns : a Bio::Seq object
     Args    : the id (as a string) of a sequence
     Throws  : "id does not exist" exception

get_Seq_by_acc
--------------

     Title   : get_Seq_by_acc
     Usage   : $seq = $db->get_Seq_by_acc('X77802');
     Function: Gets a Bio::Seq object by accession number
     Returns : A Bio::Seq object
     Args    : accession number (as a string)
     Throws  : "acc does not exist" exception

Methods [that were] specific for Bio::DB::SeqI
==============================================

get_PrimarySeq_stream
---------------------

     Title   : get_PrimarySeq_stream
     Usage   : $stream = get_PrimarySeq_stream
     Function: Makes a Bio::DB::SeqStreamI compliant object
               which provides a single method, next_primary_seq
     Returns : Bio::DB::SeqStreamI
     Args    : none

get_all_primary_ids
-------------------

     Title   : get_all_ids
     Usage   : @ids = $seqdb->get_all_primary_ids()
     Function: gives an array of all the primary_ids of the
               sequence objects in the database. These
               maybe ids (display style) or accession numbers
               or something else completely different - they
               *are not* meaningful outside of this database
               implementation.
     Example :
     Returns : an array of strings
     Args    : none

get_Seq_by_primary_id
---------------------

     Title   : get_Seq_by_primary_id
     Usage   : $seq = $db->get_Seq_by_primary_id($primary_id_string);
     Function: Gets a Bio::Seq object by the primary id. The primary
               id in these cases has to come from $db->get_all_primary_ids.
               There is no other way to get (or guess) the primary_ids
               in a database.

     The other possibility is to get Bio::PrimarySeqI objects
     via the get_PrimarySeq_stream and the primary_id field
     on these objects are specified as the ids to use here.
      Returns : A Bio::Seq object
      Args    : accession number (as a string)
      Throws  : "acc does not exist" exception

Database object interface to SwissProt retrieval
************************************************

NAME
====

   Bio::DB::SwissProt - Database object interface to SwissProt retrieval

SYNOPSIS
========

     use Bio::DB::SwissProt;

     $sp = new Bio::DB::SwissProt;

     $seq = $sp->get_Seq_by_id('P43780'); # SwissProtID
     # or ...
     $seq = $sp->get_Seq_by_acc('P43780'); # SwissProtID
     # can only query on SwissProtID at expasy right now

     # choose a different server to query
     $sp = new Bio::DB::SwissProt('-hostlocation' => 'canada');

     $seq = $sp->get_Seq_by_id('P43780'); # SwissProtID

DESCRIPTION
===========

   Allows the dynamic retrieval of Sequence objects (Bio::Seq) from the
SwissProt database via an expasy retrieval.  Perhaps through SRS later.

   In order to make changes transparent we have host type (currently only
expasy) and location (default to switzerland) separated out.  This allows
the user to pick the closest expasy mirror for running their queries.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                         - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Jason Stajich
======================

   Email Jason Stajich <jason@chg.mc.duke.edu>

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

Routines from Bio::DB::WebDBSeqI
================================

get_request
-----------

     Title   : get_request
     Usage   : my $url = $self->get_request
     Function: returns a HTTP::Request object
     Returns :
     Args    : %qualifiers = a hash of qualifiers (ids, format, etc)

postprocess_data
----------------

     Title   : postprocess_data
     Usage   : $self->postprocess_data ( 'type' => 'string',
     				     'location' => \$datastr);
     Function: process downloaded data before loading into a Bio::SeqIO
     Returns : void
     Args    : hash with two keys - 'type' can be 'string' or 'file'
                                  - 'location' either file location or string
                                               reference containing data

default_format
--------------

     Title   : default_format
     Usage   : my $format = $self->default_format
     Function: Returns default sequence format for this module
     Returns : string
     Args    : none

Bio::DB::SwissProt specific routines
====================================

servertype
----------

     Title   : servertype
     Usage   : my $servertype = $self->servertype
               $self->servertype($servertype);
     Function: Get/Set server type
     Returns : string
     Args    : server type string [optional]

hostlocation
------------

     Title   : hostlocation
     Usage   : my $location = $self->hostlocation()
              $self->hostlocation($location)
     Function: Set/Get Hostlocation
     Returns : string representing hostlocation
     Args    : string specifying hostlocation [optional]

location_url
------------

     Title   : location
     Usage   : my $url = $self->location_url()
     Function: Get host url
     Returns : string representing url
     Args    : none

An interface for writing to a database of sequences.
****************************************************

NAME
====

   Bio::DB::UpdateableSeqI - An interface for writing to a database of
sequences.

SYNOPSIS
========

     # get a Bio::DB::UpdateableSeqI somehow
     eval {
     	my ( @updatedseqs, @newseqs, @deadseqs);
     	my $seq = $db->get_Seq_by_id('ROA1_HUMAN');
     	$seq->desc('a new description');

     	push @updatedseqs, $seq;

     $db->write_seq(\@updatedseqs, \@newseqs, \@deadseqs);
         };
         if( $@ ) {
     print STDERR "an error when trying to write seq : $@\n";
         }

DESCRIPTION
===========

   This module seeks to provide a simple method for pushing sequence
changes back to a Sequence Database - which can be an SQL compliant
database, a file based database, AceDB, etc.

AUTHOR
======

   Jason Stajich <jason@chg.mc.duke.edu>

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bioperl.org
     http://www.bioperl.org/bioperl-bugs/

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

write_seq
---------

     Title   : write_seq
     Usage   : write_seq(\@updatedseqs, \@addedseqs, \@deadseqs)
     Function: updates sequences in first array,
               adds sequences in the second array,
               and removes sequences in the third array.
     Example :
     Returns :
     Args    : arrays of sequence objects that must be obtained from
               Bio::DB::UpdateableSeqI.

_add_seq
--------

     Title   : _add_seq
     Usage   : _add_seq($seq)
     Function: Adds a new sequence
     Example :
     Returns : will throw an exception if
               sequences accession number already exists
     Args    : a new seq object - should have an accession number

_remove_seq
-----------

     Title   : _remove_seq
     Usage   : _remove_seq($seq)
     Function: Removes an existing sequence
     Example :
     Returns : will throw an exception if
               sequence does not exists for the primary_id
     Args    : a seq object that was retrieved from Bio::DB::UpdateableSeqI

_update_seq
-----------

     Title   : _update_seq
     Usage   : _update_seq($seq)
     Function: Updates a sequence
     Example :
     Returns : will throw an exception if
               sequence is out of sync from expected val.
     Args    : a seq object that was retrieved from Bio::DB::UpdateableSeqI

Methods inherieted from Bio::DB::RandomAccessI
==============================================

get_Seq_by_id
-------------

     Title   : get_Seq_by_id
     Usage   : $seq = $db->get_Seq_by_id('ROA1_HUMAN')
     Function: Gets a Bio::Seq object by its name
     Returns : a Bio::Seq object
     Args    : the id (as a string) of a sequence
     Throws  : "id does not exist" exception

get_Seq_by_acc
--------------

     Title   : get_Seq_by_acc
     Usage   : $seq = $db->get_Seq_by_acc('X77802');
     Function: Gets a Bio::Seq object by accession number
     Returns : A Bio::Seq object
     Args    : accession number (as a string)
     Throws  : "acc does not exist" exception

Methods inheirited from Bio::DB::SeqI
=====================================

get_PrimarySeq_stream
---------------------

     Title   : get_PrimarySeq_stream
     Usage   : $stream = get_PrimarySeq_stream
     Function: Makes a Bio::DB::SeqStreamI compliant object
               which provides a single method, next_primary_seq
     Returns : Bio::DB::SeqStreamI
     Args    : none

get_all_primary_ids
-------------------

     Title   : get_all_ids
     Usage   : @ids = $seqdb->get_all_primary_ids()
     Function: gives an array of all the primary_ids of the
               sequence objects in the database. These
               maybe ids (display style) or accession numbers
               or something else completely different - they
               *are not* meaningful outside of this database
               implementation.
     Example :
     Returns : an array of strings
     Args    : none

get_Seq_by_primary_id
---------------------

     Title   : get_Seq_by_primary_id
     Usage   : $seq = $db->get_Seq_by_primary_id($primary_id_string);
     Function: Gets a Bio::Seq object by the primary id. The primary
               id in these cases has to come from $db->get_all_primary_ids.
               There is no other way to get (or guess) the primary_ids
               in a database.

     The other possibility is to get Bio::PrimarySeqI objects
     via the get_PrimarySeq_stream and the primary_id field
     on these objects are specified as the ids to use here.
      Returns : A Bio::Seq object
      Args    : accession number (as a string)
      Throws  : "acc does not exist" exception

Object Interface to generalize Web Databases for   retrieving sequences
***********************************************************************

NAME
====

   Bio::DB::WebDBSeqI - Object Interface to generalize Web Databases for
retrieving sequences

SYNOPSIS
========

     # get a WebDBSeqI object somehow
     # assuming it is a nucleotide db
     my $seq = $db->get_Seq_by_id('ROA1_HUMAN')

DESCRIPTION
===========

   Provides core set of functionality for connecting to a web based
database for retriving sequences.

   Users wishing to add another Web Based Sequence Dabatase will need to
extend this class (see Bio::DB::SwissProt or Bio::DB::NCBIHelper for
examples) and implement the get_request method which returns a
HTTP::Request for the specified uids (accessions, ids, etc depending on
what query types the database accepts).

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists. Your participation is much appreciated.

     bioperl-l@bioperl.org              - General discussion
     http://bioperl.org/MailList.shtml  - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Jason Stajich
======================

   Email jason@chg.mc.duke.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

get_Seq_by_id
-------------

     Title   : get_Seq_by_id
     Usage   : $seq = $db->get_Seq_by_id('ROA1_HUMAN')
     Function: Gets a Bio::Seq object by its name
     Returns : a Bio::Seq object
     Args    : the id (as a string) of a sequence
     Throws  : "id does not exist" exception

get_Seq_by_acc
--------------

     Title   : get_Seq_by_acc
     Usage   : $seq = $db->get_Seq_by_acc('X77802');
     Function: Gets a Bio::Seq object by accession number
     Returns : A Bio::Seq object
     Args    : accession number (as a string)
     Throws  : "acc does not exist" exception

get_request
-----------

     Title   : get_request
     Usage   : my $url = $self->get_request
     Function: returns a HTTP::Request object
     Returns :
     Args    : %qualifiers = a hash of qualifiers (ids, format, etc)

get_Stream_by_id
----------------

     Title   : get_Stream_by_id
     Usage   : $stream = $db->get_Stream_by_id( [$uid1, $uid2] );
     Function: Gets a series of Seq objects by unique identifiers
     Returns : a Bio::SeqIO stream object
     Args    : $ref : a reference to an array of unique identifiers for
                      the desired sequence entries

get_Stream_by_acc
-----------------

     Title   : get_Stream_by_acc
     Usage   : $seq = $db->get_Seq_by_acc([$acc1, $acc2]);
     Function: Gets a series of Seq objects by accession numbers
     Returns : a Bio::SeqIO stream object
     Args    : $ref : a reference to an array of accession numbers for
                      the desired sequence entries
     Note    : For GenBank, this just calls the same code for get_Stream_by_id()

default_format
--------------

     Title   : default_format
     Usage   : my $format = $self->default_format
     Function: Returns default sequence format for this module
     Returns : string
     Args    : none

request_format
--------------

     Title   : request_format
     Usage   : my ($req_format, $ioformat) = $self->request_format;
               $self->request_format("genbank");
               $self->request_format("fasta");
     Function: Get/Set sequence format retrieval. The get-form will normally not
               be used outside of this and derived modules.
     Returns : Array of two strings, the first representing the format for
               retrieval, and the second specifying the corresponding SeqIO format.
     Args    : $format = sequence format

get_seq_stream
--------------

     Title   : get_seq_stream
     Usage   : my $seqio = $self->get_seq_sream(%qualifiers)
     Function: builds a url and queries a web db
     Returns : a Bio::SeqIO stream capable of producing sequence
     Args    : %qualifiers = a hash qualifiers that the implementing class
               will process to make a url suitable for web querying

url_base_address
----------------

     Title   : url_base_address
     Usage   : my $address = $self->url_base_address or
               $self->url_base_address($address)
     Function: Get/Set the base URL for the Web Database
     Returns : Base URL for the Web Database
     Args    : $address - URL for the WebDatabase

proxy
-----

     Title   : proxy
     Usage   : $httpproxy = $db->proxy('http')  or
               $db->proxy(['http','ftp'], 'http://myproxy' )
     Function: Get/Set a proxy for use of proxy
     Returns : a string indicating the proxy
     Args    : $protocol : an array ref of the protocol(s) to set/get
               $proxyurl : url of the proxy to use for the specified protocol

retrieval_type
--------------

     Title   : retrieval_type
     Usage   : $self->retrieval_type($type);
               my $type = $self->retrieval_type
     Function: Get/Set a proxy for retrieval_type (io_string or tempfile)
     Returns : string representing retrieval type
     Args    : $value - the value to store

url_params
----------

     Title   : url_params
     Usage   : my $params = $self->url_params or
               $self->url_params($params)
     Function: Get/Set the URL parameters for the Web Database
     Returns : url parameters for Web Database
     Args    : $params - parameters to be appended to the URL for the WebDatabase

ua
--

     Title   : ua
     Usage   : my $ua = $self->ua or
               $self->ua($ua)
     Function: Get/Set a LWP::UserAgent for use
     Returns : reference to LWP::UserAgent Object
     Args    : $ua - must be a LWP::UserAgent

postprocess_data
----------------

     Title   : postprocess_data
     Usage   : $self->postprocess_data ( 'type' => 'string',
     				     'location' => \$datastr);
     Function: process downloaded data before loading into a Bio::SeqIO
     Returns : void
     Args    : hash with two keys - 'type' can be 'string' or 'file'
                                  - 'location' either file location or string
                                               reference containing data

Abstract interface for any object wanting to use                           database cross references
****************************************************************************************************

NAME
====

   Bio::DBLinkContainerI - Abstract interface for any object wanting to use
                       database cross references

SYNOPSIS
========

     # get an objects containing database cross reference

     foreach $obj ( @objs ) {
             if( $obj->isa('Bio::DBLinkContainerI') ) {
                     foreach $dblink ( $obj->each_DBLink() ) {
                             # do stuff
                     }
             }
     }

DESCRIPTION
===========

   This interface defines the functions one can expect for any object
wanting to use database cross-references. This class does not actually
provide any implemention, it just provides the definitions of what methods
one can call.

   The database cross-references are implemented as
Bio/Annotation/DBLink, objects.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org              - General discussion
     http://bioperl.org/MailList.shtml  - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Heikki Lehvaslaiho
===========================

   Email:  heikki@ebi.ac.uk Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

each_DBLink
-----------

     Title   : each_DBLink
     Usage   : foreach $ref ( $self->each_DBlink() )
     Function: gets an array of DBlink of objects
     Example :
     Returns : an array of Bio::Annotation::DBLink objects
     Args    : none

Base class for factory classes loading drivers
**********************************************

NAME
====

   Bio::Factory::DriverFactory - Base class for factory classes loading
drivers

SYNOPSIS
========

     #this class is not instantiable

DESCRIPTION
===========

   This a base class for factory classes that load drivers. Normally, you
don't instantiate this class directly.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                - General discussion
     http://bio.perl.org/MailList.html    - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Jason Stajich
======================

   Email Jason Stajich <jason@chg.mc.duke.edu>

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

register_driver
---------------

     Title   : register_driver
     Usage   : $factory->register_driver("genscan", "Bio::Tools::Genscan");
     Function: Registers a driver a factory class should be able to instantiate.

     This method can be called both as an instance and as a class
     method.

     Returns :
     Args    : Key of the driver (string) and the module implementing the driver
               (string).

driver_table
------------

     Title   : driver_table
     Usage   : $table = $factory->driver_table();
     Function: Returns a reference to the hash table storing associations of
               methods with drivers.

     You use this table to look up registered methods (keys) and
     drivers (values).

     In this implementation the table is class-specific and therefore
     shared by all instances. You can override this in a derived class,
     but note that this method can be called both as an instance and a
     class method.

     This will be the table used by the object internally. You should
     definitely know what you're doing if you modify the table's
     contents. Modifications are shared by _all_ instances, those present
     and those yet to be created.

     Returns : A reference to a hash table.
     Args    :

get_driver
----------

     Title   : get_driver
     Usage   : $module = $factory->get_driver("genscan");
     Function: Returns the module implementing a driver registered under the
               given key.
     Example :
     Returns : A string.
     Args    : Key of the driver (string).

_load_module
------------

     Title   : _load_module
     Usage   : $self->_load_module("Bio::Tools::Genscan");
     Function: Loads up (like use) a module at run time on demand.
     Example :
     Returns : TRUE on success
     Args    :

class capable of               creating SeqAnalysisParserI compliant parsers
****************************************************************************

NAME
====

   Bio::Factory::SeqAnalysisParserFactory - class capable of
creating SeqAnalysisParserI compliant parsers

SYNOPSIS
========

     # initialize an object implementing this interface, e.g.
     $factory = Bio::Factory::SeqAnalysisParserFactory->new();
     # find out the methods it knows about
     print "registered methods: ",
           join(', ', keys($factory->driver_table())), "\n";
     # obtain a parser object
     $parser = $factory->get_parser(-input=>$inputobj,
                                    -params=>[@params],
     		                   -method => $method);
     # $parser is an object implementing Bio::SeqAnalysisParserI
     # annotate sequence with features produced by parser
     while(my $feat = $parser->next_feature()) {
     	$seq->add_SeqFeature($feat);
     }

DESCRIPTION
===========

   This is a factory class capable of instantiating SeqAnalysisParserI
implementing parsers.

   The concept behind this class and the interface it implements
(Bio::Factory::SeqAnalysisParserFactoryI) is a generic analysis result
parsing in high-throughput automated sequence annotation pipelines. See
Bio::SeqAnalysisParserI for more documentation of this concept.

   You can always find out the methods an instance of this class knows
about by the way given in the SYNOPSIS section. By default, and assuming
that the documentation is up-to-date, this will comprise of genscan, mzef,
estscan, blast, hmmer, gff, and sim4 (all case-insensitive).

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                - General discussion
     http://bio.perl.org/MailList.html    - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp, Jason Stajich
===================================

   Email Hilmar Lapp <hlapp@gmx.net>, Jason Stajich <jason@chg.mc.duke.edu>

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

get_parser
----------

     Title   : get_parser
     Usage   : $factory->get_parser(-input=>$inputobj,
                                    [ -params=>[@params] ],
     		                -method => $method)
     Function: Creates and returns a parser object for the given input and method.
               Both file names and streams (filehandles) are allowed.

     Parameters (-params argument) are passed on to the parser object
     and therefore are specific to the parser to be created.
      Example :
      Returns : A Bio::SeqAnalysisParserI implementing object. Exception if
     creation of the parser object fails.
      Args    : B<input>  - object/file where analysis results are coming from,
     	   B<params> - parameter to use when parsing/running analysis
     	   B<method> - method of analysis

interface describing objects capable               of creating SeqAnalysisParserI compliant parsers
***************************************************************************************************

NAME
====

   Bio::Factory::SeqAnalysisParserFactoryI - interface describing objects
capable               of creating SeqAnalysisParserI compliant parsers

SYNOPSIS
========

     # initialize an object implementing this interface, e.g.
     $factory = Bio::Factory::SeqAnalysisParserFactory->new();
     # obtain a parser object
     $parser = $factory->get_parser(-input=>$inputobj,
                                    -params=>[@params],
     		                   -method => $method);
     # $parser is an object implementing Bio::SeqAnalysisParserI
     # annotate sequence with features produced by parser
     while(my $feat = $parser->next_feature()) {
     	$seq->add_SeqFeature($feat);
     }

DESCRIPTION
===========

   This is an interface for factory classes capable of instantiating
SeqAnalysisParserI implementing parsers.

   The concept behind the interface is a generic analysis result parsing
in high-throughput automated sequence annotation pipelines. See
Bio::SeqAnalysisParserI for more documentation of this concept.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                - General discussion
     http://bio.perl.org/MailList.html    - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp, Jason Stajich
===================================

   Email Hilmar Lapp <hlapp@gmx.net>, Jason Stajich <jason@chg.mc.duke.edu>

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

get_parser
----------

     Title   : get_parser
     Usage   : $factory->get_parser(-input=>$inputobj,
                                    [ -params=>[@params] ],
     		                -method => $method)
     Function: Creates and returns a parser object for the given input and method.
               The type of input which is suitable depends on the implementation,
               but a good-style implementation should allow both file names and
               streams (filehandles).

     A particular implementation may not be able to create a parser for
     the requested method. In this case it shall return undef.

     Parameters (-params argument) are passed on to the parser object
     and therefore are specific to the parser to be created. An
     implementation of this interface should make this argument optional.
      Example :
      Returns : A Bio::SeqAnalysisParserI implementing object.
      Args    : B<input>  - object/file where analysis results are coming from,
     	   B<params> - parameter to use when parsing/running analysis
     	   B<method> - method of analysis

Abstract interface for indexing a flat file
*******************************************

NAME
====

   Bio::Index::Abstract - Abstract interface for indexing a flat file

SYNOPSIS
========

   You should not be using this module directly

USING DB_FILE
=============

   To use DB_File and not SDBM for this index, pass the value:

     -dbm_package => 'DB_File'

   to new (see below).

DESCRIPTION
===========

   This object provides the basic mechanism to associate positions in
files with names. The position and filenames are stored in DBM which can
then be accessed later on. It is the equivalent of flat file indexing (eg,
SRS or efetch).

   This object is the guts to the mechanism, which will be used by the
specific objects inheriting from it.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney, James Gilbert
===================================

   Email - birney@sanger.ac.uk, jgrg@sanger.ac.uk

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with an "_" (underscore).

new
---

     Usage   : $index = Bio::Index::Abstract->new(
                   -filename    => $dbm_file,
                   -write_flag  => 0,
                   -dbm_package => 'DB_File',
                   -verbose     => 0);
     Function: Returns a new index object.  If filename is
               specified, then open_dbm() is immediately called.
               Bio::Index::Abstract->new() will usually be called
               directly only when opening an existing index.
     Returns : A new index object
     Args    : -filename    The name of the dbm index file.
               -write_flag  TRUE if write access to the dbm file is
                            needed.
               -dbm_package The Perl dbm module to use for the
                            index.
               -verbose     Print debugging output to STDERR if
                            TRUE.

filename
--------

     Title   : filename
     Usage   : $value = $self->filename();
               $self->filename($value);
     Function: Gets or sets the name of the dbm index file.
     Returns : The current value of filename
     Args    : Value of filename if setting, or none if
               getting the value.

write_flag
----------

     Title   : write_flag
     Usage   : $value = $self->write_flag();
               $self->write_flag($value);
     Function: Gets or sets the value of write_flag, which
               is wether the dbm file should be opened with
               write access.
     Returns : The current value of write_flag (default 0)
     Args    : Value of write_flag if setting, or none if
               getting the value.

dbm_package
-----------

     Usage   : $value = $self->dbm_package();
               $self->dbm_package($value);

     Function: Gets or sets the name of the Perl dbm module used.
               If the value is unset, then it returns the value of
               the package variable $USE_DBM_TYPE or if that is
               unset, then it chooses the best available dbm type,
               choosing 'DB_File' in preference to 'SDBM_File'.
               Bio::Abstract::Index may work with other dbm file
               types.

     Returns : The current value of dbm_package
     Args    : Value of dbm_package if setting, or none if
               getting the value.

db
--

     Title   : db
     Usage   : $index->db
     Function: Returns a ref to the hash which is tied to the dbm
               file.  Used internally when adding and retrieving
               data from the database.
     Example : $db = $index->db();
               $db->{ $some_key } = $data
               $data = $index->db->{ $some_key };
     Returns : ref to HASH
     Args    : NONE

get_stream
----------

     Title   : get_stream
     Usage   : $stream = $index->get_stream( $id );
     Function: Returns a file handle with the file pointer
               at the approprite place

     This provides for a way to get the actual
     file contents and not an object

     WARNING: you must parse the record deliminter
     *yourself*. Abstract wont do this for you
     So this code

     $fh = $index->get_stream($myid);
     while( <$fh> ) {
        # do something
     }
     will parse the entire file if you don't put in
     a last statement in, like

     while( <$fh> ) {
        /^\/\// && last; # end of record
        # do something
     }

     Returns : A filehandle object
     Args    : string represents the accession number
     Notes   : This method should not be used without forethought

open_dbm
--------

     Usage   : $index->open_dbm()
     Function: Opens the dbm file associated with the index
               object.  Write access is only given if explicitly
               asked for by calling new(-write => 1) or having set
               the write_flag(1) on the index object.  The type of
               dbm file opened is that returned by dbm_package().
               The name of the file to be is opened is obtained by
               calling the filename() method.

     Example : $index->_open_dbm()
     Returns : 1 on success

_version
--------

     Title   : _version
     Usage   : $type = $index->_version()
     Function: Returns a string which identifes the version of an
               index module.  Used to permanently identify an index
               file as having been created by a particular version
               of the index module.  Must be provided by the sub class
     Example :
     Returns :
     Args    : none

_code_base
----------

     Title   : _code_base
     Usage   : $code = $db->_code_base();
     Function:
     Example :
     Returns : Code package to be used with this
     Args    :

_type_and_version
-----------------

     Title   : _type_and_version
     Usage   : Called by _initalize
     Function: Checks that the index opened is made by the same index
               module and version of that module that made it.  If the
               index is empty, then it adds the information to the
               database.
     Example :
     Returns : 1 or exception
     Args    : none

_check_file_sizes
-----------------

     Title   : _check_file_sizes
     Usage   : $index->_check_file_sizes()
     Function: Verifies that the files listed in the database
               are the same size as when the database was built,
               or throws an exception.  Called by the new()
               function.
     Example :
     Returns : 1 or exception
     Args    :

make_index
----------

     Title   : make_index
     Usage   : $index->make_index( FILE_LIST )
     Function: Takes a list of file names, checks that they are
               all fully qualified, and then calls _filename() on
               each.  It supplies _filename() with the name of the
               file, and an integer which is stored with each record
               created by _filename().  Can be called multiple times,
               and can be used to add to an existing index file.
     Example : $index->make_index( '/home/seqs1', '/home/seqs2', '/nfs/pub/big_db' );
     Returns : Number of files indexed
     Args    : LIST OF FILES

_filename
---------

     Title   : _filename
     Usage   : $index->_filename( FILE INT )
     Function: Indexes the file
     Example :
     Returns :
     Args    :

_file_handle
------------

     Title   : _file_handle
     Usage   : $fh = $index->_file_handle( INT )
     Function: Returns an open filehandle for the file
               index INT.  On opening a new filehandle it
               caches it in the @{$index->_filehandle} array.
               If the requested filehandle is already open,
               it simply returns it from the array.
     Example : $fist_file_indexed = $index->_file_handle( 0 );
     Returns : ref to a filehandle
     Args    : INT

_file_count
-----------

     Title   : _file_count
     Usage   : $index->_file_count( INT )
     Function: Used by the index building sub in a sub class to
               track the number of files indexed.  Sets or gets
               the number of files indexed when called with or
               without an argument.
     Example :
     Returns : INT
     Args    : INT

add_record
----------

     Title   : add_record
     Usage   : $index->add_record( $id, @stuff );
     Function: Calls pack_record on @stuff, and adds the result
               of pack_record to the index database under key $id.
               If $id is a reference to an array, then a new entry
               is added under a key corresponding to each element
               of the array.
     Example : $index->add_record( $id, $fileNumber, $begin, $end )
     Returns : TRUE on success or FALSE on failure
     Args    : ID LIST

pack_record
-----------

     Title   : pack_record
     Usage   : $packed_string = $index->pack_record( LIST )
     Function: Packs an array of scalars into a single string
               joined by ASCII 034 (which is unlikely to be used
               in any of the strings), and returns it.
     Example : $packed_string = $index->pack_record( $fileNumber, $begin, $end )
     Returns : STRING or undef
     Args    : LIST

unpack_record
-------------

     Title   : unpack_record
     Usage   : $index->unpack_record( STRING )
     Function: Splits the sting provided into an array,
               splitting on ASCII 034.
     Example : ( $fileNumber, $begin, $end ) = $index->unpack_record( $self->db->{$id} )
     Returns : A 3 element ARRAY
     Args    : STRING containing ASCII 034

DESTROY
-------

     Title   : DESTROY
     Usage   : Called automatically when index goes out of scope
     Function: Closes connection to database and handles to
               sequence files
     Returns : NEVER
     Args    : NONE

Base class for AbstractSeq s
****************************

NAME
====

   Bio::Index::AbstractSeq - Base class for AbstractSeq s

SYNOPSIS
========

     # Make a new sequence file indexing package

     package MyShinyNewIndexer;
     use Bio::Index::AbstractSeq;

     @ISA = ('Bio::Index::AbstractSeq');

     # Now provide the necessary methods...

DESCRIPTION
===========

   Provides a common base class for multiple sequence files built using the
Bio::Index::Abstract system, and provides a Bio::DB::SeqI interface.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email birney@ebi.ac.uk

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

SEE ALSO
========

   Bio::Index::Abstract - Module which Bio::Index::AbstractSeq inherits
off, which provides dbm indexing for flat files (which are not necessarily
sequence files).

_file_format
------------

     Title   : _file_format
     Usage   : $self->_file_format
     Function: Derived classes should override this
               method (it throws an exception here)
               to give the file format of the files used
     Example :
     Returns :
     Args    :

fetch
-----

     Title   : fetch
     Usage   : $index->fetch( $id )
     Function: Returns a Bio::Seq object from the index
     Example : $seq = $index->fetch( 'dJ67B12' )
     Returns : Bio::Seq object
     Args    : ID

_get_SeqIO_object
-----------------

     Title   : _get_SeqIO_object
     Usage   : $index->_get_SeqIO_object( $file )
     Function: Returns a Bio::SeqIO object for the file
     Example : $seq = $index->_get_SeqIO_object( 0 )
     Returns : Bio::SeqIO object
     Args    : File number (an integer)

get_Seq_by_id
-------------

     Title   : get_Seq_by_id
     Usage   : $seq = $db->get_Seq_by_id()
     Function: retrieves a sequence object, identically to
               ->fetch, but here behaving as a Bio::DB::BioSeqI
     Returns : new Bio::Seq object
     Args    : string represents the id

get_Seq_by_acc
--------------

     Title   : get_Seq_by_acc
     Usage   : $seq = $db->get_Seq_by_acc()
     Function: retrieves a sequence object, identically to
               ->fetch, but here behaving as a Bio::DB::BioSeqI
     Returns : new Bio::Seq object
     Args    : string represents the accession number

get_PrimarySeq_stream
---------------------

     Title   : get_PrimarySeq_stream
     Usage   : $stream = get_PrimarySeq_stream
     Function: Makes a Bio::DB::SeqStreamI compliant object
               which provides a single method, next_primary_seq
     Returns : Bio::DB::SeqStreamI
     Args    : none

get_all_primary_ids
-------------------

     Title   : get_all_primary_ids
     Usage   : @ids = $seqdb->get_all_primary_ids()
     Function: gives an array of all the primary_ids of the
               sequence objects in the database. These
               maybe ids (display style) or accession numbers
               or something else completely different - they
               *are not* meaningful outside of this database
               implementation.
     Example :
     Returns : an array of strings
     Args    : none

get_Seq_by_primary_id
---------------------

     Title   : get_Seq_by_primary_id
     Usage   : $seq = $db->get_Seq_by_primary_id($primary_id_string);
     Function: Gets a Bio::Seq object by the primary id. The primary
               id in these cases has to come from $db->get_all_primary_ids.
               There is no other way to get (or guess) the primary_ids
               in a database.

     The other possibility is to get Bio::PrimarySeqI objects
     via the get_PrimarySeq_stream and the primary_id field
     on these objects are specified as the ids to use here.
      Returns : A Bio::Seq object
      Args    : primary id (as a string)
      Throws  : "acc does not exist" exception

Interface for indexing (multiple) EMBL/Swissprot .dat files (ie flat file embl/swissprot format).
*************************************************************************************************

NAME
====

   Bio::Index::EMBL - Interface for indexing (multiple) EMBL/Swissprot
.dat files (ie flat file embl/swissprot format).

SYNOPSIS
========

     # Complete code for making an index for several
     # EMBL files
     use Bio::Index::EMBL;

     my $Index_File_Name = shift;
     my $inx = Bio::Index::EMBL->new($Index_File_Name, 'WRITE');
     $inx->make_index(@ARGV);

     # Print out several sequences present in the index
     # in Fasta format
     use Bio::Index::EMBL;

     my $Index_File_Name = shift;
     my $inx = Bio::Index::EMBL->new($Index_File_Name);
     my $out = Bio::SeqIO->new('-format' => 'Fasta','-fh' => \*STDOUT);

     foreach my $id (@ARGV) {
         my $seq = $inx->fetch($id); # Returns Bio::Seq object
     	$out->write_seq($seq);
     }

     # alternatively

     my $seq1 = $inx->get_Seq_by_id($id);
     my $seq2 = $inx->get_Seq_by_acc($acc);

DESCRIPTION
===========

   Inherits functions for managing dbm files from Bio::Index::Abstract.pm,
and provides the basic funtionallity for indexing EMBL files, and
retrieving the sequence from them. Heavily snaffled from James Gilbert's
Fasta system.

FEED_BACK
=========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email - birney@sanger.ac.uk

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

_index_file
-----------

     Title   : _index_file
     Usage   : $index->_index_file( $file_name, $i )
     Function: Specialist function to index EMBL format files.
               Is provided with a filename and an integer
               by make_index in its SUPER class.
     Example :
     Returns :
     Args    :

_file_format
------------

     Title   : _file_format
     Usage   : Internal function for indexing system
     Function: Provides file format for this database
     Example :
     Returns :
     Args    :

Interface for indexing (multiple) fasta files
*********************************************

NAME
====

   Bio::Index::Fasta - Interface for indexing (multiple) fasta files

SYNOPSIS
========

     # Complete code for making an index for several
     # fasta files
     use Bio::Index::Fasta;

     my $Index_File_Name = shift;
     my $inx = Bio::Index::Fasta->new(
         -filename => $Index_File_Name,
         -write_flag => 1);
     $inx->make_index(@ARGV);

     # Print out several sequences present in the index
     # in Fasta format
     use Bio::Index::Fasta;

     my $Index_File_Name = shift;
     my $inx = Bio::Index::Fasta->new($Index_File_Name);
     my $out = Bio::SeqIO->new('-format' => 'Fasta','-fh' => \*STDOUT);

     foreach my $id (@ARGV) {
         my $seq = $inx->fetch($id); # Returns Bio::Seq object
     	$out->write_seq($seq);
     }

     # or, alternatively

     my $seq = $inx->get_Seq_by_id($id); #identical to fetch

DESCRIPTION
===========

   Inherits functions for managing dbm files from Bio::Index::Abstract.pm,
and provides the basic funtionallity for indexing fasta files, and
retrieving the sequence from them.

   Bio::Index::Fasta supports the Bio::DB::BioSeqI interface, meaning it
can be used a a Sequence database for other parts of bioperl

FEED_BACK
=========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - James Gilbert
======================

   Email - jgrg@sanger.ac.uk

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

_file_format
------------

     Title   : _file_format
     Function: The file format for this package, which is needed
               by the SeqIO system when reading the sequence.
     Returns : 'Fasta'

_index_file
-----------

     Title   : _index_file
     Usage   : $index->_index_file( $file_name, $i )
     Function: Specialist function to index FASTA format files.
               Is provided with a filename and an integer
               by make_index in its SUPER class.
     Example :
     Returns :
     Args    :

id_parser
---------

     Title   : id_parser
     Usage   : $index->id_parser( CODE )
     Function: Stores or returns the code used by record_id to
               parse the ID for record from a string.  Useful
               for (for instance) specifying a different
               parser for different flavours of FASTA file.
               Returns \&default_id_parser (see below) if not
               set. If you supply your own id_parser
               subroutine, then it should expect a fasta
               description line.  An entry will be added to
               the index for each string in the list returned.
     Example : $index->id_parser( \&my_id_parser )
     Returns : ref to CODE if called without arguments
     Args    : CODE

default_id_parser
-----------------

     Title   : default_id_parser
     Usage   : $id = default_id_parser( $header )
     Function: The default Fasta ID parser for Fasta.pm
               Returns $1 from applying the regexp /^>\s*(\S+)/
               to $header.
     Returns : ID string
     Args    : a fasta header line string

Interface for indexing (multiple) GenBank .seq files (ie flat file GenBank format).
***********************************************************************************

NAME
====

   Bio::Index::GenBank - Interface for indexing (multiple) GenBank .seq
files (ie flat file GenBank format).

SYNOPSIS
========

     # Complete code for making an index for several
     # GenBank files
     use Bio::Index::GenBank;

     my $Index_File_Name = shift;
     my $inx = Bio::Index::GenBank->new($Index_File_Name, 'WRITE');
     $inx->make_index(@ARGV);

     # Print out several sequences present in the index
     # in gcg format
     use Bio::Index::GenBank;

     my $Index_File_Name = shift;
     my $inx = Bio::Index::GenBank->new($Index_File_Name);

     foreach my $id (@ARGV) {
         my $seq = $inx->fetch($id); # Returns Bio::Seq object
         print $seq->layout('GCG');
     }

     # alternatively

     my $seq1 = $inx->get_Seq_by_id($id);
     my $seq2 = $inx->get_Seq_by_acc($acc);

DESCRIPTION
===========

   Inherits functions for managing dbm files from Bio::Index::Abstract.pm,
and provides the basic funtionallity for indexing GenBank files, and
retrieving the sequence from them. Heavily snaffled from James Gilbert's
Fasta system.

FEED_BACK
=========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email - birney@sanger.ac.uk

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

_index_file
-----------

     Title   : _index_file
     Usage   : $index->_index_file( $file_name, $i )
     Function: Specialist function to index GenBank format files.
               Is provided with a filename and an integer
               by make_index in its SUPER class.
     Example :
     Returns :
     Args    :

_file_format
------------

     Title   : _file_format
     Usage   : Internal function for indexing system
     Function: Provides file format for this database
     Example :
     Returns :
     Args    :

Interface for indexing swisspfam files
**************************************

NAME
====

   Bio::Index::SwissPfam - Interface for indexing swisspfam files

SYNOPSIS
========

     use Bio::Index::SwissPfam;

     my $Index_File_Name = shift;
     my $inx = Bio::Index::SwissPfam->new($Index_File_Name, 'WRITE');
     $inx->make_index(@ARGV);

     use Bio::Index::SwissPfam;

     my $Index_File_Name = shift;
     my $inx = Bio::Index::SwissPfam->new($Index_File_Name);

     foreach my $id (@ARGV) {
         my $seq = $inx->fetch($id); # Returns stream
     	while( <$seq> ) {
     	    if(/^>/) {
     	    	print;
     		last;
     	    }
     	}
     }

DESCRIPTION
===========

   SwissPfam is one of the flat files released with Pfam. This modules
provides a way of indexing this module.

   Inherits functions for managing dbm files from Bio::Index::Abstract.pm,
and provides the basic funtionallity for indexing SwissPfam files.  Only
retrieves FileStreams at the moment. Once we have something better (ie, an
object!), will use that. Heavily snaffled from James Gilbert's Fasta
system.

FEED_BACK
=========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email - birney@sanger.ac.uk

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

_index_file
-----------

     Title   : _index_file
     Usage   : $index->_index_file( $file_name, $i )
     Function: Specialist function to index swisspfam format files.
               Is provided with a filename and an integer
               by make_index in its SUPER class.
     Example :
     Returns :
     Args    :

fetch
-----

     Title   : fetch
     Usage   : $index->fetch( $id )
     Function: Returns a Bio::Seq object from the index
     Example : $seq = $index->fetch( 'dJ67B12' )
     Returns : Bio::Seq object
     Args    : ID

Interface for indexing (multiple) Swissprot .dat files (ie flat file swissprot format).
***************************************************************************************

NAME
====

   Bio::Index::Swissprot - Interface for indexing (multiple) Swissprot
.dat files (ie flat file swissprot format).

SYNOPSIS
========

     # Complete code for making an index for several
     # Swissprot files
     use Bio::Index::Swissprot;

     my $Index_File_Name = shift;
     my $inx = Bio::Index::Swissprot->new($Index_File_Name, 'WRITE');
     $inx->make_index(@ARGV);

     # Print out several sequences present in the index
     # in gcg format
     use Bio::Index::Swissprot;
     use Bio::SeqIO;

     my $out = Bio::SeqIO->new( '-format' => 'gcg', -fh => \*STDOUT );
     my $Index_File_Name = shift;
     my $inx = Bio::Index::Swissprot->new($Index_File_Name);

     foreach my $id (@ARGV) {
         my $seq = $inx->fetch($id); # Returns Bio::Seq object
         $out->write_seq($seq);
     }

     # alternatively

     my $seq1 = $inx->get_Seq_by_id($id);
     my $seq2 = $inx->get_Seq_by_acc($acc);

DESCRIPTION
===========

   Inherits functions for managing dbm files from Bio::Index::Abstract.pm,
and provides the basic funtionallity for indexing Swissprot files, and
retrieving the sequence from them. Heavily snaffled from James Gilbert's
Fasta system.

FEED_BACK
=========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                - General discussion
     http://bio.perl.org/MailList.html    - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email - birney@sanger.ac.uk (Swissprot adaption: lorenz@ist.org)

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

_index_file
-----------

     Title   : _index_file
     Usage   : $index->_index_file( $file_name, $i )
     Function: Specialist function to index Swissprot format files.
               Is provided with a filename and an integer
               by make_index in its SUPER class.
     Example :
     Returns :
     Args    :

_file_format
------------

     Title   : _file_format
     Usage   : Internal function for indexing system
     Function: Provides file format for this database
     Example :
     Returns :
     Args    :

AARange abstract class for LiveSeq
**********************************

NAME
====

   Bio::LiveSeq::AARange - AARange abstract class for LiveSeq

SYNOPSIS
========

     #documentation needed

DESCRIPTION
===========

   This is used as possible parent for aminoacid range object classes.  Or
it can be used straight away to define aminoacid ranges.  The idea is that
the ranges defined are attached to a Translation object and they refer to
its coordinate-system when they are first created (via the new() method).
When they are created they are anyway linked to the underlying DNA LiveSeq
by way of the LiveSeq labels. This allows to preserve the ranges even if
the numbering changes in the Translation due to deletions or insertions.

   The protein sequence associated with the AARange can be accessed via
the usual seq() or subseq() methods.

   The start and end of the AARange in protein coordinate system can be
fetched with aa_start() and aa_end() methods. Note: the behaviour of these
methods would be influenced by the coordinate_start set in the
corresponding Translation object. This can be desirable but can also lead
to confusion if the coordinate_start had been changed and the original
position of the AARange was to be retrieved.

   start() and end() methods of the AARange will point to the labels
identifying the first nucleotide of the first and last triplet coding for
the start and end of the AminoAcidRange.

   The underlying nucleotide sequence of the AARange can be retrieved with
the labelsubseq() method. This would retrieve the whole DNA sequence,
including possible introns. This is called "DNA_sequence".

   To fetch the nucleotide sequence of the Transcript, without introns,
the labelsubseq() of the attached Transcript (the Transcript the
Translation comes from) has to be accessed. This is called "cDNA_sequence".

   Here are the operations to retrieve these latter two kinds of sequences:

     $startlabel=$AARange->start;
     $endtripletlabel=$AARange->end;
     $endlabel=$AARange->{'seq'}->label(3,$endtripletlabel,$AARange->strand);

     $dnaseq=$AARange->labelsubseq($startlabel,undef,$endlabel));

     $cdnaseq=$AARange->get_Transcript->labelsubseq($startlabel,undef,$endlabel);

   To simplify, these operations have been included in two additional
methods: dna_seq() and cdna_seq().

   These would return the whole sequence, as in the examples above.  But
the above general scheme can be used by specifying different labels, to
retrieve hypothetical subsequences of interest.

AUTHOR - Joseph A.L. Insana
===========================

   Email:  Insana@ebi.ac.uk, jinsana@gmx.net

   Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
===

     Title   : new
     Usage   : $aarange = Bio::LiveSeq::AARange->new(-translation => $obj_ref,
                                                  -start => $beginaa,
                                                  -end => $endaa,
                                                  -name => "ABCD",
                                                  -description => "DCBA",
                                                  -translength => $length);

     Function: generates a new AminoAcidRange LiveSeq object
     Returns : reference to a new object of class AARange
     Errorcode -1
     Args    : two positions in AminoAcid coordinate numbering
               an object reference specifying to which translation the aminoacid
               ranges refer to
               a name and a description (optional)
               an optional "translength" argument: this can be given when
               a lot of AARanges are to be created at the same time for the same
               Translation object, calculating it with $translation->length
               This would increase the speed, avoiding the new() function to
               calculate everytime the same length again and again for every obj.

get_Transcript
--------------

     Title   : valid
     Usage   : $transcript = $obj->get_Transcript()
     Function: retrieves the reference to the object of class Transcript (if any)
               attached to a LiveSeq object
     Returns : object reference
     Args    : none

get_Translation
---------------

     Title   : valid
     Usage   : $translation = $obj->get_Translation()
     Function: retrieves the reference to the object of class Translation (if any)
               attached to a LiveSeq object
     Returns : object reference
     Args    : none

aa_start
--------

     Title   : aa_start
     Usage   : $end = $aarange->aa_start()
     Returns : integer (position, according to Translation coordinate system) of
               the start of an AminoAcidRange object
     Args    : none

aa_end
------

     Title   : aa_end
     Usage   : $end = $aarange->aa_end()
     Returns : integer (position, according to Translation coordinate system) of
               the end of an AminoAcidRange object
     Args    : none

dna_seq
-------

     Title   : dna_seq
     Usage   : $end = $aarange->dna_seq()
     Returns : the sequence at DNA level of the entire AminoAcidRange
               this would include introns (if present)
     Args    : none

cdna_seq
--------

     Title   : cdna_seq
     Usage   : $end = $aarange->cdna_seq()
     Returns : the sequence at cDNA level of the entire AminoAcidRange
               i.e. this is the part of the Transcript that codes for the
               AminoAcidRange. It would be composed just of exonic DNA.
     Args    : none

DoubleChain DataStructure for Perl
**********************************

NAME
====

   Bio::LiveSeq::Chain - DoubleChain DataStructure for Perl

SYNOPSIS
========

     #documentation needed

DESCRIPTION
===========

   This is a general purpose module (that's why it's not in object-oriented
form) that introduces a novel datastructure in PERL. It implements the
"double linked chain". The elements of the chain can contain basically
everything. From chars to strings, from object references to arrays or
hashes.  It is used in the LiveSequence project to create a dynamical DNA
sequence, easier to manipulate and change. It's use is mainly for sequence
variation analysis but it could be used - for example - in e-cell projects.
The Chain module in itself doesn't have any biological bias, so can be
used for any programming purpose.

   Each element of the chain (with the exclusion of the first and the last
of the chain) is connected to other two elements (the PREVious and the
NEXT one).  There is no absolute position (like in an array), hence if
positions are important, they need to be computed (methods are provided).
Otherwise it's easy to keep track of the elements with their "LABELs".
There is one LABEL (think of it as a pointer) to each ELEMENT. The labels
won't change after insertions or deletions of the chain. So it's always
possible to retrieve an element even if the chain has been modified by
successive insertions or deletions.  From this the high potential profit
for bioinformatics: dealing with sequences in a way that doesn't have to
rely on positions, without the need of constantly updating them if the
sequence changes, even dramatically.

AUTHOR - Joseph A.L. Insana
===========================

   Email:  Insana@ebi.ac.uk, jinsana@gmx.net

   Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

_updown_chain2string        Title   : chain2string   Usage   : $string = Bio::LiveSeq::Chain::chain2string("down",$chain,6,9)   Function: reads the contents of the chain, outputting a string   Returns : a string   Examples:           : down_chain2string($chain) -> all the chain from begin to end           : down_chain2string($chain,6) -> from 6 to the end           : down_chain2string($chain,6,4) -> from 6, going on 4 elements           : down_chain2string($chain,6,"",10) -> from 6 to 10           : up_chain2string($chain,10,"",6) -> from 10 to 6 upstream   Defaults: start=first element; if len undef, goes to last             if last undef, goes to end             if last defined, it overrides len (undefining it)   Error code: -1   Args    : "up"||"down" as first argument to specify the reading direction              reference (to the chain)             [first] [len] [last] optional integer arguments to specify how             much and from (and to) where to read
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

_updown_labels
--------------

     Title   : labels
     Usage   : @labels = Bio::LiveSeq::Chain::_updown_labels("down",$chain,4,16)
     Function: returns all the labels in a chain or those between two
               specified ones (termed "first" and "last")
     Returns : a reference to an array containing the labels
     Args    : "up"||"down" as first argument to specify the reading direction
               reference (to the chain)
               [first] [last] (integer for the starting and eneding labels)

start
-----

     Title   : start
     Usage   : $start = Bio::LiveSeq::Chain::start()
     Returns : the label marking the start of the chain
     Errorcode: -1
     Args    : none

end
---

     Title   : end
     Usage   : $end = Bio::LiveSeq::Chain::end()
     Returns : the label marking the end of the chain
     Errorcode: -1
     Args    : none

label_exists
------------

     Title   : label_exists
     Usage   : $check = Bio::LiveSeq::Chain::label_exists($chain,$label)
     Function: It checks if a label is defined, i.e. if an element is there or
               is not there anymore
     Returns : 1 if the label exists, 0 if it is not there, -1 error
     Errorcode: -1
     Args    : reference to the chain, integer

down_get_pos_of_label
---------------------

     Title   : down_get_pos_of_label
     Usage   : $position = Bio::LiveSeq::Chain::down_get_pos_of_label($chain,$label,$first)
     Function: returns the position of $label counting from $first, i.e. taking
               $first as 1 of coordinate system. If $first is not specified it will
               count from the start of the chain.
     Returns :
     Errorcode: 0
     Args    : reference to the chain, integer (the label of interest)
               optional: integer (a different label that will be taken as the
               first one, i.e. the one to count from)
     Note:     It counts "downstream". To proceed backward use up_get_pos_of_label

down_subchain_length
--------------------

     Title   : down_subchain_length
     Usage   : $length = Bio::LiveSeq::Chain::down_subchain_length($chain,$first,$last)
     Function: returns the length of the chain between the labels "first" and "last", included
     Returns : integer
     Errorcode: 0
     Args    : reference to the chain, integer, integer
     Note:     It counts "downstream". To proceed backward use up_subchain_length

invert_chain
------------

     Title   : invert_chain
     Usage   : $errorcode=Bio::LiveSeq::Chain::invert_chain($chain)
     Function: completely inverts the order of the chain elements; begin is swapped with end and all links updated (PREV&NEXT fields swapped)
     Returns : 1 if all OK, 0 if errors
     Errorcode: 0
     Args    : reference to the chain

down_get_value_at_pos
---------------------

     Title   : down_get_value_at_pos
     Usage   : $value = Bio::LiveSeq::Chain::down_get_value_at_pos($chain,$position,$first)
     Function: used to access the value of the chain at a particular position instead than directly with a label pointer. It will count the position from the start of the chain or from the label $first, if $first is specified
     Returns : whatever is stored in the element of the chain
     Errorcode: 0
     Args    : reference to the chain, integer, [integer]
     Note:     It works "downstream". To proceed backward use up_get_value_at_pos

down_set_value_at_pos
---------------------

     Title   : down_set_value_at_pos
     Usage   : $errorcode = Bio::LiveSeq::Chain::down_set_value_at_pos($chain,$newvalue,$position,$first)
     Function: used to store a new value inside an element of the chain at a particular position instead than directly with a label pointer. It will count the position from the start of the chain or from the label $first, if $first is specified
     Returns : 1
     Errorcode: 0
     Args    : reference to the chain, newvalue, integer, [integer]
               (newvalue can be: integer, string, object reference, hash ref)
     Note:     It works "downstream". To proceed backward use up_set_value_at_pos
     Note2:    If the $newvalue is undef, it will delete the contents of the
               element but it won't remove the element from the chain.

down_set_value_at_label
-----------------------

     Title   : down_set_value_at_label
     Usage   : $errorcode = Bio::LiveSeq::Chain::down_set_value_at_label($chain,$newvalue,$label)
     Function: used to store a new value inside an element of the chain defined by its label.
     Returns : 1
     Errorcode: 0
     Args    : reference to the chain, newvalue, integer
               (newvalue can be: integer, string, object reference, hash ref)
     Note:     It works "downstream". To proceed backward use up_set_value_at_label
     Note2:    If the $newvalue is undef, it will delete the contents of the
               element but it won't remove the element from the chain.

down_get_value_at_label
-----------------------

     Title   : down_get_value_at_label
     Usage   : $value = Bio::LiveSeq::Chain::down_get_value_at_label($chain,$label)
     Function: used to access the value of the chain from one element defined by its label.
     Returns : whatever is stored in the element of the chain
     Errorcode: 0
     Args    : reference to the chain, integer
     Note:     It works "downstream". To proceed backward use up_get_value_at_label

down_get_label_at_pos
---------------------

     Title   : down_get_label_at_pos
     Usage   : $label = Bio::LiveSeq::Chain::down_get_label_at_pos($chain,$position,$first)
     Function: used to retrieve the label of an an element of the chain at a particular position. It will count the position from the start of the chain or from the label $first, if $first is specified
     Returns : integer
     Errorcode: 0
     Args    : reference to the chain, integer, [integer]
     Note:     It works "downstream". To proceed backward use up_get_label_at_pos

_praepostinsert_array
---------------------

     Title   : _praepostinsert_array
     Usage   : ($insbegin,$insend) = Bio::LiveSeq::Chain::_praepostinsert_array($chainref,"post",$arrayref,$position)
     Function: the elements of the array specified by $arrayref are inserted (creating a new subchain) in the chain specified by $chainref, before or after (depending on the "prae"||"post" keyword passed as second argument) the specified position.
     Returns : two labels: the first and the last of the inserted subchain
     Defaults: if no position is specified, the new chain will be inserted after
     (post) the first element of the chain
     Errorcode: 0
     Args    : chainref, "prae"||"post", arrayref, integer (position)

is_downstream
=============

     Title   : is_downstream
     Usage   : Bio::LiveSeq::Chain::is_downstream($chainref,$firstlabel,$secondlabel)
     Function: checks if SECONDlabel follows FIRSTlabel
               It runs downstream the elements of the chain from FIRST searching
               for SECOND.
     Returns : 1 if SECOND is found /after/ FIRST; 0 otherwise (i.e. if it
               reaches the end of the chain without having found it)
     Errorcode -1
     Args    : two labels (integer)

is_upstream
===========

     Title   : is_upstream
     Usage   : Bio::LiveSeq::Chain::is_upstream($chainref,$firstlabel,$secondlabel)
     Function: checks if SECONDlabel follows FIRSTlabel
               It runs upstream the elements of the chain from FIRST searching
               for SECOND.
     Returns : 1 if SECOND is found /after/ FIRST; 0 otherwise (i.e. if it
               reaches the end of the chain without having found it)
     Errorcode -1
     Args    : two labels (integer)

check_chain
-----------

     Title   : check_chain
     Usage   : @errorcodes = Bio::LiveSeq::Chain::check_chain()
     Function: a wraparound to a series of check for consistency of the chain
               It will check for boundaries, size, backlinking and forwardlinking
     Returns : array of 4 warn codes, each can be 1 (all ok) or 0 (something wrong)
     Errorcode: 0
     Args    : none
     Note    : this is slow and through. It is not really needed. It is mostly
               a code-developer tool.

splice_chain
------------

     Title   : splice_chain
     Usage   : @errorcodes = Bio::LiveSeq::Chain::splice_chain($chainref,$first,$length,$last)
     Function: removes the elements designated by FIRST and LENGTH from a chain.
               The chain shrinks accordingly. If LENGTH is omitted, removes
               everything from FIRST onward.
               If END is specified, LENGTH is ignored and instead the removal
               occurs from FIRST to LAST.
     Returns : the elements removed as a string
     Errorcode: -1
     Args    : chainref, integer, integer, integer

array2chain
-----------

     Title   : array2chain
     Usage   : $chainref = Bio::LiveSeq::Chain::array2chain($arrayref,$offset)
     Function: creation of a double linked chain from an array
     Returns : reference to a hash containing the chain
     Defaults: OFFSET defaults to 1 if undef
     Error code: 0
     Args    : a reference to an array containing the elements to be chainlinked
               an optional integer > 0 (this will be the starting count for
               the chain labels instead than having them begin from "1")

Double linked chain data structure
**********************************

NAME
====

   Bio::LiveSeq::ChainI - Double linked chain data structure

SYNOPSIS
========

     #documentation needed

DESCRIPTION
===========

   This class generates and manipulates generic double linked list, chain,
that can be used to manage biological sequences.

   The advantages over strings or plain arrays is the ease of tracking
changes (mutations) in the elements (sequence). The other side of the coin
is that these structures need consideraly more memory, but that is cheap
and constantly inceasing resource in computers.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     vsns-bcd-perl@lists.uni-bielefeld.de          - General discussion
     vsns-bcd-perl-guts@lists.uni-bielefeld.de     - Technically-oriented discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via  email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Joseph A.L. Insana
===========================

   Email:  Insana@ebi.ac.uk, jinsana@gmx.net Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new        Title   : new   Usage   : $chain = Bio::LiveSeq::ChainI->new(-string => "thequickbrownfoxjumpsoverthelazydog", 					     -offset => 3 );          OR $chain = Bio::LiveSeq::ChainI->new(-array => \@array, 					     -offset => 3 );   Function: generates a new Bio::LiveSeq:ChainI   Returns : a new Chain   Args    : string          OR arrayreference         AND optional offset to create element labels =cut
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

   sub new {   my ($thing, %args) = @_;   my $class = ref($thing) ||
$thing;   my $obj;

     if ($args{-string}) {
       $obj = $thing->string2chain($args{-string}, $args{-offset});
     } elsif ($args{-array}) {
       $obj = $thing->array2chain($args{-array}, $args{-offset});
     } else {
       croak "$class not initialized properly";
     }

     $obj = bless $obj, $class;
     return $obj;
     }

   # added as of 1.9 sub string2chain {   shift @_; # so that it doesn't
pass the object reference   return Bio::LiveSeq::Chain::string2chain(@_); }
sub array2chain {   shift @_; # so that it doesn't pass the object
reference   return Bio::LiveSeq::Chain::array2chain(@_); } # sub
chain2string {   croak "ambiguous method call. Explicit down_ or up_"; }
sub down_chain2string {   return
Bio::LiveSeq::Chain::down_chain2string(@_); } sub up_chain2string {
return Bio::LiveSeq::Chain::up_chain2string(@_); } sub
chain2string_verbose {   croak "ambiguous method call. Explicit down_ or
up_"; } sub down_chain2string_verbose {   return
Bio::LiveSeq::Chain::down_chain2string_verbose(@_); } sub
up_chain2string_verbose {   return
Bio::LiveSeq::Chain::up_chain2string_verbose(@_); } sub invert_chain {
return Bio::LiveSeq::Chain::invert_chain(@_); } sub mutate_element {
croak "Old method name, please update code to: set_value_at_label"; }

   # new as of version 2.33 of Chain.pm sub down_labels {   return
Bio::LiveSeq::Chain::down_labels(@_); } sub up_labels {   return
Bio::LiveSeq::Chain::up_labels(@_); }

   sub start {   return Bio::LiveSeq::Chain::start(@_); } sub end {
return Bio::LiveSeq::Chain::end(@_); } sub label_exists {   return
Bio::LiveSeq::Chain::label_exists(@_); }

   sub get_value_at_pos {   croak "ambiguous method call. Explicit down_
or up_"; } sub down_get_value_at_pos {   return
Bio::LiveSeq::Chain::down_get_value_at_pos(@_); } sub up_get_value_at_pos {
 return Bio::LiveSeq::Chain::up_get_value_at_pos(@_); } sub
set_value_at_pos {   croak "ambiguous method call. Explicit down_ or up_";
} sub down_set_value_at_pos {   return
Bio::LiveSeq::Chain::down_set_value_at_pos(@_); } sub up_set_value_at_pos {
 return Bio::LiveSeq::Chain::up_set_value_at_pos(@_); } sub
get_value_at_label {   return Bio::LiveSeq::Chain::get_value_at_label(@_);
} sub set_value_at_label {   return
Bio::LiveSeq::Chain::set_value_at_label(@_); } sub get_label_at_pos {
croak "ambiguous method call. Explicit down_ or up_"; } sub
up_get_label_at_pos {   return
Bio::LiveSeq::Chain::up_get_label_at_pos(@_); } sub down_get_label_at_pos {
 return Bio::LiveSeq::Chain::down_get_label_at_pos(@_); } sub
get_pos_of_label {   croak "ambiguous method call. Explicit down_ or up_";
} sub up_get_pos_of_label {   return
Bio::LiveSeq::Chain::up_get_pos_of_label(@_); } sub down_get_pos_of_label {
 return Bio::LiveSeq::Chain::down_get_pos_of_label(@_); } #

   sub preinsert_string {   return
Bio::LiveSeq::Chain::praeinsert_string(@_); } sub preinsert_array {
return Bio::LiveSeq::Chain::praeinsert_array(@_); } sub praeinsert_string {
 return Bio::LiveSeq::Chain::praeinsert_string(@_); } sub
postinsert_string {   return Bio::LiveSeq::Chain::postinsert_string(@_); }
sub praeinsert_array {   return Bio::LiveSeq::Chain::praeinsert_array(@_);
} sub postinsert_array {   return
Bio::LiveSeq::Chain::postinsert_array(@_); } sub down_element{   return
Bio::LiveSeq::Chain::down_element(@_); } sub up_element {   return
Bio::LiveSeq::Chain::up_element(@_); } sub is_downstream {   return
Bio::LiveSeq::Chain::is_downstream(@_); } sub is_upstream {   return
Bio::LiveSeq::Chain::is_upstream(@_); } sub check_chain {   return
Bio::LiveSeq::Chain::check_chain(@_); } sub chain_length {   return
Bio::LiveSeq::Chain::chain_length(@_); } sub splice_chain {   return
Bio::LiveSeq::Chain::splice_chain(@_); } sub pos_of_element {   croak
"ambiguous and old method name. use: down_pos_of_label"; } sub
up_pos_of_element {   croak "old method name. use: down_pos_of_label";
return Bio::LiveSeq::Chain::up_pos_of_element(@_); } sub
down_pos_of_element {   croak "old method name. use: up_pos_of_label";
return Bio::LiveSeq::Chain::down_pos_of_element(@_); } sub subchain_length
{   croak "ambiguous method call. Explicit down_ or up_"; } sub
down_subchain_length {   return
Bio::LiveSeq::Chain::down_subchain_length(@_); } sub up_subchain_length {
return Bio::LiveSeq::Chain::up_subchain_length(@_); }

   # these have to be deleted and changed names to conform to terminology
sub elements {   return Bio::LiveSeq::Chain::down_elements(@_); } sub
up_elements {   return Bio::LiveSeq::Chain::up_elements(@_); } sub
down_elements {   return Bio::LiveSeq::Chain::down_elements(@_); }

   1;

DNA object for LiveSeq
**********************

NAME
====

   Bio::LiveSeq::DNA - DNA object for LiveSeq

SYNOPSIS
========

     # documentation needed

DESCRIPTION
===========

   This holds the DNA sequence (or the RNA in the case of cDNA entries)
and is accessed by exons, genes, transcripts... objects

AUTHOR - Joseph A.L. Insana
===========================

   Email:  Insana@ebi.ac.uk, jinsana@gmx.net

   Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
===

     Title   : new
     Usage   : $dna = Bio::LiveSeq::DNA->new(-seq => "atcgaccaatggacctca",
     					  -offset => 3 );

     Function: generates a new Bio::LiveSeq::DNA
     Returns : reference to a new object of class DNA
     Errorcode -1
     Args    : a string
           AND an optional offset to create nucleotide labels (default is 1, i.e.
               starting the count of labels from "1") -> do not bother using it ->
               it could be used by alternative loaders !EMBL format
     NOTE    : strand of DNA is set to 1 by default

Range abstract class for LiveSeq
********************************

NAME
====

   Bio::LiveSeq::Exon - Range abstract class for LiveSeq

SYNOPSIS
========

     # documentation needed

DESCRIPTION
===========

   Class for EXON objects. They consist of a beginlabel, an endlabel (both
referring to a LiveSeq DNA object) and a strand.  The strand could be 1
(forward strand, default), -1 (reverse strand).

AUTHOR - Joseph A.L. Insana
===========================

   Email:  Insana@ebi.ac.uk, jinsana@gmx.net

   Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
===

     Title   : new
     Usage   : $exon1 = Bio::LiveSeq::Exon-> new(-seq => $objref,
     					      -start => $startlabel,
     					      -end => $endlabel, -strand => 1);

     Function: generates a new Bio::LiveSeq::Exon
     Returns : reference to a new object of class Exon
     Errorcode -1
     Args    : two labels and an integer

get_Transcript
--------------

     Title   : get_Transcript
     Usage   : $transcript = $obj->get_Transcript()
     Function: retrieves the reference to the object of class Transcript (if any)
               attached to a LiveSeq object
     Returns : object reference
     Args    : none
     Note    : only Exons that compose a Transcript (i.e. those created out of
               a CDS Entry-Feature) will have an attached Transcript

Range abstract class for LiveSeq
********************************

NAME
====

   Bio::LiveSeq::Gene - Range abstract class for LiveSeq

SYNOPSIS
========

     # documentation needed

DESCRIPTION
===========

   This is used as storage for all object references concerning a
particular gene.

AUTHOR - Joseph A.L. Insana
===========================

   Email:  Insana@ebi.ac.uk, jinsana@gmx.net

   Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
===

     Title   : new
     Usage   : $gene = Bio::LiveSeq::Gene->new(-name => "name",
                                               -features => $hashref
                                               -upbound => $min
                                               -downbound => $max);

     Function: generates a new Bio::LiveSeq::Gene
     Returns : reference to a new object of class Gene
     Errorcode -1
     Args    : one string and one hashreference containing all features defined
               for the Gene and the references to the LiveSeq objects for those
               features.
               Two labels for defining boundaries of the gene. Usually the
               boundaries will reflect max span of transcript, exon... features,
               while the DNA sequence will be created with some flanking regions
               (e.g. with the EMBL_SRS::gene2liveseq routine).
               If these two labels are not given, they will default to the start
               and end of the DNA object.
     Note    : the format of the hash has to be like
                  DNA => reference to LiveSeq::DNA object
                  Transcripts => reference to array of transcripts objrefs
                  Transclations => reference to array of transcripts objrefs
                  Exons => ....
                  Introns => ....
                  Prim_Transcripts => ....
                  Repeat_Units => ....
                  Repeat_Regions => ....
               Only DNA and Transcripts are mandatory

Loader for LiveSeq from EMBL entries with BioPerl
*************************************************

NAME
====

   Bio::LiveSeq::IO::BioPerl - Loader for LiveSeq from EMBL entries with
BioPerl

SYNOPSIS
========

     my $db="EMBL";
     my $file="../data/M20132";

     my $loader=Bio::LiveSeq::IO::BioPerl->load(-db=>"EMBL", -file=>"$file");

     my @translationobjects=$loader->entry2liveseq();

     my $gene="AR";
     my $gene=$loader->gene2liveseq("gene");

     NOTE: The only -db now supported is EMBL. Hence it defaults to EMBL.

DESCRIPTION
===========

   This package uses BioPerl (SeqIO) to fetch a sequence database entry,
analyse it and create LiveSeq objects out of it.

   An filename has to be passed to this package which will return
references to all translation objects created from the EMBL entry.
References to Transcription, DNA and Exon objects can all be retrieved
departing from these.

   Alternatively, a specific "gene" name can be specified, together with
the embl-acc ID. This will create a LiveSeq::Gene object with all relevant
gene features attached/created.

AUTHOR - Joseph A.L. Insana
===========================

   Email:  Insana@ebi.ac.uk, jinsana@gmx.net

   Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

load
====

     Title   : load
     Usage   : my $filename="../data/M20132";
               $loader=Bio::LiveSeq::IO::BioPerl->load(-db=>"EMBL", -file=>"$filename");

     Function: loads an entry with BioPerl from a database into a hash
     Returns : reference to a new object of class IO::BioPerl holding an entry
     Errorcode 0
     Args    : an BioPerl query resulting in one fetched EMBL (by default) entry

embl2hash
=========

     Title   : embl2hash
     Function: retrieves with BioPerl an EMBL entry, parses it and creates
               a hash that contains all the information.
     Returns : a reference to a hash
     Errorcode: 0
     Args    : a filename pointing to a file containing one EMBL entry
     	    two array references to skip features and qualifiers (for
     	    performance)
     Example: @valid_features=qw(CDS exon prim_transcript mRNA);
              @valid_qualifiers=qw(gene codon_start db_xref product rpt_family);
              $hashref=&embl2hash("$file",\@valid_features,\@valid_qualifiers);

novelaasequence2gene
====================

     Title   : novelaasequence2gene
     Usage   : $gene=Bio::LiveSeq::IO::BioPerl->novelaasequence2gene(-aasequence => "MGLAAPTRS*");
             : $gene=Bio::LiveSeq::IO::BioPerl->novelaasequence2gene(-aasequence => "MGLAAPTRS*",
                                                -cusg_data => "58 44 7 29 3 3 480 267 105 143 122 39 144 162 14 59 53 25 233 292 19 113 88 246 28 68 161 231 27 102 128 151 67 60 138 131 48 61 153 19 233 73 150 31 129 38 147 71 138 43 181 81 44 15 255 118 312 392 236 82 20 10 14 141");
             : $gene=Bio::LiveSeq::IO::BioPerl->novelaasequence2gene(-aasequence => "MGLAAPTRS*",
                                                -cusg_data => "58 44 7 29 3 3 480 267 105 143 122 39 144 162 14 59 53 25 233 292 19 113 88 246 28 68 161 231 27 102 128 151 67 60 138 131 48 61 153 19 233 73 150 31 129 38 147 71 138 43 181 81 44 15 255 118 312 392 236 82 20 10 14 141",
                                                -translation_table => "2",
                                                -gene_name => "tyr-kinase");

     Function: creates LiveSeq objects from a novel amino acid sequence,
               using codon usage information (loaded from a file) to choose
               codons according to relative frequencies.
               If a codon_usage information is not specified,
               the default is to use Homo sapiens data (taxonomy ID 9606).
               If a translation_table ID is not specified, it will default to 1
               (standard code).
     Returns : reference to a Gene object containing references to LiveSeq objects
     Errorcode 0
     Args    : string containing an amino acid sequence
     	    string (optional) with codon usage data (64 integer numbers)
               string (optional) specifying a gene_name
               integer (optional) specifying a translation_table ID

Parent Loader for LiveSeq
*************************

NAME
====

   Bio::LiveSeq::IO::Loader - Parent Loader for LiveSeq

SYNOPSIS
========

     #documentation needed

DESCRIPTION
===========

   This package holds common methods used by BioPerl, SRS and file loaders.
It contains methods to create LiveSeq objects out of entire entries or
from a localized sequence region surrounding a particular gene.

AUTHOR - Joseph A.L. Insana
===========================

   Email:  Insana@ebi.ac.uk, jinsana@gmx.net

   Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

entry2liveseq
=============

     Title   : entry2liveseq
     Usage   : @translationobjects=$loader->entry2liveseq();
             : @translationobjects=$loader->entry2liveseq(-getswissprotinfo => 0);
     Function: creates LiveSeq objects from an entry previously loaded
     Returns : array of references to objects of class Translation
     Errorcode 0
     Args    : optional boolean flag to avoid the retrieval of SwissProt
               informations for all Transcripts containing SwissProt x-reference
               default is 1 (to retrieve those informations and create AARange
               LiveSeq objects)
     Note    : this method can get really slow for big entries. The lightweight
               gene2liveseq method is recommended

novelaasequence2gene
====================

     Title   : novelaasequence2gene
     Usage   : $gene=$loader->novelaasequence2gene(-aasequence => "MGLAAPTRS*");
             : $gene=$loader->novelaasequence2gene(-aasequence => "MGLAAPTRS*");
                                                -taxon => 9606,
                                                -gene_name => "tyr-kinase");

     Function: creates LiveSeq objects from a novel amino acid sequence,
               using codon usage database to choose codons according to
               relative frequencies.
               If a taxon ID is not specified, the default is to use the human
               one (taxonomy ID 9606).
     Returns : reference to a Gene object containing references to LiveSeq objects
     Errorcode 0
     Args    : string containing an amino acid sequence
               integer (optional) with a taxonomy ID
               string specifying a gene name

printswissprot
==============

     Title   : printswissprot
     Usage   : $loader->printswissprot($hashref);
     Function: prints out all informations loaded from a database entry into the
               loader. Mainly used for testing purposes.
     Args    : a hashref containing the SWISSPROT entry datas
     Note    : the hashref can be obtained with a call to the method
                  $loader->get_swisshash()      (only with SRS loader)
     	    that takes as argument a string like "SWISS-PROT:P10275" or
     	    from $loader->swissprot2hash() that takes an SRS query string
     	    as its argument (e.g. "swissprot-acc:P10275")

printembl
=========

     Title   : printembl
     Usage   : $loader->printembl();
     Function: prints out all informations loaded from a database entry into the
               loader. Mainly used for testing purposes.
     Args    : none

genes
=====

     Title   : genes
     Usage   : $loader->genes();
     Function: Returns an array of gene_names (strings) contained in the loaded
               entry.
     Args    : none

Loader for LiveSeq from EMBL entries with SRS
*********************************************

NAME
====

   Bio::LiveSeq::IO::SRS - Loader for LiveSeq from EMBL entries with SRS

SYNOPSIS
========

     my $db="EMBL";
     my $acc_id="M20132";
     my $query="embl-acc:$acc_id";

     my $loader=Bio::LiveSeq::IO::SRS->load(-db=>"EMBL", -query=>"$query");

     my @translationobjects=$loader->entry2liveseq();

     my $gene="AR";
     my $gene=$loader->gene2liveseq("gene");

     NOTE: The only -db now supported is EMBL. Hence it defaults to EMBL.

DESCRIPTION
===========

   This package uses the SRS (Sequence Retrieval System) to fetch a
sequence database entry, analyse it and create LiveSeq objects out of it.

   An embl-acc ID has to be passed to this package which will return
references to all translation objects created from the EMBL entry.
References to Transcription, DNA and Exon objects can all be retrieved
departing from these.

   Alternatively, a specific "gene" name can be specified, together with
the embl-acc ID. This will create a LiveSeq::Gene object with all relevant
gene features attached/created.

AUTHOR - Joseph A.L. Insana
===========================

   Email:  Insana@ebi.ac.uk, jinsana@gmx.net

   Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

load
====

     Title   : load
     Usage   : my $acc_id="M20132";
               my $query="embl-acc:$acc_id";
               $loader=Bio::LiveSeq::IO::SRS->load(-db=>"EMBL", -query=>"$query");

     Function: loads an entry with SRS from a database into a hash
     Returns : reference to a new object of class IO::SRS holding an entry
     Errorcode 0
     Args    : an SRS query resulting in one fetched EMBL (by default) entry

embl2hash
=========

     Title   : embl2hash
     Function: retrieves with SRS an EMBL entry, parses it and creates
               a hash that contains all the information.
     Returns : a reference to a hash
     Errorcode: 0
     Args    : an SRS query resulting in one fetched EMBL entry
                 i.e. a string in a form like "embl-acc:accession_number"
     	    two array references to skip features and qualifiers (for
     	    performance)
     Example: @valid_features=qw(CDS exon prim_transcript mRNA);
              @valid_qualifiers=qw(gene codon_start db_xref product rpt_family);
              $hashref=&embl2hash("$query",\@valid_features,\@valid_qualifiers);

get_swisshash
=============

     Title   : get_swisshash
     Usage   : $loader->get_swisshash();
     Example : $swisshash=$loader->swissprot2hash("SWISS-PROT:P10275")
     Function: retrieves with SRS a SwissProt entry, parses it and creates
               a hash that contains all the information.
     Returns : a reference to a hash
     Errorcode: 0
     Args    : the db_xref qualifier's value from an EMBL CDS Feature
               i.e. a string in the form "SWISS-PROT:accession_number"
     Note    : this can be modified (adding a second argument) to retrieve
               and parse SWTREMBL, SWALL... entries

swissprot2hash
==============

     Title   : swissprot2hash
     Usage   : $loader->swissprot2hash();
     Example : $swisshash=$loader->swissprot2hash("swissprot-acc:P10275")
     Function: retrieves with SRS a SwissProt entry, parses it and creates
               a hash that contains all the information.
     Returns : a reference to a hash
     Errorcode: 0
     Args    : an SRS query resulting in one entry from SwissProt database
               i.e. a string in the form "swissprot-acc:accession_number"
     Note    : this can be modified (adding a second argument) to retrieve
               and parse SWTREMBL, SWALL... entries

novelaasequence2gene
====================

     Title   : novelaasequence2gene
     Usage   : $gene=Bio::LiveSeq::IO::SRS->novelaasequence2gene(-aasequence => "MGLAAPTRS*");
             : $gene=Bio::LiveSeq::IO::SRS->novelaasequence2gene(-aasequence => "MGLAAPTRS*",
                                                -genome => "Homo sapiens");
             : $gene=Bio::LiveSeq::IO::SRS->novelaasequence2gene(-aasequence => "MGLAAPTRS*",
                                                -genome => "Mitochondrion Homo sapiens",
                                                -gene_name => "tyr-kinase");

     Function: creates LiveSeq objects from a novel amino acid sequence,
               using codon usage database to choose codons according to
               relative frequencies.
               If a genome latin name is not specified, the default is to use
               'Homo sapiens' (taxonomy ID 9606).
     Returns : reference to a Gene object containing references to LiveSeq objects
     Errorcode 0
     Args    : string containing an amino acid sequence
               string (optional) with a species/genome latin name
               string specifying a gene name
     Note    : SRS access to TAXON and CODONUSAGE databases is required

Range abstract class for LiveSeq
********************************

NAME
====

   Bio::LiveSeq::Intron - Range abstract class for LiveSeq

SYNOPSIS
========

     # documentation needed

DESCRIPTION
===========

   Class for INTRON objects. They consist of a beginlabel, an endlabel
(both referring to a LiveSeq DNA object) and a strand.  The strand could
be 1 (forward strand, default), -1 (reverse strand).

AUTHOR - Joseph A.L. Insana
===========================

   Email:  Insana@ebi.ac.uk, jinsana@gmx.net

   Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
===

     Title   : new
     Usage   : $intron1=Bio::LiveSeq::Intron->new(-seq => $objref,
     					       -start => $startlabel,
     					       -end => $endlabel,
                                                  -strand => 1
     					       );

     Function: generates a new Bio::LiveSeq::Intron
     Returns : reference to a new object of class Intron
     Errorcode -1
     Args    : two labels and an integer

Mutation event descriptor class
*******************************

NAME
====

   Bio::LiveSeq::Mutation - Mutation event descriptor class

SYNOPSIS
========

     # full descrition of a point mutation
     $mutation1a = Bio::LiveSeq::Mutation->new ( -seq => 'A',
     					      -seqori => 'T',
     					      -pos  => 100,
     					      -len => 1 # optional, defaults to length(seq)
     					     );

     # minimal information for a point mutation
     $mutation1b = Bio::LiveSeq::Mutation->new ( -seq => 'A',
     					      -pos  => 100
     					      );
     # insertion
     $mutation2 = Bio::LiveSeq::Mutation->new ( -seq => 'ATT',
     					     -pos  => 100,
     					     -len => 0
     					     );
     # deletion
     $mutation3 = Bio::LiveSeq::Mutation->new ( -seq => '',  # optional
     					     -seqori => 'TTG',  # optional
     					     -pos  => 100
     					     -len => 3
     					     );
     # complex
     $mutation4 = Bio::LiveSeq::Mutation->new ( -seq => 'CC',
     					     -seqori => 'TTG',  # optional
     					     -pos  => 100
     					     -len => 3
     					     );

DESCRIPTION
===========

   This class describes a local mutation event using minimalistic
description.  It is not necessary to know anything about the original
sequence. You need to give the changed sequence, the position of the
mutation in the (unidentified) reference sequence, and the length of the
affected subsequence in the reference sequence. If the original allele
sequence is given, the objects applying the mutation into the reference
sequence (e.g. See Bio/LiveSeq/Mutator) might
check for its validity.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to the
Bioperl mailing lists  Your participation is much appreciated.

     bioperl-l@bioperl.org                         - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via  email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Heikki Lehvaslaiho
===========================

   Email:  heikki@ebi.ac.uk Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

seq
---

     Title   : seq
     Usage   : $obj->seq();
     Function:

     Sets and returns the mutated sequence. No checking is done
     to validate the symbols.

     Example :
     Returns : string
     Args    : integer

seqori
------

     Title   : seqori
     Usage   : $obj->seqori();
     Function:

     Sets and returns the original subsequence in the reference
     sequence. No checking is done to validate the symbols.
     Optional value.

     Example :
     Returns : string
     Args    : string

pos
---

     Title   : pos
     Usage   : $obj->pos();
     Function:

     Sets and returns the position of the first element in the
     sequence.

     Example :
     Returns : string
     Args    : integer

len
---

     Title   : len
     Usage   : $obj->len();
     Function:

     Sets and returns the len of the affected original allele
     sequence.  If value is not set, defaults to the lenght of
     the mutated sequence (seq).

     Example :
     Returns : string
     Args    : string

label
-----

     Title   : label
     Usage   : $obj->label();
     Function:

     Sets and returns the label of the affected original allele
     location. Label is a stable identifier whereas location
     can be changed by mutations. Label comes from
     l<Bio::LiveSeq::Gene>.

     Example :
     Returns : string
     Args    : string

transpos
--------

     Title   : transpos
     Usage   : $obj->transpos();
     Function:

     Sets and returns the transcript position of the mutation.
     Set when associated with a reference sequence. Value
     depends on reference molecule and the co-ordinate system
     used.

     Example :
     Returns : string
     Args    : integer

issue
-----

     Title   : issue
     Usage   : $obj->issue();
     Function:

     Sets and returns the position of the mutation in an array
     of mutations to be issued. Set after the validity of the
     mutation has been confirmed.

     Example :
     Returns : string
     Args    : integer

prelabel
--------

     Title   : prelabel
     Usage   : $obj->prelabel();
     Function:

     Sets and returns the prelabel of the affected original allele
     location. Prelabel is a stable identifier whereas location
     can be changed by mutations. Prelabel comes from
     l<Bio::LiveSeq::Gene>.

     Example :
     Returns : string
     Args    : string

postlabel
---------

     Title   : postlabel
     Usage   : $obj->postlabel();
     Function:

     Sets and returns the postlabel of the affected original allele
     location. Postlabel is a stable identifier whereas location
     can be changed by mutations. Postlabel comes from
     l<Bio::LiveSeq::Gene>.

     Example :
     Returns : string
     Args    : string

lastlabel
---------

     Title   : lastlabel
     Usage   : $obj->lastlabel();
     Function:

     Sets and returns the lastlabel of the affected original allele
     location. Lastlabel is a stable identifier whereas location
     can be changed by mutations. Lastlabel comes from
     l<Bio::LiveSeq::Gene>.

     Example :
     Returns : string
     Args    : string

Package mutating LiveSequences
******************************

NAME
====

   Bio::LiveSeq::Mutator - Package mutating LiveSequences

SYNOPSIS
========

     # $gene is a Bio::LiveSeq::Gene object
     my $mutate = Bio::LiveSeq::Mutator->new('-gene' => $gene,
     					  '-numbering' => "coding"
     					   );
     # $mut is a Bio::LiveSeq::Mutation object
     $mutate->add_Mutation($mut);
     # $results is a Bio::Variation::SeqDiff object
     my $results=$mutate->change_gene();
     if ($results) {
         my $out = Bio::Variation::IO->new( '-format' => 'flat');
         $out->write($results);
     }

DESCRIPTION
===========

     This class mutates L<Bio::LiveSeq::Gene> objects and returns
     L<Bio::Variation::SeqDiff> object. Mutations are described as
     L<Bio::LiveSeq::Mutation> objects.

FEEDBACK
========

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to the
Bioperl mailing lists  Your participation is much appreciated.

     bioperl-l@bioperl.org                         - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via  email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Heikki Lehvaslaiho & Joseph A.L. Insana
================================================

     Email:  heikki@ebi.ac.uk
             insana@ebi.ac.uk, jinsana@gmx.net

     Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

     The rest of the documentation details each of the object
     methods. Internal methods are usually preceded with a _

gene
----

     Title   : gene
     Usage   : $mutobj = $obj->gene;
             : $mutobj = $obj->gene($objref);
     Function:

     Returns or sets the link-reference to a
     L<Bio::LiveSeq::Gene> object. If no value has ben set, it
     will return undef

     Returns : an object reference  or undef
     Args    : a L<Bio::LiveSeq::Gene>

numbering
---------

     Title   : numbering
     Usage   : $obj->numbering();
     Function:

     Sets and returns coordinate system used in positioning the
     mutations.

     Example :
     Returns : string
     Args    : string (coding [transcript number] | entry)

add_Mutation
------------

     Title   : add_Mutation
     Usage   : $self->add_Mutation($ref)
     Function: adds a L<Bio::Liveseq::Mutation> object
     Example :
     Returns :
     Args    : a L<Bio::Liveseq::Mutation>

each_Mutation
-------------

     Title   : each_Mutation
     Usage   : foreach $ref ( $a->each_Mutation )
     Function: gets an array of L<Bio::Liveseq::Mutation> objects
     Example :
     Returns : array of Mutations
     Args    :

mutation
--------

     Title   : mutation
     Usage   : $mutobj = $obj->mutation;
             : $mutobj = $obj->mutation($objref);
     Function:

     Returns or sets the link-reference to the current mutation
     object.  If the value is not set, it will return undef.
     Internal method.

     Returns : an object reference  or undef

DNA
---

     Title   : DNA
     Usage   : $mutobj = $obj->DNA;
             : $mutobj = $obj->DNA($objref);
     Function:

     Returns or sets the reference to the LiveSeq object holding
     the reference sequence. If there is no link, it will return
     undef.
     Internal method.

     Returns : an object reference or undef

RNA
---

     Title   : RNA
     Usage   : $mutobj = $obj->RNA;
             : $mutobj = $obj->RNA($objref);
     Function:

     Returns or sets the reference to the LiveSeq object holding
     the reference sequence. If the value is not set, it will return
     undef.
     Internal method.

     Returns : an object reference  or undef

dnamut
------

     Title   : dnamut
     Usage   : $mutobj = $obj->dnamut;
             : $mutobj = $obj->dnamut($objref);
     Function:

     Returns or sets the reference to the current DNAMutation object.
     If the value is not set, it will return undef.
     Internal method.

     Returns : an L<Bio::Variation::DNAMutation> or undef

rnachange
---------

     Title   : rnachange
     Usage   : $mutobj = $obj->rnachange;
             : $mutobj = $obj->rnachange($objref);
     Function:

     Returns or sets the reference to the current RNAChange object.
     If the value is not set, it will return undef.
     Internal method.

     Returns : an L<Bio::Variation::RNAChange> or undef

aachange
--------

     Title   : aachange
     Usage   : $mutobj = $obj->aachange;
             : $mutobj = $obj->aachange($objref);
     Function:

     Returns or sets the reference to the current AAChange object.
     If the value is not set, it will return undef.
     Internal method.

     Returns : an L<Bio::Variation::AAChange> or undef

exons
-----

     Title   : exons
     Usage   : $mutobj = $obj->exons;
             : $mutobj = $obj->exons($objref);
     Function:

     Returns or sets the reference to a current array of Exons.
     If the value is not set, it will return undef.
     Internal method.

     Returns : an array of L<Bio::LiveSeq::Exon> objects or undef

change_gene
-----------

     Title   : change_gene
     Usage   : my $mutate = Bio::LiveSeq::Mutator->new(-gene => $gene,
     						   numbering => "coding"
     						   );
               $mutate->add_Mutation($mut);
               my $results=$mutate->change_gene();

     Function:

     Returns a Bio::Variation::SeqDiff object containing the
     results of the changes performed according to the
     instructions present in the mutmatrix.  The -numbering
     argument decides what molecule is being changed and what
     numbering scheme being used:

     -numbering => "entry"

     determines the DNA level, using the numbering of the
     beginning of the sequence

     -numbering => "coding"

     determines the cDNA level, using the numbering from the
     beginning of the 1st transcript

     Alternative transcripts can be used by specifying "coding 2" or
     "coding 3" ...

     Args    : Bio::LiveSeq::Gene object
               reference to a mutmatrix array of arrays
               string specifying a numbering scheme (defaults to 'coding')
     Returns : Bio::Variation::SeqDiff object or 0 on error

_mutationpos2label
------------------

     Title   : _mutationpos2label
     Usage   :
     Function:
     Example :
     Returns : number of valid mutations
     Args    : LiveSeq sequence object

_set_DNAMutation
----------------

     Title   : _set_DNAMutation
     Usage   :
     Function:

     Stores DNA level mutation attributes before mutation into
     L<Bio::Variation::DNAMutation> object.  Links it to SeqDiff
     object.

     Example :
     Returns : L<Bio::Variation::DNAMutation> object
     Args    : L<Bio::Variation::SeqDiff> object

_set_effects
------------

     Title   : _set_effects
     Usage   :
     Function:

     Stores RNA and AA level mutation attributes before mutation
     into L<Bio::Variation::RNACange> and
     L<Bio::Variation::AACange> objects.  Links them to
     SeqDiff object.

     Example :
     Returns :
     Args    : L<Bio::Variation::SeqDiff> object
               L<Bio::Variation::DNAMutation> object

_untranslated
-------------

     Title   : _untranslated
     Usage   :
     Function:

     Stores RNA change attributes before mutation
     into L<Bio::Variation::RNAChange object.  Links it to
     SeqDiff object.

     Example :
     Returns :
     Args    : L<Bio::Variation::SeqDiff> object
               L<Bio::Variation::DNAMutation> object

Prim_Transcript class for LiveSeq
*********************************

NAME
====

   Bio::LiveSeq::Prim_Transcript - Prim_Transcript class for LiveSeq

SYNOPSIS
========

     # documentation needed

DESCRIPTION
===========

   Class for PRIM_TRANSCRIPT objects. They consist of a beginlabel, an
endlabel (both referring to a LiveSeq DNA object) and a strand.  The
strand could be 1 (forward strand, default), -1 (reverse strand).

AUTHOR - Joseph A.L. Insana
===========================

   Email:  Insana@ebi.ac.uk, jinsana@gmx.net

   Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
===

     Title   : new
     Usage   : $intron1=Bio::LiveSeq::Prim_Transcript->new(-seq => $objref,
     							-start => $startlabel,
     							-end => $endlabel,
     							-strand => 1
     							);

     Function: generates a new Bio::LiveSeq::Prim_Transcript
     Returns : reference to a new object of class Prim_Transcript
     Errorcode -1
     Args    : two labels and an integer

Range abstract class for LiveSeq
********************************

NAME
====

   Bio::LiveSeq::Range - Range abstract class for LiveSeq

SYNOPSIS
========

     # documentation needed

DESCRIPTION
===========

   This is used as parent for exon and intron classes.

AUTHOR - Joseph A.L. Insana
===========================

   Email:  Insana@ebi.ac.uk, jinsana@gmx.net

   Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
===

     Title   : new
     Usage   : $range1 = Bio::LiveSeq::Range->new(-seq => $obj_ref,
                                                  -start => $beginlabel,
                                                  -end => $endlabel, -strand => 1);

     Function: generates a new Bio::LiveSeq::Range
     Returns : reference to a new object of class Range
     Errorcode -1
     Args    : two labels, an obj_ref and an integer
               strand 1=forward strand, strand -1=reverse strand
               if strand not specified, it defaults to 1
               the -seq argument must point to the underlying DNA LiveSeq object

valid
=====

     Title   : valid
     Usage   : $boolean = $obj->valid($label)
     Function: tests if a label exists AND is part of the object
     Returns : boolean
     Args    : label

Repeat_Region class for LiveSeq
*******************************

NAME
====

   Bio::LiveSeq::Repeat_Region - Repeat_Region class for LiveSeq

SYNOPSIS
========

     # documentation needed

DESCRIPTION
===========

   Class for REPEAT_REGION objects. They consist of a beginlabel, an
endlabel (both referring to a LiveSeq DNA object) and a strand.  The
strand could be 1 (forward strand, default), -1 (reverse strand).

AUTHOR - Joseph A.L. Insana
===========================

   Email:  Insana@ebi.ac.uk, jinsana@gmx.net

   Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, Regioned Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
===

     Title   : new
     Usage   : $intron1=Bio::LiveSeq::Repeat_Region->new(-seq => $objref,
     					      -start => $startlabel,
     					      -end => $endlabel, -strand => 1);

     Function: generates a new Bio::LiveSeq::Repeat_Region
     Returns : reference to a new object of class Repeat_Region
     Errorcode -1
     Args    : two labels and an integer

Repeat_Unit class for LiveSeq
*****************************

NAME
====

   Bio::LiveSeq::Repeat_Unit - Repeat_Unit class for LiveSeq

SYNOPSIS
========

     # documentation needed

DESCRIPTION
===========

   Class for REPEAT_UNIT objects. They consist of a beginlabel, an
endlabel (both referring to a LiveSeq DNA object) and a strand.  The
strand could be 1 (forward strand, default), -1 (reverse strand).

AUTHOR - Joseph A.L. Insana
===========================

   Email:  Insana@ebi.ac.uk, jinsana@gmx.net

   Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
===

     Title   : new
     Usage   : $intron1=Bio::LiveSeq::Repeat_Unit->new(-seq => $objref,
     					      -start => $startlabel,
     					      -end => $endlabel, -strand => 1);

     Function: generates a new Bio::LiveSeq::Repeat_Unit
     Returns : reference to a new object of class Repeat_Unit
     Errorcode -1
     Args    : two labels and an integer

Abstract sequence interface class for LiveSeq
*********************************************

NAME
====

   Bio::LiveSeq::SeqI - Abstract sequence interface class for LiveSeq

SYNOPSIS
========

     # documentation needed

DESCRIPTION
===========

   This class implements BioPerl PrimarySeqI interface for Live Seq
objects.

   One of the main difference in LiveSequence compared to traditional
"string" sequences is that coordinate systems are flexible. Typically gene
nucleotide numbering starts from 1 at the first character of the initiator
codon (A in ATG). This means that negative positions are possible and
common!

   Secondly, the sequence manipulation methods do not return a new
sequence object but change the current object. The current status can be
written out to BioPerl sequence objects.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     vsns-bcd-perl@lists.uni-bielefeld.de          - General discussion
     vsns-bcd-perl-guts@lists.uni-bielefeld.de     - Technically-oriented discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via  email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Joseph A.L. Insana
===========================

   Email:  Insana@ebi.ac.uk, jinsana@gmx.net

   Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

   Some note on the terminology/notation of method names:  label: a unique
pointer to a single nucleotide  position: the position of a nucleotide
according to a particular coordinate            system (e.g. counting
downstream from a particular label taken as            number 1)  base:
the one letter code for a nucleotide (i.e.: "a" "t" "c" "g")

     a base is the "value" that an "element" of a "chain" can assume
       (see documentation on the Chain datastructure if interested)

seq
---

     Title   : seq
     Usage   : $string    = $obj->seq()
     Function: Returns the complete sequence of an object as a string of letters.
               Suggested cases are upper case for proteins and lower case for
               DNA sequence (IUPAC standard),
     Returns : a string

all_labels
----------

     Title   : all_labels
     Usage   : @labels = $obj->all_labels()
     Function: all the labels of every nucleotide an object is composed of
     Returns : an array of labels
     Args    : none

labelsubseq
===========

     Title   : labelsubseq
     Usage   : $dna->labelsubseq();
             : $dna->labelsubseq($startlabel);
             : $dna->labelsubseq($startlabel,$length);
             : $dna->labelsubseq($startlabel,undef,$endlabel);
     e.g.    : $dna->labelsubseq(4,undef,8);
     Function: prints the sequence as string. The difference between labelsubseq
               and normal subseq is that it uses /labels/ as arguments, instead
               than positions. This allows for faster and more efficient lookup,
               skipping the (usually) lengthy conversion of positions into labels.
               This is expecially useful for manipulating with high power
               LiveSeq objects, knowing the labels and exploiting their
               usefulness.
     Returns : a string
     Errorcode -1
     Args    : without arguments it returns the entire sequence
               with a startlabel it returns the sequence downstream that label
               if a length is specified, it returns only that number of bases
               if an endlabel is specified, it overrides the length argument
                and prints instead up to that label (included)
     Defaults: $startlabel defaults to the beginning of the entire sequence
               $endlabel defaults to the end of the entire sequence

subseq
------

     Title   : subseq
     Usage   : $substring = $obj->subseq(10,40);
             : $substring = $obj->subseq(10,undef,4);
     Function: returns the subseq from start to end, where the first base
               is 1 and the number is inclusive, ie 1-2 are the first two
               bases of the sequence

     Start cannot be larger than end but can be equal.

     Allows for negative numbers $obj->subseq(-10,-1). By
     definition, there is no 0!
                 -5  -1 1   5
          gctagcgcccaac atggctcgctg

     This allows to retrieve sequences upstream from given position.

     The precedence is from left to right: if END is given LENGTH is
     ignored.

     Examples: $obj->subseq(-10,undef,10) returns 10 elements before position 1
               $obj->subseq(4,8) returns elements from the 4th to the 8th, inclusive

     Returns : a string
     Errorcode: -1
     Args    : start,  integer, defaults to start of the sequence
               end,    integer, '' or undef, defaults to end of the sequence
               length, integer, '' or undef
               an optional strand (1 or -1) 4th argument
                if strand argument is not given, it will default to the object
                argment. This argument is useful when a call is issued from a child
                of a parent object containing the subseq method

length
======

     Title   : length
     Usage   : $seq->length();
     Function: returns the number of nucleotides (or the number of aminoacids)
               in the entire sequence
     Returns : an integer
     Errorcode -1
     Args    : none

display_id
----------

     Title   : display_id
     Usage   : $id_string = $obj->display_id();
     Function: returns the display id, alias the common name of the object

     The semantics of this is that it is the most likely string
     to be used as an identifier of the sequence, and likely to
     have "human" readability.  The id is equivalent to the ID
     field of the GenBank/EMBL databanks and the id field of the
     Swissprot/sptrembl database. In fasta format, the >(\S+) is
     presumed to be the id, though some people overload the id
     to embed other information.

     See also: accession_number
     Returns : a string
     Args    : none

accession_number
----------------

     Title   : accession_number
     Usage   : $unique_biological_key = $obj->accession_number;
     Function: Returns the unique biological id for a sequence, commonly
               called the accession_number.
               Notice that primary_id() provides the unique id for the
               implemetation, allowing multiple objects to have the same accession
               number in a particular implementation.

     For objects with no accession_number this method returns "unknown".
      Returns : a string
      Args    : none

primary_id
----------

     Title   : primary_id
     Usage   : $unique_implementation_key = $obj->primary_id;
     Function: Returns the unique id for this object in this
               implementation. This allows implementations to manage their own
               object ids in a way the implementation can control. Clients can
               expect one id to map to one object.

     For sequences with no primary_id, this method returns
     a stringified memory location.

     Returns : A string
     Args    : None

change
------

     Title   : change
     Usage   : $substring = $obj->change('AA', 10);
     Function: changes, modifies, mutates the LiveSequence
     Examples:
            $obj->change('',   10);      delete nucleotide #10
            $obj->change('',   10, 2);   delete two nucleotides starting from #10
            $obj->change('G',  10);      change nuc #10 to 'G'
            $obj->change('GA', 10, 4);   replace #10 and 3 following with 'GA'
            $obj->change('GA', 10, 2));  is same as $obj->change('GA',  10);
            $obj->change('GA', 10, 0 );  insert 'GA' before nucleotide at #10
            $obj->change('GA', 10, 1);   GA inserted before #10, #10 deleted
            $obj->change('GATC', 10, 2); GATC inserted before #10, #10&#11 deleted
            $obj->change('GATC', 10, 6); GATC inserted before #10, #10-#15 deleted

     Returns : a string of deleted bases (if any) or 1 (everything OK)
     Errorcode: -1
     Args    : seq,    string, or '' ('' = undef = 0 = deletion)
               start,  integer
               length, integer (optional)

positionchange
--------------

     Title   : positionchange
     Function: Exactly like change. I.e. change() defaults to positionchange()

labelchange
-----------

     Title   : labelchange
     Function: Exactly like change but uses a /label/ instead than a position
               as second argument. This allows for multiple changes in a LiveSeq
               without the burden of recomputing positions. I.e. for a multiple
               change in two different points of the LiveSeq, the approach would
               be the following: fetch the correct labels out of the two different
               positions (method: label($position)) and then use the labelchange()
               method to modify the sequence using those labels instead than
               relying on the positions (that would have modified after the
               first change).

valid
=====

     Title   : valid
     Usage   : $boolean = $obj->valid($label)
     Function: tests if a label exists inside the object
     Returns : boolean
     Args    : label

start
=====

     Title   : start
     Usage   : $startlabel=$obj->start()
     Function: returns the label of the first nucleotide of the object (exon, CDS)
     Returns : label
     Args    : none

end
===

     Title   : end
     Usage   : $endlabel=$obj->end()
     Function: returns the label of the last nucleotide of the object (exon, CDS)
     Returns : label
     Args    : none

strand
======

     Title   : strand
     Usage   : $strand=$obj->strand()
               $obj->strand($strand)
     Function: gets or sets strand information, being 1 or -1 (forward or reverse)
     Returns : -1 or 1
     Args    : none OR -1 or 1

moltype
=======

     Title   : moltype
     Usage   : if( $obj->moltype eq 'dna' ) { /Do Something/ }
     Function: Returns the type of sequence being one of
               'dna', 'rna' or 'protein'. This is case sensitive.

     Returns : a string either 'dna','rna','protein'.
     Args    : none
     Note    : "circular dna" is set as dna

     =cut

   sub moltype {   my %valid_type = map {$_, 1} qw( dna rna protein );
my ($obj,$value) = @_;   if (defined $value) {     $value =~ s/circular
dna/dna/;     unless ( $valid_type{$value} ) {       carp "Molecular type
'$value' is not a valid type";     }     $obj->{'moltype'} = $value;   }
return $obj->{'moltype'}; }

coordinate_start
================

     Title   : coordinate_start
     Usage   : $coordstartlabel=$obj->coordinate_start()
             : $coordstartlabel=$obj->coordinate_start($label)
     Function: returns and optionally sets the first label of the coordinate
               system used
               For some objects only labels inside the object or in frame (for
               Translation objects) will be allowed to get set as coordinate start

     Returns : label. It returns 0 if label not found.
     Errorcode -1
     Args    : an optional reference $label that is position 1

label
=====

     Title   : label
     Usage   : $seq->label($position)
             : $seq->label($position,$firstlabel)
     Examples: $nextlabel=$seq->label(2,$label) -> retrieves the following label
             : $prevlabel=$seq->label(-1,$label) -> retrieves the preceding label

     Function: returns the label of the nucleotide at $position from current
               coordinate start
     Returns : a label. It returns 0 if label not found.
     Errorcode -1
     Args    : a position,
               an optional reference $firstlabel that is to be used as position 1
               an optional strand (1 or -1) argument
                if strand argument is not given, it will default to the object
                argument. This argument is useful when a call is issued from a child
                of a parent object containing the subseq method

position
========

     Title   : position
     Usage   : $seq->position($label)
             : $seq->position($label,$firstlabel)
     Function: returns the position of nucleotide at $label
     Returns : the position of the label from current coordinate start
     Errorcode 0
     Args    : a label pointing to a certain nucleotide (e.g. start of exon)
               an optional "firstlabel" as reference to count from
               an optional strand (1 or -1) argument
                if strand argument is not given, it will default to the object
                argument. This argument is useful when a call is issued from a child
                of a parent object containing the subseq method

follows
=======

     Title   : follows
     Usage   : $seq->follows($firstlabel,$secondlabel)
             : $seq->follows($firstlabel,$secondlabel,$strand)
     Function: checks if SECONDlabel follows FIRSTlabel, undependent of the strand
               i.e. it checks downstream for forward strand and
               upstream for reverse strand
     Returns : 1 or 0
     Errorcode -1
     Args    : two labels
               an optional strand (1 or -1) argument
                if strand argument is not given, it will default to the object
                argument. This argument is useful when a call is issued from a child
                of a parent object containing the subseq method

translate
---------

     Title   : translate
     Usage   : $protein_seq = $obj->translate
     Function: Provides the translation of the DNA sequence
               using full IUPAC ambiguities in DNA/RNA and amino acid codes.

     The resulting translation is identical to EMBL/TREMBL database
     translations.

     Returns : a string
     Args    : character for terminator (optional) defaults to '*'
               character for unknown amino acid (optional) defaults to 'X'
               frame (optional) valid values 0, 1, 3, defaults to 0
               codon table id (optional) defaults to 1

translate_string
----------------

     Title   : translate_string
     Usage   : $protein_seq = $obj->translate_string("attcgtgttgatcgatta");
     Function: Like translate, but can be used to translate subsequences after
               having retrieved them as string.
     Args    : 1st argument is a string. Optional following arguments: like in
               the translate method

gene
====

     Title   : gene
     Usage   : my $gene=$obj->gene;
     Function: Gets or sets the reference to the LiveSeq::Gene object.
               Objects that are features of a LiveSeq Gene will have this
               attribute set automatically.

     Returns : reference to an object of class Gene
     Note    : if Gene object is not set, this method will return 0;
     Args    : none or reference to object of class Bio::LiveSeq::Gene

obj_valid
=========

     Title   : obj_valid
     Usage   : if ($obj->obj_valid) {do something;}
     Function: Checks if start and end labels are still valid for the ojbect,
               i.e. tests if the LiveSeq object is still valid
     Returns : boolean
     Args    : none

name
----

     Title   : name
     Usage   : $name = $obj->name;
             : $name = $obj->name("ABCD");
     Function: Returns or sets the name of the object.
               If there is no name, it will return "unknown";
     Returns : A string
     Args    : None

description
-----------

     Title   : description
     Usage   : $description = $obj->description;
             : $description = $obj->description("ABCD");
     Function: Returns or sets the description of the object.
               If there is no description, it will return "unknown";
     Returns : A string
     Args    : None

source
------

     Title   : source
     Usage   : $name = $obj->source;
             : $name = $obj->source("Homo sapiens");
     Function: Returns or sets the organism that is source of the object.
               If there is no source, it will return "unknown";
     Returns : A string
     Args    : None

Transcript class for LiveSeq
****************************

NAME
====

   Bio::LiveSeq::Transcript - Transcript class for LiveSeq

SYNOPSIS
========

     # documentation needed

DESCRIPTION
===========

   This stores informations about coding sequences (CDS).  The
implementation is that a Transcript object accesses a collection of Exon
objects, inferring from them the nucleotide structure and sequence.

AUTHOR - Joseph A.L. Insana
===========================

   Email:  Insana@ebi.ac.uk, jinsana@gmx.net

   Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
---

     Title   : new
     Usage   : $transcript = Bio::LiveSeq::Transcript->new(-exons => \@obj_refs);

     Function: generates a new Bio::LiveSeq::Transcript
     Returns : reference to a new object of class Transcript
     Errorcode -1
     Args    : reference to an array of Exon object references

all_Exons    Title   : all_Exons  Usage   : $transcript_obj->all_Exons()  Function: returns references to all Exon objects the Transcript is composed of  Example : foreach $exon ($transcript->all_Exons()) { do_something }  Returns : array of object references  Args    : none   =cut
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

   sub all_Exons {   my $self=shift;   my $exonsref=$self->{'exons'};   my
@exons=@{$exonsref};   my @newexons;   my $exon;   foreach $exon (@exons) {
   unless ($exon->obj_valid) {       carp "$exon no more valid, start or
end label lost, skipping....";     } else {       push(@newexons,$exon);
 }   }   if ($#exons != $#newexons) {     # update exons field
$self->{'exons'}=\@newexons;   }   return (@newexons); }

downstream_seq    Title   : downstream_seq  Usage   : $transcript_obj->downstream_seq()          : $transcript_obj->downstream_seq(64)  Function: returns a string of nucleotides downstream of the end of the            CDS. If there is some information of the real mRNA, from features in            an attached Gene object, it will return up to those boundaries.            Otherwise it will return 1000 nucleotides.            If an argument is given it will override the default 1000 number            and return instead /that/ requested number of nucleotides.            But if a Gene object is attached, this argument will be ignored.  Returns : string  Args    : an optional integer number of nucleotides to be returned instead of            the default if no gene attached
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

upstream_seq    Title   : upstream_seq  Usage   : $transcript_obj->upstream_seq()          : $transcript_obj->upstream_seq(64)  Function: just like downstream_seq but returns nucleotides before the ATG  Note    : the default, if no Gene information present and no nucleotides            number given, is to return up to 400 nucleotides.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

get_Translation
---------------

     Title   : valid
     Usage   : $translation = $obj->get_Translation()
     Function: retrieves the reference to the object of class Translation (if any)
               attached to a LiveSeq object
     Returns : object reference
     Args    : none

translation_table
-----------------

     Title   : translation_table
     Usage   : $name = $obj->translation_table;
             : $name = $obj->translation_table(11);
     Function: Returns or sets the translation_table used for translating the
               transcript.
               If it has never been set, it will return undef.
     Returns : an integer

frame
-----

     Title   : frame
     Usage   : $frame = $transcript->frame($label);
     Function: Returns the frame of a particular nucleotide.
               Frame can be 0 1 or 2 and means the position in the codon triplet
               of the particulat nucleotide. 0 is the first codon_position.
               Codon_position (1 2 3) is simply frame+1.
               If the label asked for is not inside the Transcript, -1 will be
               returned.
     Args    : a label
     Returns : 0 1 or 2
     Errorcode -1

Translation class for LiveSeq
*****************************

NAME
====

   Bio::LiveSeq::Translation - Translation class for LiveSeq

SYNOPSIS
========

     #documentation needed

DESCRIPTION
===========

   This stores informations about aminoacids translations of transcripts.
The implementation is that a Translation object is the translation of a
Transcript object, with different possibilities of manipulation, different
coordinate system and eventually its own ranges (protein domains).

AUTHOR - Joseph A.L. Insana
===========================

   Email:  Insana@ebi.ac.uk, jinsana@gmx.net

   Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
===

     Title   : new
     Usage   : $protein = Bio::LiveSeq::Translation->new(-transcript => $transcr);

     Function: generates a new Bio::LiveSeq::Translation
     Returns : reference to a new object of class Translation
     Errorcode -1
     Args    : reference to an object of class Transcript

get_Transcript
--------------

     Title   : valid
     Usage   : $transcript = $obj->get_Transcript()
     Function: retrieves the reference to the object of class Transcript (if any)
               attached to a LiveSeq object
     Returns : object reference
     Args    : none

aa_ranges
---------

     Title   : aa_ranges
     Usage   : @proteinfeatures = $translation->aa_ranges()
     Function: to retrieve all the LiveSeq AARange objects attached to a
               Translation, usually created out of a SwissProt database entry
               crossreferenced from an EMBL CDS feature.
     Returns : an array
     Args    : none

A Sequence object with start/end points on it
*********************************************

NAME
====

   Bio::LocatableSeq - A Sequence object with start/end points on it

SYNOPSIS
========

   Give standard usage here

DESCRIPTION
===========

     # a normal sequence object
     $locseq->seq();
     $locseq->id();

     # has start,end points
     $locseq->start();
     $locseq->end();

     # inheriets off RangeI, so range operations possible

     $locseq->overlaps($seqfeature);

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

   The locatable sequence object was developed mainly because the
SimpleAlign object requires this functionality, and in the rewrite of the
Sequence object we had to decide what to do with this.

   It is, to be honest, not well integrated with the rest of bioperl, for
example, the trunc() function does not return a LocatableSeq object, as
some might have thought. There are all sorts of nasty gotcha's about
interactions between coordinate systems when these sort of objects are
used.

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

start
-----

     Title   : start
     Usage   : $obj->start($newval)
     Function:
     Returns : value of start
     Args    : newvalue (optional)

end
---

     Title   : end
     Usage   : $obj->end($newval)
     Function:
     Returns : value of end
     Args    : newvalue (optional)

strand
------

     Title   : strand
     Usage   : $obj->strand($newval)
     Function:
     Returns : value of strand
     Args    : newvalue (optional)

get_nse
-------

     Title   : get_nse
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

class implementing  Bio::Location::CoordinatePolicy as the average for WITHIN and the widest possible and reasonable range otherwise
************************************************************************************************************************************

NAME
====

   Bio::Location::AvWithinCoordPolicy - class implementing
Bio::Location::CoordinatePolicy as the average for WITHIN and the widest
possible and reasonable range otherwise

SYNOPSIS
========

   See Bio::Location::CoordinatePolicyI

DESCRIPTION
===========

   CoordinatePolicyI implementing objects are used by Bio::LocationI
implementing objects to determine integer-valued coordinates when asked
for it.

   This class will compute the coordinates such that for fuzzy locations
of type WITHIN and BETWEEN the average of the two limits will be returned,
and for all other locations it will return the widest possible range, but
by using some common sense. This means that e.g. locations like "<5..100"
(start before position 5) will return 5 as start (returned values have to
be positive integers).

FEEDBACK
========

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bio.perl.org/MailList.html - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp, Jason Stajich
===================================

   Email hlapp@gmx.net, jason@chg.mc.duke.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

start
-----

     Title   : start
     Usage   : $start = $policy->start($location);
     Function: Get the integer-valued start coordinate of the given location as
               computed by this computation policy.
     Returns : A positive integer number.
     Args    : A Bio::LocationI implementing object.

end
---

     Title   : end
     Usage   : $end = $policy->end($location);
     Function: Get the integer-valued end coordinate of the given location as
               computed by this computation policy.
     Returns : A positive integer number.
     Args    : A Bio::LocationI implementing object.

Abstract interface for objects implementing a certain policy of computing integer-valued coordinates of a Location
******************************************************************************************************************

NAME
====

   Bio::Location::CoordinatePolicyI - Abstract interface for objects
implementing a certain policy of computing integer-valued coordinates of a
Location

SYNOPSIS
========

     # get a location, e.g., from a SeqFeature
     $location = $feature->location();
     # examine its coordinate computation policy
     print "Location of feature ", $feature->primary_tag(), " employs a ",
           ref($location->coordinate_policy()),
           " instance for coordinate computation\n";
     # change the policy, e.g. because the user chose to do so
     $location->coordinate_policy(Bio::Location::NarrowestCoordPolicy->new());

DESCRIPTION
===========

   Objects implementing this interface are used by Bio::LocationI
implementing objects to determine integer-valued coordinates when asked
for it. While this may seem trivial for simple locations, there are
different ways to do it for fuzzy or compound (split) locations. Classes
implementing this interface implement a certain policy, like 'always
widest range', 'always smallest range', 'mean for BETWEEN locations', etc.
By installing a different policy object in a Location object, the
behaviour of coordinate computation can be changed on-the-fly, and with a
single line of code client-side.

FEEDBACK
========

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bio.perl.org/MailList.html - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp, Jason Stajich
===================================

   Email hlapp@gmx.net, jason@chg.mc.duke.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

start
-----

     Title   : start
     Usage   : $start = $policy->start($location);
     Function: Get the integer-valued start coordinate of the given location as
               computed by this computation policy.
     Returns : A positive integer number.
     Args    : A Bio::LocationI implementing object.

end
---

     Title   : end
     Usage   : $end = $policy->end($location);
     Function: Get the integer-valued end coordinate of the given location as
               computed by this computation policy.
     Returns : A positive integer number.
     Args    : A Bio::LocationI implementing object.

Implementation of a Location on a Sequence which has unclear start and/or end locations
***************************************************************************************

NAME
====

   Bio::Location::Fuzzy - Implementation of a Location on a Sequence which
has unclear start and/or end locations

SYNOPSIS
========

     my $fuzzylocation = new Bio::Location::Fuzzy(-start => '<30',
     						 -end   => 90,
     						 -loc_type => '.');

     print "location string is ", $fuzzylocation->to_FTstring();

DESCRIPTION
===========

   This module contains the necessary methods for representing a Fuzzy
Location, one that does not have clear start and/or end points.  This will
initially serve to handle features from Genbank/EMBL feature tables that
are written as 1^100 meaning between bases 1 and 100 or <100..300 meaning
it starts somewhere before 100.  Advanced implementations of this
interface may be able to handle the necessary logic of
overlaps/intersection/contains/union.  It was constructed to handle fuzzy
locations that can be represented in Genbank/EMBL.

FEEDBACK
========

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bio.perl.org/MailList.html - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Jason Stajich
======================

   Email jason@chg.mc.duke.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

loc_type
--------

     Title   : loc_type
     Usage   : my $location_type = $location->loc_type();
     Function: Get location type encoded as text
     Returns : string ('EXACT', 'WITHIN', 'BETWEEN')
     Args    : none

LocationI methods
=================

length
------

     Title   : length
     Usage   : $length = $fuzzy_loc->length();
     Function: Get the length of this location.

     Note that the length of a fuzzy location will always depend
     on the currently active interpretation of start and end. The
     result will therefore vary for different CoordinatePolicy objects.

     Returns : an integer
     Args    : none

start
-----

     Title   : start
     Usage   : $start = $fuzzy->start();
     Function: get/set start of this range, handling fuzzy_starts
     Returns : a positive integer representing the start of the location
     Args    : start location on set (can be fuzzy point string)

end
---

     Title   : end
     Usage   : $end = $fuzzy->end();
     Function: get/set end of this range, handling fuzzy_ends
     Returns : a positive integer representing the end of the range
     Args    : end location on set (can be fuzzy string)

min_start
---------

     Title   : min_start
     Usage   : $min_start = $fuzzy->min_start();
     Function: get/set the minimum starting point
     Returns : the minimum starting point from the contained sublocations
     Args    : integer or undef on set

max_start
---------

     Title   : max_start
     Usage   : my $maxstart = $location->max_start();
     Function: Get/set maximum starting location of feature startpoint
     Returns : integer or undef if no maximum starting point.
     Args    : integer or undef on set

start_pos_type
--------------

     Title   : start_pos_type
     Usage   : my $start_pos_type = $location->start_pos_type();
     Function: Get/set start position type.
     Returns : type of position coded as text
               ('BEFORE', 'AFTER', 'EXACT','WITHIN', 'BETWEEN')
     Args    : a string on set

min_end
-------

     Title   : min_end
     Usage   : my $minend = $location->min_end();
     Function: Get/set minimum ending location of feature endpoint
     Returns : integer or undef if no minimum ending point.
     Args    : integer or undef on set

max_end
-------

     Title   : max_end
     Usage   : my $maxend = $location->max_end();
     Function: Get/set maximum ending location of feature endpoint
     Returns : integer or undef if no maximum ending point.
     Args    : integer or undef on set

end_pos_type
------------

     Title   : end_pos_type
     Usage   : my $end_pos_type = $location->end_pos_type();
     Function: Get/set end position type.
     Returns : type of position coded as text
               ('BEFORE', 'AFTER', 'EXACT','WITHIN', 'BETWEEN')
     Args    : a string on set

seq_id
------

     Title   : seq_id
     Usage   : my $seqid = $location->seq_id();
     Function: Get/Set seq_id that location refers to
     Returns : seq_id
     Args    : [optional] seq_id value to set

coordinate_policy
-----------------

     Title   : coordinate_policy
     Usage   : $policy = $location->coordinate_policy();
               $location->coordinate_policy($mypolicy); # set may not be possible
     Function: Get the coordinate computing policy employed by this object.

     See Bio::Location::CoordinatePolicyI for documentation about
     the policy object and its use.

     The interface *does not* require implementing classes to accept
     setting of a different policy. The implementation provided here
     does, however, allow to do so.

     Implementors of this interface are expected to initialize every
     new instance with a CoordinatePolicyI object. The implementation
     provided here will return a default policy object if none has
     been set yet. To change this default policy object call this
     method as a class method with an appropriate argument. Note that
     in this case only subsequently created Location objects will be
     affected.

     Returns : A Bio::Location::CoordinatePolicyI implementing object.
     Args    : On set, a Bio::Location::CoordinatePolicyI implementing object.

to_FTstring
-----------

     Title   : to_FTstring
     Usage   : my $locstr = $location->to_FTstring()
     Function: Get/Set seq_id that location refers to
     Returns : seq_id
     Args    : [optional] seq_id value to set

_fuzzypointdecode
-----------------

     Title   : _fuzzypointdecode
     Usage   : ($type,$min,$max) = $self->_fuzzypointdecode('<5');
     Function: Decode a fuzzy string.
     Returns : A 3-element array consisting of the type of location, the
               minimum integer, and the maximum integer describing the range
               of coordinates this start or endpoint refers to. Minimum or
               maximum coordinate may be undefined.
             : Returns empty array on fail.
     Args    : fuzzypoint string

Abstract interface of a Location on a Sequence which has unclear start/end location
***********************************************************************************

NAME
====

   Bio::Location::FuzzyLocationI - Abstract interface of a Location on a
Sequence which has unclear start/end location

SYNOPSIS
========

     # Get a FuzzyLocationI object somehow
     print "Fuzzy FT location string is ", $location->to_FTstring();
     print "location is of the type ", $location->loc_type, "\n";

DESCRIPTION
===========

   This interface encapsulates the necessary methods for representing a
Fuzzy Location, one that does not have clear start and/or end points.
This will initially serve to handle features from Genbank/EMBL feature
tables that are written as 1^100 meaning between bases 1 and 100 or
<100..300 meaning it starts somewhere before 100.  Advanced
implementations of this interface may be able to handle the necessary
logic of overlaps/intersection/contains/union.  It was constructed to
handle fuzzy locations that can be represented in Genbank/EMBL.

FEEDBACK
========

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bio.perl.org/MailList.html - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Jason Stajich
======================

   Email jason@chg.mc.duke.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

loc_type
--------

     Title   : loc_type
     Usage   : my $location_type = $location->loc_type();
     Function: Get location type encoded as text
     Returns : string ('EXACT', 'WITHIN', 'BETWEEN')
     Args    : none

LocationI methods
=================

min_start
---------

     Title   : min_start
     Usage   : my $minstart = $location->min_start();
     Function: Get minimum starting location of feature startpoint
     Returns : integer or undef if no maximum starting point.
     Args    : none

max_start
---------

     Title   : max_start
     Usage   : my $maxstart = $location->max_start();
     Function: Get maximum starting location of feature startpoint
     Returns : integer or undef if no maximum starting point.
     Args    : none

start_pos_type
--------------

     Title   : start_pos_type
     Usage   : my $start_pos_type = $location->start_pos_type();
     Function: Get start position type (ie <,>, ^)
     Returns : type of position coded as text
               ('BEFORE', 'AFTER', 'EXACT','WITHIN', 'BETWEEN')
     Args    : none

min_end
-------

     Title   : min_end
     Usage   : my $minend = $location->min_end();
     Function: Get minimum ending location of feature endpoint
     Returns : integer or undef if no minimum ending point.
     Args    : none

max_end
-------

     Title   : max_end
     Usage   : my $maxend = $location->max_end();
     Function: Get maximum ending location of feature endpoint
     Returns : integer or undef if no maximum ending point.
     Args    : none

end_pos_type
------------

     Title   : end_pos_type
     Usage   : my $end_pos_type = $location->end_pos_type();
     Function: Get end position type (ie <,>, ^)
     Returns : type of position coded as text
               ('BEFORE', 'AFTER', 'EXACT','WITHIN', 'BETWEEN')
     Args    : none

seq_id
------

     Title   : seq_id
     Usage   : my $seqid = $location->seq_id();
     Function: Get/Set seq_id that location refers to
     Returns : seq_id
     Args    : [optional] seq_id value to set

coordinate_policy
-----------------

     Title   : coordinate_policy
     Usage   : $policy = $location->coordinate_policy();
               $location->coordinate_policy($mypolicy); # set may not be possible
     Function: Get the coordinate computing policy employed by this object.

     See Bio::Location::CoordinatePolicyI for documentation about
     the policy object and its use.

     The interface *does not* require implementing classes to accept
     setting of a different policy. The implementation provided here
     does, however, allow to do so.

     Implementors of this interface are expected to initialize every
     new instance with a CoordinatePolicyI object. The implementation
     provided here will return a default policy object if none has
     been set yet. To change this default policy object call this
     method as a class method with an appropriate argument. Note that
     in this case only subsequently created Location objects will be
     affected.

     Returns : A Bio::Location::CoordinatePolicyI implementing object.
     Args    : On set, a Bio::Location::CoordinatePolicyI implementing object.

to_FTstring
-----------

     Title   : to_FTstring
     Usage   : my $locstr = $location->to_FTstring()
     Function: returns the FeatureTable string of this location
     Returns : string
     Args    : none

class implementing  Bio::Location::CoordinatePolicy as the narrowest possible and reasonable range
**************************************************************************************************

NAME
====

   Bio::Location::NarrowestCoordPolicy - class implementing
Bio::Location::CoordinatePolicy as the narrowest possible and reasonable
range

SYNOPSIS
========

   See Bio::Location::CoordinatePolicyI

DESCRIPTION
===========

   CoordinatePolicyI implementing objects are used by Bio::LocationI
implementing objects to determine integer-valued coordinates when asked
for it.

   This class will compute the coordinates such that always the narrowest
possible range is returned, but by using some common sense. This means
that e.g.  locations like ">5..100" (start before position 5) will return
5 as start (returned values have to be positive integers).

FEEDBACK
========

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bio.perl.org/MailList.html - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp, Jason Stajich
===================================

   Email hlapp@gmx.net, jason@chg.mc.duke.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

start
-----

     Title   : start
     Usage   : $start = $policy->start($location);
     Function: Get the integer-valued start coordinate of the given location as
               computed by this computation policy.
     Returns : A positive integer number.
     Args    : A Bio::LocationI implementing object.

end
---

     Title   : end
     Usage   : $end = $policy->end($location);
     Function: Get the integer-valued end coordinate of the given location as
               computed by this computation policy.
     Returns : A positive integer number.
     Args    : A Bio::LocationI implementing object.

Implementation of a Simple Location on a Sequence
*************************************************

NAME
====

   Bio::Location::Simple - Implementation of a Simple Location on a
Sequence

SYNOPSIS
========

     my $location = new Bio::Location::Simple(-start => 1, -end => 100,
     					     -strand => 1 );

     if( $location->strand == -1 ) {
     	printf "complement(%d..%d)\n", $location->start, $location->end;
     } else {
     	printf "%d..%d\n", $location->start, $location->end;
     }

DESCRIPTION
===========

   This is an implementation of Bio::LocationI to manage simple location
information on a Sequence.

FEEDBACK
========

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bio.perl.org/MailList.html - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Jason Stajich
======================

   Email jason@chg.mc.duke.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

start
-----

     Title   : start
     Usage   : $start = $loc->start();
     Function: get/set the start of this range
     Returns : the start of this range
     Args    : optionaly allows the start to be set
             : using $loc->start($start)

end
---

     Title   : end
     Usage   : $end = $loc->end();
     Function: get/set the end of this range
     Returns : the end of this range
     Args    : optionaly allows the end to be set
             : using $loc->end($start)

strand
------

     Title   : strand
     Usage   : $strand = $loc->strand();
     Function: get/set the strand of this range
     Returns : the strandidness (-1, 0, +1)
     Args    : optionaly allows the strand to be set
             : using $loc->strand($strand)

length
------

     Title   : length
     Usage   : $len = $loc->length();
     Function: get the length in the coordinate space this location spans
     Example :
     Returns : an integer
     Args    : none

min_start
---------

     Title   : min_start
     Usage   : my $minstart = $location->min_start();
     Function: Get minimum starting location of feature startpoint
     Returns : integer or undef if no minimum starting point.
     Args    : none

max_start
---------

     Title   : max_start
     Usage   : my $maxstart = $location->max_start();
     Function: Get maximum starting location of feature startpoint.

     In this implementation this is exactly the same as min_start().

     Returns : integer or undef if no maximum starting point.
     Args    : none

start_pos_type
--------------

     Title   : start_pos_type
     Usage   : my $start_pos_type = $location->start_pos_type();
     Function: Get start position type (ie <,>, ^).

     In this implementation this will always be 'EXACT'.

     Returns : type of position coded as text
               ('BEFORE', 'AFTER', 'EXACT','WITHIN', 'BETWEEN')
     Args    : none

min_end
-------

     Title   : min_end
     Usage   : my $minend = $location->min_end();
     Function: Get minimum ending location of feature endpoint
     Returns : integer or undef if no minimum ending point.
     Args    : none

max_end
-------

     Title   : max_end
     Usage   : my $maxend = $location->max_end();
     Function: Get maximum ending location of feature endpoint

     In this implementation this is exactly the same as min_end().

     Returns : integer or undef if no maximum ending point.
     Args    : none

end_pos_type
------------

     Title   : end_pos_type
     Usage   : my $end_pos_type = $location->end_pos_type();
     Function: Get end position type (ie <,>, ^)

     In this implementation this will always be 'EXACT'.

     Returns : type of position coded as text
               ('BEFORE', 'AFTER', 'EXACT','WITHIN', 'BETWEEN')
     Args    : none

location_type
-------------

     Title   : location_type
     Usage   : my $location_type = $location->location_type();
     Function: Get location type encoded as text
     Returns : string ('EXACT', 'WITHIN', 'BETWEEN')
     Args    : none

to_FTstring
-----------

     Title   : to_FTstring
     Usage   : my $locstr = $location->to_FTstring()
     Function: returns the FeatureTable string of this location
     Returns : string
     Args    : none

Implementation of a Location on a Sequence which has multiple locations (start/end points)
******************************************************************************************

NAME
====

   Bio::Location::Split - Implementation of a Location on a Sequence which
has multiple locations (start/end points)

SYNOPSIS
========

     my $splitlocation = new Bio::Location::Split();
     $splitlocation->add_sub_Location(new Bio::Location::Simple(-start=>1,
     							       -end=>30,
     							       -strand=>1));
     $splitlocation->add_sub_Location(new Bio::Location::Simple(-start=>50,
     							       -end=>61,
     							       -strand=>1));
     my @sublocs = $splitlocation->sub_Location();

     my $count = 1;
     # print the start/end points of the sub locations
     foreach my $location ( sort { $a->start <=> $b->start }
     			   @sublocs ) {
     	printf "sub feature %d [%d..%d]\n",
     	       $count, $location->start,$location->end, "\n";
         $count++;
     }

DESCRIPTION
===========

   This implementation handles locations which span more than one
start/end location, or and/or lie on different sequences.

FEEDBACK
========

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bio.perl.org/MailList.html - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Jason Stajich
======================

   Email jason@chg.mc.duke.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

sub_Location
------------

     Title   : sub_Location
     Usage   : @sublocs = $splitloc->sub_Location();
     Function: Returns the array of sublocations making up this compound (split)
               location. Those sublocations referring to the same sequence as
               the root split location will be sorted by start position (forward
               sort) or end position (reverse sort) and come first (before
               those on other sequences).

     The sort order can be optionally specified or suppressed by the
     value of the first argument. The default is a forward sort.

     Returns : an array of Bio::LocationI implementing objects
     Args    : Optionally 1, 0, or -1 for specifying a forward, no, or reverse
               sort order

add_sub_Location
----------------

     Title   : add_sub_Location
     Usage   : $splitloc->add_sub_Location(@locationIobjs);
     Function: add an additional sublocation
     Returns : number of current sub locations
     Args    : list of Bio::LocationI implementing object(s) to add

splittype
---------

     Title   : splittype
     Usage   : $splittype = $fuzzy->splittype();
     Function: get/set the split splittype
     Returns : the splittype of split feature (join, order)
     Args    : splittype to set

is_single_sequence
------------------

     Title   : is_single_sequence
     Usage   : if($splitloc->is_single_sequence()) {
                   print "Location object $splitloc is split ".
                         "but only across a single sequence\n";
     	    }
     Function: Determine whether this location is split across a single or
               multiple sequences.

     This implementation ignores (sub-)locations that do not define
     seq_id(). The same holds true for the root location.

     Returns : TRUE if all sublocations lie on the same sequence as the root
               location (feature), and FALSE otherwise.
     Args    : none

LocationI methods
=================

start
-----

     Title   : start
     Usage   : $start = $location->start();
     Function: get the starting point of the first (sorted) sublocation
     Returns : integer
     Args    : none

end
---

     Title   : end
     Usage   : $end = $location->end();
     Function: get the ending point of the last (sorted) sublocation
     Returns : integer
     Args    : none

min_start
---------

     Title   : min_start
     Usage   : $min_start = $location->min_start();
     Function: get the minimum starting point
     Returns : the minimum starting point from the contained sublocations
     Args    : none

max_start
---------

     Title   : max_start
     Usage   : my $maxstart = $location->max_start();
     Function: Get maximum starting location of feature startpoint
     Returns : integer or undef if no maximum starting point.
     Args    : none

start_pos_type
--------------

     Title   : start_pos_type
     Usage   : my $start_pos_type = $location->start_pos_type();
     Function: Get start position type (ie <,>, ^)
     Returns : type of position coded as text
               ('BEFORE', 'AFTER', 'EXACT','WITHIN', 'BETWEEN')
     Args    : none

min_end
-------

     Title   : min_end
     Usage   : my $minend = $location->min_end();
     Function: Get minimum ending location of feature endpoint
     Returns : integer or undef if no minimum ending point.
     Args    : none

max_end
-------

     Title   : max_end
     Usage   : my $maxend = $location->max_end();
     Function: Get maximum ending location of feature endpoint
     Returns : integer or undef if no maximum ending point.
     Args    : none

end_pos_type
------------

     Title   : end_pos_type
     Usage   : my $end_pos_type = $location->end_pos_type();
     Function: Get end position type (ie <,>, ^)
     Returns : type of position coded as text
               ('BEFORE', 'AFTER', 'EXACT','WITHIN', 'BETWEEN')
     Args    : none

seq_id
------

     Title   : seq_id
     Usage   : my $seqid = $location->seq_id();
     Function: Get/Set seq_id that location refers to
     Returns : seq_id
     Args    : [optional] seq_id value to set

coordinate_policy
-----------------

     Title   : coordinate_policy
     Usage   : $policy = $location->coordinate_policy();
               $location->coordinate_policy($mypolicy); # set may not be possible
     Function: Get the coordinate computing policy employed by this object.

     See Bio::Location::CoordinatePolicyI for documentation about
     the policy object and its use.

     The interface *does not* require implementing classes to accept
     setting of a different policy. The implementation provided here
     does, however, allow to do so.

     Implementors of this interface are expected to initialize every
     new instance with a CoordinatePolicyI object. The implementation
     provided here will return a default policy object if none has
     been set yet. To change this default policy object call this
     method as a class method with an appropriate argument. Note that
     in this case only subsequently created Location objects will be
     affected.

     Returns : A Bio::Location::CoordinatePolicyI implementing object.
     Args    : On set, a Bio::Location::CoordinatePolicyI implementing object.

to_FTstring
-----------

     Title   : to_FTstring
     Usage   : my $locstr = $location->to_FTstring()
     Function: returns the FeatureTable string of this location
     Returns : string
     Args    : none

Abstract interface of a Location on a Sequence which has multiple locations (start/end points)
**********************************************************************************************

NAME
====

   Bio::SplitLocationI - Abstract interface of a Location on a Sequence
which has multiple locations (start/end points)

SYNOPSIS
========

     # get a SplitLocationI somehow
       print $splitlocation->start, "..", $splitlocation->end, "\n";
       my @sublocs = $splitlocation->sub_Location();

     my $count = 1;
     # print the start/end points of the sub locations
     foreach my $location ( sort { $a->start <=> $b->start }
     			   @sublocs ) {
     	printf "sub feature %d [%d..%d]\n", $location->start,$location->end;
         $count++;
     }

DESCRIPTION
===========

   This interface encapsulates the necessary methods for representing the
location of a sequence feature that has more that just a single start/end
pair.  Some examples of this are the annotated exons in a gene or the
annotated CDS in a sequence file.

FEEDBACK
========

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bio.perl.org/MailList.html - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Jason Stajich
======================

   Email jason@chg.mc.duke.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

sub_Location
------------

     Title   : sub_Location
     Usage   : @locations = $feat->sub_Location();
     Function: Returns an array of LocationI objects
     Returns : An array
     Args    : none

splittype
---------

     Title   : splittype
     Usage   : $splittype = $fuzzy->splittype();
     Function: get/set the split splittype
     Returns : the splittype of split feature (join, order)
     Args    : splittype to set

is_single_sequence
------------------

     Title   : is_single_sequence
     Usage   : if($splitloc->is_single_sequence()) {
                   print "Location object $splitloc is split ".
                         "but only across a single sequence\n";
     	    }
     Function: Determine whether this location is split across a single or
               multiple sequences.
     Returns : TRUE if all sublocations lie on the same sequence as the root
               location (feature), and FALSE otherwise.
     Args    : none

LocationI methods
=================

min_start
---------

     Title   : min_start
     Usage   : my $minstart = $location->min_start();
     Function: Get minimum starting location of feature startpoint
     Returns : integer or undef if no maximum starting point.
     Args    : none

max_start
---------

     Title   : max_start
     Usage   : my $maxstart = $location->max_start();
     Function: Get maximum starting location of feature startpoint
     Returns : integer or undef if no maximum starting point.
     Args    : none

start_pos_type
--------------

     Title   : start_pos_type
     Usage   : my $start_pos_type = $location->start_pos_type();
     Function: Get start position type (ie <,>, ^)
     Returns : type of position coded as text
               ('BEFORE', 'AFTER', 'EXACT','WITHIN', 'BETWEEN')
     Args    : none

min_end
-------

     Title   : min_end
     Usage   : my $minend = $location->min_end();
     Function: Get minimum ending location of feature endpoint
     Returns : integer or undef if no minimum ending point.
     Args    : none

max_end
-------

     Title   : max_end
     Usage   : my $maxend = $location->max_end();
     Function: Get maximum ending location of feature endpoint
     Returns : integer or undef if no maximum ending point.
     Args    : none

end_pos_type
------------

     Title   : end_pos_type
     Usage   : my $end_pos_type = $location->end_pos_type();
     Function: Get end position type (ie <,>, ^)
     Returns : type of position coded as text
               ('BEFORE', 'AFTER', 'EXACT','WITHIN', 'BETWEEN')
     Args    : none

seq_id
------

     Title   : seq_id
     Usage   : my $seqid = $location->seq_id();
     Function: Get/Set seq_id that location refers to
     Returns : seq_id
     Args    : [optional] seq_id value to set

coordinate_policy
-----------------

     Title   : coordinate_policy
     Usage   : $policy = $location->coordinate_policy();
               $location->coordinate_policy($mypolicy); # set may not be possible
     Function: Get the coordinate computing policy employed by this object.

     See Bio::Location::CoordinatePolicyI for documentation about
     the policy object and its use.

     The interface *does not* require implementing classes to accept
     setting of a different policy. The implementation provided here
     does, however, allow to do so.

     Implementors of this interface are expected to initialize every
     new instance with a CoordinatePolicyI object. The implementation
     provided here will return a default policy object if none has
     been set yet. To change this default policy object call this
     method as a class method with an appropriate argument. Note that
     in this case only subsequently created Location objects will be
     affected.

     Returns : A Bio::Location::CoordinatePolicyI implementing object.
     Args    : On set, a Bio::Location::CoordinatePolicyI implementing object.

to_FTstring
-----------

     Title   : to_FTstring
     Usage   : my $locstr = $location->to_FTstring()
     Function: returns the FeatureTable string of this location
     Returns : string
     Args    : none

class implementing  Bio::Location::CoordinatePolicy as the widest possible and reasonable range
***********************************************************************************************

NAME
====

   Bio::Location::WidestCoordPolicy - class implementing
Bio::Location::CoordinatePolicy as the widest possible and reasonable range

SYNOPSIS
========

   See Bio::Location::CoordinatePolicyI

DESCRIPTION
===========

   CoordinatePolicyI implementing objects are used by Bio::LocationI
implementing objects to determine integer-valued coordinates when asked
for it.

   This class will compute the coordinates such that always the widest
possible range is returned, but by using some common sense. This means
that e.g.  locations like "<5..100" (start before position 5) will return
5 as start (returned values have to be positive integers).

FEEDBACK
========

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bio.perl.org/MailList.html - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp, Jason Stajich
===================================

   Email hlapp@gmx.net, jason@chg.mc.duke.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

start
-----

     Title   : start
     Usage   : $start = $policy->start($location);
     Function: Get the integer-valued start coordinate of the given location as
               computed by this computation policy.
     Returns : A positive integer number.
     Args    : A Bio::LocationI implementing object.

end
---

     Title   : end
     Usage   : $end = $policy->end($location);
     Function: Get the integer-valued end coordinate of the given location as
               computed by this computation policy.
     Returns : A positive integer number.
     Args    : A Bio::LocationI implementing object.

Abstract interface of a Location on a Sequence
**********************************************

NAME
====

   Bio::LocationI - Abstract interface of a Location on a Sequence

SYNOPSIS
========

     # get a LocationI somehow
     printf( "start = %d, end = %d, strand = %s, seq_id = %s\n",
     	    $location->start, $location->end, $location->strand,
     	    $location->seq_id);
     print "location str is ", $location->to_FTstring(), "\n";

DESCRIPTION
===========

   This Interface defines the methods for a Bio::LocationI, an object
which encapsulates a location on a biological sequence.  Locations need
not be attached to actual sequences as they are stand alone objects.
LocationI objects are used by Bio::SeqFeatureI objects to manage and
represent locations for a Sequence Feature.

FEEDBACK
========

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bio.perl.org/MailList.html - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Jason Stajich
======================

   Email jason@chg.mc.duke.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

start
-----

     Title   : start
     Usage   : $start = $location->start();
     Function: Get the start coordinate of this location as defined by the
               currently active coordinate computation policy. In simple cases,
               this will return the same number as min_start() and max_start(),
               in more ambiguous cases like fuzzy locations the number may be
               equal to one or neither of both.

     We override this here from RangeI in order to delegate 'get' to
     a Bio::Location::CoordinatePolicy implementing object. Implementing
     classes may also wish to provide 'set' functionality, in which
     case they *must* override this method. The implementation
     provided here will throw an exception if called with arguments.

     Returns : A positive integer value.
     Args    : none

end
---

     Title   : end
     Usage   : $end = $location->end();
     Function: Get the end coordinate of this location as defined by the
               currently active coordinate computation policy. In simple cases,
               this will return the same number as min_end() and max_end(),
               in more ambiguous cases like fuzzy locations the number may be
               equal to one or neither of both.

     We override this here from RangeI in order to delegate 'get' to
     a Bio::Location::CoordinatePolicy implementing object. Implementing
     classes may also wish to provide 'set' functionality, in which
     case they *must* override this method. The implementation
     provided here will throw an exception if called with arguments.

     Returns : A positive integer value.
     Args    : none

min_start
---------

     Title   : min_start
     Usage   : my $minstart = $location->min_start();
     Function: Get minimum starting point of feature.

     Note that an implementation must not call start() in this method.

     Returns : integer or undef if no minimum starting point.
     Args    : none

max_start
---------

     Title   : max_start
     Usage   : my $maxstart = $location->max_start();
     Function: Get maximum starting point of feature.

     Note that an implementation must not call start() in this method
     unless start() is overridden such as not to delegate to the
     coordinate computation policy object.

     Returns : integer or undef if no maximum starting point.
     Args    : none

start_pos_type
--------------

     Title   : start_pos_type
     Usage   : my $start_pos_type = $location->start_pos_type();
     Function: Get start position type encoded as text

     Known valid values are 'BEFORE' (<5..100), 'AFTER' (>5..100),
     'EXACT' (5..100), 'WITHIN' ((5.10)..100), 'BETWEEN', (5^6), with
     their meaning best explained by their GenBank/EMBL location string
     encoding in brackets.

     Returns : string ('BEFORE', 'AFTER', 'EXACT','WITHIN', 'BETWEEN')
     Args    : none

min_end
-------

     Title   : min_end
     Usage   : my $minend = $location->min_end();
     Function: Get minimum ending point of feature.

     Note that an implementation must not call end() in this method
     unless end() is overridden such as not to delegate to the
     coordinate computation policy object.

     Returns : integer or undef if no minimum ending point.
     Args    : none

max_end
-------

     Title   : max_end
     Usage   : my $maxend = $location->max_end();
     Function: Get maximum ending point of feature.

     Note that an implementation must not call end() in this method
     unless end() is overridden such as not to delegate to the
     coordinate computation policy object.

     Returns : integer or undef if no maximum ending point.
     Args    : none

end_pos_type
------------

     Title   : end_pos_type
     Usage   : my $end_pos_type = $location->end_pos_type();
     Function: Get end position encoded as text.

     Known valid values are 'BEFORE' (5..<100), 'AFTER' (5..>100),
     'EXACT' (5..100), 'WITHIN' (5..(90.100)), 'BETWEEN', (5^6), with
     their meaning best explained by their GenBank/EMBL location string
     encoding in brackets.

     Returns : string ('BEFORE', 'AFTER', 'EXACT','WITHIN', 'BETWEEN')
     Args    : none

seq_id
------

     Title   : seq_id
     Usage   : my $seqid = $location->seq_id();
     Function: Get/Set seq_id that location refers to
     Returns : seq_id (a string)
     Args    : [optional] seq_id value to set

coordinate_policy
-----------------

     Title   : coordinate_policy
     Usage   : $policy = $location->coordinate_policy();
               $location->coordinate_policy($mypolicy); # set may not be possible
     Function: Get the coordinate computing policy employed by this object.

     See Bio::Location::CoordinatePolicyI for documentation about
     the policy object and its use.

     The interface *does not* require implementing classes to accept
     setting of a different policy. The implementation provided here
     does, however, allow to do so.

     Implementors of this interface are expected to initialize every
     new instance with a CoordinatePolicyI object. The implementation
     provided here will return a default policy object if none has
     been set yet. To change this default policy object call this
     method as a class method with an appropriate argument. Note that
     in this case only subsequently created Location objects will be
     affected.

     Returns : A Bio::Location::CoordinatePolicyI implementing object.
     Args    : On set, a Bio::Location::CoordinatePolicyI implementing object.

to_FTstring
-----------

     Title   : to_FTstring
     Usage   : my $locstr = $location->to_FTstring()
     Function: returns the FeatureTable string of this location
     Returns : string
     Args    : none

The Bioperl ReadSeq interface
*****************************

NAME
====

   Seq::Parse - The Bioperl ReadSeq interface

SYNOPSIS
========

   Simple perl interface/wrapper to D.G. Gilbert's ReadSeq program.  Used
by Seq.pm when internal parsing/formatting code fails.

   **NOTE** Not currently used by any of the core bioperl modules.  It can
be used as a standalone interface to the readseq package but manual
editing of is required. See the first few lines of the .pm file for
details.

DESCRIPTION
===========

   This package was called upon by Seq.pm when internal attemts to format
or parse a sequence fail. It is currently not used by any bioperl core
module. Basically we decided to deal with sequence formatting in a
different way.

   Parse.pm is a simple interface to D.G. Gilbert's ReadSeq program, it is
not meant to be particularly elegant or efficient. The interface should be
abstract enough to allow future versions to seamlessly access other
sequence conversion programs besides ReadSeq.

   At this time the interface methods have not been fully thought out or
implemented. Suggestions are welcome.

   If ReadSeq is not on the local system, or this package is not properly
configured, Seq.pm will (hopefully) realize this and not attempt to use
this code.

USAGE
=====

   The ReadSeq executable needs to be installed on your system.

   Readseq is freely distributed and is available in shell archive (.shar)
form via FTP from ftp.bio.indiana.edu (129.79.224.25) in the
molbio/readseq directory.  (URL) ftp://ftp.bio.indiana.edu/molbio/readseq/

Standalone
----------

     use Parse;

With Seq.pm
-----------

   If properly configured, Seq.pm will automatically use this module when
internal methods at parsing or formatting fail.

   The correct path to the readseq executable is configured into this
module during the 'make Makefile.PL' phase of installation.

   Manual edits needed in Parse.pm if auto-configuration does not happen:

   - Change the value of *$READSEQ_PATH* so that it defines a path to the
ReadSeq executable on your system.

   - Uncomment the line(s) containing $OK = "Y"

As a standalone module
----------------------

   Parse.pm should be usable is a standalone module. See the usage
instructions.

Sequence Conversion/Formatting
------------------------------

   ReadSeq has trouble with raw sequences so an explicit
convert_from_raw() method has been written.  The following code will
return the sequence "GAATTCGTT" as a GCG formatted string.

     $reply  = &Parse::convert_from_raw(-sequence=>'GAATTCGTT',
                                        -fmt=>'gcg');

   The "fmt" named-parameter field can be set for the following formats:

     IG        (or 'Stanford')
     GenBank   (or 'GB')
     NBRF
     EMBL
     GCG
     Strider
     Fitch
     Fasta
     Zuker
     Phylip3.2 (use 'Phylip3')
     Phylip
     Plain     (or 'Raw')
     PIR       (or 'CODATA')
     MSF
     ASN.1     (use 'ASN1')
     PAUP
     Pretty

   The "options" named-parameter field can be used to pass switches
directly to the ReadSeq executable. This option should only be used by
people familiar with operating ReadSeq on the command-line. Use at your own
risk as this has not been fully tested.

   As an example, the ReadSeq switch -c will cause all of the characters
in the formatted sequence to be returned in lowercase.

     $reply  = &Parse::convert_from_raw(-sequence=>"$seq_string",
                                        -options=>'-c',
                                        -fmt=>'gcg');

Appendix
========

   The following documentation describes the various functions contained
in this package. Some functions are for internal use and are not meant to
be called by the user; they are preceded by an underscore ("_").

_rearrange()
------------

     Title     : _rearrange
      Usage     : n/a (internal function)
      Function  : Rearranges named parameters to requested order.
      Example   : &_rearrange([SEQUENCE,ID,DESC],@p);
      Returns   : @params - an array of parameters in the requested order.
      Argument  : $order : a reference to an array which describes the desired
                           order of the named parameters.
                  @param : an array of parameters, either as a list (in
                           which case the function simply returns the list),
                           or as an associative array (in which case the
                           function sorts the values according to @{$order}
                           and returns that new array.

_write_tmp_file()
-----------------

     Title     : _write_tmp_file
      Usage     : n/a (internal function)
      Function  : Writes a temporary file to disk. Uses
                : the POSIX tmpnam() call to get path &
                : filename. Should be more portable than
                : just writing to /tmp.
                :
      Example   : &_write_tmp_file("$formatted_sequence");
      Returns   : string containing the temp file path
      Argument  : string that is to be written to disk

version()
---------

     Title     : version
      Usage     : &Parse::version;
      Function  : Prints current package version
      Example   : &Parse::version;
      Returns   : none
      Argument  : none
                :

convert_from_raw()
------------------

     Title     : convert_from_raw()
      Usage     : print &Parse::convert_from_raw(-sequence=>$raw_seq,
                :                                -fmt=>'asn1');
                :
                : $reply  = &Parse::convert_from_raw(-sequence=>'GAATTCGTT',
                :                                    -options=>'-c',
                :                                    -fmt=>'gcg');
                :
      Function  : ReadSeq does not function well when called upon
                : to read or convert "raw" or unformatted sequence
                : strings or files. This code will take a given
                : raw sequence and manipulate it into FASTA
                : format before invoking ReadSeq.
                :
                : The following named paramters may be used as
                : arguments:
                :
                :  -sequence=>     Sequence string.
                :  -fmt=>          Format sequence will be converted to.
                :  -options=>      String containing command-line
                :                  switches for ReadSeq. Passed
                :                  directly.
                :
      Example   : see usage
      Returns   : Formatted sequence string
      Argument  : named parameters, see function
                :

convert()
---------

     Title     : convert
                :
      Usage     : print &Parse::convert(-sequence=>$raw_seq,
                :                       -fmt=>'asn1');
                :
                : $reply  = &Parse::convert(-sequence=>'GAATTCGTT',
                :                           -options=>'-c',
                :                           -fmt=>'gcg');
                :
                : $reply  = &Parse::convert(-location=>'/tmp/a.seq',
                :                           -fmt=>'raw');
                :
      Note      : ReadSeq does not function well when called upon
                : to read or convert "raw" or unformatted sequence
                : strings or files. User beware.
                :
      Function  : Will read/parse a given sequence string *OR* a given
                : sequence file.
                :
                : If a sequence string AND a sequence file path are
                : both passed in, the file path will be used with no
                : complaint.
                :
                : The following named paramters may be used as
                : arguments:
                :
                :  -sequence=>     Sequence string.
                :  -location=>     Sequence file path.
                :  -fmt=>          Format sequence will be converted to.
                :  -options=>      String containing command-line
                :                  switches for ReadSeq. Passed
                :                  directly.
                :
      Example   : see usage
      Returns   : Formatted sequence string
      Argument  : named parameters, see function
                :

ACKNOWLEDGEMENTS
================

SEE ALSO
========

     Core bioperl modules

REFERENCES
==========

   Bioperl Project http://bio.perl.org

COPYRIGHT
=========

   Copyright (c) 1997-1998 Chris Dagdigian, Georg Fuellen, Steven E.
Brenner and others. All Rights Reserved.  This module is free software;
you can redistribute it and/or modify it under the same terms as Perl
itself.

Bioperl lightweight Sequence Object
***********************************

NAME
====

   Bio::PrimarySeq - Bioperl lightweight Sequence Object

SYNOPSIS
========

     # The Bio::SeqIO for file reading, Bio::DB::GenBank for
     # database reading
     use Bio::Seq;
     use Bio::SeqIO;
     use Bio::DB::GenBank;

     #make from memory
     $seqobj = Bio::PrimarySeq->new ( -seq => 'ATGGGGTGGGCGGTGGGTGGTTTG',
     			    -id  => 'GeneFragment-12',
     			    -accession_number => 'X78121',
     			    -moltype => 'dna'
     			    );

     # read from file
     $inputstream = Bio::SeqIO->new(-file => "myseq.fa",-format => 'Fasta');
     $seqobj = $inputstream->next_seq();

     # get from database
     $db = Bio::DB::GenBank->new();
     $seqobj = $db->get_Seq_by_acc('X78121');

     # to get out parts of the sequence.

     print "Sequence ", $seqobj->id(), " with accession ", $seqobj->accession, " and desc ", $seqobj->desc, "\n";

     $string  = $seqobj->seq();
     $string2 = $seqobj->subseq(1,40);

DESCRIPTION
===========

   PrimarySeq is a lightweight Sequence object, storing little more than
the sequence, its name, a computer useful unique name. It does not contain
sequence features or other information.  To have a sequence with sequence
features you should use the Seq object which uses this object.

   Sequence objects are defined by the Bio::PrimarySeqI interface, and this
object is a pure Perl implementation of the interface (if that's gibberish
to you, don't worry. The take home message is that this object is the
bioperl default sequence object, but other people can use their own
objects as sequences if they so wish). If you are interested in wrapping
your own objects as compliant Bioperl sequence objects, then you should
read the Bio::PrimarySeqI documentation

   The documenation of this object is a merge of the Bio::PrimarySeq and
Bio::PrimarySeqI documentation.  This allows all the methods which you can
call on sequence objects here.

Reimplementation
================

   The Sequence object was completely rewritten for the 0.6 series. This
was because the old Sequence object was becoming heavily bloated and
difficult to maintain. There are some key changes from the old object to
the new object, but basically, everything should work with the new object
with a minimal number of changes.

   The key change is that the format IO has been removed from this object
and moved to the Bio::SeqIO system, which provides a much better way to
encapsulate the sequence format reading. Please read the SeqIO
documentation, but the take home message is that lines like

     # old style reading from files
     $seq = Bio::Seq->new( -file => "myfile");

   Becomes

     # new style reading from files.
     $inputstream = Bio::SeqIO->new( -file => "myfile", -format => 'Fasta');
     $seqobj = $inputstream->next_seq();

   For writing files, a similar system is used

     # old style writing to files
     print OUTPUT $seq->layout_fasta;

     # new style writing to files
     $outputstream = Bio::SeqIO->new( -fh => \*OUTPUT, -format => 'Fasta');
     $outputstream->write_seq($seqobj);

Deprecated methods
------------------

   A number of methods which were present in the old 0.04/0.05 series have
been deprecated.  Most of these methods work as before, but provide a
warning that someone has called a deprecated method.

getseq - use seq/subseq instead
str - use seq/subseq instead
ary - use seq/subseq with your own split afterwards
type - use moltype, but notice that moltype returns different values (lowercase)
FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bio.perl.org/MailList.html - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email birney@sanger.ac.uk

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
---

     Title   : new
     Usage   : $seq    = Bio::PrimarySeq->new( -seq => 'ATGGGGGTGGTGGTACCCT',
                                               -id  => 'human_id',
     					   -accession_number => 'AL000012',
     					   );

     Function: Returns a new primary seq object from
               basic constructors, being a string for the sequence
               and strings for id and accession_number.

     Note that you can provide an empty sequence string. However, in
     this case you MUST specify the type of sequence you wish to
     initialize by the parameter -moltype. See moltype() for possible
     values.
      Returns : a new Bio::PrimarySeq object

seq
---

     Title   : seq
     Usage   : $string    = $obj->seq()
     Function: Returns the sequence as a string of letters. The
               case of the letters is left up to the implementer.
               Suggested cases are upper case for proteins and lower case for
               DNA sequence (IUPAC standard), but you should not rely on this
     Returns : A scalar

subseq
------

     Title   : subseq
     Usage   : $substring = $obj->subseq(10,40);
     Function: returns the subseq from start to end, where the first base
               is 1 and the number is inclusive, ie 1-2 are the first two
               bases of the sequence
     Returns : a string
     Args    :

length
------

     Title   : length
     Usage   : $len = $seq->length()
     Function:
     Example :
     Returns : integer representing the length of the sequence.
     Args    :

display_id
----------

     Title   : display_id
     Usage   : $id_string = $obj->display_id();
     Function: returns the display id, aka the common name of the Sequence object.

     The semantics of this is that it is the most likely string to be
     used as an identifier of the sequence, and likely to have "human" readability.
     The id is equivalent to the ID field of the GenBank/EMBL databanks and
     the id field of the Swissprot/sptrembl database. In fasta format, the >(\S+)
     is presumed to be the id, though some people overload the id to embed other
     information. Bioperl does not use any embedded information in the ID field,
     and people are encouraged to use other mechanisms (accession field for example,
     or extending the sequence object) to solve this.

     Returns : A string
     Args    : None

accession_number
----------------

     Title   : accession_number
     Usage   : $unique_key = $obj->accession_number;
     Function: Returns the unique biological id for a sequence, commonly
               called the accession_number. For sequences from established
               databases, the implementors should try to use the correct
               accession number. Notice that primary_id() provides the
               unique id for the implemetation, allowing multiple objects
               to have the same accession number in a particular implementation.

     For sequences with no accession number, this method should return
     "unknown".
      Returns : A string
      Args    : A string (optional) for setting

primary_id
----------

     Title   : primary_id
     Usage   : $unique_key = $obj->primary_id;
     Function: Returns the unique id for this object in this
               implementation. This allows implementations to manage
               their own object ids in a way the implementaiton can control
               clients can expect one id to map to one object.

     For sequences with no natural primary id, this method should return
     a stringified memory location.
      Returns : A string
      Args    : A string (optional, for setting)

moltype
-------

     Title   : moltype
     Usage   : if( $obj->moltype eq 'dna' ) { /Do Something/ }
     Function: Returns the type of sequence being one of
               'dna', 'rna' or 'protein'. This is case sensitive.

     This is not called <type> because this would cause
     upgrade problems from the 0.5 and earlier Seq objects.

     Returns : a string either 'dna','rna','protein'. NB - the object must
               make a call of the type - if there is no type specified it
               has to guess.
     Args    : none

desc
----

     Title   : desc
     Usage   : $obj->desc($newval)
     Function: Get/set description of the sequence.
     Example :
     Returns : value of desc
     Args    : newvalue (optional)

can_call_new
------------

     Title   : can_call_new
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

id
--

     Title   : id
     Usage   : $id = $seq->id()
     Function: This is mapped on display_id
     Example :
     Returns :
     Args    :

Methods Inherieted from Bio::PrimarySeqI
========================================

   These methods are available on Bio::PrimarySeq, although they are
actually implemented on Bio::PrimarySeqI

revcom
------

     Title   : revcom
     Usage   : $rev = $seq->revcom()
     Function: Produces a new Bio::SeqI implementing object which
               is the reversed complement of the sequence. For protein
               sequences this throws an exception of
               "Sequence is a protein. Cannot revcom"

     The id is the same id as the orginal sequence, and the
     accession number is also indentical. If someone wants to
     track that this sequence has be reversed, it needs to
     define its own extensions

     To do an inplace edit of an object you can go:

     $seqobj = $seqobj->revcom();

     This of course, causes Perl to handle the garbage
     collection of the old object, but it is roughly speaking as
     efficient as an inplace edit.

     Returns : A new (fresh) Bio::SeqI object
     Args    : none

trunc
-----

     Title   : trunc
     Usage   : $subseq = $myseq->trunc(10,100);
     Function: Provides a truncation of a sequence,

     Example :
     Returns : a fresh Bio::SeqI implementing object
     Args    :

Internal methods
================

   These are internal methods to PrimarySeq

_guess_type
-----------

     Title   : _guess_type
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

Interface definition for a Bio::PrimarySeq
******************************************

NAME
====

   Bio::PrimarySeqI - Interface definition for a Bio::PrimarySeq

SYNOPSIS
========

     # get a Bio::PrimarySeqI compliant object somehow

     # to test this is a seq object

     $obj->isa("Bio::PrimarySeqI") || $obj->throw("$obj does not implement the Bio::PrimarySeqI interface");

     # accessors

     $string    = $obj->seq();
     $substring = $obj->subseq(12,50);
     $display   = $obj->display_id(); # for human display
     $id        = $obj->primary_id(); # unique id for this object, implementation defined
     $unique_key= $obj->accession_number();
                        # unique biological id

     # object manipulation

     eval {
     	$rev    = $obj->revcom();
     };
     if( $@ ) {
     	$obj->throw("Could not reverse complement. Probably not DNA. Actual exception\n$@\n");
     }

     $trunc = $obj->trunc(12,50);

     # $rev and $trunc are Bio::PrimarySeqI compliant objects

DESCRIPTION
===========

   This object defines an abstract interface to basic sequence
information. PrimarySeq is an object just for the sequence and its
name(s), nothing more. Seq is the larger object complete with features.
There is a pure perl implementation of this in Bio::PrimarySeq. If you
just want to use Bio::PrimarySeq objects, then please read that module
first. This module defines the interface, and is of more interest to
people who want to wrap their own Perl Objects/RDBs/FileSystems etc in way
that they "are" bioperl sequence objects, even though it is not using Perl
to store the sequence etc.

   This interface defines what bioperl consideres necessary to "be" a
sequence, without providing an implementation of this. (An implementation
is provided in Bio::PrimarySeq). If you want to provide a Bio::PrimarySeq
'compliant' object which in fact wraps another object/database/out-of-perl
experience, then this is the correct thing to wrap, generally by providing
a wrapper class which would inheriet from your object and this
Bio::PrimarySeqI interface. The wrapper class then would have methods
lists in the "Implementation Specific Functions" which would provide these
methods for your object.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email birney@sanger.ac.uk

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

Implementation Specific Functions
=================================

   These functions are the ones that a specific implementation must define.

seq
---

     Title   : seq
     Usage   : $string    = $obj->seq()
     Function: Returns the sequence as a string of letters. The
               case of the letters is left up to the implementer.
               Suggested cases are upper case for proteins and lower case for
               DNA sequence (IUPAC standard),
               but implementations are suggested to keep an open mind about
               case (some users... want mixed case!)
     Returns : A scalar
     Status  : Virtual

subseq
------

     Title   : subseq
     Usage   : $substring = $obj->subseq(10,40);
     Function: returns the subseq from start to end, where the first base
               is 1 and the number is inclusive, ie 1-2 are the first two
               bases of the sequence

     Start cannot be larger than end but can be equal

     Returns : a string
     Args    :
     Status  : Virtual

display_id
----------

     Title   : display_id
     Usage   : $id_string = $obj->display_id();
     Function: returns the display id, aka the common name of the Sequence object.

     The semantics of this is that it is the most likely string
     to be used as an identifier of the sequence, and likely to
     have "human" readability.  The id is equivalent to the ID
     field of the GenBank/EMBL databanks and the id field of the
     Swissprot/sptrembl database. In fasta format, the >(\S+) is
     presumed to be the id, though some people overload the id
     to embed other information. Bioperl does not use any
     embedded information in the ID field, and people are
     encouraged to use other mechanisms (accession field for
     example, or extending the sequence object) to solve this.

     Notice that $seq->id() maps to this function, mainly for
     legacy/convience issues
      Returns : A string
      Args    : None
      Status  : Virtual

accession_number
----------------

     Title   : accession_number
     Usage   : $unique_biological_key = $obj->accession_number;
     Function: Returns the unique biological id for a sequence, commonly
               called the accession_number. For sequences from established
               databases, the implementors should try to use the correct
               accession number. Notice that primary_id() provides the
               unique id for the implemetation, allowing multiple objects
               to have the same accession number in a particular implementation.

     For sequences with no accession number, this method should return
     "unknown".
      Returns : A string
      Args    : None
      Status  : Virtual

primary_id
----------

     Title   : primary_id
     Usage   : $unique_implementation_key = $obj->primary_id;
     Function: Returns the unique id for this object in this
               implementation. This allows implementations to manage
               their own object ids in a way the implementaiton can control
               clients can expect one id to map to one object.

     For sequences with no accession number, this method should return
     a stringified memory location.
      Returns : A string
      Args    : None
      Status  : Virtual

can_call_new
------------

     Title   : can_call_new
     Usage   : if( $obj->can_call_new ) {
                 $newobj = $obj->new( %param );
     	 }
     Function: can_call_new returns 1 or 0 depending
               on whether an implementation allows new
               constructor to be called. If a new constructor
               is allowed, then it should take the followed hashed
               constructor list.

     $myobject->new( -seq => $sequence_as_string,
     			   -display_id  => $id
     			   -accession_number => $accession
     			   -moltype => 'dna',
     			   );
      Example :
      Returns : 1 or 0
      Args    :

moltype
-------

     Title   : moltype
     Usage   : if( $obj->moltype eq 'dna' ) { /Do Something/ }
     Function: Returns the type of sequence being one of
               'dna', 'rna' or 'protein'. This is case sensitive.

     This is not called <type> because this would cause
     upgrade problems from the 0.5 and earlier Seq objects.

     Returns : a string either 'dna','rna','protein'. NB - the object must
               make a call of the type - if there is no type specified it
               has to guess.
     Args    : none
     Status  : Virtual

Optional Implementation Functions
=================================

   The following functions rely on the above functions. A implementing
class does not need to provide these functions, as they will be provided
by this class, but is free to override these functions.

   All of revcom(), trunc(), and translate() create new sequence objects.
They will call new() on the class of the sequence object instance passed
as argument, unless can_call_new() returns FALSE. In the latter case a
Bio::PrimarySeq object will be created. Implementors which really want to
control how objects are created (eg, for object persistence over a
database, or objects in a CORBA framework), they are encouraged to
override these methods

revcom
------

     Title   : revcom
     Usage   : $rev = $seq->revcom()
     Function: Produces a new Bio::PrimarySeqI implementing object which
               is the reversed complement of the sequence. For protein
               sequences this throws an exception of "Sequence is a protein. Cannot revcom"

     The id is the same id as the orginal sequence, and the accession number
     is also indentical. If someone wants to track that this sequence has be
     reversed, it needs to define its own extensions

     To do an inplace edit of an object you can go:

     $seq = $seq->revcom();

     This of course, causes Perl to handle the garbage collection of the old
     object, but it is roughly speaking as efficient as an inplace edit.

     Returns : A new (fresh) Bio::PrimarySeqI object
     Args    : none

trunc
-----

     Title   : trunc
     Usage   : $subseq = $myseq->trunc(10,100);
     Function: Provides a truncation of a sequence,

     Example :
     Returns : a fresh Bio::PrimarySeqI implementing object
     Args    : Two integers denoting first and last base of the sub-sequence.

translate
---------

     Title   : translate
     Usage   : $protein_seq_obj = $dna_seq_obj->translate
               #if full CDS expected:
               $protein_seq_obj = $cds_seq_obj->translate(undef,undef,undef,undef,1);
     Function:

     Provides the translation of the DNA sequence using full
     IUPAC ambiguities in DNA/RNA and amino acid codes.

     The full CDS translation is identical to EMBL/TREMBL
     database translation. Note that the trailing terminator
     character is removed before returning the translation
     object.

     Note: if you set $dna_seq_obj->verbose(1) you will get a
     warning if the first codon is not a valid initiator.

     Returns : A Bio::PrimarySeqI implementing object
     Args    : character for terminator (optional) defaults to '*'
               character for unknown amino acid (optional) defaults to 'X'
               frame (optional) valid values 0, 1, 2, defaults to 0
               codon table id (optional) defaults to 1
               complete coding sequence expected, defaults to 0 (false)
               boolean, throw exception if not complete CDS (true) or defaults to warning (false)

id
--

     Title   : id
     Usage   : $id = $seq->id()
     Function: ID of the sequence. This should normally be (and actually is in
               the implementation provided here) just a synonym for display_id().
     Example :
     Returns : A string.
     Args    :

length
------

     Title   : length
     Usage   : $len = $seq->length()
     Function:
     Example :
     Returns : integer representing the length of the sequence.
     Args    :

desc
----

     Title   : desc
     Usage   : $seq->desc($newval);
               $description = $seq->desc();
     Function: Get/set description text for a seq object
     Example :
     Returns : value of desc
     Args    : newvalue (optional)

Private functions
=================

   These are some private functions for the PrimarySeqI interface. You do
not need to implement these functions

_attempt_to_load_Seq
--------------------

     Title   : _attempt_to_load_Seq
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

Pure perl RangeI implementation
*******************************

NAME
====

   Bio::Range - Pure perl RangeI implementation

DESCRIPTION
===========

   This provides a pure perl implementation of the BioPerl range interface.

   Ranges are modeled as having (start, end, length, strand). They use
Bio-coordinates - all points >= start and <= end are within the range. End
is always greater-than or equal-to start, and length is greather than or
equal to 1. The behaviour of a range is undefined if ranges with negative
numbers or zero are used.

   So, in summary:

     length = end - start + 1
     end >= start
     strand = (-1 | 0 | +1)

SYNOPSIS
========

     $range = new Bio::Range(-start=>10, -end=>30, -strand=>+1);
     $r2 = new Bio::Range(-start=>15, -end=>200, -strand=>+1);

     print join(', ', $range->union($r2), "\n";
     print join(', ', $range->intersection($r2), "\n";
     print $range->overlaps($r2), "\n";
     print $range->contains($r2), "\n";

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Heikki Lehvaslaiho
===========================

   Email heikki@ebi.ac.uk

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal metho ds are usually preceded with a _

Constructors
============

new
---

     Title   : new
     Usage   : $range = Bio::Range->new(-start => 100, -end=> 200, -strand = +1);
     Function: generates a new Bio::Range
     Returns : a new range
     Args    : two of (-start, -end, '-length') - the third is calculated
             : -strand (defaults to 0)

Member variable access
======================

   These methods let you get at and set the member variables

start
-----

     Title    : start
     Function : return or set the start co-ordinate
     Example  : $s = $range->start(); $range->start(7);
     Returns  : the value of the start co-ordinate
     Args     : optionally, the new start co-ordinate
     Overrides: Bio::RangeI::start

end
---

     Title    : end
     Function : return or set the end co-ordinate
     Example  : $e = $range->end(); $range->end(2000);
     Returns  : the value of the end co-ordinate
     Args     : optionally, the new end co-ordinate
     Overrides: Bio::RangeI::end

strand
------

     Title    : strand
     Function : return or set the strandidness
     Example  : $st = $range->strand(); $range->strand(-1);
     Returns  : the value of the strandedness (-1, 0 or 1)
     Args     : optionaly, the new strand - (-1, 0, 1) or (-, ., +).
     Overrides: Bio::RangeI::Strand

length
------

     Title    : length
     Function : returns the length of this range
     Example  : $length = $range->length();
     Returns  : the length of this range, equal to end - start + 1
     Args     : if you attempt to set the length, and exeption will be thrown
     Overrides: Bio::RangeI::Length

toString
--------

     Title   : toString
     Function: stringifies this range
     Example : print $range->toString(), "\n";
     Returns : a string representation of this range

Boolean Methods
===============

   These methods return true or false.

     $range->overlaps($otherRange) && print "Ranges overlap\n";

overlaps
--------

     Title    : overlaps
     Usage    : if($r1->overlaps($r2)) { do stuff }
     Function : tests if $r2 overlaps $r1
     Args     : a range to test for overlap with
     Returns  : true if the ranges overlap, false otherwise
     Inherited: Bio::RangeI

contains
--------

     Title    : contains
     Usage    : if($r1->contains($r2) { do stuff }
     Function : tests wether $r1 totaly contains $r2
     Args     : a range to test for being contained
     Returns  : true if the argument is totaly contained within this range
     Inherited: Bio::RangeI

equals
------

     Title    : equals
     Usage    : if($r1->equals($r2))
     Function : test whether $r1 has the same start, end, length as $r2
     Args     : a range to test for equality
     Returns  : true if they are describing the same range
     Inherited: Bio::RangeI

Geometrical methods
===================

   These methods do things to the geometry of ranges, and return triplets
(start, end, strand) from which new ranges could be built.

intersection
------------

     Title    : intersection
     Usage    : ($start, $stop, $strand) = $r1->intersection($r2)
     Function : gives the range that is contained by both ranges
     Args     : a range to compare this one to
     Returns  : nothing if they do not overlap, or the range that they do overlap
     Inherited: Bio::RangeI::intersection

union
-----

     Title    : union
     Usage    : ($start, $stop, $strand) = $r1->union($r2);
              : ($start, $stop, $strand) = Bio::Range->union(@ranges);
     Function : finds the minimal range that contains all of the ranges
     Args     : a range or list of ranges to find the union of
     Returns  : the range containing all of the ranges
     Inherited: Bio::RangeI::union

Range interface
***************

NAME
====

   Bio::RangeI - Range interface

SYNOPSIS
========

   None.

DESCRIPTION
===========

   This provides a standard BioPerl range interface that should be
implemented by any object that wants to be treated as a range. This serves
purely as an abstract base class for implementers and can not be
instantiated.

   Ranges are modeled as having (start, end, length, strand). They use
Bio-coordinates - all points >= start and <= end are within the range. End
is always greater-than or equal-to start, and length is greather than or
equal to 1. The behaviour of a range is undefined if ranges with negative
numbers or zero are used.

   So, in summary:

     length = end - start + 1
     end >= start
     strand = (-1 | 0 | +1)

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Heikki Lehvaslaiho
===========================

   Email:  heikki@ebi.ac.uk

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

Abstract methods
================

   These methods must be implemented in all subclasses.

new
---

     Title   : new
     Function: confesses if you try to instantiate a RangeI
             : RangeI is an interface, so RangeI->new should never be called
     	  : To make a range, instantiate one of the implementing classes. e.g.
     	  : $range = Bio::Range->new(-start=>20, -end=>2000, -strand=>1)

start
-----

     Title   : start
     Usage   : $start = $range->start();
     Function: get/set the start of this range
     Returns : the start of this range
     Args    : optionaly allows the start to be set
             : using $range->start($start)

end
---

     Title   : end
     Usage   : $end = $range->end();
     Function: get/set the end of this range
     Returns : the end of this range
     Args    : optionaly allows the end to be set
             : using $range->end($end)

length
------

     Title   : length
     Usage   : $length = $range->length();
     Function: get/set the length of this range
     Returns : the length of this range
     Args    : optionaly allows the length to be set
             : using $range->length($length)

strand
------

     Title   : strand
     Usage   : $strand = $range->strand();
     Function: get/set the strand of this range
     Returns : the strandidness (-1, 0, +1)
     Args    : optionaly allows the strand to be set
             : using $range->strand($strand)

Boolean Methods
===============

   These methods return true or false. They throw an error if start and
end are not defined.

     $range->overlaps($otherRange) && print "Ranges overlap\n";

overlaps
--------

     Title   : overlaps
     Usage   : if($r1->overlaps($r2)) { do stuff }
     Function: tests if $r2 overlaps $r1
     Args    : arg #1 = a range to compare this one to (mandatory)
               arg #2 = strand option ('strong', 'weak', 'ignore') (optional)
     Returns : true if the ranges overlap, false otherwise

contains
--------

     Title   : contains
     Usage   : if($r1->contains($r2) { do stuff }
     Function: tests whether $r1 totally contains $r2
     Args    : arg #1 = a range to compare this one to (mandatory)
     	             alternatively, integer scalar to test
               arg #2 = strand option ('strong', 'weak', 'ignore') (optional)
     Returns : true if the argument is totaly contained within this range

equals
------

     Title   : equals
     Usage   : if($r1->equals($r2))
     Function: test whether $r1 has the same start, end, length as $r2
     Args    : a range to test for equality
     Returns : true if they are describing the same range

Geometrical methods
===================

   These methods do things to the geometry of ranges, and return
Bio::RangeI compliant objects or triplets (start, stop, strand) from which
new ranges could be built.

intersection
------------

     Title   : intersection
     Usage   : ($start, $stop, $strand) = $r1->intersection($r2)
     Function: gives the range that is contained by both ranges
     Args    : arg #1 = a range to compare this one to (mandatory)
               arg #2 = strand option ('strong', 'weak', 'ignore') (optional)
     Returns : undef if they do not overlap,
               or the range that they do overlap (in an objectlike the calling one)

union
-----

     Title   : union
     Usage   : ($start, $stop, $strand) = $r1->union($r2);
             : ($start, $stop, $strand) = Bio::RangeI->union(@ranges);
     Function: finds the minimal range that contains all of the ranges
     Args    : a range or list of ranges to find the union of
     Returns : the range object containing all of the ranges

overlap_extent
--------------

     Title   : overlap_extent
     Usage   : ($a_unique,$common,$b_unique) = $a->overlap_extent($b)
     Function: Provides actual amount of overlap between two different
               ranges.
     Example :
     Returns : array of values for
               - the amount unique to a
               - the amount common to both
               - the amount unique to b
     Args    :

Exception class for Perl 5 objects
**********************************

NAME
====

   Bio::Root::Err.pm -  Exception class for Perl 5 objects

SYNOPSIS
========

Object Creation
---------------

   *Bio::Root::Object.pm* is a wrapper for Bio::Root::Err.pm objects so
clients do not have to create these objects directly. Please see
*Bio::Root::Object::throw()* as well as `_initialize' in this node() for a
more complete treatment of how to create Bio::Root::Err.pm objects.

     use Bio::Root::Err;

     $err = Bio::Root::Err->new(-MSG     =>"Bad data: $data",
     			     -STACK   =>[\caller(0), \caller(1), ...],
     			     );

   To use the `throw' in this node() method directly:

     use Bio::Root::Err (:std);

     throw( $object_ref, 'Error message', 'additional note', 'technical note');

   The `$object_ref' argument should be a reference to a
Bio::Root::Object.pm.

   See also `USAGE' in this node.

INSTALLATION
============

   This module is included with the central Bioperl distribution:

     http://bio.perl.org/Core/Latest
     ftp://bio.perl.org/pub/DIST

   Follow the installation instructions included in the README file.

DESCRIPTION
===========

   A Bio::Root::Err.pm object encapsulates data and methods that facilitate
working with errors and exceptional conditions that arise in Perl objects.
There are no biological semantics in this module, as one may suspect from
its location in the Bio:: hierarchy. The location of this module serves to
separate it from the namespaces of other Perl Error modules. It also makes
it convenient for use by Bio:: objects.

   The motivation for having an error object is to allow Perl 5 objects to
deal with errors or exceptional conditions that can arise during their
construction or manipulation. For example:

     (1) A complex object can break in many ways.
     (2) Tracking errors within a set of nested objects can be difficult.
     (3) The way an error is reported should be context-sensitive:
         a web-user needs different information than does the
         software engineer.

   Bio::Root::Err.pm, along with *Bio::Root::Object.pm*, attempt to make
such problems tractable. Please see the *Bio::Root::Object.pm*
documentation for more about my error handling philosophy.

   A *Bio::Root::Err.pm* object is an example of a Vector-Object: This
module inherits both from *Bio::Root::Object.pm* and
*Bio::Root::Vector.pm*. This permits a single Err object to exist within a
linked list of Err objects OR alone.  See the *Bio::Root::Vector.pm*
documentation for more about Vector-Objects.

   *The API for this module is not complete since the module is under
development.*

Other Exception Strategies
--------------------------

   Exception handling with Perl 5 objects is currently not as evolved as
one would like. The error handling used by *Bio::Root::Object.pm* and
Bio::Root::Err.pm relies on Perl's built-in error/exception handling with
eval/die, which is not very object-aware. What I've attempted to do with
these modules is to make eval/die more object-savvy, as well as make Perl 5
objects more eval/die-savvy (but the current strategy is basically a hack).

   It would be great if Perl could throw an object reference with die().
This would permit more intelligent and easy to write exception handlers.
For now the Err.pm object is reconstructed from the output of `string' in
this node().

   There are some other third-party Exception classes such as Torsten
Ekedahl's *Experimental::Exception.pm* or Ken Steven's Throwable.pm or
Graham Barr's Error.pm (see `Other Exception Modules' in this node). These
modules attempt to introduce a traditional "try-catch-throw" exception
handling mechanism into Perl. Future version of my modules (and perhaps
erl itself) may utilize one of these.

USAGE
=====

   A demo script that illustrates working with Bio::Root::Err objects is
available at:

     http://bio.perl.org/Core/Examples/Root_object/error.pl

DEPENDENCIES
============

   Bio::Root::Err.pm inherits from *Bio::Root::Object.pm* and
*Bio::Root::Vector.pm*.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules.  Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR
======

   Steve A. Chervitz, sac@genome.stanford.edu

   See the `FEEDBACK' in this node section for where to send bug reports
and comments.

VERSION
=======

   Bio::Root::Err.pm, 0.041

SEE ALSO
========

     Bio::Root::Object.pm    - Core object
     Bio::Root::Vector.pm    - Vector object
     Bio::Root::Global.pm    - Manages global variables/constants

     http://bio.perl.org/Projects/modules.html  - Online module documentation
     http://bio.perl.org/                       - Bioperl Project Homepage

Other Exception Modules
-----------------------

     Experimental::Exception.pm   - ftp://ftp.matematik.su.se/pub/teke/
     Error.pm                     - http://www.cpan.org/authors/id/GBARR/
     Throwable.pm                 - mailto:kstevens@globeandmail.ca

     http://genome-www.stanford.edu/perlOOP/exceptions.html

ACKNOWLEDGEMENTS
================

   This module was developed under the auspices of the Saccharomyces Genome
Database:     http://genome-www.stanford.edu/Saccharomyces

   Other Bioperl developers contributed ideas including Ewan Birney, Ian
Korf, Chris Dagdigian, Georg Fuellen, and Steven Brenner.

COPYRIGHT
=========

   Copyright (c) 1996-8 Steve A. Chervitz. All Rights Reserved.  This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

TODO
====

   * Improve documentation.

   * Experiment with other Exception modules.

APPENDIX
========

   Methods beginning with a leading underscore are considered private and
are intended for internal use by this module. They are not considered part
of the public interface and are described here for documentation purposes
only.

_initialize
-----------

     Usage     : n/a; automatically called by Bio::Root::Object::new()
     Purpose   : Initializes key Bio::Root::Err.pm data.
     Returns   : String (the -MAKE constructor option.)
     Argument  : Named parameters passed from new()
               : (PARAMETER TAGS CAN BE UPPER OR LOWER CASE).
               :   -MSG     => basic description of the exception.
               :   -NOTE    => additional note to indicate cause of exception
               :               or provide information about how to fix/report it
               :   -TECH    => addition note with technical information
               :               of interest to developer.
               :   -STACK   => array reference containing caller() data
               :   -TYPE    => string, one of @Bio::Root::Err::ERR_TYPES
               :               (default = exception).
               :   -CONTEXT => array reference
               :   -OBJ     => Err object to be cloned.

   See Also   : *Bio::Root::Object::_set_err()*

_set_clone
----------

     Usage     : n/a; internal method used by _initialize()
     Purpose   : Copy all Bio::Root::Err.pm data members into a new object reference.
     Argument  : object ref for object to be cloned.
     Comments  : Does not cloning the vector since this method is
               : typically used to extract a single Err object from its vector.

_build_from_string
------------------

     Usage     : n/a; called by _initialize()
     Purpose   : Re-create an Err.pm object from a string containing Err data.
     Returns   : boolean, (was the Err.pm object rebuilt?)
     Argument  : message, note, tech passed from _initialize()
               : The message is examined to see if it contains a stringified error.

   See Also   : `_initialize' in this node(), `string' in this node(),
`_has_err' in this node()

_has_err
--------

     Usage     : n/a; internal method called by _build_from_string()
     Purpose   : Deterimine if an Err has already been set to prevent duplicate Errs.
     Returns   : boolean

   See Also   : `_build_from_string' in this node()

_set_type
---------

     Usage     : n/a; internal method
     Purpose   : Sets the type of Err (warning, exception, fatal)
               : Called by _initialize()
     Argument  : string

_set_list_data
--------------

     Usage     : n/a; internal method used by set().
               : $err->_set_list_data( $member, $data);
     Purpose   : For data members which are anonymous arrays: note, tech, stack,
               : adds the given data to the list.
     Arguments : $member = any of qw(note tech stack)
               : $data   = string
     Comments  : Splits $data on tab. Each item
               : of the split is a new entry.
               : To clobber the current data (unusual situation), you must first
               : call set() with no data then call again with desired data.

_set_context
------------

     Usage     : n/a; internal method used by set().
     Purpose   : Sets the object containment context for the exception.
               : (this is the hierarchy of objects in which the
               :  exception occurred.)

set
---

     Usage     : $err->set( $member, $data );
     Purpose   : General accessor for setting any Err.pm data member.
     Example   : $err->set('note', 'this is an additional note.');
     Returns   : n/a
     Argument  : $member = string, any of qw(msg type note tech stack)
               : $data   = string
     Throws    : n/a
     Comments  : Note, tech, and stack items are appended to any existing
               : notes, tech notes, and stack.
               : There should be no need to mess with the stack.

msg
---

     Usage     : $message = $err->msg;
     Purpose   : Get the main message associated with the exception.
     Returns   : String
     Argument  : optional string to be used as a delimiter.

   See Also   : `get' in this node(), `string' in this node()

type
----

     Usage     : $type = $err->type;
     Purpose   : Get the type of Err (warning, exception, fatal)
     Returns   : String
     Argument  : optional string to be used as a delimiter.

   See Also   : `get' in this node(), `string' in this node()

note
----

     Usage     : $note = $err->note;
               : $note = $err->note('<P>');
     Purpose   : Get any general note associated with the exception.
     Returns   : String
     Argument  : optional string to be used as a delimiter.

   See Also   : `get' in this node(), `string' in this node()

tech
----

     Usage     : $tech = $err->tech;
               : $tech = $err->tech('<P>');
     Purpose   : Get any technical note associate with the exception.
     Returns   : String
     Argument  : optional string to be used as a delimiter.

   See Also   : `get' in this node(), `string' in this node()

stack
-----

     Usage     : $stack = $err->stack;
               : $stack = $err->stack('<P>');
     Purpose   : Get the call stack for the exception.
     Returns   : String
     Argument  : optional string to be used as a delimiter.

   See Also   : `get' in this node(), `string' in this node()

context
-------

     Usage     : $context = $err->context;
               : $context = $err->context('<P>');
     Purpose   : Get the containment context of the object which generated the exception.
     Returns   : String
     Argument  : optional string to be used as a delimiter.

   See Also   : `get' in this node(), `string' in this node()

get
---

     Usage     : $err->get($member, $delimiter);
     Purpose   : Get specific data from the Err.pm object.
     Returns   : String in scalar context.
               : Array in list context.
     Argument  : $member = any of qw(msg type note tech stack context) or combination.
               : $delimiter = optional string to be used as a delimiter
               : between member data.

   See Also   : `string' in this node(), `msg' in this node(), `note' in
this node(), `tech' in this node(), `type' in this node(), `context' in
this node(), `stack' in this node()

_get_list_data
--------------

     Usage     : n/a; internal method used by get()
     Purpose   : Gets data for members which are list refs (note, tech, stack, context)
     Returns   : Array
     Argument  : ($member, $delimiter)

   See Also   : `get' in this node()

get_all
-------

     Usage     : (same as get())
     Purpose   : Get specific data from all errors in an Err.pm object.
     Returns   : Array in list context.
               : String in scalar context.
     Argument  : (same as get())

   See Also   : `get' in this node()

_add_note
---------

     Usage     : n/a; internal method called by _add_list_data()
     Purpose   : adds a new note.

   See Also   : `_add_list_data' in this node()

_add_list_data
--------------

     Usage     : n/a; called by _set_list_data()
     Purpose   : adds a new note or tech note.

   See Also   : `_set_list_data' in this node()

print
-----

     Usage     : $err->print;
     Purpose   : Prints Err data to STDOUT or a FileHandle.
     Returns   : Call to print
     Argument  : Named parameters for string()
     Comments  : Uses string() to get data.

   See Also   : `string' in this node()

string
------

     Usage     : $err->string( %named_parameters);
     Purpose   : Stringify the data contained in the Err.pm object.
     Example   : print STDERR $err->string;
     Returns   : String
     Argument  : Named parameters (optional) passed to
               : Bio::Root::IOManager::set_display().

   See Also   : `print' in this node(), `_build_from_string' in this
node(), *Bio::Root::IOManager::set_display()*

is_fatal
--------

     Usage     : $err->is_fatal;
     Purpose   : Determine if the error is of type 'FATAL'
     Returns   : Boolean
     Status    : Experimental, Deprecated

throw
-----

     Usage     : throw($object, [message], [note], [technical note]);
               : This method is exported.
     Purpose   : Class method version of Bio::Root::Object::throw().
     Returns   : die()s with the contents of the Err object in a string.
               : If the global strictness is less than -1, die is not called and
               : the error is printed to STDERR.
     Argument  : [0] = object throwing the error.
               : [1] = optional message about the error.
               : [2] = optional note about the error.
               : [3] = optional technical note about the error.
     Comments  : The glogal verbosity level is not used. For verbosity-sensitive
               : behavior, use Bio::Root::Object::throw().
     Status    : Experimental
               : This method is an alternative to Bio::Root::Object::throw()
               : and is not as well developed or documented as that method.

   See Also   : `warning' in this node(), *Bio::Root::Object::throw()*
*Bio::Root::Global::strictness*()

warning
-------

     Usage     : warning($object, [message], [note], [technical note]);
               : This method is exported.
     Purpose   : Class method version of Bio::Root::Object::warn().
     Returns   : Prints the contents of the error to STDERR and returns false (0).
               : If the global strictness() is > 1, warn() calls are converted
               : into throw() calls.
     Argument  : [0] = object producing the warning.
               : [1] = optional message about the error.
               : [2] = optional note about the error.
               : [3] = optional technical note about the error.
               :
     Comments  : The glogal verbosity level is not used. For verbosity-sensitive
               : behavior, use Bio::Root::Object::warn().
     Status    : Experimental
               : This method is an alternative to Bio::Root::Object::warn()
               : and is not as well developed or documented as that method.

   See Also   : `throw' in this node, *Bio::Root::Object::warn()*,
*Bio::Root::Global::strictness()*

format_stack_entry
------------------

     Usage     : &format_stack_entry(<class>,<file>,<line>,<class_method>,<has_args>,<wantarray>)
               : This function is exported.
     Purpose   : Creates a single stack entry given a caller() list.
     Argument  : List of scalars (output of the caller() method).
     Returns   : String = class_method($line)
               : e.g., Bio::Root::Object::name(1234)

FOR DEVELOPERS ONLY
===================

Data Members
------------

   Information about the various data members of this module is provided
for those wishing to modify or understand the code. Two things to bear in
mind:

  1. Do NOT rely on these in any code outside of this module.  All data
     members are prefixed with an underscore to signify that they are
     private.  Always use accessor methods. If the accessor doesn't exist
     or is inadequate, create or modify an accessor (and let me know,
     too!).

  2. This documentation may be incomplete and out of date.  It is easy for
     this documentation to become obsolete as this module is still
     evolving.  Always double check this info and search for members not
     described here.

        An instance of Bio::Root::Err.pm is a blessed reference to a hash
containing all or some of the following fields:

     FIELD     VALUE
     ------------------------------------------------------------------------
     _type     fatal | warning | exception (one of @Bio::Root::Err::ERR_TYPES).

     _msg      Terse description: Main cause of error.

     _note     List reference. Verbose description: probable cause & troubleshooting for user.

     _tech     List reference. Technical notes of interest to programmer.

     _stack    List reference. Stack trace: list of "class::method(line number)" strings.

Global variables and utility functions
**************************************

NAME
====

   Bio::Root::Global - Global variables and utility functions

SYNOPSIS
========

     # no real synopsis - see Bio::Root::Object

DESCRIPTION
===========

   The Bio::Root::Global file contains all the global flags about erro
warning etc, and also utility functions, eg to map numbers to roman
numerals.

   These functions are generally called by Bio::Root::Object or somewhere
similar, and not directly

INSTALLATION
============

   This module is included with the central Bioperl distribution:

     http://bio.perl.org/Core/Latest
     ftp://bio.perl.org/pub/DIST

   Follow the installation instructions included in the README file.

module providing several methods often needed when dealing with file IO
***********************************************************************

NAME
====

   Bio::Root::IO - module providing several methods often needed when
dealing with file IO

SYNOPSIS
========

     # utilize stream I/O in your module
     $self->{'io'} = Bio::Root::IO->new(-file => "myfile");
     $self->{'io'}->_print("some stuff");
     $line = $self->{'io'}->_readline();
     $self->{'io'}->_pushback($line);
     $self->{'io'}->close();

     # obtain platform-compatible filenames
     $path = Bio::Root::IO->catfile($dir, $subdir, $filename);
     # obtain a temporary file (created in $TEMPDIR)
     ($handle) = $io->tempfile();

DESCRIPTION
===========

   This module provides methods that will usually be needed for any sort
of file- or stream-related input/output, e.g., keeping track of a file
handle, transient printing and reading from the file handle, a close
method, automatically closing the handle on garbage collection, etc.

   To use this for your own code you will either want to inherit from this
module, or instantiate an object for every file or stream you are dealing
with. In the first case this module will most likely not be the first
class off which your class inherits; therefore you need to call
_initialize_io() with the named parameters in order set file handle, open
file, etc automatically.

   Most methods start with an underscore, indicating they are private. In
OO speak, they are not private but protected, that is, use them in your
module code, but a client code of your module will usually not want to
call them (except those not starting with an underscore).

   In addition this module contains a couple of convenience methods for
cross-platform safe tempfile creation and similar tasks. There are some
CPAN modules related that may be not be available on all platforms. At
present, File::Spec and File::Temp are attempted. This module exports
$TEMPFILE and $ROOTDIR, which will always be set, $PATHSEP, which will be
set if File::Spec fails, and $OPENFLAGS, which will be set if either of
File::Spec or File::Temp fails.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                 - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp
====================

   Email hlapp@gmx.net

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
---

     Title   : new
     Usage   :
     Function: Overridden here to automatically call _initialize_io().
     Example :
     Returns : new instance of this class
     Args    : named parameters

_initialize_io
--------------

     Title   : initialize_io
     Usage   : $self->_initialize_io(@params);
     Function: Initializes filehandle and other properties.

     Currently recognized the following named parameters: -file, -fh
      Example :
      Returns : TRUE
      Args    : named parameters

_fh
---

     Title   : _fh
     Usage   : $obj->_fh($newval)
     Function:
     Example :
     Returns : value of _filehandle
     Args    : newvalue (optional)

_print
------

     Title   : _print
     Usage   : $obj->_print(@lines)
     Function:
     Example :
     Returns : writes output

_readline
---------

     Title   : _readline
     Usage   : $obj->_readline
     Function: Reads a line of input.

     Note that this method implicitely uses the value of $/ that is
     in effect when called.

     Note also that the current implementation does not handle pushed
     back input correctly unless the pushed back input ends with the
     value of $/.
      Example :
      Returns :

_pushback
---------

     Title   : _pushback
     Usage   : $obj->_pushback($newvalue)
     Function: puts a line previously read with _readline back into a buffer
     Example :
     Returns :
     Args    : newvalue

close
-----

     Title   : close
     Usage   : $seqio->close()
     Function: Closes the file handle associated with this seqio system
     Example :
     Returns :
     Args    :

tempfile
--------

     Title   : tempfile
     Usage   : my ($handle,$tempfile) = $io->tempfile();
     Function: Returns a temporary filename and a handle opened for writing and
               and reading.

     Caveats : If you do not have File::Temp on your system you should avoid
               specifying TEMPLATE and SUFFIX. (We don't want to recode
               everything, okay?)
     Returns : a 2-element array, consisting of temporary handle and temporary
               file name
     Args    : named parameters compatible with File::Temp: DIR (defaults to
               $Bio::Root::IO::TEMPDIR), TEMPLATE, SUFFIX.

tempdir
-------

     Title   : tempdir
     Usage   : my ($tempdir) = $io->tempdir(CLEANUP=>1);
     Function: Creates and returns the name of a new temporary directory.

     Note that you should not use this function for obtaining "the"
     temp directory. Use $Bio::Root::IO::TEMPDIR for that. Calling this
     method will in fact create a new directory.

     Returns : The name of a new temporary directory.
     Args    : args - ( key CLEANUP ) indicates whether or not to cleanup
               dir on object destruction, other keys as specified by File::Temp

catfile
-------

     Title   : catfile
     Usage   : $path = Bio::Root::IO->catfile(@dirs,$filename);
     Function: Constructs a full pathname in a cross-platform safe way.

     If File::Spec exists on your system, this routine will merely
     delegate to it. Otherwise it tries to make a good guess.

     You should use this method whenever you construct a path name
     from directory and filename. Otherwise you risk cross-platform
     compatibility of your code.

     You can call this method both as a class and an instance method.

     Returns : a string
     Args    : components of the pathname (directories and filename, NOT an
               extension)

Input and output manager for Perl5 objects.
*******************************************

NAME
====

   Bio::Root::IOManager - Input and output manager for Perl5 objects.

SYNOPSIS
========

Object Creation
---------------

   The creation of Bio::Root::IOManager.pm objects is handled by
Bio::Root::Object.pm which delegates various I/O tasks to this module.

     use Bio::Root::IOManager;

     $myIO = new Bio::Root::IOManager(-WHERE   =>'/usr/tmp/data.out',
        				     -PARENT =>$self);

INSTALLATION
============

   This module is included with the central Bioperl distribution:

     http://bio.perl.org/Core/Latest
     ftp://bio.perl.org/pub/DIST

   Follow the installation instructions included in the README file.

DESCRIPTION
===========

   This module encapsulates the data and methods necessary for regulating
input/output (I/O) of data from Perl objects.  It is concerned with
"where" to get input or send output as opposed to "what" to get.
IOManager.pm is intended to consolidate various I/O issues for Perl
objects and provide an object-oriented way to do I/O things such as:

   * passing filehandles between objects,

   * opening and reading input from files or STDIN,

   * routine file management (compressing, uncompressing, and deleting).

   Subclasses of *Bio::Root::Object.pm* have access to all methods defined
in IOManager.pm since *Bio::Root::Object.pm* employs
Bio::Root::IOManager.pm by a delegation mechanism.

   It is not clear yet how much objects really need to do the fancy I/O
gymnastics as supported by IOManager. Most of the time, objects simply
send output to STDOUT which is managed at the script/program level. The
fancy I/O manipulations are considered experimental and have not been
adequately tested or utilized.  I'm not really satisfied with the current
`display' in this node()/`set_display' in this node() strategy.  The
additional functionality is not often utilized in typical applications. Is
the extra complexity worth it?

   *The API for this module is under development.*

Generic Data Access & Manipulation
----------------------------------

   The `read' in this node() method provided permits the following:

   * read from a file or STDIN.

   * read a single record or a stream containing multiple records.

   * specify a record separator.

   * store all input data in memory or process the data stream as it is
     being read.

DEPENDENCIES
============

   Bio::Root::IOManager.pm inherits from *Bio::Root::Object.pm* and uses
*FileHandle.pm*.  *Bio::Root::Utilities.pm* is also used for routine file
manipulations compression/uncompression/deletion.

SEE ALSO
========

     Bio::Root::Object.pm       - Core object
     Bio::Root::Utilities.pm    - Generic utilty object
     Bio::Root::Global.pm       - Manages global variables/constants

     http://bio.perl.org/Projects/modules.html  - Online module documentation
     http://bio.perl.org/                       - Bioperl Project Homepage

     FileHandle.pm (included in the Perl distribution or CPAN).

TODO
====

   Experiment with using the newer *IO.pm* included in the Perl
distribution, instead of FileHandle.pm.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules.  Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR
======

   Steve A. Chervitz, sac@genome.stanford.edu

   See the `FEEDBACK' in this node section for where to send bug reports
and comments.

VERSION
=======

   Bio::Root::IOManager.pm, 0.043

ACKNOWLEDGEMENTS
================

   This module was developed under the auspices of the Saccharomyces Genome
Database:     http://genome-www.stanford.edu/Saccharomyces

COPYRIGHT
=========

   Copyright (c) 1997-98 Steve A. Chervitz. All Rights Reserved.  This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

APPENDIX
========

   Methods beginning with a leading underscore are considered private and
are intended for internal use by this module. They are not considered part
of the public interface and are described here for documentation purposes
only.

file
----

     Usage     : $object->file([filename]);
     Purpose   : Set/Get name of a file associated with an object.
     Example   : $object->file('/usr/home/me/data.txt');
     Returns   : String (full path name)
     Argument  : String (full path name) OR a FileHandle or TypeGlob reference
               : (argument only required for setting)
     Throws    : Exception if the file appears to be empty or non-existent
     Comments  : File can be text or binary.

   See Also   : `compress_file' in this node(), `uncompress_file' in this
node(), `delete_file' in this node()

set_fh
------

     Usage     : $self->set_fh( named_parameters )
     Purpose   : Sets various FileHandle data members ('fh', 'fherr').
               : Provides a public interface for _open_fh().
     Returns   : n/a
     Argument  : Named parameters:  (TAGS CAN BE UPPER OR LOWER CASE)
               :   -PATH  => string (filename) or a FileHandle object ref.
               :   -PRE   => string, prefix for opening (e.g., '>', '>>').
               :   -POST  => string, postfix for opening (e.g., '|'), for commands.
               :   -WHICH => string, 'err' for setting output path for errors.
               :
     Throws    : Exception propagated from _open_fh()
     Examples  : $self->set_fh();                   # Create anonymous FileHandle object
               : $self->set_fh(-PATH =>'fileName',  # Open for writing
     	   :		   -PRE =>'>');
               : $self->set_fh(-PATH =>'fileName',  # Open error log file in append mode.
     	   :		   -PRE  =>'>>',
     	   :		   -WHICH =>'err');
               : $self->set_fh(-PATH =>$obj->fh()); # Copy a file handle from another object.
               :
     Comments  : set_read() and set_display() provide
               : interfaces for set_fh().
     Status    : Experimental

   See also   : `_open_fh' in this node(), `set_read' in this node(),
`set_display' in this node().

_open_fh
--------

     Purpose   : Creates a new FileHandle object and returns it.
               : This method can be used when you need to
               : pass FileHandles between objects.
     Returns   : The new FileHandle object.
     Throws    : Exception: if the call to new FileHandle fails.
     Examples  : $self->_open_fh();            # Create anonymous FileHandle object
               : $self->_open_fh('fileName');  # Open for reading
               : $self->_open_fh('>fileName'); # Open for writing
     Status    : Experimental

   See also   : `set_fh' in this node(), `fh' in this node(), `set_read'
in this node(), `set_display' in this node()

_close_fh
---------

     Purpose   : Destroy a FileHandle object.
     Returns   : n/a
     Status    : Experimental

   See also   : `_open_fh' in this node(), `set_fh' in this node()

set_display
-----------

     Usage     : $self->set_display([-WHERE=>'path'],
     	   :			[-SHOW =>'what is to be displayed'],
     	   :			[-MODE =>'file open mode'])
     Purpose   : Sets a new FileHandle object for output.
               : - Sets the objects 'show' data member to 'default' if it is not defined.
               : - Is a wrapper for setting an object's STDOUT filehandle:
               :   Checks the -WHERE parameter and the status of the object's current
               :   filehandle {'_fh'} and does one of three things:
               :    1. If $param{-WHERE} is defined and is not 'STDOUT', it is sent to
               :       set_fh() to open a new fh,
               :    2. else, if 'fh' has already been defined, it is returned,
               :    3. else, if where equals 'STDOUT', \*STDOUT is returned.
               :    4. else, \*STDOUT is returned.
               :
               : Thus, if an object has already set its 'fh' to some location,
               : it can still print to 'STDOUT' by explicitly passing -WHERE='STDOUT'
               : to display().
               :
     Arguments : Named parameters: (TAGS CAN BE UPPER OR LOWER CASE).
               : (all are optional).
               :    -WHERE => full path name of file to write to or 'STDOUT'.
               :    -SHOW  => what data is to be displayed. Becomes $self->{'_show'}
               :                     Default = 'default'. This results in a call to
               :                     _display_stats() method when display() is called
               :    -MODE  => mode for opening file. Default is overwrite '>'.
               :
     Returns   : FileHandle object reference or typglob reference (\*STDOUT).
     Throws    : Exception propagated from set_fh().
     Example   : $self->set_display();
               : $self->set_display(-WHERE=>'./data.out');
               : $self->set_display(-WHERE=>$obj->fh());
     Status    : Experimental
     Comments  : I'm not satisfied with the current display()/set_display() strategy.

   See also   : `display' in this node(), `set_fh' in this node()

set_read
--------

     Purpose   : Sets a new FileHandle object for input.
               : Same logic as set_display() but creates filehandle for read only.
     Returns   : The input FileHandle object or \*STDIN.
     Arguments : Named parameters: (TAGS CAN BE UPPER OR LOWER CASE).
               :    $param{-WHERE} = full path name of file to write to.
     Access    : Public
     Status    : Experimental, Deprecated
               :
     WARNING   : THIS METHOD HAS NOT BEEN TESTED AND IS LIKELY UNNECESSARY.
               : USE THE read() METHOD INSTEAD.
               :
               : Note also that set_read() uses the same data member as set_display()
               : so it is currently not possible to simultaneously have
               : different displaying and reading filehandles. This degree of
               : I/O control has not been necessary.

   See also   : `read' in this node(), `set_display' in this node()

set_display_err
---------------

     Purpose   : Sets a new FileHandle object for outputing error information.
               : Same logic as set_display() but creates a filehandle in
               : append mode.
     Returns   : The output FileHandle object for saving errors or \*STDERR.
     Status    : Experimental
     WARNING   : NOT TESTED

   See also   : `set_display' in this node(), `set_read' in this node()

show
----

     Usage     : $self->show()
     Purpose   : Get the string used to specify what to display
               : using the display() method.
     Returns   : String or undef if no show data member is defined.
     Arguments : n/a

   See also   : `set_display' in this node()

fh
--

     Usage     : $object->fh(['name'])
     Purpose   : Accessor for an object's FileHandle object or the argument used
               : to create that object.
     Returns   : One of the following:
               :   1. The arguments used when the filehandle was created ('fh_name').
               :   2. The FileHandle object reference previously assigned to $self->{'_fh'}.
               :   3. Typeglob reference \*STDIN,  \*STDOUT or \*STDERR.
     Example   : $self->fh();          # returns filehandle for the STDIN/STDOUT path.
               : $self->fh('err');     # returns filehandle for the err file.
               : $self->fh('name');    # returns fh creation arguments.
               : $self->fh('errname'); # returns fh creation arguments for the err file.
     Status    : Experimental

   See also   : `set_display' in this node(), `set_read' in this node(),
`set_fh' in this node(), `set_display_err' in this node()

read
----

     Usage     : $object->read(<named parameters>);
     Purpose   : Read raw textual data from a file or STDIN.
               : Optionally process each record it as it is read.
     Example   : $data = $object->read(-FILE    =>'usr/people/me/data.txt',
     	   :			   -REC_SEP =>"\n:",
     	   :			   -FUNC    =>\&process_rec);
               : $data = $object->read(-FILE  =>\*FILEHANDLE);
               : $data = $object->read(-FILE  =>new FileHandle $file, 'r');
               :
     Argument  : Named parameters: (TAGS CAN BE UPPER OR LOWER CASE)
               :  (all optional)
               :    -FILE    => string (full path to file) or a reference
               :                to a FileHandle object or typeglob. This is an
               :                optional parameter (if not defined, STDIN is used).
               :    -REC_SEP => record separator to be used
               :                when reading in raw data. If none is supplied,
               :                the default record separator is used ($/).
               :                $/ is localized to this method but be careful if
               :                you do any additional file reading in functions
               :                called by this method (see the -FUNC parameter).
               :                Such methods will use the value of $/ set
               :                by read() (if a -RE_SEP is supplied).
               :    -FUNC    => reference to a function to be called for each
               :                record. The return value of this function is now checked:
               :                if false, the reading is terminated.
               :                Typically -FUNC supplies a closure.
               :    -HANDLE  => reference to a FileHandle object or a
               :                typeglob to be use for reading input.
               :                The FileHandle object should be configured to
               :                read from a desired file before calling this
               :                method. If both -handle and -file are defined,
               :                -handle takes precedence.
               :                (The -HANDLE parameter is no longer necessary
               :                 since -FILE can now contain a FileHandle ref.)
               :    -WAIT    => integer (number of seconds to wait for input
               :                before timing out. Default = 20 seconds).
               :
     Returns   : string, array, or undef depending on the arguments.
               : If a function reference is supplied, this function will be
               : called using the contents of each record as it is read in.
               : If no function reference is supplied, the data are returned as a
               : string in scalar context or as a list in array context.
               : The data are not altered; blank lines are not removed.
               :
     Throws    : Exception if no input is read from source.
               : Exception if no input is read within WAIT seconds.
               : Exception if FUNC is not a function reference.
               : Propagates any exceptions thrown by create_filehandle()
               :
     Comments  : Gets the file name from the current file data member.
               : If no file has been defined, this method will attempt to
               : read from STDIN.
               :
               : COMPRESSED FILES:
               :    read() will attempt to use gzip -cd to read the file
               : if it appears to be compressed (binary file test).
               :
               : If the raw data is to be returned, wantarray is used to
               : determine how the data are to be returned (list or string).
               :
               : Sets the file data member to be the supplied file name.
               : (if any is supplied).

     : The read() method is a fairly new implementation
     : and uses a different approach than display().
     : For example, set_read() is not used.

     Bugs      : The following error is generated by Perl's FileHandle.pm module
               : when using the -w switch. It can be ignored for now:
      "Close on unopened file <GEN0> at /tools/perl/5.003/lib/FileHandle.pm line 255."

   See Also   : `file' in this node(), `create_filehandle' in this node()

display
-------

     Usage     : $self->set_display(named parameters)
     Purpose   : Provides a default display method which calls set_display()
               : and also invokes methods to display an object's stats
               : if necessary ( _print_stats_header() and _displayStats() ).
     Returns   : True (1).
     Throws    : Propagates any exceptions thrown by set_display().
     Arguments : Named parameters for set_display().
     Comments  : I'm not satisfied with the current display()/set_display() strategy.

   See also   : `set_display' in this node(), `_print_stats_header' in
this node()

_print_stats_header
-------------------

     Usage     : n/a; internal method.
               : $obj->_print_stats_header(filehandle);
     Purpose   : Prints a header containing basic info about the object
               : such as the class and name of the object followed by a
               : line of hyphens.
     Status    : Experimental

file_date
---------

     Usage     : $object->file_date( %named_parameters);
     Purpose   : Get the last modified date of a file.
     Example   : $object->file_date();
               : $object->file_date(-FMT =>'yyyy-mmm-dd',
     				-FILE =>'/usr/people/me/data.txt');
               : $object->file_date(-FMT =>'yyyy-mmm-dd');
     Returns   : String (date)
     Argument  : Named parameters:  (TAGS CAN BE UPPER OR LOWER CASE)
               :   -FILE  => string (filename full path)
               :   -FMT   => string (format for the returned date string)
               :
     Throws    : Exception if no file is specified or the file is non-existent
               : (Propagated from Utilities::file_date())
     Comments  : File can be text or binary.

   See Also   : `file' in this node(), *Bio::Root::Utilities::file_date()*

compress_file
-------------

     Usage     : $object->compress_file([filename]);
     Purpose   : Compresses a file if not already compressed.
               : Compresses to a temorary file if user is not owner of supplied file.
     Example   : $object->file('/usr/home/me/data.txt');
               : $object->compress_file();
     Argument  : String (full path name) (optional).
               : If no argument is provided, the file data member is used.
     Returns   : String (compressed file name, full path).
               : Sets the file data member to the compressed name
               : when not operating on a file supplied as an argument.
               : Returns false (undef) if the file is already compressed
               : (binary test).
     Throws    : Exception if no file is specified.
               : Propagates any exception thrown by Bio::Root::Utilities::compress()
               : if the file cannot be compressed().
               : Tests if file is already compressed to avoid trivial error due to
               : the file already being compressed.
               :
     Comments  : Relies on the compress() method of Bio::Root::Utilities.pm
               : to implement the file compression functionality.
               : (Currently, Bio::Root::Utilities::compress() uses gzip.)
               :
               : If the user is not the owner of the file, the file is
               : compressed to a tmp file.
               :
               : All file compressing/uncompressing requests should go through
               : compress_file()/uncompress_file(). This serves to confine the
               : dependency between IOManager.pm module and Utilities.pm
               : which helps maintainability.
               :
     Bugs      : Only compresses text files. This obviates a dependency on
               : particular file suffixes but is not good if you
               : want to compress a binary file.
               :
               : May not be taint-safe.

   See Also   : `uncompress_file' in this node(), `file' in this node(),
*Bio::Root::Utilities::compress()*

uncompress_file
---------------

     Usage     : $object->uncompress_file([filename]);
     Purpose   : Uncompresses the file containing the raw report.
               : Uncompresses to a temorary file if user is not owner of supplied file.
     Example   : $object->file('/usr/home/me/data.txt.gz');
               : $object->uncompress_file();
     Argument  : String (full path name) (optional).
               : If no argument is provided, the file data member is used.
     Returns   : String (uncompressed file name, full path).
               : Sets the file data member to the uncompressed name
               : when not operating on a file supplied as an argument.
               : Returns false (undef) if the file is already uncompressed.
               :
     Throws    : Exception if no file is specified.
               : Propagates any exception thrown by Bio::Root::Utilities::compress()
               : if the file cannot be uncompressed().
               : Tests if file is already uncompressed to avoid trivial error due to
               : the file already being uncompressed.
     Comments  : See comments for compress_file(). They apply here as well.
               :
     Bugs      : Considers all binary files to be compressed. This obviates
               : a dependency on particular file suffixes.
               : May not be taint safe.

   See Also   : `compress_file' in this node(), `file' in this node(),
*Bio::Root::Utilities::uncompress()*

delete_file
-----------

     Usage     : $object->delete_file([filename]);
     Purpose   : Delete a file.
     Example   : $object->delete_file('/usr/people/me/data.txt');
     Returns   : String (name of file which was deleted) if successful,
               : undef if file does not exist.
               : Sets the file data member to undef
               : when not operating on a file supplied as an argument.
     Argument  : String (full path name) (optional).
               : If no argument is provided, the file data member is used.
     Throws    : Exception if the user is not the owner of the file.
               : Propagates any exception thrown by Bio::Root::Utilities::delete().
               : if the file cannot be deleted.
     Comments  : Be careful with this method: there is no undelete().
               : Relies on the delete() method provided by Bio::Root::Utilities.pm
               : to implement the file deletion functionality.
               : This method is not taint-safe.
               : It is intended for off-line maintenance use only.

   See Also   : `file' in this node(), *Bio::Root::Utilities::delete()*

FOR DEVELOPERS ONLY
===================

Data Members
------------

   Information about the various data members of this module is provided
for those wishing to modify or understand the code. Two things to bear in
mind:

  1. Do NOT rely on these in any code outside of this module.  All data
     members are prefixed with an underscore to signify that they are
     private.  Always use accessor methods. If the accessor doesn't exist
     or is inadequate, create or modify an accessor (and let me know,
     too!).

  2. This documentation may be incomplete and out of date.  It is easy for
     this documentation to become obsolete as this module is still
     evolving.  Always double check this info and search for members not
     described here.

        An instance of Bio::Root::IOManager.pm is a blessed reference to a
hash containing all or some of the following fields:

     FIELD          VALUE
     ------------------------------------------------------------------------
      _show         Selects display options.

     _fh           FileHandle object for redirecting STDIN or STDOUT.

     _fherr        FileHandle object for error data. Append mode.

     _fh_name      The arguments used to create fh.

     _fherr_name   The arguments used to create fherr.

     INHERITED DATA MEMBERS

     _parent       (From Bio::Root::Object.pm> Object reference for the owner of this IOManager.

A core Perl 5 object.
*********************

NAME
====

   Bio::Root::Object - A core Perl 5 object.

SYNOPSIS
========

   *Use of this module is deprecated. Wherever possible try to switch to
Bio::Root::RootI as the root of your inheritance tree. Using this module as
your root of inheritance will trigger a warning at object instantiation.
This module is no longer being maintained and will eventually disappear.*

Object Creation
---------------

     require Bio::Root::Object;

     $dad = new Bio::Root::Object();
     $son = new Bio::Root::Object(-name    => 'Junior',
     			         -parent  => $dad,
     			         -make    => 'full');

   See the `new' in this node() method for a complete description of
parameters.  See also `USAGE' in this node.

INSTALLATION
============

   This module is included with the central Bioperl distribution:

     http://bio.perl.org/Core/Latest
     ftp://bio.perl.org/pub/DIST

   Follow the installation instructions included in the README file.

DESCRIPTION
===========

   *Bio::Root::Object.pm* attempts to encapsulate the "core" Perl5 object:
What are the key data and behaviors ALL (or at least most) Perl5 objects
should have?

Rationale
---------

   Use of *Bio::Root::Object.pm* within the Bioperl framework facilitates
operational consistency across the different modules defined within the
*Bio::* namespace.  Not all objects need to derive from
*Bio::Root::Object.pm*. However, when generating lots of different types
of potentially complex objects which should all conform to a set of basic
expectations, this module may be handy.

   At the very least, this module saves you from re-writing the `new' in
this node() method for each module you develop. It also permits consistent
and robust handling of `-tag => value' method arguments via the
`_rearrange' in this node() method and provides a object-oriented way
handle exceptions and warnings via the `throw' in this node() and `warn'
in this node() methods.  See the `APPENDIX' in this node for some other
handy methods.

Fault-Tolerant Objects
----------------------

   A major motivation for this module was to promote the creation of
robust, fault-tolerant Perl5 objects. The `throw' in this node() method
relies on Perl's built-in `eval{}/die' exception mechanism to generate
fatal exceptions.  The data comprising an exception is managed by the
*Bio::Root::Err.pm* module, which essentially allows the data thrown by a
`die()' event to be wrapped into an object that can be easily examined and
possibly re-thrown.

   The intent here is three-fold:

  1. Detailed error reporting.  Allow objects to report detailed
     information about the error condition (who, what, where, why, how).

  2. Handle complex errors in objects.  The goal is to make it relatively
     painless to detect and handle the wide variety of errors possible
     with a complex Perl object.  Perl's error handling mechanism is a
     might clunky when it comes to handling complex errors within complex
     objects, but it is improving.

  3. Efficient & easy exception handling.  To enable robust exception
     handling without incurring a significant performance penalty in the
     resulting code. Ideally, exception handling code should be
     transparent to the cpu until and unless an exception arises.

        These goals may at times be at odds and I am not claiming to have
achieved the perfect balance. Ultimately, we want self- sufficient
object-oriented systems able to deal with their own errors.  This area
should improve as the module, and Perl, evolve.  One possible modification
might be to utilize Graham Barr's *Error.pm* module or Torsten Ekedahl's
*Experimental::Exception.pm* module (see `Other Exception Modules' in this
node).  Technologies such as these may eventually be incorporated into
future releases of Perl. The exception handling used by
*Bio::Root::Object.pm* can be expected to change as Perl's exception
handling mechanism evolves.

   *TERMINOLOGY NOTE:* In this discussion and elsewhere in this module,
the terms "Exception" and "Error" are used interchangeably to mean
"something unexpected occurred" either as a result of incorrect user input
or faulty internal processing.

USAGE
=====

Basic Exception handling
------------------------

   Object construction is a common place for exceptions to occur. By
wrapping the construction in an `eval{ }' block, we can prevent the
exception from crashing the script and attempt to recover gracefully:

     # Package Foo.pm IS-A Bio::Root::Object.pm

     $obj = eval { new Foo(@data) };  # ending semicolon required.
     if($@) {
         print STDERR "\nTrouble creating Foo object: $@\n";
         recover_gracefully($@);
     }

   A common strategy when generating lots of objects is to collect data
about which objects failed to build but still permit the successfully
created ones get processed:

     @errs = ();
     foreach $thing ( @stuff ) {
         my $obj = eval { new Foo($thing) };
         if($@) {
             push @err, [$thing, $@];
         }
         else {
             process_obj($obj);
         }
     }

   Post-mortem reporting, logging, or analysis of the problems ensues:

     if(@errs) {
         printf "\n%d things failed:\n", scalar(@errs);
         foreach(@errs) { print "$err->[0], ";}

     print "\n\nTrapped exceptions:\n";
     foreach(@errs) { print "$err->[1]\n";}
         }

   New with *Perl 5.005* is the ability to `die()' with an object
reference in `$@' instead of just a string. This feature is not yet
exploited in Bio::Root::Object.pm but may be in future versions.
Bio::Root::Err.pm objects can be reconstructed from the contents of `$@':

     eval{ # exception-prone code here... };
     if($@) {
         $err = new Bio::Root::Err($@);
         printf "Trouble: %s\n". $err->msg;
         printf "Stack trace: %s\n". $err->stack;
     }

Demo Scripts
------------

   Some demo script that illustrate working with Bio::Root::Objects are
included with the distribution (see `INSTALLATION' in this node). These
are also available at:

     http://bio.perl.org/Core/Examples/Root_object

STRICTNESS & VERBOSITY
======================

   There are two global variables that can be used to control sensitivity
to exceptions/warnings and the amount of reporting for all objects within
a process.  These are accessed via functions `strictness()' and
`verbosity()' exported by *Bio::Root::Global.pm*.

     $STRICTNESS  - Regulates the sensitivity of the object to exceptions and warnings.

     $VERBOSITY   - Regulates the amount of reporting by an object.

   The Strict,() and `verbose' in this node() methods of
*Bio::Root::Object.pm* originally operated at the the object level, to
permit individual strictness and verbosity levels for different objects.
This level of control is not usually required and can often be
inconvenient; one typically wants to set these properties globally for a
given script. While this sacrifices some flexibility, it saves time and
memory when working with lots of objects. For instance, child objects
don't have to worry about checking their parents to determine their
strictness/verbosity levels. Strictness and verbosity are globally-defined
values, but different classes of objects can be differentially sensitive
to these values depending on design criteria.

   Strictness and verbosity can be positive or negative. Negative
verbosity equals terseness; negative strictness equals permissiveness.  In
*Bio::Root::Object.pm* only the `throw' in this node() and `warn' in this
node() methods are sensitive to these values as indicated in the tables
below:

     +---------+
     | throw() |         v e r b o s i t y
     +---------+ -------------------------------------
                    -1             0            1
     s           ----------   -----------   ----------
     t
     r   -2   --     throw() converted into warn()
     i
     c   -1   |   Exception    Exception      Exception
     t    0   |_  printed      printed        printed
     n    1   |   without      with           with stack
     e    2   |   stack trace  stack trace    trace and
     s        |                               sysbeep
     s

     +---------+
     | warn()  |         v e r b o s i t y
     +---------+ --------------------------------------
                    -1             0            1
     s           ----------   -----------   -----------
     t
     r   -2   |   Warning      Warning        Warning
     i   -1   |_  not          printed        printed
     c    0   |   printed      without        with stack
     t    1   |   but          stack trace    trace and
     n        |   attached*                   sysbeep
     e
     s    2   --      warn() converted into throw()
     s

     (*) Warnings will be attached to an object if the
     -record_err =>1 flag is set when constructing the object
     or if $object->record_err(1) is called subsequent to creation.

   See the methods `verbose' in this node(), see Strict,(),
`throw' in this node(), `warn' in this node(), and `record_err' in this
node() for more details.

DEPENDENCIES
============

   As the *Bio::Root::Object.pm* does not inherit from any modules but
wraps (i.e., provides an interface and delegates functionality to) other
modules in the Bio::Root:: hierarchy:

     Module                    Purpose
     --------------------      ------------------------------------
     Bio::Root::Err.pm         Exception handling
     Bio::Root::IOManager.pm   Input/output of object data or error data
     Bio::Root::Xref.pm        Arbitrary links between objects

   All of these modules are loaded only when necessary.
*Bio::Root::Err.pm* is an object representing an exception.
*Bio::Root::IOManager.pm* and *Bio::Root::Xref.pm* are more experimental.
They are utilized via delegation, which permits them to be developed and
utilized independently of *Bio::Root::Object.pm*.

   Since this module is at the root of potentially many different objects
in a particular application, efficiency is important. Bio::Root::Object.pm
is intended to be a lightweight, lean and mean module.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules.  Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR
======

   Steve A. Chervitz, sac@genome.stanford.edu

   See the `FEEDBACK' in this node section for where to send bug reports
and comments.

VERSION
=======

   Bio::Root::Object.pm, 0.041

TODO
====

   * Experiment with other Exception classes.

     Consider incorporating a more widely-used Error/Exception module (see
     `Other Exception Modules' in this node).

   * Think about integration with Data::Dumper.pm for persisting objects.

SEE ALSO
========

     Bio::Root::Err.pm       - Error/Exception object
     Bio::Root::IOManager.pm - Input/Output manager object
     Bio::Root::Vector.pm    - Manages dynamic lists of objects
     Bio::Root::Xref.pm      - Cross-reference object
     Bio::Root::Global.pm    - Manages global variables/constants

     http://bio.perl.org/Projects/modules.html  - Online module documentation
     http://bio.perl.org/                       - Bioperl Project Homepage

Other Exception Modules
-----------------------

     Experimental::Exception.pm   - ftp://ftp.matematik.su.se/pub/teke/
     Error.pm                     - http://www.cpan.org/authors/id/GBARR/
     Throwable.pm                 - mailto:kstevens@globeandmail.ca

     http://genome-www.stanford.edu/perlOOP/exceptions.html

ACKNOWLEDGEMENTS
================

   This module was developed under the auspices of the Saccharomyces Genome
Database:     http://genome-www.stanford.edu/Saccharomyces

   Other Bioperl developers contributed ideas including Ewan Birney, Ian
Korf, Chris Dagdigian, Georg Fuellen, and Steven Brenner.

COPYRIGHT
=========

   Copyright (c) 1996-98 Steve A. Chervitz. All Rights Reserved.  This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

APPENDIX
========

   Methods beginning with a leading underscore are considered private and
are intended for internal use by this module. They are not considered part
of the public interface and are described here for documentation purposes
only.

new
---

     Purpose   : Creates a blessed object reference (hash) for the indicated class
               : and calls _initialize() for the class passing it all parameters.
     Usage     : new CLASS_NAME [ %named_parameters];
     Example   : $obj = new Bio::Root::Object 'george';
               : $obj = Bio::Root::Object->new(-name    => 'L56163',
     	   : 			           -parent => $obj2 );
               : $obj = Bio::Root::Object->new();
     Returns   : Blessed hash reference.
     Argument  : Named parameters:  (PARAMETER TAGS CAN BE UPPER OR LOWERCASE).
               : (all are optional)
               :  -NAME       => arbitrary string to identify an object;
               :                 should be unique within its class.
               :  -PARENT    => blessed reference for an object that
               :                 is responsible for the present object
               :                 (e.g., a container).
               :  -MAKE       => string to specify special constructor option.
               :  -OBJ        => object reference for an object to be cloned.
               :  -RECORD_ERR => boolean (if true, attach all Err.pm objects generated by
     	   :                 warn() or throw() calls to the present object;
     	   :		     default = false).
               :
               : The use of STRICT and VERBOSE in constructors is no longer
               : necessary since there is no object-specific strict or verbose setting.
               : Use the strictness() and verbosity() functions exported by
               : Bio::Root::Global.pm. These options are still provided
               : in the constructor but the will affect *all* objects within a
               : given process.
               :
               :  -STRICT     => integer (level of strictness: -2, -1, 0, 1, 2).
               :  -VERBOSE    => integer (level of verbosity: -1, 0, 1)
               :                 Verbosity can be used to control how much reporting
               :                 an object should do generally. In this module,
               :                 verbosity affects the behavior of throw() and warn()
               :                 only.
               :
               :
     Comments  : This method creates blessed HASH references.
               : An object is free to define its own strict, and verbose
               : behavior as well as its own make (constructor) options.

   See Also   : `_initialize' in this node(), `name' in this node(),
`parent' in this node(), `make' in this node(), see Strict,(),
`verbose' in this node(), `throw' in this node(), `warn' in this node(),
`record_err' in this node()

_initialize
-----------

     Purpose   : Initializes key Bio::Root::Object.pm data (name, parent, make, strict).
               : Called by new().
     Usage     : n/a; automatically called by Bio::Root::Object::new()
     Returns   : String containing the -MAKE constructor option or 'default'
               : if none defined (if a -MAKE parameter is defined, the value
               : returned will be that obtained from the make() method.)
               : This return value saves any subclass from having to call
               : $self->make() during construction. For example, within a
               : subclass _initialize() method, invoke the Bio::Root::Object::
               : initialize() method as follows:
               :    my $make = $self->SUPER::_initialize(@param);
     Argument  : Named parameters passed from new()
               :  (PARAMETER TAGS CAN BE ALL UPPER OR ALL LOWER CASE).
     Comments  : This method calls name(), make(), parent(), strict(), index()
               : and thus enables polymorphism on these methods. To save on method
               : call overhead, these methods are called only if the data need
               : to be set.
               :
               : The _set_clone() method is called if the -MAKE option includes
               : the string 'clone' (e.g., -MAKE => 'clone').
               :
               : The index() method is called if the -MAKE option includes
               : the string 'index'. (This is an experimental feature)
               : (Example: -MAKE => 'full_index').
               :
               : NOTE ON USING _rearrange():
               :
               : _rearrange() is a handy method for working with tagged (named)
               : parameters and it permits case-insensitive in tag names
               : as well as handling tagged or un-tagged parameters.
               : _initialize() does not currently call _rearrange() since
               : there is a concern about performance when setting many objects.
               : One issue is that _rearrange() could be called with many elements
               : yet the caller is interested in only a few. Also, derived objects
               : typically invoke _rearrange() in their constructors as well.
               : This could particularly degrade performance when creating lots
               : of objects with extended inheritance hierarchies and lots of tagged
               : parameters which are passes along the inheritance hierarchy.
               :
               : One thing that may help is if _rearrange() deleted all parameters
               : it extracted. This would require passing a reference to the param list
               : and may add excessive dereferencing overhead.
               : It also would cause problems if the same parameters are used by
               : different methods or objects.

   See Also   : `new' in this node(), `make' in this node(), `name' in
this node(), `parent' in this node(), see Strict,(), `index' in
this node(), `_rearrange' in this node(), `_set_clone' in this node(),
`verbose' in this node()

DESTROY
-------

     Purpose   : Provides indication that the object is being reclaimed
               : by the GC for debugging purposes only.
     Usage     : n/a; automatically called by Perl when the ref count
               : on the object drops to zero.
     Argument  : n/a
     Comments  : Setting the global $DEBUG to 2 will print messages upon
               : object destruction.
               : Subclasses should override this method to
               : clean up any resources (open file handles, etc.)
               : The overridden method should end with a call to
               : SUPER::DESTROY;

   See Also   : `destroy' in this node()

destroy
-------

     Purpose   : Clean up any resources allocated by the object and
               : remove links to all objects connected to the present
               : object with the ultimate aim of signaling the GC to
               : reclaim all memory allocated for the object.
               : This method breaks links to any Err, IOManager, and Xref objects
               : and drops the present object as a child from any parent objects.
     Usage     : $object->destroy(); undef $object;
               : undef-ing the object reference signals the GC to reclaim
               : the object's memory.
     Returns   : undef
     Argument  : n/a
     Comments  : Circular reference structures are problematic for garbage
               : collection schemes such as Perl's which are based on reference
               : counting. If you create such such structures outside of
               : the parent-child relationship, be sure to properly break
               : the circularity when destroying the object.
               : Subclasses should override this method to call destroy()
               : on any contained child objects. The overridden method
               : should end with a call to SUPER::destroy().
     Bugs      : Bio::Root::Xref.pm objects have not been tested and
               : may not be handled properly here.
               : Bio::Root::Vector.pm objects are also not yet handled
               : properly so beware of crunching lots of Vector objects.

_drop_child
-----------

     Usage     : $object->_drop_child(object_ref)
               : Used internally by destroy().
     Purpose   : To remove a parent-to-child inter-object relationship.
               : The aim here is to break cyclical object refs to permit Perl's
               : GC to reclaim the object's memory. The expectation is that
               : a child object requests of its parent that the parent drop the
               : child object making the request. Parents do not drop children
               : unless requested by the child in question.
     Example   : $self->parent->_drop_child($self);
     Returns   : undef
     Argument  : Object reference for the child object to be dropped
     Throws    : Exception if an object ref is not provided as an argument.
     Comments  : This is a simplistic version that systematically checks every
               : data member, searching all top-level array, hash, and scalar data members.
               : It does not recurse through all levels of complex data members.
               : Subclasses could override this method to handle complex child data members
               : for more optimal child searching. However, the version here is
               : probably sufficient for most situations.
               :
               : _drop_child() is called by Bio::Root::Object::destroy() for all objects
               : with parents.
     Status    : Experimental

   See Also   : `destroy' in this node()

name
----

     Usage     : $object->name([string]);
     Purpose   : Set/Get an object's common name.
     Example   : $myName = $myObj->name;
               : $myObj->name('fred');
     Returns   : String consisting of the object's name or
               : "anonymous <CLASSNAME>" if name is not set.
               : Thus, this method ALWAYS returns some string.
     Argument  : String to be used as the common name of the object.
               : Should be unique within its class.

   See also   : `has_name' in this node()

to_string
---------

     Usage     : $object->to_string();
     Purpose   : Get an object as a simple string useful for debugging purposes.
     Example   : print $myObj->to_string;  # prints: Object <PACKAGE NAME> "<OBJECT NAME>"
     Returns   : String consisting of the package name + object's name
               : Object's name is obtained by calling the name() method.
     Argument  : n/a
     Throws    : n/a

   See also   : `name' in this node()

parent
------

     Usage     : $object->parent([object | 'null']);
     Purpose   : Set/Get the current object's source object.
               : An object's source object (parent) is defined as the object
               : that is responsible for creating the current object (child).
               : The parent object may also have a special mechanism for
               : destroying the child object. This should be included
               : in the parent object's DESTROY method which should end with a
               : call to $self->SUPER::DESTROY.
     Example   : $myObj->parent($otherObject);
     Returns   : Object reference for the parent object or undef if none is set.
     Argument  : Blessed object reference (optional) or the string 'null'.
               :  'null' = sets the object's _parent field to undef,
               :           breaking the child object's link to its parent.
     Throws    : Exception if argument is not an object reference or 'null'.
     Comments  : This method may be renamed 'parent' in the near future.
               : When and if this happens, parent() will still be supported but
               : will be deprecated.

   See also   : `destroy' in this node()

src_obj
-------

     Usage     : $object->src_obj([object | 'null']);
               : THIS METHOD IS NOW DEPRECATED. USE parent() INSTEAD.
     Purpose   : Set/Get the current object's source object (parent).

     =cut

   #-----------' sub src_obj { #-----------     my ($self) = shift;
$self->warn("DEPRECATED METHOD src_obj() CALLED. USE parent() INSTEAD.\n");
   $self->parent(@_); }

has_name
--------

     Usage     : $object->has_name();
     Purpose   : To determine if an object has a name.
     Returns   : True (1) if the object's {'Name'} data member is defined.
               : False otherwise.
     Comments  : One may argue, why not just use the name() method as a
               : combination setter/getter? has_name() is necessary for
               : the following reasons:
               :   (1) If an object's name is not defined, name() returns
               :        "anonymous <CLASSNAME>".
               :   (2) If an object's name is 0 (zero) or '' (empty string),
               :       conditionals that simply check name() would fail incorrectly.

   See also   : `name' in this node()

make
----

     Usage     : $object->make([string]);
     Purpose   : Set/Get an object's constructor option.
               : make() is intended for use during object construction
               : to essentially permit alternate constructors since
               : Perl doesn't have a built-in mechanism for this.
     Example   : $make = $object->make();
               : $object->make('optionA');
     Returns   : String consisting of the object's make option
               : or 'default' if make is not set.
               : Thus, this method ALWAYS returns some string.
     Argument  : String to be used as an option during object construction.
     Comments  : A typical use of a make option is when cloning an object
               : from an existing object. In this case, the new() method
               : is called with -MAKE => 'clone'.

   See also   : `_initialize' in this node(), `clone' in this node()

err
---

     Usage     : $self->err([$data], [$delimit])
     Purpose   : Check for exceptions/warnings and get data about them.
               : (object validation and error data retrieval)
     Example   : $self->err && print "has err";
               : $errCount = $self->err('count');
               : $errMsgs  = $self->err('msg',"\t");
               : @errNotes = $self->err('note');
     Returns   : One of the following:
               :   1. If no arguments are given
               :          a. If the object has an error, the err data member is
               :             returned (this is an Bio::Root::Err.pm object),
               :          b. otherwise, undef is returned.
               :   2. The number of Errs in the object's err data member (if $data eq 'count').
               :   3. A string containing data from a specific field from an object's err member.
               :      -- If the object contains multiple errors, data for all errors will be
               :         strung together in reverse chronological order with each error's data
               :         preceeded by "Error #n\n" and followed by two delimiters.
               :   4. A list containing data from a specific field from an object's err member.
               :      -- If the object contains multiple errors, data for all errors will be
               :         added in reverse chronological order as separate elements in the list
               :         with NO "Error #n\n" identifier. Individual err list data
               :         (note,tech,stack) will be tab-delimited.
     Arguments : $data    = The name of a specific Err data member (see %Bio::Root::Err::ERR_FIELDS)
               :            OR 'count'.
               : $delimit = The delimiter separating a single Err's list data member's elements.
               :            Default is "\n". For multi-error objects, two of these
               :            delimiters separate data from different errors.
               :            If wantarray is true or delimiter is 'list', data from multiple
               :            errors will be returned as a list
               :
     Comments  : Since Err objects are now fatal and are not attached to the object by default,
               : this method is largely moot. It is a relic from the former
               : error "polling" days.
               : It is handy for accessing non-fatal warnings thrown by the object,
               : or in situations where fatal errors are converted to warnings
               : as when $self->strict is -1 or $WARN_ON_FATAL is true.
               : (Note: an object now only attaches Err objects to itself when
     	   : constructed with -RECORD_ERR =>1 or if the global $RECORD_ERR is true).
               :
               : This method is intended mainly to test whether or not an object
               : has any Err objects associated with it and if so, obtaining the
               : Err object or specific data about it.
               : For obtaining ALL data about an error, use err_string().
               : For more detailed manipulations with the Err data, retrieve the
               : Err object and process its data as necessary.

   See also   : `err_string' in this node(), `print_err' in this node(),
*Bio::Root::Err.pm*::get_all

record_err
----------

     Usage     : $object->record_err([0|1]);
     Purpose   : Set/Get indicator for whether an object should save
               : the Bio::Root::Err.pm objects it generates via calls
               : to throw() or warn().
     Example   : $myObj->record_err(1)
     Returns   : Boolean (0|1)
     Argument  : Boolean (0|1)
     Comments  : Record_err is generally useful only for examining
               : warnings produced by an object, since calls to throw()
               : are normally fatal (unless strictness is set to -2).
               : To turn on recording of errors for all objects in a process,
               : use Bio::Root::Global::record_err().
     Status    : Experimental

   See also   : `_set_err' in this node(),
*Bio::Root::Global::record_err()*

err_state
---------

     Usage     : $object->err_state();
     Purpose   : To assess the status of the object's Err object (if any).
     Returns   : A string: 'EXCEPTION' | 'WARNING' | 'FATAL' | 'OKAY'
               : (OKAY is returned if there are no Errors)
     Status    : Experimental

   See also   : `_set_err_state' in this node()

clear_err
---------

     Purpose   : To remove any error associated with the given object.
     Usage     : $myObj->clear_err;

   See  also  : `_set_err' in this node()

containment
-----------

     Usage     : $aref = $object->containment();
               : Since this method can be exported, the following can be used:
               : $aref = containment($object);
     Purpose   : To determine the containment hierarchy of a object.
     Returns   : An array reference in which each element is a string
               : containing the class and name of
               : the object in which this object is contained.
               : Indentation increases progressively as the
               : hierarchy is traversed.
               : E.g.,  Object MyClass "Foo"
               :         Contained in object YourClass "Bar"
               :          Contained in object HisClass "Moo"
     Comments  : This method will report only one object at each level
               : since an object can currently have only one source object.
     Status    : Exported

   See also   : `_set_err' in this node()

set_stats
---------

     Usage     : $object->set_stats(KEY => DATA [,KEY2 => DATA2])
     Purpose   : To declare and initialize a set of statistics germain
               : to an object. Each statistic name becomes a data member
               : prefixed with an underscore (if not already) and first
               : character after the underscore is lowercased.
     Example   : $object->set_stats('num_A' =>1,
               :                    'Num_B' =>10 ):
               : This sets :
               :     $object->{'_num_A'} = 1
               :     $object->{'_num_B'} = 10;
     Returns   : n/a
     Comments  : This method implements a convention for naming Perl
               : object data members with a leading underscore,
               : consistent with the naming convention of private methods.
               : Data members should not be part of an object's public
               : interface. The leading underscore helps flag the members
               : as private and also prevents inadvertant clobbering.

strict
------

     Usage     : $object->strict( [-2|-1|0|1|2] );
               : warn $message if $object->strict > 0;
     Purpose   : To make the object hyper- or hyposensitive to exceptions & warnings.
               : Strict = 2  : extremely hyper-sensitive, converts warn() into throw().
               : Strict = 1  : hyper-sensitive, but calls to warn are not converted.
               : Strict = 0  : no change (throw() = fatal, warn() = non-fatal).
               : Strict = -1 : hypo-sensitive, but calls to throw are not converted.
               : Strict = -2 : extremely hypo-sensitive, converts throw() into warn()
               :
               : Two degrees of positive and negative values for strict permit
               : the following functionality:
               :   1. Setting strict to 2 or -2 leads to more dramatic strictness
               :      or permissiveness, respectively. With 2, all calls to warn()
               :      become calls to throw() and are therefore fatal. With -2,
               :      the opposite is true and calls to throw become non-fatal.
               :      A strict value of 2 is thus an object-level version of
               :      Perl's "use strict" pragma.
               :
               :   2. Setting strict to 1 or -1 does not affect the behavior of
               :      throw() and warn(). This allows an object to implement its
               :      its own strictness policy. A strict value of 1 is thus an
               :      an object-level version of Perl's -w flag.
               :
     Returns   : Integer between -2 to 2.
     Comments  : This method no longer accesses an object-specific strictness
               : level but rather the global $STRICTNESS variable
               : defined in Bio::Root::Global.pm and accessed via the
               : strictness() method exported by that package.
               : Thus, all objects share the same strictness which
               : is generally more convenient.
     Status    : Experimental

   See also   : `warn' in this node(), `throw' in this node(), `STRICTNESS
& VERBOSITY' in this node, *Bio::Root::Global::strictness()*

clone
-----

     Purpose   : To deeply copy an object.
               : Creates a new object reference containing an exact
               : copy of an existing object and all its data members.
     Usage     : $myClone = $myObj->clone;
     Comments  : This method only clones the Bio::Root::Object data members.
               : To fully clone an object that has data members beyond
               : those inherited from Bio::Root::Object, you must provide a
               : constructor in your class to copy all data of an object
               : data into the clone. For an example, see how _set_clone()
               : is called by _initialize() in this class.
               :
               : clone() will pass the named parameters {-MAKE=>'clone'}
               : and {-OBJ=>$self} to the object's constructor. The
               : constructor should then either check the -MAKE parameter
               : directly or should check the return value from
               : a call to the superclass constructor (see _initialize()
               : for an example) and then copy the required data members from OBJ
               : into the new object, bypassing the normal construction process.
               : Cloning of objects has not been extensively tested.
               : USE WITH CAUTION.
     Status    : Experimental

   See Also   : `_set_clone' in this node(), `_initialize' in this node()

_set_clone
----------

     Usage     : n/a; internal method used by _initialize()
               : $self->_set_clone($object_to_be_cloned)
     Purpose   : Deep copy all Bio::Root::Object.pm data members
               : into a new object reference.
               : (This is basically a copy constructor).
     Argument  : object ref for object to be cloned.
     Throws    : Exception if argument is not an object reference.
     Comments  : Data members which are objects are cloned (parent, io, err).
               : Cloning of objects has not been extensively tested.
               : USE WITH CAUTION.

   See Also   : `_initialize' in this node()

verbose
-------

     Usage     : $object->verbose([-1|0|1]);
     Purpose   : Set/Get an indicator for how much ruporting an object should do.
     Argument  : integer (-1, 0, or 1)
     Returns   : integer (-1, 0, or 1)
               : Returns 0 if verbosity has not been defined.
               : Verbosity > 0 indicates extra reporting.
               : Verbosity < 0 indicates minimal reporting.
               : Verbosity = 0 or undefined indicates default reporting.
     Comments  : This method no longer accesses an object-specific verbosity
               : level but rather the global $VERBOSITY variable
               : defined in Bio::Root::Global.pm and accessed via the
               : verbosity() method exported by that package.
               : Thus, all objects share the same verbosity which
               : is generally more convenient.
     Status    : Experimental

   See Also   : Strict,(), `STRICTNESS & VERBOSITY' in this
node, *Bio::Root::Global::verbosity()*

I/O-RELATED METHODS (Delegated to *Bio::Root::IOManager.pm*)
============================================================

_io
---

     Usage     : $object->_io()
     Purpose   : Get the Bio::Root::IOManager.pm object for the current object.

   See also   : `display' in this node(), `read' in this node(), `file' in
this node()

_set_io
-------

     Usage     : n/a; internal use only.
     Purpose   : Sets a new Bio::Root::IOManager.pm object for the current object.

   See also   : `display' in this node(), `read' in this node(), `file' in
this node()

set_display
-----------

     Usage     : $object->set_display( %named_parameters).
               : See Bio::Root::IOManager::set_display() for a description of parameters.
     Purpose   : Sets the output stream for displaying data associated with an object.
               : Delegates to Bio::Root::IOManager::set_display().
     Argument  : Named parameters (optional).
               : See Bio::Root::IOManager::set_display() for a
               : description of arguments.
     Status    : Experimental
     Comments  : Sets the IOManager.pm object if it is not set.
               : I'm not satisfied with the current display()/set_display() strategy.

   See also   : *Bio::Root::IOManager.pm*::set_display

display
-------

     Usage     : $object->display( named parameters)
               : See Bio::Root::IOManager::display() for a description of parameters.
     Purpose   : Output information about an object's data.
               : Delegates this task to Bio::Root::IOManager::display()
     Argument  : Named parameters for IOManager::set_display()
     Status    : Experimental
     Comments  : Sets the IOManager.pm object if it is not set.
               : IOManager::set_display()is then called on the new IOManager object.
               :
               : The motivation behind the display() method and IOManager.pm
               : is to allow for flexible control over output of an
               : object's data to/from filehandles, pipes, or STDIN/STDOUT,
               : and for passing file handles between objects. Currently,
               : it is used mainly for output to STDOUT.
               :
               : There is some concern whether this much functionality is
               : actually necessary, hence the "Experimental" status of this
               : method.
               :
               : -------
               : It might be worthwhile to also have a string() method
               : that will put an object's data into a string that can be
               : further processed as desired. Stringification for persistence
               : issues might be best handled by Data::Dumper.pm.
               :
               : When overriding this method, use the following syntax:
               :
               : sub display {
               :    my ($self, %param) = @_;
               :    $self->SUPER::display(%param);
               :    my $OUT = $self->fh();
               :    print $OUT "\nSome data...\n";
               :  ...
               : }
               : Now $OUT holds a filhandle reference (or the string 'STDOUT')
               : which can be passed to other methods to display different
               : data for the object.
               : _set_display() is automatically called with $OUT as the sole
               : argument (after $self) by IOManager.pm::display()
               : if the -SHOW parameter is set to 'stats' or 'default'.
               :
     Bugs      : Because the $OUT variable can be a FileHandle or a string,
               : it is necessary to include the line before using $OUT in
               : print statements:
               : I am considering a cleaner way of dealing with this.
               : Setting $OUT to a glob (*main::STDOUT) was unsuccessful.
               :
               : I'm not satisfied with the current display()/set_display() strategy.

   See also   : *Bio::Root::IOManager::display()*

_display_stats
--------------

     Usage     : n/a; called automatically by Bio::Root::Object::display(-SHOW=>'stats');
     Purpose   : Display stereotypical data for an object.
               : Automatically called via display().
     Argument  : Filehandle reference or string 'STDOUT' 'STDIN' 'STDERR'
     Status    : Experimental

   See also   : `display' in this node()

read
----

     Usage     : $object->read( named parameters)
               : See Bio::Root::IOManager::read() for a description of parameters.
     Purpose   : Inputs data from an arbitrary source (file or STDIN).
               : Delegates this task to Bio::Root::IOManager::read().
     Status    : Experimental
     Comments  : Sets the IOManager.pm object if it is not set.
               : See the comments for the display() method for some comments
               : about IO issues for objects.
               : Note that the read() method uses a different strategy than
               : the display() method.
               : IO issues are considered experimental.

     See also   : L<display>(), B<Bio::Root::IOManager::read()>

fh
--

     Usage     : $object->fh(['name'])
               : See Bio::Root::IOManager::fh() for a complete usage description.
     Purpose   : Get an object's current FileHandle object or IO stream indicator.
               : Delegates to Bio::Root::IOManager.pm.
     Status    : Experimental
     Comments  : Sets the IOManager.pm object if it is not set.

   See also   : *Bio::Root::IOManager::fh()*

show
----

     Usage     : $object->show()
               : See Bio::Root::IOManager::show() for details.
     Purpose   : Get the string used to specify what to display
               : using the display() method.
               : Delegates to Bio::Root::IOManager.pm.
     Status    : Experimental
     Comments  : Sets the IOManager.pm object if it is not set.

   See also   : *Bio::Root::IOManager::show()*,
*Bio::Root::IOManager::set_display()*

file
----

     Usage     : $object->file()
               : See Bio::Root::IOManager::file() for details.
     Purpose   : Set/Get name of a file associated with an object.
               : Delegates to Bio::Root::IOManager.pm.
     Status    : Experimental
     Comments  : Sets the IOManager.pm object if it is not set.

   See also   : *Bio::Root::IOManager::file()*

compress_file
-------------

     Usage     : $object->compress_file([filename])
               : See Bio::Root::IOManager::compress_file() for details.
     Purpose   : Compress a file associated with the current object.
               : Delegates to Bio::Root::IOManager.pm.
     Throws    : Propagates exceptions thrown by Bio::Root::IOManager.pm
     Status    : Experimental
     Comments  : Sets the IOManager.pm object if it is not set.

   See also   : `file' in this node(),
*Bio::Root::IOManager::compress_file()*

uncompress_file
---------------

     Usage     : $object->uncompress_file([filename])
               : Delegates to Bio::Root::IOManager.pm.
     Purpose   : Uncompress a file associated with the current object.
     Throws    : Propagates exceptions thrown by Bio::Root::IOManager.pm
     Status    : Experimental
     Comments  : Sets the IOManager.pm object if it is not set.

   See also   : `file' in this node(),
*Bio::Root::IOManager::uncompress_file()*

delete_file
-----------

     Usage     : $object->delete_file([filename])
               : See Bio::Root::IOManager::delete_file() for details.
     Purpose   : Delete a file associated with the current object.
               : Delegates to Bio::Root::IOManager.pm.
     Throws    : Propagates exceptions thrown by Bio::Root::IOManager.pm
     Status    : Experimental
     Comments  : Sets the IOManager.pm object if it is not set.

   See also   : `file' in this node(),
*Bio::Root::IOManager.pm*::delete_file

file_date
---------

     Usage     : $object->file_date( %named_parameters )
               : See Bio::Root::IOManager::file_date() for details.
     Purpose   : Obtain the last modified data of a file.
               : Delegates to Bio::Root::IOManager.pm.
     Example   : $object->file_date('/usr/home/me/data.txt');
     Throws    : Propagates exceptions thrown by Bio::Root::IOManager.pm
     Status    : Experimental
     Comments  : Sets the IOManager.pm object if it is not set.

   See also   : `file' in this node(), *Bio::Root::IOManager::file_date()*

EXPERIMENTAL METHODS
====================

xref
----

     Usage     : $object->xref([object | 'null']);
     Purpose   : Sets/Gets an object(s) cross-referenced
               : to the current object.
     Example   : $myObj->xref('null');       #remove all xrefs
               : $myObj->xref($otherObject); #add a cross referenced object
     Argument  : Object reference or 'null' ('undef' also accepted).
     Returns   : Object reference or undef if the object has no xref set.
     Throws    : fatal error if argument is not an object reference or 'null'.
     Comments  : An Xref.pm object is a vectorized wrapper for an object.
               : Thus, the number of objects cross-referenced can grow
               : and shrink at will.
     Status    : Experimental
     WARNING   : NOT FULLY TESTED.

   See Also   : *Bio::Root::Xref.pm*

index
-----

     Purpose   : To add an object to a package global hash of objects
               : for tracking or rapid retrieval.
     Usage     : $self->index();
     Status    : Experimental
     Comments  : The object's name is used to index it into a hash. Objects in
               : different classes (packages) will be indexed in different hashes.
               : An object's name should thus be unique within its class.
               : To find an object, use find_object().
               : Uses the package global %Objects_created.

   See also   : `find_object' in this node()

find_object
-----------

     Purpose   : To obtain any object reference based on its unique name
               : within its class.
     Usage     : $myObj = &find_object('fred');
               : No need to specify the class (package) name of the object.
     Comments  : To use this method, the object must be previously
               : indexed by Bio::Root::Object.pm. This can be accomplished
               : by including 'index' in the -MAKE parameter during object
               : construction OR by calling the index() method on the
               : the object at any point after construction.
               : This is not an instance method.
     Status    : Experimental

   See  also  : `index' in this node()

has_warning
-----------

     Purpose   : Test whether or not an object has a non-fatal error (warning).
     Usage     : $self->has_warning;
     Comments  : This method is not usually needed. Checking err() is
               : sufficient since throw()ing an exception is a fatal event
               : and must be handled when it occurs.
     Status    : Experimental

   See also   : `err' in this node(), `warn' in this node(), `throw' in
this node()

print_err
---------

     Usage     : print_err([-WHERE=>FileHandle_object [,-SHOW=>msg|note|tech|stack] or any combo])
     Purpose   : Reports error data for any errors an object may have
               : as a string. This will only print warnings since exceptions
               : are fatal (unless a strictness of -2 is used).
     Example   : $myObj->print_err;
               : $myObj->print_err(-WHERE=>$myObj->fh('err'), -SHOW=>'msgtechstack');
     Argument  : SHOW parameter  : specify a sub-set of the err data.
               : WHERE parameter : specify a filehandle for printing.
     Returns   : n/a
     Status    : Experimental

   See also   : `err_string' in this node(), see Strict,()

err_string
----------

     Usage     : err_string([-SHOW =>msg|note|tech|stack])
               : err_string([-SHOW =>'msgnote'] or other combos)
     Purpose   : Reports all warnings generated by the object as a string.
     Example   : $errData = $myObj->err_string;
               : print MYHANDLE $myObj->err_string();
     Argument  : SHOW parameter : return a specific sub-set of the err data.
     Returns   : A string containing the error data of the object.
     Comments  : This method is provided as a safer and slightly easier to type
               : alternative to $self->err->string.
     Status    : Experimental

   See also   : `print_err' in this node(), *Bio::Root::Err.pm*::string

HIGHLY EXPERIMENTAL/DEPRECATED METHODS
======================================

terse
-----

     Usage     : $object->terse([0|1]);
     Purpose   : Set/Get an indicator to report less than the normal amount.
     Argument  : Boolean (0|1)
     Returns   : Boolean (0|1)
     Comments  : This method is for reducing the amount of reporting
               : an object will do.
               : terse can be set during object construction with the
               : -TERSE => 1 flag.
               : Not putting this method in IOManager.pm since that class
               : is concerned with "where" to report, not "what" or "how much".
     Status    : Deprecated
               : Use verbose() with a negative value instead.

   See also   : `verbose' in this node()

set_read
--------

     Usage     : see Bio::Root::IOManager::set_read()
     Purpose   : Sets an input stream for importing data associated with an object.
               : Delegates to Bio::Root::IOManager::set_read().
     Status    : Experimental
     WARNING!  : This method has not been tested.

   See also   : *Bio::Root::IOManager.pm*::set_read

set_log_err
-----------

     Usage     : see Bio::Root::IOManager::set_log_err()
     Purpose   : Sets the output stream for logging information about
               : an object's errors.
               : Delegates to Bio::Root::IOManager::set_log_err().
     Status    : Experimental
     WARNING!  : This method has not been tested.

   See also   : *Bio::Root::IOManager.pm*::set_log_err

FOR DEVELOPERS ONLY
===================

Data Members
------------

   Information about the various data members of this module is provided
for those wishing to modify or understand the code. Two things to bear in
mind:

  1. Do NOT rely on these in any code outside of this module.  All data
     members are prefixed with an underscore to signify that they are
     private.  Always use accessor methods. If the accessor doesn't exist
     or is inadequate, create or modify an accessor (and let me know,
     too!).

  2. This documentation may be incomplete and out of date.  It is easy for
     this documentation to become obsolete as this module is still
     evolving.  Always double check this info and search for members not
     described here.

        An instance of Bio::Root::Object.pm is a blessed reference to a
hash containing all or some of the following fields:

     FIELD          VALUE
     ------------------------------------------------------------------------
      _name         Common name for an object useful for indexing.
     	        Should be unique within its class.

     _parent       The object which created and is responsible for this object.
                   When a parent is destroyed, it takes all of its children with it.

     _err          Bio::Root::Err.pm object reference. Undefined if the object has no error
                   or if the _record_err member is false (which is the default).
      	        If object has multiple errors, err becomes a linked
      	        list of Err objects and the err member always points to latest err.
      	        In theory, an object should care only about whether or not it HAS
      	        an Err not how many it has. I've tried to make the management of
      	        multiple errors as opaque as possible to Bio::Root::Object.

     _errState      One of @Bio::Root::Err::ERR_TYPES. Allows an object to quickly determine the
     	        the type of error it has (if any) without having to examine
     	        potentially multiple Err object(s).

     _xref         Bio::Root::Xref object (Vector) for tracking other object(s) related to the
      	        present object not by inheritance or composition but by some arbitrary
      	        criteria. This is a new, experimental feature and is not fully implemented.

     _make         Used as a switch for custom object initialization. Provides a
      	        mechanism for alternate constructors. This is somewhat experimental.
      	        It may be useful for contruction of complex objects and may be of
      	        use for determining how an object was constructed post facto.

     _io           Bio::Root::IOManager.pm object reference. Used primarily for handling the
     	        display of an object's data.

     _strict       Integer flag to set the sensitivity to exceptions/warnings
      	        for a given object.

     _verbose      Boolean indicator for reporting more or less than the normal amount.

     _record_err   Boolean indicator for attaching all thrown exception objects
                   to the current object. Default = false (don't attach exceptions).

Abstract interface to root object code
**************************************

NAME
====

   Bio::Root::RootI - Abstract interface to root object code

SYNOPSIS
========

     # any bioperl or bioperl compliant object is a RootI
     # compliant object

     $obj->throw("This is an exception");

     eval {
         $obj->throw("This is catching an exception");
     };

     if( $@ ) {
         print "Caught exception";
     } else {
         print "no exception";
     }

DESCRIPTION
===========

   This is just a set of methods which do not assumme anything about the
object they are on. The methods provide the ability to throw exceptions
with nice stack traces.

   This is what should be inherieted by all bioperl compliant interfaces,
even if they are exotic XS/CORBA/Other perl systems.

CONTACT
=======

   Functions originally from Steve Chervitz. Refactored by Ewan Birney.

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
---

     Purpose   : generic intantiation function can be overridden if
                 special needs of a module cannot be done in _initialize

     =cut

   sub new {     local($^W) = 0;     my ($caller, @args) = @_;

   my $class = ref($caller) || $caller; #copied from Conway, OOPerl     my
$self = bless({}, $class);

     my %param = @args;
     my($verbose) =  ( $param{'-VERBOSE'} || $param{'-verbose'} );

     ## See "Comments" above regarding use of _rearrange().
     $self->verbose($verbose);

     return $self;
     }

   # for backwards compatibility sub _initialize {     my($self,@args) =
@_;     return 1; }

throw
-----

     Title   : throw
     Usage   : $obj->throw("throwing exception message")
     Function: Throws an exception, which, if not caught with an eval brace
               will provide a nice stack trace to STDERR with the message
     Returns : nothing
     Args    : A string giving a descriptive error message

warn
----

     Title   : warn
     Usage   : $object->warn("Warning message");
     Function: Places a warning. What happens now is down to the
               verbosity of the object  (value of $obj->verbose)
                verbosity 0 or not set => small warning
                verbosity -1 => no warning
                verbosity 1 => warning with stack trace
                verbosity 2 => converts warnings into throw
     Example :
     Returns :
     Args    :

     =cut

   sub warn{     my ($self,$string) = @_;

     my $verbose = $self->verbose;

     if( $verbose == 2 ) {
     	$self->throw($string);
     } elsif( $verbose == -1 ) {
     	return;
     } elsif( $verbose == 1 ) {
     	my $out = "-------------------- WARNING ---------------------\n".
     		"MSG: ".$string."\n";
     	$out .= $self->stack_trace_dump;

     	print STDERR $out;
     	return;
     }

     my $out = "-------------------- WARNING ---------------------\n".
        "MSG: ".$string."\n".
     	   "---------------------------------------------------\n";
     print STDERR $out;
     }

     =head2 verbose

     Title   : verbose
     Usage   : $self->verbose(1)
     Function: Sets verbose level for how ->warn behaves
               -1 = no warning
                0 = standard, small warning
                1 = warning with stack trace
                2 = warning becomes throw
     Returns : nothing
     Args    : -1,0,1 or 2

stack_trace_dump
----------------

     Title   : stack_trace_dump
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

stack_trace
-----------

     Title   : stack_trace
     Usage   : @stack_array_ref= $self->stack_trace
     Function: gives an array to a reference of arrays with stack trace info
               each coming from the caller(stack_number) call
     Returns : array containing a reference of arrays
     Args    : none

_rearrange
----------

     Usage     : $object->_rearrange( array_ref, list_of_arguments)
     Purpose   : Rearranges named parameters to requested order.
     Example   : $self->_rearrange([qw(SEQUENCE ID DESC)],@param);
               : Where @param = (-sequence => $s,
     	   :                 -id       => $i,
     	   :	             -desc     => $d);
     Returns   : @params - an array of parameters in the requested order.
               : The above example would return ($s, $i, $d)
     Argument  : $order : a reference to an array which describes the desired
               :          order of the named parameters.
               : @param : an array of parameters, either as a list (in
               :          which case the function simply returns the list),
               :          or as an associative array with hyphenated tags
               :          (in which case the function sorts the values
               :          according to @{$order} and returns that new array.)
     	   :	      The tags can be upper, lower, or mixed case
               :          but they must start with a hyphen (at least the
               :          first one should be hyphenated.)
     Source    : This function was taken from CGI.pm, written by Dr. Lincoln
               : Stein, and adapted for use in Bio::Seq by Richard Resnick and
               : then adapted for use in Bio::Root::Object.pm by Steve A. Chervitz.
     Comments  : (SAC)
               : This method may not be appropriate for method calls that are
               : within in an inner loop if efficiency is a concern.
               :
               : Parameters can be specified using any of these formats:
               :  @param = (-name=>'me', -color=>'blue');
               :  @param = (-NAME=>'me', -COLOR=>'blue');
               :  @param = (-Name=>'me', -Color=>'blue');
               :  @param = ('me', 'blue');
               : A leading hyphenated argument is used by this function to
               : indicate that named parameters are being used.
               : Therefore, the ('me', 'blue') list will be returned as-is.
               :
     	   : Note that Perl will confuse unquoted, hyphenated tags as
               : function calls if there is a function of the same name
               : in the current namespace:
               :    -name => 'foo' is interpreted as -&name => 'foo'
     	   :
               : For ultimate safety, put single quotes around the tag:
     	   :    ('-name'=>'me', '-color' =>'blue');
               : This can be a bit cumbersome and I find not as readable
               : as using all uppercase, which is also fairly safe:
     	   :    (-NAME=>'me', -COLOR =>'blue');
     	   :
               : Personal note (SAC): I have found all uppercase tags to
               : be more managable: it involves less single-quoting,
               : the code is more readable, and there are no method naming conlicts.
               : Regardless of the style, it greatly helps to line
     	   : the parameters up vertically for long/complex lists.

   See Also   : `_initialize' in this node()

_register_for_cleanup
---------------------

     Title   : _register_for_cleanup
     Usage   : -- internal --
     Function: Register a method to be called at DESTROY time. This is useful
               and sometimes essential in the case of multiple inheritance for
               classes coming second in the sequence of inheritance.
     Returns :
     Args    : a reference to a method

General-purpose utility module
******************************

NAME
====

   Bio::Root::Utilities - General-purpose utility module

SYNOPSIS
========

Object Creation
---------------

     use Bio::Root::Utilities qw(:obj);

   There is no need to create a new Bio::Root::Utilities.pm object when
the `:obj' tag is used. This tag will import the static $Util object
created by Bio::Root::Utilities.pm into your name space. This saves you
from having to call `new Bio::Root::Utilities'.

   You are free to not use the :obj tag and create the object as you like,
but a Bio::Root::Utilities object is not configurable; any given script
only needs a single copy.

     $date_stamp = $Util->date_format('yyy-mm-dd');

     $clean = $Util->untaint($dirty);

     $Util->mail_authority("Something you should know about...");

     ...and other methods. See below.

INSTALLATION
============

   This module is included with the central Bioperl distribution:

     http://bio.perl.org/Core/Latest
     ftp://bio.perl.org/pub/DIST

   Follow the installation instructions included in the README file.

DESCRIPTION
===========

   Provides general-purpose utilities of potential interest to any Perl
script.  Scripts and modules are expected to use the static $Util object
exported by this package with the `:obj' tag.

DEPENDENCIES
============

   *Bio::Root::Utilities.pm* inherits from *Bio::Root::Object.pm*.  It
also relies on the GNU gzip program for file compression/uncompression.

SEE ALSO
========

     Bio::Root::Object.pm       - Core object
     Bio::Root::Global.pm       - Manages global variables/constants

     http://bio.perl.org/Projects/modules.html  - Online module documentation
     http://bio.perl.org/                       - Bioperl Project Homepage

     FileHandle.pm (included in the Perl distribution or CPAN).

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules.  Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR
======

   Steve A. Chervitz, sac@genome.stanford.edu

   See the `FEEDBACK' in this node section for where to send bug reports
and comments.

VERSION
=======

   Bio::Root::Utilities.pm, 0.042

ACKNOWLEDGEMENTS
================

   This module was developed under the auspices of the Saccharomyces Genome
Database:     http://genome-www.stanford.edu/Saccharomyces

COPYRIGHT
=========

   Copyright (c) 1997-98 Steve A. Chervitz. All Rights Reserved.  This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

APPENDIX
========

   Methods beginning with a leading underscore are considered private and
are intended for internal use by this module. They are not considered part
of the public interface and are described here for documentation purposes
only.

date_format
-----------

     Title     : date_format
     Usage     : $Util->date_format( [FMT], [DATE])
     Purpose   : -- Get a string containing the formated date or time
               :    taken when this routine is invoked.
               : -- Provides a way to avoid using `date`.
     	   : -- Provides an interface to localtime().
               : -- Interconverts some date formats.
               :
               : (For additional functionality, use Date::Manip or
               :  Date::DateCalc available from CPAN).
     Example   : $Util->date_format();
               : $date = $Util->date_format('yyyy-mmm-dd', '11/22/92');
     Returns   : String (unless 'list' is provided as argument, see below)
               :
               :   'yyyy-mm-dd'  = 1996-05-03    # default format.
               :   'yyyy-dd-mm'  = 1996-03-05
               :   'yyyy-mmm-dd' = 1996-May-03
               :   'd-m-y'       = 3-May-1996
               :   'd m y'       = 3 May 1996
               :   'dmy'         = 3may96
               :   'mdy'         = May 3, 1996
               :   'ymd'         = 96may3
               :   'md'          = may3
               :   'year'        = 1996
               :   'hms'         = 23:01:59  # 'hms' can be tacked on to any of the above options
               :                             # to add the time stamp: eg 'dmyhms'
               :   'full' | 'unix' = UNIX-style date: Tue May  5 22:00:00 1998
               :   'list'          = the contents of localtime(time) in an array.
     Argument  : (all are optional)
               : FMT  = yyyy-mm-dd | yyyy-dd-mm | yyyy-mmm-dd |
               :        mdy | ymd | md | d-m-y | hms | hm
               :        ('hms' may be appended to any of these to
     	   :        add a time stamp)
               :
               : DATE = String containing date to be converted.
               :        Acceptable input formats:
               :           12/1/97 (for 1 December 1997)
               :           1997-12-01
               :           1997-Dec-01
     Throws    :
     Comments  : Relies on the $BASE_YEAR constant exported by Bio:Root::Global.pm.
               :
               : If you don't care about formatting or using backticks, you can
               : always use: $date = `date`;
               :
               : For more features, use Date::Manip.pm, (which I should
               : probably switch to...)

   See Also   : `file_date' in this node(), `month2num' in this node()

month2num
---------

     Title      : month2num
     Purpose    : Converts a string containing a name of a month to integer
                : representing the number of the month in the year.
     Example    : $Util->month2num("march");  # returns 3
     Argument   : The string argument must contain at least the first
                : three characters of the month's name. Case insensitive.
     Throws     : Exception if the conversion fails.

num2month
---------

     Title   : num2month
     Purpose : Does the opposite of month2num.
             : Converts a number into a string containing a name of a month.
     Example : $Util->num2month(3);  # returns 'Mar'
     Throws  : Exception if supplied number is out of range.

compress
--------

     Title     : compress
     Usage     : $Util->compress(filename, [tmp]);
     Purpose   : Compress a file to conserve disk space.
     Example   : $Util->compress("/usr/people/me/data.txt");
     Returns   : String (name of compressed file, full path).
     Argument  : filename = String (name of file to be compressed, full path).
               :            If the supplied filename ends with '.gz' or '.Z',
               :            that extension will be removed before attempting to compress.
               : tmp = boolean,
               :    If true, (or if user is not the owner of the file)
               :         the file is compressed to a tmp file
               :    If false, file is clobbered with the compressed version.
     Throws    : Exception if file cannot be compressed
               : If user is not owner of the file, generates a warning
               :   and compresses to a tmp file.
               :   To avoid this warning, use the -o file test operator
               :   and call this function with a true second argument.
     Comments  : Attempts to compress using gzip (default compression level).
               : If that fails, will attempt to use compress.
               : In some situations, the full path to the gzip executable
               : may be required. This can be specified with the $GNU_PATH
               : package global variable. When installed, $GNU_PATH is an
               : empty string.

   See Also   : `uncompress' in this node()

uncompress
----------

     Title     : uncompress
     Usage     : $Util->uncompress(filename, [tmp]);
     Purpose   : Uncompress a file to conserve disk space.
     Example   : $Util->uncompress("/usr/people/me/data.txt.gz");
     Returns   : String (name of uncompressed file, full path).
     Argument  : filename = String (name of file to be uncompressed, full path).
               :           If the supplied filename does not end with '.gz' or '.Z'
               :           a '.gz' will be appended before attempting to uncompress.
               : tmp = boolean,
               :    If true, (or if user is not the owner of the file)
               :         the file is uncompressed to a tmp file
               :    If false, file is clobbered with the uncompressed version.
     Throws    : Exception if file cannot be uncompressed
               : If user is not owner of the file, generates a warning
               :   and uncompresses to a tmp file.
               :   To avoid this warning, use the -o file test operator
               :   and call this function with a true second argument.
     Comments  : Attempts to uncompress using gunzip.
               : If that fails, will use uncompress.
               : In some situations, the full path to the gzip executable
               : may be required. This can be specified with the $GNU_PATH
               : package global variable. When installed, $GNU_PATH is an
               : empty string.

   See Also   : `compress' in this node()

file_date
---------

     Title    : file_date
     Usage    : $Util->file_date( filename [,date_format])
     Purpose  : Obtains the date of a given file.
              : Provides flexible formatting via date_format().
     Returns  : String = date of the file as: yyyy-mm-dd (e.g., 1997-10-15)
     Argument : filename = string, full path name for file
              : date_format = string, desired format for date (see date_format()).
              :               Default = yyyy-mm-dd
     Thows    : Exception if no file is provided or does not exist.
     Comments : Uses the mtime field as obtained by stat().

untaint
-------

     Title   : untaint
     Purpose : To remove nasty shell characters from untrusted data
             : and allow a script to run with the -T switch.
             : Potentially dangerous shell meta characters:  &;`'\"|*?!~<>^()[]{}$\n\r
             : Accept only the first block of contiguous characters:
             :  Default allowed chars = "-\w.', ()"
             :  If $relax is true  = "-\w.', ()\/=%:^<>*"
     Usage   : $Util->untaint($value, $relax)
     Returns : String containing the untained data.
     Argument: $value = string
             : $relax = boolean
     Comments:
         This general untaint() function may not be appropriate for every situation.
         To allow only a more restricted subset of special characters
         (for example, untainting a regular expression), then using a custom
         untainting mechanism would permit more control.

     Note that special trusted vars (like $0) require untainting.

mean_stdev
----------

     Title    : mean_stdev
     Usage    : ($mean, $stdev) = $Util->mean_stdev( @data )
     Purpose  : Calculates the mean and standard deviation given a list of numbers.
     Returns  : 2-element list (mean, stdev)
     Argument : list of numbers (ints or floats)
     Thows    : n/a

count_files
-----------

     Title    : count_files
     Purpose  : Counts the number of files/directories within a given directory.
              : Also reports the number of text and binary files in the dir
              : as well as names of these files and directories.
     Usage    : count_files(\%data)
              :   $data{-DIR} is the directory to be analyzed. Default is ./
              :   $data{-PRINT} = 0|1; if 1, prints results to STDOUT, (default=0).
     Argument : Hash reference (empty)
     Returns  : n/a;
              : Modifies the hash ref passed in as the sole argument.
              :  $$href{-TOTAL}            scalar
              :  $$href{-NUM_TEXT_FILES}   scalar
              :  $$href{-NUM_BINARY_FILES} scalar
              :  $$href{-NUM_DIRS}         scalar
              :  $$href{-T_FILE_NAMES}     array ref
              :  $$href{-B_FILE_NAMES}     array ref
              :  $$href{-DIRNAMES}         array ref

create_filehandle
-----------------

     Usage     : $object->create_filehandle(<named parameters>);
     Purpose   : Create a FileHandle object from a file or STDIN.
               : Mainly used as a helper method by read() and get_newline().
     Example   : $data = $object->create_filehandle(-FILE =>'usr/people/me/data.txt')
     Argument  : Named parameters (case-insensitive):
               :  (all optional)
               :    -CLIENT  => object reference for the object submitting
               :                the request. This facilitates use by
               :                Bio::Root::IOManager::read(). Default = $Util.
               :    -FILE    => string (full path to file) or a reference
               :                to a FileHandle object or typeglob. This is an
               :                optional parameter (if not defined, STDIN is used).
     Returns   : Reference to a FileHandle object.
     Throws    : Exception if cannot open a supplied file or if supplied with a
               : reference that is not a FileHandle ref.
     Comments  : If given a FileHandle reference, this method simply returns it.
               : This method assumes the user wants to read ascii data. So, if
               : the file is binary, it will be treated as a compressed (gzipped)
               : file and access it using gzip -ce. The problem here is that not
               : all binary files are necessarily compressed. Therefore,
               : this method should probably have a -mode parameter to
               : specify ascii or binary.

   See Also :  `get_newline' in this node(), `Bio::Root::IOManager::read'
in this node(),

get_newline
-----------

     Usage     : $object->get_newline(<named parameters>);
     Purpose   : Determine the character(s) used for newlines in a given file or
               : input stream. Delegates to Bio::Root::Utilities::get_newline()
     Example   : $data = $object->get_newline(-CLIENT => $anObj,
               :                                   -FILE =>'usr/people/me/data.txt')
     Argument  : Same arguemnts as for create_filehandle().
     Returns   : Reference to a FileHandle object.
     Throws    : Propogates and exceptions thrown by Bio::Root::Utilities::get_newline().

   See Also : `taste_file' in this node(), `create_filehandle' in this
node()

taste_file
----------

     Usage     : $object->taste_file( <FileHandle> );
               : Mainly a utility method for get_newline().
     Purpose   : Sample a filehandle to determine the character(s) used for a newline.
     Example   : $char = $Util->taste_file($FH)
     Argument  : Reference to a FileHandle object.
     Returns   : String containing an octal represenation of the newline character string.
               :   Unix = "\012"  ("\n")
               :   Win32 = "\012\015" ("\r\n")
               :   Mac = "\015"  ("\r")
     Throws    : Exception if no input is read within $TIMEOUT_SECS seconds.
               : Exception if argument is not FileHandle object reference.
               : Warning if cannot determine neewline char(s).
     Comments  : Based on code submitted by Vicki Brown (vlb@deltagen.com).

   See Also : `get_newline' in this node()

mail_authority
--------------

     Title    : mail_authority
     Usage    : $Util->mail_authority( $message )
     Purpose  : Syntactic sugar to send email to $Bio::Root::Global::AUTHORITY

   See Also  : `send_mail' in this node()

send_mail
---------

     Title    : send_mail
     Usage    : $Util->send_mail( named_parameters )
     Purpose  : Provides an interface to /usr/lib/sendmail
     Returns  : n/a
     Argument : Named parameters:  (case-insensitive)
              :  -TO   => e-mail address to send to
              :  -SUBJ => subject for message  (optional)
              :  -MSG  => message to be sent   (optional)
              :  -CC   => cc: e-mail address   (optional)
     Thows    : Exception if TO: address appears bad or is missing
     Comments : Based on  TomC's tip at:
              :   http://www.perl.com/CPAN-local/doc/FMTEYEWTK/safe_shellings
              :
              : Using default 'From:' information.
              :   sendmail options used:
              :      -t: ignore the address given on the command line and
              :          get To:address from the e-mail header.
              :     -oi: prevents send_mail from ending the message if it
              :          finds a period at the start of a line.

   See Also  : `mail_authority' in this node()

yes_reply
---------

     Title   : yes_reply()
     Usage   : $Util->yes_reply( [query_string]);
     Purpose : To test an STDIN input value for affirmation.
     Example : print +( $Util->yes_reply('Are you ok') ? "great!\n" : "sorry.\n" );
             : $Util->yes_reply('Continue') || die;
     Returns : Boolean, true (1) if input string begins with 'y' or 'Y'
     Argument: query_string = string to be used to prompt user (optional)
             : If not provided, 'Yes or no' will be used.
             : Question mark is automatically appended.

request_data
------------

     Title   : request_data()
     Usage   : $Util->request_data( [value_name]);
     Purpose : To request data from a user to be entered via keyboard (STDIN).
     Example : $name = $Util->request_data('Name');
             : # User will see: % Enter Name:
     Returns : String, (data entered from keyboard, sans terminal newline.)
     Argument: value_name = string to be used to prompt user.
             : If not provided, 'data' will be used, (not very helpful).
             : Question mark is automatically appended.

verify_version
--------------

     Purpose : Checks the version of Perl used to invoke the script.
             : Aborts program if version is less than the given argument.
     Usage   : verify_version('5.000')

Interface for managing linked lists of Perl5 objects.
*****************************************************

NAME
====

   Bio::Root::Vector - Interface for managing linked lists of Perl5
objects.

SYNOPSIS
========

Object Creation
---------------

   *At present, Vector objects cannot be instantiated.* This package is
currently designed to be inherited along with another class that provides
a constructor (e.g., *Bio::Root::Object.pm*).  The Vector provides a set
of methods that can then be used for managing sets of objects.

   See `USAGE' in this node.

INSTALLATION
============

   This module is included with the central Bioperl distribution:

     http://bio.perl.org/Core/Latest
     ftp://bio.perl.org/pub/DIST

   Follow the installation instructions included in the README file.

DESCRIPTION
===========

   Bio::Root::Vector.pm  provides an interface for creating and
manipulating dynamic sets (linked lists) of Perl5 objects. This is an
abstract class (ie., there is no constructor) and as such is expected to
be inherited along with some other class (see note above).

   Vectors are handy when, for example, an object may contain one or more
other objects of a certain class. The container object knows only that is
has at least one such object; the multiplex nature of the contained object
is managed by the contained object via its Vector interface.  The methods
for adding, removing, counting, listing, and sorting all objects are
bundled together in Vector.pm.

   Thus, the current Bio::Root::Vector class is somewhat of a cross
between an interator and a composite design pattern. At present, a number
of classes utilize Bio::Root::Vector's composite-like behavior to
implement a composite pattern (Bio::SeqManager.pm, for example).  This is
not necessarily ideal and is expected to change.

USAGE
=====

   For a usage demo of Bio::Root::Vector.pm, see:

     http://bio.perl.org/Core/Examples/Root_object/Vector

DEPENDENCIES
============

   Bio::Root::Vector.pm does not directly inherit from
*Bio::Root::Object.pm* but creates an manager object which does.

BUGS/FEATURES
=============

   By default, all Vectors are doubly-linked lists. This relieves one from
the burden of worrying about whether a given Vector is single- or
doubly-linked.  However, when generating lots of Vectors or extremely
large vectors, memory becomes an issue. In particular, signaling the GC to
free the memory for an object when you want to remove it. *Until this
memory issue is resolved, the use of Vector.pm is not recommended for
large projects.*

   Although it is not required, all objects within a vector are expected
to derive from the same class (package). Support for heterogeneous Vectors
has not been explicitly added (but they should work fine, as long as you
know what you're doing).

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules.  Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR
======

   Steve A. Chervitz, sac@genome.stanford.edu

   See the `FEEDBACK' in this node section for where to send bug reports
and comments.

VERSION
=======

   Bio::Root::Vector.pm, 0.04

TODO
====

   * (Maybe) create an container class version of this module

     to permit Vectors to be instantiated. Thus, instead of inherited from
     both Object.pm and Vector.pm, you could create a Vector.pm object.

   * Improve documentation.

SEE ALSO
========

     Bio::Root::Object.pm    - Core object
     Bio::Root::Err.pm       - Error/Exception object
     Bio::Root::Global.pm    - Manages global variables/constants

     http://bio.perl.org/Projects/modules.html  - Online module documentation
     http://bio.perl.org/                       - Bioperl Project Homepage

ACKNOWLEDGEMENTS
================

   This module was developed under the auspices of the Saccharomyces Genome
Database:     http://genome-www.stanford.edu/Saccharomyces

COPYRIGHT
=========

   Copyright (c) 1996-98 Steve A. Chervitz. All Rights Reserved.  This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

APPENDIX
========

   Methods beginning with a leading underscore are considered private and
are intended for internal use by this module. They are not considered part
of the public interface and are described here for documentation purposes
only.

set_rank
--------

     Purpose  : To set an object's rank to an arbitrary numeric
              : value to be used for sorting the objects of the Vector.
     Usage    : $self->set_rank(-RANK    =>numeric_ranking_data,
     	  :     	    -RANK_BY =>ranking_criterion_string);
              : or without the named parameters as (rank, rank_by).
     Throws   : warning (if rank is set without also setting RANK_BY)
     Comments : It is redundant for every object to store RANK_BY data.
              : For this reason, the RANK_BY data is stored with the master
              : object associated with the vector.

   See Also  : `rank' in this node(), `rank_by' in this node()

clone_vector
------------

     Purpose  : Call this method to clone the whole vector.
              : NOT calling this method will extract the vector element.
     Usage    : $self->clone_vector();
     Throws   : Exception if argument is not an object reference.
     Comments : This method is usually called from within a module's
              : _set_clone() method for modules that inherit from
              : Bio::Root::Vector.pm.

prev
----

     Purpose  : Returns the previous object in the Vector or undef
              : if on first object.
     Usage    : $self->prev

next
----

     Purpose  : Returns the next object in the Vector or undef
              : if on last object.
     Usage    : $self->next

first
-----

     Purpose  : Returns the first object in the Vector or $self
              : if Vector size = 1.
     Usage    : $self->first

last
----

     Purpose  : Returns the last object in the Vector or
              : $self if Vector size = 1.
     Usage    : $self->last

rank
----

     Purpose  : Returns the rank of the current object or 1
              : if rank is not defined.
     Usage    : $self->rank

   See Also  : `set_rank' in this node()

rank_by
-------

     Purpose  : Returns the ranking criterion or the string 'order of addition'
              : if rankBy has not been explicitly set.
     Usage    : $self->rank_by

   See Also  : `set_rank' in this node()

size
----

     Purpose  : Returns the number of objects currently in the Vector.
     Usage    : $self->size

master
------

     Purpose  : Returns the master object associated with the Vector.
              : (should probably be a private method).
     Usage    : $self->master

is_first
--------

     Purpose  : Test whether the current object is the first in the Vector.
     Usage    : $self->is_first

is_last
-------

     Purpose  : Test whether the current object is the last in the Vector.
     Usage    : $self->is_last

get
---

     Purpose  : Retrives an object from the Vector given its name.
              : Returns undef if the object cannot be found.
     Usage    : $self->get(object_name)
     Examples : $self->get($obj->name)

   See Also  : `list' in this node()

add
---

     Purpose  : Add an object to the end of a Vector.
     Usage    : $self->add(object_reference)

   See also  : `insert' in this node(), `remove' in this node()

remove
------

     Purpose  : Remove the current object from the Vector.
     Usage    : $self->remove([-RET=>'first'|'last'|'next'|'prev'], [-UPDATE => 0|1])
     Returns  : The first, last, next, or previous object in the Vector
              : depending on the value of the -RET parameter.
              : Default = next.
     Argument : Named parameters: (TAGS CAN BE ALL UPPER OR ALL LOWER CASE)
              :    -RET    => string: 'first', 'last', 'prev' 'next'
              :               THis indicates the object to be returned.
              :    -UPDATE => boolean, if non-zero all objects in the vector
              :               will be re-ranked.
     Comments : The -UPDATE parameter should be set to true to force a re-updating
              : of the rank data for each object. (default = 0, no update).

   See Also  : `add' in this node(), `insert' in this node(), `shift' in
this node(), `chop' in this node()

remove_all
----------

     Purpose  : Remove all objects currently in the Vector.
     Usage    : $self->remove_all

   See Also  : `remove' in this node(), `shift' in this node(), `chop' in
this node()

shift
-----

     Purpose  : Remove the first object from the Vector.
              : This is a wrapper for remove().
     Usage    : $self->shift([-RET=>'first'|'last'|'next'|'prev'])
     Returns  : The object returned by remove().

   See Also  : `remove' in this node(), `chop' in this node()

chop
----

     Purpose  : Remove the last object from the Vector.
              : This is a wrapper for remove().
     Usage    : $self->chop([-RET=>'first'|'last'|'next'|'prev'])
     Returns  : The object returned by remove().

   See Also  : `remove' in this node(), `shift' in this node()

insert
------

     Purpose  : Insert a new object into the vector relative to the current object.
     Usage    : $self->insert(object_ref, ['before'|'after'])
     Examples : $self->insert($obj)  # Default insert after $self
              : $self->insert($obj,'before')
     Returns  : The new number of objects in the vector (int).
     Throws   : exception if the first argument is not a reference.

   See Also  : `add' in this node(), `remove' in this node()

list
----

     Purpose  : Returns objects in the Vector as an array or array slice.
     Usage    : $self->list([starting_object|'first'] [,ending_object|'last'])
     Examples : $self->list
              : $self->list('first',$self->prev)

   See Also  : `get' in this node()

sort
----

     Purpose  : Sort the objects in the Vector.
     Usage    : $self->sort(['rank'|'name'], [reverse])
     Returns  : The last object of the sorted Vector.
     Argument : First argument can be 'name' or 'rank' to sort on
              : the object's name or rank data member, respectively.
              : If reverse is non-zero, sort will be in reverse order.
     Example  : $self->sort()   #  Default sort by rank, not reverse.
              : $self->sort('name','reverse')

valid_any
---------

     Purpose  : Determine if at least one object in the Vector is valid.
     Usage    : $self->valid_any
     Status   : Deprecated.
     Comments : A non-valid object should throw an exception that must be
              : be caught an dealt with on the spot.

   See Also  : *Bio::Root::Object::valid()*

valid_all
---------

     Purpose  : Determine if all objects in the Vector are valid.
     Usage    : $self->valid_all
     Comments : A non-valid object should throw an exception that must be
              : be caught an dealt with on the spot.

   See Also  : *Bio::Root::Object::valid()*

FOR DEVELOPERS ONLY
===================

Data Members
------------

   Information about the various data members of this module is provided
for those wishing to modify or understand the code. Two things to bear in
mind:

  1. Do NOT rely on these in any code outside of this module.  All data
     members are prefixed with an underscore to signify that they are
     private.  Always use accessor methods. If the accessor doesn't exist
     or is inadequate, create or modify an accessor (and let me know,
     too!).

  2. This documentation may be incomplete and out of date.  It is easy for
     this documentation to become obsolete as this module is still
     evolving.  Always double check this info and search for members not
     described here.

        Bio::Root::Vector.pm objects currently cannot be instantiated.
Vector.pm must be inherited along with Bio::Root::Object.pm (or an object
that provides a constructor).  Vector.pm defines the following fields:

     FIELD          VALUE
     ------------------------------------------------------------------------
      _prev         Reference to the previous object in the Vector.

     _next         Reference to the next object in the Vector.

     _rank         Rank relative to other objects in the Vector.
     	        Default rank = chronological order of addition to the Vector.

     _master       A reference to an Bio::Root::Object that acts as a manager for
      	        the given Vector. There is only one master per Vector.
      	        A master object is only needed when the Vector size is >1.
      	        The master object manages the following Vector data:

     _first  - Reference to the first object in the Vector.
     _last   - Reference to the last object in the Vector.
     _size   - Total number of objects in the Vector.
     _rankBy - Criteria used to rank the object.
              Default: chronological order of addition.
     _index  - Hash reference for quick access to any object
              based on its name.
     Bio::Root::Object{'_err'} - Holds any errors affecting the
                          Vector as a whole.

A generic cross-reference object.
*********************************

NAME
====

   Bio::Root::Xref - A generic cross-reference object.

   *WARNING: This module is still in the experimental phase and has not
been tested.*

SYNOPSIS
========

Object Creation
---------------

     use Bio::Root::Object;

     $myObj->xref($object_ref);

     =head2 Object Manipulation

     Accessors
     ---------------------------------------------------------------------
     obj()         - Get the cross-referenced object.
     desc()        - Description of the nature of the cross-reference.
     set_desc()    - Set description.
     type()        - Symmetric or assymetric.

     Methods
     ---------------------------------------------------------------------
     clear()       - remove all cross-references within the Xref object (not implemented).

DESCRIPTION
===========

   An instance of *Bio::Root::Xref.pm* manages sets of objects not
necessarily related by inheritance or composition, but by an arbitrary
criterion defined by the client. Currently, Bio::Root::Xref inherits from
both *Bio::Root::Object.pm* and *Bio::Root::Vector.pm*. An Xref object is
an example of a heterogeneous Vector object since different objects in the
vector need not all derive from the same base class.

   The two objects involved in the cross-reference typically involve a
symmetrical relationship in which each will have a Xref object relating it
to the other object. This relationship is not necessarily transitive,
however: if A is an xref of B and B is an xref of C, A is not necessarily
an xref of C. Assymetric Xrefs are also possible.

   The establishment of cross-references is managed by
*Bio::Root::Object.pm*.  See the xref() method in that module.

   *The API for this module is not complete since the module is under
development. Caveat emptor.*

SEE ALSO
========

     Bio::Root::Object.pm       - Core object
     Bio::Root::Global.pm       - Manages global variables/constants

     http://bio.perl.org/Projects/modules.html  - Online module documentation
     http://bio.perl.org/                       - Bioperl Project Homepage

     =head1 FEEDBACK

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules.  Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR
======

   Steve A. Chervitz, sac@genome.stanford.edu

   See the `FEEDBACK' in this node section for where to send bug reports
and comments.

VERSION
=======

   Bio::Root::Xref.pm, 0.01 pre-alpha

COPYRIGHT
=========

   Copyright (c) 1997-8 Steve A. Chervitz. All Rights Reserved.  This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

TODO
====

   Update documentation to work with pod2html from Perl 5.004.

DATA MEMBERS
============

     _obj   : The object being cross-referenced to the parent.
     _type  : Symmetric or asymmetric
     _desc  : Description associated with the cross-reference

     INHERITED DATA MEMBERS (from Bio::Root::Object)

     _parent : The object receiving the cross-reference.
     _name   : Descriptive nature of the cross-reference.

Hit object specific for Fasta-generated hits
********************************************

NAME
====

   Bio::Search::Hit::Fasta - Hit object specific for Fasta-generated hits

SYNOPSIS
========

     These objects are generated automatically by Bio::Search::Processor::Fasta,
     and shouldn't be used directly.

DESCRIPTION
===========

     Bio::Search::Hit::* objects are data structures that contain information
     about specific hits obtained during a library search.  Some information will
     be algorithm-specific, but others will be generally defined, such as the
     ability to obtain alignment objects corresponding to each hit.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     bioperl-guts-l@bioperl.org        - Automated bug and CVS messages
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Aaron Mackey
=====================

   Email amackey@virginia.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

Abstract interface for Hit objects
**********************************

NAME
====

   Bio::Search::Hit::HitI - Abstract interface for Hit objects

SYNOPSIS
========

   This is a abstract class meant to define an interface, and nothing more.

DESCRIPTION
===========

     Bio::Search::Hit::* objects are data structures that contain information
     about specific hits obtained during a library search.  Some information will
     be algorithm-specific, but others will be generally defined.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     bioperl-guts-l@bioperl.org        - Automated bug and CVS messages
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Aaron Mackey
=====================

   Email amackey@virginia.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

get_hit_id
----------

     Title   : get_hit_id
     Usage   : $id = $hit->get_hit_id();
     Function: Used to obtain the id of the matched entity.
     Returns : a scalar string
     Args    : <none>

get_hit_desc
------------

     Title   : get_hit_desc
     Usage   : $desc = $hit->get_hit_desc();
     Function: Used to obtain the description of a matched entity
     Returns : a scalar string
     Args    : <none>

get_algorithm
-------------

     Title   : get_algorithm
     Usage   : $which = $hit->get_algorithm();
     Function: Used to obtain the algorithm specification used to obtain the hit
     Returns : a scalar string
     Args    : <none>

get_raw_score
-------------

     Title   : get_raw_score
     Usage   : $score = $hit->get_raw_score();
     Function: Used to obtain the "raw score" generated by the algorithm.  What
               this score is exactly will vary from algorithm to algorithm,
               returning undef if unavailable.
     Returns : a scalar value
     Args    : <none>

get_expectation_value
---------------------

     Title   : get_expectation_value
     Usage   : $evalue = $hit->get_expectation_value();
     Function: Used to obtain the E() value of a hit, i.e. the probability that
               this particular hit was obtained purely by random chance.  If
               information is not available (nor calculatable from other
               information sources), return undef.
     Returns : a scalar value or undef if unavailable
     Args    : <none>

get_evalue
----------

     Title   : get_evalue
     Usage   : $evalue = $hit->get_evalue();
     Function: same as get_expectation_value (just an alias)
     Returns : see above
     Args    : <none>

get_alignments
--------------

     Title   : get_alignments
     Usage   : @aligns = $hit->get_alignments()
     Function: Used to obtain an array of Bio::Alignment objects corresponding to
               the Hit.
     Returns : an array of Alignment objects, if more than one Alignments exist and
               called in wantarray context.  In scalar context will return a
               reference to an array of Alignment objects, if more than one
               Alignment objects exist, otherwise will return the unique
               Alignment object.  If no Alignment objects exist, returns undef
     Args    :

DESCRIPTION of Object
*********************

NAME
====

   Bio::Search::Processor - DESCRIPTION of Object

SYNOPSIS
========

   Give standard usage here

DESCRIPTION
===========

   Describe the object here

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     bioperl-guts-l@bioperl.org        - Automated bug and CVS messages
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Aaron Mackey
=====================

   Email amackey@virginia.edu

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
---

     Title   : new
     Usage   : $proc = new Bio::Search::Processor -file      => $filename,
                                                  -algorithm => 'Algorithm' ;
     Function: Used to specify and initialize a data processor of search
               algorithm results.
     Returns : A processor specific to the algorithm type, if it exists.
     Args    : -file => filename
               -algorithm => algorithm specifier
               -fh => filehandle to attach to (file or fh required)

Processor of Fasta-generated data streams
*****************************************

NAME
====

   Bio::Search::Processor::Fasta - Processor of Fasta-generated data
streams

SYNOPSIS
========

   use Bio::Search::Processor

   my $processor = new Bio::Search::Processor -file      => 'mysearchrun',
                                          -algorithm => 'Fasta';

DESCRIPTION
===========

   A Processor object is used to generate Bio::Search::Result::* objects,
given a source of Search data (a file or filehandle).  The Processor
object works very much like the SeqIO system: once initialized with the
new() method, the Processor object will continue to yield as many Result
objects as are available from the data source (for single "runs" this is
often only one Result object).

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     bioperl-guts-l@bioperl.org        - Automated bug and CVS messages
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Aaron Mackey
=====================

   Email amackey@virginia.edu

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_result
-----------

     Title   : next_result
     Usage   : $result = $processor->next_result()
     Function: Used to obtain Result objects from a FASTA-generated data source
     Returns : a Bio::Search::Result::Fasta object
     Args    : <none>

Abstract Interface for Processor Objects
****************************************

NAME
====

   Bio::Search::Processor::ProcessorI - Abstract Interface for Processor
Objects

SYNOPSIS
========

   use Bio::Search::Processor

   my $processor = new Bio::Search::Processor -file      => 'mysearchrun',
                                          -algorithm => 'Blast';

   while ($result = $processor->next_result()) {

     $id = $result->get_query_id();
     $lib = $result->get_library_name();
     $size = $result->get_library_size();

     foreach $hit ( $result->get_hits() ) {
         $matchid = $hit->get_id();
         $matchdesc = $hit->get_desc();
         # etc, etc, do stuff.
     }
     }

DESCRIPTION
===========

   A Processor object is used to generate Bio::Search::Result::* objects,
given a source of Search data (a file or filehandle).  The Processor
object works very much like the SeqIO system: once initialized with the
new() method, the Processor object will continue to yield as many Result
objects as are available from the data source (for single "runs" this is
often only one Result object).

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     bioperl-guts-l@bioperl.org        - Automated bug and CVS messages
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Aaron Mackey
=====================

   Email amackey@virginia.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_result
-----------

     Title   : next_result
     Usage   : $result = $processor->next_result()
     Function: Returns the next Bio::Search::Result::* object available from
               the provided data stream or undef if no more are available.
     Returns : Bio::Search::Result object
     Args    : <none>

Result object for FASTA-generated data sources
**********************************************

NAME
====

   Bio::Search::Result::Fasta - Result object for FASTA-generated data
sources

SYNOPSIS
========

     These objects are generated automatically by Bio::Search::Processor::Fasta,
     and shouldn't be used directly.

DESCRIPTION
===========

   Bio::Search::Result::* objects are data structures containing the
results from the execution of a search algorithm.  As such, it may contain
various algorithm specific information as well as details of the
execution, but will contain a few fundamental elements, including the
ability to return Bio::Search::Hit::* objects.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     bioperl-guts-l@bioperl.org        - Automated bug and CVS messages
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Aaron Mackey
=====================

   Email amackey@virginia.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

Abstract interface to Result objects
************************************

NAME
====

     Bio::Search::Result::ResultI.pm - Abstract interface to Result objects

SYNOPSIS
========

     These objects are generated automatically by Bio::Search::Processor
     objects, and wouldn't be used directly.

DESCRIPTION
===========

   Bio::Search::Result::* objects are data structures containing the
results from the execution of a search algorithm.  As such, it may contain
various algorithm specific information as well as details of the
execution, but will contain a few fundamental elements, including the
ability to return Bio::Search::Hit::* objects.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     bioperl-guts-l@bioperl.org        - Automated bug and CVS messages
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Aaron Mackey
=====================

   Email amackey@virginia.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

get_query_id
------------

     Title   : get_query_id
     Usage   : $id = $result->get_query_id();
     Function: Used to obtain the string identifier of the query used by the
               algorithm.
     Returns : a scalar string.
     Args    : <none>

get_library_name
----------------

     Title   : get_library_name
     Usage   : $name = $result->get_library_name()
     Function: Used to obtain the name of the library that the query was searched
               against by the algorithm.
     Returns : a scalar string
     Args    : <none>

get_library_size
----------------

     Title   : get_library_size
     Usage   : $size = $result->get_library_size()
     Function: Used to obtain the size of library that was searched against.
     Returns : a scalar integer (units specific to algorithm, but probably the
               total number of residues in the library, if available) or undef if
               the information was not available to the Processor object.
     Args    : <none>

get_library_count
-----------------

     Title   : get_library_count
     Usage   : $count = $result->get_library_count()
     Function: Used to obtain the number of entries contained in the library.
     Returns : a scalar integer representing the number of entities in the library
               or undef if the information was not available.
     Args    : <none>

get_hits
--------

     Title   : get_hits
     Usage   : @hits = $result->get_hits();
     Function: Used to obtain the array of hit objects, representing potential
               matches between the query and various entities from the library.
     Returns : an array of Bio::Search::Hit::* object (specific type depends on
               algorithm), or undef if there were none.
     Args    : <none>

A perl wrapper around Sean Eddy's histogram object
**************************************************

NAME
====

   Bio::SearchDist - A perl wrapper around Sean Eddy's histogram object

SYNOPSIS
========

     $dis = Bio::SearchDist->new();
     foreach $score ( @scores ) {
        $dis->add_score($score);
     }

     if( $dis->fit_evd() ) {
       foreach $score ( @scores ) {
         $evalue = $dis->evalue($score);
         print "Score $score had an evalue of $evalue\n";
       }
     } else {
       warn("Could not fit histogram to an EVD!");
     }

DESCRIPTION
===========

   The Bio::SearchDist object is a wrapper around Sean Eddy's excellent
histogram object. The histogram object can bascially take in a number of
scores which are sensibly distributed somewhere around 0 that come from a
supposed Extreme Value Distribution. Having add all the scores from a
database search via the add_score method you can then fit a extreme value
distribution using fit_evd(). Once fitted you can then get out the evalue
for each score (or a new score) using evalue($score).

   The fitting procedure is better described in Sean Eddy's own code
(available from http://hmmer.wustl.edu, or in the histogram.h header file
in Compile/SW). Bascially it fits a EVD via a maximum likelhood method
with pruning of the top end of the distribution so that real positives are
discarded in the fitting procedure. This comes from an orginally idea of
Richard Mott's and the likelhood fitting is from a book by Lawless [should
ref here].

   The object relies on the fact that the scores are sensibly distributed
around about 0 and that integer bins are sensible for the histogram.
Scores based on bits are often ideal for this (bits based scoring
mechanisms is what this histogram object was originally designed for).

CONTACT
=======

   The original code this was based on comes from the histogram module as
part of the HMMer2 package. Look at http://hmmer.wustl.edu/

   Its use in Bioperl is via the Compiled XS extension which is cared for
by Ewan Birney (birney@sanger.ac.uk). Please contact Ewan first about the
use of this module

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

add_score
---------

     Title   : add_score
     Usage   : $dis->add_score(300);
     Function: Adds a single score to the distribution
     Returns : nothing
     Args    :

fit_evd
-------

     Title   : fit_evd
     Usage   : $dis->fit_evd();
     Function: fits an evd to the current distribution
     Returns : 1 if it fits successfully, 0 if not
     Args    :

fit_Gaussian
------------

     Title   : fit_Gaussian
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

evalue
------

     Title   : evalue
     Usage   : $eval = $dis->evalue($score)
     Function: Returns the evalue of this score
     Returns : float
     Args    :

_engine
-------

     Title   : _engine
     Usage   : $obj->_engine($newval)
     Function: underlyine bp_sw:: histogram engine
     Returns : value of _engine
     Args    : newvalue (optional)

Sequence object, with features
******************************

NAME
====

   Bio::Seq - Sequence object, with features

SYNOPSIS
========

     $seqio  = Bio::SeqIO->new ( '-format' => 'embl' , -file => 'myfile.dat');
     $seqobj = $seqio->next_seq();

     # features must implement Bio::SeqFeatureI

     @features = $seqobj->top_SeqFeatures(); # just top level
     @features = $seqobj->all_SeqFeatures(); # descend into sub features

     $seq      = $seqobj->seq(); # actual sequence as a string
     $seqstr   = $seqobj->subseq(10,50);
     $ann      = $seqobj->annotation(); # annotation object

DESCRIPTION
===========

   A Seq object is a sequence with sequence features placed on them. The
Seq object contains a PrimarySeq object for the actual sequence and also
implements its interface.

   In bioperl we have 3 main players that people are going to use

     Bio::PrimarySeq - just the sequence and its names, nothing else.
     Bio::SeqFeatureI - a location on a sequence, potentially with a sequence.
                       and annotation
     Bio::Seq        - A sequence and a collection of seqfeatures (an aggregate) with
                       its own annotation.

   Although bioperl is not tied to file formats heavily, these
distinctions do map to file formats sensibly and for some
bioinformaticians this might help you:

     Bio::PrimarySeq - Fasta file of a sequence
     Bio::SeqFeatureI - A single entry in an EMBL/GenBank/DDBJ feature table
     Bio::Seq        - A single EMBL/GenBank/DDBJ entry

   By having this split we avoid alot of nasty ciricular references
(seqfeatures can hold a reference to a sequence without the sequence
holding a reference to the seqfeature).

   Ian Korf really helped in the design of the Seq and SeqFeature system.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                 - General discussion
     http://bio.perl.org/MailList.html  - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bioperl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney, inspired by Ian Korf objects
==================================================

   Email birney@sanger.ac.uk

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
---

     Title   : new
     Usage   : $seq    = Bio::Seq->new( -seq => 'ATGGGGGTGGTGGTACCCT',
                                        -id  => 'human_id',
     				    -accession_number => 'AL000012',
     				   );

     Function: Returns a new seq object from
               basic constructors, being a string for the sequence
               and strings for id and accession_number
     Returns : a new Bio::Seq object

PrimarySeq interface
====================

   The primaryseq interface is the basic sequence getting and setting
methods found on all sequences.

   These methods implement the PrimarySeq interface by delegating to the
primary_seq inside the object. This means that you can use a Seq object
wherever there is a PrimarySeq, and of course, you are free to use these
functions anyway.

seq
---

     Title   : seq
     Usage   : $string    = $obj->seq()
     Function: Returns the sequence as a string of letters. The
               case of the letters is left up to the implementer.
               Suggested cases are upper case for proteins and lower case for
               DNA sequence (IUPAC standard),
               but implementations are suggested to keep an open mind about
               case (some users... want mixed case!)
     Returns : A scalar

length
------

     Title   : length
     Usage   : $len = $seq->length()
     Function:
     Example :
     Returns : integer representing the length of the sequence.
     Args    :

subseq
------

     Title   : subseq
     Usage   : $substring = $obj->subseq(10,40);
     Function: returns the subseq from start to end, where the first base
               is 1 and the number is inclusive, ie 1-2 are the first two
               bases of the sequence

     Start cannot be larger than end but can be equal

     Returns : a string
     Args    :

display_id
----------

     Title   : display_id
     Usage   : $id_string = $obj->display_id($newid);
     Function: returns or sets the display id, aka the common name of the
               Sequence object.

     The semantics of this is that it is the most likely string
     to be used as an identifier of the sequence, and likely to
     have "human" readability.  The id is equivalent to the ID
     field of the GenBank/EMBL databanks and the id field of the
     Swissprot/sptrembl database. In fasta format, the >(\S+) is
     presumed to be the id, though some people overload the id
     to embed other information. Bioperl does not use any
     embedded information in the ID field, and people are
     encouraged to use other mechanisms (accession field for
     example, or extending the sequence object) to solve this.

     Notice that $seq->id() maps to this function, mainly for
     legacy/convience issues
      Returns : A string
      Args    : newid (optional)

accession_number
----------------

     Title   : accession_number
     Usage   : $unique_biological_key = $obj->accession_number;
     Function: Returns the unique biological id for a sequence, commonly
               called the accession_number. For sequences from established
               databases, the implementors should try to use the correct
               accession number. Notice that primary_id() provides the
               unique id for the implemetation, allowing multiple objects
               to have the same accession number in a particular implementation.

     For sequences with no accession number, this method should return
     "unknown".
      Returns : A string
      Args    : None

desc
----

     Title   : desc
     Usage   : $seqobj->desc()
     Function: Sets/Gets the description of the sequnce
     Example :
     Returns :
     Args    :

primary_id
----------

     Title   : primary_id
     Usage   : $unique_implementation_key = $obj->primary_id;
     Function: Returns the unique id for this object in this
               implementation. This allows implementations to manage
               their own object ids in a way the implementaiton can control
               clients can expect one id to map to one object.

     For sequences with no natural id, this method should return
     a stringified memory location.

     Also notice that this method is B<not> delegated to the
     internal PrimarySeq object
      Returns : A string
      Args    : None

can_call_new
------------

     Title   : can_call_new
     Usage   : if( $obj->can_call_new ) {
                 $newobj = $obj->new( %param );
     	   }
     Function: can_call_new returns 1 or 0 depending
               on whether an implementation allows new
               constructor to be called. If a new constructor
               is allowed, then it should take the followed hashed
               constructor list.

     $myobject->new( -seq => $sequence_as_string,
     			   -display_id  => $id
     			   -accession_number => $accession
     			   -moltype => 'dna',
     			   );
      Example :
      Returns : 1 or 0
      Args    :

moltype
-------

     Title   : moltype
     Usage   : if( $obj->moltype eq 'dna' ) { /Do Something/ }
     Function: Returns the type of sequence being one of
               'dna', 'rna' or 'protein'. This is case sensitive.

     This is not called <type> because this would cause
     upgrade problems from the 0.5 and earlier Seq objects.

     Returns : a string either 'dna','rna','protein'. NB - the object must
               make a call of the type - if there is no type specified it
               has to guess.
     Args    : none

Methods provided in the Bio::PrimarySeqI interface
==================================================

   These methods are inherited from the PrimarySeq interface and work as
one expects, building new Bio::Seq objects or other information as
expected.

   Sequence Features are not transfered to the new objects.  This is
possibly a mistake. Anyone who feels the urge in dealing with this is
welcome to give it a go.

revcom
------

     Title   : revcom
     Usage   : $rev = $seq->revcom()
     Function: Produces a new Bio::Seq object which
               is the reversed complement of the sequence. For protein
               sequences this throws an exception of "Sequence is a protein. Cannot revcom"

     The id is the same id as the orginal sequence, and the accession number
     is also indentical. If someone wants to track that this sequence has be
     reversed, it needs to define its own extensions

     To do an inplace edit of an object you can go:

     $seq = $seq->revcom();

     This of course, causes Perl to handle the garbage collection of the old
     object, but it is roughly speaking as efficient as an inplace edit.

     Returns : A new (fresh) Bio::Seq object
     Args    : none

trunc
-----

     Title   : trunc
     Usage   : $subseq = $myseq->trunc(10,100);
     Function: Provides a truncation of a sequence,

     Example :
     Returns : a fresh Bio::Seq object
     Args    :

id
--

     Title   : id
     Usage   : $id = $seq->id()
     Function: This is mapped on display_id
     Example :
     Returns :
     Args    :

Seq only methods
================

   These methods are specific to the Bio::Seq object, and not found on the
Bio::PrimarySeq object

primary_seq
-----------

     Title   : primary_seq
     Usage   : $obj->primary_seq($newval)
     Function:
     Example :
     Returns : value of primary_seq
     Args    : newvalue (optional)

annotation
----------

     Title   : annotation
     Usage   : $obj->annotation($seq_obj)
     Function:
     Example :
     Returns : value of annotation
     Args    : newvalue (optional)

add_SeqFeature
--------------

     Title   : add_SeqFeature
     Usage   : $seq->add_SeqFeature($feat);
               $seq->add_SeqFeature(@feat);
     Function: Adds the given feature object (or each of an array of feature
               objects to the feature array of this
               sequence. The object passed is required to implement the
               Bio::SeqFeatureI interface.
     Example :
     Returns : TRUE on success
     Args    : A Bio::SeqFeatureI implementing object, or an array of such objects.

top_SeqFeatures
---------------

     Title   : top_SeqFeatures
     Usage   : @feat_ary = $seq->top_SeqFeatures();
     Function: Returns the array of top-level features for this sequence object.
               Features which are not top-level are subfeatures of one or more
               of the returned feature objects, which means that you must
               traverse the subfeature arrays of each top-level feature object
               in order to traverse all features associated with this sequence.

     Use all_SeqFeatures() if you want the feature tree flattened into
     one single array.
      Example :
      Returns : An array of Bio::SeqFeatureI implementing objects.
      Args    :

all_SeqFeatures
---------------

     Title   : all_SeqFeatures
     Usage   : @feat_ary = $seq->all_SeqFeatures();
     Function: Returns the tree of feature objects attached to this sequence
               object flattened into one single array. Top-level features will
               still contain their subfeature-arrays, which means that you
               will encounter subfeatures twice if you traverse the subfeature
               tree of the returned objects.

     Use top_SeqFeatures() if you want the array to contain only the
     top-level features.
      Example :
      Returns : An array of Bio::SeqFeatureI implementing objects.
      Args    :

feature_count
-------------

     Title   : feature_count
     Usage   : $seq->feature_count()
     Function: Return the number of SeqFeatures attached to a sequence
     Example :
     Returns : number of SeqFeatures
     Args    : none

species
-------

     Title   : species
     Usage   :
     Function: Gets or sets the species
     Example : $species = $self->species();
     Returns : Bio::Species object
     Args    : Bio::Species object or none;

PrimarySeq object that stores sequence as files in the tempdir (as found by File::Temp) or the default method in Bio::Root::RootI
*********************************************************************************************************************************

NAME
====

   Bio::Seq::LargePrimarySeq - PrimarySeq object that stores sequence as
files in the tempdir (as found by File::Temp) or the default method in
Bio::Root::RootI

SYNOPSIS
========

     # normal primary seq usage

DESCRIPTION
===========

   This object stores a sequence as a series of files in a temporary
directory. The aim is to allow someone the ability to store very large
sequences (eg, > 100MBases) in a file system without running out of memory
(eg, on a 64 MB real memory machine!).

   Of course, to actually make use of this functionality, the programs
which use this object must not call $primary_seq->seq otherwise the entire
sequence will come out into memory and probably paste your machine.
However, calls $primary_seq->subseq(10,100) will cause only 90 characters
to be brought into real memory.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org               - General discussion
     http://bio.perl.org/MailList.html   - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney, Jason Stajich
===================================

   Email birney@ebi.ac.uk Email jason@chg.mc.duke.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

seq
---

     Title   : seq
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

subseq
------

     Title   : subseq
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

add_sequence_as_string
----------------------

     Title   : add_sequence_as_string
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

_filename
---------

     Title   : _filename
     Usage   : $obj->_filename($newval)
     Function:
     Example :
     Returns : value of _filename
     Args    : newvalue (optional)

SeqI compliant object that stores sequence as files in /tmp
***********************************************************

NAME
====

   Bio::Seq::LargeSeq - SeqI compliant object that stores sequence as
files in /tmp

SYNOPSIS
========

     # normal primary seq usage

DESCRIPTION
===========

   This object stores a sequence as a series of files in a temporary
directory. The aim is to allow someone the ability to store very large
sequences (eg, > 100MBases) in a file system without running out of memory
(eg, on a 64 MB real memory machine!).

   Of course, to actually make use of this functionality, the programs
which use this object must not call $primary_seq->seq otherwise the entire
sequence will come out into memory and probably paste your machine.
However, calls $primary_seq->subseq(10,100) will cause only 90 characters
to be brought into real memory.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://www.bioperl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email birney@ebi.ac.uk

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

trunc
-----

     Title   : trunc
     Usage   : $subseq = $myseq->trunc(10,100);
     Function: Provides a truncation of a sequence,

     Example :
     Returns : a fresh Bio::SeqI object
     Args    :

Module implementing a sequence created from a rich sequence database entry
**************************************************************************

NAME
====

   Bio::Seq::RichSeq - Module implementing a sequence created from a rich
sequence database entry

SYNOPSIS
========

   See Bio::Seq::RichSeqI and documentation of methods.

DESCRIPTION
===========

   This module implements Bio::Seq::RichSeqI, an interface for sequences
created from or created for entries from/of rich sequence databanks, like
EMBL, GenBank, and SwissProt. Methods added to the Bio::SeqI interface
therefore focus on databank-specific information. Note that not every rich
databank format may use all of the properties provided.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                 - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email birney@ebi.ac.uk

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
---

     Title   : new
     Usage   : $seq    = Bio::Seq::RichSeq->new( -seq => 'ATGGGGGTGGTGGTACCCT',
                                                 -id  => 'human_id',
     				             -accession_number => 'AL000012',
     				            );

     Function: Returns a new seq object from
               basic constructors, being a string for the sequence
               and strings for id and accession_number
     Returns : a new Bio::Seq::RichSeq object

division
--------

     Title   : division
     Usage   : $obj->division($newval)
     Function:
     Returns : value of division
     Args    : newvalue (optional)

molecule
--------

     Title   : molecule
     Usage   : $obj->molecule($newval)
     Function:
     Returns : type of molecule (DNA, mRNA)
     Args    : newvalue (optional)

add_date
--------

     Title   : add_date
     Usage   : $self->add_date($datestr)
     Function: adds a date
     Example :
     Returns : a date string or an array of such strings
     Args    :

get_dates
---------

     Title   : get_dates
     Usage   :
     Function:
     Example :
     Returns : an array of date strings
     Args    :

pid
---

     Title   : pid
     Usage   :
     Function: Get (and set, depending on the implementation) the PID property
               for the sequence.
     Example :
     Returns : a string
     Args    :

accession
---------

     Title   : accession
     Usage   : $obj->accession($newval)
     Function: Whilst the underlying sequence object does not
               have an accession, so we need one here.

     In this implementation this is merely a synonym for
     accession_number().
      Example :
      Returns : value of accession
      Args    : newvalue (optional)

add_secondary_accession
-----------------------

     Title   : add_secondary_accession
     Usage   : $self->add_domment($ref)
     Function: adds a secondary_accession
     Example :
     Returns :
     Args    : a string or an array of strings

get_secondary_accessions
------------------------

     Title   : get_secondary_accessions
     Usage   :
     Function:
     Example :
     Returns : An array of strings
     Args    :

seq_version
-----------

     Title   : seq_version
     Usage   : $obj->seq_version($newval)
     Function:
     Example :
     Returns : value of seq_version
     Args    : newvalue (optional)

keywords
--------

     Title   : keywords
     Usage   : $obj->keywords($newval)
     Function:
     Returns : value of keywords (a string)
     Args    : newvalue (optional) (a string)

RichSeq interface, mainly for database orientated sequences
***********************************************************

NAME
====

   Bio::Seq::RichSeqI - RichSeq interface, mainly for database orientated
sequences

SYNOPSIS
========

     @secondary   = $richseq->get_secondary_accessions;
     $division    = $richseq->division;
     $mol         = $richseq->molecule;
     @dates       = $richseq->get_dates;
     $seq_version = $richseq->seq_version;
     $pid         = $richseq->pid;

DESCRIPTION
===========

   This interface extends the Bio::SeqI interface to give additional
functionality to sequences with richer data sources, in particular from
database sequences (EMBL, GenBank and Swissprot).

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                 - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email birney@ebi.ac.uk

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

get_secondary_accessions
------------------------

     Title   : get_secondary_accessions
     Usage   :
     Function: Get the secondary accessions for a sequence.
     Example :
     Returns : an array of strings
     Args    : none

division
--------

     Title   : division
     Usage   :
     Function: Get (and set, depending on the implementation) the divison for
               a sequence.

     Examples from GenBank are PLN (plants), PRI (primates), etc.
      Example :
      Returns : a string
      Args    :

molecule
--------

     Title   : molecule
     Usage   :
     Function: Get (and set, depending on the implementation) the molecule
               type for the sequence.

     This is not necessarily the same as Bio::PrimarySeqI::moltype(),
     because it is databank-specific.
      Example :
      Returns : a string
      Args    :

pid
---

     Title   : pid
     Usage   :
     Function: Get (and set, depending on the implementation) the PID property
               for the sequence.
     Example :
     Returns : a string
     Args    :

get_dates
---------

     Title   : get_dates
     Usage   :
     Function: Get (and set, depending on the implementation) the dates the
               databank entry specified for the sequence
     Example :
     Returns : an array of strings
     Args    :

seq_version
-----------

     Title   : seq_version
     Usage   :
     Function: Get (and set, depending on the implementation) the version string
               of the sequence.
     Example :
     Returns : a string
     Args    :

Sequence analysis output parser interface
*****************************************

NAME
====

   Bio::SeqAnalysisParserI - Sequence analysis output parser interface

SYNOPSIS
========

     # get a SeqAnalysisParserI somehow, e.g. by
     my $parser = Bio::Factory::SeqAnalysisParserFactory->get_parser(
                             '-input' => 'inputfile', '-method' => 'genscan');
     while( my $feature = $parser->next_feature() ) {
     	print "Feature from ", $feature->start, " to ", $feature->end, "\n";
     }

DESCRIPTION
===========

   SeqAnalysisParserI is a generic interface for describing sequence
analysis result parsers. Sequence analysis in this sense is a search for
similarities or the identification of features on the sequence, like a
databank search or a a gene prediction result.

   The concept behind this interface is to have a generic interface in
sequence annotation pipelines (as used e.g. in high-throughput automated
sequence annotation). This interface enables plug-and-play for new analysis
methods and their corresponding parsers without the necessity for modifying
the core of the annotation pipeline. In this concept the annotation
pipeline has to rely on only a list of methods for which to process the
results, and a factory from which it can obtain the corresponding parser
implementing this interface.

   See Bio::Factory::SeqAnalysisParserFactoryI and
Bio::Factory::SeqAnalysisParserFactory for interface and an implementation
of the corresponding factory.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                - General discussion
     http://bio.perl.org/MailList.html    - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp, Jason Stajich
===================================

   Email Hilmar Lapp <hlapp@gmx.net>, Jason Stajich <jason@chg.mc.duke.edu>

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
---

     Title   : new
     Remark  : Classes implementing this interface are expected to implement
               recognition of at least the following named parameters:
               -file     input file (alternative to -fh)
               -fh       input stream (alternative to -file)

next_feature
------------

     Title   : next_feature
     Usage   : $seqfeature = $obj->next_feature();
     Function: Returns the next feature available in the analysis result, or
               undef if there are no more features.
     Example :
     Returns : A Bio::SeqFeatureI implementing object, or undef if there are no
               more features.
     Args    : none

hold pair feature information e.g. blast hits
*********************************************

NAME
====

   Bio::SeqFeature::FeaturePair - hold pair feature information e.g. blast
hits

SYNOPSIS
========

     my $feat  = new Bio::SeqFeature::FeaturePair(-feature1 => $f1,
     						 -feature2 => $f2,
     					      );

     # Bio::SeqFeatureI methods can be used

     my $start = $feat->start;
     my $end   = $feat->end;

     # Bio::FeaturePair methods can be used
     my $hstart = $feat->hstart;
     my $hend   = $feat->hend;

     my $feature1 = $feat->feature1;  # returns feature1 object

DESCRIPTION
===========

   A sequence feature object where the feature is itself a feature on
another sequence - e.g. a blast hit where residues 1-40 of a protein
sequence SW:HBA_HUMAN has hit to bases 100 - 220 on a genomic sequence
HS120G22.  The genomic sequence coordinates are used to create one
sequence feature $f1 and the protein coordinates are used to create
feature $f2.  A FeaturePair object can then be made

     my $fp = new Bio::SeqFeature::FeaturePair(-feature1 => $f1,   # genomic
     					      -feature2 => $f2,   # protein
     					      );

   This object can be used as a standard Bio::SeqFeatureI in which case

     my $gstart = $fp->start  # returns start coord on feature1 - genomic seq.
     my $gend   = $fp->end    # returns end coord on feature1.

   In general standard Bio::SeqFeatureI method calls return information in
feature1.

   Data in the feature 2 object are generally obtained using the standard
methods prefixed by h (for hit!)

     my $pstart = $fp->hstart # returns start coord on feature2 = protein seq.
     my $pend   = $fp->hend   # returns end coord on feature2.

   If you wish to swap feature1 and feature2 around :

     $feat->invert

   so...

     $feat->start # etc. returns data in $feature2 object

   No sub_SeqFeatures or tags can be stored in this object directly.  Any
features or tags are expected to be stored in the contained objects
feature1, and feature2.

CONTACT
=======

   Ewan Birney <birney@sanger.ac.uk>

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

feature1
--------

     Title   : feature1
     Usage   : $f = $featpair->feature1
               $featpair->feature1($feature)
     Function: Get/set for the query feature
     Returns : Bio::SeqFeatureI
     Args    : Bio::SeqFeatureI

feature2
--------

     Title   : feature2
     Usage   : $f = $featpair->feature2
               $featpair->feature2($feature)
     Function: Get/set for the hit feature
     Returns : Bio::SeqFeatureI
     Args    : Bio::SeqFeatureI

start
-----

     Title   : start
     Usage   : $start = $featpair->start
               $featpair->start(20)
     Function: Get/set on the start coordinate of feature1
     Returns : integer
     Args    : [optional] beginning of feature

end
---

     Title   : end
     Usage   : $end = $featpair->end
               $featpair->end($end)
     Function: get/set on the end coordinate of feature1
     Returns : integer
     Args    : [optional] ending point of feature

strand
------

     Title   : strand
     Usage   : $strand = $feat->strand()
               $feat->strand($strand)
     Function: get/set on strand information, being 1,-1 or 0
     Returns : -1,1 or 0
     Args    : [optional] strand information to set

location
--------

     Title   : location
     Usage   : $location = $featpair->location
               $featpair->location($location)
     Function: Get/set location object (using feature1)
     Returns : Bio::LocationI object
     Args    : [optional] LocationI to store

score
-----

     Title   : score
     Usage   : $score = $feat->score()
               $feat->score($score)
     Function: get/set on score information
     Returns : float
     Args    : none if get, the new value if set

frame
-----

     Title   : frame
     Usage   : $frame = $feat->frame()
               $feat->frame($frame)
     Function: get/set on frame information
     Returns : 0,1,2
     Args    : none if get, the new value if set

primary_tag
-----------

     Title   : primary_tag
     Usage   : $ptag = $featpair->primary_tag
     Function: get/set on the primary_tag of feature1
     Returns : 0,1,2
     Args    : none if get, the new value if set

source_tag
----------

     Title   : source_tag
     Usage   : $tag = $feat->source_tag()
               $feat->source_tag('genscan');
     Function: Returns the source tag for a feature,
               eg, 'genscan'
     Returns : a string
     Args    : none

seqname
-------

     Title   : seqname
     Usage   : $obj->seqname($newval)
     Function: There are many cases when you make a feature that you
               do know the sequence name, but do not know its actual
               sequence. This is an attribute such that you can store
               the seqname.

     This attribute should *not* be used in GFF dumping, as
     that should come from the collection in which the seq
     feature was found.
      Returns : value of seqname
      Args    : newvalue (optional)

hseqname
--------

     Title   : hseqname
     Usage   : $featpair->hseqname($newval)
     Function: Get/set method for the name of
               feature2.
     Returns : value of $feature2->seqname
     Args    : newvalue (optional)

hstart
------

     Title   : hstart
     Usage   : $start = $featpair->hstart
               $featpair->hstart(20)
     Function: Get/set on the start coordinate of feature2
     Returns : integer
     Args    : none

hend
----

     Title   : hend
     Usage   : $end = $featpair->hend
               $featpair->hend($end)
     Function: get/set on the end coordinate of feature2
     Returns : integer
     Args    : none

hstrand
-------

     Title   : hstrand
     Usage   : $strand = $feat->strand()
               $feat->strand($strand)
     Function: get/set on strand information, being 1,-1 or 0
     Returns : -1,1 or 0
     Args    : none

hscore
------

     Title   : hscore
     Usage   : $score = $feat->score()
               $feat->score($score)
     Function: get/set on score information
     Returns : float
     Args    : none if get, the new value if set

hframe
------

     Title   : hframe
     Usage   : $frame = $feat->frame()
               $feat->frame($frame)
     Function: get/set on frame information
     Returns : 0,1,2
     Args    : none if get, the new value if set

hprimary_tag
------------

     Title   : hprimary_tag
     Usage   : $ptag = $featpair->hprimary_tag
     Function: Get/set on the primary_tag of feature2
     Returns : 0,1,2
     Args    : none if get, the new value if set

hsource_tag
-----------

     Title   : hsource_tag
     Usage   : $tag = $feat->hsource_tag()
               $feat->source_tag('genscan');
     Function: Returns the source tag for a feature,
               eg, 'genscan'
     Returns : a string
     Args    : none

invert
------

     Title   : invert
     Usage   : $tag = $feat->invert
     Function: Swaps feature1 and feature2 around
     Returns : Nothing
     Args    : none

a feature representing an exon
******************************

NAME
====

   Bio::SeqFeature::Gene::Exon - a feature representing an exon

SYNOPSIS
========

     # obtain an exon instance $exon somehow
     print "exon from ", $exon->start(), " to ", $exon->end(),
           " on seq ", $exon->seqname(), ", strand ", $exon->strand(),
           ", encodes the peptide sequence ",
           $exon->cds()->translate()->seq(), "\n";

DESCRIPTION
===========

   This module implements a feature representing an exon by implementing
the Bio::SeqFeature::Gene::ExonI interface.

   Apart from that, this class also implements Bio::SeqFeatureI by
inheriting off Bio::SeqFeature::Generic.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp
====================

   Email hlapp@gmx.net

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

is_coding
---------

     Title   : is_coding
     Usage   : if($exon->is_coding()) {
                       # do something
               }
               if($is_utr) {
                   $exon->is_coding(0);
               }
     Function: Get/set whether or not the exon codes for amino acid.
     Returns : TRUE if the object represents a feature translated into protein,
               and FALSE otherwise.
     Args    : A boolean value on set.

primary_tag
-----------

     Title   : primary_tag
     Usage   : $tag = $feat->primary_tag()
               $feat->primary_tag('exon')
     Function: Get/set the primary tag for the exon feature.

     This method is overridden here in order to allow only for
     tag values following a certain convention. For consistency reasons,
     the tag value must either contain the string 'exon' or the string
     'utr' (both case-insensitive). In the case of 'exon', a string
     describing the type of exon may be appended or prefixed. Presently,
     the following types are allowed: initial, internal, and terminal
     (all case-insensitive).

     If the supplied tag value matches 'utr' (case-insensitive),
     is_coding() will automatically be set to FALSE, and to TRUE
     otherwise.

     Returns : A string.
     Args    : A string on set.

location
--------

     Title   : location
     Usage   : my $location = $exon->location()
     Function: Returns a location object suitable for identifying the location
     	   of the exon on the sequence or parent feature.

     This method is overridden here to restrict allowed location types
     to non-compound locations.

     Returns : Bio::LocationI object
     Args    : none

cds
---

     Title   : cds()
     Usage   : $cds = $exon->cds();
     Function: Get the coding sequence of the exon as a sequence object.

     The sequence of the returned object is prefixed by Ns (lower case)
     if the frame of the exon is defined and different from zero. The
     result is that the first base starts a codon (frame 0).

     This implementation returns undef if the particular exon is
     not translated to protein, i.e., is_coding() returns FALSE. Undef
     will also be returned if no sequence is attached to this exon
     feature.

     Returns : A Bio::PrimarySeqI implementing object.
     Args    :

Interface for a feature representing an exon
********************************************

NAME
====

   Bio::SeqFeature::Gene::ExonI - Interface for a feature representing an
exon

SYNOPSIS
========

   See documentation of methods.

DESCRIPTION
===========

   A feature representing an exon. An exon in this definition is
transcribed and at least for one particular transcript not spliced out of
the pre-mRNA. However, it does not necessarily code for amino acid.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp
====================

   Email hlapp@gmx.net

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

is_coding
---------

     Title   : is_coding
     Usage   : if($exon->is_coding()) {
                       # do something
               }
     Function: Whether or not the exon codes for amino acid.
     Returns : TRUE if the object represents a feature translated into protein,
               and FALSE otherwise.
     Args    :

cds
---

     Title   : cds()
     Usage   : $cds = $exon->cds();
     Function: Get the coding sequence of the exon as a sequence object.

     The returned sequence object must be in frame 0, i.e., the first
     base starts a codon.

     An implementation may return undef, indicating that a coding
     sequence does not exist, e.g. for a UTR (untranslated region).

     Returns : A Bio::PrimarySeqI implementing object.
     Args    :

A feature representing an arbitrarily            complex structure of a gene
****************************************************************************

NAME
====

   Bio::SeqFeature::Gene::GeneStructure - A feature representing an
arbitrarily            complex structure of a gene

SYNOPSIS
========

   See documentation of methods.

DESCRIPTION
===========

   A feature representing a gene structure. As of now, a gene structure
really is only a collection of transcripts. See
Bio::SeqFeature::Gene::TranscriptI (interface) and
Bio::SeqFeature::Gene::Transcript (implementation) for the features of
such objects.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp
====================

   Email hlapp@gmx.net

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

transcripts
-----------

     Title   : transcripts
     Usage   : @transcripts = $gene->transcripts();
     Function: Get the transcripts of this gene structure. Many gene structures
               will have only one transcript.

     Returns : An array of Bio::SeqFeature::Gene::TranscriptI implementing objects.
     Args    :

add_transcript
--------------

     Title   : add_transcript()
     Usage   : $gene->add_transcript($transcript);
     Function: Add a transcript to this gene structure.
     Returns :
     Args    : A Bio::SeqFeature::Gene::TranscriptI implementing object.

flush_transcripts
-----------------

     Title   : flush_transcripts()
     Usage   : $gene->flush_transcripts();
     Function: Remove all transcripts from this gene structure.
     Returns :
     Args    :

promoters
---------

     Title   : promoters
     Usage   : @prom_sites = $gene->promoters();
     Function: Get the promoter features of this gene structure.

     This method basically merges the promoters returned by transcripts.

     Note that OO-modeling of regulatory elements is not stable yet.
     This means that this method might change or even disappear in a
     future release. Be aware of this if you use it.

     Returns : An array of Bio::SeqFeatureI implementing objects.
     Args    :

exons
-----

     Title   : exons()
     Usage   : @exons = $gene->exons();
               @inital_exons = $gene->exons('Initial');
     Function: Get all exon features or all exons of a specified type of this gene
               structure.

     Exon type is treated as a case-insensitive regular expression and
     optional. For consistency, use only the following types:
     initial, internal, terminal, utr, utr5prime, and utr3prime.
     A special and virtual type is 'coding', which refers to all types
     except utr.

     This method basically merges the exons returned by transcripts.

     Returns : An array of Bio::SeqFeature::Gene::ExonI implementing objects.
     Args    : An optional string specifying the type of exon.

introns
-------

     Title   : introns()
     Usage   : @introns = $gene->introns();
     Function: Get all introns of this gene structure.

     Note that this class currently generates these features on-the-fly,
     that is, it simply treats all regions between exons as introns.
     It assumes that the exons in the transcripts do not overlap.

     This method basically merges the introns returned by transcripts.

     Returns : An array of Bio::SeqFeatureI implementing objects.
     Args    :

poly_A_sites
------------

     Title   : poly_A_sites()
     Usage   : @polyAsites = $gene->poly_A_sites();
     Function: Get the poly-adenylation sites of this gene structure.

     This method basically merges the poly-adenylation sites returned by
     transcripts.

     Returns : An array of Bio::SeqFeatureI implementing objects.
     Args    :

utrs
----

     Title   : utrs()
     Usage   : @utr_sites = $gene->utrs('3prime');
               @utr_sites = $gene->utrs('5prime');
               @utr_sites = $gene->utrs();
     Function: Get the features representing untranslated regions (UTR) of this
               gene structure.

     You may provide an argument specifying the type of UTR. Currently
     the following types are recognized: 5prime 3prime for UTR on the
     5' and 3' end of the CDS, respectively.

     This method basically merges the UTRs returned by transcripts.

     Returns : An array of Bio::SeqFeature::Gene::ExonI implementing objects
               representing the UTR regions or sites.
     Args    : Optionally, either 3prime, or 5prime for the the type of UTR
               feature.

sub_SeqFeature
--------------

     Title   : sub_SeqFeature
     Usage   : @feats = $gene->sub_SeqFeature();
     Function: Returns an array of all subfeatures.

     This method is defined in Bio::SeqFeatureI. We override this here
     to include the transcripts.

     Returns : An array Bio::SeqFeatureI implementing objects.
     Args    : none

flush_sub_SeqFeature
--------------------

     Title   : flush_sub_SeqFeature
     Usage   : $gene->flush_sub_SeqFeature();
               $gene->flush_sub_SeqFeature(1);
     Function: Removes all subfeatures.

     This method is overridden from Bio::SeqFeature::Generic to flush
     all additional subfeatures, i.e., transcripts, which is
     almost certainly not what you want. To remove only features added
     through $gene->add_sub_SeqFeature($feature) pass any
     argument evaluating to TRUE.

     Example :
     Returns : none
     Args    : Optionally, an argument evaluating to TRUE will suppress flushing
               of all gene structure-specific subfeatures (transcripts).

A feature representing an arbitrarily            complex structure of a gene
****************************************************************************

NAME
====

   Bio::SeqFeature::Gene::GeneStructure - A feature representing an
arbitrarily            complex structure of a gene

SYNOPSIS
========

     #documentaion needed

DESCRIPTION
===========

   A feature representing a gene structure.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp
====================

   Email hlapp@gmx.net

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

transcripts
-----------

     Title   : transcripts()
     Usage   : @transcripts = $gene->transcripts();
     Function: Get the transcript features/sites of this gene structure.

     See Bio::SeqFeature::Gene::TranscriptI for properties of the
     returned objects.

     Returns : An array of Bio::SeqFeature::Gene::TranscriptI implementing objects
               representing the promoter regions or sites.
     Args    :

promoters
---------

     Title   : promoters()
     Usage   : @prom_sites = $gene->promoters();
     Function: Get the promoter features/sites of this gene structure.

     Note that OO-modeling of regulatory elements is not stable yet.
     This means that this method might change or even disappear in a
     future release. Be aware of this if you use it.

     Returns : An array of Bio::SeqFeatureI implementing objects representing the
               promoter regions or sites.
     Args    :

exons
-----

     Title   : exons()
     Usage   : @exons = $gene->exons();
               @inital = $gene->exons('Initial');
     Function: Get all exon features or all exons of specified type of this gene
               structure.

     Refer to the documentation of the class that produced this gene
     structure object for information about the possible types.

     See Bio::SeqFeature::Gene::ExonI for properties of the
     returned objects.

     Returns : An array of Bio::SeqFeature::Gene::ExonI implementing objects
               representing the exon regions.
     Args    : An optional string specifying the type of the exon.

introns
-------

     Title   : introns()
     Usage   : @introns = $gene->introns();
     Function: Get all introns of this gene structure.
     Returns : An array of Bio::SeqFeatureI implementing objects representing the
               introns.
     Args    :

poly_A_sites
------------

     Title   : poly_A_sites()
     Usage   : @polyAsites = $gene->poly_A_sites();
     Function: Get the poly-adenylation features/sites of this gene structure.
     Returns : An array of Bio::SeqFeatureI implementing objects representing the
               poly-adenylation regions or sites.
     Args    :

utrs
----

     Title   : utrs()
     Usage   : @utr_sites = $gene->utrs();
     Function: Get the UTR features/sites of this gene structure.

     See Bio::SeqFeature::Gene::ExonI for properties of the
     returned objects.

     Returns : An array of Bio::SeqFeature::Gene::ExonI implementing objects
               representing the UTR regions or sites.
     Args    :

A feature representing a transcript
***********************************

NAME
====

   Bio::SeqFeature::Gene::Transcript - A feature representing a transcript

SYNOPSIS
========

   See documentation of methods.

DESCRIPTION
===========

   A feature representing a transcript.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp
====================

   Email hlapp@gmx.net

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

promoters
---------

     Title   : promoters()
     Usage   : @proms = $transcript->promoters();
     Function: Get the promoter features/sites of this transcript.

     Note that OO-modeling of regulatory elements is not stable yet.
     This means that this method might change or even disappear in a
     future release. Be aware of this if you use it.

     Returns : An array of Bio::SeqFeatureI implementing objects representing the
               promoter regions or sites.
     Args    :

add_promoter
------------

     Title   : add_promoter()
     Usage   : $transcript->add_promoter($feature);
     Function: Add a promoter feature/site to this transcript.

     Note that OO-modeling of regulatory elements is not stable yet.
     This means that this method might change or even disappear in a
     future release. Be aware of this if you use it.

     Returns :
     Args    : A Bio::SeqFeatureI implementing object.

flush_promoters
---------------

     Title   : flush_promoters()
     Usage   : $transcript->flush_promoters();
     Function: Remove all promoter features/sites from this transcript.

     Note that OO-modeling of regulatory elements is not stable yet.
     This means that this method might change or even disappear in a
     future release. Be aware of this if you use it.

     Returns :
     Args    : none

exons
-----

     Title   : exons()
     Usage   : @exons = $gene->exons();
               ($inital_exon) = $gene->exons('Initial');
     Function: Get all exon features or all exons of specified type of this gene
               structure.

     Exon type is treated as a case-insensitive regular expression and
     optional. For consistency, use only the following types:
     initial, internal, terminal, utr, utr5prime, and utr3prime.
     A special and virtual type is 'coding', which refers to all types
     except UTR (utr, utr5prime, utr3prime).

     Returns : An array of Bio::SeqFeature::Gene::ExonI implementing objects.
     Args    : An optional string specifying the primary_tag of the feature.

add_exon
--------

     Title   : add_exon()
     Usage   : $transcript->add_exon($exon,'initial');
     Function: Add a exon feature to this transcript.

     The second argument denotes the type of exon. Mixing exons with and
     without a type is likely to cause trouble in exons(). Either
     leave out the type for all exons or for none.

     Presently, the following types are known: initial, internal,
     terminal, utr, utr5prime, and utr3prime (all case-insensitive).
     UTR should better be added through utrs()/add_utr().

     If you wish to use other or additional types, you will almost
     certainly have to call exon_type_sortorder() in order to replace
     the default sort order, or mrna(), cds(), protein(), and exons()
     may yield unexpected results.

     Returns :
     Args    : A Bio::SeqFeature::Gene::ExonI implementing object.
               A string indicating the type of the exon (optional).

flush_exons
-----------

     Title   : flush_exons()
     Usage   : $transcript->flush_exons();
               $transcript->flush_exons('terminal');
     Function: Remove all or a certain type of exon features from this transcript.

     See add_exon() for documentation about types.

     Calling without a type will not flush UTRs. Call flush_utrs() for
     this purpose.
      Returns :
      Args    : A string indicating the type of the exon (optional).

exon_type_sortorder
-------------------

     Title   : exon_type_sortorder
     Usage   : $transcript->exon_type_sortorder('type1','type2','type3');
               $tableref = $transcript->exon_type_sortorder();
               Bio::SeqFeature::Gene::Transcript->exon_type_sortorder('type1','type2','type3');
     Function: Install or retrieve the sort-order of exon types.

               Ordering exons by type is only of relevance for methods
               constructing a sequence corresponding to the transcript object
               (e.g., mrna(), cds(), etc). For instance, an initial exon would
               have to be put before an internal exon.

     The sort-order installed by default covers only the exon types
     documented in exons(). If you use a different set or additional
     types, you must call this method with the proper ordering before
     you can obtain meaningful results from methods that concatenate
     the sequence of exons. On installing a sort-order, pass all types
     you are using in ascending order.

     You can also retrieve the installed order. Do not modify the
     returned hash table (the method returns a reference) unless you know
     exactly what you are doing. Inspecting the keys of the table will
     tell you which types are currently known.

     This method can also be called as a class method. When called as
     class method it will operate on the default sort-order, which will
     be propagated to every object instantiated thereafter. When called
     as instance method it will operate only on the private copy of the
     object.

     Returns : A reference to a hash table representing the sort-order.
     Args    : On installing an order, an array of exon types in ascending order.

introns
-------

     Title   : introns()
     Usage   : @introns = $gene->introns();
     Function: Get all intron features this gene structure.

     Note that this implementation generates these features on-the-fly,
     that is, it simply treats all regions between exons as introns,
     assuming that exons do not overlap. A consequence is that a
     consistent correspondence between the elements in the returned
     array and the array exons() returns will exist only if the
     exons are properly sorted within their types (forward for plus-
     strand and reverse for minus-strand transcripts). To ensure
     correctness the elements in the array returned will always be
     sorted.

     Returns : An array of Bio::SeqFeatureI implementing objects representing the
               intron regions.
     Args    :

poly_A_site
-----------

     Title   : poly_A_site()
     Usage   : $polyAsite = $transcript->poly_A_site();
     Function: Get/set the poly-adenylation feature/site of this transcript.
     Returns : A Bio::SeqFeatureI implementing object representing the
               poly-adenylation region.
     Args    : A Bio::SeqFeatureI implementing object on set, or FALSE to flush
               a previously set object.

utrs
----

     Title   : utrs()
     Usage   : @utr_sites = $transcript->utrs('3prime');
               @utr_sites = $transcript->utrs('5prime');
               @utr_sites = $transcript->utrs();
     Function: Get the features representing untranslated regions (UTR) of this
               transcript.

     You may provide an argument specifying the type of UTR. Currently
     the following types are recognized: 5prime 3prime for UTR on the
     5' and 3' end of the CDS, respectively.

     Returns : An array of Bio::SeqFeature::Gene::ExonI implementing objects
               representing the UTR regions or sites.
     Args    : Optionally, either 3prime, or 5prime for the the type of UTR
               feature.

add_utr
-------

     Title   : add_utr()
     Usage   : $transcript->add_utr($utrobj, '3prime');
               $transcript->add_utr($utrobj);
     Function: Add a UTR feature/site to this transcript.

     The second parameter is optional and denotes the type of the UTR
     feature. Presently recognized types include '5prime' and '3prime'
     for UTR on the 5' and 3' end of a gene, respectively.

     Calling this method is the same as calling
     add_exon($utrobj, 'utr'.$type). In this sense a UTR object is a
     special exon object, which is transcribed, not spliced out, but
     not translated.

     Note that the object supplied should return FALSE for is_coding().
     Otherwise cds() and friends will become confused.

     Returns :
     Args    : A Bio::SeqFeature::Gene::ExonI implementing object.

flush_utrs
----------

     Title   : flush_utrs()
     Usage   : $transcript->flush_utrs();
               $transcript->flush_utrs('3prime');
     Function: Remove all or a specific type of UTR features/sites from this
               transcript.

     Cf. add_utr() for documentation about recognized types.
      Returns :
      Args    : Optionally a string denoting the type of UTR feature.

sub_SeqFeature
--------------

     Title   : sub_SeqFeature
     Usage   : @feats = $transcript->sub_SeqFeature();
     Function: Returns an array of all subfeatures.

     This method is defined in Bio::SeqFeatureI. We override this here
     to include the exon etc features.

     Returns : An array Bio::SeqFeatureI implementing objects.
     Args    : none

flush_sub_SeqFeature
--------------------

     Title   : flush_sub_SeqFeature
     Usage   : $transcript->flush_sub_SeqFeature();
               $transcript->flush_sub_SeqFeature(1);
     Function: Removes all subfeatures.

     This method is overridden from Bio::SeqFeature::Generic to flush
     all additional subfeatures like exons, promoters, etc., which is
     almost certainly not what you want. To remove only features added
     through $transcript->add_sub_SeqFeature($feature) pass any
     argument evaluating to TRUE.

     Example :
     Returns : none
     Args    : Optionally, an argument evaluating to TRUE will suppress flushing
               of all transcript-specific subfeatures (exons etc.).

cds
---

     Title   : cds
     Usage   : $seq = $transcript->cds();
     Function: Returns the CDS (coding sequence) as defined by the exons of this
               transcript and the attached sequence.

     If no sequence is attached this method will return undef.

     Note that the implementation provided here returns a concatenation
     of all coding exons, thereby assuming that exons do not overlap.

     Note also that you cannot set the CDS via this method. Set a single
     CDS feature as a single exon, or derive your own class if you want
     to store a predicted CDS.

     Example :
     Returns : A Bio::PrimarySeqI implementing object.
     Args    :

protein
-------

     Title   : protein()
     Usage   : $protein = $transcript->protein();
     Function: Get the protein encoded by the transcript as a sequence object.

     The implementation provided here simply calls translate() on the
     object returned by cds().

     Returns : A Bio::PrimarySeqI implementing object.
     Args    :

mrna
----

     Title   : mrna()
     Usage   : $mrna = $transcript->mrna();
     Function: Get the mRNA of the transcript as a sequence object.

     The difference to cds() is that the sequence object returned by
     this methods will also include UTR and the poly-adenylation site,
     but not promoter sequence (TBD).

     HL: do we really need this method?

     Returns : A Bio::PrimarySeqI implementing object.
     Args    :

Interface for a feature representing a          transcript of exons, promoter(s), UTR, and a poly-adenylation site.
*******************************************************************************************************************

NAME
====

   Bio::SeqFeature::Gene::TranscriptI - Interface for a feature
representing a          transcript of exons, promoter(s), UTR, and a
poly-adenylation site.

SYNOPSIS
========

     #documentation needed

DESCRIPTION
===========

   A feature representing a transcript.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp
====================

   Email hlapp@gmx.net

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

promoters
---------

     Title   : promoters()
     Usage   : @proms = $transcript->promoters();
     Function: Get the promoter features of this transcript.

     Note that OO-modeling of regulatory elements is not stable yet.
     This means that this method might change or even disappear in a
     future release. Be aware of this if you use it.

     Returns : An array of Bio::SeqFeatureI implementing objects representing the
               promoter regions or sites.
     Args    :

exons
-----

     Title   : exons()
     Usage   : @exons = $transcript->exons();
               @inital = $transcript->exons('Initial');
     Function: Get the individual exons this transcript comprises of, or all exons
               of a specified type.

     Refer to the documentation of the class that produced this
     transcript object for information about the possible types.

     See Bio::SeqFeature::Gene::ExonI for properties of the
     returned objects.

     Returns : An array of Bio::SeqFeature::Gene::ExonI implementing objects
     Args    : An optional string specifying the type of the exon.

introns
-------

     Title   : introns()
     Usage   : @introns = $transcript->introns();
     Function: Get all introns this transcript comprises of.
     Returns : An array of Bio::SeqFeatureI implementing objects representing the
               introns.
     Args    :

poly_A_site
-----------

     Title   : poly_A_site()
     Usage   : $polyAsite = $transcript->poly_A_site();
     Function: Get the poly-adenylation site of this transcript.
     Returns : A Bio::SeqFeatureI implementing object.
     Args    :

utrs
----

     Title   : utrs()
     Usage   : @utr_sites = $transcript->utrs();
     Function: Get the UTR regions this transcript comprises of.

     See Bio::SeqFeature::Gene::ExonI for properties of the
     returned objects.

     Returns : An array of Bio::SeqFeature::Gene::ExonI implementing objects
     Args    :

mrna
----

     Title   : mrna()
     Usage   : $mrna = $transcript->mrna();
     Function: Get the mRNA of the transcript as a sequence object.

     Returns : A Bio::PrimarySeqI implementing object.
     Args    :

cds
---

     Title   : cds()
     Usage   : $cds = $transcript->cds();
     Function: Get the CDS (coding sequence) of the transcript as a sequence
               object.

     Returns : A Bio::PrimarySeqI implementing object.
     Args    :

protein
-------

     Title   : protein()
     Usage   : $protein = $transcript->protein();
     Function: Get the protein encoded by the transcript as a sequence object.

     Returns : A Bio::PrimarySeqI implementing object.
     Args    :

Generic SeqFeature
******************

NAME
====

   Bio::SeqFeature::Generic - Generic SeqFeature

SYNOPSIS
========

     $feat = new Bio::SeqFeature::Generic ( -start => 10, -end => 100,
     				-strand => -1, -primary => 'repeat',
     				-source => 'repeatmasker',
     				-score  => 1000,
     				-tag    => {
     				    new => 1,
     				    author => 'someone',
     				    sillytag => 'this is silly!' } );

     $feat = new Bio::SeqFeature::Generic ( -gff_string => $string );
     # if you want explicitly GFF1
     $feat = new Bio::SeqFeature::Generic ( -gff1_string => $string );

     # add it to an annotated sequence

     $annseq->add_SeqFeature($feat);

DESCRIPTION
===========

   Bio::SeqFeature::Generic is a generic implementation for the
Bio::SeqFeatureI interface, providing a simple object to provide all the
information for a feature on a sequence.

   For many Features, this is all you will need to use (for example, this
is fine for Repeats in DNA sequence or Domains in protein sequence). For
other features, which have more structure, this is a good base class to
extend using inheritence to have new things: this is what is done in the
Bio::SeqFeature::Gene, Bio::SeqFeature::Transcript and
Bio::SeqFeature::Exon, which provide well coordinated classes to represent
genes on DNA sequence (for example, you can get the protein sequence out
from a transcript class).

   For many Features, you want to add some piece of information, for
example a common one is that this feature is 'new' whereas other features
are 'old'.  The tag system, which here is implemented using a hash can be
used here.  You can use the tag system to extend the SeqFeature::Generic
programmatically: that is, you know that you have read in more information
into the tag 'mytag' which you can the retrieve. This means you do not
need to know how to write inherieted Perl to provide more complex
information on a feature, and/or, if you do know but you donot want to
write a new class every time you need some extra piece of information, you
can use the tag system to easily store and then retrieve information.

   The tag system can be written in/out of GFF format, and also into EMBL
format via AnnSeqIO::EMBL.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Ewan Birney <birney@sanger.ac.uk>

DEVELOPERS
==========

   This class has been written with an eye out of inheritence. The fields
the actual object hash are:

     _gsf_tag_hash  = reference to a hash for the tags
     _gsf_sub_array = reference to an array for sub arrays
     _gsf_start     = scalar of the start point
     _gsf_end       = scalar of the end point
     _gsf_strand    = scalar of the strand

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

location
--------

     Title   : location
     Usage   : my $location = $seqfeature->location()
     Function: returns a location object suitable for identifying location
     	   of feature on sequence or parent feature
     Returns : Bio::LocationI object
     Args    : none

start
-----

     Title   : start
     Usage   : $start = $feat->start
               $feat->start(20)
     Function: Get/set on the start coordinate of the feature
     Returns : integer
     Args    : none

end
---

     Title   : end
     Usage   : $end = $feat->end
               $feat->end($end)
     Function: get/set on the end coordinate of the feature
     Returns : integer
     Args    : none

length
------

     Title   : length
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

strand
------

     Title   : strand
     Usage   : $strand = $feat->strand()
               $feat->strand($strand)
     Function: get/set on strand information, being 1,-1 or 0
     Returns : -1,1 or 0
     Args    : none

score
-----

     Title   : score
     Usage   : $score = $feat->score()
               $feat->score($score)
     Function: get/set on score information
     Returns : float
     Args    : none if get, the new value if set

frame
-----

     Title   : frame
     Usage   : $frame = $feat->frame()
               $feat->frame($frame)
     Function: get/set on frame information
     Returns : 0,1,2, '.'
     Args    : none if get, the new value if set

sub_SeqFeature
--------------

     Title   : sub_SeqFeature
     Usage   : @feats = $feat->sub_SeqFeature();
     Function: Returns an array of sub Sequence Features
     Returns : An array
     Args    : none

add_sub_SeqFeature
------------------

     Title   : add_sub_SeqFeature
     Usage   : $feat->add_sub_SeqFeature($subfeat);
               $feat->add_sub_SeqFeature($subfeat,'EXPAND')
     Function: adds a SeqFeature into the subSeqFeature array.
               with no 'EXPAND' qualifer, subfeat will be tested
               as to whether it lies inside the parent, and throw
               an exception if not.

     If EXPAND is used, the parent's start/end/strand will
     be adjusted so that it grows to accommodate the new
     subFeature
      Returns : nothing
      Args    : An object which has the SeqFeatureI interface

flush_sub_SeqFeature
--------------------

     Title   : flush_sub_SeqFeature
     Usage   : $sf->flush_sub_SeqFeature
     Function: Removes all sub SeqFeature
               (if you want to remove only a subset, take
     	    an array of them all, flush them, and add
                back only the guys you want)
     Example :
     Returns : none
     Args    : none

primary_tag
-----------

     Title   : primary_tag
     Usage   : $tag = $feat->primary_tag()
               $feat->primary_tag('exon')
     Function: get/set on the primary tag for a feature,
               eg 'exon'
     Returns : a string
     Args    : none

source_tag
----------

     Title   : source_tag
     Usage   : $tag = $feat->source_tag()
               $feat->source_tag('genscan');
     Function: Returns the source tag for a feature,
               eg, 'genscan'
     Returns : a string
     Args    : none

has_tag
-------

     Title   : has_tag
     Usage   : $value = $self->has_tag('some_tag')
     Function: Tests wether a feature contaings a tag
     Returns : TRUE if the SeqFeature has the tag,
               and FALSE otherwise.
     Args    : The name of a tag

add_tag_value
-------------

     Title   : add_tag_value
     Usage   : $self->add_tag_value('note',"this is a note");
     Returns : TRUE on success
     Args    : tag (string) and value (any scalar)

each_tag_value
--------------

     Title   : each_tag_value
     Usage   : @values = $gsf->each_tag_value('note');
     Function: Returns a list of all the values stored
               under a particular tag.
     Returns : A list of scalars
     Args    : The name of the tag

all_tags
--------

     Title   : all_tags
     Usage   : @tags = $feat->all_tags()
     Function: Get a list of all the tags in a feature
     Returns : An array of tag names
     Args    : none

remove_tag
----------

     Title   : remove_tag
     Usage   : $feat->remove_tag('some_tag')
     Function: removes a tag from this feature
     Returns : nothing
     Args    : tag (string)

attach_seq
----------

     Title   : attach_seq
     Usage   : $sf->attach_seq($seq)
     Function: Attaches a Bio::Seq object to this feature. This
               Bio::Seq object is for the *entire* sequence: ie
               from 1 to 10000
     Example :
     Returns : TRUE on success
     Args    :

seq
---

     Title   : seq
     Usage   : $tseq = $sf->seq()
     Function: returns the truncated sequence (if there) for this
     Example :
     Returns : sub seq on attached sequence bounded by start & end
     Args    : none

entire_seq
----------

     Title   : entire_seq
     Usage   : $whole_seq = $sf->entire_seq()
     Function: gives the entire sequence that this seqfeature is attached to
     Example :
     Returns :
     Args    :

seqname
-------

     Title   : seqname
     Usage   : $obj->seqname($newval)
     Function: There are many cases when you make a feature that you
               do know the sequence name, but do not know its actual
               sequence. This is an attribute such that you can store
               the seqname.

     This attribute should *not* be used in GFF dumping, as
     that should come from the collection in which the seq
     feature was found.
      Returns : value of seqname
      Args    : newvalue (optional)

annotation
----------

     Title   : annotation
     Usage   : $obj->annotation($annot_obj)
     Function:
     Example :
     Returns : A Bio::Annotation object
     Args    : newvalue (optional)

gff_format
----------

     Title   : gff_format
     Usage   : # get:
               $gffio = $feature->gff_format();
               # set (change the default version of GFF2):
               $feature->gff_format(Bio::Tools::GFF->new(-gff_version => 1));
     Function: Get/set the GFF format interpreter. This object is supposed to
               format and parse GFF. See Bio::Tools::GFF for the interface.

     If this method is called as class method, the default for all
     newly created instances will be changed. Otherwise only this
     instance will be affected.
      Example :
      Returns : a Bio::Tools::GFF compliant object
      Args    : On set, an instance of Bio::Tools::GFF or a derived object.

gff_string
----------

     Title   : gff_string
     Usage   : $str = $feat->gff_string;
               $str = $feat->gff_string($gff_formatter);
     Function: Provides the feature information in GFF format.

     We override this here from Bio::SeqFeatureI in order to use the
     formatter returned by gff_format().

     Returns : A string
     Args    : Optionally, an object implementing gff_string().

_from_gff_string
----------------

     Title   : _from_gff_string
     Usage   :
     Function: Set feature properties from GFF string.

     This method uses the object returned by gff_format() for the
     actual interpretation of the string. Set a different GFF format
     interpreter first if you need a specific version, like GFF1. (The
     default is GFF2.)
      Example :
      Returns :
      Args    : a GFF-formatted string

_expand_region
--------------

     Title   : _expand_region
     Usage   : $self->_expand_region($feature);
     Function: Expand the total region covered by this feature to
               accomodate for the given feature.

     May be called whenever any kind of subfeature is added to this
     feature. add_sub_SeqFeature() already does this.
      Returns :
      Args    : A Bio::SeqFeatureI implementing object.

_parse
------

     Title   : _parse
     Usage   :
     Function: Parsing hints
     Example :
     Returns :
     Args    :

_tag_value
----------

     Title   : _tag_value
     Usage   :
     Function: For internal use only. Convenience method for those tags that
               may only have a single value.
     Returns :
     Args    :

A sequence feature based on similarity
**************************************

NAME
====

   Bio::SeqFeature::Similarity - A sequence feature based on similarity

SYNOPSIS
========

     # obtain a similarity feature somehow
     print "significance: ", $sim_fea->significance(), "\n";
     print "bit score: ", $sim_fea->bits(), "\n";
     print "score: ", $sim_fea->score(), "\n";
     print "fraction of identical residues: ", $sim_fea->frac_identical(), "\n";

DESCRIPTION
===========

   This module is basically a sequence features based on similarity, and
therefore has support for measures assessing the similarity.

   Everything else is inherited from Bio/SeqFeature/Generic.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp
====================

   Email hlapp@gmx.net or hilmar.lapp@pharma.novartis.com

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

significance
------------

     Title   : significance
     Usage   : $evalue = $obj->significance();
               $obj->significance($evalue);
     Function:
     Returns :
     Args    :

bits
----

     Title   : bits
     Usage   : $bits = $obj->bits();
               $obj->bits($value);
     Function:
     Returns :
     Args    :

frac_identical
--------------

     Title   : frac_identical
     Usage   : $fracid = $obj->frac_identical();
               $obj->frac_identical($value);
     Function:
     Returns :
     Args    :

seqlength
---------

     Title   : seqlength
     Usage   : $len = $obj->seqlength();
               $obj->seqlength($len);
     Function:
     Returns :
     Args    :

seqdesc
-------

     Title   : seqdesc
     Usage   : $desc = $obj->seqdesc();
               $obj->seqdesc($desc);
     Function: At present this method is a shorthand for
               $obj->annotation()->description().

     Note that this is not stored in the tag system and hence will
     not be included in the return value of gff_string().
      Returns :
      Args    :

Sequence feature based on the similarity                   of two sequences.
****************************************************************************

NAME
====

   Bio::SeqFeature::SimilarityPair - Sequence feature based on the
similarity                   of two sequences.

SYNOPSIS
========

     $sim_pair = Bio::SeqFeature::SimilarityPair->from_searchResult($blastHit);

     $sim = $sim_pair->query(); # a Bio::SeqFeature::Similarity object
     $sim = $sim_pair->subject(); # dto.

     # some properties for the similarity pair
     $expect = $sim_pair->significance();
     $score = $sim_pair->score();
     $bitscore = $sim_pair->bits();

     # this will not write the description for the sequence (only its name)
     print $sim_pair->query()->gff_string(), "\n";

DESCRIPTION
===========

   Lightweight similarity search result as a pair of Similarity features.
This class inherits off Bio::SeqFeature::FeaturePair and therefore
implements Bio::SeqFeatureI, whereas the two features of the pair are
descendants of Bio::SeqFeature::Generic, with better support for
representing similarity search results in a cleaner way.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org              - General discussion
     http://bio.perl.org/MailList.html  - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via  email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp
====================

   Email hlapp@gmx.net or hilmar.lapp@pharma.novartis.com

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

from_searchResult
-----------------

     Title   : from_searchResult
     Usage   : $sim_pair = Bio::SeqFeature::SimilarityPair->from_searchResult($blast_obj);
               $sim_pair->from_searchResult($blast_obj);
     Function: This method creates or fills SimilarityPair objects from objects
               representing similarity search results.

     Since there is no public interface search result objects are
     required to implement, this method basically checks for the type
     of the object and dispatches the actual SimilarityPair creation
     to a method capable of this.

     At present, the following classes are recognized:
     Bio::Tools::Blast::Sbjct
     Bio::Tools::Blast::HSP
     An exception will be thrown if an object of an unrecognized class
     is passed.

     Note that this is probably the point where you will want to add
     your class if you have a method for creating SimilarityPair
     objects from it.

     Note that passing an object that has already previously been
     filled is potentially error-prone, because undefined fields
     will not be (re-)set to an undef value.

     Returns : The object created or filled.
     Args    :

_from_blastObject
-----------------

     Title   : from_blastObject
     Usage   : $sim_pair = Bio::SeqFeature::SimilarityPair->_from_blastObj($blast_obj);
               $sim_pair->_from_blastObj($blast_obj);
     Function: See documentation for from_searchResult(). This one handles
               Bio::Tools::Blast::Sbjct and Bio::Tools::Blast::HSP objects.
     Returns : A SimilarityPair object.
     Args    :

query
-----

     Title   : query
     Usage   : $query_feature = $obj->query();
               $obj->query($query_feature);
     Function:
     Returns :
     Args    :

subject
-------

     Title   : subject
     Usage   : $sbjct_feature = $obj->subject();
               $obj->subject($sbjct_feature);
     Function:
     Returns :
     Args    :

source_tag
----------

     Title   : source_tag
     Usage   : $source = $obj->source_tag(); # i.e., program
               $obj->source_tag($evalue);
     Function:
     Returns :
     Args    :

significance
------------

     Title   : significance
     Usage   : $evalue = $obj->significance();
               $obj->significance($evalue);
     Function:
     Returns :
     Args    :

score
-----

     Title   : score
     Usage   : $score = $obj->score();
               $obj->score($value);
     Function:
     Returns :
     Args    :

bits
----

     Title   : bits
     Usage   : $bits = $obj->bits();
               $obj->bits($value);
     Function:
     Returns :
     Args    :

Abstract interface of a Sequence Feature
****************************************

NAME
====

   Bio::SeqFeatureI - Abstract interface of a Sequence Feature

SYNOPSIS
========

     # get a seqfeature somehow, eg,

     foreach $feat ( $annseq->all_seqfeatures() ) {
             print "Feature from ", $feat->start, "to ",
     	          $feat->end, " Primary tag  ", $feat->primary_tag,
     	          ", produced by ", $feat->source_tag(), "\n";

     if( $feat->strand == 0 ) {
     		print "Feature applicable to either strand\n";
     } else {
         print "Feature on strand ", $feat->strand,"\n"; # -1,1
     }

     foreach $tag ( $feat->all_tags() ) {
     		print "Feature has tag ", $tag, "with values, ",
     		      join(' ',$feat->each_tag_value($tag)), "\n";
     }
     	    print "new feature\n" if $feat->has_tag('new');
     	    # features can have sub features
     	    my @subfeat = $feat->sub_SeqFeature();
     	}

DESCRIPTION
===========

   This interface is the functions one can expect for any Sequence
Feature, whatever its implemtation or whether it is a more complex type
(eg, a Gene). This object doesn't actually provide any implemention, it
just provides the definitions of what methods one can call. See
Bio::SeqFeature::Generic for a good standard implementation of this object

FEEDBACK
========

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

start
-----

     Title   : start
     Usage   : $start = $feat->start
     Function: Returns the start coordinate of the feature
     Returns : integer
     Args    : none

end
---

     Title   : end
     Usage   : $end = $feat->end
     Function: Returns the end coordinate of the feature
     Returns : integer
     Args    : none

strand
------

     Title   : strand
     Usage   : $strand = $feat->strand()
     Function: Returns strand information, being 1,-1 or 0
     Returns : -1,1 or 0
     Args    : none

sub_SeqFeature
--------------

     Title   : sub_SeqFeature
     Usage   : @feats = $feat->sub_SeqFeature();
     Function: Returns an array of sub Sequence Features
     Returns : An array
     Args    : none

primary_tag
-----------

     Title   : primary_tag
     Usage   : $tag = $feat->primary_tag()
     Function: Returns the primary tag for a feature,
               eg 'exon'
     Returns : a string
     Args    : none

source_tag
----------

     Title   : source_tag
     Usage   : $tag = $feat->source_tag()
     Function: Returns the source tag for a feature,
               eg, 'genscan'
     Returns : a string
     Args    : none

has_tag
-------

     Title   : has_tag
     Usage   : $tag_exists = $self->has_tag('some_tag')
     Function:
     Returns : TRUE if the specified tag exists, and FALSE otherwise
     Args    :

each_tag_value
--------------

     Title   : each_tag_value
     Usage   : @values = $self->each_tag_value('some_tag')
     Function:
     Returns : An array comprising the values of the specified tag.
     Args    :

all_tags
--------

     Title   : all_tags
     Usage   : @tags = $feat->all_tags()
     Function: gives all tags for this feature
     Returns : an array of strings
     Args    : none

gff_string
----------

     Title   : gff_string
     Usage   : $str = $feat->gff_string;
               $str = $feat->gff_string($gff_formatter);
     Function: Provides the feature information in GFF format.

     The implementation provided here returns GFF2 by default. If you
     want a different version, supply an object implementing a method
     gff_string() accepting a SeqFeatureI object as argument. E.g., to
     obtain GFF1 format, do the following:

     my $gffio = Bio::Tools::GFF->new(-gff_version => 1);
     $gff1str = $feat->gff_string($gff1io);

     Returns : A string
     Args    : Optionally, an object implementing gff_string().

_static_gff_formatter
---------------------

     Title   : _static_gff_formatter
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

RangeI methods
==============

   These methods are inherited from RangeI and can be used directly from a
SeqFeatureI interface. Remember that a SeqFeature is-a RangeI, and so
wherever you see RangeI you can use a feature ($r in the below
documentation).

overlaps
--------

     Title   : overlaps
     Usage   : if($feat->overlaps($r)) { do stuff }
               if($feat->overlaps(200)) { do stuff }
     Function: tests if $feat overlaps $r
     Args    : a RangeI to test for overlap with, or a point
     Returns : true if the Range overlaps with the feature, false otherwise

contains
--------

     Title   : contains
     Usage   : if($feat->contains($r) { do stuff }
     Function: tests whether $feat totally contains $r
     Args    : a RangeI to test for being contained
     Returns : true if the argument is totaly contained within this range

equals
------

     Title   : equals
     Usage   : if($feat->equals($r))
     Function: test whether $feat has the same start, end, strand as $r
     Args    : a RangeI to test for equality
     Returns : true if they are describing the same range

Geometrical methods
===================

   These methods do things to the geometry of ranges, and return triplets
(start, stop, strand) from which new ranges could be built.

intersection
------------

     Title   : intersection
     Usage   : ($start, $stop, $strand) = $feat->intersection($r)
     Function: gives the range that is contained by both ranges
     Args    : a RangeI to compare this one to
     Returns : nothing if they do not overlap, or the range that they do overlap

union
-----

     Title   : union
     Usage   : ($start, $stop, $strand) = $feat->union($r);
             : ($start, $stop, $strand) = Bio::RangeI->union(@ranges);
     Function: finds the minimal range that contains all of the ranges
     Args    : a range or list of ranges to find the union of
     Returns : the range containing all of the ranges

location
--------

     Title   : location
     Usage   : my $location = $seqfeature->location()
     Function: returns a location object suitable for identifying location
     	   of feature on sequence or parent feature
     Returns : Bio::LocationI object
     Args    : none

Abstract Interface of Sequence (with features)
**********************************************

NAME
====

   Bio::SeqI - Abstract Interface of Sequence (with features)

SYNOPSIS
========

     # get a Bio::SeqI somehow, eg, via SeqIO. See SeqIO info
     # for more information

     $seqio  = Bio::SeqIO->new ( '-format' => 'Fasta' , -file => 'myfile.fasta');
     $seqobj = $seqio->next_seq();

     # features must implement Bio::SeqFeatureI

     @features = $seqobj->top_SeqFeatures(); # just top level
     @features = $seqobj->all_SeqFeatures(); # descend into sub features

     $seq      = $seqobj->seq(); # actual sequence as a string
     $seqstr   = $seqobj->subseq(10,50);
     $ann      = $seqobj->annotation(); # annotation object

DESCRIPTION
===========

   SeqI is the abstract interface of annotated Sequence. These methods are
those which you can be guarenteed to get for any annseq. There aren't many
here, because too many complicated functions here prevent implementations
which are just wrappers around a database or similar delayed mechanisms.

   Most of the clever stuff happens inside the SeqFeatureI system.

   A good reference implementation is Bio::Seq which is a pure perl
implementation of this class with alot of extra pieces for extra
manipulation.  However, if you want to be able to use any sequence object
in your analysis, if you can do it just using these methods, then you know
you will be future proof and compatible with other implementations of Seq.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email birney@sanger.ac.uk

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

top_SeqFeatures
---------------

     Title   : top_SeqFeatures
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

all_SeqFeatures
---------------

     Title   : all_SeqFeatures
     Usage   : @features = $annseq->all_SeqFeatures()
     Function: returns all SeqFeatures, included sub SeqFeatures
     Returns : an array
     Args    : none

seq
---

     Title   : seq
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

write_GFF
---------

     Title   : write_GFF
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

annotation
----------

     Title   : annotation
     Usage   : $obj->annotation($seq_obj)
     Function:
     Example :
     Returns : value of annotation
     Args    : newvalue (optional)

primary_seq
-----------

     Title   : primary_seq
     Usage   : $obj->primary_seq($newval)
     Function:
     Example :
     Returns : value of primary_seq
     Args    : newvalue (optional)

feature_count
-------------

     Title   : feature_count
     Usage   : $seq->feature_count()
     Function: Return the number of SeqFeatures attached to a sequence
     Example :
     Returns : number of SeqFeatures
     Args    : none

species
-------

     Title   : species
     Usage   :
     Function: Gets or sets the species
     Example : $species = $self->species();
     Returns : Bio::Species object
     Args    : Bio::Species object or none;

Handler for SeqIO Formats
*************************

NAME
====

   Bio::SeqIO - Handler for SeqIO Formats

SYNOPSIS
========

     use Bio::SeqIO;

     $in  = Bio::SeqIO->new(-file => "inputfilename" , '-format' => 'Fasta');
     $out = Bio::SeqIO->new(-file => ">outputfilename" , '-format' => 'EMBL');
     # note: we quote -format to keep older perl's from complaining.

     while ( my $seq = $in->next_seq() ) {
     	$out->write_seq($seq);
     }

   or

     use Bio::SeqIO;

     $in  = Bio::SeqIO->newFh(-file => "inputfilename" , '-format' => 'Fasta');
     $out = Bio::SeqIO->newFh('-format' => 'EMBL');

     # World's shortest Fasta<->EMBL format converter:
     print $output $_ while <$in>;

DESCRIPTION
===========

   Bio::SeqIO is a handler module for the formats in the SeqIO set (eg,
Bio::SeqIO::fasta). It is the officially sanctioned way of getting at the
format objects, which most people should use.

   The SeqIO system replaces the old parse_XXX functions in the Seq object.

   The idea is that you request a stream object for a particular format.
All the stream objects have a notion of an internal file that is read from
or written to. A particular SeqIO object instance is configured for either
input or output. A specific example of a stream object is the
Bio::SeqIO::fasta object.

   Each stream object has functions

     $stream->next_seq();

   and

     $stream->write_seq($seq);

   also

     $stream->type() # returns 'INPUT' or 'OUTPUT'

   As an added bonus, you can recover a filehandle that is tied to the
SeqIO object, allowing you to use the standard <> and print operations to
read and write sequence objects:

     use Bio::SeqIO;

     $stream = Bio::SeqIO->newFh(-format => 'Fasta'); # read from standard input

     while ( $seq = <$stream> ) {
     	# do something with $seq
     }

   and

     print $stream $seq; # when stream is in output mode

   This makes the simplest ever reformatter

     #!/usr/local/bin/perl

     $format1 = shift;
     $format2 = shift || die "Usage: reformat format1 format2 < input > output";

     use Bio::SeqIO;

     $in  = Bio::SeqIO->newFh(-format => $format1 );
     $out = Bio::SeqIO->newFh(-format => $format2 );
     #note: you might want to quote -format to keep older perl's from complaining.

     print $out $_ while <$in>;

CONSTRUCTORS
============

Bio::SeqIO->new()
-----------------

     $seqIO = Bio::SeqIO->new(-file => 'filename',   -format=>$format);
     $seqIO = Bio::SeqIO->new(-fh   => \*FILEHANDLE, -format=>$format);
     $seqIO = Bio::SeqIO->new(-format => $format);

   The new() class method constructs a new Bio::SeqIO object.  The
returned object can be used to retrieve or print BioSeq objects. new()
accepts the following parameters:

-file
     A file path to be opened for reading or writing.  The usual Perl
     conventions apply:

          'file'       # open file for reading
          '>file'      # open file for writing
          '>>file'     # open file for appending
          '+<file'     # open file read/write
          'command |'  # open a pipe from the command
          '| command'  # open a pipe to the command

-fh
     You may provide new() with a previously-opened filehandle.  For
     example, to read from STDIN:

          $seqIO = Bio::SeqIO->new(-fh => \*STDIN);

     Note that you must pass filehandles as references to globs.

     If neither a filehandle nor a filename is specified, then the module
     will read from the @ARGV array or STDIN, using the familiar <>
     semantics.

-format
     Specify the format of the file.  Supported formats include:

          Fasta       FASTA format
          EMBL        EMBL format
          GenBank     GenBank format
          swiss       Swissprot format
          SCF         SCF tracefile format
          PIR         Protein Information Resource format
          GCG         GCG format
          raw         Raw format (one sequence per line, no ID)
          ace         ACeDB sequence format

     If no format is specified and a filename is given, then the module
     will attempt to deduce it from the filename.  If this is unsuccessful,
     Fasta format is assumed.

     The format name is case insensitive.  'FASTA', 'Fasta' and 'fasta' are
     all supported.

Bio::SeqIO->newFh()
-------------------

     $fh = Bio::SeqIO->newFh(-fh   => \*FILEHANDLE, -format=>$format);
     $fh = Bio::SeqIO->newFh(-format => $format);
     # etc.

   This constructor behaves like new(), but returns a tied filehandle
rather than a Bio::SeqIO object.  You can read sequences from this object
using the familiar <> operator, and write to it using print().  The usual
array and $_ semantics work.  For example, you can read all sequence
objects into an array like this:

     @sequences = <$fh>;

   Other operations, such as read(), sysread(), write(), close(), and
printf() are not supported.

OBJECT METHODS
==============

   See below for more detailed summaries.  The main methods are:

$sequence = $seqIO->next_seq()
------------------------------

   Fetch the next sequence from the stream.

$seqIO->write_seq($sequence [,$another_sequence,...])
-----------------------------------------------------

   Write the specified sequence(s) to the stream.

TIEHANDLE(), READLINE(), PRINT()
--------------------------------

   These provide the tie interface.  See Perltie (perl.info),
for more details.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                  - General discussion
     http://bioperl.org/MailList.shtml      - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bioperl.org
     http://bioperl.org/bioperl-bugs/

AUTHOR - Ewan Birney, Lincoln Stein
===================================

   Email birney@ebi.ac.uk

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
---

     Title   : new
     Usage   : $stream = Bio::SeqIO->new(-file => $filename, -format => 'Format')
     Function: Returns a new seqstream
     Returns : A Bio::SeqIO::Handler initialised with the appropriate format
     Args    : -file => $filename
               -format => format
               -fh => filehandle to attach to

newFh
-----

     Title   : newFh
     Usage   : $fh = Bio::SeqIO->newFh(-file=>$filename,-format=>'Format')
     Function: does a new() followed by an fh()
     Example : $fh = Bio::SeqIO->newFh(-file=>$filename,-format=>'Format')
               $sequence = <$fh>;   # read a sequence object
               print $fh $sequence; # write a sequence object
     Returns : filehandle tied to the Bio::SeqIO::Fh class
     Args    :

fh
--

     Title   : fh
     Usage   : $obj->fh
     Function:
     Example : $fh = $obj->fh;      # make a tied filehandle
               $sequence = <$fh>;   # read a sequence object
               print $fh $sequence; # write a sequence object
     Returns : filehandle tied to the Bio::SeqIO::Fh class
     Args    :

next_seq
--------

     Title   : next_seq
     Usage   : $seq = stream->next_seq
     Function: Reads the next sequence object from the stream and returns it.

     Certain driver modules may encounter entries in the stream that
     are either misformatted or that use syntax not yet understood
     by the driver. If such an incident is recoverable, e.g., by
     dismissing a feature of a feature table or some other non-mandatory
     part of an entry, the driver will issue a warning. In the case
     of a non-recoverable situation an exception will be thrown.
     Do not assume that you can resume parsing the same stream after
     catching the exception. Note that you can always turn recoverable
     errors into exceptions by calling $stream->verbose(2) (see
     Bio::RootI POD page).
      Returns : a Bio::Seq sequence object
      Args    :

next_primary_seq
----------------

     Title   : next_primary_seq
     Usage   : $seq = $stream->next_primary_seq
     Function: Provides a primaryseq type of sequence object
     Returns : A Bio::PrimarySeqI object
     Args    : none

write_seq
---------

     Title   : write_seq
     Usage   : $stream->write_seq($seq)
     Function: writes the $seq object into the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::Seq object

moltype
-------

     Title   : moltype
     Usage   : $self->moltype($newval)
     Function: Set/get the molecule type for the Seq objects to be created.
     Example : $seqio->moltype('protein')
     Returns : value of moltype: 'dna', 'rna', or 'protein'
     Args    : newvalue (optional)
     Throws  : Exception if the argument is not one of 'dna', 'rna', or 'protein'

_load_format_module
-------------------

     Title   : _load_format_module
     Usage   : *INTERNAL SeqIO stuff*
     Function: Loads up (like use) a module at run time on demand
     Example :
     Returns :
     Args    :

_concatenate_lines
------------------

     Title   : _concatenate_lines
     Usage   : $s = _concatenate_lines($line, $continuation_line)
     Function: Private. Concatenates two strings assuming that the second stems
               from a continuation line of the first. Adds a space between both
               unless the first ends with a dash.

     Takes care of either arg being empty.
      Example :
      Returns : A string.
      Args    :

_filehandle
-----------

     Title   : _filehandle
     Usage   : $obj->_filehandle($newval)
     Function: This method is deprecated. Call _fh() instead.
     Example :
     Returns : value of _filehandle
     Args    : newvalue (optional)

_guess_format
-------------

     Title   : _guess_format
     Usage   : $obj->_guess_format($filename)
     Function:
     Example :
     Returns : guessed format of filename (lower case)
     Args    :

EMBL sequence input/output stream
*********************************

NAME
====

   Bio::SeqIO::EMBL - EMBL sequence input/output stream

SYNOPSIS
========

   It is probably best not to use this object directly, but rather go
through the SeqIO handler system. Go:

     $stream = Bio::SeqIO->new(-file => $filename, -format => 'EMBL');

     while $seq ( <$stream> ) {
     	# $seq is a Bio::Seq object
     }

DESCRIPTION
===========

   This object can transform Bio::Seq objects to and from EMBL flat file
databases.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     vsns-bcd-perl@lists.uni-bielefeld.de          - General discussion
     vsns-bcd-perl-guts@lists.uni-bielefeld.de     - Technically-oriented discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email birney@sanger.ac.uk

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_seq
--------

     Title   : next_seq
     Usage   : $seq = $stream->next_seq()
     Function: returns the next sequence in the stream
     Returns : Bio::Seq object
     Args    :

write_seq
---------

     Title   : write_seq
     Usage   : $stream->write_seq($seq)
     Function: writes the $seq object into the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::Seq object

_filehandle
-----------

     Title   : _filehandle
     Usage   : $obj->_filehandle($newval)
     Function:
     Example :
     Returns : value of _filehandle
     Args    : newvalue (optional)

Helper class for Embl/Genbank feature tables
********************************************

NAME
====

   Bio::SeqIO::FTHelper - Helper class for Embl/Genbank feature tables

SYNOPSIS
========

   Used by Bio::SeqIO::EMBL to help process the Feature Table

DESCRIPTION
===========

   Represents one particular Feature with the following fields

     key - the key of the feature
     loc - the location string of the feature
     <other fields> - other fields

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                 - General discussion
     http://www.bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email birney@ebi.ac.uk

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

_generic_seqfeature
-------------------

     Title   : _generic_seqfeature
     Usage   : $fthelper->_generic_seqfeature($annseq, "GenBank")
     Function: processes fthelper into a generic seqfeature
     Returns : TRUE on success and otherwise FALSE
     Args    : Bio::Seq, string indicating the source (GenBank/EMBL/SwissProt)

_parse_loc
----------

     Title   : _parse_loc
     Usage   : $fthelper->_parse_loc( $loc_string)

     Function: Parses the given location string and returns a location object
               with start() and end() and strand() set appropriately.
               Note that this method is private.
     Returns : location object or 0 on fail
     Args    : location string

from_SeqFeature
---------------

     Title   : from_SeqFeature
     Usage   : @fthelperlist = Bio::SeqIO::FTHelper::from_SeqFeature($sf,
     						     $context_annseq);
     Function: constructor of fthelpers from SeqFeatures
             :
             : The additional annseq argument is to allow the building of FTHelper
             : lines relevant to particular sequences (ie, when features are spread over
             : enteries, knowing how to build this)
     Returns : an array of FThelpers
     Args    : seq features

key
---

     Title   : key
     Usage   : $obj->key($newval)
     Function:
     Example :
     Returns : value of key
     Args    : newvalue (optional)

loc
---

     Title   : loc
     Usage   : $obj->loc($newval)
     Function:
     Example :
     Returns : value of loc
     Args    : newvalue (optional)

field
-----

     Title   : field
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

add_field
---------

     Title   : add_field
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

Fasta sequence input/output stream
**********************************

NAME
====

   Bio::SeqIO::Fasta - Fasta sequence input/output stream

SYNOPSIS
========

   It is probably best not to use this object directly, but rather go
through the SeqIO handler system. Go:

     $stream = Bio::SeqIO->new(-file => $filename, -format => 'Fasta');

     while $seq ( <$stream> ) {
     	# $seq is a Bio::Seq object
     }

DESCRIPTION
===========

   This object can transform Bio::Seq objects to and from fasta flat file
databases.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     vsns-bcd-perl@lists.uni-bielefeld.de          - General discussion
     vsns-bcd-perl-guts@lists.uni-bielefeld.de     - Technically-oriented discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email birney@sanger.ac.uk

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_seq
--------

     Title   : next_seq
     Usage   : $seq = $stream->next_seq()
     Function: returns the next sequence in the stream
     Returns : Bio::Seq object
     Args    :

write_seq
---------

     Title   : write_seq
     Usage   : $stream->write_seq($seq)
     Function: writes the $seq object into the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::Seq object

_filehandle
-----------

     Title   : _filehandle
     Usage   : $obj->_filehandle($newval)
     Function:
     Example :
     Returns : value of _filehandle
     Args    : newvalue (optional)

Raw sequence input/output stream
********************************

NAME
====

   Bio::SeqIO::GCG - Raw sequence input/output stream

SYNOPSIS
========

   It is probably best not to use this object directly, but rather go
through the SeqIO handler system. Go:

     $stream = Bio::SeqIO->new(-file => $filename, -format => 'GCG');

     while $seq ( <$stream> ) {
     	# $seq is a Bio::Seq object
     }

DESCRIPTION
===========

   This object can transform Bio::Seq objects to and from GCG-formatted
sequence files.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     vsns-bcd-perl@lists.uni-bielefeld.de          - General discussion
     vsns-bcd-perl-guts@lists.uni-bielefeld.de     - Technically-oriented discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHORS - Ewan Birney & Chris Dagdigian
=======================================

   Email birney@sanger.ac.uk, dag@sonsorol.org

   Ewan Birney wrote the all the base SeqIO stuff. This module is based on
his SeqIO::Fasta and has been tweaked by Chris Dagdigian, to support GCG
formatted sequence input/output.

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_seq
--------

     Title   : next_seq
     Usage   : $seq = $stream->next_seq()
     Function: returns the next sequence in the stream
     Returns : Bio::Seq object
     Args    :

write_seq
---------

     Title   : write_seq
     Usage   : $stream->write_seq($seq)
     Function: writes the fromatted $seq object into the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::Seq object, sequence string

_filehandle
-----------

     Title   : _filehandle
     Usage   : $obj->_filehandle($newval)
     Function:
     Example :
     Returns : value of _filehandle
     Args    : newvalue (optional)

_validate_checksum
------------------

     Title   : _validate_checksum
     Usage   : n/a - internal method
     Function: if parsed gcg sequence contains a checksum field
             : we compare it to a value computed here on the parsed
             : sequence. A checksum mismatch would indicate some
             : type of parsing failure occured.
             :
     Returns : 1 for success, 0 for failure
     Args    : string containing parsed seq, value of parsed cheksum

Handler of the SeqIO classes for tieing to filehandles
******************************************************

NAME
====

   Bio::SeqIO::Handler - Handler of the SeqIO classes for tieing to
filehandles

SYNOPSIS
========

     $stream = Bio::SeqIO->new(-file => "filename", -format => 'Fasta');

     tie *SEQ, 'Bio::SeqIO::Handler', $stream;

     while $seq ( <SEQ> ) {
     	# $seq is Bio::Seq object
     }

DESCRIPTION
===========

   This object wraps over the Bio::SeqIO:: format classes, providing the
correct glue for the tie mechanism in to filehandles. This allows normal
looking perl filehandles can be used to provide a streams for converting
sequences to and from ascii formats

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     vsns-bcd-perl@lists.uni-bielefeld.de          - General discussion
     vsns-bcd-perl-guts@lists.uni-bielefeld.de     - Technically-oriented discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email birney@sanger.ac.uk

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

_streamobj
----------

     Title   : _streamobj
     Usage   : $obj->_streamobj($newval)
     Function:
     Example :
     Returns : value of _streamobj
     Args    : newvalue (optional)

Treating a set of files as a single input stream
************************************************

NAME
====

   Bio::SeqIO::MultiFile - Treating a set of files as a single input stream

SYNOPSIS
========

     $seqin = Bio::SeqIO::MultiFile( '-format' => 'Fasta',
                                     '-files'  => ['file1','file2'] );
     while((my $seq = $seqin->next_seq)) {
         # do something with $seq
     }

DESCRIPTION
===========

   Bio::SeqIO::MultiFile provides a simple way of bundling a whole set of
identically formatted sequence input files as a single stream.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                 - General discussion
     http://www.bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email birney@ebi.ac.uk

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_seq
--------

     Title   : next_seq
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

next_primary_seq
----------------

     Title   : next_primary_seq
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

_load_file
----------

     Title   : _load_file
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

_set_file
---------

     Title   : _set_file
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

_current_seqio
--------------

     Title   : _current_seqio
     Usage   : $obj->_current_seqio($newval)
     Function:
     Example :
     Returns : value of _current_seqio
     Args    : newvalue (optional)

_format
-------

     Title   : _format
     Usage   : $obj->_format($newval)
     Function:
     Example :
     Returns : value of _format
     Args    : newvalue (optional)

Raw sequence input/output stream
********************************

NAME
====

   Bio::SeqIO::Raw - Raw sequence input/output stream

SYNOPSIS
========

   It is probably best not to use this object directly, but rather go
through the SeqIO handler system. Go:

     $stream = Bio::SeqIO->new(-file => $filename, -format => 'Raw');

     while $seq ( <$stream> ) {
     	# $seq is a Bio::Seq object
     }

DESCRIPTION
===========

   This object can transform Bio::Seq objects to and from raw textfiles.
"Raw" is defined to mean 1 or more sequences separated by a newline. Raw
sequences are just lines of data with no formatting or special fields.

   The write_seq() method has not been tested yet, should be simple enough.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     vsns-bcd-perl@lists.uni-bielefeld.de          - General discussion
     vsns-bcd-perl-guts@lists.uni-bielefeld.de     - Technically-oriented discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email birney@sanger.ac.uk

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_seq
--------

     Title   : next_seq
     Usage   : $seq = $stream->next_seq()
     Function: returns the next sequence in the stream
     Returns : Bio::Seq object
     Args    :

write_seq
---------

     Title   : write_seq
     Usage   : $stream->write_seq($seq)
     Function: writes the $seq object into the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::Seq object

_filehandle
-----------

     Title   : _filehandle
     Usage   : $obj->_filehandle($newval)
     Function:
     Example :
     Returns : value of _filehandle
     Args    : newvalue (optional)

ace sequence input/output stream
********************************

NAME
====

   Bio::SeqIO::ace - ace sequence input/output stream

SYNOPSIS
========

   Do not use this module directly.  Use it via the Bio::SeqIO class.

DESCRIPTION
===========

   This object can transform Bio::Seq objects to and from ace file format.
It only parses a DNA or Peptide objects contained in the ace file,
producing PrimarySeq objects from them.  All other objects in the files
will be ignored.  It doesn't attempt to parse any annotation attatched to
the containing Sequence or Protein objects, which would probably be
impossible, since everyone's ACeDB schema can be different.

   It won't parse ace files containing Timestamps correctly either.  This
can easily be added if considered necessary.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                  - General discussion
     http://www.bioperl.org/MailList.shtml  - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHORS - James Gilbert
=======================

   Email: jgrg@sanger.ac.uk

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_primary_seq
----------------

     Title   : next_primary_seq
     Usage   : $seq = $stream->next_primary_seq()
     Function: returns the next sequence in the stream
     Returns : Bio::PrimarySeq object
     Args    : NONE

next_seq
--------

     Title   : next_seq
     Usage   : $seq = $stream->next_seq()
     Function: returns the next sequence in the stream
     Returns : Bio::Seq object
     Args    : NONE

write_seq
---------

     Title   : write_seq
     Usage   : $stream->write_seq(@seq)
     Function: writes the $seq object into the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::Seq object(s)

EMBL sequence input/output stream
*********************************

NAME
====

   Bio::SeqIO::embl - EMBL sequence input/output stream

SYNOPSIS
========

   It is probably best not to use this object directly, but rather go
through the AnnSeqIO handler system. Go:

     $stream = Bio::SeqIO->new(-file => $filename, -format => 'EMBL');

     while ( (my $seq = $stream->next_seq()) ) {
     	# do something with $seq
     }

DESCRIPTION
===========

   This object can transform Bio::Seq objects to and from EMBL flat file
databases.

   There is alot of flexibility here about how to dump things which I need
to document fully.

   There should be a common object that this and genbank share (probably
with swissprot). Too much of the magic is identical.

Optional functions
------------------

_show_dna()
     (output only) shows the dna or not

_post_sort()
     (output only) provides a sorting func which is applied to the
     FTHelpers before printing

_id_generation_func()
     This is function which is called as

          print "ID   ", $func($annseq), "\n";

     To generate the ID line. If it is not there, it generates a sensible
     ID line using a number of tools.

          =back

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                 - General discussion
     http://www.bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email birney@ebi.ac.uk

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_seq
--------

     Title   : next_seq
     Usage   : $seq = $stream->next_seq()
     Function: returns the next sequence in the stream
     Returns : Bio::Seq object
     Args    :

write_seq
---------

     Title   : write_seq
     Usage   : $stream->write_seq($seq)
     Function: writes the $seq object (must be seq) to the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::Seq

_print_EMBL_FTHelper
--------------------

     Title   : _print_EMBL_FTHelper
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

_read_EMBL_Species
------------------

     Title   : _read_EMBL_Species
     Usage   :
     Function: Reads the EMBL Organism species and classification
               lines.
     Example :
     Returns : A Bio::Species object
     Args    :

_read_EMBL_DBLink
-----------------

     Title   : _read_EMBL_DBLink
     Usage   :
     Function: Reads the EMBL database cross reference ("DR") lines
     Example :
     Returns : A list of Bio::Annotation::DBLink objects
     Args    :

_filehandle
-----------

     Title   : _filehandle
     Usage   : $obj->_filehandle($newval)
     Function:
     Example :
     Returns : value of _filehandle
     Args    : newvalue (optional)

_read_FTHelper_EMBL
-------------------

     Title   : _read_FTHelper_EMBL
     Usage   : _read_FTHelper_EMBL($buffer)
     Function: reads the next FT key line
     Example :
     Returns : Bio::SeqIO::FTHelper object
     Args    : filehandle and reference to a scalar

_write_line_EMBL
----------------

     Title   : _write_line_EMBL
     Usage   :
     Function: internal function
     Example :
     Returns :
     Args    :

_write_line_EMBL_regex
----------------------

     Title   : _write_line_EMBL_regex
     Usage   :
     Function: internal function for writing lines of specified
               length, with different first and the next line
               left hand headers and split at specific points in the
               text
     Example :
     Returns : nothing
     Args    : file handle, first header, second header, text-line, regex for line breaks, total line length

_post_sort
----------

     Title   : _post_sort
     Usage   : $obj->_post_sort($newval)
     Function:
     Returns : value of _post_sort
     Args    : newvalue (optional)

_show_dna
---------

     Title   : _show_dna
     Usage   : $obj->_show_dna($newval)
     Function:
     Returns : value of _show_dna
     Args    : newvalue (optional)

_id_generation_func
-------------------

     Title   : _id_generation_func
     Usage   : $obj->_id_generation_func($newval)
     Function:
     Returns : value of _id_generation_func
     Args    : newvalue (optional)

_ac_generation_func
-------------------

     Title   : _ac_generation_func
     Usage   : $obj->_ac_generation_func($newval)
     Function:
     Returns : value of _ac_generation_func
     Args    : newvalue (optional)

_sv_generation_func
-------------------

     Title   : _sv_generation_func
     Usage   : $obj->_sv_generation_func($newval)
     Function:
     Returns : value of _sv_generation_func
     Args    : newvalue (optional)

_kw_generation_func
-------------------

     Title   : _kw_generation_func
     Usage   : $obj->_kw_generation_func($newval)
     Function:
     Returns : value of _kw_generation_func
     Args    : newvalue (optional)

fasta sequence input/output stream
**********************************

NAME
====

   Bio::SeqIO::fasta - fasta sequence input/output stream

SYNOPSIS
========

   Do not use this module directly.  Use it via the Bio::SeqIO class.

DESCRIPTION
===========

   This object can transform Bio::Seq objects to and from fasta flat file
databases.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org            - General discussion
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHORS - Ewan Birney & Lincoln Stein
=====================================

   Email: birney@ebi.ac.uk        lstein@cshl.org

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_seq
--------

     Title   : next_seq
     Usage   : $seq = $stream->next_seq()
     Function: returns the next sequence in the stream
     Returns : Bio::Seq object
     Args    : NONE

next_primary_seq
----------------

     Title   : next_seq
     Usage   : $seq = $stream->next_seq()
     Function: returns the next sequence in the stream
     Returns : Bio::PrimarySeq object
     Args    : NONE

write_seq
---------

     Title   : write_seq
     Usage   : $stream->write_seq(@seq)
     Function: writes the $seq object into the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::Seq object

Parses GAME XML 0.1 and higher into and out of Bio::Seq objects.
****************************************************************

NAME
====

   Bio::SeqIO::game - Parses GAME XML 0.1 and higher into and out of
Bio::Seq objects.

SYNOPSIS
========

   To use this module you need XML::Parser, XML::Parser::PerlSAX and
XML::Writer.

   Do not use this module directly.  Use it via the Bio::SeqIO class.

DESCRIPTION
===========

   This object can transform Bio::Seq objects to and from bioxml seq,
computation, feature and annotation dtds,versions 0.1 and higher.  These
can be found at http://www.bioxml.org/dtds/current.  It does this using
the idHandler, seqHandler and featureHandler modules you should have
gotten with this one.

   The idea is that any bioxml features can be turned into bioperl
annotations.  When Annotations and computations are parsed in, they gain
additional info in the bioperl SeqFeature tag attribute.  These can be
used to reconstitute a computation or annotation by the bioxml with the
bx-handler module when write_seq is called.

   If you use this to write SeqFeatures that were not generated from
computations or annotations, it will output a list of bioxml features.
Some data may be lost in this step, since bioxml features just have a
span, type and description - nothing about the anlysis performed.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioxml-dev@bioxml.org        - Technical discussion - Moderate volume
     bioxml-announce@bioxml.org   - General Announcements - Pretty dead
     http://www.bioxml.org/MailingLists/         - About the mailing lists

AUTHOR - Brad Marshall & Ewan Birney & Lincoln Stein
====================================================

   Email: bradmars@yahoo.com        birney@sanger.ac.uk
lstein@cshl.org

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

_export_subfeatures
-------------------

     Title   : _export_subfeatures
     Usage   : $obj->_export_subfeatures
     Function: export all subfeatures (also in the geneprediction structure)
     Returns : value of _export_subfeatures
     Args    : newvalue (optional)

_group_subfeatures
------------------

     Title   : _group_subfeatures
     Usage   : $obj->_group_subfeatures
     Function: Groups all subfeatures in separate feature_sets
     Returns : value of _group_subfeatures
     Args    : newvalue (optional)

_subfeature_types
-----------------

     Title   : _subfeature_types
     Usage   : $obj->_subfeature_types
     Function: array of all possible subfeatures, it should be a name of a function which
             : returns an arrau of sub_seqfeatures when called: @array = $feature->subfeaturetyp()
     Returns : array of _subfeature_types
     Args    : array of subfeature types (optional)

_add_subfeature_type    Title   : _add_subfeature_type  Usage   : $obj->_add_subfeature_type  Function: add one possible subfeature, it should be a name of a function which          : returns an arrau of sub_seqfeatures when called: @array = $feature->subfeaturetyp()  Returns : 1  Args    : one subfeature type (optional)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

next_seq
--------

     Title   : next_seq
     Usage   : $seq = $stream->next_seq()
     Function: returns the next sequence in the stream
     Returns : Bio::Seq object
     Args    : NONE

next_primary_seq
----------------

     Title   : next_primary_seq
     Usage   : $seq = $stream->next_primary_seq()
     Function: returns the next primary sequence (ie no seq_features) in the stream
     Returns : Bio::PrimarySeq object
     Args    : NONE

write_seq
---------

     Title   : write_seq
     Usage   : Not Yet Implemented! $stream->write_seq(@seq)
     Function: writes the $seq object into the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::Seq object

GCG sequence input/output stream
********************************

NAME
====

   Bio::SeqIO::gcg - GCG sequence input/output stream

SYNOPSIS
========

   Do not use this module directly.  Use it via the Bio::SeqIO class.

DESCRIPTION
===========

   This object can transform Bio::Seq objects to and from GCG flat file
databases.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                 - General discussion
     http://www.bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHORS - Ewan Birney & Lincoln Stein
=====================================

   Email: birney@ebi.ac.uk        lstein@cshl.org

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_seq
--------

     Title   : next_seq
     Usage   : $seq = $stream->next_seq()
     Function: returns the next sequence in the stream
     Returns : Bio::Seq object
     Args    :

write_seq
---------

     Title   : write_seq
     Usage   : $stream->write_seq(@seq)
     Function: writes the fromatted $seq object into the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::Seq object, sequence string

GCG_checksum
------------

     Title     : GCG_checksum
     Usage     : $cksum = $gcgio->GCG_checksum($seq);
     Function  : returns a gcg checksum for the sequence specified

     This method can also be called as a class method.
      Example   :
      Returns   : a GCG checksum string
      Argument  : a Bio::PrimarySeqI implementing object

_validate_checksum
------------------

     Title   : _validate_checksum
     Usage   : n/a - internal method
     Function: if parsed gcg sequence contains a checksum field
             : we compare it to a value computed here on the parsed
             : sequence. A checksum mismatch would indicate some
             : type of parsing failure occured.
             :
     Returns : 1 for success, 0 for failure
     Args    : string containing parsed seq, value of parsed cheksum

GenBank sequence input/output stream
************************************

NAME
====

   Bio::SeqIO::GenBank - GenBank sequence input/output stream

SYNOPSIS
========

   It is probably best not to use this object directly, but rather go
through the SeqIO handler system. Go:

     $stream = Bio::SeqIO->new(-file => $filename, -format => 'GenBank');

     while ( my $seq = $stream->next_seq() ) {
     	# do something with $seq
     }

DESCRIPTION
===========

   This object can transform Bio::Seq objects to and from GenBank flat
file databases.

   There is alot of flexibility here about how to dump things which I need
to document fully.

Optional functions
------------------

_show_dna()
     (output only) shows the dna or not

_post_sort()
     (output only) provides a sorting func which is applied to the
     FTHelpers before printing

_id_generation_func()
     This is function which is called as

          print "ID   ", $func($seq), "\n";

     To generate the ID line. If it is not there, it generates a sensible
     ID line using a number of tools.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                  - General discussion
     http://www.bioperl.org/MailList.shtml  - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Elia Stupka
====================

   Email elia@ebi.ac.uk

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_seq
--------

     Title   : next_seq
     Usage   : $seq = $stream->next_seq()
     Function: returns the next sequence in the stream
     Returns : Bio::Seq object
     Args    :

write_seq
---------

     Title   : write_seq
     Usage   : $stream->write_seq($seq)
     Function: writes the $seq object (must be seq) to the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::Seq

_print_GenBank_FTHelper
-----------------------

     Title   : _print_GenBank_FTHelper
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

_read_GenBank_References
------------------------

     Title   : _read_GenBank_References
     Usage   :
     Function: Reads references from GenBank format. Internal function really
     Example :
     Returns :
     Args    :

_read_GenBank_Species
---------------------

     Title   : _read_GenBank_Species
     Usage   :
     Function: Reads the GenBank Organism species and classification
               lines.
     Example :
     Returns : A Bio::Species object
     Args    :

_read_FTHelper_GenBank
----------------------

     Title   : _read_FTHelper_GenBank
     Usage   : _read_FTHelper_GenBank($buffer)
     Function: reads the next FT key line
     Example :
     Returns : Bio::SeqIO::FTHelper object
     Args    : filehandle and reference to a scalar

_write_line_GenBank
-------------------

     Title   : _write_line_GenBank
     Usage   :
     Function: internal function
     Example :
     Returns :
     Args    :

_write_line_GenBank_regex
-------------------------

     Title   : _write_line_GenBank_regex
     Usage   :
     Function: internal function for writing lines of specified
               length, with different first and the next line
               left hand headers and split at specific points in the
               text
     Example :
     Returns : nothing
     Args    : file handle, first header, second header, text-line, regex for line breaks, total line length

_post_sort
----------

     Title   : _post_sort
     Usage   : $obj->_post_sort($newval)
     Function:
     Returns : value of _post_sort
     Args    : newvalue (optional)

_show_dna
---------

     Title   : _show_dna
     Usage   : $obj->_show_dna($newval)
     Function:
     Returns : value of _show_dna
     Args    : newvalue (optional)

_id_generation_func
-------------------

     Title   : _id_generation_func
     Usage   : $obj->_id_generation_func($newval)
     Function:
     Returns : value of _id_generation_func
     Args    : newvalue (optional)

_ac_generation_func
-------------------

     Title   : _ac_generation_func
     Usage   : $obj->_ac_generation_func($newval)
     Function:
     Returns : value of _ac_generation_func
     Args    : newvalue (optional)

_sv_generation_func
-------------------

     Title   : _sv_generation_func
     Usage   : $obj->_sv_generation_func($newval)
     Function:
     Returns : value of _sv_generation_func
     Args    : newvalue (optional)

_kw_generation_func
-------------------

     Title   : _kw_generation_func
     Usage   : $obj->_kw_generation_func($newval)
     Function:
     Returns : value of _kw_generation_func
     Args    : newvalue (optional)

method i/o on very large fasta sequence files
*********************************************

NAME
====

   Bio::SeqIO::largefasta - method i/o on very large fasta sequence files

SYNOPSIS
========

   Do not use this module directly.  Use it via the Bio::SeqIO class.

DESCRIPTION
===========

   This object can transform Bio::Seq objects to and from fasta flat file
databases.

   This module handles very large sequence files by using the
Bio/Seq/LargePrimarySeq, module to store all the
sequence data in a file.  This can be a problem if you have limited disk
space on your computer because this will effectively cause 2 copies of the
sequence file to reside on disk for the life of the
Bio/Seq/LargePrimarySeq, object.  The default
location for this is specified by the File/Spec,->tmpdir
routine which is usually /tmp on UNIX.  If a sequence file is larger than
the swap space (capacity of the /tmp dir) this could cause problems for
the machine.  It is possible to set the directory where the temporary file
is located by adding the following line to your code BEFORE calling
next_seq.

   $Bio::Seq::LargePrimarySeq::DEFAULT_TEMP_DIR = 'newdir';

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org            - General discussion
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHORS - Jason Stajich
=======================

   Email: jason@chg.mc.duke.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_seq
--------

     Title   : next_seq
     Usage   : $seq = $stream->next_seq()
     Function: returns the next sequence in the stream
     Returns : Bio::Seq object
     Args    : NONE

next_primary_seq
----------------

     Title   : next_seq
     Usage   : $seq = $stream->next_seq()
     Function: returns the next sequence in the stream
     Returns : Bio::PrimarySeq object
     Args    : NONE

write_seq
---------

     Title   : write_seq
     Usage   : $stream->write_seq(@seq)
     Function: writes the $seq object into the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::Seq object

PIR sequence input/output stream
********************************

NAME
====

   Bio::SeqIO::pir - PIR sequence input/output stream

SYNOPSIS
========

   Do not use this module directly.  Use it via the Bio::SeqIO class.

DESCRIPTION
===========

   This object can transform Bio::Seq objects to and from fasta flat file
databases.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                 - General discussion
     http://www.bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHORS
=======

   Aaron Mackey <amackey@virginia.edu> Lincoln Stein <lstein@cshl.org>

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_seq
--------

     Title   : next_seq
     Usage   : $seq = $stream->next_seq()
     Function: returns the next sequence in the stream
     Returns : Bio::Seq object
     Args    :

write_seq
---------

     Title   : write_seq
     Usage   : $stream->write_seq(@seq)
     Function: writes the $seq object into the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::Seq object

raw sequence file input/output stream
*************************************

NAME
====

   Bio::SeqIO::raw - raw sequence file input/output stream

SYNOPSIS
========

   Do not use this module directly.  Use it via the Bio/SeqIO,
class.

DESCRIPTION
===========

   This object can transform Bio::Seq objects to and from raw flat file
databases.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                 - General discussion
     http://www.bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHORS
=======

     Ewan Birney  <birney@ebi.ac.uk>
     Lincoln Stein <lstein@cshl.org>

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_seq
--------

     Title   : next_seq
     Usage   : $seq = $stream->next_seq()
     Function: returns the next sequence in the stream
     Returns : Bio::Seq object
     Args    :

write_seq
---------

     Title   : write_seq
     Usage   : $stream->write_seq($seq)
     Function: writes the $seq object into the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::Seq object

SCF sequence input/output stream
********************************

NAME
====

   Bio::SeqIO::scf - SCF sequence input/output stream

SYNOPSIS
========

   Do not use this module directly.  Use it via the Bio/SeqIO,
class.

DESCRIPTION
===========

   This object can transform Bio::Seq objects to and from SCF trace files.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                 - General discussion
     http://www.bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHORS
=======

     Aaron Mackey
     Lincoln Stein lstein@cshl.org

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_seq
--------

     Title   : next_seq
     Usage   : $seq = $stream->next_seq()
     Function: returns the next sequence in the stream
     Returns : Bio::Seq object
     Args    :

write_seq
---------

     Title   : write_seq
     Usage   : $stream->write_seq(@seq)
     Function: writes the $seq object into the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::Seq object

Swissprot sequence input/output stream
**************************************

NAME
====

   Bio::SeqIO::swiss - Swissprot sequence input/output stream

SYNOPSIS
========

   It is probably best not to use this object directly, but rather go
through the SeqIO handler system. Go:

     $stream = Bio::SeqIO->new(-file => $filename, -format => 'swiss');

     while ( my $seq = $stream->next_seq() ) {
     	# do something with $seq
     }

DESCRIPTION
===========

   This object can transform Bio::Seq objects to and from swissprot flat
file databases.

   There is alot of flexibility here about how to dump things which I need
to document fully.

Optional functions
------------------

_show_dna()
     (output only) shows the dna or not

_post_sort()
     (output only) provides a sorting func which is applied to the
     FTHelpers before printing

_id_generation_func()
     This is function which is called as

          print "ID   ", $func($seq), "\n";

     To generate the ID line. If it is not there, it generates a sensible
     ID line using a number of tools.

          =back

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Elia Stupka
====================

   Email elia@ebi.ac.uk

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_seq
--------

     Title   : next_seq
     Usage   : $seq = $stream->next_seq()
     Function: returns the next sequence in the stream
     Returns : Bio::Seq object
     Args    :

write_seq
---------

     Title   : write_seq
     Usage   : $stream->write_seq($seq)
     Function: writes the $seq object (must be seq) to the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::Seq

_generateCRCTable
-----------------

     Title   : _generateCRCTable
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

_crc32
------

     Title   : _crc32
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

_print_swissprot_FTHelper
-------------------------

     Title   : _print_swissprot_FTHelper
     Usage   :
     Function:
     Example :
     Returns :
     Args    :

_read_swissprot_References
--------------------------

     Title   : _read_swissprot_References
     Usage   :
     Function: Reads references from swissprot format. Internal function really
     Example :
     Returns :
     Args    :

_read_swissprot_Species
-----------------------

     Title   : _read_swissprot_Species
     Usage   :
     Function: Reads the swissprot Organism species and classification
               lines.
     Example :
     Returns : A Bio::Species object
     Args    :

_filehandle
-----------

     Title   : _filehandle
     Usage   : $obj->_filehandle($newval)
     Function:
     Example :
     Returns : value of _filehandle
     Args    : newvalue (optional)

_read_FTHelper_swissprot
------------------------

     Title   : _read_FTHelper_swissprot
     Usage   : _read_FTHelper_swissprot(\$buffer)
     Function: reads the next FT key line
     Example :
     Returns : Bio::SeqIO::FTHelper object
     Args    : filehandle and reference to a scalar

_write_line_swissprot
---------------------

     Title   : _write_line_swissprot
     Usage   :
     Function: internal function
     Example :
     Returns :
     Args    :

_write_line_swissprot_regex
---------------------------

     Title   : _write_line_swissprot_regex
     Usage   :
     Function: internal function for writing lines of specified
               length, with different first and the next line
               left hand headers and split at specific points in the
               text
     Example :
     Returns : nothing
     Args    : file handle, first header, second header, text-line, regex for line breaks, total line length

_post_sort
----------

     Title   : _post_sort
     Usage   : $obj->_post_sort($newval)
     Function:
     Returns : value of _post_sort
     Args    : newvalue (optional)

_show_dna
---------

     Title   : _show_dna
     Usage   : $obj->_show_dna($newval)
     Function:
     Returns : value of _show_dna
     Args    : newvalue (optional)

_id_generation_func
-------------------

     Title   : _id_generation_func
     Usage   : $obj->_id_generation_func($newval)
     Function:
     Returns : value of _id_generation_func
     Args    : newvalue (optional)

_ac_generation_func
-------------------

     Title   : _ac_generation_func
     Usage   : $obj->_ac_generation_func($newval)
     Function:
     Returns : value of _ac_generation_func
     Args    : newvalue (optional)

_sv_generation_func
-------------------

     Title   : _sv_generation_func
     Usage   : $obj->_sv_generation_func($newval)
     Function:
     Returns : value of _sv_generation_func
     Args    : newvalue (optional)

_kw_generation_func
-------------------

     Title   : _kw_generation_func
     Usage   : $obj->_kw_generation_func($newval)
     Function:
     Returns : value of _kw_generation_func
     Args    : newvalue (optional)

Additional methods for PrimarySeq objects
*****************************************

NAME
====

   Bio::SeqUtils - Additional methods for PrimarySeq objects

SYNOPSIS
========

     # get a Bio::PrimarySeqI compliant object, $seq, somehow
     $util = new Bio::SeqUtils;
     $poplypeptide_3char = $util->seq3($seq);
     #or
     $poplypeptide_3char = Bio::SeqUtils->seq3($seq);

     #set the sequence string (stored in one char code in the object)
     Bio::SeqUtils->seq3($seq, $poplypeptide_3char);

DESCRIPTION
===========

   This class is a holder of methods that work on Bio/PrimarySeqI,
compliant sequence objects, e.g. See Bio/PrimarySeq,
and Bio/Seq. These methods are not part of
the Bio/PrimarySeqI, interface and should in
general not essential to the primary function of sequence objects. If you
are thinking of adding essential functions, it might be better to create
your own sequence class.

   The methods take as their first argument a sequence object. It is
possible to use methods without first creating a SeqUtils object, i.e. use
it as an anonymous hash.

   The first two methodsgive out or read in protein sequences coded in
three letter IUPAC amino acid codes.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Heikki Lehvaslaiho
===========================

   Email:  heikki@ebi.ac.uk Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

seq3
----

     Title   : seq3
     Usage   : $string = Bio::SeqUtils->seq3($seq)
     Function:

     Read only method that returns the amino acid sequence as a
     string of three letter codes. moltype has to be
     'protein'. Output follows the IUPAC standard plus 'Ter' for
     terminator. Any unknown character, including the default
     unknown character 'X', is changed into 'Xaa'. A noncoded
     aminoacid selenocystein is recognized (Sel, U).

     Returns : A scalar
     Args    : character used for stop in the protein seqence optional,
               defaults to '*' string used to separate the output amino
               acid codes, optional, defaults to ''

seq3in
------

     Title   : seq3in
     Usage   : $string = Bio::SeqUtils->seq3in($seq, 'MetGlyTer')
     Function:

     Read only method that returns the amino acid sequence as a
     string of three letter codes. moltype has to be
     'protein'. Output follows the IUPAC standard plus 'Ter' for
     terminator. Any unknown character, including the default
     unknown character 'X', is changed into 'Xaa'

     Returns : Bio::PrimarySeq object;
     Args    : character to be used for stop in the protein seqence,
                  optional, defaults to '*'
               character to be used for unknown in the protein seqence,
                  optional, defaults to 'X'
               string used to separate the output amino acid codes,
                  optional, defaults to ''

Multiple alignments held as a set of sequences
**********************************************

NAME
====

   SimpleAlign - Multiple alignments held as a set of sequences

SYNOPSIS
========

     $aln = new Bio::SimpleAlign;

     $aln->read_MSF(\*STDIN);

     $aln->write_fasta(\*STDOUT);

INSTALLATION
============

   This module is included with the central Bioperl distribution:

     http://bio.perl.org/Core/Latest
     ftp://bio.perl.org/pub/DIST

   Follow the installation instructions included in the README file.

DESCRIPTION
===========

   SimpleAlign handles multiple alignments of sequences. It is very
permissive of types (it wont insist on things being all same length etc):
really it is a SequenceSet explicitly held in memory with a whole series of
built in manipulations and especially file format systems for read/writing
alignments.

   SimpleAlign basically views an alignment as an immutable block of text.
SimpleAlign *is not* the object to be using if you want to perform complex
alignment alignment manipulations.  These functions are much better done
by UnivAln by Georg Fuellen.

   However for lightweight display/formatting and minimal manipulation
(e.g. removiung all-gaps columns) - this is the one to use.

   Tricky concepts. SimpleAlign expects name,start,end to be 'unique' in
the alignment, and this is the key for the internal hashes.
(name,start,end is abreviated nse in the code). However, in many cases
people don't want the name/start-end to be displayed: either multiple
names in an alignment or names specific to the alignment (ROA1_HUMAN_1,
ROA1_HUMAN_2 etc). These names are called 'displayname', and generally is
what is used to print out the alignment. They default to name/start-end

   The SimpleAlign Module came from Ewan Birney's Align module

PROGRESS
========

   SimpleAlign is being slowly converted to bioperl coding standards,
mainly by Ewan.

Use Bio::Root::Object - done
Use proper exceptions - done
Use hashed constructor - not done!
FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules.  Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR
======

   Ewan Birney, birney@sanger.ac.uk

SEE ALSO
========

     Bio::LocatableSeq.pm

     http://bio.perl.org/Projects/modules.html  - Online module documentation
     http://bio.perl.org/Projects/SeqAlign/     - Bioperl sequence alignment project
     http://bio.perl.org/                       - Bioperl Project Homepage

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

addSeq
------

     Title     : addSeq
     Usage     : $myalign->addSeq($newseq);
               :
               :
     Function  : Adds another sequence to the alignment
               : *does not* align it - just adds it to the
               : hashes
               :
     Returns   : nothing
     Argument  :

column_from_residue_number
--------------------------

     Title   : column_from_residue_number
     Usage   : $col = $ali->column_from_residue_number( $seqname, $resnumber)
     Function:
        This function gives the position in the alignment (i.e. column number) of
        the given residue number in the sequence with the given name. For example,
        for the alignment

     Seq1/91-97 AC..DEF.GH
     Seq2/24-30 ACGG.RTY..
     Seq3/43-51 AC.DDEFGHI

     column_from_residue_number( "Seq1", 94 ) returns 5.
     column_from_residue_number( "Seq2", 25 ) returns 2.
     column_from_residue_number( "Seq3", 50 ) returns 9.

     An exception is thrown if the residue number would lie outside the length
     of the aligment (e.g. column_from_residue_number( "Seq2", 22 )

     Returns :
        A column number for the postion in the alignment of the given residue in the given
             sequence (1 = first column)
     Args    :
        A sequence name (not a name/start-end)
        A residue number in the whole sequence (not just that segment of it in the alignment)

consensus_string
----------------

     Title     : consensus_string
     Usage     : $str = $ali->consensus_string($threshold_percent)
     Function  : Makes a consensus
     Returns   :
     Argument  : Optional treshold ranging from 0 to 100.  If consensus residue appears in
     		fewer than threshold % of the sequences at a given location
     		consensus_string will return a "?" at that location rather than the consensus
     		letter. (Default value = 0%)

consensus_aa
------------

     Title     : consensus_aa
     Usage     : $consensus_residue = $ali->consensus_aa($residue_number, $threshold_percent)
     Function  : Makes a consensus
     Returns   :
     Argument  : Optional treshold ranging from 0 to 100.  If consensus residue appears in
     		fewer than threshold % of the sequences at the specified location
     		consensus_string will return a "?"  rather than the consensus
     		letter. (Default value = 0%)

each_alphabetically
-------------------

     Title     : each_alphabetically
     Usage     : foreach $seq ( $ali->each_alphabetically() )
               :
               :
     Function  : returns an array of sequence object sorted
               : alphabetically by name and then by start point
               :
               : Does not change the order of the alignment
     Returns   :
     Argument  :

eachSeq
-------

     Title     : eachSeq
     Usage     : foreach $seq ( $align->eachSeq() )
               :
               :
     Function  : gets an array of Seq objects from the
               : alignment
               :
               :
     Returns   : an array
     Argument  : nothing

eachSeqWithId
-------------

     Title     : eachSeqWithId
     Usage     : foreach $seq ( $align->eachSeqWithName() )
               :
               :
     Function  : gets an array of Seq objects from the
               : alignment, the contents being those sequences
               : with the given name (there may be more than one
               :
     Returns   : an array
     Argument  : nothing

id
--

     Title     : id
     Usage     : $myalign->id("Ig")
     Function  : Gets/sets the id field of the alignment
               :
     Returns   : An id string
     Argument  : An id string (optional)

is_flush
--------

     Title     : is_flush
     Usage     : if( $ali->is_flush() )
               :
               :
     Function  : Tells you whether the alignment
               : is flush, ie all of the same length
               :
               :
     Returns   : 1 or 0
     Argument  :

length_aln
----------

     Title     : length_aln()
     Usage     : $len = $ali->length_aln()
               :
               :
     Function  : returns the maximum length of the alignment.
               : To be sure the alignment is a block, use is_flush
               :
               :
     Returns   :
     Argument  :

map_chars
---------

     Title     : map_chars
     Usage     : $ali->map_chars('\.','-')
               :
               :
     Function  : does a s/$arg1/$arg2/ on
               : the sequences. Useful for
               : gap characters
               :
               : Notice that the from (arg1) is interpretted
               : as a regex, so be careful about quoting meta
               : characters (eg $ali->map_chars('.','-') wont
               : do what you want)
     Returns   :
     Argument  :

no_residues
-----------

     Title     : no_residues
     Usage     : $no = $ali->no_residues
               :
               :
     Function  : number of residues in total
               : in the alignment
               :
               :
     Returns   :
     Argument  :

no_sequences
------------

     Title     : no_sequences
     Usage     : $depth = $ali->no_sequences
               :
               :
     Function  : number of sequence in the
               : sequence alignment
               :
               :
     Returns   :
     Argument  :

percentage_identity
-------------------

     Title   : percentage_identity
     Usage   : $id = $align->percentage_identity
     Function:
        The function uses a fast method to calculate the average percentage identity of the alignment
     Returns : The average percentage identity of the alignment
     Args    : None

purge
-----

     Title   : purge
     Usage   : $aln->purge(0.7);
     Function: removes sequences above whatever %id
     Example :
     Returns : An array of the removed sequences
     Arguments

     This function will grind on large alignments. Beware!

     (perhaps not ideally implemented)

read_fasta
----------

     Title     : read_fasta
     Usage     : $ali->read_fasta(\*INPUT)
               :
               :
     Function  : reads in a fasta formatted
               : file for an alignment
               :
               :
     Returns   :
     Argument  :

read_mase
---------

     Title     : read_mase
     Usage     : $ali->read_mase(\*INPUT)
               :
               :
     Function  : reads mase (seaview)
               : formatted alignments
               :
               :
     Returns   :
     Argument  :

read_MSF
--------

     Title   : read_MSF
     Usage   : $al->read_MSF(\*STDIN);
     Function: reads MSF formatted files. Tries to read *all* MSF
              It reads all non whitespace characters in the alignment
              area. For MSFs with weird gaps (eg ~~~) map them by using
              $al->map_chars('~','-');
     Example :
     Returns :
     Args    : filehandle

read_Pfam
---------

     Title     : read_Pfam
     Usage     : $ali->read_Pfam(\*INPUT)
               :
               :
     Function  : reads a Pfam formatted
               : Alignment (Mul format).
               : - this is the format used by Belvu
               :
     Returns   :
     Argument  :

read_Pfam_file
--------------

     Title     : read_Pfam_file
     Usage     : $ali->read_Pfam_file("thisfile");
               :
     Function  : opens a filename, reads
               : a Pfam (mul) formatted alignment
               :
               :
               :
     Returns   :
     Argument  :

read_Prodom
-----------

     Title   : read_Prodom
     Usage   : $ali->read_Prodom( $file )
     Function: Reads in a Prodom format alignment
     Returns :
        Args    : A filehandle glob or ref. to a filehandle object

read_selex
----------

     Title     : read_selex
     Usage     : $ali->read_selex(\*INPUT)
               :
               :
     Function  : reads selex (hmmer) format
               : alignments
               :
               :
     Returns   :
     Argument  :

read_stockholm
--------------

     Title     : read_stockholm
     Usage     : $ali->read_stockholm(\*INPUT)
               :
               :
     Function  : reads stockholm  format alignments
               :
               :
     Returns   :
     Argument  :

removeSeq
---------

     Title     : removeSeq
     Usage     : $aln->removeSeq($seq);
     Function  : removes a single sequence from an alignment

set_displayname_count
---------------------

     Title     : set_displayname_count
     Usage     : $ali->set_displayname_count
               :
               :
     Function  : sets the names to be name_#
               : where # is the number of times this
               : name has been used.
               :
     Returns   :
     Argument  :

set_displayname_flat
--------------------

     Title     : set_displayname_flat
     Usage     : $ali->set_displayname_flat()
               :
               :
     Function  : Makes all the sequences be displayed
               : as just their name, not name/start-end
               :
               :
     Returns   :
     Argument  :

set_displayname_normal
----------------------

     Title     : set_displayname_normal
     Usage     : $ali->set_displayname_normal()
               :
               :
     Function  : Makes all the sequences be displayed
               : as name/start-end
               :
               :
     Returns   :
     Argument  :

sort_alphabetically
-------------------

     Title     : sort_alphabetically
     Usage     : $ali->sort_alphabetically
               :
               :
     Function  : changes the order of the alignemnt
               : to alphabetical on name followed by
               : numerical by number
               :
     Returns   :
     Argument  :

uppercase
---------

     Title     : uppercase()
     Usage     : $ali->uppercase()
               :
               :
     Function  : Sets all the sequences
               : to uppercase
               :
               :
     Returns   :
     Argument  :

write_clustalw
--------------

     Title     : write_clustalw
     Usage     : $ali->write_clustalw
               :
               :
     Function  : writes a clustalw formatted
               : (.aln) file
               :
               :
     Returns   :
     Argument  :

write_fasta
-----------

     Title     : write_fasta
     Usage     : $ali->write_fasta(\*OUTPUT)
               :
               :
     Function  : writes a fasta formatted alignment
               :
     Returns   :
     Argument  : reference-to-glob to file or filehandle object

write_MSF
---------

     Title     : write_MSF
     Usage     : $ali->write_MSF(\*FH)
               :
               :
     Function  : writes MSF format output
               :
               :
               :
     Returns   :
     Argument  :

write_Pfam
----------

     Title     : write_Pfam
     Usage     : $ali->write_Pfam(\*OUTPUT)
               :
               :
     Function  : writes a Pfam/Mul formatted
               : file
               :
               :
     Returns   :
     Argument  :

write_selex
-----------

     Title     : write_selex
     Usage     : $ali->write_selex(\*OUTPUT)
               :
               :
     Function  : writes a selex (hmmer) formatted alignment
               :
     Returns   :
     Argument  : reference-to-glob to file or filehandle object

Generic species object
**********************

NAME
====

   Bio::Species - Generic species object

SYNOPSIS
========

     $species = Bio::Species->new(-classification => [@classification]);
                                     # Can also pass classification
                                     # array to new as below

     $species->classification(qw( sapiens Homo Hominidae
                                  Catarrhini Primates Eutheria
                                  Mammalia Vertebrata Chordata
                                  Metazoa Eukaryota ));

     $genus = $species->genus();

     $bi = $species->binomial();     # $bi is now "Homo sapiens"

     # For storing common name
     $species->common_name("human");

     # For storing subspecies
     $species->sub_species("accountant");

DESCRIPTION
===========

   Provides a very simple object for storing phylogenetic information.
The classification is stored in an array, which is a list of nodes in a
phylogenetic tree.  Access to getting and setting species and genus is
provided, but not to any of the other node types (eg: "phlum", "class",
"order", "family").  There's plenty of scope for making the model more
sophisticated, if this is ever needed.

   A methods are also provided for storing common names, and subspecies.

CONTACT
=======

   James Gilbert email *jgrg@sanger.ac.uk*

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

classification
--------------

     Title   : classification
     Usage   : $self->classification(@class_array);
               @classification = $self->classification();
     Function: Fills or returns the classifcation list in
               the object.  The array provided must be in
               the order SPECIES, GENUS ---> KINGDOM.
               Checks are made that species is in lower case,
               and all other elements are in title case.
     Example : $obj->classification(qw( sapiens Homo Hominidae
               Catarrhini Primates Eutheria Mammalia Vertebrata
               Chordata Metazoa Eukaryota));
     Returns : Classification array
     Args    : Classification array

common_name
-----------

     Title   : common_name
     Usage   : $self->common_name( $common_name );
               $common_name = $self->common_name();
     Function: Get or set the commonn name of the species
     Example : $self->common_name('human')
     Returns : The common name in a string
     Args    : String, which is the common name

species
-------

     Title   : species
     Usage   : $self->species( $species );
               $species = $self->species();
     Function: Get or set the scientific species name.  The species
               name must be in lower case.
     Example : $self->species( 'sapiens' );
     Returns : Scientific species name as string
     Args    : Scientific species name as string

genus
-----

     Title   : genus
     Usage   : $self->genus( $genus );
               $genus = $self->genus();
     Function: Get or set the scientific genus name.  The genus
               must be in title case.
     Example : $self->genus( 'Homo' );
     Returns : Scientific genus name as string
     Args    : Scientific genus name as string

sub_species
-----------

     Title   : sub_species
     Usage   : $obj->sub_species($newval)
     Function:
     Returns : value of sub_species
     Args    : newvalue (optional)

binomial
--------

     Title   : binomial
     Usage   : $binomial = $self->binomial();
               $binomial = $self->binomial('FULL');
     Function: Returns a string "Genus species", or "Genus species subspecies",
               the first argument is 'FULL' (and the species has a subspecies).
     Args    : Optionally the string 'FULL' to get the full name including the
               the subspecies.

NAME
----

   Bio::Tk::GO_Browser.pm - Simplistic browser for GO ontology terms

AUTHORS
-------

   Mark Wilkinson (mwilkinson@gene.pbi.nrc.ca) Plant Biotechnology
Institute, National Research Council of Canada.  Copyright (c) National
Research Council of Canada, October, 2000.

DISCLAIMER
----------

   Anyone who intends to use and uses this software and code acknowledges
and agrees to the following: The National Research Council of Canada
(herein "NRC") disclaims any warranties, expressed, implied, or statutory,
of any kind or nature with respect to the software, including without
limitation any warranty or merchantability or fitness for a particular
purpose.  NRC shall not be liable in any event for any damages, whether
direct or indirect, consequential or incidental, arising from the use of
the software.

SYNOPSIS
--------

     use GO_Browser;
     use Tk;
     use strict;

     Begin();

     MainLoop;

     sub Begin {

     my $Textbox;
     my $GO;

     # create new main window.
     my $mw = MainWindow->new(-title => "GO Ontology Browser");

     # create new textbox with scrollbars
     $Textbox = $mw->Scrolled("Text", -background => "black")->pack(-fill => "both", -expand => 1);

     # alternate method to create new textbox, NOT RECOMMENDED!!
     #$Textbox = $mw->Text(-background => "black")->pack;

     # create new GO browser
     $GO = GO_Browser->new($Textbox, TopWindow => $mw);

     # set up binding of button-2 to retrieve information
       $Textbox->bind("<Button-2>" => sub {
          my $acc = $GO->GOAcc;
          my $term = $GO->Term;
          my $def = $GO->Definition;
          print "Acc = $acc Term = $term Def = $def\n\n";
       });

      }

DESCRIPTION and ACKNOWLEDGEMENTS
--------------------------------

   Fills a Tk::Text widget with a browsable display of the GO ontology
(http://www.geneontology.org/).  Items in red are "branches", while items
in green are "leaves" of the GO ontology tree.  Double-clicking branches
moves you up and down the tree.  Middle-clicking on any element records the
clicked-upon term and definition (if available) and this event can be
trapped by the top-level windowing system to retrieve this info for
whatever external application you are building.

   Unlike previous versions, this browser connects directly to the GO
ontology database.  Therefore it requires no pre-downloading and parsing
of the XML files (halleluja!)

   Because it is connecting "live" there is sometimes a small delay while
the query is being sent over the net.  The number of queries required for
the browser has been mitigated as much as possible by some clever
left-joins written by Dave Block (dblock@gene.pbi.nrc.ca).  Thanks Dave!

CONTACT
-------

   Mark Wilkinson (mwilkinson@gene.pbi.nrc.ca)

Options
-------

     $GO = GO_Browser->new(
       $Textbox,          	# the Tk Text widget
       TopWindow => $mw,   # the top-level window (or undef)
       GO_IP => "headcase.lbl.gov",  # the IP address of your GO database
       GO_dbName => "go"   # the name of the GO database
     );

Methods
-------

     $GO->GOAcc	# returns Accession number of the middle-clicked term
     $GO->Term   # returns the Term name of the middle-clicked term
     $GO->Definition  # returns the associated definition

Frame-based widget for displaying Fasta or Blast hits/HSPs with optional text annotation
****************************************************************************************

NAME
====

   Bio::Tk::HitDisplay - Frame-based widget for displaying Fasta or Blast
hits/HSPs with optional text annotation

SYNOPSIS
========

     use Bio::Tk::HitDisplay;
     ...
     $hds = $parent->HitDisplay(?options?);

DESCRIPTION
===========

   *HitDisplay* is a Frame-based widget which contains a Canvas. When
provided with a list of data structures, each representing a hit of a
query sequence to a database, it draws:

   * A scale

     This is marked in residues (aa for a protein query, nt for a nucleic
     acid query)

   * The query sequence

     Represented as a single green line

   * Database hits

     A line for each Fasta hit, or a group of lines for each Blast hit (one
     per HSP)

   The coordinates of the hits/HSPs on the subject sequence (i.e. the
sequence in the database) are indicated below the ends of each line.

   The *HitDisplay* delegates all standard options to the Canvas contained
within it. The non-standard options for *HitDisplay* are:

*-hitdata* => \@hitdata
     The structure of each element of this list is quite complex. They are
     normally generated from object(s) representing Blast or Fasta hits
     e.g.

          Bio::PSU::IO::Blast::Hit
          Bio::PSU::IO::Fasta::Hit

     by their respective adapters

          Bio::PSU::IO::Blast::HitAdapter
          Bio::PSU::IO::Fasta::HitAdapter

     This is normally hidden, unless you want to go and look.

     Each element is a reference to a hash containing the following keys
     and values:

          { q_id     => 'query id',
          	    s_id     => 'subject id',
          	    expect   => 'expect value',
          	    score    => 'percentage identity',
          	    overlap  => 'length of hit',
          	    q_len    => 'query length',
          	    s_len    => 'subject length',
          	    data     => \@data,
            text     => "Some text",
            callback => $callback }

     @data is a list of references to lists, each of which contains the
     coordinates of a single Fasta hit or Blast HSP on both the query and
     subject sequences.  Each innermost list contains 4 values; the start
     and end coordinates on the query sequence (indices 0 and 1) and the
     start and end coordinates on the subject sequence (indices 2 and 3). A
     Blast hit with 3 HSPs will look like this:

          [ [ q_start1, q_end1, s_start1, s_end1 ],
            [ q_start2, q_end2, s_start2, s_end2 ],
            [ q_start3, q_end3, s_start3, s_end3 ] ]

     The text field may contain any text which should be associated with
     that hit e.g. a more detailed account of the result or of the subject
     sequence. The display of this text is bound to a right mouse button
     click on the subject id in the canvas window. The text will appear
     just below the hit with one click and a subsequent click will hide it
     again.

     The callback is a code reference which, if defined, will be bound to a
     left mouse button click on the subject id in the canvas window.

*-hitcolours* => \%colourhash
     The hits or HSPs will be colour-coded according to percentage identity
     according to the key->value pairs in the colourhash. The default
     values are:

          { 90 => 'red',
          	    80 => 'orange',
          	    60 => 'gold',
          	    40 => 'yellow' }

     This indicates that hits where the query is >= 90% identical to the
     subject will be red, >= 80% will be orange etc. The hash supplied to
     *-hitcolours* will override the defaults.

*-interval* => integer >= 10
     This defines the vertical spacing between hit lines on the canvas. The
     minimum (and default) value is 10.

   Mouse bindings provided:

   * Vertical scrolling

     Wheel-mouse support is provided by binding buttons 4 and 5 to vertical
     scrolling (standard Z-axis mapping under XFree86 on Linux).

   * Panning

     Holding down the middle mouse button while dragging will pan the
     canvas in all directions

   * Display/hide all text annotations

     Double-clicking the left mouse button within the canvas will display
     all text annotations, while double-clicking with the right button will
     hide them. This is slow at the moment, with more than about 20 hits.

   Possible improvements:

   * Speed up opening/closing all text annotations at once

   * Items other than text between the hits

   * Make more of the canvas configurable

     Mouse bindings should be made configurable. Perhaps the canvas items
     making up each hit should be given a unique tag

METHODS
=======

   Interaction with this widget should generally be by means of the
standard Perl/Tk options. Internal methods are documented below.

AUTHOR
======

   Keith James (kdj@sanger.ac.uk)

ACKNOWLEDGEMENTS
================

   See Bio::PSU.pod

COPYRIGHT
=========

   Copyright (C) 2000 Keith James. All Rights Reserved.

DISCLAIMER
==========

   This module is provided "as is" without warranty of any kind. It may
redistributed under the same conditions as Perl itself.

Populate
--------

     Title   : Populate
     Usage   : N/A
     Function: Standard composite Frame-based widget setup.
             : See 'man Tk::composite' for details
     Returns : Nothing
     Args    : Hash reference

draw_align
----------

     Title   : draw_align
     Usage   : N/A
     Function: Draws hit text, line and coords for the hits
     Returns : Nothing
     Args    : Canvas, hitdata hash reference, left margin for text,
             : x coord for lines, y coord for lines, interval between
             : sets of lines (representing 1 Fasta hit or 1+ Blast
             : HSPs), hitcolours hash reference

h_line
------

     Title   : h_line
     Usage   : N/A
     Function: Draws a single hit/HSP line with the subject coords
             : below it
     Returns : Nothing
     Args    : Canvas, hit hash reference, x coord for line,
             : y coord for line, line width, line colour

draw_scale
----------

     Title   : draw_scale
     Usage   : N/A
     Function: Draws scale alongside line representing query
             : sequence
     Returns : Nothing
     Args    : Canvas, hit hash reference, left margin for text
             : x coord for line, y coord for line

deannotate_hit
--------------

     Title   : deannotate_hit
     Usage   : N/A
     Function: Reverses the effect of annotate_hit
     Returns : Nothing
     Args    : Canvas, text item (subject id), text to be inserted
             : in gap, interval between hits

annotate_hit
------------

     Title   : annotate_hit
     Usage   : N/A
     Function: Displays hit annotation below a hit line by shuffling
             : all canvas elements down the canvas and placing the
             : annotation text in the gap
     Returns : Nothing
     Args    : Canvas, text item (subject id), text to be inserted
             : in gap, interval between hits

AUTHORS
-------

   Mark Wilkinson (mwilkinson@gene.pbi.nrc.ca), David Block
(dblock@gene.pbi.nrc.ca) Plant Biotechnology Institute, National Research
Council of Canada.  Copyright (c) National Research Council of Canada,
October, 2000.

DISCLAIMER
----------

   Anyone who intends to use and uses this software and code acknowledges
and agrees to the following: The National Research Council of Canada
(herein "NRC") disclaims any warranties, expressed, implied, or statutory,
of any kind or nature with respect to the software, including without
limitation any warranty or merchantability or fitness for a particular
purpose.  NRC shall not be liable in any event for any damages, whether
direct or indirect, consequential or incidental, arising from the use of
the software.

SYNOPSIS
--------

     # To create a BioSeq map and return a handle to the map object:

     use Tk;
     Begin();
     MainLoop;

     sub Begin {

     # set up the Tk Windows
      	   my $MW = MainWindow = MainWindow->new (-title => "Map Of BioSeq Object");
      	   my $Frame = $MW->Frame()->pack(-side => 'top');
      	   my $lblSysMess = $MW->Label()->pack(-side => 'bottom', -fill => 'both');

     # create a BioSeq object
        my $SIO = Bio::SeqIO->new(-file=> 'genbankfile.gb', -format => 'GenBank');
        my $SeqObj = $SIO->next_seq();

     my $axis_length = 800;  # how large I want the final map to be

     # Draw the Map

     $MapObj = SeqCanvas->new(
     			$axis_length,
     			$Frame,
     			$lblSysMess,
     			$SeqObj,
     			-orientation => 'vertical'
     			label => 'primary_id');

     # SeqCanvas returns object reference for success
     # returns -1 for failed initiation - no $SeqObj supplied
     # returns -2 for bad sequence object
     # returns -3 sequence has length 0
     # returns -4 if orientation is uninterpretable
     # returns -5 if supplied frame object is not a TK::frame

     }

DESCRIPTION and ACKNOWLEDGEMENTS
--------------------------------

   Creates an interactive scalable/zoomable map of all features and
subfeatures of a Bio::SeqI compliant object. Basic functionality for
selecting single and multiple map objects is inherent in the object
itself: left-mouse click to select, SHIFT-left-mouse to select multiple.
All other Tk Events are passed back up to the MainWindow object and can be
trapped/bound by the user as they see fit.  Colors and axis-offsets of
mapped objects are assigned based on the "source" tag of the feature
object. These are assigned "on the fly" based on whatever is contained in
the BioSeq object provided.

   This module requires an updated version of Gregg Helt's original
BioTkPerl modules(version 0.81) which are available from BioPerl.  The
original BioTkPerl (version 0.80) is Copyright (c) Gregg Helt, 1995;
Version 0.81 was generated by Mark Wilkinson, PBI-NRC, Oct., 2000.

   Zooming routines/events in this module are conceptually based on the
Zoom routines from Genotator (Copyright (c) 1996, The Regents of the
University of California.  Harris, N.L. (1997), Genome Research
7(7):754-762)

CONTACT
-------

   Mark Wilkinson (mwilkinson@gene.pbi.nrc.ca) and Dave Block
(dblock@gene.pbi.nrc.ca)

APPENDIX
--------

   Description of Object tags, SeqCanvas Methods, and trapping Mouse
events.

Object Tags:
------------

   Each map-widget has several "reliable" tags attached to it. These tags
are FIDxxxx, Source and Strand, Type, and Canvas, where:

   * FIDxxxx is the unique identifier for that particular map-widget over
     all maps (even in multiple windows)

   * Source is derived from the "source" tag of the SeqFeature object this
     widget represents

   * Strand is derived from the "strand" tag of the SeqFeature object,
     converted into the GFF standard of +/-/. to represent the three
     possible strand values.

   * Type isthe feature type, derived from the primary_tag of the
     SeqFeature object

   * Map is either 'draft' or 'finished' to represent an object on the
     white or blue maps respectively

   So for example, a map widget might have the tags :

     FID22354 (no space)
     Source GeneMarkHMM (single space separated)
     Strand + (single space separated)
     Type exon ( " )
     Canvas draft ( " )

   If your BioSeq Features are being derived from an external database, it
is possible to also include the unique index number of that database entry
as a fourth tag on the associated map-widget. To do so, create your
SeqFeature objects with an additional tag "id", where the unique databse
index number is the value of this tag. This index number is then attached
to the widget as a fourth tag with the form:

     DB_ID xxxxx (x's represent the unique index value)

   The values of these three/four tags can be retrieved for any selected
object using the getSelectedTags function (see below) in order to relate
mapped objects back to their original database entries.  Using the
selectWithTag or recolorWithTag routines (see below) requires that you
pass the **full tag** as the desired selection (eg. pass "Source
GeneMarkHMM" not just "GeneMarkHMM")

METHODS
-------

new
---

     Title    : new
     Usage    : $MapObj= SeqCanvas->new(
     				$axis_length,
     				$Frame,
     				[$lblSysMess | undef],
     				$SeqObj,
     				-orientation => ['horizontal'|'vertical']
     				[, label => $tag])

     Function : create a map from the Feature object provided
     Returns  : Handle to the Map object
     Args     :
     	    axis_length in pixels,
     	    a Tk::Frame object,
     	    a Tk::Label or undef,
     	    a BioSeqI compliant object,
     	    the orientation for the map,
     	    optionally the SeqFeature tag you wish to
                   use as the label

mapFeatures
-----------

     Title    : mapFeatures
     Usage    : $FeatureIDs = $MapObj->mapFeatures('draft'|'finished',
     					       \@FeatureObj)
     Function : map SeqFeature objects to the 'draft'(white) or
                   'finished' (blue) maps
     Returns  : reference to a list of the FeatureID's of the mapped Features
     Args     : 'draft'|'finished', \@FeatureObj

unmapFeatures
-------------

     Title    : unmapFeatures
     Usage    : my $FeatureObjsRef = $MapObj->unmapFeatures(\@FeatureIDs)
     Function : to remove mapped features from the map display
     Returns  : referenced list of removed $FeatureObj objects

getSelectedIDs
--------------

     Title    : getSelectedIDs
     Usage    : $FeatureIDs = $MapObj->getSelectedIDs
     Function : to retrieve the FeatureID's of
                   all currently selected mapped objects
     Returns  : reference to a list of FeatureID's
     Args     : none

getSelectedTags
---------------

     Title   : getSelectedTags
     Usage   : ($FeatureID, $strand, $source,
     	    $type, $canvas [, $DB_ID]) = $MapObj->getSelectedTags
     Returns : FeatureID, Source, Strand, Type (i.e. Primary_tag),
        Canvas ('draft' or 'finished'),
        and Database_Index (if available).
     Comment : This is to be used for single-selection events only!
     Args    : none

getIDsWithTag       Title    : getIDsWithTag  Usage    : $FeatureIDs = $MapObj->getIDsWithTag(\@taglist)  Function : to retrieve the FeatureID's of all currently selected mapped objects  Returns  : reference to a list of FeatureID's  Args     : a reference to a list of tags (see discussion of proper tag format above)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

getSelectedFeatures
-------------------

     Title   : getSelectedFeatures
     Usage   : $FeatureHashRef = $MapObj->getSelectedFeatures
     Returns : a reference to a hash where the FeatureID is the key,
               and the Bio::SeqFeature Object is the value
     Args : none

getFeaturesWithTag
------------------

     Title   : getFeaturesWithTag
     Usage   : $FeatureHashRef = $MapObj->getFeaturesWithTag(\@taglist)
     Returns : a reference to a hash where the FeatureID is the
               key, and the Bio::SeqFeature Object is the value
     Args    : reference to a list of valid tags
               (see discussion of proper tag format)

clearSelections
---------------

     Title    : clearSelections
     Usage    : $MapObj->clearSelections
     Function : Clear all selection boxes and "selected" status of all Features.
     Returns  : nothing
     Args     : none

selectFeatures
--------------

     Title    : selectFeatures
     Usage    : $MapObj->selectFeatures(\@FeatureIDs)
     Function : "select" all Features with @FeatureID id's
     Args     : @FeatureIDs - a list of valid
                FeatureIDs (of the form FIDnnn where nnn is a unique integer)

selectWithTag
-------------

     Title    : selectWithTag
     Usage    : $MapObj->selectWithTag(\@tag_list [,'draft'|'finished'])
     Function : "select" all features which have any of @tag_list tags.
     Args     : @taglist, and optional 'draft' or 'finished' which map

recolorWithTag
--------------

     Title    : recolorWithTag
     Usage    : $MapObj->recolorWithTag('#XXXXXX'|'default', 'draft'|'finished', \@tag_list)
     Function : change the color of mapped objects having one of @tag_list tags.
     Returns  : nothing
     Args     :
     	First arg:hex-reference to an RGB color value, or 'default'.
     	Second arg: the canvas ('draft', or 'finished')
     	Third arg: a referenced list of tags.

assignCustomColors
------------------

     Title    : assignCustomColors
     Usage    : $MapObj->assignCustomColors($top)
     Function : change the default map-color for a selected widgets "Source" tag.
     Returns  : nothing
     Args     : a reference to a Tk::MainWindow object (new or existing).

is_draft_feature
----------------

     Title    : is_draft_feature
     Usage    : $result = $MapObj->is_draft_feature($FeatureID)
     Function : check if a $FeatureID is on the draft (white) map.
     Returns  : 1 for true, undef for false
     Args     : the FeatureID you are querying

is_finished_feature
-------------------

     Title    : is_finished_feature
     Usage    : $result = $MapObj->is_finished_feature($FeatureID)
     Function : check if $FeatureID is on the finished (blue) map.
     Returns  : 1 for true, undef for false
     Args     : the FeatureID you are querying

EVENTS
======

   The SeqCanvas both internally responds to mouse events, and sets "tags"
on the mapped feature in response to mouse events such that the user can
"trap" these events in the top-level windowing system and evaluate which
mapped feature the user was manupulating.

Mouse-Click
-----------

   Clicking or shift-Clicking the left mouse button over a mapped feature
causes the feature(s) to become "selected".  A selected object is
displayed on the screen with a black box surrounding the object, and the
object becomes tagged with a testable tag "selected" (use the
getSelectedFeatures or getSelectedIDs to retrieve additional information
about this object)

Mouse-Double-Click
------------------

   Both Double-clicking and Shift Double-Clicking the mouse over an object
selects that (single) mapped feature. All other features become unselected.

Mouse-Click and Drag
--------------------

   Used to select multiple objects. Any object touched by the bounding box
will be included in the selection.

Mouse-Over
----------

   As the mouse pointer enters the mapped widget, the tag "Mouse_over" is
added to this object. information about this object could be retrieved by,
for example, calling the getIDsWithTag(["Mouse_over"]) method. This tag is
removed when the mouse pointer leaves the mapped-feature space. Bind the
<Movement> event in the top-level windowing system to track the mouse
movements if you wish to monitor the Mouse-Over widget events.

Base object for alignment factories
***********************************

NAME
====

   Bio::Tools::AlignFactory - Base object for alignment factories

SYNOPSIS
========

   You wont be using this as an object, but using a dervied class like
Bio::Tools::pSW

DESCRIPTION
===========

   Holds common Alignment Factory attributes in place

CONTACT
=======

   http://bio.perl.org/ or birney@sanger.ac.uk

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

kbyte
-----

     Title     : kbyte()
     Usage     : set/gets the amount of memory able to be used
     Function  :
               : $factory->kbyte(200);
               :
     Returns   :
     Argument  : memory in kilobytes

report
------

     Title     : report()
     Usage     : set/gets the report boolean to issue reports or not
     Function  :
               : $factory->report(1); # reporting goes on
               :
     Returns   : n/a
     Argument  : 1 or 0

set_memory_and_report
---------------------

     Title   : set_memory_and_report
     Usage   : Only used by subclasses.
     Function:
     Example :
     Returns :
     Args    :

Base class for analysis result objects and parsers
**************************************************

NAME
====

   Bio::Tools::AnalysisResult - Base class for analysis result objects and
parsers

SYNOPSIS
========

     # obtain a AnalysisResult derived object somehow
     print "Method ", $result->analysis_method(),
           ", version " $result->analysis_method_version(),
           ", performed on ", $result->analysis_date(), "\n";
     # annotate a sequence utilizing SeqAnalysisParserI methods
     while($feat = $result->next_feature()) {
     	$seq->add_SeqFeature($feat);
     }
     $result->close();
     # query object, e.g. a Bio::SeqI implementing object
     $queryseq = $result->analysis_query();
     # Subject of the analysis -- may be undefined. Refer to derived module
     # to find out what is returned.
     $subject = $result->analysis_subject();

DESCRIPTION
===========

   The AnalysisResult module is supposed to be the base class for modules
encapsulating parsers and interpreters for the result of a analysis that
was carried out with a query sequence.

   The notion of an analysis represented by this base class is that of a
unary or binary operator, taking either one query or a query and a subject
and producing a result. The query is e.g. a sequence, and a subject is
either a sequence, too, or a database of sequences.

   This module also implements the Bio::SeqAnalysisParserI interface, and
thus can be used wherever such an object fits. See
Bio/SeqAnalysisParserI.  Developers will find a
ready-to-use `parse' in this node() method, but need to implement
next_feature() in an inheriting class. Support for initialization with
input file names and reading from streams is also ready to use.

   Note that this module does not provide support for running an analysis.
Rather, it is positioned in the subsequent parsing step (concerned with
turning raw results into BioPerl objects).

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp
====================

   Email hlapp@gmx.net

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

_initialize_state
-----------------

     Title   : _initialize_state
     Usage   : n/a; usually called by _initialize()
     Function: This method is for BioPerl B<developers> only, as indicated by the
               leading underscore in its name.

     Performs initialization or reset of the state of this object. The
     difference to L<_initialize>() is that it may be called at any time,
     and repeatedly within the lifetime of this object. B<Note, however,
     that this is potentially dangerous in a multi-threading
     environment. In general, calling this method twice is discouraged
     for this reason.

     This method is supposed to reset the state such that any 'history'
     is lost. State information that does not change during object
     lifetime is not considered as history, e.g. parent, name, etc shall
     not be reset. An inheriting object should only be concerned with
     state information it introduces itself, and for everything else
     call SUPER::_initialize_state(@args).

     An example is parsing an input file: a state reset implies
     discarding any unread input, and the actual input itself, followed
     by setting the new input.

     The argument syntax is the same as for L<new>() and L<_initialize>(),
     i.e., named parameters following the -name=>$value convention.
     The following parameters are dealt with by the implementation
     provided here:
        -INPUT, -FH, -FILE
     (tags are case-insensitive).
      Example :
      Returns :
      Args    :

analysis_query
--------------

     Usage     : $query_obj = $result->analysis_query();
     Purpose   : Set/Get the name of the query used to generate the result, that
                 is, the entity on which the analysis was performed. Will mostly
                 be a sequence object (Bio::PrimarySeq compatible).
     Argument  :
     Returns   : The object set before. Mostly a Bio::PrimarySeq compatible object.

analysis_subject
----------------

     Usage     : $result->analyis_subject();
     Purpose   : Set/Get the subject of the analysis against which it was
                 performed. For similarity searches it will probably be a database,
                 and for sequence feature predictions (exons, promoters, etc) it
                 may be a collection of models or homologous sequences that were
                 used, or undefined.
     Returns   : The object that was set before, or undef.
     Argument  :

analysis_date
-------------

     Usage     : $result->analysis_date();
     Purpose   : Set/Get the date on which the analysis was performed.
     Returns   : String
     Argument  :
     Comments  :

analysis_method
---------------

     Usage     : $result->analysis_method();
     Purpose   : Set/Get the name of the sequence analysis method that was used
                 to produce this result (BLASTP, FASTA, etc.). May also be the
                 actual name of a program.
     Returns   : String
     Argument  : n/a

analysis_method_version
-----------------------

     Usage     : $result->analysis_method_version();
     Purpose   : Set/Get the version string of the analysis program.
               : (e.g., 1.4.9MP, 2.0a19MP-WashU).
     Returns   : String
     Argument  : n/a

Lightweight BLAST parser for pair-wise sequence  alignment using the BLAST algorithm.
*************************************************************************************

NAME
====

   Bio::Tools::BPbl2seq - Lightweight BLAST parser for pair-wise sequence
alignment using the BLAST algorithm.

SYNOPSIS
========

     use Bio::Tools::BPbl2seq;
     my $report = Bio::Tools::BPbl2seq->new(-file => 't/bl2seq.out');
     $report->query;
     $report->score;
     $report->bits;
     $report->percent;
     $report->P;
     $report->match;
     $report->positive;
     $report->length;
     $report->querySeq;
     $report->sbjctSeq;
     $report->homologySeq;
     $report->subject->start;
     $report->subject->end;
     $report->subject->seqname;

DESCRIPTION
===========

   BPbl2seq is a package for parsing BLAST bl2seq reports. BLAST bl2seq is
a program for comparing and aligning two sequences using BLAST.  Although
the report format is similar to that of a conventional BLAST, there are a
few differences so that the standard bioperl BLAST parsers Blast.pm and
BPlite are unable to read bl2seq reports directly.

   From the user's perspective, the main difference between bl2seq and
other blast reports is that the bl2seq report does not print out the name
of the first of the two aligned sequences.  (The second sequence name is
given in the report as the name of the "hit").  Consequently, BPbl2seq has
no way of identifying the name of the initial sequence unless it is passed
to constructor as a second argument as in:

     my $report = Bio::Tools::BPbl2seq->new(\*FH, "ALEU_HORVU");

   If the name of the first sequence is not passed to BPbl2seq.pm in this
manner, the name of the first sequence will be left as "unknown".  (Note
that to preserve a common interface with the other BLAST programs the two
sequences being compared are referred to in bl2seq as "query" and
"subject" although this is perhaps a bit misleading when simply comparing
2 sequences as opposed to querying a database.)

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via  email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Peter Schattner
========================

   Email: schattner@alum.mit.edu

ACKNOWLEDGEMENTS
================

   Based on work of: Ian Korf (ikorf@sapiens.wustl.edu,
http://sapiens.wustl.edu/~ikorf), Lorenz Pollak (lorenz@ist.org, bioperl
port)

COPYRIGHT
=========

   BPlite.pm is copyright (C) 1999 by Ian Korf.

DISCLAIMER
==========

   This software is provided "as is" without warranty of any kind.

new
---

     Title   : new
     Function: Create a new Bio::Tools::BPbl2seq object
     Returns : Bio::Tools::BPbl2seq
     Args    : -file     input file (alternative to -fh)
               -fh       input stream (alternative to -file)
               -queryname    name of query sequence

P
-

     Title    : P
     Usage    : $hsp->P();
     Function : returns the P (significance) value for a HSP
     Example  :
     Returns  : (double) significance value
     Args     :

percent
-------

     Title    : percent
     Usage    : $hsp->percent();
     Function : returns the percent matching
     Example  :
     Returns  : (double) percent matching
     Args     :

match
-----

     Title    : match
     Usage    : $hsp->match();
     Function : returns the match
     Example  :
     Returns  : (double) frac_identical
     Args     :

positive
--------

     Title    : positive
     Usage    : $hsp->positive();
     Function : returns the number of positive hits
     Example  :
     Returns  : (int) number of positive residue hits
     Args     :

querySeq
--------

     Title    : querySeq
     Usage    : $hsp->querySeq();
     Function : returns the query sequence
     Example  :
     Returns  : (string) the Query Sequence
     Args     :

sbjctSeq
--------

     Title    : sbjctSeq
     Usage    : $hsp->sbjctSeq();
     Function : returns the Sbjct sequence
     Example  :
     Returns  : (string) the Sbjct Sequence
     Args     :

homologySeq
-----------

     Title    : homologySeq
     Usage    : $hsp->homologySeq();
     Function : returns the homologous sequence
     Example  :
     Returns  : (string) homologous sequence
     Args     :

qs
--

     Title    : qs
     Usage    : $hsp->qs();
     Function : returns the Query Sequence (same as querySeq)
     Example  :
     Returns  : (string) query Sequence
     Args     :

ss
--

     Title    : ss
     Usage    : $hsp->ss();
     Function : returns the subject sequence ( same as sbjctSeq)
     Example  :
     Returns  : (string) Sbjct Sequence
     Args     :

hs
--

     Title    : hs
     Usage    : $hsp->hs();
     Function : returns the Homologous Sequence (same as homologySeq )
     Example  :
     Returns  : (string) Homologous Sequence
     Args     :

Lightweight BLAST parser
************************

NAME
====

   Bio::Tools::BPlite - Lightweight BLAST parser

SYNOPSIS
========

     use Bio::Tools::BPlite;
     my $report = new BPlite(-fh=>\*STDIN);
     $report->query;
     $report->database;
     while(my $sbjct = $report->nextSbjct) {
         $sbjct->name;
         while (my $hsp = $sbjct->nextHSP) {
             $hsp->score;
             $hsp->bits;
             $hsp->percent;
             $hsp->P;
             $hsp->match;
             $hsp->positive;
             $hsp->length;
     	 $hsp->querySeq;
     	 $hsp->sbjctSeq;
     	 $hsp->homologySeq;
     	 $hsp->query->start;
     	 $hsp->query->end;
     	 $hsp->sbjct->start;
     	 $hsp->sbjct->end;
     	 $hsp->sbjct->seqname;
     	 $hsp->sbjct->overlaps($exon);
         }
     }

DESCRIPTION
===========

   BPlite is a package for parsing BLAST reports. The BLAST programs are a
family of widely used algorithms for sequence database searches. The
reports are non-trivial to parse, and there are differences in the formats
of the various flavors of BLAST. BPlite parses BLASTN, BLASTP, BLASTX,
TBLASTN, and TBLASTX reports from both the high performance WU-BLAST, and
the more generic NCBI-BLAST.

   Many people have developed BLAST parsers (I myself have made at least
three).  BPlite is for those people who would rather not have a giant
object specification, but rather a simple handle to a BLAST report that
works well in pipes.

Object
------

   BPlite has three kinds of objects, the report, the subject, and the
HSP. To create a new report, you pass a filehandle reference to the BPlite
constructor.

     my $report = new BPlite(-fh=>\*STDIN); # or any other filehandle

   The report has two attributes (query and database), and one method
(nextSbjct).

     $report->query;     # access to the query name
     $report->database;  # access to the database name
     $report->nextSbjct; # gets the next subject
     while(my $sbjct = $report->nextSbjct) {
         # canonical form of use is in a while loop
     }

   A subject is a BLAST hit, which should not be confused with an HSP
(below). A BLAST hit may have several alignments associated with it. A
useful way of thinking about it is that a subject is a gene and HSPs are
the exons. Subjects have one attribute (name) and one method (nextHSP).

     $sbjct->name;    # access to the subject name
     "$sbjct";        # overloaded to return name
     $sbjct->nextHSP; # gets the next HSP from the sbjct
     while(my $hsp = $sbjct->nextHSP) {
         # canonical form is again a while loop
     }

   An HSP is a high scoring pair, or simply an alignment.  HSP objects
inherit all the useful methods from RangeI/SeqFeatureI/FeaturePair, but
provide an additional set of attributes (score, bits, percent, P, match,
positive, length, querySeq, sbjctSeq, homologySeq) that should be familiar
to anyone who has seen a blast report.

   For lazy/efficient coders, two-letter abbreviations are available for
the attributes with long names (qs, ss, hs). Ranges of the aligned
sequences in query/subject and other information (like seqname) are stored
in SeqFeature objects (i.e.: $hsp->query, $hsp->sbjct which is equal to
$hsp->feature1, $hsp->feature2). querySeq, sbjctSeq and homologySeq do only
contain the alignment sequences from the blast report.

     $hsp->score;
     $hsp->bits;
     $hsp->percent;
     $hsp->P;
     $hsp->match;
     $hsp->positive;
     $hsp->length;
     $hsp->querySeq;      $hsp->qs;
     $hsp->sbjctSeq;      $hsp->ss;
     $hsp->homologySeq;   $hsp->hs;
     $hsp->query->start;
     $hsp->query->end;
     $hsp->query->seqname;
     $hsp->sbjct->primary_tag; # "similarity"
     $hsp->sbjct->source_tag;  # "BLAST"
     $hsp->sbjct->start;
     $hsp->sbjct->end;
     ...
     "$hsp"; # overloaded for query->start..query->end bits

   I've included a little bit of overloading for double quote variable
interpolation convenience. A subject will return its name and an HSP will
return its query->start, query->end, and bits in the alignment. Feel free
to modify this to whatever is most frequently used by you.

   So a very simple look into a BLAST report might look like this.

     my $report = new BPlite(-fh=>\*STDIN);
     while(my $sbjct = $report->nextSbjct) {
         print "$sbjct\n";
         while(my $hsp = $sbjct->nextHSP) {
     	 	print "\t$hsp\n";
         }
     }

   The output of such code might look like this:

     >foo
         100..155 29.5
         268..300 20.1
     >bar
         100..153 28.5
         265..290 22.1

AUTHORS
=======

   Ian Korf (ikorf@sapiens.wustl.edu, http://sapiens.wustl.edu/~ikorf),
Lorenz Pollak (lorenz@ist.org, bioperl port)

ACKNOWLEDGEMENTS
================

   This software was developed at the Genome Sequencing Center at
Washington Univeristy, St. Louis, MO.

COPYRIGHT
=========

   Copyright (C) 1999 Ian Korf. All Rights Reserved.

DISCLAIMER
==========

   This software is provided "as is" without warranty of any kind.

new
---

     Title   : new
     Function: Create a new Bio::Tools::BPlite object
     Returns : Bio::Tools::BPlite
     Args    : -file     input file (alternative to -fh)
               -fh       input stream (alternative to -file)

next_feature
------------

     Title   : next_feature
     Usage   : while( my $feat = $res->next_feature ) { # do something }
     Function: SeqAnalysisParserI implementing function
     Example :
     Returns : A Bio::SeqFeatureI compliant object, in this case,
               each DomainUnit object, ie, flattening the Sequence
               aspect of this.
     Args    : None

query
-----

     Title    : query
     Usage    : $query = $obj->query();
     Function : returns the query object
     Example  :
     Returns  : query object
     Args     :

qlength
-------

     Title    : qlength
     Usage    : $len = $obj->qlength();
     Function : returns the length of the query
     Example  :
     Returns  : length of query
     Args     :

pattern
-------

     Title    : database
     Usage    : $pattern = $obj->pattern();
     Function : returns the pattern used in a PHIBLAST search

query_pattern_location
----------------------

     Title    : query_pattern_location
     Usage    : $qpl = $obj->query_pattern_location();
     Function : returns reference to array of locations in the query sequence
                of pattern used in a PHIBLAST search

database
--------

     Title    : database
     Usage    : $db = $obj->database();
     Function : returns the database used in this search
     Example  :
     Returns  : database used for search
     Args     :

nextSbjct
---------

     Title    : nextSbjct
     Usage    : $sbjct = $obj->nextSbjct();
     Function : Method of iterating through all the Sbjct retrieved
                from parsing the report
     Example  : while ( my $sbjct = $obj->nextSbjct ) {}
     Returns  : next Sbjct object or null if finished
     Args     :

P
-

     Title    : P
     Usage    : $hsp->P();
     Function : returns the P (significance) value for a HSP
     Example  :
     Returns  : (double) significance value
     Args     :

percent
-------

     Title    : percent
     Usage    : $hsp->percent();
     Function : returns the percent matching
     Returns  : (double) percent matching
     Args     : none

match
-----

     Title    : match
     Usage    : $hsp->match();
     Function : returns the match
     Example  :
     Returns  : (double) frac_identical
     Args     :

positive
--------

     Title    : positive
     Usage    : $hsp->positive();
     Function : returns the number of positive hits
     Returns  : (int) number of positive residue hits
     Args     : none

querySeq
--------

     Title    : querySeq
     Usage    : $hsp->querySeq();
     Function : returns the query sequence
     Returns  : (string) the Query Sequence
     Args     : none

sbjctSeq
--------

     Title    : sbjctSeq
     Usage    : $hsp->sbjctSeq();
     Function : returns the Sbjct sequence
     Returns  : (string) the Sbjct Sequence
     Args     : none

homologySeq
-----------

     Title    : homologySeq
     Usage    : $hsp->homologySeq();
     Function : returns the homologous sequence
     Returns  : (string) homologous sequence
     Args     : none

qs
--

     Title    : qs
     Usage    : $hsp->qs();
     Function : returns the Query Sequence (same as querySeq)
     Returns  : (string) query Sequence
     Args     : none

ss
--

     Title    : ss
     Usage    : $hsp->ss();
     Function : returns the subject sequence ( same as sbjctSeq)
     Returns  : (string) Sbjct Sequence
     Args     : none

hs
--

     Title    : hs
     Usage    : $hsp->hs();
     Function : returns the Homologous Sequence (same as homologySeq )
     Returns  : (string) Homologous Sequence
     Args     : none

object for parsing single iteration of a PSIBLAST report
********************************************************

NAME
====

   Bio::Tools:: BPlite::Iteration - object for parsing single iteration of
a PSIBLAST report

SYNOPSIS
========

     use Bio::Tools:: BPpsilite;

     open FH, "t/psiblastreport.out";
     $report = Bio::Tools::BPpsilite->new(-fh=>\*FH);

     # determine number of iterations executed by psiblast
     $total_iterations = $report->number_of_iterations;
     $last_iteration = $report->round($total_iterations);

     # Process only hits found in last iteration ...
     $oldhitarray_ref = $last_iteration->oldhits;
     HIT: while($sbjct = $last_iteration->nextSbjct) {
         $id = $sbjct->name;
         $is_old =  grep  /\Q$id\E/, @$oldhitarray_ref;
         if ($is_old ){next HIT;}
     #  do something with new hit...
     }

DESCRIPTION
===========

   See the documentation for BPpsilite.pm for a description of the
Iteration.pm module.

AUTHORS - Peter Schattner
=========================

   Email: schattner@alum.mit.edu

ACKNOWLEDGEMENTS
================

   Based on work of: Ian Korf (ikorf@sapiens.wustl.edu,
http://sapiens.wustl.edu/~ikorf), Lorenz Pollak (lorenz@ist.org, bioperl
port)

COPYRIGHT
=========

   BPlite.pm is copyright (C) 1999 by Ian Korf.

DISCLAIMER
==========

   This software is provided "as is" without warranty of any kind.

query
-----

     Title    : query
     Usage    : $query = $obj->query();
     Function : returns the query object
     Example  :
     Returns  : query object
     Args     :

qlength
-------

     Title    : qlength
     Usage    : $len = $obj->qlength();
     Returns  : length of query
     Args     : none

newhits
-------

     Title    :  newhits
     Usage    : $newhits = $obj->newhits();
     Returns  : reference to an array listing all the hits
                from the current iteration which were not identified
                in the previous iteration
     Args     : none

oldhits
-------

     Title    :  oldhits
     Usage    : $oldhits = $obj->oldhits();
     Returns  : reference to an array listing all the hits from
                the current iteration which were identified and
                above threshold in the previous iteration
     Args     : none

nextSbjct
---------

     Title    : nextSbjct
     Usage    : $sbjct = $obj->nextSbjct();
     Function : Method of iterating through all the Sbjct retrieved
                from parsing the report
     Example  : while ( my $sbjct = $obj->nextSbjct ) {}
     Returns  : next Sbjct object or undef if finished
     Args     :

name
----

     Title    : name
     Usage    : $name = $obj->name();
     Function : returns the name of the Sbjct
     Example  :
     Returns  : name of the Sbjct
     Args     :

nextFeaturePair
---------------

     Title    : nextFeaturePair
     Usage    : $name = $obj->nextFeaturePair();
     Function : same as the nextHSP function
     Example  :
     Returns  : next FeaturePair
     Args     :

nextHSP
-------

     Title    : nextHSP
     Usage    : $hsp = $obj->nextHSP();
     Function : returns the next available High Scoring Pair
     Example  :
     Returns  : Bio::Tools::HSP  or null if finished
     Args     :

Lightweight BLAST parser for (iterated) psiblast reports
********************************************************

NAME
====

   Bio::Tools:: BPpsilite - Lightweight BLAST parser for (iterated)
psiblast reports

SYNOPSIS
========

     use Bio::Tools::BPpsilite;
     open FH, "t/psiblastreport.out";
     $report = Bio::Tools::BPpsilite->new(-fh=>\*FH);

     # determine number of iterations executed by psiblast
     $total_iterations = $report->number_of_iterations;
     $last_iteration = $report->round($total_iterations);

     # Process only hits found in last iteration ...
      $oldhitarray_ref = $last_iteration->oldhits;
      HIT: while($sbjct = $last_iteration->nextSbjct) {
     	  $id = $sbjct->name;
     	  $is_old =  grep  /\Q$id\E/, @$oldhitarray_ref;
     	  if ($is_old ){next HIT;}
     #  do something with new hit...
     }

DESCRIPTION
===========

   BPpsilite is a package for parsing multiple iteration PSIBLAST reports.
It is based closely on Ian Korf's BPlite.pm module for parsing single
iteration BLAST reports (as modified by Lorenz Pollak).

   Two of the four basic objects of BPpsilite.pm are identical to the
corresponding objects in BPlite - the "HSP.pm" and "Sbjct.pm" objects.
This DESCRIPTION documents only the one new object, the "iteration", as
well as the additional methods that are implemented in BPpsilite that are
not in BPlite.  See the BPlite documentation for information on the
BPlite, SBJCT and HSP objects.

   The essential difference between PSIBLAST and the other BLAST programs
(in terms of report parsing) is that PSIBLAST performs multiple iterations
of the BLASTing of the database and the results of all of these iterations
are stored in a single PSIBLAST report.  (For general information on
PSIBLAST see the README.bla file in the standalone BLAST distribution and
references therein). PSIBLAST's use of multiple iterations imposes
additional demands on the report parser: * There are several iterations of
hits.  Many of those hits will be repeated in more than one iteration.
Often only the last iteration will be of interest.  * Each iteration will
list two different kinds of hits - repeated hits that were used in the
model and newly identified hits - which may need to be processed in
different manners * The total number of iterations performed is not
displayed in the report until (almost) the very end of the report.  (The
user can specify a maximum number of iterations for the PSIBLAST search,
but the program may perform fewer iterations if convergence is reached)

   BPpsilite addresses these issues by offering the following methods:

   * The total number of iteration used is given by the method
number_of_iterations as in:

     $total_iterations = $report->number_of_iterations;

   * Results from an arbitrary iteration round can be accessed by using
the 'round' method:

     $iteration3_report = $report->round(3);

   * The ids of the sequences which passed the significance threshold for
the first time in the "nth" iteration can be identified by using the
newhits method.  Previously identified hits are identified by using   the
oldhits method, as in:

     $oldhitarray_ref = $iteration3_report->oldhits;
     $newhitarray_ref = $iteration3_report->newhits;

   BPpsilite.pm should work equally well on reports generated by the
StandAloneBlast.pm local BLAST module as with reports generated by remote
psiblast searches. For examples of usage of BPpsilite.pm, the user is
referred to the BPpsilite.t script in the "t" directory.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org              - General discussion
     http://bio.perl.org/MailList.html  - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Peter Schattner
========================

   Email: schattner@alum.mit.edu

ACKNOWLEDGEMENTS
================

   Based on work of: Ian Korf (ikorf@sapiens.wustl.edu,
http://sapiens.wustl.edu/~ikorf), Lorenz Pollak (lorenz@ist.org, bioperl
port)

COPYRIGHT
=========

   BPlite.pm is copyright (C) 1999 by Ian Korf.

DISCLAIMER
==========

   This software is provided "as is" without warranty of any kind.

query
-----

     Title    : query
     Usage    : $query = $obj->query();
     Function : returns the query object
     Returns  : query object
     Args     :

qlength
-------

     Title    : qlength
     Usage    : $len = $obj->qlength();
     Function : returns the length of the query
     Returns  : length of query
     Args     :

database
--------

     Title    : database
     Usage    : $db = $obj->database();
     Function : returns the database used in this search
     Returns  : database used for search
     Args     :

number_of_iterations
--------------------

     Title    : number_of_iterations
     Usage    : $total_iterations = $obj-> number_of_iterations();
     Function : returns the total number of iterations used in this search
     Returns  : total number of iterations used for search
     Args     : none

pattern
-------

     Title    : database
     Usage    : $pattern = $obj->pattern();
     Function : returns the pattern used in a PHIBLAST search

query_pattern_location
----------------------

     Title    : query_pattern_location
     Usage    : $qpl = $obj->query_pattern_location();
     Function : returns reference to array of locations in the query sequence
                of pattern used in a PHIBLAST search

round
-----

     Title    : round
     Usage    : $Iteration3 = $report->round(3);
     Function : Method of retrieving data from a specific iteration
     Example  :
     Returns  : reference to requested Iteration object or null if argument
     		is greater than total number of iterations
     Args     : number of the requested iteration

_preprocess
-----------

     Title    : _preprocess
     Usage    : internal routine, not called directly
     Function :  determines number of iterations in report and prepares
     	data so individual iterations canbe parsed in non-sequential order
     Example  :
     Returns  :  nothing. Sets TOTAL_ITERATION_NUMBER in object's hash
     Args     :  reference to calling object

Bioperl BLAST sequence analysis object
**************************************

NAME
====

   Bio::Tools::Blast.pm - Bioperl BLAST sequence analysis object

SYNOPSIS
========

Parsing Blast reports
---------------------

   Parse an existing Blast report from file:

     use Bio::Tools::Blast;

     $blastObj = Bio::Tools::Blast->new( -file   => '/tmp/blast.out',
     					-parse  => 1,
     					-signif => '1e-10',
     					);

   Parse an existing Blast report from STDIN:

     $blastObj = Bio::Tools::Blast->new( -parse  => 1,
     					-signif => '1e-10',
     					);

   Then send a Blast report to your script via STDIN.

   Full parameters for parsing Blast reports.

     %blastParam = (
     		-run             => \%runParam,
     		-file            => '',
     		-parse           => 1,
     		-signif          => 1e-5,
     		-filt_func       => \&my_filter,
     		-min_len         => 15,
     		-check_all_hits  => 0,
     		-strict          => 0,
     		-stats           => 1,
     		-best            => 0,
     		-share           => 0,
     		-exec_func       => \&process_blast,
     		-save_array      => \@blast_objs,  # not used if -exce_func defined.
     	       );

   See `parse' in this node() for a description of parameters and see
`USAGE' in this node for more examples including how to parse streams
containing multiple Blast reports `Using the Static $Blast Object' in this
node.

   See `Memory Usage Issues' in this node for information about how to
make Blast parsing be more memory efficient.

Running Blast reports
---------------------

   Run a new Blast2 at NCBI and then parse it:

     %runParam = (
     		  -method   => 'remote',
     		  -prog     => 'blastp',
     		  -database => 'swissprot',
     		  -seqs     => [ $seq ],  # Bio::Seq.pm objects.
     		  );

     $blastObj = Bio::Tools::Blast->new( -run     => \%runParam,
     					-parse   => 1,
     					-signif  => '1e-10',
     					-strict  => 1,
     					);

   Full parameters for running Blasts at NCBI using Webblast.pm:

     %runParam = (
     	      -method   => 'remote',
     	      -prog     => 'blastp',
     	      -version  => 2,      # BLAST2
     	      -database =>'swissprot',
     	      -html     => 0,
     	      -seqs     => [ $seqObject ],  # Bio::Seq.pm object(s)
     	      -descr    => 250,
     	      -align    => 250,
     	      -expect   => 10,
     	      -gap      => 'on',
     	      -matrix   => 'PAM250',
     	      -email    => undef,  # don't send report via e-mail if parsing.
     	      -filter   => undef,  # use default
     	      -gap_c    => undef,  # use default
     	      -gap_e    => undef,  # use default
     	      -word     => undef,  # use default
     	      -min_len  => undef,  # use default
     	      );

   See `run' in this node() and `USAGE' in this node for more information
about running Blasts.

HTML-formatting Blast reports
-----------------------------

   Print an HTML-formatted version of a Blast report:

     use Bio::Tools::Blast qw(:obj);

     $Blast->to_html($filename);
     $Blast->to_html(-file   => $filename,
     		    -header => "<H1>Blast Results</H1>");
     $Blast->to_html(-file   => $filename,
     		    -out    => \@array);  # store output
     $Blast->to_html();  # use STDIN

   Results are sent directly to STDOUT unless an `-out => array_ref'
parameter is supplied. See `to_html' in this node() for details.

INSTALLATION
============

   This module is included with the central Bioperl distribution:

     http://bio.perl.org/Core/Latest
     ftp://bio.perl.org/pub/DIST

   Follow the installation instructions included in the README file.

DESCRIPTION
===========

   The Bio::Tools::Blast.pm module encapsulates data and methods for
running, parsing, and analyzing pre-existing BLAST reports. This module
defines an application programming interface (API) for working with Blast
reports. A Blast object is constructed from raw Blast output and
encapsulates the Blast results which can then be accessed via the
interface defined by the Blast object.

   The ways in which researchers use Blast data are many and varied. This
module attempts to be general and flexible enough to accommodate different
uses. The Blast module API is still at an early stage of evolution and I
expect it to continue to evolve as new uses for Blast data are developed.
Your `FEEDBACK' in this node is welcome.

   *FEATURES:*

   * Supports NCBI Blast1.x, Blast2.x, and WashU-Blast2.x, gapped and
     ungapped.

     Can parse HTML-formatted as well as non-HTML-formatted reports.

   * Launch new Blast analyses remotely or locally.

     Blast objects can be constructed directly from the results of the
     run. See `run' in this node().

   * Construct Blast objects from pre-existing files or from a new run.

     Build a Blast object from a single file or build multiple Blast
     objects from an input stream containing multiple reports. See `parse'
     in this node().

   * Add hypertext links from a BLAST report.

     See `to_html' in this node().

   * Generate sequence and sequence alignment objects from HSP sequences.

     If you have Bio::Seq.pm and Bio::UnivAln.pm installed on your system,
     they can be used for working with high-scoring segment pair (HSP)
     sequences in the Blast alignment.  (A new version of Bio::Seq.pm is
     included in the distribution, see `INSTALLATION' in this node).  For
     more information about them, see:

          http://bio.perl.org/Projects/Sequence/
          http://bio.perl.org/Projects/SeqAlign/

   A variety of different data can be extracted from the Blast report by
querying the Blast.pm object. Some basic examples are given in the `USAGE'
in this node section. For some working scripts, see the links provided in
the `DEMO SCRIPTS' in this node section.

   As a part of the incipient Bioperl framework, the Bio::Tools::Blast.pm
module inherits from *Bio::Tools::SeqAnal.pm*, which provides some generic
functionality for biological sequence analysis. See the documentation for
that module for details (`Links to related modules' in this node).

The BLAST Program
-----------------

   BLAST (Basic Local Alignment Search Tool) is a widely used algorithm
for performing rapid sequence similarity searches between a single DNA or
protein sequence and a large dataset of sequences.  BLAST analyses are
typically performed by dedicated remote servers, such as the ones at the
NCBI. Individual groups may also run the program on local machines.

   The Blast family includes 5 different programs:

     Query Seq        Database
                  ------------     ----------
      blastp  --  protein          protein
      blastn  --  nucleotide       nucleotide
      blastx  --  nucleotide*      protein
      tblastn --  protein          nucleotide*
      tblastx --  nucleotide*      nucleotide*

     * = dynamically translated in all reading frames, both strands

   See `References & Information about the BLAST program' in this node.

Versions Supported
------------------

   BLAST reports generated by different application front ends are similar
but not exactly the same. Blast reports are not intended to be exchange
formats, making parsing software susceptible to obsolescence. This module
aims to support BLAST reports generated by different implementations:

     Implementation    Latest version tested
     --------------    --------------------
     NCBI Blast1       1.4.11   [24-Nov-97]
     NCBI Blast2       2.0.8    [Jan-5-1999]
     WashU-BLAST2      2.0a19MP [05-Feb-1998]
     GCG               1.4.8    [1-Feb-95]

   Support for both gapped and ungapped versions is included. Currently,
there is only rudimentary support for PSI-BLAST in that these reports can
be parsed but there is no special treatment of separate iteration rounds
(they are all merged together).

References & Information about the BLAST program
------------------------------------------------

   *WEBSITES:*

     http://www.ncbi.nlm.nih.gov/BLAST/                 - Homepage at NCBI
     http://www.ncbi.nlm.nih.gov/BLAST/blast_help.html  - Help manual
     http://blast.wustl.edu/                            - WashU-Blast2

   *PUBLICATIONS:* (with PubMed links)

     Altschul S.F., Gish W., Miller W., Myers E.W., Lipman D.J. (1990).
     "Basic local alignment search tool", J Mol Biol 215: 403-410.

http://www.ncbi.nlm.nih.gov/htbin-post/Entrez/query?uid=2231712&form=6&db=m&Dopt=r

     Altschul, Stephen F., Thomas L. Madden, Alejandro A. Schaffer,
     Jinghui Zhang, Zheng Zhang, Webb Miller, and David J. Lipman (1997).
     "Gapped BLAST and PSI-BLAST: a new generation of protein database
     search programs", Nucleic Acids Res. 25:3389-3402.

http://www.ncbi.nlm.nih.gov/htbin-post/Entrez/query?uid=9254694&form=6&db=m&Dopt=r

     Karlin, Samuel and Stephen F. Altschul (1990).  Methods  for
     assessing the statistical significance of molecular sequence
     features by using general scoring schemes. Proc. Natl. Acad.
     Sci. USA 87:2264-68.

http://www.ncbi.nlm.nih.gov/htbin-post/Entrez/query?uid=2315319&form=6&db=m&Dopt=b

     Karlin, Samuel and Stephen F. Altschul (1993).  Applications
     and statistics for multiple high-scoring segments in molecu-
     lar sequences. Proc. Natl. Acad. Sci. USA 90:5873-7.

http://www.ncbi.nlm.nih.gov/htbin-post/Entrez/query?uid=8390686&form=6&db=m&Dopt=b

USAGE
=====

Creating Blast objects
----------------------

   A Blast object can be constructed from the contents of a Blast report
using a set of named parameters that specify significance criteria for
parsing.  The report data can be read in from an existing file specified
with the `-file => 'filename'' parameter or from a STDIN stream containing
potentially multiple Blast reports. If the `-file' parameter does not
contain a valid filename, STDIN will be used. Separate Blast objects will
be created for each report in the stream.

   To parse the report, you must include a `-parse => 1' parameter in
addition to any other parsing parameters See `parse' in this node() for a
full description of parsing parameters.  To run a new report and then
parse it, include a `-run => \%runParams' parameter containing a reference
to a hash that hold the parameters required by the `run' in this node()
method.

   The constructor for Blast objects is inherited from
Bio::Tools::SeqAnal.pm.  See the _initialize() method of that package for
general information relevant to creating Blast objects. (The new() method,
inherited from *Bio::Root::Object.pm*, calls _initialize(). See `Links to
related modules' in this node).

   The Blast object can read compressed (gzipped) Blast report files.
Compression/decompression uses the gzip or compress programs that are
standard on Unix systems and should not require special configuration. If
you can't or don't want to use gzip as the file compression tool, either
pre-uncompress your files before parsing with this module or modify
*Bio::Root::Utilities.pm* to your liking.

   Blast objects can be generated either by direct instantiation as in:

     use Bio::Tools::Blast;
     $blast = new Bio::Tools::Blast (%parameters);

Using the Static $Blast Object
------------------------------

     use Bio::Tools::Blast qw(:obj);

   This exports the static $Blast object into your namespace. "Static"
refers to the fact that it has class scope and there is one of these
created when you use this module. The static $Blast object is basically an
empty object that is provided for convenience and is also used for various
internal chores.

   It is exported by this module and can be used for parsing and running
reports as well as HTML-formatting without having to first create an empty
Blast object.

   Using the static $Blast object for parsing a STDIN stream of Blast
reports:

     use Bio::Tools::Blast qw(:obj);

     sub process_blast {
     	my $blastObj = shift;
     	print $blastObj->table();
     	$blastObj->destroy;
     }

     $Blast->parse( -parse     => 1,
     		   -signif    => '1e-10',
     		   -exec_func => \&process_blast,
     		   );

   Then pipe a stream of Blast reports into your script via STDIN.  For
each Blast report extracted from the input stream, the parser will
generate a new Blast object and pass it to the function specified by
`-exec_func'.  The `destroy' in this node() call tells Perl to free the
memory associated with the object, important if you are crunching through
many reports. This method is inherited from *Bio::Root::Object.pm* (see
`Links to related modules' in this node). See `parse' in this node() for a
full description of parameters and `DEMO SCRIPTS' in this node for
additional examples.

Running Blasts
--------------

   To run a Blast, create a new Blast object with a `-run => \%runParams'
parameter.  Remote Blasts are performed by including a `-method =>
'remote'' parameter; local Blasts are performed by including a `-method =>
'local'' parameter.  See `Running Blast reports' in this node as well as
the `DEMO SCRIPTS' in this node for examples.  Note that running local
Blasts is not yet supported, see below.

   Note that the `-seqs => [ $seqs ]' run parameter must contain a
reference to an array of *Bio::Seq.pm* objects (`Links to related modules'
in this node). Encapsulating the sequence in an object makes sequence
information much easier to handle as it can be supplied in a variety of
formats. Bio::Seq.pm is included with this distribution (`INSTALLATION' in
this node).

   Remote Blasts are implemented using the
*Bio::Tools::Blast::Run::Webblast.pm* module.  Local Blasts require that
you customize the *Bio::Tools::Blast::Run::LocalBlast.pm* module.  The
version of LocalBlast.pm included with this distribution provides the
basic framework for running local Blasts.  See `Links to related modules'
in this node.

Significance screening
----------------------

   A `-signif' parameter can be used to screen out all hits with P-values
(or Expect values) above a certain cutoff. For example, to exclude all
hits with Expect values above 1.0e-10: `-signif => 1e-10'. Providing a
`-signif' cutoff can speed up processing tremendously, since only a small
fraction of the report need be parsed. This is because the `-signif' value
is used to screen hits based on the data in the "Description" section of
the Blast report:

   For NCBI BLAST2 reports:

     Score     E
       Sequences producing significant alignments:                        (bits)  Value

     sp|P31376|YAB1_YEAST  HYPOTHETICAL 74.1 KD PROTEIN IN CYS3-MDM10...   957  0.0

   For BLAST1 or WashU-BLAST2 reports:

     Smallest
       Sum
                                                                     High  Probability
       Sequences producing High-scoring Segment Pairs:              Score  P(N)      N

     PDB:3PRK_E Proteinase K complexed with inhibitor ...........   504  1.8e-50   1

   Thus, the `-signif' parameter will screen based on Expect values for
BLAST2 reports and based on P-values for BLAST1/WashU-BLAST2 reports.

   To screen based on other criteria, you can supply a `-filt_func'
parameter containing a function reference that takes a
*Bio::Tools::Sbjct.pm* object as an argument and returns a boolean, true
if the hit is to be screened out. See example below for `Screening hits
using arbitrary criteria' in this node.

Get the best hit.
-----------------

     $hit = $blastObj->hit;

   A "hit" is contained by a *Bio::Tools::Blast::Sbjct.pm* object.

Get the P-value or Expect value of the most significant hit.
------------------------------------------------------------

     $p = $blastObj->lowest_p;
     $e = $blastObj->lowest_expect;

   Alternatively:

     $p = $blastObj->hit->p;
     $e = $blastObj->hit->expect;

   Note that P-values are not reported in NCBI Blast2 reports.

Iterate through all the hits
----------------------------

     foreach $hit ($blastObj->hits) {
     	 printf "%s\t %.1e\t %d\t %.2f\t %d\n",
     	                  $hit->name, $hit->expect, $hit->num_hsps,
                          $hit->frac_identical, $hit->gaps;
     }

   Refer to the documentation for *Bio::Tools::Blast::Sbjct.pm* for other
ways to work with hit objects (`Links to related modules' in this node).

Screening hits using arbitrary criteria
---------------------------------------

     sub filter { $hit=shift;
     		 return ($hit->gaps == 0 and
     			 $hit->frac_conserved > 0.5); }

     $blastObj = Bio::Tools::Blast->new( -file      => '/tmp/blast.out',
     					 -parse     => 1,
     					 -filt_func => \&filter );

   While the Blast object is parsing the report, each hit checked by
calling &filter($hit). All hits that generate false return values from
&filter are screened out and will not be added to the Blast object.  Note
that the Blast object will normally stop parsing the report after the
first non-significant hit or the first hit that does not pass the filter
function. To force the Blast object to check all hits, include a
`-check_all_hits => 1'  parameter.  Refer to the documentation for
*Bio::Tools::Blast::Sbjct.pm* for other ways to work with hit objects.

Hit start, end coordinates.
          print $sbjct->start('query');
          print $sbjct->end('sbjct');

     In array context, you can get information for both query and sbjct
     with one call:

          ($qstart, $sstart) = $sbjct->start();
          ($qend, $send)     = $sbjct->end();

     For important information regarding coordinate information, see the
     `HSP start, end, and strand' in this node section below.  Also check
     out documentation for the start and end methods in
     *Bio::Tools::Blast::Sbjct.pm*, which explains what happens if there
     is more than one HSP.

Working with HSPs
-----------------

Iterate through all the HSPs of every hit
          foreach $hit ($blastObj->hits) {
          	 foreach $hsp ($hit->hsps) {
          	 printf "%.1e\t %d\t %.1f\t %.2f\t %.2f\t %d\t %d\n",
          	                  $hsp->expect, $hsp->score, $hsp->bits,
                               $hsp->frac_identical, $hsp->frac_conserved,
          	                  $hsp->gaps('query'), $hsp->gaps('sbjct');
          }

     Refer to the documentation for Bio::Tools::Blast::HSP.pm for other
     ways to work with hit objects (`Links to related modules' in this
     node).

Extract HSP sequence data as strings or sequence objects
     Get the first HSP of the first hit and the sequences of the query and
     sbjct as strings.

          $hsp = $blast_obj->hit->hsp;
          $query_seq = $hsp->seq_str('query');
          $hsp_seq = $hsp->seq_str('sbjct');

     Get the indices of identical and conserved positions in the HSP query
     seq.

          @query_iden_indices = $hsp->seq_inds('query', 'identical');
          @query_cons_indices = $hsp->seq_inds('query', 'conserved');

     Similarly for the sbjct sequence.

          @sbjct_iden_indices = $hsp->seq_inds('sbjct', 'identical');
          @sbjct_cons_indices = $hsp->seq_inds('sbjct', 'conserved');

          print "Query in Fasta format:\n", $hsp->seq('query')->layout('fasta');
          print "Sbjct in Fasta format:\n", $hsp->seq('sbjct')->layout('fasta');

     See the *Bio::Seq.pm* package for more information about using these
     sequence objects (`Links to related modules' in this node).

Create sequence alignment objects using HSP sequences
          $aln = $hsp->get_aln;
          print " consensus:\n", $aln->consensus();
          print $hsp->get_aln->layout('fasta');

          $ENV{READSEQ_DIR} = '/home/users/sac/bin/solaris';
          $ENV{READSEQ} = 'readseq';
          print $hsp->get_aln->layout('msf');

     MSF formated layout requires Don Gilbert's ReadSeq program (not
     included).  See the *Bio::UnivAln.pm* for more information about
     using these alignment objects (`Links to related modules' in this
     node)'.

HSP start, end, and strand
     To facilitate HSP processing, endpoint data for each HSP sequence are
     normalized so that *start is always less than end*. This affects
     TBLASTN and TBLASTX HSPs on the reverse complement or "Minus" strand.

     Some examples of obtaining start, end coordinates for HSP objects:

          print $hsp->start('query');
          print $hsp->end('sbjct');
          ($qstart, $sstart) = $hsp->start();
          ($qend, $send) = $hsp->end();

     Strandedness of the HSP can be assessed using the strand() method on
     the HSP object:

          print $hsp->strand('query');
          print $hsp->strand('sbjct');

     These will return 'Minus' or 'Plus'.  Or, to get strand information
     for both query and sbjct with a single call:

          ($qstrand, $sstrand) = $hsp->strand();

Report Generation
-----------------

Generate a tab-delimited table of all results.
          print $blastObj->table;
          print $blastObj->table(0);   # don't include hit descriptions.
          print $blastObj->table_tiled;

     The `table' in this node() method returns data for each HSP of each
     hit listed one per line. The `table_tiled' in this node() method
     returns data for each *hit, i.e., Sbjct* listed one per line; data
     from multiple HSPs are combined after tiling to reduce overlaps. See
     *Bio::Tools::Blast::Sbjct.pm* for more information about HSP tiling.
     These methods generate stereotypical, tab-delimited data for each hit
     of the Blast report. The output is suitable for importation into
     spreadsheets or database tables. Feel free to roll your own table
     function if you need a custom table.

     For either table method, descriptions of each hit can be included if a
     single, true argument is supplied (e.g., $blastObj->table(1)). The
     description will be added as the last field. This will significantly
     increase the size of the table. Labels for the table columns can be
     obtained with `table_labels' in this node() and `table_labels_tiled'
     in this node().

Print a summary of the Blast report
          $blastObj->display();
          $blastObj->display(-show=>'hits');

     `display' in this node() prints various statistics extracted from the
     Blast report such as database name, database size, matrix used, etc.
     The `display(-show=>'hits')' call prints a non-tab-delimited table
     attempting to line the data up into more readable columns. The output
     generated is similar to `table_tiled' in this node().

HTML-format an existing report
          use Bio::Tools::Blast qw(:obj);

          # Going straight from a non HTML report file to HTML output using
          # the static $Blast object exported by Bio::Tools::Blast.pm
          $Blast->to_html(-file   => '/usr/people/me/blast.output.txt',
          		     -header => qq|<H1>BLASTP Results</H1><A HREF="home.html">Home</A>|
          		     );

          # You can also use a specific Blast object created previously.
          $blastObj->to_html;

     `to_html' in this node() will send HTML output, line-by-line,
     directly to STDOUT unless an `-out => array_ref' parameter is
     supplied (e.g., `-out => \@array'), in which case the HTML will be
     stored in @array, one line per array element.  The direct outputting
     permits faster response time since Blast reports can be huge. The
     -header tag can contain a string containing any HTML that you want to
     appear at the top of the Blast report.

DEMO SCRIPTS
============

   Sample Scripts are included in the central bioperl distribution in the
'examples/blast/' directory (see `INSTALLATION' in this node). These are
also available at the following URLs (but it would be safer to use the
scripts included with the distribution).

Handy library for working with Bio::Tools::Blast.pm
---------------------------------------------------

     http://bio.perl.org/Core/Examples/blast/blast_config.pl

Parsing Blast reports one at a time.
------------------------------------

     http://bio.perl.org/Core/Examples/blast/parse_blast.pl
     http://bio.perl.org/Core/Examples/blast/parse_blast2.pl
     http://bio.perl.org/Core/Examples/blast/parse_positions.pl

Parsing sets of Blast reports.
------------------------------

     http://bio.perl.org/Core/Examples/blast/parse_blast.pl
     http://bio.perl.org/Core/Examples/blast/parse_multi.pl

     B<Warning:> See note about L<Memory Usage Issues>.

Running Blast analyses one at a time.
-------------------------------------

     http://bio.perl.org/Core/Examples/blast/run_blast_remote.pl

Running Blast analyses given a set of sequences.
------------------------------------------------

     http://bio.perl.org/Core/Examples/blast/blast_seq.pl

HTML-formatting Blast reports.
------------------------------

     http://bio.perl.org/Core/Examples/blast/html.pl

TECHNICAL DETAILS
=================

Blast Modes
-----------

   A BLAST object may be created using one of three different modes as
defined by the *Bio::Tools::SeqAnal.pm* package (See `Links to related
modules' in this node):

     -- parse - Load a BLAST report and parse it, storing parsed data in
        Blast.pm object.
     -- run      - Run the BLAST program to generate a new report.
     -- read     - Load a BLAST report into the Blast object without parsing.

   *Run mode support has recently been added*.  The module
*Bio::Tools::Blast::Run::Webblast.pm* is an modularized adaptation of the
webblast script by Alex Dong Li:

     http://www.genet.sickkids.on.ca/bioinfo_resources/software.html#webblast

   for running remote Blast analyses and saving the results locally.  Run
mode can be combined with a parse mode to generate a Blast report and then
build the Blast object from the parsed results of this report (see `run'
in this node() and `SYNOPSIS' in this node).

   In read mode, the BLAST report is read in by the Blast object but is
not parsed.  This could be used to internalize a Blast report but not
parse it for results (e.g., generating HTML formatted output).

Significant Hits
----------------

   This module permits the screening of hits on the basis of
user-specified criteria for significance. Currently, Blast reports can be
screened based on:

     CRITERIA                            PARAMETER       VALUE
     ----------------------------------  ---------      ----------------
       1) the best Expect (or P) value      -signif        float or sci-notation
       2) the length of the query sequence  -min_length    integer
       3) arbitrary criteria                -filt_func     function reference

   The parameters are used for construction of the BLAST object or when
running the `parse' in this node() method on the static $Blast object.  The
-SIGNIF value represents the number listed in the description section at
the top of the Blast report. For Blast2, this is an Expect value, for
Blast1 and WashU-Blast2, this is a P-value.  The idea behind the
`-filt_func' parameter is that the hit has to pass through a filter to be
considered significant. Refer to the documentation for
*Bio::Tools::Blast::Sbjct.pm* for ways to work with hit objects.

   Using a `-signif' parameter allows for the following:

Faster parsing.
     Each hit can be screened by examination of the description line alone
     without fully parsing the HSP alignment section.

Flexibility.
     The `-signif' tag provides a more semantic-free way to specify the
     value to be used as a basis for screening hits. Thus, `-signif' can
     be used for screening Blast1 or Blast2 reports. It is up to the user
     to understand whether `-signif' represents a P-value or an Expect
     value.

   Any hit not meeting the significance criteria will not be added to the
"hit list" of the BLAST object. Also, a BLAST object without any hits
meeting the significance criteria will throw an exception during object
construction (a fatal event).

Statistical Parameters
----------------------

   There are numerous parameters which define the behavior of the BLAST
program and which are useful for interpreting the search results. These
parameters are extracted from the Blast report:

     filter  --  for masking out low-complexity sequences or short repeats
     matrix  --  name of the substitution scoring matrix (e.g., BLOSUM62)
     E       --  Expect filter (screens out frequent scores)
     S       --  Cutoff score for segment pairs
     W       --  Word length
     T       --  Threshold score for word pairs
     Lambda, --  Karlin-Altschul "sum" statistical parameters dependent on
      K, H        sequence composition.
     G       --  Gap creation penalty.
     E       --  Gap extension penalty.

   These parameters are not always needed. Extraction may be turned off
explicitly by including a `-stats => 0' parameter during object
construction.  Support for all statistical parameters is not complete.

   For more about the meaning of parameters, check out the NCBI URLs given
above.

Module Organization
-------------------

   The modules that comprise this Bioperl Blast distribution are location
in the Bio:: hierarchy as shown in the diagram below.

     Bio/
      |
                    +--------------------------+
                    |                          |
               Bio::Tools                  Bio::Root
                    |                          |
         +----------------------+           Object.pm
         |          |           |
      SeqAnal.pm  Blast.pm    Blast/
                                |
                 +---------+---------+------------+
                 |         |         |            |
               Sbjct.pm   HSP.pm   HTML.pm       Run/
                      |
                +------------+
                |            |
           Webblast.pm   LocalBlast.pm

   Bio::Tools::Blast.pm is a concrete class that inherits from
*Bio::Tools::SeqAnal.pm* and relies on other modules for parsing and
managing BLAST data.  Worth mentioning about this hierarchy is the lack of
a "Parse.pm" module.  Since parsing is considered central to the purpose
of the Bioperl Blast module (and Bioperl in general), it seems somewhat
unnatural to segregate out all parsing code. This segregation could also
lead to inefficiencies and harder to maintain code. I consider this issue
still open for debate.

   Bio::Tools::Blast.pm, *Bio::Tools::Blast::Sbjct.pm*, and
Bio::Tools::Blast::HSP.pm are mostly dedicated to parsing and all can be
used to instantiate objects.  Blast.pm is the main "command and control"
module, inheriting some basic behaviors from SeqAnal.pm (things that are
not specific to Blast *per se*).

   *Bio::Tools::Blast::HTML.pm* contains functions dedicated to generating
HTML-formatted Blast reports and does not generate objects.

Running Blasts: Details
-----------------------

   *Bio::Tools::Blast::Run::Webblast.pm* contains a set of functions for
running Blast analyses at a remote server and also does not instantiate
objects.  It uses a helper script called postclient.pl, located in the Run
directory.  The proposed LocalBlast.pm module would be used for running
Blast reports on local machines and thus would be customizable for
different sites. It would operate in a parallel fashion to Webblast.pm
(i.e., being a collection of functions, taking in sequence objects or
files, returning result files).

   The Run modules are considered experimental. In particular, Webblast.pm
catures an HTML-formatted version of the Blast report from the NCBI server
and strips out the HTML in preparation for parsing. A more direct approach
would be to capture the Blast results directly from the server using an
interface to the NCBI toolkit.  This approach was recently proposed on the
Bioperl mailing list:
http://www.uni-bielefeld.de/mailinglists/BCD/vsns-bcd-perl/9805/0000.html

Memory Usage Issues
-------------------

   Parsing large numbers of Blast reports (a few thousand or so) with
Bio::Tools::Blast.pm may lead to unacceptable memory usage situations.
This is somewhat dependent of the size and complexity of the reports.

   While this problem is under investigation, here are some workarounds
that fix the memory usage problem:

  1. Don't specify a -signif criterion when calling `parse' in this node().
     The `-signif' value is used for imposing a upper limit to the expect-
     or P-value for Blast hits to be parsed. For reasons that are still
     under investigation, specifying a value for `-signif' in the `parse'
     in this node() method prevents Blast objects from being fully garbage
     collected. When using the *parse_blast.pl* or *parse_multi.pl*
     scripts in `examples/blast/' of the bioperl distribution), don't
     supply a `-signif' command-line parameter.

  2. If you want to impose a -signif criterion, put it inside a -filt_func.
     For the `parse' in this node() method, a -signif => 1e-5 parameter is
     equivalent to using a filter function parameter of

          -filt_func => sub { my $hit = shift; return $hit->signif <= 1e-5; }

     Using the *examples/blast/parse_multi.pl* script, you can supply a
     command-line argument of

          -filt_func '$hit->signif <= 1e-5'

     For more information, see `parse' in this node() and the section
     `Screening hits using arbitrary criteria' in this node.

TODO
====

   * Develop a functional, prototype Bio::Tools::Blast::Run::LocalBlast.pm
     module.

   * Add support for PSI-BLAST and PHI-BLAST

   * Parse histogram of expectations and retrieve gif image in Blast
     report (if present).

   * Further investigate memory leak that occurs when parsing Blast
     streams whe supplying a -signif parameter to `parse' in this node().

   * Access Blast results directly from the NCBI server using a Perl
     interface to the NCBI toolkit or XML formated Blast reports (when
     available).

   * Further exploit Bio::UnivAln.pm and multiple-sequence alignment
     programs using HSP sequence data. Some of this may best go into a
     separate, dedicated module or script as opposed to burdening
     Blast.pm, Sbjct.pm, and HSP.pm with additional functionality that is
     not always required.

   * Add an example script for parsing Blast reports containing HTML
     formatting.

VERSION
=======

   Bio::Tools::Blast.pm, 0.09

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules.  Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bio.perl.org/MailList.html - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR
======

   Steve A. Chervitz, sac@genome.stanford.edu

   See the `FEEDBACK' in this node section for where to send bug reports
and comments.

ACKNOWLEDGEMENTS
================

   This module was developed under the auspices of the Saccharomyces Genome
Database:     http://genome-www.stanford.edu/Saccharomyces

   Other contributors include: Alex Dong Li (webblast), Chris Dagdigian
(Seq.pm), Steve Brenner (Seq.pm), Georg Fuellen (Seq.pm, UnivAln.pm), and
untold others who have offered comments (noted in the
Bio/Tools/Blast/CHANGES file of the distribution).

COPYRIGHT
=========

   Copyright (c) 1996-98 Steve A. Chervitz. All Rights Reserved.  This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

     Bio::Tools::SeqAnal.pm                  - Sequence analysis object base class.
     Bio::Tools::Blast::Sbjct.pm             - Blast hit object.
     Bio::Tools::Blast::HSP.pm               - Blast HSP object.
     Bio::Tools::Blast::HTML.pm              - Blast HTML-formating utility class.
     Bio::Tools::Blast::Run::Webblast.pm     - Utility module for running Blasts remotely.
     Bio::Tools::Blast::Run::LocalBlast.pm   - Utility module for running Blasts locally.
     Bio::Seq.pm                             - Biosequence object
     Bio::UnivAln.pm                         - Biosequence alignment object.
     Bio::Root::Object.pm                    - Proposed base class for all Bioperl objects.

Links to related modules
------------------------

     Bio::Tools::SeqAnal.pm
          http://bio.perl.org/Core/POD/Bio/Tools/SeqAnal.html

     Bio::Tools::Blast::Sbjct.pm
          http://bio.perl.org/Core/POD/Bio/Tools/Blast/Sbjct.html

     Bio::Tools::Blast::HSP.pm
          http://bio.perl.org/Core/POD/Bio/Tools/Blast/HSP.html

     Bio::Tools::Blast::HTML.pm
          http://bio.perl.org/Core/POD/Bio/Tools/Blast/HTML.html

     Bio::Tools::Blast::Run::Webblast.pm
          http://bio.perl.org/Core/POD/Bio/Tools/Blast/Run/Webblast.html

     Bio::Tools::Blast::Run::LocalBlast.pm
          http://bio.perl.org/Core/POD/Bio/Tools/Blast/Run/LocalBlast.html

     Bio::Seq.pm
          http://bio.perl.org/Core/POD/Seq.html

     Bio::UnivAln.pm
          http://bio.perl.org/Projects/SeqAlign/
          Europe:  http://www.techfak.uni-bielefeld.de/bcd/Perl/Bio/#univaln

     Bio::Root::Object.pm
          http://bio.perl.org/Core/POD/Root/Object.html

     http://bio.perl.org/Projects/modules.html  - Online module documentation
     http://bio.perl.org/Projects/Blast/        - Bioperl Blast Project
     http://bio.perl.org/                       - Bioperl Project Homepage

   `References & Information about the BLAST program' in this node.

KNOWN BUGS
==========

   There is a memory leak that occurs when parsing parsing streams
containing large numbers of Blast reports (a few thousand or so) and
specifying a -signif parameter to the `parse' in this node() method. For a
workaround, see `Memory Usage Issues' in this node.

   Not sharing statistical parameters between different Blast objects when
parsing a multi-report stream has not been completely tested and may be a
little buggy.

   Documentation inconsistencies or inaccuracies may exist since this
module underwend a fair bit of re-working going from 0.75 to 0.80
(corresponds to versions 0.04.4 to 0.05 of the bioperl distribution).

APPENDIX
========

   Methods beginning with a leading underscore are considered private and
are intended for internal use by this module. They are not considered part
of the public interface and are described here for documentation purposes
only.

run
---

     Usage     : $object->run( %named_parameters )
     Purpose   : Run a local or remote Blast analysis on one or more sequences.
     Returns   : String containing name of Blast output file if a single Blast
               : is run.
               :  -- OR --
               : List of Blast objects if multiple Blasts are being run as a group.
     Argument  : Named parameters:  (PARAMETER TAGS CAN BE UPPER OR LOWER CASE).
               :    -METHOD  => 'local' or 'remote' (default = remote),
               :    -PARSE   => boolean, (true if the results are to be parsed after the run)
               :    -STRICT  => boolean, the strict mode to use for the resulting Blast objects.
               :  ADDITIONAL PARAMETERS:
               :      See methods _run_remote() and _run_local() for required
               :      parameters necessary for running the blast report.
     Throws    : Exception if no Blast output file was obtained.
     Comments  : This method is called automatically during construction of a
               : Blast.pm object when run parameters are sent to the constructor:
               :  $blastObj = new Bio::Tools::Blast (-RUN =>\%runParam,
     	   :					 %parseParam );
               :
               : The specific run methods (local or remote) called by run()
               : must return a list containing  the file name(s) with the Blast output.
               :
               : The run() method can perform single or multiple Blast runs
               : (analogous to the way parse() works) depending on how many
               : sequences are submitted. However, the running of multiple
               : Blasts is probably better handled at the script level. See notes in
               : the "TODO" section below.
               :
               : As for what to do with the Blast result file, that decision is
               : left for the user who can direct the Blast object to delete, compress,
               : or leave it alone.
               :
               : This method does not worry about load balancing, which
               : is probably best handled at the server level.
               :
     TODO:     : Support for running+parsing multiple Blast analyses with a
               : single run() call is incomplete. One can generate multiple
               : reports by placing more than one sequence object in the -seqs
               : reference parameter. This saves some overhead in the code
               : that executes the Blasts since all options are configured once.
               : (This is analogous to parsing using the static $Blast object
               : see parse() and _parse_stream()).
               :
               : The trouble is that Blast objects for all runs are constructed,
               : parsed (if necessary), and then returned as a group
               : This can require lots of memory when run+parsing many Blasts
               : but should be fine if you just want to run a bunch Blasts.
               :
               : For now, when running+parsing Blasts, stick to running one
               : Blast at a time, building the Blast object with the results
               : of that report, and processing as necessary.
               :
               : Support for running PSI-Blast is not complete.

   See Also:  `_run_remote' in this node(), `_run_local' in this node(),
`parse' in this node()

_run_remote
-----------

     Usage     : n/a; internal method called by run()
               : $object->_run_remote( %named_parameters )
     Purpose   : Run Blast on a remote server.
     Argument  : Named parameters:
               :   See documentation for function &blast_remote in
               :   Bio::Tools::Blast::Run::Webblast.pm for description
               :   of parameters.
     Comments  : This method requires the Bio::Tools::Blast::Run::Webblast.pm
               : which conforms to this minimal API:
               :    * export a method called &blast_remote that accepts a
               :      Bio::Tools::Blast.pm object + named parameters
               :      (specified in the Webblast.pm module).
               :    * return a list of names of files containing the raw Blast reports.
               :      (When building a Blast object, this list would contain a
               :       single file from which the Blast object is to be constructed).

   See Also   : `run' in this node(), `_run_local' in this node(),
*Bio::Tools::Blast::Run::Webblast.pm::blast_remote()*, `Links to related
modules' in this node

_run_local
----------

     Usage     : n/a; internal method called by run()
               : $object->_run_local(%named_parameters)
     Purpose   : Run Blast on a local machine.
     Argument  : Named parameters:
               :   See documentation for function &blast_local in
               :   Bio::Tools::Blast::Run::LocalBlast.pm for description
               :   of parameters.
     Comments  : This method requires the Bio::Tools::Blast::Run::LocalBlast.pm
               : module which should be customized for your site. This module would
               : contain all the commands, paths, environment variables, and other
               : data necessary to run Blast commands on a local machine, but should
               : not contain any semantics for specific query sequences.
               :
               : LocalBlast.pm should also conform to this minimal API:
               :    * export a method called &blast_local that accepts a
               :       Bio::Tools::Blast.pm object + named parameters
               :      (specified in the LocalBlast.pm module).
               :    * return a list of names of files containing the raw Blast reports.
               :      (When building a Blast object, this list would contain a
               :       single file from which the Blast object is to be constructed).

   See Also   : `run' in this node(), `_run_remote' in this node(),
*Bio::Tools::Blast::Run::LocalBlast::blast_local()*, `Links to related
modules' in this node

db_remote
---------

     Usage     : @dbs = $Blast->db_remote( [seq_type] );
     Purpose   : Get a list of available sequence databases for remote Blast analysis.
     Returns   : Array of strings
     Argument  : seq_type = 'p' or 'n'
               :  'p' = Gets databases for peptide searches  (default)
               :  'n' = Gets databases for nucleotide searches
     Throws    : n/a
     Comments  : Peptide databases are a subset of the nucleotide databases.
               : It is convenient to call this method on the static $Blast object
               : as shown in Usage.

   See Also   : `db_local' in this node()

db_local
--------

     Usage     : @dbs = $Blast->db_local( [seq_type] );
     Purpose   : Get a list of available sequence databases for local Blast analysis.
     Returns   : Array of strings
     Argument  : seq_type = 'p' or 'n'
               :  'p' = Gets databases for peptide searches  (default)
               :  'n' = Gets databases for nucleotide searches
     Throws    : n/a
     Comments  : Peptide databases are a subset of the nucleotide databases.
               : It is convenient to call this method on the static $Blast object.
                 as shown in Usage.

   See Also   : `db_remote' in this node()

parse
-----

     Usage     : $blast_object->parse( %named_parameters )
     Purpose   : Parse a Blast report from a file or STDIN.
               :   * Parses a raw BLAST data, populating Blast object with report data.
               :   * Sets the significance cutoff.
               :   * Extracts statistical parameters about the BLAST run.
               :   * Handles both single files and streams containing multiple reports.
     Returns   : integer (number of Blast reports parsed)
     Argument  : <named parameters>:  (PARAMETER TAGS CAN BE UPPER OR LOWER CASE).
     	   : -FILE       => string (name of file containing raw Blast output.
               :                         Optional. If a valid file is not supplied,
     	   :		             STDIN will be used).
     	   : -SIGNIF     => number (float or scientific notation number to be used
     	   :                         as a P- or Expect value cutoff;
     	   :			     default =  $DEFAULT_SIGNIF (999)).
     	   : -FILT_FUNC  => func_ref (reference to a function to be used for
               :                          filtering out hits based on arbitrary criteria.
               :                          This function should take a
               :                          Bio::Tools::Blast::Sbjct.pm object as its first
               :                          argument and return a boolean value,
     	   :                          true if the hit should be filtered out).
               :                          Sample filter function:
               :                          -FILT_FUNC => sub { $hit = shift;
     	   :				                  $hit->gaps == 0; },
               : -CHECK_ALL_HITS => boolean (check all hits for significance against
               :                             significance criteria.  Default = false.
     	   :			         If false, stops processing hits after the first
               :                             non-significant hit or the first hit that fails
               :                             the filt_func call. This speeds parsing,
               :                             taking advantage of the fact that the hits
               :                             are processed in the order they are ranked.)
               : -MIN_LEN     => integer (to be used as a minimum query sequence length
               :                          sequences below this length will not be processed).
               :                          default = no minimum length).
     	   : -STATS       => boolean (collect stats for report: matrix, filters, etc.
               :                          default = false).
     	   : -BEST        => boolean (only process the best hit of each report;
               :                          default = false).
               : -OVERLAP     => integer (the amount of overlap to permit between
               :                          adjacent HSPs when tiling HSPs,
               :                          Default = $MAX_HSP_OVERLAP (2))
               :
               : PARAMETERS USED WHEN PARSING MULTI-REPORT STREAMS:
               : --------------------------------------------------
     	   : -SHARE       => boolean (set this to true if all reports in stream
     	   :			      share the same stats. Default = true)
               :                          Must be set to false when parsing both Blast1 and
               :                          Blast2 reports in the same run or if you need
               :                          statistical params for each report, Lambda, K, H).
     	   : -STRICT      => boolean (use strict mode for all Blast objects created.
               :                          Increases sensitivity to errors. For single
               :                          Blasts, this is parameter is sent to new().)
               : -EXEC_FUNC   => func_ref (reference to a function for processing each
               :                           Blast object after it is parsed. Should accept a
               :                           Blast object as its sole argument. Return value
               :                           is ignored. If an -EXEC_FUNC parameter is supplied,
               :                           the -SAVE_ARRAY parameter will be ignored.)
               : -SAVE_ARRAY  =>array_ref, (reference to an array for storing all
               :                            Blast objects as they are created.
               :                            Experimental. Not recommended.)
               : -SIGNIF_FMT  => boolean   String of 'exp' or 'parts'. Sets the format
               :                           for reporting P/Expect values. 'exp' reports
               :                           only the exponent portion. 'parts' reports
               :                           them as a 2 element list. See signif_fmt()..
               :
     Throws    : Exception if BLAST report contains a FATAL: error.
               : Propagates any exception thrown by read().
               : Propagates any exception thrown by called parsing methods.
     Comments  : This method can be called either directly using the static $Blast object
               : or indirectly (by Bio::Tools::SeqAnal.pm) during constuction of an
               : individual Blast object.
               :
               : HTML-formatted reports can be parsed as well. No special flag is required
               : since it is detected automatically. The presence of HTML-formatting
               : will result in slower performace, however, since it must be removed
               : prior to parsing. Parsing HTML-formatted reports is highly
               : error prone and is generally not recommended.
               :
               : If one has an HTML report, do NOT remove the HTML from it by using the
               : "Save As" option of a web browser to save it as text. This renders the
               : report unparsable.
               : HTML-formatted reports can be parsed after running through the strip_html
               : function of Blast::HTML.pm as in:
               :    require Bio::Tools::Blast::HTML;
               :    Bio::Tools::Blast::HTML->import(&strip_html);
               :    &strip_html(\$data);
               :    # where data contains full contents of an HTML-formatted report.
               : TODO: write a demo script that does this.

   See Also   : `_init_parse_params' in this node(), `_parse_blast_stream'
in this node(), `overlap' in this node(), `signif_fmt' in this node(),
*Bio::Root::Object::read()*, *Bio::Tools::Blast::HTML.pm::strip_html()*,
`Links to related modules' in this node

_init_parse_params
------------------

     Title   : _init_parse_params
     Usage   : n/a; called automatically by parse()
     Purpose : Initializes parameters used during parsing of Blast reports.
             : This is a static method used by the $Blast object.
             : Calls _set_signif().
     Example :
     Returns : n/a
     Args    : Args extracted by parse().

   See Also: `parse' in this node(), `_set_signif' in this node()

_set_signif
-----------

     Usage     : n/a; called automatically by _init_parse_params()
               : This is now a "static" method used only by $Blast.
               : _set_signif($signif, $min_len, $filt_func);
     Purpose   : Sets significance criteria for the BLAST object.
     Argument  : Obligatory three arguments:
               :   $signif = float or sci-notation number or undef
               :   $min_len = integer or undef
               :   $filt_func = function reference or undef
               :
               :   If $signif is undefined, a default value is set
               :   (see $DEFAULT_SIGNIF; min_length = not set).
     Throws    : Exception if significance value is defined but appears
               :   out of range or invalid.
               : Exception if $filt_func if defined and is not a func ref.
     Comments  : The significance of a BLAST report can be based on
               : the P (or Expect) value and/or the length of the query sequence.
               : P (or Expect) values GREATER than '_significance' are not significant.
               : Query sequence lengths LESS than '_min_length' are not significant.
               :
               : Hits can also be screened using arbitrary significance criteria
               : as discussed in the parse() method.
               :
               : If no $signif is defined, the '_significance' level is set to
               : $Bio::Tools::Blast::DEFAULT_SIGNIF (999).

   See Also   : `signif' in this node(), `min_length' in this node(),
`_init_parse_params' in this node(), `parse' in this node()

_parse_blast_stream
-------------------

     Usage     : n/a. Internal method called by parse()
     Purpose   : Obtains the function to be used during parsing and calls read().
     Returns   : Integer (the number of blast reports read)
     Argument  : Named parameters  (forwarded from parse())
     Throws    : Propagates any exception thrown by _get_parse_blast_func() and read().

   See Also   : `_get_parse_blast_func' in this node(),
*Bio::Root::Object::read()*

_get_parse_blast_func
---------------------

     Usage     : n/a; internal method used by _parse_blast_stream()
               : $func_ref = $blast_object->_get_parse_blast_func()
     Purpose   : Generates a function ref to be used as a closure for parsing
               : raw data as it is being loaded by Bio::Root::IOManager::read().
     Returns   : Function reference (closure).
     Comments  : The the function reference contains a fair bit of logic
               : at present. It could perhaps be split up into separate
               : functions to make it more 'digestible'.

   See Also   : `_parse_blast_stream' in this node()

_report_errors
--------------

     Title   : _report_errors
     Usage   : n/a; Internal method called by _get_parse_blast_func().
     Purpose : Throw or warn about any errors encountered.
     Returns : n/a
     Args    : n/a
     Throws  : If all hits generated exceptions, raise exception
             :   (a fatal event for the Blast object.)
             : If some hits were okay but some were bad, generate a warning
             :   (a few bad applies should not spoil the bunch).
             :   This usually indicates a limiting B-value.
             : When the parsing code fails, it is either all or nothing.

_parse_header
-------------

     Usage     : n/a; called automatically by the _get_parse_blast_func().
     Purpose   : Parses the header section of a BLAST report.
     Argument  : String containing the header+description section of a BLAST report.
     Throws    : Exception if description data cannot be parsed properly.
               : Exception if there is a 'FATAL' error in the Blast report.
               : Warning if there is a 'WARNING' in the Blast report.
               : Warning if there are no significant hits.
     Comments  : Description section contains a single line for each hit listing
               : the seq id, description, score, Expect or P-value, etc.

   See Also   : `_get_parse_blast_func' in this node()

_parse_alignment
----------------

     Usage     : n/a; called automatically by the _get_parse_blast_func().
     Purpose   : Parses a single alignment section of a BLAST report.
     Argument  : String containing the alignment section.
     Throws    : n/a; All errors are trapped while parsing the hit data
               : and are processed as a group when the report is
               : completely processed (See _report_errors()).
               :
     Comments  : Alignment section contains all HSPs for a hit.
               : Requires Bio::Tools::Blast::Sbjct.pm.
               : Optionally calls a filter function to screen the hit on arbitrary
               : criteria. If the filter function returns true for a given hit,
               : that hit will be skipped.
               :
               : If the Blast object was created with -check_all_hits set to true,
               : all hits will be checked for significance and processed if necessary.
               : If this field is false, the parsing will stop after the first
               : non-significant hit.
               : See parse() for description of parsing parameters.

   See Also   : `parse' in this node(), `_get_parse_blast_func' in this
node(), `_report_errors' in this node(), *Bio::Tools::Blast::Sbjct()*,
`Links to related modules' in this node

_parse_footer
-------------

     Usage     : n/a; internal function. called by _parse_alignment()
     Purpose   : Extracts statistical and other parameters from the BLAST report.
               : Sets various key elements such as the program and version,
               : gapping, and the layout for the report (blast1 or blast2).
     Argument  : Data to be parsed.
     Returns   : String containing an alignment section for processing by
               : _parse_alignment().
     Throws    : Exception if cannot find the parameters section of report.
               : Warning if cannot determine if gapping was used.
               : Warning if cannot determine the scoring matrix used.
     Comments  : This method must always get called, even if the -STATS
               : parse() parameter is false. The reason is that the layout
               : of the report  and the presence of gapping must always be set.
               : The determination whether to set additional stats is made
               : by methods called by _parse_footer().

   See Also   : `parse' in this node(), `_parse_alignment' in this node(),
`_set_database' in this node()

_set_blast2_stats
-----------------

     Usage     : n/a; internal function called by _parse_footer()
     Purpose   : Extracts statistical and other parameters from BLAST2 report footer.
               : Stats collected: database release, gapping,
               : posted date, matrix used, filter used, Karlin-Altschul parameters,
               : E, S, T, X, W.
     Throws    : Exception if cannot get "Parameters" section of Blast report.

   See Also   : `parse' in this node(), `_parse_footer' in this node(),
`_set_database' in this node(), *Bio::Tools::SeqAnal::set_date()*,`Links
to related modules' in this node

_set_blast1_stats
-----------------

     Usage     : n/a; internal function called by _parse_footer()
     Purpose   : Extracts statistical and other parameters from BLAST 1.x style eports.
               : Handles NCBI Blast1 and WashU-Blast2 formats.
               : Stats collected: database release, gapping,
               : posted date, matrix used, filter used, Karlin-Altschul parameters,
               : E, S, T, X, W.

   See Also   : `parse' in this node(), `_parse_footer' in this node(),
`_set_database' in this node(), *Bio::Tools::SeqAnal::set_date()*,`Links
to related modules' in this node

_set_gapping_wu
---------------

     Usage     : n/a; internal function called by _set_blast1_stats()
     Purpose   : Determine if gapping_wu was on for WashU Blast reports.
     Comments  : In earlier versions, gapping was always specified
               : but in the current version (2.0a19MP), gapping is on by default
               : and there is no positive "gapping" indicator in the Parameters
               : section.

   See Also   : `_set_blast1_stats' in this node()

_set_date
---------

     Usage     : n/a; internal function called by _parse_footer()
     Purpose   : Determine the date on which the Blast analysis was performed.
     Comments  : Date information is not consistently added to Blast output.
               : Uses superclass method set_date() to set date from the file,
               : (if any).

   See Also   : `_parse_footer' in this node(),
*Bio::Tools::SeqAnal::set_date()*,`Links to related modules' in this node

_set_length
-----------

     Usage     : n/a; called automatically during Blast report parsing.
     Purpose   : Sets the length of the query sequence (extracted from report).
     Returns   : integer (length of the query sequence)
     Throws    : Exception if cannot determine the query sequence length from
               :           the BLAST report.
               : Exception if the length is below the min_length cutoff (if any).
     Comments  : The logic here is a bit different from the other _set_XXX()
               : methods since the significance of the BLAST report is assessed
               : if MIN_LENGTH is set.

   See Also   : *Bio::Tools::SeqAnal::length()*, `Links to related
modules' in this node

_set_database
-------------

     Usage     : n/a; called automatically during Blast report parsing.
     Purpose   : Sets the name of the database used by the BLAST analysis.
               : Extracted from raw BLAST report.
     Throws    : Exception if the name of the database cannot be determined.
     Comments  : The database name is used by methods or related objects
               : for database-specific parsing.

   See Also   : `parse' in this node(),
*Bio::Tools::SeqAnal::database()*,*Bio::Tools::SeqAnal::_set_db_stats()*,`Links
to related modules' in this node

_set_query
----------

     Usage     : n/a; called automatically during Blast report parsing.
     Purpose   : Set the name of the query and the query description.
               : Extracted from the raw BLAST report.
     Returns   : String containing name of query extracted from report.
     Throws    : Warning if the name of the query cannont be obtained.

   See Also   : *Bio::Tools::SeqAnal::query_desc()*,`Links to related
modules' in this node

_parse_signif
-------------

     Usage     : &_parse_signif(string, layout, gapped);
               : This is a class function.
     Purpose   : Extracts the P- or Expect value from a single line of a BLAST description section.
     Example   : &_parse_signif("PDB_UNIQUEP:3HSC_  heat-shock cognate ...   799  4.0e-206  2", 1);
               : &_parse_signif("gi|758803  (U23828) peritrophin-95 precurs   38  0.19", 2);
     Argument  : string = line from BLAST description section
               : layout = integer (1 or 2)
               : gapped = boolean (true if gapped Blast).
     Returns   : Float (0.001 or 1e-03)
     Status    : Static

signif
------

     Usage     : $blast->signif();
     Purpose   : Gets the P or Expect value used as significance screening cutoff.
     Returns   : Scientific notation number with this format: 1.0e-05.
     Argument  : n/a
     Comments  : Screening of significant hits uses the data provided on the
               : description line. For Blast1 and WU-Blast2, this data is P-value.
               : for Blast2 it is an Expect value.
               :
               : Obtains info from the static $Blast object if it has not been set
               : for the current object.

   See Also   : `_set_signif' in this node()

is_signif
---------

     Usage     : $blast->is_signif();
     Purpose   : Determine if the BLAST report contains significant hits.
     Returns   : Boolean
     Argument  : n/a
     Comments  : BLAST reports without significant hits but with defined
               : significance criteria will throw exceptions during construction.
               : This obviates the need to check significant() for
               : such objects.

   See Also   : `_set_signif' in this node()

signif_fmt
----------

     Usage     : $blast->signif_fmt( [FMT] );
     Purpose   : Allows retrieval of the P/Expect exponent values only
               : or as a two-element list (mantissa, exponent).
     Usage     : $blast_obj->signif_fmt('exp');
               : $blast_obj->signif_fmt('parts');
     Returns   : String or '' if not set.
     Argument  : String, FMT = 'exp' (return the exponent only)
               :             = 'parts'(return exponent + mantissa in 2-elem list)
               :              = undefined (return the raw value)
     Comments  : P/Expect values are still stored internally as the full,
               : scientific notation value.
               : This method uses the static $Blast object since this issue
               : will pertain to all Blast reports within a given set.
               : This setting is propagated to Bio::Tools::Blast::Sbjct.pm.

min_length
----------

     Usage     : $blast->min_length();
     Purpose   : Gets the query sequence length used as significance screening criteria.
     Returns   : Integer
     Argument  : n/a
     Comments  : Obtains info from the static $Blast object if it has not been set
               : for the current object.

   See Also   : `_set_signif' in this node(), `signif' in this node()

gapped
------

     Usage     : $blast->gapped();
     Purpose   : Set/Get boolean indicator for gapped BLAST.
     Returns   : Boolean
     Argument  : n/a
     Comments  : Obtains info from the static $Blast object if it has not been set
               : for the current object.

_get_stats
----------

     Usage     : n/a; internal method.
     Purpose   : Set/Get indicator for collecting full statistics from report.
     Returns   : Boolean (0 | 1)
     Comments  : Obtains info from the static $Blast object which gets set
               : by _init_parse_params().

_layout
-------

     Usage     : n/a; internal method.
     Purpose   : Set/Get indicator for the layout of the report.
     Returns   : Integer (1 | 2)
               : Defaults to 2 if not set.
     Comments  : Blast1 and WashU-Blast2 have a layout = 1.
               : This is intended for internal use by this and closely
               : allied modules like Sbjct.pm and HSP.pm.
               :
               : Obtains info from the static $Blast object if it has not been set
               : for the current object.

hits
----

     Usage     : $blast->hits();
     Purpose   : Get a list containing all BLAST hit (Sbjct) objects.
               : Get the numbers of significant hits.
     Examples  : @hits       = $blast->hits();
               : $num_signif = $blast->hits();
     Returns   : List context : list of Bio::Tools::Blast::Sbjct.pm objects
               :                or an empty list if there are no hits.
               : Scalar context: integer (number of significant hits)
               :                 or zero if there are no hits.
               :                 (Equivalent to num_hits()).
     Argument  : n/a. Relies on wantarray.
     Throws    : n/a.
               : Not throwing exception because the absence of hits may have
               : resulted from stringent significance criteria, not a failure
               : set the hits.

   See Also   : `hit' in this node(), `num_hits' in this node(),
`is_signif' in this node(), `_set_signif' in this node()

hit
---

     Example   : $blast_obj->hit( [class] )
     Purpose   : Get a specific hit object.
               : Provides some syntactic sugar for the hits() method.
     Usage     : $hitObj = $blast->hit();
               : $hitObj = $blast->hit('best');
               : $hitObj = $blast->hit('worst');
               : $hitObj = $blast->hit( $name );
     Returns   : Object reference for a Bio::Tools::Blast::Sbjct.pm object.
               : undef if there are no hit (Sbjct) objects defined.
     Argument  : Class (or no argument).
               :   No argument (default) = highest scoring hit (same as 'best').
               :   'best' or 'first' = highest scoring hit.
               :   'worst' or 'last' = lowest scoring hit.
               :   $name = retrieve a hit by seq id (case-insensitive).
     Throws    : Exception if the Blast object has no significant hits.
               : Exception if a hit cannot be found when supplying a specific
               : hit sequence identifier as an argument.
     Comments  : 'best'  = lowest significance value (P or Expect) among significant hits.
               : 'worst' = highest sigificance value (P or Expect) among significant hits.

   See Also   : `hits' in this node(), `num_hits' in this node(),
`is_signif' in this node()

num_hits
--------

     Usage     : $blast->num_hits( ['total'] );
     Purpose   : Get number of significant hits or number of total hits.
     Examples  : $num_signif = $blast-num_hits;
               : $num_total  = $blast->num_hits('total');
     Returns   : Integer
     Argument  : String = 'total' (or no argument).
               :   No argument (Default) = return number of significant hits.
               :   'total' = number of total hits.
     Throws    : n/a.
               : Not throwing exception because the absence of hits may have
               : resulted from stringent significance criteria, not a failure
               : set the hits.
     Comments  : A significant hit is defined as a hit with an expect value
               : (or P value for WU-Blast) at or below the -signif parameter
               : used when parsing the report. Additionally, if a filter function
               : was supplied, the significant hit must also pass that
               : criteria.
     See Also   : L<hits>(), L<hit>(), L<is_signif>(), L<_set_signif>(), L<parse>()

lowest_p
--------

     Usage     : $blast->lowest_p()
     Purpose   : Get the lowest P-value among all hits in a BLAST report.
               : Syntactic sugar for $blast->hit('best')->p().
     Returns   : Float or scientific notation number.
               : Returns -1.0 if lowest_p has not been set.
     Argument  : n/a.
     Throws    : Exception if the Blast report does not report P-values
               : (as is the case for NCBI Blast2).
     Comments  : A value is returned regardless of whether or not there were
               : significant hits ($DEFAULT_SIGNIF, currently  999).

   See Also   : `lowest_expect' in this node(), `lowest_signif' in this
node(), `highest_p' in this node(), `signif_fmt' in this node()

lowest_expect
-------------

     Usage     : $blast->lowest_expect()
     Purpose   : Get the lowest Expect value among all hits in a BLAST report.
               : Syntactic sugar for $blast->hit('best')->expect()
     Returns   : Float or scientific notation number.
               : Returns -1.0 if lowest_expect has not been set.
     Argument  : n/a.
     Throws    : Exception if there were no significant hits and the report
               : does not have Expect values on the description lines
               : (i.e., Blast1, WashU-Blast2).

   See Also   : `lowest_p' in this node(), `lowest_signif' in this node(),
`highest_expect' in this node(), `signif_fmt' in this node()

highest_p
---------

     Example   : $blast->highest_p( ['overall'])
     Purpose   : Get the highest P-value among all hits in a BLAST report.
               : Syntactic sugar for $blast->hit('worst')->p()
               : Can also get the highest P-value overall (not just among signif hits).
     Usage     : $p_signif = $blast->highest_p();
               : $p_all    = $blast->highest_p('overall');
     Returns   : Float or scientific notation number.
               : Returns -1.0 if highest_p has not been set.
     Argument  : String 'overall' or no argument.
               : No argument = get highest P-value among significant hits.
     Throws    : Exception if object is created from a Blast2 report
               : (which does not report P-values).

   See Also   : `highest_signif' in this node(), `lowest_p' in this
node(), `_set_signif' in this node(), `signif_fmt' in this node()

highest_expect
--------------

     Usage     : $blast_object->highest_expect( ['overall'])
     Purpose   : Get the highest Expect value among all significant hits in a BLAST report.
               : Syntactic sugar for $blast->hit('worst')->expect()
     Examples  : $e_sig = $blast->highest_expect();
               : $e_all = $blast->highest_expect('overall');
     Returns   : Float or scientific notation number.
               : Returns -1.0 if highest_exoect has not been set.
     Argument  : String 'overall' or no argument.
               : No argument = get highest Expect-value among significant hits.
     Throws    : Exception if there were no significant hits and the report
               : does not have Expect values on the description lines
               : (i.e., Blast1, WashU-Blast2).

   See Also   : `lowest_expect' in this node(), `highest_signif' in this
node(), `signif_fmt' in this node()

lowest_signif
-------------

     Usage     : $blast_obj->lowest_signif();
               : Syntactic sugar for $blast->hit('best')->signif()
     Purpose   : Get the lowest P or Expect value among all hits
               : in a BLAST report.
               : This method is syntactic sugar for $blast->hit('best')->signif()
               : The value returned is the one which is reported in the decription
               : section of the Blast report.
               : For Blast1 and WU-Blast2, this is a P-value,
               : for NCBI Blast2, it is an Expect value.
     Example   : $blast->lowest_signif();
     Returns   : Float or scientific notation number.
               : Returns -1.0 if lowest_signif has not been set.
     Argument  : n/a.
     Throws    : n/a.
     Status    : Deprecated. Use lowest_expect() or lowest_p().
     Comments  : The signif() method provides a way to deal with the fact that
               : Blast1 and Blast2 formats differ in what is reported in the
               : description lines of each hit in the Blast report. The signif()
               : method frees any client code from having to know if this is a P-value
               : or an Expect value, making it easier to write code that can process
               : both Blast1 and Blast2 reports. This is not necessarily a good thing, since
               : one should always know when one is working with P-values or
               : Expect values (hence the deprecated status).
               : Use of lowest_expect() is recommended since all hits will have an Expect value.

   See Also   : `lowest_p' in this node(), `lowest_expect' in this node(),
`signif' in this node(), `signif_fmt' in this node(), `_set_signif' in
this node()

highest_signif
--------------

     Usage     : $blast_obj->highest_signif('overall');
               : Syntactic sugar for $blast->hit('worst')->signif()
     Purpose   : Get the highest P or Expect value among all hits
               : in a BLAST report.
               : The value returned is the one which is reported in the decription
               : section of the Blast report.
               : For Blast1 and WU-Blast2, this is a P-value,
               : for NCBI Blast2, it is an Expect value.
     Example   : $blast->highest_signif();
     Returns   : Float or scientific notation number.
               : Returns -1.0 if highest_signif has not been set.
     Argument  : Optional  string 'overall' to get the highest overall significance value.
     Throws    : n/a.
     Status    : Deprecated. Use highest_expect() or highest_p().
     Comments  : Analogous to lowest_signif(), q.v.

   See Also   : `lowest_signif' in this node(), `lowest_p' in this node(),
`lowest_expect' in this node(), `signif' in this node(), `signif_fmt' in
this node(), `_set_signif' in this node()

matrix
------

     Usage     : $blast_object->matrix();
     Purpose   : Get the name of the scoring matrix used.
               : This is extracted from the report.
     Argument  : n/a
     Returns   : string or undef if not defined

filter
------

     Usage     : $blast_object->filter();
     Purpose   : Get the name of the low-complexity sequence filter used.
               : (SEG, SEG+XNU, DUST, NONE).
               : This is extracted from the report.
     Argument  : n/a
     Returns   : string or undef if not defined

expect
------

     Usage     : $blast_object->expect();
     Purpose   : Get the expect parameter (E) used for the Blast analysis.
               : This is extracted from the report.
     Argument  : n/a
     Returns   : string or undef if not defined.

karlin_altschul
---------------

     Usage     : $blast_object->karlin_altschul();
     Purpose   : Get the Karlin_Altschul sum statistics (Lambda, K, H)
               : These are extracted from the report.
     Argument  : n/a
     Returns   : list of three floats (Lambda, K, H)
               : If not defined, returns list of three zeros)

word_size
---------

     Usage     : $blast_object->word_size();
     Purpose   : Get the word_size used during the Blast analysis.
               : This is extracted from the report.
     Argument  : n/a
     Returns   : integer or undef if not defined.

s
-

     Usage     : $blast_object->s();
     Purpose   : Get the s statistic for the Blast analysis.
               : This is extracted from the report.
     Argument  : n/a
     Returns   : integer or undef if not defined.

gap_creation
------------

     Usage     : $blast_object->gap_creation();
     Purpose   : Get the gap creation penalty used for a gapped Blast analysis.
               : This is extracted from the report.
     Argument  : n/a
     Returns   : integer or undef if not defined.

   See Also   : `gap_extension' in this node()

gap_extension
-------------

     Usage     : $blast_object->gap_extension();
     Purpose   : Get the gap extension penalty used for a gapped Blast analysis.
               : This is extracted from the report.
     Argument  : n/a
     Returns   : integer or undef if not defined.

   See Also   : `gap_extension' in this node()

ambiguous_aln
-------------

     Usage     : $blast_object->ambiguous_aln();
     Purpose   : Test all hits and determine if any have an ambiguous alignment.
     Example   : print "ambiguous" if $blast->ambiguous_aln();
     Returns   : Boolean (true if ANY significant hit has an ambiguous alignment)
     Argument  : n/a
     Throws    : n/a
     Status    : Experimental
     Comments  : An ambiguous BLAST alignment is defined as one where two or more
               : different HSPs have significantly overlapping sequences such
               : that it is not possible to create a unique alignment
               : by simply concatenating HSPs. This may indicate the presence
               : of multiple domains in one sequence relative to another.
               : This method only indicates the presence of ambiguity in at
               : least one significant hit. To determine the nature of the
               : ambiguity, each hit must be examined.

   See Also   : *Bio::Tools::Blast::Sbjct::ambiguous_aln()*,`Links to
related modules' in this node

overlap
-------

     Usage     : $blast_object->overlap([integer]);
     Purpose   : Set/Get the number of overlapping residues allowed when tiling multiple HSPs.
               : Delegates to Bio::Tools::Blast::Sbjct::overlap().
     Throws    : Exception if there are no significant hits.
     Status    : Experimental

   See Also   : *Bio::Tools::Blast::Sbjct::overlap()*,`Links to related
modules' in this node

homol_data
----------

     Usage     : @data = $blast_object->homo_data( %named_params );
     Purpose   : Gets specific similarity data about each significant hit.
     Returns   : Array of strings:
               : "Homology data" for each HSP is in the format:
               :  "<integer> <start> <stop>"
               : Data for different HSPs are tab-delimited.
     Argument  : named parameters passed along to the hit objects.
     Throws    : n/a
     Status    : Experimental
     Comments  : This is a very experimental method used for obtaining an
               : indication of:
               :   1) how many HSPs are in a Blast alignment
               :   2) how strong the similarity is between sequences in the HSP
               :   3) the endpoints of the alignment (sequence monomer numbers)

   See Also   : *Bio::Tools::Blast::Sbjct::homol_data()*,`Links to related
modules' in this node

REPORT GENERATING METHODS
=========================

table
-----

     Usage     : $blast_obj->table( [get_desc]);
     Purpose   : Output data for each HSP of each hit in tab-delimited format.
     Example   : print $blast->table;
               : print $blast->table(0);
               : # Call table_labels() to print labels.
     Argument  : get_desc = boolean, if false the description of each hit is not included.
               :            Default: true (if not defined, include description column).
     Returns   : String containing tab-delimited set of data for each HSP
               : of each significant hit. Different HSPs are separated by newlines.
               : Left-to-Right order of fields:
               : 1 QUERY_NAME             # Sequence identifier of the query.
               : 2 QUERY_LENGTH           # Full length of the query sequence.
               : 3 SBJCT_NAME             # Sequence identifier of the sbjct ("hit".
               : 4 SBJCT_LENGTH           # Full length of the sbjct sequence.
               : 5 EXPECT                 # Expect value for the alignment.
               : 6 SCORE                  # Blast score for the alignment.
               : 7 BITS                   # Bit score for the alignment.
               : 8 NUM_HSPS               # Number of HSPs (not the "N" value).
               : 9 HSP_FRAC_IDENTICAL     # fraction of identical substitutions.
               : 10 HSP_FRAC_CONSERVED    # fraction of conserved ("positive") substitutions.
               : 11 HSP_QUERY_ALN_LENGTH  # Length of the aligned portion of the query sequence.
               : 12 HSP_SBJCT_ALN_LENGTH  # Length of the aligned portion of the sbjct sequence.
               : 13 HSP_QUERY_GAPS        # Number of gaps in the aligned query sequence.
               : 14 HSP_SBJCT_GAPS        # Number of gaps in the aligned sbjct sequence.
               : 15 HSP_QUERY_START       # Starting coordinate of the query sequence.
               : 16 HSP_QUERY_END         # Ending coordinate of the query sequence.
               : 17 HSP_SBJCT_START       # Starting coordinate of the sbjct sequence.
               : 18 HSP_SBJCT_END         # Ending coordinate of the sbjct sequence.
               : 19 HSP_QUERY_STRAND      # Strand of the query sequence (TBLASTN/X only)
               : 20 HSP_SBJCT_STRAND      # Strand of the sbjct sequence (TBLASTN/X only)
               : 21 HSP_FRAME             # Frame for the sbjct translation (TBLASTN/X only)
               : 22 SBJCT_DESCRIPTION  (optional)  # Full description of the sbjct sequence from
               :                                  # the alignment section.
     Throws    : n/a
     Comments  : This method does not collect data based on tiling of the HSPs.
               : The table will contains redundant information since the hit name,
               : id, and other info for the hit are listed for each HSP.
               : If you need more flexibility in the output format than this
               : method provides, design a custom function.

   See Also  : `table_tiled' in this node(), `table_labels' in this
node(), `_display_hits' in this node()

table_labels
------------

     Usage     : print $blast_obj->table_labels( [get_desc] );
     Purpose   : Get column labels for table().
     Returns   : String containing column labels. Tab-delimited.
     Argument  : get_desc = boolean, if false the description column is not included.
               : Default: true (if not defined, include description column).
     Throws    : n/a

   See Also   : `table' in this node()

table_tiled
-----------

     Purpose   : Get data from tiled HSPs in tab-delimited format.
               : Allows only minimal flexibility in the output format.
               : If you need more flexibility, design a custom function.
     Usage     : $blast_obj->table_tiled( [get_desc]);
     Example   : print $blast->table_tiled;
               : print $blast->table_tiled(0);
               : # Call table_labels_tiled() if you want labels.
     Argument  : get_desc = boolean, if false the description of each hit is not included.
               :            Default: true (include description).
     Returns   : String containing tab-delimited set of data for each HSP
               : of each significant hit. Multiple hits are separated by newlines.
               : Left-to-Right order of fields:
               : 1 QUERY_NAME           # Sequence identifier of the query.
               : 2 QUERY_LENGTH         # Full length of the query sequence.
               : 3 SBJCT_NAME           # Sequence identifier of the sbjct ("hit".
               : 4 SBJCT_LENGTH         # Full length of the sbjct sequence.
               : 5 EXPECT               # Expect value for the alignment.
               : 6 SCORE                # Blast score for the alignment.
               : 7 BITS                 # Bit score for the alignment.
               : 8 NUM_HSPS             # Number of HSPs (not the "N" value).
               : 9 FRAC_IDENTICAL*      # fraction of identical substitutions.
               : 10 FRAC_CONSERVED*     # fraction of conserved ("positive") substitutions .
               : 11 FRAC_ALN_QUERY*     # fraction of the query sequence that is aligned.
               : 12 FRAC_ALN_SBJCT*     # fraction of the sbjct sequence that is aligned.
               : 13 QUERY_ALN_LENGTH*   # Length of the aligned portion of the query sequence.
               : 14 SBJCT_ALN_LENGTH*   # Length of the aligned portion of the sbjct sequence.
               : 15 QUERY_GAPS*         # Number of gaps in the aligned query sequence.
               : 16 SBJCT_GAPS*         # Number of gaps in the aligned sbjct sequence.
               : 17 QUERY_START*        # Starting coordinate of the query sequence.
               : 18 QUERY_END*          # Ending coordinate of the query sequence.
               : 19 SBJCT_START*        # Starting coordinate of the sbjct sequence.
               : 20 SBJCT_END*          # Ending coordinate of the sbjct sequence.
               : 21 AMBIGUOUS_ALN       # Ambiguous alignment indicator ('qs', 'q', 's').
               : 22 SBJCT_DESCRIPTION  (optional)  # Full description of the sbjct sequence from
               :                                  # the alignment section.
               :
               : * Items marked with a "*" report data summed across all HSPs
               :   after tiling them to avoid counting data from overlapping regions
               :   multiple times.
     Throws    : n/a
     Comments  : This function relies on tiling of the HSPs since it calls
               : frac_identical() etc. on the hit as opposed to each HSP individually.

   See Also   : `table' in this node(), `table_labels_tiled' in this
node(), *Bio::Tools::Blast::Sbjct::"HSP Tiling and Ambiguous Alignments"*,
`Links to related modules' in this node

table_labels_tiled
------------------

     Usage     : print $blast_obj->table_labels_tiled( [get_desc] );
     Purpose   : Get column labels for table_tiled().
     Returns   : String containing column labels. Tab-delimited.
     Argument  : get_desc = boolean, if false the description column is not included.
               : Default: true (include description column).
     Throws    : n/a

   See Also   : `table_tiled' in this node()

display
-------

     Usage     : $blast_object->display( %named_parameters );
     Purpose   : Display information about Bio::Tools::Blast.pm data members,
               : E.g., parameters of the report, data for each hit., etc.
               : Overrides Bio::Root::Object::display().
     Example   : $object->display(-SHOW=>'stats');
               : $object->display(-SHOW=>'stats,hits');
     Argument  : Named parameters: (TAGS CAN BE UPPER OR LOWER CASE)
               :     -SHOW  => 'file' | 'hits' | 'homol'
               :     -WHERE => filehandle (default = STDOUT)
     Returns   : n/a (print/printf is called)
     Status    : Experimental
     Comments  : For tab-delimited output, see table().

   See Also   : `_display_homol' in this node(), `_display_hits' in this
node(), `_display_stats' in this node(), `table' in this node(),
*Bio::Root::Tools::SeqAnal::display()*,`Links to related modules' in this
node,

_display_homol
--------------

     Usage     : n/a; called automatically by display()
     Purpose   : Print homology data for hits in the BLAST report.
     Example   : n/a
     Argument  : one argument = filehandle object.
     Returns   : printf call.
     Status    : Experimental

   See Also   : `homol_data' in this node(), `display' in this node()

_display_stats
--------------

     Usage     : n/a; called automatically by display()
     Purpose   : Display information about the Blast report "meta" data.
               : Overrides Bio::Tools::SeqAnal::_display_stats() calling it first.
     Example   : n/a
     Argument  : one argument = filehandle object.
     Returns   : printf call.
     Status    : Experimental

   See Also   : `display' in this node(),
*Bio::Tools::SeqAnal::_display_stats()*,`Links to related modules' in this
node

_display_hits
-------------

     Usage     : n/a; called automatically by display()
     Purpose   : Display data for each hit. Not tab-delimited.
     Example   : n/a
     Argument  : one argument = filehandle object.
     Returns   : printf call.
     Status    : Experimental
     Comments  : For tab-delimited output, see table().

   See Also   : `display' in this node(),
*Bio::Tools::Blast::Sbjct::display()*, `table' in this node(),  `Links to
related modules' in this node

to_html
-------

     Usage     : $blast_object->to_html( [%named_parameters] )
     Purpose   : To produce an HTML-formatted version of a BLAST report
               : for efficient navigation of the report using a web browser.
     Example   : # Using the static Blast object:
               : # Can read from STDIN or from a designated file:
               :   $Blast->to_html($file);
               :   $Blast->to_html(-FILE=>$file, -HEADER=>$header);
               :   (if no file is supplied, STDIN will be used).
               : # saving HTML to an array:
               :   $Blast->to_html(-FILE=>$file, -OUT =>\@out);
               : # Using a pre-existing blast object (must have been built from
               : # a file, not STDIN:
               :   $blastObj->to_html();
     Returns   : n/a, either prints report to STDOUT or saves to a supplied array
               : if an '-OUT' parameter is defined (see below).
     Argument  : %named_parameters: (TAGS ARE AND CASE INSENSITIVE).
               :    -FILE   => string containing name of a file to be processed.
               :               If not a valid file or undefined, STDIN will be used.
               :               Can skip the -FILE tag if supplying a filename
               :               as a single argument.
               :    -HEADER => string
               :               This should be an HTML-formatted string to be used
               :               as a header for the page, typically describing query sequence,
               :               database searched, the date of the analysis, and any
               :               additional links.
               :               If not supplied, no special header is used.
               :               Regardless of whether a header is supplied, the
               :               standard info at the top of the report is highlighted.
               :               This should include the <HEADER></HEADER> section
               :               of the page as well.
               :
               :    -IN    => array reference containing a raw Blast report.
               :              each line in a separate element in the array.
               :              If -IN is not supplied, read() is called
               :              and data is then read either from STDIN or a file.
               :
               :    -OUT   => array reference to hold the HTML output.
               :              If not supplied, output is sent to STDOUT.
     Throws    : Exception is propagated from $HTML::get_html_func()
               : and Bio::Root::Object::read().
     Comments  : The code that does the actual work is located in
               :  Bio::Tools::Blast::HTML::get_html_func().
     Bugs      : Some hypertext links to external databases may not be
               : correct. This due in part to the dynamic nature of
               : the web.
               : Hypertext links are not added to hits without database ids.
     TODO      : Possibly create a function to produce fancy default header
               : using data extracted from the report (requires some parsing).
               : For example, it would be nice to always include a date

   See Also   : *Bio::Tools::Blast::HTML::get_html_func()*,
*Bio::Root::Object::read()*, `Links to related modules' in this node

FOR DEVELOPERS ONLY
===================

Data Members
------------

   Information about the various data members of this module is provided
for those wishing to modify or understand the code. Two things to bear in
mind:

  1. Do NOT rely on these in any code outside of this module.  All data
     members are prefixed with an underscore to signify that they are
     private.  Always use accessor methods. If the accessor doesn't exist
     or is inadequate, create or modify an accessor (and let me know,
     too!). (An exception to this might be for Sbjct.pm or HSP.pm which
     are more tightly coupled to Blast.pm and may access Blast data
     members directly for efficiency purposes, but probably should not).

  2. This documentation may be incomplete and out of date.  It is easy for
     these data member descriptions to become obsolete as this module is
     still evolving. Always double check this info and search for members
     not described here.

        An instance of Bio::Tools::Blast.pm is a blessed reference to a
hash containing all or some of the following fields:

     FIELD           VALUE
     --------------------------------------------------------------
     _significance    P-value or Expect value cutoff (depends on Blast version:
     	          Blast1/WU-Blast2 = P-value; Blast2 = Expect value).
       	          Values GREATER than this are deemed not significant.

     _significant     Boolean. True if the query has one or more significant hit.

     _min_length      Integer. Query sequences less than this will be skipped.

     _confirm_significance  Boolean. True if client has supplied significance criteria.

     _gapped          Boolean. True if BLAST analysis has gapping turned on.

     _hits            List of Sbjct.pm objects.

     _num_hits        Number of hits obtained from the BLAST report.

     _num_hits_significant Number of significant based on Significant data members.

     _highestSignif   Highest P or Expect value overall (not just what is stored in _hits).

     _lowestSignif    Lowest P or Expect value overall (not just what is stored in _hits).

   The static $Blast object has a special set of members:

     _errs
     _share
     _stream
     _get_stats
     _gapped
     _filt_func

     Miscellaneous statistical parameters:
     -------------------------------------
      _filter, _matrix, _word_size, _expect, _gapCreation, _gapExtension, _s,
      _lambda, _k, _h

     INHERITED DATA MEMBERS
     -----------------------
     (See Bio::Tools::SeqAnal.pm for inherited data members.)

Bioperl BLAST High-Scoring Segment Pair object
**********************************************

NAME
====

   Bio::Tools::Blast::HSP.pm - Bioperl BLAST High-Scoring Segment Pair
object

SYNOPSIS
========

Object Creation
---------------

   The construction of HSP objects is handled by Bio::Tools::Blast::
Sbjct.pm.  You should not need to use this package directly. See
`_initialize' in this node() for a description of constructor parameters.

     require Bio::Tools::Blast::HSP;

     $hspObj = eval{ new Bio::Tools::Blast::HSP(-DATA    =>\@hspData,
     					       -PARENT  =>$sbjct_object,
     					       -NAME    =>$hspCount,
      		                               -PROGRAM =>'TBLASTN',
     					       );
     		};

   @hspData includes the raw BLAST report data for a specific HSP, and is
prepared by Bio::Tools::Blast::Sbjct.pm.

INSTALLATION
============

   This module is included with the central Bioperl distribution:

     http://bio.perl.org/Core/Latest
     ftp://bio.perl.org/pub/DIST

   Follow the installation instructions included in the README file.

DESCRIPTION
===========

   The Bio::Tools::Blast::HSP.pm module encapsulates data and methods for
manipulating, parsing, and analyzing HSPs ("High-scoring Segment Pairs")
derived from BLAST sequence analysis.

   This module is a utility module used by the
*Bio::Tools::Blast::Sbjct.pm* and is not intended for separate use. Please
see documentation for Bio::Tools::Blast.pm for some basic information
about using HSP objects (`Links:' in this node).

   * Supports BLAST versions 1.x and 2.x, gapped and ungapped.

   Bio::Tools::Blast::HSP.pm has the ability to extract a list of all
residue indices for identical and conservative matches along both query
and sbjct sequences. Since this degree of detail is not always needed,
this behavior does not occur during construction of the HSP object.  These
data will automatically be collected as necessary as the HSP.pm object is
used.

DEPENDENCIES
============

   Bio::Tools::Blast::HSP.pm is a concrete class that inherits from
*Bio::Root::Object.pm* and relies on *Bio::Tools::Sbjct.pm* as a container
for HSP.pm objects.  *Bio::Seq.pm* and *Bio::UnivAln.pm* are employed for
creating sequence and alignment objects, respectively.

Relationship to UnivAln.pm & Seq.pm
-----------------------------------

   HSP.pm can provide the query or sbjct sequence as a *Bio::Seq.pm*
object via the `seq' in this node() method. The HSP.pm object can also
create a two-sequence *Bio::UnivAln.pm* alignment object using the the
query and sbjct sequences via the `get_aln' in this node() method.
Creation of alignment objects is not automatic when constructing the
HSP.pm object since this level of functionality is not always required and
would generate a lot of extra overhead when crunching many reports.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules.  Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR
======

   Steve A. Chervitz, sac@genome.stanford.edu

SEE ALSO
========

     Bio::Tools::Blast::Sbjct.pm   - Blast hit object.
     Bio::Tools::Blast.pm          - Blast object.
     Bio::Seq.pm                   - Biosequence object
     Bio::UnivAln.pm               - Biosequence alignment object.
     Bio::Root::Object.pm          - Proposed base class for all Bioperl objects.

Links:
------

     http://bio.perl.org/Core/POD/Tools/Blast/Sbjct.pm.html

     http://bio.perl.org/Projects/modules.html  - Online module documentation
     http://bio.perl.org/Projects/Blast/        - Bioperl Blast Project
     http://bio.perl.org/                       - Bioperl Project Homepage

COPYRIGHT
=========

   Copyright (c) 1996-98 Steve A. Chervitz. All Rights Reserved.  This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

APPENDIX
========

   Methods beginning with a leading underscore are considered private and
are intended for internal use by this module. They are not considered part
of the public interface and are described here for documentation purposes
only.

_initialize
-----------

     Usage     : n/a; automatically called by Bio::Root::Object::new()
               : Bio::Tools::Blast::HSP.pm objects are constructed
               : automatically by Bio::Tools::Sbjct.pm, so there is no need
               : for direct consumption.
     Purpose   : Initializes HSP data and calls private methods to extract
               : the data for a given HSP.
               : Calls superclass constructor first (Bio::Root::Object.pm).
     Returns   : n/a
     Argument  : Named parameters passed from new():
               : All tags must be uppercase (does not call _rearrange()).
               :      -DATA    => array ref containing raw data for one HSP.
               :      -PARENT  => Sbjct.pm object ref.
               :      -NAME    => integer (1..n).
               :      -PROGRAM => string ('TBLASTN', 'BLASTP', etc.).

   See Also   : `_set_data' in this node(), *Bio::Root::Object::new()*,
*Bio::Tools::Blast::Sbjct::_set_hsps()*

_set_data
---------

     Usage     : n/a; called automatically during object construction.
     Purpose   : Sets the query sequence, sbjct sequence, and the "match" data
               : which consists of the symbols between the query and sbjct lines
               : in the alignment.
     Argument  : Array (all lines from a single, complete HSP, one line per element)
     Throws    : Propagates any exceptions from the methods called ("See Also")

   See Also   : `_set_seq' in this node(), `_set_residues' in this node(),
`_set_score_stats' in this node(), `_set_match_stats' in this node(),
`_initialize' in this node()

_set_score_stats
----------------

     Usage     : n/a; called automatically by _set_data()
     Purpose   : Sets various score statistics obtained from the HSP listing.
     Argument  : String with any of the following formats:
               : blast2:  Score = 30.1 bits (66), Expect = 9.2
               : blast2:  Score = 158.2 bits (544), Expect(2) = e-110
               : blast1:  Score = 410 (144.3 bits), Expect = 1.7e-40, P = 1.7e-40
               : blast1:  Score = 55 (19.4 bits), Expect = 5.3, Sum P(3) = 0.99
     Throws    : Exception if the stats cannot be parsed, probably due to a change
               : in the Blast report format.

   See Also   : `_set_data' in this node()

_set_match_stats
----------------

     Usage     : n/a; called automatically by _set_data()
     Purpose   : Sets various matching statistics obtained from the HSP listing.
     Argument  : blast2: Identities = 23/74 (31%), Positives = 29/74 (39%), Gaps = 17/74 (22%)
               : blast2: Identities = 57/98 (58%), Positives = 74/98 (75%)
               : blast1: Identities = 87/204 (42%), Positives = 126/204 (61%)
               : blast1: Identities = 87/204 (42%), Positives = 126/204 (61%), Frame = -3
               : WU-blast: Identities = 310/553 (56%), Positives = 310/553 (56%), Strand = Minus / Plus
     Throws    : Exception if the stats cannot be parsed, probably due to a change
               : in the Blast report format.
     Comments  : The "Gaps = " data in the HSP header has a different meaning depending
               : on the type of Blast: for BLASTP, this number is the total number of
               : gaps in query+sbjct; for TBLASTN, it is the number of gaps in the
               : query sequence only. Thus, it is safer to collect the data
               : separately by examining the actual sequence strings as is done
               : in _set_seq().

   See Also   : `_set_data' in this node(), `_set_seq' in this node()

_set_seq_data
-------------

     Usage     : n/a; called automatically when sequence data is requested.
     Purpose   : Sets the HSP sequence data for both query and sbjct sequences.
               : Includes: start, stop, length, gaps, and raw sequence.
     Argument  : n/a
     Throws    : Propagates any exception thrown by _set_match_seq()
     Comments  : Uses raw data stored by _set_data() during object construction.
               : These data are not always needed, so it is conditionally
               : executed only upon demand by methods such as gaps(), _set_residues(),
               : etc. _set_seq() does the dirty work.

   See Also   : `_set_seq' in this node()

_set_seq
--------

     Usage     : n/a; called automatically by _set_seq_data()
               : $hsp_obj->($seq_type, @data);
     Purpose   : Sets sequence information for both the query and sbjct sequences.
               : Directly counts the number of gaps in each sequence (if gapped Blast).
     Argument  : $seq_type = 'query' or 'sbjct'
               : @data = all seq lines with the form:
               : Query: 61  SPHNVKDRKEQNGSINNAISPTATANTSGSQQINIDSALRDRSSNVAAQPSLSDASSGSN 120
     Throws    : Exception if data strings cannot be parsed, probably due to a change
               : in the Blast report format.
     Comments  : Uses first argument to determine which data members to set
               : making this method sensitive data member name changes.
               : Behavior is dependent on the type of BLAST analysis (TBLASTN, BLASTP, etc).
     Warning   : Sequence endpoints are normalized so that start < end. This affects HSPs
               : for TBLASTN/X hits on the minus strand. Normalization facilitates use
               : of range information by methods such as match().

   See Also   : `_set_seq_data' in this node(), `matches' in this node(),
`range' in this node(), `start' in this node(), `end' in this node()

_set_residues
-------------

     Usage     : n/a; called automatically when residue data is requested.
     Purpose   : Sets the residue numbers representing the identical and
               : conserved positions. These data are obtained by analyzing the
               : symbols between query and sbjct lines of the alignments.
     Argument  : n/a
     Throws    : Propagates any exception thrown by _set_seq_data() and _set_match_seq().
     Comments  : These data are not always needed, so it is conditionally
               : executed only upon demand by methods such as seq_inds().
               : Behavior is dependent on the type of BLAST analysis (TBLASTN, BLASTP, etc).

   See Also   : `_set_seq_data' in this node(), `_set_match_seq' in this
node(), seq_inds()

_set_match_seq
--------------

     Usage     : n/a. Internal method.
               : $hsp_obj->_set_match_seq()
     Purpose   : Set the 'match' sequence for the current HSP (symbols in between
     	   : the query and sbjct lines.)
     Returns   : Array reference holding the match sequences lines.
     Argument  : n/a
     Throws    : Exception if the _matchList field is not set.
     Comments  : The match information is not always necessary. This method
               : allows it to be conditionally prepared.
               : Called by _set_residues>() and seq_str().

   See Also   : `_set_residues' in this node(), `seq_str' in this node()

score
-----

     Usage     : $hsp_obj->score()
     Purpose   : Get the Blast score for the HSP.
     Returns   : Integer
     Argument  : n/a
     Throws    : n/a

   See Also   : `bits' in this node()

bits
----

     Usage     : $hsp_obj->bits()
     Purpose   : Get the Blast score in bits for the HSP.
     Returns   : Float
     Argument  : n/a
     Throws    : n/a

   See Also   : `score' in this node()

n
-

     Usage     : $hsp_obj->n()
     Purpose   : Get the N value (num HSPs on which P/Expect is based).
               : This value is not defined with NCBI Blast2 with gapping.
     Returns   : Integer or null string if not defined.
     Argument  : n/a
     Throws    : n/a
     Comments  : The 'N' value is listed in parenthesis with P/Expect value:
               : e.g., P(3) = 1.2e-30  ---> (N = 3).
               : Not defined in NCBI Blast2 with gaps.
               : This typically is equal to the number of HSPs but not always.
               : To obtain the number of HSPs, use Bio::Tools::Blast::Sbjct::num_hsps().

   See Also   : `score' in this node()

frame
-----

     Usage     : $hsp_obj->frame()
     Purpose   : Get the reading frame number (-/+ 1, 2, 3) (TBLASTN/X only).
     Returns   : Integer or null string if not defined.
     Argument  : n/a
     Throws    : n/a

signif()
--------

     Usage     : $hsp_obj->signif()
     Purpose   : Get the P-value or Expect value for the HSP.
     Returns   : Float (0.001 or 1.3e-43)
               : Returns P-value if it is defined, otherwise, Expect value.
     Argument  : n/a
     Throws    : n/a
     Comments  : Provided for consistency with Sbjct::signif()
               : Support for returning the significance data in different
               : formats (e.g., exponent only), is not provided for HSP objects.
               : This is only available for the Sbjct or Blast object.

   See Also   : `p' in this node(), `expect' in this node(),
*Bio::Tools::Blast::Sbjct::signif()*

expect
------

     Usage     : $hsp_obj->expect()
     Purpose   : Get the Expect value for the HSP.
     Returns   : Float (0.001 or 1.3e-43)
     Argument  : n/a
     Throws    : n/a
     Comments  : Support for returning the expectation data in different
               : formats (e.g., exponent only), is not provided for HSP objects.
               : This is only available for the Sbjct or Blast object.

   See Also   : `p' in this node()

p
-

     Usage     : $hsp_obj->p()
     Purpose   : Get the P-value for the HSP.
     Returns   : Float (0.001 or 1.3e-43) or undef if not defined.
     Argument  : n/a
     Throws    : n/a
     Comments  : P-value is not defined with NCBI Blast2 reports.
               : Support for returning the expectation data in different
               : formats (e.g., exponent only) is not provided for HSP objects.
               : This is only available for the Sbjct or Blast object.

   See Also   : `expect' in this node()

length
------

     Usage     : $hsp->length( [seq_type] )
     Purpose   : Get the length of the aligned portion of the query or sbjct.
     Example   : $hsp->length('query')
     Returns   : integer
     Argument  : seq_type: 'query' | 'sbjct' | 'total'  (default = 'total')
     Throws    : n/a
     Comments  : 'total' length is the full length of the alignment
               : as reported in the denominators in the alignment section:
               : "Identical = 34/120 Positives = 67/120".
               : Developer note: when using the built-in length function within
               : this module, call it as CORE::length().

   See Also   : `gaps' in this node()

gaps
----

     Usage     : $hsp->gaps( [seq_type] )
     Purpose   : Get the number of gaps in the query, sbjct, or total alignment.
               : Also can return query gaps and sbjct gaps as a two-element list
               : when in array context.
     Example   : $total_gaps      = $hsp->gaps();
               : ($qgaps, $sgaps) = $hsp->gaps();
               : $qgaps           = $hsp->gaps('query');
     Returns   : scalar context: integer
               : array context without args: (int, int)  =  ('queryGaps', 'sbjctGaps')
     Argument  : seq_type: 'query' | 'sbjct' | 'total'
               : (default = 'total', scalar context)
               : Array context can be "induced" by providing an argument of 'list' or 'array'.
     Throws    : n/a

   See Also   : `length' in this node(), `matches' in this node()

matches
-------

     Usage     : $hsp->matches([seq_type], [start], [stop]);
     Purpose   : Get the total number of identical and conservative matches
               : in the query or sbjct sequence for the given HSP. Optionally can
               : report data within a defined interval along the seq.
               : (Note: 'conservative' matches are called 'positives' in the
     	   : Blast report.)
     Example   : ($id,$cons) = $hsp_object->matches('sbjct');
               : ($id,$cons) = $hsp_object->matches('query',300,400);
     Returns   : 2-element array of integers
     Argument  : (1) seq_type = 'query' | 'sbjct' (default = query)
               : (2) start = Starting coordinate (optional)
               : (3) stop  = Ending coordinate (optional)
     Throws    : Exception if the supplied coordinates are out of range.
     Comments  : Relies on seq_str('match') to get the string of alignment symbols
               : between the query and sbjct lines which are used for determining
               : the number of identical and conservative matches.

   See Also   : `length' in this node(), `gaps' in this node(), `seq_str'
in this node(), *Bio::Tools::Blast::Sbjct::_adjust_contigs()*

frac_identical
--------------

     Usage     : $hsp_object->frac_identical( [seq_type] );
     Purpose   : Get the fraction of identical positions within the given HSP.
     Example   : $frac_iden = $hsp_object->frac_identical('query');
     Returns   : Float (2-decimal precision, e.g., 0.75).
     Argument  : seq_type: 'query' | 'sbjct' | 'total'
               : default = 'total' (but see comments below).
     Throws    : n/a
     Comments  : Different versions of Blast report different values for the total
               : length of the alignment. This is the number reported in the
               : denominators in the stats section:
               : "Identical = 34/120 Positives = 67/120".
               : BLAST-GP uses the total length of the alignment (with gaps)
               : WU-BLAST uses the length of the query sequence (without gaps).
               : Therefore, when called without an argument or an argument of 'total',
               : this method will report different values depending on the
               : version of BLAST used.
               :
               : To get the fraction identical among only the aligned residues,
               : ignoring the gaps, call this method with an argument of 'query'
               : or 'sbjct'.

   See Also   : `frac_conserved' in this node(), `num_identical' in this
node(), `matches' in this node()

frac_conserved
--------------

     Usage     : $hsp_object->frac_conserved( [seq_type] );
     Purpose   : Get the fraction of conserved positions within the given HSP.
               : (Note: 'conservative' positions are called 'positives' in the
     	   : Blast report.)
     Example   : $frac_cons = $hsp_object->frac_conserved('query');
     Returns   : Float (2-decimal precision, e.g., 0.75).
     Argument  : seq_type: 'query' | 'sbjct'
               : default = 'total' (but see comments below).
     Throws    : n/a
     Comments  : Different versions of Blast report different values for the total
               : length of the alignment. This is the number reported in the
               : denominators in the stats section:
               : "Identical = 34/120 Positives = 67/120".
               : BLAST-GP uses the total length of the alignment (with gaps)
               : WU-BLAST uses the length of the query sequence (without gaps).
               : Therefore, when called without an argument or an argument of 'total',
               : this method will report different values depending on the
               : version of BLAST used.
               :
               : To get the fraction conserved among only the aligned residues,
               : ignoring the gaps, call this method with an argument of 'query'
               : or 'sbjct'.

   See Also   : `frac_conserved' in this node(), `num_conserved' in this
node(), `matches' in this node()

num_identical
-------------

     Usage     : $hsp_object->num_identical();
     Purpose   : Get the number of identical positions within the given HSP.
     Example   : $num_iden = $hsp_object->num_identical();
     Returns   : integer
     Argument  : n/a
     Throws    : n/a

   See Also   : `num_conserved' in this node(), `frac_identical' in this
node()

num_conserved
-------------

     Usage     : $hsp_object->num_conserved();
     Purpose   : Get the number of conserved positions within the given HSP.
     Example   : $num_iden = $hsp_object->num_conserved();
     Returns   : integer
     Argument  : n/a
     Throws    : n/a

   See Also   : `num_identical' in this node(), `frac_conserved' in this
node()

range
-----

     Usage     : $hsp->range( [seq_type] );
     Purpose   : Gets the (start, end) coordinates for the query or sbjct sequence
               : in the HSP alignment.
     Example   : ($qbeg, $qend) = $hsp->range('query');
               : ($sbeg, $send) = $hsp->range('sbjct');
     Returns   : Two-element array of integers
     Argument  : seq_type = string, 'query' or 'sbjct'  (default = 'query')
               : (case insensitive).
     Throws    : n/a

   See Also   : `start' in this node(), `end' in this node()

start
-----

     Usage     : $hsp->start( [seq_type] );
     Purpose   : Gets the start coordinate for the query, sbjct, or both sequences
               : in the HSP alignment.
     Example   : $qbeg = $hsp->start('query');
               : $sbeg = $hsp->start('sbjct');
               : ($qbeg, $sbeg) = $hsp->start();
     Returns   : scalar context: integer
               : array context without args: list of two integers
     Argument  : In scalar context: seq_type = 'query' or 'sbjct'
               :  (case insensitive). If not supplied, 'query' is used.
               : Array context can be "induced" by providing an argument of 'list' or 'array'.
     Throws    : n/a

   See Also   : `end' in this node(), `range' in this node()

end
---

     Usage     : $hsp->end( [seq_type] );
     Purpose   : Gets the end coordinate for the query, sbjct, or both sequences
               : in the HSP alignment.
     Example   : $qbeg = $hsp->end('query');
               : $sbeg = $hsp->end('sbjct');
               : ($qbeg, $sbeg) = $hsp->end();
     Returns   : scalar context: integer
               : array context without args: list of two integers
     Argument  : In scalar context: seq_type = 'query' or 'sbjct'
               :  (case insensitive). If not supplied, 'query' is used.
               : Array context can be "induced" by providing an argument of 'list' or 'array'.
     Throws    : n/a

   See Also   : `start' in this node(), `range' in this node()

strand
------

     Usage     : $hsp_object->strand( [seq_type] )
     Purpose   : Get the strand of the query or sbjct sequence.
     Example   : print $hsp->strand('query');
               : ($qstrand, $sstrand) = $hsp->strand();
     Returns   : -1, 0, or 1
               : -1 = Minus strand, +1 = Plus strand
               : Returns 0 if strand is not defined, which occurs
               : for non-TBLASTN/X reports.
               : In scalar context without arguments, returns queryStrand value.
               : In array context without arguments, returns a two-element list
               :    of strings (queryStrand, sbjctStrand).
               : Array context can be "induced" by providing an argument of 'list' or 'array'.
     Argument  : seq_type: 'query' | 'sbjct' or undef
     Throws    : n/a

   See Also   : `_set_seq' in this node(), `_set_match_stats' in this
node()

seq
---

     Usage     : $hsp->seq( [seq_type] );
     Purpose   : Get the query or sbjct sequence as a Bio::Seq.pm object.
     Example   : $seqObj = $hsp->seq('query');
     Returns   : Object reference for a Bio::Seq.pm object.
     Argument  : seq_type = 'query' or 'sbjct' (default = 'query').
     Throws    : Propagates any exception that occurs during construction
               : of the Bio::Seq.pm object.
     Comments  : The sequence is returned in an array of strings corresponding
               : to the strings in the original format of the Blast alignment.
               : (i.e., same spacing).

   See Also   : `seq_str' in this node(), `seq_inds' in this node(),
*Bio::Seq.pm*

seq_str
-------

     Usage     : $hsp->seq_str( seq_type );
     Purpose   : Get the full query, sbjct, or 'match' sequence as a string.
               : The 'match' sequence is the string of symbols in between the
               : query and sbjct sequences.
     Example   : $str = $hsp->seq_str('query');
     Returns   : String
     Argument  : seq_Type = 'query' or 'sbjct' or 'match'
     Throws    : Exception if the argument does not match an accepted seq_type.
     Comments  : Calls _set_residues() to set the 'match' sequence if it has
               : not been set already.

   See Also   : `seq' in this node(), `seq_inds' in this node(),
`_set_match_seq' in this node()

seq_inds
--------

     Usage     : $hsp->seq_inds( seq_type, class, collapse );
     Purpose   : Get a list of residue positions (indices) for all identical
               : or conserved residues in the query or sbjct sequence.
     Example   : @ind = $hsp->seq_inds('query', 'identical');
               : @ind = $hsp->seq_inds('sbjct', 'conserved');
               : @ind = $hsp->seq_inds('sbjct', 'conserved', 1);
     Returns   : List of integers
               : May include ranges if collapse is true.
     Argument  : seq_type  = 'query' or 'sbjct'  (default = query)
               : class     = 'identical' or 'conserved' (default = identical)
               :              (can be shortened to 'id' or 'cons')
               :              (actually, anything not 'id' will evaluate to 'conserved').
               : collapse  = boolean, if true, consecutive positions are merged
               :             using a range notation, e.g., "1 2 3 4 5 7 9 10 11"
               :             collapses to "1-5 7 9-11". This is useful for
               :             consolidating long lists. Default = no collapse.
     Throws    : n/a.
     Comments  : Calls _set_residues() to set the 'match' sequence if it has
               : not been set already.

   See Also   : `seq' in this node(), `_set_residues' in this node(),
`collapse_nums' in this node(), *Bio::Tools::Blast::Sbjct::seq_inds()*

get_aln
-------

     Usage     : $hsp->get_aln()
     Purpose   : Get a Bio::UnivAln.pm object constructed from the query + sbjct
               : sequences of the present HSP object.
     Example   : $aln_obj = $hsp->get_aln();
     Returns   : Object reference for a Bio::UnivAln.pm object.
     Argument  : n/a.
     Throws    : Propagates any exception ocurring during the construction of
               : the Bio::UnivAln object.
     Comments  : Requires Bio::UnivAln.pm.
               : The Bio::UnivAln.pm object is constructed from the query + sbjct
               : sequence objects obtained by calling seq().
               : Gap residues are included (see $GAP_SYMBOL). It is important that
               : Bio::UnivAln.pm recognizes the gaps correctly. A strategy for doing
               : this is being considered. Currently it is hard-wired.

   See Also   : `seq' in this node(), *Bio::UnivAln.pm*

display
-------

     Usage     : $sbjct_object->display( %named_parameters );
     Purpose   : Display information about Bio::Tools::Blast::Sbjct.pm data members
               : including:  length, gaps, score, significance value,
               :             sequences and sequence indices.
     Example   : $object->display(-SHOW=>'stats');
     Argument  : Named parameters: (TAGS CAN BE UPPER OR LOWER CASE)
               :          -SHOW  => 'hsp',
               :          -WHERE => filehandle (default = STDOUT)
     Returns   : n/a
     Status    : Experimental
     Comments  : For more control over the display of sequence data,
               : use seq(), seq_str(), seq_inds().

   See Also   : `_display_seq' in this node(), `seq' in this node(),
`seq_str' in this node(), `seq_inds' in this node(), `_display_matches' in
this node(), *Bio::Root::Object::display()*

_display_seq
------------

     Usage     : n/a; called automatically by display()
     Purpose   : Display information about query and sbjct HSP sequences.
               : Prints the start, stop coordinates and the actual sequence.
     Example   : n/a
     Argument  :
     Returns   : printf call.
     Status    : Experimental
     Comments  : For more control, use seq(), seq_str(), or seq_inds().

   See Also   : `display' in this node(), `seq' in this node(), `seq_str'
in this node(), `seq_inds' in this node(), `_display_matches' in this
node()

_display_matches
----------------

     Usage     : n/a; called automatically by display()
     Purpose   : Display information about identical and conserved positions
               : within both the query and sbjct sequences.
     Example   : n/a
     Argument  :
     Returns   : printf call.
     Status    : Experimental
     Comments  : For more control, use seq_inds().

   See Also   : `display' in this node(), `seq_inds' in this node(),
`_display_seq' in this node(),

homol_data
----------

     Usage     : $data = $hsp_object->homo_data( %named_params );
     Purpose   : Gets similarity data for a single HSP.
     Returns   : String:
               : "Homology data" for each HSP is in the format:
               :  "<integer> <start> <stop>"
               :  where integer is the value returned by homol_score().
     Argument  : Named params:  (UPPER OR LOWERCASE TAGS)
               :   currently just one param is used:
               :   -SEQ =>'query' or 'sbjct'
     Throws    : n/a
     Status    : Experimental
     Comments  : This is a very experimental method used for obtaining a
               : coarse indication of:
               :   1) how strong the similarity is between the sequences in the HSP,
               :   3) the endpoints of the alignment (sequence monomer numbers)

   See Also   : `homol_score' in this node(),
*Bio::Tools::Blast.::homol_data()*,
*Bio::Tools::Blast::Sbjct::homol_data()*

homol_score
-----------

     Usage     : $self->homol_score();
     Purpose   : Get a homology score (integer 1 - 3) as a coarse representation of
               : the strength of the similarity independent of sequence composition.
               : Based on the Blast bit score.
     Example   : $hscore = $hsp->homol_score();
     Returns   : Integer
     Argument  : n/a
     Throws    : n/a
     Status    : Experimental
     Comments  : See @Bio::Tools::Blast::HSP::SCORE_CUTOFFS for the specific values.
               : Currently,  BIT_SCORE  HOMOL_SCORE
               :             ---------  -----------
               :             >=100     --> 3
               :               30-100  --> 2
               :             < 30      --> 1

   See Also   : `homol_data' in this node()

CLASS METHODS
=============

collapse_nums
-------------

     Usage     : @cnums = collapse_nums( @numbers );
     Purpose   : Collapses a list of numbers into a set of ranges of consecutive terms:
               : Useful for condensing long lists of consecutive numbers.
               :  EXPANDED:
               :     1 2 3 4 5 6 10 12 13 14 15 17 18 20 21 22 24 26 30 31 32
               :  COLLAPSED:
               :     1-6 10 12-15 17 18 20-22 24 26 30-32
     Argument  : List of numbers and sorted numerically.
     Returns   : List of numbers mixed with ranges of numbers (see above).
     Throws    : n/a
     Comments  : Probably belongs in a more general utility class.

   See Also   : `seq_inds' in this node()

FOR DEVELOPERS ONLY
===================

Data Members
------------

   Information about the various data members of this module is provided
for those wishing to modify or understand the code. Two things to bear in
mind:

  1. Do NOT rely on these in any code outside of this module.  All data
     members are prefixed with an underscore to signify that they are
     private.  Always use accessor methods. If the accessor doesn't exist
     or is inadequate, create or modify an accessor (and let me know,
     too!).

  2. This documentation may be incomplete and out of date.  It is easy for
     these data member descriptions to become obsolete as this module is
     still evolving. Always double check this info and search for members
     not described here.

        An instance of Bio::Tools::Blast::HSP.pm is a blessed reference to
a hash containing all or some of the following fields:

     FIELD           VALUE
     --------------------------------------------------------------
     (member names are mostly self-explanatory)

     _score              :
     _bits               :
     _p                  :
     _n                  : Integer. The 'N' value listed in parenthesis with P/Expect value:
                         : e.g., P(3) = 1.2e-30  ---> (N = 3).
                         : Not defined in NCBI Blast2 with gaps.
                         : To obtain the number of HSPs, use Bio::Tools::Blast::Sbjct::num_hsps().
     _expect             :
     _queryLength        :
     _queryGaps          :
     _queryStart         :
     _queryStop          :
     _querySeq           :
     _sbjctLength        :
     _sbjctGaps          :
     _sbjctStart         :
     _sbjctStop          :
     _sbjctSeq           :
     _matchSeq           : String. Contains the symbols between the query and sbjct lines
                           which indicate identical (letter) and conserved ('+') matches
                           or a mismatch (' ').
     _numIdentical       :
     _numConserved       :
     _identicalRes_query :
     _identicalRes_sbjct :
     _conservedRes_query :
     _conservedRes_sbjct :
     _match_indent       : The number of leading space characters on each line containing
                           the match symbols. _match_indent is 13 in this example:
                             Query:   285 QNSAPWGLARISHRERLNLGSFNKYLYDDDAG
                                          Q +APWGLARIS       G+ + Y YD+ AG
                             ^^^^^^^^^^^^^

     INHERITED DATA MEMBERS

     _name          : From Bio::Root::Object.pm.
     		:
     _parent        : From Bio::Root::Object.pm. This member contains a reference to the
     		: Bio::Tools::Blast::Sbjct.pm object to which this hit belongs.

Bioperl Utility module for HTML formatting Blast reports
********************************************************

NAME
====

   Bio::Tools::Blast::HTML.pm - Bioperl Utility module for HTML formatting
Blast reports

SYNOPSIS
========

Adding HTML-formatting
----------------------

     use Bio::Tools::Blast::HTML qw(&get_html_func);

     $func = &get_html_func();

     # Now as each line of the report is read, pass it to &$func($line).

   See `get_html_func' in this node() for details.  Also see
*Bio::Tools::Blast::to_html* for an example of usage.

Removing HTML-formatting
------------------------

     use Bio::Tools::Blast::HTML qw(&strip_html);

     &strip_html(\$blast_report_string)

   See `strip_html' in this node() for details.

INSTALLATION
============

   This module is included with the central Bioperl distribution:

     http://bio.perl.org/Core/Latest
     ftp://bio.perl.org/pub/DIST

   Follow the installation instructions included in the README file.

DESCRIPTION
===========

   This module can be used to add HTML formatting to or remove HTML
formatting from a raw Blast sequence analysis report. Hypertext links to
the appropriate database are added for each hit sequence (GenBank,
Swiss-Prot, PIR, PDB, SGD).

   This module is intended for use by Bio::Tools::Blast.pm and related
modules, which provides a front-end to the methods in
Bio::Tools::Blast::HTML.pm.

DEPENDENCIES
============

   Bio::Tools::Blast::HTML.pm does not inherit from any other class
besides Exporter.  It is used by Bio::Tools::Blast.pm only.  This class
relies on *Bio::Tools::WWW.pm* to provide key URLS for adding links in the
Blast report to specific databases.

   The greatest dependency comes from the dynamic state of the web. URLs
are are likely to change in the future, so all links cannot be guaranteed
to work indefinitely.  Feel free to report broken or incorrect database
links (`FEEDBACK' in this node). Thanks!

SEE ALSO
========

     Bio::Tools::Blast.pm    - Blast object.
     Bio::Tools::WWW.pm      - URL repository.

     http://bio.perl.org/Projects/modules.html  - Online module documentation
     http://bio.perl.org/Projects/Blast/        - Bioperl Blast Project
     http://bio.perl.org/                       - Bioperl Project Homepage

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules.  Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and  their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR
======

   Steve A. Chervitz, sac@genome.stanford.edu

COPYRIGHT
=========

   Copyright (c) 1998-2000 Steve A. Chervitz. All Rights Reserved.  This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

APPENDIX
========

   Methods beginning with a leading underscore are considered private and
are intended for internal use by this module. They are not considered part
of the public interface and are described here for documentation purposes
only.

get_html_func
-------------

     Usage     : $func_ref = &get_html_func( [array_ref] );
               : This method is exported.
     Purpose   : Provides a function that adds HTML formatting to a
               : raw Blast report line-by-line.
               : Utility method used by to_html() in Bio::Tools::Blast.pm.
     Returns   : Reference to an anonymous function to be used while reading in
               : the raw report.
               : The function itself operates on the Blast report line-by-line
               : HTML-ifying it and printing it to STDOUT (or saving in the supplied
               : array ref) as it goes:
               :     foreach( @raw_report ) { &$func_ref($_); }
     Argument  : array ref (optional) for storing the HTML-formatted report.
               : If no argument is supplied, HTML output is sent to STDOUT.
     Throws    : Croaks if an argument is supplied and is not an array ref.
               : The anonymous function returned by this method croaks if
               : the Blast output appears to be HTML-formatted already.
     Comments  : Adapted from a script by Keith Robison  November 1993
               : krobison@nucleus.harvard.edu; http://golgi.harvard.edu/gilbert.html
               : Modified extensively by Steve Chervitz and Mike Cherry.
               : Some modifications are customizations for BLAST reports served up
               : by the Saccharomyces Genome Database.
               : Feel free to modify or replace portions of this code as necessary
               : to accomodate new BLAST datasets or changes to the Blast format.

   See Also   : *Bio::Tools::Blast::to_html()*

_set_markup_data
----------------

     Usage     : n/a; utility method used by get_html_func()
     Purpose   : Sets various hashes and regexps used for adding HTML
               : to raw Blast output.
     Returns   : n/a
     Comments  : These items need be set only once.

   See Also   : `get_html_func' in this node()

_markup_database
----------------

     Usage     : n/a; utility method used by get_html_func()
     Purpose   : Converts a cryptic database ID into a readable name.
     Returns   : n/a
     Comments  : This is used for converting local database IDs into
               : understandable terms. At present, it only recognizes
               : databases used locally at SGD.

   See Also   : `get_html_func' in this node()

_markup_report
--------------

     Usage     : n/a; utility function used by get_html_func()
     Purpose   : Adds HTML links to aid navigation of raw Blast output.
     Returns   : n/a
     Comments  : HTML-formatting is dependent on the Blast server that
               : provided the Blast report. Currently, this function can handle reports
               : produced by NCBI and SGD. Feel free to modify this function
               : to accomodate reports produced by other servers/sites.
               :
               : This function is simply a collection of substitution regexps
               : that recognize and modify the relevant lines of the Blast report.
               : All non-header lines of the report are passed through this function,
               : only the ones that match will get modified.
               :
               : The general scheme for adding links is as follows:
               : (Some of the SGD markups do not follow this scheme precisely
               :  but this is the general trend.)
               :
               : For description lines in the summary table at the top of report:
               :
               : DB:SEQUENCE_ID  DESCRIPTION   SIGNIF_VAL
               :        DB          = links to the indicated database (if not Gen/Embl/Ddbj).
               :        SEQUENCE_ID = links to GenBank entry for the sequence.
               :        SIGNIF_VAL  = internal link to relevant alignment section.
               :
               : For the alignment sections in the body of the report:
               :
               : DB:SEQUENCE_ID  (Back | Top) DESCRIPTION
               :        DB          = links to the indicated database (if not Gen/Embl/Ddbj).
               :        SEQUENCE_ID = links to GenBank entry for the sequence.
               :        SIGNIF_VAL  = internal link to alignment section.
               :        Back        = internal link to description line in summary section.
               :        Top         = internal link to top of page.
               :
               : 'DB' links are created for PDB, PIR, and SwissProt sequences.
               :
               : RE_PARSING HTML-FOMRATTED REPORTS:
               : ----------------------------------
               : HTML-formatted reports generated by this module, as well as reports
               : obtained from the NCBI servers, should be parsable
               : by Bio::Tools::Blast.pm. Parsing HTML-formatted reports is
               : slow, however, since the HTML must be removed prior to parsing.
               : Parsing HTML-formatted reports is dependent on the specific structure
               : of the HTML and is generally not recommended.
               :
               : Note that since URLs can change without notice, links will need updating.
               : The links are obtained from Bio::Tools::WWW.pm updating that module
               : will update this as well.
               :
     Bugs      : Some links to external databases are incorrect
               : (in particular, for 'bbs' and 'prf' databases on NCBI Blast reports.
               : Some links may fail as a result of the dynamic nature of the web.
               : Hypertext links are not added to hits without database ids.

   See Also   : `get_html_func' in this node(), *Bio::Tools::WWW.pm*,
`strip_html' in this node()

_prog_ref_html
--------------

     Usage     : n/a; utility method used by get_html_func().
     Purpose   : Get a special alert for BLAST reports against all of GenBank/EMBL.
     Returns   : string with HTML

   See Also   : `get_html_func' in this node()

_genbank_alert
--------------

     Usage     : n/a; utility method used by get_html_func().
     Purpose   : Get a special alert for BLAST reports against all of GenBank/EMBL.
     Returns   : string with HTML

   See Also   : `get_html_func' in this node()

strip_html
----------

     Usage     : $boolean = &strip_html( string_ref );
               : This method is exported.
     Purpose   : Removes HTML formatting from a supplied string.
               : Attempts to restore the Blast report to enable
               : parsing by Bio::Tools::Blast.pm.
     Returns   : Boolean: true if string was stripped, false if not.
     Argument  : string_ref = reference to a string containing the whole Blast
               :              report.
     Throws    : Croaks if the argument is not a scalar reference.
     Comments  : Based on code originally written by Alex Dong Li
               : (ali@genet.sickkids.on.ca).
               : This method does some Blast-specific stripping
               : (adds back a '>' character in front of each HSP
               : alignment listing).
               :
               : THIS METHOD IS HIGHLY ERROR-PRONE!
               :
               : Removal of the HTML tags and accurate reconstitution of the
               : non-HTML-formatted report is highly dependent on structure of
               : the HTML-formatted version. For example, it assumes that first
               : line of each alignment section (HSP listing) starts with a
               : <a name=..> anchor tag. This permits the reconstruction of the
               : original report in which these lines begin with a ">".
               : This is required for parsing.
               :
               : If the structure of the Blast report itself is not intended to
               : be a standard, the structure of the HTML-formatted version
               : is even less so. Therefore, the use of this method to
               : reconstitute parsable Blast reports from HTML-format versions
               : should be considered a temorary solution.

   See Also   : *Bio::Tools::Blast::parse()*

Bioperl module for running Blast analyses locally.
**************************************************

NAME
====

   Bio::Tools::Blast::Run::LocalBlast.pm - Bioperl module for running
Blast analyses locally.

SYNOPSIS
========

     use Bio::Tools::Blast::Run::LocalBlast qw(&blast_local);

     &blast_local( %named_parameters);

   See `blast_local' in this node() for a description of available
parameters.

INSTALLATION
============

   This module is included with the central Bioperl distribution:

     http://bio.perl.org/Core/Latest
     ftp://bio.perl.org/pub/DIST

   Follow the installation instructions included in the README file.

DESCRIPTION
===========

   Bio::Tools::Blast::Run::LocalBlast.pm contains methods and data
necessary for running Blast sequence analyses on a local machine. This
module must be customized for a specific site.

   The basic requirements are that it conform to this minimal API:

  1. Export a method called `blast_local' in this node() that accepts a
     Bio::Tools::Blast.pm object + named parameters as specified by
     `blast_local' in this node().

  2. The `blast_local' in this node() method should return a list of names
     of files containing the raw Blast reports.

  3. Exporting arrays containing a list of available databases in the
     arrays `@Blast_dbn_local' and `@Blast_dbp_local'.

        The generic version of this module provides some rudimentary logic,
but feel free to customize as necessary.

Script Files
------------

   Sometimes it is convenient to write an executable shell script for
running a set of Blasts on a local machine. This script can be saved and
re-executed as necessary or saved for documentation purposes. This module
could provide a convenient way to consolidate the logic necessary for
producing such script files or perhaps stubs of script file that could be
further modified for Blast-ing specific datasets.

DEPENDENCIES
============

   Bio::Tools::Blast::Run::LocalBast.pm is used by Bio::Tools::Blast.pm
The development of this is linked with the Blast.pm module and should be
updated along with that module.

SEE ALSO
========

     Bio::Tools::Blast.pm                    - Blast object.
     Bio::Tools::Blast::Run::postclient.pl   - Script for accessing remote server.
     Bio::Tools::Blast::Run::Webblast.pm     - Utility module for running Blasts remotely.
     Bio::Tools::Blast::HTML.pm              - Blast HTML-formating utility class.
     Bio::Seq.pm                             - Biosequence object

     http://bio.perl.org/Projects/modules.html  - Online module documentation
     http://bio.perl.org/Projects/Blast/        - Bioperl Blast Project
     http://bio.perl.org/                       - Bioperl Project Homepage

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules.  Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR
======

   Steve A. Chervitz, sac@genome.stanford.edu

VERSION
=======

   Bio::Tools::Blast::Run::LocalBlast.pm, 0.01

COPYRIGHT
=========

   Copyright (c) 1998 Steve A. Chervitz. All Rights Reserved.  This module
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

APPENDIX
========

   Methods beginning with a leading underscore are considered private and
are intended for internal use by this module. They are not considered part
of the public interface and are described here for documentation purposes
only.

blast_local
-----------

     Usage     : @files = blast_local($blast_object,  %namedParameters);
               : This method is exported.
     Purpose   : Run a local Blast analysis on one or more sequences.
               : This method defines the API for your LocalBlast.pm module.
     Returns   : Array containing a list of filenames of the Blast reports.
     Argument  : $blast_object = object ref for a Bio::Tools::Blast.pm object.
               : %named parameters: (PARAMETER TAGS CAN BU UPPER OR LOWER CASE)
               : These are some basic parameters. Supply more as desired.
               :
               :   -SEQS       => ref to an array of Bio::Seq.pm objects.
               :   -SEQ_FILES  => ref to an array of strings containing full-path file names.
               :   -PROG       => name of blast program (blastp, blastx, etc.)
               :   -DATABASE   => name of database (see below.)
               :   -EXPECT     => expect value cutoff
               :   -FILTER     => sequence complexity filter ('default' or 'none')
               :   -MATRIX     => substitution scoring matrix (blast1 only for NCBI server)
               :   -DESCR      => integer, number of on-line descriptions (V, 100)
               :   -ALIGN      => integer, number of alignments (B, 100)
               :   -GAP        => 'on' or 'off'
               :   -OUT_DIR    => output directory to store blast result files
               :
     Throws    : Exception if:
               :   - Cannot obtain parameters by calling _rearrange() on the
               :     first argument, which should be a Bio::Tools::Blast.pm object ref.
               :   - No sequences are provided (objects or files).
               :   - Sequence type is incompatible with Blast program type.
               :   - Database name is not one of the valid names.
     Comments  :
      -------------------------------------------------------------
      Available programs: blastn, blastx, blastp, tblastn, tblastx

     -------------------------------------------------------------
     Available local databases are:

     LIST YOUR LOCAL DATABASES HERE.
      These are exported by this module in the @Blast_dbp_local
      and @Blast_dbn_local arrays.
       -------------------------------------------------------------
       Available substitution scoring matrices:
      (Here are the standard ones)
      BLOSUM: 100,90,85,80,75,70,65,62,60,55,50,45,40,35,30
      PAM:    500,490,480,470,460,450,440,430,420,410,400,390,380,370,360,350
              340,330,320,310,300,290,280,270,260,250,240,230,220,210,200,190,
              180,170,160,150,140,130,120,110,100,90,80,70,60,50,40,30,20,10
      OTHER: DAYHOFF, GONNET, IDENTITY, MATCH

     These are exported by this module in the @Blast_matrix_local
       -------------------------------------------------------------
       Available sequence complexity filters:
        SEG, SEG+XNU, XNU, dust, none.

   See Also : _set_options(), _validate_options(), _blast_seqs(),
_blast_files(), Bio::Tools::Blast.pm

Bioperl module for running Blast analyses using a HTTP interface.
*****************************************************************

NAME
====

   Bio::Tools::Blast::Run::Webblast.pm - Bioperl module for running Blast
analyses using a HTTP interface.

SYNOPSIS
========

     # Run a Blast
     use Bio::Tools::Blast::Run::Webblast qw(&blast_remote);

     @out_file_names = &blast_remote($object, %named_parameters);

   `blast_remote' in this node is the only exported method of this module
and it returns a list of local file names containing the Blast reports.
$object is a reference to a *Bio::Root::Object.pm* object or subclass. See
`blast_remote' in this node() for a description of available parameters.

     # Obtain a list of available databases

     use Bio::Tools::Blast::Run::Webblast qw(@Blast_dbp_remote
     					    @Blast_dbn_remote);

     @amino_dbs      = @Blast_dbp_remote;
     @nucleotide_dbs = @Blast_dbn_remote;

INSTALLATION
============

   This module is included with the central Bioperl distribution:

     http://bio.perl.org/Core/Latest
     ftp://bio.perl.org/pub/DIST

   Follow the installation instructions included in the README file.

DESCRIPTION
===========

   *Bio::Tools::Blast::Run::Webblast.pm* contains methods and data
necessary for running Blast sequence analyses using a remote server and
saving the results locally.

   *Bio::Tools::Blast::run()* provides an interface for Webblast.pm, so,
ideally, you shouldn't use Webblast.pm directly, but via Blast.pm.

   *FEATURES:*

   * Supports NCBI Blast1, Blast2, and PSI-Blast servers as well as
     WashU-Blast servers.

   * Can operate through a proxy server enabling operation from behind a
     firewall.

   * Can save reports with and without HTML formatting.

   * Uses LWP.

   In principle, this module can be customized to use different servers
that provide a Blast interface like the NCBI or WashU style servers.  Such
servers could be remote or local. This hasn't been well-tested however.

DEPENDENCIES
============

   Bio::Tools::Blast::Run::Webblast.pm is used by Bio::Tools::Blast.pm.
The development of this is thus linked with the Blast.pm module.

SEE ALSO
========

     Bio::Tools::Blast.pm                    - Blast object.
     Bio::Tools::Blast::Run::LocalBlast.pm   - Utility module for running Blasts locally.
     Bio::Tools::Blast::HTML.pm              - Blast HTML-formating utility class.
     Bio::Seq.pm                             - Biosequence object
     Bio::Root::Object.pm                    - Bioperl base object class.

     http://bio.perl.org/Projects/modules.html  - Online module documentation
     http://bio.perl.org/Projects/Blast/        - Bioperl Blast Project
     http://bio.perl.org/                       - Bioperl Project Homepage

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules.  Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     vsns-bcd-perl@lists.uni-bielefeld.de          - General discussion
     vsns-bcd-perl-guts@lists.uni-bielefeld.de     - Technically-oriented discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR
======

Steve A. Chervitz <sac@genome.stanford.edu>
          - Webblast.pm modularized version of webblast script.

Alex Dong Li <ali@genet.sickkids.on.ca>
          - original webblast script.

Ross N. Crowhurst <RCrowhurst@hort.cri.nz>
          - modified Webblast.pm to use LWP to give proxy server support.

VERSION
=======

   Bio::Tools::Blast::Run::Webblast.pm, 1.24

COPYRIGHT
=========

   Copyright (c) 1998, 1999 Steve A. Chervitz, Alex Dong Li,  Ross N.
Crowhurst.  All Rights Reserved.This module is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

APPENDIX
========

   Methods beginning with a leading underscore are considered private and
are intended for internal use by this module. They are not considered part
of the public interface and are described here for documentation purposes
only.

blast_remote
------------

     Usage     : @files = blast_remote( $blast_object,  %namedParameters);
               : This method is exported.
     Purpose   : Run a remote Blast analysis on one or more sequences.
               : NOTE: The name of this method is potentially misleading
               :       since the a local server could be specified.
      	   :       Probably should be called blast_http.
     Returns   : Array containing a list of filenames of the Blast reports.
     Argument  : First argument should be a Bio::Tools::Blast.pm object reference.
               : This object is primarily used for error reporting
               : Remaining arguments are named parameters:
               : (PARAMETER TAGS CAN BE UPPER OR LOWER CASE).
               :
               :   -ALIGN      => integer, number of alignments (B, 100)
               :   -ALIGN_VIEW => alignment view option (see below)
               :   -CUTOFF     => Blast score cutoff (60-110 or 'default')
               :   -DATABASE   => name of database (see below)
               :   -DESCR      => integer, number of on-line descriptions (V, 100)
               :   -EXPECT     => expect value cutoff
               :   -EXPECT_PSI => expect value for inclusion in PSI-BLAST iteration 1
               :   -FILTER     => sequence complexity filter ('default' or 'none')
               :   -GAP        => 'on' or 'off'
               :   -GAP_CREATE => gap creation penalty (G, 5)
               :   -GAP_EXTEND => gap extension penalty (E, 2)
               :   -GEN_CODE   => integer for special genetic code (see below) blastx only
               :   -GRAPH      => 'on' or 'off' (graphical overview not yet supported)
               :   -HISTOGRAM  => 'on' or 'off' or 'both'
               :   -HTML       => 'on' or 'off' or 'both'
               :   -INPUT_TYPE => 'Sequence in FASTA format' or 'Accession or GI'
               :   -MATRIX     => substitution scoring matrix (blast1 only for NCBI server)
               :   -NCBI_GI    => 'on' or 'off'
               :   -MATCH      => match reward (r, 1)       (blastn only)
               :   -MAX_LEN    => max query sequence length to blast
               :   -MIN_LEN    => min query sequence length to blast
               :   -MISMATCH   => mismatch penalty (q, -3)  (blastn only)
               :   -ORGANISM   => organism name to limit Blast2 search.
               :   -ORGANISM_CUSTOM  => custom organism or taxon name.
               :   -OUT_DIR    => output directory to store blast result files
               :   -PROG       => name of blast program (blastp, blastx, etc.)
               :   -SEQS       => ref to an array of Bio::Seq.pm objects.
               :   -SERVER     => blast server to use (default is NCBI Blast2)
               :   -STRAND     => Default = 'Both' (not used by NCBI servers)
               :   -VERSION    => blast version (1, 2, PSI, WashU)
               :   -WORD       => word size (W, 11 for blastn, 3 for all others)
     #rnc:   LIST_ORG
     #       valid list_org entries for blast2 are a string of 50 chars max, default is empty string
               :
     Throws    : Exception if:
               :   - Cannot obtain parameters by calling _rearrange() on the
               :     first argument, which should be a Bio::Tools::Blast.pm object ref.
               :   - No sequences are provided.
               :   - Sequence type is incompatible with Blast program type.
               :   - Database name is not one of the valid names.
               :   - Supplied e-mail address looks invalid.
     Comments  :
      -------------------------------------------------------------
      Available programs: blastn, blastx, dbest, blastp, tblastn, tblastx
      Program versions: 1, 2, PSI, WashU (or WU)

     -------------------------------------------------------------
     Available databases:
           nr, month, swissprot, dbest, dbsts,
           est_mouse, est_human, est_others, pdb, vector, kabat,
           mito, alu, epd, yeast, ecoli, gss, htgs.

       These are exported by this module in the @Blast_dbp_remote
       and @Blast_dbn_remote arrays.
     -------------------------------------------------------------
     Available Genetic Codes are (blastx only):

     (1) Standard                    (2) Vertebrate Mitochondrial
     (3) Yeast Mitochondrial         (4) Mold Mitochondrial; ...
     (5) Invertebrate Mitochondrial  (6) Ciliate Nuclear; ...
     (9) Echinoderm Mitochondrial    (10) Euplotid Nuclear
     (11) Bacterial                  (12) Alternative Yeast Nuclear
     (13) Ascidian Mitochondrial     (14) Flatworm Mitochondrial
     (15) Blepharisma Macronuclear

       -------------------------------------------------------------
       Available values for organism (Blast2):

     (None)   (DEFAULT; note that the parentheses are required.)
     Arabidopsis thaliana
     Bacillus subtilis
     Bos taurus
     Caenorhabditis elegans
     Danio rerio
     Dictyostelium discoideum
     Drosophila melanogaster
     Escherichia coli
     Gallus gallus
     Homo sapiens
     Human immunodeficiency virus type 1
     Mus musculus
     Oryctolagus cuniculus
     Oryza sativa
     Ovis aries
     Plasmodium falciparum
     Rattus norvegicus
     Saccharomyces cerevisiae
     Schizosaccharomyces pombe
     Simian immunodeficiency virus
     Xenopus laevis
     Zea mays

     -------------------------------------------------------------
     Available values for align_view (Blast2):

     0             Pairwise  (DEFAULT)
     1             master-slave with identities
     2             master-slave without identities
     3             flat master-slave with identities
     4             flat master-slave without identities
      -------------------------------------------------------------
       Available substitution scoring matrices (NCBI):

     BLAST2 matrices: BLOSUM80, BLOSUM62, BLOSUM45, PAM30, PAM70

     BLAST1 matrices: BLOSUM62, PAM40, PAM120, PAM250, IDENTITY.

     Others members of the BLOSUM and PAM family of matrices
     may be available as well.
     These are exported by this module in the @Blast_matrix_remote array.

     Note that certain combinations of matrices and gap creation/extension
     penalties are disallowed (E.g., PAM250 will work with 12/2 but not 11/1).
      --------------------------------------------------------------
        Limited values for gap creation and extension are supported for
        blastp, blastx, tblastn.  Some supported and suggested values are:

     Creation     Extension

     10             1
     10             2
     11             1
      8             2
      9             2
       -------------------------------------------------------------
       Available sequence complexity filters:
       SEG, SEG+XNU, XNU, dust, none.

   See Also : _set_options(), _adjust_options(), _validate_options(),
_blast(), Bio::Tools::Blast.pm

APPENDIX 2: Parameter listings
==============================

   Parameters for Blast (NCBI ungapped, no longer supported by NCBI so
should dicontinue use of ungapped blast), Blast2 (NCBI), PSI-Blast2
(NCBI). WashU-Blast2 has yet to be added as does PHI-Blast2 (NCBI).

   These lists of parameters for posting to blast servers were obtained
directly from the respective WWW forms for each server.

Basic ungapped BLAST Search Server Parameters
---------------------------------------------

   PROGRAM [default value]:blastn 	blastp tblastn tblastx blastx

   DATALIB [default value]:nr 	month swissprot dbest dbsts pdb
vector kabat mito alu epd yeast gss htgs ecoli

   INPUT_TYPE [default value]:Sequence in FASTA format 	Accession or GI

   SEQUENCE

   EXPECT [default value]:default 	0.0001 0.01 1 10 100 1000

   CUTOFF [default value]:default 	60 70 80 90 100 110

   MATRIX [default value]:default 	BLOSUM62 PAM40 PAM120 PAM250 IDENTITY

   STRAND [default value]:both 	top bottom

   FILTER [default value]:default none dust SEG SEG+XNU XNU

   HISTOGRAM [default value]:" HISTOGRAM

   NCBI_GI [default value]:"" NCBI_GI

   DESCRIPTIONS [default value]:default 0 10 50 100 250 500

   ALIGNMENTS [default value]:default 0 10 50 100 250 500

   ADVANCED [default value]:""

   EMAIL [default value]:" IS_SET

   PATH [default value]:""

   HTML [default value]:" HTML

Basic Blast 2
-------------

   PROGRAM [default value]:blastn blastp blastx tblastn tblastx

   DATALIB [default value]:nr month swissprot dbest  dbsts est_mouse
est_human est_others pdb pat vector kabat mito alu epd yeast ecoli gss htgs

   UNGAPPED_ALIGNMENT [default value]:" is_set

   FSET [default value]:is_set "

   OVERVIEW [default value]:is_set "

   INPUT_TYPE [default value]:Sequence in FASTA format Accession or GI

   SEQUENCE

   EMAIL [default value]:" IS_SET

   PATH [default value]:""

   HTML [default value]:" IS_SET

BLAST2 ADVANCED
---------------

   PROGRAM [default value]:blastn blastp blastx tblastn tblastx

   DATALIB [default value]:nr  month swissprot dbest dbsts est_mouse
est_human est_others pdb pat vector kabat mito alu epd yeast ecoli gss htgs

   UNGAPPED_ALIGNMENT [default value]:"" is_set

   INPUT_TYPE [default value]:Sequence in FASTA format Accession or GI

   SEQUENCE

   GI_LIST [default value]:(None) Arabidopsis thaliana   Bacillus subtilis
 Bos taurus   Caenorhabditis elegans   Danio rerio   Dictyostelium
discoideum   Drosophila melanogaster   Escherichia coli   Gallus gallus
Homo sapiens   Human immunodeficiency virus type 1   Mus musculus
Oryctolagus cuniculus   Oryza sativa   Ovis aries   Plasmodium falciparum
Rattus norvegicus   Saccharomyces cerevisiae   Schizosaccharomyces pombe
Simian immunodeficiency virus   Xenopus laevis   Zea mays

   LIST_ORG

   EXPECT [default value]:10 0.0001 0.01 1 10 100 1000

   FILTER [default value]:default none

   NCBI_GI [default value]:" is_set

   OVERVIEW [default value]:is_set "

   DESCRIPTIONS [default value]:500 0 10 50 100 250 500

   ALIGNMENTS [default value]:500 0 10 50 100 250 500

   ALIGNMENT_VIEW [default value]:0	#Pairwise 1	#master-slave with
identities 2	#master-slave without identities 3	#flat master-slave
with identities 4	#flat master-slave without identities

   GENETIC_CODE [default value]:Standard (1) Vertebrate Mitochondrial (2)
Yeast Mitochondrial (3) Mold Mitochondrial; ... (4) Invertebrate
Mitochondrial (5) Ciliate Nuclear; ... (6) Echinoderm Mitochondrial (9)
Euplotid Nuclear (10) Bacterial (11) Alternative Yeast Nuclear (12)
Ascidian Mitochondrial (13) Flatworm Mitochondrial (14) Blepharisma
Macronuclear (15)

   MAT_PARAM [default value]:BLOSUM62	 11	 1 PAM30	 9	 1
PAM70	 10	 1 BLOSUM80	 10	 1 BLOSUM62	 11	 1 BLOSUM45
14	 2 PAM30	 7	 2 PAM30	 6	 2 PAM30	 5	 2
PAM30	 10	 1 PAM30	 9	 1  #recommended PAM30	 8	 1
PAM70	 8	 2 PAM70	 7	 2 PAM70	 6	 2 PAM70	 11	 1
PAM70	 10	 1  #recommended PAM70	 9	 1 BLOSUM80	 8	 2
BLOSUM80	 7	 2 BLOSUM80	 6	 2 BLOSUM80	 11	 1 BLOSUM80	 10	 1
#recommended BLOSUM80	 9	 1 BLOSUM62	 9	 2 BLOSUM62	 8	 2
BLOSUM62	 7	 2 BLOSUM62	 12	 1 BLOSUM62	 11	 1
#recommended BLOSUM62	 10	 1 BLOSUM45	 13	 3 BLOSUM45	 12	 3
BLOSUM45	 11	 3 BLOSUM45	 10	 3 BLOSUM45	 15	 2
BLOSUM45	 14	 2  #recommended BLOSUM45	 13	 2 BLOSUM45	 12	 2
BLOSUM45	 19	 1 BLOSUM45	 18	 1 BLOSUM45	 17	 1
BLOSUM45	 16	 1

   OTHER_ADVANCED [default value]:""

   EMAIL [default value]:" IS_SET

   PATH [default value]:""

   HTML [default value]:" IS_SET

PSI BLAST2
----------

   PROGRAM [default value]:blastp

   DATALIB [default value]:nr month swissprot pdb kabat alu yeast ecoli

   GAPPED_ALIGNMENT [default value]:is_set "

   INPUT_TYPE [default value]:Sequence in FASTA format Accession or GI

   SEQUENCE

   EXPECT [default value]:10 0.0001 0.01 1 10  100  1000

   FILTER [default value]:default none

   NCBI_GI [default value]:" is_set

   GRAPHIC_OVERVIEW [default value]:is_set "

   DESCRIPTIONS [default value]:500 0  10 50 100 250 500

   ALIGNMENTS [default value]:500 0  10 50 100 250 500

   E_THRESH [default value]:0.001 #max value is 10

   MAT_PARAM [default value]:BLOSUM62	 11	 1 PAM30	 9	 1
PAM70	 10	 1  BLOSUM80	 10	 1  BLOSUM62	 11	 1  BLOSUM45	 14	 2
PAM30	 7	 2  PAM30	 6	 2  PAM30	 5	 2  PAM30	 10	 1
PAM30	 9	 1  PAM30	 8	 1  PAM70	 8	 2  PAM70	 7	 2
PAM70	 6	 2  PAM70	 11	 1  PAM70	 10	 1  PAM70	 9	 1  BLOSUM80
8	 2  BLOSUM80	 7	 2  BLOSUM80	 6	 2  BLOSUM80	 11	 1  BLOSUM80	 10	 1
BLOSUM80	 9	 1  BLOSUM62	 9	 2  BLOSUM62	 8	 2
BLOSUM62	 7	 2  BLOSUM62	 12	 1  BLOSUM62
11	 1  BLOSUM62	 10	 1  BLOSUM45	 13	 3
BLOSUM45	 12	 3  BLOSUM45	 11	 3  BLOSUM45
10	 3  BLOSUM45	 15	 2  BLOSUM45	 14	 2
BLOSUM45	 13	 2 BLOSUM45	 12	 2 BLOSUM45	 19	 1
BLOSUM45	 18	 1 BLOSUM45	 17	 1 BLOSUM45	 16	 1

   OTHER_ADVANCED [default value]:""

WashU BLAST2
------------

   WU-Blast2 Database Searches http://www2.ebi.ac.uk/blast2/

   email ""

   title Sequence

   srchtype interactive email

   database swall swissprot swnew trembl tremblnew pdb gpcrdb prints
HLAprot embl emnew est igvec emvec imgt HLAnuc

   program WU-blastp WU-blastx WU-blastn

   matrix blosum62 blosum30 blosum35 blosum40 blosum45 blosum50 blosum65
blosum70 blosum75 blosum80 blosum85 blosum90 blosum100 GONNET pam10 pam20
pam30 pam40 pam50 pam60 pam70 pam80 pam90 pam100 pam110 pam120 pam130
pam140 pam150 pam160 pam170 pam180 pam190 pam200 pam210 pam220 pam230
pam240 pam250 pam260 pam270 pam280 pam290 pam300 pam310 pam320 pam330
pam340 pam350 pam360 pam370 pam380 pam390 pam400 pam410 pam420 pam430
pam440 pam450 pam460 pam470 pam480 pam490 pam500

   strand default top bottom

   exp default 1.0 10 100 1000

   filter none seg xnu seg+xnu dust

   echofilter no yes

   histogram no yes

   stats sump poisson

   sort pvalue count highscore totalscore

   scores default 5 10 20 50 100 150 200 250

   numal default 5 10 20 50 100 150 200 250

   sequence

Bioperl BLAST "Hit" object
**************************

NAME
====

   Bio::Tools::Blast::Sbjct.pm - Bioperl BLAST "Hit" object

SYNOPSIS
========

Object Creation
---------------

   The construction of HSP objects is handled by Bio::Tools::Blast.pm.
You should not need to use this package directly. See `_initialize' in
this node() for a description of constructor parameters.

     require Bio::Tools::Blast::Sbjct;

     $hit = new Bio::Tools::Blast::Sbjct (-DATA    =>\@hitData,
     					 -PARENT  =>$self,
     					 -NAME    =>5,
     					 -RANK    =>5,
     					 -RANK_BY =>'order',
     					 -MAKE    =>'query' (or 'sbjct'),
     					 -OVERLAP =>2,
     					 -PROGRAM =>'TBLASTN'
     					 );

   @hitData includes the summary line for the hit as element [0], plus all
lines from the HSP alignment section of the BLAST report for the present
hit.

INSTALLATION
============

   This module is included with the central Bioperl distribution:

     http://bio.perl.org/Core/Latest
     ftp://bio.perl.org/pub/DIST

   Follow the installation instructions included in the README file.

DESCRIPTION
===========

   The Bio::Tools::Blast::Sbjct.pm module encapsulates data and methods for
parsing and manipulating "hits" from a BLAST report.  This module is a
utility module used by the Bio::Tools::Blast.pm and is not intended for
separate use.

   In Blast lingo, the "sbjct" sequences are all the sequences in a target
database which were compared against a "query" sequence.  The terms
"sbjct" and "hit" will be used interchangeably in this and related modules.

   This module supports BLAST versions 1.x and 2.x, gapped and ungapped.

HSP Tiling and Ambiguous Alignments
-----------------------------------

   If a Blast hit has more than one HSP, the Bio::Tools::Blast::Sbjct.pm
object has the ability to merge overlapping HSPs into contiguous blocks.
This permits the Sbjct object to sum data across all HSPs without counting
data in the overlapping regions multiple times, which would happen if data
from each overlapping HSP are simply summed.  HSP tiling is performed
automatically when methods of the Sbjct object that rely on tiled data are
invoked. These include `frac_identical' in this node(), `frac_conserved'
in this node(), `gaps' in this node(), `frac_aligned_query' in this
node(), `frac_aligned_hit' in this node(), `num_unaligned_query' in this
node(), `num_unaligned_hit' in this node().

   It also permits the assessment of an "ambiguous alignment" if the query
(or sbjct) sequences from different HSPs overlap. The existence of an
overlap could indicate a biologically interesting region in the sequence,
such as a repeated domain.  The Sbjct object uses the -OVERLAP parameter
to determine when two sequences overlap; if this is set to 2 - the default
- then any two sbjct or query HSP sequences must overlap by more than two
residues to get merged into the same contig and counted as an overlap. See
the `BUGS' in this node section below for "issues" with HSP tiling.

   The results of the HSP tiling is reported with the following ambiguity
codes:

     'q' = Query sequence contains multiple sub-sequences matching
           a single region in the sbjct sequence.

     's' = Sbjct sequence contains multiple sub-sequences matching
           a single region in the query sequence.

     'qs' = Both query and sbjct sequences contain more than one
            sub-sequence with similarity to the other sequence.

   For addition information about ambiguous BLAST alignments, see
`_tile_hsps' in this node() and

     http://www-genome.stanford.edu/Sacch3D/help/ambig_aln.html

DEPENDENCIES
============

   Bio::Tools::Blast::Sbjct.pm is a concrete class that inherits from
*Bio::Root::Object.pm* and relies on two other modules:

Bio::Tools::Blast::HSP.pm
     Encapsulates a single high-scoring segment pair within a hit.

Bio::Tools::Blast.pm
     Provides a container for Sbjct.pm objects.

   Bio::Tools::Blast::Sbjct.pm does not currently inherit from
Bio::Root::Vector.pm since Bio::Root::Vector.pm may be re-designed to make
it usable via delegation.  Thus, a Blast.pm object would manage a vector
of Sbjct.pm objects.  Stay tuned.

BUGS
====

   One consequence of the HSP tiling is that methods that rely on HSP
tiling such as `frac_identical' in this node(), `frac_conserved' in this
node(), `gaps' in this node() etc. may report misleading numbers when
`-OVERLAP' is set to a large number.  For example, say we have two HSPs
and the query sequence tile as follows:

     1      8             22      30        40             60
      Full seq:  ------------------------------------------------------------
             *  ** *   **
      HSP1:             ---------------                    (6 identical matches)
                       **   **  **
      HSP2:                        -------------           (6 identical matches)

   If `-OVERLAP' is set to some number over 4, HSP1 and HSP2 will not be
tiled into a single contig and their numbers of identical matches will be
added, giving a total of 12, not 10 if they had be combined into one
contig. This can lead to number greater than 1.0 for methods
`frac_identical' in this node() and `frac_conserved' in this node(). This
is less of an issue with gapped Blast since it tends to combine HSPs that
would be listed separately without gapping.  (Fractions >1.0 can be viewed
as a signal for an interesting alignment that warrants further inspection,
thus turning this bug into a feature).

   Using large values for `-OVERLAP' can lead to incorrect numbers
reported by methods that rely on HSP tiling but can be useful if you care
more about detecting ambiguous alignments.  Setting `-OVERLAP' to zero
will lead to the most accurate numbers for the tiling-dependent methods
but will be useless for detecting overlapping HSPs since all HSPs will
appear to overlap.

SEE ALSO
========

     Bio::Tools::Blast::HSP.pm     - Blast HSP object.
     Bio::Tools::Blast.pm          - Blast object.
     Bio::Root::Object.pm          - Proposed base class for all Bioperl objects.

   Links:

     http://bio.perl.org/Core/POD/Tools/Blast/HSP.pm.html

     http://bio.perl.org/Projects/modules.html  - Online module documentation
     http://bio.perl.org/Projects/Blast/        - Bioperl Blast Project
     http://bio.perl.org/                       - Bioperl Project Homepage

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules.  Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR
======

   Steve A. Chervitz, sac@genome.stanford.edu

   See the `FEEDBACK' in this node section for where to send bug reports
and comments.

COPYRIGHT
=========

   Copyright (c) 1996-2000 Steve A. Chervitz. All Rights Reserved.  This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

APPENDIX
========

   Methods beginning with a leading underscore are considered private and
are intended for internal use by this module. They are not considered part
of the public interface and are described here for documentation purposes
only.

_initialize
-----------

     Usage     : n/a; automatically called by Bio::Root::Object::new()
               : Bio::Tools::Blast::Sbjct.pm objects are constructed
               : automatically by Bio::Tools::Blast.pm, so there is no need
               : for direct consumption.
     Purpose   : Initializes key varaiables and calls methods to parse a single Blast hit.
               : Constructs Bio::Tools::Blast::HSP.pm objects for each
               : high-scoring segment pair (HSP).
               : Calls superclass constructor first (Bio::Root::Object.pm).
     Returns   : n/a
     Argument  : Named Parameters passed from new()
               : ALL TAGS MUST BE UPPERCASE (does not call _rearrange()).
               :     -DATA       => array reference holding all data for a single hit.
               :                    The first element should hold the description
               :                    line (from the desctiption section at the top of
               :                    the report), remaining lines should hold all lines
               :                    within the HSP alignment listing section of report.
     	   :	 -PARENT     => object reference to a Bio::Tools::Blast.pm object.
     	   :	 -NAME       => string (typically same as -RANK, just a temporary
               :                    name to use until the actual name of hit is parsed),
     	   :	 -RANK       => integer,
     	   :	 -RANK_BY    => 'order',
     	   :	 -OVERLAP    => integer (maximum overlap between adjacent
               :                    HSPs when tiling)
     	   :	 -PROGRAM    => string (type of Blast blastp, blastn, etc).

   See Also   : `_set_id' in this node(), `_set_hsps' in this node(),
`_tile_hsps' in this node(), *Bio::Root::Object.pm*::new,
Bio::Tools::Blast.pm::_set_hit_db

rank
----

     Usage     : $sbjct->rank( integer or string );
     Purpose   : Sets/Gets the rank of the current Sbjct object relative to
               : other Sbjct objects managed by a given Blast object.
     Example   : $sbjct->rank(1);
     Returns   : The current rank value.
     Argument  : Integer or string to be used for ranking the hit
               : relative to other hits.
     Throws    : n/a
     Comments  : The rank usually corresponds to the order the listing
               : of hits in the BLAST report from lowest to highest p-value.
               : Rank need not be restricted to this value.
               : rank() may be provided by a delegated or inherited
               : iterator class in the future (such as Bio::Root::Vector.pm).

_set_id
-------

     Usage     : n/a; automatically called by _initialize()
     Purpose   : Sets the name of the Sbjct sequence from the BLAST summary line.
               : The identifier is assumed to be the first
               : chunk of non-whitespace characters in the description line
               : Does not assume any semantics in the structure of the identifier
               : (Formerly, this method attempted to extract database name from
               : the seq identifiers, but this was prone to break).
     Returns   : n/a
     Argument  : String containing description line of the hit from Blast report
               : or first line of an alignment section.
     Throws    : Warning if cannot locate sequence ID.

   See Also   : `_initialize' in this node(),
Bio::Tools::Blast.pm::database

_set_hsps
---------

     Usage     : n/a; called automatically during object construction.
     Purpose   : Creates HSP.pm objects for each HSP in a BLAST hit alignment.
               : Also collects the full description of the hit from the
               : HSP alignment section.
     Returns   : n/a
     Argument  : List of strings containing raw BLAST report data for
               : a single hit's HSP alignment data.
     Throws    : Warnings for each HSP.pm object that fails to be constructed.
               : Exception if no HSP.pm objects can be constructed.
               : Exception if can't parse length data for hit sequence.
     Comments  : Requires Bio::Tools::Blast::HSP.pm.
               : Sets the description using the full string present in
               : the alignment data.
               : Also sets Expect and P-values for the Sbjct object by
               : copying from the HSP object.
               : While this sacrifices some memory efficiency, it
               : improves access speed for these critical data.

   See Also   : `_initialize' in this node(), `_set_desc' in this node()

_set_desc
---------

     Usage     : n/a; called automatically by _set_hsps()
     Purpose   : Sets the description of the hit sequence.
               : For sequence without descriptions, sets description to "-".
     Argument  : Array containing description (multiple lines).
     Comments  : _set_hsps() calls this method with the data from the
               : HSP alignment listing, which contains the complete description.
               : (Formerly, this was called from the _set_desc_data() method initially.)

   See Also   : _set_hsps()

_tile_hsps
----------

     Usage     : n/a; called automatically during object construction or
               : as needed by methods that rely on having tiled data.
     Purpose   : Collect statistics about the aligned sequences in a set of HSPs.
               : Calculates the following data across all HSPs:
               :    -- total alignment length
               :    -- total identical residues
               :    -- total conserved residues
     Returns   : n/a
     Argument  : n/a
     Throws    : n/a
     Status    : Experimental
     Comments  :
               : This method performs more careful summing of data across
               : all HSPs in the Sbjct object. Simply summing the data from all HSPs
               : will overestimate the actual length of the alignment if there is
               : overlap between different HSPs (often the case).
               : The strategy is to tile the HSPs and sum over the
               : contigs, collecting data separately from overlapping and
               : non-overlapping regions of each HSP. To facilitate this, the
               : HSP.pm object now permits extraction of data from sub-sections
               : of an HSP.
               :
               : Additional useful information is collected from the results
               : of the tiling. It is possible that sub-sequences in
               : different HSPs will overlap significantly. In this case, it
               : is impossible to create a single unambiguous alignment by
               : concatenating the HSPs. The ambiguity may indicate the
               : presence of multiple, similar domains in one or both of the
               : aligned sequences. This ambiguity is recorded using the
               : ambiguous_aln() method.
               :
               : This method does not attempt to discern biologically
               : significant vs. insignificant overlaps. The allowable amount of
               : overlap can be set with the overlap() method or with the -OVERLAP
               : parameter used when constructing the Blast & Sbjct objects.
               :
               : For a given hit, both the query and the sbjct sequences are
               : tiled independently.
               :
               :    -- If only query sequence HSPs overlap,
               :          this may suggest multiple domains in the sbjct.
               :    -- If only sbjct sequence HSPs overlap,
               :          this may suggest multiple domains in the query.
               :    -- If both query & sbjct sequence HSPs overlap,
               :          this suggests multiple domains in both.
               :    -- If neither query & sbjct sequence HSPs overlap,
               :          this suggests either no multiple domains in either
               :          sequence OR that both sequences have the same
               :          distribution of multiple similar domains.
               :
               : This method can deal with the special case of when multiple
               : HSPs exactly overlap.
               :
               : Efficiency concerns:
               :  Speed will be an issue for sequences with numerous HSPs.
               :
     Bugs      : Currently, _tile_hsps() does not properly account for
               : the number of non-tiled but overlapping HSPs, which becomes a problem
               : as overlap() grows. Large values overlap() may thus lead to
               : incorrect statistics for some hits. For best results, keep overlap()
               : below 5 (DEFAULT IS 2). For more about this, see the "HSP Tiling and
               : Ambiguous Alignments" section.

   See Also   : `_adjust_contigs' in this node(), `ambiguous_aln' in this
node(), `overlap' in this node(), `frac_identical' in this node(),
`frac_conserved' in this node(), `frac_aligned_query' in this node(),
`frac_aligned_hit' in this node(), `num_unaligned_query' in this node(),
`num_unaligned_hit' in this node(), `HSP Tiling and Ambiguous Alignments'
in this node

_adjust_contigs
---------------

     Usage     : n/a; called automatically during object construction.
     Purpose   : Builds HSP contigs for a given BLAST hit.
               : Utility method called by _tile_hsps()
     Returns   :
     Argument  :
     Throws    : Exceptions propagated from Bio::Tools::Blast::HSP::matches()
               : for invalid sub-sequence ranges.
     Status    : Experimental
     Comments  : This method does not currently support gapped alignments.
               : Also, it does not keep track of the number of HSPs that
               : overlap within the amount specified by overlap().
               : This will lead to significant tracking errors for large
               : overlap values.

   See Also   : `overlap' in this node(), `_tile_hsps' in this node(),
Bio::Tools::Blast::HSP.pm::matches

ambiguous_aln
-------------

     Usage     : $ambig_code = $sbjct_object->ambiguous_aln();
     Purpose   : Sets/Gets ambiguity code data member.
     Example   : (see usage)
     Returns   : String = 'q', 's', 'qs', '-'
               :   'q'  = query sequence contains overlapping sub-sequences
               :          while sbjct does not.
               :   's'  = sbjct sequence contains overlapping sub-sequences
               :          while query does not.
               :   'qs' = query and sbjct sequence contains overlapping sub-sequences
               :          relative to each other.
               :   '-'  = query and sbjct sequence do not contains multiple domains
               :          relative to each other OR both contain the same distribution
               :          of similar domains.
     Argument  : n/a
     Throws    : n/a
     Status    : Experimental

   See Also   : `_tile_hsps' in this node(),  `HSP Tiling and Ambiguous
Alignments' in this node

overlap
-------

     Usage     : $blast_object->overlap( [integer] );
     Purpose   : Gets/Sets the allowable amount overlap between different HSP sequences.
     Example   : $blast_object->overlap(5);
               : $overlap = $blast_object->overlap();
     Returns   : Integer.
     Argument  : integer.
     Throws    : n/a
     Status    : Experimental
     Comments  : Any two HSPs whose sequences overlap by less than or equal
               : to the overlap() number of resides will be considered separate HSPs
               : and will not get tiled by _adjust_contigs().

   See Also   : `_adjust_contigs' in this node(), `BUGS' in this node

score
-----

     Usage     : $sbjct_object->score();
     Purpose   : Gets the BLAST score of the best HSP for the current Blast hit.
     Example   : $score = $sbjct_object->score();
     Returns   : Integer
     Argument  : n/a
     Throws    : n/a

     See Also   : L<bits>()

bits
----

     Usage     : $sbjct_object->bits();
     Purpose   : Gets the BLAST bit score of the best HSP for the current Blast hit.
     Example   : $bits = $sbjct_object->bits();
     Returns   : Integer
     Argument  : n/a
     Throws    : Exception if bit score is not set.
     Comments  : For BLAST1, the non-bit score is listed in the summary line.

   See Also   : `score' in this node()

n
-

     Usage     : $sbjct_object->n();
     Purpose   : Gets the N number for the current Blast hit.
               : This is the number of HSPs in the set which was ascribed
               : the lowest P-value (listed on the description line).
               : This number is not the same as the total number of HSPs.
               : To get the total number of HSPs, use num_hsps().
     Example   : $n = $sbjct_object->n();
     Returns   : Integer
     Argument  : n/a
     Throws    : Exception if HSPs have not been set (BLAST2 reports).
     Comments  : Note that the N parameter is not reported in gapped BLAST2.
               : Calling n() on such reports will result in a call to num_hsps().
               : The num_hsps() method will count the actual number of
               : HSPs in the alignment listing, which may exceed N in
               : some cases.

   See Also   : `num_hsps' in this node()

frame
-----

     Usage     : $sbjct_object->frame();
     Purpose   : Gets the reading frame for the hit sequence (TBLASTN/X only).
     Example   : $frame = $sbjct_object->frame();
     Returns   : Integer (-3 .. +3).
     Argument  : n/a
     Throws    : Exception if HSPs have not been set (BLAST2 reports).

   See Also   : `hsps' in this node()

p
-

     Usage     : $sbjct_object->p( [format] );
     Purpose   : Get the P-value for the given BLAST hit.
               : (Note that P-values are not provided with NCBI Blast2 reports).
     Example   : $p =  $sbjct->p;
               : $p =  $sbjct->p('exp');  # get exponent only.
               : ($num, $exp) =  $sbjct->p('parts');  # split sci notation into parts
     Returns   : Float or scientific notation number (the raw P-value, DEFAULT).
               : Integer if format == 'exp' (the magnitude of the base 10 exponent).
               : 2-element list (float, int) if format == 'parts' and P-value
               :                is in scientific notation (See Comments).
     Argument  : format: string of 'raw' | 'exp' | 'parts'
               :    'raw' returns value given in report. Default. (1.2e-34)
               :    'exp' returns exponent value only (34)
               :    'parts' returns the decimal and exponent as a
               :            2-element list (1.2, -34) (See Comments).
     Throws    : Exception if the P-value is not defined, which will occur
               : with any NCBI Blast2 report.
     Comments  : Using the 'parts' argument is not recommended since it will not
               : work as expected if the P-value is not in scientific notation.
               : That is, floats are not converted into sci notation before
               : splitting into parts.

   See Also   : `expect' in this node(), `signif' in this node(),
`get_exponent' in this node()

expect
------

     Usage     : $sbjct_object->expect( [format] );
     Purpose   : Get the Expect value for the given BLAST hit.
     Example   : $e =  $sbjct->expect;
               : $e =  $sbjct->expect('exp');  # get exponent only.
               : ($num, $exp) = $sbjct->expect('parts');  # split sci notation into parts
     Returns   : Float or scientific notation number (the raw expect value, DEFAULT).
               : Integer if format == 'exp' (the magnitude of the base 10 exponent).
               : 2-element list (float, int) if format == 'parts' and Expect
               :                is in scientific notation (see Comments).
     Argument  : format: string of 'raw' | 'exp' | 'parts'
               :    'raw' returns value given in report. Default. (1.2e-34)
               :    'exp' returns exponent value only (34)
               :    'parts' returns the decimal and exponent as a
               :            2-element list (1.2, -34)  (see Comments).
     Throws    : Exception if the Expect value is not defined.
     Comments  : Using the 'parts' argument is not recommended since it will not
               : work as expected if the expect value is not in scientific notation.
               : That is, floats are not converted into sci notation before
               : splitting into parts.

   See Also   : `p' in this node(), `signif' in this node(),
`get_exponent' in this node()

signif
------

     Usage     : $sbjct_object->signif( [format] );
     Purpose   : Get the P or Expect value for the given BLAST hit.
               : The value returned is the one which is reported in the description
               : section of the Blast report. For Blast1 and WU-Blast2, this
               : is a P-value, for Blast2, it is an Expect value.
     Example   : $obj->signif()        # returns 1.3e-34
               : $obj->signif('exp')   # returns -34
               : $obj->signif('parts') # returns (1.3, -34)
     Returns   : Float or scientific notation number (the raw P/Expect value, DEFAULT).
               : Integer if format == 'exp' (the magnitude of the base 10 exponent).
               : 2-element list (float, int) if format == 'parts' and P/Expect value
               :                is in scientific notation (see Comments).
     Argument  : format: string of 'raw' | 'exp' | 'parts'
               :    'raw' returns value given in report. Default. (1.2e-34)
               :    'exp' returns exponent value only (34)
               :    'parts' returns the decimal and exponent as a
               :            2-element list (1.2, -34)  (see Comments).
     Throws    : n/a
     Status    : Deprecated. Use p() or expect().
     Comments  : The signif() method provides a way to deal with the fact that
               : Blast1 and Blast2 formats differ in what is reported in the
               : description lines of each hit in the Blast report. The signif()
               : method frees any client code from having to know if this is a P-value
               : or an Expect value, making it easier to write code that can process
               : both Blast1 and Blast2 reports. This is not necessarily a good thing, since
               : one should always know when one is working with P-values or
               : Expect values (hence the deprecated status).
               : Use of expect() is recommended since all hits will have an Expect value.
               :
               : Using the 'parts' argument is not recommended since it will not
               : work as expected if the expect value is not in scientific notation.
               : That is, floats are not converted into sci notation before
               : splitting into parts.

   See Also   : `p' in this node(), `expect' in this node(),
`get_exponent' in this node()

desc
----

     Usage     : $sbjct_object->desc( [integer] );
     Purpose   : Get the description for the given BLAST hit.
     Example   : (see usage)
     Returns   : String
     Argument  : Integer (optional) indicating the desired length of the
               : description string to be returned.
     Throws    : n/a

   See Also   : `_set_desc' in this node()

database
--------

     Usage     : $sbjct_object->database();
     Purpose   : Get the name of the database for the hit sequence.
     Example   : (see usage)
     Returns   : String
     Argument  : n/a
     Throws    : n/a
     Status    : Experimental
     Comments  : Database id should be the same for all hits in a given
               : BLAST report, however, they do not always have the same
               : name as the database name extraced by the Blast.pm object.
               : The Sbjct.pm database id is obtained from the summary line.

hsps
----

     Usage     : $sbjct_object->hsps();
     Purpose   : Get a list containing all HSP objects.
               : Get the numbers of HSPs for the current hit.
     Example   : @hsps = $sbjct_object->hsps();
               : $num  = $sbjct_object->hsps();  # alternatively, use num_hsps()
     Returns   : Array context : list of Bio::Tools::Blast::HSP.pm objects.
               : Scalar context: integer (number of HSPs).
               :                 (Equivalent to num_hsps()).
     Argument  : n/a. Relies on wantarray
     Throws    : Exception if the HSPs have not been collected.

   See Also   : `hsp' in this node(), `num_hsps' in this node(),
`_set_hsps' in this node()

hsp
---

     Usage     : $sbjct_object->hsp( [string] );
     Purpose   : Get a single HSP.pm object for the present Sbjct.pm object.
     Example   : $hspObj  = $sbjct_object->hsp;  # same as 'best'
               : $hspObj  = $sbjct_object->hsp('best');
               : $hspObj  = $sbjct_object->hsp('worst');
     Returns   : Object reference for a Bio::Tools::Blast::HSP.pm object.
     Argument  : String (or no argument).
               :   No argument (default) = highest scoring HSP (same as 'best').
               :   'best' or 'first' = highest scoring HSP.
               :   'worst' or 'last' = lowest scoring HSP.
     Throws    : Exception if the HSPs have not been collected.
               : Exception if an unrecognized argument is used.

   See Also   : `hsps' in this node(), `num_hsps' in this node(),
`_set_hsps' in this node()

num_hsps
--------

     Usage     : $sbjct_object->num_hsps();
     Purpose   : Get the number of HSPs for the present Blast hit.
     Example   : $nhsps = $sbjct_object->num_hsps();
     Returns   : Integer
     Argument  : n/a
     Throws    : Exception if the HSPs have not been collected.

   See Also   : `hsps' in this node()

length
------

     Usage     : $sbjct_object->length();
     Purpose   : Get the total length of the hit sequence.
     Example   : $len    = $sbjct_object->length();
     Returns   : Integer
     Argument  : n/a
     Throws    : n/a
     Comments  : Developer note: when using the built-in length function within
               : this module, call it as CORE::length().

   See Also   : `logical_length' in this node(),  `length_aln' in this
node()

logical_length
--------------

     Usage     : $sbjct_object->logical_length( [seq_type] );
               : (mostly intended for internal use).
     Purpose   : Get the logical length of the hit sequence.
               : If the Blast is a TBLASTN or TBLASTX, the returned length
               : is the length of the would-be amino acid sequence (length/3).
               : For all other BLAST flavors, this function is the same as length().
     Example   : $len    = $sbjct_object->logical_length();
     Returns   : Integer
     Argument  : seq_type = 'query' or 'sbjct' (default = 'query')
     Throws    : n/a
     Comments  : This is important for functions like frac_aligned_query()
               : which need to operate in amino acid coordinate space when dealing
               : with [T]BLAST[NX] type reports.

   See Also   : `length' in this node(), `frac_aligned_query' in this
node(), `frac_aligned_hit' in this node()

length_aln
----------

     Usage     : $sbjct_object->length_aln( [seq_type] );
     Purpose   : Get the total length of the aligned region for query or sbjct seq.
               : This number will include all HSPs
     Example   : $len    = $sbjct_object->length_aln(); # default = query
               : $lenAln = $sbjct_object->length_aln('query');
     Returns   : Integer
     Argument  : seq_Type = 'query' | 'sbjct'  (Default = 'query')
     Throws    : Exception if the argument is not recognized.
     Comments  : This method will report the logical length of the alignment,
               : meaning that for TBLAST[NX] reports, the length is reported
               : using amino acid coordinate space (i.e., nucleotides / 3).
               :
               : This method requires that all HSPs be tiled. If they have not
               : already been tiled, they will be tiled first.
               : If you don't want the tiled data, iterate through each HSP
               : calling length() on each (use hsps() to get the HSPs).

   See Also   : `length' in this node(), `frac_aligned_query' in this
node(), `frac_aligned_hit' in this node(), `gaps' in this node(),
`_tile_hsps' in this node(), *Bio::Tools::Blast::HSP::length()*

gaps
----

     Usage     : $sbjct_object->gaps( [seq_type] );
     Purpose   : Get the number of gaps in the aligned query, sbjct, or both sequences.
               : Data is summed across all HSPs.
     Example   : $qgaps = $sbjct_object->gaps('query');
               : $sgaps = $sbjct_object->gaps('sbjct');
               : $tgaps = $sbjct_object->gaps();    # default = total (query + sbjct)
     Returns   : scalar context: integer
               : array context without args: two-element list of integers
               :    (queryGaps, sbjctGaps)
               : Array context can be "induced" by providing an argument of 'list' or 'array'.
     Argument  : seq_type: 'query' | 'sbjct' | 'total' | 'list'  (default = 'total')
     Throws    : n/a
     Comments  : If you need data for each HSP, use hsps() and then interate
               : through each HSP object.
               : This method requires that all HSPs be tiled. If they have not
               : already been tiled, they will be tiled first.
               : Not relying on wantarray since that will fail in situations
               : such as printf "%d", $hit->gaps() in which you might expect to
               : be printing the total gaps, but evaluates to array context.

   See Also   : `length_aln' in this node()

matches
-------

     Usage     : $sbjct_object->matches( [class] );
     Purpose   : Get the total number of identical or conserved matches
               : (or both) across all HSPs.
               : (Note: 'conservative' matches are indicated as 'positives'
     	   :         in the Blast report.)
     Example   : ($id,$cons) = $sbjct_object->matches(); # no argument
               : $id = $sbjct_object->matches('id');
               : $cons = $sbjct_object->matches('cons');
     Returns   : Integer or a 2-element array of integers
     Argument  : class = 'id' | 'cons' OR none.
               : If no argument is provided, both identical and conservative
               : numbers are returned in a two element list.
               : (Other terms can be used to refer to the conservative
               :  matches, e.g., 'positive'. All that is checked is whether or
               :  not the supplied string starts with 'id'. If not, the
               : conservative matches are returned.)
     Throws    : Exception if the requested data cannot be obtained.
     Comments  : If you need data for each HSP, use hsps() and then interate
               : through the HSP objects.
               : Does not rely on wantarray to return a list. Only checks for
               : the presence of an argument (no arg = return list).

   See Also   : *Bio::Tools::Blast::HSP::matches()*, `hsps' in this node()

start
-----

     Usage     : $sbjct->start( [seq_type] );
     Purpose   : Gets the start coordinate for the query, sbjct, or both sequences
               : in the Sbjct object. If there is more than one HSP, the lowest start
               : value of all HSPs is returned.
     Example   : $qbeg = $sbjct->start('query');
               : $sbeg = $sbjct->start('sbjct');
               : ($qbeg, $sbeg) = $sbjct->start();
     Returns   : scalar context: integer
               : array context without args: list of two integers (queryStart, sbjctStart)
               : Array context can be "induced" by providing an argument of 'list' or 'array'.
     Argument  : In scalar context: seq_type = 'query' or 'sbjct'
               :  (case insensitive). If not supplied, 'query' is used.
     Throws    : n/a
     Comments  : This method requires that all HSPs be tiled. If there is more than one
               : HSP and they have not already been tiled, they will be tiled first.
               : Remember that the start and end coordinates of all HSPs are
               : normalized so that start < end. Strand information can only be
               : obtained on an HSP-by-HSP basis by calling $hsp->strand().

   See Also   : `end' in this node(), `range' in this node(), `HSP Tiling
and Ambiguous Alignments' in this node, *Bio::Tools::Blast::HSP::start*()

end
---

     Usage     : $sbjct->end( [seq_type] );
     Purpose   : Gets the end coordinate for the query, sbjct, or both sequences
               : in the Sbjct object. If there is more than one HSP, the largest end
               : value of all HSPs is returned.
     Example   : $qend = $sbjct->end('query');
               : $send = $sbjct->end('sbjct');
               : ($qend, $send) = $sbjct->end();
     Returns   : scalar context: integer
               : array context without args: list of two integers (queryEnd, sbjctEnd)
               : Array context can be "induced" by providing an argument of 'list' or 'array'.
     Argument  : In scalar context: seq_type = 'query' or 'sbjct'
               :  (case insensitive). If not supplied, 'query' is used.
     Throws    : n/a
     Comments  : This method requires that all HSPs be tiled. If there is more than one
               : HSP and they have not already been tiled, they will be tiled first.
               : Remember that the start and end coordinates of all HSPs are
               : normalized so that start < end. Strand information can only be
               : obtained on an HSP-by-HSP basis by calling $hsp->strand().

   See Also   : `start' in this node(), `range' in this node(), `HSP
Tiling and Ambiguous Alignments' in this node,
*Bio::Tools::Blast::HSP::end*()

range
-----

     Usage     : $sbjct->range( [seq_type] );
     Purpose   : Gets the (start, end) coordinates for the query or sbjct sequence
               : in the HSP alignment.
     Example   : ($qbeg, $qend) = $sbjct->range('query');
               : ($sbeg, $send) = $sbjct->range('sbjct');
     Returns   : Two-element array of integers
     Argument  : seq_type = string, 'query' or 'sbjct'  (default = 'query')
               : (case insensitive).
     Throws    : n/a

   See Also   : `start' in this node(), `end' in this node()

frac_identical
--------------

     Usage     : $sbjct_object->frac_identical( [seq_type] );
     Purpose   : Get the overall fraction of identical positions across all HSPs.
               : The number refers to only the aligned regions and does not
               : account for unaligned regions in between the HSPs, if any.
     Example   : $frac_iden = $sbjct_object->frac_identical('query');
     Returns   : Float (2-decimal precision, e.g., 0.75).
     Argument  : seq_type: 'query' | 'sbjct' | 'total'
               : default = 'total' (but see comments below).
     Throws    : n/a
     Comments  : Different versions of Blast report different values for the total
               : length of the alignment. This is the number reported in the
               : denominators in the stats section:
               : "Identical = 34/120 Positives = 67/120".
               : BLAST-GP uses the total length of the alignment (with gaps)
               : WU-BLAST uses the length of the query sequence (without gaps).
               : Therefore, when called without an argument or an argument of 'total',
               : this method will report different values depending on the
               : version of BLAST used.
               :
               : To get the fraction identical among only the aligned residues,
               : ignoring the gaps, call this method with an argument of 'query'
               : or 'sbjct'.
               :
               : If you need data for each HSP, use hsps() and then iterate
               : through the HSP objects.
               : This method requires that all HSPs be tiled. If they have not
               : already been tiled, they will be tiled first.

   See Also   : `frac_conserved' in this node(), `frac_aligned_query' in
this node(), `matches' in this node(), `_tile_hsps' in this node()

frac_conserved
--------------

     Usage     : $sbjct_object->frac_conserved( [seq_type] );
     Purpose   : Get the overall fraction of conserved positions across all HSPs.
               : The number refers to only the aligned regions and does not
               : account for unaligned regions in between the HSPs, if any.
     Example   : $frac_cons = $sbjct_object->frac_conserved('sbjct');
     Returns   : Float (2-decimal precision, e.g., 0.75).
     Argument  : seq_type: 'query' | 'sbjct' | 'total'
               : default = 'total' (but see comments below).
     Throws    : n/a
     Comments  : Different versions of Blast report different values for the total
               : length of the alignment. This is the number reported in the
               : denominators in the stats section:
               : "Identical = 34/120 Positives = 67/120".
               : BLAST-GP uses the total length of the alignment (with gaps)
               : WU-BLAST uses the length of the query sequence (without gaps).
               : Therefore, when called without an argument or an argument of 'total',
               : this method will report different values depending on the
               : version of BLAST used.
               :
               : To get the fraction conserved among only the aligned residues,
               : ignoring the gaps, call this method with an argument of 'query'
               : or 'sbjct'.
               :
               : If you need data for each HSP, use hsps() and then interate
               : through the HSP objects.
               : This method requires that all HSPs be tiled. If they have not
               : already been tiled, they will be tiled first.

   See Also   : `frac_identical' in this node(), `matches' in this node(),
`_tile_hsps' in this node()

frac_aligned_query
------------------

     Usage     : $sbjct_object->frac_aligned_query();
     Purpose   : Get the fraction of the query sequence which has been aligned
               : across all HSPs (not including intervals between non-overlapping
               : HSPs).
     Example   : $frac_alnq = $sbjct_object->frac_aligned_query();
     Returns   : Float (2-decimal precision, e.g., 0.75).
     Argument  : n/a
     Throws    : n/a
     Comments  : If you need data for each HSP, use hsps() and then interate
               : through the HSP objects.
               : To compute the fraction aligned, the logical length of the query
               : sequence is used, meaning that for [T]BLASTX reports, the
               : full length of the query sequence is converted into amino acids
               : by dividing by 3. This is necessary because of the way
               : the lengths of aligned sequences are computed.
               : This method requires that all HSPs be tiled. If they have not
               : already been tiled, they will be tiled first.

   See Also   : `frac_aligned_hit' in this node(), `_tile_hsps' in this
node(), `logical_length' in this node(), `length_aln' in this node()

frac_aligned_hit
----------------

     Usage     : $sbjct_object->frac_aligned_hit();
     Purpose   : Get the fraction of the hit (sbjct) sequence which has been aligned
               : across all HSPs (not including intervals between non-overlapping
               : HSPs).
     Example   : $frac_alnq = $sbjct_object->frac_aligned_hit();
     Returns   : Float (2-decimal precision, e.g., 0.75).
     Argument  : n/a
     Throws    : n/a
     Comments  : If you need data for each HSP, use hsps() and then interate
               : through the HSP objects.
               : To compute the fraction aligned, the logical length of the sbjct
               : sequence is used, meaning that for TBLAST[NX] reports, the
               : full length of the sbjct sequence is converted into amino acids
               : by dividing by 3. This is necessary because of the way
               : the lengths of aligned sequences are computed.
               : This method requires that all HSPs be tiled. If they have not
               : already been tiled, they will be tiled first.

   See Also   : `frac_aligned_query' in this node(), `matches' in this
node(), `_tile_hsps' in this node(), `logical_length' in this node(),
`length_aln' in this node()

num_unaligned_hit
-----------------

     Usage     : $sbjct_object->num_unaligned_hit();
     Purpose   : Get the number of the unaligned residues in the hit sequence.
               : Sums across all all HSPs.
     Example   : $num_unaln = $sbjct_object->num_unaligned_hit();
     Returns   : Integer
     Argument  : n/a
     Throws    : n/a
     Comments  : See notes regarding logical lengths in the comments for frac_aligned_hit().
               : They apply here as well.
               : If you need data for each HSP, use hsps() and then interate
               : through the HSP objects.
               : This method requires that all HSPs be tiled. If they have not
               : already been tiled, they will be tiled first.

   See Also   : `num_unaligned_query' in this node(), `_tile_hsps' in this
node(), `frac_aligned_hit' in this node()

num_unaligned_query
-------------------

     Usage     : $sbjct_object->num_unaligned_query();
     Purpose   : Get the number of the unaligned residues in the query sequence.
               : Sums across all all HSPs.
     Example   : $num_unaln = $sbjct_object->num_unaligned_query();
     Returns   : Integer
     Argument  : n/a
     Throws    : n/a
     Comments  : See notes regarding logical lengths in the comments for frac_aligned_query().
               : They apply here as well.
               : If you need data for each HSP, use hsps() and then interate
               : through the HSP objects.
               : This method requires that all HSPs be tiled. If they have not
               : already been tiled, they will be tiled first.

   See Also   : `num_unaligned_hit' in this node(), `_tile_hsps' in this
node(), `frac_aligned_query' in this node()

seq_inds
--------

     Usage     : $hit->seq_inds( seq_type, class, collapse );
     Purpose   : Get a list of residue positions (indices) across all HSPs
               : for identical or conserved residues in the query or sbjct sequence.
     Example   : @ind = $hit->seq_inds('query', 'identical');
               : @ind = $hit->seq_inds('sbjct', 'conserved');
               : @ind = $hit->seq_inds('sbjct', 'conserved', 1);
     Returns   : Array of integers
               : May include ranges if collapse is non-zero.
     Argument  : seq_type  = 'query' or 'sbjct'  (default = query)
               : class     = 'identical' or 'conserved' (default = identical)
               :              (can be shortened to 'id' or 'cons')
               :              (actually, anything not 'id' will evaluate to 'conserved').
               : collapse  = boolean, if non-zero, consecutive positions are merged
               :             using a range notation, e.g., "1 2 3 4 5 7 9 10 11"
               :             collapses to "1-5 7 9-11". This is useful for
               :             consolidating long lists. Default = no collapse.
     Throws    : n/a.

   See Also   : *Bio::Tools::Blast::HSP::seq_inds()*

display
-------

     Usage     : $sbjct_object->display( %named_parameters );
     Purpose   : Display information about Bio::Tools::Blast::Sbjct.pm data members
     Example   : $object->display(-SHOW=>'stats');
     Argument  : Named parameters: -SHOW  => 'hsp',
               :                   -WHERE => filehandle (default = STDOUT)
     Returns   : n/a
     Status    : Deprecated, Buggy.
               : Use Blast::table() or Blast::table_tiled() instead.

   See Also   : `_display_stats' in this node(), `_display_hsps' in this
node(), *Bio::Root::Object.pm*::display

_display_stats
--------------

     Usage     : n/a; called automatically by display()
     Purpose   : Display information about Bio::Tools::Blast.pm data members.
               : Not tab-delimited.
               : Prints the rank, name, database, score, p, n, length
               : of the hit sequence, length of the aligned region,
               : fraction identical, fraction conserved, and the fraction aligned
               : for both the query and hit sequences.
     Example   : n/a
     Argument  : one argument = filehandle object.
     Returns   : printf call.
     Status    : Deprecated, Buggy.
               : Use Blast::table() or Blast::table_tiled() instead.

   See Also   : `display' in this node()

_display_hsps
-------------

     Usage     : n/a; called automatically by display()
     Purpose   : Display information about each HSP in the current BLAST hit.
     Example   : n/a
     Argument  : one argument = filehandle object.
     Returns   : printf call.
     Status    : Experimental

   See Also   : `display' in this node(),
Bio::Tools::Blast::HSP.pm::display

homol_data
----------

     Usage     : $data = $sbjct_object->homo_data( %named_params );
     Purpose   : Gets specific similarity data about all HSPs.
     Returns   : String
     Argument  : named parameters forwarded to Bio::Tools::Blast::HSP::homol_data().
     Throws    : n/a
     Status    : Experimental
     Comments  : This is an experimental method used for obtaining an
               : indication of:
               :   1) how many HSPs are in a Blast alignment
               :   2) how strong the similarity is between sequences in the HSP
               :   3) the endpoints of the alignment (sequence monomer numbers)
               : "Homology data" for each HSP is in the format:
               :  "<integer> <start> <stop>"
               : Data for different HSPs are tab-delimited.

   See Also   : *Bio::Tools::Blast::homol_data()*,
*Bio::Tools::Blast::HSP::homol_data()*

is_signif
---------

     Usage     : $sbjct_object->is_signif();
     Purpose   : Determine if the given BLAST hit is significant.
     Example   :
     Returns   : Boolean
     Argument  : n/a
     Throws    : n/a
     Comments  : Uses criteria defined in the parent Blast.pm object
               : to assess significance. Currently, only relies on
               : P-value and length criteria.
               : This mehtod is largely obsolete since are hits are now by
               : definition significant.

CLASS METHODS
=============

get_exponent
------------

     Usage     : &get_exponent( number );
     Purpose   : Determines the power of 10 exponent of an integer, float,
               : or scientific notation number.
     Example   : &get_exponent("4.0e-206");
               : &get_exponent("0.00032");
               : &get_exponent("10.");
               : &get_exponent("1000.0");
               : &get_exponent("e+83");
     Argument  : Float, Integer, or scientific notation number
     Returns   : Integer representing the exponent part of the number (+ or -).
               : If argument == 0 (zero), return value is "-999".
     Comments  : Exponents are rounded up (less negative) if the mantissa is >= 5.
               : Exponents are rounded down (more negative) if the mantissa is <= -5.
               : This method probably belongs in a more general utility class.

FOR DEVELOPERS ONLY
===================

Data Members
------------

   Information about the various data members of this module is provided
for those wishing to modify or understand the code. Two things to bear in
mind:

  1. Do NOT rely on these in any code outside of this module.  All data
     members are prefixed with an underscore to signify that they are
     private.  Always use accessor methods. If the accessor doesn't exist
     or is inadequate, create or modify an accessor (and let me know,
     too!). (An exception to this might be for HSP.pm which is more
     tightly coupled to Sbjct.pm and may access Sbjct data members
     directly for efficiency purposes, but probably should not).

  2. This documentation may be incomplete and out of date.  It is easy for
     these data member descriptions to become obsolete as this module is
     still evolving. Always double check this info and search for members
     not described here.

        An instance of Bio::Tools::Blast::Sbjct.pm is a blessed reference
to a hash containing all or some of the following fields:

     FIELD           VALUE
     --------------------------------------------------------------
     _hsps          : Array ref for a list of Bio::Tools::Blast::HSP.pm objects.
     		:
     _db            : Database identifier from the summary line.
     		:
     _desc          : Description data for the hit from the summary line.
     		:
     _length        : Total length of the hit sequence.
     		:
     _score         : BLAST score.
     		:
     _bits          : BLAST score (in bits). Matrix-independent.
     		:
     _p             : BLAST P value. Obtained from summary section. (Blast1/WU-Blast only)
     		:
     _expect        : BLAST Expect value. Obtained from summary section.
     		:
     _n             : BLAST N value (number of HSPs) (Blast1/WU-Blast2 only)
     		:
     _frame         : Reading frame for TBLASTN and TBLASTX analyses.
     		:
     _totalIdentical: Total number of identical aligned monomers.
     		:
     _totalConserved: Total number of conserved aligned monomers (a.k.a. "positives").
     		:
     _overlap       : Maximum number of overlapping residues between adjacent HSPs
     		: before considering the alignment to be ambiguous.
     		:
     _ambiguous_aln : Boolean. True if the alignment of all HSPs is ambiguous.
     		:
     _length_aln_query : Length of the aligned region of the query sequence.
     		   :
     _length_aln_sbjct : Length of the aligned region of the sbjct sequence.

     INHERITED DATA MEMBERS
     ----------------------
     _name          : From Bio::Root::Object.pm. String representing the name of the
     		: sbjct sequence obtained from the BLAST report.
     		:
     _parent        : From Bio::Root::Object.pm. This member contains a reference to the
     		: Bio::Tools::Blast.pm object to which this hit belongs.

Bioperl codon table object
**************************

NAME
====

   Bio::Tools::CodonTable - Bioperl codon table object

SYNOPSIS
========

     This is a read-only class for all known codon tables.  The IDs are
     the ones used by nucleotide sequence databases.  All common IUPAC
     ambiguity codes for DNA, RNA and animo acids are recognized.

     # to use
     use Bio::Tools::CodonTable;

     # defaults to ID 1 "Standard"
     $myCodonTable   = Bio::Tools::CodonTable->new();
     $myCodonTable2  = Bio::Tools::CodonTable -> new ( -id => 3 );

     # change codon table
     $myCodonTable->id(5);

     # examine codon table
     print  join (' ', "The name of the codon table no.", $myCodonTable->id(4),
     	       "is:", $myCodonTable->name(), "\n");

     # translate a codon
     $aa = $myCodonTable->translate('ACU');
     $aa = $myCodonTable->translate('act');
     $aa = $myCodonTable->translate('ytr');

     # reverse translate an amino acid
     @codons = $myCodonTable->revtranslate('A');
     @codons = $myCodonTable->revtranslate('Ser');
     @codons = $myCodonTable->revtranslate('Glx');
     @codons = $myCodonTable->revtranslate('cYS', 'rna');

     #boolean tests
      print "Is a start\n"       if $myCodonTable->is_start_codon('ATG');
      print "Is a termianator\n" if $myCodonTable->is_ter_codon('tar');
      print "Is a unknown\n"     if $myCodonTable->is_unknown_codon('JTG');

DESCRIPTION
===========

   Codon tables are also called translation tables or genetics codes since
that is what they try to represent. A bit more complete picture of the
full complexity of codon usage in various taxonomic groups presented at
the NCBI Genetic Codes Home page.

   CodonTable is a BioPerl class that knows all current translation tables
that are used by primary nucleotide sequence databases (GenBank, EMBL and
DDBJ). It provides methods to output information about tables and
relationships between codons and amino acids.

   This class and its methods recognized all common IUPAC ambiguity codes
for DNA, RNA and animo acids. The translation method follows the
conventions in EMBL and TREMBL databases.

   It is a nuisance to separate RNA and cDNA representations of nucleic
acid transcripts. The CodonTable object accepts codons of both type as
input and allows the user to set the mode for output when reverse
translating. Its default for output is DNA.

   Note: This class deals with individual codons and amino acids, only.
   Call it from your own objects to translate and reverse translate
longer sequences.

   The amino acid codes are IUPAC recommendations for common amino acids:

     A           Ala            Alanine
     R           Arg            Arginine
     N           Asn            Asparagine
     D           Asp            Aspartic acid
     C           Cys            Cysteine
     Q           Gln            Glutamine
     E           Glu            Glutamic acid
     G           Gly            Glycine
     H           His            Histidine
     I           Ile            Isoleucine
     L           Leu            Leucine
     K           Lys            Lysine
     M           Met            Methionine
     F           Phe            Phenylalanine
     P           Pro            Proline
     S           Ser            Serine
     T           Thr            Threonine
     W           Trp            Tryptophan
     Y           Tyr            Tyrosine
     V           Val            Valine
     B           Asx            Aspartic acid or Asparagine
     Z           Glx            Glutamine or Glutamic acid
     X           Xaa            Any or unknown amino acid

   It is worth noting that, "Bacterial" codon table no. 11 produces an
polypeptide that is, confusingly, identical to the standard one. The only
differences are in available initiator codons.

   NCBI Genetic Codes home page:
http://www.ncbi.nlm.nih.gov/htbin-post/Taxonomy/wprintgc?mode=c

   EBI Translation Table Viewer:
http://www.ebi.ac.uk/cgi-bin/mutations/trtables.cgi

   Amended ASN.1 version with ids 16 and 21 is at:
ftp://ftp.ebi.ac.uk/pub/databases/geneticcode/

   Thank your for Matteo diTomasso for the original Perl implementation of
these tables.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to the
Bioperl mailing lists  Your participation is much appreciated.

     bioperl-l@bioperl.org                         - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via  email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Heikki Lehvaslaiho
===========================

   Email:  heikki@ebi.ac.uk Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

id
--

     Title   : id
     Usage   : $obj->id(3); $id_integer = $obj->id();
     Function:

     Sets or returns the id of the translation table.  IDs are
     integers from 1 to 15, excluding 7 and 8 which have been
     removed as redundant. If an invalid ID is given the method
     returns 0, false.

     Example :
     Returns : value of id, a scalar, 0 if not a valid
     Args    : newvalue (optional)

name
----

     Title   : name
     Usage   : $obj->name()
     Function: returns the descriptive name of the translation table
     Example :
     Returns : A string
     Args    : None

translate
---------

     Title   : translate
     Usage   : $obj->translate('YTR')
     Function: Returns one letter amino acid code for a codon input.

     Returns 'X' for unknown codons and codons that code for
     more than one amino acid. Returns an empty string if input
     is not three characters long. Exceptions for these are:

     - IUPAC amino acid code B for Aspartic Acid and
       Asparagine, is used.
     - IUPAC amino acid code Z for Glutamic Acid, Glutamine is
       used.
     - if the codon is two nucleotides long and if by adding
       an a third character 'N', it codes for a single amino
       acid (with exceptions above), return that, otherwise
       return empty string.

     Returns empty string for other input strings that are not
     three characters long.

     Example :
     Returns : One letter ambiguous IUPAC amino acid code
     Args    : a codon = a three character, ambiguous IUPAC nucleotide string

translate_strict
----------------

     Title   : translate_strict
     Usage   : $obj->translate_strict('ACT')
     Function: returns one letter amino acid code for a codon input

     Fast and simple translation. User is responsible to resolve
     ambiguous nucleotide codes before calling this
     method. Returns 'X' for unknown codons and an empty string
     for input strings that are not three characters long.

     It is not recommended to use this method in a production
     environment. Use method translate, instead.

     Example :
     Returns : A string
     Args    : a codon = a three nucleotide character string

revtranslate
------------

     Title   : revtranslate
     Usage   : $obj->revtranslate('G')
     Function: returns codons for an amino acid

     Returns an empty string for unknown amino acid
     codes. Ambiquous IUPAC codes Asx,B, (Asp,D; Asn,N) and
     Glx,Z (Glu,E; Gln,Q) are resolved. Both single and three
     letter amino acid codes are accepted. '*' and 'Ter' are
     used for terminator.

     By default, the output codons are shown in DNA.  If the
     output is needed in RNA (tr/t/u/), add a second argument
     'RNA'.

     Example : $obj->revtranslate('Gly', 'RNA')
     Returns : An array of three lower case letter strings i.e. codons
     Args    : amino acid, 'RNA'

is_start_codon
--------------

     Title   : is_start_codon
     Usage   : $obj->is_start_codon('ATG')
     Function: returns true (1) for all codons that can be used as a
               translation start, false (0) for others.
     Example : $myCodonTable->is_start_codon('ATG')
     Returns : boolean
     Args    : codon

is_ter_codon
------------

     Title   : is_ter_codon
     Usage   : $obj->is_ter_codon('GAA')
     Function: returns true (1) for all codons that can be used as a
               translation tarminator, false (0) for others.
     Example : $myCodonTable->is_ter_codon('ATG')
     Returns : boolean
     Args    : codon

is_unknown_codon
----------------

     Title   : is_unknown_codon
     Usage   : $obj->is_unknown_codon('GAJ')
     Function: returns false (0) for all codons that are valid,
     	    true (1) for others.
     Example : $myCodonTable->is_unknown_codon('NTG')
     Returns : boolean
     Args    : codon

_unambiquous_codons
-------------------

     Title   : _unambiquous_codons
     Usage   : @codons = _unambiquous_codons('ACN')
     Function:
     Example :
     Returns : array of strings (one letter unambiguous amino acid codes)
     Args    : a codon = a three IUPAC nucleotide character string

Results of one ESTScan run
**************************

NAME
====

   Bio::Tools::ESTScan - Results of one ESTScan run

SYNOPSIS
========

     $estscan = Bio::Tools::ESTScan->new(-file => 'result.estscan');
     # filehandle:
     $estscan = Bio::Tools::ESTScan->new( -fh  => \*INPUT );

     # parse the results
     # note: this class is-a Bio::Tools::AnalysisResult which implements
     # Bio::SeqAnalysisParserI, i.e., $genscan->next_feature() is the same
     while($gene = $estscan->next_prediction()) {
         # $gene is an instance of Bio::Tools::Prediction::Gene
         foreach my $orf ($gene->exons()) {
     	   # $orf is an instance of Bio::Tools::Prediction::Exon
     	   $cds_str = $orf->predicted_cds();
         }
     }

     # essential if you gave a filename at initialization (otherwise the file
     # will stay open)
     $estscan->close();

DESCRIPTION
===========

   The ESTScan module provides a parser for ESTScan coding region
prediction output.

   This module inherits off Bio/Tools/AnalysisResult,
and therefore implements the
Bio/SeqAnalysisParserI, interface.  See
Bio/SeqAnalysisParserI.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp
====================

   Email hlapp@gmx.net (or hilmar.lapp@pharma.novartis.com)

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

analysis_method
---------------

     Usage     : $estscan->analysis_method();
     Purpose   : Inherited method. Overridden to ensure that the name matches
                 /estscan/i.
     Returns   : String
     Argument  : n/a

next_feature
------------

     Title   : next_feature
     Usage   : while($orf = $estscan->next_feature()) {
                      # do something
               }
     Function: Returns the next gene structure prediction of the ESTScan result
               file. Call this method repeatedly until FALSE is returned.

     The returned object is actually a SeqFeatureI implementing object.
     This method is required for classes implementing the
     SeqAnalysisParserI interface, and is merely an alias for
     next_prediction() at present.

     Example :
     Returns : A Bio::Tools::Prediction::Gene object.
     Args    :

next_prediction
---------------

     Title   : next_prediction
     Usage   : while($gene = $estscan->next_prediction()) {
                      # do something
               }
     Function: Returns the next gene structure prediction of the ESTScan result
               file. Call this method repeatedly until FALSE is returned.

     So far, this method DOES NOT work for reverse strand predictions,
     even though the code looks like.
      Example :
      Returns : A Bio::Tools::Prediction::Gene object.
      Args    :

close
-----

     Title   : close
     Usage   : $result->close()
     Function: Closes the file handle associated with this result file.
               Inherited method, overridden.
     Example :
     Returns :
     Args    :

_fasta_stream
-------------

     Title   : _fasta_stream
     Usage   : $result->_fasta_stream()
     Function: Gets/Sets the FASTA sequence IO stream for reading the contents of
               the file associated with this MZEF result object.

     If called for the first time, creates the stream from the filehandle
     if necessary.
      Example :
      Returns :
      Args    :

Bioperl Fasta utility object
****************************

NAME
====

   Bio::Tools::Fasta.pm - Bioperl Fasta utility object

INSTALLATION
============

   This module is included with the central Bioperl distribution:

     http://bio.perl.org/Core/Latest
     ftp://bio.perl.org/pub/DIST

   Follow the installation instructions included in the README file.

SYNOPSIS
========

Object Creation
---------------

   Bio::Tools::Fasta.pm cannot yet build sequence analysis objects given
output from the FASTA program. This module can only be used for parsing
Fasta multiple sequence files. This situation may change.

Parse a Fasta multiple-sequence file.
-------------------------------------

   If $file is not a valid filename, data will be read from STDIN.  See
the `parse' in this node() method for a complete description of parameters.

     use Bio::Tools::Fasta qw(:obj);

     $seqCount = $Fasta->parse(-file        => $file,
     			      -seqs        => \@seqs,
     			      -ids         => \@ids,
     			      -edit_id     => 1,
     			      -edit_seq    => 1,
     			      -descs       => \@descs,
     			      -filt_func   => \&filter_seq   # filter input sequences.
     			      -exec_func   => \&process_seq  # process each seq as it is parsed.
     			      );

DESCRIPTION
===========

   The Bio::Tools::Fasta.pm module, in its present incarnation,
encapsulates data and methods for managing Fasta multiple sequence files
(reading, parsing).  It does not yet work with output from the Fasta
sequence analysis program (`References & Information about the FASTA
program' in this node).

   The documentation of this module is incomplete. For some examples of
usage, see the DEMO SCRIPTS section.

   Unlike "Blast", the term "Fasta" is ambiguous since it refers to both a
sequence file format and a sequence analysis utility (I use "FASTA" to
refer to the program; "Fasta" for the file format).  Ultimately, this
module will be able to work with both Fasta sequence files as well as
result files generated by FASTA sequence analysis, analogous to the way the
Bio::Tools::Blast.pm object is used for working with Blast output.

References & Information about the FASTA program
------------------------------------------------

   *WEBSITES:*

     ftp://ftp.virginia.edu/pub/fasta/    - FASTA software
     http://www2.ebi.ac.uk/fasta3/        - FASTA server at EBI

   *PUBLICATIONS:* (with PubMed links)

     Pearson W.R. and Lipman, D.J. (1988). Improved tools for biological
     sequence comparison. PNAS 85:2444-2448

http://www.ncbi.nlm.nih.gov/htbin-post/Entrez/query?uid=3162770&form=6&db=m&Dopt=b

     Pearson, W.R. (1990). Rapid and sensitive sequence comparison with FASTP and FASTA.
     Methods in Enzymology 183:63-98.

http://www.ncbi.nlm.nih.gov/htbin-post/Entrez/query?uid=2156132&form=6&db=m&Dopt=b

USAGE
=====

   A simple demo script is included with the central Bioperl distribution
(`INSTALLATION' in this node) and is also available from:

     http://bio.perl.org/Core/Examples/seq/

DEPENDENCIES
============

   Bio::Tools::Fasta.pm is a concrete class that inherits from
*Bio::Tools::SeqAnal.pm*.  This module also relies on *Bio::Seq.pm* for
producing sequence objects.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules.  Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     vsns-bcd-perl@lists.uni-bielefeld.de          - General discussion
     vsns-bcd-perl-guts@lists.uni-bielefeld.de     - Technically-oriented discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR
======

   Steve A. Chervitz, sac@genome.stanford.edu

VERSION
=======

   Bio::Tools::Fasta.pm, 0.014

COPYRIGHT
=========

   Copyright (c) 1998 Steve A. Chervitz. All Rights Reserved.  This module
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

     Bio::Tools::SeqAnal.pm   - Sequence analysis object base class.
     Bio::Seq.pm              - Biosequence object
     Bio::Root::Object.pm     - Proposed base class for all Bioperl objects.

     http://bio.perl.org/Projects/modules.html  - Online module documentation
     http://bio.perl.org/                       - Bioperl Project Homepage

   `References & Information about the FASTA program' in this node.

TODO
====

   * Incorporate code for parsing Fasta sequence analysis reports.

   * Improve documentation.

APPENDIX
========

   Methods beginning with a leading underscore are considered private and
are intended for internal use by this module. They are not considered part
of the public interface and are described here for documentation purposes
only.

_initialize
-----------

     Usage     : n/a; automatically called by Bio::Root::Object::new()
     Purpose   : Calls superclass constructor.
     Returns   : n/a
     Argument  : Named parameters passed to new() are processed by this method.
               : At present, none are processed.

   See Also   : *Bio::Tools::SeqAnal::_initialize()*

parse
-----

     Usage     : $fasta_obj->$parse( %named_parameters)
     Purpose   : Parse a set of Fasta sequences or Fasta reports from a file or STDIN.
               : (Currently only Fasta sequence parsing is supported).
     Returns   : Integer (number of sequences or Fasta reports parsed).
     Argument  : Named parameters: (TAGS CAN BE UPPER OR LOWER CASE)
     	   :   -FILE       => string (name of file containing Fasta-formatted sequences.
               :                          Optional. If a valid file is not supplied,
     	   :			      STDIN will be used).
               :   -SEQS       => boolean (true = parse a Fasta multi-sequence file
               :                           false = parse a Fasta sequence analysis report).
               :   -IDS        => array_ref (optional).
               :   -DESCS      => array_ref (optional).
               :   -EDIT_ID    => boolean  (true = edit sequence identifiers).
               :   -EDIT_SEQ   => boolean  (true = edit sequence data).
               :   -TYPE       => string   (type of sequences to be processed:
               :                            'dna', 'rna', 'amino'),
               :   -FILT_FUNC  => func_ref (reference to a function for filtering out
     	   :				sequences as they are being parsed.
     	   :				This function should return a boolean
               :                            (true if the sequence should be filtered out)
     	   :				and accept three arguments as shown
     	   :				in this sample filter function:
     	   :				sub filt {
     	   :				    my($len, $id, $desc);
     	   :				    # $len is the sequence length
     	   :				    return ($len < 25 and $id =~ /^123/);
     	   :				}
               :                            This function will screen out any sequence
               :                            less than 25 in length and having an id
     	   :				starting with '123'.
               :   -SAVE_ARRAY => array_ref (reference to an array for storing all
               :                             sequence objects as they are created.)
               :   -EXEC_FUNC  => func_ref (reference to a function for processing each
               :                            sequence object) as it is parsed.
               :                            When working with sequences, this function
               :                            should accept a Bio::Seq.pm object as its
               :                            sole argument. Return value will be ignored).
               :   -STRICT     => boolean (increases sensitivity to errors).
               :
               :  ----------------------------------------------------------------
               :   NOTE: Parameters such as seqs, ids, desc, edit_id, edit_seq, type
               :         are used only when parsing Fasta sequence files.
               :         Additional parameters will be added as necessary for
               :         parsing Fasta sequence analysis reports.
               :
     	   :   NOTE: When retreiving sequence data instead of objects,
               :         the -SEQS, -IDS, and -DESCS parameters should all be array refs.
               :         This constitutes a signal that sequence objects are not
               :         to be constructed.
               :
     Throws    : Propagates any exceptions thrown by _parse_seq_stream()
     Comments  :

     WORKING WITH SEQUENCE DATA:
     ---------------------------
     The parse method can return sequence data bundled into Bio::Seq.pm objects
     or in raw format (separate arrays for seq, id, and desc data). The reason for
     this is that in some cases, you don't particularly need to work with sequence
     objects and it is inefficient to build objects just to have them broken apart.
     However, there is something to be said for choosing one approach --
     always return seq objects. In this way, the object
     becomes the basic unit of exchange. For now, both options are allowed.

     The story will be different for Fasta sequence analysis report objects
     since these are a much more complex data type and it would be unwieldy
     and dangerous to return parsed data unencapsulated from an object.

   See Also   : `_parse_seq_stream' in this node(), `_set_id_desc' in this
node(), `_get_parse_seq_func' in this node()

_parse_seq_stream
-----------------

     Usage     : n/a. Internal method called by parse()
     Purpose   : Obtains the function to be used during parsing and calls read().
     Returns   : Integer (the number of sequences read)
     Argument  : Named parameters  (forwarded from parse())
     Throws    : Propagates any exception thrown by _get_parse_seq_func() and read().
     Comments  :

     This method permits the sequence data to be parsed as it is being read in.
     The motivation here is that when working with a potentially huge set of
     sequences, there is no need to read them all into memory before you start
     processing them. In fact, you may only be interested in a few of them.

     This method constructs and returns a closure for parsing a single Fasta sequence.
     It is called automatically by the read() method inherited from
     Bio::Root::Object.pm.

     Another issue concerns what to do with the parsed data: save it or
     use it? Sometimes you need to process all sequence data as a group
     (eg., sorting). Other times, you can safely process each sequence
     as it gets parsed and then move on to the next. By delivering each
     sequence as it gets parsed, the client is free to decide what to
     do with it.

   See Also   : `_get_parse_seq_func' in this node(),
*Bio::Root::Object::read()*

_get_parse_seq_func
-------------------

     Usage     : n/a. Internal method called by _parse_seq_stream()
     Purpose   : Generates a function reference to be used for parsing raw sequence data
               : as it is being loaded by read().
               : Used when parsing Fasta sequence files.
     Returns   : Function reference (actually a closure)
     Argument  : Named parameters forwared from _parse_seq_stream()
     Throws    : Exceptions due to improper argument types.
               :   (to be elaborated...)
     Comments  : The function generated performs sequence editing if
               : the -EDIT_SEQ parse() parameter is is non-zero.
     	   : This consists of removing any ambiguous residues at begin
               : or end of seq.
     	   : Regardless of -EDIT_SEQ, all sequence will be edited to remove
               : whitespace and non-alphabetic chars.
     	   : Gaps characters are permitted ('.' and '-').
               : (Need a more universal way to identify gap characters.)
               : If sequence objects are generated and an -EXEC_FUNC is supplied,
               : each object will be destroyed after calling this function.
               : This prevents memory usage problems for large runs.

   See Also   : `parse' in this node(), `_parse_seq_stream' in this
node(), *Bio::Root::Object::_rearrange*()

edit_id
-------

     Usage     : $fasta_obj->edit_id()
     Purpose   : Set/Get a boolean indicator as to whether sequence IDs should be edited.
               : Used when parsing Fasta sequence files.
     Returns   : Boolean (true if the IDs are to be edited).
     Argument  : Boolean (optional)
     Throws    : n/a

   See Also   : `_set_id_desc' in this node(), `_get_parse_seq_func' in
this node()

edit_seqs
---------

     Usage     : $fasta_obj->edit_seqs()
     Purpose   : Set/Get a boolean indicator as to whether sequences should be edited.
               : Used when parsing Fasta sequence files.
     Returns   : Boolean (true if the sequences are to be edited).
     Argument  : Boolean (optional)
     Throws    : n/a

   See Also   : `_get_parse_seq_func' in this node()

_set_id_desc
------------

     Usage     : n/a. Internal method called by _get_parse_seq_func()
     Purpose   : Sets the _id and _desc data members, optionally editing the id.
               : Used when parsing Fasta sequence files.
     Returns   : 2-element list containing: ($id, $description)
     Argument  : String containing raw ID + description (leading '>' will be stripped)
     Throws    : n/a
     Comments  : Optionally edits the ID if the '_edit_id' field is true.
               : Descriptions are not altered.
               : ID Edits:
               :   1) Uppercases the ID.
               :   2) If the ID has any | characters the following is performed:
               :        a) Replace | characters with _ characters.
               :           (prevent regexp and shell trouble).
               :        b) Cleans up complex identifiers.
               :           Some GenBank specifiers have multiple parts:
               :           >gi|2980872|gnl|PID|e1283615 homeobox protein SHOTb
               :           Only the first ID is saved as the official ID.
               :           Extra ids will be included at the end of the
               :           description between brackets:
               :           GI_2980872 homeobox protein SHOTb [ GNL PID e1283615 ]
               :
               : ID editing is somewhat experimental.

   See Also   : `_get_parse_seq_func' in this node(), `edit_id' in this
node()

num_seqs
--------

     Usage     : $fasta_obj->num_seqs()
     Purpose   : Get the number of sequences read by the Fasta object.
     Returns   : Integer
     Argument  : n/a
     Throws    : n/a

FOR DEVELOPERS ONLY
===================

Data Members
------------

   Information about the various data members of this module is provided
for those wishing to modify or understand the code. Two things to bear in
mind:

  1. Do NOT rely on these in any code outside of this module.  All data
     members are prefixed with an underscore to signify that they are
     private.  Always use accessor methods. If the accessor doesn't exist
     or is inadequate, create or modify an accessor (and let me know,
     too!).

  2. This documentation may be incomplete and out of date.  It is easy for
     these data member descriptions to become obsolete as this module is
     still evolving. Always double check this info and search for members
     not described here.

        An instance of Bio::Tools::Fasta.pm is a blessed reference to a
hash containing all or some of the following fields:

     FIELD           VALUE
     --------------------------------------------------------------
     _seqCount       Number of sequences parsed.

     _edit_seq       Boolean. Should sequences be edited during parsing?

     _edit_id        Boolean. Should ids be edited during parsing?

     More data members will be added when code for Fasta report
     processing is incorporated.

     INHERITED DATA MEMBERS

   (See Bio::Tools::SeqAnal.pm for inherited data members.)

A Bio::SeqAnalysisParserI compliant GFF format parser
*****************************************************

NAME
====

   Bio::Tools::GFF - A Bio::SeqAnalysisParserI compliant GFF format parser

SYNOPSIS
========

     use Bio::Tool::GFF;

     # specify input via -fh or -file
     my $gffio = Bio::Tools::GFF(-fh => \*STDIN, -gff_version => 2);
     my $feature;
     # loop over the input stream
     while($feature = $gffio->next_feature()) {
         # do something with feature
     }
     $gffio->close();

     # you can also obtain a GFF parser as a SeqAnalasisParserI in
     # HT analysis pipelines (see Bio::SeqAnalysisParserI and
     # Bio::Factory::SeqAnalysisParserFactory)
     my $factory = Bio::Factory::SeqAnalysisParserFactory->new();
     my $parser = $factory->get_parser(-input => \*STDIN, -method => "gff");
     while($feature = $parser->next_feature()) {
         # do something with feature
     }

DESCRIPTION
===========

   This class provides a simple GFF parser and writer. In the sense of a
SeqAnalysisParser, it parses an input file or stream into SeqFeatureI
objects, but is not in any way specific to a particular analysis program
and the output that program produces.

   That is, if you can get your analysis program spit out GFF, here is
your result parser.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Matthew Pocock
=======================

   Email mrp@sanger.ac.uk

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
---

     Title   : new
     Usage   :
     Function: Creates a new instance. Recognized named parameters are -file, -fh,
               and -gff_version.

     Returns : a new object
     Args    : names parameters

next_feature
------------

     Title   : next_feature
     Usage   : $seqfeature = $gffio->next_feature();
     Function: Returns the next feature available in the input file or stream, or
               undef if there are no more features.
     Example :
     Returns : A Bio::SeqFeatureI implementing object, or undef if there are no
               more features.
     Args    : none

from_gff_string
---------------

     Title   : from_gff_string
     Usage   : $gff->from_gff_string($feature, $gff_string);
     Function: Sets properties of a SeqFeatureI object from a GFF-formatted
               string. Interpretation of the string depends on the version
               that has been specified at initialization.

     This method is used by next_feature(). It actually dispatches to
     one of the version-specific (private) methods.
      Example :
      Returns : void
      Args    : A Bio::SeqFeatureI implementing object to be initialized
     The GFF-formatted string to initialize it from

_from_gff1_string
-----------------

     Title   : _from_gff1_string
     Usage   :
     Function:
     Example :
     Returns : void
     Args    : A Bio::SeqFeatureI implementing object to be initialized
               The GFF-formatted string to initialize it from

_from_gff2_string
-----------------

     Title   : _from_gff2_string
     Usage   :
     Function:
     Example :
     Returns : void
     Args    : A Bio::SeqFeatureI implementing object to be initialized
               The GFF2-formatted string to initialize it from

write_feature
-------------

     Title   : write_feature
     Usage   : $gffio->write_feature($feature);
     Function: Writes the specified SeqFeatureI object in GFF format to the stream
               associated with this instance.
     Example :
     Returns :
     Args    : A Bio::SeqFeatureI implementing object to be serialized

gff_string
----------

     Title   : gff_string
     Usage   : $gffstr = $gffio->gff_string($feature);
     Function: Obtain the GFF-formatted representation of a SeqFeatureI object.
               The formatting depends on the version specified at initialization.

     This method is used by write_feature(). It actually dispatches to
     one of the version-specific (private) methods.
      Example :
      Returns : A GFF-formatted string representation of the SeqFeature
      Args    : A Bio::SeqFeatureI implementing object to be GFF-stringified

_gff1_string
------------

     Title   : _gff1_string
     Usage   : $gffstr = $gffio->_gff1_string
     Function:
     Example :
     Returns : A GFF1-formatted string representation of the SeqFeature
     Args    : A Bio::SeqFeatureI implementing object to be GFF-stringified

_gff2_string
------------

     Title   : _gff2_string
     Usage   : $gffstr = $gffio->_gff2_string
     Function:
     Example :
     Returns : A GFF2-formatted string representation of the SeqFeature
     Args    : A Bio::SeqFeatureI implementing object to be GFF2-stringified

gff_version
-----------

     Title   : _gff_version
     Usage   : $gffversion = $gffio->gff_version
     Function:
     Example :
     Returns : The GFF version this parser will accept and emit.
     Args    : none

Results of one Genscan run
**************************

NAME
====

   Bio::Tools::Genscan - Results of one Genscan run

SYNOPSIS
========

     $genscan = Bio::Tools::Genscan->new(-file => 'result.genscan');
     # filehandle:
     $genscan = Bio::Tools::Genscan->new( -fh  => \*INPUT );

     # parse the results
     # note: this class is-a Bio::Tools::AnalysisResult which implements
     # Bio::SeqAnalysisParserI, i.e., $genscan->next_feature() is the same
     while($gene = $genscan->next_prediction()) {
         # $gene is an instance of Bio::Tools::Prediction::Gene, which inherits
         # off Bio::SeqFeature::Gene::Transcript.
         #
         # $gene->exons() returns an array of
         # Bio::Tools::Prediction::Exon objects
         # all exons:
         @exon_arr = $gene->exons();

     # initial exons only
     @init_exons = $gene->exons('Initial');
     # internal exons only
     @intrl_exons = $gene->exons('Internal');
     # terminal exons only
     @term_exons = $gene->exons('Terminal');
     # singleton exons:
     ($single_exon) = $gene->exons();
        }

     # essential if you gave a filename at initialization (otherwise the file
     # will stay open)
     $genscan->close();

DESCRIPTION
===========

   The Genscan module provides a parser for Genscan gene structure
prediction output. It parses one gene prediction into a
Bio::SeqFeature::Gene::Transcript- derived object.

   This module also implements the Bio::SeqAnalysisParserI interface, and
thus can be used wherever such an object fits. See
Bio/SeqAnalysisParserI.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp
====================

   Email hlapp@gmx.net

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

analysis_method
---------------

     Usage     : $genscan->analysis_method();
     Purpose   : Inherited method. Overridden to ensure that the name matches
                 /genscan/i.
     Returns   : String
     Argument  : n/a

next_feature
------------

     Title   : next_feature
     Usage   : while($gene = $genscan->next_feature()) {
                      # do something
               }
     Function: Returns the next gene structure prediction of the Genscan result
               file. Call this method repeatedly until FALSE is returned.

     The returned object is actually a SeqFeatureI implementing object.
     This method is required for classes implementing the
     SeqAnalysisParserI interface, and is merely an alias for
     next_prediction() at present.

     Example :
     Returns : A Bio::Tools::Prediction::Gene object.
     Args    :

next_prediction
---------------

     Title   : next_prediction
     Usage   : while($gene = $genscan->next_prediction()) {
                      # do something
               }
     Function: Returns the next gene structure prediction of the Genscan result
               file. Call this method repeatedly until FALSE is returned.

     Example :
     Returns : A Bio::Tools::Prediction::Gene object.
     Args    :

_parse_predictions
------------------

     Title   : _parse_predictions()
     Usage   : $obj->_parse_predictions()
     Function: Parses the prediction section. Automatically called by
               next_prediction() if not yet done.
     Example :
     Returns :

_prediction
-----------

     Title   : _prediction()
     Usage   : $gene = $obj->_prediction()
     Function: internal
     Example :
     Returns :

_add_prediction
---------------

     Title   : _add_prediction()
     Usage   : $obj->_add_prediction($gene)
     Function: internal
     Example :
     Returns :

_predictions_parsed
-------------------

     Title   : _predictions_parsed
     Usage   : $obj->_predictions_parsed
     Function: internal
     Example :
     Returns : TRUE or FALSE

_has_cds
--------

     Title   : _has_cds()
     Usage   : $obj->_has_cds()
     Function: Whether or not the result contains the predicted CDSs, too.
     Example :
     Returns : TRUE or FALSE

_read_fasta_seq
---------------

     Title   : _read_fasta_seq()
     Usage   : ($id,$seqstr) = $obj->_read_fasta_seq();
     Function: Simple but specialised FASTA format sequence reader. Uses
               $self->_readline() to retrieve input, and is able to strip off
               the traling description lines.
     Example :
     Returns : An array of two elements.

One particular domain hit from HMMER
************************************

NAME
====

   Bio::Tools::HMMER::Domain - One particular domain hit from HMMER

SYNOPSIS
========

   Read the Bio::Tools::HMMER::Results docs

DESCRIPTION
===========

   A particular domain score. We reuse the Homol SeqFeature system here,
so this inherits off Homol SeqFeature. As this code originally came from a
separate project, there are some backward compatibility stuff provided to
keep this working with old code.

   Don\'t forget this inherits off Bio::SeqFeature, so all your usual nice
start/end/score stuff is ready for use.

CONTACT
=======

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

add_alignment_line
------------------

     Title   : add_alignment_line
     Usage   : $domain->add_alignment_line($line_from_hmmer_output);
     Function: add an alignment line to this Domain object
     Returns : Nothing
     Args    : scalar

     Adds an alignment line, mainly for storing the HMMER alignments
     as flat text which can be reguritated. You\'re right. This is *not
     nice* and not the right way to do it.  C\'est la vie.

each_alignment_line
-------------------

     Title   : each_alignment_line
     Usage   : foreach $line ( $domain->each_alignment_line )
     Function: reguritates the alignment lines as they were fed in.
               only useful realistically for printing.
     Example :
     Returns :
     Args    : None

get_nse
-------

     Title   : get_nse
     Usage   : $domain->get_nse()
     Function: Provides a seqname/start-end format, useful
               for unique keys. nse stands for name-start-end
               It is used alot in Pfam
     Example :
     Returns : A string
     Args    : Optional seperator 1 and seperator 2 (default / and -)

hmmacc
------

     Title   : hmmacc
     Usage   : $domain->hmmacc($newacc)
     Function: set get for HMM accession number. This is placed in the homol
               feature of the HMM
     Example :
     Returns :
     Args    :

hmmname
-------

     Title   : hmmname
     Usage   : $domain->hmmname($newname)
     Function: set get for HMM accession number. This is placed in the homol
               feature of the HMM
     Example :
     Returns :
     Args    :

bits
----

     Title   : bits
     Usage   :
     Function: backward compatibility. Same as score
     Example :
     Returns :
     Args    :

evalue
------

     Title   : evalue
     Usage   :
     Function: $domain->evalue($value);
     Example :
     Returns :
     Args    :

seqbits
-------

     Title   : seqbits
     Usage   :
     Function: $domain->seqbits($value);
     Example :
     Returns :
     Args    :

seq_range
---------

     Title   : seq_range
     Usage   :
     Function: Throws an exception to catch scripts which need to upgrade
     Example :
     Returns :
     Args    :

hmm_range
---------

     Title   : hmm_range
     Usage   :
     Function: Throws an exception to catch scripts which need to upgrade
     Example :
     Returns :
     Args    :

Object representing HMMER output results
****************************************

NAME
====

   Bio::Tools::HMMER::Results - Object representing HMMER output results

SYNOPSIS
========

     # parse a hmmsearch file (can also parse a hmmpfam file)
     $res = new Bio::Tools::HMMER::Results( -file => 'output.hmm' , -type => 'hmmsearch');

     # print out the results for each sequence
     foreach $seq ( $res->each_Set ) {
         print "Sequence bit score is",$seq->bits,"\n";
         foreach $domain ( $seq->each_Domain ) {
             print " Domain start ",$domain->start," end ",$domain->end,
     	   " score ",$domain->bits,"\n";
         }
     }

     # new result object on a sequence/domain cutoff of 25 bits sequence, 15 bits domain
     $newresult = $res->filter_on_cutoff(25,15);

     # alternative way of getting out all domains directly
     foreach $domain ( $res->each_Domain ) {
         print "Domain on ",$domain->seqname," with score ",
         $domain->bits," evalue ",$domain->evalue,"\n";
     }

DESCRIPTION
===========

   This object represents HMMER output, either from hmmsearch or hmmpfam.
For hmmsearch, a series of HMMER::Set objects are made, one for each
sequence, which have the the bits score for the object. For hmmpfam
searches, only one Set object is made.

   These objects come from the original HMMResults modules used internally
in Pfam, written by Ewan. Ewan then converted them to bioperl objects in
1999. That conversion is meant to be backwardly compatible, but may not be
(caveat emptor).

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                - General discussion
     http://www.bioperl.org/MailList.html - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://www.bioperl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email birney@sanger.ac.uk

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next_feature
------------

     Title   : next_feature
     Usage   : while( my $feat = $res->next_feature ) { # do something }
     Function: SeqAnalysisParserI implementing function
     Example :
     Returns : A Bio::SeqFeatureI compliant object, in this case,
               each DomainUnit object, ie, flattening the Sequence
               aspect of this.
     Args    : None

number
------

     Title   : number
     Usage   : print "There are ",$res->number," domains hit\n";
     Function: provides the number of domains in the HMMER report

add_Domain
----------

     Title   : add_Domain
     Usage   : $res->add_Domain($unit)
     Function: adds a domain to the results array. Mainly used internally.
     Args    : A Bio::Tools::HMMER::Domain

each_Domain
-----------

     Title   : each_Domain
     Usage   : foreach $domain ( $res->each_Domain() )
     Function: array of Domain units which are held in this report
     Returns : array
     Args    : none

domain_bits_cutoff_from_evalue
------------------------------

     Title   : domain_bits_cutoff_from_evalue
     Usage   : $cutoff = domain_bits_cutoff_from_evalue(0.01);
     Function: return a bits cutoff from an evalue using the
               scores here. Somewhat interesting logic:
                Find the two bit score which straddle the evalue
                if( 25 is between these two points) return 25
                else return the midpoint.

     This logic tries to ensure that with large signal to
     noise separation one still has sensible 25 bit cutoff
      Returns :
      Args    :

write_FT_output
---------------

     Title   : write_FT_output
     Usage   : $res->write_FT_output(\*STDOUT,'DOMAIN')
     Function: writes feature table output ala swissprot
     Returns :
     Args    :

filter_on_cutoff
----------------

     Title   : filter_on_cutoff
     Usage   : $newresults = $results->filter_on_cutoff(25,15);
     Function: Produces a new HMMER::Results module which has
               been trimmed at the cutoff.
     Returns : a Bio::Tools::HMMER::Results module
     Args    : sequence cutoff and domain cutoff. in bits score
               if you want one cutoff, simply use same number both places

write_ascii_out
---------------

     Title   : write_ascii_out
     Usage   : $res->write_ascii_out(\*STDOUT)
     Function: writes as
               seq seq_start seq_end model-acc model_start model_end model_name
     Returns :
     Args    :

     FIXME: Now that we have no modelacc, this is probably a bad thing.

write_GDF_bits
--------------

     Title   : write_GDF_bits
     Usage   : $res->write_GDF_bits(25,15,\*STDOUT)
     Function: writes GDF format with a sequence,domain threshold
     Returns :
     Args    :

add_Set
-------

     Title   : add_Set
     Usage   : Mainly internal function
     Function:
     Returns :
     Args    :

each_Set
--------

     Title   : each_Set
     Usage   :
     Function:
     Returns :
     Args    :

get_Set
-------

     Title   : get_Set
     Usage   : $set = $res->get_Set('sequence-name');
     Function: returns the Set for a particular sequence
     Returns : a HMMER::Set object
     Args    : name of the sequence

_parse_hmmpfam
--------------

     Title   : _parse_hmmpfam
     Usage   : $res->_parse_hmmpfam($filehandle)
     Function:
     Returns :
     Args    :

_parse_hmmsearch
----------------

     Title   : _parse_hmmsearch
     Usage   : $res->_parse_hmmsearch($filehandle)
     Function:
     Returns :
     Args    :

Set of identical domains from HMMER matches
*******************************************

NAME
====

   Bio::Tools::HMMER::Set - Set of identical domains from HMMER matches

SYNOPSIS
========

     # get a Set object probably from the results object
     print "Bits score over set ",$set->bits," evalue ",$set->evalue,"\n";

     foreach $domain ( $set->each_Domain ) {
     	print "Domain start ",$domain->start," end ",$domain->end,"\n";
     }

DESCRIPTION
===========

   Represents a set of HMMER domains hitting one sequence. HMMER reports
two different scores, a per sequence total score (and evalue) and a per
domain score and evalue. This object represents a collection of the same
domain with the sequence bits score and evalue. (these attributes are also
on the per domain scores, which you can get there).

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                - General discussion
     http://www.bioperl.org/MailList.html - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.

   Bug reports can be submitted via email or the web:

     bioperl-bugs@bioperl.org
     http://www.bioperl.org/bioperl-bugs/

AUTHOR - Ewan Birney
====================

   Email birney@sanger.ac.uk

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

add_Domain
----------

     Title   : add_Domain
     Usage   : $set->add_Domain($domain)
     Function: adds the domain to the list
     Returns : nothing
     Args    : A Bio::Tools::HMMER::Domain object

each_Domain
-----------

     Title   : each_Domain
     Usage   : foreach $domain ( $set->each_Domain() )
     Function: returns an array of domain objects in this set
     Returns : array
     Args    : none

name
----

     Title   : name
     Usage   : $obj->name($newval)
     Function:
     Example :
     Returns : value of name
     Args    : newvalue (optional)

evalue
------

     Title   : evalue
     Usage   : $obj->evalue($newval)
     Function:
     Example :
     Returns : value of evalue
     Args    : newvalue (optional)

Generates unique Seq objects from an ambiguous Seq object
*********************************************************

NAME
====

   IUPAC - Generates unique Seq objects from an ambiguous Seq object

SYNOPSIS
========

     use Bio::Seq;
     use Bio::Tools::IUPAC;

     my $ambiseq = new Bio::Seq (-seq => 'ARTCGUTGR', -type => 'Dna');
     my $stream  = new Bio::Tools::IUPAC(-seq => $ambiseq);

     while ($uniqueseq = $stream->next_seq()) {
         # process the unique Seq object.
     }

DESCRIPTION
===========

   IUPAC is a tool that produces a stream of unique, "strict"-satisfying
Seq objects from an ambiquous Seq object (containing non-standard
characters given the meaning shown below)

     Extended Dna / Rna alphabet :
     (includes symbols for nucleotide ambiguity)
     ------------------------------------------
     Symbol       Meaning      Nucleic Acid
     ------------------------------------------
      A            A           Adenine
      C            C           Cytosine
      G            G           Guanine
      T            T           Thymine
      U            U           Uracil
      M          A or C
      R          A or G
      W          A or T
      S          C or G
      Y          C or T
      K          G or T
      V        A or C or G
      H        A or C or T
      D        A or G or T
      B        C or G or T
      X      G or A or T or C
      N      G or A or T or C

     IUPAC-IUB SYMBOLS FOR NUCLEOTIDE NOMENCLATURE:
       Cornish-Bowden (1985) Nucl. Acids Res. 13: 3021-3030.

   ----------------------------------

     Amino Acid alphabet:
      ------------------------------------------
      Symbol           Meaning
      ------------------------------------------
      A        Alanine
      B        Aspartic Acid, Asparagine
      C        Cystine
      D        Aspartic Acid
      E        Glutamic Acid
      F        Phenylalanine
      G        Glycine
      H        Histidine
      I        Isoleucine
      K        Lysine
      L        Leucine
      M        Methionine
      N        Asparagine
      P        Proline
      Q        Glutamine
      R        Arginine
      S        Serine
      T        Threonine
      V        Valine
      W        Tryptophan
      X        Unknown
      Y        Tyrosine
      Z        Glutamic Acid, Glutamine
      *        Terminator

     IUPAC-IUP AMINO ACID SYMBOLS:
       Biochem J. 1984 Apr 15; 219(2): 345-373
       Eur J Biochem. 1993 Apr 1; 213(1): 2

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://www.bioperl.org/MailList.html - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bioperl.org
     http://www.bioperl.org/bioperl-bugs/

AUTHOR - Aaron Mackey
=====================

   Email amackey@virginia.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
---

     Title   : new
     Usage   : new Bio::Tools::IUPAC $seq;
     Function: returns a new seq stream (akin to SeqIO)
     Returns : a Bio::Tools::IUPAC stream object that will produce unique
               Seq objects on demand.
     Args    : an ambiguously coded Seq.pm object that has a specified 'type'

next_seq
--------

     Title   : next_seq
     Usage   : $iupac->next_seq()
     Function: returns the next unique Seq object
     Returns : a Seq.pm object
     Args    : none.

Results of one MZEF run
***********************

NAME
====

   Bio::Tools::MZEF - Results of one MZEF run

SYNOPSIS
========

     $mzef = Bio::Tools::MZEF->new(-file => 'result.mzef');
     # filehandle:
     $mzef = Bio::Tools::MZEF->new( -fh  => \*INPUT );
     # to indicate that the sequence was reversed prior to feeding it to MZEF
     # and that you want to have this reflected in the strand() attribute of
     # the exons, as well have the coordinates translated to the non-reversed
     # sequence
     $mzef = Bio::Tools::MZEF->new( -file   => 'result.mzef',
                                    -strand => -1 );

     # parse the results
     # note: this class is-a Bio::Tools::AnalysisResult which implements
     # Bio::SeqAnalysisParserI, i.e., $genscan->next_feature() is the same
     while($gene = $mzef->next_prediction()) {
         # $gene is an instance of Bio::Tools::Prediction::Gene

     # $gene->exons() returns an array of
     # Bio::Tools::Prediction::Exon objects
     # all exons:
     @exon_arr = $gene->exons();

     # internal exons only
     @intrl_exons = $gene->exons('Internal');
     # note that presently MZEF predicts only internal exons!
        }

     # essential if you gave a filename at initialization (otherwise the file
     # will stay open)
     $mzef->close();

DESCRIPTION
===========

   The MZEF module provides a parser for MZEF gene structure prediction
output.

   This module inherits off Bio/Tools/AnalysisResult,
and therefore implements
Bio/SeqAnalysisParserI.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp
====================

   Email hlapp@gmx.net (or hilmar.lapp@pharma.novartis.com)

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

analysis_method
---------------

     Usage     : $mzef->analysis_method();
     Purpose   : Inherited method. Overridden to ensure that the name matches
                 /mzef/i.
     Returns   : String
     Argument  : n/a

next_feature
------------

     Title   : next_feature
     Usage   : while($gene = $mzef->next_feature()) {
                      # do something
               }
     Function: Returns the next gene structure prediction of the MZEF result
               file. Call this method repeatedly until FALSE is returned.

     The returned object is actually a SeqFeatureI implementing object.
     This method is required for classes implementing the
     SeqAnalysisParserI interface, and is merely an alias for
     next_prediction() at present.

     Note that with the present version of MZEF there will only be one
     object returned, because MZEF does not predict individual genes
     but just potential internal exons.
      Example :
      Returns : A Bio::Tools::Prediction::Gene object.
      Args    :

next_prediction
---------------

     Title   : next_prediction
     Usage   : while($gene = $mzef->next_prediction()) {
                      # do something
               }
     Function: Returns the next gene structure prediction of the MZEF result
               file. Call this method repeatedly until FALSE is returned.

     Note that with the present version of MZEF there will only be one
     object returned, because MZEF does not predict individual genes
     but just potential internal exons.
      Example :
      Returns : A Bio::Tools::Prediction::Gene object.
      Args    :

_parse_predictions
------------------

     Title   : _parse_predictions()
     Usage   : $obj->_parse_predictions()
     Function: Parses the prediction section. Automatically called by
               next_prediction() if not yet done.
     Example :
     Returns :

_prediction
-----------

     Title   : _prediction()
     Usage   : $gene = $obj->_prediction()
     Function: internal
     Example :
     Returns :

_add_prediction
---------------

     Title   : _add_prediction()
     Usage   : $obj->_add_prediction($gene)
     Function: internal
     Example :
     Returns :

_predictions_parsed
-------------------

     Title   : _predictions_parsed
     Usage   : $obj->_predictions_parsed
     Function: internal
     Example :
     Returns : TRUE or FALSE

Object holding alternative alphabet coding for  one protein sequence
********************************************************************

NAME
====

   Bio::Tools::OddCodes - Object holding alternative alphabet coding for
one protein sequence

SYNOPSIS
========

   Take a sequence object from eg, an inputstream, and creates an object
for the purposes of rewriting that sequence in another alphabet.  These
are abbreviated amino acid sequence alphabets, designed to simplify the
statistical aspects of analysing protein sequences, by reducing the
combinatorial explosion of the 20-letter alphabet.  These abbreviated
alphabets range in size from 2 to 8.

   Creating the OddCodes object, eg:

     my $inputstream = Bio::SeqIO->new( '-file' => "seqfile",
                                                '-format' => 'Fasta');
     my $seqobj = $inputstream->next_seq();
     my $oddcode_obj = Bio::Tools::Oddcodes->new(-seq => $seqobj);

   or:

     my $seqobj = Bio::PrimarySeq->new
                   (-seq=>'[cut and paste a sequence here]',
                    -moltype = 'protein',
                    -id = 'test');
     my $oddcode_obj  =  Bio::Tools::OddCodes->new(-seq => $seqobj);

   do the alternative coding, returning the answer as a reference to a
string

     my $output = $oddcode_obj->structural();
     my $output = $oddcode_obj->chemical();
     my $output = $oddcode_obj->functional();
     my $output = $oddcode_obj->charge();
     my $output = $oddcode_obj->hydrophobic();
     my $output = $oddcode_obj->Dayhoff();
     my $output = $oddcode_obj->Sneath();
     my $output = $oddcode_obj->Stanfel();

   display sequence in new form, eg:

     my $new_coding = $$output;
     print "\n$new_coding";

DESCRIPTION
===========

   Bio::Tools::Oddcodes is a welterweight object for rewriting a protein
sequence in an alternative alphabet.  8 of these are provided, ranging
from the the 2-letter hydrophobic alphabet, to the 8-letter chemical
alphabet.  These are useful for the statistical analysis of protein
sequences since they can partially avoid the combinatorial explosion
produced by the full 20-letter alphabet (eg. 400 dimers, 8000 trimers etc.)

   See Synopsis above for object creation code.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                - General discussion
     http://www.bioperl.org/MailList.html - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bioperl.org
     http://www.bioperl.org/bioperl-bugs/

AUTHOR
======

   Derek Gatherer

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

structural
----------

     Title   : structural
     Usage   : $output = $oddcode_obj->structural();
     Function: turns amino acid sequence into 3-letter structural alphabet
     	 : A (ambivalent), E (external), I (internal)
     Example : a sequence ACDEFGH will become AAEEIAE
     Returns : Reference to the new sequence string
     Args    : none

functional
----------

     Title   : functional
     Usage   : $output = $oddcode_obj->functional();
     Function: turns amino acid sequence into 4-letter functional alphabet
     	 : A (acidic), C (basic), H (hydrophobic), P (polar)
     Example : a sequence ACDEFGH will become HPAAHHC
     Returns : Reference to the new sequence string
     Args    : none

hydrophobic
-----------

     Title   : hydrophobic
     Usage   : $output = $oddcode_obj->hydrophobic();
     Function: turns amino acid sequence into 2-letter hydrophobicity alphabet
     	 : O (hydrophobic), I (hydrophilic)
     Example : a sequence ACDEFGH will become OIIIOII
     Returns : Reference to the new sequence string
     Args    : none

Dayhoff
-------

     Title   : Dayhoff
     Usage   : $output = $oddcode_obj->Dayhoff();
     Function: turns amino acid sequence into 6-letter Dayhoff alphabet
     Example : a sequence ACDEFGH will become CADDGCE
     Returns : Reference to the new sequence string
     Args    : none

Sneath
------

     Title   : Sneath
     Usage   : $output = $oddcode_obj->Sneath();
     Function: turns amino acid sequence into 7-letter Sneath alphabet
     Example : a sequence ACDEFGH will become CEFFHCF
     Returns : Reference to the new sequence string
     Args    : none

Stanfel
-------

     Title   : Stanfel
     Usage   : $output = $oddcode_obj->Stanfel();
     Function: turns amino acid sequence into 4-letter Stanfel alphabet
     Example : a sequence ACDEFGH will become AACCDAE
     Returns : Reference to the new sequence string
     Args    : none

chemical()
----------

     Title   : chemical
     Usage   : $output = $oddcode_obj->chemical();
     Function: turns amino acid sequence into 8-letter chemical alphabet
     	 : A (acidic), L (aliphatic), M (amide), R (aromatic)
     	 : C (basic), H (hydroxyl), I (imino), S (sulphur)
     Example : a sequence ACDEFGH will become LSAARAC
     Returns : Reference to the new sequence string
     Args    : none

charge
------

     Title   : charge
     Usage   : $output = $oddcode_obj->charge();
     Function: turns amino acid sequence into 3-letter charge alphabet
     Example : a sequence ACDEFGH will become NNAANNC
     Returns : Reference to the new sequence string
     Args    : none

A predicted exon feature
************************

NAME
====

   Bio::Tools::Prediction::Exon - A predicted exon feature

SYNOPSIS
========

   See documentation of methods.

DESCRIPTION
===========

   A feature representing a predicted exon. This class actually inherits
off Bio::SeqFeature::Gene::Exon and therefore has all that functionality
(also implements Bio::SeqFeatureI), plus a few methods supporting
predicted features, like various scores and a significance. Even though
these were inspired by GenScan results, at least a subset should be
generally useable for exon prediction results.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp
====================

   Email hlapp@gmx.net

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

predicted_cds
-------------

     Title   : predicted_cds
     Usage   : $predicted_cds_dna = $exon->predicted_cds();
               $exon->predicted_cds($predicted_cds_dna);
     Function: Get/Set the CDS (coding sequence) as predicted by a program.

     This method is independent of an attached_seq. There is no
     guarantee whatsoever that the returned CDS has anything to do
     (e.g., matches) with the sequence covered by the exons as annotated
     through this object.

     Example :
     Returns : A Bio::PrimarySeqI implementing object holding the DNA sequence
               defined as coding by a prediction of a program.
     Args    : On set, a Bio::PrimarySeqI implementing object holding the DNA
               sequence defined as coding by a prediction of a program.

predicted_protein
-----------------

     Title   : predicted_protein
     Usage   : $predicted_protein_seq = $exon->predicted_protein();
               $exon->predicted_protein($predicted_protein_seq);
     Function: Get/Set the protein translation as predicted by a program.

     This method is independent of an attached_seq. There is no
     guarantee whatsoever that the returned translation has anything to
     do with the sequence covered by the exons as annotated
     through this object, or the sequence returned by predicted_cds(),
     although it should usually be just the standard translation.

     Example :
     Returns : A Bio::PrimarySeqI implementing object holding the protein
               translation as predicted by a program.
     Args    : On set, a Bio::PrimarySeqI implementing object holding the protein
               translation as predicted by a program.

significance
------------

     Title   : significance
     Usage   : $evalue = $obj->significance();
               $obj->significance($evalue);
     Function:
     Returns :
     Args    :

start_signal_score
------------------

     Title   : start_signal_score
     Usage   : $sc = $obj->start_signal_score();
               $obj->start_signal_score($evalue);
     Function: Get/Set a score for the exon start signal (acceptor splice site
               or initiation signal).
     Returns :
     Args    :

end_signal_score
----------------

     Title   : end_signal_score
     Usage   : $sc = $obj->end_signal_score();
               $obj->end_signal_score($evalue);
     Function: Get/Set a score for the exon end signal (donor splice site
               or termination signal).
     Returns :
     Args    :

coding_signal_score
-------------------

     Title   : coding_signal_score
     Usage   : $sc = $obj->coding_signal_score();
               $obj->coding_signal_score($evalue);
     Function: Get/Set a score for the exon coding signal (e.g., coding potential).
     Returns :
     Args    :

a predicted gene structure feature
**********************************

NAME
====

   Bio::Tools::Prediction::Gene - a predicted gene structure feature

SYNOPSIS
========

   See documentation of methods.

DESCRIPTION
===========

   A feature representing a predicted gene structure. This class actually
inherits off Bio::SeqFeature::Gene::Transcript and therefore has all that
functionality, plus a few methods supporting predicted sequence features,
like a predicted CDS and a predicted translation.

   Exons held by an instance of this class will usually be instances of
Bio::Tools::Prediction::Exon, although they do not have to be. Refer to the
documentation of the class that produced the instance.

   Normally, you will not want to create an instance of this class
yourself.  Instead, classes representing the results of gene structure
prediction programs will do that.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Hilmar Lapp
====================

   Email hlapp@gmx.net or hilmar.lapp@pharma.novartis.com

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

predicted_cds
-------------

     Title   : predicted_cds
     Usage   : $predicted_cds_dna = $gene->predicted_cds();
               $gene->predicted_cds($predicted_cds_dna);
     Function: Get/Set the CDS (coding sequence) as predicted by a program.

     This method is independent of an attached_seq. There is no
     guarantee whatsoever that the returned CDS has anything to do
     (e.g., matches) with the sequence covered by the exons as annotated
     through this object.

     Example :
     Returns : A Bio::PrimarySeqI implementing object holding the DNA sequence
               defined as coding by a prediction of a program.
     Args    : On set, a Bio::PrimarySeqI implementing object holding the DNA
               sequence defined as coding by a prediction of a program.

predicted_protein
-----------------

     Title   : predicted_protein
     Usage   : $predicted_protein_seq = $gene->predicted_protein();
               $gene->predicted_protein($predicted_protein_seq);
     Function: Get/Set the protein translation as predicted by a program.

     This method is independent of an attached_seq. There is no
     guarantee whatsoever that the returned translation has anything to
     do with the sequence covered by the exons as annotated
     through this object, or the sequence returned by predicted_cds(),
     although it should usually be just the standard translation.

     Example :
     Returns : A Bio::PrimarySeqI implementing object holding the protein
               translation as predicted by a program.
     Args    : On set, a Bio::PrimarySeqI implementing object holding the protein
               translation as predicted by a program.

Bioperl object for a restriction endonuclease object.
*****************************************************

NAME
====

   Bio::Tools::RestrictionEnzyme.pm - Bioperl object for a restriction
endonuclease object.

SYNOPSIS
========

Object Creation
---------------

     require Bio::Tools::RestrictionEnzyme;

     ## Create a new object by name.

     $re1 = new Bio::Tools::RestrictionEnzyme(-NAME =>'EcoRI');

     ## Create a new object using special syntax
     ## which specifies the enzyme name, recognition site, and cut position.
     ## Used for enzymes not known to this module.

     $re2 = new Bio::Tools::RestrictionEnzyme(-NAME =>'EcoRV--GAT^ATC',
     				  	     -MAKE =>'custom');

INSTALLATION
============

   This module is included with the central Bioperl distribution:

     http://bio.perl.org/Core/Latest
     ftp://bio.perl.org/pub/DIST

   Follow the installation instructions included in the README file.

DESCRIPTION
===========

   The Bio::Tools::RestrictionEnzyme.pm module encapsulates generic data
and methods for using restriction endonucleases for in silico restriction
analysis of DNA sequences.

Considerations
--------------

   This module is a precursor for a more full featured version that may do
such things as download data from online databases such as REBase
http://www.neb.com/rebase/.  Thus, there is currently no functionality for
obtaining data about commercial availability for a restriction enzyme.

   At some point in the future, it may be best to derive
RestrictionEnzymes from a class such as Bio::Enzyme.pm or
Bio::Prot::Protein.pm so that more data about the enzyme and related
information can be easily obtained.

   This module is currently in use at

     http://genome-www.stanford.edu/Sacch3D/analysis/

   *This module is at an early stage of development and is not yet ready
for general use. API documentation is presently incomplete.*

DEPENDENCIES
============

   Bio::Tools::RestrictionEnzyme.pm is a concrete class that inherits from
*Bio::Root::Object.pm* and uses by delegation *Bio::Seq.pm*.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules.  Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org             - General discussion
     http://bioperl.org/MailList.shtml - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR
======

   Steve A. Chervitz, sac@genome.stanford.edu

VERSION
=======

   Bio::Tools::RestrictionEnzyme.pm, 0.04

COPYRIGHT
=========

   Copyright (c) 1997-8 Steve A. Chervitz. All Rights Reserved.  This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

     Bio::Root::Object.pm    - Base class.
     Bio::Seq.pm             - Lightweight sequence object.

     http://bio.perl.org/Projects/modules.html  - Online module documentation
     http://bio.perl.org/Projects/Blast/        - Bioperl Blast Project
     http://bio.perl.org/                       - Bioperl Project Homepage

APPENDIX
========

   Methods beginning with a leading underscore are considered private and
are intended for internal use by this module. They are not considered part
of the public interface and are described here for documentation purposes
only.

new
===

     Title     : new
     Purpose   : Initializes the RestrictionEnzyme object and calls
               : superclass constructor last (Bio:Seq.pm).
     Returns   : n/a
     Argument  : Parameters passed to new()
     Comments  : The process of creating a new SeqPattern.pm object
               : ensures that the pattern string is untained.

   See Also   : `_make_custom' in this node(), `_make_standard' in this
node(), *Bio::Seq.pm::_initialize()*

_make_standard
==============

     Title     : _make_standard
     Usage     : n/a; automatically called by _initialize()
     Purpose   : Permits custom RE object construction from name.
               : 'EcoRI'.
     Returns   : Hash containing named parameters for Bio::Seq.pm constructor.
     Argument  : String containing string with special syntax.
     Throws    : Exception if the requested enzyme name is unavailable.
               : NOTE: Case sensitive.

   See Also   : `_initialize' in this node(), `_make_custom' in this node()

_make_custom
============

     Title     : _make_custom
     Usage     : n/a; automatically called by _initialize()
     Purpose   : Permits custom RE object construction from strings
               : such as 'EcoRI--G^AATTC' as the name of the enzyme.
     Returns   : Hash containing named parameters for Bio::Seq.pm constructor.
     Argument  : String containing string with special syntax.
     Throws    : Exception if the string has bad syntax.
               : Warning if the string did not specify cut position.
               :         Places cut site after 5'-most position.

   See Also   : `_initialize' in this node()

cuts_after
==========

     Title     : cuts_after
     Usage     : $re->cuts_after();
     Purpose   : Sets/Gets the position of cleavage relative to the 5' end.
     Example   : $num = $re->cuts_after()
     Returns   : Integer
     Argument  : Integer (optional)
     Throws    : Exception if argument is non-numeric.
     Access    : Public
     Comments  : This method is only needed to change the cuts at
               : position. This data is automatically set during
               : construction.

   See Also   : `_make_standard' in this node(), `_make_custom' in this
node()

site
====

     Title     : site
     Usage     : $re->site();
     Purpose   : Gets the recognition sequence for the enzyme.
     Example   : $seq_string = $re->site();
     Returns   : String containing recognition sequence indicating
               : cleavage site as in  'G^AATTC'.
     Argument  : n/a
     Throws    : n/a

seq
===

     Title     : seq
     Usage     : $re->seq();
     Purpose   : Get the Bio::Seq.pm-derived object representing
               : the recognition sequence
     Returns   : String
     Argument  : n/a
     Throws    : n/a

   See Also   : `string' in this node(), `revcom' in this node()

string
======

     Title     : string
     Usage     : $re->string();
     Purpose   : Get a string representing the recognition sequence.
     Returns   : String
     Argument  : n/a
     Throws    : n/a
     Comments  : Delegates to the Bio::Seq.pm-derived object.

   See Also   : `seq' in this node(), `revcom' in this node()

revcom
======

     Title     : revcom
     Usage     : $re->revcom();
     Purpose   : Get a string representing the reverse complement of
               : the recognition sequence.
     Returns   : String
     Argument  : n/a
     Throws    : n/a
     Comments  : Delegates to the Bio::Seq.pm-derived object, but needs to get
                 out the string from it, as now Bio::Seq->revcom makes a Bio::Seq
                 object

   See Also   : `seq' in this node(), `string' in this node()

cut_seq
=======

     Title     : cut_seq
     Usage     : $re->cut_seq(<sequence object>);
     Purpose   : Conceptually cut or "digest" a DNA sequence with the given enzyme.
     Example   : $string = $re->cut_seq(<sequence object>);
     Returns   : List of strings containing the resulting fragments.
     Argument  : Reference to a Bio::Seq.pm-derived object.
     Throws    : Exception if argument is not an object.
               : (Does not yet verify that it is derived from Bio::Seq.pm.)
     Comments  : Strategy relies on Perl's built-in split() function.
               : Since split removes the recognition pattern, the resulting
               : fragments must be repaired after split()-ing.
               : There is currently no support for partial digestions.

cut_locations
=============

     Title     : cut_locations
     Usage     : my $locations = $re->cut_locations(<sequence_object>);
     Purpose   : Report the location of the recognition site(s) within
               : an input sequence.
     Example   : my $locations = $re->annotate_seq($seqObj);
     Returns   : Arrayref of starting locations where enzyme would cut
     Argument  : Reference to a Bio::SeqI-derived sequence object.
     Throws    : n/a
     Comments  :

annotate_seq
============

     Title     : annotate_seq
     Usage     : $re->annotate_seq(<sequence_object>);
     Purpose   : Identify the location of the recognition site(s) within
               : an input sequence. Uses HTML.
     Example   : $annot_seq = $re->annotate_seq($seqObj);
     Returns   : String containing the annotated sequence.
     Argument  : Reference to a Bio::Seq.pm-derived sequence object.
     Throws    : n/a
     Comments  : The annotated sequence must be viewed with a web
               : browser to see the location(s) of the recognition site(s).

palindromic
===========

     Title     : palindromic
     Usage     : $re->palindromic();
     Purpose   : Determines if the recognition sequence is palindromic
               : for the current restriction enzyme.
     Returns   : Boolean
     Argument  : n/a
     Throws    : n/a
     Access    : Public
     Comments  : A palindromic site (EcoRI): 5-GAATTC-3
               :                             3-CTTAAG-5

is_available
============

     Title     : is_available
     Usage     : $re->is_available(<string containing name of enzyme>);
     Purpose   : Determine if an enzyme is available (to this module).
               : (see the package lexical %RE).
     Example   : $re->is_available('EcoRI');
               : &Bio::Tools::RestrictionEnzyme::is_available($object,'EcoRI');
     Returns   : Boolean
     Argument  : String
     Throws    : n/a
     Comments  : This method does NOT give information about
               : commercial availability (yet).
               : Enzyme names are CASE SENSITIVE.

   See Also   : `available_list' in this node()

name
----

     Title   : name
     Usage   : $obj->name($newval)
     Function:
     Example :
     Returns : value of name
     Args    : newvalue (optional)

available_list
==============

     Title     : available_list
     Usage     : $re->available_list([<integer>]);
     Purpose   : Retrieve a list of currently available enzymes.
     Example   : @all = $re->available_list();  ## All enzymes
               : @six_cutters = $re->available_list(6);  ## All 6-cutters
     Returns   : List of strings
     Argument  : Integer (optional)
     Throws    : n/a
     Comments  : This method may be more appropriate for a REData.pm class.

   See Also   : `is_available' in this node()

FOR DEVELOPERS ONLY
===================

Data Members
------------

   Information about the various data members of this module is provided
for those wishing to modify or understand the code. Two things to bear in
mind:

  1. Do NOT rely on these in any code outside of this module.  All data
     members are prefixed with an underscore to signify that they are
     private.  Always use accessor methods. If the accessor doesn't exist
     or is inadequate, create or modify an accessor (and let me know,
     too!).

  2. This documentation may be incomplete and out of date.  It is easy for
     this documentation to become obsolete as this module is still
     evolving.  Always double check this info and search for members not
     described here.

        An instance of Bio::Tools::RestrictionEnzyme.pm is a blessed
reference to a hash containing all or some of the following fields:

     FIELD          VALUE
     ------------------------------------------------------------------------
     _seq         : A Bio::Seq.pm-derived object.
                  :
     _site        : String containing the recognition sequence.
                  :
     _cuts_after  : Integer indicating the cleavage position relative to the
                  : 5' end of the recognition sequence.

     INHERITED DATA MEMBERS:

     _name      : (From Bio::Bio::Root::Object.pm) String containing name of the enzyme.

Object for the calculation of a multiple sequence alignment from a set of unaligned sequences or alignments using the Clustalw program
**************************************************************************************************************************************

NAME
====

   Bio::Tools::Run::Alignment::Clustalw - Object for the calculation of a
multiple sequence alignment from a set of unaligned sequences or
alignments using the Clustalw program

SYNOPSIS
========

     #  Build a clustalw alignment factory
     @params = ('ktuple' => 2, 'matrix' => 'BLOSUM');
     $factory = Bio::Tools::Run::Alignment::Clustalw->new(@params);

     #  Pass the factory a list of sequences to be aligned.
     $inputfilename = 't/cysprot.fa';
     $aln = $factory->align($inputfilename); # $aln is a SimpleAlign object.
     # or
     $seq_array_ref = \@seq_array;
     # where @seq_array is an array of Bio::Seq objects
     $aln = $factory->align($seq_array_ref);

     # Or one can pass the factory a pair of (sub)alignments
     #to be aligned against each other, e.g.:
     $aln = $factory->profile_align($aln1,$aln2);
     # where $aln1 and $aln2 are Bio::SimpleAlign objects.

     # Or one can pass the factory an alignment and one or more unaligned
     # sequences to be added to the alignment. For example:
     $aln = $factory->profile_align($aln1,$seq); # $seq is a Bio::Seq object.

   There are various additional options and input formats available.  See
the DESCRIPTION section that follows for additional details.

DESCRIPTION
===========

   Note: this DESCRIPTION only documents the (Bio)perl interface to
Clustalw.  Clustalw, itself, is a large & complex program - for more
information regarding clustalw, please see the clustalw documentation
which accompanies the clustalw distribution. Clustalw is available from
(among others) ftp://ftp.ebi.ac.uk/pub/software/. Clustalw.pm has been
tested so far only under Linux. I expect that it should also work under
other Unix systems.  However, since the module is currently implemented
using (unix) system calls, extensive modification may be necessary before
Clustalw.pm would work under non-Unix operating systems (eg Windows,
MacOS).  Clustalw.pm has only been tested using version 1.8 of clustalw.
Compatibility with earlier versions of the clustalw program is currently
unknown. Before running Clustalw.pm successfully it will be necessary: to
install clustalw on your system, to edit the variable $clustdir in
Clustalw.pm to point to the clustalw program, and to ensure that users
have execute privilieges for the clustalw program.

   Bio::Tools::Run::Alignment::Clustalw.pm: is an object for performing a
multiple sequence alignment from a set of unaligned sequences and/or
sub-alignments by means of the clustalw program.

   Initially, a clustalw "factory object" is created. Optionally, the
factory may be passed most of the parameters or switches of the clustalw
program, e.g.:

     @params = ('ktuple' => 2, 'matrix' => 'BLOSUM');
     $factory = Bio::Tools::Run::Alignment::Clustalw->new(@params);

   Any parameters not explicitly set will remain as the defaults of the
clustalw program.  Additional parameters and switches (not available in
clustalw) may also be set.  Currently, the only such parameter is "quiet",
which when set to a non-zero value, suppresses clustalw terminal output.
Not all clustalw parameters are supported at this stage.

   By default, Clustalw.pm output is returned solely in a the form of a
BioPerl Bio::SimpleAlign object which can then be printed and/or saved in
multiple formats using the AlignIO.pm module. Optionally the raw clustalw
output file can be saved if the calling script specifies an output file
(with the clustalw parameter OUTFILE).  Currently only the GCG-MSF output
file formats is supported.

   Other parameters and features (such as those corresponding to tree
production) have not been implemented yet in Perl format.

   Alignment parameters can be changed and/or examined at any time after
the factory has been created.  The program checks that any
parameter/switch being set/read is valid.  However, currently no
additional checks are included to check that parameters are of the proper
type (eg string or numeric) or that their values are within the proper
range.  As an example, to change the value of the clustalw parameter
ktuple to 3 and subsequently to check its value one would write:

     $ktuple = 3;
     $factory->ktuple($ktuple);
      	$get_ktuple = $factory->ktuple();

   Once the factory has been created and the appropriate parameters set,
one can call the method align() to align a set of unaligned sequences, or
call profile_align() to add one or more sequences or a second alignment to
an initial alignment.

   Input to align() may consist of a set of unaligned sequences in the
form of the name of file containing the sequences. For example,
$inputfilename = 't/cysprot.fa'; $aln = $factory->align($inputfilename);

   Alternately one can create an array of Bio::Seq objects somehow

     $str = Bio::SeqIO->new(-file=> 't/cysprot.fa', '-format' => 'Fasta');
     @seq_array =();
     while ( my $seq = $str->next_seq() ) {push (@seq_array, $seq) ;}

   and pass the factory a reference to that array

     $seq_array_ref = \@seq_array;
     $aln = $factory->align($seq_array_ref);

   In either case, align() returns a reference to a SimpleAlign object
which can then be displayed, stored, or converted to a UnivAlign object
for further manipulation.

   Once an initial alignment exists, one can pass the factory additional
sequence(s) to be added (ie aligned) to the original alignment.  The
alignment can be passed as either an alignment file or a Bio:SimpleAlign
object.  The unaligned sequence(s) can be passed as a filename or as an
array of BioPerl sequence objects or as a single BioPerl Seq object.  For
example (to add a single sequence to an alignment),

     $str = Bio::AlignIO->new(-file=> 't/cysprot1a.msf');
     $aln = $str->next_aln();
     $str1 = Bio::SeqIO->new(-file=> 't/cysprot1b.fa');
     $seq = $str1->next_seq();
     $aln = $factory->profile_align($aln,$seq);

   In either case, profile_align() returns a reference to a SimpleAlign
object containing a new SimpleAlign object of the alignment with the
additional sequence(s) added in.

   Finally one can pass the factory a pair of (sub)alignments to be
aligned against each other.  The alignments can be passed in the form of
either a pair of alignment files or a pair of Bio:SimpleAlign objects. For
example,

     $profile1 = 't/cysprot1a.msf';
     $profile2 = 't/cysprot1b.msf';
     $aln = $factory->profile_align($profile1,$profile2);
     or
     $str1 = Bio::AlignIO->new(-file=> 't/cysprot1a.msf');
     $aln1 = $str1->next_aln();
     $str2 = Bio::AlignIO->new(-file=> 't/cysprot1b.msf');
     $aln2 = $str2->next_aln();
     $aln = $factory->profile_align($aln1,$aln2);

   In either case, profile_align() returns a reference to a SimpleAlign
object containing an (super)alignment of the two input alignments.

   For more examples of syntax and use of Clustalw.pm, the user is
encouraged to run the script Clustalw.t is the bioperl/t directory.

   Note: Clustalw.pm is still under development. Various features of the
clustalw program have not yet been implemented.  If you would like that a
specific clustalw feature be added to this perl interface, let me know.

   These can be specified as paramters when instantiating a new TCoffee
object, or through get/set methods of the same name (lowercase).

PARAMETER FOR ALIGNMENT COMPUTATION
===================================

KTUPLE
------

     Title       : KTUPLE
     Description : (optional) set the word size to be used in the alignment
                   This is the size of exactly matching fragment that is used.
                   INCREASE for speed (max= 2 for proteins; 4 for DNA),
                   DECREASE for sensitivity.
                   For longer sequences (e.g. >1000 residues) you may
                   need to increase the default

TOPDIAGS
--------

     Title       : TOPDIAGS
     Description : (optional) number of best diagonals to use
                   The number of k-tuple matches on each diagonal
                   (in an imaginary dot-matrix plot) is calculated.
                   Only the best ones (with most matches) are used in
                   the alignment.  This parameter specifies how many.
                   Decrease for speed; increase for sensitivity.

WINDOW
------

     Title       : WINDOW
     Description : (optional) window size
                   This is the number of diagonals around each of the 'best'
                   diagonals that will be used.  Decrease for speed;
                   increase for sensitivity.

PAIRGAP
-------

     Title       : PAIRGAP
     Description : (optional) gap penalty for pairwise alignments
                   This is a penalty for each gap in the fast alignments.
                   It has little affect on the speed or sensitivity except
                   for extreme values.

FIXEDGAP
--------

     Title       : FIXEDGAP
     Description : (optional) fixed length gap penalty

FLOATGAP
--------

     Title       : FLOATGAP
     Description : (optional) variable length gap penalty

MATRIX
------

     Title       : MATRIX
     Default     : PAM100 for DNA - PAM250 for protein alignment
     Description : (optional) substitution matrix used in the multiple
                   alignments. Depends on the version of clustalw as to
                   what default matrix will be used

     PROTEIN WEIGHT MATRIX leads to a new menu where you are
     offered a choice of weight matrices. The default for
     proteins in version 1.8 is the PAM series derived by
     Gonnet and colleagues. Note, a series is used! The
     actual matrix that is used depends on how similar the
     sequences to be aligned at this alignment step
     are. Different matrices work differently at each
     evolutionary distance.

     DNA WEIGHT MATRIX leads to a new menu where a single
     matrix (not a series) can be selected. The default is
     the matrix used by BESTFIT for comparison of nucleic
     acid sequences.

TYPE
----

     Title       : TYPE
     Description : (optional) sequence type: protein or DNA. This allows
     	       you to explicitly overide the programs attempt at
     	       guessing the type of the sequence.  It is only useful
     	       if you are using sequences with a VERY strange
     	       composition.

OUTPUT
------

     Title       : OUTPUT
     Description : (optional) clustalw supports GCG or PHYLIP or PIR or
                    Clustal format.  See the Bio::AlignIO modules for
                    which formats are supported by bioperl.

OUTFILE
-------

     Title       : OUTFILE
     Description : (optional) Name of clustalw output file. If not set
     	       module will erase output file.  In any case alignment will
     	       be returned in the form of SimpleAlign objects

TRANSMIT
--------

     Title       : TRANSMIT
     Description : (optional) transitions not weighted.  The default is to
     	       weight transitions as more favourable than other
     	       mismatches in DNA alignments.  This switch makes all
     	       nucleotide mismatches equally weighted.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via  email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR -  Peter Schattner
=========================

   Email schattner@alum.mit.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

exists_clustal()
----------------

     Title   : exists_clustal
     Usage   : $clustalfound = Bio::Tools::Run::Alignment::Clustalw->exists_clustal()
     Function: Determine whether clustalw program can be found on current host
     Example :
     Returns : 1 if clustalw program found at expected location, 0 otherwise.
     Args    :  none

align
-----

     Title   : align
     Usage   :
     	$inputfilename = 't/cysprot.fa';
     	$aln = $factory->align($inputfilename);
     or
     	$seq_array_ref = \@seq_array; @seq_array is array of Seq objs
     	$aln = $factory->align($seq_array_ref);
     Function: Perform a multiple sequence alignment
     Example :
     Returns : Reference to a SimpleAlign object containing the
               sequence alignment.
     Args    : Name of a file containing a set of unaligned fasta sequences
               or else an array of references to Bio::Seq objects.

     Throws an exception if argument is not either a string (eg a
     filename) or a reference to an array of Bio::Seq objects.  If
     argument is string, throws exception if file corresponding to string
     name can not be found. If argument is Bio::Seq array, throws
     exception if less than two sequence objects are in array.

profile_align
-------------

     Title   : profile_align
     Usage   :
     Function: Perform an alignment of 2 (sub)alignments
     Example :
     Returns : Reference to a SimpleAlign object containing the (super)alignment.
     Args    : Names of 2 files containing the subalignments
             or references to 2 Bio::SimpleAlign objects.

   Throws an exception if arguments are not either strings (eg filenames)
or references to SimpleAlign objects.

_run
----

     Title   :  _run
     Usage   :  Internal function, not to be called directly
     Function:   makes actual system call to clustalw program
     Example :
     Returns : nothing; clustalw output is written to a
               temporary file $TMPOUTFILE
     Args    : Name of a file containing a set of unaligned fasta sequences
               and hash of parameters to be passed to clustalw

_setinput()
-----------

     Title   :  _setinput
     Usage   :  Internal function, not to be called directly
     Function:   Create input file for clustalw program
     Example :
     Returns : name of file containing clustalw data input
     Args    : Seq or Align object reference or input file name

_setparams()
------------

     Title   :  _setparams
     Usage   :  Internal function, not to be called directly
     Function:   Create parameter inputs for clustalw program
     Example :
     Returns : parameter string to be passed to clustalw
               during align or profile_align
     Args    : name of calling object

Object for the calculation of a multiple sequence alignment from a set of unaligned sequences or alignments using the TCoffee program
*************************************************************************************************************************************

NAME
====

   Bio::Tools::Run::Alignment::TCoffee - Object for the calculation of a
multiple sequence alignment from a set of unaligned sequences or
alignments using the TCoffee program

SYNOPSIS
========

     # Build a tcoffee alignment factory
     @params = ('ktuple' => 2, 'matrix' => 'BLOSUM');
     $factory = new Bio::Tools::Run::Alignment::TCoffee (@params);

     # Pass the factory a list of sequences to be aligned.
     $inputfilename = 't/cysprot.fa';
     # $aln is a SimpleAlign object.
     $aln = $factory->align($inputfilename);

     # or where @seq_array is an array of Bio::Seq objects
     $seq_array_ref = \@seq_array;
     $aln = $factory->align($seq_array_ref);

     # Or one can pass the factory a pair of (sub)alignments
     #to be aligned against each other, e.g.:

     # where $aln1 and $aln2 are Bio::SimpleAlign objects.
     $aln = $factory->profile_align($aln1,$aln2);

     # Or one can pass the factory an alignment and one or more
     # unaligned sequences to be added to the alignment. For example:

     # $seq is a Bio::Seq object.
     $aln = $factory->profile_align($aln1,$seq);

   There are various additional options and input formats available.  See
the DESCRIPTION section that follows for additional details.

DESCRIPTION
===========

   Note: this DESCRIPTION only documents the (Bio)perl interface to
TCoffee.

   There are a number of possible parameters one can pass in TCoffee.  One
should really read the online manual for the best explaination of all the
features.  See
http://igs-server.cnrs-mrs.fr/~cnotred/Documentation/t_coffee/t_coffee_doc.html

   These can be specified as paramters when instantiating a new TCoffee
object, or through get/set methods of the same name (lowercase).

PARAMETERS FOR ALIGNMENT COMPUTATION
====================================

IN
--

     Title       : IN
     Description : (optional) input filename, this is specified when
                   align so should not use this directly unless one
                   understand TCoffee program very well.

TYPE
----

     Title       : TYPE
     Args        : [string] DNA, PROTEIN
     Description : (optional) set the sequence type, guessed automatically
                   so should not use this directly

PARAMETERS
----------

     Title       : PARAMETERS
     Description : (optional) Indicates a file containing extra parameters

EXTEND
------

     Title       : EXTEND
     Args        : 0, 1, or positive value
     Default     : 1
     Description : Flag indicating that library extension should be
                   carried out when performing multiple alignments, if set
                   to 0 then extension is not made, if set to 1 extension
                   is made on all pairs in the library.  If extension is
                   set to another positive value, the extension is only
                   carried out on pairs having a weigth value superior to
                   the specified limit.

DP_NORMALISE
------------

     Title       : DP_NORMALISE
     Args        : 0 or positive value
     Default     : 1000
     Description : When using a value different from 0, this flag sets the
                   score of the highest scoring pair to 1000.

DP_MODE
-------

     Title       : DP_MODE
     Args        : [string] gotoh_pair_wise, myers_miller_pair_wise,
                   fasta_pair_wise cfasta_pair_wise
     Default     : cfast_fair_wise
     Description : Indicates the type of dynamic programming used by
                   the program

     gotoh_pair_wise : implementation of the gotoh algorithm
     (quadratic in memory and time)

     myers_miller_pair_wise : implementation of the Myers and Miller
     dynamic programming algorithm ( quadratic in time and linear in
     space). This algorithm is recommended for very long sequences. It
     is about 2 time slower than gotoh. It only accepts tg_mode=1.

     fasta_pair_wise: implementation of the fasta algorithm. The
     sequence is hashed, looking for ktuples words. Dynamic programming
     is only carried out on the ndiag best scoring diagonals. This is
     much faster but less accurate than the two previous.

     cfasta_pair_wise : c stands for checked. It is the same
     algorithm. The dynamic programming is made on the ndiag best
     diagonals, and then on the 2*ndiags, and so on until the scores
     converge. Complexity will depend on the level of divergence of the
     sequences, but will usually be L*log(L), with an accuracy
     comparable to the two first mode ( this was checked on BaliBase).

KTUPLE
------

     Title       : KTUPLE
     Args        : numeric value
     Default     : 1 or 2 (1 for protein, 2 for DNA )

     Description : Indicates the ktuple size for cfasta_pair_wise dp_mode
                   and fasta_pair_wise. It is set to 1 for proteins, and 2
                   for DNA. The alphabet used for protein is not the 20
                   letter code, but a mildly degenerated version, where
                   some residues are grouped under one letter, based on
                   physicochemical properties:
                   rk, de, qh, vilm, fy (the other residues are
                   not degenerated).

NDIAGS
------

     Title       : NDIAGS
     Args        : numeric value
     Default     : 0
     Description : Indicates the number of diagonals used by the
                   fasta_pair_wise algorithm. When set to 0,
                   n_diag=Log (length of the smallest sequence)

DIAG_MODE
---------

     Title       : DIAG_MODE
     Args        : numeric value
     Default     : 0

     Description : Indicates the manner in which diagonals are scored
                  during the fasta hashing.

     0 indicates that the score of a diagonal is equal to the
     sum of the scores of the exact matches it contains.

     1 indicates that this score is set equal to the score of
     the best uninterrupted segment

     1 can be useful when dealing with fragments of sequences.

SIM_MATRIX
----------

     Title       : SIM_MATRIX
     Args        : string
     Default     : vasiliky
     Description : Indicates the manner in which the amino acid is being
                   degenerated when hashing. All the substitution matrix
                   are acceptable. Categories will be defined as sub-group
                   of residues all having a positive substitution score
                   (they can overlap).

     If you wish to keep the non degenerated amino acid
     alphabet, use 'idmat'

MATRIX
------

     Title       : MATRIX
     Args        :
     Default     :
     Description : This flag is provided for compatibility with
                   ClustalW. Setting matrix = 'blosum' is equivalent to
                   -in=Xblosum62mt , -matrix=pam is equivalent to
                   in=Xpam250mt . Apart from this, the rules are similar
                   to those applying when declaring a matrix with the
                   -in=X fl

GAPOPEN
-------

     Title       : GAPOPEN
     Args        : numeric
     Default     : 0
     Description : Indicates the penalty applied for opening a gap. The
                   penalty must be negative. If you provide a positive
                   value, it will automatically be turned into a negative
                   number. We recommend a value of 10 with pam matrices,
                   and a value of 0 when a library is used.

GAPEXT
------

     Title       : GAPEXT
     Args        : numeric
     Default     : 0
     Description : Indicates the penalty applied for extending a gap.

COSMETIC_PENALTY
----------------

     Title       : COSMETIC_PENALTY
     Args        : numeric
     Default     : 100
     Description : Indicates the penalty applied for opening a gap. This
                   penalty is set to a very low value. It will only have
                   an influence on the portions of the alignment that are
                   unalignable. It will not make them more correct, but
                   only more pleasing to the eye ( i.e. Avoid stretches of
                   lonely residues).

     The cosmetic penalty is automatically turned off if a
     substitution matrix is used rather than a library.

TG_MODE
-------

     Title       : TG_MODE
     Args        : 0,1,2
     Default     : 1
     Description : (Terminal Gaps)
                   0: indicates that terminal gaps must be panelized with
                      a gapopen and a gapext penalty.
                   1: indicates that terminal gaps must be penalized only
                      with a gapext penalty
                   2: indicates that terminal gaps must not be penalized.

WEIGHT
------

     Title       : WEIGHT
     Args        : sim or sim_<matrix_name or matrix_file> or integer value
     Default     : sim

     Description : Weight defines the way alignments are weighted when
                   turned into a library.

     sim indicates that the weight equals the average
         identity within the match residues.

     sim_matrix_name indicates the average identity with two
         residues regarded as identical when their
         substitution value is positive. The valid matrices
         names are in matrices.h (pam250mt) . Matrices not
         found in this header are considered to be
         filenames. See the format section for matrices. For
         instance, -weight=sim_pam250mt indicates that the
         grouping used for similarity will be the set of
         classes with positive substitutions. Other groups
         include

     sim_clustalw_col ( categories of clustalw
     marked with :)

     sim_clustalw_dot ( categories of clustalw
     marked with .)

     Value indicates that all the pairs found in the
     alignments must be given the same weight equal to
     value. This is useful when the alignment one wishes to
     turn into a library must be given a pre-specified score
     (for instance if they come from a structure
     super-imposition program). Value is an integer:

     -weight=1000

     Note       : Weight only affects methods that return an alignment to
                  T-Coffee, such as ClustalW. On the contrary, the
                  version of Lalign we use here returns a library where
                  weights have already been applied and are therefore
                  insensitive to the -weight flag.

SEQ_TO_ALIGN
------------

     Title       : SEQ_TO_ALIGN
     Args        : filename
     Default     : no file - align all the sequences

     Description : You may not wish to align all the sequences brought in
                   by the -in flag. Supplying the seq_to_align flag allows
                   for this, the file is simply a list of names in Fasta
                   format.

     However, note that library extension will be carried out
     on all the sequences.

PARAMETERS FOR TREE COMPUTATION AND OUTPUT
==========================================

NEWTREE
-------

     Title       : NEWTREE
     Args        : treefile
     Default     : no file
     Description : Indicates the name of the new tree to compute. The
                   default will be <sequence_name>.dnd, or <run_name.dnd>.
                   Format is Phylips tree format

USETREE
-------

     Title       : USETREE
     Args        : treefile
     Default     : no file specified
     Description : This flag indicates that rather than computing a new
                   dendrogram, t_coffee can use a pre-computed one. The
                   tree files are in phylips format and compatible with
                   ClustalW. In most cases, using a pre-computed tree will
                   halve the computation time required by t_coffee. It is
                   also possible to use trees output by ClustalW or
                   Phylips. Format is Phylips tree format

TREE_MODE
---------

     Title       : TREE_MODE
     Args        : slow, fast, very_fast
     Default     : very_fast
     Description : This flag indicates the method used for computing the
                   dendrogram.
                   slow : the chosen dp_mode using the extended library,
                   fast : The fasta dp_mode using the extended library.
                   very_fast: The fasta dp_mode using pam250mt.

QUICKTREE
---------

     Title       : QUICKTREE
     Args        :
     Default     :
     Description : This flag is kept for compatibility with ClustalW.
                   It indicates that:  -tree_mode=very_fast

PARAMETERS FOR ALIGNMENT OUTPUT
===============================

OUTFILE
-------

     Title       : OUTFILE
     Args        : out_aln file, default, no
     Default     : default ( yourseqfile.aln)
     Description : indicates name of output alignment file

OUTPUT
------

     Title       : OUTPUT
     Args        : format1, format2
     Default     : clustalw
     Description : Indicated format for outputting outputfile
                   Supported formats are:

     clustalw_aln, clustalw: ClustalW format.
     gcg, msf_aln : Msf alignment.
     pir_aln : pir alignment.
     fasta_aln : fasta alignment.
     phylip : Phylip format.
     pir_seq : pir sequences (no gap).
     fasta_seq : fasta sequences (no gap).
         As well as:
      score_html : causes the output to be a reliability
                   plot in HTML
      score_pdf : idem in PDF.
      score_ps : idem in postscript.

     More than one format can be indicated:
                 -output=clustalw,gcg, score_html

CASE
----

     Title       : CASE
     Args        : upper, lower
     Default     : upper
     Description : triggers choice of the case for output

CPU
---

     Title       : CPU
     Args        : value
     Default     : 0
     Description : Indicates the cpu time (micro seconds) that must be
                   added to the t_coffee computation time.

OUT_LIB
-------

     Title       : OUT_LIB
     Args        : name of library, default, no
     Default     : default
     Description : Sets the name of the library output. Default implies
                   <run_name>.tc_lib

OUTORDER
--------

     Title       : OUTORDER
     Args        : input or aligned
     Default     : input
     Description : Sets the name of the library output. Default implies
                   <run_name>.tc_lib

SEQNOS
------

     Title       : SEQNOS
     Args        : on or off
     Default     : off
     Description : Causes the output alignment to contain residue numbers
                   at the end of each line:

PARAMETERS FOR GENERIC OUTPUT
=============================

RUN_NAME
--------

     Title       : RUN_NAME
     Args        : your run name
     Default     :
     Description : This flag causes the prefix <your sequences> to be
                   replaced by <your run name> when renaming the default
                   files.

ALIGN
-----

     Title       : ALIGN
     Args        :
     Default     :
     Description : Indicates that the program must produce the
                   alignment. This flag is here for compatibility with
                   ClustalW

QUIET
-----

     Title       : QUIET
     Args        : stderr, stdout, or filename, or nothing
     Default     : stderr
     Description : Redirects the standard output to either a file.
                  -quiet on its own redirect the output to /dev/null.

CONVERT
-------

     Title       : CONVERT
     Args        :
     Default     :
     Description : Indicates that the program must not compute the
                   alignment but simply convert all the sequences,
                   alignments and libraries into the format indicated with
                   -output. This flag can also be used if you simply want
                   to compute a library ( i.e. You have an alignment and
                   you want to turn it into a library).

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via  email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR -  Jason Stajich, Peter Schattner
========================================

   Email jason@chg.mc.duke.edu, schattner@alum.mit.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

exists_tcoffee
--------------

     Title   : exists_tcoffee
     Usage   : $coffeefound = Bio::Tools::Run::Alignment::TCoffee->exists_tcoffee()
     Function: Determine whether tcoffee program can be found on current host
     Example :
     Returns : 1 if tcoffee program found at expected location, 0 otherwise.
     Args    :  none

align
-----

     Title   : align
     Usage   :
     	$inputfilename = 't/cysprot.fa';
     	$aln = $factory->align($inputfilename);
     or
     	$seq_array_ref = \@seq_array; @seq_array is array of Seq objs
     	$aln = $factory->align($seq_array_ref);
     Function: Perform a multiple sequence alignment
     Example :
     Returns : Reference to a SimpleAlign object containing the
               sequence alignment.
     Args    : Name of a file containing a set of unaligned fasta sequences
               or else an array of references to Bio::Seq objects.

     Throws an exception if argument is not either a string (eg a
     filename) or a reference to an array of Bio::Seq objects.  If
     argument is string, throws exception if file corresponding to string
     name can not be found. If argument is Bio::Seq array, throws
     exception if less than two sequence objects are in array.

profile_align
-------------

     Title   : profile_align
     Usage   :
     Function: Perform an alignment of 2 (sub)alignments
     Example :
     Returns : Reference to a SimpleAlign object containing the (super)alignment.
     Args    : Names of 2 files containing the subalignments
             or references to 2 Bio::SimpleAlign objects.

   Throws an exception if arguments are not either strings (eg filenames)
or references to SimpleAlign objects.

_run
----

     Title   :  _run
     Usage   :  Internal function, not to be called directly
     Function:  makes actual system call to tcoffee program
     Example :
     Returns : nothing; tcoffee output is written to a
               temporary file $TMPOUTFILE
     Args    : Name of a file containing a set of unaligned fasta sequences
               and hash of parameters to be passed to tcoffee

_setinput
---------

     Title   :  _setinput
     Usage   :  Internal function, not to be called directly
     Function:  Create input file for tcoffee program
     Example :
     Returns : name of file containing tcoffee data input
     Args    : Seq or Align object reference or input file name

_setparams
----------

     Title   :  _setparams
     Usage   :  Internal function, not to be called directly
     Function:  Create parameter inputs for tcoffee program
     Example :
     Returns : parameter string to be passed to tcoffee
               during align or profile_align
     Args    : name of calling object

Object for the local execution of the NCBI Blast program suite (blastall, blastpgp, bl2seq)
*******************************************************************************************

NAME
====

   Bio::Tools::Run::StandAloneBlast - Object for the local execution of the
NCBI Blast program suite (blastall, blastpgp, bl2seq)

SYNOPSIS
========

   Local-blast "factory object" creation and blast-parameter
initialization:

     @params = ('database' => 'swissprot','outfile' => 'blast1.out',
     	    '_READMETHOD' => 'Blast');

     $factory = Bio::Tools::Run::StandAloneBlast->new(@params);

   Blast a sequence against a database:

     $str = Bio::SeqIO->new(-file=>'t/amino.fa' , '-format' => 'Fasta' );
     $input = $str->next_seq();
     $input2 = $str->next_seq();
     $blast_report = $factory->blastall($input);

   Run an iterated Blast (psiblast) of a sequence against a database:

     $factory->j(3);    # 'j' is blast parameter for # of iterations
     $factory->outfile('psiblast1.out');
     $factory = Bio::Tools::Run::StandAloneBlast->new(@params);
     $blast_report = $factory->blastpgp($input);

   Use blast to align 2 sequences against each other:

     $factory = Bio::Tools::Run::StandAloneBlast->new('outfile' => 'bl2seq.out');
     $factory->bl2seq($input, $input2);

   Various additional options and input formats are available.  See the
DESCRIPTION section for details.

DESCRIPTION
===========

   This DESCRIPTION only documents Bio::Tools::Run::StandAloneBlast.pm: - a
Bioperl object for running the NCBI standAlone BLAST package.  Blast,
itself, is a large & complex program - for more information regarding
BLAST, please see the BLAST documentation which accompanies the BLAST
distribution. BLAST is available from ftp://ncbi.nlm.nih.gov/blast/.

   (A source of confusion in documenting a BLAST interface is that the
term "program" is used in - at least - three different ways in the BLAST
documentation.  In this DESCRIPTION, "program" will refer to the BLAST
routine set by BLAST's -p parameter that can be set to blastn, blastp,
tblastx etc.  We will use the term Blast "executable" to refer to the
various different executable files that may be called - ie blastall,
blastpgp or bl2seq.  In addition, there are several BLAST capabilities
(which are also referred to as "programs") and are implemented by using
specific combinations of BLAST executables, programs and parameters.  They
will be referred by their specific names - eg PSIBLAST and PHIBLAST. )

   StandAloneBlast.pm has been tested so far only under Linux. I expect
that it should also work under other Unix systems. However, since the
module is implemented using (unix) system calls, modification may be
necessary before StandAloneBlast.pm would work under non-Unix operating
systems (eg Windows, MacOS).  Before running StandAloneBlast.pm it is
necessary: to install BLAST on your system, to edit set the environmental
variable $BLASTDIR or your $PATH variable to point to the BLAST directory,
and to ensure that users have execute privilieges for the BLAST program.
If the databases which will be searched by BLAST are located in the data
subdirectory of the blast program directory (the default installation
location), StandAloneBlast.pm will find them; however, if the database
files are located in any other location, environmental variable
$BLASTDATADIR will need to be set to point to that directory.

   The use of the StandAloneBlast.pm module is as follows: Initially, a
local blast "factory object" is created. The constructor may be passed an
optional array of (non-default) parameters to be used by the factory, eg:

     @params = ('program' => 'blastn', 'database' => 'ecoli.nt');
     $factory = Bio::Tools::Run::StandAloneBlast->new(@params);

   Any parameters not explicitly set will remain as the defaults of the
BLAST executable.  Note each BLAST executable has somewhat different
parameters and options.  See the BLAST Documentation for a description or
run the BLAST executable from the command line followed solely with a "-"
to see a list of options and default values for that executable; eg
>blastall -.

   BLAST parameters can be changed and/or examined at any time after the
factory has been created.  The program checks that any parameter/switch
being set/read is valid.  Except where specifically noted, StandAloneBlast
uses the same single-letter, case-sensitive parameter names as the actual
blast program.  Currently no checks are included to verify that parameters
are of the proper type (eg string or numeric) or that their values are
within the proper range.

   As an example, to change the value of the Blast parameter 'e' ('e' is
the parameter for expectation-value cutoff)

     $expectvalue = 0.01;
     $factory->e($expectvalue);

   Note that for improved script readibility one can modify the name of
the BLAST parameters as desired as long as the initial letter (and case)
of the parameter are preserved, eg $factory->expectvalue($expectvalue);
Unfortunately, some of the BLAST parameters are not the single letter one
might expect (eg "iteration round" in blastpgp is 'j'). Again one can
check by using (eg)

     > blastpgp - .

   Once the factory has been created and the appropriate parameters set,
one can call one of the supported blast executables.  The input
sequence(s) to these executables may be fasta file(s) as described in  the
BLAST documentation.

     $inputfilename = 't/testquery.fa';
     $blast_report = $factory->blastall($inputfilename);

   In addition, sequence input may be in the form of either a Bio::Seq
object or or an array of Bio::Seq objects, eg

     $input = Bio::Seq->new(-id=>"test query",-seq=>"ACTACCCTTTAAATCAGTGGGGG");
     $blast_report = $factory->blastall($input);

   For blastall and non-psiblast blastpgp runs, report object is either a
BPlite.pm or Blast.pm object, selected by the user with the parameter
_READMETHOD.  (The leading underscore is needed to distinguish this option
from options which are passed to the BLAST executable.) The default parser
is BPlite.  For (multiple iteration) psiblast and bl2seq runs the report
is automatically parsed by the BPpsilite.pm and BPbl2seq.pm parsers
respectively, since neither Blast.pm nor BPlite can parse these reports.
In any case, the "raw" blast report is also available. The filename is set
by the in the 'outfile' parameter and has the default value of
"blastreport.out".

   When using the Blast.pm parser, only a default configuration is
currently supported:

     -signif => $self->e()  || 1e-5, # where $self->e(), if set, is the BLAST cutoff value
     	-parse  => 1,
     	-stats  => 1,
     	-check_all_hits => 1,

   If it is desired to parse the resulting report with Blast.pm with other
values, the user can save the report in the file given by
$factory->outfile('outputfilelocation') and then reading that file with
Blast.pm using any parameters desired.

   For psiblast execution in BLAST's "jumpstart" mode, the program must be
passed (in addition to the query sequence itself) an alignment containing
the query sequence (in the form of a SimpleAlign object) as well as a
"mask" specifying at what residues position-specific scoring matrices
(PSSMs) are to used and at what residues default scoring matrices (eg
BLOSUM) are to be used. See psiblast documentation for more details.  The
mask itself is a string of 0's and 1's which is the same length as each
sequence in the alignment and has a "1" at locations where (PSSMs) are to
be used and a "0" at all other locations. So for example:

     $str = Bio::AlignIO->new(-file=> "cysprot.msf", '-format' => 'msf'  );
     $aln = $str->next_aln();
     $len = $aln->length_aln();
     $mask =   '1' x $len;  # simple case where PSSM's to be used at all residues
     $report = $factory->blastpgp("cysprot1.fa", $aln, $mask);

   For bl2seq execution, StandAloneBlast.pm can be combined with
AlignIO.pm to directly produce a SimpleAlign object from the alignment of
the two sequences produced by bl2seq as in:

     #Get 2 sequences
     $str = Bio::SeqIO->new(-file=>'t/amino.fa' , '-format' => 'Fasta', );
     my $seq3 = $str->next_seq();
     my $seq4 = $str->next_seq();

     # Run bl2seq on them
     $factory = Bio::Tools::Run::StandAloneBlast->new('outfile' => 'bl2seq.out');
     my $bl2seq_report = $factory->bl2seq($seq3, $seq4);

     # Use AlignIO.pm to create a SimpleAlign object from the bl2seq report
     $str = Bio::AlignIO->new(-file=> 'bl2seq.out','-format' => 'bl2seq');
     $aln = $str->next_aln();

   For more examples of syntax and use of Blast.pm, the user is encouraged
to run the scripts standaloneblast.pl in the bioperl /examples directory
and StandAloneBlast.t in the bioperl /t directory.

   Note: There is a similar (but older) perl object interface offered by
nhgri. The nhgri module only supports blastall and does not support
blastpgp, psiblast, phiblast, bl2seq etc.  This module can be found at
http://genome.nhgri.nih.gov/blastall/.

DEVELOPERS NOTES
================

   *STILL TO BE WRITTEN*

   Note: This module is still under development.  If you would like that a
specific BLAST feature be added to this perl interface, let me know.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org               - General discussion
     http://bio.perl.org/MailList.html   - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR -  Peter Schattner
=========================

   Email schattner@alum.mit.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

BLAST parameters
================

   Essentially all BLAST parameter can be set via StandAloneBlast.pm.
Some of the most commonly used parameters are listed below.  All
parameters have defaults and are optional (I think.)  For a complete
listing of settable parameters, run the relevant executable BLAST program
with the option "-" as in blastall -

Blastall
--------

     -p  Program Name [String]
           Input should be one of "blastp", "blastn", "blastx",
           "tblastn", or "tblastx".
     -d  Database [String] default = nr
           The database specified must first be formatted with formatdb.
           Multiple database names (bracketed by quotations) will be accepted.
           An example would be -d "nr est"
     -i  Query File [File In]   Set by StandAloneBlast.pm from script.
       default = stdin. The query should be in FASTA format.  If multiple FASTA entries are in the input
           file, all queries will be searched.
     -e  Expectation value (E) [Real] default = 10.0
     -o  BLAST report Output File [File Out]  Optional,
     	default = ./blastreport.out ; set by StandAloneBlast.pm
     -S  Query strands to search against database (for blast[nx], and tblastx).  3 is both, 1 is top, 2 is bottom [Integer]
     	default = 3

Blastpgp (including Psiblast)
-----------------------------

     -j   is the maximum number of rounds (default 1; i.e., regular BLAST)
     -h   is the e-value threshold for including sequences in the
     	score matrix model (default 0.001)
     -c   is the "constant" used in the pseudocount formula specified in the paper (default 10)
     -B  Multiple alignment file for PSI-BLAST "jump start mode"  Optional
     -Q  Output File for PSI-BLAST Matrix in ASCII [File Out]  Optional

Bl2seq
------

     -i  First sequence [File In]
     -j  Second sequence [File In]
     -p  Program name: blastp, blastn, blastx. For blastx 1st argument should be nucleotide [String]
       default = blastp
     -o  alignment output file [File Out] default = stdout
     -e  Expectation value (E) [Real]  default = 10.0
     -S  Query strands to search against database (blastn only).  3 is both, 1 is top, 2 is bottom [Integer]
       default = 3

Methods
=======

exists_blast
------------

     Title   : exists_blast
     Usage   : $blastfound = Bio::Tools::Run::StandAloneBlast->exists_blast()
     Function: Determine whether Blast program can be found on current host
     Returns : 1 if Blast program found at expected location, 0 otherwise.
     Args    :  none

blastall
--------

     Title   : blastall
     Usage   :  $blast_report = $factory->blastall('t/testquery.fa');
     	or
     	       $input = Bio::Seq->new(-id=>"test query",
     				      -seq=>"ACTACCCTTTAAATCAGTGGGGG");
     	       $blast_report = $factory->blastall($input);
     	or
     	      $seq_array_ref = \@seq_array;  # where @seq_array is an array of Bio::Seq objects
     	      $blast_report = $factory->blastall(\@seq_array);
     Returns :  Reference to a Blast object or BPlite object
               containing the blast report.
     Args    : Name of a file or Bio::Seq object or an array of
               Bio::Seq object containing the query sequence(s).
               Throws an exception if argument is not either a string
               (eg a filename) or a reference to a Bio::Seq object
               (or to an array of Seq objects).  If argument is string,
               throws exception if file corresponding to string name can
               not be found.

blastpgp
--------

     Title   : blastpgp
     Usage   :  $blast_report = $factory-> blastpgp('t/testquery.fa');
     	or
     	       $input = Bio::Seq->new(-id=>"test query",
     				      -seq=>"ACTADDEEQQPPTCADEEQQQVVGG");
     	       $blast_report = $factory->blastpgp ($input);
     	or
     	      $seq_array_ref = \@seq_array;  # where @seq_array is an array of Bio::Seq objects
     	      $blast_report = $factory-> blastpgp(\@seq_array);
     Returns : Reference to a Blast object or BPlite object containing
               the blast report.
     Args    : Name of a file or Bio::Seq object. In psiblast jumpstart
               mode two additional arguments are required: a SimpleAlign
               object one of whose elements is the query and a "mask" to
               determine how BLAST should select scoring matrices see
               DESCRIPTION above for more details.

     Throws an exception if argument is not either a string
     (eg a filename) or a reference to a Bio::Seq object
     (or to an array of Seq objects).  If argument is string,
     throws exception if file corresponding to string name can
     not be found.
      Returns : Reference to either a BPlite.pm, Blast.pm or BPpsilite.pm
     object containing the blast report.

bl2seq
------

     Title   : bl2seq
     Usage   : $factory-> blastpgp('t/seq1.fa', 't/seq2.fa');
     	or
     	  $input1 = Bio::Seq->new(-id=>"test query1",
     				  -seq=>"ACTADDEEQQPPTCADEEQQQVVGG");
     	  $input2 = Bio::Seq->new(-id=>"test query2",
     				  -seq=>"ACTADDEMMMMMMMDEEQQQVVGG");
     	  $blast_report = $factory->bl2seq ($input1,  $input2);
     Returns : Reference to a BPbl2seq object containing the blast report.
     Args    : Names of 2 files  or 2 Bio::Seq objects containing the
               sequences to be aligned by bl2seq.

     Throws an exception if argument is not either a pair of
     strings (eg filenames) or  references to Bio::Seq objects.
     If arguments are strings, throws exception if files
     corresponding to string names can not be found.

_generic_local_blast
--------------------

     Title   : _generic_local_blast
     Usage   :  internal function not called directly
     Returns :  Blast or BPlite object
     Args    :   Reference to calling object and name of BLAST executable

_runblast
---------

     Title   :  _runblast
     Usage   :  Internal function, not to be called directly
     Function:   makes actual system call to Blast program
     Example :
     Returns : Report object in the appropriate format (BPlite,
               BPpsilite, Blast, or BPbl2seq)
     Args    : Reference to calling object, name of BLAST executable,
               and parameter string for executable

_setinput
---------

     Title   :  _setinput
     Usage   :  Internal function, not to be called directly
     Function:   Create input file(s) for Blast executable
     Example :
     Returns : name of file containing Blast data input
     Args    : Seq object reference or input file name

_setparams
----------

     Title   : _setparams
     Usage   : Internal function, not to be called directly
     Function: Create parameter inputs for Blast program
     Example :
     Returns : parameter string to be passed to Blast
     Args    : Reference to calling object and name of BLAST executable

Bioperl sequence analysis base class.
*************************************

NAME
====

   Bio::Tools::SeqAnal.pm - Bioperl sequence analysis base class.

SYNOPSIS
========

Object Creation
---------------

   This module is an abstract base class. Perl will let you instantiate it,
but it provides little functionality on its own. This module should be
used via a specialized subclass. See `_initialize' in this node() for a
description of constructor parameters.

     require Bio::Tools::SeqAnal;

   To run and parse a new report:

     $hit = new Bio::Tools::SeqAnal ( -run   => \%runParams,
     				     -parse => 1);

   To parse an existing report:

     $hit = new Bio::Tools::SeqAnal ( -file  => 'filename.data',
     				     -parse => 1);

   To run a report without parsing:

     $hit = new Bio::Tools::SeqAnal ( -run   => \%runParams
     				     );

   To read an existing report without parsing:

     $hit = new Bio::Tools::SeqAnal ( -file  => 'filename.data',
     				     -read  => 1);

INSTALLATION
============

   This module is included with the central Bioperl distribution:

     http://bio.perl.org/Core/Latest
     ftp://bio.perl.org/pub/DIST

   Follow the installation instructions included in the README file.

DESCRIPTION
===========

   Bio::Tools::SeqAnal.pm is a base class for specialized sequence
analysis modules such as Bio::Tools::Blast.pm and *Bio::Tools::Fasta.pm*.
It provides some basic data and functionalities that are not unique to a
specialized module such as:

   * reading raw data into memory.

   * storing name and version of the program.

   * storing name of the query sequence.

   * storing name and version of the database.

   * storing & determining the date on which the analysis was performed.

   * basic file manipulations (compress, uncompress, delete).

   Some of these functionalities (reading, file maipulation) are inherited
from *Bio::Root::Object.pm*, from which Bio::Tools::SeqAnal.pm derives.

RUN, PARSE, and READ
====================

   A SeqAnal.pm object can be created using one of three modes: run,
parse, or read.

     MODE      DESCRIPTION
     -----     -----------
     run       Run a new sequence analysis report. New results can then
               be parsed or saved for analysis later.

     parse     Parse the data from a sequence analysis report loading it
               into the SeqAnal.pm object.

     read      Read in data from an existing raw analysis report without
               parsing it. In the future, this may also permit persistent
               SeqAnal.pm objects. This mode is considered experimental.

   The mode is set by supplying switches to the constructor, see
`_initialize' in this node().

   A key feature of SeqAnal.pm is the ability to access raw data in a
generic fashion. Regardless of what sequence analysis method is used, the
raw data always need to be read into memory.  The SeqAnal.pm class
utilizes the `read' in this node() method inherited from
*Bio::Root::Object.pm* to permit the following:

   * read from a file or STDIN.

   * read a single record or a stream containing multiple records.

   * specify a record separator.

   * store all input data in memory or process the data stream as it is
     being read.

   By permitting the parsing of data as it is being read, each record can
be analyzed as it is being read and saved or discarded as necessary.  This
can be useful when cruching through thousands of reports.  For examples of
this, see the `parse' in this node() methods defined in
Bio::Tools::Blast.pm and *Bio::Tools::Fasta.pm*.

Parsing & Running
-----------------

   Parsing and running of sequence analysis reports must be implemented
for each specific subclass of SeqAnal.pm. No-op stubs ("virtual methods")
are provided here for the `parse' in this node() and `run' in this node()
methods. See Bio::Tools::Blast.pm and *Bio::Tools::Fasta.pm* for examples.

DEPENDENCIES
============

   Bio::Tools::SeqAnal.pm is a concrete class that inherits from
*Bio::Root::Object.pm*.  This module also makes use of a number of
functionalities inherited from *Bio::Root::Object.pm* (file manipulations
such as reading, compressing, decompressing, deleting, and obtaining date.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules.  Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR
======

   Steve A. Chervitz, sac@genome.stanford.edu

   See the `FEEDBACK' in this node section for where to send bug reports
and comments.

VERSION
=======

   Bio::Tools::SeqAnal.pm, 0.011

COPYRIGHT
=========

   Copyright (c) 1998 Steve A. Chervitz. All Rights Reserved.  This module
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

     http://bio.perl.org/Projects/modules.html  - Online module documentation
     http://bio.perl.org/Projects/Blast/        - Bioperl Blast Project
     http://bio.perl.org/                       - Bioperl Project Homepage

APPENDIX
========

   Methods beginning with a leading underscore are considered private and
are intended for internal use by this module. They are not considered part
of the public interface and are described here for documentation purposes
only.

_initialize
-----------

     Usage     : n/a; automatically called by Bio::Root::Object::new()
     Purpose   : Calls private methods to extract the raw report data,
               : Calls superclass constructor first (Bio::Root::Object.pm).
     Returns   : string containing the make parameter value.
     Argument  : Named parameters (TAGS CAN BE ALL UPPER OR ALL LOWER CASE).
               : The SeqAnal.pm constructor only processes the following
               : parameters passed from new()
               :     -RUN     => hash reference for named parameters to be used
               :                 for running a sequence analysis program.
               :                 These are dereferenced and passed to the run() method.
     	   :     -PARSE   => boolean,
     	   :     -READ    => boolean,
               :
               : If -RUN is HASH ref, the run() method will be called with the
               :   dereferenced hash.
               : If -PARSE is true, all parameters passed from new() are passed
               :   to the parse() method. This occurs after the run method call
               :   to enable combined running + parsing.
               : If -READ is true, all parameters passed from new() are passed
               :   to the read() method.
               : Either -PARSE or -READ should be true, not both.
     Comments  : Does not calls _rearrange() to handle parameters since only
               : a few are required and there may be potentially many.

   See Also   : *Bio::Root::Object::new()*,
*Bio::Root::Object::_rearrange()*

best
----

     Usage     : $object->best();
     Purpose   : Set/Get the indicator for processing only the best match.
     Returns   : Boolean (1 | 0)
     Argument  : n/a

_set_db_stats
-------------

     Usage     : $object->_set_db_stats(<named parameters>);
     Purpose   : Set stats about the database searched.
     Returns   : String
     Argument  : named parameters:
               :   -LETTERS => <int>  (number of letters in db)
               :   -SEQS    => <int>  (number of sequences in db)

database
--------

     Usage     : $object->database();
     Purpose   : Set/Get the name of the database searched.
     Returns   : String
     Argument  : n/a

database_release
----------------

     Usage     : $object->database_release();
     Purpose   : Set/Get the release date of the queried database.
     Returns   : String
     Argument  : n/a

database_letters
----------------

     Usage     : $object->database_letters();
     Purpose   : Set/Get the number of letters in the queried database.
     Returns   : Integer
     Argument  : n/a

database_seqs
-------------

     Usage     : $object->database_seqs();
     Purpose   : Set/Get the number of sequences in the queried database.
     Returns   : Integer
     Argument  : n/a

set_date
--------

     Usage     : $object->set_date([<string>]);
     Purpose   : Set the name of the date on which the analysis was performed.
     Argument  : The optional string argument ca be the date or the
               : string 'file' in which case the date will be obtained from
               : the report file
     Returns   : String
     Throws    : Exception if no date is supplied and no file exists.
     Comments  : This method attempts to set the date in either of two ways:
               :   1) using data passed in as an argument,
               :   2) using the Bio::Root::Utilities.pm file_date() method
               :      on the output file.
               : Another way is to extract the date from the contents of the
               : raw output data. Such parsing will have to be specialized
               : for different seq analysis reports. Override this method
               : to create such custom parsing code if desired.

   See Also   : `date' in this node(), *Bio::Root::Object::file_date()*

date
----

     Usage     : $object->date();
     Purpose   : Get the name of the date on which the analysis was performed.
     Returns   : String
     Argument  : n/a
     Comments  : This method is not a combination set/get, it only gets.

   See Also   : `set_date' in this node()

length
------

     Usage     : $object->length();
     Purpose   : Set/Get the length of the query sequence (number of monomers).
     Returns   : Integer
     Argument  : n/a
     Comments  : Developer note: when using the built-in length function within
               : this module, call it as CORE::length().

program
-------

     Usage     : $object->program();
     Purpose   : Set/Get the name of the sequence analysis (BLASTP, FASTA, etc.)
     Returns   : String
     Argument  : n/a

program_version
---------------

     Usage     : $object->program_version();
     Purpose   : Set/Get the version number of the sequence analysis program.
               : (e.g., 1.4.9MP, 2.0a19MP-WashU).
     Returns   : String
     Argument  : n/a

query
-----

     Usage     : $name = $object->query();
     Purpose   : Get the name of the query sequence used to generate the report.
     Argument  : n/a
     Returns   : String
     Comments  : Equivalent to $object->name().

query_desc
----------

     Usage     : $object->desc();
     Purpose   : Set/Get the description of the query sequence for the analysis.
     Returns   : String
     Argument  : n/a

display
-------

     Usage     : $object->display(<named parameters>);
     Purpose   : Display information about Bio::Tools::SeqAnal.pm data members.
               : Overrides Bio::Root::Object::display().
     Example   : $object->display(-SHOW=>'stats');
     Argument  : Named parameters: -SHOW  => 'file' | 'stats'
               :                   -WHERE => filehandle (default = STDOUT)
     Returns   : n/a
     Status    : Experimental

   See Also   : `_display_stats' in this node(), `_display_file' in this
node(), *Bio::Root::Object::display*

_display_file
-------------

     Usage     : n/a; called automatically by display()
     Purpose   : Print the contents of the raw report file.
     Example   : n/a
     Argument  : one argument = filehandle object.
     Returns   : true (1)
     Status    : Experimental

   See Also   : `display' in this node()

_display_stats
--------------

     Usage     : n/a; called automatically by display()
     Purpose   : Display information about Bio::Tools::SeqAnal.pm data members.
               : Prints the file name, program, program version, database name,
               : database version, query name, query length,
     Example   : n/a
     Argument  : one argument = filehandle object.
     Returns   : printf call.
     Status    : Experimental

   See Also   : *Bio::Root::Object.pm*::display()

VIRTUAL METHODS
===============

parse
-----

     Usage     : $object->parse( %named_parameters )
     Purpose   : Parse a raw sequence analysis report.
     Returns   : Integer (number of sequence analysis reports parsed).
     Argument  : Named parameters.
     Throws    : Exception: virtual method not defined.
               : Propagates any exception thrown by read()
     Status    : Virtual
     Comments  : This is virtual method that should be overridden to
               : parse a specific type of data.

   See Also   : *Bio::Root::Object::read()*

run
---

     Usage     : $object->run( %named_parameters )
     Purpose   : Run a sequence analysis program on one or more sequences.
     Returns   : n/a
               : Run mode should be configurable to return a parsed object or
               : the raw results data.
     Argument  : Named parameters:
     Throws    : Exception: virtual method not defined.
     Status    : Virtual

FOR DEVELOPERS ONLY
===================

Data Members
------------

   Information about the various data members of this module is provided
for those wishing to modify or understand the code. Two things to bear in
mind:

  1. Do NOT rely on these in any code outside of this module.  All data
     members are prefixed with an underscore to signify that they are
     private.  Always use accessor methods. If the accessor doesn't exist
     or is inadequate, create or modify an accessor (and let me know,
     too!).

  2. This documentation may be incomplete and out of date.  It is easy for
     these data member descriptions to become obsolete as this module is
     still evolving. Always double check this info and search for members
     not described here.

        An instance of Bio::Tools::SeqAnal.pm is a blessed reference to a
hash containing all or some of the following fields:

     FIELD           VALUE
     --------------------------------------------------------------
      _file            Full path to file containing raw sequence analysis report.

     _mode            Affects how much detail to extract from the raw report.
      		   Future mode will also distinguish 'running' from 'parsing'

     THE FOLLOWING MAY BE EXTRACTABLE FROM THE RAW REPORT FILE:

     _prog            Name of the sequence analysis program.

     _progVersion     Version number of the program.

     _db              Database searched.

     _dbRelease       Version or date of the database searched.

     _dbLetters       Total number of letters in the database.

     _dbSequences     Total number of sequences in the database.

     _query           Name of query sequence.

     _length          Length of the query sequence.

     _date            Date on which the analysis was performed.

     INHERITED DATA MEMBERS

     _name            From Bio::Root::Object.pm. String representing the name of the query sequence.
      		   Typically obtained from the report file.

     _parent          From Bio::Root::Object.pm. This member contains a reference to the
      		   object to which this seq anal report belongs. Optional & experimenta.
                      (E.g., a protein object could create and own a Blast object.)

Bioperl object for a sequence pattern or motif
**********************************************

NAME
====

   Bio::Tools::SeqPattern.pm - Bioperl object for a sequence pattern or
motif

SYNOPSIS
========

Object Creation
---------------

     use Bio::Tools::SeqPattern ();

     $pat1     = 'T[GA]AA...TAAT';
     $pattern1 = new Bio::Tools::SeqPattern(-SEQ =>$pattern, -TYPE =>'Dna');

     $pat2     = '[VILM]R(GXX){3,2}...[^PG]';
     $pattern2 = new Bio::Tools::SeqPattern(-SEQ =>$pattern, -TYPE =>'Amino');

INSTALLATION
============

   This module is included with the central Bioperl distribution:

     http://bio.perl.org/Core/Latest
     ftp://bio.perl.org/pub/DIST

   Follow the installation instructions included in the README file.

DESCRIPTION
===========

   The Bio::Tools::SeqPattern.pm module encapsulates generic data and
methods for manipulating regular expressions describing nucleic or amino
acid sequence patterns (a.k.a, "motifs").

   Bio::Tools::SeqPattern.pm is a concrete class that inherits from
*Bio::Seq.pm*.

   This class grew out of a need to have a standard module for doing
routine tasks with sequence patterns such as:

     -- Forming a reverse-complement version of a nucleotide sequence pattern
     -- Expanding patterns containing ambiguity codes
     -- Checking for invalid regexp characters
     -- Untainting yet preserving special characters in the pattern

   Other features to look for in the future:

   - Full pattern syntax checking   - Conversion between expanded and
ondensed forms of the pattern

MOTIVATIONS
===========

   A key motivation for Bio::Tools::SeqPattern.pm is to have a way to
generate a reverse complement of a nucleotide sequence pattern.  This
makes possible simultaneous pattern matching on both sense and anti-sense
strands of a query sequence.

   In principle, one could do such a search more inefficiently by testing
ainst both sense and anti-sense versions of a sequence.  It is entirely
equivalent to test a regexp containing both sense and anti-sense versions
of the *pattern* against one copy of the sequence.  The latter approach is
much more efficient since:

   1) You need only one copy of the sequence.     2) Only one regexp is
executed.     3) Regexp patterns are typically much smaller than sequences.

   Patterns can be quite complex and it is often difficult to generate the
reverse complement pattern. The Bioperl SeqPattern.pm addresses this
problem, providing a convenient set of tools for working with biological
sequence regular expressions.

   Not all patterns have been tested. If you discover a pattern that is
not handled properly by Bio::Tools::SeqPattern.pm, please send me some
email (sac@genome.stanford.edu). Thanks.

OTHER FEATURES
==============

Extended Alphabet Support
-------------------------

   This module supports the same set of ambiguity codes for nucleotide
sequences as supported by *Bio::Seq.pm*. These ambiguity codes define the
behavior or the expand() method.  Amino acid alphabet support is different
from that of Seq.pm (see below).

     ------------------------------------------
     Symbol       Meaning      Nucleic Acid
     ------------------------------------------
      A            A           Adenine
      C            C           Cytosine
      G            G           Guanine
      T            T           Thymine
      U            U           Uracil
      M          A or C
      R          A or G        Any purine
      W          A or T
      S          C or G
      Y          C or T        Any pyrimidine
      K          G or T
      V        A or C or G
      H        A or C or T
      D        A or G or T
      B        C or G or T
      X      G or A or T or C
      N      G or A or T or C
      .      G or A or T or C

     ------------------------------------------
     Symbol           Meaning
     ------------------------------------------
     A        Alanine
     C        Cysteine
     D        Aspartic Acid
     E        Glutamic Acid
     F        Phenylalanine
     G        Glycine
     H        Histidine
     I        Isoleucine
     K        Lysine
     L        Leucine
     M        Methionine
     N        Asparagine
     P        Proline
     Q        Glutamine
     R        Arginine
     S        Serine
     T        Threonine
     V        Valine
     W        Tryptophan
     Y        Tyrosine

     B        Any hydrophobic: IFVLWMAGCY
     Z        Any hydrophilic: TSHEDQNKR
     X        Any amino acid
     .        Any amino acid

Multiple Format Support
-----------------------

   Ultimately, this module should be able to build SeqPattern.pm objects
objects using a variety of pattern formats such as ProSite, Blocks,
Prints, GCG, etc.  Currently, this module only supports patterns using a
grep-like syntax.

USAGE
=====

   A simple demo script is included with the central Bioperl distribution
(`INSTALLATION' in this node) and is also available from:

     http://bio.perl.org/Core/Examples/seq_pattern.pl

SEE ALSO
========

     Bio::Root::Object.pm    - Base class.
     Bio::Seq.pm             - Lightweight sequence object.

     http://bio.perl.org/Projects/modules.html  - Online module documentation
     http://bio.perl.org/                       - Bioperl Project Homepage

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules.  Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org              - General discussion
     http://bio.perl.org/MailList.html  - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR
======

   Steve A. Chervitz, sac@genome.stanford.edu

   See the `FEEDBACK' in this node section for where to send bug reports
and comments.

VERSION
=======

   Bio::Tools::SeqPattern.pm, 0.011

COPYRIGHT
=========

   Copyright (c) 1997-8 Steve A. Chervitz. All Rights Reserved.  This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

new
===

     Title     : new
     Usage     : my $seqpat = new Bio::Tools::SeqPattern();
     Purpose   : Verifies that the type is correct for superclass (Bio::Seq.pm)
               : and calls superclass constructor last.
     Returns   : n/a
     Argument  : Parameters passed to new()
     Throws    : Exception if the pattern string (seq) is empty.
     Comments  : The process of creating a new SeqPattern.pm object
               : ensures that the pattern string is untained.

   See Also   : `_untaint_pat' in this node(), *Bio::Root::RootI::new()*,
           *Bio::Seq::_initialize()*

alphabet_ok
===========

     Title     : alphabet_ok
     Usage     : $mypat->alphabet_ok;
     Purpose   : Checks for invalid regexp characters.
               : Overrides Bio::Seq::alphabet_ok() to allow
               : additional regexp characters ,.*()[]<>{}^$
               : in addition to the standard genetic alphabet.
               : Also untaints the pattern and sets the sequence
               : object's sequence to the untained string.
     Returns   : Boolean (1 | 0)
     Argument  : n/a
     Throws    : Exception if the pattern contains invalid characters.
     Comments  : Does not call the superclass method.
               : Actaully permits any alphanumeric, not just the
               : standard genetic alphabet.

   See Also   : *Bio::Seq::alphabet_ok()*, `_initialize' in this node()

expand
======

     Title     : expand
     Usage     : $seqpat_object->expand();
     Purpose   : Expands the sequence pattern using special ambiguity codes.
     Example   : $pat = $seq_pat->expand();
     Returns   : String containing fully expanded sequence pattern
     Argument  : n/a
     Throws    : Exception if sequence type is not recognized
               : (i.e., is not one of [DR]NA, Amino)

   See Also   : Extended Alphabet Support, `_expand_pep' in this node(),
`_exapand_nuc' in this node()

_expand_pep
===========

     Title     : _expand_pep
     Usage     : n/a; automatically called by expand()
     Purpose   : Expands peptide patterns
     Returns   : String (the expanded pattern)
     Argument  : String (the unexpanded pattern)
     Throws    : n/a

   See Also   : `expand' in this node(), `_expand_nuc' in this node()

_expand_nuc
===========

     Title     : _expand_nuc
     Purpose   : Expands nucleotide patterns
     Returns   : String (the expanded pattern)
     Argument  : String (the unexpanded pattern)
     Throws    : n/a

   See Also   : `expand' in this node(), `_expand_pep' in this node()

revcom
======

     Title     : revcom
     Usage     : revcom([1]);
     Purpose   : Forms a pattern capable of recognizing the reverse complement
               : version of a nucleotide sequence pattern.
     Example   : $pattern_object->revcom();
               : $pattern_object->revcom(1); ## returns expanded rev complement pattern.
     Returns   : Object reference for a new Bio::Tools::SeqPattern containing
               : the revcom of the current pattern as its sequence.
     Argument  : (1) boolean (optional) (default= false)
               :     true : expand the pattern before rev-complementing.
               :     false: don't expand pattern before or after rev-complementing.
     Throws    : Exception if called for amino acid sequence pattern.
     Comments  : This method permits the simultaneous searching of both
               : sense and anti-sense versions of a nucleotide pattern
               : by means of a grep-type of functionality in which any
               : number of patterns may be or-ed into the recognition
               : pattern.
               : Overrides Bio::Seq::revcom() and calls it first thing.
               : The order of _fixpat() calls is critical.

   See Also   : *Bio::Seq::revcom()*, `_fixpat_1' in this node(),
`_fixpat_2' in this node(), `_fixpat_3' in this node(), `_fixpat_4' in
this node(), `_fixpat_5' in this node()

_fixpat_1
=========

     Title     : _fixpat_1
     Usage     : n/a; called automatically by revcom()
     Purpose   : Utility method for revcom()
               : Converts all {7,5} --> {5,7}     (Part I)
               :           and [T^] --> [^T]      (Part II)
               :           and *N   --> N*        (Part III)
     Returns   : String (the new, partially reversed pattern)
     Argument  : String (the expanded pattern)
     Throws    : n/a

   See Also   : `revcom' in this node()

_fixpat_2
=========

     Title     : _fixpat_2
     Usage     : n/a; called automatically by revcom()
     Purpose   : Utility method for revcom()
               : Converts all {5,7}Y ---> Y{5,7}
               :          and {10,}. ---> .{10,}
     Returns   : String (the new, partially reversed pattern)
     Argument  : String (the expanded, partially reversed pattern)
     Throws    : n/a

   See Also   : `revcom' in this node()

_fixpat_3
=========

     Title     : _fixpat_3
     Usage     : n/a; called automatically by revcom()
     Purpose   : Utility method for revcom()
               : Converts all {5,7}(XXX) ---> (XXX){5,7}
     Returns   : String (the new, partially reversed pattern)
     Argument  : String (the expanded, partially reversed pattern)
     Throws    : n/a

   See Also   : `revcom' in this node()

_fixpat_4
=========

     Title     : _fixpat_4
     Usage     : n/a; called automatically by revcom()
     Purpose   : Utility method for revcom()
               : Converts all {5,7}[XXX] ---> [XXX]{5,7}
     Returns   : String (the new, partially reversed pattern)
     Argument  : String (the expanded, partially reversed  pattern)
     Throws    : n/a

   See Also   : `revcom' in this node()

_fixpat_5
=========

     Title     : _fixpat_5
     Usage     : n/a; called automatically by revcom()
     Purpose   : Utility method for revcom()
               : Converts all *[XXX]  ---> [XXX]*
               :          and *(XXX)  ---> (XXX)*
     Returns   : String (the new, partially reversed pattern)
     Argument  : String (the expanded, partially reversed pattern)
     Throws    : n/a

   See Also   : `revcom' in this node()

_fixpat_6
=========

     Title     : _fixpat_6
     Usage     : n/a; called automatically by revcom()
     Purpose   : Utility method for revcom()
               : Converts all ?Y{5,7}  ---> Y{5,7}?
               :          and ?(XXX){5,7}  ---> (XXX){5,7}?
               :          and ?[XYZ]{5,7}  ---> [XYZ]{5,7}?
     Returns   : String (the new, partially reversed pattern)
     Argument  : String (the expanded, partially reversed pattern)
     Throws    : n/a

   See Also   : `revcom' in this node()

str
---

     Title   : str
     Usage   : $obj->str($newval)
     Function:
     Returns : value of str
     Args    : newvalue (optional)

type
----

     Title   : type
     Usage   : $obj->type($newval)
     Function:
     Returns : value of type
     Args    : newvalue (optional)

FOR DEVELOPERS ONLY
===================

Data Members
------------

   Information about the various data members of this module is provided
for those wishing to modify or understand the code. Two things to bear in
mind:

  1. Do NOT rely on these in any code outside of this module.  All data
     members are prefixed with an underscore to signify that they are
     private.  Always use accessor methods. If the accessor doesn't exist
     or is inadequate, create or modify an accessor (and let me know,
     too!).

  2. This documentation may be incomplete and out of date.  It is easy for
     this documentation to become obsolete as this module is still
     evolving.  Always double check this info and search for members not
     described here.

        An instance of Bio::Tools::RestrictionEnzyme.pm is a blessed
reference to a hash containing all or some of the following fields:

     FIELD          VALUE
     ------------------------------------------------------------------------
     _rev     : The corrected reverse complement of the fully expanded pattern.

     INHERITED DATA MEMBERS:

     _seq     : (From Bio::Seq.pm) The original, unexpanded input sequence after untainting.
     _type    : (From Bio::Seq.pm) 'Dna' or 'Amino'

Object holding statistics for one particular sequence
*****************************************************

NAME
====

   Bio::Tools::SeqStats - Object holding statistics for one particular
sequence

SYNOPSIS
========

     # build a primary nucleic acid or protein sequence object somehow
     # then build a statistics object from the sequence object

     $seqobj = Bio::PrimarySeq->new(-seq=>'ACTGTGGCGTCAACTG',
     			       -moltype = 'dna', -id = 'test');
     $seq_stats  =  Bio::Tools::SeqStats->new(-seq=>$seqobj);

     # obtain a hash of counts of each type of monomer
     # (ie amino or nucleic acid)

        $hash_ref = $seq_stats->count_monomers();  # eg for DNA sequence
        foreach $base ( sort keys $$hash_ref) {
     	    print "Number of bases of type ",$base "= ",%$hash_ref{$base}"\n";
     	  }
         # or obtain the count directly without creating a new statistics object
     	$hash_ref = Bio::Tools::SeqStats->count_monomers($seqobj);
     	foreach $base ( sort keys $$hash_ref) {
     	    print "Number of bases of type ",$base "= ",%$hash_ref{$base}"\n";
     	}

     # obtain hash of counts of each type of codon in a nucleic acid sequence
     	$hash_ref = $seq_stats-> count_codons();  # for nucleic acid sequence
     #  or
     	$hash_ref = Bio::Tools::SeqStats->count_codons($seqobj);

   # Obtain the molecular weight of a sequence. Since the sequence may
contain # ambiguous monomers, the molecular weight is returned as a
(reference to) a # two element array containing greatest lower bound (GLB)
and least upper bound # (LUB) of the molecular weight

     $weight = $seq_stats->get_mol_wt();
         #  or
     	$weight = Bio::Tools::SeqStats->get_mol_wt($seqobj);
     	print "Molecular weight of sequence ", $seqobj->id(),
            " is greater than ", $$weight[0], " and less than " ,
            $$weight[1], "\n";

DESCRIPTION
===========

   Bio::Tools::SeqStats is a lightweight object for the calculation of
simple statistical and numerical properties of a sequence. By
"lightweight" I mean that only "primary" sequences are handled by the
object.  The calling script needs to create the appropriate primary
sequence to be passed to SeqStats if statistics on a sequence feature are
required.  Similarly if a codon count is desired for a frame-shifted
sequence and/or a negative strand sequence, the calling script needs to
create that sequence and pass it to the SeqStats object.

   SeqStats can be called in two distinct manners.  If only a single
computation is required on a given sequence object, the method can be
called easily using the SeqStats object directly:

     $weight = Bio::Tools::SeqStats->get_mol_wt($seqobj);

   Alternately, if several computations will be required on a given
sequence object, an "instance" statistics object can be constructed and
used for the method calls:

     $seq_stats  =  Bio::Tools::SeqStats->new($seqobj);
     $monomers = $seq_stats->count_monomers();
     $codons = $seq_stats->count_codons();
     $weight = $seq_stats->get_mol_wt();

   As currently implemented the object can return the following values
from a sequence: 	* The molecular weight of the sequence: get_mol_wt() 	*
The number of each type of monomer present: count_monomers() 	* The
number of each codon present in a nucleic acid sequence: count_codons()

   For dna (and rna) sequences, single-stranded weights are returned. The
molecular weights are calculated for neutral - ie not ionized - nucleic
acids. The returned weight is the sum of the base-sugar-phosphate residues
of the chain plus one weight of water to to account for the additional OH
on the phosphate of the 5' residue and the additional H on the sugar ring
of the 3' residue.  Note that this leads to a difference of 18 in
calculated molecular weights compared to some other available programs (eg
Informax VectorNTI).

   Note that since sequences may contain ambiguous monomers (eg "M"
meaning "A" or "C" in a nucleic acid sequence), the method get_mol_wt
returns a two-element array containing the greatest lower bound and least
upper bound of the molecule. (For a sequence with no ambiguous monomers,
the two elements of the returned array will be equal.) The method
count_codons() handles ambiguous bases by simply counting all ambiguous
codons together and issuing a warning to that effect.

DEVELOPERS NOTES
================

   Ewan moved it from Bio::SeqStats to Bio::Tools::SeqStats

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org               - General discussion
     http://bio.perl.org/MailList.html   - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR -  Peter Schattner
=========================

   Email schattner@alum.mit.edu

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

count_monomers
--------------

     Title   : count_monomers
     Usage   : $rcount = $seq_stats->count_monomers();
            or $rcount = $seq_stats->Bio::Tools::SeqStats->($seqobj);
     Function: Counts the number of each type of monomer (amino acid or
     	   base) in the sequence.
     Example :
     Returns : Reference to a hash in which keys are letters of the
               genetic alphabet used and values are number of occurrences
               of the letter in the sequence.
     Args    : None or reference to sequence object
     Throws : Throws an exception if type of sequence is unknown (ie amino
              or nucleic)or if unknown letter in alphabet. Ambiguous
              elements are allowed.

get_mol_wt
----------

     Title   : get_mol_wt
     Usage   : $wt = $seqobj->get_mol_wt() or
               $wt = Bio::Tools::SeqStats ->get_mol_wt($seqobj);
     Function: Calculate molecular weight of sequence
     Example :

     Returns : Reference to two element array containing lower and upper
               bounds of molecule molecular weight. (For dna (and rna)
               sequences, single-stranded weights are returned.)  If
               sequence contains no ambiguous elements, both entries in
               array are equal to molecular weight of molecule.
     Args    : None or reference to sequence object
     Throws  : Exception if type of sequence is unknown (ie not amino or
               nucleic) or if unknown letter in alphabet. Ambiguous
               elements are allowed.

count_codons
------------

     Title   : count_codons
     Usage   : $rcount = $seqstats->count_codons (); or
               $rcount = Bio::Tools::SeqStats->count_codons($seqobj);

     Function: Counts the number of each type of codons in a given frame
               for a dna or rna sequence.
     Example :
     Returns : Reference to a hash in which keys are codons of the genetic
               alphabet used and values are number of occurrences of the
               codons in the sequence. All codons with "ambiguous" bases
               are counted together.
     Args    : None or reference to sequence object

     Throws  : an exception if type of sequence is unknown or protein.

_is_alphabet_strict
-------------------

     Title   :   _is_alphabet_strict
     Usage   :
     Function: internal function to determine whether there are
               any ambiguous elements in the current sequence
     Example :
     Returns : 1 if strict alphabet is being used,
               0 if ambiguous elements are present
     Args    :

     Throws  : an exception if type of sequence is unknown (ie amino or
               nucleic) or if unknown letter in alphabet. Ambiguous
               monomers are allowed.

_print_data
-----------

     Title   : _print_data
     Usage   : $seqobj->_print_data() or Bio::Tools::SeqStats->_print_data();
     Function: Displays dna / rna parameters (used for debugging)
     Returns : 1
     Args    : None

   Used for debugging.

Object holding n-mer statistics for one sequence
************************************************

NAME
====

   Bio::Tools::SeqWords - Object holding n-mer statistics for one sequence

SYNOPSIS
========

   Take a sequence object from eg, an inputstream, and creates an object
for the purposes of holding n-mer word statistics about that sequence.
The sequence can be nucleic acid or protein, but the module is probably
most relevant for DNA.  The words are counted in a non-overlapping manner,
ie. in the style of a codon table, but with any word length.  For
overlapping word counts, a sequence can be 'shifted' to remove the first
character and then the count repeated.  For counts on opposite strand
(DNA/RNA), a reverse complement method should be performed, and then the
count repeated.

   Creating the SeqWords object, eg:

     my $inputstream = Bio::SeqIO->new( -file => "seqfile", -format =>
     'Fasta');
     my $seqobj = $inputstream->next_seq();
     my $seq_word = Bio::Tools::SeqWords->new(-seq => $seqobj);

   or:

     my $seqobj = Bio::PrimarySeq->new(-seq=>'[cut and paste a sequence here]',
                                               -moltype = 'dna', -id = 'test');
     my $seq_word  =  Bio::Tools::SeqWords->new(-seq => $seqobj);

   obtain a hash of word counts, eg:

     my $hash_ref = $seq_stats->count_words($word_length);

   display hash table, eg:

     my %hash = %$hash_ref;
     foreach my $key(sort keys %hash)
     {
     	print "\n$key\t$hash{$key}";
     }

   or

     my $hash_ref = Bio::SeqWords->count_words($seqobj,$word_length);

DESCRIPTION
===========

   Bio:SeqWords is a featherweight object for the calculation of n-mer
word occurrences in a single sequence.  It is envisaged that the object
will be useful for construction of scripts which use n-mer word tables as
the raw material for statistical calculations; for instance, hexamer
frequency for the calculation of coding protential, or the calculation of
periodicity in repetitive DNA.  Triplet frequency is already handled by
Bio::SeqStats.pm (author: Peter Schattner).  There are a few possible
applications for protein, eg: hypothesised amino acid 7-mers in heat shock
proteins, or proteins with multiple simple motifs.  Sometimes these
protein periodicities are best seen when the amino acid alphabet is
truncated, eg Shulman alphabet.  Since there are quite a few of these
shortened alphabets, this module does not specify any particular alphabet.

   See Synopsis above for object creation code.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org                 - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR
======

   Derek Gatherer, in the loosest sense of the word 'author'.  The general
shape of the module is lifted directly from Peter Schattner's SeqStats.pm
module.  The central subroutine to count the words is adapted from
original code provided by Dave Shivak, in response to a query on the
bioperl mailing list.  At least 2 other people provided alternative means
(equally good but not used in the end) of performing the same calculation.
Thanks to all for your assistance.

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

count_words
-----------

     Title   : count_words
     Usage   : $word_count = $seq_stats->count_words($word_length);
     or 	 : $word_count = $seq_stats->Bio::SeqWords->($seqobj,$word_length);
     Function: Counts non-overlapping words within a string
     	 : any alphabet is used
     Example : a sequence ACCGTCCGT, counted at word length 4,
     	 : will give the hash
     	 : ACCG 1, TCCG 1
     Returns : Reference to a hash in which keys are words (any length) of the
     alphabet
             : used and values are number of occurrences of the word in the
     sequence.
     Args    : Word length as scalar and, reference to sequence object if
     required

     Throws an exception word length is not a positive integer
     or if word length is longer than the sequence.

Bioperl object for sigcleave analysis
*************************************

NAME
====

   Bio::Tools::Sigcleave.pm - Bioperl object for sigcleave analysis

SYNOPSIS
========

Object Creation
---------------

     use Bio::Tools::Sigcleave ();

     $sigcleave_object = new Bio::Tools::Sigcleave(-file=>'sigtest.aa',
                                                   -desc=>'test sigcleave protein seq',
                                                   -type=>'AMINO',
                                                   -threshold=>'3.5',
                                                  );

   Sigcleave objects can be created via the same methods as Bio::Seq
objects. The one additional parameter is "-threshold" which sets the score
reporting limit for the algorithim. The above exmple shows a sigcleave
object being created from a protein sequence file. See the Bio::Seq
documention to see the other ways that objects can be created.

Object Methods & Accessors
--------------------------

     %raw_results      = $sigcleave_object->signals;

     $formatted_output = $sigcleave_object->pretty_print;

INSTALLATION
============

   This module is included with the central Bioperl distribution:

     http://bioperl.org/Core/Latest
     ftp://bioperl.org/pub/DIST

   Follow the installation instructions included in the README file.

DESCRIPTION
===========

   "Sigcleave" was a program distributed as part of the free EGCG add-on to
earlier versions of the GCG Sequence Analysis package.

   From the EGCG documentation:   SigCleave uses the von Heijne method to
locate signal sequences, and to identify   the cleavage site. The method
is 95% accurate in resolving signal sequences from   non-signal sequences
with a cutoff score of 3.5, and 75-80% accurate in identifying   the
cleavage site. The program reports all hits above a minimum value.

   The EGCG Sigcleave program was written by Peter Rice (E-mail:
pmr@sanger.ac.uk Post: Informatics Division, The Sanger Centre, Wellcome
Trust Genome Campus, Hinxton, Cambs, CB10 1SA, UK).

   Since EGCG is no longer distributed for the latest versions of GCG,
this code was developed to emulate the output of the original program as
much as possible for those who lost access to sigcleave when upgrading to
newer versions of GCG.

   There are 2 accessor methods for this object. "signals" will return a
perl associative array containing the sigcleave scores keyed by amino acid
position.  "pretty_print" returns a formatted string similar to the output
of the original sigcleave utility.

   In both cases, the "threshold" setting controls the score reporting
level. If no value for threshold is passed in by the user, the code
defaults to a reporting value of 3.5.

   In this implemntation the accessor will never return any score/position
pair which does not meet the threshold limit. This is the slightly
different from the behaviour of the 8.1 EGCG sigcleave program which will
report the highest of the under-threshold results if nothing else is found.

   Example of pretty_print output:

     SIGCLEAVE of sigtest from: 1 to 146

     Report scores over 3.5
     Maximum score 4.9 at residue 131

     Sequence:  FVILAAMSIQGSA-NLQTQWKSTASLALET
             	    | (signal)    | (mature peptide)
               	118            131

     Other entries above 3.5

     Maximum score 3.7 at residue 112

     Sequence:  CSRQLFGWLFCKV-HPGAIVFVILAAMSIQGSANLQTQWKSTASLALET
              	   | (signal)    | (mature peptide)
                	99            112

USAGE
=====

   No warranty implied or expressed. Use at your own risk :) Users
unfamiliar with the original Sigcleave application should read the von
Heijne papers.

   The emphasis here is on correctly replicating the calls that 8.1 EGCG
sigcleave would make. This code has been tested against a non-redundant
curated set of 405 Swissprot proteins representing secreted, non-secreted,
membrane and transit proteins. Except for the EGCG sigcleave habit of
reporting an under-threshold score if nothing better is found the output
was identical.

   The weight matrix in this code is for eukaryote signal sequences.

   Please see the example script located in the bioperl distribution to
see how this code can be used.

FEEDBACK
========

   When updating and maintaining a module, it helps to know that people
are actually using it. Let us know if you find a bug, think this code is
useful or have any improvements/features to suggest.

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bioperl.org/bioperl-bugs/

AUTHOR
======

   Chris Dagdigian, dag@sonsorol.org  & others

VERSION
=======

   Bio::Tools::Sigcleave.pm, $Id: Sigcleave.pm,v 1.12 2000/12/29 07:43:27
lapp Exp $

COPYRIGHT
=========

   Copyright (c) 1999 Chris Dagdigian & others. All Rights Reserved.  This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

REFERENCES / SEE ALSO
=====================

   von Heijne G. (1986) "A new method for predicting signal sequences
cleavage sites."  Nucleic Acids Res. 14, 4683-4690.

   von Heijne G. (1987) in "Sequence Analysis in Molecular Biology:
Treasure Trove or Trivial Pursuit" (Acad. Press, (1987), 113-117).

APPENDIX
========

   The following documentation describes the various functions contained
in this module. Some functions are for internal use and are not meant to
be called by the user; they are preceded by an underscore ("_").

_Analyze
========

     Title     : _Analyze
     Usage     : N/A This is an internal method. Not meant to be called from outside
               : the package
               :
     Purpose   : calculates sigcleave score and amino acid position for the
               : given protein sequence. The score reporting threshold can
               : be adjusted by passing in the "threshold" parameter during
               : object construction. If no threshold is passed in, the code
               : defaults to reporting any scores equal to or above 3.5
               :
     Returns   : nothing. results are added to the object
     Argument  : none.
     Throws    : nothing.
     Comments  : nothing.
     See Also   : n/a

threshold
=========

     Title     : threshold
     Usage     : $value = $self->threshold
               :
     Purpose   : Accessor method sigcleave score reporting threshold.
               :
     Returns   : float.
               :
     Argument  : none.
     Throws    : none.
     Comments  : none.
     See Also   : n/a

signals
=======

     Title     : signals
     Usage     : %sigcleave_results = $sigcleave_object->signals;
               :
     Purpose   : Accessor method for sigcleave results
               :
     Returns   : Associative array. The key value represents the amino acid position
               : and the value represents the score. Only scores that
               : are greater than or equal to the THRESHOLD value are reported.
               :
     Argument  : none.
     Throws    : none.
     Comments  : none.
     See Also   : THRESHOLD

pretty_print
============

     Title     : pretty_print
     Usage     : $output = $sigcleave_object->pretty_print;
               : print $sigcleave_object->pretty_print;
               :
     Purpose   : Emulates the output of the EGCG Sigcleave
               : utility.
               :
     Returns   : A formatted string.
     Argument  : none.
     Throws    : none.
     Comments  : none.
     See Also   : n/a

A single exon determined by an alignment
****************************************

NAME
====

   Bio::Tools::Sim4::Exon - A single exon determined by an alignment

SYNOPSIS
========

     # See Bio::Tools::Sim4::Results for a description of the context.

     # an instance of this class is-a Bio::SeqFeature::SimilarityPair

     # coordinates of the exon (recommended way):
     print "exon from ", $exon->start(),
     	" to ", $exon->end(), "\n";

     # the same (feature1() inherited from Bio::SeqFeature::FeaturePair)
     print "exon from ", $exon->feature1()->start(),
     	" to ", $exon->feature1()->end(), "\n";
     # also the same (query() inherited from Bio::SeqFeature::SimilarityPair):
     print "exon from ", $exon->query()->start(),
     	" to ", $exon->query()->end(), "\n";

     # coordinates on the matching EST (recommended way):
     print "matches on EST from ", $exon->est_hit()->start(),
     	" to ", $exon->est_hit()->end(), "\n";

     # the same (feature2() inherited from Bio::SeqFeature::FeaturePair)
     print "matches on EST from ", $exon->feature2()->start(),
     	" to ", $exon->feature2()->end(), "\n";
     # also the same (subject() inherited from Bio::SeqFeature::SimilarityPair):
     print "exon from ", $exon->subject()->start(),
     	" to ", $exon->subject()->end(), "\n";

DESCRIPTION
===========

   This class inherits from Bio::SeqFeature::SimilarityPair and represents
an exon on a genomic sequence determined by similarity, that is, by
aligning an EST sequence (using Sim4 in this case). Consequently, the
notion of query and subject is always from the perspective of the genomic
sequence: query refers to the genomic seq, subject to the aligned EST hit.
Because of this, $exon->start(), $exon->end() etc will always return what
you expect.

   To get the coordinates on the matching EST, refer to the properties of
the feature returned by `est_hit' in this node().

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably  to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.   Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney, Hilmar Lapp
=================================

   Email birney@sanger.ac.uk Hilmar Lapp <hlapp@gmx.net> or
<hilmar.lapp@pharma.novartis.com>.

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

percentage_id
-------------

     Title   : percentage_id
     Usage   : $obj->percentage_id($newval)
     Function: This is a synonym for 100 * $obj->est_hit()->frac_identical().
     Returns : value of percentage_id
     Args    : newvalue (optional)

est_hit
-------

     Title   : est_hit
     Usage   : $est_feature = $obj->est_hit();
     Function: Returns the EST hit pointing to (i.e., aligned to by Sim4) this
               exon (i.e., genomic region). At present, merely a synonym for
               $obj->feature2().
     Returns : An Bio::SeqFeatureI implementing object.
     Args    :

Results of one Sim4 run
***********************

NAME
====

   Bio::Tools::Sim4::Results - Results of one Sim4 run

SYNOPSIS
========

     # to preset the order of EST and genomic file as given on the sim4
     # command line:
     $sim4 = Bio::Tools::Sim4::Results->new(-file => 'result.sim4',
                                            -estisfirst => 1);
     # to let the order be determined automatically (by length comparison):
     $sim4 = Bio::Tools::Sim4->new( -file => 'sim4.results' );
     # filehandle:
     $sim4 = Bio::Tools::Sim4->new( -fh   => \*INPUT );

     # parse the results
     while($exonset = $sim4->next_exonset()) {
         # $exonset is-a Bio::SeqFeature::Generic with Bio::Tools::Sim4::Exons
         # as sub features
         print "Delimited on sequence ", $exonset->seqname(),
               "from ", $exonset->start(), " to ", $exonset->end() "\n";
         foreach $exon ( $exonset->sub_SeqFeature() ) {
     	  # $exon is-a Bio::SeqFeature::FeaturePair
     	  print "Exon from ", $exon->start, " to ", $exon->end,
                  " on strand ", $exon->strand(), "\n";
            # you can get out what it matched using the est_hit attribute
            $homol = $exon->est_hit();
            print "Matched to sequence", $homol->seqname,
                  " at ", $homol->start," to ", $homol->end, "\n";
        }
     }

     # essential if you gave a filename at initialization (otherwise the file
     # stays open)
     $sim4->close();

DESCRIPTION
===========

   The sim4 module provides a parser and results object for sim4 output.
The sim4 results are specialised types of SeqFeatures, meaning you can add
them to AnnSeq objects fine, and manipulate them in the "normal"
seqfeature manner.

   The sim4 Exon objects are Bio::SeqFeature::FeaturePair inherited
objects. The $esthit = $exon->est_hit() is the alignment as a feature on
the matching object (normally, an EST), in which the start/end points are
where the hit lies.

   To make this module work sensibly you need to run

     sim4 genomic.fasta est.database.fasta
     or
     sim4 est.fasta genomic.database.fasta

   To get the sequence identifiers recorded for the first sequence, too,
use A=4 as output option for sim4.

   One fiddle here is that there are only two real possibilities to the
matching criteria: either one sequence needs reversing or not. Because of
this, it is impossible to tell whether the match is in the forward or
reverse strand of the genomic DNA. We solve this here by assuming that the
genomic DNA is always forward. As a consequence, the strand attribute of
the matching EST is unknown, and the strand attribute of the genomic DNA
(i.e., the Exon object) will reflect the direction of the hit.

   See the documentation of parse_next_alignment() for abilities of the
parser to deal with the different output format options of sim4.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Ewan Birney, Hilmar Lapp
=================================

   Email birney@sanger.ac.uk       hlapp@gmx.net (or
hilmar.lapp@pharma.novartis.com)

   Describe contact details here

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

analysis_method
---------------

     Usage     : $sim4->analysis_method();
     Purpose   : Inherited method. Overridden to ensure that the name matches
                 /sim4/i.
     Returns   : String
     Argument  : n/a

parse_next_alignment
--------------------

     Title   : parse_next_alignment
     Usage   : @exons = $sim4_result->parse_next_alignment;
               foreach $exon (@exons) {
                   # do something
               }
     Function: Parses the next alignment of the Sim4 result file and returns the
               found exons as an array of Bio::Tools::Sim4::Exon objects. Call
               this method repeatedly until an empty array is returned to get the
               results for all alignments.

     The $exon->seqname() attribute will be set to the identifier of the
     respective sequence for both sequences if A=4 was used in the sim4
     run, and otherwise for the second sequence only. If the output does
     not contain the identifier, the filename stripped of path and
     extension is used instead. In addition, the full filename
     will be recorded for both features ($exon inherits off
     Bio::SeqFeature::SimilarityPair) as tag 'filename'. The length
     is accessible via the seqlength() attribute of $exon->query() and
     $exon->est_hit().

     Note that this method is capable of dealing with outputs generated
     with format 0,1,3, and 4 (via the A=n option to sim4). It
     automatically determines which of the two sequences has been
     reversed, and adjusts the coordinates for that sequence. It will
     also detect whether the EST sequence(s) were given as first or as
     second file to sim4, unless this has been specified at creation
     time of the object.

     Example :
     Returns : An array of Bio::Tools::Sim4::Exon objects
     Args    :

next_exonset
------------

     Title   : next_exonset
     Usage   : $exonset = $sim4_result->parse_next_exonset;
               print "Exons start at ", $exonset->start(),
                     "and end at ", $exonset->end(), "\n";
               foreach $exon ($exonset->sub_SeqFeature()) {
                   # do something
               }
     Function: Parses the next alignment of the Sim4 result file and returns the
               set of exons as a container of features. The container is itself
               a Bio::SeqFeature::Generic object, with the Bio::Tools::Sim4::Exon
               objects as sub features. Start, end, and strand of the container
               will represent the total region covered by the exons of this set.

     See the documentation of parse_next_alignment() for further
     reference about parsing and how the information is stored.

     Example :
     Returns : An Bio::SeqFeature::Generic object holding Bio::Tools::Sim4::Exon
               objects as sub features.
     Args    :

next_feature
------------

     Title   : next_feature
     Usage   : while($exonset = $sim4->next_feature()) {
                      # do something
               }
     Function: Does the same as L<next_exonset()>. See there for documentation of
               the functionality. Call this method repeatedly until FALSE is
               returned.

     The returned object is actually a SeqFeatureI implementing object.
     This method is required for classes implementing the
     SeqAnalysisParserI interface, and is merely an alias for
     next_exonset() at present.

     Example :
     Returns : A Bio::SeqFeature::Generic object.
     Args    :

Bioperl manager for web resources related to biology.
*****************************************************

NAME
====

   Bio::Tools::WWW.pm - Bioperl manager for web resources related to
biology.

SYNOPSIS
========

Object Creation
---------------

     use Bio::Tools qw(:obj);

     $pdb = $BioWWW->home_url('pdb');

   There is no need to create a new Bio::Tools::WWW.pm object when the
`:obj' tag is used. This tag will import the static $BioWWW object created
by Bio::Tools::WWW.pm into your name space. This saves you from having to
call `new Bio::Tools::WWW'.

   You are free to not use the :obj tag and create the object as you like,
but a Bio::Tools::WWW object is not configurable; any given script only
needs a single copy.

INSTALLATION
============

   This module is included with the central Bioperl distribution:

     http://bio.perl.org/Core/Latest
     ftp://bio.perl.org/pub/DIST

   You also need to define URLs for the following variables in this
package:

     $Not_found_url : Generic page to show in place of a 404 error.
     $Tmp_url       : Web-accessible site that is Used for scripts that
                      need to generate temporary, web-accessible files.
                      The files need not necessarily be HTML files, but
                      being on the same disk as the server will permit
                      faster IO from server scripts.

DESCRIPTION
===========

   Bio::Tools::WWW is primarily a URL broker for a select set of sites
related to bioinformatics/genome analysis. It definitely represents a
biased, unexhaustive set.  It might be more accurate to call this module
"Bio::Tools::URL.pm". But this module does handle some non-URL things and
it may do more of this in the future. Having one module to cover all
biologically relevant web utilities makes it more convenient, especially
at this early stage of development.

   Maintaining accurate URLs over time can be challenging as new web sites
spring up and old sites are re-organized. Because of this fact, the URLs
in this module are not guaranteed to be correct or exhaustive and will
require periodic updating.

URL Management
--------------

   By keeping URL management within Bio::Tools::WWW.pm, other generic
modules can easily access a variety of different web sites without having
to know about a potential multitude of specific modules specialized for
one database or another. A specific example of this is in
Bio::Tools::Blast.pm where the function blast_to_html() needs access to
different URLs in order to add database links to the Blast report. An
alternative approach would be to have multiple blast_to_html() functions
defined within modules specialized for Blast analyses of different
datasets. This, however, may create maintenance headaches when updating
the different versions of the function.

Complex Websites
----------------

   Websites with complex datasets may require special treatment within
this module. As an example, URLs for the Saccharomyces Genome Database are
clustered separately in this module, due to (1) the different ways to
access information at this database and (2) the familiarity of the
developer with this database. The Bio::SGD::WWW.pm inherits from
Bio::Tools::WWW.pm to permit access to the URLs provided by
Bio::Tools::WWW.pm and to SGD-specific HTML and images.

   The organization of Bio::Tools::WWW.pm is expected to evolve as
websites get born, die, and mutate their APIs.

SEE ALSO
========

     http://bio.perl.org/Projects/modules.html  - Online module documentation
     http://bio.perl.org/                       - Bioperl Project Homepage

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules.  Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     vsns-bcd-perl@lists.uni-bielefeld.de          - General discussion
     vsns-bcd-perl-guts@lists.uni-bielefeld.de     - Technically-oriented discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR
======

   Steve A. Chervitz, sac@genome.stanford.edu

VERSION
=======

   Bio::Tools::WWW.pm, 0.014

COPYRIGHT
=========

   Copyright (c) 1996-98 Steve A. Chervitz. All Rights Reserved.  This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

APPENDIX
========

   Methods beginning with a leading underscore are considered private and
are intended for internal use by this module. They are not considered part
of the public interface and are described here for documentation purposes
only.

home_url
--------

     Usage     : $BioWWW->home_url(<string>)
     Purpose   : To obtain the homepage URL for a biological database or resource.
     Returns   : String containing the URL (including "http://")
     Argument  : String
               : Currently acceptable arguments are:
               :    bioperl  bioperl-schema  biomoo  bsm  ebi  emotif  entrez
               :    expasy  mips  mmdb  ncbi  pir  pfam  pdb  geneQuiz
               :    molMov  pubmed  sacch3d  sgd  scop  swissProt  webmol  ypd
     Throws    : Warns if argument cannot be resolved to a URL.
     Comments  : The URLs listed here do not represent a complete list.
               : Expect this to evolve and grow with time.

   See Also   : `search_url' in this node()

search_url
----------

     Usage     : $BioWWW->search_url(<string>)
     Purpose   : To provide a URL stem for a search engine at a biological database
               : or resource.
     Returns   : String containing the URL (including "http://")
     Argument  : String
               : Currently acceptable arguments are:
               :   3db  embl  cath  ec1  ec2  ec3  emotif_id  entrez  gb1  gb2
               :   gb3  gb4  gb5  pdb  medline  mmdb  pdb  pdb_coord  pfam  pir_acc
               :   pdbSum  molMov  swpr  swModel  swprSearch  scop  scop_pdb  scop_data
               :   ypd
     Throws    : Warns if argument cannot be resolved to a URL.
     Comments  : Unlike the homepage URLs, this method does not return a complete
               : URL but a stem which must be further modified, typically by
               : appending data to it, before it can be used. The data appended
               : depends on the specific URL; typically, it is a database ID or
               : other unique identifier.
               : The requirements for each URL will be described here eventually.
               :
               : The URLs listed here do not represent a complete list.
               : Expect this to evolve and grow with time.
               :
               : Given this complexity, it may be useful to provide special methods
               : for these different URLs. This would however result in an
               : explosion of methods that might make this module less
               : maintainable and harder to use.

   See Also   : `home_url' in this node()

stem_url
--------

     Usage     : $BioWWW->stem_url(<string>)
     Purpose   : To obtain the minimal stem URL for searching a biological database or resource.
     Returns   : String containing the URL (including "http://")
     Argument  : String
               : Currently acceptable arguments are:
               :    emotif  entrez  pdb
     Throws    : Warns if argument cannot be resolved to a URL.
     Comments  : The URLs stems returned by this method are much more minimal than
               : this provided by search_url(). Use of these stems requires knowledge
               : of the CGI scripts which they invoke.

   See Also   : `search_url' in this node()

viewer_url
----------

     Usage     : $BioWWW->viewer_url(<string>)
     Purpose   : To obtain the stem URL for a 3D viewer (RasMol, WebMol, Cn3D)
     Returns   : String containing the URL (including "http://")
     Argument  : String
               : Currently acceptable arguments are:
               :    rasmol webmol cn3d java  (java is an alias for webmol)
     Throws    : Warns if argument cannot be resolved to a URL.
     Comments  : The 4-letter Brookhaven PDB identifier must be appended to the
               : URL provided by this method.
               : The URLs listed here do not represent a complete list.
               : Expect this to evolve and grow with time.

not_found_url
-------------

     Usage     : $BioWWW->not_found_url()
     Purpose   : To obtain the URL for a web page to be shown in place of a 404 error.
     Returns   : String containing the URL (including "http://")
     Argument  : n/a
     Throws    : n/a
     Comments  : This URL should be customized as desired.

tmp_url
-------

     Usage     : $BioWWW->tmp_url()
     Purpose   : To obtain the URL for a temporary, web-accessible directory.
     Returns   : String containing the URL (including "http://")
     Argument  : n/a
     Throws    : n/a
     Comments  : This URL should be customized  as desired.

search_link
-----------

     Usage     : $BioWWW->search_link(<site>, <value>, <text>)
     Purpose   : Wrapper for search_url() that returns the URL within an HTML anchor.
     Returns   : String containing the HTML anchor ( qq|<A HREF="http://..."</A>|)
     Argument  : <site>  = string to be used as argument for search_url()
               : <value> = string to be appended to the search URL stem.
               : <text>  = string to be shown as the link text (default = <value>).
     Throws    : n/a
     Status    : Experimental

   See Also   : `search_url' in this node()

viewer_link
-----------

     Usage     : $BioWWW->viewer_link(<site>, <value>, <text>)
     Purpose   : Wrapper for viewer_url() that returns the complete URL within an HTML anchor.
     Returns   : String containing the HTML anchor ( qq|<A HREF="http://..."</A>|)
     Argument  : <site>  = string to be used as argument for viewer_url()
               : <value> = string to be appended to the viewer URL stem.
               : <text>  = string to be shown as the link text (default = <value>).
     Throws    : n/a
     Status    : Experimental

   See Also   : `viewer_url' in this node()

html
----

     Usage     : $BioWWW->html(<string>)
     Purpose   : To obtain HTML-formatted text for frequently needed web-page messages.
     Returns   : String containing the HTML anchor ( qq|<A HREF="http://..."</A>|)
     Argument  : String.
               : Currently acceptable arguments are:
               :   authority  (mailto: link for webmaster; shows e-mail address as link)
               :   notify     (wraps mailto:authority link with text for link "please notify us")
               :   ourFault   ("this problem is our fault. If it persists <notify-link>")
               :   trouble    (same as ourFault but doesn't blame us for the problem)
               :   techDiff   ("we are experiencing technical difficulties. Please stand by.")
     Throws    : n/a
     Comments  : The authority (webmaster) is imported from the Bio::Root::Global.pm
               : module. The value for $AUTHORITY should be set there, or
               : customize this module so that it doesn't use Bio::Root::Global.pm.

sgd_url
-------

     Usage     : $BioWWW->sgd_url(<string>)
     Purpose   : To obtain the webpage URL or search stem for SGD.
     Returns   : String containing the URL (including "http://")
     Argument  : String
               : Currently acceptable arguments (TODO).
     Throws    : Warns if argument cannot be resolved to a URL.
     Comments  : This accessor is specialized for the Saccharomyces Genome Database.
               : It is possible that it will be moved to SGD::WWW.pm in the future.

   See Also   : `search_url' in this node()

s3d_url
-------

     Usage     : $BioWWW->s3d_url(<string>)
     Purpose   : To obtain the webpage URL or search stem for Sacch3D.
     Returns   : String containing the URL (including "http://")
     Argument  : String
               : Currently acceptable arguments (TODO).
     Throws    : Warns if argument cannot be resolved to a URL.
     Comments  : This accessor is specialized for the Saccharomyces Genome Database.
               : It is possible that it will be moved to SGD::WWW.pm in the future.

   See Also   : `search_url' in this node()

sgd_stem_url
------------

     Usage     : $BioWWW->sgd_stem_url(<string>)
     Purpose   : To obtain the minimal stem URL for a SGD/Sacch3D CGI script.
     Returns   : String containing the URL (including "http://")
     Argument  : String
               : Currently acceptable arguments (TODO).
     Throws    : Warns if argument cannot be resolved to a URL.
     Comments  : This accessor is specialized for the Saccharomyces Genome Database.
               : It is possible that it will be moved to SGD::WWW.pm in the future.

   See Also   : `search_url' in this node()

s3d_link
--------

     Usage     : $BioWWW->s3d_link(<site>, <value>, <text>)
     Purpose   : Wrapper for s3d_url() that returns the complete URL within an HTML anchor.
     Returns   : String containing the URL (including "http://")
     Argument  : <site>  = string to be used as argument for s3d_url()
               : <value> = string to be appended to the s3d URL stem.
               : <text>  = string to be shown as the link text (default = <value>).
     Throws    : n/a
     Status    : Experimental
     Comments  : This accessor is specialized for the Saccharomyces Genome Database.
               : It is possible that it will be moved to SGD::WWW.pm in the future.

   See Also   : `s3d_url' in this node(), `sgd_link' in this node()

sgd_link
--------

     Usage     : $BioWWW->sgd_link(<site>, <value>, <text>)
     Purpose   : Wrapper for sgd_url() that returns the complete URL within an HTML anchor.
     Returns   : String containing the URL (including "http://")
     Argument  : <site>  = string to be used as argument for sgd_url()
               : <value> = string to be appended to the sgd URL stem.
               : <text>  = string to be shown as the link text (default = <value>).
     Throws    : n/a
     Status    : Experimental
     Comments  : This accessor is specialized for the Saccharomyces Genome Database.
               : It is possible that it will be moved to SGD::WWW.pm in the future.

   See Also   : `sgd_url' in this node(), `s3d_link' in this node()

start_html
----------

     Usage     : $BioWWW->start_html()
     Purpose   : Prints the "Content-type: text/html\n\n<HTML>\n" header.
     Returns   : n/a; This method prints the Content-type string shown above.
     Argument  : n/a
     Throws    : n/a
     Status    : Experimental
     Comments  : This method prevents redundant invocations thus avoiding th
               : accidental printing of the "content-type..." on the page.
               : If using L. Stein's CGI.pm, this is similar to $query->header()
               : (Does CGI.pm prevent redundant invocation?)

redirect
--------

     Usage     : $BioWWW->redirect(<string>)
     Purpose   : Prints the header needed to redirect a web browser to a supplied URL.
     Returns   : n/a; Prints the redirection header.
     Argument  : String containing the URL to be redirected to.
     Throws    : n/a
     Status    : Experimental

pre
---

     Usage     : $BioWWW->pre("text to be pre-formatted");
     Purpose   : To produce HTML for text that is not to be formated by the brower.
     Returns   : String containing the "<pre>" formatted html.
     Argument  : n/a
     Throws    : n/a
     Status    : Experimental

strip_html
----------

     Usage     : $boolean = &strip_html( string_ref, [fast] );
     Purpose   : Removes HTML formatting from a supplied string.
     Returns   : Boolean: true if string was stripped, false if not.
     Argument  : string_ref = reference to a string containing the whole
               :              web page to be stripped.
               : fast = a non-zero value. Optional. If set, a faster
               :        but perhaps less thorough procedure is used for
               :        stripping. Default = not fast.
     Throws    : Exception if the argument is not a scalar reference.
     Comments  : Based on code originally written by Alex Dong Li
               : (ali@genet.sickkids.on.ca).
               : This is a more generic version of the function that appears
               : in Bio::Tools::Blast::HTML.pm
               : This version does not perform any Blast-specific stripping.
               :
               : This employs a simple method for removing tags that
               : will fail under following conditions:
               :  1) if quoted > appears in a tag  (does this ever happen?)
               :  2) if a tag is split over multiple lines and this method is
               :     used to process one line at a time.
               :
               : Without fast mode, large HTML files can take exceedingly long times to
               : strip (e.g., 1Meg file with many tags can take 10 minutes versus 5 seconds
               : in fast mode. Try the swissprot yeast table). If you know the HTML to be
               : well-behaved (i.e., tags are not split across mutiple lines), use fast
               : mode for large, dense files.

Data Members
------------

   An instance of Bio::Tools::WWW.pm is a blessed reference to a hash
containing all or some of the following fields:

     FIELD           VALUE
     --------------------------------------------------------------
     _started_html   Defined the on the initial invocation of start_html()
                     to avoid duplicate printing out the "Content-type..." header.

pairwise Smith Waterman object
******************************

NAME
====

   Bio::Tools::pSW - pairwise Smith Waterman object

SYNOPSIS
========

     $factory = new Bio::Tools::pSW( '-matrix' => 'blosum62.bla',
     				    '-gap' => 12,
     				    '-ext' => 2,
     				   );

     #use the factory to make some output

     $factory->align_and_show($seq1,$seq2,STDOUT);

     # make a Bio::SimpleAlign and do something with it

     $aln = $factory->pairwise_alignment($seq1,$seq2);

     $aln->write_MSF(\*STDOUT);

INSTALLATION
============

   This module is included with the central Bioperl distribution:

     http://bio.perl.org/Core/Latest
     ftp://bio.perl.org/pub/DIST

   Follow the installation instructions included in the README file.

DESCRIPTION
===========

   pSW is an Alignment Factory. It builds pairwise alignments using the
smith waterman algorithm. The alignment algorithm is implemented in C and
added in using an XS extension. The XS extension basically comes from the
Wise2 package, but has been slimmed down to only be the alignment part of
that (this is a good thing!). The XS extension comes from the bioperl-ext
package which is distributed along with bioperl.  Warning This package
will not work if you have not compiled the bioperl-ext package.

   The mixture of C and Perl is ideal for this sort of problem. Here are
some plus points for this strategy:

Speed and Memory
     The algorithm is actually implemented in C, which means it is faster
     than a pure perl implementation (I have never done one, so I have no
     idea how faster) and will use considerably less memory, as it
     efficiently assigns memory for the calculation.

Algorithm efficiency
     The algorithm was written using Dynamite, and so contains an automatic
     switch to the linear space divide and conquor method. This means you
     could effectively align very large sequences without killing your
     machine (it could take a while though!).

IN_DEVELOPMENT
==============

   warning - this module is under active development. Eventually it should
contain the ability to make alignment objects such as Bio::SimpleAlign or
Bio::UnivAlign

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules.  Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org              - General discussion
     http://bioperl.org/MailList.html  - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bioperl.org/bioperl-bugs/

AUTHOR
======

   Ewan Birney, birney@sanger.ac.uk

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with an underscore "_".

pairwise_alignment
------------------

     Title   : pairwise_alignment
     Usage   : $aln = $factory->pairwise_alignment($seq1,$seq2)
     Function: Makes a SimpleAlign object from two sequences
     Returns : A SimpleAlign object
     Args    :

align_and_show    Title   : align_and_show  Usage   : $factory->align_and_show($seq1,$seq2,STDOUT)
--------------------------------------------------------------------------------------------------

matrix
------

     Title     : matrix()
     Usage     : $factory->matrix('blosum62.bla');
     Function  : Reads in comparison matrix based on name
               :
     Returns   :
     Argument  : comparison matrix

gap
---

     Title     : gap
     Usage     : $gap = $factory->gap() #get
               : $factory->gap($value) #set
     Function  : the set get for the gap penalty
     Example   :
     Returns   : gap value
     Arguments : new value

ext
---

     Title     : ext
     Usage     : $ext = $factory->ext() #get
               : $factory->ext($value) #set
     Function  : the set get for the ext penalty
     Example   :
     Returns   : ext value
     Arguments : new value

Bioperl alignment object
************************

NAME
====

   Bio::UnivAln - Bioperl alignment object

SYNOPSIS
========

   This Perl module is intended to simplify the handling of biosequence
alignments.  When in doubt, always check our Homepage for the newest
version, contact emails, help files, etc:
http://www.techfak.uni-bielefeld.de/bcd/Perl/Bio/welcome.html

   See the `REVISION HISTORY' in this node for recent bugfixes and
enhancements.

Object Creation in a Nutshell
-----------------------------

     use Bio::UnivAln;

     my $aln = Bio::UnivAln->new('t/alnfile.fasta');
     $aln = Bio::UnivAln->new(-file=>'t/alnfile.aa',
                          -desc=>'Sample alignment',
                          -type=>'amino',
                          -ffmt=>'raw'      # 1 line in file -> 1 sequence
                         );
     $aln = Bio::UnivAln->new(-seqs=>"TCCCGCGTCAACTG\nTGGTGCTTCAACCG\nACTTG--TCAACTG");
     $aln = Bio::UnivAln->new(-seqs=>[$sequence_strg,\@character_list,$bioSeqObject]);
     $aln = Bio::UnivAln->new(-seqs=> ['ACCCGCGTCAACTG',
              ['A','G','G','G','G','C','T','T','C','A','A','C','C','G'],
              Bio::Seq->new(-seq=>'ACTTG--TCAACTG')
            ]);
     $aln = Bio::UnivAln->new($file,$seqs,$id,$desc,$names,$row_ids,$col_ids,
              $row_descs,$col_descs,$numbering,$type,$ffmt,$descffmt,$inplace);

Object Manipulation in a Nutshell
---------------------------------

     OUTPUT

     $aln->ffmt('fasta');   # set default output format
     print "\n aln in default format:\n", $aln->layout();
     print "\n aln in raw format:\n", $aln->layout("raw");
     print "\n aln in fasta format:\n", $aln->layout("fasta"), "\n";
     print "\n aln in MSF format (via readseq):\n", $aln->layout("MSF"), "\n";

     SLICING

     my $alnSlice = $aln->seqs(1,3,1,2); # multiline string of rows 1-3, columns 1-2
         print $alnSlice, "\n";
     my @alnSlice = $aln->seqs([1..3], [1,4]); # multidimensional array
                                               # of rows 1-3, columns 1+4
         for $aref ( @alnSlice ) { print @$aref, "\n"; }
     $alnSlice = $aln->seqs([3,2,3,1], [1,3..5]); # rows 3,2,3,1, cols 1,3..5

     ADVANCED SLICING

     sub has_purine {
       my $str = join "", @{ $_[0] };
       if ($str =~ /[AaGgRr]+/) {return 1;} else {return 0;}
     }
       @alnSlice = $aln->seqs([1,2,3], \&has_purine); # rows 1-3, and from these
     # only the entries of columns for which has_purine returns 1
       $alnSlice = $aln->seqs({ids=>'SeqA SeqB'},{ids=>'ColA ColB ColC'});
       $aln->inplace(1); $aln->seqs({ids=>'A B'},[1..6]); $aln->inplace(0);
     # manipulates the object itself, assigning the slice internally

     MAPPING

     @resSlice = $aln->map_r(\&has_purine, [1..3]); # 1,0,1 if row 1+3 has purine
     @resSlice = $aln->map_c(\&has_purine, [1,4]); # 1,0 if column 1 has purine

     UTILITIES

     $resSlice = $aln->consensus(); # 75% majority needed for consensus letter
     $resSlice = $aln->consensus(0.6, [1,3]); # 60% majority, columns 1+3 only
     $resSlice = $aln->var_sites(); # no columns that are invariable ...
     $indices = $aln->var_inds();   # ... and their indices
     $resSlice = $aln->invar_sites(); # only columns that are invariable
     $indices = $aln->invar_inds();   # (..inds() is available for most utilities)
     $resSlice = $aln->var_sites(0.6); # no columns with >= 60% maj. of 1 letter
     $resSlice = $aln->invar_sites(0.6); # only columns with >= 60% majority
     $resSlice = $aln->gap_free_sites();
     $resSlice = $aln->no_allgap_sites(); # exclude sites that only have gaps
     $resSlice = $aln->reverse([1,3]); # reverse of rows 1+3 only
     $resSlice = $aln->complement([1,3]); # dna/rna complement of rows 1+3 only
     $resSlice = $aln->revcom([1,3]); # reverse complement, rows 1+3 only
     $resSlice = $aln->remove_gaps(); # original sequences without gaps

INSTALLATION
============

   This module is included with the central Bioperl distribution:

     http://bio.perl.org/Core/Latest
     ftp://bio.perl.org/pub/DIST

   Follow the installation instructions included in the README file.

   The following are the installation instructions from the original
UnivAlign distribution for installing UnivAlign.pm by itself. These are
not necessary if installing from the central Bioperl distribution. Note
that the central distribution does not currently run the more extensive
univaln.t2 test harness.

   The original installation package is available from:

     http://www.techfak.uni-bielefeld.de/bcd/Perl/Bio/#univaln

   To install, untar it and run the following commands in the module
directory created by tar:

     % perl Makefile.PL
     % make
     % make test
     % make install

   For intensive testing, see t/univaln.t2. Run that script via

     % perl t/univaln.t2 > t/my_univaln

   and compare the output with the file t/univaln.o .  Expected error
messages can be found in t/univaln2_expected_errors .

   If you do not have superuser installation privileges, or to install in
a different directory, you can do one of two things:

   1) Either copy the UnivAln.pm module into the "Bio" subdirectory of an
accessible Perl module directory (e.g. /my/perl/lib/Bio/).  (One possible
"accessible Perl module directory" is your current working directory;
there you can create a subdirectory named "Bio" and place UnivAln.pm in
that subdirectory. Then, you can start scripts using Bio::UnivAln from
your current working directory.)

   2) Or, run the above commands but specify an alternate location for the
module by supplying a PREFIX argument to the first command:

     % perl Makefile.PL PREFIX=/my/perl/stuff

   This will place the module into '/my/perl/stuff/lib/site_lib/'. To
specify a directory for the module file, set the $INSTALLSITELIB variable
in Makefile.PL (e.g., $INSTALLSITELIB = '/my/perl/lib');

   The make install command may report problems with creating documentation
files (pod2man/perllocal.pod); please find the documentation in
UnivAln.pm.html instead.

   If you have Bio::Seq installed and want to test Bio::Seq usage by
Bio::UnivAln, you need enable the line "use Bio::Seq;" at the beginning of
t/univaln.t2; Bio::Seq can be found via
http://www.techfak.uni-bielefeld.de/bcd/Perl/Bio/ .  Note that the test
script will also test error handling; you can expect the error messages
included in the file univaln.t2_expected_errors - these are OK.

   If you wish that the module uses Don Gilbert's readseq package for
sequence format conversion (Version 1 Feb 1993), you can set the
environment variable `READSEQ_DIR'" appropriately. (Currently, only
"fasta" and "raw" format are supported directly by UnivAln.pm.)  Then, the
program detects and uses `readseq' automatically, if it is in the
specified directory (the default directory is "./"). Modifying the
environment variable `READSEQ' changes the expected name of the executable.
For example, $ENV{READSEQ_DIR} may be "/vol/biotools/bin/" and
$ENV{READSEQ} "readseq2.0". Readseq will give you support for PIR/CODATA,
MSF/GCG and PAUP/NEXUS formats; ASN.1 does not seem to work reliably.
(URLs: http://iubio.bio.indiana.edu/IUBio-Software+Data/molbio/readseq/
http://dot.imgen.bcm.tmc.edu:9331/seq-util/Help/readseq.html
http://bimas.dcrt.nih.gov/molbio/readseq/formats.html )

   Similar support for conversion from Clustal format, using Clustal as a
converter, is implemented, but not properly tested and documented.  The
relevant environment variables are `CLUSTAL_DIR' and `CLUSTAL'.  (URL:
http://www-igbmc.u-strasbg.fr/BioInfo/ClustalW/Top.html )

   (Thanks to Steve A. Chervitz for his help with bundling the module !)

DESCRIPTION
===========

   This module is the Bio::UnivAln alignment object which is part of the
Bioperl project. Currently it has some nice methods for accessing an
alignment after reading it in from certain formats, incl. utilities like
consensus and reverse complement. Bio::Seq (single sequences) is only
needed if you explicitly want to use these.

   (Most examples below are taken from the test script(s) that can be
found in directory "t" of the Bio::UnivAln distribution.  There you will
also find a CGI script producing some graphics, which is currently in
alpha status: I suspect it needs some refitting to run on a different
server. If you'd like to know more about multiple alignments, in theory
and practice, check out the tutorial at
http://www.techfak.uni-bielefeld.de/bcd/Curric/MulAli/mulali.html )

CREATION OF ALIGNMENTS
----------------------

   Alignments can be constructed from files, (multi-line) strings, arrays
and Bio::Seq objects. Files need to be in a standard format, as described
below, under the header `ALIGNMENT FORMATS' in this node.

     my $aln = Bio::UnivAln->new('t/alnfile.fasta');

   The first parameter is regarded as a file name; if you pass additional
parameters, they will overwrite the parameters read in from the file. You
can use named parameters; take a look at the documentation on the new()
method in the appendix for a list of all parameters, and their names. In
the following example, description, sequence type, and file format are
provided. The file format will relieve Bio::UnivAln from guessing it;
however, there are no guarantees if you bypass Bio::UnivAln's guessing
_and_ provide an incorrect file format.

     $aln = Bio::UnivAln->new(-file=>'t/alnfile.aa',
                          -desc=>'Sample alignment',
                          -type=>'amino',
                          -ffmt=>'raw'      # 1 line in file -> 1 sequence
                         );

   If no description ("-desc") is given, a default one will be based on the
file name.  The format type is also the default format for output; if both
differ, you need to specify the input format when you construct the $aln
object, and then use the accessor ffmt() to set the default output format.
Bio::UnivAln can be passed the aligned sequences directly, using the named
parameter "-seqs". It takes a multi-line string, or any mix of strings,
array references, and Bio::Seq objects:

     $aln = Bio::UnivAln->new(-seqs=>"TCCCGCGTCAACTG\nTGGTGCTTCAACCG\nACTTG--TCAACTG");
     $aln = Bio::UnivAln->new(-seqs=>[$sequence_strg,\@character_list,$bioSeqObject]);
     $aln = Bio::UnivAln->new(-seqs=> ['ACCCGCGTCAACTG',
              ['A','G','G','G','G','C','T','T','C','A','A','C','C','G'],
              Bio::Seq->new(-seq=>'ACTTG--TCAACTG')
            ]);

ACCESS TO THE DATA, AND MANIPULATION
------------------------------------

   The layout() method returns the sequence in a specified format;
supported formats are listed under the header `ALIGNMENT FORMATS' in this
node.

     $aln->ffmt('fasta');   # set default output format
     print "\n aln in default format:\n", $aln->layout();
     print "\n aln in raw format:\n", $aln->layout("raw");
     print "\n aln in fasta format:\n", $aln->layout("fasta"), "\n";
     print "\n aln in MSF format (via readseq):\n", $aln->layout("MSF"), "\n";

Access by Specifying Boundaries
-------------------------------

   You can calculate slices of alignments in a very flexible way; interval
slices like the intersection of rows 1-3 and columns 1-2 are calculated
using seqs(). Here, intersection means that those elements are returned
that are both in rows 1-3 and in columns 1-2.

     $alnSlice = $aln->seqs(1,3,1,2);  # rows 1-3, columns 1-2
     $alnSlice = $aln->seqs();  # returns the whole alignment

   Here's a diagram illustrating the general case, intersecting rows $y_lo
to $y_hi, and columns $x_lo to $x_hi.

     $x_lo      $x_hi
      :           :
          .. $y_lo ...:...........:.................
      :::::::::::::
      :: SELECTED :
      ::: PART ::::
      :::::::::::::
          .. $y_hi ...:::::::::::::.................
      :           :
                                 Fig.1

   Maximal intervals will be assumed if no parameters are provided.  Per
default, the first row (sequence) has index 1 (not 0), and the first
column has index 1 (not 0). The latter can be modified using numbering().

Access by Index Lists
---------------------

   If you desire non-consecutive row / column elements, you can specify
the indices as lists, one list of desired row indices and one list of
desired column indices.

     $alnSlice = $aln->seqs([1..3], [1,4]);  # rows 1-3, columns 1+4

   Here, letters in columns 2+3 will not be returned. Another example:

     $alnSlice = $aln->seqs([3,2,3,1], [1,3..5]);  # rows 3,2,3,1, cols 1,3..5

   If you specify the empty list ("[]"), all rows/columns will be returned.
The following diagram shows the case where the list of row indices is
[$r1,$r2,$r3,$r4], and the list of column indices is [$c1,$c2,$c3].

     :    :          :
     :    :          :
          ............*....*..........*.............  $r1
     :    :          :
          ............*....*..........*.............  $r2
          ............*....*..........*.............  $r3
     :    :          :
          ............*....*..........*.............  $r4
     :    :          :
     :    :          :
                     $c1  $c2        $c3           Fig.2

   Again, an element is selected for the slice if and only if it lies in
the intersection of a row and a column which are both desired according to
the index lists.

Return Values
-------------

   In the examples above, a string (scalar) is returned; the standard
sequence accessor seqs() always returns a (multi-line) string in a scalar
context. In a list context, it returns an array; each element of such an
array is a reference to another array holding the letters of one sequence,
i.e. one single row.

     @alnSlice = $aln->seqs([1..3], [1,4]);  # rows 1-3, columns 1+4
         for $aref ( @alnSlice ) { print @$aref, "\n"; }

   If you use the result of an accessor or a utility function in the
"-seqs" slot of new(), you may need to force that result into a scalar
context, because the accessor, etc, returns a list in a list context, and
the constructor naturally provides such a list context since it expects a
list of parameters.

     $aln = new Bio::UnivAln(-seqs=>scalar($aln2->seqs()));

   In the example above, the list-context return value of `$aln2->seqs()',
i.e. the list of rows of $aln2, would be fed one by one as additional
parameters into the constructor, if you didn't "protect" it by scalar().
You will be warned about the problem because Bio::UnivAln detects any
named parameters that it can't use.

Access by Id
------------

   (The following access method is currently in alpha status, it may need
some revision until the code is fully released.)

   Any list of desired row/column indices can be replaced by a hash of
desired ids, which are recognized if they are in the object's own list of
row or column ids. You need to pass a reference to a hash that has one
key, "ids", and one value, which is a string containing the ids seperated
by " "(blank) :

     $alnSlice = $aln->seqs({ids=>'SeqA SeqB'},{ids=>'ColA ColB ColC'});

   Row (sequence) ids are automatically extracted when reading fasta files
and Bio::Seq objects. Otherwise, they are set to the default numerical
index list, like (1..20) if the alignment has 20 rows. Since there's
currently no way to extract column (site) ids (none of the supported
formats has this feature), these always hold the default numerical
indices. However, both lists may be set using the accessors row_ids() and
col_ids(). Note that arbitrary numbering schemes can be supported this way.

Access by Selector Function
---------------------------

   Finally, you can specify a function such that seqs() returns exactly
those letters which lie in a row (or column) for which your function
returns true. E.g. has_purine() returns true if the row/column contains A,
a, T, t, R, or r; the following $alnSlice will contain only columns that
have one of these letters in them.

     sub has_purine {
       my $str = join "", @{ $_[0] };
       if ($str =~ /[AaGgRr]+/) {return 1;} else {return 0;}
     }
       $alnSlice = $aln->seqs([1..3], \&has_purine); # rows 1-3, and from these
     # only the columns for which has_purine returns 1

   Similarly, the list of row indices, [1..3], could be replaced by a
function, which is then used to designate the desired rows. (It has the
same role that the expression EXPR has in the Perl code template *grep
EXPR, LIST*, see the perlfunc manpage. Bio::UnivAln also provides the
equivalent to *map EXPR, LIST*; this "Mapping" will be discussed soon.)

   In other words, any list of indices can be replaced by the reference to
a function r or c. The function then selects those elements (*) that lie in
a row or column which meets a criterion, returning true if the criterion
is met, and false otherwise.  If both lists of indices are replaced by
functions, the picture is like this:

     :    :          :
     :    :          :
          ............*....*..........*.............  r(row) = true
     :    :          :
          ............*....*..........*.............  r(row) = true
          ............*....*..........*.............  r(row) = true
     :    :          :
          ............*....*..........*.............  r(row) = true
     :    :          :
     :    :          :
                c(column) c(column)  c(column)
                 = true    = true     = true       Fig.3

   The function out_fasta observes all types of selectors that seqs() does,
and returns the result in fasta format :

     print "\n aln in fasta format:\n", $aln->out_fasta([1..3],\&has_purine), "\n";

Mapping functions onto Sequences and Columns
--------------------------------------------

   You can map a function onto selected rows or columns, and receive the
results as a list:

     @resSlice = $aln->map_r(\&has_purine, [1..3]); # 1,0,1 if row 1+3 has purine
     @resSlice = $aln->map_c(\&has_purine, [1,4]); # 1,0 if column 1 has purine

   As you may expect, maximal index lists (i.e, all rows / all columns)
will be assumed if no second parameter is provided. In the same way as
before, any one if the index lists may be replaced by a hash of ids, or a
selector function. In the section on `User-defined Utility Functions' in
this node, map_r() and map_c() are used to implement user-defined
consensus, reverse, complement, etc.

   By the way, the following map is the same as @alnSlice =
$aln->seqs([1..3]) since mapping the identity function "sub id { return @_
}" to desired row/column subsets and collecting the result is just like
slicing.

     @alnSlice = $aln->map_r(\&id, [ 1..3 ]);

   The number of rows/columns of an alignment can be obtained by using
height() and width() respectively. Ids and descriptions of rows (sequences)
and columns (sites) can be manipulated using row_ids(), col_ids(),
row_descs() and col_descs(). Be *warned* that these accessors just return
a reference to the array of ids/descriptions; if you'd like to process the
array without changing the object's data, you need to create your own
copy. This decision was taken because especially the result of col_ids()
can be huge, and for a lot of applications a deep copy is unnecessary.

Inplace Manipulation
--------------------

   Slices can be applied to the object itself, replacing the old alignment
by a new one that is sliced from the old ('inplace' manipulation).  This
is particularly useful is the alignment is large. The row (sequence) and
column (site) ids are taken over from the old alignment. They are used as
the lookup tables for `Access by Id' in this node, and available via
row_ids() and col_ids().

   The following code sets the "inplace" flag, and overwrites the current
alignment with the rows named A and B, and columns 1-6:

     $aln->inplace(1);
     $aln->seqs({ids=>'A B'},[1..6]);
     $aln->inplace(0);

   'inplace' manipulation is also available for most utility functions
below, with the notable exception of consensus(). A full list is given in
the description of inplace(), see the Appendix.

UTILITY FUNCTIONS LIKE CONSENSUS, AND REVERSE COMPLEMENT
--------------------------------------------------------

   In the following paragraph, Bio::UnivAln's direct support for utility
functions like consensus, (in)variable sites, gap-free sites, reverse,
complement, and reverse complement is explained.

     $resSlice = $aln->consensus();

   calculates the consensus of the columns, i.e. those columns for which
there exists a letter which has an absolute majority of 75% or more. The
letter '!' designates the case that no consensus is given.  To bypass the
default threshold, write

     $resSlice = $aln->consensus(0.6);

   Note that for values smaller or equal to 0.5, two letters may have an
equal (relative) majority, and the tie is currently broken arbitrarily.
Thresholds larger than or equal to 1 imply that the site that has a
consensus letter must be invariant.

     $resSlice = $aln->consensus(1, [1..10]);

   Just like seqs() and map_c()/map_r(), consensus() can be passed a
reference to a hash of desired column ids, a function that selects the
columns, or the desired column indices themselves. (Here, it's columns 1
to 10.  Internally, map_c() is used to implement consensus().)

   The methods var_sites() and invar_sites() are using consensus(), just
checking whether there is a consensus letter ('invariable'), or not
('variable'). Naturally, the default threshold is 1, i.e.  sites must be
truly invariable (100% majority of 1 letter), or truly variable (strictly
less than 100% majority). Per default, var_sites() and invar_sites()
return a *multiline string of rows* (sequences), with elements from the
desired columns (sites) only. They do not return the alignment in a
column-by-column fashion ! Also, don't be confused by the possibilty to
specify a list of desired row indices / ids, or a selector function: It
just constrains the output further, without influencing which columns are
selected. (Internally, seqs() is used to implement these functions; it is
passed a row selector, and a function that returns true if there is a
consensus letter.)

     $resSlice = $aln->var_sites();
     $resSlice = $aln->invar_sites();
     $resSlice = $aln->var_sites(0.6, [1,3]); # no columns with >= 60% majority
                                        # of one letter; also, print rows 1+3 only
     $resSlice = $aln->invar_sites(0.6, [1,3]);  # only columns with >= 60% maj.
     $resSlice = $aln->no_allgap_sites([1,3]); # exclude sites that only have gaps
     $resSlice = $aln->gap_free_sites([1,3]); # exclude sites that have >= 1 gaps

   In a similar fashion, the last example selects gap-free columns, and
from those only prints the elements that happen to be in rows 1+3.  All
these utilities support `Inplace Manipulation' in this node:

     $aln->inplace(1);
     $aln->var_sites(0.6, {ids=>'1 2'});
     $aln->inplace(0);

   The utilities reverse(), complement(), and revcom() also allow for
`Inplace Manipulation' in this node, and again you can specify the rows
which shall form the new alignment by overwriting the old, or be returned
as reverse'd, complement'ed, or reverse complement'ed :

     $resSlice = $aln->reverse([1,3]);
     $resSlice = $aln->complement([1,3]);
     $resSlice = $aln->revcom([1,3]);

   If an inplace manipulation reverses column order, e.g. in the case of
reverse(), this will be reflected in the column ids available via
col_ids().  Note that complement is defined according to the IUPAC code,
using the same substitutions that Bio::Seq uses, such that results
obtained for e.g. Amino Acid sequences are probably nonsensical.

   For all functions that have "sites" in their name, a corresponding
"inds" function is available that returns the relevant array of indices
instead of the sites themselves:

     $indices = $aln->var_inds(); # array of indices of the variable sites
     $indices = $aln->no_allgap_inds([1,3]);

   Finally, the original sequences (without gaps) are available via
remove_gaps().

     $some_original_sequences = $aln->remove_gaps([1,3]);

   In a list context, all these utility functions return an array of array
references, just like seqs(); the exception is consensus(), which then
returns a simple array of consensus letters.

ALIGNMENT FORMATS
-----------------

   The directly supported formats are fasta and raw (1 line in file -> 1
sequence, where "\n" (newline) is the delimiter.) If available (see
`INSTALLATION' in this node), readseq is used to parse and write
PIR/CODATA, MSF/GCG and PAUP/NEXUS formats; ASN.1 does not seem to work
reliably. Clustal is used to parse in clustal format, if available.

ADVANCED STUFF
--------------

   An exhaustive list of accessors and methods is given in the appendix.
E.g., Alignments may be copied using copy(), and compared for equality
modulo gaps with equal_nogaps().

   Bio::UnivAln doesn't really care whether the sequences passed in are
indeed from an alignment (i.e. have the same length); sequence bags (i.e.
multisets of sequences where the same element may occur more than once) are
therefore handled, too. However, you need to be careful with some methods
(e.g. the accessor seqs(), and width()) because their default behavior may
depend on inspecting the first sequence only (or the first requested
sequence, if this information is available - new feature in 1.006) : If
you use seqs() on a sequence bag, and don't provide the number of columns
explicitly, you may be surprised to find out that the length of the first
sequence is used as the default length, and not the length of the longest
sequence. width() uses the same heuristic.

   You can add gap symbols to the elements of a multiset so that each
element takes the length of the longest sequence by calling
equalize_length(); you can even pad more gap characters by specifying the
new width yourself, as an argument to equalize_length().

   If you need to have the alignment in an intermediate form, i.e.
neither an array of array references, nor a single multiline string, but
an array of strings, just request the output as a multiline string, and
split it on "\n". For example, to just extract a single column, you can do

     @col = split "\n", $aln->seqs([],[$colindex]);

   Checking an alignment for characters that should not be there according
to the Alignment Type is currently not well-supported; see alphabet_check()
for a _preliminary_ way of doing manual checkup, though.

   The hash referenced by $names stores {loc,name} pairs of other database
locations and corresponding names where the alignment is located.
Currently, loc and name must both be set as text, and must consist
entirely of a string matching the regexp /^[A-Za-z]\w*$/.  That is, they
must be a single "word" of at least one character, without a leading
underscore.  This restriction is not enforced, but code which deviates is
subject to break in future releases.  Note also that the object may place
any other sort of items in the name string, so users of this hash should
not rely on accessing entries conforming the requirements above.

Alignment Types
---------------

   The supported sequence types and corresponding alphabets are the same
as reported in the documentation of the Bio::Seq object: "dna", "rna", and
"amino". They are carried along without much checking, etc.

User-defined Utility Functions
------------------------------

   Here are some user-defined auxiliary functions which can be applied to
rows and columns of an alignment; this technique can be used if no
appropriate built-in functions are available, or if you don't want to use
them.

   maj_dominance returns false if all letters in a column/row are the same.

     sub maj_dominance {
       my $str = join "", @{ $_[0] };
       my $first_res = @{ $_[0] }[0];
       $str =~ s/$first_res//g;
       if ($str) {return 0;} else {return 1;}
     }

   consensus returns the letter that has the (relative) majority among all
residues, if it exceeds a certain threshold. (For simplicity, the threshold
is hard-wired.)

     sub consensus {
       my @chars = @{ $_[0] };
       my %temp = ();
       my $threshold = 0.34;  # more than 1/3
       my @list = sort { $temp{$a}<=>$temp{$b} }
                       grep ++$temp{$_} >= $threshold * ($#chars+1), @chars;
         # In case of a tie, it's not specified which residue is in $list[-1]
       return (defined($list[-1]) ? $list[-1] : '!');
     }

   reverse_ and complement implement reversing a sequence (note the
underscore; I'm looking for better ways to implement function passing),
and complementing it according to IUPAC conventions.

     sub reverse_ {
       return [ reverse @{ $_[0] } ];
     }
     sub complement {
       my $str = join "", @{ $_[0] };
       $str =~ tr/acgtrymkswhbvdnxACGTRYMKSWHBVDNX/tgcayrkmswdvbhnxTGCAYRKMSWDVBHNX/;
       return [ split "", $str ];
     }

   Here, the functions above are applied:

     @resSlice = $aln->map_c(\&maj_dominance);
     print "\nDominated sites:\n", @resSlice, "\n";

     @resSlice = $aln->map_c(\&consensus);
     @resSlice = $aln->map_c(\&consensus, \&has_purine);
     print "\nConsensus of the columns that have purine\n", @resSlice, "\n";

     @resSlice = $aln->map_r(\&reverse_);

     @resSlice = $aln->map_r(\&complement);

   You can also parametrize your functions by using "closures" (See
"Programming Perl", 2nd Ed., p.253). Basically, you set up a function that
has the parameter built into it, and pass around the reference to that
function. Here's a function that does the set-up:

     sub _setup_consensus_with_threshold {
       my $threshold = shift;
       return sub {
         my @chars = @{ $_[0] };
         my %temp = ();
         my @list = sort { $temp{$a}<=>$temp{$b} }
                         grep ++$temp{$_} >= $threshold * ($#chars+1), @chars;
           # In case of a tie, it's not specified which residue is in $list[-1]
         return (defined($list[-1]) ? $list[-1] : 'N');
       }
     }

   Here, you create an instance of the function, incl. the parameter.
$consensus holds a reference to the new instance.

     my $consensus = _setup_consensus_with_threshold(0.75);

   and finally, you pass the reference to the function around, e.g. to
map_c().

     @resSlice = $aln->map_c(\&$consensus);

   (You can do pretty cute tricks using closures, e.g. you can set a
counter to 1 in the setup function, and increment it in the "real"
function.)

Bio::UnivAln Guts
=================

   Currently, the object hash has the following keys. This may be subject
to change; in particular the alignment data may at some point be stored
more efficiently in a PDL (Perl Data Language) array.

     $self->{'seqs'}   : An array of array references, each of which holds
                       one sequence of the alignment
     $self->{'id'}     : String specifying the ID; shall be in \w+ (i.e. composed
                       of characters in [a-zA-Z_0-9]; only \S+ is enforced, though)
     $self->{'desc'}   : String giving a description, (later) to be formatted
                       according to $descffmt
     $self->{'names'}  : A reference to a hash which stores {loc,name} pairs of
                       other database locations and corresponding names where
                       the alignment is located.
     $self->{'row_ids'}: A reference to an array which stores row (sequence) ids
     $self->{'col_ids'}: Same as $self->{'row_ids'}, for the columns (sites)
     $self->{'row_descs'}: A reference to an array which stores row (sequence)
                       descriptions
     $self->{'col_descs'}: Same as $self->{'row_descs'}, for the columns (sites)
     $self->{'numbering'}: The offset of the first column, an integer
     $self->{'type'}   : The type of the alignment, concatenated from the molecule
                       type (see L<Alignment Types>) and a flag that is not
                       currently used, but intended to flag sequence bags
     $self->{'ffmt'}   : alignment format, see L<ALIGNMENT FORMATS>.
     $self->{'descffmt'}: format of $desc; right now this should be ``raw''
                       or ``fasta'' which just implies that no specific
                       format is being followed, any text is allowed
                       excluding ``\n''(newline). More support is planned.
     $self->{'inplace'}: Flag which is set to true if accessors (and utility
                       functions) should make the modification to the object
                       itself, and just return true on success. (See inplace().)

   Some more helpful comments...  In Perl, false is 0 or "", true is
everything else.  Not all internal functions have a POD/HTML documentation.
If you read the code of this module, you need to be familiar with map and
grep...

TO-DO
=====

   Soon:

   Better handling of access, copying and slicing of `$self->{'row_ids'}',
etc.  Add pointer to a UnivAln demo page based on the draft at
http://www.techfak.uni-bielefeld.de/bcd/Perl/Bio/Docs/phylosnapshot.html.
Fix alphabet_check() (current workaround cannot be generalized), Fix
UnivAlnAlph{UnivAlnType{"unknown"}} (current setting is not so nice;
what's the easiest way to set it to all word characters ?), Support more
formats, especially Nexus, Improved sequence alphabet support; not just
providing a function alphabet_check() for manual checking.  Then, maybe
use strings to represent alphabets.  Test and document aln() for returning
a slice as an alignment.

   Later:

   Validity marker for correctly initialized/manipulated objects.  Assign
_unique_ IDs if none are provided.  Functions like has_seqs(), etc.  Using
`undef' during initialization, and functions for regaining such a state.
Use Perl Data Language ?!

DISCLAIMER
==========

   How is this for a maximum of disclaiming warranty ? In short, I'm
developing this module in my spare time and it's for free, don't sue me :-)

     IN NO EVENT SHALL THE GLOBEWIDE NETWORK ACADEMY, THE VIRTUAL SCHOOL OF NATURAL
     SCIENCES, THE AUTHOR OR THE UNIVERSITY OF BIELEFELD BE LIABLE TO ANY PARTY
     FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
     OUT OF THE USE OF THIS CODE, EVEN IF THE GLOBEWIDE NETWORK ACADEMY,
     THE VIRTUAL SCHOOL OF NATURAL SCIENCES, THE AUTHOR OR THE UNIVERSITY OF
     BIELEFELD HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

     THE GLOBEWIDE NETWORK ACADEMY, THE VIRTUAL SCHOOL OF NATURAL SCIENCES, THE
     AUTHOR AND THE UNIVERSITY OF BIELEFELD SPECIFICALLY DISCLAIM ANY WARRANTIES,
     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
     AND FITNESS FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN
     "AS IS" BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCEE,
     SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Copyright (c) 1996, 1997, 1998 Georg Fuellen. All Rights Reserved.
Some pieces of the code were contributed by Steven E. Brenner, Richard
Resnick and Chris Dagdigian. Thanks !!!!

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules.  Send your comments and suggestions preferably to one of
the Bioperl mailing lists.  Your participation is much appreciated.

     bioperl-l@bioperl.org          - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR
======

   Georg Fuellen

   Technische Fakultaet - AG Praktische Informatik, Universitaet Bielefeld,
D-33501 Bielefeld, Germany, georg.fuellen@uni-bielefeld.de

   http://www.techfak.uni-bielefeld.de/~fuellen/

ACKNOWLEDGEMENTS
================

   Steven E. Brenner, Steve A. Chervitz, Michael Constant, Richard Resnick,
Chris Dagdigian, Lew Gramer [more to follow]

SEE ALSO
========

     Bio::Seq.pm - The biosequence object

     http://bio.perl.org/Projects/modules.html  - Online module documentation
     http://bio.perl.org/Projects/SeqAlign/     - Bioperl sequence alignment project
     http://bio.perl.org/                       - Bioperl Project Homepage

REFERENCES
==========

   If you'd like to acknowledge use of Bio::UnivAln in your work, please
cite

   Fuellen, G. (1997). Bio::UnivAln - bioperl alignment object
[WWW-Document].  URL
http://www.techfak.uni-bielefeld.de/bcd/Perl/Bio/welcome.html

   And please drop me a note :-) An article for the Perl Journal is
planned. The page is mirrored at

   http://merlin.mbcr.bcm.tmc.edu:8001/bcd/Perl/Bio/welcome.html
http://www.biotech.ist.unige.it/bcd/Perl/Bio/welcome.html

REVISION HISTORY
================

   Version 1.000 on 12 Feb 1997.

   Version 1.001 on 19 Feb 1997. Fixed a bug that triggered _rowbounds()
and _colbounds() to use maximal index lists whenever the first index in an
index list was 0. New example in POD:

     $aln = new Bio::UnivAln(-seqs=>scalar($aln2->var_sites()));

   Internal: Now avoiding any global parameter passing by using closures,
for the utility functions.

   Version 1.002 on 21 Feb 1997. Renamed the module to UnivAln, see the
discussion (Feb 1997) in the vsns-bcd-perl mailing list archive.  Fixed
hopefully all problems in out_graph(), all of them triggered by
bugs/features of PGPLOT.

   Version 1.003 on 25 Feb 1997. Added POD on using closures.  Moved
out_graph() into the cgi-script t/univaln.cgi (this is alpha-code !)  so
that "use PGPLOT" is no longer required.

   Version 1.004 on 13 Mar 1997. Fixed bug with reading fasta files.
Changed file format identifiers "Fasta" and "Raw" to "fasta" and "raw".
Added support for arbitrary numeration schemes by providing access by
name/id for rows (sequences) and columns (sites).  Made _arys() and
_strs() accept same row/column designations like seqs().  Added 'inplace'
manipulation for slicing and most utilities.  Improved speed a little.
Deriving default description string from file name, if available.

   Version 1.005 on 18 Jun 1997. Using simple filename ("basename") as
default decription. Changed type identifiers "Unknown", "Dna", "Rna",
"Amino" to "unknown", "dna", "rna", "amino". The old acronyms should still
be supported for the forseeable future.

   Version 1.006 on 15 Dec 1997. Added function no_allgap_sites();
out_fasta() now accepts same row/column designations like seqs(). For
advanced users: the width() of sequence bags can now be controlled by
supplying the index of the row whose width is taken - by default the width
of the first row is used.

   Version 1.007 on 15 Mar 1998.  * Added functions that return indices
instead of actual sequence data: var_inds(), invar_inds(),
gap_free_inds(), unknown_free_inds(), special_free_inds() and
no_allgap_inds() return the indices of (in)variable, gap-free,
unknown-free, gap+unknown-free and non-gap-only columns; they are the
counterparts of var_sites(), etc.  * Added remove_gaps() to return
ungapped (original) sequence data * Added equal_no_gaps() to check for
equality ignoring gaps * Added equalize_lengths() for padding a sequence
bag with gaps such that all rows have equal length (current procedure is
slow) * The default id is now "_" (was: "No_Id_Given") * Internal
functions _rowbounds() and _colbounds() now return indices from the user's
perspective, but WITHOUT substracting offset.  Instead, all functions
subtract offset after applying _rowbounds()/_colbounds()

   Version 1.008 on 13 May 1998.  * Added readseq conversion support,
making it possible to read and write the following formats: MSF, Paup,
PIR/Codata, ASN.1. (ASN.1 was not parsed successfully: readseq seems to be
unable to read in its own ASN.1 output). Technically, readseq is now used
to parse files that have been processed as "raw" before; now "raw" format
is recognized using the expression
/^[A-Z_0-9$_GAP_SYMBOL$_UNKN_SYMBOL\s]+$/im, i.e. the file may only have
alphanumerical characters, gap and unknown-symbol, and whitespace. If
commata, etc, are detected, readseq is used for parsing.  Readseq itself
seems to be unable to detect "raw" format in some cases, causing weird
results.  * Added Clustal support for parsing; still to be tested and
documented.

   Version 1.009 on 25 May 1998.  * The module can now be "built" in the
standard way (perl Makefile.PL, etc).

APPENDIX
========

   Please note that functions starting with an underscore ("_") are
intended for internal use only: Use them only if you know what you're
doing :-)

_initialize()
-------------

     Usage    : n/a (internal function)
     Function : Assigns initial parameters to a blessed object.
     Returns  : 1 on success
     Argument : As Bio::UnivAln->new, allows for named or listed parameters.
                See ->new for the legal types of these values.

_rearrange()
------------

     Usage    : n/a (internal function)
     Function : Rearranges named parameters to requested order.
     Returns  : @params - an array of parameters in the requested order.
     Argument : $order : a reference to an array which describes the desired
                         order of the named parameters.
                @param : an array of parameters, either as a list (in
                         which case the function simply returns the list),
                         or as an associative array (in which case the
                         function sorts the values according to @{$order}
                         and returns that new array.

_rowbounds()
------------

     Usage    : $corrected_bounds = $aln->_rowbounds($uncorrected_bounds);
     Function : create default row index list if necessary,
                create row index list if specified by a hash of ids or
                by a selector function that acts on rows and returns true/false,
                check row index list for bounds errors,
                NO LONGER DONE IN VERSION 1.007 AND HIGHER: substract offset of 1.
     Returns  : reference to corrected row index list
     Argument : reference to uncorrected row index list

_colbounds()
------------

     Usage    : $corrected_bounds = $aln->_colbounds($uncorrected_bounds);
     Function : create default column index list if necessary,
                create column index list if specified by a hash of ids or
                by a selector function that acts on columns and returns true/false,
                check column index list for bounds errors,
                NOT IN 1.007 and higher: substract offset (according to numbering scheme).
     Returns  : reference to corrected column index list
     Argument : reference to uncorrected column index list
                reference to row index list: its first row is used to
                provide the width of the alignment considered, which matters
                if the alignment is really a sequence bag

_fixbounds()
------------

     Usage    : ($corrected_rowbounds,$corrected_colbounds) =
                   $aln->_fixbounds($uncorrected_rowbounds,$uncorrected_colbounds);
                        OR
                ($corrected_rowbounds,$corrected_colbounds) =
                   $aln->_fixbounds($firstpos1,$lastpos1,$firstpos2,$lastpos2)
     Function : Convert unfixed index list information into the standard internal
                one, allowing as input either max. 2 references or max. 4 boundary
                coordinates (2 coord. for row indices and 2 for column indices).
                Call functions to create maximal default index lists if needed,
                to create index lists if specified by a hash of ids or by a selector
                function that acts on rows/columns and returns true/false,
                to check index lists for bounds errors, and to substract offsets.
     Returns  : 2 references to corrected index lists
     Argument : EITHER max. 2 references to uncorrected index lists,
                OR max. 4 boundary coordinates (integers)

_select()
---------

     Usage    : @alnSlice = $aln->_select($rrowsel2,$rcolsel2);
     Function : select elements from the 2-dimensional array $self->{'seqs'}
                using index lists
     Returns  : array of references to array of characters
     Argument : 2 index lists, one for the rows and one for the columns,
     Comment  : Here's a diagram of dependencies of some methods relying on _select:

     seqs()
                           /    |
                         |/_   \|/
                     _arys() <-- _strs()
                       |
                      \|/
                    _select()

_arys()
-------

     Usage    : @alnSlice = $aln->_arys([$row1,$row2,$rowx],[col1,$col2,$colx])
                  (other usages see seqs())
     Function : Same as seqs(), except that an array is returned always
     Returns  : array of references to array of characters
     Argument : Same as seqs()

_strs()
-------

     Usage    : $alnSlice = $aln->_strs([$row1,$row2,$rowx],[col1,$col2,$colx])
                  (other usages see seqs())
     Function : Same as seqs(), except that a multiline string is returned always
     Returns  : multiline string (including newline characters)
     Argument : Same as seqs()

seqs()
------

     Usage    : (1) $alnSlice = $aln->seqs($firstpos1,$lastpos1,$firstpos2,$lastpos2)
                (2) $alnSlice = $aln->seqs([$row1,$row2,$rowx],[col1,$col2,$colx])
                (3) $alnSlice = $aln->seqs(\&function_of_row,\&function_of_column)
                (4) $alnSlice = $aln->seqs({ids=>'r1 r2 r3'},{ids=>'c1 c2 c3'})
                   [ (2),(3) and (4) can be intermixed ]
     Function : (1) Returns part of an alignment, from row $firstpos1 to row
                $lastpos1, and from column $firstpos2 to column $lastpos2
                Missing parameters are replaced by default (maximal possible)
                values, where the length of the first row of the _returned_ (*)
                `alignment' determines the default length in case the alignment is
                really a sequence bag. ((*) is a new feature in 1.006.)
                (2) Returns part of an alignment, i.e. those elements that lie
                in a row designated by an index from the first list
                ([$row1,$row2,$rowx]), and at the same time lie in a column
                designated in the second list ([col1,$col2,$colx]).
                The empty list (``[]'') is replaced by default (maximal possible)
                values, where the length of the first row of the _returned_
                `alignment' determines the default length in case the alignment is
                really a sequence bag. (Note that the first element
                of rows/columns has index 1 per default.)
                (3) Instead of an index list, a function acting on a row / column
                may be supplied; whenever the function returns true, the
                row / column is designated.
                (4) Instead of an index list, a hash of ids may be supplied;
                the ids are looked up in the alignment's list of row (sequence)
                ids / list of column (site) ids. The former list may be set
                during the construction of the alignment (e.g. it may be read
                from the fasta file, or the Bio::Seq objects), or it may be
                manipulated using row_ids(). col_ids() sets the the latter list.
     Returns  : in a scalar context: multiline string (including newline characters)
                in an array context: array of references to arrays of characters
     Argument : (1) $firstpos1,$lastpos1,$firstpos2,$lastpos2 (all integers; note
                that the first element of rows/columns has index 1 per default.)
                (2-4) 2 selectors, one for the rows and one for the columns,
                each of which may be a reference to a list of indices, or a
                reference to a hash that has the format ``{ids=>'id1 id2 idx'}''
                where ids is the mandatory key, and the value is a string
                containing the desired ids, seperated by `` '' (space), or a
                function that acts on a list and returns true/false.

_map_r()
--------

     Usage    : n/a (internal function)
     Function : apply a row function to selected rows,
                then return the list of all return values
     Returns  : list of all return values
     Argument : $rowf: Reference to the function that is applied to selected rows,
                its results are put into a list and returned.
                $rrowsel: Reference to the selector designating the rows
                to which rowf is applied, as in cases (2)-(4) in seqs().

_map_c()
--------

     Usage    : n/a (internal function)
     Function : apply a column function to selected columns,
                then return the list of all return values
     Returns  : list of all return values
     Argument : analogous to _map_r()

map_r()
-------

     Usage    : @resSlice = $aln->map_r($rowf,$rrowsel);
     Function : apply a function to selected rows,
                then return the list of all return values
     Returns  : list of all return values
     Argument : $rowf: Reference to the function that is applied to selected rows,
                its results are put into a list and returned.
                $rrowsel: Reference to the selector designating the rows
                to which rowf is applied, as in cases (2)-(4) in seqs().

map_c()
-------

     Usage    : @resSlice = $aln->map_c($colf,$rcolsel,$rrowsel);
     Function : apply a function to selected columns,
                then return the list of all return values
     Returns  : list of all return values
     Argument : $colf: Reference to the function that is applied to selected
                columns, its results are put into a list and returned.
                $rcolsel: Reference to the selector designating the columns
                to which colf is applied, as in cases (2)-(4) in seqs().
                $rrowsel: NOT used as a selector, but as a hint for
                determining the width of a sequence bag if $rcolsel is undef:
                The last index of the first row specified by $rrowsel is
                taken as the maximum column index.

consensus()
-----------

     Usage    : $cons_letters = $aln->consensus($threshold,$rcolsel);
     Function : return the consensus of a (subset of) the columns; the letter '!'
                ($_NO_CONSENSUS_SYMBOL) indicates that no consensus letter exists
     Returns  : in a scalar context: string of consensus letters
                in an array context: array of consensus letters
     Argument : $threshold: A letter is considered consensus of a column
                if the fraction of the letters in the column that form a
                (relative) majority is >= $threshold. Ties between 2 letters with
                an equal relative majority are broken arbitrarily.
                The default value is 0.75.
                $rcolsel: Reference to the selector designating the columns
                of which the consensus is calculated, as in cases (2)-(4) in seqs().

var_sites()
-----------

     Usage    : $resSlice = $aln->var_sites($threshold,$rrowsel);
     Function : return the variable sites of an alignment
     Returns  : in a scalar context: multiline string (including newline characters)
                in an array context: array of references to arrays of characters
     Argument : $threshold: A column is considered variable
                if the fraction of the letters in the column that form a
                (relative) majority is NOT >= $threshold.
                The default $threshold is 1, i.e. only constant, INvariable columns
                are excluded.
                $rrowsel: Reference to the selector designating the rows
                of which in turn the letters in the variable columns are printed,
                as in cases (2)-(4) in seqs(). $rrowsel DOES NOT influence the
                calculation of the variable sites, it just constrains the output
                further !

var_inds()
----------

     Usage    : $indices = $aln->var_inds($threshold,$rrowsel);
     Function : return the _indices_ of the variable sites of an alignment
     Returns  : reference to array of indices
     Argument : $threshold: A column is considered variable
                if the fraction of the letters in the column that form a
                (relative) majority is NOT >= $threshold.
                The default $threshold is 1, i.e. only constant, INvariable columns
                are excluded.
                $rrowsel: the first row in $rrowsel is used for
                determining the width of a sequence bag. In other words,
                the last index of the first row specified by $rrowsel is
                taken as the maximum column index.

invar_sites()
-------------

     Usage    : $resSlice = $aln->invar_sites($threshold,$rrowsel);
     Function : return the INvariable columns of an alignment
     Returns  : in a scalar context: multiline string (including newline characters)
                in an array context: array of references to arrays of characters
     Argument : $threshold: A column is considered INvariable
                if the fraction of the letters in the column that form a
                (relative) majority is >= $threshold.
                The default $threshold is 1, i.e. no variability is allowed.
                $rrowsel: see var_sites()

invar_inds()
------------

     Comment  : This is the indices-returning version of invar_sites(),
                cf. var_sites() and var_inds().

gap_free_sites()
----------------

     Usage    : $resSlice = $aln->gap_free_sites($rrowsel);
     Function : return the gap-free columns of an alignment.
     Returns  : in a scalar context: multiline string (including newline characters)
                in an array context: array of references to arrays of characters
     Argument : $rrowsel: see var_sites()

gap_free_inds()
---------------

     Comment  : This is the indices-returning version of gap_free_sites(),
                cf. var_sites() and var_inds().

unknown_free_sites()
--------------------

     Usage    : $resSlice = $aln->unknown_free_sites($rrowsel);
     Function : return the unknown-free columns of an alignment.
     Returns  : in a scalar context: multiline string (including newline characters)
                in an array context: array of references to arrays of characters
     Argument : $rrowsel: see var_sites()

unknown_free_inds()
-------------------

     Comment  : This is the indices-returning version of unknown_free_sites(),
                cf. var_sites() and var_inds().

no_allgap_sites()
-----------------

     Usage    : $resSlice = $aln->no_allgap_sites($rrowsel);
     Function : return the columns which do not have gaps only, of an alignment.
     Returns  : in a scalar context: multiline string (including newline characters)
                in an array context: array of references to arrays of characters
     Argument : $rrowsel: see var_sites()

no_allgap_inds()
----------------

     Comment  : This is the indices-returning version of no_allgap_sites(),
                cf. var_sites() and var_inds().

special_free_sites()
--------------------

     Usage    : $resSlice = $aln->special_free_sites($rrowsel);
     Function : return the special-free (neither gap nor unknown-symbols) columns
                of an alignment.
     Returns  : in a scalar context: multiline string (including newline characters)
                in an array context: array of references to arrays of characters
     Argument : $rrowsel: see var_sites()

special_free_inds()
-------------------

     Comment  : This is the indices-returning version of special_free_sites(),
                cf. var_sites() and var_inds().

reverse()
---------

     Usage    : $resSlice = $aln->reverse($rrowsel);
     Function : return the rows of an alignment, in reversed form (right->left)
     Returns  : in a scalar context: multiline string (including newline characters)
                in an array context: array of references to arrays of characters
     Argument : $rrowsel: Reference to the selector designating the rows
                which are returned in reversed form, as in cases (2)-(4) in seqs().

remove_gaps()
-------------

     Usage    : $resSlice = $aln->remove_gaps($rrowsel);
     Function : return the rows of an alignment, gaps removed (i.e. the original
                sequences)
     Returns  : in a scalar context: multiline string (including newline characters)
                in an array context: array of references to arrays of characters
     Argument : $rrowsel: Reference to the selector designating the rows
                which are returned without gaps, as in cases (2)-(4) in seqs().

complement()
------------

     Usage    : $resSlice = $aln->complement($rrowsel);
     Function : return the rows of an alignment, in complemented form
                In the case of dna/rna, the complement is given according to the
                IUPAC code; in other cases the result is currently calculated in the
                same way and probably meaningless
     Returns  : in a scalar context: multiline string (including newline characters)
                in an array context: array of references to arrays of characters
     Argument : $rrowsel: see reverse()

revcom()
--------

     Usage    : $aln->revcom($rrowsel);
     Function : return the rows of an alignment, in reversed complement form
                In the case of dna/rna, the complement is given according to the
                IUPAC code; otherwise the result is currently calculated in the
                same way and probably nonsensical.
     Returns  : in a scalar context: multiline string (including newline characters)
                in an array context: array of references to arrays of characters
     Argument : $rrowsel: see reverse()

equal_nogaps()
--------------

     Usage    : $aln->equal_nogaps($other_aln);
     Function : checks whether two alignments have the same original sequences
                (i.e. gaps are removed and the rows are compared for equality)
     Returns  : 1 if alignments are equal modulo gaps, 0 otherwise
     Argument : $other_aln: the other alignment

equalize_lengths()
------------------

     Usage    : $aln->equalize_lengths($width);
     Function : modifies the alignment / sequence bag such that all rows
                have length $width; in the case of sequence bags, this
                is a primitive way to obtain a true alignment with
                rows of equal length
                * The current procedure is straightforward but slow *
     Returns  : 1 if alignments are equal modulo gaps, 0 otherwise
     Argument : $width: the length until which sequences should be padded;
                per default the length of the longest row is taken

_seqs()
-------

     Usage    : @oldSeqs = $aln->_seqs(@sequences,$start)
                @oldSeqs = $aln->_seqs($sequences,$start)
     Function : to APPEND/OVERWRITE sequences to an alignment
     Returns  : old list of sequences, i.e. ($self->{'seqs'})
     Argument : 1. EITHER a reference to a list of either Bio::Seq objects, or
                   arrays of letters, or strings, or any mix of these,
                   OR a single (multi-line) string
                2. $rrowsel: Reference to the selector designating the rows
                   which shall be appended/overwritten (feature in alpha status)

id()
----

     Usage    : $aln_id = $aln->id();
                $aln->id($id_string);
     Function : Accessor, also sets field if an ID is passed in.
     Returns  : (original) ID value
     Argument : sequence string with no whitespace

desc()
------

     Usage    : $aln_desc = $aln->desc();
                $aln->desc($desc_string);
     Function : Accessor, also sets field if a description string is passed in.
     Returns  : (original) description value
     Argument : sequence string

names()
-------

     Usage    : %names = $aln->names;
                $aln->names($hash_ref)
     Function : Accessor, also sets field if names hash is passed in.
                The names hash is 'human-readable' data; each key is a
                location (whether it be URL, database, database query, etc.)
                and each value is the id at that location.
     Returns  : (original) names hash value
     Argument : reference to a hash

row_ids()
---------

     Usage    : $row_ids = $aln->row_ids();
                $aln->row_ids($row_ids);
     Function : Accessor, also sets field.
     Returns  : A reference to the (original) array of row (sequence) ids
     Argument : A reference to an array of row (sequence) ids

col_ids()
---------

     Usage    : $col_ids = $aln->col_ids();
                $aln->col_ids($col_ids);
     Function : Accessor, also sets field.
     Returns  : A reference to the (original) array of column (site) ids
     Argument : A reference to an array of column (site) ids

row_descs()
-----------

     Usage    : $row_descs = $aln->row_descs();
                $aln->row_descs($row_descs);
     Function : Accessor, also sets field.
     Returns  : A reference to the (original) array of row (sequence) descriptions
     Argument : A reference to an array of row (sequence) descriptions

col_descs()
-----------

     Usage    : $col_descs = $aln->col_descs();
                $aln->col_descs($col_descs);
     Function : Accessor, also sets field.
     Returns  : A reference to the (original) array of column (site) descriptions
     Argument : A reference to an array of column (site) descriptions

numbering()
-----------

     Usage    : $num_start = $aln->numbering;
                $aln->numbering($value);
     Function : Accessor, also sets field if a new numbering scheme is passed in.
     Returns  : (original) numbering value
     Argument : number that is used as the offset of the first column

type()
------

     Usage    : $aln_type = $aln->type;
                $aln->type($value); # May be dangerous !
     Function : Accessor, also sets field if a new type is passed in.
                The latter is considered dangerous !
     Returns  : (original) type value
     Argument : new type, see the list %UnivAlnTypes in the code
                (currently, ``dna'', ``rna'', ``amino'')

ffmt()
------

     Usage    : $ffmt = $aln->ffmt;
                $aln->ffmt($value);
     Function : Accessor, also sets field if a new format acronym is passed in.
                This can be done before reading from a file, so that
                the presumably correct parsing routine is called, or
                the value can be set before writing the object using
                layout(), so that layout uses a specified default format.
     Returns  : (original) format acronym
     Argument : string describing the format, see ``Alignment Formats''

inplace()
---------

     Usage    : $inplace = $aln->inplace();
                $aln->inplace($value);
     Function : Accessor, also sets field if a value is passed in.
                'inplace' is a flag which is set to true if accessors and
                functions should make the modification to the object itself,
                and just return true on success. Currently, inplace manipulation
                is supported for seqs(), _arys(), _strs(), remove_gaps(),
                var_sites(), invar_sites(), gap_free_sites(), no_allgap_sites(),
                reverse(), complement(), and revcom() (reverse complement).
     Returns  : (original) inplace value
     Argument : currently 0 or 1

width()
-------

     Usage    : $width = $aln->width();
     Function : number of columns (of the first row per default)
     Returns  : number of columns (of the first row per default)
     Argument : row

height()
--------

     Usage    : $height = $aln->height();
     Function : number of rows (sequences)
     Returns  : number of rows (sequences)
     Argument : ./.

alphabet_check()
----------------

     Usage    : @offendig_characters = $aln->alphabet_check($rowsel);
     Function : Check rows of the alignment for ``offending characters'', i.e.
                characters that are not (currently) expected to be found in the
                aligned sequences, because they're not in the default alphabet
                that belongs to the specified L<Alignment Type>.
                Currently, the Alignment Type can only be set explicitly
                via the constructor, or accessor. Since the default alphabet
                is not the IUPAC code (e.g. just A,C,G,T,-,? in case of DNA),
                this is just a proof of concept.
     Returns  : an array containing the offending characters, one string per row
     Argument : $rrowsel: Reference to the selector designating the rows
                to which the check is applied, as in cases (2)-(4) in seqs().

_file_read()
------------

     Usage    : n/a (internal function)
     Function : Read data from file, and call the parsing system to store data
                into the object fields
     Returns  : 1 on success
     Argument : filename, and (optionally) the format if known.

_parse()
--------

     Usage    : $aln->_parse($ent,[$ffmt]);
     Function : Parses $ent into the object fields, according to
                $ffmt or $self->{'ffmt'}.
     Returns  : 1 on success
     Argument : the prospective alignment to be parsed,
                and optionally its format so that it doesn't need to be estimated
                Note that ``raw'' is not estimated in a reliable way by readseq
                if readseq is installed; I presume it is then estimated only if
                the sequence(s) are longer than 111 basepairs

_parse_unknown()
----------------

     Usage    : $aln->_parse_unknown($ent);
     Function : tries to figure out the format of $ent and then
                calls the appropriate function to parse it into $self->{'seqs'}.
     Returns  : 1 on success
     Argument : $ent : the rough multi-line string to be parsed

_parse_bad()
------------

     Usage    : $aln->_parse_bad;
     Function : Carp on the bad data that the user gave us.
     Returns  : undef
     Argument : (multiline) string that cannot be parsed

_parse_readseq()
----------------

     Usage    : $aln->_parse_readseq;
     Function : Try readseq to parse data.
     Returns  : 1 on success
     Argument : $ent : the rough multi-line string to be parsed

_parse_raw()
------------

     Usage    : $aln->_parse_raw;
     Function : parses $ent into the $self->{'seqs'} field, using raw
                file format.
     Returns  : 1 on success
     Argument : (multiline) string to be parsed

_parse_fasta()
--------------

     Usage    : $aln->_parse_fasta;
     Function : parses $ent into the 'seqs' field, using fasta
                file format.
     Returns  : 1 on success
     Argument : (multiline) string to be parsed

copy()
------

     Usage    : $copyOfObj = $myUnivAln->copy;
     Function : Returns an identical copy of the object.
     Returns  : Bio::UnivAln
     Argument : n/a

layout()
--------

     Usage    : $aln->layout($format);
     Function : Returns the alignment in whichever format the user specifies,
                or according to the "ffmt" field if the user does not specify
                a format.
     Returns  : varies; "" if unsuccessful
     Argument : $format (one of the formats as defined in $UnivAlnForm).

out_bad()
---------

     Usage    : $aln->out_bad;
     Function : Carp if we don't know the output format.
     Returns  : undef
     Argument : n/a

out_raw()
---------

     Usage    : $aln->out_raw;
     Function : Returns the alignment in raw format.
     Returns  : multiline string
     Argument : n/a

out_fasta()
-----------

     Usage    : $aln->out_fasta;
     Function : Returns the alignment as a string in fasta format.
     Returns  : multiline string
     Argument : Same as seqs()
     Comment  : The old ``out_fasta()'' function with no arguments
                is slightly faster and simpler; still available as out_fasta2().

Sequence change class for polypeptides
**************************************

NAME
====

   Bio::Variation::AAChange - Sequence change class for polypeptides

SYNOPSIS
========

     $aamut = Bio::Variation::AAChange->new
         ('-start'         => $start,
      	'-end'           => $end,
      	'-length'        => $len,
      	'-proof'         => $proof,
      	'-isMutation'    => 1,
      	'-mut_number'    => $mut_number
      	);

     my $a1 = Bio::Variation::Allele->new;
     $a1->seq($ori) if $ori;
     $aamut->allele_ori($a1);
     my $a2 = Bio::Variation::Allele->new;
     $a2->seq($mut) if $mut;
     $aachange->add_Allele($a2);
     $aachange->allele_mut($a2);

     print  "\n";

     # add it to a SeqDiff container object
     $seqdiff->add_Variant($rnachange);

     # and create links to and from RNA level variant objects
     $aamut->RNAChange($rnachange);
     $rnachange->AAChange($rnachange);

DESCRIPTION
===========

   The instantiable class Bio::Variation::RNAChange describes basic
sequence changes at polypeptide  level. It uses methods defined in
superclass Bio/Variation/VariantI.

   If the variation described by a AAChange object has a known
`Bio::Variation::RNAAChange' in this node object, create the link with
method AAChange().

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to the
Bioperl mailing lists  Your participation is much appreciated.

     bioperl-l@bioperl.org                         - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via  email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Heikki Lehvaslaiho
===========================

   Email:  heikki@ebi.ac.uk

   Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

RNAChange
---------

     Title   : RNAChange
     Usage   : $mutobj = $self->RNAChange;
             : $mutobj = $self->RNAChange($objref);
     Function: Returns or sets the link-reference to a mutation/change object.
               If there is no link, it will return undef
     Returns : an obj_ref or undef

label
-----

     Title   : label
     Usage   : $obj->label();
     Function:

     Sets and returns mutation event label(s).  If value is not
     set, or no argument is given returns false.  Each
     instantiable subclass of L<Bio::Variation::VariantI> needs
     to implement this method. Valid values are listed in
     'Mutation event controlled vocabulary' in
     http://www.ebi.ac.uk/mutations/recommendations/mutevent.html.

     Example :
     Returns : string
     Args    : string

trivname
--------

     Title   : trivname
     Usage   : $self->trivname
     Function:

     Given a Bio::Variation::AAChange object with linked
     Bio::Variation::RNAChange and Bio::Variation::DNAMutation
     objects, this subroutine creates a string corresponding to
     the 'trivial name' of the mutation. Trivial name is
     specified in Antonorakis & MDI Nomenclature Working Group:
     Human Mutation 11:1-3, 1998.
     http://www.interscience.wiley.com/jpages/1059-7794/nomenclature.html

     Returns : string

point mutation and codon   information from single amino acid changes
*********************************************************************

NAME
====

   Bio::Variation::AAReverseMutate - point mutation and codon
information from single amino acid changes

SYNOPSIS
========

     $aamut = new Bio::Variation::AAReverseMutate
                  (-aa_ori => 'F',
     		  -aa_mut => 'S',
     		  -codon_ori => 'ttc', # optional
     		  -codon_table => '3'  # defaults to 1
     		  );

     @points = $aamut->each_Variant;

     if (scalar @points > 0 ) {
         foreach $rnachange ( @points ) {
     	   # $rnachange is a Bio::Variation::RNAChange object
     	   print " ", $rnachange->allele_ori->seq, ">",
     	   $rnachange->allele_mut->seq, " in ",
     	   $rnachange->codon_ori, ">", $rnachange->codon_mut,
     	   " at position ", $rnachange->codon_pos, "\n";
         }
     } else  {
         print "No point mutations possible\n",
     }

DESCRIPTION
===========

   Bio::Variation::AAReverseMutate objects take in reference and mutated
amino acid information and deduces potential point mutations at RNA level
leading to this change. The choice can be further limited by letting the
object know what is the the codon in the reference sequence. The results
are returned as Bio/Variation/RNAChange,
objects.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to the
Bioperl mailing lists  Your participation is much appreciated.

     bioperl-l@bioperl.org                         - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via  email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Heikki Lehvaslaiho
===========================

   Email:  heikki@ebi.ac.uk Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

aa_ori
------

     Title   : aa_ori
     Usage   : $obj->aa_ori();
     Function:

     Sets and returns original aa sequence.  If value is not
     set, returns false.

     Amino acid sequences are stored in upper case characters,
     others in lower case.

     Example :
     Returns : string
     Args    : single character amino acid code

aa_mut
------

     Title   : aa_mut
     Usage   : $obj->aa_mut();
     Function:

     Sets and returns the mutated allele sequence.  If value is not
     set, returns false.

     Example :
     Returns : string
     Args    : single character amino acid code

codon_ori
---------

     Title   : codon_ori
     Usage   : $obj->codon_ori();
     Function:

     Sets and returns codon_ori triplet.  If value is not set,
     returns false.  The string has to be three characters
     long. The chracter content is not checked.

     Example :
     Returns : string
     Args    : string

codon_table
-----------

     Title   : codon_table
     Usage   : $obj->codon_table();
     Function:

     Sets and returns the codon table id of the RNA
     If value is not set, returns 1, 'universal' code, as the default.

     Example :
     Returns : integer
     Args    : none if get, the new value if set

each_Variant
------------

     Title   : each_Variant
     Usage   : $obj->each_Variant();
     Function:

     Returns a list of Variants.

     Example :
     Returns : list of Variants
     Args    : none

Sequence object with allele-specific attributes
***********************************************

NAME
====

   Bio::Variation::Allele - Sequence object with allele-specific attributes

SYNOPSIS
========

     $allele1 = Bio::Variation::Allele->new ( -seq => 'A',
                                              -id  => 'AC00001.1',
                                              -moltype => 'dna',
                                              -is_reference => 1
                                            );

DESCRIPTION
===========

   List of alleles describe known sequence alternatives in a variable
region.  Alleles are contained in Bio/Variation/VariantI,
complying objects.

   Bio::Varation::Alleles are PrimarySeqI complying objects which can
contain database cross references as specified in Bio::DBLinkContainerI
interface, too.

   A lot of the complexity with dealing with Allele objects are caused by
null alleles; Allele objects that have zero length sequence string.

   In addition describing the allele by its sequence , it possible to give
describe repeat structure within the sequence. This done using methods
repeat_unit (e.g. 'ca') and repeat_count (e.g. 7).

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to the
Bioperl mailing lists  Your participation is much appreciated.

     bioperl-l@bioperl.org                         - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via  email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Heikki Lehvaslaiho
===========================

   Email:  heikki@ebi.ac.uk Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

is_reference
------------

     Title   : is_reference
     Usage   : $obj->is_reference()
     Function: sets and returns boolean values.
               Unset values return false.
     Example : $obj->is_reference()
     Returns : boolean
     Args    : optional true of false value

add_DBLink
----------

     Title   : add_DBLink
     Usage   : $self->add_DBLink($ref)
     Function: adds a link object
     Example :
     Returns :
     Args    :

each_DBLink
-----------

     Title   : each_DBLink
     Usage   : foreach $ref ( $self->each_DBlink() )
     Function: gets an array of DBlink of objects
     Example :
     Returns :
     Args    :

repeat_unit
-----------

     Title   : repeat_unit
     Usage   : $obj->repeat_unit('ca');
     Function:

     Sets and returns the sequence of the repeat_unit the
     allele is composed of.

     Example :
     Returns : string
     Args    : string

repeat_count
------------

     Title   : repeat_count
     Usage   : $obj->repeat_count();
     Function:

     Sets and returns the number of repeat units in the allele.

     Example :
     Returns : string
     Args    : string

DNA level mutation class
************************

NAME
====

   Bio::Variation::DNAMutation - DNA level mutation class

SYNOPSIS
========

     $dnamut = Bio::Variation::DNAMutation->new
         ('-start'         => $start,
          '-end'           => $end,
          '-length'        => $len,
          '-upStreamSeq'   => $upflank,
          '-dnStreamSeq'   => $dnflank,
          '-proof'         => $proof,
     	 '-isMutation'    => 1,
          '-mut_number'    => $mut_number
         );
     $a1 = Bio::Variation::Allele->new;
     $a1->seq('a');
     $dnamut->allele_ori($a1);
     my $a2 = Bio::Variation::Allele->new;
     $a2->seq('t');
     $dnamut->add_Allele($a2);

     print "Restriction changes are ", $dnamut->restriction_changes, "\n";

     # add it to a SeqDiff container object
     $seqdiff->add_Variant($dnamut);

DESCRIPTION
===========

   The instantiable class Bio::Variation::DNAMutation describes basic
sequence changes in genomic DNA level. It uses methods defined in
superclass Bio/Variation/VariantI.

   If the variation described by a DNAMutation object is transcibed, link
the corresponding Bio/Variation/RNAChange,
object to it using method RNAChange().

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to the
Bioperl mailing lists  Your participation is much appreciated.

     bioperl-l@bioperl.org                         - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via  email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Heikki Lehvaslaiho
===========================

   Email:  heikki@ebi.ac.uk Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

CpG
---

     Title   : CpG
     Usage   : $obj->CpG()
     Function: sets and returns boolean values for variation
               hitting a CpG site.  Unset value return -1.
     Example : $obj->CpG()
     Returns : boolean
     Args    : optional true of false value

RNAChange
---------

     Title   : RNAChange
     Usage   : $mutobj = $obj->RNAChange;
             : $mutobj = $obj->RNAChange($objref);
     Function: Returns or sets the link-reference to a mutation/change object.
               If there is no link, it will return undef
     Returns : an obj_ref or undef

label
-----

     Title   : label
     Usage   : $obj->label();
     Function:

     Sets and returns mutation event label(s).  If value is not
     set, or no argument is given returns false.  Each
     instantiable subclass of L<Bio::Variation::VariantI> needs
     to implement this method. Valid values are listed in
     'Mutation event controlled vocabulary' in
     http://www.ebi.ac.uk/mutations/recommendations/mutevent.html.

     Example :
     Returns : string
     Args    : string

sysname
-------

     Title   : sysname
     Usage   : $self->sysname
     Function:

     This subroutine creates a string corresponding to the
     'systematic name' of the mutation. Systematic name is
     specified in Antonorakis & MDI Nomenclature Working Group:
     Human Mutation 11:1-3, 1998.
     http://www.interscience.wiley.com/jpages/1059-7794/nomenclature.html
      Returns : string

Handler for sequence variation IO Formats
*****************************************

NAME
====

   Bio::Variation::IO - Handler for sequence variation IO Formats

SYNOPSIS
========

     use Bio::Variation::IO;

     $in  = Bio::Variation::IO->new(-file => "inputfilename" , '-format' => 'flat');
     $out = Bio::Variation::IO->new(-file => ">outputfilename" , '-format' => 'xml');
     # note: we quote -format to keep older perl's from complaining.

     while ( my $seq = $in->next() ) {
     	$out->write($seq);
     }

   or

     use Bio::Variation::IO;

     #input file format can be read from the file extension (dat|xml)
     $in  = Bio::Variation::IO->newFh(-file => "inputfilename");
     $out = Bio::Variation::IO->newFh('-format' => 'xml');

     # World's shortest flat<->xml format converter:
     print $output $_ while <$in>;

DESCRIPTION
===========

   Bio::Variation::IO is a handler module for the formats in the Variation
IO set (eg, Bio::Variation::IO::flat). It is the officially sanctioned way
of getting at the format objects, which most people should use.

   The structure, conventions and most of the code is inherited from
Bio/SeqIO, module. The main difference is that instead of using
methods next_seq and write_seq, you drop '_seq' from the method names.

   The idea is that you request a stream object for a particular format.
All the stream objects have a notion of an internal file that is read from
or written to. A particular SeqIO object instance is configured for either
input or output. A specific example of a stream object is the
Bio::Variation::IO::flat object.

   Each stream object has functions

     $stream->next();

   and

     $stream->write($seqDiff);

   also

     $stream->type() # returns 'INPUT' or 'OUTPUT'

   As an added bonus, you can recover a filehandle that is tied to the
SeqIO object, allowing you to use the standard <> and print operations to
read and write sequence objects:

     use Bio::Variation::IO;

     $stream = Bio::Variation::IO->newFh(-format => 'flat'); # read from standard input

     while ( $seq = <$stream> ) {
     	# do something with $seq
     }

   and

     print $stream $seq; # when stream is in output mode

   This makes the simplest ever reformatter

     #!/usr/local/bin/perl

     $format1 = shift;
     $format2 = shift || die "Usage: reformat format1 format2 < input > output";

     use Bio::Variation::IO;

     $in  = Bio::Variation::IO->newFh(-format => $format1 );
     $out = Bio::Variation::IO->newFh(-format => $format2 );
     #note: you might want to quote -format to keep older perl's from complaining.

     print $out $_ while <$in>;

CONSTRUCTORS
============

Bio::Variation::IO->new()
-------------------------

     $seqIO = Bio::Variation::IO->new(-file => 'filename',   -format=>$format);
     $seqIO = Bio::Variation::IO->new(-fh   => \*FILEHANDLE, -format=>$format);
     $seqIO = Bio::Variation::IO->new(-format => $format);

   The new() class method constructs a new Bio::Variation::IO object.  The
returned object can be used to retrieve or print BioSeq objects. new()
accepts the following parameters:

-file
     A file path to be opened for reading or writing.  The usual Perl
     conventions apply:

          'file'       # open file for reading
          '>file'      # open file for writing
          '>>file'     # open file for appending
          '+<file'     # open file read/write
          'command |'  # open a pipe from the command
          '| command'  # open a pipe to the command

-fh
     You may provide new() with a previously-opened filehandle.  For
     example, to read from STDIN:

          $seqIO = Bio::Variation::IO->new(-fh => \*STDIN);

     Note that you must pass filehandles as references to globs.

     If neither a filehandle nor a filename is specified, then the module
     will read from the @ARGV array or STDIN, using the familiar <>
     semantics.

-format
     Specify the format of the file.  Supported formats include:

          flat        pseudo EMBL format
          xml         seqvar xml format

     If no format is specified and a filename is given, then the module
     will attempt to deduce it from the filename.  If this is unsuccessful,
     Fasta format is assumed.

     The format name is case insensitive.  'FLAT', 'Flat' and 'flat' are
     all supported.

Bio::Variation::IO->newFh()
---------------------------

     $fh = Bio::Variation::IO->newFh(-fh   => \*FILEHANDLE, -format=>$format);
     $fh = Bio::Variation::IO->newFh(-format => $format);
     # etc.

     #e.g.
     $out = Bio::Variation::IO->newFh( '-FORMAT' => 'flat');
     print $out $seqDiff;

   This constructor behaves like new(), but returns a tied filehandle
rather than a Bio::Variation::IO object.  You can read sequences from this
object using the familiar <> operator, and write to it using print().  The
usual array and $_ semantics work.  For example, you can read all sequence
objects into an array like this:

     @mutations = <$fh>;

   Other operations, such as read(), sysread(), write(), close(), and
printf() are not supported.

OBJECT METHODS
==============

   See below for more detailed summaries.  The main methods are:

$sequence = $seqIO->next()
--------------------------

   Fetch the next sequence from the stream.

$seqIO->write($sequence [,$another_sequence,...])
-------------------------------------------------

   Write the specified sequence(s) to the stream.

TIEHANDLE(), READLINE(), PRINT()
--------------------------------

   These provide the tie interface.  See Perltie (perl.info),
for more details.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to the
Bioperl mailing lists  Your participation is much appreciated.

     bioperl-l@bioperl.org                         - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via  email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Heikki Lehvaslaiho
===========================

   Email:  heikki@ebi.ac.uk Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
---

     Title   : new
     Usage   : $stream = Bio::Variation::IO->new(-file => $filename, -format => 'Format')
     Function: Returns a new seqstream
     Returns : A Bio::Variation::IO::Handler initialised with the appropriate format
     Args    : -file => $filename
               -format => format
               -fh => filehandle to attach to

next
----

     Title   : next
     Usage   : $seqDiff = stream->next
     Function: reads the next $seqDiff object from the stream
     Returns : a Bio::Variation::SeqDiff object
     Args    :

write
-----

     Title   : write
     Usage   : $stream->write($seq)
     Function: writes the $seq object into the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::Variation::SeqDiff object

_guess_format
-------------

     Title   : _guess_format
     Usage   : $obj->_guess_format($filename)
     Function:
     Example :
     Returns : guessed format of filename (lower case)
     Args    :

flat file sequence variation input/output stream
************************************************

NAME
====

   Bio::Variation::IO::flat - flat file sequence variation input/output
stream

SYNOPSIS
========

   Do not use this module directly.  Use it via the Bio::Variation::IO
class.

DESCRIPTION
===========

   This object can transform Bio::Variation::SeqDiff objects to and from
flat file databases. The format used is EMBL like extension of what is
used by the "EBI Mutation Checker" at
http://www.ebi.ac.uk/cgi-bin/mutations/check.cgi and will eventually
replace it.

   More information of the attributes and values use can be found at
http://www.ebi.ac.uk/mutations/recommendations/.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to the
Bioperl mailing lists  Your participation is much appreciated.

     bioperl-l@bioperl.org                         - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via  email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Heikki Lehvaslaiho
===========================

   Email:  heikki@ebi.ac.uk Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next
----

     Title   : next
     Usage   : $haplo = $stream->next()
     Function: returns the next seqDiff in the stream
     Returns : Bio::Variation::SeqDiff object
     Args    : NONE

write
-----

     Title   : write
     Usage   : $stream->write(@seqDiffs)
     Function: writes the $seqDiff object into the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::Variation::SeqDiff object

XML sequence variation input/output stream
******************************************

NAME
====

   Bio::Variation::IO::xml - XML sequence variation input/output stream

SYNOPSIS
========

   Do not use this module directly.  Use it via the Bio::Variation::IO
class.

DESCRIPTION
===========

   This object can transform Bio::Variation::SeqDiff objects to and from
XML file databases.

   The XML format, although consistent, is still evolving. The DTD is not
yet available. There is also a formatting problem: The module is not able
to write root tags around entries.

REQUIREMENTS
============

   To use this code you need the CPAN module XML::Node to read XML and
modules XML::Writer and IO::String to write XML out.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to the
Bioperl mailing lists  Your participation is much appreciated.

     bioperl-l@bioperl.org                         - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via  email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Heikki Lehvaslaiho
===========================

   Email:  heikki@ebi.ac.uk Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

next
----

     Title   : next
     Usage   : $haplo = $stream->next()
     Function: returns the next seqDiff in the stream
     Returns : Bio::Variation::SeqDiff object
     Args    : NONE

write
-----

     Title   : write
     Usage   : $stream->write(@haplos)
     Function: writes the $seqDiff objects into the stream
     Returns : 1 for success and 0 for error
     Args    : Bio::Variation::SeqDiff object

Sequence change class for RNA level
***********************************

NAME
====

   Bio::Variation::RNAChange - Sequence change class for RNA level

SYNOPSIS
========

     $rnachange = Bio::Variation::RNAChange->new
         ('-start'         => $start,
          '-end'           => $end,
          '-length'        => $len,
          '-codon_pos'     => $cp,
          '-upStreamSeq'   => $upflank,
          '-dnStreamSeq'   => $dnflank,
          '-proof'         => $proof,
     	'-isMutation'    => 1,
          '-mut_number'    => $mut_number
         );
     $a1 = Bio::Variation::Allele->new;
     $a1->seq('a');
     $rnachange->allele_ori($a1);
     my $a2 = Bio::Variation::Allele->new;
     $a2->seq('t');
     $rnachange->add_Allele($a2);
     $rnachange->allele_mut($a2);

     print "The codon change is ", $rnachange->codon_ori,
         ">", $rnachange->codon_mut, "\n";

     # add it to a SeqDiff container object
     $seqdiff->add_Variant($rnachange);

     # and create links to and from DNA level mutation objects
     $rnachange->DNAMutation($dnamut);
     $dnamut->RNAChange($rnachange);

DESCRIPTION
===========

   The instantiable class Bio::Variation::DNAMutation describes basic
sequence changes at RNA molecule level. It uses methods defined in
superclass Bio/Variation/VariantI.

   You are normally expected to create a corresponding
Bio/Variation/DNAMutation, object even if
mutation is defined at RNA level. The numbering follows then cDNA
numbering.  Link the DNAMutation object to the RNAChange object using the
method DNAMutation(). If the variation described by a RNAChange object is
translated, link the corresponding Bio/Variation/AAChange,
object to it using method AAChange().

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to the
Bioperl mailing lists  Your participation is much appreciated.

     bioperl-l@bioperl.org                         - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via  email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Heikki Lehvaslaiho
===========================

   Email:  heikki@ebi.ac.uk Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

codon_ori
---------

     Title   : codon_ori
     Usage   : $obj->codon_ori();
     Function:

     Sets and returns codon_ori triplet.  If value is not set,
     creates the codon triplet from the codon position and
     flanking sequences.  The string has to be three characters
     long. The character content is not checked.

     Example :
     Returns : string
     Args    : string

codon_mut
---------

     Title   : codon_mut
     Usage   : $obj->codon_mut();
     Function:

     Sets and returns codon_mut triplet.  If value is not
     set, creates the codon triplet from the codon position and
     flanking sequences. Return undef for other than point mutations.

     Example :
     Returns : string
     Args    : string

codon_pos
---------

     Title   : codon_pos
     Usage   : $obj->codon_pos();
     Function:

     Sets and returns the position of the mutation start in the
     codon. If value is not set, returns false.

     Example :
     Returns : 1,2,3
     Args    : none if get, the new value if set

codon_table
-----------

     Title   : codon_table
     Usage   : $obj->codon_table();
     Function:

     Sets and returns the codon table id of the RNA
     If value is not set, returns 1, 'universal' code, as the default.

     Example :
     Returns : integer
     Args    : none if get, the new value if set

DNAMutation
-----------

     Title   : DNAMutation
     Usage   : $mutobj = $obj->DNAMutation;
             : $mutobj = $obj->DNAMutation($objref);
     Function: Returns or sets the link-reference to a mutation/change object.
               If there is no link, it will return undef
     Returns : an obj_ref or undef

AAChange
--------

     Title   : AAChange
     Usage   : $mutobj = $obj->AAChange;
             : $mutobj = $obj->AAChange($objref);
     Function: Returns or sets the link-reference to a mutation/change object.
               If there is no link, it will return undef
     Returns : an obj_ref or undef

exons_modified
--------------

     Title   : exons_modified
     Usage   : $modified = $obj->exons_modified;
             : $modified = $obj->exons_modified(1);
     Function: Returns or sets information (example: a simple boolean flag) about
               the modification of exons as a result of a mutation.

region
------

     Title   : region
     Usage   : $obj->region();
     Function:

     Sets and returns the name of the sequence region type or
     protein domain at this location.  If value is not set,
     returns false.

     Example :
     Returns : string
     Args    : string

region_value
------------

     Title   : region_value
     Usage   : $obj->region_value();
     Function:

     Sets and returns the name of the sequence region_value type or
     protein domain at this location. Not a valid method for RNAChange.
      Example :
      Returns : string
      Args    : string

cds_end
-------

     Title   : cds_end
     Usage   : $cds_end = $obj->get_cds_end();
     Function:

     Sets or returns the cds_end from the beginning of the DNA sequence
     to the coordinate start used to describe variants.
     Should be the location of the last nucleotide of the
     terminator codon of the gene.

     Example :
     Returns : value of cds_end, a scalar
     Args    :

label
-----

     Title   : label
     Usage   : $obj->label();
     Function:

     Sets and returns mutation event label(s).  If value is not
     set, or no argument is given returns false.  Each
     instantiable subclass of L<Bio::Variation::VariantI> needs
     to implement this method. Valid values are listed in
     'Mutation event controlled vocabulary' in
     http://www.ebi.ac.uk/mutations/recommendations/mutevent.html.

     Example :
     Returns : string
     Args    : string

_change_codon_pos
-----------------

     Title   : _change_codon_pos
     Usage   : $newCodonPos = _change_codon_pos($myCodonPos, 5)
     Function:

     Keeps track of the codon position in a changeing sequence

     Returns : codon_pos = integer 1, 2 or 3
     Args    : valid codon position
               signed integer offset to a new location in sequence

Container class for mutation/variant descriptions
*************************************************

NAME
====

   Bio::Variation::SeqDiff - Container class for mutation/variant
descriptions

SYNOPSIS
========

     $seqDiff = Bio::Variation::SeqDiff->new (
                                              -id => $M20132,
     					   -moltype => 'rna',
                                              -gene_symbol => 'AR'
                                              -chromosome => 'X',
                                              -numbering => 'coding'
                                              );
     # get a DNAMutation object somehow
     $seqDiff->add_Variant($dnamut);
     print  $seqDiff->sys_name(), "\n";

DESCRIPTION
===========

   SeqDiff stores Bio/Variation/VariantI,
object references and descriptive information common to all changes in a
sequence. Mutations are understood to be any kind of sequence markers and
are expected to occur in the same chromosome.

   The methods of SeqDiff are geared towards describing mutations in human
genes using gene-based coordiante system where 'A' of the initiator codon
has number 1 and the one before it -1. This is according to conventions of
human genetics.

   There will be class Bio::Variation::Genotype to describe markers in
different chromosomes and diploid genototypes.

   Classes implementing Bio/Variation/VariantI,
interface are Bio/Variation/DNAMutation,
see Bio/Variation/RNAChange,
and Bio/Variation/AAChange.

   Variant objects can be added using two ways: an array passed to the
constructor or as individual Variant objects with add_Variant method.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to the
Bioperl mailing lists  Your participation is much appreciated.

     bioperl-l@bioperl.org                         - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via  email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Heikki Lehvaslaiho
===========================

   Email:  heikki@ebi.ac.uk Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

new
---

     Title   : new
     Usage   : $seqDiff = Bio::Variation::SeqDiff->new;
     Function: generates a new Bio::Variation::SeqDiff
     Returns : reference to a new object of class SeqDiff
     Args    :

id
--

     Title   : id
     Usage   : $obj->id(H0001); $id = $obj->id();
     Function:

     Sets or returns the id of the seqDiff.
     Should be used to give the collection of variants a UID
     without semantic associations.

     Example :
     Returns : value of id, a scalar
     Args    : newvalue (optional)

sysname
-------

     Title   : sysname
     Usage   : $obj->sysname('5C>G'); $sysname = $obj->sysname();
     Function:

     Sets or returns the systematic name of the seqDiff.  The
     name should follow the HUGO Mutation Database Initiative
     approved nomenclature. If called without first setting the
     value, will generate it from L<Bio::Variation::DNAMutation>
     objects attached.

     Example :
     Returns : value of sysname, a scalar
     Args    : newvalue (optional)

trivname
--------

     Title   : trivname
     Usage   : $obj->trivname('[A2G;T56G]'); $trivname = $obj->trivname();
     Function:

     Sets or returns the trivial name of the seqDiff.
     The name should follow the HUGO Mutation Database Initiative
     approved nomenclature. If called without first setting the
     value, will generate it from L<Bio::Variation::AAChange>
     objects attached.

     Example :
     Returns : value of trivname, a scalar
     Args    : newvalue (optional)

chromosome
----------

     Title   : chromosome
     Usage   : $obj->chromosome('X'); $chromosome = $obj->chromosome();
     Function:

     Sets or returns the chromosome ("linkage group") of the seqDiff.

     Example :
     Returns : value of chromosome, a scalar
     Args    : newvalue (optional)

gene_symbol
-----------

     Title   : gene_symbol
     Usage   : $obj->gene_symbol('FOS'); $gene_symbol = $obj->gene_symbol;
     Function:

     Sets or returns the gene symbol for the studied CDS.

     Example :
     Returns : value of gene_symbol, a scalar
     Args    : newvalue (optional)

description
-----------

     Title   : description
     Usage   : $obj->description('short description'); $descr = $obj->description();
     Function:

     Sets or returns the short description of the seqDiff.

     Example :
     Returns : value of description, a scalar
     Args    : newvalue (optional)

moltype
-------

     Title   : moltype
     Usage   : if( $obj->moltype eq 'dna' ) { /Do Something/ }
     Function: Returns the type of primary reference sequence being one of
               'dna', 'rna' or 'protein'. This is case sensitive.

     Returns : a string either 'dna','rna','protein'.
     Args    : none

numbering
---------

     Title   : numbering
     Usage   : $obj->numbering('coding'); $numbering = $obj->numbering();
     Function:

     Sets or returns the string giving the numbering schema used
     to describe the variants.

     Example :
     Returns : value of numbering, a scalar
     Args    : newvalue (optional)

offset
------

     Title   : offset
     Usage   : $obj->offset(124); $offset = $obj->offset();
     Function:

     Sets or returns the offset from the beginning of the DNA sequence
     to the coordinate start used to describe variants. Typically
     the beginning of the coding region of the gene.
     The cds_start should be 1 + offset.

     Example :
     Returns : value of offset, a scalar
     Args    : newvalue (optional)

cds_start
---------

     Title   : cds_start
     Usage   : $obj->cds_start(123); $cds_start = $obj->cds_start();
     Function:

     Sets or returns the cds_start from the beginning of the DNA
     sequence to the coordinate start used to describe
     variants. Typically the beginning of the coding region of
     the gene. Needs to be and is implemented as 1 + offset.

     Example :
     Returns : value of cds_start, a scalar
     Args    : newvalue (optional)

cds_end
-------

     Title   : cds_end
     Usage   : $obj->cds_end(321); $cds_end = $obj->cds_end();
     Function:

     Sets or returns the position of the last nucleotitide of the
     termination codon. The coordinate system starts from cds_start.

     Example :
     Returns : value of cds_end, a scalar
     Args    : newvalue (optional)

rna_offset
----------

     Title   : rna_offset
     Usage   : $obj->rna_offset(124); $rna_offset = $obj->rna_offset();
     Function:

     Sets or returns the rna_offset from the beginning of the RNA sequence
     to the coordinate start used to describe variants. Typically
     the beginning of the coding region of the gene.

     Example :
     Returns : value of rna_offset, a scalar
     Args    : newvalue (optional)

rna_id
------

     Title   : rna_id
     Usage   : $obj->rna_id('transcript#3'); $rna_id = $obj->rna_id();
     Function:

     Sets or returns the ID for original RNA sequence of the seqDiff.

     Example :
     Returns : value of rna_id, a scalar
     Args    : newvalue (optional)

add_Variant
-----------

     Title   : add_Variant
     Usage   : $obj->add_Variant($variant)
     Function:

     Pushes one Bio::Variation::Variant into the list of variants.
     At the same time, creates a link from the Variant to SeqDiff
     using its SeqDiff method.

     Example :
     Returns : 1 when succeeds, 0 for failure.
     Args    : Variant object

each_Variant
------------

     Title   : each_Variant
     Usage   : $obj->each_Variant();
     Function:

     Returns a list of Variants.

     Example :
     Returns : list of Variants
     Args    : none

add_Gene
--------

     Title   : add_Gene
     Usage   : $obj->add_Gene($gene)
     Function:

     Pushes one L<Bio::LiveSeq::Gene> into the list of genes.

     Example :
     Returns : 1 when succeeds, 0 for failure.
     Args    : L<Bio::LiveSeq::Gene> object

each_Gene
---------

     Title   : each_Gene
     Usage   : $obj->each_Gene();
     Function:

     Returns a list of L<Bio::LiveSeq::Gene>s.

     Example :
     Returns : list of Genes
     Args    : none

dna_ori
-------

     Title   : dna_ori
     Usage   : $obj->dna_ori('atgctgctgctgct'); $dna_ori = $obj->dna_ori();
     Function:

     Sets or returns the original DNA sequence string of the seqDiff.

     Example :
     Returns : value of dna_ori, a scalar
     Args    : newvalue (optional)

dna_mut
-------

     Title   : dna_mut
     Usage   : $obj->dna_mut('atgctggtgctgct'); $dna_mut = $obj->dna_mut();
     Function:

     Sets or returns the mutated DNA sequence of the seqDiff.

     Example :
     Returns : value of dna_mut, a scalar
     Args    : newvalue (optional)

rna_ori
-------

     Title   : rna_ori
     Usage   : $obj->rna_ori('atgctgctgctgct'); $rna_ori = $obj->rna_ori();
     Function:

     Sets or returns the original RNA sequence of the seqDiff.

     Example :
     Returns : value of rna_ori, a scalar
     Args    : newvalue (optional)

rna_mut
-------

     Title   : rna_mut
     Usage   : $obj->rna_mut('atgctggtgctgct'); $rna_mut = $obj->rna_mut();
     Function:

     Sets or returns the mutated RNA sequence of the seqDiff.

     Example :
     Returns : value of rna_mut, a scalar
     Args    : newvalue (optional)

aa_ori
------

     Title   : aa_ori
     Usage   : $obj->aa_ori('MAGVLL*'); $aa_ori = $obj->aa_ori();
     Function:

     Sets or returns the original protein sequence of the seqDiff.

     Example :
     Returns : value of aa_ori, a scalar
     Args    : newvalue (optional)

aa_mut
------

     Title   : aa_mut
     Usage   : $obj->aa_mut('MA*'); $aa_mut = $obj->aa_mut();
     Function:

     Sets or returns the mutated protein sequence of the seqDiff.

     Example :
     Returns : value of aa_mut, a scalar
     Args    : newvalue (optional)

seqobj
------

     Title   : seqobj
     Usage   : $dnaobj = $obj->seqobj('dna_mut');
     Function:

     Returns the any original or mutated sequences as a
     L<Bio::PrimarySeq> object.

     Example :
     Returns : L<Bio::PrimarySeq> object for the requested sequence
     Args    : string, method name for the sequence requested

alignment
---------

     Title   : alignment
     Usage   : $obj->alignment
     Function:

     Returns a pretty RNA/AA sequence alignment from linked
     objects.  Under construction: Only simple coding region
     point mutations work.

     Example :
     Returns :
     Args    : none

Sequence Change SeqFeature abstract class
*****************************************

NAME
====

   Bio::Variation::VariantI - Sequence Change SeqFeature abstract class

SYNOPSIS
========

     #get Bio::Variant::VariantI somehow
     print $var->restriction_changes, "\n";
     foreach $allele ($var->each_Allele) {
         #work on Bio::Variation::Allele objects
     }

DESCRIPTION
===========

   This superclass defines common methods to basic sequence changes.  The
instantiable classes Bio/Variation/DNAMutation,
see Bio/Variation/RNAChange,
and Bio/Variation/AAChange,
use them.

   These classes store information, heavy computation to detemine allele
sequences is done elsewhere.

   The database cross-references are implemented as
Bio/Annotation/DBLink, objects. The methods to
access them are defined in Bio/DBLinkContainerI.

   Bio::Variation::VariantI redifines and extends
Bio/SeqFeature/Generic, for sequence variations.
This class describes specific sequence change events. These events are
always from a specific reference sequence to something different.

   IMPORTANT: The notion of reference sequence permeates all
Bio::Variation classes. This is especially important to remember when
dealing with Alleles. In a polymorphic site, there can be a large number
of alleles. One of then has to be selected to be the reference allele
(allele_ori). ALL the rest has to be passed to the Variant using the
method add_Allele, including the mutated allele in a canonical mutation.
The IO modules and generated attributes depend on it. They ignore the
allele linked to using allele_mut and circulate each Allele returned by
each_Allele into allele_mut and calculate the changes between that and
allele_ori.

FEEDBACK
========

Mailing Lists
-------------

   User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to the
Bioperl mailing lists  Your participation is much appreciated.

     bioperl-l@bioperl.org                         - General discussion
     http://bio.perl.org/MailList.html             - About the mailing lists

Reporting Bugs
--------------

   report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.  Bug reports can be submitted via  email or
the web:

     bioperl-bugs@bio.perl.org
     http://bio.perl.org/bioperl-bugs/

AUTHOR - Heikki Lehvaslaiho
===========================

   Email:  heikki@ebi.ac.uk Address:

     EMBL Outstation, European Bioinformatics Institute
     Wellcome Trust Genome Campus, Hinxton
     Cambs. CB10 1SD, United Kingdom

APPENDIX
========

   The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _

id
--

     Title   : id
     Usage   : $obj->id
     Function:

               Read only method. Returns the id of the variation object.
               The id is the id of the first DBLink object attached to this object.

     Example :
     Returns : scalar
     Args    : none

add_Allele
----------

     Title   : add_Allele
     Usage   : $self->add_Allele($allele)
     Function:

     Adds one Bio::Variation::Allele into the list of alleles.
                 Note that the method forces the convention that nucleotide
                 sequence is in lower case and amino acds are in upper
                 case.

     Example :
     Returns : 1 when succeeds, 0 for failure.
     Args    : Allele object

each_Allele
-----------

     Title   : alleles
     Usage   : $obj->each_Allele();
     Function:

     Returns a list of Bio::Variation::Allele objects

     Example :
     Returns : list of Alleles
     Args    : none

allele_ori
----------

     Title   : allele_ori
     Usage   : $obj->allele_ori();
     Function:

     Links to and returns the L<Bio::Variation::Allele> object.
     If value is not set, returns false. All other Alleles are
     compared to this.

     Amino acid sequences are stored in upper case characters,
     others in lower case.

     Example :
     Returns : string
     Args    : string

allele_mut
----------

     Title   : allele_mut
     Usage   : $obj->allele_mut();
     Function:

     Links to and returns the L<Bio::Variation::Allele>
     object.  Sets and returns the mutated allele sequence.
     If value is not set, returns false.

     Amino acid sequences are stored in upper case characters,
     others in lower case.

     Example :
     Returns : string
     Args    : string

length
------

     Title   : length
     Usage   : $obj->length();
     Function:

     Sets and returns the length of the affected original
     allele sequence.  If value is not set, returns false == 0.

     Value 0 means that the variant position is before the
     start=end sequence position. (Value 1 would denote a point
     mutation). This follows the convension to report an
     insertion (2insT) in equivalent way to a corresponding
     deletion (2delT) (Think about indel polymorpism ATC <=> AC
     where the origianal state is not known ).

     Example :
     Returns : string
     Args    : string

upStreamSeq
-----------

     Title   : upStreamSeq
     Usage   : $obj->upStreamSeq();
     Function:

     Sets and returns upstream flanking sequence string.  If
     value is not set, returns false. The sequence should be
     >=25 characters long, if possible.

     Example :
     Returns : string or false
     Args    : string

dnStreamSeq
-----------

     Title   : dnStreamSeq
     Usage   : $obj->dnStreamSeq();
     Function:

     Sets and returns dnstream flanking sequence string.  If
     value is not set, returns false. The sequence should be
     >=25 characters long, if possible.

     Example :
     Returns : string or false
     Args    : string

label
-----

     Title   : label
     Usage   : $obj->label();
     Function:

     Sets and returns mutation event label(s).  If value is not
     set, or no argument is given returns false.  Each
     instantiable class needs to implement this method. Valid
     values are listed in 'Mutation event controlled vocabulary' in
     http://www.ebi.ac.uk/mutations/recommendations/mutevent.html.

     Example :
     Returns : string
     Args    : string

status
------

     Title   : status
     Usage   : $obj->status()
     Function:

     Returns the status of the sequence change object.
     Valid values are: 'suspected' and 'proven'

     Example : $obj->status('proven');
     Returns : scalar
     Args    : valid string (optional, for setting)

proof
-----

     Title   : proof
     Usage   : $obj->proof()
     Function:

     Returns the proof of the sequence change object.
     Valid values are: 'suspected' and 'proven'

     Example : $obj->proof('computed');
     Returns : scalar
     Args    : valid string (optional, for setting)

region
------

     Title   : region
     Usage   : $obj->region();
     Function:

     Sets and returns the name of the sequence region type or
     protein domain at this location.  If value is not set,
     returns false.

     Example :
     Returns : string
     Args    : string

region_value
------------

     Title   : region_value
     Usage   : $obj->region_value();
     Function:

     Sets and returns the name of the sequence region_value or
     protein domain at this location.  If value is not set,
     returns false.

     Example :
     Returns : string
     Args    : string

numbering
---------

     Title   : numbering
     Usage   : $obj->numbering()
     Function:

     Returns the numbering chema used locating sequnce features.
     Valid values are: 'entry' and 'coding'

     Example : $obj->numbering('coding');
     Returns : scalar
     Args    : valid string (optional, for setting)

mut_number
----------

     Title   : mut_number
     Usage   : $num = $obj->mut_number;
             : $num = $obj->mut_number($number);
     Function:

     Returns or sets the number identifying the order in which the
     mutation has been issued. Numbers shouldstart from 1.
     If the number has never been set, the method will return ''

     If you want the output from IO modules look nice and, for
     multivariant/allele variations, make sense you better set
     this attribute.

     Returns : an integer

SeqDiff
-------

     Title   : SeqDiff
     Usage   : $mutobj = $obj->SeqDiff;
             : $mutobj = $obj->SeqDiff($objref);
     Function:

     Returns or sets the link-reference to the umbrella
     L<Bio::Variation::SeqDiff> object.  If there is no link,
     it will return undef

     Note: Adding a variant into a SeqDiff object will
     automatically set this value.

     Returns : an obj_ref or undef

add_DBLink
----------

     Title   : add_DBLink
     Usage   : $self->add_DBLink($ref)
     Function: adds a link object
     Example :
     Returns :
     Args    :

each_DBLink
-----------

     Title   : each_DBLink
     Usage   : foreach $ref ( $self->each_DBlink() )
     Function: gets an array of DBlink of objects
     Example :
     Returns :
     Args    :

restriction_changes
-------------------

     Title   : restriction_changes
     Usage   : $obj->restriction_changes();
     Function:

     Returns a string containing a list of restriction
     enzyme changes of form +EcoRI, separated by
     commas. Strings need to be valid restriction enzyme names
     as stored in REBASE. allele_ori and allele_mut need to be assigned.

     Example :
     Returns : string
     Args    : string

Bit Shift Registers with Rotate / Shift Operations
**************************************************

NAME
====

   Bit::ShiftReg - Bit Shift Registers with Rotate / Shift Operations

   Implements rotate left, rotate right, shift left and shift right
operations with carry flag for all C integer types

SYNOPSIS
========

   * `use Bit::ShiftReg qw( bits_of_byte bits_of_short bits_of_int
     bits_of_long' `LSB_byte MSB_byte LSB_short MSB_short LSB_int MSB_int
     LSB_long MSB_long' `ROL_byte ROR_byte SHL_byte SHR_byte ROL_short
     ROR_short SHL_short SHR_short' `ROL_int ROR_int SHL_int SHR_int
     ROL_long ROR_long SHL_long SHR_long );'

     imports all (or some, by leaving some out) of the available operations
     and functions

   * `use Bit::ShiftReg qw(:all);'

     imports all available operations and functions

   * `$version = Bit::ShiftReg::Version();'

     returns the module's version number

   * `$bits = bits_of_byte();'

     returns the number of bits in a byte (unsigned char) on your machine

   * `$bits = bits_of_short();'

     returns the number of bits in an unsigned short on your machine

   * `$bits = bits_of_int();'

     returns the number of bits in an unsigned int on your machine

   * `$bits = bits_of_long();'

     returns the number of bits in an unsigned long on your machine

   * `$lsb = LSB_byte($value);'

     returns the least significant bit (LSB) of a byte (unsigned char)

   * `$msb = MSB_byte($value);'

     returns the most significant bit (MSB) of a byte (unsigned char)

   * `$lsb = LSB_short($value);'

     returns the least significant bit (LSB) of an unsigned short

   * `$msb = MSB_short($value);'

     returns the most significant bit (MSB) of an unsigned short

   * `$lsb = LSB_int($value);'

     returns the least significant bit (LSB) of an unsigned int

   * `$msb = MSB_int($value);'

     returns the most significant bit (MSB) of an unsigned int

   * `$lsb = LSB_long($value);'

     returns the least significant bit (LSB) of an unsigned long

   * `$msb = MSB_long($value);'

     returns the most significant bit (MSB) of an unsigned long

   * `$carry = ROL_byte($value);'

   * `$carry = ROR_byte($value);'

   * `$carry_out = SHL_byte($value,$carry_in);'

   * `$carry_out = SHR_byte($value,$carry_in);'

   * `$carry = ROL_short($value);'

   * `$carry = ROR_short($value);'

   * `$carry_out = SHL_short($value,$carry_in);'

   * `$carry_out = SHR_short($value,$carry_in);'

   * `$carry = ROL_int($value);'

   * `$carry = ROR_int($value);'

   * `$carry_out = SHL_int($value,$carry_in);'

   * `$carry_out = SHR_int($value,$carry_in);'

   * `$carry = ROL_long($value);'

   * `$carry = ROR_long($value);'

   * `$carry_out = SHL_long($value,$carry_in);'

   * `$carry_out = SHR_long($value,$carry_in);'

   *Note that "$value" must be a variable in the calls of the functions*
*ROL, ROR, SHL and SHR, and that the contents of this variable are*
*altered IMPLICITLY by these functions!*

   *Note also that the "carry" input value is always truncated to the
least* *significant bit, i.e., input values for "carry" must be either 0
or 1!*

   *Finally, note that the return values of the functions LSB, MSB, ROL,
ROR,* *SHL and SHR are always either 0 or 1!*

DESCRIPTION
===========

   This module implements rotate left, rotate right, shift left and shift
right operations with carry flag for all C integer types.

   The results depend on the number of bits that the integer types unsigned
char, unsigned short, unsigned int and unsigned long have on your machine.

   The module automatically determines the number of bits of each integer
type and adjusts its internal constants accordingly.

   How the operations work:

ROL
     Rotate Left:

          carry:                           value:

          +---+            +---+---+---+---     ---+---+---+---+
          | 1 |  <---+---  | 1 | 0 | 0 | 1  ...  1 | 0 | 1 | 1 |  <---+
          +---+      |     +---+---+---+---     ---+---+---+---+      |
                     |                                                |
                     +------------------------------------------------+

ROR
     Rotate Right:

          value:                          carry:

          +---+---+---+---     ---+---+---+---+           +---+
           +--->  | 1 | 0 | 0 | 1  ...  1 | 0 | 1 | 1 |  ---+---> | 1 |
           |      +---+---+---+---     ---+---+---+---+     |     +---+
           |                                                |
           +------------------------------------------------+

SHL
     Shift Left:

          carry                        value:                       carry
           out:                                                      in:
          +---+        +---+---+---+---     ---+---+---+---+        +---+
          | 1 |  <---  | 1 | 0 | 0 | 1  ...  1 | 0 | 1 | 1 |  <---  | 1 |
          +---+        +---+---+---+---     ---+---+---+---+        +---+

SHR
     Shift Right:

          carry                        value:                       carry
           in:                                                       out:
          +---+        +---+---+---+---     ---+---+---+---+        +---+
          | 1 |  --->  | 1 | 0 | 0 | 1  ...  1 | 0 | 1 | 1 |  --->  | 1 |
          +---+        +---+---+---+---     ---+---+---+---+        +---+

EXAMPLE
=======

   Suppose you want to implement shift registers in a machine-independent
way.

   The only C integer type whose length in bits you can be pretty sure
about is probably a byte, since the C standard only prescribes minimum
lengths for char, short, int and long and that `sizeof(char)' `<='
`sizeof(short)' `<=' `sizeof(int)' `<=' `sizeof(long)'.

   How to implement a 4-byte shift register and the 4 operations ROL, ROR,
SHL and SHR on it:

   First, you need to define 4 byte registers:

     $byte0 = 0;
     $byte1 = 0;
     $byte2 = 0;
     $byte3 = 0;

   Then proceed as follows:

ROL
     Rotate left:

          $carry = SHL_byte($byte3, SHL_byte($byte2, SHL_byte($byte1,
                   SHL_byte($byte0, MSB_byte($byte3)))));

ROR
     Rotate right:

          $carry = SHR_byte($byte0, SHR_byte($byte1, SHR_byte($byte2,
                   SHR_byte($byte3, LSB_byte($byte0)))));

SHL
     Shift left:

          $carry_out = SHL_byte($byte3, SHL_byte($byte2, SHL_byte($byte1,
                       SHL_byte($byte0, $carry_in))));

SHR
     Shift right:

          $carry_out = SHR_byte($byte0, SHR_byte($byte1, SHR_byte($byte2,
                       SHR_byte($byte3, $carry_in))));

SEE ALSO
========

   perl(1), perlsub(1), perlmod(1), perlxs(1), perlxstut(1), perlguts(1).

VERSION
=======

   This man page documents Bit::ShiftReg version 2.0.

AUTHOR
======

   Steffen Beyer <sb@sdm.de>.

COPYRIGHT
=========

   Copyright (c) 1997 by Steffen Beyer. All rights reserved.

LICENSE AGREEMENT
=================

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Efficient bit vector, set of integers and "big int" math library
****************************************************************

NAME
====

   Bit::Vector - Efficient bit vector, set of integers and "big int" math
library

SYNOPSIS
========

OVERLOADED OPERATORS
--------------------

   See `Bit::Vector::Overload(3)' in this node.

CLASS METHODS
-------------

     Version
         $version = Bit::Vector->Version();

     Word_Bits
         $bits = Bit::Vector->Word_Bits();  #  bits in a machine word

     Long_Bits
         $bits = Bit::Vector->Long_Bits();  #  bits in an unsigned long

     new
         $vector = Bit::Vector->new($bits);  #  bit vector constructor

     new_Hex
         $vector = Bit::Vector->new_Hex($bits,$string);

     new_Bin
         $vector = Bit::Vector->new_Bin($bits,$string);

     new_Dec
         $vector = Bit::Vector->new_Dec($bits,$string);

     new_Enum
         $vector = Bit::Vector->new_Enum($bits,$string);

     Concat_List
         $vector = Bit::Vector->Concat_List(@vectors);

OBJECT METHODS
--------------

     new
         $vec2 = $vec1->new($bits);  #  alternative call of constructor

     Shadow
         $vec2 = $vec1->Shadow();  #  new vector, same size but empty

     Clone
         $vec2 = $vec1->Clone();  #  new vector, exact duplicate

     Concat
         $vector = $vec1->Concat($vec2);

     Concat_List
         $vector = $vec1->Concat_List($vec2,$vec3,...);

     Size
         $bits = $vector->Size();

     Resize
         $vector->Resize($bits);
         $vector->Resize($vector->Size()+5);
         $vector->Resize($vector->Size()-5);

     Copy
         $vec2->Copy($vec1);

     Empty
         $vector->Empty();

     Fill
         $vector->Fill();

     Flip
         $vector->Flip();

     Primes
         $vector->Primes();  #  Sieve of Erathostenes

     Reverse
         $vec2->Reverse($vec1);

     Interval_Empty
         $vector->Interval_Empty($min,$max);

     Interval_Fill
         $vector->Interval_Fill($min,$max);

     Interval_Flip
         $vector->Interval_Flip($min,$max);

     Interval_Reverse
         $vector->Interval_Reverse($min,$max);

     Interval_Scan_inc
         if (($min,$max) = $vector->Interval_Scan_inc($start))

     Interval_Scan_dec
         if (($min,$max) = $vector->Interval_Scan_dec($start))

     Interval_Copy
         $vec2->Interval_Copy($vec1,$offset2,$offset1,$length);

     Interval_Substitute
         $vec2->Interval_Substitute($vec1,$off2,$len2,$off1,$len1);

     is_empty
         if ($vector->is_empty())

     is_full
         if ($vector->is_full())

     equal
         if ($vec1->equal($vec2))

     Lexicompare (unsigned)
         if ($vec1->Lexicompare($vec2) == 0)
         if ($vec1->Lexicompare($vec2) != 0)
         if ($vec1->Lexicompare($vec2) <  0)
         if ($vec1->Lexicompare($vec2) <= 0)
         if ($vec1->Lexicompare($vec2) >  0)
         if ($vec1->Lexicompare($vec2) >= 0)

     Compare (signed)
         if ($vec1->Compare($vec2) == 0)
         if ($vec1->Compare($vec2) != 0)
         if ($vec1->Compare($vec2) <  0)
         if ($vec1->Compare($vec2) <= 0)
         if ($vec1->Compare($vec2) >  0)
         if ($vec1->Compare($vec2) >= 0)

     to_Hex
         $string = $vector->to_Hex();

     from_Hex
         $vector->from_Hex($string);

     to_Bin
         $string = $vector->to_Bin();

     from_Bin
         $vector->from_Bin($string);

     to_Dec
         $string = $vector->to_Dec();

     from_Dec
         $vector->from_Dec($string);

     to_Enum
         $string = $vector->to_Enum();  #  e.g. "2,3,5-7,11,13-19"

     from_Enum
         $vector->from_Enum($string);

     Bit_Off
         $vector->Bit_Off($index);

     Bit_On
         $vector->Bit_On($index);

     bit_flip
         $bit = $vector->bit_flip($index);

     bit_test, contains
         $bit = $vector->bit_test($index);
         $bit = $vector->contains($index);
         if ($vector->bit_test($index))
         if ($vector->contains($index))

     Bit_Copy
         $vector->Bit_Copy($index,$bit);

     LSB (least significant bit)
         $vector->LSB($bit);

     MSB (most significant bit)
         $vector->MSB($bit);

     lsb (least significant bit)
         $bit = $vector->lsb();

     msb (most significant bit)
         $bit = $vector->msb();

     rotate_left
         $carry = $vector->rotate_left();

     rotate_right
         $carry = $vector->rotate_right();

     shift_left
         $carry = $vector->shift_left($carry);

     shift_right
         $carry = $vector->shift_right($carry);

     Move_Left
         $vector->Move_Left($bits);  #  shift left "$bits" positions

     Move_Right
         $vector->Move_Right($bits);  #  shift right "$bits" positions

     Insert
         $vector->Insert($offset,$bits);

     Delete
         $vector->Delete($offset,$bits);

     increment
         $carry = $vector->increment();

     decrement
         $carry = $vector->decrement();

     inc
         $overflow = $vec2->inc($vec1);

     dec
         $overflow = $vec2->dec($vec1);

     add
         $carry = $vec3->add($vec1,$vec2,$carry);
         ($carry,$overflow) = $vec3->add($vec1,$vec2,$carry);

     subtract
         $carry = $vec3->subtract($vec1,$vec2,$carry);
         ($carry,$overflow) = $vec3->subtract($vec1,$vec2,$carry);

     Negate
         $vec2->Negate($vec1);

     Absolute
         $vec2->Absolute($vec1);

     Sign
         if ($vector->Sign() == 0)
         if ($vector->Sign() != 0)
         if ($vector->Sign() <  0)
         if ($vector->Sign() <= 0)
         if ($vector->Sign() >  0)
         if ($vector->Sign() >= 0)

     Multiply
         $vec3->Multiply($vec1,$vec2);

     Divide
         $quot->Divide($vec1,$vec2,$rest);

     GCD (Greatest Common Divisor)
         $vec3->GCD($vec1,$vec2);

     Power
         $vec3->Power($vec1,$vec2);

     Block_Store
         $vector->Block_Store($buffer);

     Block_Read
         $buffer = $vector->Block_Read();

     Word_Size
         $size = $vector->Word_Size();  #  number of words in "$vector"

     Word_Store
         $vector->Word_Store($offset,$word);

     Word_Read
         $word = $vector->Word_Read($offset);

     Word_List_Store
         $vector->Word_List_Store(@words);

     Word_List_Read
         @words = $vector->Word_List_Read();

     Word_Insert
         $vector->Word_Insert($offset,$count);

     Word_Delete
         $vector->Word_Delete($offset,$count);

     Chunk_Store
         $vector->Chunk_Store($chunksize,$offset,$chunk);

     Chunk_Read
         $chunk = $vector->Chunk_Read($chunksize,$offset);

     Chunk_List_Store
         $vector->Chunk_List_Store($chunksize,@chunks);

     Chunk_List_Read
         @chunks = $vector->Chunk_List_Read($chunksize);

     Index_List_Remove
         $vector->Index_List_Remove(@indices);

     Index_List_Store
         $vector->Index_List_Store(@indices);

     Index_List_Read
         @indices = $vector->Index_List_Read();

     Union
         $set3->Union($set1,$set2);

     Intersection
         $set3->Intersection($set1,$set2);

     Difference
         $set3->Difference($set1,$set2);

     ExclusiveOr
         $set3->ExclusiveOr($set1,$set2);

     Complement
         $set2->Complement($set1);

     subset
         if ($set1->subset($set2))  #  true if $set1 is subset of $set2

     Norm
         $norm = $set->Norm();

     Min
         $min = $set->Min();

     Max
         $max = $set->Max();

     Multiplication
         $matrix3->Multiplication($rows3,$cols3,
                         $matrix1,$rows1,$cols1,
                         $matrix2,$rows2,$cols2);

     Product
         $matrix3->Product($rows3,$cols3,
                  $matrix1,$rows1,$cols1,
                  $matrix2,$rows2,$cols2);

     Closure
         $matrix->Closure($rows,$cols);

     Transpose
         $matrix2->Transpose($rows2,$cols2,$matrix1,$rows1,$cols1);

IMPORTANT NOTES
===============

   * Method naming conventions

     Method names completely in lower case indicate a boolean return value.

     (Except for the bit vector constructor method "new()", of course.)

   * Boolean values

     Boolean values in this module are always a numeric zero ("0") for
     "false" and a numeric one ("1") for "true".

   * Negative numbers

     All numeric input parameters passed to any of the methods in this
     module are regarded as being UNSIGNED (as opposed to the contents of
     the bit vectors themselves, which are usually considered to be
     *SIGNED*).

     As a consequence, whenever you pass a negative number as an argument
     to some method of this module, it will be treated as a (usually very
     large) positive number due to its internal two's complement binary
     representation, usually resulting in an "index out of range" error
     message and program abortion.

   * Bit order

     Note that bit vectors are stored least order bit and least order word
     first internally.

     I.e., bit #0 of any given bit vector corresponds to bit #0 of word #0
     in the array of machine words representing the bit vector.

     (Where word #0 comes first in memory, i.e., it is stored at the least
     memory address in the allocated block of memory holding the given bit
     vector.)

     Note however that machine words can be stored least order byte first
     or last, depending on your system's implementation.

     When you are exporting or importing a whole bit vector at once using
     the methods "`Block_Read()'" and "`Block_Store()'" (the only time in
     this module where this could make any difference), however, a
     conversion to and from "least order byte first" order is
     automatically supplied.

     In other words, what "`Block_Read()'" provides and what
     "`Block_Store()'" expects is always in "least order byte first"
     order, regardless of the order in which words are stored internally
     on your machine.

     This is to make sure that what you export on one machine using
     "`Block_Read()'" can always be read in correctly with
     "`Block_Store()'" on a different machine.

     Note further that whenever bit vectors are converted to and from
     (binary or hexadecimal) strings, the *RIGHTMOST* bit is always the
     *LEAST SIGNIFICANT* one, and the *LEFTMOST* bit is always the *MOST
     SIGNIFICANT* bit.

     This is because in our western culture, numbers are always
     represented in this way (least significant to most significant digits
     go from right to left).

     Of course this requires an internal reversion of order, which the
     corresponding conversion methods perform automatically (without any
     additional overhead, it's just a matter of starting the internal loop
     at the bottom or the top end).

   * "Word" related methods

     Note that all methods whose names begin with "`Word_'" are
     *MACHINE-DEPENDENT*!

     They depend on the size (number of bits) of an "unsigned int" (C
     type) on your machine.

     Therefore, you should only use these methods if you are *ABSOLUTELY
     CERTAIN* that portability of your code is not an issue!

     Note that you can use arbitrarily large chunks (i.e., fragments of
     bit vectors) of up to 32 bits *IN A PORTABLE WAY* using the methods
     whose names begin with "`Chunk_'".

   * Chunk sizes

     Note that legal chunk sizes for all methods whose names begin with
     "`Chunk_'" range from "1" to "`Bit::Vector->Long_Bits();'" bits ("0"
     is *NOT* allowed!).

     In order to make your programs portable, however, you shouldn't use
     chunk sizes larger than 32 bits, since this is the minimum size of an
     "unsigned long" (C type) on all systems, as prescribed by ANSI C.

   * Matching sizes

     In general, for methods involving several bit vectors at the same
     time, all bit vector arguments must have identical sizes (number of
     bits), or a fatal "size mismatch" error will occur.

     Exceptions from this rule are the methods "`Concat()'",
     "`Concat_List()'", "`Copy()'", "`Interval_Copy()'" and
     "`Interval_Substitute()'", where no conditions at all are imposed on
     the size of their bit vector arguments.

     In method "`Multiply()'", all three bit vector arguments must in
     principle obey the rule of matching sizes, but the bit vector in
     which the result of the multiplication is to be stored may be larger
     than the two bit vector arguments containing the factors for the
     multiplication.

     In method "`Power()'", the bit vector for the result must be the same
     size or greater than the base of the exponentiation term. The exponent
     can be any size.

   * Index ranges

     All indices for any given bits must lie between "0" and
     "`$vector->Size()-1'", or a fatal "index out of range" error will
     occur.

DESCRIPTION
===========

OVERLOADED OPERATORS
--------------------

   See `Bit::Vector::Overload(3)' in this node.

CLASS METHODS
-------------

   * `$version = Bit::Vector->Version();'

     Returns the current version number of this module.

   * `$bits = Bit::Vector->Word_Bits();'

     Returns the number of bits of an "unsigned int" (C type) on your
     machine.

     (An "unsigned int" is also called a "machine word", hence the name of
     this method.)

   * `$bits = Bit::Vector->Long_Bits();'

     Returns the number of bits of an "unsigned long" (C type) on your
     machine.

   * `$vector = Bit::Vector->new($bits);'

     This is the bit vector constructor method.

     Call this method to create a new bit vector containing "`$bits'" bits
     (with indices ranging from "0" to "`$bits-1'").

     Note that - in contrast to previous versions - bit vectors of length
     zero (i.e., with `$bits = 0') are permitted now.

     The method returns a reference to the newly created bit vector.

     A new bit vector is always initialized so that all bits are cleared
     (turned off).

     An exception will be raised if the method is unable to allocate the
     necessary memory.

     Note that if you specify a negative number for "`$bits'" it will be
     interpreted as a large positive number due to its internal two's
     complement binary representation.

     In such a case, the bit vector constructor method will obediently
     attempt to create a bit vector of that size, probably resulting in an
     exception, as explained above.

   * `$vector = Bit::Vector->new_Hex($bits,$string);'

     This method is an alternative constructor which allows you to create
     a new bit vector object (with "`$bits'" bits) and to initialize it
     all in one go.

     The method is more efficient than performing these two steps
     separately first because in this method, the memory area occupied by
     the new bit vector is not initialized to zeros (which is pointless in
     this case), and second because it saves you from the associated
     overhead of one additional method invocation.

     The method first calls the bit vector constructor method "new()"
     internally, and then passes the given string to the method
     "`from_Hex()'".

     An exception will be raised if the necessary memory cannot be
     allocated (see the description of the method "new()" immediately
     above for possible causes) or if the given string cannot be converted
     successfully (see the description of the method "`from_Hex()'"
     further below for details).

     In the latter case, the memory occupied by the new bit vector is
     released first (i.e., "free"d) before the exception is actually
     raised.

   * `$vector = Bit::Vector->new_Bin($bits,$string);'

     This method is an alternative constructor which allows you to create
     a new bit vector object (with "`$bits'" bits) and to initialize it
     all in one go.

     The method is more efficient than performing these two steps
     separately first because in this method, the memory area occupied by
     the new bit vector is not initialized to zeros (which is pointless in
     this case), and second because it saves you from the associated
     overhead of one additional method invocation.

     The method first calls the bit vector constructor method "new()"
     internally, and then passes the given string to the method
     "`from_Bin()'".

     An exception will be raised if the necessary memory cannot be
     allocated (see the description of the method "new()" above for
     possible causes) or if the given string cannot be converted
     successfully (see the description of the method "`from_Bin()'"
     further below for details).

     In the latter case, the memory occupied by the new bit vector is
     released first (i.e., "free"d) before the exception is actually
     raised.

   * `$vector = Bit::Vector->new_Dec($bits,$string);'

     This method is an alternative constructor which allows you to create
     a new bit vector object (with "`$bits'" bits) and to initialize it
     all in one go.

     The method is more efficient than performing these two steps
     separately first because in this method, the memory area occupied by
     the new bit vector is not initialized to zeros (which is pointless in
     this case), and second because it saves you from the associated
     overhead of one additional method invocation.

     The method first calls the bit vector constructor method "new()"
     internally, and then passes the given string to the method
     "`from_Dec()'".

     An exception will be raised if the necessary memory cannot be
     allocated (see the description of the method "new()" above for
     possible causes) or if the given string cannot be converted
     successfully (see the description of the method "`from_Dec()'"
     further below for details).

     In the latter case, the memory occupied by the new bit vector is
     released first (i.e., "free"d) before the exception is actually
     raised.

   * `$vector = Bit::Vector->new_Enum($bits,$string);'

     This method is an alternative constructor which allows you to create
     a new bit vector object (with "`$bits'" bits) and to initialize it
     all in one go.

     The method is more efficient than performing these two steps
     separately first because in this method, the memory area occupied by
     the new bit vector is not initialized to zeros (which is pointless in
     this case), and second because it saves you from the associated
     overhead of one additional method invocation.

     The method first calls the bit vector constructor method "new()"
     internally, and then passes the given string to the method
     "`from_Enum()'".

     An exception will be raised if the necessary memory cannot be
     allocated (see the description of the method "new()" above for
     possible causes) or if the given string cannot be converted
     successfully (see the description of the method "`from_Enum()'"
     further below for details).

     In the latter case, the memory occupied by the new bit vector is
     released first (i.e., "free"d) before the exception is actually
     raised.

   * `$vector = Bit::Vector->Concat_List(@vectors);'

     This method creates a new vector containing all bit vectors from the
     argument list in concatenated form.

     The argument list may contain any number of arguments (including
     zero); the only condition is that all arguments must be bit vectors.

     There is no condition concerning the length (in number of bits) of
     these arguments.

     The vectors from the argument list are not changed in any way.

     If the argument list is empty or if all arguments have length zero,
     the resulting bit vector will also have length zero.

     Note that the *RIGHTMOST* bit vector from the argument list will
     become the *LEAST* significant part of the resulting bit vector, and
     the *LEFTMOST* bit vector from the argument list will become the
     *MOST* significant part of the resulting bit vector.

OBJECT METHODS
--------------

   * `$vec2 = $vec1->new($bits);'

     This is an alternative way of calling the bit vector constructor
     method.

     Vector "`$vec1'" is not affected by this, it just serves as an anchor
     for the method invocation mechanism.

     In fact ALL class methods in this module can be called this way, even
     though this is probably considered to be "politically incorrect" by
     OO ("object-orientation") aficionados. ;-)

     So even if you are too lazy to type "`Bit::Vector->'" instead of
     "`$vec1->'" (and even though laziness is - allegedly - a programmer's
     virtue `:-)'), maybe it is better not to use this feature if you don't
     want to get booed at. ;-)

   * `$vec2 = $vec1->Shadow();'

     Creates a NEW bit vector "`$vec2'" of the *SAME SIZE* as "`$vec1'"
     but which is EMPTY.

     Just like a shadow that has the same shape as the object it
     originates from, but is flat and has no volume, i.e., contains
     nothing.

   * `$vec2 = $vec1->Clone();'

     Creates a NEW bit vector "`$vec2'" of the *SAME SIZE* as "`$vec1'"
     which is an *EXACT COPY* of "`$vec1'".

   * `$vector = $vec1->Concat($vec2);'

     This method returns a new bit vector object which is the result of the
     concatenation of the contents of "`$vec1'" and "`$vec2'".

     Note that the contents of "`$vec1'" become the *MOST* significant part
     of the resulting bit vector, and "`$vec2'" the *LEAST* significant
     part.

     If both bit vector arguments have length zero, the resulting bit
     vector will also have length zero.

   * `$vector = $vec1->Concat_List($vec2,$vec3,...);'

     This is an alternative way of calling this (class) method as an
     object method.

     The method returns a new bit vector object which is the result of the
     concatenation of the contents of `$vec1 . $vec2 . $vec3 . ...'

     See the section "class methods" above for a detailed description of
     this method.

     Note that the argument list may be empty and that all arguments must
     be bit vectors if it isn't.

   * `$bits = $vector->Size();'

     Returns the size (number of bits) the given vector was created with
     (or "`Resize()'"d to).

   * `$vector->Resize($bits);'

     Changes the size of the given vector to the specified number of bits.

     This method allows you to change the size of an existing bit vector,
     preserving as many bits from the old vector as will fit into the new
     one (i.e., all bits with indices smaller than the minimum of the
     sizes of both vectors, old and new).

     If the number of machine words needed to store the new vector is
     smaller than or equal to the number of words needed to store the old
     vector, the memory allocated for the old vector is reused for the new
     one, and only the relevant book-keeping information is adjusted
     accordingly.

     This means that even if the number of bits increases, new memory is
     not necessarily being allocated (i.e., if the old and the new number
     of bits fit into the same number of machine words).

     If the number of machine words needed to store the new vector is
     greater than the number of words needed to store the old vector, new
     memory is allocated for the new vector, the old vector is copied to
     the new one, the remaining bits in the new vector are cleared (turned
     off) and the old vector is deleted, i.e., the memory that was
     allocated for it is released.

     (An exception will be raised if the method is unable to allocate the
     necessary memory for the new vector.)

     As a consequence, if you decrease the size of a given vector so that
     it will use fewer machine words, and increase it again later so that
     it will use more words than immediately before but still less than the
     original vector, new memory will be allocated anyway because the
     information about the size of the original vector is lost whenever
     you resize it.

     Note also that if you specify a negative number for "`$bits'" it will
     be interpreted as a large positive number due to its internal two's
     complement binary representation.

     In such a case, "Resize()" will obediently attempt to create a bit
     vector of that size, probably resulting in an exception, as explained
     above.

     Finally, note that - in contrast to previous versions - resizing a bit
     vector to a size of zero bits (length zero) is now permitted.

   * `$vec2->Copy($vec1);'

     Copies the contents of bit vector "`$vec1'" to bit vector "`$vec2'".

     The previous contents of bit vector "`$vec2'" get overwritten, i.e.,
     are lost.

     Both vectors must exist beforehand, i.e., this method does not CREATE
     any new bit vector object.

     The two vectors may be of any size.

     If the source bit vector is larger than the target, this method will
     copy as much of the least significant bits of the source vector as
     will fit into the target vector, thereby discarding any extraneous
     most significant bits.

     BEWARE that this causes a brutal cutoff in the middle of your data,
     and it will also leave you with an almost unpredictable sign if
     subsequently the number in the target vector is going to be
     interpreted as a number! (You have been warned!)

     If the target bit vector is larger than the source, this method fills
     up the remaining most significant bits in the target bit vector with
     either 0's or 1's, depending on the sign (= the most significant bit)
     of the source bit vector.

     This makes it possible to copy numbers from a smaller bit vector into
     a larger one while preserving the number's absolute value as well as
     its sign (due to the two's complement binary representation of
     numbers).

   * `$vector->Empty();'

     Clears all bits in the given vector.

   * `$vector->Fill();'

     Sets all bits in the given vector.

   * `$vector->Flip();'

     Flips (i.e., complements) all bits in the given vector.

   * `$vector->Primes();'

     Clears the given bit vector and sets all bits whose indices are prime
     numbers.

     This method uses the algorithm known as the "Sieve of Erathostenes"
     internally.

   * `$vec2->Reverse($vec1);'

     This method copies the given vector "`$vec1'" to the vector
     "`$vec2'", thereby reversing the order of all bits.

     I.e., the least significant bit of "`$vec1'" becomes the most
     significant bit of "`$vec2'", whereas the most significant bit of
     "`$vec1'" becomes the least significant bit of "`$vec2'", and so forth
     for all bits in between.

     Note that in-place processing is also possible, i.e., "`$vec1'" and
     "`$vec2'" may be identical.

     (Internally, this is the same as
     `$vec1->Interval_Reverse(0,$vec1->Size()-1);'.)

   * `$vector->Interval_Empty($min,$max);'

     Clears all bits in the interval `[$min..$max]' (including both limits)
     in the given vector.

     "`$min'" and "`$max'" may have the same value; this is the same as
     clearing a single bit with "`Bit_Off()'" (but less efficient).

     Note that `$vector->Interval_Empty(0,$vector->Size()-1);' is the same
     as `$vector->Empty();' (but less efficient).

   * `$vector->Interval_Fill($min,$max);'

     Sets all bits in the interval `[$min..$max]' (including both limits)
     in the given vector.

     "`$min'" and "`$max'" may have the same value; this is the same as
     setting a single bit with "`Bit_On()'" (but less efficient).

     Note that `$vector->Interval_Fill(0,$vector->Size()-1);' is the same
     as `$vector->Fill();' (but less efficient).

   * `$vector->Interval_Flip($min,$max);'

     Flips (i.e., complements) all bits in the interval `[$min..$max]'
     (including both limits) in the given vector.

     "`$min'" and "`$max'" may have the same value; this is the same as
     flipping a single bit with "`bit_flip()'" (but less efficient).

     Note that `$vector->Interval_Flip(0,$vector->Size()-1);' is the same
     as `$vector->Flip();' and `$vector->Complement($vector);' (but less
     efficient).

   * `$vector->Interval_Reverse($min,$max);'

     Reverses the order of all bits in the interval `[$min..$max]'
     (including both limits) in the given vector.

     I.e., bits "`$min'" and "`$max'" swap places, and so forth for all
     bits in between.

     "`$min'" and "`$max'" may have the same value; this has no effect
     whatsoever, though.

   * `if (($min,$max) = $vector->Interval_Scan_inc($start))'

     Returns the minimum and maximum indices of the next contiguous block
     of set bits (i.e., bits in the "on" state).

     The search starts at index "$start" (i.e., `"$min" >= "$start"') and
     proceeds upwards (i.e., `"$max" >= "$min"'), thus repeatedly
     increments the search pointer "$start" (internally).

     Note though that the contents of the variable (or scalar literal
     value) "$start" is *NOT* altered. I.e., you have to set it to the
     desired value yourself prior to each call to "`Interval_Scan_inc()'"
     (see also the example given below).

     Actually, the bit vector is not searched bit by bit, but one machine
     word at a time, in order to speed up execution (which means that this
     method is quite efficient).

     An empty list is returned if no such block can be found.

     Note that a single set bit (surrounded by cleared bits) is a valid
     block by this definition. In that case the return values for "`$min'"
     and "`$max'" are the same.

     Typical use:

          $start = 0;
          while (($start < $vector->Size()) &&
              (($min,$max) = $vector->Interval_Scan_inc($start)))
          {
              $start = $max + 2;

          # do something with $min and $max
              }

   * `if (($min,$max) = $vector->Interval_Scan_dec($start))'

     Returns the minimum and maximum indices of the next contiguous block
     of set bits (i.e., bits in the "on" state).

     The search starts at index "$start" (i.e., `"$max" <= "$start"') and
     proceeds downwards (i.e., `"$min" <= "$max"'), thus repeatedly
     decrements the search pointer "$start" (internally).

     Note though that the contents of the variable (or scalar literal
     value) "$start" is *NOT* altered. I.e., you have to set it to the
     desired value yourself prior to each call to "`Interval_Scan_dec()'"
     (see also the example given below).

     Actually, the bit vector is not searched bit by bit, but one machine
     word at a time, in order to speed up execution (which means that this
     method is quite efficient).

     An empty list is returned if no such block can be found.

     Note that a single set bit (surrounded by cleared bits) is a valid
     block by this definition. In that case the return values for "`$min'"
     and "`$max'" are the same.

     Typical use:

          $start = $vector->Size() - 1;
          while (($start >= 0) &&
              (($min,$max) = $vector->Interval_Scan_dec($start)))
          {
              $start = $min - 2;

          # do something with $min and $max
              }

   * `$vec2->Interval_Copy($vec1,$offset2,$offset1,$length);'

     This method allows you to copy a stretch of contiguous bits (starting
     at any position "`$offset1'" you choose, with a length of "$length"
     bits) from a given "source" bit vector "`$vec1'" to another position
     "`$offset2'" in a "target" bit vector "`$vec2'".

     Note that the two bit vectors "`$vec1'" and "`$vec2'" do *NOT* need
     to have the same (matching) size!

     Consequently, any of the two terms "`$offset1 + $length'" and
     "`$offset2 + $length'" (or both) may exceed the actual length of its
     corresponding bit vector ("`$vec1->Size()'" and "`$vec2->Size()'",
     respectively).

     In such a case, the "$length" parameter is automatically reduced
     internally so that both terms above are bounded by the number of bits
     of their corresponding bit vector.

     This may even result in a length of zero, in which case nothing is
     copied at all.

     (Of course the value of the "$length" parameter, supplied by you in
     the initial method call, may also be zero right from the start!)

     Note also that "`$offset1'" and "`$offset2'" must lie within the
     range "0" and, respectively, "`$vec1->Size()-1'" or
     "`$vec2->Size()-1'", or a fatal "offset out of range" error will
     occur.

     Note further that "`$vec1'" and "`$vec2'" may be identical, i.e., you
     may copy a stretch of contiguous bits from one part of a given bit
     vector to another part.

     The source and the target interval may even overlap, in which case
     the copying is automatically performed in ascending or descending
     order (depending on the direction of the copy - downwards or upwards
     in the bit vector, respectively) to handle this situation correctly,
     i.e., so that no bits are being overwritten before they have been
     copied themselves.

   * `$vec2->Interval_Substitute($vec1,$off2,$len2,$off1,$len1);'

     This method is (roughly) the same for bit vectors (i.e., arrays of
     booleans) as what the "splice" function in Perl is for lists (i.e.,
     arrays of scalars).

     (See `splice', see Perlfunc (perl.info), for more details
     about this function.)

     The method allows you to substitute a stretch of contiguous bits
     (defined by a position (offset) "`$off1'" and a length of "`$len1'"
     bits) from a given "source" bit vector "`$vec1'" for a different
     stretch of contiguous bits (defined by a position (offset) "`$off2'"
     and a length of "`$len2'" bits) in another, "target" bit vector
     "`$vec2'".

     Note that the two bit vectors "`$vec1'" and "`$vec2'" do *NOT* need
     to have the same (matching) size!

     Note further that "`$off1'" and "`$off2'" must lie within the range
     "0" and, respectively, "`$vec1->Size()'" or "`$vec2->Size()'", or a
     fatal "offset out of range" error will occur.

     Alert readers will have noticed that these upper limits are *NOT*
     "`$vec1->Size()-1'" and "`$vec2->Size()-1'", as they would be for any
     other method in this module, but that these offsets may actually
     point to one position *PAST THE END* of the corresponding bit vector.

     This is necessary in order to make it possible to *APPEND* a given
     stretch of bits to the target bit vector instead of *REPLACING*
     something in it.

     For reasons of symmetry and generality, the same applies to the offset
     in the source bit vector, even though such an offset (one position
     past the end of the bit vector) does not serve any practical purpose
     there (but does not cause any harm either).

     (Actually this saves you from the need of testing for this special
     case, in certain circumstances.)

     Note that whenever the term "`$off1 + $len1'" exceeds the size
     "`$vec1->Size()'" of bit vector "`$vec1'" (or if "`$off2 + $len2'"
     exceeds "`$vec2->Size()'"), the corresponding length ("`$len1'" or
     "`$len2'", respectively) is automatically reduced internally so that
     "`$off1 + $len1 <= $vec1->Size()'" (and "`$off2 + $len2 <=
     $vec2->Size()'") holds.

     (Note that this does *NOT* alter the intended result, even though
     this may seem counter-intuitive at first!)

     This may even result in a length ("`$len1'" or "`$len2'") of zero.

     A length of zero for the interval in the SOURCE bit vector ("`$len1
     == 0'") means that the indicated stretch of bits in the target bit
     vector (starting at position "`$off2'") is to be replaced by
     *NOTHING*, i.e., is to be *DELETED*.

     A length of zero for the interval in the *TARGET* bit vector
     ("`$len2' == 0") means that *NOTHING* is replaced, and that the
     stretch of bits from the source bit vector is simply *INSERTED* into
     the target bit vector at the indicated position ("`$off2'").

     If both length parameters are zero, nothing is done at all.

     Note that in contrast to any other method in this module (especially
     "`Interval_Copy()'", "`Insert()'" and "`Delete()'"), this method
     *IMPLICITLY* and *AUTOMATICALLY* adapts the length of the resulting
     bit vector as needed, as given by

          $size = $vec2->Size();   #  before
          $size += $len1 - $len2;  #  after

     (The only other method in this module that changes the size of a bit
     vector is the method "`Resize()'".)

     In other words, replacing a given interval of bits in the target bit
     vector with a longer or shorter stretch of bits from the source bit
     vector, or simply inserting ("`$len2 == 0'") a stretch of bits into
     or deleting ("`$len1 == 0'") an interval of bits from the target bit
     vector will automatically increase or decrease, respectively, the size
     of the target bit vector accordingly.

     For the sake of generality, this may even result in a bit vector with
     a size of zero (containing no bits at all).

     This is also the reason why bit vectors of length zero are permitted
     in this module in the first place, starting with version 5.0.

     Finally, note that "`$vec1'" and "`$vec2'" may be identical, i.e.,
     in-place processing is possible.

     (If you think about that for a while or if you look at the code, you
     will see that this is far from trivial!)

   * `if ($vector->is_empty())'

     Tests whether the given bit vector is empty, i.e., whether ALL of its
     bits are cleared (in the "off" state).

     In "big integer" arithmetic, this is equivalent to testing whether
     the number stored in the bit vector is zero ("0").

     Returns "true" ("1") if the bit vector is empty and "false" ("0")
     otherwise.

     Note that this method also returns "true" ("1") if the given bit
     vector has a length of zero, i.e., if it contains no bits at all.

   * `if ($vector->is_full())'

     Tests whether the given bit vector is full, i.e., whether ALL of its
     bits are set (in the "on" state).

     In "big integer" arithmetic, this is equivalent to testing whether
     the number stored in the bit vector is minus one ("-1").

     Returns "true" ("1") if the bit vector is full and "false" ("0")
     otherwise.

     If the given bit vector has a length of zero (i.e., if it contains no
     bits at all), this method returns "false" ("0").

   * `if ($vec1->equal($vec2))'

     Tests the two given bit vectors for equality.

     Returns "true" ("1") if the two bit vectors are exact copies of one
     another and "false" ("0") otherwise.

   * `$cmp = $vec1->Lexicompare($vec2);'

     Compares the two given bit vectors, which are regarded as UNSIGNED
     numbers in binary representation.

     The method returns "`-1'" if the first bit vector is smaller than the
     second bit vector, "0" if the two bit vectors are exact copies of one
     another and "1" if the first bit vector is greater than the second
     bit vector.

   * `$cmp = $vec1->Compare($vec2);'

     Compares the two given bit vectors, which are regarded as *SIGNED*
     numbers in binary representation.

     The method returns "`-1'" if the first bit vector is smaller than the
     second bit vector, "0" if the two bit vectors are exact copies of one
     another and "1" if the first bit vector is greater than the second
     bit vector.

   * `$string = $vector->to_Hex();'

     Returns a hexadecimal string representing the given bit vector.

     Note that this representation is quite compact, in that it only needs
     at most twice the number of bytes needed to store the bit vector
     itself, internally.

     Note also that since a hexadecimal digit is always worth four bits,
     the length of the resulting string is always a multiple of four bits,
     regardless of the true length (in bits) of the given bit vector.

     Finally, note that the *LEAST* significant hexadecimal digit is
     located at the *RIGHT* end of the resulting string, and the *MOST*
     significant digit at the *LEFT* end.

   * `$vector->from_Hex($string);'

     Allows to read in the contents of a bit vector from a hexadecimal
     string, such as returned by the method "`to_Hex()'" (see above).

     Remember that the least significant bits are always to the right of a
     hexadecimal string, and the most significant bits to the left.
     Therefore, the string is actually read in from right to left while
     the bit vector is filled accordingly, 4 bits at a time, starting with
     the least significant bits and going upward to the most significant
     bits.

     If the given string contains less hexadecimal digits than are needed
     to completely fill the given bit vector, the remaining (most
     significant) bits are all cleared.

     This also means that, even if the given string does not contain
     enough digits to completely fill the given bit vector, the previous
     contents of the bit vector are erased completely.

     If the given string is longer than it needs to fill the given bit
     vector, the superfluous characters are simply ignored.

     (In fact they are ignored completely - they are not even checked for
     proper syntax. See also below for more about that.)

     This behaviour is intentional so that you may read in the string
     representing one bit vector into another bit vector of different
     size, i.e., as much of it as will fit.

     If during the process of reading the given string any character is
     encountered which is not a hexadecimal digit, a fatal syntax error
     ensues ("input string syntax error").

   * `$string = $vector->to_Bin();'

     Returns a binary string representing the given bit vector.

     Example:

          $vector = Bit::Vector->new(8);
          $vector->Primes();
          $string = $vector->to_Bin();
          print "'$string'\n";

     This prints:

          '10101100'

     (Bits #7, #5, #3 and #2 are set.)

     Note that the *LEAST* significant bit is located at the *RIGHT* end
     of the resulting string, and the *MOST* significant bit at the *LEFT*
     end.

   * `$vector->from_Bin($string);'

     This method allows you to read in the contents of a bit vector from a
     binary string, such as returned by the method "`to_Bin()'" (see
     above).

     Note that this method assumes that the *LEAST* significant bit is
     located at the *RIGHT* end of the binary string, and the *MOST*
     significant bit at the *LEFT* end. Therefore, the string is actually
     read in from right to left while the bit vector is filled
     accordingly, one bit at a time, starting with the least significant
     bit and going upward to the most significant bit.

     If the given string contains less binary digits ("0" and "1") than are
     needed to completely fill the given bit vector, the remaining (most
     significant) bits are all cleared.

     This also means that, even if the given string does not contain
     enough digits to completely fill the given bit vector, the previous
     contents of the bit vector are erased completely.

     If the given string is longer than it needs to fill the given bit
     vector, the superfluous characters are simply ignored.

     (In fact they are ignored completely - they are not even checked for
     proper syntax. See also below for more about that.)

     This behaviour is intentional so that you may read in the string
     representing one bit vector into another bit vector of different
     size, i.e., as much of it as will fit.

     If during the process of reading the given string any character is
     encountered which is not either "0" or "1", a fatal syntax error
     ensues ("input string syntax error").

   * `$string = $vector->to_Dec();'

     This method returns a string representing the contents of the given
     bit vector converted to decimal (base 10).

     Note that this method assumes the given bit vector to be *SIGNED* (and
     to contain a number in two's complement binary representation).

     Consequently, whenever the most significant bit of the given bit
     vector is set, the number stored in it is regarded as being
     *NEGATIVE*.

     The resulting string can be fed into "`from_Dec()'" (see below) in
     order to copy the contents of this bit vector to another one (or to
     restore the contents of this one). This is not advisable, though,
     since this would be very inefficient (there are much more efficient
     methods for storing and copying bit vectors in this module).

     Note that such conversion from binary to decimal is inherently slow
     since the bit vector has to be repeatedly divided by 10 with remainder
     until the quotient becomes 0 (each remainder in turn represents a
     single decimal digit of the resulting string).

     This is also true for the implementation of this method in this
     module, even though a considerable effort has been made to speed it
     up: instead of repeatedly dividing by 10, the bit vector is
     repeatedly divided by the largest power of 10 that will fit into a
     machine word. The remainder is then repeatedly divided by 10 using
     only machine word arithmetics, which is much faster than dividing the
     whole bit vector ("divide and rule" principle).

     According to my own measurements, this resulted in an 8-fold speed
     increase over the straightforward approach.

     Still, conversion to decimal should be used only where absolutely
     necessary.

     Keep the resulting string stored in some variable if you need it
     again, instead of converting the bit vector all over again.

     Beware that if you set the configuration for overloaded operators to
     "output=decimal", this method will be called for every bit vector
     enclosed in double quotes!

   * `$vector->from_Dec($string);'

     This method allows you to convert a given decimal number, which may be
     positive or negative, into two's complement binary representation,
     which is then stored in the given bit vector.

     The decimal number should always be provided as a string, to avoid
     possible truncation (due to the limited precision of integers in
     Perl) or formatting (due to Perl's use of scientific notation for
     large numbers), which would lead to errors.

     If the binary representation of the given decimal number is too big
     to fit into the given bit vector (if the given bit vector does not
     contain enough bits to hold it), a fatal "numeric overflow error"
     occurs.

     If the input string contains other characters than decimal digits
     (`0-9') and an optional leading sign ("+" or "-"), a fatal "input
     string syntax error" occurs.

     Beware that large positive numbers which cause the most significant
     bit to be set (e.g. "255" in a bit vector with 8 bits) will be
     printed as negative numbers when converted back to decimal using the
     method "to_Dec()" (e.g.  "-1", in our example), because numbers with
     the most significant bit set are considered to be negative in two's
     complement binary representation.

     Note also that while it is possible to thusly enter negative numbers
     as large positive numbers (e.g. "255" for "-1" in a bit vector with 8
     bits), the contrary isn't, i.e., you cannot enter "-255" for "+1", in
     our example.  A fatal "numeric overflow error" will occur if you try
     to do so.

     If possible program abortion is unwanted or intolerable, use "eval",
     like this:

          eval { $vector->from_Dec("1152921504606846976"); };
          if ($@)
          {
              # an error occurred
          }

     There are four possible error messages:

          if ($@ =~ /item is not a string/)

          if ($@ =~ /input string syntax error/)

          if ($@ =~ /numeric overflow error/)

          if ($@ =~ /unable to allocate memory/)

     Note that the conversion from decimal to binary is costly in terms of
     processing time, since a lot of multiplications have to be carried out
     (in principle, each decimal digit must be multiplied with the binary
     representation of the power of 10 corresponding to its position in
     the decimal number, i.e., 1, 10, 100, 1000, 10000 and so on).

     This is not as time consuming as the opposite conversion, from binary
     to decimal (where successive divisions have to be carried out, which
     are even more expensive than multiplications), but still noticeable.

     Again (as in the case of "`to_Dec()'"), the implementation of this
     method in this module uses the principle of "divide and rule" in order
     to speed up the conversion, i.e., as many decimal digits as possible
     are first accumulated (converted) in a machine word and only then
     stored in the given bit vector.

     Even so, use this method only where absolutely necessary if speed is
     an important consideration in your application.

     Beware that if you set the configuration for overloaded operators to
     "input=decimal", this method will be called for every scalar operand
     you use!

   * `$string = $vector->to_Enum();'

     Converts the given bit vector or set into an enumeration of single
     indices and ranges of indices (".newsrc" style), representing the
     bits that are set ("1") in the bit vector.

     Example:

          $vector = Bit::Vector->new(20);
          $vector->Bit_On(2);
          $vector->Bit_On(3);
          $vector->Bit_On(11);
          $vector->Interval_Fill(5,7);
          $vector->Interval_Fill(13,19);
          print "'", $vector->to_Enum(), "'\n";

     which prints

          '2,3,5-7,11,13-19'

     If the given bit vector is empty, the resulting string will also be
     empty.

     Note, by the way, that the above example can also be written a little
     handier, perhaps, as follows:

          Bit::Vector->Configuration("out=enum");
          $vector = Bit::Vector->new(20);
          $vector->Index_List_Store(2,3,5,6,7,11,13,14,15,16,17,18,19);
          print "'$vector'\n";

   * `$vector->from_Enum($string);'

     This method first empties the given bit vector and then tries to set
     the bits and ranges of bits specified in the given string.

     The string "$string" must only contain unsigned integers or ranges of
     integers (two unsigned integers separated by a dash "-"), separated
     by commas (",").

     All other characters are disallowed (including white space!)  and
     will lead to a fatal "input string syntax error".

     In each range, the first integer (the lower limit of the range) must
     always be less than or equal to the second integer (the upper limit),
     or a fatal "minimum > maximum index" error occurs.

     All integers must lie in the permitted range for the given bit
     vector, i.e., they must lie between "0" and "`$vector->Size()-1'".

     If this condition is not met, a fatal "index out of range" error
     occurs.

     If possible program abortion is unwanted or intolerable, use "eval",
     like this:

          eval { $vector->from_Enum("2,3,5-7,11,13-19"); };
          if ($@)
          {
              # an error occurred
          }

     There are four possible error messages:

          if ($@ =~ /item is not a string/)

          if ($@ =~ /input string syntax error/)

          if ($@ =~ /index out of range/)

          if ($@ =~ /minimum > maximum index/)

     Note that the order of the indices and ranges is irrelevant, i.e.,

          eval { $vector->from_Enum("11,5-7,3,13-19,2"); };

     results in the same vector as in the example above.

     Ranges and indices may also overlap.

     This is because each (single) index in the string is passed to the
     method "`Bit_On()'", internally, and each range to the method
     "`Interval_Fill()'".

     This means that the resulting bit vector is just the union of all the
     indices and ranges specified in the given string.

   * `$vector->Bit_Off($index);'

     Clears the bit with index "$index" in the given vector.

   * `$vector->Bit_On($index);'

     Sets the bit with index "$index" in the given vector.

   * `$vector->bit_flip($index)'

     Flips (i.e., complements) the bit with index "$index" in the given
     vector.

     Moreover, this method returns the NEW state of the bit in question,
     i.e., it returns "0" if the bit is cleared or "1" if the bit is set
     (*AFTER* flipping it).

   * `if ($vector->bit_test($index))'

     Returns the current state of the bit with index "$index" in the given
     vector, i.e., returns "0" if it is cleared (in the "off" state) or
     "1" if it is set (in the "on" state).

   * `$vector->Bit_Copy($index,$bit);'

     Sets the bit with index "$index" in the given vector either to "0" or
     "1" depending on the boolean value "`$bit'".

   * `$vector->LSB($bit);'

     Allows you to set the least significant bit in the given bit vector
     to the value given by the boolean parameter "`$bit'".

     This is a (faster) shortcut for "`$vector->Bit_Copy(0,$bit);'".

   * `$vector->MSB($bit);'

     Allows you to set the most significant bit in the given bit vector to
     the value given by the boolean parameter "`$bit'".

     This is a (faster) shortcut for
     "`$vector->Bit_Copy($vector->Size()-1,$bit);'".

   * `$bit = $vector->lsb();'

     Returns the least significant bit of the given bit vector.

     This is a (faster) shortcut for "`$bit = $vector->bit_test(0);'".

   * `$bit = $vector->msb();'

     Returns the most significant bit of the given bit vector.

     This is a (faster) shortcut for "`$bit =
     $vector->bit_test($vector->Size()-1);'".

   * `$carry_out = $vector->rotate_left();'

          carry             MSB           vector:           LSB
           out:
          +---+            +---+---+---+---     ---+---+---+---+
          |   |  <---+---  |   |   |   |    ...    |   |   |   |  <---+
          +---+      |     +---+---+---+---     ---+---+---+---+      |
                     |                                                |
                     +------------------------------------------------+

     The least significant bit (LSB) is the bit with index "0", the most
     significant bit (MSB) is the bit with index "`$vector->Size()-1'".

   * `$carry_out = $vector->rotate_right();'

          MSB           vector:           LSB            carry
                                                          out:
                   +---+---+---+---     ---+---+---+---+           +---+
            +--->  |   |   |   |    ...    |   |   |   |  ---+---> |   |
            |      +---+---+---+---     ---+---+---+---+     |     +---+
            |                                                |
            +------------------------------------------------+

     The least significant bit (LSB) is the bit with index "0", the most
     significant bit (MSB) is the bit with index "`$vector->Size()-1'".

   * `$carry_out = $vector->shift_left($carry_in);'

          carry         MSB           vector:           LSB         carry
           out:                                                      in:
          +---+        +---+---+---+---     ---+---+---+---+        +---+
          |   |  <---  |   |   |   |    ...    |   |   |   |  <---  |   |
          +---+        +---+---+---+---     ---+---+---+---+        +---+

     The least significant bit (LSB) is the bit with index "0", the most
     significant bit (MSB) is the bit with index "`$vector->Size()-1'".

   * `$carry_out = $vector->shift_right($carry_in);'

          carry         MSB           vector:           LSB         carry
           in:                                                       out:
          +---+        +---+---+---+---     ---+---+---+---+        +---+
          |   |  --->  |   |   |   |    ...    |   |   |   |  --->  |   |
          +---+        +---+---+---+---     ---+---+---+---+        +---+

     The least significant bit (LSB) is the bit with index "0", the most
     significant bit (MSB) is the bit with index "`$vector->Size()-1'".

   * `$vector->Move_Left($bits);'

     Shifts the given bit vector left by "`$bits'" bits, i.e., inserts
     "`$bits'" new bits at the lower end (least significant bit) of the
     bit vector, moving all other bits up by "`$bits'" places, thereby
     losing the "`$bits'" most significant bits.

     The inserted new bits are all cleared (set to the "off" state).

     This method does nothing if "`$bits'" is equal to zero.

     Beware that the whole bit vector is cleared *WITHOUT WARNING* if
     "`$bits'" is greater than or equal to the size of the given bit
     vector!

     In fact this method is equivalent to

          for ( $i = 0; $i < $bits; $i++ ) { $vector->shift_left(0); }

     except that it is much more efficient (for "`$bits'" greater than or
     equal to the number of bits in a machine word on your system) than
     this straightforward approach.

   * `$vector->Move_Right($bits);'

     Shifts the given bit vector right by "`$bits'" bits, i.e., deletes the
     "`$bits'" least significant bits of the bit vector, moving all other
     bits down by "`$bits'" places, thereby creating "`$bits'" new bits at
     the upper end (most significant bit) of the bit vector.

     These new bits are all cleared (set to the "off" state).

     This method does nothing if "`$bits'" is equal to zero.

     Beware that the whole bit vector is cleared *WITHOUT WARNING* if
     "`$bits'" is greater than or equal to the size of the given bit
     vector!

     In fact this method is equivalent to

          for ( $i = 0; $i < $bits; $i++ ) { $vector->shift_right(0); }

     except that it is much more efficient (for "`$bits'" greater than or
     equal to the number of bits in a machine word on your system) than
     this straightforward approach.

   * `$vector->Insert($offset,$bits);'

     This method inserts "`$bits'" fresh new bits at position "$offset" in
     the given bit vector.

     The "`$bits'" most significant bits are lost, and all bits starting
     with bit number "$offset" up to and including bit number
     "`$vector->Size()-$bits-1'" are moved up by "`$bits'" places.

     The now vacant "`$bits'" bits starting at bit number "$offset" (up to
     and including bit number "`$offset+$bits-1'") are then set to zero
     (cleared).

     Note that this method does *NOT* increase the size of the given bit
     vector, i.e., the bit vector is *NOT* extended at its upper end to
     "rescue" the "`$bits'" uppermost (most significant) bits - instead,
     these bits are lost forever.

     If you don't want this to happen, you have to increase the size of the
     given bit vector *EXPLICITLY* and *BEFORE* you perform the "Insert"
     operation, with a statement such as the following:

          $vector->Resize($vector->Size() + $bits);

     Or use the method "`Interval_Substitute()'" instead of "`Insert()'",
     which performs automatic growing and shrinking of its target bit
     vector.

     Note also that "$offset" must lie in the permitted range between "0"
     and "`$vector->Size()-1'", or a fatal "offset out of range" error
     will occur.

     If the term "`$offset + $bits'" exceeds "`$vector->Size()-1'", all
     the bits starting with bit number "$offset" up to bit number
     "`$vector->Size()-1'" are simply cleared.

   * `$vector->Delete($offset,$bits);'

     This method deletes, i.e., removes the bits starting at position
     "$offset" up to and including bit number "`$offset+$bits-1'" from the
     given bit vector.

     The remaining uppermost bits (starting at position "`$offset+$bits'"
     up to and including bit number "`$vector->Size()-1'") are moved down
     by "`$bits'" places.

     The now vacant uppermost (most significant) "`$bits'" bits are then
     set to zero (cleared).

     Note that this method does *NOT* decrease the size of the given bit
     vector, i.e., the bit vector is *NOT* clipped at its upper end to
     "get rid of" the vacant "`$bits'" uppermost bits.

     If you don't want this, i.e., if you want the bit vector to shrink
     accordingly, you have to do so *EXPLICITLY* and *AFTER* the "Delete"
     operation, with a couple of statements such as these:

          $size = $vector->Size();
          if ($bits > $size) { $bits = $size; }
          $vector->Resize($size - $bits);

     Or use the method "`Interval_Substitute()'" instead of "`Delete()'",
     which performs automatic growing and shrinking of its target bit
     vector.

     Note also that "$offset" must lie in the permitted range between "0"
     and "`$vector->Size()-1'", or a fatal "offset out of range" error
     will occur.

     If the term "`$offset + $bits'" exceeds "`$vector->Size()-1'", all
     the bits starting with bit number "$offset" up to bit number
     "`$vector->Size()-1'" are simply cleared.

   * `$carry = $vector->increment();'

     This method increments the given bit vector.

     Note that this method regards bit vectors as being unsigned, i.e.,
     the largest possible positive number is directly followed by the
     smallest possible (or greatest possible, speaking in absolute terms)
     negative number:

          before:  2 ^ (b-1) - 1    (= "0111...1111")
          after:   2 ^ (b-1)        (= "1000...0000")

     where "b" is the number of bits of the given bit vector.

     The method returns "false" ("0") in all cases except when a carry
     over occurs (in which case it returns "true", i.e., "1"), which
     happens when the number "1111...1111" is incremented, which gives
     "0000...0000" plus a carry over to the next higher (binary) digit.

     This can be used for the terminating condition of a "while" loop, for
     instance, in order to cycle through all possible values the bit
     vector can assume.

   * `$carry = $vector->decrement();'

     This method decrements the given bit vector.

     Note that this method regards bit vectors as being unsigned, i.e.,
     the smallest possible (or greatest possible, speaking in absolute
     terms) negative number is directly followed by the largest possible
     positive number:

          before:  2 ^ (b-1)        (= "1000...0000")
          after:   2 ^ (b-1) - 1    (= "0111...1111")

     where "b" is the number of bits of the given bit vector.

     The method returns "false" ("0") in all cases except when a carry
     over occurs (in which case it returns "true", i.e., "1"), which
     happens when the number "0000...0000" is decremented, which gives
     "1111...1111" minus a carry over to the next higher (binary) digit.

     This can be used for the terminating condition of a "while" loop, for
     instance, in order to cycle through all possible values the bit
     vector can assume.

   * `$overflow = $vec2->inc($vec1);'

     This method copies the contents of bit vector "`$vec1'" to bit vector
     "`$vec2'" and increments the copy (not the original).

     If by incrementing the number its sign becomes invalid, the return
     value ("overflow" flag) will be true ("1"), or false ("0") if not.
     (See the description of the method "add()" below for a more in-depth
     explanation of what "overflow" means).

     Note that in-place operation is also possible, i.e., "`$vec1'" and
     "`$vec2'" may be identical.

   * `$overflow = $vec2->dec($vec1);'

     This method copies the contents of bit vector "`$vec1'" to bit vector
     "`$vec2'" and decrements the copy (not the original).

     If by decrementing the number its sign becomes invalid, the return
     value ("overflow" flag) will be true ("1"), or false ("0") if not.
     (See the description of the method "subtract()" below for a more
     in-depth explanation of what "overflow" means).

     Note that in-place operation is also possible, i.e., "`$vec1'" and
     "`$vec2'" may be identical.

   * `$carry = $vec3->add($vec1,$vec2,$carry);'

     `($carry,$overflow) = $vec3->add($vec1,$vec2,$carry);'

     This method adds the two numbers contained in bit vector "`$vec1'"
     and "`$vec2'" with carry "`$carry'" and stores the result in bit
     vector "`$vec3'".

     I.e.,             $vec3 = $vec1 + $vec2 + $carry

     Note that the "`$carry'" parameter is a boolean value, i.e., only its
     least significant bit is taken into account. (Think of it as though
     "`$carry &= 1;'" was always executed internally.)

     In scalar context, the method returns a boolean value which indicates
     if a carry over (to the next higher bit position) has occured. In
     list context, the method returns the carry and the overflow flag (in
     this order).

     The overflow flag is true ("1") if the sign (i.e., the most
     significant bit) of the result is wrong. This can happen when adding
     two very large positive numbers or when adding two (by their absolute
     value) very large negative numbers. See also further below.

     The carry in- and output is needed mainly for cascading, i.e., to add
     numbers that are fragmented into several pieces.

     Example:

          # initialize

          for ( $i = 0; $i < $n; $i++ )
          {
              $a[$i] = Bit::Vector->new($bits);
              $b[$i] = Bit::Vector->new($bits);
              $c[$i] = Bit::Vector->new($bits);
          }

          # fill @a and @b

          # $a[  0 ] is low order part,
          # $a[$n-1] is high order part,
          # and same for @b

          # add

          $carry = 0;
          for ( $i = 0; $i < $n; $i++ )
          {
              $carry = $c[$i]->add($a[$i],$b[$i],$carry);
          }

     Note that it makes no difference to this method whether the numbers
     in "`$vec1'" and "`$vec2'" are unsigned or signed (i.e., in two's
     complement binary representation).

     Note however that the return value (carry flag) is not meaningful
     when the numbers are *SIGNED*.

     Moreover, when the numbers are signed, a special type of error can
     occur which is commonly called an "overflow error".

     An overflow error occurs when the sign of the result (its most
     significant bit) is flipped (i.e., falsified) by a carry over from
     the next-lower bit position ("MSB-1").

     In fact matters are a bit more complicated than that: the overflow
     flag is set to "true" whenever there is a carry over from bit
     position MSB-1 to the most significant bit (MSB) but no carry over
     from the MSB to the output carry flag, or vice-versa, i.e., when
     there is no carry over from bit position MSB-1 to the most
     significant bit (MSB) but a carry over to the output carry flag.

     Thus the overflow flag is the result of an exclusive-or operation
     between incoming and outgoing carry over at the most significant bit
     position.

   * `$carry = $vec3->subtract($vec1,$vec2,$carry);'

     `($carry,$overflow) = $vec3->subtract($vec1,$vec2,$carry);'

     This method subtracts the two numbers contained in bit vector
     "`$vec1'" and "`$vec2'" with carry "`$carry'" and stores the result
     in bit vector "`$vec3'".

     I.e.,             $vec3 = $vec1 - $vec2 - $carry

     Note that the "`$carry'" parameter is a boolean value, i.e., only its
     least significant bit is taken into account. (Think of it as though
     "`$carry &= 1;'" was always executed internally.)

     In scalar context, the method returns a boolean value which indicates
     if a carry over (to the next higher bit position) has occured. In
     list context, the method returns the carry and the overflow flag (in
     this order).

     The overflow flag is true ("1") if the sign (i.e., the most
     significant bit) of the result is wrong. This can happen when
     subtracting a very large negative number from a very large positive
     number or vice-versa. See also further below.

     The carry in- and output is needed mainly for cascading, i.e., to
     subtract numbers that are fragmented into several pieces.

     Example:

          # initialize

          for ( $i = 0; $i < $n; $i++ )
          {
              $a[$i] = Bit::Vector->new($bits);
              $b[$i] = Bit::Vector->new($bits);
              $c[$i] = Bit::Vector->new($bits);
          }

          # fill @a and @b

          # $a[  0 ] is low order part,
          # $a[$n-1] is high order part,
          # and same for @b

          # subtract

          $carry = 0;
          for ( $i = 0; $i < $n; $i++ )
          {
              $carry = $c[$i]->subtract($a[$i],$b[$i],$carry);
          }

     Note that it makes no difference to this method whether the numbers
     in "`$vec1'" and "`$vec2'" are unsigned or signed (i.e., in two's
     complement binary representation).

     Note however that the return value (carry flag) is not meaningful
     when the numbers are *SIGNED*.

     Moreover, when the numbers are signed, a special type of error can
     occur which is commonly called an "overflow error".

     An overflow error occurs when the sign of the result (its most
     significant bit) is flipped (i.e., falsified) by a carry over from
     the next-lower bit position ("MSB-1").

     In fact matters are a bit more complicated than that: the overflow
     flag is set to "true" whenever there is a carry over from bit
     position MSB-1 to the most significant bit (MSB) but no carry over
     from the MSB to the output carry flag, or vice-versa, i.e., when
     there is no carry over from bit position MSB-1 to the most
     significant bit (MSB) but a carry over to the output carry flag.

     Thus the overflow flag is the result of an exclusive-or operation
     between incoming and outgoing carry over at the most significant bit
     position.

   * `$vec2->Negate($vec1);'

     This method calculates the two's complement of the number in bit
     vector "`$vec1'" and stores the result in bit vector "`$vec2'".

     Calculating the two's complement of a given number in binary
     representation consists of inverting all bits and incrementing the
     result by one.

     This is the same as changing the sign of the given number from "+" to
     "-" or vice-versa. In other words, applying this method twice on a
     given number yields the original number again.

     Note that in-place processing is also possible, i.e., "`$vec1'" and
     "`$vec2'" may be identical.

     Most importantly, beware that this method produces a counter-intuitive
     result if the number contained in bit vector "`$vec1'" is `2 ^ (n-1)'
     (i.e., "1000...0000"), where "n" is the number of bits the given bit
     vector contains: The negated value of this number is the number
     itself!

   * `$vec2->Absolute($vec1);'

     Depending on the sign (i.e., the most significant bit) of the number
     in bit vector "`$vec1'", the contents of bit vector "`$vec1'" are
     copied to bit vector "`$vec2'" either with the method "`Copy()'" (if
     the number in bit vector "`$vec1'" is positive), or with "`Negate()'"
     (if the number in bit vector "`$vec1'" is negative).

     In other words, this method calculates the absolute value of the
     number in bit vector "`$vec1'" and stores the result in bit vector
     "`$vec2'".

     Note that in-place processing is also possible, i.e., "`$vec1'" and
     "`$vec2'" may be identical.

     Most importantly, beware that this method produces a counter-intuitive
     result if the number contained in bit vector "`$vec1'" is `2 ^ (n-1)'
     (i.e., "1000...0000"), where "n" is the number of bits the given bit
     vector contains: The absolute value of this number is the number
     itself, even though this number is still negative by definition (the
     most significant bit is still set)!

   * `$sign = $vector->Sign();'

     This method returns "0" if all bits in the given bit vector are
     cleared, i.e., if the given bit vector contains the number "0", or if
     the given bit vector has a length of zero (contains no bits at all).

     If not all bits are cleared, this method returns "`-1'" if the most
     significant bit is set (i.e., if the bit vector contains a negative
     number), or "1" otherwise (i.e., if the bit vector contains a
     positive number).

   * `$vec3->Multiply($vec1,$vec2);'

     This method multiplies the two numbers contained in bit vector
     "`$vec1'" and "`$vec2'" and stores the result in bit vector "`$vec3'".

     Note that this method regards its arguments as *SIGNED*.

     If you want to make sure that a large number can never be treated as
     being negative by mistake, make your bit vectors at least one bit
     longer than the largest number you wish to represent, right from the
     start, or proceed as follows:

          $msb1 = $vec1->msb();
          $msb2 = $vec2->msb();
          $vec1->Resize($vec1->Size()+1);
          $vec2->Resize($vec2->Size()+1);
          $vec3->Resize($vec3->Size()+1);
          $vec1->MSB($msb1);
          $vec2->MSB($msb2);
          $vec3->Multiply($vec1,$vec2);

     Note also that all three bit vector arguments must in principle obey
     the rule of matching sizes, but that the bit vector "`$vec3'" may be
     larger than the two factors "`$vec1'" and "`$vec2'".

     In fact multiplying two binary numbers with "n" bits may yield a
     result which is at most "`2n'" bits long.

     Therefore, it is usually a good idea to let bit vector "`$vec3'" have
     twice the size of bit vector "`$vec1'" and "`$vec2'", unless you are
     absolutely sure that the result will fit into a bit vector of the same
     size as the two factors.

     If you are wrong, a fatal "numeric overflow error" will occur.

     Finally, note that in-place processing is possible, i.e., "`$vec3'"
     may be identical with "`$vec1'" or "`$vec2'", or both.

   * `$quot->Divide($vec1,$vec2,$rest);'

     This method divides the two numbers contained in bit vector "`$vec1'"
     and "`$vec2'" and stores the quotient in bit vector "`$quot'" and the
     remainder in bit vector "`$rest'".

     I.e.,             $quot = $vec1 / $vec2;  #  div             $rest =
     $vec1 % $vec2;  #  mod

     Therefore, "`$quot'" and "`$rest'" must be two *DISTINCT* bit vectors,
     or a fatal "result vector(s) must be distinct" error will occur.

     Note also that a fatal "division by zero error" will occur if
     "`$vec2'" is equal to zero.

     Note further that this method regards its arguments as *SIGNED*.

     If you want to make sure that a large number can never be treated as
     being negative by mistake, make your bit vectors at least one bit
     longer than the largest number you wish to represent, right from the
     start, or proceed as follows:

          $msb1 = $vec1->msb();
          $msb2 = $vec2->msb();
          $vec1->Resize($vec1->Size()+1);
          $vec2->Resize($vec2->Size()+1);
          $quot->Resize($quot->Size()+1);
          $rest->Resize($rest->Size()+1);
          $vec1->MSB($msb1);
          $vec2->MSB($msb2);
          $quot->Divide($vec1,$vec2,$rest);

     Finally, note that in-place processing is possible, i.e., "`$quot'"
     may be identical with "`$vec1'" or "`$vec2'" or both, and "`$rest'"
     may also be identical with "`$vec1'" or "`$vec2'" or both, as long as
     "`$quot'" and "`$rest'" are distinct. (!)

   * `$vec3->GCD($vec1,$vec2);'

     This method calculates the "Greatest Common Divisor" of the two
     numbers contained in bit vector "`$vec1'" and "`$vec2'" and stores
     the result in bit vector "`$vec3'".

     The method uses Euklid's algorithm internally:

          int GCD(int a, int b)
          {
              int t;

          while (b != 0)
          {
              t = a % b; /* = remainder of (a div b) */
              a = b;
              b = t;
          }
          return(a);
              }

     Note that a fatal "division by zero error" will occur if any of the
     two numbers is equal to zero.

     Note also that this method regards its two arguments as *SIGNED* but
     that it actually uses the *ABSOLUTE VALUE* of its two arguments
     internally, i.e., the RESULT of this method will *ALWAYS* be
     *POSITIVE*.

   * `$vec3->Power($vec1,$vec2);'

     This method calculates the exponentiation of base "`$vec1'" elevated
     to the "`$vec2'" power, i.e., "`$vec1 ** $vec2'", and stores the
     result in bit vector "`$vec3'".

     The method uses an efficient divide-and-conquer algorithm:

     Suppose the exponent is (decimal) 13, for example. The binary
     representation of this exponent is "1101".

     This means we want to calculate

          $vec1 * $vec1 * $vec1 * $vec1 * $vec1 * $vec1 * $vec1 * $vec1 *
          $vec1 * $vec1 * $vec1 * $vec1 *
          $vec1

     That is, "`$vec1'" multiplied with itself 13 times. The grouping into
     lines above is no coincidence. The first line comprises 8 factors,
     the second contains 4, and the last line just one. This just happens
     to be the binary representation of 13. `;-)'

     We then calculate a series of squares (of squares of squares...) of
     the base, i.e.,

          $power[0] = $vec1;
          $power[1] = $vec1 * $vec1;
          $power[2] = $power[1] * $power[1];
          $power[3] = $power[2] * $power[2];
          etc.

     To calculate the power of our example, we simply initialize our result
     with 1 and consecutively multiply it with the items of the series of
     powers we just calculated, if the corresponding bit of the binary
     representation of the exponent is set:

          $result = 1;
          $result *= $power[0] if ($vec2 & 1);
          $result *= $power[1] if ($vec2 & 2);
          $result *= $power[2] if ($vec2 & 4);
          $result *= $power[3] if ($vec2 & 8);
          etc.

     The bit vector "`$vec3'" must be of the same size as the base
     "`$vec1'" or greater. "`$vec3'" and "`$vec1'" may be the same vector
     (i.e., in-place calculation as in "`$vec1 **= $vec2;'" is possible),
     but "`$vec3'" and "`$vec2'" must be distinct. Finally, the exponent
     "`$vec2'" must be positive. A fatal error occurs if any of these
     conditions is not met.

   * `$vector->Block_Store($buffer);'

     This method allows you to load the contents of a given bit vector in
     one go.

     This is useful when you store the contents of a bit vector in a file,
     for instance (using method "`Block_Read()'"), and when you want to
     restore the previously saved bit vector.

     For this, "`$buffer'" *MUST* be a string (*NO* automatic conversion
     from numeric to string is provided here as would normally in Perl!)
     containing the bit vector in "low order byte first" order.

     If the given string is shorter than what is needed to completely fill
     the given bit vector, the remaining (most significant) bytes of the
     bit vector are filled with zeros, i.e., the previous contents of the
     bit vector are always erased completely.

     If the given string is longer than what is needed to completely fill
     the given bit vector, the superfluous bytes are simply ignored.

     See `sysread', see Perlfunc (perl.info), for how to read
     in the contents of "`$buffer'" from a file prior to passing it to
     this method.

   * `$buffer = $vector->Block_Read();'

     This method allows you to export the contents of a given bit vector in
     one block.

     This is useful when you want to save the contents of a bit vector for
     later, for instance in a file.

     The advantage of this method is that it allows you to do so in the
     compactest possible format, in binary.

     The method returns a Perl string which contains an exact copy of the
     contents of the given bit vector in "low order byte first" order.

     See `syswrite', see Perlfunc (perl.info), for how to write
     the data from this string to a file.

   * `$size = $vector->Word_Size();'

     Each bit vector is internally organized as an array of machine words.

     The methods whose names begin with "Word_" allow you to access this
     internal array of machine words.

     Note that because the size of a machine word may vary from system to
     system, these methods are inherently *MACHINE-DEPENDENT*!

     Therefore, *DO NOT USE* these methods unless you are absolutely
     certain that portability of your code is not an issue!

     You have been warned!

     To be machine-independent, use the methods whose names begin with
     "`Chunk_'" instead, with chunk sizes no greater than 32 bits.

     The method "`Word_Size()'" returns the number of machine words that
     the internal array of words of the given bit vector contains.

     This is similar in function to the term "`scalar(@array)'" for a Perl
     array.

   * `$vector->Word_Store($offset,$word);'

     This method allows you to store a given value "`$word'" at a given
     position "$offset" in the internal array of words of the given bit
     vector.

     Note that "$offset" must lie in the permitted range between "0" and
     "`$vector->Word_Size()-1'", or a fatal "offset out of range" error
     will occur.

     This method is similar in function to the expression
     "`$array[$offset] = $word;'" for a Perl array.

   * `$word = $vector->Word_Read($offset);'

     This method allows you to access the value of a given machine word at
     position "$offset" in the internal array of words of the given bit
     vector.

     Note that "$offset" must lie in the permitted range between "0" and
     "`$vector->Word_Size()-1'", or a fatal "offset out of range" error
     will occur.

     This method is similar in function to the expression "`$word =
     $array[$offset];'" for a Perl array.

   * `$vector->Word_List_Store(@words);'

     This method allows you to store a list of values "`@words'" in the
     internal array of machine words of the given bit vector.

     Thereby the *LEFTMOST* value in the list ("`$words[0]'") is stored in
     the *LEAST* significant word of the internal array of words (the one
     with offset "0"), the next value from the list ("`$words[1]'") is
     stored in the word with offset "1", and so on, as intuitively
     expected.

     If the list "`@words'" contains fewer elements than the internal
     array of words of the given bit vector contains machine words, the
     remaining (most significant) words are filled with zeros.

     If the list "`@words'" contains more elements than the internal array
     of words of the given bit vector contains machine words, the
     superfluous values are simply ignored.

     This method is comparable in function to the expression "`@array =
     @words;'" for a Perl array.

   * `@words = $vector->Word_List_Read();'

     This method allows you to retrieve the internal array of machine
     words of the given bit vector all at once.

     Thereby the *LEFTMOST* value in the returned list ("`$words[0]'") is
     the *LEAST* significant word from the given bit vector, and the
     *RIGHTMOST* value in the returned list ("`$words[$#words]'") is the
     *MOST* significant word of the given bit vector.

     This method is similar in function to the expression "`@words =
     @array;'" for a Perl array.

   * `$vector->Word_Insert($offset,$count);'

     This method inserts "$count" empty new machine words at position
     "$offset" in the internal array of words of the given bit vector.

     The "$count" most significant words are lost, and all words starting
     with word number "$offset" up to and including word number
     "`$vector->Word_Size()-$count-1'" are moved up by "$count" places.

     The now vacant "$count" words starting at word number "$offset" (up
     to and including word number "`$offset+$count-1'") are then set to
     zero (cleared).

     Note that this method does *NOT* increase the size of the given bit
     vector, i.e., the bit vector is *NOT* extended at its upper end to
     "rescue" the "$count" uppermost (most significant) words - instead,
     these words are lost forever.

     If you don't want this to happen, you have to increase the size of the
     given bit vector *EXPLICITLY* and *BEFORE* you perform the "Insert"
     operation, with a statement such as the following:

          $vector->Resize($vector->Size() + $count * Bit::Vector->Word_Bits());

     Note also that "$offset" must lie in the permitted range between "0"
     and "`$vector->Word_Size()-1'", or a fatal "offset out of range"
     error will occur.

     If the term "`$offset + $count'" exceeds "`$vector->Word_Size()-1'",
     all the words starting with word number "$offset" up to word number
     "`$vector->Word_Size()-1'" are simply cleared.

   * `$vector->Word_Delete($offset,$count);'

     This method deletes, i.e., removes the words starting at position
     "$offset" up to and including word number "`$offset+$count-1'" from
     the internal array of machine words of the given bit vector.

     The remaining uppermost words (starting at position "`$offset+$count'"
     up to and including word number "`$vector->Word_Size()-1'") are moved
     down by "$count" places.

     The now vacant uppermost (most significant) "$count" words are then
     set to zero (cleared).

     Note that this method does *NOT* decrease the size of the given bit
     vector, i.e., the bit vector is *NOT* clipped at its upper end to
     "get rid of" the vacant "$count" uppermost words.

     If you don't want this, i.e., if you want the bit vector to shrink
     accordingly, you have to do so *EXPLICITLY* and *AFTER* the "Delete"
     operation, with a couple of statements such as these:

          $bits = $vector->Size();
          $count *= Bit::Vector->Word_Bits();
          if ($count > $bits) { $count = $bits; }
          $vector->Resize($bits - $count);

     Note also that "$offset" must lie in the permitted range between "0"
     and "`$vector->Word_Size()-1'", or a fatal "offset out of range"
     error will occur.

     If the term "`$offset + $count'" exceeds "`$vector->Word_Size()-1'",
     all the words starting with word number "$offset" up to word number
     "`$vector->Word_Size()-1'" are simply cleared.

   * `$vector->Chunk_Store($chunksize,$offset,$chunk);'

     This method allows you to set more than one bit at a time with
     different values.

     You can access chunks (i.e., ranges of contiguous bits) between one
     and at most "`Bit::Vector->Long_Bits()'" bits wide.

     In order to be portable, though, you should never use chunk sizes
     larger than 32 bits.

     If the given "`$chunksize'" does not lie between "1" and
     "`Bit::Vector->Long_Bits()'", a fatal "chunk size out of range" error
     will occur.

     The method copies the "`$chunksize'" least significant bits from the
     value "`$chunk'" to the given bit vector, starting at bit position
     "$offset" and proceeding upwards until bit number
     "`$offset+$chunksize-1'".

     (I.e., bit number "0" of "`$chunk'" becomes bit number "$offset" in
     the given bit vector, and bit number "`$chunksize-1'" becomes bit
     number "`$offset+$chunksize-1'".)

     If the term "`$offset+$chunksize-1'" exceeds "`$vector->Size()-1'",
     the corresponding superfluous (most significant) bits from "`$chunk'"
     are simply ignored.

     Note that "$offset" itself must lie in the permitted range between
     "0" and "`$vector->Size()-1'", or a fatal "offset out of range" error
     will occur.

     This method (as well as the other "`Chunk_'" methods) is useful, for
     example, when you are reading in data in chunks of, say, 8 bits, which
     you need to access later, say, using 16 bits at a time (like audio CD
     wave files, for instance).

   * `$chunk = $vector->Chunk_Read($chunksize,$offset);'

     This method allows you to read the values of more than one bit at a
     time.

     You can read chunks (i.e., ranges of contiguous bits) between one and
     at most "`Bit::Vector->Long_Bits()'" bits wide.

     In order to be portable, though, you should never use chunk sizes
     larger than 32 bits.

     If the given "`$chunksize'" does not lie between "1" and
     "`Bit::Vector->Long_Bits()'", a fatal "chunk size out of range" error
     will occur.

     The method returns the "`$chunksize'" bits from the given bit vector
     starting at bit position "$offset" and proceeding upwards until bit
     number "`$offset+$chunksize-1'".

     (I.e., bit number "$offset" of the given bit vector becomes bit number
     "0" of the returned value, and bit number "`$offset+$chunksize-1'"
     becomes bit number "`$chunksize-1'".)

     If the term "`$offset+$chunksize-1'" exceeds "`$vector->Size()-1'",
     the non-existent bits are simply not returned.

     Note that "$offset" itself must lie in the permitted range between
     "0" and "`$vector->Size()-1'", or a fatal "offset out of range" error
     will occur.

   * `$vector->Chunk_List_Store($chunksize,@chunks);'

     This method allows you to fill the given bit vector with a list of
     data packets ("chunks") of any size ("`$chunksize'") you like (within
     certain limits).

     In fact the given "`$chunksize'" must lie in the range between "1"
     and "`Bit::Vector->Long_Bits()'", or a fatal "chunk size out of
     range" error will occur.

     In order to be portable, though, you should never use chunk sizes
     larger than 32 bits.

     The given bit vector is thereby filled in ascending order: The first
     chunk from the list (i.e., "`$chunks[0]'") fills the "`$chunksize'"
     least significant bits, the next chunk from the list ("`$chunks[1]'")
     fills the bits number "`$chunksize'" to number "`2*$chunksize-1'",
     the third chunk ("`$chunks[2]'") fills the bits number
     "`2*$chunksize'", to number "`3*$chunksize-1'", and so on.

     If there a less chunks in the list than are needed to fill the entire
     bit vector, the remaining (most significant) bits are cleared, i.e.,
     the previous contents of the given bit vector are always erased
     completely.

     If there are more chunks in the list than are needed to fill the
     entire bit vector, and/or if a chunk extends beyond
     "`$vector->Size()-1'" (which happens whenever "`$vector->Size()'" is
     not a multiple of "`$chunksize'"), the superfluous chunks and/or bits
     are simply ignored.

     The method is useful, for example (and among many other applications),
     for the conversion of packet sizes in a data stream.

     This method can also be used to store an octal string in a given bit
     vector:

          $vector->Chunk_List_Store(3, split(//, reverse $string));

     Note however that unlike the conversion methods "`from_Hex()'",
     "`from_Bin()'", "`from_Dec()'" and "`from_Enum()'", this statement
     does not include any syntax checking, i.e., it may fail silently,
     without warning.

     To perform syntax checking, add the following statements:

          if ($string =~ /^[0-7]+$/)
          {
              # okay, go ahead with conversion as shown above
          }
          else
          {
              # error, string contains other than octal characters
          }

     Another application is to store a repetitive pattern in a given bit
     vector:

          $pattern = 0xDEADBEEF;
          $length = 32;            # = length of $pattern in bits
          $size = $vector->Size();
          $factor = int($size / $length);
          if ($size % $length) { $factor++; }
          $vector->Chunk_List_Store($length, ($pattern) x $factor);

   * `@chunks = $vector->Chunk_List_Read($chunksize);'

     This method allows you to access the contents of the given bit vector
     in form of a list of data packets ("chunks") of a size
     ("`$chunksize'") of your choosing (within certain limits).

     In fact the given "`$chunksize'" must lie in the range between "1"
     and "`Bit::Vector->Long_Bits()'", or a fatal "chunk size out of
     range" error will occur.

     In order to be portable, though, you should never use chunk sizes
     larger than 32 bits.

     The given bit vector is thereby read in ascending order: The
     "`$chunksize'" least significant bits (bits number "0" to
     "`$chunksize-1'") become the first chunk in the returned list (i.e.,
     "`$chunks[0]'"). The bits number "`$chunksize'" to "`2*$chunksize-1'"
     become the next chunk in the list ("`$chunks[1]'"), and so on.

     If "`$vector->Size()'" is not a multiple of "`$chunksize'", the last
     chunk in the list will contain fewer bits than "`$chunksize'".

     *BEWARE* that for large bit vectors and/or small values of
     "`$chunksize'", the number of returned list elements can be extremely
     large! *BE CAREFUL!*

     You could blow up your application with lack of memory (each list
     element is a full-grown Perl scalar, internally, with an associated
     memory overhead for its administration!) or at least cause a
     noticeable, more or less long-lasting "freeze" of your application!

     Possible applications:

     The method is especially useful in the conversion of packet sizes in
     a data stream.

     This method can also be used to convert a given bit vector to a string
     of octal numbers:

          $string = reverse join('', $vector->Chunk_List_Read(3));

   * `$vector->Index_List_Remove(@indices);'

     This method allows you to specify a list of indices of bits which
     should be turned off in the given bit vector.

     In fact this method is a shortcut for

          foreach $index (@indices)
          {
              $vector->Bit_Off($index);
          }

     In contrast to all other import methods in this module, this method
     does *NOT* clear the given bit vector before processing its list of
     arguments.

     Instead, this method allows you to accumulate the results of various
     consecutive calls.

     (The same holds for the method "`Index_List_Store()'". As a
     consequence, you can "wipe out" what you did using the method
     "`Index_List_Remove()'" by passing the identical argument list to the
     method "`Index_List_Store()'".)

   * `$vector->Index_List_Store(@indices);'

     This method allows you to specify a list of indices of bits which
     should be turned on in the given bit vector.

     In fact this method is a shortcut for

          foreach $index (@indices)
          {
              $vector->Bit_On($index);
          }

     In contrast to all other import methods in this module, this method
     does *NOT* clear the given bit vector before processing its list of
     arguments.

     Instead, this method allows you to accumulate the results of various
     consecutive calls.

     (The same holds for the method "`Index_List_Remove()'". As a
     consequence, you can "wipe out" what you did using the method
     "`Index_List_Store()'" by passing the identical argument list to the
     method "`Index_List_Remove()'".)

   * `@indices = $vector->Index_List_Read();'

     This method returns a list of Perl scalars.

     The list contains one scalar for each set bit in the given bit vector.

     *BEWARE* that for large bit vectors, this can result in a literally
     overwhelming number of list elements! *BE CAREFUL!* You could run out
     of memory or slow down your application considerably!

     Each scalar contains the number of the index corresponding to the bit
     in question.

     These indices are always returned in ascending order.

     If the given bit vector is empty (contains only cleared bits) or if
     it has a length of zero (if it contains no bits at all), the method
     returns an empty list.

     This method can be useful, for instance, to obtain a list of prime
     numbers:

          $limit = 1000; # or whatever
          $vector = Bit::Vector->new($limit+1);
          $vector->Primes();
          @primes = $vector->Index_List_Read();

   * `$set3->Union($set1,$set2);'

     This method calculates the union of "`$set1'" and "`$set2'" and stores
     the result in "`$set3'".

     This is usually written as "`$set3 = $set1 u $set2'" in set theory
     (where "u" is the "cup" operator).

     (On systems where the "cup" character is unavailable this operator is
     often denoted by a plus sign "+".)

     In-place calculation is also possible, i.e., "`$set3'" may be
     identical with "`$set1'" or "`$set2'" or both.

   * `$set3->Intersection($set1,$set2);'

     This method calculates the intersection of "`$set1'" and "`$set2'" and
     stores the result in "`$set3'".

     This is usually written as "`$set3 = $set1 n $set2'" in set theory
     (where "n" is the "cap" operator).

     (On systems where the "cap" character is unavailable this operator is
     often denoted by an asterisk "*".)

     In-place calculation is also possible, i.e., "`$set3'" may be
     identical with "`$set1'" or "`$set2'" or both.

   * `$set3->Difference($set1,$set2);'

     This method calculates the difference of "`$set1'" less "`$set2'" and
     stores the result in "`$set3'".

     This is usually written as "`$set3 = $set1 \ $set2'" in set theory
     (where "\" is the "less" operator).

     In-place calculation is also possible, i.e., "`$set3'" may be
     identical with "`$set1'" or "`$set2'" or both.

   * `$set3->ExclusiveOr($set1,$set2);'

     This method calculates the symmetric difference of "`$set1'" and
     "`$set2'" and stores the result in "`$set3'".

     This can be written as "`$set3 = ($set1 u $set2) \ ($set1 n $set2)'"
     in set theory (the union of the two sets less their intersection).

     When sets are implemented as bit vectors then the above formula is
     equivalent to the exclusive-or between corresponding bits of the two
     bit vectors (hence the name of this method).

     Note that this method is also much more efficient than evaluating the
     above formula explicitly since it uses a built-in machine language
     instruction internally.

     In-place calculation is also possible, i.e., "`$set3'" may be
     identical with "`$set1'" or "`$set2'" or both.

   * `$set2->Complement($set1);'

     This method calculates the complement of "`$set1'" and stores the
     result in "`$set2'".

     In "big integer" arithmetic, this is equivalent to calculating the
     one's complement of the number stored in the bit vector "`$set1'" in
     binary representation.

     In-place calculation is also possible, i.e., "`$set2'" may be
     identical with "`$set1'".

   * `if ($set1->subset($set2))'

     Returns "true" ("1") if "`$set1'" is a subset of "`$set2'" (i.e.,
     completely contained in "`$set2'") and "false" ("0") otherwise.

     This means that any bit which is set ("1") in "`$set1'" must also be
     set in "`$set2'", but "`$set2'" may contain set bits which are not
     set in "`$set1'", in order for the condition of subset relationship
     to be true between these two sets.

     Note that by definition, if two sets are identical, they are also
     subsets (and also supersets) of each other.

   * `$norm = $set->Norm();'

     Returns the norm (number of bits which are set) of the given vector.

     This is equivalent to the number of elements contained in the given
     set.

   * `$min = $set->Min();'

     Returns the minimum of the given set, i.e., the minimum of all
     indices of all set bits in the given bit vector "$set".

     If the set is empty (no set bits), plus infinity (represented by the
     constant "MAX_LONG" on your system) is returned.

     (This constant is usually 2 ^ (n-1) - 1, where "n" is the number of
     bits of an unsigned long on your machine.)

   * `$max = $set->Max();'

     Returns the maximum of the given set, i.e., the maximum of all
     indices of all set bits in the given bit vector "$set".

     If the set is empty (no set bits), minus infinity (represented by the
     constant "MIN_LONG" on your system) is returned.

     (This constant is usually -(2 ^ (n-1) - 1) or -(2 ^ (n-1)), where "n"
     is the number of bits of an unsigned long on your machine.)

   * `$m3->Multiplication($r3,$c3,$m1,$r1,$c1,$m2,$r2,$c2);'

     This method multiplies two boolean matrices (stored as bit vectors)
     "`$m1'" and "`$m2'" and stores the result in matrix "`$m3'".

     The method uses the binary "xor" operation ("^") as the boolean
     addition operator ("+").

     An exception is raised if the product of the number of rows and
     columns of any of the three matrices differs from the actual size of
     their underlying bit vector.

     An exception is also raised if the numbers of rows and columns of the
     three matrices do not harmonize in the required manner:

          rows3 == rows1
          cols3 == cols2
          cols1 == rows2

     This method is used by the module "Math::MatrixBool".

     See `Math::MatrixBool(3)' in this node for details.

   * `$m3->Product($r3,$c3,$m1,$r1,$c1,$m2,$r2,$c2);'

     This method multiplies two boolean matrices (stored as bit vectors)
     "`$m1'" and "`$m2'" and stores the result in matrix "`$m3'".

     This special method uses the binary "or" operation ("|") as the
     boolean addition operator ("+").

     An exception is raised if the product of the number of rows and
     columns of any of the three matrices differs from the actual size of
     their underlying bit vector.

     An exception is also raised if the numbers of rows and columns of the
     three matrices do not harmonize in the required manner:

          rows3 == rows1
          cols3 == cols2
          cols1 == rows2

     This method is used by the module "Math::MatrixBool".

     See `Math::MatrixBool(3)' in this node for details.

   * `$matrix->Closure($rows,$cols);'

     This method calculates the reflexive transitive closure of the given
     boolean matrix (stored as a bit vector) using Kleene's algoritm.

     (See `Math::Kleene(3)' in this node for a brief introduction into the
     theory behind Kleene's algorithm.)

     The reflexive transitive closure answers the question whether a path
     exists between any two vertices of a graph whose edges are given as a
     matrix:

     If a (directed) edge exists going from vertex "i" to vertex "j", then
     the element in the matrix with coordinates (i,j) is set to "1"
     (otherwise it remains set to "0").

     If the edges are undirected, the resulting matrix is symmetric, i.e.,
     elements (i,j) and (j,i) always contain the same value.

     The matrix representing the edges of the graph only answers the
     question whether an *EDGE* exists between any two vertices of the
     graph or not, whereas the reflexive transitive closure answers the
     question whether a PATH (a series of adjacent edges) exists between
     any two vertices of the graph!

     Note that the contents of the given matrix are modified by this
     method, so make a copy of the initial matrix in time if you are going
     to need it again later.

     An exception is raised if the given matrix is not quadratic, i.e., if
     the number of rows and columns of the given matrix is not identical.

     An exception is also raised if the product of the number of rows and
     columns of the given matrix differs from the actual size of its
     underlying bit vector.

     This method is used by the module "Math::MatrixBool".

     See `Math::MatrixBool(3)' in this node for details.

   * `$matrix2->Transpose($rows2,$cols2,$matrix1,$rows1,$cols1);'

     This method calculates the transpose of a boolean matrix "`$matrix1'"
     (stored as a bit vector) and stores the result in matrix "`$matrix2'".

     The transpose of a boolean matrix, representing the edges of a graph,
     can be used for finding the strongly connected components of that
     graph.

     An exception is raised if the product of the number of rows and
     columns of any of the two matrices differs from the actual size of
     its underlying bit vector.

     An exception is also raised if the following conditions are not met:

          rows2 == cols1
          cols2 == rows1

     Note that in-place processing ("`$matrix1'" and "`$matrix2'" are
     identical) is only possible if the matrix is quadratic. Otherwise, a
     fatal "matrix is not quadratic" error will occur.

     This method is used by the module "Math::MatrixBool".

     See `Math::MatrixBool(3)' in this node for details.

SEE ALSO
========

   Bit::Vector::Overload(3), Set::IntRange(3), Math::MatrixBool(3),
Math::MatrixReal(3), DFA::Kleene(3), Math::Kleene(3), Graph::Kruskal(3).

   perl(1), perlsub(1), perlmod(1), perlref(1), perlobj(1), perlbot(1),
perltoot(1), perlxs(1), perlxstut(1), perlguts(1), overload(3).

VERSION
=======

   This man page documents "Bit::Vector" version 6.0.

AUTHOR
======

     Steffen Beyer
     mailto:sb@engelschall.com
     http://www.engelschall.com/u/sb/download/

COPYRIGHT
=========

   Copyright (c) 1995 - 2000 by Steffen Beyer. All rights reserved.

LICENSE
=======

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself, i.e., under the terms of the
"Artistic License" or the "GNU General Public License".

   The C library at the core of this Perl module can additionally be
redistributed and/or modified under the terms of the "GNU Library General
Public License".

   Please refer to the files "Artistic.txt", "GNU_GPL.txt" and
"GNU_LGPL.txt" in this distribution for details!

DISCLAIMER
==========

   This package 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.

Overloaded operators add-on for Bit::Vector
*******************************************

NAME
====

   Bit::Vector::Overload - Overloaded operators add-on for Bit::Vector

USAGE
=====

   Note that you do not need to "`use Bit::Vector;'" in addition to this
module.

   Simply "`use Bit::Vector::Overload;'" *INSTEAD* of "`use
Bit::Vector;'". You can still use all the methods from the "Bit::Vector"
module in addition to the overloaded operators and methods provided here
after that.

SYNOPSIS
========

     Configuration
         $config = Bit::Vector->Configuration();
         Bit::Vector->Configuration($config);
         $oldconfig = Bit::Vector->Configuration($newconfig);

     String Conversion
         $string = "$vector";             #  depending on configuration
         print "\$vector = '$vector'\n";

     Emptyness
         if ($vector)  #  if not empty (non-zero)
         if (! $vector)  #  if empty (zero)
         unless ($vector)  #  if empty (zero)

     Complement (one's complement)
         $vector2 = ~$vector1;
         $vector = ~$vector;

     Negation (two's complement)
         $vector2 = -$vector1;
         $vector = -$vector;

     Norm
         $norm = abs($vector);  #  depending on configuration

     Absolute
         $vector2 = abs($vector1);  #  depending on configuration

     Concatenation
         $vector3 = $vector1 . $vector2;
         $vector1 .= $vector2;
         $vector1 = $vector2 . $vector1;
         $vector2 = $vector1 . $scalar;  #  depending on configuration
         $vector2 = $scalar . $vector1;
         $vector .= $scalar;

     Duplication
         $vector2 = $vector1 x $factor;
         $vector x= $factor;

     Shift Left
         $vector2 = $vector1 << $bits;
         $vector <<= $bits;

     Shift Right
         $vector2 = $vector1 >> $bits;
         $vector >>= $bits;

     Union
         $vector3 = $vector1 | $vector2;
         $vector1 |= $vector2;
         $vector2 = $vector1 | $scalar;
         $vector |= $scalar;

     $vector3 = $vector1 + $vector2;  #  depending on configuration
     $vector1 += $vector2;
     $vector2 = $vector1 + $scalar;
     $vector += $scalar;

     Intersection
         $vector3 = $vector1 & $vector2;
         $vector1 &= $vector2;
         $vector2 = $vector1 & $scalar;
         $vector &= $scalar;

     $vector3 = $vector1 * $vector2;  #  depending on configuration
     $vector1 *= $vector2;
     $vector2 = $vector1 * $scalar;
     $vector *= $scalar;

     ExclusiveOr
         $vector3 = $vector1 ^ $vector2;
         $vector1 ^= $vector2;
         $vector2 = $vector1 ^ $scalar;
         $vector ^= $scalar;

     Set Difference
         $vector3 = $vector1 - $vector2;  #  depending on configuration
         $vector1 -= $vector2;
         $vector1 = $vector2 - $vector1;
         $vector2 = $vector1 - $scalar;
         $vector2 = $scalar - $vector1;
         $vector -= $scalar;

     Addition
         $vector3 = $vector1 + $vector2;  #  depending on configuration
         $vector1 += $vector2;
         $vector2 = $vector1 + $scalar;
         $vector += $scalar;

     Subtraction
         $vector3 = $vector1 - $vector2;  #  depending on configuration
         $vector1 -= $vector2;
         $vector1 = $vector2 - $vector1;
         $vector2 = $vector1 - $scalar;
         $vector2 = $scalar - $vector1;
         $vector -= $scalar;

     Multiplication
         $vector3 = $vector1 * $vector2;  #  depending on configuration
         $vector1 *= $vector2;
         $vector2 = $vector1 * $scalar;
         $vector *= $scalar;

     Division
         $vector3 = $vector1 / $vector2;
         $vector1 /= $vector2;
         $vector1 = $vector2 / $vector1;
         $vector2 = $vector1 / $scalar;
         $vector2 = $scalar / $vector1;
         $vector /= $scalar;

     Modulo
         $vector3 = $vector1 % $vector2;
         $vector1 %= $vector2;
         $vector1 = $vector2 % $vector1;
         $vector2 = $vector1 % $scalar;
         $vector2 = $scalar % $vector1;
         $vector %= $scalar;

     Exponentiation
         $vector3 = $vector1 ** $vector2;
         $vector1 **= $vector2;
         $vector2 = $vector1 ** $scalar;
         $vector2 = $scalar ** $vector1;
         $vector **= $scalar;

     Increment
         ++$vector;
         $vector++;

     Decrement
         --$vector;
         $vector--;

     Lexical Comparison (unsigned)
         $cmp = $vector1 cmp $vector2;
         if ($vector1 lt $vector2)
         if ($vector1 le $vector2)
         if ($vector1 gt $vector2)
         if ($vector1 ge $vector2)

     $cmp = $vector cmp $scalar;
     if ($vector lt $scalar)
     if ($vector le $scalar)
     if ($vector gt $scalar)
     if ($vector ge $scalar)

     Comparison (signed)
         $cmp = $vector1 <=> $vector2;
         if ($vector1 < $vector2)  #  depending on configuration
         if ($vector1 <= $vector2)
         if ($vector1 > $vector2)
         if ($vector1 >= $vector2)

     $cmp = $vector <=> $scalar;
     if ($vector < $scalar)  #  depending on configuration
     if ($vector <= $scalar)
     if ($vector > $scalar)
     if ($vector >= $scalar)

     Equality
         if ($vector1 eq $vector2)
         if ($vector1 ne $vector2)
         if ($vector eq $scalar)
         if ($vector ne $scalar)

     if ($vector1 == $vector2)
     if ($vector1 != $vector2)
     if ($vector == $scalar)
     if ($vector != $scalar)

     Subset Relationship
         if ($vector1 <= $vector2)  #  depending on configuration

     True Subset Relationship
         if ($vector1 < $vector2)  #  depending on configuration

     Superset Relationship
         if ($vector1 >= $vector2)  #  depending on configuration

     True Superset Relationship
         if ($vector1 > $vector2)  #  depending on configuration

IMPORTANT NOTES
===============

   * Boolean values

     Boolean values in this module are always a numeric zero ("0") for
     "false" and a numeric one ("1") for "true".

   * Negative numbers

     Numeric factors (as needed for the "`<<'", "`>>'" and "x" operators)
     and bit numbers are always regarded as being UNSIGNED.

     As a consequence, whenever you pass a negative number for such a
     factor or bit number, it will be treated as a (usually very large)
     positive number due to its internal two's complement binary
     representation, usually resulting in malfunctions or an "index out of
     range" error message and program abortion.

     Note that this does not apply to "big integer" decimal numbers, which
     are (usually) passed as strings, and which may of course be negative
     (see also the section "Big integers" a little further below).

   * Overloaded operators configuration

     Note that the behaviour of certain overloaded operators can be changed
     in various ways by means of the "`Configuration()'" method (for more
     details, see the description of this method further below).

     For instance, scalars (i.e., numbers and strings) provided as operands
     to overloaded operators are automatically converted to bit vectors,
     internally.

     These scalars are thereby automatically assumed to be indices or to be
     in hexadecimal, binary, decimal or enumeration format, depending on
     the configuration.

     Similarly, when converting bit vectors to strings using double quotes
     (""), the output format will also depend on the previously chosen
     configuration.

     Finally, some overloaded operators may have different semantics
     depending on the proper configuration; for instance, the operator "+"
     can be the "union" operator from set theory or the arithmetic "add"
     operator.

     In all cases (input, output and operator semantics), the defaults have
     been chosen in such a way so that the behaviour of the module is
     backward compatible with previous versions.

   * "Big integers"

     As long as "big integers" (for "big integer" arithmetic) are small
     enough so that Perl doesn't need scientific notation (exponents) to
     be able to represent them internally, you can provide these "big
     integer" constants to the overloaded operators of this module (or to
     the method "`from_Dec()'") in numeric form (i.e., either as a numeric
     constant or expression or as a Perl variable containing a numeric
     value).

     Note that you will get an error message (resulting in program
     abortion) if your "big integer" numbers exceed that limit.

     Because this limit is machine-dependent and not obvious to find out,
     it is strongly recommended that you enclose ALL your "big integer"
     constants in your programs in (double or single) quotes.

     Examples:

          $vector /= 10;  #  ok because number is small

          $vector /= -10;  #  ok for same reason

          $vector /= "10";  #  always correct

          $vector += "1152921504606846976";  #  quotes probably required here

     All examples assume

          Bit::Vector->Configuration("input=decimal");

     having been set beforehand.

     Note also that this module does not support scientific notation
     (exponents) for "big integer" decimal numbers because you can always
     make the bit vector large enough for the whole number to fit without
     loss of precision (as it would occur if scientific notation were
     used).

     Finally, note that the only characters allowed in "big integer"
     constant strings are the digits `0..9' and an optional leading sign
     ("+" or "-").

     All other characters produce a syntax error.

   * Valid operands for overloaded operators

     All overloaded operators expect at least one bit vector operand, in
     order for the operator to "know" that not the usual operation is to
     be carried out, but rather the overloaded variant.

     This is especially true for all unary operators:

          "$vector"
          if ($vector)
          if (!$vector)
          ~$vector
          -$vector
          abs($vector)
          ++$vector
          $vector++
          --$vector
          $vector--

     For obvious reasons the left operand (the "lvalue") of all assignment
     operators is also required to be a bit vector:

          .=
          x=
          <<=
          >>=
          |=
          &=
          ^=
          +=
          -=
          *=
          /=
          %=
                                 **=

     In the case of three special operators, namely "`<<'", "`>>'" and
     "x", as well as their related assignment variants, "`<<='", "`>>='"
     and "`x='", the left operand is *ALWAYS* a bit vector and the right
     operand is *ALWAYS* a number (which is the factor indicating how many
     times the operator is to be applied).

     In all truly binary operators, i.e.,

          .
          |
          &
          ^
          +
          -
          *
          /
          %
                                 **
                              <=>   cmp
                               ==    eq
                               !=    ne
                               <     lt
                               <=    le
                               >     gt
                               >=    ge

     one of either operands may be replaced by a Perl scalar, i.e., a
     number or a string, either as a Perl constant, a Perl expression or a
     Perl variable yielding a number or a string.

     The same applies to the right side operand (the "rvalue") of the
     remaining assignment operators, i.e.,

          .=
          |=
          &=
          ^=
          +=
          -=
          *=
          /=
          %=
                                 **=

     Note that this Perl scalar should be of the correct type, i.e.,
     numeric or string, for the chosen configuration, because otherwise a
     warning message will occur if your program runs under the "-w" switch
     of Perl.

     The acceptable scalar types for each possible configuration are the
     following:

          input = bit indices    (default)  :    numeric
          input = hexadecimal               :    string
          input = binary                    :    string
          input = decimal                   :    string     (in general)
          input = decimal                   :    numeric    (if small enough)
          input = enumeration               :    string

     NOTE ALSO THAT THESE SCALAR OPERANDS ARE CONVERTED TO BIT VECTORS OF
     THE SAME SIZE AS THE BIT VECTOR WHICH IS THE OTHER OPERAND.

     The only exception from this rule is the concatenation operator (".")
     and its assignment variant ("`.='"):

     If one of the two operands of the concatenation operator (".") is not
     a bit vector object but a Perl scalar, the contents of the remaining
     bit vector operand are converted into a string (the format of which
     depends on the configuration set with the "`Configuration()'" method),
     which is then concatenated in the proper order (i.e., as indicated by
     the order of the two operands) with the Perl scalar (in other words,
     a string is returned in such a case instead of a bit vector object!).

     If the right side operand (the "rvalue") of the assignment variant
     ("`.='") of the concatenation operator is a Perl scalar, it is
     converted internally to a bit vector of the same size as the left
     side operand provided that the configuration states that scalars are
     to be regarded as indices, decimal strings or enumerations.

     If the configuration states that scalars are to be regarded as
     hexadecimal or boolean strings, however, these strings are converted
     to bit vectors of a size matching the length of the input string,
     i.e., four times the length for hexadecimal strings (because each
     hexadecimal digit is worth 4 bits) and once the length for binary
     strings.

     If a decimal number ("big integer") is too large to be stored in a
     bit vector of the given size, a "numeric overflow error" occurs.

     If a bit index is out of range for the given bit vector, an "index
     out of range" error occurs.

     If a scalar operand cannot be converted successfully due to invalid
     syntax, a fatal "input string syntax error" is issued.

     If the two operands of the operator "`<<'", "`>>'" or "x" are
     reversed, a fatal "reversed operands error" occurs.

     If an operand is neither a bit vector nor a scalar, then a fatal
     "illegal operand type error" occurs.

   * Bit order

     Note that bit vectors are stored least order bit and least order word
     first internally.

     I.e., bit #0 of any given bit vector corresponds to bit #0 of word #0
     in the array of machine words representing the bit vector.

     (Where word #0 comes first in memory, i.e., it is stored at the least
     memory address in the allocated block of memory holding the given bit
     vector.)

     Note however that machine words can be stored least order byte first
     or last, depending on your system's implementation.

     Note further that whenever bit vectors are converted to and from
     (binary or hexadecimal) strings, the *RIGHTMOST* bit is always the
     *LEAST SIGNIFICANT* one, and the *LEFTMOST* bit is always the *MOST
     SIGNIFICANT* bit.

     This is because in our western culture, numbers are always
     represented in this way (least significant to most significant digits
     go from right to left).

     Of course this requires an internal reversion of order, which the
     corresponding conversion methods perform automatically (without any
     additional overhead, it's just a matter of starting the internal loop
     at the bottom or the top end).

   * Matching sizes

     In general, for methods involving several bit vectors at the same
     time, all bit vector arguments must have identical sizes (number of
     bits), or a fatal "size mismatch" error will occur.

     Exceptions from this rule are the methods "`Concat()'",
     "`Concat_List()'", "`Copy()'", "`Interval_Copy()'" and
     "`Interval_Substitute()'", where no conditions at all are imposed on
     the size of their bit vector arguments.

     In method "`Multiply()'", all three bit vector arguments must in
     principle obey the rule of matching sizes, but the bit vector in
     which the result of the multiplication is to be stored may be larger
     than the two bit vector arguments containing the factors for the
     multiplication.

     In method "`Power()'", the bit vector for the result must be the same
     size or greater than the base of the exponentiation term. The exponent
     can be any size.

     The same applies to the corresponding overloaded operators.

   * Index ranges

     All indices for any given bits must lie between "0" and
     "`$vector->Size()-1'", or a fatal "index out of range" error will
     occur.

DESCRIPTION
===========

   * `$config = Bit::Vector->Configuration();'

   * `Bit::Vector->Configuration($config);'

   * `$oldconfig = Bit::Vector->Configuration($newconfig);'

     This method serves to alter the semantics (i.e., behaviour) of certain
     overloaded operators (which are all implemented in Perl, by the way).

     It does not have any effect whatsoever on anything else. In
     particular, it does not affect the methods implemented in C.

     The method accepts an (optional) string as input in which certain
     keywords are expected, which influence some or almost all of the
     overloaded operators in several possible ways.

     The method always returns a string (which you do not need to take
     care of, i.e., to store, in case you aren't interested in keeping it)
     which is a complete representation of the current configuration
     (i.e., *BEFORE* any modifications are applied) and which can be fed
     back to this method later in order to restore the previous
     configuration.

     There are three aspects of the way certain overloaded operators
     behave which can be controlled with this method:

          +  the way scalar operands (replacing one of the two
             bit vector object operands) are automatically
             converted internally into a bit vector object of
             their own,

          +  the operation certain overloaded operators perform,
             i.e., an operation with sets or an arithmetic
             operation,

          +  the format to which bit vectors are converted
             automatically when they are enclosed in double
             quotes.

     The input string may contain any number of assignments, each of which
     controls one of these three aspects.

     Each assignment has the form "`<which>=<value>'".

     "`<which>'" and "`<value>'" thereby consist of letters (`[a-zA-Z]')
     and white space.

     Multiple assignments have to be separated by one or more comma (","),
     semi-colon (";"), colon (":"), vertical bar ("|"), slash ("/"),
     newline ("\n"), ampersand ("&"), plus ("+") or dash ("-").

     Empty lines or statements (only white space) are allowed but will be
     ignored.

     "`<which>'" has to contain one or more keywords from one of three
     groups, each group representing one of the three aspects that the
     "`Configuration()'" method controls:

          +  "^scalar", "^input", "^in$"

          +  "^operator", "^semantic", "^ops$"

          +  "^string", "^output", "^out$"

     The character "^" thereby denotes the beginning of a word, and "$"
     denotes the end. Case is ignored (!).

     Using these keywords, you can build any phrase you like to select one
     of the three aspects (see also examples given below).

     The only condition is that no other keyword from any of the other two
     groups may match - otherwise a syntax error will occur (i.e.,
     ambiguities are forbidden). A syntax error also occurs if none of the
     keywords matches.

     This same principle applies to "`<value>'":

     Depending on which aspect you specified for "`<which>'", there are
     different groups of keywords that determine the value the selected
     aspect will be set to:

          +  "<which>" = "^scalar", "^input", "^in$":

          "<value>" =

          *  "^bit$", "^index", "^indice"
          *  "^hex"
          *  "^bin"
          *  "^dec"
          *  "^enum"

          +  "<which>" = "^operator", "^semantic", "^ops$":

          "<value>" =

          *  "^set$"
          *  "^arithmetic"

          +  "<which>" = "^string", "^output", "^out$":

          "<value>" =

          *  "^hex"
          *  "^bin"
          *  "^dec"
          *  "^enum"

     Examples:

          "Any scalar input I provide should be considered to be = a bit index"

          "I want to have operator semantics suitable for = arithmetics"

          "Any bit vector in double quotes is to be output as = an enumeration"

     *SCALAR INPUT:*

     In the case of scalar input, "`^bit$'", "`^index'", or "`^indice'"
     all cause scalar input to be considered to represent a bit index,
     i.e., "`$vector ^= 5;'" will flip bit #5 in the given bit vector
     (this is essentially the same as "`$vector->bit_flip(5);'").

     Note that "bit indices" is the default setting for "scalar input".

     The keyword "`^hex'" will cause scalar input to be considered as
     being in hexadecimal, i.e., "`$vector ^= 5;'" will flip bit #0 and
     bit #2 (because hexadecimal "5" is binary "`0101'").

     (Note though that hexadecimal input should always be enclosed in
     quotes, otherwise it will be interpreted as a decimal number by Perl!
     The example relies on the fact that hexadecimal `0-9' and decimal
     `0-9' are the same.)

     The keyword "`^bin'" will cause scalar input to be considered as
     being in binary format. All characters except "0" and "1" are
     forbidden in this case (i.e., produce a syntax error).

     "`$vector ^= '0101';'", for instance, will flip bit #0 and bit #2.

     The keyword "`^dec'" causes scalar input to be considered as integers
     in decimal format, i.e., "`$vector ^= 5;'" will flip bit #0 and bit #2
     (because decimal "5" is binary "`0101'").

     (Note though that all decimal input should be enclosed in quotes,
     because for large numbers, Perl will use scientific notation
     internally for representing them, which produces a syntax error
     because scientific notation is neither supported by this module nor
     needed.)

     Finally, the keyword "`^enum'" causes scalar input to be considered
     as being a list ("enumeration") of indices and ranges of (contiguous)
     indices, i.e., "`$vector |= '2,3,5,7-13,17-23';'" will cause bits #2,
     #3, #5, #7 through #13 and #17 through #23 to be set.

     *OPERATOR SEMANTICS:*

     Several overloaded operators can have two distinct functions depending
     on this setting.

     The affected operators are: "+", "-", "*", "`<'", "`<='", "`>'" and
     "`>='".

     With the default setting, "set operations", these operators perform:

          +       set union                           ( set1  u   set2 )
          -       set difference                      ( set1  \   set2 )
          *       set intersection                    ( set1  n   set2 )
          <       true subset relationship            ( set1  <   set2 )
          <=      subset relationship                 ( set1  <=  set2 )
          >       true superset relationship          ( set1  >   set2 )
          >=      superset relationship               ( set1  >=  set2 )

     With the alternative setting, "arithmetic operations", these operators
     perform:

          +       addition                            ( num1  +   num2 )
          -       subtraction                         ( num1  -   num2 )
          *       multiplication                      ( num1  *   num2 )
          <       "less than" comparison              ( num1  <   num2 )
          <=      "less than or equal" comparison     ( num1  <=  num2 )
          >       "greater than" comparison           ( num1  >   num2 )
          >=      "greater than or equal" comparison  ( num1  >=  num2 )

     Note that these latter comparison operators ("`<'", "`<='", "`>'" and
     "`>='") regard their operands as being *SIGNED*.

     To perform comparisons with UNSIGNED operands, use the operators
     "lt", "le", "gt" and "ge" instead (in contrast to the operators
     above, these operators are *NOT* affected by the "operator semantics"
     setting).

     *STRING OUTPUT:*

     There are four methods which convert the contents of a given bit
     vector into a string: "`to_Hex()'", "`to_Bin()'", "`to_Dec()'" and
     "`to_Enum()'" (not counting "`Block_Read()'", since this method does
     not return a human-readable string).

     (For conversion to octal, see the description of the method
     "`Chunk_List_Read()'".)

     Therefore, there are four possible formats into which a bit vector can
     be converted when it is enclosed in double quotes, for example:

          print "\$vector = '$vector'\n";
          $string = "$vector";

     Hence you can set "string output" to four different values: To "hex"
     for hexadecimal format (which is the default), to "bin" for binary
     format, to "dec" for conversion to decimal numbers and to "enum" for
     conversion to enumerations (".newsrc" style sets).

     *BEWARE* that the conversion to decimal numbers is inherently slow;
     it can easily take up several seconds for a single large bit vector!

     Therefore you should store the decimal strings returned to you rather
     than converting a given bit vector again.

     *EXAMPLES:*

     The default setting as returned by the method "`Configuration()'" is:

          Scalar Input       = Bit Index
          Operator Semantics = Set Operators
          String Output      = Hexadecimal

     Performing a statement such as:

          Bit::Vector->Configuration("in=bin,ops=arithmetic,out=bin");
          print Bit::Vector->Configuration(), "\n";

     yields the following output:

          Scalar Input       = Binary
          Operator Semantics = Arithmetic Operators
          String Output      = Binary

     Note that you can always feed this output back into the
     "`Configuration()'" method to restore that setting later.

     This also means that you can enter the same given setting with almost
     any degree of verbosity you like (as long as the required keywords
     appear and no ambiguities arise).

     Note further that any aspect you do not specify is not changed, i.e.,
     the statement

          Bit::Vector->Configuration("operators = arithmetic");

     leaves all other aspects unchanged.

   * `"$vector"'

     Remember that variables enclosed in double quotes are always
     interpolated in Perl.

     Whenever a Perl variable containing the reference of a "Bit::Vector"
     object is enclosed in double quotes (either alone or together with
     other text and/or variables), the contents of the corresponding bit
     vector are converted into a printable string.

     Since there are several conversion methods available in this module
     (see the description of the methods "`to_Hex()'", "`to_Bin()'",
     "`to_Dec()'" and "`to_Enum()'"), it is of course desirable to be able
     to choose which of these methods should be applied in this case.

     This can actually be done by changing the configuration of this
     module using the method "`Configure()'" (see the previous chapter,
     immediately above).

     The default is conversion to hexadecimal.

   * `if ($vector)'

     It is possible to use a Perl variable containing the reference of a
     "Bit::Vector" object as a boolean expression.

     The condition above is true if the corresponding bit vector contains
     at least one set bit, and it is false if ALL bits of the corresponding
     bit vector are cleared.

   * `if (!$vector)'

     Since it is possible to use a Perl variable containing the reference
     of a "Bit::Vector" object as a boolean expression, you can of course
     also negate this boolean expression.

     The condition above is true if ALL bits of the corresponding bit
     vector are cleared, and it is false if the corresponding bit vector
     contains at least one set bit.

     Note that this is *NOT* the same as using the method "`is_full()'",
     which returns true if ALL bits of the corresponding bit vector are
     SET.

   * `~$vector'

     This term returns a new bit vector object which is the one's
     complement of the given bit vector.

     This is equivalent to inverting all bits.

   * `-$vector' (unary minus)

     This term returns a new bit vector object which is the two's
     complement of the given bit vector.

     This is equivalent to inverting all bits and incrementing the result
     by one.

     (This is the same as changing the sign of a number in two's complement
     binary representation.)

   * `abs($vector)'

     Depending on the configuration (see the description of the method
     "`Configuration()'" for more details), this term either returns the
     number of set bits in the given bit vector (this is the same as
     calculating the number of elements which are contained in the given
     set) - which is the default behaviour, or it returns a new bit vector
     object which contains the absolute value of the number stored in the
     given bit vector.

   * `$vector1 . $vector2'

     This term usually returns a new bit vector object which is the result
     of the concatenation of the two bit vector operands.

     The left operand becomes the most significant, and the right operand
     becomes the least significant part of the new bit vector object.

     If one of the two operands is not a bit vector object but a Perl
     scalar, however, the contents of the remaining bit vector operand are
     converted into a string (the format of which depends on the
     configuration set with the "`Configuration()'" method), which is then
     concatenated in the proper order (i.e., as indicated by the order of
     the two operands) with the Perl scalar.

     In other words, a string is returned in such a case instead of a bit
     vector object!

   * `$vector x $factor'

     This term returns a new bit vector object which is the concatenation
     of as many copies of the given bit vector operand (the left operand)
     as the factor (the right operand) specifies.

     If the factor is zero, a bit vector object with a length of zero bits
     is returned.

     If the factor is one, just a new copy of the given bit vector is
     returned.

     Note that a fatal "reversed operands error" occurs if the two operands
     are swapped.

   * `$vector << $bits'

     This term returns a new bit vector object which is a copy of the given
     bit vector (the left operand), which is then shifted left (towards the
     most significant bit) by as many places as the right operand,
     "`$bits'", specifies.

     This means that the "`$bits'" most significant bits are lost, all
     other bits move up by "`$bits'" positions, and the "`$bits'" least
     significant bits that have been left unoccupied by this shift are all
     set to zero.

     If "`$bits'" is greater than the number of bits of the given bit
     vector, this term returns an empty bit vector (i.e., with all bits
     cleared) of the same size as the given bit vector.

     Note that a fatal "reversed operands error" occurs if the two operands
     are swapped.

   * `$vector >> $bits'

     This term returns a new bit vector object which is a copy of the given
     bit vector (the left operand), which is then shifted right (towards
     the least significant bit) by as many places as the right operand,
     "`$bits'", specifies.

     This means that the "`$bits'" least significant bits are lost, all
     other bits move down by "`$bits'" positions, and the "`$bits'" most
     significant bits that have been left unoccupied by this shift are all
     set to zero.

     If "`$bits'" is greater than the number of bits of the given bit
     vector, this term returns an empty bit vector (i.e., with all bits
     cleared) of the same size as the given bit vector.

     Note that a fatal "reversed operands error" occurs if the two operands
     are swapped.

   * `$vector1 | $vector2'

     This term returns a new bit vector object which is the result of a
     bitwise OR operation between the two bit vector operands.

     This is the same as calculating the union of two sets.

   * `$vector1 & $vector2'

     This term returns a new bit vector object which is the result of a
     bitwise AND operation between the two bit vector operands.

     This is the same as calculating the intersection of two sets.

   * `$vector1 ^ $vector2'

     This term returns a new bit vector object which is the result of a
     bitwise XOR (exclusive-or) operation between the two bit vector
     operands.

     This is the same as calculating the symmetric difference of two sets.

   * `$vector1 + $vector2'

     Depending on the configuration (see the description of the method
     "`Configuration()'" for more details), this term either returns a new
     bit vector object which is the result of a bitwise OR operation
     between the two bit vector operands (this is the same as calculating
     the union of two sets) - which is the default behaviour, or it returns
     a new bit vector object which contains the sum of the two numbers
     stored in the two bit vector operands.

   * `$vector1 - $vector2'

     Depending on the configuration (see the description of the method
     "`Configuration()'" for more details), this term either returns a new
     bit vector object which is the set difference of the two sets
     represented in the two bit vector operands - which is the default
     behaviour, or it returns a new bit vector object which contains the
     difference of the two numbers stored in the two bit vector operands.

   * `$vector1 * $vector2'

     Depending on the configuration (see the description of the method
     "`Configuration()'" for more details), this term either returns a new
     bit vector object which is the result of a bitwise AND operation
     between the two bit vector operands (this is the same as calculating
     the intersection of two sets) - which is the default behaviour, or it
     returns a new bit vector object which contains the product of the two
     numbers stored in the two bit vector operands.

   * `$vector1 / $vector2'

     This term returns a new bit vector object containing the result of the
     division of the two numbers stored in the two bit vector operands.

   * `$vector1 % $vector2'

     This term returns a new bit vector object containing the remainder of
     the division of the two numbers stored in the two bit vector operands.

   * `$vector1 ** $vector2'

     This term returns a new bit vector object containing the result of the
     exponentiation of the left bit vector elevated to the right bit
     vector's power.

   * `$vector1 .= $vector2;'

     This statement "appends" the right bit vector operand (the "rvalue")
     to the left one (the "lvalue").

     The former contents of the left operand become the most significant
     part of the resulting bit vector, and the right operand becomes the
     least significant part.

     Since bit vectors are stored in "least order bit first" order, this
     actually requires the left operand to be shifted "up" by the length
     of the right operand, which is then copied to the now freed least
     significant part of the left operand.

     If the right operand is a Perl scalar, it is first converted to a bit
     vector of the same size as the left operand, provided that the
     configuration states that scalars are to be regarded as indices,
     decimal strings or enumerations.

     If the configuration states that scalars are to be regarded as
     hexadecimal or boolean strings, however, these strings are converted
     to bit vectors of a size matching the length of the input string,
     i.e., four times the length for hexadecimal strings (because each
     hexadecimal digit is worth 4 bits) and once the length for binary
     strings.

   * `$vector x= $factor;'

     This statement replaces the given bit vector by a concatenation of as
     many copies of the original contents of the given bit vector as the
     factor (the right operand) specifies.

     If the factor is zero, the given bit vector is resized to a length of
     zero bits.

     If the factor is one, the given bit vector is not changed at all.

   * `$vector <<= $bits;'

     This statement moves the contents of the given bit vector left by
     "`$bits'" positions (towards the most significant bit).

     This means that the "`$bits'" most significant bits are lost, all
     other bits move up by "`$bits'" positions, and the "`$bits'" least
     significant bits that have been left unoccupied by this shift are all
     set to zero.

     If "`$bits'" is greater than the number of bits of the given bit
     vector, the given bit vector is erased completely (i.e., all bits are
     cleared).

   * `$vector >>= $bits;'

     This statement moves the contents of the given bit vector right by
     "`$bits'" positions (towards the least significant bit).

     This means that the "`$bits'" least significant bits are lost, all
     other bits move down by "`$bits'" positions, and the "`$bits'" most
     significant bits that have been left unoccupied by this shift are all
     set to zero.

     If "`$bits'" is greater than the number of bits of the given bit
     vector, the given bit vector is erased completely (i.e., all bits are
     cleared).

   * `$vector1 |= $vector2;'

     This statement performs a bitwise OR operation between the two bit
     vector operands and stores the result in the left operand.

     This is the same as calculating the union of two sets.

   * `$vector1 &= $vector2;'

     This statement performs a bitwise AND operation between the two bit
     vector operands and stores the result in the left operand.

     This is the same as calculating the intersection of two sets.

   * `$vector1 ^= $vector2;'

     This statement performs a bitwise XOR (exclusive-or) operation
     between the two bit vector operands and stores the result in the left
     operand.

     This is the same as calculating the symmetric difference of two sets.

   * `$vector1 += $vector2;'

     Depending on the configuration (see the description of the method
     "`Configuration()'" for more details), this statement either performs
     a bitwise OR operation between the two bit vector operands (this is
     the same as calculating the union of two sets) - which is the default
     behaviour, or it calculates the sum of the two numbers stored in the
     two bit vector operands.

     The result of this operation is stored in the left operand.

   * `$vector1 -= $vector2;'

     Depending on the configuration (see the description of the method
     "`Configuration()'" for more details), this statement either
     calculates the set difference of the two sets represented in the two
     bit vector operands - which is the default behaviour, or it
     calculates the difference of the two numbers stored in the two bit
     vector operands.

     The result of this operation is stored in the left operand.

   * `$vector1 *= $vector2;'

     Depending on the configuration (see the description of the method
     "`Configuration()'" for more details), this statement either performs
     a bitwise AND operation between the two bit vector operands (this is
     the same as calculating the intersection of two sets) - which is the
     default behaviour, or it calculates the product of the two numbers
     stored in the two bit vector operands.

     The result of this operation is stored in the left operand.

   * `$vector1 /= $vector2;'

     This statement puts the result of the division of the two numbers
     stored in the two bit vector operands into the left operand.

   * `$vector1 %= $vector2;'

     This statement puts the remainder of the division of the two numbers
     stored in the two bit vector operands into the left operand.

   * `$vector1 **= $vector2;'

     This statement puts the result of the exponentiation of the left
     operand elevated to the right operand's power into the left operand.

   * `++$vector', `$vector++'

     This operator performs pre- and post-incrementation of the given bit
     vector.

     The value returned by this term is a reference of the given bit
     vector object (after or before the incrementation, respectively).

   * `--$vector', `$vector--'

     This operator performs pre- and post-decrementation of the given bit
     vector.

     The value returned by this term is a reference of the given bit
     vector object (after or before the decrementation, respectively).

   * `($vector1 cmp $vector2)'

     This term returns "`-1'" if "`$vector1'" is less than "`$vector2'",
     "0" if "`$vector1'" and "`$vector2'" are the same, and "1" if
     "`$vector1'" is greater than "`$vector2'".

     This comparison assumes UNSIGNED bit vectors.

   * `($vector1 eq $vector2)'

     This term returns true ("1") if the contents of the two bit vector
     operands are the same and false ("0") otherwise.

   * `($vector1 ne $vector2)'

     This term returns true ("1") if the two bit vector operands differ
     and false ("0") otherwise.

   * `($vector1 lt $vector2)'

     This term returns true ("1") if "`$vector1'" is less than
     "`$vector2'", and false ("0") otherwise.

     This comparison assumes UNSIGNED bit vectors.

   * `($vector1 le $vector2)'

     This term returns true ("1") if "`$vector1'" is less than or equal to
     "`$vector2'", and false ("0") otherwise.

     This comparison assumes UNSIGNED bit vectors.

   * `($vector1 gt $vector2)'

     This term returns true ("1") if "`$vector1'" is greater than
     "`$vector2'", and false ("0") otherwise.

     This comparison assumes UNSIGNED bit vectors.

   * `($vector1 ge $vector2)'

     This term returns true ("1") if "`$vector1'" is greater than or equal
     to "`$vector2'", and false ("0") otherwise.

     This comparison assumes UNSIGNED bit vectors.

   * `($vector1 <=> $vector2)'

     This term returns "`-1'" if "`$vector1'" is less than "`$vector2'",
     "0" if "`$vector1'" and "`$vector2'" are the same, and "1" if
     "`$vector1'" is greater than "`$vector2'".

     This comparison assumes *SIGNED* bit vectors.

   * `($vector1 == $vector2)'

     This term returns true ("1") if the contents of the two bit vector
     operands are the same and false ("0") otherwise.

   * `($vector1 != $vector2)'

     This term returns true ("1") if the two bit vector operands differ
     and false ("0") otherwise.

   * `($vector1 < $vector2)'

     Depending on the configuration (see the description of the method
     "`Configuration()'" for more details), this term either returns true
     ("1") if "`$vector1'" is a true subset of "`$vector2'" (and false
     ("0") otherwise) - which is the default behaviour, or it returns true
     ("1") if "`$vector1'" is less than "`$vector2'" (and false ("0")
     otherwise).

     The latter comparison assumes *SIGNED* bit vectors.

   * `($vector1 <= $vector2)'

     Depending on the configuration (see the description of the method
     "`Configuration()'" for more details), this term either returns true
     ("1") if "`$vector1'" is a subset of "`$vector2'" (and false ("0")
     otherwise) - which is the default behaviour, or it returns true ("1")
     if "`$vector1'" is less than or equal to "`$vector2'" (and false
     ("0") otherwise).

     The latter comparison assumes *SIGNED* bit vectors.

   * `($vector1 > $vector2)'

     Depending on the configuration (see the description of the method
     "`Configuration()'" for more details), this term either returns true
     ("1") if "`$vector1'" is a true superset of "`$vector2'" (and false
     ("0") otherwise) - which is the default behaviour, or it returns true
     ("1") if "`$vector1'" is greater than "`$vector2'" (and false ("0")
     otherwise).

     The latter comparison assumes *SIGNED* bit vectors.

   * `($vector1 >= $vector2)'

     Depending on the configuration (see the description of the method
     "`Configuration()'" for more details), this term either returns true
     ("1") if "`$vector1'" is a superset of "`$vector2'" (and false ("0")
     otherwise) - which is the default behaviour, or it returns true ("1")
     if "`$vector1'" is greater than or equal to "`$vector2'" (and false
     ("0") otherwise).

     The latter comparison assumes *SIGNED* bit vectors.

SEE ALSO
========

   Bit::Vector(3), Set::IntRange(3), Math::MatrixBool(3),
Math::MatrixReal(3), DFA::Kleene(3), Math::Kleene(3), Graph::Kruskal(3).

   perl(1), perlsub(1), perlmod(1), perlref(1), perlobj(1), perlbot(1),
perltoot(1), perlxs(1), perlxstut(1), perlguts(1), overload(3).

VERSION
=======

   This man page documents "Bit::Vector::Overload" version 6.0.

AUTHOR
======

     Steffen Beyer
     mailto:sb@engelschall.com
     http://www.engelschall.com/u/sb/download/

COPYRIGHT
=========

   Copyright (c) 1995 - 2000 by Steffen Beyer. All rights reserved.

LICENSE
=======

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself, i.e., under the terms of the
"Artistic License" or the "GNU General Public License".

   The C library at the core of this Perl module can additionally be
redistributed and/or modified under the terms of the "GNU Library General
Public License".

   Please refer to the files "Artistic.txt", "GNU_GPL.txt" and
"GNU_LGPL.txt" in this distribution for details!

DISCLAIMER
==========

   This package 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.

For *really* clean programs
***************************

NAME
====

   Bleach - For *really* clean programs

SYNOPSIS
========

     use Bleach;

     print "Hello world";

DESCRIPTION
===========

   The first time you run a program under `use Bleach', the module removes
all the unsightly printable characters from your source file.  The code
continues to work exactly as it did before, but now it looks like this:

     use Bleach;

DIAGNOSTICS
===========

`Can't bleach '%s''
     Bleach could not access the source file to modify it.

`Can't rebleach '%s''
     Bleach could not access the source file to execute it.

AUTHOR
======

   Damian Conway (as if you couldn't guess)

COPYRIGHT
=========

     Copyright (c) 2001, Damian Conway. All Rights Reserved.
      This module is free software. It may be used, redistributed
     and/or modified under the terms of the Perl Artistic License
       (see http://www.perl.com/perl/misc/Artistic.html)

implements the automatic recovery mechanism of "Build'n'Play"
*************************************************************

NAME
====

   BnP - implements the automatic recovery mechanism of "Build'n'Play"

PREFACE
=======

   This module provides an automatic recovery mechanism for installation
scripts (for installing any kind of Unix software package) written in Perl.

   A special log file (called the "automatic recovery file") is used by
this module in which all the commands (i.e., method calls of command
methods provided by this module) are recorded which have been executed
successfully.

   When you restart your installation script later, the commands found in
this automatic recovery file will not be executed again.

   The module provides a comprehensive set of command methods for fetching
source distribution files automatically, for manipulating (e.g., unpacking
and building) them in every possible way (using "`system()'" calls), for
making and changing directories, for patching files (in a manner resembling
the Unix tool "`sed'"), for defining subsections in your installation
scripts and for commenting out certain parts, plus some functions of
general utility.

SYNOPSIS
========

     use BnP;

Functions:
----------

     info
         info "MESSAGE", ...;  #  print

     alert
         alert "MESSAGE", ...;  #  warn

     fatal
         fatal "MESSAGE", ...;  #  die

     find
         $path = find("FILENAME", "SEARCHPATH");

     indispensable
         indispensable("FILENAME", ...);

     normalize
         $file = normalize("FILENAME");

     follow
         $file = follow("FILENAME");

     absolute
         $file = absolute("FILENAME");

     expand
         $file = expand("FILENAME");

Methods:
--------

     new
         $BnP = BnP->new($target,$subset,$prefix,$homedir,$workspace);

     target
         $target = $BnP->target();

     subset
         $subset = $BnP->subset();

     prefix
         $prefix = $BnP->prefix();

     homedir
         $homedir = $BnP->homedir();

     workspace
         $workspace = $BnP->workspace();

     path
         [ @path = ] $BnP->path( @path );
         @path = $BnP->path();

     stub
         [ @stub = ] $BnP->stub( @stub );
         @stub = $BnP->stub();

     url
         [ @url = ] $BnP->url( @url );
         @url = $BnP->url();

     begin
         $BnP->begin();

     end
         $BnP->end();

     begin_section
         $BnP->begin_section("NAME", ...);

     end_section
         $BnP->end_section("NAME", ...);

     begin_must_section
         $BnP->begin_must_section();

     end_must_section
         $BnP->end_must_section();

     begin_lazy_section
         $BnP->begin_lazy_section("NAME", ...);

     end_lazy_section
         $BnP->end_lazy_section("NAME", ...);

     ignore
         $BnP->ignore();

     resume
         $BnP->resume();

     active
         $flag = $BnP->active();

     reset
         $BnP->reset();

     back
         $BnP->back();
         $BnP->back(COUNT);

     chdir
         $BnP->chdir("DIR");

     mkdir
         $BnP->mkdir("DIR");

     fetch
         $BnP->fetch("FILENAME", "RELPATH", "SOURCEDIR");

     system
         $BnP->system("COMMAND", ...);

     patch
         $BnP->patch("FILENAME", "PERLEXPR", ...);

DESCRIPTION
===========

Functions:
----------

   * `info "MESSAGE", ...;'  #  print

     This function can be used to print informational messages to STDOUT
     (or to whatever file handle your program has currently "select"ed).

     All parameters of this function are concatenated without any
     intervening characters (i.e., without adding any spaces).

     A prefix of "BnP:   " and a trailing "\n" is added automatically.

     Moreover, the output is written unbuffered, i.e., even if it is not
     sent to a terminal, the output should appear immediately in the
     corresponding file or pipe.

   * `alert "MESSAGE", ...;'  #  warn

     This function can be used to print warning messages to STDERR (using
     "warn", internally).

     All parameters of this function are concatenated without any
     intervening characters (i.e., without adding any spaces).

     A prefix of "BnP: ! " and a trailing "\n" is added automatically.

   * `fatal "MESSAGE", ...;'  #  die

     This function can be used to print an error message to STDERR, with
     immediately ensuing program abortion (using "die", internally).

     All parameters of this function are concatenated without any
     intervening characters (i.e., without adding any spaces).

     A prefix of "BnP: ! " and a trailing "\n" is added automatically.

   * `$path = find("FILENAME", "SEARCHPATH");'

     This function can be used to find any readable (operator "-r") and
     non-empty (operator "-s") file in a given searchpath (i.e., a list of
     directories concatenated with ":") whose filename is given.

     The function returns the absolute path of the requested file if the
     file was found in the given searchpath, or an empty string otherwise.

     For example:

          $shell = find('sh', $ENV{'PATH'});

     This should return "/bin/sh".

   * `indispensable("FILENAME", ...);'

     This function checks wether all the files whose filenames are given
     can be found in the current "`$PATH'" environment variable
     ("`$ENV{'PATH'}'") using the function "`find()'" (see above)
     internally.

     An error message is printed and program execution is aborted if any of
     the files in the list cannot be found.

     The function returns silently if all the files have been found.

   * `$file = normalize("FILENAME");'

     This function "normalizes" a given filename, i.e., it reduces
     consecutive slashes ("/") and consecutive terms of the form "`/./'"
     to a single slash, and removes a dot-slash ("`./'") at the beginning
     and a slash-dot ("`/.'")  or slash ("/") at the end.

     Moreover, terms of the form "`/dir/../'" (where "dir" is not an empty
     string, contains no slashes and is not equal to "`..'") are
     iteratively reduced to a single slash each, until no more terms of
     this kind can be found.

   * `$file = follow("FILENAME");'

     If the given filename (given as an absolute path or as a path
     relative to the current working directory) is a symbolic link, this
     function follows this symbolic link iteratively, as long as the
     resulting filename is also a symbolic link, until the end of the
     chain of symbolic links is reached.

     This last filename is then returned.

     If the given filename is not a symbolic link, it is simply
     "normalized" using the function "`normalize()'" (see above) and then
     returned.

   * `$file = absolute("FILENAME");'

     If the given filename is an absolute path, it is returned unchanged.

     Otherwise the output of "`/bin/pwd'" is prepended to it and the new
     filename is returned.

   * `$file = expand("FILENAME");'

     While the function "`follow()'" (see above) only expands the
     "basename" part of a given filename if it is a symbolic link (whereas
     the "dirname" part remains unchanged), this function expands ALL
     symbolic links encountered in a given filename, yielding the true
     physical (absolute) path of the file or directory in question.

     If the given filename is relative, it is first converted into an
     absolute path using the function "absolute()" (see above).

     If a file or directory of the given name does not exist, all symbolic
     links are expanded as far as possible (as far as the leading (left)
     part of the given filename matches existing directories and symbolic
     links).

Methods:
--------

   * `$BnP = BnP->new($target,$subset,$prefix,$homedir,$workspace);'

     This is the "Build'n'Play" installation project constructor method.

     In theory you can perform several installations simultaneously; each
     installation thereby has a variable space of its own, which is stored
     in the object returned by this method.

  -
     The parameter "$target" specifies a name for the installation project.
     This name has only informational character in this module, though.

  -
     The parameter "`$subset'" specifies a list of subtargets (as a single
     string, in which the different elements are concatenated with ".")
     which enable the corresponding sections in your installation script
     as defined by the "`begin_section()'", "`end_section()'",
     "`begin_lazy_section()'" and "`end_lazy_section()'" method calls in
     your script (see further below for a description of these methods).

  -
     The parameter "`$prefix'" specifies the installation prefix, e.g.
     "`/usr/local'", "`/opt/pkg/<target>'" etc.

     If this parameter is empty or contains only whitespace, the prefix is
     set to "`/usr/local'" by default.

  -
     The parameter "`$homedir'" specifies the home directory of the
     installation project, i.e., the directory where the automatic
     recovery file ("`recover.bnp'") for this project will be stored.

     A subdirectory named "src" in this directory is usually the place
     where all the necessary source distribution files are stored, but
     this is something controlled entirely by your installation script.

     Note that simultaneous installations must have different home
     directories, otherwise they will overwrite each other's automatic
     recovery file ("`recover.bnp'") in that directory.

  -
     The parameter "`$workspace'" specifies a directory where the source
     distribution files can be temporarily unpacked and compiled.

     This is also the directory the method "reset()" (see further below)
     performs a "chdir()" to.

     Note that it is technically possible to subclass the class implemented
     in this module and to inherit this constructor method.

     `$target = $BnP->target();'

     This method returns the name of the current installation project as
     defined in the call of the installation project constructor method
     "new()" (see above for details).

     `$subset = $BnP->subset();'

     This method returns the string containing the names of the sections in
     your installation script to be processed, as defined in the call of
     the installation project constructor method "new()" (see above for
     details).

     `$prefix = $BnP->prefix();'

     This method returns the prefix of the current installation project as
     defined in the call of the installation project constructor method
     "new()" (see above for details).

     `$homedir = $BnP->homedir();'

     This method returns the home directory of the current installation
     project as defined in the call of the installation project
     constructor method "new()" (see above for details).

     `$workspace = $BnP->workspace();'

     This method returns the directory used as a temporary workspace by the
     current installation project (several simultaneous installations may
     use the same workspace directory, unless they try to unpack
     distributions which result in a distribution directory of exactly the
     same name), as defined in the call of the installation project
     constructor method "new()" (see above for details).

     Note also that provisions need to be made (i.e., an appropriate
     subdirectory has to be created first) if you unpack any misbehaving
     distributions which do not create a distribution directory first
     themselves but simply spill their contents into the current working
     directory.

     `[ @path = ] $BnP->path( @path );'

     `@path = $BnP->path();'

     This method allows you to define a number of base directories where to
     search for source distribution files (see also the description of the
     method "fetch()" further below) in your local file system (e.g., on
     your hard disk, on a CD-ROM, etc.).

     Several directory names may be concatenated with ":" to form a single
     argument, or they can be passed as separate arguments. You can also
     mix these two forms.

     Note that any previous setting is REPLACED by the given arguments,
     i.e., this method is NOT accumulative.

     The method returns a list with all the directory names that have been
     passed to it (previously, or in the current call).

     If you call this method without parameters, the current setting is
     returned but not changed.

     Example:

          $BnP->path( '/mirrors:/cdrom', `pwd` );

     Trailing slashes ("/") will be removed automatically.

     Note that these directories must be given by their absolute path,
     because the current directory will usually change frequently over the
     course of your installation.

     Note also that these directories will always be searched in the given
     order (from left to right).

     Finally, note that this setting is cleared by the "`begin()'" and
     "end()" methods (see further below).

     (This setting is initialized to an empty list by the constructor
     method "new()".)

     `[ @stub = ] $BnP->stub( @stub );'

     `@stub = $BnP->stub();'

     This method allows you to define a number of subdirectories where to
     search for source distribution files (see also the description of the
     method "fetch()" further below) in your local file system (e.g., on
     your hard disk, on a CD-ROM, etc.).

     Several subdirectory names may be concatenated with blanks (" ") to
     form a single argument, or they can be passed as separate arguments.
     You can also mix these two forms.

     Note that any previous setting is REPLACED by the given arguments,
     i.e., this method is NOT accumulative.

     The method returns a list with all the subdirectory names that have
     been passed to it (previously, or in the current call).

     If you call this method without parameters, the current setting is
     returned but not changed.

     Example:

          $BnP->stub( 'CPAN', 'BnP/src', 'BnP', 'src' );

     Note that these subdirectories must be given as relative paths (any
     leading or trailing slash ("/") will be stripped anyway, however).

     Note also that these subdirectories will always be searched in the
     given order (from left to right) and that (moreover) the subdirectory
     "."  is always implicitly assumed to be at the beginning of this list.

     (As a consequence, if you don't need this feature of search
     subdirectories, you don't need to bother with this method at all,
     just leave this setting empty as it is initialized by the constructor
     method "new()".)

     When searching for a source distribution file, each of these
     subdirectories will in turn be appended to every base directory as
     defined by the "path()" method (see above) to form the list of actual
     directories to be searched (i.e., the search path is the set product
     of the directories defined with the "path()" method and the
     subdirectories defined with the "`stub()'" method).

     Finally, note that this setting is cleared by the "`begin()'" and
     "end()" methods (see further below).

     `[ @url = ] $BnP->url( @url );'

     `@url = $BnP->url();'

     This method allows you to define a number of URLs where to download
     source distribution files from which haven't been found in your local
     file system (see also the description of the method "fetch()" further
     below).

     Several URLs may be concatenated using blanks (" ") to form a single
     argument, or they can be passed as separate arguments. You can also
     mix these two forms.

     Note that any previous setting is REPLACED by the given arguments,
     i.e., this method is NOT accumulative.

     The method returns a list with all the URLs that have been passed to
     it (previously, or in the current call).

     If you call this method without parameters, the current setting is
     returned but not changed.

     Example:

          $BnP->url
          (
              'ftp://ftp.engelschall.com/pub/bnp ftp://ftp.netsw.org/netsw'
          );

     Note that these URLs should usually terminate in the name of a
     directory but should nevertheless NOT have a trailing slash!

     Note also that these URLs will always be searched in the given order
     (from left to right).

     Finally, note that this setting is cleared by the "`begin()'" and
     "end()" methods (see below).

     `$BnP->begin();'

     This method call starts the actual installation.

     A (possibly) still open automatic recovery file is closed, and all
     internal attributes of the current installation project (except the
     ones which contain the parameters passed to the installation project
     constructor method "new()") are reset to their default values (this
     is so that you can use the same installation project object several
     times in sequence).

     The method then checks wether an automatic recovery file
     "`recover.bnp'" already exists for the current installation project,
     and if so, reads it in.

     (The contents of the automatic recovery file are then stored in
     memory in the given installation project object for fastest possible
     access.)

     Moreover, if it exists, this automatic recovery file is renamed (its
     suffix "`.bnp'" is thereby replaced by a 3-digit number which is the
     smallest such number which hasn't been assigned yet, by starting at
     "`000'" and incrementing as necessary), and a new recovery file is
     created and opened for writing.

     A header line showing the name and version number of this module as
     well as a confirmation for some of your calling parameters is printed
     to the screen, and a "chdir()" is made via the method "reset()" (see
     also further below) to the directory "`$workspace'", as defined in
     the call of the installation project constructor method "new()" (see
     above for details).

     `$BnP->end();'

     This method call terminates the actual installation.

     First the automatic recovery file is closed (nothing is done if the
     file has already been closed before, for instance by a previous call
     of this method).

     Then all internal attributes of the current installation project
     (except the ones which contain the parameters passed to the
     installation project constructor method "new()") are reset to their
     default values (this is so that you can use the same installation
     project object several times in sequence).

     Finally, a message confirming the successful installation is printed
     to the screen.

     `$BnP->begin_section("NAME", ...);'

     This method call marks the beginning of a named section in your
     installation script.

     You can pass several names (or "labels") to this method, which will
     be treated as synonyms for the section in question.

     I.e., specifying ANY of these labels from this method call in the
     parameter "`$subset'" at runtime (via the "new()" constructor method
     - see above) will enable the commands in the corresponding section.

     If none of the subtargets specified in the parameter "`$subset'"
     matches any of the labels in this method call, then the commands in
     the corresponding section will be disabled - unless the parameter
     "`$subset'" is empty, in which case the "`begin_section()'" and
     "`end_section()'" (see below) method calls are simply ignored
     altogether.

     (An empty parameter "`$subset'" means "install ALL sections",
     therefore the "`begin_section()'" and "`end_section()'" method calls
     need not to be evaluated in such a case.)

     This way you can also define the section in question as being part of
     a set of sections forming a larger whole, or mark parts which are
     prerequisites of other sections, as in the following example:

          $BnP->begin_section("net","mail","news");
          # install net software (prerequisite for mail and news)
          $BnP->end_section("net","mail","news");
          ...
          $BnP->begin_section("mail");
          # install mail software
          $BnP->end_section("mail");
          ...
          $BnP->begin_section("news");
          # install news software
          $BnP->end_section("news");

     If the runtime parameter "`$subset'" contains "net", only the "net"
     portion will be installed. If it contains "mail", the "net" portion
     as well as the "mail" part itself will be installed. If it contains
     "mail" AND "news", all three parts will be installed, and so on.

     `$BnP->end_section("NAME", ...);'

     This method call marks the end of one or several named sections in
     your installation script.

     If any of the labels listed in this method call matches any of the
     subtargets given in the runtime parameter "`$subset'" - provided that
     the latter is not empty - then the execution of all commands
     following this method call is disabled.

     If there is no match, the commands following this method call will
     continue to be executed.

     If the runtime parameter "`$subset'" is empty, this method call is
     ignored altogether.

     This allows you to terminate different sections at different times,
     as in the following example:

          $BnP->begin_section("net","mail");
          # install net software (prerequisite for mail)
          $BnP->end_section("net");
          # install mail software
          $BnP->end_section("mail");

     If the runtime parameter "`$subset'" contains "net", only the "net"
     portion will be installed. If it contains "mail", the "net" portion
     as well as the "mail" part itself will be installed.

     `$BnP->begin_must_section();'

     This method call marks the beginning of a section in your installation
     script which is executed under all circumstances.

     This method takes no arguments; all arguments passed to it are
     ignored.

     This method call takes precedence over all other method calls
     defining the beginning or end of any overlapping section, but it
     doesn't impede their (invisible) working, as in the following example:

          $BnP->begin_section("a");
          # commands 1
          $BnP->begin_must_section();
          # commands 2
          $BnP->end_section("a");
          # commands 3
          $BnP->begin_section("b");
          # commands 4
          $BnP->end_must_section();
          # commands 5
          $BnP->end_section("b");

     In this example, the commands "2", "3" and "4" are ALWAYS executed,
     regardless of the contents of the runtime parameter "`$subset'".

     The commands "1" will be executed only if the runtime parameter
     "`$subset'" is empty or if it contains "a". The commands "5" will be
     executed only if the runtime parameter "`$subset'" is empty or if it
     contains "b".

     `$BnP->end_must_section();'

     This method call marks the end of a section in your installation
     script which is executed under all circumstances.

     This method takes no arguments; all arguments passed to it are
     ignored.

     `$BnP->begin_lazy_section("NAME", ...);'

     This method call marks the beginning of a section in your installation
     script which will be executed ONLY if you specify at least ONE of the
     labels listed in this method call EXPLICITLY as part of the runtime
     parameter "`$subset'", i.e., this is some kind of a "lazy" or
     "delayed" evaluation section.

     This method call takes precedence over any overlapping sections
     defined via the "`begin_section()'" and "`end_section()'" pair of
     methods, as shown in the following example:

          $BnP->begin_section("a");
          # commands 1
          $BnP->begin_lazy_section("x");
          # commands 2
          $BnP->end_section("a");
          # commands 3
          $BnP->begin_section("b");
          # commands 4
          $BnP->end_lazy_section("x");
          # commands 5
          $BnP->end_section("b");

     In this example, the commands "2", "3" and "4" are executed if and
     only if the runtime parameter "`$subset'" contains "x".

     The commands "1" will be executed only if the runtime parameter
     "`$subset'" is empty or if it contains "a". The commands "5" will be
     executed only if the runtime parameter "`$subset'" is empty or if it
     contains "b".

     Overlapping "lazy" sections behave sligthly differently, as
     illustrated in the following example:

          $BnP->begin_lazy_section("a","c");
          # commands 1
          $BnP->begin_lazy_section("b");
          # commands 2
          $BnP->end_lazy_section("a");
          # commands 3
          $BnP->end_lazy_section("b","c");

     In this example, the commands "1" and "2" are executed if the runtime
     parameter "`$subset'" contains "a" (or "c").

     The commands "2" and "3" are executed if the runtime parameter
     "`$subset'" contains "b" (or "c").

     None of these commands is executed if the runtime parameter
     "`$subset'" contains neither "a" nor "b" (nor "c"), and all of these
     commands are executed if "`$subset'" contains "a" as well as "b" (or
     just "c").

     `$BnP->end_lazy_section("NAME", ...);'

     This method call marks the end of one or several named "lazy" sections
     in your installation script.

     `$BnP->ignore();'

     This method call can be used to "comment out" all subsequent commands
     until the next occurrence of a "`resume()'" method call (see also
     below).

     This method call takes precedence over all others, even "must"
     sections and "lazy" sections (see also their corresponding
     descriptions above).

     This method call does not impede the "section" method calls from
     working, however, it just prevents any actions to be actually
     performed, as shown in the following example:

          $BnP->begin_section("a");
          # commands 1
          $BnP->ignore();
          # commands 2
          $BnP->end_section("a");
          # commands 3
          $BnP->begin_section("b");
          # commands 4
          $BnP->resume();
          # commands 5
          $BnP->end_section("b");

     In this example, the commands "2", "3" and "4" are NEVER executed,
     regardless of the contents of the runtime parameter "`$subset'".

     The commands "1" will be executed only if the runtime parameter
     "`$subset'" is empty or if it contains "a". The commands "5" will be
     executed only if the runtime parameter "`$subset'" is empty or if it
     contains "b".

     `$BnP->resume();'

     This method call ends a section of your installation script which has
     been "commented out".

     Normal operation of your installation script resumes after this
     method call.

     Note that you cannot nest "`ignore()'" and "`resume()'" method calls;
     the first "`ignore()'" method encountered will disable all following
     commands, and the first "`resume()'" method encountered will enable
     execution again:

          $BnP->ignore();
          # commands 1
          $BnP->ignore();
          # commands 2
          $BnP->resume();
          # commands 3
          $BnP->resume();
          # commands 4

     In this example, the commands "1" and "2" will never be executed, and
     execution resumes at commands "3", not "4" (which means that both
     commands "3" and "4" are executed, in this example).

     `$flag = $BnP->active();'

     This method returns "`true'" if it is called from within a section
     which is currently being executed (for instance, this method ALWAYS
     returns "`true'" when called from within a "must" section), or "false"
     otherwise.

     In particular, this method also reports "false" if called from within
     a part in your installation script that has been "commented out" with
     the "`ignore()'" and "`resume()'" pair of methods.

     `$BnP->reset();'

     This method does nothing but a "chdir()" (see below) to the directory
     "`$workspace'", as defined in the call of the installation project
     constructor method "new()" (see above for details).

     `$BnP->back();'

     This method is just a shorthand for "`$BnP->chdir('../');'".

     `$BnP->back(COUNT);'

     This method is just a shorthand for "`$BnP->chdir('../' x COUNT);'",
     where "`COUNT'" is replaced by "1" if it is less than one.

     `$BnP->chdir("DIR");'

     This method can be used to change the current working directory for
     all subsequent commands which implicitly act upon it (all Unix and
     Perl commands dealing with files and directories normally do, if no
     absolute paths are given).

     The parameter "DIR" may be an absolute or a relative path. In the
     latter case this path will be relative to the current working
     directory as defined previously.

     At the beginning of the installation, the method "`begin()'" sets the
     current working directory to "`$workspace'", as defined in the call
     of the installation project constructor method "new()" (see above for
     details), using the method "reset()" (see above).

     `$BnP->mkdir("DIR");'

     This method can be used to create a new directory.

     If the directory's path "DIR" is not absolute, it will be relative to
     the current working directory, as defined previously using the methods
     "reset()", "chdir()" and "`back()'" (see above for details).

     In contrast to the Unix or Perl "mkdir" commands, this method will
     also automatically and recursively create any missing intervening
     directories; i.e., if the directory "/tmp" does not contain any
     subdirectories, then the method call
     "`$BnP->mkdir('/tmp/bnp/hmtl/mod');'" will first create the directory
     "`/tmp/bnp'", then the directory "`/tmp/bnp/html'", and finally the
     directory "`/tmp/bnp/html/mod'".

     The method does nothing (and does NOT produce any error message) if
     the directory to be created already exists.

     `$BnP->fetch("FILENAME", "RELPATH", "SOURCEDIR");'

     This method fetches a distribution file from a predefined search path
     or (if necessary) a list of URLs and puts it into the specified source
     directory.

     The method does nothing if the distribution file is already found in
     the given source directory.

     Otherwise it searches the directories which have been specified
     previously by the "path()" and "`stub()'" methods (see further
     above), in their given order.

     The method thereby cycles through all the directories specified by
     "path()".  It first tests any such directory wether it contains the
     requested distribution file. If not, the method cycles through all
     the subdirectories as specified by "`stub()'" and tests each of these
     subdirectories in the currently examined directory. If the test fails
     for a subdirectory, the method also tests the subsubdirectory
     "RELPATH" in that subdirectory.

     If the requested distribution file is found in any of these
     directories or (sub-) subdirectories, the method first attempts to
     create a symbolic link in the given source directory which points to
     the location where the distribution file has been found.

     Should this fail for some reason (e.g. if your system does not support
     symbolic links), the method alternatively tries to copy the
     distribution file to the specified source directory.

     If this also fails (for instance in case of disk capacity overrun),
     the method gives up and throws a (fatal) exception.

     If the requested distribution file is not found in any of these
     directories, the method tries to find a tool for the automatic
     download.

     If none of the configured tools (currently "snarf" and "lynx") can be
     found on your system, a fatal exception follows.

     Otherwise the method searches the URLs which have been specified
     previously by the "`url()'" method (see further above), in the given
     order.

     The method thereby cycles through all the URLs specified by
     "`url()'", to each of which the relative path "RELPATH" and the
     filename "FILENAME" is appended (for this reason the given URLs
     should not end in as slash "/"!).

     If the requested distribution file cannot be downloaded successfully
     from any of these URLs, a corresponding error message is printed to
     the screen and program execution is aborted.

     Note that this may be due to a server being down temporarily, so
     sometimes you may just need to restart your installation script in
     order to succeed, or specify a different server.

     If the distribution file is found on one of the specified servers, it
     is downloaded into the given source directory "SOURCEDIR" and the
     method returns to the caller.

     `$BnP->system("COMMAND", ...);'

     This method allows you to use any (shell) commands you may need while
     still benefiting from the automatic recovery mechanism provided by
     this module.

     All the arguments to this method are concatenated using spaces, i.e.,
     you don't need to include spaces at the beginning and the end of
     these arguments, and you don't need to concatenate them with the
     "."-operator yourself (you will have to supply those spaces yourself
     if you do, however).

     Since all the arguments are concatenated, they form a single command
     line.

     In order to include several different commands on that same command
     line, use the semicolon ("`;'") to separate them, as usually.

     `$BnP->patch("FILENAME", "PERLEXPR", ...);'

     This method resembles the Unix tool "`sed'".

     It allows you to apply arbitrary Perl expressions (typically
     substitution commands like "s///" and "tr///") to the lines (or
     paragraphs or the entire file at once) of the given file.

     (The lines (or paragraphs or the entire file) of the file in question
     are thereby successively read into the Perl variable "$_".)

     Before actually applying any modifications, a new filename for the
     original file is generated (for later safeguarding), by appending
     ".000" to its name and increasing this number if a file of that name
     already exists, until a filename is found which doesn't exist yet.

     Another new (temporary) filename is generated (in the same manner)
     for the file which will hold the results of the "patch" operation, by
     using the number found in the previous step plus one, and again by
     incrementing this number if a file of that name already exists, until
     a filename is found which doesn't exist yet.

     Then the original file is read, all the commands given as arguments to
     this method are applied successively (in the given order) to each of
     the lines (or paragraphs or the entire file) being read, and the
     results are written to a new file with the (temporary) filename (the
     second of the two filenames generated above).

     Note that you can control the "line" vs. "paragraph" vs. "entire
     file" mode by setting the Perl variable "$/" appropriately (see
     `perlvar(1)' in this node for more details).

     (Don't forget to reset this variable to its default value in order to
     avoid unexpected results in the remaining part of your script,
     though.)

     After reading all of the original file, and only if no errors
     occurred, the original file is renamed to the first of the two new
     filenames generated above, and the file containing the results of the
     "patch" operation is renamed to the (original) filename of the
     original file.

     In case of an error (most likely a Perl syntax error in one of the
     expressions you supplied as arguments to this method), all files are
     closed, the temporary file containing the results (if any) is
     deleted, an appropriate error message is displayed and program
     execution is aborted.

MODERATED METHODS
=================

   The following methods are subject to be switched "off" and "on" by the
methods "`begin_section()'", "`end_section()'", "`begin_must_section()'",
"`end_must_section()'", "`begin_lazy_section()'", "`end_lazy_section()'",
"`ignore()'" and "`resume()'":

     -  reset()
     -  back()
     -  chdir()
     -  mkdir()
     -  fetch()
     -  system()
     -  patch()

   You can always determine wether these methods will currently (i.e., in
the current section of your installation script) be executed or ignored by
calling the method "`active()'", which returns "`true'" if the section in
question is "active" and "false" if the commands in that section will
currently be ignored.

SEE ALSO
========

   build(1), genopt(1), make(1), CPAN(3).

VERSION
=======

   This man page documents "BnP" version 2.1.0.

AUTHORS
=======

     Ralf S. Engelschall - original idea and first private versions

     rse@engelschall.com
     www.engelschall.com

     Steffen Beyer       - complete rewrite and documentation
                           (first public version)

     sb@engelschall.com
       www.engelschall.com/u/sb/download/

COPYRIGHT
=========

     Copyright (c) 1996 - 1998 by Ralf S. Engelschall.
     All rights reserved.

     Copyright (c) 1998 by Steffen Beyer.
     All rights reserved.

LICENSE
=======

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself, i.e., under the terms of the
"Artistic License" or the "GNU General Public License".

   Please refer to the files "Artistic.txt" and "GNU_GPL.txt" in this
distribution for details!

DISCLAIMER
==========

   This package 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.

Perl module for generating pickup lines.
****************************************

NAME
====

   Bone::Easy - Perl module for generating pickup lines.

SYNOPSIS
========

     use Bone::Easy;

     # I know you get this a lot, but what's a unholy fairy like you
     # doing in a mosque like this?
     print pickup, "\n";

DESCRIPTION
===========

   Generates pickup-lines GUARANTEED to get something thrown in your face.

AUTHOR
======

   Idea and original ruleset by TheSpark.com <http://www.thespark.com> and
Chris Coyne <ccoyne@staff.thespark.com>

   Perl Code by Michael G Schwern <schwern@pobox.com>

LICENSE
=======

   This program may be distributed under the same license as Perl itself,
except for Bone::Easy::Rules.  See Bone/Easy/Rules, for
details.

SEE ALSO
========

   See Safe, Sex, `pickup' in this node, see
Bone/Easy/Rules,

Default ruleset for Bone::Easy
******************************

NAME
====

   Bone::Easy::Rules - Default ruleset for Bone::Easy

SYNOPSIS
========

     use Bone::Easy::Rules;
     @rules = <Bone::Easy::Rules::__DATA__>;

DESCRIPTION
===========

   Due to licensing issues, the default ruleset must reside seperately
from the code.

AUTHOR
======

   Original ruleset by TheSpark.com <http://www.thespark.com> and Chris
Coyne <ccoyne@staff.thespark.com>

   Perl code by Michael G Schwern <schwern@pobox.com>

LICENSE
=======

   This library (Bone::Easy::Rules) is free for noncommercial use and
modification.  Anyone wishing to use it for commercial purposes must get
the permission of Chris Coyne and TheSpark.com

SEE ALSO
========

   See Bone/Easy, and `pickup' in this node

An API for hierarchical tag/value structures
********************************************

NAME
====

   Boulder - An API for hierarchical tag/value structures

SYNOPSIS
========

     # Read a series of People records from STDIN.
     # Add an "Eligibility" attribute to all those whose
     # Age >= 35 and Friends list includes "Fred"

     use Boulder::Stream;

     my $stream = Boulder::Stream->newFh;

     while ( my $record = <$stream> ) {
        next unless $record->Age >= 35;
        my @friends = $record->Friends;
        next unless grep {$_ eq 'Fred'} @friends;

     $record->insert(Eligibility => 'yes');
     print $stream $record;
         }

   Related manual pages:

     basics
     ------
     Stone            hierarchical tag/value records
     Stone::Cursor    Traverse a hierarchy

     Boulder::Stream  stream-oriented storage for Stones
     Boulder::Store   record-oriented storage for Stones
     Boulder::XML     XML conversion for Stones
     Boulder::String  conversion to strings

     genome-related
     ---------------

     Boulder::Genbank   parse Genbank (DNA sequence) records
     Boulder::Blast     parse BLAST (basic local alignment search tool) reports
     Boulder::Medline   parse Medline (pubmed) records
     Boulder::Omim      parse OMIM (online Mendelian inheritance in man) records
     Boulder::Swissprot parse Swissprot records
     Boulder::Unigene   parse Unigene records

DESCRIPTION
===========

Boulder IO
----------

   Boulder IO is a simple TAG=VALUE data format designed for sharing data
between programs connected via a pipe.  It is also simple enough to use as
a common data exchange format between databases, Web pages, and other data
representations.

   The basic data format is very simple.  It consists of a series of
TAG=VALUE pairs separated by newlines.  It is record-oriented.  The end of
a record is indicated by an empty delimiter alone on a line.  The
delimiter is "=" by default, but can be adjusted by the user.

   An example boulder stream looks like this:

     Name=Lincoln Stein
     Home=/u/bush202/lds32
     Organization=Cold Spring Harbor Laboratory
     Login=lds32
     Password_age=20
     Password_expires=60
             Alias=lstein
             Alias=steinl
     =
     Name=Leigh Deacon
     Home=/u/bush202/tanager
     Organization=Cold Spring Harbor Laboratory
     Login=tanager
     Password_age=2
     Password_expires=60
     =

   Notes:

(1)
     There is no need for all tags to appear in all records, or indeed for
     all the records to be homogeneous.

(2)
     Multiple values are allowed, as with the Alias tag in the second
     record.

(3)
     Lines can be any length, as in a potential 40 Kbp DNA sequence entry.

(4)
     Tags can be any alphanumeric character (upper or lower case) and may
     contain embedded spaces.  Conventionally we use the characters
     A-Z0-9_, because they can be used without single quoting as keys in
     Perl associative arrays, but this is merely stylistic.  Values can be
     any character at all except for the reserved characters {}=% and
     newline.  You can incorporate binary data into the data stream by
     escaping these characters in the URL manner, using a % sign followed
     by the (capitalized) hexadecimal code for the character.  The module
     makes this automatic.

Hierarchical Records
--------------------

   The simple boulder format can be extended to accomodate nested
relations and other intresting structures.  Nested records can be created
in this way:

     Name=Lincoln Stein
     Home=/u/bush202/lds32
     Organization=Cold Spring Harbor Laboratory
     Login=lds32
     Password_age=20
     Password_expires=60
     Privileges={
       ChangePasswd=yes
       CronJobs=yes
       Reboot=yes
       Shutdown=no
     }
     =
     Name=Leigh Deacon
     Home=/u/bush202/tanager
     Organization=Cold Spring Harbor Laboratory
     Login=tanager
     Password_age=2
     Password_expires=60
     Privileges={
       ChangePasswd=yes
       CronJobs=no
       Reboot=no
       Shutdown=no
     }
     =

   As in the original format, tags may be multivalued.  For example, there
might be several Privilege record assigned to a login account.  Each
subrecord may contain further subrecords.

   Within the program, a hierarchical record is encapsulated within a
"Stone", an opaque structure that implements methods for fetching and
settings its various tags.

Using Boulder for I/O
---------------------

   The Boulder API was designed to make reading and writing of complex
hierarchical records almost as easy as reading and writing single lines of
text.

Boulder::Stream
     The main component of the Boulder modules is Boulder::Stream, which
     provides a stream-oriented view of the data.  You can read and write
     to Boulder::Streams via tied filehandles, or via method calls.  Data
     records are flattened into a simple format called "boulderio" format.

Boulder::XML
     Boulder::XML acts like Boulder::Stream, but the serialization format
     is XML.  You need XML::Parser installed to use this module.

Boulder::Store
     This is a simple persistent storage class which allows you to store
     several (thousand) Stone's into a DB_File database.  You must have
     libdb and the Perl DB_File extensions installed in order to take
     advantage of this class.

Boulder::Genbank
Boulder::Unigene
Boulder::OMIM
Boulder::Blast
Boulder::Medline
Boulder::SwissProt
     These are parsers and accessors for various biological data sources.
     They act like Boulder::Stream, but return a set of Stone objects that
     have certain prescribed tags and values.  Many of these modules were
     written by Luca I.G. Toldo <luca.toldo@merck.de>.

Stone Objects
-------------

   The Stone object encapsulates a set of tags and values.  Any tag can be
single- or multivalued, and tags are allowed to contain subtags to any
depth.  A simple set of methods named tags(), get(), put(), insert(),
replace() and so forth, allows you to examine the tags that are available,
get and set their values, and search for particular tags.  In addition, an
autoload mechanism allows you to use method calls to access tags, for
example:

     my @friends = $record->Friends;

   is equivalent to:

     my @friends = $record->get('Friends');

   A Stone::Cursor class allows you to traverse Stones systematically.

   A full explanation of the Stone class can be found in its manual page.

AUTHOR
======

   Lincoln D. Stein <lstein@cshl.org>, Cold Spring Harbor Laboratory, Cold
Spring Harbor, NY.  This module can be used and distributed on the same
terms as Perl itself.

SEE ALSO
========

   See Boulder/Blast, Boulder/Genbank,
see Boulder/Medline,
Boulder/Unigene, Boulder/Omim,
`Boulder::SwissProt' in this node

Parse and read BLAST files
**************************

NAME
====

   Boulder::Blast - Parse and read BLAST files

SYNOPSIS
========

     use Boulder::Blast;

     # parse from a single file
     $blast = Boulder::Blast->parse('run3.blast');

     # parse and read a set of blast output files
     $stream = Boulder::Blast->new('run3.blast','run4.blast');
     while ($blast = $stream->get) {
        # do something with $blast object
     }

     # parse and read a whole directory of blast runs
     $stream = Boulder::Blast->new(<*.blast>);
     while ($blast = $stream->get) {
        # do something with $blast object
     }

     # parse and read from STDIN
     $stream = Boulder::Blast->new;
     while ($blast = $stream->get) {
        # do something with $blast object
     }

     # parse and read as a filehandle
     $stream = Boulder::Blast->newFh(<*.blast>);
     while ($blast = <$stream>) {
        # do something with $blast object
     }

     # once you have a $blast object, you can get info about it:
     $query = $blast->Blast_query;
     @hits  = $blast->Blast_hits;
     foreach $hit (@hits) {
        $hit_sequence = $hit->Name;    # get the ID
        $significance = $hit->Signif;  # get the significance
        @hsps = $hit->Hsps;            # list of HSPs
        foreach $hsp (@hsps) {
          $query   = $hsp->Query;      # query sequence
          $subject = $hsp->Subject;    # subject sequence
          $signif  = $hsp->Signif;     # significance of HSP
        }
     }

DESCRIPTION
===========

   The Boulder::Blast class parses the output of the *Washington
University (WU)* or National Cenber for Biotechnology Information (NCBI)
series of BLAST programs and turns them into *Stone* records.  You may
then use the standard Stone access methods to retrieve information about
the BLAST run, or add the information to a Boulder stream.

   The parser works equally well on the contents of a static file, or on
information read dynamically from a filehandle or pipe.

METHODS
=======

parse() Method
--------------

     $stone = Boulder::Blast->parse($file_path);
     $stone = Boulder::Blast->parse($filehandle);

   The parse() method accepts a path to a file or a filehandle, parses its
contents, and returns a Boulder Stone object.  The file path may be
absolute or relative to the current directgly.  The filehandle may be
specified as an IO::File object, a FileHandle object, or a reference to a
glob (`\*FILEHANDLE' notation).  If you call parse() without any
arguments, it will try to parse the contents of standard input.

new() Method
------------

     $stream = Boulder::Blast->new;
     $stream = Boulder::Blast->new($file [,@more_files]);
     $stream = Boulder::Blast->new(\*FILEHANDLE);

   If you wish, you may create the parser first with Boulder::Blast new(),
and then invoke the parser object's parse() method as many times as you
wish to, producing a Stone object each time.

TAGS
====

   The following tags are defined in the parsed Blast Stone object:

Information about the program
-----------------------------

   These top-level tags provide information about the version of the BLAST
program itself.

Blast_program
     The name of the algorithm used to run the analysis.  Possible values
     include:

          blastn
          blastp
          blastx
          tblastn
          tblastx
          fasta3
          fastx3
          fasty3
          tfasta3
          tfastx3
          tfasty3

Blast_version
     This gives the version of the program in whatever form appears on the
     banner page, e.g. "2.0a19-WashU".

Blast_program_date
     This gives the date at which the program was compiled, if and only if
     it appears on the banner page.

Information about the run
-------------------------

   These top-level tags give information about the particular run, such as
the parameters that were used for the algorithm.

Blast_run_date
     This gives the date and time at which the similarity analysis was
     run, in the format "Fri Jul  6 09:32:36 1998"

Blast_parms
     This points to a subrecord containing information about the
     algorithm's runtime parameters.  The following subtags are used.
     Others may be added in the future:

          Hspmax		the value of the -hspmax argument
          Expectation	the value of E
          Matrix		the matrix in use, e.g. BLOSUM62
          Ctxfactor	the value of the -ctxfactor argument
          Gapall		The value of the -gapall argument

Information about the query sequence and subject database
---------------------------------------------------------

   Thse top-level tags give information about the query sequence and the
database that was searched on.

Blast_query
     The identifier for the search sequence, as defined by the FASTA
     format.  This will be the first set of non-whitespace characters
     following the ">" character.  In other words, the search sequence
     "name".

Blast_query_length
     The length of the query sequence, in base pairs.

Blast_db
     The Unix filesystem path to the subject database.

Blast_db_title
     The title of the subject database.

The search results: the *Blast_hits* tag.
-----------------------------------------

   Each BLAST hit is represented by the tag *Blast_hits*.  There may be
zero, one, or many such tags.  They will be presented in reverse sorted
order of significance, i.e. most significant hit first.

   Each *Blast_hits* tag is a Stone subrecord containing the following
subtags:

Name
     The name/identifier of the sequence that was hit.

Length
     The total length of the sequence that was hit

Signif
     The significance of the hit.  If there are multiple HSPs in the hit,
     this will be the most significant (smallest) value.

Identity
     The percent identity of the hit.  If there are multiple HSPs, this
     will be the one with the highest percent identity.

Expect
     The expectation value for the hit.  If there are multiple HSPs, this
     will be the lowest expectation value in the set.

Hsps
     One or more sub-sub-tags, pointing to a nested record containing
     information about each high-scoring segment pair (HSP).  See the next
     section for details.

The Hsp records: the Hsps tag
-----------------------------

   Each *Blast_hit* tag will have at least one, and possibly several Hsps
tags, each one corresponding to a high-scoring segment pair (HSP).  These
records contain detailed information about the hit, including the
alignments.  Tags are as follows:

Signif
     The significance (P value) of this HSP.

Bits
     The number of bits of significance.

Expect
     Expectation value for this HSP.

Identity
     Percent identity.

     =item Positives

     Percent positive matches.

Score
     The Smith-Waterman alignment score.

Orientation
     The word "plus" or "minus".  This tag is only present for nucleotide
     searches, when the reverse complement match may be present.

Strand
     Depending on algorithm used, indicates complementarity of match and
     possibly the reading frame.  This is copied out of the blast report.
     Possibilities include:

          "Plus / Minus" "Plus / Plus" -- blastn algorithm
          "+1 / -2" "+2 / -2"	     -- blastx, tblastx

Query_start
     Position at which the HSP starts in the query sequence (1-based
     indexing).

Query_end
     Position at which the HSP stops in the query sequence.

Subject_start
     Position at which the HSP starts in the subject (target) sequence.

Subject_end
     Position at which the HSP stops in the subject (target) sequence.

Query, Subject, Alignment
     These three tags contain strings which, together, create the gapped
     alignment of the query sequence with the subject sequence.

     For example, to print the alignment of the first HSP of the first
     match, you might say:

          $hsp = $blast->Blast_hits->Hsps;
          print join("\n",$hsp->Query,$hsp->Alignment,$hsp->Subject),"\n";

   See the bottom of this manual page for an example BLAST run.

CAVEATS
=======

   This module has been extensively tested with WUBLAST, but very little
with NCBI BLAST.  It probably will not work with PSI Blast or other
variants.

   The author plans to adapt this module to parse other formats, as well
as non-BLAST formats such as the output of Fastn.

SEE ALSO
========

   See Boulder, `Boulder::GenBank' in this node

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

   Copyright (c) 1998-1999 Cold Spring Harbor Laboratory

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

EXAMPLE BLASTN RUN
==================

   This output was generated by the *quickblast.pl* program, which is
located in the `eg/' subdirectory of the *Boulder* distribution directory.
It is a typical *blastn* (nucleotide->nucleotide) run; however long lines
(usually DNA sequences) have been truncated.  Also note that per the
Boulder protocol, the percent sign (%) is escaped in the usual way.  It
will be unescaped when reading the stream back in.

     Blast_run_date=Fri Nov  6 14:40:41 1998
     Blast_db_date=2:40 PM EST Nov 6, 1998
     Blast_parms={
       Hspmax=10
       Expectation=10
       Matrix=+5,-4
       Ctxfactor=2.00
     }
     Blast_program_date=05-Feb-1998
     Blast_db= /usr/tmp/quickblast18202aaaa
     Blast_version=2.0a19-WashU
     Blast_query=BCD207R
     Blast_db_title= test.fasta
     Blast_query_length=332
     Blast_program=blastn
     Blast_hits={
       Signif=3.5e-74
       Expect=3.5e-74,
       Name=BCD207R
       Identity=100%25
       Length=332
       Hsps={
         Subject=GTGCTTTCAAACATTGATGGATTCCTCCCCTTGACATATATATATACTTTGGGTTCCCGCAA...
         Signif=3.5e-74
         Length=332
         Bits=249.1
         Query_start=1
         Subject_end=332
         Query=GTGCTTTCAAACATTGATGGATTCCTCCCCTTGACATATATATATACTTTGGGTTCCCGCAA...
         Positives=100%25
         Expect=3.5e-74,
         Identity=100%25
         Query_end=332
         Orientation=plus
         Score=1660
         Strand=Plus / Plus
         Subject_start=1
         Alignment=||||||||||||||||||||||||||||||||||||||||||||||||||||||||||...
       }
     }
     =

Example BLASTP run
==================

   Here is the output from a typical *blastp* (protein->protein) run.
Long lines have again been truncated.

     Blast_run_date=Fri Nov  6 14:37:23 1998
     Blast_db_date=2:36 PM EST Nov 6, 1998
     Blast_parms={
       Hspmax=10
       Expectation=10
       Matrix=BLOSUM62
       Ctxfactor=1.00
     }
     Blast_program_date=05-Feb-1998
     Blast_db= /usr/tmp/quickblast18141aaaa
     Blast_version=2.0a19-WashU
     Blast_query=YAL004W
     Blast_db_title= elegans.fasta
     Blast_query_length=216
     Blast_program=blastp
     Blast_hits={
       Signif=0.95
       Expect=3.0,
       Name=C28H8.2
       Identity=30%25
       Length=51
       Hsps={
         Subject=HMTVEFHVTSQSW---FGFEDHFHMIIR-AVNDENVGWGVRYLSMAF
         Signif=0.95
         Length=46
         Bits=15.8
         Query_start=100
         Subject_end=49
         Query=HLTQD-HGGDLFWGKVLGFTLKFNLNLRLTVNIDQLEWEVLHVSLHF
         Positives=52%25
         Expect=3.0,
         Identity=30%25
         Query_end=145
         Orientation=plus
         Score=45
         Subject_start=7
         Alignment=H+T + H     W    GF   F++ +R  VN + + W V ++S+ F
       }
     }
     Blast_hits={
       Signif=0.99
       Expect=4.7,
       Name=ZK896.2
       Identity=24%25
       Length=340
       Hsps={
         Subject=FSGKFTTFVLNKDQATLRMSSAEKTAEWNTAFDSRRGFF----TSGNYGL...
         Signif=0.99
         Length=101
         Bits=22.9
         Query_start=110
         Subject_end=243
         Query=FWGKVLGFTL-KFNLNLRLTVNIDQLEWEVLHVSLHFWVVEVSTDQTLSVE...
         Positives=41%25
         Expect=4.7,
         Identity=24%25
         Query_end=210
         Orientation=plus
         Score=65
         Subject_start=146
         Alignment=F GK   F L K    LR++      EW     S   +     T     +...
       }
     }
     =

Parse and read NCBI BLAST files
*******************************

NAME
====

   Boulder::Blast::NCBI - Parse and read NCBI BLAST files

SYNOPSIS
========

   Not for direct use.  Use Boulder::Blast instead.

DESCRIPTION
===========

   Specialized parser for NCBI format BLAST output.  Loaded automatically
by Boulder::Blast.

SEE ALSO
========

   See Boulder, `Boulder::GenBank' in this node, see
Boulder/Blast,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

   Copyright (c) 1998 Cold Spring Harbor Laboratory

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

Parse and read WU-BLAST files
*****************************

NAME
====

   Boulder::Blast::WU - Parse and read WU-BLAST files

SYNOPSIS
========

   Not for direct use.  Use Boulder::Blast instead.

DESCRIPTION
===========

   Specialized parser for WUBLAST format BLAST output.  Loaded
automatically by Boulder::Blast.

SEE ALSO
========

   See Boulder, `Boulder::GenBank' in this node, see
Boulder/Blast,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

   Copyright (c) 1998 Cold Spring Harbor Laboratory

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

Fetch Genbank data records as parsed Boulder Stones
***************************************************

NAME
====

   Boulder::Genbank - Fetch Genbank data records as parsed Boulder Stones

SYNOPSIS
========

     use Boulder::Genbank

     # network access via Entrez
      $gb = Boulder::Genbank->newFh( qw(M57939 M28274 L36028) );

     while ($data = <$gb>) {
         print $data->Accession;

     @introns = $data->features->Intron;
     print "There are ",scalar(@introns)," introns.\n";
     $dna = $data->Sequence;
     print "The dna is ",length($dna)," bp long.\n";

     my @features = $data->features(-type=>[ qw(Exon Source Satellite) ],
     				      -pos=>[90,310] );
     foreach (@features) {
        print $_->Type,"\n";
        print $_->Position,"\n";
        print $_->Gene,"\n";
           }
         }

     # another syntax
     $gb = new Boulder::Genbank(-accessor=>'Entrez',
                                -fetch => [qw/M57939 M28274 L36028/]);

     # local access via Yank
     $gb = new Boulder::Genbank(-accessor=>'Yank',
                                -fetch=>[qw/M57939 M28274 L36028/]);
     while (my $s = $gb->get) {
        # etc.
     }

     # parse a file of Genbank records
     $gb = new Boulder::Genbank(-accessor=>'File',
                                -fetch => '/usr/local/db/gbpri3.seq');
     while (my $s = $gb->get) {
        # etc.
     }

     # parse flatfile records yourself
     open (GB,"/usr/local/db/gbpri3.seq");
     local $/ = "//\n";
     while (<GB>) {
        my $s = Boulder::Genbank->parse($_);
        # etc.
     }

DESCRIPTION
===========

   Boulder::Genbank provides retrieval and parsing services for NCBI
Genbank-format records.  It returns Genbank entries in Stone,
format, allowing easy access to the various fields and values.
Boulder::Genbank is a descendent of Boulder::Stream, and provides a
stream-like interface to a series of Stone objects.

   Access to Genbank is provided by three different *accessors*, which
together give access to remote and local Genbank databases.  When you
create a new Boulder::Genbank stream, you provide one of the three
accessors, along with accessor-specific parameters that control what
entries to fetch.  The three accessors are:

Entrez
     This provides access to NetEntrez, accessing the most recent Genbank
     information directly from NCBI's Web site.  The parameters passed to
     this accessor are either a series of Genbank accession numbers, or an
     Entrez query (see http://www.ncbi.nlm.nih.gov/Entrez/linking.html).
     If you provide a list of accession numbers, the stream will return a
     series of stones corresponding to the numbers.  Otherwise, if you
     provided an Entrez query, the entries returned will be in the order
     returned by Entez.

File
     This provides access to local Genbank entries by reading from a flat
     file (typically one of the .seq files downloadable from NCBI's Web
     site).  The stream will return a Stone corresponding to each of the
     entries in the file, starting from the top of the file and working
     downward.  The parameter in this case is the path to the local file.

Yank
     This provides access to local Genbank entries using Will Fitzhugh's
     Yank program.  Yank provides fast indexed access to a Genbank flat
     file using the accession number as the key.  The parameter passed to
     the Yank accessor is a list of accession numbers.  Stones will be
     returned in the requested order.  By default the yank binary lives in
     /usr/local/bin/yank.  To support other locations, you may define the
     environment variable YANK to contain the full path.

   It is also possible to parse a single Genbank entry from a text string
stored in a scalar variable, returning a Stone object.

Boulder::Genbank methods
------------------------

   This section lists the public methods that the Boulder::Genbank class
makes available.

new()
          # Network fetch via Entrez, with accession numbers
          $gb=new Boulder::Genbank(-accessor  =>  'Entrez',
                                   -fetch     =>  [qw/M57939 M28274 L36028/]);

          # Same, but shorter and uses -> operator
          $gb = Boulder::Genbank->new qw(M57939 M28274 L36028);

          # Network fetch via Entrez, with a query

          # Network fetch via Entrez, with a query
          $query = 'Homo sapiens[Organism] AND EST[Keyword]';
          $gb=new Boulder::Genbank(-accessor  =>  'Entrez',
                                   -fetch     =>  $query);

          # Local fetch via Yank, with accession numbers
          $gb=new Boulder::Genbank(-accessor  =>  'Yank',
                                   -fetch     =>  [qw/M57939 M28274 L36028/]);

          # Local fetch via File
          $gb=new Boulder::Genbank(-accessor  =>  'File',
                                   -fetch     =>  '/usr/local/genbank/gbpri3.seq');

     The new() method creates a new Boulder::Genbank stream on the
     accessor provided.  The three possible accessors are Entrez, Yank and
     File.  If successful, the method returns the stream object.
     Otherwise it returns undef.

     new() takes the following arguments:

          -accessor	Name of the accessor to use
          -fetch		Parameters to pass to the accessor

     Specify the accessor to use with the *-accessor* argument.  If not
     specified, it defaults to Entrez.

     *-fetch* is an accessor-specific argument.  The possibilities are:

     For Entrez, the *-fetch* argument may point to a scalar, in which
     case it is interpreted as an Entrez query string.  See
     http://www.ncbi.nlm.nih.gov/Entrez/linking.html for a description of
     the query syntax.  Alternatively, *-fetch* may point to an array
     reference, in which case it is interpreted as a list of accession
     numbers to retrieve.  If *-fetch* points to a hash, it is interpreted
     as extended information.  See `"Extended Entrez Parameters"' in this
     node below.

     For Yank, the *-fetch* argument must point to an array reference
     containing the accession numbers to retrieve.

     For File, the *-fetch* argument must point to a string-valued scalar,
     which will be interpreted as the path to the file to read Genbank
     entries from.

     For Entrez (and Entrez only) Boulder::Genbank allows you to use a
     shortcut syntax in which you provde new() with a list of accession
     numbers:

          $gb = new Boulder::Genbank('M57939','M28274','L36028');

newFh()
     This works like new(), but returns a filehandle.  To recover each
     GenBank record read from the filehandle with the <> operator:

          $fh = Boulder::GenBank->newFh('M57939','M28274','L36028');
          while ($record = <$fh>) {
             print $record->asString;
          }

get()
     The get() method is inherited from Boulder::Stream, and simply
     returns the next parsed Genbank Stone, or undef if there is nothing
     more to fetch.  It has the same semantics as the parent class,
     including the ability to restrict access to certain top-level tags.

     The object returned is a Stone/GB_Sequence,
     object, which is a descendent of Stone.

put()
     The put() method is inherited from the parent Boulder::Stream class,
     and will write the passed Stone to standard output in Boulder format.
     This means that it is currently not possible to write a
     Boulder::Genbank object back into Genbank flatfile form.

Extended Entrez Parameters
--------------------------

   The Entrez accessor recognizes extended parameters that allow you the
ability to customize the search.  Instead of passing a query string scalar
or a list of accession numbers as the *-fetch* argument, pass a hash
reference.  The hashref should contain one or more of the following keys:

*-query*
     The Entrez query to process.

*-accession*
     The list of accession numbers to fetch, as an array ref.

*-db*
     The database to search.  This is a single-letter database code
     selected from the following list:

          m  MEDLINE
          p  Protein
          n  Nucleotide
          t  3-D structure
          c  Genome

   As an example, here's how to search for ESTs from Oryza sativa that
have been entered or modified since January 12, 1999.

     my $gb = new Boulder::Genbank( -accessor=>Entrez,
     				 -query=>'Oryza sativa[Organism] AND EST[Keyword] AND 1999/01/12[Modification date]',
                                    -db   => 'n'
                                   });

METHODS DEFINED BY THE GENBANK STONE OBJECT
===========================================

   Each record returned from the Boulder::Genbank stream defines a set of
methods that correspond to features and other fields in the Genbank flat
file record.  See Stone/GB_Sequence, gives the full
details, but they are listed for reference here:

$length = $entry->length
------------------------

   Get the length of the sequence.

$start = $entry->start
----------------------

   Get the start position of the sequence, currently always "1".

$end = $entry->end
------------------

   Get the end position of the sequence, currently always the same as the
length.

@feature_list = $entry->features(-pos=>[50,450],-type=>['CDS','Exon'])
----------------------------------------------------------------------

   features() will search the entry feature list for those features that
meet certain criteria.  The criteria are specified using the *-pos* and/or
*-type* argument names, as shown below.

-pos
     Provide a position or range of positions which the feature must
     overlap.  A single position is specified in this way:

          -pos => 1500;         # feature must overlap postion 1500

     or a range of positions in this way:

          -pos => [1000,1500];  # 1000 to 1500 inclusive

     If no criteria are provided, then features() returns all the features,
     and is equivalent to calling the Features() accessor.

-type, -types
     Filter the list of features by type or a set of types.  Matches are
     case-insensitive, so "exon", "Exon" and "EXON" are all equivalent.
     You may call with a single type as in:

          -type => 'Exon'

     or with a list of types, as in

          -types => ['Exon','CDS']

     The names "-type" and "-types" can be used interchangeably.

$seqObj = $entry->bioSeq;
-------------------------

   Returns a Bio/Seq, object from the Bioperl project.
Dies with an error message unless the Bio::Seq module is installed.

OUTPUT TAGS
===========

   The tags returned by the parsing operation are taken from the NCBI
ASN.1 schema.  For consistency, they are normalized so that the initial
letter is capitalized, and all subsequent letters are lowercase.  This
section contains an abbreviated list of the most useful/common tags.  See
"The NCBI Data Model", by James Ostell and Jonathan Kans in
"Bioinformatics: A Practical Guide to the Analysis of Genes and Proteins"
(Eds. A. Baxevanis and F. Ouellette), pp 121-144 for the full listing.

Top-Level Tags
--------------

   These are tags that appear at the top level of the parsed Genbank entry.

Accession
     The accession number of this entry.  Because of the vagaries of the
     Genbank data model, an entry may have multiple accession numbers
     (e.g. after a merging operation).  Accession may therefore be a
     multi-valued tag.

     Example:

     my $accessionNo = $s->Accession;

Authors
     The list of authors, as they appear on the AUTHORS line of the Genbank
     record.  No attempt is made to parse them into individual authors.

Basecount
     The nucleotide basecount for the entry.  It is presented as a Boulder
     Stone with keys "a", "c", "t" and "g".  Example:

          my $A = $s->Basecount->A;
          my $C = $s->Basecount->C;
          my $G = $s->Basecount->G;
          my $T = $s->Basecount->T;
          print "GC content is ",($G+$C)/($A+$C+$G+$T),"\n";

Blob
     The entire flatfile record as an unparsed chunk of text (a "blob").
     This is a handy way of reassembling the record for human inspection.

Comment
     The COMMENT line from the Genbank record.

Definition
     The DEFINITION line from the Genbank record, unmodified.

Features
     The FEATURES table.  This is a complex stone object with multiple
     subtags.  See the `"The Features Tag"' in this node for details.

Journal
     The JOURNAL line from the Genbank record, unmodified.

Keywords
     The KEYWORDS line from the Genbank record, unmodified.  No attempt is
     made to parse the keywords into separate values.

     Example:

          my $keywords = $s->Keywords

Locus
     The LOCUS line from the Genbank record.  It is not further parsed.

Medline, Nid
     References to other database accession numbers.

Organism
     The taxonomic name of the organism from which this entry was derived.
     This line is taken from the Genbank entry unmodified.  See the NCBI
     data model documentation for an explanation of their taxonomic syntax.

Reference
     The REFERENCE line from the Genbank entry.  There are often multiple
     Reference lines.  Example:

          my @references = $s->Reference;

Sequence
     The DNA or RNA sequence of the entry.  This is presented as a single
     lower-case string, with all base numbers and formatting characters
     removed.

Source
     The entry's SOURCE field; often giving clues on how the sequencing was
     performed.

Title
     The TITLE field from the paper describing this entry, if any.

The Features Tag
----------------

   The Features tag points to a Stone record that contains multiple
subtags.  Each subtag is the name of a feature which points, in turn, to a
Stone that describes the feature's location and other attributes.  The
full list of feature is beyond this document, but the following are the
features that are most often seen:

     Cds		a CDS
     Intron		an intron
     Exon		an exon
     Gene		a gene
     Mrna		an mRNA
     Polya_site	a putative polyadenylation signal
     Repeat_unit	a repetitive region
     Source		More information about the organism and cell
     		type the sequence was derived from
     Satellite	a microsatellite (dinucleotide repeat)

   Each feature will contain one or more of the following subtags:

DB_xref
     A cross-reference to another database in the form
     DB_NAME:accession_number.  See the NCBI Web site for a description of
     these cross references.

Evidence
     The evidence for this feature, either "experimental" or "predicted".

Gene
     If the feature involves a gene, this will be the gene's name (or one
     of its names).  This subtag is often seen in "Gene" and Cds features.

     Example:

          foreach ($s->Features->Cds) {
             my $gene = $_->Gene;
             my $position = $_->Position;
                     Print "Gene $gene ($position)\n";
                  }

Map
     If the feature is mapped, this provides a map position, usually as a
     cytogenetic band.

Note
     A grab-back for various text notes.

Number
     When multiple features of this type occur, this field is used to
     number them.  Ordinarily this field is not needed because
     Boulder::Genbank preserves the order of features.

Organism
     If the feature is Source, this provides the source organism.

Position
     The position of this feature, usually expresed as a range
     (1970..1975).

Product
     The protein product of the feature, if applicable, as a text string.

Translation
     The protein translation of the feature, if applicable.

SEE ALSO
========

   See Boulder, Boulder/Blast,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

   Copyright (c) 1997-2000 Lincoln D. Stein

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

EXAMPLE GENBANK OBJECT
======================

   The following is an excerpt from a moderately complex Genbank Stone.
The Sequence line and several other long lines have been truncated for
readability.

     Authors=Spritz,R.A., Strunk,K., Surowy,C.S.O., Hoch,S., Barton,D.E. and Francke,U.
     Authors=Spritz,R.A., Strunk,K., Surowy,C.S. and Mohrenweiser,H.W.
     Locus=HUMRNP7011   2155 bp    DNA             PRI       03-JUL-1991
     Accession=M57939
     Accession=J04772
     Accession=M57733
     Keywords=ribonucleoprotein antigen.
     Sequence=aagcttttccaggcagtgcgagatagaggagcgcttgagaaggcaggttttgcagcagacggcagtgacagcccag...
     Definition=Human small nuclear ribonucleoprotein (U1-70K) gene, exon 10 and 11.
     Journal=Nucleic Acids Res. 15, 10373-10391 (1987)
     Journal=Genomics 8, 371-379 (1990)
     Nid=g337441
     Medline=88096573
     Medline=91065657
     Features={
       Polya_site={
         Evidence=experimental
         Position=1989
         Gene=U1-70K
       }
       Polya_site={
         Position=1990
         Gene=U1-70K
       }
       Polya_site={
         Evidence=experimental
         Position=1992
         Gene=U1-70K
       }
       Polya_site={
         Evidence=experimental
         Position=1998
         Gene=U1-70K
       }
       Source={
         Organism=Homo sapiens
         Db_xref=taxon:9606
         Position=1..2155
         Map=19q13.3
       }
       Cds={
         Codon_start=1
         Product=ribonucleoprotein antigen
         Db_xref=PID:g337445
         Position=join(M57929:329..475,M57930:183..245,M57930:358..412, ...
         Gene=U1-70K
         Translation=MTQFLPPNLLALFAPRDPIPYLPPLEKLPHEKHHNQPYCGIAPYIREFEDPRDAPPPTR...
       }
       Cds={
         Codon_start=1
         Product=ribonucleoprotein antigen
         Db_xref=PID:g337444
         Evidence=experimental
         Position=join(M57929:329..475,M57930:183..245,M57930:358..412, ...
         Gene=U1-70K
         Translation=MTQFLPPNLLALFAPRDPIPYLPPLEKLPHEKHHNQPYCGIAPYIREFEDPR...
       }
       Polya_signal={
         Position=1970..1975
         Note=putative
         Gene=U1-70K
       }
       Intron={
         Evidence=experimental
         Position=1100..1208
         Gene=U1-70K
       }
       Intron={
         Number=10
         Evidence=experimental
         Position=1100..1181
         Gene=U1-70K
       }
       Intron={
         Number=9
         Evidence=experimental
         Position=order(M57937:702..921,1..1011)
         Note=2.1 kb gap
         Gene=U1-70K
       }
       Intron={
         Position=order(M57935:272..406,M57936:1..284,M57937:1..599, <1..>1208)
         Gene=U1-70K
       }
       Intron={
         Evidence=experimental
         Position=order(M57935:284..406,M57936:1..284,M57937:1..599, <1..>1208)
         Note=first gap-0.14 kb, second gap-0.62 kb
         Gene=U1-70K
       }
       Intron={
         Number=8
         Evidence=experimental
         Position=order(M57935:272..406,M57936:1..284,M57937:1..599, <1..>1181)
         Note=first gap-0.14 kb, second gap-0.62 kb
         Gene=U1-70K
       }
       Exon={
         Number=10
         Evidence=experimental
         Position=1012..1099
         Gene=U1-70K
       }
       Exon={
         Number=11
         Evidence=experimental
         Position=1182..(1989.1998)
         Gene=U1-70K
       }
       Exon={
         Evidence=experimental
         Position=1209..(1989.1998)
         Gene=U1-70K
       }
       Mrna={
         Product=ribonucleoprotein antigen
         Position=join(M57928:358..668,M57929:319..475,M57930:183..245, ...
         Gene=U1-70K
       }
       Mrna={
         Product=ribonucleoprotein antigen
         Citation=[2]
         Evidence=experimental
         Position=join(M57928:358..668,M57929:319..475,M57930:183..245, ...
         Gene=U1-70K
       }
       Gene={
         Position=join(M57928:207..719,M57929:1..562,M57930:1..577, ...
         Gene=U1-70K
       }
     }
     Reference=1  (sites)
     Reference=2  (bases 1 to 2155)
     =

Fetch Medline data records as parsed Boulder Stones
***************************************************

NAME
====

   Boulder::Medline - Fetch Medline data records as parsed Boulder Stones

SYNOPSIS
========

     # parse a file of Medline records
     $ml = new Boulder::Medline(-accessor=>'File',
                                -param => '/data/medline/medline.txt');
     while (my $s = $ml->get) {
       print $s->Identifier;
       print $s->Abstract;
     }

     # parse flatfile  yourself
     open (ML,"/data/medline/medline.txt");
     local $/ = "*RECORD*";
     while (<ML>) {
        my $s = Boulder::Medline->parse($_);
        # etc.
     }

DESCRIPTION
===========

   Boulder::Medline provides retrieval and parsing services for Medline
records

   Boulder::Medline provides retrieval and parsing services for NCBI
Medline records.  It returns Medline entries in Stone,
format, allowing easy access to the various fields and values.
Boulder::Medline is a descendent of Boulder::Stream, and provides a
stream-like interface to a series of Stone objects.

   Access to Medline is provided by one *accessors*, which give access to
local Medline database.  When you create a new Boulder::Medline stream,
you provide the accessors, along with accessor-specific parameters that
control what entries to fetch.  The accessors is:

File
     This provides access to local Medline entries by reading from a flat
     file.  The stream will return a Stone corresponding to each of the
     entries in the file, starting from the top of the file and working
     downward.  The parameter is the path to the local file.

   It is also possible to parse a single Medline entry from a text string
stored in a scalar variable, returning a Stone object.

Boulder::Medline methods
------------------------

   This section lists the public methods that the Boulder::Medline class
makes available.

new()
          # Local fetch via File
          $ml=new Boulder::Medline(-accessor  =>  'File',
                                   -param     =>  '/data/medline/medline.txt');

     The new() method creates a new Boulder::Medline stream on the
     accessor provided.  The only possible accessors is File.  If
     successful, the method returns the stream object.  Otherwise it
     returns undef.

     new() takes the following arguments:

          -accessor	Name of the accessor to use
          -param		Parameters to pass to the accessor

     Specify the accessor to use with the *-accessor* argument.  If not
     specified, it defaults to File.

     *-param* is an accessor-specific argument.  The possibilities is:

     For File, the *-param* argument must point to a string-valued scalar,
     which will be interpreted as the path to the file to read Medline
     entries from.

get()
     The get() method is inherited from Boulder::Stream, and simply
     returns the next parsed Medline Stone, or undef if there is nothing
     more to fetch.  It has the same semantics as the parent class,
     including the ability to restrict access to certain top-level tags.

put()
     The put() method is inherited from the parent Boulder::Stream class,
     and will write the passed Stone to standard output in Boulder format.
     This means that it is currently not possible to write a
     Boulder::Medline object back into Medline flatfile form.

OUTPUT TAGS
===========

   The tags returned by the parsing operation are taken from the MEDLARS
definition file MEDDOC.DOC

Top-Level Tags
--------------

   These are tags that appear at the top level of the parsed Medline entry.

   ABSTRACT ABSTRACT AUTHOR ADDRESS AUTHOR CALL NUMBER CAS REGISTRY/EC
NUMBER CLASS UPDATE DATE COMMENTS COUNTRY DATE OF ENTRY DATE OF PUBLICATION
ENGLISH ABSTRACT INDICATOR ENTRY MONTH GENE SYMBOL ID NUMBER INDEXING
PRIORITY ISSN ISSUE/PART/SUPPLEMENT JOURNAL SUBSET JOURNAL TITLE CODE
LANGUAGE LAST REVISION DATE MACHINE-READABLE IDENTIFIER MeSH HEADING
NO-AUTHOR INDICATOR NOT FOR PUBLICATION NUMBER OF REFERENCES PAGINATION
PERSONAL NAME AS SUBJECT PUBLICATION TYPE RECORD ORIGINATOR SECONDARY
SOURCE ID SPECIAL LIST INDICATOR TITLE TITLE ABBREVIATION
TRANSLITERATED/VERNACULAR  TITLE UNIQUE IDENTIFIER VOLUME ISSUE

Identifier
     The Medline identifier of this entry.  Identifier is a single-value
     tag.

     Example:

     my $identifierNo = $s->Identifier;

Title
     The Medline title for this entry.

     Example:       my $titledef=$s->Title;

SEE ALSO
========

   See Boulder, Boulder/Blast,
Boulder/Genbank,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.  Luca I.G. Toldo <luca.toldo@merck.de>

   Copyright (c) 1997 Lincoln D. Stein Copyright (c) 1999 Luca I.G. Toldo

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

Fetch Omim data records as parsed Boulder Stones
************************************************

NAME
====

   Boulder::Omim - Fetch Omim data records as parsed Boulder Stones

SYNOPSIS
========

     # parse a file of Omim records
     $om = new Boulder::Omim(-accessor=>'File',
                                -param => '/data/omim/omim.txt');
     while (my $s = $om->get) {
       print $s->Identifier;
       print $s->Text;
     }

     # parse flatfile records yourself
     open (OM,"/data/omim/omim.txt");
     local $/ = "*RECORD*";
     while (<OM>) {
        my $s = Boulder::Omim->parse($_);
        # etc.
     }

DESCRIPTION
===========

   Boulder::Omim provides retrieval and parsing services for OMIM records

   Boulder::Omim provides retrieval and parsing services for NCBI Omim
records.  It returns Omim entries in Stone, format, allowing
easy access to the various fields and values.  Boulder::Omim is a
descendent of Boulder::Stream, and provides a stream-like interface to a
series of Stone objects.

   Access to Omim is provided by one *accessors*, which give access to
local Omim database.  When you create a new Boulder::Omim stream, you
provide the accessors, along with accessor-specific parameters that
control what entries to fetch.  The accessors is:

File
     This provides access to local Omim entries by reading from a flat file
     (typically omim.txt file downloadable from NCBI's Ftp site).  The
     stream will return a Stone corresponding to each of the entries in
     the file, starting from the top of the file and working downward.  The
     parameter is the path to the local file.

   It is also possible to parse a single Omim entry from a text string
stored in a scalar variable, returning a Stone object.

Boulder::Omim methods
---------------------

   This section lists the public methods that the *Boulder::Omim* class
makes available.

new()
          # Local fetch via File
          $om=new Boulder::Omim(-accessor  =>  'File',
                                   -param     =>  '/data/omim/omim.txt');

     The new() method creates a new *Boulder::Omim* stream on the accessor
     provided.  The only possible accessors is File.  If successful, the
     method returns the stream object.  Otherwise it returns undef.

     new() takes the following arguments:

          -accessor	Name of the accessor to use
          -param		Parameters to pass to the accessor

     Specify the accessor to use with the *-accessor* argument.  If not
     specified, it defaults to File.

     *-param* is an accessor-specific argument.  The possibilities is:

     For File, the *-param* argument must point to a string-valued scalar,
     which will be interpreted as the path to the file to read Omim
     entries from.

get()
     The get() method is inherited from Boulder::Stream, and simply
     returns the next parsed Omim Stone, or undef if there is nothing more
     to fetch.  It has the same semantics as the parent class, including
     the ability to restrict access to certain top-level tags.

put()
     The put() method is inherited from the parent Boulder::Stream class,
     and will write the passed Stone to standard output in Boulder format.
     This means that it is currently not possible to write a Boulder::Omim
     object back into Omim flatfile form.

OUTPUT TAGS
===========

   The tags returned by the parsing operation are taken from the names
shown in the network Entrez interface to Omim.

Top-Level Tags
--------------

   These are tags that appear at the top level of the parsed Omim entry.

Identifier
     The Omim identifier of this entry.  Identifier is a single-value tag.

     Example:

     my $identifierNo = $s->Identifier;

Title
     The Omim title for this entry.

     Example:       my $titledef=$s->Title;

Text The Text of this Omim entry
     Example:       my $thetext=$s->Text;

Mini The text condensed version, also called "Mini" in Entrez interface
     Example:       my $themini=$s->Mini;

SeeAlso References to other relevant work.
     Example:       my $thereviews=$s->Reviews;

CreationDate This field contains the name of the person who originated the initial entry in OMIM and the date it appeared in the database. The entry may have been subsequently added to, edited, or totally rewritten by others, and their attribution is listed in the CONTRIBUTORS field.
     Example:       my $theCreation=$s->CreationDate;

Contributors This field contains a list, in chronological order, of the persons who have contributed significantly to the content of the MIM entry. The name is followed by "updated", "edited" or "re-created".
     Example:       my @theContributors=$s->Contributors;

History This field contains the edit history of this record, with an identifier and a date in which minor changes had been performed on the record.
     Example:       my @theHistory=$s->History;

References The references cited in the entry. Example:       my @theReferences=$s->References;
ClinicalSynopsis The content of the Clinical Synopsis data field. Example:       my @theClinicalSynopsis=$s->ClinicalSynopsis;
AllelicVariants The Allelic Variants Example:       my @theAllelicVariants=$s->AllelicVariants;
SEE ALSO
========

   See Boulder, Boulder/Blast,
Boulder/Genbank,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.  Luca I.G. Toldo <luca.toldo@merck.de>

   Copyright (c) 1997 Lincoln D. Stein Copyright (c) 1999 Luca I.G. Toldo

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

Simple persistent storage for Stone tag/value objects
*****************************************************

NAME
====

   Boulder::Store - Simple persistent storage for Stone tag/value objects

SYNOPSIS
========

     Boulder:Store;

     my $store=new Boulder::Store('test.db',1);
     my $s = new Stone (Name=>'george',
     	            Age=>23,
     		    Sex=>M,
     		    Address=>{
     			   Street=>'29 Rockland drive',
     			   Town=>'Fort Washington',
     			   ZIP=>'77777'
     			   }
     		       );
     $store->put($s);
     $store->put(new Stone(Name=>'fred',
     		       Age=>30,
     		       Sex=>M,
     		       Address=>{
                                       Street=>'19 Gravel Path',
     				   Town=>'Bedrock',
     				   ZIP=>'12345'},
     		       Phone=>{
     				 Day=>'111-1111',
     				 Eve=>'222-2222'
     				 }
     			     ));
     $store->put(new Stone(Name=>'andrew',
     		       Age=>18,
     		       Sex=>M));

     $store->add_index('Name');

     my $stone = $store->get(0);
     print "name = ",$stone->Name;

DESCRIPTION
===========

   Boulder::Store provides persistent storage for Boulder objects using a
simple DB_File implementation.  To use it, you need to have Berkeley db
installed (also known as libdb), and the Perl DB_File module.  See the
DB_File package for more details on obtaining Berkeley db if you do not
already have it.

   Boulder::Store provides an unsophisticated query mechanism which takes
advantage of indexes that you specify.  Despite its lack of
sophistication, the query system is often very helpful.

CLASS METHODS
=============

$store = Boulder::Store->new("database/path",$writable)
     The new() method creates a new Boulder::Store object and associates
     it with the database file provided in the first parameter (undef is a
     valid pathname, in which case all methods work but the data isn't
     stored).  The second parameter should be a *true* value if you want
     to open the database for writing.  Otherwise it's opened read only.

     Because the underlying storage implementation is not multi-user, only
     one process can have the database for writing at a time.  A
     *fcntl()*-based locking mechanism is used to give a process that has
     the database opened for writing exclusive access to the database.
     This also prevents the database from being opened for reading while
     another process is writing to it (this is a *good* thing).  Multiple
     simultaneous processes can open the database read only.

     Physically the data is stored in a human-readable file with the
     extension ".data".

OBJECT METHODS
==============

$stone = $store->read_record(@taglist)
     The semantics of this call are exactly the same as in
     Boulder::Stream.  Stones are returned in sequential order, starting
     with the first record.  In addition to their built-in tags, each stone
     returned from this call has an additional tag called "record_no".
     This is the zero-based record number of the stone in the database.
     Use the reset() method to begin iterating from the beginning of the
     database.

     If called in an array context, *read_record()* returns a list of all
     stones in the database that contains one or more of the provided tags.

$stone = $store->write_record($stone [,$index])
     This has the same semantics as Boulder::Stream.  A stone is appended
     to the end of the database.  If successful, this call returns the
     record number of the new entry.  By providing an optional second
     parameter, you can control where the stone is entered.  A positive
     numeric index will write the stone into the database at that position.
     A value of -1 will use the Stone's internal record number (if present)
     to determine where to place it.

$stone = $store->get($record_no)
     This is random access to the database.  Provide a record number and
     this call will return the stone stored at that position.

$record_number = $store->put($stone,$record_no)
     This is a random write to the database.  Provide a record number and
     this call stores the stone at the indicated position, replacing
     whatever was there before.

     If no record number is provided, this call will look for the presence
     of a 'record_no' tag in the stone itself and put it back in that
     position.  This allows you to pull a stone out of the database, modify
     it, and then put it back in without worrying about its record number.
     If no record is found in the stone, then the effect is identical to
     write_record().

     The record number of the inserted stone is returned from this call, or
     -1 if an error occurred.

$store->delete($stone),Boulder::Store::delete($record_no)
     These method calls delete a stone from the database.  You can provide
     either the record number or a stone containing the 'record_no' tag.
     Warning: if the database is heavily indexed deletes can be
     time-consuming as it requires the index to be brought back into synch.

$record_count = $store->length()
     This returns the length of the database, in records.

$store->reset()
     This resets the database, nullifying any queries in effect, and
     causing read_record() to begin fetching stones from the first record.

$store->query(%query_array)
     This creates a query on the database used for selecting stones in
     *read_record()*.  The query is an associative array.  Three types of
     keys/value pairs are allowed:

    (1) $index=>$value
          This instructs Boulder::Store to look for stones containing the
          specified tags in which the tag's value (determined by the Stone
          *index()* method) exactly matches the provided value.  Example:

               $db->query('STS.left_primer.length'=>30);

          Only the non-bracketed forms of the index string are allowed
          (this is probably a bug...)

          If the tag path was declared to be an index, then this search
          will be fast.  Otherwise Boulder::Store must iterate over every
          record in the database.

    (2) EVAL=>'expression'
          This instructs Boulder::Store to look for stones in which the
          provided expression evaluates to *true*.  When the expression is
          evaluated, the variable $s will be set to the current record's
          stone.  As a shortcut, you can use "<index.string>" as shorthand
          for "$s->index('index.string')".

    (3) EVAL=>['expression1','expression2','expression3'...]
          This lets you provide a whole bunch of expressions, and is
          exactly equivalent to EVAL=>'(expression1) && (expression2) &&
          (expression3)'.

     You can mix query types in the parameter provided to query().  For
     example, here's how to look up all stones in which the sex is male
     and the age is greater than 30:

          $db->query('sex'=>'M',EVAL=>'<age> > 30');

     When a query is in effect, *read_record()* returns only Stones that
     satisfy the query.  In an array context, *read_record()* returns a
     list of all Stones that satisfy the query.  When no more satisfactory
     Stones are found, *read_record()* returns undef until a new query is
     entered or reset() is called.

$store->add_index(@indices)
     Declare one or more tag paths to be a part of a fast index.
     *read_record()* will take advantage of this record when processing
     queries.  For example:

          $db->add_index('age','sex','person.pets');

     You can add indexes any time you like, when the database is first
     created or later.  There is a trade off:  *write_record()*, put(),
     and other data-modifying calls will become slower as more indexes are
     added.

     The index is stored in an external file with the extension ".index".
     An index file is created even if you haven't indexed any tags.

$store->reindex_all()
     Call this if the index gets screwed up (or lost).  It rebuilds it
     from scratch.

CAVEATS
=======

   Boulder::Store makes heavy use of the flock() call in order to avoid
corruption of DB_File databases when multiple processes try to write
simultaneously.  flock() may not work correctly across NFS mounts,
particularly on Linux machines that are not running the rpc.lockd daemon.
Please confirm that your flock() works across NFS before attempting to use
Boulder::Store.  If the store.t test hangs during testing, this is the
likely culprit.

AUTHOR
======

   Lincoln D. Stein <lstein@cshl.org>, Cold Spring Harbor Laboratory, Cold
Spring Harbor, NY.  This module can be used and distributed on the same
terms as Perl itself.

SEE ALSO
========

   See Boulder, Boulder/Stream,
Stone,

Read and write tag/value data from an input stream
**************************************************

NAME
====

   Boulder::Stream - Read and write tag/value data from an input stream

SYNOPSIS
========

     #!/bin/perl
     # Read a series of People records from STDIN.
     # Add an "Eligible" tag to all those whose
     # Age >= 35 and Friends list includes "Fred"
     use Boulder::Stream;

     my $stream = Boulder::Stream->newFh;

     while ( my $record = <$stream> ) {
        next unless $record->Age >= 35;
        my @friends = $record->Friends;
        next unless grep {$_ eq 'Fred'} @friends;

     $record->insert(Eligible => 'yes');
     print $stream $record;
         }

DESCRIPTION
===========

   Boulder::Stream provides stream-oriented access to Boulder,
IO hierarchical tag/value data.  It can be used in a magic tied
filehandle mode, as shown in the synopsis, or in object-oriented mode.
Using tied filehandles, see Stone, objects are read from input
using the standard <> operator.  Stone objects printed to the tied
filehandle appear on the output stream in Boulder, format.

   By default, data is read from the magic ARGV filehandle (STDIN or a
list of files provided on the command line) and written to STDOUT.  This
can be changed to the filehandles of your choice.

Pass through behavior
---------------------

   When using the object-oriented form of Boulder::Stream, tags which
aren't specifically requested by the get() method are passed through to
output unchanged.  This allows pipes of programs to be constructed easily.
Most programs will want to put the tags back into the boulder stream once
they're finished, potentially adding their own.  Of course some programs
will want to behave differently.  For example, a database query program
will generate but not read a *boulderio* stream, while a report generator
will read but not write the stream.

   This convention allows the following type of pipe to be set up:

     query_database | find_vector | find_dups | \
       | blast_sequence | pick_primer | mail_report

   If all the programs in the pipe follow the conventions, then it will be
possible to interpose other programs, such as a repetitive element finder,
in the middle of the pipe without disturbing other components.

SKELETON BOULDER PROGRAM
========================

   Here is a skeleton example.

     #!/bin/perl
     use Boulder::Stream;

     my $stream = Boulder::Stream->newFh;

     while ( my $record = <$stream> ) {
        next unless $record->Age >= 35;
        my @friends = $record->Friends;
        next unless grep {$_ eq 'Fred'} @friends;

     $record->insert(Eligible => 'yes');
     print $stream $record;
         }

   The code starts by creating a Boulder::Stream object to handle the I/O.
It reads from the stream one record at a time, returning a Stone,
object.  We recover the *Age* and *Friends* tags, and continue
looping unless the Age is greater or equal to 35, and the list of Friends
contains "Fred".  If these criteria match, then we insert a new tag named
Eligible and print the record to the stream.  The output may look like
this:

     Name=Janice
     Age=36
     Eligible=yes
     Friends=Susan
     Friends=Fred
     Friends=Ralph
     =
     Name=Ralph
     Age=42
     Eligible=yes
     Friends=Janice
     Friends=Fred
     =
     Name=Susan
     Age=35
     Eligible=yes
     Friends=Susan
     Friends=Fred
     =

   Note that in this case only records that meet the criteria are echoed
to standard output.  The object-oriented version of the program looks like
this:

     #!/bin/perl
     use Boulder::Stream;

     my $stream = Boulder::Stream->new;

     while ( my $record = $stream->get('Age','Friends') ) {
        next unless $record->Age >= 35;
        my @friends = $record->Friends;
        next unless grep {$_ eq 'Fred'} @friends;

     $record->insert(Eligible => 'yes');
     $stream->put($record);
         }

   The get() method is used to fetch Stones containing one or more of the
indicated tags.  The put() method is used to send the result to standard
output.  The pass-through behavior might produce a set of records like
this one:

     Name=Janice
     Age=36
     Eligible=yes
     Friends=Susan
     Friends=Fred
     Friends=Ralph
     =
     Name=Phillip
     Age=30
     =
     Name=Ralph
     Age=42
     Eligible=yes
     Friends=Janice
     Friends=Fred
     =
     Name=Barbara
     Friends=Agatha
     Friends=Janice
     =
     Name=Susan
     Age=35
     Eligible=yes
     Friends=Susan
     Friends=Fred
     =

   Notice that there are now two records ("Phillip" and "Barbara") that do
not contain the Eligible tag.

Boulder::Stream METHODS
=======================

$stream = Boulder::Stream->new(*IN,*OUT)
----------------------------------------

$stream = Boulder::Stream->new(-in=>*IN,-out=>*OUT)
---------------------------------------------------

   The new() method creates a new Boulder::Stream object.  You can provide
input and output filehandles. If you leave one or both undefined new()
will default to standard input or standard output.  You are free to use
files, pipes, sockets, and other types of file handles.  You may provide
the filehandle arguments as bare words, globs, or glob refs. You are also
free to use the named argument style shown in the second heading.

$fh = Boulder::Stream->newFh(-in=>*IN, -out=>*OUT)
--------------------------------------------------

   Returns a filehandle object tied to a Boulder::Stream object.  Reads on
the filehandle perform a get().  Writes invoke a put().

   To retrieve the underlying Boulder::Stream object, call Perl's built-in
tied() function:

     $stream = tied $fh;

$stone = $stream->get(@taglist)
-------------------------------

@stones = $stream->get(@taglist)
--------------------------------

   Every time get() is called, it will return a new Stone object.  The
Stone will be created from the input stream, using just the tags provided
in the argument list.  Pass no tags to receive whatever tags are present
in the input stream.

   If none of the tags that you specify are in the current boulder record,
you will receive an empty *Stone*.  At the end of the input stream, you
will receive undef.

   If called in an array context, get() returns a list of all stones from
the input stream that contain one or more of the specified tags.

$stone = $stream->read_record(@taglist)
---------------------------------------

   Identical to get(>, but the name is longer.

$stream->put($stone)
--------------------

   Write a *Stone* to the output filehandle.

$stream->write_record($stone)
-----------------------------

   Identical to put(), but the name is longer.

Useful State Variables in a Boulder::Stream
-------------------------------------------

   Every Boulder::Stream has several state variables that you can adjust.
Fix them in this fashion:

     $a = new Boulder::Stream;
     $a->{delim}=':';
     $a->{record_start}='[';
     $a->{record_end}=']';
     $a->{passthru}=undef;

   * delim

     This is the delimiter character between tags and values, "=" by
     default.

   * record_start

     This is the start of nested record character, "{" by default.

   * record_end

     This is the end of nested record character, "}" by default.

   * passthru

     This determines whether unrecognized tags should be passed through
     from the input stream to the output stream.  This is 'true' by
     default.  Set it to undef to override this behavior.

BUGS
====

   Because the delim, record_start and record_end characters in the
Boulder::Stream object are used in optimized (once-compiled) pattern
matching, you cannot change these values once get() has once been called.
To change the defaults, you must create the Boulder::Stream, set the
characters, and only then begin reading from the input stream.  For the
same reason, different Boulder::Stream objects cannot use different
delimiters.

AUTHOR
======

   Lincoln D. Stein <lstein@cshl.org>, Cold Spring Harbor Laboratory, Cold
Spring Harbor, NY.  This module can be used and distributed on the same
terms as Perl itself.

SEE ALSO
========

   See Boulder, Boulder/Blast,
Boulder/Genbank, Boulder/Medline,
see Boulder/Unigene,
Boulder/Omim, `Boulder::SwissProt' in this node

Fetch SwissProt data records as parsed Boulder Stones
*****************************************************

NAME
====

   Boulder::SwissProt - Fetch SwissProt data records as parsed Boulder
Stones

SYNOPSIS
========

     == missing ==

DESCRIPTION
===========

     == missing ==

SEE ALSO
========

   See Boulder, Boulder/Blast,
Boulder/Genbank,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.  Luca I.G. Toldo <luca.toldo@merck.de>

   Copyright (c) 1997 Lincoln D. Stein Copyright (c) 1999 Luca I.G. Toldo

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

Fetch Unigene data records as parsed Boulder Stones
***************************************************

NAME
====

   Boulder::Unigene - Fetch Unigene data records as parsed Boulder Stones

SYNOPSIS
========

     # parse a file of Unigene records
     $ug = new Boulder::Unigene(-accessor=>'File',
                                -param => '/data/unigene/Hs.dat');
     while (my $s = $ug->get) {
       print $s->Identifier;
       print $s->Gene;
     }

     # parse flatfile records yourself
     open (UG,"/data/unigene/Hs.dat");
     local $/ = "*RECORD*";
     while (<UG>) {
        my $s = Boulder::Unigene->parse($_);
        # etc.
     }

DESCRIPTION
===========

   Boulder::Unigene provides retrieval and parsing services for UNIGENE
records

   Boulder::Unigene provides retrieval and parsing services for NCBI
Unigene records.  It returns Unigene entries in Stone,
format, allowing easy access to the various fields and values.
Boulder::Unigene is a descendent of Boulder::Stream, and provides a
stream-like interface to a series of Stone objects.

   Access to Unigene is provided by one *accessors*, which give access to
local Unigene database.  When you create a new Boulder::Unigene stream,
you provide the accessors, along with accessor-specific parameters that
control what entries to fetch.  The accessors is:

File
     This provides access to local Unigene entries by reading from a flat
     file (typically Hs.dat file downloadable from NCBI's Ftp site).  The
     stream will return a Stone corresponding to each of the entries in
     the file, starting from the top of the file and working downward.  The
     parameter is the path to the local file.

   It is also possible to parse a single Unigene entry from a text string
stored in a scalar variable, returning a Stone object.

Boulder::Unigene methods
------------------------

   This section lists the public methods that the Boulder::Unigene class
makes available.

new()
          # Local fetch via File
          $ug=new Boulder::Unigene(-accessor  =>  'File',
                                   -param     =>  '/data/unigene/Hs.dat');

     The new() method creates a new Boulder::Unigene stream on the
     accessor provided.  The only possible accessors is File.  If
     successful, the method returns the stream object.  Otherwise it
     returns undef.

     new() takes the following arguments:

          -accessor	Name of the accessor to use
          -param		Parameters to pass to the accessor

     Specify the accessor to use with the *-accessor* argument.  If not
     specified, it defaults to File.

     *-param* is an accessor-specific argument.  The possibilities is:

     For File, the *-param* argument must point to a string-valued scalar,
     which will be interpreted as the path to the file to read Unigene
     entries from.

get()
     The get() method is inherited from Boulder::Stream, and simply
     returns the next parsed Unigene Stone, or undef if there is nothing
     more to fetch.  It has the same semantics as the parent class,
     including the ability to restrict access to certain top-level tags.

put()
     The put() method is inherited from the parent Boulder::Stream class,
     and will write the passed Stone to standard output in Boulder format.
     This means that it is currently not possible to write a
     Boulder::Unigene object back into Unigene flatfile form.

OUTPUT TAGS
===========

   The tags returned by the parsing operation are taken from the names
shown in the Flat file Hs.dat since no better description of them is
provided yet by the database source producer.

Top-Level Tags
--------------

   These are tags that appear at the top level of the parsed Unigene entry.

Identifier
     The Unigene identifier of this entry.  Identifier is a single-value
     tag.

     Example:

     my $identifierNo = $s->Identifier;

Title
     The Unigene title for this entry.

     Example:       my $titledef=$s->Title;

Gene The Gene associated with   this Unigene entry
     Example:       my $thegene=$s->Gene;

Cytoband The cytological band position of this entry
     Example:       my $thecytoband=$s->Cytoband;

Counts The number of EST in this record
     Example:       my $thecounts=$s->Counts;

LocusLink The id of the LocusLink entry associated with this record
     Example:       my $thelocuslink=$s->LocusLink;

Chromosome This field contains a list, of the chromosomes numbers in which this entry has been linked
     Example:       my @theChromosome=$s->Chromosome;

STS      Multiple records in the form ^STS     ACC=XXXXXX NAME=YYYYYY
---------------------------------------------------------------------

ACC
NAME
TXMAP Multiple records in the form  ^TXMAP  XXXXXXX; MARKER=YYYYY; RHPANEL=ZZZZ
-------------------------------------------------------------------------------

   The TXMAP tag points to a Stone record that contains multiple subtags.
Each subtag is the name of a feature which points, in turn, to a Stone
that describes the feature's location and other attributes.

   Each feature will contain one or more of the following subtags:

MARKER
RHPANEL
PROTSIM Multiple records in the form ^PROTSIM ORG=XXX; PROTID=DBID:YYY; PCT=ZZZ; ALN=QQQQ Where DBID is  	PID for indicate presence of GenPept identifier,  	SP to indicate SWISSPROT identifier, 	PIR to indicate PIR identifier, 	PRF to indicate ???
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

ORG
PROTID
PCT
ALN
SEQUENCE Multiple records in the form ^SEQUENCE ACC=XXX; NID=YYYY; PID = CLONE= END= LID=
-----------------------------------------------------------------------------------------

ACC
NID
PID
CLONE
END
LID
SEE ALSO
========

   See Boulder, Boulder/Blast,
Boulder/Genbank,

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.  Luca I.G. Toldo <luca.toldo@merck.de>

   Copyright (c) 1997 Lincoln D. Stein Copyright (c) 1999 Luca I.G. Toldo

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  See DISCLAIMER.txt for disclaimers
of warranty.

XML format input/output for Boulder streams
*******************************************

NAME
====

   Boulder::XML - XML format input/output for Boulder streams

SYNOPSIS
========

     use Boulder::XML;

     $stream = Boulder::XML->newFh;

     while ($stone = <$stream>) {
          print $stream $stone;
     }

DESCRIPTION
===========

   Boulder::XML generates BoulderIO streams from XML files and/or streams.
It is also able to output Boulder Stones in XML format.  Its semantics
are similar to those of Boulder::Stream, except that there is never any
pass-through behavior.

   Because XML was not designed for streaming, some care must be taken
when reading an XML document into a series of Stones.  Consider this XML
document:

     <?xml version="1.0" standalone="yes"?>

     <Paper>
       <Author>Lincoln Stein</Author>
       <Author>Jean Siao</Author>
       <Date>September 29, 1999</Date>
       <Copyright copyrighted="yes">1999 Lincoln Stein</Copright>
       <Abstract>
           This is the abstract.  It is not anything very fancy,
           but it will do.
       </Abstract>
       <Citation>
            <Author>Fitchberg J</Author>
            <Journal>Journal of Irreproducible Results</Journal>
            <Volume>23</Volume>
            <Year>1998</Volume>
       </Citation>
       <Citation>
            <Author>Clemenson V</Author>
            <Journal>Ecumenica</Journal>
            <Volume>10</Volume>
            <Year>1968</Volume>
       </Citation>
       <Citation>
            <Author>Ruggles M</Author>
            <Journal>Journal of Aesthetic Surgery</Journal>
            <Volume>10</Volume>
            <Year>1999</Volume>
       </Citation>
     </Paper>

   Ordinarily the document will be construed as a single Paper tag
containing subtags Author, Date, Copyright, Abstract, and so on.  However
it might be desirable to fetch out just the citation tags as a series of
Stones.  In this case, you can declare Citation to be the top level tag by
passing the *-tag* argument to new(). Now calling get() will return each
of the three Citation sections in turn.  If no tag is explicitly declared
to be the top level tag, then Boulder::XML will take the first tag it sees
in the document.

   It is possible to stream XML files.  You can either separate them into
separate documents and use the automatic ARGV processing features of the
BoulderIO library, or separate the XML documents using a delimiter string
similar to the delimiters used in MIME multipart documents.  By default,
BoulderIO uses a delimiter of <!-Boulder::XML->.

   *This is not a general XML parsing engine!* Instead, it is a way to
represent BoulderIO tag/value streams in XML format.  The module uses
XML::Parser to parse the XML streams, and therefore any syntactic error in
the stream can cause the XML parser to quit with an error.  Another thing
to be aware of is that there are certain XML constructions that will not
translate into BoulderIO format, specifically free text that contains
embedded tags.  This is OK:

     <Author>Jean Siao</Author>

   but this is not:

     <Author>The <Emphatic>extremely illustrious</Emphatic> Jean Siao</Author>

   In BoulderIO format, tags can contain other tags or text, but cannot
contain a mixture of tags and text.

CONSTRUCTORS
------------

$stream = Boulder::XML->new(*IN,*OUT);
$stream = Boulder::XML->new(-in=>*IN,-out=>*OUT,-tag=>$tag,-delim=>$delim,-strip=>$strip)
     new() creates a new Boulder::XML stream that can be read from or
     written to.  All arguments are optional.

          -in    Filehandle to read from.
                 If a file name is provided, will open the file.
                 Defaults to the magic <> filehandle.

          -out   Filehandle to write to.
                 If a file name is provided, will open the file for writing.
                 Defaults to STDOUT

          -tag   The top-level XML tag to consider as the Stone record.  Defaults
                 to the first tag seen when reading from an XML file, or to
                 Less_Than_Special_SequenceStoneGreater_Than_Special_Sequence when writing to an output stream without
                 previously having read.

          -delim Delimiter to use for delimiting multiple Stone objects in an
                 XML stream.

          -strip If true, automatically strips leading and trailing whitespace
                 from text contained within tags.

$fh = Boulder::XML->newFh(*IN,*OUT);
$fh = Boulder::XML->newFh(-in=>*IN,-out=>*OUT,-tag=>$tag,-delim=>$delim,-strip=>$strip)
     The newFh() constructor creates a tied filehandle that can read and
     write Boulder::XML streams.  Invoking <> on the filehandle will
     perform a get(), returning a Stone object.  Calling print() on the
     filehandle will perform a put(), writing a Stone object to output in
     XML format.

METHODS
-------

$stone = $stream->get()
$stream->put($stone)
$done = $stream->done
     All these methods have the same semantics as the similar methods in
     Boulder/Stream, except that pass-through
     behavior doesn't apply.

AUTHOR
======

   Lincoln D. Stein <lstein@cshl.org>, Cold Spring Harbor Laboratory, Cold
Spring Harbor, NY.  This module can be used and distributed on the same
terms as Perl itself.

SEE ALSO
========

   See Boulder, Boulder/Stream,
Stone,

A bundle to install all Ask's favorite modules
**********************************************

NAME
====

   Bundle::ABH - A bundle to install all Ask's favorite modules

SYNOPSIS
========

     perl -MCPAN -e 'install Bundle::ABH'

CONTENTS
========

   Bundle::CPAN

   Bundle::libnet

   Bundle::LWP

   CGI

   ExtUtils::Embed

   Mail::Send

   Getopt::Long

   DB_File

   Bundle::DBI

   Devel::Peek

   MIME::Base64

   IO::ScalarArray      - For MIME::Tools

   MIME::Tools

   Tie::Handle

   Time::HiRes

   GD

   Storable

   HTML::Parser

   Data::ShowTable

   LWP::Parallel

   Date::Format

   Tie::IxHash

   Devel::Symdump

   Image::Size

   Convert::Translit

   Text::Soundex

   Font::AFM           - Some of my favorite modules are using this

   Pod::Parser         - For cpan-upload and more

   HTML::TreeBuilder

   Net::DNS

   Text::Template

   App::Config         - For cpan-upload

   Bit::Vector         - For MIME::Lite

   MIME::Lite          - So nice and easy to send a MIME thingy

   Set::IntRange

   XML::Parser

   Date::Calc

   Number::Format

   Event

DESCRIPTION
===========

   This bundle defines most of the modules Ask Bjoern Hansen usually
install/upgrade with CPAN.pm.

AUTHOR
======

   Ask Bjoern Hansen <ask@netcetera.dk>

libraries needed for AO servlet engine
**************************************

NAME
====

   Bundle::AO::Base - libraries needed for AO servlet engine

DESCRIPTION
===========

   This bundle specifies the libraries needed for the AO servlet engine.
It won't run without them.

SYNOPSIS
========

     perl -MCPAN -e 'install Bundle::AO::Base'

CONTENTS
========

   Storable

   Apache::Session 1.51

   XML::Parser

   XML::XPath

   File::Spec

libraries needed by standard AO interceptors
********************************************

NAME
====

   Bundle::AO::Standard - libraries needed by standard AO interceptors

DESCRIPTION
===========

   This bundle specifies the libraries needed by the standard AO
interceptors. You should install this stuff if you want AO to work out of
the box. If you are developing new interceptors, this bundle probably
doesn't apply to you.

SYNOPSIS
========

     perl -MCPAN -e 'install Bundle::AO::Standard'

CONTENTS
========

   Apache::Request

   HTML::Mason

   DBI

Install Apache mod_perl and related modules
*******************************************

NAME
====

   Bundle::Apache - Install Apache mod_perl and related modules

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::Apache''

CONTENTS
========

   MIME::Base64       - Used in authentication headers

   Digest::MD5        - Needed to do Digest authentication

   URI 0.10           - There are URIs everywhere

   Net::FTP 2.00      - If you want ftp://-support

   HTML::HeadParser   - To get the correct $res->base

   LWP                - The reason why you need the modules above

   Devel::Symdump - Symbol table browsing with Apache::Status

   Data::Dumper - Used by Apache::PerlSections->dump

   CGI - CGI.pm

   Tie::IxHash - For order in <Perl> sections

   Apache - Perl interface to Apache server API

   Apache::DBI   - Wrapper around DBI->connect to transparently maintain
persistent connections

   Apache::DB - Run the interactive Perl debugger under mod_perl

   Apache::Stage - Management of document staging directories

   Apache::Sandwich - Layered document maker

   Apache::Request - Effective methods for dealing with client request data

DESCRIPTION
===========

   This bundle contains modules used by Apache mod_perl.

   Asking CPAN.pm to install a bundle means to install the bundle itself
along with all the modules contained in the CONTENTS section above.
Modules that are up to date are not installed, of course.

AUTHOR
======

   Doug MacEachern

Install Apache::ASP and related modules
***************************************

NAME
====

   Bundle::Apache::ASP - Install Apache::ASP and related modules

SYNOPSIS
========

     perl -MCPAN -e 'install Bundle::Apache::ASP'

CONTENTS
========

   MLDBM		  - This is used for reading and writing multi-level
hashes on disk

   Data::Dumper	  - Serializes data for MLDBM

   MD5		  - 32 byte hash algorithm for cookie session-id

   CGI		  - Required for file upload, make test, and command line ./cgi/asp
script

   HTML::Clean	  - Compress text/html with Clean config or
$Response->{Clean} set to 1-9

   Net::SMTP	  - Runtime errors can be mailed to the webmaster with
MailErrorTo config

   HTTP::Date	  - Provides mapping between Perl time() and HTTP
dates

   Devel::Symdump	  - Used for StatINC setting, which reloads modules
dynamically

   Apache::DBI	  - Cache database connections per process

   Compress::Zlib    - Gzip compress HTML output on the fly

   Tie::Cache        - XLSTCacheSize, XSLT caching support

   Time::HiRes       - Sub second timing of execution with Debug 3 enabled

   HTML::Parser      - Required for HTML::FillInForm

   HTML::FillInForm  - FormFill functionality which autofills HTML forms
from form data

   Apache::ASP	  - A perl ASP port to Apache

DESCRIPTION
===========

   This bundle contains modules used by Apache::ASP.

AUTHOR
======

   Joshua Chamas

A bundle to install external CPAN modules used by BioPerl
*********************************************************

NAME
====

   Bundle::BioPerl - A bundle to install external CPAN modules used by
BioPerl

SYNOPSIS
========

     Perl one liner using CPAN.pm:

     perl -MCPAN -e 'install Bundle::BioPerl'

   Use of CPAN.pm in interactive mode:

     $> perl -MCPAN -e shell
     cpan> install Bundle::BioPerl
     cpan> quit

   Just like the manual installation of perl modules, the user may need
root access during this process to insure write permission is allowed
within the intstallation directory.

CONTENTS
========

   Bundle::LWP		- recommended, used for network access

   File::Temp		- generally required after bioperl release 0.6.2

   IO::Scalar		- optional, used only in
Bio::Tools::Blast::Run::WebBlast.pm

   IO::String		- recommended, used by Bio::DB:WebDBSeqI

   HTTP::Request::Common   - recommended, used for web access

   HTTP::Status            - recommended, used for web access

   LWP::UserAgent          - recommended, used for web access

   URI::Escape             - recommended, used for web access

   XML::Parser		- recommended for bioperl releases after 0.6.2

   XML::Parser::PerlSAX	- recommended for bioperl releases after 0.6.2

   XML::Writer		- recommended for bioperl releases after 0.6.2

   XML::Node		- recommended for bioperl releases after 0.6.2

DESCRIPTION
===========

   The BioPerl distribution from http://bioperl.org contains code and
modules that may use or require additional 'external' perl modules for
advanced functionality. Many of the external modules are not contained
within the standard Perl distribution.

   These external modules can be obtained from the Comprehensive Perl
Archive Network (CPAN) located at http://www.cpan.org.

   This perl module (Bundle::BioPerl) contains NO functionality or real
code at all. It is essentially a special perl module meant to be used by
the CPAN.pm module to simplify the task of automatically installing
multiple modules in one easy step.

   Essentially users can tell CPAN.pm to 'install Bundle::BioPerl' and
CPAN.pm will download, install and configure all of the modules listed in
the BioPerl Bundle module. See the SYNOPSIS section or do `perldoc CPAN'
to learn about how to use the CPAN.pm module to install bundles.

   NOTE: This process is complicated by the fact that some BioPerl
external modules themselves have their own dependencies and prerequisites.
In particular the XML::Parser module requires the prior installation of
the 'xpat' package which resides outside of CPAN at
http://sourceforge.net/projects/expat/.

   The `install Bundle::BioPerl' process may need to be repeated several
times to complete the full installation of all listed modules.

   NOTE: This Bundle does not install BioPerl :) Just the additional
modules that BioPerl code ocasionally makes use of. You will still need to
get the BioPerl distribution from CPAN or http://bioperl.org and install
it the usual way:

     perl Makefile.PL
     make
     make test
     make install

   CPAN.pm has many features - including the ability to download but not
install the modules listed in the BioPerl bundle.

   `perldoc CPAN' is your friend :)

AUTHOR
======

   Chris Dagdigian <`dag@sonsorol.org'> (Author only of this bundle, not
any the modules it lists)

A bundle of the modules required for Bugzilla.
**********************************************

NAME
====

   Bundle::Bugzilla - A bundle of the modules required for Bugzilla.

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::Bugzilla''

CONTENTS
========

   DBI

   Data::Dumper

   DBD::mysql

   Chart::Base

   Date::Parse

DESCRIPTION
===========

   This bundle installs the prerequisites for Bugzilla.

   After installing this bundle, it is recommended that you run the magic
checksetup.pl script to check that all modules are in place and setup the
tables in the database. Then, you will need to edit the file called
'localconfig' with your settings for bugzilla. After this, log in to your
installation and make yourself an account. Run checksetup.pl again and you
will become the superuser for your bugzilla installation. Still confused?
Read the INSTALL and README for more information.

DBI This module is used to connect to the database that Bugzilla uses  to store its information.
Data::Dumper The Data::Dumper module provides data structure persistence for Perl (similar to Java's serialization).  It comes with later sub-releases of Perl 5.004, but a re-installation just to be sure it's available won't hurt anything. Data::Dumper is used by the MySQL related Perl modules.
DBD::mysql This module is used to connect to the mysql database that Bugzilla uses  to store its information.
Chart::Base Used to create the bug charts in the reporting functions in reports.cgi.
Date::Parse Enables SQL-style search query statements for Bugzilla.
AUTHOR
======

   Zach Lipton, <zach@zachlipton.com>

Everything that Expect.pm needs
*******************************

NAME
====

   Bundle::Expect - Everything that Expect.pm needs

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::Expect''

CONTENTS
========

   Expect

   IO::Stty

   IO::Tty

   IO::Pty

DESCRIPTION
===========

   Everything that Expect.pm needs. What can I say more?

AUTHOR
======

   Roland Giersig <RGiersig@users.sourceforge.net>

A bundle to play with all the other modules on CPAN
***************************************************

NAME
====

   Bundle::CPAN - A bundle to play with all the other modules on CPAN

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::CPAN''

CONTENTS
========

   File::Spec

   MD5

   Compress::Zlib

   Archive::Tar

   Bundle::libnet

   Term::ReadKey

   Term::ReadLine::Perl # sorry, I'm discriminating the ::Gnu module

   CPAN::WAIT

   CPAN

DESCRIPTION
===========

   This bundle includes CPAN.pm as the base module and CPAN::WAIT, a
plugin for the first WAIT based CPAN search engine.

   When CPAN installs this bundle it tries immediately to enable
Term::ReadLine so that you do not need to restart your CPAN session.

   Compress::Zlib needs as a prerequisite the zlib library. Currently
(January 1998) this library is not shipped with the Compress::Zlib
distribution.

   In this bundle Term::ReadLine::Perl is preferred over
Term::ReadLine::Gnu because I expect that it gives less problems on
portability.

   Note that all modules in this Bundle are not strict prerequisites to
get a working CPAN.pm. CPAN.pm can work quite well without the other
modules (except for Net::FTP which is really highly recommended). The
other modules are just goodies that make using CPAN.pm more fun.

AUTHOR
======

   Andreas König

A bundle to install the Cisco::Conf module.
*******************************************

NAME
====

   Bundle::Cisco::Conf - A bundle to install the Cisco::Conf module.

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::Cisco::Conf''

CONTENTS
========

   Data::Dumper

   Net::Cmd

   Net::Telnet

   IO::AtomicFile

DESCRIPTION
===========

   This bundle includes all that's needed to run the Cisco::Conf module.

A bundle to install the DBD::CSV driver
***************************************

NAME
====

   Bundle::DBD::CSV - A bundle to install the DBD::CSV driver

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::DBD::CSV''

CONTENTS
========

   DBI 1.02

   Text::CSV_XS 0.14

   SQL::Statement 0.1006

   DBD::CSV

DESCRIPTION
===========

   This bundle includes all that's needed to access so-called CSV (Comma
Separated Values) files via a pseudo SQL engine (SQL::Statement) and DBI.

A bundle to install the HTML::EP package
****************************************

NAME
====

   Bundle::HTML::EP - A bundle to install the HTML::EP package

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::HTML::EP''

CONTENTS
========

   DBI 1.02

   Data::Dumper

   Storable

   CGI::Cookie

   Bundle::LWP

   Net::SMTP

   Mail::Internet 1.32

   HTML::EP

DESCRIPTION
===========

   This bundle includes all that's needed to run the HTML::EP package with
your WWW server.

A bundle to install the HTML::Mason package
*******************************************

NAME
====

   Bundle::HTML::Mason - A bundle to install the HTML::Mason package

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::HTML::Mason''

CONTENTS
========

   Data::Dumper

   MLDBM

   HTML::Mason

DESCRIPTION
===========

   This bundle includes all that's needed to run the HTML::Mason package.

A bundle of the modules nice to have for Interchange.
*****************************************************

NAME
====

   Bundle::Interchange - A bundle of the modules nice to have for
Interchange.

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::Interchange''

CONTENTS
========

   MD5

   MIME::Base64

   Bundle::LWP

   Term::ReadKey

   Term::ReadLine::Perl

   Business::UPS

   SQL::Statement

   Storable

   DBI

   Safe::Hole

DESCRIPTION
===========

   This bundle installs the prerequisites for Interchange as well as some
modules that are not strictly necessary.

   (Interchange was formerly known as Minivend.)

   After installing this bundle, it is recommended that you quit the
current session and then run Interchange's `makecat' program. That will
give you the benefit of line completion and history.

   The core functions of Interchange *will* run with a stock Perl, but to
use some features of Interchange (like the administrative interface) you
will need these modules.

MD5 This module is used to generate unique cache keys. If you don't have it, then keys will be computed with a checksum that has a very low but not infinitesimal chance of causing a cache conflict.
Bundle::LWP Certain parts of these modules (URI::URL and MIME::Base64) are required for Interchange's internal HTTP server. Also, Business::UPS, for calculating shipping, requires this.
Storable If you have this module session save speed increases by anywhere from 25-60%. Highly recommended for busy systems.
Business::UPS Enables lookup of shipping costs directly from www.ups.com.
SQL::Statement Enables SQL-style search query statements for Interchange.
Safe::Hole This helps Interchange deal with the object-creation restrictions of *Safe.pm*, used to encourage security.
DBI Most people want to use SQL with Interchange, and this is a requirement. You will also need the appropriate DBD module, i.e. DBD::mysql to support *MySQL*.
Term::ReadKey Helps Term::ReadLine::Perl generate completions and editing.
Term::ReadLine::Perl Gives you filename completion and command history in the makecat program. Not used otherwise.
AUTHOR
======

   Mike Heins, <heins@akopia.com>

A bundle to install the IspMailGate email filter.
*************************************************

NAME
====

   Bundle::IspMailGate - A bundle to install the IspMailGate email filter.

SYNOPSIS
========

   `perl -MCPAN -e 'install IspMailGate''

CONTENTS
========

   MD5

   MIME::Base64

   Net::SMTP

   Mail::Internet

   MIME::Tools

   IO::Tee

DESCRIPTION
===========

   This bundle includes all that's needed to run the HTML::EP package with
your WWW server.

A bundle to install all libwww-perl related modules
***************************************************

NAME
====

   Bundle::LWP - A bundle to install all libwww-perl related modules

SYNOPSIS
========

     perl -MCPAN -e 'install Bundle::LWP'

CONTENTS
========

   URI 1.10           - There are URIs everywhere

   Net::FTP 2.00      - If you want ftp://-support

   MIME::Base64       - Used in authentication headers

   Digest::MD5        - Needed to do Digest authentication

   HTML::Tagset       - Needed by HTML::Parser

   HTML::Parser       - Need by HTML::HeadParser

   HTML::HeadParser   - To get the correct $res->base

   LWP                - The reason why you need the modules above

DESCRIPTION
===========

   This bundle defines all reqreq modules for libwww-perl.

AUTHOR
======

   Gisle Aas <gisle@aas.no>

A bundle to install all MP3-related modules
*******************************************

NAME
====

   Bundle::MP3 - A bundle to install all MP3-related modules

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::MP3''

CONTENTS
========

   MP3::Info               - For MP3::Info by Chris Sandor

   Digest::MD5		- Used by MP3::Napster

   MP3::Napster		- For MP3::Napster by Lincoln Stein

   Bundle::Xmms            - For Xmms by Doug MacEachern

DESCRIPTION
===========

   This bundle installs a bunch of modules related to sharing and playing
MP3 files, including MP3::Info by Chris Sandor, MP3::Napster, by Lincoln
Stein, and the Xmms bundle by Doug MacEachern.

AUTHOR
======

   Lincoln Stein <`lstein@cshl.org'>

A bundle to install the IspMailGate
***********************************

NAME
====

   Bundle::Mail::IspMailGate - A bundle to install the IspMailGate

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::Mail::IspMailGate''

CONTENTS
========

   IO::Scalar

   IO::Tee

   Net::SMTP

   Mail::Internet

   Digest::MD5

   MIME::Base64

   MIME::Tools

DESCRIPTION
===========

   This bundle includes all that's needed to install the IspMailGate.
Usage:

     perl -MCPAN -e shell
     install Bundle::Mail::IspMailGate

A nice to have modules for MiniVend
***********************************

NAME
====

   Bundle::Minivend - A nice to have modules for MiniVend

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::Minivend''

CONTENTS
========

   MD5

   MIME::Base64

   Bundle::LWP

   Term::ReadKey

   Term::ReadLine::Perl

   Business::UPS

   SQL::Statement

   Storable

   Safe::Hole

   DBI

DESCRIPTION
===========

   This bundle installs the prerequisites for MiniVend as well as some
modules that are not strictly necessary.

   After installing this bundle, it is recommended that you quit the
current session and then run MiniVend's `makecat' program. That will give
you the benefit of line completion and history.

   None of the bundled modules are really needed for MiniVend, but some
functions require on them and you will be limited without them.

MD5 This module is used to generate unique cache keys. If you don't have it, then keys will be computed with a checksum that has a very low but not infinitesimal chance of causing a cache conflict.
Bundle::LWP Certain parts of these modules (URI::URL and MIME::Base64) are required for MiniVend's internal HTTP server. In addition, Data::Dumper makes the output of session dumps more readable.
Storable If you have this module session save speed increases by anywhere from 25-60%. Highly recommended for busy systems.
Business::UPS Enables lookup of shipping costs directly from www.ups.com.
SQL::Statement Enables SQL-style search query statements for MiniVend.
Term::ReadKey Helps Term::ReadLine::Perl generate completions and editing.
Term::ReadLine::Perl Gives you filename completion and command history in the makecat program. Not used otherwise.
DBI Necessary if you want to use MySQL or some other SQL database.
AUTHOR
======

   Mike Heins, <mike@minivend.com>

A bundle to install Perl drivers for mSQL or MySQL
**************************************************

NAME
====

   Bundle::Msql - A bundle to install Perl drivers for mSQL or MySQL

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::Msql''

CONTENTS
========

   DBI

   Data::ShowTable

   Msql

   DBD::mSQL

DESCRIPTION
===========

   This bundle includes all that's needed to run both DBI drivers and
non-DBI drivers for mSQL or MySQL.

A bundle to install Perl drivers for mSQL or MySQL
**************************************************

NAME
====

   Bundle::Mysql - A bundle to install Perl drivers for mSQL or MySQL

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::Mysql''

CONTENTS
========

   DBI

   Data::ShowTable

   Mysql

   DBD::mysql

DESCRIPTION
===========

   This bundle includes all that's needed to run both DBI drivers and
non-DBI drivers for mSQL or MySQL.

A bundle for Net::LDAP
**********************

NAME
====

   Bundle::Net::LDAP - A bundle for Net::LDAP

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::Net::LDAP''

CONTENTS
========

   Convert::ASN1

   Digest::MD5

   URI

   URI::ldap

   IO::Socket::SSL

   XML::Parser

   Net::LDAP

DESCRIPTION
===========

   This bundle all modules that Net::LDAP depends on.

AUTHOR
======

   Graham Barr

Bundle to install all the pre-requisites for OpenInteract
*********************************************************

NAME
====

   Bundle::OpenInteract - Bundle to install all the pre-requisites for
OpenInteract

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::OpenInteract''

CONTENTS
========

   SPOPS::Configure

   Mail::Sendmail (0.77)

   Template (2.00)

   Pod::Usage (1.12)

   Archive::Tar

   Compress::Zlib (1.08)

   Class::Singleton (1.03)

   HTML::Entities (1.13)

   Text::Sentence

   Date::Format (2.09)

   Date::Calc (4.3)

   Email::Valid (0.12)

   Apache::DBI (0.87)

   Apache::Session (1.50)

   Apache::Request (0.31)

   OpenInteract::Package

DESCRIPTION
===========

   Install all the modules needed for OpenInteract. A few of them have to
do with the package installer, but most are just for normal operation.

MORE INFORMATION
================

   Sourceforge Project Home:

     http://sourceforge.net/projects/openinteract/

   News, package repository and more information:

     http://www.openinteract.org/

AUTHOR
======

   Chris Winters <chris@cwinters.com>

CPAN Bundle for the LWP Parallel User Agent extension
*****************************************************

NAME
====

   Bundle::ParallelUA - CPAN Bundle for the LWP Parallel User Agent
extension

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::ParallelUA''

CONTENTS
========

   ExtUtils::MakeMaker  - should be in perl disribution

   LWP::UserAgent       - Base for Parallel::UserAgent

   LWP::RobotUA         - Base for Parallel::RobotUA

   LWP::Protocol        - Base Protocol implementations

   LWP::Parallel        - Parallel User Agent itself

DESCRIPTION
===========

   This bundle defines all required modules for ParallelUserAgent.

AUTHOR
======

   Marc Langheinrich

A bundle to install PlRPC-Server, Client and prerequisites.
***********************************************************

NAME
====

   Bundle::PlRPC - A bundle to install PlRPC-Server, Client and
prerequisites.

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::PlRPC''

CONTENTS
========

   Storable

   Net::Daemon

   RPC::PlServer

DESCRIPTION
===========

   This bundle includes all that's needed to run PlRPC-Server and Client.

A bundle to install all SNMP::MIB::Compiler related modules
***********************************************************

NAME
====

   Bundle::SNMP::MIB::Compiler - A bundle to install all
SNMP::MIB::Compiler related modules

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::SNMP::MIB::Compiler''

CONTENTS
========

   Data::Dumper

   Data::Compare

DESCRIPTION
===========

   This bundle includes SNMP::MIB::Compiler which is a MIB compiler.

AUTHOR
======

   Fabien Tassin <`fta@oleane.net'>

Bundle to install all the pre-requisites for SPOPS
**************************************************

NAME
====

   Bundle::SPOPS - Bundle to install all the pre-requisites for SPOPS

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::SPOPS''

CONTENTS
========

   Date::Format (2.09)

   Data::Dumper

   Date::Calc (4.3)

   Storable (1.00)

   SPOPS::Configure

DESCRIPTION
===========

   Install the few modules needed for SPOPS. Note that this is the bare
minimum - to actually do something with the module you are probably going
to need at least `DBI' in this node plus one or more of the supported DBD
drivers (like DBD/mysql, `DBD::Sybase' in this node,
`DBD::ASAny' in this node). You can also currently use SPOPS with
`GDBM_File' in this node.

MORE INFORMATION
================

   Information on the web about this module is found with OpenInteract,
even though SPOPS is self-contained and is very useful outside of
OpenInteract.

   Sourceforge Project Home:

     http://sourceforge.net/projects/openinteract/

   News, package repository and more information:

     http://www.openinteract.org/

AUTHORS
=======

   Chris Winters <chris@cwinters.com>

A bundle to install all Search::InvertedIndex related modules
*************************************************************

NAME
====

   Bundle::Search::InvertedIndex - A bundle to install all
Search::InvertedIndex related modules

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::Search::InvertedIndex''

CONTENTS
========

   Digest::MD5             - For Tie::DB_File::SplitHash and
Tie::FileLRUCache

   Class::NamedParms       - Used by most of the system

   Class::ParmList         - Used by most of the system

   Tie::DB_File::SplitHash - Used by Search::InvertedIndex

   Tie::FileLRUCache       - Used by Search::InvertedIndex

   Search::InvertedIndex   - The Search::InvertedIndex module itself

DESCRIPTION
===========

   This bundle includes all the Search::InvertedIndex modules and modules
that it depends on.

AUTHOR
======

   Benjamin Franz <`snowhare@nihongo.org'>

A bundle to install all modules used for Slash
**********************************************

NAME
====

   Bundle::Slash - A bundle to install all modules used for Slash

SYNOPSIS
========

   `perl -MCPAN -e 'install "Bundle::Slash"''

CONTENTS
========

   Bundle::CPAN		-
File::Spec,Digest::MD5,Compress::Zlib,libnet,Archive::Tar,Data::Dumper

   Bundle::LWP		- URI,HTML::Parser,MIME::Base64

   Getopt::Long

   DBI

   DBI::FAQ

   Bundle::DBD::mysql	- Data::ShowTable

   Date::Parse		- TimeDate

   XML::Parser

   XML::RSS

   Date::Manip

   Mail::Sendmail

   Apache::DBI

   Apache::Cookie

   Image::Size

   Template		- Template Toolkit

DESCRIPTION
===========

   mod_perl must be installed by hand, because of the special configuration
required for it.  DBIx::Password is special, and also installed by hand,
but needed.

   If CPAN starts downloading "perl-5.6.0" or somesuch, ctrl-C it, exit
the CPAN shell, and start it again.  The latest CPAN.pm version does not
have this problem, but older ones do, and you may have an older one
installed.

   Note that if you are not using MySQL, then you'll have some problems
with this.  Just let it fail and install your DB library manually.  Also
note that Compress::Zlib and XML::Parser need extra libraries (see INSTALL
for Slash, or the docs for the modules).

   We don't use Bundle::DBI because we don't need the Proxy stuff.  If you
want the Proxy stuff, then install Bundle::DBI yourself.

A bundle to install all Tie::DB_File::SplitHash related modules
***************************************************************

NAME
====

   Bundle::Tie::DB_File::SplitHash - A bundle to install all
Tie::DB_File::SplitHash related modules

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::Tie::DB_File::SplitHash''

CONTENTS
========

   Digest::MD5             - For repeatable 'random numbers'

   Tie::DB_File::SplitHash - The Tie::DB_File::SplitHash module itself

DESCRIPTION
===========

   This bundle includes the Tie::DB_File::SplitHash module and all modules
that it depends on.

AUTHOR
======

   Benjamin Franz <`snowhare@nihongo.org'>

A bundle to install all Tie::FileLRUCache related modules
*********************************************************

NAME
====

   Bundle::Tie::FileLRUCache - A bundle to install all Tie::FileLRUCache
related modules

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::Tie::FileLRUCache''

CONTENTS
========

   Digest::MD5             - For Tie::DB_File::SplitHash and
Tie::FileLRUCache

   Class::NamedParms       - Used by most of the system

   Class::ParmList         - Used by most of the system

   Tie::FileLRUCache       - The Tie::FileLRUCache module itself

DESCRIPTION
===========

   This bundle includes the Tie::FileLRUCache module and all modules that
it depends on.

AUTHOR
======

   Benjamin Franz <`snowhare@nihongo.org'>

CPAN Bundle for Tk and its dependencies
***************************************

NAME
====

   Bundle::Tk - CPAN Bundle for Tk and its dependencies

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::Tk''

CONTENTS
========

   ExtUtils::MakeMaker  -  should be in perl disribution

   Net::NNTP            -  for proto news reader, also pulls in rest of
Net::* which LWP needs

   Mail::Internet       -  for news again

   LWP                  -  for tkweb

   Tk                   -  Tk itself!

DESCRIPTION
===========

AUTHOR
======

   Nick Ing-Simmons

A bundle to install basic WWW::Search modules and prerequisites
***************************************************************

NAME
====

   Bundle::WWW::Search - A bundle to install basic WWW::Search modules and
prerequisites

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::WWW::Search''

CONTENTS
========

   Bundle::LWP		- prerequisite

   File::Spec		- prerequisite

   HTML::Parser            - prerequisite HTML::TreeBuilder       -
prerequisite

   HTTP::Cookies           - prerequisite HTTP::Request           -
prerequisite HTTP::Status            - prerequisite

   LWP::RobotUA            - prerequisite LWP::UserAgent          -
prerequisite

   URI::Escape             - prerequisite

   WWW::Search

DESCRIPTION
===========

   This bundle gathers together all of the prerequisite modules for
WWW::Search, as well as the basic WWW::Search mechanism itself.

AUTHOR
======

   Martin Thurn <`martinthurn@iname.com'> (Author only of this bundle, not
necessarily of the modules it lists)

A bundle to install all WWW::Search modules and backends
********************************************************

NAME
====

   Bundle::WWW::Search::ALL - A bundle to install all WWW::Search modules
and backends

SYNOPSIS
========

   `perl Makefile.PL' make install `perl -MCPAN -e 'install
Bundle::WWW::Search::ALL''

CONTENTS
========

   Bundle::WWW::Search

   WWW::Search::AlltheWeb

   J/JS/JSMYSER/WWW-Search-AltaVista-AdvancedWeb-2.02.tar.gz

   J/JS/JSMYSER/WWW-Search-EuroSeek-1.03.tar.gz

   WWW::Search::Excite

   J/JS/JSMYSER/WWW-Search-Excite-News-2.04.tar.gz

   WWW::Search::Go

   J/JS/JSMYSER/WWW-Search-GoTo-1.07.tar.gz

   J/JS/JSMYSER/WWW-Search-Google-2.21.tar.gz

   WWW::Search::HotBot

   J/JS/JSMYSER/WWW-Search-LookSmart-2.05.tar.gz

   WWW::Search::Lycos

   M/MT/MTHURN/WWW-Search-Magellan-2.09.tar.gz

   J/JS/JSMYSER/WWW-Search-MetaCrawler-2.07.tar.gz

   J/JS/JSMYSER/WWW-Search-News-2.05.tar.gz

   WWW::Search::Nomade

   J/JS/JSMYSER/WWW-Search-NorthernLight.-2.06.tar.gz

   J/JS/JSMYSER/WWW-Search-OpenDirectory-2.02.tar.gz

   WWW::Search::PRWire

   WWW::Search::PubMed

   J/JS/JSMYSER/WWW-Search-Snap-2.06.tar.gz

   WWW::Search::Translator

   J/JS/JSMYSER/WWW-Search-X-Search-1.06.tar.gz

   M/MT/MTHURN/WWW-Search-Yahoo-2.21.tar.gz

   WWW::Search::YahooNews

   J/JS/JSMYSER/WWW-Search-ZDNet-2.02+.tar.gz

DESCRIPTION
===========

   This bundle gathers together all of the modules for WWW::Search,
including all the prerequisites and all the backends.

   If you know of other backends or updated backends, please inform the
author:

AUTHOR
======

   Martin Thurn <`martinthurn@iname.com'> (Author only of this bundle, not
necessarily of the modules it lists)

a collection of modules for processing weather products
*******************************************************

NAME
====

   Bundle::Weather - a collection of modules for processing weather
products

DESCRIPTION
===========

   This bundle contains a collection of modules for processing weather
products (forecasts, observations, etc.).

   The current version only performs the only basic processing of weather
products.  Future versions may include modules for handling and routing
EMWIN (Emergency Managers Weather Information Network) streams. Or even
parsing the information into HTML or XML documents.

SYNOPSIS
========

   Below is a simple program which will fetch the latest state forecast
from the NWS server and print it out. (The default zone and URL will have
to be changed to match your location, of course.)

     require Weather::Product::NWS;

     $zone = shift || 'NYZ079';
     $file = 'ftp://iwin.nws.noaa.gov/data/text/FPUS61/KOKX.TXT';

     $forecast = new Weather::Product::NWS($file);

     print $forecast->text($zone), "\n";

CONTENTS
========

   Weather::WMO

   Weather::Product

   Weather::PIL

   Weather::UGC

   Weather::Product::NWS

AUTHOR
======

   Robert Rothenberg <wlkngowl@unix.asb.com>

A bundle to install all the application Wizard
**********************************************

NAME
====

   Bundle::Wizard - A bundle to install all the application Wizard

SYNOPSIS
========

     perl -MCPAN -e 'install Bundle::Wizard'

CONTENTS
========

   Bundle::HTML::EP

   Data::Dumper

   File::Spec

   Wizard

DESCRIPTION
===========

   This bundle defines all required modules for running the application
wizard.

AUTHOR
======

   Jochen Wiedmann, joe@ispsoft.de

A bundle to install all the LDAP Wizard
***************************************

NAME
====

   Bundle::Wizard::LDAP - A bundle to install all the LDAP Wizard

SYNOPSIS
========

     perl -MCPAN -e 'install Bundle::Wizard::LDAP'

CONTENTS
========

   Bundle::HTML::EP

   Data::Dumper

   File::Spec

   Bundle::Wizard

   Compress::Zlib

   Convert::BER

   Net::LDAP

   Net::Netmask

   IO::AtomicFile

   Wizard::LDAP

DESCRIPTION
===========

   This bundle defines all required modules for running the application
wizard.

AUTHOR
======

   Jochen Wiedmann, joe@ispsoft.de

A bundle to install all XML-related modules
*******************************************

NAME
====

   Bundle::XML - A bundle to install all XML-related modules

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::XML''

CONTENTS
========

   Bundle::LWP		- prerequisite, along with:

   Date::Manip

   Parse::Yapp

   LWP::UserAgent

   Data::Dumper

   Storable

   XML::Parser		- Clark Cooper, Larry Wall

   XML::Encoding		- CLark Cooper

   E/EN/ENNO/XML-DOM-1.25.tar.gz		- Enno Derksen, Clark Cooper

   XML::Parser::PerlSAX		- Ken MacLeod; aso wrote:

   XML::Grove

   XML::Handler::Sample

   XML::ESISParser

   XML::Handler::XMLWriter

   XML::Handler::Subs

   XML::Handler::CanonXMLWriter

   Data::Grove

   XML::SAX2Perl

   XML::Perl2SAX

   XML::PatAct::MatchName

   XML::PatAct::ToObjects

   XML::PatAct::Amsterdam

   XML::PatAct::PatternTempl

   XML::PatAct::ActionTempl

   XML::Catalog		- Eric Bohlman

   XML::DT		- J Joao

   XML::Dumper		- Jonathan Eisenzopf; also wrote:

   XML::RSS

   XML::Registry

   XML::Generator		- Benjamin Holzman

   XML::Node		- Chang Liu

   XML::QL		- Matt Sergeant, Robert Hanson

   XML::Simple		- Grant McLean

   XML::Stream		- Ryan Eatmon

   XML::Template		- Geoffrey R. Hutchison

   XML::Twig		- Michel Rodriguez

   XML::Writer		- David Megginson

   XML::XPath	- Matt Sergeant; also wrote:

   XML::miniXQL

   DBIx::XML_RDB

   XSLT		- Geert Josten, Egon Willighagen

   XML::Handler::YAWriter		- Michael Koehne; also wrote:

   XML::Edifact

   E/EN/ENNO/XML-XQL-0.61.tar.gz 	- Enno Derksen

DESCRIPTION
===========

   This bundle gathers together all of the modules in the XML directory of
CPAN, along with some other XML-related modules, and (I think) all of the
modules on which these depend.

   In this version (0.1), XML::DOM and XML::XQL are installed via
hard-wired links to versions earlier than the current ones, because the
current versions fail to install automatically.  During the install, CPAN
will attempt but fail to install the latest versions of these from
libxml-enno-1.00. Ignore the errors: although this fails, XML::DOM and
XML::XQL are still installed, but at the earlier versions (1.25 and 0.61
respectively).  Other modules dependent on them should still work as well.

   At one stage during the install, you will be prompted to provide the
XML::Edifact installer with some input; the installation will pause until
you do so.

   Left out of this version (because make fails): XML::Filter::Hekeln

   In this version, I have ignored the fact that certain parts of certain
modules require specific versions (5.005 or 5.004 or 5.003) of Perl.
Sorry.

AUTHOR
======

   Colin Muller <`colin@durbanet.co.za'> (Author only of this bundle, not
of the modules it lists)

Bundle for xmms remote control shell
************************************

NAME
====

   Bundle::Xmms - Bundle for xmms remote control shell

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::Xmms''

CONTENTS
========

   Term::ReadKey

   Term::ReadLine::Perl

   Term::ANSIColor

   MPEG::MP3Info

   Xmms

DESCRIPTION
===========

   The modules installed by this bundle will give you full power of the
xmms remote control shell.

AUTHOR
======

   Doug MacEachern

A bundle to install all libnet related modules
**********************************************

NAME
====

   Bundle::libnet - A bundle to install all libnet related modules

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::libnet''

CONTENTS
========

   Data::Dumper		- For Net::Config

   Net::Telnet		- For Net::Telnet by Jay Rogers

   Net::Cmd		- for libbet itself

DESCRIPTION
===========

   This bundle includes all the libnet distribution and the Net-Telnet
distribution by Jay Rogers <`jay@rgrs.com'>, which is a replacement module
for the original Net::Telnet module which was in the libnet distribution.

AUTHOR
======

   Graham Barr <`gbarr@ti.com'>

modules - A bundle to install pRPC-modules and prerequisites
************************************************************

NAME
====

   Bundle::pRPC-modules - A bundle to install pRPC-modules and
prerequisites

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::pRPC-modules''

CONTENTS
========

   Storable

   RPC::pServer

DESCRIPTION
===========

   This bundle includes all that's needed to run pRPC-modules.

Name
====

   Business::CSI - Perl extension for Card Services International

The Example
===========

     use strict;
     use Business::CSI qw/ :simple :mail /;

     my $max_tries = 5;

     add_settings({
        'csi_config'=> '666999',
        'csi_host'  => 'secure.linkpt.net',
        'csi_port'  => '1139',
        'csi_key'   => '/etc/keyfile.pem',
     });

     add_settings({
         'card_number'  => '1234 5678 1234 5678',
         'card_expr_m'  => '07',
         'card_expr_y'  => '07',
         'name_on_card' => 'Some Looser',
         'email_addy'   => 'looser@aol.com',
     });

     add_item("A happy meal", 0.5);  # you don't need to use these.
     add_item("A sad   meal", 0.5);  # but it makes the line items show
                                     # in the admin/customer e-mail

     add_settings({
         'grand_total' => calc_total, # note that calc_total does not account
         'real'        => 0,          # for or affect the ship/sub/tax totals
     });

     my $count  = 0;
     my %result = ();
     {
         %result = simple_transaction;

         if(not $result{connected}) {
             print "$result{error_type} => $result{error}\n";
             die "Your order fail'd $max_tries times ... I give up." if $max_tries <= ++$count;
             redo;
         }
     }

     # at this point, we're successfull

     customer_notification_mail_settings({
         # see the documentation below if you want to use templates.
         'template'   => "filename.txt",
         'extra_text' => qq( This is some extra text.  Do you like reading it? )
         'BCC'        => "sales@our.downtown.com",
     });

     customer_notification_mail(1); # generally you wouldn't use the 1, see below

     foreach my $k (keys %result) {
         print "\$result{$k} = $result{$k}\n";
     }

%results population
===================

Success
-------

     These are all retrieved from a cc_order_get(order,
     OrderField_R_Something ...  function call.  These values are well
     documented in the linkpoint api so if you're wondering what values
     these can take on, consult the aforementioned documentation.

     'approval'  => $result[0], # OrderField_R_Approved
     'ref'       => $result[1], # OrderField_R_Ref
     'code'      => $result[2], # OrderField_R_Code
     'ordernum'  => $result[3], # OrderField_R_Ordernum
     'error'     => $result[4], # OrderField_R_Error
     'time'      => $result[5], # OrderField_R_Time
     'connected' => 1

Failure
-------

     'error_type' => $result[0], # any of process or setrequest
     'error'      => $result[1], # the error returned from CSI
     'connected'  => 0

     The error_type is the stage of the order process, either 'process' or
     'setrequest'.  Again, consult the linkpoint api docs to see what
     values can be returned.

     =head1 Settings

Settings - The available settings
---------------------------------

     csi_config   csi_key      csi_host     csi_port     cust_id
     order_id     name_on_card email_addy   card_number  card_expr_m
     card_expr_y  sub_total    tax_total    ship_total   grand_total  real

Settings - The defaults
-----------------------

     'csi_host'     => 'secure.linkpt.net',
     'csi_port'     => '1139',
     'cust_id'      => 'imcertainihavenoidea',
     'order_id'     => ('order' . '.'. time . '.' . $$),
     'email_addy'   => 'unknown@aol.com',
     'real'         => 0,

     'ship_total'   => 0,
     'sub_total'    => 0,
     'tax_total'    => 0,

Settings - Extra Info
---------------------

     Unless otherwise listed, they all default to undef.
     Note that 'csi_config' and 'csi_key' are really really needed.
     'csi_config' is your store number (or whatever they call it now).
     'csi_key' is your keyfile.pem.

     Another important setting is 'real'.  'real' should be set to
     0 while you're practicing -- not $real, and 1 when you're ready
     to do it for real. ;)

Email settings
==============

     Note that in order ot use the Email functions, you must put a ':mail' in
     your use line -- as seen in the example.

customer_notification_mail;
---------------------------

     This is the function that actually sends a mail to the customer.
     If you want it to use the localhost mail gateway (sendmail?), then
     call it like it was called in the example above.

     If (for some reason) you wish to use the customers own mail gateway,
     as discovered through the MX records for the domain, call the function
     with a 1 as the argument:

     customer_notification_mail(1);

template => "filename.txt"
--------------------------

     If this funciton is used, the customer_notification_mail function will
     use the named template to do the notification.  SUMMARY and ITEMIZED_LIST
     should appear on a line by themselves somewhere in the template.  They
     get replaced appropriately.

     Additionally, the word EXTRA_TEXT will be replaced by the extra_text
     setting.  If EXTRA_TEXT is not inthe template, then the extra_text setting is
     rendered useless.  Similarly, the EXTRA_TEXT will get replaced with nothing
     if you dont' set the extra_text field.

from => "someone", from => "someone@something.tld"
--------------------------------------------------

     Use this to set the email address the mail comes from (postmaster by
     default).  Business::CSI will attempt to appened a logical fqdn if
     it can't find an [@] in the address.

from_full => "Some Dude Department"
-----------------------------------

     With this you can set the Full Name for the from: header.
     This is reccomended ... for asthetic reasons.

subject => "Your Order with Some Damn Co."
------------------------------------------

     The subject line (if not specified) will be:
     'Subject: Your order (#X)'
     Where X will get replaced with the order # you specified.

BCC => "someoneelse@at.our.co"
------------------------------

     Our sales department keeps track of all our orders in a spreadsheet.
     I think that's kinda dumb, and offered to do a database thing.
     *shrug*  They'd rather get a copy of this.  That's what this is
     for.

To do
=====

     1. Billing Shipping info
     2. Credit card number sanity checks using Business::CreditCard
     3. ... I am accepting requests especially if you wanna throw me
         code snippits. ;)
     4. More documentation.  As people ask me questions, I make more and more
        less not clear. ;)

Known Bugs
==========

     None... they're fixed

Unknown Bugs
============

     None AFAIK.

Credits
=======

     "David Deppner" <dave@psyber.com>:

     1.  The double/float bugfix mentioned in the Changes log.
     2.  Insisted on a README.

Author
======

     Jettero Heller <jettero@voltar.org>

See Also
========

   perl(1).

Perl wrapper for Cascow, a lib for making Dankort payment.
**********************************************************

NAME
====

   Business::Cashcow - Perl wrapper for Cascow, a lib for making Dankort
payment.

SYNOPSIS
========

   A module for clearing Internet payment transactions with the Danish PBS
through a SSL connection, provided by the excellent OpenSSL library.
CashCow will clear the following kinds of transactions between a customer
and PBS:

     Dankort
     Visa/Dankort
     Eurocard
     MasterCard
     Visa

   This module is a perl wrapper for the c lib cashcow, se
http://www.cashcow.dk/ for more info.

DESCRIPTION
===========

   Business::Cashcow::InitCashcow("passphrase", "rc4key");

   Call this function to load the /etc/cashcow.ini file and setup state
regarding keys and certificates. Returns true if private key was
successfully unlocked using the supplied passphase, false otherwise.

     my $transaction = {card_number => '76009244561',
                        card_expirymonth => 7,
                        card_expiryyear => 8,
                        transaction_reference => '99910326',
                        transaction_amount => 7.25,
                        transaction_currency => 208,
                        merchant_name => 'Enterprise Advertising A/S',
                        merchant_address => 'Aarhusgade 108E, 3.',
                        merchant_city => 'Koebenhavn',
                        merchant_zip => '2100 OE',
                        merchant_region => '',
                        merchant_country => 'DNK',
                        merchant_poscode => 0,    # POS_ECOMMERCE_SSL
                        merchant_number => '2133334',
                        merchant_terminalid => 'INET01',
                        result_action => 0,
                        result_approval => '',
                        result_ticket => '',
                        cashcow => ''
                       };

     Business::Cashcow::RequestAuth($transaction, $ticket, "secret");

   This function make the initial communucation to verify the card etc. It
returns on of the folowing status messages:

     'action_approved',
     'action_decline',
     'action_partly_approved',
     'action_amount_error',
     'action_invalid_transaction',
     'action_no_reply',
     'action_system_error',
     'action_expired_card',
     'action_retransmit',
     'action_internal_error'

   and sets $ticket to a ticket to be used as reference of the transaction
in Cashcow::RequestCapture. It shoud be called as a response of an order.

     Business::Cashcow::RequestCapture($ticket,"secret",7.25);

   This function compleetes the payment. It should be called when the
merchant has fullfilled the order.

BUGS
====

   The software is an alpha, so don't blame me, but bug (and success)
reports are also welcome.

AUTHOR
======

   Gustav Kristoffer Ek <stoffer@netcetera.dk>

   Copyright 1999 Gustav Kristoffer Ek. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Win32 API Extension for FedEx ShipAPI
*************************************

NAME
====

   Fedex - Win32 API Extension for FedEx ShipAPI

SYNOPSIS
========

     use Fedex;

DESCRIPTION
===========

   Stub documentation for Fedex, created by h2xs. It looks like the author
of the extension was negligent enough to leave the stub unedited.  Yes he
was.

EXPORT
------

   None by default.

AUTHOR
======

   Alex Schmelkin, alex@davanita.com

SEE ALSO
========

   perl(1).

Constants used by Business::FedEx::ShipRequest;
***********************************************

NAME
====

   Business::FedEx::Constants - Constants used by
Business::FedEx::ShipRequest;

SYNOPSIS   Constants are used in the creation of a ShipRequest Object, and in a ShipRequest get_data() method.
==============================================================================================================

API
===

DESCRIPTION
===========

   Two parts to this documentation:

   1) SET FEDEX VALUES  - used by ShipRequest->new() (for ship and
rate...not track)

   2) GET FEDEX VALUES  - used by ShipRequest->get_data()

SET FEDEX VALUES:
-----------------

     transaction_id=>'32826482',                #--/-REQUIRED - Any number you want - used for error tracking
     	      account_number => '',                      #--/-REQUIRED - Your 9 digit FedEx Account number
     	      weight => '',                              #--/-REQUIRED
     	      weight_units =>'LBS',
     	      service => '1',
     	      special_services => '',
     	      ship_date => '',
     	      declared_value => '',
     	      cod_flag => 'N',
     	      cod_amount => '',
     	      cod_cashiers_check => '',
     	      special_services => 'NNNNNNNNNNNNN',
     	      dry_ice_weight => '',
     	      meter_number => '',                        #--/-REQUIRED - Your 7 digit FedEx meter number
     	      gif_label => '400',
     	      tracking_num => '',

     shipper_name => '',                        #--/-REQUIRED -
     shipper_company => '',                      #--/-REQUIRED -
     shipper_address1 => '',                    #--/-REQUIRED -
     shipper_address2 => '',
     shipper_city => '',                        #--/-REQUIRED -
     shipper_zip_code => '',                    #--/-REQUIRED -
     shipper_state => '',                       #--/-REQUIRED -
     shipper_phone => '',                       #--/-REQUIRED -

     dest_company => '',                        #--/-REQUIRED -
     dest_address1 => '',                       #--/-REQUIRED -
     dest_address2 => '',
     dest_city => '',                           #--/-REQUIRED -
     dest_zip_code => '',                       #--/-REQUIRED -
     dest_state => '',                          #--/-REQUIRED -
     dest_phone => '',                           #--/-REQUIRED -
     recipient_department => '',
     payor_account_number => '',                #--/-REQUIRED - 10 digit fedex account # of payor
     payment_code => '1',                       #--/-REQUIRED -
     reference_info => '',
     signature_release_flag => 'N',
     #
     hal_station_address1 => '',
     hal_city => '',
     hal_state => '',
     hal_zip_code => '',
     pkg_height => '',
     pkg_width => '',
     pkg_length => '',
     dim_units => '',
     future_day_ship => '',
     dest_country_code => 'US',
     ult_dest_country_code => 'US',
     shipper_country_code => 'US',
     #INTERNATIONAL SHIPPING ONLY-------------------------------------------------
     duties_pay_type => '',
     duties_account_num => '',
     pkg_description => '',
     manufacture_country_code => '',
     currency_type => '',
     carriage_value => '',
     unit_weight1 => '',
     unit_value1 => '',
     quantity1 => '',
     unit_measure1 => '',
     #local_ship_time => '',
     customs_value => '',
     ein_num => '',
     commercial_invoice_flag => '',
     hal_phone => '',

GET FEDEX VALUES:
-----------------

   You can get all the above values as well as the values listed below
through Business::FedEx::ShipRequest->get_data('constant_name'):

     'transaction_type';
     'transaction_id';
     'error_code';
     'error_mesg';
     'weight';
     'cod_tracking_num';
     'tracking_num';
     'ursa_code';
     'service_area';
     'base_charge';
     'total_surcharge';
     'total_discount';
     'net_charge';
     'billed_weight';
     'astra_bar_code';
     'gif_label';
     'delivery_day';
     'routing_location_id';
     'cod_label';
     'dim_weight_used';
     'tracking_form_id';
     'transaction_term';
     'tracking_status';
     'package_type';
     'service_type';
     'delivery_description';
     'signed_for';
     'delivery_time';
     'dispatch_exception';
     'cartage_agent';
     'status_exception';
     'cod_ret_track_num';
     'cod_flag';
     'num_tracking_activities';
     'pkg_type';
     'delivery_date';
     'track_1';
     'track_2';
     'track_3';
     'track_4';
     'track_5';
     'track_6';
     'track_7';
     'track_8';
     'track_9';
     'track_10';
     'track_11';
     'track_12';
     'track_13';
     'track_14';
     'track_15';

   Refer to the FedEx ShipAPI documentation.

EXPORT
------

   None by default.

AUTHOR
======

   Patrick Tully, ptully@avatartech.com

SEE ALSO
========

   Business::FedEx

   Business::FedEx::ShipRequest

   Business::FedEx::ShipAPI

Interface to the FedEx API libraries (Win32 ONLY!!)
***************************************************

NAME
====

   FedEx::ShipAPI - Interface to the FedEx API libraries (Win32 ONLY!!)

SYNOPSIS
========

     use FedEx::ShipAPI;
     my $s = new FedEx::ShipAPI(host=>'127.0.0.1', port=>6970);
     $s->connect() or die $FedEx::ShipAPI::errstr;
     $s->transaction(XXXX);
     $s->disconnect();

API
===

     int WEBAPIConnect(char *system, int port, char *userId, char *passWord);
     int WEBAPITransaction(char *sBuf, int sBufLen, char *rBuf, int rBufLen, int *actualRecvBufLen);
     int WEBAPIDisconnect(void);
     int WEBAPIReceive(char *rBuf, int rBufLen, int *actualRecvBufLen, int *rBufType);
     int WEBAPISend(char *sBuf, int sBufLen, int sBufType);
     int WEBAPISetLogFile(char *fileName);
     void WEBAPISetLogMode(int mode);
     int WEBAPISetTraceFile(char *fileName);
     void WEBAPISetTraceMode(int mode);
     void WEBAPISetReadTimeout(int duration);

DESCRIPTION
===========

   Use this to bounce transactions off the FedEx gateway shipping server

EXPORT
------

   None by default.

AUTHOR
======

   Alex Schmelkin, alex@davanita.com

SEE ALSO
========

   Business::FedEx Business::FedEx::Constants Business::FedEx::ShipRequest

Shipping/Tracking Interface to FedEx
************************************

NAME
====

   Business::FedEx::ShipRequest - Shipping/Tracking Interface to FedEx

SYNOPSIS
========

   ShipRequest gives you the ability to track, rate, and ship
international and domestic packages via FedEx.

API
===

DESCRIPTION
===========

   Two ways to use ShipRequest.  If you are on a Win32 system, you can use
ShipRequest directly (w/o using the proxy interface).  However, If you
plan on using ShipRequest on any other platform, you MUST use the proxy
interface.  Read 'USE PROXY' below for instructions.

CREATE A SHIPPING OBJECT:
-------------------------

   Refer to Business::FedEx::Constants or the FedEx ShipAPI documentation
for the required fields.

     use Business::FedEx::ShipRequest;
     $s = Business::FedEx::ShipRequest->new(constant_name=>'value',constant_name2=>'value',etc...);

SHIP A PACKAGE:
---------------

     $s->ship('username','secret','localhost','domestic');
     $s->ship('username','secret','localhost','international');

RATE A PACKAGE:
---------------

     $s->rate('username','secret','localhost','domestic');
     $s->rate('username','secret','localhost','international');

TRACK A PACKAGE:
----------------

     $s->track('username','secret','localhost','123456789098');

USE PROXY:
----------

   In order to use fedex.pl (proxy interface), you must install
Business::FedEx on a Win32 web server and put the fedex.pl script in
Win32's cgi-bin.  You can then make a ShipRequest from any box just by
including the url in the method call (instead of 'localhost').

     $s->ship('username','secret','http://www.hostname.com/cgi-bin/fedex.pl','domestic');

GET REPLY INFO:
---------------

   Refer to Business::FedEx::Constants for constant_name information or
refer to the FedEx ShipAPI documentation.

   $data = $s->get_data('constant_name');

EXPORT
------

   None by default.

AUTHOR
======

   Patrick Tully, ptully@avatartech.com

SEE ALSO
========

   Business::FedEx

   Business::FedEx::Constants

   Business::FedEx::ShipAPI

work with International Standard Book Numbers
*********************************************

NAME
====

   Business::ISBN - work with International Standard Book Numbers

SYNOPSIS
========

     use Business::ISBN;

     $isbn_object = new Business::ISBN('1565922573');
     $isbn_object = new Business::ISBN('1-56592-257-3');

     #print the ISBN with hyphens at positions specified
     #by constructor
     print $isbn_object->as_string;

     #print the ISBN with hyphens at specified positions.
     #this not does affect the default positions
     print $isbn_object->as_string([]);

     #print the country code or publisher code
     print $isbn->country_code;
     print $isbn->publisher_code;

     #check to see if the ISBN is valid
     $isbn_object->is_valid;

     #fix the ISBN checksum.  BEWARE:  the error might not be
     #in the checksum!
     $isbn_object->fix_checksum;

     #EXPORTABLE FUNCTIONS

     use Business::ISBN qw( is_valid_checksum isbn_to_ean ean_to_isbn );

     #verify the checksum
     if( is_valid_checksum('0123456789') ) { ... }

     #convert to EAN (European Article Number)
     $ean = isbn_to_ean('1565921496');

     #convert from EAN (European Article Number)
     $isbn = ean_to_isbn('9781565921498');

DESCRIPTION
===========

new($isbn)
----------

   The constructor accepts a scalar representing the ISBN.

   The string representing the ISBN may contain characters other than
[0-9xX], although these will be removed in the internal representation.
The resulting string must look like an ISBN - the first nine characters
must be digits and the tenth character must be a digit, 'x', or 'X'.

   The constructor attempts to determine the country code and the
publisher code.  If these data cannot be determined, the constructor
returns an error number:

     -3 Could not determine publisher code
     -2 Could not determine country code
     -1 ISBN is not valid

   The string passed as the ISBN need not be a valid ISBN as long as it
superficially looks like one.  This allows one to use the `fix_checksum()'
method.  Despite the disclaimer in the discussion of that method, the
author has found it extremely useful.  One should check the validity of
the ISBN with `is_valid()' rather than relying on the return value of the
constructor.  If all one wants to do is check the validity of an ISBN, one
can skip the object-oriented interface and use the c<is_valid_checksum()>
function which is exportable on demand.

   If the constructor decides it can't create an object, it returns undef.
It may do this if the string passed as the ISBN can't be munged to the
internal format.

$obj->publisher_code
--------------------

   Returns the publisher code.

$obj->country_code
------------------

   Returns the country code.

$obj->hyphen_positions
----------------------

   Returns the list of hyphen positions as determined from the country and
publisher codes.  the as_string method provides a way to temporarily
override these positions and to even forego them altogether.

$obj->as_string(),  $obj->as_string([])
---------------------------------------

   Return the ISBN as a string.  This function takes an optional anonymous
array (or array reference) that specifies the placement of hyphens in the
string.  An empty list produces a string with no hyphens.

   The positions specified in the passed anonymous array are only used for
one method use and do not replace the values specified by the constructor.

   Positions less than 1 and greater than 9 are silently ignored.

   A terminating 'x' is changed to 'X'.

$obj->is_valid()
----------------

   Returns 1 if the checksum is valid and the country and publisher codes
are defined.

   Returns -1 if the ISBN does not pass the checksum test.  The
constructor accepts invalid ISBN's so that they might be fixed with
`fix_checksum'.

   Returns -2 if a country code could not be determined (relies on a valid
checksum).

   Returns -3 if a publisher code could not be determined (relies on a
valid checksum and country code).

$obj->fix_checksum()
--------------------

   Replace the tenth character with the checksum the corresponds to the
previous nine digits.  This does not guarantee that the ISBN corresponds
to the product one thinks it does, or that the ISBN corresponds to any
product at all.  It only produces a string that passes the checksum
routine.  If the ISBN passed to the constructor was invalid, the error
might have been in any of the other nine positions.

$obj->as_ean()
--------------

   Converts the ISBN to the equivalent EAN (European Article Number).  No
pricing extension is added.  Returns the EAN as a string.  This method can
also be used as an exportable function since it checks its argument list
to determine what to do.

EXPORTABLE FUNCTIONS
====================

   Some functions can be used without the object interface.  These do not
use object technology behind the scenes.

is_valid_checksum('1565921496')
-------------------------------

   Takes the ISBN string and runs it through the checksum comparison
routine.  Returns 1 if the ISBN is valid, 0 otherwise.

isbn_to_ean('1565921496')
-------------------------

   Takes the ISBN string and converts it to the equivalent EAN string.
This function checks for a valid ISBN and will return undef for invalid
ISBNs, otherwise it returns the EAN as a string.  Uses as_ean internally,
which checks its arguments to determine what to do.

ean_to_isbn('9781565921498')
----------------------------

   Takes the EAN string and converts it to the equivalent ISBN string.
This function checks for a valid ISBN and will return undef for invalid
ISBNs, otherwise it returns the EAN as a string.  Uses as_ean internally,
which checks its arguments to determine what to do.

AUTHOR
======

   brian d foy <brian@smithrenaud.com>

   Copyright 2000, Smith Renaud, Inc.

   The coding of this module was supported by Smith Renaud, Inc.
<URL:http://www.smithrenaud.com>.  This module is released under the terms
of the Perl Artistic License.

   Country code and publisher code graciously provided by Steve Fisher
<stevef@teleord.co.uk> of Whitaker (the UK ISBN folks and the major
bibliographic data provider in the UK).  "Whitaker - helping to link
authors to readers worldwide"

   Thanks to Julie Koo of Kaya Publishing <URL:http://www.kaya.com> for
useful discussions.

   Thanks to Mark W. Eichin <eichin@thok.org> for suggestions and
discussions on EAN support.  =cut

Perl extension for International Standard Serial Numbers
********************************************************

NAME
====

   Business::ISSN - Perl extension for International Standard Serial
Numbers

SYNOPSIS
========

     use Business::ISSN;
     $issn_object = new Business::ISSN('1456-5935');
     $issn_object = new Business::ISSN('14565935');

     # print the ISSN with hyphens
     print $issn_object->as_string;

     # check to see if the ISSN is valid
     $issn_object->is_valid;

     #fix the ISSN checksum.  BEWARE:  the error might not be
     #in the checksum!
     $issn_object->fix_checksum;

     #EXPORTABLE FUNCTIONS

     use Business::ISSN qw( is_valid_checksum );

     #verify the checksum
     if( is_valid_checksum('01234567') ) { ... }

DESCRIPTION
===========

new($issn)
----------

   The constructor accepts a scalar representing the ISSN.

   The string representing the ISSN may contain characters other than
[0-9xX], although these will be removed in the internal representation.
The resulting string must look like an ISSN - the first seven characters
must be digits and the eighth character must be a digit, 'x', or 'X'.

   The string passed as the ISSN need not be a valid ISSN as long as it
superficially looks like one.  This allows one to use the `fix_checksum()'
method.

   One should check the validity of the ISSN with `is_valid()' rather than
relying on the return value of the constructor.

   If all one wants to do is check the validity of an ISSN, one can skip
the object-oriented  interface and use the c<is_valid_checksum()> function
which is exportable on demand.

   If the constructor decides it can't create an object, it returns undef.
It may do this if the string passed as the ISSN can't be munged to the
internal format.

$obj->as_string()
-----------------

   Return the ISSN as a string.

   A terminating 'x' is changed to 'X'.

$obj->is_valid()
----------------

   Returns 1 if the checksum is valid.

   Returns 0 if the ISSN does not pass the checksum test.  The constructor
accepts invalid ISSN's so that they might be fixed with `fix_checksum'.

$obj->fix_checksum()
--------------------

   Replace the eighth character with the checksum the corresponds to the
previous seven digits.  This does not guarantee that the ISSN corresponds
to the product one thinks it does, or that the ISSN corresponds to any
product at all.  It only produces a string that passes the checksum
routine.  If the ISSN passed to the constructor was invalid, the error
might have been in any of the other nine positions.

EXPORTABLE FUNCTIONS
====================

   Some functions can be used without the object interface.  These do not
use object technology behind the scenes.

is_valid_checksum('01234567')
-----------------------------

   Takes the ISSN string and runs it through the checksum comparison
routine.  Returns 1 if the ISSN is valid, 0 otherwise.

AUTHOR
======

   Sami Poikonen <sp@iki.fi>

   Copyright 1999, Sami Poikonen.

   This module is released under the terms of the Perl Artistic License.

   This module is a derived work from brian d foy's Business::ISBN.

SEE ALSO
========

   Business::ISBN and its documentation.

Perl extension for online payment processing
********************************************

NAME
====

   Business::OnlinePayment - Perl extension for online payment processing

SYNOPSIS
========

     use Business::OnlinePayment;

     my $transaction = new Business::OnlinePayment($processor, %processor_info);
     $transaction->content(
                           type       => 'Visa',
                           amount     => '49.95',
                           cardnumber => '1234123412341238',
                           expiration => '0100',
                           name       => 'John Q Doe',
                          );
     $transaction->submit();

     if($transaction->is_success()) {
       print "Card processed successfully: ".$transaction->authorization()."\n";
     } else {
       print "Card was rejected: ".$transaction->error_message()."\n";
     }

DESCRIPTION
===========

   Business::OnlinePayment is a generic module for processing payments
through online credit card processors, electronic cash systems, etc.

METHODS AND FUNCTIONS
=====================

new($processor, %processor_options);
------------------------------------

   Create a new Business::OnlinePayment object, $processor is required,
and defines the online processor to use.  If necessary, processor options
can be specified, currently supported options are 'Server', 'Port', and
'Path', which specify how to find the online processor
(https://server:port/path), but individual processor modules should supply
reasonable defaults for this information, override the defaults only if
absolutely necessary (especially path), as the processor module was
probably written with a specific target script in mind.

content(%content);
------------------

   The information necessary for the transaction, this tends to vary a
little depending on the processor, so we have chosen to use a system which
defines specific fields in the frontend which get mapped to the correct
fields in the backend.  The currently defined fields are:

   * type

     Transaction type, supported types are: Visa, MasterCard, American
     Express, Discover, Check (not all processors support all these
     transaction types).

   * login

     Your login name to use for authentication to the online processor.

   * password

     Your password to use for authentication to the online processor.

   * action

     What to do with the transaction (currently available are: Normal
     Authorization, Authorization Only, Credit, Post Authorization)

   * description

     A description of the transaction (used by some processors to send
     information to the client, normally not a required field).

   * amount

     The amount of the transaction, most processors dont want dollar signs
     and the like, just a floating point number.

   * invoice_number

     An invoice number, for your use and not normally required, many
     processors require this field to be a numeric only field.

   * customer_id

     A customer identifier, again not normally required.

   * name

     The customers name, your processor may not require this.

   * address

     The customers address (your processor may not require this unless you
     are requiring AVS Verification).

   * city

     The customers city (your processor may not require this unless you
     are requiring AVS Verification).

   * state

     The customers state (your processor may not require this unless you
     are requiring AVS Verification).

   * zip

     The customers zip code (your processor may not require this unless
     you are requiring AVS Verification).

   * country

     Customer's country.

   * phone

     Customer's phone number.

   * fax

     Customer's fax number.

   * email

     Customer's email address.

   * card_number

     Credit card number (obviously not required for non-credit card
     transactions).

   * exp_date

     Credit card expiration (obviously not required for non-credit card
     transactions).

   * account_number

     Bank account number for electronic checks or electronic funds
     transfer.

   * routing_code

     Bank's routing code for electronic checks or electronic funds
     transfer.

   * bank_name

     Bank's name for electronic checks or electronic funds transfer.

submit();
---------

   Submit the transaction to the processor for completion

is_success();
-------------

   Returns true if the transaction was submitted successfully, false if it
failed (or undef if it has not been submitted yet).

result_code();
--------------

   Returns the precise result code that the processor returned, these are
normally one letter codes that don't mean much unless you understand the
protocol they speak, you probably don't need this, but it's there just in
case.

test_transaction();
-------------------

   Most processors provide a test mode, where submitted transactions will
not actually be charged or added to your batch, calling this function with
a true argument will turn that mode on if the processor supports it, or
generate a fatal error if the processor does not support a test mode
(which is probably better than accidentally making real charges).

require_avs();
--------------

   Providing a true argument to this module will turn on address
verification (if the processor supports it).

transaction_type();
-------------------

   Retrieve the transaction type (the 'type' argument to contents();).
Generally only used internally, but provided in case it is useful.

error_message();
----------------

   If the transaction has been submitted but was not accepted, this
function will return the provided error message (if any) that the
processor returned.

authorization();
----------------

   If the transaction has been submitted and accepted, this function will
provide you with the authorization code that the processor returned.

server();
---------

   Retrieve or change the processor submission server address (CHANGE AT
YOUR OWN RISK).

port();
-------

   Retrieve or change the processor submission port (CHANGE AT YOUR OWN
RISK).

path();
-------

   Retrieve or change the processor submission path (CHANGE AT YOUR OWN
RISK).

AUTHOR
======

   Jason S Kohles, jason@mediabang.com

DISCLAIMER
==========

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

SEE ALSO
========

   For verification of credit card checksums, see `Business::CreditCard'
in this node.

AuthorizeNet backend for Business::OnlinePayment
************************************************

NAME
====

   Business::OnlinePayment::AuthorizeNet - AuthorizeNet backend for
Business::OnlinePayment

SYNOPSIS
========

     use Business::OnlinePayment;

     my $tx = new Business::OnlinePayment("AuthorizeNet");
     $tx->content(
         type           => 'VISA',
         login          => 'testdrive',
         password       => '',
         action         => 'Normal Authorization',
         description    => 'Business::OnlinePayment test',
         amount         => '49.95',
         invoice_number => '100100',
         customer_id    => 'jsk',
         name           => 'Jason Kohles',
         address        => '123 Anystreet',
         city           => 'Anywhere',
         state          => 'UT',
         zip            => '84058',
         card_number    => '4007000000027',
         expiration     => '09/99',
     );
     $tx->submit();

     if($tx->is_success()) {
         print "Card processed successfully: ".$tx->authorization."\n";
     } else {
         print "Card was rejected: ".$tx->error_message."\n";
     }

SUPPORTED TRANSACTION TYPES
===========================

Visa, MasterCard, American Express, Discover
--------------------------------------------

   Content required: type, login, password, action, amount, name,
card_number, expiration.

Check
-----

   Content required: type, login, password, action, amount, name,
account_number, routing_code, bank_name.

DESCRIPTION
===========

   For detailed information see Business/OnlinePayment.

AUTHOR
======

   Jason Kohles, jason@mediabang.com

SEE ALSO
========

   perl(1). See Business/OnlinePayment.

Cardstream Plugin for Business::OnlinePayment
*********************************************

NAME
====

   Business::OnlinePayment::Cardstream - Cardstream Plugin for
Business::OnlinePayment

SYNOPSIS
========

     use Business::OnlinePayment;
     my $Cardstream = new Business::OnlinePayment("Cardstream");

     $Cardstream->content(
     	type		=>	'visa',
     	login		=>	'mylogin',
     	passwd		=>	'mypassword',
     	action		=>	'authorise',
     	amount		=>	'5.00',
     	name		=>	'John Watson',
     	address		=>	'6 Elms, Oak Road.',
     	card_number	=>	'4725444499992827',
     	expiration	=>	'0112' #YYMM
     	);
     $Cardstream->submit;

     if ($Cardstream->is_success) {
     	print "Success, Auth Code is ".$Cardstream->authorization;
     } else {
     	print "Failed, Error message ".$Cardstream->error_message;
     }

     my @RESPONSE = split('\|',$Cardstream->server_response);
     my %response_hash = @RESPONSE;

Supported Cards
===============

Visa, MasterCard, Switch	(Check website for updates)
----------------------------------------------------

   Switch cards require issue number; $Cardstream->content(issue => '1')

NOTES
=====

Merchant accounts
-----------------

   A Cardstream merchant account is free of charge to set-up.  Cardstream
operates on a commission basis. Please see http://www.cardstream.com for
pricing information, or contact sales@cardstream.com.

Expiration dates
----------------

   Cardstream.pm requires expiration dates in APACS/30 Standard format,
which, unlike what is printed on the card, is YYMM.

server-response
---------------

   The auth code and error messages are stored into
$Cardstream->authorization and $Cardstream->error_message, however should
you require more debugging information, server-response contains a pipe
delimited hash consisting of the error code, text message from bank...etc.

DESCRIPTION
===========

   For detailed information see Business/OnlinePayment.

AUTHOR
======

   Craig R. Belcham, crb@cardstream.com.

SEE ALSO
========

   perl(1). See Business/OnlinePayment.
http://www.cardstream.com for merchant account information.  =cut

Perl extension for manipulating Universal Product Codes
*******************************************************

NAME
====

   Business::UPC - Perl extension for manipulating Universal Product Codes

SYNOPSIS
========

     use Business::UPC;

     # Constructors:
     # create a UPC object using standard (type-A) UPC
     $upc = new Business::UPC('012345678905');
     # create a UPC object using zero-supressed (type-E) UPC
     $upc = type_e Business::UPC('01201303');

     # is the UPC valid (correct check digit)?
     $upc->is_valid;

     # correct the check digit
     $upc->fix_check_digit;

     # get the numeric string:
     $upc->as_upc;	# same as $upc->as_upc_a;
     $upc->as_upc_a;
     $upc->as_upc_e;

     # get the components;
     $upc->number_system;		# UPC number system character
     $upc->mfr_id;		# Manufacturer ID
     $upc->prod_id;		# Product ID
     $upc->check_digit;		# Check Digit

     # more information about the components:
     $upc->number_system_description	# explain number_system

     # methods specific to coupon UPC codes:
     $upc->is_coupon;
     $upc->coupon_family_code;		# 3-digit family code
     $upc->coupon_family_description;	# explain above
     $upc->coupon_value_code;		# 2-digit value code
     $upc->coupon_value;			# explain above

DESCRIPTION
===========

   More detail to come later...

AUTHOR
======

   Rob Fugina, robf@geeks.com

SEE ALSO
========

   perl(1).

A UPS Interface Module
**********************

NAME
====

   Business::UPS - A UPS Interface Module

SYNOPSIS
========

     use Business::UPS;

     my ($shipping,$ups_zone,$error) = getUPS(qw/GNDCOM 23606 23607 50/);
     $error and die "ERROR: $error\n";
     print "Shipping is \$$shipping\n";
     print "UPS Zone is $ups_zone\n";

     %track = UPStrack("z10192ixj29j39");
     $track{error} and die "ERROR: $track{error};

     # 'Delivered' or 'In-transit'
     print "This package is $track{Current Status}\n";

DESCRIPTION
===========

   A way of sending four arguments to a module to get shipping charges
that can be used in, say, a CGI.

REQUIREMENTS
============

   I've tried to keep this package to a minimum, so you'll need:

   * Perl 5.003 or higher

   * LWP Module

ARGUMENTS for getUPS()
======================

   Call the subroutine with the following values:

     1. Product code (see product-codes.txt)
     2. Origin Zip Code
     3. Destination Zip Code
     4. Weight of Package

   and optionally:

     5.  Country Code, (see country-codes.txt)
     6.  Rate Chart (drop-off, pick-up, etc - see below)
     6.  Length,
     7.  Width,
     8.  Height,
     9.  Oversized (defined if oversized), and
     10. COD (defined if C.O.D.)

  1. Product Codes:

          1DM		Next Day Air Early AM
          1DML		Next Day Air Early AM Letter
          1DA		Next Day Air
          1DAL		Next Day Air Letter
          1DP		Next Day Air Saver
          1DPL		Next Day Air Saver Letter
          2DM		2nd Day Air A.M.
          2DA		2nd Day Air
          2DML		2nd Day Air A.M. Letter
          2DAL		2nd Day Air Letter
          3DS		3 Day Select
          GNDCOM	Ground Commercial
          GNDRES	Ground Residential
          XPR		Worldwide Express
          XDM		Worldwide Express Plus
          XPRL		Worldwide Express Letter
          XDML		Worldwide Express Plus Letter
          XPD		Worldwide Expedited

     In an HTML "option" input it might look like this:

          <OPTION VALUE="1DM">Next Day Air Early AM
          <OPTION VALUE="1DML">Next Day Air Early AM Letter
          <OPTION SELECTED VALUE="1DA">Next Day Air
          <OPTION VALUE="1DAL">Next Day Air Letter
          <OPTION VALUE="1DP">Next Day Air Saver
          <OPTION VALUE="1DPL">Next Day Air Saver Letter
          <OPTION VALUE="2DM">2nd Day Air A.M.
          <OPTION VALUE="2DA">2nd Day Air
          <OPTION VALUE="2DML">2nd Day Air A.M. Letter
          <OPTION VALUE="2DAL">2nd Day Air Letter
          <OPTION VALUE="3DS">3 Day Select
          <OPTION VALUE="GNDCOM">Ground Commercial
          <OPTION VALUE="GNDRES">Ground Residential

  2. Origin Zip(tm) Code

     Origin Zip Code as a number or string (NOT +4 Format)

  3. Destination Zip(tm) Code

     Destination Zip Code as a number or string (NOT +4 Format)

  4. Weight

     Weight of the package in pounds

  5. Country

     Defaults to US

  6. Rate Chart

     How does the package get to UPS:

     Can be one of the following:

          Regular Daily Pickup
          On Call Air
          One Time Pickup
          Letter Center
          Customer Counter

ARGUMENTS for UPStrack()
========================

   The tracking number.

     use Business::UPS;
     %t = UPStrack("1ZX29W290250xxxxxx");
     print "This package is $track{Current Status}\n";

RETURN VALUES
=============

getUPS()
          The raw http get() returns a list with the following values:

          ##  Desc		Typical Value
          --  ---------------   -------------
          0.  Name of server: 	UPSOnLine3
          1.  Product code:	GNDCOM
          2.  Orig Postal:	23606
          3.  Country:		US
          4.  Dest Postal:	23607
          5.  Country:		US
          6.  Shipping Zone:	002
          7.  Weight (lbs):	50
          8.  Sub-total Cost:	7.75
          9.  Addt'l Chrgs:	0.00
          10. Total Cost:	7.75
          11. ???:		-1

          If anyone wants these available for some reason, let me know.

UPStrack() 	 The hash that's returned is like the following:
          'Delivered on' 	=> '1-22-1998 at 2:58 PM'
          'Notice' 		=> 'UPS authorizes you to use UPS...'
          'Received by'		=> 'DR PORCH'
          'Addressed to'	=> 'NEWPORT NEWS, VA US'
          'scan'		=>  HASH(0x146e0c) (more later...)
          'Current Status'	=> 'Delivered'
          'Delivered to'	=> 'RESIDENTIAL'
          'Sent on'		=> '1-20-1998'
          'UPS Service'		=> '2ND DAY AIR'
          'Tracking Number' 	=> '1ZX29W29025xxxxxx'
          'Scanning'		=> (See next paragraph)

     Notice the key 'Scanning' is a newline (\n) delineated list of
     scanning locations.  Each line has two parts: 1. Time/Date of scan
     and 2. Type of scan.  In its scalar context, it looks like this:

          1-22-19982:58 PM NEWPORT NEWS-OYSTER, VA US = DELIVERED
          1-21-199811:37 PM RICHMOND, VA US = LOCATION SCAN
          2:05 PM PHILA AIR HUB, PA US = LOCATION SCAN
          1-20-199811:35 PM PHILA AIR HUB, PA US = LOCATION SCAN

     ...but a line or two of code can make it very usable like this:

          foreach $line (split "\n", $track{Scanning}) {
            my ($location, $type) = split /=/, $line;
            print "At $location, the shipment was $type\n";
          }

EXAMPLE
=======

getUPS()
     To retreive the shipping of a 'Ground Commercial' Package weighing
     25lbs. sent from 23001 to 24002 this package would be called like
     this:

          #!/usr/local/bin/perl
          use Business::UPS;

          my ($shipping,$ups_zone,$error) = getUPS(qw/GNDCOM 23001 23002 25/);
          $error and die "ERROR: $error\n";
          print "Shipping is \$$shipping\n";
          print "UPS Zone is $ups_zone\n";

UPStrack()
          #!/usr/local/bin/perl

          use Business:UPS;

          %t = UPStrack("z10192ixj29j39");
          $t{error} and die "ERROR: $t{error};

          print "This package is $t{'Current Status'}\n"; # 'Delivered' or
          						  # 'In-transit'
          print "More info:\n";
          foreach $key (keys %t) {
            print "KEY: $key = $t{$key}\n";
          }

BUGS
====

   Let me know.

AUTHOR
======

   Mark Solomon <msolomon@seva.net>

   mailto:msolomon@seva.net

   http://www.seva.net/~msolomon/

   NOTE: UPS is a registered trademark of United Parcel Service.

SEE ALSO
========

   perl(1).

class encapsulating US-style amortization
*****************************************

NAME
====

   Business::US_Amort - class encapsulating US-style amortization

SYNOPSIS
========

     use Business::US_Amort;
     my $loan = Business::US_Amort->new;
     $loan->principal(123654);
     $loan->interest_rate(9.25);
     $loan->term(20);

     my $add_before_50_amt = 700;
     sub add_before_50 {
       my $this = $_[0];
       if($this->{'_month_count'} == 50) {
         $this->{'_monthly_payment'} += $add_before_50_amt;
       }
     }
     $loan->callback_before_monthly_calc(\&add_before_50);
     $loan->start_date_be_now;

     $loan->run;
     $loan->dump_table;

     print "Total paid toward interest: ", $loan->total_paid_interest, "\n";

DESCRIPTION
===========

   This class encapsulates amortization calculations figured according to
what I've been led to believe is the usual algorithm for loans in the USA.

   I used to think amortization was simple, just the output of an algorithm
that'd take just principle, term, and interest rate, and return the
monthly payment and maybe something like total paid toward interest.
However, I discovered that there's a need for loan calculations where,
say, between the 49th and 50th month, your interest rate drops, or where
you decide to add $100 to your monthly payment in the 32nd month.

   So I wrote this class, so that I could amortize simply in simple cases
while still allowing any kind of strangeness in complex cases.

FUNCTIONS
=========

   This module provides one function, which is a simple amortizer.  This
is just to save you the bother of method calls when you really don't need
any frills.

Business::US_Amort::simple $principal, $interest_rate, $term
     Amortizes based on these parameters.  In a scalar context, returns
     the initial monthly payment.

     In an array context, returns a three item list consisting of: the
     initial monthly payment, the total paid toward interest, and the loan
     object, in case you want to do things with it.

   Example usages:

     $monthly_payment = Business::US_Amort::simple(123654, 9.25, 20);

     ($monthly_payment, $total_toward_interest, $o)
       = Business::US_Amort::simple(123654, 9.25, 20);

   Of course, if you find yourself doing much of anything with the loan
object, you probably should be using the OOP interface instead of the
functional one.

OBJECT ATTRIBUTES
=================

   All attributes for this class are scalar attributes.  They can be read
via:

     $thing = $loan->principal     OR    $thing = $loan->{'principal'}

   or set via:

     $loan->principal(VALUE)       OR    $loan->{'principal'} = VALUE

MAIN ATTRIBUTES
---------------

   These attributes are used as parameters to the run method.

principal
     The principal amount of the loan.

interest_rate
     The annual rate, expressed like 8.3, not like .083.

     Note that if you're defining callbacks, you can change this attribute
     at any time in your callbacks, to change the rate of interest from
     then on.

term
     The term of the loan, in years, not months.

callback_before_monthly_calc
     If set, this should be a coderef to a routine to call at the
     *beginning* of each month, *before any* calculations are done.  The
     one parameter passed to this routine, in $_[0], is the object.  See
     the SYNOPSIS, above, for an example.

callback_after_monthly_calc
     If set, this should be a coderef to a routine to call at the end of
     each month, *after all* monthly calculations are done.  The one
     parameter passed to this routine, in $_[0], is the object.

block_table
     If set to true, this inhibits run from adding to table.  (This is
     false by default.) If you're not going to access table, set this to
     true before calling run - it'll speed things up and use less memory.

start_date
     If set to a date in the format "YYYY-MM", _date will be defined
     appropriately for each month.  You can set start_date to the current
     month by just saying $loan->start_date_be_now.

cent_rounding
     If set to true, figures are rounded to the nearest cent at appropriate
     moments, so as to avoid having to suppose that the debtor is to make a
     monthly payment of $1025.229348723948 on a remaining principal of
     $196239.12082309123408, or the like.

   These attributes are set by the run method:

initial_monthly_payment
     The monthly payment that follows from the basic amortization
     parameters given.  Compare with _monthly_payment.

total_paid_interest
     The total amount paid toward interest during the term of this loan.

total_month_count
     The total number of months the loan took to pay off.  E.g., "12" for
     a loan that took 12 months to pay off.

table
     This will be a reference to a list of copies made of the object
     ("snapshots") each month.  You can then use this if you want to
     generate a dump of particular values of the object's state in each
     month.

     Note that snapshots have their am_snapshot attribute set to true, and
     have their table attribute set to undef.  (Otherwise this'd be a
     circular data structure, which would be a hassle for you and me.)

error
     A string explaining any error that might have occurred, which
     would/should accompany run returning 0.  Use like:

          $loan->run or die("Run failed: " . $loan->error);

   Other attributes:

am_snapshot
     This attribute is set to true in snapshots, as stored in table.

_month_count_limit
     This is a variable such that if the month count ever exceeds this
     amount, the main loop will abort.  This is intended to keep the
     iterator from entering any infinite loops, even in pathological cases.
     Currently the run method sets this to twelve plus twice the number of
     months that it's expected this loan will take.  Increase as necessary.

INTERATION ATTRIBUTES
---------------------

   These are attributes of little or no interest once run is done, but may
be of interest to callbacks while run is running, or may be of interest in
examining snapshots in table.

_month_count
     This is how many months we are into the loan.  The first month is 1.

_abort
     If you want callbacks to be able to halt the iteration for some
     reason, you can have them set _abort to true.  You may also choose to
     set error to something helpful.

_monthly_payment
     The amount to be paid to toward the principal each month. At the start
     of the loan, this is set to whatever initial_monthly_payment is
     figured to be, but you can manipulate _monthly_payment with callbacks
     to change how much actually gets paid when.

_remainder
     The balance on the loan.

_date
     The given month's date, if known, in the format "YYYY-MM".  Unless
     you'd set the start_date to something, this will be undef.

_h
     The interest to be paid this month.

_old_amount
     What the remainder was before we made this month's payment.

_c
     The current monthly payment, minus the monthly interest, possibly
     tweaked in the last month to avoid paying off more than is actually
     left on the loan.

METHODS
=======

$loan = Business::US_Amort->new
     Creates a new loan object.

$loan->copy
     Copies a loan object or snapshot object.  Also performs a somewhat
     deep copy of its table, if applicable.

$loan->destroy
     Destroys a loan object.  Probably never necessary, given Perl's
     garbage collection techniques.

$loan->start_date_be_now
     This sets start_date to the current date, based on $^T.

$loan->run
     This performs the actual amortization calculations.  Returns 1 on
     success; otherwise returns 0, in which case you should check the
     error attribute.

$loan->dump_table
     This method dumps a few fields selected from snapshots in the table
     of the given object.  It's here more as example code than as anything
     particularly useful.  See the source.  You should be able to use this
     as a basis for making code of your own that dumps relevant fields from
     the contents of snapshots of loan objects.

REMEMBER
========

   When in panic or in doubt, run in circles, scream and shout.

   Or read the source.  I really suggest the latter, actually.

WARNINGS
========

   * There's little or no sanity checking in this class.  If you want to
amortize a loan for $2 at 1% interest over ten million years, this class
won't stop you.

   * Perl is liable to produce tiny math errors, like just about any other
language that does its math in binary but has to convert to and from
decimal for purposes of human interaction.  I've seen this surface as tiny
discrepencies in loan calculations - "tiny" as in less than $1 for even
multi-million-dollar loans amortized over decades.

   * Moreover, oddities may creep in because of round-off errors. This
seems to result from the fact that the formula that takes term, interest
rate, and principal, and returns the monthly payment, doesn't know that a
real-world monthly payment of "$1020.309" is impossible - and so that
ninth of a cent difference can add up across the months.  At worst, this
may cause a 30-year-loan loan coming to term in 30 years and 1 month, with
the last payment being needed to pay off a balance of two dollars, or the
like.

   These errors have never been a problem for any purpose I've put this
class to, but be on the look out.

DISCLAIMER
==========

   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*.

   But let me know if it gives you any problems, OK?

COPYRIGHT
=========

   Copyright 1999, 2000, Sean M. Burke `sburke@cpan.org', all rights
reserved.  This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

AUTHOR
======

   Sean M. Burke `sburke@cpan.org'

byte-compile modules when needed
********************************

NAME
====

   ByteCache - byte-compile modules when needed

SYNOPSIS
========

     use ByteCache;
     use Other::Module;

DESCRIPTION
===========

   This module causes any modules loaded after it to be loaded in bytecode
compiled format. If a bytecode compiled version of the module does not
currently exist, ByteCache will call the compiler to create one and then
save it away.

WARNING
=======

   This module is dependent on the compiler suite, and is therefore
B&lt;very&gt; experimental. Your results may very. Do not use in
production systems.

AUTHOR
======

   Simon Cozens, `simon@brecon.co.uk'

SEE ALSO
========

   See Perl (perl.info), `perlcc' in this node, see ByteLoader,

load byte compiled perl code
****************************

NAME
====

   ByteLoader - load byte compiled perl code

SYNOPSIS
========

     use ByteLoader 0.03;
     <byte code>

     use ByteLoader 0.03;
     <byte code>

DESCRIPTION
===========

   This module is used to load byte compiled perl code. It uses the source
filter mechanism to read the byte code and insert it into the compiled
code at the appropriate point.

AUTHOR
======

   Tom Hughes <tom@compton.nu> based on the ideas of Tim Bunce and others.

SEE ALSO
========

   perl(1).

Perl interface to C compiled code.
**********************************

NAME
====

   C::DynaLib - Perl interface to C compiled code.

SYNOPSIS
========

     use C::DynaLib;
     use sigtrap;	# recommended

     $lib = new C::DynaLib( $linker_arg );

     $func = $lib->DeclareSub( $symbol_name
     			    [, $return_type [, @arg_types] ] );
     # or
     $func = $lib->DeclareSub( { "name"    => $symbol_name,
     			      [param => $value,] ... } );
     # or
     use C::DynaLib qw(DeclareSub);
     $func = DeclareSub( $function_pointer,
     		      [, $return_type [, @arg_types] ] );
     # or
     $func = DeclareSub( { "ptr" => $function_pointer,
     			[param => $value,] ... } );

     $result = $func->( @args );

     $callback = new C::DynaLib::Callback( \&my_sub,
     			$return_type, @arg_types );
     $callback_pointer = $callback->Ptr();

PLUG FOR PERL XS
================

   If you have a C compiler that Perl supports, you will get better
results by writing XSubs than by using this module.  *I GUARANTEE IT!*  It
may take you longer to do what you want, but your code will be much more
solid and portable.  See Perlxs (perl.info).

   This module brings "pointers" to Perl.  Perl's non-use of pointers is
one of its great strengths.  If you don't know what I mean, then maybe you
ought to practice up a bit on C or C++ before using this module.  If
anything, pointers are more dangerous in Perl than in C, due to Perl's
dynamic, interpretive nature.

   The XSub interface and Perl objects provide a means of calling C and
C++ code while preserving Perl's abstraction from pointers.  Once again, I
*urge* you to check out Perlxs (perl.info),!  It's really
cool!!!

DESCRIPTION
===========

   This module allows Perl programs to call C functions in dynamic
libraries.  It is useful for testing library functions, writing simple
programs without the bother of XS, and generating C function pointers that
call Perl code.

   Your Perl must be of the dynamic variety and have a working DynaLoader
to use the dynamic loading capabilities of this module.  Be sure you
answered "y" when Configure (from the Perl source kit) asked, "Do you wish
to use dynamic loading?".

   The mechanics of passing arguments to and returning values from C
functions vary greatly among machines, operating systems, and compilers.
Therefore, Makefile.PL checks the Perl configuration and may even compile
and run a test program before the module is built.

   This module is divided into two packages, `C::DynaLib' and
`C::DynaLib::Callback'.  Each makes use of Perl objects (see
Perlobj (perl.info)) and provides its own constructor.

   A `C::DynaLib' object corresponds to a dynamic library whose functions
are available to Perl.  A `C::DynaLib::Callback' object corresponds to a
Perl sub which may be accessed from C.

`C::DynaLib' public constructor
-------------------------------

   The argument to new may be the file name of a dynamic library.
Alternatively, a linker command-line argument (e.g., `"-lc"') may be
specified.  See `DynaLoader(3)' in this node for details on how such
arguments are mapped to file names.

   On failure, new returns undef.  Error information *might* be obtainable
by calling `DynaLoader::dl_error()'.

Declaring a library routine
---------------------------

   Before you can call a function in a dynamic library, you must specify
its name, the return type, and the number and types of arguments it
expects.  This is handled by `DeclareSub'.

   `C::DynaLib::DeclareSub' can be used as either an object method or an
ordinary sub.  You can pass its arguments either in a list (what we call
*positional parameters*) or in a hash (*named parameters*).

   The simplest way to use `DeclareSub' is as a method with positional
parameters.  This form is illustrated in the first example above and both
examples below.  When used in this way, the first argument is a library
function name, the second is the function return type, and the rest are
function argument types.

   *THIS IS VERY IMPORTANT*.  You must not forget to specify the return
type as the second argument to `DeclareSub'.  If the function returns
void, you should use "" as the second argument.

   C data types are specified using the codes used by Perl's pack and
unpack operators.  See `perlfunc(1)' in this node for their description.
As a convenience (and to hide system dependencies), `PTR_TYPE' is defined
as a code suitable for pointer types (typically `"i"').

   The possible arguments to `DeclareSub' are shown below.  Each is listed
under the name that is used when passing the arguments in a hash.

name
     The name of a function exported by `$lib'.  This argument is ignored
     in the non-method forms of `DeclareSub'.

`ptr'
     The address of the C function.  This argument is required in the
     non-method forms of `DeclareSub'.  Either it or the name must be
     specified in the method forms.

return
     The return type of the function, encoded for use with the pack
     operator.  Not all of the pack codes are supported, but the
     unsupported ones mostly don't make sense as C return types.  Functions
     that return a `struct' are not supported.  However, a pointer to
     struct is okay.

     Many C functions return pointers to various things.  If you have a
     function that returns `char *' and all you're interested in is the
     string (i.e., the `char' sequence pointed to, up to the first nul),
     then you may use `"p"' as the return type.  The `"P"' code (followed
     by a number of bytes) is also permissible.

     For the case where a returned pointer value must be remembered (for
     example, *malloc()*), use `PTR_TYPE'.  The returned scalar will be
     the pointer itself.  You can use unpack to find the thing pointed to.

args
     A list of the types of arguments expected by the function, specified
     using the notation of Perl's pack operator.  For example, `"i"' means
     an integer, `"d"' means a double, and `"p"' means a nul-terminated
     string pointer.  If you need to handle pointers to things other than
     Perl scalars, use type `PTR_TYPE'.

     Note: you probably don't want to use `"c"' or `"s"' here, since C
     normally converts the corresponding types (`char' and short) to int
     when passing them to a function.  The C::DynaLib package may or may
     not perform such conversions.  Use `"i"' instead.  Likewise, use
     `"I"' in place of `"C"' or `"S"', and `"d"' in place of `"f"'.  Stick
     with `"i"', `"I"', `"d"', `"p"', `"P"', and `PTR_TYPE' if you want to
     be safe.

     Passing structs by value is not generally supported, but you might
     find a way to do it with a given compiler by experimenting.

`decl'
     Allows you to specify a function's calling convention.  This is
     possible only with a named-parameter form of `DeclareSub'.  See below
     for information about the supported calling conventions.

`libref'
     A library reference obtained from either `DynaLoader::dl_load_file'
     or the `C::DynaLib::LibRef' method.  You must use a named-parameter
     form of `DeclareSub' in order to specify this argument.

Calling a declared function
---------------------------

   The returned value of `DeclareSub' is a code reference.  Calling
through it results in a call to the C function.  See `perlref(1)' in this
node on how to use code references.

Using callback routines
-----------------------

   Some C functions expect a pointer to another C function as an argument.
The library code that receives the pointer may use it to call an
application function at a later time.  Such functions are called
*callbacks*.

   This module allows you to use a Perl sub as a C callback, subject to
certain restrictions.  There is a hard-coded maximum number of callbacks
that can be active at any given time.  The default (4) may be changed by
specifying `CALLBACKS=number' on the Makefile.PL command line.

   A callback's argument and return types are specified using pack codes,
as described above for library functions.  Currently, the return value
must be interpretable as type int or void, so the only valid codes are
`"i"', `"I"', and "".  There are also restrictions on the permissible
argument types, especially for the first argument position.  These
limitations are considered bugs to be fixed someday.

   To enable a Perl sub to be used as a callback, you must construct an
object of class `C::DynaLib::Callback'.  The syntax is

     $cb_ref = new C::DynaLib::Callback( \&some_sub,
                       $ret_type, @arg_types );

   where `$ret_type' and `@arg_types' are the pack-style types of the
function return value and arguments, respectively.  `\&some_sub' must be a
code reference or sub name (see Perlref (perl.info)).

   `$cb_ref->Ptr()' then returns a function pointer.  C code that calls it
will end up calling `&some_sub'.

EXAMPLES
========

   This code loads and calls the math library function *sinh()*.  It
assumes that you have a dynamic version of the math library which will be
found by `DynaLoader::dl_findfile("-lm")'.  If this doesn't work, replace
`"-lm"' with the name of your dynamic math library.

     use C::DynaLib;
     $libm = new C::DynaLib("-lm");
     $sinh = $libm->DeclareSub("sinh", "d", "d");
     print "The hyperbolic sine of 3 is ", &{$sinh}(3), "\n";
     # The hyperbolic sine of 3 is 10.0178749274099

   The following example uses the C library's *strncmp()* to compare the
first n characters of two strings:

     use C::DynaLib;
     $libc = new C::DynaLib("-lc");
     $strncmp = $libc->DeclareSub("strncmp", "i", "p", "p", "I");
     $string1 = "foobar";
     $string2 = "foolish";
     $result = &{$strncmp}($string1, $string2, 3);  # $result is 0
     $result = &{$strncmp}($string1, $string2, 4);  # $result is -1

   The files test.pl and `README.win32' contain examples using callbacks.

CALLING CONVENTIONS
===================

   This section is intended for anyone who is interested in debugging or
extending this module.  You probably don't need to read it just to use the
module.

The problem
-----------

   The hardest thing about writing this module is to accommodate the
different calling conventions used by different compilers, operating
systems, and CPU types.

   "What's a calling convention?" you may be wondering.  It is how
compiler-generated functions receive their arguments from and make their
return values known to the code that calls them, at the level of machine
instructions and registers.  Each machine has a set of rules for this.
Compilers and operating systems may use variations even on the same
machine type.  In some cases, it is necessary to support more than one
calling convention on the same system.

   "But that's all handled by the compiler!" you might object.  True
enough, if the calling code knows the signature of the called function at
compile time.  For example, consider this C code:

     int foo(double bar, const char *baz);
     ...
     int res;
     res = foo(sqrt(2.0), "hi");

   A compiler will generate specific instruction sequences to load the
return value from *sqrt()* and a pointer to the string `"hi"' into
whatever registers or memory locations *foo()* expects to receive them in,
based on its calling convention and the types double and `char *'.
Another specific instruction sequence stores the return value in the
variable res.

   But when you compile the C code in this module, it must be general
enough to handle all sorts of function argument and return types.

   "Why not use varargs/stdarg?"  Most C compilers support a special set
of macros that allow a function to receive a variable number of arguments
of variable type.  When the function receiving the arguments is compiled,
it does not know with what argument types it will be called.

   But the code that *calls* such a function *does* know at compile time
how many and what type of arguments it is passing to the varargs function.
There is no "reverse stdarg" standard for passing types to be determined
at run time.  You can't simply pass a `va_list' to a function unless that
function is defined to receive a `va_list'.  This module uses
varargs/stdarg where appropriate, but the only appropriate place is in the
callback support.

The solution (well, half-solution)
----------------------------------

   Having failed to find a magic bullet to spare us from the whims of
system designers and compiler writers, we are forced to examine the
calling conventions in common use and try to put together some "glue" code
that stands a chance of being portable.

   In writing glue code (that which allows code written in one language to
call code in another), an important issue is reliability.  If we don't get
the convention just right, chances are we will get a core dump (protection
fault or illegal instruction).

   To write really solid Perl-to-C glue, we would have to use assembly
language and have detailed knowledge of each calling convention.  Compiler
source code can be helpful in this regard, and if your compiler can output
assembly code, that helps, too.

   However, this is Perl, Perl is meant to be ported, and assembly
language is generally not portable.  This module typically uses C
constructs that happen to work most of the time, as opposed to assembly
code that follows the conventions faithfully.

   By avoiding the use of assembly, we lose some reliability and
flexibility.  By loss of reliability, I mean we can expect crashes,
especially on untested platforms.  Lost flexibility means having
restrictions on what parameter types and return types are allowed.

   The code for all conventions other than `hack30' (described below)
relies on C's *alloca()* function.  Unfortunately, *alloca()* itself is
not standard, so its use introduces new portability concerns.  For `cdecl'
(the most general convention) Makefile.PL creates and runs a test program
to try to ferret out any compiler peculiarities regarding *alloca()*.  If
the test program fails, the default choice becomes `hack30'.

Supported conventions
---------------------

   `C::DynaLib' currently supports the parameter-passing conventions
listed below.  The module can be compiled with support for one or more of
them by specifying (for example) `DECL=cdecl' on Makefile.PL's
command-line.  If none are given, Makefile.PL will try to choose based on
your perl configuration and/or the results of running a test program.

   At run time, a calling convention may be specified using a
named-parameter form of `DeclareSub' (described above), or a default may
be used.  The first `DECL=...' supplied to Makefile.PL will be the default
convention.

   Note that the convention must match that of the function in the dynamic
library, otherwise crashes or incorrect results are likely to occur.

`cdecl'
     All arguments are placed on the stack in reverse order from how the
     function is invoked.  This seems to be the default for Intel-based
     machines and some others.

`sparc'
     The first 24 bytes of arguments are cast to an array of six ints.
     The remaining args (and possibly piece of an arg) are placed on the
     stack.  Then the C function is called as if it expected six integer
     arguments.  On a Sparc, the six "pseudo-arguments" are passed in
     special registers.

`alpha'
     This is similar to the `sparc' convention, but the pseudo-arguments
     have type long instead of int, and all arguments are extended to
     eight bytes before being placed in the array.  On the AXP, a special
     sequence of assembly instructions is used to ensure that any function
     parameters of type double are passed correctly.

`hack30'
     This is not really a calling convention, it's just some C code that
     will successfully call a function most of the time on a variety of
     systems.  All arguments are copied into an array of 6 long integers
     (or 30 if 6 is not enough).  The function is called as if it expected
     6 (or 30) long arguments.

     You will run into problems if the C function either (1) takes more
     arguments than can fit in the array, (2) takes some non-long arguments
     on a system that passes them differently from longs (but `cdecl'
     currently has the same flaw), or (3) cares if it is passed extra
     arguments (Win32 API functions crash because of this).

     Because of these problems, the use of `hack30' is recommended only as
     a quick fix until your system's calling convention is supported.

BUGS
====

   Several unresolved issues surround this module.

Portability
-----------

   The "glue" code that allows Perl values to be passed as arguments to C
functions is architecture-dependent.  This is because the author knows of
no standard means of determining a system's parameter-passing conventions
or passing arguments to a C function whose signature is not known at
compile time.

   Although some effort is made in Makefile.PL to find out how parameters
are passed in C, this applies only to the integer type (Perl's `I32', to
be precise).  Functions that recieve or return type double, for example,
may not work on systems that use floating-point registers for this
purpose.  Specialized code may be required to support such systems.

Robustness
----------

   Usually, Perl programs run under the control of the Perl interpreter.
Perl is extremely stable and can almost guarantee an environment free of
the problems of C, such as bad pointers causing memory access violations.
Some modules use a Perl feature called "XSubs" to call C code directly
from a Perl program.  In such cases, a crash may occur if the C or XS code
is faulty.  However, once the XS module has been sufficiently debugged,
one can be reasonably sure that it will work right.

   Code called through this module lacks such protection.  Since the
association between Perl and C is made at run time, errors due to
incompatible library interfaces or incorrect assumptions have a much
greater chance of causing a crash than with either straight Perl or XS
code.

Security
--------

   This module does not require special privileges to run.  I have no
reason to think it contains any security bugs (except to the extent that
the known bugs impact security).  However, when this module is installed,
Perl programs gain great power to exploit C code which could potentially
have such bugs.  I'm not really sure whether this is a major issue or not.

   I haven't gotten around to understanding Perl's internal tainting
interface, so taint-checking may not accomplish what you expect.  (See
Perlsec (perl.info))

Deallocation of Resources
-------------------------

   To maximize portability, this module uses the DynaLoader interface to
dynamic library linking.  DynaLoader's main purpose is to support XS
modules, which are loaded once by a program and not (to my knowledge)
unloaded.  It would be nice to be able to free the libraries loaded by
this module when they are no longer needed.  This will be impossible, as
long as DynaLoader provides no means to do so.

Literal and temporary strings
-----------------------------

   Before Perl 5.00402, it was impossible to pass a string literal as a
pointer-to-nul-terminated-string argument of a C function.  For example,
the following statement (incorrectly) produced the error `Modification of
a read-only value attempted':

     &$strncmp("foo", "bar", 3);

   To work around this problem, one must assign the value to a variable
and pass the variable in its place, as in

     &$strncmp($dummy1 = "foo", $dummy2 = "bar", 3);

Callbacks
---------

   Only a certain number of callbacks can exist at a time.  Callbacks can
mess up the message produced by die in the presence of nested evals.  The
Callback code uses global data, and is consequently not thread-safe.

Miscellaneous Bugs
------------------

   There are restrictions on what C data types may be used.  Using
argument types of unusual size may have nasty results.  The techniques
used to pass values to and from C functions are generally hackish and
nonstandard.  Assembly code would be more complete.  Makefile.PL does too
much.  I haven't yet checked for memory leaks.

TODO
====

   Rewrite using GNU ffcall.  Fiddle with autoloading so we don't have to
call DeclareSub all the time.  Mangle C++ symbol names.  Get Perl to
understand C header files (macros and function declarations) with enough
confidence to make them useful here.

LICENSE
=======

   Copyright (c) 1997, 2000 by John Tobey.  This package is distributed
under the same license as Perl itself.  There is no expressed or implied
warranty, since it is free software.  See the file README in the top level
Perl source directory for details.  The Perl source may be found at:

     http://www.perl.com/CPAN/src/5.0/

AUTHOR
======

   John Tobey, jtobey@john-edwin-tobey.org

SEE ALSO
========

   `perl(1)' in this node, `perlfunc(1)' in this node (for pack),
`perlref(1)' in this node, `sigtrap(3)' in this node, `DynaLoader(3)' in
this node, `perlxs(1)' in this node, `perlcall(1)' in this node.

Tool for handling the C `struct' data type
******************************************

NAME
====

   C::DynaLib::Struct - Tool for handling the C `struct' data type

SYNOPSIS
========

     use C::DynaLib::Struct;

     Define C::DynaLib::Struct(
     	$struct_tag,
     	$template0, \@field_names0,
     	[$template1, \@field_names1,]
     	... );

     $rstruct = tie( $struct, $struct_tag [, @initializer_list] );
     $value = $rstruct->my_field();
     $rstruct->my_field( $new_value );

     $pointer_to_struct = pack( 'p', $struct );
     $struct = $new_struct;  # assigns all fields at once

     # after passing pointer-to-struct to a C function:
     $rstruct->Unpack();
     $returned_value = $rstruct->my_field();

DESCRIPTION
===========

   When mixing Perl and C, the conversion of data types can be rather
tedious and error-prone.  This module provides an abstraction from Perl's
pack and unpack operators for using structures whose member data types and
positions do not change.

   Here are some examples of C code that deals with a `struct'.  On the
right are some possible Perl equivalents.

     C				Perl
     -				----
     typedef struct {		use C::DynaLib::Struct;
     	int	m_int;		Define C::DynaLib::Struct(
     	double	m_double;	    'Foo',
     	char *	m_string;	    'i' => ['m_int'],
     } Foo;			    'd' => ['m_double'],
     				    'p' => ['m_string'] );
     				# or, equivalently,
     				Define C::DynaLib::Struct('Foo',
     				    'idp', [qw(m_int m_double m_string)]);

     Foo foo;
     Foo *pfoo = &foo;		$rfoo = tie ($foo, 'Foo');

     i = pfoo->m_int;		$i = $rfoo->m_int;

     d = foo.m_double;		$d = (tied $foo)->m_double;

     pfoo->m_string = "hi";	$rfoo->m_string("hi");

     Foo bar;			tie ($bar, 'Foo');
     bar = foo;			$bar = $foo;

     void do_foo(Foo *arg);	use C::DynaLib;
     				$lib = new C::DynaLib("-lfoo");
     				$do_foo = $lib->DeclareSub("do_foo","","P");
     				# or you could write an XSUB.

     do_foo(&foo);		&$do_foo($foo);

     returned_i = foo.m_int;	$rfoo->Unpack();
     				$returned_i = $rfoo->m_int;

BUGS
====

   Data member access is through autoloaded methods, so actual existing
methods are not allowed as structure member names.  Currently, the illegal
names are AUTOLOAD, TIESCALAR, FETCH, STORE, and Unpack.

   The names of Structs themselves must be allowable package names.  Using
an existing package name will cause problems.

   `struct's mean different things to different C compilers on different
machines.  Use caution when assigning pack codes to C data types.

SEE ALSO
========

   perlfunc(1) (for pack), perlref(1), perltie(1).

scan C language files for easily recognized constructs.
*******************************************************

NAME
====

   C::Scan - scan C language files for easily recognized constructs.

SYNOPSIS
========

     $c = new C::Scan 'filename' => $filename, 'filename_filter' => $filter,
                      'add_cppflags' => $addflags;
     $c->set('includeDirs' => [$Config::Config{shrpdir}]);

     my $fdec = $c->get('parsed_fdecls');

DESCRIPTION
===========

   *This description is *VERY* incomplete.*

   This module uses `Data::Flow' interface, thus one uses it in the
following fashion:

     $c = new C::Scan(attr1 => $value1, attr2 => $value2);
     $c->set( attr3 => $value3 );

     $value4 = $c->get('attr4');

   Attributes are depending on some other attributes. The only required
attribute, i.e., the attribute which should be set, is filename, which
denotes which file to parse.

   All other attributes are either optional, or would be calculated basing
on values of required and optional attributes.

Output attributes
-----------------

`includes'
     Value: reference to a list of included files.

`defines_args'
     Value: reference to hash of macros with arguments. The values are
     references to an array of length 2, the first element is a reference
     to the list of arguments, the second one being the expansion.
     Newlines are not unescaped, thus

          #define C(x,y) E\
                         F

     will finish with `("C" => [ ["x", "y"], "E\nF"])'.

`defines_no_args'
     Value: reference to hash of macros without arguments.  Newlines are
     not escaped, thus

          #define A B

     will finish with `("A" => "B")'.

`fdecls'
     Value: reference to list of declarations of functions.

`inlines'
     Value: reference to list of definitions of functions.

`parsed_fdecls'
     Value: reference to list of parsed declarations of functions.

     A parsed declaration is a reference to a list of `(rt, nm, args, ft,
     mod)'. Here rt is return type of a function, `nm' is the name, args
     is the list of arguments, `ft' is the full text of the declaration,
     and mod is the modifier (which is always undef).

     Each entry in the list args is of the same form `(ty, nm, args, ft,
     mod)', here `ty' is the type of an argument, `nm' is the name (a
     generated one if missing in the declaration), args is undef, and mod
     is the string of array modifiers.

`typedef_hash'
     Value: a reference to a hash which contains known `typedef's as keys.
     Values of the hash are array references of length 2, with what should
     be put before/after the type for a standalone typedef declaration (but
     without the `typedef' substring).

     Parse uses naive heuristics.

`typedef_texts'
     Value: a reference to a list which contains known expansions of
     `typedef's.

`typedefs_maybe'
     Value: a reference to a list of `typedef'ed names.  Heuristics are
     used.

`vdecls'
     Value: a reference to a list of `extern' variable declarations.

`vdecl_hash'
     Value: a reference to a hash of parsed `extern' variable declarations,
     containing the variable names as keys. Values of the hash are array
     references of length 2, with what should be put before/after the name
     for a standalone extern variable declaration (but without the `extern'
     substring).

`typedef_structs'
     Value: a reference to a hash of parsed struct declarations from
     typedefs.  Keys are typedefed names, values are undef if not a struct
     or union, else an array reference of definitions of the elements of
     the structure; each definition is itself an array reference of length
     3, consisting of what should be put before/after the name for a
     standalone variable declaration, followed by the name of the element.
     Anonymous structs and unions used within the definitions are given an
     arbitrary name including the string `ANON', and referred to using
     that name.

External C Arrays for Perl (Alpha)
**********************************

NAME
====

   CArray - External C Arrays for Perl (Alpha)

SYNOPSIS
========

     use CArray;
     $dblarr = new CDoubleArray(1000);

     @values = (0..1000);
     $dblarr = new CIntArray(1000,\@values);
     ref $dblarr eq 'CIntArray' and
       $dblarr->set(0,1) and
       $dblarr->get(0) == 1;

     tie (@array, 'CDoubleArray', 1000, \@values);
     print $array[0], join ', ', @dbl[1..20];

DESCRIPTION
===========

   Several XS classes and methods to deal with unstructured continuous C
arrays are provided, for the three basic C-types array of *INT*, *DOUBLE*
and STRING and some aggregate types int[2][], int[3][], int[4][],
double[2][], double[3][] as range checked, tieable arrays.

   This roughly reflects to:

     CArray
         CIntArray               int[]
             CInt2Array          int[][2]
             CInt3Array          int[][3]
             CInt4Array          int[][4]
         CDoubleArray            double[]
             CDouble2Array       double[][2]
             CDouble3Array       double[][3]
         CStringArray            *char[]

   External C arrays limit communication overhead with large simple data
structures, where size or time constraints become serious, optionally
manipulated by external XS modules.  Such as various computional geometry
modules dealing with 10.000 - 200.000 double[3]. Modification is done
in-place and preferably in bulk.

   It might also be easier to write XSUBs by converting the data to
CArray's before, pass this pointer to the C func, and handle the results
in Perl then.

   The Fetch/Store operations with tied arrays copy the scalars to perl
and back, so it shouldn't be abused for BIG data.

   Perl's safemalloc/safefree is used.

CLASS METHODS
=============

new ( SIZE, [ ARRAYREF ] )
     The new method is provided for all classes, the optional arrayref arg
     applies only to the base Array classes, not the aggregate.

     The constructor creates a new `CArray' object. For the Array classes
     the second optional argument is used to initialize it with an array.
     If the provided arrayref is shorter that the allocated size, the rest
     will stay uninitialized.

          $D = new CDoubleArray(1000,[0..999]);

init ( values )
     A seperate init method for bulk definitions. (fill)

     This is the same as the second new argument.  If the provided values
     arrayref is shorter that the allocated size, the rest will stay
     uninitialized.

          $I = CIntArray::new(100) ;
          $I->init( [0..99] );

len ()
     The len method returns the length of the array, 1+ the index of the
     last element. To enlarge the array grow() should be used.

          $D  = new CDoubleArray(5000);
          for my $j (0 .. $D->len-1) { $D->set($_, 0.0)); }
          $D->len; # => 5000

get ( index )
     get returns the value at the given index, which will be scalar or a
     list.  Croaks with "index out of range" on wrong index.

          $I = new CIntArray(2,[0,1]);
          print $I->get(1); # => 1
          print $I->get(2);
            => croak "index out of range"

          $I2 = new CInt2Array(2,[[0,1]]);
          print $I->get(0); # => (0 1)

set ( index, value )
     The set method is provided for all classes.  It changes the value at
     the given index.  The value should be either a scalar or an arrayref.
     Croaks with "index out of range" on wrong index.  Returns nothing.

          $I = new CIntArray(100);
          map { $I->set($_,$i[$_]) } (0..99);
          $I->set(99,-1);
          $I->set(100);
            => "index out of range"

          $I2 = CInt2Array->new(2);
          $I2->set(0, [1,0]);
          $I2->set(1, [0,1]);

list ()
     Returns the content of the flat array representation as arrayref.

grow ( n )
     Adds room for n elements to the array. These elements must be
     initialized extra with set.  To support faster grow() a certain
     number of already pre-allocated items at the end of the array will be
     used. (see free) Returns nothing.

delete ( index )
     Deletes the item at the given index. free is incremented and the
     remaining array items are shifted. Returns nothing.

get_grouped_by ( size, index )
     Returns a list of subsequent values.  It returns a list of size
     indices starting at size * index.  This is useful to abuse the
     unstructured array as typed array of the same type, such as
     *double[3] or *int[2].

     But this is normally not used since fast get methods are provided for
     the sequential classes, and those methods can be used on flat arrays
     as well.  (Internally all sequential arrays are flat).

          CInt3Array::get($I,0) == $I->get_grouped_by(3,0)

     $ptr->get_grouped_by(2,4) returns the 4-th pair if the array is seen
     as list of pairs.

          $ptr->get_grouped_by(3,$i) => (ptr[i*3] ptr[i*3+1] ptr[i*3+2] )

slice ( start, size, [ stride=1 ] )
     C++ like slice operator on a flat array. - In contrast to
     get_grouped_by() which semantics are as on a grouped array.

     Returns a list of size items, starting at start, with interim offsets
     of stride which defaults to 1.  This is useful to return columns or
     rows of a flat matrix.

          $I = new CIntArray (9, [0..8]);
          $I->slice ( 0, 3, 3 ); # 1st column
            => (0 3 6)
          $I->slice ( 0, 3, 1 ); # 1st row
            => (0 1 2)
          $I->get_grouped_by(3, 0);
            => (0 1 2)

isort ()
     "Indirect sort", numerically ascending only.  Returns a fresh sorted
     index list of integers (0 .. len-1)

nreverse ()
     "Reverse in place". (The name comes from lisp, where n denotes the
     destructive version).  Destructively swaps all array items. Returns
     nothing.

SEQUENTIAL CLASSES and CONVERSION
=================================

   To mix and change parallel and sequential data structures, the aggregate
(ie sequential) types are derived from their base classes with fast get
and set methods to return and accept lists instead of scalars.

   The Arrays for Int2, Int3, Int4, Double2 and Double3 can also be
converted from and to their base objects with fast XS methods.

     # three parallel CIntArray's
     $X = new CIntArray(1000);
     $Y = new CIntArray(1000);
     $Z = new CIntArray(1000);

     # copy to one sequential *int[3], new memory
     $I = $X->ToInt3($Y,$Z);

     # or to an existing array
     $I = new CIntArray(3000);
     $I = $X->ToInt3($Y,$Z,$I);

     # copies back with allocating new memory
     ($X, $Y, $Z) = $I->ToPar();

     # copies back with reusing some existing memory (not checked!)
     ($X, $Y, $Z) = $I->ToPar($X,$Z);  # Note: I3 will be fresh.

ToPar ( SeqArray, [ CArray,... ] )
     This returns a list of CArray objects, copied from the sequential
     object to plain parallel CArray objects. This is a fast slice.

          *int[2] => (*int, *int)

          CInt2Array::ToPar
          CInt3Array::ToPar
          CInt4Array::ToPar
          CDouble2Array::ToPar
          CDouble3Array::ToPar

     If the optional CArray args are given the memory for the returned
     objects are not new allocated, the space from the given objects is
     used instead.

To$Type$Num ( CArray, ..., [ CArray ] )
     This returns a sequential CArray object copied from the parallel
     objects given as arguments to one sequential CArray. This is a fast
     map.

          *int, *int => *int[2]

          CIntArray::ToInt2
          CIntArray::ToInt3
          CIntArray::ToInt4
          CDoubleArray::ToDouble2
          CDoubleArray::ToDouble3

     If the last optional CArray arg is defined the memory for the returned
     object is not new allocated, the space from the given object is used
     instead.

INTERNAL METHODS
================

DESTROY ()
     This used to crash on certain DEBUGGING perl's, but seems to be okay
     now.  Returns nothing.

CArray::itemsize ( )
CStringArray::itemsize ( [index] )
     Returns the size in bytes per item stored in the array. This is only
     used internally to optimize memory allocation and the free list.

     A CStringArray object accepts the optional index argument, which
     returns the string length at the given index. Without argument it
     returns the size in bytes of a char * pointer (which is 4 on 32 bit
     systems).

copy ()
     Returns a freshly allocated copy of the array with the same contents.

free ()
     Internal only.  Returns the number of free elements at the end of the
     array.  If grow() needs less or equal than free elements to be added,
     no new room will be allocated.

     This is primarly for performance measures.

TIEARRAY METHODS
================

   *Not tested yet!*

tie (var, type, size)
     After tying a array variable to an `CArray' class the variable can be
     used just as any normal perl array.

          tie (@array, 'CDoubleArray', 200);
          print $array[200];
            => croak "index out of range"

SEE ALSO
========

   http://xarch.tu-graz.ac.at/home/rurban/software/perl or
ftp://xarch.tu-graz.ac.at/pub/autocad/urban/perl

   `perlxs(1)' in this node, `tie', see Perlfunc (perl.info),
Tie::Array, Geometry::Points, C::Dynalib::Poke

AUTHOR
======

   Reini Urban <rurban@x-ray.at>

COPYRIGHT
=========

   Copyright (c) 1999 Reini Urban.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

WARNING
=======

   These classes may be easily abused and may lead to system crashes or
worse.

   Old: CPtr objects do no range checking at all, so may unintentionally
access or overwrite foreign memory. This might only crash the system in
the best case.

   Bad malloc'd perls or systems might also lead to destruction.

   The author makes NO WARRANTY, implied or otherwise, about the
suitability of this software for safety or security purposes.

   The author shall not in any case be liable for special, incidental,
consequential, indirect or other similar damages arising from the use of
this software.

   Your mileage will vary. If in any doubt *DO NOT USE IT*. You've been
warned.

BUGS
====

   There are certainly some. Not fully tested yet.  Tests for copy, grow,
delete, tie are pending.  Also some more conversion tests, esp. with
double and degenerate (grow, cut) cases.

  1. realloc() in string_set() with DEBUGGING perl fails sometimes.

  2. An implicit DESTROY invocation sometimes asserts a DEBUGGING perl,
     regardless if PERL_MALLOC or the WinNT msvcrt.dll malloc is used.
     (5.00502 - 5.00558) Esp. on perl shutdown, when freeing the extra
     objects at the second GC.

     This became much better in 0.08 than in previous versions.

        This is alpha, not fully tested yet!

Last Changed
============

   1999/12/05

Perl extension for access to cdb databases
******************************************

NAME
====

   CDB_File - Perl extension for access to cdb databases

SYNOPSIS
========

     use CDB_File;
     tie %h, 'CDB_File', 'file.cdb' or die "tie failed: $!\n";

     $t = new CDB_File ('t.cdb', 't.tmp') or die ...;
     $t->insert('key', 'value');
     $t->finish;

     CDB_File::create %t, $file, "$file.$$";

   or

     use CDB_File 'create';
     create %t, $file, "$file.$$";

DESCRIPTION
===========

   *CDB_File* is a module which provides a Perl interface to Dan
Berstein's *cdb* package:

     cdb is a fast, reliable, lightweight package for creating and
     reading constant databases.

   After the tie shown above, accesses to `%h' will refer to the *cdb*
file `file.cdb', as described in `tie', see Perlfunc (perl.info).

   A *cdb* file is created in three steps.  First call `new CDB_File
($final, $tmp)', where `$final' is the name of the database to be created,
and `$tmp' is the name of a temporary file which can be atomically renamed
to `$final'.  Secondly, call the insert method once for each (key, value)
pair.  Finally, call the finish method to complete the creation and
renaming of the *cdb* file.

   A simpler interface to *cdb* file creation is provided by
`CDB_File::create %t, $final, $tmp'.  This creates a *cdb* file named
`$final' containing the contents of `%t'.  As before,  `$tmp' must name a
temporary file which can be atomically renamed to `$final'.
`CDB_File::create' may be imported.

EXAMPLES
========

   These are all complete programs.

   1. Convert a Berkeley DB (B-tree) database to *cdb* format.

     use CDB_File;
     use DB_File;

     tie %h, DB_File, $ARGV[0], O_RDONLY, undef, $DB_BTREE or
             die "$0: can't tie to $ARGV[0]: $!\n";

     CDB_File::create %h, $ARGV[1], "$ARGV[1].$$" or
             die "$0: can't create cdb: $!\n";

   2. Convert a flat file to *cdb* format.  In this example, the flat file
consists of one key per line, separated by a colon from the value.  Blank
lines and lines beginning with *#* are skipped.

     use CDB_File;

     $cdb = new CDB_File("data.cdb", "data.$$") or
             die "$0: new CDB_File failed: $!\n";
     while (<>) {
             next if /^$/ or /^#/;
             chop;
             ($k, $v) = split /:/, $_, 2;
             if (defined $v) {
                     $cdb->insert($k, $v);
             } else {
                     warn "bogus line: $_\n";
             }
     }
     $cdb->finish or die "$0: CDB_File finish failed: $!\n";

   3. Perl version of *cdbdump*.

     use CDB_File;

     tie %data, 'CDB_File', $ARGV[0] or
             die "$0: can't tie to $ARGV[0]: $!\n";
     while (($k, $v) = each %data) {
             print '+', length $k, ',', length $v, ":$k->$v\n";
     }
     print "\n";

   4. Although a *cdb* file is constant, you can simulate updating it in
Perl.  This is an expensive operation, as you have to create a new
database, and copy into it everything that's unchanged from the old
database.  (As compensation, the update does not affect database readers.
The old database is available for them, till the moment the new one is
finished.)

     use CDB_File;

     $file = 'data.cdb';
     $new = new CDB_File($file, "$file.$$") or
             die "$0: new CDB_File failed: $!\n";

     # Add the new values; remember which keys we've seen.
     while (<>) {
             chop;
             ($k, $v) = split;
             $new->insert($k, $v);
             $seen{$k} = 1;
     }

     # Add any old values that haven't been replaced.
     tie %old, 'CDB_File', $file or die "$0: can't tie to $file: $!\n";
     while (($k, $v) = each %old) {
             $new->insert($k, $v) unless $seen{$k};
     }

     $new->finish or die "$0: CDB_File finish failed: $!\n";

REPEATED KEYS
=============

   Most users can ignore this section.

   A *cdb* file can contain repeated keys.  If the insert method is called
more than once with the same key during the creation of a *cdb* file, that
key will be repeated.

   Here's an example.

     $cdb = new CDB_File ("$file.cdb", "$file.$$") or die ...;
     $cdb->insert('cat', 'gato');
     $cdb->insert('cat', 'chat');
     $cdb->finish;

   Normally, any attempt to access a key retrieves the first value stored
under that key.  This code snippet always prints *gato*.

     $catref = tie %catalogue, CDB_File, "$file.cdb" or die ...;
     print "$catalogue{cat}";

   However, all the usual ways of iterating over a hash--keys, values, and
each--do the Right Thing, even in the presence of repeated keys.  This
code snippet prints *cat cat gato chat*.

     print join(' ', keys %catalogue, values %catalogue);

   And these two both print *cat:gato cat:chat*, although the second is
more efficient.

     foreach $key (keys %catalogue) {
             print "$key:$catalogue{$key} ";
     }

     while (($key, $val) = each %catalogue) {
             print "$key:$val ";
     }

   The `multi_get' method retrieves all the values associated with a key.
It returns a reference to an array containing all the values.  This code
prints *gato chat*.

     print "@{$catref->multi_get('cat')}";

RETURN VALUES
=============

   The routines tie, new, and finish return undef if the attempted
operation failed; $! contains the reason for failure.

DIAGNOSTICS
===========

   The following fatal errors may occur.  (See `eval', see Perlfunc (perl.info),
if you want to trap them.)

Modification of a CDB_File attempted
     You attempted to modify a hash tied to a *CDB_File*.

CDB database too large
     You attempted to create a *cdb* file larger than 4 gigabytes.

[ Write to | Read of | Seek in ] CDB_File failed: <error string>
     If *error string* is *Protocol error*, you tried to `use CDB_File' to
     access something that isn't a *cdb* file.  Otherwise a serious OS
     level problem occurred, for example, you have run out of disk space.

Use CDB_File::FIRSTKEY before CDB_File::NEXTKEY
     If you are using the NEXTKEY method directly (I can't think of a
     reason why you'd want to do this), you need to call FIRSTKEY first.

BUGS
====

   It ain't lightweight after you've plumbed Perl into it.

   The Perl interface to *cdb* imposes the restriction that data must fit
into memory.

SEE ALSO
========

   cdb(3).

AUTHOR
======

   Tim Goodwin, <tjg@star.le.ac.uk>, 1997-01-08 - 2000-05-30.

a high-level interface to the Internet Compact Disc Database
************************************************************

NAME
====

   CDDB.pm - a high-level interface to the Internet Compact Disc Database

SYNOPSIS
========

     use CDDB;

     ### connect to the CDDB server
     my $cddb = new CDDB( Host  => 'www.cddb.com',         # default
                          Port  => 8880,                   # default
                          Login => $login_id,              # defaults to %ENV's
                        ) or die $!;

     ### retrieve known genres
     my @genres = $cddb->get_genres();

     ### calculate CDDB ID based on MSF info
     my @toc = ( '1    0  2 37',           # track, CD-i MSF (space-delimited)
                 '999  1 38 17',           # lead-out track MSF
                 '1000 0  0 Error!',       # error track (don't include if ok)
               );
     my ($cddb_id,       # used for further CDDB queries
         $track_numbers, # padded with 0's provided as a convenience
         $track_lengths, # length of each track, in MM:SS format
         $track_offsets, # absolute offsets (used for further CDDB queries)
         $total_seconds  # total play time, in MM:SS format
        ) = $cddb->calculate_id(@toc);

     ### query discs based on CDDB ID and other information
     my @discs = $cddb->get_discs($cddb_id, $track_offsets, $total_seconds);
     foreach my $disc (@discs) {
       my ($genre, $cddb_id, $title) = @$disc;
     }

     ### query disc details (usually done with get_discs() information)
     my $disc_info     = $cddb->get_disc_details($genre, $cddb_id);
     my $disc_time     = $disc_info->{'disc length'};
     my $disc_id       = $disc_info->{discid};
     my $disc_title    = $disc_info->{dtitle};
     my @track_offsets = @{$disc_info->{offsets}};
     my @track_titles  = @{$disc_info->{ttitles}};
     # other information may be returned... explore!

     ### submit a disc (via e-mail, requires MailTools)
     $cddb->submit_disc
       ( Genre       => 'classical',
         Id          => 'b811a20c',
         Artist      => 'Various',
         DiscTitle   => 'Cartoon Classics',
         Offsets     => $disc_info->{offsets},   # array reference
         TrackTitles => $disc_info->{ttitles},   # array reference
         From        => 'login@host.domain.etc', # will try to determine
       );

DESCRIPTION
===========

   The CDDB serves compact disc information for programs that need it.
CDDB.pm provides a Perl interface to the CDDB server protocols.  With it,
a Perl program can identify a CD based on its "table of contents" (CD-i
MSF information), list its track titles, and manage track times.

   This information could be useful for generating CD catalogs, naming MP3
files, or even playing CDs in an automated jukebox.

PUBLIC METHODS
==============

new(...)
     Creates a CDDB server interface, returning a handle to it.  This
     interface does not connect to the server until needed, and the CDDB
     protocol may require several separate connections (sometimes one per
     query).

     new accepts these parameters: Host (defaults to www.cddb.com), Port
     (defaults to 8880), Login (defaults to your login ID), and Debug
     (defaults to boolean false) parameters.

`get_genres()'
     Takes no parameters.  Returns a list of genres known by the CDDB
     server, or undef if there is an error.

`calculate_id(...)'
     The CDDB protocol defines an ID as a hash of track lengths and the
     number of tracks, with an added checksum. The most basic information
     required to calculate this is the CD table of contents (the CD-i track
     offsets, in MSF [Minutes, Seconds, Frames] format).

     `calculate_id(...)' accepts TOC information as a list of strings.
     Each string contains four fields, separated by whitespace:

       1. The track number, starting with 1.  Special track numbers are
          999, for the CD lead-out information; and 1000, to indicate that
          an error has occurred while acquiring the CD information (error
          tracks modify the meaning of the other fields; look below).

       2. The track start, in minutes (the M in MSF).  If a track starts
          at 01:23 and 5 frames, then this field is 1.  In an error track,
          this field is ignored (but is expected to contain something;
          usually 0).

       3. The track start, in seconds (the S in MSF).  If a track starts
          at 01:23 and 5 frames, then this field is 23.  In an error
          track, this field is ignored (but is expected to contain
          something; usually 0).

       4. The track start, in frames (the F in MSF).  If a track starts at
          01:23 and 5 frames, then this field is 5.  In an error track,
          this field contains an error message (which may contain spaces).

          `calculate_id(...)' returns just the ID in scalar context.  In
     array context, it returns an array containing the following values
     (in the order listed here):

    `$cddb_id'
          This is the hashed CDDB ID, required for any queries involving
          this CD, as well as `submit_disc(...)'.

    `$track_numbers'
          This is a reference to an array containing the track numbers,
          padded to three characters with leading zeroes.  It is provided
          for convenience and is not required by the CDDB.

    `$track_lengths'
          The MSF information provided to `calculate_id(...)' refers to
          track offsets.  This is a reference to an array containing the
          track lengths in MM:SS format, as computed from the MSF offsets.
          This information is provided for convenience and is not
          required by the CDDB.

    `$track_offsets'
          These are absolute frame offsets as calculated by the MSF
          information.  They are required by `get_discs(...)' and
          `submit_disc(...)'.

    `$total_seconds'
          This is the calculated total playing time for the CD.  It is
          required by `get_discs(...)'.

`get_discs(...)'
     `get_discs(...)' asks the CDDB server for all its CDs that match the
     given ID, track offsets list, and total seconds (combined).  The CDDB
     performs "fuzzy" matching and may return more than one disc.

     `get_discs(...)' takes three parameters:

    `$cddb_id'
          This is the CDDB ID, as generated by `calculate_id(...)'.

    `$track_offsets'
          This may be in two formats.

          The first format is a reference to an array of absolute track
          offsets, similar to ones generated by `calculate_id(...)'.

          The second format is a string containing the track count and the
          absolute offsets, separated by whitespace.

    `$total_seconds'
          The total playing time for the CD, as generated by
          `calculate_id(...)'.

     `get_discs(...)' returns an array of matching discs, each of which is
     represented by an array reference.  It returns an empty array if the
     query succeeded but did not match.  It returns undef on error.

     Each disc record contains three elements, two of which can be used
     later on:

    `$genre'
          The genre this disc falls into, as determined by whoever
          submitted the disc in the first place (see `get_genres()').

    `$cddb_id'
          The actual CDDB ID, which may be different than the one supplied
          to `get_discs(...)' due to fuzzy matching.

    `$title'
          The title of this disc.

`get_discs_by_toc(...)'
     This function combines `calculate_id(...)' and `get_discs(...)' into
     one step.  It takes the same parameters as `calculate_id(...)', and
     it returns the same information as `get_discs(...)'.

`get_disc_details(...)'
     This function fetches the detailed information for a CD.  It takes two
     parameters: the disc `$genre' and the `$cddb_id'.

     It returns a hash reference containing as much information as it can.
     The information includes data normally stored in comments.  The most
     common entries this function returns include:

    `'disc length''
          This is the total playing time for the disc, as recorded in the
          CDDB.  Commonly it is in the form "somenumber seconds", but
          since the CDDB stores it in a comment, it could say just about
          anything.

    `'discid''
          This is a rehash (get it?) of the CDDB ID, and should match the
          `$cddb_id' parameter to `get_disc_details(...)'.

    `'dtitle''
          This is the disc title, again.

    `'offsets''
          This is a reference to an array of absolute disc track offsets,
          in CD frames.

    `'ttitles''
          This is a reference to an array of track titles.  These are the
          droids you are looking for.

    `'processed by''
          This is a comment field, identifying the CDDB server name and
          version.

    `'revision''
          This is the version number for the CD record.  Revisions start
          at 1 and are incremented for every correction.  It is the
          responsibility of the submitter to provide a correct revision
          number, as sort of a sanity check.

    `'submitted via'' is the name and version of the software that submitted this CDDB record.  The main intention is to identify records that are submitted by broken software so they can be purged or corrected.
`can_submit_disc()'
     Returns boolean true or false.  If true, CDDB.pm was able to import
     the MailTools it needs to send submissions.  If false, it didn't, and
     you'll need to install at least Mail::Internet and Mail::Header (and
     the underlying Net::SMTP, etc.).

`submit_disc(...)'
     `submit_disc(...)' submits a disc record to the CDDB.  The CDDB
     accepts disc submissions through e-mail, so this function requires
     MailTools to operate.  The rest of CDDB.pm will operate without
     MailTools being installed (since CDDB submissions are relatively
     rare), but `submit_disc(...)' will croak if MailTools are not
     installed.

     `submit_disc(...)' takes six required parameters and two optional
     parameters.  The parameters are in pairs, like `Parameter =' $value>,
     and can appear in any order.  Here goes:

    'Genre'
          This is the disc genre.  It must be one of the genres that the
          server knows (see `get_genres()').

    'Id'
          This is the CDDB ID, as calculated from `calculate_id(...)'.

    'Artist'
          This is the disc artist, gleaned from the CD liner, and entered
          by a human.

    'DiscTitle'
          This is the disc title, gleaned from the CD liner, and entered
          by a human.

    'Offsets'
          This is a reference to an array of absolute track offsets, as
          provided by `calculate_id(...)'.

    'TrackTitles'
          This is a reference to an array of track titles, gleaned from
          the CD liner, and entered by a human.

    'From'
          This is the disc submitter's e-mail address.  It is not
          required, and will default to the current user's login ID at the
          current machine.  The CDDB will send this person a return
          receipt, including the full headers and body of the submitted
          e-mail.

          The default return address may not be a deliverable address,
          especially if CDDB.pm is being used on a dial-up machine that
          isn't running its own MTA.  If the current machine has its own
          MTA, problems still may occur if the machine's Internet address
          changes.

    'Host'
          This is the SMTP host to contact when sending mail.  It is not
          required, and if omitted will default to the `SMTPHOSTS'
          environment variable.  If `SMTPHOSTS' is not defined, it will
          fall back to 'mail'.  If 'mail' is not a machine running an SMTP
          daemon, then `submit_disc(...)' will croak.

PRIVATE METHODS
===============

   Documented as being not documented.

EXAMPLES
========

   Please see the cddb.t program in the t (tests) directory.  It exercises
every aspect of CDDB.pm.

BUGS
====

   There are no known bugs, but see the README for things that need to be
done.

CONTACT AND COPYRIGHT
=====================

   Copyright 1998 Rocco Caputo <troc@netrus.net>.  All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Read the CDDB entry for an audio CD in your drive
*************************************************

NAME
====

   CDDB - Read the CDDB entry for an audio CD in your drive

SYNOPSIS
========

     use CDDB;

     my %config;

     # following variables just need to be declared if different from defaults

     $config{CDDB_HOST}="freedb.freedb.org";	# set cddb host
     $config{CDDB_PORT}=888;			# set cddb port
     $config{CD_DEVICE}="/dev/cdrom";		# set cd device

     # user interaction welcome?

     $config{input}=1;   # 1: ask user if more than one possibility
            	    # 0: no user interaction

     # get it on

     my %cd=get_cddb(\%config);

     unless(defined $cd{title}) {
       die "no cddb entry found";
     }

     # do somthing with the results

     print "artist: $cd{artist}\n";
     print "title: $cd{title}\n";
     print "category: $cd{cat}\n";
     print "cddbid: $cd{id}\n";
     print "trackno: $cd{tno}\n";

     my $n=1;
     foreach my $i ( @{$cd{track}} ) {
       print "track $n: $i\n";
       $n++;
     }

DESCRIPTION
===========

   This module/script gets the CDDB info for an audio cd. You need LINUX,
a cdrom drive and an active internet connection in order to do that.

LICENSE
=======

   This library is released under the same conditions as Perl, that is,
either of the following:

   a) the GNU General Public License as published by the Free Software
Foundation; either version 1, or (at your option) any later version.

   b) the Artistic License.

   If you use this library in a commercial enterprise, you are invited,
but not required, to pay what you feel is a reasonable fee to the author,
who can be contacted at armin@xos.net

AUTHOR
======

   Armin Obersteiner, armin@xos.net

SEE ALSO
========

   perl(1), <file:/usr/include/linux/cdrom.h>.

Perl extension for using the CFITSIO library
********************************************

NAME
====

   CFITSIO - Perl extension for using the CFITSIO library

SYNOPSIS
========

     use CFITSIO;
     use CFITSIO qw( :longnames );
     use CFITSIO qw( :shortnames );
     use CFITSIO qw( :constants );

DESCRIPTION
===========

   Perl interface to William Pence's CFITSIO subroutine library. For more
information on CFITSIO, see http://heasarc.gsfc.nasa.gov/fitsio.

   This module attempts to provide a wrapper for nearly every CFITSIO
routine, while retaining as much CFITSIO behavior as possible. As such,
one should be aware that it is still somewhat low-level, in the sense that
handing an array which is not the correct size to a routine like
`fits_write_img()' may cause SEGVs.

   My goal is to eventually use these routines to build a more Perl-like
interface to many common tasks such as reading and writing of images and
ASCII and binary tables.

CFITSIO API MAPPING
===================

   CFITSIO.pm allows one to use either the long or short name forms of the
CFITSIO routines. These work by using the exact same form of arguments as
one would find in an equivalent C program.

   There is also an object-oriented API which uses the same function names
as the long-name API, but with the leading "fits_" stripped. To get a
CFITSIO "object" one would call `open_file()', `create_file()' or
`create_template()':

     my $status = 0;
     my $fptr = CFITSIO::open_file($filename,CFITSIO::READONLY(),$status);

     $fptr->read_key_str('NAXIS1',$naxis1,undef,$status);

   Note that the object-oriented forms of function names are only
available for those CFITSIO routines which demand a `fitsfile*' data-type
as the first argument.

All CFITSIO routines, with the exception of `fits_iterate_data()' and `fits_open_memfile()', are available in both long and short name forms (e.g., `fits_read_key' <=> `ffgky'), as well as all constants defined in the `fitsio.h' header file. This raises the possibility of your name space being invaded by nearly 1000 function and constant names.
**********************************************************************************************************************************************************************************************************************************************************************************************************************************************************

NAME SPACE
==========

   All CFITSIO routines, with the exception of `fits_iterate_data()' and
`fits_open_memfile()', are available in both long and short name forms
(e.g., `fits_read_key' <=> `ffgky'), as well as all constants defined in
the `fitsio.h' header file. This raises the possibility of your name space
being invaded by nearly 1000 function and constant names.

   To deal with this situation, CFITSIO.pm makes use of the Exporter
package support for `%EXPORT_TAGS'. You can import the long-named functions
with

     use CFITSIO qw( :longnames );

   and the short-named routines with

     use CFITSIO qw( :shortnames );

   Constants are actually implemented as AUTOLOADed functions, so
`TSTRING', for instance, would be accessed via `CFITSIO::TSTRING()'.
Alternatively you can

     use CFITSIO qw( :constants );

   which would allow you to simply say `TSTRING'.

DATA STORAGE DETAILS
====================

Input Variables
---------------

   If a routine expects an N-dimensional array as input, and you hand it a
reference to a scalar, then CFITSIO.pm simply uses the data in the scalar
which the argument is referencing.  Otherwise it expects the argument to
be a Perl array reference whose total number of elements satisfies the
input demands of the corresponding C routine. CFITSIO.pm then unpacks the
array reference into a format that the C routine can understand. If your
input array does not hold enough data for the C routine then a segfault is
likely to occur.

   CFITSIO functions which take an optional NULL pointer - indicating no
output in that place is desired - can instead be given an undef. In other
words, the following C and Perl statements which read a keyword but ignore
the comment would be roughly equivalent:

     fits_read_key_lng(fptr,key,&value,NULL,&status);

     fits_read_key_lng($fptr,$key,$value,undef,$status);

Output Variables
----------------

   Calling CFITSIO routines which read data from FITS files causes the
output variable to be transformed into a Perl array of the appropriate
dimensions.  The exception to this is if one wants the output to be in the
machine-native format (e.g., for use with PDL). In this case you can use
the routine `PerlyUnpacking(0)'.  Then all output variables will become
scalars containing the appropriate data. The exception here is with
routines which read arrays of strings (e.g., `fits_read_col_str()').  In
this case the output is again a Perl array reference.

EXAMPLES
========

   Take a look at `testprog/testprog.pl' under the distribution directory.
It should produce output identical to `testprog.c' which comes with the
CFITSIO library. Additionally, the versions named `testprog_longnames.pl',
`testprog_OO.pl'  and `testprog_pdl.pl' test the long-name and
object-oriented APIs, and machine-native unpacking with PDL.

   There is also an `examples/' directory with scripts which do the
following:

`image_read.pl'
     reads a FITS primary image and displays it using PGPLOT

`image_read_pdl.pl'
     same as above, but uses machine-native unpacking with PDL

`bintable_read_pdl.pl'
     reads binary table column into PDL object, makes histogram and plots
     it

CONSIDERATIONS
==============

Ensure your input arrays contain enough data
     The caller is responsible for ensuring that the input arrays given to
     CFITSIO routines are large enough to satisfy the access demands of
     said routines. For example, if you tell `fits_write_col()' to write a
     data column containing 100 elements, your Perl array should contain
     at least 100 elements. Segfaults abound, so beware!

maxdim semantics
     Some CFITSIO routines take a parameter named something like 'maxdim',
     indicating that no more than that many elements should be placed into
     the output data area. An example of this would be `fits_read_tdim()'.
     In these cases CFITSIO.pm will automatically determine how much
     storage space is needed for the full amount of output possible. As a
     result, the arguments expected in CFITSIO.pm are slightly different
     than one would use in a C program, in that the 'maxdim' argument is
     unnecessary.

     Currently the routines for which this is the case are
     `fits_read_atblhdr()', `fits_read_btblhdr()', `fits_read_imghdr()',
     `fits_decode_tdim()', `fits_read_tdim()' `fits_test_expr()',
     `fits_get_img_parm()' and `fits_get_img_size()'.

Output arrays remain as undisturbed as possible
     For routines like `fits_read_col()', CFITSIO.pm unpacks the output
     into a Perl array reference (unless `PerlyUnpacking(0)' has been
     called, of course). Prior to doing this, it ensures the scalar passed
     is a reference to an array large enough to hold the data. If the
     argument is an array reference which is too small, it expands the
     array pointed to appropriately. *But*, if the array is large enough
     already, the data are just unpacked into the array. The upshot: If
     you call `fits_read_col()', telling it to read 100 data elements, and
     the array you are placing the data into already has 200 elements,
     then after `fits_read_col()' returns your array will still have 200
     elements, only the first 100 of which actually correspond to the data
     read by the routine.

     In more succinct language:

          @output = (0..199);
          fits_read_col_lng($fptr,2,1,1,100,0,\@output,$anynul,$status);

          # @output still has 200 elements, only first 100 are from FITS
          # file

EXTRA COMMANDS
==============

   Some extra commands that use sets of CFITSIO routines are supplied to
simplify some standard tasks:

fits_read_header(filename)
     This command reads in a primary fits header (unless one is using the
     extended filename sytax to move to a different HDU on open) from the
     specified filename and returns the header as a hash reference and a
     status (when called in an array context) or simply a hash reference
     (when called in a scalar context):

          ($hash_ref, $status) = fits_read_header ($file);
          $hash_ref = fits_read_header($file);

     An object-oriented interface is also provided for reading headers from
     FITS files that have already been opened. In this case, the header
     read is from the current HDU.

          $fitsfile = CFITSIO::open_file($file);
          $hash_ref = $fitsfile->read_header;
          ($hash_ref, $status) = $fitsfile->read_header;

sizeof_datatype(datatype)
     Returns the size of the given CFITSIO datatype constant (e.g.,
     `CFITSIO::TSHORT()').

BUGS
====

   FIXME

AUTHOR
======

   Pete Ratzlaff <pratzlaff@cfa.harvard.edu>, with a great deal of code
taken from Karl Glazebrook's PGPLOT module.

   Contributors include:

Tim Jenness <t.jenness@jach.hawaii.edu>
     convenience routines

Tim Conrow <tim@ipac.caltech.edu>
     function implementations, bug fixes

Simple Common Gateway Interface Class
*************************************

NAME
====

   CGI - Simple Common Gateway Interface Class

SYNOPSIS
========

     # CGI script that creates a fill-out form
     # and echoes back its values.

     use CGI qw/:standard/;
     print header,
           start_html('A Simple Example'),
           h1('A Simple Example'),
           start_form,
           "What's your name? ",textfield('name'),p,
           "What's the combination?", p,
           checkbox_group(-name=>'words',
     		       -values=>['eenie','meenie','minie','moe'],
     		       -defaults=>['eenie','minie']), p,
           "What's your favorite color? ",
           popup_menu(-name=>'color',
     	           -values=>['red','green','blue','chartreuse']),p,
           submit,
           end_form,
           hr;

     if (param()) {
         print "Your name is",em(param('name')),p,
     	     "The keywords are: ",em(join(", ",param('words'))),p,
     	     "Your favorite color is ",em(param('color')),
     	     hr;
     }

ABSTRACT
========

   This perl library uses perl5 objects to make it easy to create Web
fill-out forms and parse their contents.  This package defines CGI
objects, entities that contain the values of the current query string and
other state variables.  Using a CGI object's methods, you can examine
keywords and parameters passed to your script, and create forms whose
initial values are taken from the current query (thereby preserving state
information).  The module provides shortcut functions that produce
boilerplate HTML, reducing typing and coding errors. It also provides
functionality for some of the more advanced features of CGI scripting,
including support for file uploads, cookies, cascading style sheets,
server push, and frames.

   CGI.pm also provides a simple function-oriented programming style for
those who don't need its object-oriented features.

   The current version of CGI.pm is available at

     http://www.genome.wi.mit.edu/ftp/pub/software/WWW/cgi_docs.html
     ftp://ftp-genome.wi.mit.edu/pub/software/WWW/

DESCRIPTION
===========

PROGRAMMING STYLE
-----------------

   There are two styles of programming with CGI.pm, an object-oriented
style and a function-oriented style.  In the object-oriented style you
create one or more CGI objects and then use object methods to create the
various elements of the page.  Each CGI object starts out with the list of
named parameters that were passed to your CGI script by the server.  You
can modify the objects, save them to a file or database and recreate them.
Because each object corresponds to the "state" of the CGI script, and
because each object's parameter list is independent of the others, this
allows you to save the state of the script and restore it later.

   For example, using the object oriented style, here is how you create a
simple "Hello World" HTML page:

     #!/usr/local/bin/perl -w
     use CGI;                             # load CGI routines
     $q = new CGI;                        # create new CGI object
     print $q->header,                    # create the HTTP header
           $q->start_html('hello world'), # start the HTML
           $q->h1('hello world'),         # level 1 header
           $q->end_html;                  # end the HTML

   In the function-oriented style, there is one default CGI object that
you rarely deal with directly.  Instead you just call functions to
retrieve CGI parameters, create HTML tags, manage cookies, and so on.
This provides you with a cleaner programming interface, but limits you to
using one CGI object at a time.  The following example prints the same
page, but uses the function-oriented interface.  The main differences are
that we now need to import a set of functions into our name space (usually
the "standard" functions), and we don't need to create the CGI object.

     #!/usr/local/bin/perl
     use CGI qw/:standard/;           # load standard CGI routines
     print header,                    # create the HTTP header
           start_html('hello world'), # start the HTML
           h1('hello world'),         # level 1 header
           end_html;                  # end the HTML

   The examples in this document mainly use the object-oriented style.
See HOW TO IMPORT FUNCTIONS for important information on function-oriented
programming in CGI.pm

CALLING CGI.PM ROUTINES
-----------------------

   Most CGI.pm routines accept several arguments, sometimes as many as 20
optional ones!  To simplify this interface, all routines use a named
argument calling style that looks like this:

     print $q->header(-type=>'image/gif',-expires=>'+3d');

   Each argument name is preceded by a dash.  Neither case nor order
matters in the argument list.  -type, -Type, and -TYPE are all acceptable.
In fact, only the first argument needs to begin with a dash.  If a dash
is present in the first argument, CGI.pm assumes dashes for the subsequent
ones.

   Several routines are commonly called with just one argument.  In the
case of these routines you can provide the single argument without an
argument name.  header() happens to be one of these routines.  In this
case, the single argument is the document type.

     print $q->header('text/html');

   Other such routines are documented below.

   Sometimes named arguments expect a scalar, sometimes a reference to an
array, and sometimes a reference to a hash.  Often, you can pass any type
of argument and the routine will do whatever is most appropriate.  For
example, the param() routine is used to set a CGI parameter to a single or
a multi-valued value.  The two cases are shown below:

     $q->param(-name=>'veggie',-value=>'tomato');
     $q->param(-name=>'veggie',-value=>['tomato','tomahto','potato','potahto']);

   A large number of routines in CGI.pm actually aren't specifically
defined in the module, but are generated automatically as needed.  These
are the "HTML shortcuts," routines that generate HTML tags for use in
dynamically-generated pages.  HTML tags have both attributes (the
attribute="value" pairs within the tag itself) and contents (the part
between the opening and closing pairs.)  To distinguish between attributes
and contents, CGI.pm uses the convention of passing HTML attributes as a
hash reference as the first argument, and the contents, if any, as any
subsequent arguments.  It works out like this:

     Code                           Generated HTML
     ----                           --------------
     h1()                           <H1>
     h1('some','contents');         <H1>some contents</H1>
     h1({-align=>left});            <H1 ALIGN="LEFT">
     h1({-align=>left},'contents'); <H1 ALIGN="LEFT">contents</H1>

   HTML tags are described in more detail later.

   Many newcomers to CGI.pm are puzzled by the difference between the
calling conventions for the HTML shortcuts, which require curly braces
around the HTML tag attributes, and the calling conventions for other
routines, which manage to generate attributes without the curly brackets.
Don't be confused.  As a convenience the curly braces are optional in all
but the HTML shortcuts.  If you like, you can use curly braces when
calling any routine that takes named arguments.  For example:

     print $q->header( {-type=>'image/gif',-expires=>'+3d'} );

   If you use the -w switch, you will be warned that some CGI.pm argument
names conflict with built-in Perl functions.  The most frequent of these
is the -values argument, used to create multi-valued menus, radio button
clusters and the like.  To get around this warning, you have several
choices:

  1. Use another name for the argument, if one is available.  For example,
     -value is an alias for -values.

  2. Change the capitalization, e.g. -Values

  3. Put quotes around the argument name, e.g. '-values'
        Many routines will do something useful with a named argument that
it doesn't recognize.  For example, you can produce non-standard HTTP
header fields by providing them as named arguments:

     print $q->header(-type  =>  'text/html',
                      -cost  =>  'Three smackers',
                      -annoyance_level => 'high',
                      -complaints_to   => 'bit bucket');

   This will produce the following nonstandard HTTP header:

     HTTP/1.0 200 OK
     Cost: Three smackers
     Annoyance-level: high
     Complaints-to: bit bucket
     Content-type: text/html

   Notice the way that underscores are translated automatically into
hyphens.  HTML-generating routines perform a different type of translation.

   This feature allows you to keep up with the rapidly changing HTTP and
HTML "standards".

CREATING A NEW QUERY OBJECT (OBJECT-ORIENTED STYLE):
----------------------------------------------------

     $query = new CGI;

   This will parse the input (from both POST and GET methods) and store it
into a perl5 object called $query.

CREATING A NEW QUERY OBJECT FROM AN INPUT FILE
----------------------------------------------

     $query = new CGI(INPUTFILE);

   If you provide a file handle to the new() method, it will read
parameters from the file (or STDIN, or whatever).  The file can be in any
of the forms describing below under debugging (i.e. a series of newline
delimited TAG=VALUE pairs will work).  Conveniently, this type of file is
created by the save() method (see below).  Multiple records can be saved
and restored.

   Perl purists will be pleased to know that this syntax accepts
references to file handles, or even references to filehandle globs, which
is the "official" way to pass a filehandle:

     $query = new CGI(\*STDIN);

   You can also initialize the CGI object with a FileHandle or IO::File
object.

   If you are using the function-oriented interface and want to initialize
CGI state from a file handle, the way to do this is with
*restore_parameters()*.  This will (re)initialize the default CGI object
from the indicated file handle.

     open (IN,"test.in") || die;
     restore_parameters(IN);
     close IN;

   You can also initialize the query object from an associative array
reference:

     $query = new CGI( {'dinosaur'=>'barney',
     		       'song'=>'I love you',
     		       'friends'=>[qw/Jessica George Nancy/]}
     		    );

   or from a properly formatted, URL-escaped query string:

     $query = new CGI('dinosaur=barney&color=purple');

   or from a previously existing CGI object (currently this clones the
parameter list, but none of the other object-specific fields, such as
autoescaping):

     $old_query = new CGI;
     $new_query = new CGI($old_query);

   To create an empty query, initialize it from an empty string or hash:

     $empty_query = new CGI("");

     -or-

     $empty_query = new CGI({});

FETCHING A LIST OF KEYWORDS FROM THE QUERY:
-------------------------------------------

     @keywords = $query->keywords

   If the script was invoked as the result of an <ISINDEX> search, the
parsed keywords can be obtained as an array using the keywords() method.

FETCHING THE NAMES OF ALL THE PARAMETERS PASSED TO YOUR SCRIPT:
---------------------------------------------------------------

     @names = $query->param

   If the script was invoked with a parameter list (e.g.
"name1=value1&name2=value2&name3=value3"), the param() method will return
the parameter names as a list.  If the script was invoked as an <ISINDEX>
script and contains a string without ampersands (e.g.
"value1+value2+value3") , there will be a single parameter named
"keywords" containing the "+"-delimited keywords.

   NOTE: As of version 1.5, the array of parameter names returned will be
in the same order as they were submitted by the browser.  Usually this
order is the same as the order in which the parameters are defined in the
form (however, this isn't part of the spec, and so isn't guaranteed).

FETCHING THE VALUE OR VALUES OF A SINGLE NAMED PARAMETER:
---------------------------------------------------------

     @values = $query->param('foo');

     -or-

     $value = $query->param('foo');

   Pass the param() method a single argument to fetch the value of the
named parameter. If the parameter is multivalued (e.g. from multiple
selections in a scrolling list), you can ask to receive an array.
Otherwise the method will return a single value.

   If a value is not given in the query string, as in the queries
"name1=&name2=" or "name1&name2", it will be returned as an empty string.
This feature is new in 2.63.

SETTING THE VALUE(S) OF A NAMED PARAMETER:
------------------------------------------

     $query->param('foo','an','array','of','values');

   This sets the value for the named parameter 'foo' to an array of
values.  This is one way to change the value of a field AFTER the script
has been invoked once before.  (Another way is with the -override
parameter accepted by all methods that generate form elements.)

   param() also recognizes a named parameter style of calling described in
more detail later:

     $query->param(-name=>'foo',-values=>['an','array','of','values']);

     -or-

     $query->param(-name=>'foo',-value=>'the value');

APPENDING ADDITIONAL VALUES TO A NAMED PARAMETER:
-------------------------------------------------

     $query->append(-name=>'foo',-values=>['yet','more','values']);

   This adds a value or list of values to the named parameter.  The values
are appended to the end of the parameter if it already exists.  Otherwise
the parameter is created.  Note that this method only recognizes the named
argument calling syntax.

IMPORTING ALL PARAMETERS INTO A NAMESPACE:
------------------------------------------

     $query->import_names('R');

   This creates a series of variables in the 'R' namespace.  For example,
$R::foo, @R:foo.  For keyword lists, a variable @R::keywords will appear.
If no namespace is given, this method will assume 'Q'.  WARNING:  don't
import anything into 'main'; this is a major security risk!!!!

   In older versions, this method was called import().  As of version 2.20,
this name has been removed completely to avoid conflict with the built-in
Perl module import operator.

DELETING A PARAMETER COMPLETELY:
--------------------------------

     $query->delete('foo');

   This completely clears a parameter.  It sometimes useful for resetting
parameters that you don't want passed down between script invocations.

   If you are using the function call interface, use "Delete()" instead to
avoid conflicts with Perl's built-in delete operator.

DELETING ALL PARAMETERS:
------------------------

     $query->delete_all();

   This clears the CGI object completely.  It might be useful to ensure
that all the defaults are taken when you create a fill-out form.

   Use Delete_all() instead if you are using the function call interface.

DIRECT ACCESS TO THE PARAMETER LIST:
------------------------------------

     $q->param_fetch('address')->[1] = '1313 Mockingbird Lane';
     unshift @{$q->param_fetch(-name=>'address')},'George Munster';

   If you need access to the parameter list in a way that isn't covered by
the methods above, you can obtain a direct reference to it by calling the
*param_fetch()* method with the name of the .  This will return an array
reference to the named parameters, which you then can manipulate in any
way you like.

   You can also use a named argument style using the *-name* argument.

FETCHING THE PARAMETER LIST AS A HASH:
--------------------------------------

     $params = $q->Vars;
     print $params->{'address'};
     @foo = split("\0",$params->{'foo'});
     %params = $q->Vars;

     use CGI ':cgi-lib';
     $params = Vars;

   Many people want to fetch the entire parameter list as a hash in which
the keys are the names of the CGI parameters, and the values are the
parameters' values.  The Vars() method does this.  Called in a scalar
context, it returns the parameter list as a tied hash reference.  Changing
a key changes the value of the parameter in the underlying CGI parameter
list.  Called in a list context, it returns the parameter list as an
ordinary hash.  This allows you to read the contents of the parameter
list, but not to change it.

   When using this, the thing you must watch out for are multivalued CGI
parameters.  Because a hash cannot distinguish between scalar and list
context, multivalued parameters will be returned as a packed string,
separated by the "\0" (null) character.  You must split this packed string
in order to get at the individual values.  This is the convention
introduced long ago by Steve Brenner in his cgi-lib.pl module for Perl
version 4.

   If you wish to use Vars() as a function, import the *:cgi-lib* set of
function calls (also see the section on CGI-LIB compatibility).

SAVING THE STATE OF THE SCRIPT TO A FILE:
-----------------------------------------

     $query->save(FILEHANDLE)

   This will write the current state of the form to the provided
filehandle.  You can read it back in by providing a filehandle to the
new() method.  Note that the filehandle can be a file, a pipe, or whatever!

   The format of the saved file is:

     NAME1=VALUE1
     NAME1=VALUE1'
     NAME2=VALUE2
     NAME3=VALUE3
     =

   Both name and value are URL escaped.  Multi-valued CGI parameters are
represented as repeated names.  A session record is delimited by a single
= symbol.  You can write out multiple records and read them back in with
several calls to new.  You can do this across several sessions by opening
the file in append mode, allowing you to create primitive guest books, or
to keep a history of users' queries.  Here's a short example of creating
multiple session records:

     use CGI;

     open (OUT,">>test.out") || die;
     $records = 5;
     foreach (0..$records) {
         my $q = new CGI;
         $q->param(-name=>'counter',-value=>$_);
         $q->save(OUT);
     }
     close OUT;

     # reopen for reading
     open (IN,"test.out") || die;
     while (!eof(IN)) {
         my $q = new CGI(IN);
         print $q->param('counter'),"\n";
     }

   The file format used for save/restore is identical to that used by the
Whitehead Genome Center's data exchange format "Boulderio", and can be
manipulated and even databased using Boulderio utilities.  See

     http://stein.cshl.org/boulder/

   for further details.

   If you wish to use this method from the function-oriented (non-OO)
interface, the exported name for this method is *save_parameters()*.

RETRIEVING CGI ERRORS
---------------------

   Errors can occur while processing user input, particularly when
processing uploaded files.  When these errors occur, CGI will stop
processing and return an empty parameter list.  You can test for the
existence and nature of errors using the *cgi_error()* function.  The
error messages are formatted as HTTP status codes. You can either
incorporate the error text into an HTML page, or use it as the value of
the HTTP status:

     my $error = $q->cgi_error;
     if ($error) {
     	print $q->header(-status=>$error),
     	      $q->start_html('Problems'),
               $q->h2('Request not processed'),
     	      $q->strong($error);
         exit 0;
     }

   When using the function-oriented interface (see the next section),
errors may only occur the first time you call param(). Be ready for this!

USING THE FUNCTION-ORIENTED INTERFACE
-------------------------------------

   To use the function-oriented interface, you must specify which CGI.pm
routines or sets of routines to import into your script's namespace.
There is a small overhead associated with this importation, but it isn't
much.

     use CGI <list of methods>;

   The listed methods will be imported into the current package; you can
call them directly without creating a CGI object first.  This example
shows how to import the param() and header() methods, and then use them
directly:

     use CGI 'param','header';
     print header('text/plain');
     $zipcode = param('zipcode');

   More frequently, you'll import common sets of functions by referring to
the groups by name.  All function sets are preceded with a ":" character
as in ":html3" (for tags defined in the HTML 3 standard).

   Here is a list of the function sets you can import:

:cgi
     Import all CGI-handling methods, such as param(), path_info() and the
     like.

:form
     Import all fill-out form generating methods, such as *textfield()*.

:html2
     Import all methods that generate HTML 2.0 standard elements.

:html3
     Import all methods that generate HTML 3.0 proposed elements (such as
     <table>, <super> and <sub>).

:netscape
     Import all methods that generate Netscape-specific HTML extensions.

:html
     Import all HTML-generating shortcuts (i.e. 'html2' + 'html3' +
     'netscape')...

:standard
     Import "standard" features, 'html2', 'html3', 'form' and 'cgi'.

:all
     Import all the available methods.  For the full list, see the CGI.pm
     code, where the variable %EXPORT_TAGS is defined.

   If you import a function name that is not part of CGI.pm, the module
will treat it as a new HTML tag and generate the appropriate subroutine.
You can then use it like any other HTML tag.  This is to provide for the
rapidly-evolving HTML "standard."  For example, say Microsoft comes out
with a new tag called <GRADIENT> (which causes the user's desktop to be
flooded with a rotating gradient fill until his machine reboots).  You
don't need to wait for a new version of CGI.pm to start using it
immediately:

     use CGI qw/:standard :html3 gradient/;
     print gradient({-start=>'red',-end=>'blue'});

   Note that in the interests of execution speed CGI.pm does not use the
standard Exporter, syntax for specifying load symbols.
This may change in the future.

   If you import any of the state-maintaining CGI or form-generating
methods, a default CGI object will be created and initialized
automatically the first time you use any of the methods that require one
to be present.  This includes param(), *textfield()*, *submit()* and the
like.  (If you need direct access to the CGI object, you can find it in
the global variable *$CGI::Q*).  By importing CGI.pm methods, you can
create visually elegant scripts:

     use CGI qw/:standard/;
     print
         header,
         start_html('Simple Script'),
         h1('Simple Script'),
         start_form,
         "What's your name? ",textfield('name'),p,
         "What's the combination?",
         checkbox_group(-name=>'words',
     		      -values=>['eenie','meenie','minie','moe'],
     		      -defaults=>['eenie','moe']),p,
         "What's your favorite color?",
         popup_menu(-name=>'color',
     		  -values=>['red','green','blue','chartreuse']),p,
         submit,
         end_form,
         hr,"\n";

     if (param) {
        print
     	   "Your name is ",em(param('name')),p,
     	   "The keywords are: ",em(join(", ",param('words'))),p,
     	   "Your favorite color is ",em(param('color')),".\n";
     }
     print end_html;

PRAGMAS
-------

   In addition to the function sets, there are a number of pragmas that
you can import.  Pragmas, which are always preceded by a hyphen, change
the way that CGI.pm functions in various ways.  Pragmas, function sets,
and individual functions can all be imported in the same use() line.  For
example, the following use statement imports the standard set of functions
and enables debugging mode (pragma -debug):

     use CGI qw/:standard -debug/;

   The current list of pragmas is as follows:

-any
     When you *use CGI -any*, then any method that the query object
     doesn't recognize will be interpreted as a new HTML tag.  This allows
     you to support the next *ad hoc* Netscape or Microsoft HTML
     extension.  This lets you go wild with new and unsupported tags:

          use CGI qw(-any);
          $q=new CGI;
          print $q->gradient({speed=>'fast',start=>'red',end=>'blue'});

     Since using <cite>any</cite> causes any mistyped method name to be
     interpreted as an HTML tag, use it with care or not at all.

-compile
     This causes the indicated autoloaded methods to be compiled up front,
     rather than deferred to later.  This is useful for scripts that run
     for an extended period of time under FastCGI or mod_perl, and for
     those destined to be crunched by Malcom Beattie's Perl compiler.  Use
     it in conjunction with the methods or method families you plan to use.

          use CGI qw(-compile :standard :html3);

     or even

          use CGI qw(-compile :all);

     Note that using the -compile pragma in this way will always have the
     effect of importing the compiled functions into the current
     namespace.  If you want to compile without importing use the
     compile() method instead (see below).

-nosticky
     This makes CGI.pm not generating the hidden fields .submit and
     .cgifields. It is very useful if you don't want to have the hidden
     fields appear in the querystring in a GET method.  For example, a
     search script generated this way will have a very nice url with
     search parameters for bookmarking.

-no_xhtml
     By default, CGI.pm versions 2.69 and higher emit XHTML
     (http://www.w3.org/TR/xhtml1/).  The -no_xhtml pragma disables this
     feature.  Thanks to Michalis Kabrianis <kabrianis@hellug.gr> for this
     feature.

-nph
     This makes CGI.pm produce a header appropriate for an NPH (no parsed
     header) script.  You may need to do other things as well to tell the
     server that the script is NPH.  See the discussion of NPH scripts
     below.

-newstyle_urls
     Separate the name=value pairs in CGI parameter query strings with
     semicolons rather than ampersands.  For example:

          ?name=fred;age=24;favorite_color=3

     Semicolon-delimited query strings are always accepted, but will not be
     emitted by self_url() and query_string() unless the -newstyle_urls
     pragma is specified.

     This became the default in version 2.64.

-oldstyle_urls
     Separate the name=value pairs in CGI parameter query strings with
     ampersands rather than semicolons.  This is no longer the default.

-autoload
     This overrides the autoloader so that any function in your program
     that is not recognized is referred to CGI.pm for possible evaluation.
     This allows you to use all the CGI.pm functions without adding them to
     your symbol table, which is of concern for mod_perl users who are
     worried about memory consumption.  Warning: when *-autoload* is in
     effect, you cannot use "poetry mode" (functions without the
     parenthesis).  Use *hr()* rather than *hr*, or add something like
     *use subs qw/hr p header/* to the top of your script.

-no_debug
     This turns off the command-line processing features.  If you want to
     run a CGI.pm script from the command line to produce HTML, and you
     don't want it to read CGI parameters from the command line or STDIN,
     then use this pragma:

          use CGI qw(-no_debug :standard);

-debug
     This turns on full debugging.  In addition to reading CGI arguments
     from the command-line processing, CGI.pm will pause and try to read
     arguments from STDIN, producing the message "(offline mode: enter
     name=value pairs on standard input)" features.

     See the section on debugging for more details.

-private_tempfiles
     CGI.pm can process uploaded file. Ordinarily it spools the uploaded
     file to a temporary directory, then deletes the file when done.
     However, this opens the risk of eavesdropping as described in the file
     upload section.  Another CGI script author could peek at this data
     during the upload, even if it is confidential information. On Unix
     systems, the -private_tempfiles pragma will cause the temporary file
     to be unlinked as soon as it is opened and before any data is written
     into it, reducing, but not eliminating the risk of eavesdropping
     (there is still a potential race condition).  To make life harder for
     the attacker, the program chooses tempfile names by calculating a 32
     bit checksum of the incoming HTTP headers.

     To ensure that the temporary file cannot be read by other CGI scripts,
     use suEXEC or a CGI wrapper program to run your script.  The temporary
     file is created with mode 0600 (neither world nor group readable).

     The temporary directory is selected using the following algorithm:

          1. if the current user (e.g. "nobody") has a directory named
          "tmp" in its home directory, use that (Unix systems only).

          2. if the environment variable TMPDIR exists, use the location
          indicated.

          3. Otherwise try the locations /usr/tmp, /var/tmp, C:\temp,
          /tmp, /temp, ::Temporary Items, and \WWW_ROOT.

     Each of these locations is checked that it is a directory and is
     writable.  If not, the algorithm tries the next choice.

SPECIAL FORMS FOR IMPORTING HTML-TAG FUNCTIONS
----------------------------------------------

   Many of the methods generate HTML tags.  As described below, tag
functions automatically generate both the opening and closing tags.  For
example:

     print h1('Level 1 Header');

   produces

     <H1>Level 1 Header</H1>

   There will be some times when you want to produce the start and end
tags yourself.  In this case, you can use the form start_*tag_name* and
end_*tag_name*, as in:

     print start_h1,'Level 1 Header',end_h1;

   With a few exceptions (described below), start_*tag_name* and
end_*tag_name* functions are not generated automatically when you *use
CGI*.  However, you can specify the tags you want to generate *start/end*
functions for by putting an asterisk in front of their name, or,
alternatively, requesting either "start_*tag_name*" or "end_*tag_name*" in
the import list.

   Example:

     use CGI qw/:standard *table start_ul/;

   In this example, the following functions are generated in addition to
the standard ones:

  1. start_table() (generates a <TABLE> tag)

  2. end_table() (generates a </TABLE> tag)

  3. start_ul() (generates a <UL> tag)

  4. end_ul() (generates a </UL> tag)

GENERATING DYNAMIC DOCUMENTS
============================

   Most of CGI.pm's functions deal with creating documents on the fly.
Generally you will produce the HTTP header first, followed by the document
itself.  CGI.pm provides functions for generating HTTP headers of various
types as well as for generating HTML.  For creating GIF images, see the
GD.pm module.

   Each of these functions produces a fragment of HTML or HTTP which you
can print out directly so that it displays in the browser window, append
to a string, or save to a file for later use.

CREATING A STANDARD HTTP HEADER:
--------------------------------

   Normally the first thing you will do in any CGI script is print out an
HTTP header.  This tells the browser what type of document to expect, and
gives other optional information, such as the language, expiration date,
and whether to cache the document.  The header can also be manipulated for
special purposes, such as server push and pay per view pages.

     print $query->header;

     -or-

     print $query->header('image/gif');

     -or-

     print $query->header('text/html','204 No response');

     -or-

     print $query->header(-type=>'image/gif',
     		     -nph=>1,
     		     -status=>'402 Payment required',
     		     -expires=>'+3d',
     		     -cookie=>$cookie,
                                  -charset=>'utf-7',
                                  -attachment=>'foo.gif',
     		     -Cost=>'$2.00');

   header() returns the Content-type: header.  You can provide your own
MIME type if you choose, otherwise it defaults to text/html.  An optional
second parameter specifies the status code and a human-readable message.
For example, you can specify 204, "No response" to create a script that
tells the browser to do nothing at all.

   The last example shows the named argument style for passing arguments
to the CGI methods using named parameters.  Recognized parameters are
*-type*, *-status*, *-expires*, and *-cookie*.  Any other named parameters
will be stripped of their initial hyphens and turned into header fields,
allowing you to specify any HTTP header you desire.  Internal underscores
will be turned into hyphens:

     print $query->header(-Content_length=>3002);

   Most browsers will not cache the output from CGI scripts.  Every time
the browser reloads the page, the script is invoked anew.  You can change
this behavior with the *-expires* parameter.  When you specify an absolute
or relative expiration interval with this parameter, some browsers and
proxy servers will cache the script's output until the indicated
expiration date.  The following forms are all valid for the -expires field:

     +30s                              30 seconds from now
     +10m                              ten minutes from now
     +1h                               one hour from now
     -1d                               yesterday (i.e. "ASAP!")
     now                               immediately
     +3M                               in three months
     +10y                              in ten years time
     Thursday, 25-Apr-1999 00:40:33 GMT  at the indicated time & date

   The *-cookie* parameter generates a header that tells the browser to
provide a "magic cookie" during all subsequent transactions with your
script.  Netscape cookies have a special format that includes interesting
attributes such as expiration time.  Use the cookie() method to create and
retrieve session cookies.

   The *-nph* parameter, if set to a true value, will issue the correct
headers to work with a NPH (no-parse-header) script.  This is important to
use with certain servers that expect all their scripts to be NPH.

   The *-charset* parameter can be used to control the character set sent
to the browser.  If not provided, defaults to ISO-8859-1.  As a side
effect, this sets the charset() method as well.

   The *-attachment* parameter can be used to turn the page into an
attachment.  Instead of displaying the page, some browsers will prompt the
user to save it to disk.  The value of the argument is the suggested name
for the saved file.  In order for this to work, you may have to set the
*-type* to "application/octet-stream".

GENERATING A REDIRECTION HEADER
-------------------------------

     print $query->redirect('http://somewhere.else/in/movie/land');

   Sometimes you don't want to produce a document yourself, but simply
redirect the browser elsewhere, perhaps choosing a URL based on the time
of day or the identity of the user.

   The redirect() function redirects the browser to a different URL.  If
you use redirection like this, you should not print out a header as well.

   One hint I can offer is that relative links may not work correctly when
you generate a redirection to another document on your site.  This is due
to a well-intentioned optimization that some servers use.  The solution to
this is to use the full URL (including the http: part) of the document you
are redirecting to.

   You can also use named arguments:

     print $query->redirect(-uri=>'http://somewhere.else/in/movie/land',
     			   -nph=>1);

   The *-nph* parameter, if set to a true value, will issue the correct
headers to work with a NPH (no-parse-header) script.  This is important to
use with certain servers, such as Microsoft Internet Explorer, which
expect all their scripts to be NPH.

CREATING THE HTML DOCUMENT HEADER
---------------------------------

     print $query->start_html(-title=>'Secrets of the Pyramids',
     			    -author=>'fred@capricorn.org',
     			    -base=>'true',
     			    -target=>'_blank',
     			    -meta=>{'keywords'=>'pharaoh secret mummy',
     				    'copyright'=>'copyright 1996 King Tut'},
     			    -style=>{'src'=>'/styles/style1.css'},
     			    -BGCOLOR=>'blue');

   After creating the HTTP header, most CGI scripts will start writing out
an HTML document.  The start_html() routine creates the top of the page,
along with a lot of optional information that controls the page's
appearance and behavior.

   This method returns a canned HTML header and the opening <BODY> tag.
All parameters are optional.  In the named parameter form, recognized
parameters are -title, -author, -base, -xbase, -dtd, -lang and -target
(see below for the explanation).  Any additional parameters you provide,
such as the Netscape unofficial BGCOLOR attribute, are added to the <BODY>
tag.  Additional parameters must be proceeded by a hyphen.

   The argument *-xbase* allows you to provide an HREF for the <BASE> tag
different from the current location, as in

     -xbase=>"http://home.mcom.com/"

   All relative links will be interpreted relative to this tag.

   The argument *-target* allows you to provide a default target frame for
all the links and fill-out forms on the page.  *This is a non-standard
HTTP feature which only works with Netscape browsers!* See the Netscape
documentation on frames for details of how to manipulate this.

     -target=>"answer_window"

   All relative links will be interpreted relative to this tag.  You add
arbitrary meta information to the header with the *-meta* argument.  This
argument expects a reference to an associative array containing name/value
pairs of meta information.  These will be turned into a series of header
<META> tags that look something like this:

     <META NAME="keywords" CONTENT="pharaoh secret mummy">
     <META NAME="description" CONTENT="copyright 1996 King Tut">

   To create an HTTP-EQUIV type of <META> tag, use *-head*, described
below.

   The *-style* argument is used to incorporate cascading stylesheets into
your code.  See the section on CASCADING STYLESHEETS for more information.

   The *-lang* argument is used to incorporate a language attribute into
the <HTML> tag.  The default if not specified is "en-US" for US English.
For example:

     print $q->start_html(-lang=>'fr-CA');

   You can place other arbitrary HTML elements to the <HEAD> section with
the *-head* tag.  For example, to place the rarely-used <LINK> element in
the head section, use this:

     print start_html(-head=>Link({-rel=>'next',
     		                  -href=>'http://www.capricorn.com/s2.html'}));

   To incorporate multiple HTML elements into the <HEAD> section, just
pass an array reference:

     print start_html(-head=>[
                              Link({-rel=>'next',
     				   -href=>'http://www.capricorn.com/s2.html'}),
     		             Link({-rel=>'previous',
     				   -href=>'http://www.capricorn.com/s1.html'})
     			     ]
     		     );

   And here's how to create an HTTP-EQUIV <META> tag:

     print start_html(-head=>meta({-http_equiv => 'Content-Type',
                                   -content    => 'text/html'}))

   JAVASCRIPTING: The *-script*, *-noScript*, *-onLoad*, *-onMouseOver*,
*-onMouseOut* and *-onUnload* parameters are used to add Netscape
JavaScript calls to your pages.  *-script* should point to a block of text
containing JavaScript function definitions.  This block will be placed
within a <SCRIPT> block inside the HTML (not HTTP) header.  The block is
placed in the header in order to give your page a fighting chance of
having all its JavaScript functions in place even if the user presses the
stop button before the page has loaded completely.  CGI.pm attempts to
format the script in such a way that JavaScript-naive browsers will not
choke on the code: unfortunately there are some browsers, such as Chimera
for Unix, that get confused by it nevertheless.

   The *-onLoad* and *-onUnload* parameters point to fragments of
JavaScript code to execute when the page is respectively opened and closed
by the browser.  Usually these parameters are calls to functions defined
in the *-script* field:

     $query = new CGI;
     print $query->header;
     $JSCRIPT=<<END;
     // Ask a silly question
     function riddle_me_this() {
     	 var r = prompt("What walks on four legs in the morning, " +
     		       "two legs in the afternoon, " +
     		       "and three legs in the evening?");
     	 response(r);
     }
     // Get a silly answer
     function response(answer) {
     	 if (answer == "man")
     	    alert("Right you are!");
     	 else
     	    alert("Wrong!  Guess again.");
     }
     END
     print $query->start_html(-title=>'The Riddle of the Sphinx',
     			       -script=>$JSCRIPT);

   Use the *-noScript* parameter to pass some HTML text that will be
displayed on browsers that do not have JavaScript (or browsers where
JavaScript is turned off).

   Netscape 3.0 recognizes several attributes of the <SCRIPT> tag,
including LANGUAGE and SRC.  The latter is particularly interesting, as it
allows you to keep the JavaScript code in a file or CGI script rather than
cluttering up each page with the source.  To use these attributes pass a
HASH reference in the *-script* parameter containing one or more of
-language, -src, or -code:

     print $q->start_html(-title=>'The Riddle of the Sphinx',
     			 -script=>{-language=>'JAVASCRIPT',
                                    -src=>'/javascript/sphinx.js'}
     			 );

     print $q->(-title=>'The Riddle of the Sphinx',
     	       -script=>{-language=>'PERLSCRIPT',
     			 -code=>'print "hello world!\n;"'}
     	       );

   A final feature allows you to incorporate multiple <SCRIPT> sections
into the header.  Just pass the list of script sections as an array
reference.  this allows you to specify different source files for
different dialects of JavaScript.  Example:

     print $q->start_html(-title=>'The Riddle of the Sphinx',
                          -script=>[
                                    { -language => 'JavaScript1.0',
                                      -src      => '/javascript/utilities10.js'
                                    },
                                    { -language => 'JavaScript1.1',
                                      -src      => '/javascript/utilities11.js'
                                    },
                                    { -language => 'JavaScript1.2',
                                      -src      => '/javascript/utilities12.js'
                                    },
                                    { -language => 'JavaScript28.2',
                                      -src      => '/javascript/utilities219.js'
                                    }
                                 ]
                             );
     </pre>

   If this looks a bit extreme, take my advice and stick with straight CGI
scripting.

   See

     http://home.netscape.com/eng/mozilla/2.0/handbook/javascript/

   for more information about JavaScript.

   The old-style positional parameters are as follows:

Parameters:

     The title

     The author's e-mail address (will create a <LINK REV="MADE"> tag if
     present

     A 'true' flag if you want to include a <BASE> tag in the header.  This
     helps resolve relative addresses to absolute ones when the document
     is moved, but makes the document hierarchy non-portable.  Use with
     care!

5, 6...
     Any other parameters you want to include in the <BODY> tag.  This is
     a good place to put Netscape extensions, such as colors and wallpaper
     patterns.

ENDING THE HTML DOCUMENT:
-------------------------

     print $query->end_html

   This ends an HTML document by printing the </BODY></HTML> tags.

CREATING A SELF-REFERENCING URL THAT PRESERVES STATE INFORMATION:
-----------------------------------------------------------------

     $myself = $query->self_url;
     print q(<A HREF="$myself">I'm talking to myself.</A>);

   self_url() will return a URL, that, when selected, will reinvoke this
script with all its state information intact.  This is most useful when
you want to jump around within the document using internal anchors but you
don't want to disrupt the current contents of the form(s).  Something like
this will do the trick.

     $myself = $query->self_url;
     print "<A HREF=$myself#table1>See table 1</A>";
     print "<A HREF=$myself#table2>See table 2</A>";
     print "<A HREF=$myself#yourself>See for yourself</A>";

   If you want more control over what's returned, using the *url()* method
instead.

   You can also retrieve the unprocessed query string with query_string():

     $the_string = $query->query_string;

OBTAINING THE SCRIPT'S URL
--------------------------

     $full_url      = $query->url();
     $full_url      = $query->url(-full=>1);  #alternative syntax
     $relative_url  = $query->url(-relative=>1);
     $absolute_url  = $query->url(-absolute=>1);
     $url_with_path = $query->url(-path_info=>1);
     $url_with_path_and_query = $query->url(-path_info=>1,-query=>1);
     $netloc        = $query->url(-base => 1);

   *url()* returns the script's URL in a variety of formats.  Called
without any arguments, it returns the full form of the URL, including host
name and port number

     http://your.host.com/path/to/script.cgi

   You can modify this format with the following named arguments:

*-absolute*
     If true, produce an absolute URL, e.g.

          /path/to/script.cgi

*-relative*
     Produce a relative URL.  This is useful if you want to reinvoke your
     script with different parameters. For example:

          script.cgi

*-full*
     Produce the full URL, exactly as if called without any arguments.
     This overrides the -relative and -absolute arguments.

*-path* (*-path_info*)
     Append the additional path information to the URL.  This can be
     combined with *-full*, *-absolute* or *-relative*.  *-path_info* is
     provided as a synonym.

*-query* (*-query_string*)
     Append the query string to the URL.  This can be combined with
     *-full*, *-absolute* or *-relative*.  *-query_string* is provided as
     a synonym.

*-base*
     Generate just the protocol and net location, as in
     http://www.foo.com:8000

MIXING POST AND URL PARAMETERS
------------------------------

     $color = $query-&gt;url_param('color');

   It is possible for a script to receive CGI parameters in the URL as
well as in the fill-out form by creating a form that POSTs to a URL
containing a query string (a "?" mark followed by arguments).  The param()
method will always return the contents of the POSTed fill-out form,
ignoring the URL's query string.  To retrieve URL parameters, call the
*url_param()* method.  Use it in the same way as param().  The main
difference is that it allows you to read the parameters, but not set them.

   Under no circumstances will the contents of the URL query string
interfere with similarly-named CGI parameters in POSTed forms.  If you try
to mix a URL query string with a form submitted with the GET method, the
results will not be what you expect.

CREATING STANDARD HTML ELEMENTS:
================================

   CGI.pm defines general HTML shortcut methods for most, if not all of
the HTML 3 and HTML 4 tags.  HTML shortcuts are named after a single HTML
element and return a fragment of HTML text that you can then print or
manipulate as you like.  Each shortcut returns a fragment of HTML code
that you can append to a string, save to a file, or, most commonly, print
out so that it displays in the browser window.

   This example shows how to use the HTML methods:

     $q = new CGI;
     print $q->blockquote(
     		     "Many years ago on the island of",
     		     $q->a({href=>"http://crete.org/"},"Crete"),
     		     "there lived a Minotaur named",
     		     $q->strong("Fred."),
     		    ),
         $q->hr;

   This results in the following HTML code (extra newlines have been added
for readability):

     <blockquote>
     Many years ago on the island of
     <a HREF="http://crete.org/">Crete</a> there lived
     a minotaur named <strong>Fred.</strong>
     </blockquote>
     <hr>

   If you find the syntax for calling the HTML shortcuts awkward, you can
import them into your namespace and dispense with the object syntax
completely (see the next section for more details):

     use CGI ':standard';
     print blockquote(
        "Many years ago on the island of",
        a({href=>"http://crete.org/"},"Crete"),
        "there lived a minotaur named",
        strong("Fred."),
        ),
        hr;

PROVIDING ARGUMENTS TO HTML SHORTCUTS
-------------------------------------

   The HTML methods will accept zero, one or multiple arguments.  If you
provide no arguments, you get a single tag:

     print hr;  	#  <HR>

   If you provide one or more string arguments, they are concatenated
together with spaces and placed between opening and closing tags:

     print h1("Chapter","1"); # <H1>Chapter 1</H1>"

   If the first argument is an associative array reference, then the keys
and values of the associative array become the HTML tag's attributes:

     print a({-href=>'fred.html',-target=>'_new'},
        "Open a new frame");

     <A HREF="fred.html",TARGET="_new">Open a new frame</A>

   You may dispense with the dashes in front of the attribute names if you
prefer:

     print img {src=>'fred.gif',align=>'LEFT'};

     <IMG ALIGN="LEFT" SRC="fred.gif">

   Sometimes an HTML tag attribute has no argument.  For example, ordered
lists can be marked as COMPACT.  The syntax for this is an argument that
that points to an undef string:

     print ol({compact=>undef},li('one'),li('two'),li('three'));

   Prior to CGI.pm version 2.41, providing an empty (") string as an
attribute argument was the same as providing undef.  However, this has
changed in order to accommodate those who want to create tags of the form
<IMG ALT="">.  The difference is shown in these two pieces of code:

     CODE                   RESULT
     img({alt=>undef})      <IMG ALT>
     img({alt=>''})         <IMT ALT="">

THE DISTRIBUTIVE PROPERTY OF HTML SHORTCUTS
-------------------------------------------

   One of the cool features of the HTML shortcuts is that they are
distributive.  If you give them an argument consisting of a reference to a
list, the tag will be distributed across each element of the list.  For
example, here's one way to make an ordered list:

     print ul(
               li({-type=>'disc'},['Sneezy','Doc','Sleepy','Happy'])
             );

   This example will result in HTML output that looks like this:

     <UL>
       <LI TYPE="disc">Sneezy</LI>
       <LI TYPE="disc">Doc</LI>
       <LI TYPE="disc">Sleepy</LI>
       <LI TYPE="disc">Happy</LI>
     </UL>

   This is extremely useful for creating tables.  For example:

     print table({-border=>undef},
             caption('When Should You Eat Your Vegetables?'),
             Tr({-align=>CENTER,-valign=>TOP},
             [
                th(['Vegetable', 'Breakfast','Lunch','Dinner']),
                td(['Tomatoes' , 'no', 'yes', 'yes']),
                td(['Broccoli' , 'no', 'no',  'yes']),
                td(['Onions'   , 'yes','yes', 'yes'])
             ]
             )
          );

HTML SHORTCUTS AND LIST INTERPOLATION
-------------------------------------

   Consider this bit of code:

     print blockquote(em('Hi'),'mom!'));

   It will ordinarily return the string that you probably expect, namely:

     <BLOCKQUOTE><EM>Hi</EM> mom!</BLOCKQUOTE>

   Note the space between the element "Hi" and the element "mom!".  CGI.pm
puts the extra space there using array interpolation, which is controlled
by the magic $" variable.  Sometimes this extra space is not what you
want, for example, when you are trying to align a series of images.  In
this case, you can simply change the value of $" to an empty string.

     {
        local($") = '';
        print blockquote(em('Hi'),'mom!'));
      }

   I suggest you put the code in a block as shown here.  Otherwise the
change to $" will affect all subsequent code until you explicitly reset it.

NON-STANDARD HTML SHORTCUTS
---------------------------

   A few HTML tags don't follow the standard pattern for various reasons.

   *comment()* generates an HTML comment (<!- comment ->).  Call it like

     print comment('here is my comment');

   Because of conflicts with built-in Perl functions, the following
functions begin with initial caps:

     Select
     Tr
     Link
     Delete
     Accept
     Sub

   In addition, start_html(), end_html(), start_form(), end_form(),
start_multipart_form() and all the fill-out form tags are special.  See
their respective sections.

AUTOESCAPING HTML
-----------------

   By default, all HTML that is emitted by the form-generating functions
is passed through a function called escapeHTML():

$escaped_string = escapeHTML("unescaped string");
     Escape HTML formatting characters in a string.

   Provided that you have specified a character set of ISO-8859-1 (the
default), the standard HTML escaping rules will be used.  The "<"
character becomes "&lt;", ">" becomes "&gt;", "&" becomes "&amp;", and the
quote character becomes "&quot;".  In addition, the hexadecimal 0x8b and
0x9b characters, which many windows-based browsers interpret as the left
and right angle-bracket characters, are replaced by their numeric HTML
entities ("&#139" and "&#155;").  If you manually change the charset,
either by calling the charset() method explicitly or by passing a -charset
argument to header(), then all characters will be replaced by their
numeric entities, since CGI.pm has no lookup table for all the possible
encodings.

   The automatic escaping does not apply to other shortcuts, such as h1().
You should call escapeHTML() yourself on untrusted data in order to
protect your pages against nasty tricks that people may enter into
guestbooks, etc..  To change the character set, use charset().  To turn
autoescaping off completely, use autoescape():

$charset = charset([$charset]);
     Get or set the current character set.

$flag = autoEscape([$flag]);
     Get or set the value of the autoescape flag.

PRETTY-PRINTING HTML
--------------------

   By default, all the HTML produced by these functions comes out as one
long line without carriage returns or indentation. This is yuck, but it
does reduce the size of the documents by 10-20%.  To get pretty-printed
output, please use CGI/Pretty, a subclass contributed
by Brian Paulsen.

CREATING FILL-OUT FORMS:
========================

   *General note*  The various form-creating methods all return strings to
the caller, containing the tag or tags that will create the requested form
element.  You are responsible for actually printing out these strings.
It's set up this way so that you can place formatting tags around the form
elements.

   *Another note* The default values that you specify for the forms are
only used the first time the script is invoked (when there is no query
string).  On subsequent invocations of the script (when there is a query
string), the former values are used even if they are blank.

   If you want to change the value of a field from its previous value, you
have two choices:

   (1) call the param() method to set it.

   (2) use the -override (alias -force) parameter (a new feature in
version 2.15).  This forces the default value to be used, regardless of
the previous value:

     print $query->textfield(-name=>'field_name',
     			   -default=>'starting value',
     			   -override=>1,
     			   -size=>50,
     			   -maxlength=>80);

   *Yet another note* By default, the text and labels of form elements are
escaped according to HTML rules.  This means that you can safely use
"<CLICK ME>" as the label for a button.  However, it also interferes with
your ability to incorporate special HTML character sequences, such as
&Aacute;, into your fields.  If you wish to turn off automatic escaping,
call the autoEscape() method with a false value immediately after creating
the CGI object:

     $query = new CGI;
     $query->autoEscape(undef);

CREATING AN ISINDEX TAG
-----------------------

     print $query->isindex(-action=>$action);

     -or-

     print $query->isindex($action);

   Prints out an <ISINDEX> tag.  Not very exciting.  The parameter -action
specifies the URL of the script to process the query.  The default is to
process the query with the current script.

STARTING AND ENDING A FORM
--------------------------

     print $query->start_form(-method=>$method,
     			    -action=>$action,
     			    -enctype=>$encoding);
       <... various form stuff ...>
     print $query->endform;

     -or-

     print $query->start_form($method,$action,$encoding);
       <... various form stuff ...>
     print $query->endform;

   start_form() will return a <FORM> tag with the optional method, action
and form encoding that you specify.  The defaults are:

     method: POST
     action: this script
     enctype: application/x-www-form-urlencoded

   endform() returns the closing </FORM> tag.

   Start_form()'s enctype argument tells the browser how to package the
various fields of the form before sending the form to the server.  Two
values are possible:

   Note: This method was previously named startform(), and startform() is
still recognized as an alias.

*application/x-www-form-urlencoded*
     This is the older type of encoding used by all browsers prior to
     Netscape 2.0.  It is compatible with many CGI scripts and is suitable
     for short fields containing text data.  For your convenience, CGI.pm
     stores the name of this encoding type in *&CGI::URL_ENCODED*.

*multipart/form-data*
     This is the newer type of encoding introduced by Netscape 2.0.  It is
     suitable for forms that contain very large fields or that are
     intended for transferring binary data.  Most importantly, it enables
     the "file upload" feature of Netscape 2.0 forms.  For your
     convenience, CGI.pm stores the name of this encoding type in
     *&CGI::MULTIPART*

     Forms that use this type of encoding are not easily interpreted by
     CGI scripts unless they use CGI.pm or another library designed to
     handle them.

   For compatibility, the start_form() method uses the older form of
encoding by default.  If you want to use the newer form of encoding by
default, you can call *start_multipart_form()* instead of *start_form()*.

   JAVASCRIPTING: The *-name* and *-onSubmit* parameters are provided for
use with JavaScript.  The -name parameter gives the form a name so that it
can be identified and manipulated by JavaScript functions.  -onSubmit
should point to a JavaScript function that will be executed just before
the form is submitted to your server.  You can use this opportunity to
check the contents of the form for consistency and completeness.  If you
find something wrong, you can put up an alert box or maybe fix things up
yourself.  You can abort the submission by returning false from this
function.

   Usually the bulk of JavaScript functions are defined in a <SCRIPT>
block in the HTML header and -onSubmit points to one of these function
call.  See start_html() for details.

CREATING A TEXT FIELD
---------------------

     print $query->textfield(-name=>'field_name',
     			    -default=>'starting value',
     			    -size=>50,
     			    -maxlength=>80);
     	-or-

     print $query->textfield('field_name','starting value',50,80);

   textfield() will return a text input field.

Parameters

     The first parameter is the required name for the field (-name).

     The optional second parameter is the default starting value for the
     field contents (-default).

     The optional third parameter is the size of the field in
     characters (-size).

     The optional fourth parameter is the maximum number of characters the
          field will accept (-maxlength).

   As with all these methods, the field will be initialized with its
previous contents from earlier invocations of the script.  When the form
is processed, the value of the text field can be retrieved with:

     $value = $query->param('foo');

   If you want to reset it from its initial value after the script has been
called once, you can do so like this:

     $query->param('foo',"I'm taking over this value!");

   NEW AS OF VERSION 2.15: If you don't want the field to take on its
previous value, you can force its current value by using the -override
(alias -force) parameter:

     print $query->textfield(-name=>'field_name',
     			    -default=>'starting value',
     			    -override=>1,
     			    -size=>50,
     			    -maxlength=>80);

   JAVASCRIPTING: You can also provide *-onChange*, *-onFocus*, *-onBlur*,
*-onMouseOver*, *-onMouseOut* and *-onSelect* parameters to register
JavaScript event handlers.  The onChange handler will be called whenever
the user changes the contents of the text field.  You can do text
validation if you like.  onFocus and onBlur are called respectively when
the insertion point moves into and out of the text field.  onSelect is
called when the user changes the portion of the text that is selected.

CREATING A BIG TEXT FIELD
-------------------------

     print $query->textarea(-name=>'foo',
     			  -default=>'starting value',
     			  -rows=>10,
     			  -columns=>50);

     -or

     print $query->textarea('foo','starting value',10,50);

   textarea() is just like textfield, but it allows you to specify rows
and columns for a multiline text entry box.  You can provide a starting
value for the field, which can be long and contain multiple lines.

   JAVASCRIPTING: The *-onChange*, *-onFocus*, *-onBlur* , *-onMouseOver*,
*-onMouseOut*, and *-onSelect* parameters are recognized.  See textfield().

CREATING A PASSWORD FIELD
-------------------------

     print $query->password_field(-name=>'secret',
     				-value=>'starting value',
     				-size=>50,
     				-maxlength=>80);
     	-or-

     print $query->password_field('secret','starting value',50,80);

   password_field() is identical to textfield(), except that its contents
will be starred out on the web page.

   JAVASCRIPTING: The *-onChange*, *-onFocus*, *-onBlur*, *-onMouseOver*,
*-onMouseOut* and *-onSelect* parameters are recognized.  See textfield().

CREATING A FILE UPLOAD FIELD
----------------------------

     print $query->filefield(-name=>'uploaded_file',
     			    -default=>'starting value',
     			    -size=>50,
     			    -maxlength=>80);
     	-or-

     print $query->filefield('uploaded_file','starting value',50,80);

   filefield() will return a file upload field for Netscape 2.0 browsers.
In order to take full advantage of this *you must use the new multipart
encoding scheme* for the form.  You can do this either by calling
*start_form()* with an encoding type of *&CGI::MULTIPART*, or by calling
the new method *start_multipart_form()* instead of vanilla *start_form()*.

Parameters

     The first parameter is the required name for the field (-name).

     The optional second parameter is the starting value for the field
     contents to be used as the default file name (-default).

     For security reasons, browsers don't pay any attention to this field,
     and so the starting value will always be blank.  Worse, the field
     loses its "sticky" behavior and forgets its previous contents.  The
     starting value field is called for in the HTML specification, however,
     and possibly some browser will eventually provide support for it.

     The optional third parameter is the size of the field in characters
     (-size).

     The optional fourth parameter is the maximum number of characters the
     field will accept (-maxlength).

   When the form is processed, you can retrieve the entered filename by
calling param():

     $filename = $query->param('uploaded_file');

   Different browsers will return slightly different things for the name.
Some browsers return the filename only.  Others return the full path to
the file, using the path conventions of the user's machine.  Regardless,
the name returned is always the name of the file on the *user's* machine,
and is unrelated to the name of the temporary file that CGI.pm creates
during upload spooling (see below).

   The filename returned is also a file handle.  You can read the contents
of the file using standard Perl file reading calls:

     # Read a text file and print it out
     while (<$filename>) {
        print;
     }

     # Copy a binary file to somewhere safe
     open (OUTFILE,">>/usr/local/web/users/feedback");
     while ($bytesread=read($filename,$buffer,1024)) {
        print OUTFILE $buffer;
     }

   However, there are problems with the dual nature of the upload fields.
If you `use strict', then Perl will complain when you try to use a string
as a filehandle.  You can get around this by placing the file reading code
in a block containing the `no strict' pragma.  More seriously, it is
possible for the remote user to type garbage into the upload field, in
which case what you get from param() is not a filehandle at all, but a
string.

   To be safe, use the *upload()* function (new in version 2.47).  When
called with the name of an upload field, *upload()* returns a filehandle,
or undef if the parameter is not a valid filehandle.

     $fh = $query->upload('uploaded_file');
     while (<$fh>) {
     	   print;
     }

   This is the recommended idiom.

   When a file is uploaded the browser usually sends along some
information along with it in the format of headers.  The information
usually includes the MIME content type.  Future browsers may send other
information as well (such as modification date and size). To retrieve this
information, call uploadInfo().  It returns a reference to an associative
array containing all the document headers.

     $filename = $query->param('uploaded_file');
     $type = $query->uploadInfo($filename)->{'Content-Type'};
     unless ($type eq 'text/html') {
     	  die "HTML FILES ONLY!";
     }

   If you are using a machine that recognizes "text" and "binary" data
modes, be sure to understand when and how to use them (see the Camel book).
Otherwise you may find that binary files are corrupted during file uploads.

   There are occasionally problems involving parsing the uploaded file.
This usually happens when the user presses "Stop" before the upload is
finished.  In this case, CGI.pm will return undef for the name of the
uploaded file and set *cgi_error()* to the string "400 Bad request
(malformed multipart POST)".  This error message is designed so that you
can incorporate it into a status code to be sent to the browser.  Example:

     $file = $query->upload('uploaded_file');
     if (!$file && $query->cgi_error) {
        print $query->header(-status=>$query->cgi_error);
        exit 0;
     }

   You are free to create a custom HTML page to complain about the error,
if you wish.

   JAVASCRIPTING: The *-onChange*, *-onFocus*, *-onBlur*, *-onMouseOver*,
*-onMouseOut* and *-onSelect* parameters are recognized.  See textfield()
for details.

CREATING A POPUP MENU
---------------------

     print $query->popup_menu('menu_name',
     			    ['eenie','meenie','minie'],
     			    'meenie');

     -or-

     %labels = ('eenie'=>'your first choice',
     	      'meenie'=>'your second choice',
     	      'minie'=>'your third choice');
     print $query->popup_menu('menu_name',
     			    ['eenie','meenie','minie'],
     			    'meenie',\%labels);

     -or (named parameter style)-

     print $query->popup_menu(-name=>'menu_name',
     			    -values=>['eenie','meenie','minie'],
     			    -default=>'meenie',
     			    -labels=>\%labels);

   popup_menu() creates a menu.

  1. The required first argument is the menu's name (-name).

  2. The required second argument (-values) is an array reference
     containing the list of menu items in the menu.  You can pass the
     method an anonymous array, as shown in the example, or a reference to
     a named array, such as "\@foo".

  3. The optional third parameter (-default) is the name of the default
     menu choice.  If not specified, the first item will be the default.
     The values of the previous choice will be maintained across queries.

  4. The optional fourth parameter (-labels) is provided for people who
     want to use different values for the user-visible label inside the
     popup menu nd the value returned to your script.  It's a pointer to an
     associative array relating menu values to user-visible labels.  If you
     leave this parameter blank, the menu values will be displayed by
     default.  (You can also leave a label undefined if you want to).

        When the form is processed, the selected value of the popup menu
can be retrieved using:

     $popup_menu_value = $query->param('menu_name');

   JAVASCRIPTING: popup_menu() recognizes the following event handlers:
*-onChange*, *-onFocus*, *-onMouseOver*, *-onMouseOut*, and *-onBlur*.
See the textfield() section for details on when these handlers are called.

CREATING A SCROLLING LIST
-------------------------

     print $query->scrolling_list('list_name',
     				['eenie','meenie','minie','moe'],
     				['eenie','moe'],5,'true');
        -or-

     print $query->scrolling_list('list_name',
     				['eenie','meenie','minie','moe'],
     				['eenie','moe'],5,'true',
     				\%labels);

     -or-

     print $query->scrolling_list(-name=>'list_name',
     				-values=>['eenie','meenie','minie','moe'],
     				-default=>['eenie','moe'],
     				-size=>5,
     				-multiple=>'true',
     				-labels=>\%labels);

   scrolling_list() creates a scrolling list.

Parameters:

     The first and second arguments are the list name (-name) and values
     (-values).  As in the popup menu, the second argument should be an
     array reference.

     The optional third argument (-default) can be either a reference to a
     list containing the values to be selected by default, or can be a
     single value to select.  If this argument is missing or undefined,
     then nothing is selected when the list first appears.  In the named
     parameter version, you can use the synonym "-defaults" for this
     parameter.

     The optional fourth argument is the size of the list (-size).

     The optional fifth argument can be set to true to allow multiple
     simultaneous selections (-multiple).  Otherwise only one selection
     will be allowed at a time.

     The optional sixth argument is a pointer to an associative array
     containing long user-visible labels for the list items (-labels).  If
     not provided, the values will be displayed.

     When this form is processed, all selected list items will be returned
     as a list under the parameter name 'list_name'.  The values of the
     selected items can be retrieved with:

          @selected = $query->param('list_name');

   JAVASCRIPTING: scrolling_list() recognizes the following event
handlers: *-onChange*, *-onFocus*, *-onMouseOver*, *-onMouseOut* and
*-onBlur*.  See textfield() for the description of when these handlers are
called.

CREATING A GROUP OF RELATED CHECKBOXES
--------------------------------------

     print $query->checkbox_group(-name=>'group_name',
     				-values=>['eenie','meenie','minie','moe'],
     				-default=>['eenie','moe'],
     				-linebreak=>'true',
     				-labels=>\%labels);

     print $query->checkbox_group('group_name',
     				['eenie','meenie','minie','moe'],
     				['eenie','moe'],'true',\%labels);

     HTML3-COMPATIBLE BROWSERS ONLY:

     print $query->checkbox_group(-name=>'group_name',
     				-values=>['eenie','meenie','minie','moe'],
     				-rows=2,-columns=>2);

   checkbox_group() creates a list of checkboxes that are related by the
same name.

Parameters:

     The first and second arguments are the checkbox name and values,
     respectively (-name and -values).  As in the popup menu, the second
     argument should be an array reference.  These values are used for the
     user-readable labels printed next to the checkboxes as well as for the
     values passed to your script in the query string.

     The optional third argument (-default) can be either a reference to a
     list containing the values to be checked by default, or can be a
     single value to checked.  If this argument is missing or undefined,
     then nothing is selected when the list first appears.

     The optional fourth argument (-linebreak) can be set to true to place
     line breaks between the checkboxes so that they appear as a vertical
     list.  Otherwise, they will be strung together on a horizontal line.

     The optional fifth argument is a pointer to an associative array
     relating the checkbox values to the user-visible labels that will be
     printed next to them (-labels).  If not provided, the values will be
     used as the default.

     *HTML3-compatible browsers* (such as Netscape) can take advantage of
     the optional parameters *-rows*, and *-columns*.  These parameters
     cause checkbox_group() to return an HTML3 compatible table containing
     the checkbox group formatted with the specified number of rows and
     columns.  You can provide just the -columns parameter if you wish;
     checkbox_group will calculate the correct number of rows for you.

     To include row and column headings in the returned table, you can use
     the *-rowheaders* and *-colheaders* parameters.  Both of these accept
     a pointer to an array of headings to use.  The headings are just
     decorative.  They don't reorganize the interpretation of the
     checkboxes - they're still a single named unit.

   When the form is processed, all checked boxes will be returned as a
list under the parameter name 'group_name'.  The values of the "on"
checkboxes can be retrieved with:

     @turned_on = $query->param('group_name');

   The value returned by checkbox_group() is actually an array of button
elements.  You can capture them and use them within tables, lists, or in
other creative ways:

     @h = $query->checkbox_group(-name=>'group_name',-values=>\@values);
     &use_in_creative_way(@h);

   JAVASCRIPTING: checkbox_group() recognizes the *-onClick* parameter.
This specifies a JavaScript code fragment or function call to be executed
every time the user clicks on any of the buttons in the group.  You can
retrieve the identity of the particular button clicked on using the "this"
variable.

CREATING A STANDALONE CHECKBOX
------------------------------

     print $query->checkbox(-name=>'checkbox_name',
     			   -checked=>'checked',
     			   -value=>'ON',
     			   -label=>'CLICK ME');

     -or-

     print $query->checkbox('checkbox_name','checked','ON','CLICK ME');

   checkbox() is used to create an isolated checkbox that isn't logically
related to any others.

Parameters:

     The first parameter is the required name for the checkbox (-name).  It
     will also be used for the user-readable label printed next to the
     checkbox.

     The optional second parameter (-checked) specifies that the checkbox
     is turned on by default.  Synonyms are -selected and -on.

     The optional third parameter (-value) specifies the value of the
     checkbox when it is checked.  If not provided, the word "on" is
     assumed.

     The optional fourth parameter (-label) is the user-readable label to
     be attached to the checkbox.  If not provided, the checkbox name is
     used.

   The value of the checkbox can be retrieved using:

     $turned_on = $query->param('checkbox_name');

   JAVASCRIPTING: checkbox() recognizes the *-onClick* parameter.  See
checkbox_group() for further details.

CREATING A RADIO BUTTON GROUP
-----------------------------

     print $query->radio_group(-name=>'group_name',
     			     -values=>['eenie','meenie','minie'],
     			     -default=>'meenie',
     			     -linebreak=>'true',
     			     -labels=>\%labels);

     -or-

     print $query->radio_group('group_name',['eenie','meenie','minie'],
     					  'meenie','true',\%labels);

     HTML3-COMPATIBLE BROWSERS ONLY:

     print $query->radio_group(-name=>'group_name',
     			     -values=>['eenie','meenie','minie','moe'],
     			     -rows=2,-columns=>2);

   radio_group() creates a set of logically-related radio buttons (turning
one member of the group on turns the others off)

Parameters:

     The first argument is the name of the group and is required (-name).

     The second argument (-values) is the list of values for the radio
     buttons.  The values and the labels that appear on the page are
     identical.  Pass an array reference in the second argument, either
     using an anonymous array, as shown, or by referencing a named array as
     in "\@foo".

     The optional third parameter (-default) is the name of the default
     button to turn on. If not specified, the first item will be the
     default.  You can provide a nonexistent button name, such as "-" to
     start up with no buttons selected.

     The optional fourth parameter (-linebreak) can be set to 'true' to put
     line breaks between the buttons, creating a vertical list.

     The optional fifth parameter (-labels) is a pointer to an associative
     array relating the radio button values to user-visible labels to be
     used in the display.  If not provided, the values themselves are
     displayed.

     *HTML3-compatible browsers* (such as Netscape) can take advantage of
     the optional parameters *-rows*, and *-columns*.  These parameters
     cause radio_group() to return an HTML3 compatible table containing
     the radio group formatted with the specified number of rows and
     columns.  You can provide just the -columns parameter if you wish;
     radio_group will calculate the correct number of rows for you.

     To include row and column headings in the returned table, you can use
     the *-rowheader* and *-colheader* parameters.  Both of these accept a
     pointer to an array of headings to use.  The headings are just
     decorative.  They don't reorganize the interpretation of the radio
     buttons - they're still a single named unit.

   When the form is processed, the selected radio button can be retrieved
using:

     $which_radio_button = $query->param('group_name');

   The value returned by radio_group() is actually an array of button
elements.  You can capture them and use them within tables, lists, or in
other creative ways:

     @h = $query->radio_group(-name=>'group_name',-values=>\@values);
     &use_in_creative_way(@h);

CREATING A SUBMIT BUTTON
------------------------

     print $query->submit(-name=>'button_name',
     			-value=>'value');

     -or-

     print $query->submit('button_name','value');

   submit() will create the query submission button.  Every form should
have one of these.

Parameters:

     The first argument (-name) is optional.  You can give the button a
     name if you have several submission buttons in your form and you want
     to distinguish between them.  The name will also be used as the
     user-visible label.  Be aware that a few older browsers don't deal
     with this correctly and never send back a value from a button.

     The second argument (-value) is also optional.  This gives the button
     a value that will be passed to your script in the query string.

   You can figure out which button was pressed by using different values
for each one:

     $which_one = $query->param('button_name');

   JAVASCRIPTING: radio_group() recognizes the *-onClick* parameter.  See
checkbox_group() for further details.

CREATING A RESET BUTTON
-----------------------

     print $query->reset

   reset() creates the "reset" button.  Note that it restores the form to
its value from the last time the script was called, NOT necessarily to the
defaults.

   Note that this conflicts with the Perl reset() built-in.  Use
CORE::reset() to get the original reset function.

CREATING A DEFAULT BUTTON
-------------------------

     print $query->defaults('button_label')

   defaults() creates a button that, when invoked, will cause the form to
be completely reset to its defaults, wiping out all the changes the user
ever made.

CREATING A HIDDEN FIELD
-----------------------

     print $query->hidden(-name=>'hidden_name',
     		     -default=>['value1','value2'...]);

     -or-

     print $query->hidden('hidden_name','value1','value2'...);

   hidden() produces a text field that can't be seen by the user.  It is
useful for passing state variable information from one invocation of the
script to the next.

Parameters:

     The first argument is required and specifies the name of this field
     (-name).

     The second argument is also required and specifies its value
     (-default).  In the named parameter style of calling, you can provide
     a single value here or a reference to a whole list

   Fetch the value of a hidden field this way:

     $hidden_value = $query->param('hidden_name');

   Note, that just like all the other form elements, the value of a hidden
field is "sticky".  If you want to replace a hidden field with some other
values after the script has been called once you'll have to do it manually:

     $query->param('hidden_name','new','values','here');

CREATING A CLICKABLE IMAGE BUTTON
---------------------------------

     print $query->image_button(-name=>'button_name',
     				-src=>'/source/URL',
     				-align=>'MIDDLE');

     -or-

     print $query->image_button('button_name','/source/URL','MIDDLE');

   image_button() produces a clickable image.  When it's clicked on the
position of the click is returned to your script as "button_name.x" and
"button_name.y", where "button_name" is the name you've assigned to it.

   JAVASCRIPTING: image_button() recognizes the *-onClick* parameter.  See
checkbox_group() for further details.

Parameters:

     The first argument (-name) is required and specifies the name of this
     field.

     The second argument (-src) is also required and specifies the URL

The third option (-align, optional) is an alignment type, and may be TOP, BOTTOM or MIDDLE
   Fetch the value of the button this way:      $x =
$query->param('button_name.x');      $y = $query->param('button_name.y');

CREATING A JAVASCRIPT ACTION BUTTON
-----------------------------------

     print $query->button(-name=>'button_name',
     			  -value=>'user visible label',
     			  -onClick=>"do_something()");

     -or-

     print $query->button('button_name',"do_something()");

   button() produces a button that is compatible with Netscape 2.0's
JavaScript.  When it's pressed the fragment of JavaScript code pointed to
by the *-onClick* parameter will be executed.  On non-Netscape browsers
this form element will probably not even display.

HTTP COOKIES
============

   Netscape browsers versions 1.1 and higher, and all versions of Internet
Explorer, support a so-called "cookie" designed to help maintain state
within a browser session.  CGI.pm has several methods that support cookies.

   A cookie is a name=value pair much like the named parameters in a CGI
query string.  CGI scripts create one or more cookies and send them to the
browser in the HTTP header.  The browser maintains a list of cookies that
belong to a particular Web server, and returns them to the CGI script
during subsequent interactions.

   In addition to the required name=value pair, each cookie has several
optional attributes:

  1. an expiration time This is a time/date string (in a special GMT
     format) that indicates when a cookie expires.  The cookie will be
     saved and returned to your script until this expiration date is
     reached if the user exits the browser and restarts it.  If an
     expiration date isn't specified, the cookie will remain active until
     the user quits the browser.

  2. a domain This is a partial or complete domain name for which the
     cookie is valid.  The browser will return the cookie to any host that
     matches the partial domain name.  For example, if you specify a
     domain name of ".capricorn.com", then the browser will return the
     cookie to Web servers running on any of the machines
     "www.capricorn.com", "www2.capricorn.com", "feckless.capricorn.com",
     etc.  Domain names must contain at least two periods to prevent
     attempts to match on top level domains like ".edu".  If no domain is
     specified, then the browser will only return the cookie to servers on
     the host the cookie originated from.

  3. a path If you provide a cookie path attribute, the browser will check
     it against your script's URL before returning the cookie.  For
     example, if you specify the path "/cgi-bin", then the cookie will be
     returned to each of the scripts "/cgi-bin/tally.pl",
     "/cgi-bin/order.pl", and "/cgi-bin/customer_service/complain.pl", but
     not to the script "/cgi-private/site_admin.pl".  By default, path is
     set to "/", which causes the cookie to be sent to any CGI script on
     your site.

  4. a "secure" flag If the "secure" attribute is set, the cookie will
     only be sent to your script if the CGI request is occurring on a
     secure channel, such as SSL.

        The interface to HTTP cookies is the *cookie()* method:

     $cookie = $query->cookie(-name=>'sessionID',
     			     -value=>'xyzzy',
     			     -expires=>'+1h',
     			     -path=>'/cgi-bin/database',
     			     -domain=>'.capricorn.org',
     			     -secure=>1);
     print $query->header(-cookie=>$cookie);

   *cookie()* creates a new cookie.  Its parameters include:

*-name*
     The name of the cookie (required).  This can be any string at all.
     Although browsers limit their cookie names to non-whitespace
     alphanumeric characters, CGI.pm removes this restriction by escaping
     and unescaping cookies behind the scenes.

*-value*
     The value of the cookie.  This can be any scalar value, array
     reference, or even associative array reference.  For example, you can
     store an entire associative array into a cookie this way:

          $cookie=$query->cookie(-name=>'family information',
          		       -value=>\%childrens_ages);

*-path*
     The optional partial path for which this cookie will be valid, as
     described above.

*-domain*
     The optional partial domain for which this cookie will be valid, as
     described above.

*-expires*
     The optional expiration date for this cookie.  The format is as
     described in the section on the header() method:

          "+1h"  one hour from now

*-secure*
     If set to true, this cookie will only be used within a secure SSL
     session.

   The cookie created by cookie() must be incorporated into the HTTP
header within the string returned by the header() method:

     print $query->header(-cookie=>$my_cookie);

   To create multiple cookies, give header() an array reference:

     $cookie1 = $query->cookie(-name=>'riddle_name',
     			  -value=>"The Sphynx's Question");
     $cookie2 = $query->cookie(-name=>'answers',
     			  -value=>\%answers);
     print $query->header(-cookie=>[$cookie1,$cookie2]);

   To retrieve a cookie, request it by name by calling cookie() method
without the *-value* parameter:

     use CGI;
     $query = new CGI;
     $riddle = $query->cookie('riddle_name');
             %answers = $query->cookie('answers');

   Cookies created with a single scalar value, such as the "riddle_name"
cookie, will be returned in that form.  Cookies with array and hash values
can also be retrieved.

   The cookie and CGI namespaces are separate.  If you have a parameter
named 'answers' and a cookie named 'answers', the values retrieved by
param() and cookie() are independent of each other.  However, it's simple
to turn a CGI parameter into a cookie, and vice-versa:

     # turn a CGI parameter into a cookie
     $c=$q->cookie(-name=>'answers',-value=>[$q->param('answers')]);
     # vice-versa
     $q->param(-name=>'answers',-value=>[$q->cookie('answers')]);

   See the *cookie.cgi* example script for some ideas on how to use
cookies effectively.

WORKING WITH FRAMES
===================

   It's possible for CGI.pm scripts to write into several browser panels
and windows using the HTML 4 frame mechanism.  There are three techniques
for defining new frames programmatically:

  1. Create a <Frameset> document After writing out the HTTP header,
     instead of creating a standard HTML document using the start_html()
     call, create a <FRAMESET> document that defines the frames on the
     page.  Specify your script(s) (with appropriate parameters) as the
     SRC for each of the frames.

     There is no specific support for creating <FRAMESET> sections in
     CGI.pm, but the HTML is very simple to write.  See the frame
     documentation in Netscape's home pages for details

          http://home.netscape.com/assist/net_sites/frames.html

  2. Specify the destination for the document in the HTTP header You may
     provide a *-target* parameter to the header() method:

          print $q->header(-target=>'ResultsWindow');

     This will tell the browser to load the output of your script into the
     frame named "ResultsWindow".  If a frame of that name doesn't already
     exist, the browser will pop up a new window and load your script's
     document into that.  There are a number of magic names that you can
     use for targets.  See the frame documents on Netscape's home pages for
     details.

  3. Specify the destination for the document in the <FORM> tag You can
     specify the frame to load in the FORM tag itself.  With CGI.pm it
     looks like this:

          print $q->start_form(-target=>'ResultsWindow');

     When your script is reinvoked by the form, its output will be loaded
     into the frame named "ResultsWindow".  If one doesn't already exist a
     new window will be created.

        The script "frameset.cgi" in the examples directory shows one way
to create pages in which the fill-out form and the response live in
side-by-side frames.

LIMITED SUPPORT FOR CASCADING STYLE SHEETS
==========================================

   CGI.pm has limited support for HTML3's cascading style sheets (css).
To incorporate a stylesheet into your document, pass the start_html()
method a *-style* parameter.  The value of this parameter may be a scalar,
in which case it is incorporated directly into a <STYLE> section, or it
may be a hash reference.  In the latter case you should provide the hash
with one or more of *-src* or *-code*.  *-src* points to a URL where an
externally-defined stylesheet can be found.  *-code* points to a scalar
value to be incorporated into a <STYLE> section.  Style definitions in
*-code* override similarly-named ones in *-src*, hence the name
"cascading."

   You may also specify the type of the stylesheet by adding the optional
*-type* parameter to the hash pointed to by *-style*.  If not specified,
the style defaults to 'text/css'.

   To refer to a style within the body of your document, add the *-class*
parameter to any HTML element:

     print h1({-class=>'Fancy'},'Welcome to the Party');

   Or define styles on the fly with the *-style* parameter:

     print h1({-style=>'Color: red;'},'Welcome to Hell');

   You may also use the new *span()* element to apply a style to a section
of text:

     print span({-style=>'Color: red;'},
     	       h1('Welcome to Hell'),
     	       "Where did that handbasket get to?"
     	       );

   Note that you must import the ":html3" definitions to have the *span()*
method available.  Here's a quick and dirty example of using CSS's.  See
the CSS specification at http://www.w3.org/pub/WWW/TR/Wd-css-1.html for
more information.

     use CGI qw/:standard :html3/;

     #here's a stylesheet incorporated directly into the page
     $newStyle=<<END;
     <!--
     P.Tip {
     	margin-right: 50pt;
     	margin-left: 50pt;
         color: red;
     }
     P.Alert {
     	font-size: 30pt;
         font-family: sans-serif;
       color: red;
     }
     -->
     END
     print header();
     print start_html( -title=>'CGI with Style',
     		      -style=>{-src=>'http://www.capricorn.com/style/st1.css',
     		               -code=>$newStyle}
     	             );
     print h1('CGI with Style'),
           p({-class=>'Tip'},
     	    "Better read the cascading style sheet spec before playing with this!"),
           span({-style=>'color: magenta'},
     	       "Look Mom, no hands!",
     	       p(),
     	       "Whooo wee!"
     	       );
     print end_html;

   Pass an array reference to *-style* in order to incorporate multiple
stylesheets into your document.

DEBUGGING
=========

   If you are running the script from the command line or in the perl
debugger, you can pass the script a list of keywords or parameter=value
pairs on the command line or from standard input (you don't have to worry
about tricking your script into reading from environment variables).  You
can pass keywords like this:

     your_script.pl keyword1 keyword2 keyword3

   or this:

     your_script.pl keyword1+keyword2+keyword3

   or this:

     your_script.pl name1=value1 name2=value2

   or this:

     your_script.pl name1=value1&name2=value2

   To turn off this feature, use the -no_debug pragma.

   To test the POST method, you may enable full debugging with the -debug
pragma.  This will allow you to feed newline-delimited name=value pairs to
the script on standard input.

   When debugging, you can use quotes and backslashes to escape characters
in the familiar shell manner, letting you place spaces and other funny
characters in your parameter=value pairs:

     your_script.pl "name1='I am a long value'" "name2=two\ words"

DUMPING OUT ALL THE NAME/VALUE PAIRS
------------------------------------

   The Dump() method produces a string consisting of all the query's
name/value pairs formatted nicely as a nested list.  This is useful for
debugging purposes:

     print $query->Dump

   Produces something that looks like:

     <UL>
     <LI>name1
     	<UL>
     	<LI>value1
     	<LI>value2
     	</UL>
     <LI>name2
     	<UL>
     	<LI>value1
     	</UL>
     </UL>

   As a shortcut, you can interpolate the entire CGI object into a string
and it will be replaced with the a nice HTML dump shown above:

     $query=new CGI;
     print "<H2>Current Values</H2> $query\n";

FETCHING ENVIRONMENT VARIABLES
==============================

   Some of the more useful environment variables can be fetched through
this interface.  The methods are as follows:

Accept()
     Return a list of MIME types that the remote browser accepts. If you
     give this method a single argument corresponding to a MIME type, as in
     $query->Accept('text/html'), it will return a floating point value
     corresponding to the browser's preference for this type from 0.0
     (don't want) to 1.0.  Glob types (e.g. text/*) in the browser's accept
     list are handled correctly.

     Note that the capitalization changed between version 2.43 and 2.44 in
     order to avoid conflict with Perl's accept() function.

raw_cookie()
     Returns the HTTP_COOKIE variable, an HTTP extension implemented by
     Netscape browsers version 1.1 and higher, and all versions of Internet
     Explorer.  Cookies have a special format, and this method call just
     returns the raw form (?cookie dough).  See cookie() for ways of
     setting and retrieving cooked cookies.

     Called with no parameters, raw_cookie() returns the packed cookie
     structure.  You can separate it into individual cookies by splitting
     on the character sequence "; ".  Called with the name of a cookie,
     retrieves the *unescaped* form of the cookie.  You can use the
     regular cookie() method to get the names, or use the raw_fetch()
     method from the CGI::Cookie module.

user_agent()
     Returns the HTTP_USER_AGENT variable.  If you give this method a
     single argument, it will attempt to pattern match on it, allowing you
     to do something like $query->user_agent(netscape);

path_info()
     Returns additional path information from the script URL.  E.G.
     fetching /cgi-bin/your_script/additional/stuff will result in
     $query->path_info() returning "/additional/stuff".

     NOTE: The Microsoft Internet Information Server is broken with
     respect to additional path information.  If you use the Perl DLL
     library, the IIS server will attempt to execute the additional path
     information as a Perl script.  If you use the ordinary file
     associations mapping, the path information will be present in the
     environment, but incorrect.  The best thing to do is to avoid using
     additional path information in CGI scripts destined for use with IIS.

path_translated()
     As per path_info() but returns the additional path information
     translated into a physical path, e.g.
     "/usr/local/etc/httpd/htdocs/additional/stuff".

     The Microsoft IIS is broken with respect to the translated path as
     well.

remote_host()
     Returns either the remote host name or IP address.  if the former is
     unavailable.

script_name() Return the script name as a partial URL, for self-refering scripts.
referer()
     Return the URL of the page the browser was viewing prior to fetching
     your script.  Not available for all browsers.

*auth_type ()*
     Return the authorization/verification method in use for this script,
     if any.

*server_name ()*
     Returns the name of the server, usually the machine's host name.

*virtual_host ()*
     When using virtual hosts, returns the name of the host that the
     browser attempted to contact

*server_port ()*
     Return the port that the server is listening on.

*server_software ()*
     Returns the server software and version number.

*remote_user ()*
     Return the authorization/verification name used for user
     verification, if this script is protected.

*user_name ()*
     Attempt to obtain the remote user's name, using a variety of different
     techniques.  This only works with older browsers such as Mosaic.
     Newer browsers do not report the user name for privacy reasons!

request_method()
     Returns the method used to access your script, usually one of 'POST',
     'GET' or 'HEAD'.

content_type()
     Returns the content_type of data submitted in a POST, generally
     multipart/form-data or application/x-www-form-urlencoded

http()
     Called with no arguments returns the list of HTTP environment
     variables, including such things as HTTP_USER_AGENT,
     HTTP_ACCEPT_LANGUAGE, and HTTP_ACCEPT_CHARSET, corresponding to the
     like-named HTTP header fields in the request.  Called with the name of
     an HTTP header field, returns its value.  Capitalization and the use
     of hyphens versus underscores are not significant.

     For example, all three of these examples are equivalent:

          $requested_language = $q->http('Accept-language');
          $requested_language = $q->http('Accept_language');
          $requested_language = $q->http('HTTP_ACCEPT_LANGUAGE');

https()
     The same as http(), but operates on the HTTPS environment variables
     present when the SSL protocol is in effect.  Can be used to determine
     whether SSL is turned on.

USING NPH SCRIPTS
=================

   NPH, or "no-parsed-header", scripts bypass the server completely by
sending the complete HTTP header directly to the browser.  This has slight
performance benefits, but is of most use for taking advantage of HTTP
extensions that are not directly supported by your server, such as server
push and PICS headers.

   Servers use a variety of conventions for designating CGI scripts as
NPH.  Many Unix servers look at the beginning of the script's name for the
prefix "nph-".  The Macintosh WebSTAR server and Microsoft's Internet
Information Server, in contrast, try to decide whether a program is an NPH
script by examining the first line of script output.

   CGI.pm supports NPH scripts with a special NPH mode.  When in this
mode, CGI.pm will output the necessary extra header information when the
header() and redirect() methods are called.

   The Microsoft Internet Information Server requires NPH mode.  As of
version 2.30, CGI.pm will automatically detect when the script is running
under IIS and put itself into this mode.  You do not need to do this
manually, although it won't hurt anything if you do.

   There are a number of ways to put CGI.pm into NPH mode:

In the use statement
     Simply add the "-nph" pragmato the list of symbols to be imported into
     your script:

          use CGI qw(:standard -nph)

By calling the *nph()* method:
     Call *nph()* with a non-zero parameter at any point after using
     CGI.pm in your program.

          CGI->nph(1)

By using *-nph* parameters in the header() and *redirect()*  statements:
          print $q->header(-nph=>1);

Server Push
===========

   CGI.pm provides four simple functions for producing multipart documents
of the type needed to implement server push.  These functions were
graciously provided by Ed Jordan <ed@fidalgo.net>.  To import these into
your namespace, you must import the ":push" set.  You are also advised to
put the script into NPH mode and to set $| to 1 to avoid buffering
problems.

   Here is a simple script that demonstrates server push:

     #!/usr/local/bin/perl
     use CGI qw/:push -nph/;
     $| = 1;
     print multipart_init(-boundary=>'----here we go!');
     foreach (0 .. 4) {
         print multipart_start(-type=>'text/plain'),
               "The current time is ",scalar(localtime),"\n";
         if ($_ < 4) {
                 print multipart_end;
         } else {
                 print multipart_final;
         }
         sleep 1;
     }

   This script initializes server push by calling multipart_init().  It
then enters a loop in which it begins a new multipart section by calling
multipart_start(), prints the current local time, and ends a multipart
section with multipart_end().  It then sleeps a second, and begins again.
On the final iteration, it ends the multipart section with
multipart_final() rather than with multipart_end().

multipart_init()
          multipart_init(-boundary=>$boundary);

     Initialize the multipart system.  The -boundary argument specifies
     what MIME boundary string to use to separate parts of the document.
     If not provided, CGI.pm chooses a reasonable boundary for you.

multipart_start()
          multipart_start(-type=>$type)

     Start a new part of the multipart document using the specified MIME
     type.  If not specified, text/html is assumed.

multipart_end()
          multipart_end()

     End a part.  You must remember to call multipart_end() once for each
     multipart_start(), except at the end of the last part of the multipart
     document when multipart_final() should be called instead of
     multipart_end().

multipart_final()
          multipart_final()

     End all parts.  You should call multipart_final() rather than
     multipart_end() at the end of the last part of the multipart document.

   Users interested in server push applications should also have a look at
the CGI::Push module.

   Only Netscape Navigator supports server push.  Internet Explorer
browsers do not.

Avoiding Denial of Service Attacks
==================================

   A potential problem with CGI.pm is that, by default, it attempts to
process form POSTings no matter how large they are.  A wily hacker could
attack your site by sending a CGI script a huge POST of many megabytes.
CGI.pm will attempt to read the entire POST into a variable, growing
hugely in size until it runs out of memory.  While the script attempts to
allocate the memory the system may slow down dramatically.  This is a form
of denial of service attack.

   Another possible attack is for the remote user to force CGI.pm to
accept a huge file upload.  CGI.pm will accept the upload and store it in
a temporary directory even if your script doesn't expect to receive an
uploaded file.  CGI.pm will delete the file automatically when it
terminates, but in the meantime the remote user may have filled up the
server's disk space, causing problems for other programs.

   The best way to avoid denial of service attacks is to limit the amount
of memory, CPU time and disk space that CGI scripts can use.  Some Web
servers come with built-in facilities to accomplish this. In other cases,
you can use the shell limit or *ulimit* commands to put ceilings on CGI
resource usage.

   CGI.pm also has some simple built-in protections against denial of
service attacks, but you must activate them before you can use them.
These take the form of two global variables in the CGI name space:

$CGI::POST_MAX
     If set to a non-negative integer, this variable puts a ceiling on the
     size of POSTings, in bytes.  If CGI.pm detects a POST that is greater
     than the ceiling, it will immediately exit with an error message.
     This value will affect both ordinary POSTs and multipart POSTs,
     meaning that it limits the maximum size of file uploads as well.  You
     should set this to a reasonably high value, such as 1 megabyte.

$CGI::DISABLE_UPLOADS
     If set to a non-zero value, this will disable file uploads
     completely.  Other fill-out form values will work as usual.

   You can use these variables in either of two ways.

*1. On a script-by-script basis*
     Set the variable at the top of the script, right after the "use"
     statement:

          use CGI qw/:standard/;
          use CGI::Carp 'fatalsToBrowser';
          $CGI::POST_MAX=1024 * 100;  # max 100K posts
          $CGI::DISABLE_UPLOADS = 1;  # no uploads

*2. Globally for all scripts*
     Open up CGI.pm, find the definitions for $POST_MAX and
     $DISABLE_UPLOADS, and set them to the desired values.  You'll find
     them towards the top of the file in a subroutine named
     initialize_globals().

   An attempt to send a POST larger than $POST_MAX bytes will cause
param() to return an empty CGI parameter list.  You can test for this
event by checking *cgi_error()*, either after you create the CGI object
or, if you are using the function-oriented interface, call <param()> for
the first time.  If the POST was intercepted, then cgi_error() will return
the message "413 POST too large".

   This error message is actually defined by the HTTP protocol, and is
designed to be returned to the browser as the CGI script's status  code.
For example:

     $uploaded_file = param('upload');
     if (!$uploaded_file && cgi_error()) {
        print header(-status=>cgi_error());
        exit 0;
     }

   However it isn't clear that any browser currently knows what to do with
this status code.  It might be better just to create an HTML page that
warns the user of the problem.

COMPATIBILITY WITH CGI-LIB.PL
=============================

   To make it easier to port existing programs that use cgi-lib.pl the
compatibility routine "ReadParse" is provided.  Porting is simple:

   OLD VERSION     require "cgi-lib.pl";     &ReadParse;     print "The
value of the antique is $in{antique}.\n";

   NEW VERSION     use CGI;     CGI::ReadParse     print "The value of the
antique is $in{antique}.\n";

   CGI.pm's ReadParse() routine creates a tied variable named %in, which
can be accessed to obtain the query variables.  Like ReadParse, you can
also provide your own variable.  Infrequently used features of ReadParse,
such as the creation of @in and $in variables, are not supported.

   Once you use ReadParse, you can retrieve the query object itself this
way:

     $q = $in{CGI};
     print $q->textfield(-name=>'wow',
     			-value=>'does this really work?');

   This allows you to start using the more interesting features of CGI.pm
without rewriting your old scripts from scratch.

AUTHOR INFORMATION
==================

   Copyright 1995-1998, Lincoln D. Stein.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Address bug reports and comments to: lstein@cshl.org.  When sending bug
reports, please provide the version of CGI.pm, the version of Perl, the
name and version of your Web server, and the name and version of the
operating system you are using.  If the problem is even remotely browser
dependent, please provide information about the affected browers as well.

CREDITS
=======

   Thanks very much to:

Matt Heffron (heffron@falstaff.css.beckman.com)
James Taylor (james.taylor@srs.gov)
Scott Anguish <sanguish@digifix.com>
Mike Jewell (mlj3u@virginia.edu)
Timothy Shimmin (tes@kbs.citri.edu.au)
Joergen Haegg (jh@axis.se)
Laurent Delfosse (delfosse@delfosse.com)
Richard Resnick (applepi1@aol.com)
Craig Bishop (csb@barwonwater.vic.gov.au)
Tony Curtis (tc@vcpc.univie.ac.at)
Tim Bunce (Tim.Bunce@ig.co.uk)
Tom Christiansen (tchrist@convex.com)
Andreas Koenig (k@franz.ww.TU-Berlin.DE)
Tim MacKenzie (Tim.MacKenzie@fulcrum.com.au)
Kevin B. Hendricks (kbhend@dogwood.tyler.wm.edu)
Stephen Dahmen (joyfire@inxpress.net)
Ed Jordan (ed@fidalgo.net)
David Alan Pisoni (david@cnation.com)
Doug MacEachern (dougm@opengroup.org)
Robin Houston (robin@oneworld.org)
...and many many more...
     for suggestions and bug fixes.

A COMPLETE EXAMPLE OF A SIMPLE FORM-BASED SCRIPT
================================================

     #!/usr/local/bin/perl

     use CGI;

     $query = new CGI;

     print $query->header;
     print $query->start_html("Example CGI.pm Form");
     print "<H1> Example CGI.pm Form</H1>\n";
     &print_prompt($query);
     &do_work($query);
     &print_tail;
     print $query->end_html;

     sub print_prompt {
        my($query) = @_;

     print $query->start_form;
     print "<EM>What's your name?</EM><BR>";
     print $query->textfield('name');
     print $query->checkbox('Not my real name');

     print "<P><EM>Where can you find English Sparrows?</EM><BR>";
     print $query->checkbox_group(
     				 -name=>'Sparrow locations',
     				 -values=>[England,France,Spain,Asia,Hoboken],
     				 -linebreak=>'yes',
     				 -defaults=>[England,Asia]);

     print "<P><EM>How far can they fly?</EM><BR>",
     		$query->radio_group(
     			-name=>'how far',
     			-values=>['10 ft','1 mile','10 miles','real far'],
     			-default=>'1 mile');

     print "<P><EM>What's your favorite color?</EM>  ";
     print $query->popup_menu(-name=>'Color',
     				    -values=>['black','brown','red','yellow'],
     				    -default=>'red');

     print $query->hidden('Reference','Monty Python and the Holy Grail');

     print "<P><EM>What have you got there?</EM><BR>";
     print $query->scrolling_list(
     			 -name=>'possessions',
     			 -values=>['A Coconut','A Grail','An Icon',
     				   'A Sword','A Ticket'],
     			 -size=>5,
     			 -multiple=>'true');

     print "<P><EM>Any parting comments?</EM><BR>";
     print $query->textarea(-name=>'Comments',
     				  -rows=>10,
     				  -columns=>50);

     print "<P>",$query->reset;
     print $query->submit('Action','Shout');
     print $query->submit('Action','Scream');
     print $query->endform;
     print "<HR>\n";
     	}

     sub do_work {
        my($query) = @_;
        my(@values,$key);

     print "<H2>Here are the current settings in this form</H2>";

     foreach $key ($query->param) {
        print "<STRONG>$key</STRONG> -> ";
        @values = $query->param($key);
        print join(", ",@values),"<BR>\n";
     	  }
     	}

     sub print_tail {
        print <<END;
     <HR>
     <ADDRESS>Lincoln D. Stein</ADDRESS><BR>
     <A HREF="/">Home Page</A>
     END
     }

BUGS
====

   This module has grown large and monolithic.  Furthermore it's doing many
things, such as handling URLs, parsing CGI input, writing HTML, etc., that
are also done in the LWP modules. It should be discarded in favor of the
CGI::* modules, but somehow I continue to work on it.

   Note that the code is truly contorted in order to avoid spurious
warnings when programs are run with the -w switch.

SEE ALSO
========

   See CGI/Carp, URI/URL, CGI/Request,
see CGI/MiniSvr, CGI/Base,
CGI/Form, CGI/Push, CGI/Fast,
see CGI/Pretty,

Simple Common Gateway Interface Class
*************************************

NAME
====

   CGI3 - Simple Common Gateway Interface Class

SYNOPSIS
========

     # CGI3 script that creates a fill-out form
     # and echoes back its values.

     use CGI3 qw/:standard/;
     print header,
           start_html('A Simple Example'),
           h1('A Simple Example'),
           start_form,
           "What's your name? ",textfield('name'),p,
           "What's the combination?", p,
           checkbox_group(-name=>'words',
                  -values=>['eenie','meenie','minie','moe'],
                  -defaults=>['eenie','minie']), p,
           "What's your favorite color? ",
           popup_menu(-name=>'color',
                  -values=>['red','green','blue','chartreuse']),p,
           submit,
           end_form,
           hr;

     if (param()) {
         print "Your name is",em(param('name')),p,
           "The keywords are: ",em(join(", ",param('words'))),p,
           "Your favorite color is ",em(param('color')),
           hr;
     }

ABSTRACT
========

   This perl library uses perl5 objects to make it easy to create Web
fill-out forms and parse their contents.  This package defines CGI3
objects, entities that contain the values of the current query string and
other state variables.  Using a CGI3 object's methods, you can examine
keywords and parameters passed to your script, and create forms whose
initial values are taken from the current query (thereby preserving state
information).  The module provides shortcut functions that produce
boilerplate HTML, reducing typing and coding errors. It also provides
functionality for some of the more advanced features of CGI3 scripting,
including support for file uploads, cookies, cascading style sheets,
server push, and frames.

   CGI3.pm also provides a simple function-oriented programming style for
those who don't need its object-oriented features.

   The current version of CGI3.pm is available at

     http://www.genome.wi.mit.edu/ftp/pub/software/WWW/cgi_docs.html
     ftp://ftp-genome.wi.mit.edu/pub/software/WWW/

DESCRIPTION
===========

PROGRAMMING STYLE
-----------------

   There are two styles of programming with CGI3.pm, an object-oriented
style and a function-oriented style.  In the object-oriented style you
create one or more CGI3 objects and then use object methods to create the
various elements of the page.  Each CGI3 object starts out with the list
of named parameters that were passed to your CGI3 script by the server.
You can modify the objects, save them to a file or database and recreate
them.  Because each object corresponds to the "state" of the CGI3 script,
and because each object's parameter list is independent of the others,
this allows you to save the state of the script and restore it later.

   For example, using the object oriented style, here is how you create a
simple "Hello World" HTML page:

     #!/usr/local/bin/perl
     use CGI3;                             # load CGI3 routines
     $q = new CGI3;                        # create new CGI3 object
     print $q->header,                    # create the HTTP header
           $q->start_html('hello world'), # start the HTML
           $q->h1('hello world'),         # level 1 header
           $q->end_html;                  # end the HTML

   In the function-oriented style, there is one default CGI3 object that
you rarely deal with directly.  Instead you just call functions to
retrieve CGI3 parameters, create HTML tags, manage cookies, and so on.
This provides you with a cleaner programming interface, but limits you to
using one CGI3 object at a time.  The following example prints the same
page, but uses the function-oriented interface.  The main differences are
that we now need to import a set of functions into our name space (usually
the "standard" functions), and we don't need to create the CGI3 object.

     #!/usr/local/bin/perl
     use CGI3 qw/:standard/;           # load standard CGI3 routines
     print header,                    # create the HTTP header
           start_html('hello world'), # start the HTML
           h1('hello world'),         # level 1 header
           end_html;                  # end the HTML

   The examples in this document mainly use the object-oriented style.
See HOW TO IMPORT FUNCTIONS for important information on function-oriented
programming in CGI3.pm

CALLING CGI3.PM ROUTINES
------------------------

   Most CGI3.pm routines accept several arguments, sometimes as many as 20
optional ones!  To simplify this interface, all routines use a named
argument calling style that looks like this:

     print $q->header(-type=>'image/gif',-expires=>'+3d');

   Each argument name is preceded by a dash.  Neither case nor order
matters in the argument list.  -type, -Type, and -TYPE are all acceptable.
In fact, only the first argument needs to begin with a dash.  If a dash
is present in the first argument, CGI3.pm assumes dashes for the
subsequent ones.

   You don't have to use the hyphen at all if you don't want to.  After
creating a CGI3 object, call the *use_named_parameters()* method with a
nonzero value.  This will tell CGI3.pm that you intend to use named
parameters exclusively:

     $query = new CGI3;
     $query->use_named_parameters(1);
     $field = $query->radio_group('name'=>'OS',
                  'values'=>['Unix','Windows','Macintosh'],
                  'default'=>'Unix');

   Several routines are commonly called with just one argument.  In the
case of these routines you can provide the single argument without an
argument name.  header() happens to be one of these routines.  In this
case, the single argument is the document type.

     print $q->header('text/html');

   Other such routines are documented below.

   Sometimes named arguments expect a scalar, sometimes a reference to an
array, and sometimes a reference to a hash.  Often, you can pass any type
of argument and the routine will do whatever is most appropriate.  For
example, the param() routine is used to set a CGI3 parameter to a single
or a multi-valued value.  The two cases are shown below:

     $q->param(-name=>'veggie',-value=>'tomato');
     $q->param(-name=>'veggie',-value=>'[tomato','tomahto','potato','potahto']);

   A large number of routines in CGI3.pm actually aren't specifically
defined in the module, but are generated automatically as needed.  These
are the "HTML shortcuts," routines that generate HTML tags for use in
dynamically-generated pages.  HTML tags have both attributes (the
attribute="value" pairs within the tag itself) and contents (the part
between the opening and closing pairs.)  To distinguish between attributes
and contents, CGI3.pm uses the convention of passing HTML attributes as a
hash reference as the first argument, and the contents, if any, as any
subsequent arguments.  It works out like this:

     Code                           Generated HTML
     ----                           --------------
     h1()                           <H1>
     h1('some','contents');         <H1>some contents</H1>
     h1({-align=>left});            <H1 ALIGN="LEFT">
     h1({-align=>left},'contents'); <H1 ALIGN="LEFT">contents</H1>

   HTML tags are described in more detail later.

   Many newcomers to CGI3.pm are puzzled by the difference between the
calling conventions for the HTML shortcuts, which require curly braces
around the HTML tag attributes, and the calling conventions for other
routines, which manage to generate attributes without the curly brackets.
Don't be confused.  As a convenience the curly braces are optional in all
but the HTML shortcuts.  If you like, you can use curly braces when
calling any routine that takes named arguments.  For example:

     print $q->header( {-type=>'image/gif',-expires=>'+3d'} );

   If you use the -w switch, you will be warned that some CGI3.pm argument
names conflict with built-in Perl functions.  The most frequent of these
is the -values argument, used to create multi-valued menus, radio button
clusters and the like.  To get around this warning, you have several
choices:

  1. Use another name for the argument, if one is available.  For example,
     -value is an alias for -values.

  2. Change the capitalization, e.g. -Values

  3. Put quotes around the argument name, e.g. '-values'
        Many routines will do something useful with a named argument that
it doesn't recognize.  For example, you can produce non-standard HTTP
header fields by providing them as named arguments:

     print $q->header(-type  =>  'text/html',
                      -cost  =>  'Three smackers',
                      -annoyance_level => 'high',
                      -complaints_to   => 'bit bucket');

   This will produce the following nonstandard HTTP header:

     HTTP/1.0 200 OK
     Cost: Three smackers
     Annoyance-level: high
     Complaints-to: bit bucket
     Content-type: text/html

   Notice the way that underscores are translated automatically into
hyphens.  HTML-generating routines perform a different type of translation.

   This feature allows you to keep up with the rapidly changing HTTP and
HTML "standards".

CREATING A NEW QUERY OBJECT (OBJECT-ORIENTED STYLE):
----------------------------------------------------

     $query = new CGI3;

   This will parse the input (from both POST and GET methods) and store it
into a perl5 object called $query.

CREATING A NEW QUERY OBJECT FROM AN INPUT FILE
----------------------------------------------

     $query = new CGI3(INPUTFILE);

   If you provide a file handle to the new() method, it will read
parameters from the file (or STDIN, or whatever).  The file can be in any
of the forms describing below under debugging (i.e. a series of newline
delimited TAG=VALUE pairs will work).  Conveniently, this type of file is
created by the save() method (see below).  Multiple records can be saved
and restored.

   Perl purists will be pleased to know that this syntax accepts
references to file handles, or even references to filehandle globs, which
is the "official" way to pass a filehandle:

     $query = new CGI3(\*STDIN);

   You can also initialize the CGI3 object with a FileHandle or IO::File
object.

   If you are using the function-oriented interface and want to initialize
CGI3 state from a file handle, the way to do this is with
*restore_parameters()*.  This will (re)initialize the default CGI3 object
from the indicated file handle.

     open (IN,"test.in") || die;
     restore_parameters(IN);
     close IN;

   You can also initialize the query object from an associative array
reference:

     $query = new CGI3( {'dinosaur'=>'barney',
                'song'=>'I love you',
                'friends'=>[qw/Jessica George Nancy/]}
             );

   or from a properly formatted, URL-escaped query string:

     $query = new CGI3('dinosaur=barney&color=purple');

   or from a previously existing CGI3 object (currently this clones the
parameter list, but none of the other object-specific fields, such as
autoescaping):

     $old_query = new CGI3;
     $new_query = new CGI3($old_query);

   To create an empty query, initialize it from an empty string or hash:

     $empty_query = new CGI3("");

     -or-

     $empty_query = new CGI3({});

FETCHING A LIST OF KEYWORDS FROM THE QUERY:
-------------------------------------------

     @keywords = $query->keywords

   If the script was invoked as the result of an <ISINDEX> search, the
parsed keywords can be obtained as an array using the keywords() method.

FETCHING THE NAMES OF ALL THE PARAMETERS PASSED TO YOUR SCRIPT:
---------------------------------------------------------------

     @names = $query->param

   If the script was invoked with a parameter list (e.g.
"name1=value1&name2=value2&name3=value3"), the param() method will return
the parameter names as a list.  If the script was invoked as an <ISINDEX>
script, there will be a single parameter named 'keywords'.

   NOTE: As of version 1.5, the array of parameter names returned will be
in the same order as they were submitted by the browser.  Usually this
order is the same as the order in which the parameters are defined in the
form (however, this isn't part of the spec, and so isn't guaranteed).

FETCHING THE VALUE OR VALUES OF A SINGLE NAMED PARAMETER:
---------------------------------------------------------

     @values = $query->param('foo');

     -or-

     $value = $query->param('foo');

   Pass the param() method a single argument to fetch the value of the
named parameter. If the parameter is multivalued (e.g. from multiple
selections in a scrolling list), you can ask to receive an array.
Otherwise the method will return a single value.

SETTING THE VALUE(S) OF A NAMED PARAMETER:
------------------------------------------

     $query->param('foo','an','array','of','values');

   This sets the value for the named parameter 'foo' to an array of
values.  This is one way to change the value of a field AFTER the script
has been invoked once before.  (Another way is with the -override
parameter accepted by all methods that generate form elements.)

   param() also recognizes a named parameter style of calling described in
more detail later:

     $query->param(-name=>'foo',-values=>['an','array','of','values']);

     -or-

     $query->param(-name=>'foo',-value=>'the value');

APPENDING ADDITIONAL VALUES TO A NAMED PARAMETER:
-------------------------------------------------

     $query->append(-name=>'foo',-values=>['yet','more','values']);

   This adds a value or list of values to the named parameter.  The values
are appended to the end of the parameter if it already exists.  Otherwise
the parameter is created.  Note that this method only recognizes the named
argument calling syntax.

IMPORTING ALL PARAMETERS INTO A NAMESPACE:
------------------------------------------

     $query->import_names('R');

   This creates a series of variables in the 'R' namespace.  For example,
$R::foo, @R:foo.  For keyword lists, a variable @R::keywords will appear.
If no namespace is given, this method will assume 'Q'.  WARNING:  don't
import anything into 'main'; this is a major security risk!!!!

   In older versions, this method was called import().  As of version 2.20,
this name has been removed completely to avoid conflict with the built-in
Perl module import operator.

DELETING A PARAMETER COMPLETELY:
--------------------------------

     $query->delete('foo');

   This completely clears a parameter.  It sometimes useful for resetting
parameters that you don't want passed down between script invocations.

   If you are using the function call interface, use "Delete()" instead to
avoid conflicts with Perl's built-in delete operator.

DELETING ALL PARAMETERS:
------------------------

     $query->delete_all();

   This clears the CGI3 object completely.  It might be useful to ensure
that all the defaults are taken when you create a fill-out form.

   Use Delete_all() instead if you are using the function call interface.

DIRECT ACCESS TO THE PARAMETER LIST:
------------------------------------

     $q->param_fetch('address')->[1] = '1313 Mockingbird Lane';
     unshift @{$q->param_fetch(-name=>'address')},'George Munster';

   If you need access to the parameter list in a way that isn't covered by
the methods above, you can obtain a direct reference to it by calling the
*param_fetch()* method with the name of the .  This will return an array
reference to the named parameters, which you then can manipulate in any
way you like.

   You can also use a named argument style using the *-name* argument.

SAVING THE STATE OF THE SCRIPT TO A FILE:
-----------------------------------------

     $query->save(FILEHANDLE)

   This will write the current state of the form to the provided
filehandle.  You can read it back in by providing a filehandle to the
new() method.  Note that the filehandle can be a file, a pipe, or whatever!

   The format of the saved file is:

     NAME1=VALUE1
     NAME1=VALUE1'
     NAME2=VALUE2
     NAME3=VALUE3
     =

   Both name and value are URL escaped.  Multi-valued CGI3 parameters are
represented as repeated names.  A session record is delimited by a single
= symbol.  You can write out multiple records and read them back in with
several calls to new.  You can do this across several sessions by opening
the file in append mode, allowing you to create primitive guest books, or
to keep a history of users' queries.  Here's a short example of creating
multiple session records:

     use CGI3;

     open (OUT,">>test.out") || die;
     $records = 5;
     foreach (0..$records) {
         my $q = new CGI3;
         $q->param(-name=>'counter',-value=>$_);
         $q->save(OUT);
     }
     close OUT;

     # reopen for reading
     open (IN,"test.out") || die;
     while (!eof(IN)) {
         my $q = new CGI3(IN);
         print $q->param('counter'),"\n";
     }

   The file format used for save/restore is identical to that used by the
Whitehead Genome Center's data exchange format "Boulderio", and can be
manipulated and even databased using Boulderio utilities.  See

     http://www.genome.wi.mit.edu/genome_software/other/boulder.html

   for further details.

   If you wish to use this method from the function-oriented (non-OO)
interface, the exported name for this method is *save_parameters()*.

USING THE FUNCTION-ORIENTED INTERFACE
-------------------------------------

   To use the function-oriented interface, you must specify which CGI3.pm
routines or sets of routines to import into your script's namespace.
There is a small overhead associated with this importation, but it isn't
much.

     use CGI3 <list of methods>;

   The listed methods will be imported into the current package; you can
call them directly without creating a CGI3 object first.  This example
shows how to import the param() and header() methods, and then use them
directly:

     use CGI3 'param','header';
     print header('text/plain');
     $zipcode = param('zipcode');

   More frequently, you'll import common sets of functions by referring to
the groups by name.  All function sets are preceded with a ":" character
as in ":html3" (for tags defined in the HTML 3 standard).

   Here is a list of the function sets you can import:

:cgi
     Import all CGI3-handling methods, such as param(), path_info() and
     the like.

:form
     Import all fill-out form generating methods, such as *textfield()*.

:html2
     Import all methods that generate HTML 2.0 standard elements.

:html3
     Import all methods that generate HTML 3.0 proposed elements (such as
     <table>, <super> and <sub>).

:netscape
     Import all methods that generate Netscape-specific HTML extensions.

:html
     Import all HTML-generating shortcuts (i.e. 'html2' + 'html3' +
     'netscape')...

:standard
     Import "standard" features, 'html2', 'html3', 'form' and 'cgi'.

:all
     Import all the available methods.  For the full list, see the CGI3.pm
     code, where the variable %TAGS is defined.

   If you import a function name that is not part of CGI3.pm, the module
will treat it as a new HTML tag and generate the appropriate subroutine.
You can then use it like any other HTML tag.  This is to provide for the
rapidly-evolving HTML "standard."  For example, say Microsoft comes out
with a new tag called <GRADIENT> (which causes the user's desktop to be
flooded with a rotating gradient fill until his machine reboots).  You
don't need to wait for a new version of CGI3.pm to start using it
immediately:

     use CGI3 qw/:standard :html3 gradient/;
     print gradient({-start=>'red',-end=>'blue'});

   Note that in the interests of execution speed CGI3.pm does not use the
standard Exporter, syntax for specifying load symbols.
This may change in the future.

   If you import any of the state-maintaining CGI3 or form-generating
methods, a default CGI3 object will be created and initialized
automatically the first time you use any of the methods that require one
to be present.  This includes param(), *textfield()*, *submit()* and the
like.  (If you need direct access to the CGI3 object, you can find it in
the global variable *$CGI3::Q*).  By importing CGI3.pm methods, you can
create visually elegant scripts:

     use CGI3 qw/:standard/;
     print
         header,
         start_html('Simple Script'),
         h1('Simple Script'),
         start_form,
         "What's your name? ",textfield('name'),p,
         "What's the combination?",
         checkbox_group(-name=>'words',
                -values=>['eenie','meenie','minie','moe'],
                -defaults=>['eenie','moe']),p,
         "What's your favorite color?",
         popup_menu(-name=>'color',
            -values=>['red','green','blue','chartreuse']),p,
         submit,
         end_form,
         hr,"\n";

     if (param) {
        print
        "Your name is ",em(param('name')),p,
        "The keywords are: ",em(join(", ",param('words'))),p,
        "Your favorite color is ",em(param('color')),".\n";
     }
     print end_html;

PRAGMAS
-------

   In addition to the function sets, there are a number of pragmas that
you can import.  Pragmas, which are always preceded by a hyphen, change
the way that CGI3.pm functions in various ways.  Pragmas, function sets,
and individual functions can all be imported in the same use() line.  For
example, the following use statement imports the standard set of functions
and disables debugging mode (pragma -no_debug):

     use CGI3 qw/:standard -no_debug/;

   The current list of pragmas is as follows:

-any
     When you *use CGI3 -any*, then any method that the query object
     doesn't recognize will be interpreted as a new HTML tag.  This allows
     you to support the next *ad hoc* Netscape or Microsoft HTML
     extension.  This lets you go wild with new and unsupported tags:

          use CGI3 qw(-any);
          $q=new CGI3;
          print $q->gradient({speed=>'fast',start=>'red',end=>'blue'});

     Since using <cite>any</cite> causes any mistyped method name to be
     interpreted as an HTML tag, use it with care or not at all.

-compile
     This causes the indicated autoloaded methods to be compiled up front,
     rather than deferred to later.  This is useful for scripts that run
     for an extended period of time under FastCGI3 or mod_perl, and for
     those destined to be crunched by Malcom Beattie's Perl compiler.  Use
     it in conjunction with the methods or method families you plan to use.

          use CGI3 qw(-compile :standard :html3);

     or even

          use CGI3 qw(-compile :all);

     Note that using the -compile pragma in this way will always have the
     effect of importing the compiled functions into the current
     namespace.  If you want to compile without importing use the
     compile() method instead (see below).

-nph
     This makes CGI3.pm produce a header appropriate for an NPH (no parsed
     header) script.  You may need to do other things as well to tell the
     server that the script is NPH.  See the discussion of NPH scripts
     below.

-newstyle_urls
     Separate the name=value pairs in CGI3 parameter query strings with
     semicolons rather than ampersands.  For example:

          ?name=fred;age=24;favorite_color=3

     Semicolon-delimited query strings are always accepted, but will not be
     emitted by self_url() and query_string() unless the -newstyle_urls
     pragma is specified.

-autoload
     This overrides the autoloader so that any function in your program
     that is not recognized is referred to CGI3.pm for possible evaluation.
     This allows you to use all the CGI3.pm functions without adding them
     to your symbol table, which is of concern for mod_perl users who are
     worried about memory consumption.  Warning: when *-autoload* is in
     effect, you cannot use "poetry mode" (functions without the
     parenthesis).  Use *hr()* rather than *hr*, or add something like
     *use subs qw/hr p header/* to the top of your script.

-no_debug
     This turns off the command-line processing features.  If you want to
     run a CGI3.pm script from the command line to produce HTML, and you
     don't want it pausing to request CGI3 parameters from standard input
     or the command line, then use this pragma:

          use CGI3 qw(-no_debug :standard);

     If you'd like to process the command-line parameters but not standard
     input, this should work:

          use CGI3 qw(-no_debug :standard);
          restore_parameters(join('&',@ARGV));

     See the section on debugging for more details.

-private_tempfiles
     CGI3.pm can process uploaded file. Ordinarily it spools the uploaded
     file to a temporary directory, then deletes the file when done.
     However, this opens the risk of eavesdropping as described in the
     file upload section.  Another CGI3 script author could peek at this
     data during the upload, even if it is confidential information. On
     Unix systems, the -private_tempfiles pragma will cause the temporary
     file to be unlinked as soon as it is opened and before any data is
     written into it, eliminating the risk of eavesdropping.

SPECIAL FORMS FOR IMPORTING HTML-TAG FUNCTIONS
----------------------------------------------

   Many of the methods generate HTML tags.  As described below, tag
functions automatically generate both the opening and closing tags.  For
example:

     print h1('Level 1 Header');

   produces

     <H1>Level 1 Header</H1>

   There will be some times when you want to produce the start and end
tags yourself.  In this case, you can use the form start_*tag_name* and
end_*tag_name*, as in:

     print start_h1,'Level 1 Header',end_h1;

   With a few exceptions (described below), start_*tag_name* and
end_*tag_name* functions are not generated automatically when you *use
CGI3*.  However, you can specify the tags you want to generate *start/end*
functions for by putting an asterisk in front of their name, or,
alternatively, requesting either "start_*tag_name*" or "end_*tag_name*" in
the import list.

   Example:

     use CGI3 qw/:standard *table start_ul/;

   In this example, the following functions are generated in addition to
the standard ones:

  1. start_table() (generates a <TABLE> tag)

  2. end_table() (generates a </TABLE> tag)

  3. start_ul() (generates a <UL> tag)

  4. end_ul() (generates a </UL> tag)

GENERATING DYNAMIC DOCUMENTS
============================

   Most of CGI3.pm's functions deal with creating documents on the fly.
Generally you will produce the HTTP header first, followed by the document
itself.  CGI3.pm provides functions for generating HTTP headers of various
types as well as for generating HTML.  For creating GIF images, see the
GD.pm module.

   Each of these functions produces a fragment of HTML or HTTP which you
can print out directly so that it displays in the browser window, append
to a string, or save to a file for later use.

CREATING A STANDARD HTTP HEADER:
--------------------------------

   Normally the first thing you will do in any CGI3 script is print out an
HTTP header.  This tells the browser what type of document to expect, and
gives other optional information, such as the language, expiration date,
and whether to cache the document.  The header can also be manipulated for
special purposes, such as server push and pay per view pages.

     print $query->header;

     -or-

     print $query->header('image/gif');

     -or-

     print $query->header('text/html','204 No response');

     -or-

     print $query->header(-type=>'image/gif',
                  -nph=>1,
                  -status=>'402 Payment required',
                  -expires=>'+3d',
                  -cookie=>$cookie,
                  -Cost=>'$2.00');

   header() returns the Content-type: header.  You can provide your own
MIME type if you choose, otherwise it defaults to text/html.  An optional
second parameter specifies the status code and a human-readable message.
For example, you can specify 204, "No response" to create a script that
tells the browser to do nothing at all.

   The last example shows the named argument style for passing arguments
to the CGI3 methods using named parameters.  Recognized parameters are
*-type*, *-status*, *-expires*, and *-cookie*.  Any other named parameters
will be stripped of their initial hyphens and turned into header fields,
allowing you to specify any HTTP header you desire.  Internal underscores
will be turned into hyphens:

     print $query->header(-Content_length=>3002);

   Most browsers will not cache the output from CGI3 scripts.  Every time
the browser reloads the page, the script is invoked anew.  You can change
this behavior with the *-expires* parameter.  When you specify an absolute
or relative expiration interval with this parameter, some browsers and
proxy servers will cache the script's output until the indicated
expiration date.  The following forms are all valid for the -expires field:

     +30s                              30 seconds from now
     +10m                              ten minutes from now
     +1h                               one hour from now
     -1d                               yesterday (i.e. "ASAP!")
     now                               immediately
     +3M                               in three months
     +10y                              in ten years time
     Thursday, 25-Apr-1999 00:40:33 GMT  at the indicated time & date

   The *-cookie* parameter generates a header that tells the browser to
provide a "magic cookie" during all subsequent transactions with your
script.  Netscape cookies have a special format that includes interesting
attributes such as expiration time.  Use the cookie() method to create and
retrieve session cookies.

   The *-nph* parameter, if set to a true value, will issue the correct
headers to work with a NPH (no-parse-header) script.  This is important to
use with certain servers, such as Microsoft Internet Explorer, which
expect all their scripts to be NPH.

GENERATING A REDIRECTION HEADER
-------------------------------

     print $query->redirect('http://somewhere.else/in/movie/land');

   Sometimes you don't want to produce a document yourself, but simply
redirect the browser elsewhere, perhaps choosing a URL based on the time
of day or the identity of the user.

   The redirect() function redirects the browser to a different URL.  If
you use redirection like this, you should not print out a header as well.
As of version 2.0, we produce both the unofficial Location: header and the
official URI: header.  This should satisfy most servers and browsers.

   One hint I can offer is that relative links may not work correctly when
you generate a redirection to another document on your site.  This is due
to a well-intentioned optimization that some servers use.  The solution to
this is to use the full URL (including the http: part) of the document you
are redirecting to.

   You can also use named arguments:

     print $query->redirect(-uri=>'http://somewhere.else/in/movie/land',
                -nph=>1);

   The *-nph* parameter, if set to a true value, will issue the correct
headers to work with a NPH (no-parse-header) script.  This is important to
use with certain servers, such as Microsoft Internet Explorer, which
expect all their scripts to be NPH.

CREATING THE HTML DOCUMENT HEADER
---------------------------------

     print $query->start_html(-title=>'Secrets of the Pyramids',
                  -author=>'fred@capricorn.org',
                  -base=>'true',
                  -target=>'_blank',
                  -meta=>{'keywords'=>'pharaoh secret mummy',
                      'copyright'=>'copyright 1996 King Tut'},
                  -style=>{'src'=>'/styles/style1.css'},
                  -BGCOLOR=>'blue');

   After creating the HTTP header, most CGI3 scripts will start writing
out an HTML document.  The start_html() routine creates the top of the
page, along with a lot of optional information that controls the page's
appearance and behavior.

   This method returns a canned HTML header and the opening <BODY> tag.
All parameters are optional.  In the named parameter form, recognized
parameters are -title, -author, -base, -xbase and -target (see below for
the explanation).  Any additional parameters you provide, such as the
Netscape unofficial BGCOLOR attribute, are added to the <BODY> tag.
Additional parameters must be proceeded by a hyphen.

   The argument *-xbase* allows you to provide an HREF for the <BASE> tag
different from the current location, as in

     -xbase=>"http://home.mcom.com/"

   All relative links will be interpreted relative to this tag.

   The argument *-target* allows you to provide a default target frame for
all the links and fill-out forms on the page.  See the Netscape
documentation on frames for details of how to manipulate this.

     -target=>"answer_window"

   All relative links will be interpreted relative to this tag.  You add
arbitrary meta information to the header with the *-meta* argument.  This
argument expects a reference to an associative array containing name/value
pairs of meta information.  These will be turned into a series of header
<META> tags that look something like this:

     <META NAME="keywords" CONTENT="pharaoh secret mummy">
     <META NAME="description" CONTENT="copyright 1996 King Tut">

   There is no support for the HTTP-EQUIV type of <META> tag.  This is
because you can modify the HTTP header directly with the header() method.
For example, if you want to send the Refresh: header, do it in the
header() method:

     print $q->header(-Refresh=>'10; URL=http://www.capricorn.com');

   The *-style* tag is used to incorporate cascading stylesheets into your
code.  See the section on CASCADING STYLESHEETS for more information.

   You can place other arbitrary HTML elements to the <HEAD> section with
the *-head* tag.  For example, to place the rarely-used <LINK> element in
the head section, use this:

     print $q->start_html(-head=>Link({-rel=>'next',
                   -href=>'http://www.capricorn.com/s2.html'}));

   To incorporate multiple HTML elements into the <HEAD> section, just
pass an array reference:

     print $q->start_html(-head=>[
                               Link({-rel=>'next',
                     -href=>'http://www.capricorn.com/s2.html'}),
                   Link({-rel=>'previous',
                     -href=>'http://www.capricorn.com/s1.html'})
                  ]
              );

   JAVASCRIPTING: The *-script*, *-noScript*, *-onLoad*, *-onMouseOver*,
*-onMouseOut* and *-onUnload* parameters are used to add Netscape
JavaScript calls to your pages.  *-script* should point to a block of text
containing JavaScript function definitions.  This block will be placed
within a <SCRIPT> block inside the HTML (not HTTP) header.  The block is
placed in the header in order to give your page a fighting chance of
having all its JavaScript functions in place even if the user presses the
stop button before the page has loaded completely.  CGI3.pm attempts to
format the script in such a way that JavaScript-naive browsers will not
choke on the code: unfortunately there are some browsers, such as Chimera
for Unix, that get confused by it nevertheless.

   The *-onLoad* and *-onUnload* parameters point to fragments of
JavaScript code to execute when the page is respectively opened and closed
by the browser.  Usually these parameters are calls to functions defined
in the *-script* field:

     $query = new CGI3;
     print $query->header;
     $JSCRIPT=<<END;
     // Ask a silly question
     function riddle_me_this() {
          var r = prompt("What walks on four legs in the morning, " +
              "two legs in the afternoon, " +
              "and three legs in the evening?");
          response(r);
     }
     // Get a silly answer
     function response(answer) {
          if (answer == "man")
       alert("Right you are!");
          else
       alert("Wrong!  Guess again.");
     }
     END
     print $query->start_html(-title=>'The Riddle of the Sphinx',
                  -script=>$JSCRIPT);

   Use the *-noScript* parameter to pass some HTML text that will be
displayed on browsers that do not have JavaScript (or browsers where
JavaScript is turned off).

   Netscape 3.0 recognizes several attributes of the <SCRIPT> tag,
including LANGUAGE and SRC.  The latter is particularly interesting, as it
allows you to keep the JavaScript code in a file or CGI3 script rather
than cluttering up each page with the source.  To use these attributes
pass a HASH reference in the *-script* parameter containing one or more of
-language, -src, or -code:

     print $q->start_html(-title=>'The Riddle of the Sphinx',
              -script=>{-language=>'JAVASCRIPT',
                                    -src=>'/javascript/sphinx.js'}
              );

     print $q->(-title=>'The Riddle of the Sphinx',
            -script=>{-language=>'PERLSCRIPT'},
              -code=>'print "hello world!\n;"'
            );

   A final feature allows you to incorporate multiple <SCRIPT> sections
into the header.  Just pass the list of script sections as an array
reference.  this allows you to specify different source files for
different dialects of JavaScript.  Example:

     print $q-&gt;start_html(-title=&gt;'The Riddle of the Sphinx',
                          -script=&gt;[
                                    { -language =&gt; 'JavaScript1.0',
                                      -src      =&gt; '/javascript/utilities10.js'
                                    },
                                    { -language =&gt; 'JavaScript1.1',
                                      -src      =&gt; '/javascript/utilities11.js'
                                    },
                                    { -language =&gt; 'JavaScript1.2',
                                      -src      =&gt; '/javascript/utilities12.js'
                                    },
                                    { -language =&gt; 'JavaScript28.2',
                                      -src      =&gt; '/javascript/utilities219.js'
                                    }
                                 ]
                             );
     </pre>

   If this looks a bit extreme, take my advice and stick with straight
CGI3 scripting.

   See

     http://home.netscape.com/eng/mozilla/2.0/handbook/javascript/

   for more information about JavaScript.

   The old-style positional parameters are as follows:

Parameters:

     The title

     The author's e-mail address (will create a <LINK REV="MADE"> tag if
     present

     A 'true' flag if you want to include a <BASE> tag in the header.  This
     helps resolve relative addresses to absolute ones when the document
     is moved, but makes the document hierarchy non-portable.  Use with
     care!

5, 6...
     Any other parameters you want to include in the <BODY> tag.  This is
     a good place to put Netscape extensions, such as colors and wallpaper
     patterns.

ENDING THE HTML DOCUMENT:
-------------------------

     print $query->end_html

   This ends an HTML document by printing the </BODY></HTML> tags.

CREATING A SELF-REFERENCING URL THAT PRESERVES STATE INFORMATION:
-----------------------------------------------------------------

     $myself = $query->self_url;
     print "<A HREF="$myself">I'm talking to myself.</A>";

   self_url() will return a URL, that, when selected, will reinvoke this
script with all its state information intact.  This is most useful when
you want to jump around within the document using internal anchors but you
don't want to disrupt the current contents of the form(s).  Something like
this will do the trick.

     $myself = $query->self_url;
     print "<A HREF=$myself#table1>See table 1</A>";
     print "<A HREF=$myself#table2>See table 2</A>";
     print "<A HREF=$myself#yourself>See for yourself</A>";

   If you want more control over what's returned, using the *url()* method
instead.

   You can also retrieve the unprocessed query string with query_string():

     $the_string = $query->query_string;

OBTAINING THE SCRIPT'S URL
--------------------------

     $full_url      = $query->url();
     $full_url      = $query->url(-full=>1);  #alternative syntax
     $relative_url  = $query->url(-relative=>1);
     $absolute_url  = $query->url(-absolute=>1);
     $url_with_path = $query->url(-path_info=>1);
     $url_with_path_and_query = $query->url(-path_info=>1,-query=>1);

   *url()* returns the script's URL in a variety of formats.  Called
without any arguments, it returns the full form of the URL, including host
name and port number

     http://your.host.com/path/to/script.cgi

   You can modify this format with the following named arguments:

*-absolute*
     If true, produce an absolute URL, e.g.

          /path/to/script.cgi

*-relative*
     Produce a relative URL.  This is useful if you want to reinvoke your
     script with different parameters. For example:

          script.cgi

*-full*
     Produce the full URL, exactly as if called without any arguments.
     This overrides the -relative and -absolute arguments.

*-path* (*-path_info*)
     Append the additional path information to the URL.  This can be
     combined with *-full*, *-absolute* or *-relative*.  *-path_info* is
     provided as a synonym.

*-query* (*-query_string*)
     Append the query string to the URL.  This can be combined with
     *-full*, *-absolute* or *-relative*.  *-query_string* is provided as
     a synonym.

MIXING POST AND URL PARAMETERS
------------------------------

     $color = $query-&gt;url_param('color');

   It is possible for a script to receive CGI3 parameters in the URL as
well as in the fill-out form by creating a form that POSTs to a URL
containing a query string (a "?" mark followed by arguments).  The param()
method will always return the contents of the POSTed fill-out form,
ignoring the URL's query string.  To retrieve URL parameters, call the
*url_param()* method.  Use it in the same way as param().  The main
difference is that it allows you to read the parameters, but not set them.

   Under no circumstances will the contents of the URL query string
interfere with similarly-named CGI3 parameters in POSTed forms.  If you
try to mix a URL query string with a form submitted with the GET method,
the results will not be what you expect.

CREATING STANDARD HTML ELEMENTS:
================================

   CGI3.pm defines general HTML shortcut methods for most, if not all of
the HTML 3 and HTML 4 tags.  HTML shortcuts are named after a single HTML
element and return a fragment of HTML text that you can then print or
manipulate as you like.  Each shortcut returns a fragment of HTML code
that you can append to a string, save to a file, or, most commonly, print
out so that it displays in the browser window.

   This example shows how to use the HTML methods:

     $q = new CGI3;
     print $q->blockquote(
               "Many years ago on the island of",
               $q->a({href=>"http://crete.org/"},"Crete"),
               "there lived a minotaur named",
               $q->strong("Fred."),
              ),
         $q->hr;

   This results in the following HTML code (extra newlines have been added
for readability):

     <blockquote>
     Many years ago on the island of
     <a HREF="http://crete.org/">Crete</a> there lived
     a minotaur named <strong>Fred.</strong>
     </blockquote>
     <hr>

   If you find the syntax for calling the HTML shortcuts awkward, you can
import them into your namespace and dispense with the object syntax
completely (see the next section for more details):

     use CGI3 ':standard';
     print blockquote(
        "Many years ago on the island of",
        a({href=>"http://crete.org/"},"Crete"),
        "there lived a minotaur named",
        strong("Fred."),
        ),
        hr;

PROVIDING ARGUMENTS TO HTML SHORTCUTS
-------------------------------------

   The HTML methods will accept zero, one or multiple arguments.  If you
provide no arguments, you get a single tag:

     print hr;    #  <HR>

   If you provide one or more string arguments, they are concatenated
together with spaces and placed between opening and closing tags:

     print h1("Chapter","1"); # <H1>Chapter 1</H1>"

   If the first argument is an associative array reference, then the keys
and values of the associative array become the HTML tag's attributes:

     print a({-href=>'fred.html',-target=>'_new'},
        "Open a new frame");

     <A HREF="fred.html",TARGET="_new">Open a new frame</A>

   You may dispense with the dashes in front of the attribute names if you
prefer:

     print img {src=>'fred.gif',align=>'LEFT'};

     <IMG ALIGN="LEFT" SRC="fred.gif">

   Sometimes an HTML tag attribute has no argument.  For example, ordered
lists can be marked as COMPACT.  The syntax for this is an argument that
that points to an undef string:

     print ol({compact=>undef},li('one'),li('two'),li('three'));

   Prior to CGI3.pm version 2.41, providing an empty (") string as an
attribute argument was the same as providing undef.  However, this has
changed in order to accommodate those who want to create tags of the form
<IMG ALT="">.  The difference is shown in these two pieces of code:

     CODE                   RESULT
     img({alt=>undef})      <IMG ALT>
     img({alt=>''})         <IMT ALT="">

THE DISTRIBUTIVE PROPERTY OF HTML SHORTCUTS
-------------------------------------------

   One of the cool features of the HTML shortcuts is that they are
distributive.  If you give them an argument consisting of a reference to a
list, the tag will be distributed across each element of the list.  For
example, here's one way to make an ordered list:

     print ul(
               li({-type=>'disc'},['Sneezy','Doc','Sleepy','Happy']);
             );

   This example will result in HTML output that looks like this:

     <UL>
       <LI TYPE="disc">Sneezy</LI>
       <LI TYPE="disc">Doc</LI>
       <LI TYPE="disc">Sleepy</LI>
       <LI TYPE="disc">Happy</LI>
     </UL>

   This is extremely useful for creating tables.  For example:

     print table({-border=>undef},
             caption('When Should You Eat Your Vegetables?'),
             Tr({-align=>CENTER,-valign=>TOP},
             [
                th(['Vegetable', 'Breakfast','Lunch','Dinner']),
                td(['Tomatoes' , 'no', 'yes', 'yes']),
                td(['Broccoli' , 'no', 'no',  'yes']),
                td(['Onions'   , 'yes','yes', 'yes'])
             ]
             )
          );

HTML SHORTCUTS AND LIST INTERPOLATION
-------------------------------------

   Consider this bit of code:

     print blockquote(em('Hi'),'mom!'));

   It will ordinarily return the string that you probably expect, namely:

     <BLOCKQUOTE><EM>Hi</EM> mom!</BLOCKQUOTE>

   Note the space between the element "Hi" and the element "mom!".
CGI3.pm puts the extra space there using array interpolation, which is
controlled by the magic $" variable.  Sometimes this extra space is not
what you want, for example, when you are trying to align a series of
images.  In this case, you can simply change the value of $" to an empty
string.

     {
        local($") = '';
        print blockquote(em('Hi'),'mom!'));
      }

   I suggest you put the code in a block as shown here.  Otherwise the
change to $" will affect all subsequent code until you explicitly reset it.

NON-STANDARD HTML SHORTCUTS
---------------------------

   A few HTML tags don't follow the standard pattern for various reasons.

   *comment()* generates an HTML comment (<!- comment ->).  Call it like

     print comment('here is my comment');

   Because of conflicts with built-in Perl functions, the following
functions begin with initial caps:

     Select
     Tr
     Link
     Delete
     Accept
     Sub

   In addition, start_html(), end_html(), start_form(), end_form(),
start_multipart_form() and all the fill-out form tags are special.  See
their respective sections.

PRETTY-PRINTING HTML
--------------------

   By default, all the HTML produced by these functions comes out as one
long line without carriage returns or indentation. This is yuck, but it
does reduce the size of the documents by 10-20%.  To get pretty-printed
output, please use CGI3/Pretty, a subclass contributed
by Brian Paulsen.

CREATING FILL-OUT FORMS:
========================

   *General note*  The various form-creating methods all return strings to
the caller, containing the tag or tags that will create the requested form
element.  You are responsible for actually printing out these strings.
It's set up this way so that you can place formatting tags around the form
elements.

   *Another note* The default values that you specify for the forms are
only used the first time the script is invoked (when there is no query
string).  On subsequent invocations of the script (when there is a query
string), the former values are used even if they are blank.

   If you want to change the value of a field from its previous value, you
have two choices:

   (1) call the param() method to set it.

   (2) use the -override (alias -force) parameter (a new feature in
version 2.15).  This forces the default value to be used, regardless of
the previous value:

     print $query->textfield(-name=>'field_name',
                 -default=>'starting value',
                 -override=>1,
                 -size=>50,
                 -maxlength=>80);

   *Yet another note* By default, the text and labels of form elements are
escaped according to HTML rules.  This means that you can safely use
"<CLICK ME>" as the label for a button.  However, it also interferes with
your ability to incorporate special HTML character sequences, such as
&Aacute;, into your fields.  If you wish to turn off automatic escaping,
call the autoEscape() method with a false value immediately after creating
the CGI3 object:

     $query = new CGI3;
     $query->autoEscape(undef);

CREATING AN ISINDEX TAG
-----------------------

     print $query->isindex(-action=>$action);

     -or-

     print $query->isindex($action);

   Prints out an <ISINDEX> tag.  Not very exciting.  The parameter -action
specifies the URL of the script to process the query.  The default is to
process the query with the current script.

STARTING AND ENDING A FORM
--------------------------

     print $query->startform(-method=>$method,
                 -action=>$action,
                 -enctype=>$encoding);
       <... various form stuff ...>
     print $query->endform;

     -or-

     print $query->startform($method,$action,$encoding);
       <... various form stuff ...>
     print $query->endform;

   startform() will return a <FORM> tag with the optional method, action
and form encoding that you specify.  The defaults are:

     method: POST
     action: this script
     enctype: application/x-www-form-urlencoded

   endform() returns the closing </FORM> tag.

   Startform()'s enctype argument tells the browser how to package the
various fields of the form before sending the form to the server.  Two
values are possible:

*application/x-www-form-urlencoded*
     This is the older type of encoding used by all browsers prior to
     Netscape 2.0.  It is compatible with many CGI3 scripts and is
     suitable for short fields containing text data.  For your
     convenience, CGI3.pm stores the name of this encoding type in
     *$CGI3::URL_ENCODED*.

*multipart/form-data*
     This is the newer type of encoding introduced by Netscape 2.0.  It is
     suitable for forms that contain very large fields or that are
     intended for transferring binary data.  Most importantly, it enables
     the "file upload" feature of Netscape 2.0 forms.  For your
     convenience, CGI3.pm stores the name of this encoding type in
     *&CGI3::MULTIPART*

     Forms that use this type of encoding are not easily interpreted by
     CGI3 scripts unless they use CGI3.pm or another library designed to
     handle them.

   For compatibility, the startform() method uses the older form of
encoding by default.  If you want to use the newer form of encoding by
default, you can call *start_multipart_form()* instead of *startform()*.

   JAVASCRIPTING: The *-name* and *-onSubmit* parameters are provided for
use with JavaScript.  The -name parameter gives the form a name so that it
can be identified and manipulated by JavaScript functions.  -onSubmit
should point to a JavaScript function that will be executed just before
the form is submitted to your server.  You can use this opportunity to
check the contents of the form for consistency and completeness.  If you
find something wrong, you can put up an alert box or maybe fix things up
yourself.  You can abort the submission by returning false from this
function.

   Usually the bulk of JavaScript functions are defined in a <SCRIPT>
block in the HTML header and -onSubmit points to one of these function
call.  See start_html() for details.

CREATING A TEXT FIELD
---------------------

     print $query->textfield(-name=>'field_name',
                 -default=>'starting value',
                 -size=>50,
                 -maxlength=>80);
     -or-

     print $query->textfield('field_name','starting value',50,80);

   textfield() will return a text input field.

Parameters

     The first parameter is the required name for the field (-name).

     The optional second parameter is the default starting value for the
     field contents (-default).

     The optional third parameter is the size of the field in
     characters (-size).

     The optional fourth parameter is the maximum number of characters the
          field will accept (-maxlength).

   As with all these methods, the field will be initialized with its
previous contents from earlier invocations of the script.  When the form
is processed, the value of the text field can be retrieved with:

     $value = $query->param('foo');

   If you want to reset it from its initial value after the script has been
called once, you can do so like this:

     $query->param('foo',"I'm taking over this value!");

   NEW AS OF VERSION 2.15: If you don't want the field to take on its
previous value, you can force its current value by using the -override
(alias -force) parameter:

     print $query->textfield(-name=>'field_name',
                 -default=>'starting value',
                 -override=>1,
                 -size=>50,
                 -maxlength=>80);

   JAVASCRIPTING: You can also provide *-onChange*, *-onFocus*, *-onBlur*,
*-onMouseOver*, *-onMouseOut* and *-onSelect* parameters to register
JavaScript event handlers.  The onChange handler will be called whenever
the user changes the contents of the text field.  You can do text
validation if you like.  onFocus and onBlur are called respectively when
the insertion point moves into and out of the text field.  onSelect is
called when the user changes the portion of the text that is selected.

CREATING A BIG TEXT FIELD
-------------------------

     print $query->textarea(-name=>'foo',
                -default=>'starting value',
                -rows=>10,
                -columns=>50);

     -or

     print $query->textarea('foo','starting value',10,50);

   textarea() is just like textfield, but it allows you to specify rows
and columns for a multiline text entry box.  You can provide a starting
value for the field, which can be long and contain multiple lines.

   JAVASCRIPTING: The *-onChange*, *-onFocus*, *-onBlur* , *-onMouseOver*,
*-onMouseOut*, and *-onSelect* parameters are recognized.  See textfield().

CREATING A PASSWORD FIELD
-------------------------

     print $query->password_field(-name=>'secret',
                  -value=>'starting value',
                  -size=>50,
                  -maxlength=>80);
      -or-

     print $query->password_field('secret','starting value',50,80);

   password_field() is identical to textfield(), except that its contents
will be starred out on the web page.

   JAVASCRIPTING: The *-onChange*, *-onFocus*, *-onBlur*, *-onMouseOver*,
*-onMouseOut* and *-onSelect* parameters are recognized.  See textfield().

CREATING A FILE UPLOAD FIELD
----------------------------

     print $query->filefield(-name=>'uploaded_file',
                 -default=>'starting value',
                 -size=>50,
                 -maxlength=>80);
     -or-

     print $query->filefield('uploaded_file','starting value',50,80);

   filefield() will return a file upload field for Netscape 2.0 browsers.
In order to take full advantage of this *you must use the new multipart
encoding scheme* for the form.  You can do this either by calling
*startform()* with an encoding type of *$CGI3::MULTIPART*, or by calling
the new method *start_multipart_form()* instead of vanilla *startform()*.

Parameters

     The first parameter is the required name for the field (-name).

     The optional second parameter is the starting value for the field
     contents to be used as the default file name (-default).

     For security reasons, browsers don't pay any attention to this field,
     and so the starting value will always be blank.  Worse, the field
     loses its "sticky" behavior and forgets its previous contents.  The
     starting value field is called for in the HTML specification, however,
     and possibly some browser will eventually provide support for it.

     The optional third parameter is the size of the field in characters
     (-size).

     The optional fourth parameter is the maximum number of characters the
     field will accept (-maxlength).

   When the form is processed, you can retrieve the entered filename by
calling param().

     $filename = $query->param('uploaded_file');

   In Netscape Navigator 2.0, the filename that gets returned is the full
local filename on the *remote user's* machine.  If the remote user is on a
Unix machine, the filename will follow Unix conventions:

     /path/to/the/file

   On an MS-DOS/Windows and OS/2 machines, the filename will follow DOS
conventions:

     C:\PATH\TO\THE\FILE.MSW

   On a Macintosh machine, the filename will follow Mac conventions:

     HD 40:Desktop Folder:Sort Through:Reminders

   The filename returned is also a file handle.  You can read the contents
of the file using standard Perl file reading calls:

     # Read a text file and print it out
     while (<$filename>) {
        print;
     }

     # Copy a binary file to somewhere safe
     open (OUTFILE,">>/usr/local/web/users/feedback");
     while ($bytesread=read($filename,$buffer,1024)) {
        print OUTFILE $buffer;
     }

   When a file is uploaded the browser usually sends along some
information along with it in the format of headers.  The information
usually includes the MIME content type.  Future browsers may send other
information as well (such as modification date and size). To retrieve this
information, call uploadInfo().  It returns a reference to an associative
array containing all the document headers.

     $filename = $query->param('uploaded_file');
     $type = $query->uploadInfo($filename)->{'Content-Type'};
     unless ($type eq 'text/html') {
           die "HTML FILES ONLY!";
     }

   If you are using a machine that recognizes "text" and "binary" data
modes, be sure to understand when and how to use them (see the Camel book).
Otherwise you may find that binary files are corrupted during file uploads.

   JAVASCRIPTING: The *-onChange*, *-onFocus*, *-onBlur*, *-onMouseOver*,
*-onMouseOut* and *-onSelect* parameters are recognized.  See textfield()
for details.

CREATING A POPUP MENU
---------------------

     print $query->popup_menu('menu_name',
                  ['eenie','meenie','minie'],
                  'meenie');

     -or-

     %labels = ('eenie'=>'your first choice',
            'meenie'=>'your second choice',
            'minie'=>'your third choice');
     print $query->popup_menu('menu_name',
                  ['eenie','meenie','minie'],
                  'meenie',\%labels);

     -or (named parameter style)-

     print $query->popup_menu(-name=>'menu_name',
                  -values=>['eenie','meenie','minie'],
                  -default=>'meenie',
                  -labels=>\%labels);

   popup_menu() creates a menu.

  1. The required first argument is the menu's name (-name).

  2. The required second argument (-values) is an array reference
     containing the list of menu items in the menu.  You can pass the
     method an anonymous array, as shown in the example, or a reference to
     a named array, such as "\@foo".

  3. The optional third parameter (-default) is the name of the default
     menu choice.  If not specified, the first item will be the default.
     The values of the previous choice will be maintained across queries.

  4. The optional fourth parameter (-labels) is provided for people who
     want to use different values for the user-visible label inside the
     popup menu nd the value returned to your script.  It's a pointer to an
     associative array relating menu values to user-visible labels.  If you
     leave this parameter blank, the menu values will be displayed by
     default.  (You can also leave a label undefined if you want to).

        When the form is processed, the selected value of the popup menu
can be retrieved using:

     $popup_menu_value = $query->param('menu_name');

   JAVASCRIPTING: popup_menu() recognizes the following event handlers:
*-onChange*, *-onFocus*, *-onMouseOver*, *-onMouseOut*, and *-onBlur*.
See the textfield() section for details on when these handlers are called.

CREATING A SCROLLING LIST
-------------------------

     print $query->scrolling_list('list_name',
                  ['eenie','meenie','minie','moe'],
                  ['eenie','moe'],5,'true');
        -or-

     print $query->scrolling_list('list_name',
                  ['eenie','meenie','minie','moe'],
                  ['eenie','moe'],5,'true',
                  \%labels);

     -or-

     print $query->scrolling_list(-name=>'list_name',
                  -values=>['eenie','meenie','minie','moe'],
                  -default=>['eenie','moe'],
                  -size=>5,
                  -multiple=>'true',
                  -labels=>\%labels);

   scrolling_list() creates a scrolling list.

Parameters:

     The first and second arguments are the list name (-name) and values
     (-values).  As in the popup menu, the second argument should be an
     array reference.

     The optional third argument (-default) can be either a reference to a
     list containing the values to be selected by default, or can be a
     single value to select.  If this argument is missing or undefined,
     then nothing is selected when the list first appears.  In the named
     parameter version, you can use the synonym "-defaults" for this
     parameter.

     The optional fourth argument is the size of the list (-size).

     The optional fifth argument can be set to true to allow multiple
     simultaneous selections (-multiple).  Otherwise only one selection
     will be allowed at a time.

     The optional sixth argument is a pointer to an associative array
     containing long user-visible labels for the list items (-labels).  If
     not provided, the values will be displayed.

     When this form is processed, all selected list items will be returned
     as a list under the parameter name 'list_name'.  The values of the
     selected items can be retrieved with:

          @selected = $query->param('list_name');

   JAVASCRIPTING: scrolling_list() recognizes the following event
handlers: *-onChange*, *-onFocus*, *-onMouseOver*, *-onMouseOut* and
*-onBlur*.  See textfield() for the description of when these handlers are
called.

CREATING A GROUP OF RELATED CHECKBOXES
--------------------------------------

     print $query->checkbox_group(-name=>'group_name',
                  -values=>['eenie','meenie','minie','moe'],
                  -default=>['eenie','moe'],
                  -linebreak=>'true',
                  -labels=>\%labels);

     print $query->checkbox_group('group_name',
                  ['eenie','meenie','minie','moe'],
                  ['eenie','moe'],'true',\%labels);

     HTML3-COMPATIBLE BROWSERS ONLY:

     print $query->checkbox_group(-name=>'group_name',
                  -values=>['eenie','meenie','minie','moe'],
                  -rows=2,-columns=>2);

   checkbox_group() creates a list of checkboxes that are related by the
same name.

Parameters:

     The first and second arguments are the checkbox name and values,
     respectively (-name and -values).  As in the popup menu, the second
     argument should be an array reference.  These values are used for the
     user-readable labels printed next to the checkboxes as well as for the
     values passed to your script in the query string.

     The optional third argument (-default) can be either a reference to a
     list containing the values to be checked by default, or can be a
     single value to checked.  If this argument is missing or undefined,
     then nothing is selected when the list first appears.

     The optional fourth argument (-linebreak) can be set to true to place
     line breaks between the checkboxes so that they appear as a vertical
     list.  Otherwise, they will be strung together on a horizontal line.

     The optional fifth argument is a pointer to an associative array
     relating the checkbox values to the user-visible labels that will be
     printed next to them (-labels).  If not provided, the values will be
     used as the default.

     *HTML3-compatible browsers* (such as Netscape) can take advantage of
     the optional parameters *-rows*, and *-columns*.  These parameters
     cause checkbox_group() to return an HTML3 compatible table containing
     the checkbox group formatted with the specified number of rows and
     columns.  You can provide just the -columns parameter if you wish;
     checkbox_group will calculate the correct number of rows for you.

     To include row and column headings in the returned table, you can use
     the *-rowheaders* and *-colheaders* parameters.  Both of these accept
     a pointer to an array of headings to use.  The headings are just
     decorative.  They don't reorganize the interpretation of the
     checkboxes - they're still a single named unit.

   When the form is processed, all checked boxes will be returned as a
list under the parameter name 'group_name'.  The values of the "on"
checkboxes can be retrieved with:

     @turned_on = $query->param('group_name');

   The value returned by checkbox_group() is actually an array of button
elements.  You can capture them and use them within tables, lists, or in
other creative ways:

     @h = $query->checkbox_group(-name=>'group_name',-values=>\@values);
     &use_in_creative_way(@h);

   JAVASCRIPTING: checkbox_group() recognizes the *-onClick* parameter.
This specifies a JavaScript code fragment or function call to be executed
every time the user clicks on any of the buttons in the group.  You can
retrieve the identity of the particular button clicked on using the "this"
variable.

CREATING A STANDALONE CHECKBOX
------------------------------

     print $query->checkbox(-name=>'checkbox_name',
                -checked=>'checked',
                -value=>'ON',
                -label=>'CLICK ME');

     -or-

     print $query->checkbox('checkbox_name','checked','ON','CLICK ME');

   checkbox() is used to create an isolated checkbox that isn't logically
related to any others.

Parameters:

     The first parameter is the required name for the checkbox (-name).  It
     will also be used for the user-readable label printed next to the
     checkbox.

     The optional second parameter (-checked) specifies that the checkbox
     is turned on by default.  Synonyms are -selected and -on.

     The optional third parameter (-value) specifies the value of the
     checkbox when it is checked.  If not provided, the word "on" is
     assumed.

     The optional fourth parameter (-label) is the user-readable label to
     be attached to the checkbox.  If not provided, the checkbox name is
     used.

   The value of the checkbox can be retrieved using:

     $turned_on = $query->param('checkbox_name');

   JAVASCRIPTING: checkbox() recognizes the *-onClick* parameter.  See
checkbox_group() for further details.

CREATING A RADIO BUTTON GROUP
-----------------------------

     print $query->radio_group(-name=>'group_name',
                   -values=>['eenie','meenie','minie'],
                   -default=>'meenie',
                   -linebreak=>'true',
                   -labels=>\%labels);

     -or-

     print $query->radio_group('group_name',['eenie','meenie','minie'],
                        'meenie','true',\%labels);

     HTML3-COMPATIBLE BROWSERS ONLY:

     print $query->radio_group(-name=>'group_name',
                   -values=>['eenie','meenie','minie','moe'],
                   -rows=2,-columns=>2);

   radio_group() creates a set of logically-related radio buttons (turning
one member of the group on turns the others off)

Parameters:

     The first argument is the name of the group and is required (-name).

     The second argument (-values) is the list of values for the radio
     buttons.  The values and the labels that appear on the page are
     identical.  Pass an array reference in the second argument, either
     using an anonymous array, as shown, or by referencing a named array as
     in "\@foo".

     The optional third parameter (-default) is the name of the default
     button to turn on. If not specified, the first item will be the
     default.  You can provide a nonexistent button name, such as "-" to
     start up with no buttons selected.

     The optional fourth parameter (-linebreak) can be set to 'true' to put
     line breaks between the buttons, creating a vertical list.

     The optional fifth parameter (-labels) is a pointer to an associative
     array relating the radio button values to user-visible labels to be
     used in the display.  If not provided, the values themselves are
     displayed.

     *HTML3-compatible browsers* (such as Netscape) can take advantage of
     the optional parameters *-rows*, and *-columns*.  These parameters
     cause radio_group() to return an HTML3 compatible table containing
     the radio group formatted with the specified number of rows and
     columns.  You can provide just the -columns parameter if you wish;
     radio_group will calculate the correct number of rows for you.

     To include row and column headings in the returned table, you can use
     the *-rowheader* and *-colheader* parameters.  Both of these accept a
     pointer to an array of headings to use.  The headings are just
     decorative.  They don't reorganize the interpretation of the radio
     buttons - they're still a single named unit.

   When the form is processed, the selected radio button can be retrieved
using:

     $which_radio_button = $query->param('group_name');

   The value returned by radio_group() is actually an array of button
elements.  You can capture them and use them within tables, lists, or in
other creative ways:

     @h = $query->radio_group(-name=>'group_name',-values=>\@values);
     &use_in_creative_way(@h);

CREATING A SUBMIT BUTTON
------------------------

     print $query->submit(-name=>'button_name',
              -value=>'value');

     -or-

     print $query->submit('button_name','value');

   submit() will create the query submission button.  Every form should
have one of these.

Parameters:

     The first argument (-name) is optional.  You can give the button a
     name if you have several submission buttons in your form and you want
     to distinguish between them.  The name will also be used as the
     user-visible label.  Be aware that a few older browsers don't deal
     with this correctly and never send back a value from a button.

     The second argument (-value) is also optional.  This gives the button
     a value that will be passed to your script in the query string.

   You can figure out which button was pressed by using different values
for each one:

     $which_one = $query->param('button_name');

   JAVASCRIPTING: radio_group() recognizes the *-onClick* parameter.  See
checkbox_group() for further details.

CREATING A RESET BUTTON
-----------------------

     print $query->reset

   reset() creates the "reset" button.  Note that it restores the form to
its value from the last time the script was called, NOT necessarily to the
defaults.

   Note that this conflicts with the Perl reset() built-in.  Use
CORE::reset() to get the original reset function.

CREATING A DEFAULT BUTTON
-------------------------

     print $query->defaults('button_label')

   defaults() creates a button that, when invoked, will cause the form to
be completely reset to its defaults, wiping out all the changes the user
ever made.

CREATING A HIDDEN FIELD
-----------------------

     print $query->hidden(-name=>'hidden_name',
                  -default=>['value1','value2'...]);

     -or-

     print $query->hidden('hidden_name','value1','value2'...);

   hidden() produces a text field that can't be seen by the user.  It is
useful for passing state variable information from one invocation of the
script to the next.

Parameters:

     The first argument is required and specifies the name of this field
     (-name).

     The second argument is also required and specifies its value
     (-default).  In the named parameter style of calling, you can provide
     a single value here or a reference to a whole list

   Fetch the value of a hidden field this way:

     $hidden_value = $query->param('hidden_name');

   Note, that just like all the other form elements, the value of a hidden
field is "sticky".  If you want to replace a hidden field with some other
values after the script has been called once you'll have to do it manually:

     $query->param('hidden_name','new','values','here');

CREATING A CLICKABLE IMAGE BUTTON
---------------------------------

     print $query->image_button(-name=>'button_name',
                -src=>'/source/URL',
                -align=>'MIDDLE');

     -or-

     print $query->image_button('button_name','/source/URL','MIDDLE');

   image_button() produces a clickable image.  When it's clicked on the
position of the click is returned to your script as "button_name.x" and
"button_name.y", where "button_name" is the name you've assigned to it.

   JAVASCRIPTING: image_button() recognizes the *-onClick* parameter.  See
checkbox_group() for further details.

Parameters:

     The first argument (-name) is required and specifies the name of this
     field.

     The second argument (-src) is also required and specifies the URL

The third option (-align, optional) is an alignment type, and may be TOP, BOTTOM or MIDDLE
   Fetch the value of the button this way:      $x =
$query->param('button_name.x');      $y = $query->param('button_name.y');

CREATING A JAVASCRIPT ACTION BUTTON
-----------------------------------

     print $query->button(-name=>'button_name',
              -value=>'user visible label',
              -onClick=>"do_something()");

     -or-

     print $query->button('button_name',"do_something()");

   button() produces a button that is compatible with Netscape 2.0's
JavaScript.  When it's pressed the fragment of JavaScript code pointed to
by the *-onClick* parameter will be executed.  On non-Netscape browsers
this form element will probably not even display.

HTTP COOKIES
============

   Netscape browsers versions 1.1 and higher, and all versions of Internet
Explorer, support a so-called "cookie" designed to help maintain state
within a browser session.  CGI3.pm has several methods that support
cookies.

   A cookie is a name=value pair much like the named parameters in a CGI3
query string.  CGI3 scripts create one or more cookies and send them to
the browser in the HTTP header.  The browser maintains a list of cookies
that belong to a particular Web server, and returns them to the CGI3
script during subsequent interactions.

   In addition to the required name=value pair, each cookie has several
optional attributes:

  1. an expiration time This is a time/date string (in a special GMT
     format) that indicates when a cookie expires.  The cookie will be
     saved and returned to your script until this expiration date is
     reached if the user exits the browser and restarts it.  If an
     expiration date isn't specified, the cookie will remain active until
     the user quits the browser.

  2. a domain This is a partial or complete domain name for which the
     cookie is valid.  The browser will return the cookie to any host that
     matches the partial domain name.  For example, if you specify a
     domain name of ".capricorn.com", then the browser will return the
     cookie to Web servers running on any of the machines
     "www.capricorn.com", "www2.capricorn.com", "feckless.capricorn.com",
     etc.  Domain names must contain at least two periods to prevent
     attempts to match on top level domains like ".edu".  If no domain is
     specified, then the browser will only return the cookie to servers on
     the host the cookie originated from.

  3. a path If you provide a cookie path attribute, the browser will check
     it against your script's URL before returning the cookie.  For
     example, if you specify the path "/cgi-bin", then the cookie will be
     returned to each of the scripts "/cgi-bin/tally.pl",
     "/cgi-bin/order.pl", and "/cgi-bin/customer_service/complain.pl", but
     not to the script "/cgi-private/site_admin.pl".  By default, path is
     set to "/", which causes the cookie to be sent to any CGI3 script on
     your site.

  4. a "secure" flag If the "secure" attribute is set, the cookie will
     only be sent to your script if the CGI3 request is occurring on a
     secure channel, such as SSL.

        The interface to HTTP cookies is the *cookie()* method:

     $cookie = $query->cookie(-name=>'sessionID',
                  -value=>'xyzzy',
                  -expires=>'+1h',
                  -path=>'/cgi-bin/database',
                  -domain=>'.capricorn.org',
                  -secure=>1);
     print $query->header(-cookie=>$cookie);

   *cookie()* creates a new cookie.  Its parameters include:

*-name*
     The name of the cookie (required).  This can be any string at all.
     Although browsers limit their cookie names to non-whitespace
     alphanumeric characters, CGI3.pm removes this restriction by escaping
     and unescaping cookies behind the scenes.

*-value*
     The value of the cookie.  This can be any scalar value, array
     reference, or even associative array reference.  For example, you can
     store an entire associative array into a cookie this way:

          $cookie=$query->cookie(-name=>'family information',
                         -value=>\%childrens_ages);

*-path*
     The optional partial path for which this cookie will be valid, as
     described above.

*-domain*
     The optional partial domain for which this cookie will be valid, as
     described above.

*-expires*
     The optional expiration date for this cookie.  The format is as
     described in the section on the header() method:

          "+1h"  one hour from now

*-secure*
     If set to true, this cookie will only be used within a secure SSL
     session.

   The cookie created by cookie() must be incorporated into the HTTP
header within the string returned by the header() method:

     print $query->header(-cookie=>$my_cookie);

   To create multiple cookies, give header() an array reference:

     $cookie1 = $query->cookie(-name=>'riddle_name',
                   -value=>"The Sphynx's Question");
     $cookie2 = $query->cookie(-name=>'answers',
                   -value=>\%answers);
     print $query->header(-cookie=>[$cookie1,$cookie2]);

   To retrieve a cookie, request it by name by calling cookie() method
without the *-value* parameter:

     use CGI3;
     $query = new CGI3;
     %answers = $query->cookie(-name=>'answers');
     # $query->cookie('answers') will work too!

   The cookie and CGI3 namespaces are separate.  If you have a parameter
named 'answers' and a cookie named 'answers', the values retrieved by
param() and cookie() are independent of each other.  However, it's simple
to turn a CGI3 parameter into a cookie, and vice-versa:

     # turn a CGI3 parameter into a cookie
     $c=$q->cookie(-name=>'answers',-value=>[$q->param('answers')]);
     # vice-versa
     $q->param(-name=>'answers',-value=>[$q->cookie('answers')]);

   See the *cookie.cgi* example script for some ideas on how to use
cookies effectively.

WORKING WITH FRAMES
===================

   It's possible for CGI3.pm scripts to write into several browser panels
and windows using the HTML 4 frame mechanism.  There are three techniques
for defining new frames programmatically:

  1. Create a <Frameset> document After writing out the HTTP header,
     instead of creating a standard HTML document using the start_html()
     call, create a <FRAMESET> document that defines the frames on the
     page.  Specify your script(s) (with appropriate parameters) as the
     SRC for each of the frames.

     There is no specific support for creating <FRAMESET> sections in
     CGI3.pm, but the HTML is very simple to write.  See the frame
     documentation in Netscape's home pages for details

          http://home.netscape.com/assist/net_sites/frames.html

  2. Specify the destination for the document in the HTTP header You may
     provide a *-target* parameter to the header() method:

          print $q->header(-target=>'ResultsWindow');

     This will tell the browser to load the output of your script into the
     frame named "ResultsWindow".  If a frame of that name doesn't already
     exist, the browser will pop up a new window and load your script's
     document into that.  There are a number of magic names that you can
     use for targets.  See the frame documents on Netscape's home pages for
     details.

  3. Specify the destination for the document in the <FORM> tag You can
     specify the frame to load in the FORM tag itself.  With CGI3.pm it
     looks like this:

          print $q->startform(-target=>'ResultsWindow');

     When your script is reinvoked by the form, its output will be loaded
     into the frame named "ResultsWindow".  If one doesn't already exist a
     new window will be created.

        The script "frameset.cgi" in the examples directory shows one way
to create pages in which the fill-out form and the response live in
side-by-side frames.

LIMITED SUPPORT FOR CASCADING STYLE SHEETS
==========================================

   CGI3.pm has limited support for HTML3's cascading style sheets (css).
To incorporate a stylesheet into your document, pass the start_html()
method a *-style* parameter.  The value of this parameter may be a scalar,
in which case it is incorporated directly into a <STYLE> section, or it
may be a hash reference.  In the latter case you should provide the hash
with one or more of *-src* or *-code*.  *-src* points to a URL where an
externally-defined stylesheet can be found.  *-code* points to a scalar
value to be incorporated into a <STYLE> section.  Style definitions in
*-code* override similarly-named ones in *-src*, hence the name
"cascading."

   You may also specify the type of the stylesheet by adding the optional
*-type* parameter to the hash pointed to by *-style*.  If not specified,
the style defaults to 'text/css'.

   To refer to a style within the body of your document, add the *-class*
parameter to any HTML element:

     print h1({-class=>'Fancy'},'Welcome to the Party');

   Or define styles on the fly with the *-style* parameter:

     print h1({-style=>'Color: red;'},'Welcome to Hell');

   You may also use the new *span()* element to apply a style to a section
of text:

     print span({-style=>'Color: red;'},
            h1('Welcome to Hell'),
            "Where did that handbasket get to?"
            );

   Note that you must import the ":html3" definitions to have the *span()*
method available.  Here's a quick and dirty example of using CSS's.  See
the CSS specification at http://www.w3.org/pub/WWW/TR/Wd-css-1.html for
more information.

     use CGI3 qw/:standard :html3/;

     #here's a stylesheet incorporated directly into the page
     $newStyle=<<END;
     <!--
     P.Tip {
     margin-right: 50pt;
     margin-left: 50pt;
         color: red;
     }
     P.Alert {
     font-size: 30pt;
         font-family: sans-serif;
       color: red;
     }
     -->
     END
     print header();
     print start_html( -title=>'CGI3 with Style',
               -style=>{-src=>'http://www.capricorn.com/style/st1.css',
                        -code=>$newStyle}
                  );
     print h1('CGI3 with Style'),
           p({-class=>'Tip'},
         "Better read the cascading style sheet spec before playing with this!"),
           span({-style=>'color: magenta'},
            "Look Mom, no hands!",
            p(),
            "Whooo wee!"
            );
     print end_html;

DEBUGGING
=========

   If you are running the script from the command line or in the perl
debugger, you can pass the script a list of keywords or parameter=value
pairs on the command line or from standard input (you don't have to worry
about tricking your script into reading from environment variables).  You
can pass keywords like this:

     your_script.pl keyword1 keyword2 keyword3

   or this:

     your_script.pl keyword1+keyword2+keyword3

   or this:

     your_script.pl name1=value1 name2=value2

   or this:

     your_script.pl name1=value1&name2=value2

   or even as newline-delimited parameters on standard input.

   When debugging, you can use quotes and backslashes to escape characters
in the familiar shell manner, letting you place spaces and other funny
characters in your parameter=value pairs:

     your_script.pl "name1='I am a long value'" "name2=two\ words"

DUMPING OUT ALL THE NAME/VALUE PAIRS
------------------------------------

   The dump() method produces a string consisting of all the query's
name/value pairs formatted nicely as a nested list.  This is useful for
debugging purposes:

     print $query->dump

   Produces something that looks like:

     <UL>
     <LI>name1
     <UL>
     <LI>value1
     <LI>value2
     </UL>
     <LI>name2
     <UL>
     <LI>value1
     </UL>
     </UL>

   As a shortcut, you can interpolate the entire CGI3 object into a string
and it will be replaced with the a nice HTML dump shown above:

     $query=new CGI3;
     print "<H2>Current Values</H2> $query\n";

FETCHING ENVIRONMENT VARIABLES
==============================

   Some of the more useful environment variables can be fetched through
this interface.  The methods are as follows:

Accept()
     Return a list of MIME types that the remote browser accepts. If you
     give this method a single argument corresponding to a MIME type, as in
     $query->Accept('text/html'), it will return a floating point value
     corresponding to the browser's preference for this type from 0.0
     (don't want) to 1.0.  Glob types (e.g. text/*) in the browser's accept
     list are handled correctly.

     Note that the capitalization changed between version 2.43 and 2.44 in
     order to avoid conflict with Perl's accept() function.

raw_cookie()
     Returns the HTTP_COOKIE variable, an HTTP extension implemented by
     Netscape browsers version 1.1 and higher, and all versions of Internet
     Explorer.  Cookies have a special format, and this method call just
     returns the raw form (?cookie dough).  See cookie() for ways of
     setting and retrieving cooked cookies.

     Called with no parameters, raw_cookie() returns the packed cookie
     structure.  You can separate it into individual cookies by splitting
     on the character sequence "; ".  Called with the name of a cookie,
     retrieves the *unescaped* form of the cookie.  You can use the
     regular cookie() method to get the names, or use the raw_fetch()
     method from the CGI3::Cookie module.

user_agent()
     Returns the HTTP_USER_AGENT variable.  If you give this method a
     single argument, it will attempt to pattern match on it, allowing you
     to do something like $query->user_agent(netscape);

path_info()
     Returns additional path information from the script URL.  E.G.
     fetching /cgi-bin/your_script/additional/stuff will result in
     $query->path_info() returning "additional/stuff".

     NOTE: The Microsoft Internet Information Server is broken with
     respect to additional path information.  If you use the Perl DLL
     library, the IIS server will attempt to execute the additional path
     information as a Perl script.  If you use the ordinary file
     associations mapping, the path information will be present in the
     environment, but incorrect.  The best thing to do is to avoid using
     additional path information in CGI3 scripts destined for use with IIS.

path_translated()
     As per path_info() but returns the additional path information
     translated into a physical path, e.g.
     "/usr/local/etc/httpd/htdocs/additional/stuff".

     The Microsoft IIS is broken with respect to the translated path as
     well.

remote_host()
     Returns either the remote host name or IP address.  if the former is
     unavailable.

script_name() Return the script name as a partial URL, for self-refering scripts.
referer()
     Return the URL of the page the browser was viewing prior to fetching
     your script.  Not available for all browsers.

*auth_type ()*
     Return the authorization/verification method in use for this script,
     if any.

*server_name ()*
     Returns the name of the server, usually the machine's host name.

*virtual_host ()*
     When using virtual hosts, returns the name of the host that the
     browser attempted to contact

*server_software ()*
     Returns the server software and version number.

*remote_user ()*
     Return the authorization/verification name used for user
     verification, if this script is protected.

*user_name ()*
     Attempt to obtain the remote user's name, using a variety of different
     techniques.  This only works with older browsers such as Mosaic.
     Newer browsers do not report the user name for privacy reasons!

request_method()
     Returns the method used to access your script, usually one of 'POST',
     'GET' or 'HEAD'.

USING NPH SCRIPTS
=================

   NPH, or "no-parsed-header", scripts bypass the server completely by
sending the complete HTTP header directly to the browser.  This has slight
performance benefits, but is of most use for taking advantage of HTTP
extensions that are not directly supported by your server, such as server
push and PICS headers.

   Servers use a variety of conventions for designating CGI3 scripts as
NPH.  Many Unix servers look at the beginning of the script's name for the
prefix "nph-".  The Macintosh WebSTAR server and Microsoft's Internet
Information Server, in contrast, try to decide whether a program is an NPH
script by examining the first line of script output.

   CGI3.pm supports NPH scripts with a special NPH mode.  When in this
mode, CGI3.pm will output the necessary extra header information when the
header() and redirect() methods are called.

   The Microsoft Internet Information Server requires NPH mode.  As of
version 2.30, CGI3.pm will automatically detect when the script is running
under IIS and put itself into this mode.  You do not need to do this
manually, although it won't hurt anything if you do.

   There are a number of ways to put CGI3.pm into NPH mode:

In the use statement
     Simply add the "-nph" pragmato the list of symbols to be imported into
     your script:

          use CGI3 qw(:standard -nph)

By calling the *nph()* method:
     Call *nph()* with a non-zero parameter at any point after using
     CGI3.pm in your program.

          CGI3->nph(1)

By using *-nph* parameters in the header() and *redirect()*  statements:
          print $q->header(-nph=>1);

Server Push
===========

   CGI3.pm provides three simple functions for producing multipart
documents of the type needed to implement server push.  These functions
were graciously provided by Ed Jordan <ed@fidalgo.net>.  To import these
into your namespace, you must import the ":push" set.  You are also
advised to put the script into NPH mode and to set $| to 1 to avoid
buffering problems.

   Here is a simple script that demonstrates server push:

     #!/usr/local/bin/perl
     use CGI3 qw/:push -nph/;
     $| = 1;
     print multipart_init(-boundary=>'----------------here we go!');
     while (1) {
         print multipart_start(-type=>'text/plain'),
               "The current time is ",scalar(localtime),"\n",
               multipart_end;
         sleep 1;
     }

   This script initializes server push by calling multipart_init().  It
then enters an infinite loop in which it begins a new multipart section by
calling multipart_start(), prints the current local time, and ends a
multipart section with multipart_end().  It then sleeps a second, and
begins again.

multipart_init()
          multipart_init(-boundary=>$boundary);

     Initialize the multipart system.  The -boundary argument specifies
     what MIME boundary string to use to separate parts of the document.
     If not provided, CGI3.pm chooses a reasonable boundary for you.

multipart_start()
          multipart_start(-type=>$type)

     Start a new part of the multipart document using the specified MIME
     type.  If not specified, text/html is assumed.

multipart_end()
          multipart_end()

     End a part.  You must remember to call multipart_end() once for each
     multipart_start().

   Users interested in server push applications should also have a look at
the CGI3::Push module.

Avoiding Denial of Service Attacks
==================================

   A potential problem with CGI3.pm is that, by default, it attempts to
process form POSTings no matter how large they are.  A wily hacker could
attack your site by sending a CGI3 script a huge POST of many megabytes.
CGI3.pm will attempt to read the entire POST into a variable, growing
hugely in size until it runs out of memory.  While the script attempts to
allocate the memory the system may slow down dramatically.  This is a form
of denial of service attack.

   Another possible attack is for the remote user to force CGI3.pm to
accept a huge file upload.  CGI3.pm will accept the upload and store it in
a temporary directory even if your script doesn't expect to receive an
uploaded file.  CGI3.pm will delete the file automatically when it
terminates, but in the meantime the remote user may have filled up the
server's disk space, causing problems for other programs.

   The best way to avoid denial of service attacks is to limit the amount
of memory, CPU time and disk space that CGI3 scripts can use.  Some Web
servers come with built-in facilities to accomplish this. In other cases,
you can use the shell limit or *ulimit* commands to put ceilings on CGI3
resource usage.

   CGI3.pm also has some simple built-in protections against denial of
service attacks, but you must activate them before you can use them.
These take the form of two global variables in the CGI3 name space:

$CGI3::POST_MAX
     If set to a non-negative integer, this variable puts a ceiling on the
     size of POSTings, in bytes.  If CGI3.pm detects a POST that is
     greater than the ceiling, it will immediately exit with an error
     message.  This value will affect both ordinary POSTs and multipart
     POSTs, meaning that it limits the maximum size of file uploads as
     well.  You should set this to a reasonably high value, such as 1
     megabyte.

$CGI3::DISABLE_UPLOADS
     If set to a non-zero value, this will disable file uploads
     completely.  Other fill-out form values will work as usual.

   You can use these variables in either of two ways.

*1. On a script-by-script basis*
     Set the variable at the top of the script, right after the "use"
     statement:

          use CGI3 qw/:standard/;
          use CGI3::Carp 'fatalsToBrowser';
          $CGI3::POST_MAX=1024 * 100;  # max 100K posts
          $CGI3::DISABLE_UPLOADS = 1;  # no uploads

*2. Globally for all scripts*
     Open up CGI3.pm, find the definitions for $POST_MAX and
     $DISABLE_UPLOADS, and set them to the desired values.  You'll find
     them towards the top of the file in a subroutine named
     initialize_globals().

   Since an attempt to send a POST larger than $POST_MAX bytes will cause
a fatal error, you might want to use CGI3::Carp to echo the fatal error
message to the browser window as shown in the example above.  Otherwise
the remote user will see only a generic "Internal Server" error message.
See the `CGI3::Carp' in this node manual page for more details.

COMPATIBILITY WITH CGI3-LIB.PL
==============================

   To make it easier to port existing programs that use cgi-lib.pl the
compatibility routine "ReadParse" is provided.  Porting is simple:

   OLD VERSION     require "cgi-lib.pl";     &ReadParse;     print "The
value of the antique is $in{antique}.\n";

   NEW VERSION     use CGI3;     CGI3::ReadParse     print "The value of
the antique is $in{antique}.\n";

   CGI3.pm's ReadParse() routine creates a tied variable named %in, which
can be accessed to obtain the query variables.  Like ReadParse, you can
also provide your own variable.  Infrequently used features of ReadParse,
such as the creation of @in and $in variables, are not supported.

   Once you use ReadParse, you can retrieve the query object itself this
way:

     $q = $in{CGI3};
     print $q->textfield(-name=>'wow',
             -value=>'does this really work?');

   This allows you to start using the more interesting features of CGI3.pm
without rewriting your old scripts from scratch.

AUTHOR INFORMATION
==================

   Copyright 1995-1998, Lincoln D. Stein.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Address bug reports and comments to: lstein@cshl.org.  When sending bug
reports, please provide the version of CGI3.pm, the version of Perl, the
name and version of your Web server, and the name and version of the
operating system you are using.  If the problem is even remotely browser
dependent, please provide information about the affected browers as well.

CREDITS
=======

   Thanks very much to:

Matt Heffron (heffron@falstaff.css.beckman.com)
James Taylor (james.taylor@srs.gov)
Scott Anguish <sanguish@digifix.com>
Mike Jewell (mlj3u@virginia.edu)
Timothy Shimmin (tes@kbs.citri.edu.au)
Joergen Haegg (jh@axis.se)
Laurent Delfosse (delfosse@delfosse.com)
Richard Resnick (applepi1@aol.com)
Craig Bishop (csb@barwonwater.vic.gov.au)
Tony Curtis (tc@vcpc.univie.ac.at)
Tim Bunce (Tim.Bunce@ig.co.uk)
Tom Christiansen (tchrist@convex.com)
Andreas Koenig (k@franz.ww.TU-Berlin.DE)
Tim MacKenzie (Tim.MacKenzie@fulcrum.com.au)
Kevin B. Hendricks (kbhend@dogwood.tyler.wm.edu)
Stephen Dahmen (joyfire@inxpress.net)
Ed Jordan (ed@fidalgo.net)
David Alan Pisoni (david@cnation.com)
Doug MacEachern (dougm@opengroup.org)
Robin Houston (robin@oneworld.org)
...and many many more...
     for suggestions and bug fixes.

A COMPLETE EXAMPLE OF A SIMPLE FORM-BASED SCRIPT
================================================

     #!/usr/local/bin/perl

     use CGI3;

     $query = new CGI3;

     print $query->header;
     print $query->start_html("Example CGI3.pm Form");
     print "<H1> Example CGI3.pm Form</H1>\n";
     &print_prompt($query);
     &do_work($query);
     &print_tail;
     print $query->end_html;

     sub print_prompt {
        my($query) = @_;

     print $query->startform;
     print "<EM>What's your name?</EM><BR>";
     print $query->textfield('name');
     print $query->checkbox('Not my real name');

     print "<P><EM>Where can you find English Sparrows?</EM><BR>";
     print $query->checkbox_group(
               -name=>'Sparrow locations',
               -values=>[England,France,Spain,Asia,Hoboken],
               -linebreak=>'yes',
               -defaults=>[England,Asia]);

     print "<P><EM>How far can they fly?</EM><BR>",
      $query->radio_group(
          -name=>'how far',
          -values=>['10 ft','1 mile','10 miles','real far'],
          -default=>'1 mile');

     print "<P><EM>What's your favorite color?</EM>  ";
     print $query->popup_menu(-name=>'Color',
                  -values=>['black','brown','red','yellow'],
                  -default=>'red');

     print $query->hidden('Reference','Monty Python and the Holy Grail');

     print "<P><EM>What have you got there?</EM><BR>";
     print $query->scrolling_list(
           -name=>'possessions',
           -values=>['A Coconut','A Grail','An Icon',
                 'A Sword','A Ticket'],
           -size=>5,
           -multiple=>'true');

     print "<P><EM>Any parting comments?</EM><BR>";
     print $query->textarea(-name=>'Comments',
                -rows=>10,
                -columns=>50);

     print "<P>",$query->Reset;
     print $query->submit('Action','Shout');
     print $query->submit('Action','Scream');
     print $query->endform;
     print "<HR>\n";
         }

     sub do_work {
        my($query) = @_;
        my(@values,$key);

     print "<H2>Here are the current settings in this form</H2>";

     foreach $key ($query->param) {
        print "<STRONG>$key</STRONG> -> ";
        @values = $query->param($key);
        print join(", ",@values),"<BR>\n";
           }
         }

     sub print_tail {
        print <<END;
     <HR>
     <ADDRESS>Lincoln D. Stein</ADDRESS><BR>
     <A HREF="/">Home Page</A>
     END
     }

BUGS
====

   This module has grown large and monolithic.  Furthermore it's doing many
things, such as handling URLs, parsing CGI3 input, writing HTML, etc., that
are also done in the LWP modules. It should be discarded in favor of the
CGI3::* modules, but somehow I continue to work on it.

   Note that the code is truly contorted in order to avoid spurious
warnings when programs are run with the -w switch.

SEE ALSO
========

   `CGI3::Carp' in this node, see URI/URL, `CGI3::Form' in
this node, see CGI3/Push, CGI3/Fast,
CGI3/Pretty,

CGI3 Interface for Fast CGI3
****************************

NAME
====

   CGI3::Fast - CGI3 Interface for Fast CGI3

SYNOPSIS
========

     use CGI3::Fast qw(:standard);
     $COUNTER = 0;
     while (new CGI3::Fast) {
     print header;
     print start_html("Fast CGI3 Rocks");
     print
         h1("Fast CGI3 Rocks"),
         "Invocation number ",b($COUNTER++),
             " PID ",b($$),".",
         hr;
         print end_html;
     }

DESCRIPTION
===========

   CGI3::Fast is a subclass of the CGI3 object created by CGI3.pm.  It is
specialized to work well with the Open Market FastCGI3 standard, which
greatly speeds up CGI3 scripts by turning them into persistently running
server processes.  Scripts that perform time-consuming initialization
processes, such as loading large modules or opening persistent database
connections, will see large performance improvements.

OTHER PIECES OF THE PUZZLE
==========================

   In order to use CGI3::Fast you'll need a FastCGI3-enabled Web server.
Open Market's server is FastCGI3-savvy.  There are also freely
redistributable FastCGI3 modules for NCSA httpd 1.5 and Apache.
FastCGI3-enabling modules for Microsoft Internet Information Server and
Netscape Communications Server have been announced.

   In addition, you'll need a version of the Perl interpreter that has
been linked with the FastCGI3 I/O library.  Precompiled binaries are
available for several platforms, including DEC Alpha, HP-UX and
SPARC/Solaris, or you can rebuild Perl from source with patches provided
in the FastCGI3 developer's kit.  The FastCGI3 Perl interpreter can be
used in place of your normal Perl without ill consequences.

   You can find FastCGI3 modules for Apache and NCSA httpd, precompiled
Perl interpreters, and the FastCGI3 developer's kit all at URL:

     http://www.fastcgi.com/

WRITING FASTCGI3 PERL SCRIPTS
=============================

   FastCGI3 scripts are persistent: one or more copies of the script are
started up when the server initializes, and stay around until the server
exits or they die a natural death.  After performing whatever one-time
initialization it needs, the script enters a loop waiting for incoming
connections, processing the request, and waiting some more.

   A typical FastCGI3 script will look like this:

     #!/usr/local/bin/perl    # must be a FastCGI3 version of perl!
     use CGI3::Fast;
     &do_some_initialization();
     while ($q = new CGI3::Fast) {
     &process_request($q);
     }

   Each time there's a new request, CGI3::Fast returns a CGI3 object to
your loop.  The rest of the time your script waits in the call to new().
When the server requests that your script be terminated, new() will return
undef.  You can of course exit earlier if you choose.  A new version of the
script will be respawned to take its place (this may be necessary in order
to avoid Perl memory leaks in long-running scripts).

   CGI3.pm's default CGI3 object mode also works.  Just modify the loop
this way:

     while (new CGI3::Fast) {
     &process_request;
     }

   Calls to header(), start_form(), etc. will all operate on the current
request.

INSTALLING FASTCGI3 SCRIPTS
===========================

   See the FastCGI3 developer's kit documentation for full details.  On
the Apache server, the following line must be added to srm.conf:

     AddType application/x-httpd-fcgi .fcgi

   FastCGI3 scripts must end in the extension .fcgi.  For each script you
install, you must add something like the following to srm.conf:

     AppClass /usr/etc/httpd/fcgi-bin/file_upload.fcgi -processes 2

   This instructs Apache to launch two copies of file_upload.fcgi at
startup time.

USING FASTCGI3 SCRIPTS AS CGI3 SCRIPTS
======================================

   Any script that works correctly as a FastCGI3 script will also work
correctly when installed as a vanilla CGI3 script.  However it will not
see any performance benefit.

CAVEATS
=======

   I haven't tested this very much.

AUTHOR INFORMATION
==================

   Copyright 1996-1998, Lincoln D. Stein.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Address bug reports and comments to: lstein@cshl.org

BUGS
====

   This section intentionally left blank.

SEE ALSO
========

   `CGI3::Carp' in this node, see CGI3,

   =cut

module to produce nicely formatted HTML code
********************************************

NAME
====

   CGI3::Pretty - module to produce nicely formatted HTML code

SYNOPSIS
========

     use CGI3::Pretty qw( :html3 );

     # Print a table with a single data element
     print table( TR( td( "foo" ) ) );

DESCRIPTION
===========

   CGI3::Pretty is a module that derives from CGI3.  It's sole function is
to allow users of CGI3 to output nicely formatted HTML code.

   When using the CGI3 module, the following code:     print table( TR(
td( "foo" ) ) );

   produces the following output:     <TABLE><TR><TD>foo</TD></TR></TABLE>

   If a user were to create a table consisting of many rows and many
columns, the resultant HTML code would be quite difficult to read since it
has no carriage returns or indentation.

   CGI3::Pretty fixes this problem.  What it does is add a carriage return
and indentation to the HTML code so that one can easily read it.

     print table( TR( td( "foo" ) ) );

   now produces the following output:     <TABLE>        <TR>
<TD>              foo           </TD>        </TR>     </TABLE>

Tags that won't be formatted
----------------------------

   The <A> and <PRE> tags are not formatted.  If these tags were
formatted, the user would see the extra indentation on the web browser
causing the page to look different than what would be expected.  If you
wish to add more tags to the list of tags that are not to be touched, push
them onto the `@AS_IS' array:

     push @CGI3::Pretty::AS_IS,qw(CODE XMP);

Customizing the Indenting
-------------------------

   If you wish to have your own personal style of indenting, you can
change the `$INDENT' variable:

     $CGI3::Pretty::INDENT = "\t\t";

   would cause the indents to be two tabs.

   Similarly, if you wish to have more space between lines, you may change
the `$LINEBREAK' variable:

     $CGI3::Pretty::LINEBREAK = "\n\n";

   would create two carriage returns between lines.

   If you decide you want to use the regular CGI3 indenting, you can
easily do the following:

     $CGI3::Pretty::INDENT = $CGI3::Pretty::LINEBREAK = "";

BUGS
====

   This section intentionally left blank.

AUTHOR
======

   Brian Paulsen <Brian@ThePaulsens.com>, with minor modifications by
Lincoln Stein <lstein@cshl.org> for incorporation into the CGI3.pm
distribution.

   Copyright 1999, Brian Paulsen.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Bug reports and comments to Brian@ThePaulsens.com.  You can also write
to lstein@cshl.org, but this code looks pretty hairy to me and I'm not
sure I understand it!

SEE ALSO
========

   See CGI3,

Simple Interface to Server Push
*******************************

NAME
====

   CGI3::Push - Simple Interface to Server Push

SYNOPSIS
========

     use CGI3::Push qw(:standard);

     do_push(-next_page=>\&next_page,
             -last_page=>\&last_page,
             -delay=>0.5);

     sub next_page {
         my($q,$counter) = @_;
         return undef if $counter >= 10;
         return start_html('Test'),
            h1('Visible'),"\n",
                "This page has been called ", strong($counter)," times",
                end_html();
       }

     sub last_page {
     my($q,$counter) = @_;
         return start_html('Done'),
                h1('Finished'),
                strong($counter),' iterations.',
                end_html;
     }

DESCRIPTION
===========

   CGI3::Push is a subclass of the CGI3 object created by CGI3.pm.  It is
specialized for server push operations, which allow you to create animated
pages whose content changes at regular intervals.

   You provide CGI3::Push with a pointer to a subroutine that will draw
one page.  Every time your subroutine is called, it generates a new page.
The contents of the page will be transmitted to the browser in such a way
that it will replace what was there beforehand.  The technique will work
with HTML pages as well as with graphics files, allowing you to create
animated GIFs.

USING CGI3::Push
================

   CGI3::Push adds one new method to the standard CGI3 suite, do_push().
When you call this method, you pass it a reference to a subroutine that is
responsible for drawing each new page, an interval delay, and an optional
subroutine for drawing the last page.  Other optional parameters include
most of those recognized by the CGI3 header() method.

   You may call do_push() in the object oriented manner or not, as you
prefer:

     use CGI3::Push;
     $q = new CGI3::Push;
     $q->do_push(-next_page=>\&draw_a_page);

     -or-

     use CGI3::Push qw(:standard);
     do_push(-next_page=>\&draw_a_page);

   Parameters are as follows:

-next_page
          do_push(-next_page=>\&my_draw_routine);

     This required parameter points to a reference to a subroutine
     responsible for drawing each new page.  The subroutine should expect
     two parameters consisting of the CGI3 object and a counter indicating
     the number of times the subroutine has been called.  It should return
     the contents of the page as an array of one or more items to print.
     It can return a false value (or an empty array) in order to abort the
     redrawing loop and print out the final page (if any)

          sub my_draw_routine {
              my($q,$counter) = @_;
              return undef if $counter > 100;
              return start_html('testing'),
                     h1('testing'),
                 "This page called $counter times";
          }

     You are of course free to refer to create and use global variables
     within your draw routine in order to achieve special effects.

-last_page
     This optional parameter points to a reference to the subroutine
     responsible for drawing the last page of the series.  It is called
     after the -next_page routine returns a false value.  The subroutine
     itself should have exactly the same calling conventions as the
     -next_page routine.

-type
     This optional parameter indicates the content type of each page.  It
     defaults to "text/html".  Normally the module assumes that each page
     is of a homogenous MIME type.  However if you provide either of the
     magic values "heterogeneous" or "dynamic" (the latter provided for the
     convenience of those who hate long parameter names), you can specify
     the MIME type - and other header fields - on a per-page basis.  See
     "heterogeneous pages" for more details.

-delay
     This indicates the delay, in seconds, between frames.  Smaller delays
     refresh the page faster.  Fractional values are allowed.

     *If not specified, -delay will default to 1 second*

-cookie, -target, -expires
     These have the same meaning as the like-named parameters in
     CGI3::header().

Heterogeneous Pages
-------------------

   Ordinarily all pages displayed by CGI3::Push share a common MIME type.
However by providing a value of "heterogeneous" or "dynamic" in the
do_push() -type parameter, you can specify the MIME type of each page on a
case-by-case basis.

   If you use this option, you will be responsible for producing the HTTP
header for each page.  Simply modify your draw routine to look like this:

     sub my_draw_routine {
         my($q,$counter) = @_;
         return header('text/html'),   # note we're producing the header here
            start_html('testing'),
                h1('testing'),
            "This page called $counter times";
     }

   You can add any header fields that you like, but some (cookies and
status fields included) may not be interpreted by the browser.  One
interesting effect is to display a series of pages, then, after the last
page, to redirect the browser to a new URL.  Because redirect() does
b<not> work, the easiest way is with a -refresh header field, as shown
below:

     sub my_draw_routine {
         my($q,$counter) = @_;
     return undef if $counter > 10;
         return header('text/html'),   # note we're producing the header here
            start_html('testing'),
                h1('testing'),
            "This page called $counter times";
     }

     sub my_last_page {
     header(-refresh=>'5; URL=http://somewhere.else/finished.html',
            -type=>'text/html'),
         start_html('Moved'),
         h1('This is the last page'),
     'Goodbye!'
          hr,
          end_html;
     }

Changing the Page Delay on the Fly
----------------------------------

   If you would like to control the delay between pages on a page-by-page
basis, call push_delay() from within your draw routine.  push_delay()
takes a single numeric argument representing the number of seconds you
wish to delay after the current page is displayed and before displaying
the next one.  The delay may be fractional.  Without parameters,
push_delay() just returns the current delay.

INSTALLING CGI3::Push SCRIPTS
=============================

   Server push scripts must be installed as no-parsed-header (NPH) scripts
in order to work correctly.  On Unix systems, this is most often
accomplished by prefixing the script's name with "nph-".  Recognition of
NPH scripts happens automatically with WebSTAR and Microsoft IIS.  Users
of other servers should see their documentation for help.

AUTHOR INFORMATION
==================

   Copyright 1995-1998, Lincoln D. Stein.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Address bug reports and comments to: lstein@cshl.org

BUGS
====

   This section intentionally left blank.

SEE ALSO
========

   `CGI3::Carp' in this node, see CGI3,

a Module for ASP emulation
**************************

NAME
====

   CGI::ASP::Lite - a Module for ASP emulation

SYNOPSIS
========

     use CGI::ASP::Lite;

     $Response->Write("hello<br>\n");

     $IE=true if $Request->ServerVariables("HTTP_USER_AGENT")->Item =~/MSIE/;

     $Response->Write("IE=$IE<br>\n");

     $id    = $Request->QueryString("id")->Item;

     $name  = $Request->Form("name")->Item;

DESCRIPTION
===========

   Implement IIS $Request $Response objects in non-IIS environment
Provides common CGI API across both platforms

Backward compatibility module for CGI.pm
****************************************

NAME
====

   CGI::Apache - Backward compatibility module for CGI.pm

SYNOPSIS
========

   Do not use this module.  It is deprecated.

ABSTRACT
========

DESCRIPTION
===========

AUTHOR INFORMATION
==================

BUGS
====

SEE ALSO
========

Framework for building reusable web-applications
************************************************

NAME
====

   CGI::Application - Framework for building reusable web-applications

SYNOPSIS
========

     # WebApp.pm
     package WebApp;
     use base 'CGI::Application';
     sub setup {
     	my $self = shift;
     	$self->start_mode('mode1');
     	$self->mode_param('rm');
     	$self->run_modes(
     		'mode1' => \&do_stuff,
     		'mode2' => \&do_more_stuff
     	);
     }
     sub teardown {
     	my $self = shift;
     	# Post-response shutdown functions
     }
     sub do_stuff { ... }
     sub do_more_stuff { ... }

     # webapp.cgi
     use WebApp;
     my $webapp = WebApp->new();
     $webapp->run();

USAGE EXAMPLE
=============

   CGI::Application is intended to make it easier to create sophisticated,
reusable web-based applications.  This module implements a methodology
which, if followed, will make your web software easier to design, easier
to document, easier to write, and easier to evolve.

   CGI::Application builds on standard, non-proprietary technologies and
techniques, such as the Common Gateway Interface and Lincoln D. Stein's
excellent CGI.pm module.  CGI::Application judiciously avoids employing
technologies and techniques which would bind a developer to any one set of
tools, operating system or web server.

   Following is an example of the typical usage of CGI::Application.

   Imagine you have to write an application to search through a database
of widgets.  Your application has three screens:

     1. Search form
     2. List of results
     3. Detail of a single record

   To write this application using CGI::Application you will create two
files:

     1. WidgetView.pm -- Your "Application Module"
     2. widgetview.cgi -- Your "Instance Script"

   The Application Module contains all the code specific to your
application functionality, and it exists outside of your web server's
document root, somewhere in the Perl library search path.

   The Instance Script is what is actually called by your web server.  It
is a very small, simple file which simply creates an instance of your
application and calls an inherited method, run().  Following is the
entirety of "widgetview.cgi":

     #!/usr/bin/perl -w
     use WidgetView;
     my $webapp = WidgetView->new();
     $webapp->run();

   As you can see, widgetview.cgi simply "uses" your Application module
(which implements a Perl package called "WidgetView").  Your Application
Module, "WidgetView.pm", is somewhat more lengthy:

     package WidgetView;
     use base 'CGI::Application';
     use strict;

     # Needed for our database connection
     use DBI;

     sub setup {
     	my $self = shift;
     	$self->start_mode('mode1');
     	$self->run_modes(
     		'mode1' => \&showform,
     		'mode2' => \&showlist,
     		'mode3' => \&showdetail
     	);

     # Connect to DBI database
     $self->param('mydbh' => DBI->connect());
        }

     sub teardown {
     	my $self = shift;

     # Disconnect when we're done
     $self->param('mydbh')->disconnect();
        }

     sub showform {
     	my $self = shift;

     # Get CGI query object
     my $q = $self->query();

     my $output = '';
     $output .= $q->start_html(-title => 'Widget Search Form');
     $output .= $q->start_form();
     $output .= $q->textfield(-name => 'widgetcode');
     $output .= $q->hidden(-name => 'rm', -value => 'mode2');
     $output .= $q->submit();
     $output .= $q->end_form();
     $output .= $q->end_html();

     return $output;
        }

     sub showlist {
     	my $self = shift;

     # Get our database connection
     my $dbh = $self->param('mydbh');

     # Get CGI query object
     my $q = $self->query();
     my $widgetcode = $q->param("widgetcode");

     my $output = '';
     $output .= $q->start_html(-title => 'List of Matching Widgets');

     ## Do a bunch of stuff to select "widgets" from a DBI-connected
     ## database which match the user-supplied value of "widgetcode"
     ## which has been supplied from the previous HTML form via a
     ## CGI.pm query object.
     ##
     ## Each row will contain a link to a "Widget Detail" which
     ## provides an anchor tag, as follows:
     ##
     ##   "widgetview.cgi?rm=mode3&widgetid=XXX"
     ##
     ##  ...Where "XXX" is a unique value referencing the ID of
     ## the particular "widget" upon which the user has clicked.

     $output .= $q->end_html();

     return $output;
        }

     sub showdetail {
     	my $self = shift;

     # Get our database connection
     my $dbh = $self->param('mydbh');

     # Get CGI query object
     my $q = $self->query();
     my $widgetid = $q->param("widgetid");

     my $output = '';
     $output .= $q->start_html(-title => 'Widget Detail');

     ## Do a bunch of things to select all the properties of
     ## the particular "widget" upon which the user has
     ## clicked.  The key id value of this widget is provided
     ## via the "widgetid" property, accessed via the CGI.pm
     ## query object.

     $output .= $q->end_html();

     return $output;
        }

   CGI::Application takes care of implementing the new() and the run()
methods.  Notice that at no point do you call print() to send any output
to STDOUT.  Instead, all output is returned as a scalar.

   CGI::Application's most significant contribution is in managing the
application state.  Notice that all which is needed to push the
application forward is to set the value of a HTML form parameter 'rm' to
the value of the "run mode" you wish to handle the form submission.  This
is the key to CGI::Application.

ABSTRACT
========

   The guiding philosophy behind CGI::Application is that a web-based
application can be organized into a specific set of "Run-Modes."  Each
Run-Mode is roughly analogous to a single screen (a form, some output,
etc.).  All the Run-Modes are managed by a single "Application Module"
which is a Perl module.  In your web server's document space there is an
"Instance Script" which is called by the web server as a CGI (or an
Apache::Registry script if you're using Apache + mod_perl).

   This methodology is an inversion of the "Embedded" philosophy (ASP, JSP,
EmbPerl, Mason, etc.) in which there are "pages" for each state of the
application, and the page drives functionality.  In CGI::Application, form
follows function - the Application Module drives pages, and the code for a
single application is in one place; not spread out over multiple "pages".
If you feel that Embedded architectures are confusing, unorganized,
difficult to design and difficult to manage, CGI::Application is the
methodology for you!

   Apache is NOT a requirement for CGI::Application.  Web applications
based on CGI::Application will run equally well on NT/IIS or any other
CGI-compatible environment.  CGI::Application-based applications are,
however, ripe for use on Apache/mod_perl servers, as they naturally
encourage Good Programming Practices.  As always, use strict!

DESCRIPTION
===========

   CGI::Application is an Object-Oriented Perl module which implements an
Abstract Class.  It is not intended that this package be instantiated
directly.  Instead, it is intended that your Application Module will be
implemented as a Sub-Class of CGI::Application.

   To inherit from CGI::Application, the following code should go at the
beginning of your Application Module, after your package declaration:

     use base 'CGI::Application';

   *Notation and Conventions*

   For the purpose of this document, we will refer to the following
conventions:

     WebApp.pm   The Perl module which implements your Application Module class.
     WebApp      Your Application Module class; a sub-class of CGI::Application.
     webapp.cgi  The Instance Script which implements your Application Module.
     $webapp     An instance (object) of your Application Module class.
     $self       Same as $webapp, used in instance methods to pass around the
                 current object. (Standard Perl Object-Oriented technique)

Instance Script Methods
-----------------------

   By inheriting from CGI::Application you have access to a number of
built-in methods.  The following are those which are expected to be called
from your Instance Script.

new()
     The new() method is the constructor for a CGI::Application.  It
     returns a blessed reference to your Application Module package
     (class).  Optionally, new() may take a set of parameters as key =>
     value pairs:

          my $webapp = App->new(
          		TMPL_PATH => 'App/',
          		PARAMS => {
          			'custom_thing_1' => 'some val',
          			'another_custom_thing' => [qw/123 456/]
          		}
          );

     This method may take some specific parameters:

     TMPL_PATH     - This optional parameter adds value to the load_tmpl()
     method (specified below).  This sets a path which is prepended to all
     the filenames specified when you call load_tmpl() to get your
     HTML::Template object.  This run-time parameter allows you to further
     encapsulate instantiating templates, providing potential for more
     reusability.

     PARAMS        - This parameter, if used, allows you to set a number
     of custom parameters at run-time.  By passing in different values in
     different instance scripts which use the same application module you
     can achieve a higher level of reusability.  For instance, imagine an
     application module, "MailForm.pm".  The application takes the
     contents of a HTML form and emails it to a specified recipient.  You
     could have multiple instance scripts throughout your site which all
     use this "MailForm.pm" module, but which set different recipients or
     different forms.

run()
     The run() method is called upon your Application Module object, from
     your Instance Script.  When called, it executes the functionality in
     your Application Module.

          my $webapp = WebApp->new();
          $webapp->run();

     This method first determines the application state by looking at the
     value of the CGI parameter specified by mode_param() (defaults to
     'rm' for "Run Mode"), which is expected to contain the name of the
     mode of operation.  If not specified, the state defaults to the value
     of start_mode().

     Once the mode has been determined, run() looks at the dispatch table
     stored in run_modes() and finds the function pointer which is keyed
     from the mode name.  If found, the function is called and the data
     returned is print()'ed to STDOUT and to the browser.  If the
     specified mode is not found in the run_modes() table, run() will
     croak().

Sub-classing and Override Methods
---------------------------------

   CGI::Application implements some methods which are expected to be
overridden by implementing them in your sub-class module.  These methods
are as follows:

setup()
     This method is called by the inherited new() constructor method.  The
     setup() method should be used to define the following
     property/methods:

          mode_param() - set the name of the run mode CGI param.
          start_mode() - text scalar containing the default run mode.
          run_modes() - hash table containing mode => function mappings.
          tmpl_path() - text scalar containing path to template files.

     Your setup() method may call any of the instance methods of your
     application.  This function is a good place to define properties
     specific to your application via the $webapp->param() method.

     Your setup() method might be implemented something like this:

          sub setup {
          	my $self = shift;
          	$self->tmpl_path('/path/to/my/templates/');
          	$self->start_mode('putform');
          	$self->run_modes({
          		'putform' => \&my_putform_func,
          		'postdata' => \&my_data_func
          	});
          	$self->param('myprop1');
          	$self->param('myprop2', 'prop2value');
          	$self->param('myprop3', ['p3v1', 'p3v2', 'p3v3']);
          }

teardown()
     This method is called automatically after your application runs.  It
     can be used to clean up after your operations.  A typical use of the
     teardown() function is to disconnect a database connection which was
     established in the setup() function.  You could also use the
     teardown() method to store state information about the application to
     the server.

Application Module Methods
--------------------------

   The following methods are inherited from CGI::Application, and are
available to be called by your application within your Application Module.
These functions are listed in alphabetical order.

dump()
          print STDERR $webapp->dump();

     The dump() method is a debugging function which will return a chunk
     of text which contains all the environment and CGI form data of the
     request, formatted nicely for human readability.  Useful for
     outputting to STDERR.

dump_html()
          my $output = $webapp->dump_html();

     The dump_html() method is a debugging function which will return a
     chunk of text which contains all the environment and CGI form data of
     the request, formatted nicely for human readability via a web
     browser.  Useful for outputting to a browser.

header_props()
          $webapp->header_props(-type=>'image/gif',-expires=>'+3d');

     The header_props() method expects a hash of CGI.pm-compatible HTTP
     header properties.  These properties will be passed directly to
     CGI.pm's header() or redirect() methods.  Refer to CGI,
     for usage details.

     *IMPORTANT NOTE REGARDING HTTP HEADERS*

     It is through the header_props() method that you may modify the
     outgoing HTTP headers.  This is necessary when you want to set a
     cookie, set the mime type to something other than "text/html", or
     perform a redirect.  The header_props() method works in conjunction
     with the header_type() method.  The value contained in header_type()
     determines if we use CGI::header() or CGI::redirect().  The content
     of header_props() is passed as an argument to whichever CGI.pm
     function is called.

     Understanding this relationship is important if you wish to manipulate
     the HTTP header properly.

header_type([<'header' || 'redirect'>])
          $webapp->header_type('redirect');

     The header_type() method expects to be passed either 'header' or
     'redirect'.  This method specifies the type of HTTP headers which
     should be sent back to the browser.  If not specified, defaults is
     'header'.  See the header section of CGI, for details.

load_tmpl()
          my $tmpl_obj = $webapp->load_tmpl('some.tmpl');

     This method takes the name of a template file and returns an
     HTML::Template object.  The HTML::Template->new_file() constructor is
     used for create the object.  Refer to HTML/Template,
     for specific usage of HTML::Template.

     If tmpl_path() has been specified, load_tmpl() will prepend the
     tmpl_path() property to the filename provided.  This further assists
     in encapsulating template usage.

     The load_tmpl() method will pass any extra paramaters sent to it
     directly to HTML::Template->new_file().  This will allow the
     HTML::Template object to be further customized:

          my $tmpl_obj = $webapp->load_tmpl('some_other.tmpl',
               die_on_bad_params => 0,
               cache => 1
          );

     If your application requires more specialized behavior than this, you
     are encoraged to override load_tmpl() by implementing your own
     load_tmpl() in your CGI::Application sub-class application module.

mode_param()
          $webapp->mode_param('rm');

     This accessor/mutator method is generally called in the setup()
     method.  The mode_param() method sets the name of the CGI form
     parameter which contains the run mode of the application.  If not
     specified, the default value is 'rm'.  This CGI parameter is queried
     by the run() method to send the program to the correct mode.

param()
          $webapp->param('pname', $somevalue);

     The param() method provides a facility through which you may set
     application instance properties which are accessible throughout your
     application.

     The param() method may be used in two basic ways.  First, you may use
     it to get or set the value of a parameter:

          $webapp->param('scalar_param', '123');
          my $scalar_param_values = $webapp->param('some_param');

     Second, when called in the context of an array, with no parameter name
     specified, param() returns an array containing all the parameters
     which currently exist:

          my @all_params = $webapp->param();

     The param() method enables a very valuable system for customizing
     your applications on a per-instance basis.  One Application Module
     might be instantiated by different Instance Scripts.  Each Instance
     Script might set different values for a set of parameters.  This
     allows similar applications to share a common code-base, but behave
     differently.  For example, imagine a mail form application with a
     single Application Module, but multiple Instance Scripts.  Each
     Instance Script might specify a different recipient.  Another example
     would be a web bulletin boards system.  There could be multiple
     boards, each with a different topic and set of administrators.

     The new() method provides a shortcut for specifying a number of
     run-time parameters at once.  Internally, CGI::Application calls the
     param() method to set these properties.  The param() method is a
     powerful tool for greatly increasing your application's reusability.

query()
          my $q = $webapp->query();
          my $remote_user = $q->remote_user();

     This method retrieves the CGI.pm query object which has been created
     by instantiating your Application Module.  For details on usage of
     this query object, refer to CGI.  CGI::Application is
     built on the CGI module.  Generally speaking, you will want to become
     very familiar with CGI.pm, as you will use the query object whenever
     you want to interact with form data.

     When the new() method is called, a CGI query object is automatically
     created.  If, for some reason, you want to use your own CGI query
     object, the new() method supports passing in your existing query
     object on construction.

run_modes()
          $webapp->run_modes('mode1' => \&some_sub, 'mode2' => \&some_other_sub);

     This accessor/mutator expects a hash which specifies the dispatch
     table for the different CGI states.  The run method uses the data in
     this table to send the CGI to the correct function as determined by
     reading the CGI parameter specified by mode_param() (defaults to 'rm'
     for "Run Mode").

     The hash table set by this method is expected to contain the mode
     name as a key.  The value should be a pointer to the function which
     you want to be called when the CGI enters the specified mode:

          'mode_name' => \&mode_function

     The function referenced is expected to return a chunk of text which
     will eventually be sent back to the web browser.

     *IMPORTANT NOTE ABOUT RUN MODE FUNCTIONS*

     Your application should *NEVER* print() to STDOUT.  Using print() to
     send output to STDOUT (including HTTP headers) is exclusively the
     domain of the inherited run() method.  Breaking this rule is a common
     source of errors.  If your program is erroneously sending content
     before your HTTP header, you are probably breaking this rule.

start_mode()
          $webapp->start_mode('mode1');

     The start_mode contains the name of the mode as specified in the
     run_modes() table.  Default mode is "start".  The mode key specified
     here will be used whenever the value of the CGI form parameter
     specified by mode_param() is not defined.  Generally, this is the
     first time your application is executed.

tmpl_path()
          $webapp->tmpl_path('/path/to/some/templates/');

     This access/mutator method sets the file path to the directory where
     the templates are stored.  It is used by load_tmpl() to find the
     template files.

     It is important to make sure your tmpl_path() ends with your
     operating system's directory delimiter ('/' for UNIX, '\' for
     windows, ':' for Macintosh, etc).  The load_tmpl() method does not
     try to make sense of the various OS particularities - it simply
     prepends tmpl_path() to the file name passed to load_tmpl().

SEE ALSO
========

   See CGI, HTML/Template, perl(1)

AUTHOR
======

   Jesse Erlbaum <jesse@vm.com>

   *Support Mailing List*

   If you have any questions, comments, bug reports or feature suggestions,
post them to the support mailing list!  To join the mailing list, simply
send a blank message to "cgiapp-subscribe@lists.vm.com".

CREDITS
=======

   Thanks go to my place of work, Vanguard Media (http://www.vm.com), for
funding the development of this library, and encouraging me to release it
to the world.  If you need a web-application for your business, do check
us out!

   Many thanks to Sam Tregar (author of the most excellent HTML::Template
module!) for his innumerable contributions to this module over the past
year, and most of all for getting me off my ass to finally get this thing
up on CPAN!

LICENSE
=======

   Copyright (c) 2000, Jesse Erlbaum <jesse@vm.com> and Vanguard Media
(http://www.vm.com).  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

An extensible CGI parameter validation module (allowing commonly used checks on parameters to be called more concisely and consistently).
*****************************************************************************************************************************************

NAME
====

   CGI::ArgChecker - An extensible CGI parameter validation module
(allowing commonly used checks on parameters to be called more concisely
and consistently).

SYNOPSIS
========

     use CGI::ArgChecker;

     $checker = new CGI::Argchecker;
     $checker->register_check($name, \&sub);
     $checker->error_handler(\&errhandler);
     $checker->argcheck($CGI_query_object,
                        'param_name' => [ 'expectation', ... ],
                        ... );

DESCRIPTION
===========

   Note: Since this is really a simple wrapper around String::Checker(3),
most of the interesting reading is in that document (i.e. the definition
of an 'expectation').  The documentation that follows assumes you are
pretty familiar with String::Checker(3), and focuses on the additional
functionality provided by this module.

CGI Parameter Checking
----------------------

   The argcheck() method takes a CGI object (can be any of the CGI modules
which have a param method for fetching a parameter...) followed by a list
of parameter_name/expectation_list_reference pairs.  The parameter name is
the name of a CGI variable to examine.  The expectation list is precisely
the same as the String::Checker(3) expectation list.

   Each parameter will be retrieved from the CGI object using the param()
method, checked against all the expectations, and then the result of all
checks will be stored for returning.  If all parameters pass all
expectations, a reference to a hash will be returned, containing
parameter_name/parameter_value pairs.  If any expectation fails, the hash
will still be returned.  To check whether any errors occurred, check the
'ERROR' hash value (a boolean flag value).  For every expectation which
fails, in addition, an error handling routine (described below) will be
called.

Error Handling
--------------

   Using the error_handler() method, you can register a chunk of code
which will be called for every expectation which fails.  This subroutine
will be called with two arguments: the name of the parameter which failed,
and the name of the expectation which failed.  The return value of the
error handling code is ignored.

BUGS
====

   Hopefully none.

AUTHOR
======

   J. David Lowe, dlowe@webjuice.com

SEE ALSO
========

   perl(1), String::Checker(3)

request a HTTP authentification under specified conditions
**********************************************************

NAME
====

   CGI::Authent - request a HTTP authentification under specified
conditions

   version 0.2.1

SYNOPSIS
========

   use CGI::Authent Basic => 'The realm name', test =>
'CGI::Authent::between "h:m-h:m"';

DESCRIPTION
===========

   Send the HTTP 401 UnAuthentified header if a condition (by default
"defined $ENV{REMOTE_USER}") fails. Since your script doesn't get the
password the user entered, you cannot use it as the only authentification
scheme. And it was not intended to work like this. You have to find some
other way to check the username/password pair.

   It was written primarily to overcome a bug in MS IIS/3.0.  IIS usualy
sends a HTTP 401 response if it finds out that it cannot access a file
using the current users premissions (IUSR_... or the login/password you
entered), but since IIS doesn't check the permissions to the script before
launching perl, you get an error message :

     CGI Error

     The specified CGI application misbehaved by not returning a complete set
     of HTTP headers. The headers it did return are:

     Can't open perl script "...": Permission denied

   instead of a login/password dialog.

   So instead of restricting the permissions for the scripts, you will add

     use CGI::Authent;

   at the very beginning of your scripts and update CGI/Authent.config.pl
to suggest your servers authentification method.

   The login/password pair your user will enter into the dialog /s?he/ will
get will be checked by the server and mapped to an account, so all you
have to do, if all authentified users are to be able to access your
script, is to check the system variable REMOTE_USER - the default test.

   If you want to restrict the access to a group of users you may check
whether the script as it runs has enough permissions to access a file and
then restrict the access to this file.

     use CGI::Authent {test => 'CGI::Authent::can_read "c:\\inetpub\\group1.lck"'}

Ussage
------

     use CGI::Authent;
      Use the default options as set in CGI/Authent.config.pl.
     use CGI::Authent {options}, [$msg];
     use CGI::Authent options, [$msg];
      Replace the default options from CGI/Authent.congfig.pl, by the ones
      presented here.

Options
-------

     NTLM => 1/0
      Should we use/suggest NTLM authentification?

     Basic => ''/'IP'/'_default'/'the realm'
      Should we use the Basic authentification?
      '', 'IP' and '_default' both mean that the realm will
      be the servers IP address, which is default for MS IIS.

     msg => 'the message that should be showed if the authentification fails'

     test => \&some_boolean_function / 'some perl code' / '_default'
          / 'Authent::can_read "filename"' / 'Authent::between "h:m-h:m"'
      The test that should be performed. You may use either a reference to
      a function, or a string to be eval()uated. The string '_default' has
      a special meaning, it gets translated to 'defined $ENV{REMOTE_USER}',
      so it checks if the user was authentificated by the server.
      If the function/expression returns a true value, the script runs,
      otherwise the user gets asked for a login/password pair.

     header => 'Some: additional headers'
      You may add some headers to the response that will be sent if the test fails.
      You may add several headers either as
       header => 'Header1\r\nHeader2'
      or
       header1 => 'Header1',
       header2 => 'Header2'

     Authenticate => 'Additional authentification methods'
      You may specify additional authentification methods here.
      The string you specify will be prepended by 'WWW-Authenticate: ' and
      added to the headers.
      You may use the same methods for several methods as with headers.

Tests
-----

   The default test is 'defined $ENV{REMOTE_USER}' which only checks
whether the user entered any login/password pair that was accepted by the
server.

   Other predefined tests are :

     CGI::Authent::can_read $file[, $file2, ...]
      Does the script have permissions to read the file(s)?

     CGI::Authent::isbetween 'h:m-h:m';
      It the time in this range?

     CGI::Authent::between 'h:m-h:m';
      It the time in this range? This version will disallow
      access buring other times completely! No request for authentification,
      just 403 Forbiden response!

   You may of course combine several tests :

     test => 'CGI::Authent::can_read "c:\\inetpub\\group1.lck" and CGIAuthent::between '8:00-17:00'
              or
              CGI::Authent::can_read "c:\\inetpub\\group2.lck" and CGI::Authent::between '17:00-8:00'
             '

Other functions
---------------

     CGI::Authent::forbide [$message]
      Send the "HTTP 403 Forbiden" response.

     CGI::Authent::login [$message]
      Send the "HTTP 401 UnAuthentified" response.

REMINDER
--------

   CGI::Authent doesn't validate the passwords. It cannot even see them. It
just does a few tests and if the tests fail it sends to the user a request
for authentication. But it's the server's task to validate the credentials
passed by the browser.

   If you want for example to validate passwords against a database,
consult your servers documentation. You will probably have to install some
filter or plugin.  It should be relatively easy to find such beasts on the
net. I've written an ISAPI filter for this, you may get it at
http://jenda.krynicky.cz/authfilter.1.0.zip . Take it as an example, not
as a solution!

Guts
----

   All options are parsed and added to the headers before yout test runs,
so you may change the headers from it.

   The headers are in $CGI::Authent::header, the message is in
$CGI::Authent::message.

AUTHOR
------

   Jan Krynicky <Jenda@Krynicky.cz> 7/26/1999

HTTP Daemon Common Gateway Interface (CGI) Base Class
*****************************************************

NAME
====

   CGI::Base - HTTP Daemon Common Gateway Interface (CGI) Base Class

SYNOPSIS
========

     use CGI::Base;

     $cgi = new CGI::Base;       # reads vars from environment

     $cgi->var($name);           # get CGI variable value
     $cgi->var($name, $value);   # set CGI variable value

     @names  = $cgi->vars;       # lists standard CGI variables

     $mime_type  = $cgi->accept_best(@mime_types);
     $preference = $cgi->accept_type($mime_type);

     $cgi->pass_thru($host, $port); # forward request to server
     $cgi->redirect($url);          # redirect client

     $cgi->done($dump);     # end response, does NOT send </BODY>

     $cgi->exit(@log_msgs); # exit, optionally logging messages

     # Other functions:

     @escaped_texts = html_escape(@texts);   # '>' -> '&lt;' etc
     @texts         = html_br_lines(@texts); #  \n -> '<BR>'

     SendHeaders();  # send and flush HTTP header(s)

     CGI::Base::Debug($level);

DESCRIPTION
===========

   This module implements a CGI::Base object. This object represents the
interface between the application and an HTTP deamon.

   In a typical CGI scenario the interface is just a collection of
environment variables. This module makes those variables available either
via a $cgi->var() method or optionally as plain perl variables (see
IMPORTING CGI VARIABLES below).  Small scripts will tend to use the
imported variables, larger scripts may prefer to use the var method.

   By default the CGI::Base class will transparently deal with POST and
PUT submissions by reading STDIN into $QUERY_STRING.

   The CGI::Base module simplifies CGI debugging by providing logging
methods (which redirect STDERR to a file) and a very handy test mode.  The
test mode automatically detects that the script is not being run by a HTTP
server and requests test input from the user (or command line).

IMPORTING CGI VARIABLES
-----------------------

   Users of this module can optionally import the CGI values as ordinary
perl variables of the same name into their package. For example, saying:

     use CGI::Base qw(:DEFAULT QUERY_STRING REQUEST_METHOD);

   will allow you to refer to the CGI query string and request method as
simply $QUERY_STRING and $REQUEST_METHOD.  Any changes made to these
variables will be reflected in the values returned by the var() method.

   To import all the fixed CGI variables (excludes optional variables
string with HTTP_) use:

     use CGI::Base qw(:DEFAULT :CGI);

NOTES
-----

   The CGI::Base class has been specifically designed to enable it to be
subclassed to implement alternative interfaces. For example the
CGI::MiniSvr class implements a 'mini http daemon' which can be spawned
from a CGI script in order, for example, to maintain state information for
a client 'session'.

   The CGI::Base class (and classes derived from it) are not designed to
understand the contents of the data they are handling. Only basic data
acquisition tasks and basic metadata parsing are performed by CGI::Base.
The QUERY_STRING is not parsed.

   Higher level query processing (parsing of QUERY_STRING and handling of
form fields etc) is performed by the CGI::Request module.

   Note that CGI application developers will generally deal with the
CGI::Request class and not directly with the CGI::Base class.

FEATURES
--------

   Object oriented and sub-classable.

   Exporting of CGI environment variables as plain perl variables.

   Supports pass_thru and redirection of URL's.

   Extensible attribute system for CGI environment variables.

   Very handy automatic test mode if script is run manually.

PRINCIPLES and ASSUMPTIONS
--------------------------

   These basic principles and assumptions apply to CGI::Base and can be
built into any application using CGI::Base. Any subclass of CGI::Base,
such as CGI::MiniSvr, must uphold these principles.

   STDIN, STDOUT are connected to the client, possibly via a server.

   STDERR can be used for error logging (see open_log method).

   %ENV should not be used to access CGI parameters. See ENVIRONMENT
section below.

ENVIRONMENT
-----------

   The CGI::Base module copies all the CGI/1.1 standard environment
variables into internal storage. See the definition of %CgiEnv and
@CgiObj. The stored values are available either via the var method or as
exported variables.

   It is recommended that $ENV{...} is not used to access the CGI
variables because alternative CGI interfaces, such as CGI::MiniSvr, may
not bother to maintain %ENV consistent with the internal values. The
simple scalar variables are also much faster to access.

RECENT CHANGES
--------------

  1. Changes to create compatability with CGI::Form.

  2. Miscellaneous small bug fixes.

  3. get_url() now adds SERVER_PORT to the url. pass_thru() split into
     component methods forward_request() and pass_back().  The new
     forward_request method can shutdown() the sending side of the socket.
     SendHeaders does nothing and returns undef if called more than once.
     All these changes are useful for sophisticated applications.

  4. and 2.3 Slightly improved documentation. Added html_br_lines() to
     purify html_escape().  Added SIGPIPE handling (not used by default).
     Documented the automatic test mode. Assorted other minor clean ups.

  5. Added support for any letter case in HTTP headers. Fixed (worked
     around) a perl/stdio bug which affected POST handling in the MiniSvr.
     Added $ENTITY_BODY to hold the Entity-Body for PUT, POST and CHECKIN
     methods. $QUERY_STRING now only set from $ENTITY_BODY if CONTENT_TYPE
     is application/x-www-form-urlencoded. Changed some uses of map to
     foreach.  Slight improved performance of pass_thru.

  6. A major overhaul. Now much more object oriented but retaining the
     ability to export CGI variables. A new var() method provides access
     to CGI variables in a controlled manner. Some rather fancy footwork
     with globs and references to hash elements enables the global
     variables and hash elements to be automatically kept in sync with
     each other.  Take a look at the link_global_vars method. An export
     tag is provided to simplify importing the CGI variables.

     The new code is also much faster, mainly because it does less. Less
     work is done up front, more is defered until actually used. I have
     removed the 'expand variables' concept for now. It might return later.
     The code for read_entity_body(), get_vars_from_env() and accept_best()
     and many others has been revised. All the code now compiles with use
     strict;

     SendHeaders can now be told to automatically add a server Status-Line
     header if one is not included in the headers to be output. This
     greatly simplifies header handling in the MiniSvr and fixes the
     redirect() method.

     The module file can be run as a cgi script to execute a demo/test. You
     may need to chmod +x this file and teach your httpd that it can
     execute *.pm files.

  7. The done method no longer sends </BODY>. It was appealing but
     inappropriate for it to do so.  Added html_escape function and
     exported it by default (this should be moved into an HTML module once
     we have one). Applied html_escape to as_string.  ContentTypeHdr,
     LocationHdr, StatusHdr and ServerHdr no longer exported by default.
     Added Debug function.  Set default Debug level to 0 (off). Code to
     set $URI is no longer invoked by default and has been moved to a new
     get_uri method.  This avoids the overhead for setting $URI which few
     people used.  Methods like as_string which make use of $URI now call
     get_uri if needed.

  8. POST data read more robust. fmt() renamed to as_string(). pass_thru()
     now takes host and port parameters, applies a timeout and has better
     logging.  HTTP_REFERER defined by default. Assorted fixes and tidyups.

FUTURE DEVELOPMENTS
-------------------

   Full pod documentation.

   None of this is perfect. All suggestions welcome.

   How reliable is CONTENT_LENGTH?

   Pod documentation for the methods needs to be added.

   Header handling is not ideal (but it's getting better).  Header
handling should be moved into an HTTP specific module.

   Need mechanism to identify a 'session'. This may come out of the
ongoing HTTP security work. A session-id would be very useful for any
advanced form of inter-query state maintenance.  The CGI::Base module may
have a hand in providing some form of session-id but would not be involved
in any further use of it.

   For very large POST's we may need some mechanism to replace
read_entity_body on a per call basis or at least prevent its automatic
use. Subclassing is probably the 'right' way to do this.

   These functions should be moved out into a CGI::BasePlus module since
few simple CGI applications need them:  pass_thru, forward_request,
pass_back, new_server_link, pass_thru_headers. The CGI::BasePlus module
would still be a 'package CGI::Base;'.

AUTHOR, COPYRIGHT and ACKNOWLEDGEMENTS
--------------------------------------

   This code is Copyright (C) Tim Bunce 1995. All rights reserved.  This
code is free software; you can redistribute it and/or modify it under the
same terms as Perl itself.

   This code includes ideas from the work of Steven E. Brenner
<S.E.Brenner@bioc.cam.ac.uk> (cgi-lib), Lincoln Stein
<lstein@genome.wi.mit.edu> (CGI.pm), Pratap Pereira
<pereira@ee.eng.ohio-state.edu> (phttpd) and possibly others.

   IN NO EVENT SHALL THE AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT,
INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OF THIS SOFTWARE AND ITS DOCUMENTATION (INCLUDING, BUT NOT LIMITED TO,
LOST PROFITS) EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

SEE ALSO
--------

   URI::URL, CGI::Request, CGI::MiniSvr

SUPPORT
-------

   Please use comp.infosystems.www.* and comp.lang.perl.misc for support.
Please do _NOT_ contact the author directly. I'm sorry but I just don't
have the time.

HTTP CGI Base Class with Handling of Multipart Forms
****************************************************

NAME
====

   CGI::BasePlus - HTTP CGI Base Class with Handling of Multipart Forms

DESCRIPTION
===========

   This module implements a CGI::BasePlus object that is identical in
behavior to CGI::Base except that it provides special handling for
postings of MIME type multipart/form-data (which may get very long).  In
the case of these types of postings, parts that are described as being
from a file upload are copied into a temporary file in /usr/tmp, a
filehandle is opened on the temporary files, and the name of the
filehandle is returned to the caller in the $CGI::Base:QUERY_STRING
variable.

   Please see CGI/Base, for more information.

SEE ALSO
--------

   URI::URL, CGI::Request, CGI::MiniSvr, CGI::Base

Use CIPP embedded HTML Pages in a CGI environment
*************************************************

NAME
====

   CGI::CIPP - Use CIPP embedded HTML Pages in a CGI environment

DESCRIPTION
===========

   CGI::CIPP is a Perl module which enables you to use CIPP on every CGI
capable webserver. It is based on a central wrapper script, which does all
the preprocessing. It executes the generated Perl code directly afterwards.

   Additionally, it implements a filesystem based cache for the generated
code. Preprocessing is done only when the corresponding CIPP source code
changed on disk, otherwise this step is skipped.

WHAT IS CIPP?
=============

   CIPP is a Perl module for translating CIPP sources to pure Perl
programs. CIPP defines a HTML embedding language also called CIPP which
has powerful features for CGI and database developers.

   Many standard CGI and database operations (and much more) are covered
by CIPP, so the developer does not need to code them again and again.

   CIPP is not part of this distribution, please download it from CPAN.

SIMPLE CIPP EXAMPLE
===================

   To give you some imagination of what you can do with CIPP: here is a
(really) simple example of using CIPP in a HTML source to retrieve some
information from a database. Think this as a HTML page which is "executed"
on the fly by your webserver.

   Note: there is no code to connect to the database. This is done
implicitely. The configuration is taken from the central CGI::CIPP wrapper
srcipt.

     # print table of users who match the given parameter

     <?INTERFACE INPUT="$search_name">

     <HTML>
     <HEAD><TITLE>tiny litte CIPP example</TITLE></HEAD>
     <BODY>
     <H1>Users matching '$search_name'</H1>
     <P>

     <TABLE BORDER=1>
     <TR><TD>Name</TD><TD>Adress</TD><TD>Phone</TD></TR>
     <?SQL SQL="select name, adress, phone
                from   people
     	     where  name like '%' || ? || '%'"
           PARAMS="$search_name"
     	MY VAR="$n, $a, $p">
       <TR><TD>$n</TD><TD>$a</TD><TD>$p</TD></TR>
     <?/SQL>
     </TABLE>

     </BODY>
     </HTML>

SYNOPSIS
========

   Create a CGI program in a directory, where CGI programs usually reside
on your server (e.g. /cgi-bin/cipp), or configure this program another way
to be a CGI program (see sections beyond for details).

   This program is the central CGI::CIPP wrapper. It only consists of a
single function call to the CGI::CIPP module, with a hash of parameters
for configuration. This is a example:

     #!/usr/local/bin/perl

     use strict;
     use CGI::CIPP;

     # this program has the URL /cgi-bin/cipp

     CGI::CIPP->request (
     	document_root  => '/www/cippfiles',
     	directoy_index => 'index.cipp',
     	cache_dir      => '/tmp/cipp_cache',
     	databases      => {
     		test => {
     			data_source => 'dbi:mysql:test',
     			user        => 'dbuser',
     			password    => 'dbpassword',
     			auto_commit => 1
     		},
     		foo => {
     			...
     		}
     	}
     	default_database => 'test',
     	lang => 'EN'
     );

   A brief description of the parameters passed to the CGI::CIPP->request
call follows:

document_root
     This is the base directory where all your CIPP files resides.  You
     will place CIPP programs, Includes and Config files inside this
     subdirectory. Using subdirectories is permitted. If you use the
     Apache webserver you should point this to your Apache DocumentRoot
     and set up a extra handler for CIPP. See the Apache chapter beyond
     for details.

d*irectory_index*
     If you want CGI::CIPP to treat a special filename as a directory
     index file, pass this filename here. If you access a directory with
     CGI::CIPP and a according index file is found there, it will be
     executed.

cache_dir
     This names the directory where CGI::CIPP can store the preprocessed
     CIPP programs. If the directory does not exist it will be created.
     Aware, that the directory must have write access for the user under
     which your webserver software is running.

databases
     This parameter contains a hash reference, which defines several
     database configurations. The key of this hash is the CIPP internal
     name of the database, which can be addressed by the DB parameter of
     all CIPP SQL commands. The value is a hash reference with the
     following keys defined.

*  data_source*
     This must be a DBI conforming data source string. Please refer to the
     DBI documentation for details about this.

*  user*
     This is the username CIPP uses to connect to the database

*  password*
     This password is used for the database user.

*  auto_commit*
     This parameter sets the initial state of the AutoCommit flag.  Please
     refer to the description of the <?AUTOCOMMIT> command or the DBI
     documentation for details about AutoCommit.

default_database
     This takes the name of the default database. This database is always
     used, if a CIPP SQL command ommits the DB parameter.  The value
     passed here must be a defined key in the databases hash.

lang
     CIPP has multilanguage support for its error messages, actually
     english ('EN') and german ('DE') are supported.

   The CGI wrapper program uses the CGI feature PATH_INFO to determine
which page should be executed. To execute the CIPP page 'test.cipp'
located in '/www/htdocs/cippfiles/foo/test.cipp' you must specify the
following URL (assuming the configuration of the example above):

     http://somehost/cgi-bin/cipp/foo/test.cipp

   You simply add the path of your page (relative to the path you
specified with the document_root parameter) to the URL of the CGI wrapper.

   Be aware of the real URL of your page if you use relative URL's to non
CIPP pages in your CIPP page. In the above example relative URL's must
consider that the CGI wrapper program is located in a different location
as the directory you declared as the CIPP document root. This implies that
it is not possible to place CIPP program files and traditional static HTML
documents or images into the same directory.

APACHE CONFIGURATION
====================

   If you're using the Apache webserver (what is always recommended :) you
can avoid the above stated disadvantages. In this case you should
configure your CIPP CGI wrapper program as a extra handler.

   Simply add the following directives to your appropriate Apache config
file:

     AddHandler x-cipp-execute cipp
     Action x-cipp-execute /cgi-bin/cipp

   The CGI wrapper program is still located in a extra cgi-bin directory.
But now all files with the extension .cipp are handled through it.

   The CGI::CIPP configuration slightly changes, we reasign the
document_root:

     document_root	/www/htdocs

   We now declare the Apache DocumentRoot also to be the document_root of
CGI::CIPP, so no special subdirectory is needed.

   This is a example URL for a CIPP page located in
/www/htdocs/foo/test.cipp

     http://somehost/foo/test.cipp

   Now you are able to place CIPP files on your webserver wherever you
want, because there is no special CIPP directory anymore. Only the suffix
.cipp is relevant, due to the AddHandler directive above. So you can mix
traditional static documents with CIPP files and relative URL adressing is
no problem at all.

Security Hint
-------------

   To prevent users from viewing your Include or Config files, you should
configure your webserver to forbid access to these files. In case of
Apache add the following contatiner to your Apache configuration:

     <Location ~ "\.(conf|inc)$">
       Order allow,deny
       Deny from all
     </Location>

   This assumes that you name your Config files *.conf and your Include
*.inc. CIPP does not care about the extensions of your Config and Include
files. To make your life easier, you should ;)

CGI::SpeedyCGI and CIPP::CGI
============================

   There exists a really nice module called CGI::SpeedyCGI, which is
available freely via CPAN. It implements a nifty way of making Perl CGI
processes persistent, so subseqeuent CGI calls are answered much more
faster.

   Using CIPP::CGI together with CGI::SpeedyCGI is easy. Simply replace
the perl interpreter path in the shebang line `#!/usr/local/bin/perl' with
the according path to the speedy program, e.g.: `#!/usr/local/bin/speedy'.

   Refer to the CGI::SpeedyCGI documentation for details about configuring
SpeedyCGI. I recommend the usage of the -r and -t switch, so you are able
to control the number of parallel living speedy processes, e.g.

     #!/usr/local/bin/speedy -- -r30 -t120

   Each speedy process now answeres a maximum of 30 requests and then dies.
If a process is idle for longer than 120 secs it dies also.

AUTHOR
======

   Joern Reder <joern@dimedis.de>

COPYRIGHT
=========

   Copyright 1998-1999 Joern Reder, All Rights Reserved

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1), CIPP(3pm), Apache::CIPP(3pm), CGI::SpeedyCGI(3pm)

Perl extension to help cache output of time-intensive CGI scripts so that subsequent visits to such scripts will not cost as much time.
***************************************************************************************************************************************

NAME
====

   CGI::Cache - Perl extension to help cache output of time-intensive CGI
scripts so that subsequent visits to such scripts will not cost as much
time.

WARNING
=======

   The interface as of version 1.01 has changed considerably and is NOT
compatible with earlier versions.

SYNOPSIS
========

     use CGI;
     use CGI::Cache;

     my $query = new CGI;

     # Set up a cache in /tmp/CGI_Cache/demo_cgi, with publicly
     # read/writable cache entries, a maximum size of 20 megabytes,
     # and a time-to-live of 6 hours.
     CGI::Cache::setup( { cache_key => '/tmp/CGI_Cache',
                          namespace => 'demo_cgi',
                          filemode => 0666,
                          max_size => 20 * 1024 * 1024,
                          expires_in => 6 * 60 * 60,
                        } );

     # CGI::Vars requires CGI version 2.50 or better
     CGI::Cache::set_key($query->Vars);
     CGI::Cache::start();

     print "Content-type: text/html\n\n";

     print <<EOF;
     <html><body>
     This prints to STDOUT, which will be cached.
     If the next visit is within 6 hours, the cached STDOUT
     will be served instead of executing these 'prints'.
     </body></html>
     EOF

DESCRIPTION
===========

   This module is intended to be used in a CGI script that may benefit
from caching its output. Some CGI scripts may take longer to execute
because the data needed in order to construct the page may not be readily
available. Such a script may need to query a remote database, or may rely
on data that doesn't arrive in a timely fashion, or it may just be
computationally intensive.  Nonetheless, if you can afford the tradeoff of
showing older, cached data vs. CGI execution time, then this module will
perform that function.

   This module was written such that any existing CGI code could benefit
from caching without really changing any of existing CGI code guts.  The
CGI script can do just what it has always done, that is, construct an html
page and print it to the STDOUT file descriptor, then exit.  What you'll
do in order to cache pages is include the module, specify some cache
options and the cache key, and then call start() to begin caching output.

   Internally, the CGI::Cache module ties the STDOUT file descriptor to an
internal variable to which all output to STDOUT is saved. When the user
calls stop() (or the END{} block of CGI::Cache is executed during script
shutdown) the contents of the variable are inserted into the cache using
the cache key the user specified earlier with set_key().

   Once a page has been cached in this fashion, then a subsequent visit to
that CGI script will check for an existing cache entry for the given key
before continuing through the code. If the file exists, then the cache
file's content is printed to the real STDOUT and the process exits before
executing the regular CGI code.

CHOOSING A CACHE KEY
--------------------

   The cache key is used by CGI::Cache to determine when cached output can
be used. The key should be a unique data structure that fully describes
the execution of the script. Conveniently, CGI::Cache can take the CGI
module's parameters (using CGI::Vars) as the key. However, in some cases
you may want to specially construct the key.

   For example, say we have a CGI script "airport" that computes the
number of miles between major airports. You supply two airport codes to
the script and it builds a web pages that reports the number of miles by
air between those two locations. In addition, there is a third parameter
which tells the script whether to write debugging information to a log
file. Suppose the URL for Indianapolis Int'l to Chicago O'Hare looked like:

     http://www.some.machine/cgi/airport?from=IND&to=ORD&debug=1

   We might want to remove the debug parameter because the output from the
user's perspective is the same regardless of whether a log file is written:

     my $params = $query->Vars;
     delete $params->{'debug'};
     CGI::Cache::set_key($params);
     CGI::Cache::start();

THE CGI::CACHE ROUTINES
-----------------------

setup( \%options );
     Sets up the cache. The parameters are the same as the parameters for
     the File::Cache module's new() method, with the same defaults. Below
     is a brief overview of the options and their defaults. This overview
     may be out of date with your version of File::Cache. Consult *perldoc
     File::Cache* for more accurate information.

     NOTE: If you plan to modify warn() or die() (i.e. redefine
     $SIG{__WARN__} or $SIG{__DIE__}) so that they no longer print to
     STDERR, you must do so before calling setup(). For example, if you do
     a "require CGI::Carp qw( fatalsToBrowser)", make sure you do it
     before calling CGI::Cache::setup().

    $options{cache_key}
          The cache_key is the location of the cache. Here cache_key is
          used in keeping with the terminology used by File::Cache, and is
          different from the key referred to in set_key below.

    $options{namespace}
          Namespaces provide isolation between cache objects. It is
          recommended that you use a namespace that is unique to your
          script. That way you can have multiple scripts whose output is
          cached by CGI::Cache, and they will not collide. This value
          defaults to a subdirectory of your temp directory whose name
          matches the name of your script (as reported by
          $ENV{SCRIPT_NAME}, or $0 if $ENV{SCRIPT_NAME} is not defined).

    $options{expires_in}
          If the "expires_in" option is set, all objects in this cache
          will be cleared after that number of seconds. If expires_in is
          not set, the web pages will never expire. The default is 24
          hours.

    $options{cache_key}
          The "cache_key" is used to determine the underlying filesystem
          namespace to use. Leaving this unset will cause the cache to be
          created in a subdirectory of your temporary directory called
          CGI_Cache. (The term "key" here is a bit misleading in light of
          the usage of the term earlier-this is really the path to the
          cache.)

    $options{max_size}
          "max_size" specifies the maximum size of the cache, in bytes.
          Cache objects are removed during the set() operation in order to
          reduce the cache size before the new cache value is added. The
          max_size will be maintained regardless of the value of
          auto_remove_stale. The default size is unlimited.

set_key ( <data> );
     set_key takes any type of data (e.g. a list, a string, a reference to
     a complex data structure, etc.) and uses it to create a unique key to
     use when caching the script's output.

start();
     Could you guess that the start() routine is what does all the work? It
     is this call that actually looks for an existing cache file, returning
     its content if it exists, then exits. If the cache file does not
     exist, then it captures the STDOUT filehandle and allows the CGI
     script's normal STDOUT be redirected to the cache file.

stop( [<cache_output> = 1] );     <cache_output> - do we write the captured STDOUT to a  cache file?
     The stop() routine tells us to stop capturing STDOUT.  The argument
     "cache_output" tells us whether or not to store the captured output in
     the cache. By default this argument is 1, since this is usually what
     we want to do. In an error condition, however, we may not want to
     cache the output.  A cache_output argument of 0 is used in this case.

     You don't have to call the stop() routine if you simply want to catch
     all STDOUT that the script generates for the duration of its
     execution.  If the script exits without calling stop(), then the END{}
     block of the module will check to see of stop() has been called, and
     if not, it will call it. Note that CGI::Cache will detect whether your
     script is exiting as the result of an error, and will not cache the
     output in this case.

BUGS
====

   Contact david@coppit.org for bug reports and suggestions.

AUTHOR
======

   The original code (written before October 1, 2000) was written by Broc
Seib, and is copyright (c) 1998 Broc Seib. All rights reserved.

   Maintenance of CGI::Cache is now being done by David Coppit
(david@coppit.org).

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

     File::Cache
     perldoc -f open

CGI routines for writing to the HTTPD (or other) error log
**********************************************************

NAME
====

   CGI::Carp - CGI routines for writing to the HTTPD (or other) error log

SYNOPSIS
========

     use CGI::Carp;

     croak "We're outta here!";
     confess "It was my fault: $!";
     carp "It was your fault!";
     warn "I'm confused";
     die  "I'm dying.\n";

     use CGI::Carp qw(cluck);
     cluck "I wouldn't do that if I were you";

     use CGI::Carp qw(fatalsToBrowser);
     die "Fatal error messages are now sent to browser";

DESCRIPTION
===========

   CGI scripts have a nasty habit of leaving warning messages in the error
logs that are neither time stamped nor fully identified.  Tracking down
the script that caused the error is a pain.  This fixes that.  Replace the
usual

     use Carp;

   with

     use CGI::Carp

   And the standard warn(), die (), croak(), confess() and carp() calls
will automagically be replaced with functions that write out nicely
time-stamped messages to the HTTP server error log.

   For example:

     [Fri Nov 17 21:40:43 1995] test.pl: I'm confused at test.pl line 3.
     [Fri Nov 17 21:40:43 1995] test.pl: Got an error message: Permission denied.
     [Fri Nov 17 21:40:43 1995] test.pl: I'm dying.

REDIRECTING ERROR MESSAGES
==========================

   By default, error messages are sent to STDERR.  Most HTTPD servers
direct STDERR to the server's error log.  Some applications may wish to
keep private error logs, distinct from the server's error log, or they may
wish to direct error messages to STDOUT so that the browser will receive
them.

   The `carpout()' function is provided for this purpose.  Since carpout()
is not exported by default, you must import it explicitly by saying

     use CGI::Carp qw(carpout);

   The carpout() function requires one argument, which should be a
reference to an open filehandle for writing errors.  It should be called
in a BEGIN block at the top of the CGI application so that compiler errors
will be caught.  Example:

     BEGIN {
       use CGI::Carp qw(carpout);
       open(LOG, ">>/usr/local/cgi-logs/mycgi-log") or
         die("Unable to open mycgi-log: $!\n");
       carpout(LOG);
     }

   carpout() does not handle file locking on the log for you at this point.

   The real STDERR is not closed - it is moved to CGI::Carp::SAVEERR.  Some
servers, when dealing with CGI scripts, close their connection to the
browser when the script closes STDOUT and STDERR.  CGI::Carp::SAVEERR is
there to prevent this from happening prematurely.

   You can pass filehandles to carpout() in a variety of ways.  The
"correct" way according to Tom Christiansen is to pass a reference to a
filehandle GLOB:

     carpout(\*LOG);

   This looks weird to mere mortals however, so the following syntaxes are
accepted as well:

     carpout(LOG);
     carpout(main::LOG);
     carpout(main'LOG);
     carpout(\LOG);
     carpout(\'main::LOG');

     ... and so on

   FileHandle and other objects work as well.

   Use of carpout() is not great for performance, so it is recommended for
debugging purposes or for moderate-use applications.  A future version of
this module may delay redirecting STDERR until one of the CGI::Carp
methods is called to prevent the performance hit.

MAKING PERL ERRORS APPEAR IN THE BROWSER WINDOW
===============================================

   If you want to send fatal (die, confess) errors to the browser, ask to
import the special "fatalsToBrowser" subroutine:

     use CGI::Carp qw(fatalsToBrowser);
     die "Bad error here";

   Fatal errors will now be echoed to the browser as well as to the log.
CGI::Carp arranges to send a minimal HTTP header to the browser so that
even errors that occur in the early compile phase will be seen.  Nonfatal
errors will still be directed to the log file only (unless redirected with
carpout).

Changing the default message
----------------------------

   By default, the software error message is followed by a note to contact
the Webmaster by e-mail with the time and date of the error.  If this
message is not to your liking, you can change it using the set_message()
routine.  This is not imported by default; you should import it on the
use() line:

     use CGI::Carp qw(fatalsToBrowser set_message);
     set_message("It's not a bug, it's a feature!");

   You may also pass in a code reference in order to create a custom error
message.  At run time, your code will be called with the text of the error
message that caused the script to die.  Example:

     use CGI::Carp qw(fatalsToBrowser set_message);
     BEGIN {
        sub handle_errors {
           my $msg = shift;
           print "<h1>Oh gosh</h1>";
           print "Got an error: $msg";
       }
       set_message(\&handle_errors);
     }

   In order to correctly intercept compile-time errors, you should call
set_message() from within a BEGIN{} block.

MAKING WARNINGS APPEAR AS HTML COMMENTS
=======================================

   It is now also possible to make non-fatal errors appear as HTML
comments embedded in the output of your program.  To enable this feature,
export the new "warningsToBrowser" subroutine.  Since sending warnings to
the browser before the HTTP headers have been sent would cause an error,
any warnings are stored in an internal buffer until you call the
warningsToBrowser() subroutine with a true argument:

     use CGI::Carp qw(fatalsToBrowser warningsToBrowser);
     use CGI qw(:standard);
     print header();
     warningsToBrowser(1);

   You may also give a false argument to warningsToBrowser() to prevent
warnings from being sent to the browser while you are printing some
content where HTML comments are not allowed:

     warningsToBrowser(0);    # disable warnings
     print "<SCRIPT type=javascript><!--\n";
     print_some_javascript_code();
     print "//--></SCRIPT>\n";
     warningsToBrowser(1);    # re-enable warnings

   Note: In this respect warningsToBrowser() differs fundamentally from
fatalsToBrowser(), which you should never call yourself!

CHANGE LOG
==========

   1.05 carpout() added and minor corrections by Marc Hedlund
<hedlund@best.com> on 11/26/95.

   1.06 fatalsToBrowser() no longer aborts for fatal errors within
eval() statements.

   1.08 set_message() added and carpout() expanded to allow for FileHandle
    objects.

   1.09 set_message() now allows users to pass a code REFERENCE for
really custom error messages.  croak and carp are now      exported by
default.  Thanks to Gunther Birznieks for the      patches.

   1.10 Patch from Chris Dean (ctdean@cogit.com) to allow      module to
run correctly under mod_perl.

   1.11 Changed order of &gt; and &lt; escapes.

   1.12 Changed die() on line 217 to CORE::die to avoid -w warning.

   1.13 Added cluck() to make the module orthogonal with Carp.       More
mod_perl related fixes.

   1.20 Patch from Ilmari Karonen (perl@itz.pp.sci.fi):  Added
warningsToBrowser().  Replaced <CODE> tags with <PRE> in
fatalsToBrowser() output.

AUTHORS
=======

   Copyright 1995-1998, Lincoln D. Stein.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Address bug reports and comments to: lstein@cshl.org

SEE ALSO
========

   Carp, CGI::Base, CGI::BasePlus, CGI::Request, CGI::MiniSvr, CGI::Form,
CGI::Response

send minimalistic error messages to the browser
***********************************************

NAME
====

     CGI::ClientError - send minimalistic error messages to the browser

SYNOPSIS
========

     use CGI::ClientError;
     &CGI::ClientError::setheaderfile('/path/to/some/header');
     &CGI::ClientError::setfooterfile('/path/to/some/footer');
     &CGI::ClientError::setheader("Content-Type: text/plain\n\nYou've done something wrong: ");
     &CGI::ClientError::setfooter("If this is unclear, go hang yourself.");

     &CGI::ClientError::sethandler(sub { die; });

     (...)

     if (clientisadork) { &CGI::ClientError::error("You are a dork!");
     # or
     if (clientisadork) { &cgi_report_error("You are a dork!");

DESCRIPTION
===========

   Errors might appear in a CGI.  If the script knows what is wrong, it
should tell what is wrong.  But I think it's important to separate between
when it should tell the client, and when it should tell the webmaster.
The user/client shouldn't be get error messages that are irrelevant or
meaningless or even possibly exploitable - as "out of disk", "out of
memory", "core dumped", etc.  Instead, the script should die, the error
should be logged, and perhaps even sent by mail to the webmaster - and
perhaps even to his cellphone.  The user should get an 500 and a clear,
friendly message that the problem is at the server side and probably will
be dealt with ("try again later, or mail webmaster").

   Anyway, sometimes the client is to blame for the error.  He has typed
in a text string in a number box, he claims beeing born in 2019-14-14, he
has been typing in a long URL with illegal parameters, etc. Then the
client should get an informative error message.  That's what this small
module is for.

   Three variables might be set by the caller program, header, footer and
handler. The header and footer is what to output before and after the
error message. The default header is:   Content-Type: text/html
<H1>Error</h1>   Here is an error message for you:<br>   <i>

   The default footer is:   </i><br>   If something is unclear, feel free
to contact the   webmaster.

   The default handler is ... do nothing.

   Somebody has probably written scientific papers about how to be
respectfully and pedagogic when telling a user that he has done an error.
I think it is wise to be humble, don't expect too much - remember, the
average web user of today is not a typical unix user.  I don't know.  I
don't care.

   This module probably stinks - but the idea itself doesn't; I think it's
proper to use "die" if it's a real server error, and some other sub /
method if it's actually a client error.

AUTHOR
======

   Tobias Brox <tobix@irctos.org>

Decorator class which adds several hook to CGI::param().
********************************************************

NAME
====

   CGI::ConvertParam - Decorator class which adds several hook to
CGI::param().

SYNOPSIS
========

     package CGI::ConvertParam::OngetUTF8;
     use base 'CGI::ConvertParam';
     use Jcode;

     sub do_convert_on_get
     {
         my $self = shift;
         my $parameter_value = shift;
         return Jcode->new($parameter_value)->utf8;
     }
     1;

     package client;
     use CGI;
     use CGI::ConvertParam::OngetUTF8;

     $query = CGI::ConvertParam::OngetUTF8->new(CGI->new);
     print $query->param('parameter_foo');

DESCRIPTION
===========

   CGI::ConvertParam and the subclass are Decorator which adds some hooks
to the CGI::param() method.

EXAMPLE
=======

All parameters are converted to EUC-JP
--------------------------------------

     package CGI::ConvertParam::EUC;
     use base 'CGI::ConvertParam';
     use Jcode;

     sub initialize
     {
         my $self = shift;
         $self->convert_all_param;
     }

     sub do_convert_all
     {
         my $self    = shift;
         my $strings = shift;
         return Jcode->new($strings)->euc;
     }
     1;

     package main;
     use CGI;
     use CGI::ConvertParam::EUC;
     my $query = CGI::ConvertParam::EUC->new(CGI->new);
     print 'Name(EUC-JP):', $query->param('NAME');

Convert Shift-JIS on Setting the value or values of a named parameter:
----------------------------------------------------------------------

     package CGI::ConvertParam::OnsetShiftJIS;
     use base 'CGI::ConvertParam';
     use Jcode;

     sub do_convert_on_set
     {
         my $self    = shift;
         my $strings = shift;
         return Jcode->new($strings)->sjis;
     }
     1;

     package main;
     use CGI;
     use CGI::ConvertParam::OnsetShiftJIS;
     my $query = CGI::ConvertParam::OnsetShiftJIS->new(CGI->new);
     $query->param(NAME => $value);
     print 'Name(Shift-JIS):', $query->param('NAME');

Convert UTF-8 on Fetching the value or values of a named parameter:
-------------------------------------------------------------------

     package CGI::ConvertParam::OngetUTF8;
     use base 'CGI::ConvertParam';
     use Jcode;

     sub do_convert_on_get
     {
         my $self    = shift;
         my $strings = shift;
         return Jcode->new($strings)->utf8;
     }
     1;

     package main;
     use CGI;
     use CGI::ConvertParam::OngetUTF8;
     my $query = CGI::ConvertParam::OngetUTF8->new(CGI->new);
     $query->param(NAME => $value);
     print 'Name(UTF-8):', $query->param('NAME');

METHOD
======

Class method
------------

new(*CGI_OBJECT*)
     The new() method is the constructor for a CGI::ConvertParam and
     sub-class. *CGI_BOJECT* is the reference of the CGI instance. It
     return a specialized CGI instance.

Instance method
---------------

convert_all_param()
     This method is convert the all named parameter.

Subclassing and Override methods
--------------------------------

   CGI::ConvertParam implements some methods which are expected to be
overridden by implementing them in your subclass module. These methods are
as follows:

initialize()
     This method is colled by the inherited new() constructor method. The
     initialize() method should be used to define the following
     property/methods:

do_convert_on_set()
     This method is called by *param('name' => $value)* method. The
     do_convert_on_set() method shuld be used to define the converter.

do_convert_on_get()
     This method is called by *param('name')* method. The
     do_convert_on_get() method shuld be used to define the converter.

do_convert_all_param
     This method is called by convert_all_param() method. The
     *do_convert_all_param()* method shuld be used to define the converter.

Data-access method
------------------

query()
     This method is return the original CGI instance.

SEE ALSO
========

   See CGI,

AUTHOR
======

   OYAMA Hiroyuki <oyama@crayfish.co.jp> http://perl.infoware.ne.jp/

COPYRIGHT
=========

   Copyright(c) 2000, OYAMA Hiroyuki. Japan. All rights reserved.

   CGI::ConvertParam class may be copied only under the terms of either
the Artistic License or the GNU General Public License, which may be found
in the Perl 5 source kit.

Interface to Netscape Cookies
*****************************

NAME
====

   CGI::Cookie - Interface to Netscape Cookies

SYNOPSIS
========

     use CGI qw/:standard/;
     use CGI::Cookie;

     # Create new cookies and send them
     $cookie1 = new CGI::Cookie(-name=>'ID',-value=>123456);
     $cookie2 = new CGI::Cookie(-name=>'preferences',
                                -value=>{ font => Helvetica,
                                          size => 12 }
                                );
     print header(-cookie=>[$cookie1,$cookie2]);

     # fetch existing cookies
     %cookies = fetch CGI::Cookie;
     $id = $cookies{'ID'}->value;

     # create cookies returned from an external source
     %cookies = parse CGI::Cookie($ENV{COOKIE});

DESCRIPTION
===========

   CGI::Cookie is an interface to Netscape (HTTP/1.1) cookies, an
innovation that allows Web servers to store persistent information on the
browser's side of the connection.  Although CGI::Cookie is intended to be
used in conjunction with CGI.pm (and is in fact used by it internally),
you can use this module independently.

   For full information on cookies see

     http://www.ics.uci.edu/pub/ietf/http/rfc2109.txt

USING CGI::Cookie
=================

   CGI::Cookie is object oriented.  Each cookie object has a name and a
value.  The name is any scalar value.  The value is any scalar or array
value (associative arrays are also allowed).  Cookies also have several
optional attributes, including:

*1. expiration date*
     The expiration date tells the browser how long to hang on to the
     cookie.  If the cookie specifies an expiration date in the future, the
     browser will store the cookie information in a disk file and return it
     to the server every time the user reconnects (until the expiration
     date is reached).  If the cookie species an expiration date in the
     past, the browser will remove the cookie from the disk file.  If the
     expiration date is not specified, the cookie will persist only until
     the user quits the browser.

*2. domain*
     This is a partial or complete domain name for which the cookie is
     valid.  The browser will return the cookie to any host that matches
     the partial domain name.  For example, if you specify a domain name
     of ".capricorn.com", then Netscape will return the cookie to Web
     servers running on any of the machines "www.capricorn.com",
     "ftp.capricorn.com", "feckless.capricorn.com", etc.  Domain names
     must contain at least two periods to prevent attempts to match on top
     level domains like ".edu".  If no domain is specified, then the
     browser will only return the cookie to servers on the host the cookie
     originated from.

*3. path*
     If you provide a cookie path attribute, the browser will check it
     against your script's URL before returning the cookie.  For example,
     if you specify the path "/cgi-bin", then the cookie will be returned
     to each of the scripts "/cgi-bin/tally.pl", "/cgi-bin/order.pl", and
     "/cgi-bin/customer_service/complain.pl", but not to the script
     "/cgi-private/site_admin.pl".  By default, the path is set to "/", so
     that all scripts at your site will receive the cookie.

*4. secure flag*
     If the "secure" attribute is set, the cookie will only be sent to your
     script if the CGI request is occurring on a secure channel, such as
     SSL.

Creating New Cookies
--------------------

     $c = new CGI::Cookie(-name    =>  'foo',
                                  -value   =>  'bar',
                                  -expires =>  '+3M',
                                  -domain  =>  '.capricorn.com',
                                  -path    =>  '/cgi-bin/database'
                                  -secure  =>  1
                         );

   Create cookies from scratch with the new method.  The *-name* and
*-value* parameters are required.  The name must be a scalar value.  The
value can be a scalar, an array reference, or a hash reference.  (At some
point in the future cookies will support one of the Perl object
serialization protocols for full generality).

   *-expires* accepts any of the relative or absolute date formats
recognized by CGI.pm, for example "+3M" for three months in the future.
See CGI.pm's documentation for details.

   *-domain* points to a domain name or to a fully qualified host name.
If not specified, the cookie will be returned only to the Web server that
created it.

   *-path* points to a partial URL on the current server.  The cookie will
be returned to all URLs beginning with the specified path.  If not
specified, it defaults to '/', which returns the cookie to all pages at
your site.

   *-secure* if set to a true value instructs the browser to return the
cookie only when a cryptographic protocol is in use.

Sending the Cookie to the Browser
---------------------------------

   Within a CGI script you can send a cookie to the browser by creating
one or more Set-Cookie: fields in the HTTP header.  Here is a typical
sequence:

     my $c = new CGI::Cookie(-name    =>  'foo',
                             -value   =>  ['bar','baz'],
                             -expires =>  '+3M');

     print "Set-Cookie: $c\n";
     print "Content-Type: text/html\n\n";

   To send more than one cookie, create several Set-Cookie: fields.
Alternatively, you may concatenate the cookies together with "; " and send
them in one field.

   If you are using CGI.pm, you send cookies by providing a -cookie
argument to the header() method:

     print header(-cookie=>$c);

   Mod_perl users can set cookies using the request object's header_out()
method:

     $r->header_out('Set-Cookie',$c);

   Internally, Cookie overloads the "" operator to call its as_string()
method when incorporated into the HTTP header.  as_string() turns the
Cookie's internal representation into an RFC-compliant text
representation.  You may call as_string() yourself if you prefer:

     print "Set-Cookie: ",$c->as_string,"\n";

Recovering Previous Cookies
---------------------------

     %cookies = fetch CGI::Cookie;

   fetch returns an associative array consisting of all cookies returned
by the browser.  The keys of the array are the cookie names.  You can
iterate through the cookies this way:

     %cookies = fetch CGI::Cookie;
     foreach (keys %cookies) {
        do_something($cookies{$_});
             }

   In a scalar context, fetch() returns a hash reference, which may be more
efficient if you are manipulating multiple cookies.

   CGI.pm uses the URL escaping methods to save and restore reserved
characters in its cookies.  If you are trying to retrieve a cookie set by
a foreign server, this escaping method may trip you up.  Use raw_fetch()
instead, which has the same semantics as fetch(), but performs no
unescaping.

   You may also retrieve cookies that were stored in some external form
using the parse() class method:

     $COOKIES = `cat /usr/tmp/Cookie_stash`;
     %cookies = parse CGI::Cookie($COOKIES);

Manipulating Cookies
--------------------

   Cookie objects have a series of accessor methods to get and set cookie
attributes.  Each accessor has a similar syntax.  Called without
arguments, the accessor returns the current value of the attribute.
Called with an argument, the accessor changes the attribute and returns
its new value.

name()
     Get or set the cookie's name.  Example:

          $name = $c->name;
          $new_name = $c->name('fred');

value()
     Get or set the cookie's value.  Example:

          $value = $c->value;
          @new_value = $c->value(['a','b','c','d']);

     value() is context sensitive.  In a list context it will return the
     current value of the cookie as an array.  In a scalar context it will
     return the first value of a multivalued cookie.

domain()
     Get or set the cookie's domain.

path()
     Get or set the cookie's path.

expires()
     Get or set the cookie's expiration time.

AUTHOR INFORMATION
==================

   Copyright 1997-1998, Lincoln D. Stein.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Address bug reports and comments to: lstein@cshl.org

BUGS
====

   This section intentionally left blank.

SEE ALSO
========

   See CGI/Carp, CGI,

module for CGI programs debugging
*********************************

NAME
====

   CGI::Debug - module for CGI programs debugging

SYNOPSIS
========

     use CGI::Debug;

     use CGI::Debug( report => ['errors', 'empty_body', 'time',
     			    'params', 'cookies', 'environment',
     			    ],
     		 on     => 'fatals',
     		 to     => { browser => 1,
     			     log     => 1,
     			     file    => '/tmp/my_error',
     			     mail    => ['staff@company.orb',
     					 'webmaster',
     					 ],
     			 },
     		 header => 'control',
     		 set    => { error_document => 'oups.html' },
     		 );

DESCRIPTION
===========

   CGI::Debug will catch (almost) all compilation and runtime errors and
warnings and will display them in the browser.

   Just "use CGI::Debug" on the second row in your program.  The module
will not change the behaviour of your cgi program. As long as your program
works, you will not notice the modules presence.

   At any time you can remove the "use CGI::Debug" without changing the
behaviour of your program. It will only start faster.

   The actions of CGI::Debug is determined by, in order:   1. cookie
control variables   2. environment control variables   3. the import
control parameters   4. the defaults

Default behaviour
-----------------

   Report to browser:

   * bad HTTP-headers

   * empty HTTP-body

   * warnings and errors

   * elapsed time

   * query parameters

   * cookies

   * environment variables (max 60 chars in value)

EXAMPELS
========

   Only report errors:     use CGI::Debug( report => 'errors' );

   Do not bother about warnings:     use CGI::Debug( on => 'fatals' );

   Allways show complete debugging info:     use CGI::Debug( report =>
'everything', on => 'anything' );

   Send debug data as mail to file owner:     use CGI::Debug( to => 'mail'
);

CONTROL PARAMETERS
==================

   Cookie control variables makes it possible to control the debugging
environment from a program in another browser window. This would be
prefereble with complex web pages (framesets, etc). The page is viewd as
normal in one window. All debugging data is shown i another window, that
also provides controls to alter the debugging environment. (But this
external debugging program is not yet implemented.)

   Environment control variables makes it more easy to globaly set the
debugging environment for a web site. It is also a way for the target
program to control the CGI::Debug module actions.

   The four methods can be mixed. (Cookies, enviroment, import parameters
and defaults.) The module will try to make sense with whatever you give
it. The possibilites of control are more limitied in the Cookie / ENV
version.

report errors
-------------

     Cookie / ENV: CGI-Debug-report=errors

     Import: report => 'errors'
     	  report => [ 'errors', ... ]

   Report the content of STDERR.

   This will allways be reported. This control is for saying that none of
the other defualt things will be reported. This will only override the
default. Other report controls will be accumulated.

report empty_body
-----------------

     Cookie / ENV: CGI-Debug-report=empty_body

     Import: report => 'empty_body'
     	  report => [ 'empty_body', ... ]

   Report if HTTP-body is empty.

   This requires that "header control" is set.

report time
-----------

     Cookie / ENV: CGI-Debug-report=time

     Import: report => 'time'
     	  report => [ 'time', ... ]

   Report the elapsed time from beginning to end of execution.

   If Time::Hires is found, this will be given with subsecond precision.

report params
-------------

     Cookie / ENV: CGI-Debug-report=params

     Import: report => 'params'
     	  report => [ 'params', ... ]

   Report a table of all name/value pairs, as given by the CGI module.

   Multiple values will be reported as distinct pairs, in order.  Values
will be truncated to the "set param_length" number of chars. The total
length is shown for each value.

report cookies
--------------

     Cookie / ENV: CGI-Debug-report=cookies

     Import: report => 'cookies'
     	  report => [ 'cookies', ... ]

   Report a table of all cookies, as given by the CGI module.

   Multiple values will be reported as distinct pairs, in order.  Values
will be truncated to the "set param_length" number of chars. The total
length is shown for each value.

report environment
------------------

     Cookie / ENV: CGI-Debug-report=environment

     Import: report => 'environment'
     	  report => [ 'environment', ... ]

   Report a table of all environment varialbes INCLUDING empty_body, time,
params, cookies.

report everything
-----------------

     Cookie / ENV: CGI-Debug-report=everything

     Import: report => 'everything'
     	  report => [ 'everything', ... ]

   Report environment and all what that includes.

   (The plan is for this control to include the contorl of HTML
compliance.)

report internals
----------------

     Cookie / ENV: CGI-Debug-report=internals

     Import: report => 'internals'
     	  report => [ 'internals', ... ]

   Report data for the debugging of the module itself, including
everything else.  Data::Dumper will be used, if found.

   If the module itself dies, you will probably not get any output at al.
You can check for errors in the file /tmp/CGI-Debug-error-$$.  In order to
see what error CGI::Debug is generating, you could changing $DEBUG to 2 or
more, in the module file itself. Please email the author about any
problems.

on fatals
---------

     Cookie / ENV: CGI-Debug-on=fatals

     Import: on => 'fatals'

   Only deliver report on fatal errors.

   This will ignore warnings. CGI::Debug checks the exit value.  Reports
will also be delivered if an empty body is detected, in case "header
control" is set.

on warnings
-----------

     Cookie / ENV: CGI-Debug-on=warnings

     Import: on => 'warnings'

   Only deliver report on fatals or if there was any output to STDERR.

on anything
-----------

     Cookie / ENV: CGI-Debug-on=anything

     Import: on => 'anything'

   Always deliver reports, even if there was no errors.

to browser
----------

     Cookie / ENV: CGI-Debug-to=browser

     Import: to => 'browser'
             to => [ 'browser', ... ]
             to => { 'browser' => 1, ... }

   Send report to browser.

   The report will come after any program output. The module will assume
the page is in text/html, unless "header control" is set, in case this
will be checked. (In none HTML mode, the header and delimiter will be
ASCII.)

   There is many cases in which faulty or bad HTML will hide the report.
This could be controled with "report html_compliance" (which is not yet
implemented).

to log
------

     Cookie / ENV: CGI-Debug-to=log

     Import: to => 'log'
             to => [ 'log', ... ]
             to => { 'log' => 1, ... }

   Send report to the standard error log.

   This will easily result in a huge log.

to file
-------

     Cookie / ENV: CGI-Debug-to=file
                   CGI-Debug-to-file=filename

     Import: to => 'file'
             to => [ 'file', ... ]
             to => { 'file' => 'filename', ... }
             to => { 'file' => [ 'filename1', 'filename2', ... ] ... }

   Save report to filename.

   Default filename is "/tmp/CGI-Debug-error.txt". The file will be
overwritten by the next report. This solution is to be used for debugging
with an external program. (To be used with cookies.)

   This will not work well with framesets that generates multipple reports
at a time. The action of this control may change in future versions.

to mail
-------

     Cookie / ENV: CGI-Debug-to=mail
                   CGI-Debug-to-mail=mailaddress

     Import: to => 'mail'
             to => [ 'mail', ... ]
             to => { 'mail' => 'mailaddress', ... }
             to => { 'mail' => [ 'mailaddress1', 'mailaddress2', ... ] ... }

   Send report with email.

   The default mailaddress is the owner of the cgi program.  This function
requires the Mail::Send module. If there is any problem with the default
behaviour of Mail::Send, set the enviroment variables, as described in the
POD for Mail::Mailer, either for the HTTP server, or before "use
CGI::Debug" in a BEGIN block.

   The idea is to specify an email address that will be used if anybody
besides yourself is getting an error. You will not get your own errors as
email if you overide that action with a control cookie.

header control
--------------

     Cookie / ENV: CGI-Debug-header=control

     Import: header => 'control'

   Controls that the HTTP-header is correct.

   This control will follow the HTTP RFC to the point. It reports if the
header is ok, if the content-type is text/html, and the length of the
HTTP-body. That information will be used by other parts of CGI::Debug.
This is done by redirecting STDOUT to a temporary file.  This is the only
control that must be set in the beginning of the program.  All other
controls can be changed during before the end of the program.

header ignore
-------------

     Cookie / ENV: CGI-Debug-header=ignore

     Import: header => 'ignore'

   Assume that the HTTP-header is correct and specifies text/html.

   This will tell CGI::Debug to ignore the STDOUT. A server generated
error response will result if the program compile ok but does not produce
a valid HTTP-header.

header minimal
--------------

     Cookie / ENV: CGI-Debug-header=minimal

     Import: header => 'minimal'

   Generates a simple text/html HTTP-header for you.

   This is the only action that CHANGES THE BEHAVIOUR of your program.
You will have to insert your own header if you remove the CGI::Debug row.
But this action will guarantee that you have a valid header, without the
need to save STDOUT to a temporary file.

set param_length
----------------

     Cookie / ENV: CGI-Debug-set-param_length=value

     Import: set => { param_length => 'value', ... }

   Set the max length of the parameter values.

   The default length is 60 chars. This is used for query parameters,
cookies and environment. The purpose is to give you a table that looks
good.

set error_document
------------------

     Cookie / ENV: CGI-Debug-set-error_document=value

     Import: set => { error_document => 'value', ... }

   Set what page to redirect to if there was an error report, not sent to
browser.

   This will show up in the browser if the error is going somewhere else.
If no page is specified, a short generic CGI error response will show up.
But if the CGI program succeeded in printing a valid http header and
something in the body, that will be showed instead, even if the program
later crashed.

MOD_PERL
========

   CGI::Debug will not function under mod_perl. The only solution to get
similar functionality is to develop a replacement for Apache::Registry,
with integrated debugging features.  The configuration interface can not
include the "use CGI::Debug ( report => ... )" style, in a mod_perl
version.

   If you run CGI::Debug under mod_perl, it will do nothing, except
sending a warning to STDERR.

TODO
====

   These are things that could be done to make CGI::Debug even better.  I
have no plan to add new features myself.  Feel free to contribute.

   * Clean up and generalize configuration

   * Test on non-*nix platforms

   * Implement HTML_compliance controls (using HTML::validate)

   * Implement function for debugging in a separate window

COPYRIGHT
=========

   Copyright (c) 1999-2000 Jonas Liljegren. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

AUTHOR
======

   Jonas Liljegren <jonas@paranormal.se>

SEE ALSO
========

   CGI, Mail::Send, Time::Hires, Data::Dumper, perl

Implement trusted stateful CGI Form Data using cryptography.
************************************************************

NAME
====

   CGI::EncryptForm - Implement trusted stateful CGI Form Data using
cryptography.

SYNOPSIS
========

     use CGI::EncryptForm;

     my $cfo = new CGI::EncryptForm(secret_key => 'my secret');

     my $hashref = { username => 'joe', password => 'test' };

     my $encrypted_string = $cfo->encrypt($hashref);
     if (!defined($encrypted_string)) {
       print $cfo->error();
       return;
     }

     my $newhashref = $cfo->decrypt($encrypted_string);
     if (!defined($newhashref)) {
       print $cfo->error();
       return;
     }

     print $newhashref->{'username'};

PREREQUISITES
=============

   This modules requires the following perl modules:

   Digest::SHA1, Crypt::HCE_SHA and Storable

ABSTRACT
========

   Many CGI programmers take for granted the validity of stateful CGI form
data.

   Im talking about the common scenario where you present a form to the
browser, the user fills in the form, you verify the form values, store
them in the next form as hidden fields, the user fills in another form,
the script appends these results to the next form in hidden fields and so
on.

   Using hidden form fields is one mechanism where by CGI scripts can
maintain state in the process of collecting information from the user.

   Unfortunately, it is also one of the weakest to implement because the
CGI script must trust the hidden form fields and there values, provided by
the users browser. At some point in time the CGI program does something
with this stateful information. To be completely sure the hidden fields
haven't been altered along the way and thus rendered initial verification
checks useless, the programmer must continually verify all new form fields
and previous state (encapsulated in hidden form fields) to be sure the
desired constraints are met. This process of verification becomes tedious
to program especially if there are many forms required to produce a final
result.

   To tackle this problem I created CGI::EncryptForm, where by instead of
including state in hidden form fields verbatim, we use SHA1 encryption
algorithm to provide a satisfactory level of trust between the users
browser and the CGI script.

DESCRIPTION
===========

   An object is created with a secret key defined by the CGI script. The
objects encrypt() method is called with a perl data structure, which in the
context of CGI scripts would normally contain key/value pairs.  The
encrypt() method returns an encrypted string. The encrypted string is
stored in a hidden form field. The user fills in the form. The CGI script
processes the form, extracts the encrypted string from the hidden form
field, decrypts the string and returns the original data structure.
Further results from the form are added to the data structure, then it is
encrypted again and stored in the next form as a hidden field.  This
process continues until the CGI script has all the desired information and
is ready to process it. To process the results, the CGI script decrypts
the encrypted string from the last hidden form field, which contains the
*collective state* of all previous form input.

   Along the way, the users input was verified only once. The fact that
state was encrypted and therefore trusted, renders the process of
continually verifying all state for each form processed, unnecessary.

METHODS
=======

*new CGI::EncryptForm*([secret_key => $s [, usecharset => $a]])
     Create a new CGI::EncryptForm object. All of the paramaters are
     optional.  $s specifies the secret key to use during
     encryption/decryption. $a specifies whether to enable (1) or disable
     (0) the character set encoding/decoding of the encrypted/decrypted
     result. By default this is enabled.

encrypt($hashref)
     Encrypt the data structure and return an encrypted string. $hashref
     must be a reference to an associative array supported by the Storable
     module.  If called with no arguement, returns the previous encrypted
     string.

     Upon error, the method returns undef and sets error().

decrypt($encrypted_string)
     Decrypt the encrypted string and return a reference to an associative
     array.  $encrypted_string must be a scalar previously generated by
     encrypt().  If called with no arguement, returns the previous
     reference.

     Upon error, the method returns undef and sets error(). If the
     encrypted string is tampered with the decryption routine should fail
     with undef, but this is ultimately dependant on the strength of SHA1
     digests.

*secret_key*($secret)
     Sets the secret key for use during encryption/decryption. This method
     is analogues to the secret_key paramater when creating a
     CGI::EncryptForm object.  If called with no $secret it returns the
     current secret key or undef if undefined.

     Upon error, the method returns undef and sets error().

*usecharset*(1)
     Enables or disables the character set encoding/decoding of
     encrypted/decrypted strings. This method is analogues to the
     usecharset paramater when creating a CGI::EncryptForm object. By
     default usecharset is enabled (1) and should be ignored unless you
     use this module in non CGI programs. The encode/decode routine
     applies the default or user defined (*see charset()*) character set to
     encode/decode the encrypted string, before returning to the caller.

charset($arrayref)
     Sets the character set which will be used to encode/decode the
     encrypted/decrypted string. This method accepts a single array
     reference that must contain a character set from 0 to 255, where by
     each element must be 2 characters and UNIQUE. e.g.

          charset(qw[/aA aB aC aD ... /])

     If this method is not called with your own character set, a default
     character set will be used which produces suitable output to store the
     result of the encrypt() method in form fields, URL's and cookies.

     Upon error, the method returns undef and sets error().

error()
     Returns the last error as a scalar. You would normally read this if
     any method returns undef. error() is always cleared for each method
     that executes successfully.

EXAMPLE
=======

   This example illustrates the use of CGI::EncryptForm in combination with
CGI.pm to maintain stateful information in a multi-form CGI script.

     #!/usr/local/bin/perl

     use CGI::EncryptForm;
     use CGI;
     use vars qw($cgi $cfo);

     $cgi = new CGI();
     $cfo = new CGI::EncryptForm(secret_key => 'blah');

     print $cgi->header(), $cgi->start_html(), $cgi->start_form();

     if (defined $cgi->param('enc')) {
         form3();
     }
     elsif (defined $cgi->param('something')) {
         form2();
     }
     else {
         form1();
     }

     print $cgi->end_html(), $cgi->end_form();

     sub form1 {

     print "<h1>form1</h1>",
           "Type something and we will remember it: ",
           $cgi->textfield('something'), $cgi->submit();
       }

     sub form2 {

     print "<h1>form2</h1>",
           $cgi->hidden(-name=>'enc', value=>$cfo->encrypt({ $cgi->Vars })),
           "Now click here and I will tell you what you typed based on ",
           "the encrypted hidden form field, which you would normally ",
           "only see if you view the HTML source. For the sake of this ",
           "demonstration the encrypted field is included below.<p>",
           $cfo->encrypt(), "<p>",
           "Before proceeding with this form I suggest you take note of ",
           "what the encrypted field looks like, then click the back ",
           "button and resubmit the previous form with the same value ",
           "again. What you will notice is the encrypted field will ",
           "change. This is because the SHA encryption algorithm is ",
           "based on a secret key and a random key. In the module we ",
           "take care of generating a unique random key for each ",
           "invocation of the encryption routine, which is why a ",
           "distinct encrypted string is produced each time.",
           "<p>", $cgi->submit();
       }

     sub form3 {

     my $hashref = $cfo->decrypt($cgi->param('enc'));
     if (!defined($hashref)) {
       print $cfo->error();
       return;
     }
     print "<h1>form3</h1>",
           "Previously in the first form you typed:<p>", $hashref->{something},
           "<p>We reproduced this data by decrypting the hidden form ",
           "field called 'enc', which was passed to us from the previous ",
           "form. You may like to try and tamper with the hidden form ",
           "field in form2, to see if you can alter the result of the ",
           "data as it originally flows from form 1 to form 3. Good luck";
       }

NOTES
=====

   CGI::EncryptForm is not limited to form fields. The encrypted result
can be stored in cookies and URL's as well. Personally though, I
discourage this because your more likely to exceed size limitations with
various web browsers and servers.

BUGS
====

   None that I know of.

TODO
====

   None.

AUTHOR
======

   Copyright 1999, Peter Marelas.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Bug reports and comments to maral@phase-one.com.au.

   Thanks to the authors of these fine perl modules Storable, Digest::SHA1
and Crypt::HCE_SHA.

SEE ALSO
========

   Storable, Digest::SHA1, Digest::HCE_SHA1

module for URL-encoding strings and hashes
******************************************

NAME
====

   CGI::Enurl.pm - module for URL-encoding strings and hashes

   version 1.06

SYNOPSIS
========

     use CGI::Enurl;
     %hash = (name=>'Jenda Krynicky',address=>'Nerudova 1016');
     print "Location: http://$ENV{SERVER_NAME}/cgi-bin/do.pl?",enurl \%hash,"\n\n";

DESCRIPTION
===========

   This is a little module made for CGI scripting. It encodes the
parameters to be passed to a CGI. It does nothing more, so it's much
smaller and loads more quickly.

Functions
=========

enurl STRING
enurl ARRAY
enurl HASH
     Encodes the parameter. If the parameter is a single string it encodes
     it and returns the encoded form.

     If it is an array or a reference to an array it encodes all items and
     returns them joined by '&'.

     If it is a hash it encodes the values and return a querystring in form
     "key2=encoded_value1&key2=encoded_value2&...".

     !!! Please note that a hash in a list context returns a list of all
     keys and values. This means that if you call enurl(%hash) you will NOT
     get what you may thing you should. You HAVE to use enurl(\%hash) !!!

enURL STRING
     Encodes the parameter, this version doesn't encode '=' and '&'
     characters, so you should make sure they are not present in the data.

     Notice the difference :

          enurl 'a&b=f o o'   =>   'a%26b%3Df+o+o'
          enURL 'a&b=f o o'   =>   'a&b=f+o+o'

$Enurl::ParamSeparator
     You may specify another character to be used as the parameter
     separator.  Simply set this variable to the character (or string) you
     want to use.

     The default value is '&'

$Enurl::KeepUnencoded
     This variable contains the characters that should stay unencoded.
     Please keep in mind that the string will be interpolated into a regexp
     in a [^...] group!

     Any change of this variable will be ignored after the first call to
     enurl or enURL. (I'm using /o switch in the regexp.) So if you want to
     change the variable you should do it as soon as posible. You may do
     that even before you "use" the module!

     The default value is 'a-zA-Z 0-9_\\-@.='

EXAMPLE:
--------

     use CGI::Enurl;

     print "Location: http://www.somewhere.com/Scripts/search.pl?",
      enurl('something strange'),"\n\n";

   or

     use CGI::Enurl;

     print "Location: http://www.somewhere.com/Scripts/search.pl?",
      enurl('something strange','and other',666),"\n\n";

   or

     use CGI::Enurl;

     print "Location: http://www.somewhere.com/Scripts/myscript.pl?",
      enurl({fname => 'Jan',lname => 'Krynický',tel => '+420-2-9618 1234'},1),"\n\n";

   or

     use CGI::Enurl;

     print "Location: http://www.somewhere.com/Scripts/myscript.pl?",
      enURL('fname=Jan&lname=Krynický&tel=+420-2-9618 1234&1',"\n\n";

   or using the tricks of Interpolation.pm -
http://www.plover.com/~mjd/perl/Interpolation/manual.html

     use CGI::Enurl;
     use Interpolation URL => \&enurl;
     print "name=$URL{'Jann Linder, jr'}&address=$URL{'129 kjhlkjd st'}";

   or even

     use CGI::Enurl;
     use Interpolation enurl => sub {my %hash=split /$;/o,$_[0];enurl \%hash};
      # use other name instead of enurl if you like.

     print "script.pl?$enurl{name=>'Jenda Krynicky',address=>'Nerudova 1016'}\n";

     %hash = (name=>'Jenda Krynicky',address=>'Nerudova 1016');

     sub var {
      if (ref $_[0] eq 'HASH') {
        join $;, %{shift()}, @_;
      } else {
        join $;, @_;
      }
     }

     print "script.pl?$enurl{var %hash}\n";
     	 # the "var" is necessary !
         # without it you will get : "Odd number of elements in hash list at ... line 2."

     print "script.pl?$enurl{var %hash,age=>22}\n";

     # you may omit the "var" only if you enter the hash as a constant directly
     # into $enurl{...}.

   If you want to be cheeky you may use '$?{}' as the interpolator:

     use CGI::Enurl;
     use Interpolation '?' => sub {my %hash=split /$;/o,$_[0]; '?' . enurl \%hash};

     print "cript.pl$?{a=>5,b=>7,n=>'Jenda Krynicky'}\n";

   or

     use CGI::Enurl;
     use Interpolation '?' => sub {'?' . enURL $_[0]};

     print "cript.pl$?{'a=5&b=7&n=Jenda Krynicky'}\n";
     # # or
     # print qq{cript.pl$?{"a=5&b=7&n=$name"}\n};

   Please read the docs for enurl versus enURL so that you understand the
difference!

DISCLAIMER
----------

   The enurl_str function is taken from CGI.pm. (It's named 'escape'
there.) Thanks.

AUTHOR
------

   Jan Krynicky <Jenda@Krynicky.cz>

COPYRIGHT
---------

   Copyright (c) 1997 Jan Krynicky <Jenda@Krynicky.cz>. All rights
reserved.  This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

A class to manage a tree of data, for use in CGI scripts
********************************************************

NAME
====

   `CGI::Explorer' - A class to manage a tree of data, for use in CGI
scripts

VERSION
=======

   This document refers to version 1.00 of `CGI::Explorer', released
24-02-2001.

SYNOPSIS
========

   This is tested code, altho the she-bang (#!) must start in column 1:

     #!D:/Perl/Bin/Perl

     use integer;
     use strict;
     use warnings;

     use CGI;
     use CGI::Explorer;

     my($q)		= CGI -> new();
     my($tree)	= CGI::Explorer -> new();
     my($dir)	= 'D:/My Documents/HomePage';

     $tree -> from_dir($dir);

     my($state)		= $tree -> state($q); # Must follow from_dir() or from_hash().
     my($tree_set)	= $tree -> as_HTML($q);
     my($result_set)	= 'Id: ' . $tree -> current_id() . '. Name: ' . $tree -> name();

     print	$q -> header(),
     		$q -> start_html(),
     		$q -> start_form({action => $q -> url()}),
     		$q -> hidden({name => 'explorer_state', value => $state, force => 1}),
     		$q -> table
     		(
     			{border => 1},
     			$q -> Tr
     			([
     				$q -> td($tree_set) .
     				$q -> td($result_set),
     			])
     		),
     		$q -> end_form(),
     		$q -> end_html();

DESCRIPTION
===========

   `CGI::Explorer' is a support module for CGI scripts. It manages a tree
of data, so that the script can display the tree, and the user can click
on a node in the tree to open or close that node.

   Opening a node reveals all children of that node, and restores their
open/close state.

   Closing a node hides all children of that node.

Overview
========

   `CGI::Explorer' reconstructs its internal representation of the tree
each time the script is invoked.

   Some of data comes from the script calling $tree -> from_directory(...)
or $tree -> from_hash(...), and some of the data comes from CGI form
fields returned from the previous invocation of the script.

   Specifically, the open/closed state of each node is sent on a round
trip from one invocation of the script out to the browser, and, via a
'form submit', back to the next invocation of the script.

   Also, clicking on a node on a form submits the form, and passed the id
of the node so clicked back to the second invocation of the script.

   State maintenance - a complex issue - is discussed further below. See
the 'state' method.

Constructor and initialization
==============================

   new(...) returns a `CGI::Explorer' object.

   This is the class's contructor.

   A call to new() is equivalent to:

   new(a_href => 0, image_dir => '/images', show_current => 1, show_id =>
1, show_name => 1)

   Options:

   * a_href - Default is 0

     Make the displayed name of the node an anchor.

   * image_dir - Default is '/images'

     Specify the web server's directory in which the node icons are to be
     found.

     Note: This is not the operating system path of the directory, it is
     the path relative to the web server's document root.

   * show_current - Default is 1

     Show a special icon for the 'current' node.

   * show_id - Default is 1

     Show the id of the node, to the right of the node's icon.

   * show_name - Default is 1

     Show the name of the node, to the right of the node's icon, and to
     the right of the node's id (if show_id == 1).

     If show_id == 0 && show_name == 0, nothing is displayed.

Icons for Nodes
===============

   `CGI::Explorer' ships with a set of icons, with a PNG and a GIF for
each icon.

   The default is GIF, because more browsers support GIF transparency than
support PNG transparency.

   You don't have to pay UniSys a licence for usage of the GIF compression
algorithm, because the GIFs are uncompressed :-).

   The make file does not install these files automatically. You must
install them manually under the web server's document root, and then use
the image_dir option to point to the directory containing these files.

   Many GIFs are from a package called MySQLTool. Unfortunately the
authors of this program have forgotten to put a download URI in their
package. You may get some joy here:
http://lists.dajoba.com/m/listinfo/mysqltool.

   I've renamed their files from the names used by MySQLTool.

   The icons for the root node, and for the current node, are not quite
satisfactory.  Let me know if you have better ones available.

   If the transparent PNG does not display properly on your browser, which
is likely, update the browser, or try using the GIFs.

   Almost all icons are constrained to a size of 17 x 17. The exception is
the icon for the root, which is unconstrained, so that you may use any
image you wish.

as_HTML($q)
===========

   Returns a string.

   Converts the internal representation of the data into HTML, and returns
that.

_build_result(...)
==================

   Used internally.

current_id()
============

   Returns the id of the 'current' node.

_found()
========

   Used internally.

   Called by File::Find, which means it does not receive $self as its
first parameter, which means in turn that it must use the class global
$myself to access class data.

from_dir($dir_name)
===================

   Returns nothing.

   Tells the object to construct its internal representation of the data
by parsing the names of all sub-directories in the given directory.

   Usage:

   * $tree -> from_directory('/home/rons');

   * $tree -> from_directory('D:\My Documents');

   * $tree -> from_directory('D:/My Documents');

   You call as_HTML($q) later to retrieve a printable version of the data.

   See ce.pl for an example.

from_hash($hash_ref)
====================

   Returns nothing.

   Tells the object to construct its internal representation of the data
by extracting information from the given hash.

   You would call as_HTML($q) later to retrieve a printable version of the
data.

   Each key in %$hash_ref is a unique integer, 1 .. N, and points to a
hash ref with these sub keys:

   * id - A unique integer, 1 .. N, different for each node

     This is the identifier of this node.

     Warning: There must be a node with id == 1.

     Yes, this is a copy of the key within $hash_ref, for use within
     Tree::Nary-dependent code.

   * name - A string

     This is the (displayed) name of this node.

   * parent_id - An integer, 0 .. N

     This is the identifier of the parent of this node.

     The relationship between id and parent_id is what makes the data a
     tree.

     0 means the node has no parent, ie this node is a child of a virtual
     root node.  By virtual, I mean each `CGI::Explorer' object creates
     its own root node, so that you do not have to.

     If you do have your own root node, with id 1 (say), then your root
     node's parent will still be 0, and your next-level nodes will all
     have a parent id of 1.

   See ce.pl for an example.

name()
======

   Returns the name of the 'current' node.

parent_id()
===========

   Returns the id of the parent of the 'current' node.

set()
=====

   Returns nothing.

   Used to set a new value for any option, after a call to new().

   set() takes the same parameters as new().

state($q)
=========

   Returns the open/closed state of all nodes.

   Tells the object to update its internal representation of the data by
recovering CGI form field data from the given CGI object.

   Warning: You must use the return value as a field, presumably hidden,
in a form, in your script so that the value can do a round trip out to the
browser and back.  This way the value can be recovered by the next
invocation of your script.

   This is the mechanism `CGI::Explorer' uses to maintain the open/closed
state of each node. State maintenance is a quite a complex issue. For
details, see:

     Writing Apache Modules with Perl and C
     Lincoln Stein and Doug MacEachern
     O'Reilly
     1-56592-567-X
     Chapter 5 'Maintaining State'

   You can see the problem: When you close and then re-open a node, you
expect all child nodes to be restored to the open/close state they were in
before the node was closed.

   With a program like Windows Explorer, this is simple, since the program
remains in RAM, running, all the time nodes are being clicked. Thus it can
maintain the state of each node in its own (process) memory.

   With a CGI script, 2 separate invocations of the script must maintain
state outside their own memory. I have chosen to use (hidden) form fields
in `CGI::Explorer'.

   See ce.pl for an example.

   The form fields have these names:

   * explorer_id_(\d+) - The id of the node clicked on

     There is 1 such form field per node.

     The click on this node is what submitted the form. (\d+) is a unique
     integer 1 .. N.

     Your CGI script does not need to output these form fields.
     as_HTML($q) does this for you.

   * explorer_state - The open/closed state of all nodes. Its value is a
     string

     Your CGI script must output this value. See above.

Required Modules
================

   * Tree::Nary. Not shipped with Perl. Get it from a CPAN near you

AUTHOR
======

   `CGI::Explorer' was written by Ron Savage *<ron@savage.net.au>* in 2001.

   Home page: http://savage.net.au/index.html

COPYRIGHT
=========

   Copyright &copy; 2001, Ron Savage. All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

A bundle to install everything required for FormMagick
******************************************************

NAME
====

   Bundle::FormMagick - A bundle to install everything required for
FormMagick

SYNOPSIS
========

   `perl -MCPAN -e 'install Bundle::FormMagick''

CONTENTS
========

   Persistence::Object::Simple 0.47

   XML::Parser 2.30

   Text::Template 1.23

   CGI::Persistent

   Class::ParamParser

   Locale::Maketext 0.18

   Locale::Country 1.02

   Geography::States 1.3

   Time::ParseDate 00.01_03_01

   CGI::Persistent 0.21

   Business::CreditCard 0.21

DESCRIPTION
===========

   This bundle installs all the modules needed to run FormMagick, as well
as a bunch of modules required for the validation functions.

AUTHOR
======

   Kirrily "Skud" Robert (skud@infotrope.net)

CGI Interface for Fast CGI
**************************

NAME
====

   CGI::Fast - CGI Interface for Fast CGI

SYNOPSIS
========

     use CGI::Fast qw(:standard);
     $COUNTER = 0;
     while (new CGI::Fast) {
     	print header;
     	print start_html("Fast CGI Rocks");
     	print
     	    h1("Fast CGI Rocks"),
     	    "Invocation number ",b($COUNTER++),
             " PID ",b($$),".",
     	    hr;
         print end_html;
     }

DESCRIPTION
===========

   CGI::Fast is a subclass of the CGI object created by CGI.pm.  It is
specialized to work well with the Open Market FastCGI standard, which
greatly speeds up CGI scripts by turning them into persistently running
server processes.  Scripts that perform time-consuming initialization
processes, such as loading large modules or opening persistent database
connections, will see large performance improvements.

OTHER PIECES OF THE PUZZLE
==========================

   In order to use CGI::Fast you'll need a FastCGI-enabled Web server.
Open Market's server is FastCGI-savvy.  There are also freely
redistributable FastCGI modules for NCSA httpd 1.5 and Apache.
FastCGI-enabling modules for Microsoft Internet Information Server and
Netscape Communications Server have been announced.

   In addition, you'll need a version of the Perl interpreter that has
been linked with the FastCGI I/O library.  Precompiled binaries are
available for several platforms, including DEC Alpha, HP-UX and
SPARC/Solaris, or you can rebuild Perl from source with patches provided
in the FastCGI developer's kit.  The FastCGI Perl interpreter can be used
in place of your normal Perl without ill consequences.

   You can find FastCGI modules for Apache and NCSA httpd, precompiled
Perl interpreters, and the FastCGI developer's kit all at URL:

     http://www.fastcgi.com/

WRITING FASTCGI PERL SCRIPTS
============================

   FastCGI scripts are persistent: one or more copies of the script are
started up when the server initializes, and stay around until the server
exits or they die a natural death.  After performing whatever one-time
initialization it needs, the script enters a loop waiting for incoming
connections, processing the request, and waiting some more.

   A typical FastCGI script will look like this:

     #!/usr/local/bin/perl    # must be a FastCGI version of perl!
     use CGI::Fast;
     &do_some_initialization();
     while ($q = new CGI::Fast) {
     	&process_request($q);
     }

   Each time there's a new request, CGI::Fast returns a CGI object to your
loop.  The rest of the time your script waits in the call to new().  When
the server requests that your script be terminated, new() will return
undef.  You can of course exit earlier if you choose.  A new version of the
script will be respawned to take its place (this may be necessary in order
to avoid Perl memory leaks in long-running scripts).

   CGI.pm's default CGI object mode also works.  Just modify the loop this
way:

     while (new CGI::Fast) {
     	&process_request;
     }

   Calls to header(), start_form(), etc. will all operate on the current
request.

INSTALLING FASTCGI SCRIPTS
==========================

   See the FastCGI developer's kit documentation for full details.  On the
Apache server, the following line must be added to srm.conf:

     AddType application/x-httpd-fcgi .fcgi

   FastCGI scripts must end in the extension .fcgi.  For each script you
install, you must add something like the following to srm.conf:

     AppClass /usr/etc/httpd/fcgi-bin/file_upload.fcgi -processes 2

   This instructs Apache to launch two copies of file_upload.fcgi at
startup time.

USING FASTCGI SCRIPTS AS CGI SCRIPTS
====================================

   Any script that works correctly as a FastCGI script will also work
correctly when installed as a vanilla CGI script.  However it will not see
any performance benefit.

CAVEATS
=======

   I haven't tested this very much.

AUTHOR INFORMATION
==================

   Copyright 1996-1998, Lincoln D. Stein.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Address bug reports and comments to: lstein@cshl.org

BUGS
====

   This section intentionally left blank.

SEE ALSO
========

   See CGI/Carp, CGI,

Perl extension for managing templates, and performing variable interpolation.
*****************************************************************************

NAME
====

   CGI::FastTemplate - Perl extension for managing templates, and
performing variable interpolation.

SYNOPSIS
========

     use CGI::FastTemplate;

     $tpl = new CGI::FastTemplate();
     $tpl = new CGI::FastTemplate("/path/to/templates");

     CGI::FastTemplate->set_root("/path/to/templates");    ## all instances will use this path
     $tpl->set_root("/path/to/templates");                 ## this instance will use this path

     $tpl->define( main    => "main.tpl",
                   row     => "table_row.tpl",
                   all     => "table_all.tpl",
                   );

     $tpl->assign(TITLE => "I am the title.");

     my %defaults = (  FONT   => "<font size=+2 face=helvetica>",
                       EMAIL   => 'jmoore@sober.com',
                       );
     $tpl->assign(\%defaults);

     $tpl->parse(ROWS      => ".row");      ## the '.' appends to ROWS
     $tpl->parse(CONTENT   => ["row", "all"]);
     $tpl->parse(CONTENT   => "main");

     $tpl->print();            ## defaults to last parsed
     $tpl->print("CONTENT");   ## same as print() as "CONTENT" was last parsed

     $ref = $tpl->fetch("CONTENT");

DESCRIPTION
===========

What is a template?
-------------------

   A template is a text file with variables in it.  When a template is
parsed, the variables are interpolated to text.  (The text can be a few
bytes or a few hundred kilobytes.)  Here is a simple template with one
variable ('$NAME'):

     Hello $NAME.  How are you?

When are templates useful?
--------------------------

   Templates are very useful for CGI programming, because adding HTML to
your perl code clutters your code and forces you to do any HTML
modifications.  By putting all of your HTML in separate template files,
you can let a graphic or interface designer change the look of your
application without having to bug you, or let them muck around in your
perl code.

There are other templating modules on CPAN, what makes FastTemplate  different?
-------------------------------------------------------------------------------

   CGI::FastTemplate has the following attributes:

   Speed

   FastTemplate doesn't use eval, and parses with a single regular
expression.  It just does simple variable interpolation (i.e. there is no
logic that you can add to templates - you keep the logic in the code).
That's why it's has 'Fast' in it's name!

   Efficiency

   FastTemplate functions accept and return references whenever possible,
which saves needless copying of arguments (hashes, scalars, etc).

   *Flexibility*

   The API is robust and flexible, and allows you to build very complex
HTML documents or HTML interfaces.  It is 100% perl and works on Unix or
NT.  Also, it isn't restricted to building HTML documents - it could be
used to build any ascii based document (e.g. postscript, XML, email).

   The similar modules on CPAN are:

     Module          HTML::Template  (S/SA/SAMTREGAR/HTML-Template-0.04.tar.gz)
     Module          Taco::Template  (KWILLIAMS/Taco-0.04.tar.gz)
     Module          Text::BasicTemplate (D/DC/DCARRAWAY/Text-BasicTemplate-0.9.8.tar.gz)
     Module          Text::Template  (MJD/Text-Template-1.20.tar.gz)
     Module          HTML::Mason     (J/JS/JSWARTZ/HTML-Mason-0.5.1.tar.gz)

What are the steps to use FastTemplate?
---------------------------------------

   The main steps are:

     1. define
     2. assign
     3. parse
     4. print

   These are outlined in detail in CORE METHODS below.

CORE METHODS
============

define(HASH)
------------

   The method define() maps a template filename to a (usually shorter)
name. e.g.

     my $tpl = new FastTemplate();
     $tpl->define(   main   => "main.tpl",
                     footer   => "footer.tpl",
                     );

   This new name is the name that you will use to refer to the templates.
Filenames should not appear in any place other than a define().

   (Note: This is a required step!  This may seem like an annoying extra
step when you are dealing with a trivial example like the one above, but
when you are dealing with dozens of templates, it is very handy to refer
to templates with names that are indepandant of filenames.)

   TIP: Since define() does not actually load the templates, it is faster
and more legible to define all the templates with one call to define().

define_nofile(HASH)   alias: define_raw(HASH)
---------------------------------------------

   Sometimes it is desireable to not have to create a separate template
file for each template (though in the long run it is usually better to do
so).  The method define_nofile() allows you to do this.  For example, if
you were writing a news tool where you wanted to bold an item if it was
"new" you could do something like the following:

     my $tpl = new FastTemplate();

     $tpl->define_nofile(    new   => '<b>$ITEM_NAME</b> <BR>',
                             old   => '$ITEM_NAME <BR>');

     if ($new)
     {
         $tpl->parse($ITEM   => "new");
     }
     else
     {
         $tpl->parse($ITEM   => "old");
     }

   Of course, now you, the programmer has to update how new items are
displayed, whereas if it was in a template, you could offload that task to
someone else.

define_nofile(HASH REF)   alias: define_raw(HASH REF)
-----------------------------------------------------

   A more efficient way of passing your arguments than using a real hash.
Just pass in a hash reference instead of a real hash.

assign(HASH)
------------

   The method assign() assigns values for variables.  In order for a
variable in a template to be interpolated it must be assigned.  There are
two forms which have some important differences.  The simple form, is to
accept a hash and copy all the key/value pairs into a hash in FastTemplate.
There is only one hash in FastTemplate, so assigning a value for the same
key will overwrite that key.

     e.g.

     $tpl->assign(TITLE   => "king kong");
     $tpl->assign(TITLE   => "godzilla");    ## overwrites "king kong"

assign(HASH REF)
----------------

   A much more efficient way to pass in values is to pass in a hash
reference.  (This is particularly nice if you get back a hash or hash
reference from a database query.)  Passing a hash reference doesn't copy
the data, but simply keeps the reference in an array.  During parsing if
the value for a variable cannot be found in the main FastTemplate hash, it
starts to look through the array of hash references for the value.  As
soon as it finds the value it stops.  It is important to remember to
remove hash references when they are no longer needed.

     e.g.

     my %foo = ("TITLE" => "king kong");
     my %bar = ("TITLE" => "godzilla");

     $tpl->assign(\%foo);   ## TITLE resolves to "king kong"
     $tpl->clear_href(1);   ## remove last hash ref assignment (\%foo)
     $tpl->assign(\%bar);   ## TITLE resolves to "godzilla"

     $tpl->clear_href();    ## remove all hash ref assignments

     $tpl->assign(\%foo);   ## TITLE resolves to "king kong"
     $tpl->assign(\%bar);   ## TITLE _still_ resolves to "king kong"

parse(HASH)
-----------

   The parse function is the main function in FastTemplate.  It accepts a
hash, where the keys are the TARGET and the values are the SOURCE
templates.  There are three forms the hash can be in:

     $tpl->parse(MAIN => "main");                ## regular

     $tpl->parse(MAIN => ["table", "main"]);     ## compound

     $tpl->parse(MAIN => ".row");                ## append

   In the regular version, the template named "main" is loaded if it hasn't
been already, all the variables are interpolated, and the result is then
stored in FastTemplate as the value MAIN.  If the variable '$MAIN' shows
up in a later template, it will be interpolated to be the value of the
parsed "main" template.  This allows you to easily nest templates, which
brings us to the compound style.

   The compound style is designed to make it easier to nest templates.
The following are equivalent:

     $tpl->parse(MAIN => "table");
     $tpl->parse(MAIN => "main");

     ## is the same as:

     $tpl->parse(MAIN => ["table", "main"]);     ## this form saves function calls
                                                 ## (and makes your code cleaner)

   It is important to note that when you are using the compound form, each
template after the first, must contain the variable that you are parsing
the results into.  In the above example, 'main' must contain the variable
'$MAIN', as that is where the parsed results of 'table' is stored.  If
'main' does not contain the variable '$MAIN' then the parsed results of
'table' will be lost.

   The append style is a bit of a kludge, but it allows you to append the
parsed results to the target variable.  This is most useful when building
tables that have an dynamic number of rows - such as data from a database
query.

strict()
--------

   When strict() is on (it is on by default) all variables found during
template parsing that are unresolved have a warning printed to STDERR.
e.g.

     [CGI::FastTemplate] Warning: no value found for variable: SOME_VARIABLE

   Also, new as of version 1.04 the variables will be left in the output
document.  This was done for two reasons: to allow for parsing to be done
in stages (i.e. multiple passes), and to make it easier to identify
undefined variables since they appear in the parsed output.  If you have
been using an earlier version of FastTemplate and you want the old
behavior of replacing unknown variables with an empty string, see:
no_strict().

   Note: version 1.07 adds support for two styles of variables, so that the
following are equivalent: $VAR and ${VAR} However, when using strict(),
variables with curly brackets that are not resolved are outputted as plain
variables.  e.g. if ${VAR} has no value assigned to it, it would appear in
the output as $VAR.  This is a slight inconsistency - ideally the
unresolved variable would remain unchanged.

   Note: STDERR output should be captured and logged by the webserver so
you can just tail the error log to see the output.

     e.g.

     tail -f /etc/httpd/logs/error_log

no_strict()
-----------

   Turns off warning messages about unresolved template variables.  As of
version 1.04 a call to no_strict() is required to replace unknown
variables with an empty string.  By default, all instances of FastTemplate
behave as is strict() was called.  Also, no_strict() must be set for each
instance of CGI::FastTemplate. e.g.

     CGI::FastTemplate::no_strict;        ## no

     my $tpl = CGI::FastTemplate;
     $tpl->no_strict;                     ## yes

print(SCALAR)
-------------

   The method print() prints the contents of the named variable.  If no
variable is given, then it prints the last variable that was used in a
call to parse which I find is a reasonable default.

     e.g.

     $tpl->parse(MAIN => "main");
     $tpl->print();         ## prints value of MAIN
     $tpl->print("MAIN");   ## same

   This method is provided for convenience.

   If you need to print other than STDOUT (e.g. socket, file handle) see
fetch().

OTHER METHODS
=============

fetch(SCALAR)
-------------

   Returns a scalar reference to parsed data.

     $tpl->parse(CONTENT   => "main");
     my $content = $tpl->fetch("CONTENT");

     print $$content;        ## print to STDOUT
     print FILE $$content;   ## print to filehandle or pipe

clear()
-------

   Note: All of 'clear' functions are for use under mod_perl (or anywhere
where your scripts are persistant).  They generally aren't needed if you
are writing CGI scripts.

   Clears the internal hash that stores data passed from calls to assign()
and parse().

   Often clear() is at the end of a mod_perl script:

     $tpl->print();
     $tpl->clear();

clear(ARRAY)
------------

   With no arguments, all assigned or parsed variables are cleared, but if
passed an ARRAY of variable names, then only those variables will be
cleared.

     e.g.

     $tpl->assign(TITLE => "Welcome");
     $tpl->clear("TITLE");                 ## title is now empty

   Another way of achieving the same effect of clearnign variables is to
just assign an empty string.

     e.g.

     $tpl->assign(TITLE => '');           ## same as: $tpl->clear("TITLE");

clear_parse()
-------------

   See: clear()

clear_href(NUMBER)
------------------

   Removes a given number of hash references from the list of hash refs
that is built using:

     $tpl->assign(HASH REF);

   If called with no arguments, it removes all hash references from the
array.  This is often used for database queries where each row from the
query is a hash or hash reference.

   e.g.

   while($hash_row = $sth->fetchrow_hashref)     {
$tpl->assign($hash_row);         $tpl->parse(ROW => ".row");
$tpl->clear_href(1);     }

clear_define()
--------------

   Clears the internal hash that stores data passed to:

     $tpl->define();

   Note: The hash that holds the loaded templates is not touched with this
method.  See: clear_tpl

clear_tpl() clear_tpl(NAME)
---------------------------

   The first time a template is used, it is loaded and stored in a hash in
memory.  clear_tpl() removes all the templates being held in memory.
clear_tpl(NAME) only removes the one with NAME.  This is generally not
required for normal CGI programming, but if you have long running scripts
(e.g. mod_perl) and have very large templates that a re infrequently used
gives you some control over how memory is being used.

clear_all()
-----------

   Cleans the module of any data, except for the ROOT directory.
Equivalent to:

     $tpl->clear_define();
     $tpl->clear_href();
     $tpl->clear_tpl();
     $tpl->clear_parse();

Variables
---------

   A variable is defined as:

     $[A-Z0-9][A-Z0-9_]+

   This means, that a variable must begin with a dollar sign '$'.  The
second character must be an uppercase letter or digit 'A-Z0-9'.  Remaining
characters can include an underscore.

   As of version 1.07 variables can also be delimited by curly brackets.

     ${[A-Z0-9][A-Z0-9_]+}

   For example, the following are valid variables:

     $FOO
     $F123F
     $TOP_OF_PAGE
     ${NEW_STYLE}

Variable Interpolation (Template Parsing)
-----------------------------------------

   When the a template is being scanned for variables, pattern matching is
greedy. (For more info on "greediness" of regexps see Perlre (perl.info).)
This is important, because if there are valid
variable characters after your variable, FastTemplate will consider them
to be part of the variable.  As of version 1.07 you can use curly brackets
as delimiters for your variable names.  e.g. ${VARIABLE}  You do not need
to use curly brackets if the character immediately after your variable
name is not an uppercase letter, digit or underscore.  ['A-Z0-9_']

   If a variable cannot be resolved to a value then there are two
possibilities.  If strict() has been called (it is on by default) then the
variable remains and a warning is printed to STDERR.   If no_strict() has
been called then the variables is converted to an empty string ["].

   See `strict()' in this node and `no_strict()' in this node for more
info.

   Some examples will make this clearer.

     Assume:

     $FOO = "foo";
     $BAR = "bar";
     $ONE = "1";
     $TWO = "2";
     $UND = "_";

     Variable        Interpolated/Parsed
     ------------------------------------------------
     $FOO            foo
     $FOO-$BAR       foo-bar
     $ONE_$TWO       2             ## $ONE_ is undefined!
     $ONE_$TWO       $ONE_2        ## assume: strict()
     $ONE$UND$TWO    1_2           ## kludge!
     ${ONE}_$TWO     1_2           ## much better
     $$FOO           $foo
     $25,000         $25,000

FULL EXAMPLE
------------

   This example will build an HTML page that will consist of a table.  The
table will have 3 numbered rows.  The first step is to decide what
templates we need.  In order to make it easy for the table to change to a
different number of rows, we will have a template for the rows of the
table, another for the table, and a third for the head/body part of the
HTML page.

   Below are the templates. (Pretend each one is in a separate file.)

     <!-- NAME: main.tpl -->
     <html>
     <head><title>$TITLE</title>
     </head>
     <body>
     $MAIN
     </body>
     </html>
     <!-- END: main.tpl -->

     <!-- NAME: table.tpl -->
     <table>
     $ROWS
     </table>
     <!-- END: table.tpl -->

     <!-- NAME: row.tpl -->
     <tr>
     <td>$NUMBER</td>
     <td>$BIG_NUMBER</td>
     </tr>
     <!-- END: row.tpl -->

   Now we can start coding...

     ## START ##

     use CGI::FastTemplate;
     my $tpl = new CGI::FastTemplate("/path/to/template/files");

     $tpl->define(     main    => "main.tpl",
                       table   => "table.tpl",
                       row     => "row.tpl",
                       );

     $tpl->assign(TITLE => "FastTemplate Test");

     for $n (1..3)
     {
           $tpl->assign(   NUMBER      => $n,
           BIG_NUMBER   => $n*10);
           $tpl->parse(ROWS   => ".row");
     }

     $tpl->parse(MAIN => ["table", "main"]);
     $tpl->print();

     ## END ##

     When run it returns:

     <!-- NAME: main.tpl -->
     <html>
     <head><title>FastTemplate Test</title>
     </head>
     <body>
     <!-- NAME: table.tpl -->
     <table>
     <!-- NAME: row.tpl -->
     <tr>
     <td>1</td>
     <td>10</td>
     </tr>
     <!-- END: row.tpl -->
     <!-- NAME: row.tpl -->
     <tr>
     <td>2</td>
     <td>20</td>
     </tr>
     <!-- END: row.tpl -->
     <!-- NAME: row.tpl -->
     <tr>
     <td>3</td>
     <td>30</td>
     </tr>
     <!-- END: row.tpl -->

     </table>
     <!-- END: table.tpl -->

     </body>
     </html>
     <!-- END: main.tpl -->

   If you're thinking you could have done the same thing in a few lines of
plain perl, well yes you probably could.  But, how would a graphic
designer tweak the resulting HTML?  How would you have a designer editing
the HTML while you're editing another part of the code?  How would you
save the output to a file, or pipe it to another application (e.g.
sendmail)?  How would you make your application multi-lingual?  How would
you build an application that has options for high graphics, or text-only?
FastTemplate really starts to shine when you are building mid to large
scale web applications, simply because it begins to separate the
application's generic logic from the specific implementation.

COPYRIGHT
=========

     Copyright (c) 1998-99 Jason Moore <jmoore@sober.com>.  All rights
     reserved.

     This program is free software; you can redistribute it and/or
     modify it under the same terms as Perl itself.

     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
     Artistic License for more details.

AUTHOR
======

   Jason Moore <jmoore@sober.com>

SEE ALSO
========

   mod_perl(1).

Build Smart HTML Forms on Top of the CGI:: Modules
**************************************************

NAME
====

   CGI::Form - Build Smart HTML Forms on Top of the CGI:: Modules

ABSTRACT
========

   This perl library uses perl5 objects to make it easy to create Web
fill-out forms and parse their contents.  This package defines CGI
objects, entities that contain the values of the current query string and
other state variables.  Using a CGI object's methods, you can examine
keywords and parameters passed to your script, and create forms whose
initial values are taken from the current query (thereby preserving state
information).

INSTALLATION:
=============

   To use this package, install it in your perl library path (usually
/usr/local/lib/perl5/ and add the following to your perl CGI script:

     Use CGI::Form;

DESCRIPTION
===========

CREATING A NEW FORM OBJECT AND PROCESSING PARAMETERS:
-----------------------------------------------------

     $query = new CGI::Form;

   This will parse the input (from both POST and GET methods) and store it
into a perl5 object called $query.  This method is inherited from
CGI/Request.  See its manpage for details.  Similarly,
CGI::Form uses CGI::Request to get and set named query parameters, e.g.

     @values = $query->param('foo');

     -and-

     $query->param('foo','an','array','of','values');
     or whatever!

CALLING CGI::Form FUNCTIONS THAT TAKE MULTIPLE ARGUMENTS
--------------------------------------------------------

   In versions of Form.pm prior to 2.8, it could get difficult to remember
the proper order of arguments in CGI function calls that accepted five or
six different arguments.  As of 2.8, there's a better way to pass
arguments to the various CGI functions.  In this style, you pass a series
of name=>argument pairs, like this:

     $field = $query->radio_group(-name=>'OS',
                                  -values=>[Unix,Windows,Macintosh],
                                  -default=>'Unix');

   The advantages of this style are that you don't have to remember the
exact order of the arguments, and if you leave out a parameter, in most
cases it will default to some reasonable value.  If you provide a
parameter that the method doesn't recognize, it will usually do something
useful with it, such as incorporating it into the HTML form tag.  For
example if Netscape decides next week to add a new JUSTIFICATION parameter
to the text field tags, you can start using the feature without waiting
for a new version of CGI.pm:

     $field = $query->textfield(-name=>'State',
                                -default=>'gaseous',
                                -justification=>'RIGHT');

   This will result in an HTML tag that looks like this:

     <INPUT TYPE="textfield" NAME="State" VALUE="gaseous"
                    JUSTIFICATION="RIGHT">

   Parameter names are case insensitive: you can use -name, or -Name or
-NAME.  You don't have to use the hyphen if you don't want to.  After
creating a CGI object, call the *use_named_parameters()* method with a
nonzero value.  This will tell CGI.pm that you intend to use named
parameters exclusively:

     $query = new CGI;
     $query->use_named_parameters(1);
     $field = $query->radio_group('name'=>'OS',
                                  'values'=>['Unix','Windows','Macintosh'],
                                  'default'=>'Unix');

   Actually, CGI.pm only looks for a hyphen in the first parameter.  So
you can leave it off subsequent parameters if you like.  Something to be
wary of is the potential that a string constant like "values" will collide
with a keyword (and in fact it does!) While Perl usually figures out when
you're referring to a function and when you're referring to a string, you
probably should put quotation marks around all string constants just to
play it safe.

CREATING A SELF-REFERENCING URL THAT PRESERVES STATE INFORMATION:
-----------------------------------------------------------------

     $myself = $query->self_url
     print "<A HREF=$myself>I'm talking to myself.</A>

   self_url() will return a URL, that, when selected, will reinvoke this
script with all its state information intact.  This is most useful when
you want to jump around within the document using internal anchors but you
don't want to disrupt the current contents of the form(s).  Something like
this will do the trick.

     $myself = $query->self_url
     print "<A HREF=$myself#table1>See table 1</A>
     print "<A HREF=$myself#table2>See table 2</A>
     print "<A HREF=$myself#yourself>See for yourself</A>

   This method is actually defined in CGI/Base, but is
passed through here for compatability with CGI.pm

CREATING THE HTTP HEADER:
-------------------------

     print $query->header;

     -or-

     print $query->header('image/gif');

   header() returns the Content-type: header.  you can provide your own
MIME type if you choose, otherwise it defaults to text/html.

   This method is provided for compatability with CGI.pm *only*.  It is
much better to use the SendHeaders() method of CGI/Base.

   NOTE: This is a temporary method that will be replaced by the
CGI::Response module as soon as it is released.

GENERATING A REDIRECTION INSTRUCTION
------------------------------------

     print $query->redirect('http://somewhere.else/in/movie/land');

   redirect the browser elsewhere.  If you use redirection like this, you
should not print out a header as well.

   This method is provided for compatability with CGI.pm *only*.  New
scripts should use CGI::Base's redirect() method instead.

CREATING THE HTML HEADER:
-------------------------

     print $query->start_html(-title=>'Secrets of the Pyramids',
                              -author=>'fred@capricorn.org',
                              -base=>'true',
                              -BGCOLOR=>"#00A0A0"');

     -or-

     print $query->start_html('Secrets of the Pyramids',
                              'fred@capricorn.org','true',
                              'BGCOLOR="#00A0A0"');

   This will return a canned HTML header and the opening <BODY> tag.  All
parameters are optional.   In the named parameter form, recognized
parameters are -title, -author and -base (see below for the explanation).
Any additional parameters you provide, such as the Netscape unofficial
BGCOLOR attribute, are added to the <BODY> tag.

   Positional parameters are as follows:

Parameters:

     The title

     The author's e-mail address (will create a <LINK REV="MADE"> tag if
     present

     A 'true' flag if you want to include a <BASE> tag in the header.  This
     helps resolve relative addresses to absolute ones when the document
     is moved, but makes the document hierarchy non-portable.  Use with
     care!

5, 6...
     Any other parameters you want to include in the <BODY> tag.  This is
     a good place to put Netscape extensions, such as colors and wallpaper
     patterns.

ENDING THE HTML DOCUMENT:
-------------------------

     print $query->end_html

   This ends an HTML document by printing the </BODY></HTML> tags.

CREATING FORMS:
===============

   *General note*  The various form-creating methods all return strings to
the caller, containing the tag or tags that will create the requested form
element.  You are responsible for actually printing out these strings.
It's set up this way so that you can place formatting tags around the form
elements.

   *Another note* The default values that you specify for the forms are
only used the first time the script is invoked.  If there are already
values present in the query string, they are used, even if blank.  If you
want to change the value of a field from its previous value, call the
param() method to set it.

   *Yet another note* By default, the text and labels of form elements are
escaped according to HTML rules.  This means that you can safely use
"<CLICK ME>" as the label for a button.  However, it also interferes with
your ability to incorporate special HTML character sequences, such as
&Aacute;, into your fields.  If you wish to turn off automatic escaping,
call the autoEscape() method with a false value immediately after creating
the CGI object:

     $query = new CGI::Form;
     $query->autoEscape(undef);

CREATING AN ISINDEX TAG
-----------------------

     print $query->isindex($action);

   Prints out an <ISINDEX> tag.  Not very exciting.  The optional
parameter specifies an ACTION="<URL>" attribute.

STARTING AND ENDING A FORM
--------------------------

     print $query->startform($method,$action,$encoding);
       <... various form stuff ...>
     print $query->endform;

   startform() will return a <FORM> tag with the optional method, action
and form encoding that you specify.  The defaults are:

   method: POST     action: this script     encoding:
application/x-www-form-urlencoded

   The encoding method tells the browser how to package the various fields
of the form before sending the form to the server.  Two values are
possible:

*application/x-www-form-urlencoded*
     This is the older type of encoding used by all browsers prior to
     Netscape 2.0.  It is compatible with many CGI scripts and is suitable
     for short fields containing text data.

*multipart/form-data*
     This is the newer type of encoding introduced by Netscape 2.0.  It is
     suitable for forms that contain very large fields or that are
     intended for transferring binary data.  Most importantly, it enables
     the "file upload" feature of Netscape 2.0 forms.

     Forms that use this type of encoding are not easily interpreted by
     CGI scripts unless they use CGI.pm or another library designed to
     handle them.

   For your convenience, Form.pm defines two subroutines that contain the
values of the two alternative encodings:

     use CGI::Form(URL_ENCODED,MULTIPART);

   For compatability, the startform() method uses the older form of
encoding by default.  If you want to use the newer form of encoding by
default, you can call *start_multipart_form()* instead of *startform()*.

   endform() returns a </FORM> tag.

CREATING A TEXT FIELD
---------------------

     print $query->textfield(-name=>'field_name',
     	                    -default=>'starting value',
     	                    -size=>50,
     	                    -maxlength=>80);
     	-or-

     print $query->textfield('field_name','starting value',50,80);

   textfield() will return a text input field.

Parameters

     The first parameter is the required name for the field (-name).

     The optional second parameter is the default starting value for the
     field contents (-default).

     The optional third parameter is the size of the field in
     characters (-size).

     The optional fourth parameter is the maximum number of characters the
          field will accept (-maxlength).

   As with all these methods, the field will be initialized with its
previous contents from earlier invocations of the script.  When the form
is processed, the value of the text field can be retrieved with:

     $value = $query->param('foo');

   If you want to reset it from its initial value after the script has been
called once, you can do so like this:

     $query->param('foo',"I'm taking over this value!");

CREATING A BIG TEXT FIELD
-------------------------

     print $query->textarea(-name=>'foo',
     	 		  -default=>'starting value',
     	                  -rows=>10,
     	                  -columns=>50);

     -or

     print $query->textarea('foo','starting value',10,50);

   textarea() is just like textfield, but it allows you to specify rows
and columns for a multiline text entry box.  You can provide a starting
value for the field, which can be long and contain multiple lines.

CREATING A PASSWORD FIELD
-------------------------

     print $query->password_field(-name=>'secret',
     				-value=>'starting value',
     				-size=>50,
     				-maxlength=>80);
     	-or-

     print $query->password_field('secret','starting value',50,80);

   password_field() is identical to textfield(), except that its contents
will be starred out on the web page.

CREATING A FILE UPLOAD FIELD
----------------------------

     print $query->filefield(-name=>'uploaded_file',
     	                    -default=>'starting value',
     	                    -size=>50,
     	 		    -maxlength=>80);
     	-or-

     print $query->filefield('uploaded_file','starting value',50,80);

   filefield() will return a file upload field for Netscape 2.0 browsers.
In order to take full advantage of this *you must use the new multipart
encoding scheme* for the form.  You can do this either by calling
*startform()* with an encoding type of *$CGI::MULTIPART*, or by calling
the new method *start_multipart_form()* instead of vanilla *startform()*.

Parameters

     The first parameter is the required name for the field (-name).

     The optional second parameter is the starting value for the field
     contents to be used as the default file name (-default).

     The beta2 version of Netscape 2.0 currently doesn't pay any attention
     to this field, and so the starting value will always be blank.  Worse,
     the field loses its "sticky" behavior and forgets its previous
     contents.  The starting value field is called for in the HTML
     specification, however, and possibly later versions of Netscape will
     honor it.

     The optional third parameter is the size of the field in characters
     (-size).

     The optional fourth parameter is the maximum number of characters the
     field will accept (-maxlength).

   When the form is processed, you can retrieve the entered filename by
calling param().

     $filename = $query->param('uploaded_file');

   In Netscape Beta 1, the filename that gets returned is the full local
filename on the *remote user's* machine.  If the remote user is on a Unix
machine, the filename will follow Unix conventions:

     /path/to/the/file

   On an MS-DOS/Windows machine, the filename will follow DOS conventions:

     C:\PATH\TO\THE\FILE.MSW

   On a Macintosh machine, the filename will follow Mac conventions:

     HD 40:Desktop Folder:Sort Through:Reminders

   In Netscape Beta 2, only the last part of the file path (the filename
itself) is returned.  I don't know what the release behavior will be.

   The filename returned is also a file handle.  You can read the contents
of the file using standard Perl file reading calls:

     # Read a text file and print it out
     while (<$filename>) {
        print;
             }

     # Copy a binary file to somewhere safe
     open (OUTFILE,">>/usr/local/web/users/feedback");
     	while ($bytesread=read($filename,$buffer,1024)) {
     	   print OUTFILE $buffer;
     }

CREATING A POPUP MENU
---------------------

     print $query->popup_menu('menu_name',
                              ['eenie','meenie','minie'],
                              'meenie');

     -or-

     %labels = ('eenie'=>'your first choice',
                'meenie'=>'your second choice',
                'minie'=>'your third choice');
     print $query->popup_menu('menu_name',
                              ['eenie','meenie','minie'],
                              'meenie',\%labels);

     -or (named parameter style)-

     print $query->popup_menu(-name=>'menu_name',
     			    -values=>['eenie','meenie','minie'],
     	                    -default=>'meenie',
     	                    -labels=>\%labels);

   popup_menu() creates a menu.

  1. The required first argument is the menu's name (-name).

  2. The required second argument (-values) is an array reference
     containing the list of menu items in the menu.  You can pass the
     method an anonymous array, as shown in the example, or a reference to
     a named array, such as "\@foo".

  3. The optional third parameter (-default) is the name of the default
     menu choice.  If not specified, the first item will be the default.
     The values of the previous choice will be maintained across queries.

  4. The optional fourth parameter (-labels) is provided for people who
     want to use different values for the user-visible label inside the
     popup menu nd the value returned to your script.  It's a pointer to an
     associative array relating menu values to user-visible labels.  If you
     leave this parameter blank, the menu values will be displayed by
     default.  (You can also leave a label undefined if you want to).

        When the form is processed, the selected value of the popup menu
can be retrieved using:

     $popup_menu_value = $query->param('menu_name');

CREATING A SCROLLING LIST
-------------------------

     print $query->scrolling_list('list_name',
                                  ['eenie','meenie','minie','moe'],
                                  ['eenie','moe'],5,'true');
        -or-

     print $query->scrolling_list('list_name',
                                  ['eenie','meenie','minie','moe'],
                                  ['eenie','moe'],5,'true',
                                  \%labels);

     -or-

     print $query->scrolling_list(-name=>'list_name',
                                  -values=>['eenie','meenie','minie','moe'],
                                  -default=>['eenie','moe'],
     	                        -size=>5,
     	                        -multiple=>'true',
                                  -labels=>\%labels);

   scrolling_list() creates a scrolling list.

Parameters:

     The first and second arguments are the list name (-name) and values
     (-values).  As in the popup menu, the second argument should be an
     array reference.

     The optional third argument (-default) can be either a reference to a
     list containing the values to be selected by default, or can be a
     single value to select.  If this argument is missing or undefined,
     then nothing is selected when the list first appears.  In the named
     parameter version, you can use the synonym "-defaults" for this
     parameter.

     The optional fourth argument is the size of the list (-size).

     The optional fifth argument can be set to true to allow multiple
     simultaneous selections (-multiple).  Otherwise only one selection
     will be allowed at a time.

     The optional sixth argument is a pointer to an associative array
     containing long user-visible labels for the list items (-labels).  If
     not provided, the values will be displayed.

     When this form is procesed, all selected list items will be returned
     as a list under the parameter name 'list_name'.  The values of the
     selected items can be retrieved with:

          @selected = $query->param('list_name');

CREATING A GROUP OF RELATED CHECKBOXES
--------------------------------------

     print $query->checkbox_group(-name=>'group_name',
                                  -values=>['eenie','meenie','minie','moe'],
                                  -default=>['eenie','moe'],
     	                        -linebreak=>'true',
     	                        -labels=>\%labels);

     print $query->checkbox_group('group_name',
                                  ['eenie','meenie','minie','moe'],
                                  ['eenie','moe'],'true',\%labels);

     HTML3-COMPATIBLE BROWSERS ONLY:

     print $query->checkbox_group(-name=>'group_name',
                                  -values=>['eenie','meenie','minie','moe'],
     	                        -rows=2,-columns=>2);

   checkbox_group() creates a list of checkboxes that are related by the
same name.

Parameters:

     The first and second arguments are the checkbox name and values,
     respectively (-name and -values).  As in the popup menu, the second
     argument should be an array reference.  These values are used for the
     user-readable labels printed next to the checkboxes as well as for the
     values passed to your script in the query string.

     The optional third argument (-default) can be either a reference to a
     list containing the values to be checked by default, or can be a
     single value to checked.  If this argument is missing or undefined,
     then nothing is selected when the list first appears.

     The optional fourth argument (-linebreak) can be set to true to place
     line breaks between the checkboxes so that they appear as a vertical
     list.  Otherwise, they will be strung together on a horizontal line.

     The optional fifth argument is a pointer to an associative array
     relating the checkbox values to the user-visible labels that will will
     be printed next to them (-labels).  If not provided, the values will
     be used as the default.

     *HTML3-compatible browsers* (such as Netscape) can take advantage of
     the optional parameters *-rows*, and *-columns*.  These parameters
     cause checkbox_group() to return an HTML3 compatible table containing
     the checkbox group formatted with the specified number of rows and
     columns.  You can provide just the -columns parameter if you wish;
     checkbox_group will calculate the correct number of rows for you.

     To include row and column headings in the returned table, you can use
     the *-rowheader* and *-colheader* parameters.  Both of these accept a
     pointer to an array of headings to use.  The headings are just
     decorative.  They don't reorganize the interpetation of the
     checkboxes - they're still a single named unit.

   When the form is processed, all checked boxes will be returned as a
list under the parameter name 'group_name'.  The values of the "on"
checkboxes can be retrieved with:

     @turned_on = $query->param('group_name');

CREATING A STANDALONE CHECKBOX
------------------------------

     print $query->checkbox(-name=>'checkbox_name',
     			   -checked=>'checked',
     		           -value=>'ON',
     		           -label=>'CLICK ME');

     -or-

     print $query->checkbox('checkbox_name','checked','ON','CLICK ME');

   checkbox() is used to create an isolated checkbox that isn't logically
related to any others.

Parameters:

     The first parameter is the required name for the checkbox (-name).  It
     will also be used for the user-readable label printed next to the
     checkbox.

     The optional second parameter (-checked) specifies that the checkbox
     is turned on by default.  Synonyms are -selected and -on.

     The optional third parameter (-value) specifies the value of the
     checkbox when it is checked.  If not provided, the word "on" is
     assumed.

     The optional fourth parameter (-label) is the user-readable label to
     be attached to the checkbox.  If not provided, the checkbox name is
     used.

   The value of the checkbox can be retrieved using:

     $turned_on = $query->param('checkbox_name');

CREATING A RADIO BUTTON GROUP
-----------------------------

     print $query->radio_group(-name=>'group_name',
     			     -values=>['eenie','meenie','minie'],
                               -default=>'meenie',
     			     -linebreak=>'true',
     			     -labels=>\%labels);

     -or-

     print $query->radio_group('group_name',['eenie','meenie','minie'],
                                            'meenie','true',\%labels);

     HTML3-COMPATIBLE BROWSERS ONLY:

     print $query->checkbox_group(-name=>'group_name',
                                  -values=>['eenie','meenie','minie','moe'],
     	                        -rows=2,-columns=>2);

   radio_group() creates a set of logically-related radio buttons (turning
one member of the group on turns the others off)

Parameters:

     The first argument is the name of the group and is required (-name).

     The second argument (-values) is the list of values for the radio
     buttons.  The values and the labels that appear on the page are
     identical.  Pass an array reference in the second argument, either
     using an anonymous array, as shown, or by referencing a named array as
     in "\@foo".

     The optional third parameter (-default) is the name of the default
     button to turn on. If not specified, the first item will be the
     default.  You can provide a nonexistent button name, such as "-" to
     start up with no buttons selected.

     The optional fourth parameter (-linebreak) can be set to 'true' to put
     line breaks between the buttons, creating a vertical list.

     The optional fifth parameter (-labels) is a pointer to an associative
     array relating the radio button values to user-visible labels to be
     used in the display.  If not provided, the values themselves are
     displayed.

     *HTML3-compatible browsers* (such as Netscape) can take advantage of
     the optional parameters *-rows*, and *-columns*.  These parameters
     cause radio_group() to return an HTML3 compatible table containing
     the radio group formatted with the specified number of rows and
     columns.  You can provide just the -columns parameter if you wish;
     radio_group will calculate the correct number of rows for you.

     To include row and column headings in the returned table, you can use
     the *-rowheader* and *-colheader* parameters.  Both of these accept a
     pointer to an array of headings to use.  The headings are just
     decorative.  They don't reorganize the interpetation of the radio
     buttons - they're still a single named unit.

   When the form is processed, the selected radio button can be retrieved
using:

     $which_radio_button = $query->param('group_name');

CREATING A SUBMIT BUTTON
------------------------

     print $query->submit(-name=>'button_name',
     		        -value=>'value');

     -or-

     print $query->submit('button_name','value');

   submit() will create the query submission button.  Every form should
have one of these.

Parameters:

     The first argument (-name) is optional.  You can give the button a
     name if you have several submission buttons in your form and you want
     to distinguish between them.  The name will also be used as the
     user-visible label.  Be aware that a few older browsers don't deal
     with this correctly and never send back a value from a button.

     The second argument (-value) is also optional.  This gives the button
     a value that will be passed to your script in the query string.

   You can figure out which button was pressed by using different values
for each one:

     $which_one = $query->param('button_name');

CREATING A RESET BUTTON
-----------------------

     print $query->reset

   reset() creates the "reset" button.  Note that it restores the form to
its value from the last time the script was called, NOT necessarily to the
defaults.

CREATING A DEFAULT BUTTON
-------------------------

     print $query->defaults('button_label')

   defaults() creates a button that, when invoked, will cause the form to
be completely reset to its defaults, wiping out all the changes the user
ever made.

CREATING A HIDDEN FIELD
-----------------------

     print $query->hidden(-name=>'hidden_name',
                          -default=>['value1','value2'...]);

     -or-

     print $query->hidden('hidden_name','value1','value2'...);

   hidden() produces a text field that can't be seen by the user.  It is
useful for passing state variable information from one invocation of the
script to the next.

Parameters:

     The first argument is required and specifies the name of this field
     (-name).

     The second argument is also required and specifies its value
     (-default).  In the named parameter style of calling, you can provide
     a single value here or a reference to a whole list

   Fetch the value of a hidden field this way:

     $hidden_value = $query->param('hidden_name');

   Note, that just like all the other form elements, the value of a hidden
field is "sticky".  If you want to replace a hidden field with some other
values after the script has been called once you'll have to do it manually:

     $query->param('hidden_name','new','values','here');

CREATING A CLICKABLE IMAGE BUTTON
---------------------------------

     print $query->image_button(-name=>'button_name',
     			        -src=>'/source/URL',
     			        -align=>'MIDDLE');

     -or-

     print $query->image_button('button_name','/source/URL','MIDDLE');

   image_button() produces a clickable image.  When it's clicked on the
position of the click is returned to your script as "button_name.x" and
"button_name.y", where "button_name" is the name you've assigned to it.

Parameters:

     The first argument (-name) is required and specifies the name of this
     field.

     The second argument (-src) is also required and specifies the URL

The third option (-align, optional) is an alignment type, and may be TOP, BOTTOM or MIDDLE
   Fetch the value of the button this way:      $x =
$query->param('button_name.x');      $y = $query->param('button_name.y');

DEBUGGING:
==========

   If you are running the script from the command line or in the perl
debugger, you can pass the script a list of keywords or parameter=value
pairs on the command line or from standard input (you don't have to worry
about tricking your script into reading from environment variables).  You
can pass keywords like this:

     your_script.pl keyword1 keyword2 keyword3

   or this:

     your_script.pl keyword1+keyword2+keyword3

   or this:

     your_script.pl name1=value1 name2=value2

   or this:

     your_script.pl name1=value1&name2=value2

   or even as newline-delimited parameters on standard input.

   When debugging, you can use quotes and backslashes to escape characters
in the familiar shell manner, letting you place spaces and other funny
characters in your parameter=value pairs:

     your_script.pl name1='I am a long value' name2=two\ words

DUMPING OUT ALL THE NAME/VALUE PAIRS
------------------------------------

   The dump() method produces a string consisting of all the query's
name/value pairs formatted nicely as a nested list.  This is useful for
debugging purposes:

     print $query->dump

   Produces something that looks like:

     <UL>
     <LI>name1
         <UL>
         <LI>value1
         <LI>value2
         </UL>
     <LI>name2
         <UL>
         <LI>value1
         </UL>
     </UL>

   You can pass a value of 'true' to dump() in order to get it to print
the results out as plain text, suitable for incorporating into a <PRE>
section.

FETCHING ENVIRONMENT VARIABLES
==============================

   All the environment variables, such as REMOTE_HOST and HTTP_REFERER,
are available through the CGI::Base object.  You can get at these
variables using with the cgi() method (inherited from CGI::Request):

     $query->cgi->var('REMOTE_HOST');

AUTHOR INFORMATION
==================

   This code is copyright 1995 by Lincoln Stein and the Whitehead
Institute for Biomedical Research.  It may be used and modified freely.  I
request, but do not require, that this credit appear in the code.

   Address bug reports and comments to: lstein@genome.wi.mit.edu

A COMPLETE EXAMPLE OF A SIMPLE FORM-BASED SCRIPT
================================================

     #!/usr/local/bin/perl

             use CGI::Form;

             $query = new CGI::Form;

     print $query->header;
     print $query->start_html("Example CGI.pm Form");
     print "<H1> Example CGI.pm Form</H1>\n";
     &print_prompt($query);
     &do_work($query);
     	&print_tail;
     print $query->end_html;

     sub print_prompt {
          	   my($query) = @_;

          	   print $query->startform;
          	   print "<EM>What's your name?</EM><BR>";
          	   print $query->textfield('name');
          	   print $query->checkbox('Not my real name');

          	   print "<P><EM>Where can you find English Sparrows?</EM><BR>";
          	   print $query->checkbox_group('Sparrow locations',
     			 [England,France,Spain,Asia,Hoboken],
     			 [England,Asia]);

          	   print "<P><EM>How far can they fly?</EM><BR>",
                 	$query->radio_group('how far',
     	       ['10 ft','1 mile','10 miles','real far'],
     	       '1 mile');

          	   print "<P><EM>What's your favorite color?</EM>  ";
          	   print $query->popup_menu('Color',['black','brown','red','yellow'],'red');

          	   print $query->hidden('Reference','Monty Python and the Holy Grail');

          	   print "<P><EM>What have you got there?</EM>  ";
          	   print $query->scrolling_list('possessions',
     		 ['A Coconut','A Grail','An Icon',
     		  'A Sword','A Ticket'],
     		 undef,
     		 10,
     		 'true');

          	   print "<P><EM>Any parting comments?</EM><BR>";
          	   print $query->textarea('Comments',undef,10,50);

          	   print "<P>",$query->reset;
          	   print $query->submit('Action','Shout');
          	   print $query->submit('Action','Scream');
          	   print $query->endform;
          	   print "<HR>\n";
     }

     sub do_work {
          	   my($query) = @_;
          	   my(@values,$key);

     print "<H2>Here are the current settings in this form</H2>";

     foreach $key ($query->param) {
      	      print "<STRONG>$key</STRONG> -> ";
      	      @values = $query->param($key);
      	      print join(", ",@values),"<BR>\n";
               }
      	}

      	sub print_tail {
     print <<END;
      	<HR>
      	<ADDRESS>Lincoln D. Stein</ADDRESS><BR>
      	<A HREF="/">Home Page</A>
      	END
      	}

BUGS
====

   This module doesn't do as much as CGI.pm, and it takes longer to load.
Such is the price of flexibility.

SEE ALSO
========

   See URI/URL, CGI/Request,
CGI/MiniSvr, CGI/Base, CGI,

easily create CGI form-based applications
*****************************************

NAME
====

   CGI::FormMagick - easily create CGI form-based applications

SYNOPSIS
========

     use CGI::FormMagick;

     my $f = new CGI::FormMagick();
     my $f = new CGI::FormMagick(TYPE => FILE,  SOURCE => $myxmlfile, DEBUG => 1);
     my $f = new CGI::FormMagick(TYPE => STRING,  SOURCE => $data , DEBUG => 1);

     $f->add_lexicon("fr", { "Yes" => "Oui", "No" => "Non"});

     $f->display();

DESCRIPTION
===========

   FormMagick is a toolkit for easily building fairly complex form-based
web applications.  It allows the developer to specify the structure of a
multi-page "wizard" style form using XML, then display that form using
only a few lines of Perl.

How it works:
-------------

   You (the developer) provide at least:

   * Form descriptions (XML)

   * HTML templates (Text::Template format) for the page headers and
     footers

   And may optionally provide:

   * L10N lexicon entries

   * Validation routines for user input data

   * Routines to run before or after a page of the form is displayed

   FormMagick brings them all together to create a full application.

METHODS
=======

new()
-----

   The new() method requires no arguments, but may take the following
optional arguments (as a hash):

TYPE
     Defaults to "FILE" (the only currently implemented type).  Eventually
     we'll also allow such things as FILEHANDLE, STRING, etc (c.f.
     Text::Template, which does this quite nicely).

SOURCE
     Defaults to a filename matching that of your script, only with an
     extension of .xml (we got this idea from XML::Simple).

DEBUG
     Defaults to 0 (no debug output).  Setting it to 1 (or any other true
     value) will cause debugging messages to be output.

display()
---------

   The display method displays your form.  It takes no arguments.

add_lexicon()
-------------

   This method takes two arguments.  The first is a two-letter string
representing the language to which entries should be added.  These are
standard ISO language abbreviations, eg "en" for English, "fr" for French,
"de" for German, etc.

   The second argument is a hashref in which the keys of the hash are the
phrases to be translated and the values are the translations.

   For more information about how localization (L10N) works in FormMagick,
see `CGI::FormMagick::L10N'.

debug($msg)
-----------

   The debug method prints out a nicely formatted debug message.  It's
usually called from your script as `$f-'debug($msg)>

Form descriptions
-----------------

   Sample form description

   The following is an example of how a form is described in XML. More
complete examples can be found in the `examples/' subdirectory in the
CGI::FormMagick distribution.

     <FORM TITLE="My form application" HEADER="myform_header.tmpl"
       FOOTER="myform_footer.tmpl" POST-EVENT="submit_order">
       <PAGE NAME="Personal" TITLE="Personal details" DESCRIPTION="Please
       provide us with the following personal details for our records">
         <FIELD ID="firstname" LABEL="Your first name" TYPE="TEXT"
           VALIDATION="nonblank"/>
         <FIELD ID="lastname" LABEL="Your surname" TYPE="TEXT"
           VALIDATION="nonblank"/>
         <FIELD ID="username" LABEL="Choose a username" TYPE="TEXT"
           VALIDATION="username" DESCRIPTION="Your username must
     	be between 3 and 8 characters in length and contain only letters
     	and numbers."/>
       </PAGE>
       <PAGE NAME="Payment" TITLE="Payment details"
       POST-EVENT="check_credit_card" DESCRIPTION="We need your full credit
       card details to process your order.  Please fill in all fields.
       Your card will be charged within 48 hours.">
         <FIELD ID="cardtype" LABEL="Credit card type" TYPE="SELECT"
           OPTIONS="list_credit_card_types" VALIDATION="credit_card_type"/>
         <FIELD ID="cardnumber" LABEL="Credit card number" TYPE="TEXT"
           VALIDATION="credit_card_number"/>
         <FIELD ID="cardexpiry" LABEL="Expiry date (MM/YY)" TYPE="TEXT"
           VALIDATION="credit_card_expiry"/>
       </PAGE>
       <PAGE NAME="Random" TITLE="Random fields">
         <FIELD ID="confirm" LABEL="Click here to confirm" TYPE="CHECKBOX"
           VALUE="confirm" CHECKED="0"/>
         <FIELD ID="color" LABEL="Choose a color" TYPE="RADIO"
           OPTIONS="'red', 'green', 'blue'"/>
       </PAGE>
     </FORM>

   The XML must comply with the FormMagick DTD (included in the
distribution as FormMagick.dtd).  A command-line tool to test compliance
is planned for a future release.

Field types
-----------

   The following values are permitted in the TYPE attribute of the FIELD
element:

   * TEXT

   * SELECT (requires OPTIONS attribute)

   * RADIO (requires OPTIONS attribute)

   * CHECKBOX (CHECKED attribute is optional)

Notes on parsing of OPTIONS attribute
-------------------------------------

   The OPTIONS attribute has automagical Do What I Mean (DWIM) abilities.
You can give it a value which looks like a Perl list, a Perl hash, or a
subroutine name.  For instance:

     OPTIONS="'red', 'green', 'blue'"

     OPTIONS="'ff0000' => 'red', '00ff00' => 'green', '0000ff' => 'blue'"

     OPTIONS="get_colors()"

   How it works is that FormMagick looks for the => operator, and if it
finds it it evals the OPTIONS string and assigns the result to a hash.  If
it finds a comma (but no little => arrows) it figures it's a list, and
evals it and assigns the results to an array.  Otherwise, it tries to
interpret what's there as the name of a subroutine in the scope of the
script that called FormMagick.

   A few gotchas to look out for:

   * Make sure you quote strings in lists and hashes.  "red,blue,green"
     will fail (silently) because of the barewords.

   * Single-element lists ("red") will fail because the DWIM parsing
     doesn't find a comma there and treats it as the name of a subroutine.
     But then, a single-element radio button group or select dropdown is
     pretty meaningless anyway, so why would you do that?

   * Arrays will result in options being sorted in the same order they were
     listed.  Hashes will be sorted by key using the default Perl `sort()'.

   * An anti-gotcha: subroutine names do not require the parens on them.
     "get_colors" and "get_colors()" will work the same.

SEE ALSO
========

   CGI::FormMagick::L10N

   CGI::FormMagick::Validator

   CGI::FormMagick::FAQ

BUGS
====

   There are a number of features which have not yet been implemented.
Also, there are probably mismatches between this perldoc and the actual
functionality.

AUTHOR
======

   Kirrily "Skud" Robert <skud@infotrope.net>

   Contributors:

   Shane R. Landrum <slandrum@turing.csc.smith.edu>

   James Ramirez <jamesr@cogs.susx.ac.uk>

   More information about FormMagick may be found at
http://sourceforge.net/projects/formmagick/

Frequently asked questions about FormMagick
*******************************************

NAME
====

   FormMagick FAQ - Frequently asked questions about FormMagick

HOW DO I...
===========

How do I check that my XML is valid?
------------------------------------

How do I customise the look and feel of my forms?
-------------------------------------------------

   Use cascading style sheets.  Take a look at the HTML source output by
FormMagick, and you'll see that most things have a "label" attribute to
make CSS easier.

How do I make my own validation routines?
-----------------------------------------

   Simply create a routine in your CGI script which accepts the data to
validate as an argument.  Have it return "OK" on success or a detailed
error message on failure.

     sub my_validation {
         my $data = shift;
         if ($data =~ /$some_pattern/) {
             return "OK";
         } else {
             return "That looks wrong to me.";
         }
     }

How do I add translations into another language?
------------------------------------------------

   Use the add_lexicon() method:

     $f->add_lexicon("fr", { "Yes" => "Oui", "No" => "Non" });

How do I do extra processing when a user clicks "Next"?
-------------------------------------------------------

   Use a POST-EVENT on the PAGE element.  Create a subroutine that does
what you want:

     sub process_credit_card {
         my $cgi = shift;
     	my $cardnum = $cgi->param("cardnum");
     	my $response = do_processing($cardnum);
     	print "<p>$response</p>";
     }

How do I choose which page to go to based on user input?
--------------------------------------------------------

   Use a PAGE POST-EVENT and set the value of the "wherenext" CGI
parameter:

     sub my_post_page_event {
         my $cgi = shift;
     	if ($cgi->param("foo") eq "bar") {
             $cgi->param(-name => "wherenext", -value => "GoToThisPageName")
         } elsif ($cgi->param("had_enough") eq "Yes") {
             $cgi->param(-name => "wherenext", -value => "Finish")
         }
     }

TROUBLESHOOTING
===============

General troubleshooting tips
----------------------------

   Try turning on debugging when you invoke FormMagick:

   my $f = new CGI::FormMagick( DEBUG => 1 );

Why isn't my data preserved from one page to the next?
------------------------------------------------------

   You probably need to make your `session-tokens' directory writable and
executable by the web server.  Either:

     chown www session-tokens
        (assuming your webserver runs as the www user)
     chmod 700 session-tokens

   Or...

     chown 777 session-tokens

   CGI::FormMagick::L10N - localization routines for FormMagick

SYNOPSIS
========

     use CGI::FormMagick::L10N;

DESCRIPTION
===========

   L10N (Localisation) is the name given to the process of providing
translations into another language.  The previous step to this is I18N
(internationalisation) which is the process of making an application ready
to accept the translations.

   We've done the work of I18N for you, so all you have to do is provide
translations for your apps.

   FormMagick uses the `Locale::Maketext' module for L10N.  It stores its
translations for each language in a hash like this:

     %Lexicon = (
     	"Hello"		=> "Bonjour",
     	"Click here"	=> "Appuyez ici"
     );

   You can add your own entries to any language lexicon using the
add_lexicon() method (see `CGI::FormMagick' for how to call that method).

   Localisation preferences are picked up from the HTTP_ACCEPT_LANGUAGE
environment variable passed by the user's browser.  In Netscape, you set
this by choosing "Edit, Preferences, Navigator, Languages" and then
choosing your preferred language.

   Localisation is performed on:

   * Form titles

   * Page titles and descriptions

   * Field labels and descriptions

   * Validation error messages

   If you wish to localise other textual information such as your HTML
Templates, you will have to explicitly call the l10n routines.

SEE ALSO
========

   The general documentation for FormMagick (`perldoc CGI::FormMagick')

   More information about FormMagick may be found at
http://sourceforge.net/projects/formmagick/

Perl module that can create any HTML tags, as well as groups of or just parts of them, and complete html headers or footers.
****************************************************************************************************************************

NAME
====

   HTML::TagMaker - Perl module that can create any HTML tags, as well as
groups of or just parts of them, and complete html headers or footers.

DEPENDENCIES
============

Perl Version
------------

     5.004

Standard Modules
----------------

     I<none>

Nonstandard Modules
-------------------

     Class::ParamParser

SYNOPSIS
========

     use HTML::TagMaker;

     my $html = HTML::TagMaker->new();
     $html->groups_by_default( 1 );

     print
     	'Content-type: text/html'."\n\n",
     	$html->start_html(
     		-title => "This Is My Page",
     		-style => { -code => <<__endquote },
     \nBODY {
     	background-color: #ffffff;
     	background-image: none;
     }
     __endquote
     	),
     	$html->h1( 'A Simple Example' ),
     	$html->p(
     		"Click " .
     		$html->a( href => 'http://search.cpan.org', text => 'here' ) .
     		" for more."
     	),
     	$html->hr,
     	$html->table(
     		$html->tr( [
     			$html->th( [ 'Name', 'Count', 'URL', 'First Access' ] ),
     			$html->td( [ 'Old Page', 33, 'http://www.domain.com',
     				'1999/04/23 13:55:02' ] )
     		] )
     	),
     	$html->hr,
     	$html->form_start( method => 'post', action => 'http://localhost' ),
     	$html->p(
     		"What's your name? " .
     		$html->input( type => 'text', name => 'name' )
     	),
     	$html->p(
     		"What's the combination?" .
     		$html->input_group(
     			-type => 'checkbox',
     			-name => 'words',
     			-value => ['eenie', 'meenie', 'minie', 'moe'],
     			-checked => [1, 0, 1, 0],
     			-text => ['eenie', 'meenie', 'minie', 'moe'] ),
     	),
     	$html->p(
     		"What's your favorite colour? " .
     		$html->select_start( -size => 1, -name => 'color' ) .
     		$html->option_group(
     			-value => ['red', 'green', 'blue', 'chartreuse'],
     			-text => ['Red', 'Green', 'Blue', 'Chartreuse'] ) .
     		$html->select_end
     	),
     	$html->input( type => 'submit' ),
     	$html->form_end,
     	$html->end_html;

DESCRIPTION
===========

   This Perl 5 object class can be used to generate any HTML tags in a
format that is consistent with the W3C HTML 4.0 standard.  There are no
restrictions on what tags are named, however; you can ask for any new or
unsupported tag that comes along from Netscape or Microsoft, and it will
be made.  Additionally, you can generate lists of said tags with one
method call, or just parts of said tags (but not both at once).

   In this implementation, "standard format" means that tags are made as
pairs (<TAG></TAG>) by default, unless they are known to be "no pair"
tags.  Tags that I know to be "no pair" are [basefont, img, area, param,
br, hr, input, option, tbody, frame, comment, isindex, base, link, meta].
However, you can force any tag to be "pair" or "start only" or "end only"
by appropriately modifying your call to the tag making method.

   Also, "standard format" means that tag modifiers are formatted as
"key=value" by default, unless they are known to be "no value" modifiers.
Modifiers that I know to be "no value" are [ismap, noshade, compact,
checked, multiple, selected, nowrap, noresize, param].  These are
formatted simply as "key" because their very presence indicates positive
assertion, while their absense means otherwise.  For modifiers with
values, the values will always become bounded by quotes, which ensures
they work with both string and numerical quantities (eg: key="value").

   Note that this class is a subclass of Class::ParamParser, and inherits
all of its methods, "params_to_hash()" and "params_to_array()".

HTML CODE FROM SYNOPSIS PROGRAM
===============================

     Content-type: text/html

     <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
     <HTML>
     <HEAD>
     <TITLE>This Is My Page</TITLE>
     <STYLE>
     <!--
     BODY {
     	background-color: #ffffff;
     	background-image: none;
     }
      --></STYLE>
     </HEAD>
     <BODY>
     <H1>A Simple Example</H1>
     <P>Click
     <A HREF="http://search.cpan.org">here</A> for more.</P>
     <HR>
     <TABLE>
     <TR>
     <TH>Name</TH>
     <TH>Count</TH>
     <TH>URL</TH>
     <TH>First Access</TH></TR>
     <TR>
     <TD>Old Page</TD>
     <TD>33</TD>
     <TD>http://www.domain.com</TD>
     <TD>1999/04/23 13:55:02</TD></TR></TABLE>
     <HR>
     <FORM METHOD="post" ACTION="http://localhost">
     <P>What's your name?
     <INPUT TYPE="text" NAME="name"></P>
     <P>What's the combination?
     <INPUT TYPE="checkbox" NAME="words" CHECKED VALUE="eenie">eenie
     <INPUT TYPE="checkbox" NAME="words" VALUE="meenie">meenie
     <INPUT TYPE="checkbox" NAME="words" CHECKED VALUE="minie">minie
     <INPUT TYPE="checkbox" NAME="words" VALUE="moe">moe</P>
     <P>What's your favorite colour?
     <SELECT NAME="color" SIZE="1">
     <OPTION VALUE="red">Red
     <OPTION VALUE="green">Green
     <OPTION VALUE="blue">Blue
     <OPTION VALUE="chartreuse">Chartreuse
     </SELECT></P>
     <INPUT TYPE="submit">
     </FORM>
     </BODY>
     </HTML>

SYNTAX
======

   This class does not export any functions or methods, so you need to
call them using indirect notation.  This means using *Class->function()*
for functions and *$object->method()* for methods.

   Methods of this class always "return" their results, rather than
printing them out to a file or the screen.  Not only is this simpler, but
it gives the calling code the maximum amount of control over what happens
in the program.  They may wish to do post-processing with the generated
HTML, or want to output it in a different order than it is generated.  By
default, all results are returned as a scalar, but methods which generate
a list of tags can optionally return an ARRAY ref, with each element
containing a single tag.  This can aid in post-processing and possibly
speed up the program because there is less copying done.

   Through the magic of autoloading, this class can make any html tag by
calling a class method with the same name as the tag you want.  For
examples, use "hr()" to make a "<HR>" tag, or "p('text')" to make
"<P>text</P>".  This also means that if you mis-spell any method name, it
will still make a new tag with the mis-spelled name.  For autoloaded
methods only, the method names are case-insensitive.

   If you call a class method whose name ends in either of ['_start',
'_end', '_pair'], this will be interpreted as an instruction to make just
part of one tag whose name are the part of the method name preceeding that
suffix.  For example, calling "p_start( 'text' )" results in "<P>text"
rather than "<P>text</P>".  Similarly, calling "p_end()" will generate a
"</P>" only.  Using the '_pair' suffix will force tags to be made as a
pair, whether or not they would do so naturally.  For example, calling
"br_pair" would produce a "<BR></BR>" rather than the normal "<BR>".  When
using either of ['_start','_pair'], the arguments you pass the method are
exactly the same as the unmodified method would use, and there are no
other symantec differences.  However, when using the '_end' suffix, any
arguments are ignored, as the latter member of a tag pair never carries any
attributes anyway.

   If you call a class method whose name ends in "_group", this will be
interpreted as an instruction to make a list of tags whose name are the
part of the method name preceeding the "_group".  For example, calling
"td_group( ['here','we','are'] )" results in
"<TD>here</TD><TD>we</TD><TD>are</TD>" being generated.  The arguments
that you call this method are exactly the same as for calling a method to
make a single tag of the same name, except that the extra optional
parameter "list" can be used to force an ARRAY ref of the new tags to be
returned instead of a scalar.  The symantec difference is that any
arguments whose values are ARRAY refs are interpreted as a list of values
where each one is used in a separate tag; for a single tag, the literal
ARRAY ref itself would be used.  The number of tags produced is equal to
the length of the longest ARRAY ref passed as an argument.  For any other
arguments who have fewer than this count, their last value is replicated
and appended enough times as necessary to make them the same length.  The
value of a scalar argument is used for all the tags.  For example, calling
"input_group( type => checkbox, name => 'letters', value => ['a','b','c']
)" produces '<INPUT TYPE="checkbox" NAME="letters" VALUE="a"><INPUT
TYPE="checkbox" NAME="letters" VALUE="b"><INPUT TYPE="checkbox"
NAME="letters" VALUE="c">'.

   All autoloaded methods require their parameters to be in named format.
These names and values correspond to attribute names and values for the
new tags.  Since "no value" attributes are essentially booleans, they can
have any true or false value associated with them in the parameter list,
which won't be printed.  If an autoloaded method is passed exactly one
parameter, it will be interpreted as the "text" that goes between the tag
pair (<TAG>text</TAG>) or after "start tags" (<TAG>text).  The same result
can be had explicitely by passing the named parameter "text".  Most static
(non-autoloaded) methods require positional parameters, except for
start_html(), which can take either format.  The names of any named
parameters can optionally start with a "-".

FUNCTIONS AND METHODS
=====================

   Note that all the methods defined below are static, so information
specific to autoloaded methods won't likely apply to them.  All of these
methods take positional arguments unless otherwise specified.

new()
-----

   This function creates a new HTML::TagMaker object (or subclass thereof)
and returns it.

initialize()
------------

   This method is used by new() to set the initial properties of an object,
that it creates.  All page attributes are wiped clean, resulting in an
empty page.

clone([ CLONE ])
----------------

   This method initializes a new object to have all of the same properties
of the current object and returns it.  This new object can be provided in
the optional argument CLONE (if CLONE is an object of the same class as
the current object); otherwise, a brand new object of the current class is
used.  Only object properties recognized by HTML::TagMaker are set in the
clone; other properties are not changed.

groups_by_default([ VALUE ])
----------------------------

   This method is an accessor for the boolean "automatic grouping"
property of this object, which it returns.  If VALUE is defined, this
property is set to it.  In cases where we aren't told explicitely that
autoloaded methods are making a single or multiple tags (using ['_start',
'_end', '_pair'] and '_group' respectively), we look to this property to
determine what operation we guess.  The default is "single".  When this
property is true, we can make both single and groups of tags by using a
suffix-less method name; however, making single tags this way is slower
than when this property is false.  Also, be aware that when we are making
a "group", arguments that are ARRAY refs are always flattened, and when we
are making a "single", ARRAY ref arguments are always used literally.

positional_by_default([ VALUE ])
--------------------------------

   This method is an accessor for the boolean "positional arguments"
property of this object, which it returns.  If VALUE is defined, this
property is set to it.  With methods whose parameters could be either
named or positional, when we aren't sure what we are given, do we guess
positional?  Default is named.

prologue_tag()
--------------

   This method returns a prologue tag, which is meant to be the very first
thing in an HTML document.  It tells the web browser such things as what
version of the HTML standard we are adhering to, version 4.0 in this case.
The prologue tag we make looks like '<!DOCTYPE HTML PUBLIC "-//W3C//DTD
HTML 4.0//EN">'.

comment_tag( TEXT )
-------------------

   This method returns a comment tag, which is only visible to people
viewing the HTML source of a document, and not otherwise.  It can take
either a scalar or a list or an Array ref as its TEXT argument.  If a
single item of text is passed, then a comment tag that looks like "<!-
text ->" is made.  If more than one item of text is passed, then a
multi-line comment is made, which has each item of text on its own line
and indented with a single tab.  The latter is suitable for displaying CSS
or JavaScript code in an elegant manner.

make_html_tag( NAME[, PARAMS[, TEXT[, PART]]] )
-----------------------------------------------

   This method is used internally to do the actual construction of single
html tags.   You can call it directly when you want faster code and/or
more control over how tags are made.  The first argument, NAME, is a
scalar that defines the actual name of the tag we are making (eg: 'br');
it is case-insensitive.  The optional second argument, PARAMS, is a HASH
ref containing attribute names and values for the new tag; the names
(keys) are case-insensitive.  The attribute values are all printed
literally, so they should be scalars.  The optional third argument, TEXT,
is a scalar containing the text that goes between the tag pairs; it is not
a tag attribute.  The optional fourth argument, PART, is a scalar which
indicates we should make just a certain part of the tag; acceptable values
are ['pair', 'start', 'end'], and it is case-insensitive.  This method
knows which HTML tags are normally paired or not, which tag attributes
take specified values or not, and acts accordingly.

make_html_tag_group( NAME[, PARAMS[, TEXT[, LIST]]] )
-----------------------------------------------------

   This method is used internally to do the actual construction of html
tag groups.  You can call it directly when you want faster code and/or
more control over how tags are made.  The first argument, NAME, is a
scalar that defines the actual name of the tag we are making (eg: 'br');
it is case-insensitive.  The optional second argument, PARAMS, is a HASH
ref containing attribute names and values for the new tag; the names
(keys) are case-insensitive.  Any attribute values which are ARRAY refs
are flattened, and the number of tags made is determined by the length of
the longest one.  The optional third argument, TEXT, is a HASH ref (or
scalar) containing the text that goes between the tag pairs; it is not a
tag attribute, but if its an ARRAY ref then its length will influence the
number of tags that are made as the length of tag attribute arrays do.
The optional fourth argument, LIST, is a boolean/scalar which indicates
whether this method returns the new tags in an ARRAY ref (one tag per
element) or as a scalar (tags are concatenated together); a true value
forces an ARRAY ref, scalar is the default.  This method knows which HTML
tags are normally paired or not, which tag attributes take specified
values or not, and acts accordingly.

start_html([ TITLE[, AUTHOR[, META[, STYLE[, HEAD[, BODY]]]]] ])
----------------------------------------------------------------

   This method returns a canned HTML template that is suitable for use as
the top of an HTML page.  It consists of the prologue tag (<!DOCTYPE...),
the opening 'html' tag, the entire 'head' section, and the opening 'body'
tag.  The prologue tag looks the same as that generated by the class
method prologue_tag().  This method can take its optional six arguments in
either named or positional format; in the first case, the names look the
same as the positional placeholders above, except they must be in lower
case.  The first two arguments, TITLE and AUTHOR, are scalars which
respectively define the title and author for the document.  The default
value for TITLE is 'Untitled Document', and a '<LINK REV="made">' tag is
made if AUTHOR is present.  The third argument, META, is a HASH ref
containing name/value pairs of meta information, and a '<META NAME="n"
VALUE="v">' tag is made for each one.  The fourth argument, STYLE, allows
Cascading Style Sheets to be used in the document.  See the method
*css_for_start_html()*, which handles the particulars of this argument.
The fifth argument, HEAD, is an ARRAY ref (or scalar) containing anything
else you would like to appear in the 'head' section; it is flattened and
the elements used as-is.  The sixth argument, BODY, is a HASH ref
containing attributes and values for the opening 'body' tag.

end_html()
----------

   This method returns a canned HTML template that is suitable for use as
the bottom of an HTML page.  It consists of the closing 'body' and 'html'
tags.

css_for_start_html([ SRC[, CODE] ])
-----------------------------------

   This method returns HTML code that allows Cascading Style Sheets to be
used in the document when the code is included in its "head" section.
This method is used by start_html() to handle its STYLE argument.  This
method can take its optional arguments in either named or positional
format; in the first case, the names look the same as the positional
placeholders above, except they must be in lower case.  The first
argument, SRC, is an Array ref (or scalar) whose elements are urls for
external StyleSheet documents that should be linked to by the browser, and
a '<LINK REL="stylesheet" SRC="url">' tag is made for each one.  The
second argument, CODE, is an Array ref (or scalar) whose elements are
lines of StyleSheet code that are to be embedded in the HTML document
itself; a "<STYLE><!- code -></STYLE>" multi-line tag is made for them.
When both arguments are used, the SRC appears first in the new HTML.

COMPATABILITY WITH OTHER MODULES
================================

   The methods of this class and their parameters are designed to be
compatible with any same-named methods in the popular CGI.pm class.  This
class will produce identical or browser-compatible HTML from such methods,
and this class can accept all the same argument formats.  Exceptions to
this include:

  1. None of our methods are exported and must be called using indirect
     notation, whereas CGI.pm can export any of it's methods.

  2. start_html() doesn't support all the same arguments, but those that
     do have the same names.  However, the effects of the missing
     arguments can be easily replicated by making the appropriate tags
     explicitely and handing them in via either the "head" or "body"
     arguments, where appropriate.  The common arguments are ['title',
     'author', 'meta', 'style', 'head', 'body'], in that order.

  3. Our textarea() method is autoloaded, and doesn't have the special
     symantecs that CGI.pm's textarea() does.  However, any module who
     subclasses from this one can override textarea() with one that
     matches CGI.pm's symantecs.  The "HTML::FormMaker" module does this.

  4. Autoloaded methods do not use the presence or absense of arguments to
     decide whether to make the new tag as a pair or as "start only".

  5. Autoloaded methods that make html tags won't concatenate their
     arguments into a single argument under any circumstances, but in some
     cases the "shortcuts" of CGI.pm will do so.

  6. Currently we don't html-escape any argument values passed to our tag
     making functions, whereas CGI.pm sometimes does.  While we expect our
     caller to do the escaping themselves where necessary, we may do it
     later in an update.

  7. We go further to make the generated HTML human-readable by: 1. having
     each new tag start on a new line; 2. making all tag and attribute
     names uppercase; 3.  ensuring that about 20 often-used tag attributes
     always appear in the same order (eg: 'type' is before 'name' is
     before 'value'), and before any others.

AUTHOR
======

   Copyright (c) 1999-2000, Darren R. Duncan. All rights reserved. This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.  However, I do request that this copyright
information remain attached to the file.  If you modify this module and
redistribute a changed version then please attach a note listing the
modifications.

   I am always interested in knowing how my work helps others, so if you
put this module to use in any of your own code then please send me the
URL.  Also, if you make modifications to the module because it doesn't
work the way you need, please send me a copy so that I can roll desirable
changes into the main release.

   Address comments, suggestions, and bug reports to
*perl@DarrenDuncan.net*.

CREDITS
=======

   Thanks very much to *Kevin Werbach* for publishing "The Bare Bones
Guide to HTML", which I found to be an invaluable resource when writing
this module (and at other times as well).  The latest version of the
document is available at *http://werbach.com/barebones/*.

   This quick reference lists all the HTML tags that current browsers are
likely to recognize, including all the elements of the official HTML 4.0
recommendation, and some Netscape and Microsoft extensions as well.
Common attributes for these tags are also included in context, giving a
good idea on how they are used.

   When writing this module, I used the Bare Bones reference to verify the
consistant formatting used by all HTML tags, including how tag attributes
are formatted.  I could see the proper formatting for prologue and comment
tags as well; their formats are unique compared to all the other tags.
The other main uses I had for the document was in determining all the HTML
tags which were not used as a pair (most use pairs, few don't), and for
determining which tag attributes made a positive assertion just by their
presence, without need for any associated values (most have values, few
don't).

   Thanks also to *Lincoln D. Stein* for publishing the popular CGI.pm
module, which I found very useful in my programs.  Moreover, I have
decided to emulate much of its functionality in some of my own modules, so
I should give credit where its due for implementing that functionality
first.  Lincoln should be pleased that I am following his advice (look
under heading "BUGS" in CGI) and discarding his large and monolithic
module in favor of simpler ones.

SEE ALSO
========

   perl(1), CGI, Class::ParamParser.

   CGI::FormMagick::Validator - validate data from FormMagick forms

SYNOPSIS
========

   use CGI::FormMagick::Validator;

DESCRIPTION
===========

   This module provides some common validation routines.  Validation
routines return the string "OK" if they succeed, or a descriptive message
if they fail.

Validation routines provided:
-----------------------------

nonblank
     The data is not an empty string : `$data ne ""'

number
     The data is a number (strictly speaking, data is a positive number):
     `$data =~ /^[0-9.]+$/'

word
     The data looks like a single word: `$data !~ /\W/'

minlength(n)
     The data is at least n characters long: `length($data) >= $n'

maxlength(n)
     The data is no more than  n characters long: `length($data) <= $n'

exactlength(n)
     The data is exactly  n characters long: `length($data) E== $n'

lengthrange(n,m)
     The data is between  n and c<m> characters long: `length($data) >= $n'
     and `length($data) <= $m'.  =cut

     sub lengthrange { 	my $data = $_[0]; 	my $minlength= $_[1]; 	my
     $maxlength= $_[2]; 	print "min $minlength, max $maxlength";
     if ( ( length($data) >= $minlength ) and (length($data) <=
     $maxlength) ) { 	        return "OK"; 	} else { 		return
     "This field must be between $minlength and $maxlength characters";
     } }

url
     The data looks like a (normalish) URL: `$data =~
     m!(http|ftp)://[\w/.-/)!'

email
     The data looks more or less like an internet email address: `$data =~
     /\@/'

     Note: not fully compliant with the entire gamut of RFC 822 addressing
     ;)

domain_name
     The data looks like an internet domain name or hostname.

ip_number
     The data looks like a valid IP number.

     The data looks like a good, valid username

password
     The data looks like a good password

date
     The data looks like a date.  Requires the Time::ParseDate module to be
     installed.

iso_country_code
     The data is a standard 2-letter ISO country code.  Requires the
     Locale::Country module to be installed.

US_state
     The data is a standard 2-letter US state abbreviation.  Uses
     Geography::State in non-strict mode, so this module must be installed
     for it to work.

US_zipcode
     The data looks like a valid US zipcode

credit_card_type
     The data looks like a valid type of credit card (eg Visa, Mastercard).
     Requires Business::CreditCard to be installed.

credit_card_number
     The data looks like a valid credit card number.  Requires
     Business::CreditCard to be installed.

credit_card_expiry
     The data looks like a valid credit card expiry date.  Requires
     Business::CreditCard to be installed.

Using more than one validation routine per field
------------------------------------------------

   You can use multiple validation routines like this:

     VALUE="foo" VALIDATION="my_routine, my_other_routine"

   However, there are some requirements on formatting to make sure that
FormMagick can parse what you've given it.

   * Parens are optional on subroutines with no args.  `my_routine' is
     equivalent to `my_routine()'.

   * You *MUST* put a comma then a space between routine names, eg
     `my_routine, my_other_routine' *NOT* `my_routine,my_other_routine'.

   * You *MUST NOT* put a comma between args to a routine, eg
     `my_routine(1,2,3)' *NOT* `my_routine(1, 2, 3)'.

   This will be fixed to be more flexible in a later release.

Making your own routines
------------------------

   FormMagick's validation routines may be overridden and others may be
added on a per-application basis.  To do this, simply define a subroutine
in your CGI script that works in a similar way to the routines provided by
CGI::FormMagick::Validator and use its name in the VALIDATION attribute in
your XML.

   The arguments passed to the validation routine are the value of the
field (to be validated) and any subsequent arguments given in the
VALIDATION attribute.  For example:

     VALUE="foo" VALIDATION="my_routine"
     ===> my_routine(foo)

     VALUE="foo" VALIDATION="my_routine(42)"
     ===> my_routine(foo, 42)

   The latter type of validation routine is useful for routines like
`minlength()' and `lengthrange()' which come with
CGI::FormMagick::Validator.

   Here's an example routine that you might write:

     sub my_grep {
         my $data = shift;
         my @list = @_;
         if (grep /$data/, @list) {
             return "OK"
         } else {
             return "That's not one of: @list"
         }
     }

AUTHOR
======

   Kirrily "Skud" Robert <skud@infotrope.net>

   More information about FormMagick may be found at
http://sourceforge.net/projects/formmagick/

Convert an XML file into a suite of CGI forms.
**********************************************

NAME
====

   `CGI::Formalware' - Convert an XML file into a suite of CGI forms.

SYNOPSIS
========

   In your browser, type: localhost/cgi-bin/x.pl

   where x.pl contains nothing more than:

     #!perl -w
     use integer;
     use strict;
     use lib 'C:/Perl';
     use lib 'C:/Perl/Scripts/General';	# Ie $PERL5LIB.
     use CGI::Formalware;
     my($form) = CGI::Formalware -> new({form2file => 1, debug => 1});
     $form -> process();
     exit(0);

   Upon starting, `CGI::Formalware' asks for the name of your XML file,
which is assumed to be in cgi-bin/.

DESCRIPTION
===========

   To provide a type of repository for frequently used scripts, which can
then be executed locally or remotely (via Net::Telnet), by just entering a
password (for remote scripts), and clicking.

INSTALLATION
============

   You install `CGI::Formalware', as you would install any perl module
library, by running these commands:

     perl Makefile.PL
     make
     make test
     make install

   If you want to install a private copy of `CGI::Formalware' in your home
directory, then you should try to produce the initial Makefile with
something like this command:

     perl Makefile.PL LIB=~/perl
     	or
     perl Makefile.PL LIB=C:/Perl/Site/Lib

   If, like me, you don't have permission to write man pages into unix
system directories, use:

     make pure_install

   instead of make install. This option is secreted in the middle of p 414
of the second edition of the dromedary book.

AUDIENCE
========

   Webmasters.

SECURITY
========

   None. Even worse, `CGI::Formalware' is designed to circumvent a web
server's concept of what Apache calls DocumentRoot.

CONSTRUCTOR new
===============

   new takes either no parameters, or an anonymous hash. See the example
above.  Keys and values recognized are:

   * debug => 1 means turn on debugging. At the moment this opens and
     closes the file CGI-Formalware.log, but does not write anything to it

   * form2file => 1 means output each form to a file, using the name given
     by the form's formFileName attribute. The forms are written to
     cgi-bin/.  If the form has no such attribute, this option is ignored.
     See example below

   * timeScripts => 1 means report elapsed time at the end of each
     script's output

HIGHLIGHTS
==========

   * Read an XML file, whose format is fixed, and generate a suite of CGI
     forms

   * A cascading style sheet can be specified for each form individually

   * A Table of Contents may appear on each form

   * Each form is more-or-less assumed to contain a list of scripts

   * Tokens in the XML correspond to a few functions available in Lincoln
     Stein's CGI.pm. Available tokens are:

        * fileField

               <fileField
               	name		= 'fileName'
               	prompt		= 'Filename: '
               	size		= '60'
               	override	= '0'
               />

        * horizontalRule

               <horizontalRule />

        * paragraph

               <paragraph />

               <paragraph text = 'Output a comment' />

        * radioGroup

               <radioGroup
               	name		= 'serverName'
               	prompt		= 'Server name: '
               	value		= 'Example|Simple|Test'
               	columns		= '1'	# Optional. Defaults to '1'. Use a string, not a digit
               />

        * textField

               <textField
               	name		= 'username'
               	prompt		= 'Username: '
               	value		= ''
               	size		= '15'
               	override	= '0'
               />

     Over time, more functions will be added.

   * A textField with the name 'password' is treated as a password field.
     Also, the entity 'script' defines a Unix- or DOS-type batch file

   * These entities produce on-screen fields, or, in the case of the
     scripts, a vertical array of radio buttons

   * So, to run a script you fill in whatever fields the script uses and
     then select that script

   * Macros in the scripts, eg %fileName% are expanded with the current
     value of the field whose name appears between the % signs

   * A script whose last line is 'ftp -n -v' is recognized and handled
     specially.  Your form must contain textFields called 'host',
     'username' and 'password' and 'fileName'. A binary 'get' is
     performed. This will be made more flexible one day

   * Scripts have an attribute 'type', which can be 'local' or 'remote'.

     Remote scripts are passed to Net::Telnet, on the assumption that you
     know what you are doing. Your form must contain textFields called
     'host', 'username' and 'password'

NAVIGATION
==========

   Forms are linked with 'Previous form', 'Next form' buttons.

   Any previously-entered textFields, except those whose name is
'password', are remembered when you return to a form. This is very
convenient.

   The password values are zapped by CGI.pm, not by me. This is a security
feature.  It means you can walk away from your system and not have someone
gain automatic access to a remote system.

CASCADING STYLE SHEETS
======================

   Each form entity may have a 'css' attribute, giving the name of the CSS
file for that form. These attribute values are like '/CGI-Formalware.css',
which, under Apache, means this value is prefixed with DocumentRoot. That
is, the path to the CSS is a URI, and will not be seen if in cgi-bin/.

   The compulsory elements are: H1, H2 and P.TOC.

   Herewith a sample:

     H1
     {
     	font-size:			20pt;
     	alignment:			center;
     	color:				teal;
     }

     H2
     {
     	font-size:			16pt;
     	font-style:			italic;
     	color:				maroon;
     }

     P.TOC
     {
     	font-size:			12pt;
     	color:				white;
     	background-color:	blue;
     }

ENVIRONMENT VARIABLES
=====================

   None.

INPUT DATA VALIDATION
=====================

   These checks are performed:

   * Each forms entity may have a 'tocEntry' attribute. If present, and if
     the tocVisible attribute is 'true', then a Table of Contents is put on
     each form, headed by this text. The default is 'Contents'

   * Each forms entity may have a 'tocVisible' attribute. If its value is
     'True', then a Table of Contents is put on each form, headed by the
     value of 'tocEntry'. The default is 'True'

   * Each form entity must have 'heading' and 'tocEntry' attributes

   * Each form entity must have a unique 'heading' attribute

   * Each form entity may have a unique 'formFileName' attribute. If
     present, then this file name is used to output the form to a file if
     the constructor option new({form2file => 1}) is used

   * Each fileField entity must have 'name', 'prompt', 'value' and 'size'
     attributes

   * Each textField entity must have 'name', 'prompt', 'value' and 'size'
     attributes

   * Each scripts entity must have a 'heading' attribute

   * Each script entity must have 'heading', 'type' and 'line' attributes

   * Each script entity must have a unique 'heading' attribute

   * Each script entity's 'type' attribute must be 'local' or 'remote'

XML DTD
=======

   TBA.

XML FILE FORMAT
===============

   Herewith a sample:

     <forms
     	tocEntry	= 'Forms'
     	tocVisible	= 'True'
     >
     <form
     	heading			= 'Unix Command Menu'
     	tocEntry		= 'Unix menu'
     	css				= '/CGI-Formalware.css'
     	formFileName	= '1.html'
     >
     	<horizontalRule />

     <radioGroup
     	name	= 'host'
     	prompt	= 'Host: '
     	value	= 'bigBox|littleBox'
     />

     <paragraph />

     <textField
     	name		= 'username'
     	prompt		= 'Username: '
     	value		= ''
     	size		= '15'
     	override	= '0'
     />

     <textField
     	name		= 'password'
     	prompt		= '  Password: '
     	value		= ''
     	size		= '15'
     	override	= '0'
     />

     <horizontalRule />

     <scripts
     	heading			= 'Unix Scripts'
     	numberScripts	= 'Yes'
     >
     	<script
     		heading		= 'Files in home directory'
     		type		= 'remote'
     		line1		= 'dir'
     	/>
     	<script
     		heading		= 'Tags in repository'
     		type		= 'remote'
     		line1		= 'cd $M'
     		line2		= 'getTags'
     	/>
     </scripts>
     	</form>

     <form
     	heading		= 'DOS Command Menu'
     	tocEntry	= 'DOS menu'
     >

     <horizontalRule />

     <radioGroup
     	name	= 'host'
     	prompt	= 'Host: '
     	value	= 'bigBox|littleBox'
     />

     <paragraph text = 'Enter a username and a password.' />

     <textField
     	name		= 'username'
     	prompt		= 'Username: '
     	value		= ''
     	size		= '15'
     	override	= '0'
     />

     <textField
     	name		= 'password'
     	prompt		= '  Password: '
     	value		= ''
     	size		= '15'
     	override	= '0'
     />

     <horizontalRule />

     <fileField
     	name		= 'fileName'
     	prompt		= 'Filename: '
     	size		= '60'
     	override	= '0'
     />

     <horizontalRule />

     <scripts
     	heading	= 'PC Scripts'
     >

     <script
     	heading		= 'Files in root directory'
     	type		= 'local'
     	line1		= 'cd \'
     	line2		= 'dir'
     />
     <script
     	heading		= 'FTP something somewhere'
     	type		= 'local'
     	line1		= 'ftp -n -v'
     />
     <script
     	heading		= 'Untar a file'
     	type		= 'local'
     	line1		= 'cd \'
     	line2		= 'tar mxvzf %fileName%'
     />
     		</scripts>
     	</form>
     	</forms>

NESTED FORMS
============

   Nope, I don't recognize them. Maybe one day...

REQUIRED MODULES
================

   * CGI

   * Net::Telnet

   * XML::DOM

AUTHOR
======

   `CGI::Formalware' was written by Ron Savage *<ron@savage.net.au>* in
1999.

   Copyright (c) 1999 Ron Savage.

   Available from http://savage.net.au/Perl.html.

LICENCE
=======

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

imagemap behavior for CGI programs
**********************************

NAME
====

   CGI::Imagemap.pm - imagemap behavior for CGI programs

SYNOPSIS
========

     use CGI::Imagemap;

     $map = new CGI::Imagemap;
     $map->setmap(@map);
     $action = $map->action($x,$y);

     -- or --

     use CGI::Imagemap 'action_map';

     $action = action_map($x,$y,@map);

DESCRIPTION
===========

   CGI::Imagemap allows CGI programmers to place TYPE=IMAGE form fields on
their HTML fill-out forms, with either client-side or server-side maps
emulated.

   The imagemap file follows that of the NCSA imagemap program.  Each point
is an x,y tuple.  Each line in the map consists of one of the following
formats.  Comment lines start with "#".

     circle action center edgepoint
     rect action upperleft lowerright
     point action point
     poly action point1 point2 ... pointN
     default action

   Using "point" and "default" in the same map makes no sense. If "point"
is used, the action for the closest one is selected.

   To use CGI::Imagemap, define an image submit map on your form with
something like:

     <input type=image name=mv_todo
          SRC="image_url">

   You can pass a "client-side" imagemap like this:

     <input type="hidden" name="todo.map"
     		value="rect action1 0,0 25,20">
     <input type="hidden" name="todo.map"
     		value="rect action2 26,0 50,20">
     <input type="hidden" name="todo.map"
     		value="rect action3 51,0 75,20">
     <input type="hidden" name="todo.map"
     		value="default action0">

   If the @map passed parameter contains a NUL (\0) in the first array
position, the map is assumed to be null-separated and @map is built by
splitting it.  This allows a null-separated todo.map with multiple values
(parsed by a cgi-lib.pl or the like) to be referenced.

   All of the following examples assume the above definitions in your form.

Static Methods
--------------

   CGI::Imagemap allows the export of two routines, *action_map* and
*map_untaint*.   If you choose to use CGI::Imagemap statically, call the
module with:

     use CGI::Imagemap qw(action_map map_untaint);

action_map(x,y,map)
     We are assuming the map definition above, with the *type=image*
     variable named todo, and the map in *todo.map*. You can pass the map
     in one of two ways.  The first is compatible with the CGI.pm (or
     CGI::*) modules, and passes the map as an array:

          $query = new CGI;
          my $x = $query->param('todo.x');
          my $y = $query->param('todo.y');
          my $map = $query->param('todo.map');
          $action = action_map($x, $y, $map);

     If you are using the old *cgi-lib.pl* library, which places multiple
     instances of the same form variable in a scalar, separated by null
     (\0) characters, you can do this:

          ReadParse(*FORM);
          my $x = $FORM{'todo.x'};
          my $y = $FORM{'todo.y'};
          my $map = $FORM{'todo.map'};
          $action = action_map($x, $y, $map);

map_untaint($untaint)
     If you are running with taint checking, as is suggested for CGI
     programs, you can use map_untaint(1) to set map untainting on a
     global basis.  (If using class methods, each has its own instance of
     untainting).

     It ensures all characters in the action fit pattern of [-\w.+@]+,
     meaning alphnumerics, underscores, dashes (-), periods, and the @
     sign.  It also checks the methods (rect,poly,point,default,circle)
     and ensures that points/tuples are only integers.  Once that is done,
     it untaints the passed form variables.

          map_untaint(1);    # Turns on untainting
          map_untaint('yes');# Same as above

          map_untaint(0);    # Disable untainting
          map_untaint('no'); # Same as above

          $status = map_untaint(); # Get status

     Default is no untainting.

Class Methods
-------------

   The class methods for CGI::Imagemap are much the same as above, with the
exception that multiple imagemaps are then maintained by the module, with
full independence. The following method definitions assume the CGI::Form
module is being used, like this:

     use CGI::Form;
     use CGI::Imagemap;

     $query  = new CGI::Form;
     $map    = new CGI::Imagemap;

setmap(@map)
     This sets the map for the instance.

          $map = new CGI::Imagemap;
          $map->setmap($query->param('todo.map'));

addmap(@map)
     This adds a new map action specification *to the current map*.

          $map->addmap('point action5 3,9'));

action(x,y)
     This finds the action, based on the active map and the values of x
     and y,

          $x = $query->param('todo.x');
          $y = $query->param('todo.y');
          $action = $map->action($x, $y);

untaint()
     Sets, unsets, or returns the taint status for the instance.

          $map->untaint(1);       # Turns on untainting
          $map->untaint('yes');   # Same as above
          $map->untaint(1);       # Disables untainting
          $map->untaint('yes');   # Same as above
          $status = $map->untaint(); # Get status

version()
     Returns the version number of the module.

EXAMPLE
=======

   A couple of self-contained examples are included in the CGI::Imagemap
package.  They are:

     testmap     -  Uses the CGI::Form module
     testmap.old -  Uses the old cgi-lib.pl

BUGS
====

   The untainting stuff is not totally independent - threading might not
work very well.  This can be fixed if it is important - in the CGI world,
I doubt it.

AUTHOR
======

   Mike Heins, Internet Robotics, <mikeh@iac.net>

CREDITS
=======

   This work is heavily kited from the Perl imagemap program originally
written by V. Khera <khera@kciLink.com>.

Perl module to process and decode WWW forms and cookies.
********************************************************

NAME
====

   CGI::Lite - Perl module to process and decode WWW forms and cookies.

SYNOPSIS
========

     use CGI::Lite;

     $cgi = new CGI::Lite;

     $cgi->set_platform ($platform);

         where $platform can be one of (case insensitive):
         Unix, Windows, Windows95, DOS, NT, PC, Mac or Macintosh

     $cgi->set_file_type ('handle' or 'file');
     $cgi->add_timestamp (0, 1 or 2);

     where 0 = no timestamp
           1 = timestamp all files (default)
           2 = timestamp only if file exists

     $cgi->filter_filename (\&subroutine);

     $size = $cgi->set_buffer_size ($some_buffer_size);

     $status = $cgi->set_directory ('/some/dir');
     $cgi->set_directory ('/some/dir') || die "Directory doesn't exist.\n";

     $cgi->close_all_files;

     $cgi->add_mime_type ('application/mac-binhex40');
     $status = $cgi->remove_mime_type ('application/mac-binhex40');
     @list = $cgi->get_mime_types;

     $form = $cgi->parse_form_data;
     %form = $cgi->parse_form_data;

     or

     $form = $cgi->parse_form_data ('GET', 'HEAD' or 'POST');

     $cookies = $cgi->parse_cookies;
     %cookies = $cgi->parse_cookies;

     $status  = $cgi->is_error;
     $message = $cgi->get_error_message;

     $cgi->return_error ('error 1', 'error 2', ...);

     $keys = $cgi->get_ordered_keys;
     @keys = $cgi->get_ordered_keys;

     $cgi->print_data;

     $cgi->print_form_data;   (deprecated as of v1.8)
     $cgi->print_cookie_data; (deprecated as of v1.8)

     $new_string = $cgi->wrap_textarea ($string, $length);

     @all_values = $cgi->get_multiple_values ($reference);

     $cgi->create_variables (\%form);
     $cgi->create_variables ($form);

     $escaped_string = browser_escape ($string);

     $encoded_string = url_encode ($string);
     $decoded_string = url_decode ($string);

     $status = is_dangerous ($string);
     $safe_string = escape_dangerous_chars ($string);

DESCRIPTION
===========

   You can use this module to decode form and query information, including
file uploads, as well as cookies in a very simple manner; you need not
concern yourself with the actual details behind the decoding process.

METHODS
=======

   Here are the methods you can use to process your forms and cookies:

parse_form_data
     This will handle the following types of requests: GET, HEAD and POST.
     By default, CGI::Lite uses the environment variable REQUEST_METHOD to
     determine the manner in which the query/form information should be
     decoded. However, as of v1.8, you are allowed to pass a valid request
     method to this function to force CGI::Lite to decode the information
     in a specific manner.

     For multipart/form-data, uploaded files are stored in the user
     selected directory (see set_directory). If timestamp mode is on (see
     add_timestamp), the files are named in the following format:

          timestamp__filename

     where the filename is specified in the "Content-disposition" header.
     NOTE:, the browser URL encodes the name of the file. This module
     makes no effort to decode the information for security reasons.
     However, you can do so by creating a subroutine and then using the
     filter_filename method.

     *Return Value*

     Returns either a hash or a reference to the hash, which contains all
     of the key/value pairs. For fields that contain file information, the
     value contains either the path to the file, or the filehandle (see
     the set_file_type method).

parse_new_form_data
     As for parse_form_data, but clears the CGI object state before
     processing the request. This is useful in persistant application
     (e.g. FCGI), where the CGI object is reused for multiple requests.
     e.g.

          $CGI = new CGI::Lite;
          while (FCGI::accept > 0)
          {
          	$Query = $CGI->parse_new_form_data();
          	<process query>
          }

parse_cookies
     Decodes and parses cookies passed by the browser. This method works in
     much the same manner as parse_form_data.

is_error
     As of v1.8, errors in parsing are handled differently. You can use
     this method to check for any potential errors after you've called
     either parse_form_data or parse_cookies.

     *Return Value*

          0 Success
          1 Failure

get_error_message
     If an error occurs when parsing form/query information or cookies, you
     can use this method to retrieve the error message. Remember, you can
     check for errors by calling the is_error method.

     *Return Value*

     The error message.

return_error
     You can use this method to return errors to the browser and exit.

set_platform
     You can use this method to set the platform on which your Web server
     is running. CGI::Lite uses this information to translate end-of-line
     (EOL) characters for uploaded files (see the add_mime_type and
     remove_mime_type methods) so that they display properly on that
     platform.

     You can specify either (case insensitive):

          Unix                                  EOL: \012      = \n
          Windows, Windows95, DOS, NT, PC       EOL: \015\012  = \r\n
          Mac or Macintosh                      EOL: \015      = \r

     "Unix" is the default.

set_directory
     Used to set the directory where the uploaded files will be stored
     (only applies to the *multipart/form-data* encoding scheme).

     This function should be called before you call parse_form_data, or
     else the directory defaults to "/tmp". If the application cannot
     write to the directory for whatever reason, an error status is
     returned.

     *Return Value*

          0  Failure
          1  Success

close_all_files
     All uploaded files that are opened as a result of calling
     set_file_type with the "handle" argument can be closed in one shot by
     calling this method.

add_mime_type
     By default, EOL characters are translated for all uploaded files with
     specific MIME types (i.e text/plain, text/html, etc.). You can use
     this method to add to the list of MIME types. For example, if you
     want CGI::Lite to translate EOL characters for uploaded files of
     *application/mac-binhex40*, then you would do this:

          $cgi->add_mime_type ('application/mac-binhex40');

remove_mime_type
     This method is the converse of add_mime_type. It allows you to remove
     a particular MIME type. For example, if you do not want CGI::Lite to
     translate EOL characters for uploaded files of *text/html*, then you
     would do this:

          $cgi->remove_mime_type ('text/html');

     *Return Value*

          0  Failure
          1  Success

get_mime_types
     Returns the list, either as a reference or an actual list, of the
     MIME types for which EOL translation is performed.

set_file_type
     The names of uploaded files are returned by default, when you call
     the parse_form_data method. But,  if pass the string "handle" to this
     method, the handles to the files are returned. However, the name of
     the handle corresponds to the filename.

     This function should be called before you call parse_form_data, or
     else it will not work.

add_timestamp
     By default, a timestamp is added to the front of uploaded files.
     However, you have the option of completely turning off timestamp mode
     (value 0), or adding a timestamp only for existing files (value 2).

filter_filename
     You can use this method to change the manner in which uploaded files
     are named. For example, if you want uploaded filenames to be all
     upper case, you can use the following code:

          $cgi->filter_filename (\&make_uppercase);
          $cgi->parse_form_data;

          .
          .
          .

          sub make_uppercase
          {
              my $file = shift;

          $file =~ tr/a-z/A-Z/;
          return $file;
              }

set_buffer_size
     This method allows you to set the buffer size when dealing with
     multipart form data. However, the *actual* buffer size that the
     algorithm uses can be up to 3x the value you specify. This ensures
     that boundary strings are not "split" between multiple reads. So,
     take this into consideration when setting the buffer size.

     You cannot set a buffer size below 256 bytes and above the total
     amount of multipart form data. The default value is 1024 bytes.

     *Return Value*

     The buffer size.

get_ordered_keys
     Returns either a reference to an array or an array itself consisting
     of the form fields/cookies in the order they were parsed.

     *Return Value*

     Ordered keys.

print_data
     Displays all the key/value pairs (either form data or cookie
     information) in a ordered fashion. The methods print_form_data and
     print_cookie_data are deprecated as of version v1.8, and will be
     removed in future versions.

print_form_data
     Deprecated as of v1.8, see print_data.

print_cookie_data (deprecated as of v1.8)
     Deprecated as of v1.8, see print_data.

wrap_textarea
     You can use this function to "wrap" a long string into one that is
     separated by a combination of carriage return and newline (see
     set_platform) at fixed lengths.  The two arguments that you need to
     pass to this method are the string and the length at which you want
     the line separator added.

     *Return Value*

     The modified string.

get_multiple_values
     One of the major changes to this module as of v1.7 is that multiple
     values for a single key are returned as an reference to an array, and
     not as a string delimited by the null character ("\0"). You can use
     this function to return the actual array. And if you pass a scalar
     value to this method, it will simply return that value.

     There was no way I could make this backward compatible with versions
     older than 1.7. I apologize!

     *Return Value*

     Array consisting of the multiple values.

create_variables
     Sometimes, it is convenient to have scalar variables that represent
     the various keys in a hash. You can use this method to do just that.
     Say you have a hash like the following:

          %form = ('name'   => 'shishir gundavaram',
          	     'sport'  => 'track and field',
          	     'events' => '100m');

     If you call this method in the following manner:

          $cgi->create_variables (\%hash);

     it will create three scalar variables: $name, $sport and $events.
     Convenient, huh?

browser_escape
     Certain characters have special significance to the browser. These
     characters include: "<" and ">". If you want to display these
     "special" characters, you need to escape them using the following
     notation:

          &#ascii;

     This method does just that.

     *Return Value*

     Escaped string.

url_encode
     This method will URL encode a string that you pass it. You can use
     this to encode any data that you wish to pass as a query string to a
     CGI application.

     *Return Value*

     URL encoded string.

url_decode
     You can use this method to URL decode a string.

     *Return Value*

     URL decoded string.

is_dangerous
     This method checks for the existence of dangerous meta-characters.

     *Return Value*

          0 Safe
          1 Dangerous

escape_dangerous_chars
     You can use this method to "escape" any dangerous meta-characters.

     *Return Value*

     Escaped string.

SEE ALSO
========

   If you're looking for more comprehensive CGI modules, you can either
use the CGI::* modules or CGI.pm. Both are maintained by Dr. Lincoln Stein
*(lstein@genome.wi.mit.edu)* and can be found at your local CPAN mirror
and at his Web site:

   *http://www-genome.wi.mit.edu/WWW/tools/scripting*

ACKNOWLEDGMENTS
===============

   I'd like to thank the following for finding bugs and offering
suggestions:

Eric D. Friedman (friedman@uci.edu)
Thomas Winzig (tsw@pvo.com)
Len Charest (len@cogent.net)
Achim Bohnet (ach@rosat.mpe-garching.mpg.de)
John E. Townsend (John.E.Townsend@BST.BLS.com)
Andrew McRae (mcrae@internet.com)
Dennis Grant (dg50@chrysler.com)
Scott Neufeld (scott.neufeld@mis.ussurg.com)
Raul Almquist (imrs@ShadowMAC.org)
and many others!
COPYRIGHT INFORMATION
=====================

     Copyright (c) 1995, 1996, 1997 by Shishir Gundavaram
                     All Rights Reserved

     Permission to use, copy, and  distribute  is  hereby granted,
     providing that the above copyright notice and this permission
     appear in all copies and in supporting documentation.

Perl extension for centralized logging of debug, error, status and success messages from scripts or other modules.
******************************************************************************************************************

NAME
====

   CGI::Log - Perl extension for centralized logging of debug, error,
status and success messages from scripts or other modules.

SYNOPSIS
========

     use CGI::Log;

     Log->debug("user: $user");		## add messages
     Log->status("Welcome $user.");
     Log->error("I'm sorry $user, but you do not have access to that area.");

     @msg = Log->get_debug();		## get messages
     @msg = Log->get_error();
     @msg = Log->get_error("UI");
     @msg = Log->get_status();

     Log->is_error;			## test for messages
     Log->is_status;
     Log->is_success;

     Log->debug_off;		## causes print() and debug() to be skipped

     Log->print();			## outputs debug and error logs in HTML
     Log->clear;			## clear all entries (current pid)

     Log->_report;			## reports the sizes of the arrays (lengths)
     Log->ui_no_error();		## turns off inclusion of $! in user error messages

DESCRIPTION
===========

   This module acts as a central repository for debug, status and error
messages.  It instantiates itself automatically (if it needs to) so you
can access the Log object functions from anywhere in you code including
other modules/objects with a simple consistent syntax.

   It was written for CGI and mod_perl programming, but it could easily be
used in any perl script where there is a need for centralized logging.
(The only function which is CGI specific is print() since it outputs the
debug and error logs with HTML formatting.)

   It was originally written to just hold debugging information, but it
has been extended to hold information that you might want to return to the
user (i.e. the user-interface).

   It is designed to be very painless to use.  Add the following to any
script or module where you want to log messages:

     use CGI::Log;

   The CGI::Log:: namespace has been aliased to Log:: in order to save a
bit of typing when adding debugging messages.  So, to add a debug message,
enter:

     Log->debug("Your message here.");
     ## note: this is equivalent to CGI::Log->debug();

   To add an error message:

     Log->error("Some information about the error goes here.");

   To add an success, or status message:

     Log->status("A status or informational message for the user.");
     Log->success("Something worked properly.");

   The following commands all retrieve the messages you've logged:

     @msg = Log->get_debug;
     @msg = Log->get_error;
     @msg = Log->get_error("UI");
     @msg = Log->get_status;
     @msg = Log->get_success;

   Note: All the get_* methods return array references when called in
scalar context.  e.g.

     $msg = Log->get_success;	## ref($msg) eq "ARRAY"

   During CGI/mod_perl development it is very handy to dump all of the
debugging messages at the bottom of the HTML page.  This is done with:

     Log->print;

   This can just be left at the bottom of your main script.  Logging can
be turned off (default is on), and when it is turned off Log->print()
doesn't do anything.

Types and Formats of Messages
-----------------------------

   Each of the four types of messages (debug, error, status, success) have
slightly different logic.  The differences are as follows:

   The debug messages are not designed to be visable by the user (and in
fact may be a security risk if you show the connection string for
databases, etc.)  The format of a debug message is:

     [caller:line [caller:line...]] message

     where:

     caller is a method name
     line is the line number from the method
     message is your debugging message

   An example will make this clearer:

     [file: test.pl]

     1:      use CGI::Log;
     2:      &foo;
     3:      sub foo
     4:      {
     5:            Log->debug("We are on line 5 of the method: foo");
     6:            &bar;
     7:      }
     8:      sub bar
     9:      {
     10:           Log->debug("line 10 method: bar process id: " . $$);
     11:           Log->error("Error on line 11 in the method: bar");
     12:     }
     13:     Log->print();

   When run it prints:

     -- DEBUG (test.pl) (pid: 3262) --
     [main:2 main::foo:5] We are on line 5 of the method: foo
     [main:2 main::foo:6 main::bar:10] line 10 method: bar process id: 456
     [ERROR] [main:2 main::foo:6 main::bar:11] This an error being called from the method: bar (No such file or directory)
     -- ERROR --
     [main:2 main::foo:6 main::bar:11] Error on line 11 in the method: bar (No such file or directory)

   (Note: the HTML in the output has been removed for clarity.)

   There are some things to note:

     Each debug message includes the context of how it came to be called.
     This allows for your debug messages to be very short - often just
     stating a simple fact such as "a is undefined" or showing the value
     of a variable.

     Error messages are duplicated in the error and debug arrays, so that
     you can determine how your error message got called, and its relation
     to any debugging messages.

     Error messages in the debug list have "[ERROR]" prepended to them.

     Error messages include the contents of the error variable $! in
     brackets.  This saves you from having to remember to include this
     variable in your error message.

   Log messages of type "status" and "success" are not manipulated or
modified.  Whatever you put in is what you get back.

   Log messages of type "error" are stored in two formats.  The first is
the format that in the output above.  The second is suitable for returning
to the user.  (It doesn't include the call trace.)  By default it includes
the error message from the variable $!.  If this is not desirable, call
Log->ui_no_error()

TIPS/TRICKS
===========

     It is nice to be able to add as many debugging messages without having
     to worry about slowing down your application when it gets deployed.
     Calling Log->debug_off will set the instance variable DEBUG_FLAG to
     undefined, and will prevent any messages in the current process from
     being stored.  e.g.

          if ($config{DEBUG} eq "Off")	## pretend %config holds global
          {				##   configuration info
          	Log->debug_off;
          }
          Log->debug("this debug message won't be saved because debugging is off.");

     Even though the debug() function won't do anything when debugging is
     turned off (it returns immediately), there is still the overhead of a
     function call for each debug message.  If you really want to get
     obsessive about performance you can try redefining the debug()
     method.  e.g.

          use CGI::Log;
          sub CGI::Log::debug () { 1 };		## redefine with prototype so it gets inlined
          					## note: I haven't tested the efficiency of this!
          					##
          					## note: prototypes are from perl 5.002 +

     It is very handy to be able to turn on debugging from the URL.  e.g.

          http://somewhere.com/cgi-bin/test.pl?debug=secret

     In your perl code you could have:

          if ($param{debug} ne "secret" 		## $param{debug} holds the CGI variable "debug"
          	|| $DEBUG != 1)			## $DEBUG is a config variable
          {
          	Log->debug_off();
          }

     This can be a huge timesaver if access to the webserver is difficult.
     This can be huge trouble if you have confidential or security related
     information in your debugging messages.  (That is why "debug" in the
     above example is the string "secret" and not "1" or something easy to
     guess.)

     You can add nice status messages to your web application by doing
     something like:

          if (Log->is_error)
          {
          	print "<font color=\"#ff0000\">ERROR</font><BR>\n";
          	for (Log->get_error) { print $_ . "<BR>\n"; }
          }
          elsif (Log->is_success)
          {
          	print "<img src=\"smiley_face.gif\">";
          	for (Log->get_success) { print $_ . "<BR>\n"; }
          }

          for (Log->get_status) { print $_ . "<BR>\n"; }

     Make sure you have "Log" and not "log" or you will get the run-time
     error:

          Can't take log of 0

     At the end of your script (whether a CGI or mod_perl) you will almost
     always want a:

          Log->clear;

   Documentation for CGI::Log was created by h2xs.

BUGS
====

   - too much noise in the debug call tracing under mod_perl. e.g.

     [main:0 (eval):0 Apache::Registry::handler:141 (eval):141 Apache::ROOT::perl::test_5flog_2epl::handler:16] debug message.

   - not thread-safe.

   - if you are using mod_perl and you do not remember to clean out the
log with Log->clean(), you will waste lots of memory.

   - CGI::Log takes the Log:: namespace by default.  This might be seen as
rude, or cause problems if it is already being used.  (Check if %Log:: is
defined???)

AUTHOR
======

   Jason Moore, 1998 <jmoore@sober.com>

SEE ALSO
========

   perl(1).

   modperl(1).

Error, log and debug streams, httpd style format
************************************************

NAME
====

   CGI::LogCarp - Error, log and debug streams, httpd style format

   CGI::LogCarp redefines the STDERR stream and allows the definition of
new STDBUG and STDLOG streams in such a way that all messages are
formatted similar to an HTTPD error log.

   Methods are defined for directing messages to STDERR, STDBUG, and
STDLOG.  Each stream can be directed to its own location independent of
the others.

   It can be used as a version-compatible drop-in replacement for the
CGI::Carp module.  This means that version 1.10 of CGI::LogCarp provides
the same functionality, usage, and features as at least version 1.10 of
CGI::Carp.

SYNOPSIS
========

     use CGI::LogCarp qw( :STDBUG fatalsToBrowser );

     print "CGI::LogCarp version: ", CGI::LogCarp::VERSION;
     DEBUGLEVEL 2;

     confess "It was my fault: $!";
     cluck "What's going on here?";

     warn "This is most unusual.";
     carp "It was your fault!";

     croak "We're outta here!";
     die "I'm dying.\n";

     debug "Just for debugging: somevar=", $somevar, "\n";
     logmsg "Just for logging: We're here.\n";
     trace "detail=", $detail, "\n";

     carpout \*ERRFILE;
     debugout \*DEBUGFILE;
     logmsgout \*LOGFILE;

     is_STDOUT(\*ERRFILE)
     is_STDERR(\*LOGFILE)
     is_STDBUG(\*LOGFILE)
     is_STDLOG(\*ERRFILE)

DESCRIPTION
===========

   CGI::LogCarp is a Perl package defining methods for directing the
existing STDERR stream as well as creating and directing two new messaging
streams, STDBUG and STDLOG.

   Their use was intended mainly for a CGI development environment, or
where separate facilities for errors, logging, and debugging output are
needed.

   This is because CGI scripts have a nasty habit of leaving warning
messages in the error logs that are neither time stamped nor fully
identified.  Tracking down the script that caused the error is a pain.
Differentiating debug output or activity logging from actual error
messages is a pain.  Logging application activity or producing debugging
output are quite different tasks than (ab)using the server's error log for
this purpose.  This module fixes all of these problems.

   Replace the usual

     use Carp;

   or

     use CGI::Carp;

   with

     use CGI::LogCarp;

   And the standard `warn()', `die()', `croak()', `confess()', `cluck()',
and `carp()' calls will automagically be replaced with methods that write
out nicely time-, process-, program-, and stream- stamped messages to the
STDERR, STDLOG, and STDBUG streams.

   The method to generate messages on the new STDLOG stream is `logmsg()'.
Calls to `logmsg()' will write out the same nicely time-, process-,
program-, and stream-stamped messages described above to both the STDLOG
and the STDBUG streams.

   The process number and the stream on which the message appeared is
embedded in the default message in order to disambiguate multiple
simultaneous executions as well as multiple streams directed to the same
location.

   Messages on multiple streams directed to the same location do not
receive multiple copies.

   Methods to generate messages on the new STDBUG stream are debug() and
`trace()'.

Creating the New Streams
------------------------

   In order to create the new streams, you must name them on the use line.
This is also referred to as importing a symbol. For example:

     use CGI::LogCarp qw( :STDERR :STDLOG :STDBUG );

   Note the :STDERR is not really necessary, as it is already defined in
perl.  Importing the :STDERR symbol will not generate an error.

   By default, the STDLOG stream is duplicated from the STDERR stream, and
the STDBUG stream is duplicated from the STDOUT stream.

Redirecting Error Messages
--------------------------

   By default, error messages are sent to STDERR. Most HTTPD servers
direct STDERR to the server's error log. Some applications may wish to
keep private error logs, distinct from the server's error log, or they may
wish to direct error messages to STDOUT so that the browser will receive
them (for debugging, not for public consumption).

   The `carpout()' method is provided for this purpose.

   Because `carpout()' is not exported by default, you must import it
explicitly by saying:

     use CGI::LogCarp qw( carpout );

   Note that for `carpout()', the STDERR stream is already defined, so
there is no need to explicitly create it by importing the STDERR symbol.
However,

     use CGI::LogCarp qw( :STDERR );

   will not generate an error, and will also import carpout for you.

   For CGI programs that need to send something to the HTTPD server's real
error log, the original STDERR stream has not been closed, it has been
saved as _STDERR. The reason for this is twofold.

   The first is that your CGI application might really need to write
something to the server's error log, unrelated to your own error log. To
do so, simply write directly to the _STDERR stream.

   The second is that some servers, when dealing with CGI scripts, close
their connection to the browser when the script closes either STDOUT or
STDERR. Some consider this a (mis)feature.

   Saving the program's initial STDERR in _STDERR is used to prevent this
from happening prematurely.

   Do not manipulate the _STDERR filehandle in any other way other than
writing to it.  For CGI applications, the `serverwarn()' method formats
and sends your message to the HTTPD error log (on the _STDERR stream).

Redirecting Log Messages
------------------------

   A new stream, STDLOG, can be defined and used for log messages.  By
default, STDLOG will be routed to STDERR. Most HTTPD servers direct STDERR
(and thus the default STDLOG also) to the server's error log.  Some
applications may wish to keep private activity logs, distinct from the
server's error log, or they may wish to direct log messages to STDOUT so
that the browser will receive them (for debugging, not for public
consumption).

   The `logmsgout()' method is provided for this purpose.

   Because `logmsgout()' is not exported by default, you must create the
STDLOG stream and import them explicitly by saying:

     use CGI::LogCarp qw( :STDLOG );

Redirecting Debug Messages
--------------------------

   A new stream, STDBUG, can be defined and used for debugging messages.
Since this stream is for producing debugging output, the default STDBUG
will be routed to STDOUT. Some applications may wish to keep private debug
logs, distinct from the application output, or CGI applications may wish
to leave debug messages directed to STDOUT so that the browser will
receive them (only when debugging).  Your program may also control the
output by manipulating DEBUGLEVEL in the application.

   The `debugout()' method is provided for this purpose.

   Because the `debugout()' method is not exported by default, you must
create the STDBUG stream and import them explicitly by saying:

     use CGI::LogCarp qw( :STDBUG );

Redirecting Messages in General
-------------------------------

   Each of these methods, `carpout()', `logmsgout()', and `debugout()',
requires one argument, which should be a reference to an open filehandle
for writing.  They should be called in a BEGIN block at the top of the
application so that compiler errors will be caught.

   This example creates and redirects the STDLOG stream, as well as
redirecting the STDERR stream to a browser, formatting the error message
as an HTML document:

     BEGIN {
         use CGI::LogCarp qw( :STDLOG fatalsToBrowser );
         # fatalsToBrowser doesn't stop messages going to STDERR,
         # rather it replicates them on STDOUT. So we stop them here.
         open(_STDERR,'>&STDERR'); close STDERR;
         open(LOG,">>/var/logs/cgi-logs/mycgi-log")
             or die "Unable to open mycgi-log: $!\n";
         logmsgout \*LOG;
     }

   NOTE: `carpout()', `logmsgout()', and `debugout()' handle file locking
on systems that support flock so multiple simultaneous CGIs are not an
issue.  However, flock might not operate as desired over network-mounted
filesystems.

   If you want to send errors to the browser, give `carpout()' a reference
to STDOUT:

     BEGIN {
       use CGI::LogCarp qw( carpout );
       carpout \*STDOUT;
     }

   If you do this, be sure to send a Content-Type header immediately -
perhaps even within the BEGIN block - to prevent server errors.  However,
you probably want to take a look at importing the `fatalsToBrowser' symbol
and closing STDERR instead of doing this.  See the example above on how to
do this.

Passing filehandles
-------------------

   You can pass filehandles to `carpout()', `logmsgout()', and `debugout()'
in a variety of ways. The "correct" way according to Tom Christiansen is
to pass a reference to a filehandle GLOB (or if you are using the
FileHandle module, a reference to a anonymous filehandle GLOB):

     carpout \*LOG;

   This looks a little weird if you haven't mastered Perl's syntax, so the
following syntaxes are accepted as well:

     carpout(LOG)          -or-  carpout(\LOG)
     carpout('LOG')        -or-  carpout(\'LOG')
     carpout(main::LOG)    -or-  carpout(\main::LOG)
     carpout('main::LOG')  -or-  carpout(\'main::LOG')
     ... and so on

   FileHandle and other objects work as well.

   Using `carpout()', `logmsgout()', and `debugout()', is not great for
performance, so they are recommended for debugging purposes or for
moderate-use applications. You can also manipulate DEBUGLEVEL to control
the output during the execution of your program.

Changing the Default Message Formats
------------------------------------

   By default, the messages sent to the respective streams are formatted
as helpful time-, process-, program-, and stream-stamped messages.

   The process number (represented in the example output below as $$) and
the stream on which the message appears are displayed in the default
message format and serve to disambiguate multiple simultaneous executions
as well as multiple streams directed to the same location.

   For example:

     [Mon Sep 15 09:04:55 1997] $$ test.pl ERR: I'm confused at test.pl line 3.
     [Mon Sep 15 09:04:55 1997] $$ test.pl BUG: answer=42.
     [Mon Sep 15 09:04:55 1997] $$ test.pl LOG: I did something.
     [Mon Sep 15 09:04:55 1997] $$ test.pl ERR: Got a warning: Permission denied.
     [Mon Sep 15 09:04:55 1997] $$ test.pl ERR: I'm dying.

   You can, however, redefine your own message formats for each stream if
you don't like this one by using the `set_message()' method.  This is not
imported by default; you should import it on the use() line like thus:

     use CGI::LogCarp qw( fatalsToBrowser set_message );
     # fatalsToBrowser doesn't stop messages going to STDERR,
     # rather it replicates them on STDOUT. So we stop them here.
     open(_STDERR,'>&STDERR'); close STDERR;
     set_message("It's not a bug, it's a feature!");

     use CGI::LogCarp qw( :STDLOG );
     set_message(STDLOG, "Control: I'm here.");

   Note the varying syntax for `set_message()'.

   The first parameter, if it is a filehandle, identifies the stream whose
message is being defined. Otherwise it specifies the message for the STDERR
stream. This non-filehandle first parameter form preserves compatibility
with CGI::Carp syntax.

   You may also pass in a code reference in order to create a custom error
message. At run time, your code will be called with the text of the error
message that caused the script

     BEGIN {
         use CGI::LogCarp qw( fatalsToBrowser set_message );
         # fatalsToBrowser doesn't stop messages going to STDERR,
         # rather it replicates them on STDOUT. So we stop them here.
         open(_STDERR,'>&STDERR'); close STDERR;
         sub handle_errors {
             my $msg = shift;
             $msg =~ s/\&/&amp;/gs;
             $msg =~ s/</&lt;/gs;
             $msg =~ s/>/&gt;/gs;
             $msg =~ s/"/&quot;/gs;
             join("\n",
                 "<h1>Aw shucks</h1>",
                 "Got an error:",
                 "<pre>", $msg, "</pre>",
             "");
         }
         set_message(\&handle_errors);
     }

   In order to correctly intercept compile-time errors, you should call
`set_message()' from within a BEGIN block.

Making perl Errors Appear in the Browser Window
-----------------------------------------------

   If you want to send fatal (die or `confess') errors to the browser, ask
to import the special `fatalsToBrowser' symbol:

     BEGIN {
         use CGI::LogCarp qw( fatalsToBrowser );
         # fatalsToBrowser doesn't stop messages going to STDERR,
         # rather it replicates them on STDOUT. So we stop them here.
         open(_STDERR,'>&STDERR'); close STDERR;
     }
     die "Bad error here";

   Fatal errors will now be sent to the browser. Any messages sent to the
STDERR stream are now *also* reproduced on the STDOUT stream.  Using
`fatalsToBrowser' also causes CGI::LogCarp to define a new message format
that arranges to send a minimal HTTP header and HTML document to the
browser so that even errors that occur early in the compile phase will be
shown. Any fatal (die) and nonfatal (warn) messages are *still* produced
on the STDERR stream. They just also go to STDOUT.

   Certain web servers (Netscape) also send CGI STDERR output to the
browser.  This causes a problem for CGI's because the STDERR stream is not
buffered, and thus if something gets sent to the STDERR stream before the
normal document header is produced, the browser will get very confused.

   The following line solves this problem. See above for examples with
context.

     open(_STDERR,'>&STDERR'); close STDERR;

Changing the fatalsToBrowser message format or document
-------------------------------------------------------

   The default message generated by `fatalsToBrowser' is not the normal
`LogCarp' logging message, but instead displays the error message followed
by a short note to contact the Webmaster by e-mail with the time and date
of the error. You can use the `set_message()' method to change it as
described above.

   The default message generated on the STDLOG and STDBUG streams is
formatted differently, and is as described earlier.

What are the Carp methods?
--------------------------

   The Carp methods that are replaced by CGI::LogCarp are useful in your
own modules, scripts, and CGI applications because they act like `die()'
or `warn()', but report where the error was in the code they were called
from.  Thus, if you have a routine `Foo()' that has a `carp()' in it, then
the `carp()' will report the error as occurring where `Foo()' was called,
not where `carp()' was called.

Forcing a Stack Trace
---------------------

   As a debugging aid, you can force `LogCarp' to treat a croak as a
`confess' and a carp as a `cluck' across all modules.  In other words,
force a detailed stack trace to be given.  This can be very helpful when
trying to understand why, or from where, a warning or error is being
generated.

   This feature is enabled by 'importing' the non-existant symbol
'verbose'. You would typically enable it on the command line by saying:

     perl -MCGI::LogCarp=verbose script.pl

   or by including the string `MCGI::LogCarp=verbose' in the PERL5OPT
environment variable.

   You would typically enable it in a CGI application by saying:

     use CGI::LogCarp qw( verbose );

   Or, during your program's run by saying:

     CGI::LogCarp::import( 'verbose' );

   and calling `CGI::LogCarp''s import function directly.

   NOTE: This is a feature that is in Carp but apparently was not
implemented in CGI::Carp (as of v1.10).

METHODS
=======

   Unless otherwise stated all methods return either a true or false value,
with true meaning that the operation was a success.  When a method states
that it returns a value, failure will be returned as undef or an empty
list.

Streams and their methods
-------------------------

   The following methods are for generating a message on the respective
stream:

     The  STDERR stream: warn() and die()
     The  STDLOG stream: logmsg()
     The  STDBUG stream: debug() and trace()
     The _STDERR stream: serverwarn()

   The following methods are for generating a message on the respective
stream, but will indicate the message location from the caller's
perspective.  See the standard Carp.pm module for details.

     The STDERR stream: carp(), croak(), cluck() and confess()

   The following methods are for manipulating the respective stream:

     The STDERR stream: carpout()
     The STDLOG stream: logmsgout()
     The STDBUG stream: debugout()

   The following methods are for manipulating the amount (or level) of
output filtering on the respective stream:

     The STDBUG stream: DEBUGLEVEL()
     The STDLOG stream: LOGLEVEL()

   The following method defines the format of messages directed to a
stream.  Often used by and/or in conjunction with `fatalsToBrowser':

     set_message()

Exported Package Methods
------------------------

   By default, the only methods exported into your namespace are:

     warn, die, carp, croak, confess, and cluck

   When you import the :STDBUG tag, these additional symbols are exported:

     *STDBUG, debugmsgout, debug, trace, and DEBUGLEVEL

   When you import the :STDLOG tag, these additional symbols are exported:

     *STDLOG, logmsgout, logmsg and LOGLEVEL

   When you import the :STDERR tag, these additional symbols are exported:

     carpout

   These additional methods are not exported by default, and must be named:

     carpout, logmsgout, debugout, set_message

   The following are pseudo-symbols, in that they change the way
CGI::LogCarp works, but to not export any symbols in and of themselves.

     verbose, fatalsToBrowser

Internal Package Methods
------------------------

   The following methods are not exported but can be accessed directly in
the CGI::LogCarp package.

   The following methods are for comparing a filehandle to the respective
stream:

     is_STDOUT()
     is_STDERR()
     is_STDBUG()
     is_STDLOG()
     is_realSTDERR()

   Each is explained in its own section below.

Exported Package Variables
--------------------------

   No variables are exported into the caller's namespace.  However, the
STDLOG and STDBUG streams are defined using typeglobs in the main
namespace.

Internal Package Variables
--------------------------

$DEBUGLEVEL
     A number indicating the level of debugging output that is to occur.
     At each increase in level, additional debugging output is allowed.

     Currently three levels are defined:

          0 - No messages are output on the STDBUG stream.
          1 - debug() messages are output on the STDBUG stream.
          2 - debug() and trace() messages are output on the STDBUG stream.

     It is recommended to use the DEBUGLEVEL method to get/set this value.

$LOGLEVEL
     A number indicating the level of logging output that is to occur.  At
     each increase in level, additional logging output is allowed.

     Currently two levels are defined:

          0 - No messages are output on the STDLOG stream.
          1 - logmsg() messages are output on the STDLOG stream.

     It is recommended to use the LOGLEVEL method to get/set this value.

RETURN VALUE
============

   The value returned by executing the package is 1 (or true).

ENVIRONMENT
===========

FILES
=====

ERRORS
======

WARNINGS
========

   Operation on Win32 platforms has not been tested.

   CGI::Carp has some references to a wrap import symbol, which appears to
be an alternate name for `fatalsToBrowser'.  Internal comments refer to
errorWrap. Since this is poorly documented, I am speculating this is
legacy and/or previous implementation coding, and as such, have chosen not
implement the wrap symbol import in `CGI::LogCarp'. If some massively
popular module(s) I am currently unaware of is/are indeed using this
undocumented interface, please let me know.

DIAGNOSTICS
===========

   See importing the verbose pseudo-symbol in Forcing a Stack Trace.

BUGS
====

   Check out what's left in the TODO file.

RESTRICTIONS
============

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

CPAN DEPENDENCIES
=================

LOCAL DEPENDENCIES
==================

SEE ALSO
========

   Carp, CGI::Carp

NOTES
=====

   carpout(), debugout(), and logmsgout() now perform file locking.

   I've attempted to track the features in `CGI::LogCarp' to the features
in the CGI::Carp module by Lincoln Stein. The version number of
`CGI::LogCarp' corresponds to the highest version of CGI::Carp module that
this module replicates all features and functionality. Thus version 1.10
of `CGI::LogCarp' can be used as a drop-in replacement for versions 1.10
or lower of CGI::Carp.

   Due to the implementation of the Symbol.pm module, I have no choice but
to replace it with a version that supports extending the list of "global"
symbols. It is part of the CGI::LogCarp distribution.

   For speed reasons, the autoflush method is implemented here instead of
pulling in the entire FileHandle module.

ACKNOWLEDGEMENTS
================

   Based heavily on the CGI::Carp module by Lincoln D. Stein (
lstein@genome.wi.mit.edu ).  Thanks to Andy Wardley ( abw@kfs.org ) for
commenting the original Carp.pm module.

   Thanks to Michael G Schwern ( schwern@starmedia.net ) for the
constructive input.

AUTHOR(S)
=========

   mak - Michael King ( mike808@mo.net )

HISTORY
=======

     CGI::LogCarp.pm
     v1.01 09/15/97 mak
     v1.12 08/14/98 mak

CHANGE LOG
==========

     1.05 first posting to CPAN
     1.12 major revision, tracking CGI::Carp

MODIFICATIONS
=============

COPYRIGHT
=========

     Copyright (C) 1997,1998 Michael King ( mike808@mo.net )
     Saint Louis, MO USA.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   This module is copyright (c) 1997,1998 by Michael King ( mike808@mo.net
) and is made available to the Perl public under terms of the Artistic
License used to cover Perl itself. See the file Artistic in the
distribution  of Perl 5.002 or later for details of copy and distribution
terms.

AVAILABILITY
============

   The latest version of this module is likely to be available from:

     http://walden.mo.net/~mike808/LogCarp

   The best place to discuss this code is via email with the author.

PACKAGE PUBLIC METHODS
======================

DEBUGLEVEL $LEVEL
-----------------

   DEBUGLEVEL is a normal get/set method.

   When the scalar argument LEVEL is present, the DEBUGLEVEL will be set
to LEVEL.  LEVEL is expected to be numeric, with the following
case-insensitive character-valued translations:

     NO,  FALSE, and OFF all equate to a value of 0 (ZERO).
     YES, TRUE,  and ON  all equate to a value of 1 (ONE).
     TRACE or TRACING equate to a value of 2 (TWO).

     Values in scientific notation equate to their numeric equivalent.

   NOTE:

     All other character values of LEVEL equate to 0 (ZERO). This
     will have the effect of turning off debug output.

   After this translation to a numeric value is performed, the DEBUGLEVEL
is set to LEVEL.

   Whenever the DEBUGLEVEL is set to a non-zero value (i.e. ON or TRACE),
the LOGLEVEL will be also set to 1 (ONE).

   The value of DEBUGLEVEL is then returned to the caller, whether or not
LEVEL is present.

LOGLEVEL $LEVEL
---------------

   LOGLEVEL is a normal get/set method.

   When the scalar argument LEVEL is present, the LOGLEVEL will be set to
LEVEL.  LEVEL is expected to be numeric, with the following
case-insensitive character-valued translations:

     NO,  FALSE, and OFF all equate to a value of 0 (ZERO).
     YES, TRUE,  and ON  all equate to a value of 1 (ONE).

     Values in scientific notation equate to their numeric equivalent.

   NOTE:

     All other character values of LEVEL equate to 0 (ZERO). This
     will have the effect of turning off log output.

   After this translation to a numeric value is performed, the LOGLEVEL is
set to LEVEL.

   The value of LOGLEVEL is then returned to the caller, whether or not
LEVEL is present.

warn @message
-------------

   This method is a replacement for Perl's builtin `warn()'.  The message
is sent to the STDERR, STDLOG, and STDBUG streams.

die @message
------------

   This method is a replacement for Perl's builtin `die()'.  The message
is sent to the STDERR, STDLOG, and STDBUG streams.

carp @message
-------------

   This method is a replacement for `Carp::carp()'.  The message is sent
to the STDERR, STDLOG, and STDBUG streams.

   # mak - this fixes a problem when you passed Carp::carp a list # like
the documentation says ( shortmess uses $_[0] and not @_ ).  # This has
been fixed in later (post-1997) versions of Carp.pm.  # Since Carp.pm has
no version, I can't tell which one you have.

croak @message
--------------

   This method is a replacement for `Carp::croak()'.  The message is sent
to the STDERR, STDLOG, and STDBUG streams.

   # mak - this fixes a problem when you passed Carp::croak a list # like
the documentation says ( shortmess uses $_[0] and not @_ ).  # This has
been fixed in later (post-1997) versions of Carp.pm.  # Since Carp.pm has
no version, I can't tell which one you have.

confess @message
----------------

   This method is a replacement for `Carp::confess()'.  The message is
sent to the STDERR, STDLOG, and STDBUG streams.

cluck @message
--------------

   This method is a replacement for `Carp::cluck()'.  The message is sent
to the STDERR, STDLOG, and STDBUG streams.

set_message $message
--------------------

set_message FILEHANDLE $message
-------------------------------

   This method is a replacement for the CGI::Carp method of the same name.
It defines the message format for the STDERR stream if FILEHANDLE is not
specified. FILEHANDLE specifies which stream is having its message
redefined. `$message' is typically a reference to a subroutine.

logmsg @message
---------------

   This method operates similarly to the `warn()' method.  The message is
sent to the STDLOG and STDBUG streams.

debug @message
--------------

   This method operates similarly to the `warn()' method.  The message is
sent to the STDBUG stream when DEBUGLEVEL > 0.

trace @message
--------------

   This method operates similarly to the `warn()' method.  The message is
sent to the STDBUG stream when DEBUGLEVEL is greater than one.

serverwarn @message
-------------------

   This method operates similarly to the `warn()' method.  The message is
sent to the STDBUG, STDLOG, STDERR and _STDERR streams.  The _STDERR
stream is typically is sent to a webserver's error log if used in a CGI
program.

carpout FILEHANDLE
------------------

   A method to redirect the STDERR stream to the given FILEHANDLE.  It
accepts FILEHANDLE as a reference or a string.

   See the section on REDIRECTING ERROR MESSAGES and the section on
*REDIRECTING MESSAGES IN GENERAL*.

logmsgout FILEHANDLE
--------------------

   A method to redirect the STDLOG stream to the given FILEHANDLE.  It
accepts FILEHANDLE as a reference or a string.

   See the section on REDIRECTING ERROR MESSAGES and the section on
*REDIRECTING MESSAGES IN GENERAL*.

debugout FILEHANDLE
-------------------

   A method to redirect the STDBUG stream to the given FILEHANDLE.  It
accepts FILEHANDLE as a reference or a string.

   See the section on REDIRECTING ERROR MESSAGES and the section on
*REDIRECTING MESSAGES IN GENERAL*.

to_filehandle EXPR
------------------

   Borrowed directly from CGI.pm by Lincoln Stein.  It converts EXPR to a
filehandle.

is_STDOUT FILEHANDLE
--------------------

   This method compares FILEHANDLE with the STDOUT stream and returns the
boolean result.

   This method is not exported by default.

is_STDERR FILEHANDLE
--------------------

   This method compares FILEHANDLE with the STDERR stream and returns the
boolean result.

   This method is not exported by default.

is_STDBUG FILEHANDLE
--------------------

   This method compares FILEHANDLE with the STDBUG stream and returns the
boolean result.

   This method is not exported by default.

is_STDLOG FILEHANDLE
--------------------

   This method compares FILEHANDLE with the STDLOG stream and returns the
boolean result.

   This method is not exported by default.

is_realSTDERR FILEHANDLE
------------------------

   This method compares FILEHANDLE with the _STDERR stream and returns the
boolean result.

   This method is not exported by default.

PRIVATE METHODS
===============

realwarn @MESSAGE
-----------------

   This private method encapsulates Perl's underlying `warn()' method,
actually producing the message on the STDERR stream.  Locking is performed
to ensure exclusive access while appending.

   This method is not exportable.

realdie @MESSAGE
----------------

   This private method encapsulates Perl's underlying `die()' method,
actually producing the message on the STDERR stream and then terminating
execution.  Locking is performed to ensure exclusive access while
appending.

   This method is not exportable.

reallog @MESSAGE
----------------

   This private method synthesizes an underlying `logmsg()' method,
actually producing the message on the STDLOG stream.  Locking is performed
to ensure exclusive access while appending.  The message will only be sent
when LOGLEVEL is greater than zero.

   This method is not exportable.

realbug @message
----------------

   This private method synthesizes an underlying debug() method, actually
producing the message on the STDBUG stream.  Locking is performed to
ensure exclusive access while appending.  The message will only be sent
when DEBUGLEVEL is greater than zero.

   This method is not exportable.

realserverwarn @message
-----------------------

   This private method synthesizes an underlying `serverwarn()' method,
actually producing the message on the _STDERR stream.  Locking is
performed to ensure exclusive access while appending.  This stream is
typically directed to the webserver's error log if used in a CGI program.

   This method is not exportable.

id $level
---------

   This private method returns the file, line, and basename of the
currently executing function.

   This method is not exportable.

stamp $stream_id
----------------

   A private method to construct a normalized timestamp prefix for a
message.

   This method is not exportable.

streams_are_equal FILEHANDLE, FILEHANDLE
----------------------------------------

   This private method compares two FILEHANDLE streams to each other and
returns the boolean result.

   This method is not exportable.

   Note: This function is probably not portable to non-Unix-based
operating systems (i.e. NT, VMS, etc.).

lock FILEHANDLE
---------------

   A private method that uses Perl's builtin flock() and `seek()' to
obtain an exclusive lock on the stream specified by FILEHANDLE.  A lock is
only attempted on actual files that are writeable.

   This method is not exportable.

unlock FILEHANDLE
-----------------

   A private method that uses Perl's builtin flock() to release any
exclusive lock on the stream specified by FILEHANDLE.  An unlock is only
attempted on actual files that are writeable.

   This method is not exportable.

Adds to CGI::Base the ability for a CGI script to become a mini http server.
****************************************************************************

NAME
====

   CGI::MiniSvr - Adds to CGI::Base the ability for a CGI script to become
a mini http server.

SYNOPSIS
========

     use CGI::MiniSvr;

     $cgi = new CGI::MiniSvr;
     $cgi = new CGI::MiniSvr $port_or_path;
     $cgi = new CGI::MiniSvr $port_or_path, $timeout_mins;

     $cgi->port;               # return MiniSvr port number with leading colon

     $cgi->spawn;              # fork/detach from httpd

     $cgi->get;                # get input

     $cgi->pass_thru($host, $port);
     $cgi->redirect($url);

     $cgi->done;               # end 'page' and close connection (high-level)
     $cgi->close;              # just close connection (low-level)

   See also the CGI::Base methods.

DESCRIPTION
===========

   This file implements the CGI::MiniSvr object. This object represents an
alternative interface between the application and an HTTP deamon.

   In a typical CGI scenario the interface is just a collection of
environment variables passed to a process which then generated some outout
and exits. The CGI::Base class implements this standard interface.

   The CGI::MiniSvr class inherits from CGI::Base and extends it to
implement a 'mini http daemon' which can be spawned (forked) from a CGI
script in order to maintain state information for a client 'session'.

   This is very useful. It neatly side-steps many of the painful issues
involved in writing real-world multi-screen applications using the
standard CGI interface (namely saving and restoring state between screens).

   Another use for the MiniSvr is to allow cgi scripts to produce output
pages with dynamically generated in-line graphics (for example). To do
this the script would spawn a MiniSvr and refer to its port number in the
URL's for the embedded images. The MiniSvr would then sit on the port,
with a relatively short timeout, ready to serve the requests for those
images.  Once all the images have been served the MiniSvr would simply
exit.

   Like the CGI::Base module the CGI::MiniSvr module does not do any
significant data parsing. Higher level query processing (forms etc) is
performed by the CGI::Request module.

   Note that the implementation of these modules means that you should
invoke `new CGI::Base;' before `new CGI::MiniSvr;'. This is the natural
order anyway and so should not be a problem.

WARNING!
--------

   This module is not a good solution to many problems! It is only a good
solution to some. It should only be used by those who understand why it is
not a good solution to many problems!

   For those who don't see the pitfalls of the mini server approach,
consider just this one example:  what happens to your machine if new
'sessions' start, on average, faster than abandoned ones timeout?

   Security and short-lifespan URL's are some of the other problems.

   If in doubt don't use it! If you do then don't blame me for any of the
problems you may (will) experience. *You have been warned!*

DIRECT ACCESS USAGE
-------------------

   In this mode the MiniSvr creates an internet domain socket and returns
to the client a page with URL's which contain the MiniSvr's own port
number.

     $q = GetRequest();      # get initial request
     $cgi = new CGI::MiniSvr;# were going to switch to CGI::MiniSvr later
     $port = $cgi->port;     # get our port number (as ':NNNN') for use in URL's
     $me = "http://$SERVER_NAME$port$SCRIPT_NAME"; # build my url
     print "Hello... <A HREF="$me?INSIDE"> Step Inside ...</A>\r\n";
     $cgi->done(1);          # flush out page, include debugging
     $cgi->spawn and exit 0; # fork, original cgi process exits
     CGI::Request::Interface($cgi); # default to new interface

     while($q = GetQuery() or $cgi->exit){ # await request/timeout
        ...
     }

INDIRECT ACCESS USAGE
---------------------

   In this mode the MiniSvr creates a unix domain socket and returns to the
client a page with a hidden field containing the path to the socket.

     $q = GetRequest(); # get initial request
     $path = $q->param('_minisvr_socket_path');
     if ($path) {
         # just pass request on to our mini server
         $q->cgi->pass_thru('', $path) or (...handle timeout...)
         $q->cgi->done;
     } else {
         # launch new mini server
         $path = "/tmp/cgi.$$";
         $cgi = new CGI::MiniSvr $path; # unix domain socket
         # code here mostly same as 'DIRECT ACCESS' above except that
         # the returned page has an embedded field _minisvr_socket_path
         # set to $path
         ...
     }

SUBCLASSING THE MINISVR
-----------------------

   In some cases you may wish to have more control over the behaviour of
the mini-server, such as handling some requests at a low level without
disturbing the application.  Subclassing the server is generally a good
approach. Use something like this:

     #   Define a specialised subclass of the MiniSvr for this application
     {
       package CGI::MiniSvr::FOO;
       use CGI::MiniSvr;
       @ISA = qw(CGI::MiniSvr);

     # Default behaviour for everything except GET requests for .(gif|html|jpg)
     # Note that we must take great care not to: a) try to pass_thru to ourselves
     # (it would hang), or b) pass_thru to the server a request which it will
     # try to satisfy by starting another instance of this same script!

     sub method_GET {
         my $self = shift;
         if ($self->{SCRIPT_NAME} =~ m/\.(gif|jpg|html)$/){
             $self->pass_thru('', $self->{ORIG_SERVER_PORT});
             $self->done;
             return 'NEXT';
         }
         1;
     }
     # ... other overriding methods can be defined here ...
       }

   Once defined you can use your new customised mini server by changing:

     $cgi = new CGI::MiniSvr;

   into:

     $cgi = new CGI::MiniSvr::FOO;

   With the example code above any requests for gif, jpg or html will be
forwarded to the server which originally invoked this script. The
application no longer has to deal with them. Note: this is just an example
usage for the mechanism, you would typically generate pages in which any
embedded images had URL's which refer explicitly to the main httpd.

   With a slight change in the code above you can arrange for the handling
of the pass-thru to occur in a subprocess. This frees the main process to
handle other requests. Since the MiniSvr typically only exists for one
process, forking off a subprocess to handle a request is only useful for
browsers such as Netscape which make multiple parallel requests for inline
images.

     if ($self->{SCRIPT_NAME} =~ m/\.(gif|html|jpg)$/){
         if ($self->fork == 0) {
             $self->pass_thru('', $self->{ORIG_SERVER_PORT});
             $self->exit;
         }
         $self->done;
         return 'NEXT';
     }

   Note that forking can be expensive. It might not be worth doing for
small images.

FEATURES
--------

   Object oriented and sub-classable.

   Transparent low-level peer validation (no application involvement but
extensible through subclassing).

   Transparent low-level pass_thru/redirecting of URL's the application is
not interested in  (no application involvement but extensible through
subclassing).

   Effective timeout mechanism with default and per-call settings.

   Good emulation of standard CGI interface (for code portability).

RECENT CHANGES
--------------

  1. and 2.3 Slightly improved documentation. Added a basic fork() method.
     Fixed timeout to throw an exception so it's reliable on systems which
     restart system calls. Socket/stdio/filehandle code improved. Cleaned
     up done/close relationship. Added experimental support for optionally
     handling requests by forking on a case-by-case basis. This is handy
     for serving multiple simultaneous image requests from Netscape for
     example.  Added notes about the MiniSvr, mainly from discussions with
     Jack Shirazi Removed old explicit port searching code from
     _new_inet_socket().  Improved SIGPIPE handling (see CGI::Base).

  2. Fixed (worked around) a perl/stdio bug which affected POST handling.
     Changed some uses of map to foreach. Slightly improved debugging.
     Added support for any letter case in HTTP headers. Enhanced test code.

  3. Added more documentation and examples. The max pending connections
     parameter for listen() can now be specified as a parameter to new().
     SIGPIPE now ignored by default. Simplified inet socket code with ideas
     from Jack Shirazi. Improved server Status-Line header handling. Fixed
     validate_peer() error handling and redirect().  Simplified get_vars()
     by splitting into get_valid_connection() and read_headers(). Moved
     example method_GET() out of MiniSvr and into the test script.

     The module file can be run as a cgi script to execute a demo/test. You
     may need to chmod +x this file and teach your httpd that it can
     execute *.pm files.

  4. Added note about possible use of MiniSvr to serve dynamically
     generated in-line images. Added optional DoubleFork mechanism to
     spawn which might be helpful for buggy httpd's, off by default.

  5. Added support for an 'indirect, off-net, access' via a local UNIX
     domain socket in the file system. Now uses strict. ORIG_* values now
     stored within object and not exported as globals (Base CGI vars
     remain unchanged).  See CGI::Base for some more details.

FUTURE DEVELOPMENTS
-------------------

   Full pod documentation.

   None of this is perfect. All suggestions welcome.

   Test unix domain socket mechanism.

   Issue/problem - the handling of headers. Who outputs them and when? We
have a sequence of: headers, body, end, read, headers, body, end, read
etc. The problem is that a random piece of code can't tell if the headers
have been output yet. A good solution will probably have to wait till we
have better tools for writing HTML and we get away from pages of print
statements.

   A method for setting PATH_INFO and PATH_TRANSLATED to meaningful values
would be handy.

AUTHOR, COPYRIGHT and ACKNOWLEDGEMENTS
--------------------------------------

   This code is Copyright (C) Tim Bunce 1995. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

   This module includes ideas from Pratap Pereira
<pereira@ee.eng.ohio-state.edu>, Jack Shirazi <js@biu.icnet.uk> and others.

   IN NO EVENT SHALL THE AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT,
INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OF THIS SOFTWARE AND ITS DOCUMENTATION (INCLUDING, BUT NOT LIMITED TO,
LOST PROFITS) EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

SEE ALSO
--------

   CGI::Base, CGI::Request, URI::URL

SUPPORT
-------

   Please use comp.infosystems.www.* and comp.lang.perl.misc for support.
Please do _NOT_ contact the author directly. I'm sorry but I just don't
have the time.

A lightweight CGI form processing pacakge
*****************************************

NAME
====

   CGI::Minimal - A lightweight CGI form processing pacakge

SYNOPSIS
========

     use CGI::Minimal;

     my $cgi = CGI::Minimal->new;
     if ($cgi->truncated) {
        &scream_about_bad_form;
        exit;
     }
     my ($form_field_value) = $cgi->param('some_field_name');

DESCRIPTION
===========

   Provides a micro-weight alternative to the CPAN CGI.pm module

   Rather than attempt to address every possible need of a CGI programmer,
it provides the _minimum_ functions needed for CGI such as form decoding
(including file upload forms), URL encoding and decoding, HTTP usable date
generation (RFC1123 compliant dates) and _basic_ escaping and unescaping
of HTMLized text.

   The form decoding interface is somewhat compatible with the CGI.pm
module. No provision is made for generating HTTP or HTML on your behalf -
you are expected to be conversant with how to put together any HTML or
HTTP you need.

CHANGES
=======

     1.06 10 April 2000 - 'Unfixed' use of 'quotemeta' for multipart
                           boundaries. 'split' is doing the 'wrong thing'
                           according to the specs...

     1.05 03 April 2000 - Fixed breakage in 'param;' from 1.04 changes

     1.04 03 April 2000 - Added capability to set params via the param() method
                          like 'CGI.pm' plus general code cleanup

     1.03 02 March 2000 - 'mod_perl' compatibility added

     1.02 09 June 1999  - Initial public release.

METHODS
=======

new;
     Creates a new instance of the CGI::Minimal object and decodes any
     type of form (GET/POST). Only one 'true' object is generated - all
     subsequent calls return an alias of the one object (a 'Singleton'
     pattern).

     Example:

          use CGI::Minimal;

          my $cgi = CGI::Minimal->new;

param([$fieldname]);
     Called as `$cgi->param();' it returns the list of all defined form
     fields in the same order they appear in the data from the user agent.

     Called as `$cgi->param($fieldname);' it returns the value (or array
     of values for multiple occurances of the same field name) assigned to
     that $fieldname. If there is more than one value, the values are
     returned in the same order they appeared in the data from user agent.

     Examples:

          my (@form_fields) = $cgi->param;

          my (@multi_pick_field) = $cgi->param('pick_field_name');

          my ($form_field_value) = $cgi->param('some_field_name');

     You can also use the param method to set param values to new values.
     These values will be returned by any invokation of a CGI::Minimal
     object as if they had been found in the original passed data.

     Examples:

          $cgi->param( 'name' => 'Joe Shmoe' );

          $cgi->param({ 'name' => 'Joe Shmoe', 'birth_date' => '06/25/1966' });

          $cgi->param({ 'pick_list' => ['01','05','07'] });

param_mime([$fieldname]);
     Called as `$cgi->param_mime();' it returns the list of all defined
     form fields in the same order they appear in the data from the user
     agent.

     Called as `$cgi->param_mime($fieldname);' it returns the MIME type
     (or array of MIME types for multiple occurances of the same field
     name) assigned to that $fieldname. If there is more than one value,
     the values are returned in the same order they appeared in the data
     from user agent.

     This is only meaningful when doing Form Based File Uploads and should
     probably not be trusted even then since it depends on the _browser_
     correctly identifying what it is sending.

param_filename([$fieldname]);
     Called as `$cgi->param_filename();' it returns the list of all
     defined form fields in the same order they appear in the data from the
     user agent.

     Called as `$cgi->param_filename($fieldname);' it returns the file
     name (or array of file names for multiple occurances of the same field
     name) assigned to that $fieldname. If there is more than one value,
     the values are returned in the same order they appeared in the data
     from user agent.

     This is only meaningful when doing Form Based File Uploads.

date_rfc1123($time);
     Takes a unix time tick value and returns a RFC1123 compliant date as
     a formatted text string suitable for direct use in Expires,
     Last-Modified or other HTTP headers (with the exception of
     'Set-Cookie', which requires a different format not generated here.
     See 'CGI::Cookie' for cookie generation).

     Example:

          print "Expires: ",$cgi->date_rfc1123(time + 3600),"\015\012";

calling_parms_table;
     Returns a formatted HTML table containing all the form and environment
     variables for debugging purposes

     Example:

          print $cgi->calling_parms_table;

url_encode($string);
     Returns URL encoding of input string (URL unsafe codes are escaped to
     %xx form)

     Example:

          my $url_encoded_string = $cgi->url_encode($string);

url_decode($string);
     Returns URL *decoding* of input string (%xx substitutions are decoded
     to their actual values).

     Example:

          my $url_decoded_string = $cgi->url_decode($string);

htmlize($string);
     Returns HTML 'safe' encoding of input string. Replaces &,>,< and "
     with their named entity codes (&amp, &gt; &lt; and &quot;)

     Example:

          my $html_escaped_string = $cgi->htmlize($string);

dehtmlize($string);
     Undoes basic HTML encoding of input string. Replaces &amp;, &gt;,
     &lt; and &quot; named entity codes with their actual values.  NOT a
     general purpose entity decoder.

truncated;
     Returns '1' if the read form was shorter than the Content-Length that
     was specified by the submitting user agent (ie the data from a form
     uploaded by a web browser was cut off before all the data was
     received).

     Returns '0' if the form was NOT truncated.

     Example:

          use CGI::Minimal;

          my $cgi = CGI::Minimal->new;
          if ($cgi->truncated) {
            &bad_form_upload;
          } else {
            &good_form_upload;
          }

     'truncated' will also return '1' if the form length received would
     have exceeded the set 'max_read_length'.

CGI::Minimal::max_read_size($size);
     Sets the maximum number of bytes/octets that the CGI decoder will
     accept. By default, 1000000 bytes/octets.  This must be called
     *BEFORE* calling 'new' for the first time for it to actually affect
     form decoding.

     Example:

          use CGI::Minimal;

          CGI::Minimal::max_read_size(1000000);
          my $cgi = CGI::Minimal->new;

BUGS
====

   None known.

TODO
====

   Who knows?

AUTHORS
=======

   Benjamin Franz <snowhare@nihongo.org>

VERSION
=======

   Version 1.06 April 2000

COPYRIGHT
=========

   Copyright (c) Benjamin Franz 1999,2000. All rights reserved.

     This program is free software; you can redistribute it
     and/or modify it under the same terms as Perl itself.

SEE ALSO
========

   CGI

Sniff out various versions of browsers claming to be "Mozilla".
***************************************************************

NAME
====

   *MozSniff* - Sniff out various versions of browsers claming to be
"Mozilla".

SYNOPSIS
========

   I got tired of redoing this several times, or using CGI::user_agent(),
so I wrote my own.

DESCRIPTION
===========

   You should be able, I hope, to do something like:

     use CGI::MozSniff;
     my $foo = new CGI::MozSniff;
     my $bar = $foo->sniff;

   Values for $foo->sniff are:

   * navigator_*$ver* - Netscape Navigator v.*$ver*

   * communicator_*$ver* - Netscape Communicator v.*$ver*

   * msie_*$ver* - Microsoft Internet Explorer v.*$ver*

   * msie_*$ver*_AOL - Microsoft Internet Explorer v.*$ver* (AOL)

   * opera_*$ver* - Opera, a pretty nice browser, as far as Windoze
     browsers go...

   * other - Some other browser

buffer output when building CGI programs
****************************************

NAME
====

   CGI::Out - buffer output when building CGI programs

SYNOPSIS
========

     use CGI;
     use CGI::Out;

     $query = new CGI;
     savequery $query;		# to reconstruct input

     $CGI::Out::mailto = 'fred';	# override default of $<

     out $query->header();
     out $query->start_html(
     	-title=>'A test',
     	-author=>'muir@idiom.com');

     croak "We're outta here!";
     confess "It was my fault: $!";
     carp "It was your fault!";
     warn "I'm confused";
     die  "I'm dying.\n";

     use CGI::Out qw(carpout $out);
     carpout(\*LOG);
     $CGI::Out::$out			# is the buffer

DESCRIPTION
===========

   This is a helper routine for building CGI programs.  It buffers stdout
until you're completed building your output.  If you should get an error
before you are finished, then it will display a nice error message (in
HTML), log the error, and send email about the problem.

   It wraps all of the functions provided by CGI::Carp and Carp.  Do not
"use" them directly, instead just "use CGI::Out".

   Instead of print, use out.

AUTHOR
======

   David Muir Sharnoff <muir@idiom.com>

SEE ALSO
========

   Carp, CGI::Carp, CGI, CGI::Wrap

BUGS
====

   No support for formats is provided by CGI::Out.

A lightweight CGI processing package for using PATH_INFO like GET method form parameters
****************************************************************************************

NAME
====

   CGI::PathInfo - A lightweight CGI processing package for using
PATH_INFO like GET method form parameters

SYNOPSIS
========

     use CGI::PathInfo;

     my $path_info = CGI::PathInfo->new;
     my ($form_field_value) = $path_info->param('some_field_name');

DESCRIPTION
===========

   Provides a micro-weight equivalent to the CPAN CGI.pm module that
permits the use of the Apache CGI environment variable 'PATH_INFO' as a
functional equivalent to the GET method 'QUERY_STRING'.

   Rather than attempt to address every possible need of a CGI programmer,
it provides the _minimum_ functions needed for CGI such as parameter
decoding, URL encoding and decoding.

   The parameters decoding interface is somewhat compatible with the
CGI.pm module. No provision is made for generating HTTP or HTML on your
behalf - you are expected to be conversant with how to put together any
HTML or HTTP you need.

CHANGES
=======

     1.00 21 July 2000  - Initial public release.

METHODS
=======

new;
     Creates a new instance of the CGI::PathInfo object and decodes any
     'PATH_INFO' parameters.

     Example:

          use CGI::PathInfo;

          my $path_info = CGI::PathInfo->new;

     The defaults are for the parameters to be seperated by '/' characters
     with name/value pairs linked by '-' and with leading or trailing '/'
     characters ignored.

          Ex:

          $ENV{'PATH_INFO'} = '/yesterday-monday/tomorrow-wednesday';

          decodes to

          'yesterday' -> 'monday'

          'tomorrow' -> 'wednesday'

     Values are read using the 'param' method.

     Any of the defaults may be overridden by specifying them in the
     invokation of 'new'.

     Example:

          my $path_info = CGI::PathInfo->new({  Eq => '=',
                                              SplitOn => '&',
                        });

     It is probably a Bad Idea (tm) to set the Eq or SplitOn values to a
     letter or a number (A-Za-z0-9) unless you are a wizard at encodings.

     The defaults were chosen to maximize the likelyhood that CGI backed
     URLs will be crawled by search engines and that MSIE won't try
     something stupid because of a '.tla' on a URL.

param([$fieldname]);
     Called as `$path_info->param();' it returns the list of all defined
     parameter fields in the same order they appear in the data in
     PATH_INFO.

     Called as `$path_info->param($fieldname);' it returns the value (or
     array of values for multiple occurances of the same field name)
     assigned to that $fieldname. If there is more than one value, the
     values are returned in the same order they appeared in the data from
     user agent.  If called in a scalar context when several values are
     present for specified parameter, the *first* value will be returned.

     Examples:

          my (@form_fields) = $path_info->param;

          my (@multi_pick_field) = $path_info->param('pick_field_name');

          my ($form_field_value) = $path_info->param('some_field_name');

     You can also use the param method to set param values to new values.
     These values will be returned by this CGI::PathInfo object as if they
     had been found in the originally processed PATH_INFO data. This will
     not affect a seperately created instance of CGI::PathInfo.

     Examples:

          $path_info->param( 'name' => 'Joe Shmoe' );

          $path_info->param({ 'name' => 'Joe Shmoe', 'birth_date' => '06/25/1966' });

          $path_info->param({ 'pick_list' => ['01','05','07'] });

calling_parms_table;
     Returns a formatted HTML table containing all the PATH_INFO parameters
     for debugging purposes

     Example:

          print $path_info->calling_parms_table;

url_encode($string);
     Returns a URL encoding of the input string.  Anything except
     0-9a-zA-Z is escaped to %xx form.

     The idea is to reserve all other characters for potential use as
     parameter or key/value seperators.

     Example:

          my $url_encoded_string = $path_info->url_encode($string);

url_decode($string);
     Returns URL *decoding* of input string (%xx substitutions are decoded
     to their actual values).

     Example:

          my $url_decoded_string = $path_info->url_decode($string);

BUGS
====

   None known.

TODO
====

   Who knows?

AUTHORS
=======

   Benjamin Franz <snowhare@nihongo.org>

VERSION
=======

   Version 1.00 22 July 2000

COPYRIGHT
=========

   Copyright (c) Benjamin Franz and FreeRun Technologies July 2000. All
rights reserved.

     This program is free software; you can redistribute it
     and/or modify it under the same terms as Perl itself.

Transparent state persistence for CGI applications.
***************************************************

NAME
====

   CGI::Persistent - Transparent state persistence for CGI applications.

SYNOPSIS
========

     use CGI::Persistent;

     my $cgi = new CGI::Persistent "/directory";
     print $cgi->header ();
     my $url = $cgi->state_url ();
     print "<a href=$u>I am a persistent CGI session.</a>";

SOLUTION TO THE STATELESS PROBLEM
=================================

   HTTP is a stateless protocol; a HTTP server closes connection after
serving an object. It retains no memory of the request details and doesn't
relate subsequent requests with what it has already served. While this
works well for static resources like HTML pages and image elements,
complex user interactions often require state preservation across multiple
requests and different parts of the web resource. Statefulness on a
stateless server is achieved either through client-side mechanisms like
Netscape cookies (which are considered distasteful on general principles
of privacy) or with hidden fields in forms and value-attribute pairs in
the URLs. State preserving URLs are more desirable, because they are
independent of the client configuration, but tend to get unwieldy with
increase in space complexity of the application.

   CGI::Persistent solves this problem by introducing persistent CGI
sessions that store their state data on the server side. When a new
session starts, CGI::Persistent automatically generates a unique state
identification string and associates it with a persistent object on the
server. The identification string is used in URLs or forms to refer to the
particular session. Request attributes are transparently committed to the
associated object and the object data is bound to the query.

   CGI::Persistent is derived from CGI.pm. CGI.pm methods have been
overridden as appropriate. Very few new methods have been added.

METHODS
=======

new()
     Creates a new CGI object and binds it to its associated persistent
     state. A new state image is created if no associated state exists.
     new() takes two optional arguments. The first argument is the
     directory of persistence, the place where state information is
     stored. Ideally, this should be a separate directory dedicated to
     state files. When a directory is not specified, the current working
     directory is assumed.

     new() can also take a state id on the argument list instead of
     getting it from the query. This might be useful if you are using this
     module to store configuration data that you wish to retain across
     different sessions.

     Examples:

          $q = new CGI::Persistent;
          $q = new CGI::Persistent "/dope";
          $q = new CGI::Persistent  undef, "/dope/924910985.134";

state_url()
     Returns a URL with the state identification string. This URL should
     be used for referring to the persistent session associated with the
     query.

state_field()
     Returns a hidden INPUT type for inclusion in HTML forms. Like
     state_url(), this element is used in forms to refer to the associated
     persistent session.

delete()
     delete() is an overridden method that deletes a named attribute from
     the query.  The persistent object field associated with the attribute
     is also deleted.

     Important note: Attributes that are NOT explicitly delete()ed will
     lurk about and come back to haunt you. Remember to clear control
     attributes and other context dependent fields that need clearing. See
     `delete()', see CGI.

delete_all()
     Another overridden method. Deletes all attributes as well as the
     persistent disk image of the session. This method should be used when
     you want to irrevocably destroy a session. See `delete_all()', see
     CGI.

EXAMPLES
========

   The accompanying CGI example, roach.cgi, illustrates the features of the
module by implementing a multi-page input form.

SEE ALSO
========

   CGI(3), Persistence::Object::Simple(3)

AUTHOR
======

   Vipul Ved Prakash, mail@vipul.net

module to produce nicely formatted HTML code
********************************************

NAME
====

   CGI::Pretty - module to produce nicely formatted HTML code

SYNOPSIS
========

     use CGI::Pretty qw( :html3 );

     # Print a table with a single data element
     print table( TR( td( "foo" ) ) );

DESCRIPTION
===========

   CGI::Pretty is a module that derives from CGI.  It's sole function is to
allow users of CGI to output nicely formatted HTML code.

   When using the CGI module, the following code:     print table( TR( td(
"foo" ) ) );

   produces the following output:     <TABLE><TR><TD>foo</TD></TR></TABLE>

   If a user were to create a table consisting of many rows and many
columns, the resultant HTML code would be quite difficult to read since it
has no carriage returns or indentation.

   CGI::Pretty fixes this problem.  What it does is add a carriage return
and indentation to the HTML code so that one can easily read it.

     print table( TR( td( "foo" ) ) );

   now produces the following output:     <TABLE>        <TR>
<TD>              foo           </TD>        </TR>     </TABLE>

Tags that won't be formatted
----------------------------

   The <A> and <PRE> tags are not formatted.  If these tags were
formatted, the user would see the extra indentation on the web browser
causing the page to look different than what would be expected.  If you
wish to add more tags to the list of tags that are not to be touched, push
them onto the `@AS_IS' array:

     push @CGI::Pretty::AS_IS,qw(CODE XMP);

Customizing the Indenting
-------------------------

   If you wish to have your own personal style of indenting, you can
change the `$INDENT' variable:

     $CGI::Pretty::INDENT = "\t\t";

   would cause the indents to be two tabs.

   Similarly, if you wish to have more space between lines, you may change
the `$LINEBREAK' variable:

     $CGI::Pretty::LINEBREAK = "\n\n";

   would create two carriage returns between lines.

   If you decide you want to use the regular CGI indenting, you can easily
do the following:

     $CGI::Pretty::INDENT = $CGI::Pretty::LINEBREAK = "";

BUGS
====

   This section intentionally left blank.

AUTHOR
======

   Brian Paulsen <Brian@ThePaulsens.com>, with minor modifications by
Lincoln Stein <lstein@cshl.org> for incorporation into the CGI.pm
distribution.

   Copyright 1999, Brian Paulsen.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Bug reports and comments to Brian@ThePaulsens.com.  You can also write
to lstein@cshl.org, but this code looks pretty hairy to me and I'm not
sure I understand it!

SEE ALSO
========

   See CGI,

CGI methods output to a print handle
************************************

NAME
====

   CGI::PrintWrapper - CGI methods output to a print handle

SYNOPSIS
========

     use CGI::PrintHandle;
     use IO::Scalar; # just an example
     use HTML::Stream; # continuing the example

     # Fine, there really is no such tag as "WEAK":
     HTML::Stream->accept_tag ('WEAK');

     my $content = '';
     my $handle = IO::Scalar->new (\$content);
     my $cgi = CGI::PrintHandle ($handle);
     my $html = HTML::Stream->new ($handle);

     # Not a very exciting example:
     $cgi->start_form;
     $html->WEAK->t ('I am form: hear me submit.')->_WEAK;
     $cgi->submit;
     $cgi->end_form;

     print "$content\n";
     <FORM METHOD="POST"  ENCTYPE="application/x-www-form-urlencoded">
     <WEAK>I am form: hear me submit.</WEAK><INPUT TYPE="submit" NAME=".submit"></FORM>

DESCRIPTION
===========

   *CGI::PrintWrapper* arranges for CGI methods to output their results by
printing onto an arbitrary handle.  This gets around the problem that the
CGI's subs return strings, which may be inconvient when you wish to use
CGI for something besides CGI script processing.

   You could just call print yourself on the appropriate file handle, but
there are many contexts in which it is cleaner to provide the extra
abstraction (such as mixing CGI with *HTML::Stream*, the problem which
prompted my solution, illustrated above).

   *CGI::PrintWrapper* creates the necessary callbacks for printing
dynamically, updating the symbol table as it encounters a new CGI method.

CONSTRUCTOR
===========

`new ($h)'
     Creates a new *CGI::PrintWrapper*, printing the results of CGI
     methods onto the print handle object, $h.

`new ($h, @cgi_args)'
     Creates a new *CGI::PrintWrapper*, printing the results of CGI
     methods onto the print handle object, $h, and using the additional
     arguments to construct the CGI object.

METHODS
=======

`cgi ( )'
     Returns the underlying CGI object.  This is handy for invoking methods
     on the object whose result you do not wish to print, such as param().

`io ( )'
     Returns the underlying print handle object.

AUTOLOAD
     Initially, *CGI::PrintWrapper* has no methods (except as mentioned
     above).  As the caller invokes CGI methods, AUTOLOAD creates
     anonymous subroutines to perform the actual CGI method call
     indirection and print the results with the print handle object.  It
     also updates the symbol table for *CGI::PrintWrapper* so that future
     calls can bypass AUTOLOAD.  This makes a *CGI::PrintWrapper* object
     transparently a CGI object, usable as a drop-in replacement.

SEE ALSO
========

   See CGI, IO/Scalar, HTML/Stream,
`print', see Perlfunc (perl.info),

   CGI is the canonical package for working with fill-out forms on the
web.  It is particularly useful for generating HTML for such forms.

   *IO::Scalar* is a handy package for treating a string as an object
supporting IO handle semantics.

   *HTML::Stream* is a nice package for writing HTML markup and content
into an IO handle with stream semantics.  It's main drawback is lack of
support for HTML 4.0.

DIAGNOSTICS
===========

   The following are the diagnostics generated by *Class::Class*.  Items
marked "(W)" are non-fatal (invoke `Carp::carp'); those marked "(F)" are
fatal (invoke `Carp::croak').

No print handle
     (F) The caller tried to create a new `CGI::PrintWrapper' without
     supplying the mandatory first argument, a print handle:

          $cgi = CGI::PrintWrapper->new;

'%s' is not a print handle
     (F) The caller tried to create a new `CGI::PrintWrapper' using an
     object which does not support print as the mandatory first argument.

Couldn't create CGI object because %s
     (F) The caller tried to create a new `CGI::PrintWrapper' using bad
     addtional arguments to the constructor for CGI.

BUGS AND CAVEATS
================

   There is no way of controlling now to use CGI, for example, if you
wished to precompile all the methods.  Instead, you should make the
appropriate call to use yourself for CGI, in addition to that for
*CGI::PrintWrapper*, thus:

     use CGI qw(:compile);
     use CGI::PrintWrapper;

AUTHORS
=======

   B. K. Oxley (binkley) at Home <binkley@bigfoot.com>.  I am grateful to
my employer, DataCraft, Inc., for time spent preparing this package for
public consumption.

COPYRIGHT
=========

     $Id: PrintWrapper.pm,v 1.8 1999/12/30 13:38:06 binkley Exp $

     Copyright 1999, B. K. Oxley (binkley).

   This library is free software; you may redistribute it and/or modify it
under the same terms as Perl itself.

Simple Interface to Server Push
*******************************

NAME
====

   CGI::Push - Simple Interface to Server Push

SYNOPSIS
========

     use CGI::Push qw(:standard);

     do_push(-next_page=>\&next_page,
             -last_page=>\&last_page,
             -delay=>0.5);

     sub next_page {
         my($q,$counter) = @_;
         return undef if $counter >= 10;
         return start_html('Test'),
                h1('Visible'),"\n",
                "This page has been called ", strong($counter)," times",
                end_html();
     }

     sub last_page {
         my($q,$counter) = @_;
         return start_html('Done'),
                h1('Finished'),
                strong($counter - 1),' iterations.',
                end_html;
     }

DESCRIPTION
===========

   CGI::Push is a subclass of the CGI object created by CGI.pm.  It is
specialized for server push operations, which allow you to create animated
pages whose content changes at regular intervals.

   You provide CGI::Push with a pointer to a subroutine that will draw one
page.  Every time your subroutine is called, it generates a new page.  The
contents of the page will be transmitted to the browser in such a way that
it will replace what was there beforehand.  The technique will work with
HTML pages as well as with graphics files, allowing you to create animated
GIFs.

   Only Netscape Navigator supports server push.  Internet Explorer
browsers do not.

USING CGI::Push
===============

   CGI::Push adds one new method to the standard CGI suite, do_push().
When you call this method, you pass it a reference to a subroutine that is
responsible for drawing each new page, an interval delay, and an optional
subroutine for drawing the last page.  Other optional parameters include
most of those recognized by the CGI header() method.

   You may call do_push() in the object oriented manner or not, as you
prefer:

     use CGI::Push;
     $q = new CGI::Push;
     $q->do_push(-next_page=>\&draw_a_page);

     -or-

     use CGI::Push qw(:standard);
     do_push(-next_page=>\&draw_a_page);

   Parameters are as follows:

-next_page
          do_push(-next_page=>\&my_draw_routine);

     This required parameter points to a reference to a subroutine
     responsible for drawing each new page.  The subroutine should expect
     two parameters consisting of the CGI object and a counter indicating
     the number of times the subroutine has been called.  It should return
     the contents of the page as an array of one or more items to print.
     It can return a false value (or an empty array) in order to abort the
     redrawing loop and print out the final page (if any)

          sub my_draw_routine {
              my($q,$counter) = @_;
              return undef if $counter > 100;
              return start_html('testing'),
                     h1('testing'),
                     "This page called $counter times";
          }

     You are of course free to refer to create and use global variables
     within your draw routine in order to achieve special effects.

-last_page
     This optional parameter points to a reference to the subroutine
     responsible for drawing the last page of the series.  It is called
     after the -next_page routine returns a false value.  The subroutine
     itself should have exactly the same calling conventions as the
     -next_page routine.

-type
     This optional parameter indicates the content type of each page.  It
     defaults to "text/html".  Normally the module assumes that each page
     is of a homogenous MIME type.  However if you provide either of the
     magic values "heterogeneous" or "dynamic" (the latter provided for the
     convenience of those who hate long parameter names), you can specify
     the MIME type - and other header fields - on a per-page basis.  See
     "heterogeneous pages" for more details.

-delay
     This indicates the delay, in seconds, between frames.  Smaller delays
     refresh the page faster.  Fractional values are allowed.

     *If not specified, -delay will default to 1 second*

-cookie, -target, -expires, -nph
     These have the same meaning as the like-named parameters in
     CGI::header().

     If not specified, -nph will default to 1 (as needed for many servers,
     see below).

Heterogeneous Pages
-------------------

   Ordinarily all pages displayed by CGI::Push share a common MIME type.
However by providing a value of "heterogeneous" or "dynamic" in the
do_push() -type parameter, you can specify the MIME type of each page on a
case-by-case basis.

   If you use this option, you will be responsible for producing the HTTP
header for each page.  Simply modify your draw routine to look like this:

     sub my_draw_routine {
         my($q,$counter) = @_;
         return header('text/html'),   # note we're producing the header here
                start_html('testing'),
                h1('testing'),
                "This page called $counter times";
     }

   You can add any header fields that you like, but some (cookies and
status fields included) may not be interpreted by the browser.  One
interesting effect is to display a series of pages, then, after the last
page, to redirect the browser to a new URL.  Because redirect() does
b<not> work, the easiest way is with a -refresh header field, as shown
below:

     sub my_draw_routine {
         my($q,$counter) = @_;
         return undef if $counter > 10;
         return header('text/html'),   # note we're producing the header here
                start_html('testing'),
                h1('testing'),
                "This page called $counter times";
     }

     sub my_last_page {
         return header(-refresh=>'5; URL=http://somewhere.else/finished.html',
                       -type=>'text/html'),
                start_html('Moved'),
                h1('This is the last page'),
                'Goodbye!'
                hr,
                end_html;
     }

Changing the Page Delay on the Fly
----------------------------------

   If you would like to control the delay between pages on a page-by-page
basis, call push_delay() from within your draw routine.  push_delay()
takes a single numeric argument representing the number of seconds you
wish to delay after the current page is displayed and before displaying
the next one.  The delay may be fractional.  Without parameters,
push_delay() just returns the current delay.

INSTALLING CGI::Push SCRIPTS
============================

   Server push scripts must be installed as no-parsed-header (NPH) scripts
in order to work correctly on many servers.  On Unix systems, this is most
often accomplished by prefixing the script's name with "nph-".
Recognition of NPH scripts happens automatically with WebSTAR and
Microsoft IIS.  Users of other servers should see their documentation for
help.

   Apache web server from version 1.3b2 on does not need server push
scripts installed as NPH scripts: the -nph parameter to do_push() may be
set to a false value to disable the extra headers needed by an NPH script.

AUTHOR INFORMATION
==================

   Copyright 1995-1998, Lincoln D. Stein.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Address bug reports and comments to: lstein@cshl.org

BUGS
====

   This section intentionally left blank.

SEE ALSO
========

   See CGI/Carp, CGI,

Perl module to provide quick CGI forms.
***************************************

NAME
====

   CGI::QuickForm - Perl module to provide quick CGI forms.

SYNOPSIS
========

     # Minimal example. (Insecure no error checking.)

     #!/usr/bin/perl -w
     use strict ;
     use CGI qw( :standard :html3 ) ;
     use CGI::QuickForm ;

     show_form(
         -ACCEPT => \&on_valid_form, # You must supply this subroutine.
         -TITLE  => 'Test Form',
         -FIELDS => [
             { -LABEL => 'Name', },  # Default field type is textfield.
             { -LABEL => 'Age',  },  # Stored in param( 'Age' ).
         ],
     ) ;

     sub on_valid_form {
         my $name = param( 'Name' ) ;
         my $age  = param( 'Age' ) ;
         open PEOPLE, ">>people.tab" ;
         print PEOPLE "$name\t$age\n" ;
         close PEOPLE ;
         print header, start_html( 'Test Form Acceptance' ),
             h3( 'Test Form Data Accepted' ),
             p( "Thank you $name for your data." ), end_html ;
     }

     # All QuickForm options (aide memoir)

     #!/usr/bin/perl -w
     use strict ;
     use CGI qw( :standard :html3 ) ;
     use CGI::QuickForm ;

     show_form(
         -ACCEPT           => \&on_valid_form,
         -BORDER           => 0,
         -FOOTER           => undef,
         -HEADER           => undef,
         -INTRO            => undef,
         -LANGUAGE         => 'en',
         -USER_REQUIRED    => undef,
         -USER_INVALID     => undef,
         -TITLE            => 'Test Form',
         -REQUIRED_HTML    => '<span style="font-weight:bold;color:BLUE">+</span>',
         -INVALID_HTML     => '<span style="font-weight:bold;color:RED">*</span>',
         -VALIDATE         => undef,       # Set this to validate the entire record
         -SIZE             => undef,
         -MAXLENGTH        => undef,
         -ROWS             => undef,
         -COLUMNS          => undef,
         -CHECK            => 1,
         -SPACE            => 0, # Output some newlines to assist debugging if 1
         -MULTI_COLUMN     => 0,
         -NAME             => undef,
         -ONSUBMIT         => undef,
         -JSCRIPT          => {},
         -STYLE_FIELDNAME  => '',
         -STYLE_FIELDVALUE => '',
         -STYLE_BUTTONS    => '',
         -STYLE_ROW        => '',
         -STYLE_WHY        => '',
         -TABLE_OPTIONS    => '',
         -FIELDS           => [
             {
                 -LABEL            => 'Personal Details',
                 -HEADLINE         => 1,
                 -STYLE_FIELDNAME  => '',
                 -COLSPAN          => 2,
                 -END_ROW          => 1,
             },
             {
                 -LABEL            => 'Name',
                 -START_ROW        => 1,
                 -END_ROW          => 1,
                 -COLSPAN          => 1,
                 -REQUIRED         => undef,
                 -TYPE             => 'textfield',
                 -VALIDATE         => undef, # Set this to validate the field
                 -CLEAN            => undef, # Set this to clean up valid data
                 -DESC             => undef,
                 -STYLE_FIELDNAME  => '', # If set over-rides form-level setting
                 -STYLE_FIELDVALUE => '', # If set over-rides form-level setting
                 -STYLE_ROW        => '', # If set over-rides form-level setting
                 # Lowercase options are those supplied by CGI.pm
                 -name             => undef, # Defaults to -LABEL's value.
                 -default          => undef,
                 -size             => 30,
                 -maxlength        => undef,
             },
             # For all others: same QuickForm options as above
             # and all CGI.pm options (which vary with -TYPE) available
             {
                 -LABEL     => 'Address',
                 -TYPE      => 'textarea',
                 -rows      => 3,
                 -columns   => 40,
             },
             {
                 -LABEL     => 'Password',
                 -TYPE      => 'password_field',
             },
             {
                 -LABEL     => 'Hair colour',
                 -TYPE      => 'scrolling_list',
                 '-values'  => [ qw( Red Black Brown Grey White ) ],
                 -size      => 1,
                 -multiples => undef,
             },
             {
                 -LABEL     => 'Worst Sport',
                 -TYPE      => 'radio_group',
                 -values    => [ qw( Boxing Cricket Golf ) ],
                 -default   => 'Golf',
             },
             # Any other CGI.pm field can be used in the same way.
         ],
         -BUTTONS           => [
             { -name => 'Add'    },
             { -name => 'Edit'   },
             { -name => 'List'   },
             { -name => 'Remove' },
             { -name => 'Clear', -DEFAULTS => 1 },
         ],
     ) ;

DESCRIPTION
===========

   `show_form', provides a quick and simple mechanism for providing
on-line CGI forms.

   When `show_form' executes it presents the form with the fields
requested.  As you can see from the minimal example at the beginning of
the synopsis it will default everything it possibly can to get you up and
running as quickly as possible.

   If you have specified any validation it will validate when the user
presses the submit button. If there is an error it will re-present the
form with the erroneous fields marked and with all the data entered in
tact. This is repeated as often as needed. Once the user has corrected all
errors and the data is valid then your `&on_valid_form' subroutine will be
called so that you can process the valid data in any way you wish.

   Note that EXAMPLE #1 and EXAMPLE #2 are in this pod; `example1',
`example2', etc. are supplied as files.

QuickForm form-level (record-level) options
-------------------------------------------

`-ACCEPT'
     Required subroutine reference. This is a reference to the subroutine
     to execute when the form is successfully completed, i.e. once all the
     fields and the whole record are valid (either because no validation
     was requested or because every validation subroutine called returned
     true). The parameters are accessible via `CGI.pm', so your
     `&on_valid_form' may look something like this:

          sub on_valid_form {
              my $first_param  = param( 'first' ) ;
              my $second_param = param( 'second' ) ;
              my $third_param  = param( 'third' ) ;

          # Process, e.g. send an email or write a record to a file or database.
          # Give the user a thank you.
              }

`-BORDER'
     Optional integer. This is the border width. Default is zero. You would
     normally set this to 1 if you are using `-DESC' to add textual
     descriptions to your fields.

`-BUTTONS'
     Optional array reference. This is an array of submit buttons. The
     buttons appear at the bottom of the form, after all the fields. Each
     button is defined as an anonymous hash, e.g.

          -BUTTONS    => [
              { -name => 'New'    },
              { -name => 'Update' },
              ],

     although any other legitimate `CGI.pm' options may also be given, e.g.

          -BUTTONS    => [
              { -name => 'New',    -value => 'BUTTON_NEW'    },
              { -name => 'Update', -value => 'BUTTON_UPDATE' },
              ],

     If you want a button which resets the form to its default values then
     create an entry like this:

          { -name => 'Clear', -DEFAULTS => 1 },

     If no `-BUTTONS' option array reference is given it will be created
     with `{ -name =< 'Submit' }' by default. Note that this option
     replaces the `-BUTTONLABEL' option. If `-BUTTONLABEL' is used it will
     be converted into the new form automatically so old scripts will not
     be broken. However use of `-BUTTONS' is recommended for all new work.
     To see which button has been pressed you might use code like this in
     your on_valid_form subroutine:

          if( param( 'New' ) ) {
              # New pressed
          }
          elsif( param( 'Update' ) ) {
              # Update pressed
          }
          # etc.

`-CHECK'
     Optional boolean, default is true. When `show_form' is called it will
     check (i.e. do validation) providing there are parameters (i.e. the
     user has filled in the form) and if `-CHECK' is true. This option
     would not normally be used. However if you have links which call your
     form with some parameters (e.g. default values), you will want the
     form to be displayed with the defaults but *without* any validation
     taking place in the first instance. In this situation you would set
     `-CHECK' to false. Thus we must cope with the following scenarios:

       1. Form is called with no params - must display blank form and
          validate when the user presses a button;

       2. Form is called with params (e.g. by clicking a link we've
          provided) - must display form with any defaults and not validate
          until the user presses a button;

       3. Form is called with params (as the result of the user pressing a
          button) - validation must take place.

          To achieve the above we need to add an extra field=value pair to
     the URL we provide and if that is present then skip validation. The
     field's name must not be one of the form's fields! e.g.

          # If it is to be called from one of our own URLs with something like
          # www.mysite.com/cgi-bin/myscript?colour=green&size=large
          # then we must add in the extra field=value and write the preceeding link
          # for example as:
          # www.mysite.com/cgi-bin/myscript?QFCHK=0&colour=green&size=large
          # We then use query_string() to set -CHECK to 0 and show the form with the
          # defaults without validating - we'll validate when they press a button.
          # If its been called as something like www.mysite.com/cgi-bin/myscript
          # then set -CHECK to 1 which gives us standard behaviour:
          # i.e. if there are params then show_form will validate; otherwise it will
          # show the blank form.
          show_form(
              -CHECK => ( query_string() =~ /QFCHK=0/o ? 0 : 1 ),
              # etc
              ) ;

          # Or more verbosely:
          my $Check = 1 ;
          $Check    = 0 if query_string() =~ /QFCHK=0/o ;
          show_form(
              -CHECK => $Check,
              # etc
              ) ;

     Note that QuickForm discards any query string if it reinvokes itself
     because of invalid data. This is useful because it means you can use
     the query string to distinguish between a 'first time' call and
     subsequent calls as we do here with -CHECK. However if you want a
     query string parameter to survive these calls we must extract them
     and pass them ourselves, e.g. via a hidden field.

`-FOOTER'
     Optional string. This is used to present any text following the form
     and if used it must include everything up to and including final
     "</html>", e.g.:

          my $footer = p( "Thank's for your efforts." ) .
                       h6( "Copyright (c) 1999 Summer plc" ) . end_html ;

          show_form(
              -FOOTER => $footer,
              # etc

`-HEADER'
     Optional string. This is used to present your own title and text
     before the form proper. If you use this it must include everything
     from "Content-type: text/html" onwards. For example:

          my $header = header . start_html( "This is my Title" ) .
                       h2( "My new Form" ) . p( "Please answer the questions!" ) ;

          show_form(
              -HEADER => $header,
              # etc

`-INTRO'
     Optional string. If you specify `-TITLE' you may want to specify this
     field too; it puts a paragraph of text before the form. The English
     default is "Please enter the information.", there is a default for
     each supported language (see `-LANGUAGE').

`-INVALID_HTML'
     Optional HTML string. Default is:

          <span style="font-weight:bold;color:RED">*</span>

     You can over-ride this to set your own marker to indicate an invalid
     field.  You could use an image tag for example:

          <img src="/images/invalid.jpg" alt="*" />

     Note that if you use your own `-USER_REQUIRED' or `-USER_INVALID'
     strings, this string will replace the sequence `~I~' if it occurs.

     See `example1' and the companion option `-REQUIRED_HTML'.

`-JSCRIPT'
     Optional hash reference; should contain at least one element 'src'
     which should contain some Javascript, e.g.

          -JSCRIPT => { src => 'document.Address.myfield.focus()' },

     This is just a wrapper for CGI.pm's `-script' option. (See `-NAME' and
     `-ONSUBMIT'.)

`-LANGUAGE'
     Optional string. This option accepts 'en' (english), 'cy' (welsh),
     'de' (german), 'es' (spanish) and 'fr' (french) - the French
     translation was done by Babelfish - see CHANGES for the human
     translators. ('english' is also supported for backward
     compatibility.) If people provide me with translations I will add
     other languages. This is used for the presentation of messages to the
     user, e.g.:

          Please enter the information.
          Fields marked with + are required.
          Fields marked with * contain errors or are empty.

     If you want to create your own 'required' or 'invalid' strings using
     the `-USER_REQUIRED' and/or `-USER_INVALID' options you must set
     `-LANGUAGE' to 'user'.

     See `example1'.

`-MULTI_COLUMN'
     Optional boolean (default false). If false QuickForm behaves as it
     always has producing a two column table, the first column with field
     names and the second column with field values. If true QuickForm will
     put all field names and field values in the same row, except where
     you force a new row to be used by marking some fields with `-END_ROW
     =' 1,>. See the field-level options `-START_ROW', `-END_ROW' and
     `-COLSPAN'. See `example2' and `example4' which have been updated to
     demonstrate these options.

`-NAME'
     Optional string. If specified this string is given to the start_form()
     function as its `-name' option; used for identifying the form for
     Javascript.  (See `-JSCRIPT' and `-ONSUBMIT'.)

`-ONSUBMIT'
     Optional string. If specified this string is given to the start_form()
     function as its `-onSubmit' option; used with Javascript.  (See
     `-JSCRIPT' and `-NAME'.)

`-REQUIRED_HTML'
     Optional HTML string. Default is:

          <span style="font-weight:bold;color:BLUE">+</span>

     You can over-ride this to set your own marker to indicate a required
     field.

     Note that if you use your own `-USER_REQUIRED' or `-USER_INVALID'
     strings, this string will replace the sequence `~R~' if it occurs.

     See `example1' and the companion option `-INVALID_HTML'.

`-TITLE'
     Required string (unless you use `-HEADER'). This is used as the
     form's title and as a header on the form's page - unless you use the
     `-HEADER' option (see above) in which case this option is ignored.

`-USER_INVALID'
     Optional string. If specified you must set `-LANGUAGE' to 'user' and
     if you are not writing English then you'll need to set
     `-USER_REQUIRED' too.

     This string is used as the error text for invalid fields. If it
     contains the character sequence `~I~' that sequence will be replaced
     with the HTML used to signify an invalid field (which you can
     override by setting `-INVALID_HTML').

`-USER_REQUIRED'
     Optional string. If specified you must set `-LANGUAGE' to 'user' and
     if you are not writing English then you'll need to set
     `-USER_INVALID' too.

     This string is used as the error text for required fields. If it
     contains the character sequence `~R~' that sequence will be replaced
     with the HTML used to signify a required field (which you can
     override by setting `-REQUIRED_HTML').

`-VALIDATE'
     Optional subroutine reference. This routine is called after each
     individual field has been validated. It is given the fields in a
     name=>value hash. It should either return a simple true (valid) or
     false (invalid) or a two element list, the first element being a
     true/false value and the second value either an empty string or an
     (html) string which gives the reason why the record is invalid.
     Typically it may have this structure:

          sub valid_record {
              my %field = @_ ;
              my $valid = 1 ;
              # Do some multi-field validation, e.g.
              if( $field{'colour'} eq 'blue' and
                  $field{'make'} eq 'estate' ) {
                  $valid = 0 ; # No blue estates available.
              }
              # etc.
              $valid ; # Return the valid variable which may now be false.
          }

     or now (preferred style):

          sub valid_record {
              my %field = @_ ;
              my $valid = 1 ;
              my $why   = '' ;
              # Do some multi-field validation, e.g.
              if( $field{'colour'} eq 'blue' and
                  $field{'make'} eq 'estate' ) {
                $valid = 0 ; # No blue estates available.
                $why   = '<b><i>No blue estates available</i></b>' ;
              }
              # etc.
              ( $valid, $why ) ;
          }

     *Both syntaxes work so no existing code need be changed.* If the
     record is invalid the `$why' element will be shown near the top of
     the form just before the fields themselves, otherwise (i.e. if the
     record is valid) it will be ignored.

`-COLUMNS'
     Optional integer. If set then any `-TYPE => textarea' will have a
     `-columns' set to this value unless an explicit `-columns' is given.

`-MAXLENGTH'
     Optional integer. If set then any `-TYPE => textfield' will have a
     `-maxlength' set to this value unless an explicit `-maxlength' is
     given.

`-ROWS'
     Optional integer. If set then any `-TYPE => textarea' will have a
     `-rows' set to this value unless an explicit `-rows' is given.

`-SIZE'
     Optional integer. If set then any `-TYPE => textfield' will have a
     `-size' set to this value unless an explicit `-size' is given. For
     example:

          show_form(
             -ACCEPT => \&on_valid_form, # You must supply this subroutine.
             -TITLE  => 'Test Form',
             -SIZE   => 50,
             -FIELDS => [
                 { -LABEL => 'Name', },
                 { -LABEL => 'Age',  },
             ],
              ) ;
              # Both the fields will be textfields because that is the default and both
              # will have a -size of 50.

          show_form(
              -ACCEPT    => \&on_valid_form, # You must supply this subroutine.
              -TITLE     => 'Test Form',
              -SIZE      => 50,
              -MAXLENGTH => 70,
              -FIELDS => [
                  {
                      -LABEL => 'Name',
                      -CLEAN => \&cleanup, # You must supply this (see later).
                  },
                  { -LABEL => 'Age',  },
                  {
                      -LABEL => 'Country',
                                # Here we upper case the country.
                      -CLEAN => sub { local $_ = shift ; tr/a-z/A-Z/ ; $_ },
                      -size  => 20,
                  },
              ],
          ) ;
          # All three fields will be textfields. Name and Age will have a -size of
          # 50 but Country will have a -size of 20. All three will have a -maxlength
          # of 70.

     These options apply globally and are documented under Styles later.

`-SPACE'
     Optional integer. If true then QuickForm will output some newlines to
     help make the HTML more human readable for debugging; otherwise no
     additional whitespace is added. Defaults to false.

     =item `-FIELDS'

     Required array reference. This is an array of hashes; there must be
     at least one. The fields are displayed in the order given. The
     options available in each field hash are covered in the next section.

QuickForm field-level options
-----------------------------

`-CLEAN'
     Optional subroutine reference. If specified this subroutines will be
     called for the relevant field if and only if the whole record is
     valid, i.e. just before calling your `on_valid_form' subroutine. It
     will receive a single parameter (the value of the relevant param),
     and must return a new value. A typical routine might clean up excess
     whitespace, e.g.:

          sub cleanup {
              local $_ = shift ; # This is the value of param( <fieldname> )

          tr/\t \n\r\f/ /s ; # Convert multiple whitespace to one space.
          s/^\s*//o ;        # Remove leading whitespace.
          s/\s*$//o ;        # Remove trailing whitespace.

          $_ ;
              }

`-COLSPAN'
     Optional integer. Default is 1; ignored if `-MULTI_COLUMN' is false.
     If you choose `-MULTI_COLUMN' and want some fields to span multiple
     rows then you can use this option to define how many rows are
     spanned. (Note that every field is two rows wide, one for the
     fieldname and one for the fieldvalue.)

`-DESC'
     Optional string. This is a short piece of descriptive text which
     appears above the field and is used to give the user a little
     guidance on what they should choose or enter. Normally if you use
     these then you would set the form-level `-BORDER' option to 1 to help
     visually group the field and its descriptive text.

`-HEADLINE'
     Optional boolean. Default is false. If set to true then instead of
     inserting a field, QuickForm will insert a label. This is used to
     separate blocks of input fields - see `example2'. If this is true
     then you will probably want to set `-STYLE_FIELDNAME', e.g. to make
     the text stand out; and also `-COLSPAN' to the number of columns in
     the form if using `-MULTI_COLUMN'. The `-LABEL' is the text that will
     be displayed. If using `-MULTI_COLUMN' any field that preceeds
     `-HEADLINE' should normally set `-END_ROW' to true; this isn't done
     automatically in case your form has two or more columns and you want
     to have different headlines above each column. Thus a typical
     headline field looks like:

          {
              -LABEL           => 'General Information',
              -HEADLINE        => 1,
              -COLSPAN         => 2, # Probably needs to be more for -MULTI_COLUMN
              -END_ROW         => 1,
              -STYLE_FIELDNAME => 'style="background-color:black;color:white;font-weight:bold"',

          },

`-LABEL'
     Required string. This is the display label for the field. It is also
     used as the field's name if no `-name' option is used.

`-REQUIRED'
     Optional boolean. Default is false. If set to true the field must
     contain something. Should only be used with text fields. It is
     ignored if `-VALIDATE' is given since `-VALIDATE' overrides (see
     later).

`-START_ROW' and `-END_ROW'
     Optional booleans, default is true. These options are only relevant
     if the form-level `-MULTI_COLUMN' option is set to true in which case
     these options are used to identify at which fields rows start and
     end. In practice `-START_ROW' should never be needed; simply set
     `-END_ROW =' 1,> in each field which is to be the last field in a
     given row. Note that because some fields may need to span several
     columns e.g. a layout where say the first two fields are side-by-side
     and the following field is so wide it must take the whole width; the
     wider field's `-COLSPAN' setting may need to be set to `-COLSPAN ='
     3,> or similar. See `example2' and `example4' which have been updated
     to demonstrate these options.

     Some of these options may be applied on a per-field basis; they are
     documented under Styles later.

`-TYPE'
     Optional string. Default is `textfield'. May be any field supported by
     `CGI.pm'.

`-VALIDATE'
     Optional subroutine reference. If specified this subroutine will be
     called when the user presses the submit button; its argument will be
     the value of the field. It should either return a simple true (valid)
     or false (invalid) or a two element list, the first element being a
     true/false value and the second value either an empty string or an
     (html) string which gives the reason why the field is invalid. Its
     typical structure may be:

          sub valid_national_insurance {
              my $ni = shift ;

              $ni = uc $ni ;
              ( $ni =~ /^[A-Z]{2}\d{7}[A-Z]$/o ) ? 1 : 0 ;
          }

     or now (preferred style):

          sub valid_national_insurance {
              my $ni  = shift ;
              my $why = '<i>Should be 2 letters followed by 7 ' .
                        'digits then a letter</i>' ;

              $ni = uc $ni ;
              my $valid = ( $ni =~ /^[A-Z]{2}\d{7}[A-Z]$/o ) ? 1 : 0 ;

          ( $valid, $why ) ;
              }

     *Both syntaxes work so no existing code need be changed.* If the
     field is invalid the `$why' element will be shown immediately to the
     right of the field it refers to, otherwise (i.e. if the field is
     valid) it will be ignored.

CGI.pm field-level options
--------------------------

   All the other options passed in the hash should be the lowercase options
supported by `CGI.pm' for the particular field type. For example for a
`-TYPE' of `textfield' the options currently supported are `-name',
`-default', `-size' and `-maxlength'; you may use any, all or none of them
since `CGI.pm' always provides sensible defaults. See "All QuickForm
options" in the SYNOPSIS above for examples of the most common field types.

Styles
------

   If you wish to use a cascading style sheet with QuickForm then you need
to set the -HEADER option to include a <link> tag which includes a
reference to your stylesheet.

   If you wish to use multiple columns see `-MULTI_COLUMN', `-START_ROW',
`-END_ROW' and `-COLSPAN' as well as `example2' and `example4'.

   Whether you use a stylesheet for classes or in-line styles you can set
the class or style using the -STYLE_* options, e.g.

     -STYLE_FIELDNAME  => qq{style="font-size:12pt;margin:2em;"},
     -STYLE_FIELDVALUE => qq{class="valueclass"},
     -STYLE_ROW        => qq{class="rowclass"},
     -STYLE_DESC       => qq{style="color:darkblue"},

   The above styles apply globally to all rows, but can be over-ridden, see
later.

     -STYLE_WHY        => qq{style="font-style:italic;color:red"},

   Because a popular browser cannot cope with this:

     -STYLE_BUTTONS    => qq{style="font-family:Helvetica;text-align:center;"},

   which produces:

     <span style="font-family:Helvetica;text-align:center;>
     # buttons HTML
     </span>

   QuickForm also supports (for `-STYLE_BUTTONS' only) this:

     -STYLE_BUTTONS    => 'center', # or 'centre'

   which produces:

   <center>     # buttons HTML     </center>

   For tables you can set options (because most browsers don't seem to
support styles in tables):

     -TABLE_OPTIONS    => qq{BGCOLOR="WHITE"},

   See files, `example3' (linux-help) and `example5' (bicycle) for more
examples.

   You can of course also apply your own global styles to the existing
tags in the normal way.

   When `-STYLE_DESC', `-STYLE_FIELDNAME', `-STYLE_FIELDVALUE' and
`-STYLE_ROW' are set in `show_form' at form-level (i.e. not inside the
`-FIELDS' section) they apply globally to every fieldname cell, fieldvalue
cell and row respectively. If you require finer control you can set these
styles on a per field basis by including them as field-level options, e.g.

     show_form(
         -ACCEPT           => \&on_valid_form,
         -STYLE_FIELDNAME  => 'style="background-color:#AAAAAA"',
         -STYLE_FIELDVALUE => 'style="background-color:#DDDDDD"',
         -FIELDS           => [
                 {
                     -LABEL            => 'Forename',
                     -STYLE_FIELDNAME  => 'style="background-color:LIGHTGREEN"',
                     -STYLE_FIELDVALUE => 'style="background-color:YELLOW"',
                 },
         # etc.

   If you have set a style at form-level but do not wish it to apply to a
particular row you can over-ride either by setting a new style for the row
as in the example above or by coding `-STYLE_ROW =' ' '> for example; we
have to use a space because if we used the empty string or undef the
global style would be applied.

   See example 5.

EXAMPLE #1: Using a form to generate email
------------------------------------------

   This program is provided as an example of QuickForm's capabilities, it
is not a production-quality program: it has no error checking and is not
secure.

     #!/usr/bin/perl -w
     use strict ;
     use CGI qw( :standard :html3 ) ;
     use CGI::QuickForm ;

     show_form(
         -TITLE  => 'Test Form',
         -ACCEPT => \&on_valid_form,
         -FIELDS => [
             {
                 -LABEL    => 'Forename',
                 -REQUIRED => 1,
             },
             {
                 -LABEL    => 'Surname',
                 -REQUIRED => 1,
             },
             { -LABEL => 'Age', },
             {
                 -LABEL    => 'Sex',
                 -TYPE     => 'radio_group',
                 '-values' => [ qw( Female Male ) ],
             },
         ],
     ) ;

     # This subroutine will only be called if the name fields contain at
     # least one character.
     sub on_valid_form {
         my $forename = param( 'Forename' ) ;
         my $surname  = param( 'Surname' ) ;
         my $age      = param( 'Age' ) ;
         open MAIL, "|/usr/lib/sendmail -t" ;
         print MAIL "From: test\@localhost\n" .
                    "To: user\@localhost\n" .
                    "Subject: Quick Form Email Test\n\n" .
                    "Name: $forename $surname\n" .
                    "Age:  $age\n" ;
         print header, start_html( 'Test Form Data Accepted' ),
             h3( 'Test Form Data Accepted' ),
             p( "Thank you $forename for your data." ), end_html ;
     }

EXAMPLE #2: Appending data to a file
------------------------------------

   This program is provided as an example of QuickForm's capabilities, it
is not a production-quality program: it has no error checking and is not
secure.

     #!/usr/bin/perl -w

     use strict ;
     use CGI qw( :standard :html3 ) ;
     use CGI::QuickForm ;

     show_form(
         -TITLE     => 'Test Form',
         -ACCEPT    => \&on_valid_form,
         -VALIDATE  => \&valid_form,
         -SIZE      => 40,
         -MAXLENGTH => 60,
         -FIELDS => [
             {
                 -LABEL     => 'Forename',
                 -VALIDATE  => \&valid_name,
                 -CLEAN     => \&cleanup,    # (See earlier for definition.)
             },
             {
                 -LABEL     => 'Surname',
                 -VALIDATE  => \&valid_name,
                 -CLEAN     => \&cleanup,    # (See earlier for definition.)
             },
             {
                 -LABEL     => 'Age',
                 # &mk_valid_number generates a subroutine (a closure) and
                 # returns a reference to that subroutine.
                 -VALIDATE  => &mk_valid_number( 3, 130 ),
                 -size      => 10,
                 -maxlength => 3,
             },
         ],
     ) ;

     # This will only be called if all the validation routines return true.
     sub on_valid_form {
         my $forename = param( 'Forename' ) ;
         my $surname  = param( 'Surname' ) ;
         my $age      = param( 'Age' ) ;
         open FILE, ">>namedata.tab" ;
         print FILE "$surname\t$forename\t$age\n" ;
         close FILE ;
         print header, start_html( 'Test Form Data Accepted' ),
             h3( 'Test Form Data Accepted' ),
             p( "Thank you $forename for your data." ), end_html ;
     }

     # This is called to validate the entire form (record).
     # Use a routine like this if there are relationships between fields that
     # must be tested.
     sub valid_form {
         my %rec   = @_ ;
         my $valid = 1 ;
         # We don't allow (perfectly valid!) names like 'John John'.
         my $why   = 'Not allowed to have identical forename and surname' ;
         $valid    = 0 if lc $rec{'Surname'} eq lc $rec{'Forename'} ;
         ( $valid, $why ) ; # $why is ignored if valid.
     }

     sub valid_name {
         my $name  = shift ;
         my $valid = 1 ;
         $valid    = 0 if $name !~ /^\w{2,}$/o ;
         ( $valid, 'Name must have at least 2 letters' ) ;
     }

     sub mk_valid_number {
         my( $min, $max ) = @_ ;

     sub {
         my $valid = $_[0] ? ( $min <= $_[0] and $_[0] <= $max ) : 1 ;
         ( $valid, "<i>Should be between $min and $max inclusive</i>" ) ;
     } ;
         }

mod_perl
--------

   QuickForm appears to run fine in CGI scripts that run under
Apache::Registry without requiring any changes.

   If you want to use QuickForm under pure mod_perl, i.e. outside
Apache::Registry they you need to do the following:

  1. Add the following lines at the beginning of your script:

          use Apache::Constants qw( :common ) ;

  2. Ensure that any routines that return to mod_perl return OK. Normally
     this will be `handler()' and `on_valid_form()'.

  3. Convert your script into a module by wrapping the `show_form()' call
     in a handler subroutine etc.

  4. Copy the module into an Apache subdirectory in your `@INC' path.

  5. Edit your Apache httpd.conf (or perl.conf) to add a Location for the
     module.

  6. If you are converting a script that uses `url()' you may need to add
     the name of the script, e.g. `url() . path_info()'.

        See `example6' for a working example that covers all the points
above.  `example6' also has notes at the beginning to explain how to set
things up.  `example6' is a simple conversion of `example2' so you can see
the simple changes required. Of course you don't have to change your
scripts at all if you run them under Apache::Registry.

USING QUICKFORM WITH OBJECT MODULES
-----------------------------------

   If you want to pass QuickForm an `on_valid_form' function that is in
fact an object's method call then instead of:

     -ACCEPT => \&on_valid_form,

   you need to write:

     -ACCEPT => sub { $object->on_valid_form },

   assuming that you have an object reference called $object and you want
it to call its `on_valid_form' method.

INTRODUCTORY ARTICLE
--------------------

   See http://www.perlpress.com/perl/quickform.html

BUGS
====

   If you get messages like this under pure mod_perl:

     [error] Undefined subroutine &Apache::xxxxxxx::handler called.

   the problem is with your configuration not QuickForm, and I won't be
able to help you. Please see the copious and high quality documentation at
`http:' in this node for help with this problem.

   If mod_perl prints things like "Content: text/html" at the top of your
forms it's a mod_perl issue; check your PerlSendHeader setting (I have it
Off).

   Some browsers get awfully confused about colouring rows and cells in
tables, so if you have problems with this please check the HTML that
QuickForm produces (via your browsers View Source command) - in my test
cases QuickForm always outputs correct HTML so the problem if any is with
the browser - however if you find that the HTML is invalid please email me
your script plus the HTML shown by View Source (in case I can't run your
script).

AUTHOR
======

   Mark Summerfield. I can be contacted as <summer@perlpress.com> - please
include the word 'quickform' in the subject line.

   Emails giving the URLs of the pages where you use QuickForm would be
appreciated!

   See CHANGES for acknowledgements.

COPYRIGHT
=========

   Copyright (c) Mark Summerfield 1999-2000. All Rights Reserved.

   This module may be used/distributed/modified under the LGPL.

Parse client request via a CGI interface
****************************************

NAME
====

   CGI::Request - Parse client request via a CGI interface

SYNOPSIS
========

     use CGI::Request;

     # Simple interface: (combines SendHeaders, new and import_names)

     $req = GetRequest($pkg);

     print FmtRequest();            # same as: print $req->as_string

     # Full Interface:

     $req = new CGI::Request;       # fetch and parse request

     $field_value = $req->param('FieldName');
     @selected    = $req->param('SelectMultiField');
     @keywords    = $req->keywords; # from ISINDEX

     print $req->as_string;         # format Form and CGI variables

     # import form fields into a package as perl variables!
     $req->import_names('R');
     print "$R::FieldName";
     print "@R::SelectMultiField";

     @value = $req->param_or($fieldname, $default_return_value);

     # Access to CGI interface (see CGI::Base)

     $cgi_obj = $req->cgi;
     $cgi_var = $req->cgi->var("REMOTE_ADDR");

     # Other Functions:

     CGI::Request::Interface($cgi);  # specify alternative CGI

     CGI::Request::Debug($level);    # log to STDERR (see CGI::Base)

     # Cgi-lib compatibility functions
     # use CGI::Request qw(:DEFAULT :cgi-lib); to import them

     &ReadParse(*input);
     &MethGet;
     &PrintHeader;
     &PrintVariables(%input);

DESCRIPTION
===========

   This module implements the CGI::Request object. This object represents
a single query / request / submission from a WWW user. The CGI::Request
class understands the concept of HTML forms and fields, specifically how
to parse a CGI QUERY_STRING.

SMALLEST EXAMPLE
----------------

   This is the smallest useful CGI::Request script:

     use CGI::Request;
     GetRequest();
     print FmtRequest();

SIMPLE EXAMPLE
--------------

   This example demonstrates a simple ISINDEX based query, importing
results into a package namespace and escaping of text:

     #!/usr/local/bin/perl  # add -T to test tainted behaviour

     use CGI::Base;
     use CGI::Request;

     GetRequest('R');       # get and import request into R::...

     # Just to make life more interesting add an ISINDEX.
     # Try entering: "aa bb+cc dd=ee ff&gg hh<P>ii"
     print "<ISINDEX>\r\n";

     print "<B>You entered:</B> ", # print results safely
           join(', ', CGI::Base::html_escape(@R::KEYWORDS))."\r\n";

     print FmtRequest();    # show formatted version of request

CGI
---

   A CGI::Request object contains a reference to a CGI::Base object (or an
object derived from CGI::Base). It uses the services of that object to get
the raw request information.

   Note that CGI::Request does not inherit from CGI::Base it just uses an
instance of a CGI::Base object.

   See the cgi method description for more information.

FEATURES
--------

   Is object oriented and sub-classable.

   Can export form field names as normal perl variables.

   Integrates with CGI::MiniSvr.

RECENT CHANGES
--------------

  1. Fixed bug in import_names().  Now works properly with both scalar and
     array elements.

  2. through 2.74 Minor changes to accomodate Forms interface.

  3. thru 2.3 Minor enhancements to documentation and debugging. Added
     notes about relationship with CGI and how to access CGI variables.

  4. Updates for changed CGI:Base export tags. No longer setting
     @CGI::Request::QUERY_STRING. Added param_or() method.

     The module file can be run as a cgi script to execute a demo/test. You
     may need to chmod +x this file and teach your httpd that it can
     execute *.pm files (or create a copy/symlink with another name).

  5. GetRequest now call SendHeaders (in CGI::Base) for you. This works
     *much* better than the old 'print PrintHeaders;'. PrintHeaders is no
     longer exported by default. as_string now uses the new html_escape
     method (in CGI::Base) to safely format strings with embedded html.
     Debugging now defaults to off. New Debug function added. Image map
     coords are automatically recognised and stored as parameters X and Y.
     Added a sequence number mechanism to assist debugging MiniSvr
     applications (does not impact/cost anything for non minisvr apps).

  6. Default package for import_names() removed, you must supply a package
     name. GetRequest() won't call import_names unless a package name has
     been given, thus GetRequest no longer defaults to importing names.
     Added as_string() method (which automatically calls cgi->as_string).
     param() will croak if called in a scalar context for a multi-values
     field.

FUTURE DEVELOPMENTS
-------------------

   None of this is perfect. All suggestions welcome.

   Note that this module is *not* the place to put code which generates
HTML.  We'll need separate modules for that (which are being developed).

AUTHOR, COPYRIGHT and ACKNOWLEDGEMENTS
--------------------------------------

   This code is Copyright (C) Tim Bunce 1995. All rights reserved.  This
code is free software; you can redistribute it and/or modify it under the
same terms as Perl itself.

   The cgi-lib functions are based on cgi-lib.pl version 1.7 which is
Copyright 1994 Steven E. Brenner.

   IN NO EVENT SHALL THE AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT,
INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OF THIS SOFTWARE AND ITS DOCUMENTATION (INCLUDING, BUT NOT LIMITED TO,
LOST PROFITS) EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

SEE ALSO
--------

   CGI::Base, URI::Escape

SUPPORT
-------

   Please use comp.infosystems.www.* and comp.lang.perl.misc for support.
Please do _NOT_ contact the author directly. I'm sorry but I just don't
have the time.

FUNCTIONS
=========

GetRequest
----------

     GetRequest();
     GetRequest($package_name);
     $req = GetRequest(...);

   GetRequest is the main entry point for simple (non-object oriented) use
of the CGI::Request module. It combines output (and flushing) of the
standard Content-Type header, request processing and optional importing of
the resulting values into a package (see import_names).

   This function also enables autoflush on stdout. This has a slight
efficiency cost but huge benefits in reduced frustration by novice users
wondering why, for example, the output of system("foo") appears before
their own output.

   See `new CGI::Request' for more details.

FmtRequest
----------

     print FmtRequest();

   Return a HTML string which describes the last (current) client request
parameters and the current raw CGI parameters.  Designed to be used for
debugging purposes.

Interface
---------

     $cgi = Interface();

   Return the default CGI interface object. Rarely used by applications.

   If no interface has been defined yet it will automatically create a new
CGI::Base object, set that as the default interface and return it. This is
the mechanism by which simple applications get to use the CGI::Base
interface without knowing anything about it.

   This function can also be use to define a new default interface (such
as CGI::MiniSvr) by passing a reference to a CGI::Base object or a object
derived from CGI::Base.

Debug
-----

     $old_level = CGI::Request::Debug();
     $old_level = CGI::Request::Debug($new_level);

   Set debug level for the CGI::Request module. Debugging info is logged
to STDERR (see CGI::Base for examples of how to redirect STDERR).

METHODS
=======

new
---

     $req = new CGI::Request;
     $req = new CGI::Request $cgi_interface;
     $req = new CGI::Request $cgi_interface, $timeout_in_seconds;

   CGI::Request object constructor. Only the first form listed above
should be used by most applications.

   Note that, unlike GetRequest, new CGI::Request does not call
SendHeaders for you. You have the freedom to control how you send your
headers and what headers to send.

   The returned $req CGI::Request object stores the request parameter
values. Parameters can be retrieved using the param method.

   Index keywords (ISINDEX) are automatically recognised, parsed and
stored as values of the 'KEYWORDS' parameter. The keywords method provides
an easy way to retrieve the list of keywords.

   Image Map (ISMAP) coordinates are automatically recognised, parsed and
stored as parameters 'X' and 'Y'.

as_string
---------

     print $req->as_string;

   Return an HTML string containing all the query parameters and CGI
parameters neatly and safely formatted. Very useful for debugging.

extract_values
--------------

     $req->extract_values($QUERY_STRING)

   This method extracts parameter name/value pairs from a string
(typically QUERY_STRING) and stores them in the objects hash.  Not
normally called by applications, new() calls it automatically.

   The parameter names and values are individually unescaped using the
uri_unescape() function in the URI::URL module.

   For ISINDEX keyword search requests (QUERY_STRING contains no '=' or
'&') the string is split on /+/ and the keywords are then individually
unescaped and stored.  Either the keywords() method (or param('KEYWORDS'))
can be used to recover the values.

keywords
--------

     @words = $req->keywords

   Return the keywords associated with an ISINDEX query.

params
------

     @names = $req->params

   Return a list of all known parameter names in the order in which
they're defined

param
-----

     $value  = $req->param('field_name1');
     @values = $req->param('field_name2');	# e.g. select multiple
     $req->param('field_name3', $new_value);
     $req->param('field_name4', @new_values);

   Returns the value(s) of a named parameter. Returns an empty list/undef
if the parameter name is not known. Returns " for a parameter which had no
value.

   If invoked in a list context param returns the list of values in the
same order they were returned by the client (typically from a select
multiple form field).

   Warning: If invoked in a scalar context and the parameter has more than
one value the param method will die. This catches badly constructed forms
where a field may have been copied but its name left unchanged.

   If more than one argument is provided, the second and subsequent
arguments are used to set the value of the parameter. The previous values,
if any, are returned. Note that setting a new value has no external effect
and is only included for completeness.

   Note that param does not return CGI variables (REMOTE_ADDR etc) since
those are CGI variables and not form parameters. To access CGI variables
see the cgi method in this module and the CGI::Base module documentation.

delete
------

     $req->delete('field_name1');

   Remove the specified field name from the parameter list

param_or
--------

     $value  = $req->param_or('field_name1', $default);
     @values = $req->param_or('field_name2', @defaults);

   If the current request was a query (QUERY_STRING defined) then this
method is identical to the param method with only one argument.

   If the current request was not a query (QUERY_STRING undefined) then
this method simply returns its second and subsequent parameters.

   The method is designed to be used as a form building utility.

import_names
------------

     $req->import_names('R')

   Convert all request parameters into perl variables in a specified
package. This avoids the need to use $req->param('name'), you can simply
sat $R::name ('R' is the recommended package names).

   Note: This is a convenience function for simple CGI scripts. It should
not be used with the MiniSvr since there is no way to reset or unimport
the values from one request before importing the values of the next.

cgi
---

     $cgi = $req->cgi;

   This method returns the current CGI::Request default CGI interface
object.  It is primarily intended as a handy shortcut for accessing
CGI::Base methods: $req->cgi->done(), $req->cgi->var("REMOTE_ADDR");

Respond to CGI requests
***********************

NAME
====

   *CGI::Response* - Respond to CGI requests

SYNOPSIS
========

Simple Interface
----------------

     use CGI::Response qw(:Simple);
     print ContentType;
     print "<html><head>\n"; # .....

Full Interface
--------------

     use CGI::Response;
     $response = new CGI::Response;
     $response->content_type;
     print $response->as_string;
     print "<html><head>\n"; # .....

DESCRIPTION
===========

   *CGI::Response* is a Perl5 module for constructing responses to Common
Gateway Interface (CGI) requests.  It is designed to be light-weight and
efficient for the most common tasks, and also to provide access to all
HTTP response features for more advanced CGI applications.

   There are two ways to use CGI::Response.  For basic applications, the
Simple Interface provides a number of plain functions that cover the most
commonly-used CGI response headers.  More advanced applications may employ
the Full Interface object methods to access any HTTP header, or to add
experimental or non-standard headers.  Both interfaces try to generate
reasonable defaults whenever possible.

   For efficiency, just the Simple Interface functions are compiled on
start-up.  Full Interface methods are compiled only when they are called.
This helps to make CGI::Response usable in a variety of applications.
[See SelfLoader, for more information.]

Simple Interface
----------------

   The Simple Interface methods are not exported by default.  In order to
use them, you must import them explicitly.  You can import all of the
methods at once by saying:

     use CGI::Response qw(:Simple);

   Or, you can import just one function by listing it by name, as in:

     use CGI::Response qw(ContentType);

   Only one Simple Interface function should be called in a response,
since all of these functions terminate the response header (that is, send
the blank line denoting the end of the header) immediately upon execution.
If you need to use a combination of headers not provided by the Simple
Interface, use the Full Interface instead.

   All of the Simple Interface functions force a flush on the
currently-selected output channel (that is, they set `$| = 1').  This is
done to prevent a common probelm in CGI scripts, where a `system()' or
exec() call causes output before the response header, and generates a
server error.  If you do not want `$| = 1', you should either set it back
to 0 after using the Simple Interface, or you should employ the Full
Interface, which does not have this side effect.

   For reference, below is a list of the headers sent by each function,
and the default header values, if any.  Arguments are listed in the order
they should appear.  Square brackets ([]) indicate optional arguments;
angled brackets (<>) indicate required arguments.

     Function      Argument(s)      Header(s)      Default(s)
     --------      -----------      ---------      ----------
     &ContentType  [content-type]   Content-Type   text/html

     &Redirect     <Location/URI>   Location       [none]
                   [permanent?]     URI            [none]
                                    Content-Type   text/html
                                    Status         302 Moved Temporarily

     &NoCache      [content-type]   Content-Type   text/html
                                    Pragma         no-cache
                                    Expires        [now]

     &NoContent                     Status         204 No Content

   Each of these functions is documented more completely below, and
examples for each are provided.

&ContentType
     This is the most commonly-used function.  It identifies the Internet
     Media Type of the entity that follows.  If you call it without an
     argument, it will send `text/html' as the content-type.

          use CGI::Response qw(:Simple);
          print &ContentType;   # defaults to text/html

     Otherwise, you can specify some other content-type:

          use CGI::Response qw(:Simple);
          print &ContentType('image/gif');

     This function should be called as early as possible to prevent server
     errors (see the note on $| above).

&Redirect
     A redirect causes the user-agent to make a follow-up request for some
     other resource.  Some user-agents will be better than others at
     complying with a redirect, so this function tries to be as explicit as
     possible.

     You are required to give one argument, specifying the URL which the
     user-agent should request.  A second argument is accepted as a Boolean
     value - if any second argument is present, the browser will be told
     that the requested resource has moved permanently to a new URL (that
     is, future requests for the document should be to the new URL, not to
     the one which was first requested).

          use CGI::Response qw(:Simple);
          print &Redirect('http://www.company.com/', 'permanent');
          # this resource has moved permanently, status 301

     If no second argument is given, the redirect will be specified as
     temporary.

          use CGI::Response qw(:Simple);
          print &Redirect('http://www.company.com/');
          # this resource has moved temporarily, status 302

     A brief HTML page is output after the header so that users whose
     user-agents fail to recognize the redirect will get an informative
     message with a link to the redirect.  Use the Full Interface to supply
     some other page or none at all.

&NoCache
     This function tries to inform user-agents and proxy servers that the
     included resource should not be cached.  It does so by sending both an
     `Expires' header, set for immediate expiration, and a `Pragma:
     no-cache' header, which older user-agents and servers might not
     recognize.

     Preventing caching is important to CGI applications which produce
     output based on some factor of the request (such as which user-agent
     made the request).  For instance, a shopping-basket application would
     not want to allow caching of an order information page, which may
     contain user-specific information.

     It must be noted, however, that caches prevent excess network load and
     cache-friendly applications are always preferable to use of the
     &NoCache function.  This function should only be used when there is no
     other alternative.

     &NoCache takes one optional argument, the content-type of the entity
     to follow.  Therefore, its call is nearly identical to the
     &ContentType function, and the two functions may be interchanged
     easily.  As with &ContentType, if you call &NoCache without an
     argument, it will send `text/html' as the content-type.

          use CGI::Response qw(:Simple);
          print &NoCache;   # defaults to text/html

     Otherwise, you can specify some other content-type:

          use CGI::Response qw(:Simple);
          print &NoCache('image/gif');

     As noted earlier, this function should be called as early as possible
     to prevent server errors (see the note on $| above).

&NoContent
     &NoContent allows a script to accept input without changing the
     current page in the user-agent's view.  This may be useful for a
     successful form input that requires no response, or for an imagemap
     click that does not have a defined link.

     A No Content response does not reset form fields after submission.
     HTTP/1.1 will include a `205 Reset Document' status for this purpose,
     and a future version of this module will provide a &Reset function to
     support this status.

     This function sends only one header, `Status: 204 No Content', and it
     takes no arguments.

          use CGI::Response qw(:Simple);
          print &NoContent;

Full Interface
--------------

   The Full Interface is still under development and is not currently
documented.

DEPENDENCIES
============

SEE ALSO
========

   CGI::Base(3pm), CGI::BasePlus(3pm), CGI::Request(3pm), CGI::Lite(3pm),
CGI(3pm), CGI::Form(3pm), LWP(3pm), SelfLoader(3pm)

NOTES
=====

   Please note that future versions are not guaranteed to be
backwards-compatible with this version.  The interface will be frozen at
version 0.1 (first beta release).

VERSION
=======

     Version:      0.03 (alpha release)
     Release date: 02 December 1995

AUTHOR
======

     Marc Hedlund <hedlund@best.com>
     Copyright 1995, All rights reserved

Use SSI from CGI scripts
************************

NAME
====

     CGI::SSI - Use SSI from CGI scripts

SYNOPSIS
========

     # autotie STDOUT or any other open filehandle

     use CGI::SSI (autotie => STDOUT);

     print $shtml; # browser sees resulting HTML

     # or tie it yourself to any open filehandle

     use CGI::SSI;

     open(FILE,'+>'.$html_file) or die $!;
     $ssi = tie(*FILE, 'CGI::SSI', filehandle => 'FILE');
     print FILE $shtml; # HTML arrives in the file

     # or use the object-oriented interface

     use CGI::SSI;

     $ssi = CGI::SSI->new();

     $ssi->if('"$varname" =~ /^foo/');
        $html .= $ssi->process($shtml);
     $ssi->else();
        $html .= $ssi->include(file => $filename);
     $ssi->endif();

     print $ssi->exec(cgi => $url);
     print $ssi->flastmod(file => $filename);

     #
     # or roll your own favorite flavor of SSI
     #

     package CGI::SSI::MySSI;
     use CGI::SSI;
     @CGI::SSI::MySSI::ISA = qw(CGI::SSI);

     sub include {
        my($self,$type,$file_or_url) = @_;
        # my idea of include goes something like this...
        return $html;
     }
     1;
     __END__

DESCRIPTION
===========

   CGI::SSI is meant to be used as an easy way to filter shtml through CGI
scripts in a loose imitation of Apache's mod_include.  If you're using
Apache, you may want to use either mod_include or the Apache::SSI module
instead of CGI::SSI. Limitations in a CGI script's knowledge of how the
server behaves make some SSI directives impossible to imitate from a CGI
script.

   Most of the time, you'll simply want to filter shtml through STDOUT or
some other open filehandle. `autotie' is available for STDOUT, but in
general, you'll want to tie other filehandles yourself:

     $ssi = tie(*FH, 'CGI::SSI', filehandle => 'FH');
     print FH $shtml;

   Note that you'll need to pass the name of the filehandle to tie() as a
named parameter. Other named parameters are possible, as detailed below.
These parameters are the same as those passed to the new() method.
However, new() will not tie a filehandle for you.

   CGI::SSI has it's own flavor of SSI. Test expressions are Perlish.  You
may create and use multiple CGI::SSI objects; they will not step on each
others' variables.

   Object-Oriented methods use the same general format so as to imitate
SSI directives:

     <!--#include virtual="/foo/bar.footer" -->

     would be

     $ssi->include(virtual => '/foo/bar.footer');

   likewise,

     <!--#exec cgi="/cgi-bin/foo.cgi" -->

     would be

     $ssi->exec(cgi => '/cgi-bin/foo.cgi');

   Usually, if there's no chance for ambiguity, the first argument may be
left out:

     <!--#echo var="var_name" -->

     could be either

     $ssi->echo(var => 'var_name');

     or

     $ssi->echo('var_name');

   Likewise,

     $ssi->set(var => $varname, value => $value)

     is the same as

     $ssi->set($varname => $value)

$ssi->new([%args])
     Creates a new CGI::SSI object. The following are valid (optional)
     arguments:

          DOCUMENT_URI    => $doc_uri,
          DOCUMENT_NAME   => $doc_name,
          DOCUMENT_ROOT   => $doc_root,
          errmsg          => $oops,
          sizefmt         => ('bytes' || 'abbrev'),
          timefmt         => $time_fmt,

$ssi->config($type, $arg)
     $type is either 'sizefmt', 'timefmt', or 'errmsg'. $arg is similar to
     those of the SSI spec, referenced below.

$ssi->set($varname => $value)
     Sets variables internal to the CGI::SSI object. (Not to be confused
     with the normal variables your script uses!) These variables may be
     used in test expressions, and retreived using $ssi->echo($varname).

$ssi->echo($varname)
     Returns the value of the variable named $varname. Such variables may
     be set manually using the set() method. There are also several
     built-in variables:

          DOCUMENT_URI  - the URI of this document
          DOCUMENT_NAME - the name of the current document
          DATE_GMT      - the same as 'gmtime'
          DATE_LOCAL    - the same as 'localtime'
          FLASTMOD      - the last time this script was modified

$ssi->exec($type, $arg)
     $type is either 'cmd' or 'cgi'. $arg is similar to the SSI spec (see
     below).

$ssi->include($type, $arg)
     Similar to exec, but `virtual' and file are the two valid types.

$ssi->flastmod($type, $filename)
     Similar to include.

$ssi->fsize($type, $filename)
     Same as `flastmod'.

$ssi->printenv
     Returns the environment similar to Apache's mod_include.

FLOW-CONTROL METHODS
--------------------

   The following methods may be used to test expressions. During a block
where the test $expr is false, nothing will be returned (or printed, if
tied).

$ssi->if($expr)
     The expr can be anything Perl, but care should be taken. This causes
     problems:

          $ssi->set(varname => "foo");
          <!--#if expr="'\$varname' =~ /^foo$/" -->ok<!--#endif -->

     The $varname is expanded as you would expect. (We escape it so as to
     use the `$varname' within the CGI::SSI object, instead of that within
     our progam.) But the $/ inside the regex is also expanded. This is
     fixed by escaping the `$':

          <!--#if expr="'\$varname' =~ /^value\$/" -->ok<!--#endif -->

     The expressions used in if and elif tags/calls are tricky due to the
     number of escapes required. In some cases, you'll need to write
     `\\\\' to mean \.

$ssi->elif($expr)
$ssi->else
$ssi->endif
SEE ALSO
========

   `Apache::SSI' and the SSI spec at
http://www.apache.org/docs/mod/mod_include.html

COPYRIGHT
=========

   Copyright 2000 James Tolley   All Rights Reserved.

   This is free software. You may copy and/or modify it under the same
terms as perl itself.

AUTHOR
======

   James Tolley <james@jamestolley.com>

Implement SSI for Perl CGI
**************************

NAME
====

   CGI::SSI_Parser - Implement SSI for Perl CGI

SYNOPSIS
========

     use CGI::SSI_Parser;

     $CGI::SSI_Parser::recursive = 1;

     fssi($filename);
     sssi($string);

DESCRIPTION
===========

   CGI::SSI_Parser is used in CGI scripts for parsing SSI directives in
files or string variables, and fully implements the functionality of
apache's mod_include module.

   It is an alternative to famous Apache::SSI modules, but it doesn't
require mod_perl. This is an advantage to those who are using public
hosting services.  There is a disadvantage, however - the module consumes
much memory, and I don't recommend using it on heavy-loaded sites
(currently it's being used on a site with 10000 hits, and I consider this
as a limit). I hope to get rid of this disadvantage by the time the
release comes out (currently it's beta).

SSI Directives
--------------

   This module supports the same directives as mod_include. For methods
listed below but not documented, please see mod_include's online
documentation at http://httpd.apache.org/docs/mod/mod_include.html .

   * config

   * echo

     This directive is not fully supported in current version.

   * exec

   * fsize

   * flastmod

   * include

   * printenv

   * set

     This directive is not supported in current version.

   * perl

     This directive is not supported in current version.

   * if

   * elif

   * else

   * endif

     These four directives are not supported in current version.

Outline Usage
-------------

   First you need to load the CGI::SSI_Parser module:

     use CGI::SSI_Parser;

   You need to specify the following when processing of all nested
directives is needed (default value - 0):

     $CGI::SSI_Parser::recursive = 1;

   To parse file or string you need to use:

     fssi($filename);
     sssi($string);

   The result is printed to STDOUT.

TO DO
=====

   Full implementation of all SSI directives.

   Optimize memory consumption.

AUTHOR
======

   Vadim Y. Ponomarenko, vp@istc.kiev.ua

SEE ALSO
========

   mod_include, perl(1).

Perl extension for easy creation of multi screen CGI scripts
************************************************************

NAME
====

   CGI::Screen - Perl extension for easy creation of multi screen CGI
scripts

SYNOPSIS
========

     use CGI::Screen;
     use vars qw(@ISA);
     @ISA = qw(CGI::Screen);

     my $query = __PACKAGE__->new;

     $query->dispatch;

WARNING
=======

   This is *alpha* software. User visible changes can happen any time.

DESCRIPTION
===========

   *CGI::Screen* is a subclass of CGI which allows the esay(TM) creation
of simple multi screen CGI scripts. By 'multi screen' I mean scripts which
present different screens to the user when called with different
parameters. This is the common case for scripts linking to themselves.

   To use *CGI::Screen*, you have to subclass it. For each screen you want
to present to the user, you must create a method *screen_name*`screen_'.
This method has to produce the HTML code for the screen. CGI::Screen does
generate HTTP headers and an HTML framework for you. The HTML framework
already contains the FORM tags.  You can customize the HTTP headers and
the HTML framework by providing callback methods.

   CGI::Screen keeps track of the CGI parameters used in your screen and
passes old parameters which are not used in the current screen.

   It highjacks the parameters `screen_'* to dispatch the different
screens the script implements. The `screen_user' and `screen_passwd'
fields are used if you enable the builtin simple authentication.  In
general you should advice your HTTP server to do authentication. But
sometimes it is convenient to check the authentication at the script
level. Especially if you do not have access to your server's configuration.

The constructor new
-------------------

   If the first parameter of new is the string `-screen' the second
argument must be a hash reference specifying the options for the subclass.
Other parameters are passed to the constructor of CGI.

`-dont_cut_loops'
     Normaly the history of pages will not be extended if the current page
     is the same as the last page. So looping on a page will not change the
     result of the `last_screen' method. If the option `-dont_cut_loops'
     is provided and true, the page will recorded twice. A third visit will
     be interpreted as jump back to the first visit.

     *That sounds weird. Will have to figure out a way to recognize back
     jumps independent of the history.*

Adding Screens
--------------

   All applications should provide a main screen by defining a method
`main_screen'. This method is called if no (existing) screen is specified
in the parameters. The method is called with three arguments: The query
object, the screen name and the screen title (More precisely the third
parameter, if present, is the text on the button or anchor which caused
the jump to this page).

   So the minimal application looks like this:

     use CGI::Screen;
     use vars qw(@ISA);
     @ISA = qw(CGI::Screen);

     my $query = __PACKAGE__->new;

     $query->dispatch;

     sub main_screen {
       my $query = shift;

       print $query->p('This is the Main Screen');
     }

   That is not too exciting. Let us add a second screen and allow
navigation between the screens:

     sub main_screen {
       my $query = shift;

       print
         $query->p('This is the Main Screen'),
         $query->goto_screen('second', 'Another Screen');
     }
     sub second_screen {
       my $query = shift;

       print
         $query->p('This is the Other Screen'),
         $query->goto_screen('main', 'Back to Main Screen');

     }

Moving between screens
----------------------

   Use the method `goto_screen' to produce a button for switching to
another screen.  You can also produce an anchor instead of a button by
calling `link_to_screen' instead of `goto_screen'. You may pass additional
parameters to encode:

     for my $docid (keys %score) {
       print $query->link_to_screen('display', $title{$docid},
                                    'docid' => $docid,
                                    'score' => $score{$docid});
     }

   For convenience, CGI::Screen keeps track of the last screen for you so
that you can link to the previous page. Note that only the last seven
screens are saved:

     my $screen = $query->last_screen;
     print
       $query->p("You came from screen $screen. Press "),
       $query->goto_screen($query->last_screen),
       $query->p(" to go back");

   `last_screen' returns screen name and title in list context and screen
name in scalar context. Do not use the CGI parameters `screen_last_*'
since they are changed before you can get hold of them `;-P'

The callbacks
-------------

   All callbacks are called with three arguments: The query object, the
screen name and the screen title (= button/anchor text). Callbacks should
return a string.

application
     The application method returns a string which is used in the default
     title and headline callbacks. The Default method returns the string
     `"CGI::Screen Test"' and should definitely be overwritten by your
     application.

title
     The result of the method is used in the HTTP header and in the default
     headline. It defaults to the application.

headline
     The headline method should return a chunk of HTML code to start the
     Screen. It defaults to the title enclosed in `H1' tags.

Authentication
--------------

   To enable password authentication, define a method `check_auth_user'.
The dispatcher will call the method with the user and password entered by
the user. The method should return true if the authentication succeeded
and false otherwise. The dispatcher will present the `login_screen' if the
authentication failed.

     sub check_auth_user {
       my ($query, $user, $passwd) = @_;

     $user eq 'pfeifer';
       }

   For IP address based authentication define the method `check_auth_ip'.

     sub check_auth_ip {
       my ($query, $ipaddr) = @_;

     $ipaddr =~ /^(193\.96\.65\.|139\.4\.36\.)/;
       }

   If you do not like the default login screen, overwrite with your own
`login_screen'. Use the CGI parameters `screen_user' and `screen_passwd'.

Customizing the Title
---------------------

   You may provide a custom title method to generate a title for your
screens.

     sub title {
       my ($query, $screen)  = shift;

       $query->application . ': ' . $screen;
     }

Customizing the Headline
------------------------

   You may provide a custom headline method to generate a HTML chunk to
start your screens.

     sub headline { $_[0]->h1(title(@_)) }

   You should overwrite the application method if you use the default
title and headline.

     sub application { 'CGI::Screen Test' }

Customizing the Trailer
-----------------------

   For a custom Trailer, define the `trailer' method.

     sub trailer {
       my ($query, $screen)  = shift;

       "End of Screen $screen";
     }

Multiple Forms
--------------

   If you want to have multiple forms on one screen, call the method
`new_form'.

     sub multi_screen {
        my $query = shift;

     print
       $query->p('This is the Main Screen'),
       $query->textfield('foo'),
       $query->goto('First'),
       $query->new_form,
       $query->textfield('foo'),
       $query->goto('Second');
       }

Non HTML screens
----------------

   You can create non HTML screens by defining a name`_data' method
instead of a <name>`_screen' method. For data screens you have to generate
HTTP headers yourself.

     sub gif_data {
       my $query = shift;

       print $query->header(
                            -type    => 'image/gif',
                            -status  => '200 OK',
                            -expires => '+120s',
                           );
       my $font  = $query->param('font');
       my $w     = GD::Font->$font()->width;
       my $h     = GD::Font->$font()->height;
       my $im    = GD::Image->new((length($query->param('foo'))+2)*$w,$h);
       my $white = $im->colorAllocate(255,255,255);
       my $red   = $im->colorAllocate(255,0,0);
       my $black = $im->colorAllocate(0,0,0);
       $im->transparent($white);
       $im->arc(8,8,5,5,0,360,$red);
       $im->string(GD::Font->$font(),10,0,$query->param('foo'),$black);
       print $im->gif;
     }

Keeping parameter values
------------------------

   CGI::Screen keeps track of the CGI parameters used in the current form.
It simply looks at the first parameter in any call to a CGI method.  If
the first parameter is `-name', the second parameter is marked as *used
parameter*.  CGI::Screen passed all current parameter values not used in
hidden fields or in the query string of an anchor. So do not use old style
CGI calls to bypass this mechanism or you will end up with multiple values
for the parameters.

   If you want to get rid of a parameter, you must explicitly call the
delete method of CGI.

BUGS
====

   Support for importing from CGI.pm is incomplete.

AUTHOR
======

   Ulrich Pfeifer <`pfeifer@wait.de'>

SEE ALSO
========

   The CGI(3) manual and the demo CGI script `eg/screen' included in the
distribution.

ACKNOWLEDGEMENTS
================

   I wish to thank Andreas Koenig `koenig@kulturbox.de' for the fruitful
discussion about the design of this module.

Copyright
=========

   The *CGI::Screen* module is Copyright (c) 1997,1998 Ulrich Pfeifer.
Germany.  All rights reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

Converts CGI parameters into a multi-dimensional hash
*****************************************************

NAME
====

   CGI::State - Converts CGI parameters into a multi-dimensional hash

SYNOPSIS
========

   First you make your HTML form to submit to your CGI script.  For
example:

     <form action="order.cgi">
       <input type="text" name="Contact.first_name" value="Dan" />
       <input type="text" name="Contact.email" value="dan@mealtips.com" />
       <input type="hidden" name="item[0].price" value="10.00" />
       <input type="hidden" name="item[0].description" value="Widget" />
       <input type="submit" value="Order Now!" />
     </form>

   Notice the names of the hidden and text fields? Keep this in mind.  Then
you create a CGI script to receive the form variables after they're
submitted:

     #!/usr/bin/perl -wT

     use strict;
     use CGI;
     use CGI::State;
     use Data::Dumper;

     #Simulate receiving CGI parameters
     my $cgi = CGI->new;

     #Un-Flatten the data structure
     my $state = CGI::State->state( $cgi );

     #Show us what the $state hashref now looks like...
     print $cgi->header('text/plain'), Data::Dumper->new([$state], [qw(state)])->Indent(3)->Quotekeys(0)->Dump;

     #Which would print out the following data structure:
     $state = {
                Contact => {
                             first_name => 'Dan',
                             email => 'dan@mealtips.com'
                           },
                item => [
                          #0
                          {
                            description => 'Widget',
                            price => '10.00'
                          }
                        ]
              };

     #Also, you can change $state back into the original query string:
     $cgi = CGI::State->cgi( $state );

     print $cgi->query_string;

     #Which would print out: (in no particular order)
     Contact.first_name=Dan&Contact.email=dan@mealtips.com&item[0].price=10.00&item[0].description=Widget

DESCRIPTION
===========

   This module takes incoming *CGI form variables*, and transforms them
into a *multi-dimensional data structure*.  It can recreate a hash of
hashes, a hash of lists, a hash of lists of hashes etc, any number of
levels deep.

   A limitation of CGI is it's inability to naturally group together
submitted variables.  For example, you can't have someone fill in an order
form and have all their contact and item information grouped separate from
each other in a perl data structure without specifically doing this in the
perl code.

   This module was originally written because I always hated receiving CGI
parameters, putting them into a hash, and have this hash contain 20 or
more elements.  I think it's messy, and very tedious writing code to group
related CGI parameters together.  I wanted parameters to be put into a
multi-dimensional data structure automatically for me.

METHODS
=======

$state = CGI::State->state( $cgi )
     This routine takes one argument, a CGI.pm object reference.

     It will return a hashref containing as many levels as specified in
     the input parameters.

     It allows you to logically group together form elements, so that when
     the CGI script receives them, it has to do no logic of it's own to
     group things together.

     This routine cycles through all the form variables and looks for the
     following format:

          $object_name[$index].$attribute <-- Multivalued

          OR

          $object_name.$attribute         <-- Single valued

          ...And translates them into the following:

          $hashref = {

          $object_name => [

          #$index = 0
          { $attribute => $value },

          #$index = 1
          { $attribute => $value },

          #...

          ],
            }

     It also puts all non-objects into the top-level of the hashref.

     The format I choose to describe the data structure closely resembles
     Javascript's style.  I know, I know. But the syntax is close to perl,
     and should be fairly simple for most perl programmers to pick up.  In
     the future I may change this module to allow you to specify different
     delimeters, to allow more perl-like syntax.

$cgi = CGI::State->cgi( $state )
     This routine takes one argument, a multi-dimensional hash.

     It will return a *flattened* CGI object based on the values
     referenced by $state.  Very useful for maintaining state across
     various CGI invocations.

EXAMPLES
========

   One major advantage to grouping parameters together in a
multi-dimensional data structure is that you have everything map into your
database cleanly.

   For example, let's say that we have a relational table called
*Contact*, which stores information about a customer.  Inside this table
there are three columns called first_name, last_name, and email.

   Imagine there is a form where customer information is collected, such
as the following:

     <form action="save_customer.cgi">
       <input type="text" name="Contact.first_name" />
       <input type="text" name="Contact.last_name" />
       <input type="text" name="Contact.email"  />
     </form>

   When this form is submitted, we create a CGI.pm object to capture the
data, then pass this object off to CGI::State->state, which returns a hash
reference:

     my $cgi   = CGI->new;           #Create the CGI Object
     my $state = CGI::State( $cgi ); #$state is a hash reference

   Assuming that we submit the form, the hash reference would look like
this, as shown by Data::Dumper:

     $state = {
                Contact => {
                             first_name => 'Dan',
                             last_name  => 'Kubb'
                             email      => 'dan@mealtips.com'
                           },
     };

   With this structure, it would be rather easy just to pass off
$state->{Contact} to a subroutine that inserts Contact information into a
database.  There's no sorting, grouping or hard-coding the column names
anywhere in your code!  I am a firm believer that the database table and
column names should dictate the HTML form parameter names, and perl hash
element names.  This module helps enforce that and make it easier to write
code that will "map" HTML forms into a database with minimal effort.

LIMITATIONS
===========

   Having the ability to manipulate the data with simple HTML can either
be seen as a benefit or a liability. I find it a benefit, but I can
imagine that others might not see it that way, especially when
non-programmers are responsible for constructing all web forms.

   Anything you expect to be a hash key should not be a number.

TODO
====

   * Add more security measures and error checking.

SEE ALSO
========

   See CGI,

AUTHOR
======

   Copyright 2001, Dan Kubb <dan@mealtips.com>

   This module is distributed under the same terms as Perl itself.  Feel
free to use, modify and redistribute it as long as you retain the correct
attribution.

Backward compatibility module for defunct CGI::Switch
*****************************************************

NAME
====

   CGI::Switch - Backward compatibility module for defunct CGI::Switch

SYNOPSIS
========

   Do not use this module.  It is deprecated.

ABSTRACT
========

DESCRIPTION
===========

AUTHOR INFORMATION
==================

BUGS
====

SEE ALSO
========

Internal utilities used by CGI module
*************************************

NAME
====

   CGI::Util - Internal utilities used by CGI module

SYNOPSIS
========

   none

DESCRIPTION
===========

   no public subroutines

AUTHOR INFORMATION
==================

   Copyright 1995-1998, Lincoln D. Stein.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Address bug reports and comments to: lstein@cshl.org.  When sending bug
reports, please provide the version of CGI.pm, the version of Perl, the
name and version of your Web server, and the name and version of the
operating system you are using.  If the problem is even remotely browser
dependent, please provide information about the affected browers as well.

SEE ALSO
========

   See CGI,

Advanced CGI form parser and type validation
********************************************

NAME
====

   CGI::Validate - Advanced CGI form parser and type validation

SYNOPSIS
========

     use CGI::Validate;                # GetFormData() only
     use CGI::Validate qw(:standard);  # Normal use
     use CGI::Validate qw(:subs);      # Just functions
     use CGI::Validate qw(:vars);      # Just exception vars

     ## If you don't want it to check that every requested
     ## element arrived you can use this.  But I don't recommend it
     ## for most users.
     $CGI::Validate::Complete = 0;

     ## If you don't care that some fields in the form don't
     ## actually match what you asked for. -I don't recommend
     ## this unless you REALLY know what you're doing because this
     ## normally meens you've got typo's in your HTML and we can't
     ## catch them if you set this.
     ## $CGI::Validate::IgnoreNonMatchingFields = 1;

     my $FieldOne    = 'Default String';
     my $FieldTwo    = 8;
     my $FieldThree  = 'some default string';
     my @FieldFour   = ();  ## For multi-select field
     my @FieldFive   = ();  ## Ditto
     my $EmailAddress= '';

     ## Try...
     my $Query = GetFormData (
         'FieldOne=s'  => \$FieldOne,     ## Required string
         'FieldTwo=i'  => \$FieldTwo,     ## Required int
         'FieldThree'  => \$FieldThree,   ## Auto converted to the ":s" type
         'FieldFour=s' => \@FieldFour,    ## Multi-select field of strings
         'FieldFive=f' => \@FieldFive,    ## Multi-select field of floats
         'Email=e'     => \$EmailAddress, ## Must 'look' like an email address
     ) or do {
         ## Catch... (wouldn't you just love a case statement here?)
         if (%Missing) {
             die "Missing form elements: " . join (' ', keys %Missing);
         } elsif (%Invalid) {
             die "Invalid form elements: " . join (' ', keys %Invalid);
         } elsif (%Blank) {
             die "Blank form elements: " . join (' ', keys %Blank);
         } elsif (%InvalidType) {
             die "Invalid data types for fields: " . join (' ', keys %InvalidType);
         } else {
             die "GetFormData() exception: $CGI::Validate::Error";
         }
     };

     ## If you only want to check the form data, but don't want to
     ## have CGI::Validate set anything use this. -You still have full
     ## access to the data via the normal B<CGI> object that is returned.

     use CGI::Validate qw(CheckFormData); # not exported by default
     my $Query = CheckFormData (
       'FieldOne=s',   'FieldTwo=i',   'FieldThree',   'FieldFour',
       'FieldFive',    'Email',
     ) or do {
         ... Same exceptions available as GetFormData above ...
     };

     ## Need some of your own validation code to be used?  Here is how you do it.
     addExtensions (
         myType   => sub { $_[0] =~ /test/ },
         fooBar   => \&fooBar,
         i_modify_the_actual_data => sub {
             if ($_[0] =~ /test/) {   ## data validation
                 $_[0] = 'whatever';  ## modify the data by alias
                 return 1;
             } else {
                 return 0;
             }
        },
     );
     my $Query = GetFormData (
         'foo=xmyType'    => \$foo,
         'bar=xfooBar'    => \$bar,
         'cat=xi_modify_the_actual_data' => \$cat,
     );

     ## Builtin data type checks available are:
     s    string     # Any non-zero length value
     w    word       # Must have at least one \w char
     i    integer    # Integer value
     f    float      # Float value
     e    email      # Must match m/^\s*<?[^@<>]+@[^@.<>]+(?:\.[^@.<>]+)+>?\s*$/
     x    extension  # User extension type.  See EXTENSIONS below.

DESCRIPTION
===========

   Basicly a blending of the CGI and Getopt::Long modules, and requires
the CGI module to function.

   The basic concept of this module is to combine the best features of the
CGI and Getopt::Long modules.  The CGI module is great for parsing,
building, and rebuilding forms, however it lacks any real error checking
abilitys such as misspelled form input names, the data types received from
them, missing values, etc.  This however, is something that the
Getopt::Long module is vary good at doing.  So, basicly this module is a
layer that collects the data using the CGI module and passes it to
routines to do type validation and name consistency checks all in one
clean try/catch style block.

   The syntax of GetFormData() is mostly the same as the GetOptions() of
Getopt::Long, with a few exceptions (namely, the handling of exceptions) .
See the VALUE TYPES section for detail of the available types, and the
EXCEPTIONS section for exception handling options.  If given without a
type, fields are assumed to be type ":s" (optional string), which is
normally correct.

   If successful, GetFormData() returns the CGI object that it used to
parse the data incase you want to use it for anything else, and undef
otherwise.

   If you only want to do value type and name validation, use
CheckFormData() instead with a field=type list. -See the SYNOPSIS for an
example.

VALUE TYPES
===========

   All types are prefixed with either a ":" or "=".

   Just like in Getopt::Long, the ":" prefix meens that the value is
optional, but still much match the type that is defined if it is given.
The "=" prefix meens that the value is required for this field, and of
course much match the type given.  If you just want to make sure that some
value is there but don't care about the type, use the required string type
"=s", or required word type "=w".

s
     String type.  Any string will do if the field is optional.  If the
     field is required, then this checks to see if the value length is
     greater then 0.

w
     Word type.  Value must contain at least one \w char to be valid.
     Similar to a s (string) type, but oftin more useful.

i
     Integer type.

f
     Real number (float) type.  Data must be in '1.2' or '12' format.

e
     Email type.  Must look like a valid email address.  White space on
     either end (but not in the middle) is permitted.

          The regex used currently is m/\s*^<?[^@<>]+@[^@.<>]+(\.[^@.<>]+)+>?\s*$/.

xTYPE
     User defined type.  See the EXTENSIONS section below.  This is where
     you get to make up your own tests for this module to use.

EXCEPTIONS
==========

   Exceptions are handled by returning undef, and setting one or more of
five different package global variables.  Think of them first as exception
objects if you must. -They aren't, but they kinda act like it, kinda...
We must use this method until Perl ever gets a real exception system
(eval/die doesn't quite cut it here because we need more information and
with a cleaner way to access it).

   The exceptions are:

%Missing
     Contains all field names we were asked to check for, but the form
     didn't send us at all.  This is not the same as a field that did get
     sent but had no data.  Oftin this is from GetFormData() being given a
     misspelled field name, or the form being sent in an odd manor such as
     an alternate 'submit' button, or just hitting the enter key while in
     the last (probably only) field.

     Probably code bug generated exception.  Check for typos.

%Invalid
     All fields that were not asked to be checked for, but the form sent
     them along anyway.  Most likely these are misspelled field names in
     the HTML form page.

     Probably code bug generated exception.  Check for typos.

%Blank
     All valid fields that were sent with no value AND the type given was
     set to '=' to require the field to be filled in.  The user probably
     just didn't fill in the field(s) at all.  It's not a bad practice to
     make all required fields in form with the word '(required)' next to
     them.  Some users will try many times to fill in a form with as
     little information as they can, as lame as such practice really is.

     Probably a lazy user error generated exception.  Kick the lazy user.

*%InvalidType*.
     The type passed did not match the type asked for.  Such as the value
     'foo' being sent as the value for a field that was marked as being an
     integer, or 'I hate spam' being sent as the value for an email field.

     Probably a user error generated exception.  Kick the lazy user.

$CGI::Validate::Error
     End all, be all dumping ground for exceptions.  If any of the above
     exceptions occurs, the *long messages* are added here.  If any usage
     errors are found, they are added here.  If the moon shifts off it's
     orbit, it's added here.  Use this if you just want to do a simple one
     shot test like:

          GetFormData (foo => \$foo) or die "Parse error: $CGI::Validate::Error";

     Think of it as my version of *$@* if I were to throw "real"
     exceptions. :-)

     This is also used for internal (non-data) error reporting, such as
     not giving me a valid reference type to dump the data into, an
     unbalanced validation list, etc.

   The four hash exceptions have the same format.  The keys are all the
fields that had that kind of exception, and the values are much longer
error messages that give further details that can be useful for debugging.
Generally however, if you need such detail it's much easier to just use
the $CGI::Validate::Error bucket that contains all of the error messages
from all of the exceptions in one place.

EXTENSIONS
==========

   User validation types can be defined using the addExtensions()
function.  addExtensions() takes a hash of extension names and code refs
to use.  All extension names will automatically have an 'x' prepended to
them, so that myType would be xmyType.  Validation code is expected to
return true for valid types, and false/undef for invalid.  Validation code
is passed a single value of the form value.  This value is an alias to the
real data variable so "filters" can be implemented as well that actually
change the data.  Some examples for a Social Security Number checker, and
an amount checker that looks for a number or the string "max" doing a
conversion of "max" to it's own max amount constant:

     my $MAX_AMOUNT = 100;

     addExtensions (
         SSNumber  => sub { $_[0] =~ /^\d{9}$/ },  # SSN must be 9 digit number
         Amount    => sub {
             if ($_[0] =~ /max/i) {
                 $_[0] = $MAX_AMOUNT;  # modify value to be max amount
                 return 1;
             } elsif (($_[0] =~ /^\d+$/) {
                 return 1;
             } else {
                 return 0;
             }
         },
     );
     GetFormData (
         'ssn=xSSNumber'   => \$ssn,
         'amount=xAmount'  => \$amount,
     );

   As such, if the field "amount" were to contain the string "max", it
would be auto-converted to the value of the constant $MAX_AMOUNT (100)
before being assigned to $amount so that no further data changes or checks
are needed.

   All normal exception variables apply.

BUGS
====

   Not tested much with mod_perl, but it should work since each Apache
connection runs in it's own space as it's own process.  Be carful to
manually set your two global config values ($CGI::Validate::Complete and
$CGI::Validate::IgnoreNonMatchingFields) however, even if you use the
"default" values.  This is because as globals they will be recycled on the
next use under mod_perl.

   Email address can never be fully tested (see the Perl FAQ for reasons
why).  The regexp I use is also pretty lame, although I use a better one in
version 1.11+.	This is mainly do to the fact that I don't use it
myself, and don't have much reason to research better methods/checks.  If
you need more extensive testing, feel free to add an extension via
addExtension().

SEE ALSO
========

   perl(1), CGI(3), mod_perl(1)

HISTORY
=======

     $Log: Validate.pm,v $
     Revision 2.0  1998/05/28 10:24:58  byron
     	-Version handling code.
     	-Export symbol names.
     	-How we handle the CGI object data.  Towit, we do some direct internal access for speed
     	 reasons.  Yes, I'm walking into CGI.pm's house without asking, so shoot me.  CGI.pm's
     	 data access methods are so needlessly slow it isn't even funny, but to change them
     	 would break the "documented" interface.  If this proves to be a problem later, I'll probably
     	 just bypass CGI.pm alltogether and do it myself.

     Revision 1.11  1998/05/23 11:16:54  byron
     	-Changed CheckEmail regexp
     	-Better docs
     	-Probably something else...

     Revision 1.10  1998/05/13 21:37:22  byron
     	-Fixed bug from changes in the CGI module interface.

     Revision 1.9  1998/05/11 13:16:48  byron
     	-Added thankyous

     Revision 1.8  1998/05/11 13:06:32  byron
     	-Added CheckFormData()
     	-Added more docs

     Revision 1.7  1998/05/11 12:45:21  byron
     	-Doc changes

     Revision 1.6  1998/05/11 12:36:01  byron
     	-Almost everything
     	-Added user defined types

     Revision 1.5  1998/05/07 13:04:41  byron
     	-Changed float to match /^\d+.?\d*$/ so that ints are ok too

     Revision 1.4  1998/05/07 10:51:23  byron
     	-Changed CGI module access to use ReadParse for speed?
     	-Some doc changes.

     Revision 1.3  1998/03/30 12:12:09  byron
     	-Complete overhaul of the exception handling code.
     	 The old $Error code will still work the same, but there now are much
     	 cleaner ways to figure out exactly what happended and do something
     	 about it.
     	-Changed my email address to match my new account. :-)

     Revision 1.2  1997/12/19 03:46:30  byron
     	-Documentation changes/updates

AUTHOR
======

   Zenin <zenin@archive.rhps.org>

   aka Byron Brummer <byron@omix.com>

   With input from Earl Hood <ehood@geneva.acs.uci.edu>, and Lloyd Zusman
<ljz@asfast.com>, and the email regex from Elijah <http://www.qz.to/~eli/>.

COPYRIGHT
=========

   Copyright (c) 1997,1998 OMIX, Inc.  All rights reserved

   Use is granted under the same terms of Perl.

Subclass LDS's "CGI.pm" for WML output and WML methods
******************************************************

NAME
====

   CGI::WML - Subclass LDS's "CGI.pm" for WML output and WML methods

SYNOPSIS
========

     use CGI::WML;

     $query = new CGI::WML;

     print
        $query->header(),
        $query->start_wml(),
        $query->template(-content=>$query->prev()),
        $query->card(-id=>"first_card",
                 -title=>"First card",
                 -content=>"<p>Hello WAP world!</p>"),
        $query->end_wml();

     print
        $query->wml_to_wmlc(-wml=>$wml_buffer,
                            -errorcontext=>2);

     ($page_title,$content) = $query->html_to_wml($buffer);

DESCRIPTION
===========

   This is a library of perl functions to allow CGI.pm-style programming
to be applied to WAP/WML. Since this is a subclass of Lincoln Stein's
CGI.pm all the normal CGI.pm methods are available. See *perldoc CGI* if
you are not familiar with CGI.pm

   The most up to date version of this module is available at
http://wap.z-y-g-o.com/tools/

FUNCTIONS
=========

   The library provides an object-oriented method of creating correct WML,
together with some canned methods for often-used tasks. As this module is
a subclass of CGI.pm, the same argument-passing method is used, and
arguments may be passed in any order.

CREATING A WML DECK
-------------------

header()
     This function now overrides the default CGI.pm 'Content-type: ' header
     to be 'text/vnd.wap.wml' by default. All the standard CGI.pm header
     functions are still available for use.

     print $query->header();

          -or-
          print $query->header(-expires=>"+1m",
                               -Refresh=>'20; URL='/newplace.wml');

start_wml() Use the start_wml method to create the start of a WML deck, if you wish you can pass paramaters to the method to define a custom DTD, XML language value and any 'META' information. If a DTD is not specified then the default is to use `WML 1.1'
     $query->start_wml(-dtd      => '-//WAPFORUM//DTD WML 5.5//EN',
               -dtd_url  => 'http://www.wapforum.org/DTD/wml_5.5.xml',
                   -lang     => 'en-gb',                   -encoding =>
     'iso-8859-1',                   -meta     => {'scheme'=>'foobar',
                                'name'  =>'mystuff'} );

     There is no direct support for the HTTP-EQUIV type of <meta> tag.
     This is because you can modify the HTTP header directly with the
     header() method.  For example, if you want to send the Cache-control:
     header, do it in the header() method:

     $q->header(-cache_control=>'No-cache; forua=true');

end_wml()
     Use end_wml() to end the WML deck. Just included for completeness.

CREATING WML CARDS
------------------

card()
     Cards are created whole, by passing paramaters to the card() method,
     as well as the card attributes, a timer may be added to the start of
     the card.

     $query->card(-id=>"card_id",              -title=>"First Card",
           -ontimer=>"#next_card",
     -timer=>$query->timer(-name=>"timer1",-value=>"30"),
     -newcontext=>"true",              -onenterforward=>"#somecard",
           -onenterbackward=>"#othercard",
     -content=>"<p>Hello WAP world</p>");

     The 'ID' and 'Content' elements are manditory, and have no defaults.
     All other parameters are optional.

TEMPLATES
---------

   The template() method creates a template for placing at the start of a
card. If you just need to add a back link, use the prev() method.

   $query->template(-content=>$query->prev(-label=>"Go Back"));

TIMERS
------

   A card timer is used with the card() method to trigger an action, the
function takes two arguments, the name of the timer and it's value in
milliseconds.

   $query->timer(-name=>"mytimer",               -value=>"30");

GO BLOCKS
---------

   A <go block is created either as a single line

   $query->go(-method=>"get",
-href=>"http://www.example.com/"); ` <go href="http://www.example.com/"
method="get"/> ' or as a block

   %pfs = ('var1'=>'1',         'var2'=>'2',         'varN'=>'N');

   $query->go(-method=>"post",            -href=>"http://www.example.com/",
          -postfields=>\%pfs);

   <go href="http://www.example.com/" method="get">   <postfield
name="var1" value="1"/>   <postfield name="var2" value="2"/>   <postfield
name="varN" value="N"/> </go>

   depending on wether it is passed a hash of postfields.

DO
--

   $query->do(-type=>"options",               -label=>"Menu",
-content=>qq(go href="#menu"/>)); gives

   <do type="options" label="Menu" >   <go href="#menu"/> </do>

PREV
----

   A canned 'back' link, takes an optional label argument. Default label
is 'Back'. For use in *templates*

   $query->prev(-label=>"Reverse");

   <do type="accept" label="Reverse"><prev/></do>

INPUT
-----

   Create an input entry field. No defaults, although not all arguments
need to be specified.

   $query->input(-name=>"pin",               -value=>"1234",
-type=>"text",               -size=>4,               -title=>"Enter PIN",
            -format=>"4N",               -maxlength=>4,
-emptyok=>"false");

ONEVENT
-------

   An *onevent* element may contain one of 'go','prev','noop' or 'refresh'
and be of type 'onenterforward', 'onenterbackward' or 'ontimer'.

   $query->onevent(-type=>"onenterforward",
-content=>qq(<refresh>                               <setvar name="x"
value="1"/>                              </refresh>));

IMG
---

   An image can be created with the following attributes:

     alt       Text to display in case the image is not displayed
     align     can be top, middle, bottom
     src       The absolute or relative URI to the image
     localsrc  a variable (set using the setvar tag) that refers to an image
               this attribute takes precedence over the B<src> tag
     vspace
     hspace    amount of white space to inserted to the left and right
               of the image [hspace] or above and below the image [vspace]
     height
     width     These attributes are a hint to the user agent to leave space
               for the image while the page is rendering the page.  The
               user agent may ignore the attributes.  If the number length
               is passed as a percent the resulting image size will be
               relative to the amount of available space, not the image size.

   my $img = $query->img(                  -src      =>
'/icons/blue_boy.wbmp',                  -alt      => 'Blue Boy',
       -localsrc => '$var',                  -vspace   => '25',
      -hspace   => '30                  -align    => 'bottom',
     -height   => '15',                  -width    => '10');

   NOTE the *localsrc* element, and formatting elements are not supported
consistently by the current generation of terminals, however they should
simply ignore the attributes they do not understand.

Dial Tags
---------

   When using cell phones in WAP you can make calls.  When a dial tag is
selected the phone drops out of the WAP stack and into what ever is the
protocol used for phone calls.  At the conclusion of the call the phone
should return to the WAP stack in the same place that you linked to the
phone number.

   The tag looks much like a regular link, but has some special syntax.

   $query->dialtag(-label =>"Joe's Pizza",
-number=>"12125551212");

   The recieving terminal must support WTAI for this link to work.

WML SHORTCUTS
=============

   p b *br* table etc. etc. Just like the original CGI.pm, this module
includes functions for creating correct WML by calling methods of a query
object.

   WML Shortcuts may be called in two ways;

   With a single parameter, which will be the content of the tag, for
example;

     Perl code                           WML Result
          ---------------------            ---------------------
          $query->b("Bold text);               <b>bold</b>
          $query->p("Hello");                  <p>Hello</p>

     $query->p($query->b("Hello"));       <p><b>Hello</b></p>

     $query->br();                        <br/> # "No-close" tags are
                                                # automatically dealt with

   Alternatively, they can be called with a list of arguments, specifying
content and attibutes.

     Perl code                           WML Result
     ---------------------            ---------------------
     $query->p(-align=>"left",        <p align="left">Hi there</p>
               -content=>"Hi there");

     When being called with the second syntax, the 'content' parameter
      specifies the content of tags.

     All WML 1.1 tags are available via this method.

COMPILING WML DECKS
===================

   $query->wml_to_wmlc(-wml=>$buffer,
-errorcontext=>2);  # default 0

   A WML to WBXML converter/compiler is included for convinience purposes,
although it is not intended to replace the compiler on the WAP gateway it
may prove useful, for example measuring what the compiled document size
will be.

     $size = length($query->wml_to_wmlc(-wml=>$wml,
                                        -errorcontext=>0));

   NOTE WBXML string tables are used to compress the document size down as
small as possible, giving excellent document size performance. Because of
this though, the size returned by the function may be smaller than the size
of the WBXML document created by the WAP gateway. Turning this feature off
will be an option in future releases.

   The function takes two arguments, a buffer of textual WML and an
optional argument specifiying that should the XML parser fail then X many
lines of the buffer before and after the point where the error occured
will be printed to show the context of the error.

ERRORCONTEXT WARNING Setting this to any non-zero value will cause your program to exit if the routine is passed WML which is not "well formed" this is due to the fact that XML::Parser calls die() upon such events.
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

   If you wish to test wether a WML document is well formed, then set this
value to zero and check the return value of the function. The function
returns undef upon failiure and issues a warning, anything other than
undef indicates success.

HTML TO WML CONVERSION
======================

   ($title,$content) = $query->html_to_wml($buffer);

   -or-

   ($title,$content) = $query->html_to_wml(\*FILEHANDLE);

   A limited HTML to WML converter is included in this package. Be warned
that only pretty well marked-up HTML will convert cleanly to WML.  Dave
Ragget's excellent *tidy* utility [ see
http://www.w3.org/People/Raggett/tidy/ ] will clean up most HTML into a
parseable state.

   The main purpose of this function is for converting server error
messages and the "Compact HTML" used on "I-Mode" systems to readable WML,
not for general page translation.

   Potential users of this function are encouraged to read the source to
this module to gain a better understanding of the underlying mechanics of
the translation.

AUTHOR
======

   Angus Wood <angus@z-y-g-o.com>, with loads of additions and
improvements by Andy Murren <amurren@oven.com>

CREDITS
=======

Wilbert Smits <wilbert@telegraafnet.nl> for the header() function content-type override.
SEE ALSO
========

   perl(1), perldoc CGI, tidy(1)

Suite of modules to themeify a website
**************************************

NAME
====

   CGI::WeT - Suite of modules to themeify a website

SYNOPSIS
========

     use CGI::WeT ();

   Additional packages may be installed and used.  Please check with CPAN
for the latest collections.

DESCRIPTION
===========

   The collection of CGI::WeT::* modules allows a site to be built from
three major components: (1) static themed html files, (2) theme
definitions, (3) CGI scripts.

   This package (CGI::WeT) will load in the following packages only.  No
symbols are imported.

     CGI
     CGI::WeT::Engine
     CGI::WeT::Theme
     CGI::WeT::Modules::Basic

Themed HTML
===========

   Static files are built with no navigation or other theme-dependent
information.  The file consists of a set of header lines followed by the
body of the file separated by a blank line.  For example

     Title: This is an example file

     <p>This file is an example of themed HTML</p>

   This will produce a page with `This is an example file' as part of the
title in the head and the rest of the file as the body placed on the page
according to the theme in force.

   CGI::WeT::Engine provides the mod_perl handler for static pages.

Theme Definitions
=================

   This part of the package depends on which theme loader is being used.
A theme definition provides the engine with the information it needs to
produce a well formed page.  See the appropriate
CGI::WeT::Theme::Loader::*(3) page.

CGI Scripts
===========

   CGI::WeT can be used in place of CGI with minor modifications.  Replace
the *use CGI* statement with *use CGI::WeT* at the top of the script and
add a line to the close of the script: *CGI::WeT-*show_page>.

   The following is an example based on the CGI.pm book:

     #!/usr/bin/perl
     # Script: plaintext2.pl
     use CGI::WeT ':standard';

     print header('text/html');
     print start_html(-title => 'PlainText2.CGI');
     print "Jabberwock\n\n";
     print "'Twas brillig, and the slithy toves\n";
     print "Did gyre and gimbol in the wave.\n";
     print "All mimsy were the borogroves,\n";
     print "And the mome raths outgrabe....\n";
     print end_html();

     CGI::WeT->show_page;

SEE ALSO
========

   perl(1), CGI::WeT::*(3),

   CGI::WeT notes at `http://www.jamesmith.com/cgi-wet/'

SUPPORT
=======

   Please send any questions or comments about CGI::WeT to me at
jsmith@jamesmith.com

AUTHORS
=======

     Written by James G. Smith.
     Copyright (C) 1999.  Released under the Artistic License.

Cookie setter for theme selection
*********************************

NAME
====

   CGI::WeT::Chooser - Cookie setter for theme selection

SYNOPSIS
========

     <Location "/Chooser">
       SetHandler perl-script
       PerlHandler CGI::WeT::Chooser
     </Location>

DESCRIPTION
===========

   CGI::WeT::Chooser replaces the scripts/chooser.cgi script in version
0.70 and earlier.  The theme selector provided in distributions with
CGI::WeT::Chooser will refer to @@TOP@@/Chooser.

SEE ALSO
========

   perl(1), CGI::WeT::*(3),

   CGI::WeT notes at `http://www.jamesmith.com/cgi-wet/'

SUPPORT
=======

   Please send any questions or comments about CGI::WeT to me at
jsmith@jamesmith.com.

AUTHORS
=======

     Written by James G. Smith.
     Copyright (C) 1999.  Released under the Artistic License.

Theme engine for the CGI::WeT package
*************************************

NAME
====

   CGI::WeT::Engine - Theme engine for the CGI::WeT package

SYNOPSIS
========

     use CGI::WeT::Engine ();

DESCRIPTION
===========

   This module provides a web site with the ability to provide themes.  It
is designed to work seamlessly with mod_perl but can be made to work
without mod_perl without too much difficulty.

NOT USING MOD_PERL
==================

   To use this module without mod_perl, a script must be written to handle
all themed page requests.  A sample script might be

     #!/usr/bin/perl

     use CGI::WeT::Engine;
     use CGI::WeT::Theme;
     use CGI::WeT::Modules::Basic;

     my $filename = $ENV{'PATH_TRANSLATED'};
     my $url = $ENV{'PATH_INFO'};

     my($key, $val);

     my $engine = new CGI::WeT::Engine;

     if($inputfile) {

     #
     # get the title and other headers out of the themed page
     #

     open IN, "<$inputfile";

     while(<IN>) {

     last if /^\s*$/;
     next if /^\s*\#/;

     chomp;

     if(/^[A-Za-z_]+:/) {
         ($key, $val) = split(/:/,$_,2);
     } else {
         $val = $_;
     }

     $engine->headers_push($key, $val);
             }

             #
             # slurp up the rest of the file
             #

     $engine->print((<IN>));
     close IN;
         }

         # page is rendered when $engine is destroyed...

   Apache must then be configured to call the CGI script for all files that
are themed.

USING MOD_PERL
==============

   To use this module with mod_perl, a handler must be set using the engine
to filter the themed pages.  The following is an example of the changes
needed by the Apache configuration files.

     <Files "*.thtml">
         AddHandler perl-script .thtml
         PerlHandler CGI::WeT::Engine
         PerlSendHeader On
         PerlSetupEnv   On
     </Files>

   All required modules must be loaded in at server startup.  No code is
loaded during rendering.  The minimum modules are CGI::WeT::Engine,
CGI::WeT::Theme, and CGI::WeT::Modules::Basic.

USING TIED HANDLES
==================

   CGI::WeT::Engine now supports tied handles.  This makes themeing of
older code much easier:

     use CGI::WeT;
     tie *STDOUT, 'CGI::WeT::Engine';

     print "Title: <title of page>\nAuthor: A. U. Thor\n\n";

     .
     .  Old script here printing to STDOUT
     .

     untie *STDOUT;

   The resulting page will have the scripts output as the body.  When
using this method, do not use the CGI::start_html function - this is taken
care of by the CGI::WeT::Engine code.

CGI::WeT::Engine API
====================

$engine = new CGI::WeT::Engine;
     Returns a reference to a new rendering engine.  The returned object
     will have parsed the arguments to the URL (if GET or POST).  The
     returned object will need to be set up before a page can be rendered.

     When the object returned by new is destroyed, the page is rendered to
     STDOUT.

     If using mod_perl, the following variables may be set using
     PerlSetVar:

          WeT_SiteName - prefix for page titles to identify the site
          WeT_SiteRoot - prefix for URLs for this site - defaults to '/'
          WeT_DocumentRoot - Defaults to Apache's DocumentRoot
          WeT_Top - location of the top page of the site relative to the SiteRoot
                    (this allows splash pages)
          WeT_Email - email of the administrator
          WeT_ProblemsEmail - email for bug reports and other problems
          WeT_DefaultTheme - initial theme people will see
                             this can be overridden with the environment variable
                             `WET_THEME'
          WeT_UseSSLURLs - whether to add :SSL and :NOSSL to the
                           end of URLs generated by the engine or not. (This
                           is considered true if defined.)  This is still
                           experimental and will most likely break graphical
                           navigation.
          WeT_AnonymousCoward - in a bow to slashdot.org, this is what the site
                                names anonymous contributors.  This is not
                                retroactive (yet).

     Otherwise, the function *CGI::WeT::site_config* must be defined
     expecting a reference to the engine object.  The following members of
     the object need to be defined:

          $engine->{'SITENAME'}  -- corresponds to WeT_SiteName
          $engine->{'URLBASES'}->{'URLBASE'}  -- corresponds to WeT_DocumentRoot
          $engine->{'URLBASES'}->{'TOP'}  -- corresponds to WeT_Top
          $engine->{'EMAIL'} -- corresponds to WeT_Email
          $engine->{'PROBLEMS_EMAIL'} -- corresponds to WeT_ProblemsEmail
          $engine->{'DEFAULT_THEME'} -- corresponds to WeT_DefaultTheme
          $engine->{'SSL_URLS'} -- corresponds to WeT_UseSSLURLs
          $engine->{'AC'} -- corresponds tp WeT_AnonymousCoward
          =cut
          # ' for Emacs
          # ` for Emacs

     sub DESTROY {   my $engine = shift;   my $r;

          return if $engine->{'INTERNAL_USE_ONLY'};

          if($engine->{'doing_headers'}) {
            $engine->print("\n\n");
          }

          if($engine->{'MOD_PERL'} ) {
            $r = Apache->request;
            my $fh = $engine->{'STDOUT'};

          #    $r->content_type('text/html');

          #    $r->cgi_headers_out unless $engine->{'FILTERED'};

            $fh->print($engine->render_page);
          } else {
          #    print "Content-type: text/html\n\n";
            print $engine->render_page;
          }
          }

$engine->internal_use_only
     This function will mark the $engine object as being for internal use
     only (hence its name).  That is, it will not output a page to output
     upon destruction.  Returns the previous value.  If an argument is
     present, the internal flag is set to that value.

     This function is valuable if a CGI script decides it needs to
     redirect instead of outputing HTML.  Calling this function will
     disable automatic HTML output.

$engine->content_pop
     This function returns the item on the top of the content stack.  Used
     primarily in the rendering code and the *CGI::WeT::Modules*
     extensions to the engine.  An optional argument specifies how many
     elements to pop.

$engine->content_push(*array ref*)
     This function pushes the *array ref*erence onto the top of the content
     stack.  Used primarily in the rendering code and the
     *CGI::WeT::Modules* extensions to the engine.

$engine->content_peek
     This function returns a reference to the item on the top of the stack
     without removing it.  Used primarily in the rendering code and the
     *CGI::WeT::Modules* extensions to the engine.

$engine->arguments_pop
     This function returns the item on the top of the argument stack.
     Used primarily in the rendering code and the *CGI::WeT::Modules*
     extensions to the engine.  Caveat coder.

$engine->arguments_push(*hash ref*)
     This function pushes the *hash ref*erence onto the top of the argument
     stack.  Used primarily in the rendering code and the
     *CGI::WeT::Modules* extensions to the engine.  Caveat coder.

$engine->argument(key)
     This function descends the argument stack looking for a definition of
     key.  If one is found, it is cached at the top of the stack and
     returned.  Use this function to retrieve values passed through a GET
     or POST.  Cookies may also be retrieved through this method but will
     be overridden by any definitions in the GET or POST data.

     The calling context determines if the function returns an array or a
     scalar.  This is only significant if the key appeared multiple times
     in the cookie, GET, or POST data.

$engine->headers_push(key => value, ...)
     This function will place value associated with key in the header
     hash.  Multiple values are placed in arrays similar to the arguments.
     Several keys are meaningful to the rendering code:

     Title - Denotes the page title.  This is placed in the document head.

     Type - Document type.  This is used to determine which layout to use
     in a theme.  The first is highest priority.  The `DEFAULT' type is
     implied as the lowest priority layout.

     Author, Keywords, Date - These three are placed verbatim in META tags
     in the header.  Useful information for search engines.

$engine->header(key)
     This function retrieves the values associated with key.  The calling
     context determines if the function returns an array or a scalar.
     This is only significant if the key appeared in multiple calls to
     *headers_push*.

$engine->print(array)
     This function places array at the end of the body content caching it
     for later use by the rendering code.  Text placed in the body cannot
     be removed by a provided method.

$engine->url(array)
     This function forms a string from array prefixing it with the base URL
     for the themed site.  Any strings of the form *@@var@@* are
     interpolated from a hash of base URLs.  This provides for locations
     based on the theme or site configuration.  Multiple `/'s are
     collapsed.  This function will not be able to return theme dependent
     URLs except during the actual rendering of a page.

     If the url built from array begins with `/', then the link is
     absolute with respect to the top of the site.  Otherwise, it is
     relative to the page being produced.

     If this function is called without arguments, it will return the URI
     of the current request.

$engine->filename(URL)
     This function will return the location of URL in the filesystem.  This
     will use Apache's URl->filename translation code if running under
     mod_perl.  Otherwise, tacks the document root on the beginning.  If
     no arguments are passed, it will return the filename of the current
     page.

$engine->smarttext(array)
     This function will accept the array of plain text and return a string
     of HTML formatted text.

     HTML character entities are preserved.  Also, &star; and &under; are
     translated to `*' and `_' respectively.  Paragraphs beginning with
     whitespace are quoted as preformatted text.  The ampersand,
     greater-than and less-than are translated to character entities.
     Therefore, no HTML may be included in the input text.  Text may be
     _underlined_ or made *bold*.

$engine->render_content
     This function is the main workhorse returning an array resulting from
     rendering the top of the content stack.  Used primarily in the
     rendering code and the *CGI::WeT::Modules* extensions to the engine.
     Caveat coder.

$engine->render_page([*theme*])
     This function returns the rendered page constructed with the object
     using *theme* if supplied.  Otherwise the argument stack is consulted
     to determine which theme to use.  If *theme* is supplied, it must be
     an object returned by *new CGI::WeT::Theme* or a derived class of
     *CGI::WeT::Theme*.

SEE ALSO
========

   perl(1), CGI(3), CGI::WeT(3), CGI::WeT::Theme(3), CGI::WeT::Modules(3),

   CGI::WeT notes at `http://www.jamesmith.com/cgi-wet/'

AUTHORS
=======

     Written by James G. Smith.
     Copyright (C) 1999.  Released under the Artistic License.

Basic rendering engine extensions
*********************************

NAME
====

   CGI::WeT::Modules::Basic - Basic rendering engine extensions

SYNOPSIS
========

     use CGI::WeT::Modules::Basic ();

DESCRIPTION
===========

   This module provides basic rendering constructs for the engine.  Please
be aware that the code supersedes the documentation.  While I have tried
to be accurate there are times that words fail me and a look at the code
is far more enlightening than anything I could cobble together.  This is
especially true when trying to write a theme.  Download a theme and see
how someone else did it.  Then try making modifications and see what
happens.

EXTENSIONS
==========

   sub initialize { 1; }

BODY
     This extension will insert the body of the themed HTML into the
     rendered page.

HBOX
     This extension builds a box on the page by placing the contents in a
     <table>...</table> construct.  Available arguments are: width,
     cellspacing, cellpadding, border, height, and bgcolor.

VBOX
     This extension places its contents in a smaller box which is
     contained in a LINE.  Available arguments are: width, valign,
     colspan, rowspan, height, align, background, bgcolor.

LINE
     This extension puts together a set of VBOXs for inclusion in a HBOX.

CONTENT
     This extension renders the top of the content stack and places the
     results in the page.

TEXT
     This extension interprets the top of the content stack as plain text
     and places it in the page.

GRAPHIC
     This extension will place a theme dependent graphic image in the page.
     Available arguments are `location' (relative to the theme's base
     image URL), `height,' `width,' `align,' `valign,' and `name.'

HEADERS
     This extension places the text of a header line in the page.
     Available arguments are: key, align, size, and color.

LINK
     This extension places a link relative to the top of the site around
     the content at the top of the content stack.  The argument needed is
     `location.'

DUP
     This extension duplicates the top of the content stack.

ROT
     This extension takes the third element of the stack to the top of the
     stack.

SWAP
     This extension swaps the top two elements of the content stack

POP
     This extension discards the top of the content stack.

IF
     This extension will leave either the second or the third element on
     the top of the content stack depending on whether or not the top
     element is true or false (non-blank or blank).

QIF
     Given three elements on the top of the content stack, it will render
     the top element by the second or leave the third depending on whether
     the top is true or false (non-blank or blank).

IFMODULE
     Operates the same as IF except the conditional is a list of modules
     given as arguments.  For example

          '[IFMODULE module=NEWS_SUMMARY module=HELP_URL]'

     will leave the top of the content stack if and only if both
     NEWS_SUMMARY and HELP_URL are available under in CGI::WeT::Modules::
     .  Otherwise, it will leave the next to the top of the content stack
     on top.  In either case, the content stack will have one less element
     afterwards.

NAVIGATION
     This extension will render the navigation for the particular page.
     Several arguments are available to customize the look.

     type - if 'text' then rendering is done with text.  Otherwise, the
     value is used to determine the directory in which the graphics images
     reside.  This depends on the theme.

     bullet - defines a graphical element to prefix the navigational
     elements with.  Arguments that help define the image are:
     bullet_width, bullet_height.

     align - if this is 'center' then the navigational element is centered.

     begin - defines the initial HTML to use in building the navigation.

     end - defines the final HTML to use in building the navigation.

     top - if 'yes' will place a link to the top of the site.

     up - if 'yes' will place a link to the level above the current level.

     join - determins the HTML used between navigational elements.

     level - if 'current' only places navigation for the current level.
     Otherwise, renders an outline from the top to the current level.

NAVPATH
     This extension renders a path of links from the top of the site to the
     current level.  Currently only supports a type of `text.'  Other
     arguments are:

     join - the code to join to elements in the path.

     *ellipses* - the code to indicate absence of intervening levels

     depth - the number of levels to include in the path before dropping
     elements.

THEME_CHOOSER
     This extension will place a form on the page allowing the user to
     choose a different theme.  Requires a CGI script '/chooser.cgi' in
     the root of the site.  The value of join is placed between the
     selection list and the submit button.

ALTERNATE_THEME
     This extension duplicates LINK except that the location is the current
     page URL and the value of the *theme* argument is appended as part of
     the URL.

INCLUDE
     This extension will read in a file given by the location argument and
     return the contents.  The file is interpreted as a local URI.

Extensions to engine to allow calendar management
*************************************************

NAME
====

   CGI::WeT::Modules::Calendar - Extensions to engine to allow calendar
management

SYNOPSIS
========

     use CGI::WeT::Modules::Calendar ();

DESCRIPTION
===========

   This module provides rendering constructs to allow navigation through a
set of calendars.  Support is provided for multiple types of events in
multiple calendars, both public and private (general and user specific).

EXTENSIONS
==========

CGI::WeT::Modules::Calendar::initialize($engine, $r)
     This subroutine will initialize the engine passed as $engine with
     information from Apache (passed as $r).  The base URL for calendars
     is set with the following.

          PerlSetVar WeT_CalendarURL /baseURL/

     This is available for building URLs as @@CALENDAR@@.  For example,
     the top level calendar can be viewed at the URL returned by

          $engine->url('@@CALENDAR@@/general/');

     A list of available calendars might be found at

          $engine->url('@@CALENDAR@@/');

Extensions to engine to allow documentation management
******************************************************

NAME
====

   CGI::WeT::Modules::Documentation - Extensions to engine to allow
documentation management

SYNOPSIS
========

     use CGI::WeT::Modules::Documentation ();

DESCRIPTION
===========

   This module provides rendering constructs to allow navigation through a
set of pages.  Support is provided for a doubly linked list of pages.

EXTENSIONS
==========

CGI::WeT::Modules::Documentation::initialize($engine, $r)
     This subroutine will initialize the engine passed as $engine with
     information from Apache (passed as $r).  There is no significant code.

DOC_NEXT
     This extension is like CGI::WeT::Modules::Basic's LINK in that the
     top of the content stack is made into a link.  The location is
     determined by the values of the arguments.

    sequence
          This can be either `next' or `prev.'

Extensions to engine to allow article management
************************************************

NAME
====

   CGI::WeT::Modules::News - Extensions to engine to allow article
management

SYNOPSIS
========

     use CGI::WeT::Modules::News ();

DESCRIPTION
===========

   This module provides rendering constructs to allow navigation through a
set of articles.  Support is provided for multiple types of articles in
multiple groupings (or channels).

EXTENSIONS
==========

CGI::WeT::Modules::News::initialize($engine, $r)
     This subroutine will initialize the engine passed as $engine with
     information from Apache (passed as $r).  The base URL for articles is
     set with the following.

          PerlSetVar WeT_NewsURL /baseURL/

     This is available for building URLs as @@NEWS@@.  For example,
     general articles are under the URL returned by

          $engine->url('@@NEWS@@/general/');

     The directory may likewise be found by using

          $engine->filename($engine->url('@@NEWS@@/general/'));

NEWS_SUMMARY
     This extension will insert a summary of available news items starting
     with the most recent (ordered by submission time).  The top of the
     content stack is applied to each item as a template.

     The template used is called with four elements on the content stack:
     Title, Date, Author, and Summary (Title on top of stack).  The
     available arguments for controlling NEWS_SUMMARY are

    channel
          This argument specifies which channel to collect items from.
          This defaults to `general.'

    category
          This argument specifies which category to collect items from.
          Only one category may be specified at this time.  There is no
          way to block items marked as `all.'  The default category is
          `all.'

    link
          If this is set to `title,' the title will be made a link.  No
          other value has an effect.

    number
          This tells NEWS_SUMMARY how many items to put in the list.
          There is no default for this argument, so one must be supplied.

NEWS_NEXT
     This extension is like CGI::WeT::Modules::Basic's LINK in that the
     top of the content stack is made into a link.  The location is
     determined by the values of the arguments.

    channel
          See NEWS_SUMMARY

    type
          This can be either `story' or `response.'  If `story,' then the
          articles in the top level are looked at.  Otherwise, the
          articles in the current directory are examined.

    sequence
          This can be either `next' or `prev.'

Theme loader for the CGI::WeT package
*************************************

NAME
====

   CGI::WeT::Theme - Theme loader for the CGI::WeT package

SYNOPSIS
========

     use CGI::WeT::Theme ();

DESCRIPTION
===========

   This module provides a well-defined interface between the rendering
engine and the theme definition loaders.  It is designed to work with or
without mod_perl.  All theme loader classes must be defined in the
CGI::WeT::Theme::Loader namespace during the construction of a
CGI::WeT::Theme object.

   This module is used by the rendering engine and should not be needed
outside of that engine.  This documentation is to aid those building a
theme loader.

   All theme loaders need the following method defined:

factory(*theme*)
     This will produce a properly blessed object which represents the
     definition for *theme*.  If such an object can not be produced
     (*theme* not defined by that particular loader), this will return
     undef.

   The object returned by the factory method must provide the following
methods:

page_type(list)
     This function will return an object representing the information
     needed to layout a page of the type in list.  Since this is a list,
     the first item is most desired while the last is least desired.  It
     will return the information for the best desired match it can find.
     If none can be returned, it must return undef.

     The object returned by this function must provide *LAYOUT* and may
     provide  BODY, *CSS*, and *JAVASCRIPT*.  *LAYOUT* provides an
     anonymous array describing the layout of the page.  BODY returns a
     hash reference describing various body attributes.  BODY is
     deprecated in favor of *CSS* which returns a reference to an array
     with the Cascading Style Sheet to use for this layout.  *JAVASCRIPT*
     returns a reference to an array with any JavaScript required for this
     layout.

Module to load HTML theme definitions
*************************************

NAME
====

   CGI::WeT::Theme::Loader::HTML - Module to load HTML theme definitions

SYNOPSIS
========

     use CGI::WeT::Theme::Loader::HTML ();

DESCRIPTION
===========

Module to load pre-0.6 themes
*****************************

NAME
====

   CGI::WeT::Theme::Loader::WeT - Module to load pre-0.6 themes

SYNOPSIS
========

     use CGI::WeT::Theme::Loader::WeT ();

DESCRIPTION
===========

User database interface for CGI::WeT
************************************

NAME
====

   CGI::WeT::User - User database interface for CGI::WeT

SYNOPSIS
========

     use CGI::WeT::User ();

DESCRIPTION
===========

   This module provides the CGI::WeT package with access to the user
database used for authentication.  This allows other scripts and modules
to interact with user information when pages have been authenticated.

   To make full use of this module, one of the various
CGI::WeT::User::DBI::* modules must be compiled also. (Here
CGI::WeT::User::DBI is not a reference to the more well known DBI::
package though work is progressing on CGI::WeT::User::DBI::DBI.)

   CGI::WeT::User will query each available module under
CGI::WeT::User::DBI:: in turn until one returns a defined reference.  To
only use a particular database when several might be available, use the

     PerlSetVar WeT_UserDB <DBI Module>

   configuration directive.  This will cause CGI::WeT::User to only query
the CGI::WeT::User::DBI::<DBI Module> module.

   See the documentation for the particular database interface being used
for more requirements or configuration directives.

   To retrieve information on a user, use the following call:

     $user = new CGI::WeT::User ($engine, 'username' => $ENV{'REMOTE_USER'});

   where $engine is the CGI::WeT::Engine object being used to render the
page.

interface between CGI::WeT::User and Net::LDAP
**********************************************

NAME
====

   CGI::WeT::User::DBI::LDAP - interface between CGI::WeT::User and
Net::LDAP

SYNOPSIS
========

     use CGI::WeT::User::DBI::LDAP ();

DESCRIPTION
===========

   This package provides CGI::WeT::User with access to an LDAP database.
This module requires Net::LDAP.  Use of another LDAP package should only
require trivial changes to the code.

   Three variables are required in the Apache configuration file
(httpd.conf or equivalent).

PerlSetVar WeT_UserDB_LDAP_Host <host>
PerlSetVar WeT_UserDB_LDAP_Service <port>
PerlSetVar WeT_UserDB_LDAP_Base <base_dn>

buffer output when building CGI programs
****************************************

NAME
====

   CGI::Wrap - buffer output when building CGI programs

SYNOPSIS
========

     use CGI;
     use CGI::Croak;
     use CGI::Wrap;

     $query = new CGI;
     savequery $query;		# to reconstruct input
     $CGI::Out::mailto = 'fred';	# override default of $<

     run \&myfunc, @myargs		# a function
     run sub { code }		# an inline function
     run 'code'			# something to eval

     sub myfunc {
     	out $query->header();
     	out $query->start_html(
     		-title=>'A test',
     		-author=>'muir@idiom.com');
     }
     $CGI::Out::$out			# is the buffer

DESCRIPTION
===========

   This is a helper routine for building CGI programs.  It buffers stdout
until you're completed building your output.  If you should get an error
before you are finished, then it will display a nice error message (in
HTML), log the error, and send email about the problem.

   To use it, you must condense your program down to a single function
call and then use CGI::Wrap::run to call it.

   Instead of print, use out.

AUTHOR
======

   David Muir Sharnoff <muir@idiom.com>

SEE ALSO
========

   Carp, CGI::Carp, CGI::Out,  CGI

BUGS
====

   No support for formats is provided by CGI::Wrap.

Perl extension for converting CGI.pm variables to/from XML
**********************************************************

NAME
====

   XML::CGI - Perl extension for converting CGI.pm variables to/from XML

SYNOPSIS
========

     use XML::CGI;
     $q = new XML::CGI;

     # convert CGI.pm variables to XML
     $xml = $q->toXML;
     $xml = $q->toXML($root);

     # convert XML to CGI.pm variables
     $q->toCGI($xml);

DESCRIPTION
===========

   The XML::CGI module converts CGI.pm variables to XML and vice versa.

   *XML::CGI* is a subclass of *CGI.pm*, so it reads the CGI variables
just as CGI.pm would.

METHODS
=======

$q = new XML::CGI
     creates a new instance of XML::CGI. You also have access to all of
     the methods in CGI.pm.

$q->toXML([$root])
     where $root is an optional parameter that specifies the root element.
     By default, toXML will not return a root element.

$q->toCGI($xml)
     where $xml is the XML you would like to convert to CGI.pm parameters.
     Values in the XML will overwrite any existing values if they exist.

NOTE
====

   *XML::CGI* does not currently handle multiple selections passed from
HTML forms. This will be added in a future release.

AUTHOR
======

   Jonathan Eisenzopf <eisen@pobox.com>

CONTRIBUTORS
============

   David Black <dblack@candle.superlink.net>

SEE ALSO
========

   perl(1), XML::Parser(3).

Extension of CGI.pm which reads/generates formated XML.
*******************************************************

NAME
====

   CGI::XMLForm - Extension of CGI.pm which reads/generates formated XML.

   NB: This is a subclass of CGI.pm, so can be used in it's place.

SYNOPSIS
========

     use CGI::XMLForm;

     my $cgi = new CGI::XMLForm;

     if ($cgi->param) {
     	print $cgi->header, $cgi->pre($cgi->escapeHTML($cgi->toXML));
     }
     else {
     	open(FILE, "test.xml") or die "Can't open: $!";
     	my @queries = ('/a', '/a/b*', '/a/b/c*', /a/d');
       print $cgi->header,
     	      $cgi->pre($cgi->escapeHTML(
     		  join "\n", $cgi->readXML(*FILE, @queries)));
     }

DESCRIPTION
===========

   This module can either create form field values from XML based on
XQL/XSL style queries (full XQL is _not_ supported - this module is
designed for speed), or it can create XML from form values. There are 2
key functions: toXML and readXML.

toXML
-----

   The module takes form fields given in a specialised format, and outputs
them to XML based on that format. The idea is that you can create forms
that define the resulting XML at the back end.

   The format for the form elements is:

     <input name="/body/p/ul/li">

   which creates the following XML:

     <body>
       <p>
     	  <ul>
     	    <li>Entered Value</li>
     	  </ul>
     	</p>
     </body>

   It's the user's responsibility to design appropriate forms to make use
of this module. Details of how come below...

   Also supported are attribute form items, that allow creation of element
attributes. The syntax for this is:

     <input name="/body/p[@id='mypara' and @onClick='someFunc()']/@class">

   Which creates the following XML:

     <body>
       <p id="mypara" onClick="someFunc()" class="Entered Value"></p>
     </body>

   Also possible are relative paths. So the following form elements:

     <input type="hidden" name="/table/tr">
     <input type="text" name="td">
     <input type="text" name="td">
     <input type="text" name="../tr/td">

   Will create the following XML:

     <table>
       <tr>
     	  <td>value1</td>
     	  <td>value2</td>
     	</tr>
     	<tr>
     	  <td>value3</td>
     	</tr>
     </table>

SYNTAX
======

   The following is a brief syntax guideline

   Full paths start with a "/" :

     "/table/tr/td"

   Relative paths start with either ".." or just a tag name.

     "../tr/td"
     "td"

   *Relative paths go at the level above the previous path, unless the
previous path was also a relative path, in which case it goes at the same
level.* This seems confusing at first (you might expect it to always go at
the level above the previous element), but it makes your form easier to
design. Take the following example: You have a timesheet (see the example
supplied in the archive) that has monday,tuesday,etc. Our form can look
like this:

     <input type="text" name="/timesheet/projects/project/@Name">
     <input type="text" name="monday">
     <input type="text" name="tuesday">
     ...

   Rather than:

     <input type="text" name="/timesheet/projects/project/@Name">
     <input type="text" name="monday">
     <input type="text" name="../tuesday">
     <input type="text" name="../wednesday">
     ...

   If unsure I recommend using full paths, relative paths are great for
repeating groups of data, but weak for heavily structured data. Picture
the following paths:

     /timesheet/employee/name/forename
     ../surname
     title
     ../department

   This actually creates the following XML:

     <timesheet>
       <employee>
     	  <name>
     	    <forename>val1</forname>
     		<surname>val2</surname>
     		<title>val3></title>
     	  </name>
     	  <department>val4</department>
     	</employee>
     </timesheet>

   Confusing eh? Far better to say:

     /timesheet/employee/name/forename
     /timesheet/employee/name/surname
     /timesheet/employee/name/title
     /timesheet/employee/department

   Or alternatively, better still:

     /timesheet/employee/name (Make hidden and no value)
     forename
     surname
     title
     ../department

   Attributes go in square brackets. Attribute names are preceded with an
"@", and attribute values follow an "=" sign and are enclosed in quotes.
Multiple attributes are separated with " and ".

     /table[@bgcolor="blue" and @width="100%"]/tr/td

   If setting an attribute, it follows after the tag that it is associated
with, after a "/" and it's name is preceded with an "@".

     /table/@bgcolor

readXML
-------

   readXML takes either a file handle or text as the first parameter and a
list of queries following that. The XML is searched for the queries and it
returns a list of tuples that are the query and the match.

   It's easier to demonstrate this with an example. Given the following
XML:

     <a>Foo
       <b>Bar
     	  <c>Fred</c>
     	  <c>Blogs</c>
     	</b>
     	<b>Red
     	  <c>Barbara</c>
     	  <c>Cartland</c>
     	</b>
     	<d>Food</d>
     </a>

   And the following queries:

     /a
     /a/b*
     c*
     /a/d

   it returns the following result as a list:

     /a
     Foo
     /a/b
     Bar
     c
     Fred
     c
     Blogs
     /a/b
     Red
     c
     Barbara
     c
     Cartland
     /a/d
     Food

   (NB: This is slightly incorrect - for /a and /a/b it will return "Foo\n
  " and "Bar\n      " respectively).

   The queries support relative paths like toXML (including parent paths),
and they also support wildcards using ".*" or ".*?" (preferably ".*?" as
it's probably a better match). If a wildcard is specified the results will
have the actual value substituted with the wildcard. Wildcards are a bit
experimental, so be careful ;-)

Caveats
-------

   There are a few caveats to using this module:

AUTHOR
======

   Matt Sergeant msergeant@ndirect.co.uk, sergeant@geocities.com

   Based on an original concept, and discussions with, Jonathan Eisenzopf.
Thanks to the Perl-XML mailing list for suggesting the XSL syntax.

   Special thanks to Francois Belanger (francois@sitepak.com) for his
mentoring and help with the syntax design.

SEE ALSO
========

   CGI(1), CGI::XML

Perl module to process and decode WWW forms and cookies.
********************************************************

NAME
====

   CGI_Lite - Perl module to process and decode WWW forms and cookies.

SYNOPSIS
========

     use CGI_Lite;

     $cgi = new CGI_Lite;

     $cgi->set_platform ($platform);

         where $platform can be one of (case insensitive):
         Unix, Windows, Windows95, DOS, NT, PC, Mac or Macintosh

     $cgi->set_file_type ('handle' or 'file');
     $cgi->add_timestamp (0, 1 or 2);

     where 0 = no timestamp
           1 = timestamp all files (default)
           2 = timestamp only if file exists

     $cgi->filter_filename (\&subroutine);

     $size = $cgi->set_buffer_size ($some_buffer_size);

     $status = $cgi->set_directory ('/some/dir');
     $cgi->set_directory ('/some/dir') || die "Directory doesn't exist.\n";

     $cgi->close_all_files;

     $cgi->add_mime_type ('application/mac-binhex40');
     $status = $cgi->remove_mime_type ('application/mac-binhex40');
     @list = $cgi->get_mime_types;

     $form = $cgi->parse_form_data;
     %form = $cgi->parse_form_data;

     or

     $form = $cgi->parse_form_data ('GET', 'HEAD' or 'POST');

     $cookies = $cgi->parse_cookies;
     %cookies = $cgi->parse_cookies;

     $status  = $cgi->is_error;
     $message = $cgi->get_error_message;

     $cgi->return_error ('error 1', 'error 2', ...);

     $keys = $cgi->get_ordered_keys;
     @keys = $cgi->get_ordered_keys;

     $cgi->print_data;

     $cgi->print_form_data;   (deprecated as of v1.8)
     $cgi->print_cookie_data; (deprecated as of v1.8)

     $new_string = $cgi->wrap_textarea ($string, $length);

     @all_values = $cgi->get_multiple_values ($reference);

     $cgi->create_variables (\%form);
     $cgi->create_variables ($form);

     $escaped_string = browser_escape ($string);

     $encoded_string = url_encode ($string);
     $decoded_string = url_decode ($string);

     $status = is_dangerous ($string);
     $safe_string = escape_dangerous_chars ($string);

DESCRIPTION
===========

   You can use this module to decode form and query information, including
file uploads, as well as cookies in a very simple manner; you need not
concern yourself with the actual details behind the decoding process.

METHODS
=======

   Here are the methods you can use to process your forms and cookies:

parse_form_data
     This will handle the following types of requests: GET, HEAD and POST.
     By default, CGI_Lite uses the environment variable REQUEST_METHOD to
     determine the manner in which the query/form information should be
     decoded. However, as of v1.8, you are allowed to pass a valid request
     method to this function to force CGI_Lite to decode the information in
     a specific manner.

     For multipart/form-data, uploaded files are stored in the user
     selected directory (see set_directory). If timestamp mode is on (see
     add_timestamp), the files are named in the following format:

          timestamp__filename

     where the filename is specified in the "Content-disposition" header.
     NOTE:, the browser URL encodes the name of the file. This module
     makes no effort to decode the information for security reasons.
     However, you can do so by creating a subroutine and then using the
     filter_filename method.

     *Return Value*

     Returns either a hash or a reference to the hash, which contains all
     of the key/value pairs. For fields that contain file information, the
     value contains either the path to the file, or the filehandle (see
     the set_file_type method).

parse_cookies
     Decodes and parses cookies passed by the browser. This method works in
     much the same manner as parse_form_data.

is_error
     As of v1.8, errors in parsing are handled differently. You can use
     this method to check for any potential errors after you've called
     either parse_form_data or parse_cookies.

     *Return Value*

          0 Success
          1 Failure

get_error_message
     If an error occurs when parsing form/query information or cookies, you
     can use this method to retrieve the error message. Remember, you can
     check for errors by calling the is_error method.

     *Return Value*

     The error message.

return_error
     You can use this method to return errors to the browser and exit.

set_platform
     You can use this method to set the platform on which your Web server
     is running. CGI_Lite uses this information to translate end-of-line
     (EOL) characters for uploaded files (see the add_mime_type and
     remove_mime_type methods) so that they display properly on that
     platform.

     You can specify either (case insensitive):

          Unix                                  EOL: \012      = \n
          Windows, Windows95, DOS, NT, PC       EOL: \015\012  = \r\n
          Mac or Macintosh                      EOL: \015      = \r

     "Unix" is the default.

set_directory
     Used to set the directory where the uploaded files will be stored
     (only applies to the *multipart/form-data* encoding scheme).

     This function should be called before you call parse_form_data, or
     else the directory defaults to "/tmp". If the application cannot
     write to the directory for whatever reason, an error status is
     returned.

     *Return Value*

          0  Failure
          1  Success

close_all_files
     All uploaded files that are opened as a result of calling
     set_file_type with the "handle" argument can be closed in one shot by
     calling this method.

add_mime_type
     By default, EOL characters are translated for all uploaded files with
     specific MIME types (i.e text/plain, text/html, etc.). You can use
     this method to add to the list of MIME types. For example, if you
     want CGI_Lite to translate EOL characters for uploaded files of
     *application/mac-binhex40*, then you would do this:

          $cgi->add_mime_type ('application/mac-binhex40');

remove_mime_type
     This method is the converse of add_mime_type. It allows you to remove
     a particular MIME type. For example, if you do not want CGI_Lite to
     translate EOL characters for uploaded files of *text/html*, then you
     would do this:

          $cgi->remove_mime_type ('text/html');

     *Return Value*

          0  Failure
          1  Success

get_mime_types
     Returns the list, either as a reference or an actual list, of the
     MIME types for which EOL translation is performed.

set_file_type
     The names of uploaded files are returned by default, when you call
     the parse_form_data method. But,  if pass the string "handle" to this
     method, the handles to the files are returned. However, the name of
     the handle corresponds to the filename.

     This function should be called before you call parse_form_data, or
     else it will not work.

add_timestamp
     By default, a timestamp is added to the front of uploaded files.
     However, you have the option of completely turning off timestamp mode
     (value 0), or adding a timestamp only for existing files (value 2).

filter_filename
     You can use this method to change the manner in which uploaded files
     are named. For example, if you want uploaded filenames to be all
     upper case, you can use the following code:

          $cgi->filter_filename (\&make_uppercase);
          $cgi->parse_form_data;

          .
          .
          .

          sub make_uppercase
          {
              my $file = shift;

          $file =~ tr/a-z/A-Z/;
          return $file;
              }

set_buffer_size
     This method allows you to set the buffer size when dealing with
     multipart form data. However, the *actual* buffer size that the
     algorithm uses can be up to 3x the value you specify. This ensures
     that boundary strings are not "split" between multiple reads. So,
     take this into consideration when setting the buffer size.

     You cannot set a buffer size below 256 bytes and above the total
     amount of multipart form data. The default value is 1024 bytes.

     *Return Value*

     The buffer size.

get_ordered_keys
     Returns either a reference to an array or an array itself consisting
     of the form fields/cookies in the order they were parsed.

     *Return Value*

     Ordered keys.

print_data
     Displays all the key/value pairs (either form data or cookie
     information) in a ordered fashion. The methods print_form_data and
     print_cookie_data are deprecated as of version v1.8, and will be
     removed in future versions.

print_form_data
     Deprecated as of v1.8, see print_data.

print_cookie_data (deprecated as of v1.8)
     Deprecated as of v1.8, see print_data.

wrap_textarea
     You can use this function to "wrap" a long string into one that is
     separated by a combination of carriage return and newline (see
     set_platform) at fixed lengths.  The two arguments that you need to
     pass to this method are the string and the length at which you want
     the line separator added.

     *Return Value*

     The modified string.

get_multiple_values
     One of the major changes to this module as of v1.7 is that multiple
     values for a single key are returned as an reference to an array, and
     not as a string delimited by the null character ("\0"). You can use
     this function to return the actual array. And if you pass a scalar
     value to this method, it will simply return that value.

     There was no way I could make this backward compatible with versions
     older than 1.7. I apologize!

     *Return Value*

     Array consisting of the multiple values.

create_variables
     Sometimes, it is convenient to have scalar variables that represent
     the various keys in a hash. You can use this method to do just that.
     Say you have a hash like the following:

          %form = ('name'   => 'shishir gundavaram',
          	     'sport'  => 'track and field',
          	     'events' => '100m');

     If you call this method in the following manner:

          $cgi->create_variables (\%hash);

     it will create three scalar variables: $name, $sport and $events.
     Convenient, huh?

browser_escape
     Certain characters have special significance to the browser. These
     characters include: "<" and ">". If you want to display these
     "special" characters, you need to escape them using the following
     notation:

          &#ascii;

     This method does just that.

     *Return Value*

     Escaped string.

url_encode
     This method will URL encode a string that you pass it. You can use
     this to encode any data that you wish to pass as a query string to a
     CGI application.

     *Return Value*

     URL encoded string.

url_decode
     You can use this method to URL decode a string.

     *Return Value*

     URL decoded string.

is_dangerous
     This method checks for the existence of dangerous meta-characters.

     *Return Value*

          0 Safe
          1 Dangerous

escape_dangerous_chars
     You can use this method to "escape" any dangerous meta-characters.

     *Return Value*

     Escaped string.

SEE ALSO
========

   If you're looking for more comprehensive CGI modules, you can either
use the CGI::* modules or CGI.pm. Both are maintained by Dr. Lincoln Stein
*(lstein@genome.wi.mit.edu)* and can be found at your local CPAN mirror
and at his Web site:

   *http://www-genome.wi.mit.edu/WWW/tools/scripting*

ACKNOWLEDGMENTS
===============

   I'd like to thank the following for finding bugs and offering
suggestions:

Eric D. Friedman (friedman@uci.edu)
Thomas Winzig (tsw@pvo.com)
Len Charest (len@cogent.net)
Achim Bohnet (ach@rosat.mpe-garching.mpg.de)
John E. Townsend (John.E.Townsend@BST.BLS.com)
Andrew McRae (mcrae@internet.com)
Dennis Grant (dg50@chrysler.com)
Scott Neufeld (scott.neufeld@mis.ussurg.com)
Raul Almquist (imrs@ShadowMAC.org)
and many others!
COPYRIGHT INFORMATION
=====================

     Copyright (c) 1995, 1996, 1997 by Shishir Gundavaram
                     All Rights Reserved

     Permission to use, copy, and  distribute  is  hereby granted,
     providing that the above copyright notice and this permission
     appear in all copies and in supporting documentation.

Manage assignments out of a group of CIDR blocks
************************************************

NAME
====

   CIDR::Assign - Manage assignments out of a group of CIDR blocks

SYNOPSIS
========

   use CIDR::Assign;

   $obj = CIDR::Assign->new($filename);

   $obj->DESTROY;

   $network = $obj->assignNetwork($length, $customer, $ones, $zeros,
$location);

   $obj->changeState($network, $state, $customer, $location);

   $obj->initialiseBlock($network);

   ($network, $state, $date, $customer, $location) =
$obj->iterateAllocations;

DESCRIPTION
===========

   This module can be used to manage customer assigments out of a provider
block. The CIDR block is represented as a B-Tree in a Berkeley DB database
and is originally populated by invoking initialiseBlock with each provider
block.

   new will create the DB file, whose name is passed as a parameter, if
necessary, and then tie it to an internal hash used by the other routines.
This routine attempts to acquire a lock on the DB file using lockf in an
attempt to control access to the file. Should acquiring the lock fail the
routine will return "undef".

   DESTROY closes the DB file and releases the lock on the file.

   Networks can be allocated out of the assigned blocks by calling
assignNetwork specifying the size of the block required. The system then
scans the tree for a "free" block that is of the required size. If a block
isn't available then it splits the next largest block and invokes itself.
Should there be no free block available for allocation then the routing
returns "undef".

   The parameters "ones" and "zeroes" are used to indicate if the
allocation can make use of an all ones or all zeros network if necessary.

   The parameter "location" is optional but if present and the allocation
is smaller than a /24 it will try to choose a block in the same location as
other allocations in order to avoid too much fragmentation of the address
space.

   changeState can be used to change the state of a block in the free, for
example, to add existing allocations to the tree or return an allocation
to the free pool.

   initialiseBlock adds a new block into the allocation pool.

   iterateAllocations allows the caller to traverse the tree, much like
"each", and returns a list of information about each allocation. This list
is comprised of network, state (currently 'taken', 'free' or 'holding'),
date of last operation and customer indentifer (and possibly location) if
the block is not free.

   errorMessage return a string suitable for printing that describes the
latest error condition.

AUTHOR
======

   Mark Prior <mrp@connect.com.au>

   Original idea and code by Andrew Rutherford <andrewr@iagu.net>

NOTES   This module uses the following modules
==============================================

DB_File
     The Berkeley DB is used for storage of the allocations, in B-Tree
     format.

File::lockf
     The allocations file is locked with lockf to avoid problems with NFS.

Powerful preprocessor for embedding Perl and SQL in HTML
********************************************************

NAME
====

   CIPP - Powerful preprocessor for embedding Perl and SQL in HTML

SYNOPSIS
========

     use CIPP;
     my $CIPP = new CIPP ( @params );

     # @params are too complex for a synopsis

     $CIPP->Preprocess;

DESCRIPTION
===========

   CIPP = CgI Perl Preprocessor

   CIPP is a perl module for translating CIPP sources to pure perl
programs. CIPP defines a HTML embedding language called CIPP which has
powerful features for CGI and database developers.  Many standard CGI- and
database operations (and much more) are covered by CIPP, so the developer
has no need to code them again and again.

   CIPP is useful in two ways. One aproach is to let CIPP generate
standalone CGI scripts, which only need a little environment to run (some
configuration files). If you want to use CIPP in this way: there is a
complete development environment called spirit which supports you in many
ways, to develop such CGI programms with CIPP. spirit can be downloaded
from CPAN, but is only free for non commercial usage.

   The second is to use the Apache::CIPP_Handler module. This module
defines an Apache request handler for CIPP sources, so they will be
executed in an Apache environment on the fly, with a two-level cache and
great performance. The Apache::CIPP_Handler module is free software.

CIPP LANGUAGE REFERENCE
=======================

   Use 'perldoc CIPP::Manual' for a language reference. There also exists
a PDF document with some additional chapters about CIPP language basics
and configuration hints. This file can be downloaded from CPAN as an extra
package. This is usefull, because the format of the documentation is PDF
and the file has more than 500kb. Also not every modification of CIPP
leads to modification of the documentation.

AUTHOR
======

   Jörn Reder, joern@dimedis.de

COPYRIGHT
=========

   Copyright 1997-2001 dimedis GmbH, Cologne, All Rights Reserved

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1), Apache::CIPP_Handler(3pm)

Reference Manual
****************

NAME
====

   CIPP - Reference Manual

SYNOPSIS
========

     perldoc CIPP::Manual

DESCRIPTION
===========

   This is the reference manual for CIPP, the powerful preprocessor
language for embedding Perl and SQL in HTML. This documentation module is
part of the CIPP distribution available on CPAN.

   The manual describes all CIPP commands in alphabetical order.  Each
reference contains syntax notation, textual description and examples for
each command.

   This document is a excerpt from the full CIPP documentation which is
available as PDF format. You can download the PDF document from CPAN:

     $CPAN/modules/by-authors/id/J/JR/JRED/CIPP-DOC-x.xx.tar.gz

   The conversion of the FrameMaker source document to the POD format is
done automatically. Due to this the layout maybe slightly messed up in
some sections, but everything should be readable nevertheless. If you
don't like this please refer to the PDF document which has a really nice
layout.

QUICK FIND A COMMAND DESCRIPTION
================================

   If your perldoc is using 'less' for paging, it is easy to jump to a
particular command description.

   E.g. if you want to read the <?FOO> section, simply type this.

     /COMMAND...FOO

LIST OF CIPP COMMANDS
=====================

   This is a alphabetical list of all CIPP commands with a short
description, divided into sections of command types.

Variables and Scoping
---------------------

BLOCK
     Creation of a block context to limit the scope of private variables

MY
     Declaring a private (block local) variable

VAR
     Definition of a variable

Control Structures
------------------

DO
     Loop with condition check after first iteration

ELSE
     Alternative execution of a block

ELSIF
     Subsequent conditional execution

FOREACH
     Loop iterating with a variable over a list

IF
     Conditional execution of a block

PERL
     Insertion of pure Perl code

SUB
     Definition of a Perl subroutine

WHILE
     Loop with condition check before first iteration

Import
------

CONFIG
     Import a config file

INCLUDE
     Insertion of a CIPP Include file in the actual CIPP code

MODULE
     Definition of a CIPP Perl Module

REQUIRE
     Import a CIPP Perl Module

USE
     Import a standard  Perl module

Exception Handling
------------------

CATCH
     Execution of a block if a particular exception was thrown in a
     preceding TRY block.

LOG
     Write a entry in a logfile.

THROW
     Explicite creation of an exception.

TRY
     Secured execution of a block. Any exceptions thrown in the
     encapsulated block are caught.

SQL
---

AUTOCOMMIT
     Control of transaction behaviour

COMMIT
     Commit a transaction

DBQUOTE
     Quoting of a variable for usage in a SQL statement

GETDBHANDLE
     Returns the internal DBI database handle

ROLLBACK
     Rollback a transaction

SQL
     Execution of a SQL statement

URL- and Form Handling
----------------------

GETURL
     Creation of a CIPP object URL

HIDDENFIELDS
     Producing a number of hidden formular fields

HTMLQUOTE
     HTML encoding of a variable

URLENCODE
     URL encoding of a variable

HTML Tag Replacements
---------------------

A
     Replaces <A> tag

FORM
     Replaces <FORM> tag

IMG
     Replaces <IMG> tag

INPUT
     Replaces <INPUT> tag, with sticky feature

OPTION
     Replaces <OPTION> tag, with sticky feature

SELECT
     Replaces <SELECT> Tag, with sticky feature

TEXTAREA
     Replaces <TEXTAREA> tag

Interface
---------

GETPARAM
     Recieving a non declared CGI input parameter

GETPARAMLIST
     Returns a list of all CGI input parameter names

INCINTERFACE
     Declaration of a interface for CIPP Include

INTERFACE
     Declaration of a CGI interface for a CIPP program

SAVEFILE
     Storing a client side upload file

Apache
------

APGETREQUEST
     Returns the internal Apache request object

APREDIRECT
     Redirects to another URL internally

Preprocessor
------------

!AUTOPRINT
     Controls automatic output of HTML code

!HTTPHEADER
     Dynamic generation of a HTTP header

!PROFILE
     Initiate generation of profiling code

Debugging
---------

DUMP
     Dumps preformatted contents of data structures

COMMAND <?#>
============

Type
     Multi Line Comment

Syntax
          <?#>
          ...
          <?/#>

Description
     This block command realizes a multiline comment. Simple comments are
     introduced with a single # sign, so you can only comment one line
     with them. All text inside a <?#> block will be treated as a comment
     and will be ignored. Nesting of <?#> is allowed.

Example
     This is a simple multi line comment.

          <?#>
            This text will be ignored.
            All CIPP tags too.
            So this is no syntax error
            <?IF foo bar>
          <?/#>

     You may nest <?#> blocks:

          <?#>
            bla foo
            <?#>
               foo bar
            <?/#>
          <?/#>

COMMAND <?A>
============

Type
     HTML Tag Replacement

Syntax
          <?A HREF=hyperlinked_object_name[#anchor]
              [ additional_<A>_parameters ... ] >
          ...
          <?/A>

Description
     This command replaces the <A> HTML tag. You will need this in a
     new.spirit environment to set a link to a CIPP CGI or HTML object.

Parameter
*     HREF*
     This parameter takes the name of the hyperlinked object. You may
     optionally add an anchor (which should be defined using <A NAME> in
     the referred page) using the # character as a delimiter.

     This paremeter is expected as an URL in CGI::CIPP or Apache::CIPP
     environments and in dot-separated object notation in a new.spirit
     environment.

*     additional_A_parameters*
     All additional parameters are taken into the generated <A> tag.

Example
     Textual link to 'MSG.Main', in a new.spirit environment.

          <?A HREF="MSG.Main">Back to the main menu<?/A>

     Image link to '/main/menu.cgi', in a CGI::CIPP or Apache::CIPP
     environment:

          <?A HREF="/main/menu.cgi">
          <?IMG SRC="/images/logo.gif" BORDER=0>
          <?/A>

COMMAND <?APGETREQUEST>
=======================

Type
     Apache

Syntax
          <?APGETREQUEST [ MY ] VAR=request_variable >

Description
     This command is only working if CIPP is used as an Apache module.

     It returns the internal Apache request object, so you can use Apache
     specific features.

Parameter
*     VAR*
     This is the variable where the request object will be stored.

*     MY*
     If you set the MY switch, the created variable will be declared using
     'my'. Its scope reaches to the end of the block which surrounds the
     APGETREQUEST command.

Example
     The Apache request object will be stored in the implicitely declared
     variable $ar.

          <?APGETREQUEST MY VAR=$ar>

COMMAND <?APREDIRECT>
=====================

Type
     Apache

Syntax
          <?APREDIRECT URL=new_URL >

Description
     This command is only working if CIPP is used as an Apache module.

     It results in an internal Apache redirect. That means, the new url
     will be 'executed' without notifying the client about this.

Parameter
*     URL*
     This expression is used for the new URL.

Note:
     The program which uses <?APREDIRECT> should not produce any output,
     otherwise this may confuse the webserver or the client, if more then
     one HTTP header is sent. So you should use <?AUTOPRINT OFF> at the
     top of the program to circumvent that.

Example
     This commands redirect internally to the homepage of the
     corresponding website:

          <?AUTOPRINT OFF>
          <?APREDIRECT URL="/">

COMMAND <?AUTOCOMMIT>
=====================

Type
     SQL

Syntax
          <?AUTOCOMMIT ( ON | OFF )
                       [ DB=database_name ]
                       [ DBH=database_handle ]
                       [ THROW=exception ] >

Description
     The <?AUTOCOMMIT> command corresponds directly to the underlying DBI
     AutoCommit mechanism.

     If AutoCommit is activated each SQL statement will implicitely be
     executed in its own transaction. Think of a <?COMMT> after each
     statement. Explicite use of <?COMMIT> or <?ROLLBACK> is forbidden in
     AutoCommit mode.

     If AutoCommit is deactivated you have to call <?COMMIT> or
     <?ROLLBACK> yourself. CIPP will rollback any uncommited open
     transactions at the end of the program.

Parameter
*     ON | OFF*
     Switch AutoCommit modus either on or off.

*     DB*
     This is the CIPP internal name of the database for this command. In
     CGI::CIPP or Apache::CIPP environment this name has to be defined in
     the appropriate global configuration. In a new.spirit environment
     this is the name of the database configuration object in
     dot-separated notation.

     If DB is ommited the project default database is used.

*     DBH*
     Use this option to pass an existing DBI database handle, which should
     used for this SQL command.  You can't use the DBH option in
     conjunction with DB.

*     THROW*
     With this parameter you can provide a user defined exception which
     should be thrown on failure. The default exception thrown by this
     statement is autocommit.

     If the underlying database is not capable of transactions (e.g.
     MySQL) setting AutoCommit to ON will throw an exception.

Example
     Switch AutoCommit on for the database 'foo'.

          <?AUTOCOMMIT ON DB="foo">

     Switch AutoCommit off for the database 'bar' and throw the user
     defined exception 'myautocommit' on failure.

          <?AUTOCOMMIT OFF DB="bar" THROW="myautocommit">

COMMAND <?!AUTOPRINT>
=====================

Type
     Preprocessor

Syntax
          <?!AUTOPRINT OFF>

Description
     With the <?!AUTOPRINT OFF> command the preprocessor can be advised to
     suppress the generation of print statements for non CIPP blocks. The
     default setting is ON and it is only possible to switch it OFF and
     not the other way around.

     In earlier versions of CIPP this command was named <?AUTOPRINT>. This
     notation is depreciated, but will work for compatability reasons.

Parameter
*     OFF*
     Automatic generation of print statements for non CIPP blocks will be
     deactivated.

Note
     This is a preprocessor command. Please read the chapter about
     preprocessor commands for details about this.

     You should use this command at the very top of your program file.
     CIPP will not generate any HTTP headers for you, if you use
     <?!AUTOPRINT OFF>, so you have to do this on your own. If you only
     want to generate a special HTTP header, use <?!HTTPHEADER> instead.

     The ,CIPP Introduction" Chapter contains a paragraph about CIPP
     Preprocessor Commands. Please refer to this discussion for details of
     <?!AUTOPRINT>.

Example
     This program sends a GIF image to the client, after generating the
     proper HTTP header. (For another example, see <?APREDIRECT>)

          <?AUTOPRINT OFF>
          These lines will never be printed, they are fully ignored!!!

          <?PERL>
            my $file = "/tmp/image.gif";
            my $size = -s $file;

          print "Content-type: image/gif\n";
          print "Content-length: $size\n\n";

          open (GIF, $file) or die "can't open $file";
          while (<GIF>) {
            print;
          }
          close GIF;
            <?/PERL>

COMMAND <?BLOCK>
================

Type
     Variables and Scoping

Syntax
          <?BLOCK>
          ...
          <?/BLOCK>

Description
     Use the <?BLOCK> command to divide your program into logical blocks
     to control variable scoping. Variables declared with <?MY> inside a
     block are not valid outside.

Example
     The variable $example does not exist beyond the block.

          <?BLOCK>
            <?MY $example>
            $example is known.
          <?/BLOCK>

     $example does not exist here. This will

     result in a Perl compiler error, because

     $example is not declared here.

COMMAND <?CATCH>
================

Type
     Exception Handling

Syntax
          <?CATCH [ THROW=exception ]
                  [ MY ]
                  [ EXCVAR=variable_for_exception ]
                  [ MSGVAR=variable_for_error_message ] >
          ...
          <?/CATCH>

Description
     Typically a <?CATCH> block follows after a <?TRY> block. You can
     process one particular or just any exception with the <?CATCH> block.

     <?CATCH> and <?TRY> has to be placed inside the same block.

     See the description of <?TRY> for details about the CIPP exception
     handling mechanism.

Parameter
*     THROW*
     If this parameter is omitted, all exceptions will be processed here.
     Otherwise the <?CATCH> block is executed only if the appropriate
     exception was thrown.

*     EXCVAR*
     Names the variable, where the exception identifier should be stored
     in. Usefull if you use <?CATCH> for a generic exception handler and
     omitted the THROW parameter.

*     MSGVAR*
     Name the variable, where the error message should be stored in.

*     MY*
     If you set the MY switch the created variable will be declared using
     'my'. Its scope reaches to the end of the block which surrounds the
     <?CATCH> command.

Example
     We try to insert a row into a database table, which has a primary key
     defined, and commit the transcation. We catch two exceptions: the
     possible primary key constraint violation and a possible commit
     exception, maybe the database is not capable of transactions.

          <?TRY>
            <?SQL SQL="insert into persons
                      (firstname, lastname)
                       values ('John', 'Doe')"><?/SQL>
            <?COMMIT>
          <?/TRY>

          <?CATCH THROW=sql MY MSGVAR=$message>
            <?LOG MSG="Can't insert data: $message"
                  TYPE="database">
          <?/CATCH>

          <?CATCH THROW=commit MSGVAR=$message>
            <?LOG MSG="COMMIT rejected: $message"
                  TYPE="database">
          <?/CATCH>

COMMAND <?COMMIT>
=================

Type
     SQL

Syntax
          <?COMMIT [ DB=database_name ]
                   [ DBH=database_handle ]
                   [ THROW=exception ] >

Description
     The <?COMMIT> command concludes the actual transaction and makes all
     changes to the database permanent.

     Using <?COMMIT> in <?AUTOCOMMIT ON> mode is not possible.

     If you are not in <?AUTOCOMMIT ON> mode a transaction begins with the
     first SQL statement and end either with a <?COMMIT> or <?ROLLBACK>
     command.

Parameter
*     DB*
     This is the CIPP internal name of the database for this command. In
     CGI::CIPP or Apache::CIPP environment this name has to be defined in
     the appropriate global configuration. In a new.spirit environment
     this is the name of the database configuration object in
     dot-separated notation.

     If DB is ommited the project default database is used.

*     DBH*
     Use this option to pass an existing DBI database handle, which should
     used for this SQL command.  You can't use the DBH option in
     conjunction with DB.

*     THROW*
     With this parameter you can provide a user defined exception which
     should be thrown on failure. The default exception thrown by this
     statement is commit.

     If the underlying database is not capable of transactions (e.g.
     MySQL) execution of this command will throw an exception.

Example
     We insert a row into a database table and commit the change
     immediately. We throw a user defined exeption, if the commit fails.
     So be safe we first disable AutoCommiting.

          <?AUTOCOMMIT OFF>
          <?SQL SQL="insert into foo (num, str)
                     values (42, 'bar');">
          <?/SQL>
          <?COMMIT THROW="COMMIT_Exception">

COMMAND <?CONFIG>
=================

Type
     Import

Syntax
          <?CONFIG NAME=config_file
                   [ RUNTIME ] [ NOCACHE ]
                   [ THROW=exception ] >

Description
     The <?CONFIG> command reads a config file. This is done via a
     mechanism similar to Perl's require, so the config file has to be
     pure Perl code defining global variables.

     <?CONFIG> ensures a proper load of the configuration file even in
     persistent Perl environments.

     In contrast to "require" <?CONFIG>  will reload a config file when
     the file was altered on disk. Otherwise the file will only be loaded
     once.

Parameter
*     NAME*
     This is the name of the config file, expected as an URL in CGI::CIPP
     or Apache::CIPP environments and in dot-separated object notation in
     a new.spirit environment.

*     RUNTIME*
     This switch makes sense only in a new.spirit environment. If you set
     it the NAME parameter will be resolved at runtime, so it can contain
     variables. new.spirit will not check the existance of the file in
     this case. Normally you'll get a CIPP error message, if the adressed
     file does not exist.

     In CGI::CIPP and Apache::CIPP environments the NAME parameter will
     always be resolved at runtime.

*     NOCACHE*
     This switch is useful in persistant Perl environments. It forces
     <?CONFIG> to read the config file even if it did not change on disk.
     You'll need this if your config file does some calculations based on
     the request environment, e.g. if the value of some variables depends
     on the clients user agent.

*     THROW*
     With this parameter you can provide a user defined exception to be
     thrown on failure. The default exception thrown by this statement is
     config.

     An exception will be thrown, if the config file does not exist or is
     not readable.

Example
     Load of the configuration file "/lib/general.conf", with disabled
     cache, used in CGI::CIPP or Apache::CIPP environment:

          <?CONFIG NAME="/lib/general.conf" NOCACHE>

     Load of the configuration file object x.custom.general in a
     new.spirit environment:

          <?CONFIG NAME="x.custom.general">

     Load of a config file with a name determined at runtime, in a
     new.spirit environment, throwing "myconfig" on failure:

          <?CONFIG NAME="$config_file" RUNTIME
                   THROW="myconfig">

COMMAND <?DBQUOTE>
==================

Type
     SQL

Syntax
          <?DBQUOTE VAR=variable
                    [ MY ]
                    [ DBVAR=quoted_result_variable ]
                    [ DB=database_name ]
                    [ DBH=database_handle ] >

Description
     <?SQL> (and DBI) has a nice way of quoting parameters to SQL
     statements (called parameter binding). Usage of that mechanism is
     generally recommended (see <?SQL> for details). However if you need
     to construct your own SQL statement, <?DBQUOTE>  will let you do so.

     <?DBQUOTE>  will generate the string representation of the given
     scalar variable as fit for an SQL statement. That is, it takes care
     of quoting special characteres.

Parameter
*     VAR*
     This is the scalar variable containing the parameter you want to be
     quoted.

*     DBVAR*
     This optional parameters takes the variable where the quoted content
     should be stored. The surrounding ' characters are part of the
     result, if the variable is not undef. A value of undef will result in
     NULL (without the surrounding '), so the quoted variable can be
     placed directly in a SQL statement.

     If you ommit DBVAR, the name of the target variable is computed by
     placing the prefix 'db_' in front of the VAR name.

*     MY*
     If you set the MY switch the created variable will be declared using
     'my'. Its scope reaches to the end of the block which surrounds the
     <?DBQUOTE> command.

*     DB*
     This is the CIPP internal name of the database for this command. In
     CGI::CIPP or Apache::CIPP environment this name has to be defined in
     the appropriate global configuration. In a new.spirit environment
     this is the name of the database configuration object in
     dot-separated notation.

     If DB is ommited the project default database is used.

*     DBH*
     Use this option to pass an existing DBI database handle, which should
     used for this SQL command.  You can't use the DBH option in
     conjunction with DB.

Example
     This quotes the variable $name, the result will be stored in the just
     declared variable $db_name.

          <?DBQUOTE MY VAR="$name">

     This quotes $name, but stores the result in the variable $quoted_name.

          <?DBQUOTE VAR="$name" MY DBVAR="$quoted_name">

     The quoted variable can be used in a SQL statement this way:

          <?SQL SQL="insert into persons (name)
                     values ( $quoted_name )">

COMMAND <?DO>
=============

Type
     Control Structure

Syntax
          <?DO>
          ...
          <?/DO COND=condition >

Description
     The <?DO> block repeats executing the contained code as long as the
     condition evaluates true. The condition is checked afterwards. That
     means that the block will always be executed at least once.

Parameter
*     COND*
     This takes a Perl condition. As long as this condition is true the
     <?DO> block will be repeated.

Example
     Print  "Hello World" $n times. (note: for n=0 and n=1 you get the
     same result)

          <?DO>
            Hello World<BR>
          <?/DO COND="--$n > 0">

COMMAND <?DUMP>
===============

Type
     Debugging

Syntax
          <?DUMP $var_1 ... $var_n>

Description
     The <?DUMP> command dumps the contents of the given variables using
     Data::Dumper, inside of a HTML <pre></pre> block.

Parameter
     $var_1 .. $var_n

     The contents of this variables are dumped to STDOUT.

Example
          <?DUMP $hash_ref $list_ref>

COMMAND <?ELSE>
===============

Type
     Control Structure

Syntax
          <?ELSE>

Description
     <?ELSE> closes an open <?IF> or <?ELSIF> conditional block and opens
     a new block (which is later terminated by <?/IF>). The block is only
     executed if the condition of the preceding block was evaluated and
     failed.

     <?MY> variables are only visible inside this block.

     (Or short: it works as you would expect.)

Example
     Only Larry gets a personal greeting message:

          <?IF COND="$name eq 'Larry'">
            Hi Larry, you're welcome!
          <?ELSE>
            Hi Stranger!
          <?/IF>

COMMAND <?ELSIF>
================

Type
     Control Structure

Syntax
          <?ELSIF COND=condition >

Description
     <?ELSIF> closes an open <?IF> or <?ELSIF> conditional block and opens
     a new block. The condition is only evaluated if the condition of the
     preceding block was evaluated and failed.

     <?MY> variables are only visible inside this block.

     (Or short: it works as you would expect.)

Parameter
*     COND*
     Takes the Perl condition.

Example
     Larry and Linus get personal greeting messages:

          <?IF COND="$name eq 'Larry'">
            Hi Larry, you're welcome!
          <?ELSIF COND="$name eq 'Linus'">
            Hi Linus, you're velkomma!
          <?ELSE>
            Hi Stranger!
          <?/IF>

COMMAND <?FOREACH>
==================

Type
     Control Structure

Syntax
          <?FOREACH [ MY ] VAR=running_variable
                    LIST=perl_list >
          ...
          <?/FOREACH>

Description
     <?FOREACH> corresponds directly the Perl foreach command. The running
     variable will iterate of the list, executing the enclosed block for
     each value of the list.

Parameter
*     VAR*
     This is the scalar running variable.

*     LIST*
     You can write any Perl list here, e.g. using the bracket notation or
     pass a array variable using the @ notation.

*     MY*
     If you set the MY switch the created running variable will be
     declared using 'my'. Its scope reaches to the end of the block which
     surrounds the <?FOREACH> command.

     Note: this is a slightly different behaviour compared to a Perl
     "foreach my $var (@list)" command, where the running variable $var is
     valid only inside of the foreach block.

Example
     Counting up to 'three':

          <?FOREACH MY VAR="$cnt"
                    LIST="('one', 'two', 'three')">
            $cnt
          <?/FOREACH>

COMMAND <?FORM>
===============

Type
     HTML Tag Replacement

Syntax
          <?FORM ACTION=cgi_file
                 [ additional_<FORM>_parameters ... ] >
          ...
          <?/FORM>

Description
     <?FORM> generates a HTML <FORM> tag, setting the ACTION option to the
     appropriate URL. The request METHOD defaults to POST if no other
     value is given.

Parameter
*     ACTION*
     This is the name of the form target CGI program, expected as an URL
     in CGI::CIPP or Apache::CIPP environments and in dot-separated object
     notation in a new.spirit environment.

*     additional_FORM_parameters*
     All additional parameters are taken over without changes into the
     produced <FORM> tag. If you ommit the METHOD parameter it will
     default to POST.

Example
     Creating a named form with a submit button, pointing to the CGI
     object "x.login.start", in a new.spirit environment:

          <?FORM ACTION="x.login.start" NAME="myform">
          <?INPUT TYPE=SUBMIT VALUE=" Start ">
          <?/FORM>

     Creating a similar form, but the action is written as an URL because
     we are in CGI::CIPP or Apache::CIPP environment:

          <?FORM ACTION="/login/start.cgi" NAME="myform">
          <?INPUT TYPE=SUBMIT VALUE=" Start ">
          <?/FORM>

COMMAND <?GETDBHANDLE>
======================

Type
     SQL

Syntax
          <?GETDBHANDLE [ DB=database_name ] [ MY ]
                        VAR=handle_variable >

Description
     This command returns a reference to the internal Perl database
     handle, which is the object references returned by DBI->connect.

     With this handle you are able to perform DBI specific functions which
     are currently not directly available through CIPP.

Parameter
*     VAR*
     This is the variable where the database handle will be stored.

*     MY*
     If you set the MY switch the created variable will be declared using
     'my'. Its scope reaches to the end of the block which surrounds the
     <?GETDBHANDLE> command.

*     DB*
     This is the CIPP internal name of the database for this command. In
     CGI::CIPP or Apache::CIPP environment this name has to be defined in
     the appropriate global configuration. In a new.spirit environment
     this is the name of the database configuration object in
     dot-separated notation.

     If DB is ommited the project default database is used.

Example
     We get the database handle for the database object 'x.Oracle' in a
     new.spirit environment and perform a select query using this handle.

     Ok, you simply can do this with the <?SQL> command, but now you can
     see how much work is done for you through CIPP :)

          <?GETDBHANDLE DB="MSG.Oracle" MY VAR="$dbh">

          <?PERL>
            my $sth = $dbh->prepare ( qq{
                select n,s from TEST_table
                where n between 10 and 20
            });
            die "my_sql\t$DBI::errstr" if $DBI::errstr;

          $sth->execute;
          die "my_sql\t$DBI::errstr" if $DBI::errstr;

          my ($n, $s);
          while ( ($n, $s) = $sth->fetchrow ) {
            print "n=$n s=$s<BR>\n";
          }
          $sth->finish;
          die "my_sql\t$DBI::errstr" if $DBI::errstr;

          <?/PERL>

COMMAND <?GETPARAM>
===================

Type
     Interfaces

Syntax
          <?GETPARAM NAME=parameter_name
                     [ MY ] [ VAR=content_variable ] >

Description
     With this command you can explicitely get a CGI parameter. This is
     useful if your CGI program uses dynamically generated parameter
     names, so you are not able to use <?INTERFACE> for them.

     Refer to <?INTERFACE> to see how easy it is to handle standard CGI
     input parameters.

Parameter
*     NAME*
     Identifier of the CGI input parameter

*     VAR*
     This is the variable where the content of the CGI parameter will be
     stored. This can be either a scalar variable (indicated through a $
     sign) or an array variable (indicated through a @ sign).

*     MY*
     If you set the MY switch the created variable will be declared using
     'my'. Its scope reaches to the end of the block which surrounds the
     <?GETPARAM> command.

Example
     We recieve two parameters, one staticly named parameter and one
     scalar parameter, which has a dynamic generated identifier.

          <?GETPARAM NAME="listparam" MY VAR="@list">
          <?GETPARAM NAME="scalar$name" MY VAR="$scalar">

COMMAND <?GETPARAMLIST>
=======================

Type
     Interfaces

Syntax
          <?GETPARAMLIST [ MY ] VAR=variable >

Description
     This command returns a list containing the identifiers of all CGI
     input parameters.

Parameter
*     VAR*
     This is the variable where the identifiers of all CGI input
     parameters will be stored in. It must be an array variable, indicated
     through a @ sign.

*     MY*
     If you set the MY switch the created list variable will be declared
     using 'my'. Its scope reaches to the end of the block which surrounds
     the <?GETPARAMLIST> command.

Example
     The list of all CGI input parameter identifiers will be stored into
     the array variable @input_param_names.

          <?GETPARAMLIST MY VAR="@input_param_names">

COMMAND <?GETURL>
=================

Type
     URL and Form Handling

Syntax
          <?GETURL NAME=object_file
                   [ MY ] VAR=target_variable
                   [ RUNTIME ] [ THROW=exception ] >
                   [ PARAMS=parameters_variables ]
                   [ PAR_1=value_1 ... PAR_n=value_n ] >

Description
     This command returns a URL, optionally with parameters. In a
     new.spirit environment you use this to resolve the dot-separated
     object name to a real life URL.

     In CGI::CIPP and Apache::CIPP environments this is not necessary,
     because you work always with real URLs. Nevertheless it also useful
     there, because its powerfull possibilities of generating parmeterized
     URLs.

Parameter
*     NAME*
     This is the name of the specific file, expected as an URL in
     CGI::CIPP or Apache::CIPP environments and in dot-separated object
     notation in a new.spirit environment.

*     VAR*
     This is the scalar variable where the generated URL will be stored
     in. In earlier versions of CIPP this option was named URLVAR. The
     usage of the URLVAR notation is depreciated, but it works for
     compatibility reasons. To prevent from logical errors CIPP throws an
     error if you use URLVAR and VAR inside of one command (e.g. to create
     an URL which contains a parameter called VAR or URLVAR).

*     URLVAR*
     Depreciated. See description of VAR.

*     MY*
     If you set the MY switch the created variable will be declared using
     'my'. Its scope reaches to the end of the block which surrounds the
     <?GETURL> command.

*     RUNTIME*
     This switch makes only sense in a new.spirit environment. The NAME
     parameter will be resolved at runtime, so it can contain variables.
     CIPP will not check the existance of the file in this case. Normally
     you get a CIPP error message, if the adressed file does not exist.

     In CGI::CIPP and Apache::CIPP environments the NAME parameter will
     always be resolved at runtime.

*     THROW*
     With this parameter you can define the exception to be thrown on
     failure. The default exception thrown by this statement is geturl.

     An exception will be thrown, if the adressed file does not exist.

*     PARAMS*
     This takes a comma separated list of parameters, which will be
     encoded and added to the generated URL. You may pass scalar variables
     (indicated through the $ sign) and also array variables (indicated
     through the @ sign).

     With the PARAMS option you can only pass parameters whose values are
     stored in variables with the same name (where case is significant).
     The variables listed in PARAMS will be treated case sensitive.

*     PAR_1..PAR_n*
     Any additional parameters to <?GETURL> are interpreted as named
     parameters for the URL.  You can pass scalar and array values this
     way (using $ and @). Variables passed this way are seen by the called
     program as lower case written variable names, no matter which case
     you used in <?GETURL>.

Note
     It is highly recommended to use lower case variable names. Due to
     historical reasons CIPP converts parameter names to lower case
     without telling you about it. If this ever gets "fixed" and you have
     uppercase latters, your code will break. So, use lowercase.

Example
     We are in a new.spirit environment and produce a <IMG> tag, pointing
     to a new.spirit object (btw: the easiest way of doing this is the
     <?IMG> command):

          <?GETURL NAME="x.Images.Logo" MY VAR=$url>
          <IMG SRC="$url">

     Now we link the CGI script "/secure/messager.cgi" in a CGI::CIPP or
     Apache::CIPP environment. We pass some parameters to this script.
     (Note the case sensitivity of the parameter names, we really should
     use lower case variables all the time!)

          <?VAR MY NAME=$Username>hans<?/VAR>
          <?VAR MY NAME=@id>(1,42,5)<?/VAR>
          <?GETURL NAME="/secure/messager.cgi" MY VAR=$url
                   PARAMS="$Username, @id" EVENT=delete>
          <A HREF="$url">delete messagse</A>

     The CGI program "/secure/messager.cgi" recieves the parameters this
     way (note that the $Username parameter is seen as $Username, but
     EVENT is seen as $event). If you find this confusing, use always
     lower case variable names.

          <?INTERFACE INPUT="$event, $Username, @id">
          <?IF COND="$event eq 'delete'">
            <?MY $id_text>
            <?PERL>$id_text = join (", " @id)<?PERL>
            You are about to delete
            $username's ID's?: $id_text<BR>
          <?/IF>

COMMAND <?HIDDENFIELDS>
=======================

Type
     URL and Form Handling

Syntax
          <?HIDDENFIELDS [ PARAMS=parameter_variables ]
                         [ PAR_1=value_1 ... PAR_n=value_n ] >

Description
     This command produces a number of <INPUT TYPE=HIDDEN> HTML tags, one
     for each parameter you specify. Use this to transport a bunch of
     parameters via a HTML form. This command takes care of special
     characters in the parameter values and quotes them if necessary.

Parameter
*     PARAMS*
     This takes a comma separated list of parameters, which will be
     encoded and transformed to a <INPUT TYPE=HIDDEN> HTML tag. You may
     pass scalar variables (indicated through the $ sign) and also array
     variables (indicated through the @ sign).

     With the PARAMS option you can only pass parameters whose values are
     stored in variables with the same name (where case is significant).

*     PAR_1..PAR_n*
     Any additional parameters to <?HIDDENFIELDS> are interpreted as named
     parameters.  You can pass scalar and array values this way (using $
     and @). Variables passed this way are seen by the called program as
     lower case written variable names, no matter which case you used in
     <?HIDDENFIELDS>.

Example
     This is a form in a new.spirit environment, pointing to the object
     "x.secure.messager". The two parameters $username and $password are
     passed via PARAMS, the parameter "event" is set to "show".

          <?FORM ACTION="x.secure.messager">
          <?HIDDENFIELDS PARAMS="$username, $password"
                         event="show">
          <INPUT TYPE=SUBMIT VALUE="show messages">
          <?/FORM>

COMMAND <?HTMLQUOTE>
====================

Type
     URL and Form Handling

Syntax
          <?HTMLQUOTE VAR=variable_to_encode
                      [ MY ] HTMLVAR=target_variable >

Description
     This command quotes the content of a variable, so that it can be used
     inside a HTML option or <TEXTAREA> block without the danger of syntax
     clashes. The following conversions are done in this order:

          &  =>  &amp;

          <  =>  &lt;

          "  =>  &quot;

Parameter
*     VAR*
     This is the scalar variable containing the parameter you want to be
     quoted.

*     HTMLVAR*
     This non-optional parameter takes the variable where the quoted
     content will be stored.

*     MY*
     If you set the MY switch the created variable will be declared using
     'my'. Its scope reaches to the end of the block which surrounds the
     <?HTMLQUOTE> command.

Example
     We produce a <TEXTAREA> tag with a quoted instance of the variable
     $text. Note: you can also use the <?TEXTAREA> command for this
     purpose.

          <?HTMLQUOTE VAR="$text" MY HTMLVAR="$html_text">
          <TEXTAREA NAME="text">$html_text</TEXTAREA>

COMMAND <?!HTTPHEADER>
======================

Type
     Preprocessor

Syntax
          <?!HTTPHEADER [ MY ] VAR=http_header_hash_ref >
            # Perl Code which modifies the
            # http_header_hash_ref variable
          <?/!HTTPHEADER>

Description
     Use this command, if you want to modify the standard HTTP header
     response. CIPP generates by default a simple HTTP header of this form:

          Content-type: text/html\n\n

     In a new.spirit environment you can define a project wide default
     HTTP header extension, e.g. ,Pragme: no-cache", or something similar.

     If you want to modify the HTTP header at runtime, you can use this
     command. The <?!HTTPHEADER> command switches to Perl context, so you
     write Perl code inside the block. The variable you declared with the
     VAR option is accessable inside this block and will contain a
     reference to a hash containing the default HTTP header tags. Your
     Perl code now can delete, add or modifiy HTTP header tags.

     But be careful: because <?!HTTPHEADER> is a preprocessor command, the
     position of the <?!HTTPHEADER> command inside your CIPP program (even
     if you use it inside an Include), does not indicate the time, on
     which your HTTP header code is executed.

     CIPP inserts the code you write in the <?!HTTPHEADER> block at the
     top of the generated CGI code, so it is executed before any other
     code you wrote in you CIPP program or Include, because the HTTP
     header must appear before any content.

     So it is not possible to access any lexically scoped variables
     declared outside the <?!HTTPHEADER> block within the block. Usually
     you statically add or delete HTTP header fields. Your code may depend
     on CGI environment variables, or on a result of a SQL query, but
     that's it. If you want to access configuration variables, you must
     use the <?CONFIG> command inside your <?!HTTPHEADER> block.

Note
     This command is not implemented for Apache::CIPP and CGI::CIPP
     environments, but you can use it with new.spirit .

Parameter
*     VAR*
     The actual HTTP header will be assigned to this variable, as a
     reference to a hash. This keys of  this hash are the HTTP header tags.

*     MY*
     If you set the MY switch the created variable will be declared using
     'my'. Its scope reaches to the end of the  <?!HTTPHEADER> block .

Example
     A HTTP header is created, which tells proxies how long they may cache
     the content of the produces HTML page.

          <?!HTTPHEADER MY VAR="$http">
            # delete a Pragma Tag (may be defined
            # globally in a new.spirit environment)
            delete $http->{Pragma};

          # read a global config
          <?CONFIG NAME="x.global">

          # get cache time
          my $cache_time = $global::cachable_time || 1200;

          # set Cache-Control header tag
          $http->{'Cache-Control'} =
              "max-age=$cache_time, public";
            <?!/HTTPHEADER>

COMMAND <?IF>
=============

Type
     Control Structure

Syntax
          <?IF COND=condition >
          ...
          [ <?ELSIF COND=condition > ]
          ...
          [ <?ELSE> ]
          ...
          <?/IF>

Description
     The <?IF> command executes the enclosed block if the condition is
     true. <?ELSE> and <?ELSIF> can be used inside an <?IF> block in the
     common manner.

Parameter
*     COND*
     This takes a Perl condition. If this condition is true, the code
     inside the <?IF> block is executed.

Example
     Only Larry gets a greeting message here.

          <?IF COND="$name eq 'Larry'">
            Hi Larry!
          <?/IF>

COMMAND <?IMG>
==============

Type
     HTML Tag Replacement

Syntax
          <?IMG SRC=image_file
                [ additional_<IMG>_parameters ... ] >

Description
     A HTML <IMG> Tag will be generated, whoms SRC option points to the
     appropriate image URL.

Parameter
*     SRC*
     This is the name of the image, expected as an URL in CGI::CIPP or
     Apache::CIPP environments and in dot-separated object notation in a
     new.spirit environment.

*     additional_IMG_parameters*
     All additional parameters are taken without changes into the produced
     <IMG> tag.

Example
     In a new.spirit environment we produce a image link to another page,
     setting the border to 0.

          <?A HREF="x.main.menu">
          <?IMG SRC="x.images.logo" BORDER=0>
          <?/A>

     In CGI::CIPP or Apache::CIPP environment we provide an URL instead of
     a dot-separated object name.

          <?A HREF="/main/menu.cgi">
          <?IMG SRC="/images/logo.jpg" BORDER=0>
          <?/A>

COMMAND <?INCINTERFACE>
=======================

Type
     Interface

Syntax
          <?INCINTERFACE [ INPUT=list_of_variables ]
                         [ OPTIONAL=list_of_variables
                         [ NOQUOTE=list_of_variables ]
                         [ OUTPUT=list_of_variables ] >

Description
     Use this command to declare an interface for an Include file. You can
     use this inside the Include file. In order to declare the interface
     of a CGI file this, use the <?INTERFACE> command.

     You can declare mandatory and optional parameters. Parameters are
     always identified by name, not by position like in many programming
     languages. You can pass all types of Perl variables (scalars, arrays
     and hashes, also references). Also you can specify output parameters,
     which are passed back to the caller. Even these parameters are named,
     which requires some getting used to for most people. However it is
     very useful. :)

     All input parameters declared this way are visible as the appropriate
     variables inside the Include file. They are always declared with my
     to prevent name clashes with other parts of the program.

Parameter
     All parameters of <?INCINTERFACE> expect a comma separated list of
     variables. All Perl variable types are supported: scalars ($), arrays
     (@)and hashes (%).  Whitespaces are ignored. Read the note beneath
     the NOQUOTE section about passing non scalar values to an Include.

     Note: You have to use lower case variable names, because the
     <?INCLUDE> command converts all variable names to lower case.

*     INPUT*
     This parameters takes the list of variables the caller must provide
     in his <?INCLUDE> command (mandatory parameters).

*     OPTIONAL*
     The variables listed here are optional input parameters. They are
     always declared with my and visible inside the Include, but are set
     to undef, if the caller ommits them.

*     OUTPUT*
     If you want your Include to pass values back to the caller, list the
     appropriate variables here. This variables are declared with my. Set
     them everywhere in your Include, they will be passed back
     automatically.

     Note: the name of the variable receiving the output from the include
     must be different from the name of the output parameter. This is due
     to restrictions of the internal implementation.

*     NOQUOTE*
     By default all input parameters are defined by assigning the given
     value using double quotes. This means it is possible to pass either
     string constants or string expressions to the Include, which are
     interpreted at runtime, in the same manner. Often this is the
     behaviour you expect.

     You have to list input (no output) parameters in the NOQUOTE
     parameter if you want them to be interpreted as a real Perl
     expression, and not in the string context  (e.g. $i+1 will result in
     a string containing the value of $i concatenated with +1 in a string
     context, but in an incremented $i otherwise).

     Note: Also you have to list all non-scalar and reference input
     parameters here, because array, hash and reference variables are also
     computed inside a string context by default, and this is usually not
     what you expect.

     Note: Maybe this will change in future. Listing array and hash
     parameters in NOQUOTE will be optional, the default behaviour for
     those variables will change, so that they are not computed in string
     context by default.

Notes
     The <?INCINTERFACE> command may occur several times inside one
     Include file. The position inside the source code does not matter.
     All declarations will be added to an interface accordingly.

     If you ommit a <?INCINTERFACE> command inside your Include, its
     interface is empty. That means, you cannot pass any parameters to it.
     If you try so this will result in an error message at CIPP compile
     time.

Example
     This example declares an interface, expecting some scalars and an
     array. Note the usage of NOQUOTE for the array input parameter. The
     Include also returns a scalar and an array parameter.

          <?INCINTERFACE INPUT="$firstname, $lastname"
                         OPTIONAL="@id"
                         OUTPUT="$scalar, @list"
                         NOQUOTE="@id">
          ...

          <?PERL>
            $scalar="returning a scalar";
            @list= ("returning", "a", "list");
          <?/PERL>

     The caller may use this <?INCLUDE> command. Note that all input
     parameter names are converted to lower case.

          <?INCLUDE NAME="/include/test.inc"
                    FIRSTNAME="Larry"
                    lastname="Wall"
                    ID="(5,4,3)"
                    MY
                    $s=SCALAR
                    @l=LIST>

COMMAND <?INCLUDE>
==================

Type
     Import

Syntax
          <?INCLUDE NAME=include_name
                  [ input_parameter_1=Wert1 ... ]
                  [ MY ]
                  [ variable_1=output_parameter_1 ... ] >

Description
     Use Includes to divide your project into reusable pieces of code.
     Includes are defined in separate files. They have a well defined
     interface due to the <?INCINTERFACE> command. CIPP performs parameter
     checking for you and complain about unknown or missing parameters.

     The Include file code will be inserted at the same position you write
     <?INCLUDE>, inside of a Perl block. Due to this variables declared
     inside the Include are not valid outside.

     Please refer to the <?INCINTERFACE> chapter to see how parameters are
     processed by an Include.

Parameter
*     NAME*
     This is the name of the Include file, expected as an URL in CGI::CIPP
     or Apache::CIPP environments and in dot-separated object notation in
     a new.spirit environment.

*     INPUT-PARAMETERS*
     You can pass parameters to the Include using the usual
     PARAMETER=VALUE notation. Note that parameter names are converted to
     lower case. For more details about Include input parameters refer to
     the appropriate section of the <?INCINTERFACE> chapter.

*     OUTPUT-PARAMETERS*
     You can recieve parameters from the Include using the notation

     {$@%}variable=output_parameter

     Note that the name of the output parameters are automatically
     converted to lower case. Note also that the caller must not use the
     same name like the output parameter for the local variable which
     recieves the output parameter. That means for the above notation that
     variable must be different from output_parameter, ignoring the case.

     For more details about Include output parameters refer to the
     appropriate section of the <?INCINTERFACE> chapter.

*     MY*
     If you set the MY switch all created output parameter variables will
     be declared using 'my'. Their scope reaches to the end of the block
     which surrounds the <?INCLUDE> command.

     Important note

     The actual CIPP implementation does really include the Include code
     at the position where the <?INCLUDE> command occurs. This affects
     variable scoping. All variables visible at the callers source code
     where you write the <?INCLUDE> command are also visible inside your
     Include. So you can use these variables, although you never declared
     them inside your Include. Use of this feature is discouraged, in fact
     you should avoid the usage of variables you did not declared in your
     scope.

     Short notation

     In a new.spirit environment the <?INCLUDE> command can be abbreviated
     in the following manner:

          <?include_name
              [ input_parameter_1=Wert1 ... ]
              [ MY ]
              [ variable_1=output_parameter_1 ... ] >

Example
     See example of <?INCINTERFACE>.

COMMAND <?INPUT>
================

Type
     HTML Tag Replacement

Syntax
          <?INPUT [ NAME=parameter_name ]
                  [ VALUE=parameter_value ]
                  [ SRC=image_object ]
                  [ TYPE=input_type ] [ STICKY[=sticky_var] ]
                  [ additional_<INPUT>_parameters ... ] >

Description
     This generates a HTML <INPUT> tag where the content of the VALUE
     option is escaped to prevent HTML syntax clashes. In case of
     TYPE="radio" or TYPE="checkbox" in conjunction with the STICKY
     Option, the state of the input widget will be preserved.

Parameter
*     NAME*
     The name of the input widget.

*     VALUE*
     This is the VALUE of the corresponding <INPUT> tag. Its content will
     be escaped.

*     SRC*
     This is the name of the image, expected as an URL in CGI::CIPP or
     Apache::CIPP environments and in dot-separated object notation in a
     new.spirit environment.

*     TYPE*
     Only the TYPEs ,radio" and ,checkbox" are specially handled when the
     STICKY option is also given.

*     STICKY*
     If this option is set and the TYPE of the input widget is eiterh
     ,radio" or ,checkbox" CIPP will generate the CHECKED option
     automatically, if the value of the corresponding Perl variable (which
     is $parameter_name for TYPE="radio" and @parameter_name for
     TYPE="checkbox") equals to the VALUE of this widget. If you assign a
     value to the STICKY option, this will be taken as the Perl variable
     for checking the state of the widget. But the default behaviour of
     deriving the name from the NAME option will fit most cases.

*     additional_INPUT_parameters*
     All additional parameters are taken without changes into the
     generated <INPUT> tag.

Note
     If you use the STICKY feature in conjuncion with checkboxes, please
     note that the internal implementation may be ineffective, if you
     handle large checkbox groups. This is due the internal representation
     of the checkbox values as a list, so a grep is neccesary to check,
     wheter a checkbox is checked or not. If you feel uncomfortable about
     that, use a classic HTML <INPUT> tag, maybe with a loop around it,
     and check state of the checkboxes using a hash.

Example
     We generate two HTML input fields, a simple text and a password
     field, both initialized with some values. Also two checkboxes are
     generated, using the STICKY feature to initalize their state
     genericly.

          <?VAR MY NAME=$username>larry<?/VAR
          <?VAR MY NAME=$password>this is my "password"<?/VAR>
          <?INPUT TYPE=TEXT SIZE=40 VALUE=$username>
          <?INPUT TYPE=PASSWORD SIZE=40 VALUE=$password>

          <?VAR MY NAME=$check>42<?/VAR>
          <?INPUT TYPE=CHECKBOX NAME="check" VALUE="42"
                  STICKY> 42
          <?INPUT TYPE=CHECKBOX NAME="check" VALUE="43"
                  STICKY> 43

     This will produce the following HTML code:

          <INPUT TYPE=TEXT SIZE=40 VALUE="larry">
          <INPUT TYPE=TEXT SIZE=40
                 VALUE="this ist my &quot;password&quot;">

          <INPUT TYPE=CHECKBOX NAME="check" VALUE="42"
                 CHECKED>
          <INPUT TYPE=CHECKBOX NAME="check" VALUE="43">

COMMAND <?INTERFACE>
====================

Type
     Interface

Syntax
          <?INTERFACE [ INPUT=list_of_variables ]
                      [ OPTIONAL=list_of_variables ] >

Description
     This command declares the interface of a CGI program. You can declare
     mandatory and optional parameters. Parameters are always identified
     by their name. You can recieve scalar and array parameters.

     All input parameters declared this way are visible as the appropriate
     variables inside the CGI program. They are always declared with my to
     prevent name clashes with other parts of the program.

     Using <?INTERFACE> is optional, if you are not in 'use strict' mode.
     If you ommit <?INTERFACE> all actual parameters are passed to your
     program, no parameter checking is done in this case. But it is
     strongly recommended to use <?INTERFACE> because CIPP checks the
     consistency of your CGI calls at runtime.

     If you are in 'use strict' mode (which is the default), using
     <?INTERFACE> is mandatory, because one cannot create lexical
     variables at runtime. They must be declared in this manner, so CIPP
     can add the appropriate decalaration statements to the generated
     source code.

Parameter
     All parameters of <?INTERFACE> expect a comma separated list of
     variables. Scalars ($) and arrays (@) are supported. Whitespaces are
     ignored.

     Note: It is recommended that you use lower case variable names for
     your CGI interfaces, because some CIPP commands for generating URLs
     (e.g. <?GETURL>) convert parameter names to lower case.

*     INPUT*
     This parameters takes the list of variables the caller must pass to
     the CGI program.

*     OPTIONAL*
     The variables listed here are optional input parameters. They are
     always declared with  my and visible inside the program, but are set
     to undef, if the caller ommits them.

Notes
     The <?INTERFACE> command may occur several times inside a CGI
     program, the position inside the source code does not matter. All
     declarations will be added to an interface accordingly.

Example
     We specify an interface for two scalars and an array.

          <?INTERFACE INPUT="$firstname, $lastname"
                      OPTIONAL="@id">

     A HTML form which adresses this CGI program may look like this
     (assuming we are in a CGI::CIPP or Apache::CIPP environment).

          <?VAR MY NAME="@id" NOQUOTE>(1,2,3,4)<?/VAR>

          <?FORM ACTION="/user/save.cgi">
            <?HIDDENFIELDS PARAMS="@id">
            <P>firstname:
            <?INPUT TYPE=TEXT NAME=firstname>
            <P>lastname:
            <?INPUT TYPE=TEXT NAME=lastname>
          <?/FORM>

COMMAND <?LOG>
==============

Type
     Exception Handling

Syntax
          <?LOG MSG=error_message
                [ TYPE=type_of_message ]
                [ FILENAME=special_logfile ]
                [ THROW=exception ] >

Description
     The <?LOG> command adds a line to the project specific logfile, if no
     other filename is specified. In new.spirit environments the default
     filename of the logfile is prod/log/cipp.log. In CGI::CIPP and
     Apache::CIPP environments messages are written to /tmp/cipp.log
     (c:\tmp\cipp.log under Win32) by default.

     Log file entries contain a timestamp, client IP adress, a message
     type and the message itself.

Parameter
*     MSG*
     This is the message.

*     TYPE*
     You can use the TYPE parameter to speficy a special type for this
     message. This is simply a string. You can use this feature to ease
     logfile analysis.

*     FILENAME*
     If you want to add this message to a special logfile you pass the
     full path of this file with FILENAME.

*     THROW*
     With this parameter you can provide a user defined exception to be
     thrown on failure. The default exception thrown by this statement is
     log.

     An exception will be thrown, if the log file is not writable or the
     path is not reachable.

Example
     If the variable $error is set a simple entry will be added to the
     default logfile.

          <?IF COND="$error != 0">
            <?LOG MSG="internal error: $error">
          <?/IF>

     The error message "error in SQL statement" is added to the special
     logfile with the path /tmp/my.log. This entry is marked with the
     special type dberror. If this file is not writable an exception
     called fileio is thrown.

          <?LOG MSG="error in SQL statement"
                TYPE="dberror"
                FILE="/tmp/my.log"
                THROW="fileio">

COMMAND <?MODULE>
=================

Type
     Import

Syntax
          <?MODULE NAME=cipp_perl_module >
            ...
          <?/MODULE>

Description
     With this command you define a CIPP Perl Module. This works currently
     in a new.spirit environment only.

     The generated Perl code will be installed in the project specific
     lib/ folder and can be imported with the <?REQUIRE> command. Don't
     <?USE> for CIPP Perl modules, because <?REQUIRE> does some database
     initialization.

Parameter
*     NAME*
     This is the name of the module you want to use. Nested module names
     are delimited by ::.

     It is not possible to use a variable or expression for NAME, you must
     always use a literal string here.

Example
          <?MODULE NAME="Test::Module">

          <?SUB NAME="new">
            <?PERL>
              my $class = shift;
              return bless {
                 foo => 1,
              }, $class;
            <?/PERL>
          <?/SUB>

          <?SUB NAME="print_foo">
            <?PERL>
              my $self = shift;
              print $self->{foo}, ,<p>\n";
            <?/PERL>
          <?/SUB>

          <?/MODULE>

COMMAND <?MY>
=============

Type
     Variables and Scoping

Syntax
          <?MY [ VAR=list_of_variables ]
               variable_1 ... variable_N >

Description
     This command declares private variables, using the Perl command my
     internally. Their scope reaches to the end of the block which
     surrounds the <?MY> command, for example only inside a <?IF> block.

     All types of Perl variables (Scalars, Arrays and Hashes) can be
     declared this way.

     If you want to initialize the variables with a value you must use the
     <?VAR> command or Perl commands directly. <?MY> only declares
     variables. Their initial value is undef.

Parameter
*     VAR*
     This parameter takes a comma separated list of variable names, that
     should be declared. With this option it is possible to declare
     variables which are not in lower case.

*     variable_1..variable_N*
     You can place additionel variables everywhere inside the <?MY>
     command. This variables are always declared in lower case notation.

Note:
     If you need a new variable for another CIPP command, you can most
     often use the MY switch of that command, which declares the variable
     for you. This saves you one additional CIPP command and makes your
     code more readable.

Example
     See <?BLOCK>

COMMAND <?OPTION>
=================

Type
     HTML Tag Replacement

Syntax
          <?OPTION [ VALUE=parameter_value ]
                   [ additional_<OPTION>_parameters ... ] >
          ...
          <?/OPTION>

Description
     This command generates a HTML <OPTION> tag, where the text inside the
     <OPTION> block is HTML escaped and the VALUE is quoted. The usage of
     the <?OPTION> command outside of a <?SELECT> block is forbidden. If
     the surrounding <?SELECT> command has its STICKY option set, the
     select state of the options are preserved (see <?SELECT> for more
     information about the STICKY feature).

Parameter
*     VALUE*
     This is the VALUE of the generated <OPTION> tag. Its content will be
     escaped.

*     additional_OPTION_parameters*
     All additional parameters are taken over without changes into the
     produced <OPTION> tag.

Example
     See the description of the <?SELECT> command for a complete example.

     .

COMMAND <?PERL>
===============

Type
     Control Structure

Syntax
          <?PERL [ COND=condition ] >
          ...
          <?/PERL>

Description
     With this command you open a block with pure Perl commands. You may
     place any valid Perl code inside this block.

     You may use the Perl print statement to produce HTML code (or
     whatever output you want) for the client.

     At the moment, there are only two CIPP commands which are actually
     supported inside a <?PERL> block: <?INCLUDE> and <?SQL>. Support of
     more commands will be added in the future.

Parameter
*     COND*
     If you set the COND parameter, the Perl block is only executed, if
     the given condition is true.

Example
     All occurences of the string 'nt' in the scalar variable $str will be
     replaced by 'no thanks'. The result will be printed to the client.

          <?PERL>
            $text =~ s/nt/no thanks/g;
            print $text;
          <?/PERL>

     If this list contains some elements a string based on the list is
     generated.

          <?PERL COND="scalar(@list) != 0">
            my ($string, $element);
            foreach $element ( @list ) {
              $string .= $element;
            }
            print $string;
          <?/PERL>
          # OK, its easier to use 'join', but it's
          # only an example... :-)

     .

COMMAND <?!PROFILE>
===================

Type
     Preprocessor Command

Syntax
          <?!PROFILE { ON | OFF }
                     [ DEEP ] >

Description
     This preprocessor command controls the generation of profiling code.
     This feature is currently experimental, the syntax of the <?!PROFILE>
     command may change in future.

     If you switch profiling on, CIPP will generate profile code for the
     rest of the file, respectively until a <?!PROFILE OFF> command
     occurs. Switching profiling at runtime is not possible, because the
     <?!PROFILE> command takes effect on the preprocessor.

     Currently two tasks are profiled: SQL statements and Include
     executions. If profiling is switched on, you'll get a line on STDERR
     for every executed SQL and Include command, which contains the
     corresponding execution time. You need the Perl module Time::HiRes
     installed on your system if you want to use profiling.

Parameter
     ON | OFF

     Switch profiling either on or off.

*     DEEP*
     If you set the DEEP option, the content all processed Includes will
     be profiled, too. Otherwise only the document itself, where the
     <?!PROFILE> command stands, will be profiled.

     Note that the DEEP switch can produce lots of output.

Example
     The following SQL Statement and Include will be profiled.

          <?!PROFILE ON>
          <?SQL SQL="select foo, bla
                     from   bar
                     where  baz=?"
                PARAMS="$baz"
                MY VAR="$foo, $bla">
            $foo $bla<br>
          <?/SQL>

          <?INCLUDE NAME="/foo/bar.inc">

          <?!/PROFILE OFF>

          # no profiling here
          <?INCLUDE NAME="/bar/foo.inc">

     Something like this will appear on STDERR and thus in your webserver
     error log:

     PROFILE 42421 START

     PROFILE 42421 SQL        select foo, baz   0.0178

     PROFILE 42421 INCLUDE    /foo/bar.inc      0.0020

     PROFILE 42421 STOP

     The 42421 is the PID of the serving process, so you can differ
     between outputs of several processes. You see the head of each SQL
     statement and the name of an Include, followed by the execution time
     in seconds.

     You can use the PROFILE option of the <?SQL> command to replace the
     output of the SQL statement with a user defined label. See <?SQL> for
     details.

COMMAND <?REQUIRE>
==================

Type
     Import

Syntax
          <?REQUIRE NAME="cipp_perl_module" >

Description
     This command imports a module which was created with new.spirit in
     conjunction with the <?MODULE> command. You can't import other Perl
     modules, because <?REQUIRE> executes CIPP specific initialization
     code to establish database connections, if they're needed by the
     module.

     <?REQUIRE> uses internally the Perl command 'require' to import the
     module. So CIPP Perl Modules are unable to export symbols to the
     callers namespace. You have to fully quallify function names, or
     write OO style modules.

Parameter
*     NAME*
     This is the name of the module you want to use. Nested module names
     are delimited by ::.  This is the name of the module you provided
     with the <?MODULE> command.

     You may also place a scalar variable here, which contains the name of
     the module. So it is possible to load modules dynamically at runtime.

Example
          # refer to the description of <?MODULE> to see
          # the implementation of the Test::Module module.
          <?REQUIRE NAME="Test::Module">

          <?PERL>
            my $t = new Test::Module;
            $t->print_foo;
          <?/PERL>

COMMAND <?ROLLBACK>
===================

Type
     SQL

Syntax
          <?ROLLBACK [ DB=database_name ]
                     [ DBH=database_handle ]
                     [ THROW=exception ] >

Description
     The <?ROLLBACK> command concludes the actual transaction and cancels
     all changes to the database.

     Using <?ROLLBACK> in <?AUTOCOMMIT ON> mode is not possible.

     If you are not in <?AUTOCOMMIT ON> mode a transaction begins with the
     first SQL statement and ends either with a <?COMMIT> or <?ROLLBACK>
     command.

Parameter
*     DB*
     This is the CIPP internal name of the database for this command. In
     CGI::CIPP or Apache::CIPP environment this name has to be defined in
     the appropriate global configuration. In a new.spirit environment
     this is the name of the database configuration object in
     dot-separated notation.

     If DB is ommited the project default database is used.

*     DBH*
     Use this option to pass an existing DBI database handle, which should
     used for this SQL command.  You can't use the DBH option in
     conjunction with DB.

*     THROW*
     With this parameter you can provide a user defined exception which
     should be thrown on failure. The default exception thrown by this
     statement is rollback.

     If the underlying database is not capable of transactions (e.g.
     MySQL) execution of this command will throw an exception.

Example
     We insert a row into a database table and rollback the change
     immediately. We throw a user defined exeption, if the rollback fails,
     maybe the database is not capable of transactions.

          <?SQL SQL="insert into foo (num, str)
                     values (42, 'bar');">
          <?/SQL>
          <?ROLLBACK THROW="ROLLBACK_Exception">

COMMAND <?SAVEFILE>
===================

Type
     Interface

Syntax
          <?SAVEFILE FILENAME=server_side_filename
                     VAR=upload_formular_variable
                     [ SYMBOLIC ]
                     [ THROW=exception ] >

Description
     This command saves a file which was uploaded by a client in the
     webservers filesystem.

Parameter
*     FILENAME*
     This is the fully qualified filename where the file will be stored.

*     VAR*
     This is the identifier you used in the HTML form for the filename on
     client side, the value of the <INPUT NAME> parameter) .

*     SYMBOLIC*
     If this switch is set, VAR is the name of the variable which contains
     the <INPUT TYPE=FILE> identifier. Use this if you want to determine
     the name of the field at runtime.

*     THROW*
     With this parameter you can provide a user defined exception which
     should be thrown on failure. The default exception thrown by this
     statement is savefile.

Note
     The client side file upload will only function proper if you set the
     encoding type of the HTML form to ENCTYPE="multipart/form-data".
     Otherwise you will get a exception, that the file could not be
     fetched.

     There is another quirk you should notice. The variable which
     corresponds to the <INPUT NAME> option in the file upload form is a
     GLOB reference (due to the internal implementation of the CGI module,
     which CIPP uses). That means, if you use that variable in string
     context you get the client side filename of the uploaded file. But
     also you can use the variable as a filehandle, to read data from the
     file (this is what <?SAVEFILE> does for you).

     This GLOB thing is usually no problem, as long as you don't pass the
     variable as a binding parameter to a <?SQL> command (because you want
     to store the client side filename in the database). The DBI module
     (which CIPP uses for the database stuff) complains about passing
     GLOBS as binding parameters.

     The solution is to create a new variable assigned from the value of
     the file upload variable enforced to be in string context using
     double quotes.

     <?INTERFACE INPUT="$upfilename">

     <?MY $client_filename>

     <?PERL> $client_filename = "$upfilename" <?/PERL>

Example
     First we provide a HTML form with the file upload field.

          <?FORM METHOD="POST" ACTION="/image/save.cgi"
                 ENCTYPE="multipart/form-data">
          Fileupload:

          <INPUT TYPE=FILE NAME="upfilename" SIZE=45><BR>
          <INPUT TYPE="reset">
          <INPUT TYPE="submit" NAME="submit" VALUE="Upload">
          </FORM>

     The /image/save.cgi program has the following code to store the file
     in the filesystem.

          <?SAVEFILE FILENAME="/tmp/upload.tmp"
                     VAR="upfilename"
                     THROW=my_upload>

     The same procedure using the RUNTIME parameter.

          <?VAR MY=$field_name>upfilename<?/VAR>
          <?SAVEFILE FILENAME="/tmp/upload.tmp"
                     SYMBOLIC
                     VAR="$field_name"
                     THROW=upload>

COMMAND <?SELECT>
=================

Type
     HTML Tag Replacement

Syntax
          <?SELECT [ NAME=parameter_name ]
                   [ MULTIPLE ] [ STICKY ]
                   [ additional_<SELECT>_parameters ... ] >
          ...
          <?/SELECT>

Description
     This command generates a selection widget providing preservation of
     the selection state (similar to the STICKY feature of the <?INPUT>
     command).

Parameter
*     NAME*
     The name of the formular widget.

*     MULTIPLE*
     If this is set, a multi selection list will be generated, instead of
     a single selection popup widget.

*     STICKY*
     If the STICKY option is set, the <?OPTION> commands inside the
     <?SELECT> block preserve their state in generating automatically a
     SELECTED option, if the corresponding entry was selected before. This
     is done in checking the value of the corresponding Perl variable
     (which is $parameter_name for a popup and @parameter_name for
     MULTIPLE selection list). If you assign a value to the STICKY option,
     this will be taken as the Perl variable for checking the state of the
     widget. But the default behaviour of deriving the name from the NAME
     option will fit most cases.

*     additional_SELECT_parameters*
     All additional parameters are taken over without changes into the
     produced <SELECT> tag.

Note
     If you use the STICKY feature in conjuncion with a MULTIPLE selection
     list widget, please note that the internal implementation may be
     ineffective, if you handle large lists. This is due the internal
     representation of the list values as an array, so a grep is neccesary
     to check, wheter a list entry is selected or not. If you feel
     uncomfortable about that, use classic HTML <SELECT> and <OPTION>
     tags, maybe with a loop around it, and check state of the checkboxes
     using a hash.

Example
     This is a complete CIPP program, which provides a mulitple selection
     list and preservers its state over subsequent executions of the
     program.

          <?INCINTERFACE OPTIONAL="@list">

          <?FORM ACTION="sticky.cgi">

          <?SELECT NAME="list" MULTIPLE STICKY>
          <?OPTION VALUE="1">value 1<?/OPTION>
          <?OPTION VALUE="2">value 2<?/OPTION>
          <?OPTION VALUE="3">value 3<?/OPTION>
          <?/SELECT>

          <?INPUT TYPE="submit" VALUE="send">

          <?/FORM>

COMMAND <?SQL>
==============

Type
     SQL

Syntax
          <?SQL SQL=sql_statement
                [ VAR=list_of_variables_for_the_result ]
                [ PARAMS=input_parameter ]
                [ WINSTART=start_row ]
                [ WINSIZE=number_of_rows_to_fetch ]
                [ RESULT=sql_return_code ]
                [ DB=database_name ]
                [ DBH=database_handle ]
                [ THROW=exception ] >
                [ MY ]
                [ PROFILE=profile_label ]
          ...
          <?/SQL>

Description
     Use the <?SQL> command to execute arbitrary SQL statements in a
     specific database. You can fetch results from a SELECT query, or
     simply execute INSERT, UPDATE or other SQL statements.

     When you execute a SELECT query (resp. set the VAR parameter, see
     below) the code inside the <?SQL> block will be repeated for every
     row returned from the database.

Parameter
*     SQL*
     This takes the SQL statement to be executed. A trailing semicolon
     will be stripped off.

     The statement may contain ? placeholders. They will be replaced by
     the expressions listed in the PARAMS parameter. See the PARAMS
     section for details about placeholders.

     This is an example of a simple insert without placeholders.

          <?SQL SQL="insert into foo values (42, 'bar')">
          <?/SQL>

*     VAR*
     If you set the VAR parameter, CIPP asumes that you execute a SQL
     statement which returns a result set (normally a SELECT statement).

     The VAR parameter takes a list of scalar variables. Each variable
     corresponds to the according column of the result set,  so the
     position of the variables inside the list is relevant.

     You can use this variable inside the <?SQL> block to access the
     actual processed row of the result set. Below the <?SQL> block the
     variable contains the values of the last row fetched, even when they
     are implicitely declared via a MY switch.

     This is an example of creating a simple HTML table out of an SQL
     result set.

          <TABLE>
            <?SQL SQL="select num, str from foo"
                  MY VAR="$n, $s">
              <TR>
                <TD>$n</TD>
                <TD>$s</TD>
              </TR>
            <?/SQL>
          </TABLE>

*     PARAMS*
     All placeholders inside your SQL statement will be replaced with the
     values given in PARAMS. It expects a comma separated list (white
     spaces are ignored) of Perl expressions, normally variables (scalar
     or array), literals or constants. The Perl value undef will be
     translated to the SQL value NULL.  The content of the first
     expression substitutes the first placeholder in the SQL string, etc.

     Values of parameters are quoted, if necessary, before substitution.
     This is the main advantage of PARAMS in this context. (You could
     place the perl variables into the SQL statement as such, but you
     would have to use <?DBQUOTE> on them first. Or else.).

     Beware that you cannot use placeholders to contain (parts of) SQL
     code. The SQL must contain the syntactically complete statement -
     placeholders can only contain values. (The main reason for this is
     that the SQL statement is parsed by most databases before the
     placeholders are substituted. See the DBI manpage for details about
     placeholders.)

     Here are some examples which demonstate the usage of placeholders.

          <?VAR MY NAME=$n>42<?/VAR>
          <?VAR MY NAME=$s>Hello 'World'<?/VAR>
          <?SQL SQL="insert into foo values (?, ?, ?)"
                PARAMS="$n, $s, time()">
          <?/SQL>

          <?VAR MY NAME=$where_num>42<?/VAR>
          <?SQL SQL="select num,str from foo
                     where num = ?"
                PARAMS="$where_num">
                MY VAR="$column_n, $column_s">
            n=$column_n s='$column_s'<BR>
          <?/SQL>

          <?SQL SQL="update foo
                     set str=?
                     where n=?"
                PARAMS="$s, $where_num">
          <?/SQL>

*     WINSTART*
     If you want to process only a part of the result set you can specfiy
     the first row you want to see with the WINSTART parameter. All rows
     before the given WINSTART row will be fetched but ignored. Execution
     of the <?SQL> block begins with the WINSTART row.

     The row count begins with 1.

     Here is an example. The first 5 rows will be skipped.

          <?SQL SQL="select num, str from foo"
                MY VAR="$n, $s"
                WINSTART=6
            n=$n s='$s'<BR>
          <?/SQL>

*     WINSIZE*
     Set this parameter to specify the number of rows you want to process.
     You can combine this parameter with WINSTART to process a "window" of
     the result set.

     This is an example of doing this (skipping 5 rows, processing 5 rows).

          <?SQL SQL="select num, str from foo"
                MY VAR="$n, $s"
                WINSTART=6 WINSIZE=5
            n=$n s='$s'<BR>
          <?/SQL>

*     RESULT*
     Some SQL statements return a scalar result value, e.g. the number of
     rows processed (e.b. UPDATE and DELETE). The variable placed here
     will take the SQL result code, if there is one.

     Example:

          <?SQL SQL="delete from foo where num=42"
                MY RESULT=$deleted>
          <?/SQL>
          Successfully deleted $deleted rows!

*     DB*
     This is the CIPP internal name of the database for this command. In
     CGI::CIPP or Apache::CIPP environment this name has to be defined in
     the appropriate global configuration. In a new.spirit environment
     this is the name of the database configuration object in
     dot-separated notation.

     If DB is ommited the project default database is used.

*     DBH*
     Use this option to pass an existing DBI database handle, which should
     used for this SQL command.  You can't use the DBH option in
     conjunction with DB.

*     THROW*
     With this parameter you can provide a user defined exception which
     should be thrown on failure. The default exception thrown by this
     statement is sql.

*     MY*
     If you set the MY switch all created variables will be declared using
     'my'. Their scope reaches to the end of the block which surrounds the
     <?SQL> command.

*     PROFILE*
     Here you can define a profile label for this SQL statement. If you
     use the <?!PROFILE> command this label is printed out instead of the
     head of the SQL statement. See the chapter of <?!PROFILE> about
     details.

     Breaking the <?SQL> loop

     If you want to break the SQL loop of a select statement, simply use
     this Perl Code:

          <?PERL>
            last SQL;
          <?/PERL>

Example
     Please refer to the examples in the parameter sections above.

COMMAND <?SUB>
==============

Type
     Control Structure

Syntax
          <?SUB NAME=subroutine_name >
          ...
          <?/SUB>

Description
     This defines the <?SUB> block as a Perl subroutine. You may use any
     CIPP commands inside the block.

     Generally Includes are the best way to create reusable modules with
     CIPP. But sometimes you need real Perl subroutines, e.g. if you want
     to do some OO programming.

Parameter
*     NAME*
     This is the name of the subroutine. Please refer to the perlsub
     manpage for details about Perl subroutines.

     It is not possible to declare protoyped subroutines with <?SUB>.

Example
     This is a subroutine to create a text input field in a specific
     layout.

          <?SUB NAME=print_input_field>
            # Catch the input parameters
            <?MY $label $name $value>
            <?PERL>
              ($label, $name, $value) = @_;
            <?/PERL>

          # print the text field
          <P>
          <B>$label:</B><BR>
          <?INPUT TYPE=TEXT SIZE=40 NAME=$name VALUE=$value>
            <?/SUB>
          You may call this subroutine from every Perl context this way.

          <?PERL>
            print_input_field ('Firstname', 'firstname',
                               'Larry');
            print_input_field ('Lastname', 'surname',
                               'Wall');
          <?/PERL>

COMMAND <?TEXTAREA>
===================

Type
     HTML Tag Replacement

Syntax
          <?TEXTAREA [ additional_<TEXTAREA>_parameters ... ]>
          ...
          <?/TEXTAREA>

Description
     This generates a HTML <TEXTAREA> tag, with a HTML quoted content to
     prevent from HTML syntax clashes.

Parameter
*     additional_TEXTAREA_parameters*
     There are no special parameters. All parameters you pass to
     <?TEXTAREA> are taken in without changes.

Example
     This creates a <TEXTAREA> initialized with the content of the
     variable $fulltext.

          <?VAR MY NAME=$fulltext><B>HTML Text</B><?/VAR>
          <?TEXTAREA NAME=fulltext ROWS=10
          COLS=80>$fulltext<?/TEXTAREA>

     This leads to the following HTML code.

          <TEXTAREA NAME=fulltext ROWS=10
          COLS=80>&lt;B>HTML Text&lt;B></TEXTAREA>

COMMAND <?THROW>
================

Type
     Exception Handling

Syntax
          <?THROW THROW=exception [ MSG=message ] >

Description
     This command throws an user specified exception.

Parameter
*     THROW*
     This is the exception identifier, a simple string. It is the criteria
     for the <?CATCH> command.

*     MSG*
     Optionally, you can pass a additional message for your exception,
     e.g. a  error message you have got from a system call.

Example
     We try to open a file and throw a exception if this fails.

          <?MY $error>
          <?PERL>
            open (INPUT, '/bar/foo') or $error=$!;
          <?/PERL>

          <?IF COND="$error">
            <?THROW THROW="open_file"
                    MSG="file /bar/foo, $error">
          <?/IF>

Note
     If you want to throw a exception inside a Perl block you can do this
     with the Perl die function. The die argument must follow this
     convention:

          identifier TAB message

     This is the above example using this technique.

     <?PERL>

          open (INPUT, '/bar/foo')

          or die "open_file\tfile /bar/foo, $!";

     <?/PERL>

COMMAND <?TRY>
==============

Type
     Exception Handling

Syntax
          <?TRY >
          ...
          <?/TRY >

Description
     Normally your program exits with a general exception message if an
     error/exception occurs or is thrown explicitely. The general
     exception handler which is responsible for this behaviour is part of
     any program code which CIPP generates.

     You can provide your own exception handling using the <?TRY> and
     <?CATCH> commands.

     All exceptions thrown inside a <?TRY> block are caught. You can use a
     subsequent <?CATCH> block to process the exceptions to set up your
     own exception handling.

     If you ommit the <?CATCH> block, nothing will happen. You never see
     something of the exception, it will be fully ignored and the program
     works on.

Example
     We try to insert a row into a database table and write a log file
     entry with the error message, if the INSERT fails.

          <?TRY>
            <?SQL SQL="insert into foo values (42, 'bar')">
            <?/SQL>
          <?/TRY>

          <?CATCH THROW="insert" MY MSGVAR="$msg">
            <?LOG MSG="unable to insert row, $msg"
                  TYPE="database">
          <?/CATCH>

COMMAND <?URLENCODE>
====================

Type
     URL and Form Handling

Syntax
          <?URLENCODE VAR=unencoded_variable
                      [ MY ] ENCVAR=encoded_variable >

Description
     Use this command to URL encode the content of a scalar variable.
     Parameters passed via URL always have to be encoded this way,
     otherwise you risk syntax clashes.

Parameter
*     VAR*
     This is the variable you want to be encoded.

*     ENCVAR*
     The encoded result will be stored in this variable.

*     MY*
     If you set the MY switch the created variable will be declared using
     'my'. Its scope reaches to the end of the block which surrounds the
     <?URLENCODE> command.

Example
     In this example we link an external CGI script and pass the content
     of the variable $query after using <?URLENCODE> on it.

          <?URLENCODE VAR=$query MY ENCVAR=$enc_query>
          <A HREF="www.search.org?query=$enc_query">
          find something

          </A>

     Hint: in CGI::CIPP and Apache::CIPP environments you also can use the
     <?A> command for doing this.

COMMAND <?USE>
==============

Type
     Import

Syntax
          <?USE NAME=perl_module >

Description
     With this command you can access the extensive Perl module library.
     You can access any Perl module which is installed on your system.

     In a new.spirit environment you can place user defined modules in the
     prod/lib directory of your project, which is included in the library
     search path by default.

     If you want to use a CIPP Module (generated with new.spirit and the
     <?MODULE> command), use <?REQUIRE> instead.

Parameter
*     NAME*
     This is the name of the module you want to use. Nested module names
     are delimited by ::. This is exactly what the Perl use pragma expects
     (you guessed right, CIPP simply translates <?USE> to use :-).

     It is not possible to use a variable or expression for NAME, you must
     always use a literal string here.

Example
     The standard modules File::Path and Text::Wrap are imported to your
     program.

          <?USE NAME="File::Path">
          <?USE NAME="Text::Wrap">

COMMAND <?VAR>
==============

Type
     Variables and Scoping

Syntax
          <?VAR NAME=variable
                [ MY ]
                [ DEFAULT=value ]
                [ NOQUOTE ]>
          ...
          <?/VAR>

Description
     This command defines and optionally declares a Perl variable of any
     type (scalar, array and hash). The value of the variable is derived
     from the content of the <?VAR> block. You can assign constants,
     string expressions and any Perl expressions this way.

     It is not possible to nest the <?VAR> command or to use any CIPP
     command inside the <?VAR> block. The content of the <?VAR> block will
     be evaluated and assigned to the variable.

Parameter
*     NAME*
     This is the name of the variable. You must specify the full Perl
     variable here, including the $, @ or % sign to indicate the type of
     the variable.

     These are some examples for creating variables using <?VAR>.

          <?VAR NAME=$skalar>a string<?/VAR>
          <?VAR NAME=@liste>(1,2,3,4)<?/VAR>
          <?VAR NAME=%hash>( 1 => 'a', 2 => 'b' )<?/VAR>

*     DEFAULT*
     If you set the DEFAULT parameter, this value will be assigned to the
     variable, if the variable is actually undef. In this case the content
     of the <?VAR> block will be ignored.

     Setting the DEFAULT parameter is only supported for scalar variables.

     You can use this feature to provide default values for input
     parameters this way.

          <?VAR NAME=$event DEFAULT="show">$event<?/VAR>

     Hint: you may think there must be a easier way of doing this. You are
     right. :-) We recommend you using this alternative code, the usage of
     DEFAULT is deprecated.

          <?PERL>
            $event ||= 'show';
          <?/PERL>

*     NOQUOTE*
     By default the variable is defined by assigning the given value using
     double quotes. This means it is possible to assign either string
     constants or string expressions to the variable without using extra
     quotes.

     If you do not want the content of <?VAR> block to be evaluated in
     string context set the NOQUOTE switch. E.g., so it is possible to
     assign an integer expression to the variable.

     This is an example of using NOQUOTE for an non string expression.

          <?VAR MY NAME=$element_cnt NOQUOTE>
            scalar(@liste)
          <?/VAR>

*     MY*
     If you set the MY switch the created variable will be declared using
     'my'. Its scope reaches to the end of the block which surrounds the
     <?VAR> command.

Example
     Please refer to the examples in the parameter sections above.

COMMAND <?WHILE>
================

Type
     Control Structure

Syntax
          <?WHILE COND=condition >
          ...
          <?/WHILE>

Description
     This realizes a loop, where the condition is checked first before
     entering the loop code.

Parameter
*     COND*
     As long as this Perl condition is true, the <?WHILE> block will be
     repeated.

Example
     This creates a HTML table out of an array using <?WHILE> to iterate
     over the two arrays @firstname and @lastname, assuming that they are
     of identical size.

          <TABLE>
          <?VAR MY NAME=$i>0<?/VAR>
          <?WHILE COND="$i++ < scalar(@lastname)">
            <TR>
              <TD>$lastname[$i]</TD>
              <TD>$firstname[$i]</TD>
            </TR>
          <?/WHILE>
          </TABLE>

AUTHOR
======

   Joern Reder <joern@dimedis.de>

COPYRIGHT
=========

   Copyright (C) 1999 by Jörn Reder and dimedis GmbH, All Rights Reserved.
This documentation is free; you can redistribute it and/or modify it under
the same terms as Perl itself.

Perl Object Oriented extension for ISAM files
*********************************************

NAME
====

   CIsam - Perl Object Oriented extension for ISAM files

SYNOPSIS
========

   use CIsam;

DESCRIPTION
===========

   CIsam.pm is a thin wrapper to the C-ISAM functions calls.

Exported constants
==================

     AUDGETNAME
     AUDHEADSIZE
     AUDINFO
     AUDSETNAME
     AUDSTART
     AUDSTOP
     CHARTYPE
     DECIMALTYPE
     DOUBLETYPE
     FLOATTYPE
     INTTYPE
     LONGTYPE
     MINTTYPE
     MLONGTYPE
     STRINGTYPE
     ISAUTOLOCK
     ISCLOSED
     ISCURR
     ISD1
     ISD2
     ISDD
     ISDESC
     ISDUPS
     ISEQUAL
     ISEXCLLOCK
     ISFIRST
     ISFIXLEN
     ISGREAT
     ISGTEQ
     ISINOUT
     ISINPUT
     ISLAST
     ISLCKW
     ISLOCK
     ISMANULOCK
     ISMASKED
     ISNEXT
     ISNOCARE
     ISNODUPS
     ISNOLOG
     ISOUTPUT
     ISPREV
     ISRDONLY
     ISSYNCWR
     ISTRANS
     ISVARCMP
     ISVARLEN
     ISWAIT

AUTHOR
======

   Ilya Verlinsky, ilya@wsi.net

METHODS
=======

$obj->new()
     Parameters:

          This is the object constructor. If IsamObjects::BUILD is passed to it, it
          will create the nessasary Isam files for that object to be stored in.
          If no options are passed it will try to open the Isam files for reading and
          writing in its default mode ISINOUT + ISMANULOCK. If user desires some other
          mode than default he must pass the opening mode to the constructor.

     Example:

          my $ps = new Person(IsamObjects::BUILD) - this will build the Isam files

          my $ps = new Person; - this will open the db in the default mode

          my $ps = new Person(&ISINOUT + &ISMANULOCK) - This will open the db in custom
                                                        mode

$obj->path("indexname")
     Parameters:

          indexname as contained in the database layout module of
          the index to be used when accessing the file (set). Only one path
          may be active at a time.  The paths must be valid paths which are
          specified in the layout as indexed fields.

     Example:

     	$obj->path("foo");

$obj->get(ISMODE)
     Parameters:

     	Informix access mode should be passed. This will tell the DB 	the way
     to access the records. Examples of modes are ISFIRST, 	ISLAST,
     ISGTEQ, ISEQUAL, ISGREAT, ISNEXT.  	For all modes except
     ISFIRST, ISLAST, and ISNEXT the database 	engine will also
     perform the search function. The function will 	return a full record
     from the db with it will stuff in the 	appropriate hash
     positions.

     Example:

     	$obj->get(&ISGTEQ);

$obj->add();
     Parameters:

     	No parameters needs to be passed to this function. It will add a
     non-existant record to the database.  	WARNING: If the record
     witht he same unique number is already in the 	db unpredictable
     situation can occur. For such a case use update() 	function.

     Example:

          $obj->add();

$obj->update
     Parameters:

     	No parameters. It will update the existing record in the db.
     WARNING: Do not use to add new records. Unpredictable errors can
     occur.

     Example:

          $obj->update();

$obj->clear();
     Parameters:

     	None. This function will clear the record and set all the values 	to
     their defaults - 0 for numeric and ' ' for the character.

     Example:

     	$obj->clear();

     The CIsam module allowes for the user of IsamObjects to access even
     the lowes CIsam functions throught the Isam Object

     $obj->{ISAM_OBJ}

     CIsam.pm module include class methods indicated by CIsam->method and
     object methods indicated by $fd->method where $fd is a reference to
     an instance obtained by isopen, isbuild or iscluster eg. my $fd =
     CIsam->isopen("myfile",&ISINOUT);

CIsam->iserrno([INTVALUE])
     Returns the value of the global CIsam variable iserrno unless
     `INTVALUE' is specified, in which case, sets the value of iserrno.

CIsam->isrecnum([LONGVALUE])
     Returns the value of the global CIsam variable isrecnum unless
     `LONGVALUE' is specified, in which case, sets the value of isrecnum.

CIsam->isreclen([INTVALUE])
     Returns the value of the global CIsam variable isreclen unless
     `INTVALUE' is specified, in which case, sets the value of isreclen.

CIsam->iserrio([INTVALUE])
     Returns the value of the global CIsam variable iserrio unless
     `INTVALUE' is specified, in which case, sets the value of iserrio.

$fd->fd
     Returns CIsam file descriptor

$fd->name   Returns the filename
$fd->isaddindex(KEYDESC)
     Returns TRUE if successfully adds an index to $fd

CIsam->isbuild(NAME, LEN, KEYDESC, MODE)
     Returns a reference to an CIsam object or undef if unsuccessful

CIsam->iscleanup
     Returns TRUE if successful

$fd->isclose
     Returns TRUE if successful

$fd->iscluster(KEYDESC)
     KEYDESC is a reference to a Keydesc object.  Returns a reference to
     an CIsam object or undef if unsuccessful

CIsam->iscommit
     Returns TRUE if successful

$fd->isdelcurr
     Returns TRUE if successful

$fd->isdelete(DATA)
     DATA is a reference to a scalar. Returns TRUE if successful

$fd->isdelindex(KEYDESC)
     KEYDESC is a reference to a Keydesc object.  Returns TRUE if
     successful

$fd->isdelrec(RECNUM)
     RECNUM is a long integer Returns TRUE if successful

CIsam->iserase(NAME)
     NAME is a filename. Returns TRUE if successful

$fd->isflush
     Returns TRUE if successful

$fd->isindexinfo(IDX)
     IDX is an integer. returns undef if unsuccessful.  If IDX == 0,
     returns a reference to a Dictinfo object.  If IDX > 0, returns a
     reference to a Keydesc object

$fd->islock
     Returns TRUE if successful

CIsam->islogclose
     Returns TRUE if successful

CIsam->islogopen
     Returns TRUE if successful

CIsam->isopen(NAME, MODE)
     NAME is a filename, MODE is an integer Returns undef if unsuccessful,
     otherwise returns a reference to an CIsam object

$fd->isread(DATA, MODE)
     DATA is a reference to a scalar. MODE is an integer.  Returns TRUE if
     successful

CIsam->isrecover
     Returns TRUE if successful

$fd->isrelease
     Returns TRUE if successful

CIsam->isrename(OLDNAME, NEWNAME)
     Returns TRUE if successful

$fd->isrewcurr(DATA)
     DATA is a reference to a scalar. Returns TRUE if successful

$fd->isrewrec(RECNUM, DATA)
     RECNUM is the record number, DATA is a reference to the Data.
     Returns TRUE if successful

$fd->isrewrite(DATA)
     DATA is a reference to the Data. Returns TRUE if successful

CIsam->isrollback
     Returns TRUE if successful

$fd->issetunique(UNIQUEID)
     UNIQUEID is an integer scalar. Returns TRUE if successful

$fd->isstart(KEYDESC, LENGTH, DATA, MODE)
     KEYDESC is a reference to a Keydesc object, LENGTH is 0 or the number
     of bytes of the key, DATA is a reference to a scalar, MODE is an
     integer value.

     Returns TRUE if successful

$fd->isuniqueid
     Returns undef if unsuccessful or an long value

$fd->isunlock
     Returns TRUE if successful

$fd->iswrcurr(DATA)
     DATA is a reference to a scalar. Returns TRUE if successful

$fd->iswrite(DATA)   DATA is a reference to a scalar. Returns TRUE if successful
   perl(1).  IsamObjects.

Class to read 2-column files into a hash
****************************************

NAME
====

   CONFIG::Hash - Class to read 2-column files into a hash

SYNOPSIS
========

     use CONFIG::Hash;

     my $file = CONFIG::Hash->new($filename, \%config);

     $hash_ref = $file->get();

     $value = $file->get($key);

DESCRIPTION
===========

   Parses a two-column formated file into a hash. The module uses the
CONFIG::Plain class so you can use all features of the Plain module.

METHODS
=======

new - parse file (read via CONFIG::Plain) into hash
---------------------------------------------------

   Configuration Options:

     -> all described in CONFIG::Plain are known

     KEYREGEXP

     Scalar holding a regular expression which must match every key.

     DEFAULT: "^(\\S+)"

     HINT: Since the first character of a line has to be a non-white-space
           character it is possible to make multi-line values.
           Have a look at the examples.

     HASHREGEXP

     Scalar holding a regular expression which matches the content.

     DEFAULT: "\\s+(.*)\$"

     SUBSTITUTENEWLINE

     If defined all NewLine characters in the value will be substituted
     with this scalar.

     DEFAULT: "\n"

        REQUIRE

     Reference to a Array which holds list of required variables.

     DEFAULT: []

     DEFAULT

     	Reference to Hash holding default Values.

     DEFAULT: {}

     ALLOWREDEFINE

     Scalar switch to suppress error messages if the same key is
     redefined at a later point in file.

     DEFAULT: 1

     CASEINSENSITIVE

     All keys are convertet into lower case if this option was defined.

     DEFAULT: undef

get - get a reference to the hash or a specified field
------------------------------------------------------

     $hash_ref = $file->get();

     Returns a reference to the hash holding all data from file.

     $value = $file->get($key);

     Returns the value to the specified key.

get_line - get the linenumber where this key was found
------------------------------------------------------

     $line_nr = $file->get_line($key);

        Returns a scalar holding the line number. Call often to get
        include path.

get_file - get the filename where this key was found
----------------------------------------------------

     $filename = $file->get_file($key);

     Returns a scalar holding the filename. Call often to get
     include path.

EXAMPLES
========

     Assumes default configuration

     >KEY	This is a very stupid text
     >	but it shows the functionality \
     >	of this module

     Will get into
     'KEY' => "This is a very stupid text\nbut it shows the functionality of this module"

     With the config setting 'SUBSTITUTENEWLINE' => ' '

     >INSERT	insert into
     >	table dummy
     >		(col1, col2, col3)
     >	values
     >		(1, "value", "value2");

     Will get into
     'INSERT' => 'insert into table dummy (col1, col2, col3) values (1, "value", "value2");'

SEE ALSO
========

   CONFIG::Plain(3pm)

   The CONFIG:: Guide at http://www.fatalmind.com/programs/CONFIG/

COPYRIGHT
=========

     Copyright (C) 1999, 2000 by Markus Winand <mws@fatalmind.com>

     This program is free software; you can redistribute it and/or
     modify it under the same terms as Perl itself.

Base class for cached file reading
**********************************

NAME
====

   CONFIG::Plain - Base class for cached file reading

SYNOPSIS
========

     use CONFIG::Plain;

     my $file = CONFIG::Plain->new($filename, \%config);

     my $file_content = $file->getfile;

     while (defined $line = $file->getline) {
      	printf("%s:%d> %s\n", $file->getline_file,
     			      $file->getline_number,
                                 $line);
     }

     # example for error reporting

     while (defined ($line = $file->getline)) {
           $error = $file->getline_error;
           if (defined $error) {
                   printf("ERROR in         %s:%d\n", $file->getline_file,
                                                      $file->getline_number);

     while ($filename = $file->getline_file) {
             printf("   included from %s:%d\n", $filename,
                                        $file->getline_number);
     }
     do {
             printf("   %s\n", $error);
     } while (defined ($error = $file->getline_error));
             }
       }

ABSTRACT
========

   This perl module is highly useful in connection with mod_perl cgi
scripts. It caches files (re-reads the files if necessary) to speed up the
file reading. It is possible to configure the module to remove comments,
trailing blanks, empty lines or to do other useful things only once.

DESCRIPTION
===========

   The methods of this module are very similar to the IO methods to read a
file.  The two major differences are:

Caching
-------

   If you open/read a file twice (or often) the file will be cached after
the first access. So the second (and third, and forth, ...) access is much
faster.  This feature is very useful in connection with mod_perl CGI
scripts.

Preparsing
----------

   You can configure this class to preparse the input file immediatly
after the disk access (NOTE: the preparsed file will be cached). Some
default preparse algorithms are available (delete empty lines, remove
comments, remove trailing blanks, ...) but it's possible to overload a
method to implement special preparse functionality.

METHODS
=======

   Overview:

     new            - opens, reads and preparses a file
     close          - close the file
             parse_file     - empty method, overload this for specific preparse
                              functionality
             getfile        - returns a scalar holding the preparsed file
     getline        - returns a scalar holding a line of the file
     getline_reset  - resets the cursor for getline
     getline_number - returns the inputfile number of the last line got
     		 via getline
     		 (cursor handled for includes)
     getline_file   - returns the inputfilename of the last line got
                              via getline
     		 (cursor handled for includes)
     getline_error  - returns error messages in for this line
     		 (cursor handled)
     setline_error  - stores a errormessage to the last line got via
     		 getline
     get_errors     - returns a human readable string holding ALL error
     		 messages

new - open, read and preparse file
----------------------------------

   (1) $ref = CONFIG::Plain->new($filename);

   (2) $ref = CONFIG::Plain->new($filename, \%CONFIG);

   (3) $ref = CONFIG::Plain->new(\%CONFIG);

   This method creates a new object from the class.

   You can specify the filename as first argument (see syntax (1) or (2))
or include the filename into the options hash (use "FILE" as key).

   Configuration Options:

     COMMENT - define comment styles

     Known comment styles are:

     	sh	- shell like comments
     		  (from '#' to end of line)
     	C	- C like comments
     		  (from '/*' to '*/', multi line)
     	C++	- C++ like comments
     		  (from '//' to end of line)
     	asm     - assembler like comments
                               (from ';' to end of line)
     	pascal  - pascal like comments
                               (from '{' to '}', multi line)
     	sql     - oracle sql style
                               (from '--' to end of line)
     	regexp  - define comments by regular expression for start
                               and end.
     		  This style accepts two parameters, the syntax is:
     		  "regexp:<startre>|<stopre>"
     		  where <startre> is the regular expression for the
                               start of the comment, and <stopre> the regexp for
                               the end.

     EXAMPLE:
     "regexp:#|\$"
     comments goes from "#" to new line (same as
                               "sh" style).

     	DEFAULT: "sh C C++"

     DATA - use given data instaed of read it from a file

     Use the data given in this argument instaed of read it from disk.

     DELEMPTYLINE - delete empty lines

     Boolsch, if true empty lines will be deleted.

     DEFAULT: 1

     ESCAPE - specifies a escape character

     Use the ESCAPE character in front of magic sequences (or
     characters) to make them non magic.

     EXAMPLE: (escape a comment)
     	>this line includes a hash sign \# but no comment<
     will get into
     	>this line includes a hash sign # but no comment<
     of
     	>no \/*comment /* comment \*/ still comment */ no comment<
     will get into
     	>no /*comment no comment<

     EXAMPLE: (escape a escape character)
     	>a backslash:\\<
     will get into
     	>a backslash:\<

     EXAMPLE: (escape a new line)
     	>line one \
     	 line two<
     will get into
     	>line one                  line two<

     DEFAULT: `\\\\` # -> one backslash

     FILE - specify the filename

     If you use the syntax (3) the filename is got from this option.

     INCLUDE - specify a regexp for includes

     	If this regexp matches, the specified file will be included
     	at this point.

     This regexp must store the filename in the $1 varaible.

     DEFAULT: "include <(.*?)>"
     	  (filename in <> is stored)

     REMOVETRAILINGBLANKS - remove trailing blanks

     	Boolsch, if true trailing blanks will be removed.

     	EXAMPLE:
     		>		ho ho 	<
     	will get into
     		>ho ho< (no leading or trailing white spaces)

     DEFAULT: 1

close - closes a object instance
--------------------------------

     This method accually does nothing, but this may changed in future
     releases, so please use it for compatibily.

getfile - returns a scalar holding the whole file
-------------------------------------------------

     $file_contents = $file->getfile;

     returns the preparsed file.

getline - returns a scalar holding a line
-----------------------------------------

     $line = $file_getline;

     returns the file line by line until the end of the file is reached.
     The method will return an undefined value on end of file.

     NOTE: the first call to this method need not return the first line of
     	 the file (e.g. if the line was empty and DELEMPTYLINE was enabled)
     	 Use the method getline_number to get the linenumber of the last got
     	 line.

getline_reset - reset the cursor for getline
--------------------------------------------

     $file->getline_reset;

     If you call this method, the next call to the getline method will
     start the filereading from the top of the file.

getline_number - returns the input line number
----------------------------------------------

     $line_number = $file->getline_number;

     Returns the input line number of the last line got via getline.

     Because of the INCLUDE feature this method may called often to get
     the include path (see example below).

getline_file - returns the input filename
-----------------------------------------

     $filename = $file->getline_file;

     Returns the filename of the sourcefile of the last line got via getline.

     Because of the INCLUDE feature this mathod may called often to get
     the include path (see example below).

getline_error - returns errors of this line
-------------------------------------------

     $error = $file->getline_error;

     Returns for every error occurred in this line a human readable error message
     or an undefined value if no error occures.

     NOTE: Since one line may contain more then one error, this method may called
     	 often to get all error messages. The list will be terminated by
           an undefined value.

     NOTE: If you call this method before the first call to getline, you will
     	 get the global error messages (such as "file not found").

get_errors - returns ALL error messages
---------------------------------------

     print $file->get_errors;

     Returns a scalar holding ALL error messages in a preformated style.

setline_error - stores a errormessage
-------------------------------------

     $file->setline_error(sprintf("File %s not found", $filename));

     Stores a error message to a line.
     Every line may contain more then one error(message).

SEE ALSO
========

   CONFIG::Hash(3pm)

   The CONFIG:: Guide at http://www.fatalmind.com/programs/CONFIG

TODO
====

   Since this module is grown, the design is horrible! I should
re-implement the whole module (I'll do this in V2.0).

BUGS
====

   Many, but in most cases it will work correct ;)

   Note: the include stuff is very beta

AUTHOR
======

   Markus Winand <mws@fatalmind.com>

COPYRIGHT
=========

     Copyright (C) 1999, 2000 by Markus Winand <mws@fatalmind.com>

     This program is free software; you can redistribute it and/or
     modify it under the same terms as Perl itself.

query, download and build perl modules from CPAN sites
******************************************************

NAME
====

   CPAN - query, download and build perl modules from CPAN sites

SYNOPSIS
========

   Interactive mode:

     perl -MCPAN -e shell;

   Batch mode:

     use CPAN;

     autobundle, clean, install, make, recompile, test

DESCRIPTION
===========

   The CPAN module is designed to automate the make and install of perl
modules and extensions. It includes some searching capabilities and knows
how to use Net::FTP or LWP (or lynx or an external ftp client) to fetch
the raw data from the net.

   Modules are fetched from one or more of the mirrored CPAN
(Comprehensive Perl Archive Network) sites and unpacked in a dedicated
directory.

   The CPAN module also supports the concept of named and versioned
*bundles* of modules. Bundles simplify the handling of sets of related
modules. See Bundles below.

   The package contains a session manager and a cache manager. There is no
status retained between sessions. The session manager keeps track of what
has been fetched, built and installed in the current session. The cache
manager keeps track of the disk space occupied by the make processes and
deletes excess space according to a simple FIFO mechanism.

   For extended searching capabilities there's a plugin for CPAN available,
see CPAN/WAIT. `CPAN::WAIT' is a full-text search engine
that indexes all documents available in CPAN authors directories. If
`CPAN::WAIT' is installed on your system, the interactive shell of
<CPAN.pm> will enable the wq, wr, wd, wl, and wh commands which send
queries to the WAIT server that has been configured for your installation.

   All other methods provided are accessible in a programmer style and in
an interactive shell style.

Interactive Mode
----------------

   The interactive mode is entered by running

     perl -MCPAN -e shell

   which puts you into a readline interface. You will have the most fun if
you install Term::ReadKey and Term::ReadLine to enjoy both history and
command completion.

   Once you are on the command line, type 'h' and the rest should be
self-explanatory.

   The function call `shell' takes two optional arguments, one is the
prompt, the second is the default initial command line (the latter only
works if a real ReadLine interface module is installed).

   The most common uses of the interactive modes are

Searching for authors, bundles, distribution files and modules
     There are corresponding one-letter commands a, b, d, and m for each
     of the four categories and another, i for any of the mentioned four.
     Each of the four entities is implemented as a class with slightly
     differing methods for displaying an object.

     Arguments you pass to these commands are either strings exactly
     matching the identification string of an object or regular
     expressions that are then matched case-insensitively against various
     attributes of the objects. The parser recognizes a regular expression
     only if you enclose it between two slashes.

     The principle is that the number of found objects influences how an
     item is displayed. If the search finds one item, the result is
     displayed with the rather verbose method as_string, but if we find
     more than one, we display each object with the terse method
     <as_glimpse>.

make, test, install, clean  modules or distributions
     These commands take any number of arguments and investigate what is
     necessary to perform the action. If the argument is a distribution
     file name (recognized by embedded slashes), it is processed. If it is
     a module, CPAN determines the distribution file in which this module
     is included and processes that, following any dependencies named in
     the module's Makefile.PL (this behavior is controlled by
     *prerequisites_policy*.)

     Any make or test are run unconditionally. An

          install <distribution_file>

     also is run unconditionally. But for

          install <module>

     CPAN checks if an install is actually needed for it and prints
     *module up to date* in the case that the distribution file containing
     the module doesn't need to be updated.

     CPAN also keeps track of what it has done within the current session
     and doesn't try to build a package a second time regardless if it
     succeeded or not. The force command takes as a first argument the
     method to invoke (currently: make, test, or install) and executes the
     command from scratch.

     Example:

          cpan> install OpenGL
          OpenGL is up to date.
          cpan> force install OpenGL
          Running make
          OpenGL-0.4/
          OpenGL-0.4/COPYRIGHT
          [...]

     A clean command results in a

          make clean

     being executed within the distribution file's working directory.

get, readme, look module or distribution
     get downloads a distribution file without further action. `readme'
     displays the README file of the associated distribution. `Look' gets
     and untars (if not yet done) the distribution file, changes to the
     appropriate directory and opens a subshell process in that directory.

Signals
     CPAN.pm installs signal handlers for SIGINT and SIGTERM. While you are
     in the cpan-shell it is intended that you can press `^C' anytime and
     return to the cpan-shell prompt. A SIGTERM will cause the cpan-shell
     to clean up and leave the shell loop. You can emulate the effect of a
     SIGTERM by sending two consecutive SIGINTs, which usually means by
     pressing `^C' twice.

     CPAN.pm ignores a SIGPIPE. If the user sets inactivity_timeout, a
     SIGALRM is used during the run of the `perl Makefile.PL' subprocess.

CPAN::Shell
-----------

   The commands that are available in the shell interface are methods in
the package CPAN::Shell. If you enter the shell command, all your input is
split by the Text::ParseWords::shellwords() routine which acts like most
shells do. The first word is being interpreted as the method to be called
and the rest of the words are treated as arguments to this method.
Continuation lines are supported if a line ends with a literal backslash.

autobundle
----------

   autobundle writes a bundle file into the
`$CPAN::Config->{cpan_home}/Bundle' directory. The file contains a list of
all modules that are both available from CPAN and currently installed
within @INC. The name of the bundle file is based on the current date and
a counter.

recompile
---------

   recompile() is a very special command in that it takes no argument and
runs the make/test/install cycle with brute force over all installed
dynamically loadable extensions (aka XS modules) with 'force' in effect.
The primary purpose of this command is to finish a network installation.
Imagine, you have a common source tree for two different architectures.
You decide to do a completely independent fresh installation. You start on
one architecture with the help of a Bundle file produced earlier. CPAN
installs the whole Bundle for you, but when you try to repeat the job on
the second architecture, CPAN responds with a `"Foo up to date"' message
for all modules. So you invoke CPAN's recompile on the second architecture
and you're done.

   Another popular use for recompile is to act as a rescue in case your
perl breaks binary compatibility. If one of the modules that CPAN uses is
in turn depending on binary compatibility (so you cannot run CPAN
commands), then you should try the CPAN::Nox module for recovery.

The four `CPAN::*' Classes: Author, Bundle, Module, Distribution
----------------------------------------------------------------

   Although it may be considered internal, the class hierarchy does matter
for both users and programmer. CPAN.pm deals with above mentioned four
classes, and all those classes share a set of methods. A classical single
polymorphism is in effect. A metaclass object registers all objects of all
kinds and indexes them with a string. The strings referencing objects have
a separated namespace (well, not completely separated):

     Namespace                         Class

     words containing a "/" (slash)      Distribution
      words starting with Bundle::          Bundle
            everything else            Module or Author

   Modules know their associated Distribution objects. They always refer
to the most recent official release. Developers may mark their releases as
unstable development versions (by inserting an underbar into the visible
version number), so the really hottest and newest distribution file is not
always the default.  If a module Foo circulates on CPAN in both version
1.23 and 1.23_90, CPAN.pm offers a convenient way to install version 1.23
by saying

     install Foo

   This would install the complete distribution file (say
BAR/Foo-1.23.tar.gz) with all accompanying material. But if you would like
to install version 1.23_90, you need to know where the distribution file
resides on CPAN relative to the authors/id/ directory. If the author is
BAR, this might be BAR/Foo-1.23_90.tar.gz; so you would have to say

     install BAR/Foo-1.23_90.tar.gz

   The first example will be driven by an object of the class
CPAN::Module, the second by an object of class CPAN::Distribution.

Programmer's interface
----------------------

   If you do not enter the shell, the available shell commands are both
available as methods (`CPAN::Shell->install(...)') and as functions in the
calling package (`install(...)').

   There's currently only one class that has a stable interface -
CPAN::Shell. All commands that are available in the CPAN shell are methods
of the class CPAN::Shell. Each of the commands that produce listings of
modules (r, autobundle, u) also return a list of the IDs of all modules
within the list.

expand($type,@things)
     The IDs of all objects available within a program are strings that can
     be expanded to the corresponding real objects with the
     `CPAN::Shell->expand("Module",@things)' method. Expand returns a list
     of CPAN::Module objects according to the `@things' arguments given.
     In scalar context it only returns the first element of the list.

Programming Examples
     This enables the programmer to do operations that combine
     functionalities that are available in the shell.

          # install everything that is outdated on my disk:
          perl -MCPAN -e 'CPAN::Shell->install(CPAN::Shell->r)'

          # install my favorite programs if necessary:
          for $mod (qw(Net::FTP MD5 Data::Dumper)){
              my $obj = CPAN::Shell->expand('Module',$mod);
              $obj->install;
          }

          # list all modules on my disk that have no VERSION number
          for $mod (CPAN::Shell->expand("Module","/./")){
          	next unless $mod->inst_file;
              # MakeMaker convention for undefined $VERSION:
          	next unless $mod->inst_version eq "undef";
          	print "No VERSION in ", $mod->id, "\n";
          }

          # find out which distribution on CPAN contains a module:
          print CPAN::Shell->expand("Module","Apache::Constants")->cpan_file

     Or if you want to write a cronjob to watch The CPAN, you could list
     all modules that need updating. First a quick and dirty way:

          perl -e 'use CPAN; CPAN::Shell->r;'

     If you don't want to get any output in the case that all modules are
     up to date, you can parse the output of above command for the regular
     expression //modules are up to date// and decide to mail the output
     only if it doesn't match. Ick?

     If you prefer to do it more in a programmer style in one single
     process, maybe something like this suites you better:

          # list all modules on my disk that have newer versions on CPAN
          for $mod (CPAN::Shell->expand("Module","/./")){
            next unless $mod->inst_file;
            next if $mod->uptodate;
            printf "Module %s is installed as %s, could be updated to %s from CPAN\n",
                $mod->id, $mod->inst_version, $mod->cpan_version;
          }

     If that gives you too much output every day, you maybe only want to
     watch for three modules. You can write

          for $mod (CPAN::Shell->expand("Module","/Apache|LWP|CGI/")){

     as the first line instead. Or you can combine some of the above
     tricks:

          # watch only for a new mod_perl module
          $mod = CPAN::Shell->expand("Module","mod_perl");
          exit if $mod->uptodate;
          # new mod_perl arrived, let me know all update recommendations
          CPAN::Shell->r;

Methods in the four Classes
---------------------------

Cache Manager
-------------

   Currently the cache manager only keeps track of the build directory
($CPAN::Config->{build_dir}). It is a simple FIFO mechanism that deletes
complete directories below `build_dir' as soon as the size of all
directories there gets bigger than $CPAN::Config->{build_cache} (in MB).
The contents of this cache may be used for later re-installations that you
intend to do manually, but will never be trusted by CPAN itself. This is
due to the fact that the user might use these directories for building
modules on different architectures.

   There is another directory ($CPAN::Config->{keep_source_where}) where
the original distribution files are kept. This directory is not covered by
the cache manager and must be controlled by the user. If you choose to
have the same directory as build_dir and as keep_source_where directory,
then your sources will be deleted with the same fifo mechanism.

Bundles
-------

   A bundle is just a perl module in the namespace Bundle:: that does not
define any functions or methods. It usually only contains documentation.

   It starts like a perl module with a package declaration and a $VERSION
variable. After that the pod section looks like any other pod with the
only difference being that *one special pod section* exists starting with
(verbatim):

     =head1 CONTENTS

   In this pod section each line obeys the format

     Module_Name [Version_String] [- optional text]

   The only required part is the first field, the name of a module (e.g.
Foo::Bar, ie. not the name of the distribution file). The rest of the line
is optional. The comment part is delimited by a dash just as in the man
page header.

   The distribution of a bundle should follow the same convention as other
distributions.

   Bundles are treated specially in the CPAN package. If you say 'install
Bundle::Tkkit' (assuming such a bundle exists), CPAN will install all the
modules in the CONTENTS section of the pod. You can install your own
Bundles locally by placing a conformant Bundle file somewhere into your
@INC path. The autobundle() command which is available in the shell
interface does that for you by including all currently installed modules
in a snapshot bundle file.

Prerequisites
-------------

   If you have a local mirror of CPAN and can access all files with
"file:" URLs, then you only need a perl better than perl5.003 to run this
module. Otherwise Net::FTP is strongly recommended. LWP may be required
for non-UNIX systems or if your nearest CPAN site is associated with an
URL that is not ftp:.

   If you have neither Net::FTP nor LWP, there is a fallback mechanism
implemented for an external ftp command or for an external lynx command.

Finding packages and VERSION
----------------------------

   This module presumes that all packages on CPAN

   * declare their $VERSION variable in an easy to parse manner. This
     prerequisite can hardly be relaxed because it consumes far too much
     memory to load all packages into the running program just to determine
     the $VERSION variable. Currently all programs that are dealing with
     version use something like this

          perl -MExtUtils::MakeMaker -le \
              'print MM->parse_version(shift)' filename

     If you are author of a package and wonder if your $VERSION can be
     parsed, please try the above method.

   * come as compressed or gzipped tarfiles or as zip files and contain a
     Makefile.PL (well, we try to handle a bit more, but without much
     enthusiasm).

Debugging
---------

   The debugging of this module is a bit complex, because we have
interferences of the software producing the indices on CPAN, of the
mirroring process on CPAN, of packaging, of configuration, of
synchronicity, and of bugs within CPAN.pm.

   For code debugging in interactive mode you can try "o debug" which will
list options for debugging the various parts of the code. You should know
that "o debug" has built-in completion support.

   For data debugging there is the dump command which takes the same
arguments as make/test/install and outputs the object's Data::Dumper dump.

Floppy, Zip, Offline Mode
-------------------------

   CPAN.pm works nicely without network too. If you maintain machines that
are not networked at all, you should consider working with file: URLs. Of
course, you have to collect your modules somewhere first. So you might use
CPAN.pm to put together all you need on a networked machine. Then copy the
$CPAN::Config->{keep_source_where} (but not $CPAN::Config->{build_dir})
directory on a floppy. This floppy is kind of a personal CPAN. CPAN.pm on
the non-networked machines works nicely with this floppy. See also below
the paragraph about CD-ROM support.

CONFIGURATION
=============

   When the CPAN module is installed, a site wide configuration file is
created as CPAN/Config.pm. The default values defined there can be
overridden in another configuration file: CPAN/MyConfig.pm. You can store
this file in $HOME/.cpan/CPAN/MyConfig.pm if you want, because $HOME/.cpan
is added to the search path of the CPAN module before the use() or
require() statements.

   Currently the following keys in the hash reference $CPAN::Config are
defined:

     build_cache        size of cache for directories to build modules
     build_dir          locally accessible directory to build modules
     index_expire       after this many days refetch index files
     cache_metadata     use serializer to cache metadata
     cpan_home          local directory reserved for this package
     dontload_hash      anonymous hash: modules in the keys will not be
                        loaded by the CPAN::has_inst() routine
     gzip		     location of external program gzip
     inactivity_timeout breaks interactive Makefile.PLs after this
                        many seconds inactivity. Set to 0 to never break.
     inhibit_startup_message
                        if true, does not print the startup message
     keep_source_where  directory in which to keep the source (if we do)
     make               location of external make program
     make_arg	     arguments that should always be passed to 'make'
     make_install_arg   same as make_arg for 'make install'
     makepl_arg	     arguments passed to 'perl Makefile.PL'
     pager              location of external program more (or any pager)
     prerequisites_policy
                        what to do if you are missing module prerequisites
                        ('follow' automatically, 'ask' me, or 'ignore')
     scan_cache	     controls scanning of cache ('atstart' or 'never')
     tar                location of external program tar
     term_is_latin      if true internal UTF-8 is translated to ISO-8859-1
                        (and nonsense for characters outside latin range)
     unzip              location of external program unzip
     urllist	     arrayref to nearby CPAN sites (or equivalent locations)
     wait_list          arrayref to a wait server to try (See CPAN::WAIT)
     ftp_proxy,      }  the three usual variables for configuring
       http_proxy,   }  proxy requests. Both as CPAN::Config variables
       no_proxy      }  and as environment variables configurable.

   You can set and query each of these options interactively in the cpan
shell with the command set defined within the `o conf' command:

`o conf <scalar option>'
     prints the current value of the *scalar option*

`o conf <scalar option> <value>'
     Sets the value of the *scalar option* to value

`o conf <list option>'
     prints the current value of the *list option* in MakeMaker's
     neatvalue format.

`o conf <list option> [shift|pop]'
     shifts or pops the array in the *list option* variable

`o conf <list option> [unshift|push|splice] <list>'
     works like the corresponding perl commands.

Note on urllist parameter's format
----------------------------------

   urllist parameters are URLs according to RFC 1738. We do a little
guessing if your URL is not compliant, but if you have problems with file
URLs, please try the correct format. Either:

     file://localhost/whatever/ftp/pub/CPAN/

   or

     file:///home/ftp/pub/CPAN/

urllist parameter has CD-ROM support
------------------------------------

   The urllist parameter of the configuration table contains a list of
URLs that are to be used for downloading. If the list contains any file
URLs, CPAN always tries to get files from there first. This feature is
disabled for index files. So the recommendation for the owner of a CD-ROM
with CPAN contents is: include your local, possibly outdated CD-ROM as a
file URL at the end of urllist, e.g.

     o conf urllist push file://localhost/CDROM/CPAN

   CPAN.pm will then fetch the index files from one of the CPAN sites that
come at the beginning of urllist. It will later check for each module if
there is a local copy of the most recent version.

   Another peculiarity of urllist is that the site that we could
successfully fetch the last file from automatically gets a preference
token and is tried as the first site for the next request. So if you add a
new site at runtime it may happen that the previously preferred site will
be tried another time. This means that if you want to disallow a site for
the next transfer, it must be explicitly removed from urllist.

SECURITY
========

   There's no strong security layer in CPAN.pm. CPAN.pm helps you to
install foreign, unmasked, unsigned code on your machine. We compare to a
checksum that comes from the net just as the distribution file itself. If
somebody has managed to tamper with the distribution file, they may have
as well tampered with the CHECKSUMS file. Future development will go
towards strong authentication.

EXPORT
======

   Most functions in package CPAN are exported per default. The reason for
this is that the primary use is intended for the cpan shell or for
oneliners.

POPULATE AN INSTALLATION WITH LOTS OF MODULES
=============================================

   To populate a freshly installed perl with my favorite modules is pretty
easiest by maintaining a private bundle definition file. To get a useful
blueprint of a bundle definition file, the command autobundle can be used
on the CPAN shell command line. This command writes a bundle definition
file for all modules that are installed for the currently running perl
interpreter. It's recommended to run this command only once and from then
on maintain the file manually under a private name, say
Bundle/my_bundle.pm. With a clever bundle file you can then simply say

     cpan> install Bundle::my_bundle

   then answer a few questions and then go out for a coffee.

   Maintaining a bundle definition file means to keep track of two things:
dependencies and interactivity. CPAN.pm sometimes fails on calculating
dependencies because not all modules define all MakeMaker attributes
correctly, so a bundle definition file should specify prerequisites as
early as possible. On the other hand, it's a bit annoying that many
distributions need some interactive configuring. So what I try to
accomplish in my private bundle file is to have the packages that need to
be configured early in the file and the gentle ones later, so I can go out
after a few minutes and leave CPAN.pm unattained.

WORKING WITH CPAN.pm BEHIND FIREWALLS
=====================================

   Thanks to Graham Barr for contributing the following paragraphs about
the interaction between perl, and various firewall configurations. For
further informations on firewalls, it is recommended to consult the
documentation that comes with the ncftp program. If you are unable to go
through the firewall with a simple Perl setup, it is very likely that you
can configure ncftp so that it works for your firewall.

Three basic types of firewalls
------------------------------

   Firewalls can be categorized into three basic types.

http firewall
     This is where the firewall machine runs a web server and to access the
     outside world you must do it via the web server. If you set
     environment variables like http_proxy or ftp_proxy to a values
     beginning with http:// or in your web browser you have to set proxy
     information then you know you are running a http firewall.

     To access servers outside these types of firewalls with perl (even for
     ftp) you will need to use LWP.

ftp firewall
     This where the firewall machine runs a ftp server. This kind of
     firewall will only let you access ftp servers outside the firewall.
     This is usually done by connecting to the firewall with ftp, then
     entering a username like "user@outside.host.com"

     To access servers outside these type of firewalls with perl you will
     need to use Net::FTP.

One way visibility
     I say one way visibility as these firewalls try to make themselve look
     invisible to the users inside the firewall. An FTP data connection is
     normally created by sending the remote server your IP address and then
     listening for the connection. But the remote server will not be able
     to connect to you because of the firewall. So for these types of
     firewall FTP connections need to be done in a passive mode.

     There are two that I can think off.

    SOCKS
          If you are using a SOCKS firewall you will need to compile perl
          and link it with the SOCKS library, this is what is normally
          called a 'socksified' perl. With this executable you will be
          able to connect to servers outside the firewall as if it is not
          there.

    IP Masquerade
          This is the firewall implemented in the Linux kernel, it allows
          you to hide a complete network behind one IP address. With this
          firewall no special compiling is need as you can access hosts
          directly.

Configuring lynx or ncftp for going through a firewall
------------------------------------------------------

   If you can go through your firewall with e.g. lynx, presumably with a
command such as

     /usr/local/bin/lynx -pscott:tiger

   then you would configure CPAN.pm with the command

     o conf lynx "/usr/local/bin/lynx -pscott:tiger"

   That's all. Similarly for ncftp or ftp, you would configure something
like

     o conf ncftp "/usr/bin/ncftp -f /home/scott/ncftplogin.cfg"

   Your milage may vary...

FAQ
===

  1. I installed a new version of module X but CPAN keeps saying,       I
     have the old version installed Most probably you do have the old
     version installed. This can happen if a module installs itself into a
     different directory in the  @INC path than it was previously
     installed. This is not really a CPAN.pm problem, you would have the
     same problem when installing the module manually. The easiest way to
     prevent this behaviour is to add the argument `UNINST=1' to the make
     install call, and that is why many people add this argument
     permanently by configuring

          o conf make_install_arg UNINST=1

  2. So why is UNINST=1 not the default?  Because there are people who
     have their precise expectations about who may install where in the
     @INC path and who uses which @INC array. In fine tuned environments
     `UNINST=1' can cause damage.

  3. I want to clean up my mess, and install a new perl along with
     all modules I have. How do I go about it?  Run the autobundle command
     for your old perl and optionally rename the resulting bundle file
     (e.g. Bundle/mybundle.pm), install the new perl with the Configure
     option prefix, e.g.

          ./Configure -Dprefix=/usr/local/perl-5.6.78.9

     Install the bundle file you produced in the first step with something
     like

          cpan> install Bundle::mybundle

     and you're done.

  4. When I install bundles or multiple modules with one command
     there is too much output to keep track of You may want to configure
     something like

          o conf make_arg "| tee -ai /root/.cpan/logs/make.out"
          o conf make_install_arg "| tee -ai /root/.cpan/logs/make_install.out"

     so that STDOUT is captured in a file for later inspection.

  5. I am not root, how can I install a module in a personal
     directory?  You will most probably like something like this:

          o conf makepl_arg "LIB=~/myperl/lib \
                            INSTALLMAN1DIR=~/myperl/man/man1 \
                            INSTALLMAN3DIR=~/myperl/man/man3"
          install Sybase::Sybperl

     You can make this setting permanent like all `o conf' settings with
     `o conf commit'.

     You will have to add ~/myperl/man to the MANPATH environment variable
     and also tell your perl programs to look into ~/myperl/lib, e.g. by
     including

          use lib "$ENV{HOME}/myperl/lib";

     or setting the PERL5LIB environment variable.

     Another thing you should bear in mind is that the UNINST parameter
     should never be set if you are not root.

  6. How to get a package, unwrap it, and make a change before
     building it?
          look Sybase::Sybperl

  7. I installed a Bundle and had a couple of fails. When I       retried,
     everything resolved nicely. Can this be fixed to work       on first
     try?  The reason for this is that CPAN does not know the dependencies
     of all modules when it starts out. To decide about the additional
     items to install, it just uses data found in the generated Makefile.
     An undetected missing piece breaks the process. But it may well be
     that your Bundle installs some prerequisite later than some depending
     item and thus your second try is able to resolve everything. Please
     note, CPAN.pm does not know the dependency tree in advance and cannot
     sort the queue of things to install in a topologically correct order.
     It resolves perfectly well IFF all modules declare the prerequisites
     correctly with the PREREQ_PM attribute to MakeMaker. For bundles which
     fail and you need to install often, it is recommended sort the Bundle
     definition file manually. It is planned to improve the metadata
     situation for dependencies on CPAN in general, but this will still
     take some time.

  8. In our intranet we have many modules for internal use. How       can
     I integrate these modules with CPAN.pm but without uploading
     the modules to CPAN?  Have a look at the CPAN::Site module.

  9. When I run CPAN's shell, I get error msg about line 1 to 4,
     setting meta input/output via the /etc/inputrc file.  Some versions
     of readline are picky about capitalization in the /etc/inputrc file
     and specifically RedHat 6.2 comes with a /etc/inputrc that contains
     the word `on' in lowercase. Change the occurrences of `on' to On and
     the bug should disappear.

 10. Some authors have strange characters in their names.  Internally
     CPAN.pm uses the UTF-8 charset. If your terminal is expecting
     ISO-8859-1 charset, a converter can be activated by setting
     term_is_latin to a true value in your config file. One way of doing so
     would be

          cpan> ! $CPAN::Config->{term_is_latin}=1

     Extended support for converters will be made available as soon as perl
     becomes stable with regard to charset issues.

BUGS
====

   We should give coverage for all of the CPAN and not just the PAUSE
part, right? In this discussion CPAN and PAUSE have become equal - but
they are not. PAUSE is authors/, modules/ and scripts/. CPAN is PAUSE plus
the clpa/, doc/, misc/, ports/, and src/.

   Future development should be directed towards a better integration of
the other parts.

   If a Makefile.PL requires special customization of libraries, prompts
the user for special input, etc. then you may find CPAN is not able to
build the distribution. In that case, you should attempt the traditional
method of building a Perl module package from a shell.

AUTHOR
======

   Andreas Koenig <andreas.koenig@anima.de>

SEE ALSO
========

   perl(1), CPAN::Nox(3)

A CPAN Shell for CPAN admins
****************************

NAME
====

   CPAN::Admin - A CPAN Shell for CPAN admins

SYNOPSIS
========

   perl -MCPAN::Admin -e shell

DESCRIPTION
===========

   CPAN::Admin is a subclass of CPAN that adds the commands register and
`modsearch' to the CPAN shell.

   register calls get on the named module, assembles a couple of
informations (description, language), and calls Netscape with the -remote
argument so that a form is filled with all the assembled informations and
the registration can be performed with a single click. If the command line
has more than one argument, register does not run a get, instead it
interprets the rest of the line as DSLI status, description, and userid
and sends them to netscape such that the form is again mostly filled and
can be edited or confirmed with a single click. CPAN::Admin never performs
the submission click for you, it is only intended to fill in the form on
PAUSE and leave the confirmation to you.

   `modsearch' simply passes the arguments to the search engine for the
modules@perl.org mailing list at http://www.xray.mpe.mpg.de where all
registration requests are stored. It does so in the same way as register,
namely with the `netscape -remote' command.

   An experimental feature has also been added, namely to color already
registered modules in listings. If you have Term::ANSIColor installed, the
u, r, and m commands will show already registered modules in green.

PREREQISITES
============

   URI::Escape, netscape browser available in the path, netscape must
understand the -remote switch (as far as I know, this is only available on
UNIX); coloring of registered modules is only available if Term::ANSIColor
is installed.

Write a CHECKSUMS file for a directory as on CPAN
*************************************************

NAME
====

   CPAN::Checksums - Write a CHECKSUMS file for a directory as on CPAN

SYNOPSIS
========

     use CPAN::Checksums qw(updatedir);
     my $success = updatedir($directory);

DESCRIPTION
===========

   updatedir takes a directory name as argument and writes a CHECKSUMS
file in that directory unless a previously written CHECKSUMS file is there
that is still valid. Returns 2 if a new CHECKSUMS file has been written, 1
if a valid CHECKSUMS file is already there, otherwise dies.

   Setting the global variable $CAUTION causes updatedir to report changes
of files in the attributes size, mtime, md5, or `md5-ungz' to STDERR.

AUTHOR
======

   Andreas Koenig, andreas.koenig@anima.de

SEE ALSO
========

   perl(1).

Utility for CPAN::Config file Initialization
********************************************

NAME
====

   CPAN::FirstTime - Utility for CPAN::Config file Initialization

SYNOPSIS
========

   CPAN::FirstTime::init()

DESCRIPTION
===========

   The init routine asks a few questions and writes a CPAN::Config file.
Nothing special.

Wrapper around CPAN.pm without using any XS module
**************************************************

NAME
====

   CPAN::Nox - Wrapper around CPAN.pm without using any XS module

SYNOPSIS
========

   Interactive mode:

     perl -MCPAN::Nox -e shell;

DESCRIPTION
===========

   This package has the same functionality as CPAN.pm, but tries to
prevent the usage of compiled extensions during it's own execution. It's
primary purpose is a rescue in case you upgraded perl and broke binary
compatibility somehow.

SEE ALSO
========

   CPAN(3)

CPAN.pm subclass for adding site local modules
**********************************************

NAME
====

   CPAN::Site - CPAN.pm subclass for adding site local modules

SYNOPSIS
========

     perl -MCPAN::Site -e shell

WARNING
=======

   This is not even alpha software and will be made obsolete by CPAN.pm
extensions/plugins some day.

DESCRIPTION
===========

   This module virtually adds site specific modules to CPAN. The general
idea is to have a local (pseudo) CPAN server which is asked first. If the
request fails - which is the usual case, CPAN.pm switches to the next URL
in the list pointing to a real CPAN server. The pseudo CPAN server must
serve the files `site/02packages.details.txt.gz' and
`site/01mailrc.txt.gz' which contain the site local extensions to CPAN.
You must make sure that the pseudo server can satisfy the request for
these files since a failure will result in CPAN.pm trying to fetch the
`site/'* files from all the real CPAN servers in your urllist.

   The included *mkpackages* script can be used to generate the local
`02packages.details.txt' file. The script does scan the distribution files
for package names an version numbers. Note that lines looking like VERSION
specifications are evaluated!

   The Makefile.PL will ask you for the URL of your pseudo CPAN server.
This URL added to the front of the urllist of the CPAN.pm configuration
when using this module. Note that rereading the configuraion from the
CPAN.pm shell will cause this URL to be dropped. You must add it again
using

   cpan>` o conf urllist unshift '*your-URL-here*

   in this case.

   To use the module, generate your pseudo CPAN on a anonymous FTP, HTTP
or NFS server:

     mkdirhier ~wwwdata/htdocs/CPAN
     mkpackages ~wwwdata/htdocs/CPAN

     Then use C<-MCPAN::Site> instead of C<-MCPAN>

     perl -MCPAN::Site -e shell

Adding modules
==============

     mkdirhier ~wwwdata/htdocs/CPAN/authors/id/ULPFR
     mv /tmp/Telekom-0.101.tar.gz ~wwwdata/htdocs/CPAN/authors/id/ULPFR
     mkpackages ~wwwdata/htdocs/CPAN

AUTHOR
======

   Ulrich Pfeifer <`pfeifer@wait.de'>

adds commands to search a WAIT4CPAN server to the CPAN `shell()'
****************************************************************

NAME
====

   CPAN::WAIT - adds commands to search a WAIT4CPAN server to the CPAN
`shell()'

SYNOPSIS
========

     perl -MCPAN -e shell
     > wq au=wall
     > wr 3
     > wd 3
     > wl 20
     > wh
     > wh wq

DESCRIPTION
===========

   *CPAN::WAIT* adds some comands to the CPAN `shell()' to perform
searches on a WAIT server. It connects to a WAIT server using a simple
protocoll resembling NNTP as described in RFC977. It uses the
*WAIT::Client* module to handle this connection. This in turn inherits
from *Net::NNTP* from the `libnet' package. So you need *Net::NNTP* to use
this module.

   If no direct connection to the WAIT server is possible, the modules
tries to connect via your HTTP proxy (as given by the CPAN configuration).
Be warned though that the emulation of the stateful protocol via HTTP is
slow.

   The variable `CPAN::WAIT::TIMEOUT' specifies the number of seconds to
wait for an answer from the server. The default is 20. You may want to set
it to some larger value if you have a slow connection.

   The commands available are:

wh [command]
     Displays a short help message if called without arguments. If you
     provide the name of another command you will get more information on
     this command if available. Currently only wq will be explained.

wl count
     Limit the number of hits returned in a search to count. The limit
     usually is set ot 10 of you don't set it.

wq query
     Send a query to the server.

     Here are some query examples:

          information retrieval               free text query
          information or retrieval            same as above
          des=information retrieval           `information' must be in the description
          des=(information retrieval)         one of them in description
          des=(information or retrieval)      same as above
          des=(information and retrieval)     both of them in description
          des=(information not retrieval)     `information' in description and
                                              `retrieval' not in description
          des=(information system*)           wild-card search
          au=ilia                             author names may be misspelled

     You can build arbitary boolean combination of the above examples.
     Field names may be abbreviated. For further information see
     `http://ls6-www.informatik.uni-dortmund.de/CPAN'

     The result should look like this:

          wq au=wall

          1 8.039 a2p - Awk to Perl translator
          2 8.039 s2p - Sed to Perl translator
          3 8.039 perlipc - Perl interprocess communication (signals, fifos, pipes, safe subprocesses, sockets, and semaphores)
          4 8.039 ExtUtils::DynaGlue - Methods for generating Perl extension files
          5 8.039 h2xs - convert .h C header files to Perl extensions
          6 8.039 Sys::Syslog, openlog, closelog, setlogmask, syslog - Perl interface to the UNIX syslog(3) calls
          7 8.039 h2ph - convert .h C header files to .ph Perl header files
          8 8.039 Shell - run shell commands transparently within perl
          9 8.039 pl2pm - Rough tool to translate Perl4 .pl files to Perl5 .pm modules.
            10 8.039 perlpod - plain old documentation

wr *hit-number*
     Display the Record of hit number *hit-number*:

          wr 1

          source          authors/id/CHIPS/perl5.003_24.tar.gz
          headline        a2p - Awk to Perl translator
          size            5643
          docid           data/perl/x2p/a2p.pod

wd *hit-number*
     Fetches the full text from the server and runs perlpod on it. Make
     sure that you have perlpod in your path. Also check if your perlpod
     version can handle absolute pathes. Some older versions ironically do
     not find a document if the full patch is given on the command line.

AUTHOR
======

   Ulrich Pfeifer <`pfeifer@ls6.informatik.uni-dortmund.de'>

parser for CSS-style syntax
***************************

NAME
====

   CSS::Parser - parser for CSS-style syntax

SYNOPSIS
========

     use CSS::Parser;

     my $css = CSS::Parser->new(
                               handlers => {
                                            css_comment      => \&css_com,
                                            selector_string  => \&sel,
                                            block_start      => \&blk_s,
                                            property         => \&prop,
                                            value            => \&val,
                                            block_end        => \&blk_e,
                                            at_rule          => \&atr,
                                            at_symbol        => \&ats,
                                            error            => \&error
                                            }
                               );

     $css->parse(\$some_css_text);

     sub css_com {
        my $self = shift;
        my $comment = shift;
        print "css comment:\n\t$comment\n";
     }

     ...

DESCRIPTION
===========

   The `CSS::Parser' deals simply with fairly loose CSS syntax.  It
doesn't know anything about what it is parsing, for that see other
classes. This allows it to be the base for `CSS::CSSn', `CSS::STTSn' and
any other parser for a css-compatible syntax.

   Chances are, you will want to use one of the existing subclasses or to
subclass it yourself.

   The interface to `CSS::Parser' is:

my $css = CSS::Parser->new([style => $parse_style],[handlers => $hashref_of_handlers]);
     The constructor takes a variety of options provided in a hash.

     style defines the style of parsing that you want from the parser. As
     of now the only style is 'callback' (default), however this may evolve
     in the future.

     handlers specifies a hash of callbacks to be called when a given
     token has been met. Callbacks are CODEREFS. The callback sub will
     receive the parser object as it's first argument, and optionally the
     token when it makes sense (eg: selector_string will be passed the
     selector, but block_start won't receive the '{').

     One may use 'default' to activate them all. Note that you can set a
     callback to the empty string (not undef) if you wish to set a default
     for all but to deactivate that specific callback.

        * html_open_comment

          Called when a <!- comment is seens, no second argument.

        * html_close_comment

          Called when a -> comment is seens, no second argument.

        * css_comment

          Called when a css comment of the form /* text */ is seen.
          Receives the comment with leading /* and trailing */.

        * comment

          Called when any of the above types of comment is seen. Receives
          the comment as is.

        * at_symbol

          Called when an at-symbol (@ident) is seen and is followed by a
          block.  The block is parsed subsequently. Receives the at-symbol.

        * at_rule

          Called when a block-less at-rule (@import url('foo') print;) is
          seen, receives the entire rule (it isn't further tokenized, that
          is the job of the subclass because it requires it to know what
          is expected after the specific at-keyword).

        * selector_string

          Called whenever a selector string is seen and receives the entire
          string as tokenising it further would require knowledge of the
          specific variant of CSS.

        * block_start

          Called when the beginning of a block is seen ({), receives
          nothing.

        * property

          Called when a property is seen, receives the property.

        * value

          Called when a value is seen, receives the value which is not
          parsed to know it's individual components, that belongs to the
          subclass.

        * declaration

          Called with property : $value ;

        * block_end

          Same as block_start, for }.

        * ruleset

          Called with selector_string '{' [declaration;]* '}'

        * error

          Called whenever the parser notices an error, receives what is
          left of the CSS text when the error occurred plus an informative
          message.

        * default

          The use for default is to substitute a standard callback for all
          callbacks that are not defined.

$css->parse( $string_ref );
     Tells the parser to go ahead and parse the provided reference to a
     string. Note that the string will be empty after the parser has
     finished, unless the stylesheet contains an error. It returns 1 upon
     success and undef upon failure.

SEE ALSO
========

   See XML/Parser, HTML/Parser,
HTML/TreeBuilder,

COPYRIGHT
=========

   Copyright 1998-1999 Robin Berjon (robin@knowscape.com). All rights
reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Shared data cache using memory mapped files
*******************************************

NAME
====

   Cache::Mmap - Shared data cache using memory mapped files

SYNOPSIS
========

     use Cache::Mmap;

     $cache=Cache::Mmap->new($filename,\%options);

     $val1=$cache->read($key1);
     $cache->write($key2,$val2);
     $cache->delete($key3);

DESCRIPTION
===========

   This module implements a shared data cache, using memory mapped files.
If routines are provided which interact with the underlying data, access to
the cache is completely transparent, and the module handles all the
details of refreshing cache contents, and updating underlying data, if
necessary.

   Cache entries are assigned to "buckets" within the cache file,
depending on the key. Within each bucket, entries are stored apporximately
in order of last access, so that frequently accessed entries will move to
the head of the bucket, thus decreasing access time. Concurrent accesses
to the same bucket are prevented by file locking of the relevent section
of the cache file.

METHODS
=======

Cache::Mmap->new($filename,\%options)
     Creates a new cache object. If the file named by $filename does not
     already exist, it will be created. Various options may be set in
     %options, which affect the behaviour of the cache (defaults in
     parentheses):

    permissions (0600)
          Sets the file permissions for the cache file if it doesn't
          already exist.

    buckets (13)
          Sets the number of buckets inside the cache file. A larger
          number of buckets will give better performance for a cache with
          many accesses, as there will be less chance of concurrent access
          to the same bucket.

    bucketsize (1024)
          Sets the size of each bucket, in bytes. A larger bucket size
          will be needed to store large cache entries. If the bucketsize
          is not large enough to hold a particular entry, it will still be
          passed between the underlying data and the application in its
          entirety, but will not be stored in the cache.

    pagesize (1024)
          Sets the alignment of buckets within the file. The file header
          will be extended to this size, and bucket sizes will be rounded
          up to the nearest multiple.  Choosing a pagesize equal to the
          virtual memory page size of the host system should improve
          performance.

    strings (0)
          If true, cache entries are treated as strings, rather than
          references. This will help performance for string-only caches,
          as no time will be taken to serialize cache entries.

    expiry (0)
          If non-zero, sets the length of time, in seconds, which cache
          entries are considered valid. A new entry will be fetched from
          the underlying data if an expired cache entry would otherwise
          have been returned.

    context (undef)
          This value is passed to the read/write/delete routines below, to
          provide context. This will typically be a database handle, used
          to fetch data from.

    read (undef)
          Provides a code reference to a routine which will fetch entries
          from the underlying data. Called as `$read->($key,$context)',
          this routine should return a list `($found,$value)', where
          `$found' is true if the entry could be found in the underlying
          data, and $value is the value to cache, or undef if not found.
          If this routine is not provided, only values already in the
          cache will ever be returned.

    cachenegative (0)
          If true, even unsuccessful fetches from the underlying data are
          cached. This can be useful to only search the underlying data
          once for each required key.

    write (undef)
          Provides a code reference to a routine which will write cache
          entries into the underlying data. This routine will be called
          after `$cache->write()' is called, to synchronise the underlying
          data with the cache. Called as `$write->($key,$val,$context)'.
          If the routine is not provided, the underlying data will not be
          synchronised after cache writes.

    writethrough (1)
          If true, the write routine above will be called as soon as
          `$cache->write()' is called. This provides immediate
          synchronisation of underlying data and cache contents.

          If false, the write routine will be called for each cache entry
          which no longer fits in its bucket after a cache read or write.
          This provides a write-as-necessary behaviour, which may be more
          efficient than the writethrough behaviour. However, only data
          fetched through the cache will reflect these changes.

    delete (undef)
          Provides a code reference to a routine which will delete items
          from the underlying data. This routine will be called after
          `$cache-'delete()> is called, to synchronise the underlying data
          with the cache. Called as `$cache->delete($key,$cval,$context)',
          where `$cval' is the value currently stored in the cache. If
          this routine is not provided, entries deleted from the cache
          have no effect on the underlying data.

     An alternative to supplying a write routine, is to call
     `$cache->delete()' after updating the underlying data. Note however,
     that in the case of databases, this should be done after committing
     the update, so that a concurrent process doesn't reload the cache
     between being the entry being deleted, and the database updates being
     committed.

$cache->buckets()
     Returns the number of buckets in the cache file. Note that this may be
     different to the number passed to new(), since an existing cache file
     may have been created with different options.

$cache->bucketsize()
     Returns the size of buckets in the cache file. May be different to
     new() parameter.

$cache->pagesize()
     Returns the page size of the cache file. May be different to new()
     parameter.

$cache->strings()
     Returns true if the cache stores strings rather than references. May
     be different to new() parameter.

$cache->expiry()
     Returns the time in seconds cache entries are considered valid for,
     or zero for indefinite validity. May be different to new() parameter.

$cache->writethrough()
     Returns true if items written to the cache are immediately written to
     the underlying data. May be different to new() parameter.

$cache->cachenegative()
     Returns true if items not found in the underlying data are cached
     anyway. May be different to new() parameter.

$cache->context()
     Returns the context data for reads and writes to the underlying data.

$cache->context($context)
     Provides new context data for reads and writes to the underlying data.

$cache->read($key)
     Reads an entry from the cache, or from the underlying data if not
     cached.  Returns the value in scalar context, and `($found,$value)'
     in list context, where `$found' is true if the item was found in
     either the cache or the underlying data.

$cache->write($key,$val)
     Writes an entry into the cache, and depending on new() options, into
     the underlying data.

$cache->delete($key)
     Deletes an entry from the cache, and depending on new() options, from
     the underlying data.

AUTHOR
======

   Peter Haworth <pmh@edison.ioppublishing.com>

Perl extension to interface with CDE Calendar Manager
*****************************************************

NAME
====

   Calendar::CSA - Perl extension to interface with CDE Calendar Manager

SYNOPSIS
========

     use Calendar::CSA;
     [etc]

DESCRIPTION
===========

   Unfortunately, this module is not documented at this time.

AUTHOR
======

   Kenneth Albanowski <kjahds@kjahds.com>, with the assistance of Bharat
Mediratta <Bharat.Mediratta@Corp.Sun.COM>. Please contact me (Kenneth
Albanowski) about matters pertaining to this module.

object interface for function callbacks
***************************************

NAME
====

   Callback - object interface for function callbacks

SYNOPSIS
========

     use Callback;

     my $callback = new Callback (\&myfunc, @myargs);
     my $callback = new Callback ($myobj, $mymethod, @myargs);

     $callback->call(@some_more_args);

DESCRIPTION
===========

   Callback provides a simple interface for function callbacks.  It would
be possible to provide nearly all of the functionality using inline code
references.  Callback was written before inline code references were added
to perl.

   What callback does provide is a simple interface for common situation:
passing around a function.

   When a callback is constructed, a base set of arguments can be
provided.  These function arguments will preceed any arguments added at
the time the call is made.

   There are two forms for the callback constructor, depending on whether
the call is a pure functional call or a method call.  The rule is that if
the first argument is an object, then the second argument is a method name
to be called on that object.

TRACING
=======

     use Callback qw(@callbackTrace);

   If you're writing a debugging routine that provides a stack-dump (for
example, Carp::confess) it is useful to know where a callback was
registered.

     my $ct = 0;
     while (($package, $file, $line, $subname, $hasargs, $wantarray) = caller($i++)) {
         ...

     if ($subname eq 'Callback::call') {
     		print "callback registered $Callback::callbackTrace[$ct]\n";
     		$ct++;
     }
     	}

   Without such code, it becomes very hard to know what's going on.

COPYRIGHT
=========

   Copyright (C) 1994, 2000, David Muir Sharnoff.   All rights reserved.
License hearby granted for anyone to use this module at their own risk.
Please feed useful changes back to muir@idiom.com.

warn of errors (from perspective of caller)
*******************************************

NAME
====

   carp    - warn of errors (from perspective of caller)

   cluck   - warn of errors with stack backtrace           (not exported
by default)

   croak   - die of errors (from perspective of caller)

   confess - die of errors with stack backtrace

SYNOPSIS
========

     use Carp;
     croak "We're outta here!";

     use Carp qw(cluck);
     cluck "This is how we got here!";

DESCRIPTION
===========

   The Carp routines are useful in your own modules because they act like
die() or warn(), but report where the error was in the code they were
called from.  Thus if you have a routine Foo() that has a carp() in it,
then the carp() will report the error as occurring where Foo() was called,
not where carp() was called.

Forcing a Stack Trace
---------------------

   As a debugging aid, you can force Carp to treat a croak as a confess
and a carp as a cluck across all modules. In other words, force a detailed
stack trace to be given.  This can be very helpful when trying to
understand why, or from where, a warning or error is being generated.

   This feature is enabled by 'importing' the non-existent symbol
'verbose'. You would typically enable it by saying

     perl -MCarp=verbose script.pl

   or by including the string `MCarp=verbose' in the `PERL5OPT' in this
node environment variable.

BUGS
====

   The Carp routines don't handle exception objects currently.  If called
with a first argument that is a reference, they simply call die() or
warn(), as appropriate.

executable comments
*******************

NAME
====

   Carp::Assert - executable comments

SYNOPSIS
========

     # Assertions are on.
     use Carp::Assert;

     $next_sunrise_time = sunrise();

     # Assert that the sun must rise in the next 24 hours.
     assert(($next_sunrise_time - time) < 24*60*60) if DEBUG;

     # Assertions are off.
     no Carp::Assert;

     $next_pres = divine_next_president();

     # Assert that if you predict Dan Quayle will be the next president
     # your crystal ball might need some polishing.  However, since
     # assertions are off, IT COULD HAPPEN!
     shouldnt($next_pres, 'Dan Quayle') if DEBUG;

DESCRIPTION
===========

     "We are ready for any unforseen event that may or may not
     occur."
         - Dan Quayle

   Carp::Assert is intended for a purpose like the ANSI C library
assert.h.  If you're already familiar with assert.h, then you can probably
skip this and go straight to the FUNCTIONS section.

   Assertions are the explict expressions of your assumptions about the
reality your program is expected to deal with, and a declaration of those
which it is not.  They are used to prevent your program from blissfully
processing garbage inputs (garbage in, garbage out becomes garbage in,
error out) and to tell you when you've produced garbage output.  (If I was
going to be a cynic about Perl and the user nature, I'd say there are no
user inputs but garbage, and Perl produces nothing but...)

   An assertion is used to prevent the impossible from being asked of your
code, or at least tell you when it does.  For example:

     # Take the square root of a number.
     sub my_sqrt {
         my($num) = shift;

     # the square root of a negative number is imaginary.
     assert($num >= 0);

     return sqrt $num;
         }

   The assertion will warn you if a negative number was handed to your
subroutine, a reality the routine has no intention of dealing with.

   An assertion should also be used a something of a reality check, to
make sure what your code just did really did happen:

     open(FILE, $filename) || die $!;
     @stuff = <FILE>;
     @stuff = do_something(@stuff);

     # I should have some stuff.
     assert(scalar(@stuff) > 0);

   The assertion makes sure you have some @stuff at the end.  Maybe the
file was empty, maybe do_something() returned an empty list... either way,
the assert() will give you a clue as to where the problem lies, rather
than 50 lines down when you print out @stuff and discover it to be empty.

   Since assertions are designed for debugging and will remove themelves
from production code, your assertions should be carefully crafted so as to
not have any side-effects, change any variables or otherwise have any
effect on your program.  Here is an example of a bad assertation:

     assert($error = 1 if $king ne 'Henry');  # Bad!

   It sets an error flag which may then be used somewhere else in your
program. When you shut off your assertions with the $DEBUG flag, $error
will no longer be set.

   Here's another bad example:

     assert($next_pres ne 'Dan Quayle' or goto Canada);  # Bad!

   This assertion has the side effect of moving to Canada should it fail.
This is a very bad assertion since error handling should not be placed in
an assertion, nor should it have side-effects.

   In short, an assertion is an executable comment.  For instance, instead
of writing this

     # $life ends with a '!'
     $life = begin_life();

   you'd replace the comment with an assertion which *enforces* the
comment.

     $life = begin_life();
     assert( $life =~ /!$/ );

FUNCTIONS
=========

assert
          assert(STATEMENT) if DEBUG;

     assert's functionality is effected by compile time value of the DEBUG
     constant.  If DEBUG is true, assert will function as below.  If DEBUG
     is false the assert function will compile itself out of the program.
     See `Debugging vs Production' in this node for details.

     Give assert an expression, assert will Carp::confess() if that
     expression is false, otherwise it does nothing.  (DO NOT use the
     return value of assert for anything, I mean it... really!).

     The error from assert will look something like this:

          Assert failed
                  Carp::Assert::assert(0) called at prog line 23
                  main::foo called at prog line 50

     Indicating that in the file "prog" an assert failed inside the
     function main::foo() on line 23 and that foo() was in turn called from
     line 50 in the same file.

should
shouldnt
          should  ($this, $shouldbe)   if DEBUG;
          shouldnt($this, $shouldntbe) if DEBUG;

     Similar to assert(), it is specially for simple "this should be that"
     or "this should be anything but that" style of assertions.

     Due to Perl's lack of a good macro system, assert() can only report
     where something failed, but it can't report *what* failed or how.
     should() and shouldnt() can produce more informative error messages:

          Assert failed:  'this' should be 'that'!
                  Carp::Assert::should('this', 'that') called at moof line 29
                  main::foo() called at moof line 58

     So this:

          should($this, $that) if DEBUG;

     is similar to this:

          assert($this eq $that) if DEBUG;

     except for the better error message.

     Currently, should() and shouldnt() can only do simple eq and ne tests
     (respectively).  Future versions may allow regexes.

Debugging vs Production
=======================

   Because assertions are extra code and because it is sometimes necessary
to place them in 'hot' portions of your code where speed is paramount,
Carp::Assert provides the option to remove its assert() calls from your
program.

   So, we provide a way to force Perl to inline the switched off assert()
routine, thereby removing almost all performance impact on your production
code.

     no Carp::Assert;  # assertions are off.
     assert(1==1) if DEBUG;

   DEBUG is a constant set to 0.  Adding the 'if DEBUG' condition on your
assert() call gives perl the cue to go ahead and remove assert() call from
your program entirely, since the if conditional will always be false.

   (This is the best I can do without requiring Filter::cpp)

   Another way to switch off all asserts, system wide, is to define the
NDEBUG or the PERL_NDEBUG environment variable.

   You can safely leave out the "if DEBUG" part, but then your assert()
function will always execute (and its arguments evaluated).  Oh well.

Differences from ANSI C
=======================

   assert() is intended to act like the function from ANSI C fame.
Unfortunately, due to perl's lack of macros or strong inlining, it's not
nearly as unobtrusive.

   Well, the obvious one is the "if DEBUG" part.  This is cleanest way I
could think of to cause each assert() call and its arguments to be removed
from the program at compile-time, like the ANSI C macro does.

   Also, this version of assert does not report the statement which
failed, just the line number and call frame via Carp::confess.  You can't
do `assert('$a == $b')' because $a and $b will probably be lexical, and
thus unavailable to assert().  But with Perl, unlike C, you always have
the source to look through, so the need isn't as great.

ENVIRONMENT
===========

NDEBUG
     Defining NDEBUG switches off all assertions.  It has the same effect
     as changing "use Carp::Assert" to "no Carp::Assert" but it effects all
     code.

PERL_NDEBUG
     Same as NDEBUG and will override it.  Its provided to give you
     something which won't conflict with any C programs you might be
     working on at the same time.

BUGS, CAVETS and other MUSINGS
==============================

   Someday, Perl will have an inline pragma, and the `if DEBUG'
bletcherousness will go away.

   I really need to figure a way to get it to return the given statement
in the assertion.  should() and shouldnt() is a start.  Maybe
B::Deparse... would assert({$this eq $that}) be too annoying?

   Yes, there is a `shouldn't' routine.  It mostly works, but you must put
the `if DEBUG' after it.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

Carp guts
*********

NAME
====

   Carp::Heavy - Carp guts

SYNOPIS
=======

   (internal use only)

DESCRIPTION
===========

   No user-serviceable parts inside.

Loudly complain in lots of places when things break badly
*********************************************************

NAME
====

   Carp::Notify - Loudly complain in lots of places when things break badly

AUTHOR
======

   Jim Thomason thomasoniii@yahoo.com

SYNOPSIS
========

   Use it in place of die or croak, or warn or carp.

     #with Carp;
     use Carp;
     if ($something_a_little_bad) { carp("Oh no, a minor error!")};
     if ($something_bad) { croak ("Oh no an error!")};

     #with Carp::Notify;
     use Carp::Notify;
     if (something_a_little_bad) {notify("Oh no, a minor error!")};
     if ($something_bad) { explode ("Oh no an error!")};

REQUIRES
========

   Perl 5.004, Socket (for emailing)

DESCRIPTION
===========

   Carp::Notify is an error reporting module designed for applications
that are running unsupervised (a CGI script, for example, or a cron job).
If a program has an explosion, it terminates (same as die or croak or
exit, depending on preference) and then emails someone with useful
information about what caused the problem.  Said information can also be
logged to a file.  If you want the program to tell you something about an
error that's non fatal (disk size approaching full, but not quite there,
for example), then you can have it notify you of the error but not
terminate the program.

   Defaults are set up within the module, but they can be overridden once
the module is used, or as individual explosions take place.

BUILT IN STUFF
==============

Using the module
     use Carp::Notify;

     will require and import the module, same as always.  What you decide
     to import it with is up to you.  You can choose to import additional
     functions into your namespace, set up new default values, or give it
     a list of variables to store.

     Carp::Notify will always export the explode function and the notify
     function.  Carp always exports carp, croak, and confess, so I figure
     that I can get away with always exporting explode and notify.  Nyaah.

     Be sure that you set your default variables before using it!

    make_storable
          if this is an import argument, it will export the make_storable
          function into your namespace.  See make_storable, below.

    make_unstorable
          If this is an import argument, it will export the
          make_unstorable function into your namespce.  See
          make_unstorable, below.

    croak
          If this is an import argument, it will override the croak
          function in your namespace and alias it to explode.  That way
          you can switch all of your croaks to explodes by just changing
          how you use your module, and not all of your code.

    carp
          If this is an import argument, it will override the carp
          function in your namespace and alias it to notify.  That way you
          can switch all of your carps to notifies by just changing which
          module you use, and not all of your code.

    (log_it|email_it|store_vars|stack_trace|store_env|email|log_file|smtp|die_to_stdout|die_quietly|death_message)
          Example:

               use Carp::Notify (
               	"log_it" => 1,
               	"email_it => 0,
               	"email" => 'thomasoniii@yahoo.com'
               );

          These are hash keys that allow you to override the
          Carp::Notify's module defaults.  These can also all be
          overloaded explicitly in your explode() calls, but this allows a
          global modification.

         log_it
               Flag that tells Carp::Notify whether or not to log the
               explosions to the log file

         log_file
               Overrides the default log file.  This file will be opened
               in append mode and the error message will be stored in it,
               if log_it is true.

               If you'd like, you can give log_file a reference to a glob
               that is an open filehandle instead of a scalar containing
               the log name.  This is most useful if you want to redirect
               your error log to STDERR or to a pipe to a program.

               Be sure to use globrefs only explicitly in your call to
               explode, or to wrap the definition of the filehandle in a
               begin block before using the module.  Otherwise, you'll be
               trying to log to a non-existent file handle and
               consequently won't log anything.  That'd be bad.

         email_it
               Flag that tells Carp::Notify whether or not to email a user
               to let them know something broke

         email
               Overrides the default email address.  This is whoever the
               error message will get emailed to if U<email_it> is true.

         smtp
               Allows you to set a new SMTP relay for emailing

         store_vars
               Flag that tells Carp::Notify whether or not to list any
               storable variables in the error message.  See storable
               variables, below.

         stack_trace
               Flag that tells Carp::Notify whether or not to do a call
               stack trace of every function call leading up to the
               explosion.

         store_env
               Flag that tells Carp::Notify whether or not to store the
               environment variables in the error message.

         die_to_stdout
               Allows you to terminate your program by displaying an error
               to STDOUT, not to STDERR.

         die_quietly
               Terminates your program without displaying any message to
               STDOUT or STDERR.  =back

              death_message
                    The message that is printed to the appropriate
                    location, unless we're dying quietly.  =back

              (*storable variable*)
                    A variable name within single quotes will tell the
                    Carp::Notify module that you want to report the
                    current value of that variable when the explosion
                    occurs.  Carp::Notify will report an error if you try
                    to store a value that is undefined, if you had
                    accidentally typed something in single quotes, for
                    instance.  For example,

                         use Carp::Notify ('$scalar', '@array');

                         $scalar = "some_value";
                         @array = qw(val1 val2 val3);

                         explode("An error!");

                         will write out the values "$scalar : some_value" and "@array : val1 val2 val3" to the log file.

                    This can also only be used to store global variables.
                    Dynamic or lexical variables need to be explicitly
                    placed in explode() calls.

                    You can store variables from other packages if you'd
                    like:

                    use Carp::Notify ('$other_package::scalar',
                    '@some::nested::package::array');

                    Only global scalars, arrays, and hashes may be stored.

         make_storable
               Makes whatever variables it's given storable.  See
               *storable variables*, above.

                    make_storable('$new_scalar', '@different_array');

         make_unstorable
               Stops whatever variables it's given from being stored.  See
               *storable variables*, above.

                    make_unstorable('$scalar', '@different_array');

         explode
               explode is where the magic is.  It's exported into the
               calling package by default (no point in using this module
               if you're not gonna use this function, after all).

               You can override your default values here (see *Using the
               module above*), if you'd like, and otherwise specify as
               many error messages as you'd like to show up in your logs.

                    #override who the mail's going to, and the log file.
                    explode("email" => "thomasoniii@yahoo.com", log_file => "/home/jim/jim_explosions.log", "A terrible error: $!");

                    #Same thing, but with a globref to the same file
                    open (LOG, ">>/home/jim/jim_explosions.log");
                    explode("email" => "thomasoniii@yahoo.com", log_file => \*LOG, "A terrible error: $!");

                    #don't log.
                    explode ("log_it" => 0, "A terrible error: $!");

                    #keep the defaults
                    explode("A terrible error: $!", "And DBI said:  $DBI::errstr");

         notify
               notify is to explode as warn is to die.  It does everything
               exactly the same way, but it won't terminate your program
               the way that an explode would.

FAQ
===

   *So what's the point of this thing?*

   It's for programs that need to keep running and that need to be fixed
quickly when they break.

   *But I like Carp*

   I like Carp too.  :)

   This isn't designed to replace Carp, it serves a different purpose.
Carp will only tell you the line on which your error occurred.  While this
i helpful, it doesn't get your program running quicker and it doesn't help
you to find an error that you're not aware of in a CGI script that you
think is running perfectly.

   Carp::Notify tells you ASAP when your program breaks, so you can
inspect and correct it quicker.  You're going to have less downtime and
the end users will be happier with your program because there will be
fewer bugs since you ironed them out quicker.

   *Wow.  That was a real run-on sentence*

   Yeah, I know.  That's why I'm a programmer and not an author.  :)

   *What about CGI::Carp?*

   That's a bit of a gray area.  Obviously, by its name, CGI::Carp seems
designed for CGI scripts, whereas Carp::Notify is more obvious for
anything (cron jobs, command line utilities, as well as CGIs).

   Carp::Notify also can store more information with less interaction from
the programmer.  Plus it will email you, if you'd like to let you know
that something bad happened.

   As I understand it, CGI::Carp is a subset feature-wise of Carp::Notify.
If CGI::Carp is working fine for you, great continue to use it.  If you
want more flexible error notification, then try out Carp::Notify.

   *But I can send email with CGI::Carp by opening up a pipe to send mail
and using that as my error log.  What do you have to say about that?*

   Good for you.  I can too.  But most people that I've interacted with
either don't have the know-how to do that or just plain wouldn't have
thought of it.  Besides, it's still more of a hassle than just using
Carp::Notify.

   *Why are your stored variables kept in an array instead of a hash?
Hashes are quicker to delete from, after all*

   While it is definitely true that variables can be unstored a little
quicker in a hash, I figured that stored variables will only rarely be
unstored later.  Arrays are quicker for storing and accessing the items
later.   I'll live with the slight performance hit for the rarer case.

   *Can I store variables that are in another package from the one that
called Carp::Notify?*

   You betcha.  Just prepend the classpath to the variable name, same as
you always have to to access variables not in your name space.  If the
variable is already in your name space (you imported it), you don't need
the classpath since explode will just pick it up within your own namespace.

   *Can I store local or my variables?*

   Not in the use statement, but you can in an explicit explode.

   *Are there any bugs I should be aware of?*

   Only if you're annoying.  If you import explode into your package, then
subclass it and export explode back out it won't correctly pick up your
stored variables unless you fully qualified them with the class path
($package::variable instead of just $variable)

   Solution?  Don't re-export Carp::Notify.  But you already knew that you
should juse re-use it in your subclass, right?

   *Could I see some more examples?*

   Sure, that's the next section.

   *Okay, you've convinced me.  What other nifty modules have you
distributed?*

   Mail::Bulkmail and Text::Flowchart.

   *Was that a shameless plug?*

   Why yes, it was.

Examples
========

     #store $data, do email the errors, and alias croak => explode
     use Carp::Notify ('$data', 'email_it' => 1, "croak");

     #email it to a different address, and don't log it.
     use Carp::Notify ("email" => 'thomasoniii@yahoo.com', 'log_it' => 0);

     #die with an explosion.
     explode("Ye gods!  An error!");

     #explode, but do it quietly.
     explode ("die_quietly" => 1, "Ye gods!  An error!");

     #notify someone of a problem, but keep the program running
     notify ("Ye gods!  A little error!");

Version History
===============

   v1.00 - August 10, 2000 - Changed the name from Explode to
Carp::Notify.  It's more descriptive and I don't create a new namespace.

   v1.00 FC1 - June 9, 2000 - First publically available version.

COPYRIGHT (again)
=================

   Copyright (c) 2000 James A Thomason III (thomasoniii@yahoo.com). All
rights reserved.  This program is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

CONTACT INFO
============

   So you don't have to scroll all the way back to the top, I'm Jim
Thomason (thomasoniii@yahoo.com) and feedback is appreciated.  Bug
reports/suggestions/questions/etc.  Hell, drop me a line to let me know
that you're using the module and that it's made your life easier.  :-)

Configuration module for parsing commandline arguments
******************************************************

NAME
====

   `CfgTie::CfgArgs' - Configuration module for parsing commandline
arguments

SYNOPSIS
========

   This module is meant to help create useful configuration tools and
utilities.

DESCRIPTION
===========

   A tool to allow many of your computer's subsystems to be configured.
This module parses commandline arguments.  It is provided to help create a
standardized lexicon.

Scope controls and settings
---------------------------

   To specify how much of your system should be affected by the change in
settings:

     --scope=session|application|user|group|system

   In addition, each of the individual parts can specified (instead of
their defaults):

`--application='NAME
`--application 'NAME
     This specifies the application.

`--user='NAME
`--user 'NAME
     This specifies the user name.

`--group='NAME
`--group 'NAME
     This specifies the group name.

Operations on variables
-----------------------

   The specific operation to be done:

     --op=set|unset|remove|delete|exists|fetch|get|copy|rename

   or:

     --copy   name1=name2 name3=name4 ...
     --exists name1 name2 name3 ...
     --test   name1=value1 name2=value2 ...
             --unset  name1 name2 ...

`--delete 'NAME
`--delete='NAME
     This will remove the entry specified by NAME.  NAME may be a regular
     expression.

`--fetch 'NAME
`--fetch='NAME
     This will retrieve the information associated with NAME.  If NAME is a
     regular expression, information will retrieved for every entry that
     matches the pattern.

`--remove 'NAME
`--remove='NAME
     Like delete above, this will remove the entry specified by NAME.  NAME
     may be a regular expression.

`--rename' *NAME-NEW*=*NAME-OLD*
     This will change all of the occurrences or references that match
     *NAME-OLD* to the newer form of *NAME-NEW*.  This may be a regular
     expression, similar to;

          s/NAME-OLD/NAME-NEW/

`--set' NAME=VALUE
     This will create an entry called NAME with a setting of VALUE.

   The variable names are optional, and can be explicitly specified:

     --name

   Otherwise it is assumed to be the first no flag parameter.

   Similarly, the value can be specified

     --value

Other flags
-----------

`--file 'FILE
`--file='FILE
     This specifies the configuration file to employ.  If none is
     specified, the default for the particular subsystem will be used
     instead.

`--comment 'COMMENT
`--comment='COMMENT
     This provides a text comment on what changes are being made.

     -n,
     --dry-run,
     --just-print
     --recon

   With these flags, the utility program *should not modify any files*.
Instead, it should merely document what changes it would make, what
programs it would run, etc.

     --copyright
             --help
     --info
     --information
     --manual
     --verbose
     --version
             --warranty

Exit value
----------

   If the operation exists the return value is zero, otherwise it is
nonzero.

Return from parsing
-------------------

   The hash return:

     {
        SCOPE=> session,application,user,group,system
        OP  => COPY, RENAME, STORE, DELETE, FETCH, or EXISTS
        KEY =>
        VALUE=>
     }

AUTHOR
======

   Randall Maas (`mailto:randym@acm.org' in this node, `http:' in this
node)

An object to help interface to configuration files
**************************************************

NAME
====

   `CfgTie::Cfgfile' - An object to help interface to configuration files

SYNOPSIS
========

   Helps interface to the text based configuration files commonly used in
Unix

DESCRIPTION
===========

   This is a fairly generic interface to allow many configuration files to
be used as hash ties.  *Note: This is not intended to be called by user
programs, but by modules wishing to reuse a template structure!*

     package mytie;
     require CfgTie::Cfgfile;

     @ISA = qw(CfgTie::Cfgfile);

   The major methods:

   new(*$filepath*, *@Extra stuff*)

   or

   new(*$RCS-Object*, *@Extra stuff*)

filepath
     If defined, this is the path to the configuration file to be opened.

RCS-Object
     If defined, this is an RCS object (or similar) that will control how
     to check in and check out the configuration file.  See RCS Perl
     module for more details on how to create this object (do not use the
     same instance for each configuration file!).  Files will be checked
     back in when the END routine is called.  If a filepath is specified,
     it will override the one previously set with the RCS object.  If no
     filepath is specified, but the RCS has one specified, it will be used
     instead.

The derived object
------------------

   Your derived object may need to provide the following methods:

scan
     This is called when the file is first tied in.  It should scan the
     file, placing the associated contents into the `{Contents}' key.

format(key,*contents*)
     This formats a single entry to be stored in a file.  This is used for
     when a value can be stored simply.

`cfg_begin'
     If this method is defined, it is called just before the configuration
     file will be modified.

`cfg_end'
     If this method is defined, it is called after the configuration file
     has changed.  It can be used, for instances, to rebuild a binary
     database, restart a service, or email Martians.

`makerewrites'
     This is called just before the configuration file will be rewritten.
     It should return a reference to a function that is used to transform
     the current control file into the new one.  This transforming
     function is called for each line in the configuration file while it
     is being rewritten.

Object methods you can use
--------------------------

   `Comment_Add' This appends the string to the list of comments that will
be logged for this revision (assuming that a Revision Control object was
used).

   `Queue_Store($key,$val)' This queues (for later) the transaction that
key should be associated with val.  The queue is employed to synchronize
all of the settings with the stored settings on disk.

   `Queue_Delete($key)' This queues (for later) the transaction that any
value associated with key should be removed.

   `RENAME(\%rules)' This method will move through the whole table and
make a series of changes.  It may:

Remove some entries, based upon their keys
Rename the keys from some entries
Change the contents of the keys, possibly removing portions
   `\%rules' is the set of rules that governs will be changed in name and
what will be removed.  It is an associative array (hash) of a form like:

     {
         PATTERN1 => "",
         PATTERN2 => REWRITE,
     }

   `PATTERN1 = ' Two things will happen with a rule like this:

Every key in the table that matches the pattern will be removed
Any element (of an entry) that matches the pattern will be removed
   `PATTERN2 = REWRITE' In this case the rewrite indicates what should
replace the pattern:

   * Every key that matches the pattern will be rewritten and replace with
     a new key.

   * Any element (of an entry) that matches the pattern will be modified to
     match the rewrite rule.

See Also
========

   See CfgTie/TieAliases,   CfgTie/TieGeneric,
see CfgTie/TieGroup,
CfgTie/TieHost,      CfgTie/TieMTab,
see CfgTie/TieNamed,
CfgTie/TieNet,       CfgTie/TiePh,
 CfgTie/TieProto, CfgTie/TieRCService,
see CfgTie/TieRsrc,
CfgTie/TieServ, CfgTie/TieShadow,
see CfgTie/TieUser,

Caveats
=======

   Additions that do not change any previously established values are
reflected immediately (and `newaliases' is run as appropriate).  Anything
which changes a previously established value, regardless of whether or not
it has been committed, are queue'd for later.  This queue is used to
rewrite the file when END is executed.

Author
======

   Randall Maas (`mailto:randym@acm.org' in this node, `http:' in this
node)

an associative array of mail aliases to targets
***********************************************

NAME
====

   CfgTie::TieAliases - an associative array of mail aliases to targets

SYNOPSIS
========

   Makes it easy to manage the mail aliases (`/etc/aliases') table as a
hash.

     tie %mtie,'CfgTie::TieAliases'

     #Redirect mail for foo-man to root
     $mtie{'foo-man'}=['root'];

DESCRIPTION
===========

   This Perl module ties to the `/etc/aliases' file so that things can be
updated on the fly.  When you tie the hash, you are allowed an optional
parameter to specify what file to tie it to.

     tie %mtie,'CfgTie::TieAliases'

   or

     tie %mtie,'CfgTie::TieAliases',I<aliases-like-file>

   or

     tie %mtie,'CfgTie::TieAliases',I<revision-control-object>

Methods
-------

   `ImpGroups' will import the various groups from /etc/group using
`CfgTie::TieGroup'.  It allows an optional code reference to select which
groups get imported.  This code is passed a reference to each group and
needs to return nonzero if it is to be imported, or zero if it not to be
imported.  For example:

     (tied  %mtie)->ImpGroups
     	{
     	   my $T=shift;
     	   if ($T->{'id} < 100) {return 0;}
     	   return 1;
     	}

Format of the `/etc/aliases' file
---------------------------------

   The format of the `/etc/aliases' file is poorly documented.  The format
that `CfgTie::TieAliases' understands is documented as follows:

`#'comments
     Anything after a hash mark (`#') to the end of the line is treated as
     a comment, and ignored.

text:
     The letters, digits, dashes, and underscores before a colon are
     treated as the name of an alias.  The alias will be expanded to
     whatever is on the line after the colon.  (Each of those is in turn
     expanded).

`:include:'file
     Any element of the alias list that includes `:include:' indicates
     that the specified file should be read from.  The file may only
     specify user names or email addresses.  Several include directives
     may used in the aliase.  It is not clear which of these files is the
     preferred file to modify.

Continuation lines
     Any line that starts with a space is a continuation of the previous
     line.

Caveats
=======

   Not all changes to are immediately reflected to the specified file.
See the CfgTie/Cfgfile, module for more information

FILES
=====

   `/etc/aliases'

See Also
========

   See CfgTie/Cfgfile,    CfgTie/TieRCService,
see CfgTie/TieGeneric,
CfgTie/TieGroup, CfgTie/TieHost,
CfgTie/TieNamed,   CfgTie/TieNet,
see CfgTie/TiePh, CfgTie/TieProto,
see CfgTie/TieServ,
CfgTie/TieShadow, CfgTie/TieUser,

   `aliases(5)' in this node `newaliases(1)' in this node

Author
======

   Randall Maas (`randym@acm.org' in this node, `http:' in this node)

A generic hash that automatically binds others
**********************************************

NAME
====

   CfgTie::TieGeneric - A generic hash that automatically binds others

SYNOPSIS
========

   This is an associative array that automatially ties other configuration
hashes

DESCRIPTION
===========

   This is a tie to bring other ties together automatically so you, the
busy programmer and/or system administrator, don't have to.  The related
Perl module is not loaded unless it is needed at runtime.

     my %gen;
     tie %gen, 'CfgTie::TieGeneric';

Primary, or well-known, keys
----------------------------

env
     This refers directly to the ENV hash.

group
mail
     This is a special key.  It forms a hash, with subkeys.  See below for
     more information

`net'
     This is a special key.  It forms a hash with additional subkeys. See
     below for more details.

user
     This is a link to the `TieUser' module (see CfgTie/TieUser).

Composite
     Composite primary keys are just like absolute file paths.  For
     example, if you wanted to do something like this:

          my %lusers = $gen{'user'};
          my $Favorite_User = $lusers{'mygirl'};

     You could just do:

          my $Favorite_User = $gen{'/users/mygirl'};

others...
     These are the things automatically included in.  This will be
     described below.

Subkeys for mail
----------------

aliases
     See CfgTie/TieAliases,

Subkeys for `net'
-----------------

host
     See CfgTie/TieHost,

service
     See CfgTie/TieServ,

protocol
     See CfgTie/TieProto,

`addr'
     See CfgTie/TieNet,

How other ties are automatically bound
--------------------------------------

   Other keys are automatically (if it all possible) brought in using the
following procedure:

  1. If it is something already linked to it, that thingy is automatically
     returned (of course).

  2. If the key is simple, like `AABot', we will try to `use AABot;' If
     that works we will tie it and return the results.

  3. If the key is more complex, like `/OS3/Config', we will try to see if
     `OS3' is already tied (and try to tie it, like above, if not).  If
     that works, we will just look up Config in that hash.  If it does not
     work, we will try to use and tie `OS3::Config', `OS3::TieConfig', and
     `OS3::ConfigTie'.  If any of those work, we return the results.

  4. Otherwise, undef will be returned.

See Also
========

   See CfgTie/TieAliases, CfgTie/TieGroup,
see CfgTie/TieHost,
CfgTie/TieMTab,    CfgTie/TieNamed,
see CfgTie/TieNet, CfgTie/TiePh,
see CfgTie/TieProto,
CfgTie/TieRCService, CfgTie/TieRsrc,
see CfgTie/TieServ,
CfgTie/TieShadow, CfgTie/TieUser,

Author
======

   Randall Maas (`mailto:randym@acm.org' in this node, `http:' in this
node)

an associative array of group names and ids to information
**********************************************************

NAME
====

   CfgTie::TieGroup - an associative array of group names and ids to
information

SYNOPSIS
========

   Makes the groups database available as regular hash

     tie %group,'CfgTie::TieGroup'
     $group{'myfriends'}=['jonj', @{$group{'myfriends'}];

   or

     tie %group,'CfgTie::TieGroup', 'mygroupfile'

DESCRIPTION
===========

   This is a straight forward hash tie that allows us to access the user
group database sanely.

   It cross ties with the user package and the mail packages

Ties
----

   There are two ties available for programmers:

`tie %group,'CfgTie::TieGroup''
     `$group{$name}' will return a hash reference of the named group
     information.

`tie %group_id,'CfgTie::Group_id''
     `$group_id{$id}' will return a HASH reference for the specified group.

Structure of hash
-----------------

   Any given group entry has the following information assoicated with it:

name
id
members
     A list reference to all of the users that are part of this group.

`_members'
     A list reference to all of the users that are explicitly listed in the
     /etc/group file.

   Plus an (probably) obsolete fields:

Password
     This is the encrypted password, but will probably be obsolete.

   Each of these entries can be modified (even deleted), and they will be
reflected in the overall system.  Additionally, the programmer can set any
other associated key, but this information will only be available to a
running Perl script.

Additional Routines
-------------------

`(tied %MyHash)-'files()>
     Returns a list of files employed.

`&CfgTie::TieGroup'status()'
`&CfgTie::TieGroup_id'status()'
     Will return stat information on the group database.

Miscellaneous
-------------

   `$CfgTie::TieGroup_rec'groupmod' contains the path to the program
`groupmod'.  This can be modified as required.

   `$CfgTie::TieGroup_rec'groupadd' contains the path to the program
`groupadd'.  This can be modified as required.

   `$CfgTie::TieGroup_rec'groupdel' contains the path to the program
`groupdel'.  This can be modified as required.

Files
=====

   `/etc/passwd' /etc/group `/etc/gshadow' `/etc/shadow'

See Also
========

   See CfgTie/Cfgfile,      CfgTie/TieAliases,
see CfgTie/TieGeneric,
CfgTie/TieHost,      CfgTie/TieMTab,
see CfgTie/TieNamed,
CfgTie/TieNet,       CfgTie/TiePh,
 CfgTie/TieProto, CfgTie/TieRCService,
see CfgTie/TieRsrc,
CfgTie/TieServ, CfgTie/TieShadow,
see CfgTie/TieUser,

   `group(5)' in this node, `passwd(5)' in this node, `shadow(5)' in this
node, `groupmod(8)' in this node, `groupadd(8)' in this node,
`groupdel(8)' in this node

Caveats
=======

   The current version does cache some group information.

Author
======

   Randall Maas (`mailto:randym@acm.org' in this node, `http:' in this
node)

This accesses the hosts tables.
*******************************

NAME
====

   `CfgTie::TieHost' - This accesses the hosts tables.

SYNOPSIS
========

   This is an associative array that allows the hosts tables to be
configured easily.

     tie %host,'CfgTie::TieHost';

DESCRIPTION
===========

   This is a straightforward hash tie that allows us to access the host
database sanely.

Ties
----

   There are two ties available for programmers:

`tie %host,'CfgTie::TieHost''
     `$host{$name}' will return a hash reference of the named host
     information.

`tie %host_addr,'CfgTie::TieHost_addr''
     `$host_addr{$addr}' will return a hash reference for the specified
     host.

Structure of hash
-----------------

   Any given host entry has the following information assoicated with it:

Name
     Host name

Aliases
     Other names for this host

`AddrType'
     The type of address

Length
`Addrs'
     A list reference of addresses.  You will need something like

          ($a,$b,$c,$d) = unpack('C4',$Addr);

     to get the address out sanely.

   Additionally, the programmer can set any other associated key, but this
information will only be available to a running Perl script.

See Also
========

   See CfgTie/TieAliases, CfgTie/TieGeneric,
see CfgTie/TieGroup,
CfgTie/TieMTab,    CfgTie/TieNamed,
see CfgTie/TieNet,
CfgTie/TiePh,      CfgTie/TieProto,
 CfgTie/TieRCService, CfgTie/TieRsrc,
see CfgTie/TieServ,
CfgTie/TieShadow, CfgTie/TieUser,

   `host(5)' in this node

Caveats
=======

   The current version does cache some host information.

Author
======

   Randall Maas (`mailto:randym@acm.org' in this node, `http:' in this
node)

an associative array of mount entries
*************************************

NAME
====

   `CfgTie::TieMTab' - an associative array of mount entries

SYNOPSIS
========

   makes the mount table available as a regular hash:

     tie %MTab, 'CfgTie::TieMTab';
     tie %MTab, 'CfgTie::TieMTab_dev';

DESCRIPTION
===========

   The keys are path and devices.

   The values are always list references.  The lists are one of two forms.
For local path, the list is of the form:

     [$device, $path, $type, $options]

   Other paths not in the mount table are of the form

     [$device]

   The form of device varies from system to system.  It is usually the
device specified in the mount table.  NFS and other network mounts are of
the form *host:path*.  `amd' devices are different, and (at the time of
this writing) their form isn't known.

Caveats
=======

   This requires Quota to work.  You can get it from CPAN.

Files
=====

`/etc/mtab'
     (on many machines)

`/proc/mounts'
     (on Linux machines)

See Also
========

   `Quota::' in this node

Author
======

   Randall Maas (`mailto:randym@acm.org' in this node, `http:' in this
node)

A tool to help configure the name daemon (BIND DNS server)
**********************************************************

NAME
====

   `CfgTie::TieNamed' - A tool to help configure the name daemon (BIND DNS
server)

SYNOPSIS
========

   This is a PERL module to help make it easy to configure the DNS name
server

DESCRIPTION
===========

   This is a tie hash to the NAMED configuration files.  You use it as
follows:

     tie %named, 'CfgTie::TieNamed','/path/to/named.boot';
     $named = CfgTie::TieNamed->new('/path/to/named.boot');

   These will set up a hash (*named*) to the named configuration files.
It will used the specified `named.boot' file.

     tie %named, 'CfgTie::TieNamed';
     $named = CfgTie::TieNamed->new();

   These will set up a hash (*named*) to the named configuration files.
The files will be automatically determined from the system startup scripts.

Examples
--------

   Lets say you would like to name a bunch of machines (like modems) with
a base name and a number.  The number part needs to be the same as the
same as the last number in the IP address.  You know these go in a domain
like, "wikstrom.pilec.rm.net" which is a zone for your name server:

     tie %DNS, 'CfgTie::TieNamed';
     my $Tbl = $DNS->{'primary'}->{'wikstrom.pilec.rm.net'};
     my $N=10; #Ten modems;
     my $prefix="usr2-port";
     my $ip_start=11;
     for (my $i = 0; $i < $N; $i++)
     {
        #Insert the address record in the table
        $Tbl->{$prefix.$i}->{'A'} = "127.221.19.".($i+$ip_start);
     }

     #Finally make sure that the reverse name space is up to date
     (tied %DNS)->RevXRef('wikstrom.pilec.rm.net','19.221.127.in-addr.arpa');

   Even the address to name mapping will be kept up to date.

The basic structure of the named configuration table
----------------------------------------------------

`bogusns'
     A list of name server addresses to ignore.

cache
     See `named(8)' in this node for a description

`check-names'
directory
     This specifies the working directory of the `named' server, and is
     used in determining the location of the associated files.

`forwarders'
     A list of other servers' addresses on the site that can be used for
     recursive look up.

limit
     Controls operational parameters of the `named' server.  See below.

options
     The list of options the `named' server should adhere to.

`primary'
     This maps to a an associative array of name spaces we are primary
     for.  See below for more details on this is handled.

`secondary'
     This maps to a an associative array of name spaces we are secondary
     for.

`sortlist'
     See `named(8)' in this node for a description

`xfrnets'
     The list of networks which are allowed to request zone transfers.  If
     not present, all hosts on all networks are.

   Others may be set as well, but they are for backwards compatibility and
should be changed to the more appopriate form.  See `named(8)' in this
node for more information.

Extra methods for the configuration table
-----------------------------------------

   These are various methods you can use.  Of course, you will need an
object reference you can use for the remaining methods.  Note that if you
tied the variable, you will want to use code sorta like: `my $Obj = tied
%CfgTie::TieNamed;'

   `RevSpaces' Is the list of the reverses addresses spaces that the
server is primary for (except loopback)

   `FwdSpaces' Is the list of name spaces the server is primary for
(except the loopback and reverse name spaces)

   `RevXRef($'*fwd*`,$'rev) This will check that reverse look up is up to
date with the primary look up.  It will add reverse entries as appropriate
(if there is one missing, or the value is correct).  It will not change a
reverse entry if there are multiple names with the same address entry.
rev is optional, but this method will return (with a 0) if it is not
specified and there is more than one reverse name space.  *fwd* is
optional, but this method will return (with a 0) if it is not specified
and there is more than one primary name space.  Returns the number of
entries changed or added.

   Note: This also derives any other methods from the `CfgTie::Cfgfile'
module (see CfgTie/Cfgfile).

The basic structure of a primary name space table
-------------------------------------------------

   The `$named-'>`{primary}' entry refers to a associative arrays.  The
keys are the domain names that are to be server.  ie,

     my %mydom = $name->{primary}->{'mydomain.com'};

   These associations in turn refer to a table of names and their
respective attributes.  The keys to this table are the machine names.

   The values associated keys are hash references to domain name records.
This in turn refers to another (confused yet?) associative array.  The
keys of this table are the DNS attribute names.  The values associated
with the key are list references, usually a set of possible values for the
given attribute and name pair.  The most common ones are:

A
     This is a list reference to all of the physical addresses the given
     machine name has.

NS
     This is a list reference to all of the servers that can serve as
     domain name servers.

CNAME
     This is a list reference to all of the real names the given machine
     name has.

SOA
     Has a list reference with the following structure `HOSTDATAFROM
     MAILADDR SERIAL REFRESH RETRY EXPIRE MinTTL' The Serial number is
     automatically updated for each table that is changed.  The format is
     guessed (from various date formats include YYYYMMDD, YYYYDDD, and
     others), and properly incremented or set.

PTR
     This is a list reference to the real name of a given machines address.

`TXT'
     Each element of this list refers to a string describing the domain or
     name.

`WKS'
`HINFO'
Extra methods table
-------------------

   `DblLinks' This looks for entries with both a A and a CNAME entry.
*Keep* controls whether to keep the A or the CNAME entry; the default is
to keep the A entry (and delete the CNAME entry).  Returns a count of all
the records that were modified.

   Note: This also derives any other methods from the `CfgTie::Cfgfile'
module (see CfgTie/Cfgfile).

See Also
========

   See CfgTie/Cfgfile, CfgTie/TieAliases,
see CfgTie/TieGeneric,
CfgTie/TieGroup, CfgTie/TieHost,
 CfgTie/TieMTab,      CfgTie/TieNet,
see CfgTie/TiePh, CfgTie/TieProto,
see CfgTie/TieRCService,
CfgTie/TieRsrc,< CfgTie/TieServ,
CfgTie/TieShadow,  CfgTie/TieUser,

Cavaets
=======

   Much of the information is cached and the file is updated at the end.
The `named' process will sent the `SIGHUP' signal to restart and reload the
configuration files.

   The reverse name file can not be automatically created... Only modified.

   The SOA records in the named configuration files are not easy to change.

   Changing the file name or directory currently does not move the files
in the file system

Author
======

   Randall Maas (`randym@acm.org' in this node)

A module to tie in the net database
***********************************

NAME
====

   CfgTie::TieNet - A module to tie in the net database

SYNOPSIS
========

     tie %net,'CfgTie::TieNet'

DESCRIPTION
===========

   This is a straightforward hash tie that allows us to access the net
database sanely.

Ties
----

   There are two ties available for programmers:

`tie %net,'CfgTie::TieNet''
     `$net{$name}' will return a hash reference of the named net
     information

`tie %net_addr,'CfgTIe::TieNet_addr''
     `$net_addr{$addr}' will return a hash reference for the specified
     network address.

Structure of hash
-----------------

   Any given net entry has the following information assoicated with it:

Name
     net name

Aliases
     A list reference for other names for this net

`AddrType'
     The type of address

Addr
     The address

   Additionally, the programmer can set any other associated key, but this
information will only available to the running Perl script.

See Also
========

   See CfgTie/Cfgfile, CfgTie/TieAliases,
see CfgTie/TieGeneric,
CfgTie/TieGroup, CfgTie/TieHost,
 CfgTie/TieNamed,   CfgTie/TiePh,
see CfgTie/TieProto,
CfgTie/TieServ,    CfgTie/TieShadow,
see CfgTie/TieUser,

Caveats
=======

   The current version does cache some net information.

Author
======

   Randall Maas (`randym@acm.org' in this node)

a ph phonebook server configuration tool
****************************************

NAME
====

   `CfgTie::TiePh' - a ph phonebook server configuration tool

SYNOPSIS
========

   Makes it easy to manage the ph phonebook server configuration files as
a hash.

     tie %myhash, 'ph'

     %myhash{who}->{Person}

DESCRIPTION
===========

   This is a file to help configure the `ph' program.

     tie %myhash, 'ph'

     %myhash{who}->{Person}
     %myhash{who}->{Phone}

Methods
-------

   This inherits any methods from the `CfgTie::Cfgfile' module (see
CfgTie/Cfgfile)

See Also
========

   See CfgTie/Cfgfile,   CfgTie/TieAliases,
see CfgTie/TieGeneric,
CfgTie/TieGroup,  CfgTie/TieHost,
  CfgTie/TieMTab, CfgTie/TieNamed,
see CfgTie/TieNet,
CfgTie/TiePh, CfgTie/TieProto,
CfgTie/TieRCService, CfgTie/TieRsrc,
see CfgTie/TieServ,
CfgTie/TieShadow, CfgTie/TieUser,

Author
======

   Randall Maas (`randym@acm.org' in this node, `http:' in this node)

Ties the protocol number file to a  PERL hash
*********************************************

NAME
====

   CfgTie::TieProto, CfgTie::TieProto_num - Ties the protocol number file
to a  PERL hash

SYNOPSIS
========

     tie %proto, 'CfgTie::TieProto';
     print $proto{'tcp'};

DESCRIPTION
===========

   This is a straightforward hash tie that allows us to access the protocol
number database sanely.

Ties
----

   There are two ties available for programmers:

`tie %proto,'CfgTie::TieProto''
     `$proto{$name}' will return a hash reference of the named protocol
     information

`tie %proto_num,'CfgTie::TieProto_num''
     `$proto_num{$num}' will return a hash reference for the specified
     protocol number.

Structure of hash
-----------------

   Any given proto entry has the following information assoicated with it:

Name
     proto name

Aliases
     A list reference for other names for this proto

Number
     The protocol number

   Additionally, the programmer can set any other associated key, but this
information will only be available to the running Perl script.

See Also
========

   See CfgTie/Cfgfile, CfgTie/TieAliases,
see CfgTie/TieGeneric,
CfgTie/TieGroup,   CfgTie/TieHost,
see CfgTie/TieNamed,
CfgTie/TieNet,     CfgTie/TiePh,
CfgTie/TieProto, CfgTie/TieServ,
see CfgTie/TieShadow,
CfgTie/TieUser,

Caveats
=======

   The current version does cache some proto information.

Author
======

   Randall Maas (`randym@acm.org' in this node)

A module to manage Unix services
********************************

NAME
====

   CfgTie::TieRCService - A module to manage Unix services

SYNOPSIS
========

     my %RC;
     tie %RC, 'CfgTie::TieRCService';

DESCRIPTION
===========

   This is a straightforward interface to the control scripts in
@file{/etc/rc?.d} This package helps manage these system services.  The
tie hash is structured like so:

     {
         $Service_Name => $Service_Ref,
     }

   `$Service_Ref' is a hash reference; the details will be covered in the
next section.  `(tied $Service_Ref)' can also be treated as an object to
control the service.  That is covered in the Service Methods section.

   While fetching from the structure, and deleting services is supported
(and reflected to the system), directly storing new services is not.
Currently the method to do this is:

     (tied %RC)->add('mynewservice');

   This will add the new service (to be managed as well as available) to
the run-levels.  The start and kill scripts will be linked into each
appropriate run-level.  The script should already exist (in the proper
format) in `/etc/rc.d/init.d' or equivalent.

The Service hash reference
--------------------------

     {
        levels   => [],
        defaults => [],
        category => [],
        pid  => $pid,
        path =>,
        description =>,
        start_priority=>,
        stop_priority =>,
     }

   `levels' refers to a list used to determine if the service is present
for a given run-level.  The scope of changes this list is *system-wide*.
It is persistent across boots.  Example:

   my $listref = (tied %{$RC{'atd'}})->levels();

     if ($L < scalar @{$listref} && $listref->[$L])
       {print "present at run level $L\n";}

Service Methods
---------------

   `new($service_name,$path)' path is optional, and may refer either to the
folder containing the relevant control script, or may refer to the control
script itself.

   start  will start the service (if not already started).  The scope of
this action is *system-wide*.  Example: `$Obj-'>start();

   stop will stop the service (if running).  The scope of this action is
*system-wide*.  Example: `$Obj-'>`stop();'

   restart will restart the service, effectively stopping it (if it is
running) and then starting it.  The scope of this action is *system-wide*.
Example: `$Obj-'>`restart();'

   status The scope of this action is limited to a single session.

   reload The scope of this action is *system-wide*.

Caveats
=======

   This can not create a new service start/kill script.  At best this can
only modify an existing one, or link it into the init folders.

BUGS
====

   Requires `/sbin/chkconfig' to work.

Author
======

   Randall Maas (`randym@acm.org' in this node)

Ties configuration variables to various HTTP servers
****************************************************

NAME
====

   `CfgTie::TieRealm' - Ties configuration variables to various HTTP
servers

SYNOPSIS
========

   Makes it easy to manage a variety of web servers thru one.

Cavaets
=======

   It is not able to modify the main realms configuration file.

Author
======

   Randall Maas (`randym@acm.org' in this node, `http:' in this node)

an associative array of resources and their usage limits
********************************************************

NAME
====

   CfgTie::TieRsrc - an associative array of resources and their usage
limits

SYNOPSIS
========

   This module makes the resource limits available as a regular hash

     tie %Resources,'CfgTie::TieRsrc'

DESCRIPTION
===========

   This is a straightforward hash tie that allows us to access the user
database sanely.

   The resource limits for the system.  Note: this requires that
`BSD::Resource' be installed.

   It is a hash reference.  The keys may be any of cpu, data, stack,
`core', rss, `memlock', `nproc', `nofile', `open_max', `as', `vmem',
`nlimits', `infinity'.  The values are always list references of the form:

     [$soft, $hard]

See Also
========

   See CfgTie/Cfgfile, CfgTie/TieAliases,
see CfgTie/TieGeneric,
CfgTie/TieGroup,CfgTie/TieHost,
 CfgTie/TieMTab, CfgTie/TieNamed,
see CfgTie/TieNet,
CfgTie/TiePh, CfgTie/TieProto,
CfgTie/TieRCService,CfgTie/TieServ,
see CfgTie/TieShadow,

Author
======

   Randall Maas (`randym@acm.org' in this node)

A HASH tie that allows access the service port database
*******************************************************

NAME
====

   CfgTie::TieServ - A HASH tie that allows access the service port
database

SYNOPSIS
========

     tie %serv,'CfgTie::TieServ';
     print $serv{'smtp'};

DESCRIPTION
===========

   This is a straight forward HASH tie that allows us to access the service
port database sanely.

Ties
----

   There are two ties available for programers:

`tie %serv,'CfgTie::TieServ''
     `$serv{$name}' will return a HASH reference of the named service
     information

`tie %serv_port,'CfgTie::TieServ_port''
     `$serv_port{$port}' will return a HASH reference for the specified
     service port.

Structure of hash
-----------------

   Any given serv entry has the following information assoicated with it:

Name
     Service name

Aliases
     A list reference for other names for this service

Port
     The port number

`Protocol'
     The protocol name

   Additionally, the programmer can set any other associated key, but this
information will only available to running PERL script.

See Also
========

   See CfgTie/Cfgfile,  CfgTie/TieAliases,
see CfgTie/TieGeneric,
CfgTie/TieGroup, CfgTie/TieHost,
CfgTie/TieNamed, CfgTie/TieNet,
see CfgTie/TiePh,
CfgTie/TieProto, CfgTie/TieShadow,
see CfgTie/TieUser,

Cavaets
=======

   The current version does cache some service information.

Author
======

   Randall Maas (`randym@acm.org' in this node)

an associative array of user names to password information
**********************************************************

NAME
====

   CfgTie::TieShadow - an associative array of user names to password
information

SYNOPSIS
========

   This module makes the shadow database available as a regular hash.

DESCRIPTION
===========

   This is a straightforward hash tie that allows us to access the shadow
password database sanely.

Ties
----

   This tie is available for programmers:

   `tie %shadow,'CfgTie::TieShadow''

   `$shadow{$name}' will return a hash reference of the named shadow
information

Structure of hash
-----------------

   Any given shadow entry has the following information associated with it
(the keys are case-insensitive):

Name
     Login name

Password
     The encrypted password

Last
     Last time it was changed

`Min'
     The minimum number of days before a change is allowed

`Max'
     Maximum number of days before a change in passwords is required

`Warn'
     The number of days before expiration that they will receive a warning

`Inactive'
     The number of days before an account is inactive

`Expires'
     The date the account expires on

`Inactive'
     The number of days after a password expires that the account is
     considered inactive and expires

   Each of these entries can be modified (even deleted), and they will be
reflected in the overall system.  Additionally, the programmer can set any
other associated key, but this information will only available to the
running Perl script.

Additional Routines
-------------------

`&CfgTie::TieShadow'status()'
`&CfgTie::TieShadow_id'status()'
     Will return stat information on the shadow database.

Miscellaneous
-------------

   `$CfgTie::Tiehadow_rec'usermod' contains the path to the program
`usermod'.  This can be modified as required.

   `$CfgTie::TieShadow_rec'useradd' contains the path to the program
`useradd'.  This can be modified as required.

   `$CfgTie::TieShadow_rec'userdel' contains the path to the program
`userdel'.  This can be modified as required.

Files
=====

   `/etc/passwd' /etc/group `/etc/shadow'

See Also
========

   See CfgTie/Cfgfile,  CfgTie/TieAliases,
see CfgTie/TieGeneric,
CfgTie/TieGroup, CfgTie/TieHost,
CfgTie/TieNamed,  CfgTie/TieNet,
see CfgTie/TiePh,
CfgTie/TieProto,  CfgTie/TieServ,
CfgTie/TieShadow, CfgTie/TieUser,

   `group(5)' in this node, `passwd(5)' in this node, `shadow(5)' in this
node, `usermod(8)' in this node, `useradd(8)' in this node, `userdel(8)'
in this node

Caveats
=======

   The current version does cache some shadow information.

Author
======

   Randall Maas (`randym@acm.org' in this node)

an associative array of user names and ids to information
*********************************************************

NAME
====

   CfgTie::TieUser - an associative array of user names and ids to
information

SYNOPSIS
========

   makes the user database available as a regular hash.

     tie %user,'CfgTie::TieUser'
     print "randym's full name: ", $user{'randym'}->{gcos}, "\n";

DESCRIPTION
===========

   This is a straightforward hash tie that allows us to access the user
database sanely.

   It cross ties with the groups packages and the mail packages

Ties
----

   There are two ties available for programmers:

`tie %user,'CfgTie::TieUser''
     `$user{$name}' will return a hash reference of the named user
     information.

`tie %user_id,'CfgTie::TieUser_id''
     `$user_id{$id}' will return a hash reference for the specified user.

Structure of hash
-----------------

   Any given user entry has the following information associated with it
(the keys are case-insensitive):

Name
     Login name

`GroupId'
     The principle group the user belongs to.

Id
     The user id number that they have been assigned.  It is possible for
     many different user names to be given the same id.  However, changing
     the id for the user (i.e., setting it to a new one) has one of two
     effects.  If `user'Chg_FS' is set 1, then all the files in the system
     owned by that id will changed to the new id in addition to changing
     the id in the system table.  Otherwise, only the system table will be
     modified.

Comment
`Home'
     The user's home folder

`LOGIN_Last'
     This is the information from the last time the user logged in.  It is
     an array reference to data like:

          [$time, $line, $from_host]

Shell
     The user's shell

`AuthMethod'
     The authentication method if other than the default.  (Note: This can
     be set, but currently can't get fetched.)

`ExpireDate'
     The date the account expires on.  (Note: this can be set, but
     currently can't be fetched.)

`Inactive'
     The number of days after a password expires.  (Note: this can be set,
     but currently can't be fetched.)

`Priority'
     The scheduling priority for that user.  (Note: this requires that
     `BSD::Resource' be installed.)

Quota
`RUsage'
     The process resource consumption by the user.  Note: This requires
     that `BSD::Resource' be installed.

     Returns a list reference of the form:

          [$usertime, $systemtime, $maxrss,  $ixrss,   $idrss,  $isrss,  $minflt,
           $majflt,   $nswap,      $inblock, $oublock, $msgsnd, $msgrcv, $nsignals,
           $nvcsw, $nivcsw]

   Plus two (probably) obsolete fields:

Password
     This is the encrypted password, but will probably be obsolete.

`GCOS'
     *General Electric Comprehensive Operating System* or *General
     Comprehensive Operating System* field

     This is now the user's full name under many Unix's, incl. Linux.

   Each of these entries can be modified (even deleted), and they will be
reflected in the overall system.  Additionally, the programmer can set any
other associated key, but this information will only be available to the
running Perl script.

Configuration Variables
-----------------------

Additional Routines
-------------------

`&CfgTie::TieUser'stat()'
`&CfgTie::TieUser_id'stat()'
     Will return stat-like statistics information on the user database.

Adding or overiding methods for user records
--------------------------------------------

   Lets say you wanted to change the default HTML handling to a different
method.  To do this you need only include code like the following:

     package CfgTie::TieUser_rec;
     sub HTML($)
     {
        my $self=shift;
        "<h1>".$Self->{name}."</h1>\n".
        "<table border=0><tr><th align=right>\n".
          join("</td></tr>\n<tr><th align=right>",
            map {$_."</th><td>".$self->{$_}} (sort keys %{$self})
         </td></tr><lt></table>C<\n>";
     }

   If, instead, you wanted to add your own keys to the user records,
`CfgTie::TieUser::add_scalar('*$Name*,*$Package*) Lets you add scalar keys
to user records.  The Name specifies the key name to be used; it will be
made case-insensitve.  The Package specifies the name of the package to be
used when tie'ing the key to a value.  (The TIESCALAR is passed the user
id as a parameter).

   `CfgTie::TieUser::add_hash('*$Name*,*$Package*) Lets you add hash keys
to user records.  The Name specifies the key name to be used; it will be
made case insensitve.  The Package specifies the name of the package to be
used when tie'ing the key to a value.  (The TIEHASH is passed the user id
as a parameter).

Miscellaneous
-------------

   `$CfgTie::TieUser_rec'usermod' contains the path to the program
`usermod'.  This can be modified as required.

   `$CfgTie::TieUser_rec'useradd' contains the path to the program
`useradd'.  This can be modified as required.

   `$CfgTie::TieUser_rec'userdel' contains the path to the program
`userdel'.  This can be modified as required.

   Not all keys are supported on all systems.

   This may transparently use a shadow tie in the future.

When the changes are reflected to /etc/passwd
---------------------------------------------

Files
=====

   `/etc/passwd' /etc/group `/etc/shadow'

See Also
========

   See CfgTie/Cfgfile, CfgTie/TieAliases,
see CfgTie/TieGeneric,
CfgTie/TieGroup,CfgTie/TieHost,
 CfgTie/TieMTab, CfgTie/TieNamed,
see CfgTie/TieNet,
CfgTie/TiePh, CfgTie/TieProto,
CfgTie/TieRCService,CfgTie/TieRsrc,
see CfgTie/TieServ,
CfgTie/TieShadow,

   `group(5)' in this node, `passwd(5)' in this node, `shadow(5)' in this
node, `usermod(8)' in this node, `useradd(8)' in this node, `userdel(8)'
in this node

Caveats
=======

   The current version does cache some user information.

Author
======

   Randall Maas (`randym@acm.org' in this node)

a simple module for substituting newer versions into a file system.
*******************************************************************

NAME
====

   CfgTie::filever - a simple module for substituting newer versions into
a file system.

SYNOPSIS
========

   This module allows a newer version of file to be safely placed into the
file system.

DESCRIPTION
===========

   This is a set of utilities for manipulating files.

`File's_Rotate' (*$Old, $New*)
------------------------------

   This is the file space equivalent to the variable exchange or swap.  The
old file will be renamed (with a .old extension) and the new file will be
renamed to old.  This is extremely useful for many semi-critical
functions, where modifying the file directly will cause unpredictable
results.  Instead, the preferred method is to modify old sending the
results to new in the background and then doing a *very* quick switcheroo.

   It preserves the permissions and ownership of the original file.

   If this routine fails, it will make an attempt to restore things to
their original state and return.

   *Return Value*: 0 on success, -1 on error;

`Roll('path,depth,*sep*)
------------------------

   This convert the specified files into a backup file (the original file
is renamed, so you had better have something to put there).

Depth
     (optional) Controlls the number of backup copies

Sep
     (optional) Controlls the seperator between the main name and the
     backup number

   The defaults for depth and *sep* are controlled by following two
variables in the package:

`RollDepth'
     Controlls the number of of older versions that are kept around as
     backup copies.  *[Default: 4]*

`RollSep'
     Controls the separator between the file name and the backup number.
     *[Default: *`~']

`RCS_path ('*RCSObj*,path)
--------------------------

   For the given RCS object, this sets the working directory and the file.

find_by_user
------------

   This function attempts to locate all of the files in the system that
are owned by the specified users.  It takes the following parameters:

Base
     Base can be a string to the base path or a reference to a list of base
     paths to search.

   Return Value:

undef if there was an error
otherwise the list of file that matched
Author
======

   Randall Maas (`randym@acm.org' in this node, `http:' in this node)

a series of charting modules
****************************

NAME
====

   Chart - a series of charting modules

SYNOPSIS
========

     use Chart::type;

     $obj = Chart::type->new;
     $obj = Chart::type->new ( $gif_width, $gif_height );

     $obj->set ( $key_1, $val_1, ... ,$key_n, $val_n );
     $obj->set ( $key_1 => $val_1,
     	        ...
     	        $key_n => $val_n );
     $obj->set ( %hash );

     # GIFgraph.pm-style API
     @data = ( \@x_tick_labels, \@dataset1, ... , \@dataset_n );
     $obj->gif ( "filename", \@data );
     $obj->gif ( $filehandle, \@data );
     $obj->gif ( FILEHANDLE, \@data );
     $obj->cgi_gif ( \@data );

     # Graph.pm-style API
     $obj->add_pt ($label, $val_1, ... , $val_n);
     $obj->add_dataset ($val_1, ... , $val_n);
     $obj->gif ( "filename" );
     $obj->gif ( $filehandle );
     $obj->gif ( FILEHANDLE );
     $obj->cgi_gif ();

     # Retrieve imagemap information
     $obj->set ( 'imagemap' => 'true' );
     $imagemap_ref = $obj->imagemap_dump ();

DESCRIPTION
===========

   This module is an attempt to build a general purpose graphing module
that is easily modified and expanded.  I borrowed most of the API from
Martien Verbruggen's GIFgraph module.  I liked most of GIFgraph, but I
thought it was to difficult to modify, and it was missing a few things
that I needed, most notably legends.  So I decided to write a new module
from scratch, and I've designed it from the bottom up to be easy to
modify.  Like GIFgraph, Chart uses Lincoln Stein's GD module for all of
its graphics primitives calls.

use-ing Chart
-------------

   Okay, so you caught me.  There's really no Chart::type module.  All of
the different chart types (Points, Lines, Bars, LinesPoints, Pie,
Composite, StackedBars, and Pareto so far) are classes by themselves, each
inheriting a bunch of methods from the Chart::Base class.  Simply replace
the word type with the type of chart you want and you're on your way.  For
example,

   use Chart::Lines;

   would invoke the lines module.

Getting an object
-----------------

   The new method can either be called without arguments, in which case it
returns an object with the default image size (400x300 pixels), or you can
specify the width and height of the image.  Just remember to replace type
with the type of graph you want.  For example,

     $obj = Chart::Bars (600,400);

   would return a Chart::Bars object containing a 600x400 pixel image.
New also initializes most of the default variables, which you can
subsequently change with the set method.

Setting different options
-------------------------

   This is where the fun begins.  Set looks for a hash of keys and values.
You can pass it a hash that you've already constructed, like

     %hash = ('title' => 'Foo Bar');
     $obj->set (%hash);

     or you can try just constructing the hash inside the set call, like

     $obj->set ('title' => 'Foo Bar');

   The following are all of the currently supported options:

'transparent'
     Makes the background of the image transparent if set to 'true'.
     Useful for making web page images.  Default is 'false'.

'gif_border'
     Sets the number of pixels used as a border between the graph and the
     edges of the gif.  Defaults to 10.

'graph_border'
     Sets the number of pixels used as a border between the title/labels
     and the actual graph within the gif.  Defaults to 10.

'text_space'
     Sets the amount of space left on the sides of text, to make it more
     readable.  Defaults to 2.

'title'
     Tells GD graph what to use for the title of the graph.  If empty, no
     title is drawn.  It recognizes '\n' as a newline, and acts
     accordingly.  Default is empty.

'sub_title'
     Deprecated, left in for backwards-compatibility.  This option will
     probably be taken out of the next release.

'x_label'
     Tells Chart what to use for the x-axis label.  If empty, no label is
     drawn.  Default is empty.

'y_label', 'y_label2'
     Tells Chart what to use for the y-axis labels.  If empty, no label is
     drawn.  Default is empty.

'legend'
     Specifies the placement of the legend.  Valid values are 'left',
     'right', 'top', 'bottom'.  Setting this to 'none' tells chart not to
     draw a legend.  Default is 'right'.

'legend_labels'
     Sets the values for the labels for the different datasets.  Should be
     assigned a reference to an array of labels.  For example,

     @labels = ('foo', 'bar');   $obj->set ('legend_labels' => \@labels);

     Default is empty, in which case 'Dataset 1', 'Dataset 2', etc. are
     used as the labels.

     For a pareto graph, the first value should be the name of the set, and
     the second should be the name of the running sum of the values.

     For a pie graph, this option is ignored, as the values for the legend
     are taken from the array of data point labels.

'tick_len'
     Sets the length of the x- and y-ticks in pixels.  Default is 4.

'x_ticks'
     Specifies how to draw the x-tick labels.  Valid values are 'normal',
     'staggered' (staggers the labels vertically), and 'vertical' (the
     labels are draw upwards).  Default is 'normal'.

'y_ticks'
     Sets the number of y_ticks to draw.  Default is 6.

'max_val'
     Sets the maximum y-value on the graph, overriding the normal
     auto-scaling.  Default is undef.

'min_val'
     Sets the minimum y-value on the graph, overriding the normal
     auto-scaling.  Default is undef.

'pt_size'
     Sets the radius of the points (for Chart::Points, etc.) in pixels.
     Default is 18.

'brush_size'
     Sets the width of the lines (for Chart::Lines, etc.) in pixels.
     Default is 6.

'skip_x_ticks'
     Sets the number of x-ticks and x-tick labels to skip.  (ie.  if
     'skip_x_ticks' was set to 4, Chart would draw every 4th x-tick and
     x-tick label).  Default is undef.

'custom_x_ticks'
     Used in points, lines, linespoints, and bars charts, this option
     allows you to specify exatly which x-ticks and x-tick labels should
     be drawn.  It should be assigned a reference to an array of desired
     ticks.  Just remember that I'm counting from the 0th element of the
     array.  (ie., if 'custom_x_ticks' is assigned [0,3,4], then the 0th,
     3rd, and 4th x-ticks will be displayed)

'colors'
     This option lets you control the colors the chart will use.  It takes
     a reference to a hash.  The hash should contain keys mapped to
     references to arrays of rgb values.  For instance,

          $obj->set('colors' => {'background' => [255,255,255]});

     sets the background color to white (which is the default).  Valid
     keys for this hash are

          'background' (background color for the gif)
          'text' (all the text in the chart)
          'y_label' (color of the first y axis label)
          'y_label2' (color of the second y axis label)
          'grid_lines' (color of the grid lines)
          'x_grid_lines' (color of the x grid lines - for x axis ticks)
          'y_grid_lines' (color of the y grid lines - for to left y axis ticks)
          'y2_grid_lines' (color of the y2 grid lines - for right y axis ticks)
          'dataset0'..'dataset15' (the different datasets)
          'misc' (everything else, ie. ticks, box around the legend)

     NB. For composite charts, there is a limit of 8 datasets per
     component.  The colors for 'dataset8' through 'dataset15' become the
     colors for 'dataset0' through 'dataset7' for the second component
     chart.

'grey_background'
     Puts a nice soft grey background on the actual data plot when set to
     'true'.  Default is 'true'.

'grid_lines'
     Draws grid lines matching up to x and y ticks

'spaced_bars'
     Leaves space between the groups of bars at each data point when set
     to 'true'.  This just makes it easier to read a bar chart.  Default
     is 'true'.

'imagemap'
     Lets Chart know you're going to ask for information about the
     placement of the data for use in creating an image map from the gif.
     This information can be retrieved using the imagemap_dump() method.
     NB. that the imagemap_dump() method cannot be called until after the
     Chart has been generated (ie. using the gif() or cgi_gif() methods).

'sort'
     Tells Chart to sort the data before plotting it.  Can be assigned an
     order ('asc' or 'desc' for ascending and descending, respectively),
     in which case it sorts numerically.  Or it can also be assigned an
     array reference.  The array reference should contain 3 elements:  the
     order in which to search (as above), which dataset to use (remember
     that 0 is the x-tick labels), and the type of sort to do ('alpha' or
     'num' for alphabetical or numerical sorts, respectively).  For
     example,

          $obj->set ('sort' => ['asc', 2, 'num']);

     would sort the data numerically in ascending order, sorting by the
     third dataset (second if you don't count the x-tick labels).  Note
     that

          $obj->set ('sort' => ['asc', 0, 'alpha']);

     will sort the data in ascending alphabetical order by the x-tick
     labels.  Defualts to undef, normally, and 'desc' for pareto.

'nosort'
     Turns off the default sort for pareto graphs.  Default is undef.

'cutoff'
     Only used for pareto charts, this option determines where the cut-off
     point is.  It then lumps everything after the highest 'cutoff' data
     points into an 'Other' entry on the chart.  Default is 5.

'nocutoff'
     Turns off the default 'cutoff' feature of pareto graphs.  Defaut is
     undef.

'composite_info'
     This option is only used for composite charts.  It contains the
     information about which types to use for the two component charts,
     and which datasets belonf to which component chart.  It should be a
     reference to an array of array references, containing information
     like the following

          $obj->set ('composite_info' => [ ['Bars', [1,2]],
          				 ['Lines', [3,4] ]);

     This example would set the two component charts to be a bar chart and
     a line chart.  It would use the first two data sets for the bar chart
     (note that the numbering starts at 1, not zero like most of the other
     numbered things in Chart), and the second two data sets for the line
     chart.  The default is undef.

     NB. Chart::Composite can only do two component charts.

'min_val1', 'min_val2'
     Only for composite charts, these options specify the minimum y-value
     for the first and second components respectively.  Both default to
     undef.

'max_val1', 'max_val2'
     Only for composite charts, these options specify the maximum y-value
     for the first and second components respectively.  Both default to
     undef.

'ylabel2'
     The label for the right y-axis (the second component chart) on a
     composite chart.  Default is undef.

'yticks1', 'y_ticks2'
     The number of y ticks to use on the first and second y-axis on a
     composite chart.  Please note that if you just set the 'y_ticks'
     option, both axes will use that number of y ticks.  Both default to
     undef.

'same_y_axes'
     Forces both component charts in a composite chart to use the same
     maximum and minimum y-values if set to 'true'.  This helps to keep
     the composite charts from being too confusing.  Default is undef.

'no_cache'
     Adds Pragma: no-cache to the http header.  Be careful with this one,
     as Netscape 4.5 is unfriendly with POST using this method.

GIFgraph.pm-style API
---------------------

Sending the image to a file
     Invoking the gif method causes the graph to be plotted and saved to a
     file.  It takes the name of the output file and a reference to the
     data as arguments.  For example,

          $obj->gif ("foo.gif", \@data);

     would plot the data in @data, and the save the image to foo.gif.  Of
     course, this then beggars the question "What should @data look
     like?".  Well, just like GIFgraph, @data should contain references to
     arrays of data, with the first array reference pointing to an array
     of x-tick labels.  For example,

          @data = ( [ 'foo', 'bar', 'junk' ],
          	    [ 30.2,  23.5,  92.1   ] );

     would set up a graph with one dataset, and three data points in that
     set.  In general, the @data array should look something like

          @data = ( \@x_tick_labels, \@dataset1, ... , \@dataset_n );

     And no worries, I make my own internal copy of the data, so that it
     doesn't mess with yours.

CGI and Chart
     Okay, so you're probably thinking, "Do I always have to save these
     images to disk?  What if I want to use Chart to create dynamic images
     for my web site?"  Well, here's the answer to that.

          $obj->cgi_gif ( \@data );

     The cgi_gif method will print the chart, along with the appropriate
     http header, to stdout, allowing you to call chart-generating scripts
     directly from your html pages (ie. with a <img src=image.pl> HTML
     tag).  The @data array should be set up the same way as for the
     normal gif method.

Graph.pm-style API
------------------

   You might ask, "But what if I just want to add a few points to the
graph, and then display it, without all those references to references?".
Well, friend, the solution is simple.  Borrowing the add_pt idea from Matt
Kruse's Graph module, you simply make a few calls to the add_pt method,
like so:

     $obj->add_pt ('foo', 30, 25);
     $obj->add_pt ('bar', 16, 32);

   Or, if you want to be able to add entire datasets, simply use the
add_dataset method:

     $obj->add_dataset ('foo', 'bar');
     $obj->add_dataset (30, 16);
     $obj->add_dataset (25, 32);

   These methods check to make sure that the points and datasets you are
adding are the same size as the ones already there.  So, if you have two
datasets currently stored, and try to add a data point with three
different values, it will carp (per the Carp module) an error message.
Similarly, if you try to add a dataset with 4 data points, and all the
other datasets have 3 data points, it will carp an error message.

   Don't forget, when using this API, that I treat the first dataset as a
series of x-tick labels.  So, in the above examples, the graph would have
two x-ticks, labeled 'foo' and 'bar', each with two data points.

Clearing the data
     A simple call to the clear_data method empties any values that may
     have been entered.

          $obj->clear_data ();

Getting a copy of the data
     If you want a copy of the data that has been added so far, make a call
     to the get_data method like so:

          $dataref = $obj->get_data;

     It returns (you guessed it!) a reference to an array of references to
     datasets.  So the x-tick labels would be stored as

          @x_labels = @{$dataref->[0]};

Sending the image to a file
     If you just want to print this chart to a file, all you have to do is
     pass the name of the file to the gif() method.

          $obj->gif ("foo.gif");

Sending the image to a filehandle
     If you want to do something else with the image, you can also pass a
     filehandle (either a typeglob or a FileHandle object) to gif, and it
     will print directly to that.

          $obj->gif ($filehandle);
          $obj->gif (FILEHANDLE);

CGI and Chart
     Okay, so you're probably thinking (again), "Do I always have to save
     these images to disk?  What if I want to use Chart to create dynamic
     images for my web site?"  Well, here's the answer to that.

          $obj->cgi_gif ();

     The cgi_gif method will print the chart, along with the appropriate
     http header, to stdout, allowing you to call chart-generating scripts
     directly from your html pages (ie. with a <img src=image.pl> HTML
     tag).

Imagemap Support
----------------

   Chart can also return the pixel positioning information so that you can
create image maps from the gifs Chart generates.  Simply set the 'imagemap'
option to 'true' before you generate the gif, then call the imagemap_dump()
method afterwards to retrieve the information.  You will be returned a
data structure almost identical to the @data array described above to pass
the data into Chart.

     $imagemap_data = $obj->imagemap_dump ();

   Instead of single data values, you will be passed references to arrays
of pixel information.  For Bars and StackedBars charts, the arrays will
contain two x-y pairs (specifying the upper left and lower right corner of
the bar), like so

     ( $x1, $y1, $x2, $y2 ) = @{ $imagemap_data->[$dataset][$datapoint] };

   For Lines, Points, and LinesPoints, the arrays will contain a single
x-y pair (specifying the center of the point), like so

     ( $x, $y ) = @{ $imagemap_data->[$dataset][$datapoint] };

   A few caveats apply here.  First of all, GD treats the upper-left corner
of the gif as the (0,0) point, so positive y values are measured from the
top of the gif, not the bottom.  Second, these values will most likely
contain long decimal values.  GD, of course, has to truncate these to
single pixel values.  Since I don't know how GD does it, I can't truncate
it the same way he does.  In a worst-case scenario, this will result in an
error of one pixel on your imagemap.  If this is really an issue, your
only option is to either experiment with it, or to contact Lincoln Stein
and ask him.  Third, please remember that the 0th dataset will be empty,
since that's the place in the @data array for the data point labels.

TO DO
=====

   * Numeric x-axes.

   * Add some 3-D graphs.

BUGS
====

   Probably quite a few, since it's been completely rewritten.  As usual,
please mail me with any bugs, patches, suggestions, comments, flames,
death threats, etc.

AUTHOR
======

   David Bonner (dbonner@cs.bu.edu)

MAINTAINER
==========

   Peter Clark (ninjaz@webexpress.com)

COPYRIGHT
=========

   Copyright(c) 1997-1998 by David Bonner, 1999 by Peter Clark All rights
reserved.  This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

Perl extension for a front-end to gnuplot and XRT.
**************************************************

NAME
====

     Chart::Graph - Perl extension for a front-end to gnuplot and XRT.

     23/4/99
     Version 1.1

SYNOPSIS
========

     #make sure to include Chart::Graph
     use Chart::Graph;

     gnuplot(\%global_options, [\%data_set_options, \@matrix],
                               [\%data_set_options, \@x_column, \@y_column],
                               [\%data_set_options, < filename >], ... );

     #make sure to include Chart::Graph
     use Chart::Graph;

     xrt3d(\%options, \@data_set);

     #say for example we have a 3 by 4 matrix -> dataxy
     xrt3d(\%options,
           [[data11, data12, data13, data14],
           [data21, data22, data23, data24],
           [data31, data32, data33, data34]])

DESCRIPTION
===========

     use Chart::Graph;

     Graph.pm is a module that allows easy generation of graphs within
     perl. Currently Graph.pm supports two packages, gnuplot and xrt,
     both of which you need to have installed on your system.

     Currently the xrt3d package is not being supported, although
     it works. It is still in the development stage. Feel free to
     give it a try though.

INSTALLATION
============

     To install Graph.pm on your system you need to run:

     perl Makefile.PL
     make
     make install

     If you want to use the xrt3d package, you need to build the "graph"
     binary in the xrt3d directory.

USAGE
=====

     Graph.pm will probe your path if you do not supply paths to the
     programs that it needs.

     You need to set these variables if they are not in your path:

     For gnuplot():
     $Chart::Graph::gnuplot    # path to gnuplot
     $Chart::Graph::ppmtogif   # path to ppmtogif

     For xrt():
     $Chart::Graph::ppmtogif   # path to ppmtogif
     $Chart::Graph::xrt        # path to "graph"(the xrt wrapper)
     $Chart::Graph::xwdtopnm   # path to xwdtopnm
     $Chart::Graph::xvfb       # path to Xvfb(the virtual frame
                                # buffer required by XRT)

     Currently Chart::Graph supports two levels of debug, 0
     (no debug msgs) and 1(debug msgs). You need to set the
     $Graph::debug flag accordingly. If you are having problems
     with Graph.pm set the debug flag to 1. Also Graph.pm will check
     $ENV{TMPDIR} for the temporary file storage. If you do not
     specify, it will be set to /tmp automatically.

     All the documentation(in HTML, with examples) for Graph.pm
     is located in doc/. Documentation is also available online
     at http://www.caida.org/Tools/Graph.

CONTENT SUMMARY
===============

     Graph.pm        - top level file of Chart::Graph
     Graph/          - sub modules of Chart::Graph
     doc/            - documentation in HTML
     graph_xrt/      - xrt wrapper executable code
     test_Graph.pl   - the test script used for debugging

MORE INFO
=========

     For more information on gnuplot, please see the gnuplot web page:
     http://www.cs.dartmouth.edu/gnuplot_info.html.

CONTACT
=======

     Send email to graph-request@caida.org is you have problems,
     questions, or comments. To subscribe to the mailing list send
     mail to graph-request@caida.org with a body of
     "subscribe your@email.com"

AUTHOR
======

     Michael Young - mhyoung@caida.org

SEE ALSO
========

     gnuplot(1).

Graph Plotting Module (deprecated)
**********************************

NAME
====

   Chart::PNGgraph - Graph Plotting Module (deprecated)

SYNOPSIS
========

   use Chart::PNGgraph::moduleName;

DESCRIPTION
===========

   *Chart::PNGgraph* is a *perl5* module to create PNG output for a graph.

   Chart::PNGgraph is nothing more than a wrapper around GD::Graph, and its
use is deprecated. It only exists for backward compatibility. The
documentation for all the functionality can be found in GD/Graph.

   This module should work with all versions of GD, but it has only been
tested with version 1.19 and above. Version 1.19 is the last version that
produces GIF output, and requires a conversion step. The default
distribution of Chart::PNGgraph uses Image::Magick for this. If you'd like
to use something else, please replace the sub png2gif in
Chart::PNGgraph::Convert with something more to your liking.

NOTES
=====

   Note that if you use Chart::PNGgraph with a GD version 1.19 or lower
that any included logos will have to be in the GIF format. The only time
that PNG comes into play is _after_ GD has done its work, and the GIF gets
converted to PNG. There are no plans to change that behaviour; it's too
much work, and you should really be upgrading to a version of GD that
produces PNG directly.

SEE ALSO
========

   GD::Graph(3), GIFgraph(3).

AUTHOR
======

   Martien Verbruggen ported to GD 1.20+ (PNG) by Steve Bonds

Contact info
------------

   for Chart::PNGgraph questions: email: sbonds@agora.rdrop.com

   for GIFgraph or GD::Graph questions: email: mgjv@comdyn.com.au

Copyright
---------

   Copyright (c) 1999 Steve Bonds Copyright (c) 1995-1999 Martien
Verbruggen.  All rights reserved.  This package is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

Colour manipulation routines for use with Chart::PNGgraph
*********************************************************

NAME
====

   Colour - Colour manipulation routines for use with Chart::PNGgraph

SYNOPSIS
========

   use Chart::PNGgraph::colour qw( :colours :lists :files );

DESCRIPTION
===========

   The *Colour* Package provides a few routines to convert some colour
names to RGB values. Also included are some functions to calculate the hue
and luminance of the colours, mainly to be able to sort them.

   The :colours tags can be used to import the *_rgb*, *_hue*, and
*_luminance* functions, the :lists tag for *colour_list* and
*sorted_colour_list*, and the :files tag exports the *read_rgb* function.

FUNCTIONS
=========

Colour::colour_list( *number of colours* )
     Returns a list of *number of colours* colour names known to the
     package.

Colour::sorted_colour_list( *number of colours* )
     Returns a list of *number of colours* colour names known to the
     package, sorted by luminance or hue.  *NB.* Right now it always sorts
     by luminance. Will add an option in a later stage to decide sorting
     method at run time.

Colour::_rgb( *colour name* )
     Returns a list of the RGB values of *colour name*.

Colour::_hue( *R,G,B* )
     Returns the hue of the colour with the specified RGB values.

Colour::_luminance( *R,G,B* )
     Returns the luminance of the colour with the specified RGB values.

Colour::read_rgb( `file name' )
     Reads in colours from a rgb file as used by the X11 system.

     Doing something like:

          use Chart::PNGgraph::bars;
          use Chart::PNGgraph::colour;

          Chart::PNGgraph::colour::read_rgb("rgb.txt") or die "cannot read colours";

     Will allow you to use any colours defined in rgb.txt in your graph.

PREDEFINED COLOUR NAMES
=======================

   white, lgray, gray, dgray, black, lblue, blue, dblue, gold, lyellow,
yellow, dyellow, lgreen, green, dgreen, lred, red, dred, lpurple, purple,
dpurple, lorange, orange, pink, dpink, marine, cyan, lbrown, dbrown.

Plot two dimensional data in an image. Version 0.10.
****************************************************

NAME
====

   Chart::Plot - Plot two dimensional data in an image. Version 0.10.

SYNOPSIS
========

     use Chart::Plot;

     my $img = Chart::Plot->new();
     my $anotherImg = Chart::Plot->new ($image_width, $image_height);

     $img->setData (\@dataset) or die( $img->error() );
     $img->setData (\@xdataset, \@ydataset);
     $img->setData (\@anotherdataset, 'red_dashedline_points');
     $img->setData (\@xanotherdataset, \@yanotherdataset,
                    'Blue SolidLine NoPoints');

     my ($xmin, $ymin, $xmax, $ymax) = $img->getBounds();

     $img->setGraphOptions ('horGraphOffset' => 75,
     			    'vertGraphOffset' => 100,
     			    'title' => 'My Graph Title',
     			    'horAxisLabel' => 'my X label',
     			    'vertAxisLabel' => 'my Y label' );

     print $img->draw();

DESCRIPTION
===========

   I wrote *Chart::Plot* to create images of some simple graphs of two
dimensional data. The other graphing interface modules to GD.pm I saw on
CPAN either could not handle negative data, or could only chart evenly
spaced horizontal data. (If you have evenly spaced or nonmetric horizontal
data and you want a bar or pie chart, I have successfully used the
GIFgraph and Chart::* modules, available on CPAN.)

   *Chart::Plot* will plot multiple data sets in the same graph, each with
some negative or positive values in the independent or dependent
variables. Each dataset can be a scatter graph (data are represented by
graph points only) or with lines connecting successive data points, or
both. Colors and dashed lines are supported, as is scientific notation
(1.7E10). Axes are scaled and positioned automatically and 5-10 ticks are
drawn and labeled on each axis.

   You must have already installed the *GD.pm* library by Lincoln Stein,
available on CPAN or at http://stein.cshl.org/WWW/software/GD/ Versions of
GD below 1.19 supported only gif image format. Versions between 1.20 and
1.26 support only png format. GD version 1.27 supports either png or jpg
image formats. Chart::Plot will draw whichever format your version of GD
will draw. (See below for a method to determine which format your version
supports.)

USAGE
=====

Create an image object: new()
-----------------------------

     use Chart::Plot;

     my $img = Chart::Plot->new;
     my $img = Chart::Plot->new ( $image_width, $image_height );
     my $anotherImg = new Chart::Plot;

   Create a new empty image with the new() method. It will be transparent
and interlaced if your version of GD supports gif format.  png does not
yet support either. If image size is not specified, the default is 400 x
300 pixels, or you can specify a different image size. You can also create
more than one image in the same script.

Acquire a dataset: setData()
----------------------------

     $img->setData (\@data);
     $img->setData (\@xdata, \@ydata);
     $img->setData (\@data, 'red_dashedline_points');
     $img->setData (\@xdata, \@ydata, 'blue solidline');

   The setData() method reads in a two-dimensional dataset to be plotted
into the image. You can pass the dataset either as one flat array
containing the paired x,y data or as two arrays, one each for the x and y
data.

   As a single array, in your script construct a flat array of the form
(x0, y0, ..., xn, yn) containing n+1 x,y data points .  Then plot the
dataset by passing a reference to the data array to the setData() method.
(If you do not know what a reference is, just put a backslash (\) in front
of the name of your data array when you pass it as an argument to
setData().) Like this:

     my @data = qw( -3 9   -2 4   -1 1   0 0   1 1  2 4  3 9);
     $img->setData (\@data);

   Or, you may find it more convenient to construct two equal length
arrays, one for the horizontal and one for the corresponding vertical
data. Then pass references to both arrays (horizontal first) to setData():

     my @xdata = qw( -3  -2  -1  0  1  2  3 );
     my @ydata = qw(  9   4   1  0  1  4  9 );
     $img->setData (\@xdata, \@ydata);

   In the current version, if you pass a reference to a single, flat array
to setData(), then only a reference to the data array is stored internally
in the plot object, not a copy of the array. The object does not modify
your data, but you can and the modified data will be drawn.  On the other
hand, if you pass references to two arrays, then copies of the data are
stored internally, and you cannot modify them from within your script.
This inconsistent behavior is probably a bug, though it might be useful
from time to time.

   You can also plot multiple datasets in the same graph by calling
`$img->setData()' repeatedly on different datasets.

   *Error checking:* The setData() method returns a postive integer on
success and 0 on failure. If setData() fails, you can recover an error
message about the most recent failure with the error() method. The error
string returned will either be "The data set does not contain an equal
number of x and y values." or "The data element ... is non-numeric."

     $p->setData (\@data) or die( $p->error() );

   In the current version, only numerals, decimal points (apologies to
Europeans), minus signs, and more generally, scientific notation (+1.7E-10
or -.298e+17) are supported. Commas (,), currencies ($), time (11:23am) or
dates (23/05/98) are not yet supported and will generate errors. I hope to
figure these out sometime in the future.

   Be cautious with scientific notation, since the axis tick labels will
probably become unwieldy. Consider rescaling your data by orders of
magnitude or using logarithmic transforms before plotting them. Or
experiment with image size and graph offset.

   *Style options:* You can also specify certain graphing style options
for each dataset by passing an optional final string argument to setData()
with a concatenated list of selections from each of the following groups:

     BLACK           SOLIDLINE            POINTS
     red		    dashedline           nopoints
     green 	    noline
     blue

   The capitalized options in each group are the default for that group.
If you do not specify any options, you will get black solid lines
connecting successive data points with dots at each data point
('black_solidline_points'). If you want a red scatter plot (red dots but
no lines) you could specify either

     $p->setData (\@data, 'redNOLINE');
     $p->setData (\@xdata, \@ydata, 'Points Noline Red');

   Options are detected by a simple regexp match, so order does not matter
in the option string, options are not case sensitive and extraneous
characters between options are ignored. There is no harm in specifying a
default. There is also no error checking.

Obtain current graph boundaries: getBounds()
--------------------------------------------

     my ($xmin, $ymin, $xmax, $ymax) = $img->getBounds;

   This method returns the data values of the lower left corner and upper
right corner of the graph, based on the datasets so far set.  If you have
only positive data, then $xmin and $ymin will be 0. The upper values will
typically not be the data maxima, since axis tick ranges are usually a
little beyond the range of the data.  If you add another dataset, these
values may become inaccurate, so you will need to call the method again.
As an example, I use this to draw a least squares regression line (using
Statistics::OLS) through a scatter plot of the data, running from the
edges of the graph rather than from the bounds of the data.

Graph-wide options: setGraphOptions()
-------------------------------------

     $img->setGraphOptions ('title' => 'My Graph Title',
     		         'horAxisLabel' => 'my X label',
     		         'vertAxisLabel' => 'my Y label'
     			 'horGraphOffset' => $numHorPixels,
     	                 'vertGraphOffset' => $numvertPixels);

     my %xTickLabels = qw (1 One o'clock 2 Two o'clock 3 Three o'clock);
     my %yTickLabels = qw (1 Jan 2 Feb 3 Mar);
     $img->setGraphOptions ('xTickLabels' => \%xTickLabels,
                            'yTickLabels' => \%yTickLabels)
        or die ($img->error);

   This method and each of its arguments are optional.  You can call it
with one, some or all options, or you can call it repeatedly to set or
change options. This method will also accept a hash.

   In the current version, Chart::Plot is a little smarter about placement
of text, but is still not likely to satisfy everyone, If you are not
constructing images on the fly, you might consider leaving these blank and
using a paint program to add text by hand. Or place descriptive text in a
caption outside the image.

   Titles and Axis labels are blank, by default. The title will be
centered in the margin space below the graph. A little extra vertical
offset space (the margin between the edges of the graph proper and the
image) is added to allow room. There is no support for multi-line strings.
You can specify empty strings for one or the other of the axis labels.
The vertical label will be centered or left justified above the vertical
axis; the horizontal label will be placed below the end of the horizontal
axis, centered or right justified.

   By default, the graph will be centered within the image, with 50 pixels
offset distance from its edges to the edges of the image (though a title
will increase the vertical offset). Axis and tick labels and the title
will appear in this margin (assuming all data are positive). You can
obtain more space for a title or a horizontal label by increasing the
image size (method new() ) and adjusting the offset.

   *Custom Tick Labels:* Normally, Chart::Plot will draw five to ten ticks
on each axis and label them with their corresponding data values. You can
override this and supply your own custom tick labels to either axis in a
hash reference, in which the axis position (eg, the axis data coordinate)
is the key and the label at that distance along the axis is its value.  If
a key is not a number, an error message is set to the effect that a tick
label is non-numeric. If you supply an empty hash reference, all ticks
will be suppressed.

Draw the image: draw()
----------------------

     $img->draw();
     $img->draw('jpeg') or die "$img->error()";

   This method draws the image and returns it as a string, which you can
print to a file or to STDOUT. (This should be the last method called from
the $img object.)  You will generally need to know which image format your
version of GD supports: if it supports png, then to save the image in a
file:

     open (WR,'>plot.png') or die ("Failed to write file: $!");
     binmode WR;            # for DOSish platforms
     print WR $img->draw();
     close WR;

   Or, to return the graph from a cgi script:

     print "Content-type: image/png\n\n";
     print  $img->draw();

   Or, to pipe it to a viewing program which accepts STDIN (such as xv on
Unix)

     open (VIEWER,'| /usr/X11R6/bin/xv -') or die ("Failed to open viewer: $!");
     print VIEWER $img->draw();
     close VIEWER;

   Of course, if you have a version of GD which supports only gif, change
the file names and types to gif.  GD version 1.19 and below supported only
gif image format. Versions between 1.20 and 1.26 support only png format.
If you are not sure, or suspect the supported formats may change in the
future, you can use

     $extension = $img->image_type();
     open (WR,">plot.$extension");

   to obtain the type, 'png' or 'gif'. Often, you must know the type to
write the correct file extension or to return the correct content type
from a cgi script.

   GD version 1.27 supports both png and jpeg image formats. For this
version, draw() will default to 'png' unless you supply 'jpeg' as the
argument.  `image_type()' will return 'png' in scalar context and the list
of all supported formats `(png,jpeg)' in array context.

   If the argument to draw() is not a supported image format by the local
version of GD, draw() will return undef and an error message will be set.
error() will return 'The image format ... is not supported by this version
... of GD.'

Accessing the GD object directly
--------------------------------

   Chart::Plot is a front end to GD and creates an internal GD object. You
can access the GD object directly, to use GD methods to draw on it in ways
that Chart::Plot does not anticipate. The `getGDobject()' method in
Chart::Plot returns the object reference to its internal GD object.

     my $GDobject = $img->getGDobject();
     my ($GDobject, $black, $white, $red, $green, $blue)
         = $img->getGDObject();

   In scalar context, this method returns only the reference to the GD
object. It can also return a list containing the reference to the image
object and the colors already created by Chart::Plot for that GD onject,
in the order specified above.  If you do not obtain these colors, you will
need to allocate your own colors before drawing, example below.

   When you call the draw() method of Chart::Plot (typically the last step
in your script) any drawing you have done in your script with GD on the GD
object will also be drawn.

   Since Chart::Plot works with data values and GD works with pixel
values, you will need the `data2pxl()' method of Chart::Plot to translate
(x,y) pairs of data values to (px,py) pairs of pixel values. (You call
this method on the Chart::Plot object, not the GD object.) You must call
this method only after all datasets have been registered with the
setData() method, since the graph scaling and this translation may change
with each new dataset.

   Here is a brief example which draws small blue circles around each data
point in the chart.

     use Chart::Plot;
     my $img = Chart::Plot->new;
     my @data = qw( 10 11 11 12 12 13 13 14 14 15);
     $img->setData (\@data);

     # draw circles around each data point, diameter 15 pixels
     my $gd = $img->getGDobject;
     my $blue = $gd->colorAllocate(0,0,255); # or use $img's blue
     my ($px,$py);
     for (my $i=0; $i<$#data; $i+=2) {
       ($px,$py) = $img->data2pxl ($data[$i], $data[$i+1]);
       $gd->arc($px,$py,15,15,0,360,$blue);
     }

     # draw the rest of the chart, and print it
     open (OUT,">plot.gif");
     binmode OUT;
     print OUT $img->draw();
     close OUT;

BUGS AND TO DO
==============

   If your data is bunched tightly but far away from the origin, then you
will obtain a better chart if the graph is clipped away from the origin. I
have not yet found a useful way to do this, but I am still thinking. You
may be able to use Custom Tick Labels to improve your chart in the
meantime.

   You will probably be unhappy with axis tick labels running together if
you use scientific notation.  Controlling tick label formatting and length
for scientific notation seems doable but challenging.

   Future versions might incorporate a legend, control of font size, word
wrap and dynamic adjustment of axis labels and title. Better code, a
better pod page.

AUTHOR
======

   Copyright (c) 1998-2000 by Sanford Morton <smorton@pobox.com>  All
rights reserved.  This program is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

   This work is dedicated to the memory of Dr. Andrew Morton, who
requested it.  *Requiescat in pace*, my friend.

SEE ALSO
========

   GD::Graph(1) (formerly GIFgraph(1)) and Chart(1) are other front end
modules to GD(1). All can be found on CPAN.

3D Piechart
***********

NAME
====

   Pie.pm - 3D Piechart

SYNOPSIS
========

     use Chart::ThreeD::Pie;

     # create a new pie
     my $pie = new Chart::ThreeD::Pie (500, 300, "title");

     # add data
     $pie->add (160, '#FFAA00', 'part 1');
     $pie->add (350, '#00FF66', 'part 2');
     $pie->add (100, '#AA00FF', 'part 3');
     $pie->add (300, '#0000FF', 'part 4');
     $pie->add (300, '#DD00FF', 'part 5');
     $pie->add (300, '#00DDFF', 'part 6');

     # add a percentage after each label part.
     $pie->percents (1);

     # only draw parts greater or equal to 3%. All other parts will be
     # concatenated in to a part called "others" (using red color)
     $pie->limit (2, '#FF0000', 'others');

     # thickness of the pie
     $pie->thickness (30);

     # sort the "parts"
     $pie->want_sort (1);

     # foreground and background colors
     $pie->fgcolor ('#FF0000');
     $pie->bgcolor ('#00FFFF');

     # add a border
     $pie->border (1);

     # make sure we are writing to a binary stream
     binmode STDOUT;

     # Draw the pie, Convert the image to GIF and print it on standard output
     print $pie->plot->gif;

DESCRIPTION
===========

     Chart::ThreeD::Pie allows you to create 3D Piecharts very easily
     and emit the drawings as GIF files. You can customize almost everything
     using a large number of methods.

     This module requires the Lincoln D. Stein's GD module available on CPAN.

Method Calls
============

Creating Pie
------------

new
     `Chart::ThreeD::Pie::new(width, height, title)' *class method*

     To create a new pie, send a new() message to the Chart::ThreeD::Pie
     class.  For example:

          $pie = new Chart::ThreeD::Pie (450, 320, 'my title');

     This will create an image that is 450 x 320 pixels wide.  If you don't
     specify the dimensions, a default of 400 x 300 will be chosen. The
     default title is an empty string (no title). The three parameters can
     be changed using the corresponding methods specified bellow.

Commands
--------

`thickness'
     `Chart::ThreeD::Pie::thickness(val)' *object method*

     This allows you to set the thickness (in pixel) of the pie if val is
     defined. The current value is returned. Default value is 30 pixels.

     Example:

          print "Current thickness is ", $pie->thickness, " pixels\n";
          # set it to 20.
          $pie->thickness(20);

`want_sort'
     `Chart::ThreeD::Pie::thickness(bool)' *object method*

     This will allow you to sort the parts of the pie if bool is non-null.
     The current value is returned. Default is null;

     Example:

          print "Current want_sort value is ", $pie->want_sort, "\n";
          # set it to true
          $pie->want_sort(1);

transparent
     `Chart::ThreeD::Pie::transparent(bool)' *object method*

     This will allow you to make the background of the final picture
     transparent if bool is non-null. The current value is returned.
     Default is null;

     Example:

          # Background will be transparent.
          $pie->transparent(1);

interlaced
     `Chart::ThreeD::Pie::interlaced(bool)' *object method*

     This will allow you to make the background of the final picture
     interlaced if bool is non-null. The current value is returned.
     Default is null;

     Example:

          # Picture will be interlaced
          $pie->interlaced(1);

`percents'
     `Chart::ThreeD::Pie::percents(bool)' *object method*

     This will add percentages after the label of each part of the pie if
     bool is non-null. The current value is returned. Default is null;

     Example:

          # add percents in labels
          $pie->percents(1);

bgcolor
     `Chart::ThreeD::Pie::bgcolor(bgcolor)' *object method*

     Set the background color if bgcolor is defined. The current value is
     returned. Default value is '#000000' (black). Color is a string
     composed of a '#' followed by 3 two-digits hexadecimal values,
     respectively Red, Green and Blue.

     Example:

          # set the background color to yellow
          $pie->bgcolor ('#FFFF00');

`fgcolor'
     `Chart::ThreeD::Pie::fgcolor(fgcolor)' *object method*

     Set the foreground color if fgcolor is defined. The current value is
     returned. Default value is '#000000' (black). Color is a string
     composed of a '#' followed by 3 two-digits hexadecimal values,
     respectively Red, Green and Blue.

     Example:

          # set the foreground color to red
          $pie->fgcolor ('#FF0000');

border
     `Chart::ThreeD::Pie::border(bool)' *object method*

     This will allow you to add a border to the final picture if bool is
     non-null.  The current value is returned. Default is null. The color
     of the boder is specified by fgcolor.

     Example:

          # Want a border
          $pie->border(1);

limit
     `Chart::ThreeD::Pie::limit(val, color, label)' *object method*

     This allows you to set the size (in percent) of the smallest part of
     the pie that will be drawn. All other parts will be merged into a
     single part labeled by 'label' and using the color 'color'. If 'val'
     is null, all parts are drawn. Default values are  7, '#FF0000' and
     'others'. Current values are returned.

`radius'
     `Chart::ThreeD::Pie::radius(rad)' *object method*

     Specify the radius of the pie in pixels if rad is non-null. The
     current value is returned. The default value is a third of the xmax
     value given to the creation of the pie (first parameter of the
     constructor).

     Example:

          # set radius to 100.
          $pie->radius(100);

`xmax'
     `Chart::ThreeD::Pie::xmax(val)' *object method*

     This allows you to set the length (in pixel) of the pie if val is
     defined. The current value is returned.

     Example:

          print "Current length is ", $pie->xmax, " pixels\n";
          # set it to 600.
          $pie->xmax(600);

`ymax'
     `Chart::ThreeD::Pie::ymax(val)' *object method*

     This allows you to set the width (in pixel) of the pie if val is
     defined. The current value is returned.

     Example:

          print "Current width is ", $pie->ymax, " pixels\n";
          # set it to 500.
          $pie->ymax(500);

title
     `Chart::ThreeD::Pie::title(val)' *object method*

     This allows you to change the title of the pie if val is defined.
     The current value is returned.

     Example:

          print "Current title is '", $pie->title, "'\n";
          # set it to 'my own title'.
          $pie->title('my own title');

add
     `Chart::ThreeD::Pie::add(val, color, label)' *object method*

     This method adds a part to a pie. The size of the part is specified
     by val.  Both color and label are optional. The default color is
     '#DDDDDD' and the default label is ".

plot
     `Chart::ThreeD::Pie::plot()' *object method*

     Draw the pie. This method returns a GD object (see GD).

gif
     `Chart::ThreeD::Pie::gif()' *object method*

     This returns the image data in GIF format.  You can then print it,
     pipe it to a display program, or write it to a file. You MUST call
     the plot() method at least once before calling gif().

     Example:

          $pie->plot;
          open (PIPE, "| xv -") || die "Error: $!";
          binmode PIPE;
          print PIPE $pie->gif;
          close PIPE;

SEE ALSO
========

   See Perl (perl.info), GD,

AUTHOR
======

   Fabien Tassin (fta@oleane.net)

COPYRIGHT
=========

   Copyright 1998, 1999, Fabien Tassin. All rights reserved.  It may be
used and modified freely, but I do request that this copyright notice
remain attached to the file. You may modify this module as you wish, but
if you redistribute a modified version, please attach a note listing the
modifications you have made.

object for displaying data via XMGR
***********************************

NAME
====

   Chart::XMGR - object for displaying data via XMGR

SYNOPSIS
========

     use Chart::XMGR;

     xmgr($a, { SYMBOL => 'plus'};

     use Chart::XMGR ();

     $xmgr = new Chart::XMGR;
     $xmgr->line($pdl);

     $pdl->$xmgr->line;

     xmgr($pdl, { LINESTYLE => 'dotted' });

DESCRIPTION
===========

   Provides a perl/PDL interface to the XMGR plotting package.  Can be
used to plot PDLs or Perl arrays.

   A simple function interface is provided that is based on the more
complete object-oriented interface.

   The interface can be implemented using either anonymous pipes or named
pipes (governed by the module variable Chart::XMGR::NPIPE).  If named
pipes are used ($NPIPE = 1) XMGR can be controlled via the pipe and
buttons are available for use in XMGR. If an anonymous pipe is used XMGR
will not accept button events until the pipe has been closed.

   Currently the named pipe option can not support data sets containing 3
or more columns (I haven't worked out how to do it anyway!).  This means
that only TYPE XY is supported. For anonymouse pipe 3 or more columns can
be supplied along with the graph type.

   The default option is to use the named pipe.

OPTIONS
=======

   The following drawing options are available: The options are
case-insensitive and minimum match.

LINESTYLE
     Controls the linestyle. Allowed values are none(0), solid(1),
     dotted(2), dashed(3), dotdash(4). Default is solid.

LINECOLOUR
     Controls the line colour. LINECOLOR is an allowed synonym.  Allowed
     values are white, black, red, green, blue, yellow, brown, gray,
     violet, cyan, magenta, orange, indigo, maroon, turqse and green4
     (plus numeric equivalents: 0 to 15).  Default is black.

LINEWIDTH
     Width of the line. Default is 1.

FILL
     Governs whether the area inside the line is filled.  Default is none.

SYMBOL
     Governs symbol type. 46 different types are supported (see XMGR
     options for the mapping to symbol type). Basic symbol types are
     available by name: none, dot, circle, square, diamond, triangleup,
     triangleleft, triangledown, triangleright, triangledown,
     triangleright, plus, X, star. Default is circle.

SYMCOLOUR
     Colour of symbol. See LINECOLOUR for description of available values.
     Default is red.

SYMSIZE
     Symbol size. Default is 1.

SYMFILL
     Governs whether symbols are filled (1), opaque (0) or have no fill
     (none(0)). Default is filled.

AUTOSCALE
     Set whether to autoscale as soon as set is drawn. Default is true.

SETTYPE
     Type of data set. Allowed values as for XMGR: XY, XYDX, XYDY, XYDXDX,
     XYDYDY, XYDXDY, XYZ, XYRT.

NON-OO INTERFACE
================

   A simplified non-object oriented interface is provided.  These routines
are exported into the callers namespace by default.

xmgr( args, { options } )
     A simplified interface to plotting on Xmgr.

xmgrset(set)
     Select the current set (integer 0->).

xmgrdetach
     Detach XMGR from the pipe. This returns control of XMGR to the user.

xmgrprint(string)
     Print arbritrary commands to XMGR. The @ symbol is prepended to all
     commands and a newline is appended.

METHODS
=======

   The following methods are available.

new()
     Constructor. Is used to launch the new XMGR process and returns the
     object.

pipe
     Return file handle (of type IO::Pipe) associated with external XMGR
     process.

opt()
     Return options object associated with XMGR object.

npipe()
     Returns name of pipe associated with object.

attached()
     Returns whether an XMGR process is currently attached to the object.
     Can also be used to set the state.

set()
     Returns (or sets) the current set.

graph()
     Returns (or sets) the current graph.

debug()
     Turns the debug flag on or off. If on (1) all commands sent to XMGR
     are also printed to STDOUT.

     Default is false.

prt(text)
     Method to prt Xmgr commands to the attached XMGR process.  Carriage
     returns are appended. '@' symbols are prepended where necessary
     (needed for anonymous pipes, not for named pipes).

prt_data (data)
     Print numbers to the pipe. No @ symbol is prepended.  For named pipes
     we must use the POINT command.  For anonymous pipes the data is just
     sent as is (so multiple column can be supplied).

select_graph
     Selects the current graph in XMGR.

plot($pdl, $pdl2, ..., $hash)
     Method to plot XY data. Multiple arguments are allowed (in addition
     to the options hash). This routine plots the supplied data as the
     currently selected set on the current graph.

     The interpretation of each input argument depends on the set type
     (specified as an option: SETTYPE). For example, 3 columns can be
     translated as XYDY, XYDX or XYZ. No check is made that the number of
     arguments matches the selected type.

     Array references can be substituted for PDLs.

     The options hash is assumed to be the last argument.

          $xmgr->plot(\@x, \@y, { LINECOL => 'red' } );
          $xmgr->plot($pdl);

send_options(hashref)
     Process the options hash and send to XMGR.  This sends the options
     for the current set.

redraw()
     Forces XMGR to redraw.

killset([setnum])
     Kill a set.  If no argument is specified the current set is killed;
     else the specified set (integer greater than or equal to 0) is killed.

autoscale()
     Instruct XMGR to autoscale.

autoscale_on([set])
     Autscale on the specified set (default to current set).

world(xmin, xmax, ymin, ymax)
     Set the world coordinates.

viewport(xmin, xmax, ymin, ymax)
     Set the current graphs viewport (where the current graphi is
     displayed).

graphtype(type)
     Set the graphtype. Allowed values are: 'XY', 'BAR', 'HBAR',
     'STACKEDBAR', 'STACKEDHBAR', 'LOGX', 'LOGY', 'LOGXY', 'POLAR', 'SMITH'

configure(hash)
     Configure the current set.

          $xmgr->configure(SYMBOL=>1, LINECOLOUR=>'red');

detach()
     Close the pipe without asking XMGR to die.  This can be used if you
     want to leave XMGR running after the object is destroyed. Note that
     no more messages can be sent to the XMGR process associated with this
     object.

DESTROY
     Destructor for object. Sends the 'exit' message to the XMGR process.
     This will fail silently if the pipe is no longer open. (eg if the
     detach() method has been called.

EXAMPLE
=======

   An example program may look like this:

     use Chart::XMGR;
     use PDL;

     $a = pdl( 1,4,2,6,5);
     $xmgr = new Chart::XMGR;
     $xmgr->plot($a, { SYMBOL => 3,
                       LINECOL => 'red',
                       LINESTYLE => 2
                       SYMSIZE => 1 }
                 );

     $xmgr->configure(SYMCOL => 'green');
     $xmgr->detach;

   If PDL is not available, then arrays can be used:

     use Chart::XMGR

     @a = ( 1,4,2,6,5 );
     $xmgr = new Chart::XMGR;
     $xmgr->plot(\@a, { SYMBOL => 3,
                       LINECOL => 'red',
                       LINESTYLE => 2
                       SYMSIZE => 1 }
                 );

     $xmgr->configure(SYMCOL => 'green');
     $xmgr->detach;

XMGR (Grace)
============

   The XMGR home page is at http://plasma-gate.weizmann.ac.il/Xmgr/ This
modules is designed to be used with XMGR version 4 (tested on v4.1.2).
This module will probably not work with GRACE (XMGR version 5).

REQUIREMENTS
============

   The PDL::Options module is required. This is available as part of the
PDL distribution (http://pdl.perl.org) or separately in the PDL directory
on CPAN.

NOTES
=====

   For versions 0.90 and earlier this module was known by the name
Graphics::XMGR (not on CPAN).

AUTHOR
======

   Copyright (C) Tim Jenness 1998,1999 (t.jenness@jach.hawaii.edu).  All
rights reserved. This program is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

A clone of the classic Eliza program
************************************

NAME
====

   *Chatbot::Eliza* - A clone of the classic Eliza program

SYNOPSIS
========

     use Chatbot::Eliza;
     # see below for details

DESCRIPTION
===========

   This module implements the classic Eliza algorithm.  The original Eliza
program was written by Joseph Weizenbaum and described in the
Communications of the ACM in 1966.  Eliza is a mock Rogerian
psychotherapist.  It prompts for user input, and uses a simple
transformation algorithm to change user input into a follow-up question.
The program is designed to give the appearance of understanding.

   This program is a faithful implementation of the program described by
Weizenbaum.  It uses a simplified script language (devised by Charles
Hayden).  The content of the script is the same as Weizenbaum's.

   This module encapsulates the Eliza algorithm in the form of an object.
This should make the functionality easy to incorporate in larger programs.

   The current version of Chatbot::Eliza.pm is available on CPAN:

     http://www.perl.com/CPAN/modules/by-module/Chatbot/

INSTALLATION
============

   To install this package, just change to the directory which you created
by untarring the package, and type the following:

     perl Makefile.PL
     make test
     make
     make install

   This will copy Eliza.pm to your perl library directory for use by all
perl scripts.  You probably must be root to do this, unless you have
installed a personal copy of perl.

USAGE
=====

   This is all you need to do to launch a simple Eliza session:

     use Chatbot::Eliza;

     $mybot = new Chatbot::Eliza;
     $mybot->command_interface;

   You can also customize certain features of the session:

     $myotherbot = new Chatbot::Eliza;

     $myotherbot->name( "Hortense" );
     $myotherbot->debug( 1 );

     $myotherbot->command_interface;

   These lines set the name of the bot to be "Hortense" and turn on the
debugging output.

   When creating an Eliza object, you can specify a name and an
alternative scriptfile:

     $bot = new Chatbot::Eliza "Brian", "myscript.txt";

   You can also use an anonymous hash to set these parameters.  Any of the
fields can be initialized using this syntax:

     $bot = new Chatbot::Eliza {
     	name       => "Brian",
     	scriptfile => "myscript.txt",
     	debug      => 1,
     	prompts_on => 1,
     	memory_on  => 0,
     	myrand     =>
     		sub { my $N = defined $_[0] ? $_[0] : 1;  rand($N); },
     };

   If you don't specify a script file, then the Eliza module will
initialize the new Eliza object with a default script that the module
contains within itself.

   You can use any of the internal functions in a calling program.  The
code below takes an arbitrary string and retrieves the reply from the
Eliza object:

     my $string = "I have too many problems.";
     my $reply  = $mybot->transform( $string );

   You can easily create two bots, each with a different script, and see
how they interact:

     use Chatbot::Eliza

     my ($harry, $sally, $he_says, $she_says);

     $sally = new Chatbot::Eliza "Sally", "histext.txt";
     $harry = new Chatbot::Eliza "Harry", "hertext.txt";

     $he_says  = "I am sad.";

     # Seed the random number generator.
     srand( time ^ ($$ + ($$ << 15)) );

     while (1) {
     	$she_says = $sally->transform( $he_says );
     	print $sally->name, ": $she_says \n";

     	$he_says  = $harry->transform( $she_says );
     	print $harry->name, ": $he_says \n";
     }

   Mechanically, this works well.  However, it critically depends on the
actual script data.  Having two mock Rogerian therapists talk to each
other usually does not produce any sensible conversation, of course.

   After each call to the transform() method, the debugging output for
that transformation is stored in a variable called $debug_text.

     my $reply      = $mybot->transform( "My foot hurts" );
     my $debugging  = $mybot->debug_text;

   This feature always available, even if the instance's $debug variable
is set to 0.

   Calling programs can specify their own random-number generators.  Use
this syntax:

     $chatbot = new Chatbot::Eliza;
     $chatbot->myrand(
             sub {
                     #function goes here!
             }
     );

   The custom random function should have the same prototype as perl's
built-in rand() function.  That is, it should take a single (numeric)
expression as a parameter, and it should return a floating-point value
between 0 and that number.

   What this code actually does is pass a reference to an anonymous
subroutine ("code reference").  Make sure you've read the perlref manpage
for details on how code references actually work.

   If you don't specify any custom rand function, then the Eliza object
will just use the built-in rand() function.

MAIN DATA MEMBERS
=================

   Each Eliza object uses the following data structures to hold the script
data in memory:

%decomplist
-----------

   Hash: the set of keywords;  Values: strings containing the
decomposition rules.

%reasmblist
-----------

   Hash: a set of values which are each the join of a keyword and a
corresponding decomposition rule; Values: the set of possible reassembly
statements for that keyword and decomposition rule.

%reasmblist_for_memory
----------------------

   This structure is identical to %reasmblist, except that these rules are
only invoked when a user comment is being retrieved from memory. These
contain comments such as "Earlier you mentioned that...," which are only
appropriate for remembered comments.  Rules in the script must be
specially marked in order to be included in this list rather than
%reasmblist. The default script only has a few of these rules.

@memory
-------

   A list of user comments which an Eliza instance is remembering for
future use.  Eliza does not remember everything, only some things.  In
this implementation, Eliza will only remember comments which match a
decomposition rule which actually has reassembly rules that are marked
with the keyword "reasm_for_memory" rather than the normal "reasmb".  The
default script only has a few of these.

%keyranks
---------

   Hash: the set of keywords;  Values: the ranks for each keyword

@quit
-----

   "quit" words - that is, words the user might use to try to exit the
program.

@initial
--------

   Possible greetings for the beginning of the program.

@final
------

   Possible farewells for the end of the program.

%pre
----

   Hash: words which are replaced before any transformations; Values: the
respective replacement words.

%post
-----

   Hash: words which are replaced after the transformations and after the
reply is constructed;  Values: the respective replacement words.

%synon
------

   Hash: words which are found in decomposition rules; Values: words which
are treated just like their corresponding synonyms during matching of
decomposition rules.

Other data members
------------------

   There are several other internal data members.  Hopefully these are
sufficiently obvious that you can learn about them just by reading the
source code.

METHODS
=======

new()
-----

     my $chatterbot = new Chatbot::Eliza;

   new() creates a new Eliza object.  This method also calls the internal
_initialize() method, which in turn calls the parse_script_data() method,
which initializes the script data.

     my $chatterbot = new Chatbot::Eliza 'Ahmad', 'myfile.txt';

   The eliza object defaults to the name "Eliza", and it contains default
script data within itself.  However, using the syntax above, you can
specify an alternative name and an alternative script file.

   See the method parse_script_data(). for a description of the format of
the script file.

command_interface()
-------------------

     $chatterbot->command_interface;

   command_interface() opens an interactive session with the Eliza object,
just like the original Eliza program.

   If you want to design your own session format, then you can write your
own while loop and your own functions for prompting for and reading user
input, and use the transform() method to generate Eliza's responses.
(Note: you do not need to invoke preprocess() and postprocess() directly,
because these are invoked from within the transform() method.)

   But if you're lazy and you want to skip all that, then just use
command_interface().  It's all done for you.

   During an interactive session invoked using command_interface(), you
can enter the word "debug" to toggle debug mode on and off.  You can also
enter the keyword "memory" to invoke the _debug_memory() method and print
out the contents of the Eliza instance's memory.

preprocess()
------------

     $string = preprocess($string);

   preprocess() applies simple substitution rules to the input string.
Mostly this is to catch varieties in spelling, misspellings, contractions
and the like.

   preprocess() is called from within the transform() method.  It is
applied to user-input text, BEFORE any processing, and before a reassebly
statement has been selected.

   It uses the array %pre, which is created during the parse of the script.

postprocess()
-------------

     $string = postprocess($string);

   postprocess() applies simple substitution rules to the reassembly rule.
This is where all the "I"'s and "you"'s are exchanged.  postprocess() is
called from within the transform() function.

   It uses the array %post, created during the parse of the script.

_testquit()
-----------

     if ($self->_testquit($user_input) ) { ... }

   _testquit() detects words like "bye" and "quit" and returns true if it
finds one of them as the first word in the sentence.

   These words are listed in the script, under the keyword "quit".

_debug_memory()
---------------

     $self->_debug_memory()

   _debug_memory() is a special function which returns the contents of
Eliza's memory stack.

transform()
-----------

     $reply = $chatterbot->transform( $string, $use_memory );

   transform() applies transformation rules to the user input string.  It
invokes preprocess(), does transformations, then invokes postprocess().
It returns the tranformed output string, called `$reasmb'.

   The algorithm embedded in the transform() method has three main parts:

  1. Search the input string for a keyword.

  2. If we find a keyword, use the list of decomposition rules for that
     keyword, and pattern-match the input string against each rule.

  3. If the input string matches any of the decomposition rules, then
     randomly select one of the reassembly rules for that decomposition
     rule, and use it to construct the reply.

        transform() takes two parameters.  The first is the string we want
to transform.  The second is a flag which indicates where this sting came
from.  If the flag is set, then the string has been pulled from memory,
and we should use reassembly rules appropriate for that.  If the flag is
not set, then the string is the most recent user input, and we can use the
ordinary reassembly rules.

   The memory flag is only set when the transform() function is called
recursively.  The mechanism for setting this parameter is embedded in the
transoform method itself.  If the flag is set inappropriately, it is
ignored.

How memory is used
------------------

   An Eliza object remembers up to `$max_memory_size' (default: 5) user
input strings.  Eliza remembers any comment when it matches a
docomposition rule for which there are any reassembly rules for memory. In
the script, such reassembly rules are marked with the keyword
"reasm_for_memory".

   If the transform() method fails to find any appropriate decomposition
rule for a user's comment, and if there are any comments inside the memory
array, then Eliza may elect to ignore the most recent comment and instead
pull out one of the strings from memory.  In this case, the transform
method is called recursively with the memory flag.

   Honestly, I am not sure exactly how this memory functionality was
implemented in the original Eliza program.  Hopefully this implementation
is not too far from Weizenbaum's.

   If you don't want to use the memory functionality at all, then you can
disable it:

     $mybot->memory_on(0);

   You can also achieve the same effect by making sure that the script
data does not contain any reassembly rules marked with the keyword
"reasm_for_memory".  The default script data only has 4 such items.

parse_script_data()
-------------------

     $self->parse_script_data;
     $self->parse_script_data( $script_file );

   parse_script_data() is invoked from the _initialize() method, which is
called from the new() function.  However, you can also call this method at
any time against an already-instantiated Eliza instance.  In that case,
the new script data is added to the old script data.  The old script data
is not deleted.

   You can pass a parameter to this function, which is the name of the
script file, and it will read in and parse that file.  If you do not pass
any parameter to this method, then it will read the data embedded at the
end of the module as its default script data.

   If you pass the name of a script file to parse_script_data(), and that
file is not available for reading, then the module dies.

Format of the script file
=========================

   This module includes a default script file within itself, so it is not
necessary to explicitly specify a script file when instantiating an Eliza
object.

   Each line in the script file can specify a key, a decomposition rule,
or a reassembly rule.

     key: remember 5
       decomp: * i remember *
         reasmb: Do you often think of (2) ?
         reasmb: Does thinking of (2) bring anything else to mind ?
       decomp: * do you remember *
         reasmb: Did you think I would forget (2) ?
         reasmb: What about (2) ?
         reasmb: goto what
     pre: equivalent alike
     synon: belief feel think believe wish

   The number after the key specifies the rank.  If a user's input
contains the keyword, then the transform() function will try to match one
of the decomposition rules for that keyword.  If one matches, then it will
select one of the reassembly rules at random.  The number (2) here means
"use whatever set of words matched the second asterisk in the decomposition
rule."

   If you specify a list of synonyms for a word, the you should use a "@"
when you use that word in a decomposition rule:

     decomp: * i @belief i *
       reasmb: Do you really think so ?
       reasmb: But you are not sure you (3).

   Otherwise, the script will never check to see if there are any synonyms
for that keyword.

   Reassembly rules should be marked with *reasm_for_memory* rather than
*reasmb* when it is appropriate for use when a user's comment has been
extracted from memory.

     key: my 2
       decomp: * my *
         reasm_for_memory: Let's discuss further why your (2).
         reasm_for_memory: Earlier you said your (2).
         reasm_for_memory: But your (2).
         reasm_for_memory: Does that have anything to do with the fact that your (2) ?

How the script file is parsed
=============================

   Each line in the script file contains an "entrytype" (key, decomp,
synon) and an "entry", separated by a colon.  In turn, each "entry" can
itself be composed of a "key" and a "value", separated by a space.  The
parse_script_data() function parses each line out, and splits the "entry"
and "entrytype" portion of each line into two variables, $entry and
`$entrytype'.

   Next, it uses the string `$entrytype' to determine what sort of stuff
to expect in the $entry variable, if anything, and parses it accordingly.
In some cases, there is no second level of key-value pair, so the function
does not even bother to isolate or create $key and $value.

   $key is always a single word.  $value can be null, or one single word,
or a string composed of several words, or an array of words.

   Based on all these entries and keys and values, the function creates
two giant hashes: %decomplist, which holds the decomposition rules for
each keyword, and %reasmblist, which holds the reassembly phrases for each
decomposition rule.  It also creates %keyranks, which holds the ranks for
each key.

   Six other arrays are created: `%reasm_for_memory, %pre, %post, %synon,
@initial,' and `@final'.

AUTHOR
======

   John Nolan  jpnolan@op.net  April 1999.

   Implements the classic Eliza algorithm by Prof. Joseph Weizenbaum.
Script format devised by Charles Hayden.

Perl extension for working with Chemical Elements
*************************************************

NAME
====

   Chemistry::Elements - Perl extension for working with Chemical Elements

SYNOPSIS
========

     use Chemistry::Elements qw(get_name get_Z get_symbol);

     # the constructor can use different input
     $element = new Chemistry::Elements $atomic_number;
     $element = new Chemistry::Elements $chemical_symbol;
     $element = new Chemistry::Elements $element_name;

     # you can make up your own attributes by specifying
     # a method (which is really AUTOLOAD)
           $element->molar_mass(22.989) #sets the attribute
     $MM = $element->molar_mass         #retrieves the value

DESCRIPTION
===========

   There are two parts to the module:  the object stuff and the exportable
functions for use outside of the object stuff.  The exportable functions
are discussed in EXPORTABLE FUNCTIONS.

   Chemistry::Elements provides an easy, object-oriented way to keep track
of your chemical data.  Using either the atomic number, chemical symbol,
or element name you can construct an Element object.  Once you have an
element object, you can associate your data with the object by making up
your own methods, which the AUTOLOAD function handles.  Since each chemist
is likely to want to use his or her own data, or data for some
unforesee-able property, this module does not try to be a repository for
chemical data.

   The Element object constructor tries to be as flexible as possible -
pass it an atomic number, chemical symbol, or element name and it tries to
create the object.

     # the constructor can use different input
     $element = new Chemistry::Elements $atomic_number;
     $element = new Chemistry::Elements $chemical_symbol;
     $element = new Chemistry::Elements $element_name;

   once you have the object, you can define your own methods simply by
using them.  Giving the method an argument (others will be ignored)
creates an attribute with the method's name and the argument's value.

     # you can make up your own attributes by specifying
     # a method (which is really AUTOLOAD)
           $element->molar_mass(22.989) #sets the attribute
     $MM = $element->molar_mass         #retrieves the value

   The atomic number, chemical symbol, and element name can be retrieved
in the same way.

     $atomic_number = $element->Z;
     $name          = $element->name;
     $symbol        = $element->symbol;

   These methods can also be used to set values, although changing any of
the three affects the other two.

     $element       = new Chemistry::Elements('Lead');

     $atomic_number = $element->Z;    # $atomic_number is 82

     $element->Z(79);

     $name          = $element->name; # $name is 'Gold'

EXPORTABLE FUNCTIONS
====================

   These functions can be exported.  They are not exported by default.

get_symbol()
------------

   This function attempts to return the symbol of the chemical element
given either the chemical symbol, element name, or atmoic number.  The
function does its best to interpret inconsistent input data (e.g.
chemcial symbols of mixed and single case).

     use Chemistry::Elements qw(get_symbol);

     $name = get_symbol('Fe');     #$name is 'Fe'
     $name = get_symbol('fe');     #$name is 'Fe'
     $name = get_symbol(26);       #$name is 'Fe'
     $name = get_symbol('Iron');   #$name is 'Fe'
     $name = get_symbol('iron');   #$name is 'Fe'

   If no symbol can be found, undef is returned.

   Since this function will return the symbol if it is given a symbol, you
can use it to test whether a string is a chemical symbol (although you
have to play some tricks with case since get_symbol will try its best
despite the case of the input data).

     if( lc($string) eq lc( get_symbol($string) ) )
     	{
     	#stuff
     	}

     You can modify the symbols (e.g. you work for UCal ;) ) by changing
     the data at the end of this module.

get_name()
----------

   This function attempts to return the name the chemical element given
either the chemical symbol, element name, or atomic number.  The function
does its best to interpret inconsistent input data (e.g.  chemcial symbols
of mixed and single case).

     $name = get_name('Fe');     #$name is 'Iron'
     $name = get_name('fe');     #$name is 'Iron'
     $name = get_name(26);       #$name is 'Iron'
     $name = get_name('Iron');   #$name is 'Iron'
     $name = get_name('iron');   #$name is 'Iron'

   If there is no Z can be found, undef is returned.

   Since this function will return the name if it is given a name, you can
use it to test whether a string is a chemical element name (although you
have to play some tricks with case since get_name will try its best
despite the case of the input data).

     if( lc($string) eq lc( get_name($string) ) )
     	{
     	#stuff
     	}

   You can modify the names (e.g. for different languages) by changing the
data at the end of this module.

get_Z()
-------

   This function attempts to return the atomic number of the chemical
element given either the chemical symbol, element name, or atomic number.
The function does its best to interpret inconsistent input data (e.g.
chemcial symbols of mixed and single case).

     $name = get_Z('Fe');     #$name is 26
     $name = get_Z('fe');     #$name is 26
     $name = get_Z(26);       #$name is 26
     $name = get_Z('Iron');   #$name is 26
     $name = get_Z('iron');   #$name is 26

   If there is no Z can be found, undef is returned.

   Since this function will return the Z if it is given a Z, you can use
it to test whether a string is an atomic number.  You might want to use
the string comparison in case the $string is not a number (in which case
the comparison will be false save for the case when $string is undefined).

     if( $string eq get_Z($string) )
     	{
     	#stuff
     	}

   The package constructor automatically finds the largest defined atomic
number (in case you add your own heavy elements).

AUTOLOADing methods
-------------------

   You can pseudo-define additional methods to associate data with objects.
For instance, if you wanted to add a molar mass attribute, you simply
pretend that there is a molar_mass method:

     $element->molar_mass($MM); #add molar mass datum in $MM to object

   Similiarly, you can retrieve previously set values by not specifying an
argument to your pretend method:

     $datum = $element->molar_mass();

     #or without the parentheses
     $datum = $element->molar_mass;

   If a value has not been associated with the pretend method and the
object, the pretend method returns undef.

   I had thought about providing basic data for the elements, but thought
that anyone using this module would probably have their own data.  If
there is an interest in canned data, perhaps I can provide mine :)

TO DO
=====

   I would like make this module easily localizable so that one could
specify other names or symbols for the elements (i.e. a different language
or a different perspective on the heavy elements).  If anyone should make
changes to the data, i would like to get a copy so that i can include it
in future releases :)

AUTHOR
======

   brian d foy <comdog@computerdog.com>

Perl extension for manipulation of chess PGN format. PGN is for  Portable Game Notation and follow the *Portable Game Notation Specification and Implementation Guide* revised 1994.03.12. You can find it at `http:' in this node.
***********************************************************************************************************************************************************************************************************************************

NAME
====

   Chess::Pgn - Perl extension for manipulation of chess PGN format. PGN
is for Portable Game Notation and follow the *Portable Game Notation
Specification and Implementation Guide* revised 1994.03.12. You can find
it at `http:' in this node.

   The goal of this module is not to play chess but to help to manipulate
PGN File.

   A PGN file is like this :

     [Event "?"]
     [Site "?"]
     [Date "????.??.??"]
     [Round "?"]
     [White "Greco"]
     [Black "NN"]
     [Result "1-0"]
     [ECO "C57"]
     [WhiteElo "2010"]
     [BlackElo "1620"]
     [PlyCount "17"]

     1.e4 e5 2.Nf3 Nc6 3.Bc4 Nf6 4.Ng5 d5 5.exd5 Nxd5 6.Nxf7 Kxf7 7.Qf3+ Ke6
     8.Nc3 Ne7 9.O-O c6 10.Re1 Bd7 11.d4 Kd6 12.Rxe5 Ng6 13.Nxd5 Nxe5
     14.dxe5+ Kc5 15.Qa3+ Kxc4 16.Qd3+ Kc5 17.b4# 1-0

     [Event "?"]
     [Site "corr CS ch 22 (FS"]
     [Date "????.??.??"]
     [Round "12.0"]
     [White "Rosenzweig V"]
     [Black "Necesany Z"]
     [Result "1/2-1/2"]
     [ECO "C55"]
     [WhiteElo "2410"]
     [BlackElo "2620"]
     [PlyCount "22"]

     1.e4 e5 2.Nf3 Nc6 3.Bc4 Nf6 4.O-O Be7 5.Nc3 Nxe4 6.Nxe4 d5 7.d4 dxc4
     8.d5 Nd4 9.Nxd4 Qxd5 10.Nf3 Qxe4 11.Re1 Qc6 12.Nxe5 Qf6 13.Bd2 O-O
     14.Bc3 Bc5 15.Re2 Qf5 16.Qd5 Bd6 17.Rae1 Be6 18.Qxb7 f6 19.Nc6 Bd5
     20.Rd2 Bxg2 21.Rxd6 Bxc6 22.Rxc6 Qg4+ 1/2-1/2

   With Chess:Pgn you will find a game by $game->date or $game->game.  For
our last example we will have

     $game->date : "????.??.??"
     $game->game : "1.e4 e5 2.Nf3 Nc6 3.Bc4 Nf6 4.Ng5 d5 5.exd5 Nxd5 6.Nxf7 Kxf7 7.Qf3+ Ke6
     8.Nc3 Ne7 9.O-O c6 10.Re1 Bd7 11.d4 Kd6 12.Rxe5 Ng6 13.Nxd5 Nxe5
     14.dxe5+ Kc5 15.Qa3+ Kxc4 16.Qd3+ Kc5 17.b4# 1-0"

   The module provide a good set of tools to modify PGN File but you will
have to make yourself the while :)

SYNOPSIS
========

     use Chess::Pgn;
     $p = new Chess::Pgn("2KTSDEF.PGN" ) || die "2KTSDEF.PGN not found";
     while ( $p->ReadGame )
      {
       print $p->white ,"<=>",$p->black, "\n";
      }
     $p->quit();

     $p->white(Kouatly);
     $p->black(Kasparov);

DESCRIPTION
===========

new
          $p= new Chess::Pgn ("name")

          open the file I<name> and if it doesn't exist return undef.

ReadGame
          $p->ReadGame

          This method read just one game and return undef at the end of file. You must use methods to read the game.

quit
          $p->quit

          Close the PGN file

Basic methods
          site, date, round, white, black, result, eco, whiteelo, blackelo, plycount, game :

          return the value of the current game.

          $p->black return Greco

          =item set a value

     You can change a value if you put a argument to the method.

     For example :

          $p->black("Gilles Maire")

          will change the value of the black opponent. But just in memory ! You will need to write of file to save it.

variable
     You can access to method value bye the hash

     $p->{Event}, $p->{Site} , $p->{Date}
     ,p->{Round},$p->{White},$p->{Black},   $p->{Result},
     $p->{ECO},$p->{Game}; $p->{WhiteElo}, $p{BlackElo}, $p->{PlyCount}

All in One method
          $p->PrintAll;

     return in a string all the lines concerning the current game. You can
     of course modify  some values before call this method.

EXPORT
------

   None by default.

AUTHOR
======

   Gilles Maire

   Gilles.Maire@ungi.net

SEE ALSO
========

   perl(1).

provide functions to administrate Circa,  a www search engine running with Mysql
********************************************************************************

NAME
====

   Circa::Indexer - provide functions to administrate Circa, a www search
engine running with Mysql

SYNOPSIS
========

     use Circa::Indexer;
     my $indexor = new Circa::Indexer;

     if (!$indexor->connect_mysql($user,$pass,$db))
     	{die "Erreur à la connection MySQL:$DBI::errstr\n";}

     $indexor->create_table_circa;

     $indexor->drop_table_circa;

     $indexor->addSite("http://www.alianwebserver.com/",
                       'alian@alianwebserver.com',
                       "Alian Web Server");

     my ($nbIndexe,$nbAjoute,$nbWords,$nbWordsGood) = $indexor->parse_new_url(1);
     print 	"$nbIndexe pages indexées,"
     	"$nbAjoute pages ajoutées,"
     	"$nbWordsGood mots indexés,"
     	"$nbWords mots lus\n";

     $indexor->update(30,1);

   Look in admin.pl,admin.cgi,admin_compte.cgi

DESCRIPTION
===========

   This is Circa::Indexer, a module who provide functions to administrate
Circa, a www search engine running with Mysql. Circa is for your Web site,
or for a list of sites.  It indexes like Altavista does. It can read, add
and parse all url's found in a page. It add url and word to MySQL for use
it at search.

   This module can:

Add url
Index words
Parse url, and so on.
Provide routine to administrate present url
   Remarques:

     - This file are not added : doc,zip,ps,gif,jpg,gz,pdf,eps,png,
       deb,xls,ppt,class,GIF,css,js,wav,mid
     - Weight for each word is in hash $ConfigMoteur

How it's work ?
---------------

   Circa parse html document. convert it to text. It count all word found
and put result in hash key. In addition of that, it read title, keywords,
description and add a weight to all word found.

   Example:

     my %ConfigMoteur=(
            'facteur_keyword'       =>15,
            'facteur_description'   =>10,
            'facteur_titre'         =>10,
            'facteur_full_text'     =>1,
            'niveau_max'		=>7,
            'nb_min_mots'           =>2
            );

     <html>
     <head>
     <meta name="KeyWords"
     CONTENT="informatique,computing,javascript,CGI,perl">
     <meta name="Description" CONTENT="Rubriques Informatique (Internet,Java,Javascript, CGI, Perl)">
     <title>Alian Web Server:Informatique,Société,Loisirs,Voyages,Expression</title>
     </head>
     <body>
     different word: cgi, perl, cgi
     </body>
     </html>

   After parsing I've a hash with that:

     $words{'informatique'}= 15 + 10 + 10 =35
     $words{'cgi'} = 15 + 10 +1
     $words{'different'} = 1

   Words is add to database if total found is >
$ConfigMoteur{'nb_min_mots'} (2 by default). But if you set to 1, database
will grow very quicly but allow you to perform very exact search with many
worlds so you can do phrase searches. But if you do that, think to take a
look at size of table relation.

   After page is read, it's look into html link. And so on. At each time,
the level grow to one. So if < to $Config{'niveau_max'}, url is added.

VERSION
=======

   $Revision: 1.8 $

Manipulation des attributs
==========================

size_max($size)
---------------

   Get or set size max of file read by indexer (For avoid memory pb).

set_agent
---------

port_mysql($port)
-----------------

   Get or set the MySQL port

host_indexed($host)
-------------------

   Get or set the host indexed.

proxy($adr_proxy)
-----------------

   Positionne le proxy a utiliser le cas écheant.

     $adr_proxy : Ex: 'http://proxy.sn.no:8001/'

prefix_table
------------

   Get or set the prefix for table name for use Circa with more than one
time on a same database

connect_mysql($user,$password,$db,$server)
------------------------------------------

     $user     : User MySQL
     $password : Password MySQL
     $db       : Database MySQL
     $server   : Adr IP MySQL

   Connect Circa to MySQL. Return 1 on succes, 0 else

close_connect
-------------

   Close connection to MySQL

Administrative globales methods
===============================

addSite($url,$email,$titre,$categorieAuto,$cgi,$rep,$file);
-----------------------------------------------------------

   Ajoute le site d'url $url, responsable d'adresse mail $email à la bd de
Circa

addLocalSite($url,$email,$titre,$local_url,$path,$urlRacine,$categorieAuto,$cgi,$rep,$file);
--------------------------------------------------------------------------------------------

   Add a local $url

updateUrl($compte,$id,$url,$urllocal,$titre,$description,$langue, 		 $categorie,$browse_categorie,$parse,$valide,$niveau,$last_check,$last_update)
--------------------------------------------------------------------------------------------------------------------------------------------------

   Update url $id on table $compte

parse_new_url($idp)
-------------------

   Parse les pages qui viennent d'être ajoutée. Le programme va analyser
toutes les pages dont la colonne 'parse' est égale à 0.

   Retourne le nombre de pages analysées, le nombre de page ajoutées, le
nombre de mots indexés.

update($xj,$idp)
----------------

   Reindexe les sites qui n'ont pas été mis à jour depuis plus de $xj jours

create_table_circa
------------------

   Cree la liste des tables necessaires à Circa:

     - categorie   : Catégories de sites
     - links       : Liste d'url
     - responsable : Lien vers personne responsable de chaque lien
     - relations   : Liste des mots / id site indexes
     - inscription : Inscriptions temporaires

drop_table_circa
----------------

   Detruit les tables de Circa

drop_table_circa_id
-------------------

   Detruit les tables de Circa pour l'utilisateur id

create_table_circa_id
---------------------

   Cree la liste des tables necessaires à Circa:

     - categorie   : Catégories de sites
     - links       : Liste d'url
     - relations   : Liste des mots / id site indexes
     - stats 	: Liste des requetes

Fonctions HTML
==============

start_classic_html
------------------

   Affiche le debut de document (<head></head>)

get_liste_liens($id)
--------------------

   Rend un buffer contenant une balise select initialisée avec les données
de la table links responsable $id

get_liste_liens_a_valider($id)
------------------------------

   Rend un buffer contenant une balise select initialisée avec les données
de la table links responsable $id liens non valides

get_liste_site
--------------

   Rend un buffer contenant une balise select initialisée avec les données
de la table responsable

get_liste_categorie($id)
------------------------

   Rend un buffer contenant une balise select initialisée avec les données
de la table categorie responsable $id

fill_template($masque,$vars)
----------------------------

     $masque : Chemin du template
     $vars : reference du hash des noms/valeurs à substituer dans le template

   Rend le template avec ses variables substituées.  Ex: si
$$vars{age}=12, et que le fichier $masque contient la chaine:

     J'ai <? $age ?> ans,

   la fonction rendra

     J'ai 12 ans,

Methode administration par compte
=================================

admin_compte($compte)
---------------------

   Retourne une liste d'elements se rapportant au compte $compte:

     $responsable	: Adresse mail du responsable
     $titre		: Titre du site pour ce compte
     $nb_page	: Nombre de page pour ce site
     $nb_words      : Nombre de mots indexés
     $last_index	: Date de la dernière indexation
     $nb_requetes	: Nombre de requetes effectuées sur ce site
     $racine	: 1ere page inscrite

most_popular_word($max,$id)
---------------------------

   Retourne la reference vers un hash representant la liste des $max mots
les plus présents dans la base de reponsable $id

delete_url($compte,$id_url)
---------------------------

   Supprime le lien $id_url de la table $compte/relation et $compte/links

valide_url($compte,$id_url)
---------------------------

   Supprime le lien $id_url de la table $compte/relation et $compte/links

delete_categorie($compte,$id)
-----------------------------

   Supprime la categorie $id pour le compte de responsable $compte et tous
les liens et relation qui sont dans cette categorie

rename_categorie($compte,$id,$nom)
----------------------------------

   Renomme la categorie $id pour le compte de responsable $compte en $nom

deplace_categorie($compte,$id1,$id2)
------------------------------------

   Move url from one categorie to another

inscription($email,$url,$titre)
-------------------------------

   Inscrit un site dans une table temporaire

Méthodes privées
================

look_at ($url,$idc,$idr,$lastModif,$url_local)
----------------------------------------------

   Ajoute les liens definis à l'URL $url à la base de donnée.  Indexe les
mots de chaque page

     $url : Url de la page à indexer
     $idc : Id de l'url dans la table links
     $idr : Id du responsable de cette url
     $lastModif : Ne parse pas la page si elle n'a pas été mis à jour
                  depuis cette date (facultatif)
     $url_local : Chemin local pour accéder au fichier (facultatif)

   Retourne (-1,0) si l'adresse est invalide, le nombre de liens trouvés
dans la page ainsi que le nombre de mots trouves sinon.

add_site($url,$idMan,[$local_url],[$browse_categorie],[$niveau],[$categorie])
-----------------------------------------------------------------------------

   Ajoute un site à la table links.

     $url   : Url de la page à ajouter
     $idMan : Id dans la table responsable du responsable de ce site

drop_site($id)
--------------

   Supprime un site de la table personne. Cela supprime egalement les
elements de la table links et relation qui appartiennent à ce site

     $id   : Id du site

get_meta($entete)
-----------------

   Parse et rend les meta-mots-clef et la meta-description de la page HTML
contenu dans $entete

analyse_data($data,$facteur,%l)
-------------------------------

   Recupere chaque mot du buffer $data et lui attribue une frequence
d'apparition.  Les resultats sont ranges dans le tableau associatif passé
en paramètre.  Les résultats sont rangés sous la forme
%l=('mots'=>facteur).

     $data : buffer à analyser
     $facteur : facteur à attribuer à chacun des mots trouvés
     %l : Tableau associatif où est rangé le résultat

   Retourne la référence vers le hash

getParent($id,%tab)
-------------------

   Rend la chaine correspondante à la catégorie $id avec ses rubriques
parentes

AUTHOR
======

   Alain BARBET alian@alianwebserver.com

provide functions to perform search on Circa, a www search engine running with Mysql
************************************************************************************

NAME
====

   Circa::Search - provide functions to perform search on Circa, a www
search engine running with Mysql

SYNOPSIS
========

     use Circa::Search;
     my $search = new Circa::Search;

     # Connection à MySQL
     if (!$search->connect_mysql("aliansql","pass","my_database","localhost"))
     	{die "Erreur à la connection MySQL:$DBI::errstr\n";}

     # Affichage d'un formulaire minimum
     print 	header,
     	$search->start_classic_html,
     	$search->default_form;

     # Interrogation du moteur
     # Sites trouves, liens pages suivantes, nb pages trouvees
     my ($resultat,$links,$indice) = $search->search('informatique internet',0,1);

DESCRIPTION
===========

   This is Circa::Search, a module who provide functions to perform search
on Circa, a www search engine running with Mysql. Circa is for your Web
site, or for a list of sites.  It indexes like Altavista does. It can
read, add and parse all url's found in a page. It add url and word to
MySQL for use it at search.

   Remarques sur la recherche:

     - Accents are removed on search and when indexed
     - Search are cas unsensitive (mmmh what my english ? ;-)

VERSION
=======

   $Revision: 1.5 $

port_mysql
----------

   Get or set the MySQL port

prefix_table
------------

   Get or set the prefix for table name for use Circa with more than one
time on a same database

Méthodes publiques
==================

connect_mysql($user,$password,$db)
----------------------------------

   Connecte l'application à MySQL. Retourne 1 si succes, 0 sinon

     $user     : Utilisateur MySQL
     $password : Mot de passe MySQL
     $db       : Database MySQL
     $server   : Adr IP du serveur MySQL

search($template,$mot,$first,$id,$langue,$url,$create,$update,$catego)
----------------------------------------------------------------------

   Fonction permettant d'effectuer une recherche par mot dans Circa

   Paramètres :

     $template : Masque HTML pour le resultat de chaque lien. Si undef, le masque par defaut
     (defini en haut de ce module) sera utilise. La liste des variables définies au
     moment du eval sont : $indiceG,$titre,$description,$url,$facteur,$last_update,$langue

      Exemple de masque :

      '"<p>$indiceG - <a href=\"$url\">$titre</a> $description<br>
       <font class=\"small\"><b>Url:</b> $url <b>Facteur:</b> $facteur
       <b>Last update:</b> $last_update </font></p>\n"'

     $mot    : Séquence des mots recherchés tel que tapé par l'utilisateur
     first   : Indice du premier site affiché dans le résultat
     $id     : Id du site dans lequel effectué la recherche
     $langue : Restriction par langue (facultatif)
     $Url    : Restriction par url : les url trouvées commenceront par $Url (facultatif)
     $create : Restriction par date inscription. Format YYYY-MM-JJ HH:MM:SS (facultatif)
     $update : Restriction par date de mise à jour des pages. Format YYYY-MM-JJ HH:MM:SS (facultatif)
     $catego : Restriction par categorie (facultatif)

     Retourne ($resultat,$links,$indice)

     $resultat : Buffer HTML contenant la liste des sites trouves formaté en fonction
                 de $template et des mots present dans $mots
     $links    : Liens vers les pages suivantes / precedentes
     $indice   : Nombre de sites trouves

search_word($tab,$word,$idc,$langue,$Url,$create,$update,$categorie)
--------------------------------------------------------------------

   Construction de la requete SQL. Son exploitation est faite par search

     $tab    : Reference du hash où mettre le resultat
     $word   : Mot recherché
     $id     : Id du site dans lequel effectué la recherche
     $langue : Restriction par langue (facultatif)
     $Url    : Restriction par url
     $create : Restriction par date inscription
     $update : Restriction par date de mise à jour des pages
     $catego : Restriction par categorie

   Retourne la reference du hash avec le resultat de la recherche sur le
mot $word Le hash est constitué comme tel:

     $tab{$url}[0] : titre
     $tab{$url}[1] : description
     $tab{$url}[2] : facteur
     $tab{$url}[3] : langue
     $tab{$url}[4] : date de dernière modification
        @{$$tab{$url}[5]}: liste des mots trouves pour cet url

categories_in_categorie($id,$idr,$template)
-------------------------------------------

   Fonction retournant la liste des categories de la categorie $id dans le
site $idr

     $id       : Id de la categorie de depart. Si undef, 0 est utilisé (Considéré comme le "Home")
     $idr	   : Id du responsable
     $template : Masque HTML pour le resultat de chaque lien. Si undef, le masque par defaut
                 (defini en haut de ce module) sera utlise

   Retourne ($resultat,$nom_categorie) :

     $resultat : Buffer contenant la liste des sites formatées en ft de $template
     $nom_categorie : Nom court de la categorie

sites_in_categorie($id,$idr,$template)
--------------------------------------

   Fonction retournant la liste des pages de la categorie $id dans le site
$idr

     $id       : Id de la categorie de depart. Si undef, 0 est utilisé (Considéré comme le "Home")
     $idr	   : Id du responsable
     $template : Masque HTML pour le resultat de chaque lien. Si undef, le masque par defaut
                 (defini en haut de ce module) sera utlise

   Retourne le buffer contenant la liste des sites formatées en ft de
$template

getParent($id,$idr,%tab)
------------------------

   Rend la chaine correspondante à la catégorie $id avec ses rubriques
parentes

get_link($no_page)
------------------

   Retourne l'URL correspondant à la page no $no_page dans la recherche en
cours

get_link_categorie($no_categorie,$id)
-------------------------------------

   Retourne l'URL correspondant à la categorie no $no_categorie

start_classic_html
------------------

   Affiche le debut de document (<head></head>)

fill_template($masque,$vars)
----------------------------

     $masque : Chemin du template
     $vars : hash des noms/valeurs à substituer dans le template

   Rend le template avec ses variables substituées.  Ex: si
$$vars{age}=12, et que le fichier $masque contient la chaine:

     J'ai <? $age ?> ans,

   la fonction rendra

     J'ai 12 ans,

advanced_form($id)
------------------

   Affiche un formulaire minimum pour effectuer une recherche sur Circa

default_form
------------

   Affiche un formulaire minimum pour effectuer une recherche sur Circa

get_liste_langue
----------------

   Retourne le buffer HTML correspondant à la liste des langues disponibles

get_first($requete)
-------------------

   Retourne la premiere ligne du resultat de la requete $requete sous la
forme d'un tableau

get_masque
----------

get_name_site($id)
------------------

   Retourne le nom du site dans la table responsable correspondant à l'id
$id

get_liste_categorie_fils($id,$idr)
----------------------------------

     $id : Id de la categorie parent
     $idr : Site selectionne

   Retourne la liste des categories fils de $id dans le site $idr

AUTHOR
======

   Alain BARBET alian@alianwebserver.com

Perl module for configuring Cisco routers via TFTP
**************************************************

NAME
====

   Cisco::Conf - Perl module for configuring Cisco routers via TFTP

SYNOPSIS
========

     use Cisco::Conf;

     # Set the path of the main configuration file
     $configFile = '/usr/local/cisco/etc/config';

     # Add a new machine to the configuration file
     Cisco::Conf->Add($configFile,
     		   {'name' => 'myrouter',
     		    'description' => 'My Internet gateway',
     		    'users' => ['root', 'joe'],
     		    'host' => '192.168.1.1',
     		    'username' => 'itsme',
     		    'password' => 'secret',
     		    'enable_password' => undef  # Prompt password
     		   });

     # Remove a machine from the configuration file
     Cisco::Conf->Remove($configFile, 'myrouter');

     # Create a configuration object by reading it from the
     # configuration file
     $conf = Cisco::Conf->Read($configFile, 'myrouter');

     # Edit a machine's configuration (uses $ENV{'EDITOR'})
     $conf->Edit($editor, $file, $tmpDir);

     # Feed a machine's configuration into RCS
     $conf->RCS($file, "in");

     # Load a machine's configuration and save it in 'myfile'
     $conf->Load('myfile');

     # Strip comments from a machine configuration in $configuration
     $stripped = Cisco::Conf->Strip($configuration);

     # Read a configuration from 'myfile' and save it into the router
     $conf->Save('myfile', $write);

     # Return a list of all configurations that the current user may
     # access
     @list = Cisco::Conf->Info($configFile);

DESCRIPTION
===========

   This module offers a set of methods for creating and managing Cisco
configurations. Configurations are stored as plain text files, including
comments. Comments are indicated by an exclamation mark and may terminate
any line. Example:

     ! Here come the interfaces
     interface Ethernet 0   ! Local LAN
     ...

   All methods throw a Perl exception in case of errors, thus you should
encapsulate them with an eval, like this:

     $@ = '';
     eval {
         Cisco::Conf->Add('/usr/local/cisco/etc/configurations',
     			 {'name' => 'myrouter',
     			  ...
     			 });
     };
     if ($@) {
     	print STDERR "An error occurred: $@\n";
     	exit 1;
     }

   The following methods are offered by the module:

Add($configFile, \%attr)
------------------------

   (Class method) Adds a new configuration to the list of configurations
in the file `$configFile'. A configuration is represented by the hash ref
`\%attr' with a number of attributes, including

name
     A symbolic and short name for the configuration, unique in the list
     of configurations.

description
     A textual description of the configuration.

host
     The routers host name or IP address

username
password
enable_password
     The routers username, login and enable passwords. If these attributes
     are not present or have a value of undef, the methods will prompt for
     passwords.

file
     File name where the machine configuration is stored, for example
     `/usr/local/cisco/etc/mycisco.conf'.

   Only root may add or remove configurations.

Remove($configFile, $name)
--------------------------

   (Class method) Removes configuration $name from the list of
configurations in the file `$configFile'.

   Only root may add or remove configurations.

Read($configFile, $name)
------------------------

   (Class method) Reads the configuration of the host $name from the
configuration file `$configFile' and returns a *Cisco::Conf* instance
representing the host.

Edit($editor, $file, $tmpDir)
-----------------------------

   (Instance method) Invoke the editor `$editor' to edit the configuration
file. If $editor is not defined, use $ENV{'EDITOR'} or the first editor
from the list of editors in the configuration file. (The *editors*
attribute.)

   For security reasons valid editors are restricted to those from the
configuration file. Editing takes place in the directory $tmpDir, so that
we can change the EUID to the users.

   Example:

     $self->Edit('emacs', 'myrouter.conf', '/tmp');

RCS($file, $inout)
------------------

   (Instance method) Invoke the revision control system (RCS) by using the
ci attribute from the config file

   Example:

     $self->RCS($file, "in");

Strip($configuration)
---------------------

   (Class method) Strips comments and empty lines from the machine
configuration in the string `$configuration' and returns the resulting
string.

   Comments may appear on any line, beginning with an exclamation mark.
Example:

     ! This is a comment
     interface Ethernet 0  ! Another comment

Load($file)
-----------

   (Instance method) Loads the current configuration from the host and
saves it into the file $file. If such a file already exists, it will be
overwritten silently: It is the calling functions task to emit a warning
or do whatever appropriate.

   You cannot choose arbitrary file names for $file: The location depends
on the settings of your local TFTP server. In particular you have to
*have* a local TFTP server running. :-) See `tftpd(1)' in this node for
details.

   Note that the file mode of $file will be 0666, on other words, the file
is readable and writeable for the world! You should change this as soon as
possible.

Save($file, $write)
-------------------

   (Instance method) Reads a machines configuration from $file and save it
into the router. Like with the Load method, possible locations of $file
depend on your TFTP servers settings.

   Note that the file mode of $file will be changed to 0444, on other
words, the file is readable for the world! You should change this as soon
as possible.

   If the argument $write is TRUE, the configuration will be saved into
the non-volatile memory by executing the command

     write memory

Info($configFile)
-----------------

   (Class method) Read a list of all configurations in `$configFile' and
return those configurations that are accessible by the current user.

EtcFile($config)
----------------

   (Instance method) Returns a routers config file name.

TftpFile($config)
-----------------

   (Instance method) Returns a routers TFTP file name.

CREDITS
=======

Esfandiar Tabari <Esfandiar_Tabari@hugoboss.com>
     for giving me the contract that included the cisconf script. :-)

Tungning Cheng <cherng@bbn.com>
     for fixing the nasty open file bug ...

Mike Newton <mike@delusion.org>
     for adding the username and supporting the Rcs module.

AUTHOR AND COPYRIGHT
====================

   This module is

     Copyright (C) 1998    Jochen Wiedmann
                           Am Eisteich 9
                           72555 Metzingen
                           Germany

     Phone: +49 7123 14887
     Email: joe@ispsoft.de

   All rights reserved.

   You may distribute this module under the terms of either the GNU
General Public License or the Artistic License, as specified in the Perl
README file.

SEE ALSO
========

   `cisconf(1)' in this node

Create a configuration file for the Cisco::Conf module
******************************************************

NAME
====

   Cisco::Conf::Install - Create a configuration file for the Cisco::Conf
module

SYNOPSIS
========

     use Cisco::Conf::Install;
     Cisco::Conf::Install->Install($file, $prefix);

DESCRIPTION
===========

   This module is used to create configuration files for the Cisco::Conf
module. It holds a single class method, *Install*, that attempts to guess
the system defaults and queries the user for all settings.

   The prefix `$prefix' is used as a default for certain directory
settings.  The configuration is saved as $file. A hash ref with all
configuration is returned, the method dies in case of errors.

   The configuration file initially holds an empty list of routers. Use
the Add method or the -a option of the *cisconf* script to add routers.

AUTHOR AND COPYRIGHT
====================

   This module is

     Copyright (C) 1998    Jochen Wiedmann
                           Am Eisteich 9
                           72555 Metzingen
                           Germany

     Phone: +49 7123 14887
     Email: joe@ispsoft.de

   All rights reserved.

   You may distribute this module under the terms of either the GNU
General Public License or the Artistic License, as specified in the Perl
README file.

SEE ALSO
========

   `cisconf(1)' in this node, `Cisco::Conf(3)' in this node

Automated accessor generation
*****************************

NAME
====

     Class::Accessor - Automated accessor generation

SYNOPSIS
========

     package Foo;

     use base qw(Class::Accessor);
     Foo->mk_accessors(qw(this that whatever));

     # Meanwhile, in a nearby piece of code!
     # Class::Accessor provides new().
     my $foo = Foo->new;

     my $whatever = $foo->whatever;    # gets $foo->{whatever}
     $foo->this('likmi');              # sets $foo->{this} = 'likmi'

     # Similar to @values = @{$foo}{qw(that whatever)}
     @values = $foo->get(qw(that whatever));

     # sets $foo->{that} = 'crazy thing'
     $foo->set('that', 'crazy thing');

DESCRIPTION
===========

   This module automagically generates accessor/mutators for your class.

   Most of the time, writing accessors is an exercise in cutting and
pasting.  You usually wind up with a series of methods like this:

     # accessor for $obj->{foo}
     sub foo {
         my($self) = shift;

     if(@_ == 1) {
         $self->{foo} = shift;
     }
     elsif(@_ > 1) {
         $self->{foo} = [@_];
     }

     return $self->{foo};
       }

     # accessor for $obj->{bar}
     sub bar {
         my($self) = shift;

     if(@_ == 1) {
         $self->{bar} = shift;
     }
     elsif(@_ > 1) {
         $self->{bar} = [@_];
     }

     return $self->{bar};
       }

     # etc...

   One for each piece of data in your object.  While some will be unique,
doing value checks and special storage tricks, most will simply be
exercises in repetition.  Not only is it Bad Style to have a bunch of
repetitious code, but its also simply not Lazy, which is the real tragedy.

   If you make your module a subclass of Class::Accessor and declare your
accessor fields with mk_accessors() then you'll find yourself with a set
of automatically generated accessors which can even be customized!

   The basic set up is very simple:

     package My::Class;
     use base qw(Class::Accessor);
     My::Class->mk_accessors( qw(foo bar car) );

   Done.  My::Class now has simple foo(), bar() and car() accessors
defined.

What Makes This Different?
--------------------------

   What makes this module special compared to all the other method
generating modules (`"SEE ALSO"' in this node)?  By overriding the get()
and set() methods you can alter the behavior of the accessors class-wide.
Also, the accessors are implemented as closures which should cost a bit
less memory than most other solutions which generate a new method for each
accessor.

Methods
-------

new
          my $obj = Class->new;
          my $obj = $other_obj->new;

          my $obj = Class->new(\%fields);
          my $obj = $other_obj->new(\%fields);

     Class::Accessor provides a basic constructor.  It generates a
     hash-based object and can be called as either a class method or an
     object method.

     It takes an optional %fields hash which is used to initialize the
     object (handy if you use read-only accessors).  The fields of the hash
     correspond to the names of your accessors, so...

          package Foo;
          use base qw(Class::Accessor);
          Foo->mk_accessors('foo');

          my $obj = Class->new({ foo => 42 });
          print $obj->foo;    # 42

     however %fields can contain anything, new() will shove them all into
     your object.  Don't like it?  Override it.

mk_accessors
          Class->mk_accessors(@fields);

     This creates accessor/mutator methods for each named field given in
     @fields.  Foreach field in @fields it will generate two accessors.
     One called "field()" and the other called "_field_accessor()".  For
     example:

          # Generates foo(), _foo_accessor(), bar() and _bar_accessor().
          Class->mk_accessors(qw(foo bar));

     See `CAVEATS AND TRICKS' in this node for details.

mk_ro_accessors
mk_readonly_accessors
          Class->mk_ro_accessors(@read_only_fields);

     Same as mk_accessors() except it will generate read-only accessors
     (ie. true accessors).  If you attempt to set a value with these
     accessors it will throw an exception.  It only uses get() and not
     set().

          package Foo;
          use base qw(Class::Accessor);
          Class->mk_ro_accessors(qw(foo bar));

          # Let's assume we have an object $foo of class Foo...
          print $foo->foo;  # ok, prints whatever the value of $foo->{foo} is
          $foo->foo(42);    # BOOM!  Naughty you.

mk_wo_accessors
          Class->mk_wo_accessors(@write_only_fields);

     Same as mk_accessors() except it will generate write-only accessors
     (ie. mutators).  If you attempt to read a value with these accessors
     it will throw an exception.  It only uses set() and not get().

     NOTE I'm not entirely sure why this is useful, but I'm sure someone
     will need it.  If you've found a use, let me know.  Right now its here
     for orthoginality and because its easy to implement.

          package Foo;
          use base qw(Class::Accessor);
          Class->mk_wo_accessors(qw(foo bar));

          # Let's assume we have an object $foo of class Foo...
          $foo->foo(42);      # OK.  Sets $self->{foo} = 42
          print $foo->foo;    # BOOM!  Can't read from this accessor.

   The rest is details.

DETAILS
=======

   An accessor generated by Class::Accessor looks something like this:

     # Your foo may vary.
     sub foo {
         my($self) = shift;
         if(@_) {    # set
             return $self->set('foo', @_);
         }
         else {
             return $self->get('foo');
         }
     }

   Very simple.  All it does is determine if you're wanting to set a value
or get a value and calls the appropriate method.  Class::Accessor provides
default get() and set() methods which your class can override.  They're
detailed later.

Modifying the behavior of the accessor
--------------------------------------

   Rather than actually modifying the accessor itself, it is much more
sensible to simply override the two key methods which the accessor calls.
Namely set() and get().

   If you -really- want to, you can override make_accessor().

set
          $obj->set($key, $value);
          $obj->set($key, @values);

     set() defines how generally one stores data in the object.

     override this method to change how data is stored by your accessors.

get
          $value  = $obj->get($key);
          @values = $obj->get(@keys);

     get() defines how data is retreived from your objects.

     override this method to change how it is retreived.

make_accessor
          $accessor = Class->make_accessor($field);

     Generates a subroutine reference which acts as an accessor for the
     given $field.  It calls get() and set().

     If you wish to change the behavior of your accessors, try overriding
     get() and set() before you start mucking with make_accessor().

make_ro_accessor
          $read_only_accessor = Class->make_ro_accessor($field);

     Generates a subroutine refrence which acts as a read-only accessor for
     the given $field.  It only calls get().

     Override get() to change the behavior of your accessors.

make_wo_accessor
          $read_only_accessor = Class->make_wo_accessor($field);

     Generates a subroutine refrence which acts as a write-only accessor
     (mutator) for the given $field.  It only calls set().

     Override set() to change the behavior of your accessors.

EFFICIENCY
==========

   Class::Accessor does not employ an autoloder, thus it is much faster
than you'd think.  Its generated methods incur no special penalty over
ones you'd write yourself.

   Here's the results of benchmarking Class::Accessor,
Class::Accessor::Fast, a hand-written accessor and direct hash access
(generated by examples/bench).

     Benchmark: timing 500000 iterations of By Hand - get, By Hand - set,
       C::A - get, C::A - set, C::A::Fast - get, C::A::Fast - set,
       Direct - get, Direct - set...

     By Hand - get:  4 wallclock secs ( 5.09 usr +  0.00 sys =  5.09 CPU)
                     @ 98231.83/s (n=500000)
     By Hand - set:  5 wallclock secs ( 6.06 usr +  0.00 sys =  6.06 CPU)
                     @ 82508.25/s (n=500000)
     C::A - get:  9 wallclock secs ( 9.83 usr +  0.01 sys =  9.84 CPU)
                  @ 50813.01/s (n=500000)
     C::A - set: 11 wallclock secs ( 9.95 usr +  0.00 sys =  9.95 CPU)
                  @ 50251.26/s (n=500000)
     C::A::Fast - get:  6 wallclock secs ( 4.88 usr +  0.00 sys =  4.88 CPU)
                        @ 102459.02/s (n=500000)
     C::A::Fast - set:  6 wallclock secs ( 5.83 usr +  0.00 sys =  5.83 CPU)
                        @ 85763.29/s (n=500000)
     Direct - get:  0 wallclock secs ( 0.89 usr +  0.00 sys =  0.89 CPU)
                    @ 561797.75/s (n=500000)
     Direct - set:  2 wallclock secs ( 0.87 usr +  0.00 sys =  0.87 CPU)
                    @ 574712.64/s (n=500000)

   So Class::Accessor::Fast is just as fast as one you'd write yourself
while Class::Accessor is twice as slow, a price paid for flexibility.
Direct hash access is about six times faster, but provides no
encapsulation and no flexibility.

   Of course, its not as simple as saying "Class::Accessor is twice as
slow as one you write yourself".  These are benchmarks for the simplest
possible accessor, if your accessors do any sort of complicated work (such
as talking to a database or writing to a file) the time spent doing that
work will quickly swamp the time spend just calling the accessor.  In that
case, Class::Accessor and the ones you write will tend to be just as fast.

EXAMPLES
========

   Here's an example of generating an accessor for every public field of
your class.

     package Altoids;

     use base qw(Class::Accessor Class::Fields);
     use fields qw(curiously strong mints);
     Altoids->mk_accessors( Altoids->show_fields('Public') );

     sub new {
         my $proto = shift;
         my $class = ref $proto || $proto;
         return fields::new($class);
     }

     my Altoids $tin = Altoids->new;

     $tin->curiously('Curiouser and curiouser');
     print $tin->{curiously};    # prints 'Curiouser and curiouser'

     # Subclassing works, too.
         package Mint::Snuff;
         use base qw(Altoids);

     my Mint::Snuff $pouch = Mint::Snuff->new;
     $pouch->strong('Fuck you up strong!');
     print $pouch->{strong};     # prints 'Fuck you up strong!'

   Here's a simple example of altering the behavior of your accessors.

     package Foo;
     use base qw(Class::Accessor);
     Foo->mk_accessor(qw(this that up down));

     sub get {
         my($self, @keys) = @_;

     # Note every time someone gets some data.
     print STDERR "Getting @keys\n";

     $self->SUPER::get(@keys);
         }

     sub set {
         my($self, $key, @values) = @_;

     # Note every time someone sets some data.
     print STDERR "Setting $key to @values\n";

     $self->SUPER::set($key, @values);
         }

CAVEATS AND TRICKS
==================

   Class::Accessor has to do some internal wackiness to get its job done
quickly and efficiently.  Because of this, there's a few tricks and traps
one must know about.

   Hey, nothing's perfect.

Don't make a field called DESTROY
---------------------------------

   This is bad.  Since DESTROY is a magical method it would be bad for us
to define an accessor using that name.  Class::Accessor will carp if you
try to use it with a field named "DESTROY".

Overriding autogenerated accessors
----------------------------------

   You may want to override the autogenerated accessor with your own, yet
have your custom accessor call the default one.  For instance, maybe you
want to have an accessor which checks its input.  Normally, one would
expect this to work:

     package Foo;
     use base qw(Class::Accessor);
     Foo->mk_accessors(qw(email this that whatever));

     # Only accept addresses which look valid.
     sub email {
         my($self) = shift;
         my($email) = @_;

     if( @_ ) {  # Setting
         require Email::Valid;
         unless( Email::Valid->address($email) ) {
             carp("$email doesn't look like a valid address.");
             return;
         }
     }

     return $self->SUPER::email(@_);
         }

   There's a subtle problem in the last example, and its in this line:

     return $self->SUPER::email(@_);

   If we look at how Foo was defined, it called mk_accessors() which stuck
email() right into Foo's namespace.  There *is* no SUPER::email() to
delegate to!  Two ways around this... first is to make a "pure" base class
for Foo.  This pure class will generate the accessors and provide the
necessary super class for Foo to use:

     package Pure::Organic::Foo;
     use base qw(Class::Accessor);
     Pure::Organic::Foo->mk_accessors(qw(email this that whatever));

     package Foo;
     use base qw(Pure::Organic::Foo);

   And now Foo::email() can override the generated
Pure::Organic::Foo::email() and use it as SUPER::email().

   This is probably the most obvious solution to everyone but me.
Instead, what first made sense to me was for mk_accessors() to define an
alias of email(), _email_accessor().  Using this solution, Foo::email()
would be written with:

     return $self->_email_accessor(@_);

   instead of the expected SUPER::email().

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

THANKS
======

   Thanks to Tels for his big feature request/bug report.

SEE ALSO
========

   See Class/Accessor/Fast,

   These are some modules which do similar things in different ways
Class/Struct, `Class::Methodmaker' in this node, see
Class/Generate, Class/Class,
Class/Contract,

   See Class/DBI, for an example of this module in use.

Faster, but less expandable, accessors
**************************************

NAME
====

   Class::Accessor::Fast - Faster, but less expandable, accessors

SYNOPSIS
========

     package Foo;
     use base qw(Class::Accessor::Fast);

     # The rest as Class::Accessor except no set() or get().

DESCRIPTION
===========

   This is a somewhat faster, but less expandable, version of
Class::Accessor.  Class::Accessor's generated accessors require two method
calls to accompish their task (one for the accessor, another for get() or
set()).  Class::Accessor::Fast eliminates calling set()/get() and does the
access itself, resulting in a somewhat faster accessor.

   The downside is that you can't easily alter the behavior of your
accessors, nor can your subclasses.  Of course, should you need this
later, you can always swap out Class::Accessor::Fast for Class::Accessor.

EFFICIENCY
==========

   `EFFICIENCY', see Class/Accessor, for an efficiency
comparison.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Class/Accessor,

Defer loading ( 'use'ing ) of a class until run time
****************************************************

NAME
====

   Class::Autouse - Defer loading ( 'use'ing ) of a class until run time

SYNOPSIS
========

     use Class::Autouse;

     Class::Autouse->autouse( 'CGI' );

     print CGI->header();

DESCRIPTION
===========

   Class::Autouse allows you to specify a class the will only load when a
method of the class is called. For large classes that might not be used
during the running of a program, such as Date::Manip, this can save you
large amounts of memory, and decrease the script load time.

AUTHOR
======

   Adam Kennedy, cpan@ali.as

SEE ALSO
========

   autoload

base class to treat unhandled method calls as no-ops
****************************************************

NAME
====

   Class::BlackHole - base class to treat unhandled method calls as no-ops

SYNOPSIS
========

     use Class::BlackHole;

     # set up a class X, to inherit from Class::BlackHole
     @X::ISA = qw(Class::BlackHole);
     # put a method in it
     sub X::zaz { 123123; }

     print "Zaz is <", X->zaz, ">\n";
     print "Flork is <", X->flork, ">\n";
     print "can zaz : <", X->can('zaz'), ">\n";
     print "can flork : <", X->can('flork'), ">\n";

     The above code prints:
      Zaz is <123123>
      Flork is <>
      can zaz : <CODE(0x392c7d4)>
      can flork : <>

DESCRIPTION
===========

   Normally, if you try to call a method that there's no handler for, you
get an error:

     Can't locate object method "flork" via package "X".

   But for classes that inherit from Class::BlackHole, unhandled methods
become just no-operations.

CAVEATS
=======

   Be sure to have Class::BlackHole be the absolute last item in your
class's ISA list.

   This class will almost definitely not work right as part of any ISA
tree that has multiple inheritance.

IMPLEMENTATION
==============

   Class::BlackHole just traps everything with an AUTOLOAD sub that is a
no-operation.

   HOWEVER, what makes Class::Blackhole different than merely:

     @Class::BlackHole::ISA = ();
     sub Class::BlackHole::AUTOLOAD { }

   is that this would (unhappily) trap calls to the helpful methods in
UNIVERSAL, like can, VERSION, and isa.  Class::BlackHole aliases those
methods (or better said, all subs in package UNIVERSAL) into its own
package, so that they'll be accessible instead of being caught by the
AUTOLOAD.

FUNCTIONS AND METHODS
=====================

   This module provides no functions or methods.

   It exports no symbols into the calling package or anywhere else.

DISCLAIMER
==========

   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*.

   But let me know if it gives you any problems, OK?

COPYRIGHT
=========

   Copyright 1999, 2000, Sean M. Burke `sburke@cpan.org', all rights
reserved.  This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

AUTHOR
======

   Sean M. Burke `sburke@cpan.org'

Adds data members to Perl packages
**********************************

NAME
====

   Class::Class - Adds data members to Perl packages

SYNOPSIS
========

   In module MyModule.pm:

     package MyModule;
     use Class::Class;
     @ISA = qw (Class::Class);

     %MEMBERS =
       (scalar_ => '$', # "scalar" is a keyword
        scalarref => '\$',
        array => '@',
        arrayref => '\@',
        hash => '%',
        hashref => '\%',
        glob => '*',
        globref => '\*',
        object => 'Some::Package',
        objectref => '\Some::Package');

     sub initialize ($) {
       my ($self) = @_;

     # object initialization goes here: DO NOT USE 'new'

     return $self;
       }

     sub deinitialize ($) {
       my ($self) = @_;

     # object cleanup (if any) goes here: DO NOT USE 'DESTROY'

     return $self;
       }

   In other files which wish to use MyModule:

     use MyModule;

     my $mm = new MyModule;

     $mm->scalar_ (42); # set "scalar_" to 42
     $mm->scalar_ ( ); # get value of "scalar_"
     $mm->scalarref (1.1); # set "scalarref" to 1.1
     $mm->scalarref ( ); # get reference to value of "scalarref"

     $mm->array ( ); # get arrayref stored in "array"
     $mm->array (1); # get 2nd element of "array"
     $mm->array (1, 'fish'); # set 2nd element of "array" to 'fish'
     $mm->arrayref ( ); # get arrayref stored in "arrayref"
     $mm->arrayref (1); # get reference to 2nd element of "arrayref"
     $mm->arrayref (1, 'fish'); # set 2nd element of "arrayref" to 'fish'

     $mm->hash ( ); # get hashref stored in "hash"
     $mm->hash ('bob'); # get 'bob' element of "hash"
     $mm->hash ('bob', 'one'); # set 'bob' element of "hash" to 'one'
     $mm->hashref ( ); # get hashref stored in "hashref"
     $mm->hashref ('bob'); # get reference to 'bob' element of "hashref"
     $mm->hashref ('bob', 'one'); # set 'bob' element of "hashref" to 'one'

     open G, '<blah.txt';
     $mm->glob (*G); # set "glob" to *G
     $mm->glob ( ); # get value of "glob"
     use Symbol;
     $mm->globref (gensym); # set "globref" to anonymous symbol
     $mm->globref ( ); # get reference to value of "globref"

     $mm->object ( ); # get object in "object"
     $mm->object->method; # invoke method on object in "object"
     $mm->objectref ( ); # get reference to object in "objectref"

DESCRIPTION
===========

   *Class::Class* implements inheritable data methods for your packages
with the same rules of inheritance as your other methods by generating
creating accessor methods for your data the first time you make an
instance of your package.

   Why reinvent the wheel, you say?  I got tired of the way Class::Struct
worked, since the methods weren't inheritable the way I expected (no
initialization of parent members before child members, for example), it
was invoked programatically rather than declaratively, and I wanted to
learn more about globs and the like.  Plus I have a big head.  :-)

Using Class::Class Modules
--------------------------

   Using *Class::Class* modules is very simple.  Just inherit from them as
normal, but don't bother with writing a new method - *Class::Class*
provides one for you that arranges for superclasses to be initialized
before subclasses.  It also takes multiple inheritance into account
(correctly, I hope).

   To initialize your package, instead of `sub new', write a `sub
initialize' which takes an instance of your package as its only argument,
and returns an instance:

     sub initialize ($) {
       my ($self) = @_;

     # Do something clever here with your object...

     return $self;
       }

   There is no requirement you return the same instance that was handed to
you.  The methods `polymorph' and `polyvolve' are provided for this very
purpose, to help with "virtual constructors".

Writing Class::Class Modules
----------------------------

   Writing *Class::Class* modules is straight-forward.

Polymorph and Polyvolve
-----------------------

`polymorph'
`polyvolve'
EXAMPLES
========

Using Class::Class Modules
--------------------------

  1. Simple use:

Writing Class::Class Modules
----------------------------

  1. Setting a package global:

SEE ALSO
========

   See Class/ISA,

   *Class::ISA* creates an inverted inheritance tree, permitting easy
traversal of a packages entire inheritance.

DIAGNOSTICS
===========

   The following are the diagnostics generated by *Class::Class*.  Items
marked "(W)" are non-fatal (invoke `Carp::carp'); those marked "(F)" are
fatal (invoke `Carp::croak').

Not a class or subclass of '%s'
     (F) The caller tried to assign to an object data member something
     which isn't an instance of that object's class, or which isn't an
     instance of a derived class.

No coderef defined for '%s' yet
     (F) The caller tried to use a code reference without first providing
     assigning a coderef to the member.

BUGS AND CAVEATS
================

   Presently, *Class::Class* uses hashes for data members; array are
demonstrably better for several reasons (see XXX - *TPJ*) if you don't
need direct access to data members by name.  And even if you do, fields
shows a good way to do that with recent versions of Perl.

AUTHORS
=======

   B. K. Oxley (binkley) at Home <binkley@bigfoot.com>

COPYRIGHT
=========

     Copyright 1999, B. K. Oxley (binkley).

   This library is free software; you may redistribute it and/or modify it
under the same terms as Perl itself.

generates all get- and set-methods for new classes created by classgen.
***********************************************************************

NAME
====

   Attribute.pm - generates all get- and set-methods for new classes
created by classgen.

VERSION
=======

   3.03

SYNOPSIS
========

   Within classgen called as:

     use Attribute;			# work with object Attribute
     my $attr = Attribute->new();	# derive a new Attribute instance $attr

   Let Ex.pm be a generated class, with internal variables $var, %entry
and @list:

     use Ex.pm;			# use generated class
     my $ex=Ex->new();		# creating a new object
     $ex->set_var('this is a test');	# setting instance variable $var
     $ex->set_h_entry( 12, twelve );	# like $entry{12}='twelve'
     $ex->set_h_entry( 60, sixty );	#
     $ex->set_l_list( 3, -100 );	# like $list[3]=-100;
     $x=$ex->get_var();		# like $x=$var;
     $x=$ex->get_h_entry(12);
     @keys=$ex->get_keys_h_entry();	# get all keys of internal %entry
     etc.

DESCRIPTION
===========

   It is good OOP-style to access and manipulate instance variables of a
class NEVER by a direct call, but via appropriate methods. You should
always follow this concept to avoid problems when inheriting from your
object oriented code.

   classgen has been designed for exactly this purpose: To have all
necessary methods available for all instance variables. Right from the
start.

General syntax for generated methods
------------------------------------

   The methods name itself should uniquely identify the type of instance
variable accessed or modified. So the general method convention is:

   * methodname_scalarname to work on a scalar instance

   * methodname_h_hashname to work on a hash instance

   * methodname_l_listname to work on a list instance

   With this convention you will always know what to expect, e.g.:

     use Example;
     $ex = Example->new();
     ...
     print $ex->get_number;		# access instance variable $number
     print $ex->get_l_cities;	# access instance variable @cities
     print $ex->get_keys_h_country;	# get keys of inst.var. %country

   For %hashes and @lists it is sometimes necessary to access the
reference of the instance variable. Then use:

   * methodname_rh_hashname to find the reference of a %hash instance

   * methodname_rl_listname to find the reference of a @list instance

   Some other methods deviate from these rules when purpose and involved
type of instance variable are self evident. See below.

Generated methods for $scalars
------------------------------

   For all $scalar instance variables in classgens control file
Attribute.pm generates (the phrase 'scalar' is replaced by the actual name
of the $scalar instance variable):

   * clear_scalar(): generated clear() method for $scalars

   * get_scalar(): generated accessor method for $scalars

   * set_scalar($value): generated manipulator for $scalars

Example: control file contains $var of class Example.
-----------------------------------------------------

   Attribute generates clear_var(), get_var() and set_var. Class Example
can be used like:

     use Example;	# use object Example
     use strict;	# recommended

     my $ex = Example->new();	# creating a new Example instance
     $ex->clear_var();		# set $var in Example to undef
     $ex->set_var( "what a wonderful day" );

     print $ex->get_var();

Generated methods for %hashes
-----------------------------

   For all %hash instance variables in classgens control file Attribute.pm
generates (the phrase 'hash' is replaced by the actual name of the %hash
instance variable):

   * clear_h_hash(): generated clear() method for %hashes

   * delete_h_hash_at($key): deletes $key from internal %hash.

   * get_h_hash(): generated accessor to the %hash itself

   * get_h_hash_at($key): generated key-based accessor to %hash

   * get_keys_h_hash(): generated key-accessor for %hashes

   * get_rh_hash(): generated accessor to \%hashes

   * set_h_hash($key, $value): generated manipulator for %hashes

Generated methods for @lists
----------------------------

   For all @list instance variables in classgens control file Attribute.pm
generates (the phrase 'list' is replaced by the actual name of the @list
instance variable):

   * clear_l_list(): generated clear() method for @lists

   * get_list_at($index): generated indexed-accessor for @lists

   * get_l_list(): generated list-accessor for @lists

   * get_rl_list(): generated accessor to \@lists

   * pop_list(): generated pop-accessor for @lists

   * push_list($value): generated push-manipulator for @lists

   * set_l_list($index, $value): generated manipulator method for @lists

Internal methods
----------------

   A few methods are needed to provide all this:

   * sub new: constructor

   * sub get_type: to determine type of instance variable

   * sub get_var: access instance-variable

   * sub generate_blessed_h: for blessing an anonymous hash

   * sub generate_key: used to define appropriate method names

   * sub name: generate a standard name

   * sub simplify_var: to remove '^[\$%@]_+'

   * sub set_var: manipulate instance-variable

ENVIRONMENT
===========

   Nothing special. Just use Perl5.

DIAGNOSTICS
===========

   There is no special diagnostics. Attribute.pm is used within classgen
which is called with the -w option.

BUGS
====

   No bugs known.

FILES
=====

   Please refer to classgen.

SEE ALSO
========

   perldoc classgen

AUTHOR
======

   Name:  Michael Schlueter email: mschlue@cpan.org

COPYRIGHT
=========

   Copyright (c) 2000, Michael Schlueter. All Rights Reserved. This module
is free software. It may be used, redistributed and/or modified under the
same terms as Perl itself.

script that generates a class-module from a control file.
*********************************************************

NAME
====

   classgen - script that generates a class-module from a control file.

VERSION
=======

   3.03

SYNOPSIS
========

   !!! A fake-module, just to make the documention in the classgen-script
visible to CPAN !!!

   classgen input.txt Output.pm	# generate new class

   perldoc Output.pm	# review the fresh pod-skelton

   vi Output.pm		# edit specific methods

   less Output_gs.pm	# instance methods get-/set-

   For historical reasons the synonym ".gs" is still inthis documentation.
Please read it as "<file>_gs.pm".

DESCRIPTION
===========

   You specify the required instance-variables of a desired class by a
control-file.

   Classgen then creates a new package for you which contains the
new()-method, accessor- and manipulator-methods for all instance-variables
of that class. All instance-variables are blessed into an anonymous hash
{}.

   classgen adds a basic, simple perldoc skelton to support your
documentation for new classes.

   For a better overview version 3.03 splits the package into a .pm and a
.gs file. The .gs file contains all standard get-/set-methods and will be
reviewed only on occasion. The .pm will focus on the specific methods
only. Printouts will become much shorter and your overview will increase.

Input format of the control file
--------------------------------

   The control file is an ASCII-file which must contain the 3 sections
with specific keywords in the specified order:

     header:
     variables:

   classgen will scan for these 2 sections and act accordingly. classgen
will insist on using exactly these section-headers. It will die, if you
don't.

   * *header:* In this section you can put any Perl statement you need.
     classgen will simply copy this section to the beginning of your
     output file. You should at least include *package
     Your_Class_Name_here; use strict;*

   * *variables:* In this section you specify all your required
     instance-variables. classgen will determine the required type from
     the first character ($,@ or %) and will create all required
     variable-related methods for you. - For your convenience and to
     nurture self-documentation of your new class you can add some
     descriptive comments after the variable, just using a #.

Methods generated
-----------------

   classgen generates accessor- and manipulator-methods as required by the
variables type. The order of methods is:

   * new-method

   * specifc methods (to be extended by the user)

   * accessor methods

   * manipulator methods

   * (perldoc-skelton) (to be extended by the user)

   The *specific()* method is intended for copy&paste operation to easily
append the generated class with more specific class-methods by the user.

   A variable-name consists of <type><var_name>, with <type>=($,@,%). Via
<type> methods are generated as:

     <method name><var_name>

   Run *perldoc Attribute.pm* for an overview of all created methods.

Missing Methods for the created Objects
---------------------------------------

   A *serialize()* method should be added. So far my personal lack of
knowledge in this subject prevented me from supplying you with one. Conway
examines some possibilities, which you can find at CPAN.

Other Objects involved
----------------------

   classgen will use instances from the

   * New.pm - Object

   * Attributs.pm - Object

   * Section.pm - Object

   * Comment.pm - just a package, not an object. Cf. perldoc Comment.pm

Subroutines used by classgen
----------------------------

   Internal methods:

   * check_of_sections: to ensure every needed section is there

   * clean_up: to remove \t and other whitespaces

   * find_section: use this to use correct keywords

   * get_sections: to retrieve sections from input file

   * init_attributes : to generate Attribute-instances for all variables

   * init_new: to initialize the New-instance

   * write_begining : to write the first few lines into the new class

   * write_end :  code at the end of the new class

   * write_methods: to generate all required methods for each variable

   * write_new: to write the new-function of the generated class

How to use classgen
-------------------

   In version 3.03 an archive functionality has been introduced. Before
classgen creates the .pm and the .gs files from the control file, the old
files are copied into the /archive directory with an increasing numeriacl
starting index. So your previous edits are not lost.

   * FIRST RUN: Simply create a control file somewhere and create the
     output file where appropriate (e.g. classgen /controls/example
     /Objects/Example.pm).

   * ADDITIONAL RUNS: Classgen copies the current versions of .pm and .gs
     into the /archive directory. Next, it overwrites the current .pm and
     .gs as indicated by your control file.

   * ADDING METHODS: Edit your newly created package (e.g. Example.pm).
     Use the dummy-method at the end to create all further required
     methods of your class. All accessor- and manipulator-methods should
     already be there (I hope :-)

   * REMOVING METHODS: Cut them with your editor from the newly created
     package (e.g. Example.pm) or put comments at every line of the
     undesired subroutine. Perhaps you want to use them later again? Then
     cut them first and paste them to an intermediate-file.

   * RESTORING REMOVED METHODS: You have several choices: re-run classgen
     to create a safe copy of your package (e.g. Example_new.pm);
     copy&paste the missing part. Or re-use the intermediate-file from the
     previous hint; retrieving it from one of the files in the /archive
     directory etc.

How to produce undesired results (and how to avoid them)
--------------------------------------------------------

   Version 3.03: Problems from overwriting have been removed. Your edits
are copied to the /archive directory first.

How to handle inheritance of classes
------------------------------------

   Derive two classes with classgen. In the header-section of the derived
class you can add the required Perl-statements already in the control-file.

   Make sure to include the base-class in an @ISA-statement and adapt the
call to inherit_from() right after the blessing in the new() method of
your derived class.

   See also   examples/inheritance/README

Open issues
-----------

   I would like to know how classgen performs compared to other approaches
to object-oriented-implementations. How can I find out how much memory my
version actually consumes? - Please, gimme a hint ...

   Instance-variables could also be blessed into [] or $. Initially I
planned to offer these choices, too. It turned out to be more convenient
to omit this for a start. Your benefit is that you can do less things
wrong. As a by-product the control file becomes more handy ;-)

Background / Motivation
-----------------------

   J.Rumbaughs "Object Oriented Modelling" showed me a very promissing way
to tackle challenging software-projects. The idea is to identify relevant
classes (objects), their relationship (associations), their dynamic
behaviour (statediagrams) and their flow of data (functional model) - all
on paper.

   Once done and tested by various scenarios a very good specification has
been grown. Then there are ways to implement these objects both in
object-oriented (e.g. C++, Smalltalk, Eiffel) and NON-object-oriented
languages (e.g. C, Fortran, Algol) or databases. - What a challange for
Perl!

   I tried Damian Conways excellent book "Object Oriented Perl", which has
been published in fall 1999. I learned again, that there still "... are
always more than one way to do it" when it comes to implementing objects
in Perl:

   * do it by hand: introduce a new instance-variable and write all
     required methods to acces or change this variable yourself.

   * use the AUTOLOAD-mechanism to provide all required get- and
     set-methods at run-time.

   * use class-templates, like Class::Struct or Class::MethodMaker.

   Clearly, the first choice is the least desireable one. It is prone to
typing errors and one spends more time on same methods again rather than
on methods unique to the class (as I would prefer).

   The other methods have some advantages and some disadvantages. The
least tasty for me was that they tend to produce "obscure" code, at least
in examples I looked at. That is, code where I had to spend a lot of
thinking to understand what it does.

   Rather, I'd prefer code which I can understand at just one glance
(idealy ;-). Therefor classgen creates almost every get- and set-method
you can think of. Should you need it, it is already there. Should you
dislike it, simply throw methods away. Or even better, just do not care
about their existence at all. Stay focused on what your class should be
doing, not on the instance-variables.

   There is another inportant reason for my approach. I feel OOP-code
appears to be more 'cleaner' when it can be distributed over separated,
individual files. Some of the approaches mentioned above tend to create
and modify objects WITHIN another program. I think that shouldn't be done.
Have a look at my 'peanuts' example.

Future Plans
------------

   classgen lets me create new classes within minutes rather than days. I
myself am quite satisfied with the current performance. classgen was
created more or less on-the-fly. Perhaps I will redesign it by a more
consequent OMT-approach lateron.

   But before doing so I'd need more input about the good's and bad's from
you to make up my mind.  The missing parts. The nice-to-have things and so
on.

   If you like classgen and want it to have more useful functions please
let me know ;-)

ENVIRONMENT
===========

   Perhaps you may have to modify the first line in classgen due to
different locations of perl on different operating systems. If so, you'll
probably find classgen as (watch make install for details):

     /usr/bin/classgen

   You can avoid this adaption if you simply call:

     perl classgen <input_file> <output_class>

DIAGNOSTICS
===========

   When running classgen you will see the message:

     #: 2
     var1head1
     N: 2

   which is a relict from program development. It helped me to trace if
the correct sections where identified. It does not harm very much and
perhaps may be useful to find errors lateron. So, for the moment, it is
just in the program.

   classgen runs with the -w option. If you call classgen with the wrong
number of arguments it will simply die. The subroutines should either
return your requested result or "undef".

   The ideal diagnostics is the diagnostic which is not there, but which
function is performed. - To approach this ideal I did the following:

   The sensitivity analysis part from the Taguchi-method has been used to
measure sensitivity of classgen against errorness inputs from the control
file (that is against variable usage-conditions). Only those kinds of
errors which are likely to occure for a serious user, playing by the
rules, where investigated. Those are for example:

   * missing ; in the header section (no problem, but perl will complain
     lateron; this is somewhat inconvenient)

   * putting , or ; after a variable from the variables: section (causing
     strange methods generated)

   * putting comments in all sections (not allowed in the early version,
     but very useful for self-documentation purposes)

   This lead to creating the Comments.pm package, which provides just a
few simple routines to detect and to correct the errors mentioned above.

Error Messages:
---------------

   In alphabetical order:

   * 'less sections than expected' - not all sections could be found -
     check if delimiter ':' has been used ( from: check_of_sections() )

   * 'more sections than expected' - there are more sections specified
     than allowed - check for multiple sections or not allowed sections (
     from: check_of_section() )

   * 'specified identifier $id is ambigous' - more than one section is
     found in the control file with the same name - check the control file
     for unique sections ( from: find_section() )

   * 'specified identifier $id not found in %section' - this section is
     missing in the control file - add this section to the control file (
     from: find_section() )

BUGS
====

   You should always put at least one instance-variable into your class.
If you don't, you'll get a strange blessing ;-) . In most cases you
probably will do so automatically, so I decided to leave this
invonvenience until I know if it is worth while to re-concept classgen or
not (cf. Future Plans).

FILES
=====

Installation
------------

   Copy the .gz to a suitable directory. Run 'gunzip' and 'tar xvf '.
Change to Class/Classgen. Execute:

     perl Makefile.PL
     make

   As root do the final installation:

     make install

   When you run Perl under Windows you may want to use nmake.exe instead
of make (download e.g. from
ftp://ftp.microsoft.com/Softlib/MSLFILES/nmake15.exe)

SEE ALSO
========

     Changes

Methods created by classgen
---------------------------

   Run 	perldoc Attribute.pm

   Run 	perldoc New.pm

Example: Starting up with classgen
----------------------------------

   You may also want to review the included example files, which creates
the class Example.

   * control.txt is the control-file for the class Example

   * Example.pm is the result created by classgen

   * 'classgen control.txt Example.pm' will create Example.pm

perldoc
-------

   Please refer also to

   * perldoc New.pm (specifics of the created $self->new() function)

   * perldoc Attribute.pm (type dependend functions)

   * perldoc Section.pm (splitting up the control file)

   * perldoc Comments.pm (dealing with comments)

Books I referred to
-------------------

   * J.Rumbaugh, *Objektorientiertes Modellieren und Entwerfen*, ISBN
     3-446-17520-2  or J.Rumbaugh *Object-Oriented Modeling and Design*,
     ISBN 0136298419

   * D.Conway, *Object Oriented Perl*, ISBN 1-884777-79-1

AUTHOR
======

   Name:  Michael Schlueter email: mschlue@cpan.org

COPYRIGHT
=========

   Copyright (c) 2000, Michael Schlueter. All Rights Reserved. This module
is free software. It may be used, redistributed and/or modified under the
same terms as Perl itself.

To keep some nasty errors from users of classgen.
*************************************************

NAME
====

   Comments.pm - To keep some nasty errors from users of classgen.

VERSION
=======

   3.03

SYNOPSIS
========

   Used within classgen.

DESCRIPTION
===========

   Comments.pm checks for missing ';' in the header section. Missing ';'
will allow to run classgen smoothly but lateron perl will complain about
this error. Those anoying problems should be kept from the user.

   It turned out to be useful to add some elucidating comments after
variables in the variables-section. This increases self-documentation of
the source code and better documents intentions. Variables are simply
listed in the variables section. But user may tend to put a syntactically
';' or ',' after each variable. Again, classgen would run smoothly but
give nasty error messages lateron from perl. All these anoying problems
should be kept from the user.

ENVIRONMENT
===========

   Nothing special. Just use perl5.

DIAGNOSTICS
===========

   There is no special diagnostics. New.pm is used within classgen which
is called with the -w option.

BUGS
====

   No bugs known.

FILES
=====

   Please refer to classgen.

SEE ALSO
========

   perldoc classgen

AUTHOR
======

   Name:  Michael Schlueter email: mschlue@cpan.org

COPYRIGHT
=========

   Copyright (c) 2000, Michael Schlueter. All Rights Reserved. This module
is free software. It may be used, redistributed and/or modified under the
same terms as Perl itself.

Creates the new() method for classes generated by classgen.
***********************************************************

NAME
====

   New.pm - Creates the new() method for classes generated by classgen.

VERSION
=======

   3.03

SYNOPSIS
========

   Used within classgen.

DESCRIPTION
===========

   The main purpose of New.pm is to write the new() method for a class
generated by classgen. It provides code to derive local instance variables
with 'my' for all specified instance variables. It provides code to store
them within an anonymous hash (only way in the current version). Finally,
this hash is blessed into the desired class.

Methods generated by New.pm
---------------------------

   In the blessing section of the generated new() method:

   * inherit_from(): copies the entries of the blessed {} from the base
     class into the blessed {} of the derived class.

ENVIRONMENT
===========

   Nothing special. Just use Perl5.

DIAGNOSTICS
===========

   There is no special diagnostics. New.pm is used within classgen which
is called with the -w option.

BUGS
====

   No bugs known.

FILES
=====

   Please refer to classgen.

SEE ALSO
========

   perldoc classgen

AUTHOR
======

   Name:  Michael Schlueter email: mschlue@cpan.org

COPYRIGHT
=========

   Copyright (c) 2000, Michael Schlueter. All Rights Reserved. This module
is free software. It may be used, redistributed and/or modified under the
same terms as Perl itself.

Identifies the diffferent sections from classgens control file.
***************************************************************

NAME
====

   Section.pm - Identifies the diffferent sections from classgens control
file.

VERSION
=======

   3.03

SYNOPSIS
========

   Used within classgen.

DESCRIPTION
===========

   Section.pm is needed to administer the information found in the control
file of classgen for later use.

ENVIRONMENT
===========

   Nothing special. Just use Perl5.

DIAGNOSTICS
===========

   There is no special diagnostics. Section.pm is used within classgen
which is called with the -w option.

BUGS
====

   No bugs known.

FILES
=====

   Please refer to classgen.

SEE ALSO
========

   perldoc classgen

AUTHOR
======

   Name:  Michael Schlueter email: mschlue@cpan.org

COPYRIGHT
=========

   Copyright (c) 2000, Michael Schlueter. All Rights Reserved. This module
is free software. It may be used, redistributed and/or modified under the
same terms as Perl itself.

framework for classless OOP
***************************

NAME
====

   Class::Classless - framework for classless OOP

SYNOPSIS
========

     use strict;
     use Class::Classless;
     my $ob1 = $Class::Classless::ROOT->clone;
     $ob1->{'NAME'} = 'Ob1';
     $ob1->{'stuff'} = 123;
     $ob1->{'Thing'} = 789;

     my $ob2 = $ob1->clone;
     $ob2->{'NAME'} = 'Ob2';

     printf "ob1 stuff: <%s>\n", $ob1->{'stuff'};
     printf "ob2 stuff: <%s>\n", $ob2->{'stuff'};
     printf "ob1 Thing: <%s>\n", $ob1->{'Thing'};
     printf "ob2 Thing: <%s>\n", $ob2->{'Thing'};

     $ob1->{'METHODS'}{'zaz'} =  sub {
        print "Zaz! on ", $_[0]{'NAME'}, "\n";
     };

     $ob1->zaz;
     $ob2->zaz;
     $ob1->EXAMINE;
     $ob2->EXAMINE;

   This prints the following:

     ob1 stuff: <123>
     ob2 stuff: <123>
     ob1 Thing: <789>
     ob2 Thing: <>
     Zaz! on Ob1
     Zaz! on Ob2
     <Class::Classless::X=HASH(0x200236f4)>
        'stuff', 123,
        'NAME', 'Ob1',
        'Thing', 789,
        'METHODS', { 'zaz', 'CODE(0x20068360)' },
        'PARENTS', [ 'ROOT' ],
     <Class::Classless::X=HASH(0x2002cb48)>
        'stuff', 123,
        'NAME', 'Ob2',
        'METHODS', {  },
        'PARENTS', [ 'Ob1' ],

DESCRIPTION
===========

   In class-based OOP frameworks, methods are applicable to objects by
virtue of objects belonging to classes that either provide those methods,
or inherit them from classes that do.

   In classless OOP frameworks (AKA delegation-and-prototypes frameworks),
what methods an object is capable of is basically an attribute of that
object.  That is, in Perl terms: instead of methods being entries in the
symbol table of the package/class the object belongs to, they are entries
in a hash table inside the object.  Inheritance is implemented not by
having classes inheriting from other classes (via ISA lists), but by
having objects inherit from other objects (via PARENTS lists).

   In class-based OOP frameworks, you get new objects by calling
constructors.  In a classless framework, you get new objects by copying
("cloning") an existing object - and the new clone becomes a child
(inheritor) of the original object.  (Where do you get the one original
object?  The language provides one, which has no parents, and which
contains some general purpose methods like "clone".)

WHAT'S IN AN OBJECT
===================

   Each classless object is a reference to a hash, containing:

   * an entry 'PARENTS', which is a reference to a list of this node's
parents.  (For ROOT, this will be an empty list; for most nodes, there
will be just one item in this list; with multiple parents, you get
multiple inheritance.)

   * An entry 'NAME', which is initialized to a unique value (like "x_11")
when the object has just been created by cloning.  The 'NAME' attribute is
not required, and deleting it is harmless.

   * An entry 'METHODS', which is a reference to a hash that maps method
names (e.g., "funk") to coderefs or to constant values.  When you call
$foo->funk(@stuff), Class::Classless's dispatcher looks to see if there's
a $foo->{'METHODS'}{'funk'}.  If so, and if it's a coderef, then that
coderef is called with ($foo, $callstate, @stuff) as its parameter list
(See the section "What A Method Sees", below, for an explanation of this).
If there's a $foo->{'METHODS'}{'funk'} and it's not a coderef, then the
value is returned, possibly with automagical dereferencing.  (See the
section "Constant Methods", below.)  But, finally, if there is no such
method, Class::Classless's dispatcher looks in $foo's parent to see if
there's a $foo_parent->{'METHODS'}{'funk'}, and so on up the inheritance
tree.  If no 'funk' method is found in $foo or any of $foo's ancestors,
Class::Classless dies with an error to that effect.  (But see the section
on the NO_FAIL attribute, below.)

   * Anything else you want to put in the hash.  I provide no inherent
mechanism for accessing attributes (unlike, say, Self, which can
automagically treat method calls as accessors, roughly speaking), so
you're down to setting with $a->{'foo'} = VAL, reading with $a->{'foo'},
and possibly testing for the attribute with an exists($a->{'foo'}).
(However, do have a look at the `get_i', `set_i', and `exists_i' methods,
below.)

METHODS IN ROOT
---------------

   ROOT provides various methods you might find helpful:

   * $thing->clone - makes a new object based on an existing one.  The
only way you get to produce new objects is to clone existing ones.
Existing objects are either clones of ROOT, or clones of clones of ROOT,
and so on.  A newly cloned object has a copy of all its parent's
attributes whose names don't match /^[A-Z]/s (i.e., that don't begin with
a letter between ASCII capital A and ASCII capital Z, inclusive).  The new
object is then initialized with a per-session-unique name like "x_12"; its
PARENT attribute is set to a list containing its one parent; and its
'METHODS' attribute is set to an empty hash.  (Note that the copying of
parent attributes is not a deep copy - the parent has foo => [bar, baz],
then the child will have a reference to that same list, not a copy of that
list!)

   (Also, if $thing->is_lineage_memoized is true, the clone will have a
memoized lineage too.  And note that $Class::Classless::ROOT has lineage
memoization off.  See the description of "$thing->memoize_lineage", below,
for a description of what this all means.)

   * $thing->polyclone($thing2, $thing3...) - makes a new object based on
$thing, $thing2, $thing3, etc.  Attributes in $thing overrride those in
$thing2, and so on.  The PARENTS list will consist of $thing, $thing2,
$thing3, etc., in that order.  Also, if $thing->is_lineage_memoized is
true, the clone will have a memoized lineage too.

   * $thing->get_i('attrib') - ("get, with inheritance").
$thing->get_i('foo') returns the value of the 'foo' attribute for $thing.
If there is no $thing->{'foo'}, it looks for a 'foo' attribute in each of
$thing's ancestors.  Returns the first one found.  If none are found,
returns undef.  (But note that undef could result if $thing->{'foo'} or
$some_parent->{'foo'} is undef.)

   * $thing->exists_i('attrib') - ("exists, with inheritance").
$thing->exists('foo') returns true if either $thing or any of its
ancestors contains a 'foo' attribute (as tested with simply
exists($node->{'foo'})).  Otherwise, returns false.

   * $thing->put_i('attrib', VALUE) - ("put, with inheritance").  put_i
looks across $thing and its ancestors, and for the first one that contains
an 'attrib' attribute, sets its value to VALUE, and then returns VALUE.
If neither $thing nor any of its ancestors contain a 'attrib' attribute,
this will set $thing->{'attrib'} = VALUE and return VALUE, but will warn
(via carp) if $^W (warnings, usually from giving Perl a -w switch) is true.

   * $thing->EXAMINE - prints a somewhat simpleminded dump of the contents
of the object.  Like a cheapo version of Data::Dumper's Dump() function.

   * $thing->FLATTEN - deletes all attributes (and their values) in the
object whose names do not match /^[A-Z]/s (i.e., whose names don't begin
with a letter between ASCII capital A and ASCII capital Z, inclusive).
You can use this if you don't need an object's data, but don't feel bold
enough to destroy it, because it may have clone-children that would be
orphaned (a bad thing) if this node lost its PARENT attribute, say.

   * $thing->allcan('baz') - returns the list (in order) of all 'baz'
methods in $thing's ISA tree.  This may be an empty list.  (Note that the
NO_FAIL attribute has no effect on the allcan method.)  Note especially
that the magic dereferencing magic for constant method values is not
triggered.  That is, what allcan('baz') returns is simply a list of the
values of $x->{'METHODS'}{'baz'} wherever such a METHODS entry exists, for
all objects in $thing's inheritance tree.

   * $thing->howcan('baz') - just like allcan, but the list returned
consists of pairs of values, where each pair consists of 1) the object
that provides the 'baz' method, followed by 2) the value it provides for
that method.  (Remember that that value may be a coderef, or it may be any
kind of other reference (which will not be magically resolved as it would
have been by the dispatcher - see the section "Constant Methods", or it
may be any nonreference scalar value - including 0 or undef!)  The pairs
are in order.  You can read this list into a hash that maps from the
methods to the method-values, but of course then you lose the ordering.

   * $thing->can('baz') - if $thing is capable of the method 'baz', this
returns true, otherwise it returns false.  Do not try to override the can
method.  (Note that the NO_FAIL attribute has no effect on the can
method.)  Note also that this does NOT return the method's value, as it
did in the first version of Class::Classless, which (like Perl's normal
object system) would return the (coderef) value of the method 'baz' for
the first object in $thing's tree that provided such a method.

   That worked then, since all method values under the first version of
Class::Classless had to be coderefs (which were, of course, true in a
boolean context).  However, now that a Class::Classless method have have a
constant value that is false, having can() return that value would be
indistinguishable from having it return any false value meant as a signal
the object incapable of the method.  In short, can() simply has to return
either true or false now.  If you need the value of the methods, use
allcan() or howcan().

   * $thing->VERSION - same as $thing->get_i('VERSION').  Note that ROOT
has an entry of 'VERSION' => '0.00'.  Do not try to override the VERSION
method.

   * $thing->VERSION(version_number) - dies if $thing->VERSION is less
than version_number.  Otherwise returns $thing->VERSION.

   * $thing->isa($thing2) - returns true if $thing2 is in $thing's ISA
tree - i.e., if it's an ancestor of $thing.  (Also returns true if $thing2
*is* $thing.)  Otherwise returns false.  Do not try to override the isa
method.

   * $thing->ISA_TREE - returns $thing's ISA tree, linearized - i.e., the
list of nodes, in order, starting with $thing (and presumably ending with
$ROOT), that you would search thru for method calls on $thing, or get_i
calls on $thing.  Do not try to override the ISA_TREE method.

   * $thing->memoize_lineage - makes this object eligible for having its
ISA_TREE cached.  Normally, every method call on an object causes the
routine ISA_TREE to be called, so that Class::Classless knows where to
look for methods, and in what order.  You can avoid this having to happen
each time by causing the results of $thing->ISA_TREE to be memoized
(cached); then, subsequent method calls on $thing will just use the cached
linearization.  This means, however, that you must not change any of
$thing's ancestry (who its parents are, or any of its parents' parents,
etc.), or the changes will not be noticed.  (If you do want to change any
such thing, unmemoize the lineage first, as below.  Also remember that you
will need to unmemoize the lineages of all existing clones, too.)

   (The ISA_TREE cache happens to be stored in $thing->{'ISA_CACHE'}.)

   $thing->memoize_lineage has no effect if memoization is already on.
This always returns $thing, which makes it convenient for calling on newly
cloned objects:

     $thing = $foo->clone->memoize_lineage;

   Note that as described above, the normal behavior of $foo->clone is to
turn on ISA_TREE memoization for any new clones of $foo if $foo has its
ISA_TREE memoization turned on.

   * $thing->unmemoize_lineage - this turns off the above-mentioned
ISA_TREE cache for $thing.  Has no effect if lineage-memoization is
already off.  Like $thing->memoize_lineage, this returns $thing.  Think
carefully about how you use this.  It's never going to be a problem if the
only way you call it is as:

     $thing = $foo->clone->unmemoize_lineage;

   I.e., when you want a new object whose lineage you want to be free to
alter later without having to worry about caching.  (And when in doubt,
leave caching off.)

   However, note that this is wrong:

     $thing = $foo->clone->memoize_lineage;
     ...stuff...
     push @{$thing->{'PARENTS'}}, $yorp;
     $thing->unmemoize_lineage;

   ...because the 'unmemoize_lineage' call on $thing will be using an
already out-of-date cache of its old ISA_TREE.  That is likely to be
harmless, though, unless $yorp overrides the normal 'unmemoize_lineage'
method.  But this is better:

     $thing = $foo->clone->memoize_lineage;
     ...stuff...
     $thing->unmemoize_lineage;
     push @{$thing->{'PARENTS'}}, $yorp;
     $thing->memoize_lineage;

   But consider this harder case:

     $thing = $foo->clone->memoize_lineage;
     ...stuff...
     $zaz = $thing->clone; # so it will have memoization
     ...more stuff...
     $thing->unmemoize_lineage;
     push @{$thing->{'PARENTS'}}, $yorp;
     $thing->memoize_lineage;

   Even though you correctly turned off $thing's cache at the right
moment, you forgot about $zaz's cache, which was and still is out of date.

   * $thing->is_lineage_memoized - returns true iff $thing is using
lineage memoization.

   * $thing->DESTROY - this is here to trap DESTROY calls that Perl makes
when it's about to deallocate an object, either when the object's
reference count goes to 0, or at global destruction time.  Currently it's
a no-op, for many annoyingly complicated reasons.  Do not try to override
the DESTROY method!  If you don't know what DESTROY methods are for
anyway, don't worry about it.

CONSTANT METHODS
================

   I expect that most methods (i.e., things in the $foo->{'METHODS'} hash)
will be coderefs.  However, if you want the value of a method to be a
constant, I figure there's no point in making you say:

     $foo->{'METHODS'}{'funk'} = sub { 7 };

   just so $foo->funk can return the constant value 7.

   So instead, I've made it so that when you call $foo->funk, and
Class::Classless finds that $foo->{'METHODS'}{'funk'} exists, or that
$some_ancestor->{'METHODS'}{'funk'} exists, it takes that value and
decides what to do with that value, like so:

   * Unless that value (which, by the way, is free to be undef!) is a
reference, then it's a constant, so return it.  That means that if you set
$foo->{'METHODS'}{'funk'} = 7, then $foo->funk will always return 7.

   * If it's an unblessed coderef, call it with arguments as explained in
the "What a Method Sees" section, below.  Note that blessed coderefs (as
rare at they are) are not called.

   * Otherwise, it must be some sort other sort of constant to return,
which happens to be a reference.

   * If it's a reference of the class '_deref_array', then it's
array-dereferenced before being returned.  So if you wanted
$foo->band_members to return a constant list ('Ad Rock', 'MCA', 'Mike D'),
you can do it with: $foo->{'METHODS'}{'band_members'} = bless [ 'Ad Rock',
'MCA', 'Mike D'], '_deref_array'. When you call $foo->band_members then,
Class::Classless's dispatcher will basically say:
return(@{$foo->{'METHODS'}{'band_members'}});

   * If it's a reference of the class '_deref_scalar', then it's
scalar-dereferenced before being returned.  This is not as immediately and
obviously useful as the same trick with '_deref_array', but it does make
possible a few tricks.  First off, you can have something like:

     my $counter = 0;
     bless $counter, '_deref_scalar';
     $fee->{'METHODS'}{'counter_value'} = \$counter;
     $fye->{'METHODS'}{'counter_value'} = \$counter;
     $foe->{'METHODS'}{'counter_value'} = \$counter;

   to have these all share the same value, which you'd get from going
$fee->counter_value, $fye->counter_value, or $foe->counter_value.

   Second off, suppose (as unlikely as it is) you actually wanted a
constant value to be returned - but the value you want returned is an
unblessed coderef!  If you just stuck that value in $foo->{'METHODS'},
it'd get called instead of returned as a constant.  Well, you can just go:

     my $cr = sub { ...whatever... };
     $foo->{'METHODS'}{'zaz'} = bless \$cr, '_deref_scalar';

   So when you call $foo->zaz, Class::Classless sees a scalar of class
'_deref_scalar', and returns it, like return(${$foo->{'METHODS'}{'zaz'}}).
That value is, of course, your coderef.

   * And finally, if the value in $foo->{'METHODS'}{'funk'} was a
reference, but was neither an unblessed coderef, nor a reference of class
'_deref_array', nor of class '_deref_scalar', then it's just returned.

WHAT A METHOD SEES
==================

   Under Perl's normal object system, when you call

     $foo->bar($x, @y ...)

   bar's `@_' will consist of

     ($foo, $x, @y ...)

   So normally the first thing bar will do is something like:

     my($obj, $first, @rest) = @_;

   or

     my $obj  = shift @_;
     my $first = shift @_;
     my @rest = @_;

   *However*, subs called as methods by Class::Classless's dispatcher have
one extra argument; $_[1] is the "callstate", an object created every time
you call a Class::Classless object, and belonging to the class
'Class::Classless::CALLSTATE'.  Normally all you'd ever want to do with it
is say:

     $callstate->NEXT('foo', $bar, @baz)

   which is equivalent to $callstate->SUPER::foo($bar, @baz) under Perl's
normal object system.  See the section "More on NEXT".

   So, in other words, the first line of a Class::Classless method to be
called as

     $foo->bar($x, @y ...)

   would be

     my($obj, $callstate, $first, @rest) = @_;

   or the like.

SHARED DATA
===========

   I considered making some sort of mechanism for having private
attributes versus inherited attributes, but decided on just letting the
user work it out with `get_i', `set_i', and `exists_i'; onto this I added
the feature that attributes whose names start with a character in the
ASCII range `[A-Z]' (as opposed to `[a-z]', or anything else) don't get
copied by the clone method, and also aren't deleted by the `FLATTEN'
method.  That's the *complete extent* of the special treatment that
Class::Classless accords to attributes whose names start with `[A-Z]'.

   The upshot of this is that you can have something like "class data" by
just taking a generic object (i.e., one you expect to be cloned) and
setting attributes in it like

     $generic->{'Interface'} = 'Tk';

   then all clones of that attribute can effectively 'share' that value
like so...

     # send in the clones...
     $w1 = $generic->clone;
     $w2 = $generic->clone;
     $w3 = $generic->clone;
     ...etc...

     print $w1->get_i('Interface');  # to read it
     print $w2->get_i('Interface');  # to read it (same value)
     print $w3->get_i('Interface');  # to read it (same value)

     print $w2->put_i('Interface', 'VT320');  # to set it

   and even this, if this makes any useful sense:

     print $whatever->exists_i('Interface');  # to make sure it exists

   However, to repeat myself somewhat, the only reason this is shared is
that clone didn't copy the 'Interface' method when it made clones of
$generic, so calling `get_i' on any of the children so produced will find
the attribute not in the children, but will fall back on finding it in
$generic->{'Interface'}.

   But if you go and set $w1->{'Interface'} (as opposed to using `set_i'),
then $w1->get_i('Interface') will get you the value of $w1->{'Interface'},
not the value of $generic->{'Interface'}. In other words, you'd be
overriding the value you'd still be getting at with
$generic->{'Interface'}, $w2->get_i('Interface'), $w3->get_i('Interface'),
or even (uninterestingly) $generic->get_i('Interface').

   And in any case, you can really share data by virtue of the fact that
the clone method (at least, not the default clone method) doesn't do
copying of references (AKA "deep copying") - so you can just have all the
objects that you want to share data simply have a reference to a common
piece of data:

     my $bar = 123;
     $w->{'foo'} = \$bar;
     # Then any clones of $w will have a reference to that value --
     #  not to copies of it!
     # Similarly:
     $w->{'zaz'} = [5,6,7];
     $w->{'quux'} = {a => 11, b => 12};

INHERITANCE SYSTEM
==================

   If all you want is single-inheritance, you can skip this section, since
things will work as you expect: objects inherit from their parents, and so
on, all the way back to a parentless object (i.e., ROOT).

   As to how this works with multiple inheritance, consider first how
Perl's built-in mechanism for class inheritance works: first, a
depth-first search of the ISA tree, and then falling back to the class
UNIVERSAL, which is the implicit root for all classes.

   Class::Classless's system is different - consider this case:

     ROOT/UNIVERSAL
         |
         Y
        /  \
      A      X
      |      /
      B    /
       \ /
        C

   Here, Perl's depth-first search would linearize the tree (i.e., convert
it to a flat list consisting of search path) as:

     C   B   A   Y   X   Root/Universal

   However, I think this is just not the right way to do things.  The
point of X being a child of Y is so that X can have a chance to override
Y.  Perl's normal depth-first search doesn't allow that in cases like
this.  So my rule is: search over ancestors depth-first, but never search
a node until you've searched all its children (that is, children that are
still ancestors of the node you've built this tree for - any other
children are irrelevant).  So I linearize that list as:

     C   B   A   X   Y   Root/Universal

   So X does override Y.  (And Root/Universal is not a special case in the
searching rule.)

   Now, fatal errors may result with bizarre trees - namely ones with
cyclicity in them, such as: X's parents are A and B, A's parent is B, and
B's parent is A.  But in some cases Class::Classless *might* just try to
ignore the cyclic part.  So just don't make any cyclic trees, OK?

THE NO_FAIL ATTRIBUTE
=====================

   If you call $thing->zaz and there is no 'zaz' method that $thing is
capable of, then normally Class::Classless with throw a fatal error.
However, if $thing->get_i{'NO_FAIL'} is true, then a no-operation (like
sub { return; } ) simply results.

   (NO_FAIL also controls what happens if you call $thing->NEXT('zaz') and
there is no NEXT 'zaz' method; if NO_FAIL is true, a no-operation results;
otherwise, a fatal error results.  See the section "More on NEXT", below.)

   Implementationally, the way this is implemented is that when you call a
method, a routine of Class::Classless's called the dispatcher looks
figures out the linearization of the inheritance tree of the target object
of the method call, and then, one-at-a-time, goes over the objects in the
linearization, looking for an object whose METHODS hash contains an entry
for the name of the method. ("Linearization" meaning simply a list of
objects, in the order in which they should be searched.)

   Each call also creates an object, called a "callstate" object, one of
whose attributes is called "no_fail" (note lowercase), and whose value
starts out being undef.  If the dispatcher, while going thru the
linearization and looking at the METHODS, sees an object with a defined
'NO_FAIL' attribute (note uppercase), it uses that value (the value of the
first object in the list with a defined NO_FAIL attribute) to set the
no_fail attribute of the callstate.  If it finishes searching the list and
hasn't seen an object with a METHODS entry for the method it's dispatching
for, one of two things will happen: if no_fail is set to true, the
dispatcher will act as if it found the method and its value was
sub{return}.  Otherwise, the dispatcher will die with a fatal error like:

     Can't find method foo in OBJECT_NAME or any ancestors

   So, normally, the only way for the no_fail attribute of the callstate
to be usefully set is for the dispatcher to have seen an object with a
NO_FAIL attribute set.  In other words, if you want method lookup in an
object to be unfailing, set $x->{'NO_FAIL'} = 1 for it or any of its
ancestors; and if you want to override *that* for a descendant, set its
$y->{'NO_FAIL'} = 0.  (Note that just for sake of sanity, the NO_FAIL of
$ROOT is set to 0.)

   But in the case of using callstate->NEXT call to continue a method
dispatch (i.e., getting the dispatcher to pick up where it left off), you
may want to control the callstate's no_fail attribute directly, regardless
of the NO_FAIL attributes of any of the objects the dispatcher's seen so
far.  In that case, you can use the $callstate->set_no_fail_true to set
no_fail to true (i.e., lookup failures from NEXTing off of this callstate
don't generate fatal errors).  See the section on callstates, below, for
more options.

CALLSTATES
==========

   Every time you call a method on a Class::Classless object (whether
normally, or via a $callstate->NEXT(...) call), a new
Class::Classless::CALLSTATE object is created, and passed as $_[1] to that
method.  Besides this being the way I happen to implement
$callstate->NEXT(*methodname*, *arguments*) (by recording the state of the
dispatcher for later resumption), you can use this object to get
metainformation about this method call.  You can access that information
like so:

   * $callstate->target - the object that was the target of the method
call.  Same as the $_[0] that the method sees.

   * $callstate->found_name - the name this method was called as.

   * $callstate->lineage - the list of objects representing the
linearization of the target object's ISA tree.  (Same as $obj->ISA_TREE.)

   * $callstate->home - the object the called method was found in.

   * $callstate->sub_found - the routine that is being called.  Same as
$callstate->home->{'METHODS'}{$callstate->target}.

   * $callstate->found_depth - the number representing the index in the
$callstate->lineage list where this method was found.  In other words,
$callstate->home is ($callstate->lineage)[$callstate->found_depth].

   * $callstate->set_no_fail_true - set the no_fail attribute of this
callstate to true - meaning failure is impossible for any NEXT calls based
on this call.  (Obviously it's meaningless to consider failure of the
current method - it was already found, otherwise how could there be code
that's accessing its callstate!)  I expect this is useful for cases where
you want to NEXT, but aren't sure that there is a next method in the tree.
With the no_fail set, failure in the NEXT lookup will act as if it
triggered a method consisting of just sub { return; }.

   * $callstate->set_no_fail_false - set the no_fail attribute of this
callstate to true - meaning failure is possible for any NEXT calls in the
contituation of the current call state.  I don't anticipate this being
useful, but I provide it for completeness.

   * $callstate->set_no_fail_undef - set the no_fail attribute of this
callstate to undef - meaning that failure is possible, but that this value
can be set by the next object in the linearization of the inheritance
tree.  I don't anticipate this being useful, but I provide it for
completeness.

   * $callstate->no_fail - returns the value of no_fail attribute of this
callstate so far.  See the section "The NO_FAIL attribute", above.  I
don't anticipate this being useful, but I provide it for completeness.

   * $callstate->via_next - return true the current method was called via
$callstate->NEXT.  Otherwise returns false.

   The whole callstate mechanism (used by the above methods as well as by
the NEXT method) assumes you don't change the object's ISA tree (or any of
the METHODS hashes in any part of the ISA tree) in the middle of the call.
If you do, the information in $callstate will be out of synch with
reality (since it contains the linearization as of the *beginning* of the
call)), which is fine as long as you don't use it for anything (like
NEXTing) after that point, in that call.

MORE ON NEXT
============

   Calling $callstate->NEXT is the mechanism I allow for doing what Perl's
built-in object system does with SUPER:: calls, and like what some object
systems do with "before- and after-demons".

   The basic syntax to NEXT is as follows:

     $callstate->NEXT( method_name , ...arguments... );

   However, if you call it with a method_name of undef, it will use the
current value of $callstate->found_name, i.e., the name the currently
running method was found as.  Note that this can come to de undefined in
two ways - either by the parameter list being null, as in either of:

     $callstate->NEXT;
      ...AKA...
     $callstate->NEXT();

   or by being explicitly undef:

     $callstate->NEXT(undef, $foo, $bar);

   In either case, the undef is interpreted as $callstate->found_name.  I
offer this as just a (hopefully) convenient shortcut.

   Now, if you call NEXT and there is no method with the desired name in
the remainder of the linearization of the inheritance tree, what happens
depends on the no_fail attribute; if you want to insure that the NEXT will
not fail (since failing would mean a fatal error), you can set the
callstate's no_fail attribute to true:

     $callstate->set_no_fail_true

   (which means it can't fail.)

   Note, by the way, that NEXTing never automatically copies the argument
list of the current method for the next one. You have to do that yourself.
There's many ways to do it, but consider something like:

     $x->{"METHODS"}{"foo"} = sub {
       my($o, $cs) = splice(@_,0,2);
       # then copy arguments from @_, but don't change @_ any further:
       my($zaz, @foo) = @_

       ...stuff...

       # then you can pass on the arguments still in @_
       $cs->NEXT(undef,@_);
         # undef to mean 'the name I was called as'

       ...stuff...

     };

   If you forgot and just said $cs->NEXT() or (pointlessly)
$cs->NEXT(undef), then the next 'foo' method would have nothing in its
argument list after its usual two first items (the target object and the
callstate).

   A further note: currently, each method call (whether normal, or via a
NEXT) creates a new callstate object.  However, when NEXTing, the
attributes of the current callstate object are copied into the new
callstate object - except for the via_next attribute, which is forced to
true, of course.

BASIC IMPLEMENTATION STRATEGY
=============================

   This module does what it does by blessing all "Class::Classless"
objects into a class (Class::Classless::X, in point of fact) that provides
no methods except for an AUTOLOAD method that intercepts all method calls
and does the dispatching.  This is how I fiendishly usurp Perl's normal
method dispatching scheme.  (Actually I do provide other methods upfront:
can, VERSION, isa, DESTROY, and `ISA_TREE', as I basically have to, it
turns out.)

   Consult the source for details.  It's not that long.

CAVEATS AND MUSINGS
===================

   * The moral of this module is that if you don't like the object
framework that comes with a language, quit your bitching and just make
your own!  And the meta-moral is that object systems aren't black boxes
that have to be fused with the language itself.

   * Note that the can you may export from UNIVERSAL has nothing at all to
do with the can that you should be using for Class::Classless objects.
The only way you should call can on classless objects is like
$obj->can('foo').

   * How to test if something is a classless object: `ref($obj) eq
'Class::Classless::X''

   * Don't make cyclic trees.  I don't go to extreme lengths to stop you
from doing so, but don't expect sane behavior if you do.

   * The reason the $callstate->NEXT('foo') is called NEXT is because it
starts looking in the next object in the linearization of the ISA_TREE.
This next object is not necessarily an ancestor (i.e., a *super*ior
object) of the current object - in the above section, X is A's next node,
altho A is clearly not a superior node.

   * Don't try to derive new classes from any of the classes that
Class::Classless defines.  First off, it may not work, for any reading of
"work".  Second off, what's the point?

   * Note that there's currently no mechanism for parent objects to know
what their children are.  However, if you needed this, you could override
the clone method with something that would track this.  But note that this
would create circular data structures, complicating garbage collection -
you'd have to explicitly destroy objects, the way you have to with
Tree::DAG_Node nodes.

   * Why don't I let objects define their own DESTROY methods?  One short
reason: this unpredictably and intermittently triggers a strange bug in
Perl's garbage collection system during global destruction.  Better,
longer reason: I don't see any way to make sure that, during global
destruction, Perl never destroys a parent before its children.  If a
parent is destroyed before its children, and that parent provides a
DESTROY that the children inherit, then when it comes time for the
children to be destroyed, the DESTROY method they planned on using would
have become inaccessible.  This seems an intractable problem.

   * Callstate objects were added as an afterthought.  They are meant to
be small and inexpensive, not extensible.  I can't imagine a use for them
other than the uses outlined in the documentation - i.e., getting at (or
sometimes modifying) an attribute of the current state of the method
dispatcher. If you're considering any other use of callstate objects,
email me - I'd be interested in hearing what you have in mind.

   * While I was writing Class::Classless, I read up on Self.  To quote
FOLDOC (`http://foldoc.doc.ic.ac.uk/foldoc/foldoc.cgi?query=Self'), Self
is/was "a small, dynamically typed object-oriented language, based purely
on prototypes and delegation. Self was developed by the Self Group at Sun
Microsystems Laboratories, Inc. and Stanford University. It is an
experimental exploratory programming language."  For more information, see
`http://www.sunlabs.com/research/self/'

YOU KNOW WHAT THEY SAY...
=========================

   To Marx, a classless society never meant the absolute equality of
result, but merely the absence of artificial barriers between social
groups. According to David McClellan, a Marx scholar, Marx "had a dynamic
or subjective element in his definition of class; a class only existed
when it was conscious of itself as such, and this always implied common
hostility to another social group." In *The Thought of Karl Marx*, (New
York: Harper & Row, 1971) p. 155.

   - `http://www.polyconomics.com/searchbase/kmnotes.htm'

   The thanks for the quote as well as for thinking of the name
"Class::Classless" go to Veblen, who can be seen making that secret potato
soup of his at `http://www.llnl.gov/llnl/art-cv/image1.jpg'

   Thanks to my many minions in EFNet #perl for help, suggestions, and
encouragement.  Especial thanks to Merlyn, Halfjack, and Skrewtape for
assuring me that the idea of objects-without-class wasn't just some
Felliniesque fever dream I had, but is a concept that has precedent in
other programming languages.

   And thanks to Damian Conway for stritching the brines of his poor
students with this module.

SEE ALSO
========

   For information on Perl's classy OOP system, see Perlobj (perl.info),
see Perltoot (perl.info),
UNIVERSAL, and Damian Conway's excellent book *Object Oriented
Perl* from Manning Press.

COPYRIGHT
=========

   Copyright (c) 1999, 2000 Sean M. Burke.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Sean M. Burke, sburke@cpan.org

Design-by-Contract OO in Perl.
******************************

NAME
====

   Class::Contract - Design-by-Contract OO in Perl.

VERSION
=======

   This document describes version 1.10 of Class::Contract, released
February  9, 2001.

SYNOPSIS
========

     package ClassName
     use Class::Contract;

     contract {
       inherits 'BaseClass';

     invar { ... };

     attr 'data1';
     attr 'data2' => HASH;

     class attr 'shared' => SCALAR;

     ctor 'new';

     method 'methodname';
       pre  { ... };
         failmsg 'Error message';

     post  { ... };
       failmsg 'Error message';

     impl { ... };

     method 'nextmethod';
       impl { ... };

     class method 'sharedmeth';
       impl { ... };

     # etc.
         };

DESCRIPTION
===========

Background
----------

   Design-by-contract is a software engineering technique in which each
module of a software system specifies explicitly what input (or data or
arguments) it requires, and what output (or information or results) it
guarantees to produce in response.

   These specifications form the "clauses" of a contract between a module
and the client software that uses it. If the client software abides by the
input requirements, the module guarantees to produce the correct output.
Hence by verifying these clauses at each interaction with a module, the
overall behaviour of the system can be confidently predicted.

   Design-by-contract reinforces the benefits of modular design techniques
by inserting explicit compile-time or run-time checks on a contract.
These checks are most often found in object-oriented languages and are
typically implemented as pre-conditions and post-conditions on methods,
and invariants on classes.

   Note that these features differ from simple verification statements
such as the C assert statement. Conditions and invariants are properties
of a class, and are inherited by derived classes.

   An additional capacity that is often provided in design-by-contract
systems is the ability to selectively disable checking in production code.
This allows the contractual testing to be carried out during
implementation, without impinging on the performance of the final system.

Adding design-by-contract to Perl
---------------------------------

   The Class::Contract module provides a framework for specifying methods
and attributes for a class (much like the existing class definition
modules Class::Struct, Class::MethodMaker, and Class::Generate).
Class::Contract allows both per-object and per-class methods and
attributes to be defined. Attributes may be scalar-, array-, hash-, or
object-based.

   Class::Contract differs from other class-specification modules (except
Class::Generate) in that it also provides the ability to specify invariant
conditions on classes, and pre- and post-conditions on methods and
attributes. All of these clauses are fully inheritable, and may be
selectively disabled. It differs from all other modules in that it has a
cleaner, simpler specification syntax, and - more importantly - it
enforces encapsulation of object attributes, thereby ensuring that the
class contract cannot be subverted.

Defining classes
----------------

   Class::Contract provides an explicit syntax for defining the attributes,
methods, and constructors of a class. The class itself is defined using
the `contract' subroutine. `contract' takes a single argument - a
subroutine reference or a block. That block is executed once and the
results used to construct and install the various components of the class
in the current package:

     package Queue;
     contract {
       # specification of class Queue attributes and methods here
     };

Defining attributes
-------------------

   Attributes are defined within the `contract' block via the attr
subroutine.  Attributes must be given a name, and may also be given a
type: SCALAR, ARRAY, HASH, or a class name:

     contract {
             attr 'last';                   # Scalar attribute (by default)
             attr 'lest' => SCALAR;         # Scalar attribute
             attr 'list' => ARRAY;          # Array attribute
             attr 'lost' => HASH;           # Hash attribute
             attr 'lust' => MyClass;        # Object attribute
     };

   For each attribute so declared, Class::Contract creates an *accessor* -
a method that returns a reference to the attribute in question. Code using
these accessors might look like this:

     ${$obj->last}++;
     push @{$obj->list}, $newitem;
     print $obj->lost->{'marbles'};
     $obj->lust->after('technology stocks');

   Attributes are normally object-specific, but it is also possible to
define attributes that are shared by all objects of a class. Class objects
are specified by prefixing the call to attr with a call to the class
subroutine:

     class Queue;
     contract {
             class attr 'obj_count';
     };

   The accessor for this shared attribute can now be called either as an
object method:

     print ${$obj->obj_count};

   or as a class method:

     print ${Queue->obj_count};

   In order to ensure that the clauses of a class' contract (see below)
are honoured, both class and object attributes are only accessible via
their accessors, and those accessors may only be called within methods
belonging to the same class hierarchy. Objects are implemented as
"flyweight scalars" in order to ensure this strict encapsulation is
preserved.

Defining methods
----------------

   Methods are defined in much the same way as attributes. The method
subroutine is used to specify the name of a method, then the `impl'
subroutine is used to provide an implementation for it:

     contract {
             attr list => ARRAY;

     method 'next';
         impl { shift @{self->list} };

     method 'enqueue';
         impl { push @{self->list}, $_[1] };
             };

   `impl' takes a block (or a reference to a subroutine), which is used as
the implementation of the method named by the preceding method call.
Within that block, the subroutine `self' may be used to return a reference
to the object on which the method was called. Unlike, regular OO Perl, the
object reference is not passed as the method's first argument.  (Note:
this change occurred in version 1.10)

   Like attributes, methods normally belong to - and are accessed via - a
specific object. To define methods that belong to the entire class, the
class qualifier is once again used:

     contract {
             class attr 'obj_count';

     class method 'inc_count';
             impl { ${self->obj_count}++ };
             };

   Note that the `self' subroutine can still be used - within a class
method it returns the appropriate class name, rather than an object
reference.

Defining constructors
---------------------

   Class::Contract requires constructors to be explicitly defined using
the `ctor' subroutine:

     contract {
             ctor 'new';
                 impl { @{self->list} = ( $_[0] ) }
     };

   Note that the implementation section of a constructor *doesn't* specify
code to build or bless the new object. That is taken care of automatically
(in order to ensure the correct "flyweight" implementation of the object).

   Instead, the constructor implementation is invoked after the object has
been created and blessed into the class. Hence the implementation only
needs to initialize the various attributes of the `self' object.  In
addition, the return value of the implementation is ignored: constructor
calls always return a reference to the newly created object.

   Any attribute that is not initialized by a constructor is automatically
"default initialized". By default, scalar attributes remain undef, array
and hash attributes are initialized to an empty array or hash, and object
attributes are initialized by having their new constructor called (with no
arguments). This is the only reasonable default for object attributes, but
it is usually advisable to initialize them explicitly in the constructor.

   It is also possible to define a "class constructor", which may be used
to initialize class attributes:

     contract {
             class attr 'obj_count';

     class ctor;
             impl { ${self->obj_count} = 0 };
             };

   The class constructor is invoked at the very end of the call to
`contract' in which the class is defined.

   Note too that the class constructor does not require a name. It may,
however, be given one, so that it can be explicitly called again (as a
class method) later in the program:

     class MyClass;
     contract {
             class attr 'obj_count';

     class ctor 'reset';
             impl { ${self->obj_count} = 0 };
             };

     # and later...

     MyClass->reset;

Defining destructors
--------------------

   Destructors are also explicitly defined under Class::Contract, using
the `dtor' subroutine:

     contract {
             dtor;
                 impl { print STDLOG "Another object died\n" }
     };

   As with the constructor, the implementation section of a destructor
doesn't specify code to clean up the "flyweight" implementation of the
object. Class::Contract takes care of that automatically.

   Instead, the implementation is invoked before the object is
deallocated, and may be used to clean up any of the internal structure of
the object (for example to break reference cycles).

   It is also possible to define a "class destructor", which may be used
to clean up class attributes:

     contract {
             class attr 'obj_count';

     class dtor;
         impl { print STDLOG "Total was ${self->obj_count}\n" };
             };

   The class destructor is invoked from an END block within Class::Contract
(although the implementation itself is a closure, so it executes in the
namespace of the original class).

Constraining class elements
---------------------------

   As described so far, Class::Contract doesn't provide any features that
differ greatly from those of any other class definition module. But
Class::Contract does have one significant difference: it allows the class
designer to specify "clauses" that implement and enforce a contract on the
class's interface.

   Contract clauses are specified as labelled blocks of code, associated
with a particular class, method, or attribute definition.

Class invariants
----------------

   Classes may be given *invariants*: clauses than must be satisfied at
the end of any method call that is invoked from outside the class itself.
For example, to specify that a class's object count attribute must never
fall below zero:

     contract {
             invar { ${self->obj_count} >= 0 };
     };

   The block following `invar' is treated as if it were a class method
that is automatically invoked after every other method invocation. If the
method returns false, croak is invoked with the error message: `'Class
invariant at %s failed'' (where the '%s' is replaced by the file and line
number at which the invariant was defined).

   This error message can be customized, using the `failmsg' subroutine:

     contract {
             invar { ${self->obj_count} >= 0 };
                 failmsg 'Anti-objects detected by invariant at %s';
     };

   Once again, the '%s' is replaced by the appropriate file name and line
number. A `failmsg' can be specified after other types of clause too (see
below).

   A class may have as many invariants as it requires, and they may be
specified anywhere throughout the the body of the `contract'.

Attribute and method pre- and post-conditions
---------------------------------------------

   Pre- and post-conditions on methods and attributes are specified using
the pre and post subroutines respectively.

   For attributes, pre-conditions are called before the attribute's
accessor is invoked, and post-conditions are called after the reference
returned by the accessor is no longer accessible. This is achieved by
having the accessor return a tied scalar whose DESTROY method invokes the
post-condition.

   Method pre-conditions are tested before their method's implementation is
invoked; post-conditions are tested after the implementation finishes (but
before the method's result is returned). Constructors are (by definition)
class methods and may have pre- and post-conditions, just like any other
method.

   Both types of condition clause receive the same argument list as the
accessor or method implementation that they constrain. Both are expected
to return a false value if they fail:

     contract {
             class attr 'obj_count';
                 post { ${&value} > 0 };
                   failmsg 'Anti-objects detected by %s';

     method 'inc_count';
         post { ${self->obj_count} < 1000000 };
           failmsg 'Too many objects!';
         impl { ${self->obj_count}++ };
             };

   Note that within the pre- and post-conditions of an attribute, the
special value subroutine returns a reference to the attribute itself, so
that conditions can check properties of the attribute they guard.

   Methods and attributes may have as many distinct pre- and
post-conditions as they require, specified in any convenient order.

Checking state changes.
-----------------------

   Post-conditions and invariants can access the previous state of an
object or the class, via the old subroutine. Within any post-condition or
invariant, this subroutine returns a reference to a copy of the object or
class state, as it was just before the current method or accessor was
called.

   For example, an append method might use old to verify the appropriate
change in size of an object:

     contract {
         method 'append';
             post { @{self->queue} == @{old->queue} + @_ }
             impl { push @{self->queue}, @_ };
     };

   Note that the implementation's return value is also available in the
method's post-condition(s) and the class's invariants, through the
subroutine value. In the above example, the implementation of append
returns the new size of the queue (i.e. what push returns), so the
post-condition could also be written:

     contract {
         method 'append';
             post { ${&value} == @{old->queue} + @_ }
             impl { push @{self->queue}, @_ };
     };

   Note that value will return a reference to a scalar or to an array,
depending on the context in which the method was originally called.

Clause control
--------------

   Any type of clause may be declared optional:

     contract {
             optional invar { @{self->list} > 0 };
             failmsg 'Empty queue detected at %s after call';
     };

   By default, optional clauses are still checked every time a method or
accessor is invoked, but they may also be switched off (and back on) at
run-time, using the check method:

     local $_ = 'Queue';         # Specify in $_ which class to disable
     check my %contract => 0;    # Disable optional checks for class Queue

   This (de)activation is restricted to the scope of the hash that is
passed as the first argument to check. In addition, the change only
affects the class whose name is held in the variable $_ at the time check
is called.  This makes it easy to (de)activate checks for a series of
classes:

     check %contract => 0 for qw(Queue PriorityQueue DEQueue);  # Turn off
     check %contract => 1 for qw(Stack PriorityStack Heap);     # Turn on

   The special value `'__ALL__'' may also be used as a (pseudo-)class name:

     check %contract => 0 for __ALL__;

   This enables or disables checking on every class defined using
Class::Contract. But note that only clauses that were originally declared
optional are affected by calls to check. Non-optional clauses are always
checked.

   Optional clauses are typically universally disabled in production code,
so Class::Contract provides a short-cut for this. If the module is
imported with the single argument `'production'', optional clauses are
universally and irrevocably deactivated. In fact, the optional subroutine
is replaced by:

     sub Class::Contract::optional {}

   so that optional clauses impose no run-time overhead at all.

   In production code, contract checking ought to be disabled completely,
and the requisite code optimized away.  To do that, simply change:

     use Class::Contract;

   to

     use Class::Contract::Production;

Inheritance
-----------

   The semantics of class inheritance for Class::Contract classes differ
in several respects from those of normal object-oriented Perl.

   To begin with, classes defined using Class::Contract have a *static
inheritance hierarchy*. The inheritance relationships of contracted classes
are defined using the `inherits' subroutine within the class's `contract'
block:

     package PriorityQueue;
     contract {
             inherits qw( Queue OrderedContainer );
     };

   That means that ancestor classes are fixed at compile-time (rather than
being determined at run-time by the @ISA array). Note that multiple
inheritance is supported.

   Method implementations are only inherited if they are not explicitly
provided. As with normal OO Perl, a method's implementation is inherited
from the left-most ancestral class that provides a method of the same name
(though with Class::Contract, this is determined at compile-time).

   Constructors are a special case, however. Their "constructive"
behaviour is always specific to the current class, and hence involves no
inheritance under any circumstances. However, the "initialising" behaviour
specified by a constructor's `impl' block *is* inherited. In fact, the
implementations of all base class constructors are called automatically by
the derived class constructor (in left-most, depth-first order), and
passed the same argument list as the invoked constructor. This behaviour
is much more like that of other OO programming languages (for example,
Eiffel or C++).

   Methods in a base class can also be declared as being abstract:

     contract {
         abstract method 'remove';
             post { ${self->count} == ${old->count}-1 };
     };

   Abstract methods act like placeholders in an inheritance hierarchy.
Specifically, they have no implementation, existing only to reserve the
name of a method and to associate pre- and post-conditions with it.

   An abstract method cannot be directly called (although its associated
conditions may be). If such a method is ever invoked, it immediately calls
croak. Therefore, the presence of an abstract method in a base class
requires the derived class to redefine that method, if the derived class
is to be usable. To ensure this, any constructor built by Class::Contract
will refuse to create objects belonging to classes with abstract methods.

   Methods in a base class can also be declared as being private:

     contract {
         private method 'remove';
             impl { pop @{self->queue} };
     };

   Private methods may only be invoked by the class or one of its
descendants.

Inheritance and condition checking
----------------------------------

   Attribute accessors and object methods inherit all post-conditions of
every ancestral accessor or method of the same name. Objects and classes
also inherit all invariants from any ancestor classes. That is, methods
accumulate all the post- and invariant checks that their ancestors
performed, as well as any new ones they define for themselves, and must
satisfy all of them in order to execute successfully.

   Pre-conditions are handled slightly differently. The principles of
design-by-contract programming state that pre-conditions in derived
classes can be no stronger than those in base classes (and may well be
weaker). In other words, a derived class must handle every case that its
base class handled, but may choose to handle other cases as well, by being
less demanding regarding its pre-conditions.

   Meyers suggests an efficient way to achieve this relaxation of
constraints without the need for detailed logical analysis of
pre-conditions. His solution is to allow a derived class method or
accessor to run if *either* the pre-conditions it inherits are satisfied
or its own pre-conditions are satisfied. This is precisely the semantics
that Class::Contract uses when checking pre-conditions in derived classes.

A complete example
------------------

   The following code implements a PriorityStack class, in which elements
pushed onto the stack "sink" until they encounter an element with lower
priority.  Note the use of old to check that object state has changed
correctly, and the use of explicit dispatch (e.g. `self->Stack::pop') to
invoke inherited methods from the derived-class methods that redefine them.

     package PriorityStack;
     use Class::Contract;

     contract {
         # Reuse existing implementation...
         inherits 'Stack';

     # Name the constructor (nothing special to do, so no implementation)
     ctor 'new';

     method 'push';
         # Check that data to be added is okay...
         pre  { defined $_[0] };
             failmsg 'Cannot push an undefined value';
         pre  { $_[1] > 0 };
             failmsg 'Priority must be greater than zero';

     # Check that push increases stack depth appropriately...
     post { self->count == old->count+1 };

     # Check that the right thing was left on top...
     post { old->top->{'priority'} <= self->top->{'priority'} };

     # Implementation reuses inherited methods: pop any higher
     # priority entries, push the new entry, then re-bury it...
     impl {
         my ($newval, $priority) = @_[0,1];
         my @betters;
         unshift @betters, self->Stack::pop
             while self->count
                && self->Stack::top->{'priority'} > $priority;
         self->Stack::push( {'val'=>$newval, priority=>$priority} );
         self->Stack::push( $_ )  foreach @betters;
     };

     method 'pop';
         # Check that pop decreases stack depth appropriately...
         post { self->count == old->count-1 };

     # Reuse inherited method...
     impl {
         return  unless self->count;
         return self->Stack::pop->{'val'};
     };

     method 'top';
         post { old->count == self->count }
         impl {
             return  unless self->count;
             return self->Stack::top->{'val'};
         };
             };

FUTURE WORK
===========

   Future work on Class::Contract will concentrate on three areas:

  1. Improving the attribute accessor mechanism Lvalue subroutines will be
     introduced in perl version 5.6. They will allow a return value to be
     treated as an alias for the (scalar) argument of a return statement.
     This will make it possible to write subroutines whose return value
     may be assigned to (like the built-in pos and substr functions).

     In the absence of this feature, Class::Contract accessors of all types
     return a reference to their attribute, which then requires an explicit
     dereference:

          ${self->value} = $newval;
          ${self->access_count}++;

     When this feature is available, accessors for scalar attributes will
     be able to return the actual attribute itself as an lvalue. The above
     code would then become cleaner:

          self->value = $newval;
          self->access_count++;

  2. Providing better software engineering tools.  Contracts make the
     consequences of inheritance harder to predict, since they
     significantly increase the amount of ancestral behaviour (i.e.
     contract clauses) that a class inherits.

     Languages such as Eiffel provide useful tools to help the software
     engineer make sense of this extra information. In particular, Eiffel
     provides two alternate ways of inspecting a particular class - flat
     form and short form.

     "Flattening" a class produces an equivalent class definition without
     any inheritance. That is, the class is modified by making explicit
     all the attributes, methods, conditions, and invariants it inherits
     from other classes. This allows the designer to see every feature a
     class possesses in one location.

     "Shortening" a class, takes the existing class definition and removes
     all implementation aspects of it - that is, those that have no
     bearing on its public interface. A shortened representation of a
     class therefore has all attribute specifications and method
     implementations removed. Note that the two processes can be
     concatenated: shortening a flattened class produces an explicit
     listing of its complete public interface. Such a representation can
     be profitably used as a basis for documenting the class.

     It is envisaged that Class::Contract will eventually provide a
     mechanism to produce equivalent class representations in Perl.

  3. Offering better facilities for retrofitting contracts.  At present,
     adding contractual clauses to an existing class requires a major
     restructuring of the original code. Clearly, if design-by-contract is
     to gain popularity with Perl programmers, this transition cost must
     be minimized.

     It is as yet unclear how this might be accomplished, but one
     possibility would be to allow the implementation of certain parts of a
     Class::Contract class (perhaps even the underlying object
     implementation itself) to be user-defined.

AUTHOR
======

   Damian Conway (damian@conway.org)

MAINTAINER
==========

   C. Garrett Goebel (ggoebel@cpan.org)

BUGS
====

   There are undoubtedly serious bugs lurking somewhere in code this funky
:-) Bug reports and other feedback are most welcome.

COPYRIGHT
=========

   Copyright (c) 1997-2000, Damian Conway. All Rights Reserved.  This
module is free software. It may be used, redistributed and/or modified
under the terms of the Perl Artistic License   (see
http://www.perl.com/perl/misc/Artistic.html)

   Copyright (c) 2000-2001, C. Garrett Goebel. All Rights Reserved.  This
module is free software. It may be used, redistributed and/or modified
under the terms of the Perl Artistic License   (see
http://www.perl.com/perl/misc/Artistic.html)

Design-by-Contract OO in Perl.
******************************

NAME
====

   Class::Contract - Design-by-Contract OO in Perl.

VERSION
=======

   This document describes version 1.10 of Class::Contract, released
February  9, 2001.

SYNOPSIS
========

     package ClassName
     use Class::Contract;

     contract {
       inherits 'BaseClass';

     invar { ... };

     attr 'data1';
     attr 'data2' => HASH;

     class attr 'shared' => SCALAR;

     ctor 'new';

     method 'methodname';
       pre  { ... };
         failmsg 'Error message';

     post  { ... };
       failmsg 'Error message';

     impl { ... };

     method 'nextmethod';
       impl { ... };

     class method 'sharedmeth';
       impl { ... };

     # etc.
         };

DESCRIPTION
===========

Background
----------

   Design-by-contract is a software engineering technique in which each
module of a software system specifies explicitly what input (or data or
arguments) it requires, and what output (or information or results) it
guarantees to produce in response.

   These specifications form the "clauses" of a contract between a module
and the client software that uses it. If the client software abides by the
input requirements, the module guarantees to produce the correct output.
Hence by verifying these clauses at each interaction with a module, the
overall behaviour of the system can be confidently predicted.

   Design-by-contract reinforces the benefits of modular design techniques
by inserting explicit compile-time or run-time checks on a contract.
These checks are most often found in object-oriented languages and are
typically implemented as pre-conditions and post-conditions on methods,
and invariants on classes.

   Note that these features differ from simple verification statements
such as the C assert statement. Conditions and invariants are properties
of a class, and are inherited by derived classes.

   An additional capacity that is often provided in design-by-contract
systems is the ability to selectively disable checking in production code.
This allows the contractual testing to be carried out during
implementation, without impinging on the performance of the final system.

Adding design-by-contract to Perl
---------------------------------

   The Class::Contract module provides a framework for specifying methods
and attributes for a class (much like the existing class definition
modules Class::Struct, Class::MethodMaker, and Class::Generate).
Class::Contract allows both per-object and per-class methods and
attributes to be defined. Attributes may be scalar-, array-, hash-, or
object-based.

   Class::Contract differs from other class-specification modules (except
Class::Generate) in that it also provides the ability to specify invariant
conditions on classes, and pre- and post-conditions on methods and
attributes. All of these clauses are fully inheritable, and may be
selectively disabled. It differs from all other modules in that it has a
cleaner, simpler specification syntax, and - more importantly - it
enforces encapsulation of object attributes, thereby ensuring that the
class contract cannot be subverted.

Defining classes
----------------

   Class::Contract provides an explicit syntax for defining the attributes,
methods, and constructors of a class. The class itself is defined using
the `contract' subroutine. `contract' takes a single argument - a
subroutine reference or a block. That block is executed once and the
results used to construct and install the various components of the class
in the current package:

     package Queue;
     contract {
       # specification of class Queue attributes and methods here
     };

Defining attributes
-------------------

   Attributes are defined within the `contract' block via the attr
subroutine.  Attributes must be given a name, and may also be given a
type: SCALAR, ARRAY, HASH, or a class name:

     contract {
             attr 'last';                   # Scalar attribute (by default)
             attr 'lest' => SCALAR;         # Scalar attribute
             attr 'list' => ARRAY;          # Array attribute
             attr 'lost' => HASH;           # Hash attribute
             attr 'lust' => MyClass;        # Object attribute
     };

   For each attribute so declared, Class::Contract creates an *accessor* -
a method that returns a reference to the attribute in question. Code using
these accessors might look like this:

     ${$obj->last}++;
     push @{$obj->list}, $newitem;
     print $obj->lost->{'marbles'};
     $obj->lust->after('technology stocks');

   Attributes are normally object-specific, but it is also possible to
define attributes that are shared by all objects of a class. Class objects
are specified by prefixing the call to attr with a call to the class
subroutine:

     class Queue;
     contract {
             class attr 'obj_count';
     };

   The accessor for this shared attribute can now be called either as an
object method:

     print ${$obj->obj_count};

   or as a class method:

     print ${Queue->obj_count};

   In order to ensure that the clauses of a class' contract (see below)
are honoured, both class and object attributes are only accessible via
their accessors, and those accessors may only be called within methods
belonging to the same class hierarchy. Objects are implemented as
"flyweight scalars" in order to ensure this strict encapsulation is
preserved.

Defining methods
----------------

   Methods are defined in much the same way as attributes. The method
subroutine is used to specify the name of a method, then the `impl'
subroutine is used to provide an implementation for it:

     contract {
             attr list => ARRAY;

     method 'next';
         impl { shift @{self->list} };

     method 'enqueue';
         impl { push @{self->list}, $_[1] };
             };

   `impl' takes a block (or a reference to a subroutine), which is used as
the implementation of the method named by the preceding method call.
Within that block, the subroutine `self' may be used to return a reference
to the object on which the method was called. Unlike, regular OO Perl, the
object reference is not passed as the method's first argument.  (Note:
this change occurred in version 1.10)

   Like attributes, methods normally belong to - and are accessed via - a
specific object. To define methods that belong to the entire class, the
class qualifier is once again used:

     contract {
             class attr 'obj_count';

     class method 'inc_count';
             impl { ${self->obj_count}++ };
             };

   Note that the `self' subroutine can still be used - within a class
method it returns the appropriate class name, rather than an object
reference.

Defining constructors
---------------------

   Class::Contract requires constructors to be explicitly defined using
the `ctor' subroutine:

     contract {
             ctor 'new';
                 impl { @{self->list} = ( $_[0] ) }
     };

   Note that the implementation section of a constructor *doesn't* specify
code to build or bless the new object. That is taken care of automatically
(in order to ensure the correct "flyweight" implementation of the object).

   Instead, the constructor implementation is invoked after the object has
been created and blessed into the class. Hence the implementation only
needs to initialize the various attributes of the `self' object.  In
addition, the return value of the implementation is ignored: constructor
calls always return a reference to the newly created object.

   Any attribute that is not initialized by a constructor is automatically
"default initialized". By default, scalar attributes remain undef, array
and hash attributes are initialized to an empty array or hash, and object
attributes are initialized by having their new constructor called (with no
arguments). This is the only reasonable default for object attributes, but
it is usually advisable to initialize them explicitly in the constructor.

   It is also possible to define a "class constructor", which may be used
to initialize class attributes:

     contract {
             class attr 'obj_count';

     class ctor;
             impl { ${self->obj_count} = 0 };
             };

   The class constructor is invoked at the very end of the call to
`contract' in which the class is defined.

   Note too that the class constructor does not require a name. It may,
however, be given one, so that it can be explicitly called again (as a
class method) later in the program:

     class MyClass;
     contract {
             class attr 'obj_count';

     class ctor 'reset';
             impl { ${self->obj_count} = 0 };
             };

     # and later...

     MyClass->reset;

Defining destructors
--------------------

   Destructors are also explicitly defined under Class::Contract, using
the `dtor' subroutine:

     contract {
             dtor;
                 impl { print STDLOG "Another object died\n" }
     };

   As with the constructor, the implementation section of a destructor
doesn't specify code to clean up the "flyweight" implementation of the
object. Class::Contract takes care of that automatically.

   Instead, the implementation is invoked before the object is
deallocated, and may be used to clean up any of the internal structure of
the object (for example to break reference cycles).

   It is also possible to define a "class destructor", which may be used
to clean up class attributes:

     contract {
             class attr 'obj_count';

     class dtor;
         impl { print STDLOG "Total was ${self->obj_count}\n" };
             };

   The class destructor is invoked from an END block within Class::Contract
(although the implementation itself is a closure, so it executes in the
namespace of the original class).

Constraining class elements
---------------------------

   As described so far, Class::Contract doesn't provide any features that
differ greatly from those of any other class definition module. But
Class::Contract does have one significant difference: it allows the class
designer to specify "clauses" that implement and enforce a contract on the
class's interface.

   Contract clauses are specified as labelled blocks of code, associated
with a particular class, method, or attribute definition.

Class invariants
----------------

   Classes may be given *invariants*: clauses than must be satisfied at
the end of any method call that is invoked from outside the class itself.
For example, to specify that a class's object count attribute must never
fall below zero:

     contract {
             invar { ${self->obj_count} >= 0 };
     };

   The block following `invar' is treated as if it were a class method
that is automatically invoked after every other method invocation. If the
method returns false, croak is invoked with the error message: `'Class
invariant at %s failed'' (where the '%s' is replaced by the file and line
number at which the invariant was defined).

   This error message can be customized, using the `failmsg' subroutine:

     contract {
             invar { ${self->obj_count} >= 0 };
                 failmsg 'Anti-objects detected by invariant at %s';
     };

   Once again, the '%s' is replaced by the appropriate file name and line
number. A `failmsg' can be specified after other types of clause too (see
below).

   A class may have as many invariants as it requires, and they may be
specified anywhere throughout the the body of the `contract'.

Attribute and method pre- and post-conditions
---------------------------------------------

   Pre- and post-conditions on methods and attributes are specified using
the pre and post subroutines respectively.

   For attributes, pre-conditions are called before the attribute's
accessor is invoked, and post-conditions are called after the reference
returned by the accessor is no longer accessible. This is achieved by
having the accessor return a tied scalar whose DESTROY method invokes the
post-condition.

   Method pre-conditions are tested before their method's implementation is
invoked; post-conditions are tested after the implementation finishes (but
before the method's result is returned). Constructors are (by definition)
class methods and may have pre- and post-conditions, just like any other
method.

   Both types of condition clause receive the same argument list as the
accessor or method implementation that they constrain. Both are expected
to return a false value if they fail:

     contract {
             class attr 'obj_count';
                 post { ${&value} > 0 };
                   failmsg 'Anti-objects detected by %s';

     method 'inc_count';
         post { ${self->obj_count} < 1000000 };
           failmsg 'Too many objects!';
         impl { ${self->obj_count}++ };
             };

   Note that within the pre- and post-conditions of an attribute, the
special value subroutine returns a reference to the attribute itself, so
that conditions can check properties of the attribute they guard.

   Methods and attributes may have as many distinct pre- and
post-conditions as they require, specified in any convenient order.

Checking state changes.
-----------------------

   Post-conditions and invariants can access the previous state of an
object or the class, via the old subroutine. Within any post-condition or
invariant, this subroutine returns a reference to a copy of the object or
class state, as it was just before the current method or accessor was
called.

   For example, an append method might use old to verify the appropriate
change in size of an object:

     contract {
         method 'append';
             post { @{self->queue} == @{old->queue} + @_ }
             impl { push @{self->queue}, @_ };
     };

   Note that the implementation's return value is also available in the
method's post-condition(s) and the class's invariants, through the
subroutine value. In the above example, the implementation of append
returns the new size of the queue (i.e. what push returns), so the
post-condition could also be written:

     contract {
         method 'append';
             post { ${&value} == @{old->queue} + @_ }
             impl { push @{self->queue}, @_ };
     };

   Note that value will return a reference to a scalar or to an array,
depending on the context in which the method was originally called.

Clause control
--------------

   Any type of clause may be declared optional:

     contract {
             optional invar { @{self->list} > 0 };
             failmsg 'Empty queue detected at %s after call';
     };

   By default, optional clauses are still checked every time a method or
accessor is invoked, but they may also be switched off (and back on) at
run-time, using the check method:

     local $_ = 'Queue';         # Specify in $_ which class to disable
     check my %contract => 0;    # Disable optional checks for class Queue

   This (de)activation is restricted to the scope of the hash that is
passed as the first argument to check. In addition, the change only
affects the class whose name is held in the variable $_ at the time check
is called.  This makes it easy to (de)activate checks for a series of
classes:

     check %contract => 0 for qw(Queue PriorityQueue DEQueue);  # Turn off
     check %contract => 1 for qw(Stack PriorityStack Heap);     # Turn on

   The special value `'__ALL__'' may also be used as a (pseudo-)class name:

     check %contract => 0 for __ALL__;

   This enables or disables checking on every class defined using
Class::Contract. But note that only clauses that were originally declared
optional are affected by calls to check. Non-optional clauses are always
checked.

   Optional clauses are typically universally disabled in production code,
so Class::Contract provides a short-cut for this. If the module is
imported with the single argument `'production'', optional clauses are
universally and irrevocably deactivated. In fact, the optional subroutine
is replaced by:

     sub Class::Contract::optional {}

   so that optional clauses impose no run-time overhead at all.

   In production code, contract checking ought to be disabled completely,
and the requisite code optimized away.  To do that, simply change:

     use Class::Contract;

   to

     use Class::Contract::Production;

Inheritance
-----------

   The semantics of class inheritance for Class::Contract classes differ
in several respects from those of normal object-oriented Perl.

   To begin with, classes defined using Class::Contract have a *static
inheritance hierarchy*. The inheritance relationships of contracted classes
are defined using the `inherits' subroutine within the class's `contract'
block:

     package PriorityQueue;
     contract {
             inherits qw( Queue OrderedContainer );
     };

   That means that ancestor classes are fixed at compile-time (rather than
being determined at run-time by the @ISA array). Note that multiple
inheritance is supported.

   Method implementations are only inherited if they are not explicitly
provided. As with normal OO Perl, a method's implementation is inherited
from the left-most ancestral class that provides a method of the same name
(though with Class::Contract, this is determined at compile-time).

   Constructors are a special case, however. Their "constructive"
behaviour is always specific to the current class, and hence involves no
inheritance under any circumstances. However, the "initialising" behaviour
specified by a constructor's `impl' block *is* inherited. In fact, the
implementations of all base class constructors are called automatically by
the derived class constructor (in left-most, depth-first order), and
passed the same argument list as the invoked constructor. This behaviour
is much more like that of other OO programming languages (for example,
Eiffel or C++).

   Methods in a base class can also be declared as being abstract:

     contract {
         abstract method 'remove';
             post { ${self->count} == ${old->count}-1 };
     };

   Abstract methods act like placeholders in an inheritance hierarchy.
Specifically, they have no implementation, existing only to reserve the
name of a method and to associate pre- and post-conditions with it.

   An abstract method cannot be directly called (although its associated
conditions may be). If such a method is ever invoked, it immediately calls
croak. Therefore, the presence of an abstract method in a base class
requires the derived class to redefine that method, if the derived class
is to be usable. To ensure this, any constructor built by Class::Contract
will refuse to create objects belonging to classes with abstract methods.

   Methods in a base class can also be declared as being private:

     contract {
         private method 'remove';
             impl { pop @{self->queue} };
     };

   Private methods may only be invoked by the class or one of its
descendants.

Inheritance and condition checking
----------------------------------

   Attribute accessors and object methods inherit all post-conditions of
every ancestral accessor or method of the same name. Objects and classes
also inherit all invariants from any ancestor classes. That is, methods
accumulate all the post- and invariant checks that their ancestors
performed, as well as any new ones they define for themselves, and must
satisfy all of them in order to execute successfully.

   Pre-conditions are handled slightly differently. The principles of
design-by-contract programming state that pre-conditions in derived
classes can be no stronger than those in base classes (and may well be
weaker). In other words, a derived class must handle every case that its
base class handled, but may choose to handle other cases as well, by being
less demanding regarding its pre-conditions.

   Meyers suggests an efficient way to achieve this relaxation of
constraints without the need for detailed logical analysis of
pre-conditions. His solution is to allow a derived class method or
accessor to run if *either* the pre-conditions it inherits are satisfied
or its own pre-conditions are satisfied. This is precisely the semantics
that Class::Contract uses when checking pre-conditions in derived classes.

A complete example
------------------

   The following code implements a PriorityStack class, in which elements
pushed onto the stack "sink" until they encounter an element with lower
priority.  Note the use of old to check that object state has changed
correctly, and the use of explicit dispatch (e.g. `self->Stack::pop') to
invoke inherited methods from the derived-class methods that redefine them.

     package PriorityStack;
     use Class::Contract;

     contract {
         # Reuse existing implementation...
         inherits 'Stack';

     # Name the constructor (nothing special to do, so no implementation)
     ctor 'new';

     method 'push';
         # Check that data to be added is okay...
         pre  { defined $_[0] };
             failmsg 'Cannot push an undefined value';
         pre  { $_[1] > 0 };
             failmsg 'Priority must be greater than zero';

     # Check that push increases stack depth appropriately...
     post { self->count == old->count+1 };

     # Check that the right thing was left on top...
     post { old->top->{'priority'} <= self->top->{'priority'} };

     # Implementation reuses inherited methods: pop any higher
     # priority entries, push the new entry, then re-bury it...
     impl {
         my ($newval, $priority) = @_[0,1];
         my @betters;
         unshift @betters, self->Stack::pop
             while self->count
                && self->Stack::top->{'priority'} > $priority;
         self->Stack::push( {'val'=>$newval, priority=>$priority} );
         self->Stack::push( $_ )  foreach @betters;
     };

     method 'pop';
         # Check that pop decreases stack depth appropriately...
         post { self->count == old->count-1 };

     # Reuse inherited method...
     impl {
         return  unless self->count;
         return self->Stack::pop->{'val'};
     };

     method 'top';
         post { old->count == self->count }
         impl {
             return  unless self->count;
             return self->Stack::top->{'val'};
         };
             };

FUTURE WORK
===========

   Future work on Class::Contract will concentrate on three areas:

  1. Improving the attribute accessor mechanism Lvalue subroutines will be
     introduced in perl version 5.6. They will allow a return value to be
     treated as an alias for the (scalar) argument of a return statement.
     This will make it possible to write subroutines whose return value
     may be assigned to (like the built-in pos and substr functions).

     In the absence of this feature, Class::Contract accessors of all types
     return a reference to their attribute, which then requires an explicit
     dereference:

          ${self->value} = $newval;
          ${self->access_count}++;

     When this feature is available, accessors for scalar attributes will
     be able to return the actual attribute itself as an lvalue. The above
     code would then become cleaner:

          self->value = $newval;
          self->access_count++;

  2. Providing better software engineering tools.  Contracts make the
     consequences of inheritance harder to predict, since they
     significantly increase the amount of ancestral behaviour (i.e.
     contract clauses) that a class inherits.

     Languages such as Eiffel provide useful tools to help the software
     engineer make sense of this extra information. In particular, Eiffel
     provides two alternate ways of inspecting a particular class - flat
     form and short form.

     "Flattening" a class produces an equivalent class definition without
     any inheritance. That is, the class is modified by making explicit
     all the attributes, methods, conditions, and invariants it inherits
     from other classes. This allows the designer to see every feature a
     class possesses in one location.

     "Shortening" a class, takes the existing class definition and removes
     all implementation aspects of it - that is, those that have no
     bearing on its public interface. A shortened representation of a
     class therefore has all attribute specifications and method
     implementations removed. Note that the two processes can be
     concatenated: shortening a flattened class produces an explicit
     listing of its complete public interface. Such a representation can
     be profitably used as a basis for documenting the class.

     It is envisaged that Class::Contract will eventually provide a
     mechanism to produce equivalent class representations in Perl.

  3. Offering better facilities for retrofitting contracts.  At present,
     adding contractual clauses to an existing class requires a major
     restructuring of the original code. Clearly, if design-by-contract is
     to gain popularity with Perl programmers, this transition cost must
     be minimized.

     It is as yet unclear how this might be accomplished, but one
     possibility would be to allow the implementation of certain parts of a
     Class::Contract class (perhaps even the underlying object
     implementation itself) to be user-defined.

AUTHOR
======

   Damian Conway (damian@conway.org)

MAINTAINER
==========

   C. Garrett Goebel (ggoebel@cpan.org)

BUGS
====

   There are undoubtedly serious bugs lurking somewhere in code this funky
:-) Bug reports and other feedback are most welcome.

COPYRIGHT
=========

   Copyright (c) 1997-2000, Damian Conway. All Rights Reserved.  This
module is free software. It may be used, redistributed and/or modified
under the terms of the Perl Artistic License   (see
http://www.perl.com/perl/misc/Artistic.html)

   Copyright (c) 2000-2001, C. Garrett Goebel. All Rights Reserved.  This
module is free software. It may be used, redistributed and/or modified
under the terms of the Perl Artistic License   (see
http://www.perl.com/perl/misc/Artistic.html)

Simple Object Persistance
*************************

NAME
====

     Class::DBI - Simple Object Persistance

SYNOPSIS
========

     package Film;
     use base qw(Class::DBI);

     # Tell Class::DBI a little about yourself.
     Film->table('Movies');
     Film->columns(All     => qw( Title Director Rating NumExplodingSheep ));
     Film->columns(Primary => qw( Title ));
     Film->set_db('Main', 'dbi:mysql', 'me', 'noneofyourgoddamnedbusiness',
                  {AutoCommit => 1});

     #-- Meanwhile, in a nearby piece of code! --#
     use Film;

     # Create a new film entry for Bad Taste.
     $btaste = Film->new({ Title       => 'Bad Taste',
                           Director    => 'Peter Jackson',
                           Rating      => 'R',
                           NumExplodingSheep   => 1
                         });

     # Retrieve the 'Gone With The Wind' entry from the database.
     my $gone = Film->retrieve('Gone With The Wind');

     # Shocking new footage found reveals bizarre Scarlet/sheep scene!
     $gone->NumExplodingSheep(5);
     $gone->Rating('NC-17');
     $gone->commit;

     # Grab the 'Bladerunner' entry.
     my $blrunner = Film->retrieve('Bladerunner');

     # Make a copy of 'Bladerunner' and create an entry of the director's
     # cut from it.
     my $blrunner_dc = $blrunner->copy("Bladerunner: Director's Cut");

     # Ishtar doesn't deserve an entry anymore.
     Film->retrieve('Ishtar')->delete;

     # Find all films which have a rating of PG.
     @films = Film->search('Rating', 'PG');

     # Find all films which were directed by Bob
     @films = Film->search_like('Director', 'Bob %');

DESCRIPTION
===========

   I hate SQL.  You hate SQL.  We all hate SQL.  Alas, we often find the
need to make our objects persistant and like it or not an SQL database is
usually the most flexible solution.

   This module is for setting up a reasonably efficient, reasonably
simple, reasonably extendable persistant object with as little SQL and DBI
knowledge as possible.

   Its uses a scheme to automatically set up accessors for each data field
in your class.  These accessors control access to the underlying database.

How to set it up
----------------

   Here's a fairly quick set of steps on how to make your class
persistant.  More details about individual methods will follow.

*Set up a database.*
     You must have an existing database set up, have DBI.pm installed and
     the necessary DBD:: driver module for that database.  See `DBI' in
     this node and the documentation of your particular database for
     details.

     DBD::CSV works in a pinch.

*Set up a table for your objects to be stored in.*
     Class::DBI works on a simple one class/one table model.  It is your
     responsibility to set up that table, automating the process would
     introduce too many complications (unless somebody wants to convince me
     otherwise).

     Using our Film example, you might declare a table something like this:

          CREATE TABLE Movies (
                 Title      VARCHAR(255)    PRIMARY KEY,
                 Director   VARCHAR(80),
                 Rating     CHAR(5),    /* to fit at least 'NC-17' */
                 NumExplodingSheep      INTEGER
          )

*Inherit from Class::DBI.*
     It is prefered that you use base.pm to do this rather than appending
     directly to @ISA as your class may have to inherit some protected data
     fields from Class::DBI and this is important if you're using
     pseudohashes.

          package Film;
          use base qw(Class::DBI);

*Declare your columns.*
     This can be done using columns().  The names of your fields should
     match the columns in your database, one to one.  Class::DBI (via
     Class::Accessor) will use this information to determine how to create
     accessors.

          Film->columns(All => qw( Title Director Rating NumExplodingSheep ));

     For more information about how you can more efficiently declare your
     columns, `"Lazy Population of Columns"' in this node

*Declare the name of your table*
     Inform Class::DBI what table you will be storing your objects in.
     This is the table you set up eariler.

          Film->table('Movies');

*Declare which field is your primary key*
     One of your fields must be a unique identifier for each object.  This
     will be the primary key in your database.  Class::DBI needs this
     piece of information in order to construct the proper SQL statements
     to access your stored objects.

          Film->columns(Primary => 'Title');

*Declare a database connection*
     Class::DBI needs to know how to access the database.  It does this
     through a DBI connection which you set up.  Set up is by calling the
     set_db() method and declaring a database connection named 'Main'.

          Film->set_db('Main', 'dbi:mysql', 'user', 'password', {AutoCommit => 1});

     set_db() is inherited from Ima::DBI.  See that module's man page for
     details.

     XXX I should probably make this even simpler.  set_db_main() or
     something.

Done.
     All set!  You can now use the constructors (new(), copy() and
     retrieve()) destructors (delete()) and all the accessors and other
     garbage provided by Class::DBI.  Make some new objects and muck
     around a bit.  Watch the table in your database as your object does
     its thing and see things being stored, changed and deleted.

   Is it not nifty?  Worship the module.

METHODS
=======

   The following provided methods make the assumption that you're using
either a hash or a pseudohash as your underlying data structure for your
object.

Life and Death - Constructors and Destructors
---------------------------------------------

   The following are methods provided for convenience to create, retrieve
and delete stored objects.  Its not entirely one-size fits all and you
might find it necessary to override them.

new
          $obj = Class->new(\%data);

     This is a constructor to create a new object and store it in the
     database.  %data consists of the initial information to place in your
     object and the database.  The keys of %data match up with the columns
     of your objects and the values are the initial settings of those
     fields.

     $obj is an instance of Class built out of a hash reference.

          # Create a new film entry for Bad Taste.
          $btaste = Film->new({ Title       => 'Bad Taste',
                                Director    => 'Peter Jackson',
                                Rating      => 'R',
                                NumExplodingSheep   => 1
                              });

     If the primary column is not in %data, new() will assume it is to be
     generated.  If a sequence() has been specified for this Class, it will
     use that.  Otherwise, it will assume the primary key has an
     AUTO_INCREMENT constraint on it and attempt to use that.

     If the class has declared relationships with foreign classes via
     hasa(), it can pass an object to new() for the value of that key.
     Class::DBI will Do The Right Thing.

retrieve
          $obj = Class->retrieve($id);

     Given an ID it will retrieve an object with that ID from the database.

          my $gone = Film->retrieve('Gone With The Wind');

copy
          $new_obj = $obj->copy;
          $new_obj = $obj->copy($new_id);

     This creates a copy of the given $obj both in memory and in the
     database.  The only difference is that the $new_obj will have a new
     primary identifier.  $new_id will be used if provided, otherwise the
     usual sequence or autoincremented primary key will be used.

          my $blrunner_dc = $blrunner->copy("Bladerunner: Director's Cut");

move
          my $new_obj = Sub::Class->move($old_obj);
          my $new_obj = Sub::Class->move($old_obj, $new_id);

     For transfering objects from one class to another.  Similar to copy(),
     an instance of Sub::Class is created using the data in $old_obj
     (Sub::Class is a subclass of $old_obj's subclass).  Like copy(),
     $new_id is used as the primary key of $new_obj, otherwise the usual
     sequence or autoincrement is used.

delete
          $obj->delete;

     Deletes this object from the database and from memory.  $obj is no
     longer usable after this call.

Accessors
---------

   Class::DBI inherits from Class::Accessor and thus provides accessor
methods for every column in your subclass.  It overrides the get() and
set() methods provided by Accessor to automagically handle database
transactions.

   There are two modes for the accessors to work in.  Manual commit and
autocommit.  This is sort of analagous to the manual vs autocommit in DBI,
but is not implemented in terms of this.  What it simply means is this...
when in autocommit mode every time one calls an accessor to make a change
the change will immediately be written to the database.  Otherwise, if
autocommit is off, no changes will be written until commit() is explicitly
called.

   This is an example of manual committing:

     # The calls to NumExplodingSheep() and Rating() will only make the
     # changes in memory, not in the database.  Once commit() is called
     # it writes to the database in one swell foop.
     $gone->NumExplodingSheep(5);
     $gone->Rating('NC-17');
     $gone->commit;

   And of autocommitting:

     # Turn autocommitting on for this object.
     $gone->autocommit(1);

     # Each accessor call causes the new value to immediately be written.
     $gone->NumExplodingSheep(5);
     $gone->Rating('NC-17');

   Manual committing is probably more efficient than autocommiting and it
provides the extra safety of a rollback() option to clear out all unsaved
changes.  Autocommitting is more convient for the programmer.

   If changes are left uncommitted or not rolledback when the object is
destroyed (falls out of scope or the program ends) then Class::DBI's
DESTROY method will print a warning about unsaved changes.

autocommit
          Class->autocommit($on_or_off);
          $commit_style = Class->autocommit;

          $obj->autocommit($on_or_off);
          $commit_style = $obj->autocommit;

     This is an accessor to the current style of autocommitting.  When
     called with no arguments it returns the current autocommitting state,
     true for on, false for off.  When given an argument it turns
     autocommiting on and off.  A true value turns it on, a false one off.
     When called as a class method it will control the committing style for
     every instance of the class.  When called on an individual object it
     will control committing for just that object, overriding the choice
     for the class.

          Class->autocommit(1);     # Autocommit is now on for the class.

          $obj = Class->retrieve('Aliens Cut My Hair');
          $obj->autocommit(0);      # Shut off autocommitting for this object.

     The commit setting for an object is not stored in the database.

     Autocommitting is off by default.

     NOTE This has *nothing* to do with DBI's AutoCommit attribute.

commit
          $obj->commit;

     Writes any changes you've made via accessors to disk.  There's nothing
     wrong with using commit() when autocommit is on, it'll just silently
     do nothing.

rollback
          $obj->rollback;

     Removes any changes you've made to this object since the last commit.
     Currently this simply reloads the values from the database.  This can
     have concurrency issues.

     If you're using autocommit this method will throw an exception.

is_changed
          @changed_keys = $obj->is_changed;

     Indicates if the given $obj has uncommitted changes.  Returns a list
     of keys which have changed.

Database information
--------------------

set_db
          Class->set_db($db_name, $data_source, $user, $password, \%attr);

     For details on this method, see Ima/DBI.

     The special connection named 'Main' must always be set.  Connections
     are inherited.

     Its often wise to set up a "top level" class for your entire
     application to inherit from, rather than directly from Class::DBI.
     This gives you a convenient point to place system-wide overrides and
     enhancements to Class::DBI's behavior.  It also lets you set the Main
     connection in one place rather than scattering the connection info all
     over the code.

          package My::Class::DBI;

          use base qw(Class::DBI);
          __PACKAGE__->set_db('Main', 'dbi:foo', 'user', 'password');

          package My::Other::Thing;

          # Instead of inheriting from Class::DBI.  We now have the Main
          # connection all set up.
          use base qw(My::Class::DBI);

     Class::DBI helps you along a bit to set up the database connection.
     set_db() normally provides its own default attributes on a per
     database basis.  For instance, if MySQL is detected, AutoCommit will
     be turned on.  Under Oracle, ChopBlanks is turned on.  As more
     databases are tested, more defaults will be added.

     The defaults can always be overridden by supplying your own %attr.

id
          $id = $obj->id;

     Returns a unique identifier for this object.  Its the equivalent of
     $obj->get($self->columns('Primary'));

table
          Class->table($table);
          $table = Class->table;
          $table = $obj->table;

     An accessor to get/set the name of the database table in which this
     class is stored.  It -must- be set.

     Table information is inherited by subclasses, but can be overridden.

sequence
          Class->sequence($sequence_name);
          $sequence_name = Class->sequence;
          $sequence_name = $obj->sequence;

     An accessor to get/set the name of a sequence for the primary key.

          Class->columns(Primary => 'id');
          Class->sequence('class_id_seq');

     Class::DBI will use the sequence to generate primary keys when objects
     are created yet the primary key is not specified.

     NOTE: Class::DBI also supports AUTO_INCREMENT and similar semantics.

columns
          @all_columns  = $obj->columns;
          @columns      = $obj->columns($group);
          Class->columns($group, @columns);

     This is an accessor to the names of the database columns of a class.
     Its used to construct SQL statements to act on the class.

     Columns are grouped together by typical usage, this can allow more
     efficient access by loading all columns in a group at once.  For more
     information about this, `"Lazy Population of Columns"' in this node.

     There are three 'reserved' groups.  'All', 'Essential' and 'Primary'.

     *'All'* are all columns used by the class.  If not set it will be
     created from all the other groups.

     *'Primary'* is the single primary key column for this class.  It must
     be set before objects can be used.  (Multiple primary keys will be
     supported eventually)

          Class->columns('Primary', 'Title');

     *'Essential'* are the minimal set of columns needed to load and use
     the object.  Only the columns in this group will be loaded when an
     object is retreive()'d.  Its typically used so save memory on a class
     that has alot of columns but most only uses a few of them.  It will
     automatically be generated from `Class-'columns('All')> if you don't
     set it yourself.

     If no arguments are given it will assume you want a list of All
     columns.

     NOTE I haven't decided on this method's behavior in scalar context.

is_column
          Class->is_column($column);
          $obj->is_column($column);

     This will return true if the given $column is a column of the class or
     object.

Table relationships, Object relationships
-----------------------------------------

   Often you'll want one object to contain other objects in your database,
in the same way one table references another with foreign keys.  For
example, say we decided we wanted to store more information about
directors of our films.  You might set up a table...

     CREATE TABLE Directors (
         Name            VARCHAR(80),
         Birthday        INTEGER,
         IsInsane        BOOLEAN
     )

   And put a Class::DBI subclass around it.

     package Film::Directors;
     use base qw(Class::DBI);

     Film::Directors->table('Directors');
     Film::Directors->columns(All    => qw( Name Birthday IsInsane ));
     Film::Directors->columns(Prmary => qw( Name ));
     Film::Directors->set_db(Main => 'dbi:mysql', 'me', 'heywoodjablowme',
                             {AutoCommit => 1});

   Now Film can use its Director column as a way of getting at
Film::Directors objects, instead of just the director's name.  Its a
simple matter of adding one line to Film.

     # Director() is now an accessor to Film::Directors objects.
     Film->hasa('Film::Directors', 'Director');

   Now the Film->Director() accessor gets and sets Film::Director objects
instead of just their name.

hasa
          Class->hasa($foreign_class, @foreign_key_columns);

     Declares that the given Class has a relationship with the
     $foreign_class and is storing $foreign_class's primary key
     information in the @foreign_key_columns.

     An accessor will be generated with the name of the first element in
     @foreign_key_columns.  It gets/sets objects of $foreign_class.  Using
     our Film::Director example...

          # Set the director of Bad Taste to the Film::Director object
          # representing Peter Jackson.
          $pj     = Film::Directory->retreive('Peter Jackson');
          $btaste = Film->retreive('Bad Taste');
          $btaste->Director($pj);

     hasa() will try to require the foreign class for you.  If the require
     fails, it will assume its not a simple require (ie. Foreign::Class
     isn't in Foreign/Class.pm) and that you've already taken care of it
     and ignore the warning.

     It is not necessary to call columns() to set up the
     @foreign_key_columns.  hasa() will do this for you if you haven't
     already.

     XXX I don't know if I like the way this works.  It may change a bit in
     the future.  I'm not sure about the way the accessor is named.

     NOTE  The two classes do not have to be in the same database!

Lazy Population of Columns
--------------------------

   In the tradition of Perl, Class::DBI is lazy about how it loads your
objects.  Often, you find yourself using only a small number of the
available columns and it would be a waste of memory to load all of them
just to get at two, especially if you're dealing with large numbers of
objects simultaneously.

   Class::DBI will load a group of columns together.  You access one
column in the group, and it will load them all on the assumption that if
you use one you're probably going to use the rest.  So for example, say we
wanted to add NetProfit and GrossProfit to our Film class.  You're
probably going to use them together, so...

     Film->columns('Profit', qw(NetProfit GrossProfit));

   Now when you say:

     $net = $film->NetProfit;

   Class::DBI will load both NetProfit and GrossProfit from the database.
If you then call GrossProfit() on that same object it will not have to hit
the database.  This can potentially increase performance (YMMV).

   If you don't like this behavior, just create a group called 'All' and
stick all your columns into it.  Then Class::DBI will load everything at
once.

Data Normalization
------------------

   SQL is largely case insensitive.  Perl is largely not.  This can lead
to problems when reading information out of a database.  Class::DBI does
some data normalization.

normalize
          $obj->normalize(\@columns);

     There is no guarantee how a database will muck with the case of
     columns, so to protect against things like DBI->fetchrow_hashref()
     returning strangely cased column names (along with table names
     appended to the front) we normalize all column names before using them
     as data keys.

normalize_hash
          $obj->normalize_hash(\%hash);

     Given a %hash, it will normalize all its keys using normalize().
     This is for convenience.

Defining SQL statements
-----------------------

   Class::DBI inherits from Ima::DBI and prefers to use that class's style
of dealing with databases and DBI.  (Now is a good time to skim Ima::DBI's
man page).

   In order to write new methods which are inheritable by your subclasses
you must be careful not to hardcode any information about your class's
table name or primary key.  However, it is more efficient to use set_sql()
to generate cached statement handles.

   Generally, a call to set_sql() looks something like this:

     # Define sql_GetFooBar()
     Class->set_sql('GetFooBar', <<'SQL');
     SELECT %s
     FROM   %s
     WHERE  Foo = ? AND Bar = ?

   This generates a method called sql_GetFooBar().  Any arguments given
are used fill in your SQL statement via sprintf().

     my $sth = Class->sql_GetFooBar(join(', ', Class->columns('Essential')),
                                    Class->table);

   You must be careful not to hardcode information about your class's
table name or primary key column in your statement and instead use the
table() and columns() methods instead.

   If $db_name is omitted it will assume you are using the 'Main'
connection.

Searching
---------

   We provide a few simple search methods, more to show the potential of
the class than to be serious search methods.

search
          @objs = Class->search($key, $value);
          @objs = $obj->search($key, $value);

     This is a simple search through the stored objects for all objects
     whose $key has the given $value.

          @films = Film->search('Rating', 'PG');

search_like
          @objs = Class->search_like($key, $like_pattern);
          @objs = $obj->search_like($key, $like_pattern);

     A simple search for objects whose $key matches the $like_pattern
     given.  $like_pattern is a pattern given in SQL LIKE predicate syntax.
     '%' means "any one or more characters", '_' means "any single
     character".

     XXX Should I offer glob-style * and ? instead of % and _?

          # Search for movies directed by guys named Bob.
          @films = Film->search_like('Director', 'Bob %');

EXAMPLES
========

   Ummm... well, there's the SYNOPSIS.

   XXX Need more examples.  They'll come.

CAVEATS
=======

Only simple scalar values can be stored
---------------------------------------

   SQL sucks in that lists are really complicated to store and hashes
practically require a whole new table.  Don't even start about anything
more complicated.  If you want to store a list you're going to have to
write the accessors for it yourself (although I plan to prove ways to
handle this soon).  If you want to store a hash you should probably
consider making a new table and a new class.

   Someone might be able to convince me to build accessors which
automagically serialize data.

One table, one class
--------------------

   For every class you define one table.  Classes cannot be spread over
more than one table, this is too much of a headache to deal with.

   Eventually I'll ease this restriction for link tables and tables
representing lists of data.

Single column primary keys only
-------------------------------

   Having more than one column as your primary key in the SQL table is
currently not supported.  Why?  Its more complicated.  A later version
will support multi-column keys.

TODO
====

Table/object relationships need to be handled.
----------------------------------------------

   There's no graceful way to handle relationships between two
tables/objects.  I plan to eventually support these relationships in a
fairly simple manner.

Lists are poorly supported
--------------------------

   There's no graceful way to handle lists of things as object data.  This
is also something I plan to implement eventually.

Using pseudohashes as objects has to be documented
--------------------------------------------------

Cookbook needs to be written
----------------------------

Object caching needs to be added
--------------------------------

Multi-column primary keys untested.
-----------------------------------

   If you need this feature let me know and I'll get it working.

More testing with more databases.
---------------------------------

Complex data storage via Storable needed.
-----------------------------------------

There are concurrency problems
------------------------------

rollback() has concurrency problems
-----------------------------------

Working with transactions needs to be made easier.
--------------------------------------------------

   $obj->commit should DBI->commit???

   Need an easy way to do class-wide commit and rollback.

BUGS and CAVEATS
================

Tested with...
--------------

   DBD::mysql - MySQL 3.22 and 3.23

   DBD::Pg - PostgreSQL 7.0

   DBD::CSV

Reports it works with...
------------------------

   DBD::Oracle (patches still coming in)

Known not to work with...
-------------------------

   DBD::RAM

AUTHOR
======

   Michael G Schwern <schwern@pobox.com> with much late-night help from
Uri Gutman, Damian Conway, Mike Lambert and the POOP group.

SEE ALSO
========

   See Ima/DBI, Class/Accessor,
Base, Class/Data/Inheritable,
http://www.pobox.com/~schwern/papers/Class-DBI/, Perl Object-Oriented
Persistence <poop-group@lists.sourceforge.net>, `Alzabo' in this node and
`Tangram' in this node

Inheritable, overridable class data
***********************************

NAME
====

   Class::Data::Inheritable - Inheritable, overridable class data

SYNOPSIS
========

     package Stuff;
     use base qw(Class::Data::Inheritable);

     # Set up DataFile as inheritable class data.
     Stuff->mk_classdata('DataFile');

     # Declare the location of the data file for this class.
     Stuff->DataFile('/etc/stuff/data');

DESCRIPTION
===========

   Class::Data::Inheritable is for creating accessor/mutators to class
data.  That is, if you want to store something about your class as a whole
(instead of about a single object).  This data is then inherited by your
subclasses and can be overriden.

   For example:

     Pere::Ubu->mk_classdata('Suitcase');

   will generate the method Suitcase() in the class Pere::Ubu.

   This new method can be used to get and set a piece of class data.

     Pere::Ubu->Suitcase('Red');
     $suitcase = Pere::Ubu->Suitcase;

   The interesting part happens when a class inherits from Pere::Ubu:

     package Raygun;
     use base qw(Pere::Ubu);

     # Raygun's suitcase is Red.
     $suitcase = Raygun->Suitcase;

   Raygun inherits its Suitcase class data from Pere::Ubu.

   Inheritance of class data works analgous to method inheritance.  As
long as Raygun does not "override" its inherited class data (by using
Suitcase() to set a new value) it will continue to use whatever is set in
Pere::Ubu and inherit further changes:

     # Both Raygun's and Pere::Ubu's suitcases are now Blue
     Pere::Ubu->Suitcase('Blue');

   However, should Raygun decide to set its own Suitcase() it has now
"overridden" Pere::Ubu and is on its own, just like if it had overriden a
method:

     # Raygun has an orange suitcase, Pere::Ubu's is still Blue.
     Raygun->Suitcase('Orange');

   Now that Raygun has overridden Pere::Ubu futher changes by Pere::Ubu no
longer effect Raygun.

     # Raygun still has an orange suitcase, but Pere::Ubu is using Samsonite.
     Pere::Ubu->Suitcase('Samsonite');

Methods
=======

mk_classdata
          Class->mk_classdata($data_accessor_name);

     This is a class method used to declare new class data accessors.  A
     new accessor will be created in the Class using the name from
     $data_accessor_name.

     To facilitate overriding, mk_classdata creates an alias to the
     accessor, _field_accessor().  So Suitcase() would have an alias
     _Suitcase_accessor() that does the exact same thing as Suitcase().
     This is useful if you want to alter the behavior of a single accessor
     yet still get the benefits of inheritable class data.  For example.

          sub Suitcase {
              my($self) = shift;
              warn "Fashion tragedy" if @_ and $_[0] eq 'Plaid';

          $self->_Suitcase_accessor(@_);
            }

COPYRIGHT
=========

   Copyright (c) 2000, Damian Conway and Michael G Schwern. All Rights
Reserved.  This module is free software. It may be used, redistributed
and/or modified under the terms of the Perl Artistic License (see
http://www.perl.com/perl/misc/Artistic.html)

AUTHOR
======

   Original code by Damian Conway.

   Maintained by Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Perltootc (perl.info), has a very elaborate discussion
of class data in Perl.

easy-to-use implementation of object delegation.
************************************************

NAME
====

   Class::Delegate - easy-to-use implementation of object delegation.

SYNOPSIS
========

     require Class::Delegate;
     @ISA    = 'Class::Delegate';

     $self->add_delegate('some_name', $a);
     $self->add_delegate($b);
     $self->do_something_that_b_knows_how_to_do();
     $self->do_something_that_a_knows_how_to_do();

DESCRIPTION
===========

   This class provides transparent support for object delegation.  For more
information on delegation, see *Design Patterns* by Erich Gamma, et al.

METHODS
=======

add_delegate([ $name, ] $delegate)
     Assigns a delegate to your object.  Any delegate can be named or
     unnamed (see the delegate() method for information on the usefulness
     of naming a delegate).

resolve($methodname, $delegatename)
     Declare that calls to $methodname should be dispatched to the delegate
     named $delegatename.  This is primarily for resolving ambiguities when
     an object may have multiple delegates, more than one of which
     implements the same method.

delegate($name)
     This method returns the delegate named $name, or the empty list if
     there is no such delegate.

SOME DETAILS
============

   If a delegate's class defines a package variable called @PUBLIC, then
it is taken to be a list of method names that are available to be made
visible through the owner object.  Otherwise, all methods that are
implemented by the delegate (as returned by `can()') will be available as
call-throughs from the owner.

EXAMPLES
========

CALLING THE OWNER FROM THE DELEGATE
-----------------------------------

   If the delegate object implements a `set_owner()' method, then that
method will be called as part of the call to add_delegate().  Example:

     package Dispatcher;
     require Class::Delegate;
     @ISA    = qw(Class::Delegate);

     require Worker;

     sub new
     {
         my ($class) = @_;
         my $self    = bless {}, $class;

     $worker = Worker->new;
     $self->add_delegate('gofer', $worker);
         }

     sub respond_to_error { die "Oh no!\n" }

     ...

     package Worker;

     sub new { bless {}, shift }

     sub set_owner
     {
         my ($self, $owner)  = @_;

     $$self{owner}   = $owner;
         }

     sub do_something
     {
         my ($self, @args)   = @_;

     if (!@args) {
         $$self{owner}->respond_to_error();
     }

     ...
         }

BUGS
====

   This class only works with owner objects that are implemented as hash
references.

   If you assign a new value to a named delegate, the Right Thing will not
happen.

AUTHOR
======

     Kurt D. Starsinic <kstar@cpan.org>

COPYRIGHT
=========

   Copyright (c) 2000, Smith Renaud, Inc.  This program is free software;
you may distribute it and/or modify it under the same terms as Perl itself.

SEE ALSO
========

   perl(1).

Inspect the fields of a class.
******************************

NAME
====

   Class::Fields - Inspect the fields of a class.

SYNOPSIS
========

     use Class::Fields;

     is_field    ($class, $field);
     is_public   ($class, $field);
     is_private  ($class, $field);
     is_protected($class, $field);
     is_inherited($class, $field);

     @fields = show_fields($class, @attribs);

     $attrib     = field_attrib_mask($class, $field);
     @attribs    = field_attribs($class, $field);

     dump_all_attribs(@classes);

     # All functions also work as methods.
     package Foo;
     use base qw( Class::Fields );

     Foo->is_public($field);
     @fields = Foo->show_fields(@attribs);
     # ...etc...

DESCRIPTION
===========

   A collection of utility functions/methods for examining the data
members of a class.  It provides a nice, high-level interface that should
stand the test of time and Perl upgrades nicely.

   The functions in this module also serve double-duty as methods and can
be used that way by having your module inherit from it.  For example:

     package Foo;
     use base qw( Class::Fields );
     use fields qw( this that _whatever );

     print "'_whatever' is a private data member of 'Foo'" if
         Foo->is_private('_whatever');

     # Let's assume we have a new() method defined for Foo, okay?
     $obj = Foo->new;
     print "'this' is a public data member of 'Foo'" if
         $obj->is_public('this');

is_field
          is_field($class, $field);
          $class->is_field($field);

     Simply asks if a given $class has the given $field defined in it.

is_public
is_private
is_protected
is_inherited
          is_public($class, $field);
          is_private($class, $field);
          ...etc...
                or
          $obj->is_public($field);
                or
          Class->is_public($field);

     A bunch of functions to quickly check if a given $field in a given
     $class is of a given type.  For example...

          package Foo;
          use public  qw( Ford   );
          use private qw( _Nixon );

          package Bar;
          use base qw(Foo);

          # This will print only 'Ford is public' because Ford is a public
          # field of the class Bar.  _Nixon is a private field of the class
          # Foo, but it is not inherited.
          print 'Ford is public'        if is_public('Bar', 'Ford');
          print '_Nixon is inherited'   if is_inherited('Foo', '_Nixon');

show_fields
          @all_fields   = show_fields($class);
          @fields       = show_fields($class, @attribs);
                or
          @all_fields   = $obj->show_fields;
          @fields       = $obj->show_fields(@attribs);
                or
          @all_fields   = Class->show_fields;
          @fields       = Class->show_fields(@attribs);

     This will list all fields in a given $class that have the given set of
     @attribs.  If @attribs is not given it will simply list all fields.

     The currently available attributes are:     Public, Private,
     Protected and Inherited

     For example:

          package Foo;
          use fields qw(this that meme);

          package Bar;
          use base qw(Foo);
          use fields qw(salmon);

          # @fields contains 'that' and 'meme' since they are Public and
          # Inherited.  It doesn't contain 'salmon' since while it is
          # Public it is not Inherited.
          @fields = show_fields('Bar', qw(Private Inherited));

field_attrib_mask
          $attrib = field_attrib_mask($class, $field);
                or
          $attrib = $obj->field_attrib_mask($field);
                or
          $attrib = Class->field_attrib_mask($field);

     It will tell you the numeric attribute for the given $field in the
     given $class.  $attrib is a bitmask which must be interpreted with
     the PUBLIC, PRIVATE, etc... constants from Class::Fields::Attrib.

     field_attribs() is probably easier to work with in general.

field_attribs
          @attribs = field_attribs($class, $field);
                or
          @attribs = $obj->field_attribs($field);
                or
          @attribs = Class->field_attribs($field);

     Exactly the same as field_attrib_mask(), except that instead of
     returning a bitmask it returns a somewhat friendlier list of
     attributes which are applied to this field.  For example...

          package Foo;
          use fields qw( yarrow );

          package Bar;
          use base qw(Foo);

          # @attribs will contain 'Public' and 'Inherited'
          @attribs = field_attribs('Bar', 'yarrow');

     The attributes returned are the same as those taken by show_fields().

dump_all_attribs
          dump_all_attribs;
          dump_all_attribs(@classes);
                or
          Class->dump_all_attribs;
                or
          $obj->dump_all_attribs;

     A debugging tool which simply prints to STDERR everything it can about
     a given set of @classes in a relatively formated manner.

     Alas, this function works slightly differently if used as a function
     as opposed to a method:

     When called as a function it will print out attribute information
     about all @classes given.  If no @classes are given it will print out
     the attributes of -every- class it can find that has attributes.

     When uses as a method, it will print out attribute information for the
     class or object which uses the method.  No arguments are accepted.

     I'm not entirely happy about this split and I might change it in the
     future.

EXAMPLES
========

   Neat tricks that can be done with this module:

An integrity check for your object.
     Upon destruction, check to make sure no strange keys were added to
     your object hash.  This is a nice check against typos and other
     modules sticking their dirty little fingers where they shouldn't be
     if you're not using a pseudo-hash.

          sub DESTROY {
              my($self) = @_;
              my($class) = ref $self;

          my %fields = map { ($_,1) } $self->show_fields;
          foreach my $key ( keys %$self ) {
              warn "Strange key '$key' found in object '$self' ".
                    "of class '$class'" unless
                  exists $fields{$key};
          }
              }

Autoloaded accessors for public data members.
     Proper OO dogma tells you to do all public data access through
     accessors (methods who's sole purpose is to get and set data in your
     object).  This can be a royal pain in the ass to write and can also
     get rapidly unmaintainable since you wind up with a series of nearly
     identical methods.

     *Perfect* for an autoloader!

          package Test::Autoload::Example;
          use base qw(Class::Fields);
          use public qw(this that up down);
          use private qw(_left _right);

          sub AUTOLOAD {
              my $self = $_[0];
              my $class = ref $self;

          my($field) = $AUTOLOAD =~ /::([^:]+)$/;

          return if $field eq 'DESTROY';

          # If its a public field, set up a named closure as its
          # data accessor.
          if ( $self->is_public($field) ) {
              *{$class."::$field"} = sub {
                  my($self) = shift;
                  if (@_) {
                      $self->{$field} = shift;
                  }
                  return $self->{$field};
              };
              goto &{$class."::$field"};
          } else {
              die "'$field' is not a public data member of '$class'";
          }
              }

     `EXAMPLES', see Class/Accessor, for a much simpler
     version of this same technique.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com> with much code liberated from the
original fields.pm.

THANKS
======

   Thanks to Tels for his big feature request/bug report.

SEE ALSO
========

   See Fields, Public, Private,
Protected,

   Modules with similar effects...  See Tie/SecureHash,
Class/Contract,

Attribute constants for use with data members
*********************************************

NAME
====

     Class::Fields::Attribs - Attribute constants for use with data members

SYNOPSIS
========

     # Export the attribute constants
     use Class::Fields::Attribs;

DESCRIPTION
===========

   Simply exports a set of constants used for low level work on data
members.  Each constant is a bitmask used to represent the type of a data
member (as in Public, Private, etc...).

   The exported attributes are:

PUBLIC
PRIVATE
PROTECTED
INHERITED
     Each of these constants is a bitmask representing a possible setting
     of a field attribute.  They can be combined by using a bitwise OR and
     attributes can be checked for using a bitwise AND.  For example:

          # Indicate a piece of data which is both public and inherited.
          $attrib = PUBLIC | INHERITED;

          # Check to see if an attribute is protected.
          print "Protected" if $attrib & PROTECTED;

     It is rare that one has to use these constants and it is generally
     better to use the functions provided by Class::Fields.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Class/Fields,

Low level manipuation of object data members
********************************************

NAME
====

     Class::Fields::Fuxor - Low level manipuation of object data members

SYNOPSIS
========

     # As functions.
     use Class::Fields::Fuxor;
     add_fields($class, $attrib, @fields);
     add_field_set($class, \@fields, \@attribs);
     has_fields($class);
     $fields = get_fields($class);
     $fattr  = get_attr($class);

     # As methods.
     package Foo;
     use base qw( Class::Fields::Fuxor );

     Foo->add_fields($attrib, @fields);
     Foo->has_fields;
     $fields   = Foo->get_fields;
     $fattr    = Foo->get_attr;

DESCRIPTION
===========

   This is a module for low level manipuation of the %FIELDS hash and its
accompying %fields::attr hash without actually touching them.  Modules
like fields.pm, base.pm and public.pm make use of this module.

   %FIELDS and %fields::attr are currently used to store information about
the data members of classes.  Since the current data inheritance system,
built around pseudo-hashes, is considered a bit twitchy, it is wise to
encapsulate and rope it off in the expectation that it will be replaced
with something better.

   Typically one does not want to mess with this stuff and instead uses
fields.pm and friends or perhaps Class::Fields.

add_fields
          add_fields($class, $attrib, @fields);

     Adds a bunch of @fields to the given $class using the given $attrib.
     For example:

          # Add the public fields 'this' and 'that' to the class Foo.
          use Class::Fields::Attribs;
          add_fields('Foo', PUBLIC, qw(this that));

     $attrib is built from the constants in Class::Fields::Attribs

add_field_set
          add_field_set($class, \@fields, \@attribs);

     Functionally similar to add_fields(), excepting that it can add a
     group of fields with different attributes all at once.  This is
     necessary for the proper functioning of fields.pm.

     Each element in @fields matches up with one in @attribs.  Obviously,
     the two arrays must be the same size.

has_fields
          has_fields($class);

     A simple check to see if the given $class has a %FIELDS hash defined.
     A simple test like (defined %{"$class\::FIELDS"}) will sometimes
     produce typo warnings because it would create the hash if it was not
     present before.

get_attr
          $fattr = get_attr($class);

     Get's the field attribute array for the given $class.  This is roughly
     equivalent to $fields::attr{$class} but we put a nice wrapper around
     it for compatibility and readability.

     $fattr is an array reference containing the attributes of the fields
     in the given $class.  Each entry in $fattr corresponds to the position
     indicated by the $class's %FIELDS has.  For example:

          package Foo;
          use fields qw(this _that);

          $fattr = get_attr('Foo');

          # Get the attributes for '_that' in the class 'Foo'.
          $that_attribs = print $fattr->[$Foo::FIELDS->{_that}];

     When possible, one should avoid using this function since it exposes
     more implementation detail than I'd like.  Class::Fields should
     provide most of the functionality you'll need.

get_fields
          $fields = get_fields($class);

     Gets a reference to the %FIELDS hash for the given $class.  It will
     autogenerate a %FIELDS hash if one doesn't already exist.  If you
     don't want this behavior, be sure to check beforehand with
     has_fields().

     When possible, one should avoid using this function since it exposes
     more implementation detail than I'd like.  Class::Fields should
     provide most of the functionality you'll need.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com> based heavily on code liberated
from the original fields.pm and base.pm.

SEE ALSO
========

   See Fields, Base, Public,
Private, Protected, Class/Fields,
see Class/Fields/Attribs,

Inheritance of %FIELDS
**********************

NAME
====

   Class::Fields::Inherit - Inheritance of %FIELDS

SYNOPSIS
========

     use Class::Fields::Inherit;
     inherit_fields($derived_class, $base_class);

DESCRIPTION
===========

   A simple module to handle inheritance of the %FIELDS hash.  base.pm is
usually its only customer, though there's nothing stopping you from using
it.

inherit_fields
          inherit_fields($derived_class, $base_class);

     The $derived_class will inherit all of the $base_class's fields.  This
     is a good chunk of what happens when you use base.pm.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com> largely from code liberated from
fields.pm

SEE ALSO
========

   See Base, Class/Fields,

Generate Perl class hierarchies
*******************************

NAME
====

   Class::Generate - Generate Perl class hierarchies

SYNOPSIS
========

     use Class::Generate qw(class subclass delete_class);

     # Declare class Class_Name, with the following types of members:
     class
         Class_Name => [
             s => '$',			# scalar
     	 a => '@',			# array
     	 h => '%',			# hash
     	 c => 'Class',			# Class
     	 c_a => '@Class',		# array of Class
     	 c_h => '%Class',		# hash of Class
             '&m' => 'body',		# method
         ];

     # Allocate an instance of class_name, with members initialized to the
     # given values (pass arrays and hashes using references).
     $obj = Class_Name->new ( s => scalar,
     			  a => [ values ],
     			  h => { key1 => v1, ... },
     			  c => Class->new,
     			  c_a => [ Class->new, ... ],
     			  c_h => [ key1 => Class->new, ... ] );

     # Scalar type accessor:
      $obj->s($value);			# Assign $value to member s.
      $member_value = $obj->s;		# Access member's value.

     # (Class) Array type accessor:
      $obj->a([value1, value2, ...]);	# Assign whole array to member.
      $obj->a(2, $value);			# Assign $value to array member 2.
      $obj->add_a($value);			# Append $value to end of array.
      @a = $obj->a;				# Access whole array.
      $ary_member_value = $obj->a(2);	# Access array member 2.
      $s = $obj->a_size;			# Return size of array.
      $value = $obj->last_a;			# Return last element of array.

     # (Class) Hash type accessor:
      $obj->h({ k_1=>v1, ..., k_n=>v_n })	# Assign whole hash to member.
      $obj->h($key, $value);			# Assign $value to hash member $key.
      %hash = $obj->h;			# Access whole hash.
      $hash_member_value = $obj->h($key);	# Access hash member value $key.
      $obj->delete_h($key);			# Delete slot occupied by $key.
      @keys = $obj->h_keys;			# Access keys of member h.
      @values = $obj->h_values;		# Access values of member h.

     $another = $obj->copy;			# Copy an object.
     if ( $obj->equals($another) ) { ... }	# Test equality.

     subclass s  => [ <more members> ], -parent => 'class_name';

DESCRIPTION
===========

   The `Class::Generate' package exports functions that take as arguments
a class specification and create from these specifications a Perl 5 class.
The specification language allows many object-oriented constructs: typed
members, inheritance, private members, required members, default values,
object methods, class methods, class variables, and more.

   CPAN contains similar packages.  Why another?  Because object-oriented
programming, especially in a dynamic language like Perl, is a complicated
endeavor.  I wanted a package that would work very hard to catch the
errors you (well, I anyway) commonly make.  I wanted a package that could
help me enforce the contract of object-oriented programming.  I also
wanted it to get out of my way when I asked.

THE CLASS FUNCTION
==================

   You create classes by invoking the class function.  The class function
has two forms:

     class Class_Name => [ specification ];	# Objects are array-based.
     class Class_Name => { specification };	# Objects are hash-based.

   The result is a Perl 5 class, in a package `Class_Name'.  This package
must not exist when class is invoked.

   An array-based object is faster and smaller.  A hash-based object is
more flexible.  Subsequent sections explain where and why flexibility
matters.

   The specification consists of zero or more name/value pairs.  Each pair
declares one member of the class, with the given name, and with attributes
specified by the given value.

MEMBER TYPES
============

   In the simplest name/value form, the value you give is a string that
defines the member's type.  A `'$'' denotes a scalar member type.  A `'@''
denotes an array type.  A `'%'' denotes a hash type.  Thus:

     class Person => [ name => '$', age => '$' ];

   creates a class named `Person' with two scalar members, name and age.

   If the type is followed by an identifier, the identifier is assumed to
be a class name, and the member is restricted to a blessed reference of
the class (or one of its subclasses), an array whose elements are blessed
references of the class, or a hash whose keys are strings and whose values
are blessed references of the class.  For scalars, the `$' may be omitted;
i.e., `Class_Name' and `$Class_Name' are equivalent.  The class need not
be declared using the `Class::Generate' package.

CREATING INSTANCES
==================

   Each class that you generate has a constructor named new.  Invoking the
constructor creates an instance of the class.  You may provide new with
parameters to set the values of members:

     class Person => [ name => '$', age => '$' ];
     $p = Person->new;			# Neither name nor age is defined.
     $q = Person->new( name => 'Jim' );	# Only name is defined.
     $r = Person->new( age => 32 );	# Only age is defined.

ACCESSOR METHODS
================

   A class has a standard set of accessor methods for each member you
specify.  The accessor methods depend on a member's type.

Scalar (name => '$', name => 'Class_Name', or name => '$Class_Name')
--------------------------------------------------------------------

   The member is a scalar.  The member has a single method name.  If
called with no arguments, it returns the member's current value.  If
called with arguments, it sets the member to the first value:

     $p = Person->new;
     $p->age(32);		# Sets age member to 32.
     print $p->age;		# Prints 32.

   If the `Class_Name' form is used, the member must be a reference blessed
to the named class or to one of its subclasses.  If Perl's -w flag is
used, the method will croak (see Carp) if the argument is not
a blessed reference to an instance of `Class_Name' or one of its
subclasses.

     class Person => [
     	name => '$',
     	spouse => 'Person'	# Works, even though Person
     ];				# isn't yet defined.
     $p = Person->new(name => 'Simon Bar-Sinister');
     $q = Person->new(name => 'Polly Purebred');
     $r = Person->new(name => 'Underdog');
     $r->spouse($q);				# Underdog marries Polly.
     print $r->spouse->name;			# Prints 'Polly Purebred'.
     print "He's married" if defined $p->spouse;	# Prints nothing.
     $p->spouse('Natasha Fatale');		# Croaks.

Array (name => '@' or name => '@Class')
---------------------------------------

   The member is an array.  If the `@Class' form is used, all members of
the array must be a blessed reference to Class or one of its subclasses.
An array member has three associated methods:

name
     With no argument, name returns the member's whole array.

     With one argument, name's behavior depends on whether the argument is
     an array reference.  If it is not, then the argument must be an
     integer i, and name returns element i of the member.  If no such
     element exists, name returns undef.  If the argument is an array
     reference, it is cast into an array and assigned to the member.

     With two arguments, the first argument must be an integer i.  The
     second argument is assigned to element i of the member.

`add_name'
     This method appends its arguments to the member's array.

`name_size'
     This method returns the index of the last element in the array.

`last_name'
     This method returns the last element of name, or undef if name has no
     elements.  It's a shorthand for `$o->array_mem($o->array_mem_size)'.

   For example:

     class Person => [ name => '$', kids => '@Person' ];
     $p = Person->new;
     $p->add_kids(Person->new(name => 'Heckle'),
     		 Person->new(name => 'Jeckle'));
     print $p->kids_size;	# Prints 1.
     $p->kids([Person->new(name => 'Bugs Bunny'),
     	      Person->new(name => 'Daffy Duck')]);
     $p->add_kids(Person->new(name => 'Yosemite Sam'),
     		 Person->new(name => 'Porky Pig'));
     print $p->kids_size;	# Prints 3.
     $p->kids(2, Person->new(name => 'Elmer Fudd'));
     print $p->kids(2)->name;	# Prints 'Elmer Fudd'.
     @kids = $p->kids;		# Get all the kids.
     print $p->kids($p->kids_size)->name; # Prints 'Porky Pig'.
     print $p->last_kids->name;	   # So does this.

Hash (name => '%' or name => '%Class')
--------------------------------------

   The member is a hash.  If the `%Class' form is used, all values in the
hash must be a blessed reference to Class or one of its subclasses.  A
hash member has three associated methods:

name
     With no arguments, name returns the member's whole hash.

     With one argument that is a hash reference, the member's value
     becomes the argument.  With one argument that is a string, the
     element of the hash keyed by that string is returned.  If no such
     element exists, name returns undef.

     With two arguments, the second argument is assigned to the hash,
     keyed by the string representation of the first argument.

`name_keys'
     The `name_keys' method returns all keys associated with the member.

`name_values'
     The `name_values' method returns all values associated with the
     member.

`delete_name'
     The `delete_name' method takes one or more arguments.  It deletes
     from name's hash all elements matching the arguments.

   For example:

     class Person => [ name => '$', kids => '%Kid_Info' ];
     class Kid_Info => [
     	grade  => '$',
     	skills => '@'
     ];
     $f = new Person(
     	name => 'Fred Flintstone',
     	kids => { Pebbles => new Kid_Info(grade => 1,
     				          skills => ['Programs VCR']) }
     );
     print $f->kids('Pebbles')->grade;	# Prints 1.
     $b = new Kid_Info;
     $b->grade('Kindergarten');
     $b->skills(['Knows Perl', 'Phreaks']);
     $f->kids('BamBam', $b);
     print join ', ', $f->kids_keys;	# Prints "Pebbles, BamBam",
     					# though maybe not in that order.

COMMON METHODS
==============

   All members also have a method `undef_m'.  This method undefines a
member m.

OBJECT INSTANCE METHODS
=======================

   There are also methods that you can invoke on an object instance.
These are as follows:

Copy
----

   Use the copy method to copy the value of an object.  The expression:

     $p = $o->copy;

   assigns to $p a copy of $o.  Members of $o that are classes (or arrays
or hashes of classes) are copied using their own copy method.

Equals
------

   Use the equals method to test the equality of two object instances:

     if ( $o1->equals($o2) ) { ... }

   The two object instances are equal if members that have values in `$o1'
have equal values in `$o2', and vice versa.  Equality is tested as you
would expect: two scalar members are equal if they have the same value;
two array members are equal if they have the same elements; two hash
members are equal if they have the same key/value pairs.

   If a member's value is restricted to a class, then equality is tested
using that class' equals method.  Otherwise, it is tested using the eq
operator.

   By default, all members participate in the equality test.  If one or
more members possess true values for the key attribute, then only those
members participate in the equality test.

   You can override this definition of equality.  See `ADDING METHODS' in
this node.

ADVANCED MEMBER SPECIFICATIONS
==============================

   As shown, you specify each member as a `name=>value' pair.  If the
value is a string, it specifies the member's type.  The value may also be
a hash reference.  You use hash references to specify additional member
attributes.  The following is a complete list of the attributes you may
specify for a member:

type=>string
     If you use a hash reference for a member's value, you must use the
     type attribute to specify its type:

          scalar_member => { type => '$' }

required=>boolean
     If the required attribute is true, the member must be passed each
     time the class' constructor is invoked:

          class Person => [ name => { type => '$', required => 1 } ];
          Person->new ( name => 'Wilma' );	# Valid
          Person->new;			# Invalid

     Also, you may not call `undef_name' for the member.

default=>value
     The default attribute provides a default value for a member if none
     is passed to the constructor:

          class Person => [ name => '$',
          		      job => { type => '$',
          			       default => "'Perl programmer'" } ];
          $p = Person->new(name => 'Larry');
          print $p->job;		# Prints 'Perl programmer'.
          $q = Person->new(name => 'Bjourne', job => 'C++ programmer');
          print $q->job;		# Unprintable.

     The value is treated as a string that is evaluated when the
     constructor is invoked.

     For array members, use a string that looks like a Perl expression
     that evaluates to an array reference:

          class Person => {
          	name => '$',
          	lucky_numbers => { type => '@', default => '[42, 17]' }
          };
          class Silly => {
          	UIDs => {		# Default value is all UIDs
          	    type => '@',	# currently in /etc/passwd.
          	    default => 'do {
          		local $/ = undef;
          		open PASSWD, "/etc/passwd";
          		[ map {(split(/:/))[2]} split /\n/, <PASSWD> ]
          	    }'
          	}
          };

     Specify hash members analogously.

     The value is evaluated each time the constructor is invoked.  In
     `Silly', the default value for `UIDs' can change between invocations.
     If the default value is a reference rather than a string, it is not
     re-evaluated.  In the following, default values for `e1' and `e2' are
     based on the members of `@default_value' each time `Example->new' is
     invoked, whereas `e3''s default value is set when the class function
     is invoked to define Example:

          @default_value = (1, 2, 3);
          $var_name = '@' . __PACKAGE__ . '::default_value';
          class Example => {
              e1 => { type => '@', default => "[$var_name]" },
          	e2 => { type => '@', default => \@default_value },
          	e3 => { type => '@', default => [ @default_value ] }
          };
          Example->new;	# e1, e2, and e3 are all identical.
          @default_value = (10, 20, 30);
          Example->new;	# Now only e3 is (1, 2, 3).

     There are two more things to know about default values that are
     strings.  First, if a member is typed, the class function evaluates
     its (string-based) default value to ensure that it is of the correct
     type for the member.  Be aware of this if your default value has side
     effects (and see `Checking Default Value Types' in this node).

     Second, the context of the default value is the new() method of the
     package generated to implement your class.  That's why `e1' in
     Example, above, needs the name of the current package in its default
     value.

post=>code
     The value of this attribute is a string of Perl code.  It is executed
     immediately after the member's value is modified through its accessor.
     Within post code, you can refer to members as if they were Perl
     identifiers.  For instance:

          class Person => [ age => { type => '$',
          			       post => '$age *= 2;' } ];
          $p = Person->new(age => 30);
          print $p->age;	# Prints 30.
          $p->age(15);
          print $p->age;	# Prints 30 again.

     The trailing semicolon used to be required, but everyone forgot it.
     As of version 1.06 it's optional: `'$age*=2'' is accepted and
     equivalent to `'$age*=2;'' (but see `"BUGS"' in this node).

     You reference array and hash members as usual (except for testing for
     definition; see `"BUGS"' in this node).  You can reference individual
     elements, or the whole list:

          class Foo => [
          	m1 => { type => '@', post => '$m1[$#m1/2] = $m2{xxx};' },
          	m2 => { type => '%', post => '@m1 = keys %m2;' }
          ];

     You can also invoke accessors.  Prefix them with a &:

          class Bar => [
          	m1 => { type => '@', post => '&undef_m1;' },
          	m2 => { type => '%', post => '@m1 = &m2_keys;' }
          ];
          $o = new Bar;
          $o->m1([1, 2, 3]);		# m1 is still undefined.
          $o->m2({a => 1, b => 2});	# Now m1 is qw(a b).

pre=>code
     The pre key is similar to the post key, but it is executed just
     before an member is changed.  It is not executed if the member is
     only accessed.  The pre and post code have the same scope, which lets
     you share variables.  For instance:

          class Foo => [
          	mem => { type => '$', pre => 'my $v = $mem;', post => 'return $v;' }
          ];
          $o = new Foo;
          $p = $o->mem(1);	# Sets $p to undef.
          $q = $o->mem(2);	# Sets $q to 1.

     is a way to return the previous value of `mem' any time it's modified
     (but see `"NOTES"' in this node).

assert=>expression
     The value of this key should be a Perl expression that evaluates to
     true or false.  Use member names in the expression, as with post.
     The expression will be tested any time the member is modified through
     its accessors.  Your code will croak if the expression evaluates to
     false.  For instance,

          class Person => [
          	name => '$',
          	age => { type => '$',
          		 assert => '$age =~ /^\d+$/ && $age < 200' } ];

     ensures the age is reasonable.

     The assertion is executed after any post code associated with the
     member.

private=>boolean
     If the private attribute is true, the member cannot be accessed
     outside the class; that is, it has no accessor functions that can be
     called outside the scope of the package defined by class.  A private
     member can, however, be accessed in post, pre, and assert code of
     other members of the class.

protected=>boolean
     If the `protected' attribute is true, the member cannot be accessed
     outside the class or any of its subclasses.  A protected member can,
     however, be accessed in post, pre, and assert code of other members
     of the class or its subclasses.

readonly=>boolean
     If this attribute is true, then the member cannot be modified through
     its accessors.  Users can set the member only by using the class
     constructor.  The member's accessor that is its name can retrieve but
     not set the member.  The `undef_'name accessor is not defined for the
     member, nor are other accessors that might modify the member.  (Code
     in post can set it, however.)

key=>boolean
     If this attribute is true, then the member participates in equality
     tests.  See `"Equals"' in this node.

nocopy=>value
     The `nocopy' attribute gives you some per-member control over how the
     copy method.  If `nocopy' is false (the default), the original's
     value is copied as described in `"Copy"' in this node.  If `nocopy'
     is true, the original's value is assigned rather than copied; in
     other words, the copy and the original will have the same value if
     the original's value is a reference.

AFFECTING THE CONSTRUCTOR
=========================

   You may include a new attribute in the specification to affect the
constructor.  Its value must be a hash reference.  Its attributes are:

required=>list of constraints
     This is another (and more general) way to require that parameters be
     passed to the constructor.  Its value is a reference to an array of
     constraints.  Each constraint is a string that must be an expression
     composed of Perl logical operators and member names.  For example:

          class Person => {
          	name   => '$',
              age    => '$',
          	height => '$',
          	weight => '$',
          	new => { required => ['name', 'height^weight'] }
          };

     requires member name, and exactly one of height or weight.  Note that
     the names are not prefixed with `$', `@', or %.

     Specifying a list of constraints as an array reference can be clunky.
     The class function also lets you specify the list as a string, with
     individual constraints separated by spaces.  The following two
     strings are equivalent to the above required attribute:

          'name height^weight'
          'name&(height^weight)'

     However, `'name & (height ^ weight)'' would not work.  The class
     function interprets it as a five-member list, four members of which
     are not valid expressions.

     This equivalence between a reference to array of strings and a string
     of space-separated items is used throughout `Class::Generate'.  Use
     whichever form works best for you.

post=>string of code
     The post key is similar to the post key for members.  Its value is
     code that is inserted into the constructor after parameter values
     have been assigned to members.  The class function performs variable
     substitution.

     The pre key is not recognized in new.

assert=>expression
     The assert key's value is inserted just after the post key's value
     (if any).  Assertions for members are inserted after the
     constructor's assertion.

comment=>string
     This attribute's value can be any string.  If you save the class to a
     file (see `Saving the Classes' in this node), the string is included
     as a comment just before the member's methods.

style=>style definition
     The style attribute controls how parameters are passed to the class'
     constructor.  See `PARAMETER PASSING STYLES' in this node.

ADDING METHODS
==============

   Accessors often do not provide a class with enough functionality.  They
also do not encapsulate your algorithms.  For these reasons, the class
function lets you add methods.  Both object methods and class methods are
allowed.

   Add methods using an member of the form `'&name'=>body', where body is
a string containing valid Perl code.  This yields a method name with the
specified body.  For object methods, the class function performs variable
substitution as described in `ADVANCED MEMBER SPECIFICATIONS' in this node.
For example,

     class Person => [ first_name => '$',
     		      last_name  => '$',
     		      '&name'    => q{return "$first_name $last_name";}
     ];
     $p = Person->new(first_name => 'Barney', last_name => 'Rubble');
     print $p->name;	# Prints "Barney Rubble".

     class Stack => [	# Venerable example.
     	top_e	 => { type => '$', private => 1, default => -1 },
     	elements => { type => '@', private => 1, default => '[]' },
     	'&push' => '$elements[++$top_e] = $_[0];',
     	'&pop'  => '$top_e--;',
     	'&top'  => 'return $elements[$top_e];'
     ];

   A method has the following attributes which, like members, are
specified as a hash reference:

body=>code
     This attribute specifies the method's body.  It is required if other
     attributes are given.

private=>boolean
     The method cannot be accessed outside the class.

          class Example => [
          	m1 => '$',
          	m2 => '$',
          	'&public_interface' => q{return &internal_algorithm;},
          	'&internal_algorithm' => { private => 1,
          				   body => q{return $m1 + 4*$m2;} }
          ];
          $e = Example->new(m1 => 2, m2 => 4);
          print $e->public_interface;		# Prints 18.
          print $e->internal_algorithm;	# Run-time error.

protected=>boolean
     If true, the method cannot be accessed outside the class or any of
     its subclasses.

class_method=>boolean
     If true, the method applies to classes rather than objects.  Member
     name substitution is not performed within a class method.  You can,
     however, use accessors, as usual:

          class Foo => [
          	m1 => '$', m2 => '@',
          	'&to_string' => {
          	    class_method => 1,
          	    body => 'my $o = $_[0];
          		     return $o->m1 . "[" . join(",", $o->m2) . "]"';
          	}
          ];
          $f = Foo->new(m1 => 1, m2 => [2, 3]);
          print Foo->to_string($f);	# Prints "1[2,3]"

     You can also call class methods from within instance and class
     methods.  Use the `Class->method' syntax.

     Currently, a class method may be public or private, but not protected.

objects=>list of object instance expressions
     This attribute is only used for class methods.  It is needed when the
     method refers to a private or protected member or method.  Its
     argument is a list, each element of which is a Perl expression that
     occurs in the body of the class method.  The expression must evaluate
     to an instance of the class.  It will be replaced by an appropriate
     reference to the private member or method.  For example:

          class Bar => [
          	mem1 => '$',
          	mem2 => { type => '@', private => 1 },
          	'&meth1' => 'return $mem1 + $#mem2;',
          	'&meth2' => { private => 1,
          		      body    => 'return eval join "+", @mem2;' },
          	'&cm1' => { class_method => 1,
          		    objects => '$o',
          		    body => 'my $o = Bar->new(m1 => 8);
          			     $o->mem2([4, 5, 6]);
          			     return $o->meth2;' },
          	'&cm2' => { class_method => 1,
          		    objects => ['$o', 'Bar->new(m1 => 3)'],
          		    body => 'my $o => Bar->new(m1 => 8);
          			     $o->mem2(0, Bar->new(m1 => 3)->meth2);
          			     return $o;' }
          ];

     The `objects' attribute for `cm1' tells class to treat all
     occurrences of the string $o as an instance of class `Bar', giving
     the expression access to private members and methods of `Bar'.  The
     string can be an arbitrary expression, as long as it's valid Perl and
     evaluates to an instance of the class; hence the use of `Bar->new(m1
     => 3)' in `cm2'.  The string must match exactly, so `Bar->new(m1 =>
     8)' is not replaced.

   You can add a method named `&equals' to provide your own definition of
equality.  An example:

     $epsilon = 0.1e-20;
     class Imaginary_No => {			# Treat floating-point
     	real => '$',				# values as equal if their
     	imag => '$',				# difference is less than
     	'&equals' => qq|my \$o = \$_[0];	# some epsilon.
     		        return abs(\$real - \$o->real) < $epsilon &&
     			       abs(\$imag - \$o->imag) < $epsilon;|
     };

   If you declare `&equals' to be private, you create a class whose
instances cannot be tested for equality except within the class.

THE SUBCLASS FUNCTION
=====================

   The `subclass()' function declares classes that are subclasses of
another class.  The statement:

     subclass S => [ specification ], -parent => P

   declares a package s, and a constructor function new, just like class;
but `s->new' yields a blessed reference that inherits from P.  You can use
all the attributes discussed above in the specification of a subclass.
(Prior to version 1.02 you specified the parent using `parent=>P', but
this is deprecated in favor of `-parent=>P'.)

   As of version 1.05, the class function also accepts `-parent'.  In
other words,

     class S => [ specification ], -parent => P
     subclass S => [ specification ], -parent => P

   are equivalent.

   Class P need not have been defined using the class or `subclass'
function.  It must have a constructor named new, however, or at least be
an ancestor of a class that does.

   A subclass may be either an array or hash reference.  Its parent must
be the same type of reference.

   You can inherit from multiple classes, providing all are hash-based
(`Class::Generate' does not support multiple inheritance for array-based
classes).  Just list more than one class as the value of parent:

     subclass S => { specification }, -parent => 'P1 P2 P3';

   Elements of the `@ISA' array for package S appear in the order you list
them.  This guarantee should let you determine the order in which methods
are invoked.

   The subclass constructor automatically calls its parent constructor.
It passes to the parent constructor any parameters that aren't members of
the subclass.

   Subclass members with the same name as that of their parent override
their parent methods.

   You can access a (non-private) member or method of a parent within
user-defined code in the same way you access members or methods of the
class:

     class Person => [
     	name => '$',
     	age => '$',
     	'&report' => q{return "$name is $age years old"}
     ];
     subclass Employee => [
     	job_title => '$',
     	'&report' => q{return "$name is $age years old and is a $job_title";}
     ], -parent => 'Person';
     subclass Manager => [
     	workers => '@Employee',
     	'&report' => q{return "$name is $age years old, is a $job_title, " .
     			      "and manages " . (&workers_size + 1) . " people";}
     ], -parent => 'Employee';

   If a class has multiple parents, and these parents have members whose
names conflict, the name used is determined by a depth-first search of the
parents.

   The previous example shows that a subclass may declare a member or
method whose name is already declared in one of its ancestors.  The
subclass declaration overrides any ancestor declarations: the report
method behaves differently depending on the class of the instance that
invokes it.

   Sometimes you override an ancestor's method to add some extra
functionality.  In that situation, you want the overriding method to
invoke the ancestor's method.  All user-defined code in `Class::Generate'
has access to a variable `$self', which is a blessed reference.  You
therefore can use Perl's `SUPER::' construct to get at ancestor methods:

     class Person => [
     	name => '$',
     	age => '$',
     	'&report' => q{return &name . ": $age years old"}
     ];
     subclass Employee => [
     	job_title => '$',
     	'&report' => q{return $self->SUPER::report . "; job: $job_title";}
     ], -parent => 'Person';
     subclass Manager => [
     	workers => '@Employee',
     	'&report' => q{return $self->SUPER::report . "; manages: " .
     			      (&workers_size + 1) . " people";}
     ], -parent => 'Employee';

   Currently, you cannot access a protected method of an ancestor this way.
The following code will generate a run-time error:

     class Foo => [
     	'&method' => { protected => 1, body => '...' },
     ];
     subclass Bar => [
     	'&method' => { protected => 1, body => '$self->SUPER::method;' }
     ], -parent => 'Foo';

THE DELETE_CLASS FUNCTION
=========================

   You can delete classes you declare using `Class::Generate', after which
you can declare another class with the same name.  Use the `delete_class'
function, which accepts as arguments one or more class names:

     class Person => [ name => '$' ];
     delete_class 'Person';			 # Nah...
     class Name => [ last => '$', first => '$' ]; # ... let's really encapsulate.
     class Person => [ name = 'Name' ];		 # That's better.

   This function silently ignores classes that don't exist, but it croaks
if you try to delete a package that wasn't declared using
`Class::Generate'.

FLAGS
=====

   You can affect the specification of a class using certain flags.  A
flag is a key/value pair passed as an argument to class (or `subclass').
The first character of the key is always a hyphen.  The following is a
list of recognized flags:

-use=>list
     Your pre or post code, or your methods, may want to use functions
     declared in other packages.  List these packages as the value of the
     `-use' flag.  For example, suppose you are creating a class that does
     date handling, and you want to use functions in the Time::Local and
     Time::localtime packages.  Write the class as follows:

          class Date_User => [ ... ],
          	-use => 'Time::Local Time::localtime';

     Any code you add to `Date_User' can now access the time functions
     declared in these two packages.

     To import functions, you need to use the array reference form:

          class Foo => [ ... ],
          	-use => ["FileHandle 'autoflush'"];

     Otherwise, the class function would assume you want to use two
     packages, Filehandle and `'autoflush''.

     Package Carp is automatically used if $WARNING is true.

-class_vars=>list
     A class can have class variables, i.e., variables accessible to all
     instances of the class as well as to class methods.  Specify class
     variables using the `-class_vars' flag.  For example, suppose you
     want the average age of all Persons:

          $compute_average_age = '$n++; $total += $age; $average = $total/$n;';
          class Person => [
          	name => '$',
          	age  => { type => '$', required => 1, readonly => 1 },
          	new  => { post => $compute_average_age }
          ],
              -class_vars => '$n $total $average';
          $p = Person->new(age => 24);		# Average age is now 24.
          $q = Person->new(age => 30);		# Average age is now 27.

     You can also provide an initial value for class variables.  Specify
     the value of `-class_vars' as an array reference.  If any member of
     this array is a hash reference, its members are taken to be variable
     name/initial value pairs.  For example:

          class Person => [ name => '$',
          		      age => { type => '$', required => 1, readonly => 1 },
          		      new => { post => $compute_average_age }
          ],
          	  -class_vars => [ { '$n' => 0 },
          			   { '$total' => 0 },
          			   '$average' ];

-virtual=>boolean
     A virtual class is a class that cannot be instantiated, although its
     descendents can.  Virtual classes are useful as modeling aids and
     debugging tools.  Specify them using the `-virtual' flag:

          class Parent =>   [ e => '$' ], -virtual => 1;
          subclass Child => [ d => '$' ], -parent => 'Parent';
          Child->new;		# This is okay.
          Parent->new;	# This croaks.

     There is no built-in way to specify a virtual method, but the
     following achieves the desired effect:

          class Foo => [ '&m' => 'die "m is a virtual method";' ];

-comment=>string
     The string serves as a comment for the class.

-options=>{ options }
     This flag lets you specify options that alter your class' behavior.
     See `"OPTIONS"' in this node.

-exclude=>string
     Sometimes it isn't appropriate for a user to be able to copy an
     object.  And sometimes testing the equality of two object instances
     makes no sense.  For these and other situations, you have some
     control over the automatically generated methods for each class.

     You control method generation using the `-exclude' flag.  Its value
     is a string of space-separated regular expressions.  A method is
     included if it does not match any of the regular expressions.  For
     example, a person has a unique social security number, so you might
     want a class where a person can't be copied:

          class Person => [
          	name => '$',
          	ssn  => { type => '$', readonly => 1 }
          ], -exclude => '^copy$';
          $o = Person->new name => 'Forrest Gump', ssn => '000-00-0000';
          $p = $o->copy;	# Run-time error.

     The `-exclude' flag can describe a whole range of esoteric
     restrictions:

          class More_Examples => [
          	mem1 => { type => '$', required => 1 },
          	mem2 => { type => '@', required => 1 },
          	mem3 => '%',
          	new => { post => '%mem3 = map { $_ => $mem1 } @mem2' }
          ], -exclude => 'undef_ mem2_size mem3';
          $o = More_Examples->new mem1 => 1, mem2 => [2, 3, 4];
          @keys = $o->mem3_keys;	# Run-time error.
          $o->undef_mem1;		# Ditto.
          print $o->last_mem2;	# This works as expected.
          print $o->mem2_size;	# But this blows up.

     In `More_Examples', it isn't possible to undefine a member.  The size
     of `mem2' can't be determined.  And `mem3' is effectively private (it
     can't even be accessed from class methods).

PARAMETER PASSING STYLES
========================

   By default, parameters to the constructor are passed using a
`name=>value' form.  You have some control over this using the style key
in a constructor's new specifier.  It lets you pass parameters to
constructors using one of the following styles:

Key/Value
     This is the default.  Parameters are passed using the `name=>value'
     form, as shown in previous examples.  Specify it as
     `style=>'key_value'' if you want to be explicit.

Positional
     Parameters are passed based on a positional order you specify.  For
     example:

          class Foo => [ e1 => '$', e2 => '@', e3 => '%',
          	           new => { style => 'positional e1 e2 e3' } ];
          $obj = Foo->new(1);			# Sets e1 to 1.
          $obj = Foo->new(1, [2,3]);		# Ditto, and sets e2 to (2,3).
          my %hash = (foo => 'bar');
          $obj = Foo->new(1,			# Ditto,
          		    [2, 3],		# ditto,
          		    {%hash});		# and sets e3 to %hash.

     You must list all non-private members, although you do not have to
     include all of them in every invocation of new.  Also, if you want to
     set `e1' and `e3' but not `e2', you can give undef as `e2''s value:

          $obj = Foo->new(1, undef, { e3_value => 'see what I mean?' });

Mixed Styles
     Parameters are passed mixing the positional and key/value styles.
     The values following mix are the names of the positional parameters,
     in the order in which they will be passed.  This style is useful when
     certain parameters are "obvious".  For example:

          class Person => [
          	first_name => { type => '$', required => 1 },
          	last_name  => { type => '$', required => 1 },
          	favorite_language => '$',
          	favorite_os	  => '$',
          	new => { style => 'mix first_name last_name' }
          ];
          $obj = Person->new('Joe',  'Programmer', favorite_language => 'Perl');
          $obj = Person->new('Sally', 'Codesmith', favorite_os       => 'Linux');

     The positional parameters need not be required, but they must all be
     given if you want to set any members passed as key/value parameters.

Your Own Parameter Handling
     Finally, sometimes you want a constructor whose parameters aren't the
     members.  Specify such classes using `own'.  Access the parameters
     through `@_', as usual in Perl:

          class Person => [
          	first => { type => '$', private => 1 },
          	last  => { type => '$', private => 1 },
          	new   => { style => 'own',
          		   post => '($first, $last) = split /\s+/, $_[0];' },
          	'&name' => q|return $last . ', ' . $first;|
          ];
          $p = Person->new('Fred Flintstone');
          print $p->name;			# Prints 'Flintstone, Fred'.

     If `own' is followed by a space, and the class has a parent,
     everything after the space is treated as a space-separated list of
     Perl expressions.  The expressions are passed to the superclass
     constructor in the order given.  Thus:

          subclass Child => [
          	grade => '$',
          	new   => { style => 'own $_[0]', post => '$grade = $_[1];' }
          ], -parent => 'Person';

     Now you can create a Child by passing the grade as the second
     parameter, and the name as the first:

          $c = Child->new('Penny Robinson', 5);

   If you use styles other than `key_value', you must be aware of how a
subclass constructor passes parameter to its superclass constructor.
`Class::Generate' has some understanding of styles, but not all
combinations make sense, and for those that do, you have to follow certain
conventions.  Here are the rules for a subclass S with parent P:

  1. If S's constructor uses the `key_value' style, P's constructor must
     use the `key_value' or `own' style.  The parameters are treated as a
     hash; P's constructor receives a hash with all elements indexed by
     nonprivate members of S deleted.  P's constructor must not expect the
     hash elements to be passed in a prespecified order.

  2. If S's constructor uses the `positional' style, P's constructor may
     use any style.  If S has n nonprivate members, then parameters 0..n-1
     are used to assign members of S.  Remaining parameters are passed to
     `P::new', in the same order they were passed to `S::new'.

  3. If S's constructor uses the mix style, P's constructor may use any
     style.  If S has n nonprivate members, of which p are passed by
     position, then parameters 0..(p-1)+2*(n-p) are used to assign members
     of S.  Remaining parameters are passed to `P::new', in the same order
     they were passed to `S::new'.

  4. If S's constructor uses the `own' style, you are responsible for
     ensuring that it passes parameters to P's constructor in the correct
     style.

OPTIONS
=======

   The `Class::Generate' package provides what its author believes is
reasonable default style and behavior.  But if you disagree, there are
certain defaults you can control on a class-by-class basis, or for all
classes you generate.  These defaults are specified as options.  An option
is given in one of two ways:

  1. Via the `-options' flag, the value of which is a hash reference
     containing the individual options.  This affects an individual class.

  2. By setting a variable declared in `Class::Generate'.  The variable
     has the same name as the option.  This affects all subsequently
     generated classes except those where the option is explicitly
     overridden via the `-options' flag.  You may export these variables,
     although they are not exported by default.

        The following sections list the options that class and `subclass'
recognize.

Saving the Classes
------------------

   If the save option is true for class c, the code implementing it will
be saved to file `c.pm'.  This is useful in several situations:

  1. You may need functionality that class and `subclass' cannot provide.

  2. Errors in your methods, or in pre and post code, can result in
     obscure diagnostics.  Debugging classes is easier if they are saved
     in files.  This is especially true if you use Emacs for debugging, as
     Emacs does not handle evaluated expressions very well.

  3. If you have many classes, there is overhead in regenerating them each
     time you execute your program.  Accessing them in files may be faster.

        If the value of save looks like a Perl file name (i.e., if it ends
in `.pl' or `.pm'), the class is appended to that file.  This feature lets
your program avoid the overhead of opening and closing multiple files.  It
also saves you from the burden of maintaining multiple files.

   All comments specified using comment attributes and the `-comment' flag
are saved along with your code.

Passing References
------------------

   Sometimes you want to be able to assign a whole array to an array member
(or a whole hash to a hash member):

     class Person => [
     	name	=> '$',
     	parents => '@Person',
     	new	=> { style => 'positional name parents' }
     ];
     $p = Person->new('Will Robinson');
     $p->parents( [ Person->new('John Robinson'),
     		   Person->new('Maureen Robinson') ] );

   But sometimes you don't.  Often you only have one member value
available at any time, and you only want to add values:

     class Person => [
     	name	=> '$',
     	parents => '@Person',
     	new	=> { style => 'positional name parents' }
     ],
     	-options => { accept_refs => 0 };
     $p = Person->new('Will Robinson');
     $p->add_parents( Person->new('Maureen Robinson'),
     		     Person->new('John Robinson') );

   Passing references is a matter of taste and situation.  If you don't
think you will need or want to do it, set the `accept_refs' option to
false.  An added benefit is that the classes will catch more
parameter-passing errors, because with references there are two meanings
for passing a single parameter to the method.

Strictness
----------

   By default, the classes include a `use strict' directive.  You can
change this (if you must) using a false value for the strict option.

Redefining an Existing Package
------------------------------

   `Class::Generate' is intended for generating classes, not packages
containing classes.  For that reason, class and `subclass' croak if you
try to define a class whose name is a package that already exists.
Setting the `allow_redefine' option to true changes this behavior.  It
also opens up a minefield of potential errors, so be careful.

Instance Variable Name
----------------------

   By default, the reference to an object instance is stored in a variable
named `$self'.  If you prefer another name (e.g., `$this'), you can
specify it using the `instance_var' option:

     class Foo => {
     	array => '@'
     };
     subclass Bar => {
     	bar_mem => {
     	    type => '$',
     	    pre => 'print "array_size is ", $this->array_size;'
     	}
     }, -parent => 'Foo',
        -options => { instance_var => 'this' };

Class Variable Name
-------------------

   By default, the reference to a class variable is stored in a variable
named $class.  If you prefer another name, you can specify it using the
`class_var' option.

Checking User-Defined Code
--------------------------

   The class and `subclass' functions check that any pre, post, or assert
code is valid Perl.  They do so by creating and evaluating a subroutine
that contains the code, along with declarations that mimic the context in
which the code would execute.  The alternative would be to wait until the
entire class has been defined, but that would yield error messages with
line numbers that don't correspond to your code.  Never underestimate the
value of meaningful error messages.

   However, this approach results in code being evaluated twice: once to
check its syntax and semantics, and again when the package is created.  To
avoid this overhead, set the `check_code' option to false.

Checking Default Value Types
----------------------------

   A default value for a member is checked against the type of the member.
If a member is an array, for instance, you will get a warning if class
detects that its default value is anything other than an array reference.

   If you specify a default value as a string, class and `subclass' have
to evaluate the string to see if it yields a value of the correct type.
This may cause unwanted behavior if the string is an expression with side
effects.  Furthermore, your program will behave differently depending on
whether warnings are in effect (see `SANITY CHECKING' in this node).

   If you set the `check_default' option to false, class and `subclass'
will not check the types of default values.  It's common to do so after
you have debugged a class.

Creating New Objects From Instances
-----------------------------------

   By default, `Class::Generate' lets you create a new object instance only
from a class name, i.e., `Class->new'.  However, some Perl programmers
prefer another style, wherein you can create an object from either a class
or an instance (see Perlobj (perl.info)).  The `nfi' (new
from instance) option controls whether you can use both:

     class C => { ... };
     $o = C->new;	# Always works.
     $p = $o->new;	# Works if nfi option is true.

SANITY CHECKING
===============

   Several sections have mentioned errors that will cause your program to
croak.  Actually this only happens if you use Perl's -w flag.  Once your
classes are *fully* debugged, you may want to stop using -w for the sake
of efficiency.  But go slow on that.  Remember, you can still make
mistakes in code that invokes a class.

   Assertions are included only if the -w flag is used.

DIAGNOSTICS
===========

   The following is a list of the diagnostics the class and `subclass'
functions can produce.  Each diagnostic is prefixed with "(F)" or "(W)",
indicating that it is fatal or a warning, respectively.  Warning messages
are only emitted if you use Perl's -w flag.

   Classes that contain user defined code can yield Perl errors and
warnings.  These messages are prefixed by one of the following phrases:

     Class_Name: Member "name": In "<x>" code:
     Class_Name: Method "name":

   where `<x>' is one of pre, post, or assert.  See Perldiag (perl.info),
for an explanation of such messages.  The message
will include a line number that is relative to the lines in the erroneous
code fragment, as well as the line number on which the class begins.  For
instance, suppose the file `stacks.pl' contains the following code:

     #! /usr/local/bin/perl -w
     use Class::Generate 'class';
     class Stack => [
     	top_e	 => { type => '$', private => 1, default => -1 },
     	elements => { type => '@', private => 1, default => '[]' },
     	'&push' => '$elements[++$top_e] = $_[0];',
     	'&pop'  => '$top_e--;',
     	'&top'  => 'return $elements[$top_e];'
     ];
     class Integer_Stack => [
     	'&push' => q{die 'Not an integer' if $_[0] !~ /^-?\d+$/;
     		     $self->SUPER:push($_[0]);}	# Meant "::", not ":".
     ], -parent => 'Stack';

   Executing this file yields:

     Subclass "Integer_Stack", method "push": syntax error at line 2,
      near "->SUPER:"
      at stacks.pl line 10

   meaning the error occurs in the second line of the push method.

Compile-Time Diagnostics
------------------------

   The class and `subclass' functions emit the following diagnostics:

"-class_vars" flag must be string or array reference
     (F) The value of the `-class_vars' flag must be a string containing a
     space-separated list of class variables, or a reference to an array
     of strings, each of which specifies one or more class variables.

"-exclude" flag must be string or array reference
     (F) The value of the `-exclude' flag must be a string containing a
     space-separated list of regular expressions, or a reference to an
     array of strings, each of which specifies one or more regular
     expressions.

"-use" flag must be string or array reference
     (F) The value of the `-use' flag must be a string containing a
     space-separated list of packages to use, or a reference to an array
     of strings, each of which is a package to use.

%s: "%s" is reserved
     (F) The member name conflicts with the instance variable name for the
     class.  Change the member name, or change the instance variable name
     using the `instance_var' option.

%s: "required" attribute ignored for private/protected member "%s"
     (W) If member is private or protected, it cannot be a constructor
     parameter.

%s: %s-based class must have %s-based parent (%s is %s-based)
     (F) If the class specified using `subclass' is specified as an array
     reference, its parent must also be specified as array references.  If
     it is specified as a hash reference, its parent(s) must be specified
     as hash references.

%s: A package of this name already exists
     (F) The name passed to class or `subclass' must not be the name of an
     existing package, unless the `allow_redefine' option is true.

%s: An array reference based subclass must have exactly one parent
     (F) Multiple inheritance is only permitted for class hierarchies
     specified as hash references.

%s: Cannot append to "%s": %s
     (F) The save option was true, but a class definition cannot be
     appended to the named file for the specified operating
     system-specific reason.

%s: Cannot save to "%s": %s
     (F) The save option was true, but the class cannot be saved to the
     named file for the specified operating system-specific reason.

%s: Cannot continue after errors
     (F) The class specification includes user defined code that is not
     valid Perl.

%s: Class was not declared using Class::Generate
     (F) An argument of `delete_class' is the name of a package that
     wasn't declared using class or `subclass'.

%s: Default value for "%s" is not correctly typed
     (W) The value of the default attribute specified for the named member
     is either a reference that is does not match the type required for
     the member, or a string that, when evaluated, does not match the
     member's type.

%s: Elements must be in array or hash reference
     (F) A class specification must be an array or hash reference.
     Scalars, lists, and other references are not allowed.

%s: Error in new => { style => '... %s' }: %s is not a member
     (F) A class' constructor specifies a style that requires listing
     members, and the list includes a value that is not a member.

%s: Error in new => { style => '... %s' }: %s is not a public member
     (F) A class' constructor specifies a style that requires listing
     members, and the list includes the name of a private or protected
     member.  Only public members can be passed as a constructor parameter.

%s: Error in new => { style => '... %s' }: Name "%s" used %d times
     (F) A class' constructor specifies a style that requires listing
     members, and the list contains the same member name more than once.

%s: Evaluation failed (problem in Class::Generate?)
     (F) You have done something the creator of `Class::Generate' did not
     anticipate, you've found a bug (or both), or you've got a trailing
     comment in user-defined code (see `"BUGS"' in this node).  Please
     report either of the first two cases.  (This message is accompanied
     by some contextual information that can help you identify the error.
     Please include that information too.)

%s: Extra parameters in style specifier
     (F) A class' constructor was specified to use the mix style, but more
     values were listed than exist non-private members.

%s: Invalid member/method name "%s"
     (F) The names of members and methods must be valid Perl identifiers,
     starting with a letter or underscore and containing only letters,
     underscores, or digits.

%s: Invalid parameter-passing style (must be string or array reference)
     (F) Within the new attribute of a class, the style attribute's value
     must be given as a string or a reference to an array of strings.

%s: Invalid parameter-passing style type "%s"
     (F) Within the new attribute of a class, the style attribute's value
     must begin with one of the words `key_value', mix, `positional', or
     `own'.

%s: Invalid specification for objects of "%s" (must be string or array reference)
     (F) For the named class method, the expressions to be recognized as
     objects must be passed as a string or a reference to a list of
     strings.

%s: Invalid specification for required constructor parameters (must be string or array reference)
     (F) Within the new attribute of a class, the required attribute's
     value must be given as a string or a reference to an array of strings.

%s: Invalid specification of member "%s" (must be string or hash reference with "type" key)
     (F) A member's specification must be given as either a string
     (describing its type) or a hash reference (which must contain the
     type key).

%s: Invalid specification of method "%s" (must be string or hash reference with "body" key)
     (F) The value of a method name must be a string (specifying the
     method's body) or a hash reference, one of whose elements is keyed by
     body.

%s: Member "%s": "%s" is not a valid type
     (F) The type of a member must be `$', `@', %, one of these three
     types followed by an identifier, or an identifier.

%s: Member "%s": Unknown attribute "%s"
     (W) One of the attributes given in the hash reference specifying the
     named member is not a recognized attribute.

"%s: Member "%s" declared both private and protected (protected assumed)
     (W) The member's specification has TRUE values for both the
     `protected' and private attributes.  The more general attribute,
     `protected', will be used.

%s: Method "%s": A class method cannot be protected
     (F) In the current implementation, a class method must be public or
     private.

%s: Method "%s": Unknown attribute "%s"
     (W) One of the attributes given in the hash reference specifying the
     named method is not a recognized attribute.

%s: Missing/extra members in style
     (F) A class' constructor was specified to use the `positional' style,
     but not all non-private members (or too many members) were listed.

%s: Name "%s" used %d times
     (F) The set of member and method names cannot contain duplicates.
     Member and method names share the same namespace.

%s: Parent class "%s" was not defined using class() or subclass(); %s reference assumed
     (W) The `subclass' function permits parents to be any package, not
     just those defined using class and `subclass'.  However, because
     certain capabilities are lost (e.g., base type checking), it emits
     warnings when it detects such subclasses.  Also, the `subclass'
     function assumes that invoking `parent->new' returns a blessed
     reference to whatever the child expects.  If it's wrong, you'll get a
     run-time error when your program invokes one of the parent's or
     child's accessors.

%s: Parent package "%s" does not exist
     (F) The `subclass' function requires all parent classes to exist
     (meaning each is a package) before it is invoked.

%s: Probable mismatch calling constructor in superclass "%s"
     (W) The `subclass' function's constructor specifies a parameter
     passing style that is likely to conflict with the style of its
     parent's.

%s: Required params list for constructor contains unknown member "%s"
     (F) Within the new attribute of a class, the required attribute's
     value contains a name that is not given as class member.

%s: Specification for "new" must be hash reference
     (F) The new attribute of a class must be given as a hash reference.

%s: Value of %s option must be an identifier (without a "$")
     (F) The value passed to the `class_var' or `instance_var' option
     must, when prefixed with a `$', be a valid Perl scalar identifier.
     Note that you do not prefix it with a `$'.  Use:

          -options => { class_var => 'x' }

     and not

          -options => { class_var => '$x' }

Cannot save reference as initial value for "%s"
     (W) References are legal default or initial values.  However, they
     cannot be saved using the save option.

Each class variable must be scalar or hash reference
     (F) The specification of a class variable must be either a string
     containing a valid Perl variable name, or a hash reference; for each
     key/value pair of the reference the key must be a valid Perl variable
     name, and the value must be a Perl expression to be used as the
     variable's default value.

Expected string or array reference
     (F) The value of an attribute's key/value pair should have been a
     string or an array reference, but was not.

Expected string or hash reference
     (F) The value of an attribute's key/value pair should have been a
     string or an array reference, but was not.

Invalid parent specification (must be string or array reference)
     (F) The `subclass' function requires the class' parent(s) to be
     specified as either a string, or a list of strings passed as an array
     reference.

Missing subclass parent
     (F) The `subclass' function requires the class' parent(s) to be
     specified, using the `parent=>list' form.

Missing/extra arguments to class()
     (F) The class function requires at least two arguments: the class'
     name and specification.  Its other arguments must be flags.

Missing/extra arguments to subclass()
     (F) The `subclass' function requires at least four arguments: the
     class' name, the class' specification, and the class' parent as a
     key/value pair.  Other arguments to `subclass' must be flags.

Options must be in hash reference
     (F) The value of the `-options' flag must be a hash reference.

Unknown flag "%s" ignored
     (W) One of the arguments to class or `subclass' begins with -, but is
     not a recognized flag.

Unknown option "%s" ignored
     (W) The `-options' flag includes a key/value pair where the key is
     not a recognized option.

Run-Time Diagnostics
--------------------

   If you use the -w flag, your classes will contain code that can cause
the following diagnostics to be emitted:

%s: Failed assertion: %s
     (F) The specified assertion failed.

%s: Invalid number of parameters
     (F) One of the class' accessors was invoked with too many or too few
     parameters.

%s: Invalid parameter value (expected %s)
     (F) One of the class' accessors was invoked with a parameter of the
     wrong type.

%s: Member is read-only
     (F) Member m was specified read-only, but `$o->m' was invoked with
     parameters that looked like an attempt to set m.

%s: Parameter constraint "%s" failed
     (F) The constraint for the constructor, which involves operators, has
     failed.

%s: Virtual class
     (F) The constructor of a virtual class has been directly invoked.

%s::new: %s: Not a member
     (F) The named class uses the key/value parameter passing style.  Its
     constructor was invoked with one or more key/value pairs whose keys
     don't name a member of the class.  This message often occurs when you
     forget that keys are needed.

%s::new: Invalid value for %s
     (F) The class' constructor was given an improper value for a member.
     If the member is a list, the value passed is the wrong kind of list
     (or not a list).  If the member is typed, the value passed isn't of
     that type.

%s::new: Missing or invalid value for %s
     (F) The class' constructor was invoked without a value for a required
     member, or the value was not of the correct type (e.g., hash
     reference where an array reference is needed, not a blessed reference
     to the necessary class).

%s::new: Missing value for required member %s
     (F) The class' constructor was invoked without a required parameter.

%s::new: Odd number of parameters
     (F) The named class uses the key/value or mix parameter passing style.
     Its constructor was invoked with too many or too few (not just right)
     parameters, i.e., something that didn't look like a list of key/value
     pairs (accounting for any positional parameters in the mix style).

%s::new: Only %d parameter(s) allowed (%d given)
     (F) The named class uses the positional parameter passing style.  Its
     constructor was invoked with more parameters than the class has
     members.

SEE ALSO
========

   PERLDIAG(1), PERLOBJ(1), Carp(3), Class::Struct(3)

COPYRIGHT
=========

   Copyright (c) 1999, 2000 Steven Wartik.  All rights reserved. This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

BUGS
====

   It would be nice to have more selective control of what errors are
checked.

   That pre and post code share the same name space can cause problems if
the `check_code' option is true.  The reason is that the post code is
evaluated with a prepended copy of pre in which all newlines are replaced
by spaces.  This replacement ensures that an error message about post
refers to the appropriate line number within post.  However, if the pre
code contains the `<<' quotation form, Perl will probably complain about a
syntax error; and if it contains a comment, Perl will ignore the first
line of the post code.  Note that this only affects code checking, not the
package that's generated.

   In the current implementation, if member m is an array, then within
user-defined code, the test `if ( @m ) { ... }' does not work in
hash-based classes unless `@m' is initialized.  Use `$#m != -1' instead.
Or specify m as explicitly empty:

     m => { type => '@', default => '[]' }

   Hash members have an analogous bug.  Use `scalar(&m_keys) != 0' to test
if a hash member is empty in user-defined code.

   The `&equals' and `&copy' functions do not understand multiple
inheritance.

   Member and method name substitution in code can be fooled if a member
name is also declared as a variable.  Unfortunately the class function
doesn't detect this error.  In the following class, the $f of `$f[0]' is
mistaken for scalar member f, not array variable `@f':

     class Foo => {
     	f => {
     	    type => '$',
     	    post => 'my @f;
     	     	     $f[0] = $f;    # This causes an error.
     		     ${f}[0] = $f;' # However, this works.
     	}
     };

   If a class declares a protected method m, and one of its subclasses
also declares m, the subclass can't access the parent's version.

   A subclass can declare a member m that overrides a parent's declaration
of m, but it can cause some logical inconsistencies and isn't recommended.
Tne entire model of member overriding may change in some future version.

   The `subclass' function doesn't test for circularity in inheritance
hierarchies.

   The `-allow_redefine' option is intended to let you add functionality to
packages not declared using `Class::Generate'.  This rule isn't strictly
enforced, but probably should be.  If you redefine a class, you silently
change the constructor, as well as the copy and equals methods.  Consider
the following:

     class Foo => [ mem1 => '$' ];
     class Foo => [ mem2 => '@' ], # Intends to add a member to Foo.
     	-options => { allow_redefine => 1 };
     $o = new Foo;
     $o->mem1('this works');
     $o->mem2([qw(so does this)]);
     $p = $o->copy;		  # But this doesn't copy mem1.
     $p = new Foo mem1 => 'x';	  # And this fails.

   Use inheritance instead.

   The algorithm that adds a trailing semicolon to pre and post code uses
a simple regular expression to test for a semicolon's presence.  Please
don't strain it by doing odd things like embedding comments:

     post => 'print "foo"  # This will fail, with an obscure error message.',
     post => 'print "foo"' # Use this form instead.

NOTES
=====

   Default values that are references cannot be saved to a file.

   In pre and post code, you can access method parameters via `@_'.  You
probably should not do so except for scalar members, though.  For array
members, the same code is inserted into m and `add_'m, and the code can't
tell which method it's in.  Even within method m, the code can't tell if
it's looking at a reference or a value if `$accept_refs' is true.

   The UNIVERSAL::isa function is used to determine if something is an
array or hash reference.  This presents possibilities for
metaspecification functions.

   The name `_cginfo' is reserved in all packages generated by
`Class::Generate'.

   Emacs users will quickly discover that the form:

     class Foo => [ member_name => '$' ];

   causes subsequent lines to be incorrectly indented.  The reason is that
perl-mode is confused by `'$''.  Use instead:

     class Foo => [ member_name => "\$" ];

   This package clearly owes much to Class::Struct.  I thank its creators
for their insights.

   Speaking of which, unlike Class::Struct, the m accessor for member m
does not return a value when it is set.  This is a deliberate design
decision.  If you would like that feature, you can simulate it for
(scalar) member m by including `return $m;' as post code.  However, you
then short-circuit any assertion for member m.

Create Apache-like pseudoclass event handlers
*********************************************

NAME
====

   Class::Handler - Create Apache-like pseudoclass event handlers

SYNOPSIS
========

     use Class::Handler;

     handler http => 'My::Module';
     handler http => 'My::OtherModule';
     http->dostuff(@args);           # Tries My::Module->dostuff,
                                     # then My::OtherModule->dostuff
                                     # if it fails or is not found

     nohandler http => 'My::Module'; # Remove My::Module from the
                                     # list of modules to try

     nohandler http;                 # Remove http handler entirely

DESCRIPTION
===========

Overview
--------

   This module can be used to create and maintain pseudoclass event
handlers, which are simply special classes which inherit from multiple
modules but provide no methods of their own. These handlers can be used
just like normal classes, with the added benefit that they are able to
decline or partially handle requests, allowing multiple classes to act on
the same data through the same interface.

   This serves the dual purpose of acting as both a complete Perl 5 module
as well as a prototype for a proposed Perl 6 feature.

Adding and Using Handlers
-------------------------

   To add a handler, you simply use the handler() method which is
automatically exported by this module. handler() takes two arguments, the
first being the name of the handler and the second the name of a class
which should be added to that handler:

     handler signal => 'Signal::DoStuff';

   This would install a new handler called signal which would have one
class, `Signal::DoStuff', in it. You can install multiple handlers at the
same time:

     handler exception => 'My::Catch', 'Site::Failsafe';

   or as multiple subsequent commands:

     handler exception => 'My::Catch';
     handler exception => 'Site::Failsafe';

   The theory behind these handlers is much like the theory behind Apache
handlers. Whatever the name of the method is that is called on the
pseudoclass, is the name of the method that is called on the actual
classes. For example, assuming this code:

     handler http => 'My::HTTP';
     handler http => 'LWP::UserAgent';
     $FH = http->open("http://www.yahoo.com");

   Then the following sequence of events would occur:

     $FH         http->open                            undef
      ^              |                                   ^
      |              |                                   |
      |  Does My::HTTP->open exist?                      |
      |        YES/     \NO                              |
      |          /       \                               |
      |      Try it     Does LWP::UserAgent->open exist? |
      |       / \        ^      YES/     \NO             |
      |    OK/   \UNDEF /         /       ----------------
      -------     ------       Try it                    |
      |                         /  \                     |
      |                      OK/    \UNDEF               |
      -------------------------      ---------------------

   Some highlights:

     1. Each class's open() method is tried in turn, since
        that is the name of the method called on the handler

     2. If undef is returned, the next one in sequence is
        tried.

     3. If 'OK' (simply meaning 1 or some other true value,
        like $FH) is returned, that is propagated out and
        returned by the top-level handler.

     4. All classes are tried until 'OK' is returned or the
        last one is reached.

     This allows you to easily chain classes and methods together with a
     couple key benefits over an inline C<||>:

     1. Each handler can partially handle the request, but
        still return undef, deferring to the next one in line.

     2. The handlers can be reordered internally at-will
        without the main program having to be redone.

     3. Different class open() methods can use internal
        rules, such as "only open .com URLs", without
        you having to put checks for this all over the
        place in the top-level program.

   For more details, please see the Perl 6 RFC listed below.

Removing Handlers
-----------------

   In addition to handlers being added, they need to be removed as well.
This is where nohandler() comes in:

     nohandler http => 'My::HTTP'; # remove My::HTTP from list
     nohandler http;               # remove http handler

   The first example removes `My::HTTP' from the list of classes used by
the http handler. The second syntax removes the http handler entirely,
meaning that this call:

     $FO = http->open("http://www.yahoo.com");

   will result in the familiar error:

     Can't locate object method "open" via package "http"

   Currently, there is no way to reorder handlers without removing and
then re-adding them.

Automatic Handler Registration and Removal
------------------------------------------

   Sometimes, you may find that you want a class to automatically register
as a member of a given handler. To do so, you simply need to `use
Class::Handler' in your module and then prefix the package `main::' (or
whatever package you want to affect) to the start of the handler name:

     package Custom::Module;

     use Class::Handler;
     handler 'main::stuff' => 'Custom::Module';

   This will make it so that in your main script you can now do this:

     use Custom::Module;
     stuff->method(@args);

   And it will call the Custom::Module->method function as expected.

   However, this feature should be used with caution. It borders right on
the edge of scary action-at-a-distance.

REFERENCES
==========

   For more details on the complete Perl 6 proposal, please visit
http://dev.perl.org/rfc/101.html. Comments are welcome.

AUTHOR
======

   Copyright (c) 2000, Nathan Wiger <nate@sun.com>. All Rights Reserved.

   This module is free software; you may copy this under the terms of the
GNU General Public License, or the Artistic License, copies of which
should have accompanied your Perl kit.

report the search path for a class's ISA tree
*********************************************

NAME
====

   Class::ISA - report the search path for a class's ISA tree

SYNOPSIS
========

     # Suppose you go: use Food::Fishstick, and that uses and
     # inherits from other things, which in turn use and inherit
     # from other things.  And suppose, for sake of brevity of
     # example, that their ISA tree is the same as:

     @Food::Fishstick::ISA = qw(Food::Fish  Life::Fungus  Chemicals);
     @Food::Fish::ISA = qw(Food);
     @Food::ISA = qw(Matter);
     @Life::Fungus::ISA = qw(Life);
     @Chemicals::ISA = qw(Matter);
     @Life::ISA = qw(Matter);
     @Matter::ISA = qw();

     use Class::ISA;
     print "Food::Fishstick path is:\n ",
           join(", ", Class::ISA::super_path('Food::Fishstick')),
           "\n";

   That prints:

     Food::Fishstick path is:
      Food::Fish, Food, Matter, Life::Fungus, Life, Chemicals

DESCRIPTION
===========

   Suppose you have a class (like Food::Fish::Fishstick) that is derived,
via its @ISA, from one or more superclasses (as Food::Fish::Fishstick is
from Food::Fish, Life::Fungus, and Chemicals), and some of those
superclasses may themselves each be derived, via its @ISA, from one or
more superclasses (as above).

   When, then, you call a method in that class ($fishstick->calories),
Perl first searches there for that method, but if it's not there, it goes
searching in its superclasses, and so on, in a depth-first (or maybe
"height-first" is the word) search.  In the above example, it'd first look
in Food::Fish, then Food, then Matter, then Life::Fungus, then Life, then
Chemicals.

   This library, Class::ISA, provides functions that return that list -
the list (in order) of names of classes Perl would search to find a
method, with no duplicates.

FUNCTIONS
=========

the function Class::ISA::super_path($CLASS)
     This returns the ordered list of names of classes that Perl would
     search thru in order to find a method, with no duplicates in the list.
     $CLASS is not included in the list.  UNIVERSAL is not included - if
     you need to consider it, add it to the end.

the function Class::ISA::self_and_super_path($CLASS)
     Just like `super_path', except that $CLASS is included as the first
     element.

the function Class::ISA::self_and_super_versions($CLASS)
     This returns a hash whose keys are $CLASS and its
     (super-)superclasses, and whose values are the contents of each
     class's $VERSION (or undef, for classes with no $VERSION).

     The code for self_and_super_versions is meant to serve as an example
     for precisely the kind of tasks I anticipate that self_and_super_path
     and super_path will be used for.  You are strongly advised to read the
     source for self_and_super_versions, and the comments there.

CAUTIONARY NOTES
================

   * Class::ISA doesn't export anything.  You have to address the
functions with a "Class::ISA::" on the front.

   * Contrary to its name, Class::ISA isn't a class; it's just a package.
Strange, isn't it?

   * Say you have a loop in the ISA tree of the class you're calling one
of the Class::ISA functions on: say that Food inherits from Matter, but
Matter inherits from Food (for sake of argument).  If Perl, while
searching for a method, actually discovers this cyclicity, it will throw a
fatal error.  The functions in Class::ISA effectively ignore this
cyclicity; the Class::ISA algorithm is "never go down the same path
twice", and cyclicities are just a special case of that.

   * The Class::ISA functions just look at @ISAs.  But theoretically, I
suppose, AUTOLOADs could bypass Perl's ISA-based search mechanism and do
whatever they please.  That would be bad behavior, tho; and I try not to
think about that.

   * If Perl can't find a method anywhere in the ISA tree, it then looks
in the magical class UNIVERSAL.  This is rarely relevant to the tasks that
I expect Class::ISA functions to be put to, but if it matters to you, then
instead of this:

     @supers = Class::Tree::super_path($class);

   do this:

     @supers = (Class::Tree::super_path($class), 'UNIVERSAL');

   And don't say no-one ever told ya!

   * When you call them, the Class::ISA functions look at @ISAs anew -
that is, there is no memoization, and so if ISAs change during runtime,
you get the current ISA tree's path, not anything memoized.  However,
changing ISAs at runtime is probably a sign that you're out of your mind!

COPYRIGHT
=========

   Copyright (c) 1999, 2000 Sean M. Burke. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Sean M. Burke `sburke@cpan.org'

Iterator superclass for Class::Visitor
**************************************

NAME
====

   Class::Iter - Iterator superclass for Class::Visitor

SYNOPSIS
========

     use Class::Visitor;

     visitor_class 'CLASS', 'SUPER', { TEMPLATE };
     visitor_class 'CLASS', 'SUPER', [ TEMPLATE ];

     $obj = CLASS->new ();
     $iter = $obj->iter;
     $iter = $obj->iter ($parent, $array, $index);

     $iter->parent;
     $iter->is_iter;
     $iter->root;
     $iter->rootpath;
     $iter->next;
     $iter->at_end;
     $iter->delegate;
     $iter->is_same ($obj);

DESCRIPTION
===========

   `Class::Iter' defines the majority of iterator methods for iterator
classes created by `Class::Visitor'.

   parent returns the parent of this iterator, or undef if this is the
root object.

   `is_iter' returns true indicating that this object is an iterator (all
other `is_*TYPE*' queries would be passed on to the delegate).

   root returns the root parent of this iterator.

   `rootpath' returns an array of all iterators between and including the
root and this iterator.

   next returns the iterator of the object after this object in the
parent's element.  If there is no next object, next returns `$self'.

   `at_end' returns true if this is the last object in the parent's
element, i.e. it returns true if next would return `$self'.

   delegate returns the object that this iterator stands-in for.

   `is_same' returns true if $obj is the delegate or if $obj is an
iterator pointing to the same object.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), Class::Visitor(3).

a module for creating generic methods
*************************************

NAME
====

   *Class::MethodMaker* - a module for creating generic methods

SYNOPSIS
========

     use Class::MethodMaker
       new_with_init => 'new',
       get_set       => [ qw /foo bar baz / ];

DESCRIPTION
===========

   This module solves the problem of having to write a bazillion get/set
methods that are all the same. The argument to 'use' is a hash whose keys
are the names of types of generic methods generated by MethodMaker and
whose values tell method maker what methods to make. (More precisely, the
keys are the names of MethodMaker methods (methods that write methods) and
the values are the arguments to those methods.

   To override any generated methods, it is sufficient to ensure that the
overriding method is defined when Class::MethodMaker is called.  Note that
the use keyword introduces a BEGIN block, so you may need to define (or at
least declare) your overriding method in a BEGIN block.

   Some new facilities may be marked as EXPERIMENTAL in the documentation.
These facilities are being trialled, and whilst it is hoped that they will
become mainstream code, no promises are made.  They may change or
disappear at any time.  Caveat Emptor.  The maintainer would be delighted
to hear any feedback particularly regarding such facilities, be it good or
bad, so long as it is constructive.

   Some old facilities may be marked as COMPATIBILITY in the documentation.
These facilities are being maintained purely for compatibility with old
versions of this module, but will ultimately disappear.  They are normally
replaced by alternatives that are thought preferable for some completely
arbitrary raisin.  Please avoid using them, and consider amending any
existing code that does use them not to.  If you believe that their
removal will cast an unacceptable pall over your life, please contact the
maintainer, or get a new life: whichever is easier.

AUTHOR
======

   (Original) Peter Seibel (Organic Online).

   Current Maintainer: Martyn J. Pearce fluffy@engineer.com

   Contributions from:

     Evolution Online Systems, Inc. http://www.evolution.com
     Matthew Persico
     Yitzchak Scott-Thoennes

SEE ALSO
========

VERSION
=======

   Class::MethodMaker v1.02

SUPPORTED METHOD TYPES
======================

new
---

   Creates a basic constructor.

   Takes a single string or a reference to an array of strings as its
argument.  For each string creates a simple method that creates and
returns an object of the appropriate class.

   This method may be called as a class method, as usual, or as in instance
method, in which case a new object of the same class as the instance will
be created.  *Note that new_hash_init works slightly differently with
regard to being called on an instance.*

new_with_init
-------------

   Creates a basic constructor which calls a method named init after
instantiating the object. The init method should be defined in the class
using MethodMaker.

   Takes a single string or a reference to an array of strings as its
argument.  For each string creates a simple method that creates an object
of the appropriate class, calls init on that object propagating all
arguments, before returning the object.

   This method may be called as a class method, as usual, or as in instance
method, in which case a new object of the same class as the instance will
be created.  *Note that new_hash_init works slightly differently with
regard to being called on an instance.*

new_hash_init
-------------

   Creates a basic constructor which accepts a hash of slot-name/value
pairs with which to initialize the object.  The slot-names are interpreted
as the names of methods that can be called on the object after it is
created and the values are the arguments to be passed to those methods.

   Takes a single string or a reference to an array of strings as its
argument.  For each string creates a method that takes a list of arguments
that is treated as a set of key-value pairs, with each such pair causing a
call `$self->key ($value)'.

   This method may be called as a class method, causing a new instance to
be created, or as an instance method, which will operate on the subject
instance.  This allows it to be combined with new_with_init (see above) to
provide some default values.  For example, declare a new_with_init method,
say 'new' and a new_hash_init method, for example, 'hash_init' and then in
the init method, you can call modify or add to the %args hash and then
call hash_init.

   *Note that the operation with regard to action on an instance differs
to that of new and new_with_init differently with regard to being called
on an instance.*

get_set
-------

   Takes a single string or a reference to an array of strings as its
argument.  Each string specifies a slot, for which accessor methods are
created.  The accessor methods are, by default:

x
     If an argument is provided, sets a new value for x.  This is true even
     if the argument is undef (cf. no argument, which does not set.)

     Returns (new) value.

     Value defaults to undef.

clear_x
     Sets value to undef.  This is exactly equivalent to

          $foo->x (undef)

     No return.

   This is your basic get/set method, and can be used for slots containing
any scalar value, including references to non-scalar data. Note, however,
that MethodMaker has meta-methods that define more useful sets of methods
for slots containing references to lists, hashes, and objects.

EXPERIMENTAL: Options
---------------------

   There are several options available for controlling the names and types
of methods created.

   The following options affect the type of methods created:

-static
     The methods will refer to a class-specific, rather than
     instance-specific store.  I.e., these scalars are shared across all
     instances of your object in your process.

   The following options affect the methods created as detailed:

-java
     Creates getx and setx methods, which return the value, and set the
     value (no return), respectively.

-eiffel
     Creates x and set_x methods, analogous to -java get_x and set_x
     respectively.

-compatibility
     Creates x (as per the default), and clear_x, which resets the slot
     value to undef.  Use this to ensure backward compatibility.

-noclear
     Creates x (as per the default) only.

   Alternatively, an arrayref specifying a template for method names may be
supplied.  Each name must contain a '*' character, which will be replaced
by the slot name, and no two patterns may be the same.  undef may be
supplied for methods that you do not want created.  Currently, the first 4
members of such an arrayref may be used:

  1. Creates a method that if supplied an argument, sets the slot to the
     value of that argument; the value of the slot (after setting, if
     relevant) is returned.

  2. Creates a method that takes no arguments, sets the slot value to
     undefined, and makes no return.

  3. Creates a method that takes no arguments, and returns the value of the
     slot.

  4. Creates a method that takes one argument, and sets the value of the
     slot to that value.  Given undef as that argument, the value is set
     to undef.  If called with no arguments, the slot value is set to
     undef.

        See the examples.

Examples
--------

   Creates methods a, b, c which can be used for both getting and setting
the named slots:

     use Class::MethodMaker
       get_set => 'a',
       get_set => [qw/ b c /];

   Creates get_d which returns the value in slot d (takes no arguments),
and set_d, which sets the value in slot d (no return):

     use Class::MethodMaker
       get_set => [ -java => d ];

   Creates e_clear, e_get, e_set, f_clear, f_get, f_set methods:

     use Class::MethodMaker
       get_set => [[undef, '*_clear', '*_get', '*_set'] => qw/e f/ ];

static_get_set
--------------

   Like `get_set|get_set' in this node, takes a single string or a
reference to an array of strings as its argument. For each string, x
creates two methods:

x
     If an argument is provided, sets a new value for x.  Returns (new)
     value.  Value defaults to undef.

clear_x
     Sets value to undef.  No return.

   The difference between this and  `get_set' in this node is that these
scalars are shared across all instances of your object in your process.

   This is now a wrapper around get_set (-static => @args).

get_concat
----------

   Like get_set except sets do not clear out the original value, but
instead concatenate the new value to the existing one. Thus these slots
are only good for plain scalars. Also, like get_set, defines clear_foo
method.

   The argument taken may be a hashref, in which the keys name and join
are recognized; name being the slot name, join being a join string t glue
any given strings.

   Example:

     use Class::MethodMaker
       get_concat => { name => 'words', join => "\t" };

   Will, each time an argument is supplied to the x method, glue this
argument onto any existing value with tab separator.  Like the join
operator, the join field is applied *between* values, not prior to the
first or after the last.

grouped_fields
--------------

   Creates get/set methods like get_set but also defines a method which
returns a list of the slots in the group.

     grouped_fields methods
       some_group => [ qw / field1 field2 field3 / ];

   Its argument list is parsed as a hash of group-name => field-list
pairs. Get-set methods are defined for all the fields and a method with
the name of the group is defined which returns the list of fields in the
group.

object
------

   Creates methods for accessing a slot that contains an object of a given
class as well as methods to automatically pass method calls onto the
object stored in that slot.

     object => [
                'Foo' => 'phooey',
                'Bar' => [ qw / bar1 bar2 bar3 / ],
                'Baz' => {
                          slot => 'foo',
                          comp_mthds => [ qw / bar baz / ]
                         },
                'Fob' => [
                          {
                           slot => 'dog',
                           comp_mthds => 'bark',
                          },
                          {
                           slot => 'cat',
                           comp_mthds => 'miaow',
                          },
                         ];
               ];

   The main argument should be a reference to an array. The array should
contain pairs of class => sub-argument pairs.  The sub-arguments parsed
thus:

Hash Reference
     See `Baz' above.  The hash should contain the following keys:

    slot
          The name of the instance attribute (slot).

    comp_mthds
          A string or array ref, naming the methods that will be forwarded
          directly to the object in the slot.

Array Reference
     As for String, for each member of the array.  Also works if each
     member is a hash reference (see `Fob' above).

String
     The name of the instance attribute (slot).

   For each slot x, with forwarding methods y and z, the following methods
are created:

x
     A get/set method.

     If supplied with an object of an appropriate type, will set set the
     slot to that value.

     Else, if the slot has no value, then an object is created by calling
     new on the appropriate class, passing in any supplied arguments.

     The stored object is then returned.

y
     Forwarded onto the object in slot x, which is auto-created via new if
     necessary.  The new, if called, is called without arguments.

z
     As for y.

   So, using the example above, a method, foo, is created in the class
that calls MethodMaker, which can get and set the value of those objects
in slot foo, which will generally contain an object of class Baz.  Two
additional methods are created in the class using MethodMaker, named 'bar'
and 'baz' which result in a call to the 'bar' and 'baz' methods on the Baz
object stored in slot foo.

object_list
-----------

   Functions like list, but maintains an array of referenced objects in
each slot. Forwarded methods return a list of the results returned by
maping the method over each object in the array.

   Arguments are like object.

forward
-------

     forward => [ comp => 'method1', comp2 => 'method2' ]

   Define pass-through methods for certain fields.  The above defines that
method `method1' will be handled by component comp, whilst method
`method2' will be handled by component `comp2'.

boolean
-------

     boolean => [ qw / foo bar baz / ]

   Creates methods for setting, checking and clearing flags. All flags
created with this meta-method are stored in a single vector for space
efficiency. The argument to boolean should be a string or a reference to
an array of strings. For each string x it defines several methods:

x
     Returns the value of the x-flag.  If called with an argument, it first
     sets the x-flag to the truth-value of the argument.

set_x
     Equivalent to x(1).

clear_x
     Equivalent to x(0).

   Additionally, boolean defines three class methods:

bits
     Returns the vector containing all of the bit fields (remember however
     that a vector containing all 0 bits is still true).

boolean_fields
     Returns a list of all the flags by name.

bit_dump
     Returns a hash of the flag-name/flag-value pairs.

listed_attrib
-------------

     listed_attrib => [ qw / foo bar baz / ]

   Like boolean, listed_attrib creates x, set_x, and clear_x methods.
However, it also defines a class method x_objects which returns a list of
the objects which presently have the x-flag set to true. N.B.
listed_attrib does not use the same space efficient implementation as
boolean, so boolean should be prefered unless the x_objects method is
actually needed.

key_attrib
----------

     key_attrib => [ qw / foo bar baz / ]

   Creates get/set methods like get/set but also maintains a hash in which
each object is stored under the value of the field when the slot is set.
If an object has a slot set to a value which another object is already set
to the object currently set to that value has that slot set to undef and
the new object will be put into the hash under that value. (I.e. only one
object can have a given key. The method find_x is defined which if called
with any arguments returns a list of the objects stored under those values
in the hash. Called with no arguments, it returns a reference to the hash.

key_with_create
---------------

     key_with_create => [ qw / foo bar baz / ]

   Just like key_attrib except the find_x method is defined to call the new
method to create an object if there is no object already stored under any
of the keys you give as arguments.

list
----

   Creates several methods for dealing with slots containing list data.
Takes a string or a reference to an array of strings as its argument and
for each string, x, creates the methods:

x
     This method returns the list of values stored in the slot. In an array
     context it returns them as an array and in a scalar context as a
     reference to the array.

x_push
x_pop
x_shift
x_unshift
x_splice
x_clear
x_count
     Returns the number of elements in x.

x_index
     Takes a list of indices, returns a list of the corresponding values.

x_set
     Takes a list, treated as pairs of index => value; each given index is
     set to the corresponding value.  No return.

hash
----

   Creates a group of methods for dealing with hash data stored in a slot.

   Takes a string or a reference to an array of strings and for each
string, x, creates:

x
     Called with no arguments returns the hash stored in the slot, as a
     hash in a list context or as a reference in a scalar context.

     Called with one simple scalar argument it treats the argument as a key
     and returns the value stored under that key.

     Called with one array (list) reference argument, the array elements
     are considered to be be keys of the hash. x returns the list of values
     stored under those keys (also known as a *hash slice*.)

     Called with one hash reference argument, the keys and values of the
     hash are added to the hash.

     Called with more than one argument, treats them as a series of
     key/value pairs and adds them to the hash.

x_keys
     Returns the keys of the hash.

x_values
     Returns the list of values.

x_tally
     Takes a list of arguments and for each scalar in the list increments
     the value stored in the hash and returns a list of the current (after
     the increment) values.

x_exists
     Takes a single key, returns whether that key exists in the hash.

x_delete
     Takes a list, deletes each key from the hash.

x_clear
     Resets hash to empty.

hash_of_lists
-------------

   Creates a group of methods for dealing with list data stored by key in a
slot.

   Takes a string or a reference to an array of strings and for each
string, x, creates:

x
     Returns all the values for all the given keys, in order.  If no keys
     are given, returns all the values (in an unspecified key order).

     The result is returned as an arrayref in scalar context.  This
     arrayref is not part of the data structure; messing with it will not
     affect the contents directly (even if a single key was provided as
     argument.)

     If any argument is provided which is an arrayref, then the members of
     that array are used as keys.  Thus, the trivial empty-key case may be
     utilized with an argument of [].

x_keys
     Returns the keys of the hash.  As an arrayref in scalar context.

x_exists
     Takes a list of keys, and returns whether each key exists in the hash
     (i.e., the and of whether the individual keys exist).

x_delete
     Takes a list, deletes each key from the hash.

x_push
     Takes a key, and some values.  Pushes the values onto the list denoted
     by the key.  If the first argument is an arrayref, then each element
     of that arrayref is treated as a key and the elements pushed onto each
     appropriate list.

x_pop
     Takes a list of keys, and pops each one.  Returns the list of popped
     elements.  undef is returned in the list for each key that is has an
     empty list.

x_last
     Like x_pop, but does not actually change any of the lists.

x_unshift
     Like push, only the from the other end of the lists.

x_shift
     Like pop, only the from the other end of the lists.

x_splice
     Takes a key, offset, length, and a values list.  Splices the list
     named by the key.  Anything from the offset argument (inclusive) may
     be omitted.  See `splice', see Perlfunc (perl.info).

x_set
     Takes a key, and a set of index->value pairs, and sets each specified
     index to the corresponding value for the given key.

x_clear
     Takes a list of keys.  Resets each named list to empty (but does not
     delete the keys.)

x_count
     Takes a list of keys.  Returns the sum of the number of elements for
     each named list.

x_index
     Takes a key, and a list of indices.  Returns a list of each item at
     the corresponding index in the list of the given key.  Uses undef for
     indices beyond range.

x_remove
     Takes a key, and a list of indices.  Removes each corresponding item
     from the named list.  The indices are effectively looked up at the
     point of call -- thus removing indices 3, 1 from list (a, b, c, d)
     will remove (d) and (b).

x_sift
     Takes a key, and a set of named arguments, which may be a list or a
     hash ref.  Removes list members based on a grep-like approach.

    filter
          The filter function used (as a coderef).  Is passed two
          arguments, the value compared against, and the value in the list
          that is potential for grepping out.  If returns true, the value
          is removed.  Default:

               sub { $_[0] == $_[1] }

    keys
          The list keys to sift through (as an arrayref).  Unknown keys are
          ignored.  Default: all the known keys.

    values
          The values to sift out (as an arrayref).  Default: `[undef]'

   Options:

-static
     Make the corresponding storage class-specific, rather than
     instance-specific.

tie_hash
--------

   Much like hash, but uses a tied hash instead.

   Takes a list of pairs, where the first is the name of the component, the
second is a hash reference.  The hash reference recognizes the following
keys:

tie
     Required.  The name of the class to tie to.  *Make sure you have used
     the required class*.

args
     Required.  Additional arguments for the tie, as an array ref.

   The first argument can also be an arrayref, specifying multiple
components to create.

   Example:

     tie_hash     => [
                      hits        => {
                                      tie => qw/ Tie::RefHash /,
                                      args => [],
                                     },
                     ],

static_hash
-----------

   Much like hash, but uses a class-based hash instead.

code
----

     code => [ qw / foo bar baz / ]

   Creates a slot that holds a code reference. Takes a string or a
reference to a list of string and for each string, x, creates a method x
which if called with one argument which is a CODE reference, it installs
that code in the slot. Otherwise it runs the code stored in the slot with
whatever arguments (including none) were passed in.

method
------

     method => [ qw / foo bar baz / ]

   Just like code, except the code is called like a method, with $self as
its first argument. Basically, you are creating a method which can be
different for each object. Which is sort of weird. But perhaps useful.

abstract
--------

     abstract => [ qw / foo bar baz / ]

   This creates a number of methods will die if called.  This is intended
to support the use of abstract methods, that must be overidden in a useful
subclass.

counter
-------

   Create components containing simple counters that may be read,
incremented, or reset.  For value x, the methods are:

x
     (accepts argument to set),

incr_x
     (accepts argument for increment size),

reset_x.
     The counter is implicitly initialized to zero.

EXPERIMENTAL: copy
------------------

   Produce a copy of self.  The copy is a *shallow* copy; any references
will be shared by the instance upon which the method is called and the
returned newborn.

ADDDING NEW METHOD TYPES
========================

   MethodMaker is a class that can be inherited. A subclass can define new
method types by writing a method that generates a hash of
method_name/code-reference pairs, and then calls the class method
`install_methods' on them.  If the coderef is in fact a string, then that
string will be evalled in the hope of getting a coderef to use.

   For example a simple sub-class that defines a method type
upper_case_get_set might look like this:

     package Class::MethodMakerSubclass;

     use strict;

     use base qw( Class::MethodMaker );

     sub upper_case_get_set {
       my $class = shift;
       my ($name) = @_;
       my %methods;
       $methods{$name} =
         sub {
           my ($self, $new) = @_;
           defined $new and $self->{$name} = uc $new;
           $self->{$name};
         };
       $class->install_methods (%methods);
     }

     1;

   Alternatively, rather than a coderef, the values of the hash passed to
install_methods may be strings, which will be evaled in the hope of
returning a coderef to use.  If the eval fails, or anything other than a
coderef is returned, then C::MM croaks.

   Any return value from a method (above) that is used to generate methods
will be passed to install_methods -- so in the above, the line

     $class->install_methods (%methods);

   could be replaced with

     return %methods

EXPERIMENTAL: builtin_class
---------------------------

   History: This method was in 0.92, undocumented.  Does anybody use this?
Would anybody use this subject to some enhancement or other?  Let me know.

   Purpose: This class generates a wrapper around some builtin function,
cacheing the results in the object and providing a by-name interface.

   Takes a (core) function name, and a arrayref of return position names
(we will call it pos_list).  Creates:

new
     Calls the core func with any given arguments, stores the result in the
     instance.

x
     For each member of pos_list, creates a method of the same name which
     gets/sets the nth member of the returned list, where n is the position
     of x in pos_list.

fields
     Returns pos_list, in the given order.

dump
     Returns a list item name, item value, in order.

   Example Usage:

     package Stat;

     use Class::MethodMaker
       builtin_class => [stat => [qw/ dev ino mode nlink /]],

     package main;

     my $file = "$ENV{HOME}/.profile";
     my $s = Stat->new ($file);
     print "File $file has ", $s->nlink, " links\n";

   Note that (a) the new method does not check the return value of the
function called (in the above example, if $file does not exist, you will
silently get an empty object), and (b) if you really want the above
example, see the core File::stat module.   But you get the idea, I hope.

Support multimethods and function overloading in Perl
*****************************************************

NAME
====

   Class::Multimethods - Support multimethods and function overloading in
Perl

VERSION
=======

   This document describes version 1.70 of Class::Multimethods, released
April  9, 2000.

SYNOPSIS
========

     # IMPORT THE multimethod DECLARATION SUB...

     use Class::Multimethods;

     # DECLARE VARIOUS MULTIMETHODS CALLED find...

     # 1. DO THIS IF find IS CALLED WITH A Container REF AND A Query REF...

     multimethod find => (Container, Query)
     		     => sub { $_[0]->findquery($_[1]) };

     # 2. DO THIS IF find IS CALLED WITH A Container REF AND A Sample REF...

     multimethod find => (Container, Sample)
     		     => sub { $_[0]->findlike($_[1]) };

     # 3. DO THIS IF find IS CALLED WITH AN Index REF AND A Word REF...

     multimethod find => (Index, Word)
     		     => sub { $_[0]->lookup_word($_[1]) };

     # 4. DO THIS IF find IS CALLED WITH AN Index REF AND A qr// PATTERN

     multimethod find => (Index, Regexp)
     		     => sub { $_[0]->lookup_rx($_[1]) };

     # 5. DO THIS IF find IS CALLED WITH AN Index REF AND A NUMERIC SCALAR

     multimethod find => (Index, '#')
     		     => sub { $_[0]->lookup_elem($_[1]) };

     # 6. DO THIS IF find IS CALLED WITH AN Index REF AND A NON-NUMERIC SCALAR

     multimethod find => (Index, '$')
     		     => sub { $_[0]->lookup_str($_[1]) };

     # 7. DO THIS IF find IS CALLED WITH AN Index REF AND AN UNBLESSED ARRAY REF
     #    (NOTE THE RECURSIVE CALL TO THE find MULTIMETHOD)

     multimethod find => (Index, ARRAY)
     		     => sub { map { find($_[0],$_) } @{$_[1]} };

     # SET UP SOME OBJECTS...

     my $cntr = new Container ('./datafile');
     my $indx = $cntr->get_index();

     # ...AND SOME INHERITANCE...

     @BadWord::ISA = qw( Word );
     my $badword = new BadWord("fubar");

     # ...AND EXERCISE THEM...

     print find($cntr, new Query('cpan OR Perl'));		# CALLS 1.
     print find($cntr, new Example('by a committee'));	# CALLS 2.

     print find($indx, new Word('sugar'));			# CALLS 3.
     print find($indx, $badword);				# CALLS 3.
     print find($indx, qr/another brick in the Wall/);	# CALLS 4.
     print find($indx, 7);					# CALLS 5.
     print find($indx, 'But don't do that.');		# CALLS 6.
     print find($indx, [1,"one"]);				# CALLS 7,
     							# THEN 5 & 6.

DESCRIPTION
===========

   The Class:Multimethod module exports a subroutine (&multimethod) that
can be used to declare other subroutines that are dispatched using a
algorithm different from the normal Perl subroutine or method dispatch
mechanism.

   Normal Perl subroutines are dispatched by finding the
appropriately-named subroutine in the current (or specified) package and
calling that. Normal Perl methods are dispatched by attempting to find the
appropriately-named subroutine in the package into which the invoking
object is blessed or, failing that, recursively searching for it in the
packages listed in the appropriate `@ISA' arrays.

   Class::Multimethods multimethods are dispatched quite differently. The
dispatch mechanism looks at the classes or types of each argument to the
multimethod (by calling ref on each) and determines the "closest" matching
*variant* of the multimethod, according to the argument types specified in
the variants' definitions (see `Finding the "nearest" multimethod' in this
node for a definition of "closest").

   The result is something akin to C++'s function overloading, but more
intelligent, since multimethods take the inheritance relationships of each
argument into account. Another way of thinking of the mechanism is that it
performs polymorphic dispatch on every argument of a method, not just the
first.

Defining multimethods
---------------------

   The Class::Multimethods module exports a subroutine called
`multimethod', which can be used to specify multimethod variants with the
dispatch behaviour described above. The `multimethod' subroutine takes the
name of the desired multimethod, a list of class names, and a subroutine
reference, and generates a corresponding multimethod variant within the
current package.

   For example, the declaration:

     package LargeInt;   @ISA = (LargeNumeric);
     package LargeFloat; @ISA = (LargeNumeric);

     package LargeNumeric;
     use Class::Multimethods;

     multimethod divide => (LargeInt, LargeInt) => sub
     {
     	LargeInt::divide($_[0],$_[1]);
     };

     multimethod divide => (LargeInt, LargeFloat) => sub
     {
     	LargeFloat::divide($_[0]->AsLargeFloat(),$_[1]));
     };

   creates a (single!) multimethod `&LargeNumeric::divide' with two
variants.  If the multimethod is called with two references to `LargeInt'
objects as arguments, the first variant (i.e. anonymous subroutine) is
invoked. If the multimethod is called with a `LargeInt' reference and a
`LargeFloat' reference, the second variant is called.

   Note that if you're running under `use strict', the list of bareword
class names in each variant definition will cause problems.  In that case
you'll need to say:

     multimethod divide => ('LargeInt', 'LargeInt') => sub
     {
     	LargeInt::divide($_[0],$_[1]);
     };

     multimethod divide => ('LargeInt', 'LargeFloat') => sub
     {
     	LargeFloat::divide($_[0]->AsLargeFloat(),$_[1]));
     };

   or better still:

     multimethod divide => qw( LargeInt LargeInt ) => sub
     {
     	LargeInt::divide($_[0],$_[1]);
     };

     multimethod divide => qw( LargeInt LargeFloat ) => sub
     {
     	LargeFloat::divide($_[0]->AsLargeFloat(),$_[1]));
     };

   or best of all (;-):

     {
         no strict;

         multimethod divide => (LargeInt, LargeInt) => sub
         {
     	LargeInt::divide($_[0],$_[1]);
         };

     multimethod divide => (LargeInt, LargeFloat) => sub
     {
     		LargeFloat::divide($_[0]->AsLargeFloat(),$_[1]));
     };
     	}

   Calling the multimethod with any other combination of `LargeNumeric'
reference arguments (e.g. a reference to a `LargeFloat' and a reference to
a `LargeInt', or two `LargeFloat' referencess) results in an exception
being thrown, with the message:

     No viable candidate for call to
     multimethod LargeNumeric::divide at ...

   To avoid this, we could provide a "catch-all" variant:

     multimethod divide => (LargeNumeric, LargeNumeric) => sub
     {
     	LargeFloat::divide($_[0]->AsLargeFloat(),$_[1]->AsLargeFloat));
     }

   Now, calling `&LargeNumeric::divide' with either a `LargeFloat'
reference and a `LargeInt' reference or two `LargeFloat' references
results in this third variant being invoked. Note that, adding this third
alternative doesn't affect calls to the other two, since
Class::Multimethods always selects the "nearest" match (see `Finding the
"nearest" multimethod' in this node below for details of what "nearest"
means).

   This "best fit" behaviour is extremely useful, because it means you can
code the specific cases you want to handle, and the one or more
"catch-all" cases to deal with any other combination of arguments.

Finding the "nearest" multimethod
---------------------------------

   Of course, the usefulness of the entire system depends on how
intelligently Class::Multimethods decides which version of a multimethod
is "nearest" to the set of arguments you provided. This decision process
is called "dispatch resolution", and Class::Multimethods does it like this:

  1. If the types of the arguments given (as determined by ref) exactly
     match the types specified in any variant of the multimethod, that
     variant is the one called.

  2. Otherwise, Class::Multimethods compiles a list of "viable targets". A
     viable target is a variant of the multimethod with the correct number
     of parameters, such that for each parameter the specified parameter
     type is a base class of the actual type of the corresponding argument
     in the actual call.

  3. If there is only one viable target, it is immediately called. if
     there are no viable targets, an exception is thrown indicating the
     fact.

  4. Otherwise, Class::Multimethod examines each viable target and computes
     its "distance" to the actual set of arguments. The distance of a
     target is the sum of the distances of each of its parameters. The
     distance of an individual parameter is the number of inheritance
     steps between its class and the actual class of the corresponding
     argument.

     Hence, if a specific argument is of the same class as the
     corresponding parameter type, the distance to that parameter is zero.
     If the argument is of a class that is an immediate child of the
     parameter type, the distance is 1. If the argument is of a class which
     is a "grandchild" of the parameter type, the distance is 2. Et cetera.

  5. Class::Multimethod then chooses the viable target with the smallest
     "distance" as the "final target". If there is more than one viable
     target with an equally smallest distance, an exception is thrown
     indicating that the call is ambiguous. If there *is* only a single
     final target Class::Multimethod records its identity (so the distance
     computations don't have to be repeated next time the same set of
     argument types is used), and then calls that final target.

Where to define multimethods
----------------------------

   Class::Multimethods doesn't care which packages the individual variants
of a multimethod are defined in. Every variant of a multimethod is visible
to the underlying multimethod dispatcher, no matter where it was defined.

   For example, the three variants for the divide multimethod shown above
could all be defined in the LargeNumeric package, or the LargeFloat
package or the LargeInt package, or in main, or in a separate package of
their own.

   Of course, to make a specific multimethod visible within a given
package you still need to tell that package about it. That can be done by
specifying the name of the multimethod only (i.e. no argument list or
variant code):

     package Some::Other::Package::That::Wants::To::Use::divide;

     use Class::Multimethods;
     multimethod "divide";

   For convenience, the declaration itself can be abbreviated to:

     package Some::Other::Package::That::Wants::To::Use::divide;

     use Class::Multimethods "divide";

   Similarly, Class::Multimethod doesn't actually care whether
multimethods are called as methods or as regular subroutines. This is quite
different from the behaviour of normal Perl methods and subroutines, where
how you call them, determines how they are dispatched.

   With multimethods, since all arguments participate in the polymorphic
resolution of a call (instead of just the first), it make no difference
whether a multimethod is called as a subroutine:

     numref3 = divide($numref1, $numref2);

   or a method:

     numref3 = $numref1->divide($numref2);

   (so long as the multimethod has been *declared* in the appropriate
place: the current package for subroutine-like calls, or the invoking
object's package for method-like calls).

   In other words, Class::Multimethods also provides general subroutine
overloading. For example:

     package main;
     use IO;
     use Class::Multimethods;

     multimethod debug => (IO::File) => sub
     {
     	print $_[0] "This should go in a file\n";
     }

     multimethod debug => (IO::Pipe) => sub
     {
     	print $_[0] "This should go down a pipe\n";
     }

     multimethod debug => (IO::Socket) => sub
     {
     	print $_[0] "This should go out a socket\n";
     }

     # and later

     debug($some_io_handle);

Non-class types as parameters
-----------------------------

   Yet another thing Class::Multimethods doesn't care about is whether the
parameter types for each multimethod variant are the names of "real"
classes or just the identifiers returned when raw Perl data types are
passed to the built-in ref function. That means you could also define
multimethod variants like this:

     multimethod stringify => (ARRAY) => sub
     {
     	my @arg = @{$_[0]};
     	return "[" .  join(", ",@arg) . "]";
     }

     multimethod stringify => (HASH) => sub
     {
     	my %arg = %{$_[0]};
     	return "{" . join(", ", map("$_=>$arg{$_}",keys %arg)) . "}";
     }

     multimethod stringify => (CODE) => sub
     {
     	return "sub {???}";
     }

     # and later

     print stringify( [1,2,3] ), "\n";
     print stringify( {a=>1,b=>2,c=>3} ), "\n";
     print stringify( $array_or_hash_ref ), "\n";

   Provided you remember that the parameter types ARRAY, HASH, and CODE
really mean "reference to array", "reference to hash", and "reference to
subroutine", the names of built-in types (i.e. those returned by ref) are
perfectly acceptable as multimethod parameters.

   That's a nice bonus, but there's a problem. Because ref returns an
empty string when given any literal string or numeric value, the following
code:

     print stringify( 2001 ), "\n";
     print stringify( "a multiple dispatch oddity" ), "\n";

   will produce a nasty surprise:

     No viable candidate for call to multimethod stringify() at line 1

   That's because the dispatch resolution process first calls `ref(2001)'
to get the class name for the first argument, and therefore thinks it's of
class "". Since there's no stringify variant with an empty string as its
parameter type, there are no viable targets for the multimethod call.
Hence the exception.

   To overcome this limitation, Class::Multimethods allows three special
pseudo-type names within the parameter lists of multimethod variants.  The
first pseudo-type - `"$"' - is the class that Class::Multimethods pretends
that any scalar value (except a reference) belongs to. Hence, you can make
the two recalcitrant stringifications of scalars work by defining:

     multimethod stringify => ("$")
     	=> sub { return qq{"$_[0]"} }

   With that definition in place, the two calls:

     print stringify( 2001 ), "\n";
     print stringify( "a multiple dispatch oddity" ), "\n";

   would produce:

     "2001"
     "a multiple dispatch oddity"

   That solves the problem, but not as elegantly as it might. It would be
better if numeric values were left unquoted. To this end,
Class::Multimethods offers a second pseudo-type - `"#"' - which is the
class it pretends numeric scalar values belong to (where a scalar value is
"numeric" if it's truly a numerical value (without implicit coercions):

     $var = 0	# numeric --> '$'
     $var = 0.0	# numeric --> '$'
     $var = "0";	# string  --> '#'

   Hence you could now also define:

     multimethod stringify => ("#")
     	=> sub { return "+$_[0]" }

     the two calls to C<&stringify> now
     produce:

     +2001
     "a multiple dispatch oddity"

   The final pseudo-type - `"*"' - is a wild-card or "don't care" type
specifier, which matches any argument type exactly. For example, we could
provide a "catch-all" stringify variant (to handle "GLOB" or "IO"
references, for example):

     multimethod stringify => ("*")
     	=> sub { croak "can't stringify a " . ref($_[0]) }

   The `"*"' pseudo-type can also be used in multiple-argument
multimethods.  For example:

     # General case...

     multimethod handle => (Window, Event, Mode)
     		=> sub { ... }

     	# Special cases...

     multimethod handle => (MovableWindow, MoveEvent, NormalMode)
     		=> sub { ... }

     multimethod handle => (ScalableWindow, ResizeEvent, NormalMode)
     		=> sub { ... }

     # Very special case
     # (ignore any event in any window in PanicMode)

     multimethod handle => ("*", "*", PanicMode)
     		=> sub { ... }

Resolving ambiguities and non-dispatchable calls
------------------------------------------------

   It's relatively easy to set up a multimethod such that particular
combinations of argument types cannot be correctly dispatched. For
example, consider the following variants of a multimethod called `put_peg':

     multimethod put_peg => (RoundPeg,Hole) => sub
     {
     	print "a round peg in any old hole\n";
     };

     multimethod put_peg => (Peg,SquareHole) => sub
     {
     	print "any old peg in a square hole\n";
     };

     multimethod put_peg => (Peg,Hole) => sub
     {
     	print "any old peg in any old hole\n";
     };

   If `put_peg' is called like so:

     put_peg( RoundPeg->new(), SquareHole->new() );

   then Class::Multimethods can't dispatch the call, because it cannot
decide between the `(RoundPeg,Hole)' and `(Peg,SquareHole)' variants, each
of which is the same "distance" (i.e. 1 derivation) from the actual
arguments.

   The default behaviour is to throw an exception (i.e. die) like this:

     Cannot resolve call to multimethod put_peg(RoundPeg,SquareHole).
     The multimethods:
     	put_peg(RoundPeg,Hole)
     	put_peg(Peg,SquareHole)
     are equally viable at ...

   Sometimes, however, the more specialized variants are only
optimizations, and a more general case (e.g. the `(Peg,Hole)' variant)
would suffice as a default where such an ambiguity exists. If that is the
case, it's possible to tell Class::Multimethods to resolve the ambiguity
by calling that variant, using the `resolve_ambiguous' subroutine.
`resolve_ambiguous' is automatically exported by Class::Multimethods and
is used like this:

     resolve_ambiguous put_peg => (Peg,Hole);

   That is, you specify the name of the multimethod being disambiguated,
and the signature of the variant to be used in ambiguous cases. Of course,
the specified variant must actually exist at the time of the call. If it
doesn't, Class::Multimethod ignores it and throws the usual exception.

   Alternatively, if no variant is suitable as a default, you can register
a reference to a subroutine that is to be called instead:

     resolve_ambiguous put_peg => \&disambiguator;

   Now, whenever `put_peg' can't dispatch a call because it's ambiguous,
`disambiguator' will be called instead, with the same argument list as
`put_peg' was given.

   Of course, `resolve_ambiguous' doesn't care what subroutine it's given a
reference to, so you can also use an anonymous subroutine:

     resolve_ambiguous put_peg
     	=> sub
     	   {
     		print "can't put a ", ref($_[0]),
     		      " into a ", ref($_[1]), "\n";
     	   };

   Dispatch can also fail if there are no suitable variants available to
handle a particular call. For example:

     put_peg( JPEG->new(), Loophole->new() );

   which would normally produce the exception:

     No viable candidate for call to
     multimethod put_peg(JPeg,Loophole) at ...

   since classes JPEG and Loophole are't in the Peg and Hole hierarchies,
so there's no inheritance path back to a more general variant.

   To handle cases like this, you can use the <resolve_no_match>
subroutine, which is also exported from Class::Multimethods.
`resolve_no_match' registers a multimethod variant, or a reference to some
other subroutine, that is then used whenever the dispatch mechanism can't
find a suitable variant for a given multimethod call.

   For example:

     resolve_no_match put_peg
     	=> sub
     	   {
     		put_jpeg(@_)
     			if ref($_[0]) eq 'JPEG';
     		shift()->hang(@_)
     			if ref($_[0]) eq 'ClothesPeg';
     		hammer(@_)
     			if ref($_[0]) eq 'TentPeg';
     		# etc.

     	   };

   As with `resolve_ambiguous' the registered variant or subroutine is
called with the same set of arguments that were passed to the original
multimethod call.

Redispatching multimethod calls
-------------------------------

   Sometimes a polymorphic method in a derived class is used to add
functionality to an inherited method. For example, a derived class's
`print_me' method might call it's base class's `print_me', making use of
Perl's special `$obj-'SUPER::method()> construct:

     class Base;

     sub print_me
     {
     	my ($self) = @_;
     	print "Base stuff\n";
     }

     class Derived; @ISA = qw( Base );

     sub print_me
     {
     	my ($self) = @_;
     	$self->SUPER::print_me();	# START LOOKING IN ANCESTORS
     	print "Derived stuff\n";
     }

   If the `print_me' methods are implemented as multimethods, it's still
possible to reinvoke an "ancestral" method, using the automatically
exported `Class::Multimethods::superclass' subroutine:

     use Class::Multimethods;

     multimethod print_me => (Base) => sub
     {
     	my ($self) = @_;
     	print "Base stuff\n";
     }

     multimethod print_me => (Derived) => sub
     {
     	my ($self) = @_;
     	print_me( superclass($self) );	# START LOOKING IN ANCESTORS
     	print "Derived stuff\n";
     }
     }

   Applying superclass to the multimethod argument tells Class::Multimethod
to start looking for parameter types amongst the ancestors of Derived.

   It's also possible in regular Perl to explcitly tell the polymorphic
dispacther where to start looking, by explicitly qualifying the method
name:

     sub Derived::print_me
     {
     	my ($self) = @_;
     	$self->Base::print_me();	# START LOOKING IN Base CLASS
     	print "Derived stuff\n";
     }

   The same is possible with multimethods. superclass takes an optional
second argument that tells Class::Multimethods exactly where to start
looking:

     multimethod print_me => (Derived) => sub
     {
     	my ($self) = @_;
     	print_me( superclass($self => Base) );	# START LOOKING IN Base
     	print "Derived stuff\n";
     }

   Note that, unlike regular method calls, with multimethods you can apply
the superclass subroutine to any or all of a multimethod's arguments. For
example:

     multimethod handle => (MovableWindow, MoveEvent, NormalMode) => sub
     {
     	my ($w, $e, $m) = @_;

     # Do any special stuff,
     # then redispatch to more general handler...

     handle(superclass($w), $e, superclass($m => Mode) );
     	}

   In this case the redispatch would start looking for variants which
matched `(*any of MovableWindow's ancestors*, MoveEvent, Mode)'.

   It's also important to remember that, as with regular methods, the
class of the actual arguments doesn't change just because we subverted the
dispatch sequence. That means if the above redispatch called the handle
variant that takes arguments (Window, MoveEvent, Mode), the actual
arguments would still be of types (MovableWindow, MoveEvent, NormalMode).

DIAGNOSTICS
===========

   If you call `multimethod' and forget to provide a code reference as the
last argument, it dies with the message:

     "multimethod: last arg must be a code reference at %s"

   If the dispatch mechanism cannot find any multimethod with a signature
matching the actual arguments, it dies with the message:

     "No viable candidate for call to multimethod %s at %s"

   If the dispatch mechanism finds two or more multimethods with signatures
equally "close" to the actual arguments (see `"The dispatch resolution
process"' in this node), it dies with the message:

     "Cannot resolve call to multimethod %s. The multimethods:
     	%s
      are equally viable at %s"

   If you specify two variants with the same parameter lists,
Class::Multimethods warns:

     "Multimethod %s redefined at %s"

   but only if $^W is true (i.e. under the -w flag).

AUTHOR
======

   Damian Conway (damian@conway.org)

BUGS AND IRRITATIONS
====================

   There are undoubtedly serious bugs lurking somewhere in code this
complex :-) Bug reports and other feedback are most welcome.

   Ongoing annoyances include:

   * The module uses qr// constructs to improve performance. Hence it won't
     run under Perls earlier than 5.005.

   * Multimethod dispatch is much slower than regular dispatch when the
     resolution has to resort to the more generic cases (though it's
     actually as very nearly as fast as doing the equivalent type
     resolution "by hand", and certainly more reliable and maintainable)

   * The cache management is far too dumb. Adding any new multimethod
     clobbers the entire cache, when it should only expunge those entries
     "upstream" from the the new multimethod's actual parameter types.

     It's unclear, however, under what circumstances the expense of a more
     careful cache correction algorithm would ever be recouped by the
     savings in dispatch (well, obviously, when the installion of
     multimethods is a rare event and multimethod dispatching is frequent,
     but where is the breakeven point?)

COPYRIGHT
=========

     Copyright (c) 1998-2000, Damian Conway. All Rights Reserved.
           This module is free software. It may be used, redistributed
           and/or modified under the terms of the Perl Artistic License
        (see http://www.perl.com/perl/misc/Artistic.html)

SYNOPSIS
========

DESCRIPTION
===========

   Class::Mutator adds the power of 'dynamic polymorphism' to Perl objects,
its similar to Michael Schwern's Sex.pm which he was working on around the
same time, only a little bit more predictable.

   Any object that inherits Class::Mutator principally gains two new
methods, mutate and unmutate that allows them to add methods to themselves
at runtime from other packages. With most recently mutated packages having
precedence when methods are defiend in more than one package.

   This module came about while i was doing some training at the BBC and
someone asked how you could do this easily, after discussion with my fellow
London.pm'ers in particular Piers Cawley this module came about.

TODO
====

   Lots to be done at the minute it requires the extremely useful Memoize
module, this module as always allows be to increase performance without
having to think i'm going to write some code that retains performance if
Memoize is not installed.

   I'm also going to take Michael Schwern's idea of Sex.pm choosing method
precendence randomly and write an Agent::Sex on top of Steve Purkis' Agent
framework so we can start to do some evolutionary Agents in Perl.

METHODS
=======

build_mutation_package(@package_names)
--------------------------------------

   Builds the new mutation package.

build_package_list(operation,package)
-------------------------------------

   Builds a new package list based on the current packages list and the
operation and package (the operation is upon) handed to this method.

unmutate
--------

   Remove mutation abilities via a package

mutate
------

   Adds a mutation.

AUTHOR
======

   Greg McCarroll (greg@mccarroll.demon.co.uk)

A lightweight named parameter handling system.
**********************************************

NAME
====

   Class::NamedParms - A lightweight named parameter handling system.

SYNOPSIS
========

     package SomePackage;
     use Class::NamedParms;
     use vars qw (@ISA);
     @ISA=qw(Class::NamedParms);

     sub new {

     my ($proto) = shift;
         my ($class) = ref ($proto) || $proto;

         $self = Class::NamedParms->new(-benefits,-costs);
     $self = bless $self,$class;

     $self;
      }

     $thingy = SomePackage->new;
     $thingy->set({ -benefits => 1, -costs => 0.5 });
     my ($costs,$benefits) = $thingy->get(-costs,-benefits);

DESCRIPTION
===========

   Provides key name checking for named accessor parameters. This allows
the use of a generic 'get/set' type parameterized accessor while
automatically catching accidental mis-spellings and usage of uninitialized
parameters. This catches a large class of programming errors without
requiring a new accessor for every object parameter.

CHANGES
=======

     1.00 1999.06.16 - Initial release.

     1.01 1999.06.17 - Bug fix to 'clear' method. Added 'make test' support.

     1.02 1999.06.18 - Performance tweak to 'get' method.

     1.03 1999.06.21 - Minor docs tweaks. Removal of 'use attrs' for portability

     1.04 1999.10.08 - Bug fix to 'all_parms' method

Initialization
--------------

new;
     Creates a new instance of a NamedParms object.

     You can optionally 'declare' the legal parameter keys at the same
     time.

     Example:

          my $self = Class::NamedParms(-benefits,-costs,-other);

`list_declared_parms;'
     Returns a list of all parm names that have been declared for this
     NamedParms object. List is unsorted.

`list_initialized_parms;'
     Lists all parms that have had values initialized for this NamedParms
     object Returns a list of the parameter names. List is unsorted.

`declare($parmname,[$parmname1,...]);'
     Declares one or more parameters for use with the NamedParms object.

     Example:

          $self->declare(-moved_in,-car_key,-house_key,-relationship);

     This *does not* initialize the parameters - only declares them to be
     legal for use.

`undeclare($parmname,$parmname1,...);'
     'undeclares' one or more parameters for use with the NamedParms
     object.  This also deletes any values assigned to those parameters.

     Example:

          $self->undeclare(-house_key,-car_key,-relationship);

`exists($parmname);'
     Returns true if the specified parmname has been initialized via 'set'.

`set($parm_ref);'
     Sets one or more named parameter values.

     Example:

          $self->set({ -thingy => 'test', -other_thingy => 'more stuff' });

     Will 'confess' if an attempt is made to set an undeclared parameter
     key.

`clear(@parm_names);'
     Clears (deletes) one or more named parameter values.

     Example:

          $self->clear(-this,-that,-the_other_thing);

     Note: A 'cleared' value returns undef from 'get'.

`get(@parm_names);'
     Gets one or more named parameter values.

     Screams and dies (well, 'confess'es) if you attempt to read a value
     that has not been initialized. Results are returned in the same order
     as the parameter names passed.

     In a scalar context, the _last_ result is what is returned.

     Example:

          my ($age,$gender) = $self->get(-age,-gender);

     Will 'confess' if an attempt is made to access an undeclared key or if
     the requested value has not been initialized.

`all_parms;'
     Returns an anonymous hash containing all the currently set keys and
     values. This hash is suitable for usage with Class::NamedParms or
     Class::ParmList for setting keys/values with their 'set' methods.

     It works by making a shallow copy of the data. This means that it
     copies the scalar values.  In the case of simple numbers and strings,
     this produces a new copy, in the case of references to hashes and
     arrays or objects, it returns the reference to the original object
     such that alterations of the returned object are reflected in the
     live copy.

     Example:

          my $parms = $parms->all_parms;

COPYRIGHT
=========

   Copyright 1999, Benjamin Franz (<URL:http://www.nihongo.org/snowhare/>)
and FreeRun Technologies, Inc. (<URL:http://www.freeruntech.com/>). All
Rights Reserved.  This software may be copied or redistributed under the
same terms as Perl itelf.

AUTHOR
======

   Benjamin Franz

VERSION
=======

     1.04

TODO
====

   Debugging.

SYNOPSIS
========

     package Foo;
     use Class::ObjectTemplate;
     require Exporter;
     @ISA = qw(Class::ObjectTemplate Exporter);

     attributes('one', 'two', 'three');

DESCRIPTION
===========

   Class::ObjectTemplate is a utility class to assist in the building of
other Object Oriented Perl classes.

   It was described in detail in the O\'Reilly book, "Advanced Perl
Programming" by Sriram Srinivasam.

EXPORT
------

   attributes()

AUTHOR
======

   Original code by Sriram Srinivasam.

   Fixes and CPAN module by Jason E. Stewart (jason@openinformatics.com)

SEE ALSO
========

   http://www.oreilly.com/catalog/advperl/

   perl(1).

Perl extension for an optimized template builder base class with lookup capability.
***********************************************************************************

NAME
====

   Class::ObjectTemplate:DB - Perl extension for an optimized template
builder base class with lookup capability.

SYNOPSIS
========

     package Foo;
     use Class::ObjectTemplate::DB;
     require Exporter;
     @ISA = qw(Class::ObjectTemplate:DB Exporter);

     attributes(lookup => ['one', 'two'], no_lookup => ['three']);

     $foo = Foo->new();

     # these two invocations can trigger lookup
     $val = $foo->one();
     $val = $foo->two();

     # this invocation will not trigger lookup
     $val = $foo->three();

     # undefined() handles lookup
     sub Foo::undefined {
       my ($self,$attr) = @_;

     # we retrieve $attr from DB
     return DB_Lookup($self,$attr);
       }

DESCRIPTION
===========

   Class::ObjectTemplate::DB extends Class::ObjectTemplate in one simple
way: the `undefined()' method.

   When a class that inherits from Class::ObjectTemplate::DB defines a
method called undefined(), that method will be triggered when an
attribute\'s getter method is invoked and the attribute\'s current value
is undef.

   The author finds this useful when representing classes based on objects
stored in databases (hence the name of the module). That way an object can
be created, without triggering a DB lookup. Later if data is accessed and
it is not currently present in the object, it can be retrieved on an
as-need basis.

METHODS
-------

attributes('attr1', 'attr2')
attributes(lookup => ['attr1'], no_lookup => ['attr2'])
     attributes() still supports the standard Class::ObjectTemplate syntax
     of a list of attribute names.

     To use the new functionality, the new key-value syntax must be used.
     Any method names specified in the lookup array, will trigger
     undefined. Those specified in the `no_lookup' will not trigger
     `undefined()'.

undefined($self, $attr_name)
     A class that inherits from Class::ObjectTemplate::DB must define a
     method called `undefined()' in order to utilize the lookup behavior.

     Whenever an attribute\'s getter method is invoked, and that
     attribute\'s value is currently undef, then `undefined()' will be
     invoked if that attribute was defined as in the lookup array when
     attributes() was called.

     A class\'s `undefined()' method can include any specialized code
     needed to lookup the value for that objects\'s attribute, such as
     using DBI to connect to a local DB, and retrieve the value from a
     table.

     Class::ObjectTemplate::DB defines a default `undefined()' which does
     nothing.

EXPORT
------

attributes()
AUTHOR
======

   Jason E. Stewart (jason@openinformatics.com)

SEE ALSO
========

   perl(1).

Provides complex parameter list parsing.
****************************************

NAME
====

   Class::ParamParser - Provides complex parameter list parsing.

DEPENDENCIES
============

Perl Version
------------

     5.004

Standard Modules
----------------

     I<none>

Nonstandard Modules
-------------------

     I<none>

SYNOPSIS
========

     use Class::ParamParser;
     @ISA = qw( Class::ParamParser );

PARSING PARAMS INTO NAMED HASH
------------------------------

     sub textfield {
     	my $self = shift( @_ );
     	my $rh_params = $self->params_to_hash( \@_, 0,
     		[ 'name', 'value', 'size', 'maxlength' ],
     		{ 'default' => 'value' } );
     	$rh_params->{'type'} = 'text';
     	return( $self->make_html_tag( 'input', $rh_params ) );
     }

     sub textarea {
     	my $self = shift( @_ );
     	my $rh_params = $self->params_to_hash( \@_, 0,
     		[ 'name', 'text', 'rows', 'cols' ], { 'default' => 'text',
     		'value' => 'text', 'columns' => 'cols' }, 'text', 1 );
     	my $ra_text = delete( $rh_params->{'text'} );
     	return( $self->make_html_tag( 'textarea', $rh_params, $ra_text ) );
     }

     sub AUTOLOAD {
     	my $self = shift( @_ );
     	my $rh_params = $self->params_to_hash( \@_, 0, 'text', {}, 'text' );
     	my $ra_text = delete( $rh_params->{'text'} );
     	$AUTOLOAD =~ m/([^:]*)$/;
     	my $tag_name = $1;
     	return( $self->make_html_tag( $tag_name, $rh_params, $ra_text ) );
     }

PARSING PARAMS INTO POSITIONAL ARRAY
------------------------------------

     sub property {
     	my $self = shift( @_ );
     	my ($key,$new_value) = $self->params_to_array(\@_,1,['key','value']);
     	if( defined( $new_value ) ) {
     		$self->{$key} = $new_value;
     	}
     	return( $self->{$key} );
     }

     sub make_html_tag {
     	my $self = shift( @_ );
     	my ($tag_name, $rh_params, $ra_text) =
     		$self->params_to_array( \@_, 1,
     		[ 'tag', 'params', 'text' ],
     		{ 'name' => 'tag', 'param' => 'params' } );
     	ref($rh_params) eq 'HASH' or $rh_params = {};
     	ref($ra_text) eq 'ARRAY' or $ra_text = [$ra_text];
     	return( join( '',
     		"<$tag_name",
     		(map { " $_=\"$rh_params->{$_}\"" } keys %{$rh_params}),
     		">",
     		@{$ra_text},
     		"</$tagname>",
     	) );
     }

DESCRIPTION
===========

   This Perl 5 object class implements two methods which inherited classes
can use to tidy up parameter lists for their own methods and functions.
The two methods differ in that one returns a HASH ref containing named
parameters and the other returns an ARRAY ref containing positional
parameters.

   Both methods can process the same kind of input parameter formats:

     *empty list*

     value

     value1, value2, ...

     name1 => value1, name2 => value2, ...

     -name1 => value1, -NAME2 => value2, ...

     { -Name1 => value1, NAME2 => value2, ... }

     { name1 => value1, -Name2 => value2, ... }, valueR

     { name1 => value1, -Name2 => value2, ... }, valueR1, valueR2, ...

   Those examples included single or multiple positional parameters,
single or multiple named parameters, and a HASH ref containing named
parameters (with optional "remaining" values afterwards).  That list of
input variations is not exhaustive.  Named parameters can either be
prefixed with "-" or left natural.

   We assume that the parameters are named when either they come as a HASH
ref or the first parameter begins with a "-".  We assume that they are
positional if there is an odd number of them.  Otherwise we are in doubt
and rely on an optional argument to the tidying method that tells us which
to guess by default.

   We assume that any "value" may be an array ref (aka "multiple" values
under the same name) and hence we don't do anything special with them,
passing them as is.  The only exception to this is with "remaining"
values; if there is more than one of them and the first isn't an array
ref, then they are all put in an array ref.

   If the source and destination are both positional, then they are
identical.

SYNTAX
======

   This class does not export any functions or methods, so you need to
call them using object notation.  This means using *Class->function()* for
functions and *$object->method()* for methods.  If you are inheriting this
class for your own modules, then that often means something like
*$self->method()*.  Note that this class doesn't have any properties of
its own.

FUNCTIONS AND METHODS
=====================

params_to_hash( SOURCE, DEF, NAMES[, RENAME[, REM[, LC]]] )
-----------------------------------------------------------

   See below for argument descriptions.

params_to_array( SOURCE, DEF, NAMES[, RENAME[, REM[, LC]]] )
------------------------------------------------------------

   See below for argument descriptions.

params_to_hash_or_array( TO, SOURCE, DEF, NAMES[, RENAME[, REM[, LC]]] )
------------------------------------------------------------------------

   This bonus third method is used internally to implement the first two.
It has an extra first argument, TO, which causes an Array ref to be
returned when true and a Hash ref to be returned when false; the default
value is false.

ARGUMENTS
=========

   The arguments for the above methods are the same, so they are discussed
together here:

  1. The first argument, SOURCE, is an ARRAY ref containing the original
     parameters that were passed to the method which calls this one.  It
     is safe to pass "\@_" because we don't modify the argument at all.
     If SOURCE isn't a valid ARRAY ref then its default value is [].

  2. The second argument, DEF, is a boolean/scalar that tells us whether,
     when in doubt over whether SOURCE is in positional or named format,
     what to guess by default.  A value of 0, the default, means we guess
     named, and a value of 1 means we assume positional.

  3. The third argument, NAMES, is an ARRAY ref (or SCALAR) that provides
     the names to use when SOURCE and our return value are not in the same
     format (named or positional).  This is because positional parameters
     don't know what their names are and named parameters (hashes) don't
     know what order they belong in; the NAMES array provides the missing
     information to both.  The first name in NAMES matches the first value
     in a positional SOURCE, and so-on.  Likewise, the order of argument
     names in NAMES determines the sequence for positional output when the
     SOURCE is named.

  4. The optional fourth argument, RENAME, is a HASH ref that allows us to
     interpret a variety of names from a SOURCE in named format as being
     aliases for one enother.  The keys in the hash are names to look for
     and the values are what to rename them to.  Keys are matched
     regardless of whether the SOURCE names have "-" in front of them or
     not.  If several SOURCE names are renamed to the same hash value, then
     all but one are lost; the SOURCE should never contain more than one
     alias for the same parameter anyway.  One way to explicitely delete a
     parameter is to rename it with "", as parameters with that name are
     discarded.

  5. The optional fifth argument, REM, is only used in circumstances where
     the first element of SOURCE is a HASH ref containing the actual named
     parameters that SOURCE would otherwise be.  If SOURCE has extra,
     "remaining" elements following the HASH ref, then REM says what its
     name is.  Remaining parameters with the same name as normal
     parameters (post renaming and "-" substitution) take precedence.  The
     default value for REM is "", and it is discarded unless renamed.
     Note that the value returned with REM can be either a single scalar
     value, when the "remaining" is a single scalar value, or an array
     ref, when there are more than one "remaining" or the first
     "remaining" is an array ref (passed as is).

  6. The optional sixth argument, LC, is a boolean/scalar that forces
     named parameters in SOURCE to be lowercased; by default this is
     false, meaning that the original case is preserved.  Use this when
     you want your named parameters to have case-insensitive names, for
     accurate matching by your own code or RENAME.  If you use this, you
     must provide lowercased keys and values in your RENAME hash, as well
     as lowercased NAMES and REM; none of these are lowercased for you.

AUTHOR
======

   Copyright (c) 1999-2001, Darren R. Duncan. All rights reserved. This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.  However, I do request that this copyright
information remain attached to the file.  If you modify this module and
redistribute a changed version then please attach a note listing the
modifications.

   I am always interested in knowing how my work helps others, so if you
put this module to use in any of your own code then please send me the
URL.  Also, if you make modifications to the module because it doesn't
work the way you need, please send me a copy so that I can roll desirable
changes into the main release.

   Address comments, suggestions, and bug reports to
*perl@DarrenDuncan.net*.

SEE ALSO
========

   perl(1).

A collection of routines for processing named parameter lists for method calls.
*******************************************************************************

NAME
====

   Class::ParmList - A collection of routines for processing named
parameter lists for method calls.

SYNOPSIS
========

     use Class::ParmList qw(simple_parms parse_parms);

     $thingy->some_method({
          -bgcolor   => '#ff0000',
          -textcolor => '#000000'
     	  });

     sub some_method {
         my ($self) = shift;

     my ($parm_ref) = @_;

     my $parms = Class::ParmList->new ({
            -parms    => $parm_ref,
            -legal    => [qw (-textcolor -border -cellpadding)],
            -required => [qw (-bgcolor)],
            -defaults => {
                           -bgcolor   => "#ffffff",
                           -textcolor => "#000000"
                         }
         });

     if (not defined $parms) {
     	    my $error_message = Class::ParmList->error;
     		die ($error_message);
     }

     # Stuff...

     }

     sub another_method {
       my $self = shift;
       my ($name,$rank,$serial_number) = simple_parms([qw(-name -rank -serial_number)], @_);

     #...
       }

     sub still_another {
        my $parms = parse_parms ({
               -parms    => \@_,
               -legal    => [qw (-textcolor -border -cellpadding)],
               -required => [qw (-bgcolor)],
               -defaults => {
                              -bgcolor   => "#ffffff",
                              -textcolor => "#000000"
                            }
            });
        if (not defined $parms) {
     	    my $error_message = Class::ParmList->error;
     		die ($error_message);
        }

     # ...
       }

DESCRIPTION
===========

   This is a simple package for validating calling parameters to a
subroutine or method. It allows you to use "named parameters" while
providing checking for number and naming of parameters for verifying
inputs are as expected and meet any minimum requirements. It also allows
the setting of default values for the named parameters if omitted.

CHANGES
=======

     1.00 1999.06.16 - Initial release

     1.01 1999.06.18 - Performance tweaks

     1.02 1999.06.21 - Fixing of failure to catch undeclared parm,
                       removal of 'use attrs qw(method)', and
     				   extension of 'make test' support.

     1.03 2000.12.06 - Added exportable class functions 'simple_parms'
                       and 'parse_parms' and allowed 'stacking' references
                       for parms to the object to improve calling usage.

METHODS
=======

`new($parm_list_ref);'
     Returns a reference to an object that can be used to return values.
     If an improper specification is passed, returns 'undef'.  Otherwise
     returns the reference.

     Example:

          my $parms = Class::ParmList->new ({
                 -parms    => $parm_ref,
                 -legal    => [qw (-textcolor -border -cellpadding)],
                 -required => [qw (-bgcolor)],
                 -defaults => {
                                -bgcolor   => "#ffffff",
                                -textcolor => "#000000"
                              }
              });
          All four parameters (-parms, -legal, -required, and -defaults) are
          optional. It is liberal in that anything defined for a -default
          or -required is automatically added to the '-legal' list.

     If the '-legal' parameter is not _explicitly_ called out, no checking
     against the legal list is done. If it _is_ explicitly called out,
     then all -parms are checked against it and it will fail with an error
     if a -parms parameter is present but not defined in the -legal
     explict or implict definitions.

     To simplify calling routines, the '-parms' parameters is allowed to
     'stack' anon list references: [['parm','value']]

     This gives a calling routine the ability to parse @_ without jumping
     through hoops to handle the cases of arrays vs hashes for the passed
     parameters.

     Example:

          sub example_sub {
            my $parms = Class::ParmList->new({ -parms => \@_,
                                              -legal => [],
                                           -required => ['-file','-data'],
                                           -defaults => {},
                                           });

          #...
           }

     This routine would accept *either*

          example_sub({ '-file' => 'test', '-data' => 'stuff' });

     or

          example_sub( '-file' => 'test', '-data' => 'stuff' );

     with no code changes.

`parse_parms($parm_list_ref);'
     This is a functional equivalent to the 'new' method. Calling
     parameters are identical, but it is called as a function that may be
     exported.

     Example:

          my $parms = parse_parms({ -parms => \@_,
                                    -legal => [],
                                 -required => ['-file','-data'],
                                 -defaults => {},
                                });

`get($parm_name1,$parm_name2,...);'
     Returns the parameter value(s) specified in the call line. If a
     parameter is not defined, it returns undef. If a set of '-legal'
     parameters were declared, it croaks if a parameter not in the
     '-legal' set is asked for.

     Example:   my ($help,$who) = $parms->get(-help,-who);

`exists($parm_name);'
     Returns true if the parameter specifed by $parm_name (qv.  has been
     initialized), false if it does not exist.

          if ($parms->exists(-help) {
              # do stuff
          }

`list_parms;'
     Returns the list of parameter names. (Names are always presented in
     lowercase).

     Example:

          my (@parm_names) = $parms->list_parms;

`all_parms;'
     Returns an anonymous hash containing all the currently set keys and
     values. This hash is suitable for usage with Class::NamedParms or
     Class::ParmList for setting keys/values. It works by making a shallow
     copy of the data. This means that it copies the scalar values.  In
     the case of simple numbers and strings, this produces a new copy, in
     the case of references to hashes and arrays or objects, it returns
     the references to the original objects.

     Example:

          my $parms = $parms->all_parms;

FUNCTIONS
=========

   ################################################################

error;
     Returns the error message for the most recent invokation of 'new'.
     (Static method - does not require an object to function)

     Example:

          my $error_message = Class::ParmList->error;
          die ($error_message);

`simple_parms(['-list','-of','-parameter_names'],@_);'
     Parses the passed named parameter list (croaking/confessing if extra
     or missing parameters are found).

     Examples:

          use Class::ParmList qw(simple_parms);

          sub some_method {
             my $self = shift;

          my ($name,$rank) = simple_parms([qw(-name -rank)],@_);
          # Now do stuff
           }

          sub some_function {
             my $serial_number = simple_parms([qw(-serial_number)],@_);
             # Now do stuff
          }

     The passed parameter values for parsing this way may be either an
     anonymous hash of parameters

     Example:    a_function({ -parm1_name => $parm1_value, -parm2_name =>
     $parm2_value }) )

     or a straight list of parameters:

     Example:   a_function(-parm1_name => $parm1_value, -parm2_name =>
     $parm2_value) )

     Note that it *IS* legal for a parameter to be passed with an 'undef'
     value - it will not trigger an error.

     If you need optional parameters, this function is not well suited.
     You should use the object methods above instead for that case - they
     are much more flexible (but quite a bit slower and slightly more
     complex to use).

     Its main virtues are that is is simple to use, has rugged error
     checking for mis-usages and is reasonably fast.

     'simple_parms' can be exported by specifying it on the 'use' line.

VERSION
=======

   1.03 2000.12.06

COPYRIGHT
=========

   Copyright 1999,2000 Benjamin Franz
(<URL:http://www.nihongo.org/snowhare/>) and FreeRun Technologies, Inc.
(<URL:http://www.freeruntech.com/>). All Rights Reserved.  This software
may be copied or redistributed under the same terms as Perl itelf.

AUTHOR
======

   Benjamin Franz

TODO
====

   Everything.

Implements the Phrasebook pattern
*********************************

NAME
====

   Class::Phrasebook - Implements the Phrasebook pattern

SYNOPSIS
========

     use Class::Phrasebook;
     my $pb = new Class::Phrasebook($log, "test.xml");
     $pb->load("NL"); # using Dutch as the language
     $phrase = $pb->get("ADDRESS",
     		     { street => "Chaim Levanon",
     		       number => 88,
     		       city   => "Tel Aviv" } );

DESCRIPTION
===========

   This class implements the Phrasebook pattern. It lets us create
dictionaries of phrases. Each phrase can be accessed by a unique key. Each
phrase may have placeholders. Group of phrases are kept in a dictionary.
The first dictionary is the default one - which means that it will always
be read. One of the dictionaries might be used to override the default
one. The phrases are kept in an XML document.

   The XML document type definition is as followed:

     <?xml version="1.0"?>
     <!DOCTYPE phrasebook [
     	       <!ELEMENT phrasebook (dictionary)*>
     	       <!ELEMENT dictionary (phrase)*>
                   <!ATTLIST dictionary name CDATA #REQUIRED>
                   <!ELEMENT phrase (#PCDATA)>
                   <!ATTLIST phrase name CDATA #REQUIRED>
     ]>

   Example for XML file:

     <?xml version="1.0"?>
     <!DOCTYPE phrasebook [
     	       <!ELEMENT phrasebook (dictionary)*>
     	       <!ELEMENT dictionary (phrase)*>
                   <!ATTLIST dictionary name CDATA #REQUIRED>
                   <!ELEMENT phrase (#PCDATA)>
                   <!ATTLIST phrase name CDATA #REQUIRED>
     ]>
     <phrasebook>
     <dictionary name="EN">

     <phrase name="HELLO_WORLD">
                Hello World!!!
     </phrase>

     <phrase name="THE_HOUR">
                The time now is $hour.
     </phrase>

     <phrase name="ADDITION">
                add $a and $b and you get $c
     </phrase>

     <!-- my name is the same in English Dutch and French. -->
     <phrase name="THE_AUTHOR">
                Rani Pinchuk
     </phrase>
     </dictionary>

     <dictionary name="FR">
     <phrase name="HELLO_WORLD">
                Bonjour le Monde!!!
     </phrase>

     <phrase name="THE_HOUR">
                Il est maintenant $hour.
     </phrase>

     <phrase name="ADDITION">
                $a + $b = $c
     </phrase>

     </dictionary>

     <dictionary name="NL">
     <phrase name="HELLO_WORLD">
                Hallo Werld!!!
     </phrase>

     <phrase name="THE_HOUR">
                Het is nu $hour.
     </phrase>

     <phrase name="ADDITION">
                $a + $b = $c
     </phrase>

     </dictionary>

     </phrasebook>

   Each phrase should have a unique name. Within the phrase text we can
place placeholders. When get method is called, those placeholders will be
replaced by their value.

CONSTRUCTOR
===========

new ( [ LOG ], FILEPATH )
     The constructor. FILEPATH can be the absolute path of the XML file.
     But it can be also just a name of the file, or relative path to the
     file. In that case, that file will be searched in the following
     places:    * The current directory.     * The directory ./lib in the
     current directory.     * The directory ../lib in the current
     directory.     * The directories that are in @INC.

     LOG is a Log object. If LOG is undef, NullLog object will be used.
     If it is provided, the class will use the Log facilities to log
     unusual events.  Returns the new object, or undef on failure.

METHODS
=======

load( DICTIONARY_NAME )
     Will load the phrases of certain dictionary from the file. If the
     dictionary that is requested is not the first one (in the XML file),
     the first dictionary will be loaded first, and then the requested
     dictionary phrases will be loaded.  That way, the first dictionary
     play the role of the default dictionary.

     The DICTIONARY_NAME data member will be set to the parameter that is
     sent to this method. Yet, if nothing is sent to the method, the
     method will use the value of the DICTIONARY_NAME data member to load
     the right dictionary.  If the data member is not defined as well, the
     default dictionary will be loaded.

     Returns 1 on success, 0 on failure.

get(KEY [, REFERENCE_TO_ANONYMOUS_HASH ]) Will return the phrase that fits to the KEY. If a reference to  anonymous has is sent, it will be used to define the parameters in the  phrase.
dictionary_name( DICTIONARY_NAME )
     Access method to the DICTIONARY_NAME data member. See load method
     above.

remove_new_lines ( BOOLEAN )
     Access method to the data member REMOVE_NEW_LINES flag. If this data
     member is true (1), then new lines will be removed from the phrase
     that a is returned by the method get.  Returns the value of the data
     member REMOVE_NEW_LINES flag.

ACCESS METHODS
==============

get_xml_path ( FILE )
     Will return the path of the xml file with that name. It will look for
     this file in the current directory, in ./lib ../lib and in all the
     directories in @INC.  If it is not found, NULL will be returned.

file_path( FILEPATH )
     Access method to the FILE_PATH data member. FILEPATH can be the
     absolute path of the XML file. But it can be also just a name of the
     file, or relative path to the file. In that case, that file will be
     searched in the following places:    * The current directory.     *
     The directory ./lib below the current directory.     * The directory
     ../lib below the current directory.     * The directories that are in
     @INC.

log( LOG )
     Access method to the LOG data member.

ENVIRONMENTS
============

PHRASEBOOK_DEBUG_PRINTS
     If this environment is set to "COLOR", the get method will print the
     phrases it gets, with some extra information in color screen output
     using ANSI escape sequences. If the environment is set to "HTML", the
     information will be printed in HTML format. If the environment is set
     to "TEXT" - the information will be printed as simple text. If the
     environment is not set, or empty - nothing will be printed. This
     feature comes to help debugging the phrases that we get from the
     object of this class.

AUTHOR
======

   Rani Pinchuk, rani@cpan.org

COPYRIGHT
=========

   Copyright (c) 2001 EM-TECH (www.em-tech.net) & Rani Pinchuk.  All
rights reserved.  This package is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

SEE ALSO
========

   `XML::Parser(3)' in this node, `Log::LogLite(3)' in this node,
`Log::NullLogLite(3)' in this node, The Phrasebook Pattern - Yonat Sharon
& Rani Pinchuk - PLoP2K -
http://jerry.cs.uiuc.edu/~plop/plop2k/proceedings/Pinchuk/Pinchuk.pdf

Implements the Phrasebook pattern for SQL statements.
*****************************************************

NAME
====

   Class::Phrasebook::SQL - Implements the Phrasebook pattern for SQL
statements.

SYNOPSIS
========

     use Class::Phrasebook::SQL;
     my $sql = new Class::Phrasebook::SQL($log, "test.xml");
     $sql->load("Pg");
     $statement = $sql->get("INSERT_INTO_CONFIG_ROW",
     		       { id => 88,
     			 parent => 77,
     			 level => 5 });

DESCRIPTION
===========

   This class inherits from Class::Phrasebook and let us manage all the SQL
code we have in a project, in one file. The is done by placing all the SQL
statements as phrases in the XML file of the Class::Phrasebook.  See
*Phrasebook* for details about that file format.

METHODS
=======

get(KEY [, REFERENCE_TO_ANONYMOUS_HASH ])
     Will return the SQL statement that fits to the KEY. If a reference to
     anonymous has is sent, it will be used to define the parameters in the
     SQL statement.

     For example, if the following statement is defined in the XML file:
     <statement name="INSERT_INTO_CONFIG_ROW">                insert into
     t_config (id, parent_id, level)                       values($id,
     $parent, $level)    </statement> We usually will call get method to
     get this statement in the following way:    $statement =
     $sql->get("INSERT_INTO_CONFIG_ROW",                           { id =>
     88,                             parent => 77,
        level => 5 });

     Special case are the SQL update instructions. Most of the time, when
     we call update, we would like to update only part of the columns in a
     row.  Yet, we usually prefer to avoid from writing all the possible
     update combinations. For example if we have the following update call:

          update t_account set
                                login = '$login',
                                description = '$description',
                                dates_id = $dates_id,
                                groups = $groups,
                                owners = $owners
                                            where id = $id

     We do not want to write special update for each case like:

          update t_account set
                                owners = $owners
                                            where id = $id

     or

          update t_account set
                                login = '$login',
                                owners = $owners
                                            where id = $id

     In order to solve this, the get method will delete the "set" lines of
     the update method where the were the parameter value is udefined.
     Because of that we should write the update statements were the pairs
     of <column name> = <parameter> are in separate lines from the rest of
     the statement. Note that the get method will also fix comma problems
     between the pairs (so if the last pair is deleted we will not have
     extra comma).  The method returns the SQL statement, or undef if
     there is no SQL statement for the sent KEY.

escaped_quote ( STRING )
     An access method to the data memeber ESCAPED_QUOTE. The default way
     to escape a quote is to have two quotes ("). This will work on
     Postgres and on MSQL.  Yet, if this default is not working with your
     database of choice, you can change it by seting the ESCAPE_QUOTE data
     member using this method.

use_is_null( BOOLEAN )
     Sometimes, when we have an argument in SQL statement, we will want to
     change the equal sign to 'is'. For example:

     		   select * from my_table where my_id = $id

     If $id is NULL, we sometimes want to have 'my_id is NULL'.  We can
     have that by sending to this method 1. This will promis that where
     ever we have the pattern '= NULL' it will become 'is NULL'. The
     default is not to use the 'is' (thus 0).

save_statements_file_path ( [ FILE_PATH ] )
     Access method to the SAVE_STATEMENTS_FILE_PATH data member. If this
     data member is set, for each call to the get method, the statement
     that is returned also will be appended to that file. This might be
     useful while debugging big projects - it will let the user have a
     full log of all the statemnets that were generated by the get method.

ENVIRONMENTS
============

PHRASEBOOK_SQL_DEBUG_PRINTS
     If this environment is set to "COLOR", the get method will print the
     statements it gets, with some extra information in color screen output
     using ANSI escape sequences. If the environment is set to "HTML", the
     information will be printed in HTML format. If the environment is set
     to "TEXT" - the information will be printed as simple text. If the
     environment is not set, or empty - nothing will be printed. This
     feature comes to help debugging the SQL statements that we get from
     the object of this class.

PHRASEBOOK_SQL_SAVE_STATEMENTS_FILE_PATH
     Another way to set the SAVE_STATEMENTS_FILE_PATH data member is by
     setting this environment variable.

AUTHOR
======

   Rani Pinchuk, rani@cpan.org

COPYRIGHT
=========

   Copyright (c) 2001 EM-TECH (www.em-tech.net) & Rani Pinchuk.  All
rights reserved.  This package is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

SEE ALSO
========

   `XML::Parser(3)' in this node, `Class::Phrasebook(3)' in this node,
`Log::LogLite(3)' in this node, `Log::NullLogLite(3)' in this node

a Module for supporting instance-defined methods
************************************************

NAME
====

   Class::SelfMethods - a Module for supporting instance-defined methods

SYNOPSIS
========

     use Class::SelfMethods;

     package MyClass;
     @ISA = qw(Class::SelfMethods);
     use strict;

     sub _friendly {
       my $self = shift;
       return $self->name;
     }

     package main;
     no strict;

     my $foo = MyClass->new( name => 'foo' );
     my $bar = MyClass->new( name => 'bar', friendly => 'Bar');
     my $bas = MyClass->new( name => 'bas',
                             friendly => sub {
                               my $self = shift;
                               return ucfirst($self->_friendly);
                             }
                           );

     print $foo->friendly, "\n";
     print $bar->friendly, "\n";
     print $bas->friendly, "\n";

     $bas->friendly_SET('a reset friendly');
     print $bas->friendly, "\n";

     $bas->friendly_SET( sub { my $self = shift; return uc($self->_friendly) });
     print $bas->friendly, "\n";

     $bas->friendly_CLEAR;
     print $bas->friendly, "\n";

DESCRIPTION
===========

   `Class::SelfMethods' merges some features of other Object Oriented
languages to build a system for implementing more flexible objects than is
provided by default in Perl.

   The core features I was looking for when I wrote `Class::SelfMethods'
were:

Class-based inheritance hierarchy
     I wanted to retain Perl's normal class-based inheritance hierarchy
     rather than to write (or use) a completely prototype based system.
     If you are looking for a purely prototype based system, see Sean M.
     Burke's `Class::Classless'.  My reasoning on this is that it is
     easier in file based languages (as opposed to world based languages
     like Self) to code class based inheritance hierarchies (which are
     largely static) than to code object based inheritance hierarchies
     (since objects in such languages have a dynamicism that is not
     granted to classes).

Instance-defined method overriding
     I wanted instances to be able to override their class-defined
     methods.  In the example above, the `$bas' object has its own
     `friendly' method.  Instance-defined methods are passed the exact
     same parameter list as class-defined methods.

Subroutine/Attribute equivalence
     Borrowing from Self, I wanted to be able to treat methods and
     attributes similarly.  For instance, in the above example the `$bar'
     object has an attribute `friendly', whereas the `$bas' object has a
     method `friendly', and the `$foo' object uses the class-defined
     method.  The calling syntax is independent of the implementation.
     Parameters can even be passed in the method call and they will simply
     be ignored if the method is implemented by a simple attribute

   In addition to those core features, I (and Damian) had a wish list of
additional features:

Simple syntax
     I wanted the system to be reasonable easy to use for both
     implementers of classes and users of objects.  Simple syntax for
     users is more important than simple syntax for implementers.

Full support for SUPER type concepts
     I wanted instance-defined methods to be able to call the
     class-defined methods they replace.

Support for calling methods at instantiation time
     In some circumstances, rather than deal with multiple inheritance it
     is easier to have a class-defined object method that sets up the
     various instance-defined methods for a given object.  To support
     this, the new method allows deferred method calls to be passed in as
     parameters.

Modifying objects post-instantiation
     I originally had no need for modifying objects post-instantiation,
     but Damian Conway thought it would be a Good Thing (TM) to support.
     Being so very good at these sorts of thing, he instantly came up with
     a good general syntax to support such.  Method calls that end in a
     `_SET' result in the first parameter being assigned to the
     attribute/method.  I noticed one remaining hole and added support for
     `_CLEAR'.

HOW TO
======

Write A Class
-------------

   Your class should inherit from `Class::SelfMethods'.  The class-defined
instance methods should be *defined with* a leading underscore and should
be *called without* a leading underscore.  Don't do anything silly like
writing methods whose proper names have a leading underscore and whose
definitions have two leading underscores - that's just asking for trouble.

   Do not, of course, make use of attributes that have leading underscores
- that's also just asking for trouble.  Also, do not access attributes
directly (i.e. `$self->{foo}').  That will prevent people who use your
class from substituting a method for an attribute.  Instead, always read
attributes by making the corresponding method call (`$self->foo').

   If you need to call `SUPER::methodname', call `SUPER::_methodname'.

Create An Instance
------------------

   The default new method uses named parameters.  Unless you are
certifiable, you will too.  To specify attributes, simply use the syntax
`name => 'value'' and to specify a method use `name => sub { my $self =
shift; . . . }'.  Note that methods and attributes are interchangeable.

Modify An Instance
------------------

   Method calls that end in a `_SET' will result in their first parameter
being assigned to the appropriate attribute/method.  For instance, in the
SYNOPSIS I use `$foo->friendly_SET' to specify both a value and a method
for `friendly'.  Method calls that end in a `_CLEAR' will delete that
attribute/method from the object.  The can method will behave just like
UNIVERSAL::can - it returns a code reference that will interoperate with
the associated object properly using the `$obj->$coderef()' syntax.  For
examples of usage, see test.pl.

Installation instructions
-------------------------

   Standard module installation procedure.

INTERNALS
=========

can
---

   This implementation of can is the heart of the system.  By making can
responsible for almost everything relating to accessing the objects, the
code for deciding how to respond to the various situtations is kept in one
place.

   In order to get major speed improvements (a factor of 2 to 3 for
attribute retrieval and method calls), extensive symbol table manipulation
was used to build methods on the fly that react appropriately.

   The three types of methods are `_SET' methods, `_CLEAR' methods, and
"normal" methods.  The first two are fairly straight forward as far as
implementation goes.  First UNIVERSAL::can is called to determine whether
an appropriate entry has been made in the package symbol table.  If not,
an anonymous subroutine (actually, a closure in this case because `$func'
is a lexically scoped variable defined outside the anonymous subroutine
and referenced from within) is created and assigned into the package
symbol table.  In either case, a reference to the appropriate closure is
returned (normal can behavior is to return a reference to the code or
undef if the method call is not legal).

   The "normal" methods are somewhat trickier.  The outer if statement
exists to ensure that can returns undef for illegal method calls (remember
that there may be situations where `$self->can($func)' should return false
even though `UNIVERSAL::can($self, $func)' returns true). It then checks
whether an appropriate entry has been made in the package symbol table.  If
not, it builds a closure that will do the trick.  Remember that the
closure could get called on an object that is in any of the four possible
states - attribute, instance method, inherited method, or illegal.  The
closure includes the logic to test for instance methods and attributes,
but if neither are present it will make the call to `_method' regardless
of whether or not there is an inherited method with the proper name.  It
relies on AUTOLOAD to properly deal with unhandled `_method' calls.

AUTOLOAD
--------

   AUTOLOAD gets called the first time a given method call is made.  It
first strips off the package name from the function call to extract the
actual function name.  It then checks to see if the function name starts
with an underscore.  If it does, it's a failed call from the "normal"
method closure, so AUTOLOAD calls croak to die with the appropriate error
message.  Notice that the underscore has been stripped off, so it will die
failing to find method.

   AUTOLOAD then calls can, which will return a reference to the
appropriate CODE entity if the method call is supported.  At the same
time, can puts an entry into the symbol table for `Class::SelfMethods' to
support future calls to that method.  AUTOLOAD jumps to that CODE entity
if a valid entity was return.  Otherwise, execution continues on to
another croak call.

new
---

   The new method supplied in `Class::SelfMethods' provides one
interesting twist on an otherwise standard named parameters constructor.
It strips out any passed parameters that have leading underscores and
stores them away.  It then creates the hash ref from the remaining
parameters and blesses it appropriately.  Finally, it takes the stored
parameters that have leading underscores and makes the matching method
calls - the key is used for the method name and the value is dereferenced
to an array and passed as parameters.

AUTHOR
======

   Toby Everett, teverett@alascom.att.com

CREDITS
=======

Damian Conway, damian@cs.monash.edu.au
     Responsible for accessor methods, module name, constructive criticism
     and moral support.  After I responded to Sean's suggestion of
     implementing a can method, Damian completely rewrote my first attempt
     by routing everything through can. He also was the first to point out
     direct symbol table manipulation by implementing it for the `_SET'
     and `_CLEAR' methods.  I rebutted his routing everything through can
     by doing performance testing.  He agreed that the performance issues
     were a problem, but suggested retaining the direct symbol table for
     the accessor methods.  It was then that the lightbulb went off and I
     realized that a properly written closure could be used for the normal
     method calls. Damian's criticisms kept me on track and from making a
     fool of myself, and the result is some very fast (and I hope safe:)
     code.

     I first started writing to Damian as a result of an excellent book he
     wrote, Object Oriented Perl.  I highly recommend it - get it, read it.

Sean M. Burke, sburke@netadventure.net
     Suggested implementing a can method.  Sean was/is responsible for
     `Class::Classless'.  If you need a full-featured purely prototype
     based object system, check it out.

Implementation of a "Singleton" class
*************************************

NAME
====

   Class::Singleton - Implementation of a "Singleton" class

SYNOPSIS
========

     use Class::Singleton;

     my $one = Class::Singleton->instance();   # returns a new instance
     my $two = Class::Singleton->instance();   # returns same instance

DESCRIPTION
===========

   This is the Class::Singleton module.  A Singleton describes an object
class that can have only one instance in any system.  An example of a
Singleton might be a print spooler or system registry.  This module
implements a Singleton class from which other classes can be derived.  By
itself, the Class::Singleton module does very little other than manage the
instantiation of a single object.  In deriving a class from
Class::Singleton, your module will inherit the Singleton instantiation
method and can implement whatever specific functionality is required.

   For a description and discussion of the Singleton class, see "Design
Patterns", Gamma et al, Addison-Wesley, 1995, ISBN 0-201-63361-2.

PREREQUISITES
=============

   Class::Singleton requires Perl version 5.004 or later.  If you have an
older version of Perl, please upgrade to latest version.  Perl 5.004 is
known to be stable and includes new features and bug fixes over previous
versions.  Perl itself is available from your nearest CPAN site (see
INSTALLATION below).

INSTALLATION
============

   The Class::Singleton module is available from CPAN. As the 'perlmod' man
page explains:

     CPAN stands for the Comprehensive Perl Archive Network.
     This is a globally replicated collection of all known Perl
     materials, including hundreds of unbunded modules.

     [...]

     For an up-to-date listing of CPAN sites, see
     http://www.perl.com/perl/ or ftp://ftp.perl.com/perl/ .

   The module is available in the following directories:

     /modules/by-module/Class/Class-Singleton-<version>.tar.gz
     /authors/id/ABW/Class-Singleton-<version>.tar.gz

   For the latest information on Class-Singleton or to download the latest
pre-release/beta version of the module, consult the definitive reference:

     http://www.kfs.org/~abw/perl/

   Class::Singleton is distributed as a single gzipped tar archive file:

     Class-Singleton-<version>.tar.gz

   Note that "<version>" represents the current version number, of the
form "1.23".  See `REVISION' in this node below to determine the current
version number for Class::Singleton.

   Unpack the archive to create an installation directory:

     gunzip Class-Singleton-<version>.tar.gz
     tar xvf Class-Singleton-<version>.tar

   'cd' into that directory, make, test and install the module:

     cd Class-Singleton-<version>
     perl Makefile.PL
     make
     make test
     make install

   The 'make install' will install the module on your system.  You may need
root access to perform this task.  If you install the module in a local
directory (for example, by executing "perl Makefile.PL LIB=~/lib" in the
above - see `perldoc MakeMaker' for full details), you will need to ensure
that the PERL5LIB environment variable is set to include the location, or
add a line to your scripts explicitly naming the library location:

     use lib '/local/path/to/lib';

USING THE CLASS::SINGLETON MODULE
=================================

   To import and use the Class::Singleton module the following line should
appear in your Perl script:

     use Class::Singleton;

   The instance() method is used to create a new Class::Singleton instance,
or return a reference to an existing instance.  Using this method, it is
only possible to have a single instance of the class in any system.

     my $highlander = Class::Singleton->instance();

   Assuming that no Class::Singleton object currently exists, this first
call to instance() will create a new Class::Singleton and return a
reference to it.  Future invocations of instance() will return the same
reference.

     my $macleod    = Class::Singleton->instance();

   In the above example, both $highlander and $macleod contain the same
reference to a Class::Singleton instance.  There can be only one.

DERIVING SINGLETON CLASSES
==========================

   A module class may be derived from Class::Singleton and will inherit the
instance() method that correctly instantiates only one object.

     package PrintSpooler;
     use vars qw(@ISA);
     @ISA = qw(Class::Singleton);

     # derived class specific code
     sub submit_job {
         ...
     }

     sub cancel_job {
         ...
     }

   The PrintSpooler class defined above could be used as follows:

     use PrintSpooler;

     my $spooler = PrintSpooler->instance();

     $spooler->submit_job(...);

   The instance() method calls the _new_instance() constructor method the
first and only time a new instance is created.  All parameters passed to
the instance() method are forwarded to _new_instance().  In the base class
this method returns a blessed reference to an empty hash array.  Derived
classes may redefine it to provide specific object initialisation or change
the underlying object type (to a list reference, for example).

     package MyApp::Database;
     use vars qw( $ERROR );
     use base qw( Class::Singleton );
     use DBI;

     $ERROR = '';

     # this only gets called the first time instance() is called
     sub _new_instance {
     	my $class = shift;
     	my $self  = bless { }, $class;
     	my $db    = shift || "myappdb";
     	my $host  = shift || "localhost";

     unless (defined ($self->{ DB }
     		 = DBI->connect("DBI:mSQL:$db:$host"))) {
         $ERROR = "Cannot connect to database: $DBI::errstr\n";
         # return failure;
         return undef;
     }

     # any other initialisation...

     # return sucess
     $self;
         }

   The above example might be used as follows:

     use MyApp::Database;

     # first use - database gets initialised
     my $database = MyApp::Database->instance();
     die $MyApp::Database::ERROR unless defined $database;

   Some time later on in a module far, far away...

     package MyApp::FooBar
     use MyApp::Database;

     sub new {
     	# usual stuff...

     	# this FooBar object needs access to the database; the Singleton
     	# approach gives a nice wrapper around global variables.

     # subsequent use - existing instance gets returned
     my $database = MyApp::Database->instance();

     # the new() isn't called if an instance already exists,
     # so the above constructor shouldn't fail, but we check
     # anyway.  One day things might change and this could be the
     # first call to instance()...
     die $MyAppDatabase::ERROR unless defined $database;

     # more stuff...
         }

   The Class::Singleton instance() method uses a package variable to store
a reference to any existing instance of the object.  This variable,
"_instance", is coerced into the derived class package rather than the
base class package.

   Thus, in the MyApp::Database example above, the instance variable would
be:

     $MyApp::Database::_instance;

   This allows different classes to be derived from Class::Singleton that
can co-exist in the same system, while still allowing only one instance of
any one class to exists.  For example, it would be possible to derive both
'PrintSpooler' and 'MyApp::Database' from Class::Singleton and have a
single instance of each in a system, rather than a single instance of
*either*.

AUTHOR
======

   Andy Wardley, `<abw@cre.canon.co.uk>'

   Web Technology Group, Canon Research Centre Europe Ltd.

   Thanks to Andreas Koenig `<andreas.koenig@anima.de>' for providing some
significant speedup patches and other ideas.

REVISION
========

   $Revision: 1.3 $

COPYRIGHT
=========

   Copyright (C) 1998 Canon Research Centre Europe Ltd.  All Rights
Reserved.

   This module is free software; you can redistribute it and/or modify it
under the term of the Perl Artistic License.

SEE ALSO
========

Canon Research Centre Europe Perl Pages
     http://www.cre.canon.co.uk/perl/

The Author's Home Page
     http://www.kfs.org/~abw/

Design Patterns
     Class::Singleton is an implementation of the Singleton class
     described in "Design Patterns", Gamma et al, Addison-Wesley, 1995,
     ISBN 0-201-63361-2

declare struct-like datatypes as Perl classes
*********************************************

NAME
====

   Class::Struct - declare struct-like datatypes as Perl classes

SYNOPSIS
========

     use Class::Struct;
             # declare struct, based on array:
     struct( CLASS_NAME => [ ELEMENT_NAME => ELEMENT_TYPE, ... ]);
             # declare struct, based on hash:
     struct( CLASS_NAME => { ELEMENT_NAME => ELEMENT_TYPE, ... });

     package CLASS_NAME;
     use Class::Struct;
             # declare struct, based on array, implicit class name:
     struct( ELEMENT_NAME => ELEMENT_TYPE, ... );

     package Myobj;
     use Class::Struct;
             # declare struct with four types of elements:
     struct( s => '$', a => '@', h => '%', c => 'My_Other_Class' );

     $obj = new Myobj;               # constructor

     # scalar type accessor:
         $element_value = $obj->s;           # element value
         $obj->s('new value');               # assign to element

     # array type accessor:
         $ary_ref = $obj->a;                 # reference to whole array
         $ary_element_value = $obj->a(2);    # array element value
         $obj->a(2, 'new value');            # assign to array element

     # hash type accessor:
         $hash_ref = $obj->h;                # reference to whole hash
         $hash_element_value = $obj->h('x'); # hash element value
         $obj->h('x', 'new value');        # assign to hash element

     # class type accessor:
         $element_value = $obj->c;           # object reference
         $obj->c->method(...);               # call method of object
         $obj->c(new My_Other_Class);        # assign a new object

DESCRIPTION
===========

   Class::Struct exports a single function, `struct'.  Given a list of
element names and types, and optionally a class name, `struct' creates a
Perl 5 class that implements a "struct-like" data structure.

   The new class is given a constructor method, new, for creating struct
objects.

   Each element in the struct data has an accessor method, which is used
to assign to the element and to fetch its value.  The default accessor can
be overridden by declaring a sub of the same name in the package.  (See
Example 2.)

   Each element's type can be scalar, array, hash, or class.

The `struct()' function
-----------------------

   The `struct' function has three forms of parameter-list.

     struct( CLASS_NAME => [ ELEMENT_LIST ]);
     struct( CLASS_NAME => { ELEMENT_LIST });
     struct( ELEMENT_LIST );

   The first and second forms explicitly identify the name of the class
being created.  The third form assumes the current package name as the
class name.

   An object of a class created by the first and third forms is based on
an array, whereas an object of a class created by the second form is based
on a hash. The array-based forms will be somewhat faster and smaller; the
hash-based forms are more flexible.

   The class created by `struct' must not be a subclass of another class
other than UNIVERSAL.

   It can, however, be used as a superclass for other classes. To
facilitate this, the generated constructor method uses a two-argument
blessing.  Furthermore, if the class is hash-based, the key of each
element is prefixed with the class name (see *Perl Cookbook*, Recipe
13.12).

   A function named new must not be explicitly defined in a class created
by `struct'.

   The *ELEMENT_LIST* has the form

     NAME => TYPE, ...

   Each name-type pair declares one element of the struct. Each element
name will be defined as an accessor method unless a method by that name is
explicitly defined; in the latter case, a warning is issued if the warning
flag (-w) is set.

Element Types and Accessor Methods
----------------------------------

   The four element types - scalar, array, hash, and class - are
represented by strings - `'$'', `'@'', `'%'', and a class name -
optionally preceded by a '*'.

   The accessor method provided by `struct' for an element depends on the
declared type of the element.

Scalar (`'$'' or `'*$'')
     The element is a scalar, and by default is initialized to undef (but
     see `Initializing with new' in this node).

     The accessor's argument, if any, is assigned to the element.

     If the element type is `'$'', the value of the element (after
     assignment) is returned. If the element type is `'*$'', a reference
     to the element is returned.

Array (`'@'' or `'*@'')
     The element is an array, initialized by default to `()'.

     With no argument, the accessor returns a reference to the element's
     whole array (whether or not the element was specified as `'@'' or
     `'*@'').

     With one or two arguments, the first argument is an index specifying
     one element of the array; the second argument, if present, is
     assigned to the array element.  If the element type is `'@'', the
     accessor returns the array element value.  If the element type is
     `'*@'', a reference to the array element is returned.

Hash (`'%'' or `'*%'')
     The element is a hash, initialized by default to `()'.

     With no argument, the accessor returns a reference to the element's
     whole hash (whether or not the element was specified as `'%'' or
     `'*%'').

     With one or two arguments, the first argument is a key specifying one
     element of the hash; the second argument, if present, is assigned to
     the hash element.  If the element type is `'%'', the accessor returns
     the hash element value.  If the element type is `'*%'', a reference
     to the hash element is returned.

Class (`'Class_Name'' or `'*Class_Name'')
     The element's value must be a reference blessed to the named class or
     to one of its subclasses. The element is initialized to the result of
     calling the new constructor of the named class.

     The accessor's argument, if any, is assigned to the element. The
     accessor will croak if this is not an appropriate object reference.

     If the element type does not start with a '*', the accessor returns
     the element value (after assignment). If the element type starts with
     a '*', a reference to the element itself is returned.

Initializing with new
---------------------

   `struct' always creates a constructor called new. That constructor may
take a list of initializers for the various elements of the new struct.

   Each initializer is a pair of values: *element name*` => 'value.  The
initializer value for a scalar element is just a scalar value. The
initializer for an array element is an array reference. The initializer
for a hash is a hash reference.

   The initializer for a class element is also a hash reference, and the
contents of that hash are passed to the element's own constructor.

   See Example 3 below for an example of initialization.

EXAMPLES
========

Example 1
     Giving a struct element a class type that is also a struct is how
     structs are nested.  Here, `timeval' represents a time (seconds and
     microseconds), and `rusage' has two elements, each of which is of
     type `timeval'.

          use Class::Struct;

          struct( rusage => {
              ru_utime => timeval,  # seconds
              ru_stime => timeval,  # microseconds
          });

          struct( timeval => [
              tv_secs  => '$',
              tv_usecs => '$',
          ]);

          # create an object:
              my $t = new rusage;

          # $t->ru_utime and $t->ru_stime are objects of type timeval.
          # set $t->ru_utime to 100.0 sec and $t->ru_stime to 5.0 sec.
              $t->ru_utime->tv_secs(100);
              $t->ru_utime->tv_usecs(0);
              $t->ru_stime->tv_secs(5);
              $t->ru_stime->tv_usecs(0);

Example 2
     An accessor function can be redefined in order to provide additional
     checking of values, etc.  Here, we want the count element always to
     be nonnegative, so we redefine the count accessor accordingly.

          package MyObj;
          use Class::Struct;

          # declare the struct
          struct ( 'MyObj', { count => '$', stuff => '%' } );

          # override the default accessor method for 'count'
          sub count {
              my $self = shift;
              if ( @_ ) {
                  die 'count must be nonnegative' if $_[0] < 0;
                  $self->{'count'} = shift;
                  warn "Too many args to count" if @_;
              }
              return $self->{'count'};
          }

          package main;
          $x = new MyObj;
          print "\$x->count(5) = ", $x->count(5), "\n";
                                  # prints '$x->count(5) = 5'

          print "\$x->count = ", $x->count, "\n";
                                  # prints '$x->count = 5'

          print "\$x->count(-5) = ", $x->count(-5), "\n";
                                  # dies due to negative argument!

Example 3
     The constructor of a generated class can be passed a list of
     *element*=>value pairs, with which to initialize the struct.  If no
     initializer is specified for a particular element, its default
     initialization is performed instead. Initializers for non-existent
     elements are silently ignored.

     Note that the initializer for a nested struct is specified as an
     anonymous hash of initializers, which is passed on to the nested
     struct's constructor.

          use Class::Struct;

          struct Breed =>
          {
              name  => '$',
              cross => '$',
          };

          struct Cat =>
          [
              name     => '$',
              kittens  => '@',
              markings => '%',
              breed    => 'Breed',
          ];

          my $cat = Cat->new( name     => 'Socks',
                              kittens  => ['Monica', 'Kenneth'],
                              markings => { socks=>1, blaze=>"white" },
                              breed    => { name=>'short-hair', cross=>1 },
                            );

          print "Once a cat called ", $cat->name, "\n";
          print "(which was a ", $cat->breed->name, ")\n";
          print "had two kittens: ", join(' and ', @{$cat->kittens}), "\n";

Author and Modification History
===============================

   Modified by Damian Conway, 1999-03-05, v0.58.

     Added handling of hash-like arg list to class ctor.

     Changed to two-argument blessing in ctor to support
     derivation from created classes.

     Added classname prefixes to keys in hash-based classes
     (refer to "Perl Cookbook", Recipe 13.12 for rationale).

     Corrected behaviour of accessors for '*@' and '*%' struct
     elements.  Package now implements documented behaviour when
     returning a reference to an entire hash or array element.
     Previously these were returned as a reference to a reference
     to the element.

   Renamed to Class::Struct and modified by Jim Miner, 1997-04-02.

     members() function removed.
     Documentation corrected and extended.
     Use of struct() in a subclass prohibited.
     User definition of accessor allowed.
     Treatment of '*' in element types corrected.
     Treatment of classes as element types corrected.
     Class name to struct() made optional.
     Diagnostic checks added.

   Originally `Class::Template' by Dean Roehrich.

     # Template.pm   --- struct/member template builder
     #   12mar95
     #   Dean Roehrich
     #
     # changes/bugs fixed since 28nov94 version:
     #  - podified
     # changes/bugs fixed since 21nov94 version:
     #  - Fixed examples.
     # changes/bugs fixed since 02sep94 version:
     #  - Moved to Class::Template.
     # changes/bugs fixed since 20feb94 version:
     #  - Updated to be a more proper module.
     #  - Added "use strict".
     #  - Bug in build_methods, was using @var when @$var needed.
     #  - Now using my() rather than local().
     #
     # Uses perl5 classes to create nested data types.
     # This is offered as one implementation of Tom Christiansen's "structs.pl"
     # idea.

Combine Class::Struct, base and fields
**************************************

NAME
====

   Class::Struct::FIELDS - Combine Class::Struct, base and fields

SYNOPSIS
========

   (This page documents `Class::Struct::FIELDS' v.1.0.)

     use Class::Struct::FIELDS;
             # declare struct, based on fields, explicit class name:
     struct (CLASS_NAME => { ELEMENT_NAME => ELEMENT_TYPE, ... });

     use Class::Struct::FIELDS;
             # declare struct, based on fields, explicit class name
             # with inheritance:
     struct (CLASS_NAME => [qw(BASE_CLASSES ...)],
     	    { ELEMENT_NAME => ELEMENT_TYPE, ... });

     package CLASS_NAME;
     use Class::Struct::FIELDS;
             # declare struct, based on fields, implicit class name:
     struct (ELEMENT_NAME => ELEMENT_TYPE, ...);

     package CLASS_NAME;
     use Class::Struct::FIELDS;
             # declare struct, based on fields, implicit class name
             # with inheritance:
     struct ([qw(BASE_CLASSES ...)], ELEMENT_NAME => ELEMENT_TYPE, ...);

     package MyObj;
     use Class::Struct::FIELDS;
             # declare struct with four types of elements:
     struct (s => '$', a => '@', h => '%', x => '&', c => 'My_Other_Class');

     $obj = new MyObj;               # constructor

     # scalar type accessor:
         $element_value = $obj->s;           # element value
         $obj->s ('new value');              # assign to element

     # array type accessor:
         $ary_ref = $obj->a;                 # reference to whole array
         $ary_element_value = $obj->a->[2];  # array element value
         $ary_element_value = $obj->a (2);   # same thing
         $obj->a->[2] = 'new value';         # assign to array element
         $obj->a (2, 'newer value');         # same thing

     # hash type accessor:
         $hash_ref = $obj->h;                # reference to whole hash
         $hash_element_value = $obj->h->{x}; # hash element value
         $hash_element_value = $obj->h (x);  # same thing
         $obj->h->{x} = 'new value';         # assign to hash element
         $obj->h (x, 'newer value');         # same thing

     # code type accessor:
         $code_ref = $obj->x;                # reference to code
         $obj->x->(...);                     # call code
         $obj->x (sub {...});                # assign to element

     # regexp type accessor:
         $regexp = $obj->r;                  # reference to code
         $string =~ m/$obj->r/;              # match regexp
         $obj->r (qr/ ... /);                # assign to element

     # class type accessor:
         $element_value = $obj->c;            # object reference
         $obj->c->method (...);               # call method of object
         $obj->c (My_Other_Class::->new);     # assign a new object

DESCRIPTION
===========

   `Class::Struct::FIELDS' exports a single function, `struct'.  Given a
list of element names and types, and optionally a class name and/or an
array reference of base classes, `struct' creates a Perl 5 class that
implements a "struct-like" data structure with inheritance.

   The new class is given a constructor method, new, for creating struct
objects.

   Each element in the struct data has an accessor method, which is used
to assign to the element and to fetch its value.  The default accessor can
be overridden by declaring a sub of the same name in the package.  (See
Example 2.)

   Each element's type can be scalar, array, hash, code or class.

Differences from Class::Struct base and fields
----------------------------------------------

   `Class::Struct::FIELDS' is a combination of Class::Struct, base and
fields.

   Unlike Class::Struct, inheritance is explicitly supported, and there is
better support for user overrides of constructed accessor methods.  One
result is that you may no longer use the array ([]) notation for
indicating internal representation.  Also, `Class::Struct::FIELDS' relies
on fields for internal representation.

   Also, `Class::Struct::FIELDS' supports code and regular expression
elements.  (Class::Struct handles code and regular expressions as scalars.)

   Lastly, `Class::Struct::FIELDS' passes it's import list, if any, from
the call to `use Class::Struct::FIELDS ...' to `struct' so that you may
create new packages at compile-time.

   Unlike fields, each element has a data type, and is automatically
created at first access.

Calling `use Class::Struct::FIELDS'
-----------------------------------

   You may call `use Class::Struct::FIELDS' just as with any module
library:

     use Class::Struct::FIELDS;
     struct Bob => [];

   However, if you try `my Dog $spot' syntax with this example:

     use Class::Struct::FIELDS;
     struct Bob => [];
     my Bob $bob = Bob::->new;

   you will get a compile-time error:

     No such class Bob at <filename> line <number>, near "my Bob"
     Bareword "Bob::" refers to nonexistent package at <filename> line
     <number>.

   since the compiler has not seen your class declarations yet until after
the call to `struct', by which time it has already seen your my
declarations.  Oops, too late.  Instead, create the package for `Bob'
during compilation:

     use Class::Struct::FIELDS qw(Bob);
     my Bob $bob = Bob::->new;

   This compiles without error as import for `Class::Struct::FIELDS' calls
`struct' for you if you have any arguments in the use statement.  A more
interesting example is:

     use Class::Struct::FIELDS Bob => { a => '$' };
     use Class::Struct::FIELDS Fred => [qw(Bob)];
     my Bob $bob = Bob::->new;
     my Fred $fred = Fred::->new;

The `struct' subroutine
-----------------------

   The `struct' subroutine has three forms of parameter-list:

     struct (CLASS_NAME => { ELEMENT_LIST });
     struct (CLASS_NAME, ELEMENT_LIST);
     struct (ELEMENT_LIST);

   The first form explicitly identifies the name of the class being
created.  The second form is equivalent.  The second form assumes the
current package name as the class name.  The second and third forms are
distinguished by the parity of the argument list: an odd number of
arguments is taken to be of the second form.

   Optionally, you may specify base classes with an array reference as the
first non-class-name argument:

     struct (CLASS_NAME => [qw(BASE_CLASSES ...)], { ELEMENT_LIST });
     struct (CLASS_NAME => [qw(BASE_CLASSES ...)], ELEMENT_LIST);
     struct ([qw(BASE_CLASSES ...)], { ELEMENT_LIST });
     struct ([qw(BASE_CLASSES ...)], ELEMENT_LIST);

   (Since there is no ambiguity between CLASS_NAME and ELEMENT_LIST with
the interposing array reference, you may always make ELEMENT_LIST a list
or a hash reference with this form.)

   The class created by `struct' may be either a subclass or superclass of
other classes.  See Base, and Fields, for
details.

   The *ELEMENT_LIST* has the form

     NAME => TYPE, ...

   Each name-type pair declares one element of the struct. Each element
name will be usually be defined as an accessor method of the same name as
the field, unless a method by that name is explicitly defined (called a
"user override") by the caller prior to the use statement for
`Class::Struct::FIELDS'.  (See `' in this node.)

   `struct' returns the name of the newly-constructed package.

Element Types and Accessor Methods
----------------------------------

   The five element types - scalar, array, hash, code and class - are
represented by strings - `$', `@', %, &, / and a class name.

   The accessor method provided by `struct' for an element depends on the
declared type of the element.

Scalar (`$', `\$' or `*$')
     The element is a scalar, and by default is initialized to undef (but
     see `Initializing with new' in this node).

     The accessor's argument, if any, is assigned to the element.

     If the element type is `$', the value of the element (after
     assignment) is returned. If the element type is `\$' or `*$', a
     reference to the element is returned.

Array (`@', `\@' or `*@')
     The element is an array, initialized by default to `()'.

     With no argument, the accessor returns a reference to the element's
     whole array (whether or not the element was specified as `@', `\@' or
     `*@').

     With one or two arguments, the first argument is an index specifying
     one element of the array; the second argument, if present, is assigned
     to the array element.  If the element type is `@', the accessor
     returns the array element value.  If the element type is `\@' or
     `*@', a reference to the array element is returned.

Hash (%, `\%' or `*%')
     The element is a hash, initialized by default to `()'.

     With no argument, the accessor returns a reference to the element's
     whole hash (whether or not the element was specified as %, `\%' or
     `*%').

     With one or two arguments, the first argument is a key specifying one
     element of the hash; the second argument, if present, is assigned to
     the hash element.  If the element type is %, the accessor returns the
     hash element value.  If the element type is `\%' or `*%', a reference
     to the hash element is returned.

Code (&, `\&' or `*&')
     The element is code, and by default is initialized to undef (but see
     `Initializing with new' in this node).

     The accessor's argument, if any, is assigned to the element.

     If the element type is &, the value of the element (after assignment)
     is returned.  If the element type is `\&' or `*&', a reference to the
     element is returned.  (It is unclear of what value this facility is.
     XXX)

Regexp (/, `\/' or `*/')
     If the element type is /, the value of the element (after assignment)
     is returned.  If the element type is `\/' or `*/', a reference to the
     element is returned.  (It is unclear of what value this facility is.
     XXX)

     Regular expressions really are special in that you create them with
     special syntax, not with a call to a constructor:

          $obj->r (qr/^$/); # fine
          $obj->r (Regexp->new); # WRONG

Class (`Class_Name', `\Class_Name' or `*Class_Name')
     The element's value must be a reference blessed to the named class or
     to one of its subclasses. The element is initialized to the result of
     calling the new constructor of the named class.

     The accessor's argument, if any, is assigned to the element. The
     accessor will croak if this is not an appropriate object reference.

     If the element type does not start with a \ or *, the accessor
     returns the element value (after assignment). If the element type
     starts with a \ or *, a reference to the element itself is returned.

     The class is automatically required for you so that, for example, you
     can safely write:

          struct MyObj {io => 'IO::Scalar'};

     and access io immediately.  The same applies for nested structs:

          BEGIN {
            struct Alice { when => '$' };
            struct Bob { who => 'Alice' };
          }

          my Bob $b = Bob::->new;
          $b->who->when ('what');

     Note, however, the BEGIN block so that this example can use the `my
     Dog $spot' syntax for `my Bob $b'.  Also, no actual import happens
     for the caller - the automatic use is only for convenience in
     auto-constructing members, not magic.  Another way to do this is:

          { package Bob; use Class::Struct::FIELDS; struct }
          my Bob $b = Bob::->new;

     And of course the best way to do this is simply:

          use Class::Struct::FIELDS qw(Bob);
          my Bob $b = Bob::->new;

What about globs (*) and other funny types?
     At present, `Class::Struct::FIELDS' does not support special notation
     for other intrinsic types.  Use a scalar to hold a reference to globs
     and other unusual specimens, or wrap them in a class such as
     IO::Handle (globs).  XXX

Initializing with new
---------------------

   `struct' always creates a constructor called new. That constructor may
take a list of initializers for the various elements of the new struct.

   Each initializer is a pair of values: *element name*` => 'value.  The
initializer value for a scalar element is just a scalar value.  The
initializer for an array element is an array reference.  The initializer
for a hash is a hash reference.  The initializer for code is a code
reference.

   The initializer for a class element is also a hash reference, and the
contents of that hash are passed to the element's own constructor.

   new tries to be as clever as possible in deducing what type of object
to construct.  All of these are valid:

     use Class::Struct::FIELDS qw(Bob);
     my Bob $b = Bob::->new; # good style
     my Bob $b2 = $b->new; # works fine
     my Bob $b3 = &Bob::new; # if you insist
     my Bob $b4 = Bob::new (apple => 3, banana => 'four'); # WRONG!

   The last case doesn't behave as hoped for: new tries to construct an
object of package `apple' (and hopefully fails, unless you actually have a
package named `apple'), not an object of package `Bob'.

   See Example 3 below for an example of initialization.

Initializing with init
----------------------

   You may also use init as a constructor to assign initial values to new
objects.  (In fact, this is the preferred method.)  `struct' will see to
it that you have a ready object to work with, and pass you any arguments
used in the call to new:

     sub init {
       my MyObj $self = shift;

     @self->a->[0..3] = (a..d);

     return $self;
       }

   It is essential that you return an object from init, as this is
returned to the caller of new.  You may return a different object if you
wish, but this would be rather uncommon.

   First, new arranges for any constructor argument list to be processed
first before calling init.

   Second, new arranges to call init for base classes, calling them in
bottom-up order, before calling init.  This is so that ancestors may
construct an object before descendents.

   There is no corresponding facility for DESTROY.  XXX

Replacing member access methods with user overrides
---------------------------------------------------

   You might want to create custom access methods, or user overrides.  The
most straight forward way to do this and still retain string and warnings
is:

     use strict;
     use warnings;

     sub Bob::ff ($;$$); # declare sub so Class::Struct::FIELDS can see

     use Class::Struct::FIELDS Bob => { ff => '$' };

     sub Bob::ff ($;$$) {
       my Bob $self = shift;

     &some_other_sub (@_);
         }

   If you do not declare the user override prior to the use statement, a
warning is issued if the warning flag (-w) is set.

   Notice that we changed the default sub signature for ff from `($;$)' to
`($;$$)'.  Normally, this might generate a warning if we redefine the sub,
but declaring the sub ahead of time keeps strict and warnings happy.  You
might prefer this construction:

     { package Bob; }

     sub Bob::ff ($;$$) {
       my Bob $self = shift;

     &some_other_sub (@_);
         }

     use Class::Struct::FIELDS Bob => { ff => '$' };

   You might still want the advantages of the the constructed accessor
methods, even with user overrides (for example, checking that an assigned
value is the right type or package). `Class::Struct::FIELDS' constructs
the accessor with a special name, so that you may use it yourself in the
user override.  That special name is the regular field name prepended by a
double underscore, `__'.  You can access these so:

     use strict;
     use warnings;

     sub Bob::ff ($;$); # declare sub so Class::Struct::FIELDS can see
     sub Bob::gg ($;$); # declare sub so Class::Struct::FIELDS can see

     use Class::Struct::FIELDS Bob => { ff => '$', gg => '$' };

     # This example is identical to having no user override.
     sub Bob::ff ($;$) {
       my Bob $self = shift;
       $self->__ff (@_);
     }

     # This example illustrates a workaround for v5.6.0.
     sub Bob::gg ($;$) {
       # This silliness is due to a bug in 5.6.0: it thinks you can't
       # fiddle with @_ if you've given it a prototype.  XXX
       my @args = @_;
       $args[1] *= 2 if @args == 2 and defined $args[1];
       @_ = @args;
       goto &Bob::__gg;
     }

Private fields
--------------

   Fields starting with a leading underscore, _, are private: they are
still valid fields, but `Class::Struct::FIELDS' does not create
subroutines to access them.  Instead, you should access them the usual way
for hash members:

     $self->{_private_key}; # ok
     $self->_private_key; # Compilation error

   See Fields, for more details.

EXAMPLES
========

Example 1
     Giving a struct element a class type that is also a struct is how
     structs are nested.  Here, `timeval' represents a time (seconds and
     microseconds), and `rusage' has two elements, each of which is of
     type `timeval'.

          use Class::Struct::FIELDS;

          struct (rusage => {
            ru_utime => timeval,  # seconds
            ru_stime => timeval,  # microseconds
          });

          struct (timeval => {
            tv_secs  => '$',
            tv_usecs => '$',
          });

          # create an object:
              my $t = new rusage;

          # $t->ru_utime and $t->ru_stime are objects of type timeval.
          # set $t->ru_utime to 100.0 sec and $t->ru_stime to 5.0 sec.
              $t->ru_utime->tv_secs (100);
              $t->ru_utime->tv_usecs (0);
              $t->ru_stime->tv_secs (5);
              $t->ru_stime->tv_usecs (0);

Example 2
     An accessor function can be redefined in order to provide additional
     checking of values, etc.  Here, we want the count element always to
     be nonnegative, so we redefine the count accessor accordingly.

          package MyObj;
          use Class::Struct::FIELDS;

          # declare the struct
          struct (MyObj => {count => '$', stuff => '%'});

          # override the default accessor method for 'count'
          sub count {
            my MyObj $self = shift;

          if (@_) {
            die 'count must be nonnegative' if $_[0] < 0;
            $self->{count} = shift;
            warn "Too many args to count" if @_;
          }

          return $self->{count};
              }

          package main;
          $x = new MyObj;
          print "\$x->count (5) = ", $x->count (5), "\n";
                                  # prints '$x->count (5) = 5'

          print "\$x->count = ", $x->count, "\n";
                                  # prints '$x->count = 5'

          print "\$x->count (-5) = ", $x->count (-5), "\n";
                                  # dies due to negative argument!

Example 3
     The constructor of a generated class can be passed a list of
     *element*=>value pairs, with which to initialize the struct.  If no
     initializer is specified for a particular element, its default
     initialization is performed instead. Initializers for non-existent
     elements are silently ignored.

     Note that the initializer for a nested struct is specified as an
     anonymous hash of initializers, which is passed on to the nested
     struct's constructor.

          use Class::Struct::FIELDS;

          struct Breed =>
          {
            name  => '$',
            cross => '$',
          };

          struct Cat =>
          {
            name     => '$',
            kittens  => '@',
            markings => '%',
            breed    => 'Breed',
          };

          my $cat = Cat->new
            (name     => 'Socks',
             kittens  => ['Monica', 'Kenneth'],
             markings => { socks => 1, blaze => "white" },
             breed    => { name => 'short-hair', cross => 1 });

          print "Once a cat called ", $cat->name, "\n";
          print "(which was a ", $cat->breed->name, ")\n";
          print "had two kittens: ", join(' and ', @{$cat->kittens}), "\n";

Example 4
     `Class::Struct::FIELDS' has a very elegant idiom for creating
     inheritance trees:

          use Class::Struct::FIELDS Fred => [];
          use Class::Struct::FIELDS Barney => [qw(Fred)];
          use Class::Struct::FIELDS Wilma => [qw(Barney)],
            { aa => '@',
              bb => 'IO::Scalar' };

     That's all the code it takes!

EXPORTS
=======

   `Class::Struct::FIELDS' export `struct' for backwards-compatibility
with Class::Struct.

DIAGNOSTICS
===========

   The following are diagnostics generated by *Class::Struct::Fields*.
Items marked "(W)" are non-fatal (invoke `Carp::carp'); those marked "(F)"
are fatal (invoke `Carp::croak').

'struct' usage error
     (F) The caller failed to read the documentation for
     `Class::Struct::FIELDS' and follow the advice therein.

Accessor '%s' exists in package '%s' hides method in base class
     (W) There is already a subroutine, with the name of one of the
     accessors, located in a base class of the given package.  You should
     consider renaming the field with the given name.

Method '%s' exists in package '%s' overrides accessor
     (W) There is already a subroutine, with the name of one of the
     accessors, located in the given package.  You may have intended this,
     however, if defining your own custom accessors.

Method 'new' already exists in package '%s'
     (W) There is already a 'new' subroutine located in the given package.
     As long as the caveats for defining your own new are followed, this
     warning is harmless; otherwise your objects may not be properly
     initialized.

Initializer for '%s' must be %s reference
     (F) At runtime, the caller tried to assign the wrong type of argument
     to the element.  An example which triggers this message:

          use Class::Struct::FIELDS Bob => { ary => '@' };
          my $b = Bob::->new;
          $b->ary ({hash => 'reference'}); # croaks

     The last statement will croak with the message, "Initializer for 'ary'
     must be ARRAY reference".

Initializer for '%s' must be %s object
     (F) At runtime, the caller tried to assign the wrong class of argument
     to the element.  An example which triggers this message:

          use Class::Struct::FIELDS Bob => { mary => 'Mary' };
          use Class::Struct::FIELDS qw(Fred); # NOT inherit from Mary
          my $b = Bob::->new;
          $b->ary (Fred::->new); # croaks

     The last statement will croak with the message, "Initializer for 'aa'
     must be Mary object".

BUGS AND CAVEATS
================

   Please see the TODO list.

CREDITS
=======

   This documentation is amazingly like that of Class::Struct.  I wonder
why.  Credit to Dr. Damian Conway <damian@conway.org>.

AUTHOR
======

   B. K. Oxley (binkley) <binkley@bigfoot.com>

   Copyright (c) 2000 B. K. Oxley (binkley). All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

See Class/Contract,
     `Class::Contract' is an extension module by Damian Conway for writing
     in a design-by-contract object-oriented style.  It has many of the
     features of `Class::Struct::FIELDS', and many more besides.

See Class/Struct,
     Class::Struct is a standard module for creating simple, uninherited
     data structures.

See Base,
     base is a standard module for establishing IS-A relationships with
     base classes at compile time.

See Fields,
     fields is a standard module for imbuing your class with efficient
     pseudo-hashes for data members.

The Transportable Object Model for Perl
***************************************

NAME
====

   Class::Tom - The Transportable Object Model for Perl

SYNOPSIS
========

   use Class::Tom qw ( restore );

   my $tom = new Class::Tom;

   $tom->insert(<OBJECT>);

   $tom->insert(<ANONYMOUS SUB>);

   $tom->insert(<PACKAGE NAME>);

   my $flat = $tom->store();

   my $newtom = restore( $flat );

DESCRIPTION
===========

   `Class::Tom' allows you to transport objects from one system to another
without requiring that the packages the object relies on actually exist on
the other machine.

METHODS
=======

new
     new is the objects constructor.  It can optionally take the Encoder
     argument if you've created a new encoding scheme.

insert
     The insert method accepts one of three things as an argument, a) an
     CODE reference (such as an anonymous subroutine or a reference to a
     subroutine), b) an Object or c) a string that contains the package
     name.  If you insert an Object then insert returns the id of that
     object in the internal object list.

extract
     The extract method returns an object that has been insert'ed.  The
     argument is the Id of the object you insert.

store
     The store method returns the flattened container ready for shipping.

register
     The register method evals each of the methods stored inside the TOM
     compartment

restore
     restore is optionally exported, and is used to turn a flattened TOM
     object into a real perl object.

BUGS
====

   There are probably loads.  I've not had time to test this on any machine
other than my own,  so your milage may vary.  Remember, this is a beta
version.  3.02 will be the full bugfixed release.

AUTHOR
======

   James A. Duncan <j@mesduncan.co.uk>

SEE ALSO
========

   perl(1)

A base class for translucency
*****************************

NAME
====

   Class::Translucent - A base class for translucency

SYNOPSIS
========

     package My::Class;
     BEGIN {
         use Class::Translucent  ({
             name    => 'sparrow',
             item2   => 'else',
             attr    => { one => 'two', two => 'three', three => 'one' },
             events  => [ 'buy', 'grow', 'sell', 'eat', 'sleep' ],
         });

     use base qw{Class::Translucent};
         }

     sub new {
         my $self = shift;

     return $self->SUPER::new( @_ );
         }

     package main;

     my $o = new My::Class;
     print $o->name;             # Prints 'sparrow'
     $o->name( 'robin' );        # Set the per-object value
     print $o->name;             # Prints 'robin'
     print My::Class->name;      # Prints 'sparrow'

EXPORTS
=======

   Nothing by default.

REQUIRES
========

   See Carp, Data/Dumper,

   Actually, Data::Dumper is only required for debugging, so this module
will eventually only need Carp.

DESCRIPTION
===========

   This is an abstract base class that provides functionality for
translucent attributes in its derivatives. A translucent attribute is an
attribute which has a class-wide default. A class's attributes are set in
a template, from which all class and instance method calls initially
get/set their data. However, once an object has stored a value, it loses
its translucency, and thereafter returns its own distinct value. For more
information about translucency, see Tom Christiansen's excellent *OO
Tutorial for Class Data in Perl*, which can be found at
<http://language.perl.com/misc/perltootc.html>.

   In order for your class to usefully inherit from Class::Translucent, it
needs to tell Class::Translucent about itself via a template. This
template should be a hash or hash reference containing keys for all the
translucent attributes of your class, along with default values for each
one.

   There are several methods for defining this template. If you have class
data that needs to be accessed before any instances of your class are
created, you can pass the template as the argument to the 'use' statement,
like so:

     use Class::Translucent ({ attribute => 'defaultValue' });

   You can also define a package global named the same thing as the last
part of your package (eg., if you class is called
`HTML::Graphics::Vector', the hash should be
`%HTML::Graphics::Vector::Vector'). When Class::Translucent's constructor
is called as a superclass constructor from your class (or one of its
parent classes) and it doesn't already have a template registered for your
class, it will look for such a hash, and if it is found, use it as the
class's template.

   You can also pass a hash reference as the first argument (well, second
if you're counting the method invocation argument), which will then be
used as the class template instead.

   In any case, as soon as the template is defined, Class::Translucent
auto-generates translucent accessor methods for the attributes you've
specified in the template, skipping any that may already be defined.

   The constructor returns an empty hashref blessed into the calling class.

   *TODO: More docs*

AUTHOR / PERSON TO BLAME
========================

   Michael Granger <ged@FaerieMUD.org> based on ideas from *Tom's OO
Tutorial for Class Data in Perl* (see Perltootc (perl.info))
by Tom Christiansen.

   Copyright (c) 1999, 2000, The FaerieMUD Consortium. All rights reserved.

   This module is free software. You may use, modify, and/or redistribute
this software under the terms of the Perl Artistic License. (See
http://language.perl.com/misc/Artistic.html)

TO DO
=====

   * Do template interpolation in the method template accessor methods
     instead of in the code generation itself. This would mean that
     subclassing would not obligate one to returning templates.

   * Add per-class translucent data so that derivative class B's
     attributes are inherited from superclass A, but remain distinct for
     each class. Can probably accomplish this by iterating over
     @{"${class}::ISA"}, and fetching the parent class's hash and merging
     it with our own.

   * Package-qualify object data members ala Damian Conway's
     `Tie::SecureHash'.

   * Better documentation

   * Better test suite (or any test suite?)

BUGS
====

Unintuitive translucency with complex datatypes
     Operations other than a simple set() are ambiguous for complex
     datatypes. For example, push adds an element to an array - so if an
     array attribute is translucent, should `pushAttribute()' called as an
     object method push the given value onto a new empty array, or should
     it make a copy of the class data first, and push the new element onto
     it?

     THe copy-on-write behaviour is the current behaviour, but will need
     some rigorous testing to make sure it conforms to Perl's
     do-what-I-mean.

Cluttered BEGIN blocks
     In order for class methods to be callable immediately after the `use
     Class::Translucent', the import() function must do the method
     generation. This requires that the class template be mangled into the
     argument to use, which is perhaps ugly and unintuitive to some. I
     can't see any way around it, though, as it has to occur in a BEGIN
     block in order to guarantee that the generated methods exist before
     the constructor is called. Otherwise, setting class-wide data must
     wait until the first instance is created.

"Subroutine 'sub' redefined..." warnings with overridden methods
     Accessor methods for translucent attributes are generated at load
     time, and overriding subs are defined after that. This can cause
     warnings to be issued when the methods are encountered in the derived
     class. This problem doesn't exist when the methods are created during
     the call to the constructor, as the method-generation code won't
     clobber a method which is already defined, but then you have to
     guarantee that no method will be called as a class method before the
     first object is constructed. You could resort to calling the
     constructor from within the package itself, but ACK! =:) Things will
     still work as is, but spurious warnings can be confusing for those
     who don't RTFM.

     You can also cause the warnings to disappear by prototyping the
     methods you wish to override before the `use Class::Translucent'
     call, but that's unintuitive.

Reload problems
     When redefining a class during a reload, there is no current
     mechanism for re-generating the accessor methods. There should be
     some method that can be called which will clear at least the
     `%Classes' hash in the closure so a class's template can be reloaded.
     Perhaps some mechanism for clobbering existing accessors would also
     be desirable.

     Another related problem - do Perl internals care if a method gets
     clobbered?  Does Perl do caching of method lookups, and, if so, what
     will happen if the cached method is undefined during the life of the
     program? Randal Schwartz suggests modifying the @ISA, which will
     cause cached methods to be discarded, but I haven't yet tested this.

GLOBALS
=======

Configuration Globals
---------------------

%AccessCheck
     Method generation templates for the access-check part of each method.
     Attributes which are prefixed with a single underscore ('_') are
     considered 'protected', and the accessor methods generated for it may
     only be called from within the defining class or one of its
     derivatives. Attributes which are prefixed with two or more
     underscores are considered 'private', and may only be accessed from
     within the defining class itself. All other attributes are considered
     public, and may be accessed from any package.

     The code contained in these templates contain special tokens '`%%
     ATTRIBUTE %%'', and '`%% CLASS %%'', which will be replaced,
     respectively, with the attribute name and the name of the class for
     which they are being generated.

%AccessorCode
     Method generation templates for the scoping part of the generated
     methods. Attributes with a leading capital are considered to be of
     class scope only, and calls to its accessors always modify and/or
     return the class data. All other attributes are considered
     translucent, and reference the class data if no specific value has
     been set for the object in which the accessor was called, or if the
     accessor method is called as a class rather than an instance method.

     The code in these templates can contain the same tokens as the
     %AccessCheck global, and they are subject to the same substitution at
     method-generation.

     Note that the attribute passed to later chunks of the method will
     always be a reference to the needed attribute, even if the attribute
     is already a reference. This is to make it easier later on to modify
     the attribute without knowing exactly where the thing being modified
     lives.

%MethodTemplates
     Method generation templates for various datatypes, keyed by type.
     These templates are used to create the meat of the generated accessor
     methods. The code they contain will be passed a reference to the
     attribute to operate on in a scalar called $attribute, and the rest
     of the argument list will be untouched.

     The word 'attribute' in the key is replaced in the generated method
     with the name of the attribute. For example, if you had a key named
     'bargleAttribute', an attribute called 'name' would result in a
     generated method called 'bargleName'. Leading underscores in an
     attribute name are always translated to the beginning of the method
     name, so if the attribute above was instead called '__name', then the
     generated method would be '__bargleName'. Attributes with leading
     capitalization result in leading capitalization in the generated
     method name as well. Eg., an attribute called 'Name' would result in
     a method named 'BargleName', and an attribute called '_Name' would
     generate a method called '_BargleName'.

     The methods in the 'default' key/value pair are given to every
     datatype, and can be overidden by the more specific datatype
     key/value pair. This can be used to establish some default behaviour
     for an accessor, and then override it for specific datatypes.

METHODS
=======

*import( \%template )*
     Autogenerates methods for the calling class. This method can either
     be called automatically from a use statement, or can be called
     explicitly. Note that overriding one of the methods provided by this
     function may result in a 'subroutine redefined' warning, as they
     won't yet exist when import() is called, typically. This is probably
     harmless.

*importToLevel( $level, \%template )*
     Autogenerates methods for the class indicated by the stackframe
     specified by level. This can be useful when you want to override the
     import() method, but still use Class::Translucent's method
     generation. Idea borrowed from Exporter's export_to_level().

Constructor Methods
-------------------

*new( @args )*
     Create and return a new hash reference blessed into your class. If
     accessors have not already been generated for your class, they will
     be generated from the constructor. Existing (overridden) methods will
     be preserved.

Protected Methods
-----------------

*_buildAccessors( $class[, \%template] )*
     Build translucent data accessor methods for the specified class
     (package), using the template specified either by the optional second
     argument, or if the second argument is not passed, the template as
     defined in the class itself. This template should be synonymous with
     the last part of the package name, so that the template for
     `My::Derived::Class' will be called `%My::Derived::Class::Class'.
     This function

*_buildMethodCode( $attributeName, $codeTemplate, $package )*
     Build code for a method specified by the attribute name, with the
     specified code template and bound for the specified package.

*_makeMethodName( $attribute, $methodPrototype )*
     Make and return a method name for the specified attribute with the
     specified method name prototype.

Static Methods
--------------

*AccessCheck( $accessorType )*
     Return a method generation template for the access-check part of a
     generated method based on the accessor type specified. The type can
     be one of 'public', 'protected', or 'private'. See the configuration
     global of the same name for more information.

*AccessorCode( $accessorType )*
     Return a method generation template for the scoping part of a
     generated method based on the accessor type specified. If the
     accessor type is 'class', a template appropriate for static methods
     is returned. If the specified type is 'instance', then a template
     appropriate for instance methods is returned. See the configuration
     global of the same name for more information.

*MethodTemplates( $dataType )*
     Return a hashref of method generation templates for the specified
     datatype. See the documentation for the MethodTemplate configuration
     hash for more information.

Build and print hierarchical information such as directory trees and C++ classes.
*********************************************************************************

NAME
====

   `Class::Tree' - Build and print hierarchical information such as
directory trees and C++ classes.

SYNOPSIS
========

     use Class::Tree;

     # Or ...
     # use Class::Tree qw($root);

     # 1. A directory tree.
     my($dir1)  = 'someDir/someSubdir';
     my($tree1) = new Class::Tree;
     $tree1 -> buildDirTree($dir1, ['CVS']);
     $tree1 -> writeTree();

     # 2. A C++ class tree.
     use Cwd;
     my($currentDir) = cwd();
     my($dir2)       = 'someDir/someSubdir'; # Contains *.h. See t/family.h.
     my($origin)     = 'Root';
     my($tree2)      = new Class::Tree;
     $tree2 -> buildClassTree($dir2, $origin, $currentDir);
     print "Class tree\n----------\n";
     $tree2 -> writeTree();
     print "\n";
     print "Class list\n----------\n";
     $tree2 -> writeClassList();

DESCRIPTION
===========

   The `Class::Tree' module provides a simple way of building:

   * Directory trees

   * C++ class trees

ENVIRONMENT VARIABLE PERCEPS
============================

   I assume $ENV{'PERCEPS'} is the directory containing the C++ parser
perceps, or perceps.pl. So, you must define this variable before calling
buildClassTree().

THE HASH REFERENCE $classRef -> {'root'}
========================================

   This is an alias for $root. See below.

THE HASH REFERENCE $root
========================

   This points to the root of the tree.

METHOD: buildClassTree($dir, $fontName, $baseDir)
=================================================

   Call this to initiate processing by the C++ parser 'perceps'.

   The directories $dir and $baseDir are passed to 'perceps'.

   $fontName is a string used to label the root of the tree.

   Then call writeTree() and/or writeClassList().

METHOD: buildDirTree($dir, [qw/dirs to ignore/])
================================================

   Call this to build a memory image of a directory tree. Use the 2nd
parameter to specify a list of directories to ignore.

   Then call writeTree().

METHOD: writeClassList()
========================

   Call this after calling buildClassTree(), to print the C++ class
structure.

METHOD: writeTree()
===================

   Call this after calling buildClassTree() or buildDirTree(), to print
the directory structure.

INSTALLATION
============

   You install `Class::Tree', as you would install any perl module library,
by running these commands:

     perl Makefile.PL
     make
     make test
     make install

   If you want to install a private copy of `Class::Tree' in your home
directory, then you should try to produce the initial Makefile with
something like this command:

     perl Makefile.PL LIB=~/perl
     	or
     perl Makefile.PL LIB=C:/Perl/Site/Lib

   If, like me, you don't have permission to write man pages into unix
system directories, use:

     make pure_install

   instead of make install. This option is secreted in the middle of p 414
of the second edition of the dromedary book.

WARNING re Perl bug
===================

   As always, be aware that these 2 lines mean the same thing, sometimes:

   * $self -> {'thing'}

   * $self->{'thing'}

   The problem is the spaces around the ->. Inside double quotes, "...",
the first space stops the dereference taking place. Outside double quotes
the scanner correctly associates the $self token with the {'thing'} token.

   I regard this as a bug.

AUTHOR
======

   `Class::Tree' was written by Ron Savage *<rpsavage@ozemail.com.au>* in
1997.

LICENCE
=======

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Base class for virtual base classes.
************************************

NAME
====

   Class::Virtual - Base class for virtual base classes.

SYNOPSIS
========

     package My::Virtual::Idaho;
     use base qw(Class::Virtual);

     __PACKAGE__->virtual_methods(qw(new foo bar this that));

     package My::Private::Idaho;
     use base qw(My::Virtual::Idaho);

     # Check to make sure My::Private::Idaho implemented everything
     my @missing = __PACKAGE__->missing_methods;
     die __PACKAGE__ . ' forgot to implement ' . join ', ', @missing
         if @missing;

     # If My::Private::Idaho forgot to implement new(), the program will
     # halt and yell about that.
     my $idaho = My::Private::Idaho->new;

     # See what methods we're obligated to implement.
     my @must_implement = __PACKAGE__->virtual_methods;

DESCRIPTION
===========

   This is a base class for implementing virtual base classes (what some
people call an abstract class).  Kinda kooky.  It allows you to explicitly
declare what methods are virtual and that must be implemented by
subclasses.  This might seem silly, since your program will halt and catch
fire when an unimplemented virtual method is hit anyway, but there's some
benefits.

   The error message is more informative.  Instead of the usual "Can't
locate object method" error, you'll get one explaining that a virtual
method was left unimplemented.

   Subclass authors can explicitly check to make sure they've implemented
all the necessary virtual methods.  When used as part of a regression
test, it will shield against the virtual method requirements changing out
from under the subclass.

   Finally, subclass authors can get an explicit list of everything
they're expected to implement.

   Doesn't hurt and it doesn't slow you down.

Methods
-------

virtual_methods
          Virtual::Class->virtual_methods(@virtual_methods);
          my @must_implement = Sub::Class->virtual_methods;

     This is an accessor to the list of virtual_methods.  Virtual base
     classes will declare their list of virtual methods.  Subclasses will
     look at them.  Once the virtual methods are set they cannot be undone.

     XXX I'm tempted to make it possible for the subclass to override the
     XXX virtual methods, perhaps add to them.  Too hairy to think about
     for XXX 0.01.

missing_methods
          my @missing_methods = Sub::Class->missing_methods;

     Returns a list of methods Sub::Class has not yet implemented.

CAVEATS and BUGS
================

   Autoloaded methods are currently not recognized.  I have no idea how to
solve this.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Class/Virtually/Abstract,

Compile-time enforcement of Class::Virtual
******************************************

NAME
====

   Class::Virtually::Abstract - Compile-time enforcement of Class::Virtual

SYNOPSIS
========

     package My::Virtual::Idaho;
     use base qw(Class::Virtually::Abstract);

     __PACKAGE__->virtual_methods(qw(new foo bar this that));

     package My::Private::Idaho;
     use base qw(My::Virtual::Idaho);

     sub new { ... }
     sub foo { ... }
     sub bar { ... }
     sub this { ... }
     # oops, forgot to implement that()!!  Whatever will happen?!

     # Meanwhile, in another piece of code!
     # KA-BLAM!  My::Private::Idaho fails to compile because it didn't
     # fully implement My::Virtual::Idaho.
     use My::Private::Idaho;

DESCRIPTION
===========

   This subclass of Class::Virtual provides *compile-time* enforcement.
That means subclasses of your virtual class are required to implement all
virtual methods or else it will not compile.

BUGS and CAVEATS
================

   Because this relies on import() it is important that your classes are
used instead of required.  This is a problem, and I'm trying to figure a
way around it.

   Also, if a subclass defines its own import() routine (why would a class
need to export stuff?  I've done it) Class::Virtually::Abstract's
compile-time checking is defeated.

   Got to think of a better way to do this besides import().

AUTHOR
======

   Original idea from Ben Tilly's AbstractClass
http://www.perlmonks.org/index.pl?node_id=44300&lastnode_id=45341

   Embraced and Extended by Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Class/Virtual,

Visitor and Iterator extensions to Class::Template
**************************************************

NAME
====

   Class::Visitor - Visitor and Iterator extensions to Class::Template

SYNOPSIS
========

     use Class::Visitor;

     visitor_class 'CLASS', 'SUPER', { TEMPLATE };
     visitor_class 'CLASS', 'SUPER', [ TEMPLATE ];

     $obj = CLASS->new ();
     $iter = $obj->iter;
     $iter = $obj->iter ($parent, $array, $index);

     $obj->accept($visitor, ...);
     $obj->children_accept($visitor, ...);
     $obj->children_accept_ARRAYMEMBER ($visitor, ...);
     $obj->push_ARRAYMEMBER($value[, ...]);
     $value = $obj->pop_ARRAYMEMBER;
     $obj->as_string ([$context[, ...]]);
     $obj->ARRAYMEMBER_as_string ([$context[, ...]]);

     $iter inherits the following from Class::Iter:

     $iter->parent;
     $iter->is_iter;
     $iter->root;
     $iter->rootpath;
     $iter->next;
     $iter->at_end;
     $iter->delegate;
     $iter->is_same ($obj);

DESCRIPTION
===========

   `Class::Visitor' extends the getter/setter functions provided by
`Class::Template' for CLASS by defining methods for using the Visitor and
Iterator design patterns.  All of the Iterator methods are inherited from
`Class::Iter' except `iter'.

   CLASS is the name of the new class, SUPER the superclass of this class
(will define `@ISA'), and TEMPLATE is as defined in `Class::Template'.

   `$obj-'iter> returns a new iterator for this object.  If parent, array,
and index are not defined, then the new iterator is treated as the root
object.  Except as inherited from `Class::Iter' or as defined below,
methods for `$iter' and $obj work the same.

   The accept methods cause a callback to `$visitor' with `$self' as the
first argument plus the rest of the arguments passed to accept.  This is
implemented like:

     sub accept {
         my $self = shift; my $visitor = shift;
         $visitor->visit_MyClass ($self, @_);
     }

   `children_accept' calls accept on each object in the array field named
`contents'.  `children_accept_*ARRAYMEMBER*' does the same for
*ARRAYMEMBER*.

   Calling accept methods on iterators always calls back using iterators.
Calling accept on non-iterators calls back using non-iterators.  The
latter is significantly faster.

   push and pop act like their respective array functions.

   as_string returns the concatenated scalar values of the array field
named `contents', possibly modified by `$context'.
`*ARRAYMEMBER*_as_string' does the same for *ARRAYMEMBER*.

   Visitor handles scalars specially for `children_accept' and as_string.
In the case of `children_accept', Visitor will create an iterator in the
class `Class::Scalar::Iter' with the scalar as the delegate.

   In the case of as_string, Visitor will use the string unless
`$context->{cdata_mapper}' is defined, in which case it returns the result
of calling the `cdata_mapper' subroutine with the scalar and the remaining
arguments.  The actual implementation is:

     &{$context->{cdata_mapper}} ($scalar, @_);

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), Class::Template(3), Class::Iter(3).

   The package `SGML::SPGrove' uses `Class::Visitor' extensively.

base class to treat unhandled method calls as errors
****************************************************

NAME
====

   Class::WhiteHole - base class to treat unhandled method calls as errors

SYNOPSIS
========

     package Bar;

     # DBI inherits from DynaLoader which inherits from AutoLoader
     # Bar wants to avoid this accidental inheritance of AutoLoader.
     use base qw(Class::WhiteHole DBI);

DESCRIPTION
===========

   Its possible to accidentally inherit an AUTOLOAD method.  Often this
will happen if a class somewhere in the chain uses AutoLoader or defines
one of their own.  This can lead to confusing error messages when method
lookups fail.

   Sometimes you want to avoid this accidental inheritance.  In that case,
inherit from Class::WhiteHole.  All unhandled methods will produce normal
Perl error messages.

BUGS & CAVEATS
==============

   Be sure to have Class::WhiteHole before the class from which you're
inheriting AUTOLOAD in the ISA.  Usually you'll want Class::WhiteHole to
come first.

   If your class inherits autoloaded routines this class may cause them to
stop working.  Choose wisely before using.

   White holes are only a hypothesis and may not really exist.

COPYRIGHT
=========

   Copyright 2000 Michael G Schwern <schwern@pobox.com> all rights
reserved.  This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Class/BlackHole,

ClearCase-specific subclass of Argv
***********************************

NAME
====

   ClearCase::Argv - ClearCase-specific subclass of Argv

SYNOPSIS
========

     # OO interface
     use ClearCase::Argv;
     ClearCase::Argv->dbglevel(1);
     # Note how the command, flags, and arguments are separated ...
     my $describe = ClearCase::Argv->new('desc', [qw(-fmt %c)], ".");
     # Run the basic "ct describe" command.
     $describe->system;
     # Run it with with stderr turned off.
     $describe->stderr(0)->system;
     # Run it without the flags.
     $describe->system(-);
     # Create label type iff it doesn't exist
     ClearCase::Argv->new(qw(mklbtype -nc XX))
     	    if ClearCase::Argv->new(qw(lstype lbtype:XX))->stderr(0)->qx;

     # functional interface
     use ClearCase::Argv qw(ctsystem ctexec ctqx);
     ctsystem('pwv');
     my @lsco = ctqx(qw(lsco -avobs -s));
     # Similar to OO example: create label type iff it doesn't exist
     ctsystem(qw(mklbtype XX)) if !ctqx({stderr=>0}, "lstype lbtype:XX");

   *There are more examples in the ./examples subdir that comes with this
module. Also, the test script is designed as a demo and benchmark; it's
probably your best source for cut-and-paste code.*

DESCRIPTION
===========

   This is a subclass of *Argv* for use with ClearCase.  It overrides the
Argv->prog() method to recognize the fact that ClearCase commands have two
words, e.g. "cleartool checkout".

   It also provides a special method `'ipc_cleartool'' which, as the name
implies, enables use of the IPC::ClearTool module such that subsequent
cleartool commands are sent to a coprocess.

   *ClearCase::Argv is in most ways identical to its base class, so see
"perldoc Argv" for substantial further documentation.*

IPC::ClearTool INTERFACE
========================

   The `'ipc_cleartool'' method creates an IPC::ClearTool object and sends
subsequent commands to it. This method is highly context-sensitive:

   * When called with no arguments and a non-void context, it returns the
     underlying ClearTool object (in case you want to use it directly).

   * When called with a non-zero argument it creates an IPC::ClearTool
     object; if this fails for any reason a warning is printed and
     execution continues in 'normal mode'. The warning may be suppressed
     or turned to a fatal error by specifying different true values; see
     examples below.

   * When called with an argument of 0, it shuts down any existing
     ClearTool object; any further executions would revert to 'normal
     mode'.

Examples
--------

     # use IPC::ClearTool if available, else continue silently
     ClearCase::Argv->ipc_cleartool(1);
     # use IPC::ClearTool if available, else print warning and continue
     ClearCase::Argv->ipc_cleartool(2);
     # same as above since default == 2
     ClearCase::Argv->ipc_cleartool;
     # use IPC::ClearTool, die if not available
     ClearCase::Argv->ipc_cleartool(3);
     # shut down the IPC::ClearTool coprocess
     ClearCase::Argv->ipc_cleartool(0);
     # Use the IPC::ClearTool object directly
     ClearCase::Argv->ipc_cleartool->cmd('pwv');

   Typically `ipc_cleartool' will be used as a class method to specify a
place for all cleartool commands to be sent. However, it may also be
invoked on an object to associate just that instance with a coprocess.

FUNCTIONAL INTERFACE
====================

   For those who don't like OO style, or who want to convert existing
scripts with the least effort, the *execution methods* are made available
as traditional functions. Examples:

     use ClearCase::Argv qw(ctsystem ctexec ctqx);
     my $cwv = ctqx(pwv -s);
     ctsystem('mklbtype', ['-global'], 'FOO') && exit $?>>8;
     my @vobs = ctqx({autochomp=>1}, 'lsvob -s');

   If you prefer you can override the "real" Perl builtins. This is easier
for converting an existing script which makes heavy use of `system(),
exec(), or qx()':

     use ClearCase::Argv qw(system exec qv);
     my $cwv = qv(cleartool pwv -s);
     system('cleartool', 'mklbtype', ['-global'], 'FOO') && exit $?>>8;
     my @vobs = qv({autochomp=>1}, 'lsvob -s');

   Note that when using an overridden `system()' et al you must still
specify 'cleartool' as the program, whereas `ctsystem()' and friends
handle that.

CAREFUL PROGRAMMERS WANTED
==========================

   If you're the kind of programmer who tends to execute whole strings
such as `system("cleartool pwv -s")' or who uses backquotes in a void
context, this module won't help you much. These are bad habits regardless
of whether you use ClearCase::Argv and you should strive to overcome them.

STICKINESS
==========

   A subtlety: when an execution attribute is set in a void context, it's
*"sticky"*, meaning that it's set until explicitly reset. But in a
non-void context the new value is temporary or *"non-sticky"*; it's pushed
on a stack and popped off after being read once. This applies to both
class and instance uses. It's done this way to allow the following
locutions:

     ClearCase::Argv->stdout(0);	# turn off stdout for all objects
     $obj->stdout(0);		# turn off stdout for this object, forever
     $obj->stdout(0)->system;	# suppress stdout, this time only

   This allows you to set up an object with various sticky attributes and
keep it around, executing it at will and overriding other attrs
temporarily. In the example below, note that another way of setting sticky
attrs is shown:

     my $obj = ClearCase::Argv->new({autofail=>1, autochomp=>1});
     my $view = $obj->argv('pwv -s')->qx;
     my $exists = $obj->argv('lstype', 'brtype:FOO')->autofail(0)->qx;

   Here we keep an object with attrs 'autochomp' and 'autofail' (autofail
means to exit on any failure) around and use it to exec whichever commands
we want. While checking to see if a type exists, we suppress autofail
temporarily. On the next use the object will have both attributes again.

BUGS
====

   I suspect there are still some special quoting situations unaccounted
for in the quote method. This will need to be refined over time. Bug
reports or patches gratefully accepted.

PORTABILITY
===========

   ClearCase::Argv should work on all ClearCase platforms. It's primarily
been tested on Solaris 7 and NT 4.0, with CC 3.2.1 and 4.0, using
Perl5.004, 5.005, and 5.6. The CAL stuff doesn't work with CC versions <
3.2.1.

FILES
=====

   This is a subclass of *Argv* and thus requires it to be installed.  If
running in *ipc mode* it will also need IPC::ClearTool.

SEE ALSO
========

   perl(1), Argv, IPC::ClearTool, IPC::ChildSafe

AUTHOR
======

   David Boyce <dsb@world.std.com>

COPYRIGHT
=========

   Copyright (c) 1999,19100 David Boyce. All rights reserved.  This Perl
program is free software; you may redistribute it and/or modify it under
the same terms as Perl itself.

Handle clearprompt in a portable, convenient way
************************************************

NAME
====

   ClearCase::ClearPrompt - Handle clearprompt in a portable, convenient
way

SYNOPSIS
========

     use ClearCase::ClearPrompt qw(clearprompt clearprompt_dir);

     # boolean usage
     my $rc = clearprompt(qw(yes_no -mask y,n -type ok -prompt), 'Well?');

     # returns text into specified variable (context sensitive).
     my $txt = clearprompt(qw(text -pref -pro), 'Enter text data here: ');

     # asynchronous usage - show dialog box and continue
     clearprompt(qw(proceed -mask p -type ok -prompt), "You said: $txt");

     # prompt for a directory (not supported natively by clearprompt cmd)
     my $dir = clearprompt_dir('/tmp', "Please choose a directory");

DESCRIPTION
===========

   Native ClearCase provides a utility (*clearprompt*) for collecting user
input or displaying messages within triggers. However, usage of this tool
is awkward and error-prone, especially in multi-platform environments.
Often you must create temp files, invoke clearprompt to write into them,
open them and read the data, then unlink them. In many cases this code
must run seamlessly on both Unix and Windows systems and is replicated
throughout many trigger scripts. ClearCase::ClearPrompt abstracts this
dirty work without changing the interface to *clearprompt*.

   The `clearprompt()' function takes the exact same set of flags as the
eponymous ClearCase command, e.g.:

     my $response = clearprompt('text', '-def', '0', '-pro', 'Well? ');

   except that the `-outfile' flag is unnecessary since creation, reading,
and removal of this temp file is managed internally.

   In a void context, clearprompt() behaves asynchronously; i.e. it
displays the dialog box and returns so that execution can continue.  In
any other context it waits for the dialog's button to be pushed and
returns the appropriate data type.

   The clearprompt() function always leaves the return code of the
clearprompt command in $? just as `system()' would.  If the prompt was
interrupted via a signal, the function returns the undefined value.

DIRECTORY PROMPTING
===================

   The clearprompt command has no way to prompt for a directory, so this
module provides a separate `clearprompt_dir()' function which implements
it via "clearprompt list" and `opendir/readdir/closedir'.  Usage is

     use ClearCase::ClearPrompt qw(clearprompt_dir);
     $dir = clearprompt_dir($starting_dir, $prompt_string);

   This is a little awkward to use since it doesn't use a standard
directory-chooser interface but it works. There's no way to create a
directory within this interface, though.

NOTE
====

   *An apparent undocumented "feature" of clearprompt(1) is that it
catches SIGINT (Ctrl-C) and provides a status of 4 rather than returning
the signal number in $? according to normal (UNIX) signal semantics.*  We
fix that up here so it looks like a normal signal 2.  Thus, if
`clearprompt()' returns undef the signal number is reliably in $? as it's
documented to be.

PORTING
=======

   This package is known to work fine on Solaris 2.5.1/perl5.004_04,
Solaris 7/perl5.6, and Windows NT 4.0SP3/5.005_02.  As these platforms are
quite different, this should take care of any *significant* portability
issues but please send reports of tweaks needed for other platforms to the
address below.

AUTHOR
======

   David Boyce <dsb@world.std.com>

   Copyright (c) 1999,2000 David Boyce. All rights reserved.  This Perl
program is free software; you may redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   clearprompt(1), perl(1)

Synchronize a tree of files with a tree of elements
***************************************************

NAME
====

   ClearCase::SyncTree - Synchronize a tree of files with a tree of
elements

SYNOPSIS
========

     # Create a 'synctree' object.
     my $sync = ClearCase::SyncTree->new;
     # Tell it where the files are coming from ...
     $sync->srcbase($sbase);
     # Tell it where they're going to ...
     $sync->dstbase($dbase);
     # Supply the list of files to work on (relative or absolute paths).
     $sync->srclist(keys %files);
     # Compare src and dest lists and figure out what to do.
     $sync->analyze;
     # Create new elements in the target area.
     $sync->add;
     # Update existing files which differ between src and dest.
     $sync->modify;
     # Remove any files from dest that aren't in src.
     $sync->subtract;
     # Check in the changes.
     $sync->checkin;

   See the enclosed *synctree* script for full example usage.

DESCRIPTION
===========

   This module provides an infrastructure for programs which want to
*synchronize* a set of files, typically a subtree, with a similar
destination subtree in VOB space.  The enclosed *synctree* script is an
example of such a program.

   The source area may be in a VOB or may be a regular filesystem; the
destination area must be in a VOB. Methods are supplied for adding,
subtracting, and modifying destination files so as to make that area look
identical to the source.

   Symbolic links are supported, even on Windows (of course in this case
the source filesystem must support them, which is only likely in the event
of an MVFS->MVFS transfer). Note that the text of the link is transported
verbatim from source area to dest area; thus relative symlinks may no
longer resolve in the destination.

CONSTRUCTOR
-----------

   Use `ClearCase::SyncTree->new' to construct a SyncTree object, which
can then be filled in and used via the instance methods below.

INSTANCE METHODS
----------------

   Following is a brief description of each supported method. Examples are
given for all methods that take parameters; if no example is given usage
may be assumed to look like:

     $obj->method;

   * ->srcbase

     Provides the base by which to 'relativize' the incoming pathnames.
     E.g.  with a *srcbase* of */tmp/x* the incoming file */tmp/x/y/z*
     will become *y/z* and will be deposited under the *dstbase* (see) by
     that path. Example:

          $obj->srcbase('/var/tmp/newstuff');

   * ->dstbase

     Provides the root of the tree into which to place the relative paths
     derived from *srcbase* as described above. Example:

          $obj->dstbase('/vobs/tps/newstuff');

   * ->srclist/->srcmap

     There are two ways to specify the list of incoming files. They may be
     provided as a simple list via *srclist*, in which case they'll be
     relativized as described above and deposited in *dstbase*, or they can
     be specified via *srcmap* which allows the destination file to have a
     different name from the source.

     *srclist* takes a list of input filenames. These may be absolute or
     relative; they will be canonicalized and then relativized internally.

     *srcmap* is similar but takes a hash mapping input filenames to their
     destination counterparts.

     Examples:

          $obj->srclist(@ARGV);	# check in the named files

          my %filemap = (x/y/z.c => 'x/y/z.cxx', a/b => 'foo');
          $obj->srcmap(%filemap);	# check in the named files

   * ->analyze

     After the object knows its *srcbase*, *dstbase*, and input file
     lists, this method compares the source and target trees and
     categorizes the required actions into *additions* (new files in the
     destination area), modifications (those which exist but need to be
     updated) and *subtractions* (those which no longer exist in the
     source area).  After analysis is complete, these actions may be taken
     via the add, modify, and subtract methods as desired.

   * ->add

     Takes the list of *additions* as determined by the analyze method and
     creates them as new elements.

   * ->modify

     Takes the list of modifications as determined by the analyze method
     and updates them in the destination tree.

   * ->subtract

     Takes the list of *subtractions* as determined by the analyze method
     and rmname's them in the destination tree.

   * ->label

     Labels the new work. The label type can be specified as a parameter;
     otherwise it will be taken from the attribute previously set by the
     *lbtype* method.

     Labeling consists of a *mklabel -recurse* from *dstbase* down,
     followed by labeling of parent directories from *dstbase* up to the
     vob root. Example:

          $obj->label('FOO');

   * ->checkin

     Checks in all checkouts under the *dstbase* area.

   * ->cleanup

     Undoes all checkouts under the *dstbase* area.

   * ->fail

     Calls the cleanup method, then exits with a failure status. This is
     the default exception handler; a different handler can be registered
     via the *err_handler* method (see).

   * ->err_handler

     Registers an exception handler to be called upon failure of any
     cleartool command. Call with 0 to have no handler Pass it a code ref
     to register a function, with an object and method name to register a
     method. Examples:

          $obj->err_handler(0);		# ignore cleartool errors
          $obj->err_handler(\&func);		# register func() for errors
          $obj->err_handler($self, 'method');	# register $obj->method

   * ->protect

     Sets an attribute which causes the checkin method to align file
     permissions after checking in. By default this attribute is set on
     UNIX, unset on Windows. Example:

          $obj->protect(0);

   * ->reuse

     Attempt "element reuse". Before creating a new file with *mkelem*,
     look through its directory's version tree to see if another of the
     same name exists in any other version. If so, assume the new file
     intended to be the same element and link the old and new names.

          $obj->reuse(1);

   * ->ctime

     Sets a boolean indicating whether to throw away the timestamp of the
     source file and give modified files their checkin date instead. This
     flag is false by default (i.e. checkins have *-ptime* behavior).

   * ->no_cr

     By default, checkins initiated by the checkin method are done one at
     a time using the *-from* flag. This will preserve config records in
     the case where the input file is a derived object.  Setting the
     *no_cr* attribute causes checkins to be done in one big `"cleartool
     ci"' operation, which is faster but loses CR's.

   * ->no_cmp

     This attribute causes all files which exist in both src and dest areas
     to be considered modified by the analyze method.

   * ->cmp_func

     Sets or returns the coderef that's used to compare the source and
     destination files. The default is *File::Compare::compare()* but can
     be modifed by passing in a ref to your preferred function, like so:

          $obj->cmp_func(\&my_compare_function);

     A replacement function should set $! on failure.

   * ->comment

     Provides a comment to be used by the checkin method. The default
     comment is `"By:$0"'. Example:

          $obj->comment("your comment here");

   * ->eltypemap

     In case the eltype of a particular file or set of files needs to be
     overridden at creation time. Example:

          $obj->eltypemap('\.(ht|x)ml$' => 'compressed_file');

BUGS
====

   * Subtraction of symlinks is currently unimplemented (it's just a little
     corner case I haven't gotten to).

   * If a file is removed via the ->subtract method and later added back
     via ->add, the result will be a new element (aka *evil twin*).
     SyncTree does not have the smarts to find the old element of the same
     name and relink to it. This could be handled but I haven't yet needed
     it.

   * I have not tested SyncTree in snapshot views and would not expect it
     to work out of the box, though the fixes would be largely mechanical.
     At the least, though, expect it to be slower in a snapshot view.

AUTHOR
======

   Based on code originally written by Paul D. Smith
<pausmith@nortelnetworks.com>.  Paul's version was based on the Bourne
shell script 'citree' delivered as sample code with ClearCase.

   Rewritten for Unix/Win32 portability by David Boyce <dsb@world.std.com>
in 8/1999, then reorganized into a module in 1/2000. This module no longer
bears the slightest resemblance to citree.

COPYRIGHT
=========

   Copyright 1997,1998 Paul D. Smith and Bay Networks, Inc.

   Copyright 1999,2000 David Boyce (dsb@world.std.com).

   This script is distributed under the terms of the GNU General Public
License.  You can get a copy via ftp://ftp.gnu.org/pub/gnu/ or its many
mirrors.  This script comes with NO WARRANTY whatsoever, not even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

STATUS
======

   This is currently ALPHA code and thus I reserve the right to change the
API incompatibly. At some point I'll bump the version suitably and remove
this warning, which will constitute an (almost) ironclad promise to leave
the interface alone.

PORTING
=======

   This module is known to work on Solaris 2.6-7 and Windows NT 4.0SP3-5,
and with perl 5.004_04 and 5.6.  As these platforms cover a fairly wide
range there should be no *major* portability issues, but please send bug
reports or patches to the address above.

SEE ALSO
========

   perl(1), ClearCase::Argv(3), Getopt::Long(3), IPC::ChildSafe(3)

general-purpose wrapper for *cleartool*
***************************************

NAME
====

   ClearCase::Wrapper - general-purpose wrapper for *cleartool*

SYNOPSIS
========

   This perl module functions as a wrapper for *cleartool*, allowing the
command-line interface of *cleartool* to be extended or modified. It
allows defaults to be changed, new flags to be added to existing
*cleartool* commands, or entirely new *cleartool* commands to be
synthesized.

CLEARTOOL ENHANCEMENTS
======================

   * CATCS
       1. New *-expand* flag Follows all include statements recursively in
          order to print a complete config spec. When used with the
          *-cmnt* flag, comments are stripped from this listing.

       2. New *-sources* flag Prints all files involved in the config spec
          (the *config_spec* file itself plus any files it includes).

       3. New *-start* flag Prints the preferred *initial working
          directory* of a view by examining its config spec. If the
          conventional string C"<##:Start: dir"> is present then the value
          of dir is printed. Otherwise no output is produced. The *workon*
          command (see) uses this value.  E.g., using *workon* instead of
          *setview* with the config spec:

               ##:Start: /vobs_fw/src/java
               element * CHECKEDOUT
               element * /main/LATEST

          would automatically cd to `/vobs_fw/src/java' within the set
          view.

       4. New *-rdl* flag Prints the value of the config spec's
          C"<##:RDL:> attribute.

   * CI/CHECKIN

     Extended to handle the *-dir/-rec/-all/-avobs* flags.

     Extended to allow *symbolic links* to be checked in (by operating on
     the target of the link instead).

     Extended to implement a *-diff* flag, which runs a **diff -pred**
     command before each checkin so the user can see his/her changes while
     typing the comment.

     Automatically supplies *-nc* to checkins if the element list consists
     of only directories (since directories get a default comment).

     Implements a new *-revert* flag. This causes identical (unchanged)
     elements to be unchecked-out instead of being checked in.

     Since checkin is such a common operation, an unadorned ci is
     "promoted" to *ci -diff -dir -revert* to save typing.

   * COMMENT

     For each ClearCase object specified, dump the current comment into a
     temp file, allow the user to edit it with his/her favorite editor,
     then change the objects's comment to the results of the edit. This is
     useful if you mistyped a comment and want to correct it.

     The *-new* flag causes it to ignore the previous comment.

     See *edattr* for editor selection rules.

   * DIFF

     Extended to handle the *-dir/-rec/-all/-avobs* flags.

     Improved default: if given just one element and no flags, assume
     *-pred*.

     Extended to implement -n, where n is an integer requesting that the
     diff take place against the n'th predecessor.

   * DIFFCS

     New command.  *Diffcs* dumps the config specs of two specified views
     into temp files and diffs them. If only one view is specified,
     compares against the current working view's config spec.

   * EDATTR

     New command, inspired by the *edcs* cmd.  *Edattr* dumps the
     attributes of the specified object into a temp file, then execs your
     favorite editor on it, and adds, removes or modifies the attributes as
     appropriate after you exit the editor.  Attribute types are created
     and deleted automatically.  This is particularly useful on Unix
     platforms because as of CC 3.2 the Unix GUI doesn't support
     modification of attributes and the quoting rules make it difficult to
     use the command line.

     The environment variables WINEDITOR, VISUAL, and EDITOR are checked
     in that order for editor names. If none of the above are set, the
     default editor used is vi on UNIX and notepad on Windows.

   * EDIT

     Convenience command. Same as 'checkout' but execs your favorite editor
     afterwards. Takes all the same flags as checkout, plus *-ci* to check
     the element back in afterwards. When *-ci* is used in conjunction with
     *-diff* the file will be either checked in or un-checked out depending
     on whether it was modified.

     The aggregation flags *-dir/-rec/-all/-avo* may be used, with the
     effect being to run the editor on all checked-out files in the named
     scope. Example: *"ct edit -all"*.

   * GREP

     New command. Greps through past revisions of a file for a pattern, so
     you can see which revision introduced a particular function or a
     particular bug. By analogy with *lsvtree*, grep searches only
     "interesting" versions unless *-all* is specified.

     Flags *-nnn* are accepted where *nnn* represents the number of
     versions to go back. Thus `grep -1 foo' would search only the
     predecessor.

   * LOCK

     New *-allow* and *-deny* flags. These work like *-nuser* but operate
     incrementally on an existing *-nuser* list rather than completely
     replacing it. When *-allow* or *-deny* are used, *-replace* is
     implied.

     When *-iflocked* is used, no lock will be created where one didn't
     previously exist; the *-nusers* list will only be modified for
     existing locks.

   * LSPRIVATE

     Extended to recognize *-dir/-rec/-all/-avobs*.  Also allows a
     directory to be specified such that 'ct lsprivate .' restricts output
     to the cwd, etc. This directory arg may be used in combination with
     *-dir* etc. Output in these cases is relative to the current or
     specified directory if the *-rel/ative* flag is used.

     The flag *-type d|f* is also supported with the usual semantics.

     The flag *-visible* flag removes files not currently visible in the
     view.

     The *-ext* flag sorts the output by extension.

   * LSVIEW

     Extended to recognize the general *-me* flag, restricting the search
     namespace to <username>_*.

   * LSVTREE

     Modified default to always use -a flag.

   * MKELEM

     Extended to handle the *-dir/-rec* flags, enabling automated mkelems
     with otherwise the same syntax as original. Directories are also
     automatically checked out as required in this mode. *Note that this
     automatic directory checkout is only enabled when the candidate list
     is derived via the *-dir/-rec* flags*.  If the *-ci* flag is present,
     any directories automatically checked out are checked back in too.

     By default, only regular view-private files are considered by
     *-dir|-rec*.  The *-do* flag causes derived objects to be made into
     elements as well.

   * MKLABEL

     The new *-up* flag, when combined with *-recurse*, also labels the
     parent directories of the specified *pname*s all the way up to their
     vob tags.

   * MKBRTYPE,MKLBTYPE

     Modification: if user tries to make a type in the current VOB without
     explicitly specifying -ordinary or -global, and if said VOB is
     associated with an admin VOB, then by default create the type as a
     global type in the admin VOB instead. **In effect, this makes -global
     the default iff a suitable admin VOB exists**.

   * MKVIEW

     Extended in the following ways:

       1. New *-me* flag Supports the *-me* flag to prepend $LOGNAME to
          the view name, separated by an underscore. This enables the
          convention that all user views be named *<username>_<whatever>*.

       2. Default view-storage location Provides a standard default
          view-storage path which includes the user's name. Thus a user
          can simply type *"mkview -me -tag foo"* and the view will be
          created as <username>_foo with the view storage placed in a
          default location determined by the sysadmin.

       3. New *-clone* flag This allows you to specify another view from
          which to copy the config spec and other properties. Note that it
          does not copy view-private files from the old view, just the
          view properties.

   * MOUNT

     This is a Windows-only enhancement: on UNIX, *mount* behaves correctly
     and we do not mess with its behavior. On Windows, *cleartool mount
     -all* gives an error for already-mounted VOBs for some reason; these
     are now ignored as on UNIX. At the same time, VOB tags containing /
     are normalized to \ so they'll match the registry, and an extension
     is made to allow multiple VOB tags to be passed to one *mount*
     command.

   * SETVIEW

     ClearCase 4.0 for Windows completely removes *setview* functionality,
     but this wrapper emulates it by attaching the view to a drive letter
     and cd-ing to that drive. It supports all the flags *setview* for CC
     3.2.1/Windows supported (*-drive*, *-exec*, etc.) and adds a new one:
     *-persistent*.

     If the view is already mapped to a drive letter that drive is used.
     If not, the first available drive working backwards from Z: is used.
     Without *-persistent* a drive mapped by setview will be unmapped when
     the setview process is existed.

     The setview emulation sets *CLEARCASE_ROOT* for compatibility and adds
     a new EV *CLEARCASE_VIEWDRIVE*.

     UNIX setview functionality is left alone.

   * SETCS

     Adds a *-clone* flag which lets you specify another view from which
     to copy the config spec.

     Adds a *-sync* flag. This is similar to *-current* except that it
     analyzes the view dependencies and only flushes the view cache if the
     *compiled_spec* file is out of date with respect to the *config_spec*
     source file or any file it includes. In other words: *-sync* is to
     *-curr* as `make foo.o' is to `cc -c foo.c'.

     Adds a *-expand* flag, which "flattens out" the config spec by
     inlining the contents of any include files.

   * WORKON

     New command, similar to *setview* but provides hooks to cd to a
     preferred *initial working directory* within the view and to set up
     any required environment variables. The *initial working directory*
     is defined as the output of *ct catcs -start* (see).

     If a file called *.viewenv.pl* exists in the *initial working
     directory*, it's read before starting the user's shell. This file uses
     Perl syntax and must end with a "1;" like any `require-d' file.  Any
     unrecognized arguments given to *workon* following the view name will
     be passed on to `.viewenv.pl' in `@ARGV'. Environment variables
     required for builds within the setview may be set here.

   * UNCO

     Extended to accept (and ignore) the standard comment flags for
     consistency with other cleartool cmds.

     Extended to handle the -dir/-rec/-all/-avobs flags.

   * WINKIN

     The *-tag* flag allows you specify a local file path plus another
     view; the named DO in the named view will be winked into the current
     view.

     The *-vp* flag, when used with *-tag*, causes the "remote" file to be
     converted into a DO if required before winkin is attempted. See the
     *winkout* extension for details.

   * WINKOUT

     The *winkout* pseudo-cmd takes a set of view-private files as
     arguments and, using clearaudit, makes them into derived objects. The
     config records generated are meaningless but the mere fact of being a
     DO makes a file eligible for forced winkin.

     If the *-promote* flag is given, the view scrubber will be run on the
     new DO's. This has the effect of promoting them to the VOB and winking
     them back into the current view.

     If a meta-DO filename is specified with *-meta*, this file is created
     as a DO and caused to reference all the other new DO's, thus defining
     a *DO set* and allowing the entire set to be winked in using the
     meta-DO as a hook. E.g. assuming view-private files X, Y, and Z
     already exist:

          ct winkout -meta .WINKIN X Y Z

     will make them into derived objects and create a 4th DO ".WINKIN"
     containing references to the others. A subsequent

          ct winkin -recurse -adirs /view/extended/path/to/.WINKIN

     from a different view will wink all four files into the current view.

     Accepts *-dir/-rec/-all/-avobs*, a file containing a list of files
     with *-flist*, or a literal list of view-private files. When using
     *-dir/-rec/-all/-avobs* to derive the file list only the output of
     `lsprivate -other' is considered unless *-do* is used; *-do* causes
     existing DO's to be re-converted.

     The *"-flist -"* flag can be used to read the file list from stdin.

GENERAL FEATURES
================

   * symlink expansion

     Before processing a checkin or checkout command, any symbolic links on
     the command line are replaced with the file they point to. This allows
     allowd developers to operate directly on symlinks for ci/co.

   * -M flag

     As a convenience feature, the -M flag runs all output through your
     pager. Of course `"ct lsh -M foo"' saves only a few keystrokes over
     "ct lsh foo | more" but for heavy users of shell history the more
     important feature is that it preserves the value of ESC-_ (`ksh -o
     vi') or !$ (csh).

   * -me -tag

     Introduces a global convenience/standardization feature: the flag
     *-me* in the context of a command which takes a *-tag view-tag*
     causes *"$LOGNAME"* to be prefixed to the tag name with an
     underscore.  This relies on the fact that even though *-me* is a
     native cleartool flag, at least through CC4.0 no command which takes
     *-tag* also takes *-me* natively. For example:

          % <wrapper-context> mkview -me -tag myview ...

     The commands *setview, startview, endview, and lsview* also take
     *-me*, such that the following commands are equivalent:

          % <wrapper-context> setview dboyce_myview
          % <wrapper-context> setview -me myview

CONFIGURATION
=============

   Various degrees of configurability are supported:

   * Global Enhancements and Extensions

     To add a global override for 'cleartool xxx', simply define a
     subroutine 'xxx' after the __END__ token in Wrapper.pm or in
     lib/ClearCase/Wrapper/Site.pm and re-run 'make install'.  When doing
     so it's a good idea to document it in POD format right above the sub
     and make the appropriate addition to the "Usage Message Extensions"
     section.  Also, if the command has an abbreviation (e.g.  checkout/co)
     you should add that to the "Command Aliases" section.

     This override subroutine is called with @ARGV as its parameter list
     (and  @ARGV is also available directly of course). The sub can do
     whatever it likes but it's strongly recommended that
     *ClearCase::Argv* be used to run any cleartool subcommands and its
     base class *Argv* be used to run other programs. These modules
     provide value for UNIX/Windows portability and aid in parsing flags
     into different categories where required. See their PODs for full
     documentation.

   * Personal Preference Setting

     As well as allowing for site-wide enhancements to be made in
     Wrapper.pm, a hook is also provided for individual users (who must be
     knowledgeable about both ClearCase and Perl) to set their own
     defaults.  If the file `~/.clearcase_profile.pl' exists it will be
     read before launching any of the sitewide enhancements. Note that this
     file is passed to the Perl interpreter and thus has access to the full
     array of Perl syntax.

   * Sitewide ClearCase Comment Defaults

     This distribution comes with a file called *clearcase_profile* which
     is installed as part of the module. If the user has no
     *clearcase_profile* file in his/her home directory and if
     CLEARCASE_PROFILE isn't already set, CLEARCASE_PROFILE will
     automatically be pointed at this supplied file. This allows the
     administrator to set sitewide defaults of checkin/checkout comment
     handling using the syntax supported by ClearCase natively but without
     each user needing to maintain their own config file or set their own
     EV.

   * CLEARCASE_WRAPPER_NATIVE

     This environment variable may be set to suppress all extensions,
     causing the wrapper to behave just like an alias to cleartool (but
     slower).

DIAGNOSTICS
===========

   The flag *-/dbg=1* prints all "real" cleartool operations executed by
the wrapper to stderr as long as the extension in use was coded with
ClearCase::Argv, which is the case for all supplied extensions.

INSTALLATION
============

   I recommend you install the *cleartool.plx* file to some global dir
(e.g. /usr/local/bin), then symlink it to ct or whatever short name you
prefer.  Unfortunately, there's no equivalent mechanism for wrapping GUI
access to clearcase. For Windows the strategy is similar but requires a
"ct.bat" redirector instead of a symlink. See "ct.bat.sample" in the
distribution.

   To install or update a global enhancement you must re-run "make
install".  Also, don't forget to check that the contents of
`lib/ClearCase/Wrapper/clearcase_profile' are what you want users to have
by default.

COPYRIGHT
=========

   Copyright (c) 1997,1998,1999,2000 David Boyce (dsb@world.std.com). All
rights reserved.  This Perl program is free software; you may redistribute
it and/or modify it under the same terms as Perl itself.

site-specific overrides for ClearCase::Wrapper
**********************************************

NAME
====

   ClearCase::Wrapper::Site - site-specific overrides for
ClearCase::Wrapper

SYNOPSIS
========

   Provides a place to put site-specific enhancements to
ClearCase::Wrapper, in order to ease merging of updates.

CLEARTOOL ENHANCEMENTS
======================

   * SITE_EXAMPLE

     This is an example of a site-specific enhancement. It's nothing but a
     demo which prints out its arguments and flags when run.

SEE ALSO
========

   perl(1), ClearCase::Wrapper

Perl extension for a recurrsive copy of nested objects.
*******************************************************

NAME
====

   Clone - Perl extension for a recurrsive copy of nested objects.

SYNOPSIS
========

     use Clone;

     push @Package::A::ISA, 'Clone';

     $a = new Package::A;
     $b = $a->clone;

     # or
     use Clone qw(clone);

     $b = clone($a,1);

DESCRIPTION
===========

   The Clone module provides a clone method for making recursive copies of
nested hash, array, and scalar objects, as well as tied variables. An
optional parameter can be used to limit the depth of the copy.

AUTHOR
======

   Ray Finch, ray@classmates.com

   Copyright 2000 Ray Finch.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1), Storable(3).

Perl module for accessing dBASE files
*************************************

NAME
====

   CodeBase - Perl module for accessing dBASE files

ABSTRACT
========

   The CodeBase module provides a Perl 5 class for accessing dBASE files.
It is a development of an earlier unpublished Perl 4 extension.

SYNOPSIS
========

   Programs using the CodeBase module must include the line:

     use CodeBase;

   The functions that the module provides are listed below, grouped
according to type of function.

File manipulation functions
---------------------------

     $fh = CodeBase::open($filename, @options);
     $fh = CodeBase::create($filename, @fielddefs);
     $fh->DESTROY();

File information functions
--------------------------

     $n_recs    = $fh->reccount();
     $recsize   = $fh->recsize();
     $n_fields  = $fh->fldcount();
     @names     = $fh->names();
     $type      = $fh->type($fieldname);
     @fieldinfo = $fh->fieldinfo();

Navigation functions
--------------------

     $recno = $fh->recno();
     $fh->goto($recno);
     $fh->skip($n_recs);
     $fh->bof();
     $fh->eof();

Record manipulation functions
-----------------------------

     @values = $fh->fields();
     $value  = $fh->field($fieldname);
     $fh->set_field($fieldname, $value);
     $fh->new_record(@values);
     $fh->replace_record(@values);

     $fh->deleted();
     $fh->delete_record($recno);

     $fh->flush($tries);
     $fh->pack($compress_memo);

     $fh->lock($what, $tries);
     $fh->unlock();

Index manipulation functions
----------------------------

     $n_tags  = $fh->tag_count();
     @tags    = $fh->tags();
     @taginfo = $fh->taginfo($index_name);
     $fh->open_index($name);
     $fh->create_index($name, $taginfo);
     $fh->reindex();
     $fh->set_tag();
     $fh->seek($key);

     $q = $fh->prepare_query($expr [, $sortexpr [, $desc]]);
     $q->execute;
     $q->next([$skip]);

Miscellaneous functions
-----------------------

     CodeBase::option(@options);
     $errno   = CodeBase::errno();
     $errmsg  = CodeBase::errmsg($errno);
     $version = CodeBase::libversion;
     $dbtype  = CodeBase::dbtype;

DESCRIPTION
===========

   Each function provided by the CodeBase module is described below.  The
module uses the CodeBase library from Sequiter Software Inc., which is a C
library providing database management functions for dBASE files.

File manipulation functions
---------------------------

   Existing dBASE files can be opened with open() and new files created
with create().  Files are implicit closed by the DESTROY method, which is
called when all references to the internal file handle go out of scope.

open FILENAME [, OPTION-KEYWORD ...]
     Opens the named dBASE file and returns a file handle which can be used
     in other CodeBase functions.  The filename should omit the `.dbf'
     extension.  The following options keywords are recognized:
     `"readonly"', `"noindex"' or `"exclusive"' (`"ro"' is a synonym for
     `"readonly"' and `"x"' is a synonym for `"exclusive"').  Option
     keywords are case-insensitive.  For example to open the file
     `books.dbf' in read-only mode, without opening the production index:

          $fh = CodeBase::open("books", "readonly", "noindex");

create FILENAME, FIELD-DEFS =item create FILENAME, FIELD-DEF-ARRAY, INDEX-TAG
     Creates a new dBASE file using the field definitions specified and
     returns a file that can be used in other CodeBase functions.  The
     field definitions consist of an array of alternating pairs of field
     name and field type.

          @field_defs = ( "F1" => "C10",
                          "F2" => "N4" );
          $fh = CodeBase::create("test", @field_defs);

     The field types are as follows:

          Type       Code      Length    Decimals
          -------------------------------------------
          Character    C     1 to 65533     0
          Date         D     8              0
          F.P.         F     1 to 19     0 to len - 2
          Logical      L     1              0
          Memo         M     10             0
          Numeric      N     1 to 19     0 to len - 2

     Note: create does not create a production index file - use
     create_index with an empty filename.  The facility to create a
     production index at the same time that a database is created may be
     added later.  Field and tag information arguments would then be
     specified as references.

DESTROY FILEHANDLE
     The DESTROY function is not normally called explicitly.  It is invoked
     automatically when all copies of the file handle generated by open()
     or create() go out of scope.  For example:

          {
              my($fh2);
              {
                  $fh1 = CodeBase::open("test");
                  $fh2 = $fh1;
              }
              # $fh1 is destroyed here, but $fh2 contains a copy of the file
              # handle so CodeBase::DESTROY is not called yet.
             }
             # $fh2 is destroyed as it goes out of scope, so CodeBase::DESTROY
             # is invoked.

Navigation functions
--------------------

recno
     Returns the current record number.  It is equivalent to the dBASE
     `RECNO()' function.

          $recno = $fh->recno

     If the file has just been opened, created or packed there is no
     current record number and `recno()' will return undef.

goto RECNO
     Positions the current record of the database file to the specified
     record.  It is equivalent to the dBASE GOTO statement.

          $fh->goto($recno);

     The record number for `CodeBase::goto' should be an integer between 1
     and `CodeBase::reccount'.  It can also take one of the keywords:
     `"TOP"' or `"BOTTOM"'.  The keywords `"START"' and `"FIRST"' are
     accepted as synonyms for `"TOP"', and `"END"' and `"LAST"' as
     synonyms for `"BOTTOM"'.  Only the first character of a keyword is
     significant and case is not significant.

     Normally goto returns 1 to signify success; if an error occurs it
     returns undef.  The error code can then be retrieved with errno.

skip N_RECORDS
     Skips forwards or backwards in the database file by the specified
     number of fields.  It is equivalent to the dBASE SKIP statement.  The
     number of fields defaults to one.

          $fh->skip($n_records);

     Normally skip returns the new record number; if an error occurs it
     returns undef.  The error code can then be retrieved with errno.

bof
     Returns a boolean value indicating whether the current record is
     positioned before the first record.  It is equivalent to the dBASE
     `BOF()' function.

          if ($fh->bof()) ...

eof
     Returns a boolean value indicating whether the current record is
     positioned at the end of the file.  It is equivalent to the dBASE
     `EOF()' function.

          while (!$fh->eof()) ...

Record handling functions
-------------------------

reccount
     Returns the number of records in the database file.  It is equivalent
     to the dBASE `RECCOUNT()' function.

          $n_recs = $fh->reccount();

recsize
     Returns the size in bytes of records in the database file (including
     the deletion flag).  It is equivalent to the dBASE `RECWIDTH()'
     function.

          $recsize = $fh->recsize();

fldcount
     Returns the number of fields per record for the database file.

          $n_fields = $fh->fldcount();

     It is equivalent to the dBASE `FLDCOUNT()' function.

names
     Returns the field names as an array.

          @names = $fh->names();

type FIELD
     Returns the type of the named field as a string.

          $type = $fh->type("field1");

fieldinfo [NAMES]
     Returns an array containing information about the specified fields or
     about all fields if no fields are specified.  For example if the
     database open on $fh contains, amongst others, the fields `field1'
     and `field2' as a 12 character field and a 10 byte numeric field with
     3 decimal places respectively then:

     @names = ("field1, "field2");     $fh->fieldinfo(@names);

     would return an array containing the values:

          ("field1", "C12", "field2", "N10.3")

     This is a shortcut function.  The same information can be built up by
     using names and type:

          foreach $name ($fh->names)
          {
              push(@results, ($name, $fh->type($name)));
          }

values [NAMES]
     Returns an array containing the values of each of the specified
     fields, or of all fields if no field names are specified.

          @values = $fh->values("field1", "field3");

field NAME
     Returns the value of the named field.

          $value = $fh->field("field1");

set_field NAME, VALUE
     Sets the value of the named field to the specified value.

          $fh->set_field("field1", $value);

     If the field is a date field the value should be formatted in dBASE
     date format (e.g. `"YYYYMMDD"') or should be one of the keywords
     `"YESTERDAY"', `"TODAY"' or `"TOMORROW"' (the keywords are not case
     sensitive) or may be a number of days to the current date specified as
     `+num' or `-num'.  For example to set a date field to a week's time:

          $fh->set_field("date", "+7");

new_record VALUES
     Creates a new record using the values specified.  `VALUES' may be an
     array of field values:

          $fh->new_record({ firstname => "Fred",
                            surname   => "Bloggs"  });

     or a reference to a hash, the keys of which are the field names:

          $fh->new_record("Bloggs", "Fred");

     If the values are supplied as an array, a value must be supplied for
     each field.  If the values are supplied as a hash unspecified fields
     are filled with blanks.  Excess array values or hash keys that are not
     names of fields are simply ignored.  The handling of date fields is as
     described under set_field.

replace_record VALUES
     Replaces the fields of the current record with the values specified.
     As with new_record `VALUES' may be an array of field values:

          $fh->replace_record("Bloggs", "Fred");

     or a reference to a hash, the keys of which are the field names.

          $fh->replace_record({ firstname => "Fred",
                                surname   => "Bloggs"  });

     In the former case a value must be supplied for each field, while in
     the latter case unspecified fields are unchanged.  Excess values or
     hash keys that are not names of fields are ignored.  The handling of
     date fields is as described under set_field.

deleted
     Returns a boolean value indicating whether the current record is
     deleted.

          if ($fh->deleted()) ...

     This function is equivalent to the dBASE `DELETED()' function.

delete_record [RECNO]
     Deletes the record specified or the current record if called without
     a record number.

          $fh->delete_record($recno);

recall_record [RECNO]
     Recalls the record specified or the current record if called without a
     record number.  (Not yet implemented).

flush [TRIES]
     Flushes to file any outstanding changes (made by `set_field()'.
     Records need to be locked while changes are written.  `TRIES' is the
     number of attempts that should be made to aquire the lock.  Subsequent
     attempts are made with a one second interval.

pack COMPRESS-MEMO-FLAG
     Packs the database file removing deleted records.  If flag parameter
     is specified as true then memo fields are compressed at the same time:

          $fh->pack(1);

lock WHAT [, TRIES]
     Locks the specified record or the whole file.  `WHAT' should either
     be `"FILE"' or a record number (the current record can be referred to
     as `"."'.  `TRIES' is the number of attempts that should be made to
     aquire the lock.  Subsequent attempts are made with a one second
     interval.

unlock
     Removes any existing locks on the file.

Index Handling Functions
------------------------

   A production index file is automatically opened when a database file is
opened, if it exists unless  the noindex option is specified.  An index
file can be opened with the open_index method.

tagcount
     Returns the number of index tags.

          $n_tags = $fh->tagcount();

tags
     Returns an array containing the names of all the tags associated with
     the database file.

          @tags = $fh->tags();

set_tag TAG
     Sets the current index tag to the named tag.  If no tag is specified
     the currently selected tag is deselected.

          $fh->set_tag("TAG1") || die "Cannot set index tag.\n";

taginfo
     Returns an array containing information about tags.  Each element of
     the array is a reference to a hash containing attributes of the tag.
     The attributes are name, expression, filter, order and `duplicates'.

     This array is suitable for passing to create_index, for example for
     copying the index structure of a file:

          @taginfo = $fh1->taginfo;
          $fh2->create_index(undef, \@taginfo);

create_index NAME, TAGINFO
     Creates a new index file.  The index file name is specified by NAME
     and should not include the `.mdx' extension.  If NAME is specified as
     undef or "" a production index is created.

     The new index file will contain the tags specified in the `TAGINFO'
     argument: an array passed by reference, each element of which is a
     hash containing attributes of the particular tag.  Valid attributes
     are: name, expression, filter, `duplicates' and order.

     For example to create a production index with three tags:

          $fh->create_index( undef,
                             [ { name       => "TAG1",
                                 expression => "F1",
                                 duplicates => "KEEP" },
                               { name       => "TAG2",
                                 expression => "F2",
                                 order      => "DESCENDING" },
                               { name       => "TAG3",
                                 expression => "UPPER(F3)" }
                             ] );

open_index [ NAME ]
     Opens the specified index file.  The name should not include the
     `.mdx' extension.  If the name is not specified then the production
     index is opened.

seek VALUE
     Seeks in the currently selected index tag for a match for the
     specified value.  Returns 1 if a match is found otherwise the
     undefined value is returned and the error code can be retrieved with
     CodeBase::errno.

     The search value must be formatted correctly for the index, for
     example if an index is generted on `STR(F1)', where `F1' is a numeric
     field of width 6, the value be formatted as a right aligned
     6-character integer:

          $fh->seek("    42");

     For string valued index keys a search value shorter than the tag
     expression length will be matched on the initial substring, e.g.
     `"FRED"' would match `"FREDERICK"'.

Query functions
---------------

   The query functions interface to the CodeBase Relate/Query module.  The
interface is currently incomplete.  All that is provided is the facility
to query a single file.

   A query is prepared (in a similar manner to the Perl DBI query) and
then executed and the result set stepped through.  The functions are:

     $q = $fh->prepare_query($expr [, $sortexpr [, $desc]]);
     $q->execute;
     $q->next([$skip]);

   An example of the usage would be:

     $q = $fh->prepare_query('AGE >= 18 .AND. AGE <= 65', 'AGE', 1);
     $q->execute;
     while (my $r = $q->next) {
         @fields = $r->values;
         # do some processing.
     }

   I intend to allow more complex queries to be built up in a Perl-ish
manner, but I haven't come up with an interface yet.

Miscellaneous functions
-----------------------

CodeBase::option OPTIONS
     Sets configuration options for the CodeBase module.  The only option
     currently offered is trace.  Setting this to a non-zero value enables
     the output of tracing, which can be helpful in debugging.

          # Enable tracing
          CodeBase::option("trace=1");

          # Disable tracing
          CodeBase::option("trace=0");

CodeBase::errno
     Returns the error code for the last operation.

CodeBase::errmsg ERRNO
     Returns an explanatory string for the error code ERRNO

CodeBase::libversion
     Returns the version of the CodeBase library that the module was
     compiled and linked against.

CodeBase::dbformat
     Returns the XBase file format that the library and module were
     compiled for.  This will be one of "dBASE IV", "FoxPro" or "Clipper".

ERRORS
======

   Functions return a value on success and undef on error.  The error code
can be determined by calling CodeBase::errno, and the equivalent error
message by calling CodeBase::errmsg.

   A number of variables are defined as symbolic names for the CodeBase
error codes.  Thes variables are all defined in the `CodeBase' package and
so need to be referred with the package prefix (e.g. `$CodeBase::e4close').

   *General disk access errors*

     $e4close          =  -10;  # Closing file
     $e4create         =  -20;  # Creating file
     $e4len            =  -30;  # Determining file length
     $e4len_set        =  -40;  # Setting file length
     $e4lock           =  -50;  # Locking file
     $e4open           =  -60;  # Opening file
     $e4read           =  -70;  # Reading file
     $e4remove         =  -80;  # Removing file
     $e4rename         =  -90;  # Renaming file
     $e4seek           = -100;  # Seeking to a file position
     $e4unlock         = -110;  # Unlocking file
     $e4write          = -120;  # Writing to file

   *Data file specific errors*

     $e4data           = -200;  # File is not a data file
     $e4field_name     = -210;  # Unrecognized field name
     $e4field_type     = -220;  # Unrecognized field type
     $e4record_len     = -230;  # Record length too large

   *Index file specific errors*

     $e4entry          = -300;  # Tag entry missing
     $e4index          = -310;  # Not a correct index file
     $e4tag_name       = -330;  # Tag name not found
     $e4unique         = -340;  # Unique key error

   *Expression evaluation errors*

     $e4comma_expected = -400;  # Comma or bracket expected
     $e4complete       = -410;  # Expression not complete
     $e4data_name      = -420;  # Data file name not located
     $e4length_err     = -422;  # IIF() needs parameters of same length
     $e4not_constant   = -425;  # SUBSTR() and STR() need constant parameters
     $e4num_params     = -430;  # Number of parameters is wrong
     $e4overflow       = -440;  # Overflow while evaluating expression
     $e4right_missing  = -450;  # Right bracket missing
     $e4type_sub       = -460;  # Sub-expression type is wrong
     $e4unrec_function = -470;  # Unrecognized function
     $e4unrec_operator = -480;  # Unrecognized operator
     $e4unrec_value    = -490;  # Unrecognized value
     $e4unterminated   = -500;  # Unterminated string

   *Optimization errors*

     $e4opt            = -610;  # Optimization error
     $e4opt_suspend    = -620;  # Optimization removal error
     $e4opt_flush      = -630;  # Optimization file flushing failure

   *Relation errors* (not used)

     $e4relate         = -710;  # Relation error
     $e4lookup_err     = -720;  # Matching slave record not located

   *Severe errors*

     $e4info           = -910;  # Unexpected information
     $e4memory         = -920;  # Out of memory
     $e4parm           = -930;  # Unexpected parameter
     $e4result         = -950;  # Unexpected result

   For detailed explanations of these codes refer to the *CodeBase
Reference Guide* by Sequiter Software Inc.

RESTRICTIONS
============

   Tags cannot be added to existing index files - the entire index file
must be recreated.  This is a restriction imposed by CodeBase 5.1.

FUTURE DIRECTIONS
=================

   Record fields may be made into an associative array allowing their
values to be accessed and set with the following syntax:

     $val = $file->{"F1"};
     # rather than:  $val = $file->value("F1");

     $file->{"F1"} = $newval;
     # rather than:  $file->set_value("F1", $newval);

   The query functionality will be expanded.

COMPATIBILTY
============

CodeBase Functions
------------------

     CodeBase 6.4        CodeBase 5.1         CodeBase.pm
     ============        ============         ===========

     code4calcCreate     expr4calc_create
     code4calcReset      expr4calc_reset
     code4close          d4close_all	    implicit on exit
     code4connect
     code4data           d4data
     code4dateFormat
     code4dateFormatSet
     code4exit           e4exit
     code4flush          d4flush_files
     code4indexExtension
     code4init           d4init
     code4initUndo       d4init_undo
     code4lock
     code4lockClear
     code4lockFileName
     code4lockItem
     code4lockNetworkId
     code4lockUserId
     code4logCreate
     code4logFileName
     code4logOpen
     code4logOpenOff
     code4optAll
     code4optStart       d4opt_start
     code4optSuspend     d4opt_suspend
     code4timeout
     code4timeoutSet
     code4tranCommit
     code4tranRollback
     code4tranStart
     code4tranStatus
     code4unlock         d4unlock_files
     code4unlockAuto
     code4unlockAutoSet

Data File Functions
-------------------

     CodeBase 6.4        CodeBase 5.1         CodeBase.pm
     ============        ============         ===========

     d4alias             d4alias
     d4aliasSet          d4alias_set
     d4append
     d4appendBlank       d4append_blank
     d4appendStart       d4append_start
     d4blank
     d4bottom
     d4changed
     d4check
     d4close             d4close              undef $fh
     d4create
     d4delete
     d4deleted
     d4eof
     d4field
     d4fieldInfo         d4field_info
     d4fieldJ            d4field_j
     d4fieldNumber       d4field_number
     d4fileName
     d4flush             d4flush               $fh->flush
     d4flushData         d4flush_data
     d4freeBlocks        d4free_blocks
     d4go                d4go                  $fh->go
     d4goBof             d4go_bof
     d4goData            d4go_data
     d4goEof             d4go_eof
     d4index
     d4lock
     d4lockAdd
     d4lockAddAll
     d4lockAddAppend
     d4lockAddFile
     d4lockAll           d4lock_all
     d4lockAppend        d4lock_append
     d4lockFile          d4lock_file		$fh->lock('FILE')
     d4lockIndex         d4lock_index
     d4lockTest          d4lock_test
     d4lockTestAppend    d4lock_test_append
     d4lockTestFile      d4lock_test_file
     d4log
     d4logStatus
     d4memoCompress      d4memo_compress
     d4numFields         d4num_fields		$fh->fldcount
     d4open              d4open                   $fh = CodeBase::open($file ...)
     d4openClone
     d4optimize
     d4optimizeWrite     d4optimize_write
     d4pack              d4pack
     d4packData          d4pack_data
     d4position          d4position
     d4positionSet       d4position_set
     d4recall            d4recall
     d4recCount          d4reccount
     d4recNo             d4recno			$fh->recno
     d4record
     d4recPosition       d4record_position
     d4recWidth          d4record_width		$fh->recsize
     d4refresh           d4refresh                $fh->refresh
     d4refreshRecord     d4refresh_record
     d4reindex           d4reindex
     d4remove
     d4seek              d4seek                   $fh->seek
     d4seekDouble        d4seek_double
     d4seekN             d4seek_n
     d4seekNext
     d4seekNextDouble
     d4seekNextN
     d4skip              d4skip                   $fh->skip
     d4tag               d4tag
     d4tagDefault        d4tag_default
     d4tagNext           d4tag_next
     d4tagPrev           d4tag_prev
     d4tagSelect         d4tag_select
     d4tagSelected       d4tag_selected
     d4tagSync
     d4top               d4top
     d4unlock            d4unlock
     d4write             d4write
     d4writeData         d4write_data
     d4writeKeys         d4write_keys
     d4zapData           d4zap_data

Date Functions
--------------

     date4formatMdx      date4format_mdx
     date4formatMdx2     date4format_mdx2
     date4timeNow        date4time_now

     dfile4updateHeader  d4update_header
     e4exitTest          e4exit_test
     error4code          e4code
     error4set           e4set

     expr4calcDelete     expr4calc_delete
     expr4calcLookup     expr4calc_lookup
     expr4calcMassage    expr4calc_massage
     expr4calcModify     expr4calc_modify
     expr4calcNameChange expr4calc_name_change
     expr4keyConvert     expr4key_convert
     expr4keyLen         expr4key_len

Field Functions
---------------

     f4assignChar        f4assign_char		$fh->field_set($name, $value)
     f4assignDouble      f4assign_double
     f4assignField       f4assign_field
     f4assignInt         f4assign_int
     f4assignLong        f4assign_long
     f4assignN           f4assign_n
     f4assignPtr         f4assign_ptr
     f4memoAssign        f4memo_assign
     f4memoAssignN       f4memo_assign_n
     f4memoFree          f4memo_free
     f4memoLen           f4memo_len
     f4memoNcpy          f4memo_ncpy
     f4memoPtr           f4memo_ptr
     f4memoSetLen        f4memo_set_len
     f4memoStr           f4memo_str

     file4lenSet         file4len_set
     file4lockHook       file4lock_hook
     file4optimizeWrite  file4optimize_write
     file4readAll        file4read_all
     file4readError      file4read_error
     file4seqRead        file4seq_read
     file4seqReadAll     file4seq_read_all
     file4seqReadInit    file4seq_read_init
     file4seqWrite       file4seq_write
     file4seqWriteFlush  file4seq_write_flush
     file4seqWriteInit   file4seq_write_init
     file4seqWriteRepeat file4seq_write_repeat

     i4tagAdd            i4add_tag
     i4tagInfo           i4tag_info

     relate4createSlave  relate4create_slave
     relate4doAll        relate4do
     relate4doOne        relate4do_one
     relate4errorAction  relate4error_action
     relate4freeRelate   relate4free_relate
     relate4matchLen     relate4match_len
     relate4querySet     relate4query_set
     relate4skipEnable   relate4skip_enable
     relate4sortSet      relate4sort_set

     t4addCalc           t4add_calc
     t4uniqueSet         t4unique_set

     tfile4add           t4add(a)->tagFile, b, c
     tfile4block         t4block(a)->tagFile
     tfile4bottom        t4bottom( (a)->tagFile
     tfile4down          t4down( (a)->tagFile
     tfile4dskip         t4dskip(a)->tagFile, b
     tfile4dump          t4dump(a)->tagFile, b, c
     tfile4eof           t4eof(a)->tagFile
     tfile4flush         t4flush(a)->tagFile
     tfile4freeAll       t4free_all(a)->tagFile
     tfile4go            t4go(a)->tagFile, b, c, 0
     tfile4isDescending  t4is_descending(a)->tagFile
     tfile4key           t4key(a)->tagFile
     tfile4position      t4position(a)->tagFile
     tfile4positionSet   t4position_set(a)->tagFile, b
     tfile4recNo         t4recno(a)->tagFile
     tfile4remove        t4remove(a)->tagFile, b, c
     tfile4removeCalc    t4remove_calc(a)->tagFile, b
     tfile4seek          t4seek(a)->tagFile, b, c
     tfile4skip          t4skip(a)->tagFile, b
     tfile4top           t4top(a)->tagFile
     tfile4up            t4up(a)->tagFile
     tfile4upToRoot      t4up_to_root(a)->tagFile

Unsupported functions
---------------------

   Many lower level functions are not directly accessible from
CodeBase.pm.  These include:

   * conversion functions (c4xxx)

   * linked list functions (l4xxx)

   * memory functions (m4xxx)

   * sort functions (sort4xxx)

   * utility functions (u4xxx)

COPYRIGHT AND TRADEMARKS
========================

   The CodeBase module is Copyright (C) 1996-1999, Andrew Ford and Ford &
Mason Ltd.  All rights reserved.  The CodeBase library is copyright
Sequiter Software, Inc.

   CodeBase is a trademark of Sequiter Software, Inc.

AUTHOR
======

   Andrew Ford (andrew@icarus.demon.co.uk)

SEE ALSO
========

   The Perl reference manual, especially the following sections: *perlmod*
(modules), *perldata* (data types), *perlobj* (objects), *perlref*
(references and nested data structures), *perldsc* (data structures
cookbook), *perllol* (manipulating lists of lists).

   The second edition of *Programming Perl* by Larry Wall and Randal L.
Schwarz (O'Reilly and Associates) covers Perl 5.

   The *CodeBase Reference Guide* and the *CodeBase User Guide*, both from
Sequiter Software Inc. cover the underlying C library.

Interface to Bzip2 compression library
**************************************

NAME
====

   Compress::Bzip2 - Interface to Bzip2 compression library

SYNOPSIS
========

     use Compress::Bzip2;

     $dest = Compress::Bzip2::compress($source, [$level]);
     $dest = Compress::Bzip2::decompress($source);

DESCRIPTION
===========

   The *Compress::Bzip2* module provides a Perl interface to the *Bzip2*
compression library (see `' in this node for details about where to get
*Bzip2*). A relevant subset of the functionality provided by *Bzip2* is
available in *Compress::Bzip2*.

   All string parameters can either be a scalar or a scalar reference.

COMPRESSION FUNCTIONS
=====================

   $dest = Compress::Bzip2::compress($string)

   Compress a string using the default compression level, returning a
string containing compressed data.

   $dest = Compress::Bzip2::compress($string, $level)

   Compress string, using the chosen compression level (either 1 or 9).
Return a string containing the compressed data.

   On error undef is returned.

DECOMPRESSION FUNCTIONS
=======================

   $dest = Compress::Bzip2::decompress($string)

   Decompress the data in string, returning a string containing the
decompressed data.

   On error undef is returned.

AUTHOR
======

   The *Compress::Bzip2* module was written by Gawdi Azem
`azemgi@rupert.informatik.uni-stuttgart.de'.

MODIFICATION HISTORY
====================

   1.00 First public release of *Compress::Bzip2*.

extremely leight-weight Lev-Zimpel-Free compression
***************************************************

NAME
====

   Compress::LZF - extremely leight-weight Lev-Zimpel-Free compression

SYNOPSIS
========

     use Compress::LZF;

     $compressed = compress $uncompressed_data;

     $original_data = decompress $compressed;

DESCRIPTION
===========

   LZF is an extremely fast (not that much slower than a pure memcpy)
compression algorithm. It is ideal for applications where you want to save
some space but not at the cost of speed. It is ideal for repetitive data
as well. The module is self-contained and very small (no large library to
be pulled in). It is also free, so there should be no problems
incoporating this module into commercial programs.

   I have no idea wether any patents in any countries apply to this
algorithm, but at the moment it is believed that it is free from any
patents.

FUNCTIONS
=========

$compressed = compress $uncompressed
------------------------------------

   Try to compress the given string as quickly and as much as possible. In
the worst case, the string can enlarge by 1 byte, but that should be the
absolute exception. You can expect a 45% compression ratio on large,
binary strings.

$decompressed = decompress $compressed
--------------------------------------

   Uncompress the string (compressed by compress) and return the original
data. Decompression errors can result in either broken data (there is no
checksum kept) or a runtime error.

SEE ALSO
========

   Other Compress::* modules, especially Compress::LZV1 (an older, less
speedy module that guarentees only 1 byte overhead worst case) and
Compress::Zlib.

   http://liblzf.plan9.de/

AUTHOR
======

   This perl extension and the underlying liblzf were written by Marc
Lehmann <pcg@goof.com> (See also http://liblzf.plan9.de/).

BUGS
====

Interface to LZO compression library
************************************

NAME
====

   Compress::LZO - Interface to LZO compression library

SYNOPSIS
========

     use Compress::LZO;

     $dest = Compress::LZO::compress($source, [$level]);
     $dest = Compress::LZO::decompress($source);
     $dest = Compress::LZO::optimize($source);

     $crc = Compress::LZO::adler32($buffer [,$crc]);
     $crc = Compress::LZO::crc32($buffer [,$crc]);

     LZO_VERSION, LZO_VERSION_STRING, LZO_VERSION_DATE

DESCRIPTION
===========

   The *Compress::LZO* module provides a Perl interface to the *LZO*
compression library (see `' in this node for details about where to get
*LZO*). A relevant subset of the functionality provided by *LZO* is
available in *Compress::LZO*.

   All string parameters can either be a scalar or a scalar reference.

COMPRESSION FUNCTIONS
=====================

   $dest = Compress::LZO::compress($string)

   Compress a string using the default compression level, returning a
string containing compressed data.

   $dest = Compress::LZO::compress($string, $level)

   Compress string, using the chosen compression level (either 1 or 9).
Return a string containing the compressed data.

   On error undef is returned.

DECOMPRESSION FUNCTIONS
=======================

   $dest = Compress::LZO::decompress($string)

   Decompress the data in string, returning a string containing the
decompressed data.

   On error undef is returned.

OPTIMIZATION FUNCTIONS
======================

   $dest = Compress::LZO::optimize($string)

   Optimize the representation of the compressed data, returning a string
containing the compressed data.

   On error undef is returned.

CHECKSUM FUNCTIONS
==================

   Two functions are provided by *LZO* to calculate a checksum. For the
Perl interface, the order of the two parameters in both functions has been
reversed. This allows both running checksums and one off calculations to
be done.

     $crc = Compress::LZO::adler32($string [,$crc]) ;
     $crc = Compress::LZO::crc32($string [,$crc]) ;

AUTHOR
======

   The *Compress::LZO* module was written by Markus F.X.J. Oberhumer
`markus.oberhumer@jk.uni-linz.ac.at'.  The latest copy of the module
should also be found on CPAN in
`modules/by-module/Compress/perl-lzo-x.x.tar.gz'.

   The *LZO* compression library was written by Markus F.X.J. Oberhumer
`markus.oberhumer@jk.uni-linz.ac.at'.  It is available from the LZO home
page at `http://wildsau.idv.uni-linz.ac.at/mfx/lzo.html'.

MODIFICATION HISTORY
====================

   1.00 First public release of *Compress::LZO*.

extremely leight-weight Lev-Zimpel-Vogt compression
***************************************************

NAME
====

   Compress::LZV1 - extremely leight-weight Lev-Zimpel-Vogt compression

SYNOPSIS
========

     use Compress::LZV1;

     $probably_compressed = compress $uncompressed_data;

     $original_data = uncompress $probably_compressed;

DESCRIPTION
===========

   LZV1 is an extremely fast (not that much slower than a pure memcpy)
compression algorithm. It is ideal for applications where you want to save
some space but not at the cost of speed. It is ideal for repetitive data
as well. The module is self-contained and very small (no large library to
be pulled in).

   I have no idea wether any patents in any countries apply to this
algorithm, but at the moment it is believed that it is free from any
patents.

FUNCTIONS
=========

$compressed = compress $uncompressed
------------------------------------

   Try to compress the given string as quickly and as much as possible. In
the worst case, the string can enlarge by at most a single byte. Empty
strings yield empty strings. The uncompressed data string must be smaller
than 16MB (1<<24).

   The compressed is (currently) in one of two forms:

   * a literal 'U', followed by the original, uncompressed data

   * a literal 'L', followed by three bytes (big-endian) uncompressed
length, followed by the actual LZV1 data

$decompressed = decompress $compressed
--------------------------------------

   Uncompress the string (compressed by compress) and return the original
data. Decompression errors can result in either broken data (there is no
checksum kept) or a runtime error.

SEE ALSO
========

   Other Compress::* modules, especially Compress::LZO (for speed) and
Compress::Zlib.

AUTHOR
======

   This perl extension was written by Marc Lehmann <pcg@goof.com> (See
also http://www.goof.com/pcg/marc/). The original lzv1 code was written by
Hermann Vogt and put under the GPL. (There is also a i386 assembler
version that is not used in this module).

   The lzv1 code was accompanied by the following comment:

   The method presented here is faster and compresses better than lzrw1 and
lzrw1-a. I named it lzv for "Lev-Zimpel-Vogt".  It uses ideas introduced
by Ross Williams in his algorithm lzrw1 [R. N. Williams (1991): "An
Extremly Fast ZIV-Lempel Data Compression Algorithm", Proceedings IEEE
Data Compression Conference, Snowbird, Utah, 362-371] and by Fiala and
Green in their algorithm a1 [E. R. Fiala, D. H. Greene (1989): "Data
Compression with Finite Windows", Communications of the ACM, 4, 490-505].
Because lzv differs strongly from both, I hope there will be no patent
problems. The hashing-method has been stolen from Jean-loup Gailly's
(patent free) gzip.

BUGS
====

   It seems that the c-code has _big_ alignment problems :(

Interface to zlib compression library
*************************************

NAME
====

   Compress::Zlib - Interface to zlib compression library

SYNOPSIS
========

     use Compress::Zlib ;

     ($d, $status) = deflateInit( [OPT] ) ;
     ($out, $status) = $d->deflate($buffer) ;
     ($out, $status) = $d->flush() ;
     $d->dict_adler() ;

     ($i, $status) = inflateInit( [OPT] ) ;
     ($out, $status) = $i->inflate($buffer) ;
     $i->dict_adler() ;

     $dest = compress($source) ;
     $dest = uncompress($source) ;

     $gz = gzopen($filename or filehandle, $mode) ;
     $bytesread = $gz->gzread($buffer [,$size]) ;
     $bytesread = $gz->gzreadline($line) ;
     $byteswritten = $gz->gzwrite($buffer) ;
     $status = $gz->gzflush($flush) ;
     $status = $gz->gzclose() ;
     $errstring = $gz->gzerror() ;
     $gzerrno

     $dest = Compress::Zlib::memGzip($buffer) ;
     $dest = Compress::Zlib::memGunzip($buffer) ;

     $crc = adler32($buffer [,$crc]) ;
     $crc = crc32($buffer [,$crc]) ;

     ZLIB_VERSION

DESCRIPTION
===========

   The *Compress::Zlib* module provides a Perl interface to the *zlib*
compression library (see `' in this node for details about where to get
*zlib*). Most of the functionality provided by *zlib* is available in
*Compress::Zlib*.

   The module can be split into two general areas of functionality, namely
in-memory compression/decompression and read/write access to *gzip* files.
Each of these areas will be discussed separately below.

DEFLATE
=======

   The interface *Compress::Zlib* provides to the in-memory *deflate* (and
*inflate*) functions has been modified to fit into a Perl model.

   The main difference is that for both inflation and deflation, the Perl
interface will always consume the complete input buffer before returning.
Also the output buffer returned will be automatically grown to fit the
amount of output available.

   Here is a definition of the interface available:

($d, $status) = deflateInit( [OPT] )
------------------------------------

   Initialises a deflation stream.

   It combines the features of the *zlib* functions *deflateInit*,
*deflateInit2* and *deflateSetDictionary*.

   If successful, it will return the initialised deflation stream, $d and
$status of `Z_OK' in a list context. In scalar context it returns the
deflation stream, $d, only.

   If not successful, the returned deflation stream ($d) will be undef and
$status will hold the exact *zlib* error code.

   The function optionally takes a number of named options specified as
`-Name=>value' pairs. This allows individual options to be tailored
without having to specify them all in the parameter list.

   For backward compatibility, it is also possible to pass the parameters
as a reference to a hash containing the name=>value pairs.

   The function takes one optional parameter, a reference to a hash.  The
contents of the hash allow the deflation interface to be tailored.

   Here is a list of the valid options:

*-Level*
     Defines the compression level. Valid values are 1 through 9,
     `Z_BEST_SPEED', `Z_BEST_COMPRESSION', and `Z_DEFAULT_COMPRESSION'.

     The default is `-Level =>Z_DEFAULT_COMPRESSION'.

*-Method*
     Defines the compression method. The only valid value at present (and
     the default) is `-Method =>Z_DEFLATED'.

*-WindowBits*
     For a definition of the meaning and valid values for *WindowBits*
     refer to the *zlib* documentation for *deflateInit2*.

     Defaults to `-WindowBits =>MAX_WBITS'.

*-MemLevel*
     For a definition of the meaning and valid values for *MemLevel* refer
     to the *zlib* documentation for *deflateInit2*.

     Defaults to `-MemLevel =>MAX_MEM_LEVEL'.

*-Strategy*
     Defines the strategy used to tune the compression. The valid values
     are `Z_DEFAULT_STRATEGY', `Z_FILTERED' and `Z_HUFFMAN_ONLY'.

     The default is `-Strategy =>Z_DEFAULT_STRATEGY'.

*-Dictionary*
     When a dictionary is specified *Compress::Zlib* will automatically
     call *deflateSetDictionary* directly after calling *deflateInit*. The
     Adler32 value for the dictionary can be obtained by calling the method
     `$d-'dict_adler()>.

     The default is no dictionary.

*-Bufsize*
     Sets the initial size for the deflation buffer. If the buffer has to
     be reallocated to increase the size, it will grow in increments of
     *Bufsize*.

     The default is 4096.

   Here is an example of using the *deflateInit* optional parameter list
to override the default buffer size and compression level. All other
options will take their default values.

     deflateInit( -Bufsize => 300,
                  -Level => Z_BEST_SPEED  ) ;

*($out, $status) = $d->deflate($buffer)*
----------------------------------------

   Deflates the contents of *$buffer*. The buffer can either be a scalar
or a scalar reference.  When finished, *$buffer* will be completely
processed (assuming there were no errors). If the deflation was successful
it returns the deflated output, *$out*, and a status value, $status, of
`Z_OK'.

   On error, *$out* will be undef and $status will contain the *zlib*
error code.

   In a scalar context *deflate* will return *$out* only.

   As with the *deflate* function in *zlib*, it is not necessarily the
case that any output will be produced by this method. So don't rely on the
fact that *$out* is empty for an error test.

*($out, $status) = $d->flush([flush_type])*
-------------------------------------------

   Finishes the deflation. Any pending output will be returned via *$out*.
$status will have a value `Z_OK' if successful.

   In a scalar context flush will return *$out* only.

   Note that flushing can degrade the compression ratio, so it should only
be used to terminate a decompression.

   By default the `flush_type' used is `Z_FINISH'. Other valid values for
`flush_type' are Z_NO_FLUSH, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH and
Z_FULL_FLUSH. It is strongly recommended that you only set the
`flush_type' parameter if you fully understand what it does. See the
`zlib' documentation for details.

*$d->dict_adler()*
------------------

   Returns the adler32 value for the dictionary.

Example
-------

   Here is a trivial example of using *deflate*. It simply reads standard
input, deflates it and writes it to standard output.

     use strict ;
     use warnings ;

     use Compress::Zlib ;

     binmode STDIN;
     binmode STDOUT;
     my $x = deflateInit()
        or die "Cannot create a deflation stream\n" ;

     my ($output, $status) ;
     while (<>)
     {
         ($output, $status) = $x->deflate($_) ;

         $status == Z_OK
             or die "deflation failed\n" ;

         print $output ;
     }

     ($output, $status) = $x->flush() ;

     $status == Z_OK
         or die "deflation failed\n" ;

     print $output ;

INFLATE
=======

   Here is a definition of the interface:

($i, $status) = inflateInit()
-----------------------------

   Initialises an inflation stream.

   In a list context it returns the inflation stream, $i, and the *zlib*
status code ($status). In a scalar context it returns the inflation stream
only.

   If successful, $i will hold the inflation stream and $status will be
`Z_OK'.

   If not successful, $i will be undef and $status will hold the *zlib*
error code.

   The function optionally takes a number of named options specified as
`-Name=>value' pairs. This allows individual options to be tailored
without having to specify them all in the parameter list.

   For backward compatibility, it is also possible to pass the parameters
as a reference to a hash containing the name=>value pairs.

   The function takes one optional parameter, a reference to a hash.  The
contents of the hash allow the deflation interface to be tailored.

   Here is a list of the valid options:

*-WindowBits*
     For a definition of the meaning and valid values for *WindowBits*
     refer to the *zlib* documentation for *inflateInit2*.

     Defaults to `-WindowBits =>MAX_WBITS'.

*-Bufsize*
     Sets the initial size for the inflation buffer. If the buffer has to
     be reallocated to increase the size, it will grow in increments of
     *Bufsize*.

     Default is 4096.

*-Dictionary*
     The default is no dictionary.

   Here is an example of using the *inflateInit* optional parameter to
override the default buffer size.

     inflateInit( -Bufsize => 300 ) ;

*($out, $status) = $i->inflate($buffer)*
----------------------------------------

   Inflates the complete contents of *$buffer*. The buffer can either be a
scalar or a scalar reference.

   Returns `Z_OK' if successful and `Z_STREAM_END' if the end of the
compressed data has been successfully reached.  If not successful, *$out*
will be undef and $status will hold the *zlib* error code.

   The `$buffer' parameter is modified by `inflate'. On completion it will
contain what remains of the input buffer after inflation. This means that
`$buffer' will be an empty string when the return status is `Z_OK'. When
the return status is `Z_STREAM_END' the `$buffer' parameter will contains
what (if anything) was stored in the input buffer after the deflated data
stream.

   This feature is useful when processing a file format that encapsulates
a  compressed data stream (e.g. gzip, zip).

*$i->dict_adler()*
------------------

   Returns the adler32 value for the dictionary.

Example
-------

   Here is an example of using *inflate*.

     use strict ;
     use warnings ;

     use Compress::Zlib ;

     my $x = inflateInit()
        or die "Cannot create a inflation stream\n" ;

     my $input = '' ;
     binmode STDIN;
     binmode STDOUT;

     my ($output, $status) ;
     while (read(STDIN, $input, 4096))
     {
         ($output, $status) = $x->inflate(\$input) ;

         print $output
             if $status == Z_OK or $status == Z_STREAM_END ;

         last if $status != Z_OK ;
     }

     die "inflation failed\n"
         unless $status == Z_STREAM_END ;

COMPRESS/UNCOMPRESS
===================

   Two high-level functions are provided by *zlib* to perform in-memory
compression. They are compress and uncompress. Two Perl subs are provided
which provide similar functionality.

*$dest = compress($source) ;*
     Compresses *$source*. If successful it returns the compressed data.
     Otherwise it returns undef.

     The source buffer can either be a scalar or a scalar reference.

*$dest = uncompress($source) ;*
     Uncompresses *$source*. If successful it returns the uncompressed
     data. Otherwise it returns undef.

     The source buffer can either be a scalar or a scalar reference.

GZIP INTERFACE
==============

   A number of functions are supplied in *zlib* for reading and writing
*gzip* files. This module provides an interface to most of them. In
general the interface provided by this module operates identically to the
functions provided by *zlib*. Any differences are explained below.

*$gz = gzopen(filename or filehandle, mode)*
     This function operates identically to the *zlib* equivalent except
     that it returns an object which is used to access the other *gzip*
     methods.

     As with the *zlib* equivalent, the mode parameter is used to specify
     both whether the file is opened for reading or writing and to
     optionally specify a a compression level. Refer to the *zlib*
     documentation for the exact format of the mode parameter.

     If a reference to an open filehandle is passed in place of the
     filename, gzdopen will be called behind the scenes. The third example
     at the end of this section, *gzstream*, uses this feature.

*$bytesread = $gz->gzread($buffer [, $size]) ;*
     Reads $size bytes from the compressed file into *$buffer*. If $size
     is not specified, it will default to 4096. If the scalar *$buffer* is
     not large enough, it will be extended automatically.

     Returns the number of bytes actually read. On EOF it returns 0 and in
     the case of an error, -1.

*$bytesread = $gz->gzreadline($line) ;*
     Reads the next line from the compressed file into *$line*.

     Returns the number of bytes actually read. On EOF it returns 0 and in
     the case of an error, -1.

     It is legal to intermix calls to *gzread* and *gzreadline*.

     At this time *gzreadline* ignores the variable $/
     ($INPUT_RECORD_SEPARATOR or $RS when English is in use). The end of a
     line is denoted by the C character `'\n''.

*$byteswritten = $gz->gzwrite($buffer) ;*
     Writes the contents of *$buffer* to the compressed file. Returns the
     number of bytes actually written, or 0 on error.

*$status = $gz->gzflush($flush) ;*
     Flushes all pending output into the compressed file.  Works
     identically to the *zlib* function it interfaces to. Note that the
     use of *gzflush* can degrade compression.

     Refer to the *zlib* documentation for the valid values of *$flush*.

*$gz->gzclose*
     Closes the compressed file. Any pending data is flushed to the file
     before it is closed.

*$gz->gzerror*
     Returns the *zlib* error message or number for the last operation
     associated with $gz. The return value will be the *zlib* error number
     when used in a numeric context and the *zlib* error message when used
     in a string context. The *zlib* error number constants, shown below,
     are available for use.

          Z_OK
          Z_STREAM_END
          Z_ERRNO
          Z_STREAM_ERROR
          Z_DATA_ERROR
          Z_MEM_ERROR
          Z_BUF_ERROR

$gzerrno
     The $gzerrno scalar holds the error code associated with the most
     recent *gzip* routine. Note that unlike *gzerror()*, the error is not
     associated with a particular file.

     As with *gzerror()* it returns an error number in numeric context and
     an error message in string context. Unlike *gzerror()* though, the
     error message will correspond to the *zlib* message when the error is
     associated with *zlib* itself, or the UNIX error message when it is
     not (i.e. *zlib* returned `Z_ERRORNO').

     As there is an overlap between the error numbers used by *zlib* and
     UNIX, $gzerrno should only be used to check for the presence of an
     error in numeric context. Use *gzerror()* to check for specific
     *zlib* errors. The *gzcat* example below shows how the variable can
     be used safely.

Examples
--------

   Here is an example script which uses the interface. It implements a
*gzcat* function.

     use strict ;
     use warnings ;

     use Compress::Zlib ;

     die "Usage: gzcat file...\n"
         unless @ARGV ;

     my $file ;

     foreach $file (@ARGV) {
         my $buffer ;

         my $gz = gzopen($file, "rb")
              or die "Cannot open $file: $gzerrno\n" ;

         print $buffer while $gz->gzread($buffer) > 0 ;

         die "Error reading from $file: $gzerrno" . ($gzerrno+0) . "\n"
             if $gzerrno != Z_STREAM_END ;

         $gz->gzclose() ;
     }

   Below is a script which makes use of *gzreadline*. It implements a very
simple grep like script.

     use strict ;
     use warnings ;

     use Compress::Zlib ;

     die "Usage: gzgrep pattern file...\n"
         unless @ARGV >= 2;

     my $pattern = shift ;

     my $file ;

     foreach $file (@ARGV) {
         my $gz = gzopen($file, "rb")
              or die "Cannot open $file: $gzerrno\n" ;

         while ($gz->gzreadline($_) > 0) {
             print if /$pattern/ ;
         }

         die "Error reading from $file: $gzerrno\n"
             if $gzerrno != Z_STREAM_END ;

         $gz->gzclose() ;
     }

   This script, *gzstream*, does the opposite of the *gzcat* script above.
It reads from standard input and writes a gzip file to standard output.

     use strict ;
     use warnings ;

     use Compress::Zlib ;

     binmode STDOUT;	# gzopen only sets it on the fd

     my $gz = gzopen(\*STDOUT, "wb")
     	  or die "Cannot open stdout: $gzerrno\n" ;

     while (<>) {
         $gz->gzwrite($_)
     	or die "error writing: $gzerrno\n" ;
     }

     $gz->gzclose ;

Compress::Zlib::memGzip
-----------------------

   This function is used to create an in-memory gzip file.  It creates a
minimal gzip header.

     $dest = Compress::Zlib::memGzip($buffer) ;

   If successful, it returns the in-memory gzip file, otherwise it returns
undef.

   The buffer parameter can either be a scalar or a scalar reference.

Compress::Zlib::memGunzip
-------------------------

   This function is used to uncompress an in-memory gzip file.

     $dest = Compress::Zlib::memGunzip($buffer) ;

   If successful, it returns the uncompressed gzip file, otherwise it
returns undef.

   The buffer parameter can either be a scalar or a scalar reference. The
contents of the buffer parameter are destroyed after calling this function.

CHECKSUM FUNCTIONS
==================

   Two functions are provided by *zlib* to calculate a checksum. For the
Perl interface, the order of the two parameters in both functions has been
reversed. This allows both running checksums and one off calculations to
be done.

     $crc = adler32($buffer [,$crc]) ;
     $crc = crc32($buffer [,$crc]) ;

   The buffer parameters can either be a scalar or a scalar reference.

   If the $crc parameters is undef, the crc value will be reset.

ACCESSING ZIP FILES
===================

   Although it is possible to use this module to access .zip files, there
is a module on CPAN that will do all the hard work for you. Check out

     http://www.cpan.org/modules/by-module/Archive/Archive-Zip-*.tar.gz

   Assuming you don't want to use this module to access zip files there
are a number of undocumented features in the zlib library you need to be
aware of.

  1. When calling *inflateInit* or *deflateInit* the *WindowBits* parameter
     must be set to `-MAX_WBITS'. This disables the creation of the zlib
     header.

  2. The zlib function *inflate*, and so the *inflate* method supplied in
     this module, assume that there is at least one trailing byte after the
     compressed data stream. Normally this isn't a problem because both
     the gzip and zip file formats will guarantee that there is data
     directly after the compressed data stream.

CONSTANTS
=========

   All the *zlib* constants are automatically imported when you make use
of *Compress::Zlib*.

AUTHOR
======

   The *Compress::Zlib* module was written by Paul Marquess,
`Paul.Marquess@btinternet.com'. The latest copy of the module can be found
on CPAN in `modules/by-module/Compress/Compress-Zlib-x.x.tar.gz'.

   The primary site for the *zlib* compression library is
`http://www.info-zip.org/pub/infozip/zlib/'.

MODIFICATION HISTORY
====================

   See the README file.

access Perl configuration information
*************************************

NAME
====

   Config - access Perl configuration information

SYNOPSIS
========

     use Config;
     if ($Config{'cc'} =~ /gcc/) {
     	print "built by gcc\n";
     }

     use Config qw(myconfig config_sh config_vars);

     print myconfig();

     print config_sh();

     config_vars(qw(osname archname));

DESCRIPTION
===========

   The Config module contains all the information that was available to
the Configure program at Perl build time (over 900 values).

   Shell variables from the `config.sh' file (written by Configure) are
stored in the readonly-variable `%Config', indexed by their names.

   Values stored in config.sh as 'undef' are returned as undefined values.
The perl exists function can be used to check if a named variable exists.

myconfig()
     Returns a textual summary of the major perl configuration values.
     See also -V in `Switches', see Perlrun (perl.info).

config_sh()
     Returns the entire perl configuration information in the form of the
     original config.sh shell variable assignment script.

config_vars(@names)
     Prints to STDOUT the values of the named configuration variable. Each
     is printed on a separate line in the form:

          name='value';

     Names which are unknown are output as `name='UNKNOWN';'.  See also
     `-V:name' in `Switches', see Perlrun (perl.info).

EXAMPLE
=======

   Here's a more sophisticated example of using %Config:

     use Config;
     use strict;

     my %sig_num;
     my @sig_name;
     unless($Config{sig_name} && $Config{sig_num}) {
     	die "No sigs?";
     } else {
     	my @names = split ' ', $Config{sig_name};
     	@sig_num{@names} = split ' ', $Config{sig_num};
     	foreach (@names) {
     	    $sig_name[$sig_num{$_}] ||= $_;
     	}
     }

     print "signal #17 = $sig_name[17]\n";
     if ($sig_num{ALRM}) {
     	print "SIGALRM is $sig_num{ALRM}\n";
     }

WARNING
=======

   Because this information is not stored within the perl executable
itself it is possible (but unlikely) that the information does not relate
to the actual perl binary which is being used to access it.

   The Config module is installed into the architecture and version
specific library directory ($Config{installarchlib}) and it checks the
perl version number when loaded.

   The values stored in config.sh may be either single-quoted or
double-quoted. Double-quoted strings are handy for those cases where you
need to include escape sequences in the strings. To avoid runtime variable
interpolation, any `$' and `@' characters are replaced by `\$' and `\@',
respectively. This isn't foolproof, of course, so don't embed `\$' or `\@'
in double-quoted strings unless you're willing to deal with the
consequences. (The slashes will end up escaped and the `$' or `@' will
trigger variable interpolation)

GLOSSARY
========

   Most Config variables are determined by the Configure script on
platforms supported by it (which is most UNIX platforms).  Some platforms
have custom-made Config variables, and may thus not have some of the
variables described below, or may have extraneous variables specific to
that particular port.  See the port specific documentation in such cases.

_
-

`_a'
     From `Unix.U':

     This variable defines the extension used for ordinary libraries.  For
     unix, it is `.a'.  The . is included.  Other possible values include
     `.lib'.

`_exe'
     From `Unix.U':

     This variable defines the extension used for executable files.  For
     unix it is empty.  Other possible values include `.exe'.

`_o'
     From `Unix.U':

     This variable defines the extension used for object files.  For unix,
     it is `.o'.  The . is included.  Other possible values include `.obj'.

a
-

`afs'
     From `afs.U':

     This variable is set to `true' if AFS (Andrew File System) is used on
     the system, false otherwise.  It is possible to override this with a
     hint value or command line option, but you'd better know what you are
     doing.

`alignbytes'
     From `alignbytes.U':

     This variable holds the number of bytes required to align a double-
     or a long double when applicable. Usual values are 2, 4 and 8.  The
     default is eight, for safety.

`ansi2knr'
     From `ansi2knr.U':

     This variable is set if the user needs to run ansi2knr.  Currently,
     this is not supported, so we just abort.

`aphostname'
     From `d_gethname.U':

     This variable contains the command which can be used to compute the
     host name. The command is fully qualified by its absolute path, to
     make it safe when used by a process with super-user privileges.

`api_revision'
     From `patchlevel.U':

     The three variables, api_revision, api_version, and api_subversion,
     specify the version of the oldest perl binary compatible with the
     present perl.  In a full version string such as `5.6.1', api_revision
     is the 5.  Prior to 5.5.640, the format was a floating point number,
     like 5.00563.

          F<perl.c>:incpush() and F<lib/lib.pm> will automatically search in

          $F<sitelib/.>. for older directories back to the limit specified
          by these api_ variables.  This is only useful if you have a
          perl library directory tree structured like the default one.
          See C<INSTALL> for how this works.  The versioned site_perl
          directory was introduced in 5.005, so that is the lowest
          possible value.  The version list appropriate for the current
          system is determined in F<inc_version_list.U>.

          C<XXX> To do:  Since compatibility can depend on compile time

          options (such as bincompat, longlong, F<etc.>) it should
          (perhaps) be set by Configure, but currently it isn't.
          Currently, we read a hard-wired value from F<patchlevel.h>.
          Perhaps what we ought to do is take the hard-wired value from
          F<patchlevel.h> but then modify it if the current Configure
          options warrant.  F<patchlevel.h> then would use an #ifdef guard.

`api_subversion'
     From `patchlevel.U':

     The three variables, api_revision, api_version, and api_subversion,
     specify the version of the oldest perl binary compatible with the
     present perl.  In a full version string such as `5.6.1',
     api_subversion is the 1.  See api_revision for full details.

`api_version'
     From `patchlevel.U':

     The three variables, api_revision, api_version, and api_subversion,
     specify the version of the oldest perl binary compatible with the
     present perl.  In a full version string such as `5.6.1', api_version
     is the 6.  See api_revision for full details.  As a special case,
     5.5.0 is rendered in the old-style as 5.005.  (In the 5.005_0x
     maintenance series, this was the only versioned directory in
     $`sitelib.')

`api_versionstring'
     From `patchlevel.U':

     This variable combines api_revision, api_version, and api_subversion
     in a format such as 5.6.1 (or 5_6_1) suitable for use as a directory
     name.  This is filesystem dependent.

`ar'
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the ar program.  After Configure runs, the value
     is reset to a plain `ar' and is not useful.

`archlib'
     From `archlib.U':

     This variable holds the name of the directory in which the user wants
     to put architecture-dependent public library files for $package.  It
     is most often a local directory such as `/usr/local/lib'.  Programs
     using this variable must be prepared to deal with filename expansion.

`archlibexp'
     From `archlib.U':

     This variable is the same as the archlib variable, but is filename
     expanded at configuration time, for convenient use.

`archname64'
     From `use64bits.U':

     This variable is used for the 64-bitness part of $archname.

archname
     From `archname.U':

     This variable is a short name to characterize the current
     architecture.  It is used mainly to construct the default archlib.

`archobjs'
     From `Unix.U':

     This variable defines any additional objects that must be linked in
     with the program on this architecture.  On unix, it is usually empty.
     It is typically used to include emulations of unix calls or other
     facilities.  For perl on OS/2, for example, this would include
     `os2/os2.obj'.

`awk'
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the awk program.  After Configure runs, the
     value is reset to a plain `awk' and is not useful.

b
-

`baserev'
     From `baserev.U':

     The base revision level of this package, from the `.package' file.

`bash'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

bin
     From `bin.U':

     This variable holds the name of the directory in which the user wants
     to put publicly executable images for the package in question.  It is
     most often a local directory such as `/usr/local/bin'. Programs using
     this variable must be prepared to deal with `~name' substitution.

`bincompat5005'
     From `bincompat5005.U':

     This variable contains y if this version of Perl should be
     binary-compatible with Perl 5.005.

`binexp'
     From `bin.U':

     This is the same as the bin variable, but is filename expanded at
     configuration time, for use in your makefiles.

`bison'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`byacc'
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the byacc program.  After Configure runs, the
     value is reset to a plain `byacc' and is not useful.

`byteorder'
     From `byteorder.U':

     This variable holds the byte order. In the following, larger digits
     indicate more significance.  The variable byteorder is either 4321 on
     a big-endian machine, or 1234 on a little-endian, or 87654321 on a
     Cray ... or 3412 with weird order !

c
-

c
     From `n.U':

     This variable contains the \c string if that is what causes the echo
     command to suppress newline.  Otherwise it is null.  Correct usage is
     $echo $n "prompt for a question: $c".

`castflags'
     From `d_castneg.U':

     This variable contains a flag that precise difficulties the compiler
     has casting odd floating values to unsigned long: 0 = ok 1 = couldn't
     cast < 0 2 = couldn't cast >= 0x80000000 4 = couldn't cast in
     argument expression list

cat
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the cat program.  After Configure runs, the
     value is reset to a plain cat and is not useful.

cc
     From `cc.U':

     This variable holds the name of a command to execute a C compiler
     which can resolve multiple global references that happen to have the
     same name.  Usual values are cc, `Mcc', `cc -M', and `gcc'.

`cccdlflags'
     From `dlsrc.U':

     This variable contains any special flags that might need to be passed
     with `cc -c' to compile modules to be used to create a shared library
     that will be used for dynamic loading.  For hpux, this should be +z.
     It is up to the makefile to use it.

`ccdlflags'
     From `dlsrc.U':

     This variable contains any special flags that might need to be passed
     to cc to link with a shared library for dynamic loading.  It is up to
     the makefile to use it.  For sunos 4.1, it should be empty.

`ccflags'
     From `ccflags.U':

     This variable contains any additional C compiler flags desired by the
     user.  It is up to the Makefile to use this.

`ccsymbols'
     From `Cppsym.U':

     The variable contains the symbols defined by the C compiler alone.
     The symbols defined by cpp or by cc when it calls cpp are not in this
     list, see cppsymbols and cppccsymbols.  The list is a space-separated
     list of symbol=value tokens.

`cf_by'
     From `cf_who.U':

     Login name of the person who ran the Configure script and answered the
     questions. This is used to tag both `config.sh' and `config_h.SH'.

`cf_email'
     From `cf_email.U':

     Electronic mail address of the person who ran Configure. This can be
     used by units that require the user's e-mail, like `MailList.U'.

`cf_time'
     From `cf_who.U':

     Holds the output of the date command when the configuration file was
     produced. This is used to tag both `config.sh' and `config_h.SH'.

charsize
     From `charsize.U':

     This variable contains the value of the `CHARSIZE' symbol, which
     indicates to the C program how many bytes there are in a character.

`chgrp'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

chmod
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

chown
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`clocktype'
     From `d_times.U':

     This variable holds the type returned by times(). It can be long, or
     clock_t on `BSD' sites (in which case <sys/types.h> should be
     included).

`comm'
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the comm program.  After Configure runs, the
     value is reset to a plain `comm' and is not useful.

compress
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

C
-

`CONFIGDOTSH'
     From `Oldsyms.U':

     This is set to `true' in `config.sh' so that a shell script sourcing
     `config.sh' can tell if it has been sourced already.

contains
     From `contains.U':

     This variable holds the command to do a grep with a proper return
     status.  On most sane systems it is simply grep.  On insane systems
     it is a grep followed by a cat followed by a test.  This variable is
     primarily for the use of other Configure units.

cp
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the cp program.  After Configure runs, the value
     is reset to a plain cp and is not useful.

`cpio'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`cpp'
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the cpp program.  After Configure runs, the
     value is reset to a plain `cpp' and is not useful.

`cpp_stuff'
     From `cpp_stuff.U':

     This variable contains an identification of the catenation mechanism
     used by the C preprocessor.

`cppccsymbols'
     From `Cppsym.U':

     The variable contains the symbols defined by the C compiler when it
     calls cpp.  The symbols defined by the cc alone or cpp alone are not
     in this list, see ccsymbols and cppsymbols.  The list is a
     space-separated list of symbol=value tokens.

`cppflags'
     From `ccflags.U':

     This variable holds the flags that will be passed to the C pre-
     processor. It is up to the Makefile to use it.

`cpplast'
     From `cppstdin.U':

     This variable has the same functionality as cppminus, only it applies
     to cpprun and not cppstdin.

`cppminus'
     From `cppstdin.U':

     This variable contains the second part of the string which will invoke
     the C preprocessor on the standard input and produce to standard
     output.  This variable will have the value - if cppstdin needs a
     minus to specify standard input, otherwise the value is "".

`cpprun'
     From `cppstdin.U':

     This variable contains the command which will invoke a C preprocessor
     on standard input and put the output to stdout. It is guaranteed not
     to be a wrapper and may be a null string if no preprocessor can be
     made directly available. This preprocessor might be different from the
     one used by the C compiler. Don't forget to append cpplast after the
     preprocessor options.

`cppstdin'
     From `cppstdin.U':

     This variable contains the command which will invoke the C
     preprocessor on standard input and put the output to stdout.  It is
     primarily used by other Configure units that ask about preprocessor
     symbols.

`cppsymbols'
     From `Cppsym.U':

     The variable contains the symbols defined by the C preprocessor
     alone.  The symbols defined by cc or by cc when it calls cpp are not
     in this list, see ccsymbols and cppccsymbols.  The list is a
     space-separated list of symbol=value tokens.

`crosscompile'
     From `crosscompile.U':

     This variable conditionally defines the `CROSSCOMPILE' symbol which
     signifies that the build process is be a cross-compilation.  This is
     normally set by hints files or from Configure command line.

`cryptlib'
     From `d_crypt.U':

     This variable holds -lcrypt or the path to a `libcrypt.a' archive if
     the crypt() function is not defined in the standard C library. It is
     up to the Makefile to use this.

`csh'
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the csh program.  After Configure runs, the
     value is reset to a plain `csh' and is not useful.

d
-

`d_access'
     From `d_access.U':

     This variable conditionally defines `HAS_ACCESS' if the access()
     system call is available to check for access permissions using real
     IDs.

`d_accessx'
     From `d_accessx.U':

     This variable conditionally defines the `HAS_ACCESSX' symbol, which
     indicates to the C program that the accessx() routine is available.

`d_alarm'
     From `d_alarm.U':

     This variable conditionally defines the `HAS_ALARM' symbol, which
     indicates to the C program that the alarm() routine is available.

`d_archlib'
     From `archlib.U':

     This variable conditionally defines `ARCHLIB' to hold the pathname of
     architecture-dependent library files for $package.  If $archlib is
     the same as $privlib, then this is set to undef.

`d_atolf'
     From `atolf.U':

     This variable conditionally defines the `HAS_ATOLF' symbol, which
     indicates to the C program that the atolf() routine is available.

`d_atoll'
     From `atoll.U':

     This variable conditionally defines the `HAS_ATOLL' symbol, which
     indicates to the C program that the atoll() routine is available.

`d_attribut'
     From `d_attribut.U':

     This variable conditionally defines `HASATTRIBUTE', which indicates
     the C compiler can check for function attributes, such as printf
     formats.

`d_bcmp'
     From `d_bcmp.U':

     This variable conditionally defines the `HAS_BCMP' symbol if the
     bcmp() routine is available to compare strings.

`d_bcopy'
     From `d_bcopy.U':

     This variable conditionally defines the `HAS_BCOPY' symbol if the
     bcopy() routine is available to copy strings.

`d_bincompat5005'
     From `bincompat5005.U':

     This variable conditionally defines BINCOMPAT5005 so that `embed.h'
     can take special action if this version of Perl should be
     binary-compatible with Perl 5.005.  This is impossible for builds
     that use features like threads and multiplicity it is always $undef
     for those versions.

`d_bsd'
     From `Guess.U':

     This symbol conditionally defines the symbol `BSD' when running on a
     `BSD' system.

`d_bsdgetpgrp'
     From `d_getpgrp.U':

     This variable conditionally defines `USE_BSD_GETPGRP' if getpgrp
     needs one arguments whereas `USG' one needs none.

`d_bsdsetpgrp'
     From `d_setpgrp.U':

     This variable conditionally defines `USE_BSD_SETPGRP' if setpgrp
     needs two arguments whereas `USG' one needs none.  See also d_setpgid
     for a POSIX interface.

`d_bzero'
     From `d_bzero.U':

     This variable conditionally defines the `HAS_BZERO' symbol if the
     bzero() routine is available to set memory to 0.

`d_casti32'
     From `d_casti32.U':

     This variable conditionally defines CASTI32, which indicates whether
     the C compiler can cast large floats to 32-bit ints.

`d_castneg'
     From `d_castneg.U':

     This variable conditionally defines `CASTNEG', which indicates wether
     the C compiler can cast negative float to unsigned.

`d_charvspr'
     From `d_vprintf.U':

     This variable conditionally defines `CHARVSPRINTF' if this system has
     vsprintf returning type (char*).  The trend seems to be to declare it
     as "int vsprintf()".

`d_chown'
     From `d_chown.U':

     This variable conditionally defines the `HAS_CHOWN' symbol, which
     indicates to the C program that the chown() routine is available.

`d_chroot'
     From `d_chroot.U':

     This variable conditionally defines the `HAS_CHROOT' symbol, which
     indicates to the C program that the chroot() routine is available.

`d_chsize'
     From `d_chsize.U':

     This variable conditionally defines the `CHSIZE' symbol, which
     indicates to the C program that the chsize() routine is available to
     truncate files.  You might need a -lx to get this routine.

`d_closedir'
     From `d_closedir.U':

     This variable conditionally defines `HAS_CLOSEDIR' if closedir() is
     available.

`d_const'
     From `d_const.U':

     This variable conditionally defines the `HASCONST' symbol, which
     indicates to the C program that this C compiler knows about the const
     type.

`d_crypt'
     From `d_crypt.U':

     This variable conditionally defines the `CRYPT' symbol, which
     indicates to the C program that the crypt() routine is available to
     encrypt passwords and the like.

`d_csh'
     From `d_csh.U':

     This variable conditionally defines the `CSH' symbol, which indicates
     to the C program that the C-shell exists.

`d_cuserid'
     From `d_cuserid.U':

     This variable conditionally defines the `HAS_CUSERID' symbol, which
     indicates to the C program that the cuserid() routine is available to
     get character login names.

`d_dbl_dig'
     From `d_dbl_dig.U':

     This variable conditionally defines d_dbl_dig if this system's header
     files provide `DBL_DIG', which is the number of significant digits in
     a double precision number.

`d_difftime'
     From `d_difftime.U':

     This variable conditionally defines the `HAS_DIFFTIME' symbol, which
     indicates to the C program that the difftime() routine is available.

`d_dirnamlen'
     From `i_dirent.U':

     This variable conditionally defines `DIRNAMLEN', which indicates to
     the C program that the length of directory entry names is provided by
     a d_namelen field.

`d_dlerror'
     From `d_dlerror.U':

     This variable conditionally defines the `HAS_DLERROR' symbol, which
     indicates to the C program that the dlerror() routine is available.

`d_dlopen'
     From `d_dlopen.U':

     This variable conditionally defines the `HAS_DLOPEN' symbol, which
     indicates to the C program that the dlopen() routine is available.

`d_dlsymun'
     From `d_dlsymun.U':

     This variable conditionally defines `DLSYM_NEEDS_UNDERSCORE', which
     indicates that we need to prepend an underscore to the symbol name
     before calling dlsym().

`d_dosuid'
     From `d_dosuid.U':

     This variable conditionally defines the symbol `DOSUID', which tells
     the C program that it should insert setuid emulation code on hosts
     which have setuid #! scripts disabled.

`d_drand48proto'
     From `d_drand48proto.U':

     This variable conditionally defines the HAS_DRAND48_PROTO symbol,
     which indicates to the C program that the system provides a prototype
     for the drand48() function.  Otherwise, it is up to the program to
     supply one.

`d_dup2'
     From `d_dup2.U':

     This variable conditionally defines HAS_DUP2 if dup2() is available
     to duplicate file descriptors.

`d_eaccess'
     From `d_eaccess.U':

     This variable conditionally defines the `HAS_EACCESS' symbol, which
     indicates to the C program that the eaccess() routine is available.

`d_endgrent'
     From `d_endgrent.U':

     This variable conditionally defines the `HAS_ENDGRENT' symbol, which
     indicates to the C program that the endgrent() routine is available
     for sequential access of the group database.

`d_endhent'
     From `d_endhent.U':

     This variable conditionally defines `HAS_ENDHOSTENT' if endhostent()
     is available to close whatever was being used for host queries.

`d_endnent'
     From `d_endnent.U':

     This variable conditionally defines `HAS_ENDNETENT' if endnetent() is
     available to close whatever was being used for network queries.

`d_endpent'
     From `d_endpent.U':

     This variable conditionally defines `HAS_ENDPROTOENT' if
     endprotoent() is available to close whatever was being used for
     protocol queries.

`d_endpwent'
     From `d_endpwent.U':

     This variable conditionally defines the `HAS_ENDPWENT' symbol, which
     indicates to the C program that the endpwent() routine is available
     for sequential access of the passwd database.

`d_endsent'
     From `d_endsent.U':

     This variable conditionally defines `HAS_ENDSERVENT' if endservent()
     is available to close whatever was being used for service queries.

`d_endspent'
     From `d_endspent.U':

     This variable conditionally defines `HAS_ENDSPENT' if endspent() is
     available to finalize the scan of SysV shadow password entries.

`d_eofnblk'
     From `nblock_io.U':

     This variable conditionally defines EOF_NONBLOCK if EOF can be seen
     when reading from a non-blocking I/O source.

`d_eunice'
     From `Guess.U':

     This variable conditionally defines the symbols `EUNICE' and `VAX',
     which alerts the C program that it must deal with ideosyncracies of
     VMS.

`d_fchmod'
     From `d_fchmod.U':

     This variable conditionally defines the `HAS_FCHMOD' symbol, which
     indicates to the C program that the fchmod() routine is available to
     change mode of opened files.

`d_fchown'
     From `d_fchown.U':

     This variable conditionally defines the `HAS_FCHOWN' symbol, which
     indicates to the C program that the fchown() routine is available to
     change ownership of opened files.

`d_fcntl'
     From `d_fcntl.U':

     This variable conditionally defines the `HAS_FCNTL' symbol, and
     indicates whether the fcntl() function exists

`d_fd_macros'
     From `d_fd_set.U':

     This variable contains the eventual value of the `HAS_FD_MACROS'
     symbol, which indicates if your C compiler knows about the macros
     which manipulate an fd_set.

`d_fd_set'
     From `d_fd_set.U':

     This variable contains the eventual value of the `HAS_FD_SET' symbol,
     which indicates if your C compiler knows about the fd_set typedef.

`d_fds_bits'
     From `d_fd_set.U':

     This variable contains the eventual value of the `HAS_FDS_BITS'
     symbol, which indicates if your fd_set typedef contains the fds_bits
     member.  If you have an fd_set typedef, but the dweebs who installed
     it did a half-fast job and neglected to provide the macros to
     manipulate an fd_set, `HAS_FDS_BITS' will let us know how to fix the
     gaffe.

`d_fgetpos'
     From `d_fgetpos.U':

     This variable conditionally defines `HAS_FGETPOS' if fgetpos() is
     available to get the file position indicator.

`d_flexfnam'
     From `d_flexfnam.U':

     This variable conditionally defines the `FLEXFILENAMES' symbol, which
     indicates that the system supports filenames longer than 14
     characters.

`d_flock'
     From `d_flock.U':

     This variable conditionally defines `HAS_FLOCK' if flock() is
     available to do file locking.

`d_fork'
     From `d_fork.U':

     This variable conditionally defines the `HAS_FORK' symbol, which
     indicates to the C program that the fork() routine is available.

`d_fpathconf'
     From `d_pathconf.U':

     This variable conditionally defines the `HAS_FPATHCONF' symbol, which
     indicates to the C program that the pathconf() routine is available
     to determine file-system related limits and options associated with a
     given open file descriptor.

`d_fpos64_t'
     From `d_fpos64_t.U':

     This symbol will be defined if the C compiler supports fpos64_t.

`d_fs_data_s'
     From `d_fs_data_s.U':

     This variable conditionally defines the `HAS_STRUCT_FS_DATA' symbol,
     which indicates that the struct fs_data is supported.

`d_fseeko'
     From `d_fseeko.U':

     This variable conditionally defines the `HAS_FSEEKO' symbol, which
     indicates to the C program that the fseeko() routine is available.

`d_fsetpos'
     From `d_fsetpos.U':

     This variable conditionally defines `HAS_FSETPOS' if fsetpos() is
     available to set the file position indicator.

`d_fstatfs'
     From `d_fstatfs.U':

     This variable conditionally defines the `HAS_FSTATFS' symbol, which
     indicates to the C program that the fstatfs() routine is available.

`d_fstatvfs'
     From `d_statvfs.U':

     This variable conditionally defines the `HAS_FSTATVFS' symbol, which
     indicates to the C program that the fstatvfs() routine is available.

`d_ftello'
     From `d_ftello.U':

     This variable conditionally defines the `HAS_FTELLO' symbol, which
     indicates to the C program that the ftello() routine is available.

`d_ftime'
     From `d_ftime.U':

     This variable conditionally defines the `HAS_FTIME' symbol, which
     indicates that the ftime() routine exists.  The ftime() routine is
     basically a sub-second accuracy clock.

`d_Gconvert'
     From `d_gconvert.U':

     This variable holds what Gconvert is defined as to convert floating
     point numbers into strings. It could be `gconvert' or a more
     `complex' macro emulating gconvert with gcvt() or sprintf.  Possible
     values are: d_Gconvert=`gconvert((x),(n),(t),(b))'
     d_Gconvert=`gcvt((x),(n),(b))'
     d_Gconvert=`sprintf((b),`%`.'*g',(n),(x))'

`d_getcwd'
     From `d_getcwd.U':

     This variable conditionally defines the `HAS_GETCWD' symbol, which
     indicates to the C program that the getcwd() routine is available to
     get the current working directory.

`d_getfsstat'
     From `d_getfsstat.U':

     This variable conditionally defines the `HAS_GETFSSTAT' symbol, which
     indicates to the C program that the getfsstat() routine is available.

`d_getgrent'
     From `d_getgrent.U':

     This variable conditionally defines the `HAS_GETGRENT' symbol, which
     indicates to the C program that the getgrent() routine is available
     for sequential access of the group database.

`d_getgrps'
     From `d_getgrps.U':

     This variable conditionally defines the `HAS_GETGROUPS' symbol, which
     indicates to the C program that the getgroups() routine is available
     to get the list of process groups.

`d_gethbyaddr'
     From `d_gethbyad.U':

     This variable conditionally defines the `HAS_GETHOSTBYADDR' symbol,
     which indicates to the C program that the gethostbyaddr() routine is
     available to look up hosts by their IP addresses.

`d_gethbyname'
     From `d_gethbynm.U':

     This variable conditionally defines the `HAS_GETHOSTBYNAME' symbol,
     which indicates to the C program that the gethostbyname() routine is
     available to look up host names in some data base or other.

`d_gethent'
     From `d_gethent.U':

     This variable conditionally defines `HAS_GETHOSTENT' if gethostent()
     is available to look up host names in some data base or another.

`d_gethname'
     From `d_gethname.U':

     This variable conditionally defines the `HAS_GETHOSTNAME' symbol,
     which indicates to the C program that the gethostname() routine may be
     used to derive the host name.

`d_gethostprotos'
     From `d_gethostprotos.U':

     This variable conditionally defines the `HAS_GETHOST_PROTOS' symbol,
     which indicates to the C program that <netdb.h> supplies prototypes
     for the various gethost*() functions.  See also `netdbtype.U' for
     probing for various netdb types.

`d_getlogin'
     From `d_getlogin.U':

     This variable conditionally defines the `HAS_GETLOGIN' symbol, which
     indicates to the C program that the getlogin() routine is available
     to get the login name.

`d_getmnt'
     From `d_getmnt.U':

     This variable conditionally defines the `HAS_GETMNT' symbol, which
     indicates to the C program that the getmnt() routine is available to
     retrieve one or more mount info blocks by filename.

`d_getmntent'
     From `d_getmntent.U':

     This variable conditionally defines the `HAS_GETMNTENT' symbol, which
     indicates to the C program that the getmntent() routine is available
     to iterate through mounted files to get their mount info.

`d_getnbyaddr'
     From `d_getnbyad.U':

     This variable conditionally defines the `HAS_GETNETBYADDR' symbol,
     which indicates to the C program that the getnetbyaddr() routine is
     available to look up networks by their IP addresses.

`d_getnbyname'
     From `d_getnbynm.U':

     This variable conditionally defines the `HAS_GETNETBYNAME' symbol,
     which indicates to the C program that the getnetbyname() routine is
     available to look up networks by their names.

`d_getnent'
     From `d_getnent.U':

     This variable conditionally defines `HAS_GETNETENT' if getnetent() is
     available to look up network names in some data base or another.

`d_getnetprotos'
     From `d_getnetprotos.U':

     This variable conditionally defines the `HAS_GETNET_PROTOS' symbol,
     which indicates to the C program that <netdb.h> supplies prototypes
     for the various getnet*() functions.  See also `netdbtype.U' for
     probing for various netdb types.

`d_getpbyname'
     From `d_getprotby.U':

     This variable conditionally defines the `HAS_GETPROTOBYNAME' symbol,
     which indicates to the C program that the getprotobyname() routine is
     available to look up protocols by their name.

`d_getpbynumber'
     From `d_getprotby.U':

     This variable conditionally defines the `HAS_GETPROTOBYNUMBER'
     symbol, which indicates to the C program that the getprotobynumber()
     routine is available to look up protocols by their number.

`d_getpent'
     From `d_getpent.U':

     This variable conditionally defines `HAS_GETPROTOENT' if
     getprotoent() is available to look up protocols in some data base or
     another.

`d_getpgid'
     From `d_getpgid.U':

     This variable conditionally defines the `HAS_GETPGID' symbol, which
     indicates to the C program that the getpgid(pid) function is
     available to get the process group id.

`d_getpgrp2'
     From `d_getpgrp2.U':

     This variable conditionally defines the HAS_GETPGRP2 symbol, which
     indicates to the C program that the getpgrp2() (as in `DG/`UX'')
     routine is available to get the current process group.

`d_getpgrp'
     From `d_getpgrp.U':

     This variable conditionally defines `HAS_GETPGRP' if getpgrp() is
     available to get the current process group.

`d_getppid'
     From `d_getppid.U':

     This variable conditionally defines the `HAS_GETPPID' symbol, which
     indicates to the C program that the getppid() routine is available to
     get the parent process ID.

`d_getprior'
     From `d_getprior.U':

     This variable conditionally defines `HAS_GETPRIORITY' if getpriority()
     is available to get a process's priority.

`d_getprotoprotos'
     From `d_getprotoprotos.U':

     This variable conditionally defines the `HAS_GETPROTO_PROTOS' symbol,
     which indicates to the C program that <netdb.h> supplies prototypes
     for the various getproto*() functions.  See also `netdbtype.U' for
     probing for various netdb types.

`d_getpwent'
     From `d_getpwent.U':

     This variable conditionally defines the `HAS_GETPWENT' symbol, which
     indicates to the C program that the getpwent() routine is available
     for sequential access of the passwd database.

`d_getsbyname'
     From `d_getsrvby.U':

     This variable conditionally defines the `HAS_GETSERVBYNAME' symbol,
     which indicates to the C program that the getservbyname() routine is
     available to look up services by their name.

`d_getsbyport'
     From `d_getsrvby.U':

     This variable conditionally defines the `HAS_GETSERVBYPORT' symbol,
     which indicates to the C program that the getservbyport() routine is
     available to look up services by their port.

`d_getsent'
     From `d_getsent.U':

     This variable conditionally defines `HAS_GETSERVENT' if getservent()
     is available to look up network services in some data base or another.

`d_getservprotos'
     From `d_getservprotos.U':

     This variable conditionally defines the `HAS_GETSERV_PROTOS' symbol,
     which indicates to the C program that <netdb.h> supplies prototypes
     for the various getserv*() functions.  See also `netdbtype.U' for
     probing for various netdb types.

`d_getspent'
     From `d_getspent.U':

     This variable conditionally defines `HAS_GETSPENT' if getspent() is
     available to retrieve SysV shadow password entries sequentially.

`d_getspnam'
     From `d_getspnam.U':

     This variable conditionally defines `HAS_GETSPNAM' if getspnam() is
     available to retrieve SysV shadow password entries by name.

`d_gettimeod'
     From `d_ftime.U':

     This variable conditionally defines the `HAS_GETTIMEOFDAY' symbol,
     which indicates that the gettimeofday() system call exists (to obtain
     a sub-second accuracy clock). You should probably include
     <sys/resource.h>.

`d_gnulibc'
     From `d_gnulibc.U':

     Defined if we're dealing with the GNU C Library.

`d_grpasswd'
     From `i_grp.U':

     This variable conditionally defines `GRPASSWD', which indicates that
     struct group in <grp.h> contains gr_passwd.

`d_hasmntopt'
     From `d_hasmntopt.U':

     This variable conditionally defines the `HAS_HASMNTOPT' symbol, which
     indicates to the C program that the hasmntopt() routine is available
     to query the mount options of file systems.

`d_htonl'
     From `d_htonl.U':

     This variable conditionally defines `HAS_HTONL' if htonl() and its
     friends are available to do network order byte swapping.

`d_iconv'
     From `d_iconv.U':

     This variable conditionally defines the `HAS_ICONV' symbol, which
     indicates to the C program that the iconv() routine is available.

`d_index'
     From `d_strchr.U':

     This variable conditionally defines `HAS_INDEX' if index() and
     rindex() are available for string searching.

`d_inetaton'
     From `d_inetaton.U':

     This variable conditionally defines the `HAS_INET_ATON' symbol, which
     indicates to the C program that the inet_aton() function is available
     to parse IP address `dotted-quad' strings.

`d_int64_t'
     From `d_int64_t.U':

     This symbol will be defined if the C compiler supports int64_t.

`d_isascii'
     From `d_isascii.U':

     This variable conditionally defines the `HAS_ISASCII' constant, which
     indicates to the C program that isascii() is available.

`d_killpg'
     From `d_killpg.U':

     This variable conditionally defines the `HAS_KILLPG' symbol, which
     indicates to the C program that the killpg() routine is available to
     kill process groups.

`d_lchown'
     From `d_lchown.U':

     This variable conditionally defines the `HAS_LCHOWN' symbol, which
     indicates to the C program that the lchown() routine is available to
     operate on a symbolic link (instead of following the link).

`d_ldbl_dig'
     From `d_ldbl_dig.U':

     This variable conditionally defines d_ldbl_dig if this system's
     header files provide `LDBL_DIG', which is the number of significant
     digits in a long double precision number.

`d_link'
     From `d_link.U':

     This variable conditionally defines `HAS_LINK' if link() is available
     to create hard links.

`d_locconv'
     From `d_locconv.U':

     This variable conditionally defines `HAS_LOCALECONV' if localeconv()
     is available for numeric and monetary formatting conventions.

`d_lockf'
     From `d_lockf.U':

     This variable conditionally defines `HAS_LOCKF' if lockf() is
     available to do file locking.

`d_longdbl'
     From `d_longdbl.U':

     This variable conditionally defines `HAS_LONG_DOUBLE' if the long
     double type is supported.

`d_longlong'
     From `d_longlong.U':

     This variable conditionally defines `HAS_LONG_LONG' if the long long
     type is supported.

`d_lseekproto'
     From `d_lseekproto.U':

     This variable conditionally defines the `HAS_LSEEK_PROTO' symbol,
     which indicates to the C program that the system provides a prototype
     for the lseek() function.  Otherwise, it is up to the program to
     supply one.

`d_lstat'
     From `d_lstat.U':

     This variable conditionally defines `HAS_LSTAT' if lstat() is
     available to do file stats on symbolic links.

`d_madvise'
     From `d_madvise.U':

     This variable conditionally defines `HAS_MADVISE' if madvise() is
     available to map a file into memory.

`d_mblen'
     From `d_mblen.U':

     This variable conditionally defines the `HAS_MBLEN' symbol, which
     indicates to the C program that the mblen() routine is available to
     find the number of bytes in a multibye character.

`d_mbstowcs'
     From `d_mbstowcs.U':

     This variable conditionally defines the `HAS_MBSTOWCS' symbol, which
     indicates to the C program that the mbstowcs() routine is available
     to convert a multibyte string into a wide character string.

`d_mbtowc'
     From `d_mbtowc.U':

     This variable conditionally defines the `HAS_MBTOWC' symbol, which
     indicates to the C program that the mbtowc() routine is available to
     convert multibyte to a wide character.

`d_memchr'
     From `d_memchr.U':

     This variable conditionally defines the `HAS_MEMCHR' symbol, which
     indicates to the C program that the memchr() routine is available to
     locate characters within a C string.

`d_memcmp'
     From `d_memcmp.U':

     This variable conditionally defines the `HAS_MEMCMP' symbol, which
     indicates to the C program that the memcmp() routine is available to
     compare blocks of memory.

`d_memcpy'
     From `d_memcpy.U':

     This variable conditionally defines the `HAS_MEMCPY' symbol, which
     indicates to the C program that the memcpy() routine is available to
     copy blocks of memory.

`d_memmove'
     From `d_memmove.U':

     This variable conditionally defines the `HAS_MEMMOVE' symbol, which
     indicates to the C program that the memmove() routine is available to
     copy potentatially overlapping blocks of memory.

`d_memset'
     From `d_memset.U':

     This variable conditionally defines the `HAS_MEMSET' symbol, which
     indicates to the C program that the memset() routine is available to
     set blocks of memory.

`d_mkdir'
     From `d_mkdir.U':

     This variable conditionally defines the `HAS_MKDIR' symbol, which
     indicates to the C program that the mkdir() routine is available to
     create `directories.'.

`d_mkdtemp'
     From `d_mkdtemp.U':

     This variable conditionally defines the `HAS_MKDTEMP' symbol, which
     indicates to the C program that the mkdtemp() routine is available to
     exclusively create a uniquely named temporary directory.

`d_mkfifo'
     From `d_mkfifo.U':

     This variable conditionally defines the `HAS_MKFIFO' symbol, which
     indicates to the C program that the mkfifo() routine is available.

`d_mkstemp'
     From `d_mkstemp.U':

     This variable conditionally defines the `HAS_MKSTEMP' symbol, which
     indicates to the C program that the mkstemp() routine is available to
     exclusively create and open a uniquely named temporary file.

`d_mkstemps'
     From `d_mkstemps.U':

     This variable conditionally defines the `HAS_MKSTEMPS' symbol, which
     indicates to the C program that the mkstemps() routine is available
     to exclusively create and open a uniquely named (with a suffix)
     temporary file.

`d_mktime'
     From `d_mktime.U':

     This variable conditionally defines the `HAS_MKTIME' symbol, which
     indicates to the C program that the mktime() routine is available.

`d_mmap'
     From `d_mmap.U':

     This variable conditionally defines `HAS_MMAP' if mmap() is available
     to map a file into memory.

`d_mprotect'
     From `d_mprotect.U':

     This variable conditionally defines `HAS_MPROTECT' if mprotect() is
     available to modify the access protection of a memory mapped file.

`d_msg'
     From `d_msg.U':

     This variable conditionally defines the `HAS_MSG' symbol, which
     indicates that the entire msg*(2) library is present.

`d_msg_ctrunc'
     From `d_socket.U':

     This variable conditionally defines the `HAS_MSG_CTRUNC' symbol,
     which indicates that the `MSG_CTRUNC' is available.  #ifdef is not
     enough because it may be an enum, glibc has been known to do this.

`d_msg_dontroute'
     From `d_socket.U':

     This variable conditionally defines the `HAS_MSG_DONTROUTE' symbol,
     which indicates that the `MSG_DONTROUTE' is available.  #ifdef is not
     enough because it may be an enum, glibc has been known to do this.

`d_msg_oob'
     From `d_socket.U':

     This variable conditionally defines the `HAS_MSG_OOB' symbol, which
     indicates that the `MSG_OOB' is available.  #ifdef is not enough
     because it may be an enum, glibc has been known to do this.

`d_msg_peek'
     From `d_socket.U':

     This variable conditionally defines the `HAS_MSG_PEEK' symbol, which
     indicates that the `MSG_PEEK' is available.  #ifdef is not enough
     because it may be an enum, glibc has been known to do this.

`d_msg_proxy'
     From `d_socket.U':

     This variable conditionally defines the `HAS_MSG_PROXY' symbol, which
     indicates that the `MSG_PROXY' is available.  #ifdef is not enough
     because it may be an enum, glibc has been known to do this.

`d_msgctl'
     From `d_msgctl.U':

     This variable conditionally defines the `HAS_MSGCTL' symbol, which
     indicates to the C program that the msgctl() routine is available.

`d_msgget'
     From `d_msgget.U':

     This variable conditionally defines the `HAS_MSGGET' symbol, which
     indicates to the C program that the msgget() routine is available.

`d_msgrcv'
     From `d_msgrcv.U':

     This variable conditionally defines the `HAS_MSGRCV' symbol, which
     indicates to the C program that the msgrcv() routine is available.

`d_msgsnd'
     From `d_msgsnd.U':

     This variable conditionally defines the `HAS_MSGSND' symbol, which
     indicates to the C program that the msgsnd() routine is available.

`d_msync'
     From `d_msync.U':

     This variable conditionally defines `HAS_MSYNC' if msync() is
     available to synchronize a mapped file.

`d_munmap'
     From `d_munmap.U':

     This variable conditionally defines `HAS_MUNMAP' if munmap() is
     available to unmap a region mapped by mmap().

`d_mymalloc'
     From `mallocsrc.U':

     This variable conditionally defines `MYMALLOC' in case other parts of
     the source want to take special action if `MYMALLOC' is used.  This
     may include different sorts of profiling or error detection.

`d_nice'
     From `d_nice.U':

     This variable conditionally defines the `HAS_NICE' symbol, which
     indicates to the C program that the nice() routine is available.

`d_nv_preserves_uv'
     From `perlxv.U':

     This variable indicates whether a variable of type nvtype can
     preserve all the bits a variable of type uvtype.

`d_off64_t'
     From `d_off64_t.U':

     This symbol will be defined if the C compiler supports off64_t.

`d_old_pthread_create_joinable'
     From `d_pthrattrj.U':

     This variable conditionally defines pthread_create_joinable.  undef
     if `pthread.h' defines `PTHREAD_CREATE_JOINABLE'.

`d_oldpthreads'
     From `usethreads.U':

     This variable conditionally defines the `OLD_PTHREADS_API' symbol,
     and indicates that Perl should be built to use the old draft POSIX
     threads API.  This is only potentially meaningful if usethreads is
     set.

`d_oldsock'
     From `d_socket.U':

     This variable conditionally defines the `OLDSOCKET' symbol, which
     indicates that the `BSD' socket interface is based on 4.1c and not
     4.2.

`d_open3'
     From `d_open3.U':

     This variable conditionally defines the HAS_OPEN3 manifest constant,
     which indicates to the C program that the 3 argument version of the
     open(2) function is available.

`d_pathconf'
     From `d_pathconf.U':

     This variable conditionally defines the `HAS_PATHCONF' symbol, which
     indicates to the C program that the pathconf() routine is available
     to determine file-system related limits and options associated with a
     given filename.

`d_pause'
     From `d_pause.U':

     This variable conditionally defines the `HAS_PAUSE' symbol, which
     indicates to the C program that the pause() routine is available to
     suspend a process until a signal is received.

`d_phostname'
     From `d_gethname.U':

     This variable conditionally defines the `HAS_PHOSTNAME' symbol, which
     contains the shell command which, when fed to popen(), may be used to
     derive the host name.

`d_pipe'
     From `d_pipe.U':

     This variable conditionally defines the `HAS_PIPE' symbol, which
     indicates to the C program that the pipe() routine is available to
     create an inter-process channel.

`d_poll'
     From `d_poll.U':

     This variable conditionally defines the `HAS_POLL' symbol, which
     indicates to the C program that the poll() routine is available to
     poll active file descriptors.

`d_portable'
     From `d_portable.U':

     This variable conditionally defines the `PORTABLE' symbol, which
     indicates to the C program that it should not assume that it is
     running on the machine it was compiled on.

`d_PRId64'
     From `quadfio.U':

     This variable conditionally defines the PERL_PRId64 symbol, which
     indiciates that stdio has a symbol to print 64-bit decimal numbers.

`d_PRIeldbl'
     From `longdblfio.U':

     This variable conditionally defines the PERL_PRIfldlbl symbol, which
     indiciates that stdio has a symbol to print long doubles.

`d_PRIEldbl'
     From `longdblfio.U':

     This variable conditionally defines the PERL_PRIfldlbl symbol, which
     indiciates that stdio has a symbol to print long doubles.

`d_PRIfldbl'
     From `longdblfio.U':

     This variable conditionally defines the PERL_PRIfldlbl symbol, which
     indiciates that stdio has a symbol to print long doubles.

`d_PRIFldbl'
     From `longdblfio.U':

     This variable conditionally defines the PERL_PRIfldlbl symbol, which
     indiciates that stdio has a symbol to print long doubles.

`d_PRIgldbl'
     From `longdblfio.U':

     This variable conditionally defines the PERL_PRIfldlbl symbol, which
     indiciates that stdio has a symbol to print long doubles.

`d_PRIGldbl'
     From `longdblfio.U':

     This variable conditionally defines the PERL_PRIfldlbl symbol, which
     indiciates that stdio has a symbol to print long doubles.

`d_PRIi64'
     From `quadfio.U':

     This variable conditionally defines the PERL_PRIi64 symbol, which
     indiciates that stdio has a symbol to print 64-bit decimal numbers.

`d_PRIo64'
     From `quadfio.U':

     This variable conditionally defines the PERL_PRIo64 symbol, which
     indiciates that stdio has a symbol to print 64-bit octal numbers.

`d_PRIu64'
     From `quadfio.U':

     This variable conditionally defines the PERL_PRIu64 symbol, which
     indiciates that stdio has a symbol to print 64-bit unsigned decimal
     numbers.

`d_PRIx64'
     From `quadfio.U':

     This variable conditionally defines the PERL_PRIx64 symbol, which
     indiciates that stdio has a symbol to print 64-bit hexadecimal
     numbers.

`d_PRIX64'
     From `quadfio.U':

     This variable conditionally defines the PERL_PRIX64 symbol, which
     indiciates that stdio has a symbol to print 64-bit hExADECimAl
     numbers.

`d_pthread_yield'
     From `d_pthread_y.U':

     This variable conditionally defines the `HAS_PTHREAD_YIELD' symbol if
     the pthread_yield routine is available to yield the execution of the
     current thread.

`d_pwage'
     From `i_pwd.U':

     This variable conditionally defines `PWAGE', which indicates that
     struct passwd contains pw_age.

`d_pwchange'
     From `i_pwd.U':

     This variable conditionally defines `PWCHANGE', which indicates that
     struct passwd contains pw_change.

`d_pwclass'
     From `i_pwd.U':

     This variable conditionally defines `PWCLASS', which indicates that
     struct passwd contains pw_class.

`d_pwcomment'
     From `i_pwd.U':

     This variable conditionally defines `PWCOMMENT', which indicates that
     struct passwd contains pw_comment.

`d_pwexpire'
     From `i_pwd.U':

     This variable conditionally defines `PWEXPIRE', which indicates that
     struct passwd contains pw_expire.

`d_pwgecos'
     From `i_pwd.U':

     This variable conditionally defines `PWGECOS', which indicates that
     struct passwd contains pw_gecos.

`d_pwpasswd'
     From `i_pwd.U':

     This variable conditionally defines `PWPASSWD', which indicates that
     struct passwd contains pw_passwd.

`d_pwquota'
     From `i_pwd.U':

     This variable conditionally defines `PWQUOTA', which indicates that
     struct passwd contains pw_quota.

`d_qgcvt'
     From `d_qgcvt.U':

     This variable conditionally defines the `HAS_QGCVT' symbol, which
     indicates to the C program that the qgcvt() routine is available.

`d_quad'
     From `quadtype.U':

     This variable, if defined, tells that there's a 64-bit integer type,
     quadtype.

`d_readdir'
     From `d_readdir.U':

     This variable conditionally defines `HAS_READDIR' if readdir() is
     available to read directory entries.

`d_readlink'
     From `d_readlink.U':

     This variable conditionally defines the `HAS_READLINK' symbol, which
     indicates to the C program that the readlink() routine is available
     to read the value of a symbolic link.

`d_rename'
     From `d_rename.U':

     This variable conditionally defines the `HAS_RENAME' symbol, which
     indicates to the C program that the rename() routine is available to
     rename files.

`d_rewinddir'
     From `d_readdir.U':

     This variable conditionally defines `HAS_REWINDDIR' if rewinddir() is
     available.

`d_rmdir'
     From `d_rmdir.U':

     This variable conditionally defines `HAS_RMDIR' if rmdir() is
     available to remove directories.

`d_safebcpy'
     From `d_safebcpy.U':

     This variable conditionally defines the `HAS_SAFE_BCOPY' symbol if
     the bcopy() routine can do overlapping copies.

`d_safemcpy'
     From `d_safemcpy.U':

     This variable conditionally defines the `HAS_SAFE_MEMCPY' symbol if
     the memcpy() routine can do overlapping copies.

`d_sanemcmp'
     From `d_sanemcmp.U':

     This variable conditionally defines the `HAS_SANE_MEMCMP' symbol if
     the memcpy() routine is available and can be used to compare relative
     magnitudes of chars with their high bits set.

`d_sched_yield'
     From `d_pthread_y.U':

     This variable conditionally defines the `HAS_SCHED_YIELD' symbol if
     the sched_yield routine is available to yield the execution of the
     current thread.

`d_scm_rights'
     From `d_socket.U':

     This variable conditionally defines the `HAS_SCM_RIGHTS' symbol,
     which indicates that the `SCM_RIGHTS' is available.  #ifdef is not
     enough because it may be an enum, glibc has been known to do this.

`d_seekdir'
     From `d_readdir.U':

     This variable conditionally defines `HAS_SEEKDIR' if seekdir() is
     available.

`d_select'
     From `d_select.U':

     This variable conditionally defines `HAS_SELECT' if select() is
     available to select active file descriptors. A <sys/time.h> inclusion
     may be necessary for the timeout field.

`d_sem'
     From `d_sem.U':

     This variable conditionally defines the `HAS_SEM' symbol, which
     indicates that the entire sem*(2) library is present.

`d_semctl'
     From `d_semctl.U':

     This variable conditionally defines the `HAS_SEMCTL' symbol, which
     indicates to the C program that the semctl() routine is available.

`d_semctl_semid_ds'
     From `d_union_semun.U':

     This variable conditionally defines `USE_SEMCTL_SEMID_DS', which
     indicates that struct semid_ds * is to be used for semctl `IPC_STAT'.

`d_semctl_semun'
     From `d_union_semun.U':

     This variable conditionally defines `USE_SEMCTL_SEMUN', which
     indicates that union semun is to be used for semctl `IPC_STAT'.

`d_semget'
     From `d_semget.U':

     This variable conditionally defines the `HAS_SEMGET' symbol, which
     indicates to the C program that the semget() routine is available.

`d_semop'
     From `d_semop.U':

     This variable conditionally defines the `HAS_SEMOP' symbol, which
     indicates to the C program that the semop() routine is available.

`d_setegid'
     From `d_setegid.U':

     This variable conditionally defines the `HAS_SETEGID' symbol, which
     indicates to the C program that the setegid() routine is available to
     change the effective gid of the current program.

`d_seteuid'
     From `d_seteuid.U':

     This variable conditionally defines the `HAS_SETEUID' symbol, which
     indicates to the C program that the seteuid() routine is available to
     change the effective uid of the current program.

`d_setgrent'
     From `d_setgrent.U':

     This variable conditionally defines the `HAS_SETGRENT' symbol, which
     indicates to the C program that the setgrent() routine is available
     for initializing sequential access to the group database.

`d_setgrps'
     From `d_setgrps.U':

     This variable conditionally defines the `HAS_SETGROUPS' symbol, which
     indicates to the C program that the setgroups() routine is available
     to set the list of process groups.

`d_sethent'
     From `d_sethent.U':

     This variable conditionally defines `HAS_SETHOSTENT' if sethostent()
     is available.

`d_setlinebuf'
     From `d_setlnbuf.U':

     This variable conditionally defines the `HAS_SETLINEBUF' symbol, which
     indicates to the C program that the setlinebuf() routine is available
     to change stderr or stdout from block-buffered or unbuffered to a
     line-buffered mode.

`d_setlocale'
     From `d_setlocale.U':

     This variable conditionally defines `HAS_SETLOCALE' if setlocale() is
     available to handle locale-specific ctype implementations.

`d_setnent'
     From `d_setnent.U':

     This variable conditionally defines `HAS_SETNETENT' if setnetent() is
     available.

`d_setpent'
     From `d_setpent.U':

     This variable conditionally defines `HAS_SETPROTOENT' if
     setprotoent() is available.

`d_setpgid'
     From `d_setpgid.U':

     This variable conditionally defines the `HAS_SETPGID' symbol if the
     setpgid(pid, gpid) function is available to set process group ID.

`d_setpgrp2'
     From `d_setpgrp2.U':

     This variable conditionally defines the HAS_SETPGRP2 symbol, which
     indicates to the C program that the setpgrp2() (as in `DG/`UX'')
     routine is available to set the current process group.

`d_setpgrp'
     From `d_setpgrp.U':

     This variable conditionally defines `HAS_SETPGRP' if setpgrp() is
     available to set the current process group.

`d_setprior'
     From `d_setprior.U':

     This variable conditionally defines `HAS_SETPRIORITY' if setpriority()
     is available to set a process's priority.

`d_setpwent'
     From `d_setpwent.U':

     This variable conditionally defines the `HAS_SETPWENT' symbol, which
     indicates to the C program that the setpwent() routine is available
     for initializing sequential access to the passwd database.

`d_setregid'
     From `d_setregid.U':

     This variable conditionally defines `HAS_SETREGID' if setregid() is
     available to change the real and effective gid of the current process.

`d_setresgid'
     From `d_setregid.U':

     This variable conditionally defines `HAS_SETRESGID' if setresgid() is
     available to change the real, effective and saved gid of the current
     process.

`d_setresuid'
     From `d_setreuid.U':

     This variable conditionally defines `HAS_SETREUID' if setresuid() is
     available to change the real, effective and saved uid of the current
     process.

`d_setreuid'
     From `d_setreuid.U':

     This variable conditionally defines `HAS_SETREUID' if setreuid() is
     available to change the real and effective uid of the current process.

`d_setrgid'
     From `d_setrgid.U':

     This variable conditionally defines the `HAS_SETRGID' symbol, which
     indicates to the C program that the setrgid() routine is available to
     change the real gid of the current program.

`d_setruid'
     From `d_setruid.U':

     This variable conditionally defines the `HAS_SETRUID' symbol, which
     indicates to the C program that the setruid() routine is available to
     change the real uid of the current program.

`d_setsent'
     From `d_setsent.U':

     This variable conditionally defines `HAS_SETSERVENT' if setservent()
     is available.

`d_setsid'
     From `d_setsid.U':

     This variable conditionally defines `HAS_SETSID' if setsid() is
     available to set the process group ID.

`d_setspent'
     From `d_setspent.U':

     This variable conditionally defines `HAS_SETSPENT' if setspent() is
     available to initialize the scan of SysV shadow password entries.

`d_setvbuf'
     From `d_setvbuf.U':

     This variable conditionally defines the `HAS_SETVBUF' symbol, which
     indicates to the C program that the setvbuf() routine is available to
     change buffering on an open stdio stream.

`d_sfio'
     From `d_sfio.U':

     This variable conditionally defines the `USE_SFIO' symbol, and
     indicates whether sfio is available (and should be used).

`d_shm'
     From `d_shm.U':

     This variable conditionally defines the `HAS_SHM' symbol, which
     indicates that the entire shm*(2) library is present.

`d_shmat'
     From `d_shmat.U':

     This variable conditionally defines the `HAS_SHMAT' symbol, which
     indicates to the C program that the shmat() routine is available.

`d_shmatprototype'
     From `d_shmat.U':

     This variable conditionally defines the `HAS_SHMAT_PROTOTYPE' symbol,
     which indicates that `sys/shm.h' has a prototype for shmat.

`d_shmctl'
     From `d_shmctl.U':

     This variable conditionally defines the `HAS_SHMCTL' symbol, which
     indicates to the C program that the shmctl() routine is available.

`d_shmdt'
     From `d_shmdt.U':

     This variable conditionally defines the `HAS_SHMDT' symbol, which
     indicates to the C program that the shmdt() routine is available.

`d_shmget'
     From `d_shmget.U':

     This variable conditionally defines the `HAS_SHMGET' symbol, which
     indicates to the C program that the shmget() routine is available.

`d_sigaction'
     From `d_sigaction.U':

     This variable conditionally defines the `HAS_SIGACTION' symbol, which
     indicates that the Vr4 sigaction() routine is available.

`d_sigsetjmp'
     From `d_sigsetjmp.U':

     This variable conditionally defines the `HAS_SIGSETJMP' symbol, which
     indicates that the sigsetjmp() routine is available to call setjmp()
     and optionally save the process's signal mask.

`d_socket'
     From `d_socket.U':

     This variable conditionally defines `HAS_SOCKET', which indicates
     that the `BSD' socket interface is supported.

`d_socklen_t'
     From `d_socklen_t.U':

     This symbol will be defined if the C compiler supports socklen_t.

`d_sockpair'
     From `d_socket.U':

     This variable conditionally defines the `HAS_SOCKETPAIR' symbol, which
     indicates that the `BSD' socketpair() is supported.

`d_sqrtl'
     From `d_sqrtl.U':

     This variable conditionally defines the `HAS_SQRTL' symbol, which
     indicates to the C program that the sqrtl() routine is available.

`d_statblks'
     From `d_statblks.U':

     This variable conditionally defines `USE_STAT_BLOCKS' if this system
     has a stat structure declaring st_blksize and st_blocks.

`d_statfs_f_flags'
     From `d_statfs_f_flags.U':

     This variable conditionally defines the `HAS_STRUCT_STATFS_F_FLAGS'
     symbol, which indicates to struct statfs from has f_flags member.
     This kind of struct statfs is coming from `sys/mount.h' (`BSD'), not
     from `sys/statfs.h' (`SYSV').

`d_statfs_s'
     From `d_statfs_s.U':

     This variable conditionally defines the `HAS_STRUCT_STATFS' symbol,
     which indicates that the struct statfs is supported.

`d_statvfs'
     From `d_statvfs.U':

     This variable conditionally defines the `HAS_STATVFS' symbol, which
     indicates to the C program that the statvfs() routine is available.

`d_stdio_cnt_lval'
     From `d_stdstdio.U':

     This variable conditionally defines `STDIO_CNT_LVALUE' if the
     `FILE_cnt' macro can be used as an lvalue.

`d_stdio_ptr_lval'
     From `d_stdstdio.U':

     This variable conditionally defines `STDIO_PTR_LVALUE' if the
     `FILE_ptr' macro can be used as an lvalue.

`d_stdio_stream_array'
     From `stdio_streams.U':

     This variable tells whether there is an array holding the stdio
     streams.

`d_stdiobase'
     From `d_stdstdio.U':

     This variable conditionally defines `USE_STDIO_BASE' if this system
     has a FILE structure declaring a usable _base field (or equivalent)
     in `stdio.h'.

`d_stdstdio'
     From `d_stdstdio.U':

     This variable conditionally defines `USE_STDIO_PTR' if this system
     has a FILE structure declaring usable _ptr and _cnt fields (or
     equivalent) in `stdio.h'.

`d_strchr'
     From `d_strchr.U':

     This variable conditionally defines `HAS_STRCHR' if strchr() and
     strrchr() are available for string searching.

`d_strcoll'
     From `d_strcoll.U':

     This variable conditionally defines `HAS_STRCOLL' if strcoll() is
     available to compare strings using collating information.

`d_strctcpy'
     From `d_strctcpy.U':

     This variable conditionally defines the `USE_STRUCT_COPY' symbol,
     which indicates to the C program that this C compiler knows how to
     copy structures.

`d_strerrm'
     From `d_strerror.U':

     This variable holds what Strerrr is defined as to translate an error
     code condition into an error message string. It could be strerror or
     a more `complex' macro emulating strrror with sys_errlist[], or the
     `unknown' string when both strerror and sys_errlist are missing.

`d_strerror'
     From `d_strerror.U':

     This variable conditionally defines `HAS_STRERROR' if strerror() is
     available to translate error numbers to strings.

`d_strtod'
     From `d_strtod.U':

     This variable conditionally defines the `HAS_STRTOD' symbol, which
     indicates to the C program that the strtod() routine is available to
     provide better numeric string conversion than atof().

`d_strtol'
     From `d_strtol.U':

     This variable conditionally defines the `HAS_STRTOL' symbol, which
     indicates to the C program that the strtol() routine is available to
     provide better numeric string conversion than atoi() and friends.

`d_strtold'
     From `d_strtold.U':

     This variable conditionally defines the `HAS_STRTOLD' symbol, which
     indicates to the C program that the strtold() routine is available.

`d_strtoll'
     From `d_strtoll.U':

     This variable conditionally defines the `HAS_STRTOLL' symbol, which
     indicates to the C program that the strtoll() routine is available.

`d_strtoul'
     From `d_strtoul.U':

     This variable conditionally defines the `HAS_STRTOUL' symbol, which
     indicates to the C program that the strtoul() routine is available to
     provide conversion of strings to unsigned long.

`d_strtoull'
     From `d_strtoull.U':

     This variable conditionally defines the `HAS_STRTOULL' symbol, which
     indicates to the C program that the strtoull() routine is available.

`d_strtouq'
     From `d_strtouq.U':

     This variable conditionally defines the `HAS_STRTOUQ' symbol, which
     indicates to the C program that the strtouq() routine is available.

`d_strxfrm'
     From `d_strxfrm.U':

     This variable conditionally defines `HAS_STRXFRM' if strxfrm() is
     available to transform strings.

`d_suidsafe'
     From `d_dosuid.U':

     This variable conditionally defines `SETUID_SCRIPTS_ARE_SECURE_NOW'
     if setuid scripts can be secure.  This test looks in `/dev/fd/'.

`d_symlink'
     From `d_symlink.U':

     This variable conditionally defines the `HAS_SYMLINK' symbol, which
     indicates to the C program that the symlink() routine is available to
     create symbolic links.

`d_syscall'
     From `d_syscall.U':

     This variable conditionally defines `HAS_SYSCALL' if syscall() is
     available call arbitrary system calls.

`d_sysconf'
     From `d_sysconf.U':

     This variable conditionally defines the `HAS_SYSCONF' symbol, which
     indicates to the C program that the sysconf() routine is available to
     determine system related limits and options.

`d_sysernlst'
     From `d_strerror.U':

     This variable conditionally defines `HAS_SYS_ERRNOLIST' if
     sys_errnolist[] is available to translate error numbers to the
     symbolic name.

`d_syserrlst'
     From `d_strerror.U':

     This variable conditionally defines `HAS_SYS_ERRLIST' if
     sys_errlist[] is available to translate error numbers to strings.

`d_system'
     From `d_system.U':

     This variable conditionally defines `HAS_SYSTEM' if system() is
     available to issue a shell command.

`d_tcgetpgrp'
     From `d_tcgtpgrp.U':

     This variable conditionally defines the `HAS_TCGETPGRP' symbol, which
     indicates to the C program that the tcgetpgrp() routine is available.
     to get foreground process group ID.

`d_tcsetpgrp'
     From `d_tcstpgrp.U':

     This variable conditionally defines the `HAS_TCSETPGRP' symbol, which
     indicates to the C program that the tcsetpgrp() routine is available
     to set foreground process group ID.

`d_telldir'
     From `d_readdir.U':

     This variable conditionally defines `HAS_TELLDIR' if telldir() is
     available.

`d_telldirproto'
     From `d_telldirproto.U':

     This variable conditionally defines the `HAS_TELLDIR_PROTO' symbol,
     which indicates to the C program that the system provides a prototype
     for the telldir() function.  Otherwise, it is up to the program to
     supply one.

`d_time'
     From `d_time.U':

     This variable conditionally defines the `HAS_TIME' symbol, which
     indicates that the time() routine exists.  The time() routine is
     normaly provided on UNIX systems.

`d_times'
     From `d_times.U':

     This variable conditionally defines the `HAS_TIMES' symbol, which
     indicates that the times() routine exists.  The times() routine is
     normaly provided on UNIX systems. You may have to include
     <sys/times.h>.

`d_truncate'
     From `d_truncate.U':

     This variable conditionally defines `HAS_TRUNCATE' if truncate() is
     available to truncate files.

`d_tzname'
     From `d_tzname.U':

     This variable conditionally defines `HAS_TZNAME' if tzname[] is
     available to access timezone names.

`d_umask'
     From `d_umask.U':

     This variable conditionally defines the `HAS_UMASK' symbol, which
     indicates to the C program that the umask() routine is available.  to
     set and get the value of the file creation mask.

`d_uname'
     From `d_gethname.U':

     This variable conditionally defines the `HAS_UNAME' symbol, which
     indicates to the C program that the uname() routine may be used to
     derive the host name.

`d_union_semun'
     From `d_union_semun.U':

     This variable conditionally defines `HAS_UNION_SEMUN' if the union
     semun is defined by including <sys/sem.h>.

`d_ustat'
     From `d_ustat.U':

     This variable conditionally defines `HAS_USTAT' if ustat() is
     available to query file system statistics by dev_t.

`d_vendorarch'
     From `vendorarch.U':

     This variable conditionally defined `PERL_VENDORARCH'.

`d_vendorbin'
     From `vendorbin.U':

     This variable conditionally defines `PERL_VENDORBIN'.

`d_vendorlib'
     From `vendorlib.U':

     This variable conditionally defines `PERL_VENDORLIB'.

`d_vfork'
     From `d_vfork.U':

     This variable conditionally defines the `HAS_VFORK' symbol, which
     indicates the vfork() routine is available.

`d_void_closedir'
     From `d_closedir.U':

     This variable conditionally defines `VOID_CLOSEDIR' if closedir()
     does not return a value.

`d_voidsig'
     From `d_voidsig.U':

     This variable conditionally defines `VOIDSIG' if this system declares
     "void (*signal(...))()" in `signal.h'.  The old way was to declare it
     as "int (*signal(...))()".

`d_voidtty'
     From `i_sysioctl.U':

     This variable conditionally defines `USE_IOCNOTTY' to indicate that
     the ioctl() call with `TIOCNOTTY' should be used to void tty
     association.  Otherwise (on `USG' probably), it is enough to close
     the standard file decriptors and do a setpgrp().

`d_volatile'
     From `d_volatile.U':

     This variable conditionally defines the `HASVOLATILE' symbol, which
     indicates to the C program that this C compiler knows about the
     volatile declaration.

`d_vprintf'
     From `d_vprintf.U':

     This variable conditionally defines the `HAS_VPRINTF' symbol, which
     indicates to the C program that the vprintf() routine is available to
     printf with a pointer to an argument list.

`d_wait4'
     From `d_wait4.U':

     This variable conditionally defines the HAS_WAIT4 symbol, which
     indicates the wait4() routine is available.

`d_waitpid'
     From `d_waitpid.U':

     This variable conditionally defines `HAS_WAITPID' if waitpid() is
     available to wait for child process.

`d_wcstombs'
     From `d_wcstombs.U':

     This variable conditionally defines the `HAS_WCSTOMBS' symbol, which
     indicates to the C program that the wcstombs() routine is available
     to convert wide character strings to multibyte strings.

`d_wctomb'
     From `d_wctomb.U':

     This variable conditionally defines the `HAS_WCTOMB' symbol, which
     indicates to the C program that the wctomb() routine is available to
     convert a wide character to a multibyte.

`d_xenix'
     From `Guess.U':

     This variable conditionally defines the symbol `XENIX', which alerts
     the C program that it runs under Xenix.

date
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the date program.  After Configure runs, the
     value is reset to a plain date and is not useful.

`db_hashtype'
     From `i_db.U':

     This variable contains the type of the hash structure element in the
     <db.h> header file.  In older versions of DB, it was int, while in
     newer ones it is u_int32_t.

`db_prefixtype'
     From `i_db.U':

     This variable contains the type of the prefix structure element in
     the <db.h> header file.  In older versions of DB, it was int, while
     in newer ones it is size_t.

`defvoidused'
     From `voidflags.U':

     This variable contains the default value of the `VOIDUSED' symbol
     (15).

`direntrytype'
     From `i_dirent.U':

     This symbol is set to `struct direct' or `struct dirent' depending on
     whether dirent is available or not. You should use this pseudo type to
     portably declare your directory entries.

`dlext'
     From `dlext.U':

     This variable contains the extension that is to be used for the
     dynamically loaded modules that perl generaties.

`dlsrc'
     From `dlsrc.U':

     This variable contains the name of the dynamic loading file that will
     be used with the package.

`doublesize'
     From `doublesize.U':

     This variable contains the value of the `DOUBLESIZE' symbol, which
     indicates to the C program how many bytes there are in a double.

`drand01'
     From `randfunc.U':

     Indicates the macro to be used to generate normalized random numbers.
     Uses randfunc, often divided by (double) (((unsigned long) 1 <<
     randbits)) in order to normalize the result.  In C programs, the
     macro `Drand01' is mapped to drand01.

`dynamic_ext'
     From `Extensions.U':

     This variable holds a list of XS extension files we want to link
     dynamically into the package.  It is used by Makefile.

e
-

`eagain'
     From `nblock_io.U':

     This variable bears the symbolic errno code set by read() when no
     data is present on the file and non-blocking I/O was enabled
     (otherwise, read() blocks naturally).

`ebcdic'
     From `ebcdic.U':

     This variable conditionally defines EBCDIC if this system uses EBCDIC
     encoding.  Among other things, this means that the character ranges
     are not contiguous.  See `trnl.U'

echo
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the echo program.  After Configure runs, the
     value is reset to a plain echo and is not useful.

`egrep'
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the egrep program.  After Configure runs, the
     value is reset to a plain `egrep' and is not useful.

emacs
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`eunicefix'
     From `Init.U':

     When running under Eunice this variable contains a command which will
     convert a shell script to the proper form of text file for it to be
     executable by the shell.  On other systems it is a no-op.

`exe_ext'
     From `Unix.U':

     This is an old synonym for _exe.

`expr'
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the expr program.  After Configure runs, the
     value is reset to a plain `expr' and is not useful.

`extensions'
     From `Extensions.U':

     This variable holds a list of all extension files (both XS and non-xs
     linked into the package.  It is propagated to Config.pm and is
     typically used to test whether a particular extesion is available.

f
-

`fflushall'
     From `fflushall.U':

     This symbol, if defined, tells that to flush all pending stdio output
     one must loop through all the stdio file handles stored in an array
     and fflush them.  Note that if fflushNULL is defined, fflushall will
     not even be probed for and will be left undefined.

`fflushNULL'
     From `fflushall.U':

     This symbol, if defined, tells that fflush(NULL) does flush all
     pending stdio output.

find
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`firstmakefile'
     From `Unix.U':

     This variable defines the first file searched by make.  On unix, it
     is makefile (then Makefile).  On case-insensitive systems, it might
     be something else.  This is only used to deal with convoluted make
     depend tricks.

`flex'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`fpossize'
     From `fpossize.U':

     This variable contains the size of a fpostype in bytes.

`fpostype'
     From `fpostype.U':

     This variable defines Fpos_t to be something like fpos_t, long, uint,
     or whatever type is used to declare file positions in libc.

`freetype'
     From `mallocsrc.U':

     This variable contains the return type of free().  It is usually
     void, but occasionally int.

`full_ar'
     From `Loc_ar.U':

     This variable contains the full pathname to `ar', whether or not the
     user has specified `portability'.  This is only used in the
     `Makefile.SH'.

`full_csh'
     From `d_csh.U':

     This variable contains the full pathname to `csh', whether or not the
     user has specified `portability'.  This is only used in the compiled
     C program, and we assume that all systems which can share this
     executable will have the same full pathname to `csh.'

`full_sed'
     From `Loc_sed.U':

     This variable contains the full pathname to `sed', whether or not the
     user has specified `portability'.  This is only used in the compiled
     C program, and we assume that all systems which can share this
     executable will have the same full pathname to `sed.'

g
-

`gccversion'
     From `cc.U':

     If GNU cc (gcc) is used, this variable holds 1 or 2 to indicate
     whether the compiler is version 1 or 2.  This is used in setting some
     of the default cflags.  It is set to " if not gcc.

`gidformat'
     From `gidf.U':

     This variable contains the format string used for printing a Gid_t.

`gidsign'
     From `gidsign.U':

     This variable contains the signedness of a gidtype.  1 for unsigned,
     -1 for signed.

`gidsize'
     From `gidsize.U':

     This variable contains the size of a gidtype in bytes.

`gidtype'
     From `gidtype.U':

     This variable defines Gid_t to be something like gid_t, int, ushort,
     or whatever type is used to declare the return type of getgid().
     Typically, it is the type of group ids in the kernel.

`glibpth'
     From `libpth.U':

     This variable holds the general path (space-separated) used to find
     libraries.  It may contain directories that do not exist on this
     platform, libpth is the cleaned-up version.

grep
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the grep program.  After Configure runs, the
     value is reset to a plain grep and is not useful.

`groupcat'
     From `nis.U':

     This variable contains a command that produces the text of the
     /etc/group file.  This is normally "cat /etc/group", but can be
     "ypcat group" when NIS is used.  On some systems, such as os390,
     there may be no equivalent command, in which case this variable is
     unset.

`groupstype'
     From `groupstype.U':

     This variable defines Groups_t to be something like gid_t, int,
     ushort, or whatever type is used for the second argument to
     getgroups() and setgroups().  Usually, this is the same as gidtype
     (gid_t), but sometimes it isn't.

`gzip'
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the gzip program.  After Configure runs, the
     value is reset to a plain `gzip' and is not useful.

h
-

`h_fcntl'
     From `h_fcntl.U':

     This is variable gets set in various places to tell i_fcntl that
     <fcntl.h> should be included.

`h_sysfile'
     From `h_sysfile.U':

     This is variable gets set in various places to tell i_sys_file that
     <sys/file.h> should be included.

`hint'
     From `Oldconfig.U':

     Gives the type of hints used for previous answers. May be one of
     default, `recommended' or previous.

`hostcat'
     From `nis.U':

     This variable contains a command that produces the text of the
     `/etc/hosts' file.  This is normally "cat `/etc/hosts'", but can be
     "ypcat hosts" when NIS is used.  On some systems, such as os390,
     there may be no equivalent command, in which case this variable is
     unset.

`huge'
     From `models.U':

     This variable contains a flag which will tell the C compiler and
     loader to produce a program running with a huge memory model.  If the
     huge model is not supported, contains the flag to produce large model
     programs.  It is up to the Makefile to use this.

i
-

`i16size'
     From `perlxv.U':

     This variable is the size of an I16 in bytes.

`i16type'
     From `perlxv.U':

     This variable contains the C type used for Perl's I16.

`i32size'
     From `perlxv.U':

     This variable is the size of an I32 in bytes.

`i32type'
     From `perlxv.U':

     This variable contains the C type used for Perl's I32.

`i64size'
     From `perlxv.U':

     This variable is the size of an I64 in bytes.

`i64type'
     From `perlxv.U':

     This variable contains the C type used for Perl's I64.

`i8size'
     From `perlxv.U':

     This variable is the size of an I8 in bytes.

`i8type'
     From `perlxv.U':

     This variable contains the C type used for Perl's I8.

`i_arpainet'
     From `i_arpainet.U':

     This variable conditionally defines the `I_ARPA_INET' symbol, and
     indicates whether a C program should include <arpa/inet.h>.

`i_bsdioctl'
     From `i_sysioctl.U':

     This variable conditionally defines the `I_SYS_BSDIOCTL' symbol, which
     indicates to the C program that <sys/bsdioctl.h> exists and should be
     included.

`i_db'
     From `i_db.U':

     This variable conditionally defines the `I_DB' symbol, and indicates
     whether a C program may include Berkeley's DB include file <db.h>.

`i_dbm'
     From `i_dbm.U':

     This variable conditionally defines the `I_DBM' symbol, which
     indicates to the C program that <dbm.h> exists and should be included.

`i_dirent'
     From `i_dirent.U':

     This variable conditionally defines `I_DIRENT', which indicates to
     the C program that it should include <dirent.h>.

`i_dld'
     From `i_dld.U':

     This variable conditionally defines the `I_DLD' symbol, which
     indicates to the C program that <dld.h> (GNU dynamic loading) exists
     and should be included.

`i_dlfcn'
     From `i_dlfcn.U':

     This variable conditionally defines the `I_DLFCN' symbol, which
     indicates to the C program that <dlfcn.h> exists and should be
     included.

`i_fcntl'
     From `i_fcntl.U':

     This variable controls the value of `I_FCNTL' (which tells the C
     program to include <fcntl.h>).

`i_float'
     From `i_float.U':

     This variable conditionally defines the `I_FLOAT' symbol, and
     indicates whether a C program may include <float.h> to get symbols
     like `DBL_MAX' or `DBL_MIN', `i.e'. machine dependent floating point
     values.

`i_gdbm'
     From `i_gdbm.U':

     This variable conditionally defines the `I_GDBM' symbol, which
     indicates to the C program that <gdbm.h> exists and should be
     included.

`i_grp'
     From `i_grp.U':

     This variable conditionally defines the `I_GRP' symbol, and indicates
     whether a C program should include <grp.h>.

`i_iconv'
     From `i_iconv.U':

     This variable conditionally defines the `I_ICONV' symbol, and
     indicates whether a C program should include <iconv.h>.

`i_ieeefp'
     From `i_ieeefp.U':

     This variable conditionally defines the `I_IEEEFP' symbol, and
     indicates whether a C program should include <ieeefp.h>.

`i_inttypes'
     From `i_inttypes.U':

     This variable conditionally defines the `I_INTTYPES' symbol, and
     indicates whether a C program should include <inttypes.h>.

`i_limits'
     From `i_limits.U':

     This variable conditionally defines the `I_LIMITS' symbol, and
     indicates whether a C program may include <limits.h> to get symbols
     like `WORD_BIT' and friends.

`i_locale'
     From `i_locale.U':

     This variable conditionally defines the `I_LOCALE' symbol, and
     indicates whether a C program should include <locale.h>.

`i_machcthr'
     From `i_machcthr.U':

     This variable conditionally defines the `I_MACH_CTHREADS' symbol, and
     indicates whether a C program should include <mach/cthreads.h>.

`i_malloc'
     From `i_malloc.U':

     This variable conditionally defines the `I_MALLOC' symbol, and
     indicates whether a C program should include <malloc.h>.

`i_math'
     From `i_math.U':

     This variable conditionally defines the `I_MATH' symbol, and indicates
     whether a C program may include <math.h>.

`i_memory'
     From `i_memory.U':

     This variable conditionally defines the `I_MEMORY' symbol, and
     indicates whether a C program should include <memory.h>.

`i_mntent'
     From `i_mntent.U':

     This variable conditionally defines the `I_MNTENT' symbol, and
     indicates whether a C program should include <mntent.h>.

`i_ndbm'
     From `i_ndbm.U':

     This variable conditionally defines the `I_NDBM' symbol, which
     indicates to the C program that <ndbm.h> exists and should be
     included.

`i_netdb'
     From `i_netdb.U':

     This variable conditionally defines the `I_NETDB' symbol, and
     indicates whether a C program should include <netdb.h>.

`i_neterrno'
     From `i_neterrno.U':

     This variable conditionally defines the `I_NET_ERRNO' symbol, which
     indicates to the C program that <net/errno.h> exists and should be
     included.

`i_netinettcp'
     From `i_netinettcp.U':

     This variable conditionally defines the `I_NETINET_TCP' symbol, and
     indicates whether a C program should include <netinet/tcp.h>.

`i_niin'
     From `i_niin.U':

     This variable conditionally defines `I_NETINET_IN', which indicates
     to the C program that it should include <netinet/in.h>. Otherwise,
     you may try <sys/in.h>.

`i_poll'
     From `i_poll.U':

     This variable conditionally defines the `I_POLL' symbol, and indicates
     whether a C program should include <poll.h>.

`i_pthread'
     From `i_pthread.U':

     This variable conditionally defines the `I_PTHREAD' symbol, and
     indicates whether a C program should include <pthread.h>.

`i_pwd'
     From `i_pwd.U':

     This variable conditionally defines `I_PWD', which indicates to the C
     program that it should include <pwd.h>.

`i_rpcsvcdbm'
     From `i_dbm.U':

     This variable conditionally defines the `I_RPCSVC_DBM' symbol, which
     indicates to the C program that <rpcsvc/dbm.h> exists and should be
     included.  Some System V systems might need this instead of <dbm.h>.

`i_sfio'
     From `i_sfio.U':

     This variable conditionally defines the `I_SFIO' symbol, and
     indicates whether a C program should include <sfio.h>.

`i_sgtty'
     From `i_termio.U':

     This variable conditionally defines the `I_SGTTY' symbol, which
     indicates to the C program that it should include <sgtty.h> rather
     than <termio.h>.

`i_shadow'
     From `i_shadow.U':

     This variable conditionally defines the `I_SHADOW' symbol, and
     indicates whether a C program should include <shadow.h>.

`i_socks'
     From `i_socks.U':

     This variable conditionally defines the `I_SOCKS' symbol, and
     indicates whether a C program should include <socks.h>.

`i_stdarg'
     From `i_varhdr.U':

     This variable conditionally defines the `I_STDARG' symbol, which
     indicates to the C program that <stdarg.h> exists and should be
     included.

`i_stddef'
     From `i_stddef.U':

     This variable conditionally defines the `I_STDDEF' symbol, which
     indicates to the C program that <stddef.h> exists and should be
     included.

`i_stdlib'
     From `i_stdlib.U':

     This variable conditionally defines the `I_STDLIB' symbol, which
     indicates to the C program that <stdlib.h> exists and should be
     included.

`i_string'
     From `i_string.U':

     This variable conditionally defines the `I_STRING' symbol, which
     indicates that <string.h> should be included rather than <strings.h>.

`i_sunmath'
     From `i_sunmath.U':

     This variable conditionally defines the `I_SUNMATH' symbol, and
     indicates whether a C program should include <sunmath.h>.

`i_sysaccess'
     From `i_sysaccess.U':

     This variable conditionally defines the `I_SYS_ACCESS' symbol, and
     indicates whether a C program should include <sys/access.h>.

`i_sysdir'
     From `i_sysdir.U':

     This variable conditionally defines the `I_SYS_DIR' symbol, and
     indicates whether a C program should include <sys/dir.h>.

`i_sysfile'
     From `i_sysfile.U':

     This variable conditionally defines the `I_SYS_FILE' symbol, and
     indicates whether a C program should include <sys/file.h> to get
     `R_OK' and friends.

`i_sysfilio'
     From `i_sysioctl.U':

     This variable conditionally defines the `I_SYS_FILIO' symbol, which
     indicates to the C program that <sys/filio.h> exists and should be
     included in preference to <sys/ioctl.h>.

`i_sysin'
     From `i_niin.U':

     This variable conditionally defines `I_SYS_IN', which indicates to
     the C program that it should include <sys/in.h> instead of
     <netinet/in.h>.

`i_sysioctl'
     From `i_sysioctl.U':

     This variable conditionally defines the `I_SYS_IOCTL' symbol, which
     indicates to the C program that <sys/ioctl.h> exists and should be
     included.

`i_syslog'
     From `i_syslog.U':

     This variable conditionally defines the `I_SYSLOG' symbol, and
     indicates whether a C program should include <syslog.h>.

`i_sysmman'
     From `i_sysmman.U':

     This variable conditionally defines the `I_SYS_MMAN' symbol, and
     indicates whether a C program should include <sys/mman.h>.

`i_sysmode'
     From `i_sysmode.U':

     This variable conditionally defines the `I_SYSMODE' symbol, and
     indicates whether a C program should include <sys/mode.h>.

`i_sysmount'
     From `i_sysmount.U':

     This variable conditionally defines the `I_SYSMOUNT' symbol, and
     indicates whether a C program should include <sys/mount.h>.

`i_sysndir'
     From `i_sysndir.U':

     This variable conditionally defines the `I_SYS_NDIR' symbol, and
     indicates whether a C program should include <sys/ndir.h>.

`i_sysparam'
     From `i_sysparam.U':

     This variable conditionally defines the `I_SYS_PARAM' symbol, and
     indicates whether a C program should include <sys/param.h>.

`i_sysresrc'
     From `i_sysresrc.U':

     This variable conditionally defines the `I_SYS_RESOURCE' symbol, and
     indicates whether a C program should include <sys/resource.h>.

`i_syssecrt'
     From `i_syssecrt.U':

     This variable conditionally defines the `I_SYS_SECURITY' symbol, and
     indicates whether a C program should include <sys/security.h>.

`i_sysselct'
     From `i_sysselct.U':

     This variable conditionally defines `I_SYS_SELECT', which indicates
     to the C program that it should include <sys/select.h> in order to
     get the definition of struct timeval.

`i_syssockio'
     From `i_sysioctl.U':

     This variable conditionally defines `I_SYS_SOCKIO' to indicate to the
     C program that socket ioctl codes may be found in <sys/sockio.h>
     instead of <sys/ioctl.h>.

`i_sysstat'
     From `i_sysstat.U':

     This variable conditionally defines the `I_SYS_STAT' symbol, and
     indicates whether a C program should include <sys/stat.h>.

`i_sysstatfs'
     From `i_sysstatfs.U':

     This variable conditionally defines the `I_SYSSTATFS' symbol, and
     indicates whether a C program should include <sys/statfs.h>.

`i_sysstatvfs'
     From `i_sysstatvfs.U':

     This variable conditionally defines the `I_SYSSTATVFS' symbol, and
     indicates whether a C program should include <sys/statvfs.h>.

`i_systime'
     From `i_time.U':

     This variable conditionally defines `I_SYS_TIME', which indicates to
     the C program that it should include <sys/time.h>.

`i_systimek'
     From `i_time.U':

     This variable conditionally defines `I_SYS_TIME_KERNEL', which
     indicates to the C program that it should include <sys/time.h> with
     KERNEL defined.

`i_systimes'
     From `i_systimes.U':

     This variable conditionally defines the `I_SYS_TIMES' symbol, and
     indicates whether a C program should include <sys/times.h>.

`i_systypes'
     From `i_systypes.U':

     This variable conditionally defines the `I_SYS_TYPES' symbol, and
     indicates whether a C program should include <sys/types.h>.

`i_sysuio'
     From `i_sysuio.U':

     This variable conditionally defines the `I_SYSUIO' symbol, and
     indicates whether a C program should include <sys/uio.h>.

`i_sysun'
     From `i_sysun.U':

     This variable conditionally defines `I_SYS_UN', which indicates to
     the C program that it should include <sys/un.h> to get UNIX domain
     socket definitions.

`i_sysutsname'
     From `i_sysutsname.U':

     This variable conditionally defines the `I_SYSUTSNAME' symbol, and
     indicates whether a C program should include <sys/utsname.h>.

`i_sysvfs'
     From `i_sysvfs.U':

     This variable conditionally defines the `I_SYSVFS' symbol, and
     indicates whether a C program should include <sys/vfs.h>.

`i_syswait'
     From `i_syswait.U':

     This variable conditionally defines `I_SYS_WAIT', which indicates to
     the C program that it should include <sys/wait.h>.

`i_termio'
     From `i_termio.U':

     This variable conditionally defines the `I_TERMIO' symbol, which
     indicates to the C program that it should include <termio.h> rather
     than <sgtty.h>.

`i_termios'
     From `i_termio.U':

     This variable conditionally defines the `I_TERMIOS' symbol, which
     indicates to the C program that the POSIX <termios.h> file is to be
     included.

`i_time'
     From `i_time.U':

     This variable conditionally defines `I_TIME', which indicates to the
     C program that it should include <time.h>.

`i_unistd'
     From `i_unistd.U':

     This variable conditionally defines the `I_UNISTD' symbol, and
     indicates whether a C program should include <unistd.h>.

`i_ustat'
     From `i_ustat.U':

     This variable conditionally defines the `I_USTAT' symbol, and
     indicates whether a C program should include <ustat.h>.

`i_utime'
     From `i_utime.U':

     This variable conditionally defines the `I_UTIME' symbol, and
     indicates whether a C program should include <utime.h>.

`i_values'
     From `i_values.U':

     This variable conditionally defines the `I_VALUES' symbol, and
     indicates whether a C program may include <values.h> to get symbols
     like `MAXLONG' and friends.

`i_varargs'
     From `i_varhdr.U':

     This variable conditionally defines `I_VARARGS', which indicates to
     the C program that it should include <varargs.h>.

`i_varhdr'
     From `i_varhdr.U':

     Contains the name of the header to be included to get va_dcl
     definition.  Typically one of `varargs.h' or `stdarg.h'.

`i_vfork'
     From `i_vfork.U':

     This variable conditionally defines the `I_VFORK' symbol, and
     indicates whether a C program should include `vfork.h'.

`ignore_versioned_solibs'
     From `libs.U':

     This variable should be non-empty if non-versioned shared libraries
     (`libfoo.so.x.y') are to be ignored (because they cannot be linked
     against).

`inc_version_list'
     From `inc_version_list.U':

     This variable specifies the list of subdirectories in over which
     `perl.c':incpush() and `lib/lib.pm' will automatically search when
     adding directories to @INC.  The elements in the list are separated
     by spaces.  This is only useful if you have a perl library directory
     tree structured like the default one.  See INSTALL for how this
     works.  The versioned site_perl directory was introduced in 5.005, so
     that is the lowest possible value.

`inc_version_list_init'
     From `inc_version_list.U':

     This variable holds the same list as inc_version_list, but each item
     is enclosed in double quotes and separated by commas, suitable for
     use in the `PERL_INC_VERSION_LIST' initialization.

`incpath'
     From `usrinc.U':

     This variable must preceed the normal include path to get hte right
     one, as in `$`incpath/usr/include'' or `$`incpath/usr/lib''.  Value
     can be "" or `/bsd43' on mips.

`inews'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`installarchlib'
     From `archlib.U':

     This variable is really the same as archlibexp but may differ on
     those systems using AFS. For extra portability, only this variable
     should be used in makefiles.

installbin
     From `bin.U':

     This variable is the same as binexp unless AFS is running in which
     case the user is explicitely prompted for it. This variable should
     always be used in your makefiles for maximum portability.

`installman1dir'
     From `man1dir.U':

     This variable is really the same as man1direxp, unless you are using
     AFS in which case it points to the `read/write' location whereas
     man1direxp only points to the read-only access location. For extra
     portability, you should only use this variable within your makefiles.

`installman3dir'
     From `man3dir.U':

     This variable is really the same as man3direxp, unless you are using
     AFS in which case it points to the `read/write' location whereas
     man3direxp only points to the read-only access location. For extra
     portability, you should only use this variable within your makefiles.

`installprefix'
     From `installprefix.U':

     This variable holds the name of the directory below which "make
     install" will install the package.  For most users, this is the same
     as prefix.  However, it is useful for installing the software into a
     different (usually temporary) location after which it can be bundled
     up and moved somehow to the final location specified by prefix.

`installprefixexp'
     From `installprefix.U':

     This variable holds the full absolute path of installprefix with all
     `~'-expansion done.

`installprivlib'
     From `privlib.U':

     This variable is really the same as privlibexp but may differ on
     those systems using AFS. For extra portability, only this variable
     should be used in makefiles.

`installscript'
     From `scriptdir.U':

     This variable is usually the same as scriptdirexp, unless you are on
     a system running AFS, in which case they may differ slightly. You
     should always use this variable within your makefiles for portability.

`installsitearch'
     From `sitearch.U':

     This variable is really the same as sitearchexp but may differ on
     those systems using AFS. For extra portability, only this variable
     should be used in makefiles.

`installsitebin'
     From `sitebin.U':

     This variable is usually the same as sitebinexp, unless you are on a
     system running AFS, in which case they may differ slightly. You
     should always use this variable within your makefiles for portability.

`installsitelib'
     From `sitelib.U':

     This variable is really the same as sitelibexp but may differ on
     those systems using AFS. For extra portability, only this variable
     should be used in makefiles.

`installstyle'
     From `installstyle.U':

     This variable describes the style of the perl installation.  This is
     intended to be useful for tools that need to manipulate entire perl
     distributions.  Perl itself doesn't use this to find its libraries -
     the library directories are stored directly in Config.pm.  Currently,
     there are only two styles:  lib and `lib/perl5'.  The default library
     locations (e.g. privlib, sitelib) are either $`prefix/lib' or
     $`prefix/lib/perl5'.  The former is useful if $prefix is a directory
     dedicated to perl (e.g. `/opt/perl'), while the latter is useful if
     $prefix is shared by many packages, e.g. if $prefix=`/usr/local'.

          This may later be extended to include other information, so

          be careful with pattern-matching on the results.

          For compatibility with F<perl5.005> and earlier, the default

          setting is based on whether or not $prefix contains the string
          C<perl>.

installusrbinperl
     From `instubperl.U':

     This variable tells whether Perl should be installed also as
     `/usr/bin/perl' in addition to $`installbin/perl'

`installvendorarch'
     From `vendorarch.U':

     This variable is really the same as vendorarchexp but may differ on
     those systems using AFS. For extra portability, only this variable
     should be used in makefiles.

`installvendorbin'
     From `vendorbin.U':

     This variable is really the same as vendorbinexp but may differ on
     those systems using AFS. For extra portability, only this variable
     should be used in makefiles.

`installvendorlib'
     From `vendorlib.U':

     This variable is really the same as vendorlibexp but may differ on
     those systems using AFS. For extra portability, only this variable
     should be used in makefiles.

`intsize'
     From `intsize.U':

     This variable contains the value of the `INTSIZE' symbol, which
     indicates to the C program how many bytes there are in an int.

`ivdformat'
     From `perlxvf.U':

     This variable contains the format string used for printing a Perl IV
     as a signed decimal integer.

`ivsize'
     From `perlxv.U':

     This variable is the size of an IV in bytes.

`ivtype'
     From `perlxv.U':

     This variable contains the C type used for Perl's IV.

k
-

`known_extensions'
     From `Extensions.U':

     This variable holds a list of all XS extensions included in the
     package.

`ksh'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

l
-

large
     From `models.U':

     This variable contains a flag which will tell the C compiler and
     loader to produce a program running with a large memory model.  It is
     up to the Makefile to use this.

`ld'
     From `dlsrc.U':

     This variable indicates the program to be used to link libraries for
     dynamic loading.  On some systems, it is `ld'.  On `ELF' systems, it
     should be $cc.  Mostly, we'll try to respect the hint file setting.

`lddlflags'
     From `dlsrc.U':

     This variable contains any special flags that might need to be passed
     to $ld to create a shared library suitable for dynamic loading.  It
     is up to the makefile to use it.  For hpux, it should be -b.  For
     sunos 4.1, it is empty.

`ldflags'
     From `ccflags.U':

     This variable contains any additional C loader flags desired by the
     user.  It is up to the Makefile to use this.

`ldlibpthname'
     From `libperl.U':

     This variable holds the name of the shared library search path, often
     `LD_LIBRARY_PATH'.  To get an empty string, the hints file must set
     this to none.

less
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the less program.  After Configure runs, the
     value is reset to a plain less and is not useful.

`lib_ext'
     From `Unix.U':

     This is an old synonym for _a.

`libc'
     From `libc.U':

     This variable contains the location of the C library.

`libperl'
     From `libperl.U':

     The perl executable is obtained by linking `perlmain.c' with libperl,
     any static extensions (usually just DynaLoader), and any other
     libraries needed on this system.  libperl is usually `libperl.a', but
     can also be `libperl.so.xxx' if the user wishes to build a perl
     executable with a shared library.

`libpth'
     From `libpth.U':

     This variable holds the general path (space-separated) used to find
     libraries. It is intended to be used by other units.

`libs'
     From `libs.U':

     This variable holds the additional libraries we want to use.  It is
     up to the Makefile to deal with it.

`libsdirs'
     From `libs.U':

     This variable holds the directory names aka dirnames of the libraries
     we found and accepted, duplicates are removed.

`libsfiles'
     From `libs.U':

     This variable holds the filenames aka basenames of the libraries we
     found and accepted.

`libsfound'
     From `libs.U':

     This variable holds the full pathnames of the libraries we found and
     accepted.

`libspath'
     From `libs.U':

     This variable holds the directory names probed for libraries.

`libswanted'
     From `Myinit.U':

     This variable holds a list of all the libraries we want to search.
     The order is chosen to pick up the c library ahead of ucb or bsd
     libraries for SVR4.

line
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`lint'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`lkflags'
     From `ccflags.U':

     This variable contains any additional C partial linker flags desired
     by the user.  It is up to the Makefile to use this.

`ln'
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the ln program.  After Configure runs, the value
     is reset to a plain `ln' and is not useful.

`lns'
     From `lns.U':

     This variable holds the name of the command to make symbolic links
     (if they are supported).  It can be used in the Makefile. It is
     either `ln -s' or `ln'

`locincpth'
     From `ccflags.U':

     This variable contains a list of additional directories to be
     searched by the compiler.  The appropriate -I directives will be
     added to ccflags.  This is intended to simplify setting local
     directories from the Configure command line.  It's not much, but it
     parallels the loclibpth stuff in `libpth.U'.

`loclibpth'
     From `libpth.U':

     This variable holds the paths (space-separated) used to find local
     libraries.  It is prepended to libpth, and is intended to be easily
     set from the command line.

`longdblsize'
     From `d_longdbl.U':

     This variable contains the value of the `LONG_DOUBLESIZE' symbol,
     which indicates to the C program how many bytes there are in a long
     double, if this system supports long doubles.

`longlongsize'
     From `d_longlong.U':

     This variable contains the value of the `LONGLONGSIZE' symbol, which
     indicates to the C program how many bytes there are in a long long,
     if this system supports long long.

`longsize'
     From `intsize.U':

     This variable contains the value of the `LONGSIZE' symbol, which
     indicates to the C program how many bytes there are in a long.

`lp'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`lpr'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

ls
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the ls program.  After Configure runs, the value
     is reset to a plain ls and is not useful.

`lseeksize'
     From `lseektype.U':

     This variable defines lseektype to be something like off_t, long, or
     whatever type is used to declare lseek offset's type in the kernel
     (which also appears to be lseek's return type).

`lseektype'
     From `lseektype.U':

     This variable defines lseektype to be something like off_t, long, or
     whatever type is used to declare lseek offset's type in the kernel
     (which also appears to be lseek's return type).

m
-

mail
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`mailx'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

make
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the make program.  After Configure runs, the
     value is reset to a plain make and is not useful.

`make_set_make'
     From `make.U':

     Some versions of make set the variable MAKE.  Others do not.  This
     variable contains the string to be included in `Makefile.SH' so that
     MAKE is set if needed, and not if not needed.  Possible values are:
     make_set_make=`#'		# If your make program handles this for you,
     make_set_make=`MAKE=$make'	# if it doesn't.  I used a comment
     character so that we can distinguish a set value (from a previous
     `config.sh' or Configure -D option) from an uncomputed value.

`mallocobj'
     From `mallocsrc.U':

     This variable contains the name of the `malloc.o' that this package
     generates, if that `malloc.o' is preferred over the system malloc.
     Otherwise the value is null.  This variable is intended for generating
     Makefiles.  See mallocsrc.

`mallocsrc'
     From `mallocsrc.U':

     This variable contains the name of the `malloc.c' that comes with the
     package, if that `malloc.c' is preferred over the system malloc.
     Otherwise the value is null.  This variable is intended for generating
     Makefiles.

`malloctype'
     From `mallocsrc.U':

     This variable contains the kind of ptr returned by malloc and realloc.

`man1dir'
     From `man1dir.U':

     This variable contains the name of the directory in which manual
     source pages are to be put.  It is the responsibility of the
     `Makefile.SH' to get the value of this into the proper command.  You
     must be prepared to do the `~name' expansion yourself.

`man1direxp'
     From `man1dir.U':

     This variable is the same as the man1dir variable, but is filename
     expanded at configuration time, for convenient use in makefiles.

`man1ext'
     From `man1dir.U':

     This variable contains the extension that the manual page should
     have: one of n, l, or 1.  The Makefile must supply the ..  See
     man1dir.

`man3dir'
     From `man3dir.U':

     This variable contains the name of the directory in which manual
     source pages are to be put.  It is the responsibility of the
     `Makefile.SH' to get the value of this into the proper command.  You
     must be prepared to do the `~name' expansion yourself.

`man3direxp'
     From `man3dir.U':

     This variable is the same as the man3dir variable, but is filename
     expanded at configuration time, for convenient use in makefiles.

`man3ext'
     From `man3dir.U':

     This variable contains the extension that the manual page should
     have: one of n, l, or 3.  The Makefile must supply the ..  See
     man3dir.

M
-

`Mcc'
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the Mcc program.  After Configure runs, the
     value is reset to a plain `Mcc' and is not useful.

`medium'
     From `models.U':

     This variable contains a flag which will tell the C compiler and
     loader to produce a program running with a medium memory model.  If
     the medium model is not supported, contains the flag to produce large
     model programs.  It is up to the Makefile to use this.

`mips_type'
     From `usrinc.U':

     This variable holds the environment type for the mips system.
     Possible values are "BSD 4.3" and "System V".

mkdir
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the mkdir program.  After Configure runs, the
     value is reset to a plain mkdir and is not useful.

`mmaptype'
     From `d_mmap.U':

     This symbol contains the type of pointer returned by mmap() (and
     simultaneously the type of the first argument).  It can be `void *'
     or `caddr_t'.

`models'
     From `models.U':

     This variable contains the list of memory models supported by this
     system.  Possible component values are none, split, unsplit, small,
     medium, large, and huge.  The component values are space separated.

`modetype'
     From `modetype.U':

     This variable defines modetype to be something like mode_t, int,
     unsigned short, or whatever type is used to declare file modes for
     system calls.

more
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the more program.  After Configure runs, the
     value is reset to a plain more and is not useful.

`multiarch'
     From `multiarch.U':

     This variable conditionally defines the `MULTIARCH' symbol which
     signifies the presence of multiplatform files.  This is normally set
     by hints files.

mv
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`myarchname'
     From `archname.U':

     This variable holds the architecture name computed by Configure in a
     previous run. It is not intended to be perused by any user and should
     never be set in a hint file.

`mydomain'
     From `myhostname.U':

     This variable contains the eventual value of the `MYDOMAIN' symbol,
     which is the domain of the host the program is going to run on.  The
     domain must be appended to myhostname to form a complete host name.
     The dot comes with mydomain, and need not be supplied by the program.

`myhostname'
     From `myhostname.U':

     This variable contains the eventual value of the `MYHOSTNAME' symbol,
     which is the name of the host the program is going to run on.  The
     domain is not kept with hostname, but must be gotten from mydomain.
     The dot comes with mydomain, and need not be supplied by the program.

`myuname'
     From `Oldconfig.U':

     The output of `uname -a' if available, otherwise the hostname. On
     Xenix, pseudo variables assignments in the output are stripped, thank
     you. The whole thing is then lower-cased.

n
-

n
     From `n.U':

     This variable contains the -n flag if that is what causes the echo
     command to suppress newline.  Otherwise it is null.  Correct usage is
     $echo $n "prompt for a question: $c".

`netdb_hlen_type'
     From `netdbtype.U':

     This variable holds the type used for the 2nd argument to
     gethostbyaddr().  Usually, this is int or size_t or unsigned.  This
     is only useful if you have gethostbyaddr(), naturally.

`netdb_host_type'
     From `netdbtype.U':

     This variable holds the type used for the 1st argument to
     gethostbyaddr().  Usually, this is char * or void *,  possibly with
     or without a const prefix.  This is only useful if you have
     gethostbyaddr(), naturally.

`netdb_name_type'
     From `netdbtype.U':

     This variable holds the type used for the argument to
     gethostbyname().  Usually, this is char * or const char *.  This is
     only useful if you have gethostbyname(), naturally.

`netdb_net_type'
     From `netdbtype.U':

     This variable holds the type used for the 1st argument to
     getnetbyaddr().  Usually, this is int or long.  This is only useful
     if you have getnetbyaddr(), naturally.

`nm'
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the nm program.  After Configure runs, the value
     is reset to a plain `nm' and is not useful.

`nm_opt'
     From `usenm.U':

     This variable holds the options that may be necessary for nm.

`nm_so_opt'
     From `usenm.U':

     This variable holds the options that may be necessary for nm to work
     on a shared library but that can not be used on an archive library.
     Currently, this is only used by Linux, where nm -dynamic is
     *required* to get symbols from an `ELF' library which has been
     stripped, but nm -dynamic is *fatal* on an archive library.  Maybe
     Linux should just always set usenm=false.

`nonxs_ext'
     From `Extensions.U':

     This variable holds a list of all non-xs extensions included in the
     package.  All of them will be built.

`nroff'
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the nroff program.  After Configure runs, the
     value is reset to a plain `nroff' and is not useful.

`nvsize'
     From `perlxv.U':

     This variable is the size of an NV in bytes.

`nvtype'
     From `perlxv.U':

     This variable contains the C type used for Perl's NV.

o
-

`o_nonblock'
     From `nblock_io.U':

     This variable bears the symbol value to be used during open() or
     fcntl() to turn on non-blocking I/O for a file descriptor. If you
     wish to switch between blocking and non-blocking, you may try
     ioctl(`FIOSNBIO') instead, but that is only supported by some devices.

`obj_ext'
     From `Unix.U':

     This is an old synonym for _o.

`old_pthread_create_joinable'
     From `d_pthrattrj.U':

     This variable defines the constant to use for creating joinable (aka
     undetached) pthreads.  Unused if `pthread.h' defines
     `PTHREAD_CREATE_JOINABLE'.  If used, possible values are
     `PTHREAD_CREATE_UNDETACHED' and `__UNDETACHED'.

optimize
     From `ccflags.U':

     This variable contains any `optimizer/debugger' flag that should be
     used.  It is up to the Makefile to use it.

`orderlib'
     From `orderlib.U':

     This variable is `true' if the components of libraries must be ordered
     (with `lorder $* | tsort`) before placing them in an archive.  Set to
     false if ranlib or ar can generate random libraries.

osname
     From `Oldconfig.U':

     This variable contains the operating system name (e.g. sunos,
     solaris, hpux, etc.).  It can be useful later on for setting
     defaults.  Any spaces are replaced with underscores.  It is set to a
     null string if we can't figure it out.

`osvers'
     From `Oldconfig.U':

     This variable contains the operating system version (e.g.  4.1.3,
     5.2, etc.).  It is primarily used for helping select an appropriate
     hints file, but might be useful elsewhere for setting defaults.  It
     is set to " if we can't figure it out.  We try to be flexible about
     how much of the version number to keep, e.g. if 4.1.1, 4.1.2, and
     4.1.3 are essentially the same for this package, hints files might
     just be `os_4.0' or `os_4.1', etc., not keeping separate files for
     each little release.

p
-

package
     From `package.U':

     This variable contains the name of the package being constructed.  It
     is primarily intended for the use of later Configure units.

`pager'
     From `pager.U':

     This variable contains the name of the preferred pager on the system.
     Usual values are (the full pathnames of) more, less, pg, or cat.

`passcat'
     From `nis.U':

     This variable contains a command that produces the text of the
     `/etc/passwd' file.  This is normally "cat `/etc/passwd'", but can be
     "ypcat passwd" when NIS is used.  On some systems, such as os390,
     there may be no equivalent command, in which case this variable is
     unset.

`patchlevel'
     From `patchlevel.U':

     The patchlevel level of this package.  The value of patchlevel comes
     from the `patchlevel.h' file.  In a version number such as 5.6.1,
     this is the 6.  In `patchlevel.h', this is referred to as
     `PERL_VERSION'.

`path_sep'
     From `Unix.U':

     This is an old synonym for p_ in `Head.U', the character used to
     separate elements in the command shell search PATH.

`perl5'
     From `perl5.U':

     This variable contains the full path (if any) to a previously
     installed `perl5.005' or later suitable for running the script to
     determine inc_version_list.

`perl'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

P
-

`PERL_REVISION'
     From `Oldsyms.U':

     In a Perl version number such as 5.6.2, this is the 5.  This value is
     manually set in `patchlevel.h'

`PERL_SUBVERSION'
     From `Oldsyms.U':

     In a Perl version number such as 5.6.2, this is the 2.  Values
     greater than 50 represent potentially unstable development
     subversions.  This value is manually set in `patchlevel.h'

`PERL_VERSION'
     From `Oldsyms.U':

     In a Perl version number such as 5.6.2, this is the 6.  This value is
     manually set in `patchlevel.h'

`perladmin'
     From `perladmin.U':

     Electronic mail address of the perl5 administrator.

`perlpath'
     From `perlpath.U':

     This variable contains the eventual value of the `PERLPATH' symbol,
     which contains the name of the perl interpreter to be used in shell
     scripts and in the "eval exec" idiom.

`pg'
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the pg program.  After Configure runs, the value
     is reset to a plain `pg' and is not useful.

`phostname'
     From `myhostname.U':

     This variable contains the eventual value of the `PHOSTNAME' symbol,
     which is a command that can be fed to popen() to get the host name.
     The program should probably not presume that the domain is or isn't
     there already.

`pidtype'
     From `pidtype.U':

     This variable defines `PIDTYPE' to be something like pid_t, int,
     ushort, or whatever type is used to declare process ids in the kernel.

`plibpth'
     From `libpth.U':

     Holds the private path used by Configure to find out the libraries.
     Its value is prepend to libpth. This variable takes care of special
     machines, like the mips.  Usually, it should be empty.

`pm_apiversion'
     From `xs_apiversion.U':

     This variable contains the version of the oldest perl compatible with
     the present perl.  (That is, pure perl modules written for
     $pm_apiversion will still work for the current version).
     `perl.c':incpush() and `lib/lib.pm' will automatically search in
     $sitelib for older directories across major versions back to
     pm_apiversion.  This is only useful if you have a perl library
     directory tree structured like the default one.  The versioned
     site_perl library was introduced in 5.005, so that's the default
     setting for this variable.  It's hard to imagine it changing before
     Perl6.  It is included here for symmetry with xs_apiveprsion - the
     searching algorithms will (presumably) be similar.  See the INSTALL
     file for how this works.

`pmake'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`pr'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

prefix
     From `prefix.U':

     This variable holds the name of the directory below which the user
     will install the package.  Usually, this is `/usr/local', and
     executables go in `/usr/local/bin', library stuff in `/usr/local/lib',
     man pages in `/usr/local/man', etc.  It is only used to set defaults
     for things in `bin.U', `mansrc.U', `privlib.U', or `scriptdir.U'.

`prefixexp'
     From `prefix.U':

     This variable holds the full absolute path of the directory below
     which the user will install the package.  Derived from prefix.

`privlib'
     From `privlib.U':

     This variable contains the eventual value of the `PRIVLIB' symbol,
     which is the name of the private library for this package.  It may
     have a `~' on the front. It is up to the makefile to eventually create
     this directory while performing installation (with `~' substitution).

`privlibexp'
     From `privlib.U':

     This variable is the `~name' expanded version of privlib, so that you
     may use it directly in Makefiles or shell scripts.

prototype
     From `prototype.U':

     This variable holds the eventual value of `CAN_PROTOTYPE', which
     indicates the C compiler can handle funciton prototypes.

`ptrsize'
     From `ptrsize.U':

     This variable contains the value of the `PTRSIZE' symbol, which
     indicates to the C program how many bytes there are in a pointer.

q
-

`quadkind'
     From `quadtype.U':

     This variable, if defined, encodes the type of a quad: 1 = int, 2 =
     long, 3 = long long, 4 = int64_t.

`quadtype'
     From `quadtype.U':

     This variable defines Quad_t to be something like long, int, long
     long, int64_t, or whatever type is used for 64-bit integers.

r
-

`randbits'
     From `randfunc.U':

     Indicates how many bits are produced by the function used to generate
     normalized random numbers.

`randfunc'
     From `randfunc.U':

     Indicates the name of the random number function to use.  Values
     include drand48, random, and rand. In C programs, the `Drand01' macro
     is defined to generate uniformly distributed random numbers over the
     range [0., 1.[ (see drand01 and nrand).

`randseedtype'
     From `randfunc.U':

     Indicates the type of the argument of the seedfunc.

`ranlib'
     From `orderlib.U':

     This variable is set to the pathname of the ranlib program, if it is
     needed to generate random libraries.  Set to : if ar can generate
     random libraries or if random libraries are not supported

`rd_nodata'
     From `nblock_io.U':

     This variable holds the return code from read() when no data is
     present. It should be -1, but some systems return 0 when `O_NDELAY' is
     used, which is a shame because you cannot make the difference between
     no data and an `EOF.'. Sigh!

`revision'
     From `patchlevel.U':

     The value of revision comes from the `patchlevel.h' file.  In a
     version number such as 5.6.1, this is the 5.  In `patchlevel.h', this
     is referred to as `PERL_REVISION'.

rm
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the rm program.  After Configure runs, the value
     is reset to a plain rm and is not useful.

`rmail'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`runnm'
     From `usenm.U':

     This variable contains `true' or false depending whether the nm
     extraction should be performed or not, according to the value of
     usenm and the flags on the Configure command line.

s
-

`sched_yield'
     From `d_pthread_y.U':

     This variable defines the way to yield the execution of the current
     thread.

`scriptdir'
     From `scriptdir.U':

     This variable holds the name of the directory in which the user wants
     to put publicly scripts for the package in question.  It is either
     the same directory as for binaries, or a special one that can be
     mounted across different architectures, like `/usr/share'. Programs
     must be prepared to deal with `~name' expansion.

`scriptdirexp'
     From `scriptdir.U':

     This variable is the same as scriptdir, but is filename expanded at
     configuration time, for programs not wanting to bother with it.

`sed'
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the sed program.  After Configure runs, the
     value is reset to a plain `sed' and is not useful.

`seedfunc'
     From `randfunc.U':

     Indicates the random number generating seed function.  Values include
     srand48, srandom, and srand.

`selectminbits'
     From `selectminbits.U':

     This variable holds the minimum number of bits operated by select.
     That is, if you do select(n, ...), how many bits at least will be
     cleared in the masks if some activity is detected.  Usually this is
     either n or 32*ceil(`n/32'), especially many little-endians do the
     latter.  This is only useful if you have select(), naturally.

`selecttype'
     From `selecttype.U':

     This variable holds the type used for the 2nd, 3rd, and 4th arguments
     to select.  Usually, this is `fd_set *', if `HAS_FD_SET' is defined,
     and `int *' otherwise.  This is only useful if you have select(),
     naturally.

sendmail
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`sh'
     From `sh.U':

     This variable contains the full pathname of the shell used on this
     system to execute Bourne shell scripts.  Usually, this will be
     `/bin/sh', though it's possible that some systems will have
     `/bin/ksh', `/bin/pdksh', `/bin/ash', `/bin/bash', or even something
     such as D:`/bin/sh.exe'.  This unit comes before `Options.U', so you
     can't set sh with a -D option, though you can override this (and
     startsh) with `-O -Dsh=`/bin/whatever' -Dstartsh=whatever'

`shar'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`sharpbang'
     From `spitshell.U':

     This variable contains the string #! if this system supports that
     construct.

`shmattype'
     From `d_shmat.U':

     This symbol contains the type of pointer returned by shmat().  It can
     be `void *' or `char *'.

`shortsize'
     From `intsize.U':

     This variable contains the value of the `SHORTSIZE' symbol which
     indicates to the C program how many bytes there are in a short.

`shrpenv'
     From `libperl.U':

     If the user builds a shared `libperl.so', then we need to tell the
     `perl' executable where it will be able to find the installed
     `libperl.so'.  One way to do this on some systems is to set the
     environment variable `LD_RUN_PATH' to the directory that will be the
     final location of the shared `libperl.so'.  The makefile can use this
     with something like $shrpenv $(CC) -o perl `perlmain.o' $libperl $libs
     Typical values are shrpenv="env `LD_RUN_PATH'=$`archlibexp/`CORE''" or
     shrpenv=" See the main perl `Makefile.SH' for actual working usage.
     Alternatively, we might be able to use a command line option such as
     -R $`archlibexp/`CORE'' (Solaris, NetBSD) or -Wl,-rpath
     $`archlibexp/`CORE'' (Linux).

`shsharp'
     From `spitshell.U':

     This variable tells further Configure units whether your sh can
     handle # comments.

`sig_count'
     From `sig_name.U':

     This variable holds a number larger than the largest valid signal
     number.  This is usually the same as the NSIG macro.

sig_name
     From `sig_name.U':

     This variable holds the signal names, space separated. The leading
     `SIG' in signal name is removed.  A `ZERO' is prepended to the list.
     This is currently not used.

`sig_name_init'
     From `sig_name.U':

     This variable holds the signal names, enclosed in double quotes and
     separated by commas, suitable for use in the `SIG_NAME' definition
     below.  A `ZERO' is prepended to the list, and the list is terminated
     with a plain 0.  The leading `SIG' in signal names is removed. See
     sig_num.

sig_num
     From `sig_name.U':

     This variable holds the signal numbers, space separated. A `ZERO' is
     prepended to the list (corresponding to the fake `SIGZERO'), and the
     list is terminated with a 0.  Those numbers correspond to the value
     of the signal listed in the same place within the sig_name list.

`sig_num_init'
     From `sig_name.U':

     This variable holds the signal numbers, enclosed in double quotes and
     separated by commas, suitable for use in the `SIG_NUM' definition
     below.  A `ZERO' is prepended to the list, and the list is terminated
     with a plain 0.

`signal_t'
     From `d_voidsig.U':

     This variable holds the type of the signal handler (void or int).

`sitearch'
     From `sitearch.U':

     This variable contains the eventual value of the `SITEARCH' symbol,
     which is the name of the private library for this package.  It may
     have a `~' on the front. It is up to the makefile to eventually create
     this directory while performing installation (with `~' substitution).
     The standard distribution will put nothing in this directory.  After
     perl has been installed, users may install their own local
     architecture-dependent modules in this directory with MakeMaker
     Makefile.PL or equivalent.  See INSTALL for details.

`sitearchexp'
     From `sitearch.U':

     This variable is the `~name' expanded version of sitearch, so that you
     may use it directly in Makefiles or shell scripts.

`sitebin'
     From `sitebin.U':

     This variable holds the name of the directory in which the user wants
     to put add-on publicly executable files for the package in question.
     It is most often a local directory such as `/usr/local/bin'. Programs
     using this variable must be prepared to deal with `~name'
     substitution.  The standard distribution will put nothing in this
     directory.  After perl has been installed, users may install their
     own local executables in this directory with MakeMaker Makefile.PL or
     equivalent.  See INSTALL for details.

`sitebinexp'
     From `sitebin.U':

     This is the same as the sitebin variable, but is filename expanded at
     configuration time, for use in your makefiles.

`sitelib'
     From `sitelib.U':

     This variable contains the eventual value of the `SITELIB' symbol,
     which is the name of the private library for this package.  It may
     have a `~' on the front. It is up to the makefile to eventually create
     this directory while performing installation (with `~' substitution).
     The standard distribution will put nothing in this directory.  After
     perl has been installed, users may install their own local
     architecture-independent modules in this directory with MakeMaker
     Makefile.PL or equivalent.  See INSTALL for details.

`sitelib_stem'
     From `sitelib.U':

     This variable is $sitelibexp with any trailing version-specific
     component removed.  The elements in inc_version_list
     (`inc_version_list.U') can be tacked onto this variable to generate a
     list of directories to search.

`sitelibexp'
     From `sitelib.U':

     This variable is the `~name' expanded version of sitelib, so that you
     may use it directly in Makefiles or shell scripts.

`siteprefix'
     From `siteprefix.U':

     This variable holds the full absolute path of the directory below
     which the user will install add-on packages.  See INSTALL for usage
     and examples.

`siteprefixexp'
     From `siteprefix.U':

     This variable holds the full absolute path of the directory below
     which the user will install add-on packages.  Derived from siteprefix.

`sizesize'
     From `sizesize.U':

     This variable contains the size of a sizetype in bytes.

`sizetype'
     From `sizetype.U':

     This variable defines sizetype to be something like size_t, unsigned
     long, or whatever type is used to declare length parameters for
     string functions.

sleep
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`smail'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

small
     From `models.U':

     This variable contains a flag which will tell the C compiler and
     loader to produce a program running with a small memory model.  It is
     up to the Makefile to use this.

`so'
     From `so.U':

     This variable holds the extension used to identify shared libraries
     (also known as shared objects) on the system. Usually set to `so'.

`sockethdr'
     From `d_socket.U':

     This variable has any cpp -I flags needed for socket support.

`socketlib'
     From `d_socket.U':

     This variable has the names of any libraries needed for socket
     support.

`socksizetype'
     From `socksizetype.U':

     This variable holds the type used for the size argument for various
     socket calls like accept.  Usual values include socklen_t, size_t,
     and int.

sort
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the sort program.  After Configure runs, the
     value is reset to a plain sort and is not useful.

`spackage'
     From `package.U':

     This variable contains the name of the package being constructed,
     with the first letter uppercased, `i.e'. suitable for starting
     sentences.

`spitshell'
     From `spitshell.U':

     This variable contains the command necessary to spit out a runnable
     shell on this system.  It is either cat or a grep -v for # comments.

split
     From `models.U':

     This variable contains a flag which will tell the C compiler and
     loader to produce a program that will run in separate I and D space,
     for those machines that support separation of instruction and data
     space.  It is up to the Makefile to use this.

`sPRId64'
     From `quadfio.U':

     This variable, if defined, contains the string used by stdio to
     format 64-bit decimal numbers (format d) for output.

`sPRIeldbl'
     From `longdblfio.U':

     This variable, if defined, contains the string used by stdio to
     format long doubles (format e) for output.

`sPRIEldbl'
     From `longdblfio.U':

     This variable, if defined, contains the string used by stdio to
     format long doubles (format E) for output.

`sPRIfldbl'
     From `longdblfio.U':

     This variable, if defined, contains the string used by stdio to
     format long doubles (format f) for output.

`sPRIFldbl'
     From `longdblfio.U':

     This variable, if defined, contains the string used by stdio to
     format long doubles (format F) for output.

`sPRIgldbl'
     From `longdblfio.U':

     This variable, if defined, contains the string used by stdio to
     format long doubles (format g) for output.

`sPRIGldbl'
     From `longdblfio.U':

     This variable, if defined, contains the string used by stdio to
     format long doubles (format G) for output.

`sPRIi64'
     From `quadfio.U':

     This variable, if defined, contains the string used by stdio to
     format 64-bit decimal numbers (format i) for output.

`sPRIo64'
     From `quadfio.U':

     This variable, if defined, contains the string used by stdio to
     format 64-bit octal numbers (format o) for output.

`sPRIu64'
     From `quadfio.U':

     This variable, if defined, contains the string used by stdio to
     format 64-bit unsigned decimal numbers (format u) for output.

`sPRIx64'
     From `quadfio.U':

     This variable, if defined, contains the string used by stdio to
     format 64-bit hexadecimal numbers (format x) for output.

`sPRIX64'
     From `quadfio.U':

     This variable, if defined, contains the string used by stdio to
     format 64-bit hExADECimAl numbers (format X) for output.

src
     From `src.U':

     This variable holds the path to the package source. It is up to the
     Makefile to use this variable and set `VPATH' accordingly to find the
     sources remotely.

`ssizetype'
     From `ssizetype.U':

     This variable defines ssizetype to be something like ssize_t, long or
     int.  It is used by functions that return a count of bytes or an
     error condition.  It must be a signed type.  We will pick a type such
     that sizeof(SSize_t) == sizeof(Size_t).

`startperl'
     From `startperl.U':

     This variable contains the string to put on the front of a perl
     script to make sure (hopefully) that it runs with perl and not some
     shell. Of course, that leading line must be followed by the classical
     perl idiom: eval 'exec perl -S $0 ${1+`$@'}' if
     $running_under_some_shell; to guarantee perl startup should the shell
     execute the script. Note that this magic incatation is not understood
     by csh.

`startsh'
     From `startsh.U':

     This variable contains the string to put on the front of a shell
     script to make sure (hopefully) that it runs with sh and not some
     other shell.

`static_ext'
     From `Extensions.U':

     This variable holds a list of XS extension files we want to link
     statically into the package.  It is used by Makefile.

`stdchar'
     From `stdchar.U':

     This variable conditionally defines `STDCHAR' to be the type of char
     used in `stdio.h'.  It has the values "unsigned char" or `char'.

`stdio_base'
     From `d_stdstdio.U':

     This variable defines how, given a FILE pointer, fp, to access the
     _base field (or equivalent) of `stdio.h''s FILE structure.  This will
     be used to define the macro FILE_base(fp).

`stdio_bufsiz'
     From `d_stdstdio.U':

     This variable defines how, given a FILE pointer, fp, to determine the
     number of bytes store in the I/O buffer pointer to by the _base field
     (or equivalent) of `stdio.h''s FILE structure.  This will be used to
     define the macro FILE_bufsiz(fp).

`stdio_cnt'
     From `d_stdstdio.U':

     This variable defines how, given a FILE pointer, fp, to access the
     _cnt field (or equivalent) of `stdio.h''s FILE structure.  This will
     be used to define the macro FILE_cnt(fp).

`stdio_filbuf'
     From `d_stdstdio.U':

     This variable defines how, given a FILE pointer, fp, to tell stdio to
     refill it's internal buffers (?).  This will be used to define the
     macro FILE_filbuf(fp).

`stdio_ptr'
     From `d_stdstdio.U':

     This variable defines how, given a FILE pointer, fp, to access the
     _ptr field (or equivalent) of `stdio.h''s FILE structure.  This will
     be used to define the macro FILE_ptr(fp).

`stdio_stream_array'
     From `stdio_streams.U':

     This variable tells the name of the array holding the stdio streams.
     Usual values include _iob, __iob, and __sF.

strings
     From `i_string.U':

     This variable holds the full path of the string header that will be
     used. Typically `/usr/include/string.h' or `/usr/include/strings.h'.

`submit'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`subversion'
     From `patchlevel.U':

     The subversion level of this package.  The value of subversion comes
     from the `patchlevel.h' file.  In a version number such as 5.6.1,
     this is the 1.  In `patchlevel.h', this is referred to as
     `PERL_SUBVERSION'.  This is unique to perl.

`sysman'
     From `sysman.U':

     This variable holds the place where the manual is located on this
     system. It is not the place where the user wants to put his manual
     pages. Rather it is the place where Configure may look to find manual
     for unix commands (section 1 of the manual usually). See mansrc.

t
-

tail
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`tar'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`tbl'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`tee'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

test
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the test program.  After Configure runs, the
     value is reset to a plain test and is not useful.

`timeincl'
     From `i_time.U':

     This variable holds the full path of the included time header(s).

`timetype'
     From `d_time.U':

     This variable holds the type returned by time(). It can be long, or
     time_t on `BSD' sites (in which case <sys/types.h> should be
     included). Anyway, the type Time_t should be used.

touch
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the touch program.  After Configure runs, the
     value is reset to a plain touch and is not useful.

tr
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the tr program.  After Configure runs, the value
     is reset to a plain tr and is not useful.

`trnl'
     From `trnl.U':

     This variable contains the value to be passed to the tr(1) command to
     transliterate a newline.  Typical values are `\012' and \n.  This is
     needed for EBCDIC systems where newline is not necessarily `\012'.

`troff'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

u
-

`u16size'
     From `perlxv.U':

     This variable is the size of an U16 in bytes.

`u16type'
     From `perlxv.U':

     This variable contains the C type used for Perl's U16.

`u32size'
     From `perlxv.U':

     This variable is the size of an U32 in bytes.

`u32type'
     From `perlxv.U':

     This variable contains the C type used for Perl's U32.

`u64size'
     From `perlxv.U':

     This variable is the size of an U64 in bytes.

`u64type'
     From `perlxv.U':

     This variable contains the C type used for Perl's U64.

`u8size'
     From `perlxv.U':

     This variable is the size of an U8 in bytes.

`u8type'
     From `perlxv.U':

     This variable contains the C type used for Perl's U8.

`uidformat'
     From `uidf.U':

     This variable contains the format string used for printing a Uid_t.

`uidsign'
     From `uidsign.U':

     This variable contains the signedness of a uidtype.  1 for unsigned,
     -1 for signed.

`uidsize'
     From `uidsize.U':

     This variable contains the size of a uidtype in bytes.

`uidtype'
     From `uidtype.U':

     This variable defines Uid_t to be something like uid_t, int, ushort,
     or whatever type is used to declare user ids in the kernel.

uname
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the uname program.  After Configure runs, the
     value is reset to a plain uname and is not useful.

`uniq'
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the uniq program.  After Configure runs, the
     value is reset to a plain `uniq' and is not useful.

`uquadtype'
     From `quadtype.U':

     This variable defines Uquad_t to be something like unsigned long,
     unsigned int, unsigned long long, uint64_t, or whatever type is used
     for 64-bit integers.

`use5005threads'
     From `usethreads.U':

     This variable conditionally defines the USE_5005THREADS symbol, and
     indicates that Perl should be built to use the 5.005-based threading
     implementation.

`use64bitall'
     From `use64bits.U':

     This variable conditionally defines the USE_64_BIT_ALL symbol, and
     indicates that 64-bit integer types should be used when available.
     The maximal possible 64-bitness is employed: LP64 or ILP64, meaning
     that you will be able to use more than 2 gigabytes of memory.  This
     mode is even more binary incompatible than USE_64_BIT_INT. You may not
     be able to run the resulting executable in a 32-bit CPU at all or you
     may need at least to reboot your OS to 64-bit mode.

`use64bitint'
     From `use64bits.U':

     This variable conditionally defines the USE_64_BIT_INT symbol, and
     indicates that 64-bit integer types should be used when available.
     The minimal possible 64-bitness is employed, just enough to get
     64-bit integers into Perl.  This may mean using for example "long
     longs", while your memory may still be limited to 2 gigabytes.

`usedl'
     From `dlsrc.U':

     This variable indicates if the system supports dynamic loading of
     some sort.  See also dlsrc and dlobj.

`useithreads'
     From `usethreads.U':

     This variable conditionally defines the `USE_ITHREADS' symbol, and
     indicates that Perl should be built to use the interpreter-based
     threading implementation.

`uselargefiles'
     From `uselfs.U':

     This variable conditionally defines the `USE_LARGE_FILES' symbol, and
     indicates that large file interfaces should be used when available.

`uselongdouble'
     From `uselongdbl.U':

     This variable conditionally defines the `USE_LONG_DOUBLE' symbol, and
     indicates that long doubles should be used when available.

`usemorebits'
     From `usemorebits.U':

     This variable conditionally defines the `USE_MORE_BITS' symbol, and
     indicates that explicit 64-bit interfaces and long doubles should be
     used when available.

`usemultiplicity'
     From `usemultiplicity.U':

     This variable conditionally defines the MULTIPLICITY symbol, and
     indicates that Perl should be built to use multiplicity.

`usemymalloc'
     From `mallocsrc.U':

     This variable contains y if the malloc that comes with this package
     is desired over the system's version of malloc.  People often include
     special versions of malloc for effiency, but such versions are often
     less portable.  See also mallocsrc and mallocobj.  If this is y, then
     -lmalloc is removed from $libs.

`usenm'
     From `usenm.U':

     This variable contains `true' or false depending whether the nm
     extraction is wanted or not.

`useopcode'
     From `Extensions.U':

     This variable holds either `true' or false to indicate whether the
     Opcode extension should be used.  The sole use for this currently is
     to allow an easy mechanism for users to skip the Opcode extension
     from the Configure command line.

`useperlio'
     From `useperlio.U':

     This variable conditionally defines the `USE_PERLIO' symbol, and
     indicates that the PerlIO abstraction should be used throughout.

`useposix'
     From `Extensions.U':

     This variable holds either `true' or false to indicate whether the
     POSIX extension should be used.  The sole use for this currently is
     to allow an easy mechanism for hints files to indicate that POSIX
     will not compile on a particular system.

`usesfio'
     From `d_sfio.U':

     This variable is set to true when the user agrees to use sfio.  It is
     set to false when sfio is not available or when the user explicitely
     requests not to use sfio.  It is here primarily so that command-line
     settings can override the auto-detection of d_sfio without running
     into a "WHOA THERE".

`useshrplib'
     From `libperl.U':

     This variable is set to `yes' if the user wishes to build a shared
     libperl, and no otherwise.

`usesocks'
     From `usesocks.U':

     This variable conditionally defines the `USE_SOCKS' symbol, and
     indicates that Perl should be built to use SOCKS.

`usethreads'
     From `usethreads.U':

     This variable conditionally defines the `USE_THREADS' symbol, and
     indicates that Perl should be built to use threads.

`usevendorprefix'
     From `vendorprefix.U':

     This variable tells whether the vendorprefix and consequently other
     vendor* paths are in use.

`usevfork'
     From `d_vfork.U':

     This variable is set to true when the user accepts to use vfork.  It
     is set to false when no vfork is available or when the user
     explicitely requests not to use vfork.

`usrinc'
     From `usrinc.U':

     This variable holds the path of the include files, which is usually
     `/usr/include'. It is mainly used by other Configure units.

`uuname'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`uvoformat'
     From `perlxvf.U':

     This variable contains the format string used for printing a Perl
     `UV' as an unsigned octal integer.

`uvsize'
     From `perlxv.U':

     This variable is the size of a `UV' in bytes.

`uvtype'
     From `perlxv.U':

     This variable contains the C type used for Perl's `UV'.

`uvuformat'
     From `perlxvf.U':

     This variable contains the format string used for printing a Perl
     `UV' as an unsigned decimal integer.

`uvxformat'
     From `perlxvf.U':

     This variable contains the format string used for printing a Perl
     `UV' as an unsigned hexadecimal integer.

v
-

`vendorarch'
     From `vendorarch.U':

     This variable contains the value of the `PERL_VENDORARCH' symbol.  It
     may have a `~' on the front.  The standard distribution will put
     nothing in this directory.  Vendors who distribute perl may wish to
     place their own architecture-dependent modules and extensions in this
     directory with MakeMaker Makefile.PL INSTALLDIRS=vendor or
     equivalent.  See INSTALL for details.

`vendorarchexp'
     From `vendorarch.U':

     This variable is the `~name' expanded version of vendorarch, so that
     you may use it directly in Makefiles or shell scripts.

`vendorbin'
     From `vendorbin.U':

     This variable contains the eventual value of the `VENDORBIN' symbol.
     It may have a `~' on the front.  The standard distribution will put
     nothing in this directory.  Vendors who distribute perl may wish to
     place additional binaries in this directory with MakeMaker
     Makefile.PL INSTALLDIRS=vendor or equivalent.  See INSTALL for
     details.

`vendorbinexp'
     From `vendorbin.U':

     This variable is the `~name' expanded version of vendorbin, so that
     you may use it directly in Makefiles or shell scripts.

`vendorlib'
     From `vendorlib.U':

     This variable contains the eventual value of the `VENDORLIB' symbol,
     which is the name of the private library for this package.  The
     standard distribution will put nothing in this directory.  Vendors
     who distribute perl may wish to place their own modules in this
     directory with MakeMaker Makefile.PL INSTALLDIRS=vendor or
     equivalent.  See INSTALL for details.

`vendorlib_stem'
     From `vendorlib.U':

     This variable is $vendorlibexp with any trailing version-specific
     component removed.  The elements in inc_version_list
     (`inc_version_list.U') can be tacked onto this variable to generate a
     list of directories to search.

`vendorlibexp'
     From `vendorlib.U':

     This variable is the `~name' expanded version of vendorlib, so that
     you may use it directly in Makefiles or shell scripts.

`vendorprefix'
     From `vendorprefix.U':

     This variable holds the full absolute path of the directory below
     which the vendor will install add-on packages.  See INSTALL for usage
     and examples.

`vendorprefixexp'
     From `vendorprefix.U':

     This variable holds the full absolute path of the directory below
     which the vendor will install add-on packages.  Derived from
     vendorprefix.

version
     From `patchlevel.U':

     The full version number of this package, such as 5.6.1 (or 5_6_1).
     This combines revision, patchlevel, and subversion to get the full
     version number, including any possible subversions.  This is suitable
     for use as a directory name, and hence is filesystem dependent.

`vi'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

`voidflags'
     From `voidflags.U':

     This variable contains the eventual value of the `VOIDFLAGS' symbol,
     which indicates how much support of the void type is given by this
     compiler.  See `VOIDFLAGS' for more info.

x
-

`xlibpth'
     From `libpth.U':

     This variable holds extra path (space-separated) used to find
     libraries on this platform, for example CPU-specific libraries (on
     multi-CPU platforms) may be listed here.

`xs_apiversion'
     From `xs_apiversion.U':

     This variable contains the version of the oldest perl binary
     compatible with the present perl.  `perl.c':incpush() and
     `lib/lib.pm' will automatically search in $sitearch for older
     directories across major versions back to xs_apiversion.  This is
     only useful if you have a perl library directory tree structured like
     the default one.  See INSTALL for how this works.  The versioned
     site_perl directory was introduced in 5.005, so that is the lowest
     possible value.  Since this can depend on compile time options (such
     as bincompat) it is set by Configure.  Other non-default sources of
     potential incompatibility, such as multiplicity, threads, debugging,
     64bits, sfio, etc., are not checked for currently, though in
     principle we could go snooping around in old Config.pm files.

z
-

`zcat'
     From `Loc.U':

     This variable is defined but not used by Configure.  The value is a
     plain " and is not useful.

zip
     From `Loc.U':

     This variable is used internally by Configure to determine the full
     pathname (if any) of the zip program.  After Configure runs, the
     value is reset to a plain zip and is not useful.

NOTE
====

   This module contains a good example of how to use tie to implement a
cache and an example of how to make a tied variable readonly to those
outside of it.

Perform simple access control
*****************************

NAME
====

   `Config::Access' - Perform simple access control

SYNOPSIS
========

     use strict;                  # not optional (-:
     use Config::Access;

DESCRIPTION
===========

   The `Config::Access' module provides a method of authenticating
arbitrary client/service pairs in a way very similar to that provided by
the TCP wrappers by Wietse Venema <wietse@wzv.win.tue.nl> but not limited
to inetd services and IP/host names.

   This module can be useful for restricting access to certain parts of a
script to a certain domain.  For example, a front end program to some
device might deny certain users access to certain commands or only allow
trusted users access to dangerous commands.  The semantics of what the
client and service names actually mean is totally up to the programmer.

   The access control language is very similar to the access control
language specified in hosts_access(5) for the TCP wrappers.  Two
configuration files specify access rules.  A file ending in .allow
specifies rules to allow access and a file ending in .deny specifies rules
to deny access.  The prefix of these files is specified when a
`Config::Access' object is created.

ACCESS CONTROL FILES
====================

   As per the TCP wrappers, a request for authorisation consults the
.allow and .deny files.  The search stops at the first match.

   * Access is granted if a $client/$service matches a rule in the .allow
     file.

   * Access is denied if a $client/$service matches a rule in the .deny
     file.

   * Otherwise, if no match is made access is granted.

ACCESS CONTROL RULES
====================

   Access control rules appear in the configuration files in the following
format.

     service_list : client_list

   Each item in a list is separated by a comma and optional whitespace.
Newlines and lines beginning with a '#' character are ignored.  A line may
be continued if a backslash character is present as the end of the line.

   A service or client may be specified as the string 'ALL' which means it
will be matched by anything.  An optional parameter to the access_query
method described below allows the caller to determine whether the request
was granted (or denied) using a rule containing the ALL wildcard.

   `Config::Access' also supports IP address matching of clients and
services using the network/netmask number format.

   The EXCEPT operator present in the TCP wrappers access control language
is not supported.

Public Methods
--------------

new
     Usage:

     $obj = new Config::Access($prefix);     $obj = new
     Config::Access($prefix, $debug);     $obj =
     'Config::Access'->new($prefix);     $obj =
     'Config::Access'->new($prefix, $debug);

     Returns a newly-initialised `Config::Access' object.  The
     configuration files are read and parsed.  The allow and deny
     configuration file names are generated from the prefix argument by
     appending the string '`.allow'' and '`.deny'' to the prefix,
     respectively.

     If the $debug parameter is true, then debugging information will be
     printed to standard output.  A list of all access rules will be
     printed when a `Config::Access' object is created and a line will be
     printed for each invocation of the `access_query()' method.

access_query
     Usage:

          $result = $obj->access_query($service, $client);

     Perform an access query for the specified $service/$client pair.  The
     return value is true if access to the service is allowed for the
     client, and undefined otherwise.

          $result = $obj->access_query($service, $client, $mtype);

     Perform an access query for the $service/$client pair and return the
     match type for the client in the $mtype parameter.  The match type
     refers to the type of rule that allowed or denied the match for the
     client and can take the following values.

    MATCH_SPECIFIC
          The match was made to a directly specified rule in either the
          allow or deny file without using the ALL wildcard.

    MATCH_NET_MASK
          The match was made using a network/netmask pair.

    MATCH_ALL
          The match was made using a rule containing the ALL wildcard.

    MATCH_FALLTHRU
          No matches were made in either the allow or deny file and the
          match fell through.

Exports
-------

default
     none

exportable
     MATCH_SPECIFIC MATCH_ALL MATCH_FALLTHRU MATCH_NET_MASK

tags
     none

EXAMPLE
=======

   The following scripts form a simple example of using the
`Config::Access' module.  The access controls for the example correspond
to the "mostly closed" model of the TCP wrappers.

     cat > test.pl << 'EOF'
     #!/usr/bin/perl

     use strict;
     use Config::Access;

     my($access) = Config::Access->new("example");
     my($user) = getpwuid($UID);

     if (!$access->access_query("beans", $user)) {
         print("Access to service 'beans' denied for user ", $user, "\n");
     }

     if ($access->access_query("ham", $user)) {
         print("Access to service 'ham' allowed for user ", $user, "\n");
     }
     EOF

     cat > example.allow << 'EOF'
     # Example allow file.  Allow all users to service 'ham' and only
     # selected users to service 'beans'.
     beans: tpot, markus
     ham: ALL
     EOF

     cat > example.deny << 'EOF'
     # Example deny file.  Deny all clients access to all services unless
     # specifically allowed above.
     ALL: ALL
     EOF

COPYRIGHT
=========

     Copyright (c) 1995,1996,1997,1998 ANU and CSIRO on behalf of the
     participants in the CRC for Advanced Computational Systems
     ('ACSys').

     ACSys makes this software and all associated data and documentation
     ('Software') available free of charge.  You may make copies of the
     Software but you must include all of this notice on any copy.

     The Software was developed for research purposes and ACSys does not
     warrant that it is error free or fit for any purpose.  ACSys
     disclaims any liability for all claims, expenses, losses, damages
     and costs any user may incur as a result of using, copying or
     modifying the Software.

AUTHOR
======

   Tim Potter <Tim.Potter@anu.edu.au>

Provide in-memory configuration data
************************************

NAME
====

   Config::FreeForm - Provide in-memory configuration data

SYNOPSIS
========

     use Config::FreeForm %options;

DESCRIPTION
===========

   *Config::FreeForm* provides in-memory configuration data in a free-form
manner. Many existing configuration modules attempt to provide some
structure to your configuration data; in doing so, they force you to use
their own configuration paradigm (association of keywords with values,
etc.). Often this isn't what you need in a complex application-you need
complete control over your configuration data, and you need the ability to
structure it however you like. This is what *Config::FreeForm* gives you.

   In *Config::FreeForm* configuration data is stored as a Perl data
structure. The logic behind this is that you know Perl-you shouldn't need
to learn another little language to set up your configuration data,
however simple that language may be. Of course, this works best if
programmers or tools do the updating of your configuration files; it does
make it more difficult for other possible users to edit the files. If this
is a problem for you, try some of the other configuration modules listed
in MISCELLANEOUS.

   Still here? Good. You might then ask what *Config::FreeForm* gives you
that rolling your own light module using Data::Dumper and do would not.
It's a good question, considering in particular that *Config::FreeForm*
uses Data::Dumper and do to write and read your data, respectively.
*Config::FreeForm* adds some very nice features, though:

   * Configuration File Management

     So as not to clutter one file with configuration for all purposes,
     you can separate your configuration data into multiple files, and
     specify which files to load when you load in the module:

          use Config::FreeForm sets => [ ... ];

     *Config::FreeForm* manages the various configuration files that
     you've told it to load, and lets you update your data in memory, then
     write it back to its original location on disk, using the *rewrite*
     function (below, in UPDATING CONFIGURATION).

   * Automated Reloading

     In a mod_perl context, your configuration data will be loaded once,
     at webserver startup; subsequent access to the configuration data
     will come from memory. If you update your configuration on disk,
     then, you'll want those changes to be reflected in the in-memory
     versions of the configuration. *Config::FreeForm* will handle this
     automatically for you if you install it as a *PerlInitHandler* on
     your mod_perl-enabled server. For more details, see AUTOMATED
     RELOADING, below.

HOW TO USE IT
=============

   To create a configuration file, add its configuration to a file like
*Foo.conf*:

     $conf = {
         Foo => { Bar => 1 }
     }

   Once you've written your *Foo.conf* configuration file, load that file
explicitly (without the *.conf*):

     use Config::FreeForm sets => [ 'Foo' ];

   When the module is loaded, it will attempt to find a configuration file
for the set *Foo*; it will load the data in this file using do; then it
will loop over the top-level variables in the tree structure and alias
variables into the *Config::FreeForm* namespace to the values in the
structure.

   For example, if you have the above *Foo.conf*, the variable
*$Config::FreeForm::Foo* will be equal to the following structure:

     {   Bar => 1   }

   So you could access the value of the *Bar* attribute by treating the
aliased variable as a hash reference:

     my $value = $Config::FreeForm::Foo->{Bar};

   In addition to specifying which configuration files to load, you can
use the %options in the import list to set the directory holding the
configuration files. By default *Config::FreeForm* looks in the directory
*FreeForm* within the directory from which it was loaded for the files.
For example, if the module were loaded from `/foo/bar/Config/FreeForm.pm',
the *Foo.conf* configuration file would be default be looked up in
`/foo/bar/Config/FreeForm/Foo.conf'.

   By using the dir import list parameter, though, you can override this
default behavior:

     use Config::FreeForm dir => '/foo', sets => [ 'Foo' ];

   This would look up `Foo.conf' in the directory */foo*.

UPDATING CONFIGURATION
======================

   If you wish to update the configuration files programatically (as
opposed to editing them by hand), you can use the *rewrite* function.

   This is a two-step process. First, you'll need to update the in-memory
configuration-just make a change to one of the variables. For example:

     $Config::FreeForm::Foo->{Bar} = 2;

   This updates the configuration in memory; now you need to write the
configuration to the disk. You can do that using *rewrite*, which takes
the name of a configuration "set" (which corresponds to the name of the
configuration file). In this case, that set would be *Foo*:

     Config::FreeForm::rewrite('Foo');

   And you're done. The configuration is now updated on disk.

   If you'd like to write the configuration data to a file different than
that from which it was read, you can pass a filepath as a second argument.
For example:

     Config::FreeForm::rewrite('Foo', './myfoo.conf');

   This will write out the *Foo* configuration data to `./myfoo.conf'.

   Keep in mind that, if you're rewriting your configuration in a
webserver context, you'll want your on-disk changes to propagate to the
other webserver children (the children in which you didn't already change
the in-memory configuration). Read on-this can be made to happen
automatically.

AUTOMATED RELOADING
===================

   When used in a webserver context, the configuration files are parsed
once at webserver startup, then stored in memory. If changes occur in the
configuration files, under normal circumstances the configuration stored
in memory would not be reloaded. However, *Config::FreeForm* has a
built-in capability to automatically reload configuration files that have
changed on disk. This allows you to make a change to a config file, then
let the webserver automatically pick up the new changes.

   This is particularly important when using the *rewrite* function; if
you alter the in-memory configuration, then write the file to disk, you
want the other webserver children to pick up the changes, in addition to
the child where you actually made the in-memory changes. Using the
automated reloading, these changes will be automatically picked up by all
of the webserver children.

   To use this capability, just install *Config::FreeForm* as a
*PerlInitHandler* in the webserver. Add this to the configuration:

     PerlInitHandler Config::FreeForm

   You can either stick this into a Location block or make it global for
your entire server. The latter may be easier in terms of maintenance, but
the former may give you more flexibility.

   By default, *Config::FreeForm* will go about its business quietly. If
you'd like it to write a message to the error log each time it reloads a
configuration file, you can add a configuration directive to do so:

     PerlSetVar ConfigDebug on

   Now, each time *Config::FreeForm* reloads a configuration file, it will
write a message to the log file telling you the process ID, the
configuration set, and the modified-time comparison that caused the reload.

MISCELLANEOUS
=============

   If the so-called freeform nature of *Config::FreeForm* doesn't appeal
to you, and you'd like a more structured approach to your configuration
files, check out *App-Config*, *Boulder*, or *XML::Simple*.

AUTHOR
======

   Benjamin Trott, ben@rhumba.pair.com

Generic Config Module
*********************

NAME
====

   Config::General - Generic Config Module

SYNOPSIS
========

     use Config::General;
     $conf = new Config::General("rcfile");
     my %config = $conf->getall;

     # or
     $conf = new Config::General(\%somehash);

DESCRIPTION
===========

   This small module opens a config file and parses it's contents for you.
The new method requires one parameter which needs to be a filename. The
method getall returns a hash which contains all options and it's
associated values of your config file.

   The format of config files supported by *Config::General* is inspired
by the well known apache config format, in fact, this module is 100%
compatible to apache configs, but you can also just use simple name/value
pairs in your config files.

   In addition to the capabilities of an apache config file it supports
some enhancements such as here-documents, C-style comments or multiline
options.

METHODS
=======

new()
     Possible ways to call new():

          $conf = new Config::General("rcfile");

          $conf = new Config::General(\%somehash);

          $conf = new Config::General(
                                -file => "rcfile",
                                -AllowMultiOptions => "no"
                                     );

          $conf = new Config::General(
                                -hash => \%somehash,
                                     );

     This method returns a *Config::General* object (a hash blessed into
     "Config::General" namespace.  All further methods must be used from
     that returned object. see below.

     You can use the new style with hash parameters or the old style which
     is of course still supported. Possible parameters are:

          a filename of a configfile

          a hash reference

          or a hash with one or more of the following keys set:

          -file               - a filename.
          -hash               - a hash reference.
          -AllowMultiOptions  - if the value is "no", then multiple
                                identical options are disallowed.

NoMultiOptions()
     This method only exists for compatibility reasons.  Now you should
     set the new() flag *-AllowMultiOptions* to "no".

    The old description: This Turns off the feature of allwing multiple options with identical names. The default behavior is to create an array if an option occurs more than once. But under certain circumstances you may not be willed to allow that. In this case use this method before you call getall to turn it off.
     Please note, that there is no method provided to turn this feature on.

getall()
     Returns a hash structure which represents the whole config.

save("filename", %confighash)
     Writes the config hash back to the harddisk. Please note, that any
     occurence of comments will be ignored and thus be lost after you
     called this method.

     You need also to know that named blocks will be converted to nested
     blocks (which is the same from the perl point of view). An example:

          <user hans>
            id 13
          </user>

     will become the following after saving:

          <user>
            <hans>
               id 13
            </hans>
          </user>

CONFIG FILE FORMAT
==================

   Lines begining with *#* and empty lines will be ignored. (see section
COMMENTS!)  Spaces at the begining and the end of a line will also be
ignored as well as tabulators.  If you need spaces at the end or the
beginning of a value you can use apostrophs *"*.  An optionline starts
with it's name followed by a value. An equalsign is optional.  Some
possible examples:

     user    max
     user  = max
     user            max

   If there are more than one statements with the same name, it will
create an array instead of a scalar. See the example below.

   The method getall returns a hash of all values.

BLOCKS
======

   You can define a block of options. A block looks much like a block in
the wellknown apache config format. It starts with <*blockname*> and ends
with </*blockname*>. An example:

     <database>
        host   = muli
        user   = moare
        dbname = modb
        dbpass = D4r_9Iu
     </database>

   Blocks can also be nested. Here is a more complicated example:

     user   = hans
     server = mc200
     db     = maxis
     passwd = D3rf$
     <jonas>
            user    = tom
            db      = unknown
            host    = mila
            <tablestructure>
                    index   int(100000)
                    name    char(100)
                    prename char(100)
                    city    char(100)
                    status  int(10)
                    allowed moses
                    allowed ingram
                    allowed joice
            </tablestructure>
     </jonas>

   The hash which the method getall returns look like that:

     print Data::Dumper(\%hash);
     $VAR1 = {
              'passwd' => 'D3rf$',
              'jonas'  => {
                           'tablestructure' => {
                                                 'prename' => 'char(100)',
                                                 'index'   => 'int(100000)',
                                                 'city'    => 'char(100)',
                                                 'name'    => 'char(100)',
                                                 'status'  => 'int(10)',
                                                 'allowed' => [
                                                                'moses',
                                                                'ingram',
                                                                'joice',
                                                              ]
                                               },
                           'host'           => 'mila',
                           'db'             => 'unknown',
                           'user'           => 'tom'
                         },
              'db'     => 'maxis',
              'server' => 'mc200',
              'user'   => 'hans'
            };

   If the module cannot find an end-block statement, then this block will
be ignored.

IDENTICAL OPTIONS
=================

   You may have more than one line of the same option with different
values.

   Example:  log  log1  log  log2  log  log2

   You will get a scalar if the option occured only once or an array if it
occured more than once. If you expect multiple identical options, then you
may need to check if an option occured more than once:

     $allowed = $hash{jonas}->{tablestructure}->{allowed};
     if(ref($allowed) eq "ARRAY") {
         @ALLOWED = @{$allowed};
     else {
         @ALLOWED = ($allowed);
     }

   If you don't want to allow more than one identical options, you may
turn it off by setting the flag *AllowMutliOptions* in the new() method to
"no".  If turned off, Config::General will complain about multiple
occuring options whit identical names!

If you need multiple blocks of the same name, then you have to name every block. This works much like apache config. If the module finds a named block, it will create a hashref with the left part of the named block as the key containing one or more hashrefs with the right part of the block as key containing everything inside the block(which may again be nested!). As examples says more than words:
***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************

NAMED BLOCKS
============

   If you need multiple blocks of the same name, then you have to name
every block.  This works much like apache config. If the module finds a
named block, it will create a hashref with the left part of the named
block as the key containing one or more hashrefs with the right part of
the block as key containing everything inside the block(which may again be
nested!). As examples says more than words:

     # given the following sample
     <Directory /usr/frisco>
            Limit Deny
            Options ExecCgi Index
     </Directory>
     <Directory /usr/frik>
            Limit DenyAll
            Options None
     </Directory>

     # you will get:
     $VAR1 = {
              'Directory' => {
                               '/usr/frik' => {
                                                'Options' => 'None',
                                                'Limit' => 'DenyAll'
                                              },
                               '/usr/frisco' => {
                                                  'Options' => 'ExecCgi Index',
                                                  'Limit' => 'Deny'
                                                }
                             }
            };

   You cannot have more than one named block with the same name because it
will be stored in a hashref and therefore be overwritten if a block occurs
once more.

LONG LINES
==========

   If you have a config value, which is too long and would take more than
one line, you can break it into multiple lines by using the backslash
character at the end of the line. The Config::General module will
concatenate those lines to one single-value.

   Example:

   command = cat /var/log/secure/tripwire | \            mail -s "report
from tripwire" \            honey@myotherhost.nl

   command will become:  "cat /var/log/secure/tripwire | mail -s 'report
from twire' honey@myotherhost.nl"

HERE DOCUMENTS
==============

   You can also define a config value as a so called "here-document". You
must tell the module an identifier which identicates the end of a here
document. An identifier must follow a "<<".

   Example:

     message <<EOF
       we want to
       remove the
       homedir of
       root.
     EOF

   Everything between the two "EOF" strings will be in the option message.

   There is a special feature which allows you to use indentation with
here documents.  You can have any amount of whitespaces or tabulators in
front of the end identifier. If the module finds spaces or tabs then it
will remove exactly those amount of spaces from every line inside the
here-document.

   Example:

     message <<EOF
             we want to
             remove the
             homedir of
             root.
          EOF

   After parsing, message will become:

     we want to
     remove the
     homedir of
     root.

   because there were the string "     " in front of EOF, which were
cutted from every line inside the here-document.

INCLUDES
========

   You can include an external file at any posision in you config file
using the following statement in your config file:

     <<include externalconfig.rc>>

   This file will be inserted at the position where it was found as if the
contents of this file were directly at this position.

   You can also recurively include files, so an included file may include
another one and so on.  Beware that you do not recursively load the same
file, you will end with an errormessage like "too many files in system!".

   Include statements will be ignored within C-Comments and here-documents.

COMMENTS
========

   A comment starts with the number sign *#*, there can be any number of
spaces and/or tabstops in front of the #.

   A comment can also occur after a config statement. Example:

     username = max  # this is the comment

   If you want to comment out a large block you can use C-style comments.
A */** signals the begin of a comment block and the **/* signals the end
of the comment block.  Example:

     user  = max # valid option
     db    = tothemax
     /*
     user  = andors
     db    = toand
     */

   In this example the second options of user and db will be ignored.
Please beware of the fact, the if the Module finds a */** string which is
the start of a comment block, but no matching end block, it will ignore
the whole rest of the config file!

COPYRIGHT
=========

   Copyright (c) 2000 Thomas Linden

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

BUGS
====

   none known yet.

AUTHOR
======

   Thomas Linden <tom@daemon.de>

VERSION
=======

   1.18

Extended access to Config files
*******************************

NAME
====

   Config::General::Extended - Extended access to Config files

SYNOPSIS
========

     use Config::General::Extended;
     $conf = new Config::General::Extended("rcfile");
     # or
     $conf = new Config::General::Extended(\%somehash);

DESCRIPTION
===========

   This module is a subclass of *Config::General*. You can use it if you
want OO access to parts of your config file. The following methods are
directly inherited from Config::General: *new() getall()*.

   Please refer to the Config/General, if you want
to learn about the usage of the two methods mentioned above. The possible
format of config files supported by this module is also well described in
Config/General.

METHODS
=======

new('filename') or new(\%somehash)
     This method returns a *Config::General* object (a hash blessed into
     "Config::General::Extended" namespace. All further methods must be
     used from that returned object. see below.

     Read a more detailed discussion on how to use the new() method in
     Config/General.

NoMultiOptions()
     This method only exists for compatibility reasons.  Now you should
     set the new() flag *-AllowMultiOptions* to "no".

     Refer to Config/General, for details about this
     method.

getall()
     Returns a hash structure which represents the whole config.

     If you use this method, then it would be probably better to use the
     simpler module *Config::General*. It is just mentioned here for
     completeness.

save()
     Writes the current config hash back to the harddisk.  It takes an
     optional argument: filename. If you omit a filename, save() will use
     the filename configured by the method *configfile()* or new() (see
     below).

configfile('filename')
     Set the filename to be used by save to "filename". It returns the
     current configured filename if called without arguments.

obj('key')
     Returns a new object (of Config::General::Extended Class) from the
     given key.  Short example: Assume you have the following config:

          <individual>
               <martin>
                  age   23
               </martin>
               <joseph>
                  age   56
               </joseph>
          </individual>
          <other>
               blah     blubber
               blah     gobble
          </other>

     and already read it in using *Config::General::Extended::new()*, then
     you can get a new object from the "individual" block this way:

          $individual = $conf->obj("individual");

     Now if you call getall on *$individual* (just for reference) you
     would get:

          $VAR1 = (
             martin => { age => 13 }
                  );

     Or, here is another use:

          my $individual = $conf->obj("individual");
          foreach my $person ($conf->keys("individual")) {
             $man = $individual->obj($person);
             print "$person is " . $man->value("age") . " years old\n";
          }

     See the discussion on *hash()* and value() below.

hash('key')
     This method returns a hash(if it *is* one!) from the config which is
     referenced by "key". Given the sample config above you would get:

          my %sub_hash = $conf->hash("individual");
          print Dumper(\%sub_hash);
          $VAR1 = {
             martin => { age => 13 }
                  };

array('key')
     This the equivalent of *hash()* mentioned above, except that it
     returns an array.  Again, we use the sample config mentioned above:

          $other = $conf->obj("other");
          my @blahs = $other->array("blah");
          print Dumper(\@blahs);
          $VAR1 = [ "blubber", "gobble" ];

value('key')
     This method returns the scalar value of a given key. Given the
     following sample config:

          name  = arthur
          age   = 23

     you could do something like that:

          print $conf->value("name") . " is " . $conf->value("age") . " years old\n";

     You can use this method also to set the value of "key" to something
     if you give over a hash reference, array reference or a scalar in
     addition to the key. An example:

          $conf->value("key", \%somehash);
          # or
          $conf->value("key", \@somearray);
          # or
          $conf->value("key", $somescalar);

     Please note, that this method does not complain about existing values
     within "key"!

is_hash('key') is_array('key') is_scalar('key')
     As seen above, you can access parts of your current config using
     hash, array or scalar methods. But you are right if you guess, that
     this might become problematic, if for example you call *hash()* on a
     key which is in real not a hash but a scalar. Under normal
     circumstances perl would refuse this and die.

     To avoid such behavior you can use one of the methods is_hash()
     is_array() is_scalar() to check if the value of "key" is really what
     you expect it to be.

     An example(based on the config example from above):

          if($conf->is_hash("individual") {
             $individual = $conf->obj("individual");
          }
          else {
             die "You need to configure a "individual" block!\n";
          }

exists('key')
     This method returns just true if the given key exists in the config.

keys('key')
     Returns an array of the keys under the specified "key". If you use
     the example config above you yould do that:

          print Dumper($conf->keys("individual");
          $VAR1 = [ "martin", "joseph" ];

     You can use this method in foreach loops as seen in an example
     above(obj() ).

AOTOLOAD METHODS
================

   Another usefull feature is implemented in this class using the AUTOLOAD
feature of perl. If you know the keynames of a block within your config,
you can access to the values of each individual key using the method
notation. See the following example and you will get it:

   We assume the following config:

     <person>
        name    = Moser
        prename = Peter
        birth   = 12.10.1972
     </person>

   Now we read it in and process it:

     my $conf = new Config::General::Extended("configfile");
     my $person = $conf->obj("person");
     print $person->prename . " " . $person->name . " is " . $person->age . " years old\n";

   This notation supports only scalar values! You need to make sure, that
the block <person> does not contain any subblock or multiple identical
options(which will become an array after parsing)!

   Of course you can use this kind of methods for writing data too:

     $person->name("Neustein");

   This changes the value of the "name" key to "Neustein". This feature
behaves exactly like value(), which means you can assign hash or array
references as well and that existing values under the given key will be
overwritten.

COPYRIGHT
=========

   Copyright (c) 2000 Thomas Linden

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

BUGS
====

   none known yet.

AUTHOR
======

   Thomas Linden <tom@daemon.de>

VERSION
=======

   1.0

Perl interface to MS-Windows registry files, Windows .ini     and Unreal style .ini files.
******************************************************************************************

NAME
====

   Config::Ini - Perl interface to MS-Windows registry files, Windows .ini
   and Unreal style .ini files.

SYNOPSIS
========

     use Config::Ini;
     $ini = new Config::Ini('system.ini');

     # MS-Windows style
     print $ini->get(['system', 'path']);
     $oldpath = $ini->put(['system', 'path', 'C:\\windows']);
     if ($ini->exists(['system', 'path'])) ...
     $ini->delete(['system', 'path']);

     # Unreal style (multi-valued keys)
     $ini = new Config::Ini('UnrealTournament.ini');
     print map "$_\n", $ini->get(['Engine.GameEngine', 'ServerPackages']);
     $ini->put(['Engine.GameEngine', 'ServerPackages', 'New Mod'], -add => 1);
     if ($ini->exists(['Engine.GameEngine', 'ServerPackages', 'Old Mod'])) ...
     $ini->delete(['Engine.GameEngine', 'ServerPackages', 'Some Mod']);

     $ini->save;

     # Save it in the registry file format
     $ini->registry(1);
     $ini->save('system.reg');

DESCRIPTION
===========

   This package provides easy access to MS-Windows style .ini files, Unreal
style extended .ini files (where multiple values can be associated with a
single key), as well as registry files with automatic conversion from
native Perl to Windows registry data encoding and vice versa.

   For an .ini file to be recognized it must be of the following format:

     [section]
     key=value           ; comments

   In our implementation the key must be no longer than 1024 characters,
and contain no high-ASCII nor control character.

   On a line, everything after the semicolon (;) is ignored.  Backslash (\)
right before the end of line is treated as line continuation marker and
the contents of the next line will be appended after stripping off
preceeding whitespaces.  Comment delimiter takes precedence over line
continuation marker.  Spaces surrounding the delimiting equation sign are
stripped.  If there are more than one equation sign on a line the first
one is treated as the delimiter, the rest of them are considered part of
the value.

   The comment delimiter can be specified during calls to new or open via
the *-commentdelim* option as a regular expression.  If no comment
stripping is desired supply the empty string (") as the argument.

   Specifcations of section, key and value are to be supplied to methods
via an array reference containing just a section name, or the section name
plus a key name, or the section name plus a key name with its associated
value.

   If the first line of a file starts with "REGEDIT4" it will be treated
as a registry file. See the `"Registry Format"' in this node section below
for more details.  Invoking the save method on such a file will have it
saved in registry file format.  If this is not desirable the output mode
can be forced by calling the *registry* method.

Registry Format
---------------

   If the module is processing a Windows "registry" style file, or is
placed into registry mode, all values are automatically converted to and
from native Perl/Windows registry formats.  For special situations you can
use the *decode_reg_value* subroutine for manual decoding.

   A registry file follows the same format described above, except that
keys are expected to be enclosed in double quotes.  The first line of a
registry file starts with "REGEDIT4".

     Strings - A string is stored in the registry as a sequence of
     alphanumeric symbols that are enclosed in a pair of double quotation
     marks (").  When retrieving a string from a registry file, only the
     actual data is returned in the scalar variable.  When writting a
     string, you need to enclose it within the double quotations marks.

          $ini->put(['sys', 'mystr', '"hi there"'], -add => 1);
          print $ini->get(['sys', 'mystr']);

     This will result in the un-quoted 8 character long "hi there" string
     being printed.

     The registry file contains:

          [sys]
          "mystr"="hi there"

     *32 bit numbers* - The registry format allows for special handling of
     32 bit numbers.  When you pass in a scalar that is not enclosed in
     double quotations, this library will assume you are tring to store a
     number.  When retrieving a number it is returned as a Perl number.

          $ini->put(['sys', 'Number', 100], -add => 1);
          print $ini->get(['sys', 'Number']);

     This will result in "100" being printed.

     The registry file contains:

          [sys]
          "Number"=dword:00000064

     *Arrays of 8 bit numbers* - If you need to store value that is an
     array of numbers, you can pass in an array or list of non-quote
     enclosed scalars.  When retrieving that key's value this module will
     return an array or list of scalars.

          $ini->put(['sys', 'ListOfNumbers', ( 1...9) ], -add => 1);
          @nums = $ini->get(['sys', 'ListOfNumbers']);

     This will result in an array containing 10 elements.

     The registry file contains:

          [sys]
          "ListOfNumbers"=hex:00,01,02,03,04,05,06,07,08,09

     *Multiple Strings* - Registries can also store a list of strings.
     They are stored as a sequence of null terminated arrays of 8 bit
     numbers, and there is a final null marking the end of the sequence.
     When saving multiple strings, you pass in an array or list of scalars
     that contains double-quote delimited strings.  When retrieving one of
     these values, you will receive an array of strings (without the
     enclosing quotation marks).

          $ini->put(['sys', 'ListOfStr', ( '"str1"', '"str2"', '"str3"' ) ], -add => 1);
          @strs = $ini->get(['sys', 'ListOfStr']);

     This will result in an array containing 3 elements: "str1", "str2"
     and "str3".

     The registry file contains:

          [sys]
          "ListOfStr"=hex(7):73,74,72,31,00,73,74,72,32,00,73,74,\
          72,33,00,00

     Note that this example contains a line continuation marker "\".

METHODS
=======

new([filename])
     Constructor.  If a filename is supplied it will be opened as an .ini
     file with its content read as the initial configuration of the object.

*open(self[, filename])*
     Open the .ini file and read in all valid entries.  New entries will be
     merged with the existing configuration.

*save(self[, filename])*
     Save the current configuration into file in the .ini format.  Both
     the section order and the order of key=value pairs within a section
     are preserved.  If a filename is given the file will be used as the
     save target, otherwise the configuration will be save to the last
     used (via new, open or save) file.  The original content of the file
     will be clobbered.  Be careful not to inadvertently merge two .ini
     files into one by opening them in turn and then saving.

     True will be returned if the save is successful, false otherwise.

*file(self[, filename] )*
     Set or retrieve the filename that was last used.  new, open and save
     will all update the last used filename if a filename was supplied to
     them.

lastpos(self)
     Set or retrieve the byte offset into the file immediately after the
     last line that conforms to the .ini format.

registry(self)
     Set or retrieve the registry flag which determines whether the file is
     to be treated as a registry file or .ini file.  If this flag is true
     all subsequent file operations will work in registry file mode,
     otherwise the .ini mode is used.  Normally this flag need not be
     altered manually because it is automatically set to a value matching
     the format of the most recently read file.

commentdelim(self)
     Set or retrieve the comment delimiter.

*exists(self, [ section[, key[, value]] ])*
     Return true if the specified section exists, or if the specified key
     exists in the specified section.  If a value is specified, return true
     if it is any one of the values of the key.

*get(self, [ section[, key[, value]] ][, -mapping =* ('single'|'multiple'))>
     Depending on how many elements are specified in the array reference,
     retrieve the entire specified section or the values of the specified
     key.

     If nothing is specified the entire file is returned as a hash
     reference.

     If only a section name is specified the matching section is returned
     in its entirety as a hash reference.

     If both a section name and a key name are specified, the associated
     values are returned.  If the key has multiple values the returned
     result is an array reference containing all the values, otherwise if
     the key has only one value that single value is returned as a scalar.

     The decision of whether to return a single or multiple values can be
     forced via the *-mapping* argument.  If the multiple mapping option is
     applied to a single value result an array of one element that is the
     single value will be returned.  If on the other hand the single
     mapping option is forced upon a mutli-valued result only the first
     value will be returned.

     In general, don't specify any mapping when dealing with standard
     MS-Windows style .ini files and use the multiple mapping when dealing
     with multivalued keys in an Unreal style .ini files.

*put(self, [ section[, key[, value]] ][, -add =* boolean])>
     Set the value for the specified key in the specified section and
     return the old value.  If the optional *-add* argument is true a new
     value will be added to the key if that value does not already exist.

decode_reg_value(value)
     Returns a decoded value or list of values from a registry key.  See
     the section above on `"Registry Format"' in this node. This routine
     accepts the raw value field from a registry entry, and return a Perl
     specific data structure that natively represents the data.

     This routine is called automatically when either get or set methods
     are called specifying a particular key.  If you used get to retrieve
     a whole section, the values of the registry keys will be in their
     native file format.  You must use this method call to convert them
     from registry to Perl format.

*delete(self, [ section[, key[, value]] ][, -keep =* boolean])>
     If section, key and value are all given the corresponding key=value
     pair will be deleted from the specified section.  If a specific value
     is not given the entire key including all its values will be deleted.
     If the path only specifies a section the entire section will be
     deleted.

     If the optional *-keep* argument evaluates to true, when performing
     section deletion all the keys along with their values are deleted but
     the now empty section will still exist to mimic the bahavior of the
     Unreal uninstaller.

*adjustfilecase(filename[, dirname])*
     Return the properly cased filename by performing a case-insensitive
     match of the specified file within the specified parent directory.  If
     there is no match the filename passed in is return as-is.  If the
     dirname argument is not given the current directory will be used.

adjustpathcase(pathname)
     Return the properly cased and slashed pathname, unless running on a
     brain-damaged OS that is too dumb to handle pathnames in a modern,
     case-sensitive manner.  Each path components are inspected from left
     to right to see if a file or directory of the same name, in any case
     combination, already exists.  If any match results the first match is
     used, otherwise the original path component is used verbatim.  No
     backtracking is performed, so if any path component in the middle
     fails to match an existing directory, all subsequent path components
     are used as-is.  All backslashes are also changed to forward-slashes.

AUTHOR
======

   Avatar <`avatar@deva.net'>, based on a prototype by Mishka Gorodnitzky
<`misaka@pobox.com'>.  Registry file support by Fulko Hew
<`fulko@wecan.com'>.

A module for reading .ini-style configuration files.
****************************************************

NAME
====

   Config::IniFiles - A module for reading .ini-style configuration files.

SYNOPSIS
========

     use Config::IniFiles;
     my $cfg = new Config::IniFiles( -file => "/path/configfile.ini" );
     print "We have parm $cfg->val( 'Section', 'Parameter' )." if $cfg->val( 'Section', 'Parameter' );

DESCRIPTION
===========

   Config::IniFiles provides a way to have readable configuration files
outside your Perl script.  Configurations can be imported (inherited,
stacked,...), sections can be grouped, and settings can be accessed from a
tied hash.

USAGE - Object Interface
========================

   Get a new Config::IniFiles object with the new method:

     $cfg = Config::IniFiles->new( -file => "/path/configfile.ini" );
     $cfg = new Config::IniFiles -file => "/path/configfile.ini";

   Optional named parameters may be specified after the configuration file
name.  See the new in the METHODS section, below.

   INI files consist of a number of sections, each preceeded with the
section name in square brackets.  The first nonblank character of the line
indicating a section must be a left bracket and the last nonblank
character of a line indicating a section must be a right bracket. The
characters making up the section name can be any symbols at all. However
section names must be unique.

   Parameters are specified in each section as Name=Value.  Any spaces
around the equals sign will be ignored, and the value extends to the end
of the line. Parameter names are localized to the namespace of the
section, but must be unique within a section.

     [section]
     Parameter=Value

   Both the hash mark (#) and the semicolon (;) are comment characters.
Lines that begin with either of these characters will be ignored.  Any
amount of whitespace may preceed the comment character.

   Multiline or multivalued fields may also be defined ala UNIX "here
document" syntax:

     Parameter=<<EOT
     value/line 1
     value/line 2
     EOT

   You may use any string you want in place of "EOT".  Note that what
follows the "<<" and what appears at the end of the text MUST match
exactly, including any trailing whitespace.

   See the METHODS section, below, for settable options.

   Values from the config file are fetched with the val method:

     $value = $cfg->val('Section', 'Parameter');

   If you want a multi-line/value field returned as an array, just specify
an array as the receiver:

     @values = $cfg->val('Section', 'Parameter');

METHODS
=======

new ( [-option=>value ...] )
----------------------------

   Returns a new configuration object (or "undef" if the configuration
file has an error).  One Config::IniFiles object is required per
configuration file.  The following named parameters are available:

*-file*  filename
     Specifies a file to load the parameters from. If this option is not
     specified, (ie: you are creating a config file from scratch) you must
     specify a target file using SetFileName in order to save the
     parameters.

*-default* section
     Specifies a section is used for default values.  For example, if you
     look up the "permissions" parameter in the "users" section, but there
     is none, Config::IniFiles will look to your default section for a
     "permissions" value before returning undef.

*-reloadwarn* 0|1
     Set -reloadwarn => 1 to enable a warning message (output to STDERR)
     whenever the config file is reloaded.  The reload message is of the
     form:

          PID <PID> reloading config file <file> at YYYY.MM.DD HH:MM:SS

*-nocase* 0|1
     Set -nocase => 1 to handle the config file in a case-insensitive
     manner (case in values is preserved, however).  By default, config
     files are case-sensitive (i.e., a section named 'Test' is not the same
     as a section named 'test').  Note that there is an added overhead for
     turning off case sensitivity.

*-import* object
     This allows you to import or inherit existing setting from another
     Config::IniFiles object. When importing settings from another object,
     sections with the same name will be merged and parameters that are
     defined in both the imported object and the *-file* will take the
     value of given in the *-file*.

     If a *-default* section is also given on this call, and it does not
     coincide with the default of the imported object, the new default
     section will be used instead. If no *-default* section is given, then
     the default of the imported object will be used.

val ($section, $parameter)
--------------------------

   Returns the value of the specified parameter in section $section,
returns undef if no section or no parameter for the given section exists.

   If you want a multi-line/value field returned as an array, just specify
an array as the receiver:

     @values = $cfg->val('Section', 'Parameter');

setval ($section, $parameter, $value, [ $value2, ... ])
-------------------------------------------------------

   Sets the value of parameter $parameter in section $section to $value (or
to a set of values).  See below for methods to write the new configuration
back out to a file.

   You may not set a parameter that didn't exist in the original
configuration file.  setval will return undef if this is attempted. See
*newval* below to do this. Otherwise, it returns 1.

newval($setion, $parameter, $value [, $value2, ...])
----------------------------------------------------

   Adds a new value to the configuration file.

delval($section, $parameter)
----------------------------

   Deletes the specified value from the configuration file

ReadConfig
----------

   Forces the config file to be re-read. Returns undef if the file can not
be opened.

Sections
--------

   Returns an array containing section names in the configuration file.
If the *nocase* option was turned on when the config object was created,
the section names will be returned in lowercase.

Parameters ($sectionname)
-------------------------

   Returns an array containing the parameters contained in the specified
section.

Groups
------

   Returns an array containing the names of available groups.

   Groups are specified in the config file as new sections of the form

     [GroupName MemberName]

   This is useful for building up lists.  Note that parameters within a
"member" section are referenced normally (i.e., the section name is still
"Groupname Membername", including the space) - the concept of Groups is to
aid people building more complex configuration files.

GroupMembers ($group)
---------------------

   Returns an array containing the members of specified $group. Each
element of the array is a section name. For example, given the sections

     [Group Element 1]
     ...

     [Group Element 2]
     ...

   GroupMembers would return ("Group Element 1", "Group Element 2").

WriteConfig ($filename)
-----------------------

   Writes out a new copy of the configuration file.  A temporary file
(ending in .new) is written out and then renamed to the specified
filename.  Also see BUGS below.

RewriteConfig
-------------

   Same as WriteConfig, but specifies that the original configuration file
should be rewritten.

SetFileName ($filename)
-----------------------

   If you created the Config::IniFiles object without initialising from a
file, or if you just want to change the name of the file to use for
ReadConfig/RewriteConfig from now on, use this method.

   Returns $filename if that was a valid name, undef otherwise.

SetSectionComment($section, @comment)
-------------------------------------

   Sets the comment for section $section to the lines contained in
@comment.  Each comment line will be prepended with "#" if it doesn't
already have a comment character (ie: if $line !~ m/^\s*[#;]/)

   To clear a section comment, use DeleteSectionComment ($section)

GetSectionComment ($section)
----------------------------

   Returns a list of lines, being the comment attached to section
$section. In scalar context, returns a string containing the lines of the
comment separated by newlines.

   The lines are presented as-is, with whatever comment character was
originally used on that line.

DeleteSectionComment ($section)
-------------------------------

   Removes the comment for the specified section.

SetParameterComment ($section, $parameter, @comment)
----------------------------------------------------

   Sets the comment attached to a particular parameter.

   Any line of @comment that does not have a comment character will be
prepended with "#".

GetParameterComment ($section, $parameter)
------------------------------------------

   Gets the comment attached to a parameter.

DeleteParameterComment ($section, $parameter)
---------------------------------------------

   Deletes the comment attached to a parameter.

GetParameterEOT ($section, $parameter)
--------------------------------------

   Accessor method for the EOT text (in fact, style) of the specified
parameter. If any text is used as an EOT mark, this will be returned. If
the parameter was not recorded using HERE style multiple lines,
GetParameterEOT returns undef.

SetParameterEOT ($section, $EOT)
--------------------------------

   Accessor method for the EOT text for the specified parameter. Sets the
HERE style marker text to the value $EOT. Once the EOT text is set, that
parameter will be saved in HERE style.

   To un-set the EOT text, use DeleteParameterEOT ($section, $parameter).

DeleteParameterEOT ($section, $parameter)
-----------------------------------------

DeleteSection ( $section_name )
     Completely removes the entire section from the configuration.

Delete
     Deletes the entire configuration file.

USAGE - Tied Hash
=================

tie $ini, 'Config::Inifiles', (-file=>$filename, [-option=>value ...] )
-----------------------------------------------------------------------

   Using tie, you can tie a hash to a Config::IniFiles object. This
creates a new object which you can access through your hash, so you use
this instead of the new method. This actually creates a hash of hashes to
access the values in the .ini-file.

   Here's an example:

     use Config::IniFiles;

     my %ini
     tie %ini, 'Config::IniFiles', ( -file => "/path/configfile.ini" );

     print "We have parm %ini{Section}{Parameter}." if %ini{'Section'}{'Parameter'};

   Accessing and using the hash works just like accessing and using an
object, except in the way you reference it. More information about using
the hash interface is descibed below under the corresponding object
methods.

   For those methods that do not coincide with the hash paradigm, you can
use the Perl tied function to get at the underlying object tied to the hash
and call methods on that object. For example, to write the hash out to a
new ini file, you would do something like this:

     tied( %ini )->WriteConfig( "/newpath/newconfig.ini" ) ||
       die "Could not write settings to new file.";

$val = $ini{$section}{$parameter}
---------------------------------

   Returns the value of $parameter in $section, through the hash tie
interface.

   Because of limitations in Perl's tie implementation, multiline values
accessed through a hash will always be returned as a single value with
each line joined by the default line separator ($\). To break them apart
you can simple do this:

     @lines = split( "$\", $ini{section}{multi_line_parameter} );

$ini{$section}{$parameter} = $value;
------------------------------------

   Sets the value of $parameter in $section to value given.  through the
hash interface. If the parameter did not exist in the original file, it
will be created.

   To set a multiline or multivalue parameter use something like this:

     $ini{$section}{$parameter} = [$value1, $value2, ...];

   However, Perl does not seem to extend autovivification to tied hashes.
That means that if you try to say

     $ini{new_section}{new_paramters} = $val;

   and the section 'new_section' does not exist, then Perl won't properly
create it. In order to work around this you will need to create a hash
reference in that section and then assign the parameter value. Something
like this should do nicely:

     $ini{new_section} = {};
     $ini{new_section}{new_paramters} = $val;

%hash = %{$ini{$section}}
-------------------------

   Using the tie interface, you can copy whole sections of the ini file
into another hash. Note that this makes a copy of the entire section. The
new hash in no longer tied to the ini file, In particular, this means
-default and -nocase settings will not apply to `%hash'.

$ini{$section} = {}; %{$ini{$section}} = %parameters;
-----------------------------------------------------

   Through the hash interface, you have the ability to replace the entire
section with a new set of parameters. This call will fail, however, if the
argument passed in NOT a hash reference. You must use both lines, as shown
above so that Perl recognizes the section as a hash reference context
before COPYing over the values from your `%parameters' hash.

delete $ini{$section}{$parameter}
---------------------------------

   When tied to a hash, you can use the Perl delete function to completely
remove a parameter from a section.

delete $ini{$section}
---------------------

   The tied interface also allows you to delete an entire section from the
ini file using the Perl delete function.

$ini = ();
----------

   If you really want to delete all the items in the ini file, this will
do it. Of course, the changes won't be written to the actual file unless
you call RewriteConfig on the object tied to the hash.

Parameter names
---------------

my @keys = keys %{$ini{$section}}
while (($k, $v) = each %{$ini{$section}}) {...}
if( exists %{$ini{$section}}, $parameter ) {...}
   When tied to a hash, you use the Perl keys and each functions to
iteratively list the parameters (keys) or parameters and their values
(each) in a given section.

   You can also use the Perl exists function to see if a parameter is
defined in a given section.

   Note that none of these will return parameter names that are part if
the default section (if set), although accessing and unknown parameter in
the specified section will return a value from the default section if
there is one.

Section names
-------------

keys %ini, $section
while (($k, $v) = each %ini) {...}
if( exists %ini, $section ) {...}
   When tied to a hash, you use the Perl keys and each functions to
iteratively list the sections in the ini file.

   You can also use the Perl exists function to see if a section is
defined in the file.

DIAGNOSTICS
===========

@Config::IniFiles::errors
-------------------------

   Contains a list of errors encountered while parsing the configuration
file.  If the new method returns undef, check the value of this to find
out what's wrong.  This value is reset each time a config file is read.

BUGS
====

   * The output from [Re]WriteConfig/OutputConfig might not be as pretty as
     it can be.  Comments are tied to whatever was immediately below them.

   * No locking is done by [Re]WriteConfig.  When writing servers, take
     care that only the parent ever calls this, and consider making your
     own backup.

Data Structure
==============

   Note that this is only a reference for the package maintainers - one of
the upcoming revisions to this package will include a total clean up of the
data structure.

     $iniconf->{cf} = "config_file_name"
             ->{startup_settings} = \%orginal_object_parameters
             ->{firstload} = 0
             ->{nocase} = 0
             ->{reloadwarn} = 0
             ->{sects} = \@sections
             ->{sCMT}{$section} = \@comment_lines
             ->{group}{$group} = \@group_members
             ->{parms}{$section} = \@section_parms
             ->{EOT}{$sect}{$parm} = "end of text string"
             ->{pCMT}{$section}{$parm} = \@comment_lines
             ->{v}{$section}{$parm} = $value   OR  \@values

AUTHOR and ACKNOWLEDGEMENTS
===========================

   The original code was written by Scott Hutton.  It has since been taken
over by Rich Bowen, with many contributions from various other people.

   In particular, special thanks go to (in roughly chronological order):

   Bernie Cosell, Alan Young, Alex Satrapa, Mike Blazer, Wilbert van de
Pieterman, Steve Campbell, Robert Konigsberg, Scott Dellinger, R.
Bernstein, Jeremy Wadsack, Daniel Winkelmann, Pires Claudio,  and Adrian
Phillips.

   Geez, that's a lot of people. And apologies to the folks I missed.

   If you want someone to bug about this, that would be:

     Rich Bowen <rbowen at rcbowen dot com>

   If you want more information, or want to participate, go to:

     http://sourceforge.net/projects/config-inifiles/

   Please send bug reports to config-inifiles-bugs@lists.sourceforge.net

   Development discussion occurs on the mailing list
config-inifiles-dev@lists.sourceforge.net, which you can subscribe to by
going to the project web site (link above).

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Change log
==========

     $Log: IniFiles.pm,v $
     Revision 2.14  2001/01/08 18:02:32  wadg
     [Bug #127325] Fixed proken import; changelog; moved

     Revision 2.13  2000/12/18 07:14:41  wadg
     [Bugs# 122441,122437] Alien EOLs and OO delete method

     Revision 2.12  2000/12/18 04:59:37  wadg
     [Bug #125524] Writing multiline of 2 with tied hash

     Revision 2.11  2000/12/16 12:53:13  grail
     [BUG #122455] Problem with File Permissions

     Revision 2.10  2000/12/13 17:40:18  rbowen
     Updated version number so that CPAN will stop being angry with us.

     Revision 1.18  2000/12/08 00:45:35  grail
     Change as requested by Jeremy Wadsack, for Bug 123146

     Revision 1.17  2000/12/07 15:32:36  grail
     Further patch to duplicate sections bug, and replacement of repeated values handling code.

     Revision 1.14  2000/11/29 11:26:03  grail
     Updates for task 22401 (no more reloadsig) and 22402 (Group and GroupMember doco)

     Revision 1.13  2000/11/28 12:41:42  grail
     Added test for being able to add sections with wierd names like section|version2

     Revision 1.11  2000/11/24 21:20:11  rbowen
     Resolved SourceForge bug #122445 - a parameter should be split from its value on the first = sign encountered, not on the last one. Added test suite to test this, and put test case in test.ini

     Revision 1.10  2000/11/24 20:40:58  rbowen
     Updated MANIFEST to have file list of new files in t/
     Updated IniFiles.pm to have mention of sourceforge addresses, rather than rcbowen.com addresses
     Regenerated README from IniFiles.pm

     Revision 1.9  2000/11/23 05:08:08  grail
     Fixed documentation for bug 122443 - Check that INI files can be created from scratch.

     Revision 1.1.1.1  2000/11/10 03:04:01  rbowen
     Initial checkin of the Config::IniFiles source to SourceForge

     Revision 1.8  2000/10/17 01:52:55  rbowen
     Patch from Jeremy. Fixed "defined" warnings.

     Revision 1.7  2000/09/21 11:19:17  rbowen
     Mostly documentation changes. I moved the change log into the POD rather
     than having it in a separate Changes file. This allows people to see the
     changes in the Readme before they download the module. Now I just
     need to make sure I remember to regenerate the Readme every time I do
     a commit.

     1.6 September 19, 2000 by JW, AS
     * Applied several patches submitted to me by Jeremy and Alex.
     * Changed version number to the CVS version number, so that I won't
     have to think about changing it ever again. Big version change
     should not be taken as a huge leap forward.

     0.12 September 13, 2000 by JW/WADG
     * Added documentation to clarify autovivification issues when
     creating new sections
     * Fixed version number (Oops!)

     0.11 September 13, 2000 by JW/WADG
     * Applied patch to Group and GroupMembers functions to return empty
     list when no groups are present (submitted by John Bass, Sep 13)

     0.10 September 13, 2000 by JW/WADG
     * Fixed reference in POD to ReWriteFile. changes to RewriteConfig
     * Applied patch for failed open bug submitted by Mordechai T. Abzug Aug 18
     * Doc'd behavior of failed open
     * Removed planned SIG testing from test.pl as SIGs have been removed
     * Applied patch from Thibault Deflers to fix bug in parameter list
     when a parameter value is undef

     0.09
     Hey! Where's the change log for 0.09?

     0.08
     2000-07-30  Adrian Phillips  <adrianp@powertech.no>

     * test.pl: Fixed some tests which use $\, and made those that try
     to check a non existant val check against ! defined.

     * IniFiles.pm: hopefully fixed use of $\ when this is unset
     (problems found when running tests with -w).  Similar problem with
     $/ which can be undefined and trying to return a val which does
     not exist. Modified val docs section to indicate a undef return
     when this occurs.

     0.07
     Looks like we missed a change log for 0.07. Bummer.

     0.06 Sun Jun 25, 2000 by Daniel Winkelmann
     * Patch for uninitialized value bug in newval and setval

     0.05 Sun Jun 18, 2000 by RBOW
     * Added something to shut up -w on VERSIONS
     * Removed unused variables

     0.04 Thu Jun 15 - Fri Jun 16, 2000 by JW/WADG
     * Added support for -import option on ->new
     * Added support for tying a hash
     * Edited POD for grammer, clarity and updates
     * Updated test.pl file
     * Fixed bug in multiline/single line output
     * Fixed bug in default handling with tie interface
     * Added bugs to test.pl for regression
     * Fixed bug in {group} vs. {groups} property (first is valid)
     * Fixed return value for empty {sects} or {parms}{$sect} in
     Sections and Parameters methods

     0.03 Thu Jun 15, 2000 by RBOW
     * Modifications to permit 'use strict', and to get 'make test' working
     again.

     0.02 Tue Jun 13, 2000 by RBOW
     * Fixed bug reported by Bernie Cosell - Sections, Parameters,
     and GroupMembers return undef if there are no sections,
     parameters, or group members. These functions now return
     () if the particular value is undefined.
     * Added some contributed documentation, from Alex Satrapa, explaining
     how the internal data structure works.
     * Set up a project on SourceForge. (Not a change, but worth
     noting).
     * Added Groups method to return a list of section groups.

     0.01  Mon Jun 12, 2000 by RBOW
     Some general code cleanup, in preparation for changes to
     come. Put up Majordomo mailing list and sent invitation to
     various people to join it.

read Java-style properties files
********************************

NAME
====

   Config::Properties - read Java-style properties files

SYNOPSIS
========

   use Config::Properties;

   my $properties = new Properties(); $properties->load( $fileHandle );

   $value = $properties->getProperty( $key ); $properties->setProperty(
$key, $value );

   $properties->store( $fileHandle, $header );

DESCRIPTION
===========

   Config::Properties is an near implementation of the
java.util.Properties API.  It is designed to allow easy reading, writing
and manipulation of Java-style property files.

   The format of a Java-style property file is that of a key-value pair
seperated by either whitespace, the colon (:) character, or the equals (=)
character.  Whitespace before the key and on either side of the seperator
is ignored.

   Lines that begin with either a hash (#) or a bang (!) are considered
comment lines and ignored.

   A backslash (\) at the end of a line signifies a continuation and the
next line is counted as part of the current line (minus the backslash, any
whitespace after the backslash, the line break, and any whitespace at the
beginning of the next line).

   When a property file is saved it is in the format "key=value" for each
line.

AUTHOR
======

   `Config::Properties' was developed by Randy Jay Yarger.

API for locating user information regardless of OS
**************************************************

NAME
====

   User - API for locating user information regardless of OS

SYNOPSIS
========

     use Config::User;

     my $cfg = Config::IniFiles->new
           (
             -file    => sprintf("%s/%s", Config::User->Home, ".ncfg"),
             -default => 'Default'
           );

DESCRIPTION
===========

   This module is allows applications to retrieve per-user
characteristics. At present, it contains only one method, Home(), which is
used to return a location that can be expected to be a users "Home"
directory on either Windows or Unix.

   While one way of writing this would be to check for operating system
and then check the expected location for an operation system of that type,
I chose to do the following:

     sub Home {

     return $ENV{HOME}        if $ENV{HOME};
     return $ENV{USERPROFILE} if $ENV{USERPROFILE};
     return  "";

     }

   In other words, if $HOME is defined in the user's environment, then
that is used. Otherwise $USERPROFILE is used. Otherwise "" is returned.

   A contribution for Macintosh (or any other number of OS/arch
combinations) is greatly solicited.

EXPORT
------

   None by default.

AUTHOR
======

   T.M. Brannon, tbone@cpan.org

ACKNOWLEDGEMENTS
================

   I would like to offer profuse thanks to my fellow perl monk at
www.perlmonks.org, the_slycer, who told me where HOME could be found on
Windows machines.

   perl(1).

Simple configuration file parser
********************************

NAME
====

   ConfigReader::Simple - Simple configuration file parser

SYNOPSIS
========

     use ConfigReader::Simple;

     $config = ConfigReader::Simple->new("configrc", [qw(Foo Bar Baz Quux)]);

     $config->parse();

     $config->get("Foo");

DESCRIPTION
===========

     C<ConfigReader::Simple> reads and parses simple configuration files. It's
     designed to be smaller and simpler than the C<ConfigReader> module
     and is more suited to simple configuration files.

CONSTRUCTOR
===========

new ( FILENAME, DIRECTIVES )
     This is the constructor for a new ConfigReader::Simple object.

     FILENAME tells the instance where to look for the configuration file.

     DIRECTIVES is an optional argument and is a reference to an array.
     Each member of the array should contain one valid directive. A
     directive is the name of a key that must occur in the configuration
     file. If it is not found, the module will die. The directive list may
     contain all the keys in the configuration file, a sub set of keys or
     no keys at all.

     This does the actual work.  No parameters needed.

     Returns the parsed value for that directive.

_validate_keys ( )
     If any keys were declared when the object was constructed, check that
     those keys actually occur in the configuration file.

LIMITATIONS/BUGS
================

   Directives are case-sensitive.

   If a directive is repeated, the first instance will silently be ignored.

   Always die()s on errors instead of reporting them.

   get() doesn't warn if used before parse().

   get() doesn't warn if you try to acces the value of an unknown
directive not know (ie: one that wasn't passed via new()).

   All these will be addressed in future releases.

CREDITS
=======

   Kim Ryan <kimaryan@ozemail.com.au> adapted the module to make declaring
keys optional.  Thanks Kim.

AUTHORS
=======

   Bek Oberin <gossamer@tertius.net.au>

COPYRIGHT
=========

   Copyright (c) 2000 Bek Oberin.  All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Introduction to Perl Conjury
****************************

NAME
====

   Conjury - Introduction to Perl Conjury

DESCRIPTION
===========

   Perl Conjury is a general purpose software construction framework.
It's an alternative to the venerable make utility, but since it is written
entirely in Perl, its capabilities extend to functions traditionally
implemented using a text preprocessor to generate `Makefile' files, i.e.
to configure for product variants.

   The Perl Conjury system is a modular framework.  The core software is
very general.  For example, to compile and link executable programs
written in C or C++, you'll need the `Conjury::C' module- bundled
separately.

   To use Perl Conjury, you will need Perl installed on your system.  The
command line utility is named *cast*, and it is a very short Perl script.
It simply loads the `Conjury::Core' module, which does the heavy lifting:
parsing the arguments and interpreting the files containing the "spells"
for constructing your products from their sources.

   Before the *cast* utility loads the `Conjury::Core' module, it first
tries to add the top of the source file hierarchy to the Perl library
search path.  It does this by looking for a `Conjury' directory in the
current directory, then its parent, that that directory's parent, all the
way to the root of the current directory.  Application specific modules
for constructing the software should be placed in this directory and use
the `Conjury' namespace.

   You can carry all the general purpose Perl Conjury modules around with
your source code, in whole or in part- altering them for your own ends, if
you like.  Alternatively, you can just require that they be properly
installed in the Perl site library.  Your choice.

   If you use the `Conjury::Core' module from the Perl Conjury
distribution, then files named `Conjury.pl', which you place in the same
directories as the source, contain the code for constructing the products.
These are written in Perl, and use modules from the Perl Conjury
distribution as well as application-specific modules that are part of the
source for the software under construction.

   You'll need a `Conjury.pl' file at the top of your source file
hierarchy, but you may use the `Conjury::Core::deferral' function to
create spells that defer action to other spells defined in `Conjury.pl'
files you place in different locations in the source file hierarchy.

FILES
=====

`Conjury.pl'
     These files are Perl libraries (i.e. they are not executed directly,
     but rather loaded by the *cast* utility) that contain the code for
     constructing products from the source file with which they are
     associated.

`Conjury'
     This directory is found at the top of the source file hierarchy for
     the software under construction.

SEE ALSO
========

   More documentation can be found in `cast' in this node, see
Conjury/Core, and, of course- `Perl' in this node.

NOTES
=====

   You're wondering- why the name "Conjury" of all things?  It's very
simple.

   If you have much experience owning and maintaining the code responsible
for constructing a large, complex, cross-platform software system using
make, you've probably seen all manner of horrific mechanisms for
generating `Makefile' files using arcane translators and text processors.
Some commercial software development environments even seem to perpetuate
the problem to promote particular platforms.

   These systems tend to combine the worst features of several languages
together into the sort of Lovecraftian crawling horror that makes Perl
seem like a harmless, fluffy bunny in comparison- thus, the motivation for
this work.

   If you haven't yet, you really must see the sequence in that 1950's era
animated feature film in which the most famous mouse in the world is "the
sorcerer's apprentice," and he has used his master's magical arts to
create an army of animated broomsticks to carry his water for him. It is
the image of the mouse swirling around in the vortex of a whirlpool in the
torrent of water his broomsticks dutifully create for him, while he is
frantically thumbing through the documentation looking for the spell that
will shut them all down, that the author had in mind when he was casting
about for a name for this framework.

CREDIT AND ATTRIBUTION
======================

   James Woodyatt <`jhw@wetware.com'>

   The venerable make and its derivatives have inspired many attempts at
better ways to approach basically the same problem. Perl Conjury is not
the first, and it will doubtless not be the last. The author wishes to
give due credit to the authors of *jam* and *cons* for the deep thinking
that inspired this work- in particular, the idea of journaling MD5
signatures to track which productions are up-to-date is a very good one,
and the author slammed his forehead with his open palm very hard when he
first saw it in the *cons* utility.

LICENSE
=======

   Copyright (c) 1999-2000 James H. Woodyatt.  All rights reserved.

   Redistribution and use of the software in source and machine-readable
forms, with or without modification, are permitted provided that the
following conditions are met:

   1. Redistributions of source code must contain the above copyright
notice, this list of conditions and the following disclaimer.

   2. Redistributions in machine-readable form must reproduce the above
copyright notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND ITS CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO THE IMPLIED MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBLITY OF SUCH DAMAGE.

Perl Conjury with C/C++ compilers, linkers and archivers
********************************************************

NAME
====

   Conjury::C - Perl Conjury with C/C++ compilers, linkers and archivers

SYNOPSIS
========

     c_object
       Source => I<source-file>,
       Directory => I<directory>,
       Includes => [ I<dir1>, I<dir2>, ... ],
       Defines => { I<var1> => I<val1>, I<var2> => I<val2>, ... },
       Compiler => I<compiler>,
       Options => [ I<opt1>, I<opt2>, ... ],
       Factors => [ I<factor1>, I<factor2>, ... ];

     c_executable
       Directory => I<directory>,
       Name => I<output-filename>,
       Order => [
     	Searches => [ I<dir1>, I<dir2>, ... ],
     	Objects => [ I<obj1>, I<obj2>, ... ],
     	Libraries => [ I<lib1>, I<lib2>, ...] ],
       Linker => I<linker>,
       Options => [ I<opt1>, I<opt2>, ... ],
       Factors => [ I<factor1>, I<factors2>, ... ]

     c_static_library
       Directory => I<directory>,
       Name => I<output-filename>,
       Objects => [ I<obj1>, I<obj2>, ...],
       Archiver => I<archiver>,
       Options => [ I<opt1>, I<opt2>, ... ],
       Factors => [ I<factor1>, I<factors2>, ... ]

     c_compiler
       Program => I<program>,
       Options => [ I<opt1>, I<opt2>, ... ],
       Journal => I<journal>,
       Flag_Map => { 'I' => I<include-flag>, 'D' => I<define-flag>,
     	          'c' => I<source-flag>, 'o' => I<object-flag> },
       Suffix_Rule => sub { my ($name) = @_; ... return $result },
       Scanner => sub { my ($c_file, $args) = @_; ... return @result };

     c_compiler Vendor => I<vendor>, ...

     c_linker
       Program => I<program>,
       Options => [ I<opt1>, I<opt2>, ... ],
       Journal => I<journal>,
       Flag_Map => { 'l' => I<link-flag>, 'L' => I<search-flag>,
     	          'o' => I<output-flag> },
       Bind_Rule => sub { my ($lib, $bind) = @_;
     	               ... return @result },
       Search_Rule => sub { my ($lib, $rule, $bind, @search) = @_;
     	                 ... return @factors };

     c_linker Vendor => I<vendor>, ...

     c_archiver
       Program => I<program>,
       Options => [ I<opt1>, I<opt2>, ... ],
       Journal => I<journal>,
       Flag_Map => { 'r' => I<replace-flag> };

     c_archiver Vendor => I<vendor>, ...

DESCRIPTION
===========

   Spells for compiling and linking C/C++ software are constructed using
c_object, c_executable and c_static_library.  The compiler, linker and
archiver used in the resulting actions are the same compiler, linker and
archiver that were used to build Perl itself, unless otherwise specified.

   Specializations of the general classes of compiler, linker and archiver
can be created using c_compiler, c_linker and c_archiver.

Compiling Objects From C/C++ Source
-----------------------------------

   Use the c_object function to create a spell for compiling an object
file from a C or C++ source file.  The name of the resulting object file
will be derived by removing the .c suffix and replacing it with the suffix
for object files on the current platform.

   Use the c_compiler function to create an object to represent a
specialization of the C/C++ compiler tool class.

c_object
     This function returns a spell for the action to compile a source file
     into an object file.

     The 'Source' argument is required and specifies the name of the source
     file to compile into an object file.

     The optional 'Directory' argument specifies the directory in which the
     object file should be produced.

     The optional 'Includes' argument specifies a list of directories that
     should be used by the compiler to search for header files.

     Preprocessor variables may be specified with the optional 'Defines'
     argument by placing the names of variables to set into the keys of a
     hash, and defining the values as needed.

     The optional 'Compiler' argument specifies that a particular
     specialization of the C/C++ compiler tool be used (instead of the
     default compiler).

     The optional 'Options' argument specifies a list of options with which
     to invoke the compiler for this particular object file.

     The optional 'Factors' argument specifies additional factors to
     associate with the spell created.

c_compiler
     This function returns an object representing a specialization of the
     C/C++ compiler class.  If the 'Vendor' argument is specified, then
     the vendor-specific subclass of the `Conjury::C::Compiler' class
     parse the argument list.  Otherwise, the specialization is applied to
     the base class used for the default compiler.

     The optional 'Program' argument specifies the name of the program to
     invoke the compiler.

     The optional 'Options' argument specifies the list of options with
     which the compiler should be invoked for all object files.

     The optional 'Journal' argument specifies the journal object that
     should be used in creating all spells.

     The optional 'Flag_Map' argument specifies a hash that sets the flag
     character for various standard options to C/C++ compilers for setting
     the include path, the preprocessor definitions, the source file and
     the output file.

     The optional 'Suffix_Rule' argument specifies a subroutine that
     converts the name of a source file into the corresponding object file.

     The optional 'Scanner' argument specifies a subroutine that finds the
     list of files that a source file references with '#include'
     directives.

Linking Executables From Objects
--------------------------------

   Use the c_executable function to create a spell for linking an
executable program from a list of object files.

   Use the c_linker function to create an object to represent a
specialization of the C/C++ linker tool class.

c_executable
     This function returns a spell for the action to link a list of object
     files and libraries into an executable file.

     The optional 'Directory' argument specifies the directory where the
     executable program is to be produced.  If unspecified, the directory
     of the current context is used.

     The 'Name' argument is required and specifies the name of the
     executable program.  Any filename extensions the system requires for
     executable program files will be appended automatically.

     The 'Order' argument is a required list of verb-object pairs
     corresponding to orders for the linker to use in producing the
     executable.  The 'Searches' verb specifies a list of directories to
     add to the library search path; the 'Objects' verb specifies a list of
     object files to link (either the spells that produce them, or the
     names of spells that will produce them); the 'Libraries' verb
     specifies the list of libraries to link.  Order verbs may be
     specified in whatever sequence makes sense to the linker.

     The optional 'Linker' argument specifies that a particular
     specialization of the C/C++ linker tool be used (instead of the
     default linker).

     The optional 'Options' argument specifies a list of options with which
     to invoke the linker for this particular object file.

     The optional 'Factors' argument specifies additional factors to
     associate with the spell created.

c_linker
     This function returns an object representing a specialization of the
     C/C++ linker class.  If the 'Vendor' argument is specified, then the
     vendor-specific subclass of the `Conjury::C::Linker' class parse the
     argument list.  Otherwise, the specialization is applied to the base
     class used for the default linker.

     The optional 'Program' argument specifies the name of the program to
     invoke the linker.

     The optional 'Options' argument specifies the list of options with
     which the linker should be invoked for all product files.

     The optional 'Journal' argument specifies the journal object that
     should be used in creating all spells.

     The optional 'Flag_Map' argument specifies a hash that sets the flag
     character for various standard options to C/C++ linkers for setting
     the search path, the output file and the libraries to link.

     The optional 'Bind_Rule' argument specifies a subroutine that takes a
     library name and a binding specification and returns a list of
     library filenames for which the binding specification applies.
     Typical binding specifications include 'static' and 'dynamic'- and
     the unnamed specification, which typically implies "either dynamic or
     static as required."

     The optional 'Search_Rule' argument specifies a subroutine that takes
     a library name, a binding rule (see above), a binding specification
     (also, see above), and a list of the current directories in the
     library search path (at the current point in the sequence of orders),
     and returns the list of factors which produce the library files.

Creating Static Archives Of Objects
-----------------------------------

   Use the c_static_library function to create a spell for composing a
static library from a list of object files.

   Use the c_archiver function to create an object to represent a
specialization of the C/C++ archiver tool class.

c_static_library
     This function returns a spell for the action to archive a list of
     object files in a static library file.

     The optional 'Directory' argument specifies the directory where the
     static library file is to be produced.  If unspecified, the directory
     of the current context is used.

     The 'Name' argument is required and specifies the name of the library
     file.  Any filename extensions and prefixes the system requires for
     static library files will be added automatically.

     The 'Objects' argument is required and specifies the list of objects
     (and/or spells that produce the objects) to be archived into the
     static library file.

     The optional 'Archiver' argument specifies that a particular
     specialization of the C/C++ archiver tool be used (instead of the
     default archiver).

     The optional 'Options' argument specifies a list of options with which
     to invoke the archiver for this particular object file.

     The optional 'Factors' argument specifies additional factors to
     associate with the spell created.

c_archiver
     This function returns an object representing a specialization of the
     C/C++ archiver class.  If the 'Vendor' argument is specified, then
     the vendor-specific subclass of the `Conjury::C::Archiver' class
     parse the argument list.  Otherwise, the specialization is applied to
     the base class used for the default archiver.

     The optional 'Program' argument specifies the name of the program to
     invoke the archiver.

     The optional 'Options' argument specifies the list of options with
     which the archiver should be invoked for all static library files.

     The optional 'Journal' argument specifies the journal object that
     should be used in creating all spells.

     The optional 'Flag_Map' argument specifies a hash that sets the flag
     character for various standard options to C/C++ archivers, including
     the flag for replacing existing objects with new ones.

SEE ALSO
========

   The introduction to Perl Conjury is in Conjury.  Other
useful documents include `cast' in this node and Conjury/Core.

   The specialization for the GNU tools is documented in
Conjury/C/GNU.

AUTHOR
======

   James Woodyatt <`jhw@wetware.com'>

Perl Conjury with the GNU C/C++ tools
*************************************

NAME
====

   Conjury::C::GNU - Perl Conjury with the GNU C/C++ tools

SYNOPSIS
========

     c_compiler Vendor => 'GNU',
       Language => I<language>,
       No_Scanner => 1,
       Program => I<program>,
       Options => [ I<opt1>, I<opt2>, ... ],
       Journal => I<journal>;

     c_linker Vendor => 'GNU',
       Language => I<language>,
       Program => I<program>,
       Options => [ I<opt1>, I<opt2>, ... ],
       Journal => I<journal>;

DESCRIPTION
===========

   The optional 'Program', 'Options' and 'Journal' arguments to the
GNU-specific specializations of the c_compiler and c_linker functions are
simply passed through unmodified to the base class constructor.

   The optional 'Language' argument specifies the langauge for which the
compiler or linker should be invoked.  The C language is the default if
not otherwise specified.  The value is case-insensitive and may be any one
of the following: 'c', 'c++' or 'objective-c'.

   The optional 'No_Scanner' argument in the c_compiler specialization
specifies that the processing overhead of scanning all the source files
for their dependency trees is unnecessary.  If you are only building from
clean source file hierarchies (with no existing products from previous
runs), then the construction time of large builds may be improved with
this option.

SEE ALSO
========

   More documentation can be found in Conjury, `cast' in
this node, see Conjury/Core, and Conjury/C.

AUTHOR
======

   James Woodyatt <jhw@wetware.com>

Perl Conjury with the Sun Workshop C/C++ tools
**********************************************

NAME
====

   Conjury::C::Sun - Perl Conjury with the Sun Workshop C/C++ tools

SYNOPSIS
========

     c_compiler Vendor => 'Sun',
       Language => I<language>,
       No_Scanner => 1,
       Program => I<program>,
       Options => [ I<opt1>, I<opt2>, ... ],
       Journal => I<journal>;

     c_linker Vendor => 'Sun',
       Language => I<language>,
       Program => I<program>,
       Options => [ I<opt1>, I<opt2>, ... ],
       Journal => I<journal>;

     c_archiver Vendor => 'Sun',
       Language => I<language>,
       Program => I<program>,
       Options => [ I<opt1>, I<opt2>, ... ],
       Journal => I<journal>;

DESCRIPTION
===========

   The optional 'Program', 'Options' and 'Journal' arguments to the
Sun-specific specializations of the c_compiler and c_linker functions are
simply passed through unmodified to the base class constructor.

   The optional 'Language' argument specifies the langauge for which the
compiler or linker should be invoked.  The C language is the default if
not otherwise specified.  The value is case-insensitive and may be either
'c'or 'c++'.

   The optional 'No_Scanner' argument in the c_compiler specialization
specifies that the processing overhead of scanning all the source files
for their dependency trees is unnecessary.  If you are only building from
clean source file hierarchies (with no existing products from previous
runs), then the construction time of large builds may be improved with
this option.

SEE ALSO
========

   More documentation can be found in Conjury, `cast' in
this node, see Conjury/Core, and Conjury/C.

AUTHOR
======

   James Woodyatt <jhw@wetware.com>

the foundation of Perl Conjury
******************************

NAME
====

   Conjury::Core - the foundation of Perl Conjury

SYNOPSIS
========

     use Conjury::Core;

     tie I<HASH>, Conjury::Core::Journal, F<filename>;

     $stage = Conjury::Core::Stage->new ( I<HASH> );
     $stage->make_subdir ( F<filename> );

     $spell = Conjury::Core::Spell->new ( I<HASH> );

     cast_warning ( I<LIST> );
     cast_error ( I<LIST> );

     [$spell =] name_spell ( I<HASH> );

     @spells = fetch_spells ( I<HASH> );

     ($basedir, $subdir) = find_stage ( F<directory> );

     $spell = Conjury::Core::deferral ( I<HASH> );

     $spell = Conjury::Core::filecopy ( I<HASH> );

     $spell = Conjury::Core::dispell ( I<HASH> );

DESCRIPTION
===========

   The `Conjury::Core' module is the foundation of the Perl Conjury
software construction framework.  You need to understand this module
before you design other Perl Conjury modules, especially
application-specific ones referenced in your `Conjury.pl' files.

   In addition to some exported functions, there are four Perl packages in
the `Conjury::Core' namespace: Conjury::Core::Context,
Conjury::Core::Journal, Conjury::Core::Stage and Conjury::Core::Spell.

Conjury::Core::Context
----------------------

   A "context" is an association between a directory within the source file
hierarchy and the spells defined by the Conjury.pl file there.  (The name
of the spell definition file may differ on your platform.  See
Conjury.)

   A Conjury::Core::Context object encapsulates this association.  It
should be treated like a structure with named members.  Most of its
methods are not really for public use.

   The 'Directory' method returns the name of the directory associated
with the context.

   The `$Current_Context' package variable always contains a reference to
the current context object. The `$Top_Context' package variable always
contains a reference to the context at the top of the source file
hierarchy.

Conjury::Core::Journal
----------------------

   A "journal" is a file that contains the persistent data that Perl
Conjury uses to record the signatures of actions as they are performed, so
that they can be skipped on subsequent runs when the signature for
products are known not to have changed.

   It probably should not be implemented as a tied hash, but it is.  It
should be treated like an opaque object.

   Create a journal using the tie builtin and specifying the name of the
file to write.

Conjury::Core::Stage
--------------------

   A "stage" is an association between a directory and a journal object
mapped to a file in that directory with a standard name.  On most
platforms, journal files in a stage are named `.conjury-journal', but some
filesystems have funny conventions so your experience may vary.

   Create a Conjury::Core::Stage object with its new method.  Create
subdirectories within the stage using the `make_subdir' method.

Conjury::Core::Stage->new
     Creates a stage object associated with a directory.  The arguments
     are named in a hash.  All of them are optional.

     Use the optional 'Directory' argument to associate the stage with a
     directory other than the one associated with the current context.

     Use the optional 'Journal' argument to associate the stage explicitly
     with a specific journal object.

$stage->make_subdir(directory)
     Creates a subdirectory within the stage.  The named subdirectory must
     be specified by relative path.  It will be created during the compile
     phase, and its creation is not reversed by the *-undo* option.

Conjury::Core::Spell
--------------------

   A "spell" is an object that encapsulates the action required to perform
a task, typically for constructing or erasing files.  A spell is usually
associated with a list of factors, other spells representing actions that
must be taken first, if the spell is to succeed.

   All spells have a profile which is used in computing the signature of
the spell. Before an action is taken for a spell, the signatures of all
its factors are appended to the profile for the spell, then reduced with
the MD5 cryptographic hash function to become the signature for the spell.

   When a spell creates product files, the names of the files and the
signature of the spell that produced them is journaled to a file.  In this
way, if the signature for a file is found to have changed since it was
last journaled, it is because the spell responsible for creating it has
acquired a new profile, or one of its factors has a new signature.

   If a factor of a spell specifies a file not produced by any spells,
that file is treated as a source file, and its modification time is
appended to the profile of the spell which considers it a factor.  In this
way, changes to the modification time of a source file results in a
cascading change to the signature of every spell that references it in its
tree of factors.

   Use the `Conjury::Core::Spell-'new> subroutine to construct a spell
object.  The named parameters are all optional, but using some of them
implies a requirement for the use of others.  A spell constructed with no
parameters has no action, no profile, i.e. it generates no effect on the
signature of spells that consider it a factor.

   The named parameters of the new method in detail:

Journal => \%journal
     Associates the spell with a journal object.  This is usually not
     necessary when the spell has no product files.  Spells that have
     products should always journal their signatures, but it is not
     required.

Factors => [ `factor1', `factor2', ... ]
     Specifies the list of factors for the spell.  These may be references
     to other spell objects or the names of spells to fetch using the
     fetch_spells function.

Product => filename
Product => [ *filename1*, *filename2*, ... ]
     Specifies the name of the file, or a list of the names of files,
     produced by the action of the spell.  When the spell is created, the
     names of the products are stored internally in a global hash
     available to the fetch_spells function.

Action => SCALAR
Action => [ *PROGRAM*, *ARG1*, *ARG2*, ... ]
Action => CODE
     Specifies the action to take when the spell is invoked.  The first
     and second form result in the scalar (or the list of scalars) to be
     used with the system builtin function.

     The third form is for specifying a closure.  If you use a closure,
     you will be required to specify a profile for the closure.  This is
     because you cannot convert a code block into a string very easily in
     Perl.

     When a spell is invoked, its action is executed in the context in
     which it was created.  Actions return boolean true on failure.

Profile => SCALAR
Profile => CODE
     Specifies the profile for an action.  The first form is the simple
     case, i.e. the string is used as the profile for an action closure.
     You should provide a profile that uniquely describes the action to
     take, including the name of the action function and the values of any
     parameters used in the construction of the closure.

     The second form is the more complicated case, i.e. the profile is a
     closure itself.  Closure profiles require no arguments, and they are
     called during the invocation phase immediately before the factors are
     invoked.  The explanation for why you would want to use this form is
     tedious, esoteric and best not presented during dinner.  Hint: C
     language dependency scanning is one case.

Exported Functions
------------------

   The name_spell, fetch_spells and find_stage functions should probably
be moved into an appropriate Conjury::Core::Xxxxx namespace.  If they stay
where they are, then the contents of `@EXPORT' should be moved to
`@EXPORT_OK'. It remains unclear what is the right thing to do here- but it
will be.  It will.

cast_warning
     Prints a warning message to the standard output.  Use this function
     like the print builtin function.  A prefix is inserted to identify
     the message as a warning from the *cast* utility, and a newline is
     appended.

cast_error
     Prints an error message to the standard output and dies.  Use this
     function like the die builtin function.  A prefix is inserted to
     identify the message as an error from the *cast* utility, and a
     newline is appended.

name_spell
     name_spell    (Spell => *spell*,     Context => context,     Name =>
     [ *name1*, *name2*, ... ], # array or scalar is okay     Default => 1)

     Assigns names in a context to a spell.  The 'Spell' argument is the
     only required argument.  The others are all optional.

     If no context is specified, then the current context is assumed.

     If the 'Default' argument is specified, or the 'Name' argument is
     unspecified or specifies an empty list, then the spell is explicitly
     assigned to the list of unnamed spells in the context.  These spells
     are typically the 'default' spells that are invoked when no names are
     given to the *cast* utility from the command line.

fetch_spells
     fetch_spells(Name => name, Context => context, Require => 1)

     Returns a list containing references to all the spell objects with the
     name in the context.

     If the name is not specified, then the list will contain references
     to all the unnamed spell objects. You can use a list of names to
     fetch all the spell objects for the whole list at once.  A spell will
     be fetched if its product matches the specified name, or the spell
     was explicitly assigned the name with the name_spell function.

     If the context is not specified, the current context is assumed.

     Spells for products created in other contexts can be fetched using
     either an absolute or a relative pathname.  Be careful that the path
     you specify contains no symbolic links or references to parent
     directory pointers, i.e. the '..'  directory, as these may not be
     resolved properly.

     If the 'Require' argument is not set, then an empty list is a
     permissible result.

find_stage directory
     Finds the stage object for the specified directory.

     In array context, this returns a 2-tuple of the base directory for
     the stage object and the relative path from the base to specified
     directory.

deferral
     $spell = deferral(Directory => [ `dir1', `dir2', ...], Name => name,
     If_Present => 1);

     Creates a spell object that defers its actions to the named spells in
     contexts associated with other directories.  The 'Name' argument is
     used with the fetch_spells function to find all the named spells in
     each directory.

     There must be a spells definition file in each of the named
     directories, unless the 'If_Present' argument is defined.

     The 'Name' argument may specify a single name or a list of names.  If
     it is a list of names, then all the names are passed to the
     fetch_spells function for each directory at a time.

filecopy
     $spell = filecopy    (Journal => *journal*,     Factors => [
     *spell1*, *spell2*, ... ],     Directory => directory,     File => [
     `file1', `file2', ... ],  # array or scalar is okay     Permission =>
     *permission*,     Owner => [ user, group ];

     Creates a spell object that copies a file or a list of files to a
     directory.

     The 'File' argument is required and must specify a filename or a list
     of filenames.  The 'Directory' argument is required and must specify
     the destination directory for the copy action.

     Use the optional 'Factors' argument to add spells explicitly to the
     list of factors.  If there are already spells that produce the files
     in the 'File' list, they need not be listed here.  They will be
     fetched and automatically appended to the factors list.

     Use the optional 'Journal' argument to specify a journal object for
     the spell.

     Use the optional 'Permission' argument to specify that the chmod
     builtin should be used to set the access permissions associated with
     the files after they have been copied to the destination.  The syntax
     requirements for chmod apply.

     Use the optional 'Owner' argument to specify that the chown builtin
     should be used to set the user and group ownership after the files
     have been copied to the destination.  The syntax requirements for
     chown apply.

dispell
     $spell = dispell    (Journal => *journal*,     Factors => [ *spell1*,
     *spell2*, ... ],     Directory => [ `directory1', `directory2', ...]
     # array or scalar okay     File => [ `file1', `file2', ... ],  #
     array or scalar okay     Require => 1;

     Creates a spell object that erases files or lists of files in a
     directory.

     One or both of the arguments, 'File' and 'Directory', are required.
     The 'File' argument specifies a filename or a list of filenames to
     unlink with the 'unlink' builtin function.  The 'Directory' argument
     specifies a directory or a list of directories to remove with the
     'rmdir' builtin.

     The 'Require' argument is optional.  If it is set, then the files and
     directories to be unlinked or removed are required to exist when the
     action is executed to erase them.

     Use the optional 'Factors' argument to add spells explicitly to the
     list of factors.

     Use the optional 'Journal' argument to specify a journal object for
     the spell.

AUTHOR
======

   James Woodyatt <`jhw@wetware.com'>

function prototype checking in Conjury
**************************************

NAME
====

   Conjury::Core::Prototype - function prototype checking in Conjury

SYNOPSIS
========

     require Conjury::Core::Prototype;
     use Carp qw/&croak/;

     $prototype = Conjury::Core::Prototype->new;

     $prototype->required_arg
       (foo_arg1 => sub {
     	     my ($x, $y) = (shift, undef);
     		 $y = 'not a HASH reference' unless (ref $x eq 'HASH');
     		 return $y;
     	 });

     $prototype->optional_arg
     	 foo_arg2 => sub {
     	     my ($x, $y) = (shift, undef);
     		 $y = 'not a CODE reference' unless (ref $x eq 'CODE');
     		 return $y;
     	 });

     sub foo($%) {
     	  my ($this, %arg) = @_;
     	  my $error = $prototype->validate(\%arg);
     	  croak __PACKAGE__, "::foo-- $error" if $error;

     # use $arg{foo_arg1} with confidence that it exists and its value
     # is a HASH reference, and that $arg{foo_arg2} either does not exist,
     # or it exists and its value is a CODE reference.
       }

DESCRIPTION
===========

   The `Conjury::Core::Prototype' module is a general purpose function
prototype verifier, included in the Conjury distribution as a convenience.

   Use the `Conjury::Core::Prototype-'new> method to construct an instance
of the prototype verifier for a particular function.

   Use the `required_arg' method to add a required argument to the function
prototype.  Use the `optional_arg' method to add an optional argument to
the function prototype.  Both methods require two parameters, the name of
the argument, and a reference to a subroutine that validates the argument
and returns a descriptive message if the argument violates the prototype.

   When the validate method is called on the prototype (with a reference to
a hash containing the function arguments), each argument is passed to the
parameter verifier function that was associated with the parameter name
when the prototype was constructed.  If none of the verifiers return a
value then the argument list fits the prototype and the validate method
returns undefined.  Otherwise, the validate method returns an error code
suitable for use in a call to croak.

AUTHOR
======

   James Woodyatt <`jhw@wetware.com'>

Perl interface to Continuus CM
******************************

NAME
====

     Continuus - Perl interface to Continuus CM

SYNOPSIS
========

     use Continuus;

     Check out a file:

     use Continuus;

     $ccm = new Continuus;

     $ccm->start(database => '/proj/Continuus4/rig',
                 host => 'stoxserv01');

     $ccm->checkOut(file => 'main.c',
     		 version => '2');

     $ccm->stop();

DESCRIPTION
===========

     The Continuus perl module is a interface to the most common Continuus functions.

CHANGE HISTORY
==============

     0.1    Created.

METHODS
=======

new:
          The new method creates a new Continuus object.

start:
          The start method starts a new Continuus session.

          Parameters:
           database: Database to open.

           host: Hostname to start the engine on.

          iniFile: Ini file to read.

          Example:
           $ccm->start(database => "/proj/Continuus0/rig/", host => "stoccm01");

command:
          The command method acts as a interface to all other Continuus functions
          not implemented in the Continuus module.

          Parameters:
           command: The command to be executed by Continuus

          Example:
          $ccm->command('status');

stop:
          The stop command quits the current Continuus session.

          Parameters:
           None.

query:
          The query command is a interface to the Continuus query command.

          Parameters:
           query: The query string
           flags: Flags to pass to Continuus.
           Format: Formatting options.

          Example:
           $ccm->query(query => "status='released'", flags => "-u", format => "%objectname");

checkOut:
          Checks out a file.

          Parameters:
           file: The file to check out.
           version: The version to set on the new file.

          Example:
           $ccm->checkOut(file => "main.c", version => "1.1");

checkIn:
          Checks in a file.

          Parameters:
           file: The file to check out.
           comment: The comment to set on the new file.

          Example:
           $ccm->checkIn(file => "main.c", comment => "Created");

reconfigure:
          Reconfigure command

          Parameters:
           project: The project to reconfigure.
           parameters: Other parameters to pass to the reconfigure command.

          Example:
           $ccm->checkOut(file => "main.c", version => "1.1");

debugOn:
          Sets the debugging information on.

debugOff:
          Sets the debugging information off.

AUTHOR
======

   Henrik Jönsson henrik7205@hotmail.com

Perl extension for X10 'ActiveHome' Controller
**********************************************

NAME
====

   ControlX10::CM11 - Perl extension for X10 'ActiveHome' Controller

SYNOPSIS
========

     use ControlX10::CM11;

     # $serial_port is an object created using Win32::SerialPort
     #     or Device::SerialPort depending on OS
     # my $serial_port = setup_serial_port('COM10', 4800);

     $data = &ControlX10::CM11::receive_buffer($serial_port);
     $data = &ControlX10::CM11::read($serial_port, $no_block);
     $percent = &ControlX10::CM11::dim_level_decode('GE'); # 40%

     &ControlX10::CM11::send($serial_port, 'A1'); # Address device A1
     &ControlX10::CM11::send($serial_port, 'AJ'); # Turn device ON
       # House Code 'A' present in both send() calls

     &ControlX10::CM11::send($serial_port, 'B'.'ALL_OFF');
       # Turns All lights on house code B off

DESCRIPTION
===========

   The CM11A is a bi-directional X10 controller that connects to a serial
port and transmits commands via AC power line to X10 devices. This module
translates human-readable commands (eg. 'A2', 'AJ') into the Interface
Communication Protocol accepted by the CM11A.

send command
     This transmits a two-byte message containing dim and house information
     and either an address or a function. Checksum and acknowledge
     handshaking is automatic. The command accepts a string parameter. The
     first character in the string must be a *House Code* in the range
     [A..P] and the rest of the string determines the type of message.
     Intervening whitespace is not currently permitted between the *House
     Code* and the Operation. This may change in the future.

          STRING  ALTERNATE_STRING    FUNCTION
           1..9               Unit Address
           A..G               Unit Address
             J        ON      Turn Unit On
             K        OFF     Turn Unit Off
             L        BRIGHT      Brighten Last Light Programmed 5%
             M        DIM     Dim Last Light Programmed 5%
             O        ALL_ON      All Units On
             P        ALL_OFF     All Units Off

     There are also functions without "shortcut" letter commands:

          ALL_LIGHTS_OFF  EXTENDED_CODE   EXTENDED_DATA
          HAIL_REQUEST    HAIL_ACK    PRESET_DIM1
          PRESET_DIM2 STATUS_ON   STATUS_OFF
          STATUS

     Dim and Bright functions can also take a signed value in the range
     [-95,-90,...,-10,-5,+5,+10,...,+90,+95].

          ControlX10::CM11::send($serial_port,'A1'); # Address device A1
          ControlX10::CM11::send($serial_port,'AJ'); # Turn device ON
          ControlX10::CM11::send($serial_port,'A-25'); # Dim to 25%

send extended function
     Starting in version 2.04, extended commands may be sent to devices
     that support the enhanced X10 protocol. If you have one of the newer
     (more expensive) LM14A/PLM21 2 way X10 pro lamp modules, you can set
     it directly to a specific brightness level using a Preset Dim
     extended code.

     The 64 extended X10 Preset Dim codes are commanded by appending `&##'
     to the unit address where `##' is a number between 1 and 63.

          ControlX10::CM11::send($serial_port,'A5&P16'); # Dim A5 to 25%

     A partial translation list for the most important levels:

          &P##	 %		&P##	 %		&P##	 %
            0	  0		 13	 20		 44	 70
            1	  2		 16	 25		 47	 75
            2	  4		 19	 30		 50	 80
            3	  5		 25	 40		 57	 90
            6	 10		 31	 50		 61	 95
            9	 15		 38	 60		 63	100

     There is another set of Preset Dim commands that are used by some
     modules (e.g. the RCS TX15 thermostat). These 32 non-extended Preset
     Dim codes can be coded directly, using the following table:

          0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15   PRESET_DIM1
          M  N  O  P  C  D  A  B  E  F  G  H  K  L  I  J

          16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31  PRESET_DIM2
          M  N  O  P  C  D  A  B  E  F  G  H  K  L  I  J

     This usage, and the responses assigned to each command, are device
     specific.  For example, the following commands enable preset value 18:

          ControlX10::CM11::send($serial_port,'M4');           # Address thermostat
          ControlX10::CM11::send($serial_port,'OPRESET_DIM2'); # Select preset 18

     Starting in version 2.07, incoming extended data is also processed.
     The first character will be the *House Code* in the range [A..P].
     The next character will be *Z*, indicating extended data.  The
     remaining data will be the extended data.

read
     This checks for an incoming transmission. It will return "" for no
     input.  It also tests for a received a "power fail" message (0xa5).
     If it detects one, it automatically sends the command/data to reset
     the CM11 clock. If the `$no_block' parameter is FALSE (0, "", or
     undef), the read will retry for up to a second at 50 millisecond
     intervals. With `$no_block' TRUE, the read checks one time for
     available data.

          $data = &ControlX10::CM11::read($serial_port, $no_block);

receive_buffer
     This command handles the upload response to an "Interface Poll Signal"
     message (0x5a) read from the CM11. The module sends "ready" (0xc3) and
     receives up to 10 bytes. The first two bytes are size and description
     of the remaining bytes. These are used to decode the data bytes, but
     are not returned by the receive_buffer function. Each of the data
     bytes is decoded as if it was a send command from an external CM11 or
     equivalent external source (such as an RF keypad).

          $data = &ControlX10::CM11::receive_buffer($serial_port);
              # $data eq "A2AK" after an external device turned off A2

     Multiple house and unit addresses can appear in a single buffer.

          if ($data eq "B1BKA2AJ") {
              print "B1 off, A2 on\n";
          }

dim_level_decode
     When the external command includes dim/bright information in addition
     to the address and function, the dim_level_decode function converts
     that data byte (as processed by the receive_buffer command) into
     percent.

          $data = &ControlX10::CM11::receive_buffer($serial_port);
              # $data eq "A2AMGE" after an external device dimmed A2 to 40%
          $percent = &ControlX10::CM11::dim_level_decode("GE");
              # $percent == 40

     A more complex $data input is possible.

          if ($data eq "B1B3B5B7B9BLLE") {
              print "House B Inputs 1,3,5,7,9 Brightened to 85%\n";
          }

     The conversion between text_data and percent makes more sense to the
     code than to humans. The following table gives representative values.
     Others may be received from a CM11 and will be properly decoded.

          Percent Text        Percent Text
              0    M7        50    AA
              5    ED        55    I6
             10    EC        60    NF
             15    C7        65    N2
             20    KD        70    F6
             25    K4        75    DB
             30    O7        80    D2
             35    OA        85    LE
             40    G6        90    PB
             45    AF        95    P8

   The *send_cm11*, *receive_cm11*, *read_cm11*, and *dim_decode_cm11*
functions are exported by default starting with Version 2.09.  They are
identical to the "fully-qualified" names and accept the same parameters.
The *export on request* tag `:FUNC' is maintained for compatibility (but
deprecated).

     use ControlX10::CM11;
     send_cm11($serial_port, 'A1');            # send() - address
     send_cm11($serial_port, 'AJ');            # send() - function
     $data = receive_cm11($serial_port);           # receive_buffer()
     $data = read_cm11($serial_port, $no_block);       # read()
     $percent = dim_decode_cm11('GE');         # dim_level_decode()

AUTHORS
=======

   Bruce Winter  bruce@misterhouse.net  http://misterhouse.net

   CPAN packaging by Bill Birthisel wcbirthisel@alum.mit.edu
http://members.aol.com/bbirthisel

MAILING LISTS
-------------

   General information about the mailing lists is at:

     http://lists.sourceforge.net/mailman/listinfo/misterhouse-users
     http://lists.sourceforge.net/mailman/listinfo/misterhouse-announce

   To post to this list, send your email to:

     misterhouse-users@lists.sourceforge.net

   If you ever want to unsubscribe or change your options (eg, switch to
or from digest mode, change your password, etc.), visit your subscription
page at:

     http://lists.sourceforge.net/mailman/options/misterhouse-users/$user_id

SEE ALSO
========

   mh can be download from http://misterhouse.net

   Win32::SerialPort and Device::SerialPort from CPAN

   CM11A Protocol documentation available at http://www.x10.com

   perl(1).

COPYRIGHT
=========

   Copyright (C) 2000 Bruce Winter. All rights reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself. 30 January 2000.

Perl extension for 'FireCracker' RF Transmitter
***********************************************

NAME
====

   ControlX10::CM17 - Perl extension for 'FireCracker' RF Transmitter

SYNOPSIS
========

     use ControlX10::CM17;

     # $serial_port is an object created using Win32::SerialPort
     #     or Device::SerialPort depending on OS
     # my $serial_port = setup_serial_port('COM10', 4800);

     &ControlX10::CM17::send($serial_port, 'A1J');
       # Turns device A1 On
     &ControlX10::CM17::send($serial_port, 'A1K');
       # Turns device A1 Off
     &ControlX10::CM17::send($serial_port, 'BO');
       # Turns All lights on house code B off

DESCRIPTION
===========

   The FireCracker (CM17A) is a send-only X10 controller that connects to
a serial port and transmits commands via RF to X10 transceivers.

   The FireCracker derives its power supply from either the RTS or DTR
signals from the serial port. At least one of these signals must be high
at all times to ensure that power is not lost from the FireCracker. The
signals are pulsed to transmit a bit (DTR for '1' and RTS for '0'). The
normal rx/tx read/write lines are not used by the device - but are passed
through to allow another serial device to be connected (as long as it does
not require hardware handshaking).

   A 40-bit command packet consists of a constant 16 bit header, a constant
8 bit footer, and 16 data bits. The data is subdivided into a 5 bit
address *$house* code (A-P) and an 11 bit *$operation*. There are "ON"
commands for 16 units per *$house* code (1J, 2J...FJ, GJ) and similar "OFF"
commands (1K, 2K...FK, GK). A send decodes a parameter string that
combines *$house$operation* into a single instruction. In addition to
*$operation* commands that act on individual units, there are some that
apply to the entire *$house* code or to previous commands.

     $operation	FUNCTION
         L		Brighten Last Light Programmed 14%
         M		Dim Last Light Programmed 14%
         N		All Lights Off
         O		All Lights On
         P		All Units Off

   Starting with Version 0.6, a series of Brighten or Dim Commands may be
combined into a single *$operation* by specifying a signed amount of
change desired after the unit code. An "ON" command will be sent to select
the unit followed by at least one Brighten/Dim. The value will round to
the next larger magnitude if not a multiple of 14%.

   &ControlX10::CM17::send($serial_port, 'A3-10');       # outputs
'A3J','AM' - at least one dim

     &ControlX10::CM17::send($serial_port, 'A3-42');
         # outputs 'A3J','AM','AM','AM' - even multiple of 14

     &ControlX10::CM17::send($serial_port, 'AF-45');
         # outputs 'AFJ','AL','AL','AL','AL' - round up if remainer

EXPORTS
=======

   The *send_cm17* method is exported by default. It is identical to
`&ControlX10::CM17::send()', and accepts the same parameters.

     use ControlX10::CM17;
     send_cm17($serial_port, 'A1J');

AUTHORS
=======

   Bruce Winter  bruce@misterhouse.net  http://misterhouse.net

   CPAN packaging by Bill Birthisel wcbirthisel@alum.mit.edu
http://members.aol.com/bbirthisel

MAILING LISTS
-------------

   General information about the mailing lists is at:

     http://lists.sourceforge.net/mailman/listinfo/misterhouse-users
     http://lists.sourceforge.net/mailman/listinfo/misterhouse-announce

   To post to this list, send your email to:

     misterhouse-users@lists.sourceforge.net

   If you ever want to unsubscribe or change your options (eg, switch to
or from digest mode, change your password, etc.), visit your subscription
page at:

     http://lists.sourceforge.net/mailman/options/misterhouse-users/$user_id

SEE ALSO
========

   mh can be download from http://misterhouse.net

   You can subscribe to the mailing list at
http://www.onelist.com/subscribe.cgi/misterhouse

   You can view the mailing list archive at
http://www.onelist.com/archives.cgi/misterhouse

   perl(1).

   Win32::SerialPort and Device::SerialPort

COPYRIGHT
=========

   Copyright (C) 2000 Bruce Winter. All rights reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself. 30 January 2000.

ASN.1 Encode/Decode library
***************************

NAME
====

     Convert::ASN1 - ASN.1 Encode/Decode library

SYNOPSYS
========

     use Convert::ASN1;

     $asn = Convert::ASN1->new;
     $asn->prepare(q<

     [APPLICATION 7] SEQUENCE {
       int INTEGER,
       str OCTET STRING
     }

     >);

     $pdu = $asn->encode( int => 7, str => "string");

     $out = $asn->decode($pdu);
     print $out->{int}," ",$out->{str},"\n";

     use Convert::ASN1 qw(:io);

     $peer   = asn_recv($sock,$buffer,0);
     $nbytes = asn_read($fh, $buffer);
     $nbytes = asn_send($sock, $buffer, $peer);
     $nbytes = asn_send($sock, $buffer);
     $nbytes = asn_write($fh, $buffer);
     $buffer = asn_get($fh);
     $yes    = asn_ready($fh)

DESCRIPTION
===========

   Convert::ASN1 encodes and decodes ASN.1 data structures using BER/DER
rules.

METHODS
=======

new
---

   Contructor, creates a new object.

error
-----

   Returns the last error.

configure ( OPTIONS )
---------------------

   Configure options to control how Convert::ASN1 will perform various
tasks.  Options are passed as name-value pairs.

encode
     Reference to a hash which contains various encode options.

decode
     Reference to a hash which contains various decode options.

encoding
     One of 'ber', 'der', 'per'. *Currently not used*

   Encode options

real
     Which encoding to use for real's. One of 'binary', 'nr1', 'nr2', 'nr3'

time
     This controls how UTCTime and GeneralizedTime elements are encoded.
     The default is withzone.

    utctime
          The value passed will be encoded without a zone, ie a UTC value.

    withzone
          The value will be encoded with a zone. By default it will be
          encoded using the local time offset. The offset may be set using
          the timezone configure option.

    raw
          The value passed should already be in the correct format and
          will be copied into the PDU as-is.

timezone
     By default UTCTime and GeneralizedTime will be encoded using the local
     time offset from UTC. This will over-ride that. It is an offset from
     UTC in seconds.  This option can be overriden by passing a reference
     to a list of two values as the time value. The list should contain
     the time value and the offset from UTC in seconds.

   Decode options

time
     This controls how a UTCTime or a GeneralizedTime element will be
     decoded. The default is utctime.

    utctime
          The value returned will be a time value as returned by the time
          function.

    withzone
          The value returned will be a reference to an array of two
          values. The first is the same as with utctime, the second is the
          timezone offset, in seconds, that was used in the encoding.

    raw
          The value returned will be the raw encoding as extracted from
          the PDU.

prepare ( ASN )
---------------

   Compile the given ASN.1 descripton. The syntax used is very close to
ASN.1, but has a few differnces. If the ASN decribes only one macro then
encode/decode can be called on this object. If ASN describes more than one
ASN.1 macro then find must be called.

find ( MACRO )
--------------

   Find a macro froma prepared ASN.1 description. Returns an object which
can be used for encode/decode.

encode ( VARIABLES )
--------------------

   Encode a PDU. Top-level variable are passed as name-value pairs, or as
a reference to a hash containing them. Returns the encoded PDU, or undef
on error.

decode ( PDU )
--------------

   Decode the PDU, returns a reference to a hash containg the values for
the PDU. Returns undef if there was an error.

EXPORTS
=======

   As well as providing an object interface for encoding/decoding PDUs
Convert::ASN1 also provides the follow functions.

IO Functions
------------

asn_recv SOCK, BUFFER, FLAGS
     Will read a single element from the socket SOCK into BUFFER.  FLAGS
     may be MSG_PEEK as exported by Socket. Returns the address of the
     sender, or undef if there was an error. Some systems do not support
     the return of the peer address when the socket is a connected socket,
     in these cases the empty string will be returned. This is the same
     behaviour as the recv function in perl itself.

     It is reccomended that if the socket is of type SOCK_DGRAM then recv
     be called directly instead of calling asn_recv.

asn_read FH, BUFFER, OFFSET
asn_read FH, BUFFER
     Will read a single element from the filehandle FH into BUFFER.
     Returns the number of bytes read if a complete element was read, -1
     if an incomplete element was read or undef if there was an error. If
     OFFSET is specified then it is assumed that BUFFER already contains
     an incomplete element and new data will be appended starting at
     OFFSET.

     If FH is a socket the asn_recv is used to read the element, so the
     same restiction applies if FH is a socket of type SOCK_DGRAM.

asn_send SOCK, BUFFER, FLAGS, TO
asn_send SOCK, BUFFER, FLAGS
     Identical to calling send, see Perlfunc (perl.info),

asn_write FH, BUFFER
     Identical to calling syswrite with 2 arguments, see Perlfunc (perl.info),

asn_get FH
     asn_get provides buffered IO. Because it needs a buffer FH must be a
     GLOB or a reference to a GLOB. asn_get will use two entries in the
     hash element of the GLOB to use as it's buffer

          asn_buffer - input buffer
          asn_need   - number of bytes needed for the next element, if known

     Returns an element or undef if there was an error.

asn_ready FH
     asn_ready works with asn_get. It will return true if asn_get has
     already read enough data into the buffer to return a complete element.

Encode/Decode Functions
-----------------------

asn_tag
asn_decode_tag
asn_encode_tag
asn_decode_length
asn_encode_length
Constants
---------

ASN_BIT_STR
ASN_BOOLEAN
ASN_ENUMERATED
ASN_GENERAL_TIME

ASN_IA5_STR
ASN_INTEGER
ASN_NULL
ASN_OBJECT_ID
ASN_OCTET_STR
ASN_PRINT_STR
ASN_REAL
ASN_SEQUENCE
ASN_SET
ASN_UTC_TIME
ASN_APPLICATION
ASN_CONTEXT
ASN_PRIVATE
ASN_UNIVERSAL
ASN_PRIMITIVE
ASN_CONSTRUCTOR
ASN_LONG_LEN
ASN_EXTENSION_ID
ASN_BIT
Debug Functions
---------------

asn_dump
asn_hexdump
EXPORT TAGS
===========

:all
     All exported functions

:const
     ASN_BOOLEAN,     ASN_INTEGER,      ASN_BIT_STR,      ASN_OCTET_STR,
     ASN_NULL,        ASN_OBJECT_ID,    ASN_REAL,         ASN_ENUMERATED,
     ASN_SEQUENCE,    ASN_SET,          ASN_PRINT_STR,    ASN_IA5_STR,
     ASN_UTC_TIME,    ASN_GENERAL_TIME, ASN_UNIVERSAL,   ASN_APPLICATION,
     ASN_CONTEXT,      ASN_PRIVATE, ASN_PRIMITIVE,   ASN_CONSTRUCTOR,
     ASN_LONG_LEN,     ASN_EXTENSION_ID, ASN_BIT

:debug
     asn_dump, asn_dumphex

:io
     asn_recv, asn_send, asn_read, asn_write, asn_get, asn_ready

:tag
     asn_tag, asn_decode_tag, asn_encode_tag, asn_decode_length,
     asn_encode_length

MAPPING ASN.1 TO PERL
=====================

   Every element in the ASN.1 definition has a name, in perl a hash is used
with these names as an index and the element value as the hash value.

     # ASN.1
     int INTEGER,
     str OCTET STRING

     # Perl
     { int => 5, str => "text" }

   In the case of a SEQUENCE, SET or CHOICE then the value in the
namespace will be a hash reference which will be the namespce for the
elements with that element.

     # ASN.1
     int INTEGER,
     seq SEQUENCE {
       str OCTET STRING,
       bool BOOLEAN
     }

     # Perl
     { int => 5, seq => { str => "text", bool => 1}}

   If the element is a SEQUENCE OF, or SET OF, then the value in the
namespace will be an array reference. The elements in the array will be of
the type expected by the type following the OF. For example with "SEQUENCE
OF STRING" the array would contain strings. With "SEQUENCE OF SEQUENCE {
... }" the array will contain hash references which will be used as
namespaces

     # ASN.1
     int INTEGER,
     str SEQUENCE OF OCTET STRING

     # Perl
     { int => 5, str => [ "text1", "text2"]}

     # ASN.1
     int INTEGER,
     str SEQUENCE OF SEQUENCE {
       type OCTET STRING,
       value INTEGER
     }

     # Perl
     { int => 5, str => [
       { type => "abc", value => 4 },
       { type => "def", value => -1 },
     ]}

Exceptions
----------

   There are some exceptions where Convert::ASN1 does not require an
element to be named.  These are SEQUENCE {...}, SET {...} and CHOICE. In
each case if the element is not given a name then the elements inside the
{...} will share the same namespace as the elements outside of the {...}.

TODO
====

   * Decoding of a SET.

   * Indefinite length encoding

   * XS implementation.

   * More documentation.

   * More tests.

AUTHOR
======

   Graham Barr <gbarr@pobox.xom>

COPYRIGHT
=========

   Copyright (c) 2000 Graham Barr <gbarr@pobox.com>. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

ASN.1 Basic Encoding Rules
**************************

NAME
====

   Convert::BER - ASN.1 Basic Encoding Rules

SYNOPSIS
========

     use Convert::BER;

     $ber = new Convert::BER;

     $ber->encode(
     	INTEGER => 1,
     	SEQUENCE => [
             BOOLEAN => 0,
     	    STRING => "Hello",
     	],
         REAL => 3.7,
     );

     $ber->decode(
     	INTEGER => \$i,
     	SEQUENCE => [
             BOOLEAN => \$b,
     	    STRING => \$s,
     	],
         REAL => \$r,
     );

DESCRIPTION
===========

   Convert::BER provides an OO interface to encoding and decoding data
using the ASN.1 Basic Encoding Rules (BER), a platform independent way of
encoding structured binary data together with the structure.

METHODS
=======

new
new ( BUFFER )
new ( opList )
     new creates a new Convert::BER object.

encode ( opList )
     Encode data in *opList* appending to the data in the buffer.

decode ( opList )
     Decode the data in the buffer as described by *opList*, starting
     where the last decode finished or position set by pos.

buffer ( [ BUFFER ] )
     Return the buffer contents. If *BUFFER* is specified set the buffer
     contents and reset pos to zero.

pos ( [ POS ] )
     Without any arguments pos returns the offset where the last decode
     finished, or the last offset set by pos. If *POS* is specified then
     *POS* will be where the next decode starts.

tag ( )
     Returns the tag at the current position in the buffer.

length ( )
     Returns the length of the buffer.

error ( )
     Returns the error message associated with the last method, if any.
     This value is not automatically reset. If encode or decode returns
     undef, check this.

dump ( [ FH ] )
     Dump the buffer to the filehandle FH, or STDERR if not specified. The
     output contains the hex dump of each element, and an ASN.1-like text
     representation of that element.

hexdump  ( [ FH ] )
     Dump the buffer to the filehandle FH, or STDERR if not specified. The
     output is hex with the possibly-printable text alongside.

IO METHODS
==========

read ( IO )
write ( IO )
recv ( SOCK )
send ( SOCK [, ADDR ] )
OPLIST
======

   An *opList* is a list of operator-value pairs. An operator can be any
of those defined below, or any defined by sub-classing Convert::BER, which
will probably be derived from the primitives given here.

   The values depend on whether BER is being encoded or decoded:

Encoding
     If the value is a scalar, just encode it. If the value is a reference
     to a list, then encode each item in the list in turn. If the value is
     a code reference, then execute the code. If the returned value is a
     scalar, encode that value. If the returned value is a reference to a
     list, encode each item in the list in turn.

Decoding
     If the value is a reference to a scalar, decode the value into the
     scalar. If the value is a reference to a list, then decode all the
     items of this type into the list. Note that there must be at least one
     item to decode, otherwise the decode will fail. If the value is a
     code reference, then execute the code and decode the value into the
     reference returned from the evaluated code.

PRIMITIVE OPERATORS
===================

   These operators encode and decode the basic primitive types defined by
BER.

BOOLEAN
-------

   A BOOLEAN value is either true or false.

Encoding
     The value is tested for boolean truth, and encoded appropriately.

          # Encode a TRUE value
          $ber->encode(
              BOOLEAN => 1,
          ) or die;

Decoding
     The decoded values will be either 1 or 0.

          # Decode a boolean value into $bval
          $ber->decode(
              BOOLEAN => \$bval,
          ) or die;

INTEGER
-------

   An INTEGER value is either a positive whole number, or a negative whole
number, or zero. Numbers can either be native perl integers, or values of
the Math::BigInt class.

Encoding
     The value is the integer value to be encoded.

          $ber->encode(
              INTEGER => -123456,
          ) or die;

Decoding
     The value will be the decoded integer value.

          $ber->decode(
              INTEGER => \$ival,
          ) or die;

STRING
------

   This is an OCTET STRING, which is an arbitrarily long binary value.

Encoding
     The value contains the binary value to be encoded.

          $ber->encode(
              STRING => "\xC0First character is hex C0",
          ) or die;

Decoding
     The value will be the binary bytes.

          $ber->decode(
              STRING => \$sval,
          ) or die;

NULL
----

   There is no value for NULL. You often use NULL in ASN.1 when you want
to denote that something else is absent rather than just not encoding the
'something else'.

Encoding
     The values are ignored, but must be present.

          $ber->encode(
              NULL => undef,
          ) or die;

Decoding
     Dummy values are stored in the returned values, as though they were
     present in the encoding.

          $ber->decode(
              NULL => \$nval,
          ) or die;

OBJECT_ID
---------

   An OBJECT_ID value is an OBJECT IDENTIFIER (also called an OID). This
is a hierarchically structured value that is used in protocols to uniquely
identify something. For example, SNMP (the Simple Network Management
Protocol) uses OIDs to denote the information being requested, and LDAP
(the Lightweight Directory Access Protocol, RFC 2251) uses OIDs to denote
each attribute in a directory entry.

   Each level of the OID hierarchy is either zero or a positive integer.

Encoding
     The value should be a dotted-decimal representation of the OID.

          $ber->encode(
              OBJECT_ID => '2.5.4.0', # LDAP objectClass
          ) or die;

Decoding
     The value will be the dotted-decimal representation of the OID.

          $ber->decode(
              OBJECT_ID => \$oval,
          ) or die;

ENUM
----

   The ENUMERATED type is effectively the same as the INTEGER type. It
exists so that friendly names can be assigned to certain integer values.
To be useful, you should sub-class this operator.

BIT_STRING
----------

   The BIT STRING type is an arbitrarily long string of bits - 0's and 1's.

Encoding
     The value is a string of arbitrary 0 and 1 characters. As these are
     packed into 8-bit octets when encoding and there may not be a
     multiple of 8 bits to be encoded, trailing padding bits are added in
     the encoding.

          $ber->encode(
              BIT_STRING => '0011',
          ) or die;

Decoding
     The value will be a string of 0 and 1 characters. The string will
     have the same number of bits as were encoded (the padding bits are
     ignored.)

          $ber->decode(
              BIT_STRING => \$bval,
          ) or die;

BIT_STRING8
-----------

   This is a variation of the BIT_STRING operator, which is optimized for
writing bit strings which are multiples of 8-bits in length. You can use
the BIT_STRING operator to decode BER encoded with the BIT_STRING8
operator (and vice-versa.)

Encoding
     The value should be the packed bits to encode, not a string of 0 and
     1 characters.

          $ber->encode(
              BIT_STRING8 => pack('B8', '10110101'),
          ) or die;

Decoding
     The value will be the decoded packed bits.

          $ber->decode(
              BIT_STRING8 => \$bval,
          ) or die;

REAL
----

   The REAL type encodes an floating-point number. It requires the POSIX
module.

Encoding
     The value should be the number to encode.

          $ber->encode(
              REAL => 3.14159265358979,
          ) or die;

Decoding
     The value will be the decoded floating-point value.

          $ber->decode(
              REAL => \$rval,
          );

ObjectDescriptor
----------------

   The ObjectDescriptor type encodes an ObjectDescriptor string. It is a
sub-class of STRING.

UTF8String
----------

   The UTF8String type encodes a string encoded in UTF-8. It is a
sub-class of STRING.

NumericString
-------------

   The NumericString type encodes a NumericString, which is defined to
only contain the characters 0-9 and space. It is a sub-class of STRING.

PrintableString
---------------

   The PrintableString type encodes a PrintableString, which is defined to
only contain the characters A-Z, a-z, 0-9, space, and the punctuation
characters ()-+=:',./?. It is a sub-class of STRING.

TeletexString/T61String
-----------------------

   The TeletexString type encodes a TeletexString, which is a string
containing characters according to the T.61 character set. Each T.61
character may be one or more bytes wide. It is a sub-class of STRING.

   T61String is an alternative name for TeletexString.

VideotexString
--------------

   The VideotexString type encodes a VideotexString, which is a string. It
is a sub-class of STRING.

IA5String
---------

   The IA5String type encodes an IA5String. IA5 (International Alphabet 5)
is equivalent to US-ASCII. It is a sub-class of STRING.

UTCTime
-------

   The UTCTime type encodes a UTCTime value. Note this value only
represents years using two digits, so it is not recommended in
Y2K-compliant applications. It is a sub-class of STRING.

   UTCTime values must be strings like:

     yymmddHHMM[SS]Z
     or:
     yymmddHHMM[SS]sHHMM

   Where yy is the year, mm is the month (01-12), dd is the day (01-31),
HH is the hour (00-23), MM is the minutes (00-60). SS is the optional
seconds (00-61).

   The time is either terminated by the literal character Z, or a timezone
offset. The "Z" character indicates Zulu time or UTC. The timezone offset
specifies the sign s, which is + or -, and the difference in hours and
minutes.

GeneralizedTime
---------------

   The GeneralizedTime type encodes a GeneralizedTime value. Unlike
UTCTime it represents years using 4 digits, so is Y2K-compliant. It is a
sub-class of STRING.

   GeneralizedTime values must be strings like:

     yyyymmddHHMM[SS][.U][Z]
     or:
     yyyymmddHHMM[SS][.U]sHHMM

   Where yyyy is the year, mm is the month (01-12), dd is the day (01-31),
HH is the hour (00-23), MM is the minutes (00-60). SS is the optional
seconds (00-61). U is the optional fractional seconds value; a comma is
permitted instead of a dot before this value.

   The time may be terminated by the literal character Z, or a timezone
offset. The "Z" character indicates Zulu time or UTC. The timezone offset
specifies the sign s, which is + or -, and the difference in hours and
minutes. If there is timezone specified UTC is assumed.

GraphicString
-------------

   The GraphicString type encodes a GraphicString value. It is a sub-class
of STRING.

VisibleString/ISO646String
--------------------------

   The VisibleString type encodes a VisibleString value, which is a value
using the ISO646 character set. It is a sub-class of STRING.

   ISO646String is an alternative name for VisibleString.

GeneralString
-------------

   The GeneralString type encodes a GeneralString value. It is a sub-class
of STRING.

UniversalString/CharacterString
-------------------------------

   The UniveralString type encodes a UniveralString value, which is a
value using the ISO10646 character set. Each character in ISO10646 is
4-bytes wide. It is a sub-class of STRING.

   CharacterString is an alternative name for UniversalString.

BMPString
---------

   The BMPString type encodes a BMPString value, which is a value using
the Unicode character set. Each character in the Unicode character set is
2-bytes wide. It is a sub-class of STRING.

CONSTRUCTED OPERATORS
=====================

   These operators are used to build constructed types, which contain
values in different types, like a C structure.

SEQUENCE
--------

   A SEQUENCE is a complex type that contains other types, a bit like a C
structure. Elements inside a SEQUENCE are encoded and decoded in the order
given.

Encoding
     The value should be a reference to an array containing another
     *opList* which defines the elements inside the SEQUENCE.

          $ber->encode(
              SEQUENCE => [
                  INTEGER => 123,
                  BOOLEAN => [ 1, 0 ],
              ]
          ) or die;

Decoding
     The value should a reference to an array that contains the *opList*
     which decodes the contents of the SEQUENCE.

          $ber->decode(
              SEQUENCE => [
                  INTEGER => \$ival,
                  BOOLEAN => \@bvals,
              ]
          ) or die;

SET
---

   A SET is an complex type that contains other types, rather like a
SEQUENCE. Elements inside a SET may be present in any order.

Encoding
     The value is the same as for the SEQUENCE operator.

          $ber->encode(
              SET => [
                  INTEGER => 13,
                  STRING => 'Hello',
              ]
          ) or die;

Decoding
     The value should be a reference to an *equivalent* *opList* to that
     used to encode the SET. The ordering of the *opList* should not
     matter.

          $ber->decode(
              SET => [
                  STRING => \$sval,
                  INTEGER => \$ival,
              ]
          ) or die;

SEQUENCE_OF
-----------

   A SEQUENCE_OF is an ordered list of other types.

Encoding
     The value is a ref followed by an *opList*. The ref must be a
     reference to a list or a hash: if it is to a list, then the *opList*
     will be repeated once for every element in the list. If it is to a
     hash, then the *opList* will be repeated once for every key in the
     hash (note that ordering of keys in a hash is not guaranteed by perl.)

     The remaining *opList* will then usually contain values which are
     code references. If the ref is to a list, then the contents of that
     item in the list are passed as the only argument to the code
     reference. If the ref is to a hash, then only the key is passed to
     the code.

          @vals = ( [ 10, 'Foo' ], [ 20, 'Bar' ] ); # List of refs to lists
          $ber->encode(
              SEQUENCE_OF => [ \@vals,
                  SEQUENCE => [
                      INTEGER => sub { $_[0][0] }, # Passed a ref to the inner list
                      STRING => sub { $_[0][1] }, # Passed a ref to the inner list
                  ]
              ]
          ) or die;
          %hash = ( 40 => 'Baz', 30 => 'Bletch' ); # Just a hash
          $ber->decode(
              SEQUENCE_OF => [ \%hash,
                  SEQUENCE => [
                      INTEGER => sub { $_[0] }, # Passed the key
                      STRING => sub { $hash{$_[0]} }, # Passed the key
                  ]
              ]
          );

Decoding
     The value must be a reference to a list containing a ref and an
     *opList*. The ref must always be a reference to a scalar. Each value
     in the <opList> is usually a code reference. The code referenced is
     called with the value of the ref (dereferenced); the value of the ref
     is incremented for each item in the SEQUENCE_OF.

          $ber->decode(
              SEQUENCE_OF => [ \$count,
                  # In the following subs, make space at the end of an array, and
                  # return a reference to that newly created space.
                  SEQUENCE => [
                      INTEGER => sub { $ival[$_[0]] = undef; \$ival[-1] },
                      STRING => sub { $sval[$_[0]] = undef; \$sval[-1] },
                  ]
              ]
          ) or die;

SET_OF
------

   A SET_OF is an unordered list. This is treated in an identical way to a
SEQUENCE_OF, except that no ordering should be inferred from the list
passed or returned.

SPECIAL OPERATORS
=================

BER
---

   It is sometimes useful to construct or deconstruct BER encodings in
several pieces. The BER operator lets you do this.

Encoding
     The value should be another Convert::BER object, which will be
     inserted into the buffer. If value is undefined then nothing is added.

          $tmp->encode(
              SEQUENCE => [
                  INTEGER => 20,
                  STRING => 'Foo',
              ]
          );
          $ber->encode(
              BER => $tmp,
              BOOLEAN => 1
          );

Decoding
     value should be a reference to a scalar, which will contain a
     Convert::BER object. This object will contain the remainder of the
     current sequence or set being decoded.

          # After this, ber2 will contain the encoded INTEGER B<and> STRING.
          # sval will be ignored and left undefined, but bval will be decoded. The
          # decode of ber2 will return the integer and string values.
          $ber->decode(
              SEQUENCE => [
                  BER => \$ber2,
                  STRING => \$sval,
              ],
              BOOLEAN => \$bval,
          );
          $ber2->decode(
              INTEGER => \$ival,
              STRING => \$sval2,
          );

ANY
---

   This is like the BER operator except that when decoding only the next
item is decoded and placed into the Convert::BER object returned. There is
no difference when encoding.

Decoding
     value should be a reference to a scalar, which will contain a
     Convert::BER object. This object will only contain the next single
     item in the current sequence being decoded.

          # After this, ber2 will decode further, and ival and sval
          # will be decoded.
          $ber->decode(
              INTEGER = \$ival,
              ANY => \$ber2,
              STRING => \$sval,
          );

OPTIONAL
--------

   This operator allows you to specify that an element is absent from the
encoding.

Encoding
     The value should be a reference to another list with another
     *opList*. If all of the values of the inner *opList* are defined, the
     entire OPTIONAL value will be encoded, otherwise it will be omitted.

          $ber->encode(
              SEQUENCE => [
          	    INTEGER => 16, # Will be encoded
                  OPTIONAL => [
                      INTEGER => undef, # Will not be encoded
                  ],
                  STRING => 'Foo', # Will be encoded
              ]
          );

Decoding
     The contents of value are decoded if possible, if not then decode
     continues at the next operator-value pair.

          $ber->decode(
              SEQUENCE => [
                  INTEGER => \$ival1,
                  OPTIONAL => [
                      INTEGER => \$ival2,
                  ],
                  STRING => \$sval,
              ]
          );

CHOICE
------

   The *opList* is a list of alternate operator-value pairs. Only one will
be encoded, and only one will be decoded.

Encoding
     A scalar at the start of the *opList* identifies which *opList*
     alternative to use for encoding the value. A value of 0 means the
     first one is used, 1 means the second one, etc.

          # Encode the BMPString alternate of the CHOICE
          $ber->encode(
              CHOICE => [ 2,
                  PrintableString => 'Printable',
                  TeletexString   => 'Teletex/T61',
                  BMPString       => 'BMP/Unicode',
                  UniversalString => 'Universal/ISO10646',
              ]
          ) or die;

Decoding
     A reference to a scalar at the start of the *opList* is used to store
     which alternative is decoded (0 for the first one, 1 for the second
     one, etc.) Pass undef instead of the ref if you don't care about this,
     or you store all the alternate values in different variables.

          # Decode the above.
          # Afterwards, $alt will be set to 2, $str will be set to 'BMP/Unicode'.
          $ber->decode(
              CHOICE => [ \$alt,
                  PrintableString => \$str,
                  TeletexString   => \$str,
                  BMPString       => \$str,
                  UniversalString => \$str,
              ]
          ) or die;

TAGS
====

   In BER everything being encoded has a tag, a length, and a value.
Normally the tag is derived from the operator - so INTEGER has a different
tag from a BOOLEAN, for instance.

   In some applications it is necessary to change the tags used. For
example, a SET may need to contain two different INTEGER values. Tags may
be changed in two ways, either IMPLICITly or EXPLICITly. With IMPLICIT
tagging, the new tag completely replaces the old tag. With EXPLICIT
tagging, the new tag is used *as well as* the old tag.

   Convert::BER supports two ways of using IMPLICIT tagging. One method is
to sub-class Convert::BER, which is described in the next section. For
small applications or those that think sub-classing is just too much then
the operator may be passed an arrayref. The array must contain two
elements, the first is the usual operator name and the second is the tag
value to use, as shown below.

     $ber->encode(
     	[ SEQUENCE => 0x34 ] => [
     	    INTEGER => 10,
     	    STRING  => "A"
     	]
     ) or die;

   This will encode a sequence, with a tag value of `0x34', which will
contain and integer and a string which will have their default tag values.

   You may wish to construct your tags using some pre-defined functions
such as `&Convert::BER::BER_APPLICATION', `&Convert::BER::BER_CONTEXT',
etc, instead of calculating the tag values yourself.

   To use EXPLICIT tagging, enclose the original element in a SEQUENCE,
and just override the SEQUENCE's tag as above. Don't forget to set the
constructed bit using `&Convert::BER::BER_CONSTRUCTOR'. For example, the
ASN.1 definition:

     Foo ::= SEQUENCE {
         [0] EXPLICIT INTEGER,
         INTEGER
     }

   might be encoded using this:

     $ber->encode(
         SEQUENCE => [
             [ SEQUENCE => &Convert::BER::BER_CONTEXT |
     			  &Convert::BER::BER_CONSTRUCTOR | 0 ] => [
                 INTEGER => 10,
             ],
             INTEGER => 11,
         ],
     ) or die;

SUB-CLASSING
============

   For large applications where operators with non default tags are used a
lot the above mechanism can be very error-prone. For this reason,
Convert::BER may be sub-classed.

   To do this the sub-class must call a static method define. The
arguments to define is a list of arrayrefs. Each arrayref will define one
new operator. Each arrayref contains three values, the first is the name
of the operator, the second is how the data is encoded and the third is
the tag value. To aid with the creation of these arguments Convert::BER
exports some variables and constant subroutines.

   For each operator defined by Convert::BER, or a Convert::BER sub-class,
a scalar variable with the same name is available for import, for example
`$INTEGER' is available from Convert::BER. And any operators defined by a
new sub-class will be available for import from that class.  One of these
variables may be used as the second element of each arrayref.

   Convert::BER also exports some constant subroutines that can be used to
create the tag value. The subroutines exported are:

     BER_BOOLEAN
     BER_INTEGER
     BER_BIT_STR
     BER_OCTET_STR
     BER_NULL
     BER_OBJECT_ID
     BER_SEQUENCE
     BER_SET

     BER_UNIVERSAL
     BER_APPLICATION
     BER_CONTEXT
     BER_PRIVATE
     BER_PRIMITIVE
     BER_CONSTRUCTOR

   Convert::BER also provides a subroutine called `ber_tag' to calculate
an integer value that will be used to represent a tag. For tags with
values less than 30 this is not needed, but for tags >= 30 then tag value
passed for an operator definition must be the result of `ber_tag'

   `ber_tag' takes two arguments, the first is the tag class and the second
is the tag value.

   Using this information a sub-class of Convert::BER can be created as
shown below.

     package Net::LDAP::BER;

     use Convert::BER qw(/^(\$|BER_)/);

     use strict;
     use vars qw($VERSION @ISA);

     @ISA = qw(Convert::BER);
     $VERSION = "1.00";

     Net::LDAP::BER->define(

     # Name		Type      Tag
     ########################################

     [ REQ_UNBIND     => $NULL,
     			  BER_APPLICATION  	 	    | 0x02 ],

     [ REQ_COMPARE    => $SEQUENCE,
     			  BER_APPLICATION | BER_CONSTRUCTOR | 0x0E ],

     [ REQ_ABANDON    => $INTEGER,
     			  ber_tag(BER_APPLICATION, 0x10) ],
         );

   This will create a new class `Net::LDAP::BER' which has three new
operators available. This class then may be used as follows

     $ber = new Net::LDAP::BER;

     $ber->encode(
     	REQ_UNBIND => 0,
     	REQ_COMPARE => [
     	    REQ_ABANDON => 123,
     	]
     );

     $ber->decode(
     	REQ_UNBIND => \$var,
     	REQ_COMPARE => [
     	    REQ_ABANDON => \$num,
     	]
     );

   Which will encode or decode the data using the formats and tags defined
in the `Net::LDAP::BER' sub-class. It also helps to make the code more
readable.

DEFINING NEW PACKING OPERATORS
------------------------------

   As well as defining new operators which inherit from existing operators
it is also possible to define a new operator and how data is encoded and
decoded. The interface for doing this is still changing but will be
documented here when it is done. To be continued ...

LIMITATIONS
===========

   Convert::BER cannot support tags that contain more bits than can be
stored in a scalar variable, typically this is 32 bits.

   Convert::BER cannot support items that have a packed length which
cannot be stored in 32 bits.

BUGS
====

   The SET decode method fails if the encoded order is different to the
*opList* order.

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

   Significant POD updates from Chris Ridd <Chris.Ridd@messagingdirect.com>

COPYRIGHT
=========

   Copyright (c) 1995-2000 Graham Barr. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Encoding and decoding of base32 strings
***************************************

NAME
====

   Convert::Base32 - Encoding and decoding of base32 strings

SYNOPSIS
========

     use Convert::Base32 qw(encode_base32 decode_base32);

     $encoded = encode_base32("\x3a\x27\x0f\x93");
     $decoded = decode_base32($encoded);

DESCRIPTION
===========

   This module provides functions to convert string from / to Base32
encoding, specified in RACE internet-draft. The Base32 encoding is
designed to encode non-ASCII characters in DNS-compatible host name parts.

   See http://www.ietf.org/internet-drafts/draft-ietf-idn-race-03.txt for
more details.

FUNCTIONS
=========

   Following functions are provided; unlike `MIME::Base64', they are in
*@EXPORT_OK* array. See Exporter, for details.

encode_base32($str)
     Encode data by calling the encode_base32() function. This function
     takes a string to encode and returns the encoded base32 string.

decode_base32($str)
     Decode a base32 string by calling the decode_base32() function. This
     function takes a string to decode and returns the decoded string.

     This function might throw the exceptions such as "Data contains
     non-base32 characters", "Length of data invalid" and "PADDING number
     of bits at the end of output buffer are not all zero".

TODO
====

   Using XS would be by far efficient.

AUTHOR
======

   Tatsuhiko Miyagawa <miyagawa@bulknews.net>

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   http://www.ietf.org/internet-drafts/draft-ietf-idn-race-03.txt, see
MIME/Base64, Convert/RACE.

extract data from Macintosh BinHex files
****************************************

NAME
====

   Convert::BinHex - extract data from Macintosh BinHex files

   *ALPHA WARNING: this code is currently in its Alpha release.  Things
may change drastically until the interface is hammered out: if you have
suggestions or objections, please speak up now!*

SYNOPSIS
========

   *Simple functions:*

     use Convert::BinHex qw(binhex_crc macbinary_crc);

     # Compute HQX7-style CRC for data, pumping in old CRC if desired:
     $crc = binhex_crc($data, $crc);

     # Compute the MacBinary-II-style CRC for the data:
     $crc = macbinary_crc($data, $crc);

   *Hex to bin, low-level interface.* Conversion is actually done via an
object (`"Convert::BinHex::Hex2Bin"' in this node) which keeps internal
conversion state:

     # Create and use a "translator" object:
     my $H2B = Convert::BinHex->hex2bin;    # get a converter object
     while (<STDIN>) {
     	print $STDOUT $H2B->next($_);        # convert some more input
     }
     print $STDOUT $H2B->done;              # no more input: finish up

   *Hex to bin, OO interface.* The following operations must be done in
the order shown!

     # Read data in piecemeal:
     $HQX = Convert::BinHex->open(FH=>\*STDIN) || die "open: $!";
     $HQX->read_header;                  # read header info
     @data = $HQX->read_data;            # read in all the data
     @rsrc = $HQX->read_resource;        # read in all the resource

   *Bin to hex, low-level interface.* Conversion is actually done via an
object (`"Convert::BinHex::Bin2Hex"' in this node) which keeps internal
conversion state:

     # Create and use a "translator" object:
     my $B2H = Convert::BinHex->bin2hex;    # get a converter object
     while (<STDIN>) {
     	print $STDOUT $B2H->next($_);        # convert some more input
     }
     print $STDOUT $B2H->done;              # no more input: finish up

   *Bin to hex, file interface.*  Yes, you can convert to BinHex as well
as from it!

     # Create new, empty object:
     my $HQX = Convert::BinHex->new;

     # Set header attributes:
     $HQX->filename("logo.gif");
     $HQX->type("GIFA");
     $HQX->creator("CNVS");

     # Give it the data and resource forks (either can be absent):
     $HQX->data(Path => "/path/to/data");       # here, data is on disk
     $HQX->resource(Data => $resourcefork);     # here, resource is in core

     # Output as a BinHex stream, complete with leading comment:
     $HQX->encode(\*STDOUT);

   *PLANNED!!!! Bin to hex, "CAP" interface.* *Thanks to Ken Lunde for
suggesting this*.

     # Create new, empty object from CAP tree:
     my $HQX = Convert::BinHex->from_cap("/path/to/root/file");
     $HQX->encode(\*STDOUT);

DESCRIPTION
===========

   BinHex is a format used by Macintosh for transporting Mac files safely
through electronic mail, as short-lined, 7-bit, semi-compressed data
streams.  Ths module provides a means of converting those data streams
back into into binary data.

FORMAT
======

   *(Some text taken from RFC-1741.)* Files on the Macintosh consist of
two parts, called *forks*:

Data fork
     The actual data included in the file.  The Data fork is typically the
     only meaningful part of a Macintosh file on a non-Macintosh computer
     system.  For example, if a Macintosh user wants to send a file of
     data to a user on an IBM-PC, she would only send the Data fork.

Resource fork
     Contains a collection of arbitrary attribute/value pairs, including
     program segments, icon bitmaps, and parametric values.

   Additional information regarding Macintosh files is stored by the
Finder in a hidden file, called the "Desktop Database".

   Because of the complications in storing different parts of a Macintosh
file in a non-Macintosh filesystem that only handles consecutive data in
one part, it is common to convert the Macintosh file into some other
format before transferring it over the network.  The BinHex format
squashes that data into transmittable ASCII as follows:

  1. The file is output as a *byte stream* consisting of some basic header
     information (filename, type, creator), then the data fork, then the
     resource fork.

  2. The byte stream is *compressed* by looking for series of duplicated
     bytes and representing them using a special binary escape sequence
     (of course, any occurences of the escape character must also be
     escaped).

  3. The compressed stream is *encoded* via the "6/8 hemiola" common to
     base64 and *uuencode*: each group of three 8-bit bytes (24 bits) is
     chopped into four 6-bit numbers, which are used as indexes into an
     ASCII "alphabet".  (I assume that leftover bytes are zero-padded;
     documentation is thin).

FUNCTIONS
=========

CRC computation
---------------

macbinary_crc DATA, SEED
     Compute the MacBinary-II-style CRC for the given DATA, with the CRC
     seeded to SEED.  Normally, you start with a SEED of 0, and you pump in
     the previous CRC as the SEED if you're handling a lot of data one
     chunk at a time.  That is:

          $crc = 0;
          while (<STDIN>) {
              $crc = macbinary_crc($_, $crc);
          }

     Note: Extracted from the *mcvert* utility (Doug Moore, April '87),
     using a "magic array" algorithm by Jim Van Verth for efficiency.
     Converted to Perl5 by Eryq.  *Untested.*

binhex_crc DATA, SEED
     Compute the HQX-style CRC for the given DATA, with the CRC seeded to
     SEED.  Normally, you start with a SEED of 0, and you pump in the
     previous CRC as the SEED if you're handling a lot of data one chunk
     at a time.  That is:

          $crc = 0;
          while (<STDIN>) {
              $crc = binhex_crc($_, $crc);
          }

     Note: Extracted from the *mcvert* utility (Doug Moore, April '87),
     using a "magic array" algorithm by Jim Van Verth for efficiency.
     Converted to Perl5 by Eryq.

OO INTERFACE
============

Conversion
----------

bin2hex
     *Class method, constructor.* Return a converter object.  Just creates
     a new instance of `"Convert::BinHex::Bin2Hex"' in this node; see that
     class for details.

hex2bin
     *Class method, constructor.* Return a converter object.  Just creates
     a new instance of `"Convert::BinHex::Hex2Bin"' in this node; see that
     class for details.

Construction
------------

new PARAMHASH
     *Class method, constructor.* Return a handle on a BinHex'able entity.
     In general, the data and resource forks for such an entity are
     stored in native format (binary) format.

     Parameters in the PARAMHASH are the same as header-oriented method
     names, and may be used to set attributes:

          $HQX = new Convert::BinHex filename => "icon.gif",
                                     type    => "GIFB",
                                     creator => "CNVS";

open PARAMHASH
     *Class method, constructor.* Return a handle on a new BinHex'ed
     stream, for parsing.  Params are:

    Data
          Input a HEX stream from the given data.  This can be a scalar,
          or a reference to an array of scalars.

    Expr
          Input a HEX stream from any open()able expression.  It will be
          opened and binmode'd, and the filehandle will be closed either
          on a close() or when the object is destructed.

    FH
          Input a HEX stream from the given filehandle.

    NoComment
          If true, the parser should not attempt to skip a leading "(This
          file...)"  comment.  That means that the first nonwhite
          characters encountered must be the binhex'ed data.

Get/set header information
--------------------------

creator [VALUE]
     *Instance method.* Get/set the creator of the file.  This is a
     four-character string (though I don't know if it's guaranteed to be
     printable ASCII!)  that serves as part of the Macintosh's version of
     a MIME "content-type".

     For example, a document created by "Canvas" might have creator
     `"CNVS"'.

data [PARAMHASH]
     *Instance method.* Get/set the data fork.  Any arguments are passed
     into the new() method of `"Convert::BinHex::Fork"' in this node.

filename [VALUE]
     *Instance method.* Get/set the name of the file.

flags [VALUE]
     *Instance method.* Return the flags, as an integer.  Use bitmasking
     to get as the values you need.

header_as_string
     Return a stringified version of the header that you might use for
     logging/debugging purposes.  It looks like this:

          X-HQX-Software: BinHex 4.0 (Convert::BinHex 1.102)
          X-HQX-Filename: Something_new.eps
          X-HQX-Version: 0
          X-HQX-Type: EPSF
          X-HQX-Creator: ART5
          X-HQX-Data-Length: 49731
          X-HQX-Rsrc-Length: 23096

     As some of you might have guessed, this is RFC-822-style, and may be
     easily plunked down into the middle of a mail header, or split into
     lines, etc.

requires [VALUE]
     *Instance method.* Get/set the software version required to convert
     this file, as extracted from the comment that preceded the actual
     binhex'ed data; e.g.:

          (This file must be converted with BinHex 4.0)

     In this case, after parsing in the comment, the code:

          $HQX->requires;

     would get back "4.0".

resource [PARAMHASH]
     *Instance method.* Get/set the resource fork.  Any arguments are
     passed into the new() method of `"Convert::BinHex::Fork"' in this
     node.

type [VALUE]
     *Instance method.* Get/set the type of the file.  This is a
     four-character string (though I don't know if it's guaranteed to be
     printable ASCII!)  that serves as part of the Macintosh's version of
     a MIME "content-type".

     For example, a GIF89a file might have type `"GF89"'.

version [VALUE]
     *Instance method.* Get/set the version, as an integer.

Decode, high-level
------------------

read_comment
     *Instance method.* Skip past the opening comment in the file, which
     is of the form:

          (This file must be converted with BinHex 4.0)

     As per RFC-1741, *this comment must immediately precede the BinHex
     data,* and any text before it will be ignored.

     *You don't need to invoke this method yourself;* `read_header()' will
     do it for you.  After the call, the version number in the comment is
     accessible via the requires() method.

read_header
     *Instance method.* Read in the BinHex file header.  You must do this
     first!

read_data [NBYTES]
     *Instance method.* Read information from the data fork.  Use it in an
     array context to slurp all the data into an array of scalars:

          @data = $HQX->read_data;

     Or use it in a scalar context to get the data piecemeal:

          while (defined($data = $HQX->read_data)) {
             # do stuff with $data
          }

     The NBYTES to read defaults to 2048.

read_resource [NBYTES]
     *Instance method.* Read in all/some of the resource fork.  See
     `read_data()' for usage.

Encode, high-level
------------------

encode OUT
     Encode the object as a BinHex stream to the given output handle OUT.
     OUT can be a filehandle, or any blessed object that responds to a
     print() message.

     The leading comment is output, using the requires() attribute.

SUBMODULES
==========

Convert::BinHex::Bin2Hex
------------------------

   A BINary-to-HEX converter.  This kind of conversion requires a certain
amount of state information; it cannot be done by just calling a simple
function repeatedly.  Use it like this:

     # Create and use a "translator" object:
     my $B2H = Convert::BinHex->bin2hex;    # get a converter object
     while (<STDIN>) {
     	print STDOUT $B2H->next($_);          # convert some more input
     }
     print STDOUT $B2H->done;               # no more input: finish up

     # Re-use the object:
     $B2H->rewind;                 # ready for more action!
     while (<MOREIN>) { ...

   On each iteration, next() (and `done()') may return either a
decent-sized non-empty string (indicating that more converted data is
ready for you) or an empty string (indicating that the converter is
waiting to amass more input in its private buffers before handing you more
stuff to output.

   Note that `done()' always converts and hands you whatever is left.

   This may have been a good approach.  It may not.  Someday, the converter
may also allow you give it an object that responds to read(), or a
FileHandle, and it will do all the nasty buffer-filling on its own,
serving you stuff line by line:

     # Someday, maybe...
     my $B2H = Convert::BinHex->bin2hex(\*STDIN);
     while (defined($_ = $B2H->getline)) {
     	print STDOUT $_;
     }

   Someday, maybe.  Feel free to voice your opinions.

Convert::BinHex::Hex2Bin
------------------------

   A HEX-to-BINary converter. This kind of conversion requires a certain
amount of state information; it cannot be done by just calling a simple
function repeatedly.  Use it like this:

     # Create and use a "translator" object:
     my $H2B = Convert::BinHex->hex2bin;    # get a converter object
     while (<STDIN>) {
     	print STDOUT $H2B->next($_);          # convert some more input
     }
     print STDOUT $H2B->done;               # no more input: finish up

     # Re-use the object:
     $H2B->rewind;                 # ready for more action!
     while (<MOREIN>) { ...

   On each iteration, next() (and `done()') may return either a
decent-sized non-empty string (indicating that more converted data is
ready for you) or an empty string (indicating that the converter is
waiting to amass more input in its private buffers before handing you more
stuff to output.

   Note that `done()' always converts and hands you whatever is left.

   Note that this converter does not find the initial "BinHex version"
comment.  You have to skip that yourself.  It only handles data between
the opening and closing `":"'.

Convert::BinHex::Fork
---------------------

   A fork in a Macintosh file.

     # How to get them...
     $data_fork = $HQX->data;      # get the data fork
     $rsrc_fork = $HQX->resource;  # get the resource fork

     # Make a new fork:
     $FORK = Convert::BinHex::Fork->new(Path => "/tmp/file.data");
     $FORK = Convert::BinHex::Fork->new(Data => $scalar);
     $FORK = Convert::BinHex::Fork->new(Data => \@array_of_scalars);

     # Get/set the length of the data fork:
     $len = $FORK->length;
     $FORK->length(170);        # this overrides the REAL value: be careful!

     # Get/set the path to the underlying data (if in a disk file):
     $path = $FORK->path;
     $FORK->path("/tmp/file.data");

     # Get/set the in-core data itself, which may be a scalar or an arrayref:
     $data = $FORK->data;
     $FORK->data($scalar);
     $FORK->data(\@array_of_scalars);

     # Get/set the CRC:
     $crc = $FORK->crc;
     $FORK->crc($crc);

UNDER THE HOOD
==============

Design issues
-------------

BinHex needs a stateful parser
     Unlike its cousins base64 and *uuencode*, BinHex format is not
     amenable to being parsed line-by-line.  There appears to be no
     guarantee that lines contain 4n encoded characters... and even if
     there is one, the BinHex compression algorithm interferes: even when
     you can decode one line at a time, you can't necessarily *decompress*
     a line at a time.

     For example: a decoded line ending with the byte `\x90' (the escape
     or "mark" character) is ambiguous: depending on the next decoded byte,
     it could mean a literal `\x90' (if the next byte is a `\x00'), or it
     could mean n-1 more repetitions of the previous character (if the
     next byte is some nonzero n).

     For this reason, a BinHex parser has to be somewhat stateful: you
     cannot have code like this:

          #### NO! #### NO! #### NO! #### NO! #### NO! ####
          while (<STDIN>) {            # read HEX
              print hexbin($_);          # convert and write BIN
          }

     unless something is happening "behind the scenes" to keep track of
     what was last done.  *The dangerous thing, however, is that this
     approach will *seem* to work, if you only test it on BinHex files
     which do not use compression and which have 4n HEX characters on each
     line.*

     Since we have to be stateful anyway, we use the parser object to keep
     our state.

We need to be handle large input files
     Solutions that demand reading everything into core don't cut it in my
     book.  The first MPEG file that comes along can louse up your whole
     day.  So, there are no size limitations in this module: the data is
     read on-demand, and filehandles are always an option.

Boy, is this slow!
     A lot of the byte-level manipulation that has to go on, particularly
     the CRC computing (which involves intensive bit-shifting and masking)
     slows this module down significantly.  What is needed perhaps is an
     optional extension library where the slow pieces can be done more
     quickly... a Convert::BinHex::CRC, if you will.  Volunteers, anyone?

     Even considering that, however, it's slower than I'd like.  I'm sure
     many improvements can be made in the HEX-to-BIN end of things.  No
     doubt I'll attempt some as time goes on...

How it works
------------

   Since BinHex is a layered format, consisting of...

     A Macintosh file [the "BIN"]...
        Encoded as a structured 8-bit bytestream, then...
           Compressed to reduce duplicate bytes, then...
              Encoded as 7-bit ASCII [the "HEX"]

   ...there is a layered parsing algorithm to reverse the process.
Basically, it works in a similar fashion to stdio's fread():

     0. There is an internal buffer of decompressed (BIN) data,
        initially empty.
     1. Application asks to read() n bytes of data from object
     2. If the buffer is not full enough to accomodate the request:
          2a. The read() method grabs the next available chunk of input
              data (the HEX).
          2b. HEX data is converted and decompressed into as many BIN
              bytes as possible.
          2c. BIN bytes are added to the read() buffer.
          2d. Go back to step 2a. until the buffer is full enough
              or we hit end-of-input.

   The conversion-and-decompression algorithms need their own internal
buffers and state (since the next input chunk may not contain all the data
needed for a complete conversion/decompression operation).  These are
maintained in the object, so parsing two different input streams
simultaneously is possible.

WARNINGS
========

   Only handles `Hqx7' files, as per RFC-1741.

   Remember that Macintosh text files use `"\r"' as end-of-line: this
means that if you want a textual file to look normal on a non-Mac system,
you probably want to do this to the data:

     # Get the data, and output it according to normal conventions:
     foreach ($HQX->read_data) { s/\r/\n/g; print }

CHANGE LOG
==========

   Current version: $Id: BinHex.pm,v 1.119 1997/06/28 05:12:42 eryq Exp $

Version 1.118
     Ready to go public (with Paul's version, patched for native Mac
     support)!  Warnings have been suppressed in a few places where
     undefined values appear.

Version 1.115
     Fixed another bug in comp2bin, related to the MARK falling on a
     boundary between inputs.  Added testing code.

Version 1.114
     Added BIN-to-HEX conversion.  Eh.  It's a start.  Also, a lot of
     documentation additions and cleanups.  Some methods were also renamed.

Version 1.103
     Fixed bug in decompression (wasn't saving last character).  Fixed
     "NoComment" bug.

Version 1.102
     Initial release.

AUTHOR AND CREDITS
==================

   Written by Eryq, `http://www.enteract.com/~eryq' / `eryq@enteract.com'

   Support for native-Mac conversion, plus invaluable contributions in
Alpha Testing, plus a few patches, plus the baseline binhex/debinhex
programs, were provided by Paul J. Schinder (NASA/GSFC).

   Ken Lunde (Adobe) suggested incorporating the CAP file representation.

TERMS AND CONDITIONS
====================

   Copyright (c) 1997 by Eryq.  All rights reserved.  This program is free
software; you can redistribute it and/or modify it under the same terms as
Perl itself.

   This software comes with NO WARRANTY of any kind.  See the COPYING file
in the distribution for details.

an Attributed Text data type
****************************

NAME
====

   Convert::Context - an Attributed Text data type

   - ALPHA - release

   $Revision: 1.77 $ $Date: 1998/10/03 22:21:23 $

SYNOPSIS
========

   See below.

DESCRIPTION
===========

   Convert::Context maintains attributed strings. It allows you to access
those strings similar to perl's normal strings.

   An attributed string is a string to that attributes are connected at
certain string positions. An attribute can be everything scalar: numbers,
strings, references are welcome. Attributes are not part of the string.
Semantics of the attributes have to be done by the applying code.

   What does this mean?

   A basic work for a text system is to localize a certain text part. This
is trivial if you have only plain text to look at. It is no longer
trivial, if you have attributes or entries among your text like: bold,
italic, bookmarks and so on. One has two strategies to mingle attributes
with a string:

  1. You can enrich the text by inserting control codes. E.g., if you have
     a line with two bold words:

     (A) "The word bold is always bold"

     it would look (here with HTML controls) like:

     (B) "The word <b>bold</b> is always <b>bold</b>"

     If you would look for the text "bold is" in (B) with perls m//
     operator, you'd fail. You would have to strip the HTML control
     sequences first. This is an ok method, but not used here.

  2. You can maintain separate lists, holding at which position of the text
     which control codes are stored. This is, what Convert::Context does.
     The example from above would look like:

          offset    0---------1---------2-------
          text      The word bold is always bold
          attrib   (0        1   0          1   )

     Internally this is stored as:

          $Context = {
             "T" => \("The word bold is always bold"),
             "A" => [0, 1,  0,  1]
             "O" => [0, 9, 13, 24],
          }

     The maintainance of these lists is a little bit tricky, so what a
     luck, that you don't need to care about this.

        Do not rely on this internal representation, as it might change.
E.g. it could happen, that "O" in future stores relative offsets instead
of absolute.

   *Available Methods*

acmp
     *sub { $Code }* = *$Ct* -> acmp (*sub { $Code }*)

     When two attribs shall be compared, this normally is done stringwise,
     using function "cmp". If this is not practical for you, with acmp you
     could provide a new compare function, similar to the way you do when
     using sort.

     The standard behavior is implemented this way:

          $Ct -> acmp (sub { $_[0] cmp $_[1] })

     Note: The code provided via acmp is not used when comparing identity.
     That means: *$Ct1* -> eq (*$Ct1*) is always true.

append
     *$Ct1* = *$Ct1* -> append (*$Ct2*||*$str2*||*$strR2*, ...)

     Appends all strings, string references or Contexts to the end of
     Context1.

attrib
     Attrib is used to yield and change the attributes of a Context. It can
     be called several ways.

     (1) *$attrib* = *$Ct* -> attrib (*$pos* [,*[$attrib]*])

     When called in a scalar context with only *$pos* as parameter, attrib
     returns the attribute of Context at character position *$pos*. You can
     can set the attribute by specifying the new one as a list reference
     (not recommended).

     (2) (*[@attrib]*, *[@offset]*) = *$Ct* -> attrib (*$pos*, *$len*)

     When called in an array context, a list with references to a free
     usable attrib array and a free usable offset array is returned.

     (3) *$attrib* = *$Ct* -> attrib (*$pos*, *$len*, *$attrib*)

     When called in a scalar context with three parameters and *$attrib* is
     scalar, the attributes of Context Ct starting at position *$pos* with
     length *$len* will be set to *$attrib*.

     (4) 1||undef = *$Ct* -> attrib (*$o1*, $l1, *[@attrib]*, *[@offset]*)

     Substitutes attributes of Context Ct from position o1 and length l1
     with attributes *[@attrib]* according to offsets *[@offset]*.

     (5) 1||undef = *$Ct* -> attrib (*$o1*, $l1, *[@attrib]*, *[@offset]*,
     *$o2*, $l2)

     Like (4), but *@attrib* and *@offset* are reduced according to offset
     *$o2* and length $l2.

     (6) 1||undef = *$Ct1* -> attrib (*$o1*, $l1, *$Ct2*)

     Substitutes attributes of Context *$Ct1* from position *$o1* and
     length $l1 with attributes of Context *Ct2* from position 0 to
     position $l1.

     Note: Attrib does not care for the length of *$Ct2*!

     (7) 1||undef = *$Ct1* -> attrib (*$o1*, $l1, *$Ct2* [,*$o2*, $l2])

     Like (6), but only the part of *$Ct2* from position *$o2* with a
     length $l2 is used.

charsize
     *$Ct* = *$Ct* -> charsize ([*$bytesize_of_one_char*])

     Returns the character size of Context Ct. The character size is the
     size of one character measured in bytes. If parameter bytesize is
     given, Context Ct additionally is converted to a Context with the new
     character size bytesize.

chunks
     [ [*$str1*, *$attr1*], [*$str2*, *$attr2*], ... ] = *$Ct* -> chunks ()

     Until now this is the only way to traverse a Context by it's different
     attributes. You would use it like:

          for ( @{$Ct1->chunks()} ) {
             my ($text, $attrib) = @{$_};
             if ($attrib) {
                # do something (text has attribute $attrib)
             } else {
                # do something (text has default attribute)
             }
          }

clone
     *$Ct2* = *$Ct1* -> clone

     Returns a 1:1 copy of Context Ct1 as new Context Ct2.

dump
     *$Ct* = *$Ct* -> dump

     For debugging purposes. Dumps the Context structure to stdout.

eq
     1||0 = *$Ct1* -> eq (*$Ct2*)

     Returns 1, if Context1 is equal to Context2, returns 0 otherwise.

index
     *$pos* = *$Ct* -> index ($string [,*$pos*])

     Analogue to perls index. (see "man perlfunc")

join
     *$Ct* = Convert::Context -> join ($expr, *$Ct1*||*$str1*||*$strR1*,
     ...)

     Concatenates all strings (scalar or reference) or Contexts with
     delimitor $expr, returns a new build Context.

     *$Ct1* = *$Ct1* -> join (*$Ct2*||*$str2*||*$strR2*, ...)

     Like above, but modifies *$Ct1* instead of creating a new Context.

lc
     *$Ct2* = *$Ct1* -> lc

     Like perls lc. Returns a lowercased version of Context1 as Context2.

lcfirst
     *$Ct2* = *$Ct1* -> lcfirst

     Like perls lcfirst. Returns a version of Context1 with a lowercased
     first character as Context2.

length
     $length = *$Ct* -> length

     Returns the length of Context Ct. This is the length of the text part
     of Ct, measured in characters.

ne
     1||0 = *$Ct1* -> ne (*$Ct2*)

     Returns 1, if Context1 is different from Context2, returns 0
     otherwise.

new
     *$Ct* = Convert::Context -> new ([*$cs*])

     *$Ct* = Convert::Context -> new ([*$cs*,] *\$txt* [,*[@a]*, *[@o]*])

     *$Ct* = Convert::Context -> new ([*$cs*,] [*\$txt* [,*[@a]*, *[@o]*]],
     [...], ...)

     Returns a new Context string. It can be initialized three ways: (1)
     Without parameters, (2) with a reference to a text string, an attrib
     list reference and an offset list reference, or (3) with a list of
     references of (2).

     Optionally it can be initialized with a leading parameter *$cs*. This
     stands for "character length" and specifies the byte size of one
     character.  One needs this when using e.g. UTF16 (Unicode) characters.

     Example:

          (1)
            $Empty = Convert::Context -> new;

          (2)
            $Plain = Convert::Context -> new (\("Plain text\n"));
            $Bold  = Convert::Context -> new (\("Attribute 1 text"), [1]);

          (3)
            Special (but useful) case:
            $Mixed = Convert::Context -> new (
               [\("This is an "),                         [0] ],
               [\("all bold"),                          [122] ],
               [\(", short and sometimes ")                   ],
               [\("italic"),       ["Strange text attribute"] ],
               [\(" text."                                    ]
            ;

     Attribute 0 and Offset 0 is used as default value, if none is
     explicitly given. The meaning of all attributes (here 0, 122 and
     "Strange text attribute") has to be defined 100% by the applying code.
     In this example one would assume, that a text processor was connoting
     the attributes 0, 122 and "Strange text attribute" to the semantics:
     plain, bold and italic.

replace
     $n = *$Ct* -> replace (*$pattern*, *$replace*, `egimosx')

     Replaces one or all occurrances matching to *$pattern* with
     *$replace*.  Returns the number of replacements, or false if pattern
     is not found.  Implemented mainly via perls replace operator:

          s/$pattern/$replace/egimosx

     *$replace* here can be a string, a Context or a code reference. In the
     latter case this routine will be called at each match, passing the
     matched string as parameter. The matched text will then be replaced
     with the return value of the routine.

     $n = *$Ct* -> replace (*[@pattern]*, *[@replace]*, `egimosx')

     You can call replace with list references holding corresponding sets
     of patterns and replacements. pattern and replace can be strings or
     Contexts, and replace additionally code references. The patterns will
     be glued together to a single pattern match, using pattern match or
     operator |.

     Examples:

          (1) $Ct -> replace ("krims", "kram", "g")

     Option g says, that not only one, but all occurrances of string
     "krims" shall be substituted by string "kram".  "kram" will get the
     attributes of "krims" (see method "substr"). If you want to have more
     control about the attributes of "kram", you can pass the replacement
     string as a Context.

          (2) $Ct -> replace ("krims", $Ct, "g")

     Replaces all occurrances of string "krims" with the Context $Ct. This
     is useful, if you want to have $Ct special attributes.

          (3) $Ct -> replace (" asta tu ", " AStA TU ", "ig")

     Option i says, that the characters case shall be ignored. So example
     (3) would replace " asta tu ", " ASTA TU ", " Asta Tu " ... with "
     AStA TU ".  (AStA stands for Allgemeiner Studierendenausschuß.
     Students governments are called like this in Germany and quite cool).

          (4) $Ct -> replace ("\02", \&footnote, "g")

     This would call a function "footnote". The function will be called
     with three parameters:

          &function($match, $Ct, $pos)

          1. The matched string (here "\02")
          2. The Context        (here $Ct)
          3. The match position

          (5) $Ct -> replace ("krims", sub {allow (@_, "kram")}, "ig")

     This notation would call a function "allow" for each match, quite like
     (4). But further more here the string "kram" would be passed as
     additional parameter.

          (6) $Ct -> replace (["a", "o"], ["o", "a"], "g")

     Substitutes a's with o's and o's with a's.

rindex
     *$pos* = *$Ct* -> rindex ($string [,*$pos*])

     Analogue to perls rindex. (try "man perlfunc")

split
     *@Ct* = *$Ct* -> split (*$pattern* [$option [,*$limit*]])

     Similar to perls split. Splits a Context according to string or
     Context delimitor *$pattern*. Returns an array of Contexts. If
     *$limit* is given, returns only that many elements. *$pattern* and
     $option are to be used according to perls
     s/*$pattern*/something/`egimosx' operator (but option "g" here is
     always set).

substr
     *$Ct2* = *$Ct1* -> substr (*$o1*, $l1)

     Returns a partial Context of Ct1 as new Context Ct2. Ct2 will be
     copied from Ct1 starting at position o1 and with the length l1.

     *$Ct*  = *$Ct*  -> substr (*$o1*, $l1, $str [,*$o2*, $l2])

     If a string is given as argument, the partial Context starting at
     offset o1 with length l1 is substituted by string. String gets the
     attributes of the partial Context. If e.g. the string to be replaced
     would be "<0>di<1>n<2>g<0>s", after the replacement it might look like
     "<0>bu<1>m<2>s".

     *$Ct1* = *$Ct1* -> substr (*$o1*, $l1, *$Ct2* [,*$o2*, $l2])

     The partial Context of Ct1 starting at offset o1 with length l2 is
     substituted by Context Ct2.

     If o<n> is undef, o<n> is set to 0.

     If l<n> is undef, l<n> is set according to end of Ct<n>

text
     *\$text* = *$Ct* -> text

     Returns a reference to the text section of Context Ct.

tr
     Synonyme for y. (see below)

uc
     *$Ct2* = *$Ct1* -> uc

     Like perls uc. Returns an uppercased version of Context Ct1 as
     Context Ct2.

ucfirst
     *$Ct2* = *$Ct1* -> ucfirst

     Like perls ucfirst. Returns a version of Context Ct1 with an
     uppercased first character as Context Ct2.

y
     y can be called three ways.

     (1) *$Ct* -> y (*$search*, *$replace*, cds)

     If charsize of *$Ct* is 1, y behaves quite like perls y. Each
     character of string *$search* is replaced by the corresponding
     character of *$replace*.

     (2) *$Ct* -> y (*$search*, *$replace*, `egimosx')

     If charsize of *$Ct* is bigger than 1, y breaks the strings *$search*
     and *$replace* into substrings, each charsize bytes long. These
     corresponding strings are then passed to method replace,
     automatically with option "g".  Note, that thus internally perls tr
     operator is not used.

     (3) *$Ct* -> y (*[@search]*, *[@replace]*, `egimosx')

     This actually just calls method replace with option "g". *@search* and
     *@replace* can be Contexts or strings, just like you want. *@replace*
     can also be code references.

ERRORS
======

   - I just found that split with parameter *$limit* behaves not like perls
 split. Will be done.

TO DO
=====

   - Speeding up

   - When programming this a long time ago I was very fond of references.
 Today this seems quite odd to me sometimes. So there might happen a
major redesign sooner or later.

   - The only real way to traverse a Context is still method "chunks()".
There need to be some enhancements.

   - Support for a hash parameter style for calling methods?

   - Support for overloaded operators?

AUTHOR
======

   Martin Schwartz <`schwartz@cs.tu-berlin.de'>.

Routines for converting from one cyrillic charset to another.
*************************************************************

NAME
====

   Convert::Cyrillic v1.01 - Routines for converting from one cyrillic
charset to another.

SYNOPSIS
========

     use Convert::Cyrillic;

     $src = 'koi8';
     $dst = 'win';
     $SrcBuf = 'text in koi8 here';
     $DstBuf = Convert::Cyrillic::cstocs ($Src, $Dst, $SrcBuf);

DESCRIPTION
===========

   This package implements routine for converting from one cyrillic
charset to another. It is intended to be used from cgi's which need
built-in support for translations. For example, you may wish to use it in
form processor to translate from user encoding to one used by your site.

   Where *$Src* and *$Dst* are one of:

     KOI8 - for KOI8-R
     WIN - for WIN-1251
     DOS - for DOS, alternative, CP-866
     MAC - for Macintosh
     ISO - for ISO-8859-5
     UTF-8 - for UTF-8 (Unicode)
     VOL - for Volapuk (transliteration)

   Buffer may contain line breaks, which are preserved.

NOTES
=====

   Part of "WWW Cyrillic Encoding Suite" Get docs and newest version from
http://www.neystadt.org/cyrillic/

   Copyright (c) 1997-98, John Neystadt <http://www.neystadt.org/john/>
You may install this script on your web site for free.  To obtain
permision for redistribution or any other usage contact john@neystadt.org.

   Drop me a line if you deploy this script on your site.

AUTHOR
======

   John Neystadt <john@neystadt.org>

SEE ALSO
========

   perl(1), Lingua::DetectCharset(3).

Perl module for string conversion between EBCDIC and ASCII
**********************************************************

NAME
====

   Convert::EBCDIC, ascii2ebcdic, ebcdic2ascii - Perl module for string
conversion between EBCDIC and ASCII

SYNOPSIS
========

     use Convert::EBCDIC;
     $ascii_string = ebcdic2ascii($ebcdic_string);
     $ebcdic_string = ascci2ebcdic($ascii_string);

     $translator = new Convert::EBCDIC;
     $translator = new Convert::EBCDIC($table);
     $ascii_string = $translator->toascii($ebcdic_string);
     $ebcdic_string = $translator->toebcdic($ascii_string);

     $Convert::EBCDIC::ccsid819

DESCRIPTION
===========

   This module can be used to import then functions ascii2ebcdic and/or
ebcdic2ascii or in an Object mode.

   Exported Functions:

ascii2ebcdic()
     takes as the first argument a EBCDIC string that is to be converted
     to ASCII using default converion table.

ebcdic2ascii()
     takes as the first argument a ASCII string that is to be converted to
     EBCDIC using default converion table.

   Object methods:

new()
     creates a new translator object.  Will take an optional argument
     being a 256 character conversion table.

toascii()
     takes and ASCII string and return and EBCDIC string.

toebcdic()
     takes and EBCDIC string and return and ASCII string.

   Translation tables:

$Convert::EBCDIC::ccsid819
     Character Code Set ID 00819.  This is the default on most systems.

$Convert::EBCDIC::ccsid1047
     Character Code Set ID 01047.  This is the default on OS390.

PORTABILITY
===========

   This module should work on any system with Perl 5.  Tested under SPARC
Solaris, OS390, HP-UX AS400/OS400 RISC.

AUTHOR
======

   Chris Leach <leachcj@bp.com>.

Perl extension for the Ethiopic information processing library.
***************************************************************

NAME
====

   Ethiopic - Perl extension for the Ethiopic information processing
library.

SYNOPSIS
========

     use Convert::Ethiopic;

DESCRIPTION
===========

   Convert::Ethiopic.pm is an interface to the LibEth Ethiopic programmers
library.

   Convert::Ethiopic.pm is not a comprehensive interface to the LibEth
library.  The LibEth Perl module is the minimal interface required by the
"Zobel" implementation of the LiveGe'ez Remote Processing Protocol.

STATUS
======

   This is the third release of the LibEth Perl module and requires the
"LibEth" library version 0.35c or later.

   The LibEth Perl Module is very early in its life cycle, extensions will
be made to further utilize the LibEth library through Perl as the need
arises.

BUGS
====

   None known at this time.

AUTHOR
======

   Daniel Yacob,
`LibEth@EthiopiaOnline.Net|mailto:LibEth@EthiopiaOnline.Net' in this node

SEE ALSO
========

   perl(1).  `http:' in this node

conversions of charset encodings for Ethiopic script
****************************************************

NAME
====

   Ethiopic::Cstocs - conversions of charset encodings for Ethiopic script

SYNOPSIS
========

     use LiveGeez::Request;
     require Convert::Ethiopic::Cstocs;
     my $r = LiveGeez::Request->new;

     ReadParse ( \%input );
     $r->ParseInput ( \%input );

     my $c = Convert::Ethiopic::Cstocs->new ( $r );

     print &$c ("`selam:");
     print $c->conv("`alem"), "\n";

     $r->{number} = 1991;

     print "The Year in Ethiopia is ", EthiopicNumber ( $r ), "\n";

DESCRIPTION
===========

   Ethiopic::Cstocs and Ethiopic::Time are designed as interfaces to the
methods in the Ethiopic:: module and is oriented as services for the
LiveGeez:: module.  In this version Ethiopic::Cstocs expects to receive an
object with hash elements using the keys:

   'sysInNum', 'xferInNum', 'sysOutNum', 'xferOutNum', 'fontOutNum',
'langNum', 'iPath', 'options', '7-bit', and 'number' if a numeral system
conversion is being performed.

   These keys are set when using a LiveGeez::Request object as shown in
the example.

AUTHOR
======

   Daniel Yacob,
`LibEth@EthiopiaOnline.Net|mailto:LibEth@EthiopiaOnline.Net' in this node

SEE ALSO
========

   perl(1).  LiveGeez(3).  `http:' in this node

conversions of charset encodings for Ethiopic script
****************************************************

NAME
====

   Ethiopic::System - conversions of charset encodings for Ethiopic script

SYNOPSIS
========

     use LiveGeez::Request;
     require Convert::Ethiopic::Cstocs;
     my $r = LiveGeez::Request->new;

     ReadParse ( \%input );
     $r->ParseInput ( \%input );

     my $c = Convert::Ethiopic::Cstocs->new ( $r );

     print &$c ("`selam:");
     print $c->conv("`alem"), "\n";

     $r->{number} = 1991;

     print "The Year in Ethiopia is ", EthiopicNumber ( $r ), "\n";

DESCRIPTION
===========

   Ethiopic::Cstocs and Ethiopic::Time are designed as interfaces to the
methods in the Ethiopic:: module and is oriented as services for the
LiveGeez:: module.  In this version Ethiopic::Cstocs expects to receive an
object with hash elements using the keys:

   'sysInNum', 'xferInNum', 'sysOutNum', 'xferOutNum', 'fontOutNum',
'langNum', 'iPath', 'options', '7-bit', and 'number' if a numeral system
conversion is being performed.

   These keys are set when using a LiveGeez::Request object as shown in
the example.

AUTHOR
======

   Daniel Yacob,
`LibEth@EthiopiaOnline.Net|mailto:LibEth@EthiopiaOnline.Net' in this node

SEE ALSO
========

   perl(1).  LiveGeez(3).  `http:' in this node

conversions of calendar systems to/from Ethiopic and Gregorian.
***************************************************************

NAME
====

   Ethiopic::Time - conversions of calendar systems to/from Ethiopic and
Gregorian.

SYNOPSIS
========

     use LiveGeez::Request;
     require Convert::Ethiopic::Time;
     my $r = LiveGeez::Request->new;

     ReadParse ( \%input );
     $r->ParseInput ( \%input );

     my $t = Convert::Ethiopic::Time->new ( $r );

     $t->GregorianToEthiopic;

     print "$t->{euDay}/$t->{euMonth}/$t->{euYear} = ";
     print "$t->{etDay}/$t->{etMonth}/$t->{etYear}\n"

DESCRIPTION
===========

   Ethiopic::Time and Ethiopic::Cstocs are designed as interfaces to the
methods in the Ethiopic:: module and is oriented as services for the
LiveGeez:: module.  In this version Ethiopic::Time expects to receive an
object with hash elements using the keys:

'calIn'
     which can be "euro or "ethio".

'date'
     a comma separated list as "day,month,year".

'LCInfo'
     locale settings *see the LibEth man pages*.

   These keys are set when using a LiveGeez::Request object as shown in
the example.

AUTHOR
======

   Daniel Yacob,
`LibEth@EthiopiaOnline.Net|mailto:LibEth@EthiopiaOnline.Net' in this node

SEE ALSO
========

   perl(1).  LiveGeez(3), `http:' in this node

Convert and generate geek code sequences.
*****************************************

NAME
====

   Convert::GeekCode - Convert and generate geek code sequences.

SYNOPSIS
========

     use Convert::GeekCode; # exports geek_decode()

     print geek_decode(<<'.'); # yes, that's author's geek code
     -----BEGIN GEEK CODE BLOCK-----
     Version: 3.12
     GB/C/CM/CS/CC/ED/H/IT/L/M/MU/P/SS/TW/AT d---x s+: a--- C++++ UB++++
     P++++$ L+ E--- W+++$ N++ o? K w++(++++) O-- M- V-- PS+++ PE Y+
     PGP- t+ 5? X+ R+++ !tv b++++ DI+++@ D++ G+++ e-- h* r+ z**
     ------END GEEK CODE BLOCK------
     .

DESCRIPTION
===========

   Convert::GeekCode converts and generates Geek Code `http:' in this node
sequences. It supports different charsets and user-customizable codesets.

AUTHORS
=======

   Autrijus Tang <autrijus@autrijus.org>

   Copyright (c) 2001 by Autrijus Tang.  All rights reserved.  This module
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

functions for manipulating mainframe data
*****************************************

NAME
====

   Convert::IBM390 - functions for manipulating mainframe data

SYNOPSIS
========

     use Convert::IBM390 qw(...those desired... or :all);

     $eb  = asc2eb($string);
     $asc = eb2asc($string);
     $asc = eb2ascp($string);

     $ebrecord = packeb($template, LIST...);
     @fields = unpackeb($template, $record);
     @lines = hexdump($string [,startaddr [,charset]]);

DESCRIPTION
===========

   *Convert::IBM390* supplies various functions that you may find useful
when messing with IBM System/3[679]0 data.  No functions are exported
automatically; you must ask for the ones you want.  "use ... qw(:all)"
exports all functions.

   By the way, this module is called "IBM390" because it will deal with
data from any mainframe operating system.  Nothing about it is specific to
MVS, VM, VSE, or OS/390.

FUNCTIONS
=========

asc2eb STRING
     Converts a character string from ASCII to EBCDIC.  The translation
     table is taken from the LE/370 code set converter EDCUI1EY; it
     translates ISO8859-1 to IBM-1047.  For more information, see "IBM
     C/C++ for MVS/ESA V3R2 Programming Guide", SC09-2164.

eb2asc STRING
     Converts a character string from EBCDIC to ASCII.  EBCDIC character
     strings ordinarily come from files transferred from mainframes via
     the binary option of FTP.  The translation table is taken from the
     LE/370 code set converter EDCUEYI1; it translates IBM-1047 to
     ISO8859-1 (see above).

eb2ascp STRING
     Like eb2asc, but the output will contain only printable ASCII
     characters.

packeb TEMPLATE LIST
     This function is much like Perl's built-in "pack".  It takes a list
     of values and packs it into an EBCDIC record (structure).  If called
     in list context, it will return a list of one element.  The TEMPLATE
     is patterned after Perl's pack template but allows fewer options.
     The following characters are allowed in the template:

          c  (1)  Character string without translation, padded with nulls
          C  (1)  Character string without translation, padded with native
                  spaces
          e  (1)  ASCII string to be translated into EBCDIC, padded with nulls
          E  (1)  ASCII string to be translated into EBCDIC, padded with EBCDIC
                  spaces
          h  (1)  A hexadecimal string, high nybble always first
          i  (2)  Signed integer (S/390 fullword)
          p  (1)  Packed-decimal field (default length = 8)
          s  (2)  Signed short integer (S/390 halfword)
          S  (2)  Unsigned short integer (2 bytes)
          x  (2)  A null byte
          z  (1)  Zoned-decimal field (default length = 8)
          @       Null-fill to absolute offset

          (1) May be followed by a number giving the length of the output field;
              or, for hexadecimal, the number of nybbles in the input.
          (2) May be followed by a number giving the repeat count.

     Each character may be followed by a number giving either the length
     of the field or a repeat count, as shown above.  Types 'i', 's', and
     'S' will gobble the specified number of items from the list; if '*' is
     given as the length, all the remaining items will be gobbled.  All
     other types will gobble only one item; you will usually want to give
     a length for the output field.  The following defaults apply:

          Conversion                No length given   '*' given
          Character string [cCeE]   1                 Same length as input
          Hex string [hH]           2                 Same length as input
          Decimal [pz]              8                 8

     The number must immediately follow the character, but whitespace may
     appear between field specifiers.

     The length for packed (p) or zoned (z) fields may include a number of
     decimal places, which is added after the byte count and a '.'.  For
     instance, "p3.2" indicates a 3-byte (5-digit) packed field with 2
     implied decimal places; if the corresponding list element is 24.68,
     the result will be x'02468C'.  Likewise, "z7.2" indicates a 7-byte
     (7-digit) zoned field with 2 implied decimal places; if the input is
     -35.79, the result will be '000357R' in EBCDIC.  The number of
     implied decimals may be greater than the number of digits, but such a
     specification will usually cause you to lose part of your value;
     e.g., packing .589 with "p3.6" would yield x'89000c'.  If the input
     is not a valid Perl number, the results are unpredictable (since they
     depend on internal Perl code), but most likely the output field will
     contain zero.

     Zoned output will always have an overpunch in the last byte for the
     sign (e.g., x'C1' (EBCDIC 'A') for +1 or x'D3' (EBCDIC 'L') for -3).
     If you want unsigned numbers, you can use sprintf() and then translate
     the result: e.g., `asc2eb(sprintf("%08d", $num))'.

     The ASCII-to-EBCDIC translation used by [Ee] is the same as in
     asc2eb().

     Either 'h' or 'H' may be used to request hexadecimal conversion.  This
     conversion is exactly the same as in the Perl pack function, except
     that the high nybble must always come first in the input.

     The maximum length of a packed field is 16 bytes; of a zoned field, 32
     bytes.  All other fields may have a maximum specifier (length or
     repeat count) of 32767.  These maxima are enforced.

unpackeb TEMPLATE RECORD
     This function is much like Perl's built-in "unpack".  It takes an
     EBCDIC record (structure) and unpacks it into a list of values.  If
     called in scalar context, it will return only the first unpacked
     value.  The TEMPLATE is patterned after Perl's unpack template but
     allows fewer options.  The following characters are allowed in the
     template:

          c or C (1)   Character string without translation
          e or E (1)   EBCDIC string to be translated into ASCII
          i      (2)   Signed integer (S/390 fullword)
          I      (2)   Unsigned integer (4 bytes)
          p      (1)   Packed-decimal field
          s      (2)   Signed short integer (S/390 halfword)
          S      (2)   Unsigned short integer (2 bytes)
          v      (2)   EBCDIC varchar string
          x      (1)   Ignore these bytes
          z      (1)   Zoned-decimal field

          (1) May be followed by a number giving the length of the field.
          (2) May be followed by a number giving the repeat count.

     Each character may be followed by a number giving either the length
     of the field or a repeat count, as shown above, or by '*', which means
     to use however many items are left in the string.  The number must
     immediately follow the character, but whitespace may appear between
     field specifiers.

     The length for packed (p) or zoned (z) fields may include a number of
     decimal places, which is added after the byte count and a '.'.  For
     instance, "p3.2" indicates a 3-byte (5-digit) packed field with 2
     implied decimal places; if this field contains x'02468C', the result
     will be 24.68.  Likewise, "z7.2" indicates a 7-byte (7-digit) zoned
     field with 2 implied decimal places; if this field contains '000357R'
     (in EBCDIC), the result will be -35.79.  The number of implied
     decimals may be greater than the number of digits; e.g., unpacking
     the packed field above with "p3.6" would yield 0.002468.  Zoned input
     fields may, but need not, have an overpunch sign in the last byte.
     If the field is not a valid packed or zoned field, the resulting
     element of the list will be undefined.

     Varchar (v) fields are assumed to consist of a signed halfword
     (16-bit) integer followed by EBCDIC characters.  If the number
     appearing in the initial halfword is N, the following N bytes are
     translated from EBCDIC to ASCII and returned as one string.  This
     format is used, for instance, by DB2/MVS.  A repeat count may be
     specified; e.g., "v2" does not mean a length of 2 bytes, but that
     there are two such fields in succession.  If the length is found to
     be less than 0, the resulting element of the list will be undefined.

     The EBCDIC-to-ASCII translation used by [Eev] is the same as in
     eb2asc().

     The maximum length of a packed field is 16 bytes; of a zoned field, 32
     bytes.  All other fields may have a maximum specifier (length or
     repeat count) of 32767.  These maxima are enforced.

     In most cases, you should use 'i' rather than 'I' when unpacking
     fullword integers.  Unsigned long integers are not handled cleanly by
     all systems.

hexdump STRING [STARTADDR [CHARSET]]
     Generates a hexadecimal dump of STRING.  The dump is similar to a
     SYSABEND dump in MVS: each line contains an address, 32 bytes of data
     in hexadecimal, and the same data in printable form.  This function
     returns a list of lines, each of which is terminated with a newline.
     This allows them to be printed immediately; for instance, you can say
     "print hexdump($crud);".

     The second and third arguments are optional.  The second specifies a
     starting address for the dump (default = 0); the third specifies the
     character set to use for the printable data at the end of each line
     ("ascii" or "ebcdic", in upper or lower case; default = ascii).

REFERENCES
==========

   IBM ESA/390 Principles of Operation, SA22-7201.

   IBM System/370 Principles of Operation, GA22-7000.

   IBM C/C++ for MVS/ESA V3R2 Programming Guide, SC09-2164.

BUGS
====

   None, of course.  What do you think this is - Unix?

AUTHOR
======

   Convert::IBM390 was written by Geoffrey Rommel <grommel@webley.com> in
January 1999.

OBSOLETE
********

NAME
====

   Convert::IBM390p - OBSOLETE

SYNOPSIS
========

   This synopsis intentionally left blank.

DESCRIPTION
===========

   *Convert::IBM390p* is now obsolete.  Install Convert::IBM390 instead.

Package to convert between ASCII text and MORSE alphabet.
*********************************************************

NAME
====

   Convert::Morse - Package to convert between ASCII text and MORSE
alphabet.

SYNOPSIS
========

     use Convert::Morse qw(as_ascii as_morse is_morsable);

     print as_ascii('.... . .-.. .-.. ---  -- --- .-. ... .'),"\n";
     						 # 'Helo Morse'
     print as_morse('Perl?'),"\n";		 # '.--. . .-. .-.. ..--..'
     print "Yes!\n" if is_morsable('Helo Perl.'); # print "Yes!"

REQUIRES
========

   perl5.6.0, Exporter

EXPORTS
=======

   Exports nothing on default, but can export as_ascii() and as_morse().

DESCRIPTION
===========

   This module lets you convert between normal ASCII text and international
Morse code. You can redefine the token sets, if you like.

INPUT
-----

   ASCII text can have both lower and upper case, it will be converted to
upper case prior to converting.

   Morse code input consists of dashes '-' and dots `'.''. The elements
*MUST NOT* to have spaces between, e.g. A is `'.-'' and not `'. -''.
Characters *MUST* have at least one space between. Additonal spaces are
left over to indicate word boundaries. This means `'.- -...'' means 'AB'
and and `'.-  -...'' means 'A B'.

   The conversion routines are designed to be stable and ignore/skip
unknown input, so that you can write:

     print as_ascii('Hello -- --- .-. ... .  Perl!');

   beware, though, a single '.' or '-' at the end will be interpreted as
'. ' respective '- ' and thus become 'E' or 'T'. Use
`Convert::Morse::error()' to check wether all went ok or not.

OUTPUT
------

   The output will always consist of upper case letters or, in case of
as_morse(), of `[-. ]'.

ERRORS
------

   Unknown tokens in the input are ignored/skipped. In these cases you get
the last error message with `Convert::Morse::error()'.

FUNCTIONS
=========

as_ascii()
----------

     as_ascii();

   Convert a Morse code text consisting of dashes and dots to ASCII.

as_morse()
----------

     as_morse();

   Convert a ASCII text to Morse code text consisting of dashes, dots and
spaces.

is_morse()
----------

     is_morse();

   Return wether input is a true Morse code string or not.

is_morsable()
-------------

     is_morseable();

   Return wether input can be completely expressed as Morse code or not.

error()
-------

     error();

   Returns the last error message or undef when no error occured.

LIMITATIONS
===========

   Can not yet do Japanese code nor German Umlaute.

BUGS
====

   None known yet.

AUTHOR
======

   Tels http://bloodgate.com in late 2000.

Conversion between Unicode and RACE
***********************************

NAME
====

   Convert::RACE - Conversion between Unicode and RACE

SYNOPSIS
========

     use Convert::RACE;

     $domain = to_race($utf16str);
     $utf16str = from_race($domain);

DESCRIPTION
===========

   This module provides functions to convert between RACE (Row-based
ASCII-Compatible Encoding) and Unicode Encodings.

   RACE converts strings with internationalized characters into strings of
US-ASCII that are acceptable as host name parts in current DNS host naming
usage.

   See http://www.ietf.org/internet-drafts/draft-ietf-idn-race-03.txt for
more details.

FUNCTION
========

   Following functions are provided; they are all in *@EXPORT* array.  See
Exporter, for details.

to_race($utf16)
     to_race() takes UTF-16 encoding and returns RACE-encoded strings such
     as 'bq-aewrcsy'.

     This function throws an exception such as 'String includes no
     internationalized characters', 'String too long' and 'Invalid encoding
     to compress'. Exceptions are thrown with Carp::croak(), so you can
     cath 'em with eval {};

from_race($domain_name)
     from_race() takes 'bq-' prefixed string and returns original UTF-16
     string.

     This function throws an exception such as 'String not begin with
     bq-', 'Decoded string includes no internationalized characters' and '
     Invalid format to decompress'. Exceptions are thrown with
     Carp::croak(), so you can cath 'em with eval {};

   See Unicode/String, Unicode/Map8,
see Jcode, for Unicode conversions.

CLASS METHOD
============

   Following class methods are provided to change the behaviour of
Convert::RACE.

prefix_tag()
     Set and get the domain prefix tag. By default, 'bq-'.

EXAMPLES
========

     use Jcode;
     use Unicode::String 'latin1';
     use Convert::RACE 'to_race';

     # EUC-japanese here
     $name = to_race(Jcode->new('ÆüËÜ¸ì','euc')->ucs2);

     # or, Latin here
     $name = to_race(latin1($latin_string)->utf16);

     # in doubt of exception
     eval { $name = to_race($utf); };
     if ($@) {
         warn "Can't encode to RACE: $@";
     }

     # change the prefix
     Convert::RACE->prefix_tag('xx--');

TODO AND CAVEATS
================

   * Using XS would be by far efficient.

   * No validation is done for the input UTF-16 string in to_race(). The
     internet draft says checking for prohibited name parts must be done
     before doing the conversion.

AUTHOR
======

   Tatsuhiko Miyagawa <miyagawa@bulknews.net>, with much help from Eugen
SAVIN <seugen@serifu.com>, Philip Newton <pne@cpan.org>, Michael J Schout
<mschout@gkg.net>.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   http://www.i-d-n.net/,
http://www.ietf.org/internet-drafts/draft-ietf-idn-race-03.txt, RFC 1035,
see Unicode/String, Jcode,
Convert/Base32.

make mapping functions between character sets
*********************************************

NAME
====

   Convert::Recode - make mapping functions between character sets

SYNOPSIS
========

     use Convert::Recode qw(ebcdic_to_ascii);

     while (<>) {
        print ebcdic_to_ascii($_);
     }

DESCRIPTION
===========

   The Convert::Recode module can provide mapping functions between
character sets on demand.  It depends on GNU recode to provide the raw
mapping data, i.e. GNU recode must be installed first.  The names of the
mapping functions are found by taking the name of the two charsets and
then joining them with the string "_to_".  If you want to convert between
the "mac" and the "latin1" charsets, then you just import the
mac_to_latin1() function.

   If you prefix the function name with "strict_" then characters that can
not be mapped are removed during transformation.  For instance the
strict_mac_to_latin1() function will convert to a string to latin1 and
remove all mac characters that have not corresponding latin1 character.

   Running the command `recode -l' should give you the list of character
sets available.

AUTHOR
======

   © 1997 Gisle Aas.

convert between different representations of perl scalars
*********************************************************

NAME
====

   Convert::Scalar - convert between different representations of perl
scalars

SYNOPSIS
========

     use Convert::Scalar;

DESCRIPTION
===========

   This module exports various internal perl methods that change the
internal representation or state of a perl scalar. All of these work
in-place, that is, they modify their scalar argument. No functions are
exported by default.

   The following export tags exist:

     :utf8   all functions with utf8 in their names
     :taint  all functions with taint in their names

utf8 scalar[, mode]
     Returns true when the given scalar is marked as utf8, false
     otherwise. If the optional mode argument is given, also forces the
     interpretation of the string to utf8 (mode true) or plain bytes (mode
     false). The actual (byte-) content is not changed. The return value
     always reflects the state before any modification is done.

     This function is useful when you "import" utf8-data into perl, or when
     some external function (e.g. storing/retrieving from a database)
     removes the utf8-flag.

utf8_on scalar
     Similar to `utf8 scalar, 1', but additionally returns the scalar (the
     argument is still modified in-place).

utf8_off scalar
     Similar to `utf8 scalar, 0', but additionally returns the scalar (the
     argument is still modified in-place).

utf8_valid scalar [Perl 5.7]
     Returns true if the bytes inside the scalar form a valid utf8 string,
     false otherwise (the check is independent of the actual encoding perl
     thinks the string is in).

utf8_upgrade scalar
     Convert the string content of the scalar in-place to its UTF8-encoded
     form (and also returns it).

utf8_downgrade scalar[, fail_ok=0]
     Attempt to convert the string content of the scalar from UTF8-encoded
     to ISO-8859-1. This may not be possible if the string contains
     characters that cannot be represented in a single byte; if this is
     the case, it leaves the scalar unchanged and either returns false or,
     if `fail_ok' is not true (the default), croaks.

utf8_encode scalar
     Convert the string value of the scalar to UTF8-encoded, but then turn
     off the `SvUTF8' flag so that it looks like bytes to perl again.
     (Might be removed in future versions).

utf8_length scalar
     Returns the number of characters in the string, counting wide UTF8
     characters as a single character, independent of wether the scalar is
     marked as containing bytes or mulitbyte characters.

unmagic scalar
     Removes magic from the scalar.

weaken scalar
     Weaken a reference. (See also WeakRef).

taint scalar
     Taint the scalar.

tainted scalar
     returns true when the scalar is tainted, false otherwise.

untaint scalar, type
     Remove the specified magic from the scalar (DANGEROUS!), see
     Perlguts (perl.info). See Untaint, for a
     similar but different interface.

grow scalar, newlen
     Sets the memory area used for the scalar to the given length, if the
     current length is less than the new value. This does not affect the
     contents of the scalar, but is only useful to "pre-allocate" memory
     space if you know the scalar will grow. The return value is the
     modified scalar (the scalar is modified in-place).

CANDIDATES FOR FUTURE RELEASES
------------------------------

   The following API functions (see Perlapi (perl.info)) are
considered for future inclusion in this module If you want them, write me.

     sv_upgrade
     sv_pvn_force
     sv_pvutf8n_force
     the sv2xx family

BUGS
====

   This module has not yet been extensively tested.

AUTHOR
======

     Marc Lehmann <pcg@goof.com>
     http://www.goof.com/pcg/marc/

Convert 'numbers' with scientific postfixes
*******************************************

NAME
====

   Convert::SciEng - Convert 'numbers' with scientific postfixes

SYNOPSIS
========

     #!/usr/local/bin/perl -w

     use strict;
     use Convert::SciEng

     my $c = Convert::SciEng->new('spice');
     my $s = Convert::SciEng->new('si');

     print "Scalar\n";
     print $c->unfix('2.34u'), "\n\n";

     print "Array\n";
     print join "\n", $c->unfix(qw( 30.6k  10x  0.03456m  123n 45o)), "\n";

     ##Note, default format is 5.5g
     print "Default format is %5.5g\n";
     print join "\n", $c->fix(qw( 35e5 0.123e-4 200e3 )), "";
     $c->format('%8.2f');
     print "Change the format is %8.2g\n";
     print join "\n", $c->fix(qw( 35e5 0.123e-4 200e3 )), "";

     print "Check out the SI conversion\n";
     print join "\n", $s->unfix(qw( 30.6K  10M  0.03456m  123n 45o)), "";

REQUIRES
========

   perl5.004_04 or greater, Carp

   I'm sorry if you get bit by the 5.004_04 but I believe in the Cathedral
model.  Keep current or suffer the penalties.

DESCRIPTION
===========

   Convert::SciEng supplies an object for converting numbers to and from
scientific notation with user-defined formatting.  Two different styles of
fix are supported, standard SI and SPICE:

     SPICE  =    P    T   g   x   k  ''    m    u    n     p     f     a
     SI     =    P    T   G   M   K  ''    m    u    n     p     f     a
     Fix    = 1e15 1e12 1e9 1e6 1e3 1e0 1e-3 1e-6 1e-9 1e-12 1e-15 1e-18

   Methods are supplied for creating the object and defining which fix
style it will use, and defining for format of numbers as they are
converted to scientific notation.

METHODS
=======

Creation
--------

Convert::SciEng->new('style');
     Creates and returns a new Number::SI object of the appropiate style,
     either `'si'' or `'spice''. The styles aren't case sensitive

$fix->format(FORMAT);
     Sets the format of number converter TO fix to be FORMAT.  FORMAT is
     any valid format to sprintf, like `'%5.5g'' or `'%6.4e''.  The
     default format is `'%5.5g''.

Conversion
----------

$fix->fix(0.030405); # 30.405m
     Convert a number to scientific notation with fixes.  Returns a string
     in the format given to it with the fix appended to the end.  Also
     works with arrays, with an array of strings being returned.

$fix->unfix('12u'); # 12e-06
     Convert a string from scientific notation.  Returns a number in
     exponential format.  Also works with arrays, with an array of numbers
     being returned.

   Note, by examining the module it should be relatively easy to figure out
how to create an object for any other scientific notation abbreviations.
If you think it is something that might be useful to others, then email me
and I'll add it to the module.

DIAGNOSTICS
===========

Unrecognized mode: MODE
     (F) Generated when you try specify an illegal mode like so:

     $a = Convert::SciEng->new('foo');

Illegal printf format: FORMAT
     (F) An illegal format was specified.  Valid formats must match the
     following regexp:

     `/^\%\d+(\.\d+)?([scduxoefg]|l[duxo])$/'

AUTHOR
======

   Colin Kuskie, colink@latticesemi.com

KUDOS
=====

   Many thanks to Steven McDougall for his comments about the content and
style of my module and for sending me his templates for module creation.
They can be found at:

   http://world.std.com/~swmcd/steven/Perl/index.html

   and I highly recommend them for beginning module writers.

   Also thanks to Tom Christiansen for the perltoot podpage.

Perl module to read TNEF files
******************************

NAME
====

     Convert::TNEF - Perl module to read TNEF files

SYNOPSIS
========

     use Convert::TNEF;

     $tnef = Convert::TNEF->read($iohandle, \%parms)
      or die Convert::TNEF::errstr;

     $tnef = Convert::TNEF->read_in($filename, \%parms)
      or die Convert::TNEF::errstr;

     $tnef = Convert::TNEF->read_ent($mime_entity, \%parms)
      or die Convert::TNEF::errstr;

     $tnef->purge;

     $message = $tnef->message;

     @attachments = $tnef->attachments;

     $attribute_value      = $attachments[$i]->data($att_attribute_name);
     $attribute_value_size = $attachments[$i]->size($att_attribute_name);
     $attachment_name = $attachments[$i]->name;
     $long_attachment_name = $attachments[$i]->longname;

     $datahandle = $attachments[$i]->datahandle($att_attribute_name);

DESCRIPTION
===========

     TNEF stands for Transport Neutral Encapsulation Format, and if you've
     ever been unfortunate enough to receive one of these files as an email
     attachment, you may want to use this module.

     read() takes as its first argument any file handle open
     for reading. The optional second argument is a hash reference
     which contains one or more of the following keys:

     output_dir - Path for storing TNEF attribute data kept in files
     (default: current directory).

     output_prefix - File prefix for TNEF attribute data kept in files
     (default: 'tnef').

     output_to_core - TNEF attribute data will be saved in core memory unless
     it is greater than this many bytes (default: 4096). May also be set to
     'NONE' to keep all data in files, or 'ALL' to keep all data in core.

     buffer_size - Buffer size for reading in the TNEF file (default: 1024).

     debug - If true, outputs all sorts of info about what the read() function
     is reading, including the raw ascii data along with the data converted
     to hex (default: false).

     display_after_err - If debug is true and an error is encountered,
     reads and displays this many bytes of data following the error
     (default: 32).

     debug_max_display - If debug is true then read and display at most
     this many bytes of data for each TNEF attribute (default: 1024).

     debug_max_line_size - If debug is true then at most this many bytes of
     data will be displayed on each line for each TNEF attribute
     (default: 64).

     ignore_checksum - If true, will ignore checksum errors while parsing
     data (default: false).

     read() returns an object containing the TNEF 'attributes' read from the
     file and the data for those attributes. If all you want are the
     attachments, then this is mostly garbage, but if you're interested then
     you can see all the garbage by turning on debugging. If the garbage
     proves useful to you, then let me know how I can maybe make it more
     useful.

     If an error is encountered, an undefined value is returned and the
     package variable $errstr is set to some helpful message.

     read_in() is a convienient front end for read() which takes a filename
     instead of a handle.

     read_ent() is another convient front end for read() which can take a
     MIME::Entity object (or any object with like methods, specifically
     open("r"), read($buff,$num_bytes), and close ).

     purge() deletes any on-disk data that may be in the attachments of
     the TNEF object.

     message() returns the message portion of the tnef object, if any.
     The thing it returns is like an attachment, but its not an attachment.
     For instance, it more than likely does not have a name or any
     attachment data.

     attachments() returns a list of the attachments that the given TNEF
     object contains.

     data() takes a TNEF attribute name, and returns a string value for that
     attribute for that attachment. Its your own problem if the string is too
     big for memory. If no argument is given, then the 'AttachData' attribute
     is assumed, which is probably the data you're looking for.

     name() is the same as data(), except the attribute 'AttachTitle' is
     assumed, which returns the 8 character + 3 character extension name of
     the attachment.

     longname() returns the long filename and extension of an attachment. This
     is embedded in the 'Attachment' attribute data, so we attempt to extract
     the name out of that.

     size() takes an TNEF attribute name, and returns the size in bytes for
     the data for that attachment attribute.

     datahandle() is a method for attachments which takes a TNEF attribute
     name, and returns the data for that attribute as an object which is
     the same as a MIME::Body object.  See MIME::Body for all the applicable
     methods. If no argument is given, then 'AttachData' is assumed.

EXAMPLES
========

     # Here's a rather long example where mail is retrieved
     # from a POP3 server based on header information, then
     # it is MIME parsed, and then the TNEF contents
     # are extracted and converted.

     use strict;
     use Net::POP3;
     use MIME::Parser;
     use Convert::TNEF;

     my $mail_dir = "mailout";
     my $mail_prefix = "mail";

     my $pop = new Net::POP3 ( "pop3server_name" );
     my $num_msgs = $pop->login("user_name","password");
     die "Can't login: $!" unless defined $num_msgs;

     # Get mail by sender and subject
     my $mail_out_idx = 0;
     MESSAGE: for ( my $i=1; $i<= $num_msgs;  $i++ ) {
      my $header = join "", @{$pop->top($i)};

     for ($header) {
      next MESSAGE unless
       /^from:.*someone\@somewhere.net/im &&
       /^subject:\s*important stuff/im
     }

     my $fname = $mail_prefix."-".$$.++$mail_out_idx.".doc";
     open (MAILOUT, ">$mail_dir/$fname")
      or die "Can't open $mail_dir/$fname: $!";
     # If the get() complains, you need the new libnet bundle
     $pop->get($i, \*MAILOUT) or die "Can't read mail";
     close MAILOUT or die "Error closing $mail_dir/$fname";
     # If you want to delete the mail on the server
     # $pop->delete($i);
      }

     close MAILOUT;
     $pop->quit();

     # Parse the mail message into separate mime entities
     my $parser=new MIME::Parser;
     $parser->output_dir("mimemail");

     opendir(DIR, $mail_dir) or die "Can't open directory $mail_dir: $!";
     my @files = map { $mail_dir."/".$_ } sort
      grep { -f "$mail_dir/$_" and /$mail_prefix-$$-/o } readdir DIR;
     closedir DIR;

     for my $file ( @files ) {
      my $entity=$parser->parse_in($file) or die "Couldn't parse mail";
      print_tnef_parts($entity);
      # If you want to delete the working files
      # $entity->purge;
     }

     sub print_tnef_parts {
      my $ent = shift;

     if ( $ent->parts ) {
      for my $sub_ent ( $ent->parts ) {
       print_tnef_parts($sub_ent);
      }
     } elsif ( $ent->mime_type =~ /ms-tnef/i ) {

     # Create a tnef object
     my $tnef = Convert::TNEF->read_ent($ent,{output_dir=>"tnefmail"})
      or die $Convert::TNEF::errstr;
     for ($tnef->attachments) {
      print "Title:",$_->name,"\n";
      print "Data:\n",$_->data,"\n";
     }

     # If you want to delete the working files
     # $tnef->purge;
       }
      }

SEE ALSO
========

   perl(1), IO::Wrap(3), MIME::Parser(3), MIME::Entity(3), MIME::Body(3)

CAVEATS
=======

     The parsing may depend on the endianness (see perlport) and width of
     integers on the system where the TNEF file was created. If this proves
     to be the case (check the debug output), I'll see what I can do
     about it.

AUTHOR
======

     Douglas Wilson, dwilson@gtemail.net

Perl module for string conversion among numerous character sets
***************************************************************

NAME
====

   Convert::Translit, transliterate, build_substitutes - Perl module for
string conversion among numerous character sets

SYNOPSIS
========

   use Convert::Translit;

     $translator = new Convert::Translit($result_chset);
     $translator = new Convert::Translit($orig_chset, $result_chset);
     $translator = new Convert::Translit($orig_chset, $result_chset, $verbose);

     $result_st = $translator->transliterate($orig_st);
     $result_st = Convert::Translit::transliterate($orig_st);

     build_substitutes Convert::Translit();

     Convert::Translit::build_substitutes();

DESCRIPTION
===========

   This module converts strings among 8-bit character sets defined by IETF
RFC 1345 (about 128 sets).  The RFC document is included so you can look
up character set names and aliases; it's also read by the module when
composing conversion maps.  Failing functions or objects return undef
value.

   Export_OK Functions:

transliterate()
     returns a string in $result_chset for an argument string in
     $orig_chset, transliterating by a map composed by new().

build_substitutes()
     rebuilds the file "substitutes" containing character definitions and
     approximate substitutions used when a character in $orig_chset isn't
     defined in $result_chset.  For example, "Latin capital A" may be
     substituted for "Latin capital A with ogonek".  It takes a long time
     to rebuild this file, but you should never need to.  Its only source
     of information is file "rfc1345".

   Object methods:

new()
     creates a new object for converting from $orig_chset to
     $result_chset, these being names (or aliases) of 8-bit character sets
     defined in RFC 1345.  If only one argument, then $orig_chset is
     assumed "ascii".  If three arguments, the third is verbosity flag.
     Verbose output lists approximate substitutions and other compromises.

transliterate()
     is same as the function of that name.

build_substitutes()
     is same as the function of that name.

FILES
=====

     Convert/Translit/rfc1345  (IETF RFC 1345, June 1992)
     Convert/Translit/substitutes

METHODOLGY
==========

   Only one-to-one character mapping is done, so characters with
diacritics (like A-ogonek) are never converted to (letter character,
diacritic character) pairs, rather are subject to simplification.  If no
approximate substitute is available, then a unrelated substitute is
chosen, preferably with the same code value.  Undefined $orig_chset
characters are translated to a chosen indicator character.
Transliteration is not guaranteed commutative when substitutions were
required.  An $orig_chset defined as 7-bit is assumed to be repeated to
make an 8-bit set (in the style of "extended ascii"); no such adjustment
is made for $result_chset.  The few mistakes in the RFC document are
corrected in the module.

EXAMPLES
========

     Convert Russian language text from IBM to ASCII encoding:
     $xxx = new Convert::Translit("EBCDIC-Cyrillic", "Cyrillic");
     $ascii_cyr_st = $xxx->transliterate($ibm_cyr_st);

     Convert from plain ASCII (default $orig_chset) to Latin2 (Central European):
     $yyy = new Convert::Translit("Latin2");
     $cnt_eur_st = $yyy->transliterate($ascii_st);

     Since plain ASCII is subset of Latin2, nothing is lost in transliteration.
     But going the other direction requires numerous simplifications:
     $zzz = new Convert::Translit("Latin2", "ascii");
     $ascii_st = $zzz->transliterate($cnt_eur_st);

     Back to ASCII again, although substitutions probably mean ($again ne $cnt_eur_st):
     $again = $yyy->transliterate($ascii_st);

     The example.pl script converts a Polish language phrase from Latin2 to EBCDIC-US.

PORTABILITY
===========

   Requires Perl version 5.  Developed with MacPerl on Macintosh 68040 OS
7.6.1.  Tested on Sun Unix 4.1.3.

AUTHOR
======

   Genji Schmeder <genji@community.net>

     Enjoy in good health.
     Cieszcie sie dobrym zdrowiem.
     Que gozen con salud.
     Benutze es heilsam gern!
     Genki dewa, yorokobi nasai.

COPYRIGHT
=========

   Version 1.03 dated 5 November 1997.  Copyright (c) 1997 Genji Schmeder.
All rights reserved. This program is free software; you can redistribute
it and/or modify it under the same terms as Perl itself.

ACKNOWLEDGEMENTS
================

     Chris Leach, author of EBCDIC.pm
     Keld Simonsen, author of RFC 1345

Perl module for uuencode and uudecode
*************************************

NAME
====

   Convert::UU, uuencode, uudecode - Perl module for uuencode and uudecode

SYNOPSIS
========

     use Convert::UU qw(uudecode uuencode);
     $encoded_string = uuencode($string,[$filename],[$mode]);
     ($string,$filename,$mode) = uudecode($string);
     $string = uudecode($string); # in scalar context

DESCRIPTION
===========

   uuencode() takes as the first argument a string that is to be
uuencoded. Note, that it is the string that is encoded, not a filename.
Alternatively a filehandle may be passed that must be opened for reading.
It returns the uuencoded string including begin and end. Second and third
argument are optional and specify filename and mode. If unspecified these
default to "uuencode.uu" and 644.

   uudecode() takes a string as argument which will be uudecoded. If the
argument is a filehandle this handle will be read instead. If it is a
reference to an ARRAY, the elements are treated like lines that form a
string. Leading and trailing garbage will be ignored. The function returns
the uudecoded string for the first begin/end pair. In array context it
returns an array whose first element is the uudecoded string, the second
is the filename and the third is the mode.

EXPORT
======

   Both uudecode and uuencode are in @EXPORT_OK.

AUTHOR
======

   Andreas Koenig <andreas.koenig@mind.de>. With code integrated that was
posted to USENET from Hans Mulder <hansm@wsinti05.win.tue.nl> and Randal
L. Schwartz <merlyn@teleport.com>.

SEE ALSO
========

   puuencode(1), puudecode(1) for examples of how to use this module.

Perl interface to the uulib library (a.k.a. uudeview/uuenview).
***************************************************************

NAME
====

   Convert::UUlib - Perl interface to the uulib library (a.k.a.
uudeview/uuenview).

SYNOPSIS
========

     use Convert::UUlib;

DESCRIPTION
===========

   Read the file uulibdoc.dvi.gz and the example-decoder source. Sorry -
more to come once people use me ;)

SMALL EXAMPLE DECODER
=====================

   The following code excerpt is a minimal decoder program. It reads all
files given on the commandline and decodes any files in it.

     use Convert::UUlib ':all';

     LoadFile($_) for @ARGV;

     for($i=0; $uu=GetFileListItem($i); $i++) {
        $uu->decode if $uu->state & FILE_OK;
     }

LARGE EXAMPLE DECODER
=====================

   This is the file `example-decoder' from the distribution, put here
instead of more thorough documentation.

     # decode all the files in the directory uusrc/ and copy
     # the resulting files to uudst/

     use Convert::UUlib ':all';

     sub namefilter {
        my($path)=@_;
        $path=~s/^.*[\/\\]//;
        $path;
     }

     sub busycb {
        my($action,$curfile,$partno,$numparts,$percent,$fsize)=@_;
        $_[0]=straction($action);
        print "busy_callback(",join(",",@_),")\n";
        0;
     }

     SetOption (OPT_IGNMODE, 1);
     SetOption (OPT_VERBOSE, 1);

     # show the three ways you can set callback functions
     SetFNameFilter (\&namefilter);

     SetBusyCallback ("busycb",333);

     SetMsgCallback (sub {
        my($msg,$level)=@_;
        print uc(strmsglevel($_[1])),": $msg\n";
     });

     for(<uusrc/*>) {
        my($retval,$count)=LoadFile ($_,$_,1);
        print "file($_), status(",strerror($retval),") parts($count)\n";
     }

     SetOption (OPT_SAVEPATH, "uudst/");

     $i=0;
     while($uu=GetFileListItem($i)) {
        $i++;
        print "file nr. $i";
        print " state ",$uu->state;
        print " mode ",$uu->mode;
        print " uudet ",strencoding($uu->uudet);
        print " size ",$uu->size;
        print " filename ",$uu->filename;
        print " subfname ",$uu->subfname;
        print " mimeid ",$uu->mimeid;
        print " mimetype ",$uu->mimetype;
        print "\n";

     # print additional info about all parts
     for($uu->parts) {
        while(my($k,$v)=each(%$_)) {
           print "$k > $v, ";
        }
        print "\n";
     }

     $uu->decode_temp;
     print " temporarily decoded to ",$uu->binfile,"\n";
     $uu->remove_temp;

     print strerror($uu->decode);
     print " saved as uudst/",$uu->filename,"\n";
      }

     print "cleanup...\n";

     CleanUp();

Exported constants
==================

   Action code constants:

     ACT_COPYING ACT_DECODING ACT_ENCODING
     ACT_IDLE    ACT_SCANNING

   File status flags:

     FILE_DECODED FILE_ERROR  FILE_MISPART
     FILE_NOBEGIN FILE_NODATA FILE_NOEND
     FILE_OK      FILE_READ   FILE_TMPFILE

   Message severity levels:

     MSG_ERROR MSG_FATAL MSG_MESSAGE
     MSG_NOTE  MSG_PANIC MSG_WARNING

   Options:

     OPT_BRACKPOL OPT_DEBUG     OPT_DESPERATE OPT_DUMBNESS
     OPT_ENCEXT   OPT_ERRNO     OPT_FAST      OPT_IGNMODE
     OPT_IGNREPLY OPT_OVERWRITE OPT_PREAMB    OPT_PROGRESS
     OPT_SAVEPATH OPT_TINYB64   OPT_USETEXT   OPT_VERBOSE
     OPT_VERSION

   Error/Result codes:

     RET_CANCEL RET_CONT  RET_EXISTS RET_ILLVAL RET_IOERR
     RET_NODATA RET_NOEND RET_NOMEM  RET_OK     RET_UNSUP

   Encoding types:

     B64ENCODED BH_ENCODED PT_ENCODED
     QP_ENCODED XX_ENCODED UU_ENCODED

Exported functions
==================

   Initializing and cleanup (Initialize is automatically called when the
module is loaded and allocates quite a bit of memory. CleanUp releases
that again).

     Initialize; # not normally necessary
     CleanUp;    # could be called at the end to release memory

   Setting and querying options:

     $option = GetOption OPT_xxx;
     SetOption OPT_xxx, opt-value;

   Error and action values => stringified:

     $msg = straction ACT_xxx;
     $msg = strerror RET_xxx;

   Setting various callbacks:

     SetMsgCallback [callback-function];
     SetBusyCallback [callback-function];
     SetFileCallback [callback-function];
     SetFNameFilter [callback-function];

   Call the currently selected FNameFilter:

     $file = FNameFilter $file;

   Loading sourcefiles, optionally fuzzy merge and start decoding:

     ($retval, $count) = LoadFile $fname, [$id, [$delflag]];
     $retval = Smerge $pass;
     $item = GetFileListItem $item_number;

   The procedural interface is undocumented, use the following methods
instead:

     $retval = $item->rename($newname);
     $retval = $item->decode_temp;
     $retval = $item->remove_temp;
     $retval = $item->decode([$target_path]);
     $retval = $item->info(callback-function);

   Querying (and setting) item attributes:

     $state    = $item->state;
     $mode     = $item->mode([newmode]);
     $uudet    = $item->uudet;
     $size     = $item->size;
     $filename = $item->filename([newfilename});
     $subfname = $item->subfname;
     $mimeid   = $item->mimeid;
     $mimetype = $item->mimetype;
     $binfile  = $item->binfile;

   Totally undocumented and unsupported(!):

     $parts = $item->parts;

   Functions below not documented and not very well tested:

     int	  QuickDecode		() ;
     int	  EncodeMulti		() ;
     int	  EncodePartial	() ;
     int	  EncodeToStream	() ;
     int	  EncodeToFile		() ;
     int	  E_PrepSingle		() ;
     int	  E_PrepPartial	() ;

AUTHOR
======

   Marc Lehmann <pcg@goof.com>, the original uulib library was written by
Frank Pilhofer <fp@informatik.uni-frankfurt.de>.

SEE ALSO
========

   perl(1), uudeview homepage at http://www.uni-frankfurt.de/~fp/uudeview/.

base object for performing unit conversions
*******************************************

NAME
====

   Convert::Units::Base - base object for performing unit conversions

DESCRIPTION
===========

   The Units package is a collection of modules for parsing strings with
unit measurements (such as "12pt" or "3 meters") and converting them to
some other unit (such as "picas" or "inches").

   It uses a base package (Units::Base) which does the dirty work. Other
modules define what units they handle and how they are related.

Why a Separate Module?
----------------------

   It is *intentionally* distinct from the *Math::Units* module. Why? The
*Math::Units* module implies that unit conversions are *exact*, with
one-to-one relationships.  This is fine for scientific work.  It's even
fine for some general purpose/real-world uses (such as converting
Fehrenheight to Celcius).

   Real-world measurement systems are conflicting. For instance, a "point"
in typography is equivalent to 1/72 inch, according to PostScript specs
and common usage. Other type systems consider it 1/72.27 inch, or 0.01383
inches, or 0.0148 inches.  Outside of that context, a point may be 1/120
or 1/144 inch.

   Common notations and abbreviations also depend on context. Does "12 pt"
mean "12 point", "12 parts" or "12 pints"?

   Even without conflicts in the definition of a particular unit, there's
no need to convert point sizes for fonts into miles or light-years.
Typesetters, surveyors and astronomers user different scales as well as
systems.

People do not think like computers
----------------------------------

   Not everyone uses the metric system.

   And even less people say things like "5.25 feet". Often it's "5 feet, 3
inches" or "5 1/4 feet".

   Despite having ten fingers and toes, people don't think in tens. They
think in twos, threes, fours, twelves, and sixteens. And sometimes they
use fractional measurements like quarter-inches, sixteenths-of-an-inch, or
half-pints.

   The purpose of this module is to allow people to use the measurement
systems they are familiar with, and that is appropriate to what they are
doing.

Rationale
---------

   The Units:: hierarchy is an attempt to keep measurement systems in
distinct classes. Thus one can have modules for converting between
typography units (points, picas) distinct from common units of length (or
area, temperature, etc.), specialized units (for Astronomy, Chemistry,
Physics, Textiles, Winery, Navigation, etc.) or even traditional or
regional systems (Japanese, Chinese, Egyptian, archaic systems, etc.)  and
to keep conflicting measurement systems distinct.

Release Notes
-------------

   The current distribution contains the following packages:

     Convert::Units::
     ::Base         - a base module that does all of the work
     ::Length       - a module for converting units of length
     ::Temperature  - a module for converting units of temperature
     ::Type         - a module for converting units of type

   Units::Base by itself does nothing. Another module needs to use it to
create definitions of what units of measurement it handles and how they
are related to each other (ie, 1 m = 100 cm).

   The base unit also allows for synonym and abbreviations to be defined.

   It also allows common "multiples" to be defined, so that it can handle
things like "18 half-points" or "6 dozen feet" or even convert millimters
to "sixteenths of an inch". (It does not yet handle Greek prefixes like
centi- or mega- ... those will have to be manually defined.)

Known Issues
------------

   The current release should be considered "beta" until further testing
and refinements have been made. Then again, maybe "alpha" is more accurate.

   The current version does not yet handle fractions such as "1/2 in".  It
should handle decimals such as "0.5 in".

   Relationships have been rewritten to be handle A(x+b) as well Ax.  They
may be redone in the future to handle more complex relationships, if the
need arises.

   Unit names much be defined as all lowercase, since strings are munged
with *lc()* before processing. In other words, if you define a unit name
as "F" or "Fahrenheight" you won't be able to use it.

Future Enhancements
-------------------

   Aside from bug fixes, optimizations, and making the string parsing
conform more to the "manifesto" above, obvious additions would be modules
for converting between units of area, volume, weight... (although if
*Math::Units* does what you need, use that instead.)

   An example hierarchy for future modules:

     Convert::Units::
     ::Length		- general measures of length
     ::Area
     ::Pressure
     ::Volume

     Convert::Units::Length
     ::Chinese		- specialized regional/traditional systems
     ::English

     Convert::Units::Astronomy
     ::Length		- or Distance...?

   Modules should share a common unit (preferably metric) to allow for
conversions.

REQUIRED MODULES
================

     Carp

SEE ALSO
========

   *Units::Length*, *Units::Temperature* and *Units::Type* modules, which
demonstrate how *Units::Base* is used.

AUTHOR
======

   Robert Rothenberg <wlkngowl@unix.asb.com>

LICENSE
=======

   Copyright (c) 1999-2000 Robert Rothenberg. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Coy (like Carp only prettier)
*****************************

NAME
====

     Coy (like Carp only prettier)

SYNOPSIS
========

     # In your application:
     # ====================

     use Coy;

     warn "There seems to be a problem";

     die "Looks like it might be fatal";

     # You can add vocab in the $HOME/.coyrc file:
     # ===========================================

     	    noun {
     			wookie =>
     			{
     				category => [ Sentient ],
     				sound    => [ "roars", "grunts", "bellows" ],
     				act      =>
     				{
     					sits   => { location => Arborial },

     fights => { minimum => 2,
     	    association => "argument",
     	  },
     				},
     			},

     };

     category {
     			Sentient =>
     			{
     				act =>
     				{
     					quarrels =>
     					{
     						associations => "argument",
     						location => Terrestrial,
     						minimum => 2,
     						synonyms => [qw(bickers argues)],
     					},
     					laughs =>
     					{
     						associations => "happy",
     						location => Terrestrial,
     						non_adjectival => 1,
     					},
     				},
     			}
     		     };

     personage "R2D2";
     personage "Darth Vader";

     place "Mos Eisley";
     place "the Death Star";

     tree "Alderaan mangrove";
     fruit_tree "Wookie-oak";

     # You can also select a different syllable counter via .coyrc
     # ===========================================================

     	    use Lingua::EN::Syllables::syllable;
     	    syllable_counter  "Lingua::EN::Syllables::syllable";

     # or

     use Lingua::EN::Syllables::syllable;
     syllable_counter  \&Lingua::EN::Syllables::syllable;

     # or

     syllable_counter  sub { return 1 };  # FAST BUT INACCURATE

DESCRIPTION
===========

     Error messages
     strewn across my terminal.
     A vein starts to throb.

     Their reproof adds the
     injury of insult to
     the shame of failure.

     When a program dies
     what you need is a moment
     of serenity.

     The Coy.pm
     module brings tranquillity
     to your debugging.

     The module alters
     the behaviour of C<die> and
     C<warn> (and C<croak> and C<carp>).

     It also provides
     C<transcend> and C<enlighten> -- two
     Zen alternatives.

     Like Carp.pm,
     Coy reports errors from the
     caller's point-of-view.

     But it prefaces
     the bad news of failure with
     a soothing haiku.

     The haiku are not
     "canned", but are generated
     freshly every time.

     Once the haiku is
     complete, it's prepended to
     the error message.

     Execution of
     the original call to
     C<die> or C<warn> resumes.

     Haiku and error
     message strew across my screen.
     A smile starts to form.

EXTENDING THE VOCABULARY
========================

     Any code placed in
     "$ENV{HOME}/.coyrc"
     runs at compile-time.

     You can use that file
     to extend Coy.pm's
     vocabulary.

     The "SYNOPSIS" at
     the start of this POD shows how
     you might set it up.

     (Eventually
      this section will detail the
      full mechanism.)

CHANGING THE SYLLABLE COUNTER
=============================

     If you don't like the
     syllable counter you can
     always replace it.

     Coy provides a sub
     called C<syllable_counter> for
     that very purpose.

     It is passed a sub
     reference. That sub is then used
     to count syllables.

     You can also pass
     the sub's I<name> (that is, pass a
     symbolic reference).

     The new counter sub
     should take a string and return
     its syllable count.

     C<syllable_counter>
     can be called from your code, or
     from .coyrc.

BUGS AND LIMITATIONS
====================

     In its current form,
     the module has four problems
     and limitations:

     * Vocabulary:
       The list of nouns and verbs is
       too small at present.

     This limits the range
     of topics that the haiku
     produced can cover.

     That in turn leads to
     tell-tale repetition (which
     fails the Turing test).

     Extending the range
     of words Coy.pm can
     use is no problem

     (though finding the time
     and the creativity
     required may be :-).

     Users of Coy are
     encouraged to add their own
     vocabulary.

     (See the "SYNOPSIS",
      and also "EXTENDING THE
      VOCABULARY").

     	* Associations:
     The vocabulary has
     too few topic links.

     Hence it's often not
     able to find relevant
     words for a message.

     This leads to haiku
     utterly unrelated
     to the error text.

     Again, there is no
     technical difficulty
     in adding more links:

     Defining enough
     associations isn't
     hard, just tedious.

     User-specified
     vocabularies can solve
     this problem as well.

     	* Limited grammar:
     The number of syntactic
     templates is too small.

     This leads to haiku
     that are (structurally, at
     least) monotonous.

     Yet again, this needs
     no technical solution,
     just time and effort.

     Of course, such enhanced
     templates might require richer
     vocabulary.

     For example, verb
     predicates would need extra
     database structure:

     Each verb entry would
     have to be extended with
     links to object nouns.

     	* Syllable counting:
     This is perhaps the major
     problem at present.

     The algorithmic
     syllable counter is still
     being developed.

     It is currently
     around 96%
     accurate (per word).

     This means that correct
     syllable counts for haiku
     can't be guaranteed.

     Syllable counts for
     single words are correct to
     plus-or-minus 1.

     In a multi-word
     haiku these errors cancel
     out in most cases.

     Thus, the haiku tend
     to be correct within one
     or two syllables.

     As the syllable
     counter slowly improves, this
     problem will abate.

     Alteratively,
     you can choose to use your own
     syllable counter.

     (See above in the
      section titled "CHANGING THE
      SYLLABLE COUNTER".)

AUTHOR
======

     The Coy.pm
     module was developed by
     Damian Conway.

COPYRIGHT
=========

     Copyright (c) 1998, Damian Conway. All Rights Reserved.
           This module is free software. It may be used, redistributed
           and/or modified under the terms of the Perl Artistic License
        (see http://www.perl.com/perl/misc/Artistic.html)

Beowulf encryption
******************

NAME
====

   Crypt::Beowulf - Beowulf encryption

SYNOPSIS
========

     use Crypt::Beowulf;

     my $cipher = BeoEncrypt( $text, $passphrase );
     my $plain = BeoDecrypt( $text, $passphrase );

     # Or you can do the encryption and decryption with
     # the same method, as follows:

     my $encrypted = BeoCrypt( $text, $passphrase, "e");
     my $decrypted = BeoCrypt( $text, $passphrase, "d");

NOTICE
======

   Although I have used this module, personally, a great deal, it has not
undergone extensive public testing.  As such, it should still be
considered to be beta software.  If anyone encounters a problem, bug, or
loophole, please email me at ceo@neurogames.com.  And I'm open to any
suggestions that anyone may have to improved either the module or the
algorithm itself.

DESCRIPTION
===========

   I originally designed this system in response to a need for an
encryption scheme for Neurogames that encrypted text using a fairly
standard character set, as opposed to the various and sundry
control-characters and meta-characters that end up being part of the
ciphertext when using extent encryption modules, such as Crypt::TripleDES
and Crypt::GOST.  Personally, I ran into several cross-platform problems
with the control characters being mis-interpreted by one OS or another, or
by text-editing software. In theory at least, the fairly standard ASCII
set used by Crypt::Beowulf should remedy that matter.  Another advantage
is that it is substantially faster than encrypting with TripleDES or GOST.
Based on benchmarks encrypting the same text, Crypt::Beowulf is between 3
and 10 times faster than either Crypt::GOST or Crypt::TripleDES.  The code
is based on 95-element permutation (95!, or approx. 1.033 * 10^148
possible combinations). It should hold up fairly well against brute-force
deciphering, though in theory, there could be some sort of shortcut to
cracking the code, of which I'm unaware.

   Please note that in the event that a passphrase is less than 10
characters long, "x" will be padded to the end to reach a minimum of 10
characters. In theory, there is no upper limit to the length of the
passphrase.  In addition, for the particularly security-conscious, this
encryption method supports multiple encryption, so after encrypting your
text, you can encrypt the cipher text as many times as you wish
(personally, I've never tested this over more than approx. 10 passes), and
decryption of a like number of times will be necessary to get the plain
text.  If one were so inclined, the passphrase could be changed for each
pass.  If you do this, remember to decrypt using the multiple passphrases
in reverse order.

METHODS
=======

*BeoEncrypt*( $plaintext, $passphrase );
     Encrypts $plaintext using $passphrase to initialize the randomization.

*BeoDecrypt*( $cyphertext, $passphrase );
     Same as BeoEncrypt, only in the other direction.

*BeoCrypt*( $text, $passphrase, $mode );
     Encryption and decryption included in one nice, neat little package.
     If we are encrypting, pass a value of "e" for $mode, if we're
     decrypting, pass a value of "d".

LIMITATIONS
===========

   Due to the nature of the of the ordered code stream, this system is
really only designed to be used on text files, or to a lesser degree, word
processing documents.  The program doesn't like control-characters or
meta-characters,  and subsequently ignores them.  For example, graphic
files encrypted with Beowulf will not decrypt correctly.

AUTHOR
======

   Kurt Kincaid, ceo@neurogames.com

Perl Blowfish encryption module
*******************************

NAME
====

   Crypt::Blowfish - Perl Blowfish encryption module

SYNOPSIS
========

     use Crypt::Blowfish;

     Blowfish is capable of strong encryption and can use key sizes up
     to 56 bytes (a 448 bit key).  You're encouraged to take advantage
     of the full key size to ensure the strongest encryption possible
     from this module.

DESCRIPTION
===========

   The module implements the Crypt::CBC interface.  You're encouraged to
read the perldoc for Crypt::CBC if you intend to use this module for
Cipher Block Chaining.

   Crypt::CBC has the following methods:

blocksize =item keysize =item encrypt =item decrypt
FUNCTIONS
=========

blocksize
     Returns the size (in bytes) of the block cipher.

keysize
     Returns the size (in bytes) of the key.

new
          my $cipher = new Crypt::Blowfish $key;

     This creates a new Crypt::Blowfish BlockCipher object, using $key,
     where $key is a key of `keysize()' bytes.

encrypt
          my $cipher = new Crypt::Blowfish $key;
          my $ciphertext = $cipher->encrypt($plaintext);

     This function encrypts $plaintext and returns the $ciphertext where
     $plaintext and $ciphertext should be of `blocksize()' bytes.

decrypt
          my $cipher = new Crypt::Blowfish $key;
          my $plaintext = $cipher->decrypt($ciphertext);

     This function decrypts $ciphertext and returns the $plaintext where
     $plaintext and $ciphertext should be of `blocksize()' bytes.

EXAMPLE
=======

     my $key = pack("H16", "0123456789ABCDEF");
     my $cipher = new Crypt::Blowfish $key;
     my $ciphertext = $cipher->encrypt("plaintex");	# NB - 8 bytes
     print unpack("H16", $ciphertext), "\n";

PLATFORMS
=========

   Crypt::Blowfish has been tested *successfully* against the following:

     Linux 2.2.X (RH6.X, Mandrake 6.5)
     Solaris 2.7 SPARC
     FreeBSD 3.4
     FreeBSD 3.3
     HP-UX B.10.20 (using HP's cc)

   Crypt::Blowfish has been tested and *failed* against the following:

     FreeBSD 3.2
     Win32

NOTES
=====

   To use the CBC mode, you must use Crypt::CBC version 1.22 or higher.

SEE ALSO
========

   Crypt::CBC, Crypt::DES, Crypt::IDEA

   Bruce Schneier, *Applied Cryptography*, 1995, Second Edition, published
by John Wiley & Sons, Inc.

COPYRIGHT
=========

   The implementation of the Blowfish algorithm was developed by, and is
copyright of, A.M. Kuchling.  Other parts of the perl extension and module
are copyright of Systemics Ltd ( http://www.systemics.com/ ). Code
revisions, updates, and standalone release is the copyright of W3Works,
LLC.

AUTHOR
======

   Original algorithm, Bruce Shneier.  Original implimentation, A.M.
Kuchling.  Original Perl impilmentation, Systemics Ltd.

   Current revision and maintainer:  Dave Paris <amused@pobox.com>

THANKS
======

   To my wonderful wife for her patience & love.  To EFNet #perl, to
infobot #perl, to the folks that helped test this module.  A special
thanks to my friends for guidance and support.  Perl couldn't have had
this module without ya'll.

Blowfish encryption algorithm implemented purely in Perl
********************************************************

NAME
====

   *Crypt::Blowfish_PP* - Blowfish encryption algorithm implemented purely
in Perl

SYNOPSIS
========

   `use Crypt::Blowfish_PP';

   $blowfish=new Crypt::Blowfish_PP($key);

   $ciphertextBlock=$blowfish->encrypt($plaintextBlock);

   $plaintextBlock=$blowfish->decrypt($ciphertextBlock);

DESCRIPTION
===========

   The *Crypt::Blowfish_PP* module provides for users to use the Blowfish
encryption algorithm in perl. The implementation is entirely Object
Oriented, as there is quite a lot of context inherent in making blowfish
as fast as it is. The key is anywhere between 64 and 448 bits (8 and 56
bytes), and should be passed as a packed string. The transformation itself
is a 16-round Feistel Network, and operates on a 64 bit block.

   Object methods for the Crypt::Blowfish_PP module:

new(key)
--------

   The new() method initialises a blowfish object with the key that is
passed.  This is the slow part of doing a blowfish encryption or
decryption, as it initialises the 18 p-boxes and the 1024 s-boxes that are
used for the algorithm.  It will return undef if the key is not of a valid
length.

encrypt(block)
--------------

   The encrypt() method uses the initialised blowfish object to encrypt 8
bytes of data of the string passed to it. It returns the encrypted block.

decrypt(block)
--------------

   The decrypt() method uses the initialised blowfish object to decrypt 8
bytes of data of the string passed to it. It returns the decrypted block.

COMMENTS
========

   This is probably crap software, but hey, its for general use. I'm happy
to patch it with other people's code... :)

   If you want speed, then see the Crypt::Blowfish module.

AUTHOR
======

   Matthew Byng-Maddick <`mbm@colondot.net'>

SEE ALSO
========

   http://www.counterpane.com/,see Crypt/CBC,

Encrypt Data with Cipher Block Chaining Mode
********************************************

NAME
====

   Crypt::CBC - Encrypt Data with Cipher Block Chaining Mode

SYNOPSIS
========

     use Crypt::CBC;
     $cipher = new Crypt::CBC('my secret key','IDEA');
     $ciphertext = $cipher->encrypt("This data is hush hush");
     $plaintext = $cipher->decrypt($ciphertext);

     $cipher->start('encrypting');
     open(F,"./BIG_FILE");
     while (read(F,$buffer,1024)) {
         print $cipher->crypt($buffer);
     }
     print $cipher->finish;

DESCRIPTION
===========

   This module is a Perl-only implementation of the cryptographic cipher
block chaining mode (CBC).  In combination with a block cipher such as DES
or IDEA, you can encrypt and decrypt messages of arbitrarily long length.
The encrypted messages are compatible with the encryption format used by
*SSLeay*.

   To use this module, you will first create a new Crypt::CBC cipher
object with new().  At the time of cipher creation, you specify an
encryption key to use and, optionally, a block encryption algorithm.  You
will then call the start() method to initialize the encryption or
decryption process, crypt() to encrypt or decrypt one or more blocks of
data, and lastly finish(), to flush the encryption stream.  For your
convenience, you can call the encrypt() and decrypt() methods to operate
on a whole data value at once.

new()
-----

     $cipher = new Crypt::CBC($key,$algorithm);

   The new() method creates a new Crypt::CBC object.

   You must provide an encryption/decryption key, which can be any series
of characters of any length.  Internally, the actual key used is derived
from the MD5 hash of the key you provide.  The optional second argument is
the block encryption algorithm to use, specified as a package name.  You
may use any block encryption algorithm that you have installed.  At the
time this was written, only two were available on CPAN, Crypt::DES and
Crypt::IDEA.  You may refer to them using their full names ("Crypt::IDEA")
or in abbreviated form ("IDEA".)  If no algorithm is provided, DES is
assumed.

start()
-------

     $cipher->start('encrypting');
     $cipher->start('decrypting');

   The start() method prepares the cipher for a series of encryption or
decryption steps, resetting the internal state of the cipher if necessary.
You must provide a string indicating whether you wish to encrypt or
decrypt.  "E" or any word that begins with an "e" indicates encryption.
"D" or any word that begins with a "d" indicates decryption.

crypt()      $ciphertext = $cipher->crypt($plaintext);
------------------------------------------------------

   After calling start(), you should call crypt() as many times as
necessary to encrypt the desired data.

finish()
--------

     $ciphertext = $cipher->finish();

   The CBC algorithm must buffer data blocks inernally until they are even
multiples of the encryption algorithm's blocksize (typically 8 bytes).
After the last call to crypt() you should call finish().  This flushes the
internal buffer and returns any leftover ciphertext.

   In a typical application you will read the plaintext from a file or
input stream and write the result to standard output in a loop that might
look like this:

     $cipher = new Crypt::CBC('hey jude!');
     $cipher->start('encrypting');
     print $cipher->crypt($_) while <>;
     print $cipher->finish();

encrypt()
---------

     $ciphertext = $cipher->encrypt($plaintext)

   This convenience function runs the entire sequence of start(), crypt()
and finish() for you, processing the provided plaintext and returning the
corresponding ciphertext.

decrypt()
---------

     $plaintext = $cipher->decrypt($ciphertext)

   This convenience function runs the entire sequence of start(), crypt()
and finish() for you, processing the provided ciphertext and returning the
corresponding plaintext.

encrypt_hex(), decrypt_hex()
----------------------------

     $ciphertext = $cipher->encrypt_hex($plaintext)
     $plaintext  = $cipher->decrypt_hex($ciphertext)

   These are convenience functions that operate on ciphertext in a
hexadecimal representation.  *encrypt_hex($plaintext)* is exactly
equivalent to *unpack('H*',encrypt($plaintext))*.  These functions can be
useful if, for example, you wish to place the encrypted information into
an e-mail message, Web page or URL.

EXAMPLES
========

   Two examples, des.pl and idea.pl can be found in the eg/ subdirectory
of the Crypt-CBC distribution.  These implement command-line DES and IDEA
encryption algorithms.

LIMITATIONS
===========

   The encryption and decryption process is about a tenth the speed of the
equivalent SSLeay programs (compiled C).  This could be improved by
implementing this module in C.  It may also be worthwhile to optimize the
DES and IDEA block algorithms further.

BUGS
====

   None that I know of.

AUTHOR
======

   Lincoln Stein, lstein@cshl.org

SEE ALSO
========

   perl(1), Crypt::DES(3), Crypt::IDEA(3)

Easy things make really easy with Crypt::CBC
********************************************

NAME
====

   Crypt::CBCeasy - Easy things make really easy with Crypt::CBC

SYNOPSIS
========

     use Crypt::CBCeasy; # !!! YOU can not 'require' this module !!!

     IDEA::encipher($my_key, "plain-file", "crypted-file");

     $plain_text = DES::decipher($my_key, \*CRYPTO_FILE);

     $crypted = Blowfish::encipher($my_key, \*PLAIN_SOCKET);

ABSTRACT
========

   This module is just a helper for Crypt::CBC to make simple and usual
jobs just one-liners.

   The current version of the module is available at CPAN.

DESCRIPTION
===========

   After you call this module as

     use Crypt::CBCeasy IMPORT-LIST;

   it creates the `encipher()' and `decipher()' functions in all
namespaces (packages) listed in the `IMPORT-LIST'.

   Without the `IMPORT-LIST' it creates these 2 functions in the *DES::*,
*IDEA::* and *Blowfish::* namespaces by default to stay compatible with
the previous versions that were capable to handle only these 3 ciphers.

   You have to install `Crypt::CBC' v. 1.22 or later to work with
`Blowfish'.

   Sure IDEA:: functions will work only if you have Crypt::IDEA installed,
DES:: - if you have Crypt::DES, Blowfish:: - if you have Crypt::Blowfish
and Crypt::CBC is version 1.22 or above etc.

   Here's the list of the ciphers that could be called via the
`Crypt::CBCeasy' interface today (in fact the same modules that are
`Crypt::CBC' compatible):

     Cipher          CPAN module

     DES             Crypt::DES
     IDEA            Crypt::IDEA
     Blowfish        Crypt::Blowfish
     Twofish2        Crypt::Twofish2
     DES_PP          Crypt::DES_PP
     Blowfish_PP     Crypt::Blowfish_PP

   Note that cipher names are case sensitive in the `IMPORT-LIST', so
"blowfish" will give an error.  Type them exactly as they are written in
the correspondent underlying modules.

   Both `encipher()' and `decipher()' functions take 3 parameters:

     1 - en/decryption key
     2 - source
     3 - destination

   The sources could be: an existing file, a scalar (just a string that
would be encrypted), an opened filehandle, any other object that inherits
from the filehandle, for example IO::File or FileHandle object, and socket.

   Destinations could be any of the above except scalar, because we can not
distinguish between scalar and output file name here.

   Well, it's easier to look at the examples:

   ($fh vars here are IO::Handle, IO::File or FileHandle objects,
variables of type "GLOB", "GLOB" refs or sockets)

   *IDEA::encipher(* $my_key, "in-file", "out-file" *);*

   *IDEA::encipher(* $my_key, *IN, "out-file" *);*

   *IDEA::encipher(* $my_key, \*IN, "out-file" *);*

   *IDEA::encipher(* $my_key, $fh_in, "out-file" *);*

   *IDEA::encipher(* $my_key, "in-file", *OUT *);*

   *IDEA::encipher(* $my_key, "in-file", \*OUT *);*

   *IDEA::encipher(* $my_key, "in-file", $fh_out *);*

   *IDEA::encipher(* $my_key, *IN, *OUT *);*

   *IDEA::encipher(* $my_key, \*IN, \*OUT *);*

   *IDEA::encipher(* $my_key, $fh_in, $fh_out *);*

   *IDEA::encipher(* $my_key, $plain_text, "out-file" *);*

   *IDEA::encipher(* $my_key, $plain_text, *OUT *);*

   *IDEA::encipher(* $my_key, $plain_text, \*OUT *);*

   *IDEA::encipher(* $my_key, $plain_text, $fh_out *);*

   any of the above will work and do what was expected.

   In addition there is a 2-argument version that returns it's result as
scalar:

   $crypted_text = *IDEA::encipher(* $my_key, $plain_text *);*

   $crypted_text = *IDEA::encipher(* $my_key, "in-file" *);*

   $crypted_text = *IDEA::encipher(* $my_key, *IN *);*

   $crypted_text = *IDEA::encipher(* $my_key, \*IN *);*

   $crypted_text = *IDEA::encipher(* $my_key, $fh *);*

   All the same is possible for any of the ciphers in the `IMPORT-LIST'.

   All functions croak on errors (such as "input file not found"), so if
you want to trap errors use them inside the `eval{}' block and check the
`$@'.

   Note that all filehandles are used in binmode whether you claimed them
binmode or not. On Win32 for example this will result in CRLF's in
$plain_text after

     $plain_text = DES::decipher($my_key, "crypted_file");

   if "crypted_file" was created by

     DES::encipher($my_key, "text_file", "crypted_file");

   If the filehandle was used before - it's your job to rewind it to the
beginning and/or close.

INSTALLATION
============

   As this is just a plain module no special installation is needed. Put it
into the /Crypt subdirectory somewhere in your @INC. The standard

     Makefile.PL
     make
     make test
     make install

   procedure is provided. In addition

     make html

   will produce the HTML-docs.

   This module requires

   Crypt::CBC at least 1.20 by Lincoln Stein, lstein@cshl.org

   one or more of

   Crypt::IDEA, Crypt::DES, Crypt::Blowfish, Crypt::Blowfish_PP,
Crypt::Twofish2, Crypt::DES_PP or other Crypt::CBC compatible modules.

CAVEATS
=======

   This module has been created and tested in a Win95/98/2000Pro
environment with Perl 5.004_02 and ActiveState ActivePerl build 618.  I
expect it to function correctly on other systems too.

CHANGES
=======

     0.21   Mon Mar  6 07:28:41 2000  -  first public release

     0.22   Sun Feb 18 13:11:59 2001
     	A horrible BUG was found by Michael Drumheller <drumheller@alum.mit.edu>
     	In fact 0.21 was ALWAYS using DES despite of the desired cipher.
     	DAMN!
     	Fixed.
     	And the test is modified so that this will never happen again.

     Now you can define the list of ciphers that are compatible
     with Crypt::CBC in the import list.
     You can not call this module with the "require" statement. This
     is incompatible with the older versions.

TODO
====

   Any suggestions are much appreciated.

BUGS
====

   Please report.

VERSION
=======

   This man page documents "Crypt::CBCeasy" version 0.22

   February 18, 2001

AUTHOR
======

   Mike Blazer, blazer@mail.nevalink.ru

   http://base.dux.ru/guest/fno/perl/

SEE ALSO
========

   Crypt::CBC

COPYRIGHT
=========

   Copyright (C) 2000-2001 Mike Blazer.

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl module implementing CipherSaber encryption.
************************************************

NAME
====

   Crypt::CipherSaber - Perl module implementing CipherSaber encryption.

SYNOPSIS
========

     use Crypt::CipherSaber;
     my $cs = Crypt::CipherSaber->new('my pathetic secret key');

     my $coded = $cs->encrypt('Here is a secret message for you');
     my $decoded = $cs->decrypt($coded);

DESCRIPTION
===========

   The Crypt::CipherSaber module implements CipherSaber encryption,
described at http://ciphersaber.gurus.com.  It is simple, fairly speedy,
and relatively secure algorithm based on RC4.

   Encryption and decryption are done based on a secret key, which must be
shared with all intended recipients of a message.

METHODS
=======

*new($key, $N)*
     Initialize a new Crypt::CipherSaber object.  $key, the key used to
     encrypt or to decrypt messages is required.  $N is optional.  If
     provided and greater than one, it will implement CipherSaber-2
     encryption (slightly slower but more secure).  If not specified, or
     equal to 1, the module defaults to CipherSaber-1 encryption.  $N must
     be a positive integer greater than one.

encrypt($message)
     Encrypt a message.  This uses the key stored in the current
     Crypt::CipherSaber object.  It will generate a 10-byte random IV
     (Initialization Vector) automatically, as defined in the RC4
     specification.  This returns a string containing the encrypted
     message.

     Note that the encrypted message may contain unprintable characters,
     as it uses the extended ASCII character set (valid numbers 0 through
     255).

decrypt($message)
     Decrypt a message.  For the curious, the first ten bytes of an
     encrypted message are the IV, so this must strip it off first.  This
     returns a string containing the decrypted message.

     The decrypted message may also contain unprintable characters, as the
     CipherSaber encryption scheme can handle binary files with fair ease.
     If this is important to you, be sure to treat the results correctly.

*crypt($iv, $message)*
     If you wish to generate the IV with a more cryptographically secure
     random string (at least compared to Perl's builtin rand() function),
     you may do so separately, passing it to this method directly.  The IV
     must be a ten-byte string consisting of characters from the extended
     ASCII set.

     This is generally only useful for encryption, although you may
     extract the first ten characters of an encrypted message and pass
     them in yourself.  You might as well call decrypt(), though.  The
     more random the IV, the stronger the encryption tends to be.  On some
     operating systems, you can read from /dev/random.  Other approaches
     are the Math::TrulyRandom module, or compressing a file, removing the
     headers, and compressing it again.

AUTHOR
======

   chromatic <chromatic@wgz.org>

   thanks to jlp for testing, moral support, and never fearing the icky
details and to the fine folks at http://perlmonks.org

SEE ALSO
========

   the CipherSaber home page at http://ciphersaber.gurus.com

   perl(1), rand().

Perl interface to DES block cipher
**********************************

NAME
====

   DES - Perl interface to DES block cipher

SYNOPSIS
========

     use Crypt::DES;

DESCRIPTION
===========

   This perl extension is an implementation of the DES block cipher
algorithm.  The module implements the Crypt::BlockCipher interface, which
has the following methods

blocksize =item keysize =item encrypt =item decrypt
FUNCTIONS
=========

blocksize
     Returns the size (in bytes) of the block cipher.

keysize
     Returns the size (in bytes) of the key.

new
          my $cipher = new DES $key;

     This creates a new DES BlockCipher object, using $key, where $key is
     a key of `keysize()' bytes.

encrypt
          my $cipher = new DES $key;
          my $ciphertext = $cipher->encrypt($plaintext);

     This function encrypts $plaintext and returns the $ciphertext where
     $plaintext and $ciphertext should be of `blocksize()' bytes.

decrypt
          my $cipher = new DES $key;
          my $plaintext = $cipher->decrypt($ciphertext);

     This function decrypts $ciphertext and returns the $plaintext where
     $plaintext and $ciphertext should be of `blocksize()' bytes.

EXAMPLE
=======

     my $key = pack("H16", "0123456789ABCDEF");
     my $cipher = new DES $key;
     my $ciphertext = $cipher->encrypt("plaintex");	# NB - 8 bytes
     print unpack("H16", $ciphertext), "\n";

SEE ALSO
========

   Crypt::IDEA

   Bruce Schneier, *Applied Cryptography*, 1995, Second Edition, published
by John Wiley & Sons, Inc.

COPYRIGHT
=========

   The implementation of the DES algorithm was developed by, and is
copyright of, Eric Young (eay@mincom.oz.au).  Other parts of this perl
extension are copyright of Systemics Ltd ( http://www.systemics.com/ ).

Perl extension for DES encryption
*********************************

NAME
====

   Crypt::DES_PP - Perl extension for DES encryption

SYNOPSIS
========

   use Crypt::DES_PP;

     $des = Crypt::DES_PP->new ($key);
     $cipher = $des->encrypt ($plain);
     $plain = $des->decrypt ($cipher);
     $blocksize = $des->blocksize;
     $keysize = $des->keysize;

DESCRIPTION
===========

   The Data Encryption Standard (DES), also known as Data Encryption
Algorithm  (DEA) is a semi-strong encryption and decryption algorithm.

   The module is 100 % compatible to Crypt::DES but is implemented
entirely in Perl.  That means that you do not need a C compiler to build
and install this extension.

   The module implements the Crypt::CBC interface.  You are encouraged to
read the documentation for Crypt::CBC if you intend to use this module for
Cipher Block Chaining.

   The minimum (and maximum) key size is 8 bytes.  Shorter keys will cause
an exception, longer keys will get silently truncated.  Data is encrypted
and decrypted in blocks of 8 bytes.

   The module implements the Ultra-Fast-Crypt (UFC) algorithm as found for
example in the GNU libc.  On the Perl side a lot has been done in order to
make the module as fast as possible (function inlining, use integer, ...).

   Note: For performance issues the source code for the module is first
preprocessed by m4.  That means that you need an m4 macro processor in
order to hack on the sources.  This is of no concern for you if you only
want to use the module, the preprocessed output is always included in the
distribution.

BUGS
====

   Nothing known.  The module has not been tested on 64 bit architectures.

AUTHOR
======

   This implementation was written by Guido Flohr (guido@imperia.net).  It
is available under the terms of the Lesser GNU General Public License
(LGPL) version 2 or - at your choice - any later version, see the file
"COPYING.LIB".

   The original C implementation of the Ultra-Fast-Crypt algorithm was
written by Michael Glad (glad@daimi.aau.dk) and has been donated to the
Free Software Foundation, Inc.  It is covered by the GNU library license
version 2, see the file "COPYING.LIB".

SEE ALSO
========

   Crypt::CBC(3), Crypt::DES(3), perl(1), m4(1).

Encrypt Data using ECB Mode
***************************

NAME
====

   Crypt::ECB - Encrypt Data using ECB Mode

SYNOPSIS
========

   Use Crypt::ECB OO style

     use Crypt::ECB;

     $crypt = Crypt::ECB->new;
     $crypt->padding(PADDING_AUTO);
     $crypt->cipher("Blowfish") || die $crypt->errstring;
     $crypt->key("some_key");

     $enc = $crypt->encrypt("Some data.");
     print $crypt->decrypt($enc);

   or use the function style interface

     use Crypt::ECB qw(encrypt decrypt encrypt_hex decrypt_hex);

     $ciphertext = encrypt($key2, "Blowfish", "Some data", PADDING_AUTO);
     $plaintext  = decrypt($key2, "Blowfish", $ciphertext, PADDING_AUTO);

     $hexcode = encrypt_hex("foo_key", "IDEA", $plaintext);
     $plain   = decrypt_hex("foo_key", "IDEA", "A01B45BC");

DESCRIPTION
===========

   This module is a Perl-only implementation of the ECB mode.  In
combination with a block cipher such as DES, IDEA or Blowfish, you can
encrypt and decrypt messages of arbitrarily long length.  Though for
security reasons other modes than ECB such as CBC should be preferred.
See textbooks on cryptography if you want to know why.

   The functionality of the module can be accessed via OO methods or via
standard function calls.  Remember that some crypting module like for
example Blowfish has to be installed.  The syntax follows that of
Crypt::CBC meaning you can access Crypt::ECB exactly like Crypt::CBC,
though Crypt::ECB is more flexible.  For example you can change the key or
the cipher without having to create a new crypt object.

METHODS
=======

new(), key(), cipher(), padding()
---------------------------------

     $crypt = Crypt::ECB->new;
     $crypt->key("Some_key");
     $crypt->cipher("Blowfish") || die $crypt->errstring;
     $crypt->padding(PADDING_AUTO);

     print $crypt->key;
     print $crypt->cipher;
     print $crypt->padding;

     $crypt = Crypt::ECB->new("Some_key","Blowfish");
     $crypt->cipher || die "'Blowfish' wasn't loaded for some reason.";

   new() initializes the variables it uses.  Optional parameters are key
and cipher.  If called without parameters you have to call key() and
*cipher()* before you can start crypting.  If called with key but without
cipher, for compatibility with Crypt::CBC 'DES' is assumed.

   key() sets the key if given a parameter.  It always returns the key.
Note that some crypting modules require keys of definite length.  For
example the Crypt::Blowfish module expects an eight byte key.

   *cipher()* sets the block cipher to be used if given a parameter.  It
tries to load the corresponding module.  If an error occurs, it returns 0
and sets $crypt->{Errstring}.  Otherwise it returns the cipher name.  Free
packages available for Perl are for example Blowfish, DES or IDEA. If
called without parameter it just returns the name of the cipher.

   *padding()* sets the way how data is padded up to a multiple of the
cipher's blocksize.  Until now two ways are implemented: When set to
PADDING_NONE, no padding is done.  You then have to take care of correct
padding (and truncating) yourself. When set to PADDING_AUTO, the ECB
module handles padding (and truncating when decrypting) the same way
Crypt::CBC does.

   By default the padding style is set to PADDING_NONE.  This means if you
don't bother and your data has not the correct length, the module will
complain and therefore force you to think about what you really want.

start(), mode(), crypt(), finish()
----------------------------------

     $crypt->start('encrypt') || die $crypt->errstring;
     $enc  = $crypt->crypt($data1)
          . $crypt->crypt($data2)
          . $crypt->finish;

     $crypt->start('decrypt');
     print $crypt->mode;

   start() sets the crypting mode and checks if all required variables
like key and cipher are set.  Allowed parameters are any words starting
either with 'e' or 'd'.  The Method returns the mode which is set or 0 if
an error occurred.

   mode() is called without parameters and just returns the mode which is
set.

   crypt() processes the data given as argument.  If called without
argument $_ is processed.  The method returns the processed data.  Cipher
and key have to be set in order to be able to process data.  If some of
these are missing or start() was not called before, the method dies.

   After having sent all data to be processed to crypt() you have to call
finish() in order to flush data that's left in the buffer.

caching()
---------

     $crypt->caching(1); # caching on
     $crypt->caching(0); # caching off

     print $crypt->caching;

   The caching mode is returned.  If given an argument caching mode is set.
Caching is on if caching() evaluates true, otherwise caching is off.  By
default caching is on.

   What is this caching?  The Crypt::ECB module communicates with the
cipher module via some object.  Creating the cipher object takes some time
for the cipher module has to do some initialization.  Now caching means
that the same cipher object is used until caching is turned off or the key
or the cipher module are changed.  If caching is off, a new cipher object
is created is created each time crypt() or finish() are called and
destroyed at the end of these methods.  Crypting using caching is *much*
faster than without caching.

encrypt(), decrypt(), encrypt_hex(), decrypt_hex()
--------------------------------------------------

     $enc = $crypt->encrypt($data);
     print $crypt->decrypt($enc);

     $hexenc = $crypt->encrypt_hex($data);
     print $crypt->decrypt_hex($hexenc);

   encrypt() and decrypt() are convenience methods which call start(),
crypt() and finish() for you.

   *encrypt_hex()* and *decrypt_hex()* are convenience functions that
operate on ciphertext in a hexadecimal representation.  They are exactly
equivalent to

     $hexenc = join('',unpack('H*',$crypt->encrypt($data)));
     print $crypt->decrypt(pack('H*',$hexenc));

   These functions can be useful if, for example, you wish to place the
encrypted information into an e-mail message, Web page or URL.

errstring()
-----------

     print $crypt->errstring;

   Some methods like *cipher()* or start() return 0 if an error occurs.
You can then retrieve a more detailed error message by calling
$crypt->errstring.

VARIABLES
=========

   Variables which could be of interest to the outside world are:

     $crypt->{Key},
     $crypt->{Cipher},
     $crypt->{Module},
     $crypt->{Keysize},
     $crypt->{Blocksize},
     $crypt->{Mode},
     $crypt->{Caching},
     $crypt->{Padding},
     $crypt->{Errstring}.

   The variables should not be set directly, use instead the above
described methods.  Reading should not pose a problem, but is also
provided by the above methods.

CONSTANTS
=========

   The two constants naming the padding styles are exported by default:

     PADDING_NONE => 0
     PADDING_AUTO => 1

FUNCTIONS
=========

   For convenience en- or decrypting can also be done by calling ordinary
functions.  The functions are: encrypt(), decrypt(), *encrypt_hex*,
*decrypt_hex*.  The module is smart enough to recognize whether these
functions are called in an OO context or not.

encrypt(), decrypt(), encrypt_hex(), decrypt_hex()
--------------------------------------------------

     $ciphertext = encrypt($key, $cipher, $plaintext, PADDING_AUTO);
     $plaintext  = decrypt($key, $cipher, $ciphertext, PADDING_AUTO);

     $ciphertext = encrypt_hex($key, $cipher, $plaintext, PADDING_AUTO);
     $plaintext  = decrypt_hex($key, $cipher, $ciphertext, PADDING_AUTO);

   encrypt() and decrypt() process the provided text and return either the
corresponding ciphertext (encrypt) or plaintext (decrypt).  Data and
padstyle are optional, but remember that by default no padding is done.
If data is omitted, $_ is assumed.

   *encrypt_hex()* and *decrypt_hex()* operate on ciphertext in a
hexadecimal representation. Otherwise usage is the same as for encrypt()
and decrypt().

BUGS
====

   None that I know of.

TODO
====

   The other block cipher modes CBC, CFB and OFB could be implemented.

   Convenience encrypt and decrypt functions utilizing base64 encoding
could be added.

COPYING
=======

   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.

AUTHOR
======

   Christoph Appel, cappel@debis.com

SEE ALSO
========

   perl(1), Crypt::DES(3), Crypt::IDEA(3), Crypt::CBC(3)

A module for accessing GnuPG functionality.
*******************************************

NAME
====

   Crypt::GPG - A module for accessing GnuPG functionality.

SYNOPSIS
========

     use Crypt::GPG;
     $gpg = new Crypt::GPG;

     $gpg->gpgbin ($path_to_gpg);     # The GnuPG executable.
     $gpg->gpgopts ($option);         # Extra options for the GnuPG command.
     $gpg->secretkey ($keyid);        # Set ID of default secret key.
     $gpg->passphrase ($passphrase);  # Set passphrase.
     $gpg->armor ($boolean);          # Switch ASCII armoring on/off.
     $gpg->detach ($boolean);         # Switch detached signatures on/off.
     $gpg->encryptsafe ($boolean);    # Switch paranoid encryption on/off.
     $gpg->version ($versionstring);  # Set version string.
     $gpg->comment ($commentstring);  # Set comment string.
     $gpg->debug ($boolean);          # Switch debugging output on/off.

     $signed = $gpg->sign (@message);
     @recipients = $gpg->msginfo (@ciphertext);
     $ciphertext = $gpg->encrypt (\@plaintext, \@recipients);
     ($signature, $plaintext) = $gpg->verify (\@ciphertext, [ \@message ]);

     $status = $gpg->keygen
       ($name, $email, $keytype, $keysize, $expire, $passphrase);
     $gpg->addkey (\@key, $pretend);
     @keys = $gpg->keyinfo (@ids);

     (The methods below will likely be encapsulated into the
     Crypt::GPG::Key class in a future release, bewarned!)

     $key = $keys[0];
     $gpg->delkey ($key);
     $gpg->disablekey ($key);
     $gpg->enablekey ($key);
     $keystring = $gpg->export ($key);
     $gpg->keypass ($key, $oldpassphrase, $newpassphrase);

DESCRIPTION
===========

   The Crypt::GPG module provides near complete access to GnuPG
functionality through an object oriented interface. It provides methods
for encryption, decryption, signing, signature verification, key
generation, key export and import, and most other key management functions.

   This module works almost identically to its cousin, Crypt::PGP5. The
two modules together provide an almost uniform interface to deal with both
PGP and GPG. Eventually, these module will be folded into a single module
which will interface with GPG as well as all versions of PGP.

CONSTRUCTOR
===========

new ()
     Creates and returns a new Crypt::GPG object.

DATA METHODS
============

*gpgbin ()*
     Sets the *GPGBIN* instance variable which gives the path to the GnuPG
     binary.

*gpgopts ()*
     Sets the *GPGOPTS* instance variable which may be used to pass
     additional options to the GnuPG binary. For proper functioning of this
     module, it is advisable to always include '-lock-multiple' in the
     GPGOPTS string.

*secretkey ()*
     Sets the *SECRETKEY* instance variable which may be a KeyID or a
     username. This is the ID of the default key to use for signing.

*passphrase ()*
     Sets the *PASSPHRASE* instance variable, required for signing and
     decryption.

*armor ()*
     Sets the *ARMOR* instance variable. If set to 0, Crypt::GPG doesn't
     ASCII armor its output. Else, it does. Default is to use
     ascii-armoring. I haven't tested the methods in this module without
     ASCII armoring yet.

*detach ()*
     Sets the *DETACH* instance variable. If set to 1, the sign method
     will produce detached signature certificates, else it won't. The
     default is to produce detached signatures.

*encryptsafe ()*
     Sets the *ENCRYPTSAFE* instance variable. If set to 1, encryption
     will fail if trying to encrypt to a key which is not trusted. This is
     the default. Switch to 0 if you want to encrypt to untrusted keys.

*version ()*
     Sets the VERSION instance variable which can be used to change the
     Version: string on the GnuPG output to whatever you like.

*comment ()*
     Sets the *COMMENT* instance variable which can be used to change the
     Comment: string on the GnuPG output to whatever you like.

*debug ()*
     Sets the DEBUG instance variable which causes the raw output of
     Crypt::GPG's interaction with the GnuPG binary to be dumped to STDOUT.

OBJECT METHODS
==============

*sign (@message)*
     Signs *@message* with the secret key specified with *secretkey ()*
     and returns the result as a string.

*decrypt ( \@message, [ \@signature ])*
     Decrypts and/or verifies the message in *@message*, optionally using
     the detached signature in *@signature*, and returns the plaintext
     message as a string, along with a Crypt::GPG::Signature object
     corresponding to the signature on the message, if the message was
     signed.

*msginfo (@ciphertext)*
     Returns a list of the recipient key IDs that *@ciphertext* is
     encrypted to.

*encrypt (\@plaintext, \@keylist)*
     Encrypts *@plaintext* with the public keys of the recipients listed
     in *@keylist* and returns the result in a string, or undef if there
     was an error while processing. Returns undef if any of the keys are
     not found.

*addkey (\@key, $pretend)*
     Adds the keys given in *@key* to the user's key ring and returns a
     list of Crypt::GPG::Key objects corresponding to the keys that were
     added. If *$pretend* is true, it pretends to add the key and creates
     the key object, but doesn't actually perform the key addition.

*export ($key)*
     Exports the key specified by the Crypt::GPG::Key object $key and
     returns the result as a string.

*keygen ($name, $email, $keytype, $keysize, $expire, $passphrase)*
     Creates a new keypair with the parameters specified. The only
     supported *$keytype* is 'ELG-E'. *$keysize* can be any of 768, 1024,
     2048, 3072 or 4096. Returns undef if there was an error, otherwise
     returns a filehandle that reports the progress of the key generation
     process similar to the way GnuPG does. The key generation is not
     complete till you read an EOF from the returned filehandle.

*keyinfo (@keyids)*
     Returns an array of Crypt::GPG::Key objects corresponding to the Key
     IDs listed in *@keyids*.

*parsekeys (@keylist)*
     Parses a raw GnuPG formatted key listing in *@keylist* and returns an
     array of Crypt::GPG::Key objects.

*keypass ($key, $oldpass, $newpass)*
     Change the passphrase for a key. Returns true if the passphrase change
     succeeded, false if not, or undef if there was an error.

*delkey ($keyid)*
     Deletes the key specified by the Crypt::GPG::Key object $key from the
     user's key ring. Returns undef if there was an error, or 1 if the key
     was successfully deleted.

*disablekey ($keyid)*
     Disables the key specified by the Crypt::GPG::Key object $key.

*enablekey ($keyid)*
     Enables the key specified by the Crypt::GPG::Key object $key.

BUGS
====

   * Error checking needs work.

   * Some key manipulation functions are missing.

   * The method call interface is subject to change in future versions,
     specifically, key manipulation methods will be encapsulated into the
     Crypt::GPG::Key class in a future version.

   * The current implementation will probably eat up all your RAM if you
     try to operate on huge messages. In future versions, this will be
     addressed by reading from and returning filehandles, rather than using
     in-core data.

   * Methods may break if you don't use ASCII armoring.

AUTHOR
======

   Crypt::GPG is Copyright (c) 2000 Ashish Gulhati <hash@netropolis.org>.
All Rights Reserved.

ACKNOWLEDGEMENTS
================

   Thanks to Barkha for inspiration and lots of laughs; to the GnuPG team
and Phil Zimmerman; and of-course, to Larry Wall, Richard Stallman, and
Linus Torvalds.

LICENSE
=======

   This code is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   It would be nice if you would mail your patches to me, and I would love
to hear about projects that make use of this module.

DISCLAIMER
==========

   This is free software. If it breaks, you own both parts.

Perl extension implementing one way hash chaining encryption using MD5
**********************************************************************

NAME
====

   Crypt::HCE_MD5 - Perl extension implementing one way hash chaining
encryption using MD5

SYNOPSIS
========

     use Crypt::HCE_MD5;

     $hce_md5 = Crypt::HCE_MD5->new("SharedSecret", "Random01,39j309ad");
     $hce_md5 = Crypt::HCE_MD5->new('KEYBUG', "TheSecret", "junk o rama");

     $crypted = $hce_md5->hce_block_encrypt("Encrypt this information");
     $info = $hce_md5->hce_block_decrypt($crypted);

     $mime_crypted = $hce_md5->hce_block_encode_mime("Encrypt and Base64 this information");
     $info = $hce_md5->hce_block_decode_mime($mime_crypted);

DESCRIPTION
===========

   This module implements a chaining block cipher using a one way hash.
This method of encryption is the same that is used by radius (RFC2138) and
is also described in Applied Cryptography.

   Two interfaces are provided in the module.  The first is straight block
encryption/decryption the second does base64 mime encoding/decoding of the
encrypted/decrypted blocks.

   The idea is the the two sides have a shared secret that supplies one of
the keys and a randomly generated block of bytes provides the second key.
The random key is passed in cleartext between the two sides.

   An example client and server are packaged as modules with this module.
They are used in the tests.  They can also be found in the examples
directory.

   The 'KEYBUG' flag is for decrypting data encrypted with an older
version of Crypt::HCE_MD5.  There was a bug in the chaining portion that
prevented the full 16 bytes of the previous block from being using in
creating the chaining hash.  Decrypt your old data and re-encrypt it
without the KEYBUG flag.

   The release after this one will have the KEYBUG feature removed, but
I'll leave this version on CPAN

   Thanks to Jake Angerman for pointing out the weakness.

AUTHOR
======

   Eric Estabrooks, eric@urbanrage.com

SEE ALSO
========

   perl(1).

Perl extension implementing one way hash chaining encryption using SHA
**********************************************************************

NAME
====

   Crypt::HCE_SHA - Perl extension implementing one way hash chaining
encryption using SHA

SYNOPSIS
========

     use Crypt::HCE_SHA;

     $hce_sha = Crypt::HCE_SHA->new("SharedSecret", "Random01,39j309ad");

     $crypted = $hce_sha->hce_block_encrypt("Encrypt this information");
     $info = $hce_sha->hce_block_decrypt($crypted);

     $mime_crypted = $hce_sha->hce_block_encode_mime("Encrypt and Base64 this information");
     $info = $hce_sha->hce_block_decode_mime($mime_crypted);

DESCRIPTION
===========

   This module implements a chaining block cipher using a one way hash.
This method of encryption is the same that is used by radius (RFC2138) and
is also described in Applied Cryptography.

   Two interfaces are provided in the module.  The first is straight block
encryption/decryption the second does base64 mime encoding/decoding of the
encrypted/decrypted blocks.

   The idea is the the two sides have a shared secret that supplies one of
the keys and a randomly generated block of bytes provides the second key.
The random key is passed in cleartext between the two sides.

   An example client and server are packaged as modules with this module.
They are used in the tests. They can be found in the examples directory.

   Thanks to Jake Angerman for the bug report on the bug in key generation
for the chaining portion of the algorithm

AUTHOR
======

   Eric Estabrooks, eric@urbanrage.com

SEE ALSO
========

   perl(1).

Perl interface to IDEA block cipher
***********************************

NAME
====

   IDEA - Perl interface to IDEA block cipher

SYNOPSIS
========

     use Crypt::IDEA;

DESCRIPTION
===========

   This perl extension is an implementation of the IDEA block cipher
algorithm.  The module implements the Crypt::BlockCipher interface, which
has the following methods

blocksize =item keysize =item encrypt =item decrypt
FUNCTIONS
=========

blocksize
     Returns the size (in bytes) of the block cipher.

keysize
     Returns the size (in bytes) of the key.

new
          my $cipher = new IDEA $key;

     This creates a new IDEA BlockCipher object, using $key, where $key is
     a key of `keysize()' bytes.

encrypt
          my $cipher = new IDEA $key;
          my $ciphertext = $cipher->encrypt($plaintext);

     This function encrypts $plaintext and returns the $ciphertext where
     $plaintext and $ciphertext should be of `blocksize()' bytes.

decrypt
          my $cipher = new IDEA $key;
          my $plaintext = $cipher->decrypt($ciphertext);

     This function decrypts $ciphertext and returns the $plaintext where
     $plaintext and $ciphertext should be of `blocksize()' bytes.

EXAMPLE
=======

     my $key = pack("H32", "0123456789ABCDEF0123456789ABCDEF");
     my $cipher = new IDEA $key;
     my $ciphertext = $cipher->encrypt("plaintex");	# NB - 8 bytes
     print unpack("H16", $ciphertext), "\n";

SEE ALSO
========

   Crypt::DES

   Bruce Schneier, *Applied Cryptography*, 1995, Second Edition, published
by John Wiley & Sons, Inc.

COPYRIGHT
=========

   This implementation is copyright Systemics Ltd (
http://www.systemics.com/ ).

   The IDEA algorithm is patented in Europe and the United States by
Ascom-Tech AG.

   Module altered on 22 May 1999 to allow functionality with perl -MCPAN,
Changes by Dave Paris  (edited lib paths).

module for programmatic PGP 2.x on Unix
***************************************

NAME
====

   Crypt::PGP2 - module for programmatic PGP 2.x on Unix

DESCRIPTION
===========

   Perl module wrapper for Unix PGP 2.x

   You can get PGP from
ftp://ftp.cert.dfn.de/pub/tools/crypt/pgp/pgpi/2.x/src/

   This module:

   * is a wrapper that does parameter validation and provides application
     isolation from the external pgp program

   * returns the PGP banner and error constants.

PARAMETERS
==========

   The parameters are positional:

     $plaintext   Plaintext that you want to encrypt.
     		(mandatory)

     $key         keyring id of recipient who has a public key.
     		(mandatory)

     $options     PGP options you want, limited to any combination of 'a', and 't'.
                  # -a means ASCII armour, needed when emailing ciphertext
                  # -t means portable text newlines, needed for portability
     		(Optional - default is -feat)

RETURN CODES
============

     encrypt returns a list of 3 scalars like this: ($ciphertext, $message, $error)

     $ciphertext    Ciphertext result of encrypting $Plaintext.

     $message       pgp statement and pgp banner returned from external program

     $error         error status from this program

     PGP_ERR_SUCCESS       - success
     PGP_ERR_FAIL          - failure to start external command
     PGP_ERR_BAD_OPTIONS   - optional pgp options invalid
     PGP_ERR_MISSING_KEY   - mandatory keyring ID missing
     PGP_ERR_MISSING_TEXT  - mandatory plaintext missing

SAMPLE PROGRAM
==============

     #!/usr/bin/perl -Tw

     $ENV{'PATH'} = '';

     use strict;      # must scope all symbols
     use diagnostics; # lint checking and verbose warnings

     use Crypt::PGP2;

     my $plaintext = 'Sample plaintext';
     my ($ciphertext, $msg, $error) = encrypt($plaintext,'james','at');

     if ($error == PGP_ERR_SUCCESS) {
        print "Ciphertext: $ciphertext\nMsg: $msg\nError: $error\n";
     }
     else {
        print "PGP error: $error\n";
     }

NOTES
=====

     PGP creates temporary work files, but we don't have
     control over this. This may be a security and reliability problem
     that you should investigate.

     Note that to encrypt a message, the only key required is the
     public key of the recipient. No private keys are required,
     so not even your private keyring needs to be on the same
     machine as the webserver. Only when signing a message or
     deciphering a message is a private key or keyring required.

     Your minimum key length should be 1024 bits and should be changed
     regularly.

BUGS
====

   See Notes for general concerns. This module relies on Open3, which may
not be supported on Windows NT. Only recent versions of Open3 do not leak
memory.

AUTHORS
=======

   james@rf.net

VERSION
=======

   See $VERSION

An Object Oriented Interface to PGP5.
*************************************

NAME
====

   Crypt::PGP5 - An Object Oriented Interface to PGP5.

SYNOPSIS
========

     use Crypt::PGP5;
     $pgp = new Crypt::PGP5;

     $pgp->secretkey ($keyid);        # Set ID of default secret key.
     $pgp->passphrase ($passphrase);  # Set passphrase.
     $pgp->armor ($boolean);          # Switch ASCII armoring on/off.
     $pgp->detach ($boolean);         # Switch detached signatures on/off.
     $pgp->encryptsafe ($boolean);    # Switch paranoid encryption on/off.
     $pgp->version ($versionstring);  # Set version string.
     $pgp->debug ($boolean);          # Switch debugging output on/off.

     $signed = $pgp->sign (@message);
     @recipients = $pgp->msginfo (@ciphertext);
     $ciphertext = $pgp->encrypt ([@recipients], @plaintext);
     ($signature, $plaintext) = $pgp->verify (@ciphertext);
     ($signature, $plaintext) = $pgp->dverify ([@signature], [@message]);

     (Most of the methods below will be encapsulated into the
     Crypt::PGP5::Key class by next release, bewarned!)

     $pgp->addkey ($keyring, @key);
     $pgp->delkey ($keyid);
     $pgp->disablekey ($keyid);
     $pgp->enablekey ($keyid);
     @keys = $pgp->keyinfo (@ids);
     $keystring = $pgp->extractkey ($userid, $keyring);
     $pgp->keypass ($keyid, $oldpasswd, $newpasswd);
     $status = $pgp->keygen
       ($name, $email, $keytype, $keysize, $expire, $pass);

DESCRIPTION
===========

   The Crypt::PGP5 module provides near complete access to PGP 5
functionality through an object oriented interface. It provides methods
for encryption, decryption, signing, signature verification, key
generation, key export and import, and most other key management functions.

CONSTRUCTOR
===========

new ()
     Creates and returns a new Crypt::PGP5 object.

DATA METHODS
============

*secretkey ()*
     Sets the *SECRETKEY* instance variable which may be a KeyID or a
     username. This is the ID of the default key to use for signing.

*passphrase ()*
     Sets the *PASSPHRASE* instance variable, required for signing and
     decryption.

*armor ()*
     Sets the *ARMOR* instance variable. If set to 0, Crypt::PGP5 doesn't
     ASCII armor its output. Else, it does. Default is to use
     ascii-armoring. I haven't tested this without ASCII armoring yet.

*detach ()*
     Sets the *DETACH* instance variable. If set to 1, the sign method
     will produce detached signature certificates, else it won't. The
     default is to produce detached signatures.

*encryptsafe ()*
     Sets the *ENCRYPTSAFE* instance variable. If set to 1, encryption
     will fail if trying to encrypt to a key which is not trusted. This is
     the default. Switch to 0 if you want to encrypt to untrusted keys.

*version ()*
     Sets the VERSION instance variable which can be used to change the
     Version: string on the PGP output to whatever you like.

*debug ()*
     Sets the DEBUG instance variable which causes the raw output of
     Crypt::PGP5's interaction with the PGP binary to be dumped to STDOUT.

OBJECT METHODS
==============

*sign (@message)*
     Signs *@message* with the secret key specified with *secretkey ()*
     and returns the result as a string.

*verify (@message)*
     Verifies or decrypts the message in *@message* and returns the
     Crypt::PGP5::Signature object corresponding to the signature on the
     message (if any, or undef otherwise), and a string containing the
     decrypted message.

*dverify ([@message], [@signature])*
     Verifies the detactched signature *@signature* on *@message* and
     returns a Crypt::PGP5::Signature object corresponding to the signature
     on the message, along with a string containing the plaintext message.

*msginfo (@ciphertext)*
     Returns a list of the recipient key IDs that *@ciphertext* is
     encrypted to.

*encrypt ([$keyid1, $keyid2...], @plaintext)*
     Encrypts *@plaintext* with the public keys of the recipients listed
     in the arrayref passed as the first argument and returns the result in
     a string, or undef if there was an error while processing. Returns
     ciphertext if the message could be encrypted to at least one of the
     recipients.

*addkey ($key, $pretend)*
     Adds the keys given in $key to the user's key ring and returns a list
     of Crypt::PGP::Key objects corresponding to the keys that were added.
     If *$pretend* is true, it pretends to add the key and creates the key
     object, but doesn't actually perform the key addition.

*delkey ($keyid)*
     Deletes the key with *$keyid* from the user's key ring.

*disablekey ($keyid)*
     Disables the key with *$keyid*.

*enablekey ($keyid)*
     Enables the key with *$keyid*.

*keyinfo (@keyids)*
     Returns an array of Crypt::PGP5::Key objects corresponding to the
     keyids listed in *@keyids*.

*parsekeys (@keylist)*
     Parses a raw PGP formatted key listing and returns a list of
     Crypt::PGP5::Key objects.

*keypass ($keyid, $oldpass, $newpass)*
     Change the passphrase for a key. Returns true if the passphrase change
     succeeded, false if not.

*extractkey ($userid, $keyring)*
     Extracts the key for *$userid* from *$keyring* and returns the
     result. The *$keyring* argument is optional and defaults to the
     public keyring set with *pubring ()*.

*keygen ($name, $email, $keytype, $keysize, $expire, $pass)*
     Creates a new keypair with the parameters specified. *$keytype* may
     be one of 'RSA' or 'DSS'. *$keysize* can be any of 768, 1024, 2048,
     3072 or 4096 for DSS keys, and 768, 1024 or 2048 for RSA type keys.
     Returns undef if there was an error, otherwise returns a filehandle
     that reports the progress of the key generation process similar to
     the way PGP does. The key generation is not complete till you read an
     EOF from the returned filehandle.

BUGS
====

   * Error checking needs work.

   * Some key manipulation functions are missing.

   * May not work with versions of PGP other than PGPfreeware 5.0i.

   * The method call interface is subject to change in future versions,
     specifically, key manipulation methods will be encapsulated into the
     Crypt::PGP5::Key class in a future version.

   * The current implementation will probably eat up all your RAM if you
     try to operate on huge messages. In future versions, this will be
     addressed by reading from and returning filehandles, rather than using
     in-core data.

AUTHOR
======

   Crypt::PGP5 is Copyright (c) 1999-2000 Ashish Gulhati
<hash@netropolis.org>. All Rights Reserved.

ACKNOWLEDGEMENTS
================

   Thanks to Barkha for inspiration and lots of laughs; to Rex Rogers at
Laissez Faire City for putting together a great environment to hack on
freedom technologies; and of-course, to Phil Zimmerman, Larry Wall,
Richard Stallman, and Linus Torvalds.

LICENSE
=======

   This code is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   It would be nice if you would mail your patches to me, and I would love
to hear about projects that make use of this module.

DISCLAIMER
==========

   This is free software. If it breaks, you own both parts.

Perl wrapper around the UFC Crypt
*********************************

NAME
====

   Crypt::Passwd - Perl wrapper around the UFC Crypt

SYNOPSIS
========

     use Crypt::Passwd;

     $crypted_password = unix_std_crypt("password", "salt");
     $ultrix_password = unix_ext_crypt("password", "salt");

DESCRIPTION
===========

   This module provides an interface layer between Perl 5 and Michael
Glad's UFC Crypt library.

   The interface is comprised in two functions, described below.

   *unix_std_crypt(passwd, salt)* provides an interface to the traditional
crypt() function, as implemented by the UFC library. It returns the crypted
password, perturbed with the salt.

   *unix_ext_crypt(passwd, salt)* provides the interface to the crypt16()
function, present in Ultrix and Digital Unix systems as implemented in the
UFC Library.

   This code is provided as is, with no warranties. It is subject to the
same terms and conditions that Perl and the UFC Crypt library.

AUTHOR
======

   Luis E. Munoz, lem@cantv.net

SEE ALSO
========

   perl(1), crypt(3), fcrypt(3), crypt16(3)

Provides interoperable MD5-based crypt() function
*************************************************

NAME
====

   unix_md5_crypt - Provides interoperable MD5-based crypt() function

SYNOPSIS
========

     use Crypt::PasswdMD5;

     $cryptedpassword = unix_md5_crypt($password, $salt);

DESCRIPTION
===========

   the `unix_md5_crypt()' provides a crypt()-compatible interface to the
rather new MD5-based crypt() function found in modern operating systems.
It's based on the implementation found on FreeBSD 2.2.[56]-RELEASE and
contains the following license in it:

     "THE BEER-WARE LICENSE" (Revision 42):
     <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
     can do whatever you want with this stuff. If we meet some day, and you think
     this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp

   `apache_md5_crypt()' provides a function compatible with Apache's
`.htpasswd' files. This was contributed by Bryan Hart <bryan@eai.com>.  As
suggested by William A. Rowe, Jr. <wrowe@lnd.com>, it is exported by
default.

Provable Prime Number Generator suitable for Cryptographic Applications.
************************************************************************

NAME
====

   Crypt::Primes - Provable Prime Number Generator suitable for
Cryptographic Applications.

VERSION
=======

     $Revision: 0.46 $
     $Date: 2001/03/04 18:26:03 $

SYNOPSIS
========

     # generate a random, provable 512-bit prime.

     use Crypt::Primes qw(maurer);
     my $prime = maurer (Size => 512);

     # generate a random, provable 2048-bit prime and report
     # progress on console.

     my $another_prime = maurer (
                          Size => 2048,
                          Verbosity => 1
                         );

     # generate a random 1024-bit prime and a group
     # generator of Z*(n).

     my $hash_ref = maurer (
                     Size => 1024,
                     Generator => 1,
                     Verbosity => 1
                    );

WARNING
=======

   The codebase is stable, but the API will most definitely change in a
future release.

DESCRIPTION
===========

   This module implements Ueli Maurer's algorithm for generating large
*provable* primes and secure parameters for public-key cryptosystems.  The
generated primes are almost uniformly distributed over the set of primes of
the specified bitsize and expected time for generation is less than the
time required for generating a pseudo-prime of the same size with
Miller-Rabin tests.  Detailed description and running time analysis of the
algorithm can be found in Maurer's paper[1].

   Crypt::Primes is a pure perl implementation.  It uses Math::Pari for
multiple precision integer arithmetic and number theoretic functions.
Random numbers are gathered with Crypt::Random, a perl interface to
/dev/u?random devices found on most modern Unix operating systems.

FUNCTIONS
=========

   The following functions are availble for import.  They must be
explicitely imported.

maurer(%params)
     Generates a prime number of the specified bitsize.  Takes a hash as
     parameter and returns a Math::Pari object (prime number) or a hash
     reference (prime number and generator) when group generator
     computation is requested.  Following hash keys are understood:

Size
     Bitsize of the required prime number.

Verbosity
     Level of verbosity of progress reporting.  Report is printed on
     STDOUT.  Level of 1 indicates normal, terse reporting.  Level of 2
     prints lots of intermediate computations, useful for debugging.

Generator
     When Generator key is set to a non-zero value, a group generator of
     Z*(n) is computed.  Group generators are required key material in
     public-key cryptosystems like Elgamal and Diffie-Hellman that are
     based on intractability of the discrete logarithm problem.  When this
     option is present, maurer() returns a hash reference that contains
     two keys, Prime and Generator.

Relprime
     When set to 1, maurer() stores intermediate primes in a class array,
     and ensures they are not used during construction of primes in the
     future calls to maurer() with Reprime => 1.  This is used by
     rsaparams().

rsaparams(%params)
     Generates two primes (p,q) and public exponent (e) of a RSA key pair.
     The key pair generated with this method is resistant to iterative
     encryption attack. See Appendix 2 of [1] for more information.

     rsaparams() takes the same arguments as maurer() with the exception of
     `Generator' and `Relprime'.  Size specifies the common bitsize of p
     an q.  Returns a hash reference with keys p, q and e.

trialdiv($n,$limit)
     Performs trial division on $n to ensure it's not divisible by any
     prime smaller than or equal to $limit.  The module maintains a lookup
     table of primes (from 2 to 65521) for this purpose.  If $limit is not
     provided, a suitable value is computed automatically.  trialdiv() is
     used by maurer() to weed out composite random numbers before
     performing computationally intensive modular exponentiation tests.
     It is, however, documented should you need to use it directly.

IMPLEMENTATION NOTE
===================

   This module implements a modified FastPrime, as described in [1], to
facilitate group generator computation.  (Refer to [1] and [2] for
description and pseudo-code of FastPrime).  The modification involves
introduction of an additional constraint on relative size r of q.  While
computing r, we ensure k * r is always greater than maxfact, where maxfact
is the bitsize of the largest number we can factor easily.  This value
defaults to 140 bits.  As a result, R is always smaller than maxfact, which
allows us to get a complete factorization of 2Rq and use it to find a
generator of the cyclic group Z*(2Rq).

RUNNING TIME
============

   Crypt::Primes generates 512-bit primes in 7 seconds (on average), and
1024-bit primes in 37 seconds (on average), on my PII 300 Mhz notebook.
There are no computational limits by design; primes upto 8192-bits were
generated to stress test the code.  For detailed runtime analysis see [1].

SEE ALSO
========

   largeprimes(1), Crypt::Random(3), Math::Pari(3)

BIBLIOGRAPHY
============

  1. Fast Generation of Prime Numbers and Secure Public-Key Cryptographic
     Parameters, Ueli Maurer (1994).

  2. Corrections to Fast Generation of Prime Numbers and Secure Public-Key
     Cryptographic Parameters, Ueli Maurer (1996).

  3. Handbook of Applied Cryptography by Menezes, Paul C. van Oorschot and
     Scott Vanstone (1997).

AUTHOR
======

   Vipul Ved Prakash, <mail@vipul.net>

LICENSE
=======

   Copyright (c) 1998-2001, Vipul Ved Prakash. All rights reserved. This
code is free software; you can redistribute it and/or modify it under the
same terms as Perl itself.

TODO
====

   Maurer's algorithm generates primes of progressively larger bitsize
using a recursive construction method. The algorithm enters recursion with
a prime number and bitsize of the next prime to be generated. (Bitsizes of
the intermediate primes are computed using a probability distribution that
ensures generated primes are sufficiently random.) This recursion can be
distributed over multiple machines, participating in a competitive
computation model, to achieve close to best running time of the algorithm.
Support for this will be implemented some day, possibly when the next
version of Penguin hits CPAN.

Perl implementation of the RC4 encryption algorithm
***************************************************

NAME
====

   Crypt::RC4 - Perl implementation of the RC4 encryption algorithm

SYNOPSIS
========

     use Crypt::RC4;
     $encrypted = RC4( $passphrase, $plaintext );
     $decrypt = RC4( $passphrase, $encrypted );

DESCRIPTION
===========

   A simple implementation of the RC4 algorithm, developed by RSA
Security, Inc. Here is the description from RSA's website:

   RC4 is a stream cipher designed by Rivest for RSA Data Security (now
RSA Security). It is a variable key-size stream cipher with byte-oriented
operations. The algorithm is based on the use of a random permutation.
Analysis shows that the period of the cipher is overwhelmingly likely to
be greater than 10100. Eight to sixteen machine operations are required
per output byte, and the cipher can be expected to run very quickly in
software. Independent analysts have scrutinized the algorithm and it is
considered secure.

   Based substantially on the "RC4 in 3 lines of perl" found at
http://www.cypherspace.org

   A major bug in v1.0 was fixed by David Hook (dgh@wumpus.com.au).
Thanks, David.

AUTHOR
======

   Kurt Kincaid (sifukurt@yahoo.com) Ronald Rivest for RSA Security, Inc.
David Hook (dgh@wumpus.com.au)

SEE ALSO
========

   perl(1), http://www.cypherspace.org, http://www.rsasecurity.com

Perl extension for the RIPEMD-160 Hash function
***********************************************

NAME
====

   Crypt::RIPEMD160 - Perl extension for the RIPEMD-160 Hash function

SYNOPSIS
========

     use Crypt::RIPEMD160;

     $context = new Crypt::RIPEMD160;
     $context->reset();

     $context->add(LIST);
     $context->addfile(HANDLE);

     $digest = $context->digest();
     $string = $context->hexdigest();

     $digest = Crypt::RIPEMD160->hash(SCALAR);
     $string = Crypt::RIPEMD160->hexhash(SCALAR);

DESCRIPTION
===========

   The *Crypt::RIPEMD160* module allows you to use the RIPEMD160 Message
Digest algorithm from within Perl programs.

   The module is based on the implementation from Antoon Bosselaers from
Katholieke Universiteit Leuven.

   A new RIPEMD160 context object is created with the new operation.
Multiple simultaneous digest contexts can be maintained, if desired.  The
context is updated with the add operation which adds the strings contained
in the LIST parameter. Note, however, that `add('foo', 'bar')',
`add('foo')' followed by `add('bar')' and `add('foobar')' should all give
the same result.

   The final message digest value is returned by the digest operation as a
20-byte binary string. This operation delivers the result of add
operations since the last new or reset operation. Note that the digest
operation is effectively a destructive, read-once operation. Once it has
been performed, the context must be reset before being used to calculate
another digest value.

   Several convenience functions are also provided. The *addfile*
operation takes an open file-handle and reads it until end-of file in 8192
byte blocks adding the contents to the context. The file-handle can either
be specified by name or passed as a type-glob reference, as shown in the
examples below. The *hexdigest* operation calls digest and returns the
result as a printable string of hexdecimal digits. This is exactly the
same operation as performed by the unpack operation in the examples below.

   The hash operation can act as either a static member function (ie you
invoke it on the RIPEMD160 class as in the synopsis above) or as a normal
virtual function. In both cases it performs the complete RIPEMD160 cycle
(reset, add, digest) on the supplied scalar value. This is convenient for
handling small quantities of data. When invoked on the class a temporary
context is created. When invoked through an already created context
object, this context is used. The latter form is slightly more efficient.
The *hexhash* operation is analogous to *hexdigest*.

EXAMPLES
========

     use Crypt::RIPEMD160;

     $ripemd160 = new Crypt::RIPEMD160;
     $ripemd160->add('foo', 'bar');
     $ripemd160->add('baz');
     $digest = $ripemd160->digest();

     print("Digest is " . unpack("H*", $digest) . "\n");

   The above example would print out the message

     Digest is f137cb536c05ec2bc97e73327937b6e81d3a4cc9

   provided that the implementation is working correctly.

   Remembering the Perl motto ("There's more than one way to do it"), the
following should all give the same result:

     use Crypt::RIPEMD160;
     $ripemd160 = new Crypt::RIPEMD160;

     die "Can't open /etc/passwd ($!)\n" unless open(P, "/etc/passwd");

     seek(P, 0, 0);
     $ripemd160->reset;
     $ripemd160->addfile(P);
     $d = $ripemd160->hexdigest;
     print "addfile (handle name) = $d\n";

     seek(P, 0, 0);
     $ripemd160->reset;
     $ripemd160->addfile(\*P);
     $d = $ripemd160->hexdigest;
     print "addfile (type-glob reference) = $d\n";

     seek(P, 0, 0);
     $ripemd160->reset;
     while (<P>)
     {
         $ripemd160->add($_);
     }
     $d = $ripemd160->hexdigest;
     print "Line at a time = $d\n";

     seek(P, 0, 0);
     $ripemd160->reset;
     $ripemd160->add(<P>);
     $d = $ripemd160->hexdigest;
     print "All lines at once = $d\n";

     seek(P, 0, 0);
     $ripemd160->reset;
     while (read(P, $data, (rand % 128) + 1))
     {
         $ripemd160->add($data);
     }
     $d = $ripemd160->hexdigest;
     print "Random chunks = $d\n";

     seek(P, 0, 0);
     $ripemd160->reset;
     undef $/;
     $data = <P>;
     $d = $ripemd160->hexhash($data);
     print "Single string = $d\n";

     close(P);

NOTE
====

   The RIPEMD160 extension may be redistributed under the same terms as
Perl.  The RIPEMD160 algorithm is published in "Fast Software Encryption,
LNCS 1039, D. Gollmann (Ed.), pp.71-82".

   The basic C code implementing the algorithm is covered by the following
copyright:

   ` /********************************************************************\
*  *      FILE:     rmd160.c  *  *      CONTENTS: A sample
C-implementation of the RIPEMD-160  *                hash-function.   *
 TARGET:   any computer with an ANSI C compiler  *  *      AUTHOR:
Antoon Bosselaers, ESAT-COSIC  *      DATE:     1 March 1996  *
VERSION:  1.0  *  *      Copyright (c) Katholieke Universiteit Leuven  *
  1996, All Rights Reserved  *
\********************************************************************/ '

RIPEMD-160 test suite results (ASCII):
======================================

   ` * message: "" (empty string)   hashcode:
9c1185a5c5e9fc54612808977ee8f548b2258d31 * message: "a"   hashcode:
0bdc9d2d256b3ee9daae347be6f4dc835a467ffe * message: "abc"   hashcode:
8eb208f7e05d987a9b044a8e98c6b087f15a0bfc * message: "message digest"
hashcode: 5d0689ef49d2fae572b881b123a85ffa21595f36 * message:
"abcdefghijklmnopqrstuvwxyz"   hashcode:
f71c27109c692c1b56bbdceb5b9d2865b3708dbc * message:
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"   hashcode:
12a053384a9c0c88e405a06c27dcf49ada62eb2b * message: "A...Za...z0...9"
hashcode: b0e20b6e3116640286ed3a87a5713079b21f5189 * message: 8 times
"1234567890"   hashcode: 9b752e45573d4b39f4dbd3323cab82bf63326bfb *
message: 1 million times "a"   hashcode:
52783243c1697bdbe16d37f97f68f08325dc1528 '

   This copyright does not prohibit distribution of any version of Perl
containing this extension under the terms of the GNU or Artistic licences.

AUTHOR
======

   The RIPEMD-160 interface was written by Christian H. Geuer (CHGEUER)
(`christian.geuer@crypto.gun.de').

SEE ALSO
========

   MD5(3pm) and SHA(1).

Perl extension for RIPEMD-160 MAC function
******************************************

NAME
====

   Crypt::RIPEMD160::MAC - Perl extension for RIPEMD-160 MAC function

SYNOPSIS
========

     use Crypt::RIPEMD160::MAC;

     $key = "This is the secret key";

     $mac = new Crypt::RIPEMD160::MAC($key);

     $mac->reset();

     $mac->add(LIST);
     $mac->addfile(HANDLE);

     $digest = $mac->mac();
     $string = $mac->hexmac();

DESCRIPTION
===========

   The *Crypt::RIPEMD160* module allows you to use the RIPEMD160 Message
Digest algorithm from within Perl programs.

EXAMPLES
========

     use Crypt::RIPEMD160;

     $ripemd160 = new Crypt::RIPEMD160;
     $ripemd160->add('foo', 'bar');
     $ripemd160->add('baz');
     $digest = $ripemd160->digest();

     print("Digest is " . unpack("H*", $digest) . "\n");

   The above example would print out the message

     Digest is f137cb536c05ec2bc97e73327937b6e81d3a4cc9

   provided that the implementation is working correctly.

AUTHOR
======

   The RIPEMD-160 interface was written by Christian H. Geuer
(`christian.geuer@crypto.gun.de').

SEE ALSO
========

   MD5(3pm) and SHA(1).

RSA public-key cryptosystem.
****************************

NAME
====

   Crypt::RSA - RSA public-key cryptosystem.

VERSION
=======

     $Revision: 1.23 $ (Beta)
     $Date: 2001/03/07 15:39:55 $

DESCRIPTION
===========

   Crypt::RSA is a pure-perl, cleanroom implementation of the RSA
public-key cryptosystem, written atop the blazingly fast number theory
library PARI.  As far as possible, Crypt::RSA conforms with *PKCS #1, RSA
Cryptography Specifications v2.1*[13].

   This implementation is structured as a bundle of modules that provide
key pair generation and management, plaintext-aware encryption and digital
signatures with appendix. Crypt::RSA is a DWIM wrapper around the other
modules in the bundle.

WARNINGS
========

   This is beta, and largely untested, software. Please use at your own
risk!

   Due to lack of a suitable ASN.1 encoder in perl, ASN.1 encoded formats
are not supported yet.

MODULES
=======

   As of this writing, Crypt::RSA is just a placeholder for the wrapper
code, which will appear soon. In the meantime, please use the following
modules directly:

Crypt::RSA::Key
     RSA key pair generator.

Crypt::RSA::Key::Public
     RSA Public Key Management.

Crypt::RSA::Key::Private
     RSA Private Key Management.

Crypt::RSA::EME::OAEP
     Plaintext-aware encryption with RSA.

Crypt::RSA::SSA::PSS
     Probablistic Signature Scheme based on RSA.

ERROR HANDLING
==============

   All modules in the Crypt::RSA bundle use a common error handling method.
When a method fails it returns a non-true value and sets $self->errstr to
a string that explains the reason for the error. Private keys and
plaintext representations passed to the method in question are wiped from
memory.

AUTHOR
======

   Vipul Ved Prakash, <mail@vipul.net>

ACKNOWLEDGEMENTS
================

   Thanks to Ilya Zakharevich for answering even the goofiest of my
questions regarding Math::Pari with unwavering paitence. Shizukesa on
#perl for clueing me into the error handling method used in this module
and a-mused for good advice.

LICENSE
=======

   Copyright (c) 1998-2001, Vipul Ved Prakash. All rights reserved. This
code is free software; you can redistribute it and/or modify it under the
same terms as Perl itself.

SEE ALSO
========

   Crypt::RSA::Primitives(3), Crypt::RSA::DataFormat(3),
Crypt::RSA::Errorhandler(3), Crypt::RSA::Debug(3), Crypt::Primes(3),
Crypt::Random(3), Crypt::CBC(3), Crypt::Blowfish(3), Tie::EncryptedHash(3),
Math::Pari(3).

MAILING LIST
============

   pac@lists.vipul.net is a mailing list for discussing development of
asymmetric cryptography modules in perl. Please send Crypt::RSA related
communications directly to the list address. Subscription interface for
pac is at http://lists.vipul.net/mailman/listinfo/pac/

BIBLIOGRAPHY
============

   (Chronologically sorted.)

  1. *R. Rivest, A. Shamir, L. Aldeman.* A Method for Obtaining Digital
     Signatures and Public-Key Cryptosystems (1978).

  2. *U. Maurer.* Fast Generation of Prime Numbers and Secure Public-Key
     Cryptographic Parameters (1994).

  3. *M. Bellare, P. Rogaway.* Optimal Asymmetric Encryption - How to
     Encrypt with RSA (1995).

  4. *M. Bellare, P. Rogaway.* The Exact Security of Digital Signatures -
     How to sign with RSA and Rabin (1996).

  5. *B. Schneier.* Applied Cryptography, Second Edition (1996).

  6. *A. Menezes, P. Oorschot, S. Vanstone.* Handbook of Applied
     Cryptography (1997).

  7. *D. Boneh.* Twenty Years of Attacks on the RSA Cryptosystem (1998).

  8. *D. Bleichenbacher, M. Joye, J. Quisquater.* A New and Optimal
     Chosen-message Attack on RSA-type Cryptosystems (1998).

  9. *B. Kaliski, J. Staddon.* Recent Results on PKCS #1: RSA Encryption
     Standard, RSA Labs Bulletin Number 7 (1998).

 10. *B. Kaliski, J. Staddon.* PKCS #1: RSA Cryptography Specifications
     v2.0, RFC 2437 (1998).

 11. *SSH Communications Security.* SSH 1.2.7 source code (1998).

 12. *S. Simpson.* PGP DH vs. RSA FAQ v1.5 (1999).

 13. *RSA Laboratories* Draft I, PKCS #1 v2.1: RSA Cryptography Standard
     (1999).

 14. *E. Young, T. Hudson, OpenSSL Team.* OpenSSL 0.9.5a source code
     (2000).

Data creation, conversion and reporting primitives.
***************************************************

NAME
====

   Crypt::RSA::DataFormat - Data creation, conversion and reporting
primitives.

DESCRIPTION
===========

   This module implements several data creation, conversion and reporting
primitives used throughout the Crypt::RSA implementation. Primitives are
available as exportable functions.

FUNCTIONS
=========

i2osp Integer, Length
     Integer To Octet String Primitive. Converts an integer into its
     equivalent octet string representative of length Length. If
     necessary, the resulting string is prefixed with nulls.

os2ip String
     Octet String to Integer Primitive. Converts an octet string into its
     equivalent integer representative.

generate_random_octet Length, Strength
     Generates a random octet string of length Length. Strength specifies
     the degree of randomness. See Crypt::Random(3) for an explanation of
     the Strength parameter.

bitsize Integer
     Returns the length of the Integer in bits.

octet_xor String1, String2
     Returns the result of *String1* XOR *String2*.

AUTHOR
======

   Vipul Ved Prakash, <mail@vipul.net>

Debug routine for Crypt::RSA.
*****************************

NAME
====

   Crypt::RSA::Debug - Debug routine for Crypt::RSA.

SYNOPSIS
========

     use Crypt::RSA::Debug qw(debug);
     debug ("oops!");

DESCRIPTION
===========

   The module provides support for the print method of debugging!

FUNCTION
========

debug String
     Prints String on STDOUT, along with caller's function name and line
     number.

AUTHOR
======

   Vipul Ved Prakash, <mail@vipul.net>

Plaintext-aware encryption with RSA.
************************************

NAME
====

   Crypt::RSA::EME::OAEP - Plaintext-aware encryption with RSA.

SYNOPSIS
========

     my $oaep = new Crypt::RSA::EME::OAEP;

     my $ct = $oaep->encrypt (Key => $key, Message => $message) ||
                 die $oaep->errstr;

     my $pt = $oaep->decrypt (Key => $key, Cyphertext => $ct)   ||
                 die $oaep->errstr;

DESCRIPTION
===========

   This module implements "plaintext-aware encryption" with RSA.
Plaintext-aware means it's computationally infeasible to obtain full or
partial information about a message from a cyphertext, and computationally
infeasible to generate a valid cyphertext without knowing the
corresponding message. It's impossible to mount chosen cyphertext attacks
against this scheme. For more information on plaintext-aware encryption,
see [3], [9] & [13].

METHODS
=======

new()
-----

   Constructor.

encrypt()
---------

   Encrypts a string with a public key and returns the encrypted string on
success. encrypt() takes a hash argument with the following mandatory keys:

Message
     A string to be encrypted. The length of this string should not exceed
     k-42 octets, where k is the octet length of the RSA modulus. If
     Message is longer than k-42, the method will fail and set
     $self->errstr to "Message too long."

Key
     Public key of the recepient, a Crypt::RSA::Key::Public object.

decrypt()
---------

   Decrypts cyphertext with a private key and returns plaintext on
success. $self->errstr is set to "Decryption Error." or appropriate error
on failure. decrypt() takes a hash argument with the following mandatory
keys:

Cyphertext
     A string encrypted with encrypt(). The length of the cyphertext must
     be k octets, where k is the length of the RSA modulus.

Key
     Private key of the reciever, a Crypt::RSA::Key::Private object.

ERROR HANDLING
==============

   See ERROR HANDLING in Crypt::RSA(3) manpage.

BIBLIOGRAPHY
============

   See BIBLIOGRAPHY in Crypt::RSA(3) manpage.

AUTHOR
======

   Vipul Ved Prakash, <mail@vipul.net>

SEE ALSO
========

   Crypt::RSA(3), Crypt::RSA::Primitives(3), Crypt::RSA::Keys(3),
Crypt::RSA::SSA::PSS(3)

Parent class for Crypt::RSA::*, provides error handling capabilities.
*********************************************************************

NAME
====

   Crypt::RSA::Errorhandler - Parent class for Crypt::RSA::*, provides
error handling capabilities.

AUTHOR
======

   Vipul Ved Prakash, <mail@vipul.net>

RSA Key Pair Generator.
***********************

NAME
====

   Crypt::RSA::Key - RSA Key Pair Generator.

SYNOPSIS
========

     my $keychain = new Crypt::RSA::Key;
     my ($public, $private) = $keychain->generate (
                               Identity  => 'Lord Macbeth <macbeth@glamis.no>',
                               Size      => 2048,
                               Password  => 'A day so foul & fair',
                               Verbosity => 1,
                              );
     die $keychain->errstr() unless $public && $private;

DESCRIPTION
===========

   This module provides a method to generate an RSA key pair.

METHODS
=======

new()
-----

   Constructor.

generate()
----------

   Generates an RSA key of specified bitsize. generate() returns a list of
two elements, a Crypt::RSA::Key::Public object that holds the public part
of the key pair and a Crypt::RSA::Key::Private object that holds that
private part. On failure, it sets $self->errstr to approriate error
string. generate() takes a hash argument with the following keys:

Size
     Bitsize of the key to be generated. This should be an even integer >
     48.  Bitsize is a mandatory argument.

Password
     String with which the private key will be encrypted. Password is a
     mandatory argument.

Identity
     A string that identifies the owner of the key. This string usually
     takes the form of a name and an email address. The identity is not
     bound to the key with a signature. However, a future release or
     another module will provide this facility. Identity is a mandatory
     argument.

Cipher
     The block cipher which is used for encrypting the private key.
     Defaults to `Blowfish'. Cipher could be set to any value that works
     with Crypt::CBC(3) and Tie::EncryptedHash(3).

Verbosity
     When set to 1, generate() will draw a progress display on console.

Filename
     The generated key pair will be written to disk, in $Filename.public
     and $Filename.private files, if this argument is provided. Disk
     writes can be deffered by skipping this argument and achieved later
     with the write() method of Crypt::RSA::Key::Public(3) and
     Crypt::RSA::Key::Private(3).

ERROR HANDLING
==============

   See ERROR HANDLING in Crypt::RSA(3) manpage.

BUGS
====

   There's an inefficiency in the way generate() ensures the key pair is
exactly Size bits long. This will be fixed in a future release.

AUTHOR
======

   Vipul Ved Prakash, <mail@vipul.net>

SEE ALSO
========

   Crypt::RSA(3), Crypt::RSA::Key::Public(3), Crypt::RSA::Key::Private(3),
Crypt::Primes(3), Tie::EncryptedHash(3)

RSA Private Key Management.
***************************

NAME
====

   Crypt::RSA::Key::Private - RSA Private Key Management.

SYNOPSIS
========

     $key = new Crypt::RSA::Private::Key (
                 Identity => 'Lord Banquo <banquo@lochaber.com>',
                 Password => 'The earth hath bubbles',
            );

     $key->hide ();
     $key->reveal ( Password => 'The earth hath bubbles' );
     $key->write  ( Filename => 'rsakeys/banquo.private'  );

     $akey = new Crypt::RSA::Private::Key (
                  Filename => 'rsakeys-banque.private'
                 );

DESCRIPTION
===========

   [coming soon]

AUTHOR
======

   Vipul Ved Prakash, <mail@vipul.net>

SEE ALSO
========

   Crypt::RSA::Key(3), Crypt::RSA::Public(3)

RSA Public Key Management.
**************************

NAME
====

   Crypt::RSA::Key::Public - RSA Public Key Management.

SYNOPSIS
========

     $key = new Crypt::RSA::Key::Public;
     $key->write ( Filename => 'rsakeys/banquo.public' );

     $akey = new Crypt::RSA::Public (
                 Filename => 'rsakeys/banquo.public'
             );

DESCRIPTION
===========

   [coming soon]

AUTHOR
======

   Vipul Ved Prakash, <mail@vipul.net>

SEE ALSO
========

   Crypt::RSA::Key(3), Crypt::RSA::Private(3)

RSA encryption, decryption, signature and verification primitives.
******************************************************************

NAME
====

   Crypt::RSA::Primitives - RSA encryption, decryption, signature and
verification primitives.

SYNOPSIS
========

     my $prim = new Crypt::RSA::Primitives;
     my $ctxt = $prim->core_encrypt (Key => $key, Plaintext => $string);
     my $ptxt = $prim->core_decrypt (Key => $key, Cyphertext => $ctxt);
     my $sign = $prim->core_sign    (Key => $key, Message => $string);
     my $vrfy = $prim->core_verify  (Key => $key, Signature => $sig);

DESCRIPTION
===========

   This module implements RSA encryption, decryption, signature and
verfication primitives. These primitives should only be used in the
context of an encryption or signing scheme. See Crypt::RSA::EME::OAEP(3),
and Crypt::RSA::SSA::PSS(3) for the implementation of two such schemes.

ERROR HANDLING
==============

   See ERROR HANDLING in Crypt::RSA(3) manpage.

AUTHOR
======

   Vipul Ved Prakash, <mail@vipul.net>

SEE ALSO
========

   Crypt::RSA(3), Crypt::RSA::Key(3), Crypt::RSA::EME::OAEP(3),
Crypt::RSA::SSA::PSS(3)

Probablistic Signature Scheme based on RSA.
*******************************************

NAME
====

   Crypt::RSA::SSA::PSS - Probablistic Signature Scheme based on RSA.

SYNOPSIS
========

     my $pss = new Crypt::RSA::SSA::PSS;

     my $signature = $pss->sign (
                         Message => $message,
                         Key     => $private,
                     ) || die $pss->errstr;

     my $verify    = $pss->verify (
                         Message   => $message,
                         Key       => $key,
                         Signature => $signature,
                     ) || die $pss->errstr;

DESCRIPTION
===========

   PSS (Probabilistic Signature Scheme) is a provably secure method of
creating digital signatures with RSA. "Provable" means that the difficulty
of forging signatures can be directly related to inverting the RSA
function. "Probablistic" alludes to the randomly generated salt value
included in the signature to enchance security. For more details on PSS,
see [4] & [13].

METHODS
=======

new()
-----

   Constructor.

sign()
------

   Computes a PSS signature on a message with the private key of the
signer.  In scalar context, sign() returns the computed signature. In array
context, it returns the signature and the random salt. The signature can
verified with verify() or verify_with_salt(). sign() takes a hash argument
with the following mandatory keys:

Message
     Message to be signed, a string of arbitary length.

Key
     Private key of the signer, a Crypt::RSA::Key::Private object.

verify()
--------

   Verfies a signature generated with sign(). The salt is recovered from
the signature and need not be passed. Returns a true value on success and
false on failure. $self->errstr is set to "Invalid signature." or
appropriate error on failure. verify() takes a hash argument with the
following mandatory keys:

Key
     Public key of the signer, a Crypt::RSA::Key::Public object.

Message
     The original signed message, a string of arbitary length.

Signature
     Signature computed with sign(), a string.

verify_with_salt()
------------------

   Verifies a signature given the salt. Takes the same arguments as
verify() in addition to *Salt*, which is a 20-byte string returned by
sign() in array context.

ERROR HANDLING
==============

   See ERROR HANDLING in Crypt::RSA(3) manpage.

BIBLIOGRAPHY
============

   See BIBLIOGRAPHY in Crypt::RSA(3) manpage.

AUTHOR
======

   Vipul Ved Prakash, <mail@vipul.net>

SEE ALSO
========

   Crypt::RSA(3), Crypt::RSA::Primitives(3), Crypt::RSA::Keys(3),
Crypt::RSA::EME::OAEP(3)

random password generator based on FIPS-181
*******************************************

NAME
====

   Crypt::RandPasswd - random password generator based on FIPS-181

SYNOPSIS
========

     use Crypt::RandPasswd;
     ( $word, $hyphenated ) = Crypt::RandPasswd->word( $minlen, $maxlen );
     $word = Crypt::RandPasswd->word( $minlen, $maxlen );
     $word = Crypt::RandPasswd->letters( $minlen, $maxlen );
     $word = Crypt::RandPasswd->chars( $minlen, $maxlen );

     # override the defaults for these functions:
     *Crypt::RandPasswd::rng = \&my_random_number_generator;
     *Crypt::RandPasswd::restrict = \&my_restriction_filter;

Run as Script
-------------

     perl Crypt/RandPasswd.pm -help

SEE ALSO
========

   FIPS 181 - (APG), Automated Password Generator:
http://www.itl.nist.gov/fipspubs/fip181.htm

DESCRIPTION
===========

   This code is a Perl language implementation of the Automated Password
Generator standard, like the program described in "A Random Word Generator
For Pronounceable Passwords" (not available on-line).  This code is a
re-engineering of the program contained in Appendix A of FIPS Publication
181, "Standard for Automated Password Generator".  In accordance with the
standard, the results obtained from this program are logically equivalent
to those produced by the standard.

CAVEATS
=======

Bugs
----

   The function to generate a password can sometimes take an extremely
long time.

Deviations From Standard
------------------------

   This implementation deviates in one critical way from the standard upon
which it is based: the random number generator in this implementation does
not use DES.  Instead, it uses perl's built-in `rand()' function, which in
turn is (usually) built on the pseudo-random number generator functions of
the underlying C library.

   However, the random function can be replaced by the user if desired.
(See `' in this node.)

Functions
=========

word
----

     word = word( minlen, maxlen );
     ( word, hyphenated_form ) = word( minlen, maxlen );

   Generates a random word, as well as its hyphenated form.  The length of
the returned word will be between minlen and maxlen.

letters
-------

     word = letters( minlen, maxlen );

   Generates a string of random letters.  The length of the returned word
is between minlen and maxlen.  Calls `random_chars_in_range( 'a' =' 'z' )>.

chars
-----

     word = chars( minlen, maxlen );

   Generates a string of random printable characters.  The length of the
returned word is between minlen and maxlen.  Calls `random_chars_in_range(
'!' =' '~' )>.

random_chars_in_range
---------------------

     word = random_chars_in_range( minlen, maxlen, lo_char => hi_char );

     Generates a string of printable characters.
     The length of the returned string is between minlen and maxlen.
     Each character is selected from the range of ASCII characters
     delimited by (lo_char,hi_char).

rand_int_in_range
-----------------

     n = rand_int_in_range( min, max );

   Returns an integer between min and max, inclusive.  Calls rng like so:

     n = min + int( rng( max - min + 1 ) )

random_element
--------------

     e = random_element( \@elts )

   Selects a random element from an array, which is passed by ref.

rng
---

     r = rng( n );

   rng is designed to have the same interface as the built-in rand
function.  The default implementation here is a simple wrapper around rand,
which is typically a wrapper for some pseudo-random number function in the
underlying C library.

   The reason for having this simple wrapper is so the user can easily
substitute a different random number generator if desired.  Since many
rng's have the same interface as rand, replacing `rng()' is as simple as

     {
         local $^W; # squelch sub redef warning.
         *Crypt::RandPasswd::rng = \&my_rng;
     }

   See `rand' in this node.

restrict
--------

     word = restrict( word );

   A filter.  Returns the arg unchanged if it is allowable; returns undef
if not.

   The default version of `restrict()' allows everything.  You may install
a different form to implement other restrictions, by doing something like
this:

     {
       local $^W; # squelch sub redef warning.
       *Crypt::RandPasswd::restrict = \&my_filter;
     }

init
----

   This initializes the environment, which by default simply seeds the
random number generator.

_random_word
------------

   This is the routine that returns a random word.  It collects random
syllables until a predetermined word length is found.  If a retry
threshold is reached, another word is tried.

   returns ( word, hyphenated_word ).

_random_unit
------------

   Selects a gram (aka "unit").  This is the standard random unit
generating routine for get_syllable().

   This routine attempts to return grams (units) with a distribution
approaching that of the distribution of the units in English.

   The distribution of the units may be altered in this procedure without
affecting the digram table or any other programs using the random_word
subroutine, as long as the set of grams (units) is kept consistent
throughout this library.

   *NOTE that where this func used to return a numeric index into the
'rules' C-array, it now returns a gram.*

_improper_word
--------------

   Check that the word does not contain illegal combinations that may span
syllables.  Specifically, these are:

     1. An illegal pair of units between syllables.
     2. Three consecutive vowel units.
     3. Three consecutive consonant units.

   The checks are made against units (1 or 2 letters), not against the
individual letters, so three consecutive units can have the length of 6 at
most.

   returns boolean

_have_initial_y
---------------

   Treating y as a vowel is sometimes a problem.  Some words get formed
that look irregular.  One special group is when y starts a word and is the
only vowel in the first syllable.  The word ycl is one example.  We
discard words like these.

   return boolean

_have_final_split
-----------------

   Besides the problem with the letter y, there is one with a silent e at
the end of words, like face or nice.  We allow this silent e, but we do
not allow it as the only vowel at the end of the word or syllables like
ble will be generated.

   returns boolean

get_syllable
------------

   Generate next unit to password, making sure that it follows these rules:

   1. Each syllable must contain exactly 1 or 2 consecutive vowels, where
y is considered a vowel.

   2. Syllable end is determined as follows:

     a. Vowel is generated and previous unit is a consonant and syllable already has a vowel.
        In this case, new syllable is started and already contains a vowel.
     b. A pair determined to be a "break" pair is encountered.
        In this case new syllable is started with second unit of this pair.
     c. End of password is encountered.
     d. "begin" pair is encountered legally.  New syllable is started with this pair.
     e. "end" pair is legally encountered.  New syllable has nothing yet.

   3. Try generating another unit if:

     a. third consecutive vowel and not y.
     b. "break" pair generated but no vowel yet in current or previous 2 units are "not_end".
     c. "begin" pair generated but no vowel in syllable preceding begin pair,
        or both previous 2 pairs are designated "not_end".
     d. "end" pair generated but no vowel in current syllable or in "end" pair.
     e. "not_begin" pair generated but new syllable must begin (because previous syllable ended as defined in 2 above).
     f. vowel is generated and 2a is satisfied, but no syllable break is possible in previous 3 pairs.
     g. Second and third units of syllable must begin, and first unit is "alternate_vowel".

alt_get_syllable
----------------

   Takes an integer, the maximum number of chars to generate. (or is it
minimum?)

   returns a list of ( string, units-in-syllable )

   *This is an alternative version of `get_syllable()', which can be
useful for unit testing the other functions.*

_illegal_placement
------------------

   goes through an individual syllable and checks for illegal combinations
of letters that go beyond looking at digrams.

   We look at things like 3 consecutive vowels or consonants, or syllables
with consonants between vowels (unless one of them is the final silent e).

   returns boolean.

AUTHOR
======

   JDPORTER@cpan.org (John Porter)

COPYRIGHT
=========

   This perl module is free software; it may be redistributed and/or
modified under the same terms as Perl itself.

Cryptographically Secure, True Random Number Generator.
*******************************************************

NAME
====

   Crypt::Random - Cryptographically Secure, True Random Number Generator.

VERSION
=======

     $Revision: 0.33 $
     $Date: 2001/02/18 20:56:07 $

SYNOPSIS
========

     use Crypt::Random qw( makerandom );
     my $r = makerandom ( Size => 512, Strength => 1 );

DESCRIPTION
===========

   Crypt::Random is an interface module to the /dev/random device found on
most modern Unix systems. The /dev/random driver gathers environmental
noise from various non-deterministic sources including inter-keyboard
timings and inter-interrupt timings that occur within the operating system
environment.

   The /dev/random driver maintains an estimate of true randomness in the
pool and decreases it every time random strings are requested for use.
When the estimate goes down to zero, the routine blocks and waits for the
occurrence of non-deterministic events to refresh the pool.

   The /dev/random kernel module also provides another interface,
/dev/urandom, that does not wait for the entropy-pool to recharge and
returns as many bytes as requested. /dev/urandom is considerably faster at
generation compared to /dev/random, which should be used only when very
high quality randomness is desired.

METHODS
=======

makerandom()
     Generates a random number of requested bitsize in base 10. Following
     arguments can be specified.

    Size
          Bitsize of the random number.

    Strength 0 || 1
          Value of 1 implies that /dev/random should be used for
          requesting random bits while 0 implies /dev/urandom.

    Device
          Alternate device to request random bits from.

makerandom_itv()
     Generates a random number in the specified interval.  In addition to
     the arguments to makerandom() following attributes can be specified.

    Lower
          Inclusive Lower limit.

    Upper
          Exclusive Upper limit.

DEPENDENCIES
============

   Crypt::Random needs Math::Pari 2.001802 or higher. As of this writing,
the latest version of Math::Pari isn't available from CPAN. Fetch it from
ftp://ftp.math.ohio-state.edu/pub/users/ilya/perl/modules/

BIBLIOGRAPHY
============

  1. random.c by Theodore Ts'o.  Found in drivers/char directory of  the
     Linux kernel sources.

  2. Handbook of Applied Cryptography by Menezes, Paul C. van Oorschot and
     Scott Vanstone.

AUTHOR
======

   Vipul Ved Prakash, <mail@vipul.net>

Crypt::CBC compliant Rijndael encryption module
***********************************************

NAME
====

   Crypt::Rijndael - Crypt::CBC compliant Rijndael encryption module

SYNOPSIS
========

     use Crypt::Rijndael;

     # keysize() is 32, but 24 and 16 are also possible
     # blocksize() is 16

     $cipher = new Crypt::Rijndael "a" x 32, Crypt::Rijndael::MODE_CBC;

     $crypted = $cipher->encrypt($plaintext);
     # - OR -
     $plaintext = $cipher->decrypt($crypted);

DESCRIPTION
===========

   This module implements the Rijndael cipher, which has just been selected
as the Advanced Encryption Standard.

keysize
     Returns the keysize, which is 32 (bytes). The Rijndael cipher
     actually supports keylengths of 16, 24 or 32 bytes, but there is no
     way to communicate this to `Crypt::CBC'.

blocksize
     The blocksize for Rijndael is 16 bytes (128 bits), although the
     algorithm actually supports any blocksize that is any multiple of our
     bytes.  128 bits, is however, the AES-specified block size, so this
     is all we support for now.

$cipher = new $key [, $mode]
     Create a new `Crypt::Rijndael' cipher object with the given key
     (which must be 128, 192 or 256 bits long). The additional $mode
     argument is the encryption mode, either `MODE_ECB' (electronic
     codebook mode, the default) or `MODE_CBC' (cipher block chaining, the
     same that `Crypt::CBC' does).

     ECB mode is very insecure (read a book on cryptography if you dont
     know why!), so you should probably use CBC mode.

$cipher->encrypt($data)
     Encrypt data. The size of $data must be a multiple of blocksize (16
     bytes), otherwise this function will croak. Apart from that, it can
     be of (almost) any length.

$cipher->decrypt($data)
     Decrypts $data.

SEE ALSO
========

     L<Crypt::CBC>

BUGS
====

   Should EXPORT or EXPORT_OK the MODE constants.

   There should be a way to access initial IV contents :(

   There may be endian issues involved in this particular implementation of
Rijndael.  I have not tested my implementation on big-endian architectures
but it is my belief that at the very least, this code running on big
endian architectures will be interoperable with the same code running on
other big endian architectures, but will not produce the correct results
vis-a-vis the Rijndael testsuites.  I do not have access to a big-endian
machine and thus have no way of testing this assertion.

AUTHOR
======

     Rafael R. Sevilla <dido@pacific.net.ph>

     The Rijndael Algorithm was developed by Vincent Rijmen and Joan Daemen,
     and has been selected as the US Government's Advanced Encryption Standard.

a rotational deviator
*********************

NAME
====

   Crypt::Rot13 - a rotational deviator

SYNOPSIS
========

     #!/usr/bin/env perl
     $^W = 1;
     use strict;
     use Crypt::Rot13;

     my $cryptochango = new Crypt::Rot13;
     $cryptochango->charge("Someone help us, please!");
     print $cryptochango->rot13(5), "\n";

DESCRIPTION
===========

   Rot13 provides an object into which arrays may be placed, and then
returned to you in altered - specifically: rotated - form. The above code
would print, "Xtrjtsj mjqu zx, uqjfxj!". If instead of rot13(5), rot13(11)
had been used the result would have been "Dzxpzyp spwa fd, awpldp!", and
of course just rot13() would have resulted in the expected, "Fbzrbar uryc
hf, cyrnfr!". Valid rot13() arguments are 0-26, though 0 and 26 do not
alter the array.

   Crypt::Rot13 has the following methods.

new
     standard constructor, this creates an array object, which is most
     convienent for mass text deviation.  (For clarification, the object
     *is* an array; not a hash as most are.  This is better suited to mass
     rotations.)

charge
     defines the array object.

peek
     returns unaltered value of array object NOTE: rot13 as described
     above does not alter the object!

rot13 degree
     rotates alphabetical characters of array object degree times toward
     the Unreachable Wrapping Z, or 13 times if degree is omitted.

LICENSE
=======

   Copyright (C) 1999 julian fondren

   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

AUTHOR
======

   Julian Fondren is julian@imaji.net, and can usually be found on #Perl,
EFnet IRC.

SEE ALSO
========

   perl(1)

OpenSSL glue that provides LWP https support
********************************************

NAME
====

     Crypt::SSLeay - OpenSSL glue that provides LWP https support

SYNOPSIS
========

     lwp-request https://www.nodeworks.com

     use LWP::UserAgent;
     my $ua = new LWP::UserAgent;
     my $req = new HTTP::Request('GET', 'https://www.nodeworks.com');
     my $res = $ua->request($req);
     print $res->code."\n";

     # PROXY SUPPORT
     $ENV{HTTPS_PROXY} = 'http://proxy_hostname_or_ip:port';

     # PROXY_BASIC_AUTH
     $ENV{HTTPS_PROXY_USERNAME} = 'username';
     $ENV{HTTPS_PROXY_PASSWORD} = 'password';

     # DEFAULT SSL VERSION
     $ENV{HTTPS_VERSION} = '3';

DESCRIPTION
===========

   This perl module provides support for the https protocol under LWP, so
that a LWP::UserAgent can make https GET & HEAD & POST requests. Please see
perldoc LWP for more information on POST requests.

   The Crypt::SSLeay package contains Net::SSL, which is automatically
loaded by LWP::Protocol::https on https requests, and provides the
necessary SSL glue for that module to work via these deprecated modules:

     Crypt::SSLeay::CTX
     Crypt::SSLeay::Conn
     Crypt::SSLeay::X509

   Work on Crypt::SSLeay has been continued only to provide https support
for the LWP - libwww perl libraries.  If you want access to the OpenSSL
API via perl, check out Sampo's Net::SSLeay.

INSTALL
=======

OpenSSL
-------

   You must have OpenSSL or SSLeay installed before compiling this module.
You can get the latest OpenSSL package from:

     http://www.openssl.org

   When installing openssl make sure your config looks like:

     > ./config --openssldir=/usr/local/openssl
      or
     > ./config --openssldir=/usr/local/ssl

     then
      > make
      > make test
      > make install

   This way Crypt::SSLeay will pick up the includes and libraries
automatically.  If your includes end up going into a separate directory
like /usr/local/include, then you may need to symlink
/usr/local/openssl/include to /usr/local/include

Crypt::SSLeay
-------------

   The latest Crypt::SSLeay can be found at your nearest CPAN, and also:

     http://www.perl.com/CPAN-local/modules/by-module/Crypt/

   Once you have downloaded it, Crypt::SSLeay installs easily using the
make or nmake commands as shown below.

     > perl Makefile.PL
     > make
     > make test
     > make install

     * use nmake for win32

     !!! NOTE for Win32 users, few people seem to be able to build
     W  Crypt::SSLeay successfully on that platform.  You don't need
     I  to because ActiveState has already compiled it for you,
     N  and is available for their perl builds 618 & 522 as a ppm
     3  install.  It may also be available for their latest build.
     2  Keywords: WinNT, Win95, Win98, 95, 98, NT, 2000
     !!!          Please see http://www.activestate.com/

PROXY SUPPORT
=============

   For proxying web requests, like with LWP::UserAgent->proxy(), or
lwp-request -p ..., you need to set an environment variable HTTPS_PROXY to
your proxy server & port, as in:

     # PROXY SUPPORT
     $ENV{HTTPS_PROXY} = 'http://proxy_hostname_or_ip:port';
     $ENV{HTTPS_PROXY} = '127.0.0.1:8080';

   Use of the HTTPS_PROXY environment variable in this way is compatible
with LWP::UserAgent->env_proxy() usage.

   If we could find the current LWP object executing while in Net::SSL
context, then we could support proxy() method too, but it does not seem
feasible to do so at this time.

   Basic auth credentials to the proxy server can be provided this way:

     # PROXY_BASIC_AUTH
     $ENV{HTTPS_PROXY_USERNAME} = 'username';
     $ENV{HTTPS_PROXY_PASSWORD} = 'password';

SSL VERSIONS
============

   Crypt::SSLeay tries very hard to connect to ANY SSL web server trying
to accomodate servers that are buggy, old or simply not standards
compliant.  To this effect, this module will try SSL connections in this
order:

     SSL v23  - should allow v2 & v3 servers to pick their best type
     SSL v3   - best connection type
     SSL v2   - old connection type

   Unfortunately, some servers seem not to handle a reconnect to SSL v3
after a failed connect of SSL v23 is tried, so you may set before using
LWP or Net::SSL:

     $ENV{HTTPS_VERSION} = 3;

   so that a SSL v3 connection is tried first.  At this time only a SSL v2
connection will be tried after this, as the connection attempt order
remains unchanged by this setting.

COMPATIBILITY
=============

     This module has been compiled on the following platforms:

     PLATFORM	CPU 	SSL		PERL	 VER	DATE		WHO
     --------	--- 	---		----	 ---	----		---
     Linux 2.2.14 	x86	OpenSSL 0.9.6	5.00503	 .21	2001-01-10	Joshua Chamas
     WinNT SP6 	x86	OpenSSL 0.9.4	5.00404	 .21	2001-01-10	Joshua Chamas
     AIX 4.3.2	RS/6000	OpenSSL 0.9.6	5.6.0	 .19	2001-01-08	Peter Heimann
     Solaris 2.6	x86	OpenSSL 0.9.5a	5.00501	 .17    2000-09-04	Joshua Chamas
     Linux 2.2.12   x86     OpenSSL 0.9.5a  5.00503	 .16	2000-07-13      David Harris
     FreeBSD 3.2	?x86	OpenSSL 0.9.2b	5.00503	 ?      1999-09-29	Rip Toren
     Solaris 2.6	?Sparc	OpenSSL 0.9.4	5.00404	 ?      1999-08-24	Patrick Killelea
     FreeBSD 2.2.5	x86	OpenSSL 0.9.3	5.00404	 ?      1999-08-19	Andy Lee
     Solaris 2.5.1	USparc	OpenSSL 0.9.4	5.00503	 ?      1999-08-18	Marek Rouchal
     Solaris 2.6	x86	SSLeay 0.8.0	5.00501	 ?      1999-08-12	Joshua Chamas
     Linux 2.2.10	x86 	OpenSSL 0.9.4	5.00503	 ?      1999-08-11	John Barrett
     WinNT SP4	x86	SSLeay 0.9.2	5.00404	 ?      1999-08-10	Joshua Chamas

BUILD NOTES
===========

Win32, WinNT, Win2000, can't build
----------------------------------

   If you cannot get it to build on your windows box, try ActiveState
perl, at least their builds 522 & 618 are known to have a ppm install of
Crypt::SSLeay available.  Please see http://www.activestate.com for more
info.

AIX 4.3.2 - Symbol Error: __umoddi3 : referenced symbol not found
-----------------------------------------------------------------

   The __umoddi3 problem applies here as well when compiling with gcc.

   Alternative solution: In Makefile.PL, prepend -L/usr/local/<path to
your gcc lib>/<version> to the $LIBS value. Add after line 82:

     $LIBS = '-L' . dirname(`gcc -print-libgcc-file-name`) . ' ' . $LIBS;

Solaris x86 - Symbol Error: __umoddi3 : referenced symbol not found
-------------------------------------------------------------------

     Problem:

   On Solaris x86, the default PERL configuration, and preferred, is to use
the ld linker that comes with the OS, not gcc.  Unfortunately during the
OpenSSL build process, gcc generates in libcrypto.a, from bn_word.c, the
undefined symbol __umoddi3, which is supposed to be later resolved by gcc
from libgcc.a

   The system ld linker does not know about libgcc.a by default, so when
building Crypt::SSLeay, there is a linker error for __umoddi3

     Solution:

   The fix for this symlink your libgcc.a to some standard directory like
/usr/local/lib, so that the system linker, ld, can find it when building
Crypt::SSLeay.

FreeBSD 2.x.x / Solaris - ... des.h:96 #error _ is defined ...
--------------------------------------------------------------

   If you encounter this error: "...des.h:96: #error _ is defined, but
some strange definition the DES library cannot handle that...," then you
need to edit the des.h file and comment out the "#error" line.

   Its looks like this error might be common to other operating systems,
and that occurs with OpenSSL 0.9.3.  Upgrades to 0.9.4 seem to fix this
problem.

NOTES
=====

   Many thanks to Gisle Aas for the original writing of this module and
many others including libwww for perl.  The web will never be the same :)

   Ben Laurie deserves kudos for his excellent patches for better error
handling, SSL information inspection, and random seeding.

   James Woodyatt is a champ for finding a ridiculous memory leak that has
been the bane of many a Crypt::SSLeay user.

   Thanks to Bryan Hart for his patch adding proxy support, and thanks to
Tobias Manthey for submitting another approach.

SUPPORT
=======

   For OpenSSL and Crypt::SSLeay support, please email the openssl user
mailing list at openssl-users@openssl.org

   Emails to the list sent with at least Crypt::SSLeay in the subject line
will be responded to more quickly by myself.  Please make the subject line
informative like

     Subject: [Crypt::SSLeay] compile problems on Solaris

   This module was originally written by Gisle Aas, and I am now
maintaining it.

COPYRIGHT
=========

     Copyright (c) 1999-2001 Joshua Chamas.
     Copyright (c) 1998 Gisle Aas.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Solitaire encryption
********************

NAME
====

   Crypt::Solitaire - Solitaire encryption

SYNOPSIS
========

     use Crypt::Solitaire;
     my $encrypted = Pontifex( $plaintext, $passphrase, $mode );

DESCRIPTION
===========

   Solitaire is a top-notch pencil-and-paper encryption system developed
by Bruce Schneier.  Here is the description in Schneier's own words:

   "In Neal Stephenson's novel Cryptonomicon, the character Enoch Root
describes a cryptosystem code-named "Pontifex" to another character named
Randy Waterhouse, and later reveals that the steps of the algorithm are
intended to be carried out using a deck of playing cards. These two
characters go on to exchange several encrypted messages using this system.
The system is called "Solitaire" (in the novel, "Pontifex" is a code name
intended to temporarily conceal the fact that it employs a deck of cards)
and I designed it to allow field agents to communicate securely without
having to rely on electronics or having to carry incriminating tools. An
agent might be in a situation where he just does not have access to a
computer, or may be prosecuted if he has tools for secret communication.
But a deck of cards...what harm is that?

   "Solitaire gets its security from the inherent randomness in a shuffled
deck of cards. By manipulating this deck, a communicant can create a
string of "random" letters that he then combines with his message. Of
course Solitaire can be simulated on a computer, but it is designed to be
implemented by hand.

   "Solitaire may be low-tech, but its security is intended to be
high-tech. I designed Solitaire to be secure even against the most
well-funded military adversaries with the biggest computers and the
smartest cryptanalysts. Of course, there is no guarantee that someone
won't find a clever attack against Solitaire, but the algorithm is
certainly better than any other pencil-and-paper cipher I've ever seen."

   Simple system, easy to use, and relatively fast.

LIMITATIONS
===========

   Restricted only to letters A..Z. Lower case letters are converted to
upper case, and due to the fact that Solitaire applies its own formatting
to the text, the output can be a little tricky at first glance.

METHODS
=======

Pontifex $text, $passphrase, $mode
     $text is encrypted using $passphrase.  Encrypts or decrypts, based on
     $mode.  Mode must be set to "e" or "d," for encrypting and
     decrypting, respectively.

AUTHOR
======

   Designed by Bruce Schneier (President, Counterpane Systems)

   Original Perl Code by Ian Goldberg <ian@cypherpunks.ca>, 19980817

   Minor changes and module-ification by Kurt Kincaid <ceo@neurogames.com>

SEE ALSO
========

   perl(1), Counterpane System (http://www.counterpane.com).

Triple DES encyption.
*********************

NAME
====

   Crypt::TripleDES - Triple DES encyption.

SYNOPSIS
========

     my $des = new Crypt::TripleDES;
     my $cyphertext = $des->encrypt3 ( $plaintext, $passphrase );
     my $plaintext = $des->decrypt3 ( $cyphertext, $passphrase );

DESCRIPTION
===========

   This module implements 3DES encryption in ECB mode. The code is based on
Eric Young's implementation of DES in pure perl. It's quite slow because of
the way Perl handles bit operations and is not recommended for use with
large texts.

METHODS
=======

new
     The constructor.

encrypt3 $plaintext, $passphrase
     Encrypts the plaintext string using the passphrase. Whitespace
     characters are appended to the string if its length is not a multiple
     of eight. User applications can correct for this by storing plaintext
     size with the cyphertext. The passphrase is an ASCII character string
     of upto 48 characters.

decrypt3 $cyphertext, $passphrase
     Inverse of encrypt3().

AUTHOR
======

     Vipul Ved Prakash, mail@vipul.net
     Eric Young, eay@psych.psy.uq.oz.au

     Patches:
     Jonathan Mayer <jmayer@cobaltnet.com>

Crypt::CBC compliant Twofish encryption module
**********************************************

NAME
====

   Crypt::Twofish2 - Crypt::CBC compliant Twofish encryption module

SYNOPSIS
========

     use Crypt::Twofish2;

     # keysize() is 32, but 24 and 16 are also possible
     # blocksize() is 16

     $cipher = new Crypt::Twofish2 "a" x 32, Crypt::Twofish2::MODE_CBC;

     $crypted = $cipher->encrypt($plaintext);
     # - OR -
     $plaintext = $cipher->decrypt($crypted);

DESCRIPTION
===========

   This module implements thw twofish cipher in a less braindamaged (read:
slow and ugly) way than the existing `Crypt::Twofish' module.

   Although it is `Crypt::CBC' compliant you usually gain nothing by using
that module (except generality), since `Crypt::Twofish2' can work in
either ECB or CBC mode.

keysize
     Returns the keysize, which is 32 (bytes). The Twofish2 cipher actually
     supports keylengths of 16, 24 or 32 bytes, but there is no way to
     communicate this to `Crypt::CBC'.

blocksize
     The blocksize for Twofish2 is 16 bytes (128 bits), which is somewhat
     unique. It is also the reason I need this module myself ;)

$cipher = new $key [, $mode]
     Create a new `Crypt::Twofish2' cipher object with the given key (which
     must be 128, 192 or 256 bits long). The additional $mode argument is
     the encryption mode, either `MODE_ECB' (electronic cookbook mode, the
     default), `MODE_CBC' (cipher block chaining, the same that
     `Crypt::CBC' does) or `MODE_CFB1' (1-bit cipher feedback mode).

     ECB mode is very insecure (read a book on cryptography if you don't
     know why!), so you should probably use CBC mode. CFB1 mode is not
     tested and is most probably broken, so do not try to use it.

     In ECB mode you can use the same cipher object to encrypt and decrypt
     data. However, every change of "direction" causes an internal
     reordering of key data, which is quite slow, so if you want ECB mode
     and encryption/decryption at the same time you should create two
     seperate `Crypt::Twofish2' objects with the same key.

     In CBC mode you have to use seperate objects for
     encryption/decryption in any case.

     The `MODE_*'-constants are not exported by this module, so you must
     specify them as `Crypt::Twofish2::MODE_CBC' etc. (sorry for that).

$cipher->encrypt($data)
     Encrypt data. The size of $data must be a multiple of blocksize (16
     bytes), otherwise this function will croak. Apart from that, it can
     be of (almost) any length.

$cipher->decrypt($data)
     The pendant to encrypt in that it *de*crypts data again.

SEE ALSO
========

   See Crypt/CBC, `Crypt::Twofish' in this node.

BUGS
====

   Should EXPORT or EXPORT_OK the MODE constants.

   The testsuite does not check wether the encrypted valued are correct.

   There should be a way to access initial IV contents :(

   Although I tried to make the original twofish code portable, I can't say
how much I did succeed. The code tries to be portable itself, and I hope I
got the endianness issues right. The code is also copyright Counterpane
Systems, no license accompanied it, so using it might actually be illegal
;)

AUTHOR
======

     Marc Lehmann <pcg@goof.com>
     http://www.goof.com/pcg/marc/

     The actualy twofish encryption is written in horribly microsoft'ish looking
     almost ansi-c by Doug Whiting.

perl-only implementation of the crypt function.
***********************************************

NAME
====

   Crypt::UnixCrypt - perl-only implementation of the crypt function.

SYNOPSIS
========

     use Crypt::UnixCrypt;
     $hashed = crypt($plaintext,$salt);

     # always use this module's crypt
     BEGIN { $Crypt::UnixCrpyt::OVERRIDE_BUILTIN = 1 }
     use Crypt::UnixCrypt;

DESCRIPTION
===========

   This module is for all those poor souls whose perl port answers to the
use of crypt() with the message `The crypt() function is unimplemented due
to excessive paranoia.'.

   This module won't overload a built-in crypt() unless forced by a true
value of the variable `$Crypt::UnixCrypt::OVERRIDE_BUILTIN'.

   If you use this module, you probably neither have a built-in crypt()
function nor a `crypt(3)' in this node manpage; so I'll supply the
appropriate portions of its description (from my Linux system) here:

   crypt is the password encryption function. It is based on the Data
Encryption Standard algorithm with variations intended (among other
things) to discourage use of hardware implementations of a key search.

   $plaintext is a user's typed password.

   $salt is a two-character string chosen from the set [a-zA-Z0-9./]. This
string is used to perturb the algorithm in one of 4096 different ways.

   By taking the lowest 7 bit of each character of $plaintext (filling it
up to 8 characters with zeros, if needed), a 56-bit key is obtained. This
56-bit key is used to encrypt repeatedly a constant string (usually a
string consisting of all zeros). The returned value points to the
encrypted password, a series of 13 printable ASCII characters (the first
two characters represent the salt itself).

   Warning: The key space consists of 2**56 equal 7.2e16 possible values.
Exhaustive searches of this key space are possible using massively
parallel computers. Software, such as crack(1), is available which will
search the portion of this key space that is generally used by humans for
passwords. Hence, password selection should, at minimum, avoid common
words and names. The use of a passwd(1) program that checks for crackable
passwords during the selection process is recommended.

   The DES algorithm itself has a few quirks which make the use of the
crypt(3) interface a very poor choice for anything other than password
authentication. If you are planning on using the crypt(3) interface for a
cryptography project, don't do it: get a good book on encryption and one
of the widely available DES libraries.

COPYRIGHT
=========

   This module is free software; you may redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Written by Martin Vorlaender, martin@radiogaga.harz.de, 11-DEC-1997.
Based upon Java source code written by jdumas@zgs.com, which in turn is
based upon C source code written by Eric Young, eay@psych.uq.oz.au.

CAVEATS
=======

   In extreme situations, this function doesn't behave like `crypt(3)',
e.g. when called with a salt not in [A-Za-z0-9./]{2}.

SEE ALSO
========

   perl(1), perlfunc(1), crypt(3).

encrypt almost any kind of dbm file
***********************************

NAME
====

   Crypt::xDBM_File - encrypt almost any kind of dbm file

SYNOPSIS
========

     use Crypt::xDBM_File;
     use GDBM_File; # remember to only load those you really want
     use SDBM_File;
     use NDBM_File;
     use Fcntl; # neede by SDBM_File and NDBM_File

     tie %hash, 'Crypt::xDBM_File', crypt_method, key, 'GDBM_FILE', $filename, &GDBM_WRCREAT, 0640;

     tie %hash, 'Crypt::xDBM_File', 'IDEA', "my_key", 'NDBM_FILE', $filename, O_RDWR|O_CREAT, 0640;

     tie %hash, 'Crypt::xDBM_File', 'DES', "my_key", 'SDBM_FILE', $filename, O_RDWR|O_CREAT, 0640;

     tie %hash, 'Crypt::xDBM_File', 'Crypt::Blowfish', "my key", 'GDBM_FILE', $filename, &GDBM_WRCREAT, 0640;

DESCRIPTION
===========

   Crypt::xDBM_File encrypts/decrypts the data in a gdbm,ndbm,sdbm (and
maybe even berkeleyDB, but I didn't test that) file.  It gets tied to a
hash and you just access the hash like normal.  The crypt function can be
any of the CPAN modules that use encrypt, decrypt, keysize, blocksize (so
Crypt::IDEA, Crypt::DES, Crypt::Blowfish, ... should all work)

   You can in a single dbm file mix encryption methods, just be prepared
to handle the binary muck that you get from trying to decrypt with an
algorithm different from the one a key was originally encrypted in (for
example if you do a keys or values, you'll get all of the keys regardless
of who encrypted them).

   ***IMPORTANT*** Encryption keys (the key you pass in on the tie line)
will be padded or truncated to fit the keysize().  Data (the key/values of
the hash) is padded to fill complete blocks of blocksize().  The padding
is stripped before being returned to the user so you shouldn't need to
worry about it (except truncated keys).  Read the doc that comes with
crypt function to get an idea of what these sizes are.  If keysize or
blocksize returns a zero the default is set to 8 bytes (64 bits).

AUTHOR
======

   Eric Estabrooks, eric@urbanrage.com

SEE ALSO
========

   perl(1).

terminal screen handling and optimization
*****************************************

NAME
====

   Curses - terminal screen handling and optimization

SYNOPSIS
========

     use Curses;

     initscr;
     ...
     endwin;

DESCRIPTION
===========

   `Curses' is the interface between Perl and your system's curses(3)
library.  For descriptions on the usage of a given function, variable, or
constant, consult your system's documentation, as such information
invariably varies (:-) between different curses(3) libraries and operating
systems.  This document describes the interface itself, and assumes that
you already know how your system's curses(3) library works.

Unified Functions
-----------------

   Many curses(3) functions have variants starting with the prefixes *w-*,
*mv-*, and/or *wmv-*.  These variants differ only in the explicit addition
of a window, or by the addition of two coordinates that are used to move
the cursor first.  For example, `addch()' has three other variants:
`waddch()', `mvaddch()', and `mvwaddch()'.  The variants aren't very
interesting; in fact, we could roll all of the variants into original
function by allowing a variable number of arguments and analyzing the
argument list for which variant the user wanted to call.

   Unfortunately, curses(3) predates varargs(3), so in C we were stuck
with all the variants.  However, `Curses' is a Perl interface, so we are
free to "unify" these variants into one function.  The section `"Supported
Functions"' in this node below lists all curses(3) function supported by
`Curses', along with a column listing if it is *unified*.  If so, it takes
a varying number of arguments as follows:

   `function( [win], [y, x], args );'

   *win* is an optional window argument, defaulting to `stdscr' if not
specified.

   *y, x* is an optional coordinate pair used to move the cursor,
defaulting to no move if not specified.

   args are the required arguments of the function.  These are the
arguments you would specify if you were just calling the base function and
not any of the variants.

   This makes the variants obsolete, since their functionality has been
merged into a single function, so `Curses' does not define them by
default.  You can still get them if you want, by setting the variable
`$Curses::OldCurses' to a non-zero value before using the `Curses'
package.  See `"Perl 4.X `cursperl' in this node Compatibility"' for an
example of this.

Objects
-------

   Objects are supported.  Example:

     $win = new Curses;
     $win->addstr(10, 10, 'foo');
     $win->refresh;
     ...

   Any function that has been marked as *unified* (see `"Supported
Functions"' in this node below and `"Unified Functions"' in this node
above) can be called as a method for a Curses object.

   Do not use `initscr()' if using objects, as the first call to get a
`new Curses' will do it for you.

COMPATIBILITY
=============

Perl 4.X `cursperl' Compatibility
---------------------------------

   `Curses' has been written to take advantage of the new features of
Perl.  I felt it better to provide an improved curses programming
environment rather than to be 100% compatible.  However, many old
`curseperl' applications will probably still work by starting the script
with:

     BEGIN { $Curses::OldCurses = 1; }
     use Curses;

   Any old application that still does not work should print an
understandable error message explaining the problem.

   Some functions and variables are not supported by `Curses', even with
the BEGIN line.  They are listed under `"curses(3) items not supported by
Curses"' in this node.

   The variables `$stdscr' and `$curscr' are also available as functions
`stdscr' and `curscr'.  This is because of a Perl bug.  See the `BUGS' in
this node section for details.

Incompatibilities with previous versions of `Curses'
----------------------------------------------------

   In previous versions of this software, some Perl functions took a
different set of parameters than their C counterparts.  This is no longer
true.  You should now use `getstr($str)' and `getyx($y, $x)' instead of
`$str = getstr()' and `($y, $x) = getyx()'.

Incompatibilities with other Perl programs
------------------------------------------

     menu.pl, v3.0 and v3.1
     	There were various interaction problems between these two
     	releases and Curses.  Please upgrade to the latest version
     	(v3.3 as of 3/16/96).

DIAGNOSTICS
===========

   * Curses function '%s' called with too %s arguments at ...

     You have called a `Curses' function with a wrong number of arguments.

   * argument %d to Curses function '%s' is not a Curses %s at ... =item *
     argument is not a Curses %s at ...

     The argument you gave to the function wasn't what it wanted.

     This probably means that you didn't give the right arguments to a
     *unified* function.  See the DESCRIPTION section on `Unified
     Functions' in this node for more information.

   * Curses function '%s' is not defined by your vendor at ...

     You have a `Curses' function in your code that your system's curses(3)
     library doesn't define.

   * Curses variable '%s' is not defined by your vendor at ...

     You have a `Curses' variable in your code that your system's curses(3)
     library doesn't define.

   * Curses constant '%s' is not defined by your vendor at ...

     You have a `Curses' constant in your code that your system's curses(3)
     library doesn't define.

   * Curses does not support the curses function '%s', used at ...

     You have a curses(3) function in your code that the `Curses' module
     doesn't support.

   * Curses does not support the curses variable '%s', used at ...

     You have a curses(3) variable in your code that the `Curses' module
     doesn't support.

   * Curses does not support the curses constant '%s', used at ...

     You have a bareword in your code that is trying to be interpreted as
     a `Curses' constant, but `Curses' doesn't know anything about it.

   * Curses::Vars::FETCH called with bad index at ... =item *
     Curses::Vars::STORE called with bad index at ...

     You've been playing with the tie interface to the `Curses' variables.
     Don't do that.  :-)

   * Anything else

     Check out the `perldiag' man page to see if the error is in there.

BUGS
====

   If you use the variables `$stdscr' and `$curscr' instead of their
functional counterparts (`stdscr' and `curscr'), you might run into a bug
in Perl where the "magic" isn't called early enough.  This is manifested
by the `Curses' package telling you `$stdscr' isn't a window.  One
workaround is to put a line like `$stdscr = $stdscr' near the front of
your program.

   Probably many more.

AUTHOR
======

   William Setzer <William_Setzer@ncsu.edu>

SYNOPSIS OF PERL CURSES SUPPORT
===============================

Supported Functions
-------------------

     Supported         Unified?     Supported via $OldCurses[*]
     ---------         --------     ------------------------
     addch               Yes        waddch mvaddch mvwaddch
     echochar            Yes        wechochar
     addchstr            Yes        waddchstr mvaddchstr mvwaddchstr
     addchnstr           Yes        waddchnstr mvaddchnstr mvwaddchnstr
     addstr              Yes        waddstr mvaddstr mvwaddstr
     addnstr             Yes        waddnstr mvaddnstr mvwaddnstr
     attroff             Yes        wattroff
     attron              Yes        wattron
     attrset             Yes        wattrset
     standend            Yes        wstandend
     standout            Yes        wstandout
     chgat               Yes        wchgat mvchgat mvwchgat
     COLOR_PAIR          No
     PAIR_NUMBER         No
     beep                No
     flash               No
     bkgd                Yes        wbkgd
     bkgdset             Yes        wbkgdset
     getbkgd             Yes
     border              Yes        wborder
     box                 Yes
     hline               Yes        whline mvhline mvwhline
     vline               Yes        wvline mvvline mvwvline
     erase               Yes        werase
     clear               Yes        wclear
     clrtobot            Yes        wclrtobot
     clrtoeol            Yes        wclrtoeol
     start_color         No
     init_pair           No
     init_color          No
     has_colors          No
     can_change_color    No
     color_content       No
     pair_content        No
     delch               Yes        wdelch mvdelch mvwdelch
     deleteln            Yes        wdeleteln
     insdelln            Yes        winsdelln
     insertln            Yes        winsertln
     getch               Yes        wgetch mvgetch mvwgetch
     ungetch             No
     has_key             No
     getstr              Yes        wgetstr mvgetstr mvwgetstr
     getnstr             Yes        wgetnstr mvgetnstr mvwgetnstr
     getyx               Yes
     getparyx            Yes
     getbegyx            Yes
     getmaxyx            Yes
     getmaxy             Yes
     getmaxx             Yes
     inch                Yes        winch mvinch mvwinch
     inchstr             Yes        winchstr mvinchstr mvwinchstr
     inchnstr            Yes        winchnstr mvinchnstr mvwinchnstr
     initscr             No
     endwin              No
     isendwin            No
     newterm             No
     set_term            No
     delscreen           No
     cbreak              No
     nocbreak            No
     echo                No
     noecho              No
     halfdelay           No
     intrflush           Yes
     keypad              Yes
     meta                Yes
     nodelay             Yes
     notimeout           Yes
     raw                 No
     noraw               No
     qiflush             No
     noqiflush           No
     timeout             Yes        wtimeout
     typeahead           No
     insch               Yes        winsch mvinsch mvwinsch
     insstr              Yes        winsstr mvinsstr mvwinsstr
     insnstr             Yes        winsnstr mvinsnstr mvwinsnstr
     instr               Yes        winstr mvinstr mvwinstr
     innstr              Yes        winnstr mvinnstr mvwinnstr
     def_prog_mode       No
     def_shell_mode      No
     reset_prog_mode     No
     reset_shell_mode    No
     resetty             No
     savetty             No
     getsyx              No
     setsyx              No
     curs_set            No
     napms               No
     getmouse            No
     ungetmouse          No
     mousemask           No
     enclose             Yes        wenclose
     mouse_trafo         Yes        wmouse_trafo
     mouseinterval       No
     BUTTON_RELEASE      No
     BUTTON_PRESS        No
     BUTTON_CLICK        No
     BUTTON_DOUBLE_CLICK No
     BUTTON_TRIPLE_CLICK No
     BUTTON_RESERVED_EVENTNo
     move                Yes        wmove
     clearok             Yes
     idlok               Yes
     idcok               Yes
     immedok             Yes
     leaveok             Yes
     setscrreg           Yes        wsetscrreg
     scrollok            Yes
     nl                  No
     nonl                No
     overlay             No
     overwrite           No
     copywin             No
     newpad              No
     subpad              No
     prefresh            No
     pnoutrefresh        No
     pechochar           No
     refresh             Yes        wrefresh
     noutrefresh         Yes        wnoutrefresh
     doupdate            No
     redrawwin           Yes
     redrawln            Yes        wredrawln
     scr_dump            No
     scr_restore         No
     scr_init            No
     scr_set             No
     scroll              Yes
     scrl                Yes        wscrl
     slk_init            No
     slk_set             No
     slk_refresh         No
     slk_noutrefresh     No
     slk_label           No
     slk_clear           No
     slk_restore         No
     slk_touch           No
     slk_attron          No
     slk_attrset         No
     slk_attr            No
     slk_attroff         No
     slk_color           No
     baudrate            No
     erasechar           No
     has_ic              No
     has_il              No
     killchar            No
     longname            No
     longname            No
     termattrs           No
     termname            No
     touchwin            Yes
     touchline           Yes
     touchline           Yes
     untouchwin          Yes
     touchln             Yes        wtouchln
     is_linetouched      Yes
     is_wintouched       Yes
     unctrl              No
     keyname             No
     filter              No
     use_env             No
     putwin              No
     getwin              No
     delay_output        No
     flushinp            No
     newwin              No
     delwin              Yes
     mvwin               Yes
     subwin              Yes
     derwin              Yes
     mvderwin            Yes
     dupwin              Yes
     syncup              Yes        wsyncup
     syncok              Yes
     cursyncup           Yes        wcursyncup
     syncdown            Yes        wsyncdown
     resize              Yes        wresize
     flusok              Yes
     getcap              No
     touchoverlap        No
     new_panel           No
     bottom_panel        No
     top_panel           No
     show_panel          No
     update_panels       No
     hide_panel          No
     panel_window        No
     replace_panel       No
     move_panel          No
     panel_hidden        No
     panel_above         No
     panel_below         No
     set_panel_userptr   No
     panel_userptr       No
     del_panel           No

   [*] To use any functions in this column, the variable
`$Curses::OldCurses' must be set to a non-zero value before using the
`Curses' package.  See `"Perl 4.X cursperl Compatibility"' in this node
for an example of this.

Supported Variables
-------------------

     LINES           COLS            stdscr          curscr
     COLORS          COLOR_PAIRS

Supported Constants
-------------------

     ERR             OK              ACS_BLOCK       ACS_BOARD
     ACS_BTEE        ACS_BULLET      ACS_CKBOARD     ACS_DARROW
     ACS_DEGREE      ACS_DIAMOND     ACS_HLINE       ACS_LANTERN
     ACS_LARROW      ACS_LLCORNER    ACS_LRCORNER    ACS_LTEE
     ACS_PLMINUS     ACS_PLUS        ACS_RARROW      ACS_RTEE
     ACS_S1          ACS_S9          ACS_TTEE        ACS_UARROW
     ACS_ULCORNER    ACS_URCORNER    ACS_VLINE       A_ALTCHARSET
     A_ATTRIBUTES    A_BLINK         A_BOLD          A_CHARTEXT
     A_COLOR         A_DIM           A_INVIS         A_NORMAL
     A_PROTECT       A_REVERSE       A_STANDOUT      A_UNDERLINE
     COLOR_BLACK     COLOR_BLUE      COLOR_CYAN      COLOR_GREEN
     COLOR_MAGENTA   COLOR_RED       COLOR_WHITE     COLOR_YELLOW
     KEY_A1          KEY_A3          KEY_B2          KEY_BACKSPACE
     KEY_BEG         KEY_BREAK       KEY_BTAB        KEY_C1
     KEY_C3          KEY_CANCEL      KEY_CATAB       KEY_CLEAR
     KEY_CLOSE       KEY_COMMAND     KEY_COPY        KEY_CREATE
     KEY_CTAB        KEY_DC          KEY_DL          KEY_DOWN
     KEY_EIC         KEY_END         KEY_ENTER       KEY_EOL
     KEY_EOS         KEY_EXIT        KEY_F0          KEY_FIND
     KEY_HELP        KEY_HOME        KEY_IC          KEY_IL
     KEY_LEFT        KEY_LL          KEY_MARK        KEY_MAX
     KEY_MESSAGE     KEY_MIN         KEY_MOVE        KEY_NEXT
     KEY_NPAGE       KEY_OPEN        KEY_OPTIONS     KEY_PPAGE
     KEY_PREVIOUS    KEY_PRINT       KEY_REDO        KEY_REFERENCE
     KEY_REFRESH     KEY_REPLACE     KEY_RESET       KEY_RESTART
     KEY_RESUME      KEY_RIGHT       KEY_SAVE        KEY_SBEG
     KEY_SCANCEL     KEY_SCOMMAND    KEY_SCOPY       KEY_SCREATE
     KEY_SDC         KEY_SDL         KEY_SELECT      KEY_SEND
     KEY_SEOL        KEY_SEXIT       KEY_SF          KEY_SFIND
     KEY_SHELP       KEY_SHOME       KEY_SIC         KEY_SLEFT
     KEY_SMESSAGE    KEY_SMOVE       KEY_SNEXT       KEY_SOPTIONS
     KEY_SPREVIOUS   KEY_SPRINT      KEY_SR          KEY_SREDO
     KEY_SREPLACE    KEY_SRESET      KEY_SRIGHT      KEY_SRSUME
     KEY_SSAVE       KEY_SSUSPEND    KEY_STAB        KEY_SUNDO
     KEY_SUSPEND     KEY_UNDO        KEY_UP          KEY_MOUSE
     BUTTON1_RELEASED BUTTON1_PRESSED BUTTON1_CLICKED BUTTON1_DOUBLE_CLICKED
     BUTTON1_TRIPLE_CLICKED BUTTON1_RESERVED_EVENT BUTTON2_RELEASED
     BUTTON2_PRESSED BUTTON2_CLICKED BUTTON2_DOUBLE_CLICKED BUTTON2_TRIPLE_CLICKED
     BUTTON2_RESERVED_EVENT BUTTON3_RELEASED BUTTON3_PRESSED BUTTON3_CLICKED
     BUTTON3_DOUBLE_CLICKED BUTTON3_TRIPLE_CLICKED BUTTON3_RESERVED_EVENT
     BUTTON4_RELEASED BUTTON4_PRESSED BUTTON4_CLICKED BUTTON4_DOUBLE_CLICKED
     BUTTON4_TRIPLE_CLICKED BUTTON4_RESERVED_EVENT BUTTON_CTRL
     BUTTON_SHIFT    BUTTON_ALT      ALL_MOUSE_EVENTS REPORT_MOUSE_POSITION
     NCURSES_MOUSE_VERSION

curses(3) items not supported by `Curses'
-----------------------------------------

     Functions
     ---------
     tstp scanw wscanw mvscanw mvwscanw _putchar fullname

   [*] stdscr and curscr are also available via the Perl functions `stdscr'
and `curscr'.  See `"Perl 4.X cursperl Compatibility"' in this node for
more information.

Curses-based form handling for Curses::Widgets
**********************************************

NAME
====

   Curses::Forms - Curses-based form handling for Curses::Widgets

Doc/Module Version info
=======================

   $Id: Forms.pod,v 0.2 2000/02/29 08:47:25 corliss Exp $

SYNOPSIS
========

     use Curses::Forms;

     $form = Curses::Forms->new({ 'Y' => 1, 'X' => 0,
     	'LINES' => $LINES - 2, 'COLS' => $COLS });
     $form->add( { 'type' => 'list_box', 'name' => 'cal_list',
     	      'ypos' => 0, 'xpos' => 0,
     	      'lines' => 8, 'cols' => $COLS - 2,
     	      'title' => ' Calendars ', 'list' => \@list },
     	    { 'type' => 'txt_field', 'name' => 'record',
     	      'ypos' => 10, 'xpos' => 0, 'regex' => "\tqQ",
     	      'lines' => $LINES - 14, 'cols' => $COLS - 2,
     	      'title' => ' Record ', 'edit' => 0 });
     $form->set_defaults( DEF_FUNC => \&clock);
     $form->tab_order("cal_list");
     $form->bind(
     	["cal_list", "[ \n]", "Mod_Oth", \&rtrv_cal_rec,
     		"record" ],
     	["cal_list", "[qQ]", "Quit_Form"],
     	["cal_list", "[bB]", "Mod_Oth", \&browse_cal,
     		"record" ]);
     $form->activate;

REQUIREMENTS
============

   Requires the Curses module, Curses or nCurses libraries, and
Curses::Widgets.  You must still 'use Curses;' in your script, as well as
'use Curses::Widgets'.  Curses::Widgets v1.1 is the minimum version needed.

DESCRIPTION
===========

   This module provides an object-oriented approach to managing separate
forms composed of multiple widgets.  This approach removes the need to
code any handling for form navigation.  Only the list of widgets, the
widget tab order, and any special key/function bindings need be used.
Once the form is initialised, it handles everything else on its own.

PUBLIC METHODS
==============

   * new

   * add

   * bind

   * tab_order

   * set_defaults

   * activate

   * refresh_forms

METHODS
=======

new
---

   The 'new' method returns an object handle by which the form is both
initialised and managed.  One argument, in the form of an anonymous hash,
much be passed which specifies the desired geometry.

   This method merely creates and initialises the object, no error
checking is done outside of verifying that the following parameters were
passed:

     Parameter
     ------------------------------------------------
     Y	The y coordinate for the top-left corner
     	of the form
     X	The x coordinate for the top-left corner
     	of the form
     LINES	The number of lines in the form
     COLS	The number of columns in the form

     B<Example>

     $form = Curses::Forms->new({ 'Y' => 1, 'X' => 0,
     	'LINES' => $LINES - 2, 'COLS' => $COLS });

add
---

   The 'add' method is used to add widgets to the form, each widget being
passed as an anonymous hash.  All the necessary options for the specific
widget type must be passed, along with two other parameters:

     Parameters
     -----------
     type	The type of widget, as specified by the function name
     	in Curses::Widgets
     name	A unique name for referencing on the form (this will be
     	the identifier used in the tab_order and bind methods)

   The only error checking done at this point is ensuring that each widget
is named, and uniquely so, as well as ensuring that the widget type is a
type known to the module.  To get a list of options for the different
types of widgets, see the documentation for *Curses::Widgets*.

     B<Example>

     $form->add( { 'type' => 'list_box', 'name' => 'cal_list',
     	      'ypos' => 0, 'xpos' => 0,
     	      'lines' => 8, 'cols' => $COLS - 2,
     	      'title' => ' Calendars ', 'list' => \@list },
     	    { 'type' => 'txt_field', 'name' => 'record',
     	      'ypos' => 10, 'xpos' => 0, 'regex' => "\tqQ",
     	      'lines' => $LINES - 14, 'cols' => $COLS - 2,
     	      'title' => ' Record ', 'edit' => 0 });

bind
----

   The 'bind' method allows certain functions and actions to be bound to
specific widgets, and triggered by specific key strokes.  Each
action/function binding is passed as an anonymous array, each containing
the following fields, in the following order:

     Bind record
     -----------
     $anon[0]	The name of widget to bind the action to
     $anon[1]	The input regex which will trigger the
     		action (the widget must not trap for the
     		regex above, but must exit with that input
     		to allow the form to call this binding)
     $anon[2]	The action to be taken
     $anon[3]	The function to call (only needed for
     		Mod_Own/Mod_Oth)
     $anon[4]	The name of the widget to call the action
     		on (only needed for Mod_Oth)

     Actions
     ------------
     Quit_Form	Exit the activate routine, and return all
     		the current widget values
     Nxt_Wdgt	Move the active widget focus to the next
     		widget as specified by the tab order.
     Mod_Own		Call the specified function and pass it a
     		reference to the current widget's state hash
     Mod_Oth		Call the specified function and pass it a
     		reference to both the current and the
     		specified widget

   This method must not be called until the widgets are already added to
the form.  If you call it before, it will trigger a series of warnings
about attempts to bind to a non-existent widget.

   One should note that bindings for specific widgets and keys can be
stacked, with the bindings for that widget/key combination processed in
the order in which they were passed to the form.

   It is important to note that any function called must adhere to the
following guidelines:

     1)  It must accept two or three arguments, depending on
         whether the function must serve Mod_Own or Mod_Oth
         calls, respectively.  The first argument will always
         be the key pressed which activated the binding.  The
         second and third will be references to state hashes,
         where all widget options may be manipulated directly,
         according to the argument names listed in the
         B<Curses::Widgets> documentation for those widget types.
     2)  If desired, it may return the string "Quit_Form" if
         you wish it to exit the current form after calling
         that function.

   In the example below, the following routine will be bound to a list box
widget (as will be seen in the next example).  Upon pressing the 'a' key,
a input box will be displayed.  If the user enters either an A, R, W, or
O, the contents of the list box will be modified.  If the user presses a
'd' while the list box has the focus, though, the highlighted entry will
be deleted from the list.

     B<Example>

     local *mod_priv = sub {
         my $key = shift;
         my $in_ref = shift;
         my ($priv, $button, $prompt);

     if (lc($key) eq "a") {
     		$prompt = "Type 'A' for Administrative,\n " .
     		    "'R' for read,\n 'W' for write,\n or " .
     		    "'O' for other.";
     		($priv, $button) = input_box(
     		    'title' => 'Add Privilege',
     		    'prompt'=> $prompt, 'function' => \&clock);

     Curses::Forms->refresh_forms;

     if ($button) {
         $priv = uc($priv);
         if ($priv eq "A") {
     	push(@{$$in_ref{'list'}}, 'Administrative')
     	    unless (grep /Admin/, @{$$in_ref{'list'}});
          } elsif ($priv eq "R") {
     	push(@{$$in_ref{'list'}}, 'Read')
     	    unless (grep /Read/, @{$$in_ref{'list'}});
          } elsif ($priv eq "W") {
     	push(@{$$in_ref{'list'}}, 'Write')
     	    unless (grep /Write/, @{$$in_ref{'list'}});
          } elsif ($priv eq "O") {
     	push(@{$$in_ref{'list'}}, 'Other')
     	    unless (grep /Other/, @{$$in_ref{'list'}});
          } else {
     	status_bar(0, "'$_' is not a valid option.");
     	beep();
          }
          @{$$in_ref{'list'}} = sort @{$$in_ref{'list'}};
     }
     	    } elsif ($key =~ /^[Dd]$/) {
     splice(@{$$in_ref{'list'}}, $$in_ref{'selected'}, 1);
     	    }
     	};

   The following example shows the above function being bound to the list
box, which is named 'privs'.

     B<Example>

     $form->bind(["privs", "[aAdD]", "Mod_Own", \&mod_priv ],
     	["command", "[ \n]", "Mod_Own", \&action ]);

tab_order
---------

   The 'tab_order' method takes a list of widget names in the order that
they should be given the focus as the user navigates from one to the
other.  Note that you can leave widgets out of this order if their only
function is to display information pushed into them via the Mod_Oth
action, etc.  You can also redefine widget order as needed, since each
time the method is called, the entire order array is cleared before
processing the passed list.

   The only error-checking this method does is to verify that each widget
specified in the order was defined via the 'add' method.

     B<Example>

     $form->tab_order(qw( f_name email name psswd privs command ));

set_defaults
------------

   The 'set_defaults' method allows the setting of form-wide defaults.  It
is called with a series of key/value pairs, of which the following keys are
valid:

     Keys
     ------------
     DEF_FUNC	Subroutine reference, to be used in
     		the background while each widget is
     		waiting for input.  Defaults to ''.
     DEF_TAB		String, for interpolation in a regex
     		which will be the default key triggering
     		a change in focus to the next widget
     		in the tab order.  Defaults to "\t".
     DEF_ACTV	String, the default colour to be used
     		by widgets when they have the focus.
     		Colour choices are those supported by
     		the 'select_colour' function provided by
     		B<Curses::Widgets>.  Defaults to 'green'.
     DEF_INACTV	String, the default colour to be used
     		by widgets when they do not have the
     		focus.  Defaults to 'red'.
     BORDER		Boolean, a true or false value which
     		controls whether or not the form has a
     		border.  Defaults to 0.
     BORDER_COLOUR	String, with the colour to be used when
     		drawing the form border.  Defaults to
     		the default foreground colour.
     TITLE		String, the title to be superimposed on
     		the form border, or where the form border
     		would be if used.

   All arguments are optional, and if the defaults are acceptable, this
method can be completely ignored.  The only error-checking done is a check
on each key/value pair to see if they are a known option.

     B<Example>

     $form->set_defaults(DEF_FUNC => \&clock,
     		BORDER => 1,
     		BORDER_COLOUR => 'blue',
     		TITLE => ' Add User ');

activate
--------

   The 'activate' method is used for two purpose:  to simply display the
form in it's current state and immediately exit, and to display and
activate the form, capturing input and managing widget navigation until
the 'Quit_Form' action is recieved.

   To display the form, pass the method any argument that evaluates to
'true'.  To activate the form, call the method with no arguments.

   Error checking is done upon each call to ensure that the form geometry
won't exceed the current console dimensions, as well as for each widget,
to ensure their geometry doesn't exceed the form's dimensions.

     B<Example>

     $form->activate;

refresh_forms
-------------

   The 'refresh_forms' method is a class method, not an object method
(though calling it via the object reference will achieve the same
objective).  The purpose of this function to clean the screen of any form
remnants in background forms.  For example, consider the situation of
three forms with the following dimensions:

     +-Form 1----------------------------------------------------+
     |							    |
     | +-Form 2------------------------------+		    |
     | |					|		    |
     | |	+-Form 3-----------------------------+		    |
     | |	|				     |		    |
     | |	|				     |		    |
     | |	+------------------------------------+		    |
     | |					|		    |
     | +-------------------------------------+		    |
     +-----------------------------------------------------------+

   The scenario here is that an action taken on Form 1 prompted Form 2 to
pop up, and an action on Form 2 prompted Form 3 to be displayed.  Because
each form is created in its own private window (not a sub or derived
window from the master window created during Curses initialisation), when
Form 3, disappears, and Form 2 regains the focus, the region outside of
Form 2 will not be refreshed to remove the overlapping Form 3 region,
leaving you with the following:

     +-Form 1----------------------------------------------------+
     |							    |
     | +-Form 2------------------------------+		    |
     | |					|		    |
     | |					|----+		    |
     | |					|    |		    |
     | |					|    |		    |
     | |					|----+		    |
     | |					|		    |
     | +-------------------------------------+		    |
     +-----------------------------------------------------------+

   Calling this class method will send a touchwin and refresh signal to
each of the windows, from back to front, leaving you with:

     +-Form 1----------------------------------------------------+
     |							    |
     | +-Form 2------------------------------+		    |
     | |					|		    |
     | |					|		    |
     | |					|		    |
     | |					|		    |
     | |					|		    |
     | |					|		    |
     | +-------------------------------------+		    |
     +-----------------------------------------------------------+

   It is good to call this function whenever a child window is closed whose
borders extended past the parent window's borders.

     B<Example>

     Curses::Forms->refresh_forms;

Troubleshooting
===============

   Curses::Forms will never intentionally kill your script.  It does do
some basic checks upon creation and before executing certain methods, and
if it finds something amiss, it will use the warn function to report the
error.

   When testing scripts that use this module, you'd be well advised to pipe
STDERR to a file, so that it doesn't mess with the current display.
Checking that file later will show you what specific areas of the script
have problems.  Otherwise, the display might become corrupted, and cause
perfectly valid function calls to *appear* screwey, when it was only the
fact that the STDERR moved the cursor location before the next STDOUT
output could be rendered.

   If you run into problems that appear to be the fault of the module,
please send me the STDERR output and a script that demonstrates the
problem.

HISTORY
=======

   See the Changelog for in depth change history.

AUTHOR
======

   All bug reports, gripes, adulations, and comments can be sent to Arthur
Corliss, at *corliss@odinicfoundation.org*.

Curses-based widgets and functions
**********************************

NAME
====

   Curses::Widgets - Curses-based widgets and functions

Doc/Module Version info
=======================

   $Id: Widgets.pod,v 1.2 2000/03/17 00:30:03 corliss Exp corliss $

SYNOPSIS
========

     use Curses::Widgets;

     --or--

     use Curses::Widgets qw( :standard );	# same as above
     use Curses::Widgets qw( :functions );	# just functions
     use Curses::Widgets qw( :all );	 	# everything

REQUIREMENTS
============

   Requires the Curses module, Curses or nCurses libraries.  You must still
'use Curses;' in your script as well.

DESCRIPTION
===========

   This module provides a standard library of functions and widgets for
use in creating Curses-based interfaces.  Should work reliably with both
Curses and nCurses libraries.

   Current widgets include:

     Text field (txt_field)
     List box (list_box)
     Button sets (buttons)
     Calendar (calendar)
     Message box (msg_box)
     Input box (input_box)

   Extra functions include:

     select_colour
     line_split
     grab_key
     init_scr

   Note that all of the widgets strictly use named parameters, while the
functions use unamed arguments.  All of them either return values, or
modify references that were passed as arguments.

   Also note, for purpose of screen geometry, that all values passed for
specifying 'cols' and 'lines' refers only to the dimensions of the actual
content area, and does not include the border decorations.  You will
typically need to plan for an additional 2 for both 'cols' and 'lines' to
account for these.

EXPORTED
========

Default
-------

   * txt_field

   * buttons

   * list_box

   * calendar

   * msg_box

   * input_box

   * select_colour

   * init_scr

OK
--

   * line_split

   * grab_key

WIDGETS
=======

Text field
----------

   The text field widget creates a derived window (which uses coordinates
relative to the passed window) with a border surrounding the text.  When
used interactively, it handles its own input, passing back only the keys it
doesn't know how to handle, as well as the final content string and cursor
position.

   If border decorations are enabled (they are, by default), the widget
provides an arrow superimposed on the border to indicate whether there is
content that can be scrolled to in that direction.  The arrow only appears
when the content exceeds the display area.  The field is underlined if
border decorations are turned off.

   Currently, this widget will handle any normal characters to be inserted
into the content string, and the following keys:

     Key		Curses Constant
     -------------------------------
     backspace	KEY_BACKSPACE
     delete		KEY_DC
     left arrow	KEY_LEFT
     right arrow	KEY_RIGHT
     up arrow	KEY_UP
     down arrow	KEY_DOWN
     page up		KEY_PPAGE
     home		KEY_HOME,KEY_FIND
     end		KEY_END,KEY_SEARCH

   All parameters are passed as named parameters:

     Parameter	Commments
     -----------------------------------
     window		object handle to parent
     		window for the widget
     ypos		integer, optional,
     		default is 1
     xpos		integer, optional,
     		default is 1
     lines		integer, optional,
     		default is 1
     cols		integer, optional,
     		default is $COLS - 2
     content		string, optional,
     		default is "\n"
     password	integer, optional
     		default is 0
     pos		integer, optional
     		default is 0
     border		string, optional
     		default is 'red'
     decorations	integer, optional
     		default is 1
     edit		integer, optional
     		default is 1
     hz_scroll	integer, optional
     		default is 0
     function	reference, optional
     draw_only	integer, optional
     		default is 0
     l_limit		integer, optional
     c_limit		integer, optional
     title		string, optional
     regex		string, optional,
     		default is "\t"
     cursor_disable	integer, optional
     		default is 0

   'window' is a object handle to a predefined window or subwindow.  A
quick tip for debugging:  if either 'xpos', 'ypos', 'lines', or 'cols'
cause any portion of the window to extend passed the boundaries of the
parent window, the module will print an error message to STDERR, and
immediately exit the routine-no attempt will be made to draw or activate
the widget.

   'border' is the English name of the common console colours.  See the
'select_colour' function for a list of available colours.

   'content' is a string containing the text you wish to fill the field
with.

   'password' will cause all text to show up as asterixs when printed.
This is obviously intended for input that needs visual feedback, while
maintaining content security.

   'pos' refers to the cursor position for use in interactive mode, so
that input can be inserted or appended to the content string.  This is
ignored if passed in conjunction with the draw_only parameter.  Valid
settings are 0 - length($string), or -1 to place the cursor at the end of
the string.

   'decorations' enables or disables the border/title/arrow decorations on
the field.  When disabled, the field will be underlined, to give some
visual indication of the size of the field.

   'edit' turns on or off editing capabilities in the widget.  The field
is still navigable with all special keys, but no cursor will be printed,
and the content will not be affected by typed input.

   'hz_scroll' enables horizontal scrolling in the text field, instead of
the normal behaviour of splitting on white space and presenting a new
line.  This will only work with one line widgets.  If you call this widget
with any value of 'lines' greater than one, horizontal scrolling will
automatically be disabled.

   'function' is a scalar reference to a subroutine that can be called by
the widget when it times out, waiting for input.  For this to work, it
assumes a halfdelay(10) has been called, or on some other interval.

   'l_limit' and 'c_limit' are completely optional, and can be used
together, if desired.  Both are integers, and can limit the content in the
text field.  Which ever limit is hit first will be honoured.

   'title' is an optional string that will be superimposed over the
top-left border in reverse video.

   'regex' is a string of all the characters that you wish to use to shift
focus off the text field, and return the contents.  By default, the tab
character is used ("\t").  This string is interpolated inside of character
class brackets, so don't include regex specific punctuation.  If you wish
both new lines and tabs to shift focus, you would use "\t\n".

   'cursor_disable' disables the internal routine that prints it's own
cursor.  It's best used when you are passing it a background function that
updates another portion of the screen, otherwise, when that update occurs,
the cursor would disappear from the field.  However, if you don't have
such a function, the cursor will appear right next to the software cursor,
giving it the appearance of a two character cursor.  In those situations,
you should use this option to disable the software cursor.

   The memory allocated for the window is released when the widget routine
exits.

     B<Example (non-Interactive)>

     txt_field( 'window'	=> $window,
     	   'ypos'	=> 2,
     	   'xpos'	=> $COLS - 5,
     	   'lines'	=> $LINES - 10,
     	   'cols'	=> $COLS - 10,
     	   'content'	=> $note,
     	   'border'	=> 'red',
     	   'draw_only'	=> 1);

     B<(Interactive)>

     ($key, $rtrnd_note, $pos) = txt_field( 'window'	=> $window,
     				 'ypos'		=> 2,
     				 'xpos'		=> $COLS - 5,
     				 'lines'	=> $LINES - 10,
     				 'cols'		=> $COLS - 10,
     				 'content'	=> $note,
     				 'border'	=> 'green',
     				 'pos'		=> length($note),
     				 'function'	=> \&clock);

List box
--------

   The list box widget creates a derived window that holds a scrollable
list of items, surounded by a border.  When called interactively, it
handles it's own input for navigation.  Any keys not used for navigation
are returned, as well as the currently selected item, unless the 'regex'
option is used.  If so, it will only return if the key matches the regex.

     Key		Curses Constant
     -------------------------------
     up arrow	KEY_UP
     down arrow	KEY_DOWN
     page up		KEY_PPAGE
     page down	KEY_PPAGE

   The widget provides an arrow superimposed on the border to indicate
whether there is content that can be scrolled to in that direction.  The
arrow only appears when the content exceeds the display area.

   All parameters are passed as named parameters:

     Parameter	Commments
     -----------------------------------
     window		object handle to parent
     		window for the widget
     ypos		integer, optional,
     		default is 1
     xpos		integer, optional,
     		default is 1
     lines		integer, optional,
     		default is 1
     cols		integer, optional,
     		default is $COLS - 2
     list		hash or array reference
     border		string, optional
     		default is 'red'
     selected	integer, optional,
     		default is first element
     function	reference, optional
     draw_only	integer, optional
     		default is 0
     title		string, optional
     regex		string, optional
     sort		string, optional
     		default is 'numeric'

   All previously described parameters maintain their same use and
warnings.

   'list' can be either a hash reference or an array reference.  If a hash
is passed, the value will be displayed, but the key will be returned as the
selected entry.  The list will also be numerically sorted according to key
value when displayed.

   If 'list' is an array reference, the list will be displayed in array
order, and the index number of the element will be returned as the
selected value.

   'regex' works in the same manner as the the equivalent option in
txt_field.

   'sort' determines the type of sort used on the key values of lists
passed as hashes (it has no affect on lists passed as lists).  It defaults
to a 'numeric' sort, but if you wish it to use an 'alphabetic' sort, you
just need to set it accordingly.

     B<Example (non-Interactive)>

     list_box( 'window'	=> $main,
     	  'ypos'	=> 2,
     	  'lines'	=> 10,
     	  'cols'	=> 25,
     	  'list'	=> \%list,
     	  'border'	=> 'red',
     	  'selected'	=> 1,
     	  'draw_only'	=> 1);

     b<(Interactive)>

     ($input, $selected) = list_box( 'window'	=> $main,
     				'ypos'		=> 2,
     				'xpos'		=> 5,
     				'lines'		=> 10,
     				'cols'		=> 25,
     				'list'		=> \@list,
     				'border'	=> 'green',
     				'selected'	=> $last,
     				'function'	=> \&clock);

Button set
----------

   The button bar creates a derived window as well, printing the passed
buttons, and handles the key strokes to navigate amongst them, while
passing any other keystrokes and the currently selected button.  The
button set can be rendered either vertically or horizontally, and the
keystrokes that can be used for navigation depend upon that.  Like the
list_box, if the 'regex' option is used, it will only return on matching
values.

     Key		Curses Constant
     -------------------------------
     left arrow	KEY_LEFT
     right arrow	KEY_RIGHT
     up arrow	KEY_UP
     down arrow	KEY_DOWN

   All parameters are passed as named parameters:

     Parameter	Commments
     -----------------------------------
     window		object handle to parent
     		window for the widget
     buttons		reference
     ypos		integer, optional,
     		default is 1
     xpos		integer, optional,
     		default is 1
     active_button	integer, optional
     function	reference, optional
     vertical	integer, optional
     draw_only	integer, optional
     		default is 0
     spacing		integer, default is 2
     regex		string, optional

   Again, all previously described parameters remain the same.  Boundary
checking is still done for the entire bar, and if it exceeds them it will
simply be skipped without drawing, while sending an error message stating
as much to STDERR.

   'buttons' is an array reference with each element a separate button.
'active_button' is the element's positional reference.  'spacing' is the
number of whitespace used to separate the buttons (spaces in horizontal
mode, lines in vertical mode).

   If 'vertical' is passed with a Perlish true value the button set will be
rendered as a vertical set.

     B<Example (non-Interactive)>

     buttons( 'window'	=> $win_bar,
     	 'buttons'	=> \@buttons,
     	 'active_button'=> 2,
     	 'draw_only'	=> 1);

     b<(Interactive)>

     ($input, $selected) = buttons( 'windows'	=> $win_bar,
     			       'buttons'	=> \@buttons,
     			       'active_button'	=> $last,
     			       'function'	=> \&clock);

Calendar
--------

   The calendar widget creates a fully navigable calendar in a derived,
bordered window.  The calendar controls its own input until it captures a
keystroke it doesn't explicitly handle.  In that case, it returns the key.
Like the button_bar and list_box, though, this widget has a regex
function.

     Key		Curses Constant
     -------------------------------
     left arrow	KEY_LEFT
     right arrow	KEY_RIGHT
     up arrow	KEY_UP
     down arrow	KEY_DOWN
     home		KEY_HOME
     page up		KEY_PPAGE
     page down	KEY_NPAGE

   The home key, in this case, moves the selected date to the the current
date.  The page up and down keys move the calendar from month to month.

   All parameters are passed as named parameters:

     Parameter	Commments
     -----------------------------------
     window		object handle to parent
     		window for the widget
     ypos		integer, optional,
     		default is 1
     xpos		integer, optional,
     		default is 1
     date_disp	reference
     border		string, optional
     		default is 'red'
     function	reference, optional
     draw_only	integer, optional
     		default is 0
     t_colour	string, optional
     		default is 'yellow'
     e_colour	string, optional
     		default is 'red'
     events		reference
     regex		string, optional

   'date_disp' is an array reference that holds the desired date to
display (in day, month, year format).  If date_disp is not passed (or an
empty list reference is given instead), it will be initialised with the
current date.  Should the widget be called in interactive mode, the
reference will be modified to display the last date navigated to by the
user.  The first element, [0], is the day, the second, [1], the month, and
the third, [2], the year.

   't_colour' highlights the current date in the desired colour.  If
colour is not available, then the current date will be displayed in bold.
'e_colour' will highlight each date found in the 'events' array ref in the
desired colour.  Date formats for the 'event' array must be 'dd/mm/yyyy',
with no leading zeros.

     B<Example (non-Interactive)>

     calendar( 'window'	=> $main,
     	  'date_disp'	=> \@date,
     	  'border'	=> 'red',
     	  'draw_only'	=> 1);

     B<(Interactive)>

     $input = calendar( 'window'	=> $main,
     		   'date_disp'	=> \@date,
     		   'border'	=> 'blue',
     		   'function'	=> \&clock);

Message Box
-----------

   The msg_box displays the passed message in a new window that erases once
acknowledged.  It automatically scales and centers itself according to the
console and the passed message.

     Parameter	Commments
     -----------------------------------
     title		string, optional
     message		string, optional
     border		string, optional
     		defaults to 'blue'
     function	reference, optional
     mode		integer, optional

   All previously described options remain the same.  It only responds to
the ENTER or space key.  Mode refers to the buttons drawn with the
message.  By default, it only draws an OK button, but if set to 2, it will
display both an OK and a CANCEL button.  In that instance, the widget will
return a 1 if OK was selected, or a 0 if CANCEL was selected.

     B<Example>

     msg_box( 'title'	=> "Critical Error!",
     	 'message'	=> "Now, you've done it!",
     	 'border'	=> "red");

   Note that there is a minimum needed console size for this to work,
which is currently 5 rows by 14 columns.  If the console size is at least
that size, the message box will render.  Also note, though, that both the
message and the title may get chomped down to alloted window space, if you
pass it more than it can display.

   Further, if the function parameter is used, and the passed function
updates the screen, you may see the message box disappear, though it is
still trapping key strokes.  To avoid this behaviour, refresh the current
screen before calling this function.

Input Box
---------

   The input_box displays a dialog box with a prompt, a one-line input
field, and a two buttons, OK and *CANCEL*.  Like the msg_box, this widget
automatically scales and centers itself according to the prompt.

   Unlike the msg_box, however, this widget returns two values; the first
being the value of the text field, the second being a 1 if the OK button
was pressed, or a 0 if the *CANCEL* button was pressed.  Hitting ENTER
while in the text field is a shortcut for pressing the OK button.

     Parameter	Commments
     -----------------------------------
     title		string, optional
     prompt		string, optional
     cols		integer, optional
     border		string, optional
     		defaults to 'blue'
     f_colour	string, optional
     		defaults to 'yellow'
     c_limit		defaults to 4096
     content		string, optional
     function	reference, optional

   'cols' overrides the internally calculated width requirements (formerly
determined by the prompt width) to the specified setting.  This forces the
field width to be cols - 2 in width as well.

   'f_colour' is the colour to use for the text field border when it has
the focus.  It will use the same colour set in 'border'

   This widget requires a minimum console size for this to work, which is
8 rows by 24 columns.  Both the title and the prompt may be chomped to
accomodate available screen space.

   'c_limit' is simply passed to the text widget to restrict the length of
the typed string.  Horizontal scrolling is enabled.

     B<Example>

     ($field, $button) = input_box( 'title'		=> 'Password',
     			       'prompt'		=> 'Enter Password:',
     			       'border'		=> 'blue');

   If the function parameter is used, and the passed function updates the
screen, you may see the message box disappear, though it is still trapping
key strokes.  To avoid this behaviour, refresh the current screen before
calling this function.

FUNCTIONS
=========

select_colour
-------------

   Usage:  *select_colour($window, foreground [, background])*

   This function sets the character attributes for all subsequent
characters to the specified colour, for the specified window.  The first
two arguments are required, the first being an object handle to the
window, and the second a string denoting the desired foreground colour.  A
background colour can also be given, but if not, it defaults to black.

   Valid colours are black, cyan, green, magenta, red, white, blue, and
yellow.  All attributes stay in effect until another set is declared, or
all attributes are reset via *attrset(0)*.

     B<Example>

     select_colour($main, 'yellow');

init_scr
--------

   Usage: *init_scr($miny, $minx)*

   This function tests the terminal for both minimum dimensions and
interactivity.  If either condition is detected to be unsatisfactory, it
produces a warning on STDERR, and returns a false condition.  If it tests
okay, however, it will return a handle to a new Curses object.  It will
also set the default keypad, halfdelay, noecho, and cbreak options.

   The miny and minx, minimum lines and columns, respectively, are
optional.  If omitted, the standard console size of 25 lines by 80 columns
will be checked for.

     B<Example>

     $mwh = init_scr(40, 80);

line_split (not exported by default)
------------------------------------

   Usage:  *line_split(string, line_length)*

   This function returns the submitted string as a list, each element being
a separate line.  It accounts for not only column limits, but whitespace
as well, splitting a sentence by whitespace, so as to not break words.

     B<Example>

     @lines = line_split($note, 80);

grab_key (not exported by default)
----------------------------------

   Usage:  *grab_key($wh [, \&func_ref])*

   This function returns the pressed key, calling the passed function
reference while waiting.

   Only the first argument is mandatory, that being the object handle for
the window gathering the key strokes.  The function reference passed will
be called while waiting for a key to pressed, but only works if you've
initialised the console for half-blocking mode.  Ie., to call that function
every half a second:

     halfdelay(5);

Troubleshooting
===============

   Curses::Widgets will never intentionally kill your script.  It does do
some basic checks before executing some routines, and if it finds
something amiss, it will use the warn function to report the error.

   When testing scripts that use this module, you'd be well advised to pipe
STDERR to a file, so that it doesn't mess with the current display.
Checking that file later will show you what specific areas of the script
have problems.  Otherwise, the display might become corrupted, and cause
perfectly valid function calls to *appear* screwey, when it was only the
fact that the STDERR moved the cursor location before the next STDOUT
output could be rendered.

   You should also consider overloading the __DIE__ signal handler, to
make sure that Curses returns your terminal to a usable state in case of
fatal errors.

   If you run into problems that appear to be the fault of the module,
please send me the STDERR output and a script that demonstrates the
problem.

HISTORY
=======

   See the Changelog for in depth change history.  So far, I haven't broken
any of the default exported functions, so most scripts should run
unmodified.

   2000/02/21 - v1.1 Improved error handling/reporting, misc bug fixes, and
major feature additions to the input_box, txt_field, list_box, 		and
calendar.  Added init_scr function 2000/01/15 - v1.0 Version promotion for
first stable release 2000/01/15 - v0.10 Degugging, added input_box,
msg_box widgets 1999/11/17 - v0.9 Internal calendar generation, improved
error handling/ 		reporting, added spacing argument to button bar, removed
init_colours function 1999/06/17 - v0.8 Added line_split function, title
options, minor rewrites 1999/04/14 - v0.7 Added l_limit/c_limit to text
field 1999/02/02 - v0.6 Colour-capability detection added, up/down
charactersadded 		for content out-of-view indication, additional debugging
1999/01/11 - v0.5 Debugging 1999/01/10 - v0.4 Special key support added,
special character constants 		used, new select_colour function
1999/01/03 - v0.3 rewrite/optimisation 1998/12/30 - v0.2
rewrite/optimisation 1998/12/29 - v0.1 Initial release (text field, list
box, buttons, calendar)

AUTHOR
======

   All bug reports, gripes, adulations, and comments can be sent to Arthur
Corliss, at *corliss@odinicfoundation.org*.

get pathname of current working directory
*****************************************

NAME
====

   getcwd - get pathname of current working directory

SYNOPSIS
========

     use Cwd;
     $dir = cwd;

     use Cwd;
     $dir = getcwd;

     use Cwd;
     $dir = fastgetcwd;

     use Cwd 'chdir';
     chdir "/tmp";
     print $ENV{'PWD'};

     use Cwd 'abs_path';	    # aka realpath()
     print abs_path($ENV{'PWD'});

     use Cwd 'fast_abs_path';
     print fast_abs_path($ENV{'PWD'});

DESCRIPTION
===========

   The getcwd() function re-implements the getcwd(3) (or getwd(3))
functions in Perl.

   The abs_path() function takes a single argument and returns the
absolute pathname for that argument.  It uses the same algorithm as
getcwd().  (Actually, getcwd() is abs_path("."))  Symbolic links and
relative-path components ("." and "..") are resolved to return the
canonical pathname, just like realpath(3).  Also callable as realpath().

   The fastcwd() function looks the same as getcwd(), but runs faster.
It's also more dangerous because it might conceivably chdir() you out of a
directory that it can't chdir() you back into.  If fastcwd encounters a
problem it will return undef but will probably leave you in a different
directory.  For a measure of extra security, if everything appears to have
worked, the fastcwd() function will check that it leaves you in the same
directory that it started in. If it has changed it will die with the
message "Unstable directory path, current directory changed unexpectedly".
That should never happen.

   The fast_abs_path() function looks the same as abs_path(), but runs
faster.  And like fastcwd() is more dangerous.

   The cwd() function looks the same as getcwd and fastgetcwd but is
implemented using the most natural and safe form for the current
architecture. For most systems it is identical to `pwd` (but without the
trailing line terminator).

   It is recommended that cwd (or another *cwd() function) is used in all
code to ensure portability.

   If you ask to override your chdir() built-in function, then your PWD
environment variable will be kept up to date.  (See `Overriding Builtin
Functions', see Perlsub (perl.info).) Note that it will only be
kept up to date if all packages which use chdir import it from Cwd.

conversions of charset encodings for the Czech language
*******************************************************

NAME
====

   Cz::Cstocs - conversions of charset encodings for the Czech language

SYNOPSIS
========

     use Cz::Cstocs;
     my $il2_to_ascii = new Cz::Cstocs 'il2', 'ascii';
     while (<>)
     	{ print &$il2_to_ascii($_); }

     use Cz::Cstocs 'il2_ascii';
     while (<>)
     	{ print il2_ascii($_); }

     use Cz::Cstocs;
     sub il2toascii;
     	# inform the parser that there is a function il2toascii
     *il2toascii = new Cz::Cstocs 'il2', 'ascii';
     	# now define the function
     print il2toascii $data;
     	# thanks to Jan Krynicky for poining this out

DESCRIPTION
===========

   This module helps in converting texts between various charset
encodings, used for Czech and Slovak languages. The instance of the object
*Cz::Cstocs* is created using method new. It takes at least two parameters
for input and output encoding and can be afterwards used as a function
reference to convert strings/lists.  Cz::Cstocs supports fairly free form
of aliases, so iso8859-2, ISO-8859-2, iso88592 and il2 are all aliases of
the same encoding.  For backward compatibility, method *conv* is supported
as well, so the example above could also read

     while (<>)
     	{ print $il2_to_ascii->conv($_); }

   You can also use typeglob syntax.

   The conversion function takes a list and returns list of converted
strings (in the list context) or one string consisting of concatenated
results (in the scalar context).

   You can modify the behaviour of the conversion function by specifying
hash of other options after the encoding names in call to new.

fillstring
     Gives alternate string that will replace characters from input
     encoding that are not present in the output encoding. Default is
     space.

use_accent
     Defines whether the accent file should be used. Default is 1 (true).

nofillstring
     When 1 (true), will keep characters that do not have friends in
     accent nor output encoding, will no replace them with fillstring.
     Default is 0 except for tex, because you probably rather want to keep
     backslashed symbols than loose them.

cstocsdir
     Alternate location for encoding and accent files. The default is the
     `Cz/Cstocs/enc' directory in Perl library tree. This location can
     also be changed with the *CSTOCSDIR* environment variable.

   There is an alternate way to define the conversion function: any
arguments after use Cz::Cstocs that have form encoding_encoding or
encoding_to_encoding are processed and the appropriate functions are
imported. So,

     use Cz::Cstocs qw(pc2_to_il2 il2_ascii);

   define two functions, that are loaded into caller's namespace and can
be used directly. In this case, you cannot specify additional options, you
only have default behaviour.

ERROR HANDLING
==============

   If you request an unknown encoding in the call to new Cz::Cstocs, the
conversion object is not defined and the variable $Cz::Cstocs::errstr is
set to the error message. When you specify unknown encoding in the use
call style (like `use Cz::Cstocs 'il2_ascii';'), the die is called.

AUTHOR
======

   Jan Pazdziora, adelton@fi.muni.cz, created the module version.

   Jan "Yenya" Kasprzak has done the original Un*x implementation.

VERSION
=======

   3.182

SEE ALSO
========

   cstocs(1), perl(1).

Czech sort
**********

NAME
====

   Cz::Sort - Czech sort

SYNOPSIS
========

     use Cz::Sort;
     my $result = czcmp("_x j&á", "_&p");
     my @sorted = czsort qw(plachta plaòka Plánièka plánièka plánì);
     print "@sorted\n";

DESCRIPTION
===========

   Implements czech sorting conventions, indepentent on current locales in
effect, which are often bad. Does the four-pass sort. The idea and the
base of the conversion table comes from Petr Olsak's program *csr* and the
code is as compliant with CSN 97 6030 as possible.

   The basic function provided by this module, is *czcmp*. If compares two
scalars and returns the (-1, 0, 1) result. The function can be called
directly, like

     my $result = czcmp("_x j&á", "_&p");

   But for convenience and also because of compatibility with older
versions, there is a function *czsort*. It works on list of strings and
returns that list, hmm, sorted. The function is defined simply like

     sub czsort
     	{ sort { czcmp($a, $b); } @_; }

   standard use of user's function in sort. Hashes would be simply sorted

     @sorted = sort { czcmp($hash{$a}, $hash{$b}) }
     					keys %hash;

   Both *czcmp* and *czsort* are exported into caller's namespace by
default, as well as *cscmp* and *cssort* that are just aliases.

   This module comes with encoding table prepared for ISO-8859-2 (Latin-2)
encoding. If your data come in different one, you might want to check the
module *Cstocs* which can be used for reencoding of the list's data prior
to calling *czsort*, or reencode this module to fit your needs.

VERSION
=======

   0.68

SEE ALSO
========

   perl(1), Cz::Cstocs(3).

AUTHOR
======

   (c) 1997-2000 Jan Pazdziora <adelton@fi.muni.cz>,
http://www.fi.muni.cz/~adelton/

   at Faculty of Informatics, Masaryk University, Brno

Routines for printing dates in Czech
************************************

NAME
====

   Cz::Time - Routines for printing dates in Czech

SYNOPSIS
========

     use Cz::Time;
     my $today = cz_wday() . " " . cz_date();
     my $new_year = " 1. " . cz_month_base(1);

DESCRIPTION
===========

   Implements czech names of months and weekdays. The following functions
are exported:

cz_date
     Converts time (localtime if not specified) into Czech string, eg.
     15. ledna 1997.

cz_month_base, cz_month
     Czech names of months (1..12)

cz_wday, cz_ab_wday
     Czech names of weekdays and weekdays' abreviation.

   By default they are returned in ISO-8859-2.

AUTHORS
=======

   (c) 1997 Jan Pazdziora <adelton@fi.muni.cz>,     1997 Michael Mráka
<michael@fi.muni.cz>

   at Faculty of Informatics, Masaryk University, Brno

VERSION
=======

   0.02

SEE ALSO
========

   perl(1), Cz::Cstocs(3).

Debug module
************

NAME
====

   D'oh - Debug module

SYNOPSIS
========

     #!/usr/bin/perl -w
     use D'oh;
     D'oh::stderr();
     D'oh::stderr('/tmp/stderr');

     #print date and script name/pid to STDERR
     D'oh::date();

     #redirect STDOUT
     D'oh::stdout();
     D'oh::stdout('/tmp/stdout');
     D'oh::date('STDOUT');

     print "hellloooooo\n";
     die "world";

     __END__

     tail /tmp/stdout
     #===== myscript [1743]: Mon Feb  2 11:27:41 1998 =====#
     hellloooooo

     tail /tmp/stderr
     #===== myscript [1743]: Wed Apr  1 11:24:39 1998 =====#
     # world.
     File '/export/home/chrisn/bin/myscript'; Line 15

DESCRIPTION
===========

   The module, when used, prints all `STDERR' (or STDOUT) to a given file,
which is by default `/tmp/D'oh'.

BUGS
====

   Also, multiple scripts can write simultaneously to the same error file,
making it really messy.  If you don't like this, then select different
files for each script or whatever.

Mac OS
======

   Mac OS does not like to have multiple opens to the same file.  Use
different files.  The default directory for the files is `$ENV{TMPDIR}' in
MacPerl, not `/tmp'.

AUTHOR
======

   Chris Nandor, pudge@pobox.com, http://pudge.net/

   Copyright (c) 1998 Chris Nandor.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

VERSION
=======

   Version 0.05 (02 February 1998)

Catch stupid mistakes when mucking with years, like Y2K bugs
************************************************************

NAME
====

   D'oh::Year - Catch stupid mistakes when mucking with years, like Y2K
bugs

SYNOPSIS
========

     use D'oh::Year;

     ($year) = (localtime)[5];
     print "We're going to party like its 19$year";  # No you're not.

     print "Welcome to the year 20$year!";   # Sorry, Buck.

DESCRIPTION
===========

   NO, PERL DOES NOT HAVE A Y2K BUG! but alot of people seem determined to
add it.  Perl, and most other languges through various historical reasons,
like to return years in the form of the number of years since 1900.  This
has led to the false assumption that its actually returning the last two
digits of the current year (1999 => 99) and the mistaken assumption that
you can set the current year as "19$year".

   This is a Y2K bug, the honor is not just given to COBOL progrmamers.

   Bugs of this nature can easily be detected (most of the time) by an
automated process.  This is it.

   When D'oh::Year is used, it provides special versions of localtime() and
gmtime() which return a rigged value for the year.  When used properly
(usually 1900 + $year) you'll notice no difference.  But when used for
*EVIL* it will die with a message about misuse of the year.

   The following things are naughty (where $year is from gmtime() or
localtime()):

     "19$year",  19.$year
     "20$year",  20.$year
     "200$year", 200.$year
     $year -= 100, $year = $year - 100;

   *THE FOLLOWING ARE THE CORRECT WAYS TO MANIPULATE THE DATE* Take note,
please.

     $year += 1900;  # Get the complete year.
     $year %= 100;   # Get the last two digits of the year.
                     # ie "01" in 2001 and "99" in 1999

USAGE
=====

   Its simple.  Just use (do not require!) the module.  If it detects a
problem, it will cause your program to abort with an error.  If you don't
like this, you can use the module with the `:WARN' tag like so:

     use D'oh::Year qw(:WARN);

   and it will warn upon seeing a year mishandling instead of dying.

   Because there is a *slight* performance loss when using D'oh::Year, you
might want to only use it during development and testing.  A few
suggestions for use...

*Shove it down their throats*
     Set up /usr/bin/perl on your development machine as a shell wrapper
     around perl which always uses D'oh::Year:

          #!/bin/sh

          perl -MD::oh::Year $@

     This might be a little draconian for normal usage.

*Add it to your test harness*
*Make a quick check*
     `perl -MD::oh::Year myprogram'

CAVEATS
=======

   This program does its checking at *run time* not compile time.  Thus it
is not simply enough to slap D'oh::Year on a program, run it once and
expect it to find everything.  For a thourough scrubbing you must make
sure every line of code is excersied... but you already have test
harnesses set up to do that, RIGHT?!

TODO
====

*sort @times*
     Sorting time()'s as strings is a common mistake.  I can't detect it
     without some XS code to look at the op stack.

*printf "19%02d", $year*
     I can't handle this without being able to override printf(), but can't
     do that because it has a complex prototype.  This could be handled,
     but it would require a patch to pp_printf.  I can do sprintf(), but I
     don't think its wise to be non-orthoganal and lead non-doc readers on
     that if sprintf() is handled, printf() should be, too.

AUTHOR
======

   Original idea by Andrew Langmead

   Original code by Mark "The Ominous" Dominous

   Cleaned up and maintained by Michael G Schwern <schwern@pobox.com>.

programmatic interface to the Perl debugging API (draft, subject to change)
***************************************************************************

NAME
====

   DB - programmatic interface to the Perl debugging API (draft, subject to
change)

SYNOPSIS
========

     package CLIENT;
     use DB;
     @ISA = qw(DB);

     # these (inherited) methods can be called by the client

     CLIENT->register()      # register a client package name
     CLIENT->done()          # de-register from the debugging API
     CLIENT->skippkg('hide::hide')  # ask DB not to stop in this package
     CLIENT->cont([WHERE])       # run some more (until BREAK or another breakpt)
     CLIENT->step()              # single step
     CLIENT->next()              # step over
     CLIENT->ret()               # return from current subroutine
     CLIENT->backtrace()         # return the call stack description
     CLIENT->ready()             # call when client setup is done
     CLIENT->trace_toggle()      # toggle subroutine call trace mode
     CLIENT->subs([SUBS])        # return subroutine information
     CLIENT->files()             # return list of all files known to DB
     CLIENT->lines()             # return lines in currently loaded file
     CLIENT->loadfile(FILE,LINE) # load a file and let other clients know
     CLIENT->lineevents()        # return info on lines with actions
     CLIENT->set_break([WHERE],[COND])
     CLIENT->set_tbreak([WHERE])
     CLIENT->clr_breaks([LIST])
     CLIENT->set_action(WHERE,ACTION)
     CLIENT->clr_actions([LIST])
     CLIENT->evalcode(STRING)  # eval STRING in executing code's context
     CLIENT->prestop([STRING]) # execute in code context before stopping
     CLIENT->poststop([STRING])# execute in code context before resuming

     # These methods will be called at the appropriate times.
     # Stub versions provided do nothing.
     # None of these can block.

     CLIENT->init()          # called when debug API inits itself
     CLIENT->stop(FILE,LINE) # when execution stops
     CLIENT->idle()          # while stopped (can be a client event loop)
     CLIENT->cleanup()       # just before exit
     CLIENT->output(LIST)    # called to print any output that API must show

DESCRIPTION
===========

   Perl debug information is frequently required not just by debuggers,
but also by modules that need some "special" information to do their job
properly, like profilers.

   This module abstracts and provides all of the hooks into Perl internal
debugging functionality, so that various implementations of Perl debuggers
(or packages that want to simply get at the "privileged" debugging data)
can all benefit from the development of this common code.  Currently used
by Swat, the perl/Tk GUI debugger.

   Note that multiple "front-ends" can latch into this debugging API
simultaneously.  This is intended to facilitate things like debugging with
a command line and GUI at the same time, debugging debuggers etc.  [Sounds
nice, but this needs some serious support - GSAR]

   In particular, this API does not provide the following functions:

   * data display

   * command processing

   * command alias management

   * user interface (tty or graphical)

   These are intended to be services performed by the clients of this API.

   This module attempts to be squeaky clean w.r.t `use strict;' and when
warnings are enabled.

Global Variables
----------------

   The following "public" global names can be read by clients of this API.
Beware that these should be considered "readonly".

$DB::sub
     Name of current executing subroutine.

%DB::sub
     The keys of this hash are the names of all the known subroutines.
     Each value is an encoded string that has the sprintf(3) format
     `("%s:%d-%d", filename, fromline, toline)'.

$DB::single
     Single-step flag.  Will be true if the API will stop at the next
     statement.

$DB::signal
     Signal flag. Will be set to a true value if a signal was caught.
     Clients may check for this flag to abort time-consuming operations.

$DB::trace
     This flag is set to true if the API is tracing through subroutine
     calls.

@DB::args
     Contains the arguments of current subroutine, or the `@ARGV' array if
     in the toplevel context.

@DB::dbline
     List of lines in currently loaded file.

%DB::dbline
     Actions in current file (keys are line numbers).  The values are
     strings that have the sprintf(3) format `("%s\000%s", breakcondition,
     actioncode)'.

$DB::package
     Package namespace of currently executing code.

$DB::filename
     Currently loaded filename.

$DB::subname
     Fully qualified name of currently executing subroutine.

$DB::lineno
     Line number that will be executed next.

API Methods
-----------

   The following are methods in the DB base class.  A client must access
these methods by inheritance (*not* by calling them directly), since the
API keeps track of clients through the inheritance mechanism.

CLIENT->register()
     register a client object/package

CLIENT->evalcode(STRING)
     eval STRING in executing code context

CLIENT->skippkg('D::hide')
     ask DB not to stop in these packages

CLIENT->run()
     run some more (until a breakpt is reached)

CLIENT->step()
     single step

CLIENT->next()
     step over

CLIENT->done()
     de-register from the debugging API

Client Callback Methods
-----------------------

   The following "virtual" methods can be defined by the client.  They will
be called by the API at appropriate points.  Note that unless specified
otherwise, the debug API only defines empty, non-functional default
versions of these methods.

CLIENT->init()
     Called after debug API inits itself.

CLIENT->prestop([STRING])
     Usually inherited from DB package.  If no arguments are passed,
     returns the prestop action string.

CLIENT->stop()
     Called when execution stops (w/ args file, line).

CLIENT->idle()
     Called while stopped (can be a client event loop).

CLIENT->poststop([STRING])
     Usually inherited from DB package.  If no arguments are passed,
     returns the poststop action string.

CLIENT->evalcode(STRING)
     Usually inherited from DB package.  Ask for a STRING to be eval-ed in
     executing code context.

CLIENT->cleanup()
     Called just before exit.

CLIENT->output(LIST)
     Called when API must show a message (warnings, errors etc.).

BUGS
====

   The interface defined by this module is missing some of the later
additions to perl's debugging functionality.  As such, this interface
should be considered highly experimental and subject to change.

AUTHOR
======

   Gurusamy Sarathy	gsar@activestate.com

   This code heavily adapted from an early version of perl5db.pl
attributable to Larry Wall and the Perl Porters.

DBI driver for CSV files
************************

NAME
====

   DBD::CSV - DBI driver for CSV files

SYNOPSIS
========

     use DBI;
     $dbh = DBI->connect("DBI:CSV:f_dir=/home/joe/csvdb")
         or die "Cannot connect: " . $DBI::errstr;
     $sth = $dbh->prepare("CREATE TABLE a (id INTEGER, name CHAR(10))")
         or die "Cannot prepare: " . $dbh->errstr();
     $sth->execute() or die "Cannot execute: " . $sth->errstr();
     $sth->finish();
     $dbh->disconnect();

     # Read a CSV file with ";" as the separator, as exported by
     # MS Excel. Note we need to escape the ";", otherwise it
     # would be treated as an attribute separator.
     $dbh = DBI->connect(qq{DBI:CSV:csv_sep_char=\\;});
     $sth = $dbh->prepare("SELECT * FROM info");

     # Same example, this time reading "info.csv" as a table:
     $dbh = DBI->connect(qq{DBI:CSV:csv_sep_char=\\;});
     $dbh->{'csv_tables'}->{'info'} = { 'file' => 'info.csv'};
     $sth = $dbh->prepare("SELECT * FROM info");

WARNING
=======

   THIS IS ALPHA SOFTWARE. It is *only* 'Alpha' because the interface (API)
is not finalized. The Alpha status does not reflect code quality or
stability.

DESCRIPTION
===========

   The DBD::CSV module is yet another driver for the DBI (Database
independent interface for Perl). This one is based on the SQL "engine"
SQL::Statement and the abstract DBI driver DBD::File and implements access
to so-called CSV files (Comma separated values). Such files are mostly
used for exporting MS Access and MS Excel data.

   See `DBI(3)' in this node for details on DBI, `SQL::Statement(3)' in
this node for details on SQL::Statement and `DBD::File(3)' in this node
for details on the base class DBD::File.

Prerequisites
-------------

   The only system dependent feature that DBD::File uses, is the flock()
function. Thus the module should run (in theory) on any system with a
working flock(), in particular on all Unix machines and on Windows NT.
Under Windows 95 and MacOS the use of flock() is disabled, thus the module
should still be usable,

   Unlike other DBI drivers, you don't need an external SQL engine or a
running server. All you need are the following Perl modules, available
from any CPAN mirror, for example

     ftp://ftp.funet.fi/pub/languages/perl/CPAN/modules/by-module

DBI
     the DBI (Database independent interface for Perl), version 1.00 or a
     later release

SQL::Statement
     a simple SQL engine

Text::CSV_XS
     this module is used for writing rows to or reading rows from CSV
     files.

Installation
------------

   Installing this module (and the prerequisites from above) is quite
simple.  You just fetch the archive, extract it with

     gzip -cd DBD-CSV-0.1000.tar.gz | tar xf -

   (this is for Unix users, Windows users would prefer WinZip or something
similar) and then enter the following:

     cd DBD-CSV-0.1000
     perl Makefile.PL
     make
     make test

   If any tests fail, let me know. Otherwise go on with

     make install

   Note that you almost definitely need root or administrator permissions.
If you don't have them, read the ExtUtils::MakeMaker man page for details
on installing in your own directories. See ExtUtils/MakeMaker.

Creating a database handle
--------------------------

   Creating a database handle usually implies connecting to a database
server.  Thus this command reads

     use DBI;
     my $dbh = DBI->connect("DBI:CSV:f_dir=$dir");

   The directory tells the driver where it should create or open tables
(a.k.a. files). It defaults to the current directory, thus the following
are equivalent:

     $dbh = DBI->connect("DBI:CSV:");
     $dbh = DBI->connect("DBI:CSV:f_dir=.");

   You may set other attributes in the DSN string, separated by semicolons.

Creating and dropping tables
----------------------------

   You can create and drop tables with commands like the following:

     $dbh->do("CREATE TABLE $table (id INTEGER, name CHAR(64))");
     $dbh->do("DROP TABLE $table");

   Note that currently only the column names will be stored and no other
data.  Thus all other information including column type (INTEGER or
CHAR(x), for example), column attributes (NOT NULL, PRIMARY KEY, ...) will
silently be discarded. This may change in a later release.

   A drop just removes the file without any warning.

   See `DBI(3)' in this node for more details.

   Table names cannot be arbitrary, due to restrictions of the SQL syntax.
I recommend that table names are valid SQL identifiers: The first
character is alphabetic, followed by an arbitrary number of alphanumeric
characters. If you want to use other files, the file names must start with
'/', './' or '../' and they must not contain white space.

Inserting, fetching and modifying data
--------------------------------------

   The following examples insert some data in a table and fetch it back:
First all data in the string:

     $dbh->do("INSERT INTO $table VALUES (1, "
              . $dbh->quote("foobar") . ")");

   Note the use of the quote method for escaping the word 'foobar'. Any
string must be escaped, even if it doesn't contain binary data.

   Next an example using parameters:

     $dbh->do("INSERT INTO $table VALUES (?, ?)", undef,
     	     2, "It's a string!");

   Note that you don't need to use the quote method here, this is done
automatically for you. This version is particularly well designed for
loops. Whenever performance is an issue, I recommend using this method.

   You might wonder about the undef. Don't wonder, just take it as it is.
:-) It's an attribute argument that I have never ever used and will be
parsed to the prepare method as a second argument.

   To retrieve data, you can use the following:

     my($query) = "SELECT * FROM $table WHERE id > 1 ORDER BY id";
     my($sth) = $dbh->prepare($query);
     $sth->execute();
     while (my $row = $sth->fetchrow_hashref) {
         print("Found result row: id = ", $row->{'id'},
               ", name = ", $row->{'name'});
     }
     $sth->finish();

   Again, column binding works: The same example again.

     my($query) = "SELECT * FROM $table WHERE id > 1 ORDER BY id";
     my($sth) = $dbh->prepare($query);
     $sth->execute();
     my($id, $name);
     $sth->bind_columns(undef, \$id, \$name);
     while ($sth->fetch) {
         print("Found result row: id = $id, name = $name\n");
     }
     $sth->finish();

   Of course you can even use input parameters. Here's the same example
for the third time:

     my($query) = "SELECT * FROM $table WHERE id = ?";
     my($sth) = $dbh->prepare($query);
     $sth->bind_columns(undef, \$id, \$name);
     for (my($i) = 1;  $i <= 2;   $i++) {
     	$sth->execute($id);
     	if ($sth->fetch) {
     	    print("Found result row: id = $id, name = $name\n");
     	}
         $sth->finish();
     }

   See `DBI(3)' in this node for details on these methods. See
`SQL::Statement(3)' in this node for details on the WHERE clause.

   Data rows are modified with the UPDATE statement:

     $dbh->do("UPDATE $table SET id = 3 WHERE id = 1");

   Likewise you use the DELETE statement for removing rows:

     $dbh->do("DELETE FROM $table WHERE id > 1");

Error handling
--------------

   In the above examples we have never cared about return codes. Of course,
this cannot be recommended. Instead we should have written (for example):

     my($query) = "SELECT * FROM $table WHERE id = ?";
     my($sth) = $dbh->prepare($query)
         or die "prepare: " . $dbh->errstr();
     $sth->bind_columns(undef, \$id, \$name)
         or die "bind_columns: " . $dbh->errstr();
     for (my($i) = 1;  $i <= 2;   $i++) {
     	$sth->execute($id)
     	    or die "execute: " . $dbh->errstr();
     	if ($sth->fetch) {
     	    print("Found result row: id = $id, name = $name\n");
     	}
     }
     $sth->finish($id)
         or die "finish: " . $dbh->errstr();

   Obviously this is tedious. Fortunately we have DBI's *RaiseError*
attribute:

     $dbh->{'RaiseError'} = 1;
     $@ = '';
     eval {
         my($query) = "SELECT * FROM $table WHERE id = ?";
         my($sth) = $dbh->prepare($query);
         $sth->bind_columns(undef, \$id, \$name);
         for (my($i) = 1;  $i <= 2;   $i++) {
     	    $sth->execute($id);
     	    if ($sth->fetch) {
     	        print("Found result row: id = $id, name = $name\n");
     	    }
         }
         $sth->finish($id);
     };
     if ($@) { die "SQL database error: $@"; }

   This is not only shorter, it even works when using DBI methods within
subroutines.

Metadata
--------

   The following attributes are handled by DBI itself and not by DBD::File,
thus they all work as expected:

     Active
     ActiveKids
     CachedKids
     CompatMode             (Not used)
     InactiveDestroy
     Kids
     PrintError
     RaiseError
     Warn                   (Not used)

   The following DBI attributes are handled by DBD::File:

AutoCommit
     Always on

ChopBlanks
     Works

NUM_OF_FIELDS
     Valid after `$sth->execute'

NUM_OF_PARAMS
     Valid after `$sth->prepare'

NAME
     Valid after `$sth->execute'; undef for Non-Select statements.

NULLABLE
     Not really working. Always returns an array ref of one's, as DBD::CSV
     doesn't verify input data. Valid after `$sth->execute'; undef for
     non-Select statements.

   These attributes and methods are not supported:

     bind_param_inout
     CursorName
     LongReadLen
     LongTruncOk

   In addition to the DBI attributes, you can use the following dbh
attributes:

f_dir
     This attribute is used for setting the directory where CSV files are
     opened. Usually you set it in the dbh, it defaults to the current
     directory ("."). However, it is overwritable in the statement handles.

csv_eol
csv_sep_char
csv_quote_char
csv_escape_char
csv_class
csv_csv
     The attributes csv_eol, csv_sep_char, csv_quote_char and
     csv_escape_char are corresponding to the respective attributes of the
     Text::CSV_XS object. You want to set these attributes if you have
     unusual CSV files like `/etc/passwd' or MS Excel generated CSV files
     with a semicolon as separator. Defaults are "\015\012", ';', '"' and
     '"', respectively.

     The attributes are used to create an instance of the class csv_class,
     by default Text::CSV_XS. Alternatively you may pass an instance as
     csv_csv, the latter takes precedence. Note that the binary attribute
     must be set to a true value in that case.

     Additionally you may overwrite these attributes on a per-table base in
     the csv_tables attribute.

csv_tables
     This hash ref is used for storing table dependent metadata. For any
     table it contains an element with the table name as key and another
     hash ref with the following attributes:

    file
          The tables file name; defaults to

               "$dbh->{f_dir}/$table"

    eol
    sep_char
    quote_char
    escape_char
    class
    csv
          These correspond to the attributes csv_eol, csv_sep_char,
          csv_quote_char, csv_escape_char, csv_class and csv_csv.  The
          difference is that they work on a per-table base.

    col_names
    skip_first_row
          By default DBD::CSV assumes that column names are stored in the
          first row of the CSV file. If this is not the case, you can
          supply an array ref of table names with the col_names attribute.
          In that case the attribute skip_first_row will be set to FALSE.

          If you supply an empty array ref, the driver will read the first
          row for you, count the number of columns and create column names
          like `col0', `col1', ...

   Example: Suggest you want to use `/etc/passwd' as a CSV file. :-) There
simplest way is:

     require DBI;
     my $dbh = DBI->connect("DBI:CSV:f_dir=/etc;csv_eol=\n;"
                            . "csv_sep_char=:;csv_quote_char=;"
                            . "csv_escape_char=");
     $dbh->{'csv_tables'}->{'passwd'} = {
         'col_names' => ["login", "password", "uid", "gid", "realname",
                         "directory", "shell"]
     };
     $sth = $dbh->prepare("SELECT * FROM passwd");

   Another possibility where you leave all the defaults as they are and
overwrite them on a per table base:

     require DBI;
     my $dbh = DBI->connect("DBI:CSV:");
     $dbh->{'csv_tables'}->{'passwd'} = {
         'eol' => "\n",
         'sep_char' => ":",
         'quote_char' => undef,
         'escape_char' => undef,
         'file' => '/etc/passwd',
         'col_names' => ["login", "password", "uid", "gid", "realname",
                         "directory", "shell"]
     };
     $sth = $dbh->prepare("SELECT * FROM passwd");

Driver private methods
----------------------

   These methods are inherited from DBD::File:

data_sources
     The data_sources method returns a list of subdirectories of the
     current directory in the form "DBI:CSV:directory=$dirname".

     If you want to read the subdirectories of another directory, use

          my($drh) = DBI->install_driver("CSV");
          my(@list) = $drh->data_sources('f_dir' => '/usr/local/csv_data' );

list_tables
     This method returns a list of file names inside $dbh->{'directory'}.
     Example:

          my($dbh) = DBI->connect("DBI:CSV:directory=/usr/local/csv_data");
          my(@list) = $dbh->func('list_tables');

     Note that the list includes all files contained in the directory, even
     those that have non-valid table names, from the view of SQL. See
     `Creating and dropping tables' in this node above.

Data restrictions
-----------------

   When inserting and fetching data, you will sometimes be surprised:
DBD::CSV doesn't correctly handle data types, in particular NULLs. If you
insert integers, it might happen, that fetch returns a string. Of course,
a string containing the integer, so that's perhaps not a real problem. But
the following will never work:

     $dbh->do("INSERT INTO $table (id, name) VALUES (?, ?)",
              undef, "foo bar");
     $sth = $dbh->prepare("SELECT * FROM $table WHERE id IS NULL");
     $sth->execute();
     my($id, $name);
     $sth->bind_columns(undef, \$id, \$name);
     while ($sth->fetch) {
         printf("Found result row: id = %s, name = %s\n",
               defined($id) ? $id : "NULL",
               defined($name) ? $name : "NULL");
     }
     $sth->finish();

   The row we have just inserted, will never be returned! The reason is
obvious, if you examine the CSV file: The corresponding row looks like

     "","foo bar"

   In other words, not a NULL is stored, but an empty string. CSV files
don't have a concept of NULL values. Surprisingly the above example works,
if you insert a NULL value for the name! Again, you find the explanation
by examining the CSV file:

     ""

   In other words, DBD::CSV has "emulated" a NULL value by writing a row
with less columns. Of course this works only if the rightmost column is
NULL, the two rightmost columns are NULL, ..., but the leftmost column
will never be NULL!

   See `Creating and dropping tables' in this node above for table name
restrictions.

TODO
====

   Extensions of DBD::CSV:

CSV file scanner
     Write a simple CSV file scanner that reads a CSV file and attempts to
     guess sep_char, quote_char, escape_char and eol automatically.

   These are merely restrictions of the DBD::File or SQL::Statement
modules:

Joins
     The current version of the module works with single table SELECTs
     only, although the basic design of the SQL::Statement module allows
     joins and the like.

Table name mapping
     Currently it is not possible to use files with names like `names.csv'.
     Instead you have to use soft links or rename files. As an alternative
     one might use, for example a dbh attribute 'table_map'. It might be a
     hash ref, the keys being the table names and the values being the file
     names.

Column name mapping
     Currently the module assumes that column names are stored in the first
     row. While this is fine in most cases, there should be a possibility
     of setting column names and column number from the programmer: For
     example MS Access doesn't export column names by default.

KNOWN BUGS
==========

   * The module is using flock() internally. However, this function is not
     available on platforms. Using flock() is disabled on MacOS and Windows
     95: There's no locking at all (perhaps not so important on these
     operating systems, as they are for single users anyways).

AUTHOR AND COPYRIGHT
====================

   This module is Copyright (C) 1998 by

     Jochen Wiedmann
     Am Eisteich 9
     72555 Metzingen
     Germany

     Email: joe@ispsoft.de
     Phone: +49 7123 14887

   All rights reserved.

   You may distribute this module under the terms of either the GNU
General Public License or the Artistic License, as specified in the Perl
README file.

SEE ALSO
========

   `DBI(3)' in this node, `Text::CSV_XS(3)' in this node,
`SQL::Statement(3)' in this node

   For help on the use of DBD::CSV, see the DBI users mailing list:

     http://www.isc.org/dbi-lists.html

   For general information on DBI see

     http://www.symbolstone.org/technology/perl/DBI

Base class for writing DBI drivers for plain files
**************************************************

NAME
====

   DBD::File - Base class for writing DBI drivers for plain files

SYNOPSIS
========

     use DBI;
     $dbh = DBI->connect("DBI:File:f_dir=/home/joe/csvdb")
         or die "Cannot connect: " . $DBI::errstr;
     $sth = $dbh->prepare("CREATE TABLE a (id INTEGER, name CHAR(10))")
         or die "Cannot prepare: " . $dbh->errstr();
     $sth->execute() or die "Cannot execute: " . $sth->errstr();
     $sth->finish();
     $dbh->disconnect();

DESCRIPTION
===========

   The DBD::File module is not a true DBI driver, but an abstract base
class for deriving concrete DBI drivers from it. The implication is, that
these drivers work with plain files, for example CSV files or INI files.
The module is based on the SQL::Statement module, a simple SQL engine.

   See `DBI(3)' in this node for details on DBI, `SQL::Statement(3)' in
this node for details on SQL::Statement and `DBD::CSV(3)' in this node or
`DBD::IniFile(3)' in this node for example drivers.

Metadata
--------

   The following attributes are handled by DBI itself and not by DBD::File,
thus they all work like expected:

     Active
     ActiveKids
     CachedKids
     CompatMode             (Not used)
     InactiveDestroy
     Kids
     PrintError
     RaiseError
     Warn                   (Not used)

   The following DBI attributes are handled by DBD::File:

AutoCommit
     Always on

ChopBlanks
     Works

NUM_OF_FIELDS
     Valid after `$sth-'execute>

NUM_OF_PARAMS
     Valid after `$sth-'prepare>

NAME
     Valid after `$sth-'execute>; undef for Non-Select statements.

NULLABLE
     Not really working, always returns an array ref of one's, as DBD::CSV
     doesn't verify input data. Valid after `$sth-'execute>; undef for
     Non-Select statements.

   These attributes and methods are not supported:

     bind_param_inout
     CursorName
     LongReadLen
     LongTruncOk

   Additional to the DBI attributes, you can use the following dbh
attribute:

f_dir
     This attribute is used for setting the directory where CSV files are
     opened. Usually you set it in the dbh, it defaults to the current
     directory ("."). However, it is overwritable in the statement handles.

Driver private methods
----------------------

data_sources
     The data_sources method returns a list of subdirectories of the
     current directory in the form "DBI:CSV:f_dir=$dirname".

     If you want to read the subdirectories of another directory, use

          my($drh) = DBI->install_driver("CSV");
          my(@list) = $drh->data_sources('f_dir' => '/usr/local/csv_data' );

list_tables
     This method returns a list of file names inside $dbh->{'f_dir'}.
     Example:

          my($dbh) = DBI->connect("DBI:CSV:f_dir=/usr/local/csv_data");
          my(@list) = $dbh->func('list_tables');

     Note that the list includes all files contained in the directory, even
     those that have non-valid table names, from the view of SQL. See
     `Creating and dropping tables' in this node above.

TODO
====

Joins
     The current version of the module works with single table SELECT's
     only, although the basic design of the SQL::Statement module allows
     joins and the likes.

Table name mapping
     Currently it is not possible to use files with names like `names.csv'.
     Instead you have to use soft links or rename files. As an alternative
     one might use, for example a dbh attribute 'table_map'. It might be a
     hash ref, the keys being the table names and the values being the file
     names.

KNOWN BUGS
==========

   * The module is using flock() internally. However, this function is not
     available on all platforms. Using flock() is disabled on MacOS and
     Windows 95: There's no locking at all (perhaps not so important on
     MacOS and Windows 95, as there's a single user anyways).

AUTHOR AND COPYRIGHT
====================

   This module is Copyright (C) 1998 by

     Jochen Wiedmann
     Am Eisteich 9
     72555 Metzingen
     Germany

     Email: joe@ispsoft.de
     Phone: +49 7123 14887

   All rights reserved.

   You may distribute this module under the terms of either the GNU
General Public License or the Artistic License, as specified in the Perl
README file.

SEE ALSO
========

   `DBI(3)' in this node, `Text::CSV_XS(3)' in this node,
`SQL::Statement(3)' in this node

JDBC proxy driver for the DBI module
************************************

NAME
====

   DBD::JDBC - JDBC proxy driver for the DBI module

SYNOPSIS
========

     use DBI;

     $dbh = DBI->connect("dbi:JDBC:hostname=$hostname;port=$port;url=$url",
                         $user, $password);

     # See the DBI module documentation.

REQUIRES
========

     Perl 5.004 or higher
     DBI 1.13 or higher
     Convert::BER 1.31
     Java Virtual Machine compatible with JDK 1.1
     A JDBC driver

DESCRIPTION
===========

   DBD::JDBC is a Perl module which works in conjunction with a server
written in Java to provide a DBI front end to a JDBC driver. The Perl
module and Java server may be installed on different machines, as long as
socket connections are allowed. The Java server portion is multi-threaded
and supports multiple simultaneous connections.

   This driver currently supports JDBC drivers which implement the JDBC
1.22 interface.  JDBC 2.0-compatible drivers are expected to work, but no
JDBC 2.0 functionality is explicitly exposed via DBD::JDBC. The DBI
`$h->func' method exposes additional JDBC and driver-specific methods.
Only Java methods with primitive or String parameters and return types are
currently supported in this way.

   The expected use for this module is as a DBI interface to databases
with JDBC drivers but no DBI drivers. The implementation of this module
was originally done for a non-SQL database in order to take advantage of
the existing SQL parser in the database's JDBC driver.

   The Java classes provided with this module also allow a Java
application or servlet to create a JDBC connection and then execute a Perl
script which can use that pre-existing JDBC connection via DBI. This
particular functionality was implemented in order to allow Perl
customizations to a Java servlet-based application. See the example in the
`example/' directory.

CONNECTING
==========

   Before using DBD::JDBC, you must start the DBD::JDBC server.

Starting the server
-------------------

   The DBD::JDBC server is a Java application intended to be run from the
command line. It may be installed, along with whatever JDBC driver you
wish to use, on any host capable of accessing the database you wish to use
via JDBC. Perl applications using DBD::JDBC will open a socket connection
to this server. You will need to know the hostname and port where this
server is running.

   To start the server,

  1. Place the dbd_jdbc.jar file and your database's JDBC driver on the
     machine where you wish to run the server.

  2. Add dbd_jdbc.jar and your database's JDBC driver to your classpath.
     Follow any other instructions which came with your JDBC driver. For
     example, a type 2 JDBC driver may require that the database's native
     libraries be added to your path or library path.

  3. Start the server, providing at least the required system properties
     on the command line:

    jdbc.drivers *(required)*
          This should be set to the complete class name of your JDBC
          driver. If you want to use more than one JDBC driver, use a
          colon-separated list of driver names. See the standard Javadoc
          documentation for `java.sql.DriverManager' for an example.

    dbd.port *(required)*
          This is the port to which this server will listen. Your Perl
          client applications will need to know this in order to connect.

    dbd.trace
          If set, this value indicates the tracing level for the server.
          Tracing output will be written to stderr. Legal values are
          silent (the default), `brief', verbose, `tedious', and `abusive'.

        Example

     java -Djdbc.drivers=foo.bar.Driver -Ddbd.port=12345 com.vizdom.dbd.jdbc.Server

   Here is a simple example shell script for running the server (written
for bash).

     export CLASSPATH=dbd_jdbc.jar:/oracle/jdbc/classes111.zip:$CLASSPATH
     DRIVERS=oracle.jdbc.driver.OracleDriver
     java -Djdbc.drivers=$DRIVERS -Ddbd.port=9001 -Ddbd.trace=tedious com.vizdom.dbd.jdbc.Server

Connecting to the server
------------------------

   A dsn for DBD::JDBC has the following form:

     dbi:JDBC:hostname=$host;port=$port;url=$url;jdbc_character_set=$charset

   where

   * $host is the hostname on which the DBD::JDBC server is running
     (optionally followed by `:$port'; if so, the port name/value pair is
     optional).

   * $port is the port on which the DBD::JDBC server is running.

   * `$url' is a complete JDBC url for your JDBC driver. You might want to
     test this URL in a Java application (in the same environment in which
     you intend to run the DBD::JDBC server) before attempting to connect
     from Perl. Your JDBC url may need to include your database host and
     port information; these values are distinct from those needed in the
     DBD::JDBC dsn, which are for the DBD::JDBC server, not the database.

     If the JDBC url contains the characters ';' or '=', those characters
     must be URL-encoded. For example,

          $url =~ s/([=;])/uc sprintf("%%%02x",ord($1))/eg;

     The driver will unescape the url before sending it to the JDBC
     driver. [See the driver code if you really want to know why.]

   * $charset is the character set used by your DBI application (i.e. the
     character set in use on whichever machine is running Perl, not the
     machine running the DBD::JDBC server, unless they're the same). This
     should be specified in the form of a valid Java character encoding
     name. If no character set is given, the driver defaults to ISO8859_1.
     See
     http://java.sun.com/products/jdk/1.1/docs/guide/intl/encoding.doc.html
     for a list of supported encodings. The character set name must be
     encoded in ASCII so that the server can appropriately decode it.

     Any strings sent to the DBD::JDBC server as parameter values will be
     converted from this encoding to Unicode (Java's native encoding). Use
     `bind_param' and a type hint to avoid character set conversion of
     binary data. Data being returned as strings (everything other than
     binary columns) will be converted to this encoding.

     The character set in use will be available as the database handle
     attribute 'jdbc_character_set'. Changing this attribute will have no
     effect on character conversion; the character set is established at
     connection time.

   Example

     $dsn = "dbi:JDBC:hostname=myhost;port=12345;url=jdbc:odbc:mydatasource";
     $dsn = "dbi:JDBC:hostname=myhost:12345;url=jdbc:oracle:thin:\@mydbhost:1521:test;jdbc_character_set=ASCII";

USAGE NOTES
===========

Calling JDBC methods
--------------------

   JDBC methods are exposed using the DBI `$h->func' method and Java
reflection. This feature is not intended to replace any existing DBI
methods, merely to provide access to JDBC-specific methods with no DBI
equivalent. Reflection, rather than explicit methods corresponding to
methods in the JDBC API, is used in order to allow access to
driver-specific methods not in the JDBC API.

   The following limitations apply:

   * Only public methods can be called.

   * In general, only methods whose parameters and return values are
     primitive types (int, boolean, void, etc.) or Strings can be called.
     See below for more details.

   * DBD::JDBC doesn't know which methods are being called when reflection
     is used. This means that interleaving DBI methods and calls to JDBC
     methods using `func' may leave DBD::JDBC in an inconsistent state.
     One example of this is `$sth->rows': if you've called
     `ResultSet.next' directly, rather than using `$sth->fetch', the row
     count will not accurately reflect the rows in the result set.

   * Methods can only be called on the Connection, Statement, ResultSet,
     and ResultSetMetaData objects.

   The JDBC method name is used as the func method name. Parameters are
passed as strings by default. To pass parameters of other types, pass the
parameter as reference to an array in which the first element is the
parameter and the second is one of the DBI SQL_XXX typecodes. For example,

     $h->func("string parameter", [11 => SQL_INTEGER],
              [1 => SQL_BIT], "method_name");

   It is very important to use the correct typecodes for the actual
parameter types of the Java method in order to enable Java reflection to
locate the correct method. The method will be looked up using the
`java.lang.class.getMethod(String, Class[])' method, so if the parameter
types don't match the actual method parameters, the method won't be found.

   SQL types are mapped to Java types by mapping the DBI constants to
values from java.sql.Types, then mapping the `java.sql.Types' values to
Java types.

     DBI constant           java.sql.Types constant    Java type
     -----------------------------------------------------------
     SQL_CHAR               CHAR                       String
     SQL_VARCHAR            VARCHAR                    String
     SQL_LONGVARCHAR        LONGVARCHAR                String
     SQL_BINARY             BINARY                     byte[]
     SQL_VARBINARY          VARBINARY                  byte[]
     SQL_LONGVARBINARY      LONGVARBINARY              byte[]
     SQL_BIT                BIT                        boolean
     SQL_TINYINT            TINYINT                    byte
     SQL_SMALLINT           SMALLINT                   short
     SQL_INTEGER            INTEGER                    int
     SQL_BIGINT             BIGINT                     long
     SQL_REAL               REAL                       float
     SQL_FLOAT              FLOAT                      double
     SQL_DOUBLE             DOUBLE                     double
     SQL_NUMERIC            NUMERIC                    java.math.BigDecimal
     SQL_DECIMAL            DECIMAL                    java.math.BigDecimal
     SQL_DATE               DATE                       java.sql.Date
     SQL_TIME               TIME                       java.sql.Time
     SQL_TIMESTAMP          TIMESTAMP                  java.sql.Timestamp

   The mapping from `java.sql.Types' to Java types is taken from Table
21.6.1 in *JDBC Data Access with Java*, by Hamilton, Cattell, and Fisher.
See also Table 47.9.1 in *JDBC API Tutorial and Reference, Second
Edition*, by White, Fisher, Cattell, Hamilton, and Hapner.

   For `SQL_DATE', `SQL_TIME', and `SQL_TIMESTAMP' parameters, the default
JDBC string representations for these types must be used.

     SQL_DATE: yyyy-mm-dd
     SQL_TIME: hh:mm:ss
     SQL_TIMESTAMP: yyyy-mm-dd hh:mm:ss.f

   (The `.f' portion of the timestamp format is in nanoseconds and is
optional.)

   Possible return values from `$h->func' are undef if the Java method
returned null or had a void return type, 1 or 0 if the Java method had a
boolean return type, or a scalar for any other return type (the Object
returned by `java.lang.reflect.Method.invoke' will be converted to a String
by calling its toString method).

   You are not limited to calling methods defined by the JDBC API. Any
public method defined by your JDBC driver on the available objects, with
parameters and return type as described above, may be called.

   *Important*: You must check for errors explicitly after calling `func'.
For example,

     $h->func("method");
     if ($h->err) {
        ## handle error
     }

   *Connection methods*

   To call JDBC methods on the JDBC Connection object, use the `func'
method on the $dbh handle.

   Examples

     $ret = $dbh->func("getAutoCommit");
         $dbh->func([1 => SQL_BIT], "setAutoCommit");
         $ret = $dbh->func("select * from client", "nativeSQL");
         $dbh->func([4 => SQL_INTEGER], "setTransactionIsolation");

   *Statement, ResultSet, and ResultSetMetaData methods*

   To call JDBC methods on the JDBC Statement, ResultSet, and
ResultSetMetaData objects, use the `func' method on the $sth handle and
prefix the method name with one of the listed interface names. You may use
either Statement or PreparedStatement to indicate the current
PreparedStatement object, since DBD::JDBC uses PreparedStatements
internally.

   ResultSet and ResultSetMetaData methods are not available until after
`$sth->execute' has been called.

   Examples

     $ret = $sth->func("Statement.getMaxFieldSize");
     $sth1->func("mycursor", "Statement.setCursorName");
     $sth1->func([22 => SQL_INTEGER], "Statement.setMaxFieldSize");

     $ret = $sth1->func("ResultSet.next");
     $ret = $sth1->func("cname", "ResultSet.getString");
     $ret = $sth2->func("eno", [5003 => SQL_INTEGER], "ResultSet.updateInt");

     $ret = $sth1->func([1 => SQL_INTEGER], "ResultSetMetaData.getSchemaName");

   Notes

   If for some reason you reach the end of a ResultSet using
`$sth->func("ResultSet.next")' rather than one of the standard DBI methods
(fetch, etc.), the DBI statement handle will continue to think that it's
active. You must call `$sth->finish' explicitly in this case.

   Be aware of which JDBC methods are called by the standard DBI methods.
For example, `$sth->fetch' calls next and reads all the columns in the
current row. With some JDBC drivers, you will not be able to call
$sth->fetch followed by `$sth->func("column_name", "ResultSet.getString")'
because all the data for the row has already been read.

   If you are using a JDBC driver with scrollable result sets, please note
that support for such is provided purely through `func', not through any
explicit DBD::JDBC support. This means that a loop over the set, such as

     while ($row = $sth->fetch()) {
         # do something
     }

   will cause DBD::JDBC to mark the statement handle as inactive at the
end of the loop (`$sth->{Active}' will be false). You can still use `func'
to operate on the underlying ResultSet, but you can't continue to use any
DBI method which requires that the statement handle be active. The
following sequence seems to work, though perhaps it shouldn't:

     while ($row = $sth->fetch()) {
         # do something
     }
     $sth->func("ResultSet.beforeFirst");
     while ($row = $sth->fetch()) {
         # do something else
     }

   Some sort of explicit support for scrollable result sets will probably
be implemented at a later date.

Closing cursors
---------------

   When a statement handle goes out of scope, Perl will call its DESTROY
method. This method will cause `Statement.close' to be called on the
associated Java Statement object in the DBD::JDBC server. For many
applications, this is sufficient. However, if you find that statement
handles are not being destroyed quickly enough, or you are maintaining a
collection of statements for repeated use, you may choose to close the
ResultSet associated with the Statement explicitly using `func'. Closing
the ResultSet will not prevent you from executing the statement again, but
it will release any database resources held by the ResultSet.

   Typical usage:

     $sth = $dbh->prepare("select id from sched");
     $sth->execute();
     while ($row = $sth->fetch()) {
         # do something
     }
     # At this point, the statement handle is no longer active, but
     # the ResultSet still exists on the server.
     $sth->func("ResultSet.close");

   DBD::JDBC does not close ResultSet objects when `$sth->finish' is
called (whether it is called implicitly when the end of the result set is
reached or explicitly in your program) in order to support scrollable
result sets. With a scrollable result set, reaching the end of the data
does not mean that the ResultSet is unusable, so calling close would be
unfortunate.

Character sets
--------------

   You can find out what character set Java thinks your platform uses by
examining the value of the system property `file.encoding'.

     System.out.println("This system uses: " + System.getProperty("file.encoding"));

   Local experimentation (in the US) indicates that Windows NT uses
"Cp1252" (Windows Latin-1) and Unix variants (AIX, Solaris) use
"ISO8859_1".

jdbc_error
----------

   When a JDBC exception is thrown in the server, the exception and any
exceptions chained to the original are returned and placed in the
jdbc_error attribute of the most-recently-used handle. This attribute will
contain an array of hashrefs with keys err, `errstr', and state. The first
error's values will also be available via `$h->err', `$h->errstr', and
`$h->state'.

     foreach $err (@{$sth->{jdbc_error}}) {
         print "Error: ($err->{err}/$err->{state}) $err->{errstr}\n";
     }

DBI to JDBC method mappings
---------------------------

   What follows is a guide to the JDBC methods being called when a DBI
method or property is accessed. See the source code for
`com.vizdom.dbd.jdbc.Connection' for details.

DBI->connect
          DriverManager.getConnection(url, username, password)
          Connection.setAutoCommit   [if AutoCommit was specified]

$dbh->prepare
          Connection.prepareStatement(statement)

$dbh->commit
          Connection.commit()

$dbh->rollback
          Connection.rollback()

$dbh->disconnect
          PreparedStatement.close()   [for each open statement]
          Connection.close()

$dbh->ping
          Connection.isClosed()

$dbh->{AutoCommit}
          Connection.getAutoCommit()
          Connection.setAutoCommit()

$sth->execute
          PreparedStatement.setXXX(value)   [if there are any parameters]
          PreparedStatement.execute()
          PreparedStatement.getResultSet()
          PreparedStatement.getUpdateCount()

$sth->fetch
          ResultSet.next()
          ResultSet.getXXX

$sth->{CursorName}
          ResultSet.getCursorName()

$sth->{NAME}
          ResultSetMetaData.getColumnName()

$sth->{TYPE}
          ResultSetMetaData.getColumnType()

$sth->{PRECISION}
          ResultSetMetaData.getPrecision()

$sth->{SCALE}
          ResultSetMetaData.getScale()

$sth->{NULLABLE}
          ResultSetMetaData.isNullable()

$sth->DESTROY
          [This is called automatically when a statement handle
          goes out of scope]

          Statement.close()

Statement parameters and column values
--------------------------------------

   Parameter values are sent to the DBD::JDBC server as a sequence of
bytes. Numeric parameters are encoded as strings rather than numbers (so
11 is sent as the two characters '1' '1').

   When the DBD::JDBC server receives the parameter values, the bytes are
converted to a Java String (using the character encoding specified at
connection time by the jdbc_character_set value) and the
PreparedStatement.setString() method is used to set the parameter value.

   If a type hint (one of the SQL_XXX types you can import from the DBI
module) is supplied along with a parameter in `$sth->bind_param()', the
type code will be mapped to the corresponding JDBC type code and passed
along to the DBD::JDBC server. The JDBC type will be used to determine
which PreparedStatement.setXXX method to call. The mapping from type hint
to setXXX method is taken from Table 21.2, p. 394, in *JDBC Data Access
with Java*.

     BINARY, VARBINARY, LONGVARBINARY: setBytes
     TINYINT, SMALLINT: setShort
     INTEGER: setInt
     BIGINT: setLong
     REAL: setFloat
     FLOAT, DOUBLE: setDouble
     DECIMAL, NUMERIC: setBigDecimal
     BIT: setBoolean
     CHAR, VARCHAR, LONGVARCHAR, DATE, TIME, TIMESTAMP: setString

   Type hints are required for binary data in order to avoid having binary
parameter values passed through the default character conversion process.
In other cases, they are generally optional and may in fact reduce
performance by causing unneccessary data conversions. For example, if your
database's JDBC driver passes all data to the database as strings, the
JDBC driver will have to convert numbers back to strings anyway.

   A call to `$sth->fetch' will cause the DBD:JDBC server to use the
column type information from ResultSetMetaData to determine how to
retrieve column data.

     Column type         Method used
     BINARY, VARBINARY   getBytes
     LONGVARBINARY       getBinaryStream
     LONGVARCHAR         getUnicodeStream
     all others          getString

   Once retrieved, the data is returned to Perl as a sequence of bytes.
The caller may choose whether to treat the returned scalar as a character
string, number, or byte string.

NUM_OF_PARAMS implementation
----------------------------

   The statement attribute NUM_OF_PARAMS is set when `$dbh->prepare' is
called. Since JDBC doesn't expose this information about
PreparedStatements, DBD::JDBC uses a simple '?'  counting method which may
fail to provide an accurate count if the parameter marker is not '?' or
the syntax does not conform to standard SQL (and possibly even if it does,
if I've interpreted the SQL grammar poorly). Depending on this value to be
accurate is not recommended, although you may find that it is sufficient
for your use.

DIAGNOSTICS
===========

   All errors generated by DBD::JDBC have IJDBC as the SQLSTATE. If a
SQLException was thrown by the JDBC driver without a SQLSTATE, DBD::JDBC
will set the SQLSTATE to IDRVR.

Errors generated by the Perl driver
-----------------------------------

Unsupported AutoCommit value  (no error number)
     If you attempt to set AutoCommit to anything other than 0 or 1, the
     driver will die with this error.

Error code 100
     An error occurred while sending a request to the server.

Error code 101
     An error occurred while receiving a response from the server.

Error code 102
     There was a problem decoding a server response packet.

Error code 103
     The dsn supplied to connect is missing one or more required values.

Error code 104
     A connection to the server could not be established. The server may
     not be running, or the host or port information may be incorrect.

Error code 105
     An `$sth->execute' call caused the server to return an invalid
     response. This is an internal error.

Errors generated by the Java server
-----------------------------------

Error code 1
     The client requested an operation on a statement object which does not
     exist on the serer.

Error code 2
     fetch was called on a statement which has no data. For example, this
     error might result if fetch is called before a statement is executed.

Error code 3
     The server was asked to return the value of an unknown attribute.

Error code 4
     This error code indicates that the client attempted to do something
     which requires a cursor (a ResultSet) on the server, but no cursor is
     present.

Error code 5
     No metadata is currently available. This error will result if a
     request is made for a statement attribute at a time when no ResultSet
     is associated with the statement.

Error code 6
     This error code indicates that the client sent a message to the
     server which the server does not understand.

Error code 7
     The server was unable to respond to the client's request. This error
     would likely be sent as the result of another, undetected, error on
     the server.

Error code 8
     This error code is used when the server wishes to send a random error
     string to the client. For example, arbitrary Java exceptions may be
     sent with this error code.

Error code 9
     An error occurred during fetch. The error text will describe the
     actual error.

Error code 10
     This error code indicates that the client's requested character
     encoding is not supported.

Error code 11
     An error occurred while setting a statement parameter.

Error code 12
     A long field was truncated during fetch.

Error code 13
     A reflection request was made, but there's no object on which to call
     the indicated method. For example, trying to call `ResultSet.next'
     before calling `$sth->execute' will cause this error to be reported,
     since no ResultSet exists.

Error code 14
     An unknown class name was passed to `$sth->func'.

Error code 15
     A Java exception related to reflection was thrown. This may include,
     for example, `NoSuchMethodException' if the requested method can't be
     located.

TO DO
=====

   See the ToDo file included with the distribution. Highlights include

   * Make the complete JDBC interface available from DBI.

   * DBI metadata methods, cancel, row cache.

   * Better handling of long fields via some sort of streaming interface.

   * JDBC 2.0 support.

SEE ALSO
========

   perldoc DBI

   For general DBI information and questions, see the DBI home page at

     http://www.symbolstone.org/technology/perl/DBI/index.html

   This site contains pointers to archives of the DBI mailing lists and
list subscription information. DBI in general is primarily supported
through the dbi-users mailing list.

AUTHOR
======

   Gennis Emerson <gemerson@vizdom.com>

COPYRIGHT
=========

   Copyright 1999-2000 Vizdom Software, Inc. All Rights Reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as the Perl Kit, namely, under the terms of either:

   a) the GNU General Public License as published       by the Free
Software Foundation; either version 1       of the License, or (at your
option) any later       version, or

   b) the "Artistic License" that comes with the       Perl Kit.

   This program is distributed in the hope that it will be seful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.  See either the GNU General Public
License or the Artistic License for more details.

DBI Driver for Ovrimos (formerly Altera SQL Server)
***************************************************

NAME
====

   DBD::Ovrimos - DBI Driver for Ovrimos (formerly Altera SQL Server)

SYNOPSIS
========

     use DBI;
     my $dbh=DBI->connect(
          "dbi:Ovrimos:some.host.com:2500",
          "user",
          "passwd")
          or die "Cannot connect\n";
     # more DBI calls...

DESCRIPTION
===========

   DBI driver for Ovrimos (See `DBI(3)' in this node for details). This
driver is essentially a rename of DBD::Altera. Since DBI is a moving
target at the time of this writing, this driver should only be assumed to
work with DBI 0.93.  A standard notice in DBD drivers' man pages is that,
since the DBI is not yet stable, any DBD driver should be considered ALPHA
software. So be it.  We will try to keep up with the changes, stay tuned at
<http://www.altera.gr/download.html> which is the primary download site for
this driver.

CURRENT VERSION
===============

   Release 0.12 Name change...  Previous release were: Release 0.11
Essentially a bug-fix.  Release 0.10 (one hair short of 1.00). Main
difference from previous version 0.09 is minor alterations to permit use
for AGI (Another Gateway Interface).  In other words, how can one use the
same module to write both DBI programs and stored procedures for Ovrimos.
Also, stored procedures are now supported, using the pseudo-SQL "call xxx
..." statement. See the documentation of Ovrimos for details.

DRIVER-SPECIFIC BEHAVIOR
========================

DATA-SOURCE NAME
----------------

   The dsn string passed to DBI->connect must be of the following form:

     dbi:Ovrimos:host:port

   where host is a TCP/IP address in human-readable or dotted-decimal
format, and port is the TCP/IP port number to use (Ovrimos SQLPORT
configuration parameter).

CONNECTIONS, SESSIONS AND TRANSACTIONS
--------------------------------------

   One can have multiple connections to an Ovrimos database, up to the
limit specified by one's User License. Keep in mind that what the License
calls 'sessions' amount to what are called separate statements in DBI.
Underlying the DBI is a protocol using the ODBC-equivalent 'connections'
and 'statements'. Sessions are kept live until commit/rollback, and that
can result in denial of service if you reach the License limit. The
database handle will reuse an inactive statement handle, so finish() often.

   Commit/rollback finish()'es implicitly all open cursors (that's the
answer one asks ODBC with SQL_CURSOR_COMMIT_BEHAVIOR and
SQL_CURSOR_ROLLBACK_BEHAVIOR).

   Cached statements are not available. In the near future it is planned to
cache SQL statements internally at the SQL Server, so preparing the same
SQL statement as some time before will return a new $sth but without the
cost associated with preparing from scratch.

DATA TYPES
----------

   All ODBC 2.0 data types are supported. The format of time/date values is
as per the SQL/2 Standard, i.e.: 'DATE YYYY-MM-DD', 'TIME HH:MM:SS' and
'TIMESTAMP YYYY-MM-DD HH:MM:SS'.

   Ovrimos supports some additional types that are given below alongside
their numerical value:

UNSIGNED SMALLINT = 20
UNSIGNED INTEGER  = 21
UNSIGNED TINYINT  = 22
UNSIGNED BIGINT   = 23
ERROR HANDLING
--------------

   As it stands, the DBI does not support the notion of warnings.
Consequently, there are no diagnostics for successful calls.  There is no
obstacle in adding this, but since perl code using DBI will not check
$h->errstr for successful operations, there is not much incentive to
actually do it. Diagnostics for failed calls are inspected with the usual
DBI calls. Do not pay any attention to $h->err; it is dummy. Ovrimos
returns Standard SQL SQLSTATES and assorted messages, modelled principally
after ODBC use. Since many diagnostics can be accumulated by one call, the
diagnostics are merged, separated with newline. In that way, only the
first SQLSTATE in the queue is visible using $h->state. One has to parse
$h->errstr to find out the rest.

BLOBS
-----

   BLOBs are supported via the SQL2 types *LONG VARCHAR* and
*LONG VARBINARY*. These are not fetched with SQL queries and the
LongReadLen and LongTruncOk attributes are not honored. Instead, Ovrimos
presents a HTTP interface for retrieving BLOBS. Every BLOB has a Uniform
Resource Identifier that can be found using the built-in *URI* function.
This makes for easy retrieval of BLOBs in CGI scripts, where the URI can
be embedded in HTML constructs like this:

     my ($name,$uri1,$uri2);
     $sth->bind_columns(undef,\($name,$uri1,$uri2));

     $sth->prepare('select name,uri(blob1),uri(blob2) from blobtest');
     $sth->execute;

     while($sth->fetch) {
          print '<A HREF="' . $uri1 .'">Click here!<A> ';
          print '<IMG SRC="' . $uri2 . '" ALT="Image"><BR>', "\n";
     }

   BLOBs are MIME-typed so the HTTP browser knows how to handle them. If
one needs to retrieve a BLOB in an arbitrary script, one can use HTTP
facilities like those in the libwww bundle (see CPAN,
<http://cpan.perl.org/CPAN.html#libwww>). Or, one can just lead a simple
life and do

     require 5.002;
     use strict;
     use IO::Socket;
     my $host;
     my $file;
     my $port=80;
     if($uri =~ m[^http://(.*):(\d*)/(.*)]) {
          ($host,$port,$file)=($1,$2,$3);
     } elsif($uri =~ m[^http://(.*)/(.*)]) {
          ($host,$file)=($1,$2);
     } else {
          die "horribly";
     }
     my $so=IO::Socket::INET->new( Proto=>"tcp", PeerAddr=>$host,
          PeerPort=>$port) or die "in pain";
     print $so "GET /$file HTTP/1.0\r\n\r\n";
     $so->flush() or die "in agony";

   One can then proceed to read from $so after skipping the reply header.
If the MIME type is required, it can be found in the 'Content-type:'
attribute of the reply header.

   Maybe in a later release this functionality will be included in the
driver.

DRIVER-SPECIFIC ATTRIBUTES
--------------------------

   There are some additional attributes that the user can query a $sth for:

TYPE (also ovrimos_column_type)
     Reference to an array of column types as per ODBC, plus the Ovrimos
     extended types.  TYPE is in capitals because the values returned
     conform to approved standards (ODBC, X/Open).

ovrimos_column_precision
     Reference to an array of column precisions. Has meaning only for
     vector types (*CHAR, *BINARY) and NUMERIC/DECIMAL

ovrimos_column_scale
     Reference to an array of column scales. Has meaning only for
     NUMERIC/DECIMAL.

ovrimos_execution_plan
     It is a high-level explanation of the execution plan for the
     statement. The format is highly version-dependent and not to be
     dependent upon, but a human reader should be able to understand the
     access path for every range variable used, the order of range
     variables, the indices used, which temporary tables have been created
     et.c.

ovrimos_native_query
     The query submitted, but in the form retained by the SQL Server. The
     SQL Server applies transformations to the SQL source and
     disambiguates certain constructs. The modified source can also be
     found in the execution plan (see above).

LOW-LEVEL LIBRARY
-----------------

   The entire low-level library that implements the Ovrimos protocol is
included. The DBI driver is based on this library, but one could
conceivably use the library on its own. It is the only way, for the time
being, to use scrollable cursors and bookmarks, since the DBI does not
support them (yet?).  See the package `DBD::Ovrimos::lowlevel' in
`Ovrimos.pm'. No documentation is provided in this version about the
low-level library.

COMFORMANCE
===========

   There is a particularity concerning transactions: see `' in this node.

   Cached statements don't exist. Not even the function prepare_cached
exists.  Do not use it! You won't find any relevant attribute either.

KNOWN BUGS
==========

   There are no known bugs in the DBD Driver.

ACKNOWLEDGEMENTS
================

   I would like to thank all the people on the DBI-DEV mailing list that
helped clear some misunderstandings.

SEE ALSO
========

   DBI(3)

AUTHOR
======

     Dimitrios Souflis                  dsouflis@altera.gr,

COPYRIGHT
=========

     (c) Altera Ltd, Greece             http://www.altera.gr

   Permission is granted to use this software library according to the GNU
Library General Public License (see <http://www.gnu.org>).

Database fault tolerance through replication.
*********************************************

NAME
====

   DBD::Recall - Database fault tolerance through replication.

SYNOPSIS
========

     use DBI;

     my $replicas = '192.168.1.1:7000,192.168.1.2:7000,192.168.1.3:7000';
     my $dsn = "DBI:Recall:database=$replicas";

     my $drh = DBI->install_driver ($driver, { Replicas => $replicas });
     my @dbs = $drh->func( "_ListDBs" );
     print (join "\n",@dbs,"\n");

     my $dbh = DBI->connect($dsn);
     my @tables = $dbh->tables();
     print (join "\n",@tables,"\n");

DESCRIPTION
===========

   This module interfaces to Recall, a data replication library written by
Eric Newton, to provide transparent fault tolerance for database
applications.

   Recall is based on a data replication algorithm developed at DEC's SRC
for the Echo filesystem. It implements a fast protocol with low network
overhead and guranteed fault tolerance as long as n of 2n-1 replica nodes
are up.

   The DBD::Recall interface allows you to add fault tolerance to your
database applications by a trivial change in your code. Simply use this
module instead of the DBD you are currently using.

   To achieve replicated functionality you'll also need to set up a few
pieces of external infrastucture, such as the replica servers, and rsync
access between replicas. This is all described in greater detail in
`Replication::Recall::DBServer' in this node.

WARNING
=======

   DBD::Recall is a hack that attempts to accomplish something
(fault-tolerance through replication) at the perl DBD driver level that
would be better implemented by database servers. It works, but it is not
pretty.

   Some commercial servers, such as Oracle, do implement replication. If
speed and reliability are critical to your application, you will probably
be better off with one of the commercial databases that implement
replication within the database engine.

   I've only tried DBD::Recall with MySQL so far on Debian GNU/Linux. If
you get it to work with another database engine or on another operating
system, please email me about your experiences so I can include
information about your platform in future releases.

BUGS
====

   * Transparency is accomplished through a remote delegation hack which
     might break under certain circumstances. If this happens to you,
     please let me know.

   * There must be loads more. Let me know if you find some.

AUTHOR
======

   DBD::Recall is Copyright (c) 2000 Ashish Gulhati <hash@netropolis.org>.
All Rights Reserved.

ACKNOWLEDGEMENTS
================

   Thanks to Barkha for inspiration, laughs and all 'round good times; and
to Eric Newton, Gurusamy Sarathy, Larry Wall, Richard Stallman and Linus
Torvalds for all the great software.

LICENSE
=======

   This code is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

DISCLAIMER
==========

   This is free software. If it breaks, you own both parts.

DBI driver for XBase compatible database files
**********************************************

NAME
====

   DBD::XBase - DBI driver for XBase compatible database files

SYNOPSIS
========

     use DBI;
     my $dbh = DBI->connect("DBI:XBase:/directory/subdir")
     				or die $DBI::errstr;
     my $sth = $dbh->prepare("select MSG from test where ID != 1")
     				or die $dbh->errstr();
     $sth->execute() or die $sth->errstr();

     my @data;
     while (@data = $sth->fetchrow_array())
     		{ ## further processing }

     $dbh->do('update table set name = ? where id = 45', {}, 'krtek');

DESCRIPTION
===========

   DBI compliant driver for module XBase. Please refer to DBI(3)
documentation for how to actually use the module. In the connect call,
specify the directory containing the dbf files (and other, memo, etc.) as
the third part of the connect string. It defaults to the current directory.

   Note that with dbf, there is no database server that the driver would
talk to. This DBD::XBase calls methods from XBase.pm module to read and
write the files on the disk directly, so any limitations and features of
XBase.pm apply to DBD::XBase as well. DBD::XBase basically adds SQL, DBI
compliant interface to XBase.pm.

   The DBD::XBase doesn't make use of index files at the moment. If you
really need indexed access, check XBase(3) for notes about support for
variour index types.

SUPPORTED SQL COMMANDS
======================

   The SQL commands currently supported by DBD::XBase's prepare are:

select
------

     select fields_or_expressions from table [ where condition ]
     					[ order by field ]

   Fields_or_expressions is a comma separated list of fields or arithmetic
expressions, or a * for all fields from the table. The where condition
specifies which rows will be returned, you can have arbitrary arithmetic
and boolean expression here, compare fields and constants and use and and
or. Match using `like' is also supported. Examples:

     select * from salaries where name = "Smith"
     select first,last from people where login = "ftp"
     						or uid = 1324
     select id,first_name,last_name from employ
     		where last_name like 'Ki%' order by last_name
     select id + 1, substr(name, 1, 10) from employ where age > 65
     select id, name from employ where id = ?

   You can use bind parameters in the where clause, as the last example
shows. The actual value has to be supplied via bind_param or in the call
to execute or do, see DBI(3) for details. To check for NULL values in the
where expression, use `id is null' and `id is not null', not `id == null'.

   Please note that you can only select from one table, joins are not
supported and are not planned to be supported. If you need them, get a
real RDBMS (or send me a patch).

   In the arithmetic expressions you can use a couple of SQL functions -
currently supported are concat, substr (and substring), trim, ltrim and
rtrim, length. I do not have an exact idea of which and how many functions
I want to support. It's easy to write them in a couple of minutes now the
interface is there (check the XBase::SQL module if you want to send a
patch containing support for more), it's just that I do not really need
them and sometimes it's hard to tell what is usefull and what is SQL92
compatible. Comment welcome.

   The select command may contain and order by clause. Only one column is
supported for sorting at the moment, patches are welcome.

   The group by clause is not supported (and I do not plan them), nor are
the aggregate functions.

delete
------

     delete from table [ where condition ]

   The where condition is the same as for select. Examples:

     delete from jobs		## emties the table
     delete from jobs where companyid = "ISW"
     delete from jobs where id < ?

insert
------

     insert into table [ ( fields ) ] values ( list of values )

   Here fields is a (optional) comma separated list of fields to set, list
of values is a list of constants to assign. If the fields are not
specified, sets the fields in the natural order of the table.  You can use
bind parameters in the list of values. Examples:

     insert into accounts (login, uid) values ("guest", 65534)
     insert into accounts (login, uid) values (?, ?)
     insert into passwd values ("user","*",4523,100,"Nice user",
     				"/home/user","/bin/bash")

update
------

     update table set field = new value [ , set more fields ]
     					[ where condition ]

   Example:

     update passwd set uid = 65534 where login = "guest"
     update zvirata set name = "Jezek", age = 4 where id = 17

   Again, the value can also be specified as bind parameter.

     update zvirata set name = ?, age = ? where id = ?

create table
------------

     create table table name ( columns specification )

   Columns specification is a comma separated list of column names and
types. Example:

     create table rooms ( roomid int, cat char(10), balcony boolean )

   The allowed types are

     char num numeric int integer float boolean blob memo date time
     datetime

   Some of them are synonyms. They are of course converted to appropriate
XBase types.

drop table
----------

     drop table table name

   Example:

     drop table passwd

VERSION
=======

   0.155

AUTHOR
======

   (c) 1997-1999 Jan Pazdziora, adelton@fi.muni.cz,
http://www.fi.muni.cz/~adelton/ at Faculty of Informatics, Masaryk
University in Brno, Czech Republic

SEE ALSO
========

   perl(1); DBI(3), XBase(3); dbish(1)

   Translation into Japanese (older version) at
http://member.nifty.ne.jp/hippo2000/perltips/DBD/XBase.htm by Kawai
Takanori.

mSQL and mysql drivers for the Perl5 Database Interface (DBI)
*************************************************************

NAME
====

   DBD::mSQL / DBD::mysql - mSQL and mysql drivers for the Perl5 Database
Interface (DBI)

SYNOPSIS
========

     use DBI;

     $dbh = DBI->connect("DBI:mSQL:$database:$hostname:$port",
     			undef, undef);

     or

     $dsn = "DBI:mysql:$database:$hostname:$port";
     if ($compression) { $dsn .= ";mysql_compression=1"; }
     $dbh = DBI->connect($dsn, $user, $password);

     @databases = DBD::mysql::dr->func( $hostname, '_ListDBs' );
     @tables = $dbh->func( '_ListTables' );

     $sth = $dbh->prepare("LISTFIELDS $table");
     $sth->execute;
     $sth->finish;

     $sth = $dbh->prepare("SELECT * FROM foo WHERE bla");
     $sth->execute;
     $numRows = $sth->rows;
     $numFields = $sth->{'NUM_OF_FIELDS'};
     $sth->finish;

     $rc = $drh->func( $database, '_CreateDB' );
     $rc = $drh->func( $host, $database, '_CreateDB' );
     $rc = $drh->func( $database, '_DropDB' );
     $rc = $drh->func( $host, $database, '_DropDB' );

DESCRIPTION
===========

   <DBD::mysql> and <DBD::mSQL> are the Perl5 Database Interface drivers
for the mysql, mSQL 1.x and mSQL 2.x databases. The drivers are part of
the *mysql-modules* and *Msql-modules* packages, respectively.

Class Methods
-------------

connect
          use DBI;

          $dbh = DBI->connect("DBI:mSQL:$database", undef, undef);
          $dbh = DBI->connect("DBI:mSQL:$database:$hostname", undef, undef);
          $dbh = DBI->connect("DBI:mSQL:$database:$hostname:$port",
          			undef, undef);

          or

          use DBI;

          $dsn = "DBI:mysql:$database;$options";
          $dsn = "DBI:mysql:$database;$hostname;$options";
          $dsn = "DBI:mysql:$database;$hostname:$port;$options";
          $dsn = "DBI:mysql:$database;$hostname:$port;$options";

          $dbh = DBI->connect($dsn, $user, $password);

     A database must always be specified.

     The hostname, if not specified or specified as ", will default to an
     mysql or mSQL daemon running on the local machine on the default port
     for the UNIX socket.

     Should the mysql or mSQL daemon be running on a non-standard port
     number, you may explicitly state the port number to connect to in the
     hostname argument, by concatenating the hostname and *port number*
     together separated by a colon ( : ) character.

     Other options, possibly separated by semicolons, are:

    mysql_compression
          As of MySQL 3.22.3, a new feature is supported: If you use the
          option

               mysql_compression=1

          then the communication between client and server will be
          compressed.

    mysql_socket
          As of MySQL 3.21.15, it is possible to choose the Unix socket
          that is used for connecting to the server. This is done, for
          example, with

               mysql_socket=/dev/mysql

          Usually there's no need for this option, unless you are using
          another location for the socket than that built into the client.

Private MetaData Methods
------------------------

ListDBs
          @dbs = $dbh->func("$hostname:$port", '_ListDBs');

     Returns a list of all databases managed by the mysql daemon or mSQL
     daemon running on `$hostname', port $port. This method is rarely
     needed for databases running on `localhost': You should use the
     portable method

          @dbs = DBI->data_sources("mysql");

          or

          @dbs = DBI->data_sources("mSQL");

     whenever possible. It is a design problem of this method, that there's
     no way of supplying a host name or port number to data_sources, that's
     the only reason why we still support ListDBs. :-(

ListTables
          @tables = $dbh->func('_ListTables');

     Once connected to the desired database on the desired mysql or mSQL
     mSQL daemon with the `DBI-'connect()> method, we may extract a list
     of the tables that have been created within that database.

     ListTables returns an array containing the names of all the tables
     present within the selected database. If no tables have been created,
     an empty list is returned.

          @tables = $dbh->func( '_ListTables' );
          foreach $table ( @tables ) {
              print "Table: $table\n";
            }

ListFields
     Deprecated, see `' in this node below.

ListSelectedFields
     Deprecated, see `' in this node below.

Database Manipulation
---------------------

CreateDB
DropDB
          $rc = $drh->func( $database, '_CreateDB' );
          $rc = $drh->func( $database, '_DropDB' );

          or

          $rc = $drh->func( $host, $database, '_CreateDB' );
          $rc = $drh->func( $host, $database, '_DropDB' );

     These two methods allow programmers to create and drop databases from
     DBI scripts. Since mSQL disallows the creation and deletion of
     databases over the network, these methods explicitly connect to the
     mSQL daemon running on the machine `localhost' and execute these
     operations there.

     It should be noted that database deletion is *not prompted for* in
     any way.  Nor is it undo-able from DBI.

          Once you issue the dropDB() method, the database will be gone!

     These methods should be used at your own risk.

DATABASE HANDLES
================

   The DBD::mysql driver supports the following attributes of database
handles (read only):

     $infoString = $dbh->{'info'};
     $threadId = $dbh->{'thread_id'};

   These correspond to mysql_info() and mysql_tread_id(), respectively.

STATEMENT HANDLES
=================

   The statement handles of DBD::mysql and DBD::mSQL support a number of
attributes. You access these by using, for example,

     my $numFields = $sth->{'NUM_OF_FIELDS'};

   Note, that most attributes are valid only after a successfull execute.
An undef value will returned in that case. The most important exception is
the `mysql_use_result' attribute: This forces the driver to use
mysql_use_result rather than mysql_store_result. The former is faster and
less memory consuming, but tends to block other processes. (That's why
mysql_store_result is the default.)

   To set the `mysql_use_result' attribute, use either of the following:

     my $sth = $dbh->prepare("QUERY", { "mysql_use_result" => 1});

   or

     my $sth = $dbh->prepare("QUERY");
     $sth->{"mysql_use_result"} = 1;

   Of course it doesn't make sense to set this attribute before calling the
execute method.

   Column dependent attributes, for example NAME, the column names, are
returned as a reference to an array. The array indices are corresponding
to the indices of the arrays returned by fetchrow and similar methods. For
example the following code will print a header of table names together
with all rows:

     my $sth = $dbh->prepare("SELECT * FROM $table");
     if (!$sth) {
         die "Error:" . $dbh->errstr . "\n";
     }
     if (!$sth->execute) {
         die "Error:" . $sth->errstr . "\n";
     }
     my $names = $sth->{'NAME'};
     my $numFields = $sth->{'NUM_OF_FIELDS'};
     for (my $i = 0;  $i < $numFields;  $i++) {
         printf("%s%s", $$names[$i], $i ? "," : "");
     }
     print "\n";
     while (my $ref = $sth->fetchrow_arrayref) {
         for (my $i = 0;  $i < $numFields;  $i++) {
     	  printf("%s%s", $$ref[$i], $i ? "," : "");
         }
         print "\n";
     }

   For portable applications you should restrict yourself to attributes
with capitalized or mixed case names. Lower case attribute names are
private to DBD::mSQL and DBD::mysql. The attribute list includes:

ChopBlanks
     this attribute determines whether a fetchrow will chop preceding and
     trailing blanks off the column values. Chopping blanks does not have
     impact on the max_length attribute.

insertid
     MySQL has the ability to choose unique key values automatically. If
     this happened, the new ID will be stored in this attribute. This
     attribute is not valid for DBD::mSQL.

is_blob
     Reference to an array of boolean values; TRUE indicates, that the
     respective column is a blob. This attribute is valid for MySQL only.

is_key
     Reference to an array of boolean values; TRUE indicates, that the
     respective column is a key. This is valid for MySQL only.

is_num
     Reference to an array of boolean values; TRUE indicates, that the
     respective column contains numeric values.

is_pri_key
     Reference to an array of boolean values; TRUE indicates, that the
     respective column is a primary key. This is only valid for MySQL and
     mSQL 1.0.x: mSQL 2.x uses indices.

is_not_null
     A reference to an array of boolean values; FALSE indicates that this
     column may contain NULL's. You should better use the NULLABLE
     attribute above which is a DBI standard.

length
max_length
     A reference to an array of maximum column sizes. The max_length is
     the maximum physically present in the result table, length gives the
     theoretically possible maximum. max_length is valid for MySQL only.

NAME
     A reference to an array of column names.

NULLABLE
     A reference to an array of boolean values; TRUE indicates that this
     column may contain NULL's.

NUM_OF_FIELDS
     Number of fields returned by a SELECT or *LISTFIELDS* statement.  You
     may use this for checking whether a statement returned a result: A
     zero value indicates a non-SELECT statement like INSERT, DELETE or
     UPDATE.

table
     A reference to an array of table names, useful in a JOIN result.

type
     A reference to an array of column types. It depends on the DBMS,
     which values are returned, even for identical types. mSQL will return
     types like &DBD::mSQL::INT_TYPE, &DBD::msql::TEXT_TYPE etc., MySQL
     uses &DBD::mysql::FIELD_TYPE_SHORT, &DBD::mysql::FIELD_TYPE_STRING
     etc.

COMPATIBILITY ALERT
===================

   As of version 0.70 DBD::mSQL has a new maintainer. Even more, the
sources have been completely rewritten in August 1997, so it seemed
apropriate to bump the version number: Incompatibilities are more than
likely.

Recent changes:
---------------

New connect method
     DBD::mSQL and DBD::mysql now use the new connect method as introduced
     with DBI 0.83 or so. For compatibility reasons the old method still
     works, but the driver issues a warning when he detects use of the old
     version. There's no workaround, you must update your sources.
     (Sorry, but the change was in DBI, not in DBD::mysql and DBD::mSQL.)

_ListFields returning statement handle
     As of Msql-modules 1.1805, the private functions

          $dbh->func($table, "_ListFields");

     and

          $sth->func("_ListSelectedFields");

     no longer return a simple hash, but a statement handle.
     (*_ListSelectedFields* is a stub now which just returns $self.)  This
     should usually not be visible, when your statement handle gets out of
     scope. However, if your database handle ($dbh in the above example)
     disconnects, either because you explicitly disconnect or because he
     gets out of scope, and the statement handle is still active, DBI will
     issue a warning for active cursors being destroyed.

     The simple workaround is to execute `$sth->finish' or to ensure that
     $sth gets out of scope before $dbh. Sorry, but it was obvious
     nonsense to support two different things for accessing the basically
     same thing: A M(y)SQL result.

   The drivers do not conform to the current DBI specification in some
minor points. For example, the private attributes is_num or is_blob have
been written *IS_NUM* and *IS_BLOB*. For historical reasons we continue
supporting the capitalized names, although the DBI specification now
reserves capitalized names for standard names, mixed case for DBI and lower
case for private attributes and methods.

   We currently consider anything not conforming to the DBI as deprecated.
It is quite possible that we remove support of these deprecated names and
methods in the future. In particular these includes:

`$sth->func($table, '_ListSelectedFields')'
     highly deprecated, all attributes are directly accessible via the
     statement handle. For example instead of

          $ref = $sth->func($table, '_ListSelectedFields')
          my @names = $ref->{'NAME'}

     you just do a

          my @names = @{$sth->{'NAME'}};

Capitalized attribute names
     Deprecated, should be replaced by the respective lower case names.

MULTITHREADING
==============

   The multithreading capabilities of the Msql-Mysql-modules depend
completely on the underlying C libraries: The modules are working with
handle data only, no global variables are accessed or (to the best of my
knowledge) thread unsafe functions are called. Thus DBD::mSQL and
DBD::mysql are completely thread safe, if the C libraries thread safe and
you don't share handles among threads.

   The obvious questions is: Are the C libraries thread safe? In the case
of mSQL the answer is definitely "no". The C library has a concept of one
single active connection at a time and that is not what threads like.

   In the case of MySQL the answer is "mostly" and, in theory, you should
be able to get a "yes", if the C library is compiled for being thread safe
(By default it isn't.) by passing the option -with-thread-safe-client to
configure. See the section on *How to make a threadsafe client* in the
manual.

BUGS
====

   The port part of the first argument to the connect call is implemented
in an unsafe way when using mSQL. In fact it is just stting the
environment variable MSQL_TCP_PORT during the connect call. If another
connect call uses another port and the handles are used simultaneously,
they will interfere. I doubt that this will ever change.

   Msql-2.0.4 and 2.0.4.1 contain a bug that makes ORDER BY and hence the
test script `t/40bindparam' fail. To verify, if this is the case for you,
do a

     cd Msql
     perl -w -I../blib/lib -I../blib/arch t/40bindparam.t

   If something is wrong, the script ought to print a number of id's and
names. If the id's aren't in order, it is likely, that your mSQL has a
bug. See the INSTALL file for a patch.

AUTHOR
======

   *DBD::mSQL* has been primarily written by Alligator Descartes
(*descarte@arcana.co.uk*), who has been aided and abetted by Gary Shea,
Andreas Koenig and Tim Bunce amongst others. Apologies if your name isn't
listed, it probably is in the file called 'Acknowledgments'. As of version
0.80 the maintainer is Andreas König.  Version 2.00 is an almost complete
rewrite by Jochen Wiedmann.

COPYRIGHT
=========

   This module is Copyright (c)1997 Jochen Wiedmann, with code portions
Copyright (c)1994-1997 their original authors. This module is released
under the 'Artistic' license which you can find in the perl distribution.

   This document is Copyright (c)1997 Alligator Descartes. All rights
reserved.  Permission to distribute this document, in full or in part, via
email, Usenet, ftp archives or http is granted providing that no charges
are involved, reasonable attempt is made to use the most current version
and all credits and copyright notices are retained ( the AUTHOR and
COPYRIGHT sections ).  Requests for other distribution rights, including
incorporation into commercial products, such as books, magazine articles
or CD-ROMs should be made to Alligator Descartes <*descarte@arcana.co.uk*>.

MAILING LIST SUPPORT
====================

   This module is maintained and supported on a mailing list,

     msql-mysql-modules@tcx.se

   To subscribe to this list, send a mail with the words

     subscribe msql-mysql-modules

   or

     subscribe msql-mysql-modules-digest

   in the first line of the body to mdomo@tcx.se. A mailing list archive is
in preparation.

   Additionally you might try the dbi-user mailing list for questions about
DBI and its modules in general. Subscribe via

     http://www.fugue.com/dbi

   Mailing list archives are at

     http://www.rosat.mpe-garching.mpg.de/mailing-lists/PerlDB-Interest/
     http://outside.organic.com/mail-archives/dbi-users/
     http://www.coe.missouri.edu/~faq/lists/dbi.html

ADDITIONAL DBI INFORMATION
==========================

   Additional information on the DBI project can be found on the World
Wide Web at the following URL:

     http://www.arcana.co.uk/technologia/perl/DBI

   where documentation, pointers to the mailing lists and mailing list
archives and pointers to the most current versions of the modules can be
used.

   Information on the DBI interface itself can be gained by typing:

     perldoc DBI

   right now!

mSQL and mysql drivers for the Perl5 Database Interface (DBI)
*************************************************************

NAME
====

   DBD::mSQL / DBD::mysql - mSQL and mysql drivers for the Perl5 Database
Interface (DBI)

SYNOPSIS
========

     use DBI;

     $dbh = DBI->connect("DBI:mSQL:$database:$hostname:$port",
     			undef, undef);

     or

     $dsn = "DBI:mysql:$database:$hostname:$port";
     if ($compression) { $dsn .= ";mysql_compression=1"; }
     $dbh = DBI->connect($dsn, $user, $password);

     @databases = DBD::mysql::dr->func( $hostname, '_ListDBs' );
     @tables = $dbh->func( '_ListTables' );

     $sth = $dbh->prepare("LISTFIELDS $table");
     $sth->execute;
     $sth->finish;

     $sth = $dbh->prepare("SELECT * FROM foo WHERE bla");
     $sth->execute;
     $numRows = $sth->rows;
     $numFields = $sth->{'NUM_OF_FIELDS'};
     $sth->finish;

     $rc = $drh->func( $database, '_CreateDB' );
     $rc = $drh->func( $host, $database, '_CreateDB' );
     $rc = $drh->func( $database, '_DropDB' );
     $rc = $drh->func( $host, $database, '_DropDB' );

DESCRIPTION
===========

   <DBD::mysql> and <DBD::mSQL> are the Perl5 Database Interface drivers
for the mysql, mSQL 1.x and mSQL 2.x databases. The drivers are part of
the *mysql-modules* and *Msql-modules* packages, respectively.

Class Methods
-------------

connect
          use DBI;

          $dbh = DBI->connect("DBI:mSQL:$database", undef, undef);
          $dbh = DBI->connect("DBI:mSQL:$database:$hostname", undef, undef);
          $dbh = DBI->connect("DBI:mSQL:$database:$hostname:$port",
          			undef, undef);

          or

          use DBI;

          $dsn = "DBI:mysql:$database;$options";
          $dsn = "DBI:mysql:$database;$hostname;$options";
          $dsn = "DBI:mysql:$database;$hostname:$port;$options";
          $dsn = "DBI:mysql:$database;$hostname:$port;$options";

          $dbh = DBI->connect($dsn, $user, $password);

     A database must always be specified.

     The hostname, if not specified or specified as ", will default to an
     mysql or mSQL daemon running on the local machine on the default port
     for the UNIX socket.

     Should the mysql or mSQL daemon be running on a non-standard port
     number, you may explicitly state the port number to connect to in the
     hostname argument, by concatenating the hostname and *port number*
     together separated by a colon ( : ) character.

     Other options, possibly separated by semicolons, are:

    mysql_compression
          As of MySQL 3.22.3, a new feature is supported: If you use the
          option

               mysql_compression=1

          then the communication between client and server will be
          compressed.

    mysql_socket
          As of MySQL 3.21.15, it is possible to choose the Unix socket
          that is used for connecting to the server. This is done, for
          example, with

               mysql_socket=/dev/mysql

          Usually there's no need for this option, unless you are using
          another location for the socket than that built into the client.

Private MetaData Methods
------------------------

ListDBs
          @dbs = $dbh->func("$hostname:$port", '_ListDBs');

     Returns a list of all databases managed by the mysql daemon or mSQL
     daemon running on `$hostname', port $port. This method is rarely
     needed for databases running on `localhost': You should use the
     portable method

          @dbs = DBI->data_sources("mysql");

          or

          @dbs = DBI->data_sources("mSQL");

     whenever possible. It is a design problem of this method, that there's
     no way of supplying a host name or port number to data_sources, that's
     the only reason why we still support ListDBs. :-(

ListTables
          @tables = $dbh->func('_ListTables');

     Once connected to the desired database on the desired mysql or mSQL
     mSQL daemon with the `DBI-'connect()> method, we may extract a list
     of the tables that have been created within that database.

     ListTables returns an array containing the names of all the tables
     present within the selected database. If no tables have been created,
     an empty list is returned.

          @tables = $dbh->func( '_ListTables' );
          foreach $table ( @tables ) {
              print "Table: $table\n";
            }

ListFields
     Deprecated, see `' in this node below.

ListSelectedFields
     Deprecated, see `' in this node below.

Database Manipulation
---------------------

CreateDB
DropDB
          $rc = $drh->func( $database, '_CreateDB' );
          $rc = $drh->func( $database, '_DropDB' );

          or

          $rc = $drh->func( $host, $database, '_CreateDB' );
          $rc = $drh->func( $host, $database, '_DropDB' );

     These two methods allow programmers to create and drop databases from
     DBI scripts. Since mSQL disallows the creation and deletion of
     databases over the network, these methods explicitly connect to the
     mSQL daemon running on the machine `localhost' and execute these
     operations there.

     It should be noted that database deletion is *not prompted for* in
     any way.  Nor is it undo-able from DBI.

          Once you issue the dropDB() method, the database will be gone!

     These methods should be used at your own risk.

DATABASE HANDLES
================

   The DBD::mysql driver supports the following attributes of database
handles (read only):

     $infoString = $dbh->{'info'};
     $threadId = $dbh->{'thread_id'};

   These correspond to mysql_info() and mysql_tread_id(), respectively.

STATEMENT HANDLES
=================

   The statement handles of DBD::mysql and DBD::mSQL support a number of
attributes. You access these by using, for example,

     my $numFields = $sth->{'NUM_OF_FIELDS'};

   Note, that most attributes are valid only after a successfull execute.
An undef value will returned in that case. The most important exception is
the `mysql_use_result' attribute: This forces the driver to use
mysql_use_result rather than mysql_store_result. The former is faster and
less memory consuming, but tends to block other processes. (That's why
mysql_store_result is the default.)

   To set the `mysql_use_result' attribute, use either of the following:

     my $sth = $dbh->prepare("QUERY", { "mysql_use_result" => 1});

   or

     my $sth = $dbh->prepare("QUERY");
     $sth->{"mysql_use_result"} = 1;

   Of course it doesn't make sense to set this attribute before calling the
execute method.

   Column dependent attributes, for example NAME, the column names, are
returned as a reference to an array. The array indices are corresponding
to the indices of the arrays returned by fetchrow and similar methods. For
example the following code will print a header of table names together
with all rows:

     my $sth = $dbh->prepare("SELECT * FROM $table");
     if (!$sth) {
         die "Error:" . $dbh->errstr . "\n";
     }
     if (!$sth->execute) {
         die "Error:" . $sth->errstr . "\n";
     }
     my $names = $sth->{'NAME'};
     my $numFields = $sth->{'NUM_OF_FIELDS'};
     for (my $i = 0;  $i < $numFields;  $i++) {
         printf("%s%s", $$names[$i], $i ? "," : "");
     }
     print "\n";
     while (my $ref = $sth->fetchrow_arrayref) {
         for (my $i = 0;  $i < $numFields;  $i++) {
     	  printf("%s%s", $$ref[$i], $i ? "," : "");
         }
         print "\n";
     }

   For portable applications you should restrict yourself to attributes
with capitalized or mixed case names. Lower case attribute names are
private to DBD::mSQL and DBD::mysql. The attribute list includes:

ChopBlanks
     this attribute determines whether a fetchrow will chop preceding and
     trailing blanks off the column values. Chopping blanks does not have
     impact on the max_length attribute.

insertid
     MySQL has the ability to choose unique key values automatically. If
     this happened, the new ID will be stored in this attribute. This
     attribute is not valid for DBD::mSQL.

is_blob
     Reference to an array of boolean values; TRUE indicates, that the
     respective column is a blob. This attribute is valid for MySQL only.

is_key
     Reference to an array of boolean values; TRUE indicates, that the
     respective column is a key. This is valid for MySQL only.

is_num
     Reference to an array of boolean values; TRUE indicates, that the
     respective column contains numeric values.

is_pri_key
     Reference to an array of boolean values; TRUE indicates, that the
     respective column is a primary key. This is only valid for MySQL and
     mSQL 1.0.x: mSQL 2.x uses indices.

is_not_null
     A reference to an array of boolean values; FALSE indicates that this
     column may contain NULL's. You should better use the NULLABLE
     attribute above which is a DBI standard.

length
max_length
     A reference to an array of maximum column sizes. The max_length is
     the maximum physically present in the result table, length gives the
     theoretically possible maximum. max_length is valid for MySQL only.

NAME
     A reference to an array of column names.

NULLABLE
     A reference to an array of boolean values; TRUE indicates that this
     column may contain NULL's.

NUM_OF_FIELDS
     Number of fields returned by a SELECT or *LISTFIELDS* statement.  You
     may use this for checking whether a statement returned a result: A
     zero value indicates a non-SELECT statement like INSERT, DELETE or
     UPDATE.

table
     A reference to an array of table names, useful in a JOIN result.

type
     A reference to an array of column types. It depends on the DBMS,
     which values are returned, even for identical types. mSQL will return
     types like &DBD::mSQL::INT_TYPE, &DBD::msql::TEXT_TYPE etc., MySQL
     uses &DBD::mysql::FIELD_TYPE_SHORT, &DBD::mysql::FIELD_TYPE_STRING
     etc.

COMPATIBILITY ALERT
===================

   As of version 0.70 DBD::mSQL has a new maintainer. Even more, the
sources have been completely rewritten in August 1997, so it seemed
apropriate to bump the version number: Incompatibilities are more than
likely.

Recent changes:
---------------

New connect method
     DBD::mSQL and DBD::mysql now use the new connect method as introduced
     with DBI 0.83 or so. For compatibility reasons the old method still
     works, but the driver issues a warning when he detects use of the old
     version. There's no workaround, you must update your sources.
     (Sorry, but the change was in DBI, not in DBD::mysql and DBD::mSQL.)

_ListFields returning statement handle
     As of Msql-modules 1.1805, the private functions

          $dbh->func($table, "_ListFields");

     and

          $sth->func("_ListSelectedFields");

     no longer return a simple hash, but a statement handle.
     (*_ListSelectedFields* is a stub now which just returns $self.)  This
     should usually not be visible, when your statement handle gets out of
     scope. However, if your database handle ($dbh in the above example)
     disconnects, either because you explicitly disconnect or because he
     gets out of scope, and the statement handle is still active, DBI will
     issue a warning for active cursors being destroyed.

     The simple workaround is to execute `$sth->finish' or to ensure that
     $sth gets out of scope before $dbh. Sorry, but it was obvious
     nonsense to support two different things for accessing the basically
     same thing: A M(y)SQL result.

   The drivers do not conform to the current DBI specification in some
minor points. For example, the private attributes is_num or is_blob have
been written *IS_NUM* and *IS_BLOB*. For historical reasons we continue
supporting the capitalized names, although the DBI specification now
reserves capitalized names for standard names, mixed case for DBI and lower
case for private attributes and methods.

   We currently consider anything not conforming to the DBI as deprecated.
It is quite possible that we remove support of these deprecated names and
methods in the future. In particular these includes:

`$sth->func($table, '_ListSelectedFields')'
     highly deprecated, all attributes are directly accessible via the
     statement handle. For example instead of

          $ref = $sth->func($table, '_ListSelectedFields')
          my @names = $ref->{'NAME'}

     you just do a

          my @names = @{$sth->{'NAME'}};

Capitalized attribute names
     Deprecated, should be replaced by the respective lower case names.

MULTITHREADING
==============

   The multithreading capabilities of the Msql-Mysql-modules depend
completely on the underlying C libraries: The modules are working with
handle data only, no global variables are accessed or (to the best of my
knowledge) thread unsafe functions are called. Thus DBD::mSQL and
DBD::mysql are completely thread safe, if the C libraries thread safe and
you don't share handles among threads.

   The obvious questions is: Are the C libraries thread safe? In the case
of mSQL the answer is definitely "no". The C library has a concept of one
single active connection at a time and that is not what threads like.

   In the case of MySQL the answer is "mostly" and, in theory, you should
be able to get a "yes", if the C library is compiled for being thread safe
(By default it isn't.) by passing the option -with-thread-safe-client to
configure. See the section on *How to make a threadsafe client* in the
manual.

BUGS
====

   The port part of the first argument to the connect call is implemented
in an unsafe way when using mSQL. In fact it is just stting the
environment variable MSQL_TCP_PORT during the connect call. If another
connect call uses another port and the handles are used simultaneously,
they will interfere. I doubt that this will ever change.

   Msql-2.0.4 and 2.0.4.1 contain a bug that makes ORDER BY and hence the
test script `t/40bindparam' fail. To verify, if this is the case for you,
do a

     cd Msql
     perl -w -I../blib/lib -I../blib/arch t/40bindparam.t

   If something is wrong, the script ought to print a number of id's and
names. If the id's aren't in order, it is likely, that your mSQL has a
bug. See the INSTALL file for a patch.

AUTHOR
======

   *DBD::mSQL* has been primarily written by Alligator Descartes
(*descarte@arcana.co.uk*), who has been aided and abetted by Gary Shea,
Andreas Koenig and Tim Bunce amongst others. Apologies if your name isn't
listed, it probably is in the file called 'Acknowledgments'. As of version
0.80 the maintainer is Andreas König.  Version 2.00 is an almost complete
rewrite by Jochen Wiedmann.

COPYRIGHT
=========

   This module is Copyright (c)1997 Jochen Wiedmann, with code portions
Copyright (c)1994-1997 their original authors. This module is released
under the 'Artistic' license which you can find in the perl distribution.

   This document is Copyright (c)1997 Alligator Descartes. All rights
reserved.  Permission to distribute this document, in full or in part, via
email, Usenet, ftp archives or http is granted providing that no charges
are involved, reasonable attempt is made to use the most current version
and all credits and copyright notices are retained ( the AUTHOR and
COPYRIGHT sections ).  Requests for other distribution rights, including
incorporation into commercial products, such as books, magazine articles
or CD-ROMs should be made to Alligator Descartes <*descarte@arcana.co.uk*>.

MAILING LIST SUPPORT
====================

   This module is maintained and supported on a mailing list,

     msql-mysql-modules@tcx.se

   To subscribe to this list, send a mail with the words

     subscribe msql-mysql-modules

   or

     subscribe msql-mysql-modules-digest

   in the first line of the body to mdomo@tcx.se. A mailing list archive is
in preparation.

   Additionally you might try the dbi-user mailing list for questions about
DBI and its modules in general. Subscribe via

     http://www.fugue.com/dbi

   Mailing list archives are at

     http://www.rosat.mpe-garching.mpg.de/mailing-lists/PerlDB-Interest/
     http://outside.organic.com/mail-archives/dbi-users/
     http://www.coe.missouri.edu/~faq/lists/dbi.html

ADDITIONAL DBI INFORMATION
==========================

   Additional information on the DBI project can be found on the World
Wide Web at the following URL:

     http://www.arcana.co.uk/technologia/perl/DBI

   where documentation, pointers to the mailing lists and mailing list
archives and pointers to the most current versions of the modules can be
used.

   Information on the DBI interface itself can be gained by typing:

     perldoc DBI

   right now!

The Frequently Asked Questions for the Perl5 Database Interface
***************************************************************

NAME
====

   DBI::FAQ - The Frequently Asked Questions for the Perl5 Database
Interface

     perldoc DBI::FAQ

VERSION
=======

   This document is currently at version *0.38*, as of *February 8th,
2000*.

DESCRIPTION
===========

   This document serves to answer the most frequently asked questions on
both the DBI Mailing Lists and personally to members of the DBI
development team.

Basic Information & Information Sources
=======================================

1.1 What is DBI, DBperl, Oraperl and *perl?
-------------------------------------------

   To quote Tim Bunce, the architect and author of DBI:

     ``DBI is a database access Application Programming Interface (API)
       for the Perl Language. The DBI API Specification defines a set
       of functions, variables and conventions that provide a consistent
       database interface independant of the actual database being used.''

   In simple language, the DBI interface allows users to access multiple
database types transparently. So, if you connecting to an Oracle,
Informix, mSQL, Sybase or whatever database, you don't need to know the
underlying mechanics of the 3GL layer. The API defined by DBI will work on
all these database types.

   A similar benefit is gained by the ability to connect to two *different*
databases of different vendor within the one perl script, *ie*, I want to
read data from an Oracle database and insert it back into an Informix
database all within one program. The DBI layer allows you to do this simply
and powerfully.

   Here's a list of DBperl modules, their corresponding DBI counterparts
and support information. *Please note*, the author's listed here generally
*do not* maintain the DBI module for the same database. These email
addresses are unverified and should only be used for queries concerning the
perl4 modules listed below. DBI driver queries should be directed to the
*dbi-users* mailing list.

     Module Name	Database Required   Author          DBI
     -----------	-----------------   ------          ---
     Sybperl     Sybase              Michael Peppler DBD::Sybase
                                     <mpeppler@itf.ch>
     Oraperl     Oracle 6 & 7        Kevin Stock     DBD::Oracle
                                     <dbi-users@isc.org>
     Ingperl     Ingres              Tim Bunce &     DBD::Ingres
                                     Ted Lemon
                                     <dbi-users@isc.org>
     Interperl   Interbase           Buzz Moschetti  DBD::Interbase
                                     <buzz@bear.com>
     Uniperl     Unify 5.0           Rick Wargo      None
                                     <rickers@coe.drexel.edu>
     Pgperl      Postgres            Igor Metz       DBD::Pg
                                     <metz@iam.unibe.ch>
     Btreeperl   NDBM                John Conover    SDBM?
                                     <john@johncon.com>
     Ctreeperl   C-Tree              John Conover    None
                                     <john@johncon.com>
     Cisamperl   Informix C-ISAM     Mathias Koerber None
                                     <mathias@unicorn.swi.com.sg>
     Duaperl     X.500 Directory     Eric Douglas    None
                 User Agent

   However, some DBI modules have DBperl emulation layers, so,
*DBD::Oracle* comes with an Oraperl emulation layer, which allows you to
run legacy oraperl scripts without modification. The emulation layer
translates the oraperl API calls into DBI calls and executes them through
the DBI switch.

   Here's a table of emulation layer information:

     Module		    Emulation Layer     Status
     ------          ---------------     ------
     DBD::Oracle     Oraperl             Complete
     DBD::Informix   Isqlperl            Under development
     DBD::Ingres     Ingperl             Complete?
     DBD::Sybase     Sybperl             Working? ( Needs verification )
     DBD::mSQL       Msqlperl            Experimentally released with
                                         DBD::mSQL-0.61

   The *Msqlperl* emulation is a special case. *Msqlperl* is a perl5 driver
for *mSQL* databases, but does not conform to the DBI Specification. It's
use is being deprecated in favour of *DBD::mSQL*. *Msqlperl* may be
downloaded from CPAN *via*:

     http://www.perl.com/cgi-bin/cpan_mod?module=Msqlperl

1.2. Where can I get it from?
-----------------------------

   The Comprehensive Perl Archive Network resources should be used for
retrieving up-to-date versions of the DBI and drivers. CPAN may be
accessed *via* Tom Christiansen's splendid *CPAN multiplexer* program
located at:

     http://www.perl.com/CPAN/

   For more specific version information and exact URLs of drivers, please
see the DBI drivers list and the DBI module pages which can be found on:

     http://www.symbolstone.org/technology/perl/DBI

   This list is automatically generated on a nightly basis from CPAN and
should be up-to-date.

1.3. Where can I get more information?
--------------------------------------

   There are a few information sources on DBI.

*"Programming the Perl DBI"*
     "Programming the Perl DBI" is the *official* book on the DBI written
     by Alligator Descartes and Tim Bunce and published by O'Reilly &
     Associates.  The book was released on February 9th, 2000.

     The table of contents is:

          Preface
          1. Introduction
              From Mainframes to Workstations
              Perl
              DBI in the Real World
              A Historical Interlude and Standing Stones
          2. Basic Non-DBI Databases
              Storage Managers and Layers
              Query Languages and Data Functions
              Standing Stones and the Sample Database
              Flat-File Databases
              Putting Complex Data into Flat Files
              Concurrent Database Access and Locking
              DBM Files and the Berkeley Database Manager
              The MLDBM Module
              Summary
          3. SQL and Relational Databases
              The Relational Database Methodology
              Datatypes and NULL Values
              Querying Data
              Modifying Data Within Tables
              Creating and Destroying Tables
          4. Programming with the DBI
              DBI Architecture
              Handles
              Data Source Names
              Connection and Disconnection
              Error Handling
              Utility Methods and Functions
          5. Interacting with the Database
              Issuing Simple Queries
              Executing Non-SELECT Statements
              Binding Parameters to Statements
              Binding Output Columns
              do() Versus prepare()
              Atomic and Batch Fetching
          6. Advanced DBI
              Handle Attributes and Metadata
              Handling LONG/LOB Data
              Transactions, Locking, and Isolation
          7. ODBC and the DBI
              ODBC -- Embraced and Extended
              DBI -- Thrashed and Mutated
              The Nuts and Bolts of ODBC
              ODBC from Perl
              The Marriage of DBI and ODBC
              Questions and Choices
              Moving Between Win32::ODBC and the DBI
              And What About ADO?
          8. DBI Shell and Database Proxying
              dbish -- The DBI Shell
              Database Proxying
          A. DBI Specification
          B. Driver and Database Characteristics
          C. ASLaN Sacred Site Charter
          Index

     The book should be available from all good bookshops and can be
     ordered online either <I>via</I> O'Reilly & Associates

          http://www.oreilly.com/catalog/perldbi

     or Amazon

          http://www.amazon.com/exec/obidos/ASIN/1565926994/dbi

*POD documentation*
     PODs are chunks of documentation usually embedded within perl programs
     that document the code "*in place*", providing a useful resource for
     programmers and users of modules. POD for DBI and drivers is
     beginning to become more commonplace, and documentation for these
     modules can be read with the perldoc program included with Perl.

    The DBI Specification
          The POD for the DBI Specification can be read with the:

               perldoc DBI

          command. The Specification also forms Appendix A of "Programming
          the Perl DBI".

    Oraperl
          Users of the Oraperl emulation layer bundled with *DBD::Oracle*,
          may read up on how to program with the Oraperl interface by
          typing:

               perldoc Oraperl

          This will produce an updated copy of the original oraperl man
          page written by Kevin Stock for perl4. The oraperl API is fully
          listed and described there.

    Drivers
          Users of the DBD modules may read about some of the private
          functions and quirks of that driver by typing:

               perldoc <driver>

          For example, the *DBD::mSQL* driver is bundled with
          driver-specific documentation that can be accessed by typing

               perldoc DBD::mSQL

    Frequently Asked Questions
          This document, the *Frequently Asked Questions* is also
          available as POD documentation! You can read this on your own
          system by typing:

               perldoc DBI::FAQ

          This may be more convenient to persons not permanently, or
          conveniently, connected to the Internet. The *DBI::FAQ* module
          should be downloaded and installed for the more up-to-date
          version.

          The version of *DBI::FAQ* shipped with the DBI module may be
          slightly out of date.

    POD in general
          Information on writing POD, and on the philosophy of POD in
          general, can be read by typing:

               perldoc perlpod

          Users with the Tk module installed may be interested to learn
          there is a Tk-based POD reader available called `tkpod', which
          formats POD in a convenient and readable way. This is available
          *via* CPAN as the module called *Tk::POD* and is highly
          recommended.

*Driver and Database Characteristics*
     The driver summaries that were produced for Appendix B of
     "Programming the Perl DBI" are available online at:

          http://www.symbolstone.org/technology/perl/DBI

     in the driver information table. These summaries contain standardised
     information on each driver and database which should aid you in
     selecting a database to use. It will also inform you quickly of any
     issues within drivers or whether a driver is not fully compliant with
     the DBI Specification.

*Rambles, Tidbits and Observations*
          http://www.symbolstone.org/technology/perl/DBI/tidbits

     There are a series of occasional rambles from various people on the
     DBI mailing lists who, in an attempt to clear up a simple point, end
     up drafting fairly comprehensive documents. These are quite often
     varying in quality, but do provide some insights into the workings of
     the interfaces.

Articles
     A list of articles discussing the DBI can be found on the DBI WWW
     page at:

          http://www.symbolstone.org/technology/perl/DBI

     These articles are of varying quality and age, from the original Perl
     Journal article written by Alligator and Tim, to more recent debacles
     published online from about.com.

*README files*
     The README files included with each driver occasionally contains some
     useful information ( no, really! ) that may be pertinent to the user.
     Please read them. It makes our worthless existences more bearable.
     These can all be read from the main DBI WWW page at:

          http://www.symbolstone.org/technology/perl/DBI

Mailing Lists
     There are three mailing lists for DBI run by Ted Lemon. These can all
     be subscribed to and unsubscribed from *via* the World Wide Web at the
     URL of:

          http://www.isc.org/dbi-lists.html

     The lists that users may participate in are:

    *dbi-announce*
          This mailing list is for announcements only. Very low traffic.
          The announcements are usually posted on the main DBI WWW page.

          If you cannot successfully use the form on the above WWW page,
          please subscribe to the list in the following manner:

               Email: 'dbi-announce-request@isc.org' with a message body of
               'subscribe'

    *dbi-dev*
          This mailing list is intended for the use of developers
          discussing ideas and concepts for the DBI interface, API and
          driver mechanics.  Only any use for developers, or interested
          parties. Low traffic.

          If you cannot successfully use the form on the above WWW page,
          please subscribe to the list in the following manner:

               Email: 'dbi-dev-request@isc.org' with a message body of
               'subscribe'

    *dbi-users*
          This mailing list is a general discussion list used for bug
          reporting, problem discussion and general enquiries. Medium
          traffic.

          If you cannot successfully use the form on the above WWW page,
          please subscribe to the list in the following manner:

               Email: 'dbi-users-request@isc.org' with a message body of
               'subscribe'

*Mailing List Archives*

    *US Mailing List Archives*
               http://outside.organic.com/mail-archives/dbi-users/

          Searchable hypermail archives of the three mailing lists, and
          some of the much older traffic have been set up for users to
          browse.

    *European Mailing List Archives*
               http://www.rosat.mpe-garching.mpg.de/mailing-lists/PerlDB-Interest

          As per the US archive above.

Compilation Problems
====================

2.1. Compilation problems or "It fails the test!"
-------------------------------------------------

   First off, consult the README for that driver in case there is useful
information about the problem. It may be a known problem for your given
architecture and operating system or database. You can check the README
files for each driver in advance online at:

     http://www.symbolstone.org/technology/perl/DBI

   If it's a known problem, you'll probably have to wait till it gets
fixed. If you're *really* needing it fixed, try the following:

*Attempt to fix it yourself*
     This technique is generally not recommended to the faint-hearted.  If
     you do think you have managed to fix it, then, send a patch file (
     context diff ) to the author with an explanation of:

        * What the problem was, and test cases, if possible.

        * What you needed to do to fix it. Please make sure you mention
          everything.

        * Platform information, database version, perl version, module
          version and DBI version.

*Email the author* Do *NOT* whinge!
     Please email the address listed in the WWW pages for whichever driver
     you are having problems with. Do not directly email the author at a
     known address unless it corresponds with the one listed.

     We tend to have real jobs to do, and we do read the mailing lists for
     problems. Besides, we may not have access to <*insert your favourite
     brain-damaged platform here*> and couldn't be of any assistance
     anyway! Apologies for sounding harsh, but that's the way of it!

     However, you might catch one of these creative genii at 3am when we're
     doing this sort of stuff anyway, and get a patch within 5 minutes. The
     atmosphere in the DBI circle is that we do appreciate the users'
     problems, since we work in similar environments.

     If you are planning to email the author, please furnish as much
     information as possible, *ie*:

        * ALL the information asked for in the README file in the
          problematic module. And we mean ALL of it. We don't put lines
          like that in documentation for the good of our health, or to
          meet obscure README file standards of length.

        * If you have a core dump, try the *Devel::CoreStack* module for
          generating a stack trace from the core dump. Send us that too.
          *Devel::CoreStack* can be found on CPAN at:

               http://www.perl.com/cgi-bin/cpan_mod?module=Devel::CoreStack

        * Module versions, perl version, test cases, operating system
          versions and *any other pertinent information*.

     Remember, the more information you send us, the quicker we can track
     problems down. If you send us no useful information, expect nothing
     back.

     Finally, please be aware that some authors, including Tim Bunce,
     specifically request that you do not mail them directly. Please
     respect their wishes and use the email addresses listed in the
     appropriate module README file.

*Email the dbi-users Mailing List*
     It's usually a fairly intelligent idea to cc the mailing list anyway
     with problems. The authors all read the lists, so you lose nothing by
     mailing there.

Platform and Driver Issues
==========================

3.1 What's the difference between ODBC and DBI?
-----------------------------------------------

   In terms of architecture - not much: Both define programming
interfaces. Both allow multiple drivers to be loaded to do the actual work.

   In terms of ease of use - much: The DBI is a 'high level' interface
that, like Perl itself, strives to make the simple things easy while still
making the hard things possible. The ODBC is a 'low level' interface. All
nuts-bolts-knobs-and-dials.

   Now there's an ODBC driver for the DBI (DBD::ODBC) the "What's the
difference" question is more usefully rephrased as:

   Chapter 7 of "Programming the Perl DBI" covers this topic in far more
detail and should be consulted.

3.2 What's the difference between Win32::ODBC and DBD::ODBC?
------------------------------------------------------------

   The DBI, and thus DBD::ODBC, has a different philosophy from the
Win32::ODBC module:

   The Win32::ODBC module is a 'thin' layer over the low-level ODBC API.
The DBI defines a simpler 'higher level' interface.

   The Win32::ODBC module gives you access to more of the ODBC API.  The
DBI and DBD::ODBC give you access to only the essentials.  (But, unlike
Win32::ODBC, the DBI and DBD::ODBC do support parameter binding and
multiple prepared statements which reduces the load on the database server
and can dramatically increase performance.)

   The Win32::ODBC module only works on Win32 systems.  The DBI and
DBD::ODBC are very portable and work on Win32 and Unix.

   The DBI and DBD::ODBC modules are supplied as a standard part of the
Perl 5.004 binary distribution for Win32 (they don't work with the older,
non-standard, ActiveState port).

   Scripts written with the DBI and DBD::ODBC are faster than Win32::ODBC
on Win32 and are trivially portable to other supported database types.

   The DBI offers optional automatic printing or die()ing on errors which
makes applications simpler and more robust.

   The current DBD::ODBC driver version 0.16 is new and not yet fully
stable.  A new release is due soon [relative to the date of the next TPJ
issue :-] and will be much improved and offer more ODBC functionality.

   To summarise: The Win32::ODBC module is your best choice if you need
access to more of the ODBC API than the DBI gives you. Otherwise, the DBI
and DBD::ODBC combination may be your best bet.

   Chapter 7 of "Programming the Perl DBI" covers this topic in far more
detail and should be consulted.

3.3 Is DBI supported under Windows 95 / NT platforms?
-----------------------------------------------------

   Finally, yes! Jeff Urlwin has been working diligently on building DBI
and *DBD::ODBC* under these platforms, and, with the advent of a stabler
perl and a port of MakeMaker, the project has come on by great leaps and
bounds.

   The DBI and *DBD::Oracle* Win32 ports are now a standard part of DBI,
so, downloading DBI of version higher than *0.81* should work fine as
should using the most recent *DBD::Oracle* version.

3.4 Can I access Microsoft Access or SQL-Server databases with DBI?
-------------------------------------------------------------------

   Yes, use the *DBD::ODBC* driver.

3.5 Is the a DBD for <*insert favourite database here*>?
--------------------------------------------------------

   Is is listed on the DBI drivers page?

     http://www.symbolstone.org/technology/perl/DBI

   If not, no. A complete absence of a given database driver from that
page means that no-one has announced any intention to work on it, not that
such a driver is impossible to write.

   A corollary of the above statement implies that if you see an
announcement for a driver not on the above page, there's a good chance
it's not actually a DBI driver, and may not conform to the specifications.
Therefore, questions concerning problems with that code should not really
be addressed to the DBI Mailing Lists.

3.6 What's DBM? And why should I use DBI instead?
-------------------------------------------------

   Extracted from "*DBI - The Database Interface for Perl 5*":

     ``UNIX was originally blessed with simple file-based ``databases'', namely
     the dbm system. dbm lets you store data in files, and retrieve
     that data quickly. However, it also has serious drawbacks.

     File Locking

     The dbm systems did not allow particularly robust file locking
     capabilities, nor any capability for correcting problems arising through
     simultaneous writes [ to the database ].

     Arbitrary Data Structures

     The dbm systems only allows a single fixed data structure:
     key-value pairs. That value could be a complex object, such as a
     [ C ] struct, but the key had to be unique. This was a large
     limitation on the usefulness of dbm systems.

     However, dbm systems still provide a useful function for users with
     simple datasets and limited resources, since they are fast, robust and
     extremely well-tested. Perl modules to access dbm systems have now
     been integrated into the core Perl distribution via the
     AnyDBM_File module.''

   To sum up, DBM is a perfectly satisfactory solution for essentially
read-only databases, or small and simple datasets. However, for more
scaleable dataset handling, not to mention robust transactional locking,
users are recommended to use a more powerful database engine *via* DBI.

   Chapter 2 of "Programming the Perl DBI" discusses DBM files in detail.

3.7 What database do you recommend me using?
--------------------------------------------

   This is a particularly thorny area in which an objective answer is
difficult to come by, since each dataset, proposed usage and system
configuration differs from person to person.

   From the current author's point of view, if the dataset is relatively
small, being tables of less than 1 million rows, and less than 1000 tables
in a given database, then *mSQL* is a perfectly acceptable solution to
your problem. This database is extremely cheap, is wonderfully robust and
has excellent support. More information is available on the Hughes
Technology WWW site at:

     http://www.hughes.com.au

   You may also wish to look at MySQL which is a more powerful database
engine that has a similar feel to mSQL.

     http://www.tcx.se

   If the dataset is larger than 1 million row tables or 1000 tables, or
if you have either more money, or larger machines, I would recommend
*Oracle RDBMS*.  Oracle's WWW site is an excellent source of more
information.

     http://www.oracle.com

   *Informix* is another high-end RDBMS that is worth considering. There
are several differences between Oracle and Informix which are too complex
for this document to detail. Information on Informix can be found on their
WWW site at:

     http://www.informix.com

   In the case of WWW fronted applications, *mSQL* may be a better option
due to slow connection times between a CGI script and the Oracle RDBMS and
also the amount of resource each Oracle connection will consume. *mSQL* is
lighter resource-wise and faster.

   These views are not necessarily representative of anyone else's
opinions, and do not reflect any corporate sponsorship or views. They are
provided *as-is*.

3.8 Is <*insert feature here*> supported in DBI?
------------------------------------------------

   Given that we're making the assumption that the feature you have
requested is a non-standard database-specific feature, then the answer
will be no.

   DBI reflects a generic API that will work for most databases, and has
no database-specific functionality.

   However, driver authors may, if they so desire, include hooks to
database-specific functionality through the `func()' method defined in the
DBI API.  Script developers should note that use of functionality provided
*via* the `func()' methods is very unlikely to be portable across
databases.

Programming Questions
=====================

4.1 Is DBI any use for CGI programming?
---------------------------------------

   In a word, yes! DBI is hugely useful for CGI programming! In fact, I
would tentatively say that CGI programming is one of two top uses for DBI.

   DBI confers the ability to CGI programmers to power WWW-fronted
databases to their users, which provides users with vast quantities of
ordered data to play with. DBI also provides the possibility that, if a
site is receiving far too much traffic than their database server can cope
with, they can upgrade the database server behind the scenes with no
alterations to the CGI scripts.

4.2 How do I get faster connection times with DBD::Oracle and CGI?
------------------------------------------------------------------

     Contributed by John D. Groenveld

   The Apache `httpd' maintains a pool of `httpd' children to service
client requests.

   Using the Apache mod_perl module by *Doug MacEachern*, the perl
interpreter is embedded with the `httpd' children. The CGI, DBI, and your
other favorite modules can be loaded at the startup of each child. These
modules will not be reloaded unless changed on disk.

   For more information on Apache, see the Apache Project's WWW site:

     http://www.apache.org

   The mod_perl module can be downloaded from CPAN *via*:

     http://www.perl.com/cgi-bin/cpan_mod?module=Apache

4.3 How do I get persistent connections with DBI and CGI?
---------------------------------------------------------

     Contributed by John D. Groenveld

   Using Edmund Mergl's *Apache::DBI* module, database logins are stored
in a hash with each of these `httpd' child. If your application is based
on a single database user, this connection can be started with each child.
Currently, database connections cannot be shared between `httpd' children.

   *Apache::DBI* can be downloaded from CPAN *via*:

     http://www.perl.com/cgi-bin/cpan_mod?module=Apache::DBI

4.4 "When I run a perl script from the command line, it works, but, when I run it under the `httpd', it fails!" Why?
--------------------------------------------------------------------------------------------------------------------

   Basically, a good chance this is occurring is due to the fact that the
user that you ran it from the command line as has a correctly configured
set of environment variables, in the case of *DBD::Oracle*, variables like
`ORACLE_HOME', `ORACLE_SID' or `TWO_TASK'.

   The `httpd' process usually runs under the user id of `nobody', which
implies there is no configured environment. Any scripts attempting to
execute in this situation will correctly fail.

   One way to solve this problem is to set the environment for your
database in a `BEGIN { }' block at the top of your script. Another
technique is to configure your WWW server to pass-through certain
environment variables to your CGI scripts.

   Similarly, you should check your `httpd' error logfile for any clues,
as well as the "Idiot's Guide To Solving Perl / CGI Problems" and "Perl
CGI Programming FAQ" for further information. It is unlikely the problem
is DBI-related.

   The "Idiot's Guide To Solving Perl / CGI Problems" can be located at:

     http://www.perl.com/perl/faq/index.html

   as can the "Perl CGI Programming FAQ". Read *BOTH* these documents
carefully!

4.5 How do I get the number of rows returned from a SELECT statement?
---------------------------------------------------------------------

   Count them. Read the DBI docs for the rows() method.

Miscellaneous Questions
=======================

5.1 Can I do multi-threading with DBI?
--------------------------------------

   Perl version 5.005 and later can be built to support multi-threading.
The DBI, as of version 1.02, does not yet support multi-threading so it
would be unsafe to let more than one thread enter the DBI at the same time.

   It is expected that some future version of the DBI will at least be
thread-safe (but not thread-hot) by automatically blocking threads
intering the DBI while it's already in use.

   For some OCI example code for Oracle that has multi-threaded SELECT
statements, see:

     http://www.symbolstone.org/technology/oracle/oci/orathreads.tar.gz

5.2 How do I handle BLOB data with DBI?
---------------------------------------

   Handling BLOB data with the DBI is very straight-forward. BLOB columns
are specified in a SELECT statement as per normal columns. However, you
also need to specify a maximum BLOB size that the <I>database handle</I>
can fetch using the `LongReadLen' attribute.

   For example:

     ### $dbh is a connected database handle
     $sth = $dbh->prepare( "SELECT blob_column FROM blobby_table" );
     $sth->execute;

   would fail.

     ### $dbh is a connected database handle
     ### Set the maximum BLOB size...
     $dbh->{LongReadLen} = 16384;        ### 16Kb...Not much of a BLOB!

     $sth = $dbh->prepare( "..." );

   would succeed <I>provided no column values were larger than the
specified value</I>.

   If the BLOB data is longer than the value of `LongReadLen', then an
error will occur. However, the DBI provides an additional piece of
functionality that will automatically truncate the fetched BLOB to the
size of `LongReadLen' if it is longer. This does not cause an error to
occur, but may make your fetched BLOB data useless.

   This behaviour is regulated by the `LongTruncOk' attribute which is
defaultly set to a false value ( thus making overlong BLOB fetches fail ).

     ### Set BLOB handling such that it's 16Kb and can be truncated
     $dbh->{LongReadLen} = 16384;
     $dbh->{LongTruncOk} = 1;

   Truncation of BLOB data may not be a big deal in cases where the BLOB
contains run-length encoded data, but data containing checksums at the end,
for example, a ZIP file, would be rendered useless.

   =head2 5.3 How can I invoke stored procedures with DBI?

   The DBI does not define a database-independent way of calling stored
procedures.

   However, most database that support them also provide a way to call
them from SQL statements - and the DBI certainly supports that.

   So, assuming that you have created a stored procedure within the target
database, *eg*, an Oracle database, you can use $dbh->`do()' to
immediately execute the procedure. For example,

     $dbh->do( "BEGIN someProcedure; END;" );   # Oracle-specific

   You should also be able to prepare and execute, which is the
recommended way if you'll be calling the procedure often.

5.4 How can I get return values from stored procedures with DBI?
----------------------------------------------------------------

     Contributed by Jeff Urlwin

     $sth = $dbh->prepare( "BEGIN foo(:1, :2, :3); END;" );
     $sth->bind_param(1, $a);
     $sth->bind_param_inout(2, \$path, 2000);
     $sth->bind_param_inout(3, \$success, 2000);
     $sth->execute;

   Remember to perform error checking, though! ( Or use the `RaiseError'
attribute ).

5.5 How can I create or drop a database with DBI?
-------------------------------------------------

   Database creation and deletion are concepts that are entirely too
abstract to be adequately supported by DBI. For example, Oracle does not
support the concept of dropping a database at all! Also, in Oracle, the
database server essentially *is* the database, whereas in mSQL, the server
process runs happily without any databases created in it. The problem is
too disparate to attack in a worthwhile way.

   Some drivers, therefore, support database creation and deletion through
the private `func()' methods. You should check the documentation for the
drivers you are using to see if they support this mechanism.

5.6 How can I commit or rollback a statement with DBI?
------------------------------------------------------

   See the commit() and rollback() methods in the DBI Specification.

   Chapter 6 of "Programming the Perl DBI" discusses transaction handling
within the context of DBI in more detail.

5.7 How are NULL values handled by DBI?
---------------------------------------

   NULL values in DBI are specified to be treated as the value undef.
NULLs can be inserted into databases as NULL, for example:

     $rv = $dbh->do( "INSERT INTO table VALUES( NULL )" );

   but when queried back, the NULLs should be tested against undef.  This
is standard across all drivers.

5.8 What are these `func()' methods all about?
----------------------------------------------

   The `func()' method is defined within DBI as being an entry point for
database-specific functionality, *eg*, the ability to create or drop
databases. Invoking these driver-specific methods is simple, for example,
to invoke a `createDatabase' method that has one argument, we would write:

     $rv =$dbh->func( 'argument', 'createDatabase' );

   Software developers should note that the `func()' methods are
non-portable between databases.

5.9 Is DBI Year 2000 Compliant?
-------------------------------

   DBI has no knowledge of understanding of what dates are. Therefore, DBI
itself does not have a Year 2000 problem. Individual drivers may use date
handling code internally and therefore be potentially susceptible to the
Year 2000 problem, but this is unlikely.

   You may also wish to read the "Does Perl have a Year 2000 problem?"
section of the Perl FAQ at:

     http://www.perl.com/CPAN/doc/FAQs/FAQ/PerlFAQ.html

Support and Training
====================

   The Perl5 Database Interface is *FREE* software. IT COMES WITHOUT
WARRANTY OF ANY KIND. See the DBI README for more details.

   However, some organizations are providing either technical support or
training programs on DBI. The present author has no knowledge as to the
quality of these services. The links are included for reference purposes
only and should not be regarded as recommendations in any way.  *Caveat
emptor*.

Commercial Support
------------------

The Perl Clinic
     The Perl Clinic provides commercial support for Perl and Perl related
     problems, including the DBI and its drivers.  Support is provided by
     the company with whom Tim Bunce, author of DBI and *DBD::Oracle*,
     works and ActiveState. For more information on their services, please
     see:

          http://www.perlclinic.com

Training
--------

Westlake Solutions
     A hands-on class for experienced Perl CGI developers that teaches how
     to write database-connected CGI scripts using Perl and DBI.pm.  This
     course, along with four other courses on CGI scripting with Perl, is
     taught in Washington, DC; Arlington, Virginia; and on-site worldwide
     upon request.

     See:

          http://www.westlake.com/training

     for more details.

Other References
================

   In this section, we present some miscellaneous WWW links that may be of
some interest to DBI users. These are not verified and may result in
unknown sites or missing documents.

     http://www-ccs.cs.umass.edu/db.html
     http://www.odmg.org/odmg93/updates_dbarry.html
     http://www.jcc.com/sql_stnd.html

AUTHOR
======

   Alligator Descartes
<*http://www.symbolstone.org/descarte/contact.html*>.  Portions are
Copyright their original stated authors.

COPYRIGHT
=========

   This document is Copyright (c)1994-2000 Alligator Descartes, with
portions Copyright (c)1994-2000 their original authors. This module is
released under the 'Artistic' license which you can find in the perl
distribution.

   This document is Copyright (c)1997-2000 Alligator Descartes. All rights
reserved.  Permission to distribute this document, in full or in part, via
email, Usenet, ftp archives or http is granted providing that no charges
are involved, reasonable attempt is made to use the most current version
and all credits and copyright notices are retained ( the AUTHOR and
COPYRIGHT sections ).  Requests for other distribution rights, including
incorporation into commercial products, such as books, magazine articles
or CD-ROMs should be made to Alligator Descartes
<*http://www.symbolstone.org/descarte/contact.html*>.

DBI SQL abstraction
*******************

NAME
====

   DBIx::Abstract - DBI SQL abstraction

SYNOPSIS
========

     use DBIx::Abstract;
     $db = DBIx::Abstract->connect({
       driver=>'mydriver',
       host=>'myhost.org',
       dbname=>'mydb',
       user=>'myuser',
       password=>'mypassword',
       });

     if ($db->select('*','table')->rows) {
       while ($data = $db->fetchrow_hashref) {
         ...
       }
     }

     ($name) = $db->select('name','table',{id=>$id})->fetchrow_array;

     ***

     $db = DBIx::Abstract->connect( { driver=>'csv', f_name=>'foo/' } );

     ***

     $db = DBIx::Abstract->connect({
       dsn=>'dbi:someotherdb:so_db_name=mydb',
       user=>'myuser',
       password=>'mypassword',
       });

DESCRIPTION
===========

   This module provides methods for doing manipulating database tables This
module provides methods retrieving and storing data in SQL databases.  It
provides methods for all of the more important SQL commands (like SELECT,
INSERT, REPLACE, UPDATE, DELETE).

   It endeavors to produce an interface that will be intuitive to those
already familiar with SQL.

   Notable features include:

     * data_source generation for some DBD drivers.
     * Can check to make sure the connection is not stale and reconnect
       if it is.
     * Controls statement handles for you.
     * Can delay writes.
     * Generates complex where clauses from hashes and arrays.
     * Shortcuts (convenience functions) for some common cases. (Like
       select_all_to_hashref.)

METHODS
=======

   Unless otherwise mentioned all methods return the database handle.

connect
-------

   `connect($connect_config | $dbihandle [,$options])' CONSTRUCTOR

   Open a connection to a database as configured by $connect_config.
$connect_config can either be a scalar, in which case it is a DBI data
source, or a reference to a hash with the following keys:

     dsn      -- The data source to connect to your database

     OR, DBIx::Abstract will try to generate it if you give these instead:

     driver   -- DBD driver to use (defaults to mysql)
     host     -- Host of database server
     port     -- Port of database server
     dbname   -- Name of database

     Username and password are always valid.

     user     -- Username to connect as
     password -- Password for user

   Alternatively you can pass in a DBI handle directly.  This will disable
the methods "reconnect" and "ensure_connection" as they rely on connection
info not available on a DBI handle.

   Options is a hash reference.  Each key/value pair is passed on to the
opt method.

clone
-----

   This clones the object.  For those times when you need a second
connection to the same DB.  If you need a second connection to a different
DB, create a new object with 'connect'.

   This operation is logged at level 5 with the message "Cloned."

connected
---------

   Check to see if this object is connected to a database.  It checks to
see if it has a database handle and if that handle's "Active" attribute is
true.

reconnect
---------

   If the object is not connected to a database it will reconnect using the
same parameters connect was originally called with.

ensure_connection
-----------------

   Makes sure that the object is connect to a database.  Makes sure that
the connect is active (by sending a "SELECT 1").  If there is no
connection, or the connection is not active then it tries to reconnect.
If it fails to reconnect then it dies.

opt
---

   ($key[,$value])

   ({key=>$key[,value=>$value])

   Set option $key to $value.  Available keys are:

     loglevel (default 0)
         0 -- Fatal errors only
         1 -- Modifications
         2 -- And selects
         3 -- And user created queries
         4 -- And results of queries
         5 -- And other misc commands
         6 -- Internals of commands

     logfile (default undef)
       Log file

     delaymods (default false)
       Delay making modifications to the database until
       run_delayed is run.

     AutoCommit
       This works just like the DBI 'AutoCommit', except that it issues a
       warning (instead of dieing) if you give it bad data.

     useCached
       If this is true then prepare_cached is used instead of prepare.
       Checkout the DBI documentation on this feature before using this
       feature.

     saveSQL
       If this is true then with each query DBIx::Abstract will stuff the generated
       SQL into the 'lastsql' key in the self payload.

   This operation is logged at level 5 with the message "Option Change"
and the the key, the old value and new new value.

query
-----

   ($sql,@bind_params)

   ({sql=>$sql,bind_params=>[@bind_params]})

   This sends $sql to the database object's query method.  This should be
used for applications where the existing methods are not able to generate
flexible enough SQL for you.

   If you find yourself using this very often with things other then table
manipulation (eg 'create table','alter table','drop table') then please let
me know so I can extend DBIx::Abstract to include the functionality you
are using.

   This operation is logged at level 3

run_delayed
-----------

   Execute delayed update/insert/delete queries.

   This operation is logged at level 5 with the message "Run delayed".

delete
------

   ($table[,$where])

   ({table=>$table[,where=>$where]})

   Deletes records from $table.  See also the documentation on
`"DBIx::Abstract Where Clauses"' in this node.

insert
------

   ($table,$fields)

   ({table=>$table,fields=>$fields})

   $table is the name of the table to insert into.

   $fields is either a reference to a hash of field name/value or a scalar
containing the SQL to insert after the "SET" portion of the statement.

   These all produce functionally equivalent SQL.

     $db->insert('foo',{bar=>'baz'});
     $db->insert('foo',q|bar='baz'|);
     $db->insert({table=>'foo',fields=>{bar=>'baz'}});
     $db->insert({table=>'foo',fields=>q|bar='baz'|});

   We also support literals by making the value in the hash an arrayref:

     $db->insert('foo',{name=>'bar',date=>['substring(now(),1,10)']});

   Would generate something like this:

     INSERT INTO foo (name,date) VALUES (?,substring(now(),1,10))

   With "bar" bound to the first parameter.

replace
-------

   ($table,$fields)

   ({table=>$table,fields=>$fields})

   $table is the name of the table to replace into.

   $fields is either a reference to a hash of field name/value or a scalar
containing the SQL to insert after the "SET" portion of the statement.

   Replace works just like insert, except that if a record with the same
primary key already exists then the existing record is replaced, instead of
producing an error.

update
------

   ($table,$fields[,$where])

   ({table=>$table,fields=>$fields[,where=>$where]})

   $table is the table to update.

   $fields is a reference to a hash keyed on field name/new value.

   See also the documentation on `"DBIx::Abstract Where Clauses"' in this
node.

select
------

   select

   ($fields,[$table,[$where[,$order]]])

({fields=>$fields,table=>$table[,where=>$where][,order=>$order][,join=>$join][,group=>$group]})

   $fields can be either an array reference or a scalar.  If it is an array
reference then it should be a list of fields to include.  If it is a scalar
then it should be a literal to be inserted into the generated SQL after
"SELECT".

   $table can be either an array reference or a scalar. If it is an array
reference then it should be a list of tables to use.  If it is a scalar
then it should be a literal to be inserted into the generated SQL after
"FROM".

   See also the documentation on `"DBIx::Abstract Where Clauses"' in this
node.

   $order is the output order.  If it is a scalar then it is inserted
literally after "ORDER BY".  If it is an arrayref then it is join'd with a
comma and inserted.

   $join is there to make joining tables more convenient.  It will takes
one or more (as an arrayref) sets of statements to use when joining.  For
instance:

     $dbh->select({
       fields=>'*',
       table=>'foo,bar',
       join=>'foo.id=bar.foo_id',
       where=>{'foo.dollars',['>',30]}
       });

   Would produce:

     SELECT * FROM foo,bar WHERE (foo.dollars > ?) and (foo.id=foo_id)

   And put 30 into the bind_params list.

   $group is/are the field(s) to group by.  It may be scalar or an
arrayref.  If it is a scalar then it should be a literal to be inserted
after "GROUP BY".  If it is an arrayref then it should be a list of fields
to group on.

select_one_to_hashref
---------------------

   ($fields,$table[,$where])

   ({fields=>$fields,table=>$table[,where=>$where]})

   This returns a hashref to the first record returned by the select.
Typically this should be used for cases when your where clause limits you
to one record anyway.

   $fields is can be either a array reference or a scalar.  If it is an
array reference then it should be a list of fields to include.  If it is a
scalar then it should be a literal to be inserted into the generated SQL.

   $table is the table to select from.

   See also the documentation on `"DBIx::Abstract Where Clauses"' in this
node.

select_one_to_arrayref
----------------------

   ($fields,$table[,$where])

   ({fields=>$fields,table=>$table[,where=>$where]})

   This returns a arrayref to the first record returned by the select.
Typically this should be used for cases when your where clause limits you
to one record anyway.

   $fields is can be either a array reference or a scalar.  If it is an
array reference then it should be a list of fields to include.  If it is a
scalar then it should be a literal to be inserted into the generated SQL.

   $table is the table to select from.

   See also the documentation on `"DBIx::Abstract Where Clauses"' in this
node.

select_one_to_array
-------------------

   ($fields,$table[,$where])

   ({fields=>$fields,table=>$table[,where=>$where]})

   This returns a array to the first record returned by the select.
Typically this should be used for cases when your where clause limits you
to one record anyway.

   $fields is can be either a array reference or a scalar.  If it is an
array reference then it should be a list of fields to include.  If it is a
scalar then it should be a literal to be inserted into the generated SQL.

   $table is the table to select from.

   See also the documentation on `"DBIx::Abstract Where Clauses"' in this
node.

select_all_to_hashref
---------------------

   ($fields,$table[,$where])

   ({fields=>$fields,table=>$table[,where=>$where]})

   This returns a hashref to all of the results of the select.  It is
keyed on the first field.  If there are only two fields then the value is
just the second field.  If there are more then two fields then the value
is set to an arrayref that contains all of the fields.

   $fields is can be either a array reference or a scalar.  If it is an
array reference then it should be a list of fields to include.  If it is a
scalar then it should be a literal to be inserted into the generated SQL.

   $table is the table to select from.

   See also the documentation on `"DBIx::Abstract Where Clauses"' in this
node.

fetchrow_hashref
----------------

   This is just a call to the DBI method.

fetchrow_hash
-------------

   This calls fetchrow_hashref and dereferences it for you.

fetchrow_array
--------------

   This method calls the database handle's method of the same name.

fetchall_arrayref
-----------------

   This method calls the database handle's method of the same name.

rows
----

   This method calls the database handle's method of the same name.

quote
-----

   This method is passed to the database handle via AUTOLOAD.

disconnect
----------

   This method is passed to the database handle via AUTOLOAD.

commit
------

   This method is passed to the database handle via AUTOLOAD.

rollback
--------

   This method is passed to the database handle via AUTOLOAD.

trace
-----

   This method is passed to the database handle via AUTOLOAD.

finish
------

   This method is passed to the statement handle via AUTOLOAD.

bind_col
--------

   This method is passed to the statement handle via AUTOLOAD.

bind_columns
------------

   This method is passed to the statement handle via AUTOLOAD.

Other things that need explanation
==================================

DBIx::Abstract Where Clauses
----------------------------

   Where clauses in DBIx::Abstract can either be very simple, or highly
complex.  They are designed to be easy to use if you are just typing in a
hard coded statement or have to build a complex query from data.

   Wheres are either a scalar, hash-ref or array-ref:

   If it is a scalar, then it is used as the literal where.

   If it is a hash-ref then the key is the field to check, the value is
either a literal value to compare equality to, or an array-ref to an array
of operator and value.

     {
      first=>'joe',
      age=>['>',26],
      last=>['like',q|b'%|]
     }

   Would produce:

     WHERE first = ? AND last like ? AND age > ?

     With joe, b'% and 26 passed as bind values.

   If it is an array-ref then it is an array of hash-refs and connectors:

     [
       {
         first=>'joe',
         age=>['>',26]
       },
       'OR',
       {
         last=>['like',q|b'%|]
       }
     ]

   Would produce:

     WHERE (first = ? AND age > ?) OR (last like ?)

     With joe, 26 and b'% passed as bind values.

     [
       {
         first=>'joe',
         last=>['like','%foo%'],
       },
       'AND',
       [
         {age=>['>',26]},
         'OR',
         {age=>['<',30]}
       ]
     ]

   Would produce:

   WHERE (first = ? AND last like ?) AND ((age > ?) OR (age < ?))

   With joe, %foo%, 26 and 30 passed as bind values.

SUPPORTED DBD DRIVERS
=====================

   These drivers have been reported to work:

   * mysql (development environment)

   * Pg (with a pre-release version of DBIx::Abstract)

   * XBase

     Any driver that uses ODBC syntax should work using the hash ref
     method.  With other drivers you should pass the DBI data source
     instead (this method will work with all drivers.)

CHANGE SINCE LAST RELEASE
=========================

   * Changed how CVSVERSION and LAST_CHANGE are calculated.

   * Made it so that you can pass routines literal strings instead of
       variables (variables are used with bind_params when possbile) by
          passing a scalar reference.

   * I also allow array references to do this (in some circumstances)
       but this is depricated.

   * Made connect optionally accept DBI handles instead of connection
       info, by recommendation of Mark Stosberg <mark@summersault.com>.

AUTHOR
======

   Andrew Turner <turnera@cpan.org>

COPYRIGHT
=========

   (C) Copyright 1998-2000 MINT

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

WEBSITE
=======

   http://sourceforge.net/projects/dbix-abstract/

SEE ALSO
========

   `DBI(3)' in this node

DBD independant class
*********************

NAME
====

   DBIx::AnyDBD - DBD independant class

DESCRIPTION
===========

   This class provides application developers with an abstraction class a
level away from DBI, that allows them to write an application that works
on multiple database platforms. The idea isn't to take away the
responsibility for coding different SQL on different platforms, but to
simply provide a platform that uses the right class at the right time for
whatever DB is currently in use.

SYNOPSIS
========

     use DBIx::AnyDBD;

     my $db = DBIx::AnyDBD->connect("dbi:Oracle:sid1",
         "user", "pass", {}, "MyClass");

     my $foo = $db->foo;
     my $blee = $db->blee;

   That doesn't really tell you much... Because you have to implement a
bit more than that. Underneath you have to have a module MyClass::Oracle
that has methods foo() and blee in it. If those methods don't exist in
MyClass::Oracle, it will check in MyClass::Default, allowing you to
implement code that doesn't need to be driver dependant in the same
module. The foo() and blee() methods will recieve the DBIx::AnyDBD
instance as thier first parameter, and any parameters you pass just go as
parameters.

   See the example Default.pm and Sybase.pm classes in the AnyDBD directory
for an example.

Implementation
==============

   Underneath it's all implemented using the ISA hierarchy, which is
modified when you connect to your database. The inheritance tree ensures
that the right functions get called at the right time. There is also an
AUTOLOADer that steps in if the function doesn't exist and tries to call
the function on the database handle (i.e. in the DBI class). The
sub-classing uses `ucfirst($dbh-'{Driver}->{Name})> (along with some
clever fiddling for ODBC and ADO) to get the super-class, so if you don't
know what to name your class (see the list below first) then check that.

API
===

new( ... )
----------

     dsn => $dsn,
     user => $user,
     pass => $pass,
     attr => $attr,
     package => $package

   new() is a named parameter call that connects and creates a new db
object for your use. The named parameters are dsn, user, pass, attr and
package.  The first 4 are just the parameters passed to DBI->connect, and
package contains the package prefix for your database dependant modules,
for example, if package was "MyPackage", the AUTOLOADer would look for
MyPackage::Oracle::func, and then MyPackage::Default::func. Beware that the
DBD driver will be ucfirst'ed, because lower case package names are
reserved as pragmas in perl. See the known DBD package mappings below.

   If attr is undefined then the default attributes are:

     AutoCommit => 1
     PrintError => 0
     RaiseError => 1

   So be aware if you don't want your application dying to either eval{}
all db sections and catch the exception, or pass in a different attr
parameter.

   After re-blessing the object into the database specific object,
DBIx::AnyDBD will call the _init() method on the object, if it exists.
This allows you to perform some driver specific post-initialization.

connect($dsn, $user, $pass, $attr, $package)
--------------------------------------------

   connect() is very similar to DBI->connect, taking exactly the same first
4 parameters. The 5th parameter is the package prefix, as above.

   connect() doesn't try and default attributes for you if you don't pass
them.

   After re-blessing the object into the database specific object,
DBIx::AnyDBD will call the _init() method on the object, if it exists.
This allows you to perform some driver specific post-initialization.

$db->get_dbh()
--------------

   This method is mainly for the DB dependant modules to use, it returns
the underlying DBI database handle. There will probably have code added
here to check the db is still connected, so it may be wise to always use
this method rather than trying to retrieve $self->{dbh} directly.

Known DBD Package Mappings
==========================

   The following are the known DBD driver name mappings, including
ucfirst'ing them:

     DBD::Oracle => Oracle.pm
     DBD::Sybase => Sybase.pm
     DBD::Pg => Pg.pm
     DBD::mysql => Mysql.pm
     DBD::Informix => Informix.pm

   If you use this on other platforms, let me know what the mappings are.

ODBC
----

   ODBC needed special support, so when run with DBD::ODBC, we call GetInfo
to find out what database we're connecting to, and then map to a known
package.  The following are the known package mappings for ODBC:

     Microsoft SQL Server (7.0 and MSDE) => MSSQL.pm
     Microsoft SQL Server (6.5 and below) => Sybase.pm (sorry!)
     Sybase (ASE and ASA) => Sybase.pm
     Microsoft Access => Access.pm
     Informix => Informix.pm
     Oracle => Oracle.pm

   Anything that isn't listed above will get mapped using the following
rule:

     Get rdbms name using: $dbh->func(17, GetInfo);
     Change whitespace to a single underscore
     Add .pm on the end.

   So if you need to know what your particular database will map to,
simply run the $dbh->func(17, GetInfo) method to find out.

   ODBC also inserts `$package::ODBC.pm' into the hierarchy if it exists,
so the hierarchy will look like:

     DBIx::AnyDBD <= ODBC.pm <= Informix.pm

   (given that the database you're connecting to would be Informix). This
is useful because ODBC provides its own SQL abstraction layer.

ADO
---

   ADO uses the same semantics as ODBC for determining the right driver or
module to load. However in extension to that, it inserts an ADO.pm into
the inheritance hierarchy if it exists, so the hierarchy would look like:

     DBIx::AnyDBD <= ODBC.pm <= ADO.pm <= Informix.pm

   I do understand that this is not fundamentally correct, as not all ADO
connections go through ODBC, but if you're doing some of that funky stuff
with ADO (such as queries on MS Index Server) then you're not likely to
need this module!

LICENCE
=======

   This module is free software, and you may distribute it under the same
terms as Perl itself.

SUPPORT
=======

   Commercial support for this module is available on a pay per incident
basis from Fastnet Software Ltd. Contact matt@sergeant.org for further
details. Alternatively join the DBI-Users mailing list, where I'll help
you out for free!

a little layer somewhere between top-level code and raw DBI calls
*****************************************************************

NAME
====

   DBIx::Broker - a little layer somewhere between top-level code and raw
DBI calls

SYNOPSIS
========

     use DBIx::Broker;

     $db  =  DBIx::Broker->new( $DBI_driver, $database, $hostname, $port, $user, $password );

     $db  =  DBIx::Broker->new( );

     $db->is_active( );

     $db->set_db_handle( $classic_dbi_handle );
     $classic_dbi_handle  =  $db->get_db_handle( );

     $another_db_obj  =  $db->clone();

     $db->debug_on( \*DEBUG_OUTPUT_HANDLE );
     $db->debug_off( );

     @query_results  =  $db->select( \@desired_fields, \@desired_tables, $stipulations, $hash_or_not );
     @query_results  =  $db->select( \@desired_fields, $desired_table, $stipulations, $hash_or_not );
     [..etc..]

     @query_results  =  $db->select_all( \@desired_tables, $stipulations, $hash_or_not );

     $db->select_incrementally( \@desired_fields, \@desired_tables, $stipulations );
     $db->select_all_incrementally( \@desired_tables, $stipulations );

     $next_row_ref  =  $db->get_next_row( $hash_or_not );

     $number_of_rows  =  $db->count( $desired_table, $stipulations );

     $a_single_value  =  $db->select_one_value( $desired_field, $desired_table, $stipulations );

     @scalar_query_results  =  $db->select_one_column( $desired_field, \@desired_tables, $stipulations );

     $single_row_ref  =  $db->select_one_row( \@desired_fields, \@desired_tables, $stipulations, $hash_or_not );

     $db->delete( $desired_table, $stipulations );
     $db->delete_all( $desired_table );

     $db->insert( $desired_table, \%new_data );
     $insert_id  =  $db->insert( $desired_table, \%new_data );  # MySQL only!!
     $db->update( $desired_table, \%new_data, $stipulations );

     $db->use_db( "another_database" );

     $db->execute_sql( $some_raw_sql );

     %table_schema  =  $db->get_table_schema( $table );

     $primary_key   =  $db->get_primary_key( $table );

     @auto_increment_fields  =  $db->get_auto_increments( $table );

     #  Oracle users may find this one handy..
     $db->force_lowercase_fields( );

     #  this is just a wrapper around the corresponding DBI function
     $db->func( @func_arguments, $func_name );

     $db->disconnect( );

     $db->finish( );

DESCRIPTION
===========

     DBIx::Broker does what it says, it breaks databases (using DBI!).
     Or else you can use it to unclutter your code of its annoying
     and ugly ->execute()s and ->prepare()s and the like.  It will
     work using any Perl DBI driver (via ->new()) or database handle
     (via ->set_db_handle()).  The most common usage is to store the
     query results in an array of references, each corresponding to
     a row of results.  You may retrieve the results as array refs or
     hash refs, depending upon whether you supplied 0 or 1,
     respectively, as the $hash_or_not parameter.  For almost all
     operations, you are able to supply the desired fields and
     relevant tables either as a scalar (if there is just one value)
     or as an array reference. i.e., you can say

     $db->select( 'login', 'mail_accounts', 'WHERE status > 0', 1 )

     or else set up something more complicated with field and table
     arrays, like

     @desired_fields  =  ( "c.firstName", "c.lastName", "c.customerID", "m.login" );
     @desired_tables  =  ( "customers c", "mail_accounts m" );
     $stipulations    =  'WHERE m.status > 0 AND m.assoc_customerID = c.customerID';
     @query_results   =  $db->select( \@desired_fields, \@desired_tables, $stipulations, 1 );

     For inserting and updating rows, you send a hashref whose keys are
     the table field names and whose values are the new entries.  You may
     also retrieve the insert ID for a new row upon $db->insert(); however,
     this feature is currently only available with MySQL databases.

     The *_incrementally() routines retrieve the same results as their
     counterparts, but rather than returning all rows at once in an
     array, the statement handle is left hanging and rows may be
     retrieved one at a time, like

     $next_row_ref  =  $db->get_next_row( $hash_or_not ).

     It is recommended that you almost always use C<$hash_or_not = 1>,
     for calling-level code readability, as well as extensibility.
     Array references are supported only to avoid the inevitable
     complaints that they are not supported.

     The most common usage of $db->debug_on( ) is to send it \*STDERR
     or \*STDOUT, but you can always have some fun and use a file
     handle or a named pipe or something.  While debugging is on, all
     SQL statements are printed to the debugging output handle for
     examination.  This can be very handy.

     Most of the time you\'ll be using this module something like

     @customers  =  $db->select_all( 'customers', "WHERE age < 30", 1 );
     foreach my $customer ( @customers ) {
         print "Customer $customer->{'customerID'}: ";
         print "$customer->{'last_name'}, $customer->{'first_name'}";
     }

     And if none of the existing functions are adequate, you can send
     a raw SQL statement if you\'d like, by using

     $db->execute_sql( "SELCET name FORM mailbox_tabel WHEER login = 'binkler'" );

     You may retrieve table schema information in the form of a
     hashtable, whose keys are the field names and whose values are
     hashrefs to the various characteristics of each field, such as
     'Type', 'Key', etc.  For convenience, the ->get_primary_key()
     and ->get_auto_increments() methods have also been added.

AUTHOR
======

     xomina@bitstream.net

SEE ALSO
========

   perl(1), DBI(3).

Easy DB access from a CGI
*************************

NAME
====

   DBIx::CGITables 0.001 - Easy DB access from a CGI

SYNOPSIS
========

   use DBIx::CGITables;

   my %parameters=();

   my $query=DBIx::CGITables->new(\%parameters));

   $query->search_execute_and_do_everything_even_parse_the_template();

DESCRIPTION
===========

   This module is under development - and this version is not tested very
well.  The documentation might not be completely in sync with the latest
changes, and the documentation is not optimized for easy understanding at
the moment.  Sorry.

   DBIx::CGITables is made for making database access through CGIs really
easy.

   It's completely template-oriented.  The templates are in HTML::Template
format.  Some templates might be set up quickly by using
DBIx::CGITables::MakeTemplates; see the doc for this module.  Some web
designer should fix the templates a bit.

   The template approach might make the system a bit "static".  Gerald
Richter has another approach based upon HTML::Embperl (not published at
the time I write this), if you'd better like a more dynamic system.
Anyway, I find it quite important not to mix HTML and code - the HTML
documents should be easy to manipulate by non-technical web editors.

   Ideally, HTML and (language-dependent) content should be splitted.  I
think such things might be done better by using Zope than cgis.

   The database handling is done by DBIx::Recordset - this module gets its
parametres first from a CGI query, then it might be overridden or
completed by a parameter file, and the caller (your .cgi script or
whatever) is also free to modify or add parameters.

   I'm hoping that anybody should get a working (though, probably ugly)
CGI interface to any kind of database simply:

   1. Run DBIx::CGITables::MakeTemplates (see the pod)

   2. Create the script given above at SYNOPSIS

   3. Set up the webserver correct.

   4. If you're not satisfied with the look, try to edit the html
templates.

   5. If you're not satisfied with the functionality, try reading the
rest of this documentation, and the DBIx::Recordset documentation.

   6. If you're still not satisfied with the functionality and/or you
find bugs, hack the code and submit the patches to the mailinglist
and/or me and/or (if DBIx::Recordset is affected) Gerhard Richter.     If
you're not a perl hacker, or if you don't have time, send a mail    about
what's wrong and/or what's missing to the mailinglist anyway.     Or
privately to me if you don't want to write to a mailinglist.

PARAMETERS
==========

How to feed the script with parameters
--------------------------------------

   Firstly, parameters are taken from the query.

   Then, parameters on are taken from the *parameter file*.  This file is
either located in the same folder as the templates, or in a folder as
specified in the parameters.  The parameter file contains options to
DBIx::CGITables and to DBIx::Recordsets.  I'm more or less trying to
follow up the parameter style DBIx::Recordset is using - with one special
character in front of the parameter suggesting what kind of parameter it
is.  It is quite a bit kludgy, but it works.  The parameters should be at
the key=value form, i.e.:

   !Table=tablename !DataSource=...  !NoRGV !NoT

   CGITables will recognize a key starting with =, so it's possible to put
up '=execute=1' at a line.  The default value will be 1, so '=execute'
should be equivalent.

   If the line contains more than one equal sign which is not at the start
of the line, the other equal signs will be threated as a part of the value.

   Eventually conflicts will appear as the param keys are duplicated in
the query and in the param file.  The default is that the param file
overrides the query.  This might be changed by a special code inserted in
front of the key=value-pair to override this behaviour.  (I think too many
special codes might be a bit hairy ... but I hope this will work out
anyway).  Those codes start with '%' since this character is not used by
DBIx::Recordset, and they're separated from the key=value couple by one
space.  In addition to suggesting how collitions should be

   %= or %! 	  Always override options set other places

   %+, 	  Add new stuff to a comma separated list.  The comma might be
replaced by any other character, and to \t and \n, or simply
removed. Use '\ ' for a blank and '\\' for a backslash.

   %^, 	  Prepend, separate from existing value with a comma (same 	  rules
as above)

   %?        Yield - use this with default values that should only be set
 if no other values are set.

   %!()      Override or ignore - that is, if the key exists, overwrite,
       if not, ignore.

   %() 	  Ignore option (but keep it in template outputs)

   %T        Template option.  The key=value is given the Template Class.

   %RGV      Recordset Global Variable, most important ones are
PreserveCase and Debug.

   For =execute parameters (see DBIx::Recordset), %= or %! will `override'
other =execute by deleting those.  %+ and %^ will execute things in order.
The default is to use the priority set by DBIx::Recordset.

   In my older system, I had something called dependent and independent
subqueries.  A `dependent subquery' is a link in the DBIx::Recordset
terminology.  An `independent subquery' would be an independent
DBIx::Recordset object, i.e. for fetching data for a HTML select box.  I
also had an option to only `resolve' links when the select returned only
one row - not to waste time fetching too much data when a long list was
fetched.  I guess Recordset handles this more or less automagically.

   `dependent subqueries' (or links, if you'd like) might be handed over
like this:

   !Links/-street/!Table=street !Links/-street/!LinkedField=id
!Links/-street/!MainField=street_id

   Drop the first `!Links' to create an independent subquery.  The primary
subquery has the tag "default" without a starting minus.  The tags should
better start with minus, to avoid inprobable though potential clashes with
other output template substitutions.

   My earlier systems had some weird syntax for creating misc lists from
the parameters.  DBIx::Recordset uses string splitting.

First characters
----------------

   The first character in a parameter key or a line in the parameter file
is often special.  It's a bit messy, but I think it's the easiest way to
do it, anyway - if the rules are obeyed there shouldn't be any
ambiguisities.  Here's a complete list of the first characters:

     % - reserved for a `special handling' code putted in front of the
         real key/param.  This special code is usually describing how to
         handle parameter collitions, but also to tell that the key/param
         should be ignored, or belongs somewhere else (i.e. the
         PreserveCase option is a global variable that might need
         modification)

     / - reserved for extra named Recordset objects.

     ! - reserved for Recordset initialization and important parameters to
         CGITables.

     - - reserved for the name of a named Recordset object.

   See the DBIx::Recordset manual for those:  ' - reserved for a DB column
key = value that needs quoting  # -      ...... numeric value  \ -
...... value that should not be quoted (i.e. SQL function)  + -
...... value with multiple fields  * -      ...... Operator for DB column
key

     $ - misc options to Recordset and CGITables.

     = - execute commands to Recordset

     ? - extra output (typically ?id and ?count)

     ; - If you need extra parameters for containing state, start the
         variable name with one of those "comment" signs to avoid possible
         clashes.

Supported and future parameters
-------------------------------

   Supported parameters:

   !!Filename - defaults to $ENV{PATH_TRANSLATED}

   !!ParamFileDir - Default directory for finding ParamFile

   !!ParamFile - See below for default.  Ignores ParamFileDir.

   !!QueryClass - defaults to 'CGI', but I'm intending to head for
CGI::Fast

   !!Query - defaults to new !!QueryClass

   !TemplateClass - defaults to 'HTML::Template'

   !RecordsetClass - defaults to 'DBIx::Recordset'

   !DoNothing

   !SearchForm specifies that a search form should be printed. No
searching is done, and the default loop is returned with one 	empty
element.  This is typically useful when viewing the data 	in a
looped form, then this one will create an empty form.

   The parameters starting with '!!' must be set before the query and
parameter file is parsed.

   !Mod2 should give an output variable ?mod2 which indicates whether the
row count is an odd or not.  This is a very popular feature demand, though
not possible to implement in a nice way in this scheme.  I don't think it
belongs to the template engine, but it would be quite ugly putting it
elsewhere, I think.  I've putted a hack into the sub faenskopiering which
really shouldn't be called in the first place.  This hack ignores !Mod2
and inserts ?mod2 into the tables.

   $substring_search=column[,column..] will enable substring search for
the selected attribute.  This means *column will be set to " LIKE " and
the value will be set to "%value%" in searches.  This should be used with
care, as it might strain on most databases.  Anyway, mysql handles it
well. Case sensitivity might be an issue, searches in mysql are always
case insensitive.

   Possible future parameters: !IncludeParamfile !ParamMacro !Ooups
!OtherTemplate !SetSelected

   For !Links: $fetch_always (default) $fetch_when_found_one
$fetch_when_found_more $fetch_when_found_none

   Unfortunately I don't have the time writing more docs due to deadlines.

Output to the templates
-----------------------

   Unfortunately I don't have the time writing more docs due to deadlines.

     ?count (at the top level)
         The number of elements returned.  Nice to use in constructs
         like
            <TMPL_UNLESS name="?count">Sorry, didn't find
            anything</TMPL_UNLESS>

     ?mod2 (in all recordset loops)
         0 for even, 1 for odd (0 beeing "odd")

     any parameter key (at the top level) will give the corresponding
     value.

     a loop called cgi_query with the variables key and value will give
     the query - nice for forwarding a query in hidden input tags.

     Each database query have a loop with _only_ the database values
     (except ?mod2 which really is a hack).  It would have helped a lot
     to have access to the outer scope variables in the inner loop, but
     it seems like the author of the template engine in use disagrees.

TEMPLATE NAMING CONVENTIONS
===========================

   The templates should have an extention matching /\.(\w+)$/ - typically
sth like mydatabase.CGITables or mydatabase.db or mydatabase.db_html.  The
script will then search for the param file mydatabase.param.$1, i.e.
mydatabase.param.db.  It might also use another template if found,
mydatabase.$status.$1, where $status might be one of (in prioritied order):

     error
     update_ok
     delete_ok
     add_ok
     found_$n
     found_more

   (this is not completely implemented yet)

TODO
====

   Probably a lot of important features are missing.  It might also be
slow as it's costly to build Recordsets, and they're discarded after each
call to the cgi; I'm intending to solve this by optimizing for CGI::Fast
and storing the frequently used recordsets in a cache.  Eventually such a
cache should be kept in shared memory.  I haven't looked at it yet, but
Sam Tregar has announced some general module for keeping caches in shared
memory.

KNOWN BUGS
==========

   The code contains this line several places:    die "stub!";

   When this code is executed with the warning flag, there might be some
warnings popping up from the DBIx::Recordset module.  Those will
eventually disappear in newer versions of DBIx::Recordset.

   This is UNDER DEVELOPMENT and ABSOLUTELY NOT GOOD ENOUGH TESTED.  The
number of unknown bugs is probably high.

HISTORY
=======

   Version 0.

   This started as some template cgi system that needed database access.
To allow better flexibility, I made some hacks to allow SQL code to be
inserted into the template.  This was ... ugly, hairy and hacky.  I
expanded it, so the SQL code could be in separate files.  It still was
ugly, hairy and hacky.

   Version 1.

   I started more or less from scratch, and made a new system, where SQL
code and other parameters to the script could be inserted into a special
parameter file.  The script would "automagically" generate SQL to select,
update, insert and delete rows from tables.  It started out a lot better
than version 0, but it was still hairy, and it certainly only became worse
and worse as more and more features was to be added.

   Version 2.

   I started from scratch again, this time with object oriented modules -
DBIx::Access and DBIx::CGIAccess.  This time I aimed for cleanliness.  But
I think it has grown more messy as more features was to be crammed in.
I'm currently merging from the Solid database to MySQL - and I'm a bit
horrified because MySQL is case sensitive, and Solid wasn't - which might
mean that I will have to redesign some of the parameter syntax (I've
chosen UPPERCASE for database column names, and lowercase for misc
options).

   Version 3.

   I registered at CPAN and got a "go" for DBIx::Tables and
DBIx::CGITables.

   I scratched my head in a week.  Then I started from scratch again,
discarding DBIx::Tables for DBIx::Recordset.

   Some of the uglyness from earlier versions remain - a quite "ugly"
symbol usage in the param file/query, like "%() !Table=foo".  Maybe I
would have tried doing it in a better way if it wasn't for Recordset
already having parameters prepended by a special character.

HACKING
=======

   Feel free to submit patches, but also normal feedback, bugfixes and
wishlists.

SECURITY
========

   It's up to you to provide proper security.  I think the Right Way to do
it is to let the .cgi do the authentication (i.e. by SSL certificates or
transmitting the DB login and password encrypted) and then let the DBMS
control what privilegies the user should have.

   Another way is to override all potentially harmful parameters to the
DBIx::Recordset, either by the param file or by a hash to sub
search_execute_and_do_everything_even_parse_the_template

AUTHOR
======

   Tobias Brox <tobiasb@funcom.com>

   Feedback is appreciated - even flames.  I will eventually put up a
mailing list if I notice any interesst about this module.

   This module was written partly in my worktime.  Shameless plug for my
employer:

   Check our upcoming MMORPG at http://www.anarchy-online.com/ - Linux
client will be available.

   Play multiplayer Spades, Backgammon, Poker and more for free at
http://www.funcom.com/ (Java)

creates templates for CGITables.
********************************

NAME
====

   DBIx::CGITables::MakeTemplates - creates templates for CGITables.

SYNOPSIS
========

     cd /path/to/webserver/document_root/wherever/the/templates/should/be

     mysqldump -d mydatabase > /tmp/schema.dd
     echo '-- END' >> /tmp/schema.dd
     vi /tmp/schema.dd
     perl -MDBIx::CGITables::MakeTemplates -e 'make "dbi:mysql:test:localhost"'< /tmp/schema.dd

DESCRIPTION
===========

   This is under construction, there might be code stubs, some of the
announced features might be missing, and if you're more unlucky it might
not work at all.  Feedback will probably speed up my work on this.

   This module takes its input from a set of data definitions (SQL `create
table' statements), and generates templates and parameter files for the
tables.  The data definition file should be edited slightly before running
MakeTemplates.

   The most important thing about the hand-editing is to deal with the
foreign keys.  Mysql doesn't have them at all, so they will eventually
have to be manually added.  If there is a "Foreign key
(foreign_id)..."-line, then the attribute line (typically something like
"foreign_id integer") should be removed - eventually the other way.

   Attributes might be added to describe how to handle attributes and
foreign keys - unfortunately I don't have time documenting them at the
moment.

   Eventually, the module should work without any editing of the DD at
all, just reading the eventual extra configuration information from an
extra file.

   The module will produce three files; the form template
($dbname.$tablename.dbt), the list template
($dbname.$tablename.found_more.dbt) and the parameter file
($dbname.$tablename.param.dbt).

   About foreign keys (not implemented yet);

   Mysql doesn't have them - so if links are needed, the dd code needs to
be modified.  The dd code should be modified anyway.  In a create table
statement, the attribute should first be declared (i.e. `user_id
integer'), and later it should be declared that it's a foreign key. One of
those lines should be deleted - you will probably want to remove the
attribute declaration (the foreign key will be respected), alternatively
the foreign key declaration (letting the foreign key be threated as just
another attribute).

KNOWN BUGS
==========

   This is just some loose hacks.  This is under construction (maybe it
would be even better to start from scratch redoing it).  This is
absolutely not tested very well.  It is not a SQL parser, and it's only
tested for the output from mysql and solid.  It's linebreak sensitive, so
it might not be compatible with other DBMSs.  Foreign keys are not
supported yet.  This documentation sucks.  The code sucks.  Well.

AUTHOR
======

   Tobias Brox <tobiasb@funcom.com>

For copying database content from one db to another
***************************************************

NAME
====

   DBIx::Copy 0.02 - For copying database content from one db to another

SYNOPSIS
========

   use DBIx::Copy; use DBI;

   my $dbh_source=DBI->connect(...); my $dbh_target=DBI->connect(...);

   my %options=();

   my $copy_handler=     DBIx::Copy->new($dbh_source, $dbh_target,
\%options);

   $copy_handler->copy     (['tabletobecopied', 'anothertabletobecopied',
...]);

DESCRIPTION
===========

   For copying a DB.  Future versions might handle mirroring as well, but
it's generally better if the source might send over a transaction log
somehow.

   The current version takes a crude "select * from table" from the source
table, and crudely puts it all into the destination table, with a "delete
from table" and "insert into table values (?, ?, ?, ...)".  Eventually
column names are specified (option column_translation_table).  There might
be problems with this approach for all I know.  Anyway, I think I can
promise that the synopsis above will behave the same way also for future
versions of DBIx::Copy.

   Currently the module can only copy data content.  Data definitions
might be handled in a future version.

OPTIONS
=======

table_translation_table
-----------------------

   If a table called FOO in the source database should be called Bar in
the destination database, it's possible to specify it in the options:

     $options{'table_tanslation_table'}={'FOO' => 'Bar'};

column_translation_table
------------------------

   If the table FOO contains a column with the name
"LASTUPDATEDTIMESTAMP", and we want to call it "LastUpdated" in the table
Bar, it's possible to specify it:

     $options{'column_translation_table'}->{FOO}={
     	'ID' => 'id',
     	'TITLE' => 'Title',
     	'LASTUPDATEDTIMESTAMP' => 'LastUpdated'
     	# _All_ columns you want to copy must be mentionated here.  I
     	# will eventually fix a sub for initializing such a hash
     	# reference.
     }

ERROR HANDLING AND STABILITY
============================

   DBIx::Copy->new will die unless it's feeded with at least two arguments.

   copy will just return undef if it fails somewhere.

   The exception will probably be raised within the DBI.  By adjusting
settings within the DBI object, the error handling might be improved.
Check the options AutoCommit, PrintError and RaiseError.

   Currently the module is optimisticly lacking all kind of locking.  This
will have to be done outside the module.

   Be aware that the testing script following this package is NOT GOOD
ENOUGH, it should be tested by hand using the synopsis above.

TODO
====

data_definitions
----------------

   The module should also be capable of copying data definitions

avoid_deletion
--------------

   It should be possible to avoid deleting the old table before inserting
a new.  The module should (by first running a select call) avoid inserting
duplicates.  This option will only insert new rows, not update old ones.

replace
-------

   Do not delete old data in the destination table unless it is to be
replaced by new data from the source table.

max_timestamp / mirror
----------------------

   Check the timestamps and only import rows that has been modified after
max_timestamp (typically the timestamp for the last import).

   mirror will try to fetch the last timestamp from the database, and
store the new timestamp in the database.

merge
-----

   If the same row is edited in both databases, try to merge the result.

locking
-------

   Locking should be supported somehow.

KNOWN BUGS
==========

   Except for all the "buts" and "ifs" and missing features above - none
yet - but this module is very poorly tested!

LICENSE
=======

   Copyright (c) 2000 Tobias Brox.  All rights reserved.  This program is
released under the GNU Public License.  It might also be released under
The Artistic License if you send me a mail why GPL is insufficient.

AUTHOR
======

   Tobias Brox <tobix@irctos.org>. Comments, bug reports, patches and
flames are appreciated.

Database-independent schema objects
***********************************

NAME
====

   DBIx::DBSchema - Database-independent schema objects

SYNOPSIS
========

     use DBIx::DBSchema;

     $schema = new DBIx::DBSchema @dbix_dbschema_table_objects;
     $schema = new_odbc DBIx::DBSchema $dbh;
     $schema = new_odbc DBIx::DBSchema $dsn, $user, $pass;
     $schema = new_native DBIx::DBSchema $dbh;
     $schema = new_native DBIx::DBSchema $dsn, $user, $pass;

     $schema->save("filename");
     $schema = load DBIx::DBSchema "filename";

     $schema->addtable($dbix_dbschema_table_object);

     @table_names = $schema->tables;

     $DBIx_DBSchema_table_object = $schema->table("table_name");

     @sql = $schema->sql($dbh);
     @sql = $schema->sql($dsn, $username, $password);
     @sql = $schema->sql($dsn); #doesn't connect to database - less reliable

     $perl_code = $schema->pretty_print;
     %hash = eval $perl_code;
     use DBI qw(:sql_types); $schema = pretty_read DBIx::DBSchema \%hash;

DESCRIPTION
===========

   DBIx::DBSchema objects are collections of DBIx::DBSchema::Table objects
and represent a database schema.

   This module implements an OO-interface to database schemas.  Using this
module, you can create a database schema with an OO Perl interface.  You
can read the schema from an existing database.  You can save the schema to
disk and restore it a different process.  Most importantly, DBIx::DBSchema
can write SQL CREATE statements statements for different databases from a
single source.

   Currently supported databases are MySQL and PostgreSQL.  DBIx::DBSchema
will attempt to use generic SQL syntax for other databases.  Assistance
adding support for other databases is welcomed.

METHODS
=======

new TABLE_OBJECT, TABLE_OBJECT, ...
     Creates a new DBIx::DBSchema object.

new_odbc DATABASE_HANDLE | DATA_SOURCE USERNAME PASSWORD [ ATTR ]
     Creates a new DBIx::DBSchema object from an existing data source,
     which can be specified by passing an open DBI database handle, or by
     passing the DBI data source name, username, and password.  This uses
     the experimental DBI type_info method to create a schema with
     standard (ODBC) SQL column types that most closely correspond to any
     non-portable column types.  Use this to import a schema that you wish
     to use with many different database engines.  Although primary key
     and (unique) index information will only be read from databases with
     DBIx::DBSchema::DBD drivers (currently MySQL and PostgreSQL), import
     of column names and attributes *should* work for any database.

new_native DATABASE_HANDLE | DATA_SOURCE USERNAME PASSWORD [ ATTR ]
     Creates a new DBIx::DBSchema object from an existing data source,
     which can be specified by passing an open DBI database handle, or by
     passing the DBI data source name, username and password.  This uses
     database-native methods to read the schema, and will preserve any
     non-portable column types.  The method is only available if there is
     a DBIx::DBSchema::DBD for the corresponding database engine
     (currently, MySQL and PostgreSQL).

load FILENAME
     Loads a DBIx::DBSchema object from a file.

save FILENAME
     Saves a DBIx::DBSchema object to a file.

addtable TABLE_OBJECT
     Adds the given DBIx::DBSchema::Table object to this DBIx::DBSchema.

tables
     Returns a list of the names of all tables.

table TABLENAME
     Returns the specified DBIx::DBSchema::Table object.

sql [ DATABASE_HANDLE | DATA_SOURCE [ USERNAME PASSWORD [ ATTR ] ] ]
     Returns a list of SQL `CREATE' statements for this schema.

     The data source can be specified by passing an open DBI database
     handle, or by passing the DBI data source name, username and password.

     Although the username and password are optional, it is best to call
     this method with a database handle or data source including a valid
     username and password - a DBI connection will be opened and the
     quoting and type mapping will be more reliable.

     If passed a DBI data source (or handle) such as `DBI:mysql:database'
     or `DBI:Pg:dbname=database', will use syntax specific to that
     database engine.  Currently supported databases are MySQL and
     PostgreSQL.

     If not passed a data source (or handle), or if there is no driver for
     the specified database, will attempt to use generic SQL syntax.

pretty_print
     Returns the data in this schema as Perl source, suitable for
     assigning to a hash.

pretty_read HASHREF
     Creates a schema as specified by a data structure such as that
     created by pretty_print method.

AUTHOR
======

   Ivan Kohler <ivan-dbix-dbschema@420.am>

COPYRIGHT
=========

   Copyright (c) 2000 Ivan Kohler Copyright (c) 2000 Mail Abuse Prevention
System LLC All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

BUGS
====

   Each DBIx::DBSchema object should have a name which corresponds to its
name within the SQL database engine (DBI data source).

   pretty_print is actually pretty ugly.

   Perhaps pretty_read should eval column types so that we can use DBI
qw(:sql_types) here instead of externally.

SEE ALSO
========

   See DBIx/DBSchema/Table,
DBIx/DBSchema/ColGroup,
DBIx/DBSchema/ColGroup/Unique,
DBIx/DBSchema/ColGroup/Index,
DBIx/DBSchema/Column, DBIx/DBSchema/DBD,
`DBIx::DBSchema::mysql' in this node,
`DBIx::DBSchema::Pg' in this node, `FS::Record' in this node, `DBI' in
this node

Column group objects
********************

NAME
====

   DBIx::DBSchema::ColGroup - Column group objects

SYNOPSIS
========

     use DBIx::DBSchema::ColGroup;

     $colgroup = new DBIx::DBSchema::ColGroup ( $lol_ref );
     $colgroup = new DBIx::DBSchema::ColGroup ( \@lol );
     $colgroup = new DBIx::DBSchema::ColGroup (
       [
         [ 'single_column' ],
         [ 'multiple_columns', 'another_column', ],
       ]
     );

     $lol_ref = $colgroup->lol_ref;

     @sql_lists = $colgroup->sql_list;

     @singles = $colgroup->singles;

DESCRIPTION
===========

   DBIx::DBSchema::ColGroup objects represent sets of sets of columns.
(IOW a "list of lists" - see Perllol (perl.info).)

METHODS
=======

new [ LOL_REF ]
     Creates a new DBIx::DBSchema::ColGroup object.  Pass a reference to a
     list of lists of column names.

lol_ref
     Returns a reference to a list of lists of column names.

sql_list
     Returns a flat list of comma-separated values, for SQL statements.

     For example:

          @lol = (
                   [ 'single_column' ],
                   [ 'multiple_columns', 'another_column', ],
                 );

          $colgroup = new DBIx::DBSchema::ColGroup ( \@lol );

          print join("\n", $colgroup->sql_list), "\n";

     Will print:

          single_column
          multiple_columns, another_column

singles
     Returns a flat list of all single item lists.

AUTHOR
======

   Ivan Kohler <ivan-dbix-dbschema@420.am>

COPYRIGHT
=========

   Copyright (c) 2000 Ivan Kohler Copyright (c) 2000 Mail Abuse Prevention
System LLC All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

BUGS
====

SEE ALSO
========

   See DBIx/DBSchema/Table,
DBIx/DBSchema/ColGroup/Unique,
DBIx/DBSchema/ColGroup/Index,
DBIx/DBSchema, Perllol (perl.info),
Perldsc (perl.info), `DBI' in this node

Index column group object
*************************

NAME
====

   DBIx::DBSchema::ColGroup::Index - Index column group object

SYNOPSIS
========

     use DBIx::DBSchema::ColGroup::Index;

     # see DBIx::DBSchema::ColGroup methods

DESCRIPTION
===========

   DBIx::DBSchema::ColGroup::Index objects represent the (non-unique)
indices of a database table (see DBIx/DBSchema/Table).
DBIx::DBSchema::ColGroup::Index inherits from
DBIx::DBSchema::ColGroup.

BUGS
====

   Is this empty subclass needed?

SEE ALSO
========

   See DBIx/DBSchema/ColGroup,
DBIx/DBSchema/ColGroup/Unique,
DBIx/DBSchema/Table, DBIx/DBSchema,
`FS::Record' in this node

Unique column group object
**************************

NAME
====

   DBIx::DBSchema::ColGroup::Unique - Unique column group object

SYNOPSIS
========

     use DBIx::DBSchema::ColGroup::Unique;

     # see DBIx::DBSchema::ColGroup methods

DESCRIPTION
===========

   DBIx::DBSchema::ColGroup::Unique objects represent the unique indices
of a database table (see DBIx/DBSchema/Table).
DBIx::DBSchema::ColGroup:Unique inherits from DBIx::DBSchema::ColGroup.

BUGS
====

   Is this empty subclass needed?

SEE ALSO
========

   See DBIx/DBSchema/ColGroup,
DBIx/DBSchema/ColGroup/Index,
DBIx/DBSchema/Table, DBIx/DBSchema,
`FS::Record' in this node

Column objects
**************

NAME
====

   DBIx::DBSchema::Column - Column objects

SYNOPSIS
========

     use DBIx::DBSchema::Column;

     #named params with a hashref (preferred)
     $column = new DBIx::DBSchema::Column ( {
       'name'    => 'column_name',
       'type'    => 'varchar'
       'null'    => 'NOT NULL',
       'length'  => 64,
       'default' => '
       'local'   => '',
     } );

     #list
     $column = new DBIx::DBSchema::Column ( $name, $sql_type, $nullability, $length, $default, $local );

     $name = $column->name;
     $column->name( 'name' );

     $sql_type = $column->type;
     $column->sql_type( 'sql_type' );

     $null = $column->null;
     $column->null( 'NULL' );
     $column->null( 'NOT NULL' );
     $column->null( '' );

     $length = $column->length;
     $column->length( '10' );
     $column->length( '8,2' );

     $default = $column->default;
     $column->default( 'Roo' );

     $sql_line = $column->line;
     $sql_line = $column->line($datasrc);

DESCRIPTION
===========

   DBIx::DBSchema::Column objects represent columns in tables (see
DBIx/DBSchema/Table).

METHODS
=======

new HASHREF
new [ name [ , type [ , null [ , length  [ , default [ , local ] ] ] ] ] ]
     Creates a new DBIx::DBSchema::Column object.  Takes a hashref of named
     parameters, or a list.  name is the name of the column.  type is the
     SQL data type.  null is the nullability of the column (intrepreted
     using Perl's rules for truth, with one exception: `NOT NULL' is
     false).  length is the SQL length of the column.  default is the
     default value of the column.  local is reserved for database-specific
     information.

name [ NAME ]
     Returns or sets the column name.

type [ TYPE ]
     Returns or sets the column type.

null [ NULL ]
     Returns or sets the column null flag (the empty string is equivalent
     to `NOT NULL')

length [ LENGTH ]
     Returns or sets the column length.

default [ LOCAL ]
     Returns or sets the default value.

local [ LOCAL ]
     Returns or sets the database-specific field.

line [ DATABASE_HANDLE | DATA_SOURCE [ USERNAME PASSWORD [ ATTR ] ] ]
     Returns an SQL column definition.

     The data source can be specified by passing an open DBI database
     handle, or by passing the DBI data source name, username and password.

     Although the username and password are optional, it is best to call
     this method with a database handle or data source including a valid
     username and password - a DBI connection will be opened and the
     quoting and type mapping will be more reliable.

     If passed a DBI data source (or handle) such as `DBI:mysql:database'
     or `DBI:Pg:dbname=database', will use syntax specific to that
     database engine.  Currently supported databases are MySQL and
     PostgreSQL.  Non-standard syntax for other engines (if applicable)
     may also be supported in the future.

AUTHOR
======

   Ivan Kohler <ivan-dbix-dbschema@420.am>

COPYRIGHT
=========

   Copyright (c) 2000 Ivan Kohler Copyright (c) 2000 Mail Abuse Prevention
System LLC All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

BUGS
====

   line() has database-specific foo that probably ought to be abstracted
into the DBIx::DBSchema:DBD:: modules.

SEE ALSO
========

   See DBIx/DBSchema/Table, DBIx/DBSchema,
see DBIx/DBSchema/DBD, `DBI' in this
node

DBIx::DBSchema Driver Writer's Guide and Base Class
***************************************************

NAME
====

   DBIx::DBSchema::DBD - DBIx::DBSchema Driver Writer's Guide and Base
Class

SYNOPSIS
========

     perldoc DBIx::DBSchema::DBD

     package DBIx::DBSchema::DBD::FooBase
     use DBIx::DBSchmea::DBD;
     @ISA = qw(DBIx::DBSchema::DBD);

DESCRIPTION
===========

   Drivers should be named DBIx::DBSchema::DBD::DatabaseName, where
DatabaseName is the same as the DBD:: driver for this database.  Drivers
should implement the following class methods:

columns CLASS DBI_DBH TABLE
     Given an active DBI database handle, return a listref of listrefs (see
     Perllol (perl.info)), each containing six elements:
     column name, column type, nullability, column length, column default,
     and a field reserved for driver-specific use.

column CLASS DBI_DBH TABLE COLUMN
     Same as columns above, except return the listref for a single column.
     You can inherit from DBIx::DBSchema::DBD to provide this function.

primary_key CLASS DBI_DBH TABLE
     Given an active DBI database handle, return the primary key for the
     specified table.

unique CLASS DBI_DBH TABLE
     Given an active DBI database handle, return a hashref of unique
     indices.  The keys of the hashref are index names, and the values are
     arrayrefs which point a list of column names for each.  See `"HASHES
     OF LISTS"', see Perldsc (perl.info), and `"HASHES OF
     LISTS"', see DBIx/DBSchema/ColGroup.

index CLASS DBI_DBH TABLE
     Given an active DBI database handle, return a hashref of (non-unique)
     indices.  The keys of the hashref are index names, and the values are
     arrayrefs which point a list of column names for each.  See `"HASHES
     OF LISTS"', see Perldsc (perl.info), and `"HASHES OF
     LISTS"', see DBIx/DBSchema/ColGroup.

AUTHOR
======

   Ivan Kohler <ivan-dbix-dbschema@420.am>

COPYRIGHT
=========

   Copyright (c) 2000 Ivan Kohler Copyright (c) 2000 Mail Abuse Prevention
System LLC All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

BUGS
====

   %typemap needs to be documented.

SEE ALSO
========

   See DBIx/DBSchema, DBIx/DBSchema/DBD/mysql,
see DBIx/DBSchema/DBD/Pg,
see DBIx/DBSchema/ColGroup,
`DBI' in this node, `DBI::DBD' in this node,
see Perllol (perl.info), `"HASHES OF LISTS"', see Perldsc (perl.info),

PostgreSQL native driver for DBIx::DBSchema
*******************************************

NAME
====

   DBIx::DBSchema::DBD::Pg - PostgreSQL native driver for DBIx::DBSchema

SYNOPSIS
========

   use DBI; use DBIx::DBSchema;

   $dbh = DBI->connect('dbi:Pg:dbname=database', 'user', 'pass'); $schema
= new_native DBIx::DBSchema $dbh;

DESCRIPTION
===========

   This module implements a PostgreSQL-native driver for DBIx::DBSchema.

AUTHOR
======

   Ivan Kohler <ivan-dbix-dbschema@420.am>

COPYRIGHT
=========

   Copyright (c) 2000 Ivan Kohler Copyright (c) 2000 Mail Abuse Prevention
System LLC All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

BUGS
====

   Yes.

   columns doesn't return column default information.

SEE ALSO
========

   See DBIx/DBSchema, DBIx/DBSchema/DBD,
`DBI' in this node, `DBI::DBD' in this node

MySQL native driver for DBIx::DBSchema
**************************************

NAME
====

   DBIx::DBSchema::DBD::mysql - MySQL native driver for DBIx::DBSchema

SYNOPSIS
========

   use DBI; use DBIx::DBSchema;

   $dbh = DBI->connect('dbi:mysql:database', 'user', 'pass'); $schema =
new_native DBIx::DBSchema $dbh;

DESCRIPTION
===========

   This module implements a MySQL-native driver for DBIx::DBSchema.

AUTHOR
======

   Ivan Kohler <ivan-dbix-dbschema@420.am>

COPYRIGHT
=========

   Copyright (c) 2000 Ivan Kohler Copyright (c) 2000 Mail Abuse Prevention
System LLC All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

BUGS
====

SEE ALSO
========

   See DBIx/DBSchema, DBIx/DBSchema/DBD,
`DBI' in this node, `DBI::DBD' in this node

Table objects
*************

NAME
====

   DBIx::DBSchema::Table - Table objects

SYNOPSIS
========

     use DBIx::DBSchema::Table;

     $table = new DBIx::DBSchema::Table (
       "table_name",
       "primary_key",
       $dbix_dbschema_colgroup_unique_object,
       $dbix_dbschema_colgroup_index_object,
       @dbix_dbschema_column_objects,
     );

     $table->addcolumn ( $dbix_dbschema_column_object );

     $table_name = $table->name;
     $table->name("table_name");

     $primary_key = $table->primary_key;
     $table->primary_key("primary_key");

     $dbix_dbschema_colgroup_unique_object = $table->unique;
     $table->unique( $dbix_dbschema__colgroup_unique_object );

     $dbix_dbschema_colgroup_index_object = $table->index;
     $table->index( $dbix_dbschema_colgroup_index_object );

     @column_names = $table->columns;

     $dbix_dbschema_column_object = $table->column("column");

     #preferred
     @sql_statements = $table->sql_create_table $dbh;
     @sql_statements = $table->sql_create_table $datasrc, $username, $password;

     #possible problems
     @sql_statements = $table->sql_create_table $datasrc;
     @sql_statements = $table->sql_create_table;

DESCRIPTION
===========

   DBIx::DBSchema::Table objects represent a single database table.

METHODS
=======

new [ TABLE_NAME [ , PRIMARY_KEY [ , UNIQUE [ , INDEX [ , COLUMN... ] ] ] ] ]
     Creates a new DBIx::DBSchema::Table object.  TABLE_NAME is the name
     of the table.  PRIMARY_KEY is the primary key (may be empty).  UNIQUE
     is a DBIx::DBSchema::ColGroup::Unique object (see
     DBIx/DBSchema/ColGroup/Unique).
     INDEX is a DBIx::DBSchema::ColGroup::Index object (see
     DBIx/DBSchema/ColGroup/Index).  The
     rest of the arguments should be DBIx::DBSchema::Column objects (see
     DBIx/DBSchema/Column).

new_odbc DATABASE_HANDLE TABLE_NAME
     Creates a new DBIx::DBSchema::Table object from the supplied DBI
     database handle for the specified table.  This uses the experimental
     DBI type_info method to create a table with standard (ODBC) SQL
     column types that most closely correspond to any non-portable column
     types.   Use this to import a schema that you wish to use with many
     different database engines.  Although primary key and (unique) index
     information will only be imported from databases with
     DBIx::DBSchema::DBD drivers (currently MySQL and PostgreSQL), import
     of column names and attributes *should* work for any database.

new_native DATABASE_HANDLE TABLE_NAME
     Creates a new DBIx::DBSchema::Table object from the supplied DBI
     database handle for the specified table.  This uses database-native
     methods to read the schema, and will preserve any non-portable column
     types.  The method is only available if there is a
     DBIx::DBSchema::DBD for the corresponding database engine (currently,
     MySQL and PostgreSQL).

addcolumn COLUMN
     Adds this DBIx::DBSchema::Column object.

name [ TABLE_NAME ]
     Returns or sets the table name.

primary_key [ PRIMARY_KEY ]
     Returns or sets the primary key.

unique [ UNIQUE ]
     Returns or sets the DBIx::DBSchema::ColGroup::Unique object.

index [ INDEX ]
     Returns or sets the DBIx::DBSchema::ColGroup::Index object.

columns
     Returns a list consisting of the names of all columns.

column COLUMN_NAME
     Returns the column object (see DBIx/DBSchema/Column)
     for the specified COLUMN_NAME.

sql_create_table [ DATABASE_HANDLE | DATA_SOURCE [ USERNAME PASSWORD [ ATTR ] ] ]
     Returns a list of SQL statments to create this table.

     The data source can be specified by passing an open DBI database
     handle, or by passing the DBI data source name, username and password.

     Although the username and password are optional, it is best to call
     this method with a database handle or data source including a valid
     username and password - a DBI connection will be opened and the
     quoting and type mapping will be more reliable.

     If passed a DBI data source (or handle) such as `DBI:mysql:database',
     will use MySQL- or PostgreSQL-specific syntax.  Non-standard syntax
     for other engines (if applicable) may also be supported in the future.

AUTHOR
======

   Ivan Kohler <ivan-dbix-dbschema@420.am>

COPYRIGHT
=========

   Copyright (c) 2000 Ivan Kohler Copyright (c) 2000 Mail Abuse Prevention
System LLC All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

BUGS
====

   sql_create_table() has database-specific foo that probably ought to be
abstracted into the DBIx::DBSchema::DBD:: modules.

   sql_create_table may change or destroy the object's data.  If you need
to use the object after sql_create_table, make a copy beforehand.

   Some of the logic in new_odbc might be better abstracted into Column.pm
etc.

SEE ALSO
========

   See DBIx/DBSchema,
DBIx/DBSchema/ColGroup/Unique,
DBIx/DBSchema/ColGroup/Index,
DBIx/DBSchema/Column, `DBI' in this node

Database-independant create and drop functions
**********************************************

NAME
====

   DBIx::DataSource - Database-independant create and drop functions

SYNOPSIS
========

     use DBIx::DataSource qw( create_database drop_database );

     create_database( $data_source, $username, $password )
       or warn $DBIx::DataSource::errstr;

     drop_database( $data_source, $username, $password )
       or warn $DBIx::DataSource::errstr;

DESCRIPTION
===========

   This module implements create_database and drop_database functions for
databases.  It aims to provide a common interface to database creation and
deletion regardless of the actual database being used.

   Currently supported databases are MySQL and PostgreSQL.  Assistance
adding support for other databases is welcomed and relatively simple - see
DBIx/DataSource/Driver.

FUNCTIONS
=========

create_database DATA_SOURCE USERNAME PASSWORD
     Create the database specified by the given DBI data source.

drop_database DATA_SOURCE
     Drop the database specified by the given DBI data source.

AUTHOR
======

   Ivan Kohler <ivan-dbix-datasource@420.am>

COPYRIGHT
=========

   Copyright (c) 2000 Ivan Kohler Copyright (c) 2000 Mail Abuse Prevention
System LLC All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

BUGS
====

   If DBI data sources were objects, these functions would be methods.

SEE ALSO
========

   See DBIx/DataSource/Driver,
DBIx/DataSource/mysql, DBIx/DataSource/Pg,
`DBI' in this node

Driver Writer's Guide and base class
************************************

NAME
====

   DBIx::DataSource::Driver - Driver Writer's Guide and base class

SYNOPSIS
========

     perldoc DBIx::DataSource::Driver;

     or

     package DBIx::DataSource::FooBase;
     use DBIx::DataSource::Driver;
     @ISA = qw( DBIx::DataSource::Driver );

DESCRIPTION
===========

   To implement a driver for your database:

   1) If you can create a database with an SQL command through DBI/DBD,
simply    provide a parse_dsn class method which returns a list consisting
of the    *actual* data source to use in DBI->connect and the SQL.

     package DBIx::DataSource::NewDatabase;
     use DBIx::DataSource::Driver;
     @ISA = qw( DBIx::DataSource::Driver );

     sub parse_dsn {
       my( $class, $action, $dsn ) = @_;

     # $action is `create' or `drop'
     # for example, if you parse parse $dsn for $database,
     # $sql = "$action $database";

     # you can die on errors - it'll be caught

     ( $new_dsn, $sql );
            }

   2) Otherwise, you'll need to write create_database and drop_database
class methods.

     package DBIx::DataSource::NewDatabase;

     sub create_database {
       my( $class, $dsn, $user, $pass ) = @_;

     # for success, return true
     # for failure, die (it'll be caught)
            }

     sub drop_database {
       my( $class, $dsn, $user, $pass ) = @_;

     # for success, return true
     # for failure, die (it'll be caught)
            }

AUTHOR
======

   Ivan Kohler <ivan-dbix-datasource@420.am>

COPYRIGHT
=========

   Copyright (c) 2000 Ivan Kohler Copyright (c) 2000 Mail Abuse Prevention
System LLC All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

BUGS
====

SEE ALSO
========

   See DBIx/DataSource, DBIx/DataSource/mysql,
see DBIx/DataSource/Pg,
`DBI' in this node

PostgreSQL driver for DBIx::DataSource
**************************************

NAME
====

   DBIx::DataSource::Pg - PostgreSQL driver for DBIx::DataSource

SYNOPSIS
========

     use DBIx::DataSource;

     use DBIx::DataSource qw( create_database drop_database );

     create_database( "dbi:Pg:dbname=$dbname", $username, $password )
       or warn $DBIx::DataSource::errstr;

     create_database( "dbi:Pg:dbname=$dbname;host=$host;port=$port",
                      $username, $password )
       or warn $DBIx::DataSource::errstr;

     drop_database( "dbi:Pg:dbname=$dbname", $username, $password )
       or warn $DBIx::DataSource::errstr;

     drop_database( "dbi:Pg:dbname=$dbname;host=$host;port=$port",
                     $username, $password )
       or warn $DBIx::DataSource::errstr;

DESCRIPTION
===========

   This is the PostgresSQL driver for DBIx::DataSource.

AUTHOR
======

   Ivan Kohler <ivan-dbix-datasource@420.am>

COPYRIGHT
=========

   Copyright (c) 2000 Ivan Kohler Copyright (c) 2000 Mail Abuse Prevention
System LLC All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

BUGS
====

SEE ALSO
========

   See DBIx/DataSource/Driver,
DBIx/DataSource, `DBD::Pg' in this node, `DBI' in this
node

MySQL driver for DBIx::DataSource
*********************************

NAME
====

   DBIx::DataSource::mysql - MySQL driver for DBIx::DataSource

SYNOPSIS
========

     use DBIx::DataSource;

     use DBIx::DataSource qw( create_database drop_database );

     create_database( "dbi:mysql:$database", $username, $password )
       or warn $DBIx::DataSource::errstr;

     create_database( "dbi:mysql:database=$database;host=$hostname;port=$port",
                      $username, $password )
       or warn $DBIx::DataSource::errstr;

     drop_database( "dbi:mysql:$database", $username, $password )
       or warn $DBIx::DataSource::errstr;

     drop_database( "dbi:mysql:database=$database;host=$hostname;port=$port",
                     $username, $password )
       or warn $DBIx::DataSource::errstr;

DESCRIPTION
===========

   This is the MySQL driver for DBIx::DataSource.

AUTHOR
======

   Ivan Kohler <ivan-dbix-datasource@420.am>

COPYRIGHT
=========

   Copyright (c) 2000 Ivan Kohler Copyright (c) 2000 Mail Abuse Prevention
System LLC All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

BUGS
====

SEE ALSO
========

   See DBIx/DataSource/Driver,
DBIx/DataSource, DBD/mysql, `DBI' in
this node

Module to perform report generation via query DBI
*************************************************

NAME
====

   Formatter - Module to perform report generation via query DBI

SYNOPSIS
========

     use Formatter;

     format FMT_HEADER=
     **************************************************
     *             FIRST PAGE OF REPORT               *
     **************************************************
     .

     format FMT_TTITLE=
     **************************************************
     * SOC : @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< *
             $DEAZIEND
     **************************************************
     PROG    CDAZIEND CDDIPEND
     ----    -------- --------
     .

     format FMT_BODY=
     @<<<    @<<<     @<<<<<
     $FMT->line,     $CDAZIEND,$CDDIPEND
     .

     format FMT_CD1LVSTR=
     TOT]--> @<<<<<<< @<<<<<<< @<<<<<<<
        111,     111,     111
     .
     format FMT_BTITLE=
     --------------------------------------------------
     @</@</@<                                    P.@<<<
     $DAY,$MONTH,$YEAR,                      $FMT->page
     .

     $BREAKS[0]="CDAZIEND";
     $BREAKS[1]="CDDIPEND";

     $FMT=new Formatter(
     'DBI_DRIVER'           => 'Oracle',
     'DBI_DATABASE'         => 'database',
     'DBI_USERNAME'         => 'dbusername',
     'DBI_PASSWORD'         => 'dbpassword',
     'DBD_QUERY'            => 'SELECT * FROM ANAGRA WHERE CLPERRIF=199901 ORDER BY CDAZIEND',
     'BREAKS'               => \@BREAKS,
     'BREAKS_SKIP_PAGE'     =>  {
         CD1LVSTR => 1,
         CDCCOSTO => 0
     },
     'FORMAT_PAGESIZE'      => 40,
     'FORMAT_LINESIZE'      => 50,
     'FORMAT_FORMFEED'      => "\f",
     'FORMAT_HEADER'        => *FMT_HEADER,
     'FORMAT_TTITLE'        => *FMT_TTITLE,
     'FORMAT_BTITLE'        => *FMT_BTITLE,
     'FORMAT_BTITLE_HEIGHT' => 2,
     'FORMAT_BODY'          => *FMT_BODY,
     'FORMAT_BREAKS'        =>  {
         CD1LVSTR => *FMT_CD1LVSTR,
     },
     'EVENT_PREHEADER'      => \&PREHEADER,
     'EVENT_POSTHEADER'     => \&POSTHEADER,
     'EVENT_PRETTITLE'      => \&PRETTITLE,
     'EVENT_POSTTTITLE'     => \&POSTTTITLE,
     'EVENT_PREBODY'        => \&PREBODY,
     'EVENT_POSTBODY'       => \&POSTBODY,
     'EVENT_PREBTITLE'      => \&PREBTITLE,
     'EVENT_POSTBTITLE'     => \&POSTBTITLE,
     'EVENT_ALLBREAKS'      => \&BREAKALL,
     'EVENT_BREAKS'         =>  {
         CDAZIEND => \&CDAZIEND,
         CDDIPEND => \&CDDIPEND
     }
         );

     $FMT->generate();

     sub PREHEADER    {do something before header print out}
     sub POSTHEADER   {do something after header print out}
     sub PRETTITLE    {do something before top title print out}
     sub POSTTTITLE   {do something after top title print out}
     sub PREBTITLE    {do something before bottom title print out}
     sub POSTBTITLE   {do something after bottom title print out}
     sub PREBODY      {do something before body print out}
     sub POSTBODY     {do something after body print out}

     $FMT->ofmt("Print out a line during report generation",">");

DESCRIPTION
===========

     Formatter module perform report generation based on DBI query.

DEFINITION
==========

Function new
------------

   The <new> function create the Formatter object and configure it for all
parameters required for report generation.  One by one parameter
definition:

     * DBI_DRIVER        => Specify wath driver you would use
                            for connect to your database.
                            (See DBD drivers for specific)
     * DBI_DATABASE      => Specify database name (or instance).
                            In union of last parameter it create
                            connection string : dbi:DBI_DRIVER:DBI_DATABASE
     * DBI_USERNAME      => Specify database username
     * DBI_PASSWORD      => Specify database DBI_USERNAME password
     * DBD_QUERY         => Point to a string where Sql Query are located
     * BREAKS            => Point to an array containing fields that cause a
                            break in the report
     * BREAKS_SKIP_PAGE  => Point to an hash that specify if a new page are
                            performed when the break FORMAT ar printed
     * FORMAT_PAGESIZE   => Specify page height in character
     * FORMAT_LINESIZE   => Specify line width in character (only for outf use)
     * FORMAT_FORMFEED   => Specify formfeed sequence when a formfeed or newpage
                            are requested
     * FORMAT_HEADER     => Point to filehandle of the header definition for the
                            report
     * FORMAT_TTITLE     => Point to filehandle of the top title definition for
                            the report
     * FORMAT_BODY       => Point to filehandle of the body definition for the
                            report
     * FORMAT_BTITLE     => Point to filehandle of the bottom title definition for
                            the report
     * FORMAT_BTITLE_HEIGHT => Height in lines of BTITLE
     * FORMAT_BREAKS     => Point to an hash containig break fields related to its
                            format filehandle definition
     * EVENT_PREHEDER    => Point to the subroutine that is called before header
                            generation
     * EVENT_POSTHEDER   => Point to the subroutine that is called after header
                            generation
     * EVENT_PRETTITLE   => Point to the subroutine that is called before top title
                            generation
     * EVENT_POSTTTITLE  => Point to the subroutine that is called after top title
                            generation
     * EVENT_PREBODY     => Point to the subroutine that is called before body
                            generation
     * EVENT_POSTBODY    => Point to the subroutine that is called after body
                            generation
     * EVENT_PREBTITLE   => Point to the subroutine that is called before bottom title
                            generation
     * EVENT_POSTBTITLE  => Point to the subroutine that is called after bottom title
                            generation
     * EVENT_BREAKS      => Point to structure that contains break fields related to
                            subroutine to execute when the break is berformed

DBI_DRIVER
----------

   DBI_DRIVER specify driver to use for connection within Database via
DBI::DBD module.

   Ex.

     * Oracle  (Oracle database)
     * CSV     (Comma separated database)
     * Pg      (PostgreSQL database)
     ... ecc.

   For specific look at DBD::<Driver>

DBI_DATABASE
------------

   The clause DBI_DATABASE can change from db to db , look at DBD::Driver
for your specific.  Example parameter are:

     * ORACLE_SID            for Oracle database
     * f_dir=/csv/data       for CSV file specify directory location of text-file-table
     * dbname=your db name   for PostgreSQL database
     * DSN                   for ADO db connection

DBI_USERNAME DBI_PASSWORD
-------------------------

   Specify in order username and password of the user granted to use
database

DBD_QUERY
---------

   Here you can pass your query (SQL) , that is fetched for report
generation.  Example to pass query are:

     * Example 1 (Direct via parameters)
             $FMT=new Formatter(
             'DBI_DRIVER'           => 'Oracle',
             'DBI_DATABASE'         => 'database',
             'DBI_USERNAME'         => 'dbusername',
             'DBI_PASSWORD'         => 'dbpassword',
             'DBD_QUERY'            => 'SELECT * FROM ANAGRA WHERE CLPERRIF=199901 ORDER BY CDAZIEND',
              ...

     * Example 2 (Via variable)
             $query = qq {
                 SELECT
                     *
                 FROM
                     ANAGRA
                 WHERE
                         CLPERRIF=199901
                     AND
                         CDAZIEND=345
                 ORDER BY
                     CDAZIEND
             };

     $FMT=new Formatter(
     'DBI_DRIVER'           => 'Oracle',
     'DBI_DATABASE'         => 'database',
     'DBI_USERNAME'         => 'dbusername',
     'DBI_PASSWORD'         => 'dbpassword',
     'DBD_QUERY'            => $query,
     ...

BREAKS
------

   Specify an array containing fields that cause a break in the report.
When a breaks is performed 2 step are executed, first an EVENT_BREAKS is
called if defined , second a FORMAT_BREAKS is printed out if defined.  For
convenience if you would like to generate a new format when a field change
you can use first statement because is called after FORMAT_BREAKS (and if
they are subtotal are printed before), using the putformat function in the
event routine, for example:

     format FMT_DEPARTEMENT=
     TOTALS FOR DEPARTEMENT ARE ]--> @<<<<<<< @<<<<<<< @<<<<<<<
                                     111,     111,     111
     .

     format FMT_SUBDEPARTEMENT
     *********************************
     * @|||||||||||||||||||||||||||| *
       $SUBDEPARTEMENT
     *********************************
     .

     $BREAKS[0]="DEPARTEMENT";
     $BREAKS[1]="SUBDEPARTEMENT";

     $FMT=Formatter->new (
             ...
             'BREAKS'               => \@BREAKS,
             'BREAKS_SKIP_PAGE'     =>  {
             DEPARTEMENT => 1,
             SUBDEPARTEMENT => 0
             },
             'FORMAT_BREAKS'        =>  {
             DEPARTEMENT => *FMT_DEPARTEMENT
             },
             'EVENT_BREAKS'         =>  {
             SUBDEPARTEMENT => \&MySubDepartement
             },
             ...
     );

   sub MySubDepartement {$FMT->putformat(*FMT_SUBDEPARTEMENT)};

   In this way a possible output is :
******************************************************* *
REPORT BY SUBDEPARTMENT              *
*******************************************************
*********************************    *           CHEMICALS           *
*********************************    10    20    40    10    20    40
10    20    40    *********************************    *
PHARMACIA           *    *********************************    10    20
40    10    20    40    10    20    40

   TOTALS FOR DEPARTEMENT ARE ]-> 111 111 111

BREAKS_SKIP_PAGE
----------------

   This parameter specify only if a new page is called after a break
FORMAT is writed.

FORMAT_PAGESIZE
---------------

   (Optional-Deafult=60)

   Specify how many lines are printed for each piece of paper.

FORMAT_LINESIZE
---------------

   (Optional-Default=130)

   Specify how many character are counted by an outf function to perform
alignement of text.

FORMAT_FORMFEED
---------------

   (Optional-Deafult=\f)

   Specify the form feed sequence that are called whem a newpage or a
formfeed function are called ( and alse a new page of report is required)
Default value are CTRL-L (\f)

FORMAT_HEADER
-------------

   (Optional)

   This parameter point to the format fileheader for HEADER page.
Definition of format specific can be found in Perl documentation.  Header
page is printed only one time at beginning of the report and normally
include general specification or purpose of report.

   Example:

     format MY_HEADER=
     ******************************************
     * DATE    : @</@</@<<<                   *
                 $dd,$mm,$yyyy
     * PURPOSE : Statistique about user login *
     ******************************************
     .

FORMAT_TTITLE
-------------

   (Optional)

   Identical to HEADER definition.  TTITLE is printed on every change of
page in the top of the report page

FORMAT_BODY
-----------

   (Optional)

   Identical to HEADER definition.  BODY is printed on every change of
value in fetch of query statament, values of query are passed and
traslated to real variable in the main caller program.

   Example :     if query is SELECT NAME,SURNAME,ADDRESS FROM ADDRESSBOOK
  in yours format values $NAME,$SURNAME,$ADDRESS are created and updated
  on every fetch.

     format MYBODY=
     @<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
     $NAME,             $SURNAME            $ADDRESS
     .

FORMAT_BTITLE
-------------

   (Optional)

   Identical to HEADER definition.  BTITLE is printed on every change of
page in the bottom of the report page

FORMAT_BTITLE_HEIGHT
--------------------

   (Option if FORMAT_BTITLE not specified)

   This parameter specify how many lines are printed by the FORMAT_BTITLE
definition.  I have put this parameter beacuse i don't know how to inform
automatically my package in what lines is used by a format definition.  If
anyone know how to make it possible please contact me.

FORMAT_BREAKS
-------------

   This parameter point to a structure where are located by fields format
filehandle definitions.  For use see the BREAKS specifics.

EVENT_PRE...
------------

   All EVENT_PRE... (EVENT_PREHEADER,EVENT_PRETTITLE ...) parameters
points to a routine defined by the user that is called before the event
handle is performed.  For example if you would like to change a value in
the top title before is print out you need to create a sub for example
named MyBeforeTopTitle in which you change a value , and then you pass
this reference to the EVENT_PRETTITLE parameter :

     'EVENT_PRETTITLE' => \&MyBeforeTopTitle

   Remember that all values created by the fetch statement are already
updated when all events are generated

EVENT_POST...
-------------

   Is identical to the last but is applied after the event handle occurs.

EVENT_BREAKS
------------

   This parameter point to a structure that specify by fields events that
can be generated when a break is performed after a FORMAT_BREAKS is
printed out.

FUNCTIONS
=========

Function generate
-----------------

   This function call all parameters and build the report.

Function ofmt
-------------

   This function place a text in the report over formatting definition ,
is only for special case in which is impossible to place text on format
definition (if you found when please contact me).
Formatter->ofmt ("Text to print out",position flag,position character); *
Position flag The position flag specify where text are printed , possible
values are:     <   Text are aligned to left of the line     >   Text are
aligned to right of the line     |   Text are aligned in the middle of the
line     C   Enable Position

   * Position character The position character specify the position in the
line where the text are printed

Function page
-------------

   The page function return number of page in this moment

Function line
-------------

   The line function return the line position in the moment

Function newpage
----------------

   The new page function send a complete new page to the report this is
the next sequence :

     * Print the bottom title in the current page
     * Send the form feed sequence
     * Print the top title in the new page

Function formfeed
-----------------

   The formfeed function send only the form feed sequence to the report
and not perform the title generation.

AUTHOR
======

     Vecchio Fabrizio <jacote@tiscalinet.it>

SEE ALSO
========

   `DBI' in this node

Indexing documents with MySQL as storage
****************************************

NAME
====

   DBIx::FullTextSearch - Indexing documents with MySQL as storage

SYNOPSIS
========

     use DBIx::FullTextSearch;
     use DBI;
     # connect to database (regular DBI)
     my $dbh = DBI->connect('dbi:mysql:database', 'user', 'passwd');

     # create a new stoplist
     my $sl = DBIx::FullTextSearch::StopList->create_default($dbh, 'sl_en', 'English');

     # create a new index with default english stoplist and english stemmer
     my $fts = DBIx::FullTextSearch->create($dbh, 'fts_web_1',
     		frontend => 'string', backend => 'blob',
     		stoplist => 'sl_en', stemmer => 'en-us');
     # or open existing one
     # my $fts = DBIx::FullTextSearch->open($dbh, 'fts_web_1');

     # index documents
     $fts->index_document('krtek', 'krtek leze pod zemi');
     $fts->index_document('jezek', 'Jezek ma ostre bodliny.');

     # search for matches
     my @docs = $fts->contains('foo');
     my @docs = $fts->econtains('+foo', '-Bar');
     my @docs = $fts->search('+foo -Bar');

DESCRIPTION
===========

   DBIx::FullTextSearch is a pure man's solution for indexing contents of
documents.  It uses the MySQL database to store the information about
words and documents and provides Perl interface for indexing new documents,
making changes and searching for matches.  For DBIx::FullTextSearch, a
document is nearly anything - Perl scalar, file, Web document, database
field.

   The basic style of interface is shown above. What you need is a MySQL
database and a DBI with DBD::mysql. Then you create a DBIx::FullTextSearch
index - a set of tables that maintain all necessary information. Once
created it can be accessed many times, either for updating the index
(adding documents) or searching.

   DBIx::FullTextSearch uses one basic table to store parameters of the
index. Second table is used to store the actual information about
documents and words, and depending on the type of the index (specified
during index creation) there may be more tables to store additional
information (like conversion from external string names (eg. URL's) to
internal numeric form). For a user, these internal thingies and internal
behaviour of the index are not important. The important part is the API,
the methods to index document and ask questions about words in documents.
However, certain understanding of how it all works may be usefull when you
are deciding if this module is for you and what type of index will best
suit your needs.

Frontends
---------

   From the user, application point of view, the DBIx::FullTextSearch
index stores documents that are named in a certain way, allows adding new
documents, and provides methods to ask: "give me list of names of
documents that contain this list of words". The DBIx::FullTextSearch index
doesn't store the documents itself. Instead, it stores information about
words in the documents in such a structured way that it makes easy and
fast to look up what documents contain certain words and return names of
the documents.

   DBIx::FullTextSearch provides a couple of predefined frontend classes
that specify various types of documents (and the way they relate to their
names).

default
     By default, user specifies the integer number of the document and the
     content (body) of the document. The code would for example read

          $fts->index_document(53, 'zastavujeme vyplaty vkladu');

     and DBIx::FullTextSearch will remember that the document 53 contains
     three words.  When looking for all documents containing word (string)
     vklad, a call

          my @docs = $fts->contains('vklad%');

     would return numbers of all documents containing words starting with
     'vklad', 53 among them.

     So here it's user's responsibility to maintain a relation between the
     document numbers and their content, to know that a document 53 is
     about vklady. Perhaps the documents are already stored somewhere and
     have inique numeric id.

string
     Frontend string allows the user to specify the names of the documents
     as strings, instead of numbers. Still the user has to specify both the
     name of the document and the content:

          $fts->index_document('foobar',
          		'the quick brown fox jumped over lazy dog!');

     After that,

          $fts->contains('dog')

     will return 'foobar' as one of the names of documents with word 'dog'
     in it.

file
     To index files, use the frontend file. Here the content of the
     document is clearly the content of the file specified by the
     filename, so in a call to index_document, only the name is needed -
     the content of the file is read by the DBIx::FullTextSearch
     transparently:

          $fts->index_document('/usr/doc/FAQ/Linux-FAQ');
          my @files = $fts->contains('penguin');

url
     Web document can be indexed by the frontend url. DBIx::FullTextSearch
     uses LWP, to get the document and then parses it normally:

          $fts->index_document('http://www.perl.com/');

table
     You can have a DBIx::FullTextSearch index that indexes char or blob
     fields in MySQL table. Since MySQL doesn't support triggers, you have
     to call the index_document method of DBIx::FullTextSearch any time
     something changes in the table. So the sequence probably will be

          $dbh->do('insert into the_table (id, data, other_fields)
          	values (?, ?, ?)', {}, $name, $data, $date_or_something);
          $fts->index_document($name);

     When calling contains, the id (name) of the record will be returned.
     If the id in the_table is numeric, it's directly used as the internal
     numeric id, otherwise a string's way of converting the id to numeric
     form is used.

     When creating this index, you'll have to pass it three additionial
     options, table_name, column_name, and column_id_name.  You may use
     the optional column_process option to pre-process data in the
     specified columns.

   The structure of DBIx::FullTextSearch is very flexible and adding new
frontend (what will be indexed) is very easy.

Backends
--------

   While frontend specifies what is indexed and how the user sees the
collection of documents, backend is about low level database way of
actually storing the information in the tables. Three types are available:

blob
     For each word, a blob holding list of all documents containing that
     word is stored in the table, with the count (number of occurencies)
     associated with each document number. That makes it for very compact
     storage. Since the document names (for example URL) are internally
     converted to numbers, storing and fetching the data is fast. However,
     updating the information is very slow, since information concerning
     one document is spread across all table, without any direct database
     access.  Updating a document (or merely reindexing it) requires
     update of all blobs, which is slow.

     The list of documents is stored sorted by document name so that
     fetching an information about a document for one word is relatively
     easy, still a need to update (or at least scan) all records in the
     table makes this storage unsuitable for collections of documents that
     often change.

column
     The column backend stores a word/document pair in database fields,
     indexing both, thus allowing both fast retrieval and updates - it's
     easy to delete all records describing one document and insert new
     ones.  However, the database indexes that have to be maintained are
     large.

     Both blob and column backends only store a count - number of
     occurencies of the word in the document (and even this can be switched
     off, yielding just a yes/no information about the word's presence).
     This allows questions like

          all documents containing words 'voda' or 'Mattoni'
          	but not a word 'kyselka'

     but you cannot ask whether a document contains a phrase 'kyselka
     Mattoni' because such information is not maintained by these types of
     backends.

phrase
     To allow phrase matching, a phrase backend is available. For each word
     and document number it stores a blob of lists of positions of the word
     in the document. A query

          $fts->contains('kyselk% Mattoni');

     then only returns those documents (document names/numbers) where word
     kyselka (or kyselky, or so) is just before word Mattoni.

Mixing frontends and backends
-----------------------------

   Any frontend can be used with any backend in one DBIx::FullTextSearch
index. You can index Web documents with url frontend and phrase backend to
be able to find phrases in the documents. And you can use the default,
number based document scheme with blob backend to use the disk space as
efficiently as possible - this is usefull for example for mailing-list
archives, where we need to index huge number of documents that do not
change at all.

   Finding optimal combination is very important and may require some
analysis of the document collection and manipulation, as well as the speed
and storage requirements. Benchmarking on actual target platform is very
useful during the design phase.

METHODS
=======

   The following methods are available on the user side as
DBIx::FullTextSearch API.

create
          my $fts = DBIx::FullTextSearch->create($dbh, $index_name, %opts);

     The class method create creates index of given name (the name of the
     index is the name of its basic parameter table) and all necessary
     tables, returns an object - newly created index. The options that may
     be specified after the index name define the frontend and backend
     types, storage parameters (how many bits for what values), etc. See
     below for list of create options and discussion of their use.

open
          my $fts = DBIx::FullTextSearch->open($dbh, $index_name);

     Opens and returns object, accessing specifies DBIx::FullTextSearch
     index. Since all the index parameters and information are stored in
     the `$index_name' table (including names of all other needed tables),
     the database handler and the name of the parameter table are the only
     needed arguments.

index_document
          $fts->index_document(45, 'Sleva pri nakupu stribra.');
          $fts->index_document('http://www.mozilla.org/');
          $fts->index_document('http://www.mozilla.org/','This is the mozilla web site');

     For the default and string frontends, two arguments are expected - the
     name (number or string) of the document and its content. For file,
     url, and table frontends the content is optional.  Any content that
     you pass will be appended to the content from the file, URL, or
     database table.

delete_document
          $fts->delete_document('http://www.mozilla.org/');

     Removes information about document from the index. Note that for blob
     backend this is very time consuming process.

contains
          my @docs = $fts->contains('sleva', 'strib%');

     Returns list of names (numbers or strings, depending on the frontend)
     of documents that contain some of specified words.

econtains
          my @docs = $fts->contains('foo', '+bar%', '-koo');

     Econtains stands for extended contains and allows words to be prefixed
     by plus or minus signs to specify that the word must or mustn't be
     present in the document for it to match.

contains_hashref, econtains_hashref
     Similar to contains and econtains, only instead of list of document
     names, there methods return a hash reference to a hash where keys are
     the document names and values are the number of occurencies of the
     words.

search
          my @docs = $fts->search(qq{+"this is a phrase" -koo +bar foo});

     This is a wrapper to econtains which takes a user input string and
     parses it into can-include, must-include, and must-not-include words
     and phrases.

drop
     Removes all tables associated with the index, including the base
     parameter table. Effectivelly destroying the index form the database.

          $fts->drop;

empty
     Emptys the index so you can reindex the data.

          $fts->empty;

INDEX OPTIONS
=============

   Here we list the options that may be passed to
DBIx::FullTextSearch->create call.  These allow to specify the style and
storage parameters in great detail.

backend
     The backend type, default blob, possible values blob, column and
     phrase (see above for explanation).

frontend
     The frontend type. The default frontend requires the user to specify
     numeric id of the document together with the content of the document,
     other possible values are string, file and url (see above for more
     info).

word_length
     Maximum length of words that may be indexed, default 30.

data_table
     Name of the table where the actual data about word/document relation
     is stored. By default, the name of the index (of the base table) with
     _data suffix is used.

name_length
     Any frontend that uses strings as names of documents needs to maintain
     a conversion table from these names to internal integer ids. This
     value specifies maximum length of these string names (URLs, file
     names, ...).

blob_direct_fetch
     Only for blob backend. When looking for information about specific
     document in the list stored in the blob, the blob backend uses
     division of interval to find the correct place in the blob. When the
     interval gets equal or shorter that this value, all values are
     fetched from the database and the final search is done in Perl code
     sequentially.

word_id_bits
     With column or `phase' backends, DBIx::FullTextSearch maintains a
     numeric id for each word to optimize the space requirements. The
     word_id_bits parameter specifies the number of bits to reserve for
     this conversion and thus effectively limits number of distinct words
     that may be indexed. The default is 16 bits and possible values are
     8, 16, 24 or 32 bits.

word_id_table
     Name of the table that holds conversion from words to their numeric id
     (for column and phrase backends). By default is the name of the index
     with _words suffix.

doc_id_bits
     A number of bits to hold a numeric id of the document (that is either
     provided by the user (with default frontend) or generated by the
     module to accomplish the conversion from the string name of the
     document). This value limits the maximum number of documents to hold.
     The default is 16 bits and possible values are 8, 16 and 32 bits for
     blob backend and 8, 16, 24 and 32 bits for column and phrase backends.

doc_id_table
     Name of the table that holds conversion from string names of documents
     to their numeric id, by default the name of the index with _docid
     suffix.

count_bits
     Number of bits reserved for storing number of occurencies of each word
     in the document. The default is 8 and possible values are the same as
     with doc_id_bits.

position_bits
     With `phrase backend', DBIx::FullTextSearch stores positions of each
     word of the documents. This value specifies how much space should be
     reserved for this purpose. The default is 32 bits and possible values
     are 8, 16 or 32 bits. This value limits the maximum number of words
     of each document that can be stored.

index_splitter
     DBIx::FullTextSearch allows the user to provide any Perl code that
     will be used to split the content of the document to words when
     indexing documents.  The code will be evalled inside of the
     DBIx::FullTextSearch code. The default is

          /(\w{2,$word_length})/g

     and shows that the input is stored in the variable $data and the code
     may access any other variable available in the perl_and_index_data_*
     methods (see source), especially `$word_length' to get the maximum
     length of words and `$backend' to get the backend object.

     The default value also shows that by default, the minimum length of
     words indexed is 2.

search_splitter
     This is similar to the index_splitter method, except that it is used
     in the `contains_hashref' method when searching for documents instead
     of when indexing documents.  The default is

          /([a-zA-Z_0-9]{2,$word_length}\*?)/g

     Which, unlike the default index_splitter, allows for the wild card
     character (*).

filter
     The output words of splitter (and also any parameter of (e)contains*
     methods) are send to filter that may do further processing. Filter is
     again a Perl code, the default is

          map { lc $_ }

     showing that the filter operates on input list and by default does
     conversion to lowercase (yielding case insensitive index).

init_env
     Because user defined splitter or filter may depend on other things
     that it is reasonable to set before the actual procession of words,
     you can use yet another Perl hook to set things up. The default is

          use locale

stoplist
     This is the name of a DBIx/FullTextSearch/StopList,
     object that is used for stop words.

stemmer
     If this option is set, then word stemming will be enabled in the
     indexing and searching.

     The value is the name of a Lingua/Stem, recognized
     locale.  Currently, 'en', 'en-us' and 'en-uk' are the only recognized
     locales.  All locale identifiers are converted to lowercase.

table_name
     For table frontend; this is the name of the table that will be
     indexed.

column_name
     For table frontend; this is a reference to an array of columns in the
     table_name that contains the documents - data to be indexed. It can
     also have a form table.column that will be used if the table_name
     option is not specified.

column_id_name
     For table frontend; this is the name of the field in table_name that
     holds names (ids) of the records. If not specified, a field that has
     primary key on it is used. If this field is numeric, it's values are
     directly used as identifiers, otherwise a conversion to numeric values
     is made.

ERROR HANDLING
==============

   The create and open methods return the DBIx::FullTextSearch object on
success, upon failure they return undef and set error message in
`$DBIx::FullTextSearch::errstr' variable.

   All other methods return reasonable (documented above) value on success,
failure is signalized by unreasonable (typically undef or null) return
value; the error message may then be retrieved by `$fts->errstr' method
call.

VERSION
=======

   This documentation describes DBIx::FullTextSearch module version 0.55.

BUGS
====

   Error handling needs more polishing.

   We do not check if the stored values are larger that specified by the
*_bits parameters.

   No CGI administration tool at the moment.

   No scoring algorithm implemented.

DEVELOPMENT
===========

   These modules are under active development.  Currently a PostgreSQL
version is being developed.  If you would like to contribute, please
e-mail tj@anidea.com

   There are two mailing lists for this module, one for users, and another
for developers.  To subscribe, visit
http://sourceforge.net/mail/?group_id=8645

AUTHOR
======

   (Original) Jan Pazdziora, adelton@fi.muni.cz,
http://www.fi.muni.cz/~adelton/ at Faculty of Informatics, Masaryk
University in Brno, Czech Republic

   (Current Maintainer) Thomas J. Mather, tj@anidea.com,
http://www.thoughtstore.com/tjmather/ New York, NY, USA

CREDITS
=======

   Fixes, Bug Reports have been generously provided by:

     Ade Olonoh
     Andrew Turner
     Tarik Alkasab

   Thanks!

COPYRIGHT
=========

   All rights reserved. This package is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

SEE ALSO
========

   `DBI' in this node, ftsadmin, `DBIx::FullTextSearch::StopWord' in this
node

OTHER PRODUCTS and why I've written this module
===============================================

   I'm aware of `DBIx::TextIndex' module and about UdmSearch utility, and
about htdig and glimpse on the non-database side of the world.

   To me, using a database gives reasonable maintenance benefits. With
products that use their own files to store the information (even if the
storage algorithms are efficient and well thought of), you always struggle
with permissions on files and directories for various users, with files
that somebody accidently deleted or mungled, and making the index
available remotely is not trivial.

   That's why I've wanted a module that will use a database as a storage
backend. With MySQL, you get remote access and access control for free,
and on many web servers MySQL is part of the standard equipment. So using
it for text indexes seemed natural.

   However, existing DBIx/TextIndex, and UdmSearch
are too narrow-aimed to me. The first only supports indexing of data that
is stored in the database, but you may not always want or need to store
the documents in the database as well. The UdmSearch on the other hand is
only for web documents, making it unsuitable for indexing mailing-list
archives or local data.

   I believe that DBIx::FullTextSearch is reasonably flexible and still
very efficient. It doesn't enforce its own idea of what is good for you -
the number of options is big and you can always extend the module with
your own backend of frontend if you feel that those provided are not
sufficient. Or you can extend existing by adding one or two parameters
that will add new features. Of course, patches are always welcome.
DBIx::FullTextSearch is a tool that can be deployed in many projects. It's
not a complete environment since different people have different needs. On
the other hand, the methods that it provides make it easy to build a
complete solution on top of this in very short course of time.

   I was primarily inspired by the ConText cartrige of Oracle server. Since
MySQL doesn't support triggers, it showed up that Perl interface will be
needed. Of course, porting this module to (for example) PostgreSQL should
be easy, so different name is probably needed. On the other hand, the code
is sometimes very MySQL specific to make the module work efficiently, so I
didn't want a name that would suggest that it's a generic tool that will
work with any SQL database.

Stopwords for DBIx::FullTextSearch
**********************************

NAME
====

   DBIx::FullTextSearch::StopList - Stopwords for DBIx::FullTextSearch

SYNOPSIS
========

     use DBIx::FullTextSearch::StopList;
     # connect to database (regular DBI)
     my $dbh = DBI->connect('dbi:mysql:database', 'user', 'passwd');

     # create a new empty stop word list
     my $sl1 = DBIx::FullTextSearch::StopList->create_empty($dbh, 'sl_web_1');

     # or create a new one with default stop words
     my $sl2 = DBIx::FullTextSearch::StopList->create_default($dbh, 'sl_web_2', 'english');

     # or open an existing one
     my $sl3 = DBIx::FullTextSearch::StopList->open($dbh, 'sl_web_3');

     # add stop words
     $sl1->add_stop_word(['a','in','on','the']);

     # remove stop words
     $sl2->remove_stop_word(['be','because','been','but','by']);

     # check if word is in stoplist
     $bool = $sl1->is_stop_word('in');

     # empty stop words
     $sl3->empty;

     # drop stop word table
     $sl2->drop;

DESCRIPTION
===========

   DBIx::FullTextSearch::StopList provides stop lists that can be used
-See DBIx/FullTextSearch.  StopList objects can be
reused accross several FullTextSearch objects.

METHODS
=======

CONSTRUCTERS
------------

create_empty
          my $sl = DBIx::FullTextSearch::StopList->create_empty($dbh, $sl_name);

     This class method creates a new StopList object.

create_default
          my $sl = DBIx::FullTextSearch::StopList->create_default($dbh, $sl_name, $language);

     This class method creates a new StopList object, with default words
     loaded in for the given language.  Supported languages include
     Danish, Dutch, English, Finnish, French, German, Italian, Portuguese,
     Spanish, and Swedish.

open
          my $sl = DBIx::FullTextSearch::StopList->open($dbh, $sl_name);

     Opens and returns StopList object

OBJECT METHODS
--------------

add_stop_word
          $sl->add_stop_word(\@stop_words);

     Adds stop words to StopList object.  Expects array reference as
     argument.

remove_stop_word
          $sl->remove_stop_word(\@stop_words);

     Remove stop words from StopList object.

is_stop_word
          $bool = $sl->is_stop_word($stop_word);

     Returns true iff stop_word is StopList object

empty
          $sl->empty;

     Removes all stop words in StopList object.

drop
          $sl->drop;

     Removes table associated with the StopList object.

AUTHOR
======

   Thomas J. Mather, tjmather@alumni.princeton.edu,
http://www.thoughtstore.com/tjmather/perl/ New York, NY, USA

COPYRIGHT
=========

   All rights reserved. This package is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

SEE ALSO
========

   See DBIx/FullTextSearch,

For handling DBI relation databases and web interfaces
******************************************************

NAME
====

     DBIx::HTMLView - For handling DBI relation databases and web interfaces

SYNOPSIS
========

   use DBIx::HTMLView; my $dbi=DB("DBI:mSQL:HTMLViewTester:localhost", "",
"",            Table ('Test', Id('id'), Str('testf')),
Table('Test2', Id('id'), Str('str'), Int('nr'))           );

DESCRIPTION
===========

   HTMLView is a set of modules to handle relational SQL databases through
a DBI interface and create web user interfaces to them. Among its features
are the posibility to handle relations in the same manner as fields and it
is easily extended with additional field or relation specifications as
well as custom editors and viewers.

   For a general overview description of the system see the README file,
for a quick start see the test.pl script. It conatins instructions on how
to set up a simple test database and then it preforms all the basic
opperations in a comented manner. There is also a tutorial (not yet
written) describing the basics of relation databases and how to build web
interfaces to them using HTMLView. Finaly there is a man page for every
package describing it's methods and functionality.

   This package contains shourtcuts for the constructors of some of the
basic objects under DBIx::HTMLView that are used to created the database
description structure. This structure describes all the tables in the
database and its fields, and is then used as an interface to the database
and the tables.

   For a description of parameters to the separate functions see the
diffrent packages man pages, eg DB is actualy the new method of
DBIx::HTMLView::DB. Curently we have shourtcuts for the following objects:

     msqlDB
     mysqlDB
     Table
     Int
     Date
     Str
     Bool
     Text
     Id
     N2N
     N2One

     For backwards compatibility there is also a DB method calling msqlDB.

METHODS =cut
============

   package DBIx::HTMLView; use strict; use vars qw(@ISA $VERSION @EXPORT);

   $VERSION="0.7";

   require Exporter; require DBIx::HTMLView::DB; require
DBIx::HTMLView::mysqlDB; require DBIx::HTMLView::msqlDB; require
DBIx::HTMLView::Table; require DBIx::HTMLView::Int; require
DBIx::HTMLView::Str; require DBIx::HTMLView::Date; require
DBIx::HTMLView::Bool; require DBIx::HTMLView::Text; require
DBIx::HTMLView::Id; require DBIx::HTMLView::N2N; require
DBIx::HTMLView::N2One; require DBIx::HTMLView::Tree;

   @ISA         = qw(Exporter);  @EXPORT      = qw(DB mysqlDB msqlDB Table
Str Bool Text Id N2N Int N2One Date Tree);

   sub DB {   msqlDB(@_) # For backwards compatibility }

   sub mysqlDB {   DBIx::HTMLView::mysqlDB->new(@_); }

   sub msqlDB {   DBIx::HTMLView::msqlDB->new(@_); }

   sub Table {   DBIx::HTMLView::Table->new(@_); }

   sub Int {   DBIx::HTMLView::Int->new(@_); }

   sub Str {   DBIx::HTMLView::Str->new(@_); }

   sub Date {   DBIx::HTMLView::Date->new(@_); }

   sub Bool {   DBIx::HTMLView::Bool->new(@_); }

   sub Text {   DBIx::HTMLView::Text->new(@_); }

   sub Id {   DBIx::HTMLView::Id->new(@_); }

   sub N2N {   DBIx::HTMLView::N2N->new(@_); }

   sub N2One {   DBIx::HTMLView::N2One->new(@_); }

   sub Tree {   DBIx::HTMLView::Tree->new(@_); }

   1;

   # Local Variables: # mode:              perl # tab-width:         8 #
perl-indent-level: 2 # End:

A boolean field
***************

NAME
====

     DBIx::HTMLView::Bool - A boolean field

SYNOPSIS
========

     $fld=$post->fld('testf');
     print $fld->view_html;

DESCRIPTION
===========

   This is a subclass of DBIx::HTMLView::Str used to represent boolean
data (eg true or false). It is represented by a one character field that
is default wither Y or N. The main difference from a Str is that the
default edit_html editor uses a two  <input type=radio ...> buttons to
construct the editor.

   $data of the constructor (see the new method of DBIx::HTMLView::Fld)
can have the following values specified:

   true - the value stored in the databse when this field should represent
 true, default Y.  false - the value stored in the databse when this
field should represent   false, default N.  view_true - the value used to
view a true value for the view_html,   edit_html and view_text methods,
defaule Yes.  view_false - the value used to view a false value for the
view_html,   edit_html and view_text methods, defaule No.

METHODS =cut
============

   package DBIx::HTMLView::Bool; use strict; use Carp;

   use vars qw(@ISA); require DBIx::HTMLView::Bool;  @ISA =
qw(DBIx::HTMLView::Str);

   sub true {   my $self=shift;   if ($self->got_data('true')) {return
$self->data('true')}   return 'Y'; } sub false {   my $self=shift;   if
($self->got_data('false')) {return $self->data('false')}   return 'N'; }
sub view_true {   my $self=shift;   if ($self->got_data('view_true'))
{return $self->data('view_true')}   return 'Yes'; } sub view_false {   my
$self=shift;

     if ($self->got_data('view_false')) {return $self->data('view_false')}
     return 'No';
     }

   sub default_fmt {   my ($self, $kind)=@_;   if ($kind eq 'view_text' ||
$kind eq 'view_html') {     return   '<perl>if ($self->got_val &&
$self->val eq $self->true) {return $self->view_true} else {return
$self->view_false}</perl>';   }   if ($kind eq 'edit_html') {     return
'<perl>if ($self->got_val && $self->val eq $self->true) {'.
    '$val2="";$val1="checked"} else {$val1="";$val2="checked"}'.
  '"";</perl>'.             "<input type='radio' name='<var name>'
value='" . $self->true .             "' <perl>\$val1</perl> >" .
$self->view_true . "&nbsp;&nbsp;" .             "<input type='radio'
name='<var name>' value='" . $self->false .             "'
<perl>\$val2</perl>>" . $self->view_false;

     }
     return DBIx::HTMLView::Field::default_fmt(@_);
     }

   sub sql_create {my$self=shift;$self->db->sql_type("Bool",$self)}

   1;

   # Local Variables: # mode:              perl # tab-width:         8 #
perl-indent-level: 2 # End:

A List user interface for DBI databases
***************************************

NAME
====

     DBIx::HTMLView::CGIGermanListView - A List user interface for DBI databases

SYNOPSIS
========

     $view=new DBIx::HTMLView::CGIGermanListView($script, $dbi, $cgi);
     print $view->view_html;

DESCRIPTION
===========

   This is a database viewer/editer using the CGI interface and HTML forms
to present the user interface to the user. It's a very simple interface.
At the top all the tables of the database are listed to allow the user to
select which one to edit (including a + sign for adding a new post, and at
the bottom the selected table is listed.  If the table has more than
defined in {'rows'}, output is split into pages.  Every post has a link to
allow you to show, edit or delete them.  There is also a link to add new
posts to the table.

   To be able to use this you need a cgi script that sets up a few things
and decides which editor to use to edit single posts and to insert default
values and so on... For a simple such script see View.cgi.

   This is a subclass to DBIx::HTMLView::CGIView.  =head1 METHODS =cut

   package DBIx::HTMLView::CGIGermanListView; use strict;

   use vars qw(@ISA); require DBIx::HTMLView::CGIView;  @ISA =
qw(DBIx::HTMLView::CGIView);

   sub new {   my $self=DBIx::HTMLView::CGIView::new(@_); #pass rows via
new HOWTO?    $self->{'view_flds'}=undef;   $self->{'extra_sql'}=undef;
$self->{'page'}=1;   $self->{'rows'}=50;   $self; }

$view->flds_to_view(@flds)
--------------------------

   Specifys which flds to view by listing there names. Default is to view
all fields of a post but none of the relations.

$view->extra_sql($extra)
------------------------

   If you want to add some extra SQL clauses to the end of the select
command they can be given here. This can be used to specify in which order
the posts should appear by giving an ORDER clause.

$view->view_html
----------------

   Returns the html code for the editor as specified by previous methods.

A List user interface for DBI databases
***************************************

NAME
====

     DBIx::HTMLView::CGIListView - A List user interface for DBI databases

SYNOPSIS
========

     $view=new DBIx::HTMLView::CGIReqEdit($script, $dbi, $cgi);
     print $view->view_html;

DESCRIPTION
===========

   This is a database viewer/editer using the CGI interface and HTML forms
to present the user interface to the user. It's a very simple interface.
At the top all the tables of the database are listed to allow the user to
select which one to edit (including a + sign for adding a new post, and at
the bottom the selected table is listed.  If the table has more than
defined in {'rows'}, output is split into pages.  Every post has a link to
allow you to show, edit or delete them.  There is also a link to add new
posts to the table.

   To be able to use this you need a cgi script that sets up a few things
and decides which editor to use to edit single posts and to insert default
values and so on... For a simple such script see View.cgi.

   This is a subclass to DBIx::HTMLView::CGIView.  =head1 METHODS =cut

   package DBIx::HTMLView::CGIListView; use strict;

   use vars qw(@ISA); require DBIx::HTMLView::CGIView;  @ISA =
qw(DBIx::HTMLView::CGIView);

   sub new {   my $self=DBIx::HTMLView::CGIView::new(@_);

     $self->{'view_flds'}=undef;
     $self->{'extra_sql'}=undef;
     $self->{'page'}=1;
     $self->{'rows'}=50;
     $self;
     }

$view->rows($nr)
----------------

   Specifies how many rows should be displayed on one page. Default is 50.

$view->flds_to_view(@flds)
--------------------------

   Specifies which flds to view by listing there names. Default is to view
all fields of a post but none of the relations.

$view->extra_sql($extra)
------------------------

   If you want to add some extra SQL clauses to the end of the select
command they can be given here. This can be used to specify in which order
the posts should appear by giving an ORDER clause.

$view->view_html
----------------

   Returns the html code for the editor as specified by previous methods.

A List user interface for DBI databases
***************************************

NAME
====

     DBIx::HTMLView::CGIQueryListView - A List user interface for DBI databases

SYNOPSIS
========

     $view=new DBIx::HTMLView::CGIQueryListView($script, $dbi, $cgi);
     print $view->view_html;

DESCRIPTION
===========

   This is a database viewer/editer using the CGI interface and HTML forms
to present the user interface to the user. It's a very simple interface.
At the top all the tabels of the database is listed to allow the user to
select which one to edit, and at the botom the selected table is listed.
Every post has a link to allow you to show, edit or delete them. There is
also a link to add new posts to the table.

   To be able to use this you need a cgi script that sets up a few things
and decides which editor to use to edit single posts and to insert default
values and so on... For a simple such script see View.cgi.

   This is a subclass to DBIx::HTMLView::CGIView.  =head1 METHODS =cut

   package DBIx::HTMLView::CGIQueryListView; use strict;

   use vars qw(@ISA); require DBIx::HTMLView::CGIView;  @ISA =
qw(DBIx::HTMLView::CGIView);

   sub new {   my $self=DBIx::HTMLView::CGIView::new(@_);

     $self->{'view_flds'}=undef;
     $self->{'extra_sql'}=undef;
     $self;
     }

$view->extra_sql($extra)
------------------------

   If you want to add some extra SQL clauses to the end of the select
command they can be given here. This can be used to specify in which order
the posts should appear by giving an ORDER clause.

$view->view_html
----------------

   Returns the html code for the editor as specified by previous methods.

A simple CGI editor for single posts
************************************

NAME
====

     DBIx::HTMLView::CGIListView - A simple CGI editor for single posts

SYNOPSIS
========

     $view=new DBIx::HTMLView::CGIReqEdit($script, $post);
     print $view->view_html;

DESCRIPTION
===========

   This is a post editer using the CGI interface and HTML forms to present
the user interface to the user. It's a very simple interface, that list
all the flds and allows the user to modify.

   A Fld can be taged read-only, and then it will not show up in the list.

METHODS =cut
============

   package DBIx::HTMLView::CGIReqEdit; use strict;

   use vars qw(@ISA); require DBIx::HTMLView::CGIView;  @ISA =
qw(DBIx::HTMLView::CGIView);

$view=DBIx::HTMLView::CGIReqEdit->new($script, $post, $read_only, $cgi)
-----------------------------------------------------------------------

   Creats a new post editor to edit the post $post (a DBIx::HTMLView::Post
object. $read_only should be a regular expretion matching the fields that
should not show up in the editor.

   Note that this is not a secure way to prevent users from getting access
to specific fields as some simple tampering with the html forms passed to
the user will bring up the other tabels as well for editing.

$view->post
-----------

   Returns the post being edited (a DBIx::HTMLView::Post object).

$view->db
---------

   Returns the databse we'r working with (a DBIx::HTMLVIew::Db object).

$view->tab
----------

   Returns the table we'r working with (a DBIx::HTMLVIew::Table object.)

$view->read_only
----------------

   Returns the readonly reg exp as psecified in the constructor parameter
$read_only.

$view->view_html
----------------

   Returns the html code for the editor as specified by previous methods.

A Requester viewer/editor for DBI databases
*******************************************

NAME
====

     DBIx::HTMLView::CGIReqView - A Requester viewer/editor for DBI databases

SYNOPSIS
========

   use DBIx::HTMLView::CGIListView; use DBIx::HTMLView::CGIReqView;

   my $db="DBI:mSQL:HTMLViewTester:athena.af.lu.se:1114";

   $q = new CGI; if (DBIx::HTMLView::CGIReqView::Handles($q)) { 	$v=new
DBIx::HTMLView::CGIReqView($db, {}, $q); } else {   # Use some other view
list CGIListView for example...  }

   $v->PrintPage("this_file.cgi");

DESCRIPTION
===========

   This is a CGI interface based on the CGIView class (eg a subclass of)
that allows you to edit or view one post in a table. Alla data is shown
and all data except the key is editable, if the $self->{'editable'}
variable is not modified, in which case it should contain a regexp
matching all editable fields. It could be costruncted as
"<field1>|<field2>|<field3>|...".

   By seting the _New key in the CGI query a blank form will show upp for
adding new posts. By setting the key _Edit together with _Id, the vaule of
_Id will be looked up as the key of a post and that post will be presented
for editing.

   Is is also possible to show a post by setting _Show and _Id. The value
of _New, _Edit and _Show are never used and thereby on no importance.

METHODS
=======

$c=new DBIx::HTMLView::CGIReqView($db, $fmt, $query)
====================================================

   Initiats the viewer. $db and $fmt is the database specifier and format
specification as descriped in the DBIx::HTMLView manual. $query is the cgi
query as returned by "new CGI;".

$c->PrintPage($script)
======================

   Will print the html page, with links back to the cgi script $script.

DBIx::HTMLView::CGIReqView::Handles($q)
=======================================

   Returns 1 if this object can handle the request make by $q, otherwise 0.
$q should be an CGI object created with "new CGI";

Author
======

     Hakan Ardo <hakan@debian.org>

Common CGI functions for the viewers
************************************

NAME
====

     DBIx::HTMLView::CGIView - Common CGI functions for the viewers

SYNOPSIS
========

   package MyCGIViewer

   require DBIx::HTMLView::CGIView;  @ISA = qw(DBIx::HTMLView::CGIView);

   sub new {   my $self=DBIx::HTMLView::CGIView::new(@_);

     # ...
     }

DESCRIPTION
===========

   This class some basic functions that can be used to create cgi
interfaces to a HTMLView database. And is therefor suited as a base class
for viewr or edit classes.

METHODS =cut
============

   package DBIx::HTMLView::CGIView; use strict; use Carp;

$view=DBIx::HTMLView::CGIView->new($script, $db, $cgi)
------------------------------------------------------

   Creates a new CGIView object that will use the url $script for future
requests to the database $db (a DBIx::HTMLVIew::DB object) and $cgi is the
CGI object containing the request we got from the user.

$view->script =head2 $view->script_name
---------------------------------------

   Returns the name of the script we should use for future calls as set by
the $script param to the constructor.

$view->lnk =head2 $view->link_data
----------------------------------

   Returns a string that can be included in a link that will set the
params that is supposed to be presistand between requests. Curent that is:
_Table, the name of the table we are currently working on, _usr, the user
name, and _pw, the password used to access the database.

$view->form_data
----------------

   Will return the same data as $view->link_data but in form of <input
type=hidden ...> tags to be included in a html form instead.

$view->db
---------

   Returns the database (a DBIx::HTMLView::DB object) we'r using, as set
by the $db parameter to the constructor.

$view->cgi
----------

   Returns the CGI object as set by the $cgi parameter to the constructor.

$view->got_cgi
--------------

   Returns true if the CGI object was set by the $cgi parameter to the
constructor.

$view->tab
----------

   Returns the table (a DBIx::HTMLView::Table object) we're currently
working with. Either as specified in the CGI query or the first table
found in the database if none was defined.

A generic DBI databse with SQL interface
****************************************

NAME
====

     DBIx::HTMLView::DB - A generic DBI databse with SQL interface

SYNOPSIS
========

   use DBIx::HTMLView; my $dbi=my
$dbi=DB("DBI:mSQL:HTMLViewTester:localhost", "", "",
Table ('Test', Id('id'), Str('testf'))); my
$hist=$dbi->tab('Test')->list();

DESCRIPTION
===========

   The DB object is usualy only used to represent the top level database
and to access the diffrent tabel objects. But all databse communications
is routed through it.

   This class is intended as a generic base class it is then inherited by
engine specifik classes such as DBIx::HTMLView::msqlDB and
DBIx::HTMLView::mysqlDB. If you plan to use this with another database
engine you'll probably have to atleast overide the insert sub to handle
the assignmet of id values to new posts correctly.

METHODS =cut
============

   package DBIx::HTMLView::DB; use strict;

   use DBI; use Carp;

$dbi=DBIx::HTMLView::DB->new($db, $user, $pass, @tabs) =head2 $dbi=DBIx::HTMLView::DB->new($dbh, @tabs)
-------------------------------------------------------------------------------------------------------

   Creates a new database representation to the database engine represented
by the DBI data_source $db and connect's to it using $user and $pass as
user name and pasword. @tabs is a list of the tables contained in the
database in form of DBIx::HTMLView::Table objects.

   If you'r db needs more initialising than a DBI connect you can
initialise the connection yourself and then pass the dbh (as returned by
the DBI->connect call) using the second form of the constructor.

   The database connection will not be closed untill this object is
destroyed.

$dbi->send($cmd)
----------------

   Will prepare and send the SQL command $cmd to the database and it dies
on errors. The $sth is returned.

$dbi->tab($tab)
---------------

   Returns the DBIx::HTMLView::Table object representing the table named
$tab.

$dbi->tabs
----------

   Returns an array of DBIx::HTMLView::Table objects representing all the
tables in the database.

$dbi->sql_escape
----------------

   Escapes the supplied string to be valid inside an SQL command.  That
is, it changes the string q[I'm a string] to q['I\'m a string'];

$dbi->del($tab, $id)
--------------------

   Deletes the post with id $id form the table $tab (a
DBIx::HTMLView::Table object).

$dbi->update($tab, $post)
-------------------------

   Updates the data in the database of the post represented by $post (a
DBIx::HTMLView::Post object) in the table $tab (a DBIx::HTMLView::Table
object) with the data contained in the $post object.

$dbi->insert($tab, $post)
-------------------------

   Insert the post $post (a DBIx::HTMLView::Post object) into the table
$tab (a DBIx::HTMLView::Table object). This is the method to override if
you need to change the way new post get's their id numbers assigned. This
method should also make sure to set the id fld of $post to the id assigned
to it.

$dbi->sql_create
----------------

   Will create the tables of the database using SQL commands that works
with msql. The database has to be created by hand using msqladmin or
msqlconfig.

$dbi->sql_create_table($table)
------------------------------

   Creates the table $table, a DBIx::HTMLView::Table object, using SQL
commands that works with msql.

$dbi->sql_type($type, $fld)
---------------------------

   Returns the SQL type string used for the type $type of the Fld $fld.
$type should be one of "Id", "Int", "Str", "Text", "Bool", "Date" and $fld
should be a DBIx::HTMLView::Fld object.

A simple date filed
*******************

NAME
====

     DBIx::HTMLView::Date - A simple date filed

SYNOPSIS
========

     $fld=$post->fld('testf');
     print $fld->view_html;

DESCRIPTION
===========

   This is a subcalss of DBIx::HTMLView::Str used to represent date fields
in the databse as well as the data contained in it. Se the
DBIx::HTMLView::Field and DBIx::HTMLView:.Fld (the superclass of Field)
manpage for info on the methods of this class.

Base class for field classes
****************************

NAME
====

     DBIx::HTMLView::Field - Base class for field classes

SYNOPSIS
========

     $fld=$post->fld('testf');
     print $fld->view_html;

DESCRIPTION
===========

   This is a subcalss of DBIx::HTMLView::Fld used to represent fields in
the databse as well as the data contained in it. Except for the methods
decsribed in the DBIx::HTMLView::Fld man page this class contains some
methods for handling the data contain in the field. They are described
below.

   It also contains default implementations of all the virtual methods
except name_vals described in that man page. For viewing this means the
value is used without any formating (both for text and html), and for the
edit_html method a standard <input size=80 ...> tag is used.

   The size 80 can be changed by setting the edit_size key to the wanted
size in the $data hash passed to the new method, see DBIx::HTMLView::Fld.

METHODS =cut
============

   package DBIx::HTMLView::Field; use strict; use Carp;

   use vars qw(@ISA); require DBIx::HTMLView::Fld;  @ISA =
qw(DBIx::HTMLView::Fld);

$fld->val
---------

   Returns the value of this field if it's value is set. otherwise it dies
with "Field conatins no data".

$fld->got_val
-------------

   Return true if the value of this field is set (defined).

$fld->view_fmt($fmt_name, $fmt)
-------------------------------

   Se DBIx::HTMLView::Fld for a general description. As for the format of
the fmt string used here, the following substrings will be replaced with
described values:

   $val - The value of this field $name - The name of this field

Base class for field and relation classes
*****************************************

NAME
====

     DBIx::HTMLView::Fld - Base class for field and relation classes

SYNOPSIS
========

     $fld=$post->fld('testf');
     print $fld->view_html;

DESCRIPTION
===========

   These objects are used to represent the fields and relations of a table
inside the and the DBIx::HTMLView::Table object as well as the data
contained in those fields and relations in the DBIx::HTMLView::Post
objects.

   This is the base class of all field classes such as
DBIx::HTMLView::Text DBIx::HTMLView::Str and DBIx::HTMLView::Int as well
as the relations such as DBIx::HTMLView::N2N.

METHODS =cut
============

   package DBIx::HTMLView::Fld; use strict; use Carp;

$fld=DBIx::HTMLView::Fld->($name, $data) =head2 $fld=DBIx::HTMLView::Fld->new($name, $val, $tab)
------------------------------------------------------------------------------------------------

   The only time you create this kind of objects is when you create the
DBIx::HTMLView::Table objects of the top level description of the databse
(se DBIx::HTMLView::DB). And in that case it is the first version of the
constructor you use preferable through the shortcuts in DBIx::HTMLView.
$name is a string naming the relation or field while $data is a hashref
with parameters specific to the field or relation kind used. There are a
few parameters that are common though:

   sql_size - The size to be used to store this in the database, eg the
value 100 in the sql type definition CHAR(100).  sql_type - Allows you to
overide the database specific default type to   use for a fld. If this is
defined it will be used as sql type for   this fld.  fmt - A string
specifying how this Fld should be viewed by default. It   is the fmt
string that will be used by view_fmt if no other are   specified, or if
the one specified does not excist. The format of   this string depends on
the type of Fld se the docs to the view_fmt   methods of the diffrent Fld
subclasses for info on it.  fmt_* - You can give each Fld any number of
custom fmts used to view   this fld in diffrent contexts. There are a few
special one:   fmt_view_html, fmt_edit_html, fmt_view_text that are tied
to the   method calls view_html, edit_html, view_text respectivly (eg the
method call view_html is the same as view_fmt('view_html'))

   The second version of the constructor is used by the
DBIx::HTMLView::Table class when it creates copies of its flds, gives them
their data $val and places them in a post. $tab is the
DBIx::HTMLView::Table object the fld belongs to.

   For fields data ($val) is specified as a string or as the first item of
an array referenced to by $val. Relations are represented as a reference
to an array of the id's of the posts being related to.

$fld->name
----------

   Returns the name of the fld.

$fld->data($key)
----------------

   Returns the value of $key set from the $data hashref in the new method.
It dies if the data was not set.

$fld->got_data($key)
--------------------

   Returns true if the value of $key was set in the $data hashref in the
new method.

$fld->set_tab($tab)
-------------------

   Used by DBIx::HTMLView::Table to inform the fld of which table it
belongs to. All fld belongs to either a Table or a Post.

$fld->set_post($post)
---------------------

   Used by DBIx::HTMLView::Post to inform the fld pf which post it belongs
to. All fld belongs to either a Table or a Post.

$fld->tab
---------

   Return the DBIx::HTMLView::Table object this fld belongs to.

$fld->db
--------

   Return the DBIx::HTMLView::Db object this fld belongs to.

$fld->post
----------

   Returns the DBIx::HTMLView::Post object this fld belongs to.

VIRTUAL METHODS
===============

   Those methods are not defined in this class, but are suposed to be
defined in all fld subclasses.

$fld->view_fmt($fmt_name,$fmt)
------------------------------

   Returns a string used to display the contents (value) of the fld.
Usually this is just the value of the fld, but for more complex Fld, like
relations, $fmt_name can be used to specify which fmt that should be used
(the diffrent fmts are defined in the constructor, se the $fld->new
method). If the $fmt param is defined it will be used as the fmt string
insteda of looking up a default one.

$fld->view_html
---------------

   Returns a html string used to display the contents (value) of the fld.

$fld->edit_html
---------------

   Returns a string that can be placed inside an html <form> section used
to edit this field or relation. It will be some sort of input tag with the
same name as the fld.

$fld->sql_data($sel)
--------------------

   Called if this fld is used in the selection string in a
DBIx::HTMLView::Selection object $sel. It is supposed to add apropriate
data to the object using $sel->add_fld and $sel->add_tab (se the
DBIx::HTMLView::Selection manpage for details) and return the string to
represent it in the where clause (it will usualy be the name of the field
itself).

$fld->view_text
---------------

   Returns a text string used to view the contents (value) of the fld
(this method is not yet implemented for all fld classes).

$fld->del($id)
--------------

   Is called when a post with id $id is deleted. This is to allow the
relations of this post to clean out the data that is placed in other
tabels. The actual post will be removed from the table after all fld
object del methods has been called.

$fld->field_name
----------------

   The name of the sql field in the main table representing this fld. For
a N2N relation it will be undefined as it is represented in a separate
table and not in the main one. For fields it will ofcourse be the name of
the field.

$fld->name_vals
---------------

   This medthod is called whenever the data of a post are updated in the
actual database or a new post is added. It returns an array of hashes
containing the two keys name and val.  Where the value of the name keys
are the names of database fields that are supposed to be set to the values
of the val keys.  e.g.  return ( {'name' => 'Color', 'value' => 'Red'},
{'name' => 'Size', 'value' => 'XXL'} );

   This is the method where relations are supposed to update all secondary
tabels (eg the tables used to represent the actuall relations).

$fld->sql_create
----------------

   Will send the nesesery SQL commands to create this fld in database and
return the sql type (if any) of this field to be included in the CREATE
clause for the main table. That is normal fields will only return their
type while relations will create it's link table.

$fld->fmt($kind)
----------------

   Returns the "fmt_$kind" param as passed to the constructor (se new
method for info). If that one does not excist the default one "fmt" is
used. If thatone isn't specified either the default fmt '$val' is returned.

   To allow subclasses to provide more decent defaults the
default_fmt($kind) method is called if "fmt_$kind" is not defined.  If it
returns undef this method carries on as described above, otherwise the
return value of default_fmt is returned. Then default_fmt is called again
if there was no "fmt" param speciefied, but this time with $kind undefined.

   The default implementation here is ofcourse to always return undef, that
will give the behaviour described in the first paragraph here.

   A replacment default_fmt should never return undef but instead execute
it's supreclass version of it and return it's value if it dosn't want to
override the specified kind.

$fld->default_fmt($kind)
------------------------

   Used to allow subclasses to provide there own default fmts, se
$fld->fmt($kind).

$fld->view_text =head2 $fld->view_html =head2 $fld->edit_text
-------------------------------------------------------------

   For backwards compatibility those are linked to view_fmt('view_text'),
view_fmt('view_html'), view_fmt('edit:html'), respectivly.

   A replacment default_fmt should never return undef but instead execute
it's supreclass version of it and return it's value if it dosn't want to
override the specified kind.

Basic parser for fmt strings and files
**************************************

NAME
====

     DBIx::HTMLView::Fld - Basic parser for fmt strings and files

SYNOPSIS =head1 DESCRIPTION
===========================

   ANY: VAR | FLD | FMT | PERL | TXT VAR: "<VAR " ... ">" FLD: "<FLD " ...
">" FMT: "<FMT " ... ">" ANY "</FTM>" PERL: "<PERL " ... ">" ... "</PERL>"
TXT: Anything else

$sel->token
-----------

   Returns the current token.

$sel->token($kind)
------------------

   Returns true if the current token is of the kind $kind.

$sel->token($kind,$val)
-----------------------

   Set $val as the curent token, and $kind as the kind of that token.

A index field used to identify posts
************************************

NAME
====

     DBIx::HTMLView::Id - A index field used to identify posts

SYNOPSIS
========

     $fld=$post->fld('id');
     print $fld->view_html;

DESCRIPTION
===========

   This is a subclass of DBIx::HTMLView::Field used to represent the id
fields of a table in the databse as well as the data contained in it.  See
the DBIx::HTMLView::Field and DBIx::HTMLView:.Fld (the superclass of
Field) manpage for info on the methods of this class.

   Each post must have an unique id number which the HTMLView system uses
to identify the post. The id has to be stored in the database in a field
which is specifyed by this class in the DBIx::HTMLView::Table object used
to represent the table. There should only be one Id field.

   If you try to generate an html editor using the edit_html method this
Fld will return a <input type=hidden ...> field that is used in the form
to specify which post is being edited.

   This behaviour of not allowing the user to edit the id should probably
not be modified as the id might be stored in other places (for eaxample
relations) too, and has to be updated there too.

An integer field
****************

NAME
====

     DBIx::HTMLView::Int - An integer field

SYNOPSIS
========

     $fld=$post->fld('testf');
     print $fld->view_html;

DESCRIPTION
===========

   This is a subcalss of DBIx::HTMLView::Field used to represent integer
fields in the databse as well as the data contained in it. Se the
DBIx::HTMLView::Field and DBIx::HTMLView:.Fld (the superclass of Field)
manpage for info on the methods of this class.

A many to many relation between two tabels
******************************************

NAME
====

     DBIx::HTMLView::N2N - A many to many relation between two tabels

SYNOPSIS
========

     $fld=$post->fld('testf');
     print $fld->view_html;

DESCRIPTION
===========

   This is a subcalss of DBIx::HTMLView::Relation used to represent N2N
relations in the databse as well as the data contained in them. Se the
DBIx::HTMLView::Relation and DBIx::HTMLView:.Fld (the superclass of
Relation) manpage for info on the methods of this class.

   A N2N relation as where each post in one table can be related to any
number of posts in an other table. As for example in the User/Group table
pair example described in the tutorial where each user can be part of
several groups.

   A third table, called link table, will be used to represent the
relations. It should contain three fields. One id field (as all tabels),
one from id (eg user id) and one to id (eg group id). Now one relation
consists of a set of posts in this table each linking one from post (eg
user) to one to post (eg group).

   As for the overall operation this kind of Flds should wokr like any
other Fld, but you can also do a few extra things, as described below.

METHODS =cut
============

   package DBIx::HTMLView::N2N; use strict; use Carp;

   use vars qw(@ISA); require DBIx::HTMLView::Relation;  @ISA =
qw(DBIx::HTMLView::Relation);

   require DBIx::HTMLView::Fmt;

$fld=DBIx::HTMLView::N2N->($name, $data) =head2 $fld=DBIx::HTMLView::N2N->new($name, $val, $tab)
------------------------------------------------------------------------------------------------

   The constructor works in the exakt same way as for DBIx::HTMLView::Fld,
se it's man page for details.

   The following parameters passed within the $data has is recognised:

   tab - The table this table is related to (to table) from_field - The
field name of the link table where the from table post    id is stored.
Default is "<from table>_id".  to_field - The field name of the link table
where the to table post    id is stored. Default is "<to table>_id".
lnk_tab - The name of the link table. Default is "<from table>_to_<to
table>".  id_name - The name of the link post id field in the link table.
Default    is "id".  view - String used when viewing a related post
withing the post being    viewed (eg the groups list of a user post). All
$<fld name> constructs    will be replaced with the data of the post
beeing viewed. Obsolete, use    the fmt param instead.  join_str - As a
post can be related to several other and each will be    viewed using the
view string above and then joined together using this    string as glue.
Default is ", ".  Obsolete, use the fmt param instead.  fmt - Specifies
the fmt string to be passed to view_fmt of the PostSet    object
representing the posts we are related to. For backwards    compatibility
it defaults to "<node join="$join_str">$view</node>",    if $view is
defined. $view and $join_str are the var defined above.  extra_sql - Extra
sql code passe to the list method when listing related    posts. This can
for example be used to specify in which order related    posts should be
viewed. Default is "ORDER BY <to table id name>".

   As you se, it is only tab that does not have any default value, so it
has to be defined within the table declaration, it's usually also a good
idea to specify fmt to something decent as well.

   =cut

   sub new {   my $this = shift;   my $class = ref($this) || $this;   my
$self=  bless {}, $class;

     my ($name, $data, $tab)=@_;
     $self->{'name'}=$name;
     $self->{'tab'}=$tab;

     if (ref $data eq "HASH") {
       $self->{'data'}=$data;
     } elsif (ref $data eq "ARRAY") {
       if (ref $this) {$self->{'data'}=$this->{'data'};}
       $self->{'posts'}=DBIx::HTMLView::PostSet->new($self->to_tab);
       foreach (@$data) {
         if ($_ ne "do_edit") {
           $self->{'posts'}->add($self->to_tab->new_post({$self->tab->id->name=>$_}));
         }
       }
     } else {
       $self->{'id'}=$data;
       if (ref $this) {$self->{'data'}=$this->{'data'};}
     }

     $self;
     }

$fld->db
--------

   Returns the database handle of the tabels.

$fld->id
--------

   Returns the id of the post this relation belongs to.

$fld->to_tab_name
-----------------

   Returns the name of the to table.

$fld->to_tab
------------

   Returns the DBIx::HTMLView::Table object representing the to table.

$fld->from_field_name
---------------------

   Returns the name of the from field in the link table as specified in the
$data param to the constructor.

$fld->to_field_name
-------------------

   Returns the name of the to field in the link table as specified in the
$data param to the constructor.

$fld->lnk_tab_name
------------------

   Returns the name of the link table as specified in the $data param to
the constructor.

$fld->id_name
-------------

   Returns the name of the link post id field in the link table as
specified in the $data param to the constructor.

$fld->lnk_tab
-------------

   Creates and returns a DBIx::HTMLView::Table object representing the link
table.

$fld->join_str
--------------

   Returns the join_str parameter as specified in the $data param to the
constructor.

$fld->extra_sql
---------------

   Returns the extra_sql parameter as specified in the $data param to the
constructor.

$fld->got_post_set
------------------

   Returns true if we have a post set. Se the post_set method.

$fld->post_set
--------------

   When this object is used to represent the data of a relation that can
be done in two ways. Either we just know the id of the post we belong to
and can look up the related posts from the db whenever needed. When such a
post lookup is done the (parts of the) posts returned are stored in a
DBIx::HTMLView::PostSet object.

   This method will return such an object after selecting it from the
server if nesessery. You can use the got_post_set method to check if it
was already donwloaded. If this Fld did not belong to a specifik post, eg
no id was defiedn it will die with "Post not defined!".

$fld->posts
-----------

   Will return an array of the posts after calling the post_set method. If
there are no related posts it will not die, but return an empthy array.

$fld->view_fmt_edit_html($postfmt_name, $postfmt)
-------------------------------------------------

   Used by the default edit_html fmt. It will return a string containing
"<input type=checkbox ...>" constructs to allow the user to specify which
posts we should be related to. All posts in the to table will be listed
here and viewed with view_fmt($postfmt_name,$postfmt).

   $postfmt_name will default to 'view_html'. If $postfmt isn't defined
some decent default is tried to be derived from the default fmt for
$postfmt_name.

   The $postfmt should contain a <Var Edit> tag that will be raplaced by
the checkbox button.

$fld->del($id)
--------------

   Will remove the relation from post $id. Eg it will no longer be related
to any posts.

$fld->name_vals
---------------

   Returns an empthy array as no fields in the from table should be
modifed.

$fld->post_updated
------------------

   Updates the relation data in the db.

$fld->sql_data($sel, $sub)
--------------------------

   Used by the DBIx::HTMLView::Selection object $sel when it finds a
relation->field construct in a search string that should be evaled into an
sql select expretion. $sub will be a refference to an array of all names
after the -> signs, eg for rel1->rel2->rel3->field $sub would contain
("rel2", "rel3", "field") and this would be the rel1 relation.

$fld->field_name
----------------

   Returns undef as we've not got any field in the main table. Se
DBIx::HTMLView::Fld.

$fld->view_fmt($fmt_name, $fmt)
-------------------------------

   Will call view_fmt($fmt_name, $fmt) on the postset containing all the
posts this relation is pointing to and return the result, see
DBIx::HTMLView::PostSet for info on the $fmt format.

   If the fmt string starts with "<InRel>", the rest of the fmt will be
handled by this method instead of calling the PostSet version.  Current
the only supported construct here is <perl>...</perl> which will be
replaced by the returnvalue of eval(...).

A many to one relation between two tabels
*****************************************

NAME
====

     DBIx::HTMLView::N2One - A many to one relation between two tabels

SYNOPSIS
========

     $fld=$post->fld('testf');
     print $fld->view_html;

DESCRIPTION
===========

   This is a subcalss of DBIx::HTMLView::Int used to represent a relation
to a post in another (or possibly the same) table. The relation will be
represented in the database by a field containing the id of the post
related to. Se the DBIx::HTMLView::Field and DBIx::HTMLView:.Fld (the
superclass of Field) manpage for info on the methods of this class.

   NOTE: Even if this is a relation it is NOT a subclass of
DBIx::HTMLView::Relation.

   #FIXME: List possible params

$fld->to_tab_name
-----------------

   Returns the name of the to table.

$fld->to_tab
------------

   Returns the DBIx::HTMLView::Table object representing the to table.

$fld->view_fmt_edit_html($postfmt_name, $postfmt)
-------------------------------------------------

   Used by the default edit_html fmt. It will return a string containing
"<input type=radio ...>" constructs to allow the user to specify which
post we should be related to. All posts in the to table will be listed
here and viewed with view_fmt($postfmt_name,$postfmt).

   $postfmt_name will default to 'view_html'. If $postfmt isn't defined
some decent default is tried to be derived from the default fmt for
$postfmt_name.

   The $postfmt should contain a <Var Edit> tag that will be replaced by
the radio button.

$fld->view_fmt($fmt_name, $fmt)
-------------------------------

   Will call view_fmt($fmt_name, $fmt) on the post this relation is
pointing to and return the result, se DBIx::HTMLView::Post for info on the
$fmt format.

   If $fmt is not defined the fmt parameter named $fmt_name specified in
the $data parameter to the constructor will be used as fmt string.

   If the fmt string starts with "<InRel>", the rest of the fmt will be
handled by this method instead of calling the PostSet version.  Current
the only supported construct here is <perl>...</perl> which will be
replaced by the returnvalue of eval(...).

A post in a DBI database
************************

NAME
====

     DBIx::HTMLView::Post - A post in a DBI database

SYNOPSIS
========

     $post=$post_set->first;
     print $post->view_html;   # View a post

     $post->set('testf', 7);   # Set the testf field to 7
     $post->update;            # Update the database with the modified post

     $post=DBIx::HTMLView::Post->new($tab)   # Create a new post
     $post->set('testf', 7);   # Set the testf field to 7
     $post->update;            # Insert the new post in the databse

DESCRIPTION
===========

   This object represents a single post in a specific table in the
database. It has methods to view post as well as to modify it's data and
to reflect those modifications in the database.

$post=DBIx::HTMLView::Post->new($tab, $data, $sth)
--------------------------------------------------

   Creates a new post belonging to the table $tab (a DBIx::HTMLview::Table
object). $data and $sth is used to initialize the post with it's fields,
which can be done in several ways:

   1. To create a new empty post with no data set, simply don't specify
those arguments.  2. If $data is an array reference, $sth is supposed to
be the object    returned by a DBI execude call with a select command, and
$data should    be the array ref with the data you want to create a post
object of. If    the same fieldname apperas twice in the select the first
one is    presumed to be the one belonging to this post.  3. If $data is a
hash reference, it is supposed to contain Fld/Value    pairs.  4. If $data
is a CGI object the CGI params is supposed to be Fld/Value    pairs. Note
that relations in this case is defined by setting the name    of the
relation to the id's of the posts related to, eg it will be    defined
once for every post.

$post->set($fld, $val)
----------------------

   Set's the Fld named $fld to $val. If $val is not a DBIx::HTMLView::Fld
object $post->tab->new_fld($fld,$val) is called to create the Fld object
to represent this fld and it's data.

   For fields data ($val) is specified as a string or as the first item of
a array referenced to by $val. Relations are represented as a reference to
an array of the id's of the posts being related to.

$post->got_fld($fld_name)
-------------------------

   Returns true if we have data specified for the fld named $fld_name.

$post->view_text
----------------

   Returns a string that could be used to view this post in text format

$post->view_html
----------------

   Returns a string that could be used to view this post in html format.

$post->view_fmt($fmt_name, $fmt)
--------------------------------

   Returns a string represeting this post in the format named by $fmt_name
as returned by DBIx::HTMLView::post_fmt($fmt_name). If $fmt is specified
it will be used as the fmt strings instead of looking up a default one.

   All <Var ...> will be replaced with there corisponding values or removed
if they are not know, currently no such values are know here (eg all is
remeved).

   To include the value of an Fld in output simply put $<fld_name> in the
desired place in the $fmt string. (eg $name will be replaced with the
outpit of $self->fld('name')->view_fmt($fmt_name)).

   If $fmt is not specified the default post fmt will be used as returned
by post_fmt in DBIx::HTMLView::Table.

   $fmt_name is passed on to fld objects, so it can be used to specify how
the flds should be represented even if you use a custom fmt passed to $fmt.

$post->fld_names
----------------

   Returns an array of the fld names currently specified in this post, use
$post->tab->fld_names to list all Fld of the post.

$post->fld($fld_name) =head2 $post->val($fld_name)
--------------------------------------------------

   Returns the Fld representing that data of the Fld named $fld_name.

$post->tab
----------

   Returns the table this post belongs to (a DBIx::HTMLView::Table object).

$post->got_id
-------------

   Returns true if the id of this post is defined, which is the same as
that the post is represented in the database as well (which is not true
for new posts that not yet have been added to the datbase, using
$post->update).

$post->id
---------

   Returns the id of this post or dies with "No id defined" if it is not
defined. Se $post->got_id.

$post->update
-------------

   Updates the database with the data found in this object or creats a new
post in the database with that data if the id is not defined. Se
$post->got_id.

A set posts as in a search result for example
*********************************************

NAME
====

     DBIx::HTMLView::PostSet - A set posts as in a search result for example

SYNOPSIS
========

   my $post_set=$table->list;  # Get a PostSet $post_set->view_html;
# view it

   $post_set=$table->list;     # Get a new one as the old now is used
while (defined $post=$self->get_next) {   # Process $post...  }

   $post_set=DBIx::HTMLView::PostSet->new($table) # Create a PostSet in
save mode $post_set->add($post);

DESCRIPTION
===========

   This a class representing a set of object as for example a result of a
search. The object can either be in save mode or in no-save mode. A
PostSet object in no-save mode will be able to itterate through the posts
once and then they are gone. The posts are never stored, but retrieved
from the db when you ask for the next one and then trashed if you don't
save them. In save mode this class will star by dowbloading all the posts
from the db into memory to allow more advanced manipulations.

$post_set=DBIx:.HTMLView::PostSet->new($tab, $sth, $save)
---------------------------------------------------------

   Creates a new PostSet object for posts from the table $tab (a
DBIx::HTMlView::Table object). If $sth is a reference it's supposed to be
the result of a DBI execute call with a select command. The posts returned
from the db will be the ones represented by this set.

   If $save is defined to a false value the object will be created in
no-save mode, otherview in save mode. See the DESCRIPTION.

$post_set->rows
---------------

   Returns the number of rows (posts) in this PostSet as reported by the
$sth->rows DBI function.

$post_set->got_post($post)
--------------------------

   Returns true if $post has been returned earlier in this set (in which
case we won't return it again). Or if we are in save mode returns true if
the post is within the set. $post should be a DBIx::HTMLView::Post object.

$post_set->do_got_post
----------------------

   Marks $post (a DBIx::HTMLView::Post object) as a returned post. See
$post_set->got_post.

$post_set->tab
--------------

   Returns the table (a DBIx::HTMLView::Table object) this set of posts
belongs to.

$post_set->get_next
-------------------

   Returns the next post (a DBIx::HTMLView::Post object) in the set. The
first one will be returned if this method has not been called before.

$post_set->save_mode
--------------------

   Returns true if we are in save mode.

$post_set->add($post)
---------------------

   Adds the post $post (a DBIx::HTMLView::Post object) to the set.

$post_set->posts
----------------

   Returns an array of DBIx::HTMLView::Post object representing the posts
in the set or dies if there is no posts or if we are not in save mode with
"No posts!" and "Not in save mode" respectivly.

$post_set->first
----------------

   Returns the first post of this set, or dies with "No posts!" if there
is no posts. If we are in no-save mode it can be called once before any
next_post calls are done, after that it will die with "Not in save mode".

$post_set->view_html
--------------------

   Returns a string that can be used to view the entire set of posts in
html format.

$post->view_fmt($fmt_name, $fmt)
--------------------------------

   Returns a string represeting this set of posts in the format named by
$fmt_name. as returned by DBIx::HTMLView::list_fmt($fmt_name). If $fmt is
specified it will be used as the fmt strings instead of looking up a
default one.

   If the fmt stringit contains a <node>...</node> construct the ... part
will be repeated once for every post and passed as $fmt param to view_fmt
of DBIx::HTMLView::Post. Curretly we only support one <node>...</node>
construct in the fmt. If ... is "", undef will be passed as fmt to the
Post, thereby using default Post fmts.

   $fmt_name is passed on to the Post objects who the passes it on to the
fld objects, so it can be used to specify how the flds should be
represented  even if you use a custom fmt passed to $fmt.

A relation base class
*********************

NAME
====

     DBIx::HTMLView::Relation - A relation base class

SYNOPSIS
========

     $fld=$post->fld('id');
     print $fld->view_html;

DESCRIPTION
===========

   This is a subcalss of DBIx::HTMLView::Fld used to represent relations
between tables in the databse as well as the data contained in them.  Se
the DBIx::HTMLView:.Fld manpage for info on the methods of this class.

A kriteria used to select posts
*******************************

NAME
====

     DBIx::HTMLView::Selection - A kriteria used to select posts

SYNOPSIS
========

     $sel=DBIx::HTMLView::Selection->new($table, $search_string);
     print $sel->sql_select

DESCRIPTION
===========

   This class is used to parse search query strings and generate SQL
select queries out of them. You usually don't use this class itself, but
simply pass the strings to methods like list in DBIx::HTMLView::Table,
which then uses this class to parse them.

   The format of the search strings looks very much like the SQL select
querys, but with some modifications. All fields are supposed to belong to
the table $tab passed to the constructor and fields in related posts are
accessed using the string <relation_name>-><field_name> (eg group->name).
It's even possible (not yet implemeted though) to access fields through
several relations (eg rel1->rel2->field).

   Here is a more precise definition of the language useed:

     <expr>       = <bool_value> (("AND" | "OR") <bool_value>)?
     <bool_value> = <fld_spec> <opperator> <value> | "(" <expr> ")"
     <fld_spec>   = <fld_name> ("->" <fld_name>)*
     <fld_name>   = <word>
     <value>      = <literal>|<fld_spec>
     <literal>    = \d+ | "'" <string> "'"
     <string>     = [^']*
     <word>       = [a-zA-Z0-9_.]+
     <operator>   = "<" | ">" | "=" | "<=" | ">=" | "<>" | "LIKE" | ...

METHODS =cut
============

   # FIXME: Multilevel relations searching (rel->rel->fld), update docs

$sel=DBIx::HTMLView::Selection->new($table, $str, $flds, $opps);
----------------------------------------------------------------

   Creats a new selection for posts in the table $table (a
DBIx::HTMLView::Table object) selecting posts matching the search string
$str (in the format described above).

   $flds is for optimisations. If it is definied it is supposed to be a
reference to an array with the names of the extra fields to select from
the database server. All fields used in the $str query will ofcourse also
be selected. If this parameter is not defined, all fields of the table
will be selected.

   $opps is an array ref listing all the opperations your SQL server
supports and you wish to be able to use in your search query. Deault is:
['<', '>', '=', '<=', '>=', '<>', 'LIKE', 'RLIKE', 'CLIKE', 'SLIKE'].

$sel->sql_select
----------------

   Returns a SQL select query mathing the posts described in the search
query passed to the constructor.

$sel->sql_count
---------------

   Returns a SQL select query counting the posts described in the search
query passed to the constructor.

$sel->tab
---------

   Returns the table we're selecting posts from (a DBIx::HTMLView::Table
object).

$sel->add_to_where($str)
------------------------

   Add $str to the end of the string that will be the where clause of the
slect query.

$sel->add_fld($field_name)
--------------------------

   Adds the field named $field_name to the list of fields selected.

$sel->add_tab($table_name)
--------------------------

   Adds the table named $table_name to the list of tabels selected from.

$sel->opps
----------

   Returns an array of comparation opperation recognised as specified by
the $opps parameter to the constructor.

$sel->token
-----------

   Returns the current token.

$sel->token($kind)
------------------

   Returns true if the current token is of the kind $kind.

$sel->token($kind,$val)
-----------------------

   Set $val as the curent token, and $kind as the kind of that token.

$sel->next_token
----------------

   Get's the next token from the string, determins it's type and makes it
the current token using $self->token.

$sel->expr =head2 $sel->bool_value =head2 $sel->fld_spec =head2 $sel->value
---------------------------------------------------------------------------

   All those reads and parsers a specifik sub expretions as defined in the
description.

A single line string filed
**************************

NAME
====

     DBIx::HTMLView::Str - A single line string filed

SYNOPSIS
========

     $fld=$post->fld('testf');
     print $fld->view_html;

DESCRIPTION
===========

   This is a subcalss of DBIx::HTMLView::Field used to represent string
fields in the databse as well as the data contained in it. Se the
DBIx::HTMLView::Field and DBIx::HTMLView:.Fld (the superclass of Field)
manpage for info on the methods of this class.

A table within a generic DBI databse
************************************

NAME
====

     DBIx::HTMLView::Table - A table within a generic DBI databse

SYNOPSIS
========

   my $table=$dbi->tab('Test');

   # List all posts my $hits=$table->list();

   # Get post with id 7 my $post=$table->get(7);

DESCRIPTION
===========

   This object is supposed to be created inside a database description as
described in the DBIx::HTMLView::DB man page to represent a table and it's
fields and relations. Then it can be used to access the posts of that
table.

METHODS =cut
============

   package DBIx::HTMLView::Table; use strict; use Carp;

   require DBIx::HTMLView::Str; require DBIx::HTMLView::Post; require
DBIx::HTMLView::PostSet;

   require DBIx::HTMLView::Selection;

DBIx::HTMLView::Table->new($name, @flds)
----------------------------------------

   Creates a new table representation for a table named $name. This has to
be the same name as the database engine has for the table. @flds is an
array of DBIx::HTMLView::Fld objects which represent the separate fields
and relations of the table.

$table->id
----------

   Returns the DBIx::HTMLView::Fld object that is used as the id field for
this table.

$table->name
------------

   Returns the name of this table.

$table->set_db($db)
-------------------

   Use by the parent DBIx::HTMLView::DB object to inform this object which
databse it belongs to ($db). It should not be used elsewhere.

$table->set_viewer($db)
-----------------------

   To inform the table about ...  To have links to the cgi script inside
the table =cut

   sub set_viewer {   my ($self, $viewer)=@_;   $self->{'viewer'}=$viewer;
}

$table->list($search, $extra, $flds)
------------------------------------

   Returns a DBIx::HTMLView::PostSet object with the posts matching the
$search string (see the DBIx::HTMLView::Selection man page for a
description of the search language, it is close to SQL). $extra will be
apended to the SQL select command before it is sent to the databse it can
be used to specify a ORDER BY clause for example.

   $flds is for optimisations. If it is not defined all fileds of the
posts are retrieved from the datbase. If it is an array ref only the
fields who's names are listed in there are retrieved. If a search string
is specied the fields used in that string will also be retrieved.

   The PostSet object return is placed in no-save mode, which means that
you will be able to itterate through the posts once and then they are
gone. This is becaue there can be quite a lot of data returned from the
database server and there is usualy no reason to store it all in memory.

   To create a PostSet object in save mode with the result you could do
something like:

   $post_set=$table->list; $post_set_save=DBIx::HTMLView::PostSet->new;
while (defined $post=$self->get_next) {   $post_set_save->add($post); } '

$table->count($search, $extra)
------------------------------

   Counts the numbers of posts matching the $search string (see the
DBIx::HTMLView::Selection man page for a description of the search
language, it is close to SQL). $extra will be apended to the SQL select
command before it is sent to the databse.

$table->noid_list($search, $extra, $flds)    Works in a similar way to $table->list, but it will not add the id field to flds select, and it will do a distinct select. The posts returned are some kind of pseudo posts. If you try to modify and update  them and the new posts will be added to the db as they have no id.
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

   Will currently not work with relations (FIXME). It will never work with
N2N relations as they require the id selected in order to find the related
posts.

$table->sql_list($select)
-------------------------

   Sends $select, which should be a select clause on this table,to the
database and turns the result into a DBIx::HTMLView::PostSet object.  You
should use the list method insted. It gives you a smoother interface.

$table->new_post(...)
---------------------

   Creates a new DBIx::HTMLView::Post object linked to this table (all
posts must be linked to a table). All arguments are passed on to the new
method.

$table->new_fld($fld,$val)
--------------------------

   Creates a copy of the DBIx::HTMLView::Fld object named $fld and gives
it the value $val. It is used by the DBIx::HTMLView::Post objects to
create objects representing the diffrent values of the fields and does not
make much sense elsewhere.

   For fields data ($val) is specified as a string or as the first item of
a array referenced to by $val. Relations are represented as a reference to
an array of the id's of the posts being related to.

$table->fld_names
-----------------

   Returns an array of the names of all the fields and relation in this
table.

$table->fld($fld)
-----------------

   Returns the DBIx::HTMLView::Fld object of the field or relation named
$fld.

$table->got_fld($fld)
---------------------

   Returns true if this table has a field or relation named $fld.

$table->fld($fld)
-----------------

   Returns an array of DBIx::HTMLView::Fld objects of all the fields and
relations in this table.

$table->db
----------

   Returns the DBIx::HTMLView::DB object this table belongs to.

$table->viewer
--------------

   Returns the DBIx::HTMLView::DB object this table belongs to.

$table->del($id)
----------------

   Deletes the post with id $id.

$table->update($post) =head2 $table->change($post)
--------------------------------------------------

   Updates the data in the database of the post represented by $post (a
DBIx::HTMLView::Post object) with the data contained in the object.

$table->add($post) =head2 $table->insert($post)
-----------------------------------------------

   Inserts the post $post (a DBIx::HTMLView::Post object) into the
database.

$table->get($id)
----------------

   Returns a DBIx::HTMLView::Post object representing the post with id $id.

$table->msql_create
-------------------

   Will create the tabel using SQL commands that works with msql.

$table->post_fmt($kind)
-----------------------

   Returns a fmt for viewing a post from this table in the $kind format.
It can be specified in ... FIXME: where?

$table->list_fmt($kind, $butt, $flds)
-------------------------------------

   Returns a fmt for viewing a set of posts from this table in the $kind
format. It can be specified in ... FIXME: where?

   The default fmt will consist of a table with one colume per Fld
specified in the arrayref $flds. If it is not defined all Fld will be
viewed.

   $butt can be used to specify the contents of an extra colum to the right
of the rest. To for example contain the view, edit and delete buttons.

A multi line string filed
*************************

NAME
====

     DBIx::HTMLView::Text - A multi line string filed

SYNOPSIS
========

     $fld=$post->fld('testf');
     print $fld->view_html;

DESCRIPTION
===========

   This is a subclass of DBIx::HTMLView::Str used to represent larger
texts. The main difference from a Str is that the default edit_html editor
uses a <textarea>...</textarea> construct instead of an <input ...> tag.

   This fld also has two parameters that are specified in the $data hash
passed to the constructor (see the DBIx::HTMLView::Fld manpage). They are
'width', the width of the <textarea> editor in characters (defaults is 80)
and 'height', the height of the <textarea> editor in characters (default
is 50).

   Except for the methods described in the superclasses
(DBIx::HTMLView::Fld, DBIx::HTMLView::Field, DBIx::HTMLView::Str) there
are also the following methods.

METHODS =cut
============

   package DBIx::HTMLView::Text; use strict; use Carp;

   use vars qw(@ISA); require DBIx::HTMLView::Text;  @ISA =
qw(DBIx::HTMLView::Str);

$fld->width
-----------

   Returns the witdh in characters of the default edit_html editor.

$fld->height
------------

   Returns the height in characters of the default edit_html editor.

DBIx::HTMLView::Tree
********************

NAME
====

     DBIx::HTMLView::Tree

SYNOPSIS
========

DESCRIPTION
===========

$fld->to_tab_name
-----------------

   Returns the name of the to table.

$fld->to_tab
------------

   Returns the DBIx::HTMLView::Table object representing the to table.

$fld->view_fmt_edit_html($postfmt_name, $postfmt)
-------------------------------------------------

   Used by the default edit_html fmt. It will returns a string containing
"<input type=radio ...>" constructs to allow the user to specify which
post (chunk in the tree) we should be related to. All posts in the to
table (tree) will be listed here in a hierarchically list showing the tree
structure and viewed with view_fmt($postfmt_name,$postfmt).

   $postfmt_name will default to 'view_html'. If $postfmt isn't defined
some decent default is tried to be derived from the 'view' fmt or if
that's not defined, the default fmt.

   The $postfmt should contain a <Var Edit> tag that will be raplaced by
the radio button.

$fld->view_fmt($fmt_name, $fmt)
-------------------------------

   Will call view_fmt($fmt_name, $fmt) on the post this relation is
pointing to and return the result, se DBIx::HTMLView::Post for info on the
$fmt format.

   If $fmt is not defined the fmt parameter named $fmt_name specified in
the $data parameter to the constructor will be used as fmt string.

   If the fmt string starts with "<InRel>", the rest of the fmt will be
handled by this method instead of calling the PostSet version.  Current
the only supported construct here is <perl>...</perl> which will be
replaced by the returnvalue of eval(...).

interface for msql databases through DBI
****************************************

NAME
====

     DBIx::HTMLView::msqlDB - interface for msql databases through DBI

SYNOPSIS
========

   use DBIx::HTMLView; my $dbi=my $dbi=msqlDB("DBI:msql:HTMLViewTester",
"", "",                    Table ('Test', Id('id'), Str('testf'))); my
$list=$dbi->tab('Test')->list();

DESCRIPTION
===========

   This is a customized DB object for msql databases.  Most methods are
inherited from the superclass: DBIx::HTMLView::DB - only those that are
specific to msql are overridden.

METHODS =cut
============

   package DBIx::HTMLView::msqlDB; use strict;

   use DBI; use Carp;

   use vars qw(@ISA); require DBIx::HTMLView::DB;  @ISA =
qw(DBIx::HTMLView::DB);

   sub insert {   my ($self, $tab, $post)=@_;   my $id=$self->send('select
_seq from ' . $tab->name)->fetchrow_arrayref->[0];
$post->set($tab->id->name, $id);

     DBIx::HTMLView::DB::insert($self, $tab, $post);
     }

   sub sql_create_table {   my ($self, $table)=@_;
DBIx::HTMLView::DB::sql_create_table($self, $table);
$self->send("CREATE UNIQUE  INDEX idx1 ON " . $table->name . "(" .
      $table->id->name . ")");   $self->send("CREATE SEQUENCE ON " .
$table->name . " STEP 1"); }

   # Local Variables: # mode:              perl # tab-width:         8 #
perl-indent-level: 2 # End:

interface for mysql databases through DBI
*****************************************

NAME
====

     DBIx::HTMLView::mysqlDB - interface for mysql databases through DBI

SYNOPSIS
========

   use DBIx::HTMLView; my $dbi=my $dbi=mysqlDB("DBI:mysql:HTMLViewTester",
"", "",                    Table ('Test', Id('id'), Str('testf'))); my
$list=$dbi->tab('Test')->list();

DESCRIPTION
===========

   This is a customized DB object for mysql databases.  Most methods are
inherited from the superclass: DBIx::HTMLView::DB - only those that are
specific to mysql are overridden.

METHODS
=======

Class for creating a CGI interface to a database
************************************************

NAME
====

   DBIx::HTMLinterface - Class for creating a CGI interface to a database

SYNOPSIS
========

     use CGI;
     use DBI;
     use DBIx::HTMLinterface;

     $cgi			= new CGI;
     $dbh			= DBI->connect("DBI:mysql:[DATABASE]:[HOSTNAME]","[USERNAME]","[PASSWORD]") );
     $DBinterface	= new DBIx::HTMLinterface ($cgi, $dbh, "[INFOTABLE NAME]");

     # Below here is only executed if a HTMLinterface action was not taken, so print a menu

     print $cgi->header;
     print "<A HREF=" . $cgi->url . "?HTMLinterface-table=[TABLENAME]&HTMLinterface-action=add>Add</A>\n<BR>";
     print "<A HREF=" . $cgi->url . "?HTMLinterface-table=[TABLENAME]&HTMLinterface-action=search>Search</A>\n";

DESCRIPTION
===========

   The `DBIx::HTMLinterface' class allows a CGI interface to a database.
It enables a CGI interface to a database to be created, supporting record
addition, modification, deletion and searching. It provides a user
friendly interface with descriptions of fields provided. The field
descriptions along with information on whether the field is visible,
hidden or excluded are extracted from a table, allowing easy modification
and addition of fields and tables without having to edit code.

Features
--------

Simple database administration
     Forms are created automatically on demand, SQL statements are
     generated as needed and processed.  The module contains enough
     autonomy to potentially run with only wrapper perl code placed around
     it.

Full form configuration
     Forms can be modified to add descriptions and extra information to
     fields, making it easy to change output without having to edit code.

Control
     Extensive callback procedures and configuration options allow output,
     password protection and logging to be configured as desired.

Full HTML customisation
     HTML output and table formats can be customised easily by the user.

METHODS
=======

Main Methods
------------

*$DBinterface = new DBIx::HTMLinterface (*CGI DBI *Infotable Name* *[Suppress paramcheck]**);*
     Constructs a new `DBIx::HTMLinterface' object. You must pass a
     reference to a CGI object which will be used to get the script's
     parameters and a database handle (Returned from a `DBI->connect'
     function) which will be used to communicate with the database. The
     third parameter defines the name of the *info table* which is used to
     determine hidden/excluded fields, field names and descriptions as
     described below in INFOTABLE FORMAT. After initialisation, the CGI
     object is checked for a 'HTMLinterface-action' parameter.  If this is
     present, control is taken from the script and the specified action is
     performed on the specified table. This parameter is set when an
     action which requires further processing is in progress.

     The final parameter, suppress paramcheck, is optional and when set to
     1 will cause the script NOT to perform the parameter check. You MUST
     then call the check_params function in your code or forms will not
     work. Overriding the script in this way is not recommended unless
     necessary for error handler or security check handler setting.

Optional Methods
----------------

   Optional methods which can be called to directly jump to a script
function, for example to directly initiate a delete or modify on a record.

check_params *();*
          # Check form parameters
          $DBinterface->check_params;

     Causes the HTMLinterface-action parameter to be rechecked. If it
     contains the value 'add','modify','delete' or 'search', the
     respective function will be called
     ('exec_add','exec_modify','exec_delete' or 'exec_search').  this
     function is essential to the correct functioning of the interfaces
     with two and three part forms, and is called automatically when a
     HTMLinterface object is created, unless the 'suppress paramcheck'
     parameter is set to 1.

exec_search *();*
          # Now set the 'HTMLinterface-table' parameter so the script knows
          # what table to deal with
          $cgi->param(-name=>'HTMLinterface-table',-value=>'mytable');

          # Now call the function
          $DBinterface->exec_search;

     Searches the table named in the CGI parameter 'HTMLinterface-table'.
     The user will be presented with a blank form with the fields of the
     table.  They press submit to search the table (Wildcards can be
     used). They are then returned a table with a modify and delete button
     and the fields for each record found.

exec_modify *();*
          # Assume $cgi->param has been set to indicate the primary keys
          # for the table being modified, i.e 'Primary Key Name' = 'Primary
          # Key Value'

          # Now set the 'HTMLinterface-table' parameter so the script knows
          # what table to deal with
          $cgi->param(-name=>'HTMLinterface-table',-value=>'mytable');

          # Now call the function
          $DBinterface->exec_modify;

     Modifies a record from the table named in the CGI parameter
     'HTMLinterface-table' where the CGI parameters which have the same
     name as a table column. For example for a table called 'data' with an
     'ID' column containing the primary keys for that table, set the
     'HTMLinterface-table' parameter to 'data' and set the 'ID' parameter
     to the ID number of the record you want to modify. The user will then
     be presented with a form containing the data in the table for them to
     modify.  They then press submit to commit the data

exec_add *();*
          # Now set the 'HTMLinterface-table' parameter so the script knows
          # what table to deal with
          $cgi->param(-name=>'HTMLinterface-table',-value=>'mytable');

          # Now call the function
          $DBinterface->exec_add;

     Adds a record to the table named in the CGI parameter
     'HTMLinterface-table'.  The user will be presented with a empty form
     containing just the defaults for the values of that table (Defined in
     the SQL). They then press submit to commit the data to the table.

exec_delete *();*
          # Assume $cgi->param has been set to indicate the primary keys
          # for the table being modified, i.e 'Primary Key Name' = 'Primary
          # Key Value'

          # Now set the 'HTMLinterface-table' parameter so the script knows
          # what table to deal with
          $cgi->param(-name=>'HTMLinterface-table',-value=>'mytable');

          # Now call the function
          $DBinterface->exec_delete;

     Deletes a record from the table named in the CGI parameter
     'HTMLinterface-table' where the CGI parameters which have the same
     name as a table column. For example for a table called 'data' with an
     'ID' column containing the primary keys for that table, set the
     'HTMLinterface-table' parameter to 'data' and set the 'ID' parameter
     to the ID number of the record you want to delete.

     This function will output a confirmation page requiring users to
     confirm the delete or press their browser's back button to cancel. To
     skip confirmation, set the 'confirm' parameter to 'Y'.

Optional Customisation Methods
------------------------------

   Optional methods which can be called to alter the behaviour of the
script or enable features such as logging.

set_logcallback (*Callback function address**);*
          sub log_callback {
              my $description = shift;
              my $sql         = shift;

          open (LOG,">>$logfile")
          print LOG "$description (Executing $sql)";
          close(LOG);
            }
            $DBinterface = new DBIx::HTMLinterface ($cgi, $dbh, $table, 1);
            $DBinterface->set_logcallback(\&log_callback);
            $DBinterface->check_params();

     Enables logging of SQL changes to the database via the user defined
     routine. The first parameter passed is a description, such as 'Record
     added to mytable' and the second parameter is the SQL statement which
     was used.

     NOTE: check_params() MUST be called or HTMLinterface will not
     function correctly.

set_logfile (*Logfile name**);*   $DBinterface = new DBIx::HTMLinterface ($cgi, $dbh, $table, 1);   $DBinterface->set_logfile("/usr/local/logs/mydb-log");   $DBinterface->check_params();
     Enables logging of SQL changes to the database automatically without
     providing a callback. The script will open the file specified, with
     no locking (Althoughthis might be added in future). The file must be
     writeable to the CGI, on UNIX you normally need to *chmod 666
     mydb-log*. However this may differ depending on your system and what
     operating system you have.

     NOTE: check_params() MUST be called or HTMLinterface will not
     function correctly.

set_errhandler (*Error handler function address**);*
          sub errorhandler {
              my $errstr  = shift;

          print "<h1>Fatal Error</h1>";
          print $errstr;

          exit;
            }
            $DBinterface = new DBIx::HTMLinterface ($cgi, $dbh, $table, 1);
            $DBinterface->set_errorhandler(\&errorhandler);
            $DBinterface->check_params();

     Transfers error handling in the script from the *die()* procedure to
     the subroutine passed as the argument. The errorhandling routine
     should not return, and should terminate the program after the error
     has been output.

     NOTE: check_params() MUST be called or HTMLinterface will not
     function correctly.

set_accesscallback
          sub checkaccess {
              if ($cgi->param("password") eq "letmein") { # Example security check
                 return; # Valid password - return to allow function to continue
              } else {
                 die ("Incorrect password"); # Incorrect - die to stop execution
              }
          }
          $DBinterface = new DBIx::HTMLinterface ($cgi, $dbh, $table, 1);
          $DBinterface->set_accesscallback(\&errorhandler);
          $DBinterface->check_params();

     Enables a security check function to approve or deny access. The
     function is called before changes to the database are made. The
     function should return to allow an action to complete or die to
     terminate the program and prevent access.

     NOTE: check_params() MUST be called or HTMLinterface will not
     function correctly.

set_timezone (*UseGMT (1/0)**,* *Time change (hours)**);*
          $DBinterface->set_timezone(1, 0);  # Set time to GMT +0000
          $DBinterface->set_timezone(0, -5); # Set time to server time -0500
          $DBinterface->set_timezone(1, -8); # Set time to GMT -0800
          $DBinterface->set_timezone(0, 2);  # Set time to server time +0200

     Changes the time zone used for timestamps inserted into database
     records. The first parameter specifies whether to use GMT time or to
     use the server time, i.e the computer running this script's internal
     clock. The second parameter allows time to be added or subtracted in
     hours.

Optional HTML Customisation Methods
-----------------------------------

Future Additions
     In a later version, callbacks to print table cells, start and finish
     tables, print form fields, print back links and add user defined form
     parameters to allow state keeping such as password protection etc.

set_printheader
          sub printheader {
              my $title    = shift;
              my $headtext = shift;

          print $cgi->start_html(-title=>"$title_txt");

          if ($headtext ne "") {
              print $cgi->h3($headtext);
          }
            }
            $DBinterface->set_printheader(\&printheader);

     Transfers the header HTML outputting function to a user defined
     function to allow HTML customisation.

set_printfooter
          sub printfooter {
              print $cgi->end_html;
          }
          $DBinterface->set_printfooter(\&printfooter);

     Transfers the footer HTML outputting function to a user defined
     function to allow HTML customisation.

INFOTABLE FORMAT
================

   The correct SQL structure for the infotable is shown below, in MySQL
format. If another database is being used, an equivalent SQL structure
should work correctly providing the field names remain the same. User
defined fields can be safely appended to the table and will be ignored by
HTMLinterface.

     CREATE TABLE [infotable name] (
       TableID varchar(200) DEFAULT '' NOT NULL,         # SQL name of table
       TableName tinytext DEFAULT '' NOT NULL,           # User friendly name of table
       NameHash text DEFAULT '' NOT NULL,                # 'name=value&name2=value2' style entry for names of fields
       LabelHash text DEFAULT '' NOT NULL,               # 'name=value&name2=value2' style entry for labels of fields
       LookupHash text DEFAULT '' NOT NULL,              # 'name=select Thing from Table&name2=select Somethingelse from Table' style entry for value lookup
       ExtraHash text DEFAULT '' NOT NULL,               # 'name=extra_info&name2=extrainfo' style entry containing extra information. Currently recognised values
                                                         #        include 'encryptpassword' which causes SQL statements to encrypt this field with the mysql 'PASSWORD'
                                                         #        function.
       Hidden text DEFAULT '' NOT NULL,                  # 'name&name2' style entry for hidden columns
       Exclude text DEFAULT '' NOT NULL,                 # 'name&name2' style entry for excluded columns
       AdditionalWhere text DEFAULT '' NOT NULL,         # Additional SQL 'where' clause for search modes, e.g to exclude items from searches
       # Add any user defined fields here
       PRIMARY KEY (TableID)
     );

   A description of each field follows:

TableID
     The table's identifier. This should exactly match the table's name in
     the database. For example:

          users

TableName
     A user friendly name for the table, shown in the output. For example:

          Registered Users

NameHash
     A string containing user-friendly names for the fields in the table.
     Formatted similar to a HTML query string, although no form of
     escaping is available at the moment. For example:

          name=User Name&dob=User's Date of Birth&occupation=User's Occupation&password=User's Password

LabelHash
     Similar to NameHash, contains a description for each field that is
     displayed below any form input fields. For example:

          name=Enter the user's name&dob=Enter the user's date of birth in the format DDMMYY&occupation=Select the user's occupation&password=The user's password

LookupHash
     Used to create dropdown lists, such as in the current example, an
     additional table called 'occupations' can be created and filled with
     a list of possible occupations. In editing modes, a drop down list of
     all available occupations can then be created. LookupHash should
     contain a select statement to associate with a field. The select
     statement should return one or two fields. If it returns two, the
     first will be used as the value of the form element, the value that
     will be placed in the database and the second will be used as the
     value displayed to the user, i.e a select box will be created with
     the syntax:

          <option value="[FIRSTFIELD]">[SECONDFIELD]

     If only one field is returned, it is used as both the value displayed
     and the value of the form element.

     For example:

          occupation=select ID, Name from occupations order by Name

     If other lookups are needed they can be joined using the usual '&'
     syntax.

ExtraHash
     Used to pass additional information to HTMLinterface. Currently only
     one value is supported, 'encryptpassword' which causes any entries in
     the field to be encrypted using the MySQL PASSWORD() function. For
     example:

          password=encryptpassword

Hidden
     Used to hide fields from the user, for example primary key ID fields
     should be hidden. Simply a list of each hidden field, separated by
     '&'. Hidden fields are printed as 'hidden' input fields.  For example
     to hide 'id' and 'secretdata':

          id&secretdata

Exclude
     Completely removes fields from forms, formatted in the same way as
     Hidden. For example:

          invisiblefield&invisiblefield2

AdditionalWhere
     Additional SQL clause to be appended to the select statement used in
     search modes, for example:

          AND NOT name = 'Fred'

     could be used to exclude 'Fred' from searches. Also, order by clauses
     can be appended to sort output.

     NOTE: appending to the where clause requires the statement to begin
     with 'AND'.

KNOWN BUGS
==========

   * Hidden and exclude arrays are nonfunctional due to array handling
     problems...

     [TODO - Believed to be fixed, awaiting testing]

   * Code may be too MySQL specific and not function on other databases.
     This needs to be tested.

   * Currently may allow users to manipulate tables not defined in the
     infotable depending on database in use. This will be switchable in
     the next version.

AUTHOR
======

   James Furness, furn@base6.com

   Parts based upon *mysql-lib.pl* by Ron Crisco <ronsolo@ronsolo.com>.

SEE ALSO
========

   See CGI, `DBI' in this node

COPYRIGHT
=========

   Copyright (c)1999 James Furness <furn@base6.com>. All Rights Reserved.
This module is free software; it may be used freely and redistributed for
free providing this copyright header remains part of the module. You may
not charge for the redistribution of this module. Selling this code without
James Furness' written permission is expressly forbidden.

   This module may not be modified without first notifying James Furness
<furn@base6.com> (This is to enable me to track modifications). In all
cases the copyright header should remain fully intact in all modifications.

   This code is provided on an "As Is" basis, without warranty, expressed
or implied. The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability and fitness,
in no event shall the author, James Furness be liable for any special,
indirect or consequential damages or any damages whatsoever including but
not limited to loss of use, data or profits. By using this module you
agree to indemnify James Furness from any liability that might arise from
it's use.  Should this code prove defective, you assume the cost of any
and all necessary repairs, servicing, correction and any other costs
arising directly or indrectly from it's use.

   The copyright notice must remain fully intact at all times.  Use of
this program or its output constitutes acceptance of these terms.

   Parts of this module are based upon mysql-lib.pl by Ron Crisco.

Acknowledgments
---------------

   Thanks to Ron Crisco, Richard Smith and Stephen Heaslip without who I
would probably have not written this. Thanks to Tom Christiansen for his
Perltoot (perl.info), manpage which was useful in writing
this module in addition to the Perlmod (perl.info),
Perlmodlib (perl.info), and Tim Bunce's modules file (Available
on CPAN).

create and maintain keyword indices in DBI tables
*************************************************

NAME
====

   DBIx::KwIndex - create and maintain keyword indices in DBI tables

SYNOPSIS
========

     package MyKwIndex;
     use DBIx::KwIndex;

     sub document_sub { ... }

     package main;
     $kw = DBIx::KwIndex->new({dbh => $dbh, index_name => 'myindex'})
       or die "can't create index";

     $kw->add_document   ([1,2,3,...]) or die $kw->{ERROR};
     $kw->remove_document([1,2,3,...]) or die $kw->{ERROR};
     $kw->update_document([1,2,3,...]) or die $kw->{ERROR};

     $docs = $kw->search({ words=>'upset stomach' });
     $docs = $kw->search({ words=>'upset stomach', boolean=>'AND' });
     $docs = $kw->search({ words=>'upset stomach', start=>11, num=>10 });
     $docs = $kw->search({ words=>['upset','(bite|stomach)'], re=>1 });

     $kw->add_stop_word(['the','an','am','is','are']) or die $kw->{ERROR};
     $words = $kw->common_word(85);
     $kw->remove_word(['gingko', 'bibola']) or die $kw->{ERROR};

     $ndocs  = $kw->document_count();
     $nwords = $kw->word_count();
     $ndocs  = $kw->match_count({ words=>'upset stomach', boolean=>'OR' });

     $kw->remove_index or die $kw->{ERROR};
     $kw->empty_index  or die $kw->{ERROR};

DESCRIPTION
===========

   DBIx::KwIndex is a keyword indexer. It indexes documents and stores the
index data in database tables. You can tell DBIx::KwIndex to index [lots]
of documents and later on show you which ones contain a certain word.  The
typical application of DBIx::KwIndex is in a search engine.

   How to use this module:

  1. Provide a database handle.
          use DBI;
          my $dbh = DBI->connect(...) or die $DBI::errstr;

  2. Subclass DBIx::KwIndex and provide a `document_sub' method to
     retrieve documents referred by an integer id. The method should
     accept a list of document ids in an array reference and return the
     documents in an array reference. In this way, you can index any kind
     of documents that you want: text files, HTML files, BLOB columns,
     etc., as long as you provide the suitable document_sub() to retrieve
     the documents. The one thing to remember is that the documents must
     be referred by unique integer number. Below is a sample of a
     document_sub() that retrieves document from the 'content' field of a
     database table.
          package MyKwIndex;
          require DBIx::KwIndex;
          use base 'DBIx::KwIndex';

          sub document_sub {
             my ($self, $ary_ref) = @_;
          	my $dbh = $self->{dbh};

          my $result = $dbh->selectall_arrayref(
          'SELECT id,content FROM documents
           WHERE id IN ('. join(',',@$ary_ref). ')');

          # if retrieval fails, you should return undef
          defined($result) or return undef;

          # now returns the content field in the order of the id's
          # requested. remember to return the documents exactly
          # in the order requested!
          my %tmp = map { $_->[0] => $_->[1] } @$result;
          return [ @tmp{ @$ary_ref } ];
           }

  3. Create the indexer object.
          my $kw = MyKwIndex->new({
                   dbh => $dbh,
                   index_name => 'article_index',
                   # other options...
                   });

     dbh is the database handle. *index_name* is the name of the index,
     DBIx::KwIndex will create several tables which are all prefixed with
     the index_name. The default index_name is 'kwindex'. Other options
     include: *max_word_length* (default 32).

  4. Index some documents. You can index one document at a time, e.g.
          $kw->add_document([1]) or die $kw->{ERROR};
          $kw->add_document([2]) or die $kw->{ERROR};

     or small batches of documents at a time:

          $kw->add_document([1..10])  or die $kw->{ERROR};
          $kw->add_document([11..20]) or die $kw->{ERROR};

     or large batches of documents at a time:

          $kw->add_document([1..300])   or die $kw->{ERROR};
          $kw->add_document([301..600]) or die $kw->{ERROR};

     Which one to choose is a matter of memory-speed trade-off. Larger
     batches will increase the speed of indexing, but with increased
     memory usage.

     Note: DBIx::KwIndex ignores single-character words, numbers, and words
     longer than 'max_word_length'.

  5. If you want to search the index, use the search() method.
          $docs = $kw->search({ words => 'upset stomach' });
          die "can't search" if !defined($docs);

     The search() method will return an ARRAY ref containing the document
     ids that matches the criteria. Other parameter include: num =>
     maximum number of results to retrieve; start => starting position (1
     = from the beginning); boolean => 'AND' or 'OR' (default is 'OR'); re
     => use regular expression, 1 or 0.

     Note: num and start uses the `LIMIT' clause (which is quite unique to
     MySQL). re uses the `REGEXP' clause. Do not use these options if your
     database server does not support them.

     Also note: Searching is entirely done from the index. No documents
     will be retrieved while searching. A simple 'relevancy' ranking is
     used. Search is case-insensitive and there is no phrase-search
     support yet.

     Some examples:

          # retrieve only the 11th-20th result.
          $docs = $kw->search({ words=>'upset stomach', start=>11, num=>10 });
          die "can't search" if !defined($docs);

          # find documents which contains all the words.
          $docs = $kw->search({ words=>'upset stomach', boolean=>'AND' });
          die "can't search" if !defined($docs);

     If you just want to know how many documents match your query, use the
     match_count() method. If you want to retrieve all the matches anyway,
     to know how many documents match just find out the size of the match
     array.  That will save you from extra index access.

          # find the number of documents that match the query
          $ndocs = $kw->match_count({ words=>'halitosis' });

          # find the number of matches and retrieve only the first twenty of them
          $query = { words=>'halitosis', num=>20 };
          $ndocs = $kw->match_count($query);
          $docs  = $kw->search($query);

          # search and get the matches. get the number of matches from the
          # result set itself.
          $docs  = $kw->match_count({ words=>'halitosis' });
          $ndocs = @$docs;

  6. Now suppose some documents change, and you need to update the index
     to reflect that. Just use the methods below.    # if you want to
     remove documents from index   $kw->remove_document([90..100]) or die
     $kw->{ERROR};
          # if you want to update the index
          $kw->update_document([90..100]) or die $kw->{ERROR};

SOME UTILITY METHODS
====================

   If you want to exclude some words (usually very common words, or "stop
words") from being indexed, do this before you index any document:

     $kw->add_stop_word(['the','an','am','is','are'])
       or die "can't add stop words";

   Adding stop words is a good thing to do, as stop words are not very
useful for your index. They occur in a large proportion of documents (they
do not help searches differentiate documents) and they increase the size
your index (slowing the searches).

   But which words are common in your collection? you can use the
common_word method:

     $words = $kw->common_word(85);

   This will return an array reference containing all the words that occur
in at least 85% of all documents (default is 80%).

   If you want to delete some words from the index:

     $kw->remove_word(['common','cold']);
       or die "can't remove words";

   To get some statistics about your index:

     # the number of documents
     $ndocs = $kw->document_count();
     # the number of words
     $nwords = $kw->word_count();

   Last, if you got bored with the index and want to delete it:

     $kw->remove_index or die $kw->{ERROR};

   This will delete the database tables. Or, if you just want to empty the
index and start all over:

     $kw->empty_index or die $kw->{ERROR};

AUTHOR
======

   Steven Haryanto &lt;steven@haryan.to&gt;

COPYRIGHT
=========

   Copyright (c) 2000 Steven Haryanto. All rights reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

BUGS/CAVEATS/TODOS
==================

   Enable the module to use other database server (besides MySQL).
MySQL-specific SQL bits that need to be adjusted include, but not limited
to: LIMIT clause, LOCK/UNLOCK TABLES statements, REPLACE INTO/INSERT IGNORE
statements, COUNT(DISTINCT ...) group function, AUTO_INCREMENT and
INT/UNSIGNED. (Don't you just hate SQL? `:-)' Thanks to Edwin Pratomo for
pointing these out). Currently I do not need this feature, since I only use
MySQL for current projects. Any volunteer?

   Use a more correct search sorting (the current one is kinda bogus :).

   Probably implement phrase-searching (but this will require a larger
vectorlist).

   Probably, maybe, implement English/Indonesian stemming.

   Any safer, non database-specific way to test existence of tables other
than $dbh->tables?

NOTES
=====

   At least three other Perl extensions exist for creating keyword indices
and storing them in a database: DBIx::TextIndex, MyConText,
DBIx::FullTextSearch. You might want to take a look at them before you
decide which one better suits your need. Personally I develop DBIx::KwIndex
because I want to have a module that: a) is simple and convenient to use;
b) supports updating the index without rebuilding it from scratch.

   Incidentally, these three extensions and DBIx::KwIndex itself use MySQL
specifically. One that could use Interbase or Postgres would perhaps be
nice.

   Advices/comments/patches welcome.

HISTORY
=======

   0001xx=first draft,satunet.com. 000320=words->scalar.
000412=0.01/documentation/cpan. 000902=update doc/fixes(see Changes)

Create a lookup hash from a database table
******************************************

NAME
====

   DBIx::Lookup::Field - Create a lookup hash from a database table

SYNOPSIS
========

     use DBI;
     use DBIx::Lookup::Field qw/dbi_lookup_field/;

     $dbh = DBI->connect(...);
     my $inst_id = dbi_lookup_field(
         DBH   => $dbh,
         TABLE => 'institution'
         KEY   => 'name',
         VALUE => 'id',
     );

     print "Inst_A has id ", $inst_id->{Inst_A};

DESCRIPTION
===========

   This module provides a way to construct a hash from a database table.
This is useful for the situation where you have to perform many lookups of
a field by using a key from the same table. If, for example, a table has an
id field and a name field and you often have to look up the name by its
id, it might be wasteful to issue many separate SQL queries. Having the
two fields as a hash speeds up processing, although at the expense of
memory.

EXPORTS
=======

dbi_lookup_field()
     This function creates a hash from two fields in a database table on a
     DBI connection. One field acts as the hash key, the other acts as the
     hash value. It expects a parameter hash and returns a reference to the
     lookup hash.

     The following parameters are accepted. Parameters can be required or
     optional. If a required parameter isn't given, an exception is raised
     (i.e., it dies).

    DBH
          The database handle through which to access the table from which
          to create the lookup. Required.

    TABLE
          The name of the table that contains the key and value fields.
          Required.

    KEY
          The field name of the field that is to act as the hash key.
          Required.

    VALUE
          The field name of the field that is to act as the hash value.
          Required.

    WHERE
          A SQL 'WHERE' clause with which to restrict the 'SELECT'
          statement that is used to create the hash. Optional.

BUGS
====

   None known at this time. If you find any oddities or bugs, please do
report them to the author.

AUTHOR
======

   Marcel GrE<uuml>nauer <marcel@codewerk.com>

COPYRIGHT
=========

   Copyright 2001 Marcel GrE<uuml>nauer. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   DBI(3pm).

An module to connect Perl to MS SQL Server and MS Data Engine
*************************************************************

NAME
====

   DBIx::MSSQLReporter - An module to connect Perl to MS SQL Server and MS
Data Engine

SYNOPSIS
========

   This is complete, runnable program.

   Since you only use this module after installing MS SQL Server or MS
Data Engine, you should not even have to worry about the DSN.

     #!perl -w
     use strict;
     use DBIx::MSSQLReporter;

     my($connect) = "dbi:ODBC(RaiseError=>1, PrintError=>1, Taint=>1):DSN=LocalServer";
     my($reporter) = DBIx::MSSQLReporter -> new(connexion => $connect);

     print "User tables: \n";
     print join("\n", @{$reporter -> get_tableNames()}), "\n\n";

DESCRIPTION
===========

   `DBIx::MSSQLReporter' encapsulates the connection between Perl and MS
SQL Server.

   `DBIx::MSSQLReporter' was written so that I could teach myself about MS
SQL Server and MSDE, and as part of my Perl tutorial series.

   It should be clear from the name that this module is
database-engine-specific. If you plan on writing code which is independent
of any particular database, look elsewhere.

   See the URI, below, for my demos sql7Demo[23].pl, which both use this
module.

   sql7Demo2.pl is a command-line program. sql7Demo3.pl is a CGI script.

   Lastly, note that this module has a chequered future: I may well
re-write it to fit under the umbrella of DBIx::Easy, or someone else
working independently may have already released such a module.

INSTALLATION
============

   You install `DBIx::MSSQLReporter', as you would install any perl module,
by running these commands:

     perl Makefile.PL
     make
     make test
     make install

CONSTRUCTOR new
===============

   The constructor takes 1 parameter and 1 value for that parameter.

   It croaks if it can't connect. Otherwise it returns an object you can
use thus:

     my($reporter) = DBIx::MSSQLReporter -> new(connexion => $connect);
     print join("\n", @{$reporter -> get_viewNames()}), "\n\n";

METHOD do($sql)
===============

   It croaks if it can't prepare() and execute() the given SQL.

   It returns a statment handle, which you need for things like:

     my($sth) = $reporter -> do($sql);
     $sth -> dump_results();
     $sth -> finish();

   dump_results() is built-in to DBI.

METHOD dropDB($dbName)
======================

   It croaks if it can't drop the given database.

     $reporter -> dropDB($dbName);

METHOD dropTable($tableName)
============================

   It croaks if it can't drop the given table.

     $reporter -> dropTable($tableName);

METHOD get_dbNames($sysDbCount)
===============================

   It returns a sorted list of user database names, all in lower case.

   $sysDbCount is optional. It defaults to 4, which means this method
ignores the 4 system tables. See get_sysDbNames(), below.

     my($dbName) = $reporter -> get_dbNames();
     print "User databases: \n";
     print join("\n", @$dbName), "\n\n";

METHOD get_fieldNames($tableName)
=================================

   It returns a list of references to the names, types, and precisions, of
the fields in the given table.

     my($fieldName, $fieldType, $fieldPrecision) = $reporter -> get_fieldNames($tableName);
     print join("\n", map{"Field: $$fieldName[$_]. Type: $$fieldType[$_]. Precision: $$fieldPrecision[$_]"} 0 .. $#{$fieldName}), "\n\n";

METHOD get_tableNames()
=======================

   It returns a sorted list of user table names, all in lower case.
Recall, the DSN specified the database.

     my($tableName) = $reporter -> get_tableNames();
     print "User tables: \n";
     print join("\n", @$tableName), "\n\n";

METHOD get_viewNames()
======================

   It returns a sorted list of user view names, all in lower case. Recall,
the DSN specified the database.

     my($viewName) = $reporter -> get_viewNames();
     print "User views: \n";
     print join("\n", @$viewName), "\n\n";

METHOD get_sysDbNames($sysDbCount)
==================================

   It returns a sorted list of system database names, all in lower case.
On my system, I get master, model, msDb and tempDb.

   $sysDbCount is optional. It defaults to 4, which means this method
returns the 4 system tables. See get_dbNames(), above.

     my($sysDbName) = $reporter -> get_sysDbNames();
     print "System databases: \n";
     print join("\n", @$sysDbName), "\n\n";

METHOD get_sysTableNames()
==========================

   It returns a sorted list of system table names, all in lower case.
Recall, the DSN specified the database.

     my($sysTableName) = $reporter -> get_sysTableNames();
     print "System tables: \n";
     print join("\n", @$sysTableName), "\n\n";

METHOD get_sysViewNames()
=========================

   It returns a sorted list of system view names, all in lower case.
Recall, the DSN specified the database.

     my($sysViewName) = $reporter -> get_sysViewNames();
     print "System views: \n";
     print join("\n", @$sysViewName), "\n\n";

METHOD hash2Table($select, $sep, $keyRef)
=========================================

   Convert a hash reference, as returned by $reporter -> select($sql),
into an HTML table. See select(), below, for details.

     my($html) = $reporter -> hash2Table($select);

   $sep is optional. It separates the values of different rows in each
column. It defaults to $;.

   $keyRef is optional. It is a hash reference used to specify the order
of columns.  It defaults to sorting the keys of %$select.

   If you wish to use $keyRef, prepare it thus:

     my(%key) =
     (
     	hostName	=>
     		{
     			someData	=> '',
     			order		=> 2,
     		},
     	userName	=>
     		{
     			someData	=> '',
     			order		=> 1,
     		},
     );

     my($html) = $reporter -> hash2Table($select, $;, \%key);

     The key 'order' is used to order the keys 'hostName' and 'userName', which are
     presumed to appear as keys in %$select.

     The key 'someData' is ignored.

     =head1 METHOD select($sql, $sep)

   It croaks if it can't prepare() and execute() the given SQL.

   $sep is optional. It defaults to $;.

   It returns a reference to a hash, which hold the results of the select.

   The keys of the hash are the names of the fields, which can be used for
column headings.

   The values of the hash are the values of the fields, which can be used
for the column data. The values in each column are, by default, separated
by Perl's $; variable.

     my($select) = $reporter -> select($sql);

   Warning: select() selects the whole table. Ideally we'd use
DBIx::Recordset to page thru the table, but I had too many problems with
various versions of DBIx::Recordset.

   If you have binary data containing $;, you *<must>* set $sep to
something else. Of course, with binary data, there may be no 'safe'
character (string) which does not appear in your data.

   Alternately, store your binary data in files, and put the file name or
URI in the database.

   The hash reference can be passed straight to hash2Table for conveting
into an HTML table. Eg:

     my($html) = $reporter -> hash2Table($select);
     print $html;

AUTHOR
======

   `DBIx::MSSQLReporter' was written by Ron Savage *<ron@savage.net.au>*
in 2000.

   Copyright &copy; 2000 Ron Savage.

   Source available from http://savage.net.au/Perl.html.

LICENCE
=======

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

interface to Oracle sequences via DBI.
**************************************

NAME
====

   DBIx::OracleSequence - interface to Oracle sequences via DBI.

DESCRIPTION
===========

   DBIx::OracleSequence is an object oriented interface to Oracle
Sequences via DBI.  A sequence is an Oracle database object from which
multiple users may generate unique integers. You might use sequences to
automatically generate primary key values.  See
http://technet.oracle.com/doc/server.815/a68003/01_03sch.htm#1203 for the
full story on Oracle sequences.  Note that you must register to access
this URL, but registration is free.

SYNOPSIS
========

     use DBIx::OracleSequence;

     $oracleDbh = DBI->connect("dbi:Oracle:SID", 'login', 'password');

     my $seq = new DBIx::OracleSequence($oracleDbh,'my_sequence_name');

     $seq->create();                 # create a new sequence with default parms
     $seq->incrementBy(5);           # alter the seq to increment by 5

     my $nextVal = $seq->nextval();  # get the next sequence value
     my $currval = $seq->currval();  # retrieve the current sequence value
     $seq->print();                  # print information about the sequence

     # connect to a sequence that already exists
     my $seq2 = new DBIx::OracleSequence($oracleDbh,'preexisting_seq');
     $seq2->print();
     $seq2->drop();                  # get rid of it

     # see if sequence name 'foo' exists
     my $seq3 = new DBIx::OracleSequence($oracleDbh);
     die "Doesn't exist!\n" unless $seq3->sequenceNameExists('foo');
     $seq3->name('foo');             # attach to it
     $seq3->print;

NOTE
====

   The constructor is lazy, so if you want to alter the defaults for a
sequence, you need to use the maxvalue(), cache(), incrementBy(), etc.
methods after constructing your sequence.

   You can access an existing Oracle sequence by calling the constructor
with the existing sequence name as the second parameter.  To create a new
sequence, call the constructor with your new sequence name as the second
parameter, then call the create() method.

   The OracleSequence object holds no state about the Oracle sequence
(well, except for its name.) Instead it just serves as a passthrough to
the Oracle DDL to create, drop, and set and get information about a
sequence.

METHODS
=======

     new($dbh,$S) - construct a new sequence with name $S

     new($dbh) - construct a new sequence without naming it yet

     name($S) - set the sequence name

     name() - get the sequence name

     create() - create a new sequence.  Must have already called new().
     Sequence will start with 1.

     create($N) - create a new sequence.  Must have already called new().
     Sequence will start with $N

     currval() - return the current sequence value.  Note that for a brand
     new sequence, Oracle requires one reference to nextval before currval
     is valid.

     nextval() - return the next sequence value

     reset() - drop and recreate the sequence with default parms

     incrementBy($N) - alter sequence to increment by $N

     incrementBy() - return the current sequence's INCREMENT_BY value

     maxvalue($N) - alter sequence setting maxvalue to $N

     maxvalue() - return the current sequence's maxvalue

     minvalue($N) - alter sequence setting minvalue to $N

     minvalue() - return the current sequence's minvalue

     cache($N) - alter sequence to cache the next $N values

     cache() - return the current sequence's cache size

     nocache() - alter sequence to not cache values

     cycle('Y')/cycle('N') - alter sequence to cycle/not cycle after
     reaching maxvalue instead of returning an error.  Note that
     cycle('N') and nocycle() are equivalent.

     cycle() - return the current sequence's cycle flag

     nocycle() - alter sequence to return an error after reaching maxvalue
     instead of cycling

     order('Y')/order('N') - alter sequence to guarantee/not guarantee
     that sequence numbers are generated in the order of their request.
     Note that order('N') and noorder() are equivalent.

     order() - return current sequence's order flag

     noorder() - alter sequence to not guarantee that sequence numbers are
     generated in order of request

     sequenceNameExists() - return 0 if current sequence's name does not
     already exist as a sequence name, non-zero if it does

     sequenceNameExists($S) - return 0 if $S does not exist as a sequence
     name, non-zero if it does

     getSequencesAref() - return an arrayRef of all existing sequence
     names in the current schema

     printSequences() - print all existing sequence names in the current
     schema

     info() - return a string containing information about the sequence

     print() - print a string containing information about the sequence

     drop() - drop the sequence

COPYRIGHT
=========

   Copyright (c) 1999 Doug Bloebaum. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

AUTHOR
======

   Doug Bloebaum <bloebaum@dma.org>

Allows you to create a global password file for DB passwords
************************************************************

NAME
====

   DBIx::Password - Allows you to create a global password file for DB
passwords

SYNOPSIS
========

     use DBIx::Password;
     my $dbh = DBIx::Password->connect($user);
     my $dbh = DBIx::Password->connect_cached($user);
     $dbh->getDriver;
     DBIx::Password::getDriver($user);
     DBIx::Password::checkVirtualUser($user);

DESCRIPTION
===========

   Don't you hate keeping track of database passwords and such throughout
your scripts? How about the problem of changing those passwords on a mass
scale? This module is one possible solution. When you go to build this
module it will ask you to create virtual users.  For each user you need to
specify the database module to use, the database connect string, the
username and the password. You will be prompted to give a name to this
virtual user.  You can add as many as you like.

   I would recommend that if you are only using this with web applications
that you change the final permissions on this package after it is
installed in site_perl such that only the webserver can read it.

   A method called getDriver has been added so that you can determine what
driver is being used (handy for working out database indepence issues).

   If you want to find out if the virtual user is valid, you can call the
class method checkVirtualUser().  It returns true (1) if the username is
valid, and zero if not.

   Once your are done you can use the connect method (or the connect_cache
method) that comes with DBIx-Password and just specify one of the virtual
users you defined while making the module.

   BTW I learned the bless hack that is used from Apache::DBI so some
credit should go to the authors of that module.  This is a rewrite of the
module Tangent::DB that I did for slashcode.

   Hope you enjoy it.

INSTALL
=======

   Basically:

   perl Makefile.PL

   make

   make test

   make install

   Be sure to answer the questions as you make the module

HOME
====

   To find out more information look at:
http://www.tangent.org/DBIx-Password/

AUTHOR
======

   Brian Aker, brian@tangent.org

SEE ALSO
========

   perl(1). DBI(3).

DBI query profiler   Version 1.0
********************************

NAME
====

     DBIx::Profile - DBI query profiler
     Version 1.0

     Copyright (c) 1999,2000 Jeff Lathan, Kerry Clendinning.
     All rights reserved.

     This program is free software; you can redistribute it and/or modify it
     under the same terms as Perl itself.

SYNOPSIS
========

     use DBIx::Profile; or "perl -MDBIx::Profile <program>"
     use DBI;
     $dbh->printProfile();

DESCRIPTION
===========

     DBIx::Profile is a quick and easy, and mostly transparent, profiler
     for scripts using DBI.  It collects information on the query
     level, and keeps track of first, failed, normal, and total amounts
     (count, wall clock, cput time) for each function on the query.

     NOTE: DBIx::Profile use Time::HiRes to clock the wall time and
     the old standby times() to clock the cpu time.  The cpu time is
     pretty coarse.

     DBIx::Profile can also trace the execution of queries.  It will print
     a timestamp and the query that was called.  This is optional, and
     occurs only when the environment variable DBIXPROFILETRACE is set
     to 1. (ex: (bash) export DBIXPROFILETRACE=1).

     Not all DBI methods are profiled at this time.
     Except for replacing the existing "use" and "connect" statements,
     DBIx::Profile allows DBI functions to be called as usual on handles.

     Prints information to STDERR, prefaced with the pid.

RECIPE
======

     1) Add "use DBIx::Profile" or execute "perl -MDBIx::Profile <program>"
     2) Optional: add $dbh->printProfile (will execute during
        disconnect otherwise)
     3) Run code
     4) Data output will happen at printProfile or $dbh->disconnect;

METHODS
=======

     printProfile
        $dbh->printProfile();

     Will print out the data collected.
     If this is not called before disconnect, disconnect will call
     printProfile.

     setLogFile
        $dbh->setLogFile("ProfileOutput.txt");

     Will save all output to the file.

AUTHORS
=======

     Jeff Lathan, lathan@pobox.com
     Kerry Clendinning, kerry@deja.com

     Aaron Lee, aaron@pointx.org
     Michael G Schwern, schwern@pobox.com

SEE ALSO
========

     L<perl(1)>, L<DBI>

talk SQL by using Perl data structures
**************************************

NAME
====

   DBIx::Renderer - talk SQL by using Perl data structures

SYNOPSIS
========

     use DBIx::Renderer ':all';

     # mandatory name
     use constant TYPE_MANDNAME => ( VARCHAR(255), NOTNULL );

     my $struct = [
     	category => [
     		id        => { TYPE_ID },
     		name      => { TYPE_MANDNAME },
     		parent_id => { INT4, INDEX },
     	    ],
     ];

     my $renderer = DBIx::Renderer::get_renderer('Postgres');
     print $renderer->create_schema($struct);

DESCRIPTION
===========

   I got fed up with having to write different variants of SQL for
different database engines. Also, I was looking for a way to specify a
schema in Perl. The idea is that you construct data structures which are
then rendered into the type of SQL appropriate for the target database
server. Along the way we can make some optimizations and customizations,
such as using database-specific features. For exmaple, we might make use
of Postgres' array data types, but render them into weak relations for
other servers.

   Also, outputting the schema in XML might be useful.

EXPORTS
=======

:all
     Exports all the `DBIx::Renderer::Constants' constants and functions,
     see its manpage for details.

FUNCTIONS
=========

get_renderer($name)
     Requests construction of a specific DBI renderer. The renderer is
     constructed by called a new() constructor on the package
     `DBIx::Renderer::$name'.

TODO
====

test.pl
     Write test cases.

Renderers
     Extend with renderers for other databases, also have an XML renderer.

Specify relationships
     Allow specification of weak relations or, in fact, any sort of
     relations and have the necessary tables created automatically. This
     would be the first step in integrating it with something like
     `Class::DBI'.

BUGS
====

   None known so far. If you find any bugs or oddities, please do inform
the author.

AUTHOR
======

   Marcel GrE<uuml>nauer <marcel@codewerk.com>

COPYRIGHT
=========

   Copyright 2001 Marcel GrE<uuml>nauer. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1), DBI(3pm).

base class for DBI renderers
****************************

NAME
====

   DBIx::Renderer::Base - base class for DBI renderers

SYNOPSIS
========

     package DBIx::Renderer::MyRenderer;
     use base 'DBIx::Renderer::Base;

DESCRIPTION
===========

   This base class for DBI renderers defines some general mechanisms that
might be of use to actual renderers. It's not required that a specific
renderer subclasses this class, but it does need to support the renderer
API (which hasn't been formalized).

METHODS
=======

new
     Constructs the renderer object and returns it.

_init
     Object initialization. Does nothing in this class, but is called by
     new(), so subclasses can override this method.

create_index($indexname, $tablename, @fields)
     Returns the SQL necessary to create an index called `$indexname' on
     table `$tablename' for the specified fields. An example might be

          CREATE INDEX product_idx ON product (title);

create_table($tablename, $tabledef)
     Returns the SQL necessary to create a table called `$tablename' using
     field definitions given in the array reference `$tabledef'. Each
     field definition is a hash with the fieldname being the key and the
     field specification being the value. The field specification, in turn,
     is a reference to an array consisting of attributes. The attributes
     are themselves hashes with the key being the attribute name (e.g.,
     'int4', 'bool', 'index', 'unique') and the value being the attribute
     parameters (e.g. the size of varchar fields, or an id for grouping
     index fields).

     Instead of saying "hashes", I should really say key-value pairs, since
     they are stored in a list. But they are interpreted as hashes.

     All this sounds a bit abstract, so maybe looking at that data
     structure helps. This has been produced with Data::Dumper but rolled
     into hashes and lined up to make it more obvious what's going on.

          use DBIx::Renderer ':all';

          # mandatory name
          use constant TYPE_MANDNAME => ( VARCHAR(255), NOTNULL );

          my $struct = [
          	    product => [
          		    id         => { TYPE_ID },
          		    name       => { TYPE_MANDNAME, INDEX },
          		    short_desc => { TEXT },
          		    long_desc  => { TEXT },
          		    image      => { VARCHAR(255) },
          		],
          ];

     constructs a structure looking like this:

          product => [
            id => {
                'NOTNULL' => 1,
                'type'    => 'INT4',
                'PK'      => 1
              },
            name => {
                'NOTNULL' => 1,
                'size'    => 255,
                'INDEX'   => 1,
                'type'    => 'VARCHAR'
              },
            short_desc => {
                'type'    => 'TEXT'
              },
            long_desc => {
                'type'    => 'TEXT'
              },
            image => {
                'size'    => 255,
                'type'    => 'VARCHAR'
              }
          ];

create_schema($schema)
     Constructs all SQL commands necessary to create the specified database
     schema. $schema is an array reference consisting of table definitions
     as shown above. The method then calls `create_table' and create_index
     to generate the SQL and returns the string.

get_type_name($coldef)
     Helper method that returns this SQL version's name for the type
     specified in the column definition.

find_fields($tabledef, $wanted)
     Helper method that searches the given table definition for fields
     whose definition have the `$wanted' attribute. For example, to find
     all primary key fields of a table, use

          @pk_fields = $self->find_fields($tabledef, 'PK');

get_pk_fields($tabledef)
     Helper method that returns a list of primary key fields for the given
     table definition.

get_index_fields($tabledef)
     Helper method that returns a list of indexed fields for the given
     table definition.

get_attr_names($coldef)
     Returns the SQL corresponding to a field's specification.

     For example, the following field definition

          name => {
              'size'  => 255,
              'type'  => 'VARCHAR'
              'UNIQUE'=> 1,
            }

     might return

          VARCHAR(255) UNIQUE

get_attr($coldef)
     Return a field's attributes by scanning the `$coldef' for attributes
     as defined in `DBIx::Renderer::Constants'. The term 'attributes' is
     used here to mean things like 'NOTNULL', 'UNIQUE', 'DEFAULT', but not
     data types or whether the field is a primary key or indexed.

get_const_name($const, @args)
     This method takes a constant as defined in `DBIx::Renderer::Constants'
     and an optional list of arguments (e.g., a varchar has the size as its
     argument) and returns the appropriate name for this SQL version. The
     default method implemented in this class, for example, returns
     'VARCHAR(255)' when called as `get_const_name('VARCHAR', 255)'. Other
     SQL dialects may have a different name for it.

expand($l)
     Helper function (not a method) that takes a scalar and recursively
     expands array references to create a flat array reference, which it
     returns. If the scalar isn't an array reference to begin with, it just
     returns the scalar.

     This function is useful for constructing the structures mentioned
     above, since you can combine attributes by creating an array
     reference containing them, but then inserting this combination into a
     surrounding definition creates nested array references, so we use
     this function to flatten them. Check the source for details.

BUGS
====

   None known so far. If you find any bugs or oddities, please do inform
the author.

AUTHOR
======

   Marcel GrE<uuml>nauer <marcel@codewerk.com>

COPYRIGHT
=========

   Copyright 2001 Marcel GrE<uuml>nauer. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1), DBI(3pm), DBIx::Renderer(3pm), DBIx::Renderer::Constants(3pm).

constants for the DBI rendering framework
*****************************************

NAME
====

   DBIx::Renderer::Constants - constants for the DBI rendering framework

SYNOPSIS
========

     use DBIx::Renderer ':all';

     # mandatory name
     use constant TYPE_MANDNAME => ( VARCHAR(255), NOTNULL );

     my $struct = [
     	    category => [
     		    id        => { TYPE_ID },
     		    name      => { TYPE_MANDNAME },
     		    parent_id => { INT4, INDEX },
     		],
     ];

DESCRIPTION
===========

   This module defines a range of constants and helper functions for use
in writing and talking to DBI renderers. Typically you won't use this
module directly, but import ':all' from `DBIx::Renderer', which passes
this module's exports along.

EXPORTS
=======

   The following constants and functions are exported:

INT4 FLOAT4 TEXT BOOL TIMESTAMP
     Constants for those data types; specific DBI renderers can then decide
     how to render these constants in their SQL dialect. Actually they
     return a hash element consisting of the key 'type' and the actual
     constant as the value, so it doesn't make sense to specify more than
     one type; the last one specified wins.

CHAR($size) VARCHAR($size)
     These aren't actually constants but functions that take the size as a
     parameter, as shown in the synopsis. In addition to the 'type' hash
     key and its value, these functions also return a 'size' hash key and
     its value.

DEFAULT
     Like `CHAR' and `VARCHAR', this function returns a hash element with
     'DEFAULT' as its key (as every field can have only one default value)
     and the actual default as its value.

NOTNULL UNIQUE PK INDEX
     Defines constants for marking a field to be not nullable or to be
     unique, or for specifying that this field is a primary key or that it
     should be indexed. Per usual, these constants are a hash element with
     the constant's name as the key and 1 as its value.

TYPE_ID TYPE_FK
     These two are "complex" types; a TYPE_ID being a not-nullable primary
     key of type int4, and `TYPE_FK' being a notnullable int4 used as a
     foreign key into some other table.

get_types()
     Returns a list of all possible data types.

get_attrs()
     Returns a list of all possible field attributes (such as 'not
     nullable', 'unique value', 'has a default value').

get_markers()
     Returns a list of all field markers (such as 'primary key' or 'indexed
     field').

BUGS
====

   None known so far. If you find any bugs or oddities, please do inform
the author.

AUTHOR
======

   Marcel GrE<uuml>nauer <marcel@codewerk.com>

COPYRIGHT
=========

   Copyright 2001 Marcel GrE<uuml>nauer. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1), DBI(3pm), DBIx::Renderer(3pm).

DBI renderer for the Postgres SQL variant
*****************************************

NAME
====

   DBIx::Renderer::Postgres - DBI renderer for the Postgres SQL variant

SYNOPSIS
========

     use DBIx::Renderer ':all';
     my $struct = [ ... ];
     my $renderer = DBIx::Renderer::get_renderer('Postgres');
     print $renderer->create_schema($struct);

DESCRIPTION
===========

   This is the renderer for the Postgres dialect of SQL. There's actually
nothing to do, since `DBIx::Renderer::Base' is written to output Postgres'
version of SQL, which should be largely compatible with other SQL
versions; hence it all went into the base class.

BUGS
====

   None known so far. If you find any bugs or oddities, please do inform
the author.

AUTHOR
======

   Marcel GrE<uuml>nauer <marcel@codewerk.com>

COPYRIGHT
=========

   Copyright 2001 Marcel GrE<uuml>nauer. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1), DBI(3pm), DBIx::Renderer(3pm), DBIx::Renderer::Base(3pm).

An SQL Abstration layer for working with whole schemas
******************************************************

NAME
====

   DBIx::Schema - An SQL Abstration layer for working with whole schemas

SYNOPSIS
========

     use Schema;
     my $schema = DBIx::Schema->new({db=>'my_db',user=>'db_user',password=>'gigglesnark'});

   ***

     my $schema = DBIx::Schema->new($my_dbix_abstract_handle);

     $sth = $schema->select({table=>'product', where=>{'product.id'=>['<',6]}});
     while (my $row = $sth->fetchrow()) {
       print $row->{'name'}."\n";
       print $row->color->{'name'}."\n";
       print $row->{'price'}."\n";
       print $row->{'fish'}."\n";
     }

DESCRIPTION
===========

   Basically, this module lets you construct and use DBI-style statement
handles involving arbitrarily large schemas of related SQL tables without
concern about how exactly they're related; in essence, it builds the join
clauses for you, as necessary, from case to case. This can be a boon to
programs that want to knit together their own complex, relational SQL
queries on the fly; through the use of this module, if they know that some
tables are somehow related, even if they're two or more steps removed from
one another, they can simply name them, and start pulling out data
toot-suite.

   Of course, you will need to prepare your databases with some metadata
tables ahead of time in order for any of this to work. See the DATABASE
PREPARATION section below for more.

PREREQUISITES
=============

   You most certainly need DBI (as well as appropriate DBD modules for
your setup) for this to work.

   At this time, you also need Andrew Turner's DBIx::Abstract module. Much
of the user-level syntax for this module is inherited from it, so it's
good to be familiar with it, as well. This, like DBI and DBD, is available
from CPAN.

DATABASE PREPARATION
====================

   You will need to create three SQL tables in every database to which
you'd like to apply this module. These will act as a data dictionary for
all contents of the database. They will be called md_table, md_field, and
md_relation ('md' stands for 'metadata').

   You should have received a Perl script named md_rip.pl as part of the
distribution within which you got this module. Running it will create
these tables inside a given database if they're not already present, or
rebuild and repopulate them if they are. See its perldocs for more
information on its usage.

   Note that at this time you must name your each of tables' primary key
column 'id' for md_rip.pl to work, and you also must name columns relating
to them "${table_name}_id". So a column in the 'foo' table relating to the
'baz' table's primary key must be named 'baz_id'. Of course, it's not a
very complicated script, so you can hack it to behave differently. :)
Future versions will be more flexible.

METHODS
=======

Schema handle Methods
---------------------

new
     This is the schema object constructor. It requires, as an argument,
     either a DBIx::Abstract database handle object, or a hashref ready for
     feeding to DBIx::Abstract's 'connect' method.

connect
     An alias to the 'new' method. Takes the same arguments, returns the
     same thing.

select
     Returns a statement handle object, primed with an SQL query and ready
     for fetchrow calls (see below).

     This method takes one hashref as an argument. You must specify a table
     that you will be seleting from with the 'table' key.  You can specify
     multiple tables by using the 'tables' key instead.  You should only
     need to specify a 'tables' key if you are using a table that is
     invisible to schema (for instance, if it is in a scalar where).

     Optionally, you can have a 'where' key, which will be passed on to the
     underlying DBIx::Abstract object, so see that module. Note that this
     key's value needs only to hold the limit on results, the aspect of the
     where necessary to join tables will be generated by schema for you.

     For example:

          $sth = $schema->select({table=>'product', where=>{'product.id'=>['<',6]}});

     You can also specify a list of fields to be included beyond the normal
     ones.  This allows you to do some special things like:

          $sth = $schema->select({
              table=>'product',
              fields=>[
                  'lower(substring(product.name,1,1)) as 'product.letter',
                  'substring(product.description,1,50) as 'product.shortdesc',
                  ],
              where=>{'product.id'=>['<',6']},
              });

flush_cache
     The object keeps an internal cache to help it crawl through the
     database's relationships faster, but it doesn't check to see if the
     database's structure may have changed since the last time it performed
     a full crawl. Calling this method deletes the cache, forcing the
     object to reexamine the actual tables and start a new cache the next
     time it needs to know their structure.

Statement handle Methods
------------------------

fetchrow
     Returns a row object, or undef if no rows are available.

     As with DBI (and DBIx::Abstract), subsequent calls to fetchrow return
     the next row available to this statement handle, and undef once all
     rows have been exhausted (or no rows were available in the first
     place). Thus, a common code idiom is a while() loop, something like:

          while (my $row = $sth->fetchrow()) {
            # Do something with data from this row
            my $id = $row->{'id'};
            my $foo = $row->{'foo'};
            print "The value of foo for row $id is $foo. \n";
          }

rows
     Returns the number of rows returned from the SQL query within this
     statement handle.

key_table
     Returns, as a string, the name of the handle's key table.

Row objects
-----------

   Row object methods are special; see below.

sth
     Returns the statement handle from which this row emerged.

   Row objects don't have any predefined methods (except for 'sth'). You
can fetch data from them through directly accessing their instance
variables (hash keys), one of which will exist for each column of the row.

   For example, if a row represented with object $row has a 'foo' column,
that column's value is available through $row->{'foo'}.

   You can also pull additional statement handles out of a row by invoking
them as methods; an AUTOLOAD method inside the row object will take care
of the rest for you, and return a statement handle primed with the named
table as the key table, and with a where clause identical to that of the
row's statement handle, *with the addition of* a phrase requiring that the
current key table's id field match this row's value of same.

   For example:

     # I already have a $schema object defined.
     # I'll make a simple statement handle.

     $sth = $schema->select({table=>'product', where=>{'product.price'=>['<',6]}});
     # OK, $sth is now primed to return all products costing less than
     # $6.00.

     while (my $product_row = $sth->fetchrow) {
       print "I am on product ".$product_row->{'name'}."\n";
       # Let's say I have a many-to-many relationship in my schema that
       # allows products to exist in any number of categories. I want to
       # display all categories to which this product belongs. The current
       # statement handle doesn't know or care about categories, so it's
       # time to pull out a new one.
       if ($product_row->category->rows) {
         print "It is in the following categories:\n";
         while (my $cat_row = $product_row->category->fetchrow) {
           print $cat_row->{'name'}."\n";
         }
       } else {
         print "It is not in any category.\n";
     }

CAVEATS
=======

   I find the row object as it now stands a little sketchy due to the fact
that it's essentially user-definable, since its instance variables and
legal method names will depend on the nature of the data fetched from its
statement handle. This requires that its actual methods, 'AUTOLOAD' and
'sth' (and whatever might be added in the future) be reserved words. So,
for now, don't name your tables after the Row class's methods. (Not that
you'd want to, since they'd make pretty lousy table names, in my humble
opinion)

TODO
====

   It seems to warn about 'Unknown where piece' a bit too often, and
unnecessarily.

   The format of the data dictionaries needs to be far more configurable
than it now is.

BUGS
====

   This software is quite young, having received testing with only a
handful of database systems and Perl versions, and having only a few users
at the time of this writing (though it is in use in a production
environment). The author welcomes bug reports and other feedback at the
email address listed below.

AUTHOR
======

   Jason McIntosh <jmac@jmac.org>

HOMEPAGE
========

   http://www.jmac.org/projects/DBIx-Schema/

VERSION
=======

   This documentation corresponds with version 0.06 of DBIx::Schema.

COPYRIGHT
=========

   This software is copyright (c) 2000 Adelphia.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl extension for easy SQL SELECT Statement generation
*******************************************************

NAME
====

   DBIx::SearchBuilder - Perl extension for easy SQL SELECT Statement
generation

SYNOPSIS
========

     use DBIx::SearchBuilder;

     ...

DESCRIPTION
===========

CleanSlate
----------

   This completely erases all the data in the SearchBuilder object. It's
useful if a subclass is doing funky stuff to keep track of a search

Next
----

   Returns the next row from the set as an object of the type defined by
sub NewItem.  When the complete set has been iterated through, returns
undef and resets the search such that the following call to Next will
start over with the first item retrieved from the database.

GotoFirstItem
-------------

   Starts the recordset counter over from the first item. the next time
you call Next, you'll get the first item returned by the database, as if
you'd just started iterating through the result set.

GotoItem
--------

   Takes an integer, n.  Sets the record counter to n. the next time you
call Next, you'll get the nth item.

First
-----

   Returns the first item

ItemsArrayRef
-------------

   Return a refernece to an array containing all objects found by this
search.

NewItem
-------

     NewItem must be subclassed. It is used by DBIx::SearchBuilder to create record
     objects for each row returned from the database.

RedoSearch
----------

   Takes no arguments.  Tells DBIx::SearchBuilder that the next time it's
asked for a record, it should requery the database

UnLimit
-------

   UnLimit clears all restrictions and causes this object to return all
rows in the primary table.

Limit
-----

   Limit takes a paramhash.

   # TABLE can be set to something different than this table if a join is
# wanted (that means we can't do recursive joins as for now).  Unless

   # ALIAS is set, the join criterias will be taken from EXT_LINKFIELD #
and INT_LINKFIELD and added to the criterias.  If ALIAS is set, new #
criterias about the foreign table will be added.

   # VALUE should always be set and will always be quoted.

   # IMO (TobiX) we # shouldn't use quoted values, we should rather use
placeholders and # pass the arguments when executing the statement.  This
will also # allow us to alter limits and reexecute the search with a low
cost by # keeping the statement handler.

   # ENTRYAGGREGATOR can be AND or OR (or anything else valid to aggregate
two clauses in SQL

   # OPERATOR is whatever should be putted in between the FIELD and the #
VALUE.

ShowRestrictions
----------------

   Returns the current object's proposed WHERE clause.

   Deprecated.

ImportRestrictions
------------------

   Replaces the current object's WHERE clause with the string passed as
its argument.

   Deprecated

Orderby PARAMHASH
-----------------

   Orders the returned results by ALIAS.FIELD ORDER. (by default 'main.id
ASC')

   Takes a paramhash of ALIAS, FIELD and ORDER.  ALIAS defaults to main
FIELD defaults to the primary key of the main table.  ORDER defaults to
ASC(ending).  DESC(ending) is also a valid value for OrderBy

_OrderClause
------------

   returns the ORDER BY clause for the search.

NewAlias
--------

   Takes the name of a table.  Returns the string of a new Alias for that
table, which can be used to Join tables or to Limit what gets found by a
search.

Join
----

   Join instructs DBIx::SearchBuilder to join two tables.  It takes a
param hash with keys ALIAS1, FIELD1, ALIAS2 and FIELD2.

   ALIAS1 and ALIAS2 are column aliases obtained from $self->NewAlias or a
$self->Limit FIELD1 and FIELD2 are the fields in ALIAS1 and ALIAS2 that
should be linked, respectively.

RowsPerPage
-----------

   Limits the number of rows returned by the database.  Optionally, takes
an integer which restricts the # of rows returned in a result Returns the
number of rows the database should display.

FirstRow
--------

   Get or set the first row of the result set the database should return.
Takes an optional single integer argrument. Returns the currently set
integer first row that the database should return.

_ItemsCounter
-------------

   Returns the current position in the record set.

Count
-----

   Returns the number of records in the set.

IsLast
------

   Returns true if the current row is the last record in the set.

AUTHOR
======

   Jesse Vincent, jesse@fsck.com

SEE ALSO
========

   DBIx::SearchBuilder::Handle, DBIx::SearchBuilder::Record, perl(1).

Perl extension which is a generic DBI handle
********************************************

NAME
====

   DBIx::SearchBuilder::Handle - Perl extension which is a generic DBI
handle

SYNOPSIS
========

     use DBIx::SearchBuilder::Handle;

     my $Handle = DBIx::SearchBuilder::Handle->new();
     $Handle->Connect( Driver => 'mysql',
     		   Database => 'dbname',
     		   Host => 'hostname',
     		   User => 'dbuser',
     		   Password => 'dbpassword');

DESCRIPTION
===========

   Jesse's a slacker.

   Blah blah blah.

AUTHOR
======

   Jesse Vincent, jesse@fsck.com

   =cut

   # }}}

   # {{{ sub new

new
---

   Generic constructor

Connect PARAMHASH: Driver, Database, Host, User, Password
---------------------------------------------------------

   Takes a paramhash and connects to your DBI datasource.

RaiseError [MODE]
-----------------

   Turns on the Database Handle's RaiseError attribute.

PrintError [MODE]
-----------------

   Turns on the Database Handle's PrintError attribute.

Disconnect
----------

   Disconnect from your DBI datasource

dbh [HANDLE]
------------

   Return the current DBI handle. If we're handed a parameter, make the
database handle that.

UpdateRecordValue
-----------------

   Takes a hash with fields: Table, Column, Value PrimaryKeys, and
IsSqlFunction.  Table, and Column should be obvious, Value is where you
set the new value you want the column to have. The primary_keys field
should be the lvalue of DBIx::SearchBuilder::Record::PrimaryKeys().
Finally sql_function_p is set when the Value is a SQL function.  For
example, you might have ('Value'=>'PASSWORD(string)'), by setting
sql_function_p that string will be inserted into the query directly rather
then as a binding.

UpdateTableValue TABLE COLUMN NEW_VALUE RECORD_ID IS_SQL
--------------------------------------------------------

   Update column COLUMN of table TABLE where the record id = RECORD_ID.
if IS_SQL is set, don\'t quote the NEW_VALUE

SimpleQuery QUERY_STRING, [ BIND_VALUE, ... ]
---------------------------------------------

   Execute the SQL string specified in QUERY_STRING

FetchResult QUERY, [ BIND_VALUE, ... ]
--------------------------------------

   Takes a SELECT query as a string, along with an array of BIND_VALUEs
Returns the first row as an array

SEE ALSO
========

   perl(1), see DBIx/SearchBuilder,

Connect PARAMHASH: Driver, Database, Host, User, Password
---------------------------------------------------------

   Takes a paramhash and connects to your DBI datasource.

Insert
------

   Takes a table name as the first argument and assumes that the rest of
the arguments are an array of key-value pairs to be inserted.

an oracle specific Handle object
********************************

NAME
====

     DBIx::SearchBuilder::Handle::Oracle -- an oracle specific Handle object

SYNOPSIS
========

     =head1 DESCRIPTION

AUTHOR
======

   Jesse Vincent, jesse@fsck.com

SEE ALSO
========

   perl(1), DBIx::SearchBuilder

Insert
------

   Takes a table name as the first argument and assumes that the rest of
the arguments are an array of key-value pairs to be inserted.

Insert
------

   Takes a table name as the first argument and assumes that the rest of
the arguments are an array of key-value pairs to be inserted.

a mysql specific Handle object
******************************

NAME
====

     DBIx::SearchBuilder::Handle::mysql -- a mysql specific Handle object

SYNOPSIS
========

     =head1 DESCRIPTION

AUTHOR
======

   Jesse Vincent, jesse@fsck.com

SEE ALSO
========

   perl(1), DBIx::SearchBuilder

Perl extension for subclassing, so you can deal with a Record
*************************************************************

NAME
====

   DBIx::SearchBuilder::Record - Perl extension for subclassing, so you
can deal with a Record

SYNOPSIS
========

     module MyRecord;
     use DBIx::SearchBuilder::Record;
     @ISA = (DBIx::SearchBuilder::Record);

     sub _Init {
         my $self = shift;
         my $DBIxHandle = shift; # A DBIx::SearchBuilder::Handle::foo object for your database

     $self->_Handle($DBIxHandle);
     $self->Table("Users");
     return($self->SUPER::_Init(@_));
       }

       #Preferred and most efficient way to specify fields attributes in a derived
       #class, used by the autoloader to construct Attrib and SetAttrib methods.

     # read: calling $Object->Foo will return the value of this record's Foo column  # write: calling $Object->SetFoo with a single value will set Foo's value in
     #        both the loaded object and the database

     sub _ClassAccessible {
       {
     	 Tofu  => { 'read'=>1, 'write'=>1 },
            Maz   => { 'auto'=>1, },
            Roo   => { 'read'=>1, 'auto'=>1, 'public'=>1, },
       };
     }

     # specifying an _Accessible subroutine in a derived class is depriciated.
     # only '/' and ',' delimiters work, not full regexes

     sub _Accessible  {
         my $self = shift;
         my %Cols = (
     		  id => 'read', # id is an immutable primary key
     		  Username => 'read/write', #read/write.
     		  Password => 'write', # password. write only. see sub IsPassword
     		  Created => 'read'  # A created date. read-only
     		 );
         return $self->SUPER::_Accessible(@_, %Cols);
     }

     # A subroutine to check a user's password without ever returning the current password
     #For security purposes, we didn't expose the Password method above

     sub IsPassword {
         my $self = shift;
         my $try = shift;

         # note two __s in __Value.  Subclasses may muck with _Value, but they should
         # never touch __Value

     if ($try eq $self->__Value('Password')) {
     	  return (1);
     }
     else {
     	  return (undef);
     }

       }

     # Override DBIx::SearchBuilder::Create to do some checking on create
     sub Create {
         my $self = shift;
         my %fields = ( UserId => undef,
     		    Password => 'default', #Set a default password
     		    @_);

         #Make sure a userid is specified
         unless ($fields{'UserId'}) {
     	 die "No userid specified.";
         }

         #Get DBIx::SearchBuilder::Record->Create to do the real work
         return ($self->SUPER::Create( UserId => $fields{'UserId'},
     				   Password => $fields{'Password'},
     				   Created => time ));
     }

DESCRIPTION
===========

   DBIx::SearchBuilder::Record is designed to work with
DBIx::SearchBuilder.

What is it trying to do.
------------------------

   DBIx::SB::Record abstracts the agony of writing the common and generally
simple SQL statements needed to serialize and De-serialize an object to the
database.  In a traditional system, you would define various methods on
your object 'create', 'find', 'modify', and 'delete' being the most common.
In each method you would have a SQL statement like:

     select * from table where value='blah';

   If you wanted to control what data a user could modify, you would have
to do some special magic to make accessors do the right thing. Etc.  The
problem with this approach is that in a majority of the cases, the SQL is
incredibly simple and the code from one method/object to the next was
basically the same.

   <trumpets>

   Enter, DBIx::SearchBuilder::Record.

   With::Record, you can in the simple case, remove all of that code and
replace it by defining two methods and inheriting some code.  Its pretty
simple, and incredibly powerful.  For more complex cases, you can, gasp,
do more complicated things by overriding certain methods.  Lets stick with
the simple case for now.

   The two methods in question are '_Init' and '_ClassAccessible', all they
really do are define some values and send you on your way.  As you might
have guessed the '_' suggests that these are private methods, they are.
They will get called by your record objects constructor.

     o. '_Init'
        Defines what table we are talking about, and set a variable to store
        the database handle.

     o. '_ClassAccessible
        Defines what operations may be performed on various data selected
        from the database.  For example you can define fields to be mutable,
        or immutable, there are a few other options but I don't understand
        what they do at this time.

   And really, thats it.  So lets have some sample code, but first the
example code makes the following assumptions:

     The database is 'postgres',
     The host is 'reason',
     The login name is 'mhat',
     The database is called 'example',
     The table is called 'simple',
     The table looks like so:

     id     integer     not NULL,   primary_key(id),
     foo    varchar(10),
     bar    varchar(10)

   [file:///example/Simple.pm]

   000: package Simple; 001: use DBIx::SearchBuilder::Record; 002: @ISA =
(DBIx::SearchBuilder::Record);

   This should be pretty obvious, name the package, import ::Record and
then define ourself as a subclass of ::Record.

   003: 004: sub _Init { 005:   my $this   = shift; 006:   my $handle =
shift; 007: 008:   $this->_Handle($handle); 009:   $this->Table("Simple");
010: 011:   return ($this); 012: }

   Here we set our handle and table name, while its not obvious so far,
we'll see later that $handle (line: 006) gets passed via ::Record::new
when a new instance is created.  Thats actually an important concept, the
DB handle is not bound to a single object but rather, its shared across
objects.

   013: 014: sub _ClassAccessible { 015:   { 016:     Foo => { 'read'  =>
1 }, 017:     Bar => { 'read'  => 1, 'write' => 1  }, 018:     Id  => {
'read'  => 1 } 019:   }; 020: }

   What's happening might be obvious, but just in case this method is
going to return a reference to a hash. That hash is where our columns are
defined, as well as what type of operations are acceptable.

   021: 022: 1;

   Its perl, duh.

   Now, on to the code that will actually *do* something with this object.

   [file://examples/ex.pl] 000: use DBIx::SearchBuilder::Handle; 001: use
Simple;

   Use two packages, the first is where I get the DB handle from, the
latter is the object I just created.

   002: 003: my $handle = DBIx::SearchBuilder::Handle->new(); 004:
$handle->Connect( 'Driver'   => 'Pg', 005: 		          'Database' =>
'test', 006: 		          'Host'     => 'reason', 007:
  'User'     => 'mhat', 008: 		          'Password' => ");

   Creates a new DBIx::SB::Handle, and then connects to the database using
that handle.  Pretty straight forward, the password " is what I use when
there is no password.  I could probably leave it blank, but I find it to
be more clear to define it.

   009: 010: my $s = new Simple($handle); 011: 012: $s->LoadById(1);

   LoadById is one of four 'LoadBy' methods,  as the name suggests it
searches for an row in the database that has id='0'.  ::SearchBuilder has,
what I think is a bug, in that it current requires there to be an id
field. More reasonably it also assumes that the id field is unique.
LoadById($id) will do undefined things if there is >1 row with the same id.

   In addition to LoadById, we also have:

     o. LoadByCol
        Takes two arguments, a column name and a value.  Again, it will do
        undefined things if you use non-unique things.

     o. LoadByCols
        Takes a hash of columns=>values and returns the *first* to match.
        First is probably lossy across databases vendors.

     o. LoadFromHash
        Populates this record with data from a DBIx::SearchBuilder.  I'm
        currently assuming that DBIx::SearchBuilder is what we use in
        cases where we expect > 1 record.  More on this later.

   Now that we have a populated object, we should do something with it!
::Record automagically generates accessos and mutators for us, so all we
need to do is call the methods.  Accessors are named <Field>(), and
Mutators are named Set<Field>($).  On to the example, just appending this
to the code from the last example.

   013: 014: print "ID  : ", $s->Id(),  "\n"; 015: print "Foo : ",
$s->Foo(), "\n"; 016: print "Bar : ", $s->Bar(), "\n";

   Thats all you have to to get the data, now to change the data!

   017: 018: $s->SetBar('NewBar');

   Pretty simple! Thats really all there is to it.  Set<Field>($) returns
a boolean and a string describing the problem.  Lets look at an example of
what will happen if we try to set a 'Id' which we previously defined as
read only.

   019: my ($res, $str) = $s->SetId('2'); 020: if (! $res) { 021:   ##
Print the error!  022:   print "$str\n"; 023: }

   The output will be:   >> Immutable field

   Currently Set<Field> updates the data in the database as soon as you
call it.  In the future I hope to extend ::Record to better support
transactional operations, such that updates will only happen when "you"
say so.

   Finally, adding a removing records from the database.  ::Record
provides a Create method which simply takes a hash of key=>value pairs.
The keys exactly	map to database fields.

   023: ## Get a new record object.  024: $s1 = new Simple($handle); 025:
$s1->Create('Id'  => 4, 026: 	         'Foo' => 'Foooooo', 027:
    'Bar' => 'Barrrrr');

   Poof! A new row in the database has been created!  Now lets delete the
object!

   028: 029: $s1 = undef; 030: $s1 = new Simple($handle); 031:
$s1->LoadById(4); 032: $s1->Delete();

   And its gone.

   For simple use, thats more or less all there is to it.  The next part of
this HowTo will discuss using container classes,  overloading, and what
ever else I think of.

METHODS
=======

id
--

   Returns this row's primary key.

PrimaryKeys
-----------

   Matt Knopp owes docs for this function.

_AccessibleLoad COLUMN => OPERATIONS, ...
-----------------------------------------

_ClassAccessible HASHREF
------------------------

   Preferred and most efficient way to specify fields attributes in a
derived class.

     sub _ClassAccessible {
       {
     	 Tofu  => { 'read'=>1, 'write'=>1 },
            Maz   => { 'auto'=>1, },
            Roo   => { 'read'=>1, 'auto'=>1, 'public'=>1, },
       };
     }

__Value
-------

   Takes a field name and returns that field's value. Subclasses should
never overrid __Value.

_Value
------

   _Value takes a single column name and returns that column's value for
this row.  Subclasses can override _Value to insert custom access control.

_Set
----

   _Set takes a single column name and a single unquoted value.  It
updates both the in-memory value of this column and the in-database copy.
Subclasses can override _Set to insert custom access control.

Load
----

   Takes a single argument, $id. Calls LoadByRow to retrieve the row whose
primary key is $id

LoadByCol
---------

   Takes two arguments, a column and a value. The column can be any table
column which contains unique values.  Behavior when using a non-unique
value is undefined

LoadByCols
----------

   Takes a hash of columns and values. Loads the first record that matches
all keys.

LoadById
--------

   Loads a record by its primary key.  TODO: BUG: Column name is currently
hard coded to 'id'

LoadFromHash
------------

     Takes a hashref, such as created by DBIx::SearchBuilder and populates this record's
     loaded values hash.

Create
------

   Takes an array of key-value pairs and drops any keys that aren't known
as columns for this recordtype

Table
-----

   Returns or sets the name of the current Table

_Handle
-------

   Returns or sets the current DBIx::SearchBuilder::Handle object

Private: _DownCaseValuesHash
----------------------------

   Takes no parameters and returns no arguments.  This private routine
iterates through $self->{'values'} and makes sure that all keys are
lowercase.

AUTHOR
======

   Jesse Vincent, <jesse@fsck.com>

   Enhancements by Ivan Kohler, <ivan-rt@420.am>

   Docs by Matt Knopp <mhat@netlag.com>

SEE ALSO
========

   perl(1).

Access to SQL database via template query.
******************************************

NAME
====

   DBIx::SearchProfiles - Access to SQL database via template query.

SYNOPSIS
========

     use DBIx::SearchProfiles;

     my $DB = new DBIx::SearchProfiles( $dbh, $profiles);

     my $record  = $DB->record_get( "customer", 1024 );

     my $records = $DB->template_search( "cust_low_balance",
     					{ low_balance => 50 } );

     $DB->record_insert( "customer", $customer_data );

DESCRIPTION
===========

   DBIx::SearchProfiles is a module which wraps around a DBI database
handle and provides another way than raw SQL to access the database.  Its
aims is to take the SQL out of the code in well defined and documented
search profiles which has easier to maintain than embedded SQL all over
the application. Moreover, this decoupling of the application logic from
the SQL programming makes it possible to review the SQL by a DBA which
might not be a programmer. It may also makes the application's code more
obvious and clearer which is a Good Thing (tm)

ACCESS METHODS
==============

   The DBIx::SearchProfiles module offers three method of access to the
underlying database :

RAW SQL ACCESS
     This is the lowest level and is thin wrapper around the underlying DBI
     methods. The caller specifies the SQL statement and the params to use
     for the query.

          Ex: $DB->sql_insert( "INSERT INTO customer (?,?,?)", @params );

RECORD ACCESS
     This class of access generates automatically the SQL statement to use
     based on the fields present in the table and the fields passed as
     parameters. This type of access is very handy for insert or update
     where you don't want to specify all the fields.

          Ex: $DB->record_insert( "customer", $customer_data );

     Where *customer* is the name of the profile definition to use and
     $customer_data is a reference to an hash which contains the customer's
     infos.

TEMPLATE ACCESS
     This is the most interesting type of access. The problem with the
     previous type of access is that it is convenivent and efficient for
     simple query but when you want something more complex it fails
     miserably. (Say one where you want other operators than =, and where
     you are joining 6 tables together) In the template based access, you
     use a template query in which the parameters will be substituted. The
     query can be as complex as you want and the parameter subsitutions
     also.

          Ex: $DB->template_search( "troublesome_customers", $search_spec );

   Each class of access provides 5 methods to access the data. (SQL has an
extra one, but its the exception) :

   * The *_get methods ( `sql_get()', `record_get()' and `template_get()'
     ) will return only one record in the form of an hash reference. Each
     keys corresponds to one column of the table. (So two columns must not
     have the same name.)

   * The *_search methods (`sql_search()', `record_search()' and
     `template_search()') will return a reference to an array of hash.
     Each hash is a table row where the keys are the column's names.

     Also the `record_search()' and `template_search()' methods have
     support for limiting the number of rows returned and to results
     offset.  (1-50,51-100,etc).

   * The *_insert methods are for inserting one record in a table.

   * The *_update methods are for updating records in a table.

   * The *_delete methods are for deleting records from the table.

INITIALIZATION
==============

   To get a database search profiles handle, you use the new method.

     Ex: my $DB = new DBIx::SearchProfiles( $dsn, $profiles );

   The $dsn parameter can either be an already connected DBI handle or a
reference to an hash which contains three parameters DataSource, UserName
and Password which will be used to open one. Note that on destruction, the
connection will only be closed if the connection was established by the
DBIx::SearchProfiles modules.

   The $profiles parameter can either be a reference to an hash which
contains the search profiles, or the name of a file which will be
evaluated and that must return a reference to an hash which will contains
the search profiles. Note that whenever the search profiles' file changes
on disk, the profiles are reloaded.

DBI WRAPPER METHODS
===================

commit
------

   Simply call commit on the underlying DBI handle.

rollback
--------

   Simply call rollback on the underlying DBI handle.

PROFILE DEFINITIONS
===================

   A search profiles collection is a reference to an hash where each key
points ta profile definition. A search profile definition is an hash which
contains several elements which will be used to build query automatically.

   Here is an example profiles :

     {
     category	    =>
     	{
     	    query   => q{ SELECT id,category FROM category
     			  WHERE category_id = ? },
     	    params  => [ "category_id" ],
     	},
     product_srch    =>
       {
        query	    => q{ SELECT DISTINCT code,code_manu,category_id,category,
     				 manufacturer_id,manufacturer,
     				 price,description
     			  FROM products p ,manufacturer m ,category c
     			  WHERE ( ? = -1 OR c.id  = ? )    AND
     				( ? = -1 OR m.id  = ? )	   AND
     				category_id = c.id	   AND
     				manufacturer_id = m.id	   AND
     				( code = ? OR code_manu    = ?
     					   OR category     LIKE ?
     					   OR manufacturer LIKE ?
     					   OR description  LIKE ?
     				)
     			 },
        params	    => [ qw( category_id category_id manufacturer_id
     			     manufacturer_id
     			     search search search search search ) ],
        order	    => "category_id,manufacturer_id,code",
        defaults	    => { category_id => -1, manufacturer_id => -1 },
        limit	    => 25,
       },
     order_items	    =>
       {
        fields	 => [qw( quantity subtotal ) ],
        keys	 => [ qw( order_no code ) ],
        table	 => "order_items",
       },
     }

   In this example, you have a simple query profile (category), a complex
template search (product_srch) and an example of a profile for record based
access.

   Here is the meaning of the different fields :

table (RECORD ACCESS ONLY)
     The name of the table on which we will operate.

keys (RECORD ACCESS ONLY)
     A reference to an array which contains the name of the fields which
     are the primary key for the table.

fields (RECORD ACCESS ONLY)
     A reference to an array which contains the name of the fields which
     are not primary keys in the table.

defaults
     Reference to an hash of parameter defaults. This will be used to
     complete when no values are present.

limit
     Used by `record_search' and `template_search' as the default number
     of records to return at a time for this query.

max
     Used by `record_search' and `template_search' as the default maximum
     total number of records to return for a query.

order
     Used by `record_search' and `template_search' as the default ordering
     for the query.

query (TEMPLATE ACCESS ONLY)
     This is the query template. It should contains the SQL that will be
     executed with the standard DBI (?) placeholders embedded in it.

params (TEMPLATE ACCESS ONLY)
     A reference to an array which contains the name of the params that
     will be substituted in the template. There should be one element for
     every placeholder in the query.

SQL ACCESS METHODS
==================

sql_do ( $statement, @params );
-------------------------------

   Thin wrapper around DBI do method. The first argument is the SQL to be
executed and the remaining arguments are passed as params to the query.

sql_get ( $statement, @params );
--------------------------------

   This method will execute the SELECT query passed in the first argument
using the remaining parameters as placeholder substitutions.

   It returns an hash ref (or undef if the query didn't match any record)
corresponding to the first row returned.

sql_search ( $statement, @params );
-----------------------------------

   This method will execute the SELECT query passed in the first argument
using the remaining parameters as placeholder substitutions.

   It returns a reference to an array of hash.

sql_insert ( $statement, @params );
-----------------------------------

   This method will execute the INSERT query passed in the first argument
using the remaining parameters as placeholder substitutions.

   Return value is undefined.

sql_update ( $statement, @params );
-----------------------------------

   This method will execute the UPDATE query passed in the first argument
using the remaining parameters as placeholder substitutions.

   Return value is undefined.

sql_delete ( $statement, @params );
-----------------------------------

   This method will execute the DELETE query passed in the first argument
using the remaining parameters as placeholder substitutions.

   Return value is undefined.

RECORD BASED ACCESS
===================

record_get ( $name, params );
-----------------------------

   This method will return an hash reference to a record. The first
argument is the name of the profile where the table information will be
found. The params argument can either be :

ARRAY OR ARRAY REF
     Each element of the array is mapped to an element of the keys field
     of the profile. It is an error if the number of elements is different
     than the number of keys defined in the table.

HASH REF
     The key will be built by using the name of the keys as specified in
     the keys field of the profile, or by using the defaults hash if
     present.

     It is an error if some portion of the key is missing.

record_search ( $name, \%params );
----------------------------------

   This method will build a search on the table specified in the profile
$name. $params is a reference to an hash where each keys that is present
in the fields or keys of the profile will be used as a constraint in the
query. The test is for equality, if you want something more complex, use
`template_search'.

   There are a few magic parameters :

dbix_sp_order
     Will override the order clause of the query. If not present the order
     field of the profile will be used.

dbix_sp_limit
     Limit the number of records returned by the query. If not present the
     limit field of the profile will be used.

dbix_sp_max
     Set the maximum number of records that the query may fetch, this
     override the max field of the profile but cannot be set higher.

dbix_sp_start
     If there is a limit set for the query, this parameter will start
     returning records from that offset in the result. Offset is 0 indexed.

   The params argument is modified on return. Here is a list of the
modified elements :

dbix_sp_found
     The number of record returned.

dbix_sp_total
     The total number of record matching the query.

   Like all *_search methods `record_search' will return a reference to an
array of hash.

record_insert ( $name, \%params );
----------------------------------

   This method will insert a record in the table specified by the profile
$name. The params argument is a reference to an hash which contains the
record data to be inserted. The hash should contains one element for each
key specified in the keys field of the profile. Each elements in the
fields that is a valid table fields (as specified by the fields element of
the profile) will be inserted. Any elements specified defaults and not
present in the params hash will also be inserted.

   Return value is undefined.

record_update ( $name, \%params );
----------------------------------

   This method will update a record in the table specified by the profile
$name. The params argument is a reference to an hash which contains the
record data to be updated. The hash should contains one element for each
key specified in the keys field of the profile. Each elements in the
fields that is a valid table fields (as specified by the fields element of
the profile) will be updated. Any elements specified defaults and not
present in the params hash will also be updated.

   Return value is undefined.

record_delete ( $name, $keys );
-------------------------------

   This method will delete a record in the table specified by the profile
$name. The keys argument is a reference to an hash which contains the keys
to the record to delete. The hash should contains one element for each key
specified in the keys field of the profile.

   Return value is undefined.

TEMPLATE BASED ACCESS
=====================

   All of the `template_*' methods accepts two parameters, $name and
params. The $name parameter specified the profile to use as a template for
the operation (get,search,insert,update or delete). The other parameter is
used as substitutions for the placeholders of the template. Those
substitutions can be specified in three manners :

ARRAY OR ARRAY REF
     Each element of the array is mapped to an element of the params field
     of the profile. It is an error if the number of elements is different
     than the number of params defined in the profile.

HASH REF
     Each substitutions will be mapped to one of the element of the params
     hash in the order specified by the params element of the profile. If
     a params element isn't present, a default one will be used. (Either
     the value specified in the profile's defaults element or NULL).

template_get ( $name, params )
------------------------------

   This method will return an hash reference to a record using the profile
$name.

template_search ( $name, params )
---------------------------------

   This method will run a search using the query template specified in the
profile named $name and return the results in a reference to an array of
hashes.

   This methods accept the same magic parameters in the %params element as
the `record_search' method. It also modifies the same element in %params
as that method.

template_insert ( $name, params )
---------------------------------

   This method will insert a record according to the profile in $name.
Normal template substitutions will be used.

   Return value is undefined.

template_update ( $name, params )
---------------------------------

   This method will update records according to the profile $name and
using standard template's placholders substitutions semantics.

   Return value is the number of rows updated.

template_delete ( $name, params )
---------------------------------

   This method will delete records according to the template $name and
using regular template's placeholders substitutions semantics.

   Return value is the number of records deleted.

BUGS AND LIMITATIONS
====================

   Please report bugs, suggestions, patches and thanks to <bugs@iNsu.COM>.

   The search limitations and offset SQL generation is probably not
completely portable. It uses LIMIT and OFFSET which are maybe not
supported across SQL92 implementation. (PostgreSQL supports it so...)

   To find the number of records that will be returned by a query (in
*_search) we use `count(*)'. This could cause a number of problems.

AUTHOR
======

   Copyright (c) 1999 Francis J. Lacoste and iNsu Innovations Inc.  All
rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the terms as perl itself.

SEE ALSO
========

   DBIx::Recordset(3) DBI(3) DBIx::UserDB(3)

Class used to represent DBI database tables.
********************************************

NAME
====

   DBIx::Table - Class used to represent DBI database tables.

SYNOPSIS
========

To make it useful:
------------------

     package SUBCLASS;
     @ISA = qw(DBIx::Table);
     sub describe {
         my($self) = shift;
         $self->{'table'}       = $table_name;
         $self->{'unique_keys'} = [ [ $column, ... ], ... ];
         $self->{'columns'}     = { $col_name => { %col_options },
                                    [ ... ]
                                  };
       [ $self->{'related'}     = { $class_name => { %relationship },
                                    [ ... ]
                                  }; ]
     }

To use the useful object:
-------------------------

     $table = load SUBCLASS( db      => $dbi_object,
                           [ where   => { $column => $value, ... }, ]
                           [ columns => [ $column1, $column2 ], ]
                           [ index   => $index, ]
                           [ count   => $count, ]
                           [ groupby => $groupby, ]
                           [ orderby => ['+'|'-'] . $column ]);
     $table = create SUBCLASS( db => $dbi_object);

     $new_table  = $table->load_related( type => $classname,
                                         row  => $row,
                                       [ %where_arguments ] );
     $num_rows   = $table->num_rows();
     $query_rows = $table->query_rows();
     $columns    = $table->columns();
     $db         = $table->db();
     $level      = $table->debug_level( [ level => $level ] );
     $value      = $table->get( column => $column, [ row => $row ] );
     $retval     = $table->set( change => { $column => $value, [ ..., ] },
                                [ row => $row ] );
     $retval     = $table->refresh( columns = [ $column1, $column2 ],
                                    [ row => $row ] );
     $retval     = $table->commit( [ row => $row ] );
     $retval     = $table->remove( [ row => $row ] );
     $count      = $table->count( [ where => { $column => $value, ... } ]

DESCRIPTION
===========

   DBIx::Table is a class designed to act as an abstraction layer around a
fairly large subset of SQL queries.  It is called 'Table' because it is
primarily designed such that a single subclass provides an object-oriented
interface to a single database table.  The module is flexible enough,
though, that it can be used to abstract most any schema in a way that is
comfortable to the perl coder who is not familiar with the underlying
schema, or even SQL.

   As the synopsis above points out, this class is not useful when simply
used by itself.  Instead, it should be subclassed.  The subclass follows a
particular syntax for describing the structure of the table, which the
Table module uses internally to control its behavior.

   The subclass can then be used to access the underlying data, with the
Table module taking care of writing the actual SQL.  The current version
can write SELECT, UPDATE, INSERT and DELETE statements.  Depending on the
complexity of the definition, it can also do joins across multiple tables
and intelligently load related table objects.

   The rest of the documentation is split: first, how to create a useful
subclass.  Second, constructors and access methods on the subclass.
Third, some examples.  Without further ado...

Subclassing
-----------

   See the perltoot(1) and perlobj(1) manuals if you don't know how to
create a class, subclass, or if you don't understand inheritance or
overriding inherited functions.

   Every subclass of DBIx::Table is required to provide a method called
"describe", which, at a minimum, needs to provide some clues as to the
form of the underlying data.  This is done by modifying a few key parts of
the data stored in the object itself:

*$self->{'table'}*
     This should contain a string; the name of the table from which data
     is going to be retrieved.  This should be the primary table in the
     case of complex classes joining from multiple tables - this table
     name will be used for columns which do not provide any other table
     name.

*$self->{'unique_keys'}*
     If you plan on using the commit() or remove() methods, you'll need to
     provide at least one unique key combination.  This parameter takes a
     reference to an array of references to arrays of strings.  The listed
     strings in the second level array are the names of columns which,
     taken in conjunction, are guaranteed to be unique in the database.
     These are tried in order, so put them in order of preference.

*$self->{'columns'}*
     This should contain a reference to a hash, where most of the
     interesting bits of configuration go.  The hash referenced should be
     keyed by column names, and have values consisting of hash references.
     These nested hashes should contain configuration options for the
     column in question.  This all sounds pretty hairy, but in practice
     it's really not so bad - see the Examples section below.  Here are
     the available column options:

    null
          DBIx::Table only cares if this is defined or not defined.  If it
          is defined, a commit() call will fail if a value for this column
          is not set() first, or no default is supplied.  This only
          applies to local columns.

    quoted
          DBIx::Table only cares if this is defined or not defined.  If it
          is defined, data which is set() to this column will be quoted
          using $self->{'db'}->quote(), the quote method on the DBI object
          passed into the constructor.

    immutable
          DBIx::Table only cares if this is defined or not defined.  If it
          is defined, trying to set() a value to this column will cause
          set() to fail.  Immutability is, for now at least, implicit on
          all "foreign" and "special" columns - i.e.  you can't update
          foreign data!

    autoincrement
          DBIx::Table only cares if this is defined or not defined.  If it
          is defined, some magic will take place to ensure that, after an
          INSERT, the autoincremented value is correctly stored in the
          object.  This is probably MySQL specific.

    default
          The contents of this parameter will be used by commit() to
          UPDATE or INSERT data on a column without the null attribute.
          It will be quoted if the quoted attribute is set.

    foreign
          This contains another hash reference.  It is used to define the
          simplest case foreign columns.  The hash requires the keys
          'table', 'lkey', and 'rkey' - the name of the table to join,
          relationship column name in the joined table, and relationship
          column name in the local table, respectively.  Optionally, it
          can also take 'actual_table' and 'actual_column' keys, with
          their values being the real names of the foreign table and
          column.  This can be used to fetch the same column from a table
          more than once, based on different WHERE clauses.  See the
          Examples section to visualize this in action.

    special
          This contains yet another hash reference (doh!)  It is used to
          define columns which defy the abstraction currently provided by
          DBIx::Table.  Most frequently, this will be any column which has
          functions act on it, and/or complicated joins.  The recognized
          keys are 'select', 'join', 'where' and 'groupby'.  The values
          for each of these keys are raw SQL pieces, which will be stuffed
          into the appropriate place in the generated SQL.  One important
          note is that the constructor expects the column name defined in
          $self->{'columns'} to match the name of the column where this
          data is returned by the SQL statement, so you will want to
          always add 'AS column_name' to the end of the select chunk of
          SQL.  And again, check out the Examples to help visualize how
          this works.

*$self->{'related'}*
     This is not mandatory!  If defined, it should contain a reference to
     a hash, keyed by package names.  The values are hash references,
     keyed by column names from the foreign package, with values being the
     column name of a local column.  This is used by the load_related
     convenience method - see the description of this method below, as
     well as the Examples section, to get more of a grasp of how this
     works.

Methods
-------

   All of the public methods use hash-style arguments.  I've tried to be
consistent and obvious in the naming of arguments.

   The only class methods are the constructors, all other methods are
strictly object methods (i.e. you can't call SUBCLASS::get(...), you have
to call $subclass_object->get(...)).

   All methods return undef if they fail.

   General issues aside, here are the descriptions of the specific methods:

   There are two constructors:

load()
     This is the primary constructor and SELECT statement generator.  It
     takes a bunch of arguments, though only the db argument is mandatory:

    db
          This argument should contain a reference to a DBI object.  It is
          assumed to be connected and valid for the lifetime of the object
          to which it is passed.

    where
          This argument should contain a hash reference, with keys being
          column names and values being the value that column must equal.
          As a bonus hack, if the value is the string 'IS NULL', it'll
          work as you want it to (unless you're actually looking for the
          string 'IS NULL' in the database, in which case you're screwed.)
          If this argument is excluded, no WHERE clause will be used (all
          rows will be returned.)

    columns
          This argument should contain an array reference.  The elements
          of the array should be column names, or the special string '*'.
          It is important to realize that columns with the 'foreign' or
          'special' attributes are not loaded if this argument is left out
          of the load() call.  The special string '*' is expanded to all
          columns which are not 'foreign' or 'special'.  If this argument
          is left out, a literal '*' will go in the SQL generated,
          indicating that all local columns in this table should be loaded.

    index
          This argument should contain a numeric scalar, which is used to
          limit the amount of data stored (but not *queried*!) by the
          object returned by load().  It is the number of the first row to
          store, starting from zero.

    count
          This argument should contain a numeric scalar, which is also
          used to limit the amount of data stored (but, again, not
          queried!) by load().  This is a zero-based count of the maximum
          number of rows to store.

    groupby
          This argument should contain a string scalar.  It is the name of
          a column, and it causes the addition of a GROUP BY column_name
          clause to the end of the SQL generated.

    orderby
          This argument should contain a string scalar, the name of a
          column which to be used to sort the returned data.  It causes
          the addition of an ORDER BY column_name clause to the SQL
          generated.  Bonus hack: if you prepend a "+" to the column name,
          the clause has "ASC" appended to it, and if you prepend a "-" to
          the column name, the clause has "DESC" appended to it.

create()
     This simple constructor builds and returns an empty object.  It is
     useful for inserting new data into a table.  It is also useful for
     creating an empty instance of the object with which to use the
     count() method.  It takes only one argument, 'db', which is identical
     to the 'db' argument to load(), described above.

   Two methods for using the data in the object:

get()
     This method is used to fetch data from the object.  It takes only two
     possible arguments; only the 'column' argument is mandatory.

    column
          This should contain the name of the column to retrieve.  At the
          moment, you can only retrieve one value at a time.

    row
          This should contain the number of the row to retrieve data from.
          Rows in the object are always indexed by 0.  If this argument
          is excluded, it defaults to 0.

set()
     This method is used to change data in the object.  It has only two
     possible arguments.  Only the 'change' argument is mandatory, and the
     'row' argument is identical to that described in get() above.

    change
          This should contain a hash reference.  The keys of the hash
          should be column names, and the values should be the values you
          wish to place in those columns.  You can change as many columns
          as you want at once, but remember that 'foreign', 'special' and
          'immutable' columns cannot be changed.

   Three methods can make additional SQL queries based on the current data:

refresh()
     This method can perform additional SELECT queries to the database,
     using the data already loaded to ensure that the new data relates to
     the existing row.  It takes a mandatory 'columns' argument, an array
     reference containing column names to load.  It can also take a 'row'
     argument, as described under get() above.

commit()
     This method is responsible for writing UPDATE or INSERT SQL
     statements.  It takes one optional argument, 'row', which is
     identical to the 'row' argument described under get() above.

     Please be careful with this method, as it has only been tested for
     fairly simple cases.

remove()
     This method writes DELETE SQL statements, attempting to remove the
     current row from the database permanently.  It takes one optional
     argument, 'row', which is identical to the 'row' argument described
     under get() above.

     Please be careful with this method, as it has only been tested for
     fairly simple cases.

   Several methods can be used to get meta-data about the object, and the
data retrieved, and configure behavior of the object:

num_rows()
     Returns the number of rows stored in the current object.

query_rows()
     Returns the number of rows returned by the last query (this may be
     different from num_rows() if 'index' or 'count' parameters to load()
     were used).

columns()
     Returns a reference to an array containing the names of all the
     columns in the object.  Not only the ones with data in them, mind
     you!  All column names are returned.

db()
     Returns a reference to the database object that is being used.

debug_level()
     This takes a 'level' parameter, with a numeric value.  The range from
     0 to 2 is significant: 0 is trivial debugging information, 1 is
     informational messages, and 2 is errors.  Debugging information is
     only printed (to STDERR) if the debug_level is set to the priority
     level of the message or lower.  This function can also be used with
     no arguments to return the current debug_level.

   And a couple of "miscellaneous" utility functions:

count()
     This is a function for generating count(*) style SELECT statements.
     It does not store the return from the query; instead, it returns it
     to the caller.  It takes an optional 'where' argument, identical to
     the one described under load().

load_related()
     This is a utility function for constructing objects from different
     classes, which are related to the current class.  It takes two
     arguments of its own, but only the 'type' argument is mandatory:

    type
          This should contain the name of the class from which to load a
          new object.

    row
          This should contain the row number to which the new object
          should be related.  It defaults to 0.  The row number is used in
          the substitution process described below.

     All other arguments will be passed on to the load() constructor for
     the class passed in in 'type'.  It is not necessary to provide a 'db'
     argument; it will simply pass on the one it already has.  And
     finally, the real nicety provided by load_related is that it will
     check the 'where' argument (if any) and will use the information in
     $self->{'related'} to substitute values.  So you can say where => {
     'that_column' => 'this_column' }, and load_related will convert the
     literal 'this_column' into the current value of this_column.

Examples
--------

   These examples are simple but are designed to show you how this module
can be used.  They progress from table descriptions to complete subclasses
to usage, including showing the SQL that is output.

   Beginning with two tables (as you would create them with MySQL).
First, a simple users table, very straightforward:

     CREATE TABLE users (
       uid      INT UNSIGNED NOT NULL AUTO_INCREMENT,
       email    VARCHAR(70)  NOT NULL,
       password VARCHAR(10)  NOT NULL,
       PRIMARY KEY(uid),
       UNIQUE (uid),
     );

   Second, a feedback table.  This table is complexly related to the users
table; each user can both send and receive multiple feedback, so both the
to_uid and from_uid columns point back to the users table.

     CREATE TABLE feedback (
       fid      INT UNSIGNED                   NOT NULL AUTO_INCREMENT,
       to_uid   INT UNSIGNED                   NOT NULL,
       from_uid INT UNSIGNED                   NOT NULL,
       time     DATETIME                       NOT NULL,
       type     ENUM('good', 'bad', 'neutral') NOT NULL,
       text     VARCHAR(100)                   NOT NULL,
       PRIMARY KEY (fid),
       INDEX (to_uid),
       INDEX (from_uid),
       UNIQUE uid_combo (to_uid, from_uid)
     );

   Okay, now we need to create objects to represent them.  For users, I
want to be able to fetch the counts of the feedback recieved by the user
in question for each of the three feedback types, which requires 'special'
columns:

     package User;
     use strict;
     use DBIx::Table;
     @User::ISA = qw(DBIx::Table);

     sub describe {
         my($self) = shift || return(undef);

     $self->{'table'}       = 'users';
     $self->{'unique_keys'} = [ ['uid'] ];
     $self->{'columns'}     = {
       'uid'        => { 'immutable'     => 1,
                         'autoincrement' => 1,
                         'default'       => 'NULL' },
       'email'      => { 'quoted'        => 1 },
       'password'   => { 'quoted'        => 1 },
       'good_fb'    => { 'special'       =>
          { 'select'  => 'count(fb_g.type) AS good_fb',
            'join'    => 'LEFT JOIN feedback AS fb_g ON (fb_g.type = '
                         . '\'good\' AND fb_g.to_uid = users.uid)',
            'groupby' => 'uid' } },
       'bad_fb'     => { 'special'       =>
          { 'select'  => 'count(fb_b.type) AS bad_fb',
            'join'    => 'LEFT JOIN feedback AS fb_b ON (fb_b.type = '
                         . '\'bad\' AND fb_b.to_uid = users.uid)',
            'groupby' => 'uid' } },
       'neutral_fb' => { 'special'       =>
          { 'select'  => 'count(fb_n.type) AS neutral_fb',
            'join'    => 'LEFT JOIN feedback AS fb_n ON (fb_n.type = '
                         . '\'neutral\' AND fb_n.to_uid = users.uid)',
            'groupby' => 'uid' } }
     };
     $self->{'related'}    = { 'Feedback' => { 'from_uid' => 'uid',
                                               'to_uid'   => 'uid' } };
       }
       1;

   Phew.  Now how about the feedback table.  In this case, we'd like to be
able to fetch the email addresses of both the sender and recipient users in
the same query.  This can be done with 'foreign' columns.  Here's the
class:

     package Feedback;
     use strict;
     use DBIx::Table;
     @Feedback::ISA = qw(DBIx::Table);

     sub describe {
         my($self) = shift || return(undef);

     $self->{'table'}       = 'feedback';
     $self->{'unique_keys'} = [ ['fid'] ];
     $self->{'columns'}     = {
       'fid'        => { 'immutable'     => 1,
                         'autoincrement' => 1,
                         'default'       => 'NULL' },
       'to_uid'     => { },
       'from_uid'   => { },
       'time'       => { 'default'       => 'NOW()' },
       'type'       => { 'quoted'        => 1 },
       'text'       => { 'quoted'        => 1 },
       'to_email'   => { 'foreign'       =>
          { 'table'         => 'users_to',
            'lkey'          => 'to_uid',
            'rkey'          => 'uid',
            'actual_table'  => 'users',
            'actual_column' => 'email' } },
       'from_email' => { 'foreign'       =>
          { 'table'         => 'users_from',
            'lkey'          => 'from_uid',
            'rkey'          => 'uid',
            'actual_table'  => 'users',
            'actual_column' => 'email' } }
     };
       }
       1;

   Using these is simple enough.  The simplest case would be:

     $obj = load User( db => $db );

   which generates the SQL:

     SELECT * from users

   Not very intersting.  How about:

     $obj = load User db      => $db,
                      where   => { uid => 1 },
                      columns => [ '*', 'good_fb', 'bad_fb', 'neutral_fb' ];

   Which generates the SQL (formatted for viewing ease):

     SELECT      count(fb_g.type) AS good_fb,
                 count(fb_b.type) AS bad_fb,
                 count(fb_n.type) AS neutral_fb,
                 users.password,
                 users.email,
                 users.uid
     FROM        users
       LEFT JOIN feedback AS fb_g
              ON (fb_g.type = 'good'    AND fb_g.to_uid = users.uid)
       LEFT JOIN feedback AS fb_b
              ON (fb_b.type = 'bad'     AND fb_b.to_uid = users.uid)
       LEFT JOIN feedback AS fb_n
              ON (fb_n.type = 'neutral' AND fb_n.to_uid = users.uid)
     WHERE       users.uid = 1
     GROUP BY    uid

   Let's load up all feedback with the associated e-mail addresses,
arranged by descending time sent:

     $obj = load Feedback db      => $db,
                          columns => [ '*', 'to_email', 'from_email' ],
                          orderby => '-time' ;

   Generates the SQL (again, formatted):

     SELECT   users_to.email   AS to_email,
              users_from.email AS from_email,
              feedback.type,
              feedback.vs_fid,
              feedback.to_uid,
              feedback.text,
              feedback.from_uid,
              feedback.time
     FROM     feedback
         JOIN users AS users_to
         JOIN users AS users_from
     WHERE    feedback.to_uid = 2
          AND users_to.uid   = feedback.to_uid
          AND users_from.uid = feedback.from_uid
     ORDER BY feedback.time DESC

   That seems like enough to get started.

BUGS
====

   * Autoincrement columns are known to be mySQL specific.  There's
     probably more, since this has really only been tested with MySQL.  If
     anyone tries it with another DBD, I'd love to hear from you!

   * In a stupid design oversight, the current incarnation can only
     automatically generate "... WHERE foo = bar ..." in SELECT
     statements, emphasis on the '='.  Sorry!  I'll work on it!

AUTHOR
======

   J. David Lowe, dlowe@pootpoot.com

SEE ALSO
========

   perl(1)

Perl extension for full-text searching in SQL databases
*******************************************************

NAME
====

   DBIx::TextIndex - Perl extension for full-text searching in SQL
databases

SYNOPSIS
========

   use DBIx::TextIndex;

   my $index = DBIx::TextIndex->new({     document_dbh => $document_dbh,
 document_table => 'document_table',     document_fields => ['column_1',
'column_2'],     document_id_field => 'primary_key',     index_dbh =>
$index_dbh,     collection => 'collection_1', });

   $index->initialize;

   $index->add_document(\@document_ids);

   my $results = $index->search({     column_1 => '"a phrase" +and -not
or',     column_2 => 'more words', });

   foreach my $document_id     (sort {$$results{$b} <=> $$results{$a}}
keys %$results ) {     print "DocumentID: $document_id Score:
$$results{$document_id} \n"; }

   $index->delete;

DESCRIPTION
===========

   DBIx::TextIndex was developed for doing full-text searches on BLOB
columns stored in a MySQL database.  Almost any database with BLOB and DBI
support should work with minor adjustments to SQL statements in the module.

   Implements a crude parser for tokenizing a user input string into
phrases, can-include words, must-include words, and must-not-include words.

   The following methods are available:

$index = DBIx::TextIndex->new(\%args)
-------------------------------------

   Constructor method.  The first time an index is created, the following
arguments must be passed to new():

   my $index = DBIx::TextIndex->new({     document_dbh => $document_dbh,
 document_table => 'document_table',     document_fields => ['column_1',
'column_2'],     document_id_field => 'primary_key',     index_dbh =>
$index_dbh,     collection => 'collection_1', });

document_dbh
     DBI connection handle to database containing text documents

document_table
     Name of database table containing text documents

document_fields
     Reference to a list of column names to be indexed from document_table

document_id_field
     Name of a unique integer key column in document_table

index_dbh
     DBI connection handle to database containing TextIndex tables.  I
     recommend using a separate database for your TextIndex, because the
     module creates and drops tables without warning.

collection
     A name for the index.  Should contain only alpha-numeric characters or
     underscores [A-Za-z0-9_]

   After creating a new TextIndex for the first time, and after calling
initialize(), only the index_dbh, document_dbh, and collection arguments
are needed to create subsequent instances of a TextIndex.

$index->initialize
------------------

   This method creates all the inverted tables for the TextIndex in the
database specified by document_dbh.  This method should be called only
once when creating a new index!  It drops all the inverted tables before
creating new ones.

   initialize() also stores the document_table, document_fields, and
document_id_field attributes in a special table called "collection," so
subsequent calls to new() for a given collection do not need those
arguments.

$index->add_document(\@document_ids)
------------------------------------

   Add all the @documents_ids from document_id_field to the TextIndex.
@document_ids must be sorted from lowest to highest.  All further calls to
add_document() must use @document_ids higher than those previously added
to the index.  Reindexing previously-indexed documents will yield
unpredictable results!

$index->search(\%search_args)
-----------------------------

   search() returns $results, a reference to a hash.  The keys of the hash
are document ids, and the values are the relative scores of the documents.
If an error occured while searching, $results will be a scalar variable
containing an error message.

   $results = $index->search({     first_field => '+andword -notword
orword "phrase words"',     second_field => ...      ...  });

   if (ref $results) {     print "The score for $document_id is
$results->{$document_id}\n"; } else {     print "Error: $results\n"; }

$index->delete
--------------

   delete() removes the tables associated with a TextIndex from index_dbh.

CHANGES
=======

   0.04 Bug fix: add_document() will return if passed empty array ref
instead of producing error.

     Changed _boolean_compare() and _phrase_search() so and_words and
     phrases behave better in multiple-field searches. Result set for each
     field is calculated first, then union of all fields is taken for
     final result set.

     Scores are scaled lower in _search().

   0.03 Added example scripts in examples/.

   0.02 Added or_mask_set.

   0.01 Initial public release.  Should be considered beta, and methods
may be added or changed until the first stable release.

AUTHOR
======

   Daniel Koch, dkoch@amcity.com

COPYRIGHT
=========

   Copyright 1997, 1998, 1999 by Daniel Koch.  All rights reserved.

LICENSE
=======

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself, i.e., under the terms of the "Artistic
License" or the "GNU General Public License".

DISCLAIMER
==========

   This package 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.

ACKNOWLEDGEMENTS
================

   Thanks to Ulrich Pfeifer for ideas and code from Man::Index module in
"Information Retrieval, and What pack 'w' Is For" article from The Perl
Journal vol. 2 no. 2.

   Thanks to Steffen Beyer for the Bit::Vector module, which enables fast
set operations in this module. Version 5.3 or greater of Bit::Vector is
required by DBIx::TextIndex.

BUGS
====

   Uses quite a bit of memory.

   MySQL-specific SQL is used.

   Parser is not very good.

   Documentation is not complete.

   Phrase searching relies on full-table scan.  Any suggestions for adding
word-proximity information to the index would be much appreciated.

   No facility for deleting documents from an index.  Work-around: create
a new index.

   Please feel free to email me (dkoch@amcity.com) with any questions or
suggestions.

SEE ALSO
========

   perl(1).

Perl module for generating a tree from a self-referential table
***************************************************************

NAME
====

   DBIx::Tree - Perl module for generating a tree from a self-referential
table

SYNOPSIS
========

     use DBIx::Tree;
     my $tree = new DBIx::Tree(connection => $dbh,
                               table      => $table,
                               method     => sub { disp_tree(@_) },
                               columns    => [$id_col, $label_col, $parent_col],
                               start_id   => $start_id);
     $tree->do_query;
     $tree->tree;

DESCRIPTION
===========

   When you've got one of those nasty self-referential tables that you want
to bust out into a tree, this is the module to check out.  Assuming there
are no horribly broken nodes in your tree and (heaven forbid) any circular
references, this module will turn something like:

     food                food_id   parent_id
     ==================  =======   =========
     Food                001       NULL
     Beans and Nuts      002       001
     Beans               003       002
     Nuts                004       002
     Black Beans         005       003
     Pecans              006       004
     Kidney Beans        007       003
     Red Kidney Beans    008       007
     Black Kidney Beans  009       007
     Dairy               010       001
     Beverages           011       010
     Whole Milk          012       011
     Skim Milk           013       011
     Cheeses             014       010
     Cheddar             015       014
     Stilton             016       014
     Swiss               017       014
     Gouda               018       014
     Muenster            019       014
     Coffee Milk         020       011

   into:

     Food (001)
       Dairy (010)
         Beverages (011)
           Coffee Milk (020)
           Whole Milk (012)
           Skim Milk (013)
         Cheeses (014)
           Cheddar (015)
           Stilton (016)
           Swiss (017)
           Gouda (018)
           Muenster (019)
       Beans and Nuts (002)
         Beans (003)
           Black Beans (005)
           Kidney Beans (007)
             Red Kidney Beans (008)
             Black Kidney Beans (009)
         Nuts (004)
           Pecans (006)

   There are examples in the examples directory - one plain text example,
and two Tk examples.

Constructor arguments
=====================

     my $tree = new DBIx::Tree(connection => $dbh,
                               table      => $table,
                               method     => sub { disp_tree(@_) },
                               columns    => [$id_col, $label_col, $parent_col],
                               start_id   => $start_id,
                               match_data => $match_data,
                               limit      => $limit);

connection
     A DBI connection handle.

table
     The database table containing the hierarchical data.

method
     A callback method to be invoked each time a tree item is encountered.
     This method will be given a hashtable as a parameter, containing the
     following elements:

          item:        the name of the item
          level (0-n): the nesting level of the item.
          id:          the unique id of the item.

columns:
     A list of three columns from the table:

          id_col:     The unique id.
          label_col:  The textual data of the row, like a name.
          parent_col: The id of the row's parent.

start_id
     The unique id of the root item.

match_data
     The value of a partial match to look for - if this is supplied, only
     rows whose label_col matches (match_data + '%') this will be
     selected. This feature was supplied by Ilia Lobsanov
     <ilia@lobsanov.com>

limit
     Limit the number of rows using an SQL LIMIT clause - not all SQL
     servers support this. This feature was supplied by Ilia Lobsanov
     <ilia@lobsanov.com>

TODO
====

   Graceful handling of circular references.  Better docs.  Rewrite the
algorithm.  Separate data acquisition from data formatting.

AUTHOR
======

   Brian Jepson, bjepson@ids.net

   This module was inspired by the Expanding Hierarchies example that I
stumbled across in the Microsoft SQL Server Database Developer's Companion
section of the Microsoft SQL Server Programmer's Toolkit.

   Jan Mach <machj@ders.cz> contributed substantial performance
improvements, ordering handling for tree output, and other bug fixes.

SEE ALSO
========

   perl(1).  DBI(3).  Tk(3).

Module to manage a user database using DBIx::SearchProfiles
***********************************************************

NAME
====

   DBIx::UserDB - Module to manage a user database using
DBIx::SearchProfiles

SYNOPSIS
========

     use DBIx::UserDB;
     use DBIx::SearchProfiles;

     my $db     = new DBIx::SearchProfiles( ... );
     my $userdb = new DBIx::UserDB( $db );

     my $user   = { username => $username, password => $password };
     $user      = $userdb->user_create( $user );

     # Later on
     my $user   = $userdb->login( $user, $password );
     die "Login failed" unless $user;

     # Much later
     if ( $userdb->allowed( $user, $target, "DELETE" ) ) {
     	...
     }

DESCRIPTION
===========

   The DBIx::UserDB uses DBIx::SearchProfiles to manage a user and group
database and may be also used to manage complex ACL. The user and group
schema may be modified for application specific data since only a few
fields are required by the UserDB. This is possible thanks to
DBIx::SearchProfiles.

CONCEPTS
========

Users and Groups
----------------

   Users are represented as hash and as one SQL table. They have a unique
username and a unique uid. Group have also a unique name and a unique gid.
A user may be a members of many groups.

ACLs
----

   UserDB can also be used to manage complex ACL (Acccess Control Lists).
Access to resources is determined by the tuple (user,target,privilege)
which determines if a user has the required *privilege* on target.
*Privilege* and target are treated as application specific character
strings.

CONFIGURATION
=============

   In order to use DBIx::UserDB you will need to create a few tables in
your DMBS and to create the approriate DBIx::SearchProfiles.

   Here is the minimal schema required in your DBMS :

     CREATE TABLE userdb (
     	uid	    SERIAL PRIMARY KEY,
     	username    CHAR(32) UNIQUE,
     	password    CHAR(32)
     );

     CREATE TABLE groupdb (
     	gid	    SERIAL PRIMARY KEY,
     	groupname   CHAR(32) UNIQUE
     );

     CREATE TABLE groupmembers (
     	gid	    INT REFERENCES groupdb,
     	uid	    INT REFERENCES userdb,
     	PRIMARY KEY (gid,uid)
     );

     CREATE TABLE user_acl (
     	uid	    INT REFERENCES userdb,
     	target	    CHAR(128),
     	privilege   CHAR(32),
     	negated	    BOOL DEFAULT 0,
     	PRIMARY KEY (uid,target,privilege)
     );

     CREATE TABLE group_acl (
     	gid	    INT REFERENCES groupdb,
     	target	    CHAR(128),
     	privilege   CHAR(32),
     	negated	    BOOL DEFAULT 0,
     	PRIMARY KEY (gid,target,privilege)
     );

     CREATE TABLE default_acl (
     	target	    CHAR(128),
     	privilege   CHAR(32),
     	negated	    BOOL DEFAULT 0,
     	PRIMARY KEY (target,privilege)
     );

   This SQL was tested with PostgreSQL, modify according to your RDBMS.
And here is its related DBIx::SearchProfiles profile :

     {
     userdb	 =>
       {
        fields	 => [qw( username password ) ],
        keys	 => [qw( uid )],
        table	 => "userdb",
       },
     groupdb	 =>
       {
        query	 => q{ SELECT m.gid,uid,groupname FROM groupdb, groupmembers m
     		       WHERE  uid = ? },
        params	 => [ qw( uid ) ],
        fields	 => [ qw( groupname ) ],
        keys	 => [ qw( gid )],
        table	 => "groupdb",
       }	,
     }

   You may add any fields to the groupdb and userdb tables as long as you
add them to the profiles. The *userdb* profile should be a record profile
(see DBIx::SearchProfiles(3)) and *groupdb* should contains both template
profile's information (for finding the users associated with a group) and
record profile's information (for inserting and updating group's
information). Additionaly you may change the fields length of all required
fields.

   Passwords are uuencoded for storage (for minimal privacy not for
security), so take this into account when setting the password field's
length. If you want to store password in plaintext, use the
`scramble_password' method.

INITIALIZATION
==============

   Initializing the DBIx::UserDB is as simple as

     my $userdb = new DBIx::UserDB( $DB, "userdb", "groupdb" );

   The first parameter is a DBIx::SearchProfiles object which will be used
to access the database. The second parameter is the name of the profile
that should be used to access the users' information (defaults to
"userdb"). The third parameter is the name of the profile to use for group
access (defaults to "groupdb").

scramble_password ( [new_setting] )
-----------------------------------

   Return the scramble password setting. You may also change the setting
by giving the method a new value. If scramble password is true, user's
password will be uuencoded before being stored in the database.

USER METHODS
============

   Here are the methods for managing users in the database.

user_create ( \%user )
----------------------

   This method creates a user with the information specified in the hash
reference in the database. In the user's hash, at least the fields
username and password should be set.

   The methods return true on success and false if there is already a
username with that name in the database. Exception are thrown on database
errors. Additionally, on return, the method will add the UID of the newly
created user.

user_search ( \%params )
------------------------

   This method will return users matching the DBIx::SearchProfiles query
specification in a reference to an array.

user_get ( $uid_or_name )
-------------------------

   This method takes a UID or username and return the corresponding user
(as an hash reference) or undef if there is no such user.

   The key groups in the user's hash contains the names of the groups of
which this user is a member.

user_login ( $username, $password )
-----------------------------------

   This method will return the user which have the corresponding username
and password or undef if the username or password is invalid.

user_delete ( \%user )
----------------------

   This method removes the given user from the database.

user_update ( \%user )
----------------------

   This method updates database information of the given user. This method
has no effects on the group information. Use the `group_add_user' and
`group_remove_user' methods for modifying the groups associated with a
user.

GROUP METHODS
=============

   Here are the methods to manage group information

group_create ( \%group )
------------------------

   This method creates a new group in the database. At least the
*groupname* key should be set in the hash.

   This methods returns false if there is already a group with the same
groupname. It returns true if the creation succeeded. Additionnaly, on
return, the key gid will be set in the original group's hash.

group_search ( \%params )
-------------------------

   This method will search the database for groups matching the
DBIx::SearchProfiles record search and will return its results as a
reference to an hash.

group_get ( $gid_or_name )
--------------------------

   This method takes a gid or groupname and will fetch the corresponding
group. It returns the corresponding group or undef if there is no such
group. Additionnaly there is a key members defined in the resulting hash
which contains in an array the name of all members of the group.

group_delete ( \%group )
------------------------

   This methods removes the given group from the database.

group_update ( \%group )
------------------------

   This methods updates the information associated with the given group in
that database. This methods doesn't modify the list of members of this
group. User `group_add_user' and `group_remove_user' for that.

group_add_user ( \%group, \%user )
----------------------------------

   Adds the user to that group.

group_remove_user ( \%group, \%user )
-------------------------------------

   Removes the user from that group.

ACL METHODS
===========

   Here are the methods to access the ACL information :

grant ( \%user_or_group, $target, $privilege )
----------------------------------------------

   Grant the specified *privilege* on target to that group or user.  If
you want to set the default policy regarding that target and privilege,
use undef as the user parameter.

deny ( \%user_or_group, $target, $privilege )
---------------------------------------------

   Deny the specific *privilege* on target to that group or user. Use undef
if you want the default policy to be deny.

revoke ( \%user_or_group, $target, $privilege )
-----------------------------------------------

   Removes the specified *privilege* on target associated with user or
group. If you want to remove the default policy, use undef as the user
parameter.

   NOTE: Revoking is not the same as denying. Revoking removes the entry
from the ACL which means that the resulting policy will be determined by
other entry in the ACL (i.e: group or default). When using deny, you are
explicitely determining the level of access.

allowed ( \%user, $target, $privilege )
---------------------------------------

   Determine if user has *prilivege* on target. This how the access is
determined :

  1. Determine if there is an entry (user,target,privilege). If an entry is
     found, true or false will be returned depending whether that privilege
     was granted or denied.

  2. Check for an entry (group,target,privilege) for each group of which
     the user is a member. For the group policy to apply, all group must
     share the same result.

     For example, if user A is member of group A and B and group A is
     granted the requested privilege and group B is denied, the group
     policy doesn't apply to that particular user. Schematically :

          Group A Granted + Group B Granted = User Granted
          Group A Granted + Group B Denied  = Default policy will apply
          Group A Denied  + Group B Denied  = User Denied

  3. A entry (target,privilege) will be lookup in the default policy. If
     one is found, that policy will apply.

  4. Access is denied.

BUGS AND LIMITATIONS
====================

   Please report bugs, suggestions, patches and thanks to <bugs@iNsu.COM>.

   Authentication is limited to clear text password authentication.

   User and group data structure is restricted to single level hash.

AUTHOR
======

   Copyright (c) 1999 Francis J. Lacoste and iNsu Innovations Inc.  All
rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the terms as perl itself.

SEE ALSO
========

   DBIx::SearchProfiles(3) Apache::UserDBAuthen(3) Apache::UserDBAuthz(3)

XML Message exchange between DBI data sources
*********************************************

NAME
====

   DBIx::XMLMessage - XML Message exchange between DBI data sources

SYNOPSIS
========

OUTBOUND MESSAGE
----------------

     #!/usr/bin/perl

     use DBI;
     use DBIx::XMLMessage;

     # Template string
     my $tpl_str =<< "_EOT_";
     <?xml version="1.0" encoding="UTF-8" ?>
     <TEMPLATE NAME='SysLogins' TYPE='XML' VERSION='1.0' TABLE='syslogins'>
     <KEY NAME='suid' DATATYPE='NUMERIC' PARENT_NAME='OBJECT_ID' />
     <COLUMN NAME='LoginId' EXPR='suid' DATATYPE='NUMERIC' />
     <COLUMN NAME='PasswordDate' EXPR='pwdate' DATATYPE='DATETIME'
         BLTIN="fix_gmdatetime" />
     <CHILD NAME='SysUsers' TABLE='sysusers'>
         <KEY NAME='suid' PARENT_NAME='LoginId' DATATYPE='NUMERIC' />
         <COLUMN NAME='UserId' EXPR='uid' DATATYPE='NUMERIC' />
         <COLUMN NAME='UserName' EXPR='name' />
     </CHILD>
     </TEMPLATE>
     _EOT_
     my $msg = new DBIx::XMLMessage ('TemplateString' => $tpl_str);
     my $ghash = { 'OBJECT_ID' => [ 1, 2 ] };
     my $dbh = DBI->connect('dbi:Sybase:server=x;database=master','sa','secret');
     $msg->rexec ($dbh, $ghash);

     print "\n\n", $msg->output_xml(0,0);
     print "\n\n", $msg->output_xml(0,1);

INBOUND MESSAGE
---------------

     #!/usr/bin/perl

     use DBI;
     use DBIx::XMLMessage;

     my $template_xml =<< "_EOD1_";
     <?xml version="1.0" encoding="UTF-8" ?>
     <TEMPLATE NAME='SysLogins' TYPE='XML' VERSION='1.0' TABLE='syslogins'
         ACTION='SAVE'>
     <KEY NAME='suid' DATATYPE='NUMERIC' PARENT_NAME='OBJECT_ID' />
     <COLUMN NAME='LoginId' EXPR='suid' DATATYPE='NUMERIC' />
     <COLUMN NAME='PasswordDate' EXPR='pwdate' DATATYPE='DATETIME'
         BLTIN="fix_gmdatetime" />
     <CHILD NAME='SysUsers' TABLE='sysusers'>
         <KEY NAME='suid' PARENT_NAME='LoginId' DATATYPE='NUMERIC' />
         <COLUMN NAME='UserId' EXPR='uid' DATATYPE='NUMERIC' />
         <COLUMN NAME='UserName' EXPR='name' />
     </CHILD>
     </TEMPLATE>
     _EOD1_

     my $message_xml =<< "_EOD2_";
     <?xml version="1.0" encoding="UTF-8"?>
     <SysLogins>
     <LoginId>1</LoginId>
     <PasswordDate>1999/08/17 08:31</PasswordDate>
     <SysUsers>
         <UserId>1</UserId>
         <UserName>sa</UserName>
     </SysUsers>
     </SysLogins>
     _EOD2_

     my $xmlmsg = new DBIx::XMLMessage ('TemplateString' => $template_xml);
     my $msgtype = $xmlmsg->input_xml($message_xml);
     my $ghash = {
         'OBJECT_ID' => [ 1 ]
     };
     $xmlmsg->populate_objects ($ghash);

     my $dbh = DBI->connect('dbi:Sybase:server=x;database=master','sa','secret');
     $xmlmsg->rexec ($dbh, $ghash);
     print $xmlmsg->output_message();

DESCRIPTION
===========

   The package maintains simple XML templates that describe object
structure.

   The package is capable of generating SQL statements based on these
templates and executing them against DBI data sources. After executing the
SQL, the package formats the data results into XML strings. E.g. the
following simple template

     <TEMPLATE NAME='SysLogins' TYPE='XML' VERSION='1.0' TABLE='syslogins'
         ACTION='SAVE'>
     <KEY NAME='suid' DATATYPE='NUMERIC' PARENT_NAME='OBJECT_ID' />
     <COLUMN NAME='LoginId' EXPR='suid' DATATYPE='NUMERIC' />
     </TEMPLATE>

   being executed with key value = 1, will be tranlated into this SQL:

   SELECT suid LoginId FROM syslogins where suid = 1

   and the result will be formatted into this XML string:

     <SysLogins>
         <LoginId>1<LoginId>
     </SysLogins>

   Inbound messages can be processed according to the same kind of
templates and the database is updated accordingly. Templates are capable
of defining the SQL operators, plus new SAVE operation which is basically
a combination of SELECT and either INSERT or UPDATE depending on whether
the record was found by the compound key value or not.

SALES PITCH
===========

   This package allows for objects exchange between different databases.
They could be from different vendors, as long as they both have DBD
drivers. In certain cases it is even possible to exchange objects between
databases with different data models. Publishing of databases on the web
could potentially be one of the applications as well.

TEMPLATE TAGS
=============

TEMPLATE
--------

   This is manadatory top-level tag. It can correspond to a certain table
and be processed just like table-level REFERENCE and CHILD attributes
described below. Some of TEMPLATE attributes are related to the whole
template (e.g.  TYPE or VERSION) while others desribe the table ti's based
on (e.g. TABLE)

   If the TABLE attribute is defined, the generated SQL is going to run
against some table. Otherwise a SQL with no table will be generated. This
only makes sense for outbound messages and only possible on certain
engines, like Sybase. Also, the immediate child columns should contain
constants only for apparent reasons.

REFERENCE
---------

   REFERENCE is a table-level tag. It's meant to represent a single record
from another table that's retrieved by unique key. E.g. if my current
table is EMPL then DEPARTMENT would be a REFERENCE since employee can have
no more than one departament.

CHILD
-----

   This tag meant to represent a number of child records usually retrieved
by a foreign key value (probably primary key of the current table). Right
now there's no difference in processing between CHILD and REFERENCE, but
it may appear in the future releases.

COLUMN
------

   This tag is pretty self-explanatory. Each COLUMN tag will appear on the
SELECT, INSERT or UPDATE list of the generated SQL.

KEY
---

   Key represents linkage of this table's records to the parent table. All
KEY's will appear on the WHERE clause as AND components. This way of
linkage is typical for most of relational systems and considered to be a
good style.  I guess it shouldn't be much of a restriction anyway. If it
gets that, you could try tweak up the WHERE_CLAUSE attribute..

PARAMETER
---------

   This tag represents a parameter that will be passsed to a stored
procedure.  Currently, only Sybase-style stored procedures are supported,
i.e.

   exec proc_name @param_name = 'param_value', ...

   Fixes for Oracle, DB2 and Informix are welcome..

TEMPLATE TAG ATTRIBUTES
=======================

NAME
----

     Applicable to:  All template tags
     Required for:   All template tags

   NAME is the only required attribute for all of the template tags. The
main purpose of it is to specify the tag name as it will appear in the
resulting XML document. Also, depending on the template tag type (COLUMN,
PARAMETER and KEY) it may serve as default value for EXPR discussed below.
Here's a small example of how it works. If my column is represented in the
template like this:

     <COLUMN NAME='ObjectId' />

   the resulting SQL will contain

     SELECT ObjectID, ...

   whereas if I have

     <COLUMN NAME='ObjectId' EXPR='igObjectId' />

   it will generate the following SQL:

     SELECT igObjectId ObjectID, ...

   I.e. in the latter example, NAME used as an alias and EXPR as a real
database column name. The column in the first example has no alias.

ACTION
------

     Applicable to:  TEMPLATE, REFERENCE, CHILD
     Required for:   None

   Possible values for this attibute are SELECT, INSERT, UPDATE, EXEC and
SAVE.  If action is not provided, it is assumed that t he action should be
SELECT.  The first 4 values correspond to SQL data management operators
(EXEC is vendor-specific and represents execution of a stored procedure).
The fifth value, SAVE, is basically a combination of SELECT and either
INSERT or UPDATE, depending on whether the record was found by the
compound key value or not. This often helps to avoid usage of complicated
stored procedures with primary key generation and keep things generic and
scalable. Primary key generation issue is addressed separately by using of
the GENERATE_PK attribute (see below).

BLTIN
-----

     Applicable to:  COLUMN
     Required for:   None

   Represents a perl built-in function. before invocation of this
subroutine the package prepares array @_ and makes it visible to the
built-in function.  The 3 arguments received by the built-in are:
$self   -  DBIx::XMLMessage object     $node   -  Correspondent
DBIx::XMLMessage::COLUMN object. You                can use it to obtain
other column attributes, e.g.                 $node->{DATATYPE}     $value
-  The column value

   Meaning of the value depends on direction of the message, i.e. whether
the message is inbound or outbound. In case of inbound message, this is the
value received by the package from outside world; if the message is inbound
then this is the value selected from database. There's one built-in
function that comes with the package - fix_gmdatetime. It converts date
and time to GMT for outbound messages and from GMT to the database
date/time for inbound messages. Just add one attribute to your datetime
column:

     ... BLTIN="fix_gmdatetime" ...

CARDINALITY
-----------

     Applicable to:   KEY, PARAMETER, REFERENCE, CHILD
     Required for:    None
     Possible values: REQUIRED, OPTIONAL
     Default:         REQUIRED

   This parameter has different meaning for different element types.
Optional KEYs and PARAMETERs allow to proceed execution if the value for
it was not found at some point of execution. Optional CHILDs and
REFERENCEs will be skipped from execution, and hence from output, if the
package failed to collect all the key values.

DATATYPE
--------

     Applicable to:   KEY, PARAMETER, COLUMN
     Required for:    None
     Possible values: CHAR, VARCHAR, VARCHAR2, DATE, DATETIME, NUMERIC
     Default:         CHAR

   This attribute loosely corresponds to the database column type. The only
processing difference in the core package is quoting of the non-numeric
datatypes, particularly those containign substrings CHAR, DATE or TIME.
The built-in fix_gmdatetime utilizes this attribute more extensively.

DEBUG
-----

   Recognized but not currently supported

DEFAULT
-------

     Applicable to:   PARAMETER, COLUMN
     Required for:    None
     Possible values: Any string or number

   This attribute allows to provide a default value for COLUMNs and
PARAMETERS.  Please note that default values are not being formatted, so
they have to represent the literal value. E.g. if you want to provide a
string DEFAULT it would look somewhat like this:     ... DEFAULT =
"'UNKNOWN'"

EXPR
----

     Applicable to:  All template tags
     Required for:   None

   For COLUMN and KEY this attribute represents the actual database column
name or a constant. For PARAMETER

FACE
----

     Applicable to:   COLUMN
     Required for:    None
     Possible values: ATTRIBUTE, TAG
     Default:         TAG

   This attribute allows to output certain columns as attributes, as
opposed to the default TAG-fasion output. Since it's not supported for
inbound messages yet, usage of this feature is not recommended.

GENERATE_PK
-----------

     Applicable to:   COLUMN
     Required for:    None
     Possible values: HASH, SQL returning one value or name

   This attribute allows you to specify how to generate primary key
values. You have 2 options here:

   1. You can write your own Perl function, put its reference to the global
hash under the name of the table for which you intend to generate primary
key values and provide the value of 'HASH' as the GENERATE_PK value

   2. You can put the generating SQL block/statement into the GENERATE_PK
value

HIDDEN
------

     Applicable to:   COLUMN

   Indicates that the column will be excluded from the output. This
attribute only makes sense for outbound messages.

MAXROWS
-------

   Currently not supported. In future, intends to limits the number of
selected rows.

PARENT_NAME
-----------

     Applicable to:   KEY

   Indicates the name of the tag one level up to which this one tag is
corresponding. E.g.

     ...
     <COLUMN NAME='OBJECT_ID'/>
     <REFERENCE ...>
         <KEY NAME='nOrderId' PARENT_NAME='OBJECT_ID'/>
     </REFERENCE>

   This feature is a workaround allowing to have two columns descending
from the same parent column at the same level. There was some other prolem
it was helping to resolve, but I forgot what it was ;^)

PROC
----

     Applicable to:   TEMPLATE, REFERENCE, CHILD

   Used in conjunction with ACTION='PROC'. Defines the name of the stored
procedure to invoke.

RTRIMTEXT
---------

   Currently not supported. The package does automatic right-trimming for
all the character data.

TABLE
-----

   Name of the table against which the SQL will be run.

TOLERANCE
---------

     Applicable to:   TEMPLATE, REFERENCE, CHILD
     Possible values: IGNORE, CREATE, REJECT
     Default:         IGNORE

   Allows to adjust package behaviour when SQL execution produces
unexpected result columns. E.g. if there's a stored procedure that will
return the results for your message, you can omit describing of all the
resulting COLUMNS in the template and instead specify     ...
TOLERANCE='CREATE' Whatever columns are returned by the stored procedure
(Sybase & MS SQL) will be added on-the-fly and available for the output.

WHERE_CLAUSE
------------

   Additional where clause. Added as an AND component at the end of
generated where clause.

METHODS
=======

new
---

     my $xmsg = new DBIx::XMLMessage (
         [ _OnError => $err_coderef, ]
         [ _OnTrace => $trace_coderef, ]
         [ _OnDebug => $debug_coderef, ]
         [ Handlers => $expat_handlers_hashref, ]
         [ TemplateString => $xml_template_as_a_string, ]
         [ TemplateFile => $xml_template_file_name, ]
     )

   You can specify either TemplateString or TemplateFile, but not both. If
any of those specified, the template will be parsed.

set_handlers
------------

     $xmsg->set_handlers ($expat_handlers_hashref)

   Set additional expat handlers, see XML::Parser::Expat. Normally you
won't use this. The only case I could think of is processing of encoding..

prepare_template
----------------

     $xmsg->prepare_template ($template_xml_string)

   This method can be invoked if the template was not specified in the
'new' method invocation.

prepare_template_from_file
--------------------------

     $xmsg->prepare_template_from_file ($template_file_name)

   Same as above, but template is read from file here.

input_xml
---------

     $xmsg->input_xml ($inbound_xml_message_content)

   Parse an inbound XML message. The values form this message will be used
to fill in COLUMNS and PARAMETERS. The structure of this message should
comply with template. Uses Tree parsing style.

input_xml_file
--------------

     $xmsg->input_xml_file ($inbound_xml_message_file_name)

   Same as above, but the XML message is read from a file.

populate_objects
----------------

     $xmsg->populate_objects ($global_hash_ref [, $matching_object
         [, $tag_name [, $tag_content, [$parameter_index]]]])

   This method is trying to stuff the existing template with the inbound
message previously parsed by one of the 'input_xml' methods. The only
mandatory attribute is global hash reference, which has to contain key
values for the topmost tag TEMPLATE.

rexec
-----

     $xmsg->rexec ($dbh, $global_hash_ref)

   This method is running the created query against a DBI/DBD source and
fills in the template with results in order to make them available for
subsequent output_message call. In case of INSERT/UPDATE operations only
key values will be filled in.

output_message
--------------

   This method returns a string with query results in XML format suitable
for printing or whatever manupulations seem appropriate.

SEE ALSO
========

     XML::Parser
     XML::Parser::Expat

AUTHORS
=======

     Andrei Nossov <andrein@andrein.com>

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl extension for creating XML from existing DBI datasources
*************************************************************

NAME
====

   DBIx::XML_RDB - Perl extension for creating XML from existing DBI
datasources

SYNOPSIS
========

     use DBIx::XML_RDB;
     my $xmlout = DBIx::XML_RDB->new($datasource,
     		"ODBC", $userid, $password, $dbname) || die "Failed to make new xmlout";
     $xmlout->DoSql("select * from MyTable");
     print $xmlout->GetData;

DESCRIPTION
===========

   This module is a simple creator of XML data from DBI datasources. It
allows you to easily extract data from a database, and manipulate later
using XML::Parser.

   One use of this module might be (and will be soon from me) to extract
data on the web server, and send the raw data (in XML format) to a
client's browser, and then use either XML::Parser from PerlScript, or
MSXML from VBScript/JavaScript on the client's machine to generate HTML
(obviously this relies upon using MS IE for their Active Scripting Engine,
and MSXML comes with IE5beta).

   Another use is a simple database extraction tool, which is included,
called sql2xml.  This tool simply dumps a table in a database to an XML
file. This can be used in conjunction with xml2sql (part of the
XML::DBI(?) package) to transfer databases from one platform or database
server to another.

   Binary data is encoded using UTF-8. This is automatically decoded when
parsing with XML::Parser.

   Included with the distribution is a "Scriptlet" - this is basically a
Win32 OLE wrapper around this class, allowing you to call this module from
any application that supports OLE. To install it, first install the
scriptlets download from microsoft at http://msdn.microsoft.com/scripting.
Then right-click on XMLDB.sct in explorer and select "Register". Create
your object as an instance of "XMLDB.Scriptlet".

FUNCTIONS
=========

new
---

     new ( $datasource, $dbidriver, $userid, $password [, $dbname] )

   See the DBI documentation for what each of these means, except for
$dbname which is for support of Sybase and MSSQL server database names
(using "use $dbname").

DoSql
-----

     DoSql ( $sql )

   Takes a simple Sql command string (either a select statement or on some
DBMS's can be a stored procedure call that returns a result set - Sybase
and MSSql support this, I don't know about others).

   This doesn't do any checking if the sql is valid, if it fails, the
procedure will "die", so if you care about that, wrap it in an eval{}
block.

   The result set will be appended to the output. Subsequent calls to
DoSql don't overwrite the output, rather they append to it. This allows
you to call DoSql multiple times before getting the output (via GetData()).

GetData
-------

   Simply returns the XML generated from this SQL call. Unfortunately it
doesn't stream out as yet. I may add this in sometime in the future (this
will probably mean an IO handle being passed to new()).

   The format of the XML output is something like this:

     <?xml version="1.0"?>
     <DBI driver="dbi:Sybase:database=foo">
     	<RESULTSET statement="select * from Table">
     		<ROW>
     		<Col1Name>Data</Col1Name>
     		<Col2Name>Data</Col2Name>
     		...
     		</ROW>
     		<ROW>
     		...
     		</ROW>
     	</RESULTSET>
     	<RESULTSET statement="select * from OtherTable">
     	...
     	</RESULTSET>
     </DBI>

   This is quite easy to parse using XML::Parser.

AUTHOR
======

   Matt Sergeant, matt@sergeant.org

SEE ALSO
========

   XML::Parser

DBM with associative arrays, file locking and XML records
*********************************************************

NAME
====

   `DBM::DBass' - DBM with associative arrays, file locking and XML records

SYNOPSIS
========

     use DBM::DBass;

     die unless DBM::DBass::gestalt (-api => 'neo');
     my $db = DBM::DBass->new (
         -api  => 'neo',
         -file => '+<file.dbm',
         -lock => 'file.lock',
         -mode => 0644
     );

DESCRIPTION
===========

   This module provides methods to read, write and delete associative
arrays in DBM files, with file locking and XML records.

   It uses a named argument `-api' for class methods new and `gestalt' to
try to prevent later versions of the module from breaking preexisting APIs.

METHODS
=======

`gestalt'
     This method checks for the existence of an API:

          die 'no API neo' unless DBM::DBass::gestalt (-api => 'neo');

     `-api' is the calling API to check for.  One should use this method
     only for development or testing, and not in frequently used
     applications.

new
     This method creates a new DBass object, and should be the first one
     called:

          my $db = DBM::DBass->new (
              '-api'  => 'neo',
              '-file' => '+<file.dbm',
              '-lock' => 'file.lock',
              '-mode' => 0644
          );

     `-api' is the calling API to use.  `-file' is the read/write mode
     (default is read-only) and DBM filename.  `-lock' is the lock
     filename.  `-mode' is the file permissions mode of the DBM file.

     If the DBM file is opened for read-only access, the lock file must
     preexist, but can be empty.  In MacOS, one can create an empty file
     with SimpleText.  In *nix, one can create an empty file with touch:

          touch file.lock

     This version of the module has APIs `xeen' and X<neo>.  The `xeen'
     API is deprecated and provided for backward compatibility only, and
     the `neo' API should be used when possible.

close
     This method releases various resources in the DBass object, to allow
     other processes to access the DBM file:

          $db->close;

     Normally this method should not be used, as it renders the object
     useless for the remainder of the program execution (and is
     automatically called when the object is destroyed).

delete
     This method deletes records from the DBM file:

          $db->delete ('-keys' => \@keys);
          $db->delete ('-keys' => \%keys);
          $db->delete ('-keys' =>  $key );

     *Be careful.*  It can also delete all records:

          $db->delete;

keys
     This method returns record keys:

          my @keys = $db->keys;

read
     This method returns a hash reference pointing to records in the DBM
     file:

          my $smallerhashref = $db->read ('-keys' => \@keys, '-root' => $root);
          my $smallerhashref = $db->read ('-keys' => \%keys, '-root' => $root);
          my $smallhashref   = $db->read ('-keys' =>  $keys, '-root' => $root);
          my $entirehashref  = $db->read ('-root' =>  $root);

     `-keys' are the keys to match against.  `-root' is the XML root tag
     name used in storing the records.

write
     This method writes key-value pairs to the DBM file:

          $db->write (-hash => \%hash, -root => $root);

     `-hash' is the hash reference pointing to the key-value pairs
     (records).  `-root' is the XML root tag name to use in storing the
     records.

KNOWN ISSUES
============

   The `xeen' API is deprecated and provided for backward compatibility
only, and the `neo' API should be used when possible.  The main reason for
the API name change is that the `neo' record format is significantly
different from that of `xeen'.

   On platforms other than MacOS, *nix or Windows NT, flock will probably
cause the module to crash and burn.

   The module should be pronounced `/di'bas/'.

   The `xeen' API is not named after the IBM alphaWorks `Xeena' XML editor.

CHANGES
=======

     0.54  2000.01.19  renamed package to DBM::DBass, as per Tim Bunce

     0.53  2000.01.11  fixed Makefile.PL (oops!)

     0.52  1999.10.30  added check for _OBJ
                       added check for _HASHREF
                       fixed neo_read handling of _UNTAGGED
                       fixed neo_read to check for _HASHREF
                       fixed neo_write to check for _OBJ
                       fixed xeen_delete to check for _OBJ
                       fixed xeen_destroy to check for _OBJ
                       fixed xeen_new die preparation
                       fixed xeen_new to include _UNTAGGED
                       fixed xeen_read handling of _UNTAGGED
                       fixed xeen_read to check for _HASHREF
                       fixed xeen_write to check for _OBJ

     0.51  1999.10.26  fixed gestalt for wantarray
                       fixed neo_read to accept hash references as -keys
                       fixed xeen_delete to accept hash references as -keys
                       fixed xeen_read to accept hash references as -keys

     0.50  1999.10.06  added neo API (valid XML tags and lists of lists)

     0.40  1999.09.20  fixed DBM file locking bug in xeen_destroy
                       fixed DBM file locking bug in xeen_new
                       fixed xeen_delete to accept scalars as -keys
                       fixed xeen_read to accept scalars as -keys

AUTHOR
======

   Copyright 1999, 2000 Nguon Hao Ching (`spiderboy@spiderboy.net').

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

CREDITS
=======

   Thanks to Tom Christiansen for Perl Cookbook recipe 14.5.

   Thanks to Mark-Jason Dominus for the Perl Monger tutorial on file
locking.

   Thanks to David Harris and Paul Marquess for the recipe bug report.

   Thanks to Chris Nandor for `perlport'.

   Thanks to James Wismer for feedback on the initial, unreleased version.

   Thanks to Jay Trolley for her patience and understanding.

   Thanks to xeenie for everything else.

Database Objects
****************

NAME
====

   `DBO' - Database Objects

SYNOPSIS
========

     use DBO ':constructors';

     $dbh = DBO::Handle::DBI::mysql->connect
       ('dbi:mysql:database:host', 'larry', 'camel');

     $schema = Database
       ( tables =>
         [ Table
     	( name => 'person',
     	  columns =>
     	  [ Char(name => 'name', max_length => 100 ),
     	    Text(name => 'address'),
               Char(name => 'phone', max_length => 30 )])]);

     $dbo = DBO->new
     ( handle => $dbh,
       schema => $schema );

     use DBO::Visitor::Create;
     $dbo->apply_to_database('DBO::Visitor::Create');

DESCRIPTION
===========

   `DBO' is an object-oriented database abstraction layer.

   `DBO' is designed to be flexibly extensible in a number of directions -
adding new operations on the database, adding new kinds of tables or
columns, and applying to new database systems.  All extensions can be
carried out by creating new classes that inherit from the classes `DBO'
defines, and by defining new multimethod instances for those classes.

   `DBO' defines three class hierarchies:

Database operations
     An operation on a database is represented by an object belonging to
     the class `DBO::Visitor'.  `DBO' provides a number of operations
     including Create, Insert and Select.

Schema elements
     The structure of the database is represented by an object belonging to
     the class `DBO::Database', which contains a number of tables
     represented by `DBO::Table', each of which contains a number of
     columns represented by `DBO::Column'.  `DBO' defines many column
     types, including `Char', Text, `Unsigned', Integer and Time.

     Additional features of columns in the schema - such as the values in
     the column being restricted to a set of options, or the column being
     one of the keys of the table - are represented by wrapping the column
     with a `Modifier' class.  `DBO' defines the modifier classes Key,
     Option and `ForeignKey'.  Each column object belonging to the
     modifier class has a reference to another column object that describes
     the underlying type of the column.

     (This design allows a `ForeignKey' column to be implemented by a
     `Char' or Integer or whatever, as the designer wishes, without
     needing extra classes `ForeignKey_Char', `ForeignKey_Integer' and so
     on.)

Database handles
     The database itself is represented by an object belong to the class
     `DBO::Handle'.  `DBO' defines the class `DBO::Handle::DBI' as a thin
     wrapper around DBI, but the facility is there for `DBO' to be applied
     to other kinds of database (or to define more sophisticated wrappers
     around DBI such as "virtual databases" - views that include data from
     more than one database).

   The application of an operation to an element of the schema is
represented by a multimethod instance.  DBO uses three multimethods:

visit_database($visitor, $database, $handle)
visit_table($visitor, $table, $handle)
visit_column($visitor, $column, $handle)
   When $visitor is the generic visitor `DBO::Visitor', `visit_database'
visits all the tables in the database; `visit_table' visits all the
columns in the table, `visit_column' visits the base column when $column
is a `Modifier' column, and does nothing otherwise.

   See Class/Multimethods, for the full details
of the multimethod implementation.

PACKAGE OPTION
==============

   By default, the `DBO' package exports no names and expects you to use a
purely object-oriented interface.

   However, a number of constructor functions simplify the building of
schemas, and these can be imported by passing the `:constructors' key to
the `use DBO' statement.  Then you can write

     Text(name => 'address')

   as a shorthand for

     DBO::Column::Text->new(name => 'address')

THE DBO OBJECT
==============

   The `DBO' class packages up the database schema and the database handle
into one object, with a couple of convenience functions for creating and
applying operations.  (You don't need to use a `DBO' object if you don't
want to.)

   `DBO->new' takes a list of keys and values.  The following keys are
required:

schema
     A database schema, represented by an object of class `DBO::Database'.

handle
     A database handle, represented by an object of class `DBO::Handle'.

SCHEMA ELEMENTS
===============

   All constructors for schema elements are called new, and take a list of
keys and values.

`DBO::Database'
---------------

   A database.  The following key is defined:

tables
     A reference to an array of the tables in the database (each
     represented by a `DBO::Table' object).  Required.

`DBO::Table'
------------

   A table; or more specifically a view onto a table (you can have many
views onto the same table).  The following keys are defined:

id
     An identifying name for this object.  The tables belonging to a
     particular database must have different ids (this only matters when
     there is more than one view onto the same table).  If not supplied,
     the value for the name key is used instead.

name
     The name of the table in the database.  Required.

columns
     A reference to an array of the columns in the table (each represented
     by a `DBO::Column' object).  Required.

`DBO::Column'
-------------

   A generic column.

`DBO::Column::Base'
-------------------

   A column implementation in a table in the database.  The following keys
are defined:

name
     The name of the column in the table.  Required.

`not_null'
     True iff entries in the column are allowed to be NULL.

`DBO::Column::Number'
---------------------

   A column whose values are numbers.

`DBO::Column::Integer'
----------------------

   A column whose values are integers.

`DBO::Column::Unsigned'
-----------------------

   A column whose values are non-negative integers.

`DBO::Column::String'
---------------------

   A column whose values are strings.

`DBO::Column::Char'
-------------------

   A column whose values are fixed-length strings.  The following key is
defined:

max_length
     The maximum length of a value for the column.  Defaults to 10.

`DBO::Column::Text'
-------------------

   A column whose values are variable-length strings.  The following keys
are defined:

`avg_length'
     The average length of a value for the column.  Defaults to 100.  This
     is a performance hint for some databases (e.g. mSQL) and ignored
     elsewhere.

max_length
     The maximum length of a value for the column.  Defaults to 1000.  For
     databases that support arbitrarily long strings, this is ignored.

RATIONALE
=========

SEE ALSO
========

   See Class/Multimethods, (Damian Conway) for
the implementation of multimethods in Perl.

   See `DBI' in this node (Tim Bunce) for Perl's database independent
interface.

   "Design patterns: elements of reusable object-oriented software" by
Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides
(Addison-Wesley 1995) describes the Visitor pattern.

AUTHOR
======

   Gareth Rees `garethr@cre.canon.co.uk'.

COPYRIGHT
=========

   Copyright (c) 1999 Canon Research Centre Europe Ltd.  All rights
reserved.

Tied access to dbz files
************************

NAME
====

   DBZ_File - Tied access to dbz files

SYNOPSIS
========

     use DBZ_File;

     tie(%hist,DBZ_File,'/usr/lib/news/history');  # must exist
     tie(%hist,DBZ_File,'/usr/lib/news/history', O_CREAT, 0664);  # create OK

     $history_file_offset = %hist{$message_id};
     %hist{$message_id} = $history_file_offset;

     untie(%hist);

DESCRIPTION
===========

   *DBZ_File* allows perl programs to read and write a *dbz* database,
such as the news history file.

   The fetch and store functions handle all the *dbz* quirks, such as
including a null character at the end of the key and translating the
offset to/from a datum.  It also calls the dbzfetch and dbzstore
functions, which means that the key gets the same upper-/lower- case
processing that is done by the news system.

BUGS
====

   You cannot delete a hash entry, or enumerate the keys since *dbz*
doesn't support the functions necessary to support the DELETE, FIRSTKEY,
and NEXTKEY tied array functions.  If you attempt to use one of these
features, you'll get a fatal error.

   When creating a new database, the flags and umask are ignored by *dbz*,
however they must both be non-zero for the command to indicate that a
create is OK.

   You can't use multiple *dbz*-tied arrays at the same time since *dbz*
can only open one database.  If you try, the tie call returns a failure.

   This module is probably not compatible with any previous (partial)
versions of *dbz* support.  The reason for this is that they either
required the appending of a null character to the key (ick) or the use of
pack/unpack to be used with the offset value (yuck).

EXAMPLE
=======

     use DBZ_File;

     tie(%hist, DBZ_File, '/usr/lib/news/history') or die $!;
     open(HFP, '+</usr/lib/news/history') or die $!;

     # Find an entry and output its line from the history file
     if (defined($pos = $hist{'<1234@clari.net>'})) {
     	seek(HFP, $pos, 0);
     	$_ = <HFP>;
     	print;
     }

     # Write a new entry at the EOF
     seek(HFP, 0, 2);
     $msgid = '<54321@clari.net>';
     $hist{$msgid} = tell(HFP);
     print HFP "$msgid\t", time, "~-~0\n";

     close(HFP);
     untie(%hist);

AUTHOR
======

   DBZ_File was written by Wayne Davison <wayne@clari.net>.  It is based
on the NDBM_File module with a few ideas derived from an old alpha release
written by Ian Phillipps <ian@pipex.net>.  The dbz module has many names
on it, and is copyright 1988 Jon Zeeff.

Perl5 access to Berkeley DB version 1.x
***************************************

NAME
====

   DB_File - Perl5 access to Berkeley DB version 1.x

SYNOPSIS
========

     use DB_File ;

     [$X =] tie %hash,  'DB_File', [$filename, $flags, $mode, $DB_HASH] ;
     [$X =] tie %hash,  'DB_File', $filename, $flags, $mode, $DB_BTREE ;
     [$X =] tie @array, 'DB_File', $filename, $flags, $mode, $DB_RECNO ;

     $status = $X->del($key [, $flags]) ;
     $status = $X->put($key, $value [, $flags]) ;
     $status = $X->get($key, $value [, $flags]) ;
     $status = $X->seq($key, $value, $flags) ;
     $status = $X->sync([$flags]) ;
     $status = $X->fd ;

     # BTREE only
     $count = $X->get_dup($key) ;
     @list  = $X->get_dup($key) ;
     %list  = $X->get_dup($key, 1) ;
     $status = $X->find_dup($key, $value) ;
     $status = $X->del_dup($key, $value) ;

     # RECNO only
     $a = $X->length;
     $a = $X->pop ;
     $X->push(list);
     $a = $X->shift;
     $X->unshift(list);

     # DBM Filters
     $old_filter = $db->filter_store_key  ( sub { ... } ) ;
     $old_filter = $db->filter_store_value( sub { ... } ) ;
     $old_filter = $db->filter_fetch_key  ( sub { ... } ) ;
     $old_filter = $db->filter_fetch_value( sub { ... } ) ;

     untie %hash ;
     untie @array ;

DESCRIPTION
===========

   DB_File is a module which allows Perl programs to make use of the
facilities provided by Berkeley DB version 1.x (if you have a newer
version of DB, see `Using DB_File with Berkeley DB version 2 or 3' in this
node).  It is assumed that you have a copy of the Berkeley DB manual pages
at hand when reading this documentation. The interface defined here
mirrors the Berkeley DB interface closely.

   Berkeley DB is a C library which provides a consistent interface to a
number of database formats.  DB_File provides an interface to all three of
the database types currently supported by Berkeley DB.

   The file types are:

DB_HASH
     This database type allows arbitrary key/value pairs to be stored in
     data files. This is equivalent to the functionality provided by other
     hashing packages like DBM, NDBM, ODBM, GDBM, and SDBM. Remember
     though, the files created using DB_HASH are not compatible with any
     of the other packages mentioned.

     A default hashing algorithm, which will be adequate for most
     applications, is built into Berkeley DB. If you do need to use your
     own hashing algorithm it is possible to write your own in Perl and
     have DB_File use it instead.

DB_BTREE
     The btree format allows arbitrary key/value pairs to be stored in a
     sorted, balanced binary tree.

     As with the DB_HASH format, it is possible to provide a user defined
     Perl routine to perform the comparison of keys. By default, though,
     the keys are stored in lexical order.

DB_RECNO
     DB_RECNO allows both fixed-length and variable-length flat text files
     to be manipulated using the same key/value pair interface as in
     DB_HASH and DB_BTREE.  In this case the key will consist of a record
     (line) number.

Using DB_File with Berkeley DB version 2 or 3
---------------------------------------------

   Although DB_File is intended to be used with Berkeley DB version 1, it
can also be used with version 2.or 3 In this case the interface is limited
to the functionality provided by Berkeley DB 1.x. Anywhere the version 2
or 3 interface differs, DB_File arranges for it to work like version 1.
This feature allows DB_File scripts that were built with version 1 to be
migrated to version 2 or 3 without any changes.

   If you want to make use of the new features available in Berkeley DB
2.x or greater, use the Perl module *BerkeleyDB* instead.

   Note: The database file format has changed in both Berkeley DB version
2 and 3. If you cannot recreate your databases, you must dump any existing
databases with the `db_dump185' utility that comes with Berkeley DB.  Once
you have rebuilt DB_File to use Berkeley DB version 2 or 3, your databases
can be recreated using `db_load'. Refer to the Berkeley DB documentation
for further details.

   Please read `"COPYRIGHT"' in this node before using version 2.x or 3.x
of Berkeley DB with DB_File.

Interface to Berkeley DB
------------------------

   DB_File allows access to Berkeley DB files using the tie() mechanism in
Perl 5 (for full details, see `tie()', see Perlfunc (perl.info)).
This facility allows DB_File to access Berkeley DB
files using either an associative array (for DB_HASH & DB_BTREE file
types) or an ordinary array (for the DB_RECNO file type).

   In addition to the tie() interface, it is also possible to access most
of the functions provided in the Berkeley DB API directly.  See `THE API
INTERFACE' in this node.

Opening a Berkeley DB Database File
-----------------------------------

   Berkeley DB uses the function dbopen() to open or create a database.
Here is the C prototype for dbopen():

     DB*
     dbopen (const char * file, int flags, int mode,
             DBTYPE type, const void * openinfo)

   The parameter type is an enumeration which specifies which of the 3
interface methods (DB_HASH, DB_BTREE or DB_RECNO) is to be used.
Depending on which of these is actually chosen, the final parameter,
*openinfo* points to a data structure which allows tailoring of the
specific interface method.

   This interface is handled slightly differently in DB_File. Here is an
equivalent call using DB_File:

     tie %array, 'DB_File', $filename, $flags, $mode, $DB_HASH ;

   The filename, flags and mode parameters are the direct equivalent of
their dbopen() counterparts. The final parameter $DB_HASH performs the
function of both the type and `openinfo' parameters in dbopen().

   In the example above $DB_HASH is actually a pre-defined reference to a
hash object. DB_File has three of these pre-defined references.  Apart
from $DB_HASH, there is also $DB_BTREE and $DB_RECNO.

   The keys allowed in each of these pre-defined references is limited to
the names used in the equivalent C structure. So, for example, the
$DB_HASH reference will only allow keys called `bsize', `cachesize',
`ffactor', hash, `lorder' and nelem.

   To change one of these elements, just assign to it like this:

     $DB_HASH->{'cachesize'} = 10000 ;

   The three predefined variables $DB_HASH, $DB_BTREE and $DB_RECNO are
usually adequate for most applications.  If you do need to create extra
instances of these objects, constructors are available for each file type.

   Here are examples of the constructors and the valid options available
for DB_HASH, DB_BTREE and DB_RECNO respectively.

     $a = new DB_File::HASHINFO ;
     $a->{'bsize'} ;
     $a->{'cachesize'} ;
     $a->{'ffactor'};
     $a->{'hash'} ;
     $a->{'lorder'} ;
     $a->{'nelem'} ;

     $b = new DB_File::BTREEINFO ;
     $b->{'flags'} ;
     $b->{'cachesize'} ;
     $b->{'maxkeypage'} ;
     $b->{'minkeypage'} ;
     $b->{'psize'} ;
     $b->{'compare'} ;
     $b->{'prefix'} ;
     $b->{'lorder'} ;

     $c = new DB_File::RECNOINFO ;
     $c->{'bval'} ;
     $c->{'cachesize'} ;
     $c->{'psize'} ;
     $c->{'flags'} ;
     $c->{'lorder'} ;
     $c->{'reclen'} ;
     $c->{'bfname'} ;

   The values stored in the hashes above are mostly the direct equivalent
of their C counterpart. Like their C counterparts, all are set to a
default values - that means you don't have to set all of the values when
you only want to change one. Here is an example:

     $a = new DB_File::HASHINFO ;
     $a->{'cachesize'} =  12345 ;
     tie %y, 'DB_File', "filename", $flags, 0777, $a ;

   A few of the options need extra discussion here. When used, the C
equivalent of the keys hash, compare and prefix store pointers to C
functions. In DB_File these keys are used to store references to Perl
subs. Below are templates for each of the subs:

     sub hash
     {
         my ($data) = @_ ;
         ...
         # return the hash value for $data
     	return $hash ;
     }

     sub compare
     {
     	my ($key, $key2) = @_ ;
         ...
         # return  0 if $key1 eq $key2
         #        -1 if $key1 lt $key2
         #         1 if $key1 gt $key2
         return (-1 , 0 or 1) ;
     }

     sub prefix
     {
     	my ($key, $key2) = @_ ;
         ...
         # return number of bytes of $key2 which are
         # necessary to determine that it is greater than $key1
         return $bytes ;
     }

   See `Changing the BTREE sort order' in this node for an example of
using the compare template.

   If you are using the DB_RECNO interface and you intend making use of
`bval', you should check out `The 'bval' Option' in this node.

Default Parameters
------------------

   It is possible to omit some or all of the final 4 parameters in the
call to tie and let them take default values. As DB_HASH is the most
common file format used, the call:

     tie %A, "DB_File", "filename" ;

   is equivalent to:

     tie %A, "DB_File", "filename", O_CREAT|O_RDWR, 0666, $DB_HASH ;

   It is also possible to omit the filename parameter as well, so the call:

     tie %A, "DB_File" ;

   is equivalent to:

     tie %A, "DB_File", undef, O_CREAT|O_RDWR, 0666, $DB_HASH ;

   See `In Memory Databases' in this node for a discussion on the use of
undef in place of a filename.

In Memory Databases
-------------------

   Berkeley DB allows the creation of in-memory databases by using NULL
(that is, a `(char *)0' in C) in place of the filename.  DB_File uses
undef instead of NULL to provide this functionality.

DB_HASH
=======

   The DB_HASH file format is probably the most commonly used of the three
file formats that DB_File supports. It is also very straightforward to use.

A Simple Example
----------------

   This example shows how to create a database, add key/value pairs to the
database, delete keys/value pairs and finally how to enumerate the
contents of the database.

     use warnings ;
     use strict ;
     use DB_File ;
     use vars qw( %h $k $v ) ;

     unlink "fruit" ;
     tie %h, "DB_File", "fruit", O_RDWR|O_CREAT, 0640, $DB_HASH
         or die "Cannot open file 'fruit': $!\n";

     # Add a few key/value pairs to the file
     $h{"apple"} = "red" ;
     $h{"orange"} = "orange" ;
     $h{"banana"} = "yellow" ;
     $h{"tomato"} = "red" ;

     # Check for existence of a key
     print "Banana Exists\n\n" if $h{"banana"} ;

     # Delete a key/value pair.
     delete $h{"apple"} ;

     # print the contents of the file
     while (($k, $v) = each %h)
       { print "$k -> $v\n" }

     untie %h ;

   here is the output:

     Banana Exists

     orange -> orange
     tomato -> red
     banana -> yellow

   Note that the like ordinary associative arrays, the order of the keys
retrieved is in an apparently random order.

DB_BTREE
========

   The DB_BTREE format is useful when you want to store data in a given
order. By default the keys will be stored in lexical order, but as you
will see from the example shown in the next section, it is very easy to
define your own sorting function.

Changing the BTREE sort order
-----------------------------

   This script shows how to override the default sorting algorithm that
BTREE uses. Instead of using the normal lexical ordering, a case
insensitive compare function will be used.

     use warnings ;
     use strict ;
     use DB_File ;

     my %h ;

     sub Compare
     {
         my ($key1, $key2) = @_ ;
         "\L$key1" cmp "\L$key2" ;
     }

     # specify the Perl sub that will do the comparison
     $DB_BTREE->{'compare'} = \&Compare ;

     unlink "tree" ;
     tie %h, "DB_File", "tree", O_RDWR|O_CREAT, 0640, $DB_BTREE
         or die "Cannot open file 'tree': $!\n" ;

     # Add a key/value pair to the file
     $h{'Wall'} = 'Larry' ;
     $h{'Smith'} = 'John' ;
     $h{'mouse'} = 'mickey' ;
     $h{'duck'}  = 'donald' ;

     # Delete
     delete $h{"duck"} ;

     # Cycle through the keys printing them in order.
     # Note it is not necessary to sort the keys as
     # the btree will have kept them in order automatically.
     foreach (keys %h)
       { print "$_\n" }

     untie %h ;

   Here is the output from the code above.

     mouse
     Smith
     Wall

   There are a few point to bear in mind if you want to change the
ordering in a BTREE database:

  1. The new compare function must be specified when you create the
     database.

  2. You cannot change the ordering once the database has been created.
     Thus you must use the same compare function every time you access the
     database.

Handling Duplicate Keys
-----------------------

   The BTREE file type optionally allows a single key to be associated
with an arbitrary number of values. This option is enabled by setting the
flags element of `$DB_BTREE' to R_DUP when creating the database.

   There are some difficulties in using the tied hash interface if you
want to manipulate a BTREE database with duplicate keys. Consider this
code:

     use warnings ;
     use strict ;
     use DB_File ;

     use vars qw($filename %h ) ;

     $filename = "tree" ;
     unlink $filename ;

     # Enable duplicate records
     $DB_BTREE->{'flags'} = R_DUP ;

     tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
     	or die "Cannot open $filename: $!\n";

     # Add some key/value pairs to the file
     $h{'Wall'} = 'Larry' ;
     $h{'Wall'} = 'Brick' ; # Note the duplicate key
     $h{'Wall'} = 'Brick' ; # Note the duplicate key and value
     $h{'Smith'} = 'John' ;
     $h{'mouse'} = 'mickey' ;

     # iterate through the associative array
     # and print each key/value pair.
     foreach (sort keys %h)
       { print "$_  -> $h{$_}\n" }

     untie %h ;

   Here is the output:

     Smith   -> John
     Wall    -> Larry
     Wall    -> Larry
     Wall    -> Larry
     mouse   -> mickey

   As you can see 3 records have been successfully created with key `Wall'
- the only thing is, when they are retrieved from the database they *seem*
to have the same value, namely `Larry'. The problem is caused by the way
that the associative array interface works. Basically, when the
associative array interface is used to fetch the value associated with a
given key, it will only ever retrieve the first value.

   Although it may not be immediately obvious from the code above, the
associative array interface can be used to write values with duplicate
keys, but it cannot be used to read them back from the database.

   The way to get around this problem is to use the Berkeley DB API method
called seq.  This method allows sequential access to key/value pairs. See
`THE API INTERFACE' in this node for details of both the seq method and
the API in general.

   Here is the script above rewritten using the seq API method.

     use warnings ;
     use strict ;
     use DB_File ;

     use vars qw($filename $x %h $status $key $value) ;

     $filename = "tree" ;
     unlink $filename ;

     # Enable duplicate records
     $DB_BTREE->{'flags'} = R_DUP ;

     $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
     	or die "Cannot open $filename: $!\n";

     # Add some key/value pairs to the file
     $h{'Wall'} = 'Larry' ;
     $h{'Wall'} = 'Brick' ; # Note the duplicate key
     $h{'Wall'} = 'Brick' ; # Note the duplicate key and value
     $h{'Smith'} = 'John' ;
     $h{'mouse'} = 'mickey' ;

     # iterate through the btree using seq
     # and print each key/value pair.
     $key = $value = 0 ;
     for ($status = $x->seq($key, $value, R_FIRST) ;
          $status == 0 ;
          $status = $x->seq($key, $value, R_NEXT) )
       {  print "$key -> $value\n" }

     undef $x ;
     untie %h ;

   that prints:

     Smith   -> John
     Wall    -> Brick
     Wall    -> Brick
     Wall    -> Larry
     mouse   -> mickey

   This time we have got all the key/value pairs, including the multiple
values associated with the key `Wall'.

   To make life easier when dealing with duplicate keys, DB_File comes with
a few utility methods.

The get_dup() Method
--------------------

   The `get_dup' method assists in reading duplicate values from BTREE
databases. The method can take the following forms:

     $count = $x->get_dup($key) ;
     @list  = $x->get_dup($key) ;
     %list  = $x->get_dup($key, 1) ;

   In a scalar context the method returns the number of values associated
with the key, $key.

   In list context, it returns all the values which match $key. Note that
the values will be returned in an apparently random order.

   In list context, if the second parameter is present and evaluates TRUE,
the method returns an associative array. The keys of the associative array
correspond to the values that matched in the BTREE and the values of the
array are a count of the number of times that particular value occurred in
the BTREE.

   So assuming the database created above, we can use `get_dup' like this:

     use warnings ;
     use strict ;
     use DB_File ;

     use vars qw($filename $x %h ) ;

     $filename = "tree" ;

     # Enable duplicate records
     $DB_BTREE->{'flags'} = R_DUP ;

     $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
     	or die "Cannot open $filename: $!\n";

     my $cnt  = $x->get_dup("Wall") ;
     print "Wall occurred $cnt times\n" ;

     my %hash = $x->get_dup("Wall", 1) ;
     print "Larry is there\n" if $hash{'Larry'} ;
     print "There are $hash{'Brick'} Brick Walls\n" ;

     my @list = sort $x->get_dup("Wall") ;
     print "Wall =>	[@list]\n" ;

     @list = $x->get_dup("Smith") ;
     print "Smith =>	[@list]\n" ;

     @list = $x->get_dup("Dog") ;
     print "Dog =>	[@list]\n" ;

   and it will print:

     Wall occurred 3 times
     Larry is there
     There are 2 Brick Walls
     Wall =>	[Brick Brick Larry]
     Smith =>	[John]
     Dog =>	[]

The find_dup() Method
---------------------

     $status = $X->find_dup($key, $value) ;

   This method checks for the existence of a specific key/value pair. If
the pair exists, the cursor is left pointing to the pair and the method
returns 0. Otherwise the method returns a non-zero value.

   Assuming the database from the previous example:

     use warnings ;
     use strict ;
     use DB_File ;

     use vars qw($filename $x %h $found) ;

     my $filename = "tree" ;

     # Enable duplicate records
     $DB_BTREE->{'flags'} = R_DUP ;

     $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
     	or die "Cannot open $filename: $!\n";

     $found = ( $x->find_dup("Wall", "Larry") == 0 ? "" : "not") ;
     print "Larry Wall is $found there\n" ;

     $found = ( $x->find_dup("Wall", "Harry") == 0 ? "" : "not") ;
     print "Harry Wall is $found there\n" ;

     undef $x ;
     untie %h ;

   prints this

     Larry Wall is  there
     Harry Wall is not there

The del_dup() Method
--------------------

     $status = $X->del_dup($key, $value) ;

   This method deletes a specific key/value pair. It returns 0 if they
exist and have been deleted successfully.  Otherwise the method returns a
non-zero value.

   Again assuming the existence of the `tree' database

     use warnings ;
     use strict ;
     use DB_File ;

     use vars qw($filename $x %h $found) ;

     my $filename = "tree" ;

     # Enable duplicate records
     $DB_BTREE->{'flags'} = R_DUP ;

     $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
     	or die "Cannot open $filename: $!\n";

     $x->del_dup("Wall", "Larry") ;

     $found = ( $x->find_dup("Wall", "Larry") == 0 ? "" : "not") ;
     print "Larry Wall is $found there\n" ;

     undef $x ;
     untie %h ;

   prints this

     Larry Wall is not there

Matching Partial Keys
---------------------

   The BTREE interface has a feature which allows partial keys to be
matched. This functionality is *only* available when the seq method is
used along with the R_CURSOR flag.

     $x->seq($key, $value, R_CURSOR) ;

   Here is the relevant quote from the dbopen man page where it defines
the use of the R_CURSOR flag with seq:

     Note, for the DB_BTREE access method, the returned key is not
     necessarily an exact match for the specified key. The returned key
     is the smallest key greater than or equal to the specified key,
     permitting partial key matches and range searches.

   In the example script below, the match sub uses this feature to find
and print the first matching key/value pair given a partial key.

     use warnings ;
     use strict ;
     use DB_File ;
     use Fcntl ;

     use vars qw($filename $x %h $st $key $value) ;

     sub match
     {
         my $key = shift ;
         my $value = 0;
         my $orig_key = $key ;
         $x->seq($key, $value, R_CURSOR) ;
         print "$orig_key\t-> $key\t-> $value\n" ;
     }

     $filename = "tree" ;
     unlink $filename ;

     $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE
         or die "Cannot open $filename: $!\n";

     # Add some key/value pairs to the file
     $h{'mouse'} = 'mickey' ;
     $h{'Wall'} = 'Larry' ;
     $h{'Walls'} = 'Brick' ;
     $h{'Smith'} = 'John' ;

     $key = $value = 0 ;
     print "IN ORDER\n" ;
     for ($st = $x->seq($key, $value, R_FIRST) ;
     	 $st == 0 ;
          $st = $x->seq($key, $value, R_NEXT) )

       {  print "$key	-> $value\n" }

     print "\nPARTIAL MATCH\n" ;

     match "Wa" ;
     match "A" ;
     match "a" ;

     undef $x ;
     untie %h ;

   Here is the output:

     IN ORDER
     Smith -> John
     Wall  -> Larry
     Walls -> Brick
     mouse -> mickey

     PARTIAL MATCH
     Wa -> Wall  -> Larry
     A  -> Smith -> John
     a  -> mouse -> mickey

DB_RECNO
========

   DB_RECNO provides an interface to flat text files. Both variable and
fixed length records are supported.

   In order to make RECNO more compatible with Perl, the array offset for
all RECNO arrays begins at 0 rather than 1 as in Berkeley DB.

   As with normal Perl arrays, a RECNO array can be accessed using
negative indexes. The index -1 refers to the last element of the array, -2
the second last, and so on. Attempting to access an element before the
start of the array will raise a fatal run-time error.

The 'bval' Option
-----------------

   The operation of the bval option warrants some discussion. Here is the
definition of bval from the Berkeley DB 1.85 recno manual page:

     The delimiting byte to be used to mark  the  end  of  a
     record for variable-length records, and the pad charac-
     ter for fixed-length records.  If no  value  is  speci-
     fied,  newlines  (``\n'')  are  used to mark the end of
     variable-length records and  fixed-length  records  are
     padded with spaces.

   The second sentence is wrong. In actual fact bval will only default to
`"\n"' when the openinfo parameter in dbopen is NULL. If a non-NULL
openinfo parameter is used at all, the value that happens to be in bval
will be used. That means you always have to specify bval when making use
of any of the options in the openinfo parameter. This documentation error
will be fixed in the next release of Berkeley DB.

   That clarifies the situation with regards Berkeley DB itself. What
about DB_File? Well, the behavior defined in the quote above is quite
useful, so DB_File conforms to it.

   That means that you can specify other options (e.g. cachesize) and
still have bval default to `"\n"' for variable length records, and space
for fixed length records.

A Simple Example
----------------

   Here is a simple example that uses RECNO (if you are using a version of
Perl earlier than 5.004_57 this example won't work - see `Extra RECNO
Methods' in this node for a workaround).

     use warnings ;
     use strict ;
     use DB_File ;

     my $filename = "text" ;
     unlink $filename ;

     my @h ;
     tie @h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_RECNO
         or die "Cannot open file 'text': $!\n" ;

     # Add a few key/value pairs to the file
     $h[0] = "orange" ;
     $h[1] = "blue" ;
     $h[2] = "yellow" ;

     push @h, "green", "black" ;

     my $elements = scalar @h ;
     print "The array contains $elements entries\n" ;

     my $last = pop @h ;
     print "popped $last\n" ;

     unshift @h, "white" ;
     my $first = shift @h ;
     print "shifted $first\n" ;

     # Check for existence of a key
     print "Element 1 Exists with value $h[1]\n" if $h[1] ;

     # use a negative index
     print "The last element is $h[-1]\n" ;
     print "The 2nd last element is $h[-2]\n" ;

     untie @h ;

   Here is the output from the script:

     The array contains 5 entries
     popped black
     shifted white
     Element 1 Exists with value blue
     The last element is green
     The 2nd last element is yellow

Extra RECNO Methods
-------------------

   If you are using a version of Perl earlier than 5.004_57, the tied
array interface is quite limited. In the example script above push, pop,
shift, unshift or determining the array length will not work with a tied
array.

   To make the interface more useful for older versions of Perl, a number
of methods are supplied with DB_File to simulate the missing array
operations. All these methods are accessed via the object returned from
the tie call.

   Here are the methods:

*$X->push(list) ;*
     Pushes the elements of list to the end of the array.

*$value = $X->pop ;*
     Removes and returns the last element of the array.

*$X->shift*
     Removes and returns the first element of the array.

*$X->unshift(list) ;*
     Pushes the elements of list to the start of the array.

*$X->length*
     Returns the number of elements in the array.

Another Example
---------------

   Here is a more complete example that makes use of some of the methods
described above. It also makes use of the API interface directly (see `THE
API INTERFACE' in this node).

     use warnings ;
     use strict ;
     use vars qw(@h $H $file $i) ;
     use DB_File ;
     use Fcntl ;

     $file = "text" ;

     unlink $file ;

     $H = tie @h, "DB_File", $file, O_RDWR|O_CREAT, 0640, $DB_RECNO
         or die "Cannot open file $file: $!\n" ;

     # first create a text file to play with
     $h[0] = "zero" ;
     $h[1] = "one" ;
     $h[2] = "two" ;
     $h[3] = "three" ;
     $h[4] = "four" ;

     # Print the records in order.
         #
         # The length method is needed here because evaluating a tied
         # array in a scalar context does not return the number of
         # elements in the array.

     print "\nORIGINAL\n" ;
     foreach $i (0 .. $H->length - 1) {
         print "$i: $h[$i]\n" ;
     }

     # use the push & pop methods
     $a = $H->pop ;
     $H->push("last") ;
     print "\nThe last record was [$a]\n" ;

     # and the shift & unshift methods
     $a = $H->shift ;
     $H->unshift("first") ;
     print "The first record was [$a]\n" ;

     # Use the API to add a new record after record 2.
     $i = 2 ;
     $H->put($i, "Newbie", R_IAFTER) ;

     # and a new record before record 1.
     $i = 1 ;
     $H->put($i, "New One", R_IBEFORE) ;

     # delete record 3
     $H->del(3) ;

     # now print the records in reverse order
     print "\nREVERSE\n" ;
     for ($i = $H->length - 1 ; $i >= 0 ; -- $i)
       { print "$i: $h[$i]\n" }

     # same again, but use the API functions instead
     print "\nREVERSE again\n" ;
     my ($s, $k, $v)  = (0, 0, 0) ;
     for ($s = $H->seq($k, $v, R_LAST) ;
              $s == 0 ;
              $s = $H->seq($k, $v, R_PREV))
       { print "$k: $v\n" }

     undef $H ;
     untie @h ;

   and this is what it outputs:

     ORIGINAL
     0: zero
     1: one
     2: two
     3: three
     4: four

     The last record was [four]
     The first record was [zero]

     REVERSE
     5: last
     4: three
     3: Newbie
     2: one
     1: New One
     0: first

     REVERSE again
     5: last
     4: three
     3: Newbie
     2: one
     1: New One
     0: first

   Notes:

  1. Rather than iterating through the array, `@h' like this:

          foreach $i (@h)

     it is necessary to use either this:

          foreach $i (0 .. $H->length - 1)

     or this:

          for ($a = $H->get($k, $v, R_FIRST) ;
               $a == 0 ;
               $a = $H->get($k, $v, R_NEXT) )

  2. Notice that both times the put method was used the record index was
     specified using a variable, $i, rather than the literal value itself.
     This is because put will return the record number of the inserted
     line via that parameter.

THE API INTERFACE
=================

   As well as accessing Berkeley DB using a tied hash or array, it is also
possible to make direct use of most of the API functions defined in the
Berkeley DB documentation.

   To do this you need to store a copy of the object returned from the tie.

     $db = tie %hash, "DB_File", "filename" ;

   Once you have done that, you can access the Berkeley DB API functions
as DB_File methods directly like this:

     $db->put($key, $value, R_NOOVERWRITE) ;

   *Important:* If you have saved a copy of the object returned from tie,
the underlying database file will not be closed until both the tied
variable is untied and all copies of the saved object are destroyed.

     use DB_File ;
     $db = tie %hash, "DB_File", "filename"
         or die "Cannot tie filename: $!" ;
     ...
     undef $db ;
     untie %hash ;

   See `The untie() Gotcha' in this node for more details.

   All the functions defined in `dbopen' in this node are available except
for close() and dbopen() itself. The DB_File method interface to the
supported functions have been implemented to mirror the way Berkeley DB
works whenever possible. In particular note that:

   * The methods return a status value. All return 0 on success.  All
     return -1 to signify an error and set $! to the exact error code. The
     return code 1 generally (but not always) means that the key specified
     did not exist in the database.

     Other return codes are defined. See below and in the Berkeley DB
     documentation for details. The Berkeley DB documentation should be
     used as the definitive source.

   * Whenever a Berkeley DB function returns data via one of its
     parameters, the equivalent DB_File method does exactly the same.

   * If you are careful, it is possible to mix API calls with the tied
     hash/array interface in the same piece of code. Although only a few of
     the methods used to implement the tied interface currently make use of
     the cursor, you should always assume that the cursor has been changed
     any time the tied hash/array interface is used. As an example, this
     code will probably not do what you expect:

          $X = tie %x, 'DB_File', $filename, O_RDWR|O_CREAT, 0777, $DB_BTREE
              or die "Cannot tie $filename: $!" ;

          # Get the first key/value pair and set  the cursor
          $X->seq($key, $value, R_FIRST) ;

          # this line will modify the cursor
          $count = scalar keys %x ;

          # Get the second key/value pair.
          # oops, it didn't, it got the last key/value pair!
          $X->seq($key, $value, R_NEXT) ;

     The code above can be rearranged to get around the problem, like this:

          $X = tie %x, 'DB_File', $filename, O_RDWR|O_CREAT, 0777, $DB_BTREE
              or die "Cannot tie $filename: $!" ;

          # this line will modify the cursor
          $count = scalar keys %x ;

          # Get the first key/value pair and set  the cursor
          $X->seq($key, $value, R_FIRST) ;

          # Get the second key/value pair.
          # worked this time.
          $X->seq($key, $value, R_NEXT) ;

   All the constants defined in `dbopen' in this node for use in the flags
parameters in the methods defined below are also available. Refer to the
Berkeley DB documentation for the precise meaning of the flags values.

   Below is a list of the methods available.

*$status = $X->get($key, $value [, $flags]) ;*
     Given a key ($key) this method reads the value associated with it
     from the database. The value read from the database is returned in the
     $value parameter.

     If the key does not exist the method returns 1.

     No flags are currently defined for this method.

*$status = $X->put($key, $value [, $flags]) ;*
     Stores the key/value pair in the database.

     If you use either the R_IAFTER or R_IBEFORE flags, the $key parameter
     will have the record number of the inserted key/value pair set.

     Valid flags are R_CURSOR, R_IAFTER, R_IBEFORE, R_NOOVERWRITE and
     R_SETCURSOR.

*$status = $X->del($key [, $flags]) ;*
     Removes all key/value pairs with key $key from the database.

     A return code of 1 means that the requested key was not in the
     database.

     R_CURSOR is the only valid flag at present.

*$status = $X->fd ;*
     Returns the file descriptor for the underlying database.

     See `Locking: The Trouble with fd' in this node for an explanation
     for why you should not use fd to lock your database.

*$status = $X->seq($key, $value, $flags) ;*
     This interface allows sequential retrieval from the database. See
     `dbopen' in this node for full details.

     Both the $key and $value parameters will be set to the key/value pair
     read from the database.

     The flags parameter is mandatory. The valid flag values are R_CURSOR,
     R_FIRST, R_LAST, R_NEXT and R_PREV.

*$status = $X->sync([$flags]) ;*
     Flushes any cached buffers to disk.

     R_RECNOSYNC is the only valid flag at present.

DBM FILTERS
===========

   A DBM Filter is a piece of code that is be used when you always want to
make the same transformation to all keys and/or values in a DBM database.

   There are four methods associated with DBM Filters. All work
identically, and each is used to install (or uninstall) a single DBM
Filter. Each expects a single parameter, namely a reference to a sub. The
only difference between them is the place that the filter is installed.

   To summarise:

filter_store_key
     If a filter has been installed with this method, it will be invoked
     every time you write a key to a DBM database.

filter_store_value
     If a filter has been installed with this method, it will be invoked
     every time you write a value to a DBM database.

filter_fetch_key
     If a filter has been installed with this method, it will be invoked
     every time you read a key from a DBM database.

filter_fetch_value
     If a filter has been installed with this method, it will be invoked
     every time you read a value from a DBM database.

   You can use any combination of the methods, from none, to all four.

   All filter methods return the existing filter, if present, or undef in
not.

   To delete a filter pass undef to it.

The Filter
----------

   When each filter is called by Perl, a local copy of $_ will contain the
key or value to be filtered. Filtering is achieved by modifying the
contents of $_. The return code from the filter is ignored.

An Example - the NULL termination problem.
------------------------------------------

   Consider the following scenario. You have a DBM database that you need
to share with a third-party C application. The C application assumes that
all keys and values are NULL terminated. Unfortunately when Perl writes to
DBM databases it doesn't use NULL termination, so your Perl application
will have to manage NULL termination itself. When you write to the
database you will have to use something like this:

     $hash{"$key\0"} = "$value\0" ;

   Similarly the NULL needs to be taken into account when you are
considering the length of existing keys/values.

   It would be much better if you could ignore the NULL terminations issue
in the main application code and have a mechanism that automatically added
the terminating NULL to all keys and values whenever you write to the
database and have them removed when you read from the database. As I'm
sure you have already guessed, this is a problem that DBM Filters can fix
very easily.

     use warnings ;
     use strict ;
     use DB_File ;

     my %hash ;
     my $filename = "/tmp/filt" ;
     unlink $filename ;

     my $db = tie %hash, 'DB_File', $filename, O_CREAT|O_RDWR, 0666, $DB_HASH
       or die "Cannot open $filename: $!\n" ;

     # Install DBM Filters
     $db->filter_fetch_key  ( sub { s/\0$//    } ) ;
     $db->filter_store_key  ( sub { $_ .= "\0" } ) ;
     $db->filter_fetch_value( sub { s/\0$//    } ) ;
     $db->filter_store_value( sub { $_ .= "\0" } ) ;

     $hash{"abc"} = "def" ;
     my $a = $hash{"ABC"} ;
     # ...
     undef $db ;
     untie %hash ;

   Hopefully the contents of each of the filters should be
self-explanatory. Both "fetch" filters remove the terminating NULL, and
both "store" filters add a terminating NULL.

Another Example - Key is a C int.
---------------------------------

   Here is another real-life example. By default, whenever Perl writes to
a DBM database it always writes the key and value as strings. So when you
use this:

     $hash{12345} = "soemthing" ;

   the key 12345 will get stored in the DBM database as the 5 byte string
"12345". If you actually want the key to be stored in the DBM database as
a C int, you will have to use pack when writing, and unpack when reading.

   Here is a DBM Filter that does it:

     use warnings ;
     use strict ;
     use DB_File ;
     my %hash ;
     my $filename = "/tmp/filt" ;
     unlink $filename ;

     my $db = tie %hash, 'DB_File', $filename, O_CREAT|O_RDWR, 0666, $DB_HASH
       or die "Cannot open $filename: $!\n" ;

     $db->filter_fetch_key  ( sub { $_ = unpack("i", $_) } ) ;
     $db->filter_store_key  ( sub { $_ = pack ("i", $_) } ) ;
     $hash{123} = "def" ;
     # ...
     undef $db ;
     untie %hash ;

   This time only two filters have been used - we only need to manipulate
the contents of the key, so it wasn't necessary to install any value
filters.

HINTS AND TIPS
==============

Locking: The Trouble with fd
----------------------------

   Until version 1.72 of this module, the recommended technique for locking
DB_File databases was to flock the filehandle returned from the "fd"
function. Unfortunately this technique has been shown to be fundamentally
flawed (Kudos to David Harris for tracking this down). Use it at your own
peril!

   The locking technique went like this.

     $db = tie(%db, 'DB_File', '/tmp/foo.db', O_CREAT|O_RDWR, 0644)
         || die "dbcreat /tmp/foo.db $!";
     $fd = $db->fd;
     open(DB_FH, "+<&=$fd") || die "dup $!";
     flock (DB_FH, LOCK_EX) || die "flock: $!";
     ...
     $db{"Tom"} = "Jerry" ;
     ...
     flock(DB_FH, LOCK_UN);
     undef $db;
     untie %db;
     close(DB_FH);

   In simple terms, this is what happens:

  1. Use "tie" to open the database.

  2. Lock the database with fd & flock.

  3. Read & Write to the database.

  4. Unlock and close the database.

        Here is the crux of the problem. A side-effect of opening the
DB_File database in step 2 is that an initial block from the database will
get read from disk and cached in memory.

   To see why this is a problem, consider what can happen when two
processes, say "A" and "B", both want to update the same DB_File database
using the locking steps outlined above. Assume process "A" has already
opened the database and has a write lock, but it hasn't actually updated
the database yet (it has finished step 2, but not started step 3 yet). Now
process "B" tries to open the same database - step 1 will succeed, but it
will block on step 2 until process "A" releases the lock. The important
thing to notice here is that at this point in time both processes will
have cached identical initial blocks from the database.

   Now process "A" updates the database and happens to change some of the
data held in the initial buffer. Process "A" terminates, flushing all
cached data to disk and releasing the database lock. At this point the
database on disk will correctly reflect the changes made by process "A".

   With the lock released, process "B" can now continue. It also updates
the database and unfortunately it too modifies the data that was in its
initial buffer. Once that data gets flushed to disk it will overwrite
some/all of the changes process "A" made to the database.

   The result of this scenario is at best a database that doesn't contain
what you expect. At worst the database will corrupt.

   The above won't happen every time competing process update the same
DB_File database, but it does illustrate why the technique should not be
used.

Safe ways to lock a database
----------------------------

   Starting with version 2.x, Berkeley DB  has internal support for
locking.  The companion module to this one, *BerkeleyDB*, provides an
interface to this locking functionality. If you are serious about locking
Berkeley DB databases, I strongly recommend using *BerkeleyDB*.

   If using *BerkeleyDB* isn't an option, there are a number of modules
available on CPAN that can be used to implement locking. Each one
implements locking differently and has different goals in mind. It is
therefore worth knowing the difference, so that you can pick the right one
for your application. Here are the three locking wrappers:

Tie::DB_Lock
     A DB_File wrapper which creates copies of the database file for read
     access, so that you have a kind of a multiversioning concurrent read
     system. However, updates are still serial. Use for databases where
     reads may be lengthy and consistency problems may occur.

Tie::DB_LockFile
     A DB_File wrapper that has the ability to lock and unlock the database
     while it is being used. Avoids the tie-before-flock problem by simply
     re-tie-ing the database when you get or drop a lock.  Because of the
     flexibility in dropping and re-acquiring the lock in the middle of a
     session, this can be massaged into a system that will work with long
     updates and/or reads if the application follows the hints in the POD
     documentation.

DB_File::Lock
     An extremely lightweight DB_File wrapper that simply flocks a lockfile
     before tie-ing the database and drops the lock after the untie. Allows
     one to use the same lockfile for multiple databases to avoid deadlock
     problems, if desired. Use for databases where updates are reads are
     quick and simple flock locking semantics are enough.

Sharing Databases With C Applications
-------------------------------------

   There is no technical reason why a Berkeley DB database cannot be
shared by both a Perl and a C application.

   The vast majority of problems that are reported in this area boil down
to the fact that C strings are NULL terminated, whilst Perl strings are
not. See `DBM FILTERS' in this node for a generic way to work around this
problem.

   Here is a real example. Netscape 2.0 keeps a record of the locations you
visit along with the time you last visited them in a DB_HASH database.
This is usually stored in the file `~/.netscape/history.db'. The key field
in the database is the location string and the value field is the time the
location was last visited stored as a 4 byte binary value.

   If you haven't already guessed, the location string is stored with a
terminating NULL. This means you need to be careful when accessing the
database.

   Here is a snippet of code that is loosely based on Tom Christiansen's
*ggh* script (available from your nearest CPAN archive in
`authors/id/TOMC/scripts/nshist.gz').

     use warnings ;
     use strict ;
     use DB_File ;
     use Fcntl ;

     use vars qw( $dotdir $HISTORY %hist_db $href $binary_time $date ) ;
     $dotdir = $ENV{HOME} || $ENV{LOGNAME};

     $HISTORY = "$dotdir/.netscape/history.db";

     tie %hist_db, 'DB_File', $HISTORY
         or die "Cannot open $HISTORY: $!\n" ;;

     # Dump the complete database
     while ( ($href, $binary_time) = each %hist_db ) {

     # remove the terminating NULL
     $href =~ s/\x00$// ;

     # convert the binary time into a user friendly string
     $date = localtime unpack("V", $binary_time);
     print "$date $href\n" ;
         }

     # check for the existence of a specific key
     # remember to add the NULL
     if ( $binary_time = $hist_db{"http://mox.perl.com/\x00"} ) {
         $date = localtime unpack("V", $binary_time) ;
         print "Last visited mox.perl.com on $date\n" ;
     }
     else {
         print "Never visited mox.perl.com\n"
     }

     untie %hist_db ;

The untie() Gotcha
------------------

   If you make use of the Berkeley DB API, it is *very* strongly
recommended that you read `The untie Gotcha', see Perltie (perl.info).

   Even if you don't currently make use of the API interface, it is still
worth reading it.

   Here is an example which illustrates the problem from a DB_File
perspective:

     use DB_File ;
     use Fcntl ;

     my %x ;
     my $X ;

     $X = tie %x, 'DB_File', 'tst.fil' , O_RDWR|O_TRUNC
         or die "Cannot tie first time: $!" ;

     $x{123} = 456 ;

     untie %x ;

     tie %x, 'DB_File', 'tst.fil' , O_RDWR|O_CREAT
         or die "Cannot tie second time: $!" ;

     untie %x ;

   When run, the script will produce this error message:

     Cannot tie second time: Invalid argument at bad.file line 14.

   Although the error message above refers to the second tie() statement
in the script, the source of the problem is really with the untie()
statement that precedes it.

   Having read Perltie (perl.info), you will probably have
already guessed that the error is caused by the extra copy of the tied
object stored in `$X'.  If you haven't, then the problem boils down to the
fact that the DB_File destructor, DESTROY, will not be called until all
references to the tied object are destroyed. Both the tied variable, `%x',
and `$X' above hold a reference to the object. The call to untie() will
destroy the first, but `$X' still holds a valid reference, so the
destructor will not get called and the database file `tst.fil' will remain
open. The fact that Berkeley DB then reports the attempt to open a
database that is already open via the catch-all "Invalid argument" doesn't
help.

   If you run the script with the -w flag the error message becomes:

     untie attempted while 1 inner references still exist at bad.file line 12.
     Cannot tie second time: Invalid argument at bad.file line 14.

   which pinpoints the real problem. Finally the script can now be
modified to fix the original problem by destroying the API object before
the untie:

     ...
     $x{123} = 456 ;

     undef $X ;
     untie %x ;

     $X = tie %x, 'DB_File', 'tst.fil' , O_RDWR|O_CREAT
     ...

COMMON QUESTIONS
================

Why is there Perl source in my database?
----------------------------------------

   If you look at the contents of a database file created by DB_File,
there can sometimes be part of a Perl script included in it.

   This happens because Berkeley DB uses dynamic memory to allocate
buffers which will subsequently be written to the database file. Being
dynamic, the memory could have been used for anything before DB malloced
it. As Berkeley DB doesn't clear the memory once it has been allocated,
the unused portions will contain random junk. In the case where a Perl
script gets written to the database, the random junk will correspond to an
area of dynamic memory that happened to be used during the compilation of
the script.

   Unless you don't like the possibility of there being part of your Perl
scripts embedded in a database file, this is nothing to worry about.

How do I store complex data structures with DB_File?
----------------------------------------------------

   Although DB_File cannot do this directly, there is a module which can
layer transparently over DB_File to accomplish this feat.

   Check out the MLDBM module, available on CPAN in the directory
`modules/by-module/MLDBM'.

What does "Invalid Argument" mean?
----------------------------------

   You will get this error message when one of the parameters in the tie
call is wrong. Unfortunately there are quite a few parameters to get
wrong, so it can be difficult to figure out which one it is.

   Here are a couple of possibilities:

  1. Attempting to reopen a database without closing it.

  2. Using the O_WRONLY flag.

What does "Bareword 'DB_File' not allowed" mean?
------------------------------------------------

   You will encounter this particular error message when you have the
`strict 'subs'' pragma (or the full strict pragma) in your script.
Consider this script:

     use warnings ;
     use strict ;
     use DB_File ;
     use vars qw(%x) ;
     tie %x, DB_File, "filename" ;

   Running it produces the error in question:

     Bareword "DB_File" not allowed while "strict subs" in use

   To get around the error, place the word DB_File in either single or
double quotes, like this:

     tie %x, "DB_File", "filename" ;

   Although it might seem like a real pain, it is really worth the effort
of having a `use strict' in all your scripts.

REFERENCES
==========

   Articles that are either about DB_File or make use of it.

  1. *Full-Text Searching in Perl*, Tim Kientzle (tkientzle@ddj.com), Dr.
     Dobb's Journal, Issue 295, January 1999, pp 34-41

HISTORY
=======

   Moved to the Changes file.

BUGS
====

   Some older versions of Berkeley DB had problems with fixed length
records using the RECNO file format. This problem has been fixed since
version 1.85 of Berkeley DB.

   I am sure there are bugs in the code. If you do find any, or can
suggest any enhancements, I would welcome your comments.

AVAILABILITY
============

   DB_File comes with the standard Perl source distribution. Look in the
directory `ext/DB_File'. Given the amount of time between releases of Perl
the version that ships with Perl is quite likely to be out of date, so the
most recent version can always be found on CPAN (see `CPAN', see
Perlmod (perl.info), for details), in the directory
`modules/by-module/DB_File'.

   This version of DB_File will work with either version 1.x, 2.x or 3.x
of Berkeley DB, but is limited to the functionality provided by version 1.

   The official web site for Berkeley DB is `http://www.sleepycat.com'.
All versions of Berkeley DB are available there.

   Alternatively, Berkeley DB version 1 is available at your nearest CPAN
archive in `src/misc/db.1.85.tar.gz'.

   If you are running IRIX, then get Berkeley DB version 1 from
`http://reality.sgi.com/ariel'. It has the patches necessary to compile
properly on IRIX 5.3.

COPYRIGHT
=========

   Copyright (c) 1995-1999 Paul Marquess. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

   Although DB_File is covered by the Perl license, the library it makes
use of, namely Berkeley DB, is not. Berkeley DB has its own copyright and
its own license. Please take the time to read it.

   Here are are few words taken from the Berkeley DB FAQ (at
`http://www.sleepycat.com') regarding the license:

     Do I have to license DB to use it in Perl scripts?

     No. The Berkeley DB license requires that software that uses
     Berkeley DB be freely redistributable. In the case of Perl, that
     software is Perl, and not your scripts. Any Perl scripts that you
     write are your property, including scripts that make use of
     Berkeley DB. Neither the Perl license nor the Berkeley DB license
     place any restriction on what you may do with them.

   If you are in any doubt about the license situation, contact either the
Berkeley DB authors or the author of DB_File. See `"AUTHOR"' in this node
for details.

SEE ALSO
========

   `perl(1)' in this node, `dbopen(3)' in this node, `hash(3)' in this
node, `recno(3)' in this node, `btree(3)' in this node, `dbmfilter' in
this node

AUTHOR
======

   The DB_File interface was written by Paul Marquess
<Paul.Marquess@btinternet.com>.  Questions about the DB system itself may
be addressed to <db@sleepycat.com<gt>.

Locking with flock wrapper for DB_File
**************************************

NAME
====

   DB_File::Lock - Locking with flock wrapper for DB_File

SYNOPSIS
========

     use DB_File::Lock;

     $locking = "read";
     $locking = "write";
     $locking = {
         mode            => "read",
         nonblocking     => 0,
         lockfile_name   => "/path/to/shared.lock",
         lockfile_mode   => 0600,
     };

     [$X =] tie %hash,  'DB_File::Lock', [$filename, $flags, $mode, $DB_HASH], $locking;
     [$X =] tie %hash,  'DB_File::Lock', $filename, $flags, $mode, $DB_BTREE, $locking;
     [$X =] tie @array, 'DB_File::Lock', $filename, $flags, $mode, $DB_RECNO, $locking;

     ...use the same way as DB_File for the rest of the interface...

DESCRIPTION
===========

   This module provides a wrapper for the DB_File module, adding locking.

   When you need locking, simply use this module in place of DB_File and
add an extra argument onto the tie command specifying if the file should
be locked for reading or writing.

   The alternative is to write code like:

     open(LOCK, "<$db_filename.lock") or die;
     flock(LOCK, LOCK_SH) or die;
     tie(%db_hash, 'DB_File', $db_filename,  O_RDONLY, 0600, $DB_HASH) or die;
     ... then read the database ...
     untie(%db_hash);
     close(LOCK);

   This module lets you write

     tie(%db_hash, 'DB_File', $db_filename,  O_RDONLY, 0600, $DB_HASH, 'read') or die;
     ... then read the database ...
     untie(%db_hash);

   This is better for two reasons:

   (1) Less cumbersome to write.

   (2) A fatal exception in the code working on the database which does
not lead to process termination will probably not close the lockfile and
therefore cause a dropped lock.

USAGE DETAILS
=============

   The filename used for the lockfile defaults to "$filename.lock" (the
filename of the DB_File with ".lock" appended). Using a lockfile separate
from the database file is recommended because it prevents weird
interactions with the underlying database file library

   The additional locking argument added to the tie call, can be:

   (1) "read" - aquires a shared lock for reading

   (2) "write" - aquires an exclusive lock for writing

   (3) A hash with the following keys (all optional except for the "mode"):

mode
     the locking mode, "read" or "write".

lockfile_name
     specifies the name of the lockfile to use. Default is
     "$filename.lock".  This is useful for locking multiple resources with
     the same lockfiles.

nonblocking
     determines if the flock call on the lockfile should block waiting for
     a lock, or if it should return failure if a lock can not be
     immediately attained. If "nonblocking" is set and a lock can not be
     attained, the tie command will fail.  Currently, I'm not sure how to
     differentiate this between a failure form the DB_File layer.

lockfile_mode
     determines the mode for the sysopen call in opening the lockfile. The
     default mode will be formulated to allow anyone that can read or
     write the DB_File permission to read and write the lockfile.  (This
     is because some systems may require that one have write access to a
     file to lock it for reading, I understand.) The umask will be
     prevented from applying to this mode.

   Note: One may import the same values from DB_File::Lock as one may
import from DB_File.

OTHER LOCKING MODULES
=====================

   There are three locking wrappers for DB_File in CPAN right now. Each one
implements locking differently and has different goals in mind. It is
therefore worth knowing the difference, so that you can pick the right one
for your application.

   Here are the three locking wrappers:

   Tie::DB_Lock - DB_File wrapper which creates copies of the database file
for read access, so that you have kind of a multiversioning concurrent
read system. However, updates are still serial. Use for databases where
reads may be lengthy and consistency problems may occur.

   Tie::DB_LockFile - DB_File wrapper that has the ability to lock and
unlock the database while it is being used. Avoids the tie-before-flock
problem by simply re-tie-ing the database when you get or drop a lock.
Because of the flexibility in dropping and re-acquiring the lock in the
middle of a session, this can be massaged into a system that will work
with long updates and/or reads if the application follows the hints in the
POD documentation.

   DB_File::Lock (this module) - extremely lightweight DB_File wrapper
that simply flocks a lockfile before tie-ing the database and drops the
lock after the untie.  Allows one to use the same lockfile for multiple
databases to avoid deadlock problems, if desired. Use for databases where
updates are reads are quick and simple flock locking semantics are enough.

   (This text duplicated in the POD documentation, by the way.)

AUTHOR
======

   David Harris <dharris@drh.net>

   Helpful insight from Stas Bekman <sbekman@iil.intel.com>

SEE ALSO
========

   DB_File(3).

DBM with associative arrays, file locking and XML records
*********************************************************

NAME
====

   `DBass' - DBM with associative arrays, file locking and XML records

SYNOPSIS
========

     use DBass;

     die unless DBass::gestalt (-api => 'xeen');
     my $db = DBass->new (
         -api  => 'neo',
         -file => '+<file.dbm',
         -lock => 'file.lock',
         -mode => 0644
     );

DESCRIPTION
===========

   This module provides methods to read, write and delete associative
arrays in DBM files, with file locking and XML records.

   It uses a named argument `-api' for class methods new and `gestalt' to
try to prevent later versions of the module from breaking preexisting APIs.

METHODS
=======

`gestalt'
     This method checks for the existence of an API:

          die 'no API neo' unless DBass::gestalt (-api => 'neo');

     `-api' is the calling API to check for.  One should use this method
     only for development or testing, and not in frequently used
     applications.

new
     This method creates a new DBass object, and should be the first one
     called:

          my $db = DBass->new (
              '-api'  => 'neo',
              '-file' => '+<file.dbm',
              '-lock' => 'file.lock',
              '-mode' => 0644
          );

     `-api' is the calling API to use.  `-file' is the read/write mode
     (default is read-only) and DBM filename.  `-lock' is the lock
     filename.  `-mode' is the file permissions mode of the DBM file.

     If the DBM file is opened for read-only access, the lock file must
     preexist, but can be empty.  In MacOS, one can create an empty file
     with SimpleText.  In *nix, one can create an empty file with touch:

          touch file.lock

     This version of the module has APIs `xeen' and X<neo>.  The `xeen'
     API is deprecated and provided for backward compatibility only, and
     the `neo' API should be used when possible.

close
     This method releases various resources in the DBass object, to allow
     other processes to access the DBM file:

          $db->close;

     Normally this method should not be used, as it renders the object
     useless for the remainder of the program execution (and is
     automatically called when the object is destroyed).

delete
     This method deletes records from the DBM file:

          $db->delete ('-keys' => \@keys);
          $db->delete ('-keys' => \%keys);
          $db->delete ('-keys' =>  $key );

     *Be careful.*  It can also delete all records:

          $db->delete;

keys
     This method returns record keys:

          my @keys = $db->keys;

read
     This method returns a hash reference pointing to records in the DBM
     file:

          my $smallerhashref = $db->read ('-keys' => \@keys, '-root' => $root);
          my $smallerhashref = $db->read ('-keys' => \%keys, '-root' => $root);
          my $smallhashref   = $db->read ('-keys' =>  $keys, '-root' => $root);
          my $entirehashref  = $db->read ('-root' =>  $root);

     `-keys' are the keys to match against.  `-root' is the XML root tag
     name used in storing the records.

write
     This method writes key-value pairs to the DBM file:

          $db->write (-hash => \%hash, -root => $root);

     `-hash' is the hash reference pointing to the key-value pairs
     (records).  `-root' is the XML root tag name to use in storing the
     records.

KNOWN ISSUES
============

   The `xeen' API is deprecated and provided for backward compatibility
only, and the `neo' API should be used when possible.  The main reason for
the API name change is that the `neo' record format is significantly
different from that of `xeen'.

   On platforms other than MacOS, *nix or Windows NT, flock will probably
cause the module to crash and burn.

   The module should be pronounced `/di'bas/'.

   The `xeen' API is not named after the IBM alphaWorks `Xeena' XML editor.

CHANGES
=======

     0.53  2000.01.11  fixed Makefile.PL (oops!)

     0.52  1999.10.30  added check for _OBJ
                       added check for _HASHREF
                       fixed neo_read handling of _UNTAGGED
                       fixed neo_read to check for _HASHREF
                       fixed neo_write to check for _OBJ
                       fixed xeen_delete to check for _OBJ
                       fixed xeen_destroy to check for _OBJ
                       fixed xeen_new die preparation
                       fixed xeen_new to include _UNTAGGED
                       fixed xeen_read handling of _UNTAGGED
                       fixed xeen_read to check for _HASHREF
                       fixed xeen_write to check for _OBJ

     0.51  1999.10.26  fixed gestalt for wantarray
                       fixed neo_read to accept hash references as -keys
                       fixed xeen_delete to accept hash references as -keys
                       fixed xeen_read to accept hash references as -keys

     0.50  1999.10.06  added neo API (valid XML tags and lists of lists)

     0.40  1999.09.20  fixed DBM file locking bug in xeen_destroy
                       fixed DBM file locking bug in xeen_new
                       fixed xeen_delete to accept scalars as -keys
                       fixed xeen_read to accept scalars as -keys

AUTHOR
======

   Copyright 1999, 2000 Nguon Hao Ching (`spiderboy@spiderboy.net').

CREDITS
=======

   Thanks to Tom Christiansen for Perl Cookbook recipe 14.5.

   Thanks to Mark-Jason Dominus for the Perl Monger tutorial on file
locking.

   Thanks to David Harris and Paul Marquess for the recipe bug report.

   Thanks to Chris Nandor for `perlport'.

   Thanks to James Wismer for feedback on the initial, unreleased version.

   Thanks to Jay Trolley for her patience and understanding.

   Thanks to xeenie for everything else.

Perl interface to DCE ACL client API
************************************

NAME
====

   DCE::ACL - Perl interface to DCE ACL client API

SYNOPSIS
========

     use DCE::ACL;

     $aclh = DCE::ACL->bind($object);

     =head1 DESCRIPTION

   DCE::ACL provides a Perl interface to the sec_acl_* client API.  As the
sec_acl_list_t structure is rather complex, additional classes and methods
are provided so Perl scripts can deal with it in a reasonable fashion.

DCE::ACL::handle methods
========================

DCE::ACL::handle->bind
     See `DCE::ACL->bind' in this node.

$aclh->num_acls
     Returns the number of acls in the sec_acl_list_t structure.

          $num = $aclh->num_acls

$aclh->get_manager_types
     Equivalent to the sec_acl_get_manager_types function.
     `$manager_types' is a array reference.

          ($num_used, $num_types, $manager_types, $status) =
             $aclh->get_manager_types();

     If called in a scalar context, only the `$manager_types' array
     reference is returned.

          $manager = $achl->get_manager_types->[0]; #first manager

          =item $aclh->get_access

     Equivalent to the sec_acl_get_access function.

          ($permset, $status) = $aclh->get_access($manager);

$aclh->get_printstring
     Equivalent to the sec_acl_get_printstring function.

     `$printstrings' is an array reference of hash references.

          ($chain, $mgr_info, $tokenize, $total, $num, $printstrings, $status) =
             $aclh->get_printstring($manager);

     If called in a scalar context, only the `$printstrings' reference is
     returned.

          $printstrings = $aclh->get_printstring($manager);

          foreach $str (@$printstrings) {
              $permstr .=
          	 ($str->{permissions} & $entry->perms) ?
          	     $str->{printstring} : "-";
          }

$aclh->test_access
     Equivalent to the sec_acl_test_access function.

          ($ok, $status) = $aclh->test_access($manager, $perms);

$aclh->replace
     Equivalent to the sec_acl_replace function.

          $status = $aclh->replace($manager, $aclh->type_object, $list);

$aclh->lookup
     Equivalent to the sec_acl_lookup function.  $list is a reference to a
     sec_acl_list_t structure, blessed into the *DCE::ACL::list* class.
     $type is an optional argument which defaults to
     `DCE::ACL-'type_object>.

          ($list, $status) = $aclh->lookup($manager, [$type]);

$aclh->new_list
     This method does a lookup, deleting all entries and returns the empty
     list.  $type is an optional argument which defaults to
     `DCE::ACL-'type_object>.

          ($list, $status) = $aclh->new_list($manager, [$type]);

DCE::ACL::list methods
======================

$list->acls
     Returns a list of all acls if no index argument is given, when called
     in a scalar context, only the first acl is returned.  Objects
     returned are references to sec_acl_t structures, blessed into the
     *DCE::ACL* class.

          $acl = $list->acls;

DCE::ACL methods
================

DCE::ACL->bind
     Equivalent to the sec_acl_bind function.  Returns a reference to the
     sec_acl_list_t structure bless into the *DCE::ACL::handle* class.
     The optional argument `$bind_to_entry' defaults to FALSE.

          ($aclh, $status) = DCE::ACL->bind($object, [$bind_to_entry]);

DCE::ACL->type
     When given an integer argument, returns the string representation.

          $str = DCE::ACL->type(0); #returns 'user_obj'

     A method is provided foreach sec_acl_type_t type, returning an
     integer.

          $type = DCE::ACL->type_user;

$acl->num_entries
     Returns the number of sec_acl_entry_t structures.

          $num = $acl->num_entries;

          =item $acl->default_realm

     Returns a hash reference with *uuid* and name keys.

          $name = $acl->default_realm->{name}; #/.../cell.foo.com

$acl->remove
     Removes the specifed entry from the acl structure, where entry is a
     reference to sec_acl_entry_t structure, blessed into the
     *DCE::ACL::entry* class.

          $status = $acl->remove($entry);

$acl->delete
     Removes all entries from the $acl.

     =item $acl->new_entry

     Allocates memory needed for a new sec_acl_entry_t structure, returns a
     reference to that structure blessed in to the *DCE::ACL::entry* class.

          $entry = $acl->new_entry;

          =item $acl->add

     Adds a sec_acl_entry_t structure to a sec_acl_t structure.

          $status = $acl->add($entry);

$acl->entries
     Returns references to sec_acl_entry_t structures blessed in to the
     *DCE::ACL::entry* class.  If an integer argument is given, only that
     entry will be returned, otherwise, a list of all entries will be
     returned.

          $entry = $acl->entries(0); #return the first entry

          foreach $entry ($acl->entries) { #return all entries
             ...

DCE::ACL::entry methods
=======================

$entry->compare
     Compares two acl entries, returns true if they are the same, returns
     false otherwise.

          $match = $entry1->compare($entry2);

$entry->perms
     Returns the permission bits for the specified entry, setting the bits
     if given an argument.

          $bits = $entry->perms;

          for (qw(perm_read perm_control perm_insert)) {
          	$bits |= DCE::ACL->$_();
          }

          $e->perms($bits);

$entry->entry_info
     Returns a hash reference containing entry info, changing it if given
     an argument.

          $uuid = $entry->entry_info->{id}{uuid};

          $entry->entry_info({
          	entry_type => DCE::ACL->type_user,
          	id => {
          	    uuid => $uuid,
          	},
          });

AUTHOR
======

   Doug MacEachern <dougm@osf.org>

SEE ALSO
========

   perl(1), DCE::aclbase(3), DCE::Registry(3), DCE::UUID(3),
DCE::Login(3), DCE::Status(3).

Perl module interface to DFS internals
**************************************

NAME
====

   DCE::DFS - Perl module interface to DFS internals

SYNOPSIS
========

   use DCE::DFS;

DESCRIPTION
===========

General DFS methods
===================

DCE::DFS::cellname(path)
DCE::DFS::crmount(path, fileset, read_write)
DCE::DFS::delmount(path)
DCE::DFS::fid(path)
ACL stuff
=========

DCE::DFS::acl(path, acl_type, registry_handle);
$acl->entries()
$acl->entry(entry_key)
$acl->modify(entry_key, permissions)
$acl->delete(entry_key)
$acl->deleteall()
$acl->calc_mask()
$acl->commit()
FLDB methods
============

DCE::DFS::flserver(cell_fs)
$flserver->ftserver()
$flserver->fileset_mask_reset()
$flserver->fileset_mask_ftserver(ftserver)
$flserver->fileset_mask_aggregate(aggregate)
$flserver->fileset()
$flserver->fileset_by_name(name)
$flserver->fileset_by_id(fid)
ftserver methods
================

$ftserver->address()
$ftserver->hostname()
$ftserver->aggregate()
aggregate methods
=================

$aggregate->ftserver()
$aggregate->name()
$aggregate->device()
$aggregate->id()
$aggregate->type()
$aggregate->size()
$aggregate->free()
fileset methods
===============

$fileset->ftserver()
$fileset->aggregate()
$fileset->name()
$fileset->quota()
$fileset->used()
$fileset->set_quota(quota)
$fileset->update()
AUTHOR
======

   Paul Henson <henson@acm.org>

SEE ALSO
========

   perl(1), DCE::*.

Perl extension for interfacing to the DCE login API
***************************************************

NAME
====

   DCE::Login - Perl extension for interfacing to the DCE login API

SYNOPSIS
========

     use DCE::Login;
     my($l, $status) = DCE::Login->get_current_context;
     my $pwent = $l->get_pwent;

DESCRIPTION
===========

   Perl extension for interfacing to the DCE login API.

AUTHOR
======

   Doug MacEachern <dougm@osf.org>

SEE ALSO
========

   perl(1), DCE::login_base(3), DCE::Registry(3).

Perl interface to DCE Registry API
**********************************

NAME
====

   DCE::Registry - Perl interface to DCE Registry API

SYNOPSIS
========

     use DCE::Registry;

     my $rgy = DCE::Registry->site_open($site_name);

DESCRIPTION
===========

   This module provides an OO Perl interface to the DCE Registry API.  The
sec_rgy_ prefix has been dropped and methods are invoked via a blessed
registry_context object.

AUTHOR
======

   Doug MacEachern <dougm@osf.org>

SEE ALSO
========

   perl(1), DCE::rgybase(3), DCE::Status(3), DCE::Login(3), DCE::UUID(3).

Make sense of DCE status codes
******************************

NAME
====

   DCE::Status - Make sense of DCE status codes

SYNOPSIS
========

     use DCE::Status;

     $errstr = error_inq_text($status);

     tie $status => DCE::Status;

DESCRIPTION
===========

   When a $scalar is tie'd to the DCE::Status class, it has a different
value depending on the context it is evaluated in, similar to the magic $!
variable.  When evaluated in a numeric context, the numeric value is
returns, otherwise, the string value obtained from *dce_error_inq_text* is
returned.

EXPORTS
=======

error_inq_text
     Equivalent to the dce_error_inq_text function.

          $errstr = error_inq_text($status);

AUTHOR
======

   Doug MacEachern <dougm@osf.org>

SEE ALSO
========

   perl(1), DCE::Registry(3), DCE::Login(3), DCE::ACL(3).

Misc UUID functions
*******************

NAME
====

   DCE::UUID - Misc UUID functions

SYNOPSIS
========

     use DCE::UUID;

DESCRIPTION
===========

   DCE::UUID exports the following functions:

uuid_create()
          my($uuid, $status) = uuid_create();

uuid_hash()
          my($hash, $status) = uuid_hash($uuid);

AUTHOR
======

   Doug MacEachern <dougm@osf.org>

SEE ALSO
========

   perl(1), DCE::Status(3), DCE::Registry(3), DCE::Login(3).

Constants from dce/aclbase.h
****************************

NAME
====

   DCE::aclbase - Constants from dce/aclbase.h

SYNOPSIS
========

     use DCE::aclbase;

DESCRIPTION
===========

AUTHOR
======

   h2xs

SEE ALSO
========

   DCE::ACL(3), perl(1).

Perl extension for blah blah blah
*********************************

NAME
====

   DCE::attrbase - Perl extension for blah blah blah

SYNOPSIS
========

     use DCE::attrbase;
     blah blah blah

DESCRIPTION
===========

   Stub documentation for DCE::attrbase was created by h2xs. It looks like
the author of the extension was negligent enough to leave the stub
unedited.

   Blah blah blah.

Exported constants
==================

     sec_attr_base_v0_0_included
     sec_attr_bind_type_string
     sec_attr_bind_type_svrname
     sec_attr_bind_type_twrs
     sec_attr_sch_entry_multi_inst
     sec_attr_sch_entry_none
     sec_attr_sch_entry_reserved
     sec_attr_sch_entry_unique
     sec_attr_sch_entry_use_defaults
     sec_attr_schema_part_acl_mgrs
     sec_attr_schema_part_comment
     sec_attr_schema_part_defaults
     sec_attr_schema_part_intercell
     sec_attr_schema_part_multi_inst
     sec_attr_schema_part_name
     sec_attr_schema_part_reserved
     sec_attr_schema_part_scope
     sec_attr_schema_part_trig_bind
     sec_attr_schema_part_trig_types
     sec_attr_schema_part_unique
     sec_attr_trig_type_none
     sec_attr_trig_type_query
     sec_attr_trig_type_update
     volatile

AUTHOR
======

   A. U. Thor, a.u.thor@a.galaxy.far.far.away

SEE ALSO
========

   perl(1).

Constants from sec_login_*.h
****************************

NAME
====

   DCE::login_base - Constants from sec_login_*.h

SYNOPSIS
========

     use DCE::login_base;

DESCRIPTION
===========

   These constant methods are inherited by DCE::Login, a developer should
not need to use this module and its methods directly.

AUTHOR
======

   h2xs

SEE ALSO
========

   perl(1), DCE::Login(3), DCE::Registry(3).

Constants from dce/rgybase.h
****************************

NAME
====

   DCE::rgybase - Constants from dce/rgybase.h

SYNOPSIS
========

     use DCE::rgybase;

DESCRIPTION
===========

   These constant methods are inherited by DCE::Registry, a developer
should not need to use this module and its methods directly.

   Here is a list of the available constants:

     acct_admin_audit
     acct_admin_client
     acct_admin_flags_none
     acct_admin_server
     acct_admin_valid
     acct_auth_dup_skey
     acct_auth_flags_none
     acct_auth_forwardable
     acct_auth_post_dated
     acct_auth_proxiable
     acct_auth_renewable
     acct_auth_tgt
     acct_key_group
     acct_key_last
     acct_key_none
     acct_key_org
     acct_key_person
     acct_user_flags_none
     acct_user_passwd_valid
     domain_group
     domain_last
     domain_org
     domain_person
     max_unix_passwd_len
     name_max_len
     name_t_size
     no_override
     no_resolve_pname
     override
     pgo_flags_none
     pgo_is_an_alias
     pgo_is_required
     pgo_projlist_ok
     plcy_pwd_flags_none
     plcy_pwd_no_spaces
     plcy_pwd_non_alpha
     pname_max_len
     pname_t_size
     prop_auth_cert_unbound
     prop_embedded_unix_id
     prop_readonly
     prop_shadow_passwd
     properties_none
     quota_unlimited
     resolve_pname
     rgynbase_v0_0_included
     status_ok
     uxid_unknown
     wildcard_name
     wildcard_sid

AUTHOR
======

   h2xs

SEE ALSO
========

   perl(1), DCE::Registry(3), DCE::Login(3).

Perl extension for blah blah blah
*********************************

NAME
====

   DCE::rpcbase - Perl extension for blah blah blah

SYNOPSIS
========

     use DCE::rpcbase;
     blah blah blah

DESCRIPTION
===========

   Stub documentation for DCE::rpcbase was created by h2xs. It looks like
the author of the extension was negligent enough to leave the stub
unedited.

   Blah blah blah.

Exported constants
==================

     rpc_c_authn_dce_dummy
     rpc_c_authn_dce_public
     rpc_c_authn_dce_secret
     rpc_c_authn_default
     rpc_c_authn_dssa_public
     rpc_c_authn_none
     rpc_c_authz_dce
     rpc_c_authz_name
     rpc_c_authz_none
     rpc_c_binding_default_timeout
     rpc_c_binding_infinite_timeout
     rpc_c_binding_max_count_default
     rpc_c_binding_max_timeout
     rpc_c_binding_min_timeout
     rpc_c_call_brdcst
     rpc_c_call_idempotent
     rpc_c_call_in_pipe
     rpc_c_call_maybe
     rpc_c_call_non_idempotent
     rpc_c_call_out_pipe
     rpc_c_cancel_infinite_timeout
     rpc_c_ep_max_annotation_size
     rpc_c_listen_max_calls_default
     rpc_c_mgmt_inq_if_ids
     rpc_c_mgmt_inq_princ_name
     rpc_c_mgmt_inq_stats
     rpc_c_mgmt_is_server_listen
     rpc_c_mgmt_stop_server_listen
     rpc_c_ns_dec_dns
     rpc_c_ns_default_exp_age
     rpc_c_ns_none
     rpc_c_ns_syntax_dce
     rpc_c_ns_syntax_dec_dns
     rpc_c_ns_syntax_default
     rpc_c_ns_syntax_internet_dns
     rpc_c_ns_syntax_unknown
     rpc_c_ns_syntax_uuid
     rpc_c_ns_syntax_x500
     rpc_c_profile_all_elts
     rpc_c_profile_default_elt
     rpc_c_profile_match_by_both
     rpc_c_profile_match_by_if
     rpc_c_profile_match_by_mbr
     rpc_c_protect_level_call
     rpc_c_protect_level_connect
     rpc_c_protect_level_default
     rpc_c_protect_level_none
     rpc_c_protect_level_pkt
     rpc_c_protect_level_pkt_integ
     rpc_c_protect_level_pkt_privacy
     rpc_c_protseq_max_reqs_default
     rpc_s_ok
     rpcbase_v0_0_included
     volatile

AUTHOR
======

   A. U. Thor, a.u.thor@a.galaxy.far.far.away

SEE ALSO
========

   perl(1).

a DDL generator for Oracle databases
************************************

NAME
====

   DDL::Oracle - a DDL generator for Oracle databases

VERSION
=======

   VERSION = 1.04

SYNOPSIS
========

     use DBI;
     use DDL::Oracle;

     my $dbh = DBI->connect(
                             "dbi:Oracle:dbname",
                             "username",
                             "password",
                             {
                              PrintError => 0,
                              RaiseError => 1
                             }
         );

     # Use default resize and schema options.
     # query default DBA_xxx tables (could use USER_xxx for non-DBA types)
     DDL::Oracle->configure(
                             dbh    => $dbh,
                           );

     # Create a list of one or more objects
     my $sth = $dbh->prepare(
            "SELECT
                    owner
                  , table_name
             FROM
                    dba_tables
             WHERE
                    tablespace_name = 'MY_TBLSP'    -- your mileage may vary
            "
         );

     $sth->execute;
     my $list = $sth->fetchall_arrayref;

     my $obj = DDL::Oracle->new(
                                 type  => 'table',
                                 list  => $list,                          );
                               );

     my $ddl = $obj->create;      # or $obj->resize;  or $obj->drop;  etc.

     print $ddl;    # Use STDOUT so user can redirect to desired file.

DESCRIPTION
===========

Overview
--------

   Designed for Oracle DBA's and users.  It reverse engineers database
objects (tables, indexes, users, profiles, tablespaces, roles,
constraints, etc.).  It generates DDL to *resize* tables and indexes to
the provided standard or to a user defined standard.

   We originally wrote a script to defrag tablespaces, but as DBA's we
regularly find a need for the DDL of a single object or a list of objects
(such as all of the indexes for a certain table).  So we took all of the
DDL statement creation logic out of defrag.pl, and put it into the general
purpose DDL::Oracle module, then expanded that to include tablespaces,
users, roles, and all other dictionary objects.

   Oracle tablespaces tend to become fragmented (now THAT's an
understatement).  Even when object sizing standards are adopted, it is
difficult to get 100% compliance from users.  And even if you get a high
degree of compliance, objects turn out to be a different size than
originally thought/planned - small tables grow to become large (i.e.,
hundreds of extents), what was thought would be a large table ends up
having only a few rows, etc.  So the main driver for DDL::Oracle was the
object management needs of Oracle DBA's.  The "resize" method generates
DDL for a list of tables or indexes.  For partitioned objects, the
"appropriate" size of EACH partition is calculated and supplied in the
generated DDL.  The original defrag.pl will be rewritten to use
DDL::Oracle, and supplied with its distribution.

Initialization and Constructor
------------------------------

   configure

   The configure method is used to supply the DBI connection and to set
several session level attributes.  These are:

     dbh      A reference to a valid DBI connection (obtained via
              DBI->connect).  This is the only mandatory attribute.

     NOTE: The user connecting should have SELECT privileges
           on the following views (in addition to the DBA or
           USER views), but see attributes 'heading', 'blksize'
           and 'version' below for exceptions:

     V$VERSION
     V$DATABASE
     V$PARAMETER

     And, in order to generate CREATE SNAPSHOT LOG
     statements, you will also need to create a PUBLIC
     SYNONYM for DBA_SNAPSHOT_LOG_FILTER_COLS.  In
     order for non-DBA users to do the same, you will
     need to grant SELECT on this view to them (e.g.,
     to PUBLIC).  Why Oracle Corp. feels this view is
     of no interest to non-replication users is a
     mystery to the author.

     And, in order to generate CREATE INDEX statements
     for indexes which have DESCending column(s) and/or
     include FUNCTION based column(s), you must have
     select privileges on SYS.COL$, wherein the real
     name of the column or function definition is held.

     schema   Defines whether and what to use as the schema for DDL
              on objects which use this syntax.  "1" means use the
              owner of the object as the schema; "0" or "" means
              omit the schema syntax; any other arbtrary string will
              be imbedded in the DDL as the schema.  The default is "1".

     resize   Defines whether and what to use in resizing segments.
              "1" means resize segments using the default algorithm;
              "0" or "" means keep the current INITIAL and NEXT
              values; any other string will be interpreted as a
              resize definition.  The default is "1".

     To establish a user defined algorithm, define this with
     a string consisting of n sets of LIMIT:INITIAL:NEXT.
     LIMIT is expressed in Database Blocks.  The highest LIMIT
     may contain the string 'UNLIMITED', and in any event will
     be forced to be so by DDL::Oracle.

     view     Defines which Dictionary views to query:  DBA or USER
              (e.g., DBA_TABLES or USER_TABLES).  The default is DBA.

     heading  Defines whether to include a Heading having Host, Instance,
              Date/Time, List of generated Objects, etc.  "1" means
              include the heading; "0" or "" means to suppress the
              heading (and eliminate the query against V$DATABASE).
              The default is "1".

     blksize  Defines the database block size.  If this attribute is
              supplied, you eliminate the query against V$PARAMETER.
              The default is to query V$PARAMETER for this value.

     version  A quoted string which defines the version of the database,
              and must be a version supported by the module (currently
              7.x, 8.0 and 8.1).  If this attribute is supplied, you
              eliminate the query against V$VERSION.  The default is to
              query V$VERSION for this value.

   new

   The new method is the object constructor.  The two mandatory object
definitions are supplied with this method, to wit:

     type    The type of object (e.g., TABLE, INDEX, SYNONYM, family,
             etc.).

     For 'table family', supply the name(s) of tables -- the
     DDL will include the table and its:
         Comments (Table and Column)
         Indexes
         Constraints
         Triggers

     list    An arrayref to an array of arrayrefs (as in the DBI's
            "fetchall_arrayref" method) containing pairs of owner and
             name.

Object methods
--------------

   create

   The create method generates the DDL to create the list of Oracle
objects.

   drop

   The drop method generates the DDL to drop the list of Oracle objects.

   resize

   The *resize* method generates the DDL to resize the list of Oracle
objects.  The 'type' defined in the 'new' method is limited to 'index' and
'table'.  For tables, this generates an ALTER TABLE MOVE statement; for
indexes, it generates an ALTER INDEX REBUILD statement.  If the table or
index is partitioned, then a statement for each partition is generated.

   To generate DDL for a single partition of an index or table, define the
'name' as a colon delimited field (e.g., 'name:partition').

   compile

   The compile method generates the DDL to compile the list of Oracle
objects.  The 'type' defined in the 'new' method is limited to 'function',
'package', 'procedure', 'trigger' and 'view'.

BUGS
====

   The generated DDL contains the Schema and Object Name in lower case.
In the case of triggers, this will cause a problem if the "... ON
<schema>.<table>" clause is quoted.  For example, a trigger on table
MY_TABLE in schema ME written as '...BEFORE INSERT ON "ME"."MY_TABLE"...'
will generate the DDL as

     '... BEFORE INSERT ON "me"."my_table"...'

   There are no plans to change this.

FILES
=====

     copy_user.pl
     copy_user.sh
     ddl.pl
     defrag.pl
     query.pl

AUTHOR
======

     Richard V. Sutherland
     rvsutherland@yahoo.com

COPYRIGHT
=========

   Copyright (c) 2000, 2001 Richard V. Sutherland.  All rights reserved.
This module is free software.  It may be used, redistributed, and/or
modified under the same terms as Perl itself.  See:

     http://www.perl.com/perl/misc/Artistic.html

An augmented transition network object.
***************************************

NAME
====

   `DFA::ATN' - An augmented transition network object.

DESCRIPTION
===========

     my $Obj = new DFA::ATN $Actions,[States];

   This creates a powerful automaton with a finite number of individual
states.  It inherits many of its methods from `DFN::Simple' in this node.
The object is composed of the following three things (with methods to
match):

State
     The object has a particular state it is in; a specific state from a
     set of possible states.  See DFA/Simple,

*State Stack*
     You can push a stack onto the stack, or pop one off.  The register
     frame is saved and restored as well.

Actions
     The object when enterring or leaving a state may perform some action.
     See DFA/Simple,

Rules
     The object has rules for determining what its next state should be,
     and how to get there.  See DFA/Simple,

Registers
     The object has the method for storing and retrieving information
     about its processing.

The State Stack
---------------

     $Obj->Save;
     $Obj->Restore;

   Save will save the current state of the automaton, including the
registers.

   Restore will restore the automaton's previously saved state and
registers.

Register
--------

     $Obj->Register->{'name'}='fred';

   Register is a method that can set or get the objects register reference.
This is a information that the actions, conditions, or transitions can
employ in their processing.  The reference can be anything.  It is
otherwise not used by the object implementation.

Installation
============

     perl Makefile.PL
     make
     make install

Author
======

   Randall Maas (`randym@acm.org' in this node, `http:' in this node)

A Discrete Finite Automata command processor.
*********************************************

NAME
====

   `DFA::Command' - A Discrete Finite Automata command processor.

   `DFA::Generate' - A DFA program generator.

SYNOPSIS
========

     use DFA::Command;

     $stateMachine = new DFA::Command('Name of first event');
     # Or:
     #$stateMachine = DFA::Command -> new('Name of first event');

     $stateMachine -> load('Name of STT file');
     $stateMachine -> dump() if ($YouAreDebugging);

     $stateMachine -> process('Name of a event file');

DESCRIPTION
===========

   `DFA::Command'

   This module reads a state transition table and then reads a data file
looking for patterns as defined by regular expressions in the state
transition table. When a transition is detected, a sub is called.

   `DFA::Generate'

   This module reads a state transition table and generates a Perl script
which uses the module `DFA::Command' to process data according to the said
table.

   These 2 modules are installed together.

   The name `DFA::Command' was chosen because:

   * Somebody beat me to it. I wanted to use FSM (Finite State Machine)

   * It creates an appropriate and convenient naming structure for related
     packages

   * It installs easily in Unix, DOS and NT file systems

   * It was developed in an environment where the input file contained
     commands and non-commands

INSTALLATION
============

   You install `DFA::Command', as you would install any perl module
library, by running these commands:

     perl Makefile.PL
     make
     make test
     make install

   If you want to install a private copy of `DFA::Command' in your home
directory, then you should try to produce the initial Makefile with
something like this command:

     perl Makefile.PL LIB=~/perl
     	or
     perl Makefile.PL LIB=C:/Perl/Site/Lib

   If, like me, you don't have permission to write man pages into unix
system directories, use:

     make pure_install

   instead of make install. This option is secreted in the middle of p 414
of the second edition of the dromedary book.

FEATURES
========

   When input is recognised, and an action function is about to be called,
`popEvent()' checks that the event just detected was one of those expected
in the current state.

   Just after an action function is called, the names of those events
expected next are saved by `pushEvent()', in preparation for the next call
to popEvent(). This feature and the previous one add overhead to the code,
but form a marvellous debugging aid.

TEST SCRIPTS
============

   This package contains 3 sets of test files:

   * Chinese

   * Citizen

   * X500

   Each set of test files contains:

   * A state transition table.  	These files are called:
     Chinese.STT, Citizen.STT and X500DN.STT.

   * A data file comtaining commands to be recognized by the DFA.  	These
     files are called: 	Chinese.dat, Citizen.dat and X500DN.dat.

   * A script (1) demonstrating DFA::Generate, which when run generates a
     script (2) 	demonstrating DFA::Command.  	These scripts (1) are
     called: 	Chinese_Gen.pl, Citizen_Gen.pl and X500DN_Gen.pl.

   * A script (2) which is the output of the previous script (1).  	These
     scripts (2) are called: 	ChineseTest.pl, CitizenTest.pl and
     X500DNTest.pl.

   * A script (3) which is a version of (2), ie which I have generated and
     then modified 	to demonstrate some possibilities.  	These scripts (3)
     are called: 	Chinese.pl, Citizen.pl and X500DN.pl.

   * 2 log files output by these 2 scripts (2, 3).  	These logs are called:
     ChineseTest.log, Chinese.log, CitizenTest.log, Citizen.log,
     X500DNTest.log, 	X500DN.log.

   These scripts are all in a subdirectory called test. They are not in a
subdirectory called t because the test harness does not provide for
scripts to be run which generate scripts to be run.

CONFIGURATION OPTIONS
=====================

   chomp. Chomp each input line before processing it. Default: True

   commentPrefix. Ignore any input lines which start with this character.
If trimLeading is false, and a line starts with whitespace followed by this
character, that line will still be ignored. Default: '#'

   ignoreBlankLines. If true, ignore input lines which are blank after any
chomping.  Default: True

   trimLeading. If true, trim leading whitespace from each input line
before processing it. Default: True

   trimTrailing. If true, trim trailing whitespace from each input line
before processing it. This takes place after any chomping. Default: True

WARNING
=======

   Go to any lengths whatsoever to avoid '%' characters in your input,
since some C compilers butcher such input. Eg: The thrice-cursed Pyramid
C++ compiler.

FORMAT OF A STATE TRANSITION TABLE
==================================

   Typically, there will be several lines for each state. These lines will
differ by their event names, and the corresponding regexp which recognises
the given event.

   Each line consists of these fields:

   * The name of the state. Use \w as your guideline for forming names -
     ie no whitespace

   * The regexp to be used to search for an event in the input line. In
     colloquial terms, this means the regexp to be used to search for the
     presence of a command in the input line. The arrival of this command
     is the event in question. Don't use whitespace within the regexp,
     since these lines are split on whitespace. (No package is perfect...)

   * The name of the event detected if the regexp fires. Use \w - ie no
     whitespace

   * The name of the action function to call if the regexp fires

   * The names of the events which are allowed to follow the current
     event. Separate event names with '|', without surrounding whitespace.
     Alternately, as syntactic sugar, use the special token commandList to
     refer to all events where the name of the state is 'commandState'

Q & A
=====

   How do I skip input text? Use a regexp of '.*' in your state transition
table.

   If my input is 'abcd' and I have 2 regexps, 'abc.*' and 'abcd.*', which
regexp fires? Hmmm. Grammatically speaking, that is a question. Seriously
tho, the order of evaluation will be the order in which keys are stored in
hashes, which is not under user control. In short, you bungled it by using
ambiguous regexps.

DEREFERENCING GUIDELINES
========================

     $self -> {$state} -> {$event} -> {'sub'}          Name of subroutine
     $self -> {$state} -> {$event} -> {'nextState'}    Name of state
     $self -> {$state} -> {$event} -> {'validEvents'}  Event|Event
     $self -> {$state} -> {'RE'}                       [REs]
     $self -> {$state} -> {'event'}                    [Events]
     $self -> {'nextEvent'}                            [Expected events]
     $self -> {'state'}                                Current state
     $self -> {'event'}                                Current event
     $self -> {'command'}                              Current command
     $self -> {'RE'}                                   Current RE
     $self -> {'original'}                             Current input line, original
     $self -> {'clean'}                                Current input line, cleaned up
     $self -> {'$1'}                                   Current text matching () IN RE
     $self -> {'$2'}                                   Current text matching () IN RE
     $self -> {'$3'}                                   Current text matching () IN RE

PROCESSING of #if defined()
===========================

   Reference: PC Techniques, Aug/Sep 1993, p 102, Hax 166. Unimplemented.

WARNING re Perl bug
===================

   As always, be aware that these 2 lines mean the same thing, sometimes:

   * $self -> {'thing'}

   * $self->{'thing'}

   The problem is the spaces around the ->. Inside double quotes, "...",
the first space stops the dereference taking place. Outside double quotes
the scanner correctly associates the $self token with the {'thing'} token.

   I regard this as a bug.

AUTHOR
======

   `DFA::Command' and `DFA::Generate' were written by Ron Savage
*<rpsavage@ozemail.com.au>* in 1997.

ACKNOWLEDGEMENTS
================

   The processing loop at the heart of this module is something I
downloaded from comp.land.perl.misc circa 1994. I encourage the author to
contact me.

   You'll know who you are: There were 2 bugs - both harmless - in 1 line
of code, in the routine I call load(). Anybody who accepts responsibility
for this code will be deemed to be the author. Well done!

LICENCE
=======

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Kleene's Algorithm for Deterministic Finite Automata
****************************************************

NAME
====

   DFA::Kleene - Kleene's Algorithm for Deterministic Finite Automata

   Calculates the "language" (set of words) accepted (= recognized) by a
Deterministic Finite Automaton

   See `Math::Kleene(3)' in this node for the theory behind this algorithm!

SYNOPSIS
========

   * `use DFA::Kleene qw(initialize define_accepting_states' `define_delta
     kleene example);'

   * `use DFA::Kleene qw(:all);'

   * `&initialize(6,"ab");'

     Define the number of states (state #1 is the "start" state!) of your
     Deterministic Finite Automaton and the alphabet used (as a string
     containing all characters which are part of the alphabet).

   * `&define_accepting_states(2,3,4,5);'

     Define which states are "accepting states" in your Deterministic
     Finite Automaton (list of state numbers).

   * `&define_delta(1,'a',4);'

     Define the state transition function "delta" (arguments are: "from"
     state, character (or empty string!) read during the transition, "to"
     state).

     You need several calls to this function in order to build a complete
     transition table describing your Deterministic Finite Automaton.

   * `@language = &kleene();'

     Returns a (sorted) list of regular expressions describing the language
     (= set of patterns) recognized ("accepted") by your Deterministic
     Finite Automaton.

   * `&example();'

     Calculates the language of a sample Deterministic Finite Automaton.

     Prints a (sorted) list of regular expressions which should be
     equivalent to the following regular expression:

          (a(a)*b)*a(a)*(b)*

     This is the same as

          ((a+)b)*(a+)b*

DESCRIPTION
===========

   The routines in this module allow you to define a Deterministic Finite
Automaton and to compute the "language" (set of "words" or "patterns")
accepted (= recognized) by it.

   Actually, a list of regular expressions is generated which describe the
same language (set of patterns) as the one accepted by your Deterministic
Finite Automaton.

   The output generated by this module can easily be modified to produce
Perl-style regular expressions which can actually be used to recognize
words (= patterns) contained in the language defined by your Deterministic
Finite Automaton.

   Other modules in this series (variants of Kleene's algorithm):

   * Math::MatrixBool (see "Kleene()")

   * Math::MatrixReal (see "kleene()")

SEE ALSO
========

   Math::MatrixBool(3), Math::MatrixReal(3), Math::Kleene(3),
Set::IntegerRange(3), Set::IntegerFast(3), Bit::Vector(3).

VERSION
=======

   This man page documents "DFA::Kleene" version 1.0.

AUTHOR
======

   Steffen Beyer <sb@sdm.de>.

COPYRIGHT
=========

   Copyright (c) 1996, 1997 by Steffen Beyer. All rights reserved.

LICENSE
=======

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

A PERL module to implement simple Discrete Finite Automata
**********************************************************

NAME
====

   `DFA::Simple' - A PERL module to implement simple Discrete Finite
Automata

SYNOPSIS
========

     my $Obj = new DFA::Simple

   or

     my $Obj = new DFA::Simple $Transitions;

   or

     my $Obj = new DFA::Simple $Actions, $StateRules;

     $Obj->Actions = [...];
     my $Trans = $LP->Actions;

     $Obj->StateRules = [...];
     my $StateRules = $LP->StateRules;

DESCRIPTION
===========

     my $Obj = new DFA::Simple $Actions,[States];

   This creates a simple automaton with a finite number of individual
states.  The object is composed of the following three things (with
methods to match):

State
     The object has a particular state it is in; a specific state from a
     set of possible states

Actions
     The object when enterring or leaving a state may perform some action.

Rules
     The object has rules for determining what its next state should be,
     and how to get there.

State
-----

   State is a method that can get the current state or initiate a
transition to a new state.

     my $S = $Obj->State;

     $Obj->State = $NewState;

   The last one leaves the current state and goes to the specified
*NewState*.  If the current state is defined, its *StateExitCodeRef* will
be called (see below).  Then the new states *StateEnterCodeRef* will be
called (if defined) (see below).  Cavaet, no check is made to see if the
new state is the same as the old state; this can be used to `reset' the
state.

Actions
-------

   Actions is a method that can set or get the objects list of actions to
perform when enterring or leaving a particular state.

     my $Actions = $Obj->Actions;

     $Obj->Actions = [
     		   [StateEnterCodeRef, StateExitCodeRef],
     		 ];

     I<Actions> is an array reference describing what to do when enterring and
     leaving various states.  When a state is entered, its I<StateEnterCodeRef>
     will be called (if defined).   When a state is left (as in going to a new
     state) its I<StateExitCodeRef> will be called (if defined).

StateRules
----------

     my $StateRules = [
     		     #Rules for state 0
     		     [
     		      [NextState, Test, Thing to do after getting there
     		      ],

     #Rules for state 1
     [
      ...
      ],
     ];

Installation
============

     perl Makefile.PL
     make
     make install

Author
======

   Randall Maas (`randym@acm.org' in this node, `http:' in this node)

Object-Oriented Management of a Master File
*******************************************

NAME
====

     DNS::ZoneFile - Object-Oriented Management of a Master File

SYNOPSIS
========

     use C<DNS::ZoneFile>;

     my $zone=C<DNS::ZoneFile>->new(
     	$filename_or_file_as_scalar,
     	ZONE_ORIGIN	=>	$ORIGIN,
     	NEW_ZONE	=>	$NEW_ZONE,
     	);

     $zone->addRecord(
     	Domain	=>	$domain,
     	TTL	=>	$ttl,
     	Class	=>	$class,
     	Type	=>	$type,
     	Data	=>	\@arr,
     	);

     $zone->deleteRecord(
     	$domain
     	);

     $zone->deleteRecord(
     	$domain,
     	$type
     	);

     $zone->printZone();

DESCRIPTION
===========

my *$zone*=DNS::ZoneFile->new($file,*%params*);
-----------------------------------------------

   new() creates a new DNS::ZoneFile object. It is initialised either from
the filename supplied, or, if the first argument is a reference to a
scalar, then the values is read.

   Params:

ZONE_ORIGIN (.)
     Sets the $ORIGIN for this zone.

NEW_ZONE (false)
     If unset and DNS::ZoneFile can't read any data, then return undef.
     Otherwise create a new SOA. (If this is set, ZONE_ORIGIN shouldn't
     really be set to '.')

*$zone*->*success*();
---------------------

   Returns true if the object was created OK, false if otherwise.

*$zone*->fail();
----------------

   Returns the error message of a a failed object call, or false if the
object was created OK.

*$zone*->*addRecord*(*@RRDATA*);
--------------------------------

   This will add a record to the zone (maybe that should be %RRDATA?)

*$zone*->*deleteRecord*($domain[,$type]);
-----------------------------------------

   This is also unwritten as yet - but I envisage this as a
$zone->deleteRecord("rigel.codix.net","MX"); or
$zone->deleteRecord("alioth.codix.net");

*$zone*->*printZone*();
-----------------------

   Returns a (reference to)? a scalar which is the zone file in full.  or
perhaps it keeps track of the filenames to open?

COMMENTS
========

   I have been recommended to release this bit of code unfinished onto
CPAN by some people - yes Greg, you know who you are - I'm fully aware
that this doesn't abstract enough yet.

   Hopefully doing this will enable me to write it quicker.

   Version: 0.95

AUTHOR
======

   Matthew Byng-Maddick `<matthew@codix.net'>

SEE ALSO
========

   `bind(8)' in this node

single DNS record in a zone database
************************************

NAME
====

   *DNS::ZoneFile::Record* - single DNS record in a zone database

SYNOPSIS
========

   `use DNS::ZoneFile::Record;'

   $rec=*DNS::ZoneFile::Record*->new(origin,name,type,data...);

   $name=$rec->Name(name);

   $type=$rec->Type(type);

   $address=$rec->Addr(address);

   $serial=$rec->*Serial*(*serialno*);

   $mxcost=$rec->*MXCost*(*MXcost*);

   @record=$rec->*getRecord*();

DESCRIPTION
===========

   *DNS::ZoneFile::Record* is a companion object model to *DNS::ZoneFile*
to provide a seperate object and methods for each of the records in a zone.

   The object methods are as follows:

new(origin,name,type,data...)
-----------------------------

   The new method is to create a new object. origin is used for the value
of the $ORIGIN system in the database, so that the record can be
canonicalised. name is the name relative to origin, or ending in a period
('.') is the canonical name for this record. type is the type of this
record, and affects what data the new method expects, and how it stores it
internally. Valid types are:

SOA
     This is a start of authority record, and expects 7 data arguments, in
     order the host, the hostmaster, the serial number, the refresh time,
     the retry time, the expiry time and the minimum time to live of the
     records.

NS
     This is a nameserver record, detailing nameservers for a domain. This
     just expects one data argument viz the name of the server.

A
     This is a forward record, pointing a name to an IP address, so the
     data argument expected is a dotted quad IP address.

PTR
     This is a reverse record, only really valid in .in-addr.arpa domains,
     and points a number to a name.

MX
     This is a mail exchanger record. The arguments expected are in order
     the cost of using that server (or reverse priority) and the name of
     the server.

CNAME
     This is a canonical name record, it points one name as a redirector
     for another. Its one data argument is the name to point to.

Name(name)
----------

   Returns the full DNS name of the record, also sets the name if an
argument is provided.

Type(type)
----------

   Returns the type of the record, also sets the type if an argument is
provided, although at present this is not recommended, because no data is
moved internally, so things could break.

Addr(*addr*)
------------

   Returns the address that this record points to, this differs in meaning
depending on the record type, the main difference being in the *start of
authority* records, where the address returned is the authoritative host
for this zone. This value can also be set with the optional argument.

*Serial*(*serialno*)
--------------------

   Returns the serial number of the zone file if this is an SOA record,
also sets it if an argument is provided.

*MXCost*(*MXcost*)
------------------

   Returns the cost of this server if this is an MX record, also sets it
if an argument is provided.

*getRecord*()
-------------

   Returns the data for this record in the order that it was input (see
above new() method).

COMMENTS
========

   This is currently alpha software, internal structures are likely to
change at any time.

AUTHOR
======

   Matthew Byng-Maddick <matthew@codix.net>

SEE ALSO
========

   *DNS::ZoneFile*

Standardize U.S. postal addresses.
**********************************

NAME
====

   Data::Address::Standardize - Standardize U.S. postal addresses.

SYNOPSIS
========

     use Data::Address::Standardize;
     ($street, $city, $state, $zip) = std_addr($street, $city, $state, $zip);

   or,

     use Data::Address::Standardize;
     # Read in a pipe-delimited data set like a filter.
     while(<>) {
         chomp;
         my @addr = split('\|');
         push @addr_list, [ @addr ];
     }
     my @std_list = std_addrs(@addr_list);
     # Write a pipe-delimited data set to standard output.
     foreach (@std_list) {
         print join('|', @$_), "\n";
     }

DESCRIPTION
===========

   The United States Postal Service (USPS) has on its web site an HTML
form at `http://www.usps.gov/ncsc/lookups/lookup_zip+4.html' for
standardizing an address. Given a firm, urbanization, street address,
city, state, and zip, it will put the address into standard form (provided
the address is in their database) and display a page with the resulting
address.

   This Perl module provides a programmatic interface to this service, so
you can write a program to process your entire personal address book
without having to manually type them all in to the form.

   Because the USPS could change or remove this functionality at any time,
be prepared for the possibility that this code may fail to function. In
fact, as of this version, there is no error checking in place, so if they
do change things, this code will most likely fail in a noisy way. If you
discover that the service has changed, please email the author your
findings.

   If an error occurs in trying to standardize the address, then no array
will be returned. Otherwise, a four-element array will be returned.

   To see debugging output, set $Data::Address::Standardize::verbose to a
true value.

TERMS OF USE
============

   BE SURE TO READ AND FOLLOW THE UNITED STATES POSTAL SERVICE TERMS OF USE
PAGE AT `http://www.usps.gov/disclaimer.html'. IN PARTICULAR, NOTE THAT
THEY DO NOT PERMIT THE USE OF THEIR WEB SITE'S FUNCTIONALITY FOR COMMERCIAL
PURPOSES. DO NOT USE THIS CODE IN A WAY THAT VIOLATES THE TERMS OF USE.

   The author believes that the example usage given above does not violate
these terms, but sole responsibility for conforming to the terms of use
belongs to the user of this code, not the author.

AUTHOR
======

   Gregor N. Purdy, `gregor@focusresearch.com'.

COPYRIGHT
=========

   Copyright (C) 1999-2000 Gregor N. Purdy. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

compare perl data structures
****************************

NAME
====

   Data::Compare - compare perl data structures

SYNOPSIS
========

     use Data::Compare;

     my $h = { 'foo' => [ 'bar', 'baz' ], 'FOO' => [ 'one', 'two' ] };
     my @a1 = ('one', 'two');
     my @a2 = ('bar', 'baz');
     my %v = ( 'FOO', \@a1, 'foo', \@a2 );

     # simple procedural interface
     print 'structures of $h and \%v are ',
       Compare($h, \%v) ? "" : "not ", "identical.\n";

     # OO usage
     my $c = new Data::Compare($h, \%v);
     print 'structures of $h and \%v are ',
       $c->Cmp ? "" : "not ", "identical.\n";
     # or
     my $c = new Data::Compare;
     print 'structures of $h and \%v are ',
       $c->Cmp($h, \%v) ? "" : "not ", "identical.\n";

DESCRIPTION
===========

   Compare two perl data structures recursively. Returns 0 if the
structures differ, else returns 1.

BUGS
====

   `Data::Compare' cheats with REF, CODE and GLOB references. If such a
reference is encountered in a structure being processed, the result is 0
unless references are equal.

   Currently, there is no way to compare two compiled piece of code with
perl so there is no hope to add a better CODE references support in
`Data::Compare' in a near future.

AUTHOR
======

   Fabien Tassin        fta@oleane.net

   Copyright (c) 1999 Fabien Tassin. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

VERSION
=======

   Version 0.01    (21 Apr 1999)

SEE ALSO
========

   perl(1), perlref(1)

Delimited-key access to complex data structures
***********************************************

NAME
====

   Data::DRef - Delimited-key access to complex data structures

SYNOPSIS
========

     use Data::DRef qw( :dref_access );
     my $hash = { 'items' => [ 'first' ] };
     print get_value_for_dref($hash, 'items.0');
     set_value_for_dref( $hash, 'items.1', 'second' );

     set_value_for_root_dref( 'myhash', $hash );
     print get_value_for_root_dref('myhash.items.0');

     use Data::DRef qw( :select );
     matching_keys($target, %filter_criteria) : $key or @keys
     matching_values($target, %filter_criteria) : $item or @items

     use Data::DRef qw( :index );
     index_by_drefs($target, @drefs) : $index
     unique_index_by_drefs($target, @drefs) : $index
     ordered_index_by_drefs( $target, $index_dref ) : $entry_ary

     use Data::DRef qw( :leaf );
     leaf_drefs($target) : @drefs
     leaf_values( $target ) : @values
     leaf_drefs_and_values( $target ) : %dref_value_pairs

DESCRIPTION
===========

   Data::DRef provides a streamlined interface for accessing values within
nested Perl data structures. These structures are generally networks of
hashes and arrays, some of which may be blessed into various classes,
containing a mix of simple scalar values and references to other items in
the structure.

   The Data::DRef functions allow you to use delimited key strings to set
and retrieve values at desired nodes within these structures. These
functions are slower than direct variable access, but provide additional
flexibility for high-level scripting and other late-binding behaviour. For
example, a web-based application could use DRefs to simplify customization,
allowing the user to refer to arguments processed by CGI.pm in fairly
readable way, such as `query.param.*foo*'.

   A suite of utility functions, previous maintained in a separate
Data::Collection module, performs a variety of operations across nested
data structures. Because the Data::DRef abstraction layer is used, these
functions should work equally well with arrays, hashes, or objects that
provide their own key-value interface.

REFERENCE
=========

Value-For-Key Interface
-----------------------

   The first set of functions define our core key-value interface, and
provide its implementation for references to Perl arrays and hashes. For
example, direct access to array and hash keys usually looks like this:

     print $employee->[3];
     $person->{'name'} = 'Joe';

   Using these functions, you could replace the above statements with:

     print get_value_for_key( $employee, 3 );
     set_value_for_key( $person, 'name', 'Joe' );

   Each of these functions checks for object methods as described below.

get_keys($target) : @keys
     Returns a list of keys for which this item would be able to provide a
     value. For hash refs, returns the hash keys; for array refs, returns a
     list of numbers from 0 to $#; otherwise returns nothing.

get_values($target) : @values
     Returns a list of values for this item. For hash refs, returns the
     hash values; for array refs, returns the array contents; otherwise
     returns nothing.

get_value_for_key($target, $key) : $value
     Returns the value associated with this key. For hash refs, returns the
     value at this key, if present; for array refs, returns the value at
     this index, or complains if it's not numeric.

set_value_for_key($target, $key, $value)
     Sets the value associated with this key. For hash refs, adds or
     overwrites the entry for this key; for array refs, sets the value at
     this index, or complains if it's not numeric.

get_or_create_value_for_key($target, $key) : $value
     Gets value associated with this key using get_value_for_key, or if
     that value is undefined, sets the value to refer to a new anonymous
     hash using set_value_for_key and returns that reference.

get_reference_for_key($target, $key) : $value_reference
     Returns a reference to the scalar which is used to hold the value
     associated with this key.

Multiple-Key Chaining
---------------------

   Frequently we wish to access values at some remove within a structure
by chaining through a list of references. Programmatic access to these
values within Perl usually looks something like this:

     print $report->{'employees'}[3]{'id'};
     $report->{'employees'}[3]{'name'} = 'Joe';

   Using these functions, you could replace the above statements with:

     print get_value_for_keys( $report, 'employees', 3, 'id' );
     set_value_for_keys( $report, 'Joe', 'employees', 3, 'name' );

   These functions also support the "m_*" method delegation described
above.

get_value_for_keys($target, @keys) : $value
     Starting at the target, look up each of the provided keys sequentially
     from the results of the previous one, returning the final value.
     Return value is undefined if at any time we find a key for which no
     value is present.

set_value_for_keys($target, $value, @keys)
     Starting at the target, look up each of the provided keys sequentially
     from the results of the previous one; when we reach the final key, use
     set_value_for_key to make the assignment. If an intermediate value is
     undefined, replaces it with an empty hash to hold the next key-value
     pair.

get_or_create_value_for_keys($target, @keys) : $value
     As above.

get_reference_for_keys($target, @keys) : $val_ref
     As above.

Object Overrides
----------------

   Each of the value-for-key and multiple-key functions first check for
methods with similar names preceeded by "m_" and, if present, uses that
implementation. For example, callers can consistently request
`get_value_for_key($foo, $key)', but in cases where `$foo' supports a
method named `m_get_value_for_key', its results will be returned instead.

   Classes that wish to provide alternate DRef-like behavior or generate
values on demand should implement these methods in their packages.  A
Data::DRef::MethodBased class is provided for use by objects which use
methods to get and set attributes. By making your package a subclass of
MethodBased you'll inherit m_get_value_for_key and m_set_value_for_key
methods which treat the key as a method name to invoke.

DRef Syntax
-----------

   In order to simplify expression of the lists of keys used above, we
define a string format in which they may be represented. A DRef string is
composed of a series of simple scalar keys, each escaped with
String::Escape's printable() function, joined with the $Separator
character, '.'.

$Separator
     The multiple-key delimiter character, by default ., the period
     character.

get_key_drefs($target) : @drefs
     Uses get_keys to determine the available keys for this target, and
     then returns an appropriately-escaped version of each of them.

dref_from_keys( @keys ) : $dref
     Escapes and joins the provided keys to create a dref string.

keys_from_dref( $dref ) : @keys
     Splits and unescapes a dref string to its consituent keys.

join_drefs( @drefs ) : $dref
     Joins already-escaped dref strings into a single dref.

unshift_dref_key( $dref, $key )
     Modify the provided dref string by escaping and prepending the
     provided key.  Note that the original $dref variable is altered.

shift_dref_key( $dref ) : $key
     Modify the provided dref string by removing and unescaping the first
     key.  Note that the original $dref variable is altered, and set to "
     when the last key is removed.

DRef Pragmas
------------

   Several types of parenthesized expressions are supported as extension
mechanisms for dref strings. Nested parentheses are supported, with the
innermost parentheses resolved first.

   Continuing the above example, one could write:

     set_value_for_root_dref('empl_number', 3);
     ...
     print get_value_for_dref($report, 'employees.(#empl_number).name');

resolve_pragmas( $dref_with_embedded_parens ) : $dref
resolve_pragmas( $dref_with_embedded_parens ) : ($dref, %options)
     Calling resolve_pragmas() causes these expressions to be evaluated,
     and an expanded version of the dref is returned. In a list context,
     also returns a list of key-value pairs that may contain pragma
     information.

    (#*dref*)
          Parenthesized expressions begining with $DRefPrefix, the "#"
          character by default, are replaced with the Root-relative value
          for that *dref* using get_value_for_root_dref().

    (!flag)
          A flag indicating some optional or accessory behavior. Removed
          from the string. Sets $options{flag} to 1.

DRef Access
-----------

   These functions provide the main public interface for dref-based access
to values in nested data structures. They invoke the equivalent
..._value_for_keys() function after expanding and spliting the provided
drefs.

   Using these functions, you could replace the above statements with:

     print get_value_for_dref( $report, 'employees.3.id' );
     set_value_for_dref( $report, 'employees.3.name', 'Joe' );

get_value_for_dref($target, $dref) : $value
     Resolve pragmas and split the provided dref, then use
     get_value_for_keys to look those keys up starting with target.

set_value_for_dref($target, $dref, $value)
     Resolve pragmas and split the provided dref, then use
     set_value_for_keys.

Shared Data Graph Entry
-----------------------

   Data::DRef also provides a common point-of-entry datastructure, refered
to as $Root. Objects or structures accessible through $Root can be refered
to identically from any package using the get_value_for_root_dref and
set_value_for_root_dref functions. Here's another example:

     set_value_for_root_dref('report', $report);
     print get_value_for_root_dref('report.employees.3.name');

$Root
     The data graph entry point, by default a reference to an anonymous
     hash.

get_value_for_root_dref($dref) : $value
     Returns the value for the provided dref, starting at the root.

set_value_for_root_dref($dref, $value) : $value
     Sets the value for the provided dref, starting at the root.

get_value_for_optional_dref($literal_or_prefixed_dref) : $value
     If the argument begins with $DRefPrefix, the "#" character by default,
     the remainder is passed through get_value_for_root_dref(); otherwise
     it is returned unchanged.

Select by DRefs
---------------

   The selection functions extract and return elements of a collection by
evaluating them against a provided hash of criteria. When called in a
scalar context, they will return the first sucessful match; in a list
context, they will return all sucessful matches.

   The keys in the criteria hash are drefs to check for each candidate; a
match is sucessful if for each of the provided drefs, the candidate
returns the same value that is associated with that dref in the criteria
hash. To check the value itself, rather than looking up a dref, use undef
as the hash key.

matching_keys($target, %dref_value_criteria_pairs) : $key or @keys
     Returns keys of the target whose corresponding values match the
     provided criteria.

matching_values($target, %dref_value_criteria_pairs) : $item or @items
     Returns values of the target which match the provided criteria.

Index by DRefs
--------------

   The indexing functions extract the values from some target structure,
then return a new structure containing references to those same values.

index_by_drefs($target, @drefs) : $index
     Generates a hash, or series of nested hashes, of arrays containing
     values from the target. A single dref argument produces a
     single-level index, a hash which maps each value obtained to an array
     of values which returned them; multiple dref arguments create nested
     hashes.

unique_index_by_drefs($target, @drefs) : $index
     Similar to index_by_drefs, except that only the most-recently visited
     single value is stored at each point in the index, rather than an
     array.

ordered_index_by_drefs( $target, $index_dref ) : $entry_ary
     Constructs a single-level index while preserving the order in which
     top-level index keys are discovered. An array of hashes is returned,
     each containing one of the index keys and the array of associated
     values.

DRefs to Leaf nodes
-------------------

   These functions explore all of the references in the network of
structures accessible from some starting point, and provide access to the
outermost (non-reference) items. For a tree structure, this is equivalent
to listing the leaf nodes, but these functions can also be used in
structures with circular references.

leaf_drefs($target) : @drefs
     Returns a list of drefs to the outermost values.

leaf_values( $target ) : @values
     Returns a list of the outermost values.

leaf_drefs_and_values( $target ) : %dref_value_pairs
     Returns a flat hash of the outermost drefs and values.

Compatibility
-------------

   To provide compatibility with earlier versions of this module, many of
the functions above are also accesible through an alias with the old name.

EXAMPLES
========

   Here is a sample data structure which will be used to illustrate various
example function calls. Note that the individual hashes shown below are
only refered to in the following example results, not completely copied.

     $spud : {
       'type'=>'tubers', 'name'=>'potatoes', 'color'=>'red', 'size'=>[2,3,5]
     }
     $apple : {
       'type'=>'fruit', 'name'=>'apples', 'color'=>'red', 'size'=>[2,2,2]
     }
     $orange : {
       'type'=>'fruit', 'name'=>'oranges', 'color'=>'orange', 'size'=>[1,1,1]
     }

     $produce_info : [ $spud, $apple, $orange, ];

Select by DRefs
---------------

     matching_keys($produce_info, 'type'=>'tubers') : ( 0 )
     matching_keys($produce_info, 'type'=>'fruit') : ( 1, 2 )
     matching_keys($produce_info, 'type'=>'fruit', 'color'=>'red' ) : ( 1 )
     matching_keys($produce_info, 'type'=>'tubers', 'color'=>'orange' ) : ( )

     matching_values($produce_info, 'type'=>'fruit') : ( $apple, $orange )
     matching_values($produce_info, 'type'=>'fruit', 'color'=>'red' ) : ( $apple )

Index by DRefs
--------------

     index_by_drefs($produce_info, 'type') : {
       'fruit' =>  [ $apple, $orange ],
       'tubers' => [ $spud ],
     }

     index_by_drefs($produce_info, 'color', 'type') : {
       'red' => {
         'fruit' => [ $apple ],
         'tubers' => [ $spud ],
       },
       'orange' => {
         'fruit' => [ $orange ],
       },
     }

     unique_index_by_drefs($produce_info, 'type') : {
       'fruit' => $orange,
       'tubers' => $spud,
     }

     ordered_index_by_drefs($produce_info, 'type') : [
       {
         'value' => 'tubers',
         'items' => [ $spud ],
       },
       {
         'value' => 'fruit',
         'items' => [ $orange, $apple ],
       },
     ]

DRefs to Leaf nodes
-------------------

     leaf_drefs($spud) : ( 'type', 'name', 'color', 'size.0', 'size.1', 'size.2' )

     leaf_values($spud) : ( 'tubers', 'potatoes', 'red', '2', '3', '5' )

     leaf_drefs_and_values($spud) : (
       'type' => 'tubers', 'name' => 'potatoes', 'color' => 'red',
       'size.0' => 2, 'size.1' => 3, 'size.2' => 5
     )

Object Overrides
----------------

   Here's a get_value_for_key method for an object which provides a
calculated timestamp value:

     package Clock;

     sub new { bless { @_ }; }

     sub m_get_value_for_key {
       my ($self, $key) = @_;
       return time() if ( $key eq 'timestamp' );
       return $self->{ $key };
     }

     package main;

     set_value_for_root_dref( 'clock', new Clock ( name => "Clock 1" ) );
     ...
     print get_value_for_root_dref('clock.timestamp');

STATUS AND SUPPORT
==================

   This release of Data::DRef is intended for public review and feedback.
This is the most recent version of code that has been used for several
years and thoroughly tested, however, the interface has recently been
overhauled and it should be considered "alpha" pending that feedback.

     Name            DSLI  Description
     --------------  ----  ---------------------------------------------
     Data::
     ::DRef          adph  Nested data access using delimited strings

   You will also need the String::Escape module from CPAN or
www.evoscript.com.

   Further information and support for this module is available at
<www.evoscript.com>.

   Please report bugs or other problems to <bugs@evoscript.com>.

   There is one known bug in this version:

   * We don't always properly escape and unescape special characters within
     DRef strings or protect $Separators embedded within a subkey. This is
     expected to change soon.

   There is one major change under consideration:

   * Perhaps a minimal method-based implementation similar to that used in
     Data::DRef::MethodBased should be exported to UNIVERSAL, rather than
     requiring all sorts of unrelated classes to establish a dependancy on
     this module.  Prototype checking might prove to be useful here.

AUTHORS AND COPYRIGHT
=====================

   Copyright 1996, 1997, 1998, 1999 Evolution Online Systems, Inc.
<www.evolution.com>

   You may use this software for free under the terms of the Artistic
License.

   Contributors: M. Simon Cavalletto <simonm@evolution.com>, E. J. Evans
<piglet@evolution.com>

Perl module to emulate seqeuntial access to SQL tables.
*******************************************************

NAME
====

   Data::Direct - Perl module to emulate seqeuntial access to SQL tables.

SYNOPSIS
========

In a script:
------------

   use Data::Direct;

   $dd = new Data::Direct("dbi:Informix:FBI", "bill_c", "M0n|c4",
"porn_suppliers", "PRICE < 99.99", "ORDER BY PUBLICATION_DATE" || die
"Failed to connect";

   Last two arguments can be ommitted.

     while (!$dd->eof) {
     		# Iterate over all records
     if ($dd{'LAST_MODIFIED'}) {
     	$dd->delete;
     		# Mark RIP flag
     	next;
     }
     		# Change fields
     $dd->{'KILL'}++ if ($dd->{'REVENUE'} > 199.99);
     $dd->update;
     		# Update record in memory
     $dd->next;
     		# Goto next record
     }

   $dd->addnew;                            # Add a new record
$dd->{'PRICE'} = 999.99; $dd->{'KILL'} = 0; $dd->{'REVENUE'} = 199.99;
$dd->update;                            # Update new record in memory

   $dd->flush;                             # Rewrite table

From the command prompt:
------------------------

*prompt %* perl -MData::Direct -e 'edit("dbi::XBase::/var/db/files",  "contacts");'
*prompt %* perl -MData::Direct -e 'edit("dbi::Oracle::CIA",  "weapons");' /U 'bill_c' /P 'M0n1c4'  /W "EXPIRES <= SYS_DATE()" /A "GROUP BY PRICE"
DESCRIPTION
===========

   Data::Direct selects rows from a table and lets you updated them in a
memory array. Upon calling the flush method, it erases the records from
the table and inserts them from the array.  You can supply a WHERE filter
to be applied both on query and on deletion, and additional SQL code for
sorting the records.

OPTIONS
=======

Constructor
-----------

new($dsn, $user, $pass, $table [, $where_clause [, $additional_select_code]] Connects to the DBI DSN specified, using #user and $pass. $where_clause and $additional_select_code will be added to your SQL code. After that, reads all the records to memory.
Navigating
----------

next
     Fetches the next record. Returns undef if gone past end.

back
     Fetches the previous record. Returns undef if gone past beginning.

eof
     Returns true if cursor is after all the records.

bof
     Simillar, checks beginning of table.

recs
     Returns the number of records in the buffer

rows
     Returns the number of records in the buffer which are not deleted.
     recs and rows are not the same!

*setbookmark*($name)
     Sets a named bookmark, to be used for gotobookmark.

*gotobookmark*($name)
     Takes the cursor to the specific bookmark.

fetch(*$rownumber*)
     Retrieve a numbered record.

cursor
     Returns the row number the cursor is at.

Manipulating records
--------------------

bind(*$column* => *\$var*, *$column* => *\$var*...)
     Binds a column to a scalar, using a scalar reference.

*bindsimple*($package)
     Binds each column to a variable with the same name, under the package
     given. Use bindsimple with no parameters to bind to the main
     namespace.

update
     Update record after fields have been changed by accessing the members
     of the object or the bound variables.

addnew
     Add a new record and point the cursor on it.

delete
     Mark a record for deletion.

undelete
     Unmark a record for deletion.

isdeleted
     Check if a record is marked for deletion.

Automatic editing
-----------------

spawn($editor, $packing_instructions, $unpacking_instructions)
     Writes a text file where every line represents a record, launch the
     process $editor, then update the table with the saved file.  Records
     are serialized and deserialized by the code references in the last
     parameters.

     $dd->spawn("grep <-v> <-i> Bill", sub {join(":", @_);}, 	sub
     {my $l = <$_>; chop $l; split(/:/, $l);});

spawn(*$editor*, *$delimiter*)
     Uses the string as a delimiter to serialize and deserialize records.

spawn(*$editor*)
     Uses CSV format to serialize and deserialize records.

spawn
     Launches vi or whatever $ENV{'EDITOR'} points to as an editor.

AUTHOR
======

   Ariel Brosh, *schop@cpan.org*

SEE ALSO
========

   `DBI' in this node.

Pretty printing of data structures
**********************************

NAME
====

   Data::Dump - Pretty printing of data structures

SYNOPSIS
========

     use Data::Dump qw(dump);

     $str = dump(@list)
     @copy_of_list = eval $str;

DESCRIPTION
===========

   This module provide a single function called dump() that takes a list
of values as argument and produce a string as result.  The string contains
perl code that when evaled will produce a deep copy of the original
arguments.  The string is formatted for easy reading.

   If dump() is called in void context, then the dump will be printed on
STDERR instead of being returned.

   If you don't like to import a function that overrides Perl's
not-so-useful builtin, then you can also import the same function as pp(),
mnemonic for "pretty-print".

HISTORY
=======

   The `Data::Dump' module grew out of frustration with Sarathy's
in-most-cases-excellent Data::Dumper.  Basic ideas and some code is shared
with Sarathy's module.

   The `Data::Dump' module provide a much simpler interface than
Data::Dumper.  No OO interface is available and there are no configuration
options to worry about (yet :-).  The other benefit is that the dump
produced does not try to set any variables.  It only returns what is
needed to produce a copy of the arguments.  It means that `dump("foo")'
simply returns `"foo"', and `dump(1..5)' simply returns `(1, 2, 3, 4, 5)'.

SEE ALSO
========

   See Data/Dumper, Storable,

AUTHORS
=======

   The `Data::Dump' module is written by Gisle Aas <gisle@aas.no>, based
on Data::Dumper by Gurusamy Sarathy <gsar@umich.edu>.

     Copyright 1998-2000 Gisle Aas.
     Copyright 1996-1998 Gurusamy Sarathy.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Dump arbitrary data structures as XML
*************************************

NAME
====

   Data::DumpXML - Dump arbitrary data structures as XML

SYNOPSIS
========

     use Data::DumpXML qw(dump_xml);
     $xml = dump_xml(@list)

DESCRIPTION
===========

   This module provide a single function called dump_xml() that takes a
list of something as argument and produce a string as result.

   The string returned is an XML document that represents any perl data
structure passed in.  The following DTD is used:

     <!DOCTYPE data [
      <!ENTITY % scalar "undef | str | ref | alias">

     <!ELEMENT data (%scalar;)*>
     <!ELEMENT undef EMPTY>
     <!ELEMENT str (#PCDATA)>
     <!ELEMENT ref (%scalar; | array | hash | glob | code)>
     <!ELEMENT alias EMPTY>
     <!ELEMENT array (%scalar;)*>
     <!ELEMENT hash  (key, (%scalar;))*>
     <!ELEMENT key (#PCDATA)>
     <!ELEMENT glob EMPTY>
     <!ELEMENT code EMPTY>

     <!ENTITY % stdattlist 'id       ID             #IMPLIED
                            class    CDATA          #IMPLIED'>
     <!ENTITY % encoding   'encoding (plain|base64) "plain"'>

     <!ATTLIST undef %stdattlist;>
     <!ATTLIST ref %stdattlist;>
     <!ATTLIST undef %stdattlist;>
     <!ATTLIST array %stdattlist;>
     <!ATTLIST hash %stdattlist;>
     <!ATTLIST glob %stdattlist;>
     <!ATTLIST code %stdattlist;>

     <!ATTLIST str %stdattlist; %encoding;>
     <!ATTLIST key %encoding;>

     <!ATTLIST alias ref IDREF #IMPLIED>
       ]>

   As an example of the XML documents producted; the following call:

     $a = bless [1,2], "Foo";
     $a->[2] = \$a;
     $b = $a;
     dump_xml($a, $b);

   will produce:

     <?xml version="1.0" encoding="US-ASCII"?>
     <data>
      <ref id="r1">
       <array class="Foo" id="r2">
        <str>1</str>
        <str>2</str>
        <ref>
         <alias ref="r1"/></ref></array></ref>
      <ref>
       <alias ref="r2"/></ref></data>

   If dump_xml() is called in void context, then the dump will be printed
on STDERR instead of being returned.  For compatibility with `Data::Dump'
there is also an alias for dump_xml() simply called dump().

   You can set the variable $Data::DumpXML::INDENT to control indenting
before calling dump_xml().  To suppress indenting set it as "".

   The `Data::DumpXML::Parser' is a class that can restore datastructures
dumped by dump_xml().

BUGS
====

   Class names with 8-bit characters will be dumped as Latin-1, but
converted to UTF-8 when restored by the Data::DumpXML::Parser.

   The content of globs and subroutines are not dumped.  They are restored
as the strings; "** glob **" and "** code **".

   LVALUE and IO objects are not dumped at all.  They will simply
disappear from the restored data structure.

SEE ALSO
========

   See Data/DumpXML/Parser, XML/Parser,
see XML/Dumper, Data/Dump,

AUTHORS
=======

   The `Data::DumpXML' module is written by Gisle Aas <gisle@aas.no>,
based on `Data::Dump'.

   The `Data::Dump' module was written by Gisle Aas, based on Data::Dumper
by Gurusamy Sarathy <gsar@umich.edu>.

     Copyright 1998-2000 Gisle Aas.
     Copyright 1996-1998 Gurusamy Sarathy.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Restore data dumped by Data::DumpXML
************************************

NAME
====

   Data::DumpXML::Parser - Restore data dumped by Data::DumpXML

SYNOPSIS
========

     use Data::DumpXML::Parser;

     my $p = Data::DumpXML::Parser->new;
     my $data = $p->parsefile(shift || "test.xml");

DESCRIPTION
===========

   The `Data::DumpXML::Parser' is an XML::Parser subclass that will
recreate the data structure from the XML document produced by
`Data::DumpXML'.  The parserfile() method returns a reference to an array
of the values dumped.

   The constructor method new() takes a single additional argument to that
of XML::Parser :

Blesser => CODEREF
     A subroutine that is invoked for blessing of restored objects.  The
     subroutine is invoked with two arguments; a reference to the object
     and a string containing the class name.  If not provided the built in
     bless function is used.

     For situations where the input file cannot necessarily be trusted and
     blessing arbitrary Classes might give the ability of malicious input
     to exploit the DESTROY methods of modules used by the code it is a
     good idea to provide an noop blesser:

          my $p = Data::DumpXML::Parser->new(Blesser => sub {});

SEE ALSO
========

   See Data/DumpXML, XML/Parser,

AUTHOR
======

   Copyright 2000 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

stringified perl data structures, suitable for both printing and eval
*********************************************************************

NAME
====

   Data::Dumper - stringified perl data structures, suitable for both
printing and eval

SYNOPSIS
========

     use Data::Dumper;

     # simple procedural interface
     print Dumper($foo, $bar);

     # extended usage with names
     print Data::Dumper->Dump([$foo, $bar], [qw(foo *ary)]);

     # configuration variables
     {
       local $Data::Dump::Purity = 1;
       eval Data::Dumper->Dump([$foo, $bar], [qw(foo *ary)]);
     }

     # OO usage
     $d = Data::Dumper->new([$foo, $bar], [qw(foo *ary)]);
        ...
     print $d->Dump;
        ...
     $d->Purity(1)->Terse(1)->Deepcopy(1);
     eval $d->Dump;

DESCRIPTION
===========

   Given a list of scalars or reference variables, writes out their
contents in perl syntax. The references can also be objects.  The contents
of each variable is output in a single Perl statement.  Handles
self-referential structures correctly.

   The return value can be evaled to get back an identical copy of the
original reference structure.

   Any references that are the same as one of those passed in will be named
`$VAR'n (where n is a numeric suffix), and other duplicate references to
substructures within `$VAR'n will be appropriately labeled using arrow
notation.  You can specify names for individual values to be dumped if you
use the `Dump()' method, or you can change the default `$VAR' prefix to
something else.  See $Data::Dumper::Varname and $Data::Dumper::Terse below.

   The default output of self-referential structures can be evaled, but the
nested references to `$VAR'n will be undefined, since a recursive
structure cannot be constructed using one Perl statement.  You should set
the `Purity' flag to 1 to get additional statements that will correctly
fill in these references.

   In the extended usage form, the references to be dumped can be given
user-specified names.  If a name begins with a *, the output will describe
the dereferenced type of the supplied reference for hashes and arrays, and
coderefs.  Output of names will be avoided where possible if the `Terse'
flag is set.

   In many cases, methods that are used to set the internal state of the
object will return the object itself, so method calls can be conveniently
chained together.

   Several styles of output are possible, all controlled by setting the
`Indent' flag.  See `Configuration Variables or Methods' in this node below
for details.

Methods
-------

PACKAGE->new(*ARRAYREF [*, *ARRAYREF]*)
     Returns a newly created Data::Dumper object.  The first argument is an
     anonymous array of values to be dumped.  The optional second argument
     is an anonymous array of names for the values.  The names need not
     have a leading `$' sign, and must be comprised of alphanumeric
     characters.  You can begin a name with a * to specify that the
     dereferenced type must be dumped instead of the reference itself, for
     ARRAY and HASH references.

     The prefix specified by $Data::Dumper::Varname will be used with a
     numeric suffix if the name for a value is undefined.

     Data::Dumper will catalog all references encountered while dumping the
     values. Cross-references (in the form of names of substructures in
     perl syntax) will be inserted at all possible points, preserving any
     structural interdependencies in the original set of values.
     Structure traversal is depth-first,  and proceeds in order from the
     first supplied value to the last.

*$OBJ*->Dump  or  PACKAGE->Dump(*ARRAYREF [*, *ARRAYREF]*)
     Returns the stringified form of the values stored in the object
     (preserving the order in which they were supplied to new), subject to
     the configuration options below.  In an array context, it returns a
     list of strings corresponding to the supplied values.

     The second form, for convenience, simply calls the new method on its
     arguments before dumping the object immediately.

*$OBJ*->Dumpxs  or  PACKAGE->Dumpxs(*ARRAYREF [*, *ARRAYREF]*)
     This method is available if you were able to compile and install the
     XSUB extension to Data::Dumper. It is exactly identical to the `Dump'
     method above, only about 4 to 5 times faster, since it is written
     entirely in C.

*$OBJ*->Seen(*[HASHREF]*)
     Queries or adds to the internal table of already encountered
     references.  You must use Reset to explicitly clear the table if
     needed.  Such references are not dumped; instead, their names are
     inserted wherever they are encountered subsequently.  This is useful
     especially for properly dumping subroutine references.

     Expects a anonymous hash of name => value pairs.  Same rules apply
     for names as in new.  If no argument is supplied, will return the
     "seen" list of name => value pairs, in an array context.  Otherwise,
     returns the object itself.

*$OBJ*->Values(*[ARRAYREF]*)
     Queries or replaces the internal array of values that will be dumped.
     When called without arguments, returns the values.  Otherwise,
     returns the object itself.

*$OBJ*->Names(*[ARRAYREF]*)
     Queries or replaces the internal array of user supplied names for the
     values that will be dumped.  When called without arguments, returns
     the names.  Otherwise, returns the object itself.

*$OBJ*->Reset
     Clears the internal table of "seen" references and returns the object
     itself.

Functions
---------

Dumper(LIST)
     Returns the stringified form of the values in the list, subject to the
     configuration options below.  The values will be named `$VAR'n in the
     output, where n is a numeric suffix.  Will return a list of strings
     in an array context.

DumperX(LIST)
     Identical to the `Dumper()' function above, but this calls the XSUB
     implementation.  Only available if you were able to compile and
     install the XSUB extensions in Data::Dumper.

Configuration Variables or Methods
----------------------------------

   Several configuration variables can be used to control the kind of
output generated when using the procedural interface.  These variables are
usually localized in a block so that other parts of the code are not
affected by the change.

   These variables determine the default state of the object created by
calling the new method, but cannot be used to alter the state of the object
thereafter.  The equivalent method names should be used instead to query
or set the internal state of the object.

   The method forms return the object itself when called with arguments,
so that they can be chained together nicely.

$Data::Dumper::Indent  or  *$OBJ*->Indent(*[NEWVAL]*)
     Controls the style of indentation.  It can be set to 0, 1, 2 or 3.
     Style 0 spews output without any newlines, indentation, or spaces
     between list items.  It is the most compact format possible that can
     still be called valid perl.  Style 1 outputs a readable form with
     newlines but no fancy indentation (each level in the structure is
     simply indented by a fixed amount of whitespace).  Style 2 (the
     default) outputs a very readable form which takes into account the
     length of hash keys (so the hash value lines up).  Style 3 is like
     style 2, but also annotates the elements of arrays with their index
     (but the comment is on its own line, so array output consumes twice
     the number of lines).  Style 2 is the default.

$Data::Dumper::Purity  or  *$OBJ*->Purity(*[NEWVAL]*)
     Controls the degree to which the output can be evaled to recreate the
     supplied reference structures.  Setting it to 1 will output
     additional perl statements that will correctly recreate nested
     references.  The default is 0.

$Data::Dumper::Pad  or  *$OBJ*->Pad(*[NEWVAL]*)
     Specifies the string that will be prefixed to every line of the
     output.  Empty string by default.

$Data::Dumper::Varname  or  *$OBJ*->Varname(*[NEWVAL]*)
     Contains the prefix to use for tagging variable names in the output.
     The default is "VAR".

$Data::Dumper::Useqq  or  *$OBJ*->Useqq(*[NEWVAL]*)
     When set, enables the use of double quotes for representing string
     values.  Whitespace other than space will be represented as
     `[\n\t\r]', "unsafe" characters will be backslashed, and unprintable
     characters will be output as quoted octal integers.  Since setting
     this variable imposes a performance penalty, the default is 0.  The
     `Dumpxs()' method does not honor this flag yet.

$Data::Dumper::Terse  or  *$OBJ*->Terse(*[NEWVAL]*)
     When set, Data::Dumper will emit single, non-self-referential values
     as atoms/terms rather than statements.  This means that the `$VAR'n
     names will be avoided where possible, but be advised that such output
     may not always be parseable by eval.

$Data::Dumper::Freezer  or  $OBJ->Freezer(*[NEWVAL]*)
     Can be set to a method name, or to an empty string to disable the
     feature.  Data::Dumper will invoke that method via the object before
     attempting to stringify it.  This method can alter the contents of
     the object (if, for instance, it contains data allocated from C), and
     even rebless it in a different package.  The client is responsible
     for making sure the specified method can be called via the object,
     and that the object ends up containing only perl data types after the
     method has been called.  Defaults to an empty string.

$Data::Dumper::Toaster  or  $OBJ->Toaster(*[NEWVAL]*)
     Can be set to a method name, or to an empty string to disable the
     feature.  Data::Dumper will emit a method call for any objects that
     are to be dumped using the syntax `bless(DATA, CLASS)-'METHOD()>.
     Note that this means that the method specified will have to perform
     any modifications required on the object (like creating new state
     within it, and/or reblessing it in a different package) and then
     return it.  The client is responsible for making sure the method can
     be called via the object, and that it returns a valid object.
     Defaults to an empty string.

$Data::Dumper::Deepcopy  or  $OBJ->Deepcopy(*[NEWVAL]*)
     Can be set to a boolean value to enable deep copies of structures.
     Cross-referencing will then only be done when absolutely essential
     (i.e., to break reference cycles).  Default is 0.

$Data::Dumper::Quotekeys  or  $OBJ->Quotekeys(*[NEWVAL]*)
     Can be set to a boolean value to control whether hash keys are quoted.
     A false value will avoid quoting hash keys when it looks like a simple
     string.  Default is 1, which will always enclose hash keys in quotes.

$Data::Dumper::Bless  or  $OBJ->Bless(*[NEWVAL]*)
     Can be set to a string that specifies an alternative to the bless
     builtin operator used to create objects.  A function with the
     specified name should exist, and should accept the same arguments as
     the builtin.  Default is bless.

Exports
-------

Dumper
EXAMPLES
========

   Run these code snippets to get a quick feel for the behavior of this
module.  When you are through with these examples, you may want to add or
change the various configuration variables described above, to see their
behavior.  (See the testsuite in the Data::Dumper distribution for more
examples.)

     use Data::Dumper;

     package Foo;
     sub new {bless {'a' => 1, 'b' => sub { return "foo" }}, $_[0]};

     package Fuz;                       # a weird REF-REF-SCALAR object
     sub new {bless \($_ = \ 'fu\'z'), $_[0]};

     package main;
     $foo = Foo->new;
     $fuz = Fuz->new;
     $boo = [ 1, [], "abcd", \*foo,
              {1 => 'a', 023 => 'b', 0x45 => 'c'},
              \\"p\q\'r", $foo, $fuz];

     ########
     # simple usage
     ########

     $bar = eval(Dumper($boo));
     print($@) if $@;
     print Dumper($boo), Dumper($bar);  # pretty print (no array indices)

     $Data::Dumper::Terse = 1;          # don't output names where feasible
     $Data::Dumper::Indent = 0;         # turn off all pretty print
     print Dumper($boo), "\n";

     $Data::Dumper::Indent = 1;         # mild pretty print
     print Dumper($boo);

     $Data::Dumper::Indent = 3;         # pretty print with array indices
     print Dumper($boo);

     $Data::Dumper::Useqq = 1;          # print strings in double quotes
     print Dumper($boo);

     ########
     # recursive structures
     ########

     @c = ('c');
     $c = \@c;
     $b = {};
     $a = [1, $b, $c];
     $b->{a} = $a;
     $b->{b} = $a->[1];
     $b->{c} = $a->[2];
     print Data::Dumper->Dump([$a,$b,$c], [qw(a b c)]);

     $Data::Dumper::Purity = 1;         # fill in the holes for eval
     print Data::Dumper->Dump([$a, $b], [qw(*a b)]); # print as @a
     print Data::Dumper->Dump([$b, $a], [qw(*b a)]); # print as %b

     $Data::Dumper::Deepcopy = 1;       # avoid cross-refs
     print Data::Dumper->Dump([$b, $a], [qw(*b a)]);

     $Data::Dumper::Purity = 0;         # avoid cross-refs
     print Data::Dumper->Dump([$b, $a], [qw(*b a)]);

     ########
     # object-oriented usage
     ########

     $d = Data::Dumper->new([$a,$b], [qw(a b)]);
     $d->Seen({'*c' => $c});            # stash a ref without printing it
     $d->Indent(3);
     print $d->Dump;
     $d->Reset->Purity(0);              # empty the seen cache
     print join "----\n", $d->Dump;

     ########
     # persistence
     ########

     package Foo;
     sub new { bless { state => 'awake' }, shift }
     sub Freeze {
         my $s = shift;
     	print STDERR "preparing to sleep\n";
     	$s->{state} = 'asleep';
     	return bless $s, 'Foo::ZZZ';
     }

     package Foo::ZZZ;
     sub Thaw {
         my $s = shift;
     	print STDERR "waking up\n";
     	$s->{state} = 'awake';
     	return bless $s, 'Foo';
     }

     package Foo;
     use Data::Dumper;
     $a = Foo->new;
     $b = Data::Dumper->new([$a], ['c']);
     $b->Freezer('Freeze');
     $b->Toaster('Thaw');
     $c = $b->Dump;
     print $c;
     $d = eval $c;
     print Data::Dumper->Dump([$d], ['d']);

     ########
     # symbol substitution (useful for recreating CODE refs)
     ########

     sub foo { print "foo speaking\n" }
     *other = \&foo;
     $bar = [ \&other ];
     $d = Data::Dumper->new([\&other,$bar],['*other','bar']);
     $d->Seen({ '*foo' => \&foo });
     print $d->Dump;

BUGS
====

   Due to limitations of Perl subroutine call semantics, you cannot pass an
array or hash.  Prepend it with a \ to pass its reference instead.  This
will be remedied in time, with the arrival of prototypes in later versions
of Perl.  For now, you need to use the extended usage form, and prepend the
name with a * to output it as a hash or array.

   Data::Dumper cheats with CODE references.  If a code reference is
encountered in the structure being processed, an anonymous subroutine that
contains the string '"DUMMY"' will be inserted in its place, and a warning
will be printed if `Purity' is set.  You can eval the result, but bear in
mind that the anonymous sub that gets created is just a placeholder.
Someday, perl will have a switch to cache-on-demand the string
representation of a compiled piece of code, I hope.  If you have prior
knowledge of all the code refs that your data structures are likely to
have, you can use the `Seen' method to pre-seed the internal reference
table and make the dumped output point to them, instead.  See `EXAMPLES'
in this node above.

   The `Useqq' flag is not honored by `Dumpxs()' (it always outputs
strings in single quotes).

   SCALAR objects have the weirdest looking bless workaround.

AUTHOR
======

   Gurusamy Sarathy        gsar@umich.edu

   Copyright (c) 1996-98 Gurusamy Sarathy. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

VERSION
=======

   Version 2.101    (30 Apr 1999)

SEE ALSO
========

   perl(1)

converter between fixed-fields and hashes
*****************************************

NAME
====

   Data::FixedFormat - converter between fixed-fields and hashes

SYNOPSIS
========

     use Data::FixedFormat;

     my $tarhdr = new Data::FixedFormat [ 'name:a100', 'mode:a8', 'uid:a8',
     			        'gid:a8', 'size:a12', 'mtime:a12',
     				'chksum:a8', 'typeflag:a1',
     				'linkname:a100', 'magic:a6',
     				'version:a2', 'uname:a32',
     				'gname:a32', 'devmajor:a8',
     				'devminor:a8', 'prefix:a155' ];
     my $buf;
     read TARFILE, $buf, 512;

     # create a hash from the buffer read from the file
     my $hdr = $tarhdr->unformat($buf);   # $hdr gets a hash ref

     # create a flat record from a hash reference
     my $buf = $tarhdr->format($hdr);     # $hdr is a hash ref

DESCRIPTION
===========

   *Data::FixedFormat* can be used to convert between a buffer with fixed
field definitions and a hash with named entries for each field.

   First, load the Data::FixedFormat module:

     use Data::FixedFormat;

   To create a converter, invoke the new method with a reference to an
array of field specifications:

     my $cvt = new Data::FixedFormat [ 'field-name:descriptor:count', ... ];

field-name
     This is the name of the field and will be used as the hash index.

descriptor
     This describes the content and size of the field.  All of the
     descriptors get strung together and passed to pack and unpack as part
     of the template argument.  See *perldoc -f pack* for information on
     what can be specified here.

count
     This specifies a repeat count for the field.  If not specified, it
     defaults to 1.  If greater than 1, this field's entry in the resultant
     hash will be an array reference instead of a scalar.

   To convert a buffer of data into a hash, pass the buffer to the
*unformat* method:

     $hashref = $cvt->unformat($buf);

   Data::FixedFormat applies the format to the buffer and creates a hash
containing an element for each field.  Fields can now be accessed by name
though the hash:

     print $hashref->{field-name};
     print $hashref->{array-field}[3];

   To convert the hash back into a fixed-format buffer, pass the hash
reference to the format method:

     $buf = $cvt->format($hashref);

   Variant record formats are supported.  Instead of passing an array
reference to the new method, pass a hash reference containing the
following elements:

Chooser
     When converting a buffer to a hash, this subroutine is invoked after
     applying the first format to the buffer.  The hash reference is passed
     to this routine.  Any field names specified in the first format are
     available to be used in making a decision on which format to use to
     decipher the buffer.  This routine should return the index of the
     proper format specification.

     When converting a hash to a buffer, this subroutine is invoked to
     first to choose a packing format.  Since the same function is used for
     both conversions, this function should restrict itself to field names
     that exist in format 0 and those fields should exist in the same place
     in all formats.

Formats
     This is a reference to an array of references to formats.

   For example:

     my $cvt = new Data::FixedFormat {
         Chooser => sub { $_[0]->{RecordType} eq '0' ? 1 : 2 },
     	Format => [ [ 'RecordType:A1' ],
     		    [ 'RecordType:A1', 'FieldA:A6', 'FieldB:A4:4' ],
     		    [ 'RecordType:A1', 'FieldC:A4', 'FieldD:A18' ] ]
         };
     my $rec0 = $cvt->unformat("0FieldAB[0]B[1]B[2]B[3]");
     my $rec1 = $cvt->unformat("1FldC<-----FieldD----->");

   Each Data::FixedFormat instance also contains the following attributes:

Names
     Names contains a list of lists of field names indexed as [record
     variant, field number].  For example, to find the third field name in
     a non-variant record, use `$cvt-'{Names}[0][2]>.

Count
     Count contains a list of list of occurrence counts.  This is used to
     indicate which fields contain arrays.

Format
     Format contains a list of template strings for the Perl pack and
     unpack functions.

AUTHOR
======

   Data::FixedFormat was written by Thomas Pfau <pfau@eclipse.net>
http://www.eclipse.net/~pfau/.

COPYRIGHT
=========

   Copyright (C) 2000 Thomas Pfau.  All rights reserved.

   This module 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 library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
License for more details.

   You should have received a copy of the GNU General Public License along
with this progam; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.

Perl extension for simple-minded recipe-controlled build of data.
*****************************************************************

NAME
====

   Data::Flow - Perl extension for simple-minded recipe-controlled build
of data.

SYNOPSIS
========

     use Data::Flow;
     $recipes = { path  => { default => './MANIFEST'},
     	       contents => { prerequisites => ['path', 'x'] ,
     			     process =>
     			     sub {
     			       my $data = shift;
     			       $data->{ shift() } = `cat $data->get('path')`
     				 x $data->get('x');
     			     }
     			   },
     	     };

     $request = new Data::Flow $recipes;
     $request->set( x => 1);
     print $request->get('contents');

     tie %request, Data::Flow, $recipes;
     $request{x} = 1;
     print $request{contents};

DESCRIPTION
===========

   The module Data::Flow provides its services via objects. The objects may
be obtained by the usual

     $request = new Data::Flow $recipes;

   paradigm. The argument $recipes is a hash reference, which provides the
rules for request processing. The objects support two methods, set() and
get(). The first one is used to provide input data for processing, the
second one to obtain the output.

   The unit of requested information is a field. The method set() takes a
pair `field => value', the method get() takes one argument: the field.

   Every object is created without any fields filled, but it knows how to
*construct* fields basing on other fields or some global into. This
knowledge is provided in the argument $recipe of the new() function. This
is a reference to a hash, keyed by fields. The values of this hash are
hash references themselves, which describe how to acquire the field which
is the corresponding key of the initial hash.

   The internal hashes may have the following keys:

default
     describes the default value for the key, if none is provided by
     set(). The value becomes the value of the field of the object. No
     additional processing is performed. Example:

          default => $Config{installdir}

`prerequisites'
     gives the fields which are needed for the construction of the given
     field. The corresponding value is an array references. The array
     contains the required fields.

     If defaults did not satisfy the request for a field, but
     `$recipe->{field}{prerequisites}' exists, the required fields are
     build before any further processing is done. Example:

          prerequisites => [ qw(prefix arch) ]

process
     contains the rule to build the field. The value is a reference to a
     subroutine taking 2 arguments: the object $request, and the name of
     the required field. It is up to the subroutine to actually fill the
     corresponding field of $data, an error condition is raised if it did
     not. Example:

          process => sub { my $data = shift;
          		   $data->set( time => localtime(time) ) }

output
     the corresponing value has the same meaning as for process, but the
     return value of the subroutine is used as the value of the field.
     Example:

          output => sub { localtime(time) }

filter
     contains the rule to build the field basing on other fields. The value
     is a reference to an array. The first element of the array is a
     reference to a subroutine, the rest contains names of the fields. When
     the subroutine is called, the arguments are the values of fields of
     the object $request which appear in the array (in the same order). The
     return value of the subroutine is used as the value of the field.
     Example:

          filter => [ sub { shift + shift },
          	      'first_half', 'second_half' ]

     Note that the mentioned field will be automatically marked as
     prerequisites.

`class_filter'
     is similar to filter, but the first argument is the name of the
     method to call, second one is the name of the package to use for the
     method invocation. The rest contains names of field to provide as
     method arguments. Example:

          class_filter => [ 'new', 'FileHandle', 'filename' ]

`method_filter'
     is similar to `class_filter', but the second argument is the name of
     the field which is used to call the method upon. Example:

          method_filter => [ 'show', 'widget_name', 'current_display' ]

Tied interface
--------------

   The access to the same functionality is available via tied hash
interface.

AUTHOR
======

   Ilya Zakharevich, ilya@math.ohio-state.edu

SEE ALSO
========

   perl(1), make(1).

support for deeply nested structures
************************************

NAME
====

   Data::Grove - support for deeply nested structures

SYNOPSIS
========

     use Data::Grove;

     $object = MyPackage->new;

     package MyPackage;
     @ISA = qw{Data::Grove};

DESCRIPTION
===========

   `Data::Grove' provides support for deeply nested tree or graph
structures.  `Data::Grove' is intended primarily for Perl module authors
writing modules with many types or classes of objects that need to be
manipulated and extended in a consistent and flexible way.

   `Data::Grove' is best used by creating a core set of "data" classes and
then incrementally adding functionality to the core data classes by using
"extension" modules.  One reason for this design is so that the data
classes can be swapped out and the extension modules can work with new
data sources.  For example, these other data sources could be disk-based,
network-based or built on top of a relational database.

   Two extension modules that come with `Data::Grove' are
`Data::Grove::Parent' and `Data::Grove::Visitor'.  `Data::Grove::Parent'
adds a `Parent' property to grove objects and implements a `root' method
to grove objects to return the root node of the tree from anywhere in the
tree and a ``rootpath'' method to return a list of nodes between the root
node and "this" node.  `Data::Grove::Visitor' adds callback methods
`accept' and ``accept_name'' that call your handler or receiver module
back by object type name or the object's name.

   `Data::Grove' objects do not contain parent references, Perl garbage
collection will delete them when no longer referenced and sub-structures
can be shared among several structures.  `Data::Grove::Parent' is used to
create temporary objects with parent pointers.

   Properties of data classes are accessed directly using Perl's hash
functions (i.e. ``$object->{Property}'').  Extension modules may also
define properties that they support or use, for example
Data::Grove::Parent adds `Parent' and `Raw' properties and Visitor depends
on `Name' and `Content' properties.

   See the module XML::Grove for an example implementation of
`Data::Grove'.

METHODS
=======

new( PROPERTIES )
     Return a new object blessed into the SubClass, with the given
     properties.  PROPERTIES may either be a list of key/value pairs, a
     single hash containing key/value pairs, or an existing `Data::Grove'
     object.  If an existing `Data::Grove' is passed to `new()', a shallow
     copy of that object will be returned.  A shallow copy means that you
     are returned a new object, but all of the objects underneath still
     refer to the original objects.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1)

provide parent properties to Data::Grove objects
************************************************

NAME
====

   Data::Grove::Parent - provide parent properties to Data::Grove objects

SYNOPSIS
========

     use Data::Grove::Parent;

     $root = $object->root;
     $rootpath = $object->rootpath;
     $tied = $object->add_magic([ $parent ]);

     $node = Data::Grove::Parent->new($hash [, $parent]);
     $node_list = Data::Grove::ParentList->new($array [, $parent]);

DESCRIPTION
===========

   Data::Grove::Parent is an extension to Data::Grove that adds `Parent'
and `Raw' properties to Data::Grove objects and methods for returning the
root node of a grove, a list of nodes between and including the root node
and the current node, and a method that creates parented nodes.

   Data::Grove::Parent works by creating a Perl "tied" object that
contains a parent reference (`Parent') and a reference to the original
Data::Grove object (`Raw').  Tying-magic is used so that every time you
reference the Data::Grove::Parent object it actually references the
underlying raw object.

   When you retrieve a list or a property of the Raw object,
Data::Grove::Parent automatically adds magic to the returned list or node.
This means you only call `add_magic()' once to create the first
Data::Grove::Parent object and then use the grove objects like you
normally would.

   The most obvious use of this is so you don't have to call a `delete'
method when you want to release a grove or part of a grove; since
Data::Grove and Data::Grove::Parent objects have no cyclic references,
Perl can garbage collect them normally.

   A secondary use is to allow you to reuse grove or property set
fragments in multiple trees.  WARNING: Data::Grove currently does not
protect you from creating your *own* cyclic references!  This could lead
to infinite loops if you don't take care to avoid them.

METHODS
=======

$object->root()
$object->rootpath()
     `root()' returns the root node if `$object' is a
     ``Data::Grove::Parent'' object.  ``rootpath()'' returns an array of
     all the nodes between and including the root node and `$object'.

$tied = $object->add_magic([ $parent ])
     ``add_magic()'' returns a `Data::Grove::Parent' object with `$object'
     as it's `Raw' object.  If ``$parent'' is given, that becomes the tied
     object's parent object.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), Data::Grove(3)

add visitor/callback methods to Data::Grove objects
***************************************************

NAME
====

   Data::Grove::Visitor - add visitor/callback methods to Data::Grove
objects

SYNOPSIS
========

     use Data::Grove::Visitor;

     @results = $object->accept ($visitor, ...);
     @results = $object->accept_name ($visitor, ...);
     @results = $object->children_accept ($visitor, ...);
     @results = $object->children_accept_name ($visitor, ...);

DESCRIPTION
===========

   Data::Grove::Visitor adds visitor methods (callbacks) to Data::Grove
objects.  A "visitor" is a class (a package) you write that has methods
(subs) corresponding to the objects in the classes being visited.  You use
the visitor methods by creating an instance of your visitor class, and
then calling ``accept($my_visitor)'' on the top-most object you want to
visit, that object will in turn call your visitor back with
``visit_*OBJECT*'', where OBJECT is the type of object.

   There are several forms of `accept'.  Simply calling `accept' calls
your package back using the object type of the object you are visiting.
Calling ``accept_name'' on an element object calls you back with
``visit_name_*NAME*'' where NAME is the tag name of the element, on all
other objects it's as if you called `accept'.

   All of the forms of `accept' return a concatenated list of the result
of all `visit' methods.

   ``children_accept'' calls `accept' on each of the children of the
element.  This is generally used in element callbacks to recurse down into
the element's children, you don't need to get the element's contents and
call `accept' on each item.  ``children_accept_name'' does the same but
calling ``accept_name'' on each of the children.  ``attr_accept'' calls
`accept' on each of the objects in the named attribute.

   Refer to the documentation of the classes you are visiting (XML::Grove,
etc.) for the type names (``element'', ``document'', etc.) of the objects
it implements.

RESERVED NAMES
==============

   The hash keys `Contents' and `Name' are used to indicate objects with
children (for ``children_accept'') and named objects (for ``accept_name'').

NOTES
=====

   These are random ideas that haven't been implemented yet:

   * Several objects fall into subclasses, or you may want to be able to
     subclass a visited object and still be able to tell the difference.
     In SGML::Grove I had used the package name in the callback
     (``visit_SGML_Element'') instead of a generic name
     (``visit_element'').  The idea here would be to try calling
     ``visit_*PACKAGE*'' with the most specific class first, then try
     superclasses, and lastly to try the generic.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), Data::Grove

   Extensible Markup Language (XML) <http://www.w3c.org/XML>

Hexadecial Dumper
*****************

NAME
====

   Data::HexDump - Hexadecial Dumper

SYNOPSIS
========

     use Data::HexDump;

     my $buf = "foo\0bar";
     print HexDump $buf;

     or

     my $f = new Data::HexDump;
     $f->data($buf);
     print $f->dump;

     or

     my $fh = new FileHandle $file2dump;
     my $f = new Data::HexDump;
     $f->fh($fh);
     $f->block_size(1024);
     print while $_ = $f->dump;
     close $fh;

     or

     my $f = new Data::HexDump;
     $f->file($file2dump);
     $f->block_size(1024);
     print while $_ = $f->dump;

DESCRIPTION
===========

   Dump in hexadecimal the content of a scalar. The result is returned in a
string. Each line of the result consists of the offset in the source in
the leftmost column of each line, followed by one or more columns of data
from the source in hexadecimal. The rightmost column of each line shows
the printable characters (all others are shown as single dots).

COPYRIGHT
=========

   Copyright (c) 1998-1999 Fabien Tassin. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

AUTHOR
======

   Fabien Tassin <fta@oleane.net>

VERSION
=======

   0.02 - Second release (September 1999)

SEE ALSO
========

   perl(1)

A module for displaying binary data in a readable format
********************************************************

NAME
====

   Hexdumper - A module for displaying binary data in a readable format

SYNOPSIS
========

   use Data::Hexdumper; Data::Hexdumper::dump(     data => $data,
# what to dump     number_format => 'S',   # display as unsigned 'shorts'
  start_position => 100,  # start at this offset ...      end_position =>
148     # ... and end at this offset );

DESCRIPTION
===========

   `Data::Hexdumper' provides a simple way to format and display arbitary
binary data in a way similar to how some debuggers do for lesser languages.
It gives the programmer a considerable degree of flexibility in how the
data is formatted, with sensible defaults.  It is envisaged that it will
primarily be of use for those wrestling alligators in the swamp of binary
file formats, which is why it was written in the first place.

   `Data::Hexdumper' provides the following subroutine:

Hexdump
     Does everything :-)  Takes a hash of parameters, one of which is
     mandatory, the rest having sensible defaults if not specified.
     Available parameters are:

    data
          A scalar containing the binary data we're interested in.  This is
          mandatory.

    start_position
          An integer telling us where in data to start dumping.  Defaults
          to the beginning of data.

    end_position
          An integer telling us where in data to stop dumping.  Defaults
          to the end of data.

    number_format
          A character specifying how to format the data.  This tells us
          whether the data consists of bytes, shorts (16-bit values),
          longs (32-bit values), and whether they are big- or
          little-endian.  The permissible values are C, S, n, v, L, N, and
          V, having exactly the same meanings as they do in unpack.  It
          defaults to 'C'.

SEE ALSO
========

   See Data/Dumper,

   See Data/HexDump, if your needs are simple

   perldoc -f unpack

   perldoc -f pack

BUGS
====

   If displaying data in 'short' or 'long' formats, the last element
displayed may be screwed up if it does not end on the boundary of a short
or a long - eg, if you try to display 39 bytes as longs.

AUTHOR
======

   David Cantrell (david@cantrell.org.uk).

HISTORY
=======

Version 0.01
     Original version.

Perl extension for dumping structures into JavaScript code
**********************************************************

NAME
====

   Data::JavaScript - Perl extension for dumping structures into JavaScript
code

SYNOPSIS
========

     use Data::JavaScript;

     @code = jsdump($array_ref, 'my_array');
     $code = jsdump($hash_ref, 'my_object');
     $code = hjsdump($array_ref B<or> $hash_ref, 'my_stuff');

DESCRIPTION
===========

   This module is aimed mainly for CGI programming, when a perl script
generates a page with client side JavaScript code that needs access to
structures created on the server.

   It works by creating one line of JavaScript code per datum. Therefore,
structures cannot be created anonymously and needed to be assigned to
variables. This enables dumping big structures.

   The first arguement is a hashref or arrayref. Structures can be nested,
circular referrencing is supported EXPERIMENTALLY only.  The second
argument is the name of JavaScript object to create.

   hsdump also dumps HTML tags to embed the scriplet inside an HTML page.

   When called in array context, the functions return an array of code
lines. When called in scalar context, it returns one chunk of lines
delimited by line fields.

AUTHOR
======

   Ariel Brosh, schop@cpan.org. Inspired by WDDX.pm JavaScript support.

SEE ALSO
========

   perl(1), see WDDX.

Perl package to provide lightweight data dumping
************************************************

NAME
====

   Data::JavaScript::LiteObject - Perl package to provide lightweight data
dumping

SYNOPSIS
========

     use Data::JavaScript:LiteObject;

     jsodump("user", \%users);

DESCRIPTION
===========

   This module was inspired by Data/JavaScript,
which while incredibly versatile, seems rather brute force and inelegant
for certain forms of data. Specifically a series of objects of the same
class, which it seems is a likely use for this kind of feature. So this
module was created to provide a lightweight means of producing
configurable, clean and compact output.

   *LiteObject* is used to format and output an array or hash of objects;
that is hash references. The referenced hashes may contain values that are
scalars, or references to arrays containing scalars.

   *LiteObject* contains one function; jsodump; which takes a list of named
parameters. Two of which are required, the rest being optional.

Required parameters
-------------------

`protoName'
     The name to be used for the prototype object function.

`dataRef'
     A reference to an array or hash of hashes to dump.

Optional parameters
-------------------

attributes
     A reference to an array containing a list of the object attributes
     (hash keys). This is useful if every object does not necessarily
     posses a value for each attributes; exists fails. e.g.

          %A = (a=>1, z=>26);
          %B = (b=>2, y=>25);

          jsodump("example", \(%A, %B), \('a', 'b', 'y', 'z'));

     This could also be used to explicitly prevent certain data from being
     dumped.

explode
     The default; false; produces output with one object per line.  If
     true, the output is one *attribute* per line.

`lineIN'
     If true, output is numbered every 5 lines. The value provided should
     be the number of lines printed before this output.  For example if a
     CGI script included:

          C<print q(<html>
          	    <head>
          	    <title>Pthbb!!</title>
          	    <script language=javascript>);>
          jsdump(protoName=>"object", dataRef=>\@objects, lineIN=>4);

     The client might see:

          <html>
          <head>
          <title>Pthbb!!</title>
          <script language=javascript>
          // 5
          function object (x, y, z) {
                  this.x = x; this.y = y; this.z = z; }
          object0 = new object(1, 0, 0 );
          object1 = new object(0, 1, 0 );
          // 10
          object2 = new object(0, 0, 1 );

     making it easier to read and/or debug.

`lineOUT'
     A scalar reference. jsodump will set it's value to the number of the
     last line of numbered output produced when lineIN is specified. This
     way you may pass the scalar to a subsequent call to jsdump as the
     value of lineIn for continuous numbering.  For example:

          C<jsdump(protoName=>"object", dataRef=>\@objects, lineIN=>4, lineOUT=>\$.);>

          ...

          C<jsdump(protoName=>"object", dataRef=>\@objects, lineIN=>$.);>

`listObjects'
     If true, the parameters value is used as the name of an array to be
     output contaning a list of all the objects dumped. This way, your
     client side code need not know as much about the data, but simply to
     traverse an array of your choosing.

     For example:

          C<jsdump(protoName=>"object", dataRef=>\@objects, listObjects=>"objects");>

     would return

          objects = new Array('object0', 'object1', 'object2');

CAVEATS
=======

   All of the objects in a given hash or array reference should contain
the same keys. Explicit undefined values should be used for instances of
an object that do not posess a certain value.  For example:

     C<%hash0 = (alpha=>undef, beta=>1);>
     C<%hash1 = (beta=>1);>

   %hash0 is safe, since exists($hash0{alpha}) is true.  However
exists($hash1{alpha}) is false, and %hash1 would cause problems.

   Deep structures are not dumped. That is anything beyond a scalar or a
scalar within an Array as an attribute value. It is not entirely clear
that it's necessary, but if you require it `SEE ALSO' in this node

BUGS
====

   Nothing that am I aware of.

SEE ALSO
========

   See Data/JavaScript,

AUTHOR
======

   Jerrad Pierce *belg4mit@mit.edu*, *webmaster@pthbb.org*.
`http://pthbb.org/'

magic insertion points in your data
***********************************

NAME
====

   Data::Locations - magic insertion points in your data

PREFACE
=======

   Did you already encounter the problem that you had to produce some data
in a particular order, but that some piece of the data was still
unavailable at the point in the sequence where it belonged and where it
should have been produced?

   Did you also have to resort to cumbersome and tedious measures such as
storing the first and the last part of your data separately, then
producing the missing middle part, and finally putting it all together?

   In this simple case, involving only one deferred insertion, you might
still put up with this solution.

   But if there is more than one deferred insertion, requiring the handling
of many fragments of data, you will probably get annoyed and frustrated.

   You might even have to struggle with limitations of the file system of
your operating system, or handling so many files might considerably slow
down your application due to excessive file input/output.

   And if you don't know exactly beforehand how many deferred insertions
there will be (if this depends dynamically on the data being processed),
and/or if the pieces of data you need to insert need additional (nested)
insertions themselves, things will get really tricky, messy and
troublesome.

   In such a case you might wonder if there wasn't an elegant solution to
this problem.

   This is where the "`Data::Locations'" module comes in: It handles such
insertion points automatically for you, no matter how many and how deeply
nested, purely in memory, requiring no (inherently slower) file
input/output operations.

   (The underlying operating system will automatically take care if the
amount of data becomes too large to be handled fully in memory, though, by
swapping out unneeded parts.)

   Moreover, it also allows you to insert the same fragment of data into
SEVERAL different places.

   This increases space efficiency because the same data is stored in
memory only once, but used multiple times.

   Potential infinite recursion loops are detected automatically and
refused.

   In order to better understand the underlying concept, think of
"`Data::Locations'" as virtual files with almost random access: You can
write data to them, you can say "reserve some space here which I will fill
in later", and continue writing data.

   And you can of course also read from these virtual files, at any time,
in order to see the data that a given virtual file currently contains.

   When you are finished filling in all the different parts of your virtual
file, you can write out its contents in flattened form to a physical, real
file this time, or process it otherwise (purely in memory, if you wish).

   You can also think of "`Data::Locations'" as bubbles and bubbles inside
of other bubbles. You can inflate these bubbles in any arbitrary order you
like through a straw (i.e., the bubble's object reference).

   Note that this module handles your data completely transparently, which
means that you can use it equally well for text AND binary data.

   You might also be interested in knowing that this module and its concept
have already been heavily used in the automatic code generation of large
software projects.

SYNOPSIS
========

     use Data::Locations;

     new
         $toplocation = Data::Locations->new();
         $toplocation = Data::Locations->new($filename);
         $sublocation = $location->new();
         $sublocation = $location->new($filename);

     filename
         $location->filename($filename);
         $filename = $location->filename();
         $oldfilename = $location->filename($newfilename);

     toplevel
         $flag = $location->toplevel();

     print
         $location->print(@items);
         print $location @items;

     printf
         $location->printf($format, @items);
         printf $location $format, @items;

     println
         $location->println(@items);

     read
         $item = $location->read();
         $item = <$location>;
         @list = $location->read();
         @list = <$location>;

     reset
         $location->reset();

     traverse
         $location->traverse(\&callback_function);

     dump
         $ok = $location->dump();
         $ok = $location->dump($filename);

     delete
         $location->delete();

     tie
         $location->tie('FILEHANDLE');
         $location->tie(*FILEHANDLE);
         $location->tie(\*FILEHANDLE);
         $location->tie(*{FILEHANDLE});
         $location->tie(\*{FILEHANDLE});
         $location->tie($filehandle);
         tie(  *FILEHANDLE,  "Data::Locations", $location);
         tie(*{$filehandle}, "Data::Locations", $location);

     tied
         $location = tied   *FILEHANDLE;
         $location = tied *{$filehandle};

     untie
         untie   *FILEHANDLE;
         untie *{$filehandle};

     select
         $filehandle = select();
         select($location);
         $oldfilehandle = select($newlocation);

IMPORTANT NOTES
===============

  1. Although "`Data::Locations'" behave like normal Perl file handles in
     most circumstances, opening a location with "open()" should be
     avoided: The corresponding file or pipe will actually be created, but
     subsequently data will nevertheless be sent to (and read from) the
     given location instead.

     There is also no need to switch from read to write mode (or
     vice-versa), since locations are ALWAYS open BOTH for reading AND
     writing.

     If you want to rewind a location to start reading at the beginning
     again (usually achieved by closing and re-opening a file), use the
     method "reset()" instead (see farther below for a description).

     Likewise, closing a location with "close()" will have no other effect
     than to produce a warning message (under Perl 5.005 and if the "-w"
     switch is set) saying "operation ignored", and should therefore be
     avoided, too.

  2. "`Data::Locations'" are rather delicate objects; they are valid Perl
     file handles AS WELL AS valid Perl objects AT THE SAME TIME.

     As a consequence, *YOU CANNOT INHERIT* from the "`Data::Locations'"
     class, i.e., it is NOT possible to create a derived class or subclass
     of the "`Data::Locations'" class!

     Trying to do so will cause many severe malfunctions, most of which
     will not be apparent immediately.

     Chances are also great that by adding new attributes to a
     "`Data::Locations'" object you will clobber its (quite tricky) data
     structure.

     Therefore, use embedding and delegation instead, rather than
     inheritance, as shown below:

          package My::Class;
          use Data::Locations;
          use Carp;

          sub new
          {
              my($self) = shift;
              my($location,$object);
              if (ref($self)) { $location = $self->{'delegate'}->new(); }
              else            { $location =     Data::Locations->new(); }
              $object =
                  {
                      'delegate'   => $location,
                      'attribute1' => $whatever,  ##  add your own
                      'attribute2' => $whatelse
                  };
              bless($object, ref($self) || $self || __PACKAGE__);
          }

          sub AUTOLOAD
          {
              my($i,@args);
              $AUTOLOAD =~ s/^.*:://;
              return if ($AUTOLOAD eq 'DESTROY');
              $AUTOLOAD = 'Data::Locations::' . $AUTOLOAD;
              if (defined &$AUTOLOAD)
              {
                  for ( $i = 0; $i < @_; $i++ )
                  {
                      if (ref($_[$i]) eq __PACKAGE__)
                      {
                          $args[$i] = $_[$i]->{'delegate'};
                      }
                      else
                      {
                          $args[$i] = $_[$i];
                      }
                  }
                  @_ = @args;
                  goto &$AUTOLOAD;
              }
              else
              {
                  croak("$AUTOLOAD(): no such method");
              }
          }

          1;

     Note that using this scheme, all methods available for
     "`Data::Locations'" objects are also (automatically and directly)
     available for "`My::Class'" objects, i.e.,

          use My::Class;
          $obj = My::Class->new();
          $obj->filename('test.txt');
          $obj->print("This is ");
          $sub = $obj->new();
          $obj->print("information.");
          @items = $obj->read();
          print "<", join('|', @items), ">\n";
          $sub->print("an additional piece of ");
          $obj->reset();
          @items = $obj->read();
          print "<", join('|', @items), ">\n";
          $obj->dump();

     will work as expected (unless you redefine these methods in
     "`My::Class'").

     Moreover, with this scheme, you are free to add new methods and/or
     attributes as you please.

     The class "`My::Class'" can also be subclassed without any
     restrictions.

     However, "`My::Class'" objects are NOT valid Perl file handles;
     therefore, they cannot be used as such in combination with Perl's
     built-in operators for file access.

DESCRIPTION
===========

   * `use Data::Locations;'

     Enables the use of locations in your program.

   * `$toplocation = Data::Locations->new();'

     The CLASS METHOD "new()" creates a new top-level location.

     A "top-level" location is a location which isn't embedded (nested) in
     any other location.

     Note that CLASS METHODS are invoked using the NAME of their respective
     class, i.e., "`Data::Locations'" in this case, in contrast to OBJECT
     METHODS which are invoked using an OBJECT REFERENCE such as returned
     by the class's object constructor method (which "new()" happens to
     be).

     Any location that you intend to dump to a file later on in your
     program needs to have a filename associated with it, which you can
     either specify using the "new()" method (where you can optionally
     supply a filename, as shown below), or by setting this filename using
     the method "filename()" (see further below), or by specifying an
     explicit filename when invoking the "dump()" method itself (see also
     further below).

   * `$toplocation = Data::Locations->new($filename);'

     This variant of the CLASS METHOD "new()" creates a new top-level
     location (where "top-level" means a location which isn't embedded in
     any other location) and assigns a default filename to it.

     Note that this filename is simply passed through to the Perl "open()"
     function later on (which is called internally when you dump your
     locations to a file), which means that any legal Perl filename may be
     used such as ">-" (for writing to STDOUT) and "| more", to give you
     just two of the more exotic examples.

     See the section on "open()" in `perlfunc(1)' in this node for more
     details.

   * `$sublocation = $location->new();'

     The OBJECT METHOD "new()" creates a new location which is embedded in
     the given location "`$location'" at the current position (defined by
     what has been printed to the embedding location till this moment).

     Such a nested location usually does not need a filename associated
     with it (because it will be dumped to the same file as the location
     in which it is embedded anyway), unless you want to additionally dump
     this location to a file of its own.

     In the latter case use the variant of the "new()" method shown
     immediately below, or the method "filename()" (see below) to set this
     filename, or call the method "dump()" (described further below) with
     an appropriate filename argument.

   * `$sublocation = $location->new($filename);'

     This variant of the OBJECT METHOD "new()" creates a new location
     which is embedded in the given location "`$location'" at the current
     position (defined by what has been printed to the embedding location
     till this moment) and assigns a default filename to it.

     See the section on "open()" in `perlfunc(1)' in this node for details
     about the exact syntax of Perl filenames (this includes opening pipes
     to other programs as a very interesting and useful application, for
     instance).

   * `$oldfilename = $location->filename($newfilename);'

     If the optional parameter is given, this method stores its argument as
     the default filename along with the given location.

     This filename also serves as an auto-dump flag. If it is set to a
     non-empty string, auto-dumping (i.e., an automatic call of the
     "dump()" method) occurs when your last reference of the location in
     question goes out of scope, or at shutdown time of your script
     (whichever comes first). See also the description of the "dump()"
     method further below for more details.

     When a location is auto-dumped, its associated filename is used as the
     filename of the file into which the location's contents are dumped.

     This method returns the filename that was associated with the given
     location before this method call (i.e., the filename given to the
     "new()" method or to a previous call of this method), or the empty
     string if there was no filename associated with the given location.

   * `$flag = $location->toplevel();'

     Use this method to check wether the given location is a "top-level"
     location, i.e., if the given location is NOT embedded in any other
     location.

     Note that locations created by the CLASS METHOD "new()" all start
     their life-cycle as top-level locations, whereas locations which are
     embedded in some other location by using the OBJECT METHOD "new()"
     (or the method "print()"; see further below for details) are NOT, by
     definition, top-level locations.

     Whenever a top-level location is embedded in another location (using
     the method "print()" - see further below for more details), it
     automatically loses its "top-level" status.

     When you throw away the contents of a location (using the method
     "delete()" - see further below for details), however, the locations
     that may have been embedded in the deleted location can become
     "orphans" which have no "parents" anymore, i.e., they may not be
     embedded in any other location anymore. These "orphan" locations will
     automatically become "top-level" locations.

     The method returns "true" ("1") if the given location is a top-level
     location, and "false" ("0") otherwise.

   * `$location->print(@items);'

     This method prints the given list of arguments to the indicated
     location, i.e., appends the given items to the given location.

     IMPORTANT FEATURE:

     Note that you can EMBED any given location IN MORE THAN ONE
     surrounding location using this method!

     Simply use a statement similar to this one:

          $location->print($sublocation);

     This embeds location "`$sublocation'" in location "`$location'" at
     the current position (defined by what has been printed to location
     "`$location'" till this moment).

     (Note that the name "`$sublocation'" above only refers to the fact
     that this location is going to be embedded in the location
     "`$location'".  "`$sublocation'" may actually be ANY location you
     like, even a top-level location. Note though that a top-level
     location will automatically lose its "top-level" status by doing so.)

     This is especially useful if you are generating data once in your
     program which you need to include at several places in your output.

     This saves a lot of memory because only a reference of the embedded
     location is stored in every embedding location, instead of all the
     data, which is stored in memory only once.

     Note that other references than "Data::Locations" object references
     are illegal, trying to "print" such a reference to a location will
     result in a warning message (if the "-w" switch is set) and the
     reference in question will simply be ignored.

     Note also that potential infinite recursions (which would occur when a
     given location contained itself, directly or indirectly) are detected
     automatically and refused (with an appropriate error message and
     program abortion).

     Because of the necessity for this check, it is more efficient to embed
     locations using the object method "new()", where possible, rather
     than with this mechanism, because embedding an empty new location (as
     with "new()") is always possible without checking.

     Remember that in order to minimize the number of "print()" method
     calls in your program (remember that lazyness is a programmer's
     virtue! `;-)') you can always use the "here-document" syntax:

          $location->print(<<"VERBATIM");
          Article: $article
            Price: $price
            Stock: $stock
          VERBATIM

     Remember also that the type of quotes (single/double) around the
     terminating string ("VERBATIM" in this example) determines wether
     variables inside the given text will be interpolated or not!  (See
     `perldata(1)' in this node for more details.)

   * `print $location @items;'

     Note that you can also use Perl's built-in operator "print" to print
     data to a given location.

   * `$location->printf($format, @items);'

     This method is an analogue of the Perl (and C library) function
     "printf()".

     See the section on "printf()" in `perlfunc(1)' in this node and
     `printf(3)' in this node (or `sprintf(3)' in this node) on your
     system for a description.

   * `printf $location $format, @items;'

     Note that you can also use Perl's built-in operator "printf" to print
     data to a given location.

   * `$location->println(@items);'

     This is (in principle) the same method as the "print()" method
     described further above, except that it always appends a "newline"
     character ("\n") to the list of items being printed to the given
     location.

     Note that this newline character is NOT appended to (i.e.,
     concatenated with) the last item of the given list of items, but that
     it is rather stored as an item of its own.

     This is mainly because the last item of the given list could be a
     reference (of another location), and also to make sure that the data
     (which could be binary data) being stored in the given location is
     not altered (i.e., falsified) in any way.

     This also allows the given list of items to be empty (in that case,
     there wouldn't be a "last item" anyway to which the newline character
     could be appended).

   * `$item = $location->read();'

     In "scalar" context, the method "read()" returns the next item of
     data from the given location.

     If that item happens to have the value "undef", this method returns
     the empty string instead.

     If you have never read from this particular location before, "read()"
     will automatically start reading at the beginning of the given
     location.

     Otherwise each call of "read()" will return successive items from the
     given location, thereby traversing the given location recursively
     through all embedded locations (which it may or may not contain), thus
     returning the contents of the given location (and any locations
     embedded therein) in a "flattened" way.

     To start reading at the beginning of the given location again, invoke
     the method "reset()" (see a little further below for its description)
     on that location.

     The method returns "undef" when there is no more data to read.

     Calling "read()" again thereafter will simply continue to return
     "undef", even if you print some more data to the given location in
     the meantime.

     However, if you have read the last item from the given location, but
     you haven't got the "undef" return value yet, it is possible to print
     more data to the location in question and to subsequently continue to
     read this new data.

     Remember to use "reset()" if you want to read data from the beginning
     of the given location again.

     Finally, note that you can read from two (or any number of) different
     locations at the same time, even if any of them is embedded (directly
     or indirectly) in any other of the locations you are currently reading
     from, without any interference.

     This is because the state information associated with each "read()"
     operation is stored along with the (given) location for which the
     "read()" method has been called, and NOT with the locations the
     "read()" visits during its recursive descent.

   * `$item = <$location>;'

     Note that you can also use Perl's diamond operator syntax ("`<>'") in
     order to read data from the given location.

     BEWARE that unlike reading from a file, reading from a location in
     this manner will return the items that have been stored in the given
     location in EXACTLY the same way as they have been written previously
     to that location, i.e., the data is NOT read back line by line, with
     "\n" as the line separator, but item by item, whatever these items
     are!

     (Note that you can also store binary data in locations, which will
     likewise be read back in exactly the same way as it has been stored
     previously.)

   * `@list = $location->read();'

     In "array" or "list" context, the method "read()" returns the rest of
     the contents of the given location, starting where the last "read()"
     left off, or from the beginning of the given location if you never
     read from this particular location before or if you called the method
     "reset()" (see a little further below for its description) for this
     location just before calling "read()".

     The method returns a single (possibly very long!) list containing all
     the items of data the given location and all of its embedded
     locations (if any) contain - in other words, the data contained in
     all these nested locations is returned in a "flattened" way (in
     "infix" order, for the mathematically inclined).

     If any of the items in the list happens to have the value "undef", it
     is replaced by an empty string.

     The method returns an empty list if the given location is empty or if
     a previous "read()" read past the end of the data in the given
     location.

     Remember to use "reset()" whenever you want to be sure to read the
     contents of the given location from the very beginning!

     For an explanation of "scalar" versus "array" or "list" context, see
     the section on "Context" in `perldata(1)' in this node.

   * `@list = <$location>;'

     Note that you can also use Perl's diamond operator syntax ("`<>'") in
     order to read data from the given location.

     BEWARE that unlike reading from a file, reading from a location in
     this manner will return the list of items that have been stored in
     the given location in EXACTLY the same way as they have been written
     previously to that location, i.e., the data is NOT read back as a
     list of lines, with "\n" as the line separator, but as a list of
     items, whatever these items are!

     (Note that you can also store binary data in locations, which will
     likewise be read back in exactly the same way as it has been stored
     previously.)

   * `$location->reset();'

     The method "reset()" deletes the state information associated with
     the given location which is used by the "read()" method in order to
     determine the next item of data to be returned.

     After using "reset()" on a given location, any subsequent "read()" on
     the same location will start reading at the beginning of that
     location.

     This method has no other (side) effects whatsoever.

     The method does nothing if there is no state information associated
     with the given location, i.e., if the location has never been accessed
     before using the "read()" method or if "reset()" has already been
     called previously.

   * `$location->traverse(\&callback_function);'

     The method "traverse()" performs a recursive descent on the given
     location just as the methods "read()" and "dump()" do internally, but
     instead of immediately returning the items of data contained in the
     location or printing them to a file, this method calls the callback
     function you specify as a parameter once for each item stored in the
     location.

     Expect one parameter handed over to your callback function which
     consists of the next item of data contained in the given location (or
     the locations embedded therein).

     Note that unlike the "read()" method, items returned by this method
     which happen to have the value "undef" are NOT replaced by the empty
     string, i.e., the parameter your callback function receives might be
     undefined. You should therefore take appropriate measures in your
     callback function to handle this special case.

     Moreover, since callback functions can do a lot of unwanted things,
     use this method with precaution!

     Please refer to the "examples" section at the bottom of this document
     for an example of how to use this method.

     Using the method "traverse()" is actually an alternate way of reading
     back the contents of a given location (besides using the method
     "read()") completely in memory (i.e., without writing the contents of
     the given location to a file and reading that file back in).

     Note that the method "traverse()" is completely independent from the
     method "read()" and from the state information associated with the
     "read()" method (the one which can be reset to point to the beginning
     of the location using the method "reset()").

     This means that you can "traverse()" and "read()" (and "reset()") the
     same location at the same time without any interference.

   * `$ok = $location->dump();'

     The method "dump()" (without parameters) dumps the contents of the
     given location to its associated default file (whose filename must
     have been stored along with the given location previously using the
     method "new()" or "filename()").

     Note that a warning message will be printed (if the "-w" switch is
     set) if the location happens to lack a default filename and that the
     location will simply not be dumped to a file in that case. Moreover,
     the method returns "false" ("0") to indicate the failure.

     Should any other problem arise while attempting to dump the given
     location (for instance an invalid filename or an error while trying
     to open or close the specified file), a corresponding warning message
     will be printed to the screen (provided that the "-w" switch is set)
     and the method will also return "false" ("0").

     The method returns "true" ("1") if and only if the given location has
     been successfully written to its respective file.

     Note that a ">" is prepended to the default filename just before
     opening the file if the default filename does not begin with ">", "|"
     or "+" (leading white space is ignored).

     This does NOT change the filename which is stored along with the given
     location, however.

     Finally, note that this method does not affect the contents of the
     location being dumped.

     If you want to delete the contents of the given location once they
     have been dumped, call the method "delete()" (explained further below)
     thereafter.

     If you want to dump and immediately afterwards destroy a location, you
     don't need to call the method "dump()" explicitly. It suffices to
     store a filename along with the location in question using the method
     "new()" or "filename()" and then to make sure that all references to
     this location are destroyed (this happens for instance whenever the
     last "my" variable containing a reference to the location in question
     goes out of scope - provided there are no global variables containing
     references to the location in question).

     This will automatically cause the location to be dumped (by calling
     the "dump()" method internally) and then to be destroyed. (This
     feature is called "auto-dump".)

     Auto-dumping also occurs at shutdown time of your Perl script or
     program: All locations that have a non-empty filename associated with
     them will automatically be dumped (by calling the "dump()" method
     internally) before the global garbage collection (i.e., the
     destruction of all data variables) takes place.

     In order to prevent auto-dumping, just make sure that there is no
     filename associated with the location in question at the time when
     its last reference goes out of scope or at shutdown time.

     You can ensure this by calling the "filename()" method with an empty
     string ("") as argument.

   * `$ok = $location->dump($filename);'

     The method "dump()" (with a filename argument) in principle does
     exactly the same as the variant without arguments described
     immediately above, except that it temporarily overrides the default
     filename associated with the given location and that it uses the
     given filename instead.

     Note that the location's associated filename is just being temporarily
     overridden, BUT NOT CHANGED.

     I.e., if you call the method "dump()" again later without a filename
     argument, the filename stored along with the given location will be
     used, and not the filename specified here.

     Should any problem arise while attempting to dump the given location
     (for instance if the given filename is invalid or empty or if Perl is
     unable to open or close the specified file), a corresponding warning
     message will be printed to the screen (provided that the "-w" switch
     is set) and the method returns "false" ("0").

     The method returns "true" ("1") if and only if the given location has
     been successfully written to the specified file.

     (Note that if the given filename is empty or contains only white
     space, the method does NOT fall back to the filename previously
     stored along with the given location, because doing so could
     overwrite valuable data.)

     Note also that a ">" is prepended to the given filename if it does not
     begin with ">", "|" or "+" (leading white space is ignored).

     Finally, note that this method does not affect the contents of the
     location being dumped.

     If you want to delete the given location once it has been dumped, you
     need to call the method "delete()" (explained below) explicitly.

   * `$location->delete();'

     The method "delete()" deletes the CONTENTS of the given location -
     the location CONTINUES TO EXIST and REMAINS EMBEDDED where it was!

     The associated filename stored along with the given location is also
     NOT AFFECTED by this method.

     BEWARE that any locations which were previously embedded in the given
     location might go out of scope by invoking this method!

     Note that in order to actually DESTROY a location altogether it
     suffices to simply let the last reference to the location in question
     go out of scope, or to set the variable containing the last reference
     to a new value (e.g. `$ref = 0;').

   * `$location->tie('FILEHANDLE');'

   * `$location->tie(*FILEHANDLE);'

   * `$location->tie(\*FILEHANDLE);'

   * `$location->tie(*{FILEHANDLE});'

   * `$location->tie(\*{FILEHANDLE});'

     Although locations behave like file handles themselves, i.e., even
     though they allow you to use Perl's built-in operators "print",
     "printf" and the diamond operator "`<>'" in order to write data to and
     read data from them, it is sometimes desirable to be able to redirect
     the output which is sent to other file handles (such as STDOUT and
     STDERR, for example) to some location instead (rather than the
     screen, for instance).

     It may also be useful to be able to read data from a location via some
     other file handle (such as STDIN, for example, which allows you to
     "remote-control" a program which reads commands from standard input
     by redirecting STDIN and then spoon-feeding the program as desired).

     (Note that on the Windows NT/95 platform, tying is probably the only
     way of redirecting output sent to STDERR, since the command shell
     won't allow you to do so!)

     The method "tie()" (be careful not to confuse the METHOD "tie()" and
     the Perl built-in OPERATOR "tie"!) provides an easy way for doing
     this.

     Simply invoke the method "tie()" for the location which should be
     "tied" to a file handle, and provide either the name, a typeglob or a
     typeglob reference of the file handle in question as the (only)
     parameter to this method.

     After that, printing data to this file handle will actually send this
     data to its associated ("tied") location, and reading from this file
     handle will actually read the data from the tied location instead.

     Note that you don't need to explicitly "open()" or "close()" such a
     tied file handle in order to be able to access its associated location
     (regardless wether you want to read from or write to the location or
     both), even if this file handle has never been explicitly (or
     implicitly) opened (or even used) before.

     The physical file or terminal the tied file handle may have been
     connected to previously is simply put on hold, i.e., it is NOT written
     to or read from anymore, until you "untie" the connection between the
     file handle and the location (see further below for more details
     about "untie").

     Note also that if you do not "untie" the file handle before your
     program ends, Perl will try to close it for you, which under Perl
     5.005 will lead to a warning message (provided that the "-w" switch
     is set) saying that the attempted "close()" operation was ignored.
     This is because under Perl 5.005, a "close()" on a tied file handle
     is forwarded to the associated (i.e., tied) object instead.

     Under Perl 5.004, the behaviour of "close()" is different: When used
     on a location it is simply ignored (without any warning message), and
     a close on a tied file handle will close the underlying file or pipe
     (if there is one).

     Finally, note that you don't need to qualify the built-in file handles
     STDIN, STDOUT and STDERR, which are enforced by Perl to be in package
     "main", and file handles belonging to your own package, but that it
     causes no harm if you do (provided that you supply the correct
     package name).

     The only file handles you need to qualify are custom file handles
     belonging to packages other than the one in which the method "tie()"
     is called.

     Some examples:

          $location->tie('STDOUT');
          $location->tie('MYFILE');
          $location->tie('My::Class::FILE');
          $location->tie(*STDERR);
          $location->tie(\*main::TEMP);

     Please also refer to the example given at the bottom of this document
     for more details about tying file handles to locations (especially
     for STDERR).

     See `perlfunc(1)' in this node and `perltie(1)' in this node for more
     details about "tying" in general.

   * `$location->tie($filehandle);'

     Note that you can also tie file handles to locations which have been
     created by using the standard Perl modules "FileHandle" and
     "IO::File":

          use FileHandle;
          $fh = FileHandle->new();
          $location->tie($fh);

          use IO::File;
          $fh = IO::File->new();
          $location->tie($fh);

   * `tie(*FILEHANDLE, "Data::Locations", $location);'

   * `tie(*{$filehandle}, "Data::Locations", $location);'

     Finally, note that you are not forced to use the METHOD "tie()", and
     that you can of course also use the OPERATOR "tie" directly, as shown
     in the two examples above.

   * `$location = tied *FILEHANDLE;'

   * `$location = tied *{$filehandle};'

     The Perl operator "tied" can be used to get back a reference to the
     object the given file handle is "tied" to.

     This can be used to invoke methods for this object, as follows:

          (tied   *FILEHANDLE)->method();
          (tied *{$filehandle})->method();

     Note that "`tied *{$location}'" is identical with "`$location'"
     itself.

     See `perlfunc(1)' in this node and `perltie(1)' in this node for more
     details.

   * `untie *FILEHANDLE;'

   * `untie *{$filehandle};'

     The Perl operator "untie" is used to "cut" the magic connection
     between a file handle and its associated object.

     Note that a warning message such as

          untie attempted while 1 inner references still exist

     will be issued (provided the "-w" switch is set) whenever you try to
     "untie" a file handle from a location.

     To get rid of this warning message, use the following approach:

          {
              local($^W) = 0;     ##  Temporarily disable the "-w" switch
              untie *FILEHANDLE;
          }

     (Note the surrounding braces which limit the effect of disabling the
     "-w" switch.)

     See `perlfunc(1)' in this node and `perltie(1)' in this node for more
     details.

   * `$filehandle = select();'

   * `select($location);'

   * `$oldfilehandle = select($newlocation);'

     Remember that you can define the default output file handle using
     Perl's built-in function "select()".

     "print" and "printf" statements without explicit file handle (note
     that "`println'" ALWAYS needs an explicit location where to send its
     output to!) always send their output to the currently selected default
     file handle (which is usually "STDOUT").

     "select()" always returns the current default file handle and allows
     you to define a new default file handle at the same time.

     By selecting a location as the default file handle, all subsequent
     "print" and "printf" statements (without explicit file handle) will
     send their output to that location:

          select($location);
          print "Hello, World!\n";  ##  prints to "$location"

     See the section on "select()" in `perlfunc(1)' in this node for more
     details.

EXAMPLE #1
==========

     #!/sw/bin/perl -w

     use Data::Locations;

     use strict;
     no strict "vars";

     $head = Data::Locations->new();  ##  E.g. for interface definitions
     $body = Data::Locations->new();  ##  E.g. for implementation

     $head->filename("example.h");
     $body->filename("example.c");

     $common = $head->new();    ##  Embed a new location in "$head"
     $body->print($common);     ##  Embed this same location in "$body"

     ##  Create some more locations...

     $copyright = Data::Locations->new();
     $includes  = Data::Locations->new();
     $prototype = Data::Locations->new();

     ##  ...and embed them in location "$common":

     $common->print($copyright,$includes,$prototype);

     ##  Note that the above is just to show you an alternate
     ##  (but less efficient) way! Normally you would use:
     ##
     ##      $copyright = $common->new();
     ##      $includes  = $common->new();
     ##      $prototype = $common->new();

     $head->println(";");  ##  The final ";" after a function prototype
     $body->println();     ##  Just a newline after a function header

     $body->println("{");
     $body->println('    printf("Hello, world!\n");');
     $body->println("}");

     $includes->print("#include <");
     $library = $includes->new();     ##  Nesting even deeper still...
     $includes->println(">");

     $prototype->print("void hello(void)");

     $copyright->println("/*");
     $copyright->println("    Copyright (c) 1997, 1998, 1999 by Steffen Beyer.");
     $copyright->println("    All rights reserved.");
     $copyright->println("*/");

     $library->print("stdio.h");

     $copyright->filename("default.txt");

     $copyright->dump(">-");

     print "default filename = '", $copyright->filename(), "'\n";

     $copyright->filename("");

     __END__

   When executed, this example will print

     /*
         Copyright (c) 1997, 1998, 1999 by Steffen Beyer.
         All rights reserved.
     */
     default filename = 'default.txt'

   to the screen and create the following two files:

     ::::::::::::::
     example.c
     ::::::::::::::
     /*
         Copyright (c) 1997, 1998, 1999 by Steffen Beyer.
         All rights reserved.
     */
     #include <stdio.h>
     void hello(void)
     {
         printf("Hello, world!\n");
     }

     ::::::::::::::
     example.h
     ::::::::::::::
     /*
         Copyright (c) 1997, 1998, 1999 by Steffen Beyer.
         All rights reserved.
     */
     #include <stdio.h>
     void hello(void);

EXAMPLE #2
==========

     #!/sw/bin/perl -w

     use Data::Locations;

     use strict;
     no strict "vars";

     $html = Data::Locations->new("example.html");

     $html->println("<HTML>");
     $head = $html->new();
     $body = $html->new();
     $html->println("</HTML>");

     $head->println("<HEAD>");
     $tohead = $head->new();
     $head->println("</HEAD>");

     $body->println("<BODY>");
     $tobody = $body->new();
     $body->println("</BODY>");

     $tohead->print("<TITLE>");
     $title = $tohead->new();
     $tohead->println("</TITLE>");

     $tohead->print('<META NAME="description" CONTENT="');
     $description = $tohead->new();
     $tohead->println('">');

     $tohead->print('<META NAME="keywords" CONTENT="');
     $keywords = $tohead->new();
     $tohead->println('">');

     $tobody->println("<CENTER>");

     $tobody->print("<H1>");
     $tobody->print($title);      ##  Re-using this location!!
     $tobody->println("</H1>");

     $contents = $tobody->new();

     $tobody->println("</CENTER>");

     $title->print("'Data::Locations' Example HTML-Page");

     $description->println("Example for generating HTML pages");
     $description->print("using 'Data::Locations'");

     $keywords->print("locations, magic, insertion points,\n");
     $keywords->print("nested, recursive");

     $contents->println("This page was generated using the");
     $contents->println("<P>");
     $contents->println("&quot;<B>Data::Locations</B>&quot;");
     $contents->println("<P>");
     $contents->println("module for Perl.");

     __END__

   When executed, this example will produce the following file
("example.html"):

     <HTML>
     <HEAD>
     <TITLE>'Data::Locations' Example HTML-Page</TITLE>
     <META NAME="description" CONTENT="Example for generating HTML pages
     using 'Data::Locations'">
     <META NAME="keywords" CONTENT="locations, magic, insertion points,
     nested, recursive">
     </HEAD>
     <BODY>
     <CENTER>
     <H1>'Data::Locations' Example HTML-Page</H1>
     This page was generated using the
     <P>
     &quot;<B>Data::Locations</B>&quot;
     <P>
     module for Perl.
     </CENTER>
     </BODY>
     </HTML>

EXAMPLE #3
==========

     #!/sw/bin/perl -w

     ##  Note that this example only works as described if the "-w" switch
     ##  is set!

     package Non::Sense;

     ##  (This is to demonstrate that this example works with ANY package)

     use Data::Locations;
     use FileHandle;

     use strict;
     use vars qw($level0 $level1 $level2 $level3 $fh $fake);

     ##  Create the topmost location:

     $level0 = Data::Locations->new("level0.txt");

     print $level0 <<'VERBATIM';
     Printing first line to location 'level0' via OPERATOR 'print'.
     VERBATIM

     ##  Create an embedded location (nested 1 level deep):

     $level1 = $level0->new();

     $level0->print(<<'VERBATIM');
     Printing last line to location 'level0' via METHOD 'print'.
     VERBATIM

     ##  Now "tie" the embedded location to file handle STDOUT:

     $level1->tie('STDOUT');

     print "Printing to location 'level1' via STDOUT.\n";

     ##  Create another location (which will be embedded later):

     $level2 = Data::Locations->new();

     ##  Create a file handle ("IO::Handle" works equally well):

     $fh = FileHandle->new();

     ##  Now "tie" the location "$level2" to this file handle "$fh":

     $level2->tie($fh);

     ##  And select "$fh" as the default output file handle:

     select($fh);

     print "Printing to location 'level2' via default file handle '\$fh'.\n";

     ##  Embed location "$level2" in location "$level1":

     print $level1 $level2;

     ##  (Automatically removes "toplevel" status from location "$level2")

     print STDOUT "Printing to location 'level1' explicitly via STDOUT.\n";

     ##  Create a third embedded location (nested 3 levels deep):

     $level3 = $level2->new();

     ##  Restore STDOUT as the default output file handle:

     select(STDOUT);

     print $fh "Printing to location 'level2' via file handle '\$fh'.\n";

     ##  Trap all warnings:

     $SIG{__WARN__} = sub
     {
         print STDERR "WARNING intercepted:\n", @_, "End Of Warning.\n";
     };

     ##  Note that WITHOUT this trap, warnings would go to the system
     ##  standard error device DIRECTLY, WITHOUT passing through the
     ##  file handle STDERR!

     ##  Now "tie" location "$level3" to file handle STDERR:

     $level3->tie(*STDERR);

     ##  Provoke a warning message (don't forget the "-w" switch!):

     $fake = \$fh;
     $level3->print($fake);

     ##  Provoke another warning message (don't forget the "-w" switch!):

     $level3->dump();

     {
         ##  Silence warning that reference count of location is still > 0:

     local($^W) = 0;

     ##  And untie file handle STDOUT from location "$level1":

     untie *STDOUT;
       }

     print "Now STDOUT goes to the screen again.\n";

     ##  Read from location "$level3":

     while (<STDERR>)  ##  Copy warning messages to the screen:
     {
         if (/^.*?\bData::Locations::[a-z]+\(\):\s+(.+?)(?=\s+at\s|\n)/)
         {
             print "Warning: $1\n";
         }
     }

     while (<STDERR>) { print; }

     ##  (Prints nothing because location was already read past its end)

     ##  Reset the internal reading mark:

     (tied *{STDERR})->reset();

     ##  (You should usually use "$level3->reset();", though!)

     while (<STDERR>) { print; }

     ##  (Copies the contents of location "$level3" to the screen)

     ##  Write output file "level0.txt":

     __END__

   When running this example, the following text will be printed to the
screen (provided that you did use the "-w" switch):

     Now STDOUT goes to the screen again.
     Warning: REF reference ignored
     Warning: filename missing or empty
     WARNING intercepted:
     Data::Locations::print(): REF reference ignored at test.pl line 92
     End Of Warning.
     WARNING intercepted:
     Data::Locations::dump(): filename missing or empty at test.pl line 96
     End Of Warning.

   The example also produces an output file named "level0.txt" with the
following contents:

     Printing first line to location 'level0' via OPERATOR 'print'.
     Printing to location 'level1' via STDOUT.
     Printing to location 'level2' via default file handle '$fh'.
     WARNING intercepted:
     Data::Locations::print(): REF reference ignored at test.pl line 92
     End Of Warning.
     WARNING intercepted:
     Data::Locations::dump(): filename missing or empty at test.pl line 96
     End Of Warning.
     Printing to location 'level2' via file handle '$fh'.
     Printing to location 'level1' explicitly via STDOUT.
     Printing last line to location 'level0' via METHOD 'print'.

EXAMPLE #4
==========

     #!/sw/bin/perl -w

     use Data::Locations;

     use strict;
     no strict "vars";

     $loc = Data::Locations->new();

     print $loc "Thi";
     print $loc "s is an ex";
     print $loc "treme";
     print $loc "ly long and ted";
     print $loc "ious line o";
     print $loc "f text con";
     print $loc "taining on";
     print $loc "ly meaning";
     print $loc "less gibberish.";

     $string = '';

     $loc->traverse( sub { $string .= $_[0]; } );

     print "'$string'\n";

     __END__

   This example will print:

   'This is an extremely long and tedious line of text containing only
meaningless gibberish.'

SEE ALSO
========

   perl(1), perldata(1), perlfunc(1), perlsub(1), perlmod(1), perlref(1),
perlobj(1), perlbot(1), perltoot(1), perltie(1), printf(3), sprintf(3).

VERSION
=======

   This man page documents "Data::Locations" version 5.2.

AUTHOR
======

     Steffen Beyer
     Ainmillerstr. 5 / App. 513
     D-80801 Munich
     Germany

     mailto:sb@engelschall.com
     http://www.engelschall.com/u/sb/download/

     (Contact by e-mail preferred)

COPYRIGHT
=========

   Copyright (c) 1997, 1998, 1999 by Steffen Beyer.  All rights reserved.

LICENSE
=======

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself, i.e., under the terms of the
"Artistic License" or the "GNU General Public License".

   Please refer to the files "Artistic.txt" and "GNU_GPL.txt" in this
distribution for details.

DISCLAIMER
==========

   This package 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.

This module implements a proxy like Perl TIE interface over local and remote Berkeley DB files containing BLOBs
***************************************************************************************************************

NAME
====

   Data::MagicTie - This module implements a proxy like Perl TIE interface
over local and remote Berkeley DB files containing BLOBs

SYNOPSIS
========

     use Data::MagicTie;
     	use Fcntl;

     my $hash = tie %a,'Data::MagicTie','test';
     my $hash = tie %a,'Data::MagicTie','test',( Q => 7, mode => O_RDONLY); #query 7 dbs in one
     my $hash = tie %a,'Data::MagicTie','test',( Q => 1, noft => 1); #normal hash
     my $hash = tie %a,'Data::MagicTie','test',( style => "BerkeleyDB"); #sleepycat-ish :-)
     my $hash = tie %a,'Data::MagicTie','test',( lr => 1, dbms_host => 'me.jrc.it'); #cool way

     $a{mykey} = 'myvalue'; #store
     my $b = $a{mykey}; #fetch
     #iterator
     while (($k,$v) = each %a) {
     	my $c = $v;
     };
     #clear
     %a=();

     #basic delegation model - first match %a then %b
     my $hash1 = tie %b,'Data::MagicTie','test1';
     $hash1->set_parent($hash);
     print $b{mykey}; # looks up in %a :)
     untie %b;

     untie %a;

DESCRIPTION
===========

   This module acts as a proxy for the actual implementations of local and
remote counterparts Data::MagicTie::DBMS(3) Data::MagicTie::DB_File(3)
Data::MagicTie::BerkeleyDB(3) modules.  It allows to an application script
to transparently TIE hashes and arrays to either local or remote Berkeley
DB files, containing key/value pairs. The values can be either strings or
in-memory data structures (BLOBs) - see Storable(3); each tie database can
then be splitted up on several files for eccifency and reduce the size of
the actual database files. More, for query purposes only, tie operations
can be "chained" to transparently access different databases; such a chain
feature does not need any additional field in the database, but it is just
using in-memory Perl OO methods to delegate read operations (FETCH,
EXISTS, FIRSTKEY, NETXKEY). I.e. a look up for a key or value in a
database ends up in a read operation in the current database or in one of
its "delegates".

   Each atomic operation using the Perl operators actually trigger either
local or remote database lookups and freeze/thaw operations on values.
Perl constructs such as each, keys and values can be used to iterate over
the content of a tied database; when the file is splitted over several
single files the module iterates over the whole set of files. Even when a
parent (delegate) is set for a database these operators allow to scan the
whole set of storages (note: this feature might be not efficent over large
databases).

   By using such a Perl TIE model is becoming easy to write simple "cache"
systems for example using the Apache Web server and mod_perl. This could
really important for RDF storages and cumbersome and cpu-consuming
queries. (see RDFStore::Model and RDFStore::FindIndex)

CONSTRUCTORS
============

   The following methods construct/tie Data::MagicTie databases and
objects:

$db_hash = tie %b, 'Data::MagicTie', $filename, %whateveryoulikeit;
     Tie the hash %b to a MagicTie database called $filename. The
     %whateveryoulikeit hash contains a set of configuration options about
     how and where store actual data.  Possible options are the following:

    lr
          This is an integer flag 1/0 if a database is going to be stored
          in the local filesystem or on a remote DBMS(3) server - see
          Data::MagicTie::DBMS(3). Default is 0, local storage

    Q
          An integer about how many files to split around the database.
          Default to 1 (normal perltie behaviour).  Please note that set a
          number too high here might exceed you operating system MAX
          filedescriptors threshold (see man dbmsd(8) and DBMS(3) if
          installed on your system)

    mode
          Some valid predefied constant specifing if the database must be
          created, opened read/write/readonly.  For
          Data::MagicTie::DB_File(3) and Data::MagicTie::DBMS(3) possible
          values are O_CREAT, O_RDWR or O_RDONLY. For
          Data::MagicTie::BerkeleyDB(3) it culd either be DB_CREATE or
          DB_RDONLY - see DB_File(3) and BerkeleyDB(3)

    style
          A string identifing if the database is going to be
          Data::MagicTie::DB_File(3), Data::MagicTie::BerkeleyDB(3) or
          Data::MagicTie::DBMS(3). Possible values are 'DB_File',
          'BerkeleyDB' or 'DBMS'.  Default is 'DB_File'.

    noft
          This is in integer flag 1/0 to tell to the Data::MagicTie module
          whether or not use Storable(3) freeze/thaw operations on values.
          This could be renamed blobs option. See BUGS section below.

    dbms_host
          This option is only valid for Data::MagicTie::DBMS(3) style and
          tells to the system which is the IP address or machine name of
          the DBMS(3) server. Default is 'localhost'. See man dbmsd(8)

    dbms_port
          This option is only valid for Data::MagicTie::DBMS(3) style and
          tells to the system which is the TCP/IP port to connect to for
          the DBMS protocol. Default is '1234'. See man dbmsd(8)

    $db_array = tie @b, 'Data::MagicTie', $filename, %whateveryoulikeit;
          Tie the array @b to a MagicTie database called $filename. The
          %whateveryoulikeit hash is the same as above.

METHODS
=======

   Most of the method are common to the standard perltie(3) interface
(sync, TIEHASH, TIEARRAY, FETCH, STORE, EXISTS, FIRSTKEY, NEXTKEY, CLEAR,
DELETE, DESTROY)

   In addition Data::MagicTie provides additional method that allow to
magane a simple delegation or pass-through model for database for read
methods such as FETCH, EXISTS, FIRSTKEY, NEXTKEY. These are the following:

get_Options()
     Return an hash reference containing all the major options plus the
     directory and filename of the database. See CONSTRUCTORS

set_parent($ref)
     Set the parent delegate to which forward read requests. $ref must be
     a valid Data::MagicTie blessed Perl object, othewise the delegate is
     not set. After this method call any FETCH, EXISTS, FIRSTKEY or
     NEXTKEY invocation (normally automagically called by Perl for you :-)
     starts up a chain of requests to parents till the result has been
     found or undef.

get_parent()
     Return a valid Data::MagicTie blessed Perl object pointing to the
     parent of a tied database

reset_parent()
     Remove the parent of the database and the operations are back to
     normal.

EXAMPLES
========

delegates
     use Data::MagicTie;

     my $hash = tie %a,'Data::MagicTie','test'; my $hash1 = tie
     %b,'Data::MagicTie','test1'; my $hash2 = tie
     %c,'Data::MagicTie','test2';

     for (1..10) {         $a{"A".$_} = "valueA".$_;         $b{"B".$_} =
     "valueB".$_;         $c{"C".$_} = "valueC".$_; };

     #basic delegation model - first match %a then %a1 then %2
     $hash->set_parent($hash1); $hash1->set_parent($hash2); print $a{B3};
     # looks up in %b print $a{C9}; # looks up in %c

     #I think this one is much cooler :-> my $hash3 = tie
     %d,'Data::MagicTie','test3',( lr => 1 ); my $hash4 = tie
     %e,'Data::MagicTie','test4',( style => "BerkeleyDB" );

     for (1..10) {         $d{"D".$_} = "valueD".$_;         $e{"E".$_} =
     "valueE".$_; };

     #...and then use local or remote databases transparently
     $hash2->set_parent($hash3); $hash3->set_parent($hash4); print $a{D1};
     # really the Perl way of doing ;-) print $a{E1},"\n";

     #iterator while (($k,$v) = each %a) {         print $k,"=",$v,"\n"; };

     undef $hash; untie %a; undef $hash1; untie %b; undef $hash2; untie %c;
     undef $hash3; untie %d; undef $hash4; untie %e;

BUGS
====

     - The current implementation of TIE supports only the TIEHASH and TIEARRAY interfaces.
     - Data::MagicTie::DBMS does not support TIEARRAY yet.
     - Data::MagicTie ARRAY support is not complete and probably broken
     - a well-known problem using BLOBs is the following:

     	tie %a,"Data::MagicTie","test"; #by default is using BLOBs
     	$a{key1} = sub { print "test"; }; # works
     	$a{key2} = { a => [ 1,2,3], b => { tt => [6,7],zz => "test1234" } }; # it works too
     	$a{key3}->{this}->{is}->{not} = sub { "working"; }; #does not always work

     The problem seems to be realated to the fact Perl is "automagically" extending/defining
     hashes (or other in-memory structures). As soon as you start to reference a value it
     gets created "spontaneously" :-(
     E.g.
     	$a = {};
     	$a->{a1} = { a2 => [] };

     $b->{a1}->{a2} = []; # this is the same of the two lines above

     In the Data::MagicTie realm this problem affects the Storable freeze/thaw method results.
     Any idea how to fix this?

SEE ALSO
========

   perltie(3) Storable(3) DBMS(3) Data::MagicTie::DBMS(3)
Data::MagicTie::DB_File(3) Data::MagicTie::BerkeleyDB(3)

AUTHOR
======

   Alberto Reggiori <alberto.reggiori@jrc.it> You can send your postcards
and bugfixes to

Contact Details
===============

     TP270 - Reliable Information Technologies
     Institute for Systems, Informatics and Safety
     Joint Research Center of the European Community
     Ispra VA
     21020 Italy

     Fax +39 332 78 9185

This module is used by Data::MagicTie(3) to get a tied over SleepyCat BerkeleyDB files.
***************************************************************************************

NAME
====

   Data::MagicTie::BerkeleyDB - This module is used by Data::MagicTie(3)
to get a tied over SleepyCat BerkeleyDB files.

SYNOPSIS
========

   see BerkeleyDB(3)

DESCRIPTION
===========

SEE ALSO
========

   http://www.sleepycat.com

AUTHOR
======

   Alberto Reggiori <alberto.reggiori@jrc.it>

This module is used by Data::MagicTie(3) to get a tied remote interface over TCP/IP using DBMS(3) and DB_File(3)
****************************************************************************************************************

NAME
====

   Data::MagicTie::DBMS - This module is used by Data::MagicTie(3) to get
a tied remote interface over TCP/IP using DBMS(3) and DB_File(3)

SYNOPSIS
========

   see DBMS(3) and DB_File(3)

DESCRIPTION
===========

SEE ALSO
========

   http://www.sleepycat.com

AUTHOR
======

   Alberto Reggiori <alberto.reggiori@jrc.it>

This module is used by Data::MagicTie(3) to get a tied tied DB_File with locking support.
*****************************************************************************************

NAME
====

   Data::MagicTie::DB_File - This module is used by Data::MagicTie(3) to
get a tied tied DB_File with locking support.

SYNOPSIS
========

   see DB_File(3)

DESCRIPTION
===========

SEE ALSO
========

   http://www.sleepycat.com

AUTHOR
======

   Alberto Reggiori <alberto.reggiori@jrc.it>

Convert arbitrary objects to/from strings
*****************************************

NAME
====

   Data::PropertyList - Convert arbitrary objects to/from strings

SYNOPSIS
========

     use Data::PropertyList qw(astext fromtext);

     $hash_ref = { 'items' => [ 7 .. 11 ], 'key' => 'value' };
     $string = astext($hash_ref);
     # ...
     $hash_ref = fromtext($string);
     print $hash_ref->{'items'}[0];

     $array_ref = [ 1, { 'key' => 'value' }, 'Omega' ];
     $string = astext($array_ref);
     # ...
     $array_ref = fromtext($string, '-array'=>1 );
     print $array_ref->[1]{'key'};

DESCRIPTION
===========

   Data::Propertylist provides functions that turn data structures with
nested references into NeXT's Property List text format and back again.

   You may find this useful for saving and loading application information
in text files, or perhaps for generating error messages while debugging.

astext( $reference ) : $propertylist_string;
     Writes out a nested Perl data structure in NeXT property list format.

fromtext( $propertylist_string ) : $hash_ref
fromtext( $propertylist_string, '-array'=>1 ) : $array_ref
     Reconstructs a Perl data structure of nested references and scalars
     from a NeXT property list. Use the -array flag if the string encodes
     an array rather than a hash.

The Property List Format
------------------------

   *The below is excerpted from a draft of the NeXT PropertyList(5) man
page:*

   A property list organizes data into named values and lists of values.
Property lists are used by the NEXTSTEP user defaults system (among other
things).

   In simple terms, a property list contains strings, binary data, arrays
of items, and dictionaries.  These four kinds of items can be combined in
various ways, as described below.

   A string is enclosed in double quotation marks; for example, "This is a
string." (The period is included in this string.)  The quotation marks can
be omitted if the string is composed strictly of alphanumeric characters
and contains no white space (numbers are handled as strings in property
lists).  Though the property list format uses ASCII for strings, note that
NEXTSTEP uses Unicode.  You may see strings containing unreadable
sequences of ASCII characters; these are used to represent Unicode
characters.

   Binary data is enclosed in angle brackets and encoded in hexadecimal
ASCII; for example, <0fbd777 1c2735ae>.  Spaces are ignored.

   An array is enclosed in parentheses, with the elements separated by
commas; for example, ("San Francisco", "New York", "London").  The items
don't all have to be of the same type (for example, all strings) - but
they normally should be.  Arrays can contain strings, binary data, other
arrays, or dictionaries.

   A dictionary is enclosed in curly braces, and contains a list of keys
with their values.  Each key-value pair ends with a semicolon.  Here's a
sample dictionary: { user = maryg; "error string" = "core dump"; code =
<fead0007>; }.  (Note the omission of quotation marks for single-word
alphanumeric strings.) Values don't all have to be the same type, since
their types are usually defined by whatever pro- gram uses them (in this
example, the program using the dic- tionary knows that user is a string
and code is binary data).  Dictionaries can contain strings, binary data,
arrays, and other dictionaries.

   Below is a sample of a more complex property list, taken from a user's
defaults system (see defaults(1)).  The pro- perty list itself is a
dictionary with keys "Clock," "NSGlobalDomain," and so on; each value is
also a diction- ary, which contains the individual defaults.

     {
     	Clock = {ClockStyle = 3; };
     	NSGlobalDomain = {24HourClock = Yes; Language = English; };
     	NeXT1 = {Keymap = /NextLibrary/Keyboards/NeXTUSA; };
     	Viewer = {NSBrowserColumnWidth = 145; "NSWindow Frame
     Preferences" = "5 197 395 309 "; };
     	Workspace = {SelectedTabIndex = 0; WindowOrigin = "-75.000000"; };
     	pbs = {};
     }

   *Please note that the above documentation is incomplete, and that the
current implementation does not support all of the features discussed
above.*

EXAMPLE
=======

   Here's an example of a PropertyList-encoded data structure:

     my $produce_info = {
       'red' =>     { 'fruit' => [ { 'name' => 'apples',
     				  'source' => 'Washington' } ],
     		  'tubers' => [ { 'name' => 'potatoes',
     				  'source' => 'Idaho' } ] },
       'orange' =>  { 'fruit' => [ { 'name' => 'oranges',
     				  'source' => 'Florida' } ] }
     };
     print astext( $produce_info);

   Examine STDOUT, et voila!

     orange = {
       fruit = (
         {
     	name = oranges;
     	source = Florida;
         },
       );
     };
     red = {
       fruit = (
         {
     	name = apples;
     	source = Washington;
         },
       );
       tubers = (
         {
     	name = potatoes;
     	source = Washington;
         },
       );
     };

PREREQUISITES AND INSTALLATION
==============================

   This package requires the String::Escape module. It should run on any
standard Perl 5 installation.

   To install this package, download and unpack the distribution archive
from http://www.evoscript.com/dist/ and execute the standard "perl
Makefile.PL", "make test", "make install" sequence.

STATUS AND SUPPORT
==================

   This release of Data::PropertyList is intended for public review and
feedback.  It has been tested in several environments and used in
commercial production, but it should be considered "alpha" pending that
feedback and fixes for some of the below bugs.

     Name            DSLI  Description
     --------------  ----  ---------------------------------------------
     Data::
     ::PropertyList  adpf  Convert arbitrary objects to/from strings

   Further information and support for this module is available at
<www.evoscript.com>.

   Please report bugs or other problems to <bugs@evoscript.com>.

   The following changes are in progress or under consideration:

Better Whitespace Parsing
     Code is currently picky about parsing whitespace, and stilted about
     printing it. In particular, a newline is required after each item in
     an array or hash.

Restore Classes During Parsing
     The class of blessed objects is indicated in `/* ... */' comments
     embedded in the output, but are not yet restored when reading.

Restore Circular References During Parsing
     Circular references are indicated in `/* ... */' comments embedded in
     the output, but are not yet restored when reading.

NeXT Binary Format
     Doesn't currently parse or write NeXT's <FFFF> binary format.

SEE ALSO
========

   Similar to PropertyList.pm by Markus Felten
<markus@arlac.rhein-main.de>.

   The packages Data::Dumper and FreezeThaw (available from CPAN) also
stream and destream data structures.

AUTHORS AND COPYRIGHT
=====================

   Copyright 1996, 1997, 1998 Evolution Online Systems, Inc.

   You may use this software for free under the terms of the Artistic
License

   Contributors: M. Simon Cavalletto `<simonm@evolution.com>', Eleanor J.
Evans `<piglet@evolution.com>', Jeremy G. Bishop `<jeremy@evolution.com>',
Eric Schneider `<roark@evolution.com>'

Perl module to generate random data
***********************************

NAME
====

   Data::Random - Perl module to generate random data

SYNOPSIS
========

     use Data::Random qw(:all);

     my @random_words = rand_words( wordlist => '/usr/dict/words', size => 10 );

     my @random_chars = rand_chars( set => 'all', min => 5, max => 8 );

     my @random_set = rand_set( set => \@set, size => 5 );

     my $random_enum = rand_enum( set => \@set );

     my $random_date = rand_date();

     my $random_time = rand_time();

     my $random_datetime = rand_datetime();

DESCRIPTION
===========

   A module used to generate random data.  Useful mostly for test programs.

METHODS
=======

rand_words()
------------

   This returns a list of random words given a wordlist.  See below for
possible parameters.

   * wordlist - the path to the wordlist file.  A lot of systems have one
     at /usr/dict/words.  You can also optionally supply a
     Data::Random::WordList object to keep a persistent wordlist.

   * min - the minimum number of words to return.  The default is 1.

   * max - the maximum number of words to return.  The default is 1.

   * size - the number of words to return.  The default is 1.  If you
     supply a value for 'size', then 'min' and 'max' aren't paid attention
     to.

   * shuffle - whether or not the words should be randomly shuffled.  Set
     this to 0 if you don't want the words shuffled.  The default is 1.
     Random::Data::WordList returns words in the order that they're viewed
     in the word list file, so shuffling will make sure that the results
     are a little more random.

rand_chars()
------------

   This returns a list of random characters given a set of characters.
See below for possible parameters.

   * set - the set of characters to be used.  This value can be either a
     reference to an array of strings, or one of the following:

          alpha        - alphabetic characters: a-z, A-Z
          upperalpha   - upper case alphabetic characters: A-Z
          loweralpha   - lower case alphabetic characters: a-z
          numeric      - numeric characters: 0-9
          alphanumeric - alphanumeric characters: a-z, A-Z, 0-9
          char         - non-alphanumeric characters: # ~ ! @ $ % ^ & * ( ) _ + = - { } | : " < > ? / . ' ; ] [ \ `
          all          - all of the above

          =item *

          min - the minimum number of characters to return.  The default is 0.

   * max - the maximum number of characters to return.  The default is the
     size of the set.

   * size - the number of characters to return.  The default is 1.  If you
     supply a value for 'size', then 'min' and 'max' aren't paid attention
     to.

   * shuffle - whether or not the characters should be randomly shuffled.
     Set this to 0 if you want the characters to stay in the order
     received.  The default is 1.

rand_set()
----------

   This returns a random set of elements given an initial set.  See below
for possible parameters.

   * set - the set of strings to be used.  This should be a reference to
     an array of strings.

   * min - the minimum number of strings to return.  The default is 0.

   * max - the maximum number of strings to return.  The default is the
     size of the set.

   * size - the number of strings to return.  The default is 1.  If you
     supply a value for 'size', then 'min' and 'max' aren't paid attention
     to.

   * shuffle - whether or not the strings should be randomly shuffled.
     Set this to 0 if you want the strings to stay in the order received.
     The default is 1.

rand_enum()
-----------

   This returns a random element given an initial set.  See below for
possible parameters.

   * set - the set of strings to be used.  This should be a reference to
     an array of strings.

rand_date()
-----------

   This returns a random date in the form "YYYY-MM-DD".  2-digit years are
not currently supported.  Efforts are made to make sure you're returned a
truly valid date-ie, you'll never be returned the date February 31st.  See
the options below to find out how to control the date range.  Here are a
few examples:

     # returns a date somewhere in between the current date, and one year from the current date
     $date = rand_date();

     # returns a date somewhere in between September 21, 1978 and September 21, 1979
     $date = rand_date( min => '1978-9-21' );

     # returns a date somewhere in between September 21, 1978 and the current date
     $date = rand_date( min => '1978-9-21', max => 'now' );

     # returns a date somewhere in between the current date and September 21, 2008
     $date = rand_date( min => 'now', max => '2008-9-21' );

     See below for possible parameters.

   * min - the minimum date to be returned. It should be in the form
     "YYYY-MM-DD" or you can alternatively use the string "now" to
     represent the current date.  The default is the current date;

   * max - the maximum date to be returned. It should be in the form
     "YYYY-MM-DD" or you can alternatively use the string "now" to
     represent the current date.  The default is one year from the minimum
     date;

rand_time()
-----------

   This returns a random time in the form "HH:MM:SS".  24 hour times are
supported.  See the options below to find out how to control the time
range.  Here are a few examples:

     # returns a random 24-hr time (between 00:00:00 and 23:59:59)
     $time = rand_time();

     # returns a time somewhere in between 04:00:00 and the end of the day
     $time = rand_time( min => '4:0:0' );

     # returns a time somewhere in between 8:00:00 and the current time (if it's after 8:00)
     $time = rand_time( min => '12:00:00', max => 'now' );

     # returns a date somewhere in between the current time and the end of the day
     $time = rand_time( min => 'now' );

     See below for possible parameters.

   * min - the minimum time to be returned. It should be in the form
     "HH:MM:SS" or you can alternatively use the string "now" to represent
     the current time.  The default is 00:00:00;

   * max - the maximum time to be returned. It should be in the form
     "HH:MM:SS" or you can alternatively use the string "now" to represent
     the current time.  The default is 23:59:59;

rand_datetime()
---------------

   This returns a random date and time in the form "YYYY-MM-DD HH:MM:SS".
See the options below to find out how to control the date/time range.
Here are a few examples:

     # returns a date somewhere in between the current date/time, and one year from the current date/time
     $datetime = rand_datetime();

     # returns a date somewhere in between 4:00 September 21, 1978 and 4:00 September 21, 1979
     $datetime = rand_datetime( min => '1978-9-21 4:0:0' );

     # returns a date somewhere in between 4:00 September 21, 1978 and the current date
     $datetime = rand_datetime( min => '1978-9-21 4:0:0', max => 'now' );

     # returns a date somewhere in between the current date/time and the end of the day September 21, 2008
     $datetime = rand_datetime( min => 'now', max => '2008-9-21 23:59:59' );

     See below for possible parameters.

   * min - the minimum date/time to be returned. It should be in the form
     "YYYY-MM-DD HH:MM:SS" or you can alternatively use the string "now"
     to represent the current date/time.  The default is the current
     date/time;

   * max - the maximum date/time to be returned. It should be in the form
     "YYYY-MM-DD HH:MM:SS" or you can alternatively use the string "now"
     to represent the current date/time.  The default is one year from the
     minimum date/time;

VERSION
=======

   0.01

AUTHOR
======

   Adekunle Olonoh, ade@bottledsoftware.com

COPYRIGHT
=========

   Copyright (c) 2000 Adekunle Olonoh. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   Data::Random::WordList

Perl module to get random words from a word list
************************************************

NAME
====

   Data::Random::WordList - Perl module to get random words from a word
list

SYNOPSIS
========

     use Data::Random::WordList;

     my $wl = new Data::Random::WordList( wordlist => '/usr/dict/words' );

     my @rand_words = $wl->get_words(10);

     $wl->close();

DESCRIPTION
===========

   Data::Random::WordList is a module that manages a file containing a
list of words.

   The module expects each line of the word list file to contain only one
word.  It could thus be easily used to select random lines from a file,
but for coherency's sake, I'll keep referring to each line as a word.

   The module uses a persistent filehandle so that there isn't a lot of
overhead every time you want to fetch a list of random words.  However,
it's much more efficient to grab multiple words at a time than it is to
fetch one word at a time multiple times.

   The module also refrains from reading the whole file into memory, so it
can be safer to use with larger files.

METHODS
=======

new()
-----

   Returns a reference to a new Data::Random::WordList object.  Use the
"wordlist" param to initialize the object:

   * wordlist - the path to the wordlist file.

get_words([NUM])
----------------

   NUM contains the number of words you want from the wordlist.  NUM
defaults to 1 if it's not specified.  get_words() dies if NUM is greater
than the number of words in the wordlist.  This function returns an array
or an array reference depending on the context in which it's called.

close()
-------

   Closes the filehandle associated with the word list.  It's good
practice to do this every time you're done with the word list.

VERSION
=======

   0.01

AUTHOR
======

   Adekunle Olonoh, ade@bottledsoftware.com

COPYRIGHT
=========

   Copyright (c) 2000 Adekunle Olonoh. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   Data::Random

Report generator.
*****************

NAME
====

   Reporter - Report generator.

SYNOPSIS
========

     use strict;
     use Data::Reporter::RepFormat;
     use Data::Reporter;
     use Data::Reporter::Filesource;

     sub HEADER($$$$) {
        my ($reporter, $sheet, $rep_actline, $rep_lastline) = @_;
        $sheet->MVPrint(10,0, 'This is the header');
        $sheet->MVPrint(10,1, 'This is the page :');
        $sheet->Print($reporter->page());
     }

     sub TITLE($$$$) {
        my ($reporter, $sheet, $rep_actline, $rep_lastline) = @_;
        $sheet->MVPrint(10,0, 'This is the title');
     }

     sub DETAIL($$$$) {
        my ($reporter, $sheet, $rep_actline, $rep_lastline) = @_;
        $sheet->MVPrint(10,0, 'This is the detail');
        $sheet->MVPrint(10,1, 'This is the begin of the report') if ($reporter->{BOR});
     }

     #main
     {
        $source = new Data::Reporter::Filesource(File => "inputfile");
        my $report = new Data::Reporter();
        $report->configure(
            Width => 105,
            Height => 66,
            SubHeaher => \&HEADER,
            SubTitle => \&TITLE,
            SubDetail => \&DETAIL,
            Source => $source,
            File_name => "OUPUT"
        );
        $report->generate();
     }

DESCRIPTION
===========

Data::Reporter::new();
     Creates a new Report handler

$report->configure(option => value)
     valid options are:

          Width		number of columns

          Height		number of rows

          Orientation 	Report orientation (portrait, landscape)

          Footer_size 	rows in footer

          File_name		output file name

          Source		Data source (Datasource class descendant)

          Breaks		Hash reference, which contains the breaks information

          SubHeader		function reference, which will be called to print the
          report header

          SubTitle		function reference, which will be called to print the
          report title

          SubDetail		function reference, which will be called to print every
          report detail

          SubFooter		function reference, which will be called to print the
          report footer

          SubFinal		function reference, which is called when all data has
          been processed

          SubPrint		function reference, which is called when the report is
          created

     $report->generate()		Generates the report. Returns 0 if OK, 2
     if there was no data

SPECIAL FUNCTIONS
=================

     $report->page()		returns the page number

     $report->date(n)	returns the date in a specific format. n is the
     format code. Currently, there are only 2 formats

          1		dd/mm/aaaa
          2		mm/dd/aaaa

     $report->time(n)	returns the time in a specific format. n is the
     format code. Currently, there is only 1 format

          1    hh:mm

     $report->eOR()		indicates the end of report

     $report->bOR()		indicates the begining of the report

     $report->bOP()		indicates the firts detail in the the page

     $report->width()	Report's width

     $report->height()	Report's height

     $report->islastbreak()	Returns true if it's the last
     processing break (using the cascade breaks approach)

     $report->iPB()	Returns true if the reporter is processing breaks
     (useful when you want or not to do something while processing breaks)

     $report->newpage([TIMES])	indicates that a new page is
     required. TIMES is the number of form feeds to do. By default is 1

     $report->newreport(FILE)		indicates that the data processed up
     to this point should be stored in file FILE.

EVENT FUNCTIONS
===============

   Each event function (Header, Title, Detail, Break, Foooter, Final), is
called automatically when neccesary, passing them the following parameters:

     report		which can be used to access the special variables

     sheet		blank sheet where the output will be defined (see
     RepFormat pod documentation)

     actual_reg	actual processing register

     last_reg		last processing register

HEADER FUNCTION
---------------

   This functions is called each time when a new page is required

TITLE FUNCTION
--------------

   This function is called after the header, and breaks functions.

DETAIL FUNCTION
---------------

   This function is called for every data record

FOOTER FUNCTION
---------------

   This functions is called at the end of each page

FINAL FUNCTION
--------------

   This function is called after the last record has been processed for
the detail function

BREAK FUNTIONS
--------------

   These functions are called when the break field of the function has
changed (see BREAKS section). These functions are called before the detail
function for the actual register.

BREAKS
======

GENERALS
     Each break is defined with a break field and a break function. For
     example:

     assume we have the following data:

          1 2
          1 3
          2 4

     If we want a break for the first field, that prints the sum of the
     second field, we have to define the following hash

     $breaks{0} = \&sub_break;

     where sub_break is the function where the output is defined. We have
     to define the sum for each record in the 'detail' function

          sub detail ( .....
          ...
          $sum += $field[1];
          ....

     so we can do

          sub sub_break ( ....
          ...
          $sheet->Print("the sum is $sum");
          $sum = 0; #reset $sum
          ...

     As many breaks as necessary can be defined, but only one break per
     field is allowed.

CASCADE BREAKS
     When defining more that one Break, they are handled in cascade. A
     change in a break field will cause all the break functions defined
     for fields with a lower value to be called. For example

     assume the following data

          1 2 3 1 1
          1 2 3 1 2
          1 2 4 2 3
          1 3 4 2 4

     and the following break hash

          $breaks{0} = \&break1;
          $breaks{1} = \&break2;
          $breaks{3} = \&break3;

     in the third register, the field #3 changes. This will cause the
     functions break1, break2 and break3 to be called. The order in which
     these functions are called are from the left most to the right most
     one.

     In the fourth register the field #2 changes, so functions break1 and
     break2 will be called, in this order.

DATASOURCES
===========

   This indicates the source for the report data. It can be a Database or
a plain ascii file.

   Internally, Data::Reporter uses this object to retreive data. This
object should have a function 'getdata' defined, which receives a function
reference that will be called on each record.

   This approach allows to have diferent data sources. At this point the
only sources available are a Sybase database and a plain ascii file, but
sources for others databases can easily be implemented.

Abstract base class for all the Reporter source data types
**********************************************************

NAME
====

   Datasource - Abstract base class for all the Reporter source data types

SYNOPSIS
========

   use Data::Reporter::Datasource;

DESCRIPTION
===========

   This class helps to maintain control of the source data types in
Data::Reporter.  The method 'getdata', should be defined in each source
data type.

Reporter handler for plain text information
*******************************************

NAME
====

   Filesource - Reporter handler for plain text information

SYNOPSIS
========

   use Data::Reporter::Filesource;

     $source = new Data::Reporter::Filesource(File => $file);
     #			$file 			- source filename

     $subru = sub {print "record -> $_\n"};
     $source->getdata($subru);
     $source->configure(File => $file);

DESCRIPTION
===========

new()
     Creates a new handler to manipulate the file information.

$source->configure(option => value)
     File		File with the information to process. It is the only
     valid option at this moment

$source->getdata($subru)
     For each record in the file, call the function $subru, passing the
     record as a parameter

NOTES
=====

   "|" is the field separator.

Reporter Handler for oracle connection
**************************************

NAME
====

   Orasource - Reporter Handler for oracle connection

SYNOPSIS
========

     use Data::Reporter::Orasource;

     $source = new Data::Reporter::Orasource(File => $file,
     			Arguments => $info,
     			Query => $query);

     $file 		- information file about connection login
     $info		- array reference (usr, pwd, db, srv) about connection login
     $query		- query to execute for getting data

     $subru = sub {print "record -> $_\n"};
     $source->getdata($subru);

DESCRIPTION
===========

new()
     Creates a new handler to manipulate the oracle information.

$source->configure(option => value)
     valid options are:

          File			Information file about connection login. The file
          must have the following information: user, password, database,
          server. These items must come in this order, each on a separate
          line.

          Arguments		array reference with the following information: usr,
          pwd, db, srv. This can be used instead of the File option

          query		string with the query to execute to retrive the data

$source->getdata($subru)
     For each record of the query result, calls the function $subru,
     sending the record as parameter

AUTHOR 	 	Vecchio Fabrizio <jacote@tiscalinet.it> FABRVEC =cut
==============================================================

   package Data::Reporter::Orasource; use DBI; use Carp; use
Data::Reporter::Datasource;  @ISA =  qw(Data::Reporter::Datasource); use
strict;

   sub new (%) { 	my $class = shift; 	my $self={}; 	my %param = @_; 	bless
$self, $class; 	foreach my $key (keys %param) { 		if ($key eq "File")
{ 			$self->{CONNECTIONINFO} = $self->_getfileparams($param{$key}); 		} elsif
($key eq "Arguments") { 			my @data = @{$param{$key}}; 			croak
"Invalid arguments for conexion  (usr, pwd, db)!!!"  				if (@data < 3);
$self->{CONNECTIONINFO} = \@data; 		} elsif ($key eq "Query") {
$self->{QUERY} = $param{$key}; 		} 	} 	$self->_connect();
bless $self, $class; }

   sub getdata($$) { 	my $self = shift; 	my $routine = shift; 	my
@row=(); 	$self->{STH}=$self->{DBH}->prepare($self->{QUERY});
$self->{STH}->execute(); 	while(@row=$self->{STH}->fetchrow_array)
{ 	&$routine(split(/\|/,join("|",@row))); 	}; 	$self->{STH}->finish();
}

   sub _getfileparams($$) { 	my $self = shift; 	my $file = shift;

     open FILECON, $file or croak "Can't open file $file!!!";
     my @data = <FILECON>;
     close FILECON;

     croak "file error: $file!!!" if (@data < 3);
     my $usr = $data[0];
     my $pas = $data[1];
     my $db  = $data[2];
     chomp($usr);
     chomp($pas);
     chomp($db);
     return [$usr, $pas, $db];
     }

   sub _connect($) { 	my $self = shift; 	my ($usr, $pass, $db) =
@{$self->{CONNECTIONINFO}};
$self->{DBH}=DBI->connect("dbi:Oracle:".$db,$usr,$pass); }

   sub close($) { 	my $self=shift; 	$self->{DBH}->disconnect(); };

   1;

Allows text formatting with simple instructions, mapping to a user-defined grid (the sheet).
********************************************************************************************

NAME
====

   RepFormat	- Allows text formatting with simple instructions,
mapping to a user-defined grid (the sheet).

SYNOPSIS
========

     use Data::Reporter::RepFormat;

     $sheet = new Data::Reporter::RepFormat($cols, $rows);
     $sheet->Move(0,3);
     $sheet->Print('123');
     $sheet->Out();
     $sheet->Clear();
     $sheet->Printf('%010d', 12);
     $sheet->MVPrint(0, 3, '123');
     $sheet->MVPrintf(0, 1, '%3.2f', 79.123);
     $sheet->Nlines();
     $sheet->Getline(20);
     $sheet->Copy($source_sheet);
     $sheet->Center('hello', 10);
     my $pic = $sheet->ToPicture('$$$,999, 999', 1234.56);
     $value = $sheet->Commify('1234567.89');

DESCRIPTION
===========

new($cols, $rows)
     Creates a new RepFormat object. This function receives two
     parameters: columms and rows of the sheet.

$sheet->Move($col, $row)
     Moves cursor to the indicated position

$sheet->Print($string)
     Puts $string at the current cursor position.

$sheet->Out([$handle])
     Moves the sheet information to target output. If $handle is not
     specified, then STDOUT is used.

$sheet->Clear()
     Clears the sheet

$sheet->Printf(format, argument)
     Prints using printf style format

$sheet->MVPrint($col, $row, $string)
     Moves, then Prints

$sheet->MVPrintf($col, $row, format, argument)
     Moves, then Prints (using printf style format)

$sheet->Nlines()
     Returns the number of lines in the sheet, discarding the last blank
     lines

$sheet->Getline($index)
     Returns the $index row

$sheet->Copy($source_sheet)
     Appends $source_sheet in $sheet

$sheet->Center($string, $size)
     Returns a string with size = $size having $string centered in it.
     This function uses spaces to pad on both sides.

$sheet->Commify($number);
     Returns $number as a string with commas (123456789.90 ->
     123,456,789.90)

     *NOTE This function will be no longer supported in next releases. Use
     PrintP instead.

$sheet->printP($string, $picture);
     Puts a string at the current position with $string in the specified
     $picture.

     There are two clases of pictures: strings and numerical

    strings
          The following table list the text edit format characters:

          Character			Description X             		Use character in field
          B             		Insert blank ~(tilde)      		Skip
          character in field

          examples

          Mask				value			Display
          (xxx)bxxx-xxxx		2169910551		(216) 991-0551
          xxx-xx-xxxx   		123456789 		123-45-6789 ~~xx~xx
          		ABCDEFGHIJ		CDFG

    numerical
          The following table list the numerical edit format characters:

          Character			Description 8				Digit, zero fill to the rigth of 				the
          decimal point trim leading 				blanks (left justify the number)
          9				Digit, zero fill to the right of 				the decimal point,
          space fill to 				the left 0				Digit, zero fill to the
          left $				Dollar sign, optionally floats to 				the right
          B				Treated as a "9", but if a value 				is zero, the field is
          converted 				to blanks V				Implied decimal point
          MI				Entered at the end of the mask 				causes a minus to be
          displayed at 				the right of the number PR				Entered at teh end of the
          mask 				causes angle brackets (<>) to be 				displayed
          around the number if 				the number is negative PS				Entered at
          the end of the mask 				causes parentheses to display 				around
          the number if the number 				is negative PF				Entered at the end of the
          mask 				causes floating parentheses to 				display around teh
          number if 				the number is negative .				Decimal point ,				Comma

          examples

          Mask				value			Display 999.99        		34.568
               34.57 9,999,999v99  		123,456.78		 123,456.78
          8,888,888.88  		123,456,78		123,456.78 9,999
           	1234       		      1,234 09999           	1234
            		      01234 9999            	12345
          **** 9999mi          	-123       		       123- 9999pr
             	-123       		     < 123> 9999ps          	-123
              		     ( 123) 9999pf           	-123
          ( 123)

$sheet->MVPrintP($col, $row, $string, $pic)
     Moves, then PrintP

Reporter Handler for sybase connection
**************************************

NAME
====

   Sybsource - Reporter Handler for sybase connection

SYNOPSIS
========

     use Data::Reporter::Sybsource;

     $source = new Data::Reporter::Sybsource(File => $file,
     			Arguments => $info,
     			Query => $query);

     $file 		- information file about connection login
     $info		- array reference (usr, pwd, db, srv) about connection login
     $query		- query to execute for getting data

     $source->configure(option => value, ...);
     $subru = sub {print "record -> $_\n"};
     $source->getdata($subru);

DESCRIPTION
===========

new()
     Creates a new handler to manipulate the sybase information.

$source->configure(option => value)
     valid options are:

          File			Information file about connection login. The file
          must have the following information: user, password, database,
          server. database and server can be defined as "default", so the
          conexion uses the server defaults. These items must come in this
          order, each on a separate line.

          Arguments		array reference with the following information: usr,
          pwd , db, srv. db and srv can be "undef" so the conexion uses
          the server defaults. This can be used instead of the File option

          query		string with the query to execute to retrive the data

          Handler		Sybase conexion handler. The class uses this handler to
          perform the query

$source->getdata($subru)
     For each record of the query result, calls the function $subru,
     sending the record as parameter

$source->close()
     Close sybase connection

handler to manipulate sections in VisRep.pl.
********************************************

NAME
====

   VisSection - handler to manipulate sections in VisRep.pl.

SYNOPSIS
========

     use Data::Reporter::VisSection;

     $section = new Data::Reporter::VisSection();
     $section->configure(Name => 'mydetail',
     		Lines => ('line 1', 'line 2', 'line 3'),
     		Code => "print 'this is the detail section\n';",
     		Size => 3,
     		Break_field => 0,
     		Width => 20,
     		Only_code => 0);
     my $name = $section->name();
     my $size = $section->size();
     my $break_field = $section->break_field();
     my @lines = $section->lines();
     my $code = $section->code();
     my $only_code = $section->only_code();
     $section->append("print 'this is the last line of code\n');
     $section->insert("print 'this is the first line of code\n'");

     open OUT, "out.txt";
     $section->generate(\*OUT);

DESCRIPTION
===========

new();
     Creates a new section handler

$section->configure(option => value)
     valid options are:

          Name			Section name

          Lines		array of Lines to be printed in this section

          Code			Code to execute before printing the data section

          Size			Number of lines in the section

          Break_field	Field number in which the break applies

          Width		Numbers of columns in section

          Only_code		Indicator for a no-lines section

$section->name()
     Returns the section's name

$section->size()
     Returns the section's size

$section->break_field()
     Returns the section's break_field

$section->lines()
     Returns an array with the section`s lines

$section->code()
     Returns the section's Code

$section->only_code()
     Returns the only_code indicator

     Print perl code in OUT handler. This code is the section's information

NOTES
=====

   A section is a part of a report. For example the header section, the
title section, etc. Each section has two parts:

Code part
     This contains perl code, which is executed before printing the data
     lines of the section. This is useful because you can prepare the data
     to print in the report or acumulate totals. The special variable
     @field, is used to print data in lines.

Lines part
     Here are the lines to print. The lines are printed using the
     RepFormat module, there are special fields in printing the lines:

@Fn
     This field generates code to print $field[n]

@Pn
     This field generates code to print $report->page(n). page is a
     special feature from Reporter module

@Tn
     This field generates code to print $report->time(n). time is a
     special feature from Reporter module

@Dn
     This field generates code to print $report->date(n). date is a
     special feature from Reporter module

routines to display tabular data in several formats.
****************************************************

NAME
====

   ShowTable - routines to display tabular data in several formats.

USAGE
=====

   `use Data::ShowTable;'

   ShowTable { parameter => value, ... };

   ShowTable *\@titles*, *\@types*, *\@widths*, *\&row_sub* [, *\&fmt_sub*
];

   ShowDatabases *\@dbnames*;

   ShowDatabases { parameter => value, ... };

   ShowTables *\@tblnames*;

   ShowTables { parameter => value, ... };

   ShowColumns *\@columns*, *\@col_types*, *\@col_lengths*, *\@col_attrs*;

   ShowColumns { parameter => value, ... };

   ShowBoxTable *\@titles*, *\@types*, *\@widths*, *\&row_sub* [,
*\&fmt_sub* ];

   ShowBoxTable { parameter => value, ... };

   ShowSimpleTable *\@titles*, *\@types*, *\@widths*, *\&row_sub* [,
*\&fmt_sub*];

   ShowSimpleTable { parameter => value, ... };

   ShowHTMLTable *\@titles*, *\@types*, *\@widths*, *\&row_sub* [,
*\&fmt_sub*];

   ShowHTMLTable { parameter => value, ... };

   ShowListTable *\@titles*, *\@types*, *\@widths*, *\&row_sub* [,
*\&fmt_sub*];

   ShowListTable { parameter => value, ... };

   `package Data::ShowTable';

   $Show_Mode = 'mode';

   $Max_Table_Width = number;

   $Max_List_Width = number;

   $No_Escape = flag;

   %URL_Keys = { "*$colname*" => "*$col_URL*", ... };

   *@Title_Formats* = ( *fmt1_html*, <fmt2_html>, ... );

   *@Data_Formats* = ( *fmt1_html*, <fmt2_html>, ... );

   ShowRow *$rewindflag*, *\$index*, *$col_array_1* [, *$col_array_2*,
...;]

   *$fmt* = ShowTableValue $value, $type, $max_width, $width, $precision,
$showmode;

   [*$plaintext* = ] PlainText [*$htmltext*];

DESCRIPTION
===========

   The ShowTable module provides subroutines to display tabular data,
typially from a database, in nicely formatted columns, in several formats.
Its arguments can either be given in a fixed order, or, as a single,
anonymous hash-array.

   The output format for any one invocation can be one of four possible
styles:

Box
     A tabular format, with the column titles and the entire table
     surrounded by a "box" of "+", "-", and "|" characters.  See
     `"ShowBoxTable"' in this node for details.

Table
     A simple tabular format, with columns automatically aligned, with
     column titles.  See `"ShowSimpleTable"' in this node.

List
     A list style, where columns of data are listed as a name:value pair,
     one pair per line, with rows being one or more column values,
     separated by an empty line.  See `"ShowListTable"' in this node.

HTML
     The data is output as an HTML TABLE, suitable for display through a
     Web-client.  See `"ShowHTMLTable"' in this node.  Input can either be
     plain ASCII text, or text with embedded HTML elements, depending upon
     an argument or global parameter.

   The subroutines which perform these displays are listed below.

EXPORTED NAMES
==============

   This module exports the following subroutines:

     ShowDatabases    - show list of databases
     ShowTables       - show list of tables
     ShowColumns      - show table of column info
     ShowTable        - show a table of data
     ShowRow          - show a row from one or more columns
     ShowTableValue   - show a single column's value
     ShowBoxTable     - show a table of data in a box
     ShowListTable    - show a table of data in a list
     ShowSimpleTable  - show a table of data in a simple table
     ShowHTMLTable    - show a table of data using HTML
     PlainText	  - convert HTML text into plain text

   All of these subroutines, and others, are described in detail in the
following sections.

MODULES
=======

ShowTable
=========

   Format and display the contents of one or more rows of data.

     ShowTable { parameter => value, ... };

     ShowTable *\@titles*, *\@types*, *\@widths*, *\&row_sub* [,
*\&fmt_sub* [, $max_width ] [, *$show_mode* ] ];

   The ShowTable subroutine displays tabular data aligned in columns, with
headers.  ShowTable supports four *modes* of display: Box, Table, List,
and HTML.  Each mode is described separately below.

   The arguments to ShowTable may be given in one of two ways: as a
hashed-array, or by a combination of fixed order arguments, and some
package-global variable settings.  The hash-array parameters correspond to
the fixed arguments and the global-parameter settings.

   In the list below, both the hash-array parameter name and the
fixed-order argument name is given as the value.  In the case where there
is no fixed-order argument for a given parameter-value pair, then the
corresponding global variable name is given.

titles => *\@titles*
     A reference to an array of column names, or titles.  If a particular
     column name is null, then the string `Field_*num*' is used by
     default.  To have a column have no title, use the empty string.

types => *\@types*
     A reference to an array of types, one for each column.  These types
     are passed to the *fmt_sub* for appropriate formatting.  Also, if a
     column type matches the regexp "`/text|char|string/i'", then the
     column alignment will be left-justified, otherwise it will be
     right-justified.

`widths' => *\@widths*
     A reference to an array of column widths, which may be given as an
     integer, or as a string of the form: "width.*precision*".

`row_sub' => *\&row_sub*
     A reference to a subroutine which successively returns rows of values
     in an array.  It is called for two purposes, each described
     separately:

     * To fetch successive rows of data:

          @row = &$row_sub(0);

     When given a null, zero, or empty argument, the next row is returned.

     * To initialize or rewind the data traversal.

          $rewindable = &$row_sub(1);

     When invoked with a non-null argument, the subroutine should rewind
     its row pointer to start at the first row of data.  If the data which
     *row_sub* is traversing is not rewindable, it must return zero or
     null.  If the data is rewindable, a non-null, non-zero value should
     be returned.

     The *row_sub* must expect to be invoked once with a non-null argument,
     in order to discover whether or not the data is rewindable.  If the
     data cannot be rewound, *row_sub* will thereafter only be called with
     a zero argument.

     Specifically, *row_sub* subroutine is used in this manner:

          $rewindable = &$row_sub(1);
          if ($rewindable) {
              while ((@row = &$row_sub(0)), $#row >= 0) {
                  # examine lengths for optimal formatting
              }
              &$row_sub(1);   # rewind
          }
          while ((@row = &$row_sub(0)), $#row >= 0) {
              # format the data
          }

     The consequence of data that is not rewindable, a reasonably nice
     table will still be formatted, but it may contain fairly large
     amounts of whitespace for wide columns.

`fmtsub' => *\&fmt_sub*
     A reference to a subroutine which formats a value, according to its
     type, width, precision, and the current column width.  It is invoked
     either with a fixed list of arguments, or with a hash-array of
     parameter and value pairs.

          $string = &fmt_sub { I<parameter> => I<value>, ... };

          $string = &fmt_sub($value, $type, $max_width, $width, $precision)

     If *\&fmt_sub* is omitted, then a default subroutine, ShowTableValue,
     will be used, which will use Perl's standard string formatting rules.

     The arguments to *\&fmt_sub*, either as values passed in a fixed
     order, or as part of the parameter value pair, are described in the
     section on `"ShowTableValue' in this node below.

`max_width' => number,
     The maximum table width, including the table formatting characters.
     If not given, defaults to the global variable $Max_Table_Width;

`show_mode' => 'mode',
     The display mode of the output.  One of five strings: `'Box'',
     `'Table'', `'Simple'', `'List'', and `'HTML''.

ShowDatabases
=============

   Show a list of database names.

     ShowDatabases *\@dbnames*;

     ShowDatabases { 'data' => *\@dbnames*, parameter => value, ...};

   ShowDatabases is intended to be used to display a list of database
names, under the column heading of "Databases".  It is a special case
usage of ShowTable (and can thus be passed any parameter suitable for
ShowTable.

   The argument, *\@dbnames*, is a reference to an array of strings, used
as the values of the single column display.

ShowTables
==========

   Show an array of table names.

     ShowTables *\@tblnames*;

     ShowTables { 'data' => *\@tblnames*, parameter => value, ...};

   ShowTables is used to display a list of table names, under the column
heading of "Tables".  It is a special case usage of ShowTable, and can be
passed any `"ShowTable"' in this node argument parameter.

ShowColumns
===========

   Display a table of column names, types, and attributes.

     ShowColumns { parameter => values, ... };

     ShowColumns *\@columns*, *\@col_types*, *\@col_lengths*,
*\@col_attrs*;

   The ShowColumns subroutine displays a table of column names, types,
lengths, and other attributes in a nicely formatted table.  It is a
special case usage of ShowTable, and can be passed any argument suitable
for `"ShowTable"' in this node;

   The arguments are:

columns = *\@columns*
     An array of column names.  This provides the value for the first
     column of the output.

`col_types' = *\@col_types*
     An array of column types names.  This provides the value for the
     second column.

`col_lengths' = *\@col_lengths*
     An array of maximum lengths for corresponding columns.  This provides
     the value for the third column of the output.

`col_attrs' = *\@col_attrs*
     An array of column attributes array references (ie: an array of
     arrays).  The attributes array for the first column are at
     "*$col_attrs*-\>[0]".  The first attribute of the second column is
     "*$col_attrs*-\>[1][0]".

   The columns, types, lengths, and attributes are displayed in a table
with the column headings: "Column", "Type", "Length", and "Attributes".
This is a special case usage of ShowTable, and can be passed additional
arguments suitable for `"ShowTable"' in this node.

ShowBoxTable
============

   Show tabular data in a box.

     ShowBoxTable { parameter = value, ... };

     ShowBoxTable *\@titles*, *\@types*, *\@widths*, *\&row_sub*       [,
[ *\&fmt_sub* ] [, $max_width ] ];

   The ShowBoxTable displays tabular data in titled columns using a "box"
of ASCII graphics, looking something like this:

     +------------+----------+-----+----------+
     | Column1    | Column2  | ... | ColumnN  |
     +------------+----------+-----+----------+
     | Value11    | Value12  | ... | Value 1M |
     | Value21    | Value22  | ... | Value 2M |
     | Value31    | Value32  | ... | Value 3M |
     |  ...       |  ...     | ... |  ...     |
     | ValueN1    | ValueN2  | ... | Value NM |
     +------------+----------+-----+----------+

   The arguments are the same as with `"ShowTable"' in this node.  If the
*@titles* array is empty, the header row is omitted.

ShowSimpleTable
===============

   Display a table of data using a simple table format.

     ShowSimpleTable *\@titles*, *\@types*, *\@widths*, *\&row_sub* [,
*\&fmt_sub*];

     ShowSimpleTable { parameter => values, ... };

   The ShowSimpleTable subroutine formats data into a simple table of
aligned columns, in the following example:

     Column1  Column2  Column3
     -------  -------  -------
     Value1   Value2   Value3
     Value12  Value22  Value32

   Columns are auto-sized by the data's widths, plus two spaces between
columns.  Values which are too long for the maximum colulmn width are
wrapped within the column.

ShowHTMLTable
=============

   Display a table of data nicely using HTML tables.

     ShowHTMLTable { parameter => value, ... };

     ShowHTMLTable *\@titles*, *\@types*, *\@widths*, *\&row_sub* [,
*\&fmt_sub* [, $max_width [, *\%URL_Keys* [, *$no_escape* [,
*\@title_formats [, I<\@data_formats [, I<$table_attrs* ] ] ] ] ] ] ];

   The ShowHTMLTable displays one or more rows of columns of data using
the HTML `\<TABLE\'> feature.  In addition to the usual parameter arguments
of `"ShowTable"' in this node, the following parameter arguments are
defined:

`url_keys' => *\%URL_Keys*,
     This is a hash array of column names (titles) and corresponding base
     URLs.  The values of any column names or indexes occuring as keys in
     the hash array will be generated as hypertext anchors using the
     associated printf-like string as the base URL. Either the column name
     or the column index (beginning with 1) may be used as the hash key.

     In the string value, these macros can be substituted:

     "`%K'" is replaced with the column name.

     "`%V'" is replaced with the column value;

     "`%I'" is replaced with the column index.

     For example, if we define the array:

          $base_url = "http://www.$domain/cgi/lookup?col=%K?val=%V";
          %url_cols = ('Author' => $base_url,
          		 'Name'   => $base_url);

     Then, the values in the Author column will be generated with the
     following HTML text:

          <A HREF="http://www.$domain/cgi/lookup?col=Author?val=somevalue>somevalue</A>

     and the values in the Name column will be generated with the URL:

          <A HREF="http://www.$domain/cgi/lookup?col=Name?val=othervalue>othervalue</A>

     If this variable is not given, it will default to the global variable
     `\%URL_Keys'.

`no_escape' => boolean,
     Unless *$no_escape* is set, HTML-escaping is performed on the data
     values in order to properly display the special HTML formatting
     characters : '\<', '\>', and '&'.  If you wish to display data with
     embedded HTML text, you must set *$no_escape*.

     Enabling embedded HTML, turns on certain heuristics which enable the
     user to more completely define appearance of the table.  For instance,
     any `\<TR\'> tokens found embedded *anywhere* within a row of data
     will be placed at the front of the row, within the generated `\<TR\'>.

     Similarly, a row of data containing the `\<THEAD\'> or `\<TFOOT\'>
     tokens, and their closing counterparts, will begin and end,
     respectively a table header or footer data.

`title_formats' => *\@title_formats*,
`tformats' => *\@title_formats*,
     An array of HTML formatting elements for the column titles, one for
     each column.  Each array element is a list of one or more HTML
     elements, given as `\<ELEMENT\'> or plainly, `ELEMENT', and separated
     by a comma `','', semi-colon `';'', or vertical bar '|'.  Each given
     HTML element is prepended to the corresponding column title, in the
     order given.  The corresponding HTML closing elements are appended in
     the opposite order.

     For example, if *\@title_formats* contains the two elements:

          [ 'FONT SIZE=+2,BOLD', 'FONT COLOR=red,EM' ]

     then the text output for the title of the first column would be:

          <FONT SIZE=+2><BOLD>I<column_1_title></BOLD></FONT>

     If `title_formats' is omitted, the global variable *@Title_Formats*
     is used by default.

`data_formats' => *\@data_formats*,
`dformats' => *\@data_formats*,
     Similar to `title_formats', this array provides HTML formatting for
     the columns of each row of data.  If `data_formats' is omitted or
     null, then the global variable *\@Data_Formats* is used by default.

`table_attrs' => *$table_attrs*,
     This variable defines a string of attributes to be inserted within the
     `\<TABLE\'> token.  For example, if the user wishes to have no table
     border:

          ShowHTMLTable {
          	...
          	table_attrs => 'BORDER=0',
              ...
          };

ShowListTable
=============

   Display a table of data using a list format.

     ShowListTable { parameter => value, ... };

     ShowListTable *\@titles*, *\@types*, *\@widths*, *\&row_sub* [,
*\&fmt_sub* [, $max_width [, *$wrap_margin* ] ] ];

   The arguments for ShowListTable are the same as for `"ShowTable"' in
this node, except for those described next.

`max_width' = number,
`wrap_margin' = number,
     Lines are truncated, and wrapped when their length exceeds
     $max_width.  Wrapping is done on a word-basis, unless the resulting
     right margin exceeds *$wrap_margin*, in which case the line is simply
     truncated at the $max_width limit.

     The $max_width variable defaults to $Max_List_Width.  The
     *$wrap_margin* defaults to $List_Wrap_Margin.

   In List mode, columns (called "fields" in List mode) are displayed wth
a field name and value pair per line, with records being one or more
fields .  In other words, the output of a table would look something like
this:

     Field1_1: Value1_1
     Field1_2: Value1_2
     Field1_3: Value1_3
     ...
     Field1-N: Value1_M
     <empty line>
     Field2_1: Value2_1
     Field2_2: Value2_2
     Field2_3: Value2_3
     ...
     Field2_N: Value2_N
     ...
     FieldM_1: ValueM_1
     FieldM_2: ValueM_2
     ...
     FieldM_N: ValueM_N
     <empty line>
     <empty line>

   Characteristics of List mode:

   * two empty lines indicate the end of data.

   * An empty field (column) may be omitted, or may have a label, but no
     data.

   * A long line can be continue by a null field (column):

          Field2: blah blah blah
                : blah blah blah

   * On a continuation, the null field is an arbitrary number of leading
     white space, a colon ':', a single blank or tab, followed by the
     continued text.

   * Embedded newlines are indicated by the escape mechanism "\n".
     Similarly, embedded tabs are indicated with "\t", returns with "\r".

   * If the *@titles* array is empty, the field names "`Field_'*NN*" are
     used instead.

ShowRow
=======

   Fetch rows successively from one or more columns of data.

     ShowRow *$rewindflag*, *\$index*, *$col_array_1* [, *$col_array_2*,
...;]

   The ShowRow subroutine returns a row of data from one or more columns
of data.  It is designed to be used as a callback routine, within the
ShowTable routine.   It can be used to select elements from one or more
array reference arguments.

   If passed two or more array references as arguments, elements of the
arrays selected by $index are returned as the "row" of data.

   If a single array argument is passed, and each element of the array is
itself an array, the subarray is returned as the "row" of data.

   If the *$rewindflag* flag is set, then the $index pointer is reset to
zero, and "true" is returned (a scalar 1).  This indicates that the data
is rewindable to the ShowTable routines.

   When the *$rewindflag* is not set, then the current row of data, as
determined by $index is returned, and $index will have been incremented.

   An actual invocation (from ShowColumns) is:

     ShowTable \@titles, \@types, \@lengths,
         sub { &ShowRow( $_[0], \$current_row, $col_names, $col_types,
                         $col_lengths, \@col_attrs); };

   In the example above, after each invocation, the *$current_row* argument
will have been incremented.

ShowTableValue
==============

   Prepare and return a formatted representation of a value.  A value
argument, using its corresponding type, effective width, and precision is
formatted into a field of a given maximum width.

     *$fmt* = ShowTableValue $value, $type, $max_width, $width,
$precision, $showmode;

width => $width
$width
     The width of the current value.  If omittied, $max_width is assumed.

`precision' => $precision
$precision
     The number of decimal digits; zero is assumed if omittied.

value => $value
$value
     The value to be formatted.

$type
     The type name of the value; eg: `char', `varchar', int, etc.

`maxwidth' => $max_width
$max_width
     The maximum width of any value in the current value's column.  If
     $width is zero or null, $max_width is used by default.  $max_width is
     also used as a minimum width, in case $width is a smaller value.

$width
     The default width of the value, obtained from the width specification
     of the column in which this value occurs.

$precision
     The precision specification, if any, from the column width
     specification.

$showmode
     The mode of the output: one of "table", "list", "box", or "html".
     Currently, only the "html" mode is significant: it is used to avoid
     using HTML tokens as part of the formatted text and length
     calculations.

PlainText
=========

     *$plaintext* = *&PlainText*(*$htmltext*);

     *&PlainText*

   This function removes any HTML formatting sequences from the input
argument, or from $_ if no argument is given.  The resulting plain text is
returned as the result.

VARIABLES
=========

   The following variables may be set by the user to affect the display
(with the defaults enclosed in square brackets [..]):

$Show_Mode [Box]
     This is the default display mode when using ShowTable.  The
     environment variable, `$ENV{'SHOW_MODE'}', is used when this variable
     is null or the empty string.  The possible values for this variable
     are: `"Box"', `"List"', `"Table"', and `"HTML"'.  Case is
     insignificant.

$List_Wrap_Margin [2]
     This variable's value determines how large a margin to keep before
     wrarpping a long value's display in a column.  This value is only
     used in "List" mode.

$Max_List_Width [80]
     This variable, used in "List" mode, is used to determine how long an
     output line may be before wrapping it.  The environment variable,
     `$ENV{'COLUMNS'}', is used to define this value when it is null.

$Max_Table_Width ["]
     This variable, when set, causes all tables to have their columns
     scaled such that their total combined width does not exceed this
     value.  When this variable is not set, which is the default case,
     there is no maximum table width, and no scaling will be done.

$No_Escape ["]
     If set, allows embedded HTML text to be included in the data displayed
     in an HTML-formatted table.  By default, the HTML formatting
     characters ("<", ">", and "&") occuring in values are escaped.

%URL_Keys
     In HTML mode, this variable is used to recognize which columns are to
     be displayed with a corresponding hypertext anchor.  See
     `"ShowHTMLTable"' in this node for more details.

*@HTML_Elements*
     An array of HTML elements (as of HTML 3.0) used to recognize and
     strip for width calculations.

$HTML_Elements
     A regular expression string formed from the elements of
     *@HTML_Elements*.

INTERNAL SUBROUTINES
====================

get_params
==========

     my $args = *&get_params* *\@argv*, *\%params*, *\@arglist*;

   Given the *@argv* originally passed to the calling sub, and the hash of
named parameters as *%params*, and the array of parameter names in the
order expected for a pass-by-value invocation, set the values of each of
the variables named in *@vars*.

   If the only element of the *@argv* is a hash array, then set the
variables to the values of their corresponding parameters used as keys to
the hash array.  If the parameter is not a key of the *%params* hash, and
is not a key in the global hash *%ShowTableParams*, then an error is noted.

   When *@argv* has multiple elements, or is not a hash array, set each
variable, in the order given within *@arglist*, to the values from the
*@argv*, setting the variables named by each value in *%params*.

   Variables may given either by name or by reference.

   The result is a HASH array reference, either corresponding directly to
the HASH array passed as the single argument, or one created by
associating the resulting variable values to the parameter names
associated with the variable names.

html_formats
============

     (*$prefixes*,*$suffixes*) = html_formats *\@html_formats*;

   The *html_format* function takes an array reference of HTML formatting
elements *\@html_formats*, and builds two arrays of strings: the first:
*$prefixes*, is an array of prefixes containing the corresponding HTML
formatting elements from *\@html_formats*, and the second, *$suffixes*,
containing the appropriate HTML closing elements, in the opposite order.

   The result is designed to be used as prefixes and suffixes for the
corresponding titles and column values.

   The array *\@html_formats* contains lists of HTML formatting elements,
one for each column (either title or data).  Each array element is a list
of one or more HTML elements, either given in HTML syntax, or as a "plain"
name (ie: given as `\<ELEMENT\'> or plainly, `ELEMENT').  Multiple
elements are separated by a comma `',''.

   The resulting array of *$prefixes* contains the corresponding opening
elements, in the order given, with the proper HTML element syntax.  The
resulting array of *$suffixes* contains the closing elements, in the
opposite order given, with the proper HTML element syntax.

   For example, if *\@html_formats* contains the two elements:

     [ 'FONT SIZE=+2,BOLD', 'FONT COLOR=red,EM' ]

   then the resulting two arrays will be returned as:

     [ [ '<FONT SIZE=+2><BOLD>', '<FONT COLOR=red><EM>' ],
       [ '</FONT></BOLD>',	'</FONT></EM>' ] ]

calc_widths
===========

     ($num_cols, $widths, $precision, $max_widths) =   *&calc_widths*(
$widthspec, $titles, $rewindable,       $row_sub, $fmt_sub, $types,
$showmode,       $max_width);

DESCRIPTION
-----------

   calc_widths is a generalized subroutine used by all the ShowTable
variant subroutines to setup internal variables prior to formatting for
display.  *Calc_widths* handles the column width and precision analysis,
including scanning the data (if rewindable) for appropriate default values.

   The number of columns in the data is returned, as well as three arrays:
the declared column widths, the column precision values, and the maximum
column widths.

RETURN VALUES
-------------

$num_cols
     is the number of columns in the data.  If the data is not rewindable,
     this is computed as the maximum of the number of elements in the
     $widthspec array and the number of elements in the $titles array.
     When the data is rewindable, this is the maximum of the number of
     columns of each row of data.

$widths
     is the column widths array ref, without the precision specs (if any).
     Each column's width value is determined by the original $widthspec
     value and/or the maximum length of the formatted data for the column.

$precision
     is the precision component (if any) of the original $widthspec array
     ref.  If there was no original precision component from the
     $widthspec, and the data is rewindable, then the data is examined to
     determine the maximum default precision.

$max_widths
     is the ref to the array of maximum widths for the given columns.

ARGUMENTS
---------

$widthspec
     A reference to an array of column width (or length) values, each given
     as an integer, real number, or a string value of "width.*precision*".
     If a value is zero or null, the length of the corresponding
     formatted data (if rewindable) and column title length are used to
     determine a reasonable default.

     If a column's width portion is a positive, non-zero number, then the
     column will be this wide, regardless of the values lengths of the data
     in the column.

     If the column's width portion is given as a negative number, then the
     positive value is used as a minimum column width, with no limit on the
     maximum column width.  In other words, the column will be at least
     width characters wide.

     If the data is not rewindable, and a column's width value is null or
     zero, then the length of the column title is used.  This may cause
     severe wrapping of data in the column, if the column data lengths are
     much greater than the column title widths.

$titles
     The array ref to the column titles; used to determine the minimum
     acceptable width, as well as the default number of columns.  If the
     $titles array is empty, then the $widthspec array is used to
     determine the default number of columns.

$rewindable
     A flag indicating whether or not the data being formatted is
     rewindable.  If this is true, a pass over the data will be done in
     order to calculate the maximum lengths of the actual formatted data,
     using $fmt_sub (below), rather than just rely on the declared column
     lengths.  This allows for optimal column width adjustments (ie: the
     actual column widths may be less than the declared column widths).

     If it is not desired to have the column widths dynamically adjusted,
     then set the $rewindable argument to 0, even if the data is
     rewindable.

$row_sub
     The code reference to the subroutine which returns the data; invoked
     only if $rewindable is non-null.

$fmt_sub
     The subroutine used to determine the length of the data when
     formatted; if this is omitted or null, the length of the data is used
     by default.  The $fmt_sub is used only when the data is rewindable.

$types
     An array reference to the types of each of the value columns; used
     only when $fmt_sub is invoked.

$showmode
     A string indicating the mode of the eventual display; one of four
     strings: "box", "table", "list", and "html".  Used to adjust widths
     for formatting requirements.

$max_width
     The maximum width of the table being formatted.  If set, and the total
     sum of the individual columns exceeds this value, the column widths
     are scaled down uniformly.  If not set (null), no column width
     scaling is done.

putcell
=======

     *$wrapped* = *&putcell*( *\@cells*, $c, *$cell_width*, *\@prefix*,
*\@suffix*, *$wrap_flag* );

   Output the contents of an array cell at *$cell*[$c], causing text
longer than *$cell_width* to be saved for output on subsequent calls.
Prefixing the output of each cell's value is a string from the two-element
array *@prefix*.  Suffixing each cell's value is a string from the
two-element array *@suffix*.  The first element of either array is
selected when *$wrap_flag* is zero or null, or when there is no more text
in the current to be output.  The second element is selected when
*$wrap_flag* is non-zero, and when there is more text in the current cell
to be output.

   In the case of text longer than *$cell_width*, a non-zero value is
returned.

   Cells with undefined data are not output, nor are the prefix or suffix
strings.

center
======

   Center a string within a given width.

     $field = center $string, $width;

max
===

   Compute the maximum value from a list of values.

     *$max* = *&max*( *@values* );

min
===

   Compute the minum value from a list of values.

     *$min* = *&min*( *@values* );

max_length
==========

   Compute the maximum length of a set of strings in an array reference.

     *$maxlength* = *&max_length*( *\@array_ref* );

htmltext
========

   Translate regular text for output into an HTML document.  This means
certain characters, such as "&", ">", and "<" must be escaped.

     *$output* = *&htmltext*( *$input* [, *$allflag* ] );

   If *$allflag* is non-zero, then all characters are escaped.  Normally,
only the four HTML syntactic break characters are escaped.

out
===

   Print text followed by a newline.

     out *$fmt* [, *@text* ];

put
===

   Print text (without a trailing newline).

     out *$fmt* [, *@text* ];

AUTHOR
======

   Alan K. Stebbens <aks@sgi.com>

BUGS
====

   * Embedded HTML is how the user can insert formatting overrides.
     However, the HTML formatting techniques have not been given much
     consideration - feel free to provide constructive feedback.

Data type related to database tables, spreadsheets, CSV/TSV files, HTML table displays, etc.
********************************************************************************************

NAME
====

   Data::Table - Data type related to database tables, spreadsheets,
CSV/TSV files, HTML table displays, etc.

SYNOPSIS
========

     # some cool ways to use Table.pm
     use Data::Table;

     $header = ["name", "age"];
     $data = [
       ["John", 20],
       ["Kate", 18],
       ["Mike", 23]
     ]
     $t = new Data::Table($data, $header, 0);	# Construct a table object with
     					# $data, $header, $type=0 (consider
     					# $data as the rows of the table).
     print $t->csv;                        # Print out the table as a csv file.

     $t = Data::Table::fromCSV("aaa.csv");       # Read a csv file into a table oject
       print $t->html;                       # Diplay a 'portrait' HTML TABLE on web.

     use DBI;
     $dbh= DBI->connect("DBI:mysql:test", "test", "") or die $DBI::errstr;
     my $minAge = 10;
     $t = Data::Table::fromSQL($dbh, "select * from mytable where age >= ?", [$minAge]);
     					# Construct a table form an SQL
     					# database query.

     $t->sort("age", 0, 0);                # Sort by col 'age',numerical,descending
     print $t->html2;                      # Print out a 'landscape' HTML Table.

     $row = $t->delRow(2);			# Delete the third row (index=2).
     $t->addRow($row, 4);			# Add the deleted row back as fifth row.
     @rows = $t->delRows([0..2]);		# Delete three rows (row 0 to 2).
     $col = $t->delCol("age");		# Delete column 'age'.
     $t->addCol($col, "age",2);		# Add column 'age' as the third column
     @cols = $t->delCols(["name","phone","ssn"]);
     					# Delete 3 columns at the same time.

     $name =  $t->elm(2,"name");	        # Element access
     $t2=$t->subTable([1, 3..4],['age', 'name']);
     					# Extract a sub-table

     $t->rename("Entry", "New Entry");	# Rename column 'Entry' by 'New Entry'
     $t->replace("Entry", [1..$t->nofRow()], "New Entry");
     					# Replace column 'Entry' by an array of
     					# numbers and rename it as 'New Entry'
     $t->swap("age","ssn");		# Swap the positions of column 'age'
     					# with column 'ssn' in the table.

     $t->colMap('name', sub {return uc});  # Map a function to a column
     $t->sort('age',0,0,'name',1,0);	# Sort table first by the numerical
     					# column 'age' and then by the
     					# string column 'name' in descending
     					# order
     $t2=$t->match_pattern('$_->[0] =~ /^L/ && $_->[3]<0.2');
     					# Select the rows that matched the
     					# pattern specified
     $t2=$t->match_string('John');		# Select the rows that matches 'John'
     					# in any column

     $t2=$t->clone();			# Make a copy of the table.
     $t->rowMerge($t2);			# Merge two tables
     $t->colMerge($t2);

ABSTRACT
========

   This perl package uses perl5 objects to make it easy for manipulating
spreadsheet data among disk files, database, and Web publishing.

   A table object contains a header and a two-dimensional array of scalars.
Three class methods Data::Table::fromCSV, Data::Table::fromTSV, and
Data::Table::fromSQL allow users to create a table object from a CSV/TSV
file or a database SQL selection in a snap.

   Table methods provide basic access, add, delete row(s) or column(s)
operations, as well as more advanced sub-table extraction, table sorting,
record matching via keywords or patterns, table merging, and web
publishing.  Data::Table class also provides a straightforward interface
to other popular Perl modules such as DBI and GD::Graph.

   The current version of Table.pm is available at
http://www.geocities.com/easydatabase

   We use Data::Table instead of Table, because Table.pm has already been
used inside PerlQt module in CPAN.

INTRODUCTION
============

   A table object has three data members:

  1. $data: a reference to an array of array-references.  It's basically a
     reference to a two-dimensional array.

  2. $header: a reference to a string array. The array contains all the
     column names.

  3. $type = 1 or 0.  1 means that @$data is an array of table columns
     (fields) (column-based); 0 means that @$data is an array of table
     rows (records) (row-based);

        Row-based/Column-based are two internal implementations for a
table object.  E.g., if a spreadsheet consists of two columns lastname and
age.  In a row-based table, $data = [ ['Smith', 29], ['Dole', 32] ].  In a
column-based table, $data = [ ['Smith', 'Dole'], [29, 32] ].

   Two implementions have their pros and cons for different operations.
Row-based implementation is better for sorting and pattern matching, while
column-based one is better for adding/deleting/swapping columns.

   Users only need to specify the implementation type of the table upon its
creation via Data::Table::new, and can forget about it afterwards.
Implementation type of a table should be considered volital, because
methods switch table objects from one type into another internally.  Be
advised that row/column/element references gained via table::rowRef,
table::rowRefs, table::colRef, table::colRefs, or table::elmRef may become
stale after other method calls afterwards.

   For those who want to inherit from the Data::Table class, internal
method table::rotate is used to switch from one implementation type into
another.  There is an additional internal assistant data structure called
colHash in our current implementation. This hash table stores all column
names and their corresponding column index number as key-value pairs for
fast conversion. This gives users an option to use column name wherever a
column ID is expected, so that user don't have to use table::colIndex all
the time. E.g., you may say $t->rename('oldColName', 'newColName') instead
of $t->rename($t->colIndex('oldColName'), 'newColIdx').

DESCRIPTION
===========

Field Summary
-------------

data refto_arrayof_refto_array
     contains a two-dimensional spreadsheet data.

header refto_array
     contains all column names.

type 0/1
     0 is row-based, 1 is column-based, describe the orientation of @$data.

Package Variables
-----------------

$Data::Table::VERSION
@Data::Table::OK
     see table::match_string and table::match_pattern

     # =item $Data::Table::ID # #see Data::Table::fromSQL

Class Methods
-------------

   Syntax: return_type method_name ( [ parameter [ = default_value ]] [,
parameter [ = default_value ]] )

   If method_name starts with table::, this is an instance method, it can
be used as $t->method( parameters ), where $t is a table reference.

   If method_name starts with Data::Table::, this is a class method, it
should be called as   Data::Table::method, e.g., $t =
Data::Table::fromCSV("filename.csv").

   Convensions for local variables:

     colID: either a numerical column index or a column name;
     rowIdx: numerical row index;
     rowIDsRef: reference to an array of column IDs;
     rowIdcsRef: reference to an array of row indices;
     rowRef, colRef: reference to an array of scalars;
     data: ref_to_array_of_ref_to_array of data values;
     header: ref to array of column headers;
     table: a table object, a blessed reference.

Table Creation
--------------

table Data::Table::new ( $data = [], $header = [], $type = 0, $enforceCheck = 1)
     create a new table.  It returns a table object upon success, undef
     otherwise.  $data: points to the spreadsheet data.  $header: points
     to an array of column names. A column name must have at least one
     non-digit character.  $type: 0 or 1 for row-based/column-based
     spreadsheet.  $enforceCheck: 1/0 to turn on/off initial checking on
     the size of each row/column to make sure the data arguement indeed
     points to a valid structure.

table table::subTable ($rowIdcsRef, $colIDsRef)
     create a new table, which is a subset of the original.  It returns a
     table object.  $rowIdcsRef: points to an array of row indices.
     $colIDsRef: points to an array of column IDs.  The function make a
     copy of selected elements from the original table.  Undefined
     $rowIdcsRef or $colIDsRef is interrpreted as all rows or all columns.

table table::clone
     make a clone of the original.  It return a table object, equivalent
     to table::subTable(undef,undef).

table Data::Table::fromCSV ($name, $header = 1)
     create a table from a CSV file.  return a table object.  $name: the
     CSV file name.  $header: 0 or 1 to ignore/interrpret the first line
     in the file as column names, If it is set to 0, the default column
     names are "col1", "col2", ...

table table::fromCSVi ($name, $header = 1)
     Same as Data::Table::fromCSV. However, this is an instant method
     (that's what 'i' stands for), which can be inheritated.

table Data::Table::fromTSV ($name, $header = 1)
     create a table from a TSV file.  return a table object.  $name: the
     TSV file name.  $header: 0 or 1 to ignore/interrpret the first line
     in the file as column names, If it is set to 0, the default column
     names are "col1", "col2", ...

     Note: read "TSV FORMAT" section for details.

table table::fromTSVi ($name, $header = 1)
     Same as Data::Table::fromTSV. However, this is an instant method
     (that's what 'i' stands for), whic h can be inheritated.

table Data::Table::fromSQL ($dbh, $sql, $vars)
     create a table from the result of an SQL selection query.  It returns
     a table object upon success or undef otherwise.  $dbh: a valid
     database handler.  Typically $dbh is obtained from DBI->connect, see
     "Interface to Database" or DBI.pm.  $sql: an SQL query string.
     $vars: optional reference to an array of variable values, required if
     $sql contains '?'s which need to be replaced by the corresponding
     variable values upon execution, see DBI.pm for details.  Hint: in
     MySQL, Data::Table::fromSQL($dbh, 'show tables from test') will also
     create a valid table object.

table Data::Table::fromSQLi ($dbh, $sql, $vars)
     Same as Data::Table::fromSQL. However, this is an instant method
     (that's what 'i' stands for), whic h can be inheritated.

Table Access and Properties
---------------------------

int table::colIndex ($colID)
     translate a column name into its numerical position, the first column
     has index 0 as in as any perl array.  return -1 for invalid column
     names.

int table::nofCol
     return number of columns.

int table::nofRow
     return number of rows.

scalar table::elm ($rowIdx, $colID)
     return the value of a table element at [$rowIdx, $colID], undef if
     $rowIdx or $colID is invalid.

refto_scalar table::elmRef ($rowIdx, $colID)
     return the reference to a table element at [$rowIdx, $colID], to
     allow possible modification.  It returns undef for invalid $rowIdx or
     $colID.

refto_array table::header
     return an array of column names.

int table::type
     return the implementation type of the table (row-based/column-based)
     at the time, be aware that the type of a table should be considered
     as volital during method calls.

Table Formatting
----------------

string table::csv
     return a string corresponding to the CSV representation of the table.

string table::tsv
     return a string corresponding to the TSV representation of the table.

     Note: read "TSV FORMAT" section for details.

string table::html ($colors = ["#D4D4BF","#ECECE4","#CCCC99"],  			  $specs = {'name' => ", 'border => '1', ...})
     return a string corresponding to a 'Portrait'-style html-tagged table.
     $colors: a reference to an array of three color strings, used for
     backgrounds for table header, odd-row records, and even-row records,
     respectively.  A defaut color array ("#D4D4BF","#ECECE4","#CCCC99")
     will be used if $colors isn't defined.  $specs: a reference to a hash
     that specifies other attributes such as name, border, id, class, etc.
     for the TABLE tag.  The table is shown in the "Portrait" style, like
     in Excel.

string table::html2 ($colors = ["#D4D4BF","#ECECE4","#CCCC99"], 		 	   $specs = {'name' => ", 'border' => '1', ...})
     return a string corresponding to a "Landscape" html-tagged table.
     This is useful to present a table with many columns, but very few
     entries.  Check the above table::html for parameter descriptions.

Table Operations
----------------

int table::setElm ($rowIdx, $colID, $val)
     modify the value of a table element at [$rowIdx, $colID] to a new
     value $val.  It returns 1 upon success, undef otherwise.

int table::addRow ( $rowRef, $rowIdx = table::nofRow)
     add a new row ($rowRef points to the actual list of scalars), the new
     row will be referred as $rowIdx as the result. E.g., addRow($aRow, 0)
     will put the new row as the very first row.  By default, it appends a
     row to the end.  It returns 1 upon success, undef otherwise.

refto_array table::delRow ( $rowIdx )
     delete a row at $rowIdx. It will the reference to the deleted row.

refto_array table::delRows ( $rowIdcsRef )
     delete rows in @$rowIdcsRef. It will return an array of deleted rows
     upon success.

int table::addCol ($colRef, $colName, $colIdx = numCol)
     add a new column ($colRef points to the actual data), the new column
     will be referred as $colName or $colIdx as the result. E.g.,
     addCol($aCol, 'newCol', 0) will put the new column as the very first
     column.  By default, append a row to the end.  It will return 1 upon
     success or undef otherwise.

refto_array table::delCol ($colID)
     delete a column at $colID return the reference to the deleted column.

arrayof_refto_array table::delCols ($colIDsRef)
     delete a list of columns, pointed by $colIDsRef. It will return an
     array of deleted columns upon success.

refto_array table::rowRef ($rowIdx)
     return a reference to the row at $rowIdx upon success or undef
     otherwise.

refto_arrayof_refto_array table::rowRefs ($rowIdcsRef)
     return a reference to array of row references upon success, undef
     otherwise.

array table::row ($rowIdx)
     return a copy of the row at $rowIdx upon success or undef otherwise.

refto_hash table::rowHashRef ($rowIdx)
     return a reference to a hash, which contains a copy of the row at
     $rowIdx, upon success or undef otherwise. The keys in the hash are
     column names, and the values are corresponding elements in that row.
     The hash is a copy, therefore modifying the hash values doesn't
     change the original table.

refto_array table::colRef ($colID)
     return a reference to the column at $colID upon success.

refto_arrayof_refto_array table::colRefs ($colIDsRef)
     return a reference to array of column references upon success.

array table::col ($colID)
     return a copy to the column at $colID upon success or undef otherwise.

int table::rename ($colID, $newName)
     rename the column at $colID to a $newName (the newName must be valid,
     and should not be idential to any other existing column names).  It
     returns 1 upon success or undef otherwise.

refto_array table::replace ($oldColID, $newColRef, $newName)
     replace the column at $oldColID by the array pointed by $newColRef,
     and renamed it to $newName. $newName is optional if you don't want to
     rename the column.  It returns 1 upon success or undef otherwise.

int table::swap ($colID1, $colID2)
     swap two columns referred by $colID1 and $colID2.  It returns 1 upon
     success or undef otherwise.

int table::colMap ($colID, $fun)
     foreach element in column $colID, map a function $fun to it.  It
     returns 1 upon success or undef otherwise.  This is a handy way to
     format a column. E.g. if a column named URL contains URL strings,
     colMap("URL", sub {"<a href='$_'>$_</a>"}) before html() will change
     each URL into a clickable hyper link while displayed in a web browser.

int table::sort($colID1, $type1, $order1, $colID2, $type2, $order2, ... )
     sort a table in place.  First sort by column $colID1 in $order1 as
     $type1, then sort by $colID2 in $order2 as $type2, ...  $type is 0
     for numerical and 1 for others; $order is 0 for ascending and 1 for
     descending; Sorting is done in the priority of colID1, colID2, ...
     It returns 1 upon success or undef otherwise.  Notice the table is
     rearranged as a result! This is different from perl's list sort,
     which returns a sorted copy while leave the original list untouched,
     the authors feel inplace sorting is more natural.

table table::match_pattern ($pattern)
     return a new table consisting those rows evaluated to be true by
     $pattern upon success or undef otherwise.  Side effect:
     @Data::Table::OK stores a true/false array for the original table
     rows. Using it, users can find out what are the rows being
     selected/unselected.  In the $pattern string, a column element should
     be referred as $_->[$colIndex]. E.g., match_pattern('$_->[0]>3 &&
     $_->[1]=~/^L') retrieve all the rows where its first column is
     greater than 3 and second column starts with letter 'L'. Notice it
     only takes colIndex, column names are not acceptable here!

table table::match_string ($s, $caseIgnore)
     return a new table consisting those rows contains string $s in any of
     its fields upon success, undef otherwise. if $caseIgnore evaluated to
     true, case will is be ignored (s/$s/i).

     Side effect: @Data::Table::OK stores a true/false array for the
     original table rows.  Using it, users can find out what are the rows
     being selected/unselected.  The $s string is actually treated as a
     regular expression and applied to each row element, therefore one can
     actually specify several keywords by saying, for instance,
     match_string('One|Other').

Table-Table Manipulations
-------------------------

int table::rowMerge ($tbl)
     Append all the rows in the table object $tbl to the original rows.
     The merging table $tbl must have the same number of columns as the
     original.  It returns 1 upon success, undef otherwise.  The table
     object $tbl should not be used afterwards, since it becomes part of
     the new table.

int table::colMerge ($tbl)
     Append all the columns in table object $tbl to the original columns.
     Table $tbl must have the same number of rows as the original.  It
     returns 1 upon success, undef otherwise.  Table $tbl should not be
     used afterwards, since it becomes part of the new table.

Internal Methods
----------------

   All internal methods are mainly implemented for used by other methods
in the Table class. Users should avoid using them.  Nevertheless, they are
listed here for developers who would like to understand the code and may
derive a new class from Data::Table.

int table::rotate
     convert the internal structure of a table between row-based and
     column-based.  return 1 upon success, undef otherwise.

string csvEscape($rowRef)
     Encode an array of scalars into a CSV-formatted string.

refto_array parseCSV($string)
     Break a CSV encoded string to an array of scalars (check it out, we
     did it the cool way).

string tsvEscape($rowRef)
     Encode an array of scalars into a TSV-formatted string.

refto_array parseTSV($string)
     Break a TSV encoded string to an array of scalars (check it out, we
     did it the cool way).

TSV FORMAT
==========

   There is no standard for TSV format as far as we know. CSV format can't
handle binary data very well, therefore, we choose the TSV format to
overcome this limitation.

   We define TSV based on MySQL convention.

     "\0", "\n", "\t", "\r", "\b", "'", "\"", and "\\" are all escaped by '\' in the TSV file.
     (Warning: MySQL treats '\f' as 'f', and it's not escaped here)
     Undefined values are represented as '\N'.

INTERFACE TO OTHER SOFTWARES
============================

   Spreadsheet is a very generic type, therefore Data::Table class
provides an easy interface between databases, web pages, CSV/TSV files,
graphics packages, etc.

   Here is a summary (partially repeat) of some classic usages of
Data::Table.

Interface to Database and Web
-----------------------------

     use DBI;

     $dbh= DBI->connect("DBI:mysql:test", "test", "") or die $DBI::errstr;
     my $minAge = 10;
     $t = Data::Table::fromSQL($dbh, "select * from mytable where age >= ?", [$minAge]);
     print $t->html;

Interface to CSV/TSV
--------------------

     $t = fromCSV("mydata.csv");
     $t->sort(1,1,0);
     print $t->csv;

     Same for TSV

Interface to Graphics Package
-----------------------------

     use GD::Graph::points;

     $graph = GD::Graph::points->new(400, 300);
     $t2 = $t->match('$_->[1] > 20 && $_->[3] < 35.7');
     my $gd = $graph->plot($t->colRefs([0,2]));
     open(IMG, '>mygraph.png') or die $!;
     binmode IMG;
     print IMG $gd->png;
     close IMG;

AUTHOR
======

   Copyright 1998-2000, Yingyao Zhou & Guangzhou Zou. All rights reserved.

   It was first written by Zhou in 1998, significantly improved and
maintained by Zou since 1999. The authors thank Tong Peng and Yongchuang
Tao for valuable suggestions.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Please send bug reports and comments to: easydatabase@yahoo.com. When
sending bug reports, please provide the version of Table.pm, the version of
Perl.

SEE ALSO
========

     DBI, GD::Graph.

A tool for navigating through Perl data structures
**************************************************

NAME
====

   *Data::Walker* - A tool for navigating through Perl data structures

SYNOPSIS
========

   Without any explicit objects:

     use Data::Walker;
     Data::Walker->cli( $data_structure );

   Object-style invocation:

     use Data::Walker;
     my $w = new Data::Walker;
     $w->walk( $data_structure );
     $w->ls("-al");
     $w->pwd;
     $w->cli;

   Importing methods into the current package:

     use Data::Walker qw(:direct);
     walk $data_structure;
     ls "-al";
     pwd;
     cli;

DESCRIPTION
===========

   This module allows you to "walk" an arbitrary Perl data structure in
the same way that you can walk a directory tree from a UNIX command line.
It reuses familiar unix commands (such as "ls", "cd", "pwd") and applies
these to data structures.

   It has a command-line interface which behaves like a UNIX shell.  You
can also use object-style sytax to invoke the CLI commands from outside
the CLI.   Data::Walker objects are encapsulated, so that you can hop into
and out of a CLI without losing state, and you can have several
Data::Walker objects pointing at different structures.

   The main functions can also be imported and used directly from within
the Perl debugger's CLI.

INSTALLATION
============

   To install this package, just into the directory which you created by
untarring the package, and type the following:

     perl Makefile.PL
     make test
     make
     make install

   This will copy Walker.pm to your perl library directory for use by all
perl scripts.  You probably must be root to do this, unless you have
installed a personal copy of perl or you have write access to a Perl lib
directory.

USAGE
=====

   You open a command-line interface by invoking the cli() function.

     use Data::Walker;
     Data::Walker->cli( $data_structure );

   You can customize certain features, like so:

     use Data::Walker;
     $Data::Walker::Config{'skipdoublerefs'} = 0;
     Data::Walker->cli( $data_structure );

   If you prefer to use object-style notation, then you can use this
syntax to customize the settings.  You can invoke the walk() method
directly, our you can let the cli() method call walk() implicitly:

     use Data::Walker;
     my $w1 = new Data::Walker;
     $w1->walk( $data_structure );
     $w1->cli;

     my $w2 = new Data::Walker;
     $w2->cli( $data_structure );

     my $w3 = new Data::Walker( 'skipdoublerefs' => 0 );
     $w3->walk( $data_structure );
     $w3->cli();

     $w3->showrecursion(0);
     $w3->cli();

   You can also import most of the functions directly into the current
package.  This is especially useful from within the debugger (see the
example below).

     use Data::Walker qw(:direct);
     walk $data_structure;
     ls "-al";
     pwd;
     cli;

   When you use the :direct pragma and invoke the walk() function, a
Data::Walker object is implicitly created, and is available as
$Data::Walker::WALKER.

   Imagine a data structure like so:

     my $s = {

     a => [ 10, 20, "thirty" ],
     b => {
             "w" => "forty",
             "x" => "fifty",
             "y" => 60,
             "z" => \70,
     },
     c => sub { print "I'm a data structure!\n"; },
     d => 80,
     	};
     	$s->{e} = \$s->{d};

   Here is a sample CLI session examining this structure ('/>' is the
prompt):

     />
     /> ls -l
     a               ARRAY                     (3)
     b               HASH                      (4)
     c               CODE
     d               scalar                    80
     e               SCALAR                    80
     /> cd a
     /->{a}> ls -al
     ..              HASH                      (5)
     .               ARRAY                     (3)
     0               scalar                    10
     1               scalar                    20
     2               scalar                    'thirty'
     /->{a}> cd ../b
     /->{b}> ls -al
     ..              HASH                      (5)
     .               HASH                      (4)
     w               scalar                    'forty'
     x               scalar                    'fifty'
     y               scalar                    60
     z               SCALAR                    70
     /->{b}> cd ..
     /> dump b
     dump--> 'b'
     $b = {
       'x' => 'fifty',
       'y' => 60,
       'z' => \70,
       'w' => 'forty'
     };
     /> ls -al
     ..              HASH                      (5)
     .               HASH                      (5)
     a               ARRAY                     (3)
     b               HASH                      (4)
     c               CODE
     d               scalar                    80
     e               SCALAR                    80
     /> ! $cur->{d} += 3
     eval--> $cur->{d} += 3
     retv--> 83
     /> ls -al
     ..              HASH                      (5)
     .               HASH                      (5)
     a               ARRAY                     (3)
     b               HASH                      (4)
     c               CODE
     d               scalar                    83
     e               SCALAR                    83
     />

   Below is a sample debugger session examining this structure.

   Note that the walk() function returns a reference to the "cursor",
which is itself a reference to whatever is the "current directory," so to
speak.  The actual Data::Walker object iself is managed implicitly, and is
available as $Data::Walker::WALKER.  When you are finished, you can undef
this object directly, or use the unwalk() function, which does this for
you.  But if you saved a copy of the cursor, then you will need to undef
this on your own.

     (violet) ~/perl/walker/Data-Walker-0.18 > perl -d sample_db

     Loading DB routines from perl5db.pl version 1.0401
     Emacs support available.

     Enter h or `h h' for help.

     main::(sample:19):              d => 80,
       DB<1> n
     main::(sample:22):      $s->{e}      = \$s->{d};
       DB<1> n
     main::(sample:30):      1;
       DB<1> use Data::Walker qw(:direct)

     DB<2> $cur = walk $s

     DB<3> pwd
     	/
     DB<4> ls
     	a       b       c       d       e
     DB<5> lal
     	..              HASH                      (5)
     	.               HASH                      (5)
     	a               ARRAY                     (3)
     	b               HASH                      (4)
     	c               CODE
     	d               scalar                    80
     	e               SCALAR                    80
     DB<6> cd a
     	/->{a}
     DB<7> ll
     	0               scalar                    10
     	1               scalar                    20
     	2               scalar                    'thirty'
     DB<8> cd '../b'
     	/->{b}
     DB<9> lal
     	..              HASH                      (5)
     	.               HASH                      (4)
     	w               scalar                    'forty'
     	x               scalar                    'fifty'
     	y               scalar                    60
     	z               SCALAR                    70
     DB<10> cd '..'
     	/
     DB<11> dump b
     	dump--> 'b'
     	$b = {
     'x' => 'fifty',
     'y' => 60,
     'z' => \70,
     'w' => 'forty'
     	};
     DB<12> ll
     	a               ARRAY                     (3)
     	b               HASH                      (4)
     	c               CODE
     	d               scalar                    80
     	e               SCALAR                    80
     DB<13> $$cur->{d} += 3

     DB<14> ll
     	a               ARRAY                     (3)
     	b               HASH                      (4)
     	c               CODE
     	d               scalar                    83
     	e               SCALAR                    83
     DB<15>
     DB<16> pwd
     	/
     DB<17> cli
     	/> cd b
     	/->{b}> ls -l
     	w               scalar                    'forty'
     	x               scalar                    'fifty'
     	y               scalar                    60
     	z               SCALAR                    70
     	/->{b}> print y
     	60
     	/->{b}> print x
     	fifty
     	/->{b}> exit

     DB<18> pwd
     	/->{b}
     DB<19> ll
     	w               scalar                    'forty'
     	x               scalar                    'fifty'
     	y               scalar                    60
     	z               SCALAR                    70
     DB<20> unwalk

     DB<21> undef $cur

     DB<22>

   The following commands are available from within the CLI.  With these
commands, you can navigate around the data structure as if it were a
directory tree.

     cd <target>          like UNIX cd
     ls                   like UNIX ls (also respects options -a, -l)
     print <target>       prints the item as a scalar
     dump <target>        invokes Data::Dumper
     set <key> <value>    set configuration variables
     show <key>           show configuration variables
     ! or eval            eval arbitrary perl (careful!)
     help                 this help message
     help set             lists the available config variables

   For each session (or object) the following items can be configured:

     rootname        (default:  '/'    )  displays the root node
     refname         (default:  'ref'  )  displays embedded refs
     scalarname      (default: 'scalar')  displays simple scalars
     undefname       (default: 'undef' )  displays undefined scalars

     maxdepth        (default:   1 )  maximum dump-depth (Data::Dumper)
     indent          (default:   1 )  amount of indent (Data::Dumper)
     lscol1width     (default:  15 )  column widths for 'ls' displays
     lscol2width     (default:  25 )  column widths for 'ls' displays

     showrecursion   (default:   1 )  note recursion in the prompt
     showids         (default:   0 )  show ref id numbers in ls lists
     skipdoublerefs  (default:   1 )  hop over ref-to-refs during walks
     skipwarning     (default:   1 )  warn when hopping over ref-to-refs
     truncatescalars (default:  37 )  truncate scalars in 'ls' displays
     autoprint       (default:   1 )  print directory after chdir when not in CLI

     promptchar      (default:  '>')  customize the session prompt
     arrowshaft      (default:  '-')  ('-' in '->')
     arrowhead       (default:  '>')  ('>' in '->')

     curname         (default:  'cur'  )  how to refer to the cursor for evals
     parname         (default:  'par'  )  how to refer to the parent ref for evals

CHANGES
=======

   * Version 1.02-1.04
          Minor changes to installer tests.

   * Version 1.01
          Minor changes to the documentation.
          Added walker_http.pl, which is a library for using
          Data::Walker together with HTTP::Daemon to view objects
          with a Web browser.  Two example scripts are also included.

   * Version 0.21
          Minor changes to the documentation

   * Version 0.19-0.20
          Added new tests and updated the documentation.

   * Version 0.18
          Completely separated the CLI loop, command-parsing regexes,
          and the functions which implement the commands.  AUTOLOAD is now
          set up to handle any commands that the CLI can parse (except
          for eval() ).

          By using the :direct pragma, you can now import AUTOLOADed functions
          into the current package, so that you can easily invoke them
          from the perl debugger.

   * Version 0.16-0.17
          The Data::Walker objects are now fully encapsulated.

          NOTE:  The walk() function has been separated into two functions,
          namely walk() and cli(). The usage instructions have changed.
          Please have a look.

   * Version 0.15
          Reorganized the installation tests.
          A few minor changes to the module itself.

   * Version 0.13-0.14
          Moved some functionality from the CLI-loop
          into distinct functions.

   * Version 0.12
          Blessed references to non-hashes are now handled correctly.
          Modified the output of "ls" commands (looks different).
          Added new options:
             showids, lscol2width, scalarname, undefname,
             skipwarning
          Numerous internal changes.

   * Version 0.11
          Fixed some misspellings in the help information.
          Modified the pretty-print format of scalars.
          Added some new comments to the source code.
          Various other small updates.

THANKS
======

   Thanks to Gurusamy Sarathy for writing Data::Dumper, and to Dominique
Dumont for writing Tk::ObjScanner.

   Thanks to Matthew Persico for sending some ideas on how this module
might be useful in the debugger.

   Thanks to Scott Lindsey for pointing out that this module is useful for
reading files created with the Storable module, and for sending a sample
script to do this.

AUTHOR
======

   John Nolan  jpnolan@sonic.net  1999,2000.  A copyright statment is
contained within the source code itself.

Pivot (cross-tabulate) a table of data.
***************************************

NAME
====

   Data::Xtab - Pivot (cross-tabulate) a table of data.

DESCRIPTION
===========

   This module allows you to feed it tables of data to be pivoted in such
a way that they can be easily used in a report or graph. Here is an
example of input data:

     'A', 'JUN', 7
     'A', 'JAN', 4
     'B', 'JAN', 3
     'B', 'FEB', 39
     'C', 'MAY', 8
     'A', 'JUN', 100

   The output would be rendered as:

     JAN     FEB     MAR     APR     MAY     JUN
       A       4       0       0       0       0       107
       B       3       39      0       0       0       0
       C       0       0       0       0       8       0

   The first column in the table ends up becoming the data series. The
second column becomes the headers, under which the third column is summed.
If more than one data records for the same data series and header column
appear in the input data, the values are totalled for that intersection.

   This module was designed to be used in conjunction with the GIFGraph
module, but no doubt has other uses.

SYNOPSIS
========

     #!/usr/local/bin/perl

     use Data::Xtab;
     use GIFgraph::lines;
     use CGI;
     $query = new CGI;
     print $query->header("image/gif");

     my @data = ( ['A', 'FEB', 31],
                  ['A', 'FEB', 12],
                  ['A', 'MAR', 18],
                  ['A', 'MAR', 29],
                  ['A', 'APR', 142],
                  ['B', 'FEB', 217],
                  ['B', 'FEB', 14],
                  ['B', 'MAR', 121],
                  ['B', 'APR', 37],
                  ['C', 'MAR', 39],
                  ['C', 'MAR', 8],
                  ['C', 'APR', 100] );

     # The outputcols parameter is used to enumerate the
     # columns that should be used in the output table, and
     # more importantly, the order in which they should appear.
     #
     my @outputcols = ('JAN', 'FEB', 'MAR', 'APR');

     my $xtab = new Data::Xtab(\@data, \@outputcols);

     my @graph_data = $xtab->graph_data;

     $my_graph = new GIFgraph::lines();

     $my_graph->set( 'x_label' => 'Month',
                     'y_label' => 'Sales',
                     'title' => 'Monthly Sales',
                     'y_max_value' => 450,
                     'y_tick_number' => 5,
                     'y_label_skip' => 2 );
     print $my_graph->plot( \@graph_data );

AUTHOR
======

   Copyright (c) 1997, Brian Jepson You may distribute this kit under the
same terms as Perl itself.

fast calendar and business date calculations
********************************************

NAME
====

     Date::Business - fast calendar and business date calculations

SYNOPSIS
========

     All arguments to the Date::Business constructor are optional.

     # simplest case, default is today's date (localtime)
     $d = new Date::Business();

     # initialize with date string,
     # offset in business days is optional
     $d = new Date::Business(DATE => '19991124' [, OFFSET => <integer>]);

     # initialize with another Date::Business object
     # offset in business days is optional
     $x = new Date::Business(DATE => $d [, OFFSET => <integer>]);

     # initialize with holiday function (see Holidays, below)
     $d = new Date::Business(HOLIDAY => \&holiday);

     # force weekends/holidays to the previous or next business day
     $d = new Date::Business(FORCE => 'prev'); # Friday (usually)
     $d = new Date::Business(FORCE => 'next'); # Monday (usually)

     $d->image(); # returns YYYYMMDD string
     $d->value(); # returns Unix time as integer

     $d->day_of_week();     # 0 = Sunday

     $d->datecmp($x);       # are two dates equal?
     $d->eq($x);            # synonym for datecmp
     $d->lt($x);            # less than
     $d->gt($x);            # greater than

     Calendar date functions
     $d->next();         # next calendar day
     $d->prev();         # previous calendar day
     $d->add(<offset>);  # adds n calendar days
     $d->sub(<offset>);  # subtracts n calendar days
     $d->diff($x);       # difference between two dates

     Business date functions
     $d->nextb();        # next business day
     $d->prevb();        # previous business day
     $d->addb(<offset>); # adds n business days
     $d->subb(<offset>); # subtracts n business days
     $d->diffb($x);      # difference between two business dates
     $d->diffb($x, 'next'); # treats $d weekend/holiday as next business date
     $d->diffb($x, 'next', 'next'); # treats $x weekend/holiday as above

DESCRIPTION
===========

   Date::Business provides the functionality to perform simple date
manipulations quickly. Support for calendar date and business date math is
provided.

   Business dates are weekdays only. Adding 1 to a weekend returns Monday,
subtracting 1 returns Friday.

   The difference in business days between Friday and the following Monday
(using the diffb function) is one business day. The number of business
days between Friday and the following Monday (using the betweenb function)
is zero.

EXAMPLE
=======

   Date::Business works very well for iterating over dates, and
determining start and end dates of arbitray n business day periods (e.g.
consider how to perform a computation for a series of business days
starting from an arbitrary day).

   $end   = new Date::Business(); # today  # 10 business days ago  $start
= new Date::Business(DATE => $end, OFFSET => -10);

     while (!$start->gt($end)) {
       compute_something($start);
       $start->nextb();
     }

HOLIDAYS
========

   Optionally, a reference to a function that counts the number of
holidays in a given date range can be passed. Business date addition,
subtraction, and difference functions will consider holidays.

   Sample holiday function:

     # MUST BE NON-WEEKEND HOLIDAYS !!!
     sub holiday($$) {
        my($start, $end) = @_;

        my($numHolidays) = 0;
        my($holiday, @holidays);

        push @holidays, '19981225'; # Christmas
        push @holidays, '19990101'; $ New Year's

        foreach $holiday (@holidays) {
     	$numHolidays++ if ($start le $holiday && $end ge $holiday);
        }
        return $numHolidays;
     }

   Example using the holiday function:

     # 10 business days after 21 DEC 1998, where
     # 25 DEC 1998 and 01 JAN 1999 are holidays
     #
     $d = new Date::Business(DATE    => '19981221',
                             OFFSET  => 10,
                             HOLIDAY => \&holiday);

     print $d->image."\n"; # prints 19990106

The diffb() function explained
==============================

   The difference between two business days is relatively straightforward
when the operands are business days. The difference (in business days)
between two days when one or both of those days is a weekend or holiday is
ambiguous. The 'next' and 'prev' parameters are used to resolve the
ambiguity.

   The first parameter to the diffb function is the other date. The second
parameter indicates that 'self' is to be treated as the previous or next
business date if it is not a business date. The third parameter is similar
to the second parameter but applies to the 'other' date. The default
behavior is treat both dates as if the 'prev' option was set.

   For example:

     $d = new Date::Business(DATE => '19991225'); # saturday
     $x = new Date::Business(DATE => '19991225'); # saturday
     print $d->image;                     # prints 19991225
     print $d->diffb($x);                 # prints  0
     print $d->diffb($x, 'prev', 'next'); # prints -1
     print $d->diffb($x, 'next', 'prev'); # prints  1
     print $d->diffb($x, 'next', 'next'); # prints  0

CAVEATS
=======

   Business dates may be initialized with values in the range of
'19700101' through '20380119'. The range of valid results are '19011213'
through '20380119'.

   Computations on dates that exceed the maximum value will wrap around.
(i.e. the day after '20380119' is '19011214'). Computations that exceed
the minimum value will result in the minimum value. (i.e. the day before
'19011213' is '19011213')

Gregorian calendar date calculations
************************************

NAME
====

   Date::Calc - Gregorian calendar date calculations

PREFACE
=======

   This package consists of a C library and a Perl module (which uses the
C library, internally) for all kinds of date calculations based on the
Gregorian calendar (the one used in all western countries today), thereby
complying with all relevant norms and standards: ISO/R 2015-1971, DIN 1355
and, to some extent, ISO 8601 (where applicable).

   (See also http://www.engelschall.com/u/sb/download/Date-Calc/DIN1355/
for a scan of part of the "DIN 1355" document (in German)).

   The module of course handles year numbers of 2000 and above correctly
("Year 2000" or "Y2K" compliance) - actually all year numbers from 1 to
the largest positive integer representable on your system (which is at
least 32767) can be dealt with.

   Note that this package projects the Gregorian calendar back until the
year 1 A.D. - even though the Gregorian calendar was only adopted in 1582
by most (not all) European countries, in obedience to the corresponding
decree of catholic pope Gregor I in that year.

   Some (mainly protestant) countries continued to use the Julian calendar
(used until then) until as late as the beginning of the 20th century.

   Finally, note that this package is not intended to do everything you
could ever imagine automagically for you; it is rather intended to serve
as a toolbox (in the best of UNIX spirit and traditions) which should,
however, always get you where you want to go.

   See the section "RECIPES" at the bottom of this document for solutions
to common problems!

   If nevertheless you can't figure out how to solve a particular problem,
please let me know! (See e-mail address at the end of this document.)

SYNOPSIS
========

     use Date::Calc qw(
         Days_in_Year
         Days_in_Month
         Weeks_in_Year
         leap_year
         check_date
         check_business_date
         Day_of_Year
         Date_to_Days
         Day_of_Week
         Week_Number
         Week_of_Year
         Monday_of_Week
         Nth_Weekday_of_Month_Year
         Standard_to_Business
         Business_to_Standard
         Delta_Days
         Delta_DHMS
         Add_Delta_Days
         Add_Delta_DHMS
         Add_Delta_YMD
         System_Clock
         Today
         Now
         Today_and_Now
         Easter_Sunday
         Decode_Month
         Decode_Day_of_Week
         Decode_Language
         Decode_Date_EU
         Decode_Date_US
         Compress
         Uncompress
         check_compressed
         Compressed_to_Text
         Date_to_Text
         Date_to_Text_Long
         English_Ordinal
         Calendar
         Month_to_Text
         Day_of_Week_to_Text
         Day_of_Week_Abbreviation
         Language_to_Text
         Language
         Languages
         Decode_Date_EU2
         Decode_Date_US2
         Parse_Date
     );

     use Date::Calc qw(:all);

     Days_in_Year
         $days = Days_in_Year($year,$month);

     Days_in_Month
         $days = Days_in_Month($year,$month);

     Weeks_in_Year
         $weeks = Weeks_in_Year($year);

     leap_year
         if (leap_year($year))

     check_date
         if (check_date($year,$month,$day))

     check_business_date
         if (check_business_date($year,$week,$dow))

     Day_of_Year
         $doy = Day_of_Year($year,$month,$day);

     Date_to_Days
         $days = Date_to_Days($year,$month,$day);

     Day_of_Week
         $dow = Day_of_Week($year,$month,$day);

     Week_Number
         $week = Week_Number($year,$month,$day);

     Week_of_Year
         ($week,$year) = Week_of_Year($year,$month,$day);

     Monday_of_Week
         ($year,$month,$day) = Monday_of_Week($week,$year);

     Nth_Weekday_of_Month_Year
         if (($year,$month,$day) =
         Nth_Weekday_of_Month_Year($year,$month,$dow,$n))

     Standard_to_Business
         ($year,$week,$dow) =
         Standard_to_Business($year,$month,$day);

     Business_to_Standard
         ($year,$month,$day) =
         Business_to_Standard($year,$week,$dow);

     Delta_Days
         $Dd = Delta_Days($year1,$month1,$day1,
                          $year2,$month2,$day2);

     Delta_DHMS
         ($Dd,$Dh,$Dm,$Ds) =
         Delta_DHMS($year1,$month1,$day1, $hour1,$min1,$sec1,
                    $year2,$month2,$day2, $hour2,$min2,$sec2);

     Add_Delta_Days
         ($year,$month,$day) =
         Add_Delta_Days($year,$month,$day,
                        $Dd);

     Add_Delta_DHMS
         ($year,$month,$day, $hour,$min,$sec) =
         Add_Delta_DHMS($year,$month,$day, $hour,$min,$sec,
                        $Dd,$Dh,$Dm,$Ds);

     Add_Delta_YMD
         ($year,$month,$day) =
         Add_Delta_YMD($year,$month,$day,
                       $Dy,$Dm,$Dd);

     System_Clock
         ($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
         System_Clock();

     Today
         ($year,$month,$day) = Today();

     Now
         ($hour,$min,$sec) = Now();

     Today_and_Now
         ($year,$month,$day, $hour,$min,$sec) = Today_and_Now();

     Easter_Sunday
         ($year,$month,$day) = Easter_Sunday($year);

     Decode_Month
         if ($month = Decode_Month($string))

     Decode_Day_of_Week
         if ($dow = Decode_Day_of_Week($string))

     Decode_Language
         if ($lang = Decode_Language($string))

     Decode_Date_EU
         if (($year,$month,$day) = Decode_Date_EU($string))

     Decode_Date_US
         if (($year,$month,$day) = Decode_Date_US($string))

     Compress
         $date = Compress($year,$month,$day);

     Uncompress
         if (($century,$year,$month,$day) = Uncompress($date))

     check_compressed
         if (check_compressed($date))

     Compressed_to_Text
         $string = Compressed_to_Text($date);

     Date_to_Text
         $string = Date_to_Text($year,$month,$day);

     Date_to_Text_Long
         $string = Date_to_Text_Long($year,$month,$day);

     English_Ordinal
         $string = English_Ordinal($number);

     Calendar
         $string = Calendar($year,$month);

     Month_to_Text
         $string = Month_to_Text($month);

     Day_of_Week_to_Text
         $string = Day_of_Week_to_Text($dow);

     Day_of_Week_Abbreviation
         $string = Day_of_Week_Abbreviation($dow);

     Language_to_Text
         $string = Language_to_Text($lang);

     Language
         $lang = Language();
         Language($lang);
         $oldlang = Language($newlang);

     Languages
         $max_lang = Languages();

     Decode_Date_EU2
         if (($year,$month,$day) = Decode_Date_EU2($string))

     Decode_Date_US2
         if (($year,$month,$day) = Decode_Date_US2($string))

     Parse_Date
         if (($year,$month,$day) = Parse_Date($string))

     Version
         $string = Date::Calc::Version();

IMPORTANT NOTES
===============

   (See the section "RECIPES" at the bottom of this document for solutions
to common problems!)

   * "Year 2000" ("Y2K") compliance

     The upper limit for any year number in this module is only given by
     the size of the largest positive integer that can be represented in a
     variable of the C type "int" on your system, which is at least 32767,
     according to the ANSI C standard (exceptions see below).

     In order to simplify calculations, this module projects the gregorian
     calendar back until the year 1 A.D. - i.e., back *BEYOND* the year
     1582 when this calendar was first decreed by the catholic pope
     Gregor I!

     Therefore, *BE SURE TO ALWAYS SPECIFY "1998" WHEN YOU MEAN "1998"*,
     for instance, and *DO NOT WRITE "98" INSTEAD*, because this will in
     fact perform a calculation based on the year "98" A.D. and *NOT*
     "1998"!

     The only exceptions from this rule are the functions which contain
     the word "compress" in their names (which only handle years between
     1970 and 2069 and also accept the abbreviations "00" to "99"), and
     the functions whose names begin with "Decode_Date_" (which map year
     numbers below 100 to the range 1970 - 2069, using a technique known
     as "windowing").

   * First index

     ALL ranges in this module start with "1", *NOT* "0"!

     I.e., the day of month, day of week, day of year, month of year, week
     of year, first valid year number and language ALL start counting at
     one, *NOT* zero!

     The only exception is the function "`Week_Number()'", which may in
     fact return "0" when the given date actually lies in the last week of
     the PREVIOUS year.

   * Function naming conventions

     Function names completely in lower case indicate a boolean return
     value.

   * Boolean values

     Boolean values in this module are always a numeric zero ("0") for
     "false" and a numeric one ("1") for "true".

   * Exception handling

     The functions in this module will usually die with a corresponding
     error message if their input parameters, intermediate results or
     output values are out of range.

     The following functions handle errors differently:

          -  check_date()
          -  check_business_date()
          -  check_compressed()

     (which return a "false" return value when the given input does not
     represent a valid date),

          -  Nth_Weekday_of_Month_Year()

     (which returns an empty list if the requested 5th day of week does
     not exist),

          -  Decode_Month()
          -  Decode_Day_of_Week()
          -  Decode_Language()
          -  Compress()

     (which return "0" upon failure or invalid input), and

          -  Decode_Date_EU()
          -  Decode_Date_US()
          -  Decode_Date_EU2()
          -  Decode_Date_US2()
          -  Parse_Date()
          -  Uncompress()

     (which return an empty list upon failure or invalid input).

     Note that you can always catch an exception thrown by any of the
     functions in this module and handle it yourself by enclosing the
     function call in an "eval" with curly brackets and checking the
     special variable "`$@'" (see `perlfunc(1)' in this node for details).

DESCRIPTION
===========

   * `use Date::Calc qw( Days_in_Year Days_in_Month ... );'

   * `use Date::Calc qw(:all);'

     You can either specify the functions you want to import explicitly by
     enumerating them between the parentheses of the "`qw()'" operator, or
     you can use the ":all" tag instead to import ALL available functions.

   * `$days = Days_in_Year($year,$month);'

     This function returns the sum of the number of days in the months
     starting with January up to and including "$month" in the given year
     "$year".

     I.e., "`Days_in_Year(1998,1)'" returns "31", "`Days_in_Year(1998,2)'"
     returns "59", "`Days_in_Year(1998,3)'" returns "90", and so on.

     Note that "`Days_in_Year($year,12)'" returns the number of days in the
     given year "$year", i.e., either "`365'" or "`366'".

   * `$days = Days_in_Month($year,$month);'

     This function returns the number of days in the given month "$month"
     of the given year "$year".

     The year must always be supplied, even though it is only needed when
     the month is February, in order to determine wether it is a leap year
     or not.

     I.e., "`Days_in_Month(1998,1)'" returns "31",
     "`Days_in_Month(1998,2)'" returns "28", "`Days_in_Month(2000,2)'"
     returns "29", "`Days_in_Month(1998,3)'" returns "31", and so on.

   * `$weeks = Weeks_in_Year($year);'

     This function returns the number of weeks in the given year "$year",
     i.e., either "52" or "53".

   * `if (leap_year($year))'

     This function returns "true" ("1") if the given year "$year" is a
     leap year and "false" ("0") otherwise.

   * `if (check_date($year,$month,$day))'

     This function returns "true" ("1") if the given three numerical
     values "$year", "$month" and "$day" constitute a valid date, and
     "false" ("0") otherwise.

   * `if (check_business_date($year,$week,$dow))'

     This function returns "true" ("1") if the given three numerical
     values "$year", "`$week'" and "`$dow'" constitute a valid date in
     business format, and "false" ("0") otherwise.

     *Beware* that this function does *NOT* compute wether a given date is
     a business day (i.e., Monday to Friday)!

     To do so, use "`(Day_of_Week($year,$month,$day) < 6)'" instead.

   * `$doy = Day_of_Year($year,$month,$day);'

     This function returns the (relative) number of the day of the given
     date in the given year.

     E.g., "`Day_of_Year($year,1,1)'" returns "1",
     "`Day_of_Year($year,2,1)'" returns "32", and
     "`Day_of_Year($year,12,31)'" returns either "`365'" or "`366'".

   * `$days = Date_to_Days($year,$month,$day);'

     This function returns the (absolute) number of the day of the given
     date, where counting starts at the 1st of January of the year 1 A.D.

     I.e., "`Date_to_Days(1,1,1)'" returns "1", "`Date_to_Days(1,12,31)'"
     returns "`365'", "`Date_to_Days(2,1,1)'" returns "`366'",
     "`Date_to_Days(1998,5,1)'" returns "`729510'", and so on.

   * `$dow = Day_of_Week($year,$month,$day);'

     This function returns the number of the day of week of the given date.

     The function returns "1" for Monday, "2" for Tuesday and so on until
     "7" for Sunday.

     Note that in the Hebrew calendar (on which the Christian calendar is
     based), the week starts with Sunday and ends with the Sabbath or
     Saturday (where according to the Genesis (as described in the Bible)
     the Lord rested from creating the world).

     In medieval times, catholic popes have decreed the Sunday to be the
     official day of rest, in order to dissociate the Christian from the
     Hebrew belief.

     Nowadays, the Sunday AND the Saturday are commonly considered (and
     used as) days of rest, usually referred to as the "week-end".

     Consistent with this practice, current norms and standards (such as
     ISO/R 2015-1971, DIN 1355 and ISO 8601) define the Monday as the
     first day of the week.

   * `$week = Week_Number($year,$month,$day);'

     This function returns the number of the week the given date lies in.

     If the given date lies in the *LAST* week of the PREVIOUS year, "0"
     is returned.

     If the given date lies in the FIRST week of the NEXT year,
     "`Weeks_in_Year($year) + 1'" is returned.

   * `($week,$year) = Week_of_Year($year,$month,$day);'

     This function returns the number of the week the given date lies in,
     as well as the year that week belongs to.

     I.e., if the given date lies in the *LAST* week of the PREVIOUS year,
     "`(Weeks_in_Year($year-1), $year-1)'" is returned.

     If the given date lies in the FIRST week of the NEXT year, "`(1,
     $year+1)'" is returned.

     Otherwise, "`(Week_Number($year,$month,$day), $year)'" is returned.

   * `($year,$month,$day) = Monday_of_Week($week,$year);'

     This function returns the date of the first day of the given week,
     i.e., the Monday.

     "$year" must be greater than or equal to "1", and "`$week'" must lie
     in the range "1" to "`Weeks_in_Year($year)'".

     Note that you can write "`($year,$month,$day) =
     Monday_of_Week(Week_of_Year($year,$month,$day));'" in order to
     calculate the date of the Monday of the same week as the given date.

   * `if (($year,$month,$day) =
     Nth_Weekday_of_Month_Year($year,$month,$dow,$n))'

     This function calculates the date of the "$n"th day of week "`$dow'"
     in the given month "$month" and year "$year"; such as, for example,
     the 3rd Thursday of a given month and year.

     This can be used to send a notification mail to the members of a group
     which meets regularly on every 3rd Thursday of a month, for instance.

     (See the section "RECIPES" near the end of this document for a code
     snippet to actually do so.)

     "$year" must be greater than or equal to "1", "$month" must lie in
     the range "1" to "12", "`$dow'" must lie in the range "1" to "7" and
     "$n" must lie in the range "1" to "5", or a fatal error (with
     appropriate error message) occurs.

     The function returns an empty list when the 5th of a given day of week
     does not exist in the given month and year.

   * `($year,$week,$dow) = Standard_to_Business($year,$month,$day);'

     This function converts a given date from standard notation (year,
     month, day (of month)) to business notation (year, week, day of week).

   * `($year,$month,$day) = Business_to_Standard($year,$week,$dow);'

     This function converts a given date from business notation (year,
     week, day of week) to standard notation (year, month, day (of month)).

   * `$Dd = Delta_Days($year1,$month1,$day1, $year2,$month2,$day2);'

     This function returns the difference in days between the two given
     dates.

     The result is positive if the two dates are in chronological order,
     i.e., if date #1 comes chronologically *BEFORE* date #2, and negative
     if the order of the two dates is reversed.

     The result is zero if the two dates are identical.

   * `($Dd,$Dh,$Dm,$Ds) = Delta_DHMS($year1,$month1,$day1,
     $hour1,$min1,$sec1, $year2,$month2,$day2, $hour2,$min2,$sec2);'

     This function returns the difference in days, hours, minutes and
     seconds between the two given dates with times.

     All four return values will be positive if the two dates are in
     chronological order, i.e., if date #1 comes chronologically *BEFORE*
     date #2, and negative (in all four return values!) if the order of
     the two dates is reversed.

     This is so that the two functions "`Delta_DHMS()'" and
     "`Add_Delta_DHMS()'" (description see further below) are
     complementary, i.e., mutually inverse:

          Add_Delta_DHMS(@date1,@time1, Delta_DHMS(@date1,@time1, @date2,@time2))

     yields "`(@date2,@time2)'" again, whereas

          Add_Delta_DHMS(@date2,@time2,
              map(-$_, Delta_DHMS(@date1,@time1, @date2,@time2)))

     yields "`(@date1,@time1)'", and

          Delta_DHMS(@date1,@time1, Add_Delta_DHMS(@date1,@time1, @delta))

     yields "`@delta'" again.

     The result is zero (in all four return values) if the two dates and
     times are identical.

   * `($year,$month,$day) = Add_Delta_Days($year,$month,$day, $Dd);'

     This function has two principal uses:

     First, it can be used to calculate a new date, given an initial date
     and an offset (which may be positive or negative) in days, in order
     to answer questions like "today plus 90 days - which date gives
     that?".

     (In order to add a weeks offset, simply multiply the weeks offset with
     "7" and use that as your days offset.)

     Second, it can be used to convert the canonical representation of a
     date, i.e., the number of that day (where counting starts at the 1st
     of January in 1 A.D.), back into a date given as year, month and day.

     Because counting starts at "1", you will actually have to subtract "1"
     from the canonical date in order to get back the original date:

          $canonical = Date_to_Days($year,$month,$day);

          ($year,$month,$day) = Add_Delta_Days(1,1,1, $canonical - 1);

     Moreover, this function is the inverse of the function
     "`Delta_Days()'":

          Add_Delta_Days(@date1, Delta_Days(@date1, @date2))

     yields "`@date2'" again, whereas

          Add_Delta_Days(@date2, -Delta_Days(@date1, @date2))

     yields "`@date1'", and

          Delta_Days(@date1, Add_Delta_Days(@date1, $delta))

     yields "`$delta'" again.

   * `($year,$month,$day, $hour,$min,$sec) =
     Add_Delta_DHMS($year,$month,$day, $hour,$min,$sec, $Dd,$Dh,$Dm,$Ds);'

     This function serves to add a days, hours, minutes and seconds offset
     to a given date and time, in order to answer questions like "today
     and now plus 7 days but minus 5 hours and then plus 30 minutes, what
     date and time gives that?":

          ($y,$m,$d,$H,$M,$S) = Add_Delta_DHMS(Today_and_Now(), +7,-5,+30,0);

   * `($year,$month,$day) = Add_Delta_YMD($year,$month,$day, $Dy,$Dm,$Dd);'

     This function serves to add a years, months and days offset to a
     given date.

     (In order to add a weeks offset, simply multiply the weeks offset
     with "7" and add this number to your days offset.)

     Note that the three offsets for years, months and days are applied
     separately from each other, in reverse order.

     (This also allows them to have opposite signs.)

     In other words, first the days offset is applied (using the function
     "`Add_Delta_Days()'", internally), then the months offset, and finally
     the years offset.

     If the resulting date happens to fall on a day beyond the end of the
     resulting month, like the 31st of April or the 29th of February (in
     non-leap years), then the day is replaced by the last valid day of
     that month in that year (e.g., the 30th of April or 28th of February).

     *BEWARE* that this behaviour differs from that of previous versions
     of this module!

     (Formerly, only the 29th of February in non-leap years was checked for
     (which - in contrast to the current version - was replaced by the 1st
     of March). Other possible invalid dates were not checked (and returned
     unwittingly), constituting a severe bug of previous versions.)

     *BEWARE* also that because of this replacement, but even more because
     a year and a month offset is not equivalent to a fixed number of days,
     the transformation performed by this function is *NOT REVERSIBLE*!

     This is in contrast to the functions "`Add_Delta_Days()'" and
     "`Add_Delta_DHMS()'", which for this very reason have inverse
     functions (namely "`Delta_Days()'" and "`Delta_DHMS()'"), whereas
     there exists no inverse for this function.

     Note that for this same reason, even

          @date = Add_Delta_YMD(
                  Add_Delta_YMD(@date, $Dy,$Dm,$Dd), -$Dy,-$Dm,-$Dd);

     will (in general!) *NOT* return the initial date "`@date'"!

     (This might work in some cases, though.)

     Note that this is *NOT* a program bug but *NECESSARILY* so because of
     the varying lengths of years and months!

   * `($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
     System_Clock();'

     If your operating system supports the corresponding system calls
     ("`time()'" and "`localtime()'"), this function will return the
     information provided by your system clock, i.e., the current date and
     time, the number of the day of year, the number of the day of week
     and a flag signaling wether daylight savings time is currently in
     effect or not.

     The ranges of values returned (and their meanings) are as follows:

          $year   :   should at least cover 1900..2038
          $month  :   1..12
          $day    :   1..31
          $hour   :   0..23
          $min    :   0..59
          $sec    :   0..59    (0..61 on some systems)
          $doy    :   1..366
          $dow    :   1..7
          $dst    :  -1..1

     The day of week ("`$dow'") will be "1" for Monday, "2" for Tuesday
     and so on until "7" for Sunday.

     The daylight savings time flag ("$dst") will be "`-1'" if this
     information is not available on your system, "0" for no daylight
     savings time (i.e., normal time) and "1" when daylight savings time
     is in effect.

     If your operating system does not provide the necessary system calls,
     calling this function will result in a fatal "not available on this
     system" error message.

     If you want to handle this exception yourself, use "eval" as follows:

          eval { ($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
            System_Clock(); };

          if ($@)
          {
              # Handle missing system clock
              # (For instance, ask user to enter this information manually)
          }

     Note that curlies ("{" and "}") are used here to delimit the
     statement to be "eval"ed (which is the way to catch exceptions in
     Perl), and not quotes (which is a way to evaluate Perl expressions at
     runtime).

   * `($year,$month,$day) = Today();'

     This function returns a subset of the values returned by the function
     "`System_Clock()'" (see above for details), namely the current year,
     month and day.

     A fatal "not available on this system" error message will appear if
     the corresponding system calls are not supported by your current
     operating system.

   * `($hour,$min,$sec) = Now();'

     This function returns a subset of the values returned by the function
     "`System_Clock()'" (see above for details), namely the current time
     (hours, minutes and full seconds).

     A fatal "not available on this system" error message will appear if
     the corresponding system calls are not supported by your current
     operating system.

   * `($year,$month,$day, $hour,$min,$sec) = Today_and_Now();'

     This function returns a subset of the values returned by the function
     "`System_Clock()'" (see above for details), namely the current date
     (year, month, day) and time (hours, minutes and full seconds).

     A fatal "not available on this system" error message will appear if
     the corresponding system calls are not supported by your current
     operating system.

   * `($year,$month,$day) = Easter_Sunday($year);'

     This function calculates the date of easter sunday for all years in
     the range from 1583 to 2299 (all other year numbers will result in a
     fatal "year out of range" error message) using the method known as
     the "Gaussian Rule".

     Some related christian feast days which depend on the date of easter
     sunday:

          Carnival Monday / Rosenmontag / Veille du Mardi Gras   =  -48 days
          Mardi Gras / Karnevalsdienstag / Mardi Gras            =  -47 days
          Ash Wednesday / Aschermittwoch / Mercredi des Cendres  =  -46 days
          Palm Sunday / Palmsonntag / Dimanche des Rameaux       =   -7 days
          Easter Friday / Karfreitag / Vendredi Saint            =   -2 days
          Easter Saturday / Ostersamstag / Samedi de Paques      =   -1 day
          Easter Monday / Ostermontag / Lundi de Paques          =   +1 day
          Ascension of Christ / Christi Himmelfahrt / Ascension  =  +39 days
          Whitsunday / Pfingstsonntag / Dimanche de Pentecote    =  +49 days
          Whitmonday / Pfingstmontag / Lundi de Pentecote        =  +50 days
          Feast of Corpus Christi / Fronleichnam / Fete-Dieu     =  +60 days

     Use the offsets shown above to calculate the date of the corresponding
     feast day as follows:

          ($year,$month,$day) = Add_Delta_Days(Easter_Sunday($year), $offset));

   * `if ($month = Decode_Month($string))'

     This function takes a string as its argument, which should contain the
     name of a month *IN THE CURRENTLY SELECTED LANGUAGE* (see further
     below for details about the multi-language support of this package),
     or any uniquely identifying abbreviation of a month's name (i.e., the
     first few letters), and returns the corresponding number (1..12) upon
     a successful match, or "0" otherwise (therefore, the return value can
     also be used as the conditional expression in an "if" statement).

     Note that the input string may not contain any other characters which
     do not pertain to the month's name, especially no leading or trailing
     whitespace.

     Note also that matching is performed in a case-insensitive manner
     (this may depend on the "locale" setting on your current system,
     though!)

     With "English" as the currently selected language (which is the
     default), the following examples will all return the value "9":

          $month = Decode_Month("s");
          $month = Decode_Month("Sep");
          $month = Decode_Month("septemb");
          $month = Decode_Month("September");

   * `if ($dow = Decode_Day_of_Week($string))'

     This function takes a string as its argument, which should contain the
     name of a day of week *IN THE CURRENTLY SELECTED LANGUAGE* (see
     further below for details about the multi-language support of this
     package), or any uniquely identifying abbreviation of the name of a
     day of week (i.e., the first few letters), and returns the
     corresponding number (1..7) upon a successful match, or "0" otherwise
     (therefore, the return value can also be used as the conditional
     expression in an "if" statement).

     Note that the input string may not contain any other characters which
     do not pertain to the name of the day of week, especially no leading
     or trailing whitespace.

     Note also that matching is performed in a case-insensitive manner
     (this may depend on the "locale" setting on your current system,
     though!)

     With "English" as the currently selected language (which is the
     default), the following examples will all return the value "3":

          $dow = Decode_Day_of_Week("w");
          $dow = Decode_Day_of_Week("Wed");
          $dow = Decode_Day_of_Week("wednes");
          $dow = Decode_Day_of_Week("Wednesday");

   * `if ($lang = Decode_Language($string))'

     This function takes a string as its argument, which should contain the
     name of one of the languages supported by this package (*IN THIS VERY
     LANGUAGE ITSELF*), or any uniquely identifying abbreviation of the
     name of a language (i.e., the first few letters), and returns its
     corresponding internal number (1..7 in the original distribution)
     upon a successful match, or "0" otherwise (therefore, the return
     value can also be used as the conditional expression in an "if"
     statement).

     Note that the input string may not contain any other characters which
     do not pertain to the name of a language, especially no leading or
     trailing whitespace.

     Note also that matching is performed in a case-insensitive manner
     (this may depend on the "locale" setting on your current system,
     though!)

     The original distribution supports the following seven languages:

          English                    ==>   1    (default)
          Français    (French)       ==>   2
          Deutsch     (German)       ==>   3
          Español     (Spanish)      ==>   4
          Português   (Portuguese)   ==>   5
          Nederlands  (Dutch)        ==>   6
          Italiano    (Italian)      ==>   7

     See the section "How to install additional languages" in the file
     "INSTALL.txt" in this distribution for how to add more languages to
     this package.

     In the original distribution (no other languages installed), the
     following examples will all return the value "3":

          $lang = Decode_Language("d");
          $lang = Decode_Language("de");
          $lang = Decode_Language("Deutsch");

     Note that you may not be able to enter the special international
     characters in some of the languages' names over the keyboard directly
     on some systems.

     This should never be a problem, though; just enter an abbreviation of
     the name of the language consisting of the first few letters up to
     the character before the first special international character.

   * `if (($year,$month,$day) = Decode_Date_EU($string))'

     This function scans a given string and tries to parse any date which
     might be embedded in it.

     The function returns an empty list if it can't successfully extract a
     valid date from its input string, or else it returns the date found.

     The function accepts almost any format, as long as the date is given
     in the european order (hence its name) day-month-year.

     Thereby, zero or more *NON-NUMERIC* characters may *PRECEDE* the day
     and *FOLLOW* the year.

     Moreover, zero or more *NON-ALPHANUMERIC* characters are permitted
     *BETWEEN* these three items (i.e., between day and month and between
     month and year).

     The month may be given either numerically (i.e., a number from "1" to
     "12"), or alphanumerically, i.e., as the name of the month *IN THE
     CURRENTLY SELECTED LANGUAGE*, or any uniquely identifying abbreviation
     thereof.

     (See further below for details about the multi-language support of
     this package!)

     If the year is given as one or two digits only (i.e., if the year is
     less than 100), it is mapped to the window "`1970 - 2069'" as follows:

          0 Less_Than_Special_Sequence= $year Less_Than_Special_Sequence  70  ==>  $year += 2000;
            70 Less_Than_Special_Sequence= $year Less_Than_Special_Sequence 100  ==>  $year += 1900;

     If the day, month and year are all given numerically but *WITHOUT* any
     delimiting characters between them, this string of digits will be
     mapped to the day, month and year as follows:

          Length:        Mapping:
            3              dmy
            4              dmyy
            5              dmmyy
            6              ddmmyy
            7              dmmyyyy
            8              ddmmyyyy

     (Where "d" stands for "day", "m" stands for "month" and "y" stands for
     "year".)

     All other strings consisting purely of digits (without any intervening
     delimiters) are rejected, i.e., not recognized.

     Examples:

          "3.1.64"
          "3 1 64"
          "03.01.64"
          "03/01/64"
          "3. Jan 1964"
          "Birthday: 3. Jan '64 in Backnang/Germany"
          "03-Jan-64"
          "3.Jan1964"
          "3Jan64"
          "030164"
          "3ja64"
          "3164"

     Experiment! (See the corresponding example applications in the
     "examples" subdirectory of this distribution in order to do so.)

   * `if (($year,$month,$day) = Decode_Date_US($string))'

     This function scans a given string and tries to parse any date which
     might be embedded in it.

     The function returns an empty list if it can't successfully extract a
     valid date from its input string, or else it returns the date found.

     The function accepts almost any format, as long as the date is given
     in the U.S. american order (hence its name) month-day-year.

     Thereby, zero or more *NON-ALPHANUMERIC* characters may *PRECEDE* and
     *FOLLOW* the month (i.e., precede the month and separate it from the
     day which follows behind).

     Moreover, zero or more *NON-NUMERIC* characters are permitted
     *BETWEEN* the day and the year, as well as *AFTER* the year.

     The month may be given either numerically (i.e., a number from "1" to
     "12"), or alphanumerically, i.e., as the name of the month *IN THE
     CURRENTLY SELECTED LANGUAGE*, or any uniquely identifying abbreviation
     thereof.

     (See further below for details about the multi-language support of
     this package!)

     If the year is given as one or two digits only (i.e., if the year is
     less than 100), it is mapped to the window "`1970 - 2069'" as follows:

          0 Less_Than_Special_Sequence= $year Less_Than_Special_Sequence  70  ==>  $year += 2000;
            70 Less_Than_Special_Sequence= $year Less_Than_Special_Sequence 100  ==>  $year += 1900;

     If the month, day and year are all given numerically but *WITHOUT* any
     delimiting characters between them, this string of digits will be
     mapped to the month, day and year as follows:

          Length:        Mapping:
            3              mdy
            4              mdyy
            5              mddyy
            6              mmddyy
            7              mddyyyy
            8              mmddyyyy

     (Where "m" stands for "month", "d" stands for "day" and "y" stands for
     "year".)

     All other strings consisting purely of digits (without any intervening
     delimiters) are rejected, i.e., not recognized.

     If only the day and the year form a contiguous string of digits, they
     will be mapped as follows:

          Length:        Mapping:
            2              dy
            3              dyy
            4              ddyy
            5              dyyyy
            6              ddyyyy

     (Where "d" stands for "day" and "y" stands for "year".)

     Examples:

          "1 3 64"
          "01/03/64"
          "Jan 3 '64"
          "Jan 3 1964"
          "===> January 3rd 1964 (birthday)"
          "Jan31964"
          "Jan364"
          "ja364"
          "1364"

     Experiment! (See the corresponding example applications in the
     "examples" subdirectory of this distribution in order to do so.)

   * `$date = Compress($year,$month,$day);'

     This function encodes a date in 16 bits, which is the value being
     returned.

     The encoding scheme is as follows:

          Bit number:    FEDCBA9 8765 43210
          Contents:      yyyyyyy mmmm ddddd

     (Where the "yyyyyyy" contain the number of the year, "mmmm" the
     number of the month and "ddddd" the number of the day.)

     The function returns "0" if the given input values do not represent a
     valid date. Therefore, the return value of this function can also be
     used as the conditional expression in an "if" statement, in order to
     check wether the given input values constitute a valid date).

     Through this special encoding scheme, it is possible to *COMPARE*
     compressed dates for equality and order (less than/greater than)
     *WITHOUT* any previous *DECODING*!

     Note however that contiguous dates do *NOT* necessarily have
     contiguous compressed representations!

     I.e., incrementing the compressed representation of a date *MAY OR
     MAY NOT* yield a valid new date!

     Note also that this function can only handle dates within one century.

     This century can be chosen at random by defining a base century and
     year (also called the "epoch"). In the original distribution of this
     package, the base century is set to "1900" and the base year to "70"
     (which is standard on UNIX systems).

     This allows this function to handle dates from "1970" up to "2069".

     If the given year is equal to, say, "95", this package will
     automatically assume that you really mean "1995" instead. However, if
     you specify a year number which is *SMALLER* than 70, like "64", for
     instance, this package will assume that you really mean "2064".

     You are not confined to two-digit (abbreviated) year numbers, though.

     The function also accepts "full-length" year numbers, provided that
     they lie in the supported range (i.e., from "1970" to "2069", in the
     original configuration of this package).

     Note that this function is maintained mainly for backward
     compatibility, and that its use is not recommended.

   * `if (($century,$year,$month,$day) = Uncompress($date))'

     This function decodes dates that were encoded previously using the
     function "`Compress()'".

     It returns the century, year, month and day of the date encoded in
     "`$date'" if "`$date'" represents a valid date, or an empty list
     otherwise.

     The year returned in "$year" is actually a two-digit year number
     (i.e., the year number taken modulo 100), and only the expression
     "`$century + $year'" yields the "full-length" year number (for
     example, `1900 + 95 = 1995').

     Note that this function is maintained mainly for backward
     compatibility, and that its use is not recommended.

   * `if (check_compressed($date))'

     This function returns "true" ("1") if the given input value
     constitutes a valid compressed date, and "false" ("0") otherwise.

     Note that this function is maintained mainly for backward
     compatibility, and that its use is not recommended.

   * `$string = Compressed_to_Text($date);'

     This function returns a string of fixed length (always 9 characters
     long) containing a textual representation of the compressed date
     encoded in "`$date'".

     This string has the form "dd-Mmm-yy", where "dd" is the two-digit
     number of the day, "Mmm" are the first three letters of the name of
     the month in the currently selected language (see further below for
     details about the multi-language support of this package), and "yy"
     is the two-digit year number (i.e., the year number taken modulo 100).

     If "`$date'" does not represent a valid date, the string "??-???-??"
     is returned instead.

     Note that this function is maintained mainly for backward
     compatibility, and that its use is not recommended.

   * `$string = Date_to_Text($year,$month,$day);'

     This function returns a string containing a textual representation of
     the given date of the form "www dd-Mmm-yyyy", where "www" are the
     first three letters of the name of the day of week in the currently
     selected language, or a special abbreviation, if special
     abbreviations have been defined for the currently selected language
     (see further below for details about the multi-language support of
     this package), "dd" is the day (one or two digits), "Mmm" are the
     first three letters of the name of the month in the currently
     selected language, and "yyyy" is the number of the year in full
     length.

     If the given input values do not constitute a valid date, a fatal
     "not a valid date" error occurs.

     (See the section "RECIPES" near the end of this document for a code
     snippet for how to print dates in any format you like.)

   * `$string = Date_to_Text_Long($year,$month,$day);'

     This function returns a string containing a textual representation of
     the given date roughly of the form "Wwwwww, dd Mmmmmm yyyy", where
     "Wwwwww" is the name of the day of week in the currently selected
     language (see further below for details about the multi-language
     support of this package), "dd" is the day (one or two digits),
     "Mmmmmm" is the name of the month in the currently selected language,
     and "yyyy" is the number of the year in full length.

     The exact format of the output string depends on the currently
     selected language. In the original distribution of this package,
     these formats are defined as follows:

          1  English    :  "Wwwwww, Mmmmmm ddth yyyy"
          2  French     :  "Wwwwww, le dd Mmmmmm yyyy"
          3  German     :  "Wwwwww, den dd. Mmmmmm yyyy"
          4  Spanish    :  "Wwwwww, dd de Mmmmmm de yyyy"
          5  Portuguese :  "Wwwwww, dia dd de Mmmmmm de yyyy"
          6  Dutch      :  "Wwwwww, dd. Mmmmmm yyyy"
          7  Italian    :  "Wwwwww, dd Mmmmmm yyyy"

     (You can change these formats in the file "DateCalc.c" before
     building this module in order to suit your personal preferences.)

     If the given input values do not constitute a valid date, a fatal
     "not a valid date" error occurs.

     (See the section "RECIPES" near the end of this document for an
     example on how to print dates in any format you like.)

   * `$string = English_Ordinal($number);'

     This function returns a string containing the (english) abbreviation
     of the ordinal number for the given (cardinal) number "`$number'".

     I.e.,

          0  =>  '0th'    10  =>  '10th'    20  =>  '20th'
          1  =>  '1st'    11  =>  '11th'    21  =>  '21st'
          2  =>  '2nd'    12  =>  '12th'    22  =>  '22nd'
          3  =>  '3rd'    13  =>  '13th'    23  =>  '23rd'
          4  =>  '4th'    14  =>  '14th'    24  =>  '24th'
          5  =>  '5th'    15  =>  '15th'    25  =>  '25th'
          6  =>  '6th'    16  =>  '16th'    26  =>  '26th'
          7  =>  '7th'    17  =>  '17th'    27  =>  '27th'
          8  =>  '8th'    18  =>  '18th'    28  =>  '28th'
          9  =>  '9th'    19  =>  '19th'    29  =>  '29th'

     etc.

   * `$string = Calendar($year,$month);'

     This function returns a calendar of the given month in the given year
     (somewhat similar to the UNIX "cal" command), *IN THE CURRENTLY
     SELECTED LANGUAGE* (see further below for details about the
     multi-language support of this package).

     Example:

          print Calendar(1998,5);

     This will print:

          May 1998
            Mon Tue Wed Thu Fri Sat Sun
                   1   2   3
              4   5   6   7   8   9  10
             11  12  13  14  15  16  17
             18  19  20  21  22  23  24
             25  26  27  28  29  30  31

   * `$string = Month_to_Text($month);'

     This function returns the name of the given month in the currently
     selected language (see further below for details about the
     multi-language support of this package).

     If the given month lies outside of the valid range from "1" to "12",
     a fatal "month out of range" error will occur.

   * `$string = Day_of_Week_to_Text($dow);'

     This function returns the name of the given day of week in the
     currently selected language (see further below for details about the
     multi-language support of this package).

     If the given day of week lies outside of the valid range from "1" to
     "7", a fatal "day of week out of range" error will occur.

   * `$string = Day_of_Week_Abbreviation($dow);'

     This function returns the special abbreviation of the name of the
     given day of week, IF such special abbreviations have been defined
     for the currently selected language (see further below for details
     about the multi-language support of this package).

     (In the original distribution of this package, this is only true for
     Portuguese.)

     If not, the first three letters of the name of the day of week in the
     currently selected language are returned instead.

     If the given day of week lies outside of the valid range from "1" to
     "7", a fatal "day of week out of range" error will occur.

     Currently, this table of special abbreviations is only used by the
     functions "`Date_to_Text()'" and "`Calendar()'", internally.

   * `$string = Language_to_Text($lang);'

     This function returns the name of any language supported by this
     package when the internal number representing that language is given
     as input.

     The original distribution supports the following seven languages:

          1   ==>   English                     (default)
          2   ==>   Français    (French)
          3   ==>   Deutsch     (German)
          4   ==>   Español     (Spanish)
          5   ==>   Português   (Portuguese)
          6   ==>   Nederlands  (Dutch)
          7   ==>   Italiano    (Italian)

     See the section "How to install additional languages" in the file
     "INSTALL.txt" in this distribution for how to add more languages to
     this package.

     See the description of the function "`Languages()'" further below to
     determine how many languages are actually available in a given
     installation of this package.

   * `$lang = Language();'

   * `Language($lang);'

   * `$oldlang = Language($newlang);'

     This function can be used to determine which language is currently
     selected, and to change the selected language.

     Thereby, each language has a unique internal number.

     The original distribution contains the following seven languages:

          1   ==>   English                     (default)
          2   ==>   Français    (French)
          3   ==>   Deutsch     (German)
          4   ==>   Español     (Spanish)
          5   ==>   Português   (Portuguese)
          6   ==>   Nederlands  (Dutch)
          7   ==>   Italiano    (Italian)

     See the section "How to install additional languages" in the file
     "INSTALL.txt" in this distribution for how to add more languages to
     this package.

     See the description of the function "`Languages()'" further below to
     determine how many languages are actually available in a given
     installation of this package.

     *BEWARE* that in order for your programs to be portable, you should
     *NEVER* actually use the internal number of a language in this
     package *EXPLICITLY*, because the same number could mean different
     languages on different systems, depending on what languages have been
     added to any given installation of this package.

     Therefore, you should always use a statement such as

          Language(Decode_Language("Name_of_Language"));

     to select the desired language, and

          $language = Language_to_Text(Language());

     or

          $old_language = Language_to_Text(Language("Name_of_new_Language"));

     to determine the (previously) selected language.

     If the so chosen language is not available in the current
     installation, this will result in an appropriate error message,
     instead of silently using the wrong (a random) language (which just
     happens to have the same internal number in the other installation).

     Note that in the current implementation of this package, the selected
     language is a global setting valid for ALL functions that use the
     names of months, days of week or languages internally, valid for *ALL
     PROCESSES* using the same copy of the "Date::Calc" shared library in
     memory!

     This may have surprising side-effects in a multi-user environment,
     and even more so when Perl will be capable of multi-threading in some
     future release.

   * `$max_lang = Languages();'

     This function returns the (maximum) number of languages which are
     currently available in your installation of this package.

     (This may vary from installation to installation.)

     See the section "How to install additional languages" in the file
     "INSTALL.txt" in this distribution for how to add more languages to
     this package.

     In the original distribution of this package there are seven built-in
     languages, therefore the value returned by this function will be "7"
     if no other languages have been added to your particular installation.

   * `if (($year,$month,$day) = Decode_Date_EU2($string))'

     This function is the Perl equivalent of the function
     "`Decode_Date_EU()'" (implemented in C), included here merely as an
     example to demonstrate how easy it is to write your own routine in
     Perl (using regular expressions) adapted to your own special needs,
     should the necessity arise, and intended primarily as a basis for
     your own development.

     In one particular case this Perl version is actually slightly more
     permissive than its C equivalent, as far as the class of permitted
     intervening (i.e., delimiting) characters is concerned.

     (Can you tell the subtle, almost insignificant difference by looking
     at the code? Or by experimenting? Hint: Try the string "a3b1c64d"
     with both functions.)

   * `if (($year,$month,$day) = Decode_Date_US2($string))'

     This function is the Perl equivalent of the function
     "`Decode_Date_US()'" (implemented in C), included here merely as an
     example to demonstrate how easy it is to write your own routine in
     Perl (using regular expressions) adapted to your own special needs,
     should the necessity arise, and intended primarily as a basis for
     your own development.

     In one particular case this Perl version is actually slightly more
     permissive than its C equivalent.

     (Hint: This is the same difference as with the "`Decode_Date_EU()'"
     and "`Decode_Date_EU2()'" pair of functions.)

     In a different case, the C version is a little bit more permissive
     than its Perl equivalent.

     (Can you tell the difference by looking at the code? Or by
     experimenting?  Hint: Try the string "(1/364)" with both functions.)

   * `if (($year,$month,$day) = Parse_Date($string))'

     This function is useful for parsing dates as returned by the UNIX
     "date" command or as found in the headers of e-mail (in order to
     determine the date at which some e-mail has been sent or received,
     for instance).

     Example #1:

          ($year,$month,$day) = Parse_Date(`/bin/date`);

     Example #2:

          while (<MAIL>)
          {
              if (/^From \S/)
              {
                  ($year,$month,$day) = Parse_Date($_);
                  ...
              }
              ...
          }

     The function returns an empty list if it can't extract a valid date
     from the input string.

   * `$string = Date::Calc::Version();'

     This function returns a string with the (numeric) version number of
     the C library ("DateCalc.c") at the core of this package (which is
     also (automatically) the version number of the "Calc.xs" file).

     Note that under all normal circumstances, this version number should
     be identical with the one found in the Perl variable
     "`$Date::Calc::VERSION'" (the version number of the "Calc.pm" file).

     Since this function is not exported, you always have to qualify it
     explicitly, i.e., "`Date::Calc::Version()'".

     This is to avoid possible name space conflicts with version functions
     from other modules.

RECIPES
=======

  1. How do I compare two dates?

     Solution #1:

          use Date::Calc qw( Date_to_Days );

          if (Date_to_Days($year1,$month1,$day1)  <
              Date_to_Days($year2,$month2,$day2))

          if (Date_to_Days($year1,$month1,$day1)  <=
              Date_to_Days($year2,$month2,$day2))

          if (Date_to_Days($year1,$month1,$day1)  >
              Date_to_Days($year2,$month2,$day2))

          if (Date_to_Days($year1,$month1,$day1)  >=
              Date_to_Days($year2,$month2,$day2))

          if (Date_to_Days($year1,$month1,$day1)  ==
              Date_to_Days($year2,$month2,$day2))

          if (Date_to_Days($year1,$month1,$day1)  !=
              Date_to_Days($year2,$month2,$day2))

          $cmp = (Date_to_Days($year1,$month1,$day1)  <=>
                  Date_to_Days($year2,$month2,$day2));

     Solution #2:

          use Date::Calc qw( Delta_Days );

          if (Delta_Days($year1,$month1,$day1,
                         $year2,$month2,$day2) > 0)

          if (Delta_Days($year1,$month1,$day1,
                         $year2,$month2,$day2) >= 0)

          if (Delta_Days($year1,$month1,$day1,
                         $year2,$month2,$day2) < 0)

          if (Delta_Days($year1,$month1,$day1,
                         $year2,$month2,$day2) <= 0)

          if (Delta_Days($year1,$month1,$day1,
                         $year2,$month2,$day2) == 0)

          if (Delta_Days($year1,$month1,$day1,
                         $year2,$month2,$day2) != 0)

  2. How do I check wether a given date lies within a certain range of
     dates?

          use Date::Calc qw( Date_to_Days );

          $lower = Date_to_Days($year1,$month1,$day1);
          $upper = Date_to_Days($year2,$month2,$day2);

          $date = Date_to_Days($year,$month,$day);

          if (($date >= $lower) && ($date <= $upper))
          {
              # ok
          }
          else
          {
              # not ok
          }

  3. How do I verify wether someone has a certain age?

          use Date::Calc qw( Decode_Date_EU Today leap_year Delta_Days );

          $date = <STDIN>; # get birthday

          ($year1,$month1,$day1) = Decode_Date_EU($date);

          ($year2,$month2,$day2) = Today();

          if (($day1 == 29) && ($month1 == 2) && !leap_year($year2))
              { $day1--; }

          if ( (($year2 - $year1) >  18) ||
             ( (($year2 - $year1) == 18) &&
             (Delta_Days($year2,$month1,$day1, $year2,$month2,$day2) >= 0) ) )
          {
              print "Ok - you are over 18.\n";
          }
          else
          {
              print "Sorry - you aren't 18 yet!\n";
          }

  4. How do I calculate the number of the week of month the current date
     lies in?

     For example:

          April 1998
              Mon Tue Wed Thu Fri Sat Sun
            1   2   3   4   5  =  week #1
                6   7   8   9  10  11  12  =  week #2
               13  14  15  16  17  18  19  =  week #3
               20  21  22  23  24  25  26  =  week #4
               27  28  29  30              =  week #5

     Solution:

          use Date::Calc qw( Today Day_of_Week );

          ($year,$month,$day) = Today();

          $week = int(($day + Day_of_Week($year,$month,1) - 2) / 7) + 1;

  5. How do I calculate wether a given date is the 1st, 2nd, 3rd, 4th or
     5th of that day of week in the given month?

     For example:

          October 2000
              Mon Tue Wed Thu Fri Sat Sun
                             1
                2   3   4   5   6   7   8
                9  10  11  12  13  14  15
               16  17  18  19  20  21  22
               23  24  25  26  27  28  29
               30  31

     Is Sunday, the 15th of October 2000, the 1st, 2nd, 3rd, 4th or 5th
     Sunday of that month?

     Solution:

          use Date::Calc qw( Day_of_Week Delta_Days
                             Nth_Weekday_of_Month_Year
                             Date_to_Text_Long English_Ordinal
                             Day_of_Week_to_Text Month_to_Text );

          ($year,$month,$day) = (2000,10,15);

          $dow = Day_of_Week($year,$month,$day);

          $n = int( Delta_Days(
                    Nth_Weekday_of_Month_Year($year,$month,$dow,1),
                    $year,$month,$day)
                    / 7) + 1;

          printf("%s is the %s %s in %s %d.\n",
              Date_to_Text_Long($year,$month,$day),
              English_Ordinal($n),
              Day_of_Week_to_Text($dow),
              Month_to_Text($month),
              $year);

     This prints:

          Sunday, October 15th 2000 is the 3rd Sunday in October 2000.

  6. How do I calculate the date of the Wednesday of the same week as the
     current date?

     Solution #1:

          use Date::Calc qw( Today Day_of_Week Add_Delta_Days );

          $searching_dow = 3; # 3 = Wednesday

          @today = Today();

          $current_dow = Day_of_Week(@today);

          @date = Add_Delta_Days(@today, $searching_dow - $current_dow);

     Solution #2:

          use Date::Calc qw( Today Add_Delta_Days
                             Monday_of_Week Week_of_Year );

          $searching_dow = 3; # 3 = Wednesday

          @today = Today();

          @date = Add_Delta_Days( Monday_of_Week( Week_of_Year(@today) ),
                                  $searching_dow - 1 );

     Solution #3:

          use Date::Calc qw( Standard_to_Business Today
                             Business_to_Standard );

          @business = Standard_to_Business(Today());

          $business[2] = 3; # 3 = Wednesday

          @date = Business_to_Standard(@business);

  7. How can I add a week offset to a business date (including across year
     boundaries)?

          use Date::Calc qw( Business_to_Standard Add_Delta_Days
                             Standard_to_Business );

          @temp = Business_to_Standard($year,$week,$dow);

          @temp = Add_Delta_Days(@temp, $week_offset * 7);

          ($year,$week,$dow) = Standard_to_Business(@temp);

  8. How do I calculate the last and the next Saturday for any given date?

          use Date::Calc qw( Today Day_of_Week Add_Delta_Days
                             Day_of_Week_to_Text Date_to_Text );

          $searching_dow = 6; # 6 = Saturday

          @today = Today();

          $current_dow = Day_of_Week(@today);

          if ($searching_dow == $current_dow)
          {
              @prev = Add_Delta_Days(@today,-7);
              @next = Add_Delta_Days(@today,+7);
          }
          else
          {
              if ($searching_dow > $current_dow)
              {
                  @next = Add_Delta_Days(@today,
                            $searching_dow - $current_dow);
                  @prev = Add_Delta_Days(@next,-7);
              }
              else
              {
                  @prev = Add_Delta_Days(@today,
                            $searching_dow - $current_dow);
                  @next = Add_Delta_Days(@prev,+7);
              }
          }

          $dow = Day_of_Week_to_Text($searching_dow);

          print "Today is:      ", ' ' x length($dow),
                                       Date_to_Text(@today), "\n";
          print "Last $dow was:     ", Date_to_Text(@prev),  "\n";
          print "Next $dow will be: ", Date_to_Text(@next),  "\n";

     This will print something like:

          Today is:              Sun 12-Apr-1998
          Last Saturday was:     Sat 11-Apr-1998
          Next Saturday will be: Sat 18-Apr-1998

  9. How can I calculate the last business day (payday!) of a month?

     Solution #1 (holidays *NOT* taken into account):

          use Date::Calc qw( Days_in_Month Day_of_Week Add_Delta_Days );

          $day = Days_in_Month($year,$month);
          $dow = Day_of_Week($year,$month,$day);
          if ($dow > 5)
          {
              ($year,$month,$day) =
                  Add_Delta_Days($year,$month,$day, 5-$dow);
          }

     Solution #2 (holidays taken into account):

     This solution expects a multi-dimensional array "`@holiday'", which
     contains all holidays, as follows: "`$holiday[$year][$month][$day] =
     1;'".

     (See the description of the function "`Easter_Sunday()'" further
     above for how to calculate the moving (variable) christian feast
     days!)

     Days which are not holidays remain undefined or should have a value
     of zero in this array.

          use Date::Calc qw( Days_in_Month Add_Delta_Days Day_of_Week );

          $day = Days_in_Month($year,$month);
          while (1)
          {
              while ($holiday[$year][$month][$day])
              {
                  ($year,$month,$day) =
                      Add_Delta_Days($year,$month,$day, -1);
              }
              $dow = Day_of_Week($year,$month,$day);
              if ($dow > 5)
              {
                  ($year,$month,$day) =
                      Add_Delta_Days($year,$month,$day, 5-$dow);
              }
              else { last; }
          }

 10. How do I convert a MS Visual Basic "DATETIME" value into its date and
     time constituents?

          use Date::Calc qw( Add_Delta_DHMS Date_to_Text );

          $datetime = "35883.121653";

          ($Dd,$Dh,$Dm,$Ds) = ($datetime =~ /^(\d+)\.(\d\d)(\d\d)(\d\d)$/);

          ($year,$month,$day, $hour,$min,$sec) =
              Add_Delta_DHMS(1900,1,1, 0,0,0, $Dd,$Dh,$Dm,$Ds);

          printf("The given date is %s %02d:%02d:%02d\n",
              Date_to_Text($year,$month,$day), $hour, $min, $sec);

     This prints:

          The given date is Tue 31-Mar-1998 12:16:53

 11. How can I send a reminder to members of a group on the day before a
     meeting which occurs every first Friday of a month?

          use Date::Calc qw( Today Date_to_Days Add_Delta_YMD
                             Nth_Weekday_of_Month_Year );

          ($year,$month,$day) = Today();

          $tomorrow = Date_to_Days($year,$month,$day) + 1;

          $dow = 5; # 5 = Friday
          $n   = 1; # 1 = First of that day of week

          $meeting_this_month = Date_to_Days(
              Nth_Weekday_of_Month_Year($year,$month,$dow,$n) );

          ($year,$month,$day) = Add_Delta_YMD($year,$month,$day, 0,1,0);

          $meeting_next_month = Date_to_Days(
              Nth_Weekday_of_Month_Year($year,$month,$dow,$n) );

          if (($tomorrow == $meeting_this_month) ||
              ($tomorrow == $meeting_next_month))
          {
              # Send reminder e-mail!
          }

 12. How can I print a date in a different format than provided by the
     functions "`Date_to_Text()'", "`Date_to_Text_Long()'" or
     "`Compressed_to_Text()'"?

          use Date::Calc qw( Today Day_of_Week_to_Text
                             Day_of_Week Month_to_Text
                             English_Ordinal );

          ($year,$month,$day) = Today();

     For example with leading zeros for the day: "Fri 03-Jan-1964"

          printf("%.3s %02d-%.3s-%d\n",
              Day_of_Week_to_Text(Day_of_Week($year,$month,$day)),
              $day,
              Month_to_Text($month),
              $year);

     For example in U.S. american format: "April 12th, 1998"

          $string = sprintf("%s %s, %d",
                        Month_to_Text($month),
                        English_Ordinal($day),
                        $year);

     (See also `perlfunc(1)' in this node and/or `perlfunc(1)' in this
     node!)

 13. How can I iterate through a range of dates?

          use Date::Calc qw( Delta_Days Add_Delta_Days );

          @start = (1999,5,27);
          @stop  = (1999,6,1);

          $j = Delta_Days(@start,@stop);

          for ( $i = 0; $i <= $j; $i++ )
          {
              @date = Add_Delta_Days(@start,$i);
              printf("%4d/%02d/%02d\n", @date);
          }

     Note that the loop can be improved; see also the recipe below.

 14. How can I create a (Perl) list of dates in a certain range?

          use Date::Calc qw( Delta_Days Add_Delta_Days Date_to_Text );

          sub date_range
          {
              my(@date) = (@_)[0,1,2];
              my(@list);
              my($i);

          $i = Delta_Days(@_);
          while ($i-- >= 0)
          {
              push( @list, [ @date ] );
              @date = Add_Delta_Days(@date, 1) if ($i >= 0);
          }
          return(@list);
            }

          @range = &date_range(1999,11,3, 1999,12,24); # in chronological order

          foreach $date (@range)
          {
              print Date_to_Text(@{$date}), "\n";
          }

     Note that you probably shouldn't use this one, because it is much
     more efficient to iterate through all the dates (as shown in the
     recipe immediately above) than to construct such an array and then to
     loop through it. Also, it is much more space-efficient not to create
     this array.

 15. How can I calculate the difference in days between dates, but without
     counting Saturdays and Sundays?

          sub Delta_Business_Days
          {
              my(@date1) = (@_)[0,1,2];
              my(@date2) = (@_)[3,4,5];
              my($minus,$result,$dow1,$dow2,$diff,$temp);

          $minus  = 0;
          $result = Delta_Days(@date1,@date2);
          if ($result != 0)
          {
              if ($result < 0)
              {
                  $minus = 1;
                  $result = -$result;
                  $dow1 = Day_of_Week(@date2);
                  $dow2 = Day_of_Week(@date1);
              }
              else
              {
                  $dow1 = Day_of_Week(@date1);
                  $dow2 = Day_of_Week(@date2);
              }
              $diff = $dow2 - $dow1;
              $temp = $result;
              if ($diff != 0)
              {
                  if ($diff < 0)
                  {
                      $diff += 7;
                  }
                  $temp -= $diff;
                  $dow1 += $diff;
                  if ($dow1 > 6)
                  {
                      $result--;
                      if ($dow1 > 7)
                      {
                          $result--;
                      }
                  }
              }
              if ($temp != 0)
              {
                  $temp /= 7;
                  $result -= ($temp << 1);
              }
          }
          if ($minus) { return -$result; }
          else        { return  $result; }
            }

     This solution is probably of little practical value, however, because
     it doesn't take legal holidays into account.

SEE ALSO
========

   perl(1), perlfunc(1), perlsub(1), perlmod(1), perlxs(1), perlxstut(1),
perlguts(1).

   news:news.answers "Calendar FAQ, v. 1.9 (modified 25 Apr 1998) Part 1/3"

   news:news.answers "Calendar FAQ, v. 1.9 (modified 25 Apr 1998) Part 2/3"

   news:news.answers "Calendar FAQ, v. 1.9 (modified 25 Apr 1998) Part 3/3"

   http://www.math.uio.no/faq/calendars/faq.html

   http://www.pip.dknet.dk/~pip10160/calendar.html

   (All authored by Claus Tondering <c-t@pip.dknet.dk>)

LIMITATIONS
===========

   In the current implementation of this package, the selected language is
stored in a global variable.

   Therefore, when you are using a threaded Perl, this may cause undesired
side effects (of one thread always selecting the language for *ALL OTHER*
threads as well).

VERSION
=======

   This man page documents "Date::Calc" version 4.3.

AUTHOR
======

     Steffen Beyer
     Ainmillerstr. 5 / App. 513
     D-80801 Munich
     Germany

     mailto:sb@engelschall.com
     http://www.engelschall.com/u/sb/download/

   *Please contact me by e-mail whenever possible!*

COPYRIGHT
=========

   Copyright (c) 1995 - 2000 by Steffen Beyer.  All rights reserved.

LICENSE
=======

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself, i.e., under the terms of the
"Artistic License" or the "GNU General Public License".

   The C library at the core of this Perl module can additionally be
redistributed and/or modified under the terms of the "GNU Library General
Public License".

   Please refer to the files "Artistic.txt", "GNU_GPL.txt" and
"GNU_LGPL.txt" in this distribution for details!

DISCLAIMER
==========

   This package 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.

Calculates the day of the week Christmas falls upon given the year.
*******************************************************************

NAME
====

   Date::Christmas - Calculates the day of the week Christmas falls upon
given the year.

SYNOPSIS
========

   * Getting the Christmas Day of the Week in English.

          use Date::Christmas qw(christmasday);

          my $year = "2010";
          my $dow = christmasday $year;
          print "Christmas day falls on $dow in the year $year\n";

          -or-

          perl -MDate::Christmas -le 'print christmasday (2010)';

   * Getting the Christmas Day of the Week in any other language.

     use Date::Christmas qw(christmasday);

          my $year = 2004;
          $xmasdow = christmasday ($year, qw:sunnuntai maanantai tiistai keskiviikko torstai perjantai lauantai:);
          print "Christmas is on $xmasdow in the year $year\n";

          -or-

          perl -MDate::Christmas -le 'print christmasday (2000, qw:Sonntag Montag Dienstag Mittwoche Donnerstag Freitag Sonnabend:)'

DESCRIPTION
===========

   Date::Christmas calculates the day of the week that Christmas will fall
upon in any given year after the year 1600AD, including leap years when
using a Gregorian Calendar. The algorithm is based on "The Formula for
Christmas Day" on pages 261-262 in the book _The Physics of Christmas_ by
Roger Highfield.

   "Other prognostications, not only of the weather, were based on the day
of the week on which Christmas fell:

     Sunday
     If the natiuity of our Lorde come on Sunday, Winter shall
     be good, the spring windy, sweet & hot, Vintage flourishing,
     Oxen and Sheepe multiplied: Hony & milke plentifull, peace
     and accord in the Land, yea, all the Sundayes in the yeere
     following profitable: They that bee borne shall be strong,
     great and shining: and he that flieth shall be found.

     Monday
     If it fall on the Monday, Winter shall bee indifferent,
     Sommer dry, or clean contrary, so that if it be rainy and
     tempestuous, vintage shall be doubtfull; in each Munday of
     the said yeere, to enterprise any thing is shall bee prosperous
     and sstrong. Who that flieth shall soone be found: theft done
     shall be proued, and hee that falleth into his bed, soone recouer.

     Tuesday
     If it come on the Tuesday, Winter shall be good, the spring
     windy, Summer fruitfull, Vintage laboursome, Weomen die and
     shippes perish on the Seas. In each Tuesday of this same yeere,
     to beginne a worke, it will prosper: hee that is borne shall be
     strong and couteous, dreames pertaine to age. Hee that flieth
     shall soone bee found; theft done shall be proued.

     Wednesday
     If it come on the Wednesday, Winter shall be sharpe and hard,
     the Spring windy and euill, summer good, Vintage plentifull,
     good wit easily found, young men die, hony sparing, men desire
     to trauell, and ship-men saile with great hazard that yeere.
     In each Wednesday to begin a worke is good.

     Thursday
     If it come on the Thursday, Winter shall bee good, the Spring
     windy, Summer fruitfull, Vintage plentifull. Kings and Princes
     in hazard. And in each Thursday to beginne a new worke,
     prosperous. Hee that is borne shall be of faire speech and
     worshipfull, hee that flieth shall soone be found: theft done
     by weomen shall be proued. Hee that falleth in his bed shall
     soone recouer.

     Friday
     If it come on the Friday, winter shall be maruellous, the Spring
     windy and good, Summer dry, Vintage plenteous: There shall be
     trouble of the aire, Sheepe and Bees perish, Oates deare. In each
     Friday to begin a worke it shall prosper; hee that is borne shall
     be profitabe and lecherous. Hee that flieth shall soone be found;
     theft done by a Childe shall bee proued.

     Saturday
     If it come on the Saturday, Winter shall be dark, snow great,
     fruit plentious, the spring windy, Summer euill, Vintage sparing
     in many places: Oates shall be deare, Men waxe sicke, and Bees die.
     In no Saturday to begin a worke shall be good, except in the course
     of the Moone alter it: Theft done shall be found, hee that flieth
     shall turne againe to his owne; those that are sicke, shall long
     waile, and vnneath they shall escape death.
     'Godfridus', The knowledge of things vnknowne, 1-3"
     [The Oxford Companion to the Year, pp. 516-517.]

     Happy Holidays
     +
     +
     XXX
     XXXXX
     XXXXXXX
     XXXXXXXXX
     BOAS FESTAS
     JOYEUX NOEL
     VESELE VANOCE
     MELE KALIKIMAKA
     NODLAG SONA DHUIT
     BLWYDDYN NEWYDD DDA
     GOD JUL
     BUON ANNO
     FELIZ NATAL
     HYVAA JOULUA
     FELIZ NAVIDAD
     MERRY CHRISTMAS
     KALA CHRISTOUGENA
     VROLIJK KERSTFEEST
     FROHLICHE WEIHNACHTEN
     BUON NATALE-GODT NYTAR
     HUAN YING SHENG TAN CHIEH
     WESOLYCH SWIAT-SRETAN BOZIC
     MOADIM LESIMH0-LINKSMU KALEDU
     HAUSKAA JOULU0-AID SAID MOUBARK
     'N PRETTIG KERSTMIS
     ONNZLLISTA UUTTA VUOTTA
     Z ROZHDESTYOM KHRYSTOVYM
     ADOLIG LLAWEN-GOTT NYTTSAR
     FELIC NADAL-GOJAN KRISTNASKON
     S NOVYM GODOM-FELIZ ANO NUEVO
     GLEDILEG JOL-NOELINIZ KUTLU OLSUM
     EEN GELUKKIG NIEUWJAAR-SRETAN BOSIC
     KRIHSTLINDJA GEZUAR-KALA CHRISTOUGENA
     SELAMAT HARI NATAL - LAHNINGU NAJU METU
     SARBATORI FERICITE-BUON ANNO
     ZORIONEKO GABON-HRISTOS SE RODI
     BOLDOG KARACSONNY-VESELE VIANOCE
     MERRY CHRISTMAS - - HAPPY NEW YEAR
     ROOMSAID JOULU PUHI -KUNG HO SHENG TEN
     FELICES PASUAS-EIN GLUCKICHES NEWJAHR
     PRIECIGUSZIEMAN SVETKUS SARBATORI VESLLE
     BONNE ANNEBLWYDDYN NEWYDD DDADRFELIZ NATAL
     XXXXX
     XXXXX
     XXXXX
     XXXXXXXXXXXXX

AUTHOR
======

   HFB, hfb@cpan.org

SEE ALSO
========

   perl(1), Date::Calc, Date::Manip.

Convert Between any two Calendrical Formats
*******************************************

NAME
====

   Date::Convert - Convert Between any two Calendrical Formats

SYNOPSIS
========

     use Date::DateCalc;

     $date=new Date::Convert::Gregorian(1997, 11, 27);
     @date=$date->date;
     convert Date::Convert::Hebrew $date;
     print $date->date_string, "\n";

   Currently defined subclasses:

     Date::Convert::Absolute
     Date::Convert::Gregorian
     Date::Convert::Hebrew
     Date::Convert::Julian

   Date::Convert is intended to allow you to convert back and forth between
any arbitrary date formats (ie. pick any from: Gregorian, Julian, Hebrew,
Absolute, and any others that get added on).  It does this by having a
separate subclass for each format, and requiring each class to provide
standardized methods for converting to and from the date format of the base
class.  In this way, instead of having to code a conversion routine for
going between and two arbitrary formats foo and bar, the function only
needs to convert foo to the base class and the base class to bar.  Ie:

     Gregorian <--> Base class <--> Hebrew

   The base class includes a *Convert* method to do this transparently.

   Nothing is exported because it wouldn't make any sense to export.  :)

DESCRIPTION
===========

   Fucntion can be split into several categories:

   * Universal functions available for all subclasses (ie. all formats).
     The fundamental conversion routines fit this category.

   * Functions that are useful but don't necessarily make sense for all
     subclasses.  The overwhelming majority of functions fall into this
     category.  Even such seemingly universal concepts as year, for
     instance, don't apply to all date formats.

   * Private functions that are required of all subclasses, ie. initialize.
     These should not be called by users.

   Here's the breakdown by category:

Functions Defined for all Subclasses
------------------------------------

new
     Create a new object in the specified format with the specified start
     paramaters, ie. `$date = new Date::Convert::Gregorian(1974, 11, 27)'.
     The start parameters vary with the subclass.  My personal preference
     is to order in decreasing order of generality (ie. year first, then
     month, then day, or year then week, etc.)

     This can have a default date, which should probably be "today".

date
     Extract the date in a format appropriate for the subclass.
     Preferably this should match the format used with new, so

          (new date::Convert::SomeClass(@a))->date;

     should be an identity function on @a if @a was in a legitmate format.

date_string
     Return the date in a pretty format.

convert
     Change the date to a new format.

Non-universal functions
-----------------------

year
     Return just the year element of date.

month
     Just like year.

day
     Just like year and month.

is_leap
     Boolean.  Note that (for *::Hebrew* and *::Gregorian*, at least!) this
     can be also be used as a static.  That is, you can either say
     $date->is_leap or 	is_leap Date::Convert::Hebrew 5757

Private functions that are required of all subclasses
-----------------------------------------------------

   You shouldn't call these, but if you want to add a class, you'll need to
write them!  Or it, since at the moment, there's only one.

initialize
     Read in args and initialize object based on their values.  If there
     are no args, initialize with the base class's initialize (which will
     initialize in the default way described above for new.)  Note the
     American spelling of "initialize": "z", not "s".

SUBCLASS SPECIFIC NOTES
=======================

Absolute
--------

   The "Absolute" calendar is just the number of days from a certain
reference point.  Calendar people should recognize it as the "Julian Day
Number" with one minor modification:  When you convert a Gregorian day n
to absolute, you get the JDN of the Gregorian day from noon on.

   Since "absolute" has no notion of years it is an extremely easy calendar
for conversion purposes.  I stole the "absolute" calendar format from
Reingold's emacs calendar mode, for debugging purposes.

   The subclass is little more than the base class, and as the lowest
common denominator, doesn't have any special functions.

Gregorian
---------

   The Gregorian calendar is a purely solar calendar, with a month that is
only an approximation of a lunar month.  It is based on the old Julian
(Roman) calendar.  This is the calendar that has been used by most of the
Western world for the last few centuries.  The time of its adoption varies
from country to country.  This *::Gregorian* allows you to extrapolate
back to 1 A.D., as per the prorgamming tradition, even though the calendar
definitely was not in use then.

   In addition to the required methods, Gregorian also has year, month,
day, and is_leap methods.  As mentioned above, is_leap can also be used
statically.

Hebrew
------

   This is the traditional Jewish calendar.  It's based on the solar year,
on the lunar month, and on a number of additional rules created by Rabbis
to make life tough on people who calculate calendars.  :)  If you actually
wade through the source, you should note that the seventh month really
does come before the first month, that's not a bug.

   It comes with the following additional methods: year, month, day,
is_leap, *rosh*, *part_add*, and *part_mult*.  *rosh* returns the absolute
day corresponding to "Rosh HaShana" (New year) for a given year, and can
also be invoked as a static.  *part_add* and *part_mult* are useful
functions for Hebrew calendrical calculations are not for much else; if
you're not familiar with the Hebrew calendar, don't worry about them.

Islamic
-------

   The traditional Muslim calendar, a purely lunar calendar with a year
that is a rough approximation of a solar year.  Currently unimplemented.

Julian
------

   The old Roman calendar, allegedly named for Julius Caesar.  Purely
solar, with a month that is a rough approximation of the lunar month.  Used
extensively in the Western world up to a few centuries ago, then the West
gradually switched over to the more accurate Gregorian.  Now used only by
the Eastern Orthodox Church, AFAIK.

ADDING NEW SUBCLASSES
=====================

   This section describes how to extend *Date::Convert* to add your
favorite date formats.  If you're not interested, feel free to skip it.  :)

   There are only three function you *have* to write to add a new subclass:
you need initialize, date, and date_string.  Of course, helper functions
would probably help. . .  You do not need to write a new or convert
function, since the base class handles them nicely.

   First, a quick conceptual overhaul: the base class uses an "absolute day
format" (basically "Julian day format") borrowed from emacs.  This is just
days numbered absolutely from an extremely long time ago.  It's really
easy to use, particularly if you have emacs and emacs' *calendar mode*.
Each Date::Convert object is a reference to a hash (as in all OO perl) and
includes a special "absol" value stored under a reserved "absol" key.  When
initialize initializes an object, say a Gregorian date, it stores whatever
data it was given in the object and it also calculates the "absol"
equivalent of the date and stores it, too.  If the user converts to another
date, the object is wiped clean of all data except "absol".  Then when the
date method for the new format is called, it calculates the date in the
new format from the "absol" data.

   Now that I've thoroughly confused you, here's a more compartmentalized
version:

initialize
     Take the date supplied as argument as appropriate to the format, and
     convert it to "absol" format.  Store it as `$$self{'absol'}'.  You
     might also want to store other data, ie. *::Gregorian* stores
     `$$self{'year'}', `$$self{'month'}', and `$$self{'day'}'.  If no args
     are supplied, explicitly call the base class's initialize, ie.
     `Date::Convert::initialize', to initialize with a default 'absol' date
     and nothing else.

     NOTE:  I may move the default behavior into the new constructor.

date
     Return the date in a appropriate format.  Note that the only fact that
     date can take as given is that `$$self{'absol'}' is defined, ie. this
     object may not have been initialized by the initialize of this
     object's class.  For instance, you might have it check if
     `$$self{'year'}' is defined.  If it is, then you have the year
     component, otherwise, you calculate year from `$$self{'absol'}'.

date_string
     This is the easy part.  Just call date, then return a pretty string
     based on the values.

   NOTE: The *::Absolute* subclass is a special case, since it's nearly an
empty subclass (ie. it's just the base class with the required methods
filled out).  Don't use it as an example!  The easiest code to follow would
have been *::Julian* except that Julian inherits from *::Gregorian*.
Maybe I'll reverse that. . .

EXAMPLES
========

     #!/usr/local/bin/perl5 -w

     use Date::Convert;

     $date=new Date::Convert::Gregorian(1974, 11, 27);
     convert Date::Convert::Hebrew $date;
     print $date->date_string, "\n";

   My Gregorian birthday is 27 Nov 1974.  The above prints my Hebrew
birthday.

     convert Date::Convert::Gregorian $date;
     print $date->date_string, "\n";

   And that converts it back and prints it in Gregorian.

     $guy = new Date::Convert::Hebrew (5756, 7, 8);
     print $guy->date_string, " -> ";
     convert Date::Convert::Gregorian $guy;
     print $guy->date_string, "\n";

   Another day, done in reverse.

     @a=(5730, 3, 2);
     @b=(new Date::Convert::Hebrew @a)->date;
     print "@a\n@b\n";

   The above should be an identity for any list @a that represents a
legitimate date.

     #!/usr/local/bin/perl -an

     use Date::Convert;

     $date = new Date::Convert::Gregorian @F;
     convert Date::Convert::Hebrew $date;
     print $date->date_string, "\n";

   And that's a quick Greg -> Hebrew conversion program, for those times
when people ask.

SEE ALSO
========

   perl(1), Date::DateCalc(3)

VERSION
=======

   Date::Convert 0.15 (pre-alpha)

AUTHOR
======

   Mordechai T. Abzug <morty@umbc.edu>

ACKNOWLEDGEMENTS AND FURTHER READING
====================================

   The basic idea of using astronomical dates as an intermediary between
all calculations comes from Dershowitz and Reingold.  Reingold's code is
the basis of emacs's calendar mode.  Two papers describing their work
(which I used to own, but lost!  Darn.) are:

   "Calendrical Calculations" by Nachum Dershowitz and Edward M. Reingold,
*Software-Practice and Experience*, Volume 20, Number 9 (September, 1990),
pages 899-928.  "Calendrical Calculations, Part II: Three Historical
Calendars" by E. M. Reingold, N. Dershowitz, and S. M. Clamen,
*Software-Practice and Experience*, Volume 23, Number 4 (April, 1993),
pages 383-404.

   They were also scheduled to come out with a book on calendrical
calculations in Dec. 1996, but as of March 1997, it still isn't out yet.

   The Hebrew calendrical calculations are largely based on a cute little
English book called *The Hebrew Calendar* (I think. . .)  in a box
somewhere at my parents' house.  (I'm organized, see!)  I'll have to dig
around next time I'm there to find it.  If you want to access the original
Hebrew sources, let me give you some advice: Hilchos Kiddush HaChodesh in
the Mishneh Torah is not the Rambam's most readable treatment of the
subject.  He later wrote a little pamphlet called "MaAmar HaEibur" which is
both more complete and easier to comprehend.  It's included in "Mich't'vei
HaRambam" (or some such; I've *got* to visit that house), which was
reprinted just a few years ago.

   Steffen Beyer's Date::DateCalc showed me how to use MakeMaker and write
POD documentation.  Of course, any error is my fault, not his!

COPYRIGHT
=========

   Copyright 1997 by Mordechai T. Abzug

LICENSE STUFF
=============

   You can distribute, modify, and otherwise mangle Date::Convert under the
same terms as perl.

Calculate the Discordian date of a particular day
*************************************************

NAME
====

   Date::Discordian - Calculate the Discordian date of a particular day

SYNOPSIS
========

     use Date::Discordian;
     $discordian = discordian(time);
     $epochtime = inverse_discordian('bureaucracy 47, 3166');

DESCRIPTION
===========

   Calculate the Discordian date of a particular 'real' date.

   Date::Discordian exports two functions - discordian(), and
inverse_discordian. `discordian()', when given a time value, returns a
string, giving the Discordian date for the given day.
*inverse_discordian()*, given a Discordian date in the same format that
`discordian()' emits, returns an epoch time value. It is pretty picky
about time format. Pity.

   I'm really not sure how this would ever be used, so if you actually use
this, send me a note.

Bugs/To Do
==========

     a timestamp-ish form of Discordian (similar to Julian)
     more chicken references.
          Accept C<ddate>-style input.

General comments
================

   You can find out more about the Discordian Calendar at
http://www.concentric.net/~darkfox/DiscoCal.html and at a plethora of
other sites on the Internet.

   It is related to the Principia Discordia
(http://members.xoom.com/ffungo/titlepage.html) and the "religion" of
Discordianism. I suppose that there are people that actually take this
sort of thing seriously. But then, there are people that collect Beanie
Babies, so what do you expect?

AUTHOR
======

     Rich Bowen <rbowen@rcbowen.com>
               -- (doubter of the wisdom of Discordianism)
     Matt Cashner <sungo@earthling.net>
               -- (Sungo the Funky)

   $Header$

   $Log$

Calculates Easter for any given year
************************************

NAME
====

   Date::Easter - Calculates Easter for any given year

SYNOPSIS
========

     use Date::Easter;
     ($month, $day) = julian_easter(1752);
     ($month, $day) = easter(1753);
     ($month, $day) = gregorian_easter(1753);

DESCRIPTION
===========

   Calculates Easter for a given year.

   easter() is, for the moment, an alias to gregorian_easter(), since
that's what most people use now.

AUTHOR
======

   Rich Bowen <rbowen@rcbowen.com>

To Do
=====

   I need to put some real tests in test.pl

   Since the dates that various countries switched to the Gregorian
calendar vary greatly, it's hard to figure out when to use which method.
Perhaps some sort of locale checking would be cool?

Other Comments
==============

   Yes, Date::Manip already has code in it to do this. But Date::Manip is
very big, and rather slow. I needed something faster and smaller, and did
not need all that other stuff. And I have a real interest in date
calculations, so I thought this would be fun.  Date::Manip is a very cool
module. I use it myself.

   See also http://www.pauahtun.org/CalendarFAQ/cal/node3.html for more
details on calculating Easter.

Date formating subroutines
**************************

NAME
====

   Date::Format - Date formating subroutines

SYNOPSIS
========

     use Date::Format;

     @lt = timelocal(time);

     print time2str($template, time);
     print strftime($template, @lt);

     print time2str($template, time, $zone);
     print strftime($template, @lt, $zone);

     print ctime(time);
     print ascctime(@lt);

     print ctime(time, $zone);
     print asctime(@lt, $zone);

DESCRIPTION
===========

   This module provides routines to format dates into ASCII strings. They
correspond to the C library routines strftime and ctime.

time2str(TEMPLATE, TIME [, ZONE])
     `time2str' converts TIME into an ASCII string using the conversion
     specification given in TEMPLATE. `ZONE' if given specifies the zone
     which the output is required to be in, `ZONE' defaults to your
     current zone.

strftime(TEMPLATE, TIME [, ZONE])
     strftime is similar to `time2str' with the exception that the time is
     passed as an array, such as the array returned by localtime.

ctime(TIME [, ZONE])
     ctime calls `time2str' with the given arguments using the conversion
     specification `"%a %b %e %T %Y\n"'

asctime(TIME [, ZONE])
     asctime calls `time2str' with the given arguments using the
     conversion specification `"%a %b %e %T %Y\n"'

MULTI-LANGUAGE SUPPORT
======================

   Date::Format is capable of formating into several languages, these are
English, French, German and Italian. Changing the language is done via a
static method call, for example

     Date::Format->language('German');

   will change the language in which all subsequent dates are formatted.

   This is only a first pass, I am considering changing this to be

     $lang = Date::Language->new('German');
     $lang->time2str("%a %b %e %T %Y\n", time);

   I am open to suggestions on this.

CONVERSION SPECIFICATION
========================

   Each conversion specification  is  replaced  by  appropriate characters
 as   described  in  the  following  list.   The appropriate  characters
are  determined  by   the   LC_TIME category of the program's locale.

     %%	PERCENT
     %a	day of the week abbr
     %A	day of the week
     %b	month abbr
     %B 	month
     %c	MM/DD/YY HH:MM:SS
     %C 	ctime format: Sat Nov 19 21:05:57 1994
     %d 	numeric day of the month, with leading zeros (eg 01..31)
     %e 	numeric day of the month, without leading zeros (eg 1..31)
     %D 	MM/DD/YY
     %h 	month abbr
     %H 	hour, 24 hour clock, leading 0's)
     %I 	hour, 12 hour clock, leading 0's)
     %j 	day of the year
     %k 	hour
     %l 	hour, 12 hour clock
     %m 	month number, starting with 1
     %M 	minute, leading 0's
     %n 	NEWLINE
     %o	ornate day of month -- "1st", "2nd", "25th", etc.
     %p 	AM or PM
     %q	Quarter number, starting with 1
     %r 	time format: 09:05:57 PM
     %R 	time format: 21:05
     %s	seconds since the Epoch, UCT
     %S 	seconds, leading 0's
     %t 	TAB
     %T 	time format: 21:05:57
     %U 	week number, Sunday as first day of week
     %w 	day of the week, numerically, Sunday == 0
     %W 	week number, Monday as first day of week
     %x 	date format: 11/19/94
     %X 	time format: 21:05:57
     %y	year (2 digits)
     %Y	year (4 digits)
     %Z 	timezone in ascii. eg: PST
     %z	timezone in format -/+0000

   `%d', `%e', `%H', `%I', `%j', `%k', `%l', `%m', `%M', `%q', `%y' and
`%Y' can be output in Roman numerals by prefixing the letter with O, e.g.
`%OY' will output the year as roman numerals.

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

COPYRIGHT
=========

   Copyright (c) 1995-1999 Graham Barr. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Date operations based on the horoscope calendar
***********************************************

NAME
====

   Date::Horoscope - Date operations based on the horoscope calendar

SYNOPSIS
========

   #!/usr/bin/perl

   use Date::Horoscope; use Date::Manip;

   $date='1969-05-11';

   $zodiac_sign_name =  Date::Horoscope::locate($date); $zodiac_sign_posn
=
$Date::Horoscope::horoscope{Date::Horoscope::locate($date)}->{position},$/;

DESCRIPTION
===========

   This module was written to help with zodiac processing.  It returns an
all-lowercase zodiac sign name based on a given date parseable by
Date::Manip.  You can take this string and use it as a key to %horoscope
to get a position in the zodiac cycle.

API
===

locate
------

   Provide any date parseable by Date::Manip and it turns an all-lowercase
zodiac name.

%horoscope
----------

   This hash contains the position, and start and end dates for a zodiac
sign.  The zodiac starts with Aries as far as I know. Some idiot didn't
think taurus was number 1.

OTHER
=====

   I cannot say how tickled I am that RCS changes by <scalar>Date code into
as RCS string for me.

AUTHOR
======

   T.M. Brannon

SEE ALSO
========

   Date::Manip

Perl extension for converting dates between ISO and Gregorian formats.
**********************************************************************

NAME
====

   Date::ISO - Perl extension for converting dates between ISO and
Gregorian formats.

SYNOPSIS
========

     use Date::ISO;
     ($yearnumber, $weeknumber, $weekday) = iso($year, $month, $day);
     ($yearnumber, $weeknumber, $weekday) = localiso(time);

DESCRIPTION
===========

   Convert dates between ISO and Gregorian formats.

iso
---

     ($year, $week, $day) = iso($year, $month, $day);

   Returns the ISO year, week and day, when given the year, month, and day,
as returned by localtime. (That is, months are zero-based, years are
-1900.)

localiso
--------

     ($year, $week, $day) = localiso(time);

   Given a time value (epoch time) returns the ISO year, week, and day.

AUTHOR
======

   Rich Bowen <rbowen@rcbowen.com>

Additional comments
===================

   For more information about this calendar, please see:

   http://personal.ecu.edu/mccartyr/ISOwdALG.txt

   http://personal.ecu.edu/mccartyr/isowdcal.html

handling of temporal intervals based on Date::Manip
***************************************************

NAME
====

   Date::Interval - handling of temporal intervals based on Date::Manip

SYNOPSIS
========

     use Date::Interval;

     ### class methods ###
     Date::Interval->setDefaultIntervalType ($Date::Interval::OPEN_INT);
     $int_open = new Date::Interval ("10-10-1997", "10-20-1997");
     print "$int_open\n"        # prints  '(10-10-1997, 10-20-1997)

     $nDefaultType = Date::Interval->getDefaultIntervalType;

     ### constructor ##
     $i1 = new Date::Interval ("10-30-1997", "12-01-1998");
     $i2 = new Date::Interval ("01-20-1996", "11-01-1997", $Date::Interval::RIGHT_OPEN_INT);

     use Date::Manip;
     $date1 = &ParseDate ("10-10-1997");
     $date2 = &ParseDate ("10-15-1997");
     $int = new Date::Interval ($d1, $d2);

     ### Overload operators ###
     $i3 = $i1 + $i2;          # + gives the sum of intervals if the overlap
     print "$i3\n";            # prints '[01-20-1997, 12-01-1998)'

     $i4 = $i1 - $i2;          # - gives difference of intervals of intervals
     print "$i4\n";            # prints '[11-01-1997, 12-01-1998)'

     $i5 = $i1 - $i1;
     print "$i5\n";            # prints '<empty>'

     ### <Allen overlap type> ###
     $X = new Date::Interval (<parameters>);
     $Y = new Date::Interval (<parameters>);
                               ###  relationship between intervals ###
     $Y->AllenBefore ($X);             YYYYYY XXXXXX

     $Y->AllenMeets ($X);              YYYYYYXXXXXX

     $Y->AllenLeftOverlaps ($X);          XXXXXX
                                       YYYYYY

     $Y->AllenLeftCovers ($X);            XXXXXX
                                       YYYYYYYYY

     $Y->AllenCovers ($X);                XXXXXX
                                       YYYYYYYYYYYY

     $Y->AllenStarts ($X);             XXXXXX
                                       YYY

     $Y->AllenEquals ($X);             XXXXXX
                                       YYYYYY

     $Y->AllenRightCovers ($X);        XXXXXX
                                       YYYYYYYYY

     $Y->AllenDuring ($X);             XXXXXX
                                        YYYY

     $Y->AllenFinishes ($X);           XXXXXX
     				        YYYY

     $Y->AllenRightOverlaps ($X);      XXXXXX
                                          YYYYYY

     $Y->AllenExtends ($X);            XXXXXXYYYYYY

     $Y->AllenAfter ($X):              XXXXXX YYYYYY

     ### <overlap type> ###
     $Y->before ($X)         same as  $Y->AllenBefore ($X)
     $Y->meets  ($X)         same as  $Y->AllenMeets ($X)

     $Y->leftOverlaps ($X)   same as  $Y->AllenLeftOverlaps ($X)  or
                                      $Y->AllenStarts ($X)

     $Y->totalOverlaps ($X)  same as  $Y->AllenCovers ($X)        or
                                      $Y->AllenLeftCovers ($X)    or
                                      $Y->AllenRightCovers ($X)   or
                                      $Y->AllenEquals ($X)

     $Y->rightOverlaps ($X)  same as  $Y->AllenFinishes ($X)      or
                                      $Y->AllenRightCovers

     $Y->during ($X)         same as  $Y->AllenDuring ($X)
     $Y->extends ($X)        same as  $Y->AllenExtends ($X)
     $Y->after ($X)          same as  $Y->AllenAfter ($X)

     ### <interval type> ###
     $closed_int = new Interval ("10-10-1997", "10-20-1997", $CLOSED_INT);
     print "$closed_int\n";      # prints [10-10-1997, 10-20-1997]

     $left_open_int = new Interval ("10-10-1997", "10-20-1997", $LEFT_OPEN_INT);
     print "$left_open_int\n";   # prints (10-10-1997, 10-20-1997]

     $right_open_int = new Interval ("10-10-1997", "10-20-1997", $RIGHT_OPEN_INT);
     print "$right_open_int\n";  # prints [10-10-1997, 10-20-1997)

     $open_int = new Interval ("10-10-1997", "10-20-1997", $OPEN_INT);
     print "$open_int\n";         # prints (10-10-1997, 10-20-1997)

     ### check and get overlapping interval ###
      $i1 = new Interval ("10-30-1997", "12-01-1998");
      $i2 = new Interval ("01-20-1996", "11-01-1997");
      $i3 = new Interval ("01-01-1995", "04-30-1995");

     if ($i1->overlaps ($i2)) {
         $i4 = $i1->getOverlap($i2);
         print "$i4\n";              # prints [10-30-1997, 11-01-1997)
     }
     if ($i1->overlaps ($i3)){       # tests fails, does not print anything
         $i5 = $i1->getOverlap($i2);
         print "$i5\n";
     }

DESCRIPTION
===========

     All strings which can be used to create a Date::Manip date object
     can be used to create an Interval. However, the start date must be
     greater than the stop date. Because Date::Manip both handles dates
     and times this module can also handle both dates and times.

     The comparison of intervals is based on the 13 ways intervals can
     overlap as defined by J.F. Allen (See the litteratur). Further, I
     have included a small number of interval comparison which are
     handy if you are only interested in getting the overlapping region
     of two intervals.

Open and Closed Intervals
-------------------------

     A closed interval is closed in an interval where both the start
     and the stop values are included in the interval. As an example
     [10-10-1997, 10-30-1997] both the 10th and the 30th of November is
     a part of the interval.

     An open interval is an interval where the start value or the stop
     value are not included in the interval. In the right open interval
     [10-10-1997, 10-30-1997) the 10th of November is a part of the
     interval but the 30th of November is not.

     There are three types of open intervals
     - right open intervals, e.g., [10-10-1997, 10-30-1997)
     - left open intervals, e.g., (10-10-1997, 10-30-1997]
     - open intervals, e.g., (10-10-1997, 10-30-1997)

Absolute and Relative Intervals
-------------------------------

     An absolute interval is an interval where the start and the stop
     values of the inteval are anchored on the time line, i.e., they
     are specific dates as 04-30-1994.

     A relative interval is an interval where the start or the stop
     value is not anchored on the time line, e.g., 'tomorrow'. When
     'tomorrow' evaluated now it has one value when evaluated a month
     from now it has a different values.

     Date::Interval fully supports absolute intervals and to a limited
     degree relative intervals.

     The relative intervals supported currently (NOW :-)) are of the
     following type.

     $int1 = new Date::Interval("10-21-1997", 'NOBIND NOW');

     Relative start and stop values are prefixed with the word
     'NOBIND'. In the example 'NOBIND NOW' means that the current time
     (now) whenever it asked for. So if you ask for the length of $int1
     at the 24th of October you get 3 days. If you ask for the length
     of $int1 again at the 28th of October you get 7 days.

     I am working on additional support for relative Intervals.

Defaults
--------

     The default interval type is right open intervals. Stick to this
     interval type if you want to keep life simple.

     To use Date::Manip the time zone variable must be set. It is
     default set to Central European Time (CET). For Americans, this is
     the Capital of Stockholm :-).

     To change the time zone, e.g., to Eastern Standard Time (EST) put
     in our script $Date::Manip::TZ = 'EST'; (As an European I assume
     this must be close to Atlanta, New Mexico).

     The default input format is default of Date::Manip, that is
     "10-12-1997" is the 12th of October 1997 not the 10th of December
     1997. To change the input format, e.g., put in our script
     &Date::Manip::Date_Init("DateFormat=non-US");

     The default output format is MM-DD-YYY. It Can be changed by
     calling Interval->setDisplayFormat(<string>). Where <string> is
     a UnixDate format in Date::Manip.

     The default separator when an interval is printed is the special
     variable $, $OUTPUT_FIELD_SEPARATOR. If this value is not defined
     ',' is used.

The "Fixed" Clock
-----------------

     The module has a class variable $NOW which contains the current
     time. The current time must be fixed when relative intervals are
     compared, otherwise the comparison may return the wrong result. As
     an example if the two intervals [NOBIND NOW, NOBIND NOW) [NOBIND
     NOW, NOBIND NOW) are compared for equality the result is
     true. However, if the equality comparison is implemented by asking
     four time for the current time the times returned may be different
     because the *real world clock* ticks between the invocations of
     getting the current time. If the clock ticks the equality
     predicate in the example returns false.

     Because different interval objects must be compared with the same
     clock the variable must be a class variable and not an instance
     variable. $NOW is used in the method _to_date.

"Non-terminals" used in the Source Code
---------------------------------------

<delta>              ::= Date::Manip delta data type
<date>               ::= Date::Manip data type
<interval end>       ::= CLOSE || OPEN
<interval type>      ::= CLOSED_INT || OPEN_INT || LEFT_OPEN_INT || RIGHT_OPEN_INT
<value type>         ::= ABSOLUTE || RELATIVE
<overlap type>       ::= How two intervals overlaps
<Allen overlap type> ::= How two intervals Allen overlaps
BUGS
====

     Tried my best to avoid them send me an email if you are bitten by
     a bug.

     Note, the module cannot handle subtract intervals which overlap
     with "during" overlaps, this results in two intervals (currently
     results in an empty interval)

TODO
====

     - Cannot take references to dates as input parameters for the
       constructors

     - Cannot subtract intervals which overlap with "during" overlaps,
       this results in two intervals (currently results an error message and
       an empty interval is returned)

     - Implement getOverlap and overloaded operators for relative intervals

Change History
==============

     ### Changes version 0.01 => 0.02 ###
     - Add overload  <, >, ==, !=, <=>.
     - Add stringLength, to print length of interval in a more readable way.
     - Changed the default separator to the $, special variable
     - Added support for comparison of relative intervals

     Changes thanks to Tim Bruce
     - Changed the module name from Interval to Date::Interval
     - Added methods getStart and getStop.
     - Added method lengthString to print nicely the length of the
       interval.
     - Changed the default output format to be similar to the
       default input format
     - Taken BEGIN {$Date::Manip::TZ = "CET"; &Date_Init ("DateFormat=non-US");}
       out because it is anti-social :-)
     - Added to POD that the both dates and times can be used with intervals
     - Added to POD the description of open and closed intervals

LITTERATURE
===========

     Allen, J. F., "An Interval-Based Representation of Temporal Knowledge",
     Communication of the ACM, 26(11) pp. 832-843, November 1983.

AUTHOR
======

   Kristian Torp <`torp@cs.auc.dk'>

Blurb
=====

   Date::Lima - Perl extension for dates like those from
conv_date() in the Lima mudlib (2d4h1m4s).

A brief example
===============

Simple
------

     use Date::Lima qw/beek_date/;

     for $i (25, 85, 300, 6000, 7654, 10000, 7654321) {
         printf "\%7d seconds: \%s\n", $i, beek_date($i);
     }

Webified
--------

     use Date::Lima qw/:all/;
     use CGI qw/:html/;

     my $a = new CGI;

     set_pre_element_string  $a->start_font({-face=>"helvetica"});
     set_post_element_string $a->end_font;

     for $i (25, 85, 300, 6000, 7654, 10000, 7654321) {
         printf "\%7d seconds: \%s\n", $i, beek_date($i);
     }

Exported Functions
==================

set_pre_element_string
----------------------

     The single argument hereto is the text to put before
     each duration element.

set_post_element_string
-----------------------

     The single argument hereto is the text to put after
     each duration element.

beek_date
---------

     The first argument is either a number of seconds or
     a duration string in HH:MM:SS format.  It returns
     the date in lima who-list fasion.  It's called
     beek date because, AFAIK, it was written by beek.

Authors
=======

The best way to reach us
------------------------

   <telnet://bakhara.org:4000>

Lord Dorn the God of White Majik
--------------------------------

   <dorn@bakhara.org>  Authored the module the documentation, and did
minor re-writes to get the functions to module-like state.

Lord Nichus the God of Black Majik
----------------------------------

   <nichus@bakhara.org> Wrote all the actual code used to generate the
date strings.

See Also
========

   perl(1).

date manipulation routines
**************************

NAME
====

   Date::Manip - date manipulation routines

SYNOPSIS
========

     use Date::Manip;

     $date=&ParseDate(\@args);
     $date=&ParseDate($string);
     $date=&ParseDate(\$string);

     @date=&UnixDate($date,@format);
     $date=&UnixDate($date,@format);

     $delta=&ParseDateDelta(\@args);
     $delta=&ParseDateDelta($string);
     $delta=&ParseDateDelta(\$string);

     @str=&Delta_Format($delta,$dec,@format);
     $str=&Delta_Format($delta,$dec,@format);

     $recur=&ParseRecur($string,$base,$date0,$date1,$flags);
     @dates=&ParseRecur($string,$base,$date0,$date1,$flags);

     $flag=&Date_Cmp($date1,$date2);

     $d=&DateCalc($d1,$d2 [,$errref] [,$del]);

     $date=&Date_SetTime($date,$hr,$min,$sec);
     $date=&Date_SetTime($date,$time);

     $date=&Date_SetDateField($date,$field,$val [,$nocheck]);

     $date=&Date_GetPrev($date,$dow,$today,$hr,$min,$sec);
     $date=&Date_GetPrev($date,$dow,$today,$time);

     $date=&Date_GetNext($date,$dow,$today,$hr,$min,$sec);
     $date=&Date_GetNext($date,$dow,$today,$time);

     $version=&DateManipVersion;

     $flag=&Date_IsWorkDay($date [,$flag]);

     $date=&Date_NextWorkDay($date,$off [,$time]);
     $date=&Date_PrevWorkDay($date,$off [,$time]);

     $name=&Date_IsHoliday($date);

     $listref=&Events_List($date);
     $listref=&Events_List($date0,$date1);

     &Date_Init();
     &Date_Init("VAR=VAL","VAR=VAL",...);
     @list=&Date_Init();
     @list=&Date_Init("VAR=VAL","VAR=VAL",...);

   The above routines all check to make sure that Date_Init is called.  If
it hasn't been, they will call it automatically.  As a result, there is
usually no need to call Date_Init explicitely unless you want to change
some of the config variables (described below).

   The following routines are used by the above routines (though they can
also be called directly).  $y may be entered as either a 2 or 4 digit year
(it will be converted to a 4 digit year based on the variable YYtoYYYY
described below).  Month and day should be numeric in all cases.  Most (if
not all) of the information below can be gotten from UnixDate which is
really the way I intended it to be gotten, but there are reasons to use
these (these are significantly faster).

   ***NOTE*** Unlike the routines listed above, the following routines do
NOT explicitely call Date_Init.  You must make sure that Date_Init has been
called, either by you explicitely, or by one of the above routines before
you use these routines.

     $day=&Date_DayOfWeek($m,$d,$y);
     $secs=&Date_SecsSince1970($m,$d,$y,$h,$mn,$s);
     $secs=&Date_SecsSince1970GMT($m,$d,$y,$h,$mn,$s);
     $days=&Date_DaysSince1BC($m,$d,$y);
     $day=&Date_DayOfYear($m,$d,$y);
     $days=&Date_DaysInYear($y);
     $wkno=&Date_WeekOfYear($m,$d,$y,$first);
     $flag=&Date_LeapYear($y);
     $day=&Date_DaySuffix($d);
     $tz=&Date_TimeZone();
     ($y,$m,$d,$h,$mn,$s)=&Date_NthDayOfYear($y,$n);

DESCRIPTION
===========

   This is a set of routines designed to make any common date/time
manipulation easy to do.  Operations such as comparing two times,
calculating a time a given amount of time from another, or parsing
international times are all easily done.  From the very beginning, the main
focus of Date::Manip has been to be able to do ANY desired date/time
operation easily, not necessarily quickly.  Also, it is definitely oriented
towards the type of operations we (as people) tend to think of rather than
those operations used routinely by computers.  There are other modules that
can do a subset of the operations available in Date::Manip much quicker
than those presented here, so be sure to read the section SHOULD I USE
DATE::MANIP below before deciding which of the Date and Time modules from
CPAN is for you.

   Date::Manip deals with time as it is presented the Gregorian calendar
(the one currently in use).  The Julian calendar defined leap years as
every 4th year.  The Gregorian calendar improved this by making every
100th year NOT a leap year, unless it was also the 400th year.  The
Gregorian calendar has been extrapolated back to the year 0000 AD and
forward to the year 9999 AD.  Note that in historical context, the Julian
calendar was in use until 1582 when the Gregorian calendar was adopted by
the Catholic church.  Protestant countries did not accept it until later;
Germany and Netherlands in 1698, British Empire in 1752, Russia in 1918.
Note that the Gregorian calendar is itself imperfect and at some point
will need to be corrected.  No attempt is made to correct for that, and my
great grandchildren will be long dead before this even occurs, so it's not
an immediate concern (isn't this the same type of attitude that caused the
great Y2K problem? :-).

   Date::Manip is therefore not equipped to truly deal with historical
dates, but should be able to perform (virtually) any operation dealing
with a modern time and date.

   Date::Manip has (or will have) functionality to work with several
fundamental types of data.

DATE
     Although the word date is used extensively here, it is actually
     somewhat misleading.  Date::Manip works with the full date AND time
     (year, month, day, hour, minute, second and weeks when appropriate).
     It doesn't work with fractional seconds.  Timezones are also
     supported to some extent.

     NOTE:  Much better support for timezones (including Daylight Savings
     Time) is planned for the future.

DELTA
     This refers to a duration or elapsed time.  One thing to note is
     that, as used in this module, a delta refers only to the amount of
     time elapsed.  It includes no information about a starting or ending
     time.

RECURRENCE
     A recurrence is simply a notation for defining when a recurring event
     occurs.  For example, if an event occurs every other Friday or every
     4 hours, this can be defined as a recurrence.  With a recurrence and a
     starting and ending date, you can get a list of dates in that period
     when a recurring event occurs.

GRAIN
     The granularity of a time basically refers to how accurate you wish to
     treat a date.  For example, if you want to compare two dates to see if
     they are identical at a granularity of days, then they only have to
     occur on the same day.  At a granularity of an hour, they have to
     occur within an hour of each other, etc.

     NOTE:  Support for this will be added in the future.

HOLIDAYS and EVENTS
     These are basically a named time.  Holidays are used in business mode
     calculations.  Events allow things like calendar and scheduling
     applications to be designed much more easily.

   Among other things, Date::Manip allow you to:

   1.  Enter a date and be able to choose any format convenient

   2.  Compare two dates, entered in widely different formats     to
determine which is earlier

   3.  Extract any information you want from ANY date using a     format
string similar to the Unix date command

   4.  Determine the amount of time between two dates

   5.  Add a time offset to a date to get a second date (i.e.
determine the date 132 days ago or 2 years and 3 months     after Jan 2,
1992)

   6.  Work with dates with dates using international formats     (foreign
month names, 12/10/95 referring to October     rather than December, etc.).

   7.  To find a list of dates where a recurring event happens.

   Each of these tasks is trivial (one or two lines at most) with this
package.

EXAMPLES
========

   In the documentation below, US formats are used, but in most (if not
all) cases, a non-English equivalent will work equally well.

   1.  Parsing a date from any convenient format

     $date=&ParseDate("today");
     $date=&ParseDate("1st thursday in June 1992");
     $date=&ParseDate("05/10/93");
     $date=&ParseDate("12:30 Dec 12th 1880");
     $date=&ParseDate("8:00pm december tenth");
     if (! $date) {
       # Error in the date
     }

   2.  Compare two dates

     $date1=&ParseDate($string1);
     $date2=&ParseDate($string2);
     $flag=&Date_Cmp($date1,$date2);
     if ($flag<0) {
       # date1 is earlier
     } elsif ($flag==0) {
       # the two dates are identical
     } else {
       # date2 is earlier
     }

   3.  Extract information from a date.

     print &UnixDate("today","It is now %T on %b %e, %Y.");
       =>  "It is now 13:24:08 on Feb  3, 1996."

   4.  The amount of time between two dates.

     $date1=&ParseDate($string1);
     $date2=&ParseDate($string2);
     $delta=&DateCalc($date1,$date2,\$err);
       => 0:0:WK:DD:HH:MM:SS   the weeks, days, hours, minutes,
                               and seconds between the two
     $delta=&DateCalc($date1,$date2,\$err,1);
       => YY:MM:WK:DD:HH:MM:SS  the years, months, etc. between
                                the two

     Read the documentation below for an explanation of the
     difference.

   5.  To determine a date a given offset from another.

     $date=&DateCalc("today","+ 3hours 12minutes 6 seconds",\$err);
     $date=&DateCalc("12 hours ago","12:30 6Jan90",\$err);

     It even works with business days:

     $date=&DateCalc("today","+ 3 business days",\$err);

   6.  To work with dates in another language.

     &Date_Init("Language=French","DateFormat=non-US");
     $date=&ParseDate("1er decembre 1990");

   7.  To find a list of dates where a recurring event happens
(including quite complex ones).

     # To find the 2nd tuesday of every month
     @date=&ParseRecur("0:1*2:2:0:0:0",$base,$start,$stop);

     # To find the Monday after easter in 1997-1999.
     @date=&ParseRecur("*1997-1999:0:0:0:0:0:0*EASTER,ND1");

   NOTE: Some date forms do not work as well in languages other than
English, but this is not because Date::Manip is incapable of doing so
(almost nothing in this module is language dependent).  It is simply that
I do not have the correct translation available for some words.  If there
is a date form that works in English but does not work in a language you
need, let me know and if you can provide me the translation, I will fix
Date::Manip.

SHOULD I USE DATE::MANIP
========================

   If you look in CPAN, you'll find that there are a number of Date and
Time packages.  Is Date::Manip the one you should be using?  In my opinion,
the answer is no about 90% of the time.  This sounds odd coming from the
author of the software, but read on.

   Date::Manip is written entirely in perl.  It's the most powerful of the
date modules.  It's also the biggest and slowest.

   Since Date::Manip is written entirely in perl, no C compiler is
required to install it.  In fact, Date::Manip has no dependancy on
anything not included in a standard perl distribution.  To my knowledge,
none of the other time or date modules have any dependancies either,
except that Date::Calc is written in C and therfore requires that you have
a C compiler OR get a pre-compiled version of the module.  Since most (if
not all) unix platforms come with a C compiler, and since pre-compiled
versions of many of the modules are available for WinXX platforms, the
fact that Date::Manip is written in perl is rarely a huge advantage.  On
the other hand, modules written in C are significantly faster than their
perl counterparts (at least if they're done right).  The TimeDate and
Time-modules modules are written in perl.  The Date::Calc module is
written in C.  Between these three, most of your common date operations
can be done.

   Date::Manip is certainly the most powerful of the Date modules.  To the
best of my knowledge, it will do everything that any other date module will
do (not just the ones I listed above), and there are a number of features
that Date::Manip has that none of the other modules have.  Date::Manip is
the "Swiss Army Knife" of Date modules.  I'm trying to build a library
which can do _EVERY_ conceivable date/time manipulation that you'll run
into in everyday life.

   The downside is that Date::Manip is slow.  The much simpler Date modules
listed above are all faster (usually by a significant amount).  Although I
am working on making Date::Manip faster, it will never be as fast as these
modules.  And before anyone asks, Date::Manip will never be translated to C
(at least by me).  I write C because I have to.  I write perl because I
like to.  Date::Manip is something I do because it interests me, not
something I'm paid for.

   Date::Manip is also big.  The last time I looked, it's one of the
largest CPAN modules there is.  If you ignore modules like Tk, LWP, etc.
which are actually packages of modules, it may be the largest.  It's true
that Date::Manip will do almost every date operation you could imagine...
but you rarely need all that power.  I'm working on reducing the footprint
of Date::Manip, but even at it's slimmest, it'll outweigh the other
modules by a good bit.

   If you are going to be using the module in cases where performance is an
important factor (started up in a CGI program being run by your web server
5,000 times a second), you might check out one of the other Date or Time
modules in CPAN.  If you're only doing fairly simple date operations
(parsing common date formats, finding the difference between two dates,
etc.), the other modules will almost certainly suffice.  If you're doing
one operation very repetively (parsing 10,000 dates from a database), you
are probably better off writing your own functions (perhaps bypassing all
date modules entirely) designed specifically for your needs.

   On the other hand, if you want one solution for all date needs, don't
need peak speed, or are trying to do more exotic date operations,
Date::Manip is for you.  Operations on things like business dates, foreign
language dates, holidays and other recurring events, etc. are available
more-or-less exclusively in Date::Manip.  If you want a module written in
terms of how you (not the computer) think of dates and times, Date::Manip
is it.

ROUTINES
========

ParseDate
          $date=&ParseDate(\@args);
          $date=&ParseDate($string);
          $date=&ParseDate(\$string);

     This takes an array or a string containing a date and parses it.
     When the date is included as an array (for example, the arguments to
     a program) the array should contain a valid date in the first one or
     more elements (elements after a valid date are ignored).  Elements
     containing a valid date are shifted from the array.  The largest
     possible number of elements which can be correctly interpreted as a
     valid date are always used.  If a string is entered rather than an
     array, that string is tested for a valid date.  The string is
     unmodified, even if passed in by reference.

     The real work is done in the ParseDateString routine.

     The ParseDate routine is primarily used to handle command line
     arguments.  If you have a command where you want to enter a date as a
     command line argument, you can use Date::Manip to make something like
     the following work:

          mycommand -date Dec 10 1997 -arg -arg2

     No more reading man pages to find out what date format is required in
     a man page.

     Historical note: this is originally why the Date::Manip routines were
     written (though long before they were released as the Date::Manip
     module).  I was using a bunch of programs (primarily batch queue
     managers) where dates and times were entered as command line options
     and I was getting highly annoyed at the many different (but not
     compatible) ways that they had to be entered.  Date::Manip originally
     consisted of basically 1 routine which I could pass "@ARGV" to and
     have it remove a date from the beginning.

ParseDateString
          $date=&ParseDateString($string);

     This routine is called by ParseDate, but it may also be called
     directly to save some time (a negligable amount).

     NOTE:  One of the most frequently asked questions that I have gotten
     is how to parse seconds since the epoch.  ParseDateString cannot
     simply parse a number as the seconds since the epoch (it conflicts
     with some ISO-8601 date formats).  There are two ways to get this
     information.  First, you can do the following:

          $secs = ...         # seconds since Jan 1, 1970  00:00:00 GMT
          $date = &DateCalc("Jan 1, 1970  00:00:00 GMT",$secs);

     Second, you can call it directly as:

          $date = &ParseDateString("epoch $secs");

     To go backwards, just use the "%s" format of UnixDate:

          $secs = &UnixDate($date,"%s");

     A full date actually includes 2 parts: date and time.  A time must
     include hours and minutes and can optionally include seconds,
     fractional seconds, an am/pm type string, and a timezone.  For
     example:

          [at] HH:MN              [Zone]
          [at] HH:MN         [am] [Zone]
          [at] HH:MN:SS      [am] [Zone]
          [at] HH:MN:SS.SSSS [am] [Zone]
          [at] HH            am   [Zone]

     Hours can be written using 1 or 2 digits, but the single digit form
     may only be used when no ambiguity is introduced (i.e. when it is not
     immediately preceded by a digit).

     A time is usually entered in 24 hour mode, but 12 hour mode can be
     used as well if AM/PM are entered (AM can be entered as AM or A.M. or
     other variations depending on the language).

     Fractional seconds are also supported in parsing but the fractional
     part is discarded (with NO rounding ocurring).

     Timezones always appear immediately after the time.  A number of
     different forms are supported (see the section TIMEZONEs below).

     Incidentally, the time is removed from the date before the date is
     parsed, so the time may appear before or after the date, or between
     any two parts of the date.

     Valid date formats include the ISO 8601 formats:

          YYYYMMDDHHMNSSF...
          YYYYMMDDHHMNSS
          YYYYMMDDHHMN
          YYYYMMDDHH
          YY-MMDDHHMNSSF...
          YY-MMDDHHMNSS
          YY-MMDDHHMN
          YY-MMDDHH
          YYYYMMDD
          YYYYMM
          YYYY
          YY-MMDD
          YY-MM
          YY
          YYYYwWWD      ex.  1965-W02-2
          YYwWWD
          YYYYDOY       ex.  1965-045
          YYDOY

     In the above list, YYYY and YY signify 4 or 2 digit years, MM, DD,
     HH, MN, SS refer to two digit month, day, hour, minute, and second
     respectively.  F...  refers to fractional seconds (any number of
     digits) which will be ignored.  The last 4 formats can be explained
     by example:  1965-w02-2 refers to Tuesday (day 2) of the 2nd week of
     1965.  1965-045 refers to the 45th day of 1965.

     In all cases, parts of the date may be separated by dashes "-".  If
     this is done, 1 or 2 digit forms of MM, DD, etc. may be used.  All
     dashes are optional except for those given in the table above (which
     MUST be included for that format to be correctly parsed).  So
     19980820, 1998-0820, 1998-08-20, 1998-8-20, and 199808-20 are all
     equivalent, but that date may NOT be written as 980820 (it must be
     written as 98-0820).

     NOTE:  Even though not allowed in the standard, the timezone for an
     ISO-8601 date is flexible and may be any of the timezones understood
     by Date::Manip.

     Additional date formats are available which may or may not be common
     including:

          MM/DD  **
          MM/DD/YY  **
          MM/DD/YYYY  **

          mmmDD       DDmmm                   mmmYYYY/DD     mmmYYYY
          mmmDD/YY    DDmmmYY     DD/YYmmm    YYYYmmmDD      YYYYmmm
          mmmDDYYYY   DDmmmYYYY   DDYYYYmmm   YYYY/DDmmm

     Where mmm refers to the name of a month.  All parts of the date can be
     separated by valid separators (space, "/", or ".").  The separator
     "-" may be used as long as it doesn't conflict with an ISO 8601
     format, but this is discouraged since it is easy to overlook
     conflicts.  For example, the format MM/DD/YY is just fine, but
     MM-DD-YY does not work since it conflicts with YY-MM-DD.  To be safe,
     if "-" is used as a separator in a non-ISO format, they should be
     turned into "/" before calling the Date::Manip routines.  As with ISO
     8601 formats, all separators are optional except for those given as a
     "/" in the list above.

     ** Note that with these formats, Americans tend to write month first,
     but many other countries tend to write day first.  The latter
     behavior can be obtained by setting the config variable DateFormat to
     something other than "US" (see CUSTOMIZING DATE::MANIP below).

     Date separators are treated very flexibly (they are converted to
     spaces), so the following dates are all equivalent:

          12/10/1965
          12-10 / 1965
          12 // 10 -. 1965

     In some cases, this may actually be TOO flexible, but no attempt is
     made to trap this.

     Years can be entered as 2 or 4 digits, days and months as 1 or 2
     digits.  Both days and months must include 2 digits whenever they are
     immediately adjacent to another numeric part of the date or time.
     Date separators are required if single digit forms of DD or MM are
     used.  If separators are not used, the date will either be unparsable
     or will get parsed incorrectly.

     Miscellaneous other allowed formats are:   which dofw in mmm in YY
      "first sunday in june 1996 at 14:00" **   dofw week num YY
       "sunday week 22 1995" **   which dofw YY                "22nd
     sunday at noon" **   dofw which week YY           "sunday 22nd week
     in 1996" **   next/last dofw               "next friday at noon"
     next/last week/month         "next month"   in num days/weeks/months
       "in 3 weeks at 12:00"   num days/weeks/months later  "3 weeks
     later"   num days/weeks/months ago    "3 weeks ago"   dofw in num
     week             "Friday in 2 weeks"   in num weeks dofw
     "in 2 weeks on friday"   dofw num week ago            "Friday 2 weeks
     ago"   num week ago dofw            "2 weeks ago friday"   last day
     in mmm in YY        "last day of October"   dofw
       "Friday" (Friday of current week)   Nth
     "12th", "1st" (day of current month)   epoch SECS
     seconds since the epoch

     ** Note that the formats "sunday week 22" and "22nd sunday" give very
     different bahaviors.  "sunday week 22" returns the sunday of the 22nd
     week of the year based on how week 1 is defined.  ISO 8601 defines
     week one to contain Jan 4, so "sunday week 1" might be the first or
     second sunday of the current year, or the last sunday of the previous
     year.  "22nd sunday" gives the actual 22nd time sunday occurs in a
     given year, regardless of the definition of a week.

     Note that certain words such as "in", "at", "of", etc. which commonly
     appear in a date or time are ignored.  Also, the year is always
     optional.

     In addition, the following strings are recognized:   today
     (exactly now OR today at a given time if a time is specified)   now
        (synonym for today)   yesterday (exactly 24 hours ago unless a
     time is specified)   tomorrow  (exactly 24 hours from now unless a
     time is specifed)   noon      (12:00:00)   midnight  (00:00:00) Other
     languages have similar (and in some cases additional) strings.

     Some things to note:

     All strings are case insensitive.  "December" and "DEceMBer" both
     work.

     When a part of the date is not given, defaults are used: year defaults
     to current year; hours, minutes, seconds to 00.

     The year may be entered as 2 or 4 digits.  If entered as 2 digits, it
     will be converted to a 4 digit year.  There are several ways to do
     this based on the value of the YYtoYYYY variable (described below).
     The default behavior it to force the 2 digit year to be in the 100
     year period CurrYear-89 to CurrYear+10.  So in 1996, the range is
     [1907 to 2006], and the 2 digit year 05 would refer to 2005 but 07
     would refer to 1907.  See CUSTOMIZING DATE::MANIP below for
     information on YYtoYYYY for other methods.

     Dates are always checked to make sure they are valid.

     In all of the formats, the day of week ("Friday") can be entered
     anywhere in the date and it will be checked for accuracy.  In other
     words,   "Tue Jul 16 1996 13:17:00" will work but   "Jul 16 1996
     Wednesday 13:17:00" will not (because Jul 16, 1996 is Tuesday, not
     Wednesday).  Note that depending on where the weekday comes, it may
     give unexpected results when used in array context (with ParseDate).
     For example, the date ("Jun","25","Sun","1990") would return June 25
     of the current year since Jun 25, 1990 is not Sunday.

     The times "12:00 am", "12:00 pm", and "midnight" are not well
     defined.  For good or bad, I use the following convention in
     Date::Manip:   midnight = 12:00am = 00:00:00   noon     = 12:00pm =
     12:00:00 and the day goes from 00:00:00 to 23:59:59.  In other words,
     midnight is the beginning of a day rather than the end of one.  The
     time 24:00:00 is also allowed (though it is automatically transformed
     to 00:00:00 of the following day).

     The format of the date returned is YYYYMMDDHH:MM:SS.  The advantage
     of this time format is that two times can be compared using simple
     string comparisons to find out which is later.  Also, it is readily
     understood by a human.  Alternate forms can be used if that is more
     convenient.  See Date_Init below and the config variable Internal.

     NOTE: The format for the date is going to change at some point in the
     future to YYYYMMDDHH:MN:SS+HHMN*FLAGS.  In order to maintain
     compatibility, you should use UnixDate to extract information from a
     date, and Date_Cmp to compare two dates.  The simple string
     comparison will only work for dates in the same timezone.

UnixDate
          @date=&UnixDate($date,@format);
          $date=&UnixDate($date,@format);

     This takes a date and a list of strings containing formats roughly
     identical to the format strings used by the UNIX date(1) command.
     Each format is parsed and an array of strings corresponding to each
     format is returned.

     $date may be any string that can be parsed by ParseDateString.

     The format options are:

          Year
              %y     year                     - 00 to 99
              %Y     year                     - 0001 to 9999
              %G     year                     - 0001 to 9999 (see below)
              %L     year                     - 0001 to 9999 (see below)
          Month, Week
              %m     month of year            - 01 to 12
              %f     month of year            - " 1" to "12"
              %b,%h  month abbreviation       - Jan to Dec
              %B     month name               - January to December
              %U     week of year, Sunday
                     as first day of week     - 01 to 53
              %W     week of year, Monday
                     as first day of week     - 01 to 53
          Day
              %j     day of the year          - 001 to 366
              %d     day of month             - 01 to 31

          %e     day of month             - " 1" to "31"
          %v     weekday abbreviation     - " S"," M"," T"," W","Th"," F","Sa"
          %a     weekday abbreviation     - Sun to Sat
          %A     weekday name             - Sunday to Saturday
          %w     day of week              - 1 (Monday) to 7 (Sunday)
          %E     day of month with suffix - 1st, 2nd, 3rd...
           Hour
          %H     hour                     - 00 to 23
          %k     hour                     - " 0" to "23"
          %i     hour                     - " 1" to "12"
          %I     hour                     - 01 to 12
          %p     AM or PM
           Minute, Second, Timezone
          %M     minute                   - 00 to 59
          %S     second                   - 00 to 59
          %s     seconds from 1/1/1970 GMT- negative if before 1/1/1970
          %o     seconds from Jan 1, 1970
                 in the current time zone
          %Z     timezone                 - "EDT"
          %z     timezone as GMT offset   - "+0100"
           Date, Time
          %c     %a %b %e %H:%M:%S %Y     - Fri Apr 28 17:23:15 1995
          %C,%u  %a %b %e %H:%M:%S %z %Y  - Fri Apr 28 17:25:57 EDT 1995
          %g     %a, %d %b %Y %H:%M:%S %z - Fri, 28 Apr 1995 17:23:15 EDT
          %D,%x  %m/%d/%y                 - 04/28/95
          %l     date in ls(1) format
                   %b %e $H:$M            - Apr 28 17:23  (if within 6 months)
                   %b %e  %Y              - Apr 28  1993  (otherwise)
          %r     %I:%M:%S %p              - 05:39:55 PM
          %R     %H:%M                    - 17:40
          %T,%X  %H:%M:%S                 - 17:40:58
          %V     %m%d%H%M%y               - 0428174095
          %Q     %Y%m%d                   - 19961025
          %q     %Y%m%d%H%M%S             - 19961025174058
          %P     %Y%m%d%H%M%S             - 1996102517:40:58
          %F     %A, %B %e, %Y            - Sunday, January  1, 1996
          %J     %G-W%W-%w                - 1997-W02-2
          %K     %Y-%j                    - 1997-045
           Other formats
          %n     insert a newline character
          %t     insert a tab character
          %%     insert a `%' character
          %+     insert a `+' character
           The following formats are currently unused but may be used in the future:
          NO 1234567890 !@#$^&*()_|-=\`[];',./~{}:<>?
           They currently insert the character following the %, but may (and probably
           will) change in the future as new formats are added.

     If a lone percent is the final character in a format, it is ignored.

     Note that the ls format (%l) applies to date within the past OR
     future 6 months!

     The formats %U and %W return a week from 01 to 53.  Because days at
     the beginning or end of the year may actually appear in a week in the
     previous or next year, the %L and %G formats were added to handle
     this case.  %L and %G give the year of the week for %U and %W
     respectively.  So Jan 1, 1993 is written in ISO-8601 format as
     1992-W53-5.  In this case, %Y is 1993, but %G is 1992 and %W is 53.
     %L and %U are similar for weeks starting with Sunday.  %J returns the
     full ISO-8601 format.

     The formats used in this routine were originally based on date.pl
     (version 3.2) by Terry McGonigal, as well as a couple taken from
     different versions of the Solaris date(1) command.  Also, several
     have been added which are unique to Date::Manip.

ParseDateDelta
          $delta=&ParseDateDelta(\@args);
          $delta=&ParseDateDelta($string);
          $delta=&ParseDateDelta(\$string);

     This takes an array and shifts a valid delta date (an amount of time)
     from the array.  Recognized deltas are of the form:   +Yy +Mm +Ww +Dd
     +Hh +MNmn +Ss       examples:          +4 hours +3mn -2second
     + 4 hr 3 minutes -2          4 hour + 3 min -2 s
     +Y:+M:+W:+D:+H:+MN:+S       examples:          0:0:0:0:4:3:-2
     +4:3:-2   mixed format       examples:          4 hour 3:-2

     A field in the format +Yy is a sign, a number, and a string specifying
     the type of field.  The sign is "+", "-", or absent (defaults to the
     next larger element).  The valid strings specifying the field type
     are:    y:  y, yr, year, years    m:  m, mon, month, months    w:  w,
     wk, ws, wks, week, weeks    d:  d, day, days    h:  h, hr, hour, hours
       mn: mn, min, minute, minutes    s:  s, sec, second, seconds

     Also, the "s" string may be omitted.  The sign, number, and string may
     all be separated from each other by any number of whitespaces.

     In the date, all fields must be given in the order: Y M W D H MN S.
     Any number of them may be omitted provided the rest remain in the
     correct order.  In the 2nd (colon) format, from 2 to 7 of the fields
     may be given.  For example +D:+H:+MN:+S may be given to specify only
     four of the fields.  In any case, both the MN and S field may be
     present.  No spaces may be present in the colon format.

     Deltas may also be given as a combination of the two formats.  For
     example, the following is valid: +Yy +D:+H:+MN:+S.  Again, all fields
     must be given in the correct order.

     The word "in" may be given (prepended in English) to the delta ("in 5
     years") and the word "ago" may be given (appended in English) ("6
     months ago").  The "in" is completely ignored.  The "ago" has the
     affect of reversing all signs that appear in front of the components
     of the delta.  I.e. "-12 yr 6 mon ago" is identical to "+12yr +6mon"
     (don't forget that there is an implied minus sign in front of the 6
     because when no sign is explicitly given, it carries the previously
     entered sign).

     One thing is worth noting.  The year/month and day/hour/min/sec parts
     are returned in a "normalized" form.  That is, the signs are adjusted
     so as to be all positive or all negative.  For example, "+ 2 day -
     2hour" does not return "0:0:0:2:-2:0:0".  It returns
     "+0:0:0:1:22:0:0" (1 day 22 hours which is equivalent).  I find (and
     I think most others agree) that this is a more useful form.

     Since the year/month and day/hour/min/sec parts must be normalized
     separately there is the possibility that the sign of the two parts
     will be different.  So, the delta "+ 2years -10 months - 2 days + 2
     hours" produces the delta "+1:2:-0:1:22:0:0".

     It is possible to include a sign for all elements that is output.
     See the configuration variable DeltaSigns below.

     NOTE: The internal format of the delta changed in version 5.30 from
     Y:M:D:H:MN:S to Y:M:W:D:H:MN:S .  Also, it is going to change again
     at some point in the future to Y:M:W:D:H:MN:S*FLAGS .  Use the
     routine Delta_Format to extract information rather than parsing it
     yourself.

Delta_Format
          @str=&Delta_Format($delta,$dec,@format);
          $str=&Delta_Format($delta,$dec,@format);

     This is similar to the UnixDate routine except that it extracts
     information from a delta.  Unlike the UnixDate routine, most of the
     formats are 2 characters instead of 1.

     NOTE: For the time being, Delta_Format only understands the "exact"
     parts of a delta (Y/M) and (W/D/H/MN/S).  There is currently no
     "mixing" between the two parts.

     Formats currently understood are:

          %Xv     : the value of the field named X
          %Xd     : the value of the field X, and all smaller fields, expressed in
                    units of X
          %Xh     : the value of field X, and all larger fields, expressed in units
                    of X
          %Xt     : the value of all fields expressed in units of X

          X is one of y,M,w,d,h,m,s (case sensitive).

          %%      : returns a "%"

     So, the format "%hd" means the values of H, MN, and S expressed in
     hours.  So for the delta "0:0:0:0:2:30:0", this format returns 2.5.
     Similarly, the format "%yd" means the value (in years) of both the Y
     and M fields.

     The format "%hh" returns the value of W, D, and H expressed in hours.

     If $dec is non-zero, the %Xd and %Xt values are formatted to contain
     $dec decimal places.

ParseRecur
          $recur=&ParseRecur($string [,$base,$date0,$date1,$flags]);
          @dates=&ParseRecur($string [,$base,$date0,$date1,$flags]);

     A recurrence refers to a recurring event.  A fully specified
     recurrence requires (in most cases) 4 items: a recur description
     (describing the frequency of the event), a base date (a date when the
     event occurred and which other occurrences are based on), and a start
     and end date.  There may be one or more flags included which modify
     the behavior of the recur description.  The fully specified
     recurrence is written as:

          recur*flags*base*date0*date1

     Here, base, date0, and date1 are any strings (which must not contain
     any asterixes) which can be parsed by ParseDate.  flags is a comma
     separated list of flags (described below), and recur is a string
     describing a recurring event.

     If called in scalar context, it returns a string containing a fully
     specified recurrence (or as much of it as can be determined with
     unspecified fields left blank).  In list context, it returns a list
     of all dates referred to by a recurrence if enough information is
     given in the recurrence.  All dates returned are in the range:

          date0 <= date < date1

     The argument $string can contain any of the parts of a full
     recurrence.  For example:

          recur
          recur*flags
          recur**base*date0*date1

     The only part which is required is the recur description.  Any values
     contained in $string are overridden or modified by values passed in as
     parameters to ParseRecur.

     A recur description is a string of the format Y:M:W:D:H:MN:S .
     Exactly one of the colons may optionally be replaced by an asterisk,
     or an asterisk may be prepended to the string.

     Any value "N" to the left of the asterisk refers to the "Nth" one.
     Any value to the right of the asterisk refers to a value as it
     appears on a calendar/clock.  Values to the right can be listed a
     single values, ranges (2 numbers separated by a dash "-"), or a comma
     separated list of values or ranges.  In a few cases, negative values
     are appropriate.

     This is best illustrated by example.

          0:0:2:1:0:0:0        every 2 weeks and 1 day
          0:0:0:0:5:30:0       every 5 hours and 30 minutes
          0:0:0:2*12:30:0      every 2 days at 12:30 (each day)
          3*1:0:2:12:0:0       every 3 years on Jan 2 at noon
          0:1*0:2:12,14:0:0    2nd of every month at 12:00 and 14:00
          1:0:0*45:0:0:0       45th day of every year
          0:1*4:2:0:0:0        4th tuesday (day 2) of every month
          0:1*-1:2:0:0:0       last tuesday of every month
          0:1:0*-2:0:0:0       2nd to last day of every month
          0:0:3*2:0:0:0        every 3rd tuesday (every 3 weeks on 2nd day of week)
          1:0*12:2:0:0:0       tuesday of the 12th week of each year
          *1990-1995:12:0:1:0:0:0
                               Dec 1 in 1990 through 1995

          0:1*2:0:0:0:0        the start of the 2nd week of every month (see Note 2)
          1*1:2:0:0:0:0        the start of the 2nd week in January each year (Note 2)

     I realize that this looks a bit cryptic, but after a discussion on the
     CALENDAR mailing list, it looked like there was no concise, flexible
     notation for handling recurring events.  ISO 8601 notations were very
     bulky and lacked the flexibility I wanted.  As a result, I developed
     this notation (based on crontab formats, but with much more
     flexibility) which fits in well with this module, and which is able
     to express every type of recurring event I could think of.

     NOTE: If a recurrence has a date0 and date1 in it AND a date0 and
     date1 are passed in to the function, both sets of criteria apply.  If
     flags are passed in, they override any flags in the recurrence UNLESS
     the flags passed in start with a plus (+) character in which case
     they are appended to the flags in the recurrence.

     NOTE: There is no way to express the following with a single
     recurrence:

          every day at 12:30 and 1:00

     You have to use two recurrences to do this.

     NOTE: A recurrence specifying the week of a month is NOT clearly
     defined in common usage.  What is the 1st week in a month?  The
     behavior (with respect to this module) is well defined (using the FDn
     and FIn flags below), but in common usage, this is so ambiguous that
     this form should probably never be used.  It is included here solely
     for the sake of completeness.

     NOTE: Depending on whether M and W are 0 or nonzero, D means different
     things.  This is given in the following table.

          M  W  D (when right of an asterisk) refers to
          -  -  -------------------------------------------
          0  0  day of year (1-366)
          M  0  day of month (1-31)
          0  W  day of week (1-7),  W refers to the week of year
          M  W  the Wth (1-5 or -1 to -5) occurrence of Dth (1-7) day of week in month

     NOTE: Base dates are only used with some types of recurrences.  For
     example,

          0:0:3*2:0:0:0        every 3rd tuesday

     requires a base date.  If a base date is specified which doesn't
     match the criteria (for example, if a base date falling on Monday
     were passed in with this recurrence), the base date is moved forward
     to the first relevant date.

     Other dates do not require a base date.  For example:

          0:0*3:2:0:0:0        third tuesday of every month

     A recurrence written in the above format does NOT provide default
     values for base, date0, or date1.  They must be specified in order to
     get a list of dates.

     A base date is not used entirely.  It is only used to provide the
     parts necessary for the left part of a recurrence.  For example, the
     recurrence:

          1:3*0:4:0:0:0        every 1 year, 3 months on the 4th day of the month

     would only use the year and month of the base date.

     There are a small handful of English strings which can be parsed in
     place of a numerical recur description.  These include:

          every 2nd day [in 1997]
          every 2nd day in June [1997]
          2nd day of every month [in 1997]
          2nd tuesday of every month [in 1997]
          last tuesday of every month [in 1997]
          every 2nd tuesday [in 1997]
          every 2nd tuesday in June [1997]

     Each of these set base, date0, and date1 to a default value (the
     current year with Jan 1 being the base date is the default if the
     year and month are missing).

     The following flags (case insensitive) are understood:

          MWn   : n is 1-7.  The first week of the month is the week
                  which contains the first occurrence of day n (1=Monday).
                  FD2 means that the first week contains the first Tuesday
                  of the month.
          MDn   : n is 1-7.  The first week of the month contains the
                  actual date (1st through 7th).  FI4 means that the first
                  week of the month contains the 4th of that month.

          PDn   : n is 1-7.  Means the previous day n not counting today
          PTn   : n is 1-7.  Means the previous day n counting today
          NDn   : n is 1-7.  Means the next day n not counting today
          NTn   : n is 1-7.  Means the next day n counting today

          FDn   : n is any number.  Means step forward n days.
          BDn   : n is any number.  Means step backward n days.
          FWn   : n is any number.  Means step forward n workdays.
          BWn   : n is any number.  Means step backward n workdays.

          CWD   : the closest work day (using the TomorrowFirst config variable).
          CWN   : the closest work day (looking forward first).
          CWP   : the closest work day (looking backward first).

          EASTER: select easter for this year (the M, W, D fields are ignored
                  in the recur).

     NOTE: only one of FDn and FIn can be set.  If both are set, only the
     last one is used.  The default is FD7 (i.e. the first week contains
     the first Sunday).

     CWD, CWN, and CWP will usually return the same value, but if you are
     starting at the middle day of a 3-day weekend (for example), it will
     return either the first work day of the following week, or the last
     work day of the previous week depending on whether it looks forward
     or backward first.

     All flags are applied AFTER the recurrence dates are calculated, and
     they may move a date outside of the date0 to date1 range.  No check
     is made for this.

     The workday flags do not act exactly the same as a business mode
     calculation.  For example, a date that is Saturday with a FW1 steps
     forward to the first workday (i.e. Monday).

Date_Cmp
          $flag=&Date_Cmp($date1,$date2);

     This takes two dates and compares them.  Almost all dates can be
     compared using the perl "cmp" command.  The only time this will not
     work is when comparing dates in different timezones.  This routine
     will take that into account.

     NOTE:  This routine currently does little more than use "cmp", but
     once the internal format for storing dates is in place (where
     timezone information is kept as part of the date), this routine will
     become more important.  You should use this routine in prepartation
     for that version.

DateCalc
          $d=&DateCalc($d1,$d2 [,\$err] [,$mode]);

     This takes two dates, deltas, or one of each and performs the
     appropriate calculation with them.  Dates must be a string that can
     be parsed by &ParseDateString.  Deltas must be a string that can be
     parsed by &ParseDateDelta.  Two deltas add together to form a third
     delta.  A date and a delta returns a 2nd date.  Two dates return a
     delta (the difference between the two dates).

     Note that in many cases, it is somewhat ambiguous what the delta
     actually refers to.  Although it is ALWAYS known how many months in a
     year, hours in a day, etc., it is NOT known how many days form a
     month.  As a result, the part of the delta containing month/year and
     the part with sec/min/hr/day must be treated separately.  For
     example, "Mar 31, 12:00:00" plus a delta of 1month 2days would yield
     "May 2 12:00:00".  The year/month is first handled while keeping the
     same date.  Mar 31 plus one month is Apr 31 (but since Apr only has
     30 days, it becomes Apr 30).  Apr 30 + 2 days is May 2.  As a result,
     in the case where two dates are entered, the resulting delta can take
     on two different forms.  By default ($mode=0), an absolutely correct
     delta (ignoring daylight savings time) is returned in days, hours,
     minutes, and seconds.

     If $mode is 1, the math is done using an approximate mode where a
     delta is returned using years and months as well.  The year and month
     part is calculated first followed by the rest.  For example, the two
     dates "Mar 12 1995" and "Apr 13 1995" would have an exact delta of
     "31 days" but in the approximate mode, it would be returned as "1
     month 1 day".  Also, "Mar 31" and "Apr 30" would have deltas of "30
     days" or "1 month" (since Apr 31 doesn't exist, it drops down to Apr
     30).  Approximate mode is a more human way of looking at things
     (you'd say 1 month and 2 days more often then 33 days), but it is
     less meaningful in terms of absolute time.  In approximate mode $d1
     and $d2 must be dates.  If either or both is a delta, the calculation
     is done in exact mode.

     If $mode is 2, a business mode is used.  That is, the calculation is
     done using business days, ignoring holidays, weekends, etc.  In order
     to correctly use this mode, a config file must exist which contains
     the section defining holidays (see documentation on the config file
     below).  The config file can also define the work week and the hours
     of the work day, so it is possible to have different config files for
     different businesses.

     For example, if a config file defines the workday as 08:00 to 18:00, a
     work week consisting of Mon-Sat, and the standard (American)
     holidays, then from Tuesday at 12:00 to the following Monday at 14:00
     is 5 days and 2 hours.  If the "end" of the day is reached in a
     calculation, it automatically switches to the next day.  So, Tuesday
     at 12:00 plus 6 hours is Wednesday at 08:00 (provided Wed is not a
     holiday).  Also, a date that is not during a workday automatically
     becomes the start of the next workday.  So, Sunday 12:00 and Monday
     at 03:00 both automatically becomes Monday at 08:00 (provided Monday
     is not a holiday).  In business mode, any combination of date and
     delta may be entered, but a delta should not contain a year or month
     field (weeks are fine though).

     See below for some additional comments about business mode
     calculations.

     Note that a business week is treated the same as an exact week (i.e.
     from Tuesday to Tuesday, regardless of holidays).  Because this means
     that the relationship between days and weeks is NOT unambiguous, when
     a delta is produced from two dates, it will be in terms of d/h/mn/s
     (i.e. no week field).

     If $mode is 3 (which only applies when two dates are passed in), an
     exact business mode is used.  In this case, it returns a delta as an
     exact number of business days/hours/etc. between the two.  Weeks,
     months, and years are ignored.

     Any other non-nil value of $mode is treated as $mode=1 (approximate
     mode).

     The mode can be automatically set in the dates/deltas passed by
     including a key word somewhere in it.  For example, in English, if
     the word "approximately" is found in either of the date/delta
     arguments, approximate mode is forced.  Likewise, if the word
     "business" or "exactly" appears, business/exact mode is forced (and
     $mode is ignored).  So, the two following are equivalent:

          $date=&DateCalc("today","+ 2 business days",\$err);
          $date=&DateCalc("today","+ 2 days",\$err,2);

     Note that if the keyword method is used instead of passing in $mode,
     it is important that the keyword actually appear in the argument
     passed in to DateCalc.  The following will NOT work:

          $delta=&ParseDateDelta("+ 2 business days");
          $today=&ParseDate("today");
          $date=&DateCalc($today,$delta,\$err);

     because the mode keyword is removed from a date/delta by the parse
     routines, and the mode is reset each time a parse routine is called.
     Since DateCalc parses both of its arguments, whatever mode was
     previously set is ignored.

     If \$err is passed in, it is set to:    1 is returned if $d1 is not a
     delta or date    2 is returned if $d2 is not a delta or date    3 is
     returned if the date is outside the years 1000 to 9999 This argument
     is optional, but if included, it must come before $mode.

     Nothing is returned if an error occurs.

     When a delta is returned, the signs such that it is strictly positive
     or strictly negative ("1 day - 2 hours" would never be returned for
     example).  The only time when this cannot be enforced is when two
     deltas with a year/month component are entered.  In this case, only
     the signs on the day/hour/min/sec part are standardized.

Date_SetTime
          $date=&Date_SetTime($date,$hr,$min,$sec);
          $date=&Date_SetTime($date,$time);

     This takes a date (any string that may be parsed by ParseDateString)
     and sets the time in that date.  For example, one way to get the time
     for 7:30 tomorrow would be to use the lines:

          $date=&ParseDate("tomorrow");
          $date=&Date_SetTime($date,"7:30");

     Note that in this routine (as well as the other routines below which
     use a time argument), no real parsing is done on the times.  As a
     result,

          $date=&Date_SetTime($date,"13:30");

     works, but

          $date=&Date_SetTime($date,"1:30 PM");

     doesn't.

Date_SetDateField
          $date=&Date_SetDateField($date,$field,$val [,$nocheck]);

     This takes a date and sets one of it's fields to a new value.  $field
     is any of the strings "y", "m", "d", "h", "mn", "s" (case
     insensitive) and $val is the new value.

     If $nocheck is non-zero, no check is made as to the validity of the
     date.

Date_GetPrev
          $date=&Date_GetPrev($date,$dow, $curr [,$hr,$min,$sec]);
          $date=&Date_GetPrev($date,$dow, $curr [,$time]);
          $date=&Date_GetPrev($date,undef,$curr,$hr,$min,$sec);
          $date=&Date_GetPrev($date,undef,$curr,$time);

     This takes a date (any string that may be parsed by ParseDateString)
     and finds the previous occurrence of either a day of the week, or a
     certain time of day.

     If $dow is defined, the previous occurrence of the day of week is
     returned.  $dow may either be a string (such as "Fri" or "Friday") or
     a number (between 1 and 7).  The date of the previous $dow is
     returned.

     If $date falls on the day of week given by $dow, the date returned
     depends on $curr.  If $curr is 0, the date returned is a week before
     $date.  If $curr is 1, the date returned is the same as $date.  If
     $curr is 2, the date returned (including the time information) is
     required to be before $date.

     If a time is passed in (either as separate hours, minutes, seconds or
     as a time in HH:MM:SS or HH:MM format), the time on this date is set
     to it.  The following examples should illustrate the use of
     Date_GetPrev:

          date                   dow    curr  time            returns
          Fri Nov 22 18:15:00    Thu    any   12:30           Thu Nov 21 12:30:00
          Fri Nov 22 18:15:00    Fri    0     12:30           Fri Nov 15 12:30:00
          Fri Nov 22 18:15:00    Fri    1/2   12:30           Fri Nov 22 12:30:00

          Fri Nov 22 18:15:00    Fri    1     18:30           Fri Nov 22 18:30:00
          Fri Nov 22 18:15:00    Fri    2     18:30           Fri Nov 15 18:30:00

     If $dow is undefined, then a time must be entered, and the date
     returned is the previous occurrence of this time.  If $curr is
     non-zero, the current time is returned if it matches the criteria
     passed in.  In other words, the time returned is the last time that a
     digital clock (in 24 hour mode) would have displayed the time you
     passed in.  If you define hours, minutes and seconds default to 0 and
     you might jump back as much as an entire day.  If hours are
     undefined, you are looking for the last time the minutes/seconds
     appeared on the digital clock, so at most, the time will jump back
     one hour.

          date               curr  hr     min    sec      returns
          Nov 22 18:15:00    0/1   18     undef  undef    Nov 22 18:00:00
          Nov 22 18:15:00    0/1   18     30     0        Nov 21 18:30:00
          Nov 22 18:15:00    0     18     15     undef    Nov 21 18:15:00
          Nov 22 18:15:00    1     18     15     undef    Nov 22 18:15:00
          Nov 22 18:15:00    0     undef  15     undef    Nov 22 17:15:00
          Nov 22 18:15:00    1     undef  15     undef    Nov 22 18:15:00

Date_GetNext
          $date=&Date_GetNext($date,$dow, $curr [,$hr,$min,$sec]);
          $date=&Date_GetNext($date,$dow, $curr [,$time]);
          $date=&Date_GetNext($date,undef,$curr,$hr,$min,$sec);
          $date=&Date_GetNext($date,undef,$curr,$time);

     Similar to Date_GetPrev.

Date_IsHoliday
          $name=&Date_IsHoliday($date);

     This returns undef if $date is not a holiday, or a string containing
     the name of the holiday otherwise.  An empty string is returned for
     an unnamed holiday.

Events_List
          $ref=&Events_List($date);
          $ref=&Events_List($date ,0      [,$flag]);
          $ref=&Events_List($date0,$date1 [,$flag]);

     This returns a list of events.  Events are defined in the Events
     section of the config file (discussed below).

     In the first form (a single argument), $date is any string containing
     a date.  A list of events active at that precise time will be
     returned.  The format is similar to when $flag=0, except only a
     single time will be returned.

     In all other cases, a range of times will be used.  If the 2nd
     argument evaluates to 0, the range of times will be the 24 hour
     period from midnight to midnight containing $date.  Otherwise, the
     range is given by the two dates.

     The value of $flag determines the format of the information that is
     returned.

     With $flag=0, the events are returned as a reference to a list of the
     form:

          [ date, [ list_of_events ], date, [ list_of_events ], ... ]

     For example, if the following events are defined (using the syntax
     discussed below in the description of the Event section of the config
     file):

          2000-01-01 ; 2000-03-21  = Winter
          2000-03-22 ; 2000-06-21  = Spring
          2000-02-01               = Event1
          2000-05-01               = Event2
          2000-04-01-12:00:00      = Event3

     might result in the following output:

          &Events_List("2000-04-01")
           => [ 2000040100:00:00, [ Spring ] ]

          &Events_List("2000-04-01 12:30");
           => [ 2000040112:30:00, [ Spring, Event3 ] ]

          &Events_List("2000-04-01",0);
           => [ 2000040100:00:00, [ Spring ],
                2000040112:00:00, [ Spring, Event3 ],
                2000040113:00:00, [ Spring ] ]

          &Events_List("2000-03-15","2000-04-10");
           => [ 2000031500:00:00, [ Winter ],
                2000032200:00:00, [ Spring ]
                2000040112:00:00, [ Spring, Event3 ]
                2000040113:00:00, [ Spring ] ]

     Much more complicated events can be defined using recurrences.

     When $flag is non-zero, the format of the output is changed.  If $flag
     is 1, then a tally of the amount of time given to each event is
     returned.  Time for which two or more events apply is counted for
     both.

          &Events_List("2000-03-15","2000-04-10",1);
           => { Winter => +0:0:1:0:0:0:0,
                Spring => +0:0:2:5:0:0:0,
                Event3 => +0:0:0:0:1:0:0 }

     When $flag is 2, a more complex tally with no event counted twice is
     returned.

          &Events_List("2000-03-15","2000-04-10",2);
           => { Winter => +0:0:1:0:0:0:0,
                Spring => +0:0:2:4:23:0:0,
                Event3+Spring => +0:0:0:0:1:0:0 }

     The hash contains one element for each combination of events.

Date_DayOfWeek
          $day=&Date_DayOfWeek($m,$d,$y);

     Returns the day of the week (1 for Monday, 7 for Sunday).

     All arguments must be numeric.

Date_SecsSince1970
          $secs=&Date_SecsSince1970($m,$d,$y,$h,$mn,$s);

     Returns the number of seconds since Jan 1, 1970 00:00 (negative if
     date is earlier).

     All arguments must be numeric.

Date_SecsSince1970GMT
          $secs=&Date_SecsSince1970GMT($m,$d,$y,$h,$mn,$s);

     Returns the number of seconds since Jan 1, 1970 00:00 GMT (negative
     if date is earlier).  If CurrTZ is "IGNORE", the number will be
     identical to Date_SecsSince1970 (i.e. the date given will be treated
     as being in GMT).

     All arguments must be numeric.

Date_DaysSince1BC
          $days=&Date_DaysSince1BC($m,$d,$y);

     Returns the number of days since Dec 31, 1BC.  This includes the year
     0000.

     All arguments must be numeric.

Date_DayOfYear
          $day=&Date_DayOfYear($m,$d,$y);

     Returns the day of the year (001 to 366)

     All arguments must be numeric.

Date_NthDayOfYear
          ($y,$m,$d,$h,$mn,$s)=&Date_NthDayOfYear($y,$n);

     Returns the year, month, day, hour, minutes, and decimal seconds given
     a floating point day of the year.

     All arguments must be numeric.  $n must be greater than or equal to 1
     and less than 366 on non-leap years and 367 on leap years.

Date_DaysInYear
          $days=&Date_DaysInYear($y);

     Returns the number of days in the year (365 or 366)

Date_DaysInMonth
          $days=&Date_DaysInMonth($m,$y);

     Returns the number of days in the month.

Date_WeekOfYear
          $wkno=&Date_WeekOfYear($m,$d,$y,$first);

     Figure out week number.  $first is the first day of the week which is
     usually 1 (Monday) or 7 (Sunday), but could be any number between 1
     and 7 in practice.

     All arguments must be numeric.

     NOTE: This routine should only be called in rare cases.  Use UnixDate
     with the %W, %U, %J, %L formats instead.  This routine returns a week
     between 0 and 53 which must then be "fixed" to get into the ISO-8601
     weeks from 1 to 53.  A date which returns a week of 0 actually
     belongs to the last week of the previous year.  A date which returns
     a week of 53 may belong to the first week of the next year.

Date_LeapYear
          $flag=&Date_LeapYear($y);

     Returns 1 if the argument is a leap year Written by David Muir
     Sharnoff <muir@idiom.com>

Date_DaySuffix
          $day=&Date_DaySuffix($d);

     Add `st', `nd', `rd', `th' to a date (ie 1st, 22nd, 29th).  Works for
     international dates.

Date_TimeZone
          $tz=&Date_TimeZone;

     This determines and returns the local timezone.  If it is unable to
     determine the local timezone, the following error occurs:

          ERROR: Date::Manip unable to determine TimeZone.

     See The TIMEZONES section below for more information.

Date_ConvTZ
          $date=&Date_ConvTZ($date);
          $date=&Date_ConvTZ($date,$from);
          $date=&Date_ConvTZ($date,"",$to);
          $date=&Date_ConvTZ($date,$from,$to);

     This converts a date (which MUST be in the format returned by
     ParseDate) from one timezone to another.

     If it is called with no arguments, the date is converted from the
     local timezone to the timezone specified by the config variable
     ConvTZ (see documentation on ConvTZ below).  If ConvTZ is set to
     "IGNORE", no conversion is done.

     If called with $from but no $to, the timezone is converted from the
     timezone in $from to ConvTZ (of TZ if ConvTZ is not set).  Again, no
     conversion is done if ConvTZ is set to "IGNORE".

     If called with $to but no $from, $from defaults to ConvTZ (if set) or
     the local timezone otherwise.  Although this does not seem
     immediately obvious, it actually makes sense.  By default, all dates
     that are parsed are converted to ConvTZ, so most of the dates being
     worked with will be stored in that timezone.

     If Date_ConvTZ is called with both $from and $to, the date is
     converted from the timezone $from to $to.

     NOTE: As in all other cases, the $date returned from Date_ConvTZ has
     no timezone information included as part of it, so calling UnixDate
     with the "%z" format will return the timezone that Date::Manip is
     working in (usually the local timezone).

     Example:  To convert 2/2/96 noon PST to CST (regardless of what
     timezone you are in, do the following:

          $date=&ParseDate("2/2/96 noon");
          $date=&Date_ConvTZ($date,"PST","CST");

     Both timezones MUST be in one of the formats listed below in the
     section TIMEZONES.

Date_Init
          &Date_Init();
          &Date_Init("VAR=VAL","VAR=VAL",...);
          @list=&Date_Init();
          @list=&Date_Init("VAR=VAL","VAR=VAL",...);

     Normally, it is not necessary to explicitly call Date_Init.  The first
     time any of the other routines are called, Date_Init will be called
     to set everything up.  If for some reason you want to change the
     configuration of Date::Manip, you can pass the appropriate string or
     strings into Date_Init to reinitialize things.

     The strings to pass in are of the form "VAR=VAL".  Any number may be
     included and they can come in any order.  VAR may be any configuration
     variable.  A list of all configuration variables is given in the
     section CUSTOMIZING DATE::MANIP below.  VAL is any allowed value for
     that variable.  For example, to switch from English to French and use
     non-US format (so that 12/10 is Oct 12), do the following:

          &Date_Init("Language=French","DateFormat=nonUS");

     If Date_Init is called in list context, it will return a list of all
     config variables and their values suitable for passing in to Date_Init
     to return Date::Manip to the current state.  The only possible
     problem is that by default, holidays will not be erased, so you may
     need to prepend the "EraseHolidays=1" element to the list.

Date_IsWorkDay
          $flag=&Date_IsWorkDay($date [,$flag]);

     This returns 1 if $date is a work day.  If $flag is non-zero, the
     time is checked to see if it falls within work hours.

Date_NextWorkDay
          $date=&Date_NextWorkDay($date,$off [,$time]);

     Finds the day $off work days from now.  If $time is passed in, we
     must also take into account the time of day.

     If $time is not passed in, day 0 is today (if today is a workday) or
     the next work day if it isn't.  In any case, the time of day is
     unaffected.

     If $time is passed in, day 0 is now (if now is part of a workday) or
     the start of the very next work day.

Date_PrevWorkDay
          $date=&Date_PrevWorkDay($date,$off [,$time]);

     Similar to Date_NextWorkDay.

Date_NearestWorkDay
          $date=&Date_NearestWorkDay($date [,$tomorrowfirst]);

     This looks for the work day nearest to $date.  If $date is a work
     day, it is returned.  Otherwise, it will look forward or backwards in
     time 1 day at a time until a work day is found.  If $tomorrowfirst is
     non-zero (or if it is omitted and the config variable TomorrowFirst
     is non-zero), we look to the future first.  Otherwise, we look in the
     past first.  In other words, in a normal week, if $date is Wednesday,
     $date is returned.  If $date is Saturday, Friday is returned.  If
     $date is Sunday, Monday is returned.  If Wednesday is a holiday,
     Thursday is returned if $tomorrowfirst is non-nil or Tuesday
     otherwise.

DateManipVersion
          $version=&DateManipVersion;

     Returns the version of Date::Manip.

TIMEZONES
=========

   The following timezone names are currently understood (and can be used
in parsing dates).  These are zones defined in RFC 822.

     Universal:  GMT, UT
     US zones :  EST, EDT, CST, CDT, MST, MDT, PST, PDT
     Military :  A to Z (except J)
     Other    :  +HHMM or -HHMM
     ISO 8601 :  +HH:MM, +HH, -HH:MM, -HH

   In addition, the following timezone abbreviations are also accepted.
In a few cases, the same abbreviation is used for two different timezones
(for example, NST stands for Newfoundland Standard -0330 and North Sumatra
+0630).  In these cases, only 1 of the two is available.  The one preceded
by a "#" sign is NOT available but is documented here for completeness.
This list of zones comes in part from the Time::Zone module by Graham
Barr, David Muir Sharnoff, and Paul Foley (with several additions by
myself).

     IDLW    -1200    International Date Line West
     NT      -1100    Nome
     HST     -1000    Hawaii Standard
     CAT     -1000    Central Alaska
     AHST    -1000    Alaska-Hawaii Standard
     AKST    -0900    Alaska Standard
     YST     -0900    Yukon Standard
     HDT     -0900    Hawaii Daylight
     AKDT    -0800    Alaska Daylight
     YDT     -0800    Yukon Daylight
     PST     -0800    Pacific Standard
     PDT     -0700    Pacific Daylight
     MST     -0700    Mountain Standard
     MDT     -0600    Mountain Daylight
     CST     -0600    Central Standard
     CDT     -0500    Central Daylight
     EST     -0500    Eastern Standard
     SAT     -0400    Chile
     EDT     -0400    Eastern Daylight
     AST     -0400    Atlantic Standard
          #NST     -0330    Newfoundland Standard       nst=North Sumatra    +0630
     NFT     -0330    Newfoundland
          #GST     -0300    Greenland Standard          gst=Guam Standard    +1000
          #BST     -0300    Brazil Standard             bst=British Summer   +0100
     ADT     -0300    Atlantic Daylight
     NDT     -0230    Newfoundland Daylight
     AT      -0200    Azores
     SAST    -0200    South African Standard
     WAT     -0100    West Africa
     GMT     +0000    Greenwich Mean
     UT      +0000    Universal (Coordinated)
     UTC     +0000    Universal (Coordinated)
     WET     +0000    Western European
     WEST    +0000    Alias for Western European
     CET     +0100    Central European
     FWT     +0100    French Winter
     MET     +0100    Middle European
     MEZ     +0100    Middle European
     MEWT    +0100    Middle European Winter
     SWT     +0100    Swedish Winter
     BST     +0100    British Summer              bst=Brazil standard  -0300
     GB      +0100    GMT with daylight savings
     CEST    +0200    Central European Summer
     EET     +0200    Eastern Europe, USSR Zone 1
     FST     +0200    French Summer
     MEST    +0200    Middle European Summer
     MESZ    +0200    Middle European Summer
     METDST  +0200    An alias for MEST used by HP-UX
     SST     +0200    Swedish Summer              sst=South Sumatra    +0700
     EEST    +0300    Eastern Europe Summer
     BT      +0300    Baghdad, USSR Zone 2
     MSK     +0300    Moscow
     IT      +0330    Iran
     ZP4     +0400    USSR Zone 3
     MSD     +0300    Moscow Daylight
     ZP5     +0500    USSR Zone 4
     IST     +0530    Indian Standard
     ZP6     +0600    USSR Zone 5
     NST     +0630    North Sumatra               nst=Newfoundland Std -0330
          #SST     +0700    South Sumatra, USSR Zone 6  sst=Swedish Summer   +0200
     CCT     +0800    China Coast, USSR Zone 7
     AWST    +0800    West Australian Standard
     WST     +0800    West Australian Standard
     PHT     +0800    Asia Manila
     JST     +0900    Japan Standard, USSR Zone 8
     ROK     +0900    Republic of Korea
     CAST    +0930    Central Australian Standard
     EAST    +1000    Eastern Australian Standard
     GST     +1000    Guam Standard, USSR Zone 9  gst=Greenland Std    -0300
     CADT    +1030    Central Australian Daylight
     EADT    +1100    Eastern Australian Daylight
     IDLE    +1200    International Date Line East
     NZST    +1200    New Zealand Standard
     NZT     +1200    New Zealand
     NZDT    +1300    New Zealand Daylight

   Others can be added in the future upon request.

   Date::Manip must be able to determine the timezone the user is in.  It
does this by looking in the following places:

     $Date::Manip::TZ (set with Date_Init or in Manip.pm)
     $ENV{TZ}
     the unix `date` command (if available)
     $main::TZ
     /etc/TIMEZONE
     /etc/timezone

   At least one of these should contain a timezone in one of the supported
forms.  If none do by default, the TZ variable must be set with Date_Init.

   The timezone may be in the STD#DST format (in which case both
abbreviations must be in the table above) or any of the formats described
above.  The STD#DST format is NOT available when parsing a date however.
The following forms are also available and are treated similar to the
STD#DST forms:

     US/Pacific
     US/Mountain
     US/Central
     US/Eastern
     Canada/Pacific
     Canada/Mountain
     Canada/Central
     Canada/Eastern

BUSINESS MODE
=============

   Anyone using business mode is going to notice a few quirks about it
which should be explained.  When I designed business mode, I had in mind
what UPS tells me when they say 2 day delivery, or what the local business
which promises 1 business day turnaround really means.

   If you do a business day calculation (with the workday set to
9:00-5:00), you will get the following:

     Saturday at noon + 1 business day = Tuesday at 9:00
     Saturday at noon - 1 business day = Friday at 9:00

   What does this mean?

   We have a business that works 9-5 and they have a drop box so I can drop
things off over the weekend and they promise 1 business day turnaround.  If
I drop something off Friday night, Saturday, or Sunday, it doesn't matter.
They're going to get started on it Monday morning.  It'll be 1 business day
to finish the job, so the earliest I can expect it to be done is around
17:00 Monday or 9:00 Tuesday morning.  Unfortunately, there is some
ambiguity as to what day 17:00 really falls on, similar to the ambiguity
that occurs when you ask what day midnight falls on.  Although it's not the
only answer, Date::Manip treats midnight as the beginning of a day rather
than the end of one.  In the same way, 17:00 is equivalent to 9:00 the next
day and any time the date calculations encounter 17:00, it automatically
switch to 9:00 the next day.  Although this introduces some quirks, I think
this is justified.  You just have to treat 17:00/9:00 as being ambiguous
(in the same way you treat midnight as being ambiguous).

   Equivalently, if I want a job to be finished on Saturday (despite the
fact that I cannot pick it up since the business is closed), I have to
drop it off no later than Friday at 9:00.  That gives them a full business
day to finish it off.  Of course, I could just as easily drop it off at
17:00 Thursday, or any time between then and 9:00 Friday.  Again, it's a
matter of treating 9:00 as ambiguous.

   So, in case the business date calculations ever produce results that you
find confusing, I believe the solution is to write a wrapper which,
whenever it sees a date with the time of exactly 9:00, it treats it
specially (depending on what you want.

   So Saturday + 1 business day = Tuesday at 9:00 (which means anything
from Monday 17:00 to Tuesday 9:00), but Monday at 9:01 + 1 business day =
Tuesday at 9:01 which is exact.

   If this is not exactly what you have in mind, don't use the DateCalc
routine.  You can probably get whatever behavior you want using the
routines Date_IsWorkDay, Date_NextWorkDay, and Date_PrevWorkDay described
above.

CUSTOMIZING DATE::MANIP
=======================

   There are a number of variables which can be used to customize the way
Date::Manip behaves.  There are also several ways to set these variables.

   At the top of the Manip.pm file, there is a section which contains all
customization variables.  These provide the default values.

   These can be overridden in a global config file if one is present (this
file is optional).  If the GlobalCnf variable is set in the Manip.pm file,
it contains the full path to a config file.  If the file exists, it's
values will override those set in the Manip.pm file.  A sample config file
is included with the Date::Manip distribution.  Modify it as appropriate
and copy it to some appropriate directory and set the GlobalCnf variable in
the Manip.pm file.

   Each user can have a personal config file which is of the same form as
the global config file.  The variables PersonalCnf and PersonalCnfPath set
the name and search path for the personal config file.  This file is also
optional.  If present, it overrides any values set in the global file.

   NOTE: if you use business mode calculations, you must have a config file
(either global or personal) since this is the only place where you can
define holidays.

   Finally, any variables passed in through Date_Init override all other
values.

   A config file can be composed of several sections.  The first section
sets configuration variables.  Lines in this section are of the form:

     VARIABLE = VALUE

   For example, to make the default language French, include the line:

     Language = French

   Only variables described below may be used.  Blank lines and lines
beginning with a pound sign (#) are ignored.  All spaces are optional and
strings are case insensitive.

   A line which starts with an asterisk (*) designates a new section.  For
example, the HOLIDAY section starts with a line:

     *Holiday

   The various sections are defined below.

DATE::MANIP VARIABLES
=====================

   All Date::Manip variables which can be used are described in the
following section.

IgnoreGlobalCnf
     If this variable is used (any value is ignored), the global config
     file is not read.  It must be present in the initial call to
     Date_Init or the global config file will be read.

EraseHolidays
     If this variable is used (any value is ignored), the current list of
     defined holidays is erased.  A new set will be set the next time a
     config file is read in.  This can be set in either the global config
     file or as a Date_Init argument (in which case holidays can be read
     in from both the global and personal config files) or in the personal
     config file (in which case, only holidays in the personal config file
     are counted).

PathSep
     This is a regular expression used to separate multiple paths.  For
     example, on Unix, it defaults to a colon (:) so that multiple paths
     can be written PATH1:PATH2 .  For Win32 platforms, it defaults to a
     semicolon (;) so that paths such as "c:\;d:\" will work.

GlobalCnf
     This variable can be passed into Date_Init to point to a global
     configuration file.  The value must be the complete path to a config
     file.

     By default, no global config file is read.  Any time a global config
     file is read, the holidays are erased.

     Paths may have a tilde (~) expansion on platforms where this is
     supported (currently Unix and VMS).

PersonalCnf
     This variable can be passed into Date_Init or set in a global config
     file to set the name of the personal configuration file.

     The default name for the config file is .DateManip.cnf on all Unix
     platforms and Manip.cnf on all non-Unix platforms (because some of
     them insist on 8.3 character filenames :-).

PersonalCnfPath
     This is a list of paths separated by the separator specified by the
     PathSep variable.  These paths are each checked for the PersonalCnf
     config file.

     Paths may have a tilde (~) expansion on platforms where this is
     supported (currently Unix and VMS).

Language
     Date::Manip can be used to parse dates in many different languages.
     Currently, it is configured to read  the following languages (the
     version in which they added is included for historical interest):

          English      (default)
          French       (5.02)
          Swedish      (5.05)
          German       (5.31)
          Dutch        (5.32)     aka Nederlands
          Polish       (5.32)
          Spanish      (5.33)
          Portuguese   (5.34)
          Romanian     (5.35)
          Italian      (5.35)

     Others can be added easily.  Language is set to the language used to
     parse dates.  If you are interested in providing a translation for a
     new language, email me (see the AUTHOR section below) and I'll send
     you a list of things that I need.

DateFormat
     Different countries look at the date 12/10 as Dec 10 or Oct 12.  In
     the United States, the first is most common, but this certainly
     doesn't hold true for other countries.  Setting DateFormat to "US"
     forces the first behavior (Dec 10).  Setting DateFormat to anything
     else forces the second behavior (Oct 12).

TZ
     If set, this defines the local timezone.  See the TIMEZONES section
     above for information on it's format.

ConvTZ
     All date comparisons and calculations must be done in a single time
     zone in order for them to work correctly.  So, when a date is parsed,
     it should be converted to a specific timezone.  This allows dates to
     easily be compared and manipulated as if they are all in a single
     timezone.

     The ConvTZ variable determines which timezone should be used to store
     dates in.  If it is left blank, all dates are converted to the local
     timezone (see the TZ variable above).  If it is set to one of the
     timezones listed above, all dates are converted to this timezone.
     Finally, if it is set to the string "IGNORE", all timezone
     information is ignored as the dates are read in (in this case, the
     two dates "1/1/96 12:00 GMT" and "1/1/96 12:00 EST" would be treated
     as identical).

Internal
     When a date is parsed using ParseDate, that date is stored in an
     internal format which is understood by the Date::Manip routines
     UnixDate and DateCalc.  Originally, the format used to store the date
     internally was:

          YYYYMMDDHH:MN:SS

     It has been suggested that I remove the colons (:) to shorten this to:

          YYYYMMDDHHMNSS

     The main advantage of this is that some databases are colon delimited
     which makes storing a date from Date::Manip tedious.

     In order to maintain backwards compatibility, the Internal variable
     was introduced.  Set it to 0 (to use the old format) or 1 (to use the
     new format).

FirstDay
     It is sometimes necessary to know what day of week is regarded as
     first.  By default, this is set to Monday, but many countries and
     people will prefer Sunday (and in a few cases, a different day may be
     desired).  Set the FirstDay variable to be the first day of the week
     (1=Monday, 7=Sunday) Monday should be chosen to to comply with ISO
     8601.

WorkWeekBeg, WorkWeekEnd
     The first and last days of the work week.  By default, Monday and
     Friday.  WorkWeekBeg must come before WorkWeekEnd numerically.  The
     days are numbered from 1 (Monday) to 7 (Sunday).

     There is no way to handle an odd work week of Thu to Mon for example
     or 10 days on, 4 days off.

WorkDay24Hr
     If this is non-nil, a work day is treated as being 24 hours long.  The
     WorkDayBeg and WorkDayEnd variables are ignored in this case.

WorkDayBeg, WorkDayEnd
     The times when the work day starts and ends.  WorkDayBeg must come
     before WorkDayEnd (i.e. there is no way to handle the night shift
     where the work day starts one day and ends another).  Also, the
     workday MUST be more than one hour long (of course, if this isn't the
     case, let me know... I want a job there!).

     The time in both can be in any valid time format (including
     international formats), but seconds will be ignored.

TomorrowFirst
     Periodically, if a day is not a business day, we need to find the
     nearest business day to it.  By default, we'll look to "tomorrow"
     first, but if this variable is set to 0, we'll look to "yesterday"
     first.  This is only used in the Date_NearestWorkDay and is easily
     overridden (see documentation for that function).

DeltaSigns
     Prior to Date::Manip version 5.07, a negative delta would put negative
     signs in front of every component (i.e. "0:0:-1:-3:0:-4").  By
     default, 5.07 changes this behavior to print only 1 or two signs in
     front of the year and day elements (even if these elements might be
     zero) and the sign for year/month and day/hour/minute/second are the
     same.  Setting this variable to non-zero forces deltas to be stored
     with a sign in front of every element (including elements equal to 0).

Jan1Week1
     ISO 8601 states that the first week of the year is the one which
     contains Jan 4 (i.e. it is the first week in which most of the days
     in that week fall in that year).  This means that the first 3 days of
     the year may be treated as belonging to the last week of the previous
     year.  If this is set to non-nil, the ISO 8601 standard will be
     ignored and the first week of the year contains Jan 1.

YYtoYYYY
     By default, a 2 digit year is treated as falling in the 100 year
     period of CURR-89 to CURR+10.  YYtoYYYY may be set to any integer N
     to force a 2 digit year into the period CURR-N to CURR+(99-N).  A
     value of 0 forces the year to be the current year or later.  A value
     of 99 forces the year to be the current year or earlier.  Since I do
     no checking on the value of YYtoYYYY, you can actually have it any
     positive or negative value to force it into any century you want.

     YYtoYYYY can also be set to "C" to force it into the current century,
     or to "C##" to force it into a specific century.  So, no (1998), "C"
     forces 2 digit years to be 1900-1999 and "C18" would force it to be
     1800-1899.

     It can also be set to the form "C####" to force it into a specific 100
     year period.  C1950 refers to 1950-2049.

UpdateCurrTZ
     If a script is running over a long period of time, the timezone may
     change during the course of running it (i.e. when daylight savings
     time starts or ends).  As a result, parsing dates may start putting
     them in the wrong time zone.  Since a lot of overhead can be saved if
     we don't have to check the current timezone every time a date is
     parsed, by default checking is turned off.  Setting this to non-nil
     will force timezone checking to be done every time a date is
     parsed... but this will result in a considerable performance penalty.

     A better solution would be to restart the process on the two days per
     year where the timezone switch occurs.

IntCharSet
     If set to 0, use the US character set (7-bit ASCII) to return strings
     such as the month name.  If set to 1, use the appropriate
     international character set.

ForceDate
     This variable can be set to a date in the format: YYYY-MM-DD-HH:MN:SS
     to force the current date to be interpreted as this date.  Since the
     current date is used in parsing, this string will not be parsed and
     MUST be in the format given above.

HOLIDAY SECTION
===============

   The holiday section of the config file is used to define holidays.  Each
line is of the form:

     DATE = HOLIDAY

   HOLIDAY is the name of the holiday (or it can be blank in which case the
day will still be treated as a holiday... for example the day after
Thanksgiving or Christmas is often a work holiday though neither are
named).

   DATE is a string which can be parsed to give a valid date in any year.
It can be of the form

     Date
     Date + Delta
     Date - Delta
     Recur

   A valid holiday section would be:

     *Holiday

     1/1                             = New Year's Day
     third Monday in Feb             = Presidents' Day
     fourth Thu in Nov               = Thanksgiving

     # The Friday after Thanksgiving is an unnamed holiday most places
     fourth Thu in Nov + 1 day       =

     1*0:0:0:0:0:0*EASTER            = Easter
     1*11:0:11:0:0:0*CWD             = Veteren's Day (observed)
     1*0:0:0:0:0:0*EASTER,PD5        = Good Friday

   In a Date + Delta or Date - Delta string, you can use business mode by
including the appropriate string (see documentation on DateCalc) in the
Date or Delta.  So (in English), the first workday before Christmas could
be defined as:

     12/25 - 1 business day          =

   The date's may optionally contain the year.  For example, the dates

     1/1
     1/1/1999

   refers to Jan 1 in any year or in only 1999 respectively.  For dates
that refer to any year, the date must be written such that by simply
appending the year (separated by spaces) it can be correctly interpreted.
This will work for everything except ISO 8601 dates, so ISO 8601 dates may
not be used in this case.

   In cases where you are interested in business type calculations, you'll
want to define most holidays using recurrences, since they can define when
a holiday is celebrated in the financial world.  For example, Christmas
should be defined as:

     1*12:0:24:0:0:0*FW1  = Christmas

   if you wanted to define both Christmas and Boxing days (Boxing is the
day after Christmas, and is celebrated in some parts of the world), you
could do it in one of the following ways:

     1*12:0:24:0:0:0*FW1  = Christmas
     1*12:0:25:0:0:0*FW1  = Boxing

     1*12:0:24:0:0:0*FW1 = Christmas
        01*12:0:24:0:0:0*FW1 = Boxing

     1*12:0:24:0:0:0*FW1,a  = Christmas
     1*12:0:25:0:0:0*FW1,b  = Boxing

   The following will NOT work:

     1*12:0:24:0:0:0*FW1  = Christmas
     1*12:0:24:0:0:0*FW2  = Boxing

     1*12:0:24:0:0:0*FW1  = Christmas
     1*12:0:24:0:0:0*FW1  = Boxing

   The reasoning behind all this is as follows:

   Holidays go into affect the minute they are parsed.  So, the minute the
line:

     1*12:0:24:0:0:0*FW1  = Christmas

   is parse, Christmas is defined.  Then, if you tried to use

     1*12:0:24:0:0:0*FW2  = Boxing

   it'll step forward 2 work days (skipping Christmas since that's no
longer a work day) and define the work day two days after Christmas, NOT
the day after Christmas.  So, the best way to define Boxing day is using
either:

     1*12:0:25:0:0:0*FW1  = Boxing
     1*12:0:24:0:0:0*FW1  = Boxing

   with the first being the preferred method since it avoids confusion.  An
alternative is to use the same recurrence twice in a row:

     1*12:0:24:0:0:0*FW1  = Christmas
     1*12:0:24:0:0:0*FW1  = Boxing

   but since the recurrences are currently stored in a hash, this won't
work as desired.  To fix this, make them unique with either a fake flag,
adding an innocuous 0 somewhere, etc., so the following would be valid
ways to define Boxing day:

     1*12:0:24:0:0:0*FW1,a  = Boxing
     01*12:0:24:0:0:0*FW1   = Boxing

   At times, you may want to switch back and forth between two holiday
files.  This can be done by calling the following:

     &Date_Init("EraseHolidays=1","PersonalCnf=FILE1");
     ...
     &Date_Init("EraseHolidays=1","PersonalCnf=FILE2");
     ...

EVENTS SECTION
==============

   The Events section of the config file is similar to the Holiday section.
It is used to name certain days or times, but there are a few important
differences:

Events can be assigned to any time and duration
     All holidays are exactly 1 day long.  They are assigned to a period
     of time from midnight to midnight.

     Events can be based at any time of the day, and may be of any
     duration.

Events don't affect business mode calculations
     Unlike holidays, events are completely ignored when doing business
     mode calculations.

   Whereas holidays were added with business mode math in mind, events
were added with calendar and scheduling applications in mind.

   Every line in the events section is of the form:

     EVENT = NAME

   where NAME is the name of the event, and EVENT defines when it occurs
and it's duration.  An EVENT can be defined in the following ways:

     Date
     Date*
     Recur    [NYI]
     Recur*   [NYI]

     Date  ; Date
     Date  ; Delta
     Recur ; Delta   [NYI]

     Date  ; Delta ; Delta   [NYI]
     Recur ; Delta ; Delta   [NYI]

   Here, Date* refers to a string containing a Date with NO TIME fields
(Jan 12, 1/1/2000, 2010-01-01) while Date does contain time fields.
Similarily, Recur* stands for a recurrence with the time fields all equal
to 0) while Recur stands for a recurrence with at least one non-zero time
field.

   Both Date* and Recur* refer to an event very similar to a holiday which
goes from midnight to midnight.

   Date and Recur refer to events which occur at the time given and with a
duration of 1 hour.

   Events given by "Date ; Date", "Date ; Delta", and "Recur ; Delta"
contain both the starting date and either ending date or duration.

   Events given as three elements "Date ; Delta ; Delta" or "Recur ; Delta
; Delta" take a date and add both deltas to it to give the starting and
ending time of the event.  The order and sign of the deltas is unimportant
(and both can be the same sign to give a range of times which does not
contain the base date).

   Items marked with [NYI] are not yet implemented but will be by the time
this is released.

BACKWARDS INCOMPATIBILITIES
===========================

   For the most part, Date::Manip has remained backward compatible at every
release.  There have been a few minor incompatibilities introduced at
various stages.  Major differences are marked with bullets.

VERSION 5.38
Removed Date_DaysSince999
     The Date_DaysSince999 function (deprecated in 5.35) has been removed.

VERSION 5.35

    Deprected Date_DaysSince999
          In fixing support for the years 0000-0999, I rewrote
          Date_DaysSince999 to be Date_DaysSince1BC.  The
          Date_DaysSince999 function will be removed.

    Added PathSep variable
          In order to better support Win32 platforms, I added the PathSep
          config variable.  This will allow the use of paths such as
          "c:\date" on Win32 platforms.  Old config files on Win32
          platforms (which were not working correctly in many cases) may
          not work if they contain path information to the personal config
          file.

VERSION 5.34
        * All Date::Manip variables are no longer accessible

          Previously, Date::Manip variables were declared using a full
          package name.  Now, they are declared with the my() function.
          This means that internal variables are no longer accessible
          outside of the module.

        * Week interpretation in business mode deltas A business mode
          delta containing a week value used to be treated as 7 days.  A
          much more likely interpretation of a week is Monday to Monday,
          regardless of holidays, so this is now the behavior.

        * %z UnixDate format The %z UnixDate format used to return the
          Timezone abbreviation.  It now returns it as a GMT offset (i.e.
          -0500).  %Z still returns the Timezone abbreviation.

        * Formats "22nd sunday" returns the intuitive value The date "22nd
          sunday" used to return the Sunday of the 22nd week of the year
          (which could be the 21st, 22nd, or 23rd Sunday of the year
          depending on how weeks were defined).  Now, it returns the 22nd
          Sunday of the year regardless.

        * Separator in DD/YYmmm and mmmDD/YY formats no longer optional
          Previously, the date "Dec1065" would return Dec 10, 1965.  After
          adding the YYYYmmm and mmmYYYY formats, this was no longer
          possible.  The separator between DD and YY is no longer
          optional, so

               Dec1065     returns December 1, 1065
               Dec10/65    returns December 10, 1965

        * Date_Cmp added

          This is not a backwards incompatibility... but is added to help
          prepare for a future incompatibility.  In one of the next
          versions of Date::Manip, the internal format of the date will
          change to include timezone information.  All date comparisons
          should be made using Date_Cmp (which currently does nothing more
          than call the perl "cmp" command, but which will important when
          comparing dates that include the timezone).

VERSION 5.32

    Date_Init arguments
          The old style Date_Init arguments that were deprecated in
          version 5.07 have been removed.

    DateManip.cnf change
          Changed .DateManip.cnf to Manip.cnf (to get rid of problems on
          OS's that insist on 8.3 filenames) for all non-Unix platforms
          (Wintel, VMS, Mac).  For all Unix platforms, it's still
          .DateManip.cnf .  It will only look in the user's home directory
          on VMS and Unix.

VERSION 5.30
        * Delta format changed

          A week field has been added to the internal format of the delta.
          It now reads "Y:M:W:D:H:MN:S" instead of "Y:M:D:H:MN:S".

VERSION 5.21

    Long running processes may give incorrect timezone
          A process that runs during a timezone change (Daylight Saving
          Time specifically) may report the wrong timezone.  See the
          UpdateCurrTZ variable for more information.

    UnixDate "%J", "%W", and "%U" formats fixed
          The %J, %W, and %U will no longer report a week 0 or a week 53
          if it should really be week 1 of the following year.  They now
          report the correct week number according to ISO 8601.

VERSION 5.20
        * ParseDate formats removed (ISO 8601 compatibility)

          Full support for ISO 8601 formats was added.  As a result, some
          formats which previously worked may no longer be parsed since
          they conflict with an ISO 8601 format.  These include MM-DD-YY
          (conflicts with YY-MM-DD) and YYMMDD (conflicts with YYYYMM).
          MM/DD/YY still works, so the first form can be kept easily by
          changing "-" to "/".  YYMMDD can be changed to YY-MM-DD before
          being parsed.  Whenever parsing dates using dashes as
          separators, they will be treated as ISO 8601 dates.  You can get
          around this by converting all dashes to slashes.

        * Week day numbering

          The day numbering was changed from 0-6 (sun-sat) to 1-7
          (mon-sun) to be ISO 8601 compatible.  Weeks start on Monday
          (though this can be overridden using the FirstDay config
          variable) and the 1st week of the year contains Jan 4 (though it
          can be forced to contain Jan 1 with the Jan1Week1 config
          variable).

VERSION 5.07

    UnixDate "%s" format
          Used to return the number of seconds since 1/1/1970 in the
          current timezone.  It now returns the number of seconds since
          1/1/1970 GMT.  The "%o" format was added which returns what "%s"
          previously did.

    Internal format of delta
          The format for the deltas returned by ParseDateDelta changed.
          Previously, each element of a delta had a sign attached to it
          (+1:+2:+3:+4:+5:+6).  The new format removes all unnecessary
          signs by default (+1:2:3:4:5:6).  Also, because of the way
          deltas are normalized (see documentation on ParseDateDelta), at
          most two signs are included.  For backwards compatibility, the
          config variable DeltaSigns was added.  If set to 1, all deltas
          include all 6 signs.

    Date_Init arguments
          The format of the Date_Init calling arguments changed.  The old
          method

               &Date_Init($language,$format,$tz,$convtz);

          is still supported , but this support will likely disappear in
          the future.  Use the new calling format instead:

               &Date_Init("var=val","var=val",...);

          NOTE:  The old format is no longer supported as of version 5.32 .

KNOWN PROBLEMS
==============

   The following are not bugs, but they may give some people problems.

Unable to determine TimeZone
     Perhaps the most common problem occurs when you get the error:

          Error: Date::Manip unable to determine TimeZone.

     Date::Manip tries hard to determine the local timezone, but on some
     machines, it cannot do this (especially non-unix systems).  To fix
     this, just set the TZ variable, either at the top of the Manip.pm
     file, or in the DateManip.cnf file.  I suggest using the form
     "EST5EDT" so you don't have to change it every 6 months when going to
     or from daylight savings time.

     Windows NT does not seem to set the TimeZone by default.  From the
     Perl-Win32-Users mailing list:

          > How do I get the TimeZone on my NT?
          >
          >      $time_zone = $ENV{'TZ'};
          >
          You have to set the variable before, WinNT doesn't set it by
          default.  Open the properties of "My Computer" and set a SYSTEM
          variable TZ to your timezone.   Jenda@Krynicky.cz

     This might help out some NT users.

     A minor (false) assumption that some users might make is that since
     Date::Manip passed all of it's tests at install time, this should not
     occur and are surprised when it does.

     Some of the tests are timezone dependent.  Since the tests all include
     input and expected output, I needed to know in advance what timezone
     they would be run in.  So, the tests all explicitly set the timezone
     using the TZ configuration variable passed into Date_Init.  Since
     this overrides any other method of determining the timezone,
     Date::Manip uses this and doesn't have to look elsewhere for the
     timezone.

     When running outside the tests, Date::Manip has to rely on it's other
     methods for determining the timezone.

Complaining about getpwnam/getpwuid
     Another problem is when running on Micro$oft OS'es.  I have added many
     tests to catch them, but they still slip through occasionally.  If
     any ever complain about getpwnam/getpwuid, simply add one of the
     lines:

          $ENV{OS} = Windows_NT
          $ENV{OS} = Windows_95

     to your script before

          use Date::Manip

Date::Manip is slow
     The reasons for this are covered in the SHOULD I USE DATE::MANIP
     section above.

     Some things that will definitely help:

     Version 5.21 does run noticeably faster than earlier versions due to
     rethinking some of the initialization, so at the very least, make
     sure you are running this version or later.

     ISO-8601 dates are parsed first and fastest.  Use them whenever
     possible.

     Avoid parsing dates that are referenced against the current time (in 2
     days, today at noon, etc.).  These take a lot longer to parse.

          Example:  parsing 1065 dates with version 5.11 took 48.6 seconds, 36.2
          seconds with version 5.21, and parsing 1065 ISO-8601 dates with version
          5.21 took 29.1 seconds (these were run on a slow, overloaded computer with
          little memory... but the ratios should be reliable on a faster computer).

     Business date calculations are extremely slow.  You should consider
     alternatives if possible (i.e. doing the calculation in exact mode
     and then multiplying by 5/7).  There will be an approximate business
     mode in one of the next versions which will be much faster (though
     less accurate) which will do something like this.  Whenever possible,
     use this mode.  And who needs a business date more accurate than "6
     to 8 weeks" anyway huh :-)

     Never call Date_Init more than once.  Unless you're doing something
     very strange, there should never be a reason to anyway.

Sorting Problems
     If you use Date::Manip to sort a number of dates, you must call
     Date_Init either explicitly, or by way of some other Date::Manip
     routine before it is used in the sort.  For example, the following
     code fails:

          use Date::Manip;
          # &Date_Init;
          sub sortDate {
              my($date1, $date2);
              $date1 = &ParseDate($a);
              $date2 = &ParseDate($b);
              return (&Date_Cmp($date1,$date2));
          }
          @date = ("Fri 16 Aug 96",
                   "Mon 19 Aug 96",
                   "Thu 15 Aug 96");
          @i=sort sortDate @dates;

     but if you uncomment the Date_Init line, it works.  The reason for
     this is that the first time you call Date_Init, it initializes a
     number of items used by Date::Manip.  Some of these have to be sorted
     (regular expressions sorted by length to ensure the longest match).
     It turns out that perl (5.004 and earlier) has a bug in it which does
     not allow a sort within a sort.  At some point, this should be fixed,
     but for now, the best thing to do is to call Date_Init explicitly.

     NOTE: This is an EXTREMELY inefficient way to sort data.  Instead, you
     should parse the dates with ParseDate, sort them using a normal string
     comparison, and then convert them back to the format desired using
     UnixDate.

RCS Control
     If you try to put Date::Manip under RCS control, you are going to have
     problems.  Apparently, RCS replaces strings of the form "$Date...$"
     with the current date.  This form occurs all over in Date::Manip.  To
     prevent the RCS keyword expansion, checkout files using "co -ko".
     Since very few people will ever have a desire to do this (and I don't
     use RCS), I have not worried about it.

KNOWN BUGS
==========

Daylight Savings Times
     Date::Manip does not handle daylight savings time, though it does
     handle timezones to a certain extent.  Converting from EST to PST
     works fine.  Going from EST to PDT is unreliable.

     The following examples are run in the winter of the US East coast
     (i.e.  in the EST timezone).

          print UnixDate(ParseDate("6/1/97 noon"),"%u"),"\n";
                  => Sun Jun  1 12:00:00 EST 1997

     June 1 EST does not exist.  June 1st is during EDT.  It should print:

          => Sun Jun  1 00:00:00 EDT 1997

     Even explicitly adding the timezone doesn't fix things (if anything,
     it makes them worse):

          print UnixDate(ParseDate("6/1/97 noon EDT"),"%u"),"\n";
                  => Sun Jun  1 11:00:00 EST 1997

     Date::Manip converts everything to the current timezone (EST in this
     case).

     Related problems occur when trying to do date calculations over a
     timezone change.  These calculations may be off by an hour.

     Also, if you are running a script which uses Date::Manip over a
     period of time which starts in one time zone and ends in another
     (i.e. it switches form Daylight Savings Time to Standard Time or vice
     versa), many things may be wrong (especially elapsed time).

     I hope to fix these problems in a future release so that it would
     convert everything to the current zones (EST or EDT).

BUGS AND QUESTIONS
==================

   If you find a bug in Date::Manip, please send it directly to me (see the
AUTHOR section below) rather than posting it to one of the newsgroups.
Although I try to keep up with the comp.lang.perl.* groups, all too often I
miss news (flaky news server, articles expiring before I caught them, 1200
articles to wade through and I missed one that I was interested in, etc.).

   When filing a bug report, please include the following information:

     o  The version of Date::Manip you are using.  You can get this by using
        the script:

     use Date::Manip;
     print &DateManipVersion(),"\n";

     o  The output from "perl -V"

   If you have a problem using Date::Manip that perhaps isn't a bug (can't
figure out the syntax, etc.), you're in the right place.  Go right back to
the top of this man page and start reading.  If this still doesn't answer
your question, mail me (again, please mail me rather than post to the
newsgroup).

YEAR 2000
=========

   In hindsight, the fact that I've only been asked once (so far) if
Date::Manip is year 2000 compliant surprises me a bit.  Still, as 2000
approaches and this buzzword starts flying around more and more
frantically, other's might follow suit, so this section answers the
question.

   Is Date::Manip year 2000 compliant?

   This question is largely meaningless.  Date::Manip is basically just a
parser.  You give it a date and it'll manipulate it.  Date::Manip does
store the date internally as a 4 digit year, and performs all operations
using this internal representation, so I will state that Date::Manip is
CAPABLE of writing Y2K compliant code.

   But Date::Manip is simply a library.  If you use it correctly, your code
can be Y2K compliant.  If you don't, your code may not be Y2K compliant.

   The bottom line is this:

     Date::Manip is a library that is capable of being used to write Y2K
     compliant code.  It may also be used to write non-Y2K compliant code.

     If your code is NOT Y2K compliant, it is NOT due to any deficiency in
     Date::Manip.  Rather, it is due to poor programming on the part of the
     person using Date::Manip.

   For an excellent treatment of the Y2K problem, see the article by Tom
Christiansen at:

     http://language.perl.com/news/y2k.html

   A slightly better question is "Is Perl year 2000 compliant"?  This is
covered in the perl FAQ (section 4) and in the article by Tom Crhistiansen.

   The best question is "For what dates is Date::Manip useful?"  It
definitely can't handle BC dates, or dates past Dec 31, 9999.  So
Date::Manip works during the years 1000 to 9999.

   In practical terms however, Date::Manip deals with the Gregorian
calendar, and is therefore useful in the period that that calendar has
been, or will be, in effect.  The Gregorian calendar was first adopted by
the Catholic church in 1582, but some countries were still using the
Julian calendar as late as the early part of the 20th century.  Also, at
some point (probably no earlier than the year 3000 and possibly much
later), the Gregorian system is going to have to be modified slightly
since the current system of leap years is off by a few seconds a year.
So...  in practical terms, Date::Manip is _probably_ useful from 1900 to
3000.

   One other note is that Date::Manip will NOT handle 3 digit years.  So,
if you store the year as an offset from 1900 (which is 2 digits now, but
will become 3 digits in 2000), these will NOT be parsable by Date::Manip.

ACKNOWLEDGMENTS
===============

   There are many people who have contributed to Date::Manip over the years
that I'd like to thank.  The most important contributions have come in the
form of suggestions and bug reports by users.  I have tried to include the
name of every person who first suggested each improvement or first reported
each bug.  These are included in the HISTORY file in the Date::Manip
distribution.  The list is simply too long to appear here, but I appreciate
their help.  A number of people have made suggestions which have not yet
been implemented.  When (and if) the suggestion is implemented, they will
go in the HISTORY file as well, but even if the suggestion is never
implemented, my thanks to them as well.

   Thanks to Alan Cezar and Greg Schiedler for paying me to implement the
Events_List routine.  They gave me the idea, and were then willing to pay
me for my time to get it implemented quickly.

   I'd also like a couple of authors.  Date::Manip has recently been
getting some really good press in a couple of books.  Since no one's
paying me to write Date::Manip, seeing my module get a good review in a
book written by someone else really makes my day.  My thanks to Nate
Padwardhan and Clay Irving (Programming with Perl Modules - part of the
O'Reilly Perl Resource Kit); and Tom Christiansen and Nathan Torkington
(The Perl Cookbook).  Also, thanks to any other authors who've written
about Date::Manip who's books I haven't seen.

AUTHOR
======

   Sullivan Beck (sbeck@cpan.org)

   You can always get the newest beta version of Date::Manip (which may fix
problems in the current CPAN version... and may add others) from my home
page:

   http://www.cise.ufl.edu/~sbeck/

Translate between Julian days and Maya days.
********************************************

NAME
====

   Date::Maya  -  Translate between Julian days and Maya days.

SYNOPSIS
========

     use Date::Maya;

     my  $long_count             = julian_to_maya 2451432;
     my ($long, $tzolkin, $haab) = julian_to_maya 2451432;
     my  $julian                 = maya_to_julian '12.19.6.9.9';

DESCRIPTION
===========

   For an extensive description of both the Maya calendar and Julian days,
see the calendar faq [1].

   This module presents routines to calculate the Mayan day from a Julian
day, and a Julian day from a Mayan day. The Mayan calendar has different
dating systems, the Long Count (which cycles every 5125 years), the
Tzolkin (260 days) and the Haab (365 days). The Long Count consists of
quintuple of numbers (really a mixed base 20/18 number), while the Tzolkin
and the Haab consist of day numbers and week or month names. In the
Tzolkin, both the week number and week name change from day to day; the
week number cycles through 1 to 13, while there are 20 week names to cycle
through. This gives a period of 260 days. The Haab has 18 months, of each
20 days, numbered 0 to 19. A new month is only started after reaching day
19. At the end of the 360 days, there are 5 Uayeb days. In the Long Count,
all the numbers of the quintuple are 0 to 19 or 0 to 17, except the first,
(the number of *baktuns*), which goes from 1 to 13; with 13 serving as 0.

   By default, Date::Maya exports two subroutines, `julian_to_maya' and
`maya_to_julian'. `julian_to_maya' takes a Julian day as argument, and
returns the Long Count date in scalar context. In list context, it returns
the Long Count date, the Tzolkin date, and the Haab date. `maya_to_julian'
takes a Long Count date as argument, and returns a Julian day.

EPOCH AND ROLL OVER
-------------------

   It is unclear when the epoch of the Mayan calendar occurred. Three dates
are mentioned as candidates, 13 Aug 3114 BC, 11 Aug 3114 BC, and
15 Oct 3374 BC. Unless changed, this module assumes 13 Aug 3114 as the
epoch.

   To change the epoch, import the function `maya_epoch', and call it with
the Julian date that should be the epoch. Constants `MAYA_EPOCH1',
`MAYA_EPOCH2' and `MAYA_EPOCH3' can be imported, which will have the
Julian days for 13 Aug 3114 BC, 11 Aug 3114 BC, and 15 Oct 3374 BC as
values.  The three constants can be imported at once by using the
`:MAYA_EPOCH' tag.

   The Mayan calendar is cyclic, with a period of just over 5125 years.
This means that if the epoch was in Aug 3114 BC, the calendar will roll
over in Dec 2012 AD. If the epoch was in 3374 BC, the roll over has occured
over 200 years ago. Since the calendar is cyclic, the `maya_to_julian'
function is not unique. We will however return only one date, and that is
the first Julian day matching the Long Count date on or after the choosen
epoch.

   The Mayan Long Count calendar rolls over after 1872000 days.

REFERENCES
==========

[1]
     Tondering, Claus: *FREQUENTLY ASKED QUESTIONS ABOUT CALENDARS*
     http://www.pip.dknet.dk/%7Ec-t/calendar.html

REVISION HISTORY
================

     $Log: Maya.pm,v $
     Revision 1.1  1999/09/10 18:01:05  abigail
     Initial revision

AUTHOR
======

   This package was written by Abigail, abigail@delanet.com

COPYRIGHT AND LICENSE
=====================

   This package is copyright 1999 by Abigail.

   This program is free and open software. You may use, copy, modify,
distribute and sell this program (and any modified variants) in any way
you wish, provided you do not restrict others to do the same.

Conversion of dates to ordinal numbers and vice versa
*****************************************************

NAME
====

   Date::Ordinal - Conversion of dates to ordinal numbers and vice versa

SYNOPSIS
========

     use Date::Ordinal;

     $ord     = month2ord('January');           # $ord gets 1
     $mon     = ord2month('1');                 # $mon gets 'January'
     $mon     = ord2month(1);                   # $mon gets 'January'
     $mon     = ord2month('01');                # $mon gets 'January'
     $arryref = all_month_ordinations
     @arry    = all_month_names
     $arryref = all_month_names_ref
     $arryref = all_short_month_names_ref
     $arryref = all_day_ordinations

     $arryref = all_hour_ordinations
     $arryref = all_minute_ordinations

     $hashref = ordination_month_pair # {'01' => 'January', ... }
     @day     = days

     =cut

   #----------------------------------------------------------------------

   package Date::Ordinal; #use strict;

   #----------------------------------------------------------------------

DESCRIPTION
===========

   This module is designed to aid in  creation of CGI popup_menus and also
interaction with SQL databases.

CONVERSION ROUTINES
===================

   There are two conversion routines: ord2month() and `month2ord()'.

ord2month()
     This function takes a month number [1..12] and returns a string which
     contains the name of the month identified. If the number is not a
     valid number, then undef will be returned:

          $mon = ord2month('3');

`month2ord()'
     This function takes a month name and returns the integer
     corresponding to the month name, if such exists.

     The match is a regexp match, so both 'Mar' and 'March' will return 3.

     If the argument could not be identified as a month name, then undef
     will be returned:

          $ord = month2ord('March');

     The case of the month name is not important.  See the section `KNOWN
     BUGS AND LIMITATIONS' in this node below.

QUERY ROUTINES
==============

   There is one function (and a reference variant) which can be used to
obtain a list of all month names:

`all_month_names()'
          Returns a list of all month names;

`all_month_names_ref()'
          Returns a reference to a list of all month names;

`all_short_month_names_ref()'
          Returns a reference to a list of all month names in 3-letter form

`ordination_month_pair()'
          returns a reference to a hash of the ordination of a month name
          and the month name

`all_month_ordinations()'
          returns a reference  a hash of the ordination of a month name
          and the month name

PRETTY-PRINTING ROUTINES
========================

`prezero()'
          if the current number is single-diit, prefix it with a '0'

KNOWN BUGS AND LIMITATIONS
==========================

   none

SEE ALSO
========

Locale::US
Date::Manip
AUTHOR
======

   Terrence Brannon <tbrannon@end70.com>

COPYRIGHT
=========

   Copyright (c) 2000 End70 Corporation

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Parse date strings into time values
***********************************

NAME
====

   Date::Parse - Parse date strings into time values

SYNOPSIS
========

     use Date::Parse;

     $time = str2time($date);

     ($ss,$mm,$hh,$day,$month,$year,$zone) = strptime($date);

DESCRIPTION
===========

   Date::Parse provides two routines for parsing date strings into time
values.

str2time(DATE [, ZONE])
     `str2time' parses DATE and returns a unix time value, or undef upon
     failure.  `ZONE', if given, specifies the timezone to assume when
     parsing if the date string does not specify a timezome.

strptime(DATE [, ZONE])
     `strptime' takes the same arguments as str2time but returns an array
     of values `($ss,$mm,$hh,$day,$month,$year,$zone)'. Elements are only
     defined if they could be extracted from the date string. The `$zone'
     element is the timezone offset in seconds from GMT. An empty array is
     returned upon failure.

MULTI-LANGUAGE SUPPORT
======================

   Date::Parse is capable of parsing dates in several languages, these are
English, French, German and Italian. Changing the language is done via a
static method call, for example

     Date::Parse->language('German');

   will cause Date::Parse to attempt to parse any subsequent dates in
German.

   This is only a first pass, I am considering changing this to be

     $lang = Date::Language->new('German');
     $lang->str2time("25 Jun 1996 21:09:55 +0100");

   I am open to suggestions on this.

EXAMPLE DATES
=============

   Below is a sample list of dates that are known to be parsable with
Date::Parse

     1995:01:24:09:08:17.1823213           ISO-8601
     1995-01-24:09:08:17.1823213
     Wed, 16 Jun 94 07:29:35 CST           Comma and day name are optional
     Thu, 13 Oct 94 10:13:13 -0700
     Wed, 9 Nov 1994 09:50:32 -0500 (EST)  Text in ()'s will be ignored.
     21 dec 17:05                          Will be parsed in the current time zone
     21-dec 17:05
     21/dec 17:05
     21/dec/93 17:05
     1999 10:02:18 "GMT"
     16 Nov 94 22:28:20 PST

BUGS
====

   When both the month and the date are specified in the date as numbers
they are always parsed assuming that the month number comes before the
date. This is the usual format used in American dates.

   The reason why it is like this and not dynamic is that it must be
deterministic. Several people have suggested using the current locale, but
this will not work as the date being parsed may not be in the format of
the current locale.

   My plans to address this, which will be in a future release, is to allow
the programmer to state what order they want these values parsed in.

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

COPYRIGHT
=========

   Copyright (c) 1995 Graham Barr. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Date::Tolkien::Shire.pm
***********************

NAME
====

   Date::Tolkien::Shire.pm

DESCRIPTION
===========

   This is an object-oriented module to convert dates into the Shire
Calender as presented in the Lord of the Rings by J. R. R. Tolkien.  It
includes converting epoch time to the Shire Calendar (you can also get
epoch time back), comparison operators, and a method to print a formatted
string containing that does something to the effect of on this date in
history - pulling events from the Lord of the Rings.

   The biggest use I can see in this thing is in a startup script or
possible to keep yourself entertained in an otherwise boring app that
includes a date.  If you have any other ideas/suggestions/uses, etc.,
please let me know.  I am curious to see how this gets used (if it gets
used that is).

AUTHOR
======

   Tom Braun <tbraun@pobox.com>

DATE
====

   February 2001

METHOD REFERENCE
================

   Note:  I have tried to make these as friendly as possible when an error
occurs.  As a consequence, none of them die, croak, etc.  All of these
return 0 on error, but as 0 can be a valid output in a couple cases (the
day of the month for a holiday, for example), the error method should
always be checked to see if an error has occured.  As long as you set a
date before you try to use it, you should be ok.

new
---

   $shiredate = Date::Tolkien::Shire->new; $shiredate =
Date::Tolkien::Shire->new(time); $shiredate =
Date::Tolkien::Shire->new($another_shiredate);

   The constructor new can take zero or one parameter.  Either a new
object can be created without setting a specific date (the zero parameter
version), or an object can be created and the date set to either a current
shire date, or an epoch time such as is returned by the time function.
For specifics on setting dates, see the 'set_date' function.

error
-----

     $the_error = $shiredate->error;
     $the_error = Date::Tolkien::Shire->error;

   This returns a null string if everything in the previous method call was
as it should be, and a string contain a description of what happened if an
error occurred.

set_date
--------

   This method takes either the seconds from the start of the epoch (like
what time returns) or another shire date object, and sets the date of the
object in question equal to that date.  If the object previously contained
a date, it will be overwritten.  Locatime, rather than utc, is used in
converting from epoch date.

   Please see the note below on calculating the year if your curious how I
arrived by that.

time_in_seconds
---------------

   $epoch_time = $shire_date->time_in_seconds

   Returns the epoch time (with 0 for hours, minutes, and seconds) of a
given shire date.   This relies on the library Time::Local, so the caveats
and error handling with that module apply to this method as well.

weekday
-------

   $day_of_week = $shiredate->weekday;

   This function returns the day of the week using the more modern names
in use during the War of the Ring and given in the Lord of the Rings
Appendix D.  If the day in question is not part of any week (Midyear day
and the Overlithe), then the null string is returned.

trad_weekday (for traditional weekday)
--------------------------------------

   $day_of_week = $shiredate->trad_weekday

   This function returns the day of the week using the archaic forms, the
oldest forms found in the Yellowskin of Tuckborough (also given in Appendix
D).  If the day in question is not part of any week (Midyear day and the
Overlithe), then the null string is returned.

month
-----

   $month = $shiredate->month;

   Returns the month of the date in question, or the null string if the
day is a holiday, since holidays are not part of any month.

day
---

   $day_of_month = $self->{monthday};

   returns the day of the month of the day in question, or 0 in the case of
a holiday, since they are not part of any month

holiday
-------

   $holiday = $shiredate->holiday;

   If the day in question is a holiday, returns a string which holiday it
is: "Yule 1", "Yule 2" (first day of the new year), "Lithe 1", "Midyear's
day", "Overlithe", or "Lithe 2".  If the day is not a holiday, the null
string is returned

year
----

   $shire_year = $shiredate->year;

   Returns the year of the shire date in question.  See the note on year
calculaton below if you want to see how I figured this.

Operators
---------

   The following comparison operators are available:     $shiredate1 <
$shiredate2     $shiredate1 lt $shiredate2     $shiredate1 <= $shiredate2
  $shiredate1 le $shiredate2     $shiredate1 >  $shiredate2
$shiredate1 gt $shiredate2     $shiredate1 >= $shiredate2     $shiredate1
ge $shiredate2     $shiredate1 == $shiredate2     $shiredate1 eq
$shiredate2     $shiredate1 != $shiredate2     $shiredate1 ne $shiredate2
  $shiredate1 <=> $shiredate2     $shiredate1 cmp $shiredate2

   You can only compare on shire date to another (no apples to oranges
here).  In this context both the numeric and string operators perform the
exact same function.  Like the standard operators, all but <=> and cmp
return 1 if the condition is true and the null string if it is false.  <=>
and cmp return -1 if the left operand is less than the right one, 0 if the
two operands are equal, and 1 if the left operand is greater than the
right one.

on_date
-------

   $historic_events = $shire_date->on_date

   or you may want to try something like my $shiredate =
Date::Tolkien::Shire->new(time); print "Today is " . $shiredate->on_date .
"\n";

   This method returns a string containing important events that happened
on this day and month in history, as well as the day itself.  It does not
give much more usefullness as far as using dates go, but it should be fun
to run during a startup script or something.  At present the events are
limited to the crucial years at the end of the third age when the final war
of the ring took place and Sauron was permanently defeated.  More dates
will be added as I find them (if I find them maybe I should say).  All the
ones below come from Appendix B of the Lord of the Rings.  At this point,
these are only available in English.

   Note here that the string is formatted.  This is to keep things simple
when using it as in the second example above.  Note that in this second
example you are actually ending with a double space, as the first endline
is part of the return value.

   If you don't like how this is formatted, complain at me and if I like
you I'll consider changing it :-)

NOTE: YEAR CALCULATION
======================

   http://www.glyhweb.com/arda/f/fourthage.html references a letter sent by
Tolkien in 1958 in which he estimates approxiimately 6000 years have passed
since the War of the Ring and the end of the Third Age.  (Thanks to Danny
O'Brien from sending me this link).  I took this approximate as an exact
and calculated back 6000 years from 1958 and set this as the start of the
4th age (1422).  Thus the fourth age begins in our B.C 4042.

   There is one issue that I have not finished yet with year calculation
and it may change in the future (and opinions on it are welcome, as
always).  According to Appendix D of the Lord of the Rings, leap years in
hobbit calendar are every 4 years unless its the turn of the century, in
which case it's not a leap year.  Our calendar uses every 4 years unless
it's 100 years unless its 400 years.  So, if no changes have been made to
the hobbit's calendar since the end of the third age, their calendar would
be about 15 days further behind ours now then when the War of the Ring took
place.  Implementing this seemed to me to go against Tolkien's general
habit of converting dates in the novel to our equivalents to give us a
better sense of time.  My thoughts, at least right now, is that it is
truer to the spirit of things for March 25 today to be about the same as
March 25 was back then.  So instead, I have modified Tolkien's description
of the hobbit calendar so that leap years occur once every 4 years unless
it's 100 years unless it's 400 years, so as it matches our calendar in that
regard.  These 100 and 400 year intervals occur at different times in the
two calendars, however.

   This final fact leads to the one known issue still in this module.
Currently, the logic used here only works for years between 1937 and 2035
(shire years 7401 to 7499).  This is due to the day offset at different
times (in 400 year cycles) between the leap years of the different
calendars.  The module still works for other dates and will provide valid
comparisons, but the day it gives will be slightly off from what is
actually the shire date unless you are between 1937 and 2035 (or 1537 and
1635, etc).  I am planning on fixing this, but that must take a back seat
for the moment to my college classes and more practical projects.

BIBLIOGRAPHY
============

   Tolkien, J. R. R. <i>Return of the King<i>.  New York: Houghton Mifflin
Press, 1955.  http://www.glyphweb.com/arda/f/fourthage.html

BUGS
====

   At present, does shire date reckoning is slightly off for years not
between 1937 and 2035 (shire reckoning 7401 to 7499).  See year
calculation for more information.

Perform common time and date operations with additional GPS operations
**********************************************************************

NAME
====

   DateTime::Precise - Perform common time and date operations with
additional GPS operations

SYNOPSIS
========

     use DateTime::Precise;

     use DateTime::Precise qw(:TimeVars);

     # Constructors and ways to set time.
     $t1 = DateTime::Precise->new;
     $t2 = DateTime::Precise->new('1998. 4. 3 12:13:44.054');
     $t3 = DateTime::Precise->new(time() - 100);
     $t4 = DateTime::Precise->new('1998.04.24');
     $t1->set_localtime_from_epoch_time;
     $t1->set_gmtime_from_epoch_time(time + 120);
     $t1->set_from_datetime('1998.03.23 16:58:14.65');
     $t1->set_time('YDHMS', 1998, 177, 9, 15, 26.5);

     # This is the same as $d3->set_from_datetime(...)
     $t3->dscanf("%^Y.%M.%D %h:%m:%s", "1998.03.25 20:25:23");
     if ($msg = $d1->dscanf("%~M", $input)) {
         print "error: $msg\n";
         print "Must enter a three-letter month abbrev.\n";
     }

     # Get different parts of the time.
     $year    = $t3->year;
     $month   = $t3->month;
     $day     = $t3->day;
     $hours   = $t3->hours;
     $minutes = $t3->minutes;
     $seconds = $t3->seconds;
     ($year, $day_of_year) = $t3->get_time('Yj');

     # Print times and dates.
     print $t2->asctime;
     print $t2->strftime('%T %C%n');
     print $t2->dprintf("%^Y.%M.%D %h:%m:%s");           # datetime
     print $t2->dprintf("%~w %~M %-D %h:%m:%s CST %^Y"); # ctime

     # Copy times.
     my $t4 = $t2->copy;

     # Set one time object to the same time as another: set $t3 equal to $t2.
     $t3->clone($t2);

     # Find the difference between two times.
     $secs_from_midnight = $t4 - $t1;
     $secs_from_midnight = $t4->diff($t1);

     # Add seconds, days, months, etc to time.
     $t1 = $t4 + 3600;                      # $t1 is now an hour after midnight
     $t1->inc_month(2);                     # add two months to $t1
     $t1->floor_month;                      # set $t1 to the first of the month

     # Can compare and sort DateTime::Precise.
     print "It's late!!!" if ($t1 > $t4);
     @sorted = sort @birthdays;             # normal comparisons work fine

     # Get the GPS weeks, seconds and day.
     $gps_week    = $t1->gps_week;
     $gps_seconds = $t1->gps_seconds;
     $gps_day     = $t1->gps_day;
     ($gps_week, $gps_seconds, $gps_day) = $t1->gps_week_seconds_day;

DESCRIPTION
===========

   The purpose of this library was to replace our dependence on Unix epoch
time, which, being limited to a range of about 1970 to 2030, is inadequate
for our purposes (we have data as old as 1870).  This date library
effectively handles dates from A.D. 1000 to infinity, and would probably
work all the way back to 0 (ignoring, of course, the switch-over to the
Gregorian calendar).  The useful features of Unix epoch time (ease of date
difference calculation and date comparison, strict ordering) are
preserved, and elements such as human-legibility are added.  The library
handles fractional seconds and some date/time manipulations used for the
Global Positioning Satellite system.

   The operators +/-, <=>, cmp, stringify are overloaded.  Addition
handles seconds and fractions of seconds, subtraction handles seconds or
date differences, compares work, and stringification returns the a
representation of the date.

   The US Geological Survey (USGS), likes midnight to be 24:00:00, not
00:00:00.  If $DateTime::Precise::USGSMidnight is set, dprintf will always
print midnight as 24:00:00.  Regardless, time is always stored internally
as 00:00:00.

CONSTRUCTOR
===========

new

new('1998. 4. 3 12:13:44')
new(time() - 100)
new('YDHMS', 1998, 200, 13, 16, 49.5)
     This creates a new time object.  If no argument is passed, then the
     time object is initialized with the time returned from gmtime
     (time()).  The second form is used to set the time explicitly.  The
     argument can be in one of three formats: "YYYY.MM.DD hh:mm:ss.ffff",
     "YYYY.MM.DD" (midnight assumed), or "YYYYMMDDhhmmss.ffff".  Here ffff
     are the fractions of seconds.  The third form sets the time using
     gmtime().  The fourth form sets the time using a format as the first
     argument followed by the particular date adjustments as the following
     arguments.  See set_time() for more information.  If the new fails,
     then new returns an empty list in a list context, an undefined value
     in a scalar context, or nothing in a void context.

     Because the second and third forms pass only one argument to new(),
     there must be a way of distinguishing them.  Currently the following
     test is used: if any non-digit characters are found in the argument or
     if the string form of the argument is longer than 10 character, then
     assume it to be a string to parse for the date.  Otherwise it is the
     time since the Unix epoch.  The string length of 10 was chosen since
     when the Unix epoch time flips to 11 digits, it'll be roughly year
     2287.

METHODS
=======

set_from_datetime *datetime*
     Set date/time from passed date/time string "YYYY.MM.DD hh:mm:ss.fff".
     If set_from_datetime successfully parses *datetime*, then the newly
     set date/time object is returned, otherwise it returns an empty list
     in a list context, an undefined value in a scalar context, or nothing
     in a void context.

set_localtime_from_epoch_time [*epoch*]
     Set from epoch time into the local time zone.  If *epoch* is passed,
     then use that time to set the current time, otherwise use the time as
     returned from time().  The newly set date/time object is returned.

set_gmtime_from_epoch_time [*epoch*]
     Set from the epoch time into the standard Greenwich time zone.  If
     *epoch* is passed, then use that time to set the current time,
     otherwise use the time as returned from time().  The newly set
     date/time object is returned.

set_from_day_of_year year day_of_year
     Set date/from from the year and the decimal day of the year.  Midnight
     January 1st is day 1, noon January 1st is 1.5, etc.  If the date was
     successfully set, then the newly set date/time object is returned,
     otherwise it returns an empty list in a list context, an undefined
     value in a scalar context, or nothing in a void context.

set_from_serial_day *serial_day_number*
     Set the date/time from the serial day.  See also serial_day().  If the
     date was successfully set, then the newly set date/time object is
     returned, otherwise is returns an empty list in a list context, an
     undefined value in a scalar context, or nothing in a void context.

set_from_gps_week_seconds gps_week gps_seconds
     Set the current time using the number of weeks and seconds into the
     week since GPS epoch (January 6, 1980 UTC).  If the date was
     successfully set, then the newly set date/time object is returned,
     otherwise is returns an empty list in a list context, an undefined
     value in a scalar context, or nothing in a void context.

set_time format [*arg*, [*arg*, ...]]
     Set the time.  format is a string composed of a select set of
     characters.  Some characters may take an optional argument, which are
     listed following the format argument in the same order as the
     characters.  The first character must be an absolute time:

          N => Set time to now.  No argument taken.
          G => Set time to GPS time 0 (January 6, 1980).  No argument taken.
          Y => Set time to beginning of the year.  Argument taken.
          J => Set time to modified Julian date.  Argument taken.
          s => Set time to seconds since January 1, 1970.  Argument taken.

     These characters represent modifiers to the time set using the above
     characters:

          B => Add months to time.  Argument taken.
          W => Add weeks to time.  Argument taken.
          D => Add days counted from 1 to time.  Argument taken.
          d => Add days counted from 0 to time.  Argument taken.
          H => Add hours to time.  Argument taken.
          M => Add minutes to time.  Argument taken.
          S => Add seconds to time.  Argument taken.

     If the date and time was successfully set, then it returns the newly
     set date/time object, otherwise set_time() returns an empty list in a
     list context, an undefined value in a scalar context, or nothing in a
     void context and the date and time remain unchanged.

get_time string
     Return an array, where each element of the array corresponds to the
     corresponding strftime() value.  This string should not contain %
     characters.  This method is a much, much better and faster way of
     doing

          map {$self->strftime("%$_")} split(//, $string)

year [year]
     Return the year.  If an argument is passed to year, then set the year
     to the the integer part of the argument and then return the newly set
     year.

month [month]
     Return the numerical month (1 = January, 12 = December).  If an
     argument is passed to month, then set the month to the integer part
     of the argument and return the newly set month.

day [day]
     Return the day of the month.  If an argument is passed to day, then
     set the day to the integer part of the argument and return the newly
     set day.

hours [hours]
     Return the hours in the day.  If an argument is passed to hours, then
     set the hours to the integer part of the argument and return the
     newly set hours.

minutes [minutes]
     Return the minutes in the hour.  If an argument is passed to minutes,
     then set the minutes to the integer part of the argument and return
     the newly set minutes.

seconds [seconds]
     Return the seconds in the minutes.  If an argument is passed to
     seconds, then set the seconds to the argument and return the newly
     set seconds.  This argument accepts fractional seconds and will return
     the fractional seconds.

serial_day
     Returns a serial day number representing the date, plus a fraction
     representing the time since midnight (i.e., noon=0.5).  This is for
     applications which need an scale index (we use it for positioning a
     date on a time-series graph axis).  See also set_from_serial_day().

day_of_year
     Return the day of the year including the fraction part of the day.
     Midnight January 1st is day 1, noon January 1st is 1.5, etc.

julian_day
     Return the day of the year including the fraction part of the day
     where time is 0 based.  Midnight January 1st is day 0, noon January
     1st is 0.5, noon January 2nd is 1.5, etc.

unix_seconds_since_epoch
     Return the time in seconds between the object and January 1, 1970 UTC.

gps_seconds_since_epoch
     Return the time in seconds between the object and January 6, 1980 UTC.

gps_week_seconds_day
     Return an array consisting of the GPS week 0 filled to four spaces,
     the number of seconds into the GPS week, and the GPS day, where day 0
     is Sunday.

gps_week
     Return the GPS week of the object.  The returned number is 0 filled to
     four digits.

gps_seconds
     Return the number of seconds into the current GPS week for the current
     object.

gps_day
     Return the GPS day of the week for the current object, where day 0 is
     Sunday.

copy
     Return an identical copy of the current object.

clone *other_dt*      Set this DateTime::Precise equal to *other_dt*.
dprintf string      Returns string with substitutions:          %x     number zero-padded to 2 digits (ie, '02')     %-x number space-padded to 2 digits (ie, ' 2')     %^x    unpadded number (ie, '2')     %~x    3-letter abbrev corresponding to value (%M and %w only)     %*x    full name corresponding to value (%M and %w only)     %%     '%'
     where x is one of:

     h      hours (0..23)     m      minutes (0..59)     s      seconds
     (0..59)     D      day of the month (1..31)     M      month (1..12)
       Y      years since 1900 (ie, 96)     W      USGS water year
     (year+1 for months Oct-Dec)     w      day of the week (0..6, or
     "Mon", etc.)      E      internal string (no ~^*-)

     so, for example, to get a string in datetime format, you would pass a
     string of '%^Y.%M.%D %h:%m:%s', or, to get a ctime-like string, you
     would pass: `'%~w %~M %-D %h:%m:%s CDT %^Y'' (presuming you're in the
     CDT.  Maybe timezone support will show up some day).

dscanf format string
     Takes a format string format, and use it to read the date and time
     fields from the supplied string.  The current date and time is
     unchanged if dscanf fails.

     All format characters recognized by dprintf() are valid.  Two
     additional characters are recognized, 'U' which sets the time to the
     local time/date using the number of seconds since Unix epoch time and
     'u' which sets the time to GMT time/date using the number of seconds
     since Unix epoch time.  Unless exact characters are supplied or format
     characters are concatenated, will separate on non-matching characters.

strftime format
     Just like the strftime() function call.  This version is based on the
     Solaris manual page.  format is a string containing of zero or more
     conversion specifications.  A specification character consists of a
     '%' (percent) character followed by one conversion characters that
     determine the conversion specifications behavior.  All ordinary
     characters are copied unchanged to the return string.

     The following GPS specific conversions are supported in this strftime:
        %s    the seconds since UTC January 1, 1970     %G    the GPS
     week (4 digits with leading 0's)     %g    the GPS seconds into the
     GPS week with no leading zeros     %f    the GPS day where 0 =
     Sunday, 1 = Monday, etc     %F    the GPS day where 1 = Sunday, 2 =
     Monday, etc

     The following standard conversions are understood:

          %%    the same as %
          %a    the abbreviated weekday name
          %A    the full weekday name
          %b    the abbreviated month name
          %B    the full month name
          %c    the appropriate date and time representation
          %C    century number (the year divided by 100 and truncated to an
                integer as a decimal number [1,99]); single digits are
                preceded by 0
          %d    day of month [1,31]; single digits are preceded by 0
          %D    date as %m/%d/%y
          %e    day of month [1,31]; single digits are preceded by a space
          %h    locale's abbreviated month name
          %H    hour (24-hour clock) [0,23]; single digits are preceded by 0
          %I    hour (12-hour clock) [1,12]; single digits are preceded by 0
          %j    day number of year [1,366]; single digits are preceded by 0
          %k    hour (24-hour clock) [0,23]; single digits are preceded by
                a blank
          %l    hour (12-hour clock) [1,12]; single digits are preceded by
                a blank
          %m    month number [1,12]; single digits are preceded by 0
          %M    minute [00,59]; leading zero is permitted but not required
          %n    insert a newline
          %p    either AM or PM
          %r    appropriate time representation in 12-hour clock format with
                %p
          %R    time as %H:%M
          %S    seconds [00,61]
          %t    insert a tab
          %T    time as %H:%M:%S
          %u    weekday as a decimal number [1,7], with 1 representing Sunday
          %U    week number of year as a decimal number [00,53], with Sunday
                as the first day of week 1
          %V    week number of the year as a decimal number [01,53], with
                Monday as the first day of the week. If the week containing 1
                January has four or more days in the new year, then it is
                considered week 1; otherwise, it is week 53 of the previous
                year, and the next week is week 1.
          %w    weekday as a decimal number [0,6], with 0 representing Sunday
          %W    week number of year as a decimal number [00,53], with Monday
                as the first day of week 1
          %x    locale's appropriate date representation
          %X    locale's appropriate time representation
          %y    year within century [00,99]
          %Y    year, including the century (for example 1993)
          %Z    Always GMT

asctime
     Return a string such as 'Fri Apr 3 12:13:44 GMT 1998'.  This is
     equivalent to strftime('%c').

Incrementing and rounding
-------------------------

   There are many subroutines of the format 'func_unit', where func is one
of (inc, dec, floor, ceil, round) and unit is one of (second, minute,
hour, day, month, year) [second and minute can be abbreviated as sec and
min respectively].

   *inc_unit*(i) increments the date by i units (i defaults to 1 if no
parameter is supplied).  For days through seconds, fractional increments
are allowed.  However, for months and years, only the integer part of the
increment is used.

   *dec_unit*(i) identical to *inc_unit*(-i).

   *round_unit*() rounds the date to the nearest unit.  Rounds years down
for Jan-Jun, and up for Jul-Dec; months down for 1st-15th and up for 16th
and later; days round up on or after 12:00:00; hours on or after xx:30:00,
minutes on or after 30 seconds; seconds on or after 0.5 seconds.

   *floor_unit*() rounds the date down to the earliest time for the
current unit.  For example, *floor_month*() rounds to midnight of the
first day of the current month, floor_day() to midnight of the current
day, and *floor_hour*() to xx:00:00.

   *ceil_unit*() is the complementary function to floor.  It rounds the
date up, to the earliest time in the next unit.  E.g., *ceil_month*()
makes the date midnight of the first day of the next month.

Overloaded operators
--------------------

   Addition, subtraction, and comparison operators are overloaded, as well
as the string representation of a date object.

     # create a new object
     $x = DateTime::Precise->new('1996.05.05 05:05:05');
     # copy it
     $y = $x;
     # increment x by one second
     $x++;
     # decrement by a day
     $y = $y - 86400;
     # test em
     print ($x < $y ? "x is earlier\n" : "y is earlier\n");
     # get the difference
     print "The difference between x and y is ", $x-$y, " seconds.\n";

   If $x is a date object, `$x + $i' is identical to $x->inc_sec($i).

   There are two possible results from subtraction.  `$x - $i', where $i
is a number, will return a new date, $i seconds before $x. `$x - $y',
where $y is another date object, is identical to $x->diff($y).

   Comparison operators (<,>,==,etc) work as one would expect.

PUBLIC CONSTANTS
================

   The following variables are not imported into your package by default.
If you want to use them, then use

     use DateTime::Precise qw(:TimeVars);

   in your package.  Otherwise, you can use the fully qualified package
name, such as $DateTime::Precise::USGSMidnight.

$USGSMidnight
     Set this to 1 if you want midnight represented as 24:00:00 of the
     previous day.  To use this variable in your

*@MonthDays*
     Days per month in a non-leap year.  This array is 1 indexed, so 0 is
     December, 1 is January, etc.

*@MonthName*
     Month names.  This array is 1 indexed, so 0 is December, 1 is January,
     etc.

*@MonthAbbrev*
     Month abbreviated names.  This array is 1indexed, so 0 is Dec, 1 is
     Jan, etc.

*@WeekName*
     Names of the week, 0 indexed.  So 0 is Sunday, 1 is Monday, etc.

*@WeekAbbrev*
     Abbreviated names of the week, 0 indexed.  So 0 is Sun, 1 is Mon, etc.

$Secs_per_week
     The number of seconds in one week (604800).

$Secs_per_day
     The number of seconds in one day (86400).

$Secs_per_hour
     The number of seconds in one hour (3600).

$Secs_per_minute
     The number of seconds in one minute (60).

&JANUARY_1_1970
     Subroutine returning the Unix epoch time January 1, 1970 UTC.

&JANUARY_6_1980
     Subroutine returning the GPS epoch time January 6, 1980 UTC.

PUBLIC SUBROUTINES
==================

*IsLeapYear*(year)
     Returns true if the argument is a leap year.

*DaysInMonth*(month, year)
     Returns the number of days in the month.

IMPLEMENTATION
==============

   This package is based on the DateTime package written by Greg Fast
<gdfast@usgs.gov>.  The _week_of_year routine is based on the
Date_WeekOfYear routine from the Date::DateManip package written by
Sullivan Beck.

   Instead of using the string representation used in the original
DateTime package, this package represents the time internally as a seven
element array, where the elements correspond to the year, month, day,
hours, minutes, seconds, and fractional seconds.

AUTHOR
======

   Contact: Blair Zajac <blair@gps.caltech.edu>.  The original version of
this was was based on DateTime written by Greg Fast <gdfast@usgs.gov>.

Perl extension to interface with Faircom's CTREE product
********************************************************

NAME
====

   Db::Ctree - Perl extension to interface with Faircom's CTREE product

SYNOPSIS
========

     use Db::Ctree qw(:all);

     InitISAM(10,2,4);
     $ptr = Db::Ctree -> new(0,'file.dat',&SHARED);
     $record = $ptr -> fetch_first();
     while ($record)
     {
        print $record."\n";
        $record = $ptr -> fetch_next();
     }

DESCRIPTION
===========

   This module allows the use of some ISAM and Low-Level CTREE routines
from within perl.  It is a PERL5 replacement for CTREEPERL by John Conover.

   In addition to base CTREE functionality, the ability to tie a hash to a
CTREE table, and some method based access is available.

Base CTREE support.
===================

   Support is provided for most low-level and ISAM routines as documented
in the Faircom documentation.  Those routines that use C structures
(resource records, DODA) are not currently supported. A routine that reads
DODA records is available in the METHOD access method.

   Like in C it is very important to pre-allocate the destination on reads.
Db::CTree just calls the Ctree routine... you *WILL* crash perl just as
fast as you crash C without preallocating enough space.

Error code functions
====================

   With C, error status is available via global variables.  Db::Ctree
provides functions that access the following global "C" variables.

     &isam_err
     &isam_fil
     &sysiocod
     &uerr_cod

Perl hash TIE support
=====================

   A limited Perl hash TIE implementation is available.  If the file has
been created by a C program, includes resource records, and uses unique
keys, it can be TIED to a Perl hash.  Unique keys are required because the
tie uses the GetRecord facility which requires Unique keys.

   TIE returns a pointer you can use for method access.

   Preallocating of space is not required for TIE support.

   The file is automatically closed when the hash (and ptr returned by
TIE) is destroyed or reassigned.

   Sample Code:    InitISAM(10,2,4);    tie %hash, "Db::Ctree",2,
$testIfile,&SHARED;    foreach (keys (%hash) )    {        printf
"%-10s=%s\n",$_,$hash{$_};    }

Perl METHOD support
===================

   A limited Perl method access is provided. The following methods are
available.  In case of error, most functions will return undef. For
details, use the error function defined above.

   These functions ensure enough space is available for the CTREE return
values.  There is no need to preallocate the space.  Variable/Fixed
functions are also selected for you.

   new (fileno,filename,mode)         returns an object reference to the
open file.

   fetch_first()         returns the first record based on the current
index.

   fetch_gte {$key)         note:  key modified with current key
returns the record just like getGTErecord

   fetch_lte {$key)         note:  key modified with current key
returns the record just like getGTErecord

   fetch_prev {)         returns the record just like getGTErecord

   fetch_next {)         returns the record just like getGTErecord

   unpack_record($record)         note: DODA must be stored in file
returns hash with fields as keys

   Sample Code:    InitISAM(10,2,4);    $dbptr = Db::Ctree -> new(2,
$testIfile,&SHARED);    $record = $dbptr -> fetch_first;    while ($record)
  {        %hash = $dbptr -> unpack_record($record);        print
"$hash{COLUMN}\n";        $record = $dbptr -> fetch_next;    }

Notes
=====

   ISAM and LOW LEVEL calls do not preallocate space (like C). Be sure
your variables are big enough! (Method and HASH access do this for you)

   InitISAM sets a tag variable in a class with a DESTROY method that
should issue a StopUser upon a normal Perl exit (including Die's).  This
prevents leaving shared memory segments around in server based systems.
If you coredump (die without Perl cleaning up), these memory segments can
be left around and eventually crash your server!

   Ctree functions are not exported by default. EXPORTER tags are
available for ALL,ISAM,LOWLEVEL,CONSTANTS and VARIABLES. Personally, I
just import tag ":all" and live with the namespace pollution.

   I've also included ctdump and ctload.  These are some simple ctree perl
routines I've written to dump and load tables. (The tables were created by
a C program and have resource and DODA structures already.)

Author
======

   Robert Eden CommTech Corporation rmeden@yahoo.com

SEE ALSO
========

   perl(1), Faircom C-Tree Plus Function Reference Guide, Faircom C-Tree
Plus Programmer's Guide =cut

Perl's Object-oriented interface to Documentum's DFC
****************************************************

NAME
====

   Db::DFC - Perl's Object-oriented interface to Documentum's DFC

SYNOPSIS
========

     use Db::DFC;
     $dfc = Db::DFC->new();

     $DOCBASE = "docbase";
     $USER = "user";
     $PASSWORD = "passwd";
     $DOMAIN = "domain";
     $FILE = $0;

     $dfclient = DfClient->new();
     $idfclient = $dfclient->getLocalClient();
     $idflogininfo = DfLoginInfo->new();

     $idflogininfo->setUser($USER);
     $idflogininfo->setPassword($PASSWORD);
     $idflogininfo->setDomain($DOMAIN);

     $idfsession = $idfclient->newSession($DOCBASE,$idflogininfo);

     $pobj = $idfsession->newObject("dm_document");
     $doc = $dfc->castToIDfDocument($pobj);

     $doc->setObjectName("this file");
     $doc->setContentType("crtext");
     $doc->setFile($FILE);
     $doc->save();

     print "\nDocument Id:" . $doc->getObjectId()->toString() . " created.\n";
     $idfsession->disconnect;

DESCRIPTION
===========

     Db::DFC provides an object-oriented interface to Documentum's DFC.
     ...

AUTHOR
======

     m. Scott Roth, michael.s.roth@saic.com

SEE ALSO
========

   perl(1).

Attribute class
***************

NAME
====

   DbFramework::Attribute - Attribute class

SYNOPSIS
========

     use DbFramework::Attribute;
     my $a = new DbFramework::Attribute($name,$default_value,$is_optional,$data_type);
     $name  = $a->name($name);
     $value = $a->default_value($value);
     $opt   = $a->is_optional($boolean);
     $type  = $a->references($data_type);
     $bgc   = $a->bgcolor($bgcolor);
     $sql   = $a->as_sql;
     $s     = $a->as_string;
     $html  = $a->as_html_form_field($value,$type);
     $html  = $a->as_html_heading($bgcolor);

DESCRIPTION
===========

   A *DbFramework::Attribute* object represents an attribute (column) in a
table (entity).

SUPERCLASSES
============

   *DbFramework::Util*

CLASS METHODS
=============

new($name,$default_value,$is_optional,$data_type)
-------------------------------------------------

   Create a new *DbFramework::Attribute* object.  $name is the name of the
attribute.  *$default_value* is the default value for the attribute.
*$is_optional* should be set to true if the attribute is optional or
false.  $data_type is a *DbFramework::DataType* object.

name($name)
-----------

   If $name is supplied sets the attribute name.  Returns the attribute
name.

default_value($value)
---------------------

   If $value is supplied sets the default value for the attribute.  $value
should be compatible with the the data type set by references().  Returns
the default value for the attribute.

is_optional($boolean)
---------------------

   If $boolean is supplied sets the optionality of the attribute (i.e.
whether it can contain NULLs.)  $boolean should evaluate to true or false.
Returns the optionality of the attribute.

references($data_type)
----------------------

   If $data_type is supplied sets the data type of the attribute.
$data_type is an ANSII data type object i.e.
*DbFramework::DataType::ANSII* or a driver-specific object e.g.
*DbFramework::DataType::Mysql*.  Returns the data type object.

bgcolor($bgcolor)
-----------------

   If $color is supplied sets the background colour for HTML table
headings returned by as_html_heading().  Returns the current background
colour.

as_sql($dbh)
------------

   Returns a string which can be used to create a column in an SQL 'CREATE
TABLE' statement.  $dbh is a DBI handle.

as_html_form_field($value,$type)
--------------------------------

   Returns an HTML form field representation of the attribute.  The HTML
field type produced depends on the name of object returned by data_type().
This can be overidden by setting $type.  $value is the default value to
be entered in the generated field.

as_string()
-----------

   Return attribute details as a text string.

as_html_heading($bgcolor)
-------------------------

   Returns a string for use as a column heading cell in an HTML table.
$bgcolor is the background colour to use for the heading.

SEE ALSO
========

   See DbFramework/DataType/ANSII, and
DbFramework/DataType/Mysql.

AUTHOR
======

   Paul Sharpe <paul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1997,1998,1999 Paul Sharpe. England.  All rights
reserved.  This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

Catalog class
*************

NAME
====

   DbFramework::Catalog - Catalog class

SYNOPSIS
========

     use DbFramework::Catalog;
     my $c = new DbFramework::Catalog($dsn,$user,$password);
     $c->set_primary_key($table);
     $c->set_keys($table);
     $c->set_foreign_keys($dm);

DESCRIPTION
===========

   *DbFramework::Catalog* is a class for manipulating the catalog database
used by various DbFramework modules and scripts.

The Catalog
-----------

   DbFramework retrieves as much metadata as possible using DBI.  It aims
to store the metadata not provided by DBI in a consistent manner across
all DBI drivers by using a catalog database called *dbframework_catalog*.
Each database you use with DbFramework requires corresponding key
information added to the catalog.  The *dbframework_catalog* database will
be created for each driver you test when you build DbFramework.  Entries
in the catalog only need to be modified when the corresponding database
schema changes.

   The following (Mysql) SQL creates the catalog database schema.

     CREATE TABLE c_db (
       	  db_name varchar(50) DEFAULT '' NOT NULL,
       	  PRIMARY KEY (db_name)
     );

     CREATE TABLE c_key (
       db_name varchar(50) DEFAULT '' NOT NULL,
       table_name varchar(50) DEFAULT '' NOT NULL,
       key_name varchar(50) DEFAULT '' NOT NULL,
       key_type int(11) DEFAULT '0' NOT NULL,
       key_columns varchar(255) DEFAULT '' NOT NULL,
       PRIMARY KEY (db_name,table_name,key_name)
     );

     CREATE TABLE c_relationship (
       db_name varchar(50) DEFAULT '' NOT NULL,
       fk_table varchar(50) DEFAULT '' NOT NULL,
       fk_key varchar(50) DEFAULT '' NOT NULL,
       pk_table varchar(50) DEFAULT '' NOT NULL,
       PRIMARY KEY (db_name,fk_table,fk_key,pk_table)
     );

     CREATE TABLE c_table (
       table_name varchar(50) DEFAULT '' NOT NULL,
       db_name varchar(50) DEFAULT '' NOT NULL,
       PRIMARY KEY (table_name,db_name)
     );

   The example below shows the creation of a simple Mysql database and the
corresponding catalog entries required by DbFramework.

     CREATE DATABASE foo;
             use foo;

     CREATE TABLE foo (
       	  foo integer not null,
       bar varchar(50),
       KEY var(bar),
       	  PRIMARY KEY (foo)
     );

     CREATE TABLE bar (
       	  bar integer not null,
       # foreign key to table foo
       foo integer not null,
       	  PRIMARY KEY (bar)
     );

     use dbframework_catalog;

     # catalog entry for database 'foo'
     INSERT INTO c_db VALUES('foo');

     # catalog entries for table 'foo'
     INSERT INTO c_table VALUES('foo','foo');
     # primary key type = 0
     INSERT INTO c_key VALUES('foo','foo','primary',0,'foo');
     # index type = 2
     INSERT INTO c_key VALUES('foo','foo','bar_index',2,'bar');

     # catalog entries for table 'bar'
     INSERT INTO c_table VALUES('bar','foo');
     # primary key type = 0
     INSERT INTO c_key VALUES('foo','bar','primary',0,'bar');
     # foreign key type = 1
     INSERT INTO c_key VALUES('foo','bar','foreign_foo',2,'foo');
     # relationship between 'bar' and 'foo'
     INSERT INTO c_relationship VALUES('foo','bar','foreign_foo','foo');

SUPERCLASSES
============

   *DbFramework::Util*

CLASS METHODS
=============

new($dsn,$user,$password)
-------------------------

   Create a new *DbFramework::Catalog* object.  *$dsn* is the DBI data
source name containing the catalog database (default is
'dbframework_catalog').  *$user* and $password are optional arguments
specifying the username and password to use when connecting to the
database.

OBJECT METHODS
==============

set_primary_key($table)
-----------------------

   Set the primary key for the *DbFramework::Table* object *$table*.

set_keys($table)
----------------

   Set the keys (indexes) for the *DbFramework::Table* object *$table*.

set_foreign_keys($dm)
---------------------

   Set the foreign keys for the *DbFramework::DataModel* object *$dm*.

AUTHOR
======

   Paul Sharpe <paul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1999 Paul Sharpe. England.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Data Model class
****************

NAME
====

   DbFramework::DataModel - Data Model class

SYNOPSIS
========

     use DbFramework::DataModel;
     $dm = new DbFramework::DataModel($name,$dsn,$user,$password);
     $dm->init_db_metadata;
     @tables = @{$dm->collects_table_l};
     %tables = %{$dm->collects_table_h};
     @tables = @{$dm->collects_table_h_byname(@tables)};
     $sql    = $dm->as_sql;
     $db     = $dm->db;
     $driver = $dm->driver;

DESCRIPTION
===========

   A *DbFramework::DataModel* object represents a database schema.  It can
be initialised using the metadata provided by a DBI driver and a catalog
database (see DbFramework/Catalog).

SUPERCLASSES
============

   *DbFramework::Util*

CLASS METHODS
=============

new($name,$dsn,$user,$password)
-------------------------------

   Create a new *DbFramework::DataModel* object called $name.  *$dsn* is
the DBI data source name associated with the data model.  *$user* and
$password are optional arguments specifying the username and password to
use when connecting to the database.

OBJECT METHODS
==============

   A data model has a number of tables.  These tables can be accessed
using the methods *COLLECTS_TABLE_L* and *COLLECTS_TABLE_H*.  See
`AUTOLOAD()', see DbFramework/Util, for the accessor
methods for these attributes.

name($name)
-----------

   If $name is supplied sets the data model name.  Returns the data model
name.

db()
----

   Returns the name of the database associated with the data model.

driver()
--------

   Returns the name of the driver associated with the data model.

as_sql()
--------

   Returns a SQL string which can be used to create the tables which make
up the data model.

init_db_metadata()
------------------

   Returns a *DbFramework::DataModel* object configured using metadata
from the database handle returned by dbh() and the catalog (see
DbFramework/Catalog).  Foreign keys will be
automatically configured for tables in the data model but this method will
die() unless the number of attributes in each foreign and related primary
key match.

SEE ALSO
========

   See DbFramework/Catalog,
DbFramework/Table, and DbFramework/Util.

AUTHOR
======

   Paul Sharpe <paul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1997,1998 Paul Sharpe. England.  All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

ACKNOWLEDGEMENTS
================

   This module was inspired by *Msql::RDBMS*.

DataModelObject class
*********************

NAME
====

   DbFramework::DataModelObject - DataModelObject class

SYNOPSIS
========

     use DbFramework::DataModelObject;

DESCRIPTION
===========

   Abstract class for CDIF Data Model objects.

SUPERCLASSES
============

   *DbFramework::Util*

AUTHOR
======

   Paul Sharpe <paul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1998 Paul Sharpe. England.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Data type class
***************

NAME
====

   DbFramework::DataType - Data type class

SYNOPSIS
========

     use DbFramework::DataType;
     my $dt = new DbFramework::DataType($name,$length,$extra);
     $dt->name($name);
     $dt->length($length);
     $dt->extra($extra);

DESCRIPTION
===========

   A *DbFramework::DataType* object represents a data type associated with
a *DbFramework::Attribute* object.

SUPERCLASSES
============

   *DbFramework::DefinitionObject*

CLASS METHODS
=============

new($name,$length,$extra)
-------------------------

   Create a new *DbFramework::DataType* object.  $name is the name of the
data type.  $length is the length of the data type.  *$extra* is any extra
information which applies to the data type e.g. *AUTO_INCREMENT* in they
case of a Mysql INTEGER data type.

name($name)
-----------

   If $name is supplied, sets the name of the data type.  Valid data types
are *CHAR DATE DATETIME INT INTEGER TEXT TIMESTAMP VARCHAR*.  Returns the
name of the data type.

length($length)
---------------

   If $length is supplied, sets the length of the data type.  Returns the
length of the data type.

extra($extra)
-------------

   If *$extra* is supplied, sets any extra information which applies to
the data type e.g. *AUTO_INCREMENT* in they case of a Mysql INTEGER data
type.  Returns the extra information which applies to the data type.

SEE ALSO
========

   See DbFramework/DefinitionObject,

AUTHOR
======

   Paul Sharpe <paul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1998 Paul Sharpe. England.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

ANSII data type class
*********************

NAME
====

   DbFramework::DataType::ANSII - ANSII data type class

SYNOPSIS
========

     use DbFramework::DataType::ANSII;
     $dt     = new DbFramework::DataType::ANSII($dbh,$type,$length);
     $name   = $dt->name($name);
     $type   = $type($type);
     $length = $dt->length($length);
     $extra  = $dt->extra($extra);

DESCRIPTION
===========

   A *DbFramework::DataType::ANSII* object represents an ANSII data type.

SUPERCLASSES
============

   *DbFramework::DefinitionObject*

CLASS METHODS
=============

new($dbh,$type,$length)
-----------------------

   Create a new *DbFramework::DataType* object.  $dbh is a DBI database
handle.  $type is a numeric ANSII type e.g. a type containd in the array
reference returned by $sth->{TYPE}.  This method will die() unless $type
is a member of the set of ANSII types returned by $dbh.  $length is the
length of the data type.

name($name)
-----------

   If $name is supplied, sets the name of the ANSII data type.  Returns
the name of the data type.

type($type)
-----------

   If $type is supplied, sets the number of the ANSII data type.  Returns
the numeric data type.

length($length)
---------------

   If $length is supplied, sets the length of the data type.  Returns the
length of the data type.

extra($extra)
-------------

   If *$extra* is supplied, sets any extra information which applies to
the data type e.g. *AUTO_INCREMENT*.  Returns the extra information which
applies to the data type.

SEE ALSO
========

   See DbFramework/DefinitionObject,

AUTHOR
======

   Paul Sharpe <paul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1999 Paul Sharpe. England.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Mysql data type class
*********************

NAME
====

   DbFramework::DataType::Mysql - Mysql data type class

SYNOPSIS
========

     use DbFramework::DataType::Mysql;
     $dt     = new DbFramework::DataType::ANSII($dbh,$type,$length);
     $name   = $dt->name($name);
     $type   = $dt->type($type);
     $length = $dt->length($length);
     $extra  = $dt->extra($extra);

DESCRIPTION
===========

   A *DbFramework::DataType::Mysql* object represents a Mysql data type.

SUPERCLASSES
============

   *DbFramework::DefinitionObject*

CLASS METHODS
=============

new($dbh,$type,$length,$extra)
------------------------------

   Create a new *DbFramework::DataType* object.  $dbh is a DBI database
handle.  $type is a numeric Mysql type e.g. a type containd in the array
reference returned by $sth->{mysql_type}.  This method will die() unless
$type is a member of the set of Mysql types returned by $dbh.  $length is
the length of the data type.  *$extra* is any extra stuff which applies to
the type e.g. 'AUTO_INCREMENT'.

name($name)
-----------

   If $name is supplied sets the name of the Mysql data type.  Returns the
name of the data type.

type($type)
-----------

   If $type is supplied sets the number of the Mysql data type.  Returns
the numeric data type.

length($length)
---------------

   If $length is supplied sets the length of the data type.  Returns the
length of the data type.

extra($extra)
-------------

   If *$extra* is supplied sets any extra information which applies to the
data type e.g. *AUTO_INCREMENT* in they case of a Mysql INTEGER data type.
Returns the extra information which applies to the data type.

SEE ALSO
========

   See DbFramework/DefinitionObject,

AUTHOR
======

   Paul Sharpe <paul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1999 Paul Sharpe. England.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

DefinitionObject class
**********************

NAME
====

   DbFramework::DefinitionObject - DefinitionObject class

SYNOPSIS
========

     use DbFramework::DefinitionObject;

DESCRIPTION
===========

   Abstract class for CDIF Definition Object objects.

SUPERCLASSES
============

   *DbFramework::Util*

OBJECT METHODS
==============

   A definition object contains 0 or more *DbFramework::Attribute*
objects.  These objects can be accessed using the attributes *CONTAINS_L*
and *CONTAINS_H*.  See `AUTOLOAD()', see DbFramework/Util,
for the accessor methods for these attributes.

SEE ALSO
========

   See DbFramework/Util,

AUTHOR
======

   Paul Sharpe <paul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1998 Paul Sharpe. England.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Foreign Key class
*****************

NAME
====

   DbFramework::ForeignKey - Foreign Key class

SYNOPSIS
========

     use DbFramework::ForeignKey;
     $fk   = new DbFramework::ForeignKey($name,\@attributes,$primary);
     $pk   = $fk->references($primary);
     $sql  = $fk->as_sql;
     $html = $fk->as_html_form_field(\%values);

DESCRIPTION
===========

   The *DbFramework::ForeignKey* class implements foreign keys for a table.

SUPERCLASSES
============

   *DbFramework::Key*

CLASS METHODS
=============

new($name,\@attributes,$primary)
--------------------------------

   Returns a new *DbFramework::ForeignKey* object.

   $name is the name of the foreign key.  *@attributes* is a list of
*DbFramework::Attribute* objects from a single *DbFramework::Table* object
which make up the key.  *$primary* is the *DbFramework::Primary* object
which the foreign key references.

OBJECT METHODS
==============

references($primary)
--------------------

   *$primary* should be a *DbFramework::PrimaryKey* object.  If supplied
it sets the primary key referenced by this foreign key.  Returns the
*DbFramework::PrimaryKey* object referenced by this foreign key.

as_html_form_field(\%values)
----------------------------

   Returns an HTML selection box containing values and labels from the
primary key columns in the related table. *%values* is a hash whose keys
are the attribute names of the foreign key and whose values indicate the
item in the selection box which should be selected by default.  See
`html_select_field()', see DbFramework/PrimaryKey.

SEE ALSO
========

   See DbFramework/Key, DbFramework/PrimaryKey,
and DbFramework/Catalog.

AUTHOR
======

   Paul Sharpe <paul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1997,1998,1999 Paul Sharpe. England.  All rights
reserved.  This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

Key class
*********

NAME
====

   DbFramework::Key - Key class

SYNOPSIS
========

     use DbFramework::Key;
     $k = new DbFramework::Key($name,\@attributes);
     $name  = $k->name($name);
     @a     = @{$k->incorporates_l(\@attributes)};
     @names = $k->attribute_names;
     $sql   = $k->as_sql;
     $table = $k->belongs_to($table);
     $html  = $k->as_html_heading;

DESCRIPTION
===========

   The *DbFramework::Key* class implements keys (indexes) for a table.

SUPERCLASSES
============

   *DbFramework::Util*

CLASS METHODS
=============

new($name,\@attributes)
-----------------------

   Create a new *DbFramework::Key* object.  $name is the name of the key.
*@attributes* is a list of *DbFramework::Attribute* objects from a single
*DbFramework::Table* object which make up the key.

OBJECT METHODS
==============

   A key incorporates 0 or more attributes.  These attributes can be
accessed using the attribute *INCORPORATES_L*.  See `AUTOLOAD()', see
DbFramework/Util, for the accessor methods for this
attribute.

name($name)
-----------

   If $name is supplied sets the data model name.  Returns the data model
name.

belongs_to($table)
------------------

   *$table* is a *DbFramework::Table* object.  If supplied sets the table
to which this key refers to *$table*.  Returns a *DbFramework::Table*.

bgcolor($bgcolor)
-----------------

   If $color is supplied sets the background colour for HTML table cells.
Returns the current background colour.

attribute_names()
-----------------

   Returns a list of the names of the attributes which make up the key.

as_sql()
--------

   Returns a string which can be used in an SQL 'CREATE TABLE' statement
to create the key.

as_html_heading()
-----------------

   Returns a string for use as a column heading cell in an HTML table;

SEE ALSO
========

   See DbFramework/ForeignKey,
DbFramework/PrimaryKey, and
DbFramework/Catalog.

AUTHOR
======

   Paul Sharpe <paul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1997,1998 Paul Sharpe. England.  All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Persistent Perl object base class
*********************************

NAME
====

   DbFramework::Persistent - Persistent Perl object base class

SYNOPSIS
========

     package Foo;
     use base qw(DbFramework::Persistent);

     package main;
     $foo = new Foo($table,$dbh);
     $foo->attributes_h(\%foo};
     $foo->insert;
     $foo->attributes_h(\%new_foo);
     $foo->update;
     $foo->delete;
     $foo->init_pk;
     @foo     = $foo->select($condition,$order);
     $hashref = $foo->table_qualified_attribute_hashref;
     $code    = DbFramework::Persistent::make_class($name);

DESCRIPTION
===========

   Base class for persistent objects which use a DBI database for storage.
To create your own persistent object classes subclass
*DbFramework::Persistent* (see the make_class() class method.)

SUPERCLASSES
============

   *DbFramework::Util*

CLASS METHODS
=============

new($table,$dbh)
----------------

   Create a new persistent object. *$table* is a *DbFramework::Table*
object or the name of a database table.  $dbh is a DBI database handle
which refers to a database containing a table associated with *$table*.

make_class($name)
-----------------

   Returns some Perl code which can be used with eval() to create a new
persistent object (sub)class called $name.

OBJECT METHODS
==============

   Attributes in a persistent object which relate to columns in the
associated table are made available through the attribute *ATTRIBUTES_H*.
See `AUTOLOAD()', see DbFramework/Util, for the
accessor methods for this attribute.

delete()
--------

   Delete this object from the associated table based on the values of
it's primary key attributes.  Returns the number of rows deleted if
supplied by the DBI driver.

insert()
--------

   Insert this object in the associated table.  Returns the primary key of
the inserted row if it is a Mysql 'AUTO_INCREMENT' column or -1.

update()
--------

   Update this object in the associated table.  Returns the number of rows
updated if supplied by the DBI driver.

select($conditions,$order)
--------------------------

   Returns a list of objects of the same class as the object which invokes
it.  Each object in the list has its attributes initialised from the
values returned by selecting all columns from the associated table
matching *$conditions* ordered by the list of columns in $order.

as_html_form()
--------------

   Returns an HTML form representing the object, filled with the object's
attribute values.

init_pk()
---------

   Initialise an object by setting its attributes based on the current
value of the its primary key attributes.

table_qualified_attribute_hashref()
-----------------------------------

   Returns a reference to a hash whose keys are the keys of
*%ATTRIBUTES_H* with a prefix of *$table*, where *$table* is the table
associated with the object and whose values are values from
*%ATTRIBUTES_H*.  This is useful for filling a template (see `fill()',
see DbFramework/Template.)

SEE ALSO
========

   See DbFramework/Util, DbFramework/Table,
and DbFramework/Template.

AUTHOR
======

   Paul Sharpe <paul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1997,1998,1999 Paul Sharpe. England.  All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Primary key class
*****************

NAME
====

   DbFramework::PrimaryKey - Primary key class

SYNOPSIS
========

     use DbFramework::PrimaryKey;
     $pk   = new DbFramework::Primary(\@attributes);
     $sql  = $pk->as_sql;
     $html = $pk->html_pk_select_field(\@column_names,$multiple,\@default);
     $html = $pk->as_html_heading;
     $qw   = $pk->as_query_string(\%values);

DESCRIPTION
===========

   The *DbFramework::PrimaryKey* class implements primary keys for a table.

SUPERCLASSES
============

   *DbFramework::Key*

CLASS METHODS
=============

new(\@attributes)
-----------------

   Create a new *DbFramework::PrimaryKey* object.  *@attributes* is a list
of *DbFramework::Attribute* objects from a single *DbFramework::Table*
object which make up the key.

OBJECT METHODS
==============

as_sql()
--------

   Returns a string which can be used in an SQL 'CREATE TABLE' statement
to create the primary key.

html_select_field(\@column_names,$multiple,\@default,$name)
-----------------------------------------------------------

   Returns an HTML form select field where the value consists of the
values from the columns which make up the primary key and the labels
consist of the corresponding values from *@column_names*.  If
*@column_names* is undefined the labels consist of the values from all
column names.  If *$multiple* is defined the field will allow multiple
selections.  *@default* is a list of values in the select field which
should be selected by default.  For fields which allow only a single
selection the first value in *@default* will be used as the default.  If
$name is defined it will be used as the name of the select field,
otherwise the name will consist of the attribute names of the primary key
joined by ',' (comma) and the values will consist of the corresponding
attribute values joined by ',' (comma).

as_html_heading()
-----------------

   Returns a string for use as a column heading cell in an HTML table;

as_query_string(\%values)
-------------------------

   Returns a CGI query string consisting of attribute names from the
primary key and their corresponding values from *%values*.

SEE ALSO
========

   See DbFramework/Key,

AUTHOR
======

   Paul Sharpe <paul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1997,1998,1999 Paul Sharpe. England.  All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Table class
***********

NAME
====

   DbFramework::Table - Table class

SYNOPSIS
========

     use DbFramework::Table;

     $t    = new DbFramework::Table new($name,\@attributes,$pk,$dbh,$dm);
     $t->init_db_metadata;
     $dbh  = $t->dbh($dbh);
     $pk   = $t->is_identified_by($pk);
     @fks  = @{$t->has_foreign_keys_l};
     %fks  = %{$t->has_foreign_keys_h};
     @keys = @{$t->is_accessed_using_l};
     @a    = $t->get_attributes(@names);
     @n    = $t->attribute_names;
     $html = $t->as_html_form;
     $s    = $t->as_string;
     $sql  = $t->as_sql;
     $rows = $t->delete($conditions);
     $pk   = $t->insert(\%values);
     $rows = $t->update(\%values,$conditions);
     @lol  = $t->select(\@columns,$conditions,$order);
     @loh  = $t->select_loh(\@columns,$conditions,$order);
     @a    = $t->non_key_attributes;
     $dm   = $t->belongs_to;
     do_something if $t->in_foreign_key($attribute);
     do_something if $t->in_key($attribute);
     do_something if $t->in_primary_key($attribute);
     do_something if $t->in_any_key($attribute);

DESCRIPTION
===========

   A *DbFramework::Table* object represents a database table (entity).

SUPERCLASSES
============

   *DbFramework::DefinitionObject*

   *DbFramework::DataModelObject*

CLASS METHODS
=============

new($name,\@attributes,$pk,$dbh,$dm)
------------------------------------

   Create a new *DbFramework::Table* object.  $dbh is a DBI database
handle which refers to a database containing a table named $name.
*@attribues* is a list of *DbFramework::Attribute* objects.  *$primary* is
a *DbFramework::PrimaryKey* object.  *@attributes* and *$primary* can be
omitted if you plan to use the init_db_metadata() object method (see
below).  *$dm* is a *DbFramework::DataModel* object to which this table
belongs.

OBJECT METHODS
==============

   Foreign keys in a table can be accessed using the *HAS_FOREIGN_KEYS_L*
and *HAS_FOREIGN_KEYS_H* attributes.  Note that foreign key objects will
not be created automatically by calling init_db_metadata() on a table
object.  If you want to automatically create foreign key objects for your
tables you should use call init_db_metadata() on a
*DbFramework::DataModel* object (see `DbFramework::Datamodel' in this
node).  Other keys (indexes) defined for a table can be accessed using the
*IS_ACCESSED_USING_L* attribute.  See `AUTOLOAD()', see
DbFramework/Util, for the accessor methods for these
attributes.

is_identified_by($primary)
--------------------------

   *$primary* is a *DbFramework::PrimaryKey* object.  If supplied sets the
table's primary key to *$primary*.  Returns a *DbFramework::PrimaryKey*
object with is the table's primary key.

dbh($dbh)
---------

   $dbh is a DBI database handle.  If supplied sets the database handle
associated with the table.  Returns the database handle associated with
the table.

belongs_to($dm)
---------------

   *$dm* is a *DbFramework::DataModel* object.  If supplied sets the data
model to which the table belongs.  Returns the data model to which the
table belongs.

get_attributes(@names)
----------------------

   Returns a list of *DbFramework::Attribute* objects.  *@names* is a list
of attribute names to return.  If *@names* is undefined all attributes
associated with the table are returned.

attribute_names()
-----------------

   Returns a list of attribute names for the table.

as_html_form()
--------------

   Returns HTML form fields for all attributes in the table.

in_foreign_key($attribute)
--------------------------

   $attribute is a *DbFramework::Attribute* object.  Returns true if
$attribute is a part of any foreign key in the table.

in_primary_key($attribute)
--------------------------

   $attribute is a *DbFramework::Attribute* object.  Returns true if
$attribute is a part of the primary key in the table.

in_key($attribute)
------------------

   $attribute is a *DbFramework::Attribute* object.  Returns true if
$attribute is a part of a key (index) in the table.

in_any_key($attribute)
----------------------

   $attribute is a *DbFramework::Attribute* object.  Returns true if
$attribute is a part of a key (index), a primary key or a foreign key in
the table.

non_key_attributes()
--------------------

   Returns a list of *DbFramework::Attribute* objects which are not
members of any key, primary key or foreign key.

as_string()
-----------

   Returns table details as a string.

init_db_metadata()
------------------

   Returns an initialised *DbFramework::Table* object for the table
matching this object's name() in the database referenced by dbh().

as_sql()
--------

   Returns a string which can be used to create a table in an SQL 'CREATE
TABLE' statement.

delete($conditions)
-------------------

   DELETE rows FROM the table associated with this object WHERE the
conditions in *$conditions* are met.  Returns the number of rows deleted
if supplied by the DBI driver.

insert(\%values)
----------------

   INSERT INTO the table columns corresponding to the keys of *%values*
the VALUES corresponding to the values of *%values*.  Returns the primary
key of the inserted row if it is a Mysql 'AUTO_INCREMENT' column or -1.

update(\%values,$conditions)
----------------------------

   UPDATE the table SETting the columns matching the keys in %values to
the values in %values WHERE *$conditions* are met.  Returns the number of
rows updated if supplied by the DBI driver.

select(\@columns,$conditions,$order)
------------------------------------

   Returns a list of lists of values by SELECTing values FROM *@columns*
WHERE rows meet *$conditions* ORDERed BY the list of columns in $order.
Strings in *@columns* can refer to functions supported by the database in
a SELECT clause e.g.

   `@columns = q/sin(foo),cos(bar),tan(baz)/;'

select_loh(\@columns,$conditions,$order)
----------------------------------------

   Returns a list of hashrefs containing *(column_name,value)* pairs by
SELECTing values FROM *@columns* WHERE rows meet *$conditions* ORDERed BY
the list of columns in $order.  Strings in *@columns* can refer to
functions supported by the database in a SELECT clause e.g.

   `@columns = q/sin(foo),cos(bar),tan(baz)/;'

   The keys in the hashrefs will match the name of the function applied to
the column i.e.

   `@loh = $foo->select(\@columns);'

   `print "sin(foo) = $loh[0]->{sin(foo)}\n";'

as_html_heading()
-----------------

   Returns a string for use as a table heading row in an HTML table.

SEE ALSO
========

   See DbFramework/DefinitionObject,
DbFramework/Attribute,
DbFramework/DataModelObject, and
DbFramework/DataModel.

AUTHOR
======

   Paul Sharpe <paul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1997,1998,1999 Paul Sharpe. England.  All rights
reserved.  This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

Fill template with database values
**********************************

NAME
====

   DbFramework::Template - Fill template with database values

SYNOPSIS
========

     use DbFramework::Template;
     $t = new DbFramework::Template($template,\@tables);
     print $t->fill;
     $t->default($table);
     $t->template->set_text($template);

DESCRIPTION
===========

   *DbFramework::Template* is a class for filling templates with values
from a database.

Template placeholders
---------------------

   The following list describes the placeholders allowed in a template.
In each case *%values* relates to the hash passed to the fill() method.

(:&db_value(table.column):)
     Replaced with the value from *%values* whose key is *table.column*.
     See `table_qualified_attribute_hashref()', see
     DbFramework/Persistent, for a useful method
     for generating a hash to fill this type of placeholder.

*(:&db_html_form_field(table.column[ value=value][ type=type]):)*
     Replaced with an HTML form field appropriate for the column column in
     the table table.  value is the inital value which will be applied to
     the field.  The type of field generated is determined by the data
     type of column.  This can be overridden by setting type.  See
     `as_html_form_field()', see DbFramework/Attribute,
     for more details.

(:&db_fk_html_form_field(table.fk):)
     Replaced with an HTML form field appropriate for the foreign key *fk*
     in the table table.  See `as_html_form_field()', see
     DbFramework/ForeignKey, for more details.

SUPERCLASSES
============

   *DbFramework::Util*

CLASS METHODS
=============

new($template,\@tables)
-----------------------

   Create a new *DbFramework::Template* object.  $template is the template
to be filled.  *@tables* are the *DbFramework::Table* objects required for
filling the template.

OBJECT METHODS
==============

template()
----------

   Returns the *Text::FillIn* object associated with the template.

fill(\%values)
--------------

   Returns a filled template.  The values in *%values* are used to fill
certain placeholders in the template (see `"Template placeholders"' in
this node.)

default($table)
---------------

   *$table* is a *DbFramework::Table* object.  Sets up a default template
consisting of all fields in *$table*.

SEE ALSO
========

   See Text/FillIn, and DbFramework/Util.

AUTHOR
======

   Paul Sharpe <paul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1999 Paul Sharpe. England.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

DbFramework utility functions
*****************************

NAME
====

   DbFramework::Util - DbFramework utility functions

SYNOPSIS
========

     use DbFramework::Util;
     ($user,$password) = DbFramework::Util::get_auth();
     $dbh = DbFramework::Util::get_dbh($dsn,$user,$password);
     $sth = DbFramework::Util::do_sql($dbh,$sql);
     ($user,$password) = DbFramework::Util::get_auth();

     $object->debug($n);

DESCRIPTION
===========

   *DbFramework::Util* contains miscellaneous utility functions and acts
as a base class for many other *DbFramework* classes.

BASE CLASS METHODS
==================

AUTOLOAD()
----------

   AUTOLOAD() provides default accessor methods (apart from DESTROY()) for
any of its subclasses.  For AUTOLOAD() to catch calls to these methods
objects must be implemented as an anonymous hash.  Object attributes must

   * have UPPER CASE names

   * have keys in attribute _PERMITTED (an anonymous hash)

   The name accessor method is the name of the attribute in *lower case*.
The 'set' versions of these accessor methods require a single scalar
argument (which could of course be a reference.)  Both 'set' and 'get'
versions return the attribute's value.

   *Special Attributes*

/_L$/
     Attribute names matching the pattern /_L$/ will be treated as
     arrayrefs.  These accessors require an arrayref as an argument.  If
     the attribute is defined they return the arrayref, otherwise they
     return an empty arrayref.

     A method **_l_add(@foo)* can be called on this type of attribute to
     add the elements in *@foo* to the array.  If the attribute is defined
     they return the arrayref, otherwise they return an empty arrayref.

/_H$/
     Attribute names matching the pattern /_H$/ will be treated as
     hashrefs.  These accessors require a reference to an array containing
     key/value pairs.  If the attribute is defined they return the hashref,
     otherwise they return an empty hashref.

     A method **_h_byname(@list)* can be called on this type of attribute.
     These methods will return a list which is the hash slice of the *_H*
     attribute value over *@list* or an empty list if the attribute is
     undefined.

     A method **_h_add(\%foo)* can be called on this type of attribute to
     add the elements in *%foo* to the hash.  If the attribute is defined
     they return the hashref, otherwise they return an empty hashref.

debug($n)
---------

   As a class method sets the class attribute *$Debugging* to $n.  As an
object method sets the object attribute *$_DEBUG* to $n.

UTILITY FUNCTIONS
=================

get_auth()
----------

   Read (*$user*,$password) from standard input with no echo when entering
password.

get_dbh($dsn,$user,$password)
-----------------------------

   Returns a database handle for the data source name *$dsn* by connecting
using *$user* and $password.

do_sql($dbh,$sql)
-----------------

   Executes *$sql* on $dbh and returns a statement handle.  This method
will die with *$h->errstr* if prepare() or execute() fails.

AUTHOR
======

   Paul Sharpe <paul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1997,1998 Paul Sharpe. England.  All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Markov models for decision analysis
***********************************

NAME
====

   Decision::Markov - Markov models for decision analysis

SYNOPSIS
========

     use Decision::Markov;
     $model = new Decision::Markov;
     $state = $model->AddState("Name",$utility);
     $error = $model->AddPath($state1,$state2,$probability);
     $error = $model->Check
     $model->Reset([$starting_state,[$number_of_patients]]);
     $error = $model->StartingState($starting_state[,$number_of_patients]);
     $model->DiscountRate($rate);
     ($utility,$cycles) = $model->EvalMC();
     $state = $model->EvalMCStep($cycle);
     ($utility,$cycles) = $model->EvalCoh();
     $patients_left = $model->EvalCohStep($cycle);
     $model->PrintCycle($FH,$cycle);
     $model->PrintMatrix($FH);

DESCRIPTION
===========

   This module provides functions used to built and evaluate Markov models
for use in decision analysis. A Markov model consists of a set of states,
each with an associated utility, and links between states representing the
probability of moving from one node to the next. Nodes typically include
links to themselves.  Utilities and probabilities may be fixed or may be
functions of the time in cycles since the model began running.

METHODS
=======

new
     Create a new Markov model.

AddState
     Add a state to the model. The arguments are a string describing the
     state and the utility of the state. The utility may be specified
     either as a number or as a reference to a subroutine that returns the
     utility. The subroutine will be passed the current cycle number as an
     argument. Returns the new state, which is an object of class
     Decision::Markov::State.

AddPath
     Adds a path between two states. The arguments are the source state,
     the destination state, and the probability of transition.

     Probability may be specified either as a number or as a reference to a
     subroutine that returns the probability. The subroutine will be
     passed the current cycle number as an argument.

     AddPath returns undef if successful, error message otherwise.

Check
     Checks all states in the model to include that the probabilities of
     the paths from each state sum to 1. Returns undef if the model checks
     out, error message otherwise.

Reset
     Resets the model. Use before evaluating the model.

StartingState
     Sets the state in which patients start when the model is evaluated.
     The optional second argument sets the number of patients in a cohort
     when performing a cohort simulation.

     Returns undef if successful or an error message.

DiscountRate
     Sets the per-cycle discount rate for utility. By default, there is no
     discounting. To set, for example, 3%/cycle discounting, use
     $model->DiscountRate(.03);

     If no discount rate is given, returns the current discount rate.

EvalMC
     Performs a Monte Carlo simulation of a single patient through the
     model, and returns that patient's cumulative utility and the number
     of cycles the model ran. The patient begins in the state set by
     StartingState.

EvalMCStep
     Given the current model cycle, evaluates a single step of the Markov
     model, and returns the patient's new state. Internally continues to
     track the patient's cumulative utility.

EvalCoh
     Performs a cohort simulation of the model and returns the average
     cumulative utility of a patient in the cohort, and the number of
     cycles the model ran. The number of patients and their initial state
     are set with StartingState.

EvalCohStep
     Evaluates a single cycle of a cohort simulation. Returns the number
     of patients who will change states in the next cycle (i.e., if it
     returns 0, you're at the end of the model run).

PrintCycle
     Given a FileHandle object and the cycle, prints the current
     distribution of patients in the cohort (if a cohort simulation is in
     progress) or the current state and utility of the patient (if a Monte
     Carlo simulation is in progress).

PrintMatrix
     Given a FileHandle object, prints the model in transition matrix form

REFERENCES
==========

   Sonnenberg, F. A. & Beck, J. R. (1993). Markov Models in Medical
Decision Making: A Practical Guide. Med. Dec. Making, 13: 322-338.

COPYRIGHT
=========

   Copyright (c) 1998 Alan Schwartz <alansz@uic.edu>. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

REVISION HISTORY
================

  1. March 1988 - Initial concept.

Markov state object for Decision::Markov
****************************************

NAME
====

   Decision::Markov::State - Markov state object for Decision::Markov

SYNOPSIS
========

     use Decision::Markov::State;
     $state = new Decision::Markov::State("Name",<utility>);
     $state->Reset();
     $state->Name("Name");
     $name = $state->Name;
     $state->NumPatients(100);
     $num = $state->NumPatients;
     $utility = $state->Utility($cycle);
     $error = $state->AddTransition($newstate,$prob);
     $prob = $state->TransitionProb($newstate[,$cycle]);
     $total = $state->SumProbs([$cycle]);
     $boolean = $state->FinalState;
     $newstate = $state->NextState($cycle);
     $state->DistributeCohort($cycle);
     $state->UpdateCohort();

DESCRIPTION
===========

   This module implements a Markov state object used by Decision::Markov.
It's not really intended to be used directly, but for completeness, its
public methods are documented here.

METHODS
=======

new
     Creates a new Markov state object, given a name for the state and its
     utility. The utility may be specified either as a number or as a
     reference to a subroutine which will be called with the current model
     cycle as its only argument.

Reset
     Resets the state, clearing temporary information that is stored in the
     state during model evaluations.

Name
     With no argument, returns the name of the state. With an argument,
     sets the name of the state.

NumPatients
     With no argument, returns the number of patients in the state. With an
     argument, sets the number of patients in the state.

Utility
     Given the current model cycle, computes and returns the utility of
     being in the state during that cycle.

AddTransition
     Given a second Markov state, and a transition probability, adds a
     transition from the first state to the second that will occur with
     probability equal to the transition probability at the model cycle.
     Probability can be specified as a number or a reference to a
     subroutine which will be called with the current model cycle as its
     only argument.

     Returns undef if successful or an error message if unsuccessful
     (e.g., there's already a transition between those states.)

TransitionProb
     Given a second Markov state, return the probability of transitioning
     from the first state to the second. May return either a number or a
     reference to a subroutine that can be called with the current model
     cycle to get the numerical probability. If TransitionProb is given a
     cycle number as its optional second argument, it will always return
     the probability during that cycle. If a state doesn't have a
     transition to the new state, this function returns 0.

SumProbs
     Return the sum of all the transition probabilities from the state.  If
     any of the probabilities are subroutine references, they are evaluated
     at the cycle given as an argument to SumProbs or at cycle 3 if
     SumProbs is called without arguments. This function is used to check
     that probabilities sum to 1.

FinalState
     Returns 1 if the state is a final state: a state with no transitions
     to states other than itself. Otherwise, returns 0.

NextState
     Given the model cycle, randomly determine and return the next state
     that a patient in this state will move to, based on the transition
     probabilities. Used in Monte Carlo evaluations.

DistributeCohort
     Given the model cycle, distribute all of the patients in the state to
     other states in proportion to their transition probabilities. Note
     that a state usually transitions to itself as well, so some of the
     patients are distributed back to the same state. Distributed patients
     are held in a temporary attribute of the object so that all states can
     be distributed before calling UpdateCohort to actually set the new
     number of patients for each state. Used in cohort simulations.

UpdateCohort
     Update the number of patients in this state from the temporary
     attribute created by DistributeCohort.

COPYRIGHT
=========

   Copyright (c) 1998 Alan Schwartz <alansz@uic.edu>. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

REVISION HISTORY
================

  1. March 1988 - Initial concept.

Simple time-delay data stucture
*******************************

NAME
====

   DelayLine - Simple time-delay data stucture

SYNOPSIS
========

     use DelayLine;

     my $dl = DelayLine->new(delay => $defaultdelay);

     $dl->in($item);

     [ ... ]

     if (my $ob = $dl->out()) {
         # do stuff with $ob
     }

DESCRIPTION
===========

   The `DelayLine' is a simple two-port data structure, like a FIFO, but
with variable delay. Each object put into the input of the DelayLine will
appear on the output only after some pre-determined amount of time has
elapsed. This time can be set as a default for the DelayLine, or can be
individually overridden for each object put into the DelayLine.

   If the default delay time is set to zero, and is not overridden for the
individual objects, the DelayLine mimics a straightforward FIFO.

   The DelayLine accepts any scalar value as input, including references.

   The DelayLine is a very useful component when building simple event
loops.

Methods
-------

   `DelayLine' provides the following methods:

DelayLine->new( [ delay => DELAY [, debug => DEBUG ]] )
     Returns a newly created `DelayLine' object.

     The default delay is 0 seconds, unless an optional DELAY time in
     seconds is given.

     Debugging is turned off by default. Setting DEBUG to true, enables
     debugging output to STDOUT.

     The parameter naming style is very flexible: the keyword can be in
     lower, upper or mixed case, and can be optionally prefixed with a
     dash. Thus, the following are all equivalent:

          $dl = DelayLine->new( -delay => 42 );
          $dl = DelayLine->new(  delay => 42 );
          $dl = DelayLine->new( -Delay => 42 );
          $dl = DelayLine->new(  DELAY => 42 );
          $dl = DelayLine->new( -deLaY => 42 );

     new() can be called as a class (static) or object method. Calling
     new() as an object method is only a convenience; no data from the
     original DelayLine is carried over into the newly created object.

$DL->in( OBJ [, DELAY ] )
     This method puts object OBJ into DelayLine `$DL'.

     The object OBJ can be any scalar value, including references.

     The default delay as set in the new() method is used, unless
     overridden by setting DELAY.

$DL->out()
     This method fetches objects from the out from the DelayLine `$DL'.

     Returns the first of the timed-out objects, if any.

     Returns undef if the DelayLine is empty, of if no objects in the
     DelayLine have timed out yet.

$DL->delay( [ DELAY ] )
     Returns the current default delay setting of the DelayLine. If the
     optional value DELAY is set, sets a new default delay value.

$DL->debug( [ DEBUG ] )
     Returns the current debug setting of the DelayLine. If the optional
     value DEBUG is set, sets a new debug value.

     If the debug value is set (true), calling any of the 'active' methods
     (`in()' or `out()' will yield a short debug message on STDERR.

BUGS
====

   This is a fairly simple module, so no serious bugs are expected.
Patches are welcome, though.

RELEASE HISTORY
===============

v0.02 - 2000-jul-22
     Fixed test for multiple unknown args.  Removed superfluous test
     output.  Streamlined debug output.

v0.01 - 2000-jul-13
     Initial release.

COPYRIGHT
=========

   Copyright (c) 2000 Lars Thegler. All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Lars Thegler <lars@thegler.dk>

Des extension module for Perl
*****************************

NAME
====

   Des - Des extension module for Perl

DESCRIPTION
===========

   The Des extension module gives access to the DES library.

   The following is a brief and over-simplified description of the relevant
stuff about DES.

   DES keys are 8-byte blocks. A key is passed to a perl function as an
8-byte string. Before keys can be used to encrypt or decrypt data, the key
needs to be transformed into a key schedule using the function set_key.
There is a certain amount of overhead in creating these key schedules
(which are 128 bytes or 256 bytes depending on implementation and
architecture) so they can be created and cached for later if desired.
Encryption and decryption can be done in 3 modes:

ECB (electronic code book) mode
     Takes a des_cblock (perl 8-byte string) and produces another
     des_cblock.  (Very rarely useful for large amounts of plain text,
     subject to known plaintext attacks under certain circumstances, only
     slightly faster than CBC or PCBC mode, and you lose even this
     advantage in perl).

CBC (cipher block chaining) mode
     Takes an arbitrary length string, pads it out (internally) on the
     right with NULs to a multiple of 8-bytes. Encrypts/decrypts the data
     and produces output (same size as padded input) which is an exact
     multiple of 8 bytes long. Changing a single bit of the cleartext
     affects all the following ciphertext. However, changing a single bit
     of the ciphertext affects only the corresponding cleartext block and
     the following block. This is occasionally an advantage but is usually
     a disadvantage.

PCBC mode
     A modified CBC mode with indefinite proagation of single bit errors
     both from cleartext to ciphertext and from ciphertext to cleartext.
     "Usually" the best mode (for certain values of "usually").

Functions imported by *use Des*.
--------------------------------

string_to_key (STRING)
     Takes an arbitrary STRING and munges it (with a one-way function) into
     a DES key, which is returned.

set_key (KEY)
     The DES key KEY (which must be a string of exactly 8 bytes) is turned
     into a key schedule which is returned.

ecb_encrypt (INPUT, SCHEDULE)
     The INPUT argument (which must be a string of exactly 8 bytes) is
     encrypted using ECB mode using key schedule SCHEDULE (created using
     set_key) and the resulting 8-byte string is returned.

ecb_decrypt (INPUT, SCHEDULE)
     The INPUT argument (which must be a string of exactly 8 bytes) is
     decrypted using ECB mode using key schedule SCHEDULE (created using
     set_key) and the resulting 8-byte string is returned.

cbc_encrypt (INPUT, OUTPUT, SCHEDULE, IV)
     The INPUT argument can be of arbitrary length, although it will be
     internally padded on the right with NULs to the nearest multiple of 8
     bytes.  INPUT is taken and encrypted using CBC mode with key schedule
     SCHEDULE and initialisation vector IV. If OUTPUT is not undef then it
     assumed to be an lvalue which is grown (if necessary) and receives
     the encrypted output. Whether or not OUTPUT is undef, the output is
     also available as the return value of the function.

cbc_decrypt (INPUT, OUTPUT, SCHEDULE, IV)
     The INPUT argument can be of arbitrary length, although it will be
     internally padded on the right with NULs to the nearest multiple of 8
     bytes.  INPUT is taken and decrypted using CBC mode with key schedule
     SCHEDULE and initialisation vector IV. If OUTPUT is not undef then it
     assumed to be an lvalue which is grown (if necessary) and receives
     the decrypted output. Whether or not OUTPUT is undef, the output is
     also available as the return value of the function.

pcbc_encrypt (INPUT, OUTPUT, SCHEDULE, IV)
     The INPUT argument can be of arbitrary length, although it will be
     internally padded on the right with NULs to the nearest multiple of 8
     bytes.  INPUT is taken and encrypted using PCBC mode with key
     schedule SCHEDULE and initialisation vector IV. If OUTPUT is not
     undef then it assumed to be an lvalue which is grown (if necessary)
     and receives the encrypted output. Whether or not OUTPUT is undef,
     the output is also available as the return value of the function.

pcbc_decrypt (INPUT, OUTPUT, SCHEDULE, IV)
     The INPUT argument can be of arbitrary length, although it will be
     internally padded on the right with NULs to the nearest multiple of 8
     bytes.  INPUT is taken and decrypted using PCBC mode with key
     schedule SCHEDULE and initialisation vector IV. If OUTPUT is not
     undef then it assumed to be an lvalue which is grown (if necessary)
     and receives the decrypted output. Whether or not OUTPUT is undef,
     the output is also available as the return value of the function.

pcbc_cksum (INPUT, SCHEDULE, IV)
     The INPUT argument can be of arbitrary length, although it will be
     internally padded on the right with NULs to the nearest multiple of 8
     bytes.  CBC mode is used to generate an 8-byte cryptographic checksum
     using key schedule SCHEDULE and initialisation vector IV. This
     checksum is returned.

Functions in package Des which can be imported
----------------------------------------------

random_key ()
     Produces a random DES key based on current time, PID and a counter.

read_password (PROMPT [, VERIFY])
     Prints PROMPT on the terminal, turns off echo if possible and reads a
     password from the keyboard. If the optional VERIFY argument is present
     and true than the password is prompted for a second time and the two
     are compared. If different, the prompting is repeated. The resulting
     string is turned into a DES key (using string_to_key (q.v.)
     internally) and that key is returned.

AUTHOR
------

   Malcolm Beattie, `mbeattie@sable.ox.ac.uk', 6 Dec 1994.

warn of errors (from perspective of caller)
*******************************************

NAME
====

   carp    - warn of errors (from perspective of caller)

   cluck   - warn of errors with stack backtrace           (not exported
by default)

   croak   - die of errors (from perspective of caller)

   confess - die of errors with stack backtrace

SYNOPSIS
========

     use Carp;
     croak "We're outta here!";

     use Carp qw(cluck);
     cluck "This is how we got here!";

DESCRIPTION
===========

   The Carp routines are useful in your own modules because they act like
die() or warn(), but report where the error was in the code they were
called from.  Thus if you have a routine Foo() that has a carp() in it,
then the carp() will report the error as occurring where Foo() was called,
not where carp() was called.

Forcing a Stack Trace
---------------------

   As a debugging aid, you can force Carp to treat a croak as a confess
and a carp as a cluck across all modules. In other words, force a detailed
stack trace to be given.  This can be very helpful when trying to
understand why, or from where, a warning or error is being generated.

   This feature is enabled by 'importing' the non-existant symbol
'verbose'. You would typically enable it by saying

     perl -MCarp=verbose script.pl

   or by including the string `MCarp=verbose' in the `PERL5OPT' in this
node environment variable.

try to generate a stack dump from a core file
*********************************************

NAME
====

   Devel::CoreStack - try to generate a stack dump from a core file

SYNOPSIS
========

     perl -MDevel::CoreStack -e 'stack'

     perl -MDevel::CoreStack -e 'stack("../myperl", "./mycore", "debugger")'

DESCRIPTION
===========

   This module attempts to generate a stack dump from a core file by
locating the best available debugger (if any) and running it with the
appropriate arguments and command script.

Perl module to perform coverage analysis
****************************************

NAME
====

   Devel::Coverage - Perl module to perform coverage analysis

SYNOPSIS
========

     perl -d:Coverage script_name [ args ]

DESCRIPTION
===========

   This software is still very early-alpha quality. Use the tool
`coverperl' to analyze the files that result from running your scripts
with coverage enabled.

AUTHOR
======

   Randy J. Ray <rjray@blackperl.com>

SEE ALSO
========

   See Devel/DProf,

a Perl code profiler
********************

NAME
====

   Devel::DProf - a Perl code profiler

SYNOPSIS
========

     perl5 -d:DProf test.pl

DESCRIPTION
===========

   The Devel::DProf package is a Perl code profiler.  This will collect
information on the execution time of a Perl script and of the subs in that
script.  This information can be used to determine which subroutines are
using the most time and which subroutines are being called most often.
This information can also be used to create an execution graph of the
script, showing subroutine relationships.

   To profile a Perl script run the perl interpreter with the -d debugging
switch.  The profiler uses the debugging hooks.  So to profile script
test.pl the following command should be used:

     perl5 -d:DProf test.pl

   When the script terminates (or when the output buffer is filled) the
profiler will dump the profile information to a file called `tmon.out'.  A
tool like dprofpp can be used to interpret the information which is in
that profile.  The following command will print the top 15 subroutines
which used the most time:

     dprofpp

   To print an execution graph of the subroutines in the script use the
following command:

     dprofpp -T

   Consult `dprofpp' in this node for other options.

PROFILE FORMAT
==============

   The old profile is a text file which looks like this:

     #fOrTyTwO
     $hz=100;
     $XS_VERSION='DProf 19970606';
     # All values are given in HZ
     $rrun_utime=2; $rrun_stime=0; $rrun_rtime=7
     PART2
     + 26 28 566822884 DynaLoader::import
     - 26 28 566822884 DynaLoader::import
     + 27 28 566822885 main::bar
     - 27 28 566822886 main::bar
     + 27 28 566822886 main::baz
     + 27 28 566822887 main::bar
     - 27 28 566822888 main::bar
     [....]

   The first line is the magic number.  The second line is the hertz
value, or clock ticks, of the machine where the profile was collected.
The third line is the name and version identifier of the tool which
created the profile.  The fourth line is a comment.  The fifth line
contains three variables holding the user time, system time, and realtime
of the process while it was being profiled.  The sixth line indicates the
beginning of the sub entry/exit profile section.

   The columns in *PART2* are:

     sub entry(+)/exit(-) mark
     app's user time at sub entry/exit mark, in ticks
     app's system time at sub entry/exit mark, in ticks
     app's realtime at sub entry/exit mark, in ticks
     fully-qualified sub name, when possible

   With newer perls another format is used, which may look like this:

     #fOrTyTwO
     $hz=10000;
     $XS_VERSION='DProf 19971213';
     # All values are given in HZ
     $over_utime=5917; $over_stime=0; $over_rtime=5917;
     $over_tests=10000;
     $rrun_utime=1284; $rrun_stime=0; $rrun_rtime=1284;
     $total_marks=6;

     PART2
     @ 406 0 406
     & 2 main bar
     + 2
     @ 456 0 456
     - 2
     @ 1 0 1
     & 3 main baz
     + 3
     @ 141 0 141
     + 2
     @ 141 0 141
     - 2
     @ 1 0 1
     & 4 main foo
     + 4
     @ 142 0 142
     + & Devel::DProf::write
     @ 5 0 5
     - & Devel::DProf::write

   (with high value of $ENV{PERL_DPROF_TICKS}).

   New `$over_*' values show the measured overhead of making $over_tests
calls to the profiler These values are used by the profiler to subtract
the overhead from the runtimes.

   The lines starting with `@' mark time passed from the previous `@'
line.  The lines starting with & introduce new subroutine id and show the
package and the subroutine name of this id.  Lines starting with +, - and
* mark entering and exit of subroutines by ids, and `goto &subr'.

   The *old-style* +- and -lines are used to mark the overhead related to
writing to profiler-output file.

AUTOLOAD
========

   When Devel::DProf finds a call to an `&AUTOLOAD' subroutine it looks at
the $AUTOLOAD variable to find the real name of the sub being called.  See
`"Autoloading"', see Perlsub (perl.info).

ENVIRONMENT
===========

   `PERL_DPROF_BUFFER' sets size of output buffer in words.  Defaults to
2**14.

   `PERL_DPROF_TICKS' sets number of ticks per second on some systems where
a replacement for times() is used.  Defaults to the value of `HZ' macro.

   `PERL_DPROF_OUT_FILE_NAME' sets the name of the output file.  If not
set, defaults to tmon.out.

BUGS
====

   Builtin functions cannot be measured by Devel::DProf.

   With a newer Perl DProf relies on the fact that the numeric slot of
$DB::sub contains an address of a subroutine.  Excessive manipulation of
this variable may overwrite this slot, as in

     $DB::sub = 'current_sub';
     ...
     $addr = $DB::sub + 0;

   will set this numeric slot to numeric value of the string
`current_sub', i.e., to 0.  This will cause a segfault on the exit from
this subroutine.  Note that the first assignment above does not change the
numeric slot (it will mark it as invalid, but will not write over it).

   Mail bug reports and feature requests to the perl5-porters mailing list
at `<perl5-porters@perl.org>'.

SEE ALSO
========

   See Perl (perl.info), `dprofpp' in this node, times(2)

Perl extension for creating a debugger initialization files from C header file macros
*************************************************************************************

NAME
====

   Devel::DebugInit - Perl extension for creating a debugger
initialization files from C header file macros

SYNOPSIS
========

     use Devel::DebugInit::GDB;
     my $gdb = new Devel::DebugInit::GDB 'filenames' => ["/my/path/to/library.h"];
     $gdb->write("/my/path/to/library/.gdbinit");

DESCRIPTION
===========

   Devel::DebugInit is aimed at C/C++ developers who want access to C
macro definitions from within a debugger. It provides a simple and
automated way of creating debugger initialization files for a specific
project. The initialization files created contain user-defined functions
built from the macro definitions in the project's header files.

   By calling new(), the files specified by the 'filenames' parameter are
parsed by the C preprocessor, and all macros #define'd in the file (and if
desired, all macros #define'd by all #include'd files as well), will be
parsed and expanded. By then calling the write() method, these macros can
be written to an output file in the format of user-defined functions
specific for your debugger.

   By automating the process, a new file can be created whenever the code
of a project changes, and that way there will not be antiquated copies
lying around to trap the unwary.

NOTES
=====

   This module requires the use of one of the debugger-specific backend
modules, such as Devel::DebugInit::GDB which is supplied with DebugInit.
The backends supply the output routines which are specific for that
debugger.

   This module also requires both the C::Scan and Data::Flow modules and
will not function without them.

WHY CARE?
=========

   Debugger initialization files can contain user-defined functions that
make doing complicated or repetitive actions easier. Normally, from within
the debugger a user can evaluate any C function call. But for a number of
reasons, many projects use C preprocessor macros (#define statements) in
place of an actual C function call. The use of macros instead of function
calls is transparent during compilation, but most debuggers do not allow
access to macros, and so the user must type in the code by hand each time
s/he wants to use a macro, or must build an initialization file by hand.
Retyping is tedious, but hand coding the initialization file may result in
antiquated code when the project changes. By automating the process, I
hope to alleviate a few headaches for developers.

   There are two types of macros: macros with arguments, e.g:

     #define min(x,y) ((x) < (y) ? (x) : (y))

   and macros without arguments (simple macros), e.g.

     #define PI 3.14

   Of the two types, macros with arguments are more useful from within a
debugger, and so, printing of simple macros is turned off by default (but
see `INTERNALS' in this node for how to turn them on).

INTERNALS
=========

   For the casual user the defaults, and the three lines given in the
`SYNOPSIS' in this node should be enough. But for the determined user, a
few details of how things happen under the hood might be useful in
customizing the output of this module.

How Devel::DebugInit Parses Files
---------------------------------

   When new() is called to create an instance of a Devel::DebugInit, the
following steps occur. The C preprocessor is invoked on the file with the
'macros only' flag set (this flag defaults to '-dM' and if this does not
work on your system, change the value of $C::Scan::MACROS_ONLY and let the
author know, and he will try and fix it :-). This lists all macros
#define'd in the file PLUS all macros #define'd in all files #include'd by
that file (both the system files <types.h> and the user files
"mystring.h"). This may include many more macros than is desired (not
everybody really wants '_LINUX_C_LIB_VERSION_MAJOR' as a user defined
function in their debugger...), so there are 3 mode flags defined that
allow the user to control which macros are included: MACROS_ALL,
MACROS_LOCAL, and MACROS_NONE.

MACROS_ALL, MACROS_LOCAL, and MACROS_NONE
-----------------------------------------

   These flags can be used to control what macros go into the print tables
that Devel::DebugInit uses to create the output file. The MACROS_ALL flag
instructs DebugInit to included all macros of that type in the output
table. To avoid printing out all of the system level macros that can get
#include'd you can use the MACROS_LOCAL flag. This indicates that only
macros actually #define'd in that file should be stored, and macros
#define'd in other files which are #include'd into the file should NOT be
stored (they are, however, still made available for expansion purposes).
The MACROS_LOCAL flag is the default for macros with arguments. Finally,
the MACROS_NONE flag indicates that no macros of that type should be put
in the output table. The MACROS_NONE flag is the default for the simple
macros.

Output Tables and Lookup Tables
-------------------------------

   Devel::DebugInit has two separate groups of tables that it uses -
lookup tables for expanding macro definitions and output tables for
printing the fully expanded macros. The lookup tables always include all
macros that a given file has access to, but the output tables may have
many fewer. Because the user-defined functions of some debuggers can be
very limited, Devel::DebugInit fully expands all macros stored in the
output tables before writing them to a file. In this way, any macro which
utilized other macros in its body will have those expanded in place. So by
the end of the expansion process, all macros will be self defined and not
rely on any other macro definition. Each macro in the output tables is
expanded in this manner using the definitions in the lookup tables. Using
separate lookup tables and output tables allows users to print out only
those macros they care about while still be able to fully expand all
macros.

METHODS
=======

new()
-----

   Returns a blessed reference to an instance of a Devel::DebugInit
subclass. Each Devel::DebugInit subclass takes a list of option value
pairs as optional arguments to new. Currently there are three recognized
options 'filenames', 'macros_args', and 'macros_no_args'. The 'filenames'
option controls which file is used for creating the output. The
'macros_args' option controls the level of output support for macros with
arguments. The 'macro_no_args' option controls the level of output support
for simple macros. For example, to make a .gdbinit file useful for
debugging perl or perl XSUBs try the following:

     $gdb = new Devel::DebugInit::GDB
         'filenames' => ["$Config{'archlib'}/CORE/perl.h"],
         'macros_args'    => $Devel::DebugInit::MACROS_ALL,
         'macros_no_args' => $Devel::DebugInit::MACROS_ALL;

     $gdb->write();

   When written, this will create a file that is about 110k in size and
have about 1750 user-defined functions. So it may be useful to limit it in
scope somewhat. It is not clear that simple macros are useful from within
a debugger, so the default value for 'macros_no_args' is MACROS_NONE, and
to avoid printing all system level macros, the default for 'macros_args'
is MACROS_LOCAL. NOTE that by using MACROS_LOCAL, you will inhibit
printing of all macros not #define'd in the file listed, both from local
header files and system headers alike. To get around this multiple files
can be included in the array ref for the 'filenames' option. Each files
macros are added to a common lookup table, but only the macros #defined in
each file are printed. So could do the following:

     $gdb = new Devel::DebugInit::GDB
         'filenames' => ["$Config{'archlib'}/CORE/perl.h",
     		       "$Config{'archlib'}/CORE/sv.h",
     		       "$Config{'archlib'}/CORE/XSUB.h"],
         'macros_args'    => $Devel::DebugInit::MACROS_LOCAL,
         'macros_no_args' => $Devel::DebugInit::MACROS_NONE;

     $gdb->write();

   This reduces the output file to only 21k and 250 or so macros.

write() =head2 write($filename)
-------------------------------

   This function is overloaded by each of the debugger specific subclasses
to produce output recognized by that debugger. If $filename is not given,
it defaults to something reasonable for that debugger. All macros in the
output table for each macro type (macros with arguments and simple macros)
will be printed if it passes scrutiny by the `scan()' in this node method.
See the `INTERNALS' in this node section for more details on controlling
what macros are stored in the print tables.

scan()
------

   The only other method of interest to users of this module is the scan()
method which is also overloaded by each backend subclass. This method is
called by write() to ascertain whether or not a given macro should be
written out to the output file. By default, scan() stops undefined macros,
blank macros (e.g. macros such as <#define VMS> which are usually just
conditional compiler flags and of no use in a debugger), and macros with
names that conflict with built-in debugger commands. Users desiring a very
fine grained control over the output can override the builtin scan() with
their own on a per need basis. For example:

     package myGDB;
     use Devel::DebugInit::GDB;
     @myGDB::ISA = (Devel::DebugInit::GDB);

     sub scan {
       my ($gdb,$key,$macro) = @_;

       #first give the superclass scan a chance
       return 0 unless $gdb->SUPER::scan(@_);

       # dont' print out any macros with a leading '_'
       return 0 if $macro =~ /^_/;

       # print the rest
       return 1;
     }

AUTHOR
======

   Jason E. Stewart, jasons@cs.unm.edu

SEE ALSO
========

   perl(1), Devel::DebugInit::GDB(3), C::Scan(3), and Data::Flow(3).

Perl extension for creating .gdbinit file from C header file macros
*******************************************************************

NAME
====

   Devel::DebugInit::GDB - Perl extension for creating .gdbinit file from
C header file macros

SYNOPSIS
========

     use Devel::DebugInit::GDB;
     use Config;
     my $g = new Devel::DebugInit::GDB "filename => $Config{'archlib'}/CORE/perl.h";

     $g->write("~/perl5.00403/.gdbinit");

DESCRIPTION
===========

   This module is a backend for the GNU debugger, gdb, that is used
together with the generic Devel::DebugInit front end to produce an
initialization file for gdb. This module provides the output routines that
are specific for gdb. See Devel/DebugInit, for more
information.

METHODS
=======

write() =head2 write($filename)
-------------------------------

   This method outputs the macros to $filename, which defaults to
"./gdbinit".  It first writes out any macros without arguments (if
enabled, see `INTERNALS', see Devel/DebugInit, for more
info), and then it writes any macros with arguments.

scan($name,$macro)
------------------

   This is used by the print function to determine if $macro should be
printed or not. It returns 0 if the macro should NOT be printed.
Currently, the method rejects undefined macros (this is possible if the
user specified printing of local macros only), empty macros (typical
compiler flags like -DDEBUG, or #define linux), macros whose names begin
with '_', as well as any macro whose name is a built-in GDB command.

   This function can be overloaded by the user to more rigidly restrict
the output of print. For example:

     package myGDB;
     use Devel::DebugInit::GDB;
     @myGDB::ISA = (Devel::DebugInit::GDB);

     sub scan {
       my ($gdb,$key,$macro) = @_;

       #first give the superclass scan a chance
       return 0 unless $gdb->SUPER::scan(@_);

       # dont' print out any macros beginning with 'rfsf_'
       return 0 if $macro =~ /^rfsf_/;

       # print the rest
       return 1;
     }

AUTHOR
======

   Jason E. Stewart, jasons@cs.unm.edu

SEE ALSO
========

   perl(1), Devel::DebugInit(3).

Report exactly where Perl sawampersand
**************************************

NAME
====

   Devel::FindAmpersand - Report exactly where Perl sawampersand

SYNOPSIS
========

     use Devel::FindAmpersand ();

DESCRIPTION
===========

   Use this module only during development and wait for your script to
finish. It will report where your script gets infected by a sawampersand
operation.

SEE ALSO
========

   Devel::SawAmpersand, B::FindAmpersand

Utility for looking for perl objects that are not reclaimed.
************************************************************

NAME
====

   Devel::Leak - Utility for looking for perl objects that are not
reclaimed.

SYNOPSIS
========

     use Devel::Leak;
     ... setup code

     my $count = Devel::Leak::NoteSV($handle);

     ... code that may leak

     Devel::Leak::CheckSV($handle);

DESCRIPTION
===========

   Devel::Leak has two functions `NoteSV' and `CheckSV'.

   `NoteSV' walks the perl internal table of allocated SVs (scalar values)
- (which actually  contains arrays and hashes too), and records their
addresses in a table. It returns a count of these "things", and stores a
pointer to the table (which is obtained from the heap using malloc()) in
its argument.

   `CheckSV' is passed argument which holds a pointer to a table created by
`NoteSV'. It re-walks the perl-internals and calls sv_dump() for any
"things" which did not exist when `NoteSV' was called. It returns a count
of the number of "things" now allocated.

CAVEATS
=======

   Note that you need a perl built with -DDEBUGGING for sv_dump() to print
anything, but counts are valid in any perl.

   If new "things" *have* been created, `CheckSV' may (also) report
additional "things" which are allocated by the sv_dump() code.

HISTORY
=======

   This little utility module was part of Tk until the variable renaming
in perl5.005 made it clear that Tk had no business knowing this much about
the perl internals.

AUTHOR
======

   Nick Ing-Simmons <nick@ni-s.u-net.com>

memoize function calls
**********************

NAME
====

   *Devel::Memo* - memoize function calls

SYNOPSIS
========

     use Devel::Memo;
     sub number_cruncher {
       local(*tough)=new Devel::Memo sub($$@) {
         my ($arg1, $arg2, @others)=@_;
         ...calculate...
         return $some_val, $some_other_val;
       }, qw(-eq -equal -rest);
       my @result1=tough 17, [1, 2];
       my @result2=tough 15, {foo => 1}, 'bar';
       my @result3=tough 15, {foo => 1}, 'bar'; # Faster!
     }

DESCRIPTION
===========

   A *Devel::Memo* object is defined as a subroutine reference to do some
sort of calculation, together with a simple sort of prototype. The
elements of the prototype may be: *-eq*, indicating a simple scalar
argument (number or string); *-equal*, indicating an argument held in a
scalar but possibly containing references, which will be examined in a
recursive fashion; and *-rest*, meaning that zero or more extra arguments
may appear, which should be compared both in number, and individually as
with *-equal*.

   The object is just a blessed subroutine reference, so you can call it
directly or assign it to a typeglob to make it look like any other
function call. The difference is that the object maintains an internal
cache of previous invocations and their results, and returns a previous
result directly if a set of arguments is ever duplicated (as defined by
the "prototype", above). The cache is freed when the object leaves scope.

   The implementing function is always called in array context; if the
object is called in scalar context, the last value is returned.

Implementation
--------------

   *FreezeThaw* is used.

BUGS AND RESTRICTIONS
=====================

   There is no way to access instance data without changing this module,
as it is completely private to the code reference.

   Overhead in creating the hash key, etc. will make this module not worth
your while unless the operations to be memoized are fairly time-consuming.
An XSUB version would be nice...

   Any bugs in *FreezeThaw* will presumably affect this module.

   The use of *FreezeThaw::safeFreeze* actually oversteps *FreezeThaw*'s
documented guaranteed behavior in that it assumes that *safeFreeze* will
return the same result for structurally equivalent arguments. Currently
(*FreezeThaw* as in `ILYAZ/etext/etext1.6.2.tar.gz') this is in fact the
case, and it will probably remain so. If not, performance will suffer but
the results should not be incorrect.

AUTHORS
=======

   Jesse Glick, *jglick@sig.bsh.com*

SEE ALSO
========

   `FreezeThaw(3P)' in this node.

REVISION
========

   X<$Format: "`$Source$' last modified $Date$, release
$DevelMemoRelease$. $Copyright$"$> `Devel-Memo/lib/Devel/Memo.pm' last
modified Wed, 10 Dec 1997 17:58:09 -0500, release 0.004. Copyright (c)
1997 Strategic Interactive Group. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Perl extension to collect module use information
************************************************

NAME
====

   Devel::Modlist - Perl extension to collect module use information

SYNOPSIS
========

     perl -d:Modlist script.pl

DESCRIPTION
===========

   The *Devel::Modlist* utility is provided as a means by which to get a
quick run-down on which libraries and modules are being utilized by a
given script.

   Just as compiler systems like *gcc* provide dependancy information via
switches such as -M, *Devel::Modlist* is intended to assist script authors
in preparing dependancy information for potential users of their scripts.

USAGE
=====

   Usage of *Devel::Modlist* is simple. The primary method of invocation
is to use the -d option of Perl:

     perl -d:Modlist script.pl

   Alternately, one could use the -M option:

     perl -MDevel::Modlist script.pl

   In the case of this module, the two are identical save for the amount of
typing (and option passing, see below). It is not recommended that this
module be loaded directly by a script via the use keyword, as that would
cause the dependancy reporting after every invocation until it was removed
from the code.

OPTIONS
=======

   The following options may be specified to the package on the command
line. Current (as of July 2000) Perl versions (release version up to 5.6.0)
cannot accept options to the `-d:' flag as with the -M flag. Thus, to pass
an option one must use:

     perl -MDevel::Modlist=option1[,option2,...]

   Unfortunately, this inhibits the stop option detailed below. To use this
option, an invocation of:

     perl -d:Modlist -MDevel::Modlist=option1[,option2,...]

   does the trick, as the first invocation puts the interpreter in
debugging mode (necessary for stop to work) while the second causes the
options to be parsed and recorded by *Devel::Modlist*.

cpan
     Reduce the resulting list of modules by using the data maintained in
     the local CPAN configuration area. The CPAN module (see CPAN)
     maintains a very thorough representation of the contents of
     the archive, on a per-module basis.  Using this option means that if
     there are two or more modules that are parts of the same
     distribution, only one will be reported (the one with the shortest
     name). This is useful for generating a minimalist dependancy set that
     can in turn be fed to the CPAN install command to ensure that all
     needed modules are in fact present.

cpandist
     This is identical to the option above, with the exception that it
     causes the reported output to be the CPAN filename rather than the
     module name in the standard Perl syntax. This can also be fed to the
     CPAN shell, but it can also be used by other front-ends as a path
     component in fetching the requisite file from an archive site. Since
     the name contains the version number, this behaves as though
     noversion (see below) was also set. If both cpan and cpandist are
     set, this option (cpandist) takes precedence. If path is also
     specified, this option again takes precedence.

nocore
     Suppress the display of those modules that are a part of the Perl
     core. This is dependant on the Perl private library area not being an
     exact substring of the site-dependant library. The build process
     checks this for you prior to install.

noversion
     Suppress the inclusion of version information with the module names.
     If a module has defined its version by means of the accepted standard
     of declaring a variable $VERSION in the package namespace,
     *Devel::Modlist* finds this and includes it in the report by default.
     Use this option to override that default.

path
     Display the path and filename of each module instead of the module
     name. Useful for producing lists for later input to tools such as
     *rpm*.

stop
     Exit before the first actual program line is executed. This provides
     for fetching the dependancy list without actually running the full
     program. This has a drawback: if the program uses any of require,
     eval or other such mechanisms to load libraries after the compilation
     phase, these will not be reported.

AUTHOR
======

   Randy J. Ray <rjray@blackperl.com>, using idea and prototype code
provided by Tim Bunce <Tim.Bunce@ig.co.uk>

SEE ALSO
========

   perl(1).

Profile the internals of a Perl program
***************************************

NAME
====

   Devel::OpProf - Profile the internals of a Perl program

SYNOPSIS
========

     use Devel::OpProf qw(profile print_stats);
     ...
     profile(1);    # turn on profiling
     ...            # code to be profiled
     profile(0);    # turn off profiling
     ...
     print_stats;   # print out operator statistics

DESCRIPTION
===========

   This module lets perl keep a count of each internal operation in a
program so that you can profile your Perl code. The following functions
are exported.

profile(FLAG)
     Turns profiling on if FLAG is non-zero, off if FLAG is zero. The
     operator profile counts are only incremented whilst profiling is on.

stats
     Returns a reference to a hash containing the current profile counts.
     Each key in the hash is an operator description (e.g. "constant item",
     "addition" or "string comparison") and the corresponding value is the
     associated count.

print_stats
     Prints a formatted, sorted list of all operators with non-zero counts
     to stdout.

zero_stats
     Zeroes the profile counts of all operators.

op_count
     Returns an array of the raw profiling counts (indexed by opcode).
     This is mainly for internal use but may be useful for internals
     hackers: functions in the Opcode module may be helpful here.

BUGS
====

   Part of the internal operations involved in statements such as
`profile(1)' and `profile(0)' affect the profiling counts themselves.
This should be unimportant if the code being profiled is non-trivial.

AUTHOR
======

   Malcolm Beattie, mbeattie@sable.ox.ac.uk.

A data debugging tool for the XS programmer
*******************************************

NAME
====

   Devel::Peek - A data debugging tool for the XS programmer

SYNOPSIS
========

     use Devel::Peek;
     Dump( $a );
     Dump( $a, 5 );
     DumpArray( 5, $a, $b, ... );
     	mstat "Point 5";

DESCRIPTION
===========

   Devel::Peek contains functions which allows raw Perl datatypes to be
manipulated from a Perl script.  This is used by those who do XS
programming to check that the data they are sending from C to Perl looks
as they think it should look.  The trick, then, is to know what the raw
datatype is supposed to look like when it gets to Perl.  This document
offers some tips and hints to describe good and bad raw data.

   It is very possible that this document will fall far short of being
useful to the casual reader.  The reader is expected to understand the
material in the first few sections of Perlguts (perl.info).

   Devel::Peek supplies a `Dump()' function which can dump a raw Perl
datatype, and `mstat("marker")' function to report on memory usage (if
perl is compiled with corresponding option).  The function DeadCode()
provides statistics on the data "frozen" into inactive CV.  Devel::Peek
also supplies `SvREFCNT()', `SvREFCNT_inc()', and `SvREFCNT_dec()' which
can query, increment, and decrement reference counts on SVs.  This
document will take a passive, and safe, approach to data debugging and for
that it will describe only the `Dump()' function.  For format of output of
mstats() see `Using `$ENV{PERL_DEBUG_MSTATS}', see Perldebug (perl.info),'.

   Function `DumpArray()' allows dumping of multiple values (useful when
you need to analize returns of functions).

   The global variable $Devel::Peek::pv_limit can be set to limit the
number of character printed in various string values.  Setting it to 0
means no limit.

EXAMPLES
========

   The following examples don't attempt to show everything as that would
be a monumental task, and, frankly, we don't want this manpage to be an
internals document for Perl.  The examples do demonstrate some basics of
the raw Perl datatypes, and should suffice to get most determined people
on their way.  There are no guidewires or safety nets, nor blazed trails,
so be prepared to travel alone from this point and on and, if at all
possible, don't fall into the quicksand (it's bad for business).

   Oh, one final bit of advice: take Perlguts (perl.info),
with you.  When you return we expect to see it well-thumbed.

A simple scalar string
----------------------

   Let's begin by looking a simple scalar which is holding a string.

     use Devel::Peek;
     $a = "hello";
     Dump $a;

   The output:

     SV = PVIV(0xbc288)
       REFCNT = 1
       FLAGS = (POK,pPOK)
       IV = 0
       PV = 0xb2048 "hello"\0
       CUR = 5
       LEN = 6

   This says `$a' is an SV, a scalar.  The scalar is a PVIV, a string.
Its reference count is 1.  It has the `POK' flag set, meaning its current
PV field is valid.  Because POK is set we look at the PV item to see what
is in the scalar.  The \0 at the end indicate that this PV is properly
NUL-terminated.  If the FLAGS had been IOK we would look at the IV item.
CUR indicates the number of characters in the PV.  LEN indicates the
number of bytes requested for the PV (one more than CUR, in this case,
because LEN includes an extra byte for the end-of-string marker).

A simple scalar number
----------------------

   If the scalar contains a number the raw SV will be leaner.

     use Devel::Peek;
     $a = 42;
     Dump $a;

   The output:

     SV = IV(0xbc818)
       REFCNT = 1
       FLAGS = (IOK,pIOK)
       IV = 42

   This says `$a' is an SV, a scalar.  The scalar is an IV, a number.  Its
reference count is 1.  It has the `IOK' flag set, meaning it is currently
being evaluated as a number.  Because IOK is set we look at the IV item to
see what is in the scalar.

A simple scalar with an extra reference
---------------------------------------

   If the scalar from the previous example had an extra reference:

     use Devel::Peek;
     $a = 42;
     $b = \$a;
     Dump $a;

   The output:

     SV = IV(0xbe860)
       REFCNT = 2
       FLAGS = (IOK,pIOK)
       IV = 42

   Notice that this example differs from the previous example only in its
reference count.  Compare this to the next example, where we dump $b
instead of `$a'.

A reference to a simple scalar
------------------------------

   This shows what a reference looks like when it references a simple
scalar.

     use Devel::Peek;
     $a = 42;
     $b = \$a;
     Dump $b;

   The output:

     SV = RV(0xf041c)
       REFCNT = 1
       FLAGS = (ROK)
       RV = 0xbab08
     SV = IV(0xbe860)
       REFCNT = 2
       FLAGS = (IOK,pIOK)
       IV = 42

   Starting from the top, this says $b is an SV.  The scalar is an RV, a
reference.  It has the `ROK' flag set, meaning it is a reference.  Because
ROK is set we have an RV item rather than an IV or PV.  Notice that Dump
follows the reference and shows us what $b was referencing.  We see the
same `$a' that we found in the previous example.

   Note that the value of RV coincides with the numbers we see when we
stringify $b. The addresses inside RV() and IV() are addresses of `X***'
structure which holds the current state of an SV. This address may change
during lifetime of an SV.

A reference to an array
-----------------------

   This shows what a reference to an array looks like.

     use Devel::Peek;
     $a = [42];
     Dump $a;

   The output:

     SV = RV(0xf041c)
       REFCNT = 1
       FLAGS = (ROK)
       RV = 0xb2850
     SV = PVAV(0xbd448)
       REFCNT = 1
       FLAGS = ()
       IV = 0
       NV = 0
       ARRAY = 0xb2048
       ALLOC = 0xb2048
       FILL = 0
       MAX = 0
       ARYLEN = 0x0
       FLAGS = (REAL)
     Elt No. 0 0xb5658
     SV = IV(0xbe860)
       REFCNT = 1
       FLAGS = (IOK,pIOK)
       IV = 42

   This says `$a' is an SV and that it is an RV.  That RV points to
another SV which is a PVAV, an array.  The array has one element, element
zero, which is another SV. The field FILL above indicates the last element
in the array, similar to `$#$a'.

   If `$a' pointed to an array of two elements then we would see the
following.

     use Devel::Peek 'Dump';
     $a = [42,24];
     Dump $a;

   The output:

     SV = RV(0xf041c)
       REFCNT = 1
       FLAGS = (ROK)
       RV = 0xb2850
     SV = PVAV(0xbd448)
       REFCNT = 1
       FLAGS = ()
       IV = 0
       NV = 0
       ARRAY = 0xb2048
       ALLOC = 0xb2048
       FILL = 0
       MAX = 0
       ARYLEN = 0x0
       FLAGS = (REAL)
     Elt No. 0  0xb5658
     SV = IV(0xbe860)
       REFCNT = 1
       FLAGS = (IOK,pIOK)
       IV = 42
     Elt No. 1  0xb5680
     SV = IV(0xbe818)
       REFCNT = 1
       FLAGS = (IOK,pIOK)
       IV = 24

   Note that `Dump' will not report all the elements in the array, only
several first (depending on how deep it already went into the report tree).

A reference to a hash
---------------------

   The following shows the raw form of a reference to a hash.

     use Devel::Peek;
     $a = {hello=>42};
     Dump $a;

   The output:

     SV = RV(0xf041c)
       REFCNT = 1
       FLAGS = (ROK)
       RV = 0xb2850
     SV = PVHV(0xbd448)
       REFCNT = 1
       FLAGS = ()
       NV = 0
       ARRAY = 0xbd748
       KEYS = 1
       FILL = 1
       MAX = 7
       RITER = -1
       EITER = 0x0
     Elt "hello" => 0xbaaf0
     SV = IV(0xbe860)
       REFCNT = 1
       FLAGS = (IOK,pIOK)
       IV = 42

   This shows `$a' is a reference pointing to an SV.  That SV is a PVHV, a
hash. Fields RITER and EITER are used by ``each' in this node'.

Dumping a large array or hash
-----------------------------

   The `Dump()' function, by default, dumps up to 4 elements from a
toplevel array or hash.  This number can be increased by supplying a
second argument to the function.

     use Devel::Peek;
     $a = [10,11,12,13,14];
     Dump $a;

   Notice that `Dump()' prints only elements 10 through 13 in the above
code.  The following code will print all of the elements.

     use Devel::Peek 'Dump';
     $a = [10,11,12,13,14];
     Dump $a, 5;

A reference to an SV which holds a C pointer
--------------------------------------------

   This is what you really need to know as an XS programmer, of course.
When an XSUB returns a pointer to a C structure that pointer is stored in
an SV and a reference to that SV is placed on the XSUB stack.  So the
output from an XSUB which uses something like the T_PTROBJ map might look
something like this:

     SV = RV(0xf381c)
       REFCNT = 1
       FLAGS = (ROK)
       RV = 0xb8ad8
     SV = PVMG(0xbb3c8)
       REFCNT = 1
       FLAGS = (OBJECT,IOK,pIOK)
       IV = 729160
       NV = 0
       PV = 0
       STASH = 0xc1d10       "CookBookB::Opaque"

   This shows that we have an SV which is an RV.  That RV points at another
SV.  In this case that second SV is a PVMG, a blessed scalar.  Because it
is blessed it has the OBJECT flag set.  Note that an SV which holds a C
pointer also has the `IOK' flag set.  The STASH is set to the package name
which this SV was blessed into.

   The output from an XSUB which uses something like the T_PTRREF map,
which doesn't bless the object, might look something like this:

     SV = RV(0xf381c)
       REFCNT = 1
       FLAGS = (ROK)
       RV = 0xb8ad8
     SV = PVMG(0xbb3c8)
       REFCNT = 1
       FLAGS = (IOK,pIOK)
       IV = 729160
       NV = 0
       PV = 0

A reference to a subroutine
---------------------------

   Looks like this:

     SV = RV(0x798ec)
       REFCNT = 1
       FLAGS = (TEMP,ROK)
       RV = 0x1d453c
     SV = PVCV(0x1c768c)
       REFCNT = 2
       FLAGS = ()
       IV = 0
       NV = 0
       COMP_STASH = 0x31068  "main"
       START = 0xb20e0
       ROOT = 0xbece0
       XSUB = 0x0
       XSUBANY = 0
       GVGV::GV = 0x1d44e8   "MY" :: "top_targets"
       FILE = "(eval 5)"
       DEPTH = 0
       PADLIST = 0x1c9338

   This shows that

   * the subroutine is not an XSUB (since START and ROOT are non-zero, and
     XSUB is zero);

   * that it was compiled in the package main;

   * under the name `MY::top_targets';

   * inside a 5th eval in the program;

   * it is not currently executed (see DEPTH);

   * it has no prototype (`PROTOTYPE' field is missing).

EXPORTS
=======

   `Dump', `mstat', `DeadCode', `DumpArray', `DumpWithOP' and `DumpProg'
by default. Additionally available SvREFCNT, SvREFCNT_inc and SvREFCNT_dec.

BUGS
====

   Readers have been known to skip important parts of Perlguts (perl.info),
causing much frustration for all.

AUTHOR
======

   Ilya Zakharevich	ilya@math.ohio-state.edu

   Copyright (c) 1995-98 Ilya Zakharevich. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

   Author of this software makes no claim whatsoever about suitability,
reliability, edability, editability or usability of this product, and
should not be kept liable for any damage resulting from the use of it. If
you can use it, you are in luck, if not, I should not be kept responsible.
Keep a handy copy of your backup tape at hand.

SEE ALSO
========

   See Perlguts (perl.info), and Perlguts (perl.info),
again.

Module inlining and other Perl source manipulations
***************************************************

NAME
====

   Devel::PreProcessor - Module inlining and other Perl source
manipulations

SYNOPSIS
========

   From a command line,

     sh> perl Devel/PreProcessor.pm -Flags sourcefile > targetfile

   Or in a Perl script,

     use Devel::PreProcessor qw( Flags );

     select(OUTPUTFH);
     Devel::PreProcessor::parse_file( $source_pathname );

DESCRIPTION
===========

   This package processes Perl source files and outputs a modified version
acording to several user-setable option flags, as detailed below.

   Each of the flag names listed below can be used as above, with a hyphen
on the command line, or as one of the arguments in an import statement.
Each of these flags are mapped to the scalar package variable of the same
name.

Includes
     If true, parse_file will attempt to replace require, use and no
     statements with inline declarations containg the source of the
     relevant library found in the current @INC. The resulting script
     should operate identically and no longer be dependant on external
     libraries (but see compatibility note below).

     If the corresponding file can not be located, the statements are left
     unchanged in the source; numeric perl version requirements are handled
     the same way.

     If a `use libs ...' statement is encountered in the source, the
     library path arguments are evaluated and pushed onto @INC at run-time
     to enable inclusion of libraries from these paths.

     Unless the file explicitly use's or require's AutoLoader, information
     after `__END__' is not included in the resultant file. Information
     after `__DATA__' is also discarded, except for the first, outermost
     source file.

ShowFileBoundaries
     If true, comment lines will be inserted delimiting the start and end
     of each inlined file.

StripPods
     If true, parse_file will not include POD from the source files. All
     groups of lines resembling the following will be discarded:

          =(pod|head1|head2)
          ...
          =cut

StripBlankLines
     If true, parse_file will skip lines that are empty, or that contain
     only whitespace.

StripComments
     If true, parse_file will not include full-line comments from the
     source files. Only lines that start with a pound sign are discarded;
     this behaviour might not match Perl's parsing rules in some cases,
     such as multiline strings.

Conditionals
     If true, parse_file will utilize a simple conditional inclusion
     scheme, as follows.

          #__CONDITIONAL__ if expr
          ...
          #__CONDITIONAL__ endif

     The provided Perl expression is evaluated, and unless it is true,
     everything up to the next endif declaration is replaced with empty
     lines. In order to allow the default behavour to be provided when
     running the raw files, comment out lines in non-default branches with
     the following:

          #__CONDITIONAL__ ...

     Empty lines are used  in place of skipped blocks to make line numbers
     come out evenly, but conditional use or require statements will throw
     the count off, as we don't pad by the size of the file that would have
     been in-lined.

     The conditional functionality can be combined with Perl's -s switch,
     which allows you to set flags on the command line, such as:

          perl -s Devel/PreProcessor.pm -Conditionals -Switch filter.test

     You can use any name for your switch, and the matching scalar variable
     will be set true; the following code will only be used if you supply
     the argument as shown below.

          #__CONDITIONAL__ if $Switch
          #__CONDITIONAL__   print "you hit the switch!\n";
          #__CONDITIONAL__ endif

EXAMPLES
========

   To inline all used modules:

     perl -s Devel/PreProcessor.pm -Includes foo.pl > foo_complete.pl

   To count the lines of Perl source in a file, run the preprocessor from
a shell with the following options

     perl -s Devel/PreProcessor.pm -StripComments -StripPods \
     -StripBlankLines foo.pl | wc -l

BUGS AND CAVEATS
================

Compatibility: Includes
     Libraries inlined with Includes may not be appropriate on another
     system; for example, if Config is inlined, the script may fail if run
     on a platform other than that on which it was built. This problem can
     be minimized by adjusting the search path to not include modules in
     the version- or architecture-specific library trees, but you will
     then need to ensure that those modules are available on the execution
     platform.

Limitation: Pragmas
     While some pragmas are known to work, including use vars, problems may
     pop up with others. In particular, use strict and no strict pragmas
     are removed from the resulting source, because their scoping changes
     in a single-file context, usually with fatal results.

Bug: Multi-line use statements not handled
     Should support newline in import blocks for multiline use statements.

Limitation: Module __DATA__ contents lost
     Few modules place anything other than POD in a __DATA__ section, much
     less ever try to read from it, so this hasn't been a priority to fix.

Limitation: binary files not included
     There's not much we can do about XSub/SO/PLL files.

PREREQUISITES AND INSTALLATION
==============================

   This package should run on any standard Perl 5 installation.

   You may retrieve this package from the below URL:
http://www.evoscript.com/dist/

   To install this package, download and unpack the distribution archive,
then:

   * `perl Makefile.PL'

   * make test

   * make install

STATUS AND SUPPORT
==================

   This release of Devel::PreProcessor is intended primarily for public
review and feedback, but is stable enough for production use. It has been
tested in several environments and no major problems have been discovered,
but it should be considered "beta" pending further feedback.

     Name            DSLI  Description
     --------------  ----  ---------------------------------------------
     Devel::
     ::PreProcessor  bdpf  Module inlining and other Perl source manipulations

   Further information and support for this module is available at
<www.evoscript.com>.

   Please report bugs or other problems to <bugs@evoscript.com>.

AUTHORS AND COPYRIGHT
=====================

   Copyright 1998, 1999 Evolution Online Systems, Inc. <www.evolution.com>

   You may use this software for free under the terms of the Artistic
License.

   Contributors: M. Simon Cavalletto <simonm@evolution.com> and Del
Merritt <dmerritt@intranetics.com>, with Win32 debugging assistance from
Randy Roy.

   Derived from filter.pl, as provided by ActiveWare <www.activestate.com>

Perl extension querying sawampersand variable
*********************************************

NAME
====

   Devel::SawAmpersand - Perl extension querying sawampersand variable

SYNOPSIS
========

     use Devel::SawAmpersand qw(sawampersand);

     sawampersand();

DESCRIPTION
===========

   There's a global variable in the perl source, called sawampersand. It
gets set to true in that moment in which the parser sees one of $`, $',
and $&. It never can be set to false again. Trying to set it to false
breaks the handling of the $`, $&, and $' completely.

   If the global variable `sawampersand' is set to true, all subsequent RE
operations will be accompanied by massive in-memory copying, because there
is nobody in the perl source who could predict, *when* the (necessary)
copy for the ampersand family will be needed. So all subsequent REs are
considerable slower than necessary.

   There are at least three impacts for developers:

   * never use $& and friends in a library.

   * Never "use English" in a library, because it contains the three bad
     fellows.

   * before you release a module or program, check if sawampersand is set
     by any of the modules you use or require.

Workaround
----------

   Fortunately perl offers easy to use alternatives, that is

     instead of this              you can use this

     $`   of   /pattern/          $1   of  /(.*?)pattern/s
     $&   of   /pattern/          $1   of  /(pattern)/
     $'   of   /pattern/          $+   of  /pattern(.*)/s

   In general, apply `/^(.*)(pattern)(.*)$/s' and use $1 for $`, $2 for $&
and $+ for $' ($+ is not dependent on the number of parens in the original
pattern). Note that the `/s' switch can alter the meaning of . in your
pattern.

Future Directions
-----------------

     From: jmm@elegant.com (John Macdonald)
     Date: Wed, 24 Dec 1997 10:49:56 -0500

   How about adding an option to matches/substitutes that explicitly sets
$`, $&, and $'?  When this new option is seen, sawampersand will be set
for the duration of the match and then turned off.  That causes the
expense for unflagged matches to go back to normal and only flagged
matches incur the extra expense and they would be the ones that actually
need it.  (Or does sawampersand need to affect the compilation of the RE's
too?)

AUTHOR
======

   Andreas Koenig, special thanks to Johan Vromans and John Macdonald for
parts of the manpage and to Doug MacEachern for the FindAmpersand.

SEE ALSO
========

   Devel::FindAmpersand, B::FindAmpersand

generate stubs for a SelfLoading module
***************************************

NAME
====

   Devel::SelfStubber - generate stubs for a SelfLoading module

SYNOPSIS
========

   To generate just the stubs:

     use Devel::SelfStubber;
     Devel::SelfStubber->stub('MODULENAME','MY_LIB_DIR');

   or to generate the whole module with stubs inserted correctly

     use Devel::SelfStubber;
     $Devel::SelfStubber::JUST_STUBS=0;
     Devel::SelfStubber->stub('MODULENAME','MY_LIB_DIR');

   MODULENAME is the Perl module name, e.g. Devel::SelfStubber, NOT
'Devel/SelfStubber' or 'Devel/SelfStubber.pm'.

   MY_LIB_DIR defaults to '.' if not present.

DESCRIPTION
===========

   Devel::SelfStubber prints the stubs you need to put in the module
before the __DATA__ token (or you can get it to print the entire module
with stubs correctly placed). The stubs ensure that if a method is called,
it will get loaded. They are needed specifically for inherited autoloaded
methods.

   This is best explained using the following example:

   Assume four classes, A,B,C & D.

   A is the root class, B is a subclass of A, C is a subclass of B, and D
is another subclass of A.

     A
                            / \
                           B   D
                          /
                         C

   If D calls an autoloaded method 'foo' which is defined in class A, then
the method is loaded into class A, then executed. If C then calls method
'foo', and that method was reimplemented in class B, but set to be
autoloaded, then the lookup mechanism never gets to the AUTOLOAD mechanism
in B because it first finds the method already loaded in A, and so
erroneously uses that. If the method foo had been stubbed in B, then the
lookup mechanism would have found the stub, and correctly loaded and used
the sub from B.

   So, for classes and subclasses to have inheritance correctly work with
autoloading, you need to ensure stubs are loaded.

   The SelfLoader can load stubs automatically at module initialization
with the statement 'SelfLoader->load_stubs()';, but you may wish to avoid
having the stub loading overhead associated with your initialization
(though note that the SelfLoader::load_stubs method will be called sooner
or later - at latest when the first sub is being autoloaded). In this
case, you can put the sub stubs before the __DATA__ token. This can be
done manually, but this module allows automatic generation of the stubs.

   By default it just prints the stubs, but you can set the global
$Devel::SelfStubber::JUST_STUBS to 0 and it will print out the entire
module with the stubs positioned correctly.

   At the very least, this is useful to see what the SelfLoader thinks are
stubs - in order to ensure future versions of the SelfStubber remain in
step with the SelfLoader, the SelfStubber actually uses the SelfLoader to
determine which stubs are needed.

per-line Perl profiler
**********************

NAME
====

   Devel::SmallProf - per-line Perl profiler

SYNOPSIS
========

     perl5 -d:SmallProf test.pl

DESCRIPTION
===========

   The Devel::SmallProf profiler is focused on the time taken for a
program run on a line-by-line basis.  It is intended to be as "small" in
terms of impact on the speed and memory usage of the profiled program as
possible and also in terms of being simple to use.  Those statistics are
placed in the file `smallprof.out' in the following format:

     <num> <time> <ctime> <line>:<text>

   where <num> is the number of times that the line was executed, <time>
is the amount of "wall time" (time according the the clock on the wall vs.
cpu time) spent executing it, <ctime> is the amount of cpu time expended
on it and <line> and <text> are the line number and the actual text of the
executed line (read from the file).

   The package uses the debugging hooks in Perl and thus needs the -d
switch, so to profile test.pl, use the command:

     perl5 -d:SmallProf test.pl

   Once the script is done, the statistics in `smallprof.out' can be
sorted to show which lines took the most time.  The output can be sorted
to find which lines take the longest, either with the sort command:

     sort -k 2nr,2 smallprof.out | less

   or a perl script:

     open(PROF,"smallprof.out");
     @sorted = sort {(split(/\s+/,$b))[2] <=>
                             (split(/\s+/,$a))[2]} <PROF>;
             close PROF;
     print join('',@sorted);

NOTES
=====

   * The "wall time" readings come from Time::HiRes and are reasonably
     useful, at least on my system.  The cpu times come from the 'times'
     built-in and the granularity is not necessarily as small as with the
     wall time.  On some systems this column may be useful.  On others it
     may not.

   * SmallProf does attempt to make up for its shortcomings by subtracting
     a small amount from each timing (null time compensation).  This
     should help somewhat with the accuracy.

   * SmallProf depends on the Time::HiRes package to do its timings.  It
     claims to require version 1.20, but may work with earlier versions,
     depending on your platform.

OPTIONS
=======

   SmallProf has 3 variables which can be used during your script to
affect what gets profiled.

   * If you do not wish to see lines which were never called, set the
     variable `$DB::drop_zeros = 1'.  With `drop_zeros' set, SmallProf can
     be used for basic coverage analysis.

   * To turn off profiling for a time, insert a `$DB::profile = 0' into
     your code (profiling may be turned back on with `$DB::profile = 1').
     All of the time between profiling being turned off and back on again
     will be lumped together and reported on the `$DB::profile = 0' line.
     This can be used to summarize a subroutine call or a chunk of code.

   * To only profile code in a certain package, set the `%DB::packages'
     array.  For example, to see only the code in packages main and
     `Test1', do this:

          %DB::packages = ( 'main' => 1, 'Test1' => 1 );

   * These variables can be put in a file called `.smallprof' in the
     current directory.  For example, a `.smallprof' containing

          $DB::drop_zeros = 1;
          $DB::profile = 0;

     will set SmallProf to not report lines which are never touched for
     any file profiled in that directory and will set profiling off
     initially (presumably to be turned on only for a small portion of
     code).

INSTALLATION
============

   Just the usual

     perl Makefile.PL
     make
     make test
     make install

   and should install fine via the CPAN module.

BUGS
====

   Subroutine calls are currently not under the control of %DB::packages.
This should not be a great inconvenience in general.

   The handling of evals is bad news.  This is due to Perl's handling of
evals under the -d flag.  For certain evals, caller() returns '(eval n)'
for the filename and for others it doesn't.  For some of those which it
does, the array `@{'_<filename'}' contains the code of the eval.  For
others it doesn't.  Sometime, when I've an extra tuit or two, I'll figure
out why and how I can compensate for this.  (Note: 5.6.0 made some
debugging changes.  This may now be fixed, I'm not sure).

   SmallProf must be invoked from the command line.  If it is included on
the shebang line, the file in which it is included will not be visible in
the symbol table.  Profiling will continue as expected, but the contents
of the source lines will not be listed.  This is new as of 5.6.0.

   Comments, advice and questions are welcome.  If you see inefficent
stuff in this module and have a better way, please let me know.

AUTHOR   Ted Ashton <ashted@southern.edu>   SmallProf was developed from code originally posted to usenet by Philippe Verdret <philippe.verdret@sonovision-itep.fr>.  Special thanks to Geoffrey Broadwell <habusan2@sprynet.com> for his assistance on the Win32 platform and to Philippe for his patient assistance in testing and  debugging.   Copyright (c) 1997 Ted Ashton   This module is free software and can be redistributed and/or modified under the same terms as Perl itself.
=============================================================================================================================================================================================================================================================================================================================================================================================================================================================================================

SEE ALSO
========

   See Devel/DProf, Time/HiRes.

Stack trace and stack trace frame objects
*****************************************

NAME
====

   Devel::StackTrace - Stack trace and stack trace frame objects

SYNOPSIS
========

     use Devel::StackTrace;

     my $trace = Devel::StackTrace->new;

     print $trace->as_string; # like carp

     # from top (most recent) of stack to bottom.
     while (my $frame = $trace->next_frame)
     {
         print "Has args\n" if $f->hasargs;
     }

     # from bottom (least recent) of stack to top.
     while (my $frame = $trace->prev_frame)
     {
         print "Sub: ", $f->subroutine, "\n";
     }

DESCRIPTION
===========

   The Devel::StackTrace module contains two classes, Devel::StackTrace
and Devel::StackTraceFrame.  The goal of this object is to encapsulate the
information that can found through using the caller() function, as well as
providing a simple interface to this data.

   The Devel::StackTrace object contains a set of Devel::StackTraceFrame
objects, one for each level of the stack.  The frames contain all the data
available from caller() as of Perl 5.00503.  There are changes in Perl
5.6.0 that have yet to be incorporated.

   This code was created to support my `Exception::Class::Base' in this
node class (part of Exception::Class) but may be useful in other contexts.

'TOP' AND 'BOTTOM' OF THE STACK
===============================

   When describing the methods of the trace object, I use the words 'top'
and 'bottom'.  In this context, the 'top' frame on the stack is the most
recent frame and the 'bottom' is the least recent.

   Here's an example:

     foo();  # bottom frame is here

     sub foo
     {
        bar();
     }

     sub bar
     {
        Devel::StackTrace->new;  # top frame is here.
     }

Devel::StackTrace METHODS
=========================

   * new(%named_params)

     Returns a new Devel::StackTrace object.

     Takes the following parameters:

   * - ignore_package => $package_name OR \@package_names Any frames where
     the package is one of these packages will not be on the stack.

   * - ignore_class => $package_name OR \@package_names Any frames where
     the package is a subclass of one of these packages (or is the same
     package) will not be on the stack.

     Devel::StackTrace internally adds itself to the 'ignore_package'
     parameter, meaning that the Devel::StackTrace package is *ALWAYS*
     ignored.  However, if you create a subclass of Devel::StackTrace it
     will not be ignored.

   * next_frame

     Returns the next Devel::StackTraceFrame object down on the stack.  If
     it hasn't been called before it returns the first frame.  It returns
     undef when it reaches the bottom of the stack and then resets its
     pointer so the next call to `next_frame' or `prev_frame' will work
     properly.

   * prev_frame

     Returns the next Devel::StackTraceFrame object up on the stack.  If it
     hasn't been called before it returns the last frame.  It returns undef
     when it reaches the top of the stack and then resets its pointer so
     pointer so the next call to `next_frame' or `prev_frame' will work
     properly.

   * reset_pointer

     Resets the pointer so that the next call `next_frame' or `prev_frame'
     will start at the top or bottom of the stack, as appropriate.

   * frames

     Returns a list of Devel::StackTraceFrame objects.  The order they are
     returned is from top (most

   * frame ($index)

     Given an index, returns the relevant frame or undef if there is not
     frame at that index.  The index is exactly like a Perl array.  The
     first frame is 0 and negative indexes are allowed.

   * frame_count

     Returns the number of frames in the trace object.

   * as_string

     Calls as_string on each frame from top to bottom, producing output
     quite similar to the Carp module's cluck/confess methods.

Devel::StackTraceFrame METHODS
==============================

   See the `caller' in this node documentation for more information on
what these methods return.

   * package

   * filename

   * line

   * subroutine

   * hasargs

   * wantarray

   * evaltext

     Returns undef if the frame was not part of an eval.

   * is_require

     Returns undef if the frame was not part of a require.

   * args

     Returns the arguments passed to the frame.  Note that any arguments
     that are references are returned as references, not copies.

Perl 5.6.0 and greater _ONLY_
-----------------------------

   * hints

   * bitmask

AUTHOR
======

   Dave Rolsky, <autarch@urth.org>

SEE ALSO
========

   Exception::Class

dump symbol names or the symbol table
*************************************

NAME
====

   Devel::Symdump - dump symbol names or the symbol table

SYNOPSIS
========

     # Constructor
     require Devel::Symdump;
     @packs = qw(some_package another_package);
     $obj = Devel::Symdump->new(@packs);        # no recursion
     $obj = Devel::Symdump->rnew(@packs);       # with recursion

     # Methods
     @array = $obj->packages;
     @array = $obj->scalars;
     @array = $obj->arrays;
     @array = $obj->hashs;
     @array = $obj->functions;
     @array = $obj->filehandles;  # deprecated, use ios instead
     @array = $obj->dirhandles;   # deprecated, use ios instead
     @array = $obj->ios;
     @array = $obj->unknowns;

     $string = $obj->as_string;
     $string = $obj->as_HTML;
     $string = $obj1->diff($obj2);

     $string = Devel::Symdump->isa_tree;    # or $obj->isa_tree
     $string = Devel::Symdump->inh_tree;    # or $obj->inh_tree

     # Methods with autogenerated objects
     # all of those call new(@packs) internally
     @array = Devel::Symdump->packages(@packs);
     @array = Devel::Symdump->scalars(@packs);
     @array = Devel::Symdump->arrays(@packs);
     @array = Devel::Symdump->hashes(@packs);
     @array = Devel::Symdump->functions(@packs);
     @array = Devel::Symdump->ios(@packs);
     @array = Devel::Symdump->unknowns(@packs);

Incompatibility with versions before 2.00
-----------------------------------------

   Perl 5.003 already offered the opportunity to test for the individual
slots of a GLOB with the *GLOB{XXX} notation. Devel::Symdump version 2.00
uses this method internally which means that the type of undefined values
is recognized in general. Previous versions couldn't determine the type of
undefined values, so the slot unknowns was invented. From version 2.00
this slot is still present but will usually not contain any elements.

   The interface has changed slightly between the perl versions 5.003 and
5.004. To be precise, from perl5.003_11 the names of the members of a GLOB
have changed. IO is the internal name for all kinds of input-output
handles while `FILEHANDLE' and `DIRHANDLE' are deprecated.

   `Devel::Symdump' accordingly introduces the new method ios() which
returns filehandles and directory handles. The old methods filehandles()
and dirhandles() are still supported for a transitional period.  They will
probably have to go in future versions.

DESCRIPTION
===========

   This little package serves to access the symbol table of perl.

`Devel::Symdump->rnew(@packages)'
---------------------------------

   returns a symbol table object for all subtrees below @packages.  Nested
Modules are analyzed recursively. If no package is given as argument, it
defaults to main. That means to get the whole symbol table, just do a
`rnew' without arguments.

`Devel::Symdump->new(@packages)'
--------------------------------

   does not go into recursion and only analyzes the packages that are
given as arguments.

   The methods packages(), scalars(), arrays(), hashes(), functions(),
ios(), and unknowns() each return an array of fully qualified symbols of
the specified type in all packages that are held within a Devel::Symdump
object, but without the leading `$', `@' or %.  In a scalar context, they
will return the number of such symbols.  Unknown symbols are usually
either formats or variables that haven't yet got a defined value.

   As_string() and as_HTML() return a simple string/HTML representations
of the object.

   Diff() prints the difference between two Devel::Symdump objects in
human readable form. The format is similar to the one used by the
as_string method.

   Isa_tree() and inh_tree() both return a simple string representation of
the current inheritance tree. The difference between the two methods is
the direction from which the tree is viewed: top-down or bottom-up. As I'm
sure, many users will have different expectation about what is top and
what is bottom, I'll provide an example what happens when the Socket
module is loaded:

% print Devel::Symdump->inh_tree
          AutoLoader
                  DynaLoader
                          Socket
          DynaLoader
                  Socket
          Exporter
                  Carp
                  Config
                  Socket

     The inh_tree method shows on the left hand side a package name and
     indented to the right the packages that use the former.

% print Devel::Symdump->isa_tree
          Carp
                  Exporter
          Config
                  Exporter
          DynaLoader
                  AutoLoader
          Socket
                  Exporter
                  DynaLoader
                          AutoLoader

     The isa_tree method displays from left to right ISA relationships, so
     Socket IS A DynaLoader and DynaLoader IS A AutoLoader. (Actually, they
     were at the time this manpage was written)

   You may call both methods, isa_tree() and inh_tree(), with an object.
If you do that, the object will store the output and retrieve it when you
call the same method again later. The typical usage would be to use them
as class methods directly though.

SUBCLASSING
===========

   The design of this package is intentionally primitive and allows it to
be subclassed easily. An example of a (maybe) useful subclass is
Devel::Symdump::Export, a package which exports all methods of the
Devel::Symdump package and turns them into functions.

AUTHORS
=======

   Andreas Koenig `<andk@cpan.org>' and Tom Christiansen
`<tchrist@perl.com>'. Based on the old `dumpvar.pl' by Larry Wall.

Track and report execution time for parts of code
*************************************************

NAME
====

   Devel::Timer - Track and report execution time for parts of code

SYNOPSIS
========

     use Devel::Timer;

     my $t = new Devel::Timer();

     $t->mark("first db query");

     ## do some work

     $t->mark("second db query");

     ## do some more work

     $t->mark("end of second db query");

     $t->report();

DESCRIPTION
===========

   Devel::Timer allows developers to accurately time how long a specific
piece of code takes to execute.  This can be helpful in locating the
slowest parts of an existing application.

   First, the Devel::Timer module is used and instantiated.

     use Devel::Timer;

     my $t = new Devel::Timer();

   Second, markers are placed before and after pieces of code that need to
be timed.  For this example, we are profiling the methods get_user_score()
and get_average_user_score().

     $t->mark("first db query");
     &get_user_score($user);

     $t->mark("second db query");
     &get_average_user_score();

   Finally, at the end of the code that you want to profile, and end marker
is place, and a report is generated on stderr.

     $t->mark("END");
     $t->report();

   Sample report:

     Devel::Timer Report -- Total time: 0.3464 secs
     Interval  Time    Percent
     ----------------------------------------------
     02 -> 03  0.3001  86.63%  second db query -> END
     01 -> 02  0.0461  13.30%  first db query -> second db query
     00 -> 01  0.0002   0.07%  INIT -> first db query

   The report is output using the method Devel::Timer::print() which
currently just prints to stderr.  If you want to send the output to a
custom location you can override the print() method.  The initialize() and
shutdown() methods can also overridden if you want to open and close log
files or database connections.

   e.g.

   package MyTimer;

   use strict; use Devel::Timer; use vars qw(@ISA);

   @ISA = ("Devel::Timer");

   sub initialize {     my $log = "/tmp/timer.log";     open(LOG,
">>$log") or die("Unable to open [$log] for writing."); }

   sub print {     my($self, $msg) = @_;     print LOG $msg . "\n"; }

   sub shutdown {     close LOG; }

   You would then use the new module MyTimer exactly as you would use
Devel::Timer.

     use MyTimer;
     my $t = new MyTimer();
     $t->mark("about to do x");
     $t->mark("about to do y");
     $t->mark("done y");
     $t->report();

SEE ALSO
========

   Time::HiRes

AUTHOR
======

     Jason Moore - jmoore@sober.com

weak references (not reference-counted)
***************************************

NAME
====

   *Devel::WeakRef* - weak references (not reference-counted)

SYNOPSIS
========

     my $foo={a => 1, b => 2};	# Some sort of reference scalar.
     my $foo_=new Devel::WeakRef $foo;
     my $bar=$foo_->deref;		# Hard ref through dereference
     $foo_->deref->{c}=3;		# Dereference
     $foo=$bar=77;			# OK, hash collected
     $foo_->deref;			# Yields undef now
     $foo_->empty;			# True now.

   Currently this also works:

     $$foo_->{a};

   But this dies with a stern message:

     $$foo_=$new_thingy;		# Nope! Weak ref must never change referents.

   This hash table has weak references as values:

     tie my %table, Devel::WeakRef::Table;
     $table{key1}=$some_object;
     $table{key2}=$some_other_object;
     $table{key1}=$yet_another_object; # OK to replace keys like this

DESCRIPTION
===========

   A weak reference maintains a "pointer" to an object (specified by a
reference to it, just like bless) that does not contribute to the object's
reference count; thus, the object's storage will be freed (and its
destructor invoked) when only weak references remain to it. (It is fine to
have multiple weak references to a single object.) The deref method
derefences the weak reference. Dereferencing a weak reference whose target
has already been destroyed results in undef.

   empty tests if the reference is invalid; `$ref->empty' is equivalent to
`!defined $ref->deref'. *For now*, you can just use Perl's normal scalar
dereference to the same effect; but be sure to use this for reading only.
This interface may change.

   The package *Devel::WeakRef::Table* may be used to tie hashes so as to
make their values all weak references. This is useful for caches in
particular, where it would be more annoying to have to explicitly
dereference the value each time.

   The most likely applications of this module are:

Cyclic Structures
     Various structures, like arbitrarily-traversable trees, or
     doubly-linked lists, or some queues, naturally have cyclic pointer
     structures in them. If you are not very careful, removing external
     references without breaking up the internal links will give you a
     memory leak. With weak references, you need only be sure that there
     is no cyclic structure of *hard* (normal) references; back-links and
     other convenient links can easily be made weak.

Caches
     For some applications it is desirable to maintain a cache of lookups
     (search results) keyed off (say) search string. The values might be
     some objects. To have these entries removed when an object is
     destroyed, you want to leave each object's reference count untouched
     (so it will be collected as it would have otherwise), and make sure
     its destructor removes the appropriate keys from the caching table.

AUTHORS
=======

   Jesse Glick, *jglick@sig.bsh.com*.

BUGS
====

   If you mess with the internal structure of a weak ref you will probably
dump core.

   The module attempts to catch attempts to directly set the target of a
weak reference in a scalar dereference operation as an lvalue, and dies
abruptly. It tries to do so as nicely as possible, but it is not feasible
to 100% protect the environment in this case. In other words, if you plan
on having this error occur, do not plan on `eval-BLOCK'ing it and
expecting everything to be dandy later.

   Tied weak tables have not been tested as well as the bare references.
There may be unforeseen memory leaks (presumably, not in the referred-to
objects themselves, but in supporting data areas-this would affect raw
memory usage, not collection of the reference targets).

   Putting a weak ref on a reference object places extension-magic (`~',
see `perlguts(1P)' in this node) on that object. This could conflict with
other user extensions using custom magic. To avoid this, *Devel::WeakRef*
specifically looks for its own magic and only its own magic; however,
another extension might not do so for itself and become extremely
confused, if it was specifically looking for its own magic (probably not so
common).

REVISION
========

   X<$Format: "`$Source$' last modified $Date$, release
$DevelWeakRefRelease$. $Copyright$"$> `Devel-WeakRef/lib/Devel/WeakRef.pm'
last modified Thu, 25 Sep 1997 20:32:00 -0400, release 0.003. Copyright
(c) 1997 Strategic Interactive Group. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Perl debugger using a Tk GUI
****************************

NAME
====

   Devel::ptkdb - Perl debugger using a Tk GUI

DESCRIPTION
===========

     ptkdb is a debugger for perl that uses perlTk for a user interface.
     Features include:

     Hot Variable Inspection
     Breakpoint Control Panel
     Expression List
     Subroutine Tree

     <body bgcolor=white>

SYNOPSIS
========

     To debug a script using ptkdb invoke perl like this:

     perl -d:ptkdb myscript.pl

Usage
=====

     perl -d:ptkdb myscript.pl

Code Pane
---------

Line Numbers
          Line numbers are presented on the left side of the window.	Lines that
          have lines through them are not breakable.	Lines that are plain text
          are breakable.	Clicking on these line numbers will insert a
          breakpoint on that line and change the line number color to
          $ENV{'PTKDB_BRKPT_COLOR'} (Defaults to Red).	Clicking on the number
          again will remove the breakpoint.	 If you disable the breakpoint with
          the controls on the BrkPt notebook page the color will change to
          $ENV{'PTKDB_DISABLEDBRKPT_COLOR'}(Defaults to Green).

Cursor Motion
          If you place the cursor over a variable (i.e. $myVar, @myVar, or
          																				 %myVar) and pause for a second the debugger will evaluate the current
          value of the variable and pop a balloon up with the evaluated
          result. I<This feature is not available with Tk400.>

          If Data::Dumper(standard with perl5.00502)is available it will be used
          to format the result.	 If there is an active selection, the text of
          that selection will be evaluated.

Notebook Pane
-------------

Exprs
          This is a list of expressions that are evaluated each time the debugger stops.	The results
          of the expresssion are presented heirarchically for expression that result in hashes or lists.
          Double clicking on such an expression will cause it to collapse; double clicking again
          will cause the expression to expand.	Expressions are entered through B<Enter Expr> entry,
          or by Alt-E when text is selected in the code pane.

          The B<Quick Expr> entry, will take an expression, evaluate it, and replace the entries
          contents with the result.	 The result is also transfered to the 'clipboard' for pasting.

Subs
          Displays a list of all the packages invoked with the script heirarchially.	At the bottom
          of the heirarchy are the subroutines within the packages.	 Double click on a package to
          expand it.	Subroutines are listed by their full package names.

BrkPts
          Presents a list of the breakpoints current in use.	The pushbutton allows a breakpoint to
          be 'disabled' without removing it.	Expressions can be applied to the breakpoint.	 If the
          expression evaluates to be 'true'(results in a defined value that is not 0) the debugger
          will stop the script.	 Pressing the 'Goto' button will set the text pane to that file and
          line where the breakpoint is set.	 Pressing the 'Delete' button will delete the breakpoint.

Menus
=====

File Menu
---------

About...
          Presents a dialog box telling you about the version of ptkdb.	 It recovers
          your OS name, version of perl, version of Tk, and some other information

Open
          Presents a list of files that are part of the invoked perl script.	Selecting
          a file from this list will present this file in the text window.

Save Config...
          Requires Data::Dumper.	Prompts for a filename to save the configuration to.	Saves
          the breakpoints, expressions, eval text and window geometry.	If the name given as
          the default is used and the script is reinvoked, this configuration will be reloaded
          automatically.

          B<NOTE:>	You may find this preferable to using

Restore Config...
          Requires Data::Dumper.	Prompts for a filename to restore a configuration saved with
          the "Save Config..." menu item.

Goto Line...
          Prompts for a line number.	Pressing the "Okay" button sends the window to the line number entered.

Find Text...
          Prompts for text to search for.	 Options include forward search, backwards search, and regular expression
          searching.

Quit
          Causes the debugger and the target script to exit.

Control Menu
------------

Run
          The debugger allows the script to run to the next breakpoint or until the script exits.

Run To Here
          Runs the debugger until it comes to wherever the insertion cursor in text window
          is placed.

Set Breakpoint
          Sets a breakpoint on the line at the insertion cursor.

Clear Breakpoint
          Remove a breakpoint on the at the insertion cursor.

Clear All Breakpoints
          Removes all current breakpoints

Step Over
          Causes the debugger to step over the next line.	 If the line
          is a subroutine call it steps over the call, stopping when
          the subroutine returns.

Step In
          Causes the debugger to step into the next line.	 If the line
          is a subroutine call it steps into the subroutine, stopping
          at the first executable line within the subroutine.

Return
          Runs the script until it returns from the currently executing
          subroutine.

Restart
          Saves the breakpoints and expressions in a temporary file and
          	restarts the script from the beginning.  CAUTION: This feature will
          	not work properly with debugging of CGI Scripts.

Stop On Warning
     When -w is enabled the debugger will stop when warnings such as, "Use
     of uninitialized value at undef_warn.pl line N" are encountered.  The
     debugger will stop on the NEXT line of execution since the error
     can't be detected until the current line has executed.

     This feature can be turned on at startup by adding:

     $DB::ptkdb::stop_on_warning = 1 ;

     to a .ptkdbrc file

Data Menu
---------

Enter Expression
          When an expression is entered in the "Enter Expression:" text box, selecting
          this item will enter the expression into the expression list.	 Each time the
          debugger stops this expression will be evaluated and its result updated in
          the list window.

Delete Expression
          Deletes the highlighted expression in the expression window.

Delete All Expressions
          Delete all expressions in the expression window.

Expression Eval Window
          Pops up a two pane window.	Expressions of virtually unlimitted length
          can be entered in the top pane.	 Pressing the 'Eval' button will cause
          the expression to be evaluated and its placed in the lower pane.	If
          Data::Dumper is available it will be used to format the resulting
          text.	 Undo is enabled for the text in the upper pane.

     HINT:	 You can enter multiple expressions by separating them
     with commas.

Use Data::Dumper for Eval Window
          Enables or disables the use of Data::Dumper for formatting the results
          of expressions in the Eval window.

Stack Menu
----------

     Maintains a list of the current subroutine stack each time the debugger
     stops.	Selecting an item from this menu will set the text in the code
     window to that particular subourtine entry point.

Bookmarks Menu
--------------

     Maintains a list of bookmarks.	The booksmarks are saved in ~/.ptkdb_bookmarks

Add Bookmark
          Adds a bookmark to the bookmark list.

Options
=======

     Here is a list of the current active XResources options.	Several
     of these can be overridden with environmental variables.	Resources
     can be added to .Xresources or .Xdefaults depending on your X configuration.
     To enable these resources you must either restart your X server or
     use the xrdb -override resFile command.	 xfontsel can be used to select
     fonts.

     /*
     * Perl Tk Debugger XResources.
     * Note... These resources are subject to change.
     *
     * Use 'xfontsel' to select different fonts.
     *
     * Append these resource to ~/.Xdefaults | ~/.Xresources
     * and use xrdb -override ~/.Xdefaults | ~/.Xresources
     * to activate them.
     */
     /* Set Value to se to place scrollbars on the right side of windows
     	CAUTION:	extra whitespace at the end of the line is causing
     failures with Tk800.011.

     sw -> puts scrollbars on left, se puts scrollars on the right

     */
     ptkdb*scrollbars: sw
     /* controls where the code pane is oriented, down the left side, or across the top */
     /* values can be set to left, right, top, bottom */
     ptkdb*codeside: left

     /*
     * Background color for the balloon
     * CAUTION:	For certain versions of Tk trailing
     * characters after the color produces an error
     */
     ptkdb.frame2.frame1.rotext.balloon.background: green
     ptkdb.frame2.frame1.rotext.balloon.font: fixed											 /* Hot Variable Balloon Font */

     ptkdb.frame*font: fixed														/* Menu Bar */
     ptkdb.frame.menubutton.font: fixed								/* File menu */
     ptkdb.frame2.frame1.rotext.font: fixed						/* Code Pane */
     ptkdb.notebook.datapage.frame1.hlist.font: fixed	/* Expression Notebook Page */

     ptkdb.notebook.subspage*font: fixed								/* Subroutine Notebook Page */
     ptkdb.notebook.brkptspage*entry.font: fixed				/* Delete Breakpoint Buttons */
     ptkdb.notebook.brkptspage*button.font: fixed			/* Breakpoint Expression Entries */
     ptkdb.notebook.brkptspage*button1.font: fixed			/* Breakpoint Expression Entries */
     ptkdb.notebook.brkptspage*checkbutton.font: fixed /* Breakpoint Checkbuttons */
     ptkdb.notebook.brkptspage*label.font: fixed				/* Breakpoint Checkbuttons */

     ptkdb.toplevel.frame.textundo.font: fixed					/* Eval Expression Entry Window */
     ptkdb.toplevel.frame1.text.font: fixed						/* Eval Expression Results Window */
     ptkdb.toplevel.button.font:	 fixed								/* "Eval..." Button */
     ptkdb.toplevel.button1.font: fixed								/* "Clear Eval" Button */
     ptkdb.toplevel.button2.font: fixed								/* "Clear Results" Button */
     ptkdb.toplevel.button3.font: fixed								/* "Clear Dismiss" Button */

     /*
     * Background color for where the debugger has stopped
     */
     ptkdb*stopcolor: blue

     /*
     * Background color for set breakpoints
     */
     ptkdb*breaktagcolor*background: yellow
     ptkdb*disabledbreaktagcolor*background: white
     /*
     * Font for where the debugger has stopped
     */
     ptkdb*stopfont: -*-fixed-bold-*-*-*-*-*-*-*-*-*-*-*

     /*
     * Background color for the search tag
     */
     ptkdb*searchtagcolor: green

Environmental Variables
=======================

PTKDB_BRKPT_COLOR
          Sets the background color of a set breakpoint

PTKDB_DISABLEDBRKPT_COLOR
          Sets the background color of a disabled breakpoint

PTKDB_CODE_FONT
          Sets the font of the Text in the code pane.

PTKDB_CODE_SIDE
          Sets which side the code pane is packed onto.	 Defaults to 'left'.
          Can be set to 'left', 'right', 'top', 'bottom'.

          Overrides the Xresource ptkdb*codeside: I<side>.

PTKDB_EXPRESSION_FONT
          Sets the font used in the expression notebook page.

PTKDB_EVAL_FONT
          Sets the font used in the Expression Eval Window

PTKDB_EVAL_DUMP_INDENT
          Sets the value used for Data::Dumper 'indent' setting.	See man Data::Dumper

PTKDB_SCROLLBARS_ONRIGHT
          A non-zero value Sets the scrollbars of all windows to be on the right side of the window.	Useful
          for Windows users using ptkdb in an XWindows environment.

PTKDB_LINENUMBER_FORMAT
          Sets the format of line numbers on the left side of the window.	 Default value is %05d.	 useful
          if you have a script that contains more than 99999 lines.

PTKDB_DISPLAY
          Sets the X display that the ptkdb window will appear on when invoked.	 Useful for debugging CGI
          scripts on remote systems.

PTKDB_BOOKMARKS_PATH
          Sets the path of the bookmarks file.	Default is $ENV{'HOME'}/.ptkdb_bookmarks

PTKDB_STOP_TAG_COLOR
          Sets the color that highlights the line where the debugger is stopped

FILES
=====

.ptkdbrc
--------

     If this file is present in ~/ or in the directory where perl is invoked the file will
     be read and executed as a perl script before the debugger makes its initial stop at startup.
     There	 are several 'api' calls that can be used with such scripts.	There is an internal
     variable $DB::no_stop_at_start that may be set to non-zero to prevent the debugger from
     stopping at the first line of the script.	 This is useful for debugging CGI scripts.

     There is a system ptkdbrc file in $PREFIX/lib/perl5/$VERS/Devel/ptkdbrc

brkpt($fname, @lines)
          Sets breakspoints on the list of lines in $fname.	 A warning message is generated
          if a line is not breakable.

condbrkpt($fname, @($line, $expr) )
          Sets conditional breakpoints in $fname on pairs of $line and $expr.	A warning message is generated
          if a line is not breakable.	 NOTE:	the validity of the expression will not be determined until execution
          of that particular line.

brkonsub(@names)
          Sets a breakpoint on each subroutine name listed.	A warning message is generated
          if a subroutine does not exist.	 NOTE:	for a script with no other packages the default
          package is "main::" and the subroutines would be "main::mySubs".

brkonsub_regex(@regExprs)
          Uses the list of @regExprs as a list of regular expressions to set breakpoints.	 Sets breakpoints
          on every subroutine that matches any of the listed regular expressions.

textTagConfigure(tag, ?option?, ?value?)
          Allows the user to format the text in the code window.	The option
          value pairs are the same values as the option for the tagConfigure
          method documented in Tk::Text.	Currently the following tags are
          in effect:

          'code'							 Format for code in the text pane
          		'stoppt'						 Format applied to the line where the debugger is currently stopped
          		'breakableLine'			 Format applied to line numbers where the code is 'breakable'
          		'nonbreakableLine'	 Format applied to line numbers where the code is no breakable
          		'breaksetLine'			 Format applied to line numbers were a breakpoint is set
          		'breakdisabledLine'	 Format applied to line numbers were a disabled breakpoint is set
          		'search_tag'				 Format applied to text when located by a search.

     Example:

     # # Turns off the overstrike on lines that you can't set a breakpoint
     on # and makes the text color yellow.  #
     textTagConfigure('nonbreakableLine', -overstrike => 0, -foreground =>
     "yellow") ;

add_exprs(@exprList)
          Add a list of expressions to the 'Exprs' window.	NOTE: use the single
          quote character \' to prevent the expression from being "evaluated" in
          the string context.

          Example:

          #
          # Adds the $_ and @_ expressions to the active list
          #

          add_exprs('$_', '@_') ;

NOTES
=====

Debugging Other perlTk Applications
-----------------------------------

     ptkdb can be used to debug other perlTk applications if some
     cautions are observed.	Basically, do not click the mouse in the
     application's window(s) when you've entered the debugger and do not
     click in the debugger's window(s) while the application is running.
     	Doing either one is not necessarily fatal, but it can confuse things
     	that are going on and produce unexpected results.

     Be aware that most perlTk applications have a central event loop.
     	User actions, such as mouse clicks, key presses, window exposures,
     	etc will generate 'events' that the script will process.	When
     	a perlTk application is running, its 'MainLoop' call will accept these
     	events and then dispatch them to appropriate callbacks associated
     	with the appropriate widgets.

     Ptkdb has its own event loop that runs whenever you've stopped at a
     	breakpoint and entered the debugger.	However, it can accept events
     	that are generated by other perlTk windows and dispatch their callbacks.
     	The problem here is that the application is supposed to be 'stopped',
     	and logically the application should not be able to process events.

     A future version of ptkdb will have an extension that will 'filter'
     events so that application events are not processed while the
     debugger is active, and debugger events will not be processed while
     the target script is active.

Debugging CGI Scripts
---------------------

     One advantage of ptkdb over the builtin debugger(-d) is that it can
     be used to debug CGI perl scripts as they run on a web server.	Be
     sure that that your web server's perl instalation includes Tk.

   Change your

     #! /usr/local/bin/perl

   to

     #! /usr/local/bin/perl -d:ptkdb

   TIP: You can debug scripts remotely if you're using a unix based
Xserver and where you are authoring the script has an Xserver.	 The
Xserver can be another unix workstation, a Macintosh or Win32 platform
with an appropriate XWindows package.	 In your script insert the 		following
BEGIN subroutine:

     sub BEGIN {
     	$ENV{'DISPLAY'} = "myHostname:0.0" ;
     }

   Be sure that your web server has permission to open windows on your
Xserver (see the xhost manpage).

     Access your web page with your browswer and 'submit' the script as
     normal.	 The ptkdb window should appear on myHostname's monitor.	At
     this point you can start debugging your script.	 Be aware that your
     browser may timeout waiting for the script to run.

   To expedite debugging you may want to setup your breakpoints in advance
with a .ptkdbrc file and use the $DB::no_stop_at_start variable.	 NOTE: for
debugging web scripts you may have to have the .ptkdbrc file installed in
the server account's home directory (~www) or whatever username your
webserver is running under.	 Also try installing a .ptkdbrc file in
the same directory as the target script.

KNOWN PROBLEMS
==============

Breakpoint Controls
     If the size of the right hand pane is too small the breakpoint
     controls are not visible.	The breakpoints are still there, the
     window may have to be enlarged in order for them to be visible.

Balloons and Tk400
     The Balloons in Tk400 will not work with ptkdb.	 All other functions
     are supported, but the Balloons require Tk800 or higher.

AUTHOR
======

   Andrew E. Page, aep@world.std.com

ACKNOWLEDGEMENTS
================

   Matthew Persico		 For suggestions, and beta testing.

A perl module to control the 3com OfficeConnect LanModem
********************************************************

NAME
====

   Device::ISDN::OCLM - A perl module to control the 3com OfficeConnect
LanModem

SYNOPSIS
========

     $sp = 1;
     $pw = 'secret;
     $lanmodem = Device::ISDN::OCLM->new ();
     $lanmodem->password ($pw);
     $command = 'manualConnect';
     $status = $lanmodem->$command ($sp);
     while (($status eq 'CLOCK') || ($status eq 'PASSWORD') ||
            ($status eq 'CONNECTING') || ($status eq 'LOGGING IN')) {
       if ($status eq 'CLOCK') {
         sleep (1);
         $status = $lanmodem->setClock ();
       } elsif ($status eq 'PASSWORD') {
         sleep (1);
         $status = $lanmodem->enterPasword ();
       } elsif (($status eq 'CONNECTING') || ($status eq 'LOGGING IN')) {
         $command = 'connectStatus';
         $status = 'OK';
       }
       if ($status eq 'OK') {
         sleep (1);
         $status = $lanmodem->$command ($sp);
       }
     }
     print "$status\n";

DESCRIPTION
===========

   This module can be used to control the 3com OfficeConnect LanModem, an
ISDN TA/router. Device statistics can be queried and manual connections
can be brought up and taken down. Support is provided for setting the
clock if the device is power-cycled, and for automatically entering the
password if the device is password-protected.

   All operations that access the device return a status code indicating
whether the operation was successful or not; and, if not, why. For
example, if you attempt to query device statistics and the device is
locked then the status code will indicate this fact, allowing you to enter
the password and retry the operation. Hence the loop in the above synopsis.

   This module does not perform these loops internally in an effort to
allow it to be embedded within a controlling application such as the *oclm*
Perl command-line application, and a GNOME/GTK graphical user interface
that is available separately.

   This module has a few warts; some are mandated by the device itself and
some are the fault of the author.

CONSTRUCTORS
============

   The following constructor is provided:

$lanmodem = Device::ISDN::OCLM->new ()
     This class method constructs a new LanModem object. A default HTTP
     user agent is created with no proxy information.

METHODS
=======

   The following methods are provided:

$copy = $lanmodem->clone ()
     This method returns a clone of this object.

$oldHostname = $lanmodem->lanmodem ( [$newHostname] )
     This method gets, and optionally sets, the hostname (and optionally
     port) of the device being controlled. The default value is
     *3com.oc.lanmodem*.

$oldPassword = $lanmodem->password ( [$newPassword] )
     This method gets, and optionally sets, the password needed to access
     the device. This is only needed if your device is password-protected.

$userAgent = $lanmodem->userAgent ()
     This method gets the *LWP::UserAgent* that is used by this object to
     access the device. Use this if you want to configure HTTP proxy
     settings, etc.

$defHostname = $lanmodem->defaultLanModem ()
     This method gets the default device hostname, *3com.oc.lanmodem*.

$status = $lanmodem->manualConnect ($providerIndex)
     This method attempts to manually connect to the specified service
     provider (identified by index, starting from 1). The result will be
     one of the standard status codes, *'CONNECTING'* if the ISDN
     connection attempt is in progress (most likely), *'LOGGING IN'* if
     the device is attempting to log in to the service provider, *'ISDN
     FAILED'* if there was an error placing the ISDN call or *'LOGON
     FAILED'* if there was an error logging on. Currently, further details
     of the error are not available.

     Once you have called this and the response is *'CONNECTING'* or
     *'LOGGING IN'* then you should poll the *connectStatus()* method to
     determine the updated connection attempt status.

     If you call this method while the device is already connecting to, or
     logging into the service provider, then the results are not clearly
     defined; the connection attempt may be aborted. If you call this
     after the device has connected to the service provider, then again it
     is not clearly defined; it may return success.

$status = $lanmodem->connectStatus ($providerIndex)
     This method returns the connection status of the call currently in
     progress to the specified provider.

$status = $lanmodem->manualDisconnect ($lineIndex)
     This method attempts to manually disconnect the specified ISDN line
     (identified by index, starting from 1). The result will be one of the
     standard status codes.

$status = $lanmodem->manualAbort ($lineIndex)
     This method attempts to abort the current connection attempt on the
     specified ISDN line (identified by index, starting from 1). The result
     will be one of the standard status codes.

$status = $lanmodem->enterPassword ()
     This method enters the password on the device to unlock it. You should
     first configure a password through the password() method. This method
     should generally be called when a query returns the status code
     'PASSWORD'. The result will be one of the standard status codes or
     *'BAD PASSWORD'* if the password you configured is incorrect.

$status = $lanmodem->setClock ()
     This method sets the time on the device to the current time on your
     system. This should generally be called when a query returns the
     status code 'CLOCK'. The result will be one of the standard status
     codes.

$status = $lanmodem->getManualStatistics ()
     This method queries manual calling statistics from the device. This
     includes all configured service providers and whether they are
     currently connected or not. The result will be one of the standard
     status codes.

$info = $lanmodem->manualStatistics ()
     This method returns the result of the previous manual calling
     statistics query; the result is of type
     Device::ISDN::OCLM::ManualStatistics. If the previous request failed,
     then the result is indeterminate.

$status = $lanmodem->getSystemStatistics ()
     This method queries system statistics from the device. This includes
     the device serial number, firmware revision etc. The result will be
     one of the standard status codes.

$info = $lanmodem->systemStatistics ()
     This method returns the result of the previous system statistics
     query; the result is of type Device::ISDN::OCLM::SystemStatistics. If
     the previous request failed, then the result is indeterminate.

$status = $lanmodem->getISDNStatistics ()
     This method queries ISDN statistics from the device. This includes the
     status of the different ISDN layers, etc. The result will be one of
     the standard status codes.

$info = $lanmodem->isdnStatistics ()
     This method returns the result of the previous ISDN statistics query;
     the result is of type Device::ISDN::OCLM::ISDNStatistics. If the
     previous request failed, then the result is indeterminate.

$status = $lanmodem->getCurrentStatistics ()
     This method queries current call statistics from the device. This
     includes details about the current connection on each ISDN line,
     including its up time, to whom it is connected, etc. The result will
     be one of the standard status codes.

$info = $lanmodem->currentStatistics ()
     This method returns the result of the previous current call statistics
     query; the result is of type Device::ISDN::OCLM::CurrentStatistics.
     If the previous request failed, then the result is indeterminate.

$status = $lanmodem->getLastStatistics ()
     This method queries last call statistics from the device. This
     includes details about the previous connection on each ISDN line,
     including its up time, the reason for it going down, etc. The result
     will be one of the standard status codes.

$info = $lanmodem->lastStatistics ()
     This method returns the result of the previous last call statistics
     query; the result is of type Device::ISDN::OCLM::LastStatistics. If
     the previous request failed, then the result is indeterminate.

$status = $lanmodem->getLast10Statistics ()
     This method queries last 10 call statistics from the device. This
     includes details of the last 10 calls, including their durations, the
     reason for going up, etc. The result will be one of the standard
     status codes.

$info = $lanmodem->last10Statistics ()
     This method returns the result of the previous last 10 call statistics
     query; the result is of type Device::ISDN::OCLM::Last10Statistics. If
     the previous request failed, then the result is indeterminate.

$status = $lanmodem->getSPStatistics ()
     This method queries service provider statistics from the device. This
     includes the name of each configured service provider as well as how
     much time you have spent connected to that provider, etc. The result
     will be one of the standard status codes.

$info = $lanmodem->spStatistics ()
     This method returns the result of the previous service provider
     statistics query; the result is of type
     Device::ISDN::OCLM::SPStatistics. If the previous request failed,
     then the result is indeterminate.

STANDARD STATUS CODES
=====================

   The following are the status codes that you should expect from any
command that you perform against the device:

'OK'
     The command succeeded.

'CLOCK'
     The device clock is unset (probably because of a power cycle). You
     should call *setClock()* to set the clock and then repeat your
     original command.

'PASSWORD'
     The device is password locked. You should call *enterPassword()* to
     enter the password and then repeat your original command.

'BAD HTML'
     The device returned and unexpected HTML page. This is either because
     of a bug in this module or because your firmware is different from
     mine.  Probably best to contact me and we can work out the problem.

'BAD HTTP'
     There was a problem performing an HTTP request of the device. Either
     you got the hostname wrong, it is not reachable from your machine,
     there was a network error, or something bizarre of that nature
     happened.

BUGS
====

   Specifying your password in any manner is, of course, insecure. Doesn't
support multiple concurrent connection attemps. Others unknown.

SEE ALSO
========

   `oclm' in this node, see Device/ISDN/OCLM/ManualStatistics,
see
Device/ISDN/OCLM/SystemStatistics,
Device/ISDN/OCLM/ISDNStatistics,
Device/ISDN/OCLM/CurrentStatistics,
see
Device/ISDN/OCLM/LastStatistics,
Device/ISDN/OCLM/Last10Statistics,
Device/ISDN/OCLM/SPStatistics,
Device/ISDN/OCLM/Statistics,

COPYRIGHT
=========

   Copyright 1999-2000 Merlin Hughes.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Merlin Hughes <merlin@merlin.org>

OCLM current call statistics
****************************

NAME
====

   Device::ISDN::OCLM::CurrentStatistics - OCLM current call statistics

SYNOPSIS
========

     $status = $lanmodem->getCurrentStatistics ();
     ...
     $info = $lanmodem->currentStatistics ();
     $sp = $info->spName (1);

DESCRIPTION
===========

   This class encapsulates 3com OCLM current call statistics, including
call time, destination, etc.

   This class is a subclass of *Device::ISDN::OCLM::Statistics*.

CONSTRUCTORS
============

   Extract instances of this class from *Device::ISDN::OCLM::LanModem*.

METHODS
=======

   The following methods are provided: For most calls, a call number must
be specified; this will be either 1 or 2.

$copy = $info->clone ()
     This method returns a clone of this object.

$type = $info->callType ($index)
     This method returns the call type of the specified call or undef.

$dir = $info->callDirection ($index)
     This method returns the call direction of the specified call or undef.

$sp = $info->spName ($index)
     This method returns the service provider name or dial-in user of the
     specified call or undef.

$ip = $info->ipAddress ($index)
     This method returns the IP address of the specified call or undef.

$dns = $info->primaryDNS ($index)
     This method returns the primary DNS server of the specified call or
     undef.

$dns = $info->secondaryDNS ($index)
     This method returns the secondary DNS server of the specified call or
     undef.

$opt = $info->callOptions ($index)
     This method returns the call options of the specified call or undef.

$st = $info->startTime ($index)
     This method returns the start time of the specified call or undef.

$ut = $info->upTime ($index)
     This method returns the up time of the specified call or undef.

$it = $info->idleTime ($index)
     This method returns the idle time of the specified call or undef.

$oct = $info->octetsReceived ($index)
     This method returns the octets received on the specified call or
     undef.

$oct = $info->octetsTransmitted ($index)
     This method returns the octets transmitted on the specified call or
     undef.

$num = $info->callingNumber ($index)
     This method returns the calling number of the specified call or undef.

$num = $info->calledNumber ($index)
     This method returns the called number of the specified call or undef.

$reason = $info->upReason ($index)
     This method returns the reason for the specified call going up or
     undef.

$str = $info->toString ()
     This method returns a textual representation of this object.

COPYRIGHT
=========

   Copyright 1999-2000 Merlin Hughes.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Merlin Hughes <merlin@merlin.org>

OCLM ISDN statistics
********************

NAME
====

   Device::ISDN::OCLM::ISDNStatistics - OCLM ISDN statistics

SYNOPSIS
========

     $status = $lanmodem->getISDNStatistics ();
     ...
     $info = $lanmodem->isdnStatistics ();
     $tei = $info->tei ();

DESCRIPTION
===========

   This class encapsulates 3com OCLM ISDN statistics, including line
status, etc.

   This class is a subclass of *Device::ISDN::OCLM::Statistics*.

CONSTRUCTORS
============

   Extract instances of this class from *Device::ISDN::OCLM::LanModem*.

METHODS
=======

   The following methods are provided:

$copy = $info->clone ()
     This method returns a clone of this object.

$l1 = $info->layer1 ()
     This method returns the layer 1 status.

$l2 = $info->layer2 ()
     This method returns the layer 2 status.

$tei = $info->tei ()
     This method returns the line TEI.

$str = $info->toString ()
     This method returns a textual representation of this object.

COPYRIGHT
=========

   Copyright 1999-2000 Merlin Hughes.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Merlin Hughes <merlin@merlin.org>

OCLM Last10 call statistics
***************************

NAME
====

   Device::ISDN::OCLM::Last10Statistics - OCLM Last10 call statistics

SYNOPSIS
========

     $status = $lanmodem->getLast10Statistics ();
     ...
     $info = $lanmodem->Last10Statistics ();
     $sp = $info->serviceProvider (1);

DESCRIPTION
===========

   This class encapsulates 3com OCLM last 10 call statistics, including
known service providers and whether or not they are currently connected.

CONSTRUCTORS
============

   Extract instances of this class from *Device::ISDN::OCLM::LanModem*.

METHODS
=======

   The following methods are provided:

$copy = $info->clone ()
     This method returns a clone of this object.

$typ = $info->callType ($index)
     This method returns the call type of the specified call (1-offset) or
     undef.

$sp = $info->serviceProvider ($index)
     This method returns the name of the service provider of the specified
     call (1-offset) or undef.

$dur = $info->duration ($index)
     This method returns the duration of the specified call (1-offset) or
     undef.

$reason = $info->initiationReason ($index)
     This method returns the initiation reason of the specified call
     (1-offset) or undef.

$str = $info->toString ()
     This method returns a textual representation of this object.

COPYRIGHT
=========

   Copyright 1999-2000 Merlin Hughes.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Merlin Hughes <merlin@merlin.org>

OCLM last call statistics
*************************

NAME
====

   Device::ISDN::OCLM::LastStatistics - OCLM last call statistics

SYNOPSIS
========

     $status = $lanmodem->getLastStatistics ();
     ...
     $info = $lanmodem->lastStatistics ();
     $reason = $info->downReason (1);

DESCRIPTION
===========

   This class encapsulates 3com OCLM last call statistics, including call
time, destination, etc.

   This class is a subclass of *Device::ISDN::OCLM::Statistics*.

CONSTRUCTORS
============

   Extract instances of this class from *Device::ISDN::OCLM::LanModem*.

METHODS
=======

   The following methods are provided: For most calls, a call number must
be specified; this will be either 1 or 2.

$copy = $info->clone ()
     This method returns a clone of this object.

$type = $info->callType ($index)
     This method returns the call type of the specified call or undef.

$dir = $info->callDirection ($index)
     This method returns the call direction of the specified call or undef.

$sp = $info->spName ($index)
     This method returns the service provider name or dial-in user of the
     specified call or undef.

$opt = $info->callOptions ($index)
     This method returns the call options of the specified call or undef.

$st = $info->startTime ($index)
     This method returns the start time of the specified call or undef.

$ut = $info->upTime ($index)
     This method returns the up time of the specified call or undef.

$oct = $info->octetsReceived ($index)
     This method returns the octets received on the specified call or
     undef.

$oct = $info->octetsTransmitted ($index)
     This method returns the octets transmitted on the specified call or
     undef.

$num = $info->callingNumber ($index)
     This method returns the calling number of the specified call or undef.

$num = $info->calledNumber ($index)
     This method returns the called number of the specified call or undef.

$reason = $info->upReason ($index)
     This method returns the reason for the specified call going up or
     undef.

$reason = $info->downReason ($index)
     This method returns the reason for the specified call going down or
     undef.

$str = $info->toString ()
     This method returns a textual representation of this object.

COPYRIGHT
=========

   Copyright 1999-2000 Merlin Hughes.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Merlin Hughes <merlin@merlin.org>

OCLM manual call statistics
***************************

NAME
====

   Device::ISDN::OCLM::ManualStatistics - OCLM manual call statistics

SYNOPSIS
========

     $status = $lanmodem->getManualStatistics ();
     ...
     $info = $lanmodem->manualStatistics ();
     $sp = $info->serviceProvider (1);

DESCRIPTION
===========

   This class encapsulates 3com OCLM manual call statistics, including
known service providers and whether or not they are currently connected.

CONSTRUCTORS
============

   Extract instances of this class from *Device::ISDN::OCLM::LanModem*.

METHODS
=======

   The following methods are provided:

$copy = $info->clone ()
     This method returns a clone of this object.

$sp = $info->serviceProvider ($index)
     This method returns the name of the service provider at the specified
     index (1-offset) or undef. Beware of *TempSvcProvider* as this is not
     a normal service provider.

$st = $info->callStatus ($index)
     This method returns the call status of the service provider at the
     specified index (1-offset) or undef. Typically this will be *Down* or
     *Up (1B)* or something like that.

$cm = $info->command ($index)
     This method returns the command hyperlink of the service provider at
     the specified index (1-offset) or undef. Typically this will be
     *CALL1.HTM* or *DISC1.htm* or something like that.

$str = $info->toString ()
     This method returns a textual representation of this object.

COPYRIGHT
=========

   Copyright 1999-2000 Merlin Hughes.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Merlin Hughes <merlin@merlin.org>

OCLM service provider statistics
********************************

NAME
====

   Device::ISDN::OCLM::SPStatistics - OCLM service provider statistics

SYNOPSIS
========

     $status = $lanmodem->getSPStatistics ();
     ...
     $info = $lanmodem->spStatistics ();
     $sp = $info->providerName (1);

DESCRIPTION
===========

   This class encapsulates 3com OCLM service provider statistics, including
total call time, failures, etc.

   This class is a subclass of *Device::ISDN::OCLM::Statistics*.

CONSTRUCTORS
============

   Extract instances of this class from *Device::ISDN::OCLM::LanModem*.

METHODS
=======

   The following methods are provided: For most calls, a provider index
must be specified; this should probably range from 1 through 5.

$copy = $info->clone ()
     This method returns a clone of this object.

$type = $info->providerName ($index)
     This method returns the name of the specified provider or undef.

$dir = $info->successes ($index)
     This method returns the number of successful connections to the
     specified provider or undef.

$dir = $info->failures ($index)
     This method returns the number of failed connections to the specified
     provider or undef.

$dir = $info->octetsReceived ($index)
     This method returns the number of octets received from the specified
     provider or undef.

$dir = $info->octetsTransmitted ($index)
     This method returns the number of octets transmitted to the specified
     provider or undef.

$dir = $info->connectTime ($index)
     This method returns the total connect time with the specified
     provider or undef.

$str = $info->toString ()
     This method returns a textual representation of this object.

COPYRIGHT
=========

   Copyright 1999-2000 Merlin Hughes.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Merlin Hughes <merlin@merlin.org>

OCLM statistics superclass
**************************

NAME
====

   Device::ISDN::OCLM::Statistics - OCLM statistics superclass

SYNOPSIS
========

     $fields = $info->supportedFields ();
     foreach my $field (@{$fields}) {
       ...
     }

DESCRIPTION
===========

   This is the superclass of various OCLM statistics classes.

METHODS
=======

   The following methods are provided:

$copy = $info->clone ()
     This method returns a clone of the subclass.

$fields = $lanmodem->suppoertedFields ()
     This method returns a reference to a list of all the statistics fields
     supported by the subclass.

$str = $lanmodem->toString ()
     This method returns a textual representation of the subclass.

COPYRIGHT
=========

   Copyright 1999-2000 Merlin Hughes.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Merlin Hughes <merlin@merlin.org>

OCLM system statistics
**********************

NAME
====

   Device::ISDN::OCLM::SystemStatistics - OCLM system statistics

SYNOPSIS
========

     $status = $lanmodem->getSystemStatistics ();
     ...
     $info = $lanmodem->systemStatistics ();
     $upTime = $info->upTime ();

DESCRIPTION
===========

   This class encapsulates 3com OCLM system statistics, including serial
number, firmware version, etc.

   This class is a subclass of *Device::ISDN::OCLM::Statistics*.

CONSTRUCTORS
============

   Extract instances of this class from *Device::ISDN::OCLM::LanModem*.

METHODS
=======

   The following methods are provided:

$copy = $info->clone ()
     This method returns a clone of this object.

$id = $info->productID ()
     This method returns the device product ID.

$sn = $info->serialNumber ()
     This method returns the device serial number.

$addr = $info->ethernetAddress ()
     This method returns the device ethernet address. Note that this is
     the NIC address, not the IP address.

$sv = $info->systemVersion ()
     This method returns the device system software version.

$bv = $info->bootVersion ()
     This method returns the device boot software version.

$ut = $info->upTime ()
     This method returns the device up-time.

$dat = $info->date ()
     This method returns the device date.

$tim = $info->upTime ()
     This method returns the device time.

$str = $info->toString ()
     This method returns a textual representation of this object.

COPYRIGHT
=========

   Copyright 1999-2000 Merlin Hughes.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Merlin Hughes <merlin@merlin.org>

Perl interface to `dialog(3)' in this node
******************************************

NAME
====

   *Dialog* - Perl interface to `dialog(3)' in this node

SYNOPSIS
========

     B<use Dialog;>

     #now we are creating the new dialog window
     $dlg  = Dialog->new(title, y,x,height,width);
     #inserting input line
     $line = $dlg->inputline(name, y, x, width, text);
     #adding button
     $btn  = $dlg->button(name, y, x, text, result);
     #and text label
     $labl = $dlg->label(name, y, x, text);
     #and now running all the stuff
     $res  = $dlg->run;

DESCRIPTION
===========

   Debauched Perl interface to `dialog(3)' in this node. Seems to work
somehow.  At least it's been working as v0.01 for 3-4 years at
*http://www.vlink.ru/* before I decided to donate it free as v0.02.

   The idea itself of *$dlg->run*, *$obj->draw* etc was stolen cynically
from Borland Turbo Vision library. Sorry, guys, and if it breaks any
copyrights, please, let me know. Trust me, I haven't got any profit from
this stuff yet. Hopefully will haven't.

   Read `"SEE ALSO"' in this node and maybe it helps.

   Besides `"SYNOPSIS"' in this node the next OOP tricks are available:

     $dlg->redraw;
     $mr = $dlg->modalresult;
     $dlg->modalresult(number);
     $obj = $dlg->object(name);
     $obj = $dlg->current;
     $dlg->current(name);
     $dlg->current($obj);
     $text = $obj->data;
     $obj->data(newtext);
     $tabstop = $obj->tabstop;
     $obj->tabstop(boolean);
     $name = $obj->name;

   And, of course, good ancient non-OOP functions:

     Dialog::<many-many-consts>;
     Dialog::Const::<yet-same-and-other-consts>;
     void Dialog::Init(); /* only use it if there are no Dialog->new statements */
     void Dialog::Exit(); /* the same note */
     void Dialog::draw_shadow(y, x, h, w, win=stdscr);
     void Dialog::draw_box(y, x, h, w, box, border, win=stdscr);
     int Dialog::line_edit(y, x, w, box, border, win=stdscr);
     WINDOW *Dialog::stdscr();
     void Dialog::refresh();
     int Dialog::ungetch(ch);
     void Dialog::attrset(attr);
     void Dialog::mvprintw(y, x, s);
     void Dialog::gotoyx(y, x);
     int Dialog::getch();
     int Dialog::YesNo(title, prompt, h, w);
     int Dialog::PrgBox(title, line, h, w, pause, use_shell);
     int Dialog::MsgBox(title, prompt, h, w, pause);
     int Dialog::TextBox(title, file, h, w);
     str Dialog::Menu(title, prompt, h, w, menu_h, ...);
     str Dialog::RadioList(title, prompt, h, w, list_h, ...);
     array Dialog::CheckList(title, prompt, h, w, list_h, ...);
     str Dialog::InputBox(title, prompt, h, w, str);
     int Dialog::Y();
     int Dialog::X();

   Strings passed to Menu, CheckList and RadioList may contain single zero
char (ASCII 0) which delimites menu columns. You may, of course, pass such
strings into other routines, but it will be your pain yet.

   And, at all, see test.pl and try to understand anything.

   If you have any suggestions and/or contributions, please, don't
hesitate to send me.

AUTHOR
======

   Michael Samanov <samanov@yahoo.com>

SEE ALSO
========

   dialog.h, dialog(1), dialog(3), ncurses(3).

Modules that calculate message digests
**************************************

NAME
====

   Digest:: - Modules that calculate message digests

SYNOPSIS
========

     $md2 = Digest->MD2;
     $md5 = Digest->MD5;

     $sha1 = Digest->SHA1;
     $sha1 = Digest->new("SHA-1");

     $hmac = Digest->HMAC_MD5($key);

DESCRIPTION
===========

   The `Digest::' modules calculate digests, also called "fingerprints" or
"hashes", of some data, called a message.  The digest is some small fixed
size string.  The actual size of the digest depend of the algorithm used.
The message is simply a sequence of arbitrary bytes.

   An important property of the digest algorithms is that the digest is
*likely* to change if the message change in some way.  Another property is
that digest functions are one-way functions, i.e. it should be *hard* to
find a message that correspond to some given digest.  Algorithms differ in
how "likely" and how "hard", as well as how efficient they are to compute.

   All `Digest::' modules provide the same programming interface.  A
functional interface for simple use, as well as an object oriented
interface that can handle messages of arbitrary length and which can read
files directly.

   The digest can be delivered in three formats:

binary
     This is the most compact form, but it is not well suited for printing
     or embedding in places that can't handle arbitrary data.

hex
     A twice as long string of (lowercase) hexadecimal digits.

base64
     A string of portable printable characters.  This is the base64 encoded
     representation of the digest with any trailing padding removed.  The
     string will be about 30% longer than the binary version.  See
     MIME/Base64, tells you more about this encoding.

   The functional interface is simply importable functions with the same
name as the algorithm.  The functions take the message as argument and
return the digest.  Example:

     use Digest::MD5 qw(md5);
     $digest = md5($message);

   There are also versions of the functions with "_hex" or "_base64"
appended to the name, which returns the digest in the indicated form.

OO INTERFACE
============

   The following methods are available for all `Digest::' modules:

$ctx = Digest->XXX($arg,...)
$ctx = Digest->new(XXX => $arg,...)
$ctx = Digest::XXX->new($arg,...)
     The constructor returns some object that encapsulate the state of the
     message-digest algorithm.  You can add data to the object and finally
     ask for the digest.  The "XXX" should of course be replaced by the
     proper name of the digest algorithm you want to use.

     The two first forms are simply syntactic sugar which automatically
     load the right module on first use.  The second form allow you to use
     algorithm names which contains letters which are not legal perl
     identifiers, e.g. "SHA-1".

     If new() is called as a instance method (i.e. $ctx->new) it will just
     reset the state the object to the state of a newly created object.  No
     new object is created in this case, and the return value is the
     reference to the object (i.e. $ctx).

$ctx->reset
     This is just an alias for $ctx->new.

$ctx->add($data,...)
     The $data provided as argument are appended to the message we
     calculate the digest for.  The return value is the $ctx object itself.

$ctx->addfile($io_handle)
     The $io_handle is read until EOF and the content is appended to the
     message we calculate the digest for.  The return value is the $ctx
     object itself.

$ctx->digest
     Return the binary digest for the message.

     Note that the digest operation is effectively a destructive,
     read-once operation. Once it has been performed, the $ctx object is
     automatically reset and can be used to calculate another digest value.

$ctx->hexdigest
     Same as $ctx->digest, but will return the digest in hexadecimal form.

$ctx->b64digest
     Same as $ctx->digest, but will return the digest as a base64 encoded
     string.

SEE ALSO
========

   See Digest/MD5, Digest/SHA1,
Digest/HMAC, Digest/MD2,

   See MIME/Base64,

AUTHOR
======

   Gisle Aas <gisle@aas.no>

   The `Digest::' interface is based on the interface originally developed
by Neil Winton for his MD5 module.

Keyed-Hashing for Message Authentication
****************************************

NAME
====

   Digest::HMAC - Keyed-Hashing for Message Authentication

SYNOPSIS
========

     # Functional style
     use Digest::HMAC qw(hmac hmac_hex);
     $digest = hmac($data, $key, \&myhash);
     print hmac_hex($data, $key, \&myhash);

     # OO style
     use Digest::HMAC;
     $hmac = Digest::HMAC->new($key, "Digest::MyHash");

     $hmac->add($data);
     $hmac->addfile(*FILE);

     $digest = $hmac->digest;
     $digest = $hmac->hexdigest;
     $digest = $hmac->b64digest;

DESCRIPTION
===========

   HMAC is used for message integrity checks between two parties that
share a secret key, and works in combination with some other Digest
algorithm, usually MD5 or SHA-1.  The HMAC mechanism is described in RFC
2104.

   HMAC follow the common `Digest::' interface, but the constructor takes
the secret key and the name of some other simple `Digest::' as argument.

SEE ALSO
========

   See Digest/HMAC_MD5, Digest/HMAC_SHA1,

   RFC 2104

AUTHORS
=======

   Graham Barr <gbarr@ti.com>, Gisle Aas <gisle@aas.no>

Keyed-Hashing for Message Authentication
****************************************

NAME
====

   Digest::HMAC_MD5 - Keyed-Hashing for Message Authentication

SYNOPSIS
========

     # Functional style
     use Digest::HMAC_MD5 qw(hmac_md5 hmac_md5_hex);
     $digest = hmac_md5($data, $key);
     print hmac_md5_hex($data, $key);

     # OO style
     use Digest::HMAC_MD5;
     $hmac = Digest::HMAC_MD5->new($key);

     $hmac->add($data);
     $hmac->addfile(*FILE);

     $digest = $hmac->digest;
     $digest = $hmac->hexdigest;
     $digest = $hmac->b64digest;

DESCRIPTION
===========

   This module provide HMAC-MD5 hashing.

SEE ALSO
========

   See Digest/HMAC, Digest/MD5,
Digest/HMAC_SHA1,

AUTHOR
======

   Gisle Aas <gisle@aas.no>

Keyed-Hashing for Message Authentication
****************************************

NAME
====

   Digest::HMAC_SHA1 - Keyed-Hashing for Message Authentication

SYNOPSIS
========

     # Functional style
     use Digest::HMAC_SHA1 qw(hmac_sha1 hmac_sha1_hex);
     $digest = hmac_sha1($data, $key);
     print hmac_sha1_hex($data, $key);

     # OO style
     use Digest::HMAC_SHA1;
     $hmac = Digest::HMAC_SHA1->new($key);

     $hmac->add($data);
     $hmac->addfile(*FILE);

     $digest = $hmac->digest;
     $digest = $hmac->hexdigest;
     $digest = $hmac->b64digest;

DESCRIPTION
===========

   This module provide HMAC-SHA-1 hashing.

SEE ALSO
========

   See Digest/HMAC, Digest/SHA1,
Digest/HMAC_MD5,

AUTHOR
======

   Gisle Aas <gisle@aas.no>

Perl interface to the MD2 Algorithm
***********************************

NAME
====

   Digest::MD2 - Perl interface to the MD2 Algorithm

SYNOPSIS
========

     # Functional style
     use Digest::MD2  qw(md2 md2_hex md2_base64);

     $digest = md2($data);
     $digest = md2_hex($data);
     $digest = md2_base64($data);

     # OO style
     use Digest::MD2;

     $ctx = Digest::MD2->new;

     $ctx->add($data);
     $ctx->addfile(*FILE);

     $digest = $ctx->digest;
     $digest = $ctx->hexdigest;
     $digest = $ctx->b64digest;

DESCRIPTION
===========

   The `Digest::MD2' module allows you to use the RSA Data Security Inc.
MD2 Message Digest algorithm from within Perl programs.  The algorithm
takes as input a message of arbitrary length and produces as output a
128-bit "fingerprint" or "message digest" of the input.

   The `Digest::MD2' programming interface is identical to the interface
of Digest::MD5.

SEE ALSO
========

   See Digest/MD5,

COPYRIGHT
=========

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

     Copyright 1998-2000 Gisle Aas.
     Copyright 1990-1992 RSA Data Security, Inc.

AUTHOR
======

   Gisle Aas <gisle@aas.no>

Perl interface to the RSA Data Security Inc. MD4 Message-Digest Algorithm
*************************************************************************

NAME
====

   Digest::MD4 - Perl interface to the RSA Data Security Inc. MD4
Message-Digest Algorithm

SYNOPSIS
========

     use Digest::MD4;

     $context = new Digest::MD4;
     $context->reset();

     $context->add(LIST);
     $context->addfile(HANDLE);

     $digest = $context->digest();
     $string = $context->hexdigest();

     $digest = Digest::MD4->hash(SCALAR);
     $string = Digest::MD4->hexhash(SCALAR);

DESCRIPTION
===========

   The *Digest::MD4* module allows you to use the RSA Data Security Inc.
MD4 Message Digest algorithm from within Perl programs.

   A new MD4 context object is created with the new operation.  Multiple
simultaneous digest contexts can be maintained, if desired.  The context
is updated with the add operation which adds the strings contained in the
LIST parameter. Note, however, that `add('foo', 'bar')', `add('foo')'
followed by `add('bar')' and `add('foobar')' should all give the same
result.

   The final message digest value is returned by the digest operation as a
16-byte binary string. This operation delivers the result of add
operations since the last new or reset operation. Note that the digest
operation is effectively a destructive, read-once operation. Once it has
been performed, the context must be reset before being used to calculate
another digest value.

   Several convenience functions are also provided. The *addfile*
operation takes an open file-handle and reads it until end-of file in 1024
byte blocks adding the contents to the context. The file-handle can either
be specified by name or passed as a type-glob reference, as shown in the
examples below. The *hexdigest* operation calls digest and returns the
result as a printable string of hexdecimal digits. This is exactly the
same operation as performed by the unpack operation in the examples below.

   The hash operation can act as either a static member function (ie you
invoke it on the MD4 class as in the synopsis above) or as a normal
virtual function. In both cases it performs the complete MD4 cycle (reset,
add, digest) on the supplied scalar value. This is convenient for handling
small quantities of data. When invoked on the class a temporary context is
created. When invoked through an already created context object, this
context is used. The latter form is slightly more efficient. The *hexhash*
operation is analogous to *hexdigest*.

EXAMPLES
========

     use Digest::MD4;

     $md4 = new Digest::MD4;
     $md4->add('foo', 'bar');
     $md4->add('baz');
     $digest = $md4->digest();

     print("Digest is " . unpack("H*", $digest) . "\n");

   The above example would print out the message

     Digest is 6df23dc03f9b54cc38a0fc1483df6e21

   provided that the implementation is working correctly.

   Remembering the Perl motto ("There's more than one way to do it"), the
following should all give the same result:

     use Digest::MD4;
     $md4 = new Digest::MD4;

     die "Can't open /etc/passwd ($!)\n" unless open(P, "/etc/passwd");

     seek(P, 0, 0);
     $md4->reset;
     $md4->addfile(P);
     $d = $md4->hexdigest;
     print "addfile (handle name) = $d\n";

     seek(P, 0, 0);
     $md4->reset;
     $md4->addfile(\*P);
     $d = $md4->hexdigest;
     print "addfile (type-glob reference) = $d\n";

     seek(P, 0, 0);
     $md4->reset;
     while (<P>)
     {
         $md4->add($_);
     }
     $d = $md4->hexdigest;
     print "Line at a time = $d\n";

     seek(P, 0, 0);
     $md4->reset;
     $md4->add(<P>);
     $d = $md4->hexdigest;
     print "All lines at once = $d\n";

     seek(P, 0, 0);
     $md4->reset;
     while (read(P, $data, (rand % 128) + 1))
     {
         $md4->add($data);
     }
     $d = $md4->hexdigest;
     print "Random chunks = $d\n";

     seek(P, 0, 0);
     $md4->reset;
     undef $/;
     $data = <P>;
     $d = $md4->hexhash($data);
     print "Single string = $d\n";

     close(P);

NOTE
====

   The MD4 extension may be redistributed under the same terms as Perl.
The MD4 algorithm is defined in RFC1320. The basic C code implementing the
algorithm is derived from that in the RFC and is covered by the following
copyright:

     Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.

     License to copy and use this software is granted provided that it
     is identified as the "RSA Data Security, Inc. MD4 Message-Digest
     Algorithm" in all material mentioning or referencing this software
     or this function.

     License is also granted to make and use derivative works provided
     that such works are identified as "derived from the RSA Data
     Security, Inc. MD4 Message-Digest Algorithm" in all material
     mentioning or referencing the derived work.

     RSA Data Security, Inc. makes no representations concerning either
     the merchantability of this software or the suitability of this
     software for any particular purpose. It is provided "as is"
     without express or implied warranty of any kind.

     These notices must be retained in any copies of any part of this
     documentation and/or software.

   This copyright does not prohibit distribution of any version of Perl
containing this extension under the terms of the GNU or Artistic licences.

AUTHOR
======

   The MD4 interface was adapted by Mike McCauley (`mikem@open.com.au'),
based entirely on MD5-1.7, written by Neil Winton
(`N.Winton@axion.bt.co.uk').

SEE ALSO
========

   perl(1).

Perl interface to the MD5 Algorithm
***********************************

NAME
====

   Digest::MD5 - Perl interface to the MD5 Algorithm

SYNOPSIS
========

     # Functional style
     use Digest::MD5  qw(md5 md5_hex md5_base64);

     $digest = md5($data);
     $digest = md5_hex($data);
     $digest = md5_base64($data);

     # OO style
     use Digest::MD5;

     $ctx = Digest::MD5->new;

     $ctx->add($data);
     $ctx->addfile(*FILE);

     $digest = $ctx->digest;
     $digest = $ctx->hexdigest;
     $digest = $ctx->b64digest;

DESCRIPTION
===========

   The Digest::MD5 module allows you to use the RSA Data Security Inc. MD5
Message Digest algorithm from within Perl programs.  The algorithm takes
as input a message of arbitrary length and produces as output a 128-bit
"fingerprint" or "message digest" of the input.

   The Digest::MD5 module provide a procedural interface for simple use,
as well as an object oriented interface that can handle messages of
arbitrary length and which can read files directly.

   A binary digest will be 16 bytes long.  A hex digest will be 32
characters long.  A base64 digest will be 22 characters long.

FUNCTIONS
=========

   The following functions can be exported from the Digest::MD5 module.
No functions are exported by default.

md5($data,...)
     This function will concatenate all arguments, calculate the MD5 digest
     of this "message", and return it in binary form.

md5_hex($data,...)
     Same as md5(), but will return the digest in hexadecimal form.

md5_base64($data,...)
     Same as md5(), but will return the digest as a base64 encoded string.

METHODS
=======

   The following methods are available:

$md5 = Digest::MD5->new
     The constructor returns a new Digest::MD5 object which encapsulate
     the state of the MD5 message-digest algorithm.  You can add data to
     the object and finally ask for the digest.

     If called as a instance method (i.e. $md5->new) it will just reset the
     state the object to the state of a newly created object.  No new
     object is created in this case.

$md5->reset
     This is just an alias for $md5->new.

$md5->add($data,...)
     The $data provided as argument are appended to the message we
     calculate the digest for.  The return value is the $md5 object itself.

$md5->addfile($io_handle)
     The $io_handle is read until EOF and the content is appended to the
     message we calculate the digest for.  The return value is the $md5
     object itself.

$md5->digest
     Return the binary digest for the message.

     Note that the digest operation is effectively a destructive,
     read-once operation. Once it has been performed, the Digest::MD5
     object is automatically reset and can be used to calculate another
     digest value.

$md5->hexdigest
     Same as $md5->digest, but will return the digest in hexadecimal form.

$md5->b64digest
     Same as $md5->digest, but will return the digest as a base64 encoded
     string.

EXAMPLES
========

   The simplest way to use this library is to import the md5_hex()
function (or one of its cousins):

     use Digest::MD5 qw(md5_hex);
     print "Digest is ", md5_hex("foobarbaz"), "\n";

   The above example would print out the message

     Digest is 6df23dc03f9b54cc38a0fc1483df6e21

   provided that the implementation is working correctly.  The same
checksum can also be calculated in OO style:

     use Digest::MD5;

     $md5 = Digest::MD5->new;
     $md5->add('foo', 'bar');
     $md5->add('baz');
     $digest = $md5->hexdigest;

     print "Digest is $digest\n";

   With OO style you can break the message arbitrary.  This means that we
are no longer limited to have space for the whole message in memory, i.e.
we can handle messages of any size.

   This is useful when calculating checksum for files:

     use Digest::MD5;

     my $file = shift || "/etc/passwd";
     open(FILE, $file) or die "Can't open '$file': $!";
     binmode(FILE);

     $md5 = Digest::MD5->new;
     while (<FILE>) {
         $md5->add($_);
     }
     close(FILE);
     print $md5->b64digest, " $file\n";

   Or we can use the builtin addfile method for more efficient reading of
the file:

     use Digest::MD5;

     my $file = shift || "/etc/passwd";
     open(FILE, $file) or die "Can't open '$file': $!";
     binmode(FILE);

     print Digest::MD5->new->addfile(*FILE)->hexdigest, " $file\n";

SEE ALSO
========

   See Digest, Digest/MD2,
Digest/SHA1, Digest/HMAC,

   `md5sum(1)' in this node

   RFC 1321

COPYRIGHT
=========

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

     Copyright 1998-2000 Gisle Aas.
     Copyright 1995-1996 Neil Winton.
     Copyright 1991-1992 RSA Data Security, Inc.

   The MD5 algorithm is defined in RFC 1321. The basic C code implementing
the algorithm is derived from that in the RFC and is covered by the
following copyright:

     Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
     rights reserved.

     License to copy and use this software is granted provided that it is
     identified as the "RSA Data Security, Inc. MD5 Message-Digest
     Algorithm" in all material mentioning or referencing this software or
     this function.

     License is also granted to make and use derivative works provided
     that such works are identified as "derived from the RSA Data
     Security, Inc. MD5 Message-Digest Algorithm" in all material
     mentioning or referencing the derived work.

     RSA Data Security, Inc. makes no representations concerning either
     the merchantability of this software or the suitability of this
     software for any particular purpose. It is provided "as is" without
     express or implied warranty of any kind.

     These notices must be retained in any copies of any part of this
     documentation and/or software.

   This copyright does not prohibit distribution of any version of Perl
containing this extension under the terms of the GNU or Artistic licenses.

AUTHORS
=======

   The original MD5 interface was written by Neil Winton
(`N.Winton@axion.bt.co.uk').

   This release was made by Gisle Aas <gisle@aas.no>

Perl implementation of Ron Rivests MD5 Algorithm
************************************************

NAME
====

   Digest::MD5::Perl - Perl implementation of Ron Rivests MD5 Algorithm

DISCLAIMER
==========

   This is not an interface (like Digest::MD5) but a Perl implementation
of MD5.  It is written in perl only and because of this it is slow but it
works without C-Code.  You should use Digest::MD5 instead of this module
if it is available.  This module is only usefull for

     computers where you cannot install Digest::MD5 (e.g. lack of a
     C-Compiler)

     encrypting only small amounts of data (less than one million bytes).
     I use it to hash passwords.

     educational purposes

SYNOPSIS
========

     # Functional style
     use Digest::MD5  qw(md5 md5_hex md5_base64);

     $hash = md5 $data;
     $hash = md5_hex $data;
     $hash = md5_base64 $data;

     # OO style
     use Digest::MD5;

     $ctx = Digest::MD5->new;

     $ctx->add($data);
     $ctx->addfile(*FILE);

     $digest = $ctx->digest;
     $digest = $ctx->hexdigest;
     $digest = $ctx->b64digest;

DESCRIPTION
===========

   This modules has the same interface as the much faster Digest::MD5. So
you can easily exchange them, e.g.

     BEGIN {
       eval {
         require Digest::MD5;
         import Digest::MD5 'md5_hex'
       };
       if ($@) { # ups, no Digest::MD5
         require Digest::Perl::MD5;
         import Digest::Perl::MD5 'md5_hex'
       }
     }

   If the Digest::MD5 module is available it is used and if not you take
`Digest::Perl::MD5'.

   You can also install the Perl part of Digest::MD5 together with
Digest::Perl::MD5 and use Digest::MD5 as normal, it falls back to
Digest::Perl::MD5 if it cannot load its object files.

   For a detailed Documentation see the Digest::MD5 module.

EXAMPLES
========

   The simplest way to use this library is to import the md5_hex()
function (or one of its cousins):

     use Digest::Perl::MD5 'md5_hex';
     print 'Digest is ', md5_hex('foobarbaz'), "\n";

   The above example would print out the message

     Digest is 6df23dc03f9b54cc38a0fc1483df6e21

   provided that the implementation is working correctly.  The same
checksum can also be calculated in OO style:

     use Digest::MD5;

     $md5 = Digest::MD5->new;
     $md5->add('foo', 'bar');
     $md5->add('baz');
     $digest = $md5->hexdigest;

     print "Digest is $digest\n";

LIMITATIONS
===========

   This implementation of the MD5 algorithm has some limitations:

     It's slow, very slow. I've done my very best but Digest::MD5 is still
     about 135 times faster.  You can only encrypt Data up to one million
     bytes in an acceptable time. But it's very usefull for encrypting
     small amounts of data like passwords.

     You can only encrypt up to 2^32 bits = 512 MB on 32bit archs. You
     should use Digest::MD5 for those amounts of data.

     `Digest::Perl::MD5' loads all data to encrypt into memory. This is a
     todo.

SEE ALSO
========

   See Digest/MD5,

   `md5sum(1)' in this node

   RFC 1321

COPYRIGHT
=========

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

     Copyright 2000 Christian Lackas, Imperia Software Solutions
     Copyright 1998-1999 Gisle Aas.
     Copyright 1995-1996 Neil Winton.
     Copyright 1991-1992 RSA Data Security, Inc.

   The MD5 algorithm is defined in RFC 1321. The basic C code implementing
the algorithm is derived from that in the RFC and is covered by the
following copyright:

     Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
     rights reserved.

     License to copy and use this software is granted provided that it is
     identified as the "RSA Data Security, Inc. MD5 Message-Digest
     Algorithm" in all material mentioning or referencing this software or
     this function.

     License is also granted to make and use derivative works provided
     that such works are identified as "derived from the RSA Data
     Security, Inc. MD5 Message-Digest Algorithm" in all material
     mentioning or referencing the derived work.

     RSA Data Security, Inc. makes no representations concerning either
     the merchantability of this software or the suitability of this
     software for any particular purpose. It is provided "as is" without
     express or implied warranty of any kind.

     These notices must be retained in any copies of any part of this
     documentation and/or software.

   This copyright does not prohibit distribution of any version of Perl
containing this extension under the terms of the GNU or Artistic licenses.

AUTHORS
=======

   The original MD5 interface was written by Neil Winton
(`N.Winton@axion.bt.co.uk').

   Digest::MD5 was made by Gisle Aas <gisle@aas.no> (I took his Interface
and part of the documentation)

   Thanks to Guido Flohr for his 'use integer'-hint.

   This release was made by Christian Lackas <delta@clackas.de>.

Perl interface to the SHA-1 Algorithm
*************************************

NAME
====

   Digest::SHA1 - Perl interface to the SHA-1 Algorithm

SYNOPSIS
========

     # Functional style
     use Digest::SHA1  qw(sha1 sha1_hex sha1_base64);

     $digest = sha1($data);
     $digest = sha1_hex($data);
     $digest = sha1_base64($data);

     # OO style
     use Digest::SHA1;

     $ctx = Digest::SHA1->new;

     $ctx->add($data);
     $ctx->addfile(*FILE);

     $digest = $ctx->digest;
     $digest = $ctx->hexdigest;
     $digest = $ctx->b64digest;

DESCRIPTION
===========

   The `Digest::SHA1' module allows you to use the NIST SHA-1 message
digest algorithm from within Perl programs.  The algorithm takes as input
a message of arbitrary length and produces as output a 160-bit
"fingerprint" or "message digest" of the input.

   The `Digest::SHA1' module provide a procedural interface for simple
use, as well as an object oriented interface that can handle messages of
arbitrary length and which can read files directly.

   A binary digest will be 20 bytes long.  A hex digest will be 40
characters long.  A base64 digest will be 27 characters long.

FUNCTIONS
=========

   The following functions can be exported from the `Digest::SHA1' module.
No functions are exported by default.

sha1($data,...)
     This function will concatenate all arguments, calculate the SHA-1
     digest of this "message", and return it in binary form.

sha1_hex($data,...)
     Same as sha1(), but will return the digest in hexadecimal form.

sha1_base64($data,...)
     Same as sha1(), but will return the digest as a base64 encoded string.

METHODS
=======

   The `Digest::SHA1' module provide the standard `Digest' OO-interface.
The constructor looks like this:

$sha1 = Digest->new('SHA-1')

$sha1 = Digest::SHA1->new
     The constructor returns a new `Digest::SHA1' object which encapsulate
     the state of the SHA-1 message-digest algorithm.  You can add data to
     the object and finally ask for the digest using the methods described
     in Digest.

SEE ALSO
========

   See Digest, Digest/HMAC_SHA1,
Digest/MD5,

   http://www.itl.nist.gov/fipspubs/fip180-1.htm

COPYRIGHT
=========

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

     Copyright 1999-2000 Gisle Aas.
     Copyright 1997 Uwe Hollerbach.

AUTHORS
=======

   Peter C. Gutmann, Uwe Hollerbach <uh@alumni.caltech.edu>, Gisle Aas
<gisle@aas.no>

a module that implements the tiger hash
***************************************

NAME
====

   Digest::Tiger - a module that implements the tiger hash

SYNOPSIS
========

     use Digest::Tiger;

     # hash() returns a 192 bit hash
     my $hash = Digest::Tiger::hash('Tiger')

     # hexhash() returns a hex representation of the 192 bits...
     # $hexhash should be '9F00F599072300DD276ABB38C8EB6DEC37790C116F9D2BDF'
     my $hexhash = Digest::Tiger::hexhash('Tiger')

DESCRIPTION
===========

   A perl module that implements the tiger hash, which is believed to be
secure and runs quickly on 64-bit processors.

AUTHOR
======

   Perl interface by Clinton Wong, reference C code used by Digest::Tiger
supplied by Ross Anderson and Eli Biham.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

     http://www.cs.technion.ac.il/~biham/Reports/Tiger/

Purge directories to a given number of files.
*********************************************

NAME
====

   Dir::Purge - Purge directories to a given number of files.

SYNOPSIS
========

     perl -MDir::Purge -e 'purgedir (5, @ARGV)' /spare/backups

     use Dir::Purge;
     purgedir ({keep => 5, strategy => "by_age", verbose => 1}, "/spare/backups");

     use Dir::Purge qw(purgedir_by_age);
     purgedir_by_age (5, "/spare/backups");

DESCRIPTION
===========

   Dir::Purge implements functions to reduce the number of files in a
directory according to a strategy. It currently provides one strategy:
removal of files by age.

   By default, the module exports one user subroutine: `purgedir'.

   The first argument of `purgedir' should either be an integer,
indicating the number of files to keep in each of the directories, or a
reference to a hash with options. In either case, a value for the number
of files to keep is mandatory.

   The other arguments are the names of the directories that must be
purged. Note that this process is not recursive. Also, hidden files (file
name starts with a .) and non-plain files (e.g., directories, symbolic
links) are not taken into account.

   All directory arguments and options are checked before anything else is
done. In particular, all arguments should point to existing directories
and the program must have read, write, and search (execute) access to the
directories.

   One additional function, `purgedir_by_age', can be exported on demand,
or called by its fully qualified name. `purgedir_by_age' calls `purgedir'
with the "by age" purge strategy preselected. Since this happens to be the
default strategy for `purgedir', calling `purgedir_by_age' is roughly
equivalent to calling `purgedir'.

WARNING
=======

   Removing files is a quite destructive operation. Supply the test
option, described below, to dry-run before production.

OPTIONS
=======

   Options are suppled by providing a hash reference as the first
argument. The following calls are equivalent:

     purgedir ({keep => 3, test => 1}, "/spare/backups");
     purgedir_by_age ({keep => 3, test => 1}, "/spare/backups");
     purgedir ({strategy => "by_age", keep => 3, test => 1}, "/spare/backups");

   All subroutines take the same arguments.

keep
     The number of files to keep.

     If positive, the newest files will be kept. If negative, the absolute
     value will be used and the oldest files will be kept.

strategy
     Specifies the purge strategy.  Default (and only allowed) value is
     "by_age".

     This option is for `purgedir' only. The other subroutines should not
     be provided with a strategy option.

verbose
     Verbosity of messages. Default value is 1. A value of 0 (zero) will
     suppress messages.

debug
     For internal debugging only.

test
     If true, no files will be removed. For testing.

EXPORT
======

   Subroutine `purgedir' is exported by default.

   Subroutine `purgedir_by_age' may be exported on demand.

   Calling purgedir_by_age() is roughly equivalent to calling purgedir()
with an options hash that includes `strategy =' "by_age">.

   The variable $Dir::Purge::VERSION may be used to inspect the version of
the module.

AUTHOR
======

   Johan Vromans (jvromans@squirrel.nl) wrote this module.

COPYRIGHT AND DISCLAIMER
========================

   This program is Copyright 2000 by Squirrel Consultancy. All rights
reserved.

   This program is free software; you can redistribute it and/or modify it
under the terms of either: a) the GNU General Public License as published
by the Free Software Foundation; either version 1, or (at your option) any
later version, or b) the "Artistic License" which comes with Perl.

   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 either the GNU General Public
License or the Artistic License for more details.

supply object methods for directory handles
*******************************************

NAME
====

   DirHandle - supply object methods for directory handles

SYNOPSIS
========

     use DirHandle;
     $d = new DirHandle ".";
     if (defined $d) {
         while (defined($_ = $d->read)) { something($_); }
         $d->rewind;
         while (defined($_ = $d->read)) { something_else($_); }
         undef $d;
     }

DESCRIPTION
===========

   The DirHandle method provide an alternative interface to the opendir(),
closedir(), readdir(), and rewinddir() functions.

   The only objective benefit to using DirHandle is that it avoids
namespace pollution by creating globs to hold directory handles.

client module for MS format conversions
***************************************

NAME
====

   Docclient - client module for MS format conversions

SEE ALSO
========

   docclient(1), Docserver(3), Win32::OLE(3)

determine file type for Office documents
****************************************

NAME
====

   Document::Info v0.01 - determine file type for Office documents

SYNOPSIS
========

     use Document::Info;

     if ( $Info=Document::Info->new($fileName) ) {;
         # $Info constructed, that means something has been determined.

     # Fetch the currently supported properties.
     $type = $Info -> getType ( );
     $rev  = $Info -> getRevision ( );
     $os   = $Info -> getOS ( );

     if ( $type eq $Info->cMSExcel() ) {
        # Do something. Note: when checking a type or an operating System
        # always use the string constants like cMSExcel().
     }
     if ( !$revision ) {
         # revision not determined.
     }
         } else {
     # Document type could not be determined.
         }

DESCRIPTION
===========

   The module tries to figure out the document type of Office files. It
utilizes OLE::Storage to determine the file type of Windows-documents. The
module is in a very early state.

AUTHOR
======

   Martin Schwartz, schwartz@cs.tu-berlin.de

SEE ALSO
========

   file(1), lfile(1), OLE::Storage.

Multi-host advisory queing locking system
*****************************************

NAME
====

   DotLock - Multi-host advisory queing locking system

SYNOPSIS
========

   `use DotLock;'

   see CONSTRUCTOR & METHODS section below

DESCRIPTION
===========

   `DotLock' is a multipurpose queing locking system. Originally designed
to take some of the pain away from locking on NFS filesystems.

   This module allows script writers to develop on multiple hosts when
locking between these hosts is an issue. It allows queing - scary but
true. It also provides an atomic method of locking by using the "link"
function between files.

   The locking/queing method provided is purely on a file manipulation
level. Also note that this object does not handle signals. If the program
is interrupted, any open lockfiles will be left behind.

CONSTRUCTOR
===========

*new (OPTIONS)* - create a new DotLock object
     This is the constructor of the `DotLock' object.

     OPTIONS are passed to the object in a hash-like fashion using keys
     and values. The keys are the same as the methods provided below, as
     shown:

     $t = new DotLock(         path => "/home/ken/perl/locking/",
     errmode => "die",         timeout => 100,         maxqueue => 8,
       retrytime => 1,         domain => 'optusnet.com.au', );

     So you can define all settings in one go. Besides the "lock" method,
     this is the heart and soul of the module.

METHODS
=======

lock - attempt to obtain a lock
     This method will attempt to obtain a lock with the configuration
     passed to it from the constructor or from the various setup methods.

     The process is basically as follows:

     1. A temporary lockfile is created which is associated with the
     script and host.

     2. The lockfile directory is listed to find the highest free lock.

     3. Depending on the maxqueue setting, the highest lock is obtained.

     4. If for some reason the highest lock was nabbed before the current
     script could get it, the current script will try the next higher up
     lock que until it obtains a placing.

     5. Once a place in the que is obtained, lock will attempt to get the
     next lock. It will retry every second, or the time defined in the
     retrytime method.

     6. Unless the process has reached the point of obtaining the main
     lock, the script will return to step 5 to obtain the next que placing.

     7. Once the main lock is obtained, the script using this object will
     do its business.

unlock - remove all lockfiles
     The method removes all open lockfiles, enabling other processes to
     obtain any lock you have left open. This is also the method called
     upon object destruction.

*timeout ([TIMEOUT])* - timeout for obtaining a lock
     This defaults to 60 seconds.

     Set this method to the amount of time you want your script to wait
     for a lock. The TIMEOUT value is in seconds.

     If you fail to obtain the lock with the set time, the object will
     return an error and react based on the errmode method set when
     creating the object.

*path ([PATH])* - path of lockfiles
     Set the directory for where the lockfiles will be kept. This by
     default is set to /var/lock/quelock. If the path does not exist, an
     error will occur.

     For two processes to use the same lockfiles, this path must be the
     same in both processes.

     With this method you can either set the path of the lockfiles, or
     return the previous path.

*errmode ([MODE])* - set how to react to errors
     The errmode method can be set to either "die" to die when an error is
     encountered or "return" to return an error message. The error message
     can be obtained from the errmsg method.

     The default setting for errmode is "die".

*maxqueue ([QUE])* - the highest allowable que placing
     The maxqueue data method is used by the lock method. When attempting
     to find a place in the que, it will look at this figure - if the
     figure is higher than the highest free que then DotLock will return
     an error.

     By default, queing is turned off.

*retrytime ([TIME])* - the time in seconds to retry the next lock placing
     You set this data method to the amount of time in seconds you with
     the system to retry for the next available lock. The default is 1
     second.

*domain ([DOMAIN])* - set the domain of your system
     Although not necessary, this allows all hosts entries to be reduced
     to just their hostname. This is only really usefull if you plan on
     running scripts with one domain and one domain only.

errmsg - returns the last error message
     This method will return the error message of the last error found.
     When errmode is set to "return" this variable will be loaded with the
     error message.

SEE ALSO
========

   Some other good modules for locking:

   *LockFile::Simple*

   *IPC::Locker*

EXAMPLES
========

   use DotLock;

   $t = new DotLock(         path => "/home/ken/perl/locking/locktest",
    errmode => "return",         timeout => 100,         maxqueue => 8,
     retrytime => 1,         domain => 'optusnet.com.au', );

   $t->lock || print $t->errmsg . "\n";

   print "Locked\n";

   $blah = <STDIN>;

   $t->unlock;

AUTHOR
======

   Ken Barber <ken@optusnet.com.au>

COPYRIGHT
=========

   Copyright (c) 1999 Ken Barber. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

DUA/Perl interface to an X.500 directory
****************************************

NAME
====

   Dua - DUA/Perl interface to an X.500 directory

SYNOPSIS
========

     use Dua;

DESCRIPTION
===========

     This module provides a set of subroutines which allow a Perl script to
     access to the X.500 directory.

SUBROUTINES
===========

     $dua = new Dua()

     Creates a new instance of a Dua object.

     $dua->open($dsa, $port, $dn, $passwd)

     Open an association to the DSA  specified  in  dsa  and
     running  on  the  port specified by port. If no port is
     specified, then  duaperl  will  use  the  default  port
     number.  duaperl  will bind to the DSA as dn, using the
     credentials supplied in passwd. Currently, only  simple
     authentication is supported.

     $dua->error()

     This routine returns a description of the problem when an error
     occurs.

     $dua->settmout($seconds, $microseconds)

     This routine sets the asynchronous timeout value for
     all operations.  The default is 30 seconds.

     $dua->close()

     This routine closes the association to the X.500 DSA.

     $dua->moveto($dn)

     Move to the location in the DIT specified by dn.

     $dua->modrdn($rdn, $newrdn)

     Modify the object whose RDN is rdn to newrdn.

     $dua->delete($rdn)

     Delete the object specified by rdn from the DIT.

     $dua->add($rdn, %attrs)

     Add a new object to the DIT with an RDN of rdn with the
     attributes attrs.

     $dua->modattr($rdn, %attrs)

     Modify the object specified by rdn with the  attribute-
     value pairs in attrs. If a value is set to an empty string
     the associated attribute is deleted from the entry.

     $dua->show($rdn)

     Returns in an  associative  array  the  attribute-value
     pairs found in the object specified by rdn.

     $dua->attribute($rdn,$attribute)

     Returns an array of values for the specified attribute
     found in the object specified by rdn.

     This method maybe used to retrieve binary attributes not
     accessible via the show method.

     $dua->find($rdn, $filter, $scope, $all)

     Returns in an associative array the attribute-value pairs found
     beneath the object specified by rdn. filter is a string
     representation of a filter to apply to the search.  A
     Backus-Naur Form definition is given below.  scope refers to how
     deep the search is to progress in the DIT. A value of 0
     specifies the immediate children of the object; a value of 1
     specifies the entire sub- tree beneath the object.  all refers
     to what will be returned in the associative array. A value of 0
     will return just the DN's of matching objects, keyed by their
     ordinality in the search response; a value of 1 specifies that
     the attribute-value pairs of all match- ing objects are to be
     returned.  This routine is used for non-leaf objects.

NOTES
=====

     $dua->moveto() determines the path which is prepended to the rdn of all
     other functions. This simulates ``standing'' at a particular position
     in the DIT, and being able to specify DN's relative to the current
     position. If a fully-qualified DN is more appropriate for a
     particular call, begin the rdn string with an `@' character.

     The Backus-Naur Form (BNF) for the filter specified in dua_find()
     is as follows:

     <filter> ::= '(' <filtercomp> ')'
     <filtercomp> ::= <and> | <or> | <not> | <simple>
     <and> ::= '&' <filterlist>
     <or> ::= '|' <filterlist>
     <not> ::= '!' <filter>
     <filterlist> ::= <filter> | <filter> <filterlist>
     <simple> ::= <attributetype> <filtertype> <attributevalue>
     <filtertype> ::= '=' | '~=' | '<=' | '>='

RETURN VALUES
=============

     All routines except $dua->show() and $dua->find() will return 1 on
     success, 0 otherwise. For those routines which return associative
     arrays ( $dua->show() and $dua->find() ), the array is returned
     empty if an error occurs. The description of the problem may be
     obtained by use of $dua->error().

AUTHOR
======

     Converted from duaperl Version 1.0a3 to a Perl 5 module by
     Stephen Pillinger, School of Computer Science,
     The University of Birmingham, UK.

     duaperl was written by Eric W. Douglas, California State University,
     Fresno.

SEE ALSO
========

   perl(1), ldap(3).

provides screen dump of Perl data.
**********************************

NAME
====

   Dumpvalue - provides screen dump of Perl data.

SYNOPSIS
========

     use Dumpvalue;
     my $dumper = new Dumpvalue;
     $dumper->set(globPrint => 1);
     $dumper->dumpValue(\*::);
     $dumper->dumpvars('main');

DESCRIPTION
===========

Creation
--------

   A new dumper is created by a call

     $d = new Dumpvalue(option1 => value1, option2 => value2)

   Recognized options:

`arrayDepth', `hashDepth'
     Print only first N elements of arrays and hashes.  If false, prints
     all the elements.

compactDump, veryCompact
     Change style of array and hash dump.  If true, short array may be
     printed on one line.

`globPrint'
     Whether to print contents of globs.

`DumpDBFiles'
     Dump arrays holding contents of debugged files.

`DumpPackages'
     Dump symbol tables of packages.

`DumpReused'
     Dump contents of "reused" addresses.

`tick', `HighBit', `printUndef'
     Change style of string dump.  Default value of `tick' is `auto', one
     can enable either double-quotish dump, or single-quotish by setting it
     to `"' or `''.  By default, characters with high bit set are printed
     *as is*.

`UsageOnly'
     *very* rudimentally per-package memory usage dump.  If set, dumpvars
     calculates total size of strings in variables in the package.

unctrl
     Changes the style of printout of strings.  Possible values are unctrl
     and quote.

subdump
     Whether to try to find the subroutine name given the reference.

bareStringify
     Whether to write the non-overloaded form of the stringify-overloaded
     objects.

quoteHighBit
     Whether to print chars with high bit set in binary or "as is".

stopDbSignal
     Whether to abort printing if debugger signal flag is raised.

   Later in the life of the object the methods may be queries with get()
method and set() method (which accept multiple arguments).

Methods
-------

dumpValue
          $dumper->dumpValue($value);
          $dumper->dumpValue([$value1, $value2]);

dumpValues
          $dumper->dumpValues($value1, $value2);

dumpvars
          $dumper->dumpvars('my_package');
          $dumper->dumpvars('my_package', 'foo', '~bar$', '!......');

     The optional arguments are considered as literal strings unless they
     start with `~' or !, in which case they are interpreted as regular
     expressions (possibly negated).

     The second example prints entries with names foo, and also entries
     with names which ends on bar, or are shorter than 5 chars.

set_quote
          $d->set_quote('"');

     Sets `tick' and unctrl options to suitable values for printout with
     the given quote char.  Possible values are `auto', `'' and `"'.

set_unctrl
          $d->set_unctrl('"');

     Sets unctrl option with checking for an invalid argument.  Possible
     values are unctrl and quote.

compactDump
          $d->compactDump(1);

     Sets compactDump option.  If the value is 1, sets to a reasonable big
     number.

veryCompact
          $d->veryCompact(1);

     Sets compactDump and veryCompact options simultaneously.

set
          $d->set(option1 => value1, option2 => value2);

get
          @values = $d->get('option1', 'option2');

Protects against sloppy use of files.
*************************************

NAME
====

   Dunce::Files - Protects against sloppy use of files.

SYNOPSIS
========

     use Dunce::Files;

     # open() warns you that you forgot to check if it worked.
     open(FILE, $filename);
     while( <FILE> ) {
         chop;     # chop() warns you to use chomp() instead
         print;
     }
     exit;

     # *FILE will warn you that you forgot to close it.

DESCRIPTION
===========

   One of the most common programming mistakes is failing to check if an
open() worked.  Same goes for other file and system operations.  The world
outside your program is a scary, unreliable place, and things you try to
do with it might not always work.

   Dunce::Files makes trick versions of all file functions which do some
basic sanity checking.

   If used in void context (ie. you didn't check to see if it worked),
they will throw a warning.  If the function returns a filehandle (like
open() and readdir()) that filehandle will complain if its never closed,
or if its never used.

   This module is useful for automated code auditing.  Its also useful as
a dunce cap to place on junior programmers, make sure they're not making
silly mistakes.

   The list of overridden functions is:

     chdir
     chmod
     chop
     chown
     chroot
     dbmopen
     flock
     link
     mkdir
     open
     opendir
     read
     rename
     rmdir
     seek
     seekdir
     symlink
     syscall
     sysseek
     system
     syswrite
     truncate
     unlink
     write

   A few functions have some additional warnings:

chmod
     Often, people will gratuitiously grant files more permissions than
     they really need causing unnecessary security problems.  Making
     non-program files executable is a common mistake.  Unnecessarily
     giving world write permission is another.  Dunce::Files will throw a
     warning if either is detected.

     *Note: It may be worthwhile to split this out into a seperate module*

chop
     chop() works a little differently.  Using it in void context is fine,
     but if it looks like you're using it to strip newlines it will throw a
     warning reminding you about chomp().

     NOTE chop() was non-overridable before 5.7.0, so this feature will
     only work on that perl or newer.

dbmopen
     dbmopen() will warn you if the hash argument you gave it already
     contains data.

open
     *NOT YET IMPLEMENTED*

     open() will warn you if you don't close its filehandle explicitly
     before the program ends.  It will also warn if you give it an already
     open filehandle.

     XXX I'd also like to have made sure $! is checked, but $! can't be
     usefully tied. :(

     #'# # Waiting on postamble callbacks in Function::Override.

opendir
     *NOT YET IMPLEMENTED*

     Same as open().

CAVEATS
=======

   Because of the way perl compiles, the following code will produce a
'Name main::FILE used only once: possible typo' where it shouldn't.

     use Dunce::Files;
     open(FILE, $filename) or die $!;
     print <FILE>;

   Because open() is really Dunce::Files::open() and not the real open,
Perl doesn't realize that FILE is the filehandle *FILE, so it thinks its
only being used once.

   Turns out this is a useful feature.  If you close FILE the warning will
go away, and you should have closed it in the first place.

TODO
====

   Make a flag to have Dunce::Files die instead of just warning.

   Complete Function::Override so I can finish open() and opendir().

AUTHOR
======

   Michael G Schwern <schwern@pobox.com> with help from crysflame and
Simon Cozens.  Thanks to Jay A. Kreibich for the chop() idea.

SEE ALSO
========

   See Function/Override,

closure-in-a-box for simple scalars
***********************************

NAME
====

   DynScalar - closure-in-a-box for simple scalars

SYNOPSIS
========

     use DynScalar;  # imports as dynamic()
     use strict;
     use vars '$name';

     my $foo = dynamic { "Hello, $name!\n" };
     for $name ("Jeff", "Joe", "Jonas") { print $foo }

DESCRIPTION
===========

   This module creates closures, and masks them as objects that stringify
themselves when used.  This allows you to make incredibly simplistic string
templates:

     use DynScalar 'delay';  # import as delay()
     use strict;
     use vars qw( $name $age $sex );

     my $template = delay {
       "Hello, $name.  You're a good-looking $age-year-old $sex.\n"
     };

     while (my $rec = get_person()) {
       ($name,$age,$sex) = $rec->features;
       print $template;
     }

   You can embed arbitrarily complex code in the block.

CAVEATS
=======

   Lexically scoped variables can be used inside the block, but you must
do so with caution.  The variable must be visible, as in this example:

     use DynScalar;

     my $name;
     my $str = dynamic { $name };
     for ("Jeff", "Joe", "Jonas") { $name = $_; print $str }

   If you use the lexically scoped variable as the iterator variable in
the loop, however, Perl will scope it even further, and the `DynScalar'
object will not be able to see it:

     use DynScalar;

     my $name;
     my $str = dynamic { $name };
     # this next line will not print as you hoped
     for $name ("Jeff", "Joe", "Jonas") { print $str }

AUTHOR
======

     Jeff "japhy" Pinyan
     CPAN ID: PINYAN
     japhy@pobox.com
     http://www.pobox.com/~japhy/

Dynamically load C libraries into Perl code
*******************************************

NAME
====

   DynaLoader - Dynamically load C libraries into Perl code

   dl_error(), dl_findfile(), dl_expandspec(), dl_load_file(),
dl_unload_file(), dl_find_symbol(), dl_find_symbol_anywhere(),
dl_undef_symbols(), dl_install_xsub(), dl_load_flags(), bootstrap() -
routines used by DynaLoader modules

SYNOPSIS
========

     package YourPackage;
     require DynaLoader;
     @ISA = qw(... DynaLoader ...);
     bootstrap YourPackage;

     # optional method for 'global' loading
     sub dl_load_flags { 0x01 }

DESCRIPTION
===========

   This document defines a standard generic interface to the dynamic
linking mechanisms available on many platforms.  Its primary purpose is to
implement automatic dynamic loading of Perl modules.

   This document serves as both a specification for anyone wishing to
implement the DynaLoader for a new platform and as a guide for anyone
wishing to use the DynaLoader directly in an application.

   The DynaLoader is designed to be a very simple high-level interface
that is sufficiently general to cover the requirements of SunOS, HP-UX,
NeXT, Linux, VMS and other platforms.

   It is also hoped that the interface will cover the needs of OS/2, NT
etc and also allow pseudo-dynamic linking (using `ld -A' at runtime).

   It must be stressed that the DynaLoader, by itself, is practically
useless for accessing non-Perl libraries because it provides almost no
Perl-to-C 'glue'.  There is, for example, no mechanism for calling a C
library function or supplying arguments.  A C::DynaLib module is available
from CPAN sites which performs that function for some common system types.

   DynaLoader Interface Summary

     @dl_library_path
     @dl_resolve_using
     @dl_require_symbols
     $dl_debug
     @dl_librefs
     @dl_modules
                                                     Implemented in:
     bootstrap($modulename)                               Perl
     @filepaths = dl_findfile(@names)                     Perl
     $flags = $modulename->dl_load_flags                  Perl
     $symref  = dl_find_symbol_anywhere($symbol)          Perl

     $libref  = dl_load_file($filename, $flags)           C
     $status  = dl_unload_file($libref)                   C
     $symref  = dl_find_symbol($libref, $symbol)          C
     @symbols = dl_undef_symbols()                        C
     dl_install_xsub($name, $symref [, $filename])        C
     $message = dl_error                                  C

@dl_library_path
     The standard/default list of directories in which dl_findfile() will
     search for libraries etc.  Directories are searched in order:
     $dl_library_path[0], [1], ... etc

     @dl_library_path is initialised to hold the list of 'normal'
     directories (`/usr/lib', etc) determined by Configure
     (`$Config{'libpth'}').  This should ensure portability across a wide
     range of platforms.

     @dl_library_path should also be initialised with any other directories
     that can be determined from the environment at runtime (such as
     LD_LIBRARY_PATH for SunOS).

     After initialisation @dl_library_path can be manipulated by an
     application using push and unshift before calling dl_findfile().
     Unshift can be used to add directories to the front of the search
     order either to save search time or to override libraries with the
     same name in the 'normal' directories.

     The load function that dl_load_file() calls may require an absolute
     pathname.  The dl_findfile() function and @dl_library_path can be
     used to search for and return the absolute pathname for the
     library/object that you wish to load.

@dl_resolve_using
     A list of additional libraries or other shared objects which can be
     used to resolve any undefined symbols that might be generated by a
     later call to load_file().

     This is only required on some platforms which do not handle dependent
     libraries automatically.  For example the Socket Perl extension
     library (`auto/Socket/Socket.so') contains references to many socket
     functions which need to be resolved when it's loaded.  Most platforms
     will automatically know where to find the 'dependent' library (e.g.,
     `/usr/lib/libsocket.so').  A few platforms need to be told the
     location of the dependent library explicitly.  Use @dl_resolve_using
     for this.

     Example usage:

          @dl_resolve_using = dl_findfile('-lsocket');

@dl_require_symbols
     A list of one or more symbol names that are in the library/object file
     to be dynamically loaded.  This is only required on some platforms.

@dl_librefs
     An array of the handles returned by successful calls to
     dl_load_file(), made by bootstrap, in the order in which they were
     loaded.  Can be used with dl_find_symbol() to look for a symbol in
     any of the loaded files.

@dl_modules
     An array of module (package) names that have been bootstrap'ed.

dl_error()
     Syntax:

          $message = dl_error();

     Error message text from the last failed DynaLoader function.  Note
     that, similar to errno in unix, a successful function call does not
     reset this message.

     Implementations should detect the error as soon as it occurs in any of
     the other functions and save the corresponding message for later
     retrieval.  This will avoid problems on some platforms (such as SunOS)
     where the error message is very temporary (e.g., dlerror()).

$dl_debug
     Internal debugging messages are enabled when $dl_debug is set true.
     Currently setting $dl_debug only affects the Perl side of the
     DynaLoader.  These messages should help an application developer to
     resolve any DynaLoader usage problems.

     $dl_debug is set to `$ENV{'PERL_DL_DEBUG'}' if defined.

     For the DynaLoader developer/porter there is a similar debugging
     variable added to the C code (see dlutils.c) and enabled if Perl was
     built with the *-DDEBUGGING* flag.  This can also be set via the
     PERL_DL_DEBUG environment variable.  Set to 1 for minimal information
     or higher for more.

dl_findfile()
     Syntax:

          @filepaths = dl_findfile(@names)

     Determine the full paths (including file suffix) of one or more
     loadable files given their generic names and optionally one or more
     directories.  Searches directories in @dl_library_path by default and
     returns an empty list if no files were found.

     Names can be specified in a variety of platform independent forms.
     Any names in the form *-lname* are converted into `libname.*', where
     `.*' is an appropriate suffix for the platform.

     If a name does not already have a suitable prefix and/or suffix then
     the corresponding file will be searched for by trying combinations of
     prefix and suffix appropriate to the platform: "$name.o", "lib$name.*"
     and "$name".

     If any directories are included in @names they are searched before
     @dl_library_path.  Directories may be specified as *-Ldir*.  Any other
     names are treated as filenames to be searched for.

     Using arguments of the form `-Ldir' and `-lname' is recommended.

     Example:

          @dl_resolve_using = dl_findfile(qw(-L/usr/5lib -lposix));

dl_expandspec()
     Syntax:

          $filepath = dl_expandspec($spec)

     Some unusual systems, such as VMS, require special filename handling
     in order to deal with symbolic names for files (i.e., VMS's Logical
     Names).

     To support these systems a dl_expandspec() function can be implemented
     either in the `dl_*.xs' file or code can be added to the autoloadable
     dl_expandspec() function in `DynaLoader.pm'.  See `DynaLoader.pm' for
     more information.

dl_load_file()
     Syntax:

          $libref = dl_load_file($filename, $flags)

     Dynamically load $filename, which must be the path to a shared object
     or library.  An opaque 'library reference' is returned as a handle for
     the loaded object.  Returns undef on error.

     The $flags argument to alters dl_load_file behaviour.  Assigned bits:

          0x01  make symbols available for linking later dl_load_file's.
                (only known to work on Solaris 2 using dlopen(RTLD_GLOBAL))
                (ignored under VMS; this is a normal part of image linking)

     (On systems that provide a handle for the loaded object such as SunOS
     and HPUX, $libref will be that handle.  On other systems $libref will
     typically be $filename or a pointer to a buffer containing $filename.
     The application should not examine or alter $libref in any way.)

     This is the function that does the real work.  It should use the
     current values of @dl_require_symbols and @dl_resolve_using if
     required.

          SunOS: dlopen($filename)
          HP-UX: shl_load($filename)
          Linux: dld_create_reference(@dl_require_symbols); dld_link($filename)
          NeXT:  rld_load($filename, @dl_resolve_using)
          VMS:   lib$find_image_symbol($filename,$dl_require_symbols[0])

     (The dlopen() function is also used by Solaris and some versions of
     Linux, and is a common choice when providing a "wrapper" on other
     mechanisms as is done in the OS/2 port.)

dl_unload_file()
     Syntax:

          $status = dl_unload_file($libref)

     Dynamically unload $libref, which must be an opaque 'library
     reference' as returned from dl_load_file.  Returns one on success and
     zero on failure.

     This function is optional and may not necessarily be provided on all
     platforms.  If it is defined, it is called automatically when the
     interpreter exits for every shared object or library loaded by
     DynaLoader::bootstrap.  All such library references are stored in
     @dl_librefs by DynaLoader::Bootstrap as it loads the libraries.  The
     files are unloaded in last-in, first-out order.

     This unloading is usually necessary when embedding a shared-object
     perl (e.g.  one configured with -Duseshrplib) within a larger
     application, and the perl interpreter is created and destroyed
     several times within the lifetime of the application.  In this case
     it is possible that the system dynamic linker will unload and then
     subsequently reload the shared libperl without relocating any
     references to it from any files DynaLoaded by the previous
     incarnation of the interpreter.  As a result, any shared objects
     opened by DynaLoader may point to a now invalid 'ghost' of the
     libperl shared object, causing apparently random memory corruption
     and crashes.  This behaviour is most commonly seen when using Apache
     and mod_perl built with the APXS mechanism.

          SunOS: dlclose($libref)
          HP-UX: ???
          Linux: ???
          NeXT:  ???
          VMS:   ???

     (The dlclose() function is also used by Solaris and some versions of
     Linux, and is a common choice when providing a "wrapper" on other
     mechanisms as is done in the OS/2 port.)

dl_loadflags()
     Syntax:

          $flags = dl_loadflags $modulename;

     Designed to be a method call, and to be overridden by a derived class
     (i.e. a class which has DynaLoader in its @ISA).  The definition in
     DynaLoader itself returns 0, which produces standard behavior from
     dl_load_file().

dl_find_symbol()
     Syntax:

          $symref = dl_find_symbol($libref, $symbol)

     Return the address of the symbol $symbol or undef if not found.  If
     the target system has separate functions to search for symbols of
     different types then dl_find_symbol() should search for function
     symbols first and then other types.

     The exact manner in which the address is returned in $symref is not
     currently defined.  The only initial requirement is that $symref can
     be passed to, and understood by, dl_install_xsub().

          SunOS: dlsym($libref, $symbol)
          HP-UX: shl_findsym($libref, $symbol)
          Linux: dld_get_func($symbol) and/or dld_get_symbol($symbol)
          NeXT:  rld_lookup("_$symbol")
          VMS:   lib$find_image_symbol($libref,$symbol)

dl_find_symbol_anywhere()
     Syntax:

          $symref = dl_find_symbol_anywhere($symbol)

     Applies dl_find_symbol() to the members of @dl_librefs and returns
     the first match found.

dl_undef_symbols()
     Example

          @symbols = dl_undef_symbols()

     Return a list of symbol names which remain undefined after
     load_file().  Returns `()' if not known.  Don't worry if your
     platform does not provide a mechanism for this.  Most do not need it
     and hence do not provide it, they just return an empty list.

dl_install_xsub()
     Syntax:

          dl_install_xsub($perl_name, $symref [, $filename])

     Create a new Perl external subroutine named $perl_name using $symref
     as a pointer to the function which implements the routine.  This is
     simply a direct call to newXSUB().  Returns a reference to the
     installed function.

     The $filename parameter is used by Perl to identify the source file
     for the function if required by die(), caller() or the debugger.  If
     $filename is not defined then "DynaLoader" will be used.

bootstrap()
     Syntax:

     bootstrap($module)

     This is the normal entry point for automatic dynamic loading in Perl.

     It performs the following actions:

        * locates an auto/$module directory by searching @INC

        * uses dl_findfile() to determine the filename to load

        * sets @dl_require_symbols to `("boot_$module")'

        * executes an `auto/$module/$module.bs' file if it exists
          (typically used to add to @dl_resolve_using any files which are
          required to load the module on the current platform)

        * calls dl_load_flags() to determine how to load the file.

        * calls dl_load_file() to load the file

        * calls dl_undef_symbols() and warns if any symbols are undefined

        * calls dl_find_symbol() for "boot_$module"

        * calls dl_install_xsub() to install it as "${module}::bootstrap"

        * calls &{"${module}::bootstrap"} to bootstrap the module (actually
          it uses the function reference returned by dl_install_xsub for
          speed)

AUTHOR
======

   Tim Bunce, 11 August 1994.

   This interface is based on the work and comments of (in no particular
order): Larry Wall, Robert Sanders, Dean Roehrich, Jeff Okamoto, Anno
Siegel, Thomas Neumann, Paul Marquess, Charles Bailey, myself and others.

   Larry Wall designed the elegant inherited bootstrap mechanism and
implemented the first Perl 5 dynamic loader using it.

   Solaris global loading added by Nick Ing-Simmons with design/coding
assistance from Tim Bunce, January 1996.

SYNOPSIS
========

   use EMatrix; my $titleHash = {  "0,0" => "Header1",  "0,1" => "Header2",
"0,2" => "Header3",  "0,3" => "Header4",  "0,4" => "Header5", };

   my $table; $table = $mw->Scrolled('EMatrix',    -cols          => 5,
-bd            => 2,    -bg            => 'white',    -titlerows     => 1,
  -variable      => $titleHash, );

   $table->tagConfigure('title',    -bg => 'tan',    -fg => 'black',
-relief => 'raised' );

   $table->pack(-expand => 1, -fill => 'both');

DESCRIPTION
===========

   The EMatrix widget is a derived widget that provides 6 additional
methods above and beyond the traditional Tk::TableMatrix widget.

METHODS
=======

   *bindRow(-index =* int, -sequence => string, -command => sub ref);>

   bindRow binds a particular sequence to the subroutine at the row
specified by the "-index" option.  Note that binding row 0 will bind the
column headers, which may not be what you want.

   You cannot currently bind a range of rows (i.e. -index=>2-5) for now,
though that is an enhancement I may add in the future.

   e.g. $em->bindRow( 	-index    => 2,    -sequence => '<Control-g>',
-command  => sub{ print "Hello World!" } );

   *bindCol(-index =* int, -sequence => string, -command => sub ref);>

   This method is identical to 'bindRow()' above, except that it binds a
column instead of a row (duh).

   *getRow(index, ?range?);*

   Returns the row at specified index as an array in list context, or an
array reference in scalar context.

   If the range is omitted (or 'end' is used), it will return the contents
of all cells in that row (including empty cells).  Otherwise, it will only
return the contents of the cells up to the specified range, starting at
index 0.

   *getRowHash(index, ?range?, ?tie?);*

   Returns the row at the specified index as a hash.  The key is the cell
value ('0,1' for example), the value is the content of the cell.

   If a second index is omitted (or 'end' is used), it will return the
contents of all cells in that row (including empty cells).  Otherwise, it
will only return the contents of the cells up to the specified range
starting at index 0.

   If the string 'tie' is included, the hash will be returned in cell
order (left to right).  To use this option you must have the Tie::IxHash
module installed.

   *getCol(index, ?range?);*

   Returns the column at the specified index as an array in list context,
or an array reference in scalar context.  See 'getRow()' for more details.

   *getColHash(index, ?range?, ?tie?);*

   Returns the column at the specified index as a hash in list context, or
a hash reference in scalar context.  See 'getRowHash()' above for more
details.

   If the string 'tie' is included as an argument, the hash will be
returned in cell order (top to bottom).  This requires the Tie::IxHash
module.

FUTURE RELEASES
===============

  1. Cell ranges - allow a range of cells to be selected at a particular
     index.  e.g. $dw->getRow(0, 3-5); # Would return the contents of
     cells 3, 4 and 5 at row 0.

  2. A row of buttons on the left side to mimic MS Excel behavior.

  3. Methods to make importing Excel spreadsheets a snap (via the
     ParseExcel module perhaps).

AUTHOR
======

   Daniel Berger, djberg96@hotmail.com

   Many thanks go out to John Cerney for providing help with this module
(especially the bind methods).

SEE ALSO
========

   Tk::TableMatrix, Tie::IxHash.

module to implement common text editing functions
*************************************************

NAME
====

   String::Edit - module to implement common text editing functions

   chopexpr - returns args after they've been chopped

   chompexpr - returns args after they've been chomped

   trim - remove leading and trailing white space

   trimleft - remove leading white space

   trimright - remove trailing white space

   sqsps - trim, then squeeze internal white space

   detab - convert tabs to spaces

   set_tab_width - set tab for detab() function

   detab_till - tab through a particular point

   commify - put commas in numbers

   unmeta - convert 8bit chars to M-<seven bit>

   uncontrol - convert control chars to ^a, etc.

   uncontrolmeta - make both control and metachars legible

DESCRIPTION
===========

   The String::Edit module implements various commonly executed functions
to maniuplate text.  All share the following properties:  they may be
called with one or more args; they leave their arguments unchanged,
instead returning the result of the change; and raise an exception if the
function is called without any arguments at all or else with many
arguments while in a scalar context.

   Here are the functions defined by the module:

Chopping Functions
------------------

chopexpr
     Each argument is chop()ed.  This takes care of the common problem of
     wanting to chop() an expression, like backticks.

chompexpr
     Like chopexpr() but calling chomp() instead.

Trimming Functions
------------------

trim
     All leading and trailing white space will be removed from the
     resulting string(s).  Strings with embedded newlines may not be
     handled as you expect: internal newlines will be ignored.

trimleft
     Like trim() but only the left-hand side of the string will be changed.

trimright
     Like trim() but only the right-hand side of the string will be
     changed.

sqsps
     First trim()s the string, then converts all runs of white space
     internally into just one space.

Tab Conversion Functions
------------------------

detab
     All tabs are converted into the appropriate number of spaces.  Note
     that characters of width other than one (like backspace, null, etc),
     will always be counted as length one.

detab_till
     First arg is the width of each tab, then remaining arguments are as
     in detab().

set_tab_width
     Reset internal tab width for further calls to detab().

Control and Meta-character Conversions
--------------------------------------

uncontrol
     Convert control chars to "^" plus the capital character.  For example,
     <CONTROL-H> goes to "^H".  <DELETE> will be represented as "^?".

unmeta
     Convert 8-bit chars to "M-" plus the character with the 8th bit
     stripped.  Octal 210 looks like "M-^H" though (4 chars).

uncontrolmeta
     Convert metacharacters to their printing equivalents and control
     characters to theirs.

Numerical Text Functions
------------------------

commify
     Put commas every 3 places in the integer portion of a number.

EXAMPLES
========

   Here are some examples of calling a few of these:

     print "Today is <", chopexpr(`date`), ">\n";

     $better = trim("  stuff\t\n");
     @best = trim(@old);

     $n = commify(65358979);

     set_tab_width(4);
     while (<>) {
         chop;
         print uncontrolmeta(detab($_)), "\n";
     }

INHERITANCE
===========

   You can define your own module that uses String::Edit's argument
checking and associated properties.  Inherit from String::Edit (you need
its AUTOLOAD() function), and place an entry in the %Command_Table from
that module.  The key is the name of the function, and the value is the
function to call for each of the functions arguments.  For example:

     package Sample;
     require String::Edit;
     require Exporter;
     @ISA = qw(Exporter String::Edit);
     @EXPORT = qw(intmany);
     $String::Edit::Command_Table{intmany} = sub {
         package String::Edit;
         warn "$AUTOLOAD called!";  # dang inheritance
         s/\..*//;  # $_ is a true global!!
     };
     1;

   Now someone can call it this way:

     use Sample;
     @short = intmany(2.12, 3.23, 23.122);

   and @short will be

     (2, 3, 23)

BUGS
====

   If you call these with a list of length 0, they will be very unhappy.

AUTHOR
======

   Tom Christiansen `<tchrist@perl.com>'.

Enlightenment Window Manager IPC Library
****************************************

NAME
====

   Eesh - Enlightenment Window Manager IPC Library

SYNOPSIS
========

     ## Long form:
     use Eesh qw( e_open e_send e_recv ) ;

     e_open() ;
     print e_recv( 'window_list' ) ;
     e_send( 'restart' ) ;

     ## Short form
     use Eesh qw( :all ) ;
     e_open() ;
     print "$_\n" for ( e_window_list ) ;

     my $win_id = (grep { /Terminal/ } e_window_list)[0] ;
     e_win_op( $win_id, 'raise' ) ;

     ## For non-blocking receives:
     my $hmmm = e_recv( { non_blocking => 1 } ) ;

DESCRIPTION
===========

   Eesh.pm provides simple wrappers around the routines from eesh
(included).

   This code is in alpha mode, please let me know of any improvements, and
patches are especially welcome.

Basic Communications Functions
------------------------------

e_open
     Opens communications with E.

e_send
     Sends to E.

e_recv
     Receives from E, blocking until data is received.

     Can send strings first and then wait for the result:

          my @windows = split( /^/m, e_recv( 'window_list' ) ) ;

     Can be called non-blocking:

          e_send( 'window_list' ) ;

          my $hmmm ;
          $hmmm = e_recv( { non_blocking => 1 } ) until defined $hmmmm ;

e_fileno
     Returns the file number of the connection to E, useful for select
     loops.

High level functions
--------------------

   These are simple functions that wrap around E IPC commands.  The really
simple commands aren't wrapped, since it wouldn't save much typing (though
they would provide varying levels of mispeled option detection):

     e_send( 'advanced_focus new_window_focus on' ) ;

   vs.

     e_enable_advanced_focus_new_window_focus() ;
     e_advanced_focus_new_window_focus( 'on' ) ;
     e_advanced_focus( 'new_window_focus', 'on' ) ;
     e_enable( 'advanced_focus', 'new_window_focus' ) ;

   Perhaps we could provide something like:

     e_enable_new_window_focus() ;

   which would be a savings and allow for safer programming (since a
mispelling would show up under 'use strict').  But that's only viable so
long as no identifier is used more than once in the entire command set,
which I can't guarantee.

   If you don't see a function here that you need, ask for it or send a
patch.  See the eesh help command for more documentation on these.

e_backgrounds
     Returns a list of all background ids, one per element.

e_delete_background
     Deletes a background

e_background
     Returns a hash reference to the values defined for a particular
     background:

          print e_background( shift e_backgrounds )->{'bg.solid'}, "\n" ;

e_set_background
     Takes a background id and either a hash or a list of key/value pairs
     and sets them:

          e_set_background( $bg_id, 'bg.file' => $filename ) ;

e_focused
     A short form of e_set_focus( '?' ) :

          my $win_id = e_focused() ;

e_internal_list
     Returns the requested list:

          e_internal_list( 'menus' ) ;

     might yield:

          ('1400509','14000f9')

     Note that spaces and newlines are stripped, and that these are
     strings, not numbers.

e_list_class
     Returns a list of the supplied class.

          e_list_class( 'backgrounds' ) ;

     should return the same list as e_backgrounds().

e_list_themes
     Returns a list of themes.

e_modules
     Returns a list of modules.  Don't ask me why this isn't
     "list_modules" or "modules_list".

e_remember
     Takes a window ID and a parameter.  The window ID may be the full item
     returned from e_window_list(), or just the ID portion.

e_set_focus
     Can take a window ID, the full ID returned from window_list().

     See e_focused() for a short form of e_set_focus( '?' ).

e_win_op
     Takes a window ID, or one of the values returned by e_window_list()
     and performs a win_op on it.

     If used in a non-void context, this will block and return any data
     received.  So don't do that if you might not get anything back.

e_window_list
     Returns a list of strings containing window IDs and titles:

          (
             '2400006 : Terminal',
             '3c00080 : VIM - ~/src/Eesh/Eesh.pm',
             ...
          )

     The leading whitespace and trailing newlines are trimmed.

     These may be passed in anywhere a window ID is needed, such as
     e_win_op() or e_iconify().

LICENSE
=======

   Copyright (C) 2000 Barrie Slaymaker, Carsten Haitzler, Geoff Harrison
and various contributors

   Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
in all copies of the Software, its documentation and marketing & publicity
materials, and acknowledgment shall be given in the documentation,
materials and software packages that this Software was used.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

AUTHORS
=======

   Eesh: Barrie Slaymaker <barries@slaysys.com>

   eesh: Carsten Haitzler, Geoff Harrison and various contributors

SEE ALSO
========

   eesh

Redefine Perl's system primitives to work inside of Emacs
*********************************************************

NAME
====

   Emacs - Redefine Perl's system primitives to work inside of Emacs

SYNOPSIS
========

     perlmacs -w -MEmacs -e main -- --display :0.0 file.txt

     #! /usr/bin/perlmacs
     use Emacs;
     use Emacs::Lisp;
     setq { $mail_self_blind = t; };
     exit main ($0, "-q", @ARGV);

DESCRIPTION
===========

   This module replaces STDIN, STDOUT, `STDERR', %ENV, %SIG, exit, and
warn (via `$SIG{__WARN__}') with versions that work safely within an Emacs
session.  In Perlmacs, it also defines a function named main, which
launches an Emacs editing session from within a script.

STDIN
-----

   Reading a line from Perl's STDIN filehandle causes a string to be read
from the minibuffer with the prompt `"Enter input: "'.  To show a
different prompt, use:

     $string = &read_string ("Prompt: ");

STDOUT
------

   Printing to Perl's STDOUT filehandle inserts text into the current
buffer as though typed, unless you have changed the Lisp variable
`standard-output' to do something different.

STDERR and `warn'
-----------------

   Perl's warn operator and `STDERR' filehandle are redirected to the
minibuffer.

%ENV
----

   Access to %ENV is redirected to the Lisp variable `process-environment'.

%SIG
----

   Setting signal handlers is not currently permitted under Emacs.

exit
----

   exit calls `kill-emacs'.

main (CMDLINE)
--------------

   When you `use Emacs' in a *perlmacs* script, a Perl sub named main may
be used to invoke the Emacs editor.  This makes it possible to put
customization code, which would normally appear as Lisp in `~/.emacs',
into a Perl script.

   NOTE: This function does not work under EPL.  You have to have Perlmacs
to use it.  See `"EPL AND PERLMACS"', see Emacs/Lisp.

   For example, this startup code

     (setq
      user-mail-address "gnaeus@perl.moc"
      mail-self-blind t
      mail-yank-prefix "> "
      )

     (put 'eval-expression 'disabled nil)

     (global-font-lock-mode 1 t)
     (set-face-background 'highlight "maroon")
     (set-face-background 'region "Sienna")

   could be placed in a file with the following contents:

     #! /usr/local/bin/perlmacs

     use Emacs;
     use Emacs::Lisp;

     setq {
     	$user_mail_address = 'gnaeus@perl.moc';
     	$mail_self_blind = t;
     	$mail_yank_prefix = '> ';
     	$eval_expression{\*disabled} = undef;
     };

     &global_font_lock_mode(1, t);
     &set_face_background(\*highlight, "maroon");
     &set_face_background(\*region, "Sienna");

     exit main($0, "-q", @ARGV);

   When you wanted to run Emacs, you would invoke this program.

   The arguments to main correspond to the `argv' of the main function in
a C program.  The first argument should be the program's invocation name,
as in this example.  -q inhibits running `~/.emacs' (which is the point,
after all).

BUGS
====

   * Problems with `main'.

     `main()' doesn't work under EPL.  It may open an X display and not
     close it.  Those are the most obvious of many problems with main.

     The thing is, Emacs was not written with the expectation of being
     embedded in another program, least of all a language interpreter such
     as Perl.  Therefore, when Emacs is told to exit, it believes the
     process is really about to exit, and it neglects to tidy up after
     itself.

     For best results, the value returned by main should be passed to
     Perl's exit soon, as in this code:

          exit (main($0, @args));

COPYRIGHT
=========

   Copyright (C) 1998-2001 by John Tobey, jtobey@john-edwin-tobey.org.
All rights reserved.

     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; see the file COPYING.  If not, write to the
     Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
     MA 02111-1307  USA

SEE ALSO
========

   See Perl (perl.info), Emacs/Lisp, emacs.

Protocol implementation and data conversions for Emacs Perl
***********************************************************

NAME
====

   Emacs::EPL - Protocol implementation and data conversions for Emacs Perl

SYNOPSIS
========

     use Emacs::EPL ':server';
     Emacs::EPL::loop;

DESCRIPTION
===========

   This module is used internally by `epl.el' and Emacs::Lisp.

   If you use eval to catch errors in Lisp functions, and `$@' contains a
string beginning with `'.Emacs::EPL'' (note initial dot), be sure to die
with the same string before returning control to Lisp.

Protocol State Transition Table
-------------------------------

   This stuff is mainly for the benefit of the author.

     NO.   CONSTRAINTS            INITIAL       MSG CLASS    FINAL
     ----- ---------------------- ------------- ------------ --------------
     (1)                          <0>           START        <1>
     (2)                          <1>           RAISE        <0>
     (3)                          <1>           RETURN       <2,0>
     (4)                          <2,0>         RETURN       <0>
     (5)                          <2,n>         UNREF        <3,0,n>
     (6)                          <2,n>         CALL         <2,n+1>
     (7)   n>0                    <2,n>         RETURN       <2,n-1>
     (13)                         <3,0,n>       RETURN       <2,n>
     (14)                         <3,m,n>       UNREF        <3,m+1,n>
     (15)  m>0                    <3,m,n>       RETURN       <3,m-1,n>

   The master is defined to be the process that sends the START message.
The other process is the slave.  It follows by induction from the table
that the master sends in states <0>, <2,n> for even n, and <3,m,n> for odd
m+n, and that the slave sends in all other states.

Message Classes
---------------

START
     Initiate communication, e.g. by running a subprocess or opening a
     connection.  The slave, if able, sends either a handshake (RETURN) or
     an exception (RAISE) in response.  If an exception is raised, no
     further communication is permitted.

          frame = 1

CALL
     Request to run code.  The calling process may be reentered by a
     subsequent CALL.  Our call ends when we receive a RETURN, RAISE, or
     POP in the same frame or we send a POP in a next inner frame.  If we
     receive a POP and subsequently use RETURN to exit this frame, the
     value we return will be ignored.

          frame += 1
          Lisp: funcall
          Perl: eval

RETURN
     Deliver the response to a CALL request (7), report successful startup
     (3), or mark the end of a series of UNREF requests (13, 15).  Not
     permitted in a popped frame.

     The three meanings could have been given different names: "return",
     "handshake", and "end_unrefs".

          frame -= 1
          Lisp: function return
          Perl: eval return

RAISE
     Return via exception mechanism, i.e., non-locally.  RAISE has the same
     protocol semantics as RETURN, except that it is permitted in popped
     frames.  It is expected that unless the user has taken specific steps
     (i.e., a "try" block) in the frame being returned to, the recipient
     will propagate the exception by sending another RAISE with the same or
     equivalent argument.

          frame -= 1
          Lisp: signal
          Perl: die

POP
     Either terminate communication (4), or exit the current frame (11,
     12).  This also says that we will ignore the argument of a subsequent
     RETURN from this frame (but will not ignore a RAISE value).

          frame -= 1
          Lisp: throw, kill-emacs
          Perl: exit, any nonlocal jump other than die

UNREF
     Send a list of handles that they have given us and that we promise
     never to use again, so that they may free up some resources.  Maybe
     the resources they free will include references to our stuff, so they
     may send us some UNREF requests before ending the list with a RETURN.
     They must not, however, issue any other kinds of requests until
     they've sent RETURN in this frame.

          frame += 1
          Lisp: perl-free-ref, whatever garbage-detection means is in effect
          Perl: DESTROY

Thoughts
--------

   Mark-and-sweep garbage collection could be supported by:

     (16)                         <2,n,@s>      GC           <4,n,@s>
     (17)                         <4,n,@s>      RETURN(0)    <2,n,@s>
     (18)                         <4,n,@s>      RETURN(1)    <5,0,n,@s>
     (19)                         <5,0,n,@s>    RETURN       <3,0,n,@s>
     (20)                         <5,m,n,@s>    MARK         <5,m+1,n,@s>
     (21)  m>=1                   <5,m,n,@s>    RETURN       <5,m-1,n,@s>

   Transition (17) gives the receiver a chance to refuse to support
mark-and-sweep or simply to indicate that all references are in use.
Which of these two is the case could be indicated by another return code.

   It might be useful to distinguish between recursive and nonrecursive
calls:

     (22)                         <2,n>         SIMPLE_CALL  <6,n>
     (23)                         <6,n>         RETURN       <2,n>

   Further state classes could be introduced to allow UNREF, GC, RAISE, or
POP operations during nonrecursive calls.  Better yet, add some boolean
parameters to the states we've got and to CALL.

   Hey, how about CALL/CC and START_THREAD.  Then of course you'd need
JOIN, YIELD, LOCK, WAIT, ... .  Pretty soon you'd have yourself an
operating system.  Yawn.

   The current EPL implementation uses only transitions of types (1) to
(15).

COPYRIGHT
=========

   Copyright (C) 2001 by John Tobey, jtobey@john-edwin-tobey.org.  All
rights reserved.

     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; see the file COPYING.  If not, write to the
     Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
     MA 02111-1307  USA

SEE ALSO
========

   See Emacs/Lisp, Emacs.

Demand-loaded protocol debugging support
****************************************

NAME
====

   Emacs::EPL::Debug - Demand-loaded protocol debugging support

SYNOPSIS
========

     $Emacs::EPL::debug = 'stderr'; # or filename, scalarref, handle
     Emacs::EPL::debug (@strings);

DESCRIPTION
===========

   See the Texinfo documentation about debugging options.

COPYRIGHT
=========

   Copyright (C) 2001 by John Tobey, jtobey@john-edwin-tobey.org.  All
rights reserved.

     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; see the file COPYING.  If not, write to the
     Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
     MA 02111-1307  USA

SEE ALSO
========

   See Emacs/Lisp, Emacs.

Support for writing Emacs extensions in Perl
********************************************

NAME
====

   Emacs::Lisp - Support for writing Emacs extensions in Perl

SYNOPSIS
========

In Emacs
--------

     M-x perl-eval-expression RET 2+2 RET
     M-x perl-eval-region RET
     M-x perl-eval-buffer RET
     ... and more ...

In Perl
-------

     use Emacs::Lisp;

     &switch_to_buffer('*scratch*');
     &insert("Hello, world!\n");

     setq { $cperl_font_lock = t };

     &add_hook(\*find_file_hooks,
     	      sub { &message("found a file!") });

     use Emacs::Lisp qw($emacs_version $epl_version);
     save_excursion {
     	&set_buffer(&get_buffer_create("*test*"));
     	&insert("This is ");
     	&insert(&featurep(\*::xemacs) ? "XEmacs" : "Emacs");
     	&insert(" version $emacs_version,\n");
     	&insert("EPL version $epl_version.\n");
     	&insert("Emacs::Lisp version is $Emacs::Lisp::VERSION.\n");
     };

DESCRIPTION
===========

   Emacs allows you to customize your environment using Lisp.  With EPL,
you can use Perl, too.  This module allows Perl code to call functions and
access variables of Lisp.

   You still need to learn some Lisp in order to understand *The Elisp
Manual*, which is the definitive reference for Emacs programming.  This
document assumes a basic understanding of Emacs commands and Lisp data
types.  I also assume familiarity with Perl's complex data structures
(described in Perlref (perl.info)) and objects (see
Perlobj (perl.info)).

Quick Start
-----------

   Run *emacs -l perl* and type:

     C-x p e &insert ("hello!\n") RET

   The string `"hello!"' should appear in your scratch buffer.  The Perl
sub `&insert' has called the Emacs Lisp insert function, which inserts its
string argument into the current buffer at point.

   Paste this text into a buffer, select it, and type `M-x
perl-eval-region RET':

     sub doit { &message("Cool, huh?"); }
     defun (\*perltest, interactive, \&doit);

   Type `M-x perltest RET'.  The text will appear in the minibuffer.
defun and interactive are used to create Emacs commands.

EPL AND PERLMACS
================

   Perlmacs was (is?) a project that embedded a Perl interpreter into the
Emacs binary so that it could run Lisp, Perl, or any combination of the
two.  It uses Perl's C interface, which requires patching and recompiling
Emacs.  As a result, each release is tied to a version of Emacs, it takes
a lot of time and disk space to build, and it is not very portable.

   EPL (Emacs Perl) accomplishes most of what Perlmacs can do, but it does
not suffer from the same drawbacks.  It uses unmodified Emacs and Perl and
lets them work together through IPC (pipes).  This may make some tasks
much slower, but it is much more convenient to install and upgrade, and it
works with XEmacs as well as Emacs 21 betas.

   For the time being, this module attempts to support both Perlmacs and
EPL.  The user-visible APIs are almost identical, except for EPL's lack of
`Emacs::main()'.

LISP SUPPORT FOR PERL
=====================

   Lisp code can check for Perl support using `(require 'perl)'.  In
Perlmacs, some of the Perl functions are built in, and others are defined
in `perl.el'.  When you use EPL, `epl.el' substitutes for the built-in
support, but the same `perl.el' is used.

Functions
---------

   The following Lisp functions do not rely on the Emacs::Lisp module.
Use `C-h f <function-name> RET' within Emacs to see their doc strings.

     perl-eval-expression  EXPRESSION
     perl-eval-region      START END
     perl-eval-buffer
     perl-load-file        NAME
     perl-eval             STRING &optional CONTEXT
     perl-call             SUB &optional CONTEXT &rest ARGS
     perl-eval-and-call    STRING &optional CONTEXT &rest ARGS
     perl-to-lisp          OBJECT
     perl-wrap             OBJECT
     perl-value-p          OBJECT
     perl-eval-raw         STRING &optional CONTEXT
     perl-call-raw         SUB &optional CONTEXT &rest ARGS
     make-perl-interpreter &rest ARGV
     perl-destruct         &optional INTERPRETER
     perl-gc               &optional PURGE
     perl-free-refs        &rest REFS

   The following Lisp variables affect the Perl interpreter and have doc
strings accessible via `C-h f <variable-name> RET'.  They are:

     perl-interpreter-program
     perl-interpreter-args
     perl-interpreter

Data Conversions
----------------

   When Perl calls a Lisp function, its arguments are converted to Lisp
objects, and the returned object is converted to a Perl value.  Likewise,
when Lisp calls Perl, the arguments are converted from Lisp to Perl and
the return values are converted to Lisp.

   * Lisp has three scalar types.

     Lisp integers, floats, and strings all become Perl scalars.  A simple
     Perl scalar becomes either an integer, a float, or a string.

     Interesting character encodings such as UTF-8 are not currently
     supported.  I don't even know what happens to 8-bit characters during
     string conversion.

   * Lisp symbols correspond to globrefs.

     Glob references become symbols in Lisp.  Underscores are swapped with
     hyphens in the name, since Perl prefers underscores and Lisp prefers
     hyphens.  See `' in this node for more information.

   * Lisp's `nil' is equivalent to Perl's `undef' or `()'.

     As an exception to the rule for symbols, `nil' in Lisp corresponds to
     undef in Perl.

     In Lisp, `nil' is really a symbol.  However, it is typically used as
     the boolean value false.  Glob references evaluate to *true* in
     boolean context.  It is much more natural to convert `nil' to undef.

   * Arrayrefs correspond to lists.

     Lists are a central data structure in Lisp.  To make it as easy as
     possible to pass lists to Lisp functions that require them, Perl array
     references are converted Lisp lists.  For example, the Perl expression
     such as

          ["x", ["y", 1]]

     is converted to

          '("x" ("y" 1))

     in Lisp.

   * Arrayref refs correspond to vectors.

     Adding \ to an arrayref makea it an arrayref ref, which becomes a
     vector in Lisp.  For example, `\[1, 2, undef]' becomes `[1 2 nil]'.

   * Conses that are not lists become Emacs::Lisp::Cons objects.

     Compatibility note:  Perlmacs does not have this feature.

          $x = &cons("left", "right");
          print ref($x);                # "Emacs::Lisp::Cons"
          print $x->car;                # "left"
          print $x->cdr;                # "right"

     But:

          $x = &cons ("top", undef);    # a Lisp list
          print ref($x);                # "ARRAY"
          print $x->[0];                # "top"

   * Conversion uses "deep" copying by default.

     Conversion of lists and vectors to arrayrefs and arrayref refs is
     recursive by default.  Changes made by Lisp to a list will not affect
     the Perl array of which it is a copy, nor will changes to a Perl array
     affect a Lisp list.  See `' in this node about converting cyclic
     structures.

   * There are ways to make "shallow" copies.

     A shallow copy simply wraps a Perl scalar in a Lisp object or vice
     versa.  Wrapped Perl values appear as a Lisp objects of type
     `perl-value'.  Wrapped Lisp values appear in Perl as objects of class
     `Emacs::Lisp::Object'.  See `' in this node for issues relating to
     wrapped data.

     Where a data type has no natural equivalent in the other language,
     shallow copying is the default.  Examples include Perl hashrefs and
     Lisp buffer objects.

     In Perl, the `lisp' function wraps its argument in a Lisp object.
     This allows Perl arrays to be passed by reference to Lisp functions.
     (Of course, the value returned by `lisp' is really a Perl value
     wrapped in a Lisp object wrapped in a Perl object.)

     An Emacs::Lisp::Object's `to_perl' method performs a deep copy (if
     the argument is Lisp data) or unwraps its argument (if it is Perl
     data).

     Lisp functions called through package Emacs::Lisp convert their return
     values using deep copying.  The same functions are accessible through
     Emacs::Lisp::Object, which does shallow conversion and always returns
     an Emacs::Lisp::Object object.

     These examples show how the data wrapping functions work:

          $x = lisp [1, 2, 3];
          print ref($x);           # "Emacs::Lisp::Object"
          print ref($x->to_perl);  # "ARRAY"
          print @{&list(2, 3)};    # "23"

          $x = Emacs::Lisp::Object::list(2, 3);
          print ref($x);           # "Emacs::Lisp::Object"
          print @{$x->to_perl};    # "23"

Scripts
-------

   Perlmacs can run Perl programs.  By default, Perlmacs is installed
under two names, *pmacs* and *perlmacs*.  Which name is used to invoke the
program determines how it parses its command line.

   If *perlmacs* is used (or, more precisely, any name containing
"*perl*"), it behaves like Perl.  For example,

     $ perlmacs script.pl

   runs the Perl program script.pl.

   When invoked as *pmacs*, it behaves like Emacs.  Example:

     $ pmacs file.txt

   This begins an editing session with `file.txt' in the current buffer.

   The first command line argument can override the invocation name.  If
it is *-emacs*, Emacs takes control.  If it is *-perl*, the program runs
in Perl mode.

   The *Emacs* module (that is, the Perl module named "Emacs") includes
support for starting an editing session from within a Perlmacs script.
See Emacs.

PERL SUPPORT FOR LISP
=====================

   The Emacs::Lisp module allows Perl programs to invoke Lisp functions
and handle Lisp variables as if they were Perl subs and variables.

   The directive `use Emacs::Lisp;' causes any use of a function not
defined in Perl to invoke the Lisp function of the same name (with hyphens
in place of underscores).  For example, this writes a message to the
standard error stream (in Perl mode) or displays it in the minibuffer:

     &message ("this is a test");

Functions
---------

   This code calls the hypothetical Lisp function `foo-bar' with arguments
4 and t.

     &foo_bar(4, t);

   The Lisp syntax for the same call would be

     (foo-bar 4 t)

   The ampersand (&) in the Perl example is not required, but it is needed
for functions, such as read, eval, and print, which are Perl keywords.
Using it with Emacs::Lisp is a good habit, so the examples in this
document include it.

   If you don't want an AUTOLOAD sub to affect your namespace, you may
either put parentheses after "`use Emacs::Lisp'" or import to a different
package, and use qualified function names.  For example:

     use Emacs::Lisp ();
     Emacs::Lisp::message("hello\n");

     {package L; use Emacs::Lisp;}
     L::message("goodbye\n");

Symbols
-------

   Many Lisp functions take arguments that may be, or are required to be,
symbols.  In Lisp, a symbol is a kind of name, but does not have the same
type as a string.  Lisp programs typically use the quote operator to
specify a symbol.  For example, this Lisp code refers to the `beep' symbol:

     (run-at-time nil 1 'beep)

   EPL uses glob references to specify symbols.  A literal globref begins
with a backslash followed by an asterisk, so the last example would be
written as

     &run_at_time(undef, 1, \*beep);

   in Perl.  (You may want to do `&cancel_function_timers(\*beep)' soon
after trying this example.)

   When comparing the returned values of Lisp functions to each other and
to symbols, it is best to use the Lisp eq function instead of Perl's
equality operators.

     ### PREFERRED
     if (&eq(&type_of($x), \*::cons)) { ... }

     ### PROBABLY OK
     if (&type_of($x) eq \*cons) { ... }
     if (&type_of($x) == \*cons) { ... }

Variables
---------

   In Lisp, variables play a role akin to that of Perl scalar variables.
A variable may hold a number, a string, or a reference to any type of
complex Lisp data structure.  (They are not called references in Lisp, but
rather "objects".)

   You can create a Perl alias for any reasonably named Lisp variable by
saying `use Emacs::Lisp qw($varname);'.  Thereafter, assignment to
`$varname' will update the Lisp value.  Changes made to the variable in
Lisp will be reflected in Perl when `$varname' is used in expressions.

   This example saves and replaces the value of the Lisp variable
`inhibit-eol-conversion':

     use Emacs::Lisp qw($inhibit_eol_conversion);
     $old_val = $inhibit_eol_conversion;
     $inhibit_eol_conversion = 1;

   This sort of thing could be accomplished in Lisp as follows:

     (setq old-val inhibit-eol-conversion)
     (setq inhibit-eol-conversion 1)

   (but you would probably rather use let instead, for which there is
still no convenient Emacs::Lisp equivalent).  See also the setq function
below.

Property Lists
--------------

   Lisp symbols all have an associated object called a *plist*, for
"property list".  The plist is an object just like any other, but it is
typically used in a way vaguely resembling Perl's hashes.

   Plists are not used nearly as often as Lisp functions and variables.
If you are new to Lisp, you can probably skip this section.

   A plist is different from a Perl hash.  Lookups are not based on string
equality as with Perl, but rather on Lisp object equality of the eq
variety.  For this reason, it is best to stick to the Lisp convention of
using only symbols as keys.  (See `' in this node.)

   Emacs::Lisp provides a shorthand notation for getting and setting plist
elements.  If you say "`use Emacs::Lisp qw(%any_name)'", then subsequent
access to the elements of `%any_name' will get or set the corresponding
properties of the Lisp symbol `any-name'.

   For example, the following Perl and Lisp fragments are more or less
equivalent:

     # Perl fragment
     use Emacs::Lisp qw(%booboo %upcase_region);
     $booboo{\*error_conditions} = [\*booboo, \*error];
     $can_upcase = ! $upcase_region{\*disabled};

     ; Lisp fragment
     (put 'booboo 'error-conditions '(booboo error))
     (setq can-upcase (not (get 'upcase-region 'disabled)))

   See also the setq function below.

Macros
------

   Lisp macros, such as setq and defun, do not work the same way functions
do, although they are invoked using the function syntax.  (Here you see
the vast philosophical chasm separating Perl from Lisp.  While Perl might
have five syntaxes to mean the same thing, Lisp has one syntax with two
meanings!)

   Some macros are equivalent to Perl operators, such as if and while.
Others have meanings peculiar to Lisp.  A few macros are implemented in
Emacs::Lisp.  They are described below.  If you try to call a macro that
has not been implemented, you will get an error message which may propose
an alternative.

catch SYMBOL,CODE
     Evaluate CODE in a Lisp catch construct.  At any point during CODE's
     execution, the throw function may be used to return control to the
     end of the catch block.  For example:

          $x = catch \*::out, sub {
          	$y = 1;
          	&throw(\*::out, 16);
          	$y = 2;
          };
          print $x;  # prints 16
          print $y;  # prints 1

     Some Perl constructs have functionality similar to throw; for
     example, return and last.  However, they do not work with catches in
     Lisp code.

defun SYMBOL,DOCSTRING,SPEC,CODE
defun SYMBOL,DOCSTRING,CODE
defun SYMBOL,SPEC,CODE
defun SYMBOL,CODE
     Make CODE callable as the Lisp function SYMBOL.  This is Lisp's
     version of Perl's sub keyword.  A function defined in this way
     becomes visible to Lisp code.

     defun is useful for defining Emacs *commands*.  Commands are
     functions that the user can invoke by typing `M-x <function-name>'.
     A command may be bound to a key or sequence of keystrokes.  See the
     Emacs documentation for specifics.

     When defining a command, you must specify the interactive nature of
     the command.  There are various codes to indicate that the command
     acts on the current region, a file name to be read from the
     minibuffer, etc.  Please see *The Elisp Manual* for details.

     Emacs::Lisp's defun uses a SPEC returned by the interactive function
     to specify a command's interactivity.  If no SPEC is given, the
     function will still be callable by Lisp, but it will not be available
     to the user via `M-x <function-name> RET' and cannot be bound to a
     sequence of keystrokes.  Even commands that do not request
     information from the user need an interactive spec.  See `' in this
     node.

     This example creates a command, `reverse-region-words', that replaces
     a region of text with the same text after reversing the order of
     words.  To be user-friendly, we'll provide a documentation string,
     which will be accessible through the Emacs help system (`C-h f
     reverse-region-words RET').

          use Emacs::Lisp;
          defun (\*reverse_region_words,
          	   "Reverse the order of the words in the region.",
          	   interactive("r"),
          	   sub {
          	       my ($start, $end) = @_;
          	       my $text = &buffer_substring($start, $end);
          	       $text = join('', reverse split (/(\s+)/, $text));
          	       &delete_region($start, $end);
          	       &insert($text);
          	   });

     If you try this example and invoke the help system, you may notice
     something not quite right in the message.  It reads as follows:

          reverse-region-words is an interactive Lisp function.
          (reverse-region-words &optional START END &rest ARGS)

          Reverse the order of the words in the region.

     Notice the part about "&optional" and "&rest".  This means that Lisp
     thinks the function accepts any number of arguments.  It knows the
     names of the first two because of the assignment "`my ($start, $end)
     = @_'".

     But our function only works if it receives two args.  Specifying a
     prototype documents this:

          sub ($$) {
          	my ($start, $end) = @_;
          	...
          }

          reverse-region-words is an interactive Lisp function.
          (reverse-region-words START END)

interactive SPEC
interactive
     Used to generate the third (or, in the absence of a doc string, the
     second) argument to defun.  This determines how a command's arguments
     are obtained.

     What distinguishes a "command" from an ordinary function in Emacs is
     the presence of an interactive specifier in the defun expression.

     SPEC may be a string, as described in *The Elisp Manual*, or a
     reference to code which returns the argument list.  If no spec is
     given, the command runs without user input.

save_excursion BLOCK
     Execute BLOCK within a Lisp `save-excursion' construct.  This
     restores the current buffer and other settings to their original
     values after the code has completed.  See *The Elisp Manual* for
     details.

setq BLOCK
     BLOCK is searched for assignments of either of these forms:

          $var = EXPR;
          $hash{$key} = EXPR;

     Every such `$var' and `%hash' is imported from the Emacs::Lisp module
     as if you had said, "`use Emacs::Lisp qw($var %hash)'".  Afterwards,
     BLOCK is executed.  This is a convenient way to assign to variables,
     for example in customization code.

     This code

          use Emacs::Lisp;
          setq {
          	$A = 2*$foo[5];
          	$B{\*foo} = "more than $A";
          };

     would have exactly the same effect as this:

          use Emacs::Lisp qw(:DEFAULT $A %B);
          $A = 2*$foo[5];
          $B{\*foo} = "more than $A";

     The following, which does not tie or import any variables, has the
     same effect on Lisp as the above:

          use Emacs::Lisp ();
          Emacs::Lisp::set( \*A, 2*$foo[5] );
          Emacs::Lisp::put( \*B, \*foo, "more than "
            . &Emacs::Lisp::symbol_value( \*A ));

unwind_protect (BODY, HANDLER)
     Execute coderef BODY, returning its result.  Execute coderef HANDLER
     after BODY finishes, even if BODY exits nonlocally through die or the
     like.

BUGS
====

   These are some of the known bugs in EPL and Emacs::Lisp.  If you find
other bugs, please check that you have the latest version, and email me.

   * Emacs::Lisp doesn't work outside of XEmacs.

     If a Perl program not under the control of an Emacs process uses
     Emacs::Lisp functions, Emacs::Lisp tries to run Emacs in batch mode.
     This only works with GNU Emacs 21 beta, not Emacs 20 or XEmacs.  This
     can probably be fixed, but I don't know what the problem is yet.

     A real solution would involve talking to Emacs on a channel other than
     its standard input and output.  This might allow one to run in
     interactive mode with arbitrary command line options.  I don't know if
     Emacs can use arbitrary file descriptors or named pipes.  I suspect
     not.  If not, I guess I'll try inet sockets.  Other possibilities
     would be ptys (Emacs loves them, I'm not overly fond) and an
     intermediary perl process that talks to the original process over a
     named pipe.

   * Non-robust with respect to subprocess Perl dying.

     Perl dies because of (e.g.) version mismatch between epl.el and
     EPL.pm.  Then you can't exit Emacs, because it tries to tell Perl to
     exit and gives you an error "Process perl not running".  Very
     unfriendly.

   * Within Lisp code, everything defaults to package `main'.

     It would perhaps be best to give the Lisp evaluation environment the
     notion of a "current package" such as Perl has.

   * Symbols whose names contain :: or '

     How can we convert them to and from Perl?

   * High IPC overhead

     Strings are copied more than they absolutely need to be.  Even if they
     weren't, it's bound to be a lot slower than Perlmacs.

   * Lisp hash tables are not deep-copied.

     What to do?  Produce tied hashes whose keys can be any Lisp object?
     Wrap hashes that contain non-string keys?

   * XEmacs package autoloads commands but not key bindings.

     I need to figure out how to do this.

CAVEATS
=======

   * Conversion of scalar types is uncertain.

     A defined, non-reference Perl scalar converted to Lisp becomes either
     an integer, a float, or a string.  The method of choice is unclear.
     This could be considered a bug, but it is somewhat inherent in the
     languages' semantics, as Perl has no really good way to distinguish a
     number from an equivalent string or an integer from a float.

   * Conversion is not always reversible.

     Information may be lost through the default ("deep") data conversion
     process.  For example, the glob reference `\*::nil' and an empty
     arrayref both become undef when converted to Lisp and back.  Perl and
     Emacs support different ranges for integer values.  Integers that
     don't fit are upgraded to floats, so the distinction is lost.

   * Circular data structures are troublesome.

     See `"Two-Phased Garbage Collection"', see Perlobj (perl.info).
     Lisp data structures may be recursive (contain
     references to themselves) without the danger of a memory leak,
     because Lisp uses a periodic-mark-and-sweep garbage collector.

     However, if a recursive structure involves any Perl references, it
     may never be destroyable.

     For best results, Perl code should handle mainly Perl data, and Lisp
     code should handle mainly Lisp data.

   * Cross-language references incur overhead.

     For the benefit of Lisp's garbage collection, all Perl data that is
     referenced by Lisp participates in mark-and-sweep.  For the benefit of
     Perl's garbage collection, all Lisp objects that are referenced by
     Perl maintain a (kind of) reference count.

     A chain of Perl -> Lisp -> ... -> Perl references may take several
     garbage collection cycles to be freed.  It is therefore probably best
     to keep the number and complexity of such references to a minimum.

     To make matters worse, if Emacs does not support weak hash tables,
     Lisp must explicitly free its references to Perl data.  GNU Emacs 20
     does not support weak hash tables, but Perlmacs solves this problem by
     adding necessary support.  XEmacs 21 has weak hash tables, but EPL
     does not yet know how to use them.

TO DO
=====

   * Finish texinfo doc

   * Delete/revise obsolete portions of POD

   * Figure out how to handle hash tables

   * Garbage collection for XEmacs

   * Debian package target

   * Overload Emacs::Lisp::Object in various ways

   * Formal rules for scalar type conversion

   * Regression-test multiple Emacses under Perl

   * Regression-test any Perls under Emacs

   * Steal from IPC::Open2

   * Optimized regex find and replace functions

   * Multibyte characters

     Emacs has had them for some time.  Now Perl's UTF-8 support is
     stabilizing.  It's time the two met.

   * Special forms: let, defmacro, defvar.

   * Make a way to get a tied filehandle that reads a buffer.

   * Improve perl-eval-buffer, perl-eval-and-call, et al.

COPYRIGHT
=========

   Copyright (C) 1998-2001 by John Tobey, jtobey@john-edwin-tobey.org.
All rights reserved.

     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; see the file COPYING.  If not, write to the
     Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
     MA 02111-1307  USA

SEE ALSO
========

   See Perl (perl.info), Perlref (perl.info),
Perlobj (perl.info), Emacs, emacs, and *The Elisp
Manual* (available where you got the Emacs source, or from
ftp://ftp.gnu.org/pub/gnu/emacs/).

Find RFC 822 email addresses in plain text
******************************************

NAME
====

     Email::Find - Find RFC 822 email addresses in plain text

SYNOPSIS
========

     use Email::Find;
     $num_found = find_emails($text, \&callback);

DESCRIPTION
===========

   This is a module for finding a *subset* of RFC 822 email addresses in
arbitrary text (`CAVEATS' in this node).  The addresses it finds are not
guaranteed to exist or even actually be email addresses at all (`CAVEATS'
in this node), but they will be valid RFC 822 syntax.

   Email::Find will perform some heuristics to avoid some of the more
obvious red herrings and false addresses, but there's only so much which
can be done without a human.

Functions
---------

   Email::Find exports one function, find_emails().  It works very similar
to URI::Find's find_uris().

     $num_emails_found = find_emails($text, \&callback);

   The first argument is a block of text for find_emails to search through
and manipulate.  Second is a callback routine which defines what to do
with each email as they're found.  It returns the total number of emails
found.

   The callback is given two arguments.  The first is a Mail::Address
object representing the address found.  The second is the actual original
email as found in the text.  Whatever the callback returns will replace
the original text.

EXAMPLES
========

     # Simply print out all the addresses found leaving the text undisturbed.
     find_emails($text, sub {
                            my($email, $orig_email) = @_;
                            print "Found ".$email->format."\n";
                            return $orig_email;
                        });

     # For each email found, ping its host to see if its alive.
     require Net::Ping;
     $ping = Net::Ping->new;
     my %Pinged = ();
     find_emails($text, sub {
                            my($email, $orig_email) = @_;
                            my $host = $email->host;
                            next if exists $Pinged{$host};
                            $Pinged{$host} = $ping->ping($host);
                        });

     while( my($host, $up) = each %Pinged ) {
         print "$host is ". $up ? 'up' : 'down' ."\n";
     }

     # Count how many addresses are found.
     print "Found ", find_emails($text, sub { return $_[1] }), " addresses\n";

     # Wrap each address in an HTML mailto link.
     find_emails($text, sub {
                            my($email, $orig_email) = @_;
                            my($address) = $email->format;
                            return qq|<a href="mailto:$address">$orig_email</a>|;
                        });

CAVEATS
=======

Why a subset of RFC 822?
     I say that this module finds a *subset* of RFC 822 because if I
     attempted to look for all possible valid RFC 822 addresses I'd wind
     up practically matching the entire block of text!  The complete
     specification is so wide open that its difficult to construct
     soemthing that's not an RFC 822 address.

     To keep myself sane, I look for the 'address spec' or 'global address'
     part of an RFC 822 address.  This is the part which most people
     consider to be an email address (the 'foo@bar.com' part) and it is
     also the part which contains the information necessary for delivery.

Why are some of the matches not email addresses?
     Alas, many things which aren't email addresses *look* like email
     addresses and parse just fine as them.  The biggest headache is email
     and usenet message IDs.  I do my best to avoid them, but there's only
     so much cleverness you can pack into one library.

This module requires 5.005_63 or higher!
     This module runs so slow as to be unusable with 5.005 stable.  I'm not
     sure, but it might be because I build up my search regex using lots of
     compiled regexes.  Either way, it runs orders of magnitude faster
     under 5.005_63.

     Perhaps in later versions I'll be able to tweak it to be efficient
     with 5.005 stable.

AUTHOR
======

   Copyright 2000, Michael G Schwern <schwern@pobox.com>.  All rights
reserved.

LICENSE
=======

   This module may not be used for the purposes of sending unsolicited
email (ie. spamming) in any way, shape or form or for the purposes of
generating lists for commercial sale without explicit permission from the
author.

   For everyone else this module is free software; you may redistribute it
and/or modify it under the same terms as Perl itself.

SEE ALSO
========

     L<Email::Valid>, RFC 822, L<URI::Find>

Check validity of Internet email addresses
******************************************

NAME
====

   Email::Valid - Check validity of Internet email addresses

SYNOPSIS
========

     use Email::Valid;
     print (Email::Valid->address('maurice@hevanet.com') ? 'yes' : 'no');

DESCRIPTION
===========

   This module determines whether an email address is well-formed, and
optionally, whether a mail host exists for the domain.

   Please note that there is no way to determine whether an address is
deliverable without attempting delivery (for details, see perlfaq 9).

PREREQUISITES
=============

   This module requires perl 5.004 or later and the Mail::Address module.
Either the Net::DNS module or the nslookup utility is required for DNS
checks.

METHODS
=======

     Every method which accepts an <ADDRESS> parameter may
     be passed either a string or an instance of the Mail::Address
     class.  All errors raise an exception.

new ( [PARAMS] )
     This method is used to construct an Email::Valid object.  It accepts
     an optional list of named parameters to control the behavior of the
     object at instantiation.

     The following named parameters are allowed.  See the individual
     methods below of details.

          -mxcheck
          -fudge
          -fqdn
          -local_rules

mx ( <ADDRESS>|<DOMAIN> )
     This method accepts an email address or domain name and determines
     whether a DNS record (A or MX) exists for it.

     The method returns true if a record is found and undef if not.

     Either the Net::DNS module or the nslookup utility is required for
     DNS checks.  Using Net::DNS is the preferred method since error
     handling is improved.  If Net::DNS is available, you can modify the
     behavior of the resolver (e.g. change the default tcp_timeout value)
     by manipulating the global Net::DNS::Resolver instance stored in
     $Email::Valid::Resolver.

rfc822 ( <ADDRESS> )
     This method determines whether an address conforms to the RFC822
     specification (except for nested comments).  It returns true if it
     conforms and undef if not.

fudge ( <TRUE>|<FALSE> )
     Specifies whether calls to address() should attempt to correct common
     addressing errors.  Currently, this results in the removal of spaces
     in AOL addresses, and the conversion of commas to periods in
     Compuserve addresses.  The default is false.

fqdn ( <TRUE>|<FALSE> )
     Species whether addresses passed to address() must contain a fully
     qualified domain name (FQDN).  The default is true.

local_rules ( <TRUE>|<FALSE> )
     Specifies whether addresses passed to address() should be tested for
     domain specific restrictions.  Currently, this is limited to certain
     AOL restrictions that I'm aware of.  The default is false.

mxcheck ( <TRUE>|<FALSE> )
     Specifies whether addresses passed to address() should be checked for
     a valid DNS entry.  The default is false.

address ( <ADDRESS> )
     This is the primary method which determines whether an email address
     is valid.  It's behavior is modified by the values of mxcheck(),
     local_rules(), fqdn(), and fudge().  If the address passes all
     checks, the (possibly modified) address is returned as a string.
     Otherwise, the undefined value is returned.  In a list context, the
     method also returns an instance of the Mail::Address class
     representing the email address.

details ()
     If the last call to address() returned undef, you can call this
     method to determine why it failed.  Possible values are:

          rfc822
          local_rules
          fqdn
          mxcheck

     If the class is not instantiated, you can get the same information
     from the global $Email::Valid::Details.

EXAMPLES
========

   Let's see if the address 'maurice@hevanet.com' conforms to the RFC822
specification:

     print (Email::Valid->address('maurice@hevanet.com') ? 'yes' : 'no');

   Additionally, let's make sure there's a mail host for it:

     print (Email::Valid->address( -address => 'maurice@hevanet.com',
                                   -mxcheck => 1 ) ? 'yes' : 'no');

   Let's see an example of how the address may be modified:

     $addr = Email::Valid->address('Alfred Neuman <Neuman @ foo.bar>');
     print "$addr\n"; # prints Neuman@foo.bar

   Need to determine why an address failed?

     unless(Email::Valid->address('maurice@hevanet')) {
       print "address failed $Email::Valid::Details check.\n";
     }

   If an error is encountered, an exception is raised.  This is really
only possible when performing DNS queries.  Trap any exceptions by
wrapping the call in an eval block:

     eval {
       $addr = Email::Valid->address( -address => 'maurice@hevanet.com',
                                      -mxcheck => 1 );
     };
     warn "an error was encountered: $@" if $@;

BUGS
====

   Email::Valid should work with Perl for Win32.  In my experience,
however, Net::DNS queries seem to take an extremely long time when a
record cannot be found.

AUTHOR
======

   Copyright 1998-1999, Maurice Aubrey <maurice@hevanet.com>.  All rights
reserved.

   This module is free software; you may redistribute it and/or modify it
under the same terms as Perl itself.

CREDITS
=======

   Significant portions of this module are based on the ckaddr program
written by Tom Christiansen and the RFC822 address pattern developed by
Jeffrey Friedl.  Neither were involved in the construction of this module;
all errors are mine.

   Thanks very much to the following people for their suggestions and bug
fixes:

     Otis Gospodnetic <otis@DOMINIS.com>
     Kim Ryan <kimaryan@ozemail.com.au>
     Pete Ehlke <pde@listserv.music.sony.com>
     Lupe Christoph
     David Birnbaum
     Achim

SEE ALSO
========

   Mail::Address, Net::DNS, perlfaq9

WebFetch Embedding API
======================

   As of version 0.10 of WebFetch, the Embedding API (application
programming interface) was added.  WebFetch used to be mostly for use for
saving captured web content to files.  The purpose of the Embedding API is
to allow any Perl program to run a WebFetch module and capture its output
for use within that program.

   Once the information is available to other programs, there are as many
possibilities as Perl allows for what to do with it.  So the Embedding API
delivers on the implied promise that came from packaging WebFetch as Perl5
modules instead of scripts.  Instead of just saving the information to
files, now it's available within a program too.

Conversion of WebFetch 0.09 Modules to the Embedding API
========================================================

   Old WebFetch 0.09 and earlier modules continue to work in what is called
"0.09 compatibility mode".  Actually, the old strucutres are still there
so it's more than just compatibility - the new Embedding API is triggered
by the presence of new variables which contain more information.

   The following modules were converted to the new API in WebFetch 0.10:
*CNETnews, CNNsearch, COLA, Freshmeat, SiteNews, and Slashdot*.

   The remaining modules have not been converted yet and operate in 0.09
compatibility mode: *DebianNews, General, LinuxDevNet, LinuxTelephony,
ListSubs, PerlStruct, 32BitsOnline and YahooBiz*.  Upcoming WebFetch
releases will convert more until all the modules are done.

   Modules that users have written for WebFetch 0.09 and earlier which are
not (yet) distributed with WebFetch should also continue to work
unmodified.  If they don't, that would be a bug and should be reported.

How the Embedding API Works
===========================

   In WebFetch 0.09 and earlier, each module was responsible for saving its
own information to a file, for all file formats that they supported.  Now
the module saves to some predefined variables.  If the module was called
from WebFetch's core command-line routines, the core will handle saving
the files in all requested formats.  If the module was called from another
program, now it has the option to look inside the returned data and do its
own processing with it.

   A WebFetch module which implements the Embedding API must define the
following variables, which are defined in more detail in the WebFetch core
module documentation:

$obj->{data}
     a hash reference which contains more data-related variables

$obj->{actions}
     a hash reference which defines things that the WebFetch core must do
     with the data (i.e. where and how to save it.)  Entry may have hash
     keys like "html", "xml", "wf" (WebFetch native format), and "rdf"
     (XML Resource Definition Format) or other names if the proper handler
     functions are defined.  (Your module can define its own handler
     function and then use it to output your information.  See
     WebFetch::SiteNews for an example.)

$obj->{data}{fields}
     an array reference which contains a list of field names in order.
     This is part of the definition of the data captured and returned from
     the module.

$obj->{data}{wk_names}
     a hash reference which uses hash keys of "well known names", field
     names which WebFetch can attribute specific functions to (like title,
     url, etc.)  and hash values of the names of the fields defined in
     $obj->{data}{fields} that contain that data in this data set.

$obj->{data}{records}
     an array reference containing more array references - a
     two-dimensional table of records containing fields of data.  Each
     record is one unit/entry of information captured.  Each field within
     a record corresponds by position within the array to the names in
     $obj->{data}{fields}.

   Programs which need to use this data can read it directly from the
records and fields in $obj->{data}{records}.  Some sample code is shown in
the WebFetch FAQ at http://www.webfetch.org/

   A module which inherits from WebFetch and fails to provide these
variables is assumed to be a WebFetch 0.09 module.  Any module in WebFetch
0.09 compatibiltily mode is responsible to save its own HTML or other
files.

persistence for ECDs
********************

NAME
====

   Embedix::DB - persistence for ECDs

SYNOPSIS
========

   instantiation

     my $edb = Embedix::DB->new (
         backend => 'Pg',
         source  => [
             'dbi:Pg:dbname=embedix',
             'user', 'password',
             { AutoCommit => 0 },
         ],
     );

     # $edb should be an instance of Embedix::DB::Pg

   adding a distro

     $edb->addDistro (
         name  => 'uCLinux 2.4',
         board => 'm68k',
     );

     $edb->addDistro (
         name  => 'Embedix 1.2',
         board => 'ppc',
     );

   selecting a distro to work on

     $edb->workOnDistro(name => 'Embedix 1.2', board => 'ppc');

   cloning a distro

     $edb->cloneDistro(board => 'mpc8260adsp');

   updating a distro with new information

     my $apache_ecd = Embedix::ECD->newFromFile('apache.ecd');
     $edb->updateDistro(ecd => $apache_ecd);

   deleting components from a distro

     $edb->deleteNode(name => 'busybox');

REQUIRES
========

Embedix::ECD
     This is needed to get data from ECD files into perl objects that can
     then be inserted into a database.

DBD::Pg
     The PostgreSQL backend uses this.

DBD::mysql
     If anyone writes a MySQL backend, it'll surely use this.

DESCRIPTION
===========

   The "DB" in Embedix::DB stands for database.  Although Embedix::DB was
inspired by the *tigger* code that implements the original Embedix
Database, the implementation strategy is quite different.

   First, Embedix::DB is a means to provide persistence for data found in
ECD files.  Tigger uses the filesystem for this purpose.  Embedix::DB may
have a filesystem-based backend in the future, but the current
implementation provides a PostgreSQL-based backend.  The goal here was to
minimize the amount of parsing necessary to start an Embedix configuration
program (like TargetWizard).  By doing the CPU-intensive parsing stage
only once for when an Embedix distribution is initially defined, startup
can be much faster.  TargetWizard currently parses a large collection of
ECDs every time it starts up.

   Beyond that, it has the ability to take ECD data and organize it at a
higher level into distributions.  Currently, it is awkward to use a single
TargetWizard installation to provide the ability to configure different
distributions.  For example, you could not use TargetWizard to configure
both a uCLinux distribution and an Embedix distribution during the same
session.  In order to do this, one would currently have to exit
TargetWizard, install a new config that points to the appropriate
directories, and restart TargetWizard.  Although tigger is theoretically
capable of handling this more gracefully, the directory structure for how
ECDs are stored doesn't facilitate this.  In contrast, Embedix::DB was
designed from the beginning to be able to manipulate multiple
distributions simultaneously.

   Another area where Embedix::DB deviates from tigger is in node names
for ECDs.  Tigger requires that all nodes must have unique names
regardless of the node's nesting.  Embedix::DB does not have this
restriction.  Hopefully, this will allow node names to be less contrived
in the future.

   One significant difference between Embedix::DB and tigger is that
Embedix::DB does not handle dependency and conflict resolution.  That job
is delegated to Embedix::Config which will use an instance of Embedix::DB
to get information from the database when necessary.  Also note that
Embedix::DB does not know how to parse or generate ECD files.  That job
belongs to Embedix::ECD.  Tigger does many things, and its parts are
tightly coupled making it difficult to use any given part of it in
isolation from the rest of tigger.  The functionality provided by tigger
is roughly equivalent to the functionality provided by Embedix::ECD,
Embedix::DB, and Embedix::Config.  (I need to make this paragraph flow
better).

   The overall theme of Embedix::DB is to try to improve upon the areas
where tigger is lacking.  It's a lot of work, and I'd like to emphasize
that I'm not doing this out of disrespect.  Surely, I would have made many
of the same mistakes (and some original ones of my own) if I were
implementing this without the benefit of hindsight.  I believe the concept
of TargetWizard is a good one, and that's why I'm doing this.

   Embedix::DB is an exploratory work where I am trying to put certain
ideas about how tigger could be improved into practice.

CONCEPTS
========

distro
     Short for "distribution".  Examples:  'Embedix 1.2', 'uCLinux 2.4'.
     Distros are collections of ECDs.

board
     A board is a name for a piece of hardware that a distro has been
     ported to.  Examples:  'i386', 'm68k', 'ppc', 'alpha'.

node
     From ECDs, the data enclosed within a <GROUP>, <COMPONENT>, <OPTION>,
     <AUTOVAR>, or <ACTION> tag is the data of a node.  Nodes may be
     nested.

database
     This is where it's all stored.  The underlying implementation may be
     something other than a 'real' database.  For example, the filesystem
     with a specific directory structure may be providing persistence.  We
     still call that a database - just play along.

cloning
     When creating a derivative of a distro, it is convenient (and space
     efficient) to use the cloneDistro() method to create a clone to work
     on.  Think of it as a form of inheritance.

METHODS
=======

   The Embedix::DB API provides methods for performing abstract operations
on the database.  Whether the backend is based on a filesystem or a
relational database, the same API should be applicable.

Initialization
--------------

   First, one must connect to a database.

new(backend => $str, source => $source_ref)
     This instantiates an Embedix::DB with the appropriate backend.

          my $edb = Embedix::DB->new(
              backend => 'Pg',
              source  => [
                  'dbi:Pg:dbname=embedix', $user, $pass,
                  { AutoCommit => 0},
              ],
          );

     `$edb' will be an instance of Embedix::DB::Pg in this example.

workOnDistro(distro => $str, board => $str)
     This method is used to set the current working distribution.  This
     method is usually called immediately after the new(), because almost
     all other methods require that a current working distribution has been
     set.  (The only exception is addDistro()).

          $edb->workOnDistro(distro => 'Embedix 1.2', board => 'i386');

Methods for defining distributions
----------------------------------

   Now that a connection to the database has been made, the database may
be populated.

addDistro
     This adds a new distribution to the database.

updateDistro
     This takes data from an ECD and populates the current working database
     with it.

cloneDistro
     This takes the current working distribution and makes an exact clone
     of it.  This method exists to make it easy to create variations on a
     distribution using a sort of inheritance.  For example, the "Embedix
     1.2" distro may have the following variations.

          generic
          |-- i386
          |-- mips
          |-- ppc
          |   `-- mpc8260adsp
          `-- sh
              |-- sh3
              `-- sh4

     generic would be a distro containing data from only architecturally
     neutral ECDs.  The `i386', `mips', `ppc', and `sh' versions of
     "Embedix 1.2" would be derived from generic by using cloneDistro().
     They would then be populated with additional data from
     architecturally-specific ECDs.  ECD nodes may be removed as well as
     with the case for the `mpc8260adsp'.  Since it doesn't have a graphics
     controller, it doesn't make sense to provide the X11 packages, so the
     `mpc8260adsp' would be a cloned `ppc' distribution w/ the X11 packages
     removed.

unrelateNode
     This is used to dissociate a node from a distro.

relateNode
     This is used to associate a node with a distro.

deleteNode
     This totally deletes a node.  If a node has been cloned many times,
     all the clones go away.  This is more serious than unrelateNode().

Methods for querying the database
---------------------------------

   This is an area that still needs to be fleshed out.  As Embedix::Config
matures, this API will mature as well to.

getComponentList
     This returns an arrayref of the form:

          [
              [ '/category0' [ $node0, $node1, ... ] ],
              [ '/category1' [ $node0, $node1, ... ] ],
              ...
          ];

     The list of categories as well as the list of nodes within each
     category come sorted in ASCII order.

getDistroList
     This returns an arrayref of the form:

          [
              [ 'distro0' [ $board0, $board1, ... ] ],
              [ 'distro1' [ $board0, $board1, ... ] ],
              ...
          ];

     This is a list of distributions where each distribution has a list of
     which boards it supports.  The board lists are sorted in ASCII order.

DIAGNOSTICS
===========

   error messages

COPYRIGHT
=========

   Copyright (c) 2000,2001 John BEPPU.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

AUTHOR
======

   John BEPPU <beppu@lineo.com>

SEE ALSO
========

related perl modules
     Embedix::ECD(3pm), Embedix::Config(3pm)

FileSystem back-end for Embedix::DB
***********************************

NAME
====

   Embedix::DB::FileSystem - FileSystem back-end for Embedix::DB

SYNOPSIS
========

   instantiation

     $edb = Embedix::DB::FileSystem->new()

   other examples

     ...

REQUIRES
========

Embedix::FileSystem
DESCRIPTION
===========

   a brief summary of the module written with users in mind.

METHODS
=======

   methods

CLASS VARIABLES
===============

   cvars

DIAGNOSTICS
===========

   error messages

COPYRIGHT
=========

   Copyright (c) 2000,2001 John BEPPU.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

AUTHOR
======

   John BEPPU <beppu@lineo.com>

SEE ALSO
========

related perl modules
the latest version

PostgreSQL back-end for Embedix::DB
***********************************

NAME
====

   Embedix::DB::Pg - PostgreSQL back-end for Embedix::DB

SYNOPSIS
========

   The API presented here is subject to change.  I haven't figured out all
the details, yet.

   instantiation

     $ebx = Embedix::DB::Pg->new (
         source => [
             'dbi:Pg:dbname=embedix', $user, $pass,
             { AutoCommit => 0 }
         ],
     );

   adding a new distribution

     $ebx->addDistro (
         arch        => 'm68k',      # maybe in the future?
         name        => 'uClinux',
         description => 'Linux for MMU-less architectures',
     );

   selecting a default distro to work on

     $ebx->workOnDistro('Embedix 1.2');

   updating a distro with information from an ECD

     my $ecd = Embedix::ECD->newFromFile('apache.ecd');
     $ebx->updateDistro($ecd);

REQUIRES
========

Embedix::ECD
DBI
DBD::Pg
DESCRIPTION
===========

   a brief summary of the module written with users in mind.

METHODS
=======

Constructor
-----------

new(backend => ..., source => [ ... ])
          $edb = Embedix::DB::Pg->new (
              backend => 'Pg',
              source  => [ 'dbi:Pg:dbname=embedix', $user, $password ],
          );

Administration Methods
----------------------

addDistro( name => ..., description => ...)
          $distro = $edb->addDistro (
              name        => $string,
              description => $another_string,
          );

workOnDistro('name of distribution')
          $distro = $edb->workOnDistro(
              distro => 'Embedix 1.2',
              board  => 'i386',
          );

updateDistro(ecd => $ecd, parent_id => $id)
          $edb->updateDistro(ecd => $ecd);

cloneDistro(board => ...);
          $edb->cloneDistro(board => $_) foreach qw(ppc mips m68k sh);

Client Methods
--------------

getComponentList
          my $cl = $edb->getComponentList;

getDistroList
          my $dl = $edb->getDistroList;

DIAGNOSTICS
===========

   error messages

COPYRIGHT
=========

   Copyright (c) 2000,2001 John BEPPU.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

AUTHOR
======

   John BEPPU <beppu@lineo.com>

SEE ALSO
========

related perl modules
the latest version

MySQL back-end for Embedix::DB
******************************

NAME
====

   Embedix::DB::mysql - MySQL back-end for Embedix::DB

SYNOPSIS
========

   instantiation

     $obj = Embedix::DB::mysql->new()

   other examples

     ...

REQUIRES
========

Embedix::mysql
DESCRIPTION
===========

   a brief summary of the module written with users in mind.

METHODS
=======

   methods

CLASS VARIABLES
===============

   cvars

DIAGNOSTICS
===========

   error messages

COPYRIGHT
=========

   Copyright (c) 2000,2001 John BEPPU.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

AUTHOR
======

   John BEPPU <beppu@lineo.com>

SEE ALSO
========

related perl modules
the latest version

Embedix Component Descriptions as objects
*****************************************

NAME
====

   Embedix::ECD - Embedix Component Descriptions as objects

SYNOPSIS
========

   instantiate from a file

     my $ecd       = Embedix::ECD->newFromFile('busybox.ecd');
     my $other_ecd = Embedix::ECD->newFromFile('tinylogin.ecd');

   access nodes

     my $busybox = $ecd->System->Utilities->busybox;

   build from scratch

     my $server = Embedix::ECD::Group->new(name => 'Server');
     my $www    = Embedix::ECD::Group->new(name => 'WWW');
     my $apache = Embedix::ECD::Component->new (
         name   => 'apache',
         srpm   => 'apache',
         prompt => 'Include apache web server?',
         help   => 'The most popular http server on the internet',
     );
     $ecd->addChild($server);
     $ecd->Server->addChild($www);
     $ecd->Server->WWW->addChild($apache);

   get/set attributes

     my $srpm = $busybox->srpm();

     $busybox->help('i am busybox of borg -- unix will be assimilated.');

     $busybox->requires([
         'libc.so.6',
         'ld-linux.so.2',
         'skellinux',
     ]);

   combine Embedix::ECD objects together

     $ecd->mergeWith($other_ecd);

   print as text

     print $ecd->toString;

   print as XML

     use Embedix::ECD::XMLv1 qw(xml_from_cons);

     print $ecd->toXML(shiftwidth => 4, dtd => 'yes');

     my $cons = Embedix::ECD->consFromFile('minicom.ecd');
     print xml_from_cons($cons);

REQUIRES
========

Parse::RecDescent
     for the ECD parser

Data::Dumper
     for debugging

Tie::IxHash
     for preserving the insertion order of children while retaining `O(1)'
     named access (at the expense of memory).

Pod::Usage
     `bin/ecd2xml' uses this to generate its help message.

DESCRIPTION
===========

   Embedix::ECD allows one to represent ECD files as a tree of perl
objects.  One can construct objects by parsing an ECD file, or one can
build an ECD object from scratch by combining instances of Embedix::ECD
and its subclasses.  These objects can then be turned back into ECD files
via the `toString()' method.

   ECD stands for Embedix Component Description, and its purpose is to
contain meta-data regarding packages (aka components) in the Embedix
distribution.  ECD files contain much of the same data a .spec file does
for an RPM.  A major difference however is that ECD files do not contain
building instructions whereas .spec files do.  Another major difference
between .spec files and ECD files is the structure.  ECD files are
hierarchically structured whereas .spec files are comparatively flat.

   The ECD format reminds me of the syntax for Apache configuration files.
Items are tag-delimited (like in XML) and attributes are found between
these tags.  Comments are written by prefixing them with /^\s*#/.  Unlike
apache configurations, attribute names and values are separated by an "="
sign, whereas in apache the first token is the attribute name and
everything after that (sans leading whitespace) and up to the end of the
line is the attribute's value.  Also, unlike apache configurations,
attributes may also be enclosed in tags, whereas in apache tags are used
only to describe nodes.

   ECD files look like pseudo-XML with shell-styled comments.

METHODS
=======

Constructors
------------

   There are two types of constructors provided by this class.  The first
kind of constructor begins with "new" and returns an Embedix::ECD object.
There is another kind of constructor that begins with "cons" and returns
the syntax tree as nested arrayrefs.

   I realized that creating an object of the syntax tree takes a long time
(especially for long ECD files).  I also realized that sometimes, the
simple nested arrayref is useful enough on its own.  It also has the nice
property of retaining comments whereas the object constructor disposes of
comments.  I thought if ECD files were ever to be translated into XML,
it'd be nice to be able to keep the comments.  These factors convinced me
that it would be useful to have these 2 kinds of constructors.

new(key => $value, ...)
     This returns an Embedix::ECD object.  It can be initialized with named
     parameters which represent the attributes the object should have.  The
     set of valid attributes is described under `' in this node.

          $system     = Embedix::ECD::Group->new(name => 'System');
          $utilities  = Embedix::ECD::Group->new(name => 'Utilities');
          $busybox    = Embedix::ECD::Component->new(

          name    => 'busybox',
          type    => 'bool',
          value   => 0,
          srpm    => 'busybox',

          static_size     => 3006,
          min_dynamic_size=> 0,
          storage_size    => 4408,
          startup_time    => 0,

          keeplist        => [ '/bin/busybox' ],
          requires_expr   => [
              '(libc.so.6 == "y") &&',
              '(ld-linux.so.2 == "y") &&',
              '(skellinux == "y") &&',
              '(  (Misc-utilities == "y")',
              '|| (File-compression-utilities == "y")',
              '|| (Network-utilities == "y")',
              '|| (Process-utilities == "y")',
              '|| (Directory-utilities == "y")',
              '|| (User-info-utilities == "y")',
              '|| (Disk-info-utilities == "y")',
              '|| (Screen-utilities == "y")',
              '|| (System-utilities == "y")',
              '|| (File-manipulation-utilities == "y") )',
          ],

              );

   The following 5 constructors rely on a Parse::RecDescent parser.  When
they encounter a syntax error they will die, so be sure to wrap them
around an eval block.

newFromCons($cons)
     This returns an Embedix::ECD object from a nested arrayref.

          $ecd = Embedix::ECD->newFromCons($cons)

newFromString($string)
     This returns an Embedix::ECD object from a string in ECD format.

          $ecd = Embedix::ECD->newFromString($string)

newFromFile($filename)
     This returns an Embedix::ECD object from an ECD file.

          $ecd = Embedix::ECD->newFromFile($filename)

consFromString($string)
     This returns a nested arrayref from a string in ECD format.

          $cons = Embedix::ECD->consFromString($string)

consFromFile($filename)
     This returns a nested arrayref from an ECD file.

          $cons = Embedix::ECD->consFromFile($filename)

   (This next constructor is an anomaly.)

Embedix::ECD->parser
     This returns an instance of Parse::RecDescent configured to understand
     the ECD grammar.  This instance is a singleton, so you will receive
     the same instance every time.

          $ecd_parser = Embedix::ECD->parser()

Nodes
-----

   Nodes are the fundamental building block of the tree structure in an ECD
file.   Nodes are containers of attributes and other nodes.  No matter
what, all nodes will have a "name" attribute.  This is the key feature
that makes nodes distiguishable from attributes.

   This is a node

     <AUTOVAR embedix_ui-VGAOPT>
         TYPE=string
         DEFAULT_VALUE=785
     </AUTOVAR>

   This is an attribute

     <IF>
         ( ( EBXDUP_CONFIG_USB_BANDWIDTH == "y" )
         LET ( $VALUE = "y" ) )
         ||
         ( ( ( CONFIG_USB != "n" )
         && ( CONFIG_EXPERIMENTAL != "y" ) )
         LET ( $VALUE = "n" ) )
     </IF>

   The distinction is in the opening tag.  The autovar has a second string
in it which represents the node's name whereas the if has nothing which
means that it is an attribute of the node it is contained in.

   There are 5 (not 4) types of nodes.

the root node | Embedix::ECD
     This node is implicit but very real.  When invoking any of the
     constructors that begin with "newFrom", one will get back an
     Embedix::ECD object within which the rest of the ECD data will be
     contained.

Group | Embedix::ECD::Group
     Their purpose is to establish a hierarchy of components under
     meaningful subheadings such as "Server/WWW" or "System/Utilities".
     Their main use is as containers of other nodes.

Component | Embedix::ECD::Component
     A component node represents a package in the Embedix distribution.

Option | Embedix::ECD::Option
     An option node is almost always contained under a component node.  The
     purpose of an option is to provide a point of configurability for a
     package.

Autovar | Embedix::ECD::Autovar
     What exactly is this?

Accessing Child Nodes
---------------------

   The following are accessor methods for child nodes.

getChild($name)
     This returns a child node with the given $name or undef if no such
     child exists.

          $child_ecd = $ecd->getChild($name)

n($name)
     `n()' is an alias for `getChild()'.  "n" stands for "node" and is a
     lot easier to type than "getChild".

          $ecd->n('System')
              ->n('Utilities')
              ->n('busybox')
              ->n('long-ass-option-name-with-redundant-information');

addChild($obj)
     This adds a child to the current node.

          $ecd->addChild($obj)

delChild($obj) or delChild($name)
     This deletes a child from the current node.  The child may either be
     specified by an object or by its name.

          $ecd->delChild($obj) or $ecd->delChild($name)

getChildren
     This returns a list of all child nodes.

          @child_ecd = $ecd->getChildren()

hasChildren
     This returns true if the current node has child nodes.

          $ecd->hasChildren()

Accessing Child Nodes via AUTOLOAD
----------------------------------

   The name of a node can be used as a method.  This is what makes it
possible to say something like:

     my $busybox = $ecd->System->Utilities->busybox;

   and get back the Embedix::ECD::Component object that contains the
information for the busybox package.  "System", "Utilities", and "busybox"
are not predefined methods in Embedix::ECD or any of its subclasses, so
they are delegated to the AUTOLOAD method.  The AUTOLOAD method will try
to find a child with the same name as the undefined method and it will
return it if found.

   I have not yet decided whether the AUTOLOAD should die when a child is
not found.  Currently undef is returned in this situation.

   One annoyance is that many nodes have names with "-" in them.  These
cannot be AUTOLOADed, because method names may not have a "-" in perl.
When accessing such nodes, use the `getChild()' method.

Attributes
----------

   If nodes are objects, then attributes are a node's instance variables.
All attributes may be single-valued or aggregate-valued.  Single-valued
attributes are non-reference scalar values, and aggregate attributes are
non-reference scalar values enclosed within an arrayref.

   A single valued attribute:

     my $bbsed = $busybox->n('Misc-utilities')->n('keep-bb-sed');
     $bbsed->provides('sed');

   The same attribute as an aggregate:

     $bbsed->provides([ 'sed' ]);

   Semantically, these are equivalent.  The main difference one will notice
is cosmetic.  When the `toString()' method is called, the single-valued
one will look like:

     PROVIDES=sed

   and the aggregate valued provides will look like:

     <PROVIDES>
         sed
     </PROVIDES>

   Again, these two expressions mean the same thing.  An aggregate of one
is interpreted just as if it were a single value.

   Aggregates become useful when attributes needs to have a list of values.

     $busybox->n('compile-time-features')->n('enable-bb-feature-use-inittab')->requires ([
         'keep-bb-init',
         'inittab',
         '/bin/sh',
     ]);

   This will be rendered by `toString()' as

     <REQUIRES>
         keep-bb-init
         inittab
         /bin/sh
     </REQUIRES>

   There are accessors for attributes that work like your typical perl
getters and setters.  That is, when called without a parameter, the method
behaves as a getter.  When called with a parameter, the method behaves as
a setter and the value of the parameter is assigned to the attribute.

   getter:

     my $name = $busybox->name();

   setter:

     $busybox->name('busybox');

Accessors For Single-Valued Attributes
--------------------------------------

   These are accessors for attributes that are typically single-valued.

name
     This is the name of the node.

          $ecd->name()

type
     This is the type of the node.  This is usually (always?) seen in the
     context of an option and it can contain values such as "bool", "int",
     "int.hex", "string", and "tridep".

          $ecd->type()

value
     This is the value of a node which must be something appropriate for
     its type.

          $ecd->value()

default_value
     This is the value taken by the node if value is not defined.

          $ecd->default_value()

range
     For the numerical types, it may be desirable to limit the range of
     values that may be assigned such that value() will always be
     meaningful.  The use of this attribute has only been observed in
     linux.ecd.

          $ecd->range()

help
     This often contains prose regarding the current node.  I think it
     would be nice if it were possible to use an alternative form of
     mark-up language inside these sections.  (HTML, for instance).

          $ecd->help()

prompt
     The value in prompt is used in TargetWizard to pose a question to the
     user regarding whether he/she wants to enable an option or not.

          $ecd->prompt()

license
     This is the license that the software falls under.  Usually, there is
     only one license, but once in a while you may get a dual-licensed
     package.  In that case, it's OK to give it an arrayref with multiple
     licenses in it.

          $ecd->license()

srpm
     This contains the name of the source RPM sans version information and
     the file extension.  This attribute almost always has the same value
     as name().

          $ecd->srpm()

specpatch
     This attribute is only meaningful within the context of a component.
     Specpatches are applied to .spec files just prior to the building of a
     component.  They are often used to configure the compilation of a
     component.  The busybox package provides a good example of this in
     action.

          $ecd->specpatch()

static_size
     This is the sum of .text, .data, and .bss for an option and/or
     component.

          $ecd->static_size()

eval_static_size
     If static_size contains a mathematical expression, this method
     evaluates it.

          ($size, $give_or_take) = $ecd->eval_static_size;

min_dynamic_size
     The very least a program will `malloc()' during its execution.

          $ecd->min_dynamic_size()

eval_min_dynamic_size
     If min_dynamic_size contains a mathematical expression, this method
     evaluates it.

          ($size, $give_or_take) = $ecd->eval_min_dynamic_size;

storage_size
     This is the amount of space this component and/or option would
     consume on a filesystem.

          $ecd->storage_size()

eval_storage_size
     If storage_size contains a mathematical expression, this method
     evaluates it.

          ($size, $give_or_take) = $ecd->eval_storage_size;

startup_time
     The amount of time (in what metric?) from the time a program is
     executed up to the point in time when the program becomes useful.

          $ecd->startup_time()

eval_startup_time
     If startup_time contains a mathematical expression, this method
     evaluates it.

          ($size, $give_or_take) = $ecd->eval_startup_time;

Accessing Aggregate Attributes
------------------------------

   The following are attributes that frequently contain aggregate values.
When setting attributes with aggregate values, enclose the values within
an arrayref.

requiresexpr
     This contains a C-like expression describing node dependencies.

          $ecd->requiresexpr()

if
     I didn't know if using a keyword as a method name would be legal, but
     apparently it is.  I also wonder if more than on 'if' statement is
     allowed per node.

          $ecd->if()

conflicts
     This is used to explicitly specify a node that conflicts with the
     current node.  My first thought is that this is just another way to
     say provides.

          $ecd->conflicts()

build_vars
     This specifies a list of transformations that can be applied to a
     .spec file prior to building.

          $ecd->build_vars()

provides
     This is a list of symbolic names that a node is said to be able to
     provide.  For example, grep in busybox provides grep.  GNU/grep also
     provides grep.  According to TargetWizard, these two cannot coexist on
     the same instance of an Embedix distribution, because they both
     provide grep.

          $ecd->provides()

requires
     This is a list of libraries, files, provides, and other nodes required
     by the current node.

          $ecd->requires()

keeplist
     This is a list of files and directories provided by a component or
     option.

          $ecd->keeplist()

choicelist
     This is used for options in the kernel.

          $ecd->choicelist()

trideps
     This is used for options in the kernel.

          $ecd->trideps()

Accessors That Take Named Attributes
------------------------------------

   The most general kind of accessor takes the name of an attribute as a
parameter and gets or sets it.

getAttribute($name)
     This gets the attribute called $name.

          $val = $ecd->getAttribute($name)

setAttribute($name, $value)
     This sets the attribute called $name to $value.

          $ecd->setAttribute($name, $value)

Utility Methods
---------------

toString(indent => 0, shiftwidth => 4)
     This will render an $ecd object as ASCII in ECD format.  JavaScript
     programmers may find this familiar.  An interesting deviation from the
     JavaScript version of `toString()' is that this one will accept
     optional parameters that allow one to control the rendering options.

          $string = $ecd->toString(indent => 0, shiftwidth => 4)

    indent
          This is the number of spaces the first level nodes should be
          indented.  The default value is 0.

    shiftwidth
          This is the number of spaces a nested item should be indented.
          The default value is 4.

mergeWith($the_other_ecd)
     This combines the information contained in $the_other_ecd with $ecd.
     In the event that there is conflicting information, the information in
     $the_other_ecd takes precedence over what already existed in $ecd.

          $ecd->mergeWith($the_other_ecd)

getDepth
     This method returns how many levels deep one is in the object tree.
     The root level is considered 0.

          $depth = $ecd->getDepth()

getNodeClass
     This returns the node class (ie. Group, Component, Option, or
     Autovar) of an Embedix::ECD object.  It differs from the *ref()*
     operator in that the string "Embedix::ECD::" is omitted from the
     returned value.

          $name = $ecd->getNodeClass()

getFormatOptions(@opt);
     This is used internally by implementations of `toString()' to compute
     and return spacing information based on the formatting parameters
     passed to it.

          $opt_hash_ref = $ecd->getFormatOptions(@opt);

attributeToString($opt_hash_ref);
     This is used internally by implementations of `toString()' to render a
     node's attributes.

          $string = $ecd->attributeToString($opt_hash_ref);

CLASS VARIABLES
===============

   You shouldn't be touching these.  This is just here for your
information.

Embedix::ECD::__grammar
     This scalar contains the grammar for ECD files.

Embedix::ECD::__parser
     This contains an instance of Parse::RecDescent.

DIAGNOSTICS
===========

$line: was expecting $TAGNAME, but found $CRAP instead.
     This error occurs whenever an imbalanced tag is found.

$line: $ATTRIBUTE not allowed in $NODE_TYPE
     not implemented

BUGS
====

   This parser becomes exponentially slower as the size of ECD data
increases.  busybox.ecd takes 30 seconds to parse.  Don't even try to
parse linux.ecd - it will sit there for hours just sucking CPU before it
ultimately fails and gives you back nothing.  I don't know if there's
anything I can do about it.

   I have noticed that XML::Parser (which wraps around the C library,
expat) is 60 times faster than my Parse::RecDescent-based parser when
reading busybox.ecd.  I really want to take advantage of this.

COPYRIGHT
=========

   Copyright (c) 2000,2001 John BEPPU.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

AUTHOR
======

   John BEPPU <beppu@lineo.com>

SEE ALSO
========

related libraries and programs
     `ecdlib.py(3)', `config2ecd(1)', `tw(1)'

related perl modules
     Embedix::ECD::XMLv1(3pm)

CML2
     The Configuration Menu Language is a constraint-based language
     developed by Eric Raymond in an attempt to simplify the process of
     configuring the Linux kernel.

          http://www.tuxedo.org/~esr/kbuild/

CDL
     The Component Description Language was developed by Cygnus to support
     configurable compilation for the eCos operating system.

          http://sourceware.cygnus.com/ecos/

the lastest version
          http://opensource.lineo.com/cgi-bin/cvsweb/pm/Embedix/ECD/

an object for AUTOVAR nodes
***************************

NAME
====

   Embedix::ECD::Autovar - an object for AUTOVAR nodes

SYNOPSIS
========

     my $ecd = Embedix::ECD::Autovar->new();

DESCRIPTION
===========

   Embedix::ECD::Autovar is a subclass of Embedix::ECD for representing
AUTOVAR nodes.  It differs from its superclass in the following ways.

Differences
-----------

it doesn't (yet) except in name
AUTHOR
======

   John BEPPU <beppu@lineo.com>

SEE ALSO
========

   Embedix::ECD(3pm)

an object for COMPONENT nodes
*****************************

NAME
====

   Embedix::ECD::Component - an object for COMPONENT nodes

SYNOPSIS
========

     my $ecd = Embedix::ECD::Component->new();

DESCRIPTION
===========

   Embedix::ECD::Component is a subclass of Embedix::ECD for representing
COMPONENT nodes.  It differs from its superclass in the following ways.

Differences
-----------

it doesn't (yet) except in name
AUTHOR
======

   John BEPPU <beppu@lineo.com>

SEE ALSO
========

   Embedix::ECD(3pm)

an object for GROUP nodes
*************************

NAME
====

   Embedix::ECD::Group - an object for GROUP nodes

SYNOPSIS
========

     my $ecd = Embedix::ECD::Group->new();

DESCRIPTION
===========

   Embedix::ECD::Group is a subclass of Embedix::ECD for representing
GROUP nodes.  It differs from its superclass in the following ways.

Differences
-----------

it doesn't (yet) except in name
AUTHOR
======

   John BEPPU <beppu@lineo.com>

SEE ALSO
========

   Embedix::ECD(3pm)

a base class for ECD nodes
**************************

NAME
====

   Embedix::ECD::Node - a base class for ECD nodes

SYNOPSIS
========

   instantiation

     # don't instantiate me!

   inheriting

     package Embedix::ECD::Group;
     use vars qw(@ISA);

     @ISA = qw(Embedix::ECD::Node);

REQUIRES
========

Some::Module
DESCRIPTION
===========

   a brief summary of the module written with users in mind.

METHODS
=======

   methods

CLASS VARIABLES
===============

   cvars

DIAGNOSTICS
===========

   error messages

COPYRIGHT
=========

   Copyright (c) 2000 John BEPPU.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

AUTHOR
======

   John BEPPU <beppu@lineo.com>

SEE ALSO
========

related perl modules
the latest version

an object for OPTION nodes
**************************

NAME
====

   Embedix::ECD::Option - an object for OPTION nodes

SYNOPSIS
========

     my $ecd = Embedix::ECD::Option->new();

DESCRIPTION
===========

   Embedix::ECD::Option is a subclass of Embedix::ECD for representing
OPTION nodes.  It differs from its superclass in the following ways.

Differences
-----------

it doesn't (yet) except in name
AUTHOR
======

   John BEPPU <beppu@lineo.com>

SEE ALSO
========

   Embedix::ECD(3pm)

a class for root nodes
**********************

NAME
====

   Embedix::ECD::Root - a class for root nodes

SYNOPSIS
========

   instantiation

     $ecd = Embedix::ECD::Root->new(name => 'ecd');

REQUIRES
========

Embedix::ECD::Node
     to inherit from

DESCRIPTION
===========

   a brief summary of the module written with users in mind.

METHODS
=======

   methods

CLASS VARIABLES
===============

   cvars

DIAGNOSTICS
===========

   error messages

COPYRIGHT
=========

   Copyright (c) 2000 John BEPPU.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

AUTHOR
======

   John BEPPU <beppu@lineo.com>

SEE ALSO
========

related perl modules
the latest version

miscellaneous stuff
*******************

NAME
====

   Embedix::ECD::Util - miscellaneous stuff

SYNOPSIS
========

   import interesting stuff into your namespace

     use Embedix::ECD::Util qw(indent %default @attribute_order)

DESCRIPTION
===========

   In this module are things that didn't quite fit anywhere else.  I hope
to keep the contents of this module to a minimum.

COPYRIGHT
=========

   Copyright (c) 2000 John BEPPU.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

AUTHOR
======

   John BEPPU <beppu@lineo.com>

adds a method to write ECD data as XML
**************************************

NAME
====

   Embedix::ECD::XMLWriter - adds a method to write ECD data as XML

SYNOPSIS
========

   Load appropriate modules first

     use Embedix::ECD;
     use Embedix::ECD::XMLWriter qw(xml_from_cons);

   load an ECD and print it as XML

     my $ecd->newFromFile('tinylogin.ecd');
     print $ecd->toXML;

   If you want to preserve comments, use a cons instead of an Embedix::ECD
object.

     my $cons = Embedix::ECD->consFromFile('tinylogin.ecd');
     print xml_from_cons($cons);

REQUIRES
========

Embedix::ECD
     This is the module Embedix::ECD::XMLWriter augments.

EXPORTS
=======

xml_from_cons($cons)
DESCRIPTION
===========

   This module adds a few methods to the Embedix::ECD namespace for the
purposes of XML generation.  The reason it has been separated from the
main module is to allow one to only load this module when necessary and to
save memory when you it's not.

METHODS
=======

Generating XML from a cons
--------------------------

$xml = xml_from_cons($cons);
     A cons (or nested arrayref) is generated from the constructors in
     Embedix::ECD that have names starting with "cons".  This method will
     take a cons and generate well-formed XML from it.  Because a cons
     preserves comments in an ECD, xml_from_cons() is able to preserve
     comments in the XML it generates.

     Although the XML this generates will be well-formed, it runs a high
     risk of not being valid, because it cannot (yet?) order the
     attributes in accordance w/ the current DTD.

Add-ons to Embedix::ECD
-----------------------

$ecd = Embedix::ECD->newFromXML()
     not implemented.

$xml = $ecd->toXML()
     This generates an XML expression of an ECD in accordance to the DTD
     found in $Embedix::ECD::XMLWriter::__dtd.  The generated XML will be
     well-formed and valid.

$string = $ecd->attributeToXML()
     This does the same thing as attributeToString() but generates XML,
     instead.

CLASS VARIABLES
===============

$Embedix::ECD::XMLWriter::__dtd
     This contains the Document Type Definition for the XML version of the
     ECD format.

AUTHOR
======

   John BEPPU <beppu@lineo.com>

SEE ALSO
========

related perl modules
     Embedix::ECD(3pm)

adds a method to write ECD data as XML
**************************************

NAME
====

   Embedix::ECD::XMLv1 - adds a method to write ECD data as XML

SYNOPSIS
========

   Load appropriate modules first

     use Embedix::ECD;
     use Embedix::ECD::XMLv1 qw(xml_from_cons);

   load an ECD and print it as XML

     my $ecd->newFromFile('tinylogin.ecd');
     print $ecd->toXML;

   If you want to preserve comments, use a cons instead of an Embedix::ECD
object.

     my $cons = Embedix::ECD->consFromFile('tinylogin.ecd');
     print xml_from_cons($cons);

REQUIRES
========

Embedix::ECD
     This is the module Embedix::ECD::XMLv1 augments.

EXPORTS
=======

xml_from_cons($cons)
DESCRIPTION
===========

   This module adds a few methods to the Embedix::ECD namespace for the
purposes of XML generation.  The reason it has been separated from the
main module is to allow one to only load this module when necessary and to
save memory when you it's not.

METHODS
=======

Generating XML from a cons
--------------------------

$xml = xml_from_cons($cons);
     A cons (or nested arrayref) is generated from the constructors in
     Embedix::ECD that have names starting with "cons".  This method will
     take a cons and generate well-formed XML from it.  Because a cons
     preserves comments in an ECD, xml_from_cons() is able to preserve
     comments in the XML it generates.

     Although the XML this generates will be well-formed, it runs a high
     risk of not being valid, because it cannot (yet?) order the
     attributes in accordance w/ the current DTD.

Add-ons to Embedix::ECD
-----------------------

$ecd = Embedix::ECD->newFromXML()
     not implemented.

$xml = $ecd->toXML()
     This generates an XML expression of an ECD in accordance to the DTD
     found in $Embedix::ECD::XMLv1::__dtd.  The generated XML will be
     well-formed and valid.

$string = $ecd->attributeToXML()
     This does the same thing as attributeToString() but generates XML,
     instead.

CLASS VARIABLES
===============

$Embedix::ECD::XMLv1::__dtd
     This contains the Document Type Definition for the XML version of the
     ECD format.

AUTHOR
======

   John BEPPU <beppu@lineo.com>

SEE ALSO
========

related perl modules
     Embedix::ECD(3pm)

discrete emotion annotation processing
**************************************

NAME
====

   Emotion - discrete emotion annotation processing

SYNOPSIS
========

     empathize <transcript>
     empathize --index <transcript> [<transcript> ...]

DESCRIPTION
===========

   The most difficult part of this module is learning how to annotate
free-form text with information about what competition is taking place.
If you haven't studied http://ghost-wheel.net then go do that now.

   The first part of this document describes the XML representation of 3rd
person annotations and the validation rules.  The second part describes
the perl API.

XML TUTORIAL
============

The Basics
----------

   The minimum situation consists of the type of competition and two
opponents.

     abbreviation  type of competition (situation)
     ------------  -------------------------------
     destroys      [-] destroys [-]
     steals        [-] steals from [+]
     uneasy        [-] is made uneasy by [0]
     exposes       [+] exposes [-]
     impasse       [+] and [+] are at an impasse
     admires       [+] admires [0]
     observes      [0] observes [-]
     accepts       [0] accepts [+]
     ready         [0] and [0] are at readiness

   Each opponent is labelled either left or right, indicating on which
side of the situation he or she participates.  For example:

     <observes left="student" right="teacher">
       A student watches the teacher make a presentation.
     </observes>

     <observes right="student" left="teacher">
       The teacher watches a student make a presentation.
     </observes>

   Of course a teacher is probably more accustomed to lecturing in front
of a class than a student.  This information can be captured with the
`intensity' attribute:

     <observes left="student" right="teacher" intensity="gentle">
       A student watches the teacher make a presentation.
     </observes>

     <observes right="student" left="teacher" intensity="forceful">
       The teacher watches a student make a presentation.
     </observes>

   Now it is clear that the teacher's presentation involves some gentle
excitement, but a student presentation is an exciting test of
self-control.  Since no spin is involved, the emotion is roughly the same
regardless of whether we empathize with the presenter or the audience.  To
contrast, situations involving spin require some additional structure.
For example:

     <steals left="thief" right="child">
       The thief steals the teddy bear from the child.
     </steals>

   Here it is not clear which emotion is intended.  Opponents experience
the situation very differently.  Perhaps the thief is drunk with
accomplishment, but the child is probably quite angry.  To avoid this
ambiguity, situations involving spin follow a transactional structure:

     initiator:   (1) before ---+---> (3) after
                                |
                                v
     victim:             (2) tension

   Here is a hypothetical trace of a `steals' situation decomposed into
the three transaction phases:

     <steals left="thief" right="child" before="focused">
       The thief eyes the teddy bear maliciously and wrenches it
       from the child's passionate grip.
     </steals>

     <steals left="thief" right="child" tension="focused">
       The child becomes furious and starts crying.
     </steals>

     <steals left="thief" right="child" after="focused">
       The thief triumphantly stows the teddy bear in his backpack.
     </steals>

   Perhaps this sequence of events is ghastly, but here the goal is merely
to model emotions accurately.  In this example, the three phases
unambiguously correspond to "anxiety," "anger," and "drunk with
accomplishment."

   The attributes before, `tension', and after describe the emotional
tension.  Tension modifies a general emotion to fit the precise situation.
For example:

     <steals left="thief" right="child" before="relaxed">
       The thief grabs the teddy bear with abandon.
     </steals>

     <steals left="thief" right="child" before="stifled">
       The thief studies whether the teddy bear can be stolen.
     </steals>

   A tension modifier is either `focused', `relaxed', or `stifled'.
Emotion correspondance charts can assist in fitting the most accurate
modifier to the situation.  Of course a thief is not always successful:

     <steals left="thief" right="child" before="stifled">
       The thief studies whether the teddy bear can be stolen.
     </steals>

     <impasse left="child" right="thief" tension="focused">
       The child grips the teddy bear even more tightly.
     </impasse>

   The four situations involving spin (`steals', `exposes', `admires', and
`accepts') mostly follow the three phase transaction structure.  However,
flexibility offered by `accepts' shows the need to explicitly indicate an
initiator.  For example:

     <accepts left="chef" right="child" before="focused">
       I am hungry.  Is dinner ready?
     </accepts>

     <accepts left="chef" right="child" before="focused">
       You are hungry!
     </accepts>

   Looking just at the annotation, a reader cannot determine whether the
child is making a demand, or the chef is voicing the child's expression of
hunger.  An `initiator' attribute eliminates the ambiguity:

     <accepts left="chef" right="child" before="focused" initiator="right">
       I am hungry.  Is dinner ready?
     </accepts>

     <accepts left="chef" right="child" before="focused" initiator="left">
       You are hungry!
     </accepts>

   Now the situations can be distinguish.  While the annotation is
precise, it is also quite a lot of typing.  To reduce the burden on the
analyst, the parser is capable of guessing reasonable defaults by
consideration of who is talking.  For example:

     <accepts left="chef" initiator="child" before="focused">
       I am hungry.  Is dinner ready?
     </accepts>

   Or alternately:

     <talk who="child">
       <accepts left="chef" before="focused">
         I am hungry.  Is dinner ready?
       </accepts>
     </talk>

   We covered most of the simple variations.  Here is a summary:

     situation  variations
     ---------- ---------------------------------
     steals     before|tension|after, initiator
     exposes    before|tension|after, initiator
     admires    before|tension|after, initiator
     accepts    before|tension|after, initiator
     impasse    tension
     observes   intensity, [initiator]
     uneasy     intensity, [initiator]
     ready      intensity
     destroys   -

   The square brackets denote optional attributes.  More will be said
about this later.

Reaction
--------

   Question & answer (Q&A) format is a common way to structure discussion.
This section looks at the Q&A structure in comparison with the
competition model.  It will be shown that there are some conflicts in the
corresponce, however, the complementary features can be embraced.

   Questions usually end with a question mark.  Even so, from the point of
view of competition, questions are essentially demands.  For example:

     <accepts left="child" initiator="parent" before="focused">
       Does your teddy bear have brown fur?
     </accepts>

   In answer, the child's choices include:

     <accepts initiator="child" right="parent" before="focused">
       Yes!
     </accepts>

   Or:

     <impasse initiator="child" right="parent" tension="relaxed">
       Which teddy bear?
     </accepts>

   Notice that similar replies could be expected from the non-question
demand, "I want the teddy bear."  For example, `accepts' ("OK, here it
is.") or `impasse' ("Which teddy bear?").  While the question mark
inflects the demand somehow, its presence or absence does not seem
particularly significant in the context of competition.

   The answer side of Q&A will now be considered.  Answers are generally
offered in reaction to questions.  However, it is easy to demonstrate
ambiguity.  For example:

     <accepts left="child" initiator="parent" before="focused">
       Does your teddy bear have brown fur?
     </accepts>

     <impasse initiator="child" right="parent" tension="relaxed">
       Which teddy bear?
     </accepts>

   Is the child's reply a question or an answer?  Perhaps both, but
clearly the Q&A terminology is imprecise.  Despite these problems, some
kind of contextual relationship definitely exists.  To encode the Q&A
relationship precisely, a clear standard is needed to recognize it.

   The standard suggested here is that the participants must match but the
initiator must flip-flop.  These rules were discovered by surveying many
Q&A style exchanges and the rules seem to work well in practice.  re
(meaning "in reaction to") and id attributes serve the purpose.  For
example:

     <accepts id="q1" right="child" initiator="adult" before="focused">
       Does your teddy bear have brown fur?
     </accepts>

     <accepts re="q1" left="parent" initiator="child" before="focused">
       Yes!
     </accepts>

Quality
-------

   So far, the chosen markup may seem somewhat arbitrary.  For example,
why indicate merely `accepts'?

     <accepts id="q1" right="child" initiator="adult" before="focused">
       Does your teddy bear have brown fur?
     </accepts>

   Why not more detail, such as:

     <accepts id="q1" right="child" initiator="adult" before="focused">
       Does your
         <admires initiator="child" right="teddy bear" tension="relaxed">
           teddy bear
         </admires>
       have brown fur?
     </accepts>

   In fact, either annotation could be accurate.  Part of the problem is
that both the story and annotation are being written by the same person.
This is a conflict of interest because i can adjust the story to improve
my annotations, and visa-versa.  Recall that the goal here is to develop
the best quality annotations *without* changing the story.

   Another problem is that written text is not rich enough as a medium to
thoroughly convey life's emotional textual.  To contrast, film (or the
actual life experience itself) is quite sufficiently expressive.  So
assuming we are watching a film, what consistitutes best quality markup?
For example:

     <steals initiator="Yupi" right="Lon" before="focused">
       Yupi gives Lon a beautiful and fragrant flower.
     </steals>

   Most likely this markup is wrong.  A proposed criteria for judging the
quality of markup follows:

   * Is it detailed enough to isolate single emotions?

     Looking at a scene as a sequences of moments, every moment can be
     consider an *independent* competition event.  The question is: into
     how many intervals must we divide the timeline such that each interval
     is exactly one emotion?

   * Does it span the entire duration of the emotion?

     Some clarity is lost if a single emotion is sub-divided excessively.
     A single annotation should span as much time as is practical.  The
     duration criteria is also consided in the next section, "Resolution."

Resolution
----------

   The parser tries to keep track of situations which remain unresolved
(or pending).  For example:

     <accepts id="o1" initiator="clerk" left="Joey" before="focused">
       What toppings do you want on your pizza?
     </accepts>

     <impasse id="o2" re="o1" left="Joey" right="cleck" tension="stifled">
       Joey puts the phone on hold.
     </impasse>

   In general, stories don't stop abruptly leaving unresolved
cliffhangers.  Here is a clue that can be used to debug annotations.
After processing a transcript, `empathize' outputs all the situations
which do not find closure.  In the above example, the situation is pending
until Joey picks up the phone or the clerk gives up in disgust or whatever.

   Similarly, a warning is triggered when the same situation is resolved
more than once.  For example:

     <accepts id="o3" initiator="clerk" left="Joey" before="focused">
       How many pizzas do you want?
     </accepts>

     <accepts re="o3" initiator="Joey" before="focused">
       i want exactly three pizzas.
     </accepts>

     <accepts re="o3" initiator="Joey" before="focused">
       i want exactly two pizzas.
     </accepts>

   Notice the situation `o3' is listed in the re attribute twice.  This is
unnecessarily ambiguous.  There are a variety of ways to better model the
scenario.

Revoke / Amend
--------------

   Sometimes i say something which i wish i never said.  The `revoke'
attribute reflects this scenario.

     <accepts id="q1" initiator="Spike" left="Jeff" before="focused">
       What time is it?
     </accepts>

     <impasse id="a1" re="q1" tension="focused" right="Spike" initiator="Jeff">
       No idea!
     </observes>

     <uneasy id="q2" amend="q1" initiator="Spike" left="Jeff" intensity="gentle">
       Spike gives Jeff a threatening look.
     </uneasy>

     <accepts id="a2" revoke="a1" re="q1" before="focused" left="Spike"
              initiator="Jeff">
       Eleven hundred hours!  Sir!
     </accepts>

   `q1' is resolved by `a1' until `q1' becomes pending again when `a1' is
revoked by `a2'.  Now that `q1' is again pending, the re attribute can be
used in `a2' to substitute a revised reaction.

   To contrast, Spike's demand for the time in `q1' is not revoked by his
subsequent threatening look in `q2'.  Here, what needs to be reflected is
Spike's change in tone, but not change in fact.  The `amend' attribute
serves this purpose.

Echo
----

   The echo attribute represents the repeated emphasis of the same
situation.

     <impasse id="m1" left="child" right="mother" tension="focused"
              absent="right">
       Where is my mother?
     </impasse>

     <impasse echo="m1" id="m2" left="child" right="mother" tension="stifled">
       i miss my mom!  :-(
     </impasse>

   Once echo'd, `m1' is no longer pending.  Only `m2' remains pending.

Absent
------

   Another way to manage resolution is to declare the victim absent.  Here
is an example:

     <talk who="teacher">
       <accepts left="students" before="focused" absent="left">
         The students listen to the teacher's tedious monologue.
       </accepts>
     </talk>

   In fact, the teacher may never know whether the situation was truly
`accepts', `observes', or even merely:

     <ready intensity="gentle" left="students" right="teacher">
       The students are intermittently aware that the
       teacher continues to talk.
     </ready>

   Notice that the `absent' attribute is unnecessary in this case.  A few
situations do not trigger any need for resolution, and `ready' is one of
them.

Wildcards
---------

     <accepts left="*" initiator="Crawford" before="focused">
       Does anyone know the time?
     </accepts>

   Talk about anthropomorphic rivals. XXX

Context
-------

   Here is a prior example updated with new markup:

     <steals id="p1" initiator="thief" right="child" before="focused">
       The thief eyes the teddy bear maliciously and wrenches it
       from the child's passionate grip.
     </steals>

     <steals re="p1" left="thief" initiator="child" tension="focused">
       The child becomes furious and starts crying.
     </steals>

     <steals context="p1" initiator="thief" right="child" after="focused">
       The thief triumphantly stows the teddy bear in his backpack.
     </steals>

   This last situation describing the thief gloating over his
accomplishment is not really an `answer' to "p1", but there is certainly
some kind of direct contextual connection.  The context attribute is
available for such cases.  context is a catch-all.  It is appropriate for
any kind of generic relationship for which a more specific classification
is not available.

EMOTION LIBRARY API
===================

   * Emotion::set_transcript($xml_file)

   * my $dialog_id = Emotion::set_speaker($who)

   * my @pending = Emotion::unresolved()

Emotion::Atom Methods
---------------------

   * my $situation = Emotion::Atom->new($expat, $attr)

   * my $emotion = $atom->emotion;

SEE ALSO
========

   http://ghost-wheel.net

generalized END {}.
*******************

NAME
====

   End - generalized END {}.

SYNOPSIS
========

     use End;

     {  my $foo = end {print "Leaving the block\n"};
        ...
        last;    # prints "Leaving the block\n".
        ...
     }

DESCRIPTION
===========

   The module End exports a single subroutine end, which allows you to set
up some code that is run whenever the current block is exited, regardless
whether that is due to a return, next, last, redo, exit, die, goto or just
reaching the end of the block.

   To be more precise, end returns an object, that will execute the code
when the object is destroyed; that is, when the variable assigned to goes
out of scope. If the variable is lexical to the current block, the code
will be executed when leaving the block.

   One can force premature execution of the code by undefining the variable
assigned to, or assigning another value to the variable.

   end only takes one argument, a code reference. If one wishes the code
reference to take arguments, wrapping the code reference in a closure
suffices.

BUGS
====

   Due to a bug in Perl 5.6.0 (and perhaps before), anonymous subroutines
that are not a closure will not go out of scope, not even on program
termination. That is why end wraps the code fragment in a closure.

   There is a second bug in Perl 5.6.0 (and perhaps before) why this is
necessary. If the code fragment isn't wrapped in another code reference,
the original subroutine will be blessed in the package, making that ref on
that code no longer returns the right value.

REVISION HISTORY
================

     $Log: End.pm,v $
     Revision 1.2  2000/05/31 20:25:33  abigail
     Added the license paragraph in the POD section.

     Revision 1.1  2000/05/31 19:35:01  abigail
     Initial revision

AUTHOR
======

   This package was written by Abigail, *abigail@delanet.com*.

COPYRIGHT & LICENSE
===================

   This program is copyright 2000 by Abigail.

   Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

use nice English (or awk) names for ugly punctuation variables
**************************************************************

NAME
====

   English - use nice English (or awk) names for ugly punctuation variables

SYNOPSIS
========

     use English;
     ...
     if ($ERRNO =~ /denied/) { ... }

DESCRIPTION
===========

   This module provides aliases for the built-in variables whose names no
one seems to like to read.  Variables with side-effects which get
triggered just by accessing them (like $0) will still be affected.

   For those variables that have an *awk* version, both long and short
English alternatives are provided.  For example, the $/ variable can be
referred to either $RS or $INPUT_RECORD_SEPARATOR if you are using the
English module.

   See Perlvar (perl.info), for a complete list of these.

BUGS
====

   This module provokes sizeable inefficiencies for regular expressions,
due to unfortunate implementation details.  If performance matters,
consider avoiding English.

use words to dereference things
*******************************

NAME
====

   English::Reference - use words to dereference things

SYNOPSIS
========

     use English::Reference;
     or
     use English::Reference qw(deref);
     ...
     print SCALAR \"Hello World";

DESCRIPTION
===========

   Provides the ability to use:

     ARRAY  $arrayref
     CODE   $coderef
     GLOB   $globref
     HASH   $hashref
     SCALAR $scalaref

   en lieu of

     @$arrayref
     &$coderef
     *$globref
     %$hashref
     $$scalaref

   or

     @{$arrayref}
     &{$coderef}
     *{$globref}
     %{$hashref}
     ${$scalaref}

   As an added bonus, there is a function deref; not exported by default;
which you can use to dereference a reference of any type.

CAVEATS
=======

   You cannot do ARRAY{$arrayref} etc. This is not too bad seeing as the
whole point of this module is to reduce the amount of punctuation you use.

AUTHORS
=======

   Jerrad Pierce <belg4mit@mit.edu, the_lorax@usa.net>, Jeff Pinyan
<japhy@pobox.com>, Casey R. Tweten <crt@kiski.net>

SEE ALSO
========

   English(3).

perl module that imports environment variables as scalars or arrays
*******************************************************************

NAME
====

   Env - perl module that imports environment variables as scalars or
arrays

SYNOPSIS
========

     use Env;
     use Env qw(PATH HOME TERM);
     use Env qw($SHELL @LD_LIBRARY_PATH);

DESCRIPTION
===========

   Perl maintains environment variables in a special hash named %ENV.  For
when this access method is inconvenient, the Perl module Env allows
environment variables to be treated as scalar or array variables.

   The `Env::import()' function ties environment variables with suitable
names to global Perl variables with the same names.  By default it ties
all existing environment variables (`keys %ENV') to scalars.  If the
import function receives arguments, it takes them to be a list of
variables to tie; it's okay if they don't yet exist. The scalar type
prefix '$' is inferred for any element of this list not prefixed by '$' or
'@'. Arrays are implemented in terms of split and join, using
`$Config::Config{path_sep}' as the delimiter.

   After an environment variable is tied, merely use it like a normal
variable.  You may access its value

     @path = split(/:/, $PATH);
     print join("\n", @LD_LIBRARY_PATH), "\n";

   or modify it

     $PATH .= ":.";
     push @LD_LIBRARY_PATH, $dir;

   however you'd like. Bear in mind, however, that each access to a tied
array variable requires splitting the environment variable's string anew.

   The code:

     use Env qw(@PATH);
     push @PATH, '.';

   is equivalent to:

     use Env qw(PATH);
     $PATH .= ":.";

   except that if `$ENV{PATH}' started out empty, the second approach
leaves it with the (odd) value "`:.'", but the first approach leaves it
with ".".

   To remove a tied environment variable from the environment, assign it
the undefined value

     undef $PATH;
     undef @LD_LIBRARY_PATH;

LIMITATIONS
===========

   On VMS systems, arrays tied to environment variables are read-only.
Attempting to change anything will cause a warning.

AUTHOR
======

   Chip Salzenberg <`chip@fin.uucp'> and Gregor N. Purdy
<`gregor@focusresearch.com'>

Perl module that "imports" environment variables as arrays
**********************************************************

NAME
====

   Env::Array - Perl module that "imports" environment variables as arrays

SYNOPSIS
========

   With explicit delimiters:

     use Env::Array qw(PATH :);
     use Env::Array qw(@MANPATH :);

   With inferred delimiters:

     use Env::Array qw(@LD_LIBRARY_PATH);

DESCRIPTION
===========

   The `Env::Array' Perl module allows environment variables to be treated
as Perl array variables, analogous to the way the Env module allows them
to be treated as scalar variables.

   The Env::Array::import() function requires pairs of environment variable
names and delimiter strings to be presented in the use statement. If just
one argument is given, then `$Config::Config{path_sep}' is taken as the
delimiter. `Env::Array' allows the variable name to have the '`@'' array
type prefix, if desired. The variable being tied must otherwise begin with
a letter. Unlike Env, `Env::Array' does nothing if the use list is empty.

   After an environment variable is tied, just use it like an ordinary
array.  Bear in mind, however, that each access to the variable requires
splitting the string anew.

   The code:

     use Env::Array qw(@PATH);
     push @PATH, '.';

   is equivalent to:

     use Env qw(PATH);
     	$PATH .= ":.";

   except that the `Env::Array' approach does the right thing for both
Unix-like operating systems and for Win32. Also, if `$ENV{PATH}' was the
empty string, the Env approach leaves it with the (odd) value "`:.'", but
the `Env::Array' approach leaves it with ".".

   `Env::Array' requires Perl 5.005 or later for proper operation due to
its use of tied arrays.

SEE ALSO
========

   The Env Perl module.

AUTHOR
======

   Gregor N. Purdy <`gregor@focusresearch.com'>

COPYRIGHT
=========

   Copyright (C) 1999-2000 Gregor N. Purdy. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Advanced operations on path variables
*************************************

NAME
====

   Env::Path - Advanced operations on path variables

SYNOPSIS
========

     use Env::Path;

     # basic usage
     my $manpath = Env::Path->MANPATH;
     $manpath->Append('/opt/samba/man');
     for ($manpath->List) { print $_, "\n" };

     # similar to above using the "implicit object" shorthand
     Env::Path->MANPATH;
     MANPATH->Append('/opt/samba/man');
     for (MANPATH->List) { print $_, "\n" };

     # one-shot use
     Env::Path->PATH->Append('/usr/sbin');

     # change instances of /usr/local/bin to an architecture-specific dir
     Env::Path->PATH->Replace('/usr/local/bin', "/usr/local/$ENV{PLATFORM}/bin");

     # more complex use (different names for same semantics)
     my $libpath;
     if ($^O =~ /aix/) {
         $libpath = Env::Path->LIBPATH;
     } else {
         $libpath = Env::Path->LD_LIBRARY_PATH;
     }
     $libpath->Assign(qw(/usr/lib /usr/openwin/lib));
     $libpath->Prepend('/usr/ucblib') unless $libpath->Has('/usr/ucblib');
     $libpath->InsertAfter('/usr/ucblib', '/xx/yy/zz');
     $libpath->Uniqify;
     $libpath->DeleteNonexistent;
     $libpath->Remove('/usr/local/lib');
     print $libpath->Name, ":";
     for ($libpath->List) { print " $_" };
     print "\n";

     # simplest usage: bless all existing EV's as Env::Path objects
     use Env::Path ':all';
     my @cats = PATH->Whence('cat*');
     print "@cats\n";

DESCRIPTION
===========

   Env::Path presents an object-oriented interface to *path variables*,
defined as that subclass of *environment variables* which name an ordered
list of filesystem elements separated by a platform-standard separator
(typically ':' on UNIX and ';' on Windows).

   Of course, core Perl constructs such

     $ENV{PATH} .= ":/usr/local/bin";

   will suffice for most uses. Env::Path is for the others; cases where
you need to insert or remove interior path entries, strip redundancies,
operate on a pathvar without having to know whether the current platform
uses ":" or ";", operate on a pathvar which may have a different name on
different platforms, etc.

   This OO interface is slightly unusual in that the environment variable
is itself the object and the constructor is Env::Path->AUTOLOAD(); thus

     Env::Path->MANPATH;

   would bless $ENV{MANPATH} into its package. `$ENV{MANPATH}' is
otherwise unmodified with the exception of possible autovivification.  The
only attribute the new object has is its pre-existing value.

   Also, while the object reference may be assigned and used in the normal
style

     my $path = Env::Path->CLASSPATH;
     $path->Append('/opt/foo/classes.jar');

   a shorthand is also available:

     Env::Path->CLASSPATH;
     CLASSPATH->Append('/opt/foo/classes.jar');

   I.e. the name of the path variable may be used as a proxy for its
object reference. This may be done at 'use' time too:

     use Env::Path qw(PATH CLASSPATH);	# or qw(:all) to bless all EV's
     CLASSPATH->Append('/opt/foo/classes.jar');

CLASS METHODS
-------------

   * <CONSTRUCTOR>

     The constructor may have any name; it's assumed to name a *path
     variable* as defined above. Returns the object reference.

   * PathSeparator

     Returns or sets the platform-specific path separator character, by
     default : on open platforms and *;* on monopolistic ones.

INSTANCE METHODS
----------------

   Unless otherwise indicated these methods return the object reference,
allowing method calls to be strung together. All methods which take lists
join them together using the value of `Env::Path->PathSeparator'.

   * Name

     Returns the name of the pathvar.

   * Has

     Returns true iff the specified entry is present in the pathvar.

   * Assign

     Takes a list and sets the pathvar to that value, separated by the
     current PathSeparator.

   * List

     Returns the current path in list format.

   * Prepend

     For each entry in the supplied list, removes it from the pathvar if
     present and prepends it, thus ensuring that it's present exactly once
     and at the front.

   * Append

     Analogous to Prepend.

   * InsertBefore

     Takes a <dirname> and a list, inserts the list just before the first
     instance of the <dirname>. If *dirname* is not found, works just like
     *Prepend*. As with *Prepend*, duplicates of the supplied entries are
     removed.

   * InsertAfter

     Analogous to *InsertBefore*

   * Remove

     Removes the specified entries from the path.

   * Replace

     Takes a /pattern/ and a list. Traverses the path and replaces all
     entries which match the pattern with the concatenated list entries.

   * DeleteNonexistent

     Removes from the path all entries which do not exist as filesystem
     entities.

   * Uniqify

     Removes redundant entries (the 2nd through nth instances of each
     entry).

   * Whence

     Takes a pattern and returns an ordered list of all filenames found
     along the path which match it and are executable.

   * Shell

     Returns a string suitable for passing to a shell which would set and
     export the pathvar to its current value within the shell context.

NOTES
=====

   * No provision is made for path variables which are not also environment
     variables, a situation which is technically possible but quite rare.

   * Except where necessary no assumption is made that path entries should
     be directories, because pathvars like CLASSPATH may contain "virtual
     dirs" such as zip/jar files. For instance the *DeleteNonexistent*
     method does not remove entries which are files.  In Perl terms the
     test applied is -e, not -d.

   * The shorthand notation for pathvar FOO is implemented by hacking
     *@FOO::ISA*, so there's a slight risk of namespace collision if your
     code also creates packages with all-upper-case names. No packages are
     created unless the shorthand notation is employed.

WORKS ON
========

   UNIX and Windows.

AUTHOR
======

   David Boyce <dsb@world.std.com>

COPYRIGHT
=========

   Copyright (c) 2000 David Boyce. All rights reserved.  This Perl program
is free software; you may redistribute and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   perl(1), perlobj(1), Env::Array(3)

Load Envy Files
***************

NAME
====

   Envy::Load - Load Envy Files

SYNOPSIS
========

     use Envy::Load qw(dev objstore);

     {
     	my $env = Envy::Load->new();
     	$env->load(qw(prod testdb));

     # %ENV restored when $env goes out of scope
         }

DESCRIPTION
===========

   Similar to `envy load ...`.

System errno constants
**********************

NAME
====

   Errno - System errno constants

SYNOPSIS
========

     use Errno qw(EINTR EIO :POSIX);

DESCRIPTION
===========

   Errno defines and conditionally exports all the error constants defined
in your system `errno.h' include file. It has a single export tag,
`:POSIX', which will export all POSIX defined error numbers.

   Errno also makes `%!' magic such that each element of `%!' has a
non-zero value only if $! is set to that value. For example:

     use Errno;

     unless (open(FH, "/fangorn/spouse")) {
         if ($!{ENOENT}) {
             warn "Get a wife!\n";
         } else {
             warn "This path is barred: $!";
         }
     }

   If a specified constant `EFOO' does not exist on the system, `$!{EFOO}'
returns "".  You may use `exists $!{EFOO}' to check whether the constant
is available on the system.

CAVEATS
=======

   Importing a particular constant may not be very portable, because the
import will fail on platforms that do not have that constant.  A more
portable way to set $! to a valid value is to use:

     if (exists &Errno::EFOO) {
         $! = &Errno::EFOO;
     }

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

COPYRIGHT
=========

   Copyright (c) 1997-8 Graham Barr. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Error/exception handling in an OO-ish way
*****************************************

NAME
====

   Error - Error/exception handling in an OO-ish way

SYNOPSIS
========

     use Error qw(:try);

     throw Error::Simple( "A simple error");

     sub xyz {
         ...
     	record Error::Simple("A simple error")
     	    and return;
     }

     unlink($file) or throw Error::Simple("$file: $!",$!);

     try {
     	do_some_stuff();
     	die "error!" if $condition;
     	throw Error::Simple -text => "Oops!" if $other_condition;
     }
     catch Error::IO with {
     	my $E = shift;
     	print STDERR "File ", $E->{'-file'}, " had a problem\n";
     }
     except {
     	my $E = shift;
     	my $general_handler=sub {send_message $E->{-description}};
     	return {
     	    UserException1 => $general_handler,
     	    UserException2 => $general_handler
     	};
     }
     otherwise {
     	print STDERR "Well I don't know what to say\n";
     }
     finally {
     	close_the_garage_door_already(); # Should be reliable
     }; # Don't forget the trailing ; or you might be surprised

DESCRIPTION
===========

   The Error package provides two interfaces. Firstly Error provides a
procedural interface to exception handling. Secondly Error is a base class
for errors/exceptions that can either be thrown, for subsequent catch, or
can simply be recorded.

   Errors in the class Error should not be thrown directly, but the user
should throw errors from a sub-class of Error.

PROCEDURAL INTERFACE
====================

   Error exports subroutines to perform exception handling. These will be
exported if the `:try' tag is used in the use line.

try BLOCK CLAUSES
     try is the main subroutine called by the user. All other subroutines
     exported are clauses to the try subroutine.

     The BLOCK will be evaluated and, if no error is throw, try will return
     the result of the block.

     `CLAUSES' are the subroutines below, which describe what to do in the
     event of an error being thrown within BLOCK.

catch CLASS with BLOCK
     This clauses will cause all errors that satisfy `$err->isa(CLASS)' to
     be caught and handled by evaluating BLOCK.

     BLOCK will be passed two arguments. The first will be the error being
     thrown. The second is a reference to a scalar variable. If this
     variable is set by the catch block then, on return from the catch
     block, try will continue processing as if the catch block was never
     found.

     To propagate the error the catch block may call `$err->throw'

     If the scalar reference by the second argument is not set, and the
     error is not thrown. Then the current try block will return with the
     result from the catch block.

except BLOCK
     When try is looking for a handler, if an except clause is found BLOCK
     is evaluated. The return value from this block should be a HASHREF or
     a list of key-value pairs, where the keys are class names and the
     values are CODE references for the handler of errors of that type.

otherwise BLOCK
     Catch any error by executing the code in BLOCK

     When evaluated BLOCK will be passed one argument, which will be the
     error being processed.

     Only one otherwise block may be specified per try block

finally BLOCK
     Execute the code in BLOCK either after the code in the try block has
     successfully completed, or if the try block throws an error then
     BLOCK will be executed after the handler has completed.

     If the handler throws an error then the error will be caught, the
     finally block will be executed and the error will be re-thrown.

     Only one finally block may be specified per try block

CLASS INTERFACE
===============

CONSTRUCTORS
------------

   The Error object is implemented as a HASH. This HASH is initialized
with the arguments that are passed to it's constructor. The elements that
are used by, or are retrievable by the Error class are listed below, other
classes may add to these.

     -file
     -line
     -text
     -value
     -object

   If `-file' or `-line' are not specified in the constructor arguments
then these will be initialized with the file name and line number where
the constructor was called from.

   If the error is associated with an object then the object should be
passed as the `-object' argument. This will allow the Error package to
associate the error with the object.

   The Error package remembers the last error created, and also the last
error associated with a package. This could either be the last error
created by a sub in that package, or the last error which passed an object
blessed into that package as the `-object' argument.

throw ( [ ARGS ] )
     Create a new Error object and throw an error, which will be caught by
     a surrounding try block, if there is one. Otherwise it will cause the
     program to exit.

     throw may also be called on an existing error to re-throw it.

with ( [ ARGS ] )
     Create a new Error object and returns it. This is defined for
     syntactic sugar, eg

          die with Some::Error ( ... );

record ( [ ARGS ] )
     Create a new Error object and returns it. This is defined for
     syntactic sugar, eg

          record Some::Error ( ... )
          	and return;

STATIC METHODS
--------------

prior ( [ PACKAGE ] )
     Return the last error created, or the last error associated with
     PACKAGE

OBJECT METHODS
--------------

stacktrace
     If the variable `$Error::Debug' was non-zero when the error was
     created, then stacktrace returns a string created by calling
     `Carp::longmess'. If the variable was zero the stacktrace returns the
     text of the error appended with the filename and line number of where
     the error was created, providing the text does not end with a newline.

object
     The object this error was associated with

file
     The file where the constructor of this error was called from

line
     The line where the constructor of this error was called from

text
     The text of the error

OVERLOAD METHODS
----------------

stringify
     A method that converts the object into a string. This method may
     simply return the same as the text method, or it may append more
     information. For example the file name and line number.

     By default this method returns the `-text' argument that was passed to
     the constructor, or the string `"Died"' if none was given.

value
     A method that will return a value that can be associated with the
     error. For example if an error was created due to the failure of a
     system call, then this may return the numeric value of $! at the time.

     By default this method returns the `-value' argument that was passed
     to the constructor.

PRE-DEFINED ERROR CLASSES
=========================

Error::Simple
     This class can be used to hold simple error strings and values. It's
     constructor takes two arguments. The first is a text value, the second
     is a numeric value. These values are what will be returned by the
     overload methods.

     If the text value ends with `at file line 1' as $@ strings do, then
     this infomation will be used to set the `-file' and `-line' arguments
     of the error object.

     This class is used internally if an eval'd block die's with an error
     that is a plain string.

KNOWN BUGS
==========

   None, but that does not mean there are not any.

AUTHORS
=======

   Graham Barr <gbarr@pobox.com>

   The code that inspired me to write this was originally written by Peter
Seibel <peter@weblogic.com> and adapted by Jesse Glick
<jglick@sig.bsh.com>.

a Module for letting Errors do their own handling
*************************************************

NAME
====

   Error::Unhandled - a Module for letting Errors do their own handling

SYNOPSIS
========

     use Error qw(:try);
     use Error::Unhandled;

     try {
       &foo;
     } otherwise {
       my $E = shift;
       print "I caught:\n".$E->stringify."\n\n";
     };

     &foo;

     sub foo {
       throw Error::Unhandled(unhandled => sub {print "No one handled this.\n"; exit});
     }

DESCRIPTION
===========

   While doing ASP programming, I wanted to use an object oriented
exception handling system.  Graham Barr pointed me at `Error.pm', which
handled almost everything I needed.  It was missing, however, a way for
exceptions to define their own default error handling behavior.  This can
be very useful when ASP programming - someone using your object can decide
to implement their own error handling routines, but if they don't the user
will at least get a semi-informative message in their browser.  After
trying several different approaches, I ended up with a subclass of Error
titled `Error::Unhandled'.

   The *only* difference in behavior between `Error::Unhandled' and Error
is what happens when throw is called.  The implementation of throw in
`Error::Unhandled' uses caller to search the call stack, looking for
`Error::subs::try'.  If it finds one, it throws the exception as per
normal behavior.  If it doesn't find one, it calls `$self->unhandled'.
Before doing that, however, it checks to see if the element `unhandled' is
defined in its hash.  If it is and it is a reference to a subroutine, it
calls that instead.  Note that if the element `unhandled' is present and
is not a reference to a subroutine, throw will not call `$self->unhandled'.
Finally, after all of that returns, throw will throw the exception as per
normal behavior.  If you don't want it to throw the exception, call exit
or die within your `unhandled' subroutine.

   It is, of course, also possible (and recommended in many situations) to
sub class `Error::Unhandled' and provide a class-defined implementation of
`unhandled'.  Also note that both the instance-defined and class-defined
`unhandled' methods receive `$self' as their first parameter.

Installation instructions
-------------------------

   This module requires Error, available from CPAN.

AUTHOR
======

   Toby Everett, teverett@alascom.att.com

Event loop processing
*********************

NAME
====

   Event - Event loop processing

WARNING
=======

   *THIS IS EXPERIMENTAL CODE AND IS LIKELY TO CHANGE A CONSIDERABLE
AMOUNT* *BEFORE IT IS RELEASED FOR GENERAL USE.*

SYNOPSIS
========

     use Event;

     # initialize application

     Event->Loop;

     # and some callback will call
     Event->exit;

DESCRIPTION
===========

EVENT TYPES
===========

idle
          Event->idle( \&idle );

     Call `&idle' when the loop is idle.

atexit
          $e = Event->atexit( \&cleanup )

     Call `&cleanup' when the event loop is about to exit. If after
     registering an atexit handler it is not required, the the `cancel'
     method can be called on $e.

watchvar
          $e = Event->watchvar(
          	-variable => \$var,
          	-async    => 0,
          	-callback => \&watcher,
          );

     Call `&watcher' when `$var' is changed. If `-async' is *true* then
     `&watcher' will be called immediately, otherwise the call to
     `&watcher' will be pushed onto the event queue.

     When called `&watcher' will be passed $e as the first argument,
     `&watcher' may the call the `cancel' method to stop any future
     changes to `$var' creating events.

timer          $e = Event->timer( 	-after    => 10, 	-at	  => time + 10, 	-interval => 2, 	-callback => \&timeout     );
     Call `&timeout' either after a given delay or at a given time (-after
     and -at are mutually exclusive). Then optionally call `&timeout' at
     given intervals.

     When called `&timeout' will be passed $e as the first argument, and
     the time that the event was triggered as the second argument.
     `&timeout' may the call the `cancel' method on $e to stop any future
     timer events, or if `-interval' was not given and `-after' was then
     `&timeout' may call the `again' method on $e which will cause the
     event to re-occur, the time at which the event will re-occur is the
     value given by `-after' added to the time the event was triggered.
     Due to lags in the event loop calling the callback, this time may
     already be in the past, in which case the event will be queued
     immediately

io
          $e = Event->io(
          	-handle => $sock,
          	-events => POLLREAD,
          	-callback => \&ready
          );

     Call `&ready' when $sock has data to be read. `-event' can take any
     combination of the constants that are accepted by IO::Poll.

     When called `&ready' is passed $e as the first argument, $handle as
     the second argument and the events that happened as the third
     argument.  `&ready' may call the `cancel' method on $e to stop any
     future event handling on $handle

signal          $e = Event->signal( 	-signal => 'INT', 	-callback => \&interrupt     );
     Call `&interrupt' when an `INT' signal is received. `-signal' accepts
     any signal name except `CHLD', see below.

     When called `&interrupt' will be passed $e as the first argument and
     the name of the signal as the second. `&interrupt' amy call the
     `cancel' method on $e to stop any future events being caught.

process
          $e = Event->process(
          	-pid => $pid,
          	-callback => \&reap
          );

     Call `&reap' when the child process with pid `$pid' exits. If `$pid'
     is not given then `&reap' will be called for any process that does not
     have it's own event handler.

     When called `&reap' will be passed $e as the first parameter, the
     process id of the child as the second and the exit status of the
     child as the third. `&reap' may call the `cancel' method on $e to stop
     future process events, this is only of use on event handlers where
     `-pid' is not specified.

FUTURE ENHANCEMENTS
===================

     # generate an event when we can successfully run an op
     $e = Event->semaphore(
     	-semaphore => $sem,
     	-op => $op,
     	-callback => \&gotit
     );

     # generate an event when the msg queue is/is not empty
     $e = Event->msg(
     	-msg => $msg,
     	-callback => \&doit
     );

     =head1 AUTHOR

   Graham Barr <`gbarr@pobox.com'>

COPYRIGHT
=========

   Copyright (c) 1997 Graham Barr. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

MakeMaker glue for the C-level Event API
****************************************

NAME
====

   Event::MakeMaker - MakeMaker glue for the C-level Event API

SYNOPSIS
========

   This is an advanced feature of Event.

DESCRIPTION
===========

   For optimal performance, hook into Event at the C-level.  You'll need
to make changes to your Makefile.PL and add code to your `xs' / c file(s).

WARNING
=======

   When you hook in at the C-level you get a *huge* performance gain, but
you also reduce the chances that your code will work unmodified with newer
versions of `perl' or Event.  This may or may not be a problem.  Just be
aware, and set your expectations accordingly.

HOW TO
======

Makefile.PL
-----------

     use Event::MakeMaker qw(event_args);

     # ... set up %args ...

     WriteMakefile(event_args(%args));

XS
--

     #include "EventAPI.h"

     BOOT:
       I_EVENT_API("YourModule");

API (v21)
---------

     struct EventAPI {
        I32 Ver;

     /* EVENTS */
     void (*queue   )(pe_event *ev);
     void (*start   )(pe_watcher *ev, int repeat);
     void (*now     )(pe_watcher *ev);
     void (*stop    )(pe_watcher *ev, int cancel_events);
     void (*cancel  )(pe_watcher *ev);
     void (*suspend )(pe_watcher *ev);
     void (*resume  )(pe_watcher *ev);

     /* All constructors optionally take a stash and template.  Either
       or both can be NULL.  The template should not be a reference. */
     pe_idle     *(*new_idle  )(HV*, SV*);
     pe_timer    *(*new_timer )(HV*, SV*);
     pe_io       *(*new_io    )(HV*, SV*);
     pe_var      *(*new_var   )(HV*, SV*);
     pe_signal   *(*new_signal)(HV*, SV*);

     /* TIMEABLE */
     void (*tstart)(pe_timeable *);
     void (*tstop)(pe_timeable *);

     /* HOOKS */
     pe_qcallback *(*add_hook)(char *which, void *cb, void *ext_data);
     void (*cancel_hook)(pe_qcallback *qcb);

     /* STATS */
     void (*install_stats)(pe_event_stats_vtbl *esvtbl);
     void (*collect_stats)(int yes);
     pe_ring *AllWatchers;

     /* TYPEMAP */
     SV   *(*watcher_2sv)(pe_watcher *wa);
     void *(*sv_2watcher)(SV *sv);
     SV   *(*event_2sv)(pe_event *ev);
     void *(*sv_2event)(SV *sv);
      };

EXAMPLE
-------

     static pe_io *X11_ev=0;

     static void x_server_dispatch(void *ext_data)
     { ... }

     if (!X11_ev) {
       X11_ev = GEventAPI->new_io(0,0);
       X11_ev->poll = PE_R;
       sv_setpv(X11_ev->base.desc, "X::Server");
       X11_ev->base.callback = (void*) x_server_dispatch;
       X11_ev->base.ext_data = <whatever>;
       X11_ev->base.prio = PE_PRIO_NORMAL;
     }
     X11_ev->fd = x_fd;
     GEventAPI->resume((pe_event*) X11_ev);
     GEventAPI->start((pe_event*) X11_ev, 0);

BUT I NEED A NEW TYPE OF WATCHER FOR MY INTERGALACTIC INFEROMETER
-----------------------------------------------------------------

   I'd prefer not to export the entire Event.h apparatus in favor of
minimizing interdependencies.  If you really, really need to create a new
type of watcher send your problem analysis to the mailing list!

Event loop statistics
*********************

NAME
====

   Event::Stats - Event loop statistics

SYNOPSIS
========

   XXX

DESCRIPTION
===========

   Instrument the Event module in order to gather statistics.

API
===

collect($yes)
     Determines whether statistics are collected.  Arithmetically adds $yes
     to the usage count.  Stats are enabled while the usage count is
     positive.

$round_sec = round_seconds($sec)
     Statistics are not collected in one second intervals.  This function
     converts a *desired* time interval into an *available* time interval.
     Units are in seconds.

$elapse = total_time($sec)
     Due to long-running callbacks, measurement intervals may take longer
     than expected.  This function returns the actual clock-time for a
     given measurement interval.

($rans, $dies, $elapse) = idle_time($sec)
($runs, $dies, $elapse) = $watcher->stats($sec)
     Return statistics for the last $sec seconds of operation.  Three
     numbers are returned: the number of times the callback has been
     invoked, the number of uncaught exceptions and the number of seconds
     spent within the callback.  Also see `NetServer::ProcessTop' in this
     node.

enforce_max_callback_time($yes)
     Useful for debugging. XXX

SUPPORT
=======

   Please direct your insights and complaints to the perl-loop@perl.org
mailing list!

COPYRIGHT
=========

   Copyright © 1999, 2000 Joshua Nathaniel Pritikin.  All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

reliable bidirectional RPC session layer
****************************************

NAME
====

   Event::tcpsession - reliable bidirectional RPC session layer

SYNOPSIS
========

     my $api = [
     	   { name  => 'my_rpc',
     	     req   => 'nN',                 # network short, network long
              reply => '',                   # no translator for reply
              code  =>
     	       sub { 'returned to caller' } # server-side code
            },
     	   ...
     	      ];

     Event->tcpsession(fd => $socket, api => $api);

DESCRIPTION
===========

   Automatic client-side recovery.

   Embedded NULLs are OK.

   What are the arbitrary limits?

SUPPORT
=======

   If you have insights or complaints then please subscribe to the mailing
list!  Send email to:

     majordomo@perl.org

   The body of your message should read:

     subscribe perl-loop

   This list is archived at

     http://www.xray.mpe.mpg.de/mailing-lists/perl-loop/

   Thanks!

COPYRIGHT
=========

   Copyright © 1999 Joshua Nathaniel Pritikin.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

A module that allows you to declare real exception classes in Perl
******************************************************************

NAME
====

   Exception::Class - A module that allows you to declare real exception
classes in Perl

SYNOPSIS
========

     use Exception::Class (
                     'MyException',
                     'AnotherException' => { isa => 'MyException' },
                     'YetAnotherException' => { isa => 'AnotherException',
                                                description => 'These exceptions are related to IPC' }                                  );

     eval { MyException->throw( error => 'I feel funny.'; };

     print $@->error, "\n";

     MyException->trace(1);
     eval { MyException->throw( error => 'I feel funnier.'; };

     print $@->error, "\n", $@->trace->as_string, "\n";
     print join ' ',  $@->euid, $@->egid, $@->uid, $@->gid, $@->pid, $@->time;

     # catch
     if ($@->isa('MyException'))
     {
        do_something();
     }
     elsif ($@->isa('FooException'))
     {
        go_foo_yourself();
     }
     else
     {
        $@->rethrow;
     }

DESCRIPTION
===========

   Exception::Class allows you to declare exceptions in your modules in a
manner similar to how exceptions are declared in Java.

   It features a simple interface allowing programmers to 'declare'
exception classes at compile time.  It also has a base exception class,
Exception::Class::Base, that can be used for classes stored in files (aka
modules ;) ) that are subclasses.

   It is designed to make structured exception handling simpler and better
by encouraging people to use hierarchies of exceptions in their
applications.

   NOTE: This module does not implement any try/catch syntax.  Please see
the `OTHER EXCEPTION MODULES (try' in this node for more information on
how to get this syntax.

DECLARING EXCEPTION CLASSES
===========================

   The 'use Exception::Class' syntax lets you automagically create the
relevant Exception::Class::Base subclasses.  You can also create
subclasses via the traditional means of external modules loaded via 'use'.
These two methods may be combined.

   The syntax for the magic declarations is as follows:

   'MANDATORY CLASS NAME' => \%optional_hashref

   The hashref may contain two options:

   * isa

     This is the class's parent class.  If this isn't provided then the
     class name is $Exception::Class::BASE_EXC_CLASS is assumed to be the
     parent (see below).

     This parameter lets you create arbitrarily deep class hierarchies.
     This can be any other Exception::Class::Base subclass in your
     declaration _or_ a subclass loaded from a module.

     To change the default exception class you will need to change the
     value of $Exception::Class::BASE_EXC_CLASS _before_ calling import.
     To do this simply do something like this:

     BEGIN { $Exception::Class::BASE_EXC_CLASS = 'SomeExceptionClass'; }

     If anyone can come up with a more elegant way to do this please let me
     know.

     CAVEAT: If you want to automagically subclass a Exception::Class::Base
     class loaded from a file, then you _must_ compile the class (via use
     or require or some other magic) _before_ you do 'use Exception::Class'
     or you'll get a compile time error.  This may change with the advent
     of Perl 5.6's CHECK blocks, which could allow even more crazy
     automagicalness (which may or may not be a good thing).

   * description

     Each exception class has a description method that returns a fixed
     string.  This should describe the exception _class_ (as opposed to the
     particular exception being thrown).  This is useful for debugging if
     you start catching exceptions you weren't expecting (particularly if
     someone forgot to document them) and you don't understand the error
     messages.

   The Exception::Class magic attempts to detect circular class
hierarchies and will die if it finds one.  It also detects missing links
in a chain so if you declare Bar to be a subclass of Foo and never declare
Foo then it will also die.  My tests indicate that this is functioning
properly but this functionality is still somewhat experimental.

Exception::Class::Base CLASS METHODS
====================================

   * do_trace($true_or_false)

     Each Exception::Class::Base subclass can be set individually to make a
     Devel::StackTrace object when an exception is thrown.  The default is
     to not make a trace.  Calling this method with a value changes this
     behavior.  It always returns the current value (after any change is
     applied).

   * throw( error => $error_message )

     This method creates a new Exception::Class::Base object with the given
     error message.  If no error message is given, $! is used.  It then
     die's with this object as its argument.

   * new( error => $error_message )

     Returns a new Exception::Class::Base object with the given error
     message.  If no error message is given, $! is used.

   * description

     Returns the description for the given Exception::Class::Base subclass.
     The Exception::Class::Base class's description is 'Generic exception'
     (this may change in the future).  This is also an object method.

Exception::Class::Base OBJECT METHODS
=====================================

   * rethrow

     Simply dies with the object as its sole argument.  It's just syntactic
     sugar.  This does not change any of the object's attribute values.
     However, it will cause caller to report the die as coming from within
     the Exception::Class::Base class rather than where rethrow was called.

   * error

     Returns the error message associated with the exception.

   * pid

     Returns the pid at the time the exception was thrown.

   * uid

     Returns the real user id at the time the exception was thrown.

   * gid

     Returns the real group id at the time the exception was thrown.

   * euid

     Returns the effective user id at the time the exception was thrown.

   * egid

     Returns the effective group id at the time the exception was thrown.

   * time

     Returns the time in seconds since the epoch at the time the exception
     was thrown.

   * package

     Returns the package from which the exception was thrown.

   * file

     Returns the file within which the exception was thrown.

   * line

     Returns the line where the exception was thrown.

   * trace

     Returns the trace object associated with the Exception::Class::Base if
     do_trace was true at the time it was created or undef.

   * as_string

     Returns a string form of the error message (something like what you'd
     expect from die).  If there is a trace available then it also returns
     this in string form (like Carp::confess).

OVERLOADING
===========

   The Exception::Class::Base object is overloaded so that stringification
produces a normal error message.  It just calls the as_string method
described above.  This means that you can just `print $@' after an eval
and not worry about whether or not its an actual object.  It also means an
application or module could do this:

     $SIG{__DIE__} = sub { Exception::Class::Base->throw( error => join '', @_ ); };

   and this would probably not break anything (unless someone was
expecting a different type of exception object from die).

USAGE RECOMMENDATION
====================

   If you're creating a complex system that throws lots of different types
of exceptions consider putting all the exception declarations in one
place.  For an app called Foo you might make a Foo::Exceptions module and
use that in all your code.  This module could just contain the code to
make Exception::Class do its automagic class creation.  This allows you to
more easily see what exceptions you have and makes it easier to keep track
of them all (as opposed to looking at the top of 10-20 different files).
It's also ever so slightly faster as the Class::Exception->import method
doesn't get called over and over again (though a given class is only ever
made once).

   You may want to create a real module to subclass Exception::Class::Base
as well, particularly if you want your exceptions to have more methods.
Read the `DECLARING EXCEPTION CLASSES' in this node for more details.

OTHER EXCEPTION MODULES (try/catch syntax)
==========================================

   If you are interested in adding try/catch/finally syntactic sugar to
your code then I recommend you check out Graham Barr's Error module, which
implements this syntax.  It also includes its own base exception class,
Error::Simple, but you should be able to use Exception::Class::Base along
with his try/catch routines transparently.  If you encounter any issues in
getting these two to work together, please let me know (and maybe Graham
as well) and I will fix this.

AUTHOR
======

   Dave Rolsky, <autarch@urth.org>

SEE ALSO
========

   Devel::StackTrace

Switch to ANSI C++ exceptions
*****************************

NAME
====

     Exception::Cxx - Switch to ANSI C++ exceptions

SYNOPSIS
========

     use Exception::Cxx;

DESCRIPTION
===========

   This module arranges for perl to use ANSI C++ exceptions (instead of
setjmp/longjmp).  The reason you might want this is for integration with
3rd party libraries that use C++ exceptions and cannot switch back to
longjmp.

BUGS
====

   sigsetjmp saves more state than catch {}.  In C++, sigprocmask &
`priocntl' are not saved or restored.

   C++ exceptions will not work with the CC perl compiler backend.  IMO,
this is a bug in the backend.

CONTACT
=======

   If you have suggestions or more hints files, please contact me at
bitset@mindspring.com.  Thanks!

AUTHOR
======

   Copyright © 1997-1999 Joshua Nathaniel Pritikin.  All rights reserved.

   This package is free software and is provided "as is" without express
or implied warranty.  It may be used, redistributed and/or modified under
the terms of the Perl Artistic License (see
http://www.perl.com/perl/misc/Artistic.html)

Expect for Perl, Version 1.11
*****************************

NAME
====

     Expect.pm - Expect for Perl, Version 1.11

SYNOPSIS 	 	use Expect;
=======================

   Expect.pm is built to either spawn a process or take an existing
filehandle and interact with it such that normally interactive tasks can
be done without operator assistance. This concept makes more sense if you
are already familiar with the versatile Tcl version of Expect.  The
(current) public functions that make up Expect.pm are:

     Expect->exp_init(\*FILEHANDLE)
     Expect->spawn($command, @parameters)
     Expect::interconnect(@objects_to_be_read_from)
     Expect::test_handles($timeout, @objects_to_test)
     Expect::version($version_requested | undef);
     $object->clear_accum()
     $object->debug($debug_level)
     $object->exp_internal(0 | 1 | undef)
     $object->exp_stty(@stty_modes)# See the IO::Stty docs
     $object->expect($timeout, @match_patterns)
     $object->exp_before();
     $object->exp_match();
             $object->exp_after();
     $object->exp_matchlist();
             $object->exp_match_number();
             $object->exp_error();
             $object->exp_command();
             $object->exp_exitstatus();
             $object->exp_pty_handle();
             $object->restart_timeout_upon_receive(0 | 1);
     $object->interact($other_object, $escape_sequence)
     $object->log_group(0 | 1 | undef)
     $object->log_user(0 | 1 | undef)
     $object->log_file("filename" | $filehandle | undef)
     $object->manual_stty(0 | 1 | undef)
     $object->match_max($max_buffersize or undef)
     $object->exp_pid();
     $object->send_slow($delay, @strings_to_send)
     $object->set_group(@listen_group_objects | undef)
     $object->set_seq($sequence,\&function,\@parameters);

     There are several configurable package variables that affect the behavior of Expect. They are:

     $Expect::Debug;
     $Expect::Exp_Internal;
     $Expect::Log_Group;
     $Expect::Log_Stdout;
     $Expect::Manual_Stty;
     $Expect::Multiline_Matching;

DESCRIPTION
===========

   The Expect module is a successor of Comm.pl and a descendent of
Chat.pl. It more closely ressembles the Tcl Expect language than its
predecessors. It does not contain any of the networking code found in
Comm.pl. I suspect this would be obsolete anyway given the advent of
IO::Socket and external tools such as netcat.

   Expect.pm is an attempt to have more of a switch() & case: feeling to
make decision processing more fluid.  Three separate types of debugging
have been implemented to make code production easier.

   It is now possible to interconnect multiple file handles (and
processes) much like Tcl's expect. An attempt was made to enable all the
features of Tcl's expect without forcing Tcl on the victim programmer :-) .

USAGE
=====

   * Initializes $new_handle_object for use with other Expect functions.
     It must be passed a *_reference_* to FILEHANDLE if you want it to
     work properly.  IO::File objects are preferable. Returns a reference
     to the newly created object.

   * Expect->spawn($command, @parameters) Forks and execs $command.
     returns a reference to the newly created process object. Returns
     undef if the fork was unsuccessful or the object could not be created.

   * Expect::interconnect(@objects); Read from @objects and print to their
     @listen_groups until an escape sequence is matched from one of
     @objects and the associated function returns 0 or undef.  The special
     escape sequence 'EOF' is matched when an object's handle returns an
     end of file. Note that it is not necessary to include objects that
     only accept data in @objects since the escape sequence is _read_ from
     an object.  Further note that the listen_group for a write-only
     object is always empty.  Why would you want to have objects listening
     to STDOUT (for example)?  By default every member of @objects _as
     well as every member of its listen group_ will be set to 'raw -echo'
     for the duration of interconnection.  Setting $object->manual_stty()
     will stop this behavior per object.  The original tty settings will
     be restored as interconnect exits.

   * Expect::test_handles(@objects) Given a set of objects determines
     which objects' handles have data ready to be read. *Returns an array*
     who's members are positions in @objects that have ready handles.
     Returns undef if there are no such handles ready.

   * Expect::version($version_requested or undef); Returns current version
     of Expect. As of .99 earlier versions are not supported. Too many
     things were changed to make versioning possible.

   * $object->clear_accum() Clear the contents of the accumulator for
     $object. This gets rid of any residual contents of a handle after
     expect() or send_slow() such that the next expect() call will only
     see new data from $object. The contents of the accumulator are
     returned.

   * $object->debug(0 | 1 | 2 | 3 | undef) Sets debug level for $object. 1
     refers to general debugging information, 2 refers to verbose
     debugging and 0 refers to no debugging. If you call debug() with no
     parameters it will return the current debugging level.  When the
     object is created the debugging level will match that $Expect::Debug,
     normally 0.

     The '3' setting is new with 1.05, and adds the additional
     functionality of having the _full_ accumulated buffer printed every
     time data is read from an Expect object. This was implemented by
     request. I recommend against using this unless you think you need it
     as it can create quite a quantity of output under some circumstances..

   * $object->exp_internal(1 | 0) Sets/unsets 'exp_internal' debugging.
     This is similar in nature to its Tcl counterpart. It is extremely
     valuable when debugging expect() sequences.  When the object is
     created the exp_internal setting will match the value of
     $Expect::Exp_Internal, normally 0. Returns the current setting if
     called without parameters. It is highly recommended that you make use
     of the debugging features lest you have angry code.

   * $object->expect_stty($mode) Sets the tty mode for $object's
     associated terminal to $mode. Typical values are 'sane', 'raw', and
     'raw -echo'. This should be used in conjunction with manual_stty().
     See the docs for IO::Stty to see what values make sense here.

   * $object->expect($timeout, @match_patterns) or, more like Tcl/Expect,

          expect($timeout,
                 '-i', [ $obj1, $obj2, ... ],
                       [ $re_pattern, sub { ...; exp_continue; }, @subparms, ],
                       [ 'eof', sub { ... } ],
                       [ 'timeout', sub { ... }, \$subparm1 ],
                 '-i', [ $objn, ...],
                       '-ex', $exact_pattern, sub { ... },
                       $exact_pattern, sub { ...; exp_continue_timeout; },
                       '-re', $re_pattern, sub { ... },
                 '-i', \@object_list, @pattern_list,
                 ...);

     *Simple interface:*

     Given $timeout in seconds Expect will wait for $object's handle to
     produce one of the match_patterns. Due to o/s limitations $timeout
     should be a round number. If $timeout is 0 Expect will check one time
     to see if $object's handle contains any of the match_patterns. If
     $timeout is undef Expect will wait forever for a pattern to match.

     If called in a scalar context, expect() will return the position of
     the matched pattern within $match_patterns, or undef if no pattern was
     matched. This is a position starting from 1, so if you want to know
     which of an array of @matched_patterns matched you should subtract one
     from the return value.

     If called in an array context expect() will return
     ($matched_pattern_position, $error, $successfully_matching_string,
     $before_match, and $after_match).

     $matched_pattern_position will contain the value that would have been
     returned if expect() had been called in a scalar context. $error is
     the error that occurred that caused expect() to return. $error will
     contain a number followed by a string equivalent expressing the nature
     of the error. Possible values are undef, indicating no error,
     '1:TIMEOUT' indicating that $timeout seconds had elapsed without a
     match, '2:EOF' indicating an eof was read from $object, '3: spawn
     id($fileno) died' indicating that the process exited before matching
     and '4:$!' indicating whatever error was set in $ERRNO during the last
     read on $object's handle. All handles indicated by set_group plus
     STDOUT will have all data to come out of $object printed to them
     during expect() if log_group and log_stdout are set.

     Changed from older versions is the regular expression handling. By
     default now all strings passed to expect() are treated as literals. To
     match a regular expression pass '-re' as a parameter in front of the
     pattern you want to match as a regexp.

     Example:

          $object->expect(15, 'match me exactly','-re','match\s+me\s+exactly');

     This change makes it possible to match literals and regular
     expressions in the same expect() call.

     Also new is multiline matching. ^ will now match the beginning of
     lines. Unfortunately, because perl doesn't use $/ in determining where
     lines break using $ to find the end of a line frequently doesn't
     work. This is because your terminal is returning "\r\n" at the end of
     every line. One way to check for a pattern at the end of a line would
     be to use \r?$ instead of $.

     Example: Spawning telnet to a host, you might look for the escape
     character.  telnet would return to you "\r\nEscape character is
     '^]'.\r\n". To find this you might use $match='^Escape char.*\.\r?$';

          $telnet->expect(10,'-re',$match);

     *New more TCL-like interface (added by RGiersig@cpan.org):*

     It's now possible to expect on more than one connection at a time by
     specifying '-i' (see the TCL expect manpage) and a ref to an array
     containing Expect objects.

     Furthermore, patterns can now be specified as array refs containing
     [$regexp, sub { ...}, @optional_subprams] . When the pattern matches,
     the subroutine is called with parameters ($matched_expect_obj,
     @optional_subparms). The subroutine can return the symbol
     `exp_continue' to continue the expect matching with timeout starting
     anew or return the symbol `exp_continue_timeout' for continuing expect
     without resetting the timeout count.

     `expect' is now exported by default.

     [I did my best to assure backward compatibility with the old-style
     call interface, but hey, I'm JAPH... - Roland]

   * $object->exp_before(); exp_before() returns the 'before' part of the
     last expect() call. If the last expect() call didn't match anything,
     exp_before() will return the entire output of the object accumulated
     before the expect() call finished.

   * $object->exp_after();   exp_after() returns the 'after' part of the
     last expect() call. If the last expect() call didn't match anything,
     exp_after() will return undef().  exp_match() returns the string
     matched by the last expect() call, undef if no string was matched.

   * $object->exp_match_number(); exp_match_number() returns the number of
     the pattern matched by the last expect() call. Keep in mind that the
     first pattern in a list of patterns is 1, not 0. Returns undef if no
     pattern was matched.

   * $object->exp_matchlist(); exp_matchlist() returns a list of matched
     substrings from the brackets () inside the regexp that last matched.
     ($object->exp_matchlist)[0] thus corresponds to $1,
     ($object->exp_matchlist)[1] to $2, etc.

   * $object->exp_error(); exp_error() returns the error generated by the
     last expect() call if no pattern was matched. It is typically useful
     to examine the value returned by exp_before() to find out what the
     output of the object was in determining why it didn't match any of
     the patterns.

   * $object->exp_command(); exp_command() returns the string that was
     used to spawn the command. Helpful for debugging and for reused
     patternmatch subroutines.

   * $object->exp_exitstatus() Returns the exit status of $object (if it
     already exited).

   * $object->exp_pty_handle() Returns a string representation of the
     attached pty, for example: `spawn id(5)' (pty has fileno 5), `handle
     id(7)' (pty was initialized from fileno 7) or `STDIN'. Useful for
     debugging.

   * $object->restart_timeout_upon_receive(0 | 1) If this is set to 1, the
     expect timeout is retriggered whenever something is received from the
     spawned command.  This allows to perform some aliveness testing and
     still expect for patterns.

          $exp->restart_timeout_upon_receive(1);
          $exp->expect($timeout,
                       [ timeout => \&report_timeout ],
          		 [ qr/pattern/ => \&handle_pattern],
                      );

     Now the timeout isn't triggered if the command produces any kind of
     output, i.e. is still alive, but you can act upon patterns in the
     output.

   * $object->interact( `\*FILEHANDLE, $escape_sequence') interact() is
     essentially a macro for calling interconnect() for connecting 2
     processes together. \*FILEHANDLE defaults to \*STDIN and
     $escape_sequence defaults to undef. Interaction ceases when
     $escape_sequence is read from *FILEHANDLE*, not $object. $object's
     listen group will consist solely of \*FILEHANDLE for the duration of
     the interaction.  \*FILEHANDLE will not be echoed on STDOUT.

   * $object->log_group(0 | 1 | undef) Set/unset logging of $object to its
     'listen group'. If set all objects in the listen group will have
     output from $object printed to them during $object->expect(),
     $object->send_slow(), and `Expect::interconnect($object , ...)'.
     Default value is on. During creation of $object the setting will
     match the value of $Expect::Log_Group, normally 1.

   * $object->log_user(0 | 1 | undef) Set/unset logging of object's handle
     to STDOUT. This corresponds to Tcl's log_user variable. Returns
     current setting if called without parameters.  Default setting is off
     for initialized handles.  When a process object is created (not a
     filehandle initialized with exp_init) the log_stdout setting will
     match the value of $Expect::Log_Stdout variable, normally 1.  If/when
     you initialize STDIN it is usually associated with a tty which will
     by default echo to STDOUT anyway, so be careful or you will have
     multiple echoes.

   * $object->log_file("filename" | $filehandle | undef)
     Log session to a file.  All characters send to or received from the
     spawned process are written to the file.  Normally appends to the
     logfile, but you can pass an additional mode of "w" to truncate the
     file upon open():
          $object->log_file("filename", "w");

     Returns the logfilehandle.

     If called with an undef value, stops logging and closes logfile:

          $object->log_file(undef);

     If called without argument, returns the logfilehandle:

          $fh = $object->log_file();

   * $object->set_seq($sequence, \&function, \@function_parameters) During
     Expect->interconnect() if $sequence is read from $object &function
     will be executed with parameters @function_parameters. It is *_highly
     recommended_* that the escape sequence be a single character since the
     likelihood is great that the sequence will be broken into to separate
     reads from the $object's handle, making it impossible to strip
     $sequence from getting printed to $object's listen group. \&function
     should be something like 'main::control_w_function' and
     @function_parameters should be an array defined by the caller, passed
     by reference to set_seq().  Your function should return a non-zero
     value if execution of interconnect() is to resume after the function
     returns, zero or undefined if interconnect() should return after your
     function returns.  The special sequence 'EOF' matches the end of file
     being reached by $object.  See interconnect() for details.

   * $object->set_group(@listener_objects) @listener_objects is the list
     of objects that should have their handles printed to by $object when
     Expect::interconnect, $object->expect() or $object->send_slow() are
     called. Calling w/out parameters will return the current list of the
     listener objects.

   * $object->manual_stty(0 | 1 | undef) Sets/unsets whether or not Expect
     should make reasonable guesses as to when and how to set tty
     parameters for $object. Will match $Expect::Manual_Stty value
     (normally 0) when $object is created. If called without parameters
     manual_stty() will return the current manual_stty setting.

   * $object->match_max($maximum_buffer_length | undef) Set the maximum
     accumulator size for object. This is useful if you think that the
     accumulator will grow out of hand during expect() calls. Since the
     buffer will be matched by every match_pattern it may get slow if the
     buffer gets too large. Returns current value if called without
     parameters.  Not defined by default.

   * $object->exp_pid() Return pid of $object, if one exists. Initialized
     filehandles will not have pids (of course).

   * $object->send_slow($delay, @strings); print each character from each
     string of @strings one at a time with $delay seconds before each
     character. This is handy for devices such as modems that can be
     annoying if you send them data too fast. After each character $object
     will be checked to determine whether or not it has any new data ready
     and if so update the accumulator for future expect() calls and print
     the output to STDOUT and @listen_group if log_stdout and log_group are
     appropriately set.

Configurable Package Variables:
-------------------------------

     $Expect::Debug;

     Defaults to 0. Newly created objects have a $object->debug() value
     of $Expect::Debug. See $object->debug();

     $Expect::Exp_Internal;

     Defaults to 0. Newly created objects have a $object->exp_internal()
     value of $Expect::Exp_Internal. See $object->exp_internal().

     $Expect::Log_Group;

     Defaults to 1. Newly created objects have a $object->log_group()
     value of $Expect::Log_Group. See $object->log_group().

     $Expect::Log_Stdout;

     Defaults to 1 for spawned commands, 0 for file handles
     attached with exp_init(). Newly created objects have a
     $object->log_stdout() value of $Expect::Log_Stdout. See
     $object->log_stdout().

     $Expect::Manual_Stty;

     Defaults to 0. Newly created objects have a $object->manual_stty()
     value of $Expect::Manual_Stty. See $object->manual_stty().

     $Expect::Multiline_Matching;

     Defaults to 1. Affects whether or not expect() uses the /m flag for
     doing regular expression matching. If set to 1 /m is used.
     This makes a difference when you are trying to match ^ and $. If
     you have this on you can match lines in the middle of a page of output
     using ^ and $ instead of it matching the beginning and end of the entire
     expression. I think this is handy.

CONTRIBUTIONS
=============

   Lee Eakin <leakin@japh.itg.ti.com> has ported the kibitz script from
Tcl/Expect to Perl/Expect.  You can find it in the examples/ subdir.
Thanks Lee!

SEE ALSO
========

   See Expect_FAQ,

HOMEPAGE
========

   http://sourceforge.net/projects/expectperl/

AUTHORS
=======

   (c) 1997 Austin Schutz <ASchutz@users.sourceforge.net>

   expect() interface & functionality enhancements (c) 1999 Roland Giersig.

   This module now is maintained by Roland Giersig <RGiersig@cpan.org>

LICENSE
=======

   This module can be used under the same terms as Perl.

Frequently Asked Questions
**************************

NAME
====

   Expect.pm - Frequently Asked Questions

SYNOPSIS
========

   This is a growing collection of things that might help.  Please send
you questions that are not answered here to RGiersig@cpan.org

DESCRIPTION
===========

Can I use this module with ActivePerl on Windows?
-------------------------------------------------

   I don't know.  Probably not.  There is no native support for ptys
available under Windows.  On the other hand, Cygwin
(http://sourceware.cygnus.com) promises to provide POSIX ptys for NT, so
it should be possible to run Expect.pm under Cygwin.

   The Tcl/Expect homepage at http://expect.nist.gov gives two links to
porting projects that might be of interest (one being DejaGnu on Cygwin).

How can I find out what Expect is doing?
----------------------------------------

   If you set

     $Expect::Exp_Internal = 1;

   Expect will tell you very verbosely what it is receiving and sending,
what matching it is trying and what it found.  You can do this on a
per-command base with

     $exp->exp_internal(1);

   You can also set

     $Expect::Debug = 1;

   which gives you even more output.

I am seeing the output of the command I spawned.  Can I turn that off?
----------------------------------------------------------------------

   Yes, just set

     $Expect::Log_Stdout = 0;

   to globally disable it or

     $exp->log_stdout(0);

   for just that command.  'log_user' is provided as an alias so
Tcl/Expect user get a DWIM experience... :-)

I want to log the whole session to a file.
------------------------------------------

   Use

     $exp->log_file("filename");

   or

     $exp->log_file($filehandle);

   to start logging.  Note that the log is appended by default, but you can
specify an optional mode "w" to truncate the logfile:

     $exp->log_file("filename", "w");

   To stop logging, just call it with a false argument:

     $exp->log_file(undef);

How can I turn off multi-line matching for my regexps?
------------------------------------------------------

   To globally unset multi-line matching for all regexps:

     $Expect::Multiline_Matching = 0;

   You can do that on a per-regexp basis by stating `(?-m)' inside the
regexp (you need perl5.00503 or later for that).

How can I expect on multiple spawned commands?
----------------------------------------------

   You can use the -i parameter to specify a single object or a list of
Expect objects.  All following patterns will be evaluated against that
list.

   You can specify -i multiple times to create groups of objects and
patterns to match against within the same expect statement.

   This works just like in Tcl/Expect.

   See the source example below.

I seem to have problems with ptys!
----------------------------------

   [You're on HP-UX, right?]  Well, pty handling is really a black magic,
as it is extremely system dependend.  I'm thinking about stealing the pty
stuff from Tcl/Expect (Hi, Don!), as that code looks much more mature than
what gets done in Expect and/or IO::[TP]ty.  Please be patient, this may
take a while...

Source Examples
===============

How to automate login
---------------------

     $obj->expect($timeout,
     	       [
     		qr'login: $',
     		sub {
     		  my $fh = shift;
     		  print $fh "$username\r"; exp_continue;
     		}
     	       ],
     	       [
     		'Password: $',
     		sub {
     		  my $fh = shift;
     		  print $fh "$password\r"; exp_continue;
     		}
     	       ],
     	       [
     		timeout =>
     		sub {
     		  die "No login.\n";
     		}
     	       ],
     	       '-re', qr'[#>:] $', #' wait for shell prompt, then exit expect
     	      );

How to expect on multiple spawned commands
------------------------------------------

     foreach my $cmd (@list_of_commands) {
       push @commands, new Expect $cmd;
     }

     expect($timeout,
     	 '-i', \@commands,
     	 [
     	  qr"pattern",		# find this pattern in output of all commands
     	  sub {
     	    my $obj = shift;	# object that matched
     	    print $obj "something\r";
     	    exp_continue;	# we don't want to terminate the expect call
     	  }
     	 ],
     	 '-i', $some_other_command,
     	 [
     	  "some other pattern",
     	  sub {
     	    my ($obj, $parmref) = @_;
     	    # ...

     # now we exit the expect command
     	  },
     	  \$parm
     	 ],
     	);

Perl Expect interface
*********************

NAME
====

   Expect.pm (1.08) - Perl Expect interface

SYNOPSIS
========

     use Expect.pm

NOTE
====

   This document is obsolete and left in for hysterical raisins.
Expect.pod now is the officially maintained document.  Expect_FAQ.pod
should be of value too.

DESCRIPTION
===========

   The Expect module is a successor of Comm.pl and a descendent of
Chat.pl. It more closely ressembles the Tcl Expect language than its
predecessors. It does not contain any of the networking code found in
Comm.pl. I suspect this would be obsolete anyway given the advent of
IO::Socket and external tools such as netcat.

   Expect.pm is an attempt to have more of a switch() & case: feel to make
decision processing more fluid. three separate types of debugging have
been implemented to make code production easier.

   It is now possible to interconnect multiple file handles (and
processes) much like Tcl's expect. An attempt was made to enable all the
features of Tcl's expect without forcing Tcl on the victim programmer :-) .

CAVEATS
=======

   Expect.pm was designed to be generally portable across Unixes.

   1. The operating system must include  ptys. This excludes non-Unix
operating systems as far as I know.

   2. The operating system must be POSIX compliant and include the Perl 5
POSIX.pm module. The Fcntl.pm module is also used. My understanding is
that there is no POSIX for Microsoft stuff. Bummer.

   3. Perl 5.00401+ must be used. This module has been tested with 5.001
and 5.003 under Linux and SunOS 5 and worked fine, but with the new IO::Pty
support 5.00401 is required. Expect itself doesn't require this in case at
some point IO::Pty should become backwards compatible with earlier versions
of Perl. Please read the FAQ if you have trouble before going any further.

   The old perl 4 Comm.pl was only compatible with SunOS 4 and 5 due to
heavy use of ioctl() calls. It is the author's wish that this lack of
portability be fixed as much as possible.

CAVEATS PART 2
==============

   Tty settings are a major pain to keep track of. If you find unexpected
behavior such as double-echoing or a frozen session doublecheck the
documentation for default settings. When in doubt handle them yourself
using the exp_stty() and manual_stty() functions. As of .98 you shouldn't
have to worry about stty settings getting fouled unless you use
interconnect or intentionally change them (like doing -echo to get a
password).

   If you foul your terminal's tty settings kill any hung processes and
enter stty sane at a shell prompt. This should make your terminal
manageable again.

HOMEPAGE
========

   http://sourceforge.net/projects/expectperl/

BUGS
====

   This module has not been tested on a great variety of platforms and
doesn't seem to have a wide spread yet.  You may want to check the modules
homepage at http://sourceforge.net/projects/expectperl/ and submit any
questions or bugreports there.

AUTHORS
=======

   Austin Schutz <tex@habit.com>: (retired)

   Partner/Mad Scientist, The Habit Internet Cafe.  Feel free to send any
compliments/gripes my way.  And now my shameless commercial plug: Check
out Portland's First and Finest 'Net cafe at http://*www.habit.com*

   Roland Giersig <RGiersig@users.sourceforge.net>:

   I have added the multi-match functionality and also now taken over
maintainance and further development of Expect.pm. There will be a
complete clean rewrite in the near future (cannot promise any date) that
may break some backward-compatibility for cleaner design.  For example, I
would like to break it up somewhat, probably move the interconnect-stuff
to a separate module to slim down the core functionality.  I still want to
keep it as close to Tcl/Expect as possible to make switching real easy.

   =head1 CONTRIBUTORS

   There are still a few lines of code dating back to the inspirational
Comm.pl and Chat.pl modules without which this would not have been
possible.  Kudos to Eric Arnold <Eric.Arnold@Sun.com> and Randal 'Nuke
your NT box with one line of perl code' Schwartz<merlyn@stonehenge.com>
for making these available to the perl public.

   As of .98 I think all the old code is toast. No way could this have
been done without it though. Special thanks to Graham Barr for helping
make sense of the IO::Handle stuff as well as providing the highly
recommended IO::Tty module.

Implements default import method for modules
********************************************

NAME
====

   Exporter - Implements default import method for modules

SYNOPSIS
========

   In module ModuleName.pm:

     package ModuleName;
     require Exporter;
     @ISA = qw(Exporter);

     @EXPORT = qw(...);            # symbols to export by default
     @EXPORT_OK = qw(...);         # symbols to export on request
     %EXPORT_TAGS = tag => [...];  # define names for sets of symbols

   In other files which wish to use ModuleName:

     use ModuleName;               # import default symbols into my package

     use ModuleName qw(...);       # import listed symbols into my package

     use ModuleName ();            # do not import any symbols

DESCRIPTION
===========

   The Exporter module implements a default import method which many
modules choose to inherit rather than implement their own.

   Perl automatically calls the import method when processing a use
statement for a module. Modules and use are documented in Perlfunc (perl.info),
and Perlmod (perl.info). Understanding
the concept of modules and how the use statement operates is important to
understanding the Exporter.

How to Export
-------------

   The arrays `@EXPORT' and `@EXPORT_OK' in a module hold lists of symbols
that are going to be exported into the users name space by default, or
which they can request to be exported, respectively.  The symbols can
represent functions, scalars, arrays, hashes, or typeglobs.  The symbols
must be given by full name with the exception that the ampersand in front
of a function is optional, e.g.

     @EXPORT    = qw(afunc $scalar @array);   # afunc is a function
     @EXPORT_OK = qw(&bfunc %hash *typeglob); # explicit prefix on &bfunc

Selecting What To Export
------------------------

   Do not export method names!

   Do not export anything else by default without a good reason!

   Exports pollute the namespace of the module user.  If you must export
try to use @EXPORT_OK in preference to @EXPORT and avoid short or common
symbol names to reduce the risk of name clashes.

   Generally anything not exported is still accessible from outside the
module using the ModuleName::item_name (or $blessed_ref->method) syntax.
By convention you can use a leading underscore on names to informally
indicate that they are 'internal' and not for public use.

   (It is actually possible to get private functions by saying:

     my $subref = sub { ... };
     &$subref;

   But there's no way to call that directly as a method, since a method
must have a name in the symbol table.)

   As a general rule, if the module is trying to be object oriented then
export nothing. If it's just a collection of functions then  @EXPORT_OK
anything but use @EXPORT with caution.

   Other module design guidelines can be found in Perlmod (perl.info).

Specialised Import Lists
------------------------

   If the first entry in an import list begins with !, : or / then the
list is treated as a series of specifications which either add to or
delete from the list of names to import. They are processed left to right.
Specifications are in the form:

     [!]name         This name only
     [!]:DEFAULT     All names in @EXPORT
     [!]:tag         All names in $EXPORT_TAGS{tag} anonymous list
     [!]/pattern/    All names in @EXPORT and @EXPORT_OK which match

   A leading ! indicates that matching names should be deleted from the
list of names to import.  If the first specification is a deletion it is
treated as though preceded by :DEFAULT. If you just want to import extra
names in addition to the default set you will still need to include
:DEFAULT explicitly.

   e.g., Module.pm defines:

     @EXPORT      = qw(A1 A2 A3 A4 A5);
     @EXPORT_OK   = qw(B1 B2 B3 B4 B5);
     %EXPORT_TAGS = (T1 => [qw(A1 A2 B1 B2)], T2 => [qw(A1 A2 B3 B4)]);

     Note that you cannot use tags in @EXPORT or @EXPORT_OK.
     Names in EXPORT_TAGS must also appear in @EXPORT or @EXPORT_OK.

   An application using Module can say something like:

     use Module qw(:DEFAULT :T2 !B3 A3);

   Other examples include:

     use Socket qw(!/^[AP]F_/ !SOMAXCONN !SOL_SOCKET);
     use POSIX  qw(:errno_h :termios_h !TCSADRAIN !/^EXIT/);

   Remember that most patterns (using //) will need to be anchored with a
leading ^, e.g., `/^EXIT/' rather than `/EXIT/'.

   You can say `BEGIN { $Exporter::Verbose=1 }' to see how the
specifications are being processed and what is actually being imported
into modules.

Exporting without using Export's import method
----------------------------------------------

   Exporter has a special method, 'export_to_level' which is used in
situations where you can't directly call Export's import method. The
export_to_level method looks like:

   MyPackage->export_to_level($where_to_export, $package, @what_to_export);

   where $where_to_export is an integer telling how far up the calling
stack to export your symbols, and @what_to_export is an array telling what
symbols *to* export (usually this is @_).  The $package argument is
currently unused.

   For example, suppose that you have a module, A, which already has an
import function:

   package A;

   @ISA = qw(Exporter);  @EXPORT_OK = qw ($b);

   sub import {     $A::b = 1;     # not a very useful import method }

   and you want to Export symbol $A::b back to the module that called
package A. Since Exporter relies on the import method to work, via
inheritance, as it stands Exporter::import() will never get called.
Instead, say the following:

   package A;  @ISA = qw(Exporter);  @EXPORT_OK = qw ($b);

   sub import {     $A::b = 1;     A->export_to_level(1, @_); }

   This will export the symbols one level 'above' the current package -
ie: to the program or module that used package A.

   Note: Be careful not to modify '@_' at all before you call
export_to_level - or people using your package will get very unexplained
results!

Module Version Checking
-----------------------

   The Exporter module will convert an attempt to import a number from a
module into a call to $module_name->require_version($value). This can be
used to validate that the version of the module being used is greater than
or equal to the required version.

   The Exporter module supplies a default require_version method which
checks the value of $VERSION in the exporting module.

   Since the default require_version method treats the $VERSION number as
a simple numeric value it will regard version 1.10 as lower than 1.9. For
this reason it is strongly recommended that you use numbers with at least
two decimal places, e.g., 1.09.

Managing Unknown Symbols
------------------------

   In some situations you may want to prevent certain symbols from being
exported. Typically this applies to extensions which have functions or
constants that may not exist on some systems.

   The names of any symbols that cannot be exported should be listed in
the `@EXPORT_FAIL' array.

   If a module attempts to import any of these symbols the Exporter will
give the module an opportunity to handle the situation before generating
an error. The Exporter will call an export_fail method with a list of the
failed symbols:

     @failed_symbols = $module_name->export_fail(@failed_symbols);

   If the export_fail method returns an empty list then no error is
recorded and all the requested symbols are exported. If the returned list
is not empty then an error is generated for each symbol and the export
fails. The Exporter provides a default export_fail method which simply
returns the list unchanged.

   Uses for the export_fail method include giving better error messages
for some symbols and performing lazy architectural checks (put more
symbols into @EXPORT_FAIL by default and then take them out if someone
actually tries to use them and an expensive check shows that they are
usable on that platform).

Tag Handling Utility Functions
------------------------------

   Since the symbols listed within %EXPORT_TAGS must also appear in either
@EXPORT or @EXPORT_OK, two utility functions are provided which allow you
to easily add tagged sets of symbols to @EXPORT or @EXPORT_OK:

     %EXPORT_TAGS = (foo => [qw(aa bb cc)], bar => [qw(aa cc dd)]);

     Exporter::export_tags('foo');     # add aa, bb and cc to @EXPORT
     Exporter::export_ok_tags('bar');  # add aa, cc and dd to @EXPORT_OK

   Any names which are not tags are added to @EXPORT or @EXPORT_OK
unchanged but will trigger a warning (with -w) to avoid misspelt tags
names being silently added to @EXPORT or @EXPORT_OK. Future versions may
make this a fatal error.

Exporter guts
*************

NAME
====

   Exporter::Heavy - Exporter guts

SYNOPIS
=======

   (internal use only)

DESCRIPTION
===========

   No user-serviceable parts inside.

utilities to replace common UNIX commands in Makefiles etc.
***********************************************************

NAME
====

   ExtUtils::Command - utilities to replace common UNIX commands in
Makefiles etc.

SYNOPSIS
========

     perl -MExtUtils::Command -e cat files... > destination
     perl -MExtUtils::Command -e mv source... destination
     perl -MExtUtils::Command -e cp source... destination
     perl -MExtUtils::Command -e touch files...
     perl -MExtUtils::Command -e rm_f file...
     perl -MExtUtils::Command -e rm_rf directories...
     perl -MExtUtils::Command -e mkpath directories...
     perl -MExtUtils::Command -e eqtime source destination
     perl -MExtUtils::Command -e chmod mode files...
     perl -MExtUtils::Command -e test_f file

DESCRIPTION
===========

   The module is used in the Win32 port to replace common UNIX commands.
Most commands are wrappers on generic modules File::Path and
File::Basename.

cat
     Concatenates all files mentioned on command line to STDOUT.

eqtime src dst
     Sets modified time of dst to that of src

rm_f files....
     Removes directories - recursively (even if readonly)

rm_f files....
     Removes files (even if readonly)

touch files ...
     Makes files exist, with current timestamp

mv source... destination
     Moves source to destination.  Multiple sources are allowed if
     destination is an existing directory.

cp source... destination
     Copies source to destination.  Multiple sources are allowed if
     destination is an existing directory.

chmod mode files...
     Sets UNIX like permissions 'mode' on all the files.

mkpath directory...
     Creates directory, including any parent directories.

test_f file
     Tests if a file exists

BUGS
====

   Should probably be Auto/Self loaded.

SEE ALSO
========

   ExtUtils::MakeMaker, ExtUtils::MM_Unix, ExtUtils::MM_Win32

AUTHOR
======

   Nick Ing-Simmons <`nick@ni-s.u-net.com'>.

Methods for generating Perl extension files
*******************************************

NAME
====

   ExtUtils::DynaGlue - Methods for generating Perl extension files

SYNOPSIS
========

     use ExtUtils::DynaGlue ();

DESCRIPTION
===========

AUTHOR
======

   Doug MacEachern <dougm@osf.org> based on h2xs written by Larry Wall and
others

SEE ALSO
========

   perl(1).

Utilities for embedding Perl in C/C++ applications
**************************************************

NAME
====

   ExtUtils::Embed - Utilities for embedding Perl in C/C++ applications

SYNOPSIS
========

     perl -MExtUtils::Embed -e xsinit
     perl -MExtUtils::Embed -e ldopts

DESCRIPTION
===========

   ExtUtils::Embed provides utility functions for embedding a Perl
interpreter and extensions in your C/C++ applications.  Typically, an
application *Makefile* will invoke ExtUtils::Embed functions while
building your application.

@EXPORT
=======

   ExtUtils::Embed exports the following functions:

   xsinit(), ldopts(), ccopts(), perl_inc(), ccflags(), ccdlflags(),
xsi_header(), xsi_protos(), xsi_body()

FUNCTIONS
=========

xsinit()
     Generate C/C++ code for the XS initializer function.

     When invoked as ``perl -MExtUtils::Embed -e xsinit --`' the following
     options are recognized:

     -o <output filename> (Defaults to *perlxsi.c*)

     *-o STDOUT* will print to STDOUT.

     *-std* (Write code for extensions that are linked with the current
     Perl.)

     Any additional arguments are expected to be names of modules to
     generate code for.

     When invoked with parameters the following are accepted and optional:

     `xsinit($filename,$std,[@modules])'

     Where,

     $filename is equivalent to the -o option.

     *$std* is boolean, equivalent to the *-std* option.

     *[@modules]* is an array ref, same as additional arguments mentioned
     above.

Examples
          perl -MExtUtils::Embed -e xsinit -- -o xsinit.c Socket

     This will generate code with an *xs_init* function that glues the
     perl *Socket::bootstrap* function to the C *boot_Socket* function and
     writes it to a file named "xsinit.c".

     Note that DynaLoader is a special case where it must call
     *boot_DynaLoader* directly.

          perl -MExtUtils::Embed -e xsinit

     This will generate code for linking with DynaLoader and each static
     extension found in *$Config{static_ext}*.  The code is written to the
     default file name *perlxsi.c*.

          perl -MExtUtils::Embed -e xsinit -- -o xsinit.c -std DBI DBD::Oracle

     Here, code is written for all the currently linked extensions along
     with code for DBI and *DBD::Oracle*.

     If you have a working DynaLoader then there is rarely any need to
     statically link in any other extensions.

ldopts()
     Output arguments for linking the Perl library and extensions to your
     application.

     When invoked as ``perl -MExtUtils::Embed -e ldopts --`' the following
     options are recognized:

     *-std*

     Output arguments for linking the Perl library and any extensions
     linked with the current Perl.

     -I <path1:path2>

     Search path for ModuleName.a archives.  Default path is *@INC*.
     Library archives are expected to be found as
     */some/path/auto/ModuleName/ModuleName.a* For example, when looking
     for *Socket.a* relative to a search path, we should find
     *auto/Socket/Socket.a*

     When looking for *DBD::Oracle* relative to a search path, we should
     find *auto/DBD/Oracle/Oracle.a*

     Keep in mind, you can always supply */my/own/path/ModuleName.a* as an
     additional linker argument.

     -  <list of linker args>

     Additional linker arguments to be considered.

     Any additional arguments found before the - token are expected to be
     names of modules to generate code for.

     When invoked with parameters the following are accepted and optional:

     `ldopts($std,[@modules],[@link_args],$path)'

     Where,

     *$std* is boolean, equivalent to the *-std* option.

     *[@modules]* is equivalent to additional arguments found before the -
     token.

     *[@link_args]* is equivalent to arguments found after the - token.

     $path is equivalent to the -I option.

     In addition, when ldopts is called with parameters, it will return
     the argument string rather than print it to STDOUT.

Examples
          perl -MExtUtils::Embed -e ldopts

     This will print arguments for linking with *libperl.a*, DynaLoader and
     extensions found in *$Config{static_ext}*.  This includes libraries
     found in *$Config{libs}* and the first ModuleName.a library for each
     extension that is found by searching *@INC* or the path specifed by
     the -I option.  In addition, when ModuleName.a is found, additional
     linker arguments are picked up from the *extralibs.ld* file in the
     same directory.

          perl -MExtUtils::Embed -e ldopts -- -std Socket

     This will do the same as the above example, along with printing
     additional arguments for linking with the Socket extension.

          perl -MExtUtils::Embed -e ldopts -- DynaLoader

     This will print arguments for linking with just the DynaLoader
     extension and *libperl.a*.

          perl -MExtUtils::Embed -e ldopts -- -std Msql -- -L/usr/msql/lib -lmsql

     Any arguments after the second '-' token are additional linker
     arguments that will be examined for potential conflict.  If there is
     no conflict, the additional arguments will be part of the output.

perl_inc()
     For including perl header files this function simply prints:

          -I$Config{archlibexp}/CORE

     So, rather than having to say:

          perl -MConfig -e 'print "-I$Config{archlibexp}/CORE"'

     Just say:

          perl -MExtUtils::Embed -e perl_inc

ccflags(), ccdlflags()
     These functions simply print $Config{ccflags} and $Config{ccdlflags}

ccopts()
     This function combines perl_inc(), ccflags() and ccdlflags() into one.

xsi_header()
     This function simply returns a string defining the same *EXTERN_C*
     macro as *perlmain.c* along with #including *perl.h* and *EXTERN.h*.

xsi_protos(@modules)
     This function returns a string of *boot_$ModuleName* prototypes for
     each @modules.

xsi_body(@modules)
     This function returns a string of calls to *newXS()* that glue the
     module bootstrap function to *boot_ModuleName* for each @modules.

     xsinit() uses the xsi_* functions to generate most of it's code.

EXAMPLES
========

   For examples on how to use ExtUtils::Embed for building C/C++
applications with embedded perl, see the eg/ directory and
Perlembed (perl.info).

SEE ALSO
========

   See Perlembed (perl.info),

AUTHOR
======

   Doug MacEachern <`dougm@osf.org'>

   Based on ideas from Tim Bunce <`Tim.Bunce@ig.co.uk'> and *minimod.pl*
by Andreas Koenig <`k@anna.in-berlin.de'> and Tim Bunce.

Simple interface to F77 libs
****************************

NAME
====

   ExtUtils::F77 - Simple interface to F77 libs

DESCRIPTION
===========

   This module tries to figure out how to link C programs with Fortran
subroutines on your system. Basically one must add a list of Fortran
runtime libraries. The problem is their location and name varies with each
OS/compiler combination!

   This module tries to implement a simple 'rule-of-thumb' database for
various flavours of UNIX systems.  A simple self-documenting Perl database
of knowledge/code for figuring out how to link for various combinations of
OS and compiler is embedded in the modules Perl code. Please help save the
world by sending database entries for your system to kgb@aaoepp.aao.gov.au

   The library list which the module returns can be explicitly overridden
by setting the environment variable F77LIBS, e.g.

     % setenv F77LIBS "-lfoo -lbar"
     % perl Makefile.PL
     ...

SYNOPSIS
========

     use ExtUtils::F77;               # Automatic guess
     use ExtUtils::F77 qw(sunos);     # Specify system
     use ExtUtils::F77 qw(linux g77); # Specify system and compiler
     $fortranlibs = ExtUtils::F77->runtime;

METHODS
=======

   The following methods are provided:

   * *runtime*

     Returns a list of F77 runtime libraries.

          $fortranlibs = ExtUtils::F77->runtime;

   * *runtimeok*

     Returns TRUE only if runtime libraries have been found successfully.

   * *trail_*

     Returns true if F77 names have trailing underscores.

   * *compiler*

     Returns command to execute the compiler (e.g. 'f77').

   * cflags

     Returns compiler flags.

   * *testcompiler*

     Test to see if compiler actually works.

   More methods  will probably be added in the future.

AUTHOR
======

   Karl Glazebrook (kgb@aaoepp.aao.GOV.AU).

install files from here to there
********************************

NAME
====

   ExtUtils::Install - install files from here to there

SYNOPSIS
========

   *use ExtUtils::Install;*

   *install($hashref,$verbose,$nonono);*

   *uninstall($packlistfile,$verbose,$nonono);*

   *pm_to_blib($hashref);*

DESCRIPTION
===========

   Both install() and uninstall() are specific to the way
ExtUtils::MakeMaker handles the installation and deinstallation of perl
modules. They are not designed as general purpose tools.

   install() takes three arguments. A reference to a hash, a verbose
switch and a don't-really-do-it switch. The hash ref contains a mapping of
directories: each key/value pair is a combination of directories to be
copied. Key is a directory to copy from, value is a directory to copy to.
The whole tree below the "from" directory will be copied preserving
timestamps and permissions.

   There are two keys with a special meaning in the hash: "read" and
"write". After the copying is done, install will write the list of target
files to the file named by `$hashref->{write}'. If there is another file
named by `$hashref->{read}', the contents of this file will be merged into
the written file. The read and the written file may be identical, but on
AFS it is quite likely that people are installing to a different directory
than the one where the files later appear.

   install_default() takes one or less arguments.  If no arguments are
specified, it takes $ARGV[0] as if it was specified as an argument.  The
argument is the value of MakeMaker's `FULLEXT' key, like `Tk/Canvas'.
This function calls install() with the same arguments as the defaults the
MakeMaker would use.

   The argument-less form is convenient for install scripts like

     perl -MExtUtils::Install -e install_default Tk/Canvas

   Assuming this command is executed in a directory with a populated blib
directory, it will proceed as if the blib was build by MakeMaker on this
machine.  This is useful for binary distributions.

   uninstall() takes as first argument a file containing filenames to be
unlinked. The second argument is a verbose switch, the third is a
no-don't-really-do-it-now switch.

   pm_to_blib() takes a hashref as the first argument and copies all keys
of the hash to the corresponding values efficiently. Filenames with the
extension pm are autosplit. Second argument is the autosplit directory.

Inventory management of installed modules
*****************************************

NAME
====

   ExtUtils::Installed - Inventory management of installed modules

SYNOPSIS
========

     use ExtUtils::Installed;
     my ($inst) = ExtUtils::Installed->new();
     my (@modules) = $inst->modules();
     my (@missing) = $inst->validate("DBI");
     my $all_files = $inst->files("DBI");
     my $files_below_usr_local = $inst->files("DBI", "all", "/usr/local");
     my $all_dirs = $inst->directories("DBI");
     my $dirs_below_usr_local = $inst->directory_tree("DBI", "prog");
     my $packlist = $inst->packlist("DBI");

DESCRIPTION
===========

   ExtUtils::Installed  provides a standard way to find out what core and
module files have been installed.  It uses the information stored in
.packlist files created during installation to provide this information.
In addition it provides facilities to classify the installed files and to
extract directory information from the .packlist files.

USAGE
=====

   The new() function searches for all the installed .packlists on the
system, and stores their contents. The .packlists can be queried with the
functions described below.

FUNCTIONS
=========

new()
     This takes no parameters, and searches for all the installed
     .packlists on the system.  The packlists are read using the
     ExtUtils::packlist module.

modules()
     This returns a list of the names of all the installed modules.  The
     perl 'core' is given the special name 'Perl'.

files()
     This takes one mandatory parameter, the name of a module.  It returns
     a list of all the filenames from the package.  To obtain a list of
     core perl files, use the module name 'Perl'.  Additional parameters
     are allowed.  The first is one of the strings "prog", "man" or "all",
     to select either just program files, just manual files or all files.
     The remaining parameters are a list of directories. The filenames
     returned will be restricted to those under the specified directories.

directories()
     This takes one mandatory parameter, the name of a module.  It returns
     a list of all the directories from the package.  Additional
     parameters are allowed.  The first is one of the strings "prog",
     "man" or "all", to select either just program directories, just
     manual directories or all directories.  The remaining parameters are
     a list of directories. The directories returned will be restricted to
     those under the specified directories.  This method returns only the
     leaf directories that contain files from the specified module.

directory_tree()
     This is identical in operation to directory(), except that it
     includes all the intermediate directories back up to the specified
     directories.

validate()
     This takes one mandatory parameter, the name of a module.  It checks
     that all the files listed in the modules .packlist actually exist,
     and returns a list of any missing files.  If an optional second
     argument which evaluates to true is given any missing files will be
     removed from the .packlist

packlist()
     This returns the ExtUtils::Packlist object for the specified module.

version()
     This returns the version number for the specified module.

EXAMPLE
=======

   See the example in ExtUtils/Packlist.

AUTHOR
======

   Alan Burlison <Alan.Burlison@uk.sun.com>

determine libraries to use and how to use them
**********************************************

NAME
====

   ExtUtils::Liblist - determine libraries to use and how to use them

SYNOPSIS
========

   `require ExtUtils::Liblist;'

   `ExtUtils::Liblist::ext($self, $potential_libs, $verbose);'

DESCRIPTION
===========

   This utility takes a list of libraries in the form `-llib1 -llib2
-llib3' and prints out lines suitable for inclusion in an extension
Makefile.  Extra library paths may be included with the form
`-L/another/path' this will affect the searches for all subsequent
libraries.

   It returns an array of four scalar values: EXTRALIBS, BSLOADLIBS,
LDLOADLIBS, and LD_RUN_PATH.  Some of these don't mean anything on VMS and
Win32.  See the details about those platform specifics below.

   Dependent libraries can be linked in one of three ways:

   * For static extensions

     by the ld command when the perl binary is linked with the extension
     library. See EXTRALIBS below.

   * For dynamic extensions

     by the ld command when the shared object is built/linked. See
     LDLOADLIBS below.

   * For dynamic extensions

     by the DynaLoader when the shared object is loaded. See BSLOADLIBS
     below.

EXTRALIBS
---------

   List of libraries that need to be linked with when linking a perl
binary which includes this extension. Only those libraries that actually
exist are included.  These are written to a file and used when linking
perl.

LDLOADLIBS and LD_RUN_PATH
--------------------------

   List of those libraries which can or must be linked into the shared
library when created using ld. These may be static or dynamic libraries.
LD_RUN_PATH is a colon separated list of the directories in LDLOADLIBS. It
is passed as an environment variable to the process that links the shared
library.

BSLOADLIBS
----------

   List of those libraries that are needed but can be linked in
dynamically at run time on this platform.  SunOS/Solaris does not need
this because ld records the information (from LDLOADLIBS) into the object
file.  This list is used to create a .bs (bootstrap) file.

PORTABILITY
===========

   This module deals with a lot of system dependencies and has quite a few
architecture specific ifs in the code.

VMS implementation
------------------

   The version of ext() which is executed under VMS differs from the
Unix-OS/2 version in several respects:

   * Input library and path specifications are accepted with or without the
     -l and -L prefixes used by Unix linkers.  If neither prefix is
     present, a token is considered a directory to search if it is in fact
     a directory, and a library to search for otherwise.  Authors who wish
     their extensions to be portable to Unix or OS/2 should use the Unix
     prefixes, since the Unix-OS/2 version of ext() requires them.

   * Wherever possible, shareable images are preferred to object libraries,
     and object libraries to plain object files.  In accordance with VMS
     naming conventions, ext() looks for files named libshr and librtl; it
     also looks for liblib and liblib to accommodate Unix conventions used
     in some ported software.

   * For each library that is found, an appropriate directive for a linker
     options file is generated.  The return values are space-separated
     strings of these directives, rather than elements used on the linker
     command line.

   * LDLOADLIBS contains both the libraries found based on
     `$potential_libs' and the CRTLs, if any, specified in Config.pm.
     EXTRALIBS contains just those libraries found based on
     `$potential_libs'.  BSLOADLIBS and LD_RUN_PATH are always empty.

   In addition, an attempt is made to recognize several common Unix library
names, and filter them out or convert them to their VMS equivalents, as
appropriate.

   In general, the VMS version of ext() should properly handle input from
extensions originally designed for a Unix or VMS environment.  If you
encounter problems, or discover cases where the search could be improved,
please let us know.

Win32 implementation
--------------------

   The version of ext() which is executed under Win32 differs from the
Unix-OS/2 version in several respects:

   * If `$potential_libs' is empty, the return value will be empty.
     Otherwise, the libraries specified by `$Config{libs}' (see Config.pm)
     will be appended to the list of `$potential_libs'.  The libraries
     will be searched for in the directories specified in
     `$potential_libs', `$Config{libpth}', and in
     `$Config{installarchlib}/CORE'.  For each library that is found,  a
     space-separated list of fully qualified library pathnames is
     generated.

   * Input library and path specifications are accepted with or without the
     -l and -L prefixes used by Unix linkers.

     An entry of the form `-La:\foo' specifies the `a:\foo' directory to
     look for the libraries that follow.

     An entry of the form `-lfoo' specifies the library foo, which may be
     spelled differently depending on what kind of compiler you are using.
     If you are using GCC, it gets translated to `libfoo.a', but for
     other win32 compilers, it becomes `foo.lib'.  If no files are found
     by those translated names, one more attempt is made to find them
     using either `foo.a' or `libfoo.lib', depending on whether GCC or
     some other win32 compiler is being used, respectively.

     If neither the -L or -l prefix is present in an entry, the entry is
     considered a directory to search if it is in fact a directory, and a
     library to search for otherwise.  The `$Config{lib_ext}' suffix will
     be appended to any entries that are not directories and don't already
     have the suffix.

     Note that the -L and -l prefixes are *not required*, but authors who
     wish their extensions to be portable to Unix or OS/2 should use the
     prefixes, since the Unix-OS/2 version of ext() requires them.

   * Entries cannot be plain object files, as many Win32 compilers will
     not handle object files in the place of libraries.

   * Entries in `$potential_libs' beginning with a colon and followed by
     alphanumeric characters are treated as flags.  Unknown flags will be
     ignored.

     An entry that matches `/:nodefault/i' disables the appending of
     default libraries found in `$Config{libs}' (this should be only
     needed very rarely).

     An entry that matches `/:nosearch/i' disables all searching for the
     libraries specified after it.  Translation of `-Lfoo' and `-lfoo'
     still happens as appropriate (depending on compiler being used, as
     reflected by `$Config{cc}'), but the entries are not verified to be
     valid files or directories.

     An entry that matches `/:search/i' reenables searching for the
     libraries specified after it.  You can put it at the end to enable
     searching for default libraries specified by `$Config{libs}'.

   * The libraries specified may be a mixture of static libraries and
     import libraries (to link with DLLs).  Since both kinds are used
     pretty transparently on the Win32 platform, we do not attempt to
     distinguish between them.

   * LDLOADLIBS and EXTRALIBS are always identical under Win32, and
     BSLOADLIBS and LD_RUN_PATH are always empty (this may change in
     future).

   * You must make sure that any paths and path components are properly
     surrounded with double-quotes if they contain spaces. For example,
     `$potential_libs' could be (literally):

          "-Lc:\Program Files\vc\lib" msvcrt.lib "la test\foo bar.lib"

     Note how the first and last entries are protected by quotes in order
     to protect the spaces.

   * Since this module is most often used only indirectly from extension
     Makefile.PL files, here is an example Makefile.PL entry to add a
     library to the build process for an extension:

          LIBS => ['-lgl']

     When using GCC, that entry specifies that MakeMaker should first look
     for `libgl.a' (followed by `gl.a') in all the locations specified by
     `$Config{libpth}'.

     When using a compiler other than GCC, the above entry will search for
     `gl.lib' (followed by `libgl.lib').

     If the library happens to be in a location not in `$Config{libpth}',
     you need:

          LIBS => ['-Lc:\gllibs -lgl']

     Here is a less often used example:

          LIBS => ['-lgl', ':nosearch -Ld:\mesalibs -lmesa -luser32']

     This specifies a search for library `gl' as before.  If that search
     fails to find the library, it looks at the next item in the list. The
     `:nosearch' flag will prevent searching for the libraries that follow,
     so it simply returns the value as `-Ld:\mesalibs -lmesa -luser32',
     since GCC can use that value as is with its linker.

     When using the Visual C compiler, the second item is returned as
     `-libpath:d:\mesalibs mesa.lib user32.lib'.

     When using the Borland compiler, the second item is returned as
     `-Ld:\mesalibs mesa.lib user32.lib', and MakeMaker takes care of
     moving the `-Ld:\mesalibs' to the correct place in the linker command
     line.

SEE ALSO
========

   See ExtUtils/MakeMaker,

methods to override UN*X behaviour in ExtUtils::MakeMaker
*********************************************************

NAME
====

   ExtUtils::MM_Cygwin - methods to override UN*X behaviour in
ExtUtils::MakeMaker

SYNOPSIS
========

     use ExtUtils::MM_Cygwin; # Done internally by ExtUtils::MakeMaker if needed

DESCRIPTION
===========

   See ExtUtils::MM_Unix for a documentation of the methods provided there.

canonpath
     replaces backslashes with forward ones.  then acts as *nixish.

cflags
     if configured for dynamic loading, triggers #define EXT in EXTERN.h

manifypods
     replaces strings '::' with '.' in man page names

perl_archive
     points to libperl.a

methods to override UN*X behaviour in ExtUtils::MakeMaker
*********************************************************

NAME
====

   ExtUtils::MM_OS2 - methods to override UN*X behaviour in
ExtUtils::MakeMaker

SYNOPSIS
========

     use ExtUtils::MM_OS2; # Done internally by ExtUtils::MakeMaker if needed

DESCRIPTION
===========

   See ExtUtils::MM_Unix for a documentation of the methods provided
there. This package overrides the implementation of these methods, not the
semantics.

methods used by ExtUtils::MakeMaker
***********************************

NAME
====

   ExtUtils::MM_Unix - methods used by ExtUtils::MakeMaker

SYNOPSIS
========

   `require ExtUtils::MM_Unix;'

DESCRIPTION
===========

   The methods provided by this package are designed to be used in
conjunction with ExtUtils::MakeMaker. When MakeMaker writes a Makefile, it
creates one or more objects that inherit their methods from a package
`MM'. MM itself doesn't provide any methods, but it ISA ExtUtils::MM_Unix
class. The inheritance tree of MM lets operating specific packages take
the responsibility for all the methods provided by MM_Unix. We are trying
to reduce the number of the necessary overrides by defining rather
primitive operations within ExtUtils::MM_Unix.

   If you are going to write a platform specific MM package, please try to
limit the necessary overrides to primitive methods, and if it is not
possible to do so, let's work out how to achieve that gain.

   If you are overriding any of these methods in your Makefile.PL (in the
MY class), please report that to the makemaker mailing list. We are trying
to minimize the necessary method overrides and switch to data driven
Makefile.PLs wherever possible. In the long run less methods will be
overridable via the MY class.

METHODS
=======

   The following description of methods is still under development. Please
refer to the code for not suitably documented sections and complain loudly
to the makemaker mailing list.

   Not all of the methods below are overridable in a Makefile.PL.
Overridable methods are marked as (o). All methods are overridable by a
platform specific MM_*.pm file (See ExtUtils/MM_VMS)
and ExtUtils/MM_OS2).

Preloaded methods
-----------------

canonpath
     No physical check on the filesystem, but a logical cleanup of a path.
     On UNIX eliminated successive slashes and successive "/.".

catdir
     Concatenate two or more directory names to form a complete path ending
     with a directory. But remove the trailing slash from the resulting
     string, because it doesn't look good, isn't necessary and confuses
     OS2. Of course, if this is the root directory, don't cut off the
     trailing slash :-)

catfile
     Concatenate one or more directory names and a filename to form a
     complete path ending with a filename

curdir
     Returns a string representing of the current directory.  "." on UNIX.

rootdir
     Returns a string representing of the root directory.  "/" on UNIX.

updir
     Returns a string representing of the parent directory.  ".." on UNIX.

SelfLoaded methods
------------------

c_o (o)
     Defines the suffix rules to compile different flavors of C files to
     object files.

cflags (o)
     Does very much the same as the cflags script in the perl
     distribution. It doesn't return the whole compiler command line, but
     initializes all of its parts. The const_cccmd method then actually
     returns the definition of the CCCMD macro which uses these parts.

clean (o)
     Defines the clean target.

const_cccmd (o)
     Returns the full compiler call for C programs and stores the
     definition in CONST_CCCMD.

const_config (o)
     Defines a couple of constants in the Makefile that are imported from
     %Config.

const_loadlibs (o)
     Defines EXTRALIBS, LDLOADLIBS, BSLOADLIBS, LD_RUN_PATH. See
     ExtUtils/Liblist, for details.

constants (o)
     Initializes lots of constants and .SUFFIXES and .PHONY

depend (o)
     Same as macro for the depend attribute.

dir_target (o)
     Takes an array of directories that need to exist and returns a
     Makefile entry for a .exists file in these directories. Returns
     nothing, if the entry has already been processed. We're helpless
     though, if the same directory comes as $(FOO) _and_ as "bar". Both of
     them get an entry, that's why we use "::".

dist (o)
     Defines a lot of macros for distribution support.

dist_basics (o)
     Defines the targets distclean, distcheck, skipcheck, manifest.

dist_ci (o)
     Defines a check in target for RCS.

dist_core (o)
     Defines the targets dist, tardist, zipdist, uutardist, shdist

dist_dir (o)
     Defines the scratch directory target that will hold the distribution
     before tar-ing (or shar-ing).

dist_test (o)
     Defines a target that produces the distribution in the
     scratchdirectory, and runs 'perl Makefile.PL; make ;make test' in that
     subdirectory.

dlsyms (o)
     Used by AIX and VMS to define DL_FUNCS and DL_VARS and write the *.exp
     files.

dynamic (o)
     Defines the dynamic target.

dynamic_bs (o)
     Defines targets for bootstrap files.

dynamic_lib (o)
     Defines how to produce the *.so (or equivalent) files.

exescan
     Deprecated method. Use libscan instead.

extliblist
     Called by init_others, and calls ext ExtUtils::Liblist. See
     ExtUtils/Liblist, for details.

file_name_is_absolute
     Takes as argument a path and returns true, if it is an absolute path.

find_perl
     Finds the executables PERL and FULLPERL

Methods to actually produce chunks of text for the Makefile
-----------------------------------------------------------

   The methods here are called for each MakeMaker object in the order
specified by @ExtUtils::MakeMaker::MM_Sections.

fixin
     Inserts the sharpbang or equivalent magic number to a script

force (o)
     Just writes FORCE:

guess_name
     Guess the name of this package by examining the working directory's
     name. MakeMaker calls this only if the developer has not supplied a
     NAME attribute.

has_link_code
     Returns true if C, XS, MYEXTLIB or similar objects exist within this
     object that need a compiler. Does not descend into subdirectories as
     needs_linking() does.

htmlifypods (o)
     Defines targets and routines to translate the pods into HTML manpages
     and put them into the INST_HTMLLIBDIR and INST_HTMLSCRIPTDIR
     directories.

init_dirscan
     Initializes DIR, XS, PM, C, O_FILES, H, PL_FILES, HTML*PODS,
     MAN*PODS, EXE_FILES.

init_main
     Initializes NAME, FULLEXT, BASEEXT, PARENT_NAME, DLBASE, PERL_SRC,
     PERL_LIB, PERL_ARCHLIB, PERL_INC, INSTALLDIRS, INST_*, INSTALL*,
     PREFIX, CONFIG, AR, AR_STATIC_ARGS, LD, OBJ_EXT, LIB_EXT, EXE_EXT,
     MAP_TARGET, LIBPERL_A, VERSION_FROM, VERSION, DISTNAME, VERSION_SYM.

init_others
     Initializes EXTRALIBS, BSLOADLIBS, LDLOADLIBS, LIBS, LD_RUN_PATH,
     OBJECT, BOOTDEP, PERLMAINCC, LDFROM, LINKTYPE, NOOP, FIRST_MAKEFILE,
     MAKEFILE, NOECHO, RM_F, RM_RF, TEST_F, TOUCH, CP, MV, CHMOD,
     UMASK_NULL

install (o)
     Defines the install target.

installbin (o)
     Defines targets to make and to install EXE_FILES.

libscan (o)
     Takes a path to a file that is found by init_dirscan and returns false
     if we don't want to include this file in the library. Mainly used to
     exclude RCS, CVS, and SCCS directories from installation.

linkext (o)
     Defines the linkext target which in turn defines the LINKTYPE.

lsdir
     Takes as arguments a directory name and a regular expression. Returns
     all entries in the directory that match the regular expression.

macro (o)
     Simple subroutine to insert the macros defined by the macro attribute
     into the Makefile.

makeaperl (o)
     Called by staticmake. Defines how to write the Makefile to produce a
     static new perl.

     By default the Makefile produced includes all the static extensions in
     the perl library. (Purified versions of library files, e.g.,
     DynaLoader_pure_p1_c0_032.a are automatically ignored to avoid link
     errors.)

makefile (o)
     Defines how to rewrite the Makefile.

manifypods (o)
     Defines targets and routines to translate the pods into manpages and
     put them into the INST_* directories.

maybe_command
     Returns true, if the argument is likely to be a command.

maybe_command_in_dirs
     method under development. Not yet used. Ask Ilya :-)

needs_linking (o)
     Does this module need linking? Looks into subdirectory objects (see
     also has_link_code())

nicetext
     misnamed method (will have to be changed). The MM_Unix method just
     returns the argument without further processing.

     On VMS used to insure that colons marking targets are preceded by
     space - most Unix Makes don't need this, but it's necessary under VMS
     to distinguish the target delimiter from a colon appearing as part of
     a filespec.

parse_version
     parse a file and return what you think is $VERSION in this file set
     to.  It will return the string "undef" if it can't figure out what
     $VERSION is.

parse_abstract
     parse a file and return what you think is the ABSTRACT

pasthru (o)
     Defines the string that is passed to recursive make calls in
     subdirectories.

path
     Takes no argument, returns the environment variable PATH as an array.

perl_script
     Takes one argument, a file name, and returns the file name, if the
     argument is likely to be a perl script. On MM_Unix this is true for
     any ordinary, readable file.

perldepend (o)
     Defines the dependency from all *.h files that come with the perl
     distribution.

ppd
     Defines target that creates a PPD (Perl Package Description) file for
     a binary distribution.

perm_rw (o)
     Returns the attribute PERM_RW or the string `644'.  Used as the
     string that is passed to the chmod command to set the permissions for
     read/writeable files.  MakeMaker chooses `644' because it has turned
     out in the past that relying on the umask provokes hard-to-track bug
     reports.  When the return value is used by the perl function chmod,
     it is interpreted as an octal value.

perm_rwx (o)
     Returns the attribute PERM_RWX or the string `755', i.e. the string
     that is passed to the chmod command to set the permissions for
     executable files.  See also perl_rw.

pm_to_blib
     Defines target that copies all files in the hash PM to their
     destination and autosplits them. See `DESCRIPTION', see
     ExtUtils/Install,

post_constants (o)
     Returns an empty string per default. Dedicated to overrides from
     within Makefile.PL after all constants have been defined.

post_initialize (o)
     Returns an empty string per default. Used in Makefile.PLs to add some
     chunk of text to the Makefile after the object is initialized.

postamble (o)
     Returns an empty string. Can be used in Makefile.PLs to write some
     text to the Makefile at the end.

prefixify
     Check a path variable in $self from %Config, if it contains a prefix,
     and replace it with another one.

     Takes as arguments an attribute name, a search prefix and a
     replacement prefix. Changes the attribute in the object.

processPL (o)
     Defines targets to run *.PL files.

realclean (o)
     Defines the realclean target.

replace_manpage_separator
     Takes the name of a package, which may be a nested package, in the
     form Foo/Bar and replaces the slash with `::'. Returns the
     replacement.

static (o)
     Defines the static target.

static_lib (o)
     Defines how to produce the *.a (or equivalent) files.

staticmake (o)
     Calls makeaperl.

subdir_x (o)
     Helper subroutine for subdirs

subdirs (o)
     Defines targets to process subdirectories.

test (o)
     Defines the test targets.

test_via_harness (o)
     Helper method to write the test targets

test_via_script (o)
     Other helper method for test.

tool_autosplit (o)
     Defines a simple perl call that runs autosplit. May be deprecated by
     pm_to_blib soon.

tools_other (o)
     Defines SHELL, LD, TOUCH, CP, MV, RM_F, RM_RF, CHMOD, UMASK_NULL in
     the Makefile. Also defines the perl programs MKPATH,
     WARN_IF_OLD_PACKLIST, MOD_INSTALL. DOC_INSTALL, and UNINSTALL.

tool_xsubpp (o)
     Determines typemaps, xsubpp version, prototype behaviour.

top_targets (o)
     Defines the targets all, subdirs, config, and O_FILES

writedoc
     Obsolete, deprecated method. Not used since Version 5.21.

xs_c (o)
     Defines the suffix rules to compile XS files to C.

xs_cpp (o)
     Defines the suffix rules to compile XS files to C++.

xs_o (o)
     Defines suffix rules to go from XS to object files directly. This is
     only intended for broken make implementations.

perl_archive
     This is internal method that returns path to libperl.a equivalent to
     be linked to dynamic extensions. UNIX does not have one but OS2 and
     Win32 do.

export_list
     This is internal method that returns name of a file that is passed to
     linker to define symbols to be exported.  UNIX does not have one but
     OS2 and Win32 do.

SEE ALSO
========

   See ExtUtils/MakeMaker,

methods to override UN*X behaviour in ExtUtils::MakeMaker
*********************************************************

NAME
====

   ExtUtils::MM_VMS - methods to override UN*X behaviour in
ExtUtils::MakeMaker

SYNOPSIS
========

     use ExtUtils::MM_VMS; # Done internally by ExtUtils::MakeMaker if needed

DESCRIPTION
===========

   See ExtUtils::MM_Unix for a documentation of the methods provided
there. This package overrides the implementation of these methods, not the
semantics.

Methods always loaded
---------------------

wraplist
     Converts a list into a string wrapped at approximately 80 columns.

rootdir (override)
     Returns a string representing of the root directory.

SelfLoaded methods
------------------

   Those methods which override default MM_Unix methods are marked
"(override)", while methods unique to MM_VMS are marked "(specific)".  For
overridden methods, documentation is limited to an explanation of why this
method overrides the MM_Unix method; see the ExtUtils::MM_Unix
documentation for more details.

guess_name (override)
     Try to determine name of extension being built.  We begin with the
     name of the current directory.  Since VMS filenames are
     case-insensitive, however, we look for a `.pm' file whose name
     matches that of the current directory (presumably the 'main' `.pm'
     file for this extension), and try to find a package statement from
     which to obtain the Mixed::Case package name.

find_perl (override)
     Use VMS file specification syntax and CLI commands to find and invoke
     Perl images.

path (override)
     Translate logical name DCL$PATH as a searchlist, rather than trying
     to split string value of `$ENV{'PATH'}'.

maybe_command (override)
     Follows VMS naming conventions for executable files.  If the name
     passed in doesn't exactly match an executable file, appends `.Exe'
     (or equivalent) to check for executable image, and `.Com' to check
     for DCL procedure.  If this fails, checks directories in DCL$PATH and
     finally `Sys$System:' for an executable file having the name
     specified, with or without the `.Exe'-equivalent suffix.

maybe_command_in_dirs (override)
     Uses DCL argument quoting on test command line.

perl_script (override)
     If name passed in doesn't specify a readable file, appends `.com' or
     `.pl' and tries again, since it's customary to have file types on all
     files under VMS.

file_name_is_absolute (override)
     Checks for VMS directory spec as well as Unix separators.

replace_manpage_separator
     Use as separator a character which is legal in a VMS-syntax file name.

init_others (override)
     Provide VMS-specific forms of various utility commands, then hand off
     to the default MM_Unix method.

constants (override)
     Fixes up numerous file and directory macros to insure VMS syntax
     regardless of input syntax.  Also adds a few VMS-specific macros and
     makes lists of files comma-separated.

cflags (override)
     Bypass shell script and produce qualifiers for CC directly (but warn
     user if a shell script for this extension exists).  Fold multiple
     /Defines into one, since some C compilers pay attention to only one
     instance of this qualifier on the command line.

const_cccmd (override)
     Adds directives to point C preprocessor to the right place when
     handling #include <sys/foo.h> directives.  Also constructs CC command
     line a bit differently than MM_Unix method.

pm_to_blib (override)
     DCL *still* accepts a maximum of 255 characters on a command line, so
     we write the (potentially) long list of file names to a temp file,
     then persuade Perl to read it instead of the command line to find
     args.

tool_autosplit (override)
     Use VMS-style quoting on command line.

tool_sxubpp (override)
     Use VMS-style quoting on xsubpp command line.

xsubpp_version (override)
     Test xsubpp exit status according to VMS rules ($sts & 1 ==> good)
     rather than Unix rules ($sts == 0 ==> good).

tools_other (override)
     Adds a few MM[SK] macros, and shortens some the installatin commands,
     in order to stay under DCL's 255-character limit.  Also changes
     EQUALIZE_TIMESTAMP to set revision date of target file to one second
     later than source file, since MMK interprets precisely equal revision
     dates for a source and target file as a sign that the target needs to
     be updated.

dist (override)
     Provide VMSish defaults for some values, then hand off to default
     MM_Unix method.

c_o (override)
     Use VMS syntax on command line.  In particular, $(DEFINE) and
     $(PERL_INC) have been pulled into $(CCCMD).  Also use MM[SK] macros.

xs_c (override)
     Use MM[SK] macros.

xs_o (override)
     Use MM[SK] macros, and VMS command line for C compiler.

top_targets (override)
     Use VMS quoting on command line for Version_check.

dlsyms (override)
     Create VMS linker options files specifying universal symbols for this
     extension's shareable image, and listing other shareable images or
     libraries to which it should be linked.

dynamic_lib (override)
     Use VMS Link command.

dynamic_bs (override)
     Use VMS-style quoting on Mkbootstrap command line.

static_lib (override)
     Use VMS commands to manipulate object library.

manifypods (override)
     Use VMS-style quoting on command line, and VMS logical name to
     specify fallback location at build time if we can't find pod2man.

processPL (override)
     Use VMS-style quoting on command line.

installbin (override)
     Stay under DCL's 255 character command line limit once again by
     splitting potentially long list of files across multiple lines in
     realclean target.

subdir_x (override)
     Use VMS commands to change default directory.

clean (override)
     Split potentially long list of files across multiple commands (in
     order to stay under the magic command line limit).  Also use MM[SK]
     commands for handling subdirectories.

realclean (override)
     Guess what we're working around?  Also, use MM[SK] for subdirectories.

dist_basics (override)
     Use VMS-style quoting on command line.

dist_core (override)
     Syntax for invoking `VMS_Share' differs from that for Unix `shar', so
     `shdist' target actions are VMS-specific.

dist_dir (override)
     Use VMS-style quoting on command line.

dist_test (override)
     Use VMS commands to change default directory, and use VMS-style
     quoting on command line.

install (override)
     Work around DCL's 255 character limit several times,and use VMS-style
     command line quoting in a few cases.

perldepend (override)
     Use VMS-style syntax for files; it's cheaper to just do it directly
     here than to have the MM_Unix method call catfile repeatedly.  Also,
     if we have to rebuild Config.pm, use MM[SK] to do it.

makefile (override)
     Use VMS commands and quoting.

test (override)
     Use VMS commands for handling subdirectories.

test_via_harness (override)
     Use VMS-style quoting on command line.

test_via_script (override)
     Use VMS-style quoting on command line.

makeaperl (override)
     Undertake to build a new set of Perl images using VMS commands.  Since
     VMS does dynamic loading, it's not necessary to statically link each
     extension into the Perl image, so this isn't the normal build path.
     Consequently, it hasn't really been tested, and may well be
     incomplete.

nicetext (override)
     Insure that colons marking targets are preceded by space, in order to
     distinguish the target delimiter from a colon appearing as part of a
     filespec.

methods to override UN*X behaviour in ExtUtils::MakeMaker
*********************************************************

NAME
====

   ExtUtils::MM_Win32 - methods to override UN*X behaviour in
ExtUtils::MakeMaker

SYNOPSIS
========

     use ExtUtils::MM_Win32; # Done internally by ExtUtils::MakeMaker if needed

DESCRIPTION
===========

   See ExtUtils::MM_Unix for a documentation of the methods provided
there. This package overrides the implementation of these methods, not the
semantics.

catfile
     Concatenate one or more directory names and a filename to form a
     complete path ending with a filename

constants (o)
     Initializes lots of constants and .SUFFIXES and .PHONY

static_lib (o)
     Defines how to produce the *.a (or equivalent) files.

dynamic_bs (o)
     Defines targets for bootstrap files.

dynamic_lib (o)
     Defines how to produce the *.so (or equivalent) files.

canonpath
     No physical check on the filesystem, but a logical cleanup of a path.
     On UNIX eliminated successive slashes and successive "/.".

perl_script
     Takes one argument, a file name, and returns the file name, if the
     argument is likely to be a perl script. On MM_Unix this is true for
     any ordinary, readable file.

pm_to_blib
     Defines target that copies all files in the hash PM to their
     destination and autosplits them. See `DESCRIPTION', see
     ExtUtils/Install,

test_via_harness (o)
     Helper method to write the test targets

tool_autosplit (override)
     Use Win32 quoting on command line.

tools_other (o)
     Win32 overrides.

     Defines SHELL, LD, TOUCH, CP, MV, RM_F, RM_RF, CHMOD, UMASK_NULL in
     the Makefile. Also defines the perl programs MKPATH,
     WARN_IF_OLD_PACKLIST, MOD_INSTALL. DOC_INSTALL, and UNINSTALL.

xs_o (o)
     Defines suffix rules to go from XS to object files directly. This is
     only intended for broken make implementations.

top_targets (o)
     Defines the targets all, subdirs, config, and O_FILES

htmlifypods (o)
     Defines targets and routines to translate the pods into HTML manpages
     and put them into the INST_HTMLLIBDIR and INST_HTMLSCRIPTDIR
     directories.

     Same as MM_Unix version (changes command-line quoting).

manifypods (o)
     We don't want manpage process.

dist_ci (o)
     Same as MM_Unix version (changes command-line quoting).

dist_core (o)
     Same as MM_Unix version (changes command-line quoting).

pasthru (o)
     Defines the string that is passed to recursive make calls in
     subdirectories.

create an extension Makefile
****************************

NAME
====

   ExtUtils::MakeMaker - create an extension Makefile

SYNOPSIS
========

   `use ExtUtils::MakeMaker;'

   `WriteMakefile( ATTRIBUTE => VALUE [, ...] );'

   which is really

   `MM->new(\%att)->flush;'

DESCRIPTION
===========

   This utility is designed to write a Makefile for an extension module
from a Makefile.PL. It is based on the Makefile.SH model provided by Andy
Dougherty and the perl5-porters.

   It splits the task of generating the Makefile into several subroutines
that can be individually overridden.  Each subroutine returns the text it
wishes to have written to the Makefile.

   MakeMaker is object oriented. Each directory below the current
directory that contains a Makefile.PL. Is treated as a separate object.
This makes it possible to write an unlimited number of Makefiles with a
single invocation of WriteMakefile().

How To Write A Makefile.PL
--------------------------

   The short answer is: Don't.

     Always begin with h2xs.
     Always begin with h2xs!
     ALWAYS BEGIN WITH H2XS!

   even if you're not building around a header file, and even if you don't
have an XS component.

   Run h2xs(1) before you start thinking about writing a module. For so
called pm-only modules that consist of `*.pm' files only, h2xs has the -X
switch. This will generate dummy files of all kinds that are useful for
the module developer.

   The medium answer is:

     use ExtUtils::MakeMaker;
     WriteMakefile( NAME => "Foo::Bar" );

   The long answer is the rest of the manpage :-)

Default Makefile Behaviour
--------------------------

   The generated Makefile enables the user of the extension to invoke

     perl Makefile.PL # optionally "perl Makefile.PL verbose"
     make
     make test        # optionally set TEST_VERBOSE=1
     make install     # See below

   The Makefile to be produced may be altered by adding arguments of the
form `KEY=VALUE'. E.g.

     perl Makefile.PL PREFIX=/tmp/myperl5

   Other interesting targets in the generated Makefile are

     make config     # to check if the Makefile is up-to-date
     make clean      # delete local temp files (Makefile gets renamed)
     make realclean  # delete derived files (including ./blib)
     make ci         # check in all the files in the MANIFEST file
     make dist       # see below the Distribution Support section

make test
---------

   MakeMaker checks for the existence of a file named test.pl in the
current directory and if it exists it adds commands to the test target of
the generated Makefile that will execute the script with the proper set of
perl -I options.

   MakeMaker also checks for any files matching glob("t/*.t"). It will add
commands to the test target of the generated Makefile that execute all
matching files via the Test/Harness, module with the -I
switches set correctly.

make testdb
-----------

   A useful variation of the above is the target `testdb'. It runs the
test under the Perl debugger (see Perldebug (perl.info)).
If the file test.pl exists in the current directory, it is used for the
test.

   If you want to debug some other testfile, set `TEST_FILE' variable
thusly:

     make testdb TEST_FILE=t/mytest.t

   By default the debugger is called using -d option to perl. If you want
to specify some other option, set `TESTDB_SW' variable:

     make testdb TESTDB_SW=-Dx

make install
------------

   make alone puts all relevant files into directories that are named by
the macros INST_LIB, INST_ARCHLIB, INST_SCRIPT, INST_HTMLLIBDIR,
INST_HTMLSCRIPTDIR, INST_MAN1DIR, and INST_MAN3DIR.  All these default to
something below ./blib if you are not building below the perl source
directory. If you *are* building below the perl source, INST_LIB and
INST_ARCHLIB default to ../../lib, and INST_SCRIPT is not defined.

   The install target of the generated Makefile copies the files found
below each of the INST_* directories to their INSTALL* counterparts. Which
counterparts are chosen depends on the setting of INSTALLDIRS according to
the following table:

     INSTALLDIRS set to
            	       	              perl   	          site

     INST_ARCHLIB	INSTALLARCHLIB        INSTALLSITEARCH
     INST_LIB		INSTALLPRIVLIB        INSTALLSITELIB
     INST_HTMLLIBDIR	INSTALLHTMLPRIVLIBDIR INSTALLHTMLSITELIBDIR
     INST_HTMLSCRIPTDIR            INSTALLHTMLSCRIPTDIR
     INST_BIN			  INSTALLBIN
     INST_SCRIPT                   INSTALLSCRIPT
     INST_MAN1DIR                  INSTALLMAN1DIR
     INST_MAN3DIR                  INSTALLMAN3DIR

   The INSTALL... macros in turn default to their %Config
($Config{installprivlib}, $Config{installarchlib}, etc.) counterparts.

   You can check the values of these variables on your system with

     perl '-V:install.*'

   And to check the sequence in which the library directories are searched
by perl, run

     perl -le 'print join $/, @INC'

PREFIX and LIB attribute
------------------------

   PREFIX and LIB can be used to set several INSTALL* attributes in one
go. The quickest way to install a module in a non-standard place might be

     perl Makefile.PL LIB=~/lib

   This will install the module's architecture-independent files into
~/lib, the architecture-dependent files into ~/lib/$archname/auto.

   Another way to specify many INSTALL directories with a single parameter
is PREFIX.

     perl Makefile.PL PREFIX=~

   This will replace the string specified by $Config{prefix} in all
$Config{install*} values.

   Note, that in both cases the tilde expansion is done by MakeMaker, not
by perl by default, nor by make. Conflicts between parameters LIB, PREFIX
and the various INSTALL* arguments are resolved so that XXX

   If the user has superuser privileges, and is not working on AFS (Andrew
File System) or relatives, then the defaults for INSTALLPRIVLIB,
INSTALLARCHLIB, INSTALLSCRIPT, etc. will be appropriate, and this
incantation will be the best:

     perl Makefile.PL; make; make test
     make install

   make install per default writes some documentation of what has been
done into the file `$(INSTALLARCHLIB)/perllocal.pod'. This feature can be
bypassed by calling make pure_install.

AFS users
---------

   will have to specify the installation directories as these most
probably have changed since perl itself has been installed. They will have
to do this by calling

     perl Makefile.PL INSTALLSITELIB=/afs/here/today \
     	INSTALLSCRIPT=/afs/there/now INSTALLMAN3DIR=/afs/for/manpages
     make

   Be careful to repeat this procedure every time you recompile an
extension, unless you are sure the AFS installation directories are still
valid.

Static Linking of a new Perl Binary
-----------------------------------

   An extension that is built with the above steps is ready to use on
systems supporting dynamic loading. On systems that do not support dynamic
loading, any newly created extension has to be linked together with the
available resources. MakeMaker supports the linking process by creating
appropriate targets in the Makefile whenever an extension is built. You
can invoke the corresponding section of the makefile with

     make perl

   That produces a new perl binary in the current directory with all
extensions linked in that can be found in INST_ARCHLIB , SITELIBEXP, and
PERL_ARCHLIB. To do that, MakeMaker writes a new Makefile, on UNIX, this
is called Makefile.aperl (may be system dependent). If you want to force
the creation of a new perl, it is recommended, that you delete this
Makefile.aperl, so the directories are searched-through for linkable
libraries again.

   The binary can be installed into the directory where perl normally
resides on your machine with

     make inst_perl

   To produce a perl binary with a different name than `perl', either say

     perl Makefile.PL MAP_TARGET=myperl
     make myperl
     make inst_perl

   or say

     perl Makefile.PL
     make myperl MAP_TARGET=myperl
     make inst_perl MAP_TARGET=myperl

   In any case you will be prompted with the correct invocation of the
`inst_perl' target that installs the new binary into INSTALLBIN.

   make inst_perl per default writes some documentation of what has been
done into the file `$(INSTALLARCHLIB)/perllocal.pod'. This can be bypassed
by calling make pure_inst_perl.

   Warning: the inst_perl: target will most probably overwrite your
existing perl binary. Use with care!

   Sometimes you might want to build a statically linked perl although
your system supports dynamic loading. In this case you may explicitly set
the linktype with the invocation of the Makefile.PL or make:

     perl Makefile.PL LINKTYPE=static    # recommended

   or

     make LINKTYPE=static                # works on most systems

Determination of Perl Library and Installation Locations
--------------------------------------------------------

   MakeMaker needs to know, or to guess, where certain things are located.
Especially INST_LIB and INST_ARCHLIB (where to put the files during the
make(1) run), PERL_LIB and PERL_ARCHLIB (where to read existing modules
from), and PERL_INC (header files and `libperl*.*').

   Extensions may be built either using the contents of the perl source
directory tree or from the installed perl library. The recommended way is
to build extensions after you have run 'make install' on perl itself. You
can do that in any directory on your hard disk that is not below the perl
source tree. The support for extensions below the ext directory of the
perl distribution is only good for the standard extensions that come with
perl.

   If an extension is being built below the `ext/' directory of the perl
source then MakeMaker will set PERL_SRC automatically (e.g., `../..').  If
PERL_SRC is defined and the extension is recognized as a standard
extension, then other variables default to the following:

     PERL_INC     = PERL_SRC
     PERL_LIB     = PERL_SRC/lib
     PERL_ARCHLIB = PERL_SRC/lib
     INST_LIB     = PERL_LIB
     INST_ARCHLIB = PERL_ARCHLIB

   If an extension is being built away from the perl source then MakeMaker
will leave PERL_SRC undefined and default to using the installed copy of
the perl library. The other variables default to the following:

     PERL_INC     = $archlibexp/CORE
     PERL_LIB     = $privlibexp
     PERL_ARCHLIB = $archlibexp
     INST_LIB     = ./blib/lib
     INST_ARCHLIB = ./blib/arch

   If perl has not yet been installed then PERL_SRC can be defined on the
command line as shown in the previous section.

Which architecture dependent directory?
---------------------------------------

   If you don't want to keep the defaults for the INSTALL* macros,
MakeMaker helps you to minimize the typing needed: the usual relationship
between INSTALLPRIVLIB and INSTALLARCHLIB is determined by Configure at
perl compilation time. MakeMaker supports the user who sets
INSTALLPRIVLIB. If INSTALLPRIVLIB is set, but INSTALLARCHLIB not, then
MakeMaker defaults the latter to be the same subdirectory of
INSTALLPRIVLIB as Configure decided for the counterparts in %Config ,
otherwise it defaults to INSTALLPRIVLIB. The same relationship holds for
INSTALLSITELIB and INSTALLSITEARCH.

   MakeMaker gives you much more freedom than needed to configure internal
variables and get different results. It is worth to mention, that make(1)
also lets you configure most of the variables that are used in the
Makefile. But in the majority of situations this will not be necessary,
and should only be done if the author of a package recommends it (or you
know what you're doing).

Using Attributes and Parameters
-------------------------------

   The following attributes can be specified as arguments to
WriteMakefile() or as NAME=VALUE pairs on the command line:

AUTHOR
     String containing name (and email address) of package author(s). Is
     used in PPD (Perl Package Description) files for PPM (Perl Package
     Manager).

ABSTRACT
     One line description of the module. Will be included in PPD file.

ABSTRACT_FROM
     Name of the file that contains the package description. MakeMaker
     looks for a line in the POD matching /^($package\s-\s)(.*)/. This is
     typically the first line in the "=head1 NAME" section. $2 becomes the
     abstract.

BINARY_LOCATION
     Used when creating PPD files for binary packages.  It can be set to a
     full or relative path or URL to the binary archive for a particular
     architecture.  For example:

          perl Makefile.PL BINARY_LOCATION=x86/Agent.tar.gz

     builds a PPD package that references a binary of the `Agent' package,
     located in the `x86' directory relative to the PPD itself.

C
     Ref to array of *.c file names. Initialised from a directory scan and
     the values portion of the XS attribute hash. This is not currently
     used by MakeMaker but may be handy in Makefile.PLs.

CAPI
     [This attribute is obsolete in Perl 5.6.  PERL_OBJECT builds are
     C-compatible by default.]

     Switch to force usage of the Perl C API even when compiling for
     PERL_OBJECT.

     Note that this attribute is passed through to any recursive build,
     but if and only if the submodule's Makefile.PL itself makes no mention
     of the 'CAPI' attribute.

CCFLAGS
     String that will be included in the compiler call command line between
     the arguments INC and OPTIMIZE.

CONFIG
     Arrayref. E.g. [qw(archname manext)] defines ARCHNAME & MANEXT from
     config.sh. MakeMaker will add to CONFIG the following values anyway:
     ar cc cccdlflags ccdlflags dlext dlsrc ld lddlflags ldflags libc
     lib_ext obj_ext ranlib sitelibexp sitearchexp so

CONFIGURE
     CODE reference. The subroutine should return a hash reference. The
     hash may contain further attributes, e.g. {LIBS => ...}, that have to
     be determined by some evaluation method.

DEFINE
     Something like `"-DHAVE_UNISTD_H"'

DIR
     Ref to array of subdirectories containing Makefile.PLs e.g. [ 'sdbm'
     ] in ext/SDBM_File

DISTNAME
     Your name for distributing the package (by tar file). This defaults to
     NAME above.

DL_FUNCS
     Hashref of symbol names for routines to be made available as universal
     symbols.  Each key/value pair consists of the package name and an
     array of routine names in that package.  Used only under AIX, OS/2,
     VMS and Win32 at present.  The routine names supplied will be expanded
     in the same way as XSUB names are expanded by the XS() macro.
     Defaults to

          {"$(NAME)" => ["boot_$(NAME)" ] }

     e.g.

          {"RPC" => [qw( boot_rpcb rpcb_gettime getnetconfigent )],
           "NetconfigPtr" => [ 'DESTROY'] }

     Please see the ExtUtils/Mksymlists,
     documentation for more information about the DL_FUNCS, DL_VARS and
     FUNCLIST attributes.

DL_VARS
     Array of symbol names for variables to be made available as universal
     symbols.  Used only under AIX, OS/2, VMS and Win32 at present.
     Defaults to [].  (e.g. [ qw(Foo_version Foo_numstreams Foo_tree ) ])

EXCLUDE_EXT
     Array of extension names to exclude when doing a static build.  This
     is ignored if INCLUDE_EXT is present.  Consult INCLUDE_EXT for more
     details.  (e.g.  [ qw( Socket POSIX ) ] )

     This attribute may be most useful when specified as a string on the
     command line:  perl Makefile.PL EXCLUDE_EXT='Socket Safe'

EXE_FILES
     Ref to array of executable files. The files will be copied to the
     INST_SCRIPT directory. Make realclean will delete them from there
     again.

FIRST_MAKEFILE
     The name of the Makefile to be produced. Defaults to the contents of
     MAKEFILE, but can be overridden. This is used for the second Makefile
     that will be produced for the MAP_TARGET.

FULLPERL
     Perl binary able to run this extension.

FUNCLIST
     This provides an alternate means to specify function names to be
     exported from the extension.  Its value is a reference to an array of
     function names to be exported by the extension.  These names are
     passed through unaltered to the linker options file.

H
     Ref to array of *.h file names. Similar to C.

HTMLLIBPODS
     Hashref of .pm and .pod files.  MakeMaker will default this to all
     .pod and any .pm files that include POD directives.  The files listed
     here will be converted to HTML format and installed as was requested
     at Configure time.

HTMLSCRIPTPODS
     Hashref of pod-containing files.  MakeMaker will default this to all
     EXE_FILES files that include POD directives.  The files listed here
     will be converted to HTML format and installed as was requested at
     Configure time.

IMPORTS
     This attribute is used to specify names to be imported into the
     extension. It is only used on OS/2 and Win32.

INC
     Include file dirs eg: `"-I/usr/5include -I/path/to/inc"'

INCLUDE_EXT
     Array of extension names to be included when doing a static build.
     MakeMaker will normally build with all of the installed extensions
     when doing a static build, and that is usually the desired behavior.
     If INCLUDE_EXT is present then MakeMaker will build only with those
     extensions which are explicitly mentioned. (e.g.  [ qw( Socket POSIX
     ) ])

     It is not necessary to mention DynaLoader or the current extension
     when filling in INCLUDE_EXT.  If the INCLUDE_EXT is mentioned but is
     empty then only DynaLoader and the current extension will be included
     in the build.

     This attribute may be most useful when specified as a string on the
     command line:  perl Makefile.PL INCLUDE_EXT='POSIX Socket Devel::Peek'

INSTALLARCHLIB
     Used by 'make install', which copies files from INST_ARCHLIB to this
     directory if INSTALLDIRS is set to perl.

INSTALLBIN
     Directory to install binary files (e.g. tkperl) into.

INSTALLDIRS
     Determines which of the two sets of installation directories to
     choose: installprivlib and installarchlib versus installsitelib and
     installsitearch. The first pair is chosen with INSTALLDIRS=perl, the
     second with INSTALLDIRS=site. Default is site.

INSTALLHTMLPRIVLIBDIR
     This directory gets the HTML pages at 'make install' time. Defaults to
     $Config{installhtmlprivlibdir}.

INSTALLHTMLSCRIPTDIR
     This directory gets the HTML pages at 'make install' time. Defaults to
     $Config{installhtmlscriptdir}.

INSTALLHTMLSITELIBDIR
     This directory gets the HTML pages at 'make install' time. Defaults to
     $Config{installhtmlsitelibdir}.

INSTALLMAN1DIR
     This directory gets the man pages at 'make install' time. Defaults to
     $Config{installman1dir}.

INSTALLMAN3DIR
     This directory gets the man pages at 'make install' time. Defaults to
     $Config{installman3dir}.

INSTALLPRIVLIB
     Used by 'make install', which copies files from INST_LIB to this
     directory if INSTALLDIRS is set to perl.

INSTALLSCRIPT
     Used by 'make install' which copies files from INST_SCRIPT to this
     directory.

INSTALLSITEARCH
     Used by 'make install', which copies files from INST_ARCHLIB to this
     directory if INSTALLDIRS is set to site (default).

INSTALLSITELIB
     Used by 'make install', which copies files from INST_LIB to this
     directory if INSTALLDIRS is set to site (default).

INST_ARCHLIB
     Same as INST_LIB for architecture dependent files.

INST_BIN
     Directory to put real binary files during 'make'. These will be copied
     to INSTALLBIN during 'make install'

INST_EXE
     Old name for INST_SCRIPT. Deprecated. Please use INST_SCRIPT if you
     need to use it.

INST_LIB
     Directory where we put library files of this extension while building
     it.

INST_HTMLLIBDIR
     Directory to hold the man pages in HTML format at 'make' time

INST_HTMLSCRIPTDIR
     Directory to hold the man pages in HTML format at 'make' time

INST_MAN1DIR
     Directory to hold the man pages at 'make' time

INST_MAN3DIR
     Directory to hold the man pages at 'make' time

INST_SCRIPT
     Directory, where executable files should be installed during 'make'.
     Defaults to "./blib/script", just to have a dummy location during
     testing. make install will copy the files in INST_SCRIPT to
     INSTALLSCRIPT.

PERL_MALLOC_OK
     defaults to 0.  Should be set to TRUE if the extension can work with
     the memory allocation routines substituted by the Perl malloc()
     subsystem.  This should be applicable to most extensions with
     exceptions of those

        * with bugs in memory allocations which are caught by Perl's
          malloc();

        * which interact with the memory allocator in other ways than via
          malloc(), realloc(), free(), calloc(), sbrk() and brk();

        * which rely on special alignment which is not provided by Perl's
          malloc().

     *NOTE.*  Negligence to set this flag in *any one* of loaded extension
     nullifies many advantages of Perl's malloc(), such as better usage of
     system resources, error detection, memory usage reporting, catchable
     failure of memory allocations, etc.

LDFROM
     defaults to "$(OBJECT)" and is used in the ld command to specify what
     files to link/load from (also see dynamic_lib below for how to
     specify ld flags)

LIB
     LIB can only be set at `perl Makefile.PL' time. It has the effect of
     setting both INSTALLPRIVLIB and INSTALLSITELIB to that value
     regardless any

LIBPERL_A
     The filename of the perllibrary that will be used together with this
     extension. Defaults to libperl.a.

LIBS
     An anonymous array of alternative library specifications to be
     searched for (in order) until at least one library is found. E.g.

          'LIBS' => ["-lgdbm", "-ldbm -lfoo", "-L/path -ldbm.nfs"]

     Mind, that any element of the array contains a complete set of
     arguments for the ld command. So do not specify

          'LIBS' => ["-ltcl", "-ltk", "-lX11"]

     See ODBM_File/Makefile.PL for an example, where an array is needed. If
     you specify a scalar as in

          'LIBS' => "-ltcl -ltk -lX11"

     MakeMaker will turn it into an array with one element.

LINKTYPE
     'static' or 'dynamic' (default unless usedl=undef in config.sh).
     Should only be used to force static linking (also see linkext below).

MAKEAPERL
     Boolean which tells MakeMaker, that it should include the rules to
     make a perl. This is handled automatically as a switch by MakeMaker.
     The user normally does not need it.

MAKEFILE
     The name of the Makefile to be produced.

MAN1PODS
     Hashref of pod-containing files. MakeMaker will default this to all
     EXE_FILES files that include POD directives. The files listed here
     will be converted to man pages and installed as was requested at
     Configure time.

MAN3PODS
     Hashref of .pm and .pod files. MakeMaker will default this to all
     .pod and any .pm files that include POD directives. The files listed
     here will be converted to man pages and installed as was requested at
     Configure time.

MAP_TARGET
     If it is intended, that a new perl binary be produced, this variable
     may hold a name for that binary. Defaults to perl

MYEXTLIB
     If the extension links to a library that it builds set this to the
     name of the library (see SDBM_File)

NAME
     Perl module name for this extension (DBD::Oracle). This will default
     to the directory name but should be explicitly defined in the
     Makefile.PL.

NEEDS_LINKING
     MakeMaker will figure out if an extension contains linkable code
     anywhere down the directory tree, and will set this variable
     accordingly, but you can speed it up a very little bit if you define
     this boolean variable yourself.

NOECHO
     Defaults to `@'. By setting it to an empty string you can generate a
     Makefile that echos all commands. Mainly used in debugging MakeMaker
     itself.

NORECURS
     Boolean.  Attribute to inhibit descending into subdirectories.

NO_VC
     In general, any generated Makefile checks for the current version of
     MakeMaker and the version the Makefile was built under. If NO_VC is
     set, the version check is neglected. Do not write this into your
     Makefile.PL, use it interactively instead.

OBJECT
     List of object files, defaults to '$(BASEEXT)$(OBJ_EXT)', but can be
     a long string containing all object files, e.g. "tkpBind.o
     tkpButton.o tkpCanvas.o"

OPTIMIZE
     Defaults to -O. Set it to -g to turn debugging on. The flag is passed
     to subdirectory makes.

PERL
     Perl binary for tasks that can be done by miniperl

PERLMAINCC
     The call to the program that is able to compile perlmain.c. Defaults
     to $(CC).

PERL_ARCHLIB
     Same as above for architecture dependent files.

PERL_LIB
     Directory containing the Perl library to use.

PERL_SRC
     Directory containing the Perl source code (use of this should be
     avoided, it may be undefined)

PERM_RW
     Desired permission for read/writable files. Defaults to `644'.  See
     also `MM_Unix' in this node.

PERM_RWX
     Desired permission for executable files. Defaults to `755'.  See also
     `MM_Unix' in this node.

PL_FILES
     Ref to hash of files to be processed as perl programs. MakeMaker will
     default to any found *.PL file (except Makefile.PL) being keys and
     the basename of the file being the value. E.g.

          {'foobar.PL' => 'foobar'}

     The *.PL files are expected to produce output to the target files
     themselves. If multiple files can be generated from the same *.PL
     file then the value in the hash can be a reference to an array of
     target file names. E.g.

          {'foobar.PL' => ['foobar1','foobar2']}

PM
     Hashref of .pm files and *.pl files to be installed.  e.g.

          {'name_of_file.pm' => '$(INST_LIBDIR)/install_as.pm'}

     By default this will include *.pm and *.pl and the files found in the
     PMLIBDIRS directories.  Defining PM in the Makefile.PL will override
     PMLIBDIRS.

PMLIBDIRS
     Ref to array of subdirectories containing library files.  Defaults to
     [ 'lib', $(BASEEXT) ]. The directories will be scanned and any files
     they contain will be installed in the corresponding location in the
     library.  A libscan() method can be used to alter the behaviour.
     Defining PM in the Makefile.PL will override PMLIBDIRS.

POLLUTE
     Release 5.005 grandfathered old global symbol names by providing
     preprocessor macros for extension source compatibility.  As of
     release 5.6, these preprocessor definitions are not available by
     default.  The POLLUTE flag specifies that the old names should still
     be defined:

          perl Makefile.PL POLLUTE=1

     Please inform the module author if this is necessary to successfully
     install a module under 5.6 or later.

PPM_INSTALL_EXEC
     Name of the executable used to run PPM_INSTALL_SCRIPT below. (e.g.
     perl)

PPM_INSTALL_SCRIPT
     Name of the script that gets executed by the Perl Package Manager
     after the installation of a package.

PREFIX
     Can be used to set the three INSTALL* attributes in one go (except for
     probably INSTALLMAN1DIR, if it is not below PREFIX according to
     %Config).  They will have PREFIX as a common directory node and will
     branch from that node into lib/, lib/ARCHNAME or whatever Configure
     decided at the build time of your perl (unless you override one of
     them, of course).

PREREQ_PM
     Hashref: Names of modules that need to be available to run this
     extension (e.g. Fcntl for SDBM_File) are the keys of the hash and the
     desired version is the value. If the required version number is 0, we
     only check if any version is installed already.

SKIP
     Arryref. E.g. [qw(name1 name2)] skip (do not write) sections of the
     Makefile. Caution! Do not use the SKIP attribute for the negligible
     speedup. It may seriously damage the resulting Makefile. Only use it
     if you really need it.

TYPEMAPS
     Ref to array of typemap file names.  Use this when the typemaps are
     in some directory other than the current directory or when they are
     not named *typemap*.  The last typemap in the list takes precedence.
     A typemap in the current directory has highest precedence, even if it
     isn't listed in TYPEMAPS.  The default system typemap has lowest
     precedence.

VERSION
     Your version number for distributing the package.  This defaults to
     0.1.

VERSION_FROM
     Instead of specifying the VERSION in the Makefile.PL you can let
     MakeMaker parse a file to determine the version number. The parsing
     routine requires that the file named by VERSION_FROM contains one
     single line to compute the version number. The first line in the file
     that contains the regular expression

          /([\$*])(([\w\:\']*)\bVERSION)\b.*\=/

     will be evaluated with eval() and the value of the named variable
     after the eval() will be assigned to the VERSION attribute of the
     MakeMaker object. The following lines will be parsed o.k.:

          $VERSION = '1.00';
          *VERSION = \'1.01';
          ( $VERSION ) = '$Revision: 1.222 $ ' =~ /\$Revision:\s+([^\s]+)/;
          $FOO::VERSION = '1.10';
          *FOO::VERSION = \'1.11';

     but these will fail:

          my $VERSION = '1.01';
          local $VERSION = '1.02';
          local $FOO::VERSION = '1.30';

     The file named in VERSION_FROM is not added as a dependency to
     Makefile. This is not really correct, but it would be a major pain
     during development to have to rewrite the Makefile for any smallish
     change in that file. If you want to make sure that the Makefile
     contains the correct VERSION macro after any change of the file, you
     would have to do something like

          depend => { Makefile => '$(VERSION_FROM)' }

     See attribute depend below.

XS
     Hashref of .xs files. MakeMaker will default this.  e.g.

          {'name_of_file.xs' => 'name_of_file.c'}

     The .c files will automatically be included in the list of files
     deleted by a make clean.

XSOPT
     String of options to pass to xsubpp.  This might include `-C++' or
     `-extern'.  Do not include typemaps here; the TYPEMAP parameter
     exists for that purpose.

XSPROTOARG
     May be set to an empty string, which is identical to `-prototypes', or
     `-noprototypes'. See the xsubpp documentation for details. MakeMaker
     defaults to the empty string.

XS_VERSION
     Your version number for the .xs file of this package.  This defaults
     to the value of the VERSION attribute.

Additional lowercase attributes
-------------------------------

   can be used to pass parameters to the methods which implement that part
of the Makefile.

clean
          {FILES => "*.xyz foo"}

depend
          {ANY_TARGET => ANY_DEPENDECY, ...}

dist
          {TARFLAGS => 'cvfF', COMPRESS => 'gzip', SUFFIX => '.gz',
          SHAR => 'shar -m', DIST_CP => 'ln', ZIP => '/bin/zip',
          ZIPFLAGS => '-rl', DIST_DEFAULT => 'private tardist' }

     If you specify COMPRESS, then SUFFIX should also be altered, as it is
     needed to tell make the target file of the compression. Setting
     DIST_CP to ln can be useful, if you need to preserve the timestamps on
     your files. DIST_CP can take the values 'cp', which copies the file,
     'ln', which links the file, and 'best' which copies symbolic links and
     links the rest. Default is 'best'.

dynamic_lib
          {ARMAYBE => 'ar', OTHERLDFLAGS => '...', INST_DYNAMIC_DEP => '...'}

linkext
          {LINKTYPE => 'static', 'dynamic' or ''}

     NB: Extensions that have nothing but *.pm files had to say

          {LINKTYPE => ''}

     with Pre-5.0 MakeMakers. Since version 5.00 of MakeMaker such a line
     can be deleted safely. MakeMaker recognizes when there's nothing to
     be linked.

macro
          {ANY_MACRO => ANY_VALUE, ...}

realclean
          {FILES => '$(INST_ARCHAUTODIR)/*.xyz'}

test
          {TESTS => 't/*.t'}

tool_autosplit
          {MAXLEN => 8}

Overriding MakeMaker Methods
----------------------------

   If you cannot achieve the desired Makefile behaviour by specifying
attributes you may define private subroutines in the Makefile.PL.  Each
subroutines returns the text it wishes to have written to the Makefile. To
override a section of the Makefile you can either say:

     sub MY::c_o { "new literal text" }

   or you can edit the default by saying something like:

     sub MY::c_o {
         package MY;	# so that "SUPER" works right
         my $inherited = shift->SUPER::c_o(@_);
         $inherited =~ s/old text/new text/;
         $inherited;
     }

   If you are running experiments with embedding perl as a library into
other applications, you might find MakeMaker is not sufficient. You'd
better have a look at ExtUtils::Embed which is a collection of utilities
for embedding.

   If you still need a different solution, try to develop another
subroutine that fits your needs and submit the diffs to
`perl5-porters@perl.org' or `comp.lang.perl.moderated' as appropriate.

   For a complete description of all MakeMaker methods see
ExtUtils/MM_Unix.

   Here is a simple example of how to add a new target to the generated
Makefile:

     sub MY::postamble {
     	'
     $(MYEXTLIB): sdbm/Makefile
     	    cd sdbm && $(MAKE) all
     ';
     }

Hintsfile support
-----------------

   MakeMaker.pm uses the architecture specific information from Config.pm.
In addition it evaluates architecture specific hints files in a `hints/'
directory. The hints files are expected to be named like their
counterparts in `PERL_SRC/hints', but with an `.pl' file name extension
(eg. `next_3_2.pl'). They are simply evaled by MakeMaker within the
WriteMakefile() subroutine, and can be used to execute commands as well as
to include special variables. The rules which hintsfile is chosen are the
same as in Configure.

   The hintsfile is eval()ed immediately after the arguments given to
WriteMakefile are stuffed into a hash reference $self but before this
reference becomes blessed. So if you want to do the equivalent to override
or create an attribute you would say something like

     $self->{LIBS} = ['-ldbm -lucb -lc'];

Distribution Support
--------------------

   For authors of extensions MakeMaker provides several Makefile targets.
Most of the support comes from the ExtUtils::Manifest module, where
additional documentation can be found.

make distcheck
     reports which files are below the build directory but not in the
     MANIFEST file and vice versa. (See ExtUtils::Manifest::fullcheck() for
     details)

make skipcheck
     reports which files are skipped due to the entries in the
     MANIFEST.SKIP file (See ExtUtils::Manifest::skipcheck() for details)

make distclean
     does a realclean first and then the distcheck. Note that this is not
     needed to build a new distribution as long as you are sure that the
     MANIFEST file is ok.

make manifest
     rewrites the MANIFEST file, adding all remaining files found (See
     ExtUtils::Manifest::mkmanifest() for details)

make distdir
     Copies all the files that are in the MANIFEST file to a newly created
     directory with the name `$(DISTNAME)-$(VERSION)'. If that directory
     exists, it will be removed first.

make disttest
     Makes a distdir first, and runs a `perl Makefile.PL', a make, and a
     make test in that directory.

make tardist
     First does a distdir. Then a command $(PREOP) which defaults to a null
     command, followed by $(TOUNIX), which defaults to a null command under
     UNIX, and will convert files in distribution directory to UNIX format
     otherwise. Next it runs `tar' on that directory into a tarfile and
     deletes the directory. Finishes with a command $(POSTOP) which
     defaults to a null command.

make dist
     Defaults to $(DIST_DEFAULT) which in turn defaults to tardist.

make uutardist
     Runs a tardist first and uuencodes the tarfile.

make shdist
     First does a distdir. Then a command $(PREOP) which defaults to a null
     command. Next it runs `shar' on that directory into a sharfile and
     deletes the intermediate directory again. Finishes with a command
     $(POSTOP) which defaults to a null command.  Note: For shdist to work
     properly a `shar' program that can handle directories is mandatory.

make zipdist
     First does a distdir. Then a command $(PREOP) which defaults to a null
     command. Runs `$(ZIP) $(ZIPFLAGS)' on that directory into a zipfile.
     Then deletes that directory. Finishes with a command $(POSTOP) which
     defaults to a null command.

make ci
     Does a $(CI) and a $(RCS_LABEL) on all files in the MANIFEST file.

   Customization of the dist targets can be done by specifying a hash
reference to the dist attribute of the WriteMakefile call. The following
parameters are recognized:

     CI           ('ci -u')
     COMPRESS     ('gzip --best')
     POSTOP       ('@ :')
     PREOP        ('@ :')
     TO_UNIX      (depends on the system)
     RCS_LABEL    ('rcs -q -Nv$(VERSION_SYM):')
     SHAR         ('shar')
     SUFFIX       ('.gz')
     TAR          ('tar')
     TARFLAGS     ('cvf')
     ZIP          ('zip')
     ZIPFLAGS     ('-r')

   An example:

     WriteMakefile( 'dist' => { COMPRESS=>"bzip2", SUFFIX=>".bz2" })

Disabling an extension
----------------------

   If some events detected in Makefile.PL imply that there is no way to
create the Module, but this is a normal state of things, then you can
create a `Makefile' which does nothing, but succeeds on all the "usual"
build targets.  To do so, use

     ExtUtils::MakeMaker::WriteEmptyMakefile();

   instead of WriteMakefile().

   This may be useful if other modules expect this module to be *built*
OK, as opposed to *work* OK (say, this system-dependent module builds in a
subdirectory of some other distribution, or is listed as a dependency in a
CPAN::Bundle, but the functionality is supported by different means on the
current architecture).

ENVIRONMENT
===========

PERL_MM_OPT
     Command line options used by `MakeMaker->new()', and thus by
     `WriteMakefile()'.  The string is split on whitespace, and the result
     is processed before any actual command line arguments are processed.

SEE ALSO
========

   ExtUtils::MM_Unix, ExtUtils::Manifest, ExtUtils::testlib,
ExtUtils::Install, ExtUtils::Embed

AUTHORS
=======

   Andy Dougherty <`doughera@lafcol.lafayette.edu'>, Andreas KE<ouml>nig
<`A.Koenig@franz.ww.TU-Berlin.DE'>, Tim Bunce <`Tim.Bunce@ig.co.uk'>.  VMS
support by Charles Bailey <`bailey@newman.upenn.edu'>.  OS/2 support by
Ilya Zakharevich <`ilya@math.ohio-state.edu'>.  Contact the makemaker
mailing list `mailto:makemaker@franz.ww.tu-berlin.de', if you have any
questions.

utilities to write and check a MANIFEST file
********************************************

NAME
====

   ExtUtils::Manifest - utilities to write and check a MANIFEST file

SYNOPSIS
========

     require ExtUtils::Manifest;

     ExtUtils::Manifest::mkmanifest;

     ExtUtils::Manifest::manicheck;

     ExtUtils::Manifest::filecheck;

     ExtUtils::Manifest::fullcheck;

     ExtUtils::Manifest::skipcheck;

     ExtUtils::Manifest::manifind();

     ExtUtils::Manifest::maniread($file);

     ExtUtils::Manifest::manicopy($read,$target,$how);

DESCRIPTION
===========

   mkmanifest() writes all files in and below the current directory to a
file named in the global variable $ExtUtils::Manifest::MANIFEST (which
defaults to MANIFEST) in the current directory. It works similar to

     find . -print

   but in doing so checks each line in an existing MANIFEST file and
includes any comments that are found in the existing MANIFEST file in the
new one. Anything between white space and an end of line within a MANIFEST
file is considered to be a comment. Filenames and comments are separated
by one or more TAB characters in the output. All files that match any
regular expression in a file MANIFEST.SKIP (if such a file exists) are
ignored.

   manicheck() checks if all the files within a MANIFEST in the current
directory really do exist. It only reports discrepancies and exits
silently if MANIFEST and the tree below the current directory are in sync.

   filecheck() finds files below the current directory that are not
mentioned in the MANIFEST file. An optional file MANIFEST.SKIP will be
consulted. Any file matching a regular expression in such a file will not
be reported as missing in the MANIFEST file.

   fullcheck() does both a manicheck() and a filecheck().

   skipcheck() lists all the files that are skipped due to your
MANIFEST.SKIP file.

   manifind() returns a hash reference. The keys of the hash are the files
found below the current directory.

   maniread($file) reads a named MANIFEST file (defaults to MANIFEST in
the current directory) and returns a HASH reference with files being the
keys and comments being the values of the HASH.  Blank lines and lines
which start with `#' in the MANIFEST file are discarded.

   `manicopy($read,$target,$how)' copies the files that are the keys in
the HASH *%$read* to the named target directory. The HASH reference $read
is typically returned by the maniread() function. This function is useful
for producing a directory tree identical to the intended distribution
tree. The third parameter $how can be used to specify a different methods
of "copying". Valid values are cp, which actually copies the files, `ln'
which creates hard links, and best which mostly links the files but copies
any symbolic link to make a tree without any symbolic link. Best is the
default.

MANIFEST.SKIP
=============

   The file MANIFEST.SKIP may contain regular expressions of files that
should be ignored by mkmanifest() and filecheck(). The regular expressions
should appear one on each line. Blank lines and lines which start with `#'
are skipped.  Use `\#' if you need a regular expression to start with a
sharp character. A typical example:

     \bRCS\b
     ^MANIFEST\.
     ^Makefile$
     ~$
     \.html$
     \.old$
     ^blib/
     ^MakeMaker-\d

EXPORT_OK
=========

   `&mkmanifest', `&manicheck', `&filecheck', `&fullcheck', `&maniread',
and `&manicopy' are exportable.

GLOBAL VARIABLES
================

   `$ExtUtils::Manifest::MANIFEST' defaults to MANIFEST. Changing it
results in both a different MANIFEST and a different MANIFEST.SKIP file.
This is useful if you want to maintain different distributions for
different audiences (say a user version and a developer version including
RCS).

   `$ExtUtils::Manifest::Quiet' defaults to 0. If set to a true value, all
functions act silently.

DIAGNOSTICS
===========

   All diagnostic output is sent to `STDERR'.

`Not in MANIFEST:' file
     is reported if a file is found, that is missing in the MANIFEST file
     which is excluded by a regular expression in the file MANIFEST.SKIP.

`No such file:' file
     is reported if a file mentioned in a MANIFEST file does not exist.

`MANIFEST:' $!
     is reported if MANIFEST could not be opened.

`Added to MANIFEST:' file
     is reported by mkmanifest() if $Verbose is set and a file is added to
     MANIFEST. $Verbose is set to 1 by default.

SEE ALSO
========

   See ExtUtils/MakeMaker, which has handy targets
for most of the functionality.

AUTHOR
======

   Andreas Koenig <`koenig@franz.ww.TU-Berlin.DE'>

write the C code for perlmain.c
*******************************

NAME
====

   ExtUtils::Miniperl, writemain - write the C code for perlmain.c

SYNOPSIS
========

   `use ExtUtils::Miniperl;'

   `writemain(@directories);'

DESCRIPTION
===========

   This whole module is written when perl itself is built from a script
called minimod.PL. In case you want to patch it, please patch minimod.PL
in the perl distribution instead.

   writemain() takes an argument list of directories containing archive
libraries that relate to perl modules and should be linked into a new perl
binary. It writes to STDOUT a corresponding perlmain.c file that is a
plain C file containing all the bootstrap code to make the modules
associated with the libraries available from within perl.

   The typical usage is from within a Makefile generated by
ExtUtils::MakeMaker. So under normal circumstances you won't have to deal
with this module directly.

SEE ALSO
========

   See ExtUtils/MakeMaker,

make a bootstrap file for use by DynaLoader
*******************************************

NAME
====

   ExtUtils::Mkbootstrap - make a bootstrap file for use by DynaLoader

SYNOPSIS
========

   `mkbootstrap'

DESCRIPTION
===========

   Mkbootstrap typically gets called from an extension Makefile.

   There is no `*.bs' file supplied with the extension. Instead, there may
be a `*_BS' file which has code for the special cases, like posix for
berkeley db on the NeXT.

   This file will get parsed, and produce a maybe empty
`@DynaLoader::dl_resolve_using' array for the current architecture.  That
will be extended by $BSLOADLIBS, which was computed by
ExtUtils::Liblist::ext(). If this array still is empty, we do nothing,
else we write a .bs file with an `@DynaLoader::dl_resolve_using' array.

   The `*_BS' file can put some code into the generated `*.bs' file by
placing it in `$bscode'. This is a handy 'escape' mechanism that may prove
useful in complex situations.

   If @DynaLoader::dl_resolve_using contains `-L*' or `-l*' entries then
Mkbootstrap will automatically add a dl_findfile() call to the generated
`*.bs' file.

write linker options files for dynamic extension
************************************************

NAME
====

   ExtUtils::Mksymlists - write linker options files for dynamic extension

SYNOPSIS
========

     use ExtUtils::Mksymlists;
     Mksymlists({ NAME     => $name ,
                  DL_VARS  => [ $var1, $var2, $var3 ],
                  DL_FUNCS => { $pkg1 => [ $func1, $func2 ],
                                $pkg2 => [ $func3 ] });

DESCRIPTION
===========

   ExtUtils::Mksymlists produces files used by the linker under some OSs
during the creation of shared libraries for dynamic extensions.  It is
normally called from a MakeMaker-generated Makefile when the extension is
built.  The linker option file is generated by calling the function
`Mksymlists', which is exported by default from ExtUtils::Mksymlists.  It
takes one argument, a list of key-value pairs, in which the following keys
are recognized:

DLBASE
     This item specifies the name by which the linker knows the extension,
     which may be different from the name of the extension itself (for
     instance, some linkers add an '_' to the name of the extension).  If
     it is not specified, it is derived from the NAME attribute.  It is
     presently used only by OS2 and Win32.

DL_FUNCS
     This is identical to the DL_FUNCS attribute available via MakeMaker,
     from which it is usually taken.  Its value is a reference to an
     associative array, in which each key is the name of a package, and
     each value is an a reference to an array of function names which
     should be exported by the extension.  For instance, one might say
     `DL_FUNCS => { Homer::Iliad => [ qw(trojans greeks) ], Homer::Odyssey
     => [ qw(travellers family suitors) ] }'.  The function names should
     be identical to those in the XSUB code; `Mksymlists' will alter the
     names written to the linker option file to match the changes made by
     xsubpp.  In addition, if none of the functions in a list begin with
     the string *boot_*, `Mksymlists' will add a bootstrap function for
     that package, just as xsubpp does.  (If a *boot_<pkg>* function is
     present in the list, it is passed through unchanged.)  If DL_FUNCS is
     not specified, it defaults to the bootstrap function for the
     extension specified in NAME.

DL_VARS
     This is identical to the DL_VARS attribute available via MakeMaker,
     and, like DL_FUNCS, it is usually specified via MakeMaker.  Its value
     is a reference to an array of variable names which should be exported
     by the extension.

FILE
     This key can be used to specify the name of the linker option file
     (minus the OS-specific extension), if for some reason you do not want
     to use the default value, which is the last word of the NAME
     attribute (*e.g.* for `Tk::Canvas', FILE defaults to Canvas).

FUNCLIST
     This provides an alternate means to specify function names to be
     exported from the extension.  Its value is a reference to an array of
     function names to be exported by the extension.  These names are
     passed through unaltered to the linker options file.  Specifying a
     value for the FUNCLIST attribute suppresses automatic generation of
     the bootstrap function for the package. To still create the bootstrap
     name you have to specify the package name in the DL_FUNCS hash:

          Mksymlists({ NAME     => $name ,
          		 FUNCLIST => [ $func1, $func2 ],
                       DL_FUNCS => { $pkg => [] } });

IMPORTS
     This attribute is used to specify names to be imported into the
     extension. It is currently only used by OS/2 and Win32.

NAME
     This gives the name of the extension (*e.g.* `Tk::Canvas') for which
     the linker option file will be produced.

   When calling `Mksymlists', one should always specify the NAME
attribute.  In most cases, this is all that's necessary.  In the case of
unusual extensions, however, the other attributes can be used to provide
additional information to the linker.

AUTHOR
======

   Charles Bailey *<bailey@newman.upenn.edu>*

REVISION
========

   Last revised 14-Feb-1996, for Perl 5.002.

manage .packlist files
**********************

NAME
====

   ExtUtils::Packlist - manage .packlist files

SYNOPSIS
========

     use ExtUtils::Packlist;
     my ($pl) = ExtUtils::Packlist->new('.packlist');
     $pl->read('/an/old/.packlist');
     my @missing_files = $pl->validate();
     $pl->write('/a/new/.packlist');

     $pl->{'/some/file/name'}++;
        or
     $pl->{'/some/other/file/name'} = { type => 'file',
                                        from => '/some/file' };

DESCRIPTION
===========

   ExtUtils::Packlist provides a standard way to manage .packlist files.
Functions are provided to read and write .packlist files.  The original
.packlist format is a simple list of absolute pathnames, one per line.  In
addition, this package supports an extended format, where as well as a
filename each line may contain a list of attributes in the form of a space
separated list of key=value pairs.  This is used by the installperl script
to differentiate between files and links, for example.

USAGE
=====

   The hash reference returned by the new() function can be used to
examine and modify the contents of the .packlist.  Items may be
added/deleted from the .packlist by modifying the hash.  If the value
associated with a hash key is a scalar, the entry written to the .packlist
by any subsequent write() will be a simple filename.  If the value is a
hash, the entry written will be the filename followed by the key=value
pairs from the hash.  Reading back the .packlist will recreate the
original entries.

FUNCTIONS
=========

new()
     This takes an optional parameter, the name of a .packlist.  If the
     file exists, it will be opened and the contents of the file will be
     read.  The new() method returns a reference to a hash.  This hash
     holds an entry for each line in the .packlist.  In the case of
     old-style .packlists, the value associated with each key is undef.
     In the case of new-style .packlists, the value associated with each
     key is a hash containing the key=value pairs following the filename
     in the .packlist.

read()
     This takes an optional parameter, the name of the .packlist to be
     read.  If no file is specified, the .packlist specified to new() will
     be read.  If the .packlist does not exist, Carp::croak will be called.

write()
     This takes an optional parameter, the name of the .packlist to be
     written.  If no file is specified, the .packlist specified to new()
     will be overwritten.

validate()
     This checks that every file listed in the .packlist actually exists.
     If an argument which evaluates to true is given, any missing files
     will be removed from the internal hash.  The return value is a list
     of the missing files, which will be empty if they all exist.

packlist_file()
     This returns the name of the associated .packlist file

EXAMPLE
=======

   Here's `modrm', a little utility to cleanly remove an installed module.

     #!/usr/local/bin/perl -w

     use strict;
     use IO::Dir;
     use ExtUtils::Packlist;
     use ExtUtils::Installed;

     sub emptydir($) {
     	my ($dir) = @_;
     	my $dh = IO::Dir->new($dir) || return(0);
     	my @count = $dh->read();
     	$dh->close();
     	return(@count == 2 ? 1 : 0);
     }

     # Find all the installed packages
     print("Finding all installed modules...\n");
     my $installed = ExtUtils::Installed->new();

     foreach my $module (grep(!/^Perl$/, $installed->modules())) {
        my $version = $installed->version($module) || "???";
        print("Found module $module Version $version\n");
        print("Do you want to delete $module? [n] ");
        my $r = <STDIN>; chomp($r);
        if ($r && $r =~ /^y/i) {
     	  # Remove all the files
     	  foreach my $file (sort($installed->files($module))) {
     	     print("rm $file\n");
     	     unlink($file);
     	  }
     	  my $pf = $installed->packlist($module)->packlist_file();
     	  print("rm $pf\n");
     	  unlink($pf);
     	  foreach my $dir (sort($installed->directory_tree($module))) {
     	     if (emptydir($dir)) {
     		print("rmdir $dir\n");
     		rmdir($dir);
     	     }
     	  }
        }
     }

AUTHOR
======

   Alan Burlison <Alan.Burlison@uk.sun.com>

A Perl Preprocessor
*******************

NAME
====

   ExtUtils::PerlPP - A Perl Preprocessor

SYNOPSIS
========

     use ExtUtils::PerlPP;
     my $config = { 'version' => $VERSION,
     		   'driver' => $DRIVER };

     # The long and winding road ...
     my $self = ExtUtils::PerlPP->new();

     $self->{'in_fh'} = IO::File->new('file.PL', 'r');
     $self->{'out_fh'} = IO::File->new('file', 'w');
     $self->{'config'} =

     $self->parse();

     # And now a short cut for the same:
     ppp('file.PL', 'file', $config);

DESCRIPTION
===========

   Perl's installation suite, ExtUtils::MakeMaker, contains a mechanism for
installing preparsed files, so-called *PL* files: If the MakeMaker utility
detects files with the extension `.PL' then these files are executed by
make, usually creating a file of the same name, except the `.PL' extension.

   Writing these PL files is usually always the same, for example a typical
`.PL' file might look like this:

     my $script = <<'SCRIPT';
     ... # True file following here
     SCRIPT

     # Modify variable $script, depending on configuration, local
     # site or whatever
     ...

     if (!open(FILE, ">file")  ||  !(print FILE $script)  ||
     	!close(FILE)) {
     	die "Cannot write file: $!";
     }

   But in essence, what else is this than a Perl preprocessor?

   Traditionally you have to write such a Perl preprocessor for yourself
all the time, although I have found that they always do the same, for
example:

-
     Fix defaults, for example installation paths.

-
     Including or excluding code sections. It is a matter of taste whether
     one likes to see

          if ($] < 5.003) {
          	# Thirty lines of code following here
              ...
          } else {
              # A single line of code
              ...
          }

     when already using Perl 5.005. I don't.

   This module is dedicated to simplify such tasks. In short, you can use
it like this:

Create a new preprocessor
-------------------------

   You start with creating an instance of *ExtUtils::PerlPP* by calling
the new constructor:

     my $ppp = ExtUtils::PerlPP->new(%attr);

   The constructor accepts a list of attributes, including the following:

in_fh
     The input file, any kind of IO object, for example an instance of
     IO::File or IO::Scalar. More general: It can be any object that offers
     a getline method.

     A scalar value (to be distinguished from an IO::Scalar instance!) will
     be interpreted as a file name that the method opens for you.

out_fh
     The output file; another IO object or any other object that offers a
     print method. A scalar value is accepted as output file name.

config
     A hash ref of preprocessor variables. In other words

          $ppp->{'config'}->{'var'} = 1;

     is what `-Dvar=val' is for the C preprocessor. Similarly you can
     compare

          delete $ppp->{'config'};

     with `-Uvar'. See `"Macro replacements"' in this node below. Unlike
     C, variables may be arbitrarily complex, in particular you can use
     hash or array refs as values.

     Surprisingly you may pass a scalar value again: In that case the file
     of the same name evaluated and the result is used as a configuration
     hash.  In other words

          $ppp->{'config'} = "myapp.cfg";

     is similar to

          $ppp->{'config'} = do "myapp.cfg";

     Such config files can easily be created using the Data::Dumper module.
     `Data::Dumper(3)' in this node.

no_config_default
     If a variable name is used, but no such attribute is present in the
     config hash, then by default the variable is looked up in the
     `$Config' from the Config module. This behaviour is suppressed, if
     you set no_config_default to a TRUE value. `Config(3)' in this node.

no_makedirs
     By default directories are created silently if required. For example,
     if you pass a value of `/usr/local/foo/bar' as output file and only
     `/usr/local' exists, then the subdirectory foo will be created.  The
     option no_makedirs suppresses this behaviour.

Running the preprocessor
------------------------

   This is done by executing

     $ppp->parse();

   A Perl exception will be thrown in case of errors, thus the complete
use might look like this:

     eval { $ppp->parse(); };
     if ($@) { print "An error occurred: $@\n" }

Using the frontend
------------------

   Most applications won't call the new or parse methods directly, but
rather do a

     use ExtUtils::PerlPP;
     ppp('infile', 'outfile', 'configfile');

   This is equivalent to

     my $parser = ExtUtils::PerlPP->new('in_fh' => 'infile',
     				       'out_fh' => 'outfile',
                                        'config' => 'configfile');
     $parser->parse();

   In order to be easily used within Makefiles, the ppp frontend can read
from @ARGV. That is, you can use the module like this:

     perl -MExtUtils::PerlPP -e ppp <infile> <outfile> <configfile>

   from the commandline.

Macro replacements
------------------

   The primary use of preprocessor variables (aka attributes of
`$ppp-'{'config'}>) is replacing patterns in the stream written to the
output file. With `$c = $ppp-'{'config'}> in mind the typical patterns and
their replacements are:

     ~~a~~		$c->{'a'}
     ~~b~~		$c->{'b'}
     ~~a->b~~		$c->{'a'}->{'b'}
     ~~a->e~~		$c->{'a'}->{'e'}
     ~~a->1~~		$c->{'a'}->[1]
     ~~a->1->b~~         $c->{'a'}->[1]->{'b'}

   I hope the idea is obvious. Real world examples might be:

     my $config_file = "~~etc_dir~~/configuration";
     my $VERSION = "~~version~~";

   Preprocessor variables need not be scalar values: If a variable
contains a code ref, then the module will execute

     &$var($ppp, $text);

   and replace the pattern with the result. $text is the pattern being
replaced, for example, if `$ppp-'{'config'}->{'bar'}> has the value
`\&foo', then `~~bar~~' will be replaced with the result of

     foo($ppp, "bar");

   Arguments are not yet supported.

Creating macros
---------------

   When talking about code refs, we need a possibility to create them.
The best possibility is creating them within the input file, as in

     ~&foo&~ my($self, $text) = @_; $text x 2; ~&&~

   This example is mainly equivalent to

     $ppp->{'config'}->{'foo'} = sub {
         my($self, $text) = @_; $text x 2;
     };

   The `~&var&~' definition must start at the beginning of a line, much
like the C preprocessor. The end pattern ~&&~ may appear at any point, but
the remaining line will be ignored.

Conditional output
------------------

   The next application of a preprocessor is conditional output, as in an

     #ifdef var
     ...
     #endif

   segment. This can be done with

     ~#if#~ <expression>
     ...
     ~#elsif#~ <expression>
     ...
     ~#else#~
     ...
     ~#endif#~

   `<expression>' is handled as follows: First it is subject to the usual
pattern replacements and then it is evaluated as a Perl expression
returning a TRUE or FALSE value. Examples:

     ~#if#~ "~~a~~"

   is TRUE, if and only if $ppp->{'config'}->{'a'} is TRUE.

   Currently conditionals must start at the beginning of a line and
expressions must not exceed a single line. Nesting conditions is possible.

Embedding into MakeMaker
------------------------

   For using the preprocessor from within MakeMaker, I propose the
following: First of all you create a config file from within Makefile.PL.
For example the *libnet* suite creates a file `libnet.cfg' and the
*SNMP::Monitor* and *Cisco::Conf* modules create a file `configuration'.
The Data::Dumper module will aid you in that task. `Data::Dumper(3)' in
this node.

   Then you add the following to your Makefile.PL, I assume the name
`myapp.cnf' for the config file:

     package MY;

     sub processPL {
         my($self) = shift;
         return "" unless $self->{PL_FILES};
         my(@m, $from, $to);
         foreach $from (sort keys %{$self->{PL_FILES}}) {
     	    $to = $self->{PL_FILES}->{$from};
     	    push @m, "
     all :: $self->{PL_FILES}->{$plfile}
     	    $self->{NOECHO}\$(NOOP)

     $self->{PL_FILES}->{$plfile} :: $plfile
             \$(PERL) -I\$(INST_ARCHLIB) -I\$(INST_LIB) \
                     -I\$(PERL_ARCHLIB) -I\$(PERL_LIB) \
                     -MExtUtils::PerlPP -e 'ppp($from, $to, \"myapp.cnf\")'
     ";
         }
         join "", @m;
     }

   Next you create your template files under their usual names, but add an
extension `.PL'. The MakeMaker utility will automatically detect these
files for you and add appropriate rules to the Makefile it generates.

AUTHOR AND COPYRIGHT
====================

   This module is Copyright (C) 1998 by

     Jochen Wiedmann
     Am Eisteich 9
     72555 Metzingen
     Germany

     Email: joe@ispsoft.de
     Phone: +49 7123 14887

   All rights reserved.

   You may distribute this module under the terms of either the GNU
General Public License or the Artistic License, as specified in the Perl
README file.

SEE ALSO
========

   `ExtUtils::MakeMaker(3)' in this node, `Data::Dumper(3)' in this node

a "skeleton" for writing "t/*.t" test files.
********************************************

NAME
====

   ExtUtils::TBone - a "skeleton" for writing "t/*.t" test files.

SYNOPSIS
========

   Include a copy of this module in your t directory (as
t/ExtUtils/TBone.pm), and then write your t/*.t files like this:

     use lib "./t";             # to pick up a ExtUtils::TBone
     use ExtUtils::TBone;

     # Make a tester... here are 3 different alternatives:
     my $T = typical ExtUtils::TBone;                 # standard log
     my $T = new ExtUtils::TBone;                     # no log
     my $T = new ExtUtils::TBone "testout/Foo.tlog";  # explicit log

     # Begin testing, and expect 3 tests in all:
     $T->begin(3);                           # expect 3 tests
     $T->msg("Something for the log file");  # message for the log

     # Run some tests:
     $T->ok($this);                  # test 1: no real info logged
     $T->ok($that,                   # test 2: logs a comment
     	   "Is that ok, or isn't it?");
     $T->ok(($this eq $that),        # test 3: logs comment + vars
     	   "Do they match?",
     	   This => $this,
     	   That => $that);

     # That last one could have also been written...
     $T->ok_eq($this, $that);            # does 'eq' and logs operands
     $T->ok_eqnum($this, $that);         # does '==' and logs operands

     # End testing:
     $T->end;

DESCRIPTION
===========

   This module is intended for folks who release CPAN modules with "t/*.t"
tests.  It makes it easy for you to output syntactically correct
test-output while at the same time logging all test activity to a log
file.  Hopefully, bug reports which include the contents of this file will
be easier for you to investigate.

LOG FILE
========

   A typical log file output by this module looks like this:

     1..3

     ** A message logged with msg().
     ** Another one.
     1: My first test, using test(): how'd I do?
     1: ok 1

     ** Yet another message.
     2: My second test, using test_eq()...
     2: A: The first string
     2: B: The second string
     2: not ok 2

     3: My third test.
     3: ok 3

     END

   Each test() is logged with the test name and results, and the
test-number prefixes each line.  This allows you to scan a large file
easily with "grep" (or, ahem, "perl").  A blank line follows each test's
record, for clarity.

PUBLIC INTERFACE
================

Construction
------------

new [ARGS...]
     *Class method, constructor.* Create a new tester.  Any arguments are
     sent to log_open().

typical
     *Class method, constructor.* Create a typical tester.  Use this
     instead of new() for most applicaitons.  The directory "testout" is
     created for you automatically, to hold the output log file.

Doing tests
-----------

begin NUMTESTS
     *Instance method.* Start testing.

end
     *Instance method.* End testing.

ok BOOL, [TESTNAME], [PARAMHASH...]
     *Instance method.* Do a test, and log some information connected with
     it.  Use it like this:

          $T->ok(-e $dotforward);

     Or better yet, like this:

          $T->ok((-e $dotforward),
          	   "Does the user have a .forward file?");

     Or even better, like this:

          $T->ok((-e $dotforward),
          	   "Does the user have a .forward file?",
          	   User => $ENV{USER},
          	   Path => $dotforward,
          	   Fwd  => $ENV{FWD});

     That last one, if it were test #3, would be logged as:

          3: Does the user have a .forward file?
          3:   User: "alice"
          3:   Path: "/home/alice/.forward"
          3:   Fwd: undef
          3: ok

     You get the idea.  Note that defined quantities are logged with
     delimiters and with all nongraphical characters suitably escaped, so
     you can see evidence of unexpected whitespace and other badnasties.
     Had "Fwd" been the string "this\nand\nthat", you'd have seen:

          3:   Fwd: "this\nand\nthat"

     And unblessed array refs like ["this", "and", "that"] are treated as
     multiple values:

          3:   Fwd: "this"
          3:   Fwd: "and"
          3:   Fwd: "that"

ok_eq ASTRING, BSTRING, [TESTNAME], [PARAMHASH...]
     *Instance method.* Convenience front end to ok(): test whether
     `ASTRING eq BSTRING', and logs the operands as 'A' and 'B'.

ok_eqnum ANUM, BNUM, [TESTNAME], [PARAMHASH...]
     *Instance method.* Convenience front end to ok(): test whether `ANUM
     == BNUM', and logs the operands as 'A' and 'B'.

Logging messages
----------------

log_open PATH
     *Instance method.* Open a log file for messages to be output to.
     This is invoked for you automatically by `new(PATH)' and `typical()'.

log_close
     *Instance method.* Close the log file and stop logging.  You
     shouldn't need to invoke this directly; the destructor does it.

log MESSAGE...
     *Instance method.* Log a message to the log file.  No alterations are
     made on the text of the message.  See msg() for an alternative.

msg MESSAGE...
     *Instance method.* Log a message to the log file.  Lines are prefixed
     with "** " for clarity, and a terminating newline is forced.

Utilities
---------

catdir DIR, ..., DIR
     *Class/instance method.* Concatenate several directories into a path
     ending in a directory.  Lightweight version of the one in the (very
     new) File::Spec.

     Paths are assumed to be absolute.  To signify a relative path, the
     first DIR must be ".", which is processed specially.

     On Mac, the path *does* end in a ':'.  On Unix, the path *does not*
     end in a '/'.

catfile DIR, ..., DIR, FILE
     *Class/instance method.* Like catdir(), but last element is assumed
     to be a file.  Note that, at a minimum, you must supply at least a
     single DIR.

CHANGE LOG
==========

   *Current version:* $Id: TBone.pm,v 1.117 2000/08/16 05:08:09 eryq Exp $

Version 1.116
     Cosmetic improvements only.

Version 1.112
     Added lightweight catdir() and catfile() (a la File::Spec) to enhance
     portability to Mac environment.

Version 1.111
     Now uses File::Basename to create "typical" logfile name, for
     portability.

Version 1.110
     Fixed bug in constructor that surfaced if no log was being used.

   Created: Friday-the-13th of February, 1998.

AUTHOR
======

   Eryq (`eryq@zeegee.com').  President, ZeeGee Software Inc.
(`http://www.zeegee.com')

add blib/* directories to @INC
******************************

NAME
====

   ExtUtils::testlib - add blib/* directories to @INC

SYNOPSIS
========

   `use ExtUtils::testlib;'

DESCRIPTION
===========

   After an extension has been built and before it is installed it may be
desirable to test it bypassing make test. By adding

     use ExtUtils::testlib;

   to a test program the intermediate directories used by make are added
to @INC.

a Perl API to manipulate FAQ-O-Matics
*************************************

NAME
====

   FAQ::OMatic::API - a Perl API to manipulate FAQ-O-Matics

SYNOPSIS
========

     use FAQ::OMatic::API;
     my $fom_api = new FAQ::OMatic::API();

DESCRIPTION
===========

   `FAQ::OMatic::API' is a class that makes HTTP requests to a FAQ-O-Matic.
It provides a way to manipulate a FAQ-O-Matic from Perl code. Operations
are performed by making HTTP requests on the FAQ-O-Matic server; this
ensures that any operation is performed in exactly the same environment as
it would be if it were requested by a human using a web browser.

Setup
=====

   The following methods are used to set up an API object.

$fom_api = new FAQ::OMatic::API([$url, [$id, $pass]]);
     Constructs a new `FAQ::OMatic::API' object that points at the FAQ
     whose CGI is at `$url'. Requests will be authenticated on behalf of
     FAQ user $id using password `$pass'.

$fom_api->setURL($url);
     Sets the URL of the target FAQ's CGI. This is where requests will be
     sent.

$fom_api->setAuth($id, $pass);
     Sets the ID and password that will be used to authenticate requests.

$fom_api->setAuth('query');
     Passing in 'query' will cause the script to query the terminal for
     the id and password at runtime.

Queries
=======

   The following methods retrieve information about a FAQ-O-Matic.

$fom_api->getCategories()
     Returns a list of the categories (by file name) in the FAQ.

$item = $fom_api->getItem($filename)
     Returns a local FAQ::OMatic::Item object created by retrieving
     $filename from the FAQ. You can perform operations on the result such
     as:

          print $item->getTitle();

          $parentItem = $item->getParent();

          print $item->displayHTML({'render'=>'text'});

my ($rc, $result) = $fom_api->fuzzyMatch(['Parent Category','child cat'])
          my ($rc, $result) = $fom_api->fuzzyMatch(['Parent Category','child cat'])
          die $result if (not $rc);
          my $item = $fom_api->getItem($result->[0]);

     `fuzzyMatch()' attempts to figure out which category the last string
     in its array argument represents. The category name is matched
     "fuzzily" against existing categories. If a unique match is found, it
     is returned (as an array ref `[$filename, $parent, $title]'). If the
     match is ambiguous, the previous array element is matched against the
     parents of the set of fuzzy matches. This is performed recursively
     until the child category is disambiguated.

     Fuzzy matching means that

    (a)
          You don't have to get the parent category names right if they're
          not needed to disambiguate the child category.

    (b)
          Category names are matched without respect to case, spacing, or
          punctuation: only alphanumerics matter. Also, the name you
          supply only has to appear somewhere inside the one you want to
          match. (Exact matches are preferred; this allows you to match
          categories whose names are prefixes of other category names.)

Operations
==========

   The following methods perform operations on a FAQ-O-Matic.

$fom_api->newAnswer($parent, $title, $text)
     A new answer is created as a child of item `$parent'.  The new answer
     has title `$title' and a single text part containing $text.

REQUIRES
========

See LWP, and its hierarchy of helper classes.

Fast CGI module
***************

NAME
====

   FCGI - Fast CGI module

SYNOPSIS
========

     use FCGI;

     my $count = 0;
     my $request = FCGI::Request();

     while($request->Accept() >= 0) {
     	print("Content-type: text/html\r\n\r\n", ++$count);
     }

DESCRIPTION
===========

   Functions:

FCGI::Request
     Creates a request handle. It has the following optional parameters:

    input perl file handle (default: \*STDIN)
    output perl file handle (default: \*STDOUT)
    error perl file handle (default: \*STDERR)
          These filehandles will be setup to act as input/output/error on
          succesful Accept.

    environment hash reference (default: \%ENV)
          The hash will be populated with the environment.

    socket (default: 0)
          Socket to communicate with the server.  Can be the result of the
          OpenSocket function.  For the moment, it's the file descriptor
          of the socket that should be passed. This may change in the
          future.

    flags (default: 0)
          Possible values:

         FCGI::FAIL_ACCEPT_ON_INTR
               If set, Accept will fail if interrupted.  It not set, it
               will just keep on waiting.

     Example usage:     my $req = FCGI::Request;

     or:     my %env;     my $in = new IO::Handle;     my $out = new
     IO::Handle;     my $err = new IO::Handle;     my $req =
     FCGI::Request($in, $out, $err, \%env);

FCGI::OpenSocket(path, backlog)
     Creates a socket suitable to use as an argument to Request.

    path
          Pathname of socket or colon followed by local tcp port.

    backlog
          Maximum length of the queue of pending connections.  If a
          connection request arrives with the queue full the client may
          receive an  error  with  an  indication of ECONNREFUSED.

FCGI::CloseSocket(socket)
     Close a socket opened with OpenSocket.

$req->Accept()
     Accepts a connection on $req, attaching the filehandles and
     populating the environment hash.  Returns 0 on success.  If a
     connection has been accepted before, the old one will be finished
     first.

     Note that unlike with the old interface, no die and warn handlers are
     installed by default. This means that if you are not running an sfio
     enabled perl, any warn or die message will not end up in the server's
     log by default.  It is advised you set up die and warn handlers
     yourself.  FCGI.pm contains an example of die and warn handlers.

$req->Finish()
     Finishes accepted connection.  Also detaches filehandles.

$req->Flush()
     Flushes accepted connection.

$req->Detach()
     Temporarily detaches filehandles on an accepted connection.

$req->Attach()
     Re-attaches filehandles on an accepted connection.

$env = $req->GetEnvironment()
     Returns the environment parameter passed to FCGI::Request.

($in, $out, $err) = $req->GetHandles()
     Returns the file handle parameters passed to FCGI::Request.

$isfcgi = $req->IsFastCGI()
     Returns whether or not the program was run as a FastCGI.

AUTHOR
======

   Sven Verdoolaege <skimo@kotnet.org>

functions for managing FastCGI applications.
********************************************

NAME
====

     FCGI::ProcManager - functions for managing FastCGI applications.

SYNOPSIS
========

   {  # In Object-oriented style.   use CGI::Fast;  use FCGI::ProcManager;
my $proc_manager = FCGI::ProcManager->new({ 	n_processes => 10  });
$proc_manager->pm_manage();  while (my $cgi = CGI::Fast->new()) {
$proc_manager->pm_pre_dispatch();    # ... handle the request here ...
$proc_manager->pm_post_dispatch();  }

     # This style is also supported:
     use CGI::Fast;
     use FCGI::ProcManager qw(pm_manage pm_pre_dispatch
     			  pm_post_dispatch);
     pm_manage( n_processes => 10 );
     while (my $cgi = CGI::Fast->new()) {
       pm_pre_dispatch();
       #...
       pm_post_dispatch();
     }

DESCRIPTION
===========

   FCGI::ProcManager is used to serve as a FastCGI process manager.  By
re-implementing it in perl, developers can more finely tune performance in
their web applications, and can take advantage of copy-on-write semantics
prevalent in UNIX kernel process management.  The process manager should
be invoked before the caller"s request loop

   The primary routine, pm_manage, enters a loop in which it maintains a
number of FastCGI servers (via fork(2)), and which reaps those servers
when they die (via wait(2)).

   pm_manage provides too hooks:

     C<managing_init> - called just before the manager enters the manager loop.
     C<handling_init> - called just before a server is returns from C<pm_manage>

   It is necessary for the caller, when implementing its request loop, to
insert a call to pm_pre_dispatch at the top of the loop, and then
7pm_post_dispatch at the end of the loop.

METHODS
=======

new
---

     class or instance
     (ProcManager) new([hash parameters])

   Constructs a new process manager.  Takes an option has of initial
parameter values, and assigns these to the constructed object HASH,
overriding any default values.  The default parameter values currently are:

     role         => manager
     start_delay  => 0
     die_timeout  => 60

Manager methods
===============

pm_manage
---------

     instance or export
     (int) pm_manage([hash parameters])

   DESCRIPTION:

   When this is called by a FastCGI script to manage application servers.
It defines a sequence of instructions for a process to enter this method
and begin forking off and managing those handlers, and it defines a
sequence of instructions to intialize those handlers.

   If n_processes < 1, the managing section is subverted, and only the
handling sequence is executed.

   Either returns the return value of pm_die() and/or pm_abort() (which
will not ever return in general), or returns 1 to the calling script to
begin handling requests.

managing_init
-------------

     instance
     () managing_init()

   DESCRIPTION:

   Overrideable method which initializes a process manager.  In order to
handle signals, manage the PID file, and change the process name properly,
any method which overrides this should call SUPER::managing_init().

pm_die
------

     instance or export
     () pm_die(string msg[, int exit_status])

   DESCRIPTION:

   This method is called when a process manager receives a notification to
shut itself down.  pm_die() attempts to shutdown the process manager
gently, sending a SIGTERM to each managed process, waiting die_timeout()
seconds to reap each process, and then exit gracefully once all children
are reaped, or to abort if all children are not reaped.

pm_wait
-------

     instance or export
     (int pid) pm_wait()

   DESCRIPTION:

   This calls wait() which suspends execution until a child has exited.
If the process ID returned by wait corresponds to a managed process,
pm_notify() is called with the exit status of that process.  pm_wait()
returns with the return value of wait().

pm_write_pid_file
-----------------

     instance or export
     () pm_write_pid_file([string filename])

   DESCRIPTION:

   Writes current process ID to optionally specified file.  If no filename
is specified, it uses the value of the pid_fname parameter.

pm_remove_pid_file
------------------

     instance or export
     () pm_remove_pid_file()

   DESCRIPTION:

   Removes optionally specified file.  If no filename is specified, it uses
the value of the pid_fname parameter.

sig_manager
-----------

     instance
     () sig_manager(string name)

   DESCRIPTION:

   Handles signals of the process manager.  Takes as input the name of
signal being handled.

Handler methods
===============

handling_init
-------------

     instance or export
     () handling_init()

   DESCRIPTION:

pm_pre_dispatch
---------------

     instance or export
     () pm_pre_dispatch()

   DESCRIPTION:

pm_post_dispatch
----------------

     instance or export
     () pm_post_dispatch()

   DESCRIPTION:

sig_handler
-----------

     instance or export
     () sig_handler()

   DESCRIPTION:

Common methods and routines
===========================

self_or_default
---------------

     private global
     (ProcManager, @args) self_or_default([ ProcManager, ] @args);

   DESCRIPTION:

   This is a helper subroutine to acquire or otherwise create a singleton
default object if one is not passed in, e.g., a method call.

pm_change_process_name
----------------------

     instance or export
     () pm_change_process_name()

   DESCRIPTION:

pm_received_signal
------------------

     instance or export
     () pm_received signal()

   DESCRIPTION:

parameters
==========

pm_parameter
------------

     instance or export
     () pm_parameter()

   DESCRIPTION:

n_processes
-----------

no_signals
----------

pid_fname
---------

die_timeout
-----------

role
----

start_delay
-----------

   DESCRIPTION:

notification and death
======================

pm_warn
-------

     instance or export
     () pm_warn()

   DESCRIPTION:

pm_notify
---------

     instance or export
     () pm_notify()

   DESCRIPTION:

pm_exit
-------

     instance or export
     () pm_exit(string msg[, int exit_status])

   DESCRIPTION:

pm_abort
--------

     instance or export
     () pm_abort(string msg[, int exit_status])

   DESCRIPTION:

BUGS
====

   No known bugs, but this does not mean no bugs exist.

SEE ALSO
========

   See FCGI.

COPYRIGHT
=========

     FCGI-ProcManager - A Perl FCGI Process Manager
     Copyright (c) 2000, FundsXpress Financial Network, Inc.

     This library is free software; you can redistribute it and/or
     modify it under the terms of the GNU Lesser General Public
     License as published by the Free Software Foundation; either
     version 2 of the License, or (at your option) any later version.

     BECAUSE THIS LIBRARY IS LICENSED FREE OF CHARGE, THIS LIBRARY IS
     BEING PROVIDED "AS IS WITH ALL FAULTS," WITHOUT ANY WARRANTIES
     OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT
     LIMITATION, ANY IMPLIED WARRANTIES OF TITLE, NONINFRINGEMENT,
     MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, AND THE
     ENTIRE RISK AS TO SATISFACTORY QUALITY, PERFORMANCE, ACCURACY,
     AND EFFORT IS WITH THE YOU.  See the GNU Lesser General Public
     License for more details.

     You should have received a copy of the GNU Lesser General Public
     License along with this library; if not, write to the Free Software
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA

Perl Foreign Function Interface
*******************************

NAME
====

   FFI - Perl Foreign Function Interface

SYNOPSIS
========

     use FFI;
     $addr = <address of a C function>
     $signature = <function signature>
     $ret = FFI::call($addr, $signature, ...);

     $cb = FFI::callback($signature, sub {...});
     $ret = FFI::call($addr, $signature, $cb->addr, ...);

DESCRIPTION
===========

   This module provides a low-level foreign function interface to Perl. It
allows the calling of any function for which the user can supply an
address and calling signature. Furthermore, it provides a method of
encapsulating Perl subroutines as callback functions whose addresses can
be passed to C code.

FUNCTION SIGNATURES
===================

   Function interfaces are defined by signatures. A function's signature
is a string which specifies the function's return type, argument types and
calling convention. The first character of the string is the function's
calling convention. This is one of

     s   The standard calling convention for dynamically linked functions
     c   The calling convention used by C functions

   Note that on many platforms, these two calling conventions may be
identical.  On the Windows platform, the s code corresponds to the
`stdcall' calling convention, which is used for most dynamic link
libraries.  The c code corresponds to the `cdecl' calling convention,
which is used for C functions, such as those in the C runtime library.

   The remaining characters of the string are the return type of the
function, followed by the argument types, in left-to-right order. Valid
values are based on the codes used for the `pack' in this node function,
namely

     c	A signed char value.
     C	An unsigned char value.
     s	A signed short value.
     S	An unsigned short value.
     i	A signed integer value.
     I	An unsigned integer value.
     l	A signed long value.
     L	An unsigned long value.
     f	A single-precision float.
     d	A double-precision float.
     p	A pointer.
     v   No value (only valid as a return type).

   Note that all of the above codes refer to "native" format values.

   The p code as an argument type simply passes the address of the Perl
value's memory to the foreign function. It is the caller's responsibility
to be sure that the called function does not overwrite memory outside that
allocated by Perl.

   The p code as a return type treats the returned value as a
null-terminated string, and passes it back to Perl as such. There is
currently no support for functions which return pointers to structures, or
to other blocks of memory which do not contain strings, nor for functions
which return memory which the caller must free.

   To pass pointers to strings, use the p code. Perl ensures that strings
are null-terminated for you. To pass pointers to structures, use `pack' in
this node. To pass an arbitrary block of memory, use something like the
following:

     $buf = ' ' x 100;
     # Use $buf via a 'p' parameter as a 100-byte memory block

   At the present time, there is no direct support for passing pointers to
'native' types (like int). To work around this, use `$buf = pack('i', 12);'
to put an integer into a block of memory, then use the p pointer type, and
obtain any returned value using `$n = unpack('i', $buf);' In the future,
better support may be added (but remember that this is intended as a
low-level interface!)

EXAMPLES
========

   It is somewhat difficult to provide examples of using this module in
isolation, as it is necessary to (somehow) obtain the address of a
function to call. In general, this task is delegated to higher-level
wrapper modules.

   However, the standard DynaLoader module returns symbol references via
the `DynaLoader::dl_find_symbol()' function. While these references are not
documented as being addresses, in practice, they seem to be. Code to obtain
the address of various C library functions can be built around this

     $clib_file = ($^O eq "MSWin32") ? "MSVCRT40.DLL" : "-lc";
     $clib = DynaLoader::dl_findfile($clib_file);
     $strlen = DynaLoader::dl_find_symbol($clib, "strlen");
     $n = FFI::call($strlen, "cIp", $my_string);
     DynaLoader::dl_free_file($clib);

   Clearly, code like this needs to be encapsulated in a module of some
form...

   NOTE: In fact, the DynaLoader interface has problems in ActiveState
Perl, and probably in other binary distributions of Perl. (The issue is
related to the way in which the DynaLoader module is built, and may be
addressed in future versions of Perl). In the interim, the higher-level
wrapper module FFI::Library does not use DynaLoader on Win32 - it uses the
(deprecated, but still available) Win32::LoadLibrary and related calls.

TODO
====

   * Improve support for returning pointers to things other than
     null-terminated strings.

   * Possibly, improve support for passing pointers to "native" types.

LICENSE
=======

   Substantial portions of the code for this module (the underlying FFI
code) are licensed under the Gnu General Public License. Under the terms
of that license, my understanding is that this module has to be
distrubuted under that same license.

   My personal preference would be to distribute this module under the
same terms as Perl. However, I understand that this is not possible, given
the licensing of the FFI code.

AUTHOR
======

   Paul Moore, gustav@morpheus.demon.co.uk

SEE ALSO
========

   http://clisp.cons.org/~haible/clisp.html Bruno Haible's CLisp Common
Lisp implementation, from which the underlying foreign function interface
code was taken.

Perl Access to Dynamically Loaded Libraries
*******************************************

NAME
====

   FFI::Library - Perl Access to Dynamically Loaded Libraries

SYNOPSIS
========

     use FFI::Library;
     $lib = FFI::Library->new("mylib");
     $fn = $lib->function("fn", "signature");
     $ret = $fn->(...);

DESCRIPTION
===========

   This module provides access from Perl to functions exported from
dynamically linked libraries. Functions are described by signatures, for
details of which see the FFI, module's documentation.

EXAMPLES
========

     $clib_file = ($^O eq "MSWin32") ? "MSVCRT40.DLL" : "-lc";
     $clib = FFI::Library->new($clib_file);
     $strlen = $clib->function("strlen", "cIp");
     $n = $strlen->($my_string);

TODO
====

LICENSE
=======

   This module can be distributed under the same terms as Perl. However,
as it depends on the FFI, module, please note the licensing
terms for the FFI code.

AUTHOR
======

   Paul Moore, gustav@morpheus.demon.co.uk

SEE ALSO
========

   The FFI, module.

Simulate the behavior of a Perl hash variable
*********************************************

NAME
====

   FakeHash - Simulate the behavior of a Perl hash variable

SYNOPSIS
========

     use FakeHash;
     my $hash = FakeHash->new;
     $hash->store($key, $value);     # analogous to $h{$key} = $value
     @keys = $hash->keys;            # analogous to @keys = keys %h
     $hash->delete($key);		# analogous to delete $h{$key}
     $value = $hash->fetch($key);    # analogous to $value = $h{$key}
     $string = $hash->scalarval;     # analogous to $string = %h
     $string = $hash->clear;         # analogous to %h = ()

     $hash->iterate(...);            # Invoke callbacks for each bucket and node

             # Caution: Not tested
     my $hash = tie %h => FakeHash;  # $hash will mirror the changes to %h

     use FakeHash 'hashval';
     $n = hashval($string);          # hash value for string

     FakeHash->version(5.005);       # Use Perl 5.005 hashval function
     $version = FakeHash->version;   # Return Perl version currently in force

DESCRIPTION
===========

   `FakeHash' simulates the behavior of a Perl hash variable, maintaining
a synthetic data structure that mirrors the true data structure inside of
Perl.  This can be used to investigate hash performance or behavior.  For
example, see the `FakeHash::DrawHash' class, described below, which draws
a box-and-arrow diagram representing the memory layout of a hash.

   The store, fetch, keys, and delete methods perform the corresponding
operations on the simulated hash.

   The iterate method iterates over the simulated structure and invokes
user-supplied callbacks.  The arguments to iterate are a hash of actions,
and an optional *user parameter*.

   The actions hash may have any or all of the following keys:

prebucket
     A function that is called once for each bucket in the hash, prior to
     iterating over the nodes in the bucket.  The arguments to the
     prebucket function are: the bucket number; a `FakeHash::Node' object
     representing the first node in the bucket (or an undefined value of
     the bucket is empty,) and the user parameter.

prebucket
     The same, except that the function is called after iterating over the
     nodes in the bucket.

node
     A function that is called once for each node (key-value pair) in the
     hash.  The node function is called for a node after the prebucket
     function and before the `postbucket' function is called for the
     node's bucket.

     The arguments to the node function are: The bucket number; a
     `FakeHash::Node' object representing the first node in the bucket;
     the node's number within the bucket (0 for the first node in the
     bucket); the node itself; and the user parameter.

maxbucket
     If this is a number, say n, iterate will only iterate over the first
     n buckets, and will skip the later buckets and their contents.  If
     this is a function, iterate will call it once, with the user
     paramater as its argument, and will expect it to return a number n to
     be used as above.  If it is omitted, iterate will iterate over all
     buckets and their contents.

   For example, the keys method is implemented as a call to iterate, as
follows:

     sub keys {
       my $self = shift;
       my @r;
       $self->iterate({node => sub { my ($i, $b, $n, $node) = @_;
                                     push @r, $node->key;
                                   },
                      });
       @r;
     }

Other Methods
-------------

   `FakeHash->DEBUG' will return the current setting of the DEBUG flag,
and will change the value of the flag if given an argument.  When the
DEBUG flag is set to a true value, the module may emit diagnostic messages
to `STDERR'.

   Each `FakeHash' object may carry auxiliary information.  Auxiliary
information is not used by `FakeHash' but may be used by subclasses.
`$hash->set_defaults(key, value, key, value,...)' sets the specified
auxiliariy data values for the `FakeHash' object.  A hashref may be passed
instead; its contents will be appended to the values already installed.
To query the currently-set values, use `$hash->defaults(key, key, ...)',
which will return a list of the corresponding values, or, in scalar
context, a reference to an array of the corresponding values.

   `$hash->size' retrieves the number of buckets in the hash.

   The Perl hash function changed between versions 5.005 and 5.6, so the
behavior of Perl hashes changed at the same time.  By default, `FakeHash'
will emulate the behavior of whatever version of Perl it is running under.
To change this, use the version method.  Its argument is the version of
Perl that you would like to emulate.  It returns the version number prior
to setting.

Draw a `pic' diagram of the internal structure of a hash
********************************************************

NAME
====

   FakeHash::DrawHash - Draw a `pic' diagram of the internal structure of
a hash

SYNOPSIS
========

     my $hash = FakeHash::DrawHash->new;

     # see L<FakeHash> for more details

     $hash->draw($filehandle);  #  Print 'pic' commands to filehandle

DESCRIPTION
===========

   `FakeHash::DrawHash' is a subclass of `FakeHash' that can draw a
picture of the internal structure of a Perl hash variable.  It emits code
suitable for the Unix `pic' drawing program.

   `FakeHash::DrawHash' provides the following methods:

draw
----

   Emit `pic' code for a box-and-arrow diagram that represents the current
state of the simulated hash.  A filehandle argument may be provided to
receive the output.  If omitted, output goes to STDOUT.  Additionally, a
user parameter argument may be provided, which will be passed to the other
`draw_*' methods.

draw_param
----------

   Set or retrieve various parameters dermining box size and layout.
Takes a name and an optional value argument and returns the old value
associated with the name.  If the value is provided, sets the new value.
Valid names are:

BUCKET
     Determines the size of the boxes used to represent each hash bucket.
     The value should be a reference to an array of the height and width,
     in inches.

     Defaults to `[1, 0.55]', or one inch wide by 0.55 inches tall.

BUCKETSPACE
     Amount of horizontal space,in inches, between the box that represents
     a bucket and the bixes that represent the bucket contents.  If zero,
     the buckets will abut their contents.

     Defaults to 1/5 inch.

KVP
     The size of the boxes used to represent each key-value node.  The
     value should be a reference to an array of the height and width, in
     inches.

     Defaults to `[1, 0.5]', or one inch wide by half an inch tall.

draw_start
----------

   Called once, each time drawing commences.  Arguments: The filehandle
and user parameter, if any, that were passed to draw.

draw_end
--------

   Called once, just at the end of each call to draw.  Arguments: The
filehandle and user parameter, if any, that were passed to draw.

draw_bucket
-----------

   Called each time draw needs to draw a single bucket.

   Arguments: The filehandle that was passed to draw; the bucket number
(starting from 0) of the current bucket; a boolean value which is true if
and only if the bucket is nonempty; and the user parameter that was passed
to draw.

draw_node
---------

   Called each time draw needs to draw a single key-value node.

   Arguments: The filehandle that was passed to draw; the bucket number
(starting from 0) of the bucket in which the current node resides; the
number of the node in the current bucket (the first node is node zero); a
`FakeHash::Node' object representing the node itself; and the user
parameter that was passed to draw.

IDEA
====

   The theory here is that it should be easy to override these methods
with corresponding methods that draw the diagram in PostScript or GD or
whatever.

   If you do this, please send me the code so that I can distribute it.

Class used internally by `FakeHash' to represent key-value pairs
****************************************************************

NAME
====

   FakeHash::Node - Class used internally by `FakeHash' to represent
key-value pairs

SYNOPSIS
========

     $key   = $node->key;
     $value = $node->value;
     $hash  = $node->hash;
     $next  = $node->next;

DESCRIPTION
===========

   `FakeHash::Node' is used internally by `FakeHash' for various purposes.
For example, the `FakeHash::iterate' function invokes a user-supplied
callback for each key-value pair, passing it a series of `FakeHash::Node'
objects that represent the key-value pairs.

   The key and value methods retrieve the key and value of a node.  The
hash method retrieves the key's hash value.

   `$node->next' method retrieves the node that follows $node in its
bucket, or an undefined value if $node is last in its bucket.

   If any of these methods is passed an additional argument, it will set
the corresponding value.  It will return the old value in any case.

AUTHOR
======

   Mark-Jason Dominus (`mjd-perl-fakehash+@plover.com')

COPYRIGHT
=========

   `FakeHash.pm' is a Perl module that simulates the behavior of a Perl
hash variable.  `FakeHash::DrawHash' renders a diagram of a simulated hash.

   Copyright (C) 200 Mark-Jason Dominus

   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.

Perl5 access to FAME
********************

NAME
====

   Fame - Perl5 access to FAME

SYNOPSIS
========

     use Fame;

     [$X =] tie %hash, Fame::DB, $dbname|$mode...

     @data=@{$hash{"object:1jan80:31dec81"}}

     untie %hash

     &Fame::HLI::cfmddes($status,$dbkey,$desc);

     print "error" if $status != &Fame::HLI::HSUCC;

     $db = new Fame::DB $dbname|$mode...;

     @data = $db->Read($name, $start, $end);

     $db->Write($name, $start, @data);

     $interp = new Fame::LANG;

     $interp->command('open <access read> "db"');

     @profit = $interp->exec('revenue.qtr - sales.qtr');

SUMMARY
=======

  1. All but 6 C HLI 7.7 functions are fully implemented in native perl
     code.  Not implemented: cfmlsts, cfmrdfa, cfmrrng, cfmrsts, cfmwrng,
     cfmwsts.

  2. For implementations with the FRB extensions, all hli_* functions are
     implemented fully.  famedbpath is also implemented.

  3. New perl-like functions have been added (see FAME Utilities).  These
     provide an interface to TIE and the FAME interpreter.

  4. Values of hli.h are available.

DESCRIPTION
===========

   This is a long section.  The first part describes essential FAME hli.h
macros.  The second part, TIE, deals with the TIEHASH mechanism for
accessing FAME data.  The next part deals with high level functions for
reading and writing.  Following is a short description about accessing the
FAME interpreter. The next parts deal with more direct control of the C
HLI.  Familiarity with the C HLI is assumed in this last part.

   Three subpackages are defined by this package:

Fame::HLI
     Includes almost all the CHLI functions as well as some simple
     utilities.

Fame::DB
     Includes a TIE interface using the Fame::HLI package, as well a
     high-level object-oriented functions for reading and writing data.

Fame::LANG
     Provides a simple object-oriented way to run programs, commands, and
     functions in the FAME 4GL language.  It uses the Fame::HLI package.

HLI.H
-----

   Values of hli.h are accessed by adding "&Fame::HLI::" in front of the
name.  Thus, HDAILY becomes &Fame::HLI::HDAILY.

TIE
---

   You can use the Perl TIEHASH mechanism for accessing most of the FAME
database features.  Unlike with Fame, the default open mode is read-only.
First, open the databases with the tie command:

     tie(%db, Fame::DB, "prices", "orders");

   You may specify a fame open mode by using it before the databases for
which the mode should be used:

     tie(%db, Fame::DB, &Fame::HUMODE, "prices");

   Instead of listing the databse names, you may also specify a reference
to an array.  Either way, the new hash is tied to all the opened databases
so that they are searched for objects in the order specified.

   Data is read by indexing the hash (%db in our example) using the object
name and an optional start and end date.  The index is the object name
followed by a ":", the start date, a ",", and the end date.  However, only
the object name is required.  When accessed this way, the hash returns a
reference to an array so it must be indirected.  For example

     @{$db{"ibm:1jun95,31jun95"}}

   will return an array containing the values of "ibm" from 1jun95 to
31jun95.  Note the use of the @{} construct which returns the values of a
reference.  The dates must be in a format consistent with the frequency of
the object ("ibm"), which in this case is daily.

   Likewise, to write values to the database, assign the hash to an array
reference.  For example

     $db{"ibm:1jun95"} = [1,4,6];

   will write out the numbers 1, 4, and 6 starting at date 1jun95.
fameperl will write the given number of elements starting at the given
date.  You may specify an end date, but it will be silently ignored.  This
construct will only write data to existing data object.  To create
objects, you must use the C HLI routines or the functions described below.

   Hash functions, like "each" and "keys" will work by performing a
wildcard lookup on the database.  The variable $Fame::DB::WILD contains a
string with the FAME wildcard specification (default "?").

   There are certain variables in the Fame::DB package which are used as
defaults by some Fame::DB functions.  $Fame::DB::FREQ contains the default
frequency code.  This code can be one of the valid HLI frequency codes
such as &Fame::HLI::HDAILY.  The following data items similarly can take
on any valid and appropriate HLI code.  $Fame::DB::TYPE contains the
default data type.  $Fame::DB::BASIS contains the default basis attribute.
$Fame::DB::OBSERVED contains the default observed attribute.
$Fame::DB::CLASS is the default class.

FUNCTIONS
---------

   There are several high level functions for reading, writing and
creating data object.  These functions can be used as both normal function
calls and object-oriented calls.  They are summarized below.  The first
function opens a database using the same syntax as the tie command.

     $ref = &Fame::DB::new($db_path|$db_mode...)
        $db_path  database path
        $db_mode  access mode from Fame::HLI

   An alternative syntax for the Fame::DB::new syntax is

     $ref = new Fame::DB $db_path|$db_mode;

   There are also two other functions for adding databases to an existing
object.

     $ref->append($db_path|$db_mode...);

   or

     $ref->append_db($dbkey...)

   The following functions take as their first parameter either a
reference to array of databases as returned by Fame::DB::new or a single
database key number.

     @val = &Fame::DB::Read($db, $name, $start, $end)
        @val    array of values read
        $db     database key (or $ref)
        $name   string object name
        $start  start string date
        $end    end string date

   .

     &Fame::DB::Write($db, $name, $start, @val)
        $db     database key (or $ref)
        $name   string object name
        $start  start string date
        @val    array of values to store

   .

     &Fame::DB::Create($db, $name [, $class, $freq, $type, $basis, $obs])
        $db     database key (or $ref)
        $name   object name
     The following are optional:
        $class  class code
        $freq   frequency code
        $type   object type
        $basis  basis attribute
        $obs    observed attribute

   An alternative object-oriented syntax for all of the above functions
would be:

     @data = $ref->Read($name, $start, $end);

   where $ref is an object of type Fame::HLI which would usually be
initialized by

     $ref = new Fame::DB $dbname;

FAME 4GL
--------

   There is also a simple object-oriented interface to the FAME 4GL
language using the HLI FAME/Server HLI functions.  There are several
methods for doing this in Fame::LANG.

$x = new Fame::LANG
     Create a new LANG object and open the work database.

$x->command($cmd)
     Execute the command $cmd.  If the command is more than one line long,
     all lines except the last one must be followed by "&&", the FAME
     line-continuation string.

$x->exec($fxn)
     Execute the given function and return an array (not a scalar) of the
     results.

$x->inp($file)
     Input the lines file named $file (this file should follow the "&&"
     line-continuation standard) and execute the commands with command().
     Note that you cannot use $x->command("inp file").  FAME will ignore
     this command.

$x->destroy
     Close the work database and remove the LANG object.

$x->{status}
     The HLI status of the last command.

$x->{workdb}
     The HLI database key for the work database.

C HLI
-----

   The Fame::HLI package includes almost all of the C HLI functions
available form Fame.  The typical C HLI function is translated directly to
perl.  For example, to call cfmddes from C HLI, you would use:

     cfmddes(&status,dbkey,desc);

   In fameperl, you would use:

     &Fame::HLI::cfmddes($status,$dbkey,$desc);

   Perl makes no distinction between pointers and values.  Thus, all
variables (whether output or input) are specified the same way.  Perl
takes care of modifying those values it has to modify.

SPECIAL FUNCTIONS
-----------------

   There are exceptions.  Functions which use a range (or other array with
a limited and fixed length) are called with one variable for every array
element.  Thus, cfmsrng would be called from C as:

     cfmsrng(&status,freq,&sy,&sp,&ey,&ep,range,&numobs);

   From perl, each element of range must be specified.  Thus, you would
use the following:

     &Fame::HLI::cfmsrng($status,$freq,$sy,$sp,$ey,$ep,
                         $range1,$range2,$range3,$numobs);

   The functions which require this type of array expansion are: cfmrstr,
cfmsbm, cfmsfis, cfmsnm, cfmspm, cfmwstr.

   Some functions have not been implemented.  See Summary for a list.

UTILITY FUNCTIONS
-----------------

   There are several functions which assist perl users in rapidly getting
and updating FAME data.  Most of the C HLI functions that write or read
data are not implemented.  In their place, you should use the functions
described in this section.

   When missing value translation is not specified, missing values are
returned as string "NA", "ND", "NC" if the values are numeric; this will
evaluate to a zero in a numeric context.  For strings, "" is returned.

$dbkey = &Fame::HLI::fameopen($name);
$dbkey = &Fame::HLI::fameopen($name,$mode);
     Open a FAME database.  First, look at the FAME databse directory as
     given by famedbpath.  If the database is not there, then try to open
     it in the current directory.  Returns -1 on error.

&Fame::HLI::fameclose($dbkey);
     Close database.

$type = &Fame::HLI::famegettype($dbkey,$objnam);
     Get an object's type.

$freq = &Fame::HLI::famegetfreq($dbkey,$objnam);
     Get an object's frequency.

@list = $Fame::HLI::famegetinfo($dbkey,$objnam);
     Get info (as returned by cfmwhat) with:

          ($class,$type,$freq,$basis,$observ,$fyear,$fprd,
           $lyear,$lprd,$cyear,$cmonth,$cday,$myear,$mmonth,
           $mday,$desc,$doc) = @list

     The following table describes the order of your parameters for easy
     reference in an array context:

          Name             #
          ------------    ---
          class            0
          type             1
          freq             2
          basis            3
          observed         4
          first year       5
          first period     6
          last year        7
          last period      8
          create year      9
          create month    10
          create day      11
          modify year     12
          modify month    13
          modify day      14
          description     15
          documentation   16

@data = &Fame::HLI::fameread($dbkey,$objnam,$syear,$sprd,$eyear,$eprd);
     Read data for the given range of dates.  Returns undef if there's a
     problem (the $Fame::HLI:status variable should be set with the error
     code).

@data = &Fame::HLI::famereadn($dbkey,$objnam,$numobs,@r,@m);
          @r=($range1,$range2,$range3);

          @m=($tmiss,$mistt1,$mistt2,$mistt3);

     Read a given number of value starting with the values of a given
     range.  Get the rangex values with the functions cfmsrng, cfmsfix.
     This function will read the whole range of values, but only store
     numobs of them.  You can get the value of numobs when setting the
     range.  The missing value variables must contain data even if no
     translation is being done.

&Fame::HLI::famewrite($dbkey,$objnam,$year,$prd,@list);
     Writes out all the elements of @list into the object staring with the
     given date.  Returns error status if failed; 0 if sucessful.\n;

ERRORS
------

   Errors in the utility functions are generally not reported.  However,
an empty list or undef returned from a function call generally means there
is an error.  You can also check the variable Fame::HLI::status which
returns the HLI status code for the last HLI function that was executed by
a utility function.  This value is not affected by calling HLI functions
directly from perl (such as "&cfmini($s)").

NOTES
-----

  1. The source code is written in Perl, C and CLI (a common language
     interface).  It does not use the standard Perl 5 extension macro
     language "xs" because the code was originally written for both Perl 4
     and Tcl.  Because it uses CLI, a lot of the code is the same for both
     interfaces.

  2. FAME is a registered trademark of Fame Information Services.  Neither
     this program nor its author are associated with Fame Information
     Services, nor does the author guarantee this software in any way.
     This software is derived from public domain work done at the Federal
     Reserve Board, Washington, DC.

  3. Everything except the Fame::HLI component is Copyright 1995-1997 by
     Fernando Trias.  Parts of the Fame::HLI component are also Copyright
     1995 by Fernando Trias.  These are marked as such.

BUGS
====

   There's an object symbolic name inconsistency between the Fame C HLI
library and the perl executable.  Both have an symbol named "Error".  You
may have to edit the perl executable and change all occurrences of "Error"
to something like "ErroX"; the Makefile includes a line for doing this
automatically (make patchperl).  Alternatively, you can try to edit the
Fame dynamic libarary file in the same way.

   Fame also handles some functions as #define's in hli.h.  This is not
the best coding practice, since it confuses the linking process. I cannot
guarantee that further versions of Fame will not do this also and possibly
affect this extension.

AUTHOR
======

     Fernando Trias
     trias@ix.netcom.com
     http://www.netcom.com/~trias

replace functions with equivalents which succeed or die
*******************************************************

NAME
====

   Fatal - replace functions with equivalents which succeed or die

SYNOPSIS
========

     use Fatal qw(open close);

     sub juggle { . . . }
     import Fatal 'juggle';

DESCRIPTION
===========

   Fatal provides a way to conveniently replace functions which normally
return a false value when they fail with equivalents which raise exceptions
if they are not successful.  This lets you use these functions without
having to test their return values explicitly on each call.  Exceptions
can be caught using `eval{}'.  See Perlfunc (perl.info),
and Perlvar (perl.info), for details.

   The do-or-die equivalents are set up simply by calling Fatal's import
routine, passing it the names of the functions to be replaced.  You may
wrap both user-defined functions and overridable CORE operators (except
exec, system which cannot be expressed via prototypes) in this way.

   If the symbol `:void' appears in the import list, then functions named
later in that import list raise an exception only when these are called in
void context-that is, when their return values are ignored.  For example

     use Fatal qw/:void open close/;

     # properly checked, so no exception raised on error
     if(open(FH, "< /bogotic") {
     	warn "bogo file, dude: $!";
     }

     # not checked, so error raises an exception
     close FH;

AUTHOR
======

   Lionel.Cons@cern.ch

   prototype updates by Ilya Zakharevich ilya@math.ohio-state.edu

load the C Fcntl.h defines
**************************

NAME
====

   Fcntl - load the C Fcntl.h defines

SYNOPSIS
========

     use Fcntl;
     use Fcntl qw(:DEFAULT :flock);

DESCRIPTION
===========

   This module is just a translation of the C `fnctl.h' file.  Unlike the
old mechanism of requiring a translated `fnctl.ph' file, this uses the
h2xs program (see the Perl source distribution) and your native C
compiler.  This means that it has a far more likely chance of getting the
numbers right.

NOTE
====

   Only `#define' symbols get translated; you must still correctly pack up
your own arguments to pass as args for locking functions, etc.

EXPORTED SYMBOLS
================

   By default your system's F_* and O_* constants (eg, F_DUPFD and
O_CREAT) and the FD_CLOEXEC constant are exported into your namespace.

   You can request that the flock() constants (LOCK_SH, LOCK_EX, LOCK_NB
and LOCK_UN) be provided by using the tag `:flock'.  See Exporter.

   You can request that the old constants (FAPPEND, FASYNC, FCREAT,
FDEFER, FEXCL, FNDELAY, FNONBLOCK, FSYNC, FTRUNC) be provided for
compatibility reasons by using the tag `:Fcompat'.  For new applications
the newer versions of these constants are suggested (O_APPEND, O_ASYNC,
O_CREAT, O_DEFER, O_EXCL, O_NDELAY, O_NONBLOCK, O_SYNC, O_TRUNC).

   For ease of use also the SEEK_* constants (for seek() and sysseek(),
e.g. SEEK_END) and the S_I* constants (for chmod() and stat()) are
available for import.  They can be imported either separately or using the
tags `:seek' and `:mode'.

   Please refer to your native fcntl(2), open(2), fseek(3), lseek(2)
(equal to Perl's seek() and sysseek(), respectively), and chmod(2)
documentation to see what constants are implemented in your system.

   See Perlopentut (perl.info), to learn about the uses
of the O_* constants with sysopen().

   See `seek', see Perlfunc (perl.info), and `sysseek', see
Perlfunc (perl.info), about the SEEK_* constants.

   See `stat', see Perlfunc (perl.info), about the S_I*
constants.

Communicate with a Festival server
**********************************

NAME
====

   Festival::Client - Communicate with a Festival server

SYNOPSIS
========

     use Festival::Client;

     $Festival = Festival::Client->New("my.festival.server");
     $Festival->say("Something to say");

DESCRIPTION
===========

   `Festival' is a class implementing a simple Festival client in Perl.

CONSTRUCTOR
===========

new ( [ HOST [, PORT ] ] )
     This is the constructor for a new Festival object. `HOST' is the name
     of the remote host to which a Festival connection is required.

     `PORT' is the Festival port to connect to, it defaults to the
     standard port 1314 if nothing else is found.

     The constructor returns the open socket, or undef if an error has
     been encountered.

SAY ( TEXT )
============

   The obvious.

AUTHOR
======

   Bek Oberin <gossamer@tertius.net.au>

COPYRIGHT
=========

   Copyright (c) 1998 Bek Oberin.  All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Figure out what is in an archive file
*************************************

NAME
====

   File::Archive - Figure out what is in an archive file

SYNOPSIS
========

     use File::Archive;
     $arch = File::Archive->new($filename);
     $name = $arch->filename;
     $filelist = $arch->catalog;
     $contents = $arch->member($file);

DESCRIPTION
===========

   Given an archive file of some kind, these methods will determine what
type of archive it is, and tell you what files are contained in that
archive. It will also give you the contents of a particular file contained
in that archive.

   This was written for the Scripts section of CPAN, so that users could
upload tarballs, rather than just single-file scripts

PREREQUISITES
=============

     Compress::Zlib
     Archive::Tar

AUTHOR
======

   Rich Bowen, <rbowen@rcbowen.com>

Perl extension for BSD glob routine
***********************************

NAME
====

   File::BSDGlob - Perl extension for BSD glob routine

SYNOPSIS
========

     use File::BSDGlob ':glob';
     @list = glob('*.[ch]');
     $homedir = glob('~gnat', GLOB_TILDE | GLOB_ERR);
     if (GLOB_ERROR) {
       # an error occurred reading $homedir
     }

     ## override the core glob (even with -T)
     use File::BSDGlob 'globally';
     my @sources = <*.{c,h,y}>

DESCRIPTION
===========

   File::BSDGlob implements the FreeBSD glob(3) routine, which is a
superset of the POSIX glob() (described in IEEE Std 1003.2 "POSIX.2").  The
glob() routine takes a mandatory pattern argument, and an optional flags
argument, and returns a list of filenames matching the pattern, with
interpretation of the pattern modified by the flags variable.  The POSIX
defined flags are:

`GLOB_ERR'
     Force glob() to return an error when it encounters a directory it
     cannot open or read.  Ordinarily glob() continues to find matches.

`GLOB_MARK'
     Each pathname that is a directory that matches the pattern has a slash
     appended.

`GLOB_NOCHECK'
     If the pattern does not match any pathname, then glob() returns a list
     consisting of only the pattern.  If `GLOB_QUOTE' is set, its effect
     is present in the pattern returned.

`GLOB_NOSORT'
     By default, the pathnames are sorted in ascending ASCII order; this
     flag prevents that sorting (speeding up glob()).

   The FreeBSD extensions to the POSIX standard are the following flags:

`GLOB_BRACE'
     Pre-process the string to expand C<{pat,pat,...} strings like csh(1).
     The pattern '{}' is left unexpanded for historical reasons (and csh(1)
     does the same thing to ease typing of find(1) patterns).

`GLOB_NOMAGIC'
     Same as `GLOB_NOCHECK' but it only returns the pattern if it does not
     contain any of the special characters "*", "?" or "[".  `NOMAGIC' is
     provided to simplify implementing the historic csh(1) globbing
     behaviour and should probably not be used anywhere else.

`GLOB_QUOTE'
     Use the backslash ('\') character for quoting: every occurrence of a
     backslash followed by a character in the pattern is replaced by that
     character, avoiding any special interpretation of the character.

`GLOB_TILDE'
     Expand patterns that start with '~' to user name home directories.

`GLOB_CSH'
     For convenience, `GLOB_CSH' is a synonym for `GLOB_BRACE |
     GLOB_NOMAGIC | GLOB_QUOTE | GLOB_TILDE'.

   The POSIX provided `GLOB_APPEND', `GLOB_DOOFFS', and the FreeBSD
extensions `GLOB_ALTDIRFUNC', and `GLOB_MAGCHAR' flags have not been
implemented in the Perl version because they involve more complex
interaction with the underlying C structures.

DIAGNOSTICS
===========

   glob() returns a list of matching paths, possibly zero length.  If an
error occurred, &File::BSDGlob::GLOB_ERROR will be non-zero and $! will be
set.  &File::BSDGlob::GLOB_ERROR is guaranteed to be zero if no error
occurred, or one of the following values otherwise:

`GLOB_NOSPACE'
     An attempt to allocate memory failed.

`GLOB_ABEND'
     The glob was stopped because an error was encountered.

   In the case where glob() has found some matching paths, but is
interrupted by an error, glob() will return a list of filenames and set
&File::BSDGlob::ERROR.

   Note that glob() deviates from POSIX and FreeBSD glob(3) behaviour by
not considering `ENOENT' and `ENOTDIR' as errors - glob() will continue
processing despite those errors, unless the `GLOB_ERR' flag is set.

   Be aware that all filenames returned from File::BSDGlob are tainted.

NOTES
=====

   * If you want to use multiple patterns, e.g. `glob "a* b*"', you should
     probably throw them in a set as in `glob "{a*,b*}'.  This is because
     the argument to glob isn't subjected to parsing by the C shell.
     Remember that you can use a backslash to escape things.

   * Win32 users should use the real slash.  If you really want to use
     backslashes, consider using Sarathy's File::DosGlob, which comes with
     the standard Perl distribution.

AUTHOR
======

   The Perl interface was written by Nathan Torkington (gnat@frii.com),
and is released under the artistic license.  Further modifications were
made by Greg Bacon <gbacon@cs.uah.edu>.  The C glob code has the following
copyright:

     Copyright (c) 1989, 1993 The Regents of the University of California.
     All rights reserved.  This code is derived from software contributed
     to Berkeley by Guido van Rossum.

   For redistribution of the C glob code, read the copyright notice in the
file bsd_glob.c, which is part of the File::BSDGlob source distribution.

For making rotating backups of directories
******************************************

NAME
====

   File::Backup - For making rotating backups of directories

SYNOPSIS
========

     use File::Backup("backup");
     backup(
        from          => "/dir/to/back/up",
        to            => "/destination/of/backup/files",
        torootname    => root name of backup file (default is ""),
        keep          => number of backups to keep in todir (default is 7),
        tar           => path to archiving utility (default is "/usr/bin/tar"),
        compress      => path to compressing utility (default is "/usr/bin/gzip"),
        tarflags      => flags to pass to 'tar' (default is "-cf"),
        compressflags => flags to pass to 'cmpr' (default is ""),
        tarsuffix     => suffix to put on the tarfile (default is '.tar'),
     );

DESCRIPTION
===========

   This module implements a very simple backup scheme.  In its barest
form, it takes as input a source directory and a destination directory,
and puts a backup of the source directory in the destination directory.
You may specify a maximum number of backups to keep in the directory (the
'keep' parameter).  By setting the 'keep' parameter to n, you will keep
the n most recent backups.  Specify -1 to keep all backups.

   The backup will include a date string (of the format
YYYY-MM-DD_hh-mm-ss) that will be used to figure out which files are the
most recent.  You can also give a string that will be used as the
beginning of the backup's filename (before the date string), which may be
useful if you're keeping backups of several different things in the same
directory.

BUGS
====

   You can't make two backups of the same stuff in one second, because
they'll try to have the same name.

AUTHOR
======

   Ken Williams (ken@forum.swarthmore.edu)

COPYRIGHT
=========

   Copyright 1998 Ken Williams.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1).

split a pathname into pieces
****************************

NAME
====

   fileparse - split a pathname into pieces

   basename - extract just the filename from a path

   dirname - extract just the directory from a path

SYNOPSIS
========

     use File::Basename;

     ($name,$path,$suffix) = fileparse($fullname,@suffixlist)
     fileparse_set_fstype($os_string);
     $basename = basename($fullname,@suffixlist);
     $dirname = dirname($fullname);

     ($name,$path,$suffix) = fileparse("lib/File/Basename.pm","\.pm");
     fileparse_set_fstype("VMS");
     $basename = basename("lib/File/Basename.pm",".pm");
     $dirname = dirname("lib/File/Basename.pm");

DESCRIPTION
===========

   These routines allow you to parse file specifications into useful
pieces using the syntax of different operating systems.

fileparse_set_fstype
     You select the syntax via the routine fileparse_set_fstype().

     If the argument passed to it contains one of the substrings "VMS",
     "MSDOS", "MacOS", "AmigaOS" or "MSWin32", the file specification
     syntax of that operating system is used in future calls to
     fileparse(), basename(), and dirname().  If it contains none of these
     substrings, Unix syntax is used.  This pattern matching is
     case-insensitive.  If you've selected VMS syntax, and the file
     specification you pass to one of these routines contains a "/", they
     assume you are using Unix emulation and apply the Unix syntax rules
     instead, for that function call only.

     If the argument passed to it contains one of the substrings "VMS",
     "MSDOS", "MacOS", "AmigaOS", "os2", "MSWin32" or "RISCOS", then the
     pattern matching for suffix removal is performed without regard for
     case, since those systems are not case-sensitive when opening
     existing files (though some of them preserve case on file creation).

     If you haven't called fileparse_set_fstype(), the syntax is chosen by
     examining the builtin variable $^O according to these rules.

fileparse
     The fileparse() routine divides a file specification into three
     parts: a leading path, a file name, and a suffix.  The path contains
     everything up to and including the last directory separator in the
     input file specification.  The remainder of the input file
     specification is then divided into name and suffix based on the
     optional patterns you specify in `@suffixlist'.  Each element of this
     list is interpreted as a regular expression, and is matched against
     the end of name.  If this succeeds, the matching portion of name is
     removed and prepended to suffix.  By proper use of `@suffixlist', you
     can remove file types or versions for examination.

     You are guaranteed that if you concatenate path, name, and suffix
     together in that order, the result will denote the same file as the
     input file specification.

EXAMPLES
========

   Using Unix file syntax:

     ($base,$path,$type) = fileparse('/virgil/aeneid/draft.book7',
     				    '\.book\d+');

   would yield

     $base eq 'draft'
     $path eq '/virgil/aeneid/',
     $type eq '.book7'

   Similarly, using VMS syntax:

     ($name,$dir,$type) = fileparse('Doc_Root:[Help]Rhetoric.Rnh',
     				   '\..*');

   would yield

     $name eq 'Rhetoric'
     $dir  eq 'Doc_Root:[Help]'
     $type eq '.Rnh'

`basename'
     The basename() routine returns the first element of the list produced
     by calling fileparse() with the same arguments, except that it always
     quotes metacharacters in the given suffixes.  It is provided for
     programmer compatibility with the Unix shell command basename(1).

`dirname'
     The dirname() routine returns the directory portion of the input file
     specification.  When using VMS or MacOS syntax, this is identical to
     the second element of the list produced by calling fileparse() with
     the same input file specification.  (Under VMS, if there is no
     directory information in the input file specification, then the
     current default device and directory are returned.)  When using Unix
     or MSDOS syntax, the return value conforms to the behavior of the
     Unix shell command dirname(1).  This is usually the same as the
     behavior of fileparse(), but differs in some cases.  For example, for
     the input file specification `lib/', fileparse() considers the
     directory name to be `lib/', while dirname() considers the directory
     name to be .).

file locking with flock
***********************

NAME
====

     File::BasicFlock - file locking with flock

SYNOPSIS
========

     use File::BasicFlock;

     lock($filename);

     lock($filename, 'shared');

     lock($filename, undef, 'nonblocking');

     lock($filename, 'shared', 'nonblocking');

     unlock($filename);

DESCRIPTION
===========

   Lock files using the flock() call.  The file to be locked must already
exist.  This is a very thing interface.

AUTHOR
======

   David Muir Sharnoff, <muir@idiom.com>

Binary file reading module
**************************

NAME
====

   File::Binary - Binary file reading module

SYNOPSIS
========

     use File::Binary;

     # open an SWF file as a new File::Binary object ...
      $bin = new File::Binary('test.swf') or die "Couldn't open test.swf\n";
     # ... and check tos ee that it's a valid SWF file
     $bin->getBytes(3) eq 'FWS' or die $bin->getFilename()." is not a valid SWF file\n";

     # get bytes and words
     $format = unpack("C",$bin->getBytes(1));
     $width  = $bin->getWord;

     # get bits and signed bits
     $hasloops = $bin->getBits(1);
     $hasend   = $bin->getSBits(2):

     # find out where you are
     print "File Position : " . $bin->where() . "\n";

     # seek to arbitary places in the file
     $bin->seekTo($bin->where + 100) or die "Couldn't seek to that position\n";

     # make sure that all the bit buffers are flushed and reset
     $bin->initBits;

DESCRIPTION
===========

   *File::Binary* is a Binary file reading module. It is currently being
used to write a suite of modules for manipulating Macromedia SWF files
available from `http:' in this node </gratuitous plug>, and as such is
heavily biased towards this.

BUGS
====

   getSBits does not handle negative numbers well.

   It used to slurp all of the file into an array which made it very
unsuitable for large files. This was fixed in version 0.3 by Leon Brocard.
There may be problems with the filehandle returning undef for no
particular reason.

AUTHOR
======

   Simon Wistow, <simon@twoshortplanks.com>

Share data between processes via filesystem
*******************************************

NAME
====

   File::Cache - Share data between processes via filesystem

DESCRIPTION
===========

   *File::Cache* is a perl module that implements an object storage space
where data is persisted across process boundaries via the filesystem.

   File::Cache builds a cache in the file system using a multi-level
directory structure that looks like this:

     <CACHE_KEY>/<USERNAME>/<NAMESPACE>/[D1]/[D2]/.../<OBJECTS>

   CACHE_KEY is the location of the root level of the cache. The cache key
defaults to <TMPDIR>/File::Cache, where <TMPDIR> is the temporary
directory on your system. USERNAME is the user identifier. This value
defaults to the userid, if it can be determined from the system, or
"nobody" if it can not. <NAMESPACE> defaults to "_default". D1, D2, etc.
are subdirectories that are created to hold the cache objects.  The number
subdirectories depends on the *cache_depth* value, which defaults to 0.
Objects are stored in the cache using a method which depends on the
*persistence_mechanism* value.

SYNOPSIS
========

     use File::Cache;

     # create a cache in the default namespace, where objects
     # do not expire

     my $cache = new File::Cache();

     # create a user-private cache in the specified
     # namespace, where objects will expire in one day, and
     # will automatically be removed from the cache.

     my $cache = new File::Cache( { namespace  => 'MyCache',
                                    expires_in => 86400,
                                    filemode => 0600 } );

     # create a public cache in the specified namespace,
     # where objects will expire in one day, but will not be
     # removed from the cache automatically.

     my $cache = new File::Cache( { namespace  => 'MyCache',
                                    expires_in => 86400,
                                    username => 'shared_user',
                                    auto_remove_stale => 0,
                                    filemode => 0666 } );

     # create a cache readable by the user and the user's
     # group in the specified namespace, where objects will
     # expire in one day, but may be removed from the cache
     # earlier if the size becomes more than a megabyte. Also,
     # request that the cache use subdirectories to increase
     # performance of large number of objects

     my $cache = new File::Cache( { namespace  => 'MyCache',
                                    expires_in => 86400,
                                    max_size => 1048576,
                                    username => 'shared_user',
                                    filemode => 0660,
     			        cache_depth => 3 } );

     # store a value in the cache (will expire in one day)

     $cache->set("key1", "value1");

     # retrieve a value from the cache

     $cache->get("key1");

     # retrieve a stale value from the cache.
     # (Undefined behavior if auto_remove_stale is 1)

     $cache->get_stale("key1");

     # store a value that expires in one hour

     $cache->set("key2", "value2", 3600);

     # reduce the cache size to 3600 bytes

     $cache->reduce_size(3600);

     # clear this cache's contents

     $cache->clear();

     # delete all namespaces from the filesystem

     File::Cache::CLEAR();

TYPICAL USAGE
-------------

   A typical scenario for this would be a mod_perl or perl CGI
application.  In a multi-tier architecture, it is likely that a trip from
the front-end to the database is the most expensive operation, and that
data may not change frequently.  Using this module will help keep that
data on the front-end.

   Consider the following usage in a mod_perl application, where a
mod_perl application serves out images that are retrieved from a database.
Those images change infrequently, but we want to check them once an hour,
just in case.

   my $imageCache = new Cache( { namespace => 'Images',
          expires_in => 3600 } );

   my $image = $imageCache->get("the_requested_image");

   if (!$image) {

     # $image = [expensive database call to get the image]

     $imageCache->set("the_requested_image", $image);

   }

   That bit of code, executed in any instance of the mod_perl/httpd
process will first try the filesystem cache, and only perform the
expensive database call if the image has not been fetched before, has
timed out, or the cache has been cleared.

   The current implementation of this module automatically removes expired
items from the cache when the get() method is called and the
auto_remove_stale setting is true.  Automatic removal does not occur when
the set() method is called, which means that the cache can become polluted
with expired items if many items are stored in the cache for short periods
of time, and are rarely accessed. This is a design decision that favors
efficiency in the common case, where items are accessed frequently. If you
want to limit cache growth, see the max_size option, which will
automatically shrink the cache when the set() method is called. (max_size
is unaffected by the value of auto_remove_stale.)

   Be careful that you call the purge method periodically if
auto_remove_stale is 0 and max_size has its default value of unlimited
size. In this configuration, the cache size will be a function of the
number of items inserted into the cache since the last purge. (i.e. It can
grow extremely large if you put lots of different items in the cache.)

METHODS
-------

new(\%options)
     Creates a new instance of the cache object.  The constructor takes a
     reference to an options hash which can contain any or all of the
     following:

    $options{namespace}
          Namespaces provide isolation between objects.  Each cache refers
          to one and only one namespace.  Multiple caches can refer to the
          same namespace, however.  While specifying a namespace is not
          required, it is recommended so as not to have data collide.

    $options{expires_in}
          If the "expires_in" option is set, all objects in this cache
          will be cleared in that number of seconds.  It can be overridden
          on a per-object basis.  If expires_in is not set, the objects
          will never expire unless explicitly set.

    $options{cache_key}
          The "cache_key" is used to determine the underlying filesystem
          namespace to use.  In typical usage, leaving this unset and
          relying on namespaces alone will be more than adequate.

    $options{username}
          The "username" is used to explicitely set the username. This is
          useful for cases where one wishes to share a cache among
          multiple users. If left unset, the value will be the current
          user's username. (Also see $options{filemode}.)  Note that the
          username is not used to set ownership of the cache files - the
          i.e. the username does not have to be a user of the system.

    $options{filemode}
          "filemode" specifies the permissions for cache files. This is
          useful for cases where one wishes to share a cache among
          multiple users. If left unset, the value will be "u", indicating
          that only the current user can read an write the cache files.
          See the filemode() method documentation for the specification
          syntax.

    $options{max_size}
          "max_size" specifies the maximum size of the cache, in bytes.
          Cache objects are removed during the set() operation in order to
          reduce the cache size before the new cache value is added. See
          the reduce_size() documentation for the cache object removal
          policy. The max_size will be maintained regardless of the value
          of auto_remove_stale.

    $options(auto_remove_stale}
          "auto_remove_stale" specifies that the cache should remove
          expired objects from the cache when they are requested.

    $options(cache_depth}
          "cache_depth" specifies the depth of the subdirectories that
          should be created.  This is helpful when especially large
          numbers of objects are being cached (>1000) at once.  The
          optimal number of files per directory is dependent on the type
          of filesystem, so some hand-tuning may be required.

*set($identifier, $object, $expires_in)*
     Adds an object to the cache.  set takes the following parameters:

    $identifier
          The key the refers to this object.

    $object
          The object to be stored.  This any Storable or Data::Dumper-able
          scalar or (optionally blessed) ref.  Filehandles and database
          handles can not be stored, but most other references to objects
          can be.

    $expires_in *(optional)*
          The object will be cleared from the cache in this number of
          seconds.  Overrides the default expires_in value for the cache.

get($identifier)
     get retrieves an object from the cache.  If the object referred to by
     the identifier exists in the cache and has not expired then then
     object will be returned.  If the object does not exist then get will
     return undef.  If the object does exist but has expired then get will
     return undef and, depending on the setting of auto_remove_stale,
     remove the expired object from the cache.

    $identifier
          The key referring to the object to be retrieved.

get_stale($identifier)
     get_stale retrieves objects that have expired from the cache.
     Normally, expired objects are removed automatically and can not be
     retrieved via get_stale, but if the auto_remove_stale option is set to
     false, then expired objects will be left in the cache.  get_stale
     returns undef if the object does not exist at all or has not expired
     yet.

    $identifier
          The key referring to the object to be retrieved.

remove($identifier)
     Removes an object from the cache.

    $identifier
          The key referring to the object to be removed.

clear()
     Removes all objects from this cache.

purge()
     Removes all objects that have expired

size()
     Return an estimate of the disk usage of the current namespace.

reduce_size($size)
     Reduces the size of the cache so that it is below $size. Note that the
     cache size is approximate, and may slightly exceed the value of $size.

     Cache objects are removed in order of nearest expiration time, or
     latest access time if there are no cache objects with expiration
     times. (If there are a mix of cache objects with expiration times and
     without, the ones with expiration times are removed first.)
     reduce_size takes the following parameter:

    $size
          The new target cache size.

get_creation_time($identifier)
     Gets the time at which the data associated with $identifier was stored
     in the cache. Returns undef if $identifier is not cached.

    $identifier
          The key referring to the object to be retrieved.

get_expiration_time($identifier)
     Gets the time at which the data associated with $identifier will
     expire from the cache. Returns undef if $identifier is not cached.

    $identifier
          The key referring to the object to be retrieved.

get_global_expires_in()
     Returns the default number of seconds before an object in the cache
     expires.

set_global_expires_in($global_expires_in)
     Sets the default number of seconds before an object in the cache
     expires.  set_global_expires_in takes the following parameter:

    $global_expires_in
          The default number of seconds before an object in the cache
          expires.  It should be a number greater than zero,
          $File::Cache::sEXPIRES_NEVER, or $File::Cache::sEXPIRES_NOW.

get_auto_remove_stale()
     Returns whether or not the cache will automatically remove objects
     after they expire.

set_auto_remove_stale($auto_remove_stale)
     Sets whether or not the cache will automatically remove objects after
     they expire.  set_auto_remove_stale takes the following parameter:

    $auto_remove_stale
          The new auto_remove_stale value.  If $auto_remove_stale is 1 or
          $File::Cache::sTRUE, then the cache will automatically remove
          items when they are being retrieved if they have expired.  If
          $auto_remove_stale is 0 or $File::Cache::sFALSE, the cache will
          only remove expired items when the purge() method is called, or
          if max_size is set.  Note that the behavior of get_stale is
          undefined if $auto_remove_stale is true.

get_username()
     Returns the username that is currently being used to define the
     location of this cache.

set_username($username)
     Sets the username that is currently being used to define the location
     of this cache.  set_username takes the following parameter:

    $username
          The username that is to be used to define the location of this
          cache. It is not directly used to determine the ownership of the
          cache files, but can be used to isolate sections of a cache for
          different permissions.

get_namespace()
     Returns the current cache namespace.

set_namespace($namespace)
     Sets the cache namespace. set_namespace takes the following parameter:

    $namespace
          The namespace that is to be used by the cache. The namespace can
          be used to isolate sections of a cache.

get_max_size()
     Returns the current cache maximum size. $File::Cache::sNO_MAX_SIZE
     indicates no maximum size.

set_max_size($max_size)
     Sets the maximum cache size. The cache size is reduced as necessary.
     set_max_size takes the following parameter:

    $max_size
          The maximum size of the cache. $File::Cache::sNO_MAX_SIZE
          indicates no maximum size.

get_cache_depth()
     Returns the current cache depth.

set_cache_depth($cache_depth)
     Sets the cache depth. Consider calling clear() before resetting the
     cache depth in order to prevent inaccessible cache objects from
     occupying disk space. set_cache_depth takes the following parameter:

    $cache_depth
          The depth of subdirectories that are to be used by the cache when
          storing cache objects.

get_persistence_mechanism()
     Returns the current cache persistence mechanism.

set_persistence_mechanism($persistence_mechanism)
     Sets the cache persistence mechanism. This method clears the cache in
     order to ensure consistent cache objects. set_persistence_mechanism
     takes the following parameter:

    $persistence_mechanism
          The persistence mechanism that is to be used by the cache. This
          value can be either "Storable" or "Data::Dumper".

get_filemode()
     Returns the filemode specification for newly created cache objects.

set_filemode($mode)
     Sets the filemode specification for newly created cache objects.
     set_filemode takes the following parameter:

    $mode
          The file mode - a numerical mode identical to that used by
          chmod(). See the chmod() documentation for more information.

File::Cache::CLEAR($cache_key)
     Removes this cache and all the associated namespaces from the
     filesystem.  CLEAR takes the following parameter:

    $cache_key *(optional)*
          Specifies the filesystem data to be cleared.  Needed only if a
          cache was created with a non-standard cache key.

File::Cache::PURGE($cache_key)
     Removes all objects in all namespaces that have expired.  PURGE takes
     the following parameter:

    $cache_key *(optional)*
          Specifies the filesystem data to be purged.  Needed only if a
          cache was created with a non-standard cache key.

File::Cache::SIZE($cache_key)
     Roughly estimates the amount of memory in use.  SIZE takes the
     following parameter:

    $cache_key *(optional)*
          Specifies the filesystem data to be examined.  Needed only if a
          cache was created with a non-standard cache key.

*File::Cache::REDUCE_SIZE($size, $cache_key)*
     Reduces the size of the cache so that it is below $size. Note that the
     cache size is approximate, and may slightly exceed the value of $size.

     Cache objects are removed in order of nearest expiration time, or
     latest access time if there are no cache objects with expiration
     times. (If there are a mix of cache objects with expiration times and
     without, the ones with expiration times are removed first.)
     REDUCE_SIZE takes the following parameters:

    $size
          The new target cache size.

    $cache_key *(optional)*
          Specifies the filesystem data to be examined.  Needed only if a
          cache was created with a non-standard cache key.

BUGS
====

   * The root of the cache namespace is created with global read/write
     permissions.

SEE ALSO
========

   IPC::Cache, Storable, Data::Dumper

AUTHOR
======

   DeWitt Clinton <dewitt@avacet.com>, and please see the CREDITS file

Perl implementation of cat(1)
*****************************

NAME
====

   File::Cat - Perl implementation of cat(1)

SYNOPSIS
========

     use File::Cat;

     cat ('/etc/motd', \*STDOUT)
     	or die "Can't cat /etc/motd: $!";

DESCRIPTION
===========

   File::Cat is a module of adventure, danger, and low cunning. With it,
you will explore some of the most inane programs ever seen by mortals. No
computer should be without one!

FUNCTIONS
=========

   * cat EXPR, *FILEHANDLE*

     Copies data from EXPR to FILEHANDLE, or returns false if an error
     occurred.  EXPR can be either an open readable filehandle or a
     filename to use as input.

   * cattail EXPR, *FILEHANDLE*

     Prints EXPR to FILEHANDLE - backwards, line by line - or returns
     false if an error occurred. Again, EXPR can be either a filehandle or
     a filename.

AUTHOR
======

   Dennis Taylor, <corbeau@execpc.com>

APOLOGIES TO...
===============

   Marc Blank.

SEE ALSO
========

   cat(1)

run many filetest checks on a tree
**********************************

NAME
====

   validate - run many filetest checks on a tree

SYNOPSIS
========

     use File::CheckTree;

     $warnings += validate( q{
     	/vmunix                 -e || die
     	/boot                   -e || die
     	/bin                    cd
     	    csh                 -ex
     	    csh                 !-ug
     	    sh                  -ex
     	    sh                  !-ug
     	/usr                    -d || warn "What happened to $file?\n"
     });

DESCRIPTION
===========

   The validate() routine takes a single multiline string consisting of
lines containing a filename plus a file test to try on it.  (The file test
may also be a "cd", causing subsequent relative filenames to be
interpreted relative to that directory.)  After the file test you may put
`|| die' to make it a fatal error if the file test fails.  The default is
`|| warn'.  The file test may optionally have a "!' prepended to test for
the opposite condition.  If you do a cd and then list some relative
filenames, you may want to indent them slightly for readability.  If you
supply your own die() or warn() message, you can use $file to interpolate
the filename.

   Filetests may be bunched:  "-rwx" tests for all of -r, -w, and -x.
Only the first failed test of the bunch will produce a warning.

   The routine returns the number of warnings issued.

Compare files or filehandles
****************************

NAME
====

   File::Compare - Compare files or filehandles

SYNOPSIS
========

     use File::Compare;

     if (compare("file1","file2") == 0) {
         print "They're equal\n";
     }

DESCRIPTION
===========

   The File::Compare::compare function compares the contents of two
sources, each of which can be a file or a file handle.  It is exported
from File::Compare by default.

   File::Compare::cmp is a synonym for File::Compare::compare.  It is
exported from File::Compare only by request.

   File::Compare::compare_text does a line by line comparison of the two
files. It stops as soon as a difference is detected. compare_text()
accepts an optional third argument: This must be a CODE reference to a
line comparison function, which returns 0 when both lines are considered
equal. For example:

     compare_text($file1, $file2)

   is basically equivalent to

     compare_text($file1, $file2, sub {$_[0] ne $_[1]} )

RETURN
======

   File::Compare::compare return 0 if the files are equal, 1 if the files
are unequal, or -1 if an error was encountered.

AUTHOR
======

   File::Compare was written by Nick Ing-Simmons.  Its original
documentation was written by Chip Salzenberg.

Copy files or filehandles
*************************

NAME
====

   File::Copy - Copy files or filehandles

SYNOPSIS
========

     use File::Copy;

     copy("file1","file2");
       	copy("Copy.pm",\*STDOUT);'
     move("/dev1/fileA","/dev2/fileB");

     use POSIX;
     	use File::Copy cp;

     $n=FileHandle->new("/dev/null","r");
     cp($n,"x");'

DESCRIPTION
===========

   The File::Copy module provides two basic functions, copy and move,
which are useful for getting the contents of a file from one place to
another.

   * The copy function takes two parameters: a file to copy from and a
     file to copy to. Either argument may be a string, a FileHandle
     reference or a FileHandle glob. Obviously, if the first argument is a
     filehandle of some sort, it will be read from, and if it is a file
     name it will be opened for reading. Likewise, the second argument
     will be written to (and created if need be).

     *Note that passing in files as handles instead of names may lead to
     loss of information on some operating systems; it is recommended that
     you use file names whenever possible.*  Files are opened in binary
     mode where applicable.  To get a consistent behaviour when copying
     from a filehandle to a file, use binmode on the filehandle.

     An optional third parameter can be used to specify the buffer size
     used for copying. This is the number of bytes from the first file,
     that wil be held in memory at any given time, before being written to
     the second file. The default buffer size depends upon the file, but
     will generally be the whole file (up to 2Mb), or 1k for filehandles
     that do not reference files (eg. sockets).

     You may use the syntax `use File::Copy "cp"' to get at the "cp" alias
     for this function. The syntax is *exactly* the same.

   * The move function also takes two parameters: the current name and the
     intended name of the file to be moved.  If the destination already
     exists and is a directory, and the source is not a directory, then
     the source file will be renamed into the directory specified by the
     destination.

     If possible, move() will simply rename the file.  Otherwise, it copies
     the file to the new location and deletes the original.  If an error
     occurs during this copy-and-delete process, you may be left with a
     (possibly partial) copy of the file under the destination name.

     You may use the "mv" alias for this function in the same way that you
     may use the "cp" alias for copy.

   File::Copy also provides the `syscopy' routine, which copies the file
specified in the first parameter to the file specified in the second
parameter, preserving OS-specific attributes and file structure.  For Unix
systems, this is equivalent to the simple copy routine.  For VMS systems,
this calls the `rmscopy' routine (see below).  For OS/2 systems, this
calls the `syscopy' XSUB directly. For Win32 systems, this calls
`Win32::CopyFile'.

Special behaviour if `syscopy' is defined (OS/2, VMS and Win32)
---------------------------------------------------------------

   If both arguments to copy are not file handles, then copy will perform
a "system copy" of the input file to a new output file, in order to
preserve file attributes, indexed file structure, etc.  The buffer size
parameter is ignored.  If either argument to copy is a handle to an opened
file, then data is copied using Perl operators, and no effort is made to
preserve file attributes or record structure.

   The system copy routine may also be called directly under VMS and OS/2
as `File::Copy::syscopy' (or under VMS as `File::Copy::rmscopy', which is
the routine that does the actual work for syscopy).

rmscopy($from,$to[,$date_flag])
     The first and second arguments may be strings, typeglobs, typeglob
     references, or objects inheriting from IO::Handle; they are used in
     all cases to obtain the *filespec* of the input and output files,
     respectively.  The name and type of the input file are used as
     defaults for the output file, if necessary.

     A new version of the output file is always created, which inherits
     the structure and RMS attributes of the input file, except for owner
     and protections (and possibly timestamps; see below).  All data from
     the input file is copied to the output file; if either of the first
     two parameters to `rmscopy' is a file handle, its position is
     unchanged.  (Note that this means a file handle pointing to the
     output file will be associated with an old version of that file after
     `rmscopy' returns, not the newly created version.)

     The third parameter is an integer flag, which tells `rmscopy' how to
     handle timestamps.  If it is < 0, none of the input file's timestamps
     are propagated to the output file.  If it is > 0, then it is
     interpreted as a bitmask: if bit 0 (the LSB) is set, then timestamps
     other than the revision date are propagated; if bit 1 is set, the
     revision date is propagated.  If the third parameter to `rmscopy' is
     0, then it behaves much like the DCL COPY command: if the name or
     type of the output file was explicitly specified, then no timestamps
     are propagated, but if they were taken implicitly from the input
     filespec, then all timestamps other than the revision date are
     propagated.  If this parameter is not supplied, it defaults to 0.

     Like copy, `rmscopy' returns 1 on success.  If an error occurs, it
     sets $!, deletes the output file, and returns 0.

RETURN
======

   All functions return 1 on success, 0 on failure.  $! will be set if an
error was encountered.

AUTHOR
======

   File::Copy was written by Aaron Sherman *<ajs@ajs.com>* in 1995, and
updated by Charles Bailey *<bailey@newman.upenn.edu>* in 1996.

Persistent counter class
************************

NAME
====

   File::CounterFile - Persistent counter class

SYNOPSIS
========

     use File::CounterFile;
     $c = new File::CounterFile "COUNTER", "aa00";

     $id = $c->inc;
     open(F, ">F$id");

DESCRIPTION
===========

   This module implements a persistent counter class.  Each counter is
represented by a separate file in the file system.  File locking is
applied, so multiple processes might try to access the same counters at
the same time without risk of counter destruction.

   You give the file name as the first parameter to the object constructor
(new).  The file is created if it does not exist.

   If the file name does not start with "/" or ".", then it is interpreted
as a file relative to `$File::CounterFile::DEFAULT_DIR'.  The default
value for this variable is initialized from the environment variable
TMPDIR, or `/usr/tmp' is no environment variable is defined.  You may want
to assign a different value to this variable before creating counters.

   If you pass a second parameter to the constructor, that sets the
initial value for a new counter.  This parameter only takes effect when
the file is created (i.e. it does not exist before the call).

   When you call the `inc()' method, you increment the counter value by
one. When you call `dec()' the counter value is decrementd.  In both cases
the new value is returned.  The `dec()' method only works for numerical
counters (digits only).

   You can peek at the value of the counter (without incrementing it) by
using the value() method.

   The counter can be locked and unlocked with the lock() and unlock()
methods.  Incrementing and value retrieval is faster when the counter is
locked, because we do not have to update the counter file all the time.
You can query whether the counter is locked with the `locked()' method.

   There is also an operator overloading interface to the
File::CounterFile object.  This means that you might use the `++' operator
for incrementing the counter, - operator for decrementing and you can
interpolate counters diretly into strings.

BUGS
====

   It uses flock(2) to lock the counter file.  This does not work on all
systems.  Perhaps we should use the File::Lock module?

COPYRIGHT
=========

   Copyright (c) 1995-1998 Gisle Aas. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Gisle Aas <aas@sn.no>

Perl extension for getting file descriptions
********************************************

NAME
====

   File::Descriptions - Perl extension for getting file descriptions

SYNOPSIS
========

     use File::Descriptions;

     $d = new File::Descriptions;
     %descriptions = $d->gethash($directory);

DESCRIPTION
===========

   This extension retrieves file descriptions from common mirror
distributions like SimtelNet, Debian, etc...

   It should auto-recognize the presence of file descriptions for a
particular type soon there will be more methods implemented

AUTHOR
======

   Pedro Leite, leite@ua.pt

SEE ALSO
========

   perl(1).

DOS like globbing and then some
*******************************

NAME
====

   File::DosGlob - DOS like globbing and then some

SYNOPSIS
========

     require 5.004;

     # override CORE::glob in current package
     use File::DosGlob 'glob';

     # override CORE::glob in ALL packages (use with extreme caution!)
     use File::DosGlob 'GLOBAL_glob';

     @perlfiles = glob  "..\\pe?l/*.p?";
     print <..\\pe?l/*.p?>;

     # from the command line (overrides only in main::)
     > perl -MFile::DosGlob=glob -e "print <../pe*/*p?>"

DESCRIPTION
===========

   A module that implements DOS-like globbing with a few enhancements.  It
is largely compatible with perlglob.exe (the M$ setargv.obj version) in
all but one respect-it understands wildcards in directory components.

   For example, `<..\\l*b\\file/*glob.p?'> will work as expected (in that
it will find something like '..\lib\File/DosGlob.pm' alright).  Note that
all path components are case-insensitive, and that backslashes and forward
slashes are both accepted, and preserved.  You may have to double the
backslashes if you are putting them in literally, due to double-quotish
parsing of the pattern by perl.

   Spaces in the argument delimit distinct patterns, so `glob('*.exe
*.dll')' globs all filenames that end in `.exe' or `.dll'.  If you want to
put in literal spaces in the glob pattern, you can escape them with either
double quotes, or backslashes.  e.g. `glob('c:/"Program Files"/*/*.dll')',
or `glob('c:/Program\ Files/*/*.dll')'.  The argument is tokenized using
`Text::ParseWords::parse_line()', so see Text/ParseWords,
for details of the quoting rules used.

   Extending it to csh patterns is left as an exercise to the reader.

EXPORTS (by request only)
=========================

   glob()

BUGS
====

   Should probably be built into the core, and needs to stop pandering to
DOS habits.  Needs a dose of optimizium too.

AUTHOR
======

   Gurusamy Sarathy <gsar@activestate.com>

HISTORY
=======

   * Support for globally overriding glob() (GSAR 3-JUN-98)

   * Scalar context, independent iterator context fixes (GSAR 15-SEP-97)

   * A few dir-vs-file optimizations result in glob importation being 10
     times faster than using perlglob.exe, and using perlglob.bat is only
     twice as slow as perlglob.exe (GSAR 28-MAY-97)

   * Several cleanups prompted by lack of compatible perlglob.exe under
     Borland (GSAR 27-MAY-97)

   * Initial version (GSAR 20-FEB-97)

SEE ALSO
========

   perl

   perlglob.bat

   Text::ParseWords

Perl extension for blah blah blah
*********************************

NAME
====

   File::FDpasser - Perl extension for blah blah blah

SYNOPSIS
========

     use File::FDpasser;

     @fd=spipe();
     die "spipe() failed\n" if !defined(@fd);

     $LS=endp_create("/tmp/openserver") || die "endp_create: $!\n";

     $rin = ''; vec($rin,fileno($LS),1) = 1; $timeout=0.5;
     ($nfound,$timeleft) = select($rout=$rin, '', $eout=$rin, $timeout);

     $fh=serv_accept_fh($LS,$uid) || die "serv_accept: $!\n";
     $rc=send_file($fh,*FH{IO});

     $fh=endp_connect("/tmp/openserver") || die "endp_connect: $!\n";
     $newfh=recv_fh($fh);

DESCRIPTION
===========

   File::FDpasser is a module for passing open filedescriptors to and from
other scripts or even other programs.

   An endpoint is just a Filehandle that can be used to send and receive
filehandles over.  To create two endpoints before forking spipe() is used
- it returns two endpoints or undef on failiure.

   If the processes are unrelated or can not use spipe() for some reason,
it is possible to create a 'server endpoint' in the filesystem by calling
endp_create().  That endpoint can be polled for incomming connections
similar to how sockets are polled for incomming connection.  To accept an
incomming connection serv_accept_fh() is used. It returns a filehandle or
undef on failiure.

   To connect to a server endpoint from a client program endp_connect() is
used. It returns a filehandle to an open connection.

   Irregardless of how the endpoints were created send_file() is used to
send an open filehandle to the process who has other end of the pipe or
socket.  The first argument to send_file is the connection to send the
open handle over.  The second argument is the actual handle to send.
Similarly recv_fh() is always used to receive an open filehandle.  Both
return false on failiure.

How does it work
================

   Under BSD derived systems open filedescriptors are passed over unix
domain sockets.  SysV systems however pass them over streams.

   This means to create that under BSD socketpair() is used to create the
socket endpoints.  While SysV uses pipe() since pipe on SysV creates a
bidirectional stream based pipe.

   This is all nice and dandy if you are going to fork later on since both
child and parent are going to have an endpoint to read from or write to.

   endp_create() is used to create a server endpoint that can be polled
for incomming connections with poll or select.  Under BSD the perl call
socket() is used to create a Unix Domain Socket in the filesystem.  Under
SysV the perl function pipe() is called followed by an XS function that
pushes the conn_ld module on one end of the stream pipe and then calles
fattach to attach the pipe end to a point in the filesystem.

   To connect to a server endpoint in BSD a socket is created (but not
bound to any point in the filesystem) and a connect call is made.  In SysV
a normal open() in perl is made.

   The actuall sending of filedescriptors is done with XS functions that
under BSD use sendmsg for sending and recvmsg for reciving.  SysV uses an
ioctl call to send and receive (getmsg is actually a wrapper for receiving
the fd - a uid of the connecting process is discarded since it's not
reliably avaliable for BSD system too).

AUTHOR
======

   amh@mbl.is

SEE ALSO
========

   perl(1), sendmsg, recvmsg, ioctl, ioctl_list, select, poll.  IO::Handle.
http://gauss.mbl.is/~amh/FDpasser/.  Advanced Programming in the UNIX
Environment, Addison-Wesley, 1992.  UNIX Network Programming, Prentice
Hall, 1990.

traverse a file tree
********************

NAME
====

   find - traverse a file tree

   finddepth - traverse a directory structure depth-first

SYNOPSIS
========

     use File::Find;
     find(\&wanted, '/foo', '/bar');
     sub wanted { ... }

     use File::Find;
     finddepth(\&wanted, '/foo', '/bar');
     sub wanted { ... }

     use File::Find;
     find({ wanted => \&process, follow => 1 }, '.');

DESCRIPTION
===========

   The first argument to find() is either a hash reference describing the
operations to be performed for each file, or a code reference.

   Here are the possible keys for the hash:

`wanted'
     The value should be a code reference.  This code reference is called
     *the wanted() function* below.

`bydepth'
     Reports the name of a directory only AFTER all its entries have been
     reported.  Entry point finddepth() is a shortcut for specifying `{
     bydepth =' 1 }> in the first argument of find().

`follow'
     Causes symbolic links to be followed. Since directory trees with
     symbolic links (followed) may contain files more than once and may
     even have cycles, a hash has to be built up with an entry for each
     file.  This might be expensive both in space and time for a large
     directory tree. See *follow_fast* and *follow_skip* below.  If either
     *follow* or *follow_fast* is in effect:

        * It is guarantueed that an lstat has been called before the user's
          *wanted()* function is called. This enables fast file checks
          involving  _.

        * There is a variable `$File::Find::fullname' which holds the
          absolute pathname of the file with all symbolic links resolved

`follow_fast'
     This is similar to *follow* except that it may report some files more
     than once. It does detect cycles however.  Since only symbolic links
     have to be hashed, this is much cheaper both in space and time.  If
     processing a file more than once (by the user's *wanted()* function)
     is worse than just taking time, the option *follow* should be used.

`follow_skip'
     `follow_skip==1', which is the default, causes all files which are
     neither directories nor symbolic links to be ignored if they are about
     to be processed a second time. If a directory or a symbolic link are
     about to be processed a second time, File::Find dies.
     `follow_skip==0' causes File::Find to die if any file is about to be
     processed a second time.  `follow_skip==2' causes File::Find to
     ignore any duplicate files and dirctories but to proceed normally
     otherwise.

`no_chdir'
     Does not chdir() to each directory as it recurses. The wanted()
     function will need to be aware of this, of course. In this case, $_
     will be the same as `$File::Find::name'.

untaint
     If find is used in taint-mode (-T command line switch or if EUID !=
     UID or if EGID != GID) then internally directory names have to be
     untainted before they can be cd'ed to. Therefore they are checked
     against a regular expression *untaint_pattern*. Note, that all names
     passed to the user's *wanted()* function are still tainted.

`untaint_pattern'
     See above. This should be set using the qr quoting operator.  The
     default is set to  `qr|^([-+@\w./]+)$|'.  Note that the paranthesis
     which are vital.

`untaint_skip'
     If set, directories (subtrees) which fail the *untaint_pattern* are
     skipped. The default is to 'die' in such a case.

   The wanted() function does whatever verifications you want.
`$File::Find::dir' contains the current directory name, and $_ the current
filename within that directory.  `$File::Find::name' contains the complete
pathname to the file. You are chdir()'d to `$File::Find::dir' when the
function is called, unless `no_chdir' was specified.  When <follow> or
<follow_fast> are in effect there is also a `$File::Find::fullname'.  The
function may set `$File::Find::prune' to prune the tree unless `bydepth'
was specified.  Unless `follow' or `follow_fast' is specified, for
compatibility reasons (find.pl, find2perl) there are in addition the
following globals available: `$File::Find::topdir', `$File::Find::topdev',
`$File::Find::topino', `$File::Find::topmode' and `$File::Find::topnlink'.

   This library is useful for the find2perl tool, which when fed,

     find2perl / -name .nfs\* -mtime +7 \
         -exec rm -f {} \; -o -fstype nfs -prune

   produces something like:

     sub wanted {
         /^\.nfs.*\z/s &&
         (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_)) &&
         int(-M _) > 7 &&
         unlink($_)
         ||
         ($nlink || (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_))) &&
         $dev < 0 &&
         ($File::Find::prune = 1);
     }

   Set the variable `$File::Find::dont_use_nlink' if you're using AFS,
since AFS cheats.

   Here's another interesting wanted function.  It will find all symlinks
that don't resolve:

     sub wanted {
          -l && !-e && print "bogus link: $File::Find::name\n";
     }

   See also the script `pfind' on CPAN for a nice application of this
module.

CAVEAT
======

   Be aware that the option to follow symblic links can be dangerous.
Depending on the structure of the directory tree (including symbolic links
to directories) you might traverse a given (physical) directory more than
once (only if `follow_fast' is in effect).  Furthermore, deleting or
changing files in a symbolically linked directory might cause very
unpleasant surprises, since you delete or change files in an unknown
directory.

file locking with flock
***********************

NAME
====

     File::Flock - file locking with flock

SYNOPSIS
========

     use File::Flock;

     lock($filename);

     lock($filename, 'shared');

     lock($filename, undef, 'nonblocking');

     lock($filename, 'shared', 'nonblocking');

     unlock($filename);

     my $lock = new File::Flock '/somefile';

     lock_rename($oldfilename, $newfilename)

DESCRIPTION
===========

   Lock files using the flock() call.  If the file to be locked does not
exist, then the file is created.  If the file was created then it will be
removed when it is unlocked assuming it's still an empty file.

   Locks can be created by new'ing a *File::Flock* object.  Such locks are
automatically removed when the object goes out of scope.  The unlock()
method may also be used.

   *lock_rename()* is used to tell File::Flock when a file has been renamed
(and thus the locking data that is stored based on the filename should be
moved to a new name).

AUTHOR
======

   David Muir Sharnoff, <muir@idiom.com>

override perl flock() for network or portability purposes
*********************************************************

NAME
====

   FlockDir - override perl flock() for network or portability purposes

SYNOPSIS
========

   use File::FlockDir qw (open close flock);

   open (FH, ">$path");

   flock(FH, 2);

   close FH;

DESCRIPTION
===========

   A flock module for Windows9x and other systems lacking a good perl
flock() function (not platform specific)

   Usage:

   use File::FlockDir qw (open close flock);

   OR (careful)

   use File::FlockDir qw (GLOBAL_open GLOBAL_close GLOBAL_flock);

   Rationale: flock on Win95/98 is badly broken but perl code needs to be
portable. One way to do this is to override perl's open(), flock(), and
close().  We then get an absolute file specification for all opened files
and and use it in a hash to create a unique lock for the file using the
File::LockDir module from *Perl Cookbook*, by Christiansen and Torkington
(O'Reilly, 1998). This module may be included in the CPAN distribution but
belongs to those authors.  New code is deliberately kept at a minimum. As
with nflock(), this will allow flock() to work over a network (usually).

KNOWN PROBLEMS AND LIMITATIONS
==============================

   * May be slow compared to unix flock(). This is mainly due to the fact
     it depends upon non-buffered disk writes (directory creation) for its
     implementation. May be speeded up somewhat by importing and setting
     the variable *$Max_SH_Processes* to a smaller value as long as no more
     than a few processes will be using shared locks at a time on any one
     file.

   * Abnormal termination may leave File::LockDir entries still on the
     drive. This means the directory locks set by File::LockDir may have
     to be removed after a system crash to prevent the module from
     assuming that files locked at the time of the crash are still locked
     later. This may be partially overcome by importing and setting the
     variable *$Assume_LockDir_Zombie_Minutes* to a value equal to the
     maximal number of minutes a lock is to be allowed to exist (defaults
     to one week or 10040 minutes).

   * Since the implementation creates a subdirectory in the directory
     containing the file that you flock(), you must have permission to
     create a directory where the file is located in order to flock() that
     file over the network.

CREDITS
=======

   *Perl Cookbook*, by Tom Christiansen and Nathan Torkington.

   This module is an extension of *Perl Cookbook*'s nflock(), in chapter
7, section 21 (7.21, pp 264-266).

AUTHOR
======

   William Herrera <wherrera@lynxview.com>

Perl extension for BSD glob routine
***********************************

NAME
====

   File::Glob - Perl extension for BSD glob routine

SYNOPSIS
========

     use File::Glob ':glob';
     @list = glob('*.[ch]');
     $homedir = glob('~gnat', GLOB_TILDE | GLOB_ERR);
     if (GLOB_ERROR) {
       # an error occurred reading $homedir
     }

     ## override the core glob (core glob() does this automatically
     ## by default anyway, since v5.6.0)
     use File::Glob ':globally';
     my @sources = <*.{c,h,y}>

     ## override the core glob, forcing case sensitivity
     use File::Glob qw(:globally :case);
     my @sources = <*.{c,h,y}>

     ## override the core glob forcing case insensitivity
     use File::Glob qw(:globally :nocase);
     my @sources = <*.{c,h,y}>

DESCRIPTION
===========

   File::Glob implements the FreeBSD glob(3) routine, which is a superset
of the POSIX glob() (described in IEEE Std 1003.2 "POSIX.2").  The glob()
routine takes a mandatory pattern argument, and an optional flags
argument, and returns a list of filenames matching the pattern, with
interpretation of the pattern modified by the flags variable.  The POSIX
defined flags are:

`GLOB_ERR'
     Force glob() to return an error when it encounters a directory it
     cannot open or read.  Ordinarily glob() continues to find matches.

`GLOB_MARK'
     Each pathname that is a directory that matches the pattern has a slash
     appended.

`GLOB_NOCASE'
     By default, file names are assumed to be case sensitive; this flag
     makes glob() treat case differences as not significant.

`GLOB_NOCHECK'
     If the pattern does not match any pathname, then glob() returns a list
     consisting of only the pattern.  If `GLOB_QUOTE' is set, its effect
     is present in the pattern returned.

`GLOB_NOSORT'
     By default, the pathnames are sorted in ascending ASCII order; this
     flag prevents that sorting (speeding up glob()).

   The FreeBSD extensions to the POSIX standard are the following flags:

`GLOB_BRACE'
     Pre-process the string to expand `{pat,pat,...}' strings like csh(1).
     The pattern '{}' is left unexpanded for historical reasons (and csh(1)
     does the same thing to ease typing of find(1) patterns).

`GLOB_NOMAGIC'
     Same as `GLOB_NOCHECK' but it only returns the pattern if it does not
     contain any of the special characters "*", "?" or "[".  `NOMAGIC' is
     provided to simplify implementing the historic csh(1) globbing
     behaviour and should probably not be used anywhere else.

`GLOB_QUOTE'
     Use the backslash ('\') character for quoting: every occurrence of a
     backslash followed by a character in the pattern is replaced by that
     character, avoiding any special interpretation of the character.
     (But see below for exceptions on DOSISH systems).

`GLOB_TILDE'
     Expand patterns that start with '~' to user name home directories.

`GLOB_CSH'
     For convenience, `GLOB_CSH' is a synonym for `GLOB_BRACE |
     GLOB_NOMAGIC | GLOB_QUOTE | GLOB_TILDE'.

   The POSIX provided `GLOB_APPEND', `GLOB_DOOFFS', and the FreeBSD
extensions `GLOB_ALTDIRFUNC', and `GLOB_MAGCHAR' flags have not been
implemented in the Perl version because they involve more complex
interaction with the underlying C structures.

DIAGNOSTICS
===========

   glob() returns a list of matching paths, possibly zero length.  If an
error occurred, &File::Glob::GLOB_ERROR will be non-zero and $! will be
set.  &File::Glob::GLOB_ERROR is guaranteed to be zero if no error
occurred, or one of the following values otherwise:

`GLOB_NOSPACE'
     An attempt to allocate memory failed.

`GLOB_ABEND'
     The glob was stopped because an error was encountered.

   In the case where glob() has found some matching paths, but is
interrupted by an error, glob() will return a list of filenames and set
&File::Glob::ERROR.

   Note that glob() deviates from POSIX and FreeBSD glob(3) behaviour by
not considering `ENOENT' and `ENOTDIR' as errors - glob() will continue
processing despite those errors, unless the `GLOB_ERR' flag is set.

   Be aware that all filenames returned from File::Glob are tainted.

NOTES
=====

   * If you want to use multiple patterns, e.g. `glob "a* b*"', you should
     probably throw them in a set as in `glob "{a*,b*}'.  This is because
     the argument to glob isn't subjected to parsing by the C shell.
     Remember that you can use a backslash to escape things.

   * On DOSISH systems, backslash is a valid directory separator character.
     In this case, use of backslash as a quoting character (via GLOB_QUOTE)
     interferes with the use of backslash as a directory separator. The
     best (simplest, most portable) solution is to use forward slashes for
     directory separators, and backslashes for quoting. However, this does
     not match "normal practice" on these systems. As a concession to user
     expectation, therefore, backslashes (under GLOB_QUOTE) only quote the
     glob metacharacters '[', ']', '{', '}', '-', '~', and backslash
     itself.  All other backslashes are passed through unchanged.

   * Win32 users should use the real slash.  If you really want to use
     backslashes, consider using Sarathy's File::DosGlob, which comes with
     the standard Perl distribution.

AUTHOR
======

   The Perl interface was written by Nathan Torkington <gnat@frii.com>,
and is released under the artistic license.  Further modifications were
made by Greg Bacon <gbacon@cs.uah.edu> and Gurusamy Sarathy
<gsar@activestate.com>.  The C glob code has the following copyright:

     Copyright (c) 1989, 1993 The Regents of the University of California.
     All rights reserved.

     This code is derived from software contributed to Berkeley by
     Guido van Rossum.

     Redistribution and use in source and binary forms, with or without
     modification, are permitted provided that the following conditions
     are met:

     1. Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
     2. Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.
     3. Neither the name of the University nor the names of its contributors
        may be used to endorse or promote products derived from this software
        without specific prior written permission.

     THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     SUCH DAMAGE.

get home directory for self or other users
******************************************

NAME
====

   File::HomeDir - get home directory for self or other users

SYNOPSIS
========

     use File::HomeDir;
     print "My dir is ", home(), " and root's is ", home('root'), "\n";
     print "My dir is $~{''} and root's is $~{root}\n";
      # These both print the same thing, something like:
      #  "My dir is /home/user/mojo and root's is /"

DESCRIPTION
===========

   This module provides a function, `home', and also ties the
in-all-packages variable `%~'.

home()
     Returns a filespec to this user's home directory.

home($user)
     Returns a filespec to the home directory of the given user, or undef
     if no such user.

     Note that the argument to this must be a defined value, and mustn't be
     a zero-length string, or a fatal error will result.

`$~{$user}'
`$~{username}'
`"...$~{$user}..."'
`"...$~{username}..."'
     This calls home($user) or `home('username')' - except that if you ask
     for `$~{some_user}' and there is no such user, a fatal error results!

     Note that this is especially useful in doublequotish strings, like:

          print "Jojo's .newsrc is ", -s "$~{jojo}/.newsrc", "b long!\n";
           # (helpfully dies if there is no user 'jojo')

     If you want to avoid the fatal errors, first test the value of
     `home('jojo')', which will return undef (instead of dying) in case of
     there being no such user.

     Note, however, that if the hash key is "" or undef (whether thru being
     a literal "", or a scalar whose value is empty-string or undef), then
     this returns zero-argument home(), i.e., your home directory:

`$~{""}'
`$~{undef}'
`"...$~{''}..."'
     These all return home(), i.e., your home directory.

   If running under an OS that doesn't implement `getpwid', this library
tries to provide a sane return value for the no-argument home().  Under
MacOS, for example, it tries returning the pathspec to the desktop folder.
See source for full details.

   Under OSs that don't implement getpwnam (as home($user) calls), you
will always get a failed lookup, just as if you'd tried to look up the
home dir for a nonexistent user on an OS that *does* support getpwnam.

BUGS AND CAVEATS
================

   * One-argument `home($username)' is memoized.  Read the source if you
need it unmemoized.

   * According to the fileio.c in one version of Emacs, MSWindows (NT?)
does have the concept of users having home directories, more or less.  But
I don't know if MSWin ports of Perl allow accessing that with getpwnam.  I
hear that it (currently) doesn't.

   * This documentation gets garbled by some AIX manual formatters.
Consider `perldoc -t File::HomeDir' instead.

COPYRIGHT
=========

   Copyright (c) 2000 Sean M. Burke. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Sean M. Burke `sburke@cpan.org'

Lock and unlock the passwd and shadow files with lckpwdf and ulckpwdf
*********************************************************************

NAME
====

   File::LckPwdF - Lock and unlock the passwd and shadow files with
lckpwdf and ulckpwdf

SYNOPSIS
========

     use File::LckPwdF;

     (lock_passwd(15)) || (die "Can't lock password file:\n$! stopped");

     # ... do stuff with the passwd file ...

     (unlock_passwd()) || (die "Can't unlock password file:\n$! stopped");

DESCRIPTION
===========

   This is a perl module to use *lckpwdf(3)* and *ulckpwdf(3)* to lock the
`/etc/passwd' and (if present) `/etc/shadow' files.

Functions exported automatically
--------------------------------

   *lock_passwd($timeout)*

   $timeout works as follows:

  1. The initial time is checked.

  2. If $timeout is 0, it tries *lckpwdf()* until it succeeds,
     waiting a random time in between.

  3. If $timeout is above 0, it tries *lckpwdf()* once. If          that
     (or any following *lckpwdf()*) succeeds, it returns          1. It
     will try *lckpwdf()* until either it succeeds or the          time is
     greater than the initial time plus $timeout. In          the latter
     case, it returns 0. It waits a random time in          between tries
     of *lckpwdf()*.
        The random timeout is controlled by *$File::LckPwdF::Rand_Wait*,
which is exported on request. It is used via

     sleep int(rand($Rand_Wait) + 1);

   inside an until loop. This sleep is only done if
*$File::LckPwdF::Rand_Wait* is above 0.

   $timeout defaults to *$File::LckPwdF::Default_Timeout*, which is also
exported on request; the initial setting of
*$File::LckPwdF::Default_Timeout* (the default default) is 15 seconds. The
default setting for *$File::LckPwdF::Rand_Wait* is 10 seconds.

   *unlock_passwd()*

   This function uses *ulckpwdf()*. If *lock_passwd()* has previously been
used to lock the passwd file, and *unlock_passwd()* has not been used to
lock it, then it will be used to unlock the passwd file in an END:
statement.  (Admittedly, with many implementations of *lckpwdf()* this is
not necessary, since when a process exits it loses the passwd file lock;
it is present as a safety measure for those systems for which this is not
true.)

Functions exported by request
-----------------------------

   *lckpwdf()* *ulckpwdf()*

   These are the xs-loaded versions of *lckpwdf(3)* and *ulckpwdf(3)*,
respectively.

RETURN VALUE
============

   The *lock_passwd()* and *unlock_passwd()* functions return 1 on success
and 0 on failure.  The return values for *lckpwdf()* and *ulckpwdf()* are
the same as for the system versions (*lckpwdf(3)* and *ulckpwdf(3)*).

ERRORS
======

   If the effective UID is not 0, then *lock_passwd()* and
*unlock_passwd()* set $! to *EACCES* if they fail (they do try once, just
in case you've got a *really* weird setup).

   If the effective UID is 0, in the event of failure, *lock_passwd()*
sets $! to:

  1. if you've already locked the file through *lock_passwd()*,
     *EALREADY*

  2. *EAGAIN* (or *EWOULDBLOCK*, if *EAGAIN* isn't present on your
     system and *EWOULDBLOCK* is; *$File::LckPwdF::EAGAIN*,    which is
     exported on request, is equal to the value    returned).
        *unlock_passwd()*, in the event of failure, sets $! to:

  1. if you've already unlocked the file via *unlock_passwd()* or
     haven't locked it via *lock_passwd()*, *EALREADY*.

  2. *EINVAL*.
        If you try to use a negative number for $timeout with
*lock_passwd($timeout)*, it carps, returns 0, and sets $! to *EINVAL*.

CAVEATS
=======

   This program only works if your system has *lckpwdf(3)* and
*ulckpwdf(3)*. This should be true of SVR4 systems; others will vary. If
you use *lock_passwd()* and *unlock_passwd()*, *lckpwdf(3)* and
*ulckpwdf(3)* need to have return values of 0+ for success and below 0
(usually -1) for failure.

   The timeout period for *lock_passwd()* is approximate, since many
versions of *lckpwdf()* will keep trying for a total of 15 seconds to lock
the passwd (and possibly shadow) files before they return an appropriate
value.

   This module only keeps track on its own of whether the passwd file is
locked if you always use *lock_passwd()* and *unlock_passwd()*. If you use
*lckpwdf()* or *ulckpwdf()* by themselves for locking and unlocking, you
will need to set *$File::LckPwdF::Passwd_Locked* to 1 for locked and 0 for
unlocked yourself.

BUGS
====

   I haven't written any good automated tests for this program yet. If
anyone's interested, be my guest (or for any other improvements, of
course).

AUTHOR
======

   E. Allen Smith, <easmith@beatrice.rutgers.edu>. Copyright 1998. This
software may be used, distributed, modified, etcetera under the same
conditions as *perl*.

FILES
=====

   `/etc/passwd', `/etc/shadow'

SEE ALSO
========

   `perl(1)' in this node, `lckpwdf(3)' in this node, `ulckpwdf(3)' in
this node

parse directory listing
***********************

NAME
====

   parse_dir - parse directory listing

SYNOPSIS
========

     use File::Listing;
     for (parse_dir(`ls -l`)) {
         ($name, $type, $size, $mtime, $mode) = @$_;
         next if $type ne 'f'; # plain file
         #...
     }

     # directory listing can also be read from a file
     open(LISTING, "zcat ls-lR.gz|");
     $dir = parse_dir(\*LISTING, '+0000');

DESCRIPTION
===========

   The parse_dir() routine can be used to parse directory listings.
Currently it only understand Unix `'ls -l'' and `'ls -lR'' format.  It
should eventually be able to most things you might get back from a ftp
server file listing (LIST command), i.e. VMS listings, NT listings, DOS
listings,...

   The first parameter to parse_dir() is the directory listing to parse.
It can be a scalar, a reference to an array of directory lines or a glob
representing a filehandle to read the directory listing from.

   The second parameter is the time zone to use when parsing time stamps
in the listing. If this value is undefined, then the local time zone is
assumed.

   The third parameter is the type of listing to assume.  The values will
be strings like 'unix', 'vms', 'dos'.  Currently only 'unix' is
implemented and this is also the default value.  Ideally, the listing type
should be determined automatically.

   The fourth parameter specifies how unparseable lines should be treated.
Values can be 'ignore', 'warn' or a code reference.  Warn means that the
perl warn() function will be called.  If a code reference is passed, then
this routine will be called and the return value from it will be
incorporated in the listing.  The default is 'ignore'.

   Only the first parameter is mandatory.

   The return value from parse_dir() is a list of directory entries.  In a
scalar context the return value is a reference to the list.  The directory
entries are represented by an array consisting of [ $filename, $filetype,
$filesize, $filetime, $filemode ].  The $filetype value is one of the
letters 'f', 'd', 'l' or '?'.  The $filetime value is the seconds since
Jan 1, 1970.  The $filemode is a bitmask like the mode returned by stat().

CREDITS
=======

   Based on lsparse.pl (from Lee McLoughlin's ftp mirror package) and
Net::FTP's parse_dir (Graham Barr).

Guess file type
***************

NAME
====

   File::MMagic - Guess file type

SYNOPSIS
========

     use File::MMagic;
     use FileHandle;

     $mm = new File::MMagic; # use internal magic file
     # $mm = File::MMagic::new('/etc/magic'); # use external magic file
     $res = $mm->checktype_filename("/somewhere/unknown/file");

     $fh = new FileHandle "< /somewhere/unknown/file2";
     $res = $mm->checktype_filehandle($fh);

     $fh->read($data, 0x8564);
     $res = $mm->checktype_contents($data);

ABSTRACT
========

   This perl library uses perl5 objects to guess file type from filename
and/or filehandle.

DESCRIPTION
===========

   checktype_filename(), checktype_filehandle() and checktype_contents
returns string contains file type with MIME mediatype format.

COPYRIGHT
=========

   This program is originated from file.kulp that is a production of The
Unix Reconstruction Projct.     <http://language.perl.com/ppt/index.html>
Copyright (c) 1999 NOKUBI Takatsugu <knok@daionet.gr.jp>.

   There is no warranty for the program.

   This product includes software developed by the Apache Group for use in
the Apache HTTP server project (http://www.apache.org/).

   License for the program is followed the original software. The license
is below.

   This program is free and open software. You may use, copy, modify,
distribute and sell this program (and any modified variants) in any way
you wish, provided you do not restrict others to do the same, except for
the following consideration.

   I read some of Ian F. Darwin's BSD C implementation, to try to
determine how some of this was done since the specification is a little
vague.  I don't believe that this perl version could be construed as an
"altered version", but I did grab the tokens for identifying the
hard-coded file types in names.h and copied some of the man page.

   Here's his notice:

     * Copyright (c) Ian F. Darwin, 1987.
     * Written by Ian F. Darwin.
     *
     * This software is not subject to any license of the American Telephone
     * and Telegraph Company or of the Regents of the University of California.
     *
     * Permission is granted to anyone to use this software for any purpose on
     * any computer system, and to alter it and redistribute it freely, subject
     * to the following restrictions:
     *
     * 1. The author is not responsible for the consequences of use of this
     *    software, no matter how awful, even if they arise from flaws in it.
     *
     * 2. The origin of this software must not be misrepresented, either by
     *    explicit claim or by omission.  Since few users ever read sources,
     *    credits must appear in the documentation.
     *
     * 3. Altered versions must be plainly marked as such, and must not be
     *    misrepresented as being the original software.  Since few users
     *    ever read sources, credits must appear in the documentation.
     *
     * 4. This notice may not be removed or altered.

   The following is the Apache License. This program contains the magic
file that derived from the Apache HTTP Server.

     * Copyright (c) 1995-1999 The Apache Group.  All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * 1. Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in
     *    the documentation and/or other materials provided with the
     *    distribution.
     *
     * 3. All advertising materials mentioning features or use of this
     *    software must display the following acknowledgment:
     *    "This product includes software developed by the Apache Group
     *    for use in the Apache HTTP server project (http://www.apache.org/)."
     *
     * 4. The names "Apache Server" and "Apache Group" must not be used to
     *    endorse or promote products derived from this software without
     *    prior written permission. For written permission, please contact
     *    apache@apache.org.
     *
     * 5. Products derived from this software may not be called "Apache"
     *    nor may "Apache" appear in their names without prior written
     *    permission of the Apache Group.
     *
     * 6. Redistributions of any form whatsoever must retain the following
     *    acknowledgment:
     *    "This product includes software developed by the Apache Group
     *    for use in the Apache HTTP server project (http://www.apache.org/)."
     *
     * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
     * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
     * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     * OF THE POSSIBILITY OF SUCH DAMAGE.

Make temporary filename from template
*************************************

NAME
====

   File::MkTemp - Make temporary filename from template

SYNOPSIS
========

     use File::MkTemp;

     mktemp(tempXXXXXX,[dir]);

     $string = mktemp(tempXXXXXX,[dir]);
     open(F,$string);

     mkstemp(tempXXXXXX,dir);

     $fh = mkstemp(tempXXXXXX,dir);
     print $fh "stuff";
     $fh->close;

     mkstempt(tempXXXXXX,dir);

     ($fh,$template) = mkstempt(tempXXXXXX,dir);
     print $fh "stuff";
     $fh->close;
     print "Template is: $template\n";

DESCRIPTION
===========

   The MkTemp module provides three functions mktemp() mkstemp() and
mkstempt().

   The function mktemp() returns a unique string based upon the template.
The template must contain at least six trailing Xs.  The Xs are replaced
by a unique string and the template is returned.  The unique string is
made from picking random elements out of a 52 alpha character array
([a-z][A-Z]).  A directory can be specified in which to test for
duplicates of the string.

   The function mkstemp() does the same as mktemp() except it returns an
open file handle.  This prevents any possibility of opening up an
identical file.  The function requires that the directory be specified.

   The function mkstempt() does the same as mkstemp() except it returns
the name of the template in addition to the file handle.

AUTHOR
======

   File::MkTemp was written by Travis Gummels.  Please send bug reports
and or comments to: travis@gummels.com

COPYRIGHT
=========

   Copyright 1999|2000 Travis Gummels.  All rights reserved.  This may be
used and modified however you want.  If you redistribute after making
modifications please note modifications you made somewhere in the
distribution and notify the author.

Make temporary filename from template
*************************************

NAME
====

   File::MkTempO - Make temporary filename from template

SYNOPSIS
========

     use File::MkTempO;

     $object = new File::MkTempO('tempXXXXXX','dir');

     $string = $object->mktemp;
     open(F,$string);
     close(<F>);

     $fh = $object->mkstemp;
     print $fh "stuff";
     $fh->close;

     print "template stored in the object: $object->template\n";
     print "directory stored in the object: $object->dir\n";
     print "file handle in scalar form: $object->fhtmpl\n";
     print "fh and the directory in scalar form: $object->fhdirtmpl\n";

DESCRIPTION
===========

   The MkTempO module provides the following functions:

     new()      - for creation of the object.
     mktemp()   - for creation of a unique string based on the template
     mkstemp()  - for creation of a unique file handle opened in the
                  directory specified during creation of the object.
     template() - for returning the template stored in the object.
     dir()      - for returning the directory stored in the object.
     fhtmpl()   - for returning the file handle in scalar form.
     fhdirtmpl()- for returning the file handle and the directory its in.

   The function mktemp() returns a unique string based upon the template.
The template must contain at least six trailing Xs.  The Xs are replaced
by a unique string and the template is returned.  The unique string is
made from picking random elements out of a 52 alpha character array
([a-z][A-Z]).  A directory can be specified in which to test for
duplicates of the string.

   The function mkstemp() does the same as mktemp() except it returns an
open file handle.  This prevents any possibility of opening up an
identical file.  The function requires that the directory be specified
when creating the object with the new function.

AUTHOR
======

   File::MkTemp was written by Travis Gummels.  Please send bug reports
and or comments to: travis@gummels.com

COPYRIGHT
=========

   Copyright 1999|2000 Travis Gummels.  All rights reserved.  This may be
used and modified however you want.  If you redistribute after making
modifications please note modifications you made somewhere in the
distribution.

Tail multiple files for Unix systems
************************************

NAME
====

     MultiTail - Tail multiple files for Unix systems

SYNOPSIS
========

     use File::MultiTail;

DESCRIPTION
===========

     This perl library uses perl5 objects to make it easy to
     tail a dynamic list of files and match/except lines using full
     regular expressions.

   File::MultiTail;

     will tail multiple files and return the records
     read to a Data Structure. The Data Structure can
     be processed by MultiTail functions

   The  files  specified  are processed in accordance with the following
rules:

   Note: File devices and inode number uniquely identify each entry in the
UNIX filesystem. If the stat() command shows them to be the same, then
only one will be used. Windows NT filesystem NTFS does not allow links so
I don't check for links on NT.

   (1) Files that exist at program start  time  will  be     positioned to
Object attribute "NumLines" before input.

   (2) Files that become available subsequently  will  be  read     from
the beginning. Attribute ScanForFiles must be set to     True (>=1) for
the option.

   (3) If a file that has been selected as per rules 1 or 2  is
deleted  or  truncated input will continue until end-of-file     is
reached before the file is closed.

   (4) If a file is deleted and  it is recreated it     is treated as a
new file, will  be  read     from the beginning

   (5) To conserve file descriptors, files that are selected for     input
are  not actually opened until data is present beyond     the input point
selected.  For example,     if a file exists when ptail starts, ptail will
determine the     file mtime at that time and only open the file when the
mtime     increases.

     Note: mtime = Time when data was last modified. Changed by  the
                   following functions: creat, mknod, pipe, utime,
                   and write.

   (6) If an opened file has not been updated for MultiTail Object
attribute     "MaxAge" minutes it will be closed.      It will be reopened
if it is later updated.

   (7) Since MultiTail is OO you can alway change its attributes. If you
change     the list of file to be tailed (Files attribute) the attribute
 ScanForFiles will set to true and all dir and files ilists will be
check for new files.

METHODS
=======

   new

   Creating a new PTAIL object

   $tail = File::MultiTail->new( 				OutputPrefix => 'tf',
RemoveDuplicate => $True,             Files =>
['/var/log','/var/adm/*.log'] );

   Or

   $tail = File::MultiTail->new;
$tail->Files(['/var/log','/var/adm/*.log']); $tail->RemoveDuplicate($True);

     class/object method takes arguments ( All have defaults )
     and returning a reference to a newly created MultiTail object.

     File     :  File attribute accepts file names that includes
     	both explicit  file/dir  names  and  file/dir expressions.
     	Duplicate  file  paths  are rejected, along with non-duplicate
        names  that  resolve to  a  device/inode combination that is
     	currently being read. NT file name must start with drive letter
        or //.

     Pattern  :  Arguments can be a file name or an array of patterns
         Stores in object attribute  "LineArray" all lines
         that contain the patterns
     	(Default is *)

     ExceptPattern : Arguments can be a file name or an array of patterns
     	Stores in object attribute  "LineArray" all lines except
     	those that contain the patterns
     	(Default is *)

     MaxAge  : Maximum time in minute that an open file will be held open
     	without an update.
     	(Default is 10 minute)

     NumLines : Files that exist at MultiTail start time will have up to
     	NumLines lines from the end of file displayed.
     	Similar to tail -NumLines.
     	(Default is 10)

     Fuction  : Reference to a function that will be run by the MultiTail
         object.
         MultiTail object will pass a ref array of all the lines read from
         the files and passed through any filters you set in the object
     		 to the function.
     	0 = (Default) No Fuction

     ScanForFiles : Maximum time in minute before Read will scan for new
     				 files.
     	If you change the attribute "Files" with fuction update_attribute
         the next Read will scan for new files.
     	0 = (Default) Off

     RemoveDuplicate : Removes all duplicate lines from LineArray
     	0 = (Default) Off
     	1 = On

     : Turn Debuging messages on for MultiTail.pm.
     	0 = (Default) Off
     	1 = On

     OutputPrefix : Determines the prefix applied to each output record.
     	Output records are store in MultiTail object attribute "LineArray"
         The prefix is separated from the record by ': '.
         Prefixes supported are:
     		       p  : path name of the input file
     		       f  : file name of the input file
     		       t  : time in HHMMSS
     		       tg : time in HHMMSS GMT
     		       tc : time in MM/DD/YYYY HH:MM:SS
     		       pt : path and time
     		       ptg: path and time GMT
     		       ptc: path and time complete
     		       ft : file and time
     		       ftg: file and time GMT
     		       ftc: file and time complete
     		       tp : time and path
     		       tpg: time and path GMT
     		       tpc: time complete and path
     		       tf : time and file
     		       tfg: time and file GMT
     		       tfc: time complete and file
     	0 = (Default) No prefix
     	GMT = Greenwich time ZONE

     Exit Codes

     1001 - MaxAge is less the zero
     1002 - NumLines is less the zero
     1003 - OutputPrefix must one ( )
     1004 - Pattern must is not a file or ARRAY
     1005 - ExceptPattern is not a file or ARRAY
     1006 - Debug is not 0 or 1
     1007 - ScanForFiles is less the zero
     1008 - RemoveDuplicate is not 0 or 1
     1009 - Function is not ref to fuction
     1010 - File attribute not set

read
     Read all new data from file

     $tail->read

     Read all new date from tailed files and return new lines as part of
     the Data Structure (MultiTail Object attribute LineArray)

print
     Print all line contained in MultiTail Object attribute LineArray

     $tail->print

update_attribute
     Allow you to Update (Change) any MultiTail Object attribute

     $tail->update_attribute( 	Files =>
     ["/var/log","/var/adm","/home/nnysgm/logwatcher/foo*"],
     ExceptPattern => /home/nnysgm/ExceptPattern.txt, 	RemoveDuplicate =>
     $True 	);

     This changes the Files, ExceptPattern and RemoveDuplicate attributes
     for the Object $tail.

     New files will be scanned for during next Read if "Files" attribute is
     changed.

     Also you can use supplied methods to set attribute values.

     $tail->RemoveDuplicate($True); $tail->NumLines(100);

version
     Return version number on PTAIL package

     $tail->version

debug
     Toggle the debug switch for MultiTail package

     $tail->debug

          There are a number of  function in the MultiTail.pm module.

          	o printstat :
          		Print out stat output for each file.
          	o printfilestates :
          		Print out All file states.
          		(See note in MultiTail.pm for function OpenUpdateFiles)
          	o printpat :
          		Print out lines from pattern file array.
          	o printexceptpat :
          		Print out line from pattern file except array.

close_all_files
     Closes all file that are being tailed

     $tail->close_all_files

EXAMPLE
=======

   1) 	use File::MultiTail;

     $tail1=File::MultiTail->new (  OutputPrefix => "f",
                           Debug => "$True",
                           Files => ["/var/adm/messages"]
     );

     while(1) {
     	$tail1->read;
     	#
     	$tail1->print;
     	sleep 10;
     }

   $tail1=MultiTail->new : Create new ptail object

   - Files => Tail file /var/adm/messages

   - OutputPrefix => Prepend the name of the file beginning of each   line
in object attribute  "LineArray"

   $tail1->read      : Read all line from files

   $tail1->print     : Print all line in object attribute  "LineArray";

   2) 	use File::MultiTail;

     $tail1=File::MultiTail->new (  OutputPrefix => "tf",
     	      Pattern => "/home/nnysgm/logwatcher/pattern",
     	      ExceptPattern => "/home/nnysgm/logwatcher/epattern",
     	      Fuction = > \&want,
                 Files => ["/var/adm","/var/log/*.log"]
     );

     while(1) {
     	$tail1->read;
     	#
     	$tail1->print;
     	sleep 10;
     }

     sub want {
     		(your code .... );
     }

   $tail1=File::MultiTail->new : Create new ptail object

   - OutputPrefix => Prepend the name of the file and time to the
beginning of each line in object attribute  "LineArray"

   - ExceptPattern => Stores in object attribute  "LineArray" all lines
except   those that contain the patterns from file "epattern" - Pattern =>
Stores in object attribute  "LineArray" all lines   that contain the
patterns from file "pattern"

   - Fuction => ref to a function that will be run by MultiTail object.
MultiTail object will pass a ref array to the function of all the lines
read from   the file and passed through any filters you set in the object.

   - Files => Tail all files in dir /var/adm and all .log files   dir
/var/log.

   $tail1->read      : Read all line from files

   $tail1->print     : Print all line in object attribute  "LineArray";

   3)    use File::MultiTail;

   $tail=File::MultiTail->new;

     $tail->OutputPrefix(tf);
        $tail->Fuction(\&want);
        $tail->Files(["/var/adm","/var/log/*.log"]);

        while(1) {
           $tail1->read;
        }

        sub want {
              (your code .... );
        }

AUTHOR
======

   Stephen Miano, smiano@mindspring.com

SEE ALSO   perl(1).
===================

Copy file, file               Copy file[s] | dir[s], dir
********************************************************

NAME
====

   *File::NCopy* - Copy file, file               Copy file[s] | dir[s], dir

SYNOPSIS
========

     use File::NCopy qw(copy);

     copy "file","other_file";
     copy "file1","file2","file3","directory";

     # we want to copy the directory recursively
     copy \1,"directory1","directory2";
     copy \1,"file1","file2","directory1","file3","directory2","file4",
         "directory";

     # can also use references to file handles, this is for backward
     # compatibility with File::Copy
     copy \*FILE1,\*FILE2;
     copy \*FILE1,"file";
     copy "file1",\*FILE2;

     # we don't specify \1 as the first argument because we don't want to
     # copy directories recursively
     copy "*.c","*.pl","programs";
     copy "*", "backup";

     use File::NCopy;

     # the below are the default config values
     $file = File::NCopy->new(
             'recursive'      => 0,
             'preserve'       => 0,
             'follow_links'   => 0,
             'force_write'   => 0,
             'set_permission' => \&File::NCopy::u_chmod,
             'file_check'     => \&File::NCopy::f_check,
             'set_times'      => \&File::NCopy::s_times,
     );

     set_permission will take two file names, the original to get the
     file permissions from and the new file to set the file permissions
     for.

     file_check takes two parameters, the file names to check the file to
     copy from and the file to copy to. I am using flock for Unix
     systems.
     Default for this is \&File::NCopy::f_check.  On Unix you can also use
     \&File::NCopy::unix_check.  This one compares the inode and device
     numbers.

     set_times is used if the preserve attribute is true.  It preserves
     the access and modification time of the file and also attempts to
     set the owner of the file to the original owner.  This can be useful
     in a script used by root, though enyone can preserve the access and
     modification times. This also takes two arguments.  The file to get
     the stats from and apply the stats to.

     On Unix boxes you shouldn't need to worry.  On other system you may
     want to supply your own sub references.

     $file = File::NCopy->new(recursive => 1);
     $file->copy "file","other_file";
     $file->copy "directory1","directory2";

     $file = File::NCopy->new(u_chmod => \&my_chmod,f_check => \&my_fcheck);
     $file->copy "directory1","directory2";

DESCRIPTION
===========

   *File::NCopy::copy* copies files to directories, or a single file to
another file.  You can also use a reference to a file handle if you wish
whem doing a file to file copy.  The functionality is very similar to cp.
If the argument is a directory to directory copy and the recursive flag is
set then it is done recursively like *cp -R*.  In fact it behaves like cp
on Unix for the most part.  If called in array context, an array of
successful copies is returned, otherwise the number of succesful copies is
returned.  If passed a file handle, it's difficult to make sure the file
we are copying isn't the same that we are copying to, since by opening the
file in write mode it gets pooched.  To avoid this use file names instead,
if at all possible, especially for the to file.  If passed a file handle,
it is not closed when copy returns, files opened by copy are closed.

copy
     Copies a file to another file.  Or a file to a directory.  Or multiple
     files and directories to another directory.  Or a directory to another
     directory.  Wildcard arguments are expanded, except for the last
     argument which should not be expanded.  The file and directory
     permissions are set to the orginating file's permissions and if
     preserve is set the access and modification times are also set.  If
     preserve is set then the uid and gid will also be attempted to be
     set, though this may only for for the men in white hats.  In list
     context it returns all the names of the files/directories that were
     successfully copied.  In scalar context it returns the number of
     successful copies made.  A directory argument is considerd a single
     successful copy if it manages to copy anything at all.  To make a
     directory to directory copy the recursive flag must be set.

cp
     Just calls copy.  It's there to be compatible with File::Copy.

new
     If used then you can treat this as an object oriented module with some
     configuration abilities.

recursive
     If used as an object then you can use this to set the recursive
     attribute.  It can also be set when instantiating with new.  The other
     attributes must all be set when instantiating the object.  If it isn't
     specified then directories are not followed.

preserve
     Attempt to preserve the last modification and access time as well as
     user and group id's.  This is a useful feature for sysadmins, though
     the access and modification time should always be preservable, the
     uid and gid may not.

follow_links
     If the link is to a directory and this attribute is true then the
     directory is followed and recursively copied.  Otherwise a link is
     made to the root directory the link points to. eg.

     /sys/ is a link to /usr/src/sys/ is a link to /usr/src/i386/sys then
     the link /sys/ is actually created in the source directory as a link
     to /usr/src/i386/sys/ rather than /usr/src/sys/ since if the link
     /usr/src/sys/ is removed then we lost the link even though the
     directory we originally intended to link to still exists.

force_write
     Force the writing of a file even if the permissions are read only on
     it.

EXAMPLE
=======

   See SYNOPSIS.

BUGS
====

   When following links the target directory might not exactly the same as
the source directory.  The reason is that we have to make sure we don't
follow circular or dead links.  This is really a feature though the result
may not quite resemble the source dir, the overall content will be the
same. :)

AUTHOR
======

   Gabor Egressy *gabor@vmunix.com*

   Copyright (c) 1998 Gabor Egressy.  All rights reserved.  All wrongs
reversed.  This program is free software; you can redistribute and/or
modify it under the same terms as Perl itself.

   Some ideas gleaned from File::Copy by Aaron Sherman & Charles Bailey,
but the code was written from scratch.

create or remove directory trees
********************************

NAME
====

   File::Path - create or remove directory trees

SYNOPSIS
========

     use File::Path;

     mkpath(['/foo/bar/baz', 'blurfl/quux'], 1, 0711);
     rmtree(['foo/bar/baz', 'blurfl/quux'], 1, 1);

DESCRIPTION
===========

   The mkpath function provides a convenient way to create directories,
even if your mkdir kernel call won't create more than one level of
directory at a time.  mkpath takes three arguments:

   * the name of the path to create, or a reference to a list of paths to
     create,

   * a boolean value, which if TRUE will cause mkpath to print the name of
     each directory as it is created (defaults to FALSE), and

   * the numeric mode to use when creating the directories (defaults to
     0777)

   It returns a list of all directories (including intermediates,
determined using the Unix '/' separator) created.

   Similarly, the `rmtree' function provides a convenient way to delete a
subtree from the directory structure, much like the Unix command `rm -r'.
`rmtree' takes three arguments:

   * the root of the subtree to delete, or a reference to a list of roots.
     All of the files and directories below each root, as well as the
     roots themselves, will be deleted.

   * a boolean value, which if TRUE will cause `rmtree' to print a message
     each time it examines a file, giving the name of the file, and
     indicating whether it's using rmdir or unlink to remove it, or that
     it's skipping it.  (defaults to FALSE)

   * a boolean value, which if TRUE will cause `rmtree' to skip any files
     to which you do not have delete access (if running under VMS) or
     write access (if running under another OS).  This will change in the
     future when a criterion for 'delete permission' under OSs other than
     VMS is settled.  (defaults to FALSE)

   It returns the number of files successfully deleted.  Symlinks are
simply deleted and not followed.

   NOTE: If the third parameter is not TRUE, `rmtree' is *unsecure* in the
face of failure or interruption.  Files and directories which were not
deleted may be left with permissions reset to allow world read and write
access.  Note also that the occurrence of errors in rmtree can be
determined *only* by trapping diagnostic messages using `$SIG{__WARN__}';
it is not apparent from the return value.  Therefore, you must be
extremely careful about using `rmtree($foo,$bar,0' in situations where
security is an issue.

AUTHORS
=======

   Tim Bunce <`Tim.Bunce@ig.co.uk'> and Charles Bailey
<`bailey@newman.upenn.edu'>

convert an absolute path to a relative path
*******************************************

NAME
====

   abs2rel - convert an absolute path to a relative path

   rel2abs - convert a relative path to an absolute path

   realpath - convert a logical path to a physical path (resolve symlinks)

   splitpath - split a path in to volume, directory and filename components

   joinpath - join volume, directory, and filename components to form a
path

   splitdirs - split directory specification in to component names

   joindirs - join component names in to a directory specification

   setfstype - set the file system type

SYNOPSIS
========

     use File::PathConvert qw(realpath abs2rel rel2abs setfstype splitpath
       joinpath splitdirs joindirs $resolved);

     $relpath = abs2rel($abspath);
     $abspath = abs2rel($abspath, $base);

     $abspath = rel2abs($relpath);
     $abspath = rel2abs($relpath, $base);

     $path = realpath($logpath) || die "resolution stopped at $resolved";

     ( $volume, $directory, $filename )= splitpath( $path ) ;
     ( $volume, $directory, $filename )= splitpath( $path, 'nofile' ) ;

     $path= joinpath( $volume, $directory, $filename ) ;

     @directories= splitdirs( $directory ) ;
     $directory= joindirs( @directories ) ;

DESCRIPTION
===========

   File::PathConvert provides functions to convert between absolute and
relative paths, and from logical paths to physical paths on a variety of
filesystems, including the URL 'filesystem'.

   Paths are decomposed internally in to volume, directory, and, sometimes
filename portions as appropriate to the operation and filesystem, then
recombined.  This preserves the volume and filename portions so that they
may be returned, and prevents them from interfering with the path
conversions.

   Here are some examples of path decomposition.  A '****' in a column
indicates the column is not used in abs2rel and rel2abs functions for that
filesystem type.

     FS      VOLUME                  Directory       filename
     ======= ======================= =============== =============
     URL     http:                   /a/b/           c?query
             http://fubar.com        /a/b/           c?query
             //p.d.q.com             /a/b/c/         ?query

     VMS     Server::Volume:         [a.b]           c
             Server"access spec"::   [a.b]           c
             Volume:                 [a.b]           c

     Win32   A:                      \a\b\c          ****
             \\server\Volume         \a\b\c          ****
             \\server\Volume         \a/b/c          ****

     Unix    ****                    \a\b\c          ****

     MacOS   Volume::                a:b:c           ****

   Many more examples abound in the test.pl included with this module.

   Only the VMS and URL filesystems indicate if the last name in a path is
a directory or file.  For other filesystems, all non-volume names are
assumed to be directory names.  For URLs, the last name in a path is
assumed to be a filename unless it ends in '/', '/.', or '/..'.

   Other assumptions are made as well, especially MacOS and VMS. THESE MAY
CHANGE BASED ON PROGRAMMER FEEDBACK!

   The conversion routines abs2rel, rel2abs, and realpath are the main
focus of this package.  splitpath and joinpath are provided to allow
volume oriented filesystems (almost anything non-unixian, actually) to be
accomodated.  splitdirs and joindirs provide directory path grammar
parsing and encoding, which is especially useful for VMS.

setfstype
     This is called automatically on module load to set the filesystem type
     according to $^O. The user can call this later set the filesystem type
     manually.  If the name is not recognized, unix defaults are used.
     Names matching /^URL$/i, /^VMS$/i, /^MacOS$/i, or
     /^(ms)?(win|dos)/32|nt)?$/i yield the appropriate (hopefully)
     filesystem settings.  These strings may be generalized in the future.

     Examples:

          File::PathConvert::setfstype( 'url' ) ;
          File::PathConvert::setfstype( 'Win32' ) ;
          File::PathConvert::setfstype( 'HAL9000' ) ; # Results in Unix default

abs2rel
     abs2rel converts an absolute path name to a relative path: converting
     /1/2/3/a/b/c relative to /1/2/3 returns a/b/c

          $relpath= abs2rel( $abspath ) ;
          $relpath= abs2rel( $abspath, $base ) ;

     If $abspath is already relative, it is returned unchanged.  Otherwise
     the relative path from $base to $abspath is returned.  If $base is
     undefined the current directory is used.

     The volume and filename portions of $base are ignored if present.  If
     $abspath and $base are on different volumes, the volume from $abspath
     is used.

     No filesystem calls are made except for getting the current working
     directory if $base is undefined, so symbolic links are not checked
     for or resolved, and no check is done for existance.

     Examples

          # Unix
          'a/b/c' == abs2rel( 'a/b/c', $anything )
          'a/b/c' == abs2rel( '/1/2/3/a/b/c', '/1/2/3' )

          # DOS
          'a\\b/c' == abs2rel( 'a\\b/c', $anything )
          'a\\b/c' == abs2rel( '/1\\2/3/a\\b/c', '/1/2/3' )

          # URL
          'http:a/b/c'           == abs2rel( 'http:a/b/c', $anything )
          'http:a/b/c'           == abs2rel( 'http:/1/2/3/a/b/c',
                                             'ftp://t.org/1/2/3/?z' )
          'http:a/b/c?q'         == abs2rel( 'http:/1/2/3/a/b/c/?q',
                                             'ftp://t.org/1/2/3?z'  )
          'http://s.com/a/b/c?q' == abs2rel( 'http://s.com/1/2/3/a/b/c?q',
                                             'ftp://t.org/1/2/3/?z')

rel2abs
     rel2abs makes converts a relative path name to an absolute path:
     converting a/b/c relative to /1/2/3 returns /1/2/3/a/b/c.

          $abspath= rel2abs( $relpath ) ;
          $abspath= rel2abs( $relpath, $base ) ;

     If $relpath is already absolute, it is returned unchanged.  Otherwise
     $relpath is taken to be relative to $base and the resulting absolute
     path is returned.  If $base is not supplied, the current working
     directory is used.

     The volume portion of $relpath is ignored.  The filename portion of
     $base is also ignored. The volume from $base is returned if present.
     The filename portion of $abspath is returned if present.

     No filesystem calls are made except for getting the current working
     directory if $base is undefined, so symbolic links are not checked
     for or resolved, and no check is done for existance.

     rel2abs will not return a path of the form "./file".

     Examples

          # Unix
          '/a/b/c'       == rel2abs( '/a/b/c', $anything )
          '/1/2/3/a/b/c' == rel2abs( 'a/b/c', '/1/2/3' )

          # DOS
          '\\a\\b/c'                == rel2abs( '\\a\\b/c', $anything )
          '/1\\2/3\\a\\b/c'         == rel2abs( 'a\\b/c', '/1\\2/3' )
          'C:/1\\2/3\\a\\b/c'       == rel2abs( 'D:a\\b/c', 'C:/1\\2/3' )
          '\\\\s\\v/1\\2/3\\a\\b/c' == rel2abs( 'D:a\\b/c', '\\\\s\\v/1\\2/3' )

          # URL
          'http:/a/b/c?q'            == rel2abs( 'http:/a/b/c?q', $anything )
          'ftp://t.org/1/2/3/a/b/c?q'== rel2abs( 'http:a/b/c?q',
                                                 'ftp://t.org/1/2/3?z' )

realpath
     realpath makes a canonicalized absolute pathname and resolves all
     symbolic links, extra "/" characters, and references to /./ and /../
     in the path.  realpath resolves both absolute and relative paths.  It
     returns the resolved name on success, otherwise it returns undef and
     sets the valiable `$File::PathConvert::resolved' to the pathname that
     caused the problem.

     All but the last component of the path must exist.

     This implementation is based on 4.4BSD realpath(3).  It is not tested
     under other operating systems at this time.

     If '/sys' is a symbolic link to '/usr/src/sys':

          chdir('/usr');
          '/usr/src/sys/kern' == realpath('../sys/kern');
          '/usr/src/sys/kern' == realpath('/sys/kern');

splitpath
     To be written...

joinpath
     To be written...

     Note that `joinpath( splitpath( $path ) )' usually yields path.  URLs
     with directory components ending in '/.' or '/..' will be fixed up to
     end in '/./' and '/../'.

splitdirs
     To be written...

joindirs
BUGS
====

   realpath is not fully multiplatform.

LIMITATIONS
===========

   * In URLs, paths not ending in '/' are split such that the last name in
     the path is a filename.  This is not intuitive: many people use such
     URLs for directories, and most servers send a redirect.  This may
     cause programers using this package to code in bugs, it may be more
     pragmatic to always assume all names are directory names.  (Note that
     the query portion is always part of the filename).

   * If the relative and base paths are on different volumes, no error is
     returned.  A silent, hopefully reasonable assumption is made.

   * No detection of unix style paths is done when other filesystems are
     selected, like File::Basename does.

AUTHORS
=======

   Barrie Slaymaker <rbs@telerama.com> Shigio Yamaguchi
<shigio@wafu.netgate.net>

Read a file backwards by lines.
*******************************

NAME
====

   File::ReadBackwards.pm - Read a file backwards by lines.

SYNOPSIS
========

     use File::ReadBackwards ;

     # Object interface

     $bw = File::ReadBackwards->new( 'log_file' ) or
     			die "can't read 'log_file' $!" ;

     while( defined( $log_line = $bw->readline ) ) {
     	    print $log_line ;
     }

     # Tied Handle Interface

     tie *BW, File::ReadBackwards, 'log_file' or
     			die "can't read 'log_file' $!" ;

     while( <BW> ) {
     	    print ;
     }

DESCRIPTION
===========

   This module reads a file backwards line by line. It is simple to use,
memory efficient and fast. It supports both an object and a tied handle
interface.

   It is intended for processing log and other similar text files which
typically have their newest entries appended to them. By default files are
assumed to be plain text and have a line ending appropriate to the OS. But
you can set the input record separator string on a per file basis.

OBJECT INTERFACE
================

   There are only 2 methods in Backwards' object interface, new and
readline.

new( $file, [$rec_sep] )
------------------------

   New takes as arguments a filename and an optional record separator. It
either returns the object on a successful open or undef upon failure. $!
is set to the error code if any.

readline
--------

   Readline takes no arguments and it returns the previous line in the file
or undef when there are no more lines in the file.

TIED HANDLE INTERFACE
=====================

tie( *HANDLE, File::ReadBackwards, $file, [$rec_sep] )
------------------------------------------------------

   The TIEHANDLE and READLINE methods are aliased to the new and readline
methods respectively so refer to them for their arguments and API.  Once
you have tied a handle to File::ReadBackwards the only operation
permissible is <> which will read the previous line. All other tied handle
operations will generate an unknown method error. Do not seek, write or
perform any other operation other than <> on the tied handle.

LINE AND RECORD ENDINGS
=======================

   Since this module needs to use low level I/O for efficiency, it can't
portably seek and do block I/O without managing line ending conversions.
This module supports the default record separators of normal line ending
strings used by the OS. You can also set the separator on a per file basis.

   Only if the record separator is not specified and it defaults to CR/LF
(e.g, VMS, redmondware) will it will be converted to a single newline.
Unix and MacOS files systems use only a single character for line endings
and the lines are left unchanged.  This means that for native text files,
you should be able to process their lines backwards without any problems
with line endings. If you specify a record separator, no conversions will
be done and you will get the records as if you read them in binary mode.

DESIGN
======

   It works by reading a large (8kb) block of data from the end of the
file.  It then splits them on the record separator and stores a list of
records in the object. Each call to readline returns the top record of the
list and if the list is empty it refills it by reading the previous block
from the file and splitting it.  When the beginning of the file is reached
and there are no more lines, undef is returned.  All boundary conditions
are handled correctly i.e. if there is a trailing partial line (no
newline) it will be the first line returned and lines larger than the read
buffer size are handled properly.

NOTES
=====

   There is no support for list context in either the object or tied
interfaces. If you want to slurp all of the lines into an array in
backwards order (and you don't care about memory usage) just do:

     @back_lines = reverse <FH>.

   This module is only intended to read one line at a time from the end of
a file to the beginning.

AUTHOR
======

   Uri Guttman, uri@sysarch.com

COPYRIGHT
=========

   Copyright (C) 2000 by Uri Guttman. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Read/write/edit remote files transparently
******************************************

NAME
====

   File::Remote - Read/write/edit remote files transparently

SYNOPSIS
========

     #
     # Two ways to use File::Remote
     # First, the object-oriented style
     #
     use File::Remote;
     my $remote = new File::Remote;

     # Standard filehandles
     $remote->open(FILE, '>>host:/remote/file') or die $!;
     print FILE "Here's a line that's added.\n";
     $remote->close(FILE);

     # Create a new file and change its permissions
     $remote->mkdir('host:/remote/dir');
     $remote->touch('host:/remote/dir/file');
     $remote->chown('root', 'other', 'host:/remote/dir/file');
     $remote->chmod('0600', 'host:/remote/dir/file');

     # Move files around
     $remote->copy('/local/file', 'host:/remote/file') or warn $!;
     $remote->move('host:/remote/file', '/local/file');

     # Read and write whole files
     my @file = $remote->readfile('host:/remote/file');
     $remote->writefile('/local/file', @file);

     # Backup a file with a suffix
     $remote->backup('host:/remote/oldfile', 'save');

     # Use secure connection methods
     my $secure = new File::Remote (rsh => '/usr/local/bin/ssh',
                                    rcp => '/usr/local/bin/scp');
     $secure->unlink('/local/file');
     $secure->rmdir('host:/remote/dir');

     #
     # Next, the function-based style. Here, we can use the
     # special :replace tag to overload Perl builtins!
     #
     use File::Remote qw(:replace);	# special :replace tag

     open(REMOTE, 'host:/remote/file') or die $!;
     print while (<REMOTE>);
     close(REMOTE);

     open(LOCAL, '>>/local/file');	# still works!
     print LOCAL "This is a new line.\n";
     close(LOCAL);

     mkdir('host:/remote/dir', 0755);
     unlink('host:/remote/file');
     unlink('/local/file');		# still works too!
     symlink('host:/remote/src', 'host:/remote/dest');

DESCRIPTION
===========

   This module takes care of dealing with files regardless of whether
they're local or remote.  It allows you to create and edit files without
having to worry about their physical location on the network.  If a file
passed into a function is of the form 'host:/path/to/file', then
File::Remote uses rsh/rcp (or ssh/scp, depending on how you configure it)
to edit the file remotely.  Otherwise, it assumes the file is local and
passes calls directly through to Perl's core functions.

   The nice thing about this module is that you can use it for all your
file calls, since it handles both remote and local files transparently.
This means you don't have to put a whole bunch of checks for remote files
in your code.  Plus, if you use the function-oriented interface along with
the `:replace' tag, you can actually redefine the Perl builtin file
functions so that your existing Perl scripts can automatically handle
remote files with no re-engineering!

   There are two ways to program with File::Remote, an object-oriented
style and a function-oriented style.  Both methods work equally well, it's
just a matter of taste.  One advantage of the object-oriented method is
that this allows you to read and write from different servers using
different methods (eg, rsh vs. ssh) simultaneously:

     # Object-oriented method
     use File::Remote;
     my $remote = new File::Remote;
     my $secure = new File::Remote (rsh => '/bin/ssh', rcp => '/bin/scp');

     # Securely copy, write, and remove a file in one swoop...
     $remote->open(LOCAL, '/local/file') or die "Open failed: $!\n";
     $secure->open(REMOTE, 'host:/remote/file') or die "Open failed: $!\n";
     print REMOTE "$_" while (<LOCAL>);

     $remote->close(LOCAL);
     $secure->close(REMOTE);

     # And let's move some files around securely
     $secure->move('/local/file', 'host:/remote/file');
     $secure->copy('host:/remote/file', '/local/file');

   Because the names for the File::Remote methods clash with the Perl
builtins, if you use the function-oriented style with the :standard tag
there is an extra 'r' added to the front of the function names.  Thus,
'$remote->open' becomes 'ropen' in the function-oriented version:

     # Function-oriented method
     use File::Remote qw(:standard);	# use standard functions
     setrsh('/local/bin/ssh');
     setrcp('/local/bin/scp');

     ropen(FILE, 'host:/remote/file') or die "Open failed: $!\n";
     print while (<FILE>);
     rclose(FILE) or die "Close failed: $!\n";

     runlink('host:/remote/file');
     rmkdir('host:/remote/dir');
     rchmod('0700', 'host:/remote/dir');

   With the function-oriented interface there is also a special tag called
`:replace' which will actually replace the Perl builtin functions:

     # Replace Perl's file methods with File::Remote's
     use File::Remote qw(:replace);

     open(FILE, '>host:/remote/file') or die "Open failed: $!\n";
     print FILE "Hello, world!\n";
     close(FILE) or die "Close failed: $!\n";

     mkdir('/local/new/dir', '2775');
     mkdir('host:/remote/new/dir');
     chown('root', 'other', '/local/new/dir');
     unlink('host:/remote/file');

   This is pretty neat; since File::Remote will pass calls to local files
straight through to Perl's core functions, you'll be able to do all this
"transparently" and not care about the locations of the files. Plus, this
has the big advantage of making your existing Perl scripts capable of
dealing with remote files without having to rewrite any code.

FUNCTIONS
=========

   Below are each of the functions you can make use of with File::Remote.
Remember, for the function-oriented style, unless you use the `:replace'
tag you'll have to add an extra 'r' to the start of each function name.
For all functions, the file arg can be either local or remote.

new(opt => val, opt => val)
---------------------------

   This is the main constructor when you're using the object-oriented
method of calling. You can pass it three arguments which change how it
works:

     rsh  -  path to your rsh or ssh program
     rcp  -  path to your rcp or scp program
     tmp  -  path to your tmp directory

   So, for example:

     use File::Remote;
     my $secure = File::Remote->new(rsh => '/usr/local/bin/ssh',
                                    rcp => '/usr/local/bin/scp',
                                    tmp => '/var/run');
     $secure->copy($src, $dest);

   The above would setup your $secure object so that calls to methods on
it would use ssh and scp for connections.

setrsh(prog) ; setrcp(prog) ; settmp(dir)
-----------------------------------------

   These perform the equivalent functionality to setting the above flags,
for use in the function-oriented method of calling. So, if you were to
decide you didn't want to use the OO method, but instead wanted to use the
drop-in replacement function method (which I prefer):

     use File::Remote qw(:replace);

     setrsh('/usr/local/bin/ssh');
     setrcp('/usr/local/bin/scp');
     settmp('/var/run');

     copy($src, $dest);

   That chain of calls would have the exact same effect, only using the
function-oriented format instead of the object-oriented format.

open(HANDLE, file) ; close(HANDLE)
----------------------------------

   Used to open and close files just like the Perl builtins. These
functions accept both string filehandles and typeglob references.

touch(file)
-----------

   Updates the modification time on a file, or creates it if it doesn't
exist.

mkdir(dir [, mode]) ; rmdir(dir [, recurse])
--------------------------------------------

   Create a dir with optional octal mode [mode]; remove a dir tree
optionally recursively. By default, rmdir works recursively, and the mode
of the new dir from mkdir depends on your umask.

copy(file1, file2)
------------------

   Simply copies a file, just like File::Copy's function of the same name.
You can also address it as 'cp' (if you import the :aliases tag).

move(file1, file2)
------------------

   Moves a file ala File::Copy.  You can also address it as 'mv' (if you
import the :aliases tag).

chmod(mode, file) ; chown(owner, group, file)
---------------------------------------------

   Change the permissions or the owner of a file.

unlink(file)
------------

   Remove a file. You can also address it as 'rm' (if you import the
:aliases tag).

link(file1, file2)
------------------

   Create a hard link between two files. The caveat to this function is
that both files must be local, or both files must be remote.

symlink(file1, file2)
---------------------

   Works just like link only creates symbolic instead of hard links.

readlink(file)
--------------

   This reads what a symbolic link points to, just like the Perl builtin.

backup(file, [file|suffix])
---------------------------

   This backs up a file, useful if you're going to be manipulating it.  If
you just call it without the optional second filename or suffix, the
suffix 'bkup' will be added to the file.  Either file can be local or
remote; this is really just a front-end to File::Remote::copy().

readfile(file) , writefile(file, @data)
---------------------------------------

   These read and write whole files in one swoop, just like File::Slurp.
readfile() returns an array of the file, and writefile just returns
success or failure.

append(file, @data) , prepend(file, @data)
------------------------------------------

   Similar to writefile(), only these don't overwrite the file, these
either append or prepend the data to the file.

EXAMPLES
========

   Here's some more examples of how to use this module:

1. Add a new user to /etc/passwd on your server
-----------------------------------------------

   This might be useful if you've got some type of web-based newuser
program that runs on a host other than the one you have to edit
/etc/passwd on:

     # Function-oriented method
     use File::Remote qw(:replace);

     $passwd = "server:/etc/passwd";
     backup($passwd, 'old');		# back it up to be safe
     open(PASSWD, ">>$passwd") or die "Couldn't write $passwd: $!\n";
     print PASSWD "$newuser_entry\n";
     close(PASSWD);

2. Securely copy over a bunch of files
--------------------------------------

   Hopefully you would use loops and variable names to make any actual
code look much cleaner...

     # Object-oriented method
     use File::Remote
     my $secure = File::Remote->new(rsh => '/share/bin/ssh',
                                    rcp => '/share/bin/scp',
                                    tmp => '/var/tmp');

     # Move files
     $secure->move('client:/home/bob/.cshrc', 'client:/home/bob/.cshrc.old');
     $secure->copy('/etc/skel/cshrc.user', 'client:/home/bob/.cshrc');
     $secure->copy('/etc/skel/kshrc.user', 'client:/home/bob/.kshrc');

3. Use rsync w/ ssh for really fast transfers
---------------------------------------------

   Here we're assuming we're getting some huge datastream from some other
process and having to dump it into a file in realtime.  Note that the
remote file won't be updated until close() is called.

     # Function-oriented, no :replace tag, so all functions
     # will be prefixed with an 'r'
     use File::Remote qw(:standard);

     setrsh('/local/bin/ssh');
     setrcp('/local/bin/rsync -z -e /local/bin/ssh');
     settmp('/var/stmp');

     $file = "server:/local/dir/some/huge/file";
     ropen(REMOTE, ">>$file") or die "Couldn't write $file: $!\n";
     while(<DATASTREAM>) {
        print REMOTE $_;
     }
     rclose(REMOTE);		# file is finally updated

NOTES
=====

   File::Remote only works on UNIX systems.

   The main caveat to File::Remote is that you have to have rsh/rcp or
ssh/scp access to the hosts you want to manipulate files on.  Make sure
you consider the security implications of this, especially if you live
outside a firewall.

   Enabling autoflush ($|) won't have any effect on remote filehandles,
since the remote file is not synched until close() is called on the
filehandle.

   File::Remote does not support writing to remote pipes.

   Because of speed, by default no checks are made as to whether or not
rsh/rcp or their equivalents are executable. To change this, see the
source.

BUGS
====

   Because of the internal implementation of open() on remote files, it is
not possible to read from an ever-growing remote file ("tail" it).
Basically, a snapshot of the remote file is taken when you open it for
reading. Patches to overcome this limitation are welcomed.

   Perl scripts that are tainted or setuid might not work with File::Remote
because of its reliance on system() calls, depending on your %ENV. To work
around this, simply add an "undef %ENV" statement to the top of your
script, which you should be doing anyways.

   If you have a bug report or suggestion, please direct them to me (see
below).  Please be specific and include the version of File::Remote you're
using.

VERSION
=======

   $Id: Remote.pm,v 1.12 2000/11/30 00:29:53 nwiger Exp $

AUTHOR
======

   Copyright (c) 1998-2000 Nathan Wiger <nate@nateware.com>. All Rights
Reserved.

   This module is free software; you may copy this under the terms of the
GNU General Public License, or the Artistic License, copies of which
should have accompanied your Perl kit.

Remove files and directories
****************************

NAME
====

   *File::Remove* - Remove files and directories

SYNOPSIS
========

     use File::Remove qw(remove);

     remove \1,"file1","file2","directory1","file3","directory2","file4",
         "directory2","file5","directory3";

     # removes only files, even if the filespec matches a directory
     remove "*.c","*.pl";

     # recurses into subdirectories and removes them all
     remove \1, "directory";

DESCRIPTION
===========

   *File::Remove::remove* removes files and directories.  It acts like rm
for the most part.  Although unlink can be given a list of files it will
not remove directories.  This module remedies that.  It also accepts
wildcards, * and ?, as arguments for filenames.

remove
     Removes files and directories.  Directories are removed recursively
     like in *rm -rf* if the first argument is a reference to a scalar that
     evaluates to true.  If the first arguemnt is a reference to a scalar
     then it is used as the value of the recursive flag.  By default it's
     false so only pass \1 to it.  In list context it returns a list of
     files/directories removed, in scalar context it returns the number of
     files/directories removed.  The list/number should match what was
     passed in if everything went well.

rm
     Just calls remove.  It's there for people who get tired of typing
     'remove'.

EXAMPLE
=======

   See SYNOPSIS.

BUGS
====

   Not that I know of. ;)

AUTHOR
======

   Gabor Egressy *gabor@vmunix.com*

   Copyright (c) 1998 Gabor Egressy.  All rights reserved.  All wrongs
reversed.  This program is free software; you can redistribute and/or
modify it under the same terms as Perl itself.

single call read & write file routines; read directories
********************************************************

NAME
====

     File::Slurp -- single call read & write file routines; read directories

SYNOPSIS
========

     use File::Slurp;

     $all_of_it = read_file($filename);
     @all_lines = read_file($filename);

     write_file($filename, @contents)

     overwrite_file($filename, @new_contnts);

     append_file($filename, @additional_contents);

     @files = read_dir($directory);

DESCRIPTION
===========

   These are quickie routines that are meant to save a couple of lines of
code over and over again.  They do not do anything fancy.

   read_file() does what you would expect.  If you are using its output in
array context, then it returns an array of lines.  If you are calling it
from scalar context, then returns the entire file in a single string.

   It croaks()s if it can't open the file.

   write_file() creates or overwrites files.

   append_file() appends to a file.

   overwrite_file() does an in-place update of an existing file or creates
a new file if it didn't already exist.  Write_file will also replace a
file.  The difference is that the first that that write_file() does is to
trucate the file whereas the last thing that overwrite_file() is to
trucate the file.  Overwrite_file() should be used in situations where you
have a file that always needs to have contents, even in the middle of an
update.

   read_dir() returns all of the entries in a directory except for "."
and "..".  It croaks if it cannot open the directory.

AUTHOR
======

   David Muir Sharnoff <muir@idiom.com>

Sort a file or merge sort multiple files
****************************************

NAME
====

   File::Sort - Sort a file or merge sort multiple files

SYNOPSIS
========

     use File::Sort qw(sort_file);
     sort_file({
       I => [qw(file_1 file_2)],
       o => 'file_new', k => '5.3,5.5rn', -t => '|'
     });

     sort_file('file1', 'file1.sorted');

DESCRIPTION
===========

   ***DANGER, WILL ROBINSON***

   The interface has changed in some significant ways from 0.1x.  See
`"HISTORY"' in this node.

   This module sorts text files by lines (or records).  Comparisons are
based on one or more sort keys extracted from each line of input, and are
performed lexicographically. By default, if keys are not given, sort
regards each input line as a single field.  The sort is a merge sort.  If
you don't like that, feel free to change it.

Options
-------

   The following options are available, and are passed in the hash
reference passed to the function in the format:

     OPTION => VALUE

   Where an option can take multiple values (like I, k, and pos), values
may be passed via an anonymous array:

     OPTION => [VALUE1, VALUE2]

   Where the OPTION is a switch, it should be passed a boolean VALUE of 1
or 0.

   This interface will always be supported, though a more perlish
interface may be offered in the future, as well.  This interface is
basically a mapping of the command-line options to the Unix sort utility.

I INPUT
     Pass in the input file(s).  This can be either a single string with
     the filename, or an array reference containing multiple filename
     strings.

c
     Check that single input fle is ordered as specified by the arguments
     and the collating sequence of the current locale.  No output is
     produced; only the exit code is affected.

m
     Merge only; the input files are assumed to already be sorted.

o OUTPUT
     Specify the name of an OUTPUT file to be used instead of the standard
     output.

u
     Unique: Suppresses all but one in each set of lines having equal keys.
     If used with the c option check that there are no lines with
     consecutive lines with duplicate keys, in addition to checking that
     the input file is sorted.

y MAX_SORT_RECORDS
     Maximum number of lines (records) read before writing to temp file.
     Default is 200,000. This may eventually change to be kbytes instead of
     lines.  Lines was easier to implement.  Can also specify with
     MAX_SORT_RECORDS environment variable.

F MAX_SORT_FILES
     Maximum number of temp files to be held open at once.  Default to 40,
     as older Windows ports had quite a small limit.  Can also specify
     with MAX_SORT_FILES environment variable.  No temp files will be used
     at all if MAX_SORT_RECORDS is never reached.

D
     Send debugging information to STDERR.  Behavior subject to change.

   The following options override the default ordering rules. When ordering
options appear independent of any key field specifications, the requested
field ordering rules are applied globally to all sort keys. When attached
to a specific key (see k), the specified ordering options override all
global ordering options for that key.

d
     Specify that only blank characters and alphanumeric characters,
     according to the current locale setting, are significant in
     comparisons.  d overrides i.

f
     Consider all lower-case characters that have upper-case equivalents,
     according to the current locale setting, to be the upper-case
     equivalent for the purposes of comparison.

i
     Ignores all characters that are non-printable, according to the
     current locale setting.

n
     Does numeric instead of string compare, using whatever perl considers
     to be a number in numeric comparisons.

r
     Reverse the sense of the comparisons.

b
     Ignore leading blank characters when determining the starting and
     ending positions of a restricted sort key.  If the b option is
     specified before the first k option, it is applied to all k options.
     Otherwise, the b option can be attached indepently to each
     field_start or field_end option argument (see below).

t STRING
     Use STRING as the field separator character; char is not considered
     to be part of a field (although it can be included in a sort key).
     Each occurrence of char is significant (for example, <char><char>
     delimits an empty field).  If t is not specified, blank characters
     are used as default field separators; each maximal non-empty sequence
     of blank characters that follows a non-blank character is a field
     separator.

X STRING
     Same as t, but STRING is interpreted as a Perl regular expression
     instead.  Do not escape any characters (/ characters need to be
     escaped internally, and will be escaped for you).

     The string matched by STRING is not included in the fields
     themselves, unless demanded by perl's regex and split semantics (e.g.,
     regexes in parentheses will add that matched expression as an extra
     field).  See Perlre (perl.info), and `split', see
     Perlfunc (perl.info).

R STRING
     Record separator, defaults to newline.

k *pos1[,pos2]*
     The keydef argument is a restricted sort key field definition. The
     format of this definition is:

          field_start[.first_char][type][,field_end[.last_char][type]]

     where field_start and field_end define a key field restricted to a
     portion of the line, and type is a modifier from the list of
     characters b, d, f, i, n, r.  The b modifier behaves like the b
     option, but applies only to the field_start or field_end to which it
     is attached. The other modifiers behave like the corresponding
     options, but apply only to the key field to which they are attached;
     they have this effect if specified with field_start, field_end, or
     both.  If any modifier is attached to a field_start or a field_end,
     no option applies to either.

     Occurrences of the k option are significant in command line order.
     If no k option is specified, a default sort key of the entire line is
     used.  When there are multiple keys fields, later keys are compared
     only after all earlier keys compare equal.

     Except when the u option is specified, lines that otherwise compare
     equal are ordered as if none of the options d, f, i, n or k were
     present (but with r still in effect, if it was specified) and with
     all bytes in the lines significant to the comparison.  The order in
     which lines that still compare equal are written is unspecified.

pos *+pos1 [-pos2]*
     Similar to k, these are mostly obsolete switches, but some people
     like them and want to use them.  Usage is:

          +field_start[.first_char][type] [-field_end[.last_char][type]]

     Where field_end in k specified the last position to be included, it
     specifes the last position to NOT be included.  Also, numbers are
     counted from 0 instead of 1.  *pos2* must immediately follow
     corresponding *+pos1*.  The rest should be the same as the k option.

     Mixing *+pos1* *pos2* with k is allowed, but will result in all of
     the *+pos1* *pos2* options being ordered AFTER the k options.  It is
     best if you Don't Do That.  Pick one and stick with it.

     Here are some equivalencies:

          pos => '+1 -2'              ->  k => '2,2'
          pos => '+1.1 -1.2'          ->  k => '2.2,2.2'
          pos => ['+1 -2', '+3 -5']   ->  k => ['2,2', '4,5']
          pos => ['+2', '+0b -1']     ->  k => ['3', '1b,1']
          pos => '+2.1 -2.4'          ->  k => '3.2,3.4'
          pos => '+2.0 -3.0'          ->  k => '3.1,4.0'

Not Implemented
---------------

   If the options are not listed as implemented above, or are not listed
in TODO below, they are not in the plan for implementation.  This includes
T and z.

EXAMPLES
========

   Sort file by straight string compare of each line, sending output to
STDOUT.

     use File::Sort qw(sort_file);
     sort_file('file');

   Sort contents of file by second key in file.

     sort_file({k => 2, I => 'file'});

   Sort, in reverse order, contents of file1 and file2, placing output in
outfile and using second character of second field as the sort key.

     sort_file({
         r => 1, k => '2.2,2.2', o => 'outfile',
         I => ['file1', 'file2']
     });

   Same sort but sorting numerically on characters 3 through 5 of the
fifth field first, and only return records with unique keys.

     sort_file({
         u => 1, r => 1, k => ['5.3,5.5rn', '2.2,2.2'],
         o => 'outfile', I => ['file1', 'file2']
     });

   Print passwd(4) file sorted by numeric user ID.

     sort_file({t => ':', k => '3n', I => '/etc/passwd'});

   For the anal sysadmin, check that passwd(4) file is sorted by numeric
user ID.

     sort_file({c => 1, t => ':', k => '3n', I => '/etc/passwd'});

ENVIRONMENT
===========

MAX_SORT_RECORDS
     Default is 200,000.  Maximum number of records to use before writing
     to a temp file.  Overriden by y option.

MAX_SORT_FILES
     Maximum number of open temp files to use before merging open temp
     files.  Overriden by F option.

LC_COLLATE
     Determine the locale for ordering rules.

LC_CTYPE
     Determine the locale for the interpretation of sequences of bytes of
     text data as characters (for example, single- versus multi-byte
     characters in arguments and input files) and the behaviour of
     character classification for the b, d, f, i and n options.

EXPORT
======

   Exports `sort_file' on request.

TODO
====

Better debugging and error reporting
Performance hit with -u
Do bytes instead of lines
Tests fail on non-ASCII locales.
HISTORY
=======

v0.91, Saturday, February 12, 2000
     Closed all files in test.pl so they could be unlinked on some
     platforms.  (Hubert Toullec)

     Documented I option.  (Hubert Toullec)

     Removed O_EXCL flag from `sort_file'.

     Fixed bug in sorting multiple files.  (Paul Eckert)

v0.90, Friday, April 30, 1999
     Complete rewrite.  Took the code from this module to write sort
     utility for PPT project, then brought changes back over.  As a result
     the interface has changed slightly, mostly in regard to what letters
     are used for options, but there are also some key behavioral
     differences.  If you need the old interface, the old module will
     remain on CPAN, but will not be supported.  Sorry for any
     inconvenience this may cause.  The good news is that it should not be
     too difficult to update your code to use the new interface.

v0.20
     Fixed bug with unique option (didn't work :).

     Switched to sysopen for better portability.

     Print to STDOUT if no output file supplied.

     Added c option to check sorting.

v0.18 (31 January 1998)
     Tests 3 and 4 failed because we hit the open file limit in the
     standard Windows port of perl5.004_02 (50).  Adjusted the default for
     total number of temp files from 50 to 40 (leave room for other open
     files), changed docs.  (Mike Blazer, Gurusamy Sarathy)

v0.17 (30 December 1998)
     Fixed bug in `_merge_files' that tried to open a passed IO::File
     object.

     Fixed up docs and did some more tests and benchmarks.

v0.16 (24 December 1998)
     One year between releases was too long.  I made changes Miko
     O'Sullivan wanted, and I didn't even know I had made them.

     Also now use IO::File to create temp files, so the TMPDIR option is
     no longer supported.  Hopefully made the whole thing more robust and
     faster, while supporting more options for sorting, including delimited
     sorts, and arbitrary sorts.

     Made CHUNK default a lot larger, which improves performance.  On
     low-memory systems, or where (e.g.) the MacPerl binary is not
     allocated much RAM, it might need to be lowered.

v0.11 (04 January 1998)
     More cleanup; fixed special case of no linebreak on last line; wrote
     test suite; fixed warning for redefined subs (sort1 and sort2).

v0.10 (03 January 1998)
     Some cleanup; made it not subject to system file limitations;
     separated many parts out into separate functions.

v0.03 (23 December 1997)
     Added reverse and numeric sorting options.

v0.02 (19 December 1997)
     Added unique and merge-only options.

v0.01 (18 December 1997)
     First release.

THANKS
======

   Mike Blazer <blazer@mail.nevalink.ru>, Vicki Brown <vlb@cfcl.com>, Tom
Christiansen <tchrist@perl.com>, Albert Dvornik <bert@mit.edu>, Paul
Eckert <peckert@epicrealm.com>, Gene Hsu <gene@moreinfo.com>, Andrew M.
Langmead <aml@world.std.com>, Brian L. Matthews <blm@halcyon.com>, Rich
Morin <rdm@cfcl.com>, Matthias Neeracher <neeri@iis.ee.ethz.ch>, Miko
O'Sullivan <miko@idocs.com>, Tom Phoneix <rootbeer@teleport.com>, Gurusamy
Sarathy <gsar@activestate.com> Hubert Toullec <Hubert.Toullec@wanadoo.fr>.

AUTHOR
======

   Chris Nandor <pudge@pobox.com>, http://pudge.net/

   Copyright (c) 2000 Chris Nandor.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the terms of
the Artistic License, distributed with Perl.

VERSION
=======

   v0.91, Saturday, February 12, 2000

SEE ALSO
========

   sort(1), locale, PPT project, <URL:http://language.perl.com/ppt/>.

portably perform operations on file names
*****************************************

NAME
====

   File::Spec - portably perform operations on file names

SYNOPSIS
========

     use File::Spec;

     $x=File::Spec->catfile('a', 'b', 'c');

   which returns 'a/b/c' under Unix. Or:

     use File::Spec::Functions;

     $x = catfile('a', 'b', 'c');

DESCRIPTION
===========

   This module is designed to support operations commonly performed on file
specifications (usually called "file names", but not to be confused with
the contents of a file, or Perl's file handles), such as concatenating
several directory and file names into a single path, or determining
whether a path is rooted. It is based on code directly taken from
MakeMaker 5.17, code written by Andreas KE<ouml>nig, Andy Dougherty,
Charles Bailey, Ilya Zakharevich, Paul Schinder, and others.

   Since these functions are different for most operating systems, each
set of OS specific routines is available in a separate module, including:

     File::Spec::Unix
     File::Spec::Mac
     File::Spec::OS2
     File::Spec::Win32
     File::Spec::VMS

   The module appropriate for the current OS is automatically loaded by
File::Spec. Since some modules (like VMS) make use of facilities available
only under that OS, it may not be possible to load all modules under all
operating systems.

   Since File::Spec is object oriented, subroutines should not called
directly, as in:

     File::Spec::catfile('a','b');

   but rather as class methods:

     File::Spec->catfile('a','b');

   For simple uses, see File/Spec/Functions,
provides convenient functional forms of these methods.

   For a list of available methods, please consult File/Spec/Unix,
which contains the entire set, and which is inherited by
the modules for other platforms. For further information, please see
File/Spec/Mac, File/Spec/OS2,
File/Spec/Win32, or File/Spec/VMS.

SEE ALSO
========

   File::Spec::Unix, File::Spec::Mac, File::Spec::OS2, File::Spec::Win32,
File::Spec::VMS, File::Spec::Functions, ExtUtils::MakeMaker

AUTHORS
=======

   Kenneth Albanowski <`kjahds@kjahds.com'>, Andy Dougherty
<`doughera@lafcol.lafayette.edu'>, Andreas KE<ouml>nig
<`A.Koenig@franz.ww.TU-Berlin.DE'>, Tim Bunce <`Tim.Bunce@ig.co.uk'>. VMS
support by Charles Bailey <`bailey@newman.upenn.edu'>.  OS/2 support by
Ilya Zakharevich <`ilya@math.ohio-state.edu'>. Mac support by Paul Schinder
<`schinder@pobox.com'>.  abs2rel() and rel2abs() written by Shigio
Yamaguchi <`shigio@tamacom.com'>, modified by Barrie Slaymaker
<`barries@slaysys.com'>.  splitpath(), splitdir(), catpath() and catdir()
by Barrie Slaymaker.

portably perform operations on file names
*****************************************

NAME
====

   File::Spec::Functions - portably perform operations on file names

SYNOPSIS
========

     use File::Spec::Functions;
     $x = catfile('a','b');

DESCRIPTION
===========

   This module exports convenience functions for all of the class methods
provided by File::Spec.

   For a reference of available functions, please consult
File/Spec/Unix, which contains the entire set, and which
is inherited by the modules for other platforms. For further information,
please see File/Spec/Mac, File/Spec/OS2,
see File/Spec/Win32, or
File/Spec/VMS.

Exports
-------

   The following functions are exported by default.

     canonpath
     catdir
     catfile
     curdir
     rootdir
     updir
     no_upwards
     file_name_is_absolute
     path

   The following functions are exported only by request.

     devnull
     tmpdir
     splitpath
     splitdir
     catpath
     abs2rel
     rel2abs

   All the functions may be imported using the :ALL tag.

SEE ALSO
========

   File::Spec, File::Spec::Unix, File::Spec::Mac, File::Spec::OS2,
File::Spec::Win32, File::Spec::VMS, ExtUtils::MakeMaker

File::Spec for MacOS
********************

NAME
====

   File::Spec::Mac - File::Spec for MacOS

SYNOPSIS
========

     require File::Spec::Mac; # Done internally by File::Spec if needed

DESCRIPTION
===========

   Methods for manipulating file specifications.

METHODS
=======

canonpath
     On MacOS, there's nothing to be done.  Returns what it's given.

catdir
     Concatenate two or more directory names to form a complete path
     ending with a directory.  Put a trailing : on the end of the complete
     path if there isn't one, because that's what's done in MacPerl's
     environment.

     The fundamental requirement of this routine is that

          File::Spec->catdir(split(":",$path)) eq $path

     But because of the nature of Macintosh paths, some additional
     possibilities are allowed to make using this routine give reasonable
     results for some common situations.  Here are the rules that are
     used.  Each argument has its trailing ":" removed.  Each argument,
     except the first, has its leading ":" removed.  They are then joined
     together by a ":".

     So

          File::Spec->catdir("a","b") = "a:b:"
          File::Spec->catdir("a:",":b") = "a:b:"
          File::Spec->catdir("a:","b") = "a:b:"
          File::Spec->catdir("a",":b") = "a:b"
          File::Spec->catdir("a","","b") = "a::b"

     etc.

     To get a relative path (one beginning with :), begin the first
     argument with : or put a "" as the first argument.

     If you don't want to worry about these rules, never allow a ":" on
     the ends of any of the arguments except at the beginning of the first.

     Under MacPerl, there is an additional ambiguity.  Does the user
     intend that

          File::Spec->catfile("LWP","Protocol","http.pm")

     be relative or absolute?  There's no way of telling except by
     checking for the existence of LWP: or :LWP, and even there he may
     mean a dismounted volume or a relative path in a different directory
     (like in @INC).   So those checks aren't done here. This routine will
     treat this as absolute.

catfile
     Concatenate one or more directory names and a filename to form a
     complete path ending with a filename.  Since this uses catdir, the
     same caveats apply.  Note that the leading : is removed from the
     filename, so that

          File::Spec->catfile($ENV{HOME},"file");

     and

          File::Spec->catfile($ENV{HOME},":file");

     give the same answer, as one might expect.

curdir
     Returns a string representing the current directory.

devnull
     Returns a string representing the null device.

rootdir
     Returns a string representing the root directory.  Under MacPerl,
     returns the name of the startup volume, since that's the closest in
     concept, although other volumes aren't rooted there.

tmpdir
     Returns a string representation of the first existing directory from
     the following list or " if none exist:

          $ENV{TMPDIR}

updir
     Returns a string representing the parent directory.

file_name_is_absolute
     Takes as argument a path and returns true, if it is an absolute path.
     In the case where a name can be either relative or absolute (for
     example, a folder named "HD" in the current working directory on a
     drive named "HD"), relative wins.  Use ":" in the appropriate place
     in the path if you want to distinguish unambiguously.

     As a special case, the file name " is always considered to be
     absolute.

path
     Returns the null list for the MacPerl application, since the concept
     is usually meaningless under MacOS. But if you're using the MacPerl
     tool under MPW, it gives back $ENV{Commands} suitably split, as is
     done in :lib:ExtUtils:MM_Mac.pm.

splitpath
splitdir
catpath

abs2rel
     See `abs2rel', see File/Spec/Unix, for general
     documentation.

     Unlike `File::Spec::Unix-'abs2rel()>, this function will make checks
     against the local filesystem if necessary.  See `' in this node for
     details.

rel2abs
     See `rel2abs', see File/Spec/Unix, for general
     documentation.

     Unlike `File::Spec::Unix-'rel2abs()>, this function will make checks
     against the local filesystem if necessary.  See `' in this node for
     details.

SEE ALSO
========

   See File/Spec,

methods for OS/2 file specs
***************************

NAME
====

   File::Spec::OS2 - methods for OS/2 file specs

SYNOPSIS
========

     require File::Spec::OS2; # Done internally by File::Spec if needed

DESCRIPTION
===========

   See File::Spec::Unix for a documentation of the methods provided there.
This package overrides the implementation of these methods, not the
semantics.

methods used by File::Spec
**************************

NAME
====

   File::Spec::Unix - methods used by File::Spec

SYNOPSIS
========

     require File::Spec::Unix; # Done automatically by File::Spec

DESCRIPTION
===========

   Methods for manipulating file specifications.

METHODS
=======

canonpath
     No physical check on the filesystem, but a logical cleanup of a path.
     On UNIX eliminated successive slashes and successive "/.".

          $cpath = File::Spec->canonpath( $path ) ;

catdir
     Concatenate two or more directory names to form a complete path ending
     with a directory. But remove the trailing slash from the resulting
     string, because it doesn't look good, isn't necessary and confuses
     OS2. Of course, if this is the root directory, don't cut off the
     trailing slash :-)

catfile
     Concatenate one or more directory names and a filename to form a
     complete path ending with a filename

curdir
     Returns a string representation of the current directory.  "." on
     UNIX.

devnull
     Returns a string representation of the null device. "/dev/null" on
     UNIX.

rootdir
     Returns a string representation of the root directory.  "/" on UNIX.

tmpdir
     Returns a string representation of the first writable directory from
     the following list or "" if none are writable:

          $ENV{TMPDIR}
          /tmp

updir
     Returns a string representation of the parent directory.  ".." on
     UNIX.

no_upwards
     Given a list of file names, strip out those that refer to a parent
     directory. (Does not strip symlinks, only '.', '..', and equivalents.)

case_tolerant
     Returns a true or false value indicating, respectively, that
     alphabetic is not or is significant when comparing file
     specifications.

file_name_is_absolute
     Takes as argument a path and returns true if it is an absolute path.

     This does not consult the local filesystem on Unix, Win32, or OS/2.
     It does sometimes on MacOS (see `File::Spec::MacOS' in this node).
     It does consult the working environment for VMS (see
     `file_name_is_absolute', see File/Spec/VMS).

path
     Takes no argument, returns the environment variable PATH as an array.

join
     join is the same as catfile.

splitpath
          ($volume,$directories,$file) = File::Spec->splitpath( $path );
          ($volume,$directories,$file) = File::Spec->splitpath( $path, $no_file );

     Splits a path in to volume, directory, and filename portions. On
     systems with no concept of volume, returns undef for volume.

     For systems with no syntax differentiating filenames from directories,
     assumes that the last file is a path unless $no_file is true or a
     trailing separator or /. or /.. is present. On Unix this means that
     $no_file true makes this return ( ", $path, " ).

     The directory portion may or may not be returned with a trailing '/'.

     The results can be passed to `' in this node to get back a path
     equivalent to (usually identical to) the original path.

splitdir
     The opposite of `' in this node.

          @dirs = File::Spec->splitdir( $directories );

     $directories must be only the directory portion of the path on systems
     that have the concept of a volume or that have path syntax that
     differentiates files from directories.

     Unlike just splitting the directories on the separator, empty
     directory names (") can be returned, because these are significant on
     some OSs (e.g. MacOS).

     On Unix,

          File::Spec->splitdir( "/a/b//c/" );

     Yields:

          ( '', 'a', 'b', '', 'c', '' )

catpath
     Takes volume, directory and file portions and returns an entire path.
     Under Unix, $volume is ignored, and directory and file are catenated.
     A '/' is inserted if need be.  On other OSs, $volume is significant.

abs2rel
     Takes a destination path and an optional base path returns a relative
     path from the base path to the destination path:

          $rel_path = File::Spec->abs2rel( $path ) ;
          $rel_path = File::Spec->abs2rel( $path, $base ) ;

     If $base is not present or ", then `cwd()' in this node is used. If
     $base is relative, then it is converted to absolute form using `' in
     this node. This means that it is taken to be relative to `cwd()' in
     this node.

     On systems with the concept of a volume, this assumes that both paths
     are on the $destination volume, and ignores the $base volume.

     On systems that have a grammar that indicates filenames, this ignores
     the $base filename as well. Otherwise all path components are assumed
     to be directories.

     If $path is relative, it is converted to absolute form using `' in
     this node.  This means that it is taken to be relative to `cwd()' in
     this node.

     No checks against the filesystem are made on most systems.  On MacOS,
     the filesystem may be consulted (see `File::Spec::MacOS' in this
     node).  On VMS, there is interaction with the working environment, as
     logicals and macros are expanded.

     Based on code written by Shigio Yamaguchi.

rel2abs
     Converts a relative path to an absolute path.

          $abs_path = File::Spec->rel2abs( $path ) ;
          $abs_path = File::Spec->rel2abs( $path, $base ) ;

     If $base is not present or ", then `cwd()' in this node is used. If
     $base is relative, then it is converted to absolute form using `' in
     this node. This means that it is taken to be relative to `cwd()' in
     this node.

     On systems with the concept of a volume, this assumes that both paths
     are on the $base volume, and ignores the $path volume.

     On systems that have a grammar that indicates filenames, this ignores
     the $base filename as well. Otherwise all path components are assumed
     to be directories.

     If $path is absolute, it is cleaned up and returned using `' in this
     node.

     No checks against the filesystem are made on most systems.  On MacOS,
     the filesystem may be consulted (see `File::Spec::MacOS' in this
     node).  On VMS, there is interaction with the working environment, as
     logicals and macros are expanded.

     Based on code written by Shigio Yamaguchi.

SEE ALSO
========

   See File/Spec,

methods for VMS file specs
**************************

NAME
====

   File::Spec::VMS - methods for VMS file specs

SYNOPSIS
========

     require File::Spec::VMS; # Done internally by File::Spec if needed

DESCRIPTION
===========

   See File::Spec::Unix for a documentation of the methods provided there.
This package overrides the implementation of these methods, not the
semantics.

eliminate_macros
     Expands MM[KS]/Make macros in a text string, using the contents of
     identically named elements of `%$self', and returns the result as a
     file specification in Unix syntax.

fixpath
     Catchall routine to clean up problem MM[SK]/Make macros.  Expands
     macros in any directory specification, in order to avoid juxtaposing
     two VMS-syntax directories when MM[SK] is run.  Also expands
     expressions which are all macro, so that we can tell how long the
     expansion is, and avoid overrunning DCL's command buffer when MM[KS]
     is running.

     If optional second argument has a TRUE value, then the return string
     is a VMS-syntax directory specification, if it is FALSE, the return
     string is a VMS-syntax file specification, and if it is not
     specified, fixpath() checks to see whether it matches the name of a
     directory in the current default directory, and returns a directory
     or file specification accordingly.

Methods always loaded
---------------------

canonpath (override)
     Removes redundant portions of file specifications according to VMS
     syntax.

catdir
     Concatenates a list of file specifications, and returns the result as
     a VMS-syntax directory specification.  No check is made for
     "impossible" cases (e.g. elements other than the first being absolute
     filespecs).

catfile
     Concatenates a list of file specifications, and returns the result as
     a VMS-syntax file specification.

curdir (override)
     Returns a string representation of the current directory: '[]'

devnull (override)
     Returns a string representation of the null device: '_NLA0:'

rootdir (override)
     Returns a string representation of the root directory:
     'SYS$DISK:[000000]'

tmpdir (override)
     Returns a string representation of the first writable directory from
     the following list or " if none are writable:

          sys$scratch
          $ENV{TMPDIR}

updir (override)
     Returns a string representation of the parent directory: '[-]'

case_tolerant (override)
     VMS file specification syntax is case-tolerant.

path (override)
     Translate logical name DCL$PATH as a searchlist, rather than trying
     to split string value of `$ENV{'PATH'}'.

file_name_is_absolute (override)
     Checks for VMS directory spec as well as Unix separators.

splitpath (override)
     Splits using VMS syntax.

splitdir (override)
     Split dirspec using VMS syntax.

catpath (override)
     Construct a complete filespec using VMS syntax

abs2rel (override)
     Use VMS syntax when converting filespecs.

rel2abs (override)
     Use VMS syntax when converting filespecs.

SEE ALSO
========

   See File/Spec,

methods for Win32 file specs
****************************

NAME
====

   File::Spec::Win32 - methods for Win32 file specs

SYNOPSIS
========

     require File::Spec::Win32; # Done internally by File::Spec if needed

DESCRIPTION
===========

   See File::Spec::Unix for a documentation of the methods provided there.
This package overrides the implementation of these methods, not the
semantics.

devnull
     Returns a string representation of the null device.

tmpdir
     Returns a string representation of the first existing directory from
     the following list:

          $ENV{TMPDIR}
          $ENV{TEMP}
          $ENV{TMP}
          /tmp
          /

catfile
     Concatenate one or more directory names and a filename to form a
     complete path ending with a filename

canonpath
     No physical check on the filesystem, but a logical cleanup of a path.
     On UNIX eliminated successive slashes and successive "/.".

splitpath
          ($volume,$directories,$file) = File::Spec->splitpath( $path );
          ($volume,$directories,$file) = File::Spec->splitpath( $path, $no_file );

     Splits a path in to volume, directory, and filename portions. Assumes
     that the last file is a path unless the path ends in '\\', '\\.',
     '\\..'  or $no_file is true.  On Win32 this means that $no_file true
     makes this return ( $volume, $path, undef ).

     Separators accepted are \ and /.

     Volumes can be drive letters or UNC sharenames (\\server\share).

     The results can be passed to `' in this node to get back a path
     equivalent to (usually identical to) the original path.

splitdir
     The opposite of `' in this node.

          @dirs = File::Spec->splitdir( $directories );

     $directories must be only the directory portion of the path on systems
     that have the concept of a volume or that have path syntax that
     differentiates files from directories.

     Unlike just splitting the directories on the separator, leading empty
     and trailing directory entries can be returned, because these are
     significant on some OSs. So,

          File::Spec->splitdir( "/a/b/c" );

     Yields:

          ( '', 'a', 'b', '', 'c', '' )

catpath
     Takes volume, directory and file portions and returns an entire path.
     Under Unix, $volume is ignored, and this is just like catfile(). On
     other OSs, the $volume become significant.

SEE ALSO
========

   See File/Spec,

Perl access to fsync() and sync() function calls
************************************************

NAME
====

   File::Sync - Perl access to fsync() and sync() function calls

SYNOPSIS
========

     use File::Sync qw(fsync sync);
     fsync(\*FILEHANDLE) or die "fsync: $!";
     sync();

     use File::Sync qw(fsync);
     use IO::File;
     $fh = IO::File->new("> /tmp/foo")
         or die "new IO::File: $!";
     ...
     fsync($fh) or die "fsync: $!";

DESCRIPTION
===========

   The fsync() function takes a Perl file handle as its only argument, and
passes its fileno() to the C function fsync().  It returns undef on
failure, or *true* on success.

   The fsync_fd() function is used internally by fsync(); it takes a file
descriptor as its only argument.

   The sync() function is identical to the C function sync().

   This module does not export any methods by default, but fsync() is made
available as a method of the FileHandle and IO::Handle classes.

NOTES
=====

   Doing fsync() if the stdio buffers aren't flushed (with $| or the
autoflush method) is probably pointless.

   Calling sync() too often on a multi-user system is slightly antisocial.

AUTHOR
======

   Carey Evans <*c.evans@clear.net.nz*>

SEE ALSO
========

   perl(1), fsync(2), sync(2), perlvar(1)

Perl extension for reading from continously updated files
*********************************************************

NAME
====

   File::Tail - Perl extension for reading from continously updated files

SYNOPSIS
========

     use File::Tail;
     $file=File::Tail->new("/some/log/file");
     while (defined($line=$file->read)) {
         print "$line";
     }

     use File::Tail;
     $file=File::Tail->new(name=>$name, maxinterval=>300, adjustafter=>7);
     while (defined($line=$file->read)) {
         print "$line";
     }

   OR, you could use tie (additional parameters can be passed with the
name, or can be set using $ref):

     use File::Tail;
     my $ref=tie *FH,"File::Tail",(name=>$name);
     while (<FH>) {
         print "$_";
     }
     }

   Note that the above script will never exit. If there is nothing being
written to the file, it will simply block.

   You can find more synopsii in the file logwatch, which is included in
the distribution.

   Note: Select functionality was added in version 0.9, and it required
some reworking of all routines. ***PLEASE*** let me know if you see
anything strange happening.

   You can find two way of using select in the file select_demo which is
included in the ditribution.

DESCRIPTION
===========

   The primary purpose of File::Tail is reading and analysing log files
while they are being written, which is especialy usefull if you are
monitoring the logging process with a tool like Tobias Oetiker's MRTG.

   The module tries very hard NOT to "busy-wait" on a file that has little
traffic. Any time it reads new data from the file, it counts the number of
new lines, and divides that number by the time that passed since data were
last written to the file before that. That is considered the average time
before new data will be written. When there is no new data to read,
`File::Tail' sleeps for that number of seconds. Thereafter, the waiting
time is recomputed dynamicaly. Note that `File::Tail' never sleeps for
more than the number of seconds set by maxinterval.

   If the file does not get altered for a while, `File::Tail' gets
suspicious and startschecking if the file was truncated, or moved and
recreated. If anything like that had happened, `File::Tail' will quietly
reopen the file, and continue reading. The only way to affect what happens
on reopen is by setting the reset_tail parameter (see below). The effect
of this is that the scripts need not be aware when the logfiles were
rotated, they will just quietly work on.

   Note that the sleep and time used are from Time::HiRes, so this module
should do the right thing even if the time to sleep is less than one
second.

   The logwatch script (also included) demonstrates several ways of calling
the methods.

CONSTRUCTOR
===========

new ([ ARGS ])
--------------

   Creates a `File::Tail'. If it has only one paramter, it is assumed to
be the filename. If the open fails, the module performs a croak. I am
currently looking for a way to set $! and return undef.

   You can pass several parameters to new:

name
     This is the name of the file to open. The file will be opened for
     reading.  This must be a regular file, not a pipe or a terminal (i.e.
     it must be seekable).

maxinterval
     The maximum number of seconds (real number) that will be spent
     sleeping.  Default is 60, meaning `File::Tail' will never spend more
     than sixty seconds without checking the file.

interval
     The initial number of seconds (real number) that will be spent
     sleeping, before the file is first checked. Default is ten seconds,
     meaning `File::Tail' will sleep for 10 seconds and then determine,
     how many new lines have appeared in the file.

adjustafter
     The number of times `File::Tail' waits for the current interval,
     before adjusting the interval upwards. The default is 10.

resetafter
     The number of seconds after last change when `File::Tail' decides the
     file may have been closed and reopened. The default is
     adjustafter*maxinterval.

maxbuf
     The maximum size of the internal buffer. When File::Tail suddenly
     found an enormous ammount of information in the file (for instance if
     the retry parameters were set to very infrequent checking and the
     file was rotated), File::Tail sometimes slurped way too much file
     into memory.  This sets the maximum size of File::Tail's buffer.

     Default value is 16384 (bytes).

     A large internal buffer may result in worse performance (as well as
     increased memory usage), since File::Tail will have to do more work
     processing the internal buffer.

nowait
     Does not block on read, but returns an empty string if there is
     nothing to read. DO NOT USE THIS unless you know what you are doing.
     If you are using it in a loop, you probably DON'T know what you are
     doing.  If you want to read tails from multiple files, use select.

ignore_nonexistant
          Do not complain if the file doesn't exist when it is first
          opened or when it is to be reopened. (File may be reopened after
          resetafter seconds have passed since last data was found.)

tail
          When first started, read and return C<n> lines from the file.
          If C<n> is zero, start at the end of file. If C<n> is negative,
          return the whole file.

          Default is C<0>.

reset_tail
          Same as tail, but applies after reset. (i.e. after the
          file has been automaticaly closed and reopened). Defaults to
          C<-1>, i.e. does not skip any information present in the
          file when it first checks it.

          Why would you want it otherwise? I've seen files which
          have been cycled like this:

          grep -v lastmonth log >newlog
          mv log archive/lastmonth
          mv newlog log
          kill -HUP logger

     Obviously, if this happens and you have reset_tail set to c<-1>, you
     will suddenly get a whole bunch of lines - lines you already saw. So
     in this case, reset_tail should probably be set to a small positive
     number or even 0.

debug
     Set to nonzero if you want to see more about the inner workings of
     File::Tail. Otherwise not useful.

errmode
     Modeled after the methods from Net:Telnet, here you decide how the
     errors should be handled. The parameter can be a code reference which
     is called with the error string as a parameter, an array with a code
     reference as the first parameter and other parameters to be passed to
     handler subroutine, or one of the words:

     return  - ignore any error (just put error message in errmsg).  warn
      - output the error message but continue die     - display error
     message and exit

     Default is die.

METHODS
=======

read
----

   read returns one line from the input file. If there are no lines ready,
it blocks until there are.

select
------

   select is intended to enable the programmer to simoultaneously wait for
input on normal filehandles and File::Tail filehandles. Of course, you may
use it to simply read from more than one File::Tail filehandle at a time.

   For an example of usage, look at the script select_demo.

   Basicaly, you call File::Tail::select just as you would normal select,
with fields for rbits, wbits and ebits, as well as a timeout, however, you
can tack any number of File::Tail objects (not File::Tail filehandles!)
to the end.

   When you do this, File::Tail's select emulates normal select, with two
exceptions:

   a) it will return if there is input on any of the parameters (i.e.
normal filehandles) _or_ File::Tails.

   b) In addition to `($nfound, $timeleft)', the return array will also
contain a list of File::Tail objects which are ready for reading.
`$nfound' will contain the correct number of filehandles to be read (i.e.
both normal and File::Tails).

   Once select returns, when you want to determine which File::Tail objects
have input ready, you can either use the list of objects select returned,
or you can check each individual object with $object->predict. This returns
the ammount of time (in fractional seconds) after which the handle expects
input. If it returns 0, there is input waiting. There is no guarantee that
there will be input waiting after the returned number of seconds has
passed.  However, File::Tail won't do any I/O on the file until that time
has passed.

   Also note, if you are determining which files are ready for input by
calling each individual predict, the `$nfound' value may be invalid,
because one or more of File::Tail object may have become ready between the
time select has returned and the time when you checked it.

TO BE DONE
==========

   Planned for 0.95-1.0: Using $/ instead of \n to separate "lines" (which
should make it possible to read wtmp type files).

AUTHOR
======

   Matija Grabnar, matija.grabnar@arnes.si

SEE ALSO
========

   perl(1), tail (1), MRTG
(http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html)

return name and handle of a temporary file safely
*************************************************

NAME
====

   File::Temp - return name and handle of a temporary file safely

PORTABILITY
===========

   This module is designed to be portable across operating systems and it
currently supports Unix, VMS, DOS, OS/2 and Windows. When porting to a new
OS there are generally three main issues that have to be solved:

   * Can the OS unlink an open file? If it can not then the
     `_can_unlink_opened_file' method should be modified.

   * Are the return values from stat reliable? By default all the return
     values from stat are compared when unlinking a temporary file using
     the filename and the handle. Operating systems other than unix do not
     always have valid entries in all fields. If unlink0 fails then the
     stat comparison should be modified accordingly.

   * Security. Systems that can not support a test for the sticky bit on a
     directory can not use the MEDIUM and HIGH security tests.  The
     `_can_do_level' method should be modified accordingly.

SYNOPSIS
========

     use File::Temp qw/ tempfile tempdir /;

     $dir = tempdir( CLEANUP => 1 );
     ($fh, $filename) = tempfile( DIR => $dir );

     ($fh, $filename) = tempfile( $template, DIR => $dir);
     ($fh, $filename) = tempfile( $template, SUFFIX => '.dat');

     $fh = tempfile();

   MkTemp family:

     use File::Temp qw/ :mktemp  /;

     ($fh, $file) = mkstemp( "tmpfileXXXXX" );
     ($fh, $file) = mkstemps( "tmpfileXXXXXX", $suffix);

     $tmpdir = mkdtemp( $template );

     $unopened_file = mktemp( $template );

   POSIX functions:

     use File::Temp qw/ :POSIX /;

     $file = tmpnam();
     $fh = tmpfile();

     ($fh, $file) = tmpnam();
     ($fh, $file) = tmpfile();

   Compatibility functions:

     $unopened_file = File::Temp::tempnam( $dir, $pfx );

   Objects (NOT YET IMPLEMENTED):

     require File::Temp;

     $fh = new File::Temp($template);
     $fname = $fh->filename;

DESCRIPTION
===========

   `File::Temp' can be used to create and open temporary files in a safe
way.  The tempfile() function can be used to return the name and the open
filehandle of a temporary file.  The tempdir() function can be used to
create a temporary directory.

   The security aspect of temporary file creation is emphasized such that
a filehandle and filename are returned together.  This helps guarantee
that a race condition can not occur where the temporary file is created by
another process between checking for the existence of the file and its
opening.  Additional security levels are provided to check, for example,
that the sticky bit is set on world writable directories.  See
`"safe_level"' in this node for more information.

   For compatibility with popular C library functions, Perl
implementations of the mkstemp() family of functions are provided. These
are, mkstemp(), mkstemps(), mkdtemp() and mktemp().

   Additionally, implementations of the standard `POSIX|POSIX' in this node
tmpnam() and tmpfile() functions are provided if required.

   Implementations of mktemp(), tmpnam(), and tempnam() are provided, but
should be used with caution since they return only a filename that was
valid when function was called, so cannot guarantee that the file will not
exist by the time the caller opens the filename.

FUNCTIONS
=========

   This section describes the recommended interface for generating
temporary files and directories.

tempfile
     This is the basic function to generate temporary files.  The
     behaviour of the file can be changed using various options:

          ($fh, $filename) = tempfile();

     Create a temporary file in  the directory specified for temporary
     files, as specified by the tmpdir() function in File/Spec.

          ($fh, $filename) = tempfile($template);

     Create a temporary file in the current directory using the supplied
     template.  Trailing `X' characters are replaced with random letters to
     generate the filename.  At least four `X' characters must be present
     in the template.

          ($fh, $filename) = tempfile($template, SUFFIX => $suffix)

     Same as previously, except that a suffix is added to the template
     after the `X' translation.  Useful for ensuring that a temporary
     filename has a particular extension when needed by other applications.
     But see the WARNING at the end.

          ($fh, $filename) = tempfile($template, DIR => $dir);

     Translates the template as before except that a directory name is
     specified.

          ($fh, $filename) = tempfile($template, UNLINK => 1);

     Return the filename and filehandle as before except that the file is
     automatically removed when the program exits. Default is for the file
     to be removed if a file handle is requested and to be kept if the
     filename is requested. In a scalar context (where no filename is
     returned) the file is always deleted either on exit or when it is
     closed.

     If the template is not specified, a template is always automatically
     generated. This temporary file is placed in tmpdir() (see
     File/Spec) unless a directory is specified explicitly
     with the DIR option.

          $fh = tempfile( $template, DIR => $dir );

     If called in scalar context, only the filehandle is returned and the
     file will automatically be deleted when closed (see the description
     of tmpfile() elsewhere in this document).  This is the preferred mode
     of operation, as if you only have a filehandle, you can never create
     a race condition by fumbling with the filename. On systems that can
     not unlink an open file or can not mark a file as temporary when it
     is opened (for example, Windows NT uses the `O_TEMPORARY' flag)) the
     file is marked for deletion when the program ends (equivalent to
     setting UNLINK to 1). The `UNLINK' flag is ignored if present.

          (undef, $filename) = tempfile($template, OPEN => 0);

     This will return the filename based on the template but will not open
     this file.  Cannot be used in conjunction with UNLINK set to true.
     Default is to always open the file to protect from possible race
     conditions. A warning is issued if warnings are turned on. Consider
     using the tmpnam() and mktemp() functions described elsewhere in this
     document if opening the file is not required.

     Options can be combined as required.

tempdir
     This is the recommended interface for creation of temporary
     directories.  The behaviour of the function depends on the arguments:

          $tempdir = tempdir();

     Create a directory in tmpdir() (see `File::Spec|File::Spec' in this
     node).

          $tempdir = tempdir( $template );

     Create a directory from the supplied template. This template is
     similar to that described for tempfile(). `X' characters at the end
     of the template are replaced with random letters to construct the
     directory name. At least four `X' characters must be in the template.

          $tempdir = tempdir ( DIR => $dir );

     Specifies the directory to use for the temporary directory.  The
     temporary directory name is derived from an internal template.

          $tempdir = tempdir ( $template, DIR => $dir );

     Prepend the supplied directory name to the template. The template
     should not include parent directory specifications itself. Any parent
     directory specifications are removed from the template before
     prepending the supplied directory.

          $tempdir = tempdir ( $template, TMPDIR => 1 );

     Using the supplied template, creat the temporary directory in a
     standard location for temporary files. Equivalent to doing

          $tempdir = tempdir ( $template, DIR => File::Spec->tmpdir);

     but shorter. Parent directory specifications are stripped from the
     template itself. The TMPDIR option is ignored if DIR is set
     explicitly.  Additionally, TMPDIR is implied if neither a template
     nor a directory are supplied.

          $tempdir = tempdir( $template, CLEANUP => 1);

     Create a temporary directory using the supplied template, but attempt
     to remove it (and all files inside it) when the program exits. Note
     that an attempt will be made to remove all files from the directory
     even if they were not created by this module (otherwise why ask to
     clean it up?). The directory removal is made with the rmtree()
     function from the `File::Path|File::Path' in this node module.  Of
     course, if the template is not specified, the temporary directory
     will be created in tmpdir() and will also be removed at program exit.

MKTEMP FUNCTIONS
================

   The following functions are Perl implementations of the mktemp() family
of temp file generation system calls.

mkstemp
     Given a template, returns a filehandle to the temporary file and the
     name of the file.

          ($fh, $name) = mkstemp( $template );

     In scalar context, just the filehandle is returned.

     The template may be any filename with some number of X's appended to
     it, for example `/tmp/temp.XXXX'. The trailing X's are replaced with
     unique alphanumeric combinations.

mkstemps
     Similar to mkstemp(), except that an extra argument can be supplied
     with a suffix to be appended to the template.

          ($fh, $name) = mkstemps( $template, $suffix );

     For example a template of `testXXXXXX' and suffix of `.dat' would
     generate a file similar to `testhGji_w.dat'.

     Returns just the filehandle alone when called in scalar context.

mkdtemp
     Create a directory from a template. The template must end in X's that
     are replaced by the routine.

          $tmpdir_name = mkdtemp($template);

     Returns the name of the temporary directory created.  Returns undef
     on failure.

     Directory must be removed by the caller.

mktemp
     Returns a valid temporary filename but does not guarantee that the
     file will not be opened by someone else.

          $unopened_file = mktemp($template);

     Template is the same as that required by mkstemp().

POSIX FUNCTIONS
===============

   This section describes the re-implementation of the tmpnam() and
tmpfile() functions described in POSIX, using the mkstemp()
from this module.

   Unlike the `POSIX|POSIX' in this node implementations, the directory
used for the temporary file is not specified in a system include file
(`P_tmpdir') but simply depends on the choice of tmpdir() returned by
`File::Spec|File::Spec' in this node. On some implementations this
location can be set using the TMPDIR environment variable, which may not
be secure.  If this is a problem, simply use mkstemp() and specify a
template.

tmpnam
     When called in scalar context, returns the full name (including path)
     of a temporary file (uses mktemp()). The only check is that the file
     does not already exist, but there is no guarantee that that condition
     will continue to apply.

          $file = tmpnam();

     When called in list context, a filehandle to the open file and a
     filename are returned. This is achieved by calling mkstemp() after
     constructing a suitable template.

          ($fh, $file) = tmpnam();

     If possible, this form should be used to prevent possible race
     conditions.

     See `tmpdir', see File/Spec, for information on the
     choice of temporary directory for a particular operating system.

tmpfile
     In scalar context, returns the filehandle of a temporary file.

          $fh = tmpfile();

     The file is removed when the filehandle is closed or when the program
     exits. No access to the filename is provided.

     If the temporary file can not be created undef is returned.
     Currently this command will probably not work when the temporary
     directory is on an NFS file system.

ADDITIONAL FUNCTIONS
====================

   These functions are provided for backwards compatibility with common
tempfile generation C library functions.

   They are not exported and must be addressed using the full package name.

tempnam
     Return the name of a temporary file in the specified directory using
     a prefix. The file is guaranteed not to exist at the time the
     function was called, but such guarantees are good for one clock tick
     only.  Always use the proper form of sysopen with `O_CREAT | O_EXCL'
     if you must open such a filename.

          $filename = File::Temp::tempnam( $dir, $prefix );

     Equivalent to running mktemp() with $dir/$prefixXXXXXXXX (using unix
     file convention as an example)

     Because this function uses mktemp(), it can suffer from race
     conditions.

UTILITY FUNCTIONS
=================

   Useful functions for dealing with the filehandle and filename.

unlink0
     Given an open filehandle and the associated filename, make a safe
     unlink. This is achieved by first checking that the filename and
     filehandle initially point to the same file and that the number of
     links to the file is 1 (all fields returned by stat() are compared).
     Then the filename is unlinked and the filehandle checked once again to
     verify that the number of links on that file is now 0.  This is the
     closest you can come to making sure that the filename unlinked was the
     same as the file whose descriptor you hold.

          unlink0($fh, $path) or die "Error unlinking file $path safely";

     Returns false on error. The filehandle is not closed since on some
     occasions this is not required.

     On some platforms, for example Windows NT, it is not possible to
     unlink an open file (the file must be closed first). On those
     platforms, the actual unlinking is deferred until the program ends and
     good status is returned. A check is still performed to make sure that
     the filehandle and filename are pointing to the same thing (but not at
     the time the end block is executed since the deferred removal may not
     have access to the filehandle).

     Additionally, on Windows NT not all the fields returned by stat() can
     be compared. For example, the dev and `rdev' fields seem to be
     different.  Also, it seems that the size of the file returned by
     stat() does not always agree, with `stat(FH)' being more accurate than
     `stat(filename)', presumably because of caching issues even when
     using autoflush (this is usually overcome by waiting a while after
     writing to the tempfile before attempting to unlink0 it).

     Finally, on NFS file systems the link count of the file handle does
     not always go to zero immediately after unlinking. Currently, this
     command is expected to fail on NFS disks.

PACKAGE VARIABLES
=================

   These functions control the global state of the package.

safe_level
     Controls the lengths to which the module will go to check the safety
     of the temporary file or directory before proceeding.  Options are:

    STANDARD
          Do the basic security measures to ensure the directory exists and
          is writable, that the umask() is fixed before opening of the
          file, that temporary files are opened only if they do not
          already exist, and that possible race conditions are avoided.
          Finally the `unlink0|"unlink0"' in this node function is used to
          remove files safely.

    MEDIUM
          In addition to the STANDARD security, the output directory is
          checked to make sure that it is owned either by root or the user
          running the program. If the directory is writable by group or by
          other, it is then checked to make sure that the sticky bit is
          set.

          Will not work on platforms that do not support the -k test for
          sticky bit.

    HIGH
          In addition to the MEDIUM security checks, also check for the
          possibility of "chown() giveaway" using the `POSIX|POSIX' in
          this node sysconf() function. If this is a possibility, each
          directory in the path is checked in turn for safeness,
          recursively walking back to the root directory.

          For platforms that do not support the `POSIX|POSIX' in this node
          `_PC_CHOWN_RESTRICTED' symbol (for example, Windows NT) it is
          assumed that "chown() giveaway" is possible and the recursive
          test is performed.

     The level can be changed as follows:

          File::Temp->safe_level( File::Temp::HIGH );

     The level constants are not exported by the module.

     Currently, you must be running at least perl v5.6.0 in order to run
     with MEDIUM or HIGH security. This is simply because the safety tests
     use functions from `Fcntl|Fcntl' in this node that are not available
     in older versions of perl. The problem is that the version number for
     Fcntl is the same in perl 5.6.0 and in 5.005_03 even though they are
     different versions.

     On systems that do not support the HIGH or MEDIUM safety levels (for
     example Win NT or OS/2) any attempt to change the level will be
     ignored. The decision to ignore rather than raise an exception allows
     portable programs to be written with high security in mind for the
     systems that can support this without those programs failing on
     systems where the extra tests are irrelevant.

     If you really need to see whether the change has been accepted simply
     examine the return value of safe_level.

          $newlevel = File::Temp->safe_level( File::Temp::HIGH );
          die "Could not change to high security"
              if $newlevel != File::Temp::HIGH;

TopSystemUID
     This is the highest UID on the current system that refers to a root
     UID. This is used to make sure that the temporary directory is owned
     by a system UID (root, bin, sys etc) rather than simply by root.

     This is required since on many unix systems `/tmp' is not owned by
     root.

     Default is to assume that any UID less than or equal to 10 is a root
     UID.

          File::Temp->top_system_uid(10);
          my $topid = File::Temp->top_system_uid;

     This value can be adjusted to reduce security checking if required.
     The value is only relevant when safe_level is set to MEDIUM or higher.

WARNING
=======

   For maximum security, endeavour always to avoid ever looking at,
touching, or even imputing the existence of the filename.  You do not know
that that filename is connected to the same file as the handle you have,
and attempts to check this can only trigger more race conditions.  It's
far more secure to use the filehandle alone and dispense with the filename
altogether.

   If you need to pass the handle to something that expects a filename
then, on a unix system, use `"/dev/fd/" . fileno($fh)' for arbitrary
programs, or more generally `< "+<=&" . fileno($fh) '> for Perl programs.
You will have to clear the close-on-exec bit on that file descriptor
before passing it to another process.

     use Fcntl qw/F_SETFD F_GETFD/;
     fcntl($tmpfh, F_SETFD, 0)
         or die "Can't clear close-on-exec flag on temp fh: $!\n";

Temporary files and NFS
-----------------------

   Some problems are associated with using temporary files that reside on
NFS file systems and it is recommended that a local filesystem is used
whenever possible. Some of the security tests will most probably fail when
the temp file is not local. Additionally, be aware that the performance of
I/O operations over NFS will not be as good as for a local disk.

HISTORY
=======

   Originally began life in May 1999 as an XS interface to the system
mkstemp() function. In March 2000, the OpenBSD mkstemp() code was
translated to Perl for total control of the code's security checking, to
ensure the presence of the function regardless of operating system and to
help with portability.

SEE ALSO
========

   `tmpnam', see POSIX, `tmpfile', see POSIX,
`tmpfile', see File/Spec, `tmpfile', see File/Path,

   See IO/File, and File/MkTemp, for
different implementations of temporary file handling.

AUTHOR
======

   Tim Jenness <t.jenness@jach.hawaii.edu>

   Copyright (C) 1999-2001 Tim Jenness and the UK Particle Physics and
Astronomy Research Council. All Rights Reserved.  This program is free
software; you can redistribute it and/or modify it under the same terms as
Perl itself.

   Original Perl implementation loosely based on the OpenBSD C code for
mkstemp(). Thanks to Tom Christiansen for suggesting that this module
should be written and providing ideas for code improvements and security
enhancements.

Implements symbolic and ls chmod modes
**************************************

NAME
====

   File::chmod - Implements symbolic and ls chmod modes

VERSION
=======

   This is File::chmod v0.31.

SYNOPSIS
========

     use File::chmod;

     # chmod takes all three types
     # these all do the same thing
     chmod(0666,@files);
     chmod("=rw",@files);
     chmod("-rw-rw-rw-",@files);

     # or

     use File::chmod qw( symchmod lschmod );

     chmod(0666,@files);		# this is the normal chmod
     symchmod("=rw",@files);	# takes symbolic modes only
     lschmod("-rw-rw-rw-",@files);	# takes "ls" modes only

     # more functions, read on to understand

DESCRIPTION
===========

   File::chmod is a utility that allows you to bypass system calls or bit
processing of a file's permissions.  It overloads the chmod() function
with its own that gets an octal mode, a symbolic mode (see below), or an
"ls" mode (see below).  If you wish not to overload chmod(), you can
export symchmod() and lschmod(), which take, respectively, a symbolic mode
and an "ls" mode.

   Symbolic modes are thoroughly described in your chmod(1) man page, but
here are a few examples.

     # NEW: if $UMASK is true, symchmod() applies a bit-mask found in $MASK

     chmod("+x","file1","file2");	# overloaded chmod(), that is...
     # turns on the execute bit for all users on those two files

     chmod("o=,g-w","file1","file2");
     # removes 'other' permissions, and the write bit for 'group'

     chmod("=u","file1","file2");
     # sets all bits to those in 'user'

   "ls" modes are the type produced on the left-hand side of an `ls -l' on
a directory.  Examples are:

     chmod("-rwxr-xr-x","file1","file2");
     # the 0755 setting; user has read-write-execute, group and others
     # have read-execute priveleges

     chmod("-rwsrws---","file1","file2");
     # sets read-write-execute for user and group, none for others
     # also sets set-uid and set-gid bits

   The regular chmod() and lschmod() are absolute; that is, they are not
appending to or subtracting from the current file mode.  They set it,
regardless of what it had been before.  symchmod() is useful for allowing
the modifying of a file's permissions without having to run a system call
or determining the file's permissions, and then combining that with
whatever bits are appropriate.  It also operates separately on each file.

   An added feature to version 0.30 is the $UMASK variable, explained
below; if symchmod() is called and this variable is true, then the
function uses the (also new) $MASK variable (which defaults to umask()) as
a mask against the new mode.  This is documented below more clearly.

Functions
---------

   Exported by default:

chmod(MODE,FILES)
     Takes an octal, symbolic, or "ls" mode, and then chmods each file
     appropriately.

getchmod(MODE,FILES)
     Returns a list of modified permissions, without chmodding files.
     Accepts any of the three kinds of modes.

          @newmodes = getchmod("+x","file1","file2");
          # @newmodes holds the octal permissons of the files'
          # modes, if they were to be sent through chmod("+x"...)

   Exported by request:

symchmod(MODE,FILES)
     Takes a symbolic permissions mode, and chmods each file.

lschmod(MODE,FILES)
     Takes an "ls" permissions mode, and chmods each file.

getsymchmod(MODE,FILES)
     Returns a list of modified permissions, without chmodding files.
     Accepts only symbolic permisson modes.

getlschmod(MODE,FILES)
     Returns a list of modified permissions, without chmodding files.
     Accepts only "ls" permisson modes.

getmod(FILES)
     Returns a list of the current mode of each file.

Variables
---------

$File::chmod::DEBUG
     If set to a true value, it will report warnings, similar to those
     produced by chmod() on your system.  Otherwise, the functions will
     not report errors.  Example: a file can not have file-locking and the
     set-gid bits on at the same time.  If $File::chmod::DEBUG is true,
     the function will report an error.  If not, you are not warned of the
     conflict.  It is set to 1 as default.

$File::chmod::MASK
     Contains the umask to apply to new file modes when using
     getsymchmod().  This defaults to the return value of umask() at
     compile time.  Is only applied if $UMASK is true.

$File::chmod::UMASK
     This is a boolean which tells getsymchmod() whether or not to apply
     the umask found in $MASK.  It defaults to true.

REVISIONS
=========

   *Note: this section was started with version 0.30.*

   This is an in-depth look at the changes being made from version to
version.

0.30 to 0.31
------------

*fixed getsymchmod() bug*
     Whoa.  getsymchmod() was doing some crazy ish.  That's about all I
     can say.  I did a great deal of debugging, and fixed it up.  It ALL
     had to do with two things:

          $or = (/+=/ ? 1 : 0); # should have been /[+=]/

          /u/ && $ok ? u_or() : u_not(); # should have been /u/ and $ok

*fixed getmod() bug*
     I was using map() incorrectly in getmod().  Fixed that.

*condensed lschmod()*
     I shorted it up, getting rid a variable.

0.21 to 0.30
------------

*added umask() honoring for symchmod()*
     The symchmod() function now honors the $UMASK and $MASK variables.
     $UMASK is a boolean which indicates whether or not to honor the $MASK
     variable.  $MASK holds a umask, and it defaults to umask().  $UMASK
     defaults to true.  These variables are NOT exported.  They must
     explictly set (i.e. $File::chmod::UMASK = 0).

*function name changes*
     Renamed internal function determine_mode() to mode().  However, if
     you happen to be using determine_mode() somewhere, mode() will be
     called, but you'll also get a warning about deprecation.

     Renamed internal functions {or,not}_{l,s,t} to {l,s,t}_{or,not}.
     This is to keep in standard with the OTHER 6 pairs of bitwise
     functions, such as r_or() and g_not().  I don't know WHY the others
     had 'not' or 'or' in the front.

*fixed debugging bugs*
     Certain calls to warn() were not guarded by the $DEBUG variable, and
     now they are.  Also, for some reason, I left a debugging check (that
     didn't check to see if $DEBUG was true) in getsymchmod(), line 118.
     It printed "ENTERING /g/".  It's gone now.

*fixed set-uid and set-gid bug*
     Heh, it seems that in the previous version of File::chmod, the
     following code went along broken:

          # or_s sub, File/chmod.pm, v0.21, line 330
          ($VAL & 00100) && do {
            $DEBUG && warn("execute bit must be on for set-uid"); 1;
          } && next;

     Aside from me using '&&' more than enough (changed in the new code),
     this is broken.  This is now fixed.

*fixed file lock/set-gid bug*
     The not_l() function (now renamed to l_not()) used to take the file
     mode and bit-wise NOT it with ~02000.  However, it did not check if
     the file was locked vs. set-gid.  Now, the function is `$VAL &=
     ~02000 if not $VAL & 00010;'.

*removed useless data structures*
     I do not know why I had the $S variable, or %r, %w, and %x hashes.
     In fact, $S was declared in `use vars qw( ... );', but never given a
     value, and the %r, %w, and %x hashes had a 'full' key which never got
     used.  And the hashes themselves weren't really needed anyway.  Here
     is a list of the variables no longer in use, and what they have been
     replaced with (if any):

          $S		nothing
          $U, $G, $O	$W
          %r, %w, %x	octal numbers
          @files	@_ (I had @files = @_; in nearly EVERY sub)
          $c		$_

*compacted code*
     The first version of File::chmod that was published was 0.13, and it
     was written in approximately 10 days, being given the off-and-on
     treatment I end up having to give several projects, due to more
     pressing matters.  Well, since then, most of the code has stayed the
     same, although bugs were worked out.  Well, I got rid of a lot of
     slow, clunky, and redundant sections of code in this version.
     Sections include the processing of each character of the mode in
     getsymchmod(), the getmod() subroutine, um, nearly ALL of the
     getsymchmod() function, now that I look at it.

     Here's part of the getsymchmod() rewrite:

          for ($c){
            if (/u/){
              u_or() if $MODE eq "+" or $MODE eq "=";
              u_not() if $MODE eq "-";
            }
          ...
          }

          # changed to

          /u/ && $or ? u_or() : u_and();
          # note: operating on $_, $c isn't used anymore
          # note: $or holds 1 if the $MODE was + or =, 0 if $MODE was -
          # note: previous was redundant.  didn't need $MODE eq "-" check
          #       because u_or() and u_not() both go to the next character

PORTING
=======

   This is only good on Unix-like boxes.  I would like people to help me
work on File::chmod for any OS that deserves it.  If you would like to
help, please email me (address below) with the OS and any information you
might have on how chmod() should work on it; if you don't have any
specific information, but would still like to help, hey, that's good too.
I have the following information (from `' in this node):

Win32
     Only good for changing "owner" read-write access, "group", and
     "other" bits are meaningless.  *NOTE: Win32::File and
     Win32::FileSecurity already do this.  I do not currently see a need
     to port File::chmod.*

MacOS
     Only limited meaning. Disabling/enabling write permission is mapped to
     locking/unlocking the file.

RISC OS
     Only good for changing "owner" and "other" read-write access.

AUTHOR
======

   Jeff Pinyan, japhy+perl@pobox.com, CPAN ID: PINYAN

SEE ALSO
========

     Stat::lsMode (by Mark-James Dominus, CPAN ID: MJD)
     chmod(1) manpage
     perldoc -f chmod
     perldoc -f stat

Perl module interface to the lockf system call
**********************************************

NAME
====

   File::lockf - Perl module interface to the lockf system call

SYNOPSIS
========

     use File::lockf;

DESCRIPTION
===========

   File-Lockf is an interface to the lockf system call. Perl supports the
flock system call natively, but that does not acquire network locks. Perl
also supports the fcntl system call, but that is somewhat ugly to use.
There are other locking modules available for Perl, but none of them
provided what I wanted - a simple, clean interface to the lockf system
call, without any bells or whistles getting in the way.

   File-Lockf contains four functions which map directly to the four modes
of lockf, and an OO wrapper class that encapulates the basic locking
functionality along with an additional utility method that iteratively
attempts to acquire a lock.

Lock functions
==============

   The following functions return 0 (zero) on success, and the system error
number from errno on failure. They each take an open file handle as the
first argument, and optionally a size parameter. Please see your system
lockf man page for more details about lockf functionality on your system.

$status = File::lockf::lock(FH, size = 0)
     This function maps to the F_LOCK mode of lockf.

$status = File::lockf::tlock(FH, size = 0)
     This function maps to the F_TLOCK mode of lockf.

$status = File::lockf::ulock(FH, size = 0)
     This function maps to the F_ULOCK mode of lockf.

$status = File::lockf::test(FH, size = 0)
     This function maps to the F_TEST mode of lockf.

OO wrapper
==========

   File-Lockf also provides a simple OO wrapper class around the locking
functionality, which allows you to create a lock object for a file handle
and then perform lock operations with it. All of the methods return 0
(zero) on success, and the system error number from errno on failure.

$lock = new File::lockf(\*FH)
     This function returns a new lock object bound to the given file
     handle. Note that you need to pass a reference to the file handle to
     the constructor, not the file handle itself.

$status = $lock->lock(size = 0)
     This method calls File::lockf::lock on the bound file handle.

$status = $lock->tlock(size = 0)
     This method calls File::lockf::tlock on the bound file handle.

$status = $lock->ulock(size = 0)
     This method calls File::lockf::ulock on the bound file handle.

$status = $lock->test(size = 0)
     This method calls File::lockf::test on the bound file handle.

$status = $lock->slock(count = 5, delay = 2, size = 0)
     This method will attempt to lock the bound file handle <count> times,
     sleeping <delay> seconds after each try. It will return 0 if the lock
     succeeded, or the system error number from errno if all attempts fail.

AUTHOR
======

   Paul Henson <henson@acm.org>

SEE ALSO
========

   perl(1).

by-name interface to Perl's built-in stat() functions
*****************************************************

NAME
====

   File::stat - by-name interface to Perl's built-in stat() functions

SYNOPSIS
========

     use File::stat;
     $st = stat($file) or die "No $file: $!";
     if ( ($st->mode & 0111) && $st->nlink > 1) ) {
         print "$file is executable with lotsa links\n";
     }

     use File::stat qw(:FIELDS);
     stat($file) or die "No $file: $!";
     if ( ($st_mode & 0111) && $st_nlink > 1) ) {
         print "$file is executable with lotsa links\n";
     }

DESCRIPTION
===========

   This module's default exports override the core stat() and lstat()
functions, replacing them with versions that return "File::stat" objects.
This object has methods that return the similarly named structure field
name from the stat(2) function; namely, dev, ino, mode, nlink, uid, gid,
rdev, size, atime, mtime, ctime, blksize, and blocks.

   You may also import all the structure fields directly into your
namespace as regular variables using the :FIELDS import tag.  (Note that
this still overrides your stat() and lstat() functions.)  Access these
fields as variables named with a preceding `st_' in front their method
names.  Thus, `$stat_obj->dev()' corresponds to $st_dev if you import the
fields.

   To access this functionality without the core overrides, pass the use
an empty import list, and then access function functions with their full
qualified names.  On the other hand, the built-ins are still available via
the `CORE::' pseudo-package.

NOTE
====

   While this class is currently implemented using the Class::Struct
module to build a struct-like class, you shouldn't rely upon this.

AUTHOR
======

   Tom Christiansen

keep more files open than the system permits
********************************************

NAME
====

   FileCache - keep more files open than the system permits

SYNOPSIS
========

     cacheout $path;
     print $path @data;

DESCRIPTION
===========

   The `cacheout' function will make sure that there's a filehandle open
for writing available as the pathname you give it.  It automatically
closes and re-opens files if you exceed your system file descriptor
maximum.

BUGS
====

   `sys/param.h' lies with its `NOFILE' define on some systems, so you may
have to set $FileCache::cacheout_maxopen yourself.

supply object methods for filehandles
*************************************

NAME
====

   FileHandle - supply object methods for filehandles

SYNOPSIS
========

     use FileHandle;

     $fh = new FileHandle;
     if ($fh->open("< file")) {
         print <$fh>;
         $fh->close;
     }

     $fh = new FileHandle "> FOO";
     if (defined $fh) {
         print $fh "bar\n";
         $fh->close;
     }

     $fh = new FileHandle "file", "r";
     if (defined $fh) {
         print <$fh>;
         undef $fh;       # automatically closes the file
     }

     $fh = new FileHandle "file", O_WRONLY|O_APPEND;
     if (defined $fh) {
         print $fh "corge\n";
         undef $fh;       # automatically closes the file
     }

     $pos = $fh->getpos;
     $fh->setpos($pos);

     $fh->setvbuf($buffer_var, _IOLBF, 1024);

     ($readfh, $writefh) = FileHandle::pipe;

     autoflush STDOUT 1;

DESCRIPTION
===========

   NOTE: This class is now a front-end to the IO::* classes.

   `FileHandle::new' creates a FileHandle, which is a reference to a newly
created symbol (see the Symbol package).  If it receives any parameters,
they are passed to `FileHandle::open'; if the open fails, the FileHandle
object is destroyed.  Otherwise, it is returned to the caller.

   `FileHandle::new_from_fd' creates a FileHandle like new does.  It
requires two parameters, which are passed to `FileHandle::fdopen'; if the
fdopen fails, the FileHandle object is destroyed.  Otherwise, it is
returned to the caller.

   `FileHandle::open' accepts one parameter or two.  With one parameter,
it is just a front end for the built-in open function.  With two
parameters, the first parameter is a filename that may include whitespace
or other special characters, and the second parameter is the open mode,
optionally followed by a file permission value.

   If `FileHandle::open' receives a Perl mode string (">", "+<", etc.)  or
a POSIX fopen() mode string ("w", "r+", etc.), it uses the basic Perl open
operator.

   If `FileHandle::open' is given a numeric mode, it passes that mode and
the optional permissions value to the Perl sysopen operator.  For
convenience, `FileHandle::import' tries to import the O_XXX constants from
the Fcntl module.  If dynamic loading is not available, this may fail, but
the rest of FileHandle will still work.

   `FileHandle::fdopen' is like open except that its first parameter is
not a filename but rather a file handle name, a FileHandle object, or a
file descriptor number.

   If the C functions fgetpos() and fsetpos() are available, then
`FileHandle::getpos' returns an opaque value that represents the current
position of the FileHandle, and `FileHandle::setpos' uses that value to
return to a previously visited position.

   If the C function setvbuf() is available, then `FileHandle::setvbuf'
sets the buffering policy for the FileHandle.  The calling sequence for
the Perl function is the same as its C counterpart, including the macros
`_IOFBF', `_IOLBF', and `_IONBF', except that the buffer parameter
specifies a scalar variable to use as a buffer.  WARNING: A variable used
as a buffer by `FileHandle::setvbuf' must not be modified in any way until
the FileHandle is closed or until `FileHandle::setvbuf' is called again,
or memory corruption may result!

   See Perlfunc (perl.info), for complete descriptions of
each of the following supported FileHandle methods, which are just front
ends for the corresponding built-in functions:

     close
     fileno
     getc
     gets
     eof
     clearerr
     seek
     tell

   See Perlvar (perl.info), for complete descriptions of
each of the following supported FileHandle methods:

     autoflush
     output_field_separator
     output_record_separator
     input_record_separator
     input_line_number
     format_page_number
     format_lines_per_page
     format_lines_left
     format_name
     format_top_name
     format_line_break_characters
     format_formfeed

   Furthermore, for doing normal I/O you might need these:

$fh->print
     See `print', see Perlfunc (perl.info).

$fh->printf
     See `printf', see Perlfunc (perl.info).

$fh->getline
     This works like <$fh> described in `"I', see Perlop (perl.info),
     except that it's more readable and can be safely
     called in an array context but still returns just one line.

$fh->getlines
     This works like <$fh> when called in an array context to read all the
     remaining lines in a file, except that it's more readable.  It will
     also croak() if accidentally called in a scalar context.

   There are many other functions available since FileHandle is descended
from IO::File, IO::Seekable, and IO::Handle.  Please see those respective
pages for documentation on more functions.

SEE ALSO
========

   The IO extension, see Perlfunc (perl.info), `"I', see
Perlop (perl.info).

Print to multiple filehandles with one output call
**************************************************

NAME
====

   Multi - Print to multiple filehandles with one output call

SYNOPSIS
========

     use FileHandle::Multi;
     $mult_obj=new FileHandle::Multi;
     $mult_obj->open('>-');
     $mult_obj->open('>file');
     $mult_obj->open(">$file");
     $mult_obj->open('>>file2');
     $mult_obj->print("This will be printed to several filehandles\n");
     $mult_obj->printf("This will be printed to %d filehandles\n",
         scalar @{$mult_obj->{handles}});
     $mult_obj->autoflush();
     @handle_refs = $mult_obj->members();
     $mult_obj->output_field_separator(':');
     $mult_obj->output_record_separator('\n');
     $mult_obj->format_page_number(2);
     $mult_obj->format_lines_per_page(66);
     $mult_obj->format_lines_left(10);
     $mult_obj->format_name('AN_REPORT');
     $mult_obj->format_top_name('AN_REPORT_TOP');
     $mult_obj->format_line_break_characters('\n');
     $mult_obj->format_formfeed('\l');
     $mult_obj->close();

DESCRIPTION
===========

   This module requires that the user have the FileHandle module installed
(it comes with the perl distribution).  Create objects for each of the
output filehandles you'll have - then call the print() and printf()
methods to send output to ALL the filehandles associated with an object.

EXAMPLES
========

   Look at the SYNOPSIS section.  Also, here is a simple implementation of
the unix tee(1) program (non-append mode):

     #!/local/bin/perl
     use Multi;
     $mh=new Multi;
     $mh->open('>-');
     for (@ARGV) { $mh->open(">$_"); }
     while (<STDIN>) { $mh->print($_); }

BUGS
====

   I don't think using my()s the way I am in the open() method is all that
good.  binmode isn't supported, but I don't see anybody using that anyways.
In order to use fcntl(), fileno(), or flock() you'll have to access the
filehandles yourself by calling members().  There's no write() yet (but I'm
working on it!).  Also, any limitations to the FileHandle module also apply
here.

AUTHOR
======

   Nem W Schlecht (nem@plains.nodak.edu).  Comments, bugs fixes, and
suggestions welcome.

Interface to e2fs filesystem attributes
***************************************

NAME
====

   FileSys::Ext2 - Interface to e2fs filesystem attributes

SYNOPSIS
========

     use FileSys::Ext2 qw(chattr lsattr);
     $mode = lsattr("/etc/passwd");
     chattr($mode+0003, "/etc/passwd");

DESCRIPTION
===========

`chattr($mask, @files)'
     Change the mode of `@files' to match $mask.  $mask may be a symbolic
     mode or a bitmask.

`lsattr($file)'
     In list context it returns a list containing symbols representing the
     symbolic mode of $file.  In scalar context it returns a bitmask.

`lstat($file)'
     Same as CORE::lstat, but appends the numerical attribute bitmask.

`stat($file)'
     Same as CORE::stat, but appends the numerical attribute bitmask.

`calcSymMask'
     Accepts a bitmask and returns the symbolic mode.  In list context it
     returns a symbol list like lsattr, in scalar mode it returns a string
     that matches the ------- region of lsattr (akin to that of ls -l e.g.
     drwxr-x--)

SEE ALSO
========

   chattr(1), lsattr(1)

NOTES
=====

   Of course, this would be more efficient if it were an XSUB.

   The bit mappings for attributes, from ext2_fs.h

     s #define EXT2_SECRM_FL           0x00000001 /* Secure deletion */
     u #define EXT2_UNRM_FL            0x00000002 /* Undelete */
     c #define EXT2_COMPR_FL           0x00000004 /* Compress file */
     S #define EXT2_SYNC_FL            0x00000008 /* Synchronous updates */
     i #define EXT2_IMMUTABLE_FL       0x00000010 /* Immutable file */
     a #define EXT2_APPEND_FL          0x00000020 /* writes to file may only append */
     d #define EXT2_NODUMP_FL          0x00000040 /* do not dump file */
     A #define EXT2_NOATIME_FL         0x00000080 /* do not update atime */

AUTHOR
======

   Jerrad Pierce <belg4mit@mit.edu>, <webmaster@pthbb.org>

Perl extension for obtaining file system stats.
***********************************************

NAME
====

   Filesys::Df - Perl extension for obtaining file system stats.

SYNOPSIS
========

     use Filesys::Df;
     $ref = df("/tmp", 512); #Display output in 512 byte blocks
                             #Default is 1024 byte blocks.
     print"Percent Full:               $ref->{per}\n";
     print"Superuser Blocks:           $ref->{blocks}\n";
     print"Superuser Blocks Available: $ref->{bfree}\n";
     print"User Blocks:                $ref->{user_blocks}\n";
     print"User Blocks Available:      $ref->{bavail}\n";
     print"Blocks Used:                $ref->{used}\n";

DESCRIPTION
===========

   This module will produce information on the amount disk space available
to the normal user and the superuser for any given filesystem.

   It contains one function df(), which takes a directory as the first
argument and an optional second argument which will let you specify the
block size for the output.  Note that the inode values are not changed by
the block size argument.

   The return value of df() is a refrence to a hash.  The main keys of
intrest in this hash are:

   {per} Percent used. This is based on what the non-superuser will have
used.  (In other words, if the filesystem has 10% of its space reserved for
the superuser, then the percent used can go up to 110%.)

   {blocks} Total number of blocks on the file system.

   {used} Total number of blocks used.

   {bavail} Total number of blocks available.

   {fper} Percent of inodes used. This is based on what the non-superuser
will have used.

   {files} Total inodes on the file system.

   {fused} Total number of inodes used.

   {favail} Inodes available.

   Most filesystems have a certain amount of space reserved that only the
superuser can access.

   If you wish to differentiate between the amount of space that the
normal user can access, and the amount of space the superuser can access,
you can use these keys:

   {su_blocks} or {blocks} Total number of blocks on the file system.

   {user_blocks} Total number of blocks on the filesystem for the
non-superuser.

   {su_bavail} or {bfree} Total number of blocks available to the
superuser.

   {user_bavail} or {bavail} Total number of blocks available to the
non-superuser.

   {su_files} or {files} Total inodes on the file system.

   {user_files} Total number of inodes on the filesystem for the
non-superuser.

   {su_favail} or {ffree} Inodes available in file system.

   {user_favail} or {favail} Inodes available to non-superuser.

   Most 'df' applications will print out the 'blocks' or 'user_blocks',
'bavail', 'used', and the percent full values. So you will probably end up
using these values the most.

   If the file system does not contain a diffrential in space for the
superuser then the user_ keys will contain the same values as the su_ keys.

   If there was an error df() will return undef and $! will have been set.

   Requirements: Your system must contain statvfs().  You must be running
perl.5003 or higher.

   Note: The way the percent full is measured is based on what the HP-UX
application 'bdf' returns.  The 'bdf' application seems to round a bit
different than 'df' does but I like 'bdf' so that is what I based the
percentages on.

AUTHOR
======

   Ian Guthrie IGuthrie@aol.com

   Copyright (c) 1998 Ian Guthrie. All rights reserved.
This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.

SEE ALSO
========

   statvfs(2), df(1M), bdf(1M)

   perl(1).

perform the Unix command 'df' in a portable fashion
***************************************************

NAME
====

   Filesys::DiskFree - perform the Unix command 'df' in a portable fashion

SYNOPSIS
========

     use Filesys::DiskFree;

     $handle = new Filesys::DiskFree;
     $handle->df();
     print "The root device is ".$handle->device("/")."\n";
     print "It has ".$handle->avail("/")." bytes available\n";
     print "It has ".$handle->total("/")." bytes total\n";
     print "It has ".$handle->used("/")." bytes used\n";

DESCRIPTION
===========

   Filesys::DiskFree does about what the unix command df(1) does, listing
the mounted disks, and the amount of free space used & available.

Functions
---------

Filesys::DiskFree->set('option' => 'value')
     Sets various options within the module.

     The most common option to change is the mode, which can be either
     blocks or inodes. By default, blocks is used.

     If reading a file from a 'foreign' OS using the load() function,
     format may be used, which takes the name of an OS as set in the $^O
     variable.

     Returns the previous values of the options.

Filesys::DiskFree->df()
     Perfoms a 'df' command, and stores the values for later use.

Filesys::DiskFree->command()
     Returns the appropriate command to do a 'df' command, for the current
     format.  This is used when you wish to call a df on a remote system.
     Use the df() method for local df's.

     Returns undef if there isn't an appropriate command.

Filesys::DiskFree->load($line)
     Reads in the output of a 'df', $line can be either a scalar or a
     filehandle.  If $line is a filehandle, then the filehandle is read
     until EOF.

     Returns undef on failure

Filesys::DiskFree->disks()
     Returns all the disks known about

Filesys::DiskFree->device($id)
     Returns the device for $id, which is a scalar containing the device
     name of a disk or a filename, in which case the disk that filename in
     stored upon is used. If a filename doesn't begin with '/', then it is
     treated as if is '/'.

Filesys::DiskFree->mount($id)
     Returns the mount point for $id, which is a scalar containing the
     device name of a disk or a filename, in which case the disk that
     filename in stored upon is used.

Filesys::DiskFree->avail($id)
     Returns the amount of available space in bytes for $id, which is a
     scalar containing the device name of a disk or a filename, in which
     case the disk that filename in stored upon is used.

Filesys::DiskFree->total($id)
     Returns the amount of total space in bytes for $id, which is a scalar
     containing the device name of a disk or a filename, in which case the
     disk that filename in stored upon is used.

Filesys::DiskFree->used($id)
     Returns the amount of used space in bytes for $id, which is a scalar
     containing the device name of a disk or a filename, in which case the
     disk that filename in stored upon is used.

BUGS
====

   It should support more formats, currently only Linux, Irix, Solaris &
BSD are supported. Other formats will be added as available. Please sent
your OS Name & version, the 'best' df options to use, and the output of df
with those options, and the contents of $^O if you have access to a
non-supported format.

AUTHOR
======

   Alan R. Barclay <gorilla@drink.com>

Perl df
*******

NAME
====

   Filesys::DiskSpace - Perl df

SYNOPSIS
========

     use Filesys::DiskSpace;
     ($fs_type, $fs_desc, $used, $avail, $fused, $favail) = df $dir;

DESCRIPTION
===========

   This routine displays information on a file system such as its type, the
amount of disk space occupied, the total disk space and the number of
inodes.  It tries `syscall(SYS_statfs)' and `syscall(SYS_statvfs)' in
several ways.  If all fails, it croaks.

OPTIONS
=======

$fs_type
     [number] type of the filesystem.

$fs_desc
     [string] description of this fs.

$used
     [number] size used (in Kb).

$avail
     [number] size available (in Kb).

$ffree
     [number] free inodes.

$fused
     [number] inodes used.

Installation
============

   See the INSTALL file.

COPYRIGHT
=========

   Copyright (c) 1996-1999 Fabien Tassin. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

AUTHOR
======

   Fabien Tassin <fta@oleane.net>

NOTES
=====

   This module was formerly called File::Df. It has been renamed into
Filesys::DiskSpace. It could have be Filesys::Df but unfortunatly another
module created in the meantime uses this name.

   Tested with Perl 5.003 under these systems :

     - Solaris 2.[4/5]
     - SunOS 4.1.[2/3/4]
     - HP-UX 9.05, 10.[1/20] (see below)
     - OSF1 3.2, 4.0
     - Linux 2.0.*, 2.2.*

   Note for HP-UX users :

     if you obtain this message :
     "Undefined subroutine &main::SYS_statfs called at Filesys/DiskSpace.pm
     line XXX" and if you are using a hp9000s700, then edit the syscall.ph file
     (in the Perl lib tree) and copy the line containing "SYS_statfs {196;}"
     outside the "if (defined &__hp9000s800)" block (around line 356).

Interface to e2fs filesystem attributes
***************************************

NAME
====

   Filesys::Ext2 - Interface to e2fs filesystem attributes

SYNOPSIS
========

     use Filesys::Ext2 qw(chattr lsattr);
     $mode = lsattr("/etc/passwd");
     chattr("+aud", "/etc/passwd");
     	#or equivalently
     #chattr($mode|0x0062, "/etc/passwd");

DESCRIPTION
===========

`chattr($mask, @files)'
     Change the mode of *@files* to match $mask.  $mask may be a symbolic
     mode or a bitmask.

`lsattr($file)'
     In list context it returns a list containing symbols representing the
     symbolic mode of $file.  In scalar context it returns a bitmask.

`lstat($file)'
     Same as `CORE::lstat', but appends the numerical attribute bitmask.

`stat($file)'
     Same as `CORE::stat', but appends the numerical attribute bitmask.

`calcSymMask'
     Accepts a bitmask and returns the symbolic mode.  In list context it
     returns a symbol list like lsattr, in scalar mode it returns a string
     that matches the ------- region of *lsattr(1)* (akin to that of *ls
     -l* e.g. drwxr-x--)

SEE ALSO
========

   *chattr(1)*, *lsattr(1)*

NOTES
=====

   Of course, this would be more efficient if it were an XSUB.

   The bit mappings for attributes, from ext2_fs.h

     s #define EXT2_SECRM_FL           0x00000001 /* Secure deletion */
     u #define EXT2_UNRM_FL            0x00000002 /* Undelete */
     c #define EXT2_COMPR_FL           0x00000004 /* Compress file */
     S #define EXT2_SYNC_FL            0x00000008 /* Synchronous updates */
     i #define EXT2_IMMUTABLE_FL       0x00000010 /* Immutable file */
     a #define EXT2_APPEND_FL          0x00000020 /* writes to file may only append */
     d #define EXT2_NODUMP_FL          0x00000040 /* do not dump file */
     A #define EXT2_NOATIME_FL         0x00000080 /* do not update atime */

AUTHOR
======

   Jerrad Pierce <belg4mit@mit.edu>, <webmaster@pthbb.org>

Perl extension for access Samba filesystem with libsmclient.so
**************************************************************

NAME
====

   Filesys::SmbClient - Perl extension for access Samba filesystem with
libsmclient.so

SYNOPSIS
========

     use POSIX;
     use Filesys::SmbClient;

     my $smb = new Filesys::SmbClient("alian",10);

     # Read a directory
     my $fd = $smb->opendir("smb://jupiter/doc");
     while ($smb->readdir($fd)) {print $_,"\n";}
     close($fd);

     # Read long info on a directory
     my $fd = $smb->opendir("smb://jupiter/doc");
     while (my $f = $smb->readdir_struct($fd))
       {
       if ($f->[0] == SMBC_DIR) {print "Directory ",$f->[1],"\n";}
       elsif ($f->[0] == SMBC_FILE) {print "File ",$f->[1],"\n";}
       # ...
       }
     close($fd);

     # Create a directory
     $smb->mkdir("smb://jupiter/doc/toto",'0666');

     # Read a file
     my $fd = $smb->open("smb://jupiter/doc/toto",O_RDONLY,'0666');
     while (defined(my $l= $smb->read($fd,50))) {print $l; }
     $smb->close(fd);

     # Write a file
     my $fd = $smb->open("smb://jupiter/doc/test",O_CREAT, 0666);
     $smb->write($fd,"A test of write call") || print $!,"\n";
     $smb->close(fd);

     # Rename a file
     $smb->rename("smb://jupiter/doc/toto","smb://jupiter/doc/tata"),"\n";

     # Delete a file
     $smb->unlink("smb://jupiter/doc/test");

     # Stat a file
     my @tab = $smb->stat("smb://jupiter/doc/tata");
     for (10..12) {$tab[$_] = localtime($tab[$_]);}
     print join("\n",@tab);

DESCRIPTION
===========

   Provide interface to access routine defined in libsmbclient.so.  On
2001/01/21, this library is only available with CVS source of Samba
(target head), See on samba.org web site, section download. This module is
a beta version !

   When a path is used, his scheme is :

     smb://server/share/rep/doc

VERSION
=======

   $Revision: 0.2 $

FONCTIONS
=========

new($wgroup,$debug)
     Init some things

          $wgroup : Current workgroup
          $debug : level of debug

     Return 0 on succes, errno else.

Directory
---------

mkdir($fname,$mode)
     Create directory $fname with permissions set to $mode

opendir($fname)
     Open directory $fname and return file descriptor.

readdir($fd)
     Read a directory. In a list context, return the full content of the
     directory $fd, else return next element. Each elem is a name of a
     directory or files.

     Return undef at end of directory.

readdir_struct($fd)
     Read a directory. In a list context, return the full content of the
     directory $fd, else return next element. Each element is a ref to an
     array with type and name. Type can be :

     Return undef at end of directory.

    SMBC_WORKGROUP
    SMBC_SERVER
    SMBC_FILE_SHARE
    SMBC_PRINTER_SHARE
    SMBC_COMMS_SHARE
    SMBC_IPC_SHARE
    SMBC_DIR
    SMBC_FILE
    SMBC_LINK
closedir($fd)
     Close directory $fd.

Files
-----

unlink($fname)
     Delete file $fname

     Return 0 on succes, errno else.

stat($fname)
     Stat a file to get info via file $fname. Return a array with info on
     success, else errno is return and $! is set. Tab is made with:

        * device

        * inode

        * protection

        * number of hard links

        * user ID of owner

        * group ID of owner

        * device type (if inode device)

        * total size, in bytes

        * blocksize for filesystem I/O

        * number of blocks allocated

        * time of last access

        * time of last modification

        * time of last change

rename($oname,$nname)
     Rename $oname in  $nname. Return 0 on success, else -1 is return and
     errno and $! is set.

open($fname, $flags, $mode)
     Open file $fname with flags $flags and mode $mode. Return file
     descriptor on success, else -1 is return and errno and $! is set.

read($fd,$count)
     Read $count bytes of data on file descriptor $fd. Return buffer read
     on success, undef at end of file, -1 is return on error and $! is set.

write($fd,$buf)
     Write $buf on file descriptor $fd. Return number of bytes wrote, else
     -1 is return and errno and $! is set.

close($fd)
     Close file descriptior $fd. Return 0 on success, else -1 is return and
     errno and $! is set.

AUTHOR
======

   Alain BARBET,  alian@alianwebserver.com

Perl client to reach Samba ressources
*************************************

NAME
====

   Filesys::SmbClientParser - Perl client to reach Samba ressources

SYNOPSIS
========

     use Filesys::SmbClientParser;
     my $smb = new Filesys::SmbClientParser;

     # Set parameters for connect
     $smb->User('Administrateur');
     $smb->Password('password');
     $smb->Host('jupiter');

     # List host available on this network machine
     my @l = $smb->GetHosts;
     foreach (@l) {print $_->{name},"\t",$_->{comment},"\n";}

     # List share disk available
     my @l = $smb->GetShr;
     foreach (@l) {print $_->{name},"\n";}

     # Choose a shared disk
     $smb->Share('games2');

     # List content
     my @l = $smb->dir;
     foreach (@l) {print $_->{name},"\n";}

     # Send a Winpopup message
     $smb->sendWinpopupMessage('jupiter',"Hello world !");

     # File manipulation
     $smb->cd('jdk1.1.8');
     $smb->get("COPYRIGHT");
     $smb->mkdir('tata');
     $smb->cd('tata');
     $smb->put("COPYRIGHT");
     $smb->del("COPYRIGHT");
     $smb->cd('..');
     $smb->rmdir('tata');

     # Archive method
     $smb->tar('c','/tmp/jdk.tar');
     $smb->cd('..');
     $smb->mkdir('tatz');
     $smb->cd('tatz');
     $smb->tar('x','/tmp/jdk.tar');

DESCRIPTION
===========

   SmbClientParser work with output of bin smbclient, so it doesn't work
on win platform. (but query of win platform work of course)

   A best method is work with a samba shared librarie and xs language, but
on Nov.2000 (Samba version prior to 2.0.8) there is no public interface
and shared library defined in Samba projet.

   Request has been submit and accepted on Samba-technical mailing list,
so a new module with name SmbClient will be done as soon as the public
interface has been known.

   For Samba client prior to 2.0.8, use this module !

   SmbClientParser is adapted from SMB.pm make by Remco van Mook
mook@cs.utwente.nl on smb2www project.

AUTHOR
======

   Alain BARBET alian@alianwebserver.com

SEE ALSO
========

   smbclient(1) man pages.

DESCRIPTION
===========

Objects methods
---------------

new([$path_of_smbclient])
Network methods
---------------

GetShr
     Return an array with sorted share listing

     Syntax: @output = $smb->GetShr

     array contains hashes; keys: name, type, comment

GetHosts
     Return an array with sorted host listing

     Syntax: @output = $smb->GetHosts

     array contains hashes; keys: name, comment

sendWinpopupMessage($dest,$text)
     This method allows you to send messages, using the "WinPopup"
     protocol, to another computer. If the receiving computer is running
     WinPopup the user will receive the message and probably a beep. If
     they are not running WinPopup the message will be lost, and no error
     message will occur.

     The message is also automatically truncated if the message is over
     1600 bytes, as this is the limit of the protocol.

     Parameters :

          $dest: name of host or user to send message
          $text: text to send

Operations
----------

cd [$dir]
     cd [directory name] If "directory name" is specified, the current
     working directory on the server will be changed to the directory
     specified. This operation will fail if for any reason the specified
     directory is inaccessible. Return list.

     If no directory name is specified, the current working directory on
     the server will be reported.

dir
     Return an array with sorted dir and filelisting

     Syntax: @output = $smb->dir (host,share,dir,user,pass)

     Array contains hashes; keys: name, attr, size, date

mkdir($masq)
     mkdir <mask> Create a new directory on the server (user access
     privileges permitting) with the specified name.

rmdir($masq)
     Remove the specified directory (user access privileges permitting)
     from the server.

get($file, $target, [$dir])
     Gets the file $file, using $user and $pass, to $target on courant SMB
     server and return the error code.  If $target is unspecified, courant
     directory will be used For use STDOUT, set target to '-'.

     Syntax: $error = $smb->get ($file,$target,[$dir])

mget($file,[$recurse])
     Gets file(s) $file on current SMB server,directory and return the
     error code. If multiple file, push an array ref as first parameter or
     pattern * or file separated by space

     Syntax:

          $error = $smb->mget ('file'); #or
          $error = $smb->mget (join(' ',@file); #or
          $error = $smb->mget (\@file); #or
          $error = $smb->mget ("*",1);

put$($orig,$file,[$dir])
     Puts the file $orig to $file, using $user and $pass on courant SMB
     server and return the error code.  If $orig is unspecified, STDIN is
     used (-).

     Syntax: $error = $smb->PutFile ($host,$share,$file,$user,$pass,$orig)

mput($file,[$recurse])
     Puts file(s) $file on current SMB server,directory and return the
     error code. If multiple file, push an array ref as first parameter or
     pattern * or file separated by space

     Syntax:

          $error = $smb->mput ('file'); #or
          $error = $smb->mput (join(' ',@file); #or
          $error = $smb->mput (\@file); #or
          $error = $smb->mput ("*",1);

del($mask)
     del <mask> The client will request that the server attempt to delete
     all files matching "mask" from the current working directory on the
     server

Archives methods
----------------

tar($command,$target)
     Execute TAR commande on //$host/$share/$dir, using $user and $pass,
     to $target.  and return the error code. If $target is unspecified,
     current directory will be used.

     Syntax: $error = $smb->tar ($command) where command in ('x','c',...)
     See smbclient man page

Private methods
---------------

byname
     sort an array of hashes by $_->{name} (for GetSMBDir et al)

operation(...)
command($args,$command)

Perl extension for statvfs().
*****************************

NAME
====

   Filesys::Statvfs - Perl extension for statvfs().

SYNOPSIS
========

     use Filesys::Statvfs;

     my($bsize, $frsize, $blocks, $bfree, $bavail,
     $files, $ffree, $favail, $fsid, $basetype, $flag,
     $namemax, $fstr) = statvfs("/tmp");

     ##### On HP-UX 10x systems f_time and f_size are avaliable

     ($bsize, $frsize, $blocks, $bfree, $bavail,
     $files, $ffree, $favail, $fsid, $basetype, $flag,
     $namemax, $fstr, $size, $time) = statvfs("/tmp");

DESCRIPTION
===========

   Interface for statvfs();

   The statvfs() function will return a list of values or will return
undef and set $! if there was an error.

   The values returned are described in the statvfs header or the
statvfs() man page.

   Note: On Digital Unix $fstr will be NULL.

   $size and $time are only returned on HP-UX systems.

AUTHOR
======

   Ian Guthrie IGuthrie@aol.com

   Copyright (c) 1998 Ian Guthrie. All rights reserved.
This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.

SEE ALSO
========

   statvfs(2), df(1M)

Apply filters to output filehandles
***********************************

NAME
====

   Filter::Handle - Apply filters to output filehandles

SYNOPSIS
========

     use Filter::Handle;
     my $f = Filter::Handle->new(\*STDOUT);
     $f->print(...);

     use Filter::Handle qw/subs/;
     Filter \*STDOUT;
     ...
     UnFilter \*STDOUT;

     tie *STDOUT, 'Filter::Handle', \*HANDLE;
     ...
     untie *STDOUT;

DESCRIPTION
===========

   *Filter::Handle* allows you to apply arbitrary filters to output
filehandles. You can perform any sorts of transformations on the outgoing
text: you can prepend it with some data, you can replace all instances of
one word with another, etc.

   You can even filter all of your output to one filehandle and send it to
another; for example, you can filter everything written to STDOUT and
write it instead to another filehandle. To do this, you need to explicitly
use the tie interface (see below).

Calling Interfaces
------------------

   There are three interfaces to filtering a handle:

   * Functional
          use Filter::Handle qw/subs/;

          Filter \*STDOUT;
          print "I am filtered text";
          UnFilter \*STDOUT;

          print "I am normal text";

     The functional interface works by exporting two functions into the
     caller's namespace: Filter and *UnFilter*. To start filtering a
     filehandle, call the Filter function; to stop, call *UnFilter* on
     that same filehandle.

     Any writes between the time you start and stop filtering will be
     filtered.

   * Object-Oriented
          use Filter::Handle;

          {
              my $f = Filter::Handle->new(\*STDOUT);
              $f->print("I am filtered text");
          }

          print "I am normal text";

     The object-oriented interface works differently than the other two
     interfaces (Functional and Tie); while the others use Perl's tie
     mechanism to provide the filtering, the OO interface expects you to
     explicitly call methods on your *Filter::Handle* object. This is
     really just a difference of approach; you should get the same results,
     either way. The filter is in scope as long as your *Filter::Handle*
     object is in scope. But in order to write to the filtered filehandle,
     you must explicitly use either print or printf methods.

   * Tie
          use Filter::Handle;

          local *HANDLE;
          tie *STDOUT, 'Filter::Handle', \*HANDLE;

          print "I am filtered text written to HANDLE";

          untie *STDOUT;

     The tie interface will filter your filehandle until you explicitly
     untie it. This is the only interface that allows you to filter one
     filehandle through another.  The above example will filter all writes
     to STDOUT through the output filter, then write it out on HANDLE.
     Note that this is different behavior than that of the first two
     interfaces; if you want your output written to the same handle that
     you're filtering, you could use:

          tie *STDOUT, 'Filter::Handle', \*STDOUT;

Customized Filters
------------------

   The default filter is relatively boring: it simply prepends any text
you print with the filename and line of the invoking caller. You'll
probably want to do something more interesting.

   To do so, pass an anonymous subroutine as a second argument to either
the new method, if you're using the OO interface, or to the Filter
function, if you're using the functional interface. Your subroutine will
be passed the list originally passed to print, and it should return
another list, suitable for passing to your (unfiltered) output filehandle.

   For example, say that we want to replace all instances of "blue" with
"red". We could say:

     use Filter::Handle qw/subs/;

     Filter \*STDOUT,
         sub { local $_ = "@_"; s/blue/red/g; $_ };

     print "My house is blue.\n";
     print "So is my cat, whose nose is blue.\n";

     UnFilter \*STDOUT;

     print "And the plane is also blue.\n";

   This prints:

     My house is red.
     So is my cat, whose nose is red.
     And the plane is also blue.

   As expected.

Tips, Tricks, Samples
---------------------

   * Capturing Output

     Normally, output is passed through your filtering function, then
     printed on the output filehandle that you're filtering. Suppose that,
     instead of writing the filtered output to the filehandle, you just
     want to capture that filtered output. In other words, you want to
     store the output and not have it written to the filehandle. Here's an
     example that does just that:

          my($out, $i);
          Filter \*STDOUT, sub {
              $out .= sprintf "%d: %s\n", $i++, "@_";
              ()
          };
          print "Foo";
          print "Bar";
          UnFilter \*STDOUT;

     `$out' now contains:

          0: Foo
          1: Bar

     And nothing has been written to STDOUT.

CAVEATS
=======

   Note that this won't work correctly with output from XSUBs or system
calls. This is due to a limitation of Perl's tie mechanism when tying
filehandles.

AUTHOR
======

   Benjamin Trott, ben@rhumba.pair.com

CREDITS
=======

   Thanks to tilly, chromatic, and merlyn at PerlMonks.org for
suggestions, critiques, and code samples.

Simplified source filtering
***************************

NAME
====

   Filter::Simple - Simplified source filtering

SYNOPSIS
========

     # in MyFilter.pm:

     package MyFilter;

     use Filter::Simple sub { ... };

     # in user's code:

     use MyFilter;

     # this code is filtered

     no MyFilter;

     # this code is not

DESCRIPTION
===========

The Problem
-----------

   Source filtering is an immensely powerful feature of recent versions of
Perl.  It allows one to extend the language itself (e.g. the Switch
module), to simplify the language (e.g. Language::Pythonesque), or to
completely recast the language (e.g. Lingua::Romana::Perligata).
Effectively, it allows one to use the full power of Perl as its own,
recursively applied, macro language.

   The excellent Filter::Util::Call module (by Paul Marquess) provides a
usable Perl interface to source filtering, but it is often too powerful
and not nearly as simple as it could be.

   To use the module it is necessary to do the following:

  1. Download, build, and install the Filter::Util::Call module.

  2. Set up a module that does a use Filter::Util::Call.

  3. Within that module, create an import subroutine.

  4. Within the import subroutine do a call to `filter_add', passing it
     either a subroutine reference.

  5. Within the subroutine reference, call filter_read or
     `filter_read_exact' to "prime" $_ with source code data from the
     source file that will use your module. Check the status value
     returned to see if any source code was actually read in.

  6. Process the contents of $_ to change the source code in the desired
     manner.

  7. Return the status value.

  8. If the act of unimporting your module (via a no) should cause source
     code filtering to cease, create an `unimport' subroutine, and have it
     call filter_del. Make sure that the call to filter_read or
     `filter_read_exact' in step 5 will not accidentally read past the no.
     Effectively this limits source code filters to line-by-line
     operation, unless the import subroutine does some fancy
     pre-pre-parsing of the source code it's filtering.

        For example, here is a minimal source code filter in a module named
BANG.pm. It simply converts every occurrence of the sequence `BANG\s+BANG'
to the sequence `die 'BANG' if $BANG' in any piece of code following a
`use BANG;' statement (until the next `no BANG;' statement, if any):

     package BANG;

     use Filter::Util::Call ;

     sub import {
         filter_add( sub {
             my $caller = caller;
             my ($status, $no_seen, $data);
             while ($status = filter_read()) {
                     if (/^\s*no\s+$caller\s*;\s*$/) {
                             $no_seen=1;
                             last;
                     }
                     $data .= $_;
                     $_ = "";
             }
             $_ = $data;
             s/BANG\s+BANG/die 'BANG' if \$BANG/g
                     unless $status < 0;
             $_ .= "no $class;\n" if $no_seen;
             return 1;
         })
     }

     sub unimport {
         filter_del();
     }

     1 ;

   This level of sophistication puts filtering out of the reach of many
programmers.

A Solution
----------

   The Filter::Simple module provides a simplified interface to
Filter::Util::Call; one that is sufficient for most common cases.

   Instead of the above process, with Filter::Simple the task of setting up
a source code filter is reduced to:

  1. Set up a module that does a `use Filter::Simple sub { ... }'.

  2. Within the anonymous subroutine passed to `use Filter::Simple',
     process the contents of $_ to change the source code in the desired
     manner.

        In other words, the previous example, would become:

     package BANG;

     use Filter::Simple sub {
         s/BANG\s+BANG/die 'BANG' if \$BANG/g;
     };

     1 ;

How it works
------------

   The Filter::Simple module exports into the package that uses it (e.g.
package "BANG" in the above example) two automagically constructed
subroutines - import and `unimport' - which take care of all the nasty
details.

   In addition, the generated import subroutine passes its own argument
list to the filtering subroutine, so the BANG.pm filter could easily be
made parametric:

     package BANG;

     use Filter::Simple sub {
         my ($die_msg, $var_name) = @_;
         s/BANG\s+BANG/die '$die_msg' if \${$var_name}/g;
     };

     # and in some user code:

     use BANG "BOOM", "BAM;  # "BANG BANG" becomes: die 'BOOM' if $BAM

   The specified filtering subroutine is called every time a `use BANG' is
encountered, and passed all the source code following that call, up to
either the next `no BANG;' call or the end of the source file (whichever
occurs first). Currently, any `no BANG;' call must appear by itself on a
separate line, or it is ignored.

AUTHOR
======

   Damian Conway (damian@conway.org)

COPYRIGHT
=========

     Copyright (c) 2000, Damian Conway. All Rights Reserved.
     This module is free software. It may be used, redistributed
     and/or modified under the terms of the Perl Artistic License
         (see http://www.perl.com/perl/misc/Artistic.html)

Perl Source Filter Utility Module
*********************************

NAME
====

   Filter::Util::Call - Perl Source Filter Utility Module

SYNOPSIS       use Filter::Util::Call ;
=======================================

DESCRIPTION
===========

   This module provides you with the framework to write *Source Filters*
in Perl.

   An alternate interface to Filter::Util::Call is now available. See
Filter/Simple, for more details.

   A *Perl Source Filter* is implemented as a Perl module. The structure
of the module can take one of two broadly similar formats. To distinguish
between them, the first will be referred to as *method filter* and the
second as *closure filter*.

   Here is a skeleton for the *method filter*:

     package MyFilter ;

     use Filter::Util::Call ;

     sub import
     {
         my($type, @arguments) = @_ ;
         filter_add([]) ;
     }

     sub filter
     {
         my($self) = @_ ;
         my($status) ;

         $status = filter_read() ;
         $status ;
     }

     1 ;

   and this is the equivalent skeleton for the *closure filter*:

     package MyFilter ;

     use Filter::Util::Call ;

     sub import
     {
         my($type, @arguments) = @_ ;

         filter_add(
             sub
             {
                 my($status) ;
                 $status = filter_read() ;
                 $status ;
             } )
     }

     1 ;

   To make use of either of the two filter modules above, place the line
below in a Perl source file.

     use MyFilter;

   In fact, the skeleton modules shown above are fully functional *Source
Filters*, albeit fairly useless ones. All they does is filter the source
stream without modifying it at all.

   As you can see both modules have a broadly similar structure. They both
make use of the `Filter::Util::Call' module and both have an import
method. The difference between them is that the *method filter* requires a
filter method, whereas the *closure filter* gets the equivalent of a
filter method with the anonymous sub passed to *filter_add*.

   To make proper use of the *closure filter* shown above you need to have
a good understanding of the concept of a *closure*. See Perlref (perl.info),
for more details on the mechanics of *closures*.

use Filter::Util::Call
----------------------

   The following functions are exported by `Filter::Util::Call':

     filter_add()
     filter_read()
     filter_read_exact()
     filter_del()

import()
--------

   The import method is used to create an instance of the filter. It is
called indirectly by Perl when it encounters the `use MyFilter' line in a
source file (See `import', see Perlfunc (perl.info), for more
details on import).

   It will always have at least one parameter automatically passed by Perl
- this corresponds to the name of the package. In the example above it
will be `"MyFilter"'.

   Apart from the first parameter, import can accept an optional list of
parameters. These can be used to pass parameters to the filter. For
example:

     use MyFilter qw(a b c) ;

   will result in the `@_' array having the following values:

     @_ [0] => "MyFilter"
     @_ [1] => "a"
     @_ [2] => "b"
     @_ [3] => "c"

   Before terminating, the import function must explicitly install the
filter by calling `filter_add'.

   *filter_add()*

   The function, `filter_add', actually installs the filter. It takes one
parameter which should be a reference. The kind of reference used will
dictate which of the two filter types will be used.

   If a CODE reference is used then a *closure filter* will be assumed.

   If a CODE reference is not used, a *method filter* will be assumed.  In
a *method filter*, the reference can be used to store context information.
The reference will be blessed into the package by `filter_add'.

   See the filters at the end of this documents for examples of using
context information using both *method filters* and *closure filters*.

filter() and anonymous sub
--------------------------

   Both the filter method used with a *method filter* and the anonymous
sub used with a *closure filter* is where the main processing for the
filter is done.

   The big difference between the two types of filter is that the *method
filter* uses the object passed to the method to store any context data,
whereas the *closure filter* uses the lexical variables that are
maintained by the closure.

   Note that the single parameter passed to the *method filter*, `$self',
is the same reference that was passed to `filter_add' blessed into the
filter's package. See the example filters later on for details of using
`$self'.

   Here is a list of the common features of the anonymous sub and the
`filter()' method.

$_
     Although $_ doesn't actually appear explicitly in the sample filters
     above, it is implicitly used in a number of places.

     Firstly, when either filter or the anonymous sub are called, a local
     copy of $_ will automatically be created. It will always contain the
     empty string at this point.

     Next, both filter_read and `filter_read_exact' will append any source
     data that is read to the end of $_.

     Finally, when filter or the anonymous sub are finished processing,
     they are expected to return the filtered source using $_.

     This implicit use of $_ greatly simplifies the filter.

$status
     The status value that is returned by the user's filter method or
     anonymous sub and the filter_read and `read_exact' functions take the
     same set of values, namely:

          < 0  Error
          = 0  EOF
          > 0  OK

filter_read and *filter_read_exact*
     These functions are used by the filter to obtain either a line or
     block from the next filter in the chain or the actual source file if
     there aren't any other filters.

     The function filter_read takes two forms:

          $status = filter_read() ;
          $status = filter_read($size) ;

     The first form is used to request a line, the second requests a block.

     In line mode, filter_read will append the next source line to the end
     of the $_ scalar.

     In block mode, filter_read will append a block of data which is <=
     $size to the end of the $_ scalar. It is important to emphasise the
     that filter_read will not necessarily read a block which is
     *precisely* $size bytes.

     If you need to be able to read a block which has an exact size, you
     can use the function `filter_read_exact'. It works identically to
     filter_read in block mode, except it will try to read a block which
     is exactly $size bytes in length. The only circumstances when it will
     not return a block which is $size bytes long is on EOF or error.

     It is *very* important to check the value of $status after every call
     to filter_read or `filter_read_exact'.

filter_del
     The function, filter_del, is used to disable the current filter. It
     does not affect the running of the filter. All it does is tell Perl
     not to call filter any more.

     See `Example 4: Using filter_del' in this node for details.

EXAMPLES
========

   Here are a few examples which illustrate the key concepts - as such
most of them are of little practical use.

   The examples sub-directory has copies of all these filters implemented
both as *method filters* and as *closure filters*.

Example 1: A simple filter.
---------------------------

   Below is a *method filter* which is hard-wired to replace all
occurrences of the string `"Joe"' to `"Jim"'. Not particularly Useful, but
it is the first example and I wanted to keep it simple.

     package Joe2Jim ;

     use Filter::Util::Call ;

     sub import
     {
         my($type) = @_ ;

         filter_add(bless []) ;
     }

     sub filter
     {
         my($self) = @_ ;
         my($status) ;

         s/Joe/Jim/g
             if ($status = filter_read()) > 0 ;
         $status ;
     }

     1 ;

   Here is an example of using the filter:

     use Joe2Jim ;
     print "Where is Joe?\n" ;

   And this is what the script above will print:

     Where is Jim?

Example 2: Using the context
----------------------------

   The previous example was not particularly useful. To make it more
general purpose we will make use of the context data and allow any
arbitrary from and to strings to be used. This time we will use a *closure
filter*. To reflect its enhanced role, the filter is called `Subst'.

     package Subst ;

     use Filter::Util::Call ;
     use Carp ;

     sub import
     {
         croak("usage: use Subst qw(from to)")
             unless @_ == 3 ;
         my ($self, $from, $to) = @_ ;
         filter_add(
             sub
             {
                 my ($status) ;
                 s/$from/$to/
                     if ($status = filter_read()) > 0 ;
                 $status ;
             })
     }
     1 ;

   and is used like this:

     use Subst qw(Joe Jim) ;
     print "Where is Joe?\n" ;

Example 3: Using the context within the filter
----------------------------------------------

   Here is a filter which a variation of the `Joe2Jim' filter. As well as
substituting all occurrences of `"Joe"' to `"Jim"' it keeps a count of the
number of substitutions made in the context object.

   Once EOF is detected ($status is zero) the filter will insert an extra
line into the source stream. When this extra line is executed it will
print a count of the number of substitutions actually made.  Note that
$status is set to 1 in this case.

     package Count ;

     use Filter::Util::Call ;

     sub filter
     {
         my ($self) = @_ ;
         my ($status) ;

         if (($status = filter_read()) > 0 ) {
             s/Joe/Jim/g ;
     	    ++ $$self ;
         }
     	elsif ($$self >= 0) { # EOF
             $_ = "print q[Made ${$self} substitutions\n]" ;
             $status = 1 ;
     	    $$self = -1 ;
         }

     $status ;
         }

         sub import
         {
     my ($self) = @_ ;
     my ($count) = 0 ;
     filter_add(\$count) ;
         }

         1 ;

   Here is a script which uses it:

     use Count ;
     print "Hello Joe\n" ;
     print "Where is Joe\n" ;

   Outputs:

     Hello Jim
     Where is Jim
     Made 2 substitutions

Example 4: Using filter_del
---------------------------

   Another variation on a theme. This time we will modify the `Subst'
filter to allow a starting and stopping pattern to be specified as well as
the from and to patterns. If you know the *vi* editor, it is the
equivalent of this command:

     :/start/,/stop/s/from/to/

   When used as a filter we want to invoke it like this:

     use NewSubst qw(start stop from to) ;

   Here is the module.

     package NewSubst ;

     use Filter::Util::Call ;
     use Carp ;

     sub import
     {
         my ($self, $start, $stop, $from, $to) = @_ ;
         my ($found) = 0 ;
         croak("usage: use Subst qw(start stop from to)")
             unless @_ == 5 ;

         filter_add(
             sub
             {
                 my ($status) ;

                 if (($status = filter_read()) > 0) {

                     $found = 1
                         if $found == 0 and /$start/ ;

                     if ($found) {
                         s/$from/$to/ ;
                         filter_del() if /$stop/ ;
                     }

                 }
                 $status ;
             } )

     }

     1 ;

Filter::Simple
==============

   If you intend using the Filter::Call functionality, I would strongly
recommend that you check out Damian Conway's excellent Filter::Simple
module. This module provides a much cleaner interface than
Filter::Util::Call. Although it doesn't allow the fine control that
Filter::Util::Call does, it should be adequate for the majority of
applications. It's available at

     http://www.cpan.org/modules/by-author/Damian_Conway/Filter-Simple.tar.gz
     http://www.csse.monash.edu.au/~damian/CPAN/Filter-Simple.tar.gz

AUTHOR
======

   Paul Marquess

DATE
====

   26th January 1996

exec source filter
******************

NAME
====

   Filter::Util::Exec - exec source filter

SYNOPSIS       use Filter::Util::Exec;
======================================

DESCRIPTION
===========

   This module is provides the interface to allow the creation of *Source
Filters* which use a Unix coprocess.

   See Filter/exec, Filter/cpp, and
Filter/sh, for examples of the use of this module.

AUTHOR
======

   Paul Marquess

DATE
====

   11th December 1995.

cpp source filter
*****************

NAME
====

   Filter::cpp - cpp source filter

SYNOPSIS
========

     use Filter::cpp ;

DESCRIPTION
===========

   This source filter pipes the current source file through the C
pre-processor (cpp) if it is available.

   As with all source filters its scope is limited to the current source
file only. Every file you want to be processed by the filter must have a

     use Filter::cpp ;

   near the top.

   Here is an example script which uses the filter:

     use Filter::cpp ;

     #define FRED 1
     $a = 2 + FRED ;
     print "a = $a\n" ;
     #ifdef FRED
     print "Hello FRED\n" ;
     #else
     print "Where is FRED\n" ;
     #endif

   And here is what it will output:

     a = 3
     Hello FRED

   This example below, provided by Michael G Schwern, shows a clever way
to get Perl to use a C pre-processor macro when the Filter::cpp module is
available, or to use a Perl sub when it is not.

     # use Filter::cpp if we can.
     BEGIN { eval 'use Filter::cpp' }

     sub PRINT {
         my($string) = shift;

     #define PRINT($string) \
         (print $string."\n")
     }

     PRINT("Mu");

   Look at Michael's Tie::VecArray module for a practical use.

AUTHOR
======

   Paul Marquess

DATE
====

   11th December 1995.

template for a decrypt source filter
************************************

NAME
====

   Filter::decrypt - template for a decrypt source filter

SYNOPSIS
========

     use Filter::decrypt ;

DESCRIPTION
===========

   This is a sample decrypting source filter.

   Although this is a fully functional source filter and it does implement
a *very* simple decrypt algorithm, it is not intended to be used as it is
supplied. Consider it to be a template which you can combine with a proper
decryption algorithm to develop your own decryption filter.

WARNING
=======

   It is important to note that a decryption filter can never provide
complete security against attack. At some point the parser within Perl
needs to be able to scan the original decrypted source. That means that at
some stage fragments of the source will exist in a memory buffer.

   Also, with the introduction of the Perl Compiler backend modules, and
the B::Deparse module in particular, using a Source Filter to hide source
code is becoming an increasingly futile exercise.

   The best you can hope to achieve by decrypting your Perl source using a
source filter is to make it unavailable to the casual user.

   Given that proviso, there are a number of things you can do to make
life more difficult for the prospective cracker.

  1. Strip the Perl binary to remove all symbols.

  2. Build the decrypt extension using static linking. If the extension is
     provided as a dynamic module, there is nothing to stop someone from
     linking it at run time with a modified Perl binary.

  3. Do not build Perl with `-DDEBUGGING'. If you do then your source can
     be retrieved with the `-Dp' command line option.

     The sample filter contains logic to detect the DEBUGGING option.

  4. Do not build Perl with C debugging support enabled.

  5. Do not implement the decryption filter as a sub-process (like the cpp
     source filter). It is possible to peek into the pipe that connects to
     the sub-process.

  6. Check that the Perl Compiler isn't being used.

     There is code in the BOOT: section of decrypt.xs that shows how to
     detect the presence of the Compiler. Make sure you include it in your
     module.

     Assuming you haven't taken any steps to spot when the compiler is in
     use and you have an encrypted Perl script called "myscript.pl", you
     can get access the source code inside it using the perl Compiler
     backend, like this

          perl -MO=Deparse myscript.pl

     Note that even if you have included the BOOT: test, it is still
     possible to use the Deparse module to get the source code for
     individual subroutines.

  7. Do not use the decrypt filter as-is. The algorithm used in this filter
     has been purposefully left simple.

        If you feel that the source filtering mechanism is not secure
enough you could try using the unexec/undump method. See the Perl FAQ for
further details.

AUTHOR
======

   Paul Marquess

DATE
====

   19th December 1995

exec source filter
******************

NAME
====

   Filter::exec - exec source filter

SYNOPSIS
========

     use Filter::exec qw(command parameters) ;

DESCRIPTION
===========

   This filter pipes the current source file through the program which
corresponds to the command parameter.

   As with all source filters its scope is limited to the current source
file only. Every file you want to be processed by the filter must have a

     use Filter::exec qw(command ) ;

   near the top.

   Here is an example script which uses the filter:

     use Filter::exec qw(tr XYZ PQR) ;
     $a = 1 ;
     print "XYZ a = $a\n" ;

   And here is what it will output:

     PQR = 1

WARNING
=======

   You should be *very* careful when using this filter. Because of the way
the filter is implemented it is possible to end up with deadlock.

   Be especially careful when stacking multiple instances of the filter in
a single source file.

AUTHOR
======

   Paul Marquess

DATE
====

   11th December 1995.

sh source filter
****************

NAME
====

   Filter::sh - sh source filter

SYNOPSIS
========

     use Filter::sh 'command' ;

DESCRIPTION
===========

   This filter pipes the current source file through the program which
corresponds to the command parameter using the Bourne shell.

   As with all source filters its scope is limited to the current source
file only. Every file you want to be processed by the filter must have a

     use Filter::sh 'command' ;

   near the top.

   Here is an example script which uses the filter:

     use Filter::sh 'tr XYZ PQR' ;
     $a = 1 ;
     print "XYZ a = $a\n" ;

   And here is what it will output:

     PQR = 1

WARNING
=======

   You should be *very* careful when using this filter. Because of the way
the filter is implemented it is possible to end up with deadlock.

   Be especially careful when stacking multiple instances of the filter in
a single source file.

AUTHOR
======

   Paul Marquess

DATE
====

   11th December 1995.

tee source filter
*****************

NAME
====

   Filter::tee - tee source filter

SYNOPSIS
========

     use Filter::tee 'filename' ;
     use Filter::tee '>filename' ;
     use Filter::tee '>>filename' ;

DESCRIPTION
===========

   This filter copies all text from the line after the use in the current
source file to the file specified by the parameter filename.

   By default and when the filename is prefixed with a '>' the output file
will be emptied first if it already exists.

   If the output filename is prefixed with '>>' it will be opened for
appending.

   This filter is useful as a debugging aid when developing other source
filters.

AUTHOR
======

   Paul Marquess

DATE
====

   20th June 1995.

Perl extension for *SporoPay* of Slovenska Sporitelna.
******************************************************

NAME
====

     Finance::Bank::Sporo - Perl extension for B<SporoPay> of Slovenska Sporitelna.

VERSION
=======

     0.16

SYNOPSIS
========

     use Finance::Bank::Sporo;

     $sporo_obj = Bank::Sporo->new($prenumber,$number);

     $sporo_obj->configure(
     	      amt	=> $amt,
     	      vs	=> $vs,
     	      ss	=> $ss,
     	      rurl	=> $rurl,
     	      param	=> $param,
     );

     print $sporo_obj->pay_form();

DESCRIPTION
===========

     Module for generating pay forms and links for B<SporoPay> of Slovenska
     Sporitelna (http://www.slsp.sk/).

USE
===

Functions ( or Methods ? )
--------------------------

new
          $sporo_obj  = Finance::Bank::Sporo->new($prenumber,$number);

     This creates a new Finance::Bank::Sporo object using $prenumber as a
     "Predcisle uctu" and $number as a "Cislo uctu"

configure
          $sporo_obj->configure(
                amt	=> $amt,
                vs	=> $vs,
                ss	=> $ss,
                rurl	=> $rurl,
                param	=> $param,
                        image_src => '/PICS/sporopay_logo.gif',
                  );

     Set correct values to object.  Possible parameters is:        amt =>
     Amount         vs => Variable Symbol         ss => Specific Symbol
       rurl => Redirect URL  image_src => Path to image ( relative to
     DocumentRoot )      param => any parameter

     Possible but default correct parameter is:

          action_url => SporoPayPay action URL
          default:
            https://ib.slsp.sk/epayment/epayment/epayment.xml

          image_src => Path to image ( relative to DocumentRoot )
          default:
            /PICS/sporopay_logo.gif

pay_form
          print $sporo_obj->pay_form();

          Return HTML FORM.

generic_pay_form
          print $sporo_obj->generic_pay_form($type);

          Return HTML FORM for payment with submit button.

pay_link
          print $sporo_obj->pay_link();

          Return URL for payment.

EXAMPLES
========

     Look at B<SYNOPSIS>, t/*, examples/* and use the source.
     ( lookin for a volunteer for writing documentation and man pages)

AUTHOR INFORMATION
==================

     Copyright 2000 Jan ' Kozo ' Vajda, Jan.Vajda@alert.sk. All rights
     reserved.  It may be used and modified freely, but I do request that this
     copyright notice remain attached to the file.  You may modify this module as
     you wish, but if you redistribute a modified version, please attach a note
     listing the modifications you have made.

   Address bug reports and comments to: Jan.Vajda@alert.sk

CREDITS
=======

   Thanks very much to:

my wife Erika & kozliatko
     for patience and love

SEE ALSO
========

     perl(1),Finance::Bank::TB(1).

Perl extension for *TatraPay* and *CardPay* of Tatrabanka and *EliotPay* of .eliot.
***********************************************************************************

NAME
====

   Finance::Bank::TB - Perl extension for *TatraPay* and *CardPay* of
Tatrabanka and *EliotPay* of .eliot.

VERSION
=======

     0.23

SYNOPSIS
========

     use Finance::Bank::TB;

     $tb_obj = Finance::Bank::TB->new($mid,$key);

     $tb_obj->configure(
     	      cs	=> $cs,
     	      vs	=> $vs,
     	      amt	=> $amt,
     	      rurl	=> $rurl,
     	      image_src => '/PICS/tatrapay_logo.gif',
     );

     my $send_sign = $tb_obj->get_send_sign();
     my $recv_sign = $tb_obj->get_recv_sign();
     my $new_cs = $tb_obj->cs($cs);

     or

     use Finance::Bank::TB;

     $tb_obj = Finance::Bank::TB->new($mid,$key);

     $tb_obj->configure(
     	      cs	=> $cs,
     	      vs	=> $vs,
     	      amt	=> $amt,
     	      rurl	=> $rurl,
     	      desc	=> $description,
     	      rsms	=> $mobilephonenumber,
     	      rem	=> $remote_mail,
     	      image_src => '/PICS/tatrapay_logo.gif',
     );

     print $tb_obj->pay_form();

DESCRIPTION
===========

   Module for generating signatures and pay forms for *TatraPay* and
*CardPay* of Tatra Banka ( http://www.tatrabanka.sk/ ) and for *EliotPay*
of .eliot.  ( http://www.eliot.sk/ )

   The current version of Finance::Bank::TB is available at

     http://rodney.alert.sk/perl/

USE
===

Functions ( or Methods ? )
--------------------------

new
          $tb_obj  = Finance::Bank::TB->new($mid,$key);

     This creates a new Finance::Bank::TB object using $mid as a MID (
     MerchantID ) and $key as a DES PassPhrase.

configure
          $tb_obj->configure(
          	cs        => $cs,
          	vs        => $vs,
          	amt       => $amt,
          	rurl      => $rurl,
          	image_src => '/PICS/tatrapay_logo.gif',
          );

          Set correct values to object.
          Possible parameters is:
                  cs => Constant Symbol
                  vs => Variable Symbol
                 amt => Amount
                rurl => Redirect URL
           image_src => Path to image ( relative to DocumentRoot )
                desc => Description
                rsms => Mobile Number for SMS notification
                 rem => E-mail address for email notification
                 ipc => IP address of Client
                name => Name of client
                 res => Result Code of transaction
                  ac => Approval Code

          Possible but default correct parameters is:
            tatra_action_url => TatraPay action URL
            default:
              https://moja.tatrabanka.sk/cgi-bin/ibanking/start/e-commerce.jsp

          eliot_action_url => EliotPay action URL
          default:
            https://moja.tatrabanka.sk/cgi-bin/ibanking/start/eliotpay.jsp

          action_url => default action URL
          default:
            https://moja.tatrabanka.sk/cgi-bin/ibanking/start/e-commerce.jsp

          image_src => Path to image ( relative to DocumentRoot )
          default:
            /PICS/tatrapay_logo.gif

calculate_signatures
          $tb_obj->calculate_signatures();
          print $tb_obj->send_sign;
          print $tb_obj->recv_sign;
          print $tb_obj->card_sign;

     Calculate Send, Card and Receive Signature from parameters of  object
     and set send_sign, card_sign and recv_sign.

get_send_sign
          print $tb_obj->get_send_sign();

          Calculate and return send signature.  Set $tb_obj->send_sign.

get_card_sign
          print $tb_obj->get_card_sign();

          Calculate and return CardPay signature. Set $tb_obj->card_sign.

get_recv_sign
          print $tb_obj->get_send_sign();

          Calculate and return receive signature. Set $tb_obj->recv_sign.

pay_form
          print $tb_obj->pay_form($type);

     Type is "tatra" or "eliot" or null. Default is null (action_url).
     Recomended is null.

     Return HTML FORM.

card_form
          print $tb_obj->card_form();

     Return CardPay HTML FORM.

pay_link
          print $tb_obj->pay_link($type);

     Type is "tatra" or "eliot" or null. Default is null (action_url).
     Recomended is null.

     Return URL for payment.

card_link
          print $tb_obj->card_link();

     Return CardPay URL for payment.

generic_pay_form
          print $tb_obj->generic_pay_form($type);

     Type is "tatra" or "eliot" or null. Default is null (action_url).
     Recomended is null.

     Return HTML FORM for payment with submit button.

generic_cardpay_form
          print $tb_obj->generic_cardpay_form();

     Return HTML FORM for CardPay with submit button.

EXAMPLES
========

   Look at SYNOPSIS, *t/**, *examples/** and use the source.  (lookin for
a volunteer for writing documentation and man pages)

AUTHOR INFORMATION
==================

   Copyright 2000 Jan ' Kozo ' Vajda, Jan.Vajda@alert.sk. All rights
reserved.  This library is free software; you can redistribute it and/or
modify it under the same terms as Perl itself, but I do request that this
copyright notice remain attached to the file. You may modify this module
as you wish, but if you redistribute a modified version, please attach a
note listing the modifications you have made.

   Address bug reports and comments to: Jan.Vajda@alert.sk

CREDITS
=======

   Thanks very much to:

my wife Erika & kozliatko
     for patience and love

Gildir ( gildir@alert.sk )
     for debugging

M. Sulik from TatraBanka
     for documentation, C examples and mail helpdesk.

SEE ALSO
========

     perl(1),Digest::SHA1(1),Crypt::DES(1).

Convert currencies and fetch their exchange rates (with Finance::Quote)
***********************************************************************

NAME
====

   Finance::Currency::Convert - Convert currencies and fetch their
exchange rates (with Finance::Quote)

SYNOPSIS
========

     use Finance::Currency::Convert;
     my $converter = new Finance::Currency::Convert;

     $amount_euro = $converter->convert(100, "DEM", "EUR");
     $amount_euro = $converter->convertToEuro(100, "DEM");
     $amount_dem = $converter->convertFromEuro(100, "DEM");

     $converter->updateRates("EUR", "DEM", "USD");

     $converter->setRatesFile(".rates");
     $converter->writeRatesFile();

DESCRIPTION
===========

   This module converts currencies. It has built in the fixed exchange
rates for all Euro currencies (as of November 2000). If you wish to use
other / more currencies, you can automatically fetch their exchange rates
from the internet and (optionally) store them in a file for later
reference.

   Use this module if you have large volumes of currency data to convert.
Using the exchange rates from memory makes it a lot faster than using
Finance::Quote directly and will save you the duty of storing the exchange
rates yourself.

CURRENCY SYMBOLS
----------------

   Finance::Currency::Convert uses the three character ISO currency codes
used by  Finance::Quote.  Here is a list of currency codes.

   Currencies with built-in rates (complete):

     EUR		Euro
     ATS		Austrian Schilling
     BEF		Belgiam Franc
     DEM		German Mark
     ESP		Spanish Peseta
     FIM		Finnish Mark
     FRF		French Franc
     GRD		Greek Drachma
     IEP		Irish Punt
     ITL		Italian Lira
     LUF		Luxembourg Franc
     NLG		Dutch Guilder
     PTE		Portuguese Escudo

   Other currencies (incomplete):

     AUD		Australian Dollar
     USD		US Dollar

AVAILABLE METHODS
=================

NEW
---

     my $converter = new Finance::Currency::Convert;

   The newly created conversion object will by default only know how to
convert Euro currencies. To "teach" it more currencies use updateRates.

CONVERT
-------

     $amount_euro = $converter->convert(100, "DEM", "EUR");

   This will convert 100 German Marks into the equivalent amount Euro.

CONVERTTOEURO
-------------

     $amount_euro = $converter->convertToEuro(100, "DEM");

   This will convert 100 German Marks into the equivalent amount Euro.
This function is simply shorthand for calling convert directly with "EUR"
als the second (target) currency.

CONVERTFROMEURO
---------------

     $amount_dem = $converter->convertFromEuro(100, "DEM");

   This will convert 100 Eurointo the equivalent amount German Marks.
This function is simply shorthand for calling convert directly with "EUR"
als the first (source) currency.

UPDATERATES
-----------

     $converter->updateRates("USD");
     $converter->updateRates("EUR", "DEM", "USD");

   This will fetch the exchange rates for one or more currencies using
Finance::Quote and update the exchange rates in memory.  This method will
fetach all combinations of exchange rates between the named currencies and
the ones already in memory.  This may result in a large number of requests
to Finance::Quote.  To avoid network overhead you can store the retrieved
rates with setRatesFile() / writeRatesFile() once you have retrieved them
and load them again with setRatesFile().

SETUSERAGENT
------------

     $converter->setUserAgent("MyCurrencyAgent 1.0");

   Set the user agent string to be used by Finance::Quote.

SETRATE
-------

     $converter->setRate("EUR", "USD", 999);

   Set one exchange rate. Used internally by updateRates, but may be of
use if you have to add a rate manually.

SETRATESFILE
------------

     $converter->setRatesFile(".rates");

   Name the file where exchange rates are stored. If it already exists it
will be read into memory.

READRATESFILE
-------------

     $converter->readRatesFile();

   Usually called internally by setRatesFile, but may also be called
directly to revert to the rates stored in the file.  Calling
readRatesFile() will erase all existing exchange rates in memory.

WRITERATESFILE
--------------

     $converter->writeRatesFile();

   Call this function to save table with exchange rates from memory to the
file named by setRatesFile() eg. after fetching new rates with updateRates.

AUTHOR
======

     Jan Willamowius <jan@willamowius.de>, http://www.willamowius.de

SEE ALSO
========

   Finance::Quote

   This module is only needed for fetching exchange rates.  There is no
need to install it when only Euro currencies are used.

Get current US Mortgage Rates from HSH
**************************************

NAME
====

   Finance::HSHrates - Get current US Mortgage Rates from HSH

SYNOPSIS
========

     use Finance::HSHrates;
     @rates = getrates;

DESCRIPTION
===========

   This module gets the current US Mortgage rages from HSH.  The *getrates*
function will return an array with the following elements:

     0 30 Year Fixed - Rate
     1 30 Year Fixed - Points
     2 15 Year Fixed - Rate
     3 15 Year Fixed - Points
     4 1 Year Adjustable - Rate
     5 1 Year Adjustable - Points

COPYRIGHT
=========

   Copyright 2000, Dj Padzensky

   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.

   The information that you obtain with this library may be copyrighted by
HSH Associates, Financial Publishers, and is governed by their usage
license.

AUTHOR
======

   Dj Padzensky (`djpadz@padz.net'), PadzNet, Inc.

   The Finance::HSHrates home page can be found at
http://www.padz.net/~djpadz/HSHrates/

Perl extension for parsing html bank statements from the Huntington Bank website.
*********************************************************************************

NAME
====

   Finance::Huntington::Statement - Perl extension for parsing html bank
statements from the Huntington Bank website.

SYNOPSIS
========

     use Finance::Huntington::Statement;
     $obj = new Finance::Huntington::Statement;
     $obj->parse_file (<open file handle | path to file>);

     print $obj->{account_name};
     print $obj->{account_number};
     print $obj->{last_updated}; (a time value)
     print $obj->{current_statement_balance};
     print $obj->{available_statement_balance};
     print $obj->{current_register_balance};
     @atms = %{$obj->{atms}};
     foreach (@atms) {
             print $_->{number};
             print $_->{date};
             print $_->{payee};
             print $_->{category};
             print $_->{amount};
     }
     # The following arrays may be accessed in the same way as 'atms':
     # checks
     # debit_cards
     # epays
     # mdcs
     @deposits = %{$obj->{deposits}};
     foreach (@deposits) {
             print $_->{number};
             print $_->{date};
             print $_->{payor}; # NOTE: only diff from others
             print $_->{category};
             print $_->{amount};
     }

DESCRIPTION
===========

   This version of Statement will parse Huntington online bank statements
as of 09/2000.  If the statement format changes, this gets broken.  Look
for later versions of this module for updates to correspond with current
statements.

   After parsing supplied html statement, $obj will hold a data structure
representing the information extracted from the page.

EXPORT
------

   None by default.

AUTHOR
======

   Chad Lavy, chad@chadlavy.com

SEE ALSO
========

   perl(1).

Look up a stock symbol from MoneyNet
************************************

NAME
====

   Finance::MoneyNetSymbolLookup - Look up a stock symbol from MoneyNet

SYNOPSIS
========

     use Finance::MoneyNetSymbolLookup;
     @symbols = symbollookup $searchstring; # Look up stock symbols

DESCRIPTION
===========

   This module looks up stock symbols from MoneyNet.  The *symbollookup*
function will return an array of lists, each containing the following
items:

     0 Symbol
     1 Company name
     2 Security type (typically B<STOCK> or B<MUTUAL FUND>)

EXAMPLE
=======

     use Finance::MoneyNetSymbolLookup;
     @foo = symbollookup("apple");
     foreach (@foo) {
       print "Symbol: ${$_}[0]; Company: ${$_}[1]; Type: ${$_}[2]\n";
     }

COPYRIGHT
=========

   Copyright 1998, Dj Padzensky

   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.

   The information that you obtain with this library may be copyrighted by
Reuters, Inc., and is governed by their usage license.  See
http://www.moneynet.com/home/MONEYNET/info/moneynetcopyright.asp for more
information.

AUTHOR
======

   Dj Padzensky (`djpadz@padz.net'), PadzNet, Inc.

   The Finance::MoneyNetSymbolLookup home page can be found at
http://www.padz.net/~djpadz/MoneyNetSymbolLookup/

Option analysis based on different option pricing models.
*********************************************************

NAME
====

   `Finance::Options::Calc' - Option analysis based on different option
pricing models.

SYNOPSIS
========

     use Finance::Options::Calc;

     print b_s_call(90, 80, 20, 30, 4.5);
     print b_s_put (90, 80, 20, 30, 4.5);
     print call_delta(90, 80, 20, 30, 4.5);
     print put_delta(90, 80, 20, 30, 4.5);
     print call_theta(90, 80, 20, 30, 4.5);
     print put_theta(90, 80, 20, 30, 4.5);
     print gamma(90, 80, 20, 30, 4.5);
     print vega(90, 80, 20, 30, 4.5);
     print call_rho(90, 80, 20, 30, 4.5);
     print put_rho(90, 80, 20, 30, 4.5);

DESCRIPTION
===========

   b_s_call() subroutines returns theorical value of the call option based
on Black_Scholes model. The arguments are current stock price, strike
price, time to expiration (calender days, note this module does NOT use
business days), volatility(%), annual interest rate(%) in order.

   b_s_put() subroutines returns theorical value of the put option based on
Black_Scholes model. The arguments are current stock price, strike price,
time to expiration (calender days, note this module does NOT use business
days), volatility(%), annual interest rate(%) in order.

   call_delta() returns call delta.

   put_delta() returns put delta.

   Other methods are similar.

TODO
====

   more calculation models will be included.

AUTHOR
======

   Chicheng Zhang

   chichengzhang@hotmail.com

Get stock and mutual fund quotes from various exchanges
*******************************************************

NAME
====

   Finance::Quote - Get stock and mutual fund quotes from various exchanges

SYNOPSIS
========

     use Finance::Quote;
     $q = Finance::Quote->new;

     $q->timeout(60);

     $conversion_rate = $q->currency("AUD","USD");
     $q->set_currency("EUR");  # Return all info in Euros.

     $q->require_labels(qw/price date high low volume/);

     $q->failover(1);	# Set failover support (on by default).

     %quotes  = $q->fetch("nasdaq",@stocks);
     $hashref = $q->fetch("nyse",@stocks);

DESCRIPTION
===========

   This module gets stock quotes from various internet sources, including
Yahoo! Finance, Fidelity Investments, and the Australian Stock Exchange.
There are two methods of using this module - a functional interface that
is depreciated, and an object-orientated method that provides greater
flexibility and stability.

   With the exception of straight currency exchange rates, all information
is returned as a two-dimensional hash (or a reference to such a hash, if
called in a scalar context).  For example:

     %info = $q->fetch("australia","CML");
     print "The price of CML is ".$info{"CML","price"};

   The first part of the hash (eg, "CML") is referred to as the stock.
The second part (in this case, "price") is referred to as the label.

LABELS
------

   When information about a stock is returned, the following standard
labels may be used.  Some custom-written modules may use labels not
mentioned here.  If you wish to be certain that you obtain a certain set
of labels for a given stock, you can specify that using require_labels().

     name         Company or Mutual Fund Name
     last         Last Price
     high	 Highest trade today
     low		 Lowest trade today
     date         Last Trade Date  (MM/DD/YY format)
     time         Last Trade Time
     net          Net Change
     p_change     Percent Change from previous day's close
     volume       Volume
     avg_vol      Average Daily Vol
     bid          Bid
     ask          Ask
     close        Previous Close
     open         Today's Open
     day_range    Day's Range
     year_range   52-Week Range
     eps          Earnings per Share
     pe           P/E Ratio
     div_date     Dividend Pay Date
     div          Dividend per Share
     div_yield    Dividend Yield
     cap          Market Capitalization
     ex_div	 Ex-Dividend Date.
     nav          Net Asset Value
     yield        Yield (usually 30 day avg)
     exchange	 The exchange the information was obtained from.
     success	 Did the stock successfully return information? (true/false)
     errormsg	 If success is false, this field may contain the reason why.
     method	 The module (as could be passed to fetch) which found
     		 this information.

   If all stock lookups fail (possibly because of a failed connection) then
the empty list may be returned, or undef in a scalar context.

AVAILABLE METHODS
=================

NEW
---

     my $q = Finance::Quote->new;
     my $q = Finance::Quote->new("ASX");
     my $q = Finance::Quote->new("-defaults", "CustomModule");

   With no arguents, this creates a new Finance::Quote object with the
default methods.  If the environment variable FQ_LOAD_QUOTELETS is set,
then the contents of FQ_LOAD_QUOTELETS (split on whitespace) will be used
as the argument list.  This allows users to load their own custom modules
without having to change existing code.  If you do not want users to be
able to load their own modules at run-time, pass an explicit argumetn to
->new() (usually "-defaults").

   When new() is passed one or more arguments, an object is created with
only the specified modules loaded.  If the first argument is "-defaults",
then the default modules will be loaded first, followed by any other
specified modules.

   Note that the FQ_LOAD_QUOTELETS environment variable must begin with
"-defaults" if you wish the default modules to be loaded.

   Any modules specified will automatically be looked for in the
Finance::Quote:: module-space.  Hence, Finance::Quote->new("ASX") will
load the module Finance::Quote::ASX.

   Please read the Finance::Quote hacker's guide for information on how to
create new modules for Finance::Quote.

FETCH
-----

     my %stocks  = $q->fetch("usa","IBM","MSFT","LNUX");
     my $hashref = $q->fetch("usa","IBM","MSFT","LNUX");

   Fetch takes an exchange as its first argument.  The second and remaining
arguments are treated as stock-names.  In the standard Finance::Quote
distribution, the following exchanges are recognised:

     australia		Australan Stock Exchange
     dwsfunds		Deutsche Bank Gruppe funds
     fidelity		Fidelity Investments
     tiaacref		TIAA-CREF
     troweprice		T. Rowe Price
     europe		European Markets
     canada		Canadian Markets
     usa			USA Markets
     nyse		New York Stock Exchange
     nasdaq		NASDAQ
     uk_unit_trusts	UK Unit Trusts
     vanguard		Vanguard Investments
     vwd			Vereinigte Wirtschaftsdienste GmbH

   When called in an array context, a hash is returned.  In a scalar
context, a reference to a hash will be returned.  The structure of this
hash is described earlier in this document.

   The fetch method automatically arranges for failover support and
currency conversion if requested.

   If you wish to fetch information from only one particular source, then
consult the documentation of that sub-module for further information.

CURRENCY
--------

     $conversion_rate = $q->currency("USD","AUD");

   The currency method takes two arguments, and returns a conversion rate
that can be used to convert from the first currency into the second.  In
the example above, we've requested the factor that would convert US
dollars into Australian dollars.

   The currency method will return a false value if a given currency
conversion cannot be fetched.

   At the moment, currency rates are fetched from Yahoo!, and the
information returned is governed by Yahoo!'s terms and conditions.  See
Finance::Quote::Yahoo for more information.

SET_CURRENCY
------------

     $q->set_currency("FRF");	# Get results in French Francs.

   The set_currency method can be used to request that all information be
returned in the specified currency.  Note that this increases the chance
stock-lookup failure, as remote requests must be made to fetch both the
stock information and the currency rates.  In order to improve reliability
and speed performance, currency conversion rates are cached and are
assumed not to change for the duration of the Finance::Quote object.

   At this time, currency conversions are only looked up using Yahoo!'s
services, and hence information obtained with automatic currency
conversion is bound by Yahoo!'s terms and conditions.

FAILOVER
--------

     $q->failover(1);	# Set automatic failover support.
     $q->failover(0);	# Disable failover support.

   The failover method takes a single argument which either sets (if true)
or unsets (if false) automatic failover support.  If automatic failover
support is enabled (default) then multiple information sources will be
tried if one or more sources fail to return the requested information.
Failover support will significantly increase the time spent looking for a
non-existant stock.

   If the failover method is called with no arguments, or with an
undefined argument, it will return the current failover state (true/false).

USER_AGENT
----------

     my $ua = $q->user_agent;

   The user_agent method returns the LWP::UserAgent object that
Finance::Quote and its helpers use.  Normally this would not be useful to
an application, however it is possible to modify the user-agent directly
using this method:

     $q->user_agent->timeout(10);	# Set the timeout directly.

SCALE_FIELD
-----------

     my $pounds = $q->scale_field($item_in_pence,0.01);

   The scale_field() function is a helper that can scale complex fields
such as ranges (eg, "102.5 - 103.8") and other fields where the numbers
should be scaled but any surrounding text preserved.  It's most useful in
writing new Finance::Quote modules where you may retrieve information in a
non-ISO4217 unit (such as cents) and would like to scale it to a more
useful unit (like dollars).

ENVIRONMENT
===========

   Finance::Quote respects all environment that your installed version of
LWP::UserAgent respects.  Most importantly, it respects the http_proxy
environment variable.

BUGS
====

   There are no ways for a user to define a failover list.

   The two-dimensional hash is a somewhat unwieldly method of passing
around information when compared to references.  A future release is
planned that will allow for information to be returned in a more flexible
$hash{$stock}{$label} style format.

   There is no way to override the default behaviour to cache currency
conversion rates.

COPYRIGHT
=========

     Copyright 1998, Dj Padzensky
     Copyright 1998, 1999 Linas Vepstas
     Copyright 2000, Yannick LE NY (update for Yahoo Europe and YahooQuote)
     Copyright 2000, Paul Fenwick (updates for ASX, maintainence and release)
     Copyright 2000, Brent Neal (update for TIAA-CREF)

   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.

   Currency information fetched through this module is bound by Yahoo!'s
terms and conditons.

   Other copyrights and conditions may apply to data fetched through this
module.  Please refer to the sub-modules for further information.

AUTHORS
=======

     Dj Padzensky (C<djpadz@padz.net>), PadzNet, Inc.
     Linas Vepstas (C<linas@linas.org>)
     Yannick LE NY (C<y-le-ny@ifrance.com>)
     Paul Fenwick (C<pjf@schools.net.au>)
     Brent Neal (C<brentn@users.sourceforge.net>)
     Volker Stuerzl (C<volker.stuerzl@gmx.de>)
     Keith Refson (C<Keith.Refson#earth.ox.ac.uk>)

   The Finance::Quote home page can be found at
http://finance-quote.sourceforge.net/

   The Finance::YahooQuote home page can be found at
http://www.padz.net/~djpadz/YahooQuote/

   The GnuCash home page can be found at http://www.gnucash.org/

SEE ALSO
========

   Finance::Quote::Yahoo, Finance::Quote::ASX, Finance::Quote::Fidelity,
Finance::Quote::Tiaacref, Finance::Quote::Troweprice, LWP::UserAgent,
Finance::Quote::DWS, Finance::Quote::VWD, Finance::Quote::Trustnet

   You should have also received the Finance::Quote hacker's guide with
this package.  Please read it if you are interested in adding extra
methods to this package.  The hacker's guide can also be found on the
Finance::Quote website, http://finance-quote.sourceforge.net/

Obtain quotes from the Australian Stock Exchange.
*************************************************

NAME
====

   Finance::Quote::ASX	- Obtain quotes from the Australian Stock Exchange.

SYNOPSIS
========

     use Finance::Quote;

     $q = Finance::Quote->new;

     %stockinfo = $q->fetch("asx","BHP");	   # Only query ASX.
     %stockinfo = $q->fetch("australia","BHP"); # Failover to other sources OK.

DESCRIPTION
===========

   This module obtains information from the Australian Stock Exchange
http://www.asx.com.au/.  All Australian stocks and indicies are available.
Indexes start with the letter 'X'.  For example, the All Ordinaries is
"XAO".

   This module is loaded by default on a Finance::Quote object.  It's also
possible to load it explicity by placing "ASX" in the argument list to
Finance::Quote->new().

   This module provides both the "asx" and "australia" fetch methods.
Please use the "australia" fetch method if you wish to have failover with
other sources for Australian stocks (such as Yahoo).  Using the "asx"
method will guarantee that your information only comes from the Australian
Stock Exchange.

   Information returned by this module is governed by the Australian Stock
Exchange's terms and conditions.

LABELS RETURNED
===============

   The following labels may be returned by Finance::Quote::ASX: date, bid,
ask, open, high, low, last, close, p_change, volume, and price.

SEE ALSO
========

   Australian Stock Exchange, http://www.asx.com.au/

   Finance::Quote::Yahoo::Australia.

Obtain quotes from DWS (Deutsche Bank Gruppe).
**********************************************

NAME
====

   Finance::Quote::DWS	- Obtain quotes from DWS (Deutsche Bank Gruppe).

SYNOPSIS
========

     use Finance::Quote;

     $q = Finance::Quote->new;

     %stockinfo = $q->fetch("dwsfunds","847402");

DESCRIPTION
===========

   This module obtains information about DWS managed funds.

   Information returned by this module is governed by DWS's terms and
conditions.

LABELS RETURNED
===============

   The following labels may be returned by Finance::Quote::DWS: exchange,
name, date, price, last.

SEE ALSO
========

   DWS (Deutsche Bank Gruppe), http://www.dws.de/

Obtain information from Fidelity Investments.
*********************************************

NAME
====

   Finance::Quote::Fidelity - Obtain information from Fidelity Investments.

SYNOPSIS
========

     use Finance::Quote;

     $q = Finance::Quote->new;

     %info = Finance::Quote->fetch("fidelity","FBGRX");
     %info = Finance::Quote->fetch("fidelity_direct","FBGRX");

DESCRIPTION
===========

   This module obtains information from Fidelity Investments,
http://www.fidelity.com/.  This module is loaded by default on the
Finance::Quote object.  It is also possible to load this module explicitly
by passing "Fidelity" as one of Finance::Quote->new()'s parameters.

   The "fidelity" fetch method may make use of failover modules.  The
"fidelity_direct" method will only obtain information directly from
Fidelity.

   Information returned by this module is governed by Fidelity
Investment's terms and conditions.

LABELS RETURNED
===============

   The following labels may be returned by Finance::Quote::Fidelity:
exchange, name, number, nav, change, ask, date, yield, price.

SEE ALSO
========

   Fidelity Investments, http://www.fidelity.com/

   Finance::Quote::Yahoo::USA;

Obtain quote from TIAA-CREF.
****************************

NAME
====

   Finance::Quote::Tiaacref	- Obtain quote from TIAA-CREF.

SYNOPSIS
========

     use Finance::Quote;

     $q = Finance::Quote->new;

     %stockinfo = $q->fetch("tiaacref","TIAAreal");

DESCRIPTION
===========

   This module obtains information about TIAA-CREF managed funds.

   The following symbols can be used:

     Stock: 			CREFstok
     Money Market:		CREFmony
     Equity Index:		CREFequi
     Inf-Linked Bond:		CREFinfb
     Bond Market:		CREFbond
     Social Choice:		CREFsoci
     Global Equities:		CREFglob
     Growth:			CREFgrow
     TIAA Real Estate:		TIAAreal
     PA Stock Index:		TIAAsndx
     PA Select Stock:		TIAAsele

   This module is loaded by default on a Finance::Quote object.  It's also
possible to load it explicitly by passing "Tiaacref" in to the argument
argument list of Finance::Quote->new().

   Information returned by this module is governed by TIAA-CREF's terms
and conditions.

LABELS RETURNED
===============

   The following labels may be returned by Finance::Quote::Tiaacref:
symbol, exchange, name, date, nav, price.

SEE ALSO
========

   TIAA-CREF, http://www.tiaa-cref.org/

Obtain quotes from T. Rowe Price
********************************

NAME
====

   Finance::Quote::Troweprice	- Obtain quotes from T. Rowe Price

SYNOPSIS
========

     use Finance::Quote;

     $q = Finance::Quote->new;

     %stockinfo = $q->fetch("troweprice","PRFDX"); # Can failover to other methods
     %stockinfo = $q->fetch("troweprice_direct","PRFDX"); # Use this module only.

DESCRIPTION
===========

   This module obtains information about managed funds from T. Rowe Price.
Information about T. Rowe Price funds is available from a variety of
sources.  The information source "troweprice" can be used if you don't
care which source you obtain information from.  If you wish to be
guaranteed of fetching information from T. Rowe Price directly, then the
information source "troweprice_direct" should be used.

LABELS RETURNED
===============

   Information available from T. Rowe Price may include the following
labels:  exchange, name, nav, date, price.

SEE ALSO
========

   T. Rowe Price website - http://www.troweprice.com/

   Finance::Quote::Yahoo::USA

Obtain unit trust prices from trustnet.co.uk
********************************************

NAME
====

   Finance::Quote::Trustnet	- Obtain unit trust prices from
trustnet.co.uk

SYNOPSIS
========

     use Finance::Quote;

     $q = Finance::Quote->new;

     %stockinfo = $q->fetch("unit_trusts","trust-name"); # Can failover to other methods
     %stockinfo = $q->fetch("trustnex","trust-name"); # Use this module only.

DESCRIPTION
===========

   This module obtains information about UK unit trust prices from
www.trustnet.co.uk.  The information source "unit_trusts" can be used if
the source of prices is irrelevant, and "trustnet" if you specifically
want to use trustnet.co.uk.

UNIT TRUST NAMES
================

   Unfortunately there is no unique identifier for unit trust names.
Therefore enough of the name should be given including spaces to yield a
unique match.  Trustnet sometimes uses abbreviated names, and the string
given should match the abbreviation.

   Consult http://www.trustnet.co.uk/ut/funds/perf.asp?sort=0 to find a
match for your unit trusts.

   Example "jupiter income"

LABELS RETURNED
===============

   Information available from Trustnet may include the following labels:
exchange method source name currency bid ask yield price.  In case of a
unit trust, "price" returns the offer (ask) price.  In case of an OIEC,
the unique price is returned in "bid", "ask" and "price".

SEE ALSO
========

   Trustnet website - http://www.trustnet.co.uk/

   Finance::Quote::Yahoo::USA

Obtain quotes from vwd Vereinigte Wirtschaftsdienste GmbH.
**********************************************************

NAME
====

   Finance::Quote::vwd	- Obtain quotes from vwd Vereinigte
Wirtschaftsdienste GmbH.

SYNOPSIS
========

     use Finance::Quote;

     $q = Finance::Quote->new;

     %stockinfo = $q->fetch("vwd","847402");

DESCRIPTION
===========

   This module obtains information from vwd Vereinigte Wirtschaftsdienste
GmbH http://www.vwd.de/. Many european stocks and funds are available, but
at the moment only funds are supported.

   Information returned by this module is governed by vwd's terms and
conditions.

LABELS RETURNED
===============

   The following labels may be returned by Finance::Quote::vwd: exchange,
name, date, price, last.

SEE ALSO
========

   vwd Vereinigte Wirtschaftsdienste GmbH, http://www.vwd.de/

Fetch Australian stock quotes via Yahoo.
****************************************

NAME
====

   Finance::Quote::Yahoo::Australia - Fetch Australian stock quotes via
Yahoo.

SYNOPSIS
========

     use Finance::Quote;
     my $q = Finance::Quote->new;

     my %info = $q->fetch("yahoo_australia","BHP"); # Use this module only.
     my %info = $q->fetch("australia","BHP"); # Failover with other methods.

DESCRIPTION
===========

   This module allows information to be fetched from Yahoo abouts stocks
traded on the Australian Stock Exchange.  Information about indexes (such
as the All Ordinaries) are not available through this module, although if
information is requested from the "australia" source then these will
automatically failover to direct queries from the Australian Stock
Exchange.

   This module is loaded by default on a Finance::Quote object, although
it can be explicitly loaded by passing the argument "Yahoo::Australia" to
Finance::Quote->new().

   This module provides both the "australia" and "yahoo_australia" fetch
methods.  You should use the "australia" method if you wish to allow
failovers to other sources, and "yahoo_australia" if you only want to
obtain quotes from this module.

   Information obtained via this module is governed by Yahoo's terms and
conditions, see http://au.finance.yahoo.com/ for more details.

LABELS RETURNED
===============

   This module returns all the standard labels (where available) provided
by Yahoo, as well as the currency label.  See Finance::Quote::Yahoo::Base
for more information.

SEE ALSO
========

   Yahoo Australia, http://au.finance.yahoo.com/

   Finance::Quote::Yahoo::Base

Common functions for fetching Yahoo info.
*****************************************

NAME
====

   Finance::Quote::Yahoo::Base - Common functions for fetching Yahoo info.

SYNOPSIS
========

   Base functions for use by the Finance::Quote::Yahoo::* modules.

DESCRIPTION
===========

   This module is not called directly, rather it provides a set of base
functions which other Yahoo-related modules can use.  If you're thinking
of writing a module to fetch specific information from Yahoo, then you
might wish to look through the source code for this module.

LABELS RETURNED
===============

   Most Yahoo functions will return a standard set of labels.  These
include (where available): symbol, name, last, date, time, net, p_change,
volume, bid, ask close, open, day_range, year_range, eps, pe, div_date,
div, div_yield, cap, ex_div, avg_vol.

SEE ALSO
========

   Finance::Quote::Yahoo::Australia, Finance::Quote::Yahoo::USA,
Finance::Quote::Yahoo::Europe.

Fetch quotes from Yahoo Europe
******************************

NAME
====

   Finance::Quote::Yahoo::Europe - Fetch quotes from Yahoo Europe

SYNOPSIS
========

     use Finance::Quote;
     $q = Finance::Quote->new;

     %info = $q->fetch("europe","12150.PA"); # Failover to other methods ok.
     %info = $q->fetch("yahoo_europe","12150.PA"); # Use this module only.

DESCRIPTION
===========

   This module fetches information from Yahoo Europe.  Symbols should be
provided in the format "SYMBOL.EXCHANGE", where the exchange code is one
of the following:

     PA - Paris
     BC - Barcelona
     BE - Berlin
     BI - Bilbao
     BR - Breme
     CO - Copenhagen
     D  - Dusseldorf
     F  - Frankfurt
     H  - Hamburg
     HA - Hanover
     L  - London
     MA - Madrid
     MC - Madrid (M.C.)
     MI - Milan
     MU - Munich
     O  - Oslo
     ST - Stockholm
     SG - Stuttgart
     VA - Valence
     DE - Xetra (was FX)

   This module provides both the "europe" and "yahoo_europe" methods.  The
"europe" method should be used if failover methods are desirable.  The
"yahoo_europe" method should be used you desire to only fetch information
from Yahoo Europe.

   This module is loaded by default by Finance::Quote, but can be loaded
explicitly by specifying the parameter "Yahoo::Europe" to
Finance::Quote->new().

   Information obtained by this module may be covered by Yahoo's terms and
conditions.  See http://finance.uk.yahoo.com/ for more details.

LABELS RETURNED
===============

   This module returns all the standard labels (where available) provided
by Yahoo.  See Finance::Quote::Yahoo::Base for a list of these.  The
currency label is also returned.

SEE ALSO
========

   Yahoo Europe, http://finance.uk.yahoo.com/

Obtain information about stocks and funds in the USA and Canada.
****************************************************************

NAME
====

   Finance::Quote::Yahoo::USA - Obtain information about stocks and funds
in the USA and Canada.

SYNOPSIS
========

     use Finance::Quote;

     $q = Finance::Quote->new;

     %info = $q->fetch("usa","SGI");

DESCRIPTION
===========

   This method provides access to financial information from a number of
exhcanges in the United States and Canada.  The following methods are
available:

     canada
     usa
     yahoo
     nyse
     nasdaq
     vanguard
     fidelity

   These methods all use the same information source, and hence can be
considered somewhat interchangable.  However, the method "yahoo" should be
passed to fetch if you wish to obtain information from any source that
Yahoo tracks.

   This method is loaded by default by Finance::Quote, although it can be
explicitly loaded by passing the argument "Yahoo::USA" to
Finance::Quote->new().

   Information returned by this module may be subject to Yahoo's terms and
conditions.  See http://finance.yahoo.com/ for more information.

LABELS RETURNED
===============

   This module returns all the standard labels that Yahoo provides, as
well as the currency label.  See Finance::Quote::Yahoo::Base for more
information.

BUGS
====

   Yahoo does not make a distinction between the various exchanges in the
United States and Canada.  For example, it is possible to request a stock
using the "NYSE" method and still obtain data even if that stock does not
exist on the NYSE but exists on a different exchange.

SEE ALSO
========

   Yahoo Finance, http://finance.yahoo.com/

   Finance::Quote::Base

Perl module for fetching historical stock quotes.
*************************************************

NAME
====

   Finance::QuoteHist - Perl module for fetching historical stock quotes.

SYNOPSIS
========

     use Finance::QuoteHist;
     $q = new Finance::QuoteHist
        (
         symbols    => [qw(IBM UPS AMZN)],
         start_date => '01/01/1999',
         end_date   => 'today',
        );

     # Adjusted values
     foreach $row ($q->quote_get()) {
       ($symbol, $date, $open, $high, $low, $close, $volume) = @$row;
       ...
     }

     # Non adjusted values
     $q->adjusted(0);
     foreach $row ($q->quotes()) {
        ($symbol, $date, $open, $high, $low, $close, $volume, $adj_close) = @$row;
     }

     # Splits
     foreach $row ($q->splits()) {
        ($symbol, $date, $post, $pre) = @$row;
     }

     # Dividends
     foreach $row ($q->dividends()) {
        ($symbol, $date, $dividend) = @$row;
     }

     # Culprit
     $fetch_class = $q->quote_source('IBM');

DESCRIPTION
===========

   Finance::QuoteHist is a top level interface for fetching historical
stock quotes from the web.

   It is actually a front end to modules based on
Finance::QuoteHist::Generic, the main difference being that it has a
default lineup of web sites from which to attempt quote retrieval.

   Unless otherwise defined via the lineup attribute, this module will
select a lineup for you, the default being:

     Finance::QutoeHist::Yahoo
     Finance::QuoteHist::MotleyFool
     Finance::QuoteHist::FinancialWeb

   Once instantiated, this module behaves identically to the first module
in the lineup, sharing all of that module's methods.

   Most queries will likely be handled by the first module in the lineup.
If the site is down for some reason, or perhaps that site does not provide
quotes for defunct ticker symbols, then the other sites in the lineup will
be attempted.

   See `Finance::QuoteHist::Generic(3)' in this node for gory details on
all of the parameters and methods this module accepts. The basic interface
is noted below.

METHODS
=======

   The basic user interface consists of several methods, as seen in the
example above. Those methods are:

quotes()
     Returns a list of rows (or a reference to an array containing those
     rows, if in scalar context). Each row contains the Symbol, Date,
     Open, *High*, Low, Close, and Volume for that date. Optionally, if
     non-adjusted values were requested, their will be an extra element at
     the end of the row for the *Adjusted* closing price.

dividends()
     Returns a list of rows (or a reference to an array containing those
     rows, if in scalar context). Each row contains the Date and amount of
     the *Dividend*, in that order.

splits()
     Returns a list of rows (or a reference to an array containing those
     rows, if in scalar context). Each row contains the Date, *Post* split
     shares, and *Pre* split shares, in that order.

quote_source($ticker)
dividend_source($ticker)
split_source($ticker)
     Each of these methods displays which site-specific class actually
     retrieved the information, if any, for a particular ticker symbol.

adjusted($boolean)
     Sets whether adjusted or non-adjusted quotes are desired. Quotes are
     pre-adjusted by default.

DISCLAIMER
==========

   The data returned from these modules is in no way guaranteed, nor are
the developers responsible in any way for how this data (or lack thereof)
is used. The interface is based on URLs and page layouts that might change
at any time. Even though these modules are designed to be adaptive under
these circumstances, they will at some point probably be unable to
retrieve data unless fixed or provided with new parameters. Furthermore,
the data from these web sites is usually not even guaranteed by the web
sites themselves, and oftentimes is acquired elsewhere. See the
documentation for each site-specific module for more information regarding
the disclaimer for that site.

AUTHOR
======

   Matthew P. Sisk, <`sisk@mojotoad.com'>

COPYRIGHT
=========

   Copyright (c) 2000 Matthew P. Sisk. All rights reserved. All wrongs
revenged. This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

SEE ALSO
========

   Finance::QuoteHist::Generic(3), Finance::QuoteHist::Yahoo(3),
Finance::QuoteHist::MotleyFool(3), Finance::QuoteHist::FinancialWeb(3),
perl(1).

Site-specific class for retrieving historical stock quotes.
***********************************************************

NAME
====

   Finance::QuoteHist::FinancialWeb - Site-specific class for retrieving
historical stock quotes.

SYNOPSIS
========

     use Finance::QuoteHist::FinancialWeb;
     $q = new Finance::QuoteHist::FinancialWeb
        (
         symbols    => [qw(IBM UPS AMZN)],
         start_date => '01/01/1999',
         end_date   => 'today',
        );

     foreach $row ($q->quotes()) {
       ($symbol, $date, $open, $high, $low, $close, $volume) = @$row;
       ...
     }

DESCRIPTION
===========

   Finance::QuoteHist::FinancialWeb is a subclass of
Finance::QuoteHist::Generic, specifically tailored to read historical
quotes from the FinancialWeb web site (*http://www.financialweb.com*).
FinancialWeb does not offer information regarding dividends or splits.

   For quote queries, at the time of this writing, the Financial web site
utilizes only start dates, and returns a years worth of data if available.
The quote_urls() method provides all the URLs necessary given the date
range. These are automatically utilized by the native methods of
Finance::QuoteHist::Generic.

   Please see `Finance::QuoteHist::Generic(3)' in this node for more
details on usage and available methods. If you just want to get historical
quotes and are not interested in the details of how it is done, check out
`Finance::QuoteHist(3)' in this node.

METHODS
=======

   The basic user interface consists of a single method, as shown in the
example above. That method is:

quotes()
     Returns a list of rows (or a reference to an array containing those
     rows, if in scalar context). Each row contains the Symbol, Date,
     Open, *High*, Low, Close, and Volume for that date. Quote values are
     pre-adjusted for this site.

REQUIRES
========

   Finance::QuoteHist::Generic

DISCLAIMER
==========

   The data returned from these modules is in no way guaranteed, nor are
the developers responsible in any way for how this data (or lack thereof)
is used. The interface is based on URLs and page layouts that might change
at any time. Even though these modules are designed to be adaptive under
these circumstances, they will at some point probably be unable to
retrieve data unless fixed or provided with new parameters. Furthermore,
the data from these web sites is usually not even guaranteed by the web
sites themselves, and oftentimes is acquired elsewhere.

   In the case of FinancialWeb, as of September 13, 2000, their statment
reads, in part:

     This data may be used for PERSONAL USE ONLY. Any
     redistribution of this data, including publishing it
     in whole or in part, or publishing any calculations
     derived from it, on the internet I<(sic)> or in any
     other public forum, is illegal.

   There you have it. If you feel like you might have concerns with this
then first double check the statement on their web site:

     http://www.financialweb.com/

   If you still have concerns, then use another site-specific historical
quote instance, or none at all.

   Above all, play nice.

AUTHOR
======

   Matthew P. Sisk, <`sisk@mojotoad.com'>

COPYRIGHT
=========

   Copyright (c) 2000 Matthew P. Sisk. All rights reserved. All wrongs
revenged. This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

SEE ALSO
========

   Finance::QuoteHist::Generic(3), Finance::QuoteHist(3), perl(1).

Base class for retrieving historical stock quotes.
**************************************************

NAME
====

   Finance::QuoteHist::Generic - Base class for retrieving historical
stock quotes.

SYNOPSIS
========

     package Finance::QuoteHist::MyFavoriteSite;
     use strict;
     use vars qw(@ISA);
     use Finance::QuoteHist::Generic;
     @ISA = qw(Finance::QuoteHist::Generic);

     sub quote_urls {
       # This method should return the set of URLs necessary to extract
       # the quotes from this particular site given the list of symbols
       # and date range provided during instantiation. See
       # Finance::QuoteHist::MotleyFool for a basic example of how to do
       # this, or Finance::QuoteHist::Yahoo for a more complicated
       # example.
     }

DESCRIPTION
===========

   This is the base class for retrieving historical stock quotes. It is
built around LWP::UserAgent, and by default it expects the returned data
to be in HTML format, in which case the quotes are gathered using
HTML::TableExtract. Support for CSV (Comma Separated Value) data is
included as well.

   In order to actually retrieve historical stock quotes, this class
should be subclassed and tailored to a particular web site.  In
particular, the quote_urls() method should be overridden, and provide
however many URLs are necessary to retrieve the data over a list of
symbols within the given date range.  Different sites have different
limitations on how many quotes are returned for each query. See
Finance::QuoteHist::MotleyFool, Finance::QuoteHist::FinancialWeb, and
Finance::QuoteHist::Yahoo for some examples of how to do this.

   For more complicated sites, such as Yahoo, more methods are available
for overriding that deal with things such as splits and dividends.

METHODS
=======

new()
     Returns a new Finance::QuoteHist::Generic object.  Valid attributes
     are:

    start_date
    end_date
          Specify the date range from which you would like historical
          quotes.  These dates get parsed by the `ParseDate()' method in
          Date::Manip, so see `Date::Manip(3)' in this node for more
          information on valid date strings.  They are quite flexible, and
          include such strings as '1 year ago'. Date boundaries can also
          be dynamically set with methods of the same name.

    symbols
          Indicates which ticker symbols to include in the search for
          historical quotes. Passed either as a string (for single ticker)
          or an array ref for multiple tickers.

    reverse
          Indicates whether each batch of rows from each URL provided in
          quote_urls() should be reversed from top to bottom.  Some sites
          present historical quotes with the newest quotes on the top.
          Since the rows from each URL are eventually catenated, if the
          overall order of your rows is important you might want to pay
          attention to this flag. If the overall order is not that
          important, then ignore this flag. Typically, site-specific sub
          classes of this module will take care of setting this
          appropriately. The default is 0.

    attempts
          Sets how persistently the module tries to retrieve the quotes.
          There are two places this will manifest. First, if there are
          what appear to be network errors, this many network connections
          are attempted for that URL. Secondly, for quotes only, if a
          document was successfully retrieved, but it contained no quotes,
          this number of attempts are made to retrieve a document with
          data. Sometimes sites will report a temporary internal error via
          HTML, and if it is truly transitory this will usually get around
          it. The default is 3.

    lineup
          Passed as an array reference (or scalar for single site), this
          list indicates which Finance::QuoteHist::Generic sub classes
          should be invoked in the event this class fails in its attempt
          to retrieve historical quotes. In the event of failure, the
          first class in this list is invoked with the same parameters as
          the original class, and the remaining classes are passed as the
          lineup to the new class. This sets up a daisy chain of
          redundancy in the event a particular site is hosed. See
          `Finance::QuoteHist(3)' in this node to see an example of how
          this is done in a top level invocation of these modules. This
          list is empty by default.

    quote_precision
          Sets the number of decimal places to which quote values are
          rounded. This might be of particular significance if there is
          auto-adjustment taking place (which is only under particular
          circumstances currently...see Finance/QuoteHist/Yahoo).
          Setting this to 0 will disable the
          rounding behavior, returning the quote values as they appear on
          the sites (assuming no auto-adjustment has taken place). The
          default is 4.

    verbose
          When set, many status messages are printed to STDERR indicating
          progression through URLs and lineup invocations.

    quiet
          When set, certain failure messages are suppressed from appearing
          on STDERR. These messages would normally appear regardless the
          setting of the verbose flag.

   The following methods are the primary user interface methods; methods
of interest to developers wishing to make their own site-specific instance
of this module will find information on overriding methods further below.

quotes()
     Retrieves historical quotes for all provided symbols over the
     specified date range. Depending on context, returns either a list of
     rows or an array reference to the same list of rows.

dividends()
splits()
     If available, retrieves dividend or split information for all provided
     symbols over the specified date range. If there are no site-specific
     subclassed modules in the lineup capable of getting dividends or
     splits, the user will be notified on STDERR unless the quiet flag was
     requested during object creation.

start_date(date_string)
end_date(date_string)
     Set the date boundaries of all queries. The date_string is
     interpreted by the Date::Manip module.

clear_cache()
     When results are gathered for a particular date range, whether they be
     via direct query or incidental extraction, they are cached. This cache
     is cleared by invoking this method directly, by resetting the boundary
     dates of the query, or by changing the `adjusted()' setting.

quote_source(ticker_symbol)
dividend_source(ticker_symbol)
split_source(ticker_symbol)
     After query, these methods can be used to find out which particular
     subclass in the lineup fulfilled the corresponding request.

   The following methods are the primary methods of interest for
developers wishing to make a site-specific subclass. For simple quote
retrievals, the quote_urls() method is typically all that is necessary.
For splits, dividends, and more complicated data parsing conditions beyond
HTML tables, the other methods could be of interest (see the
Finance::QuoteHist::Yahoo module as an example of the more complicated
behavior). If a new target type is ever defined in addition to quote,
split, and *dividend*, then corresponding methods (`TARGET_urls()',
`TARGET_get()', `TARGET_symbols()') should be provided when appropriate.

quote_urls()
     When a site supports historical stock quote queries, this method
     should return the list of URLs necessary to retrieve all historical
     quotes from a particular site for the symbols and date ranges
     provided.

dividend_urls()
     If a site supports direct dividend queries, this method should provide
     the list of URLs necessary for the symbol and date range involved.
     Currently this is only implemented by the Yahoo subclass.

split_urls()
     If a site supports direct split queries, this method should provide
     the list of URLs necessary. Currently no sites support this type of
     query (splits are gathered from the regular quote output from Yahoo).

quote_get()
dividend_get()
split_get()
     All three of these methods invoke `target_get()' with the relevant
     target information. The analogous methods, quotes(), dividends(), and
     splits(), should automatically take care of finding these based on
     the presence of the corresponding `TARGET_urls()' method. If the
     `TARGET_urls()' method is not available, then they will look for ways
     to utilize the `TARGET_extract()' method.

split_extract()
dividend_extract()
     These extraction methods are not provided by default. When present in
     a site-specific subclass, they are invoked on a per-row basis during
     direct (i.e., via URLs provided by a `TARGET_urls()' method) queries
     of other target types; it is passed an array reference representing a
     table row, and should return another array reference representing
     successfully extracted dividend/split information. When a successful
     extraction occurs, that row is filtered from the target query
     results. See the Yahoo subclass for an example of its use.
     Theoretically there could be a `quote_extract()' method as well, but
     it is redundant at this point and therefore never used.

adjusted($boolean)
     Return or set whether results should be returned as adjusted or
     non-adjusted values. *Adjusted* means that the quotes have been
     retroactively adjusted in terms of the current share price, such as
     for splits. The sites represented so far by site-specific subclassing
     all offer pre-adjusted data by default, and most offer nothing else.
     One significant exception is Yahoo, which provides non-adjusted
     quotes in HTML, but adjusted for CSV, the default mode of transmission
     for the Yahoo module. Pre-adjusted quote values can be requested from
     capable sites by providing a true value to this method. By default,
     adjusted values are always returned.

     If non-adjusted values have been requested, and a site in the lineup
     that does not provide non-adjusted values ends up fulfilling the
     request, a warning is issued to STDERR (unless quiet was specified as
     a parameter to new()). Currently, Yahoo is the only supported site
     that provides non-adjusted values, but they have to be specifically
     requested.

     There are a couple of points to note that could be significant;
     QuoteHist will automatically notice if a quote source has an "Adj"
     column - one that represents an adjusted closing value. If present,
     all other values, including volume, will be adjusted based on the
     ratio of the represented closing value and the adjusted value. This
     might actually occur with the Yahoo module if, for example, you
     request splits() before you request quotes(). The split data is only
     available in HTML mode; QuoteHist caches initial queries and will
     gather the quote information represented in the HTML. It will notice
     the adjusted close column, and automatically normalize the rest of the
     quote information. If non-adjusted data is desired, you must pass 0 to
     this method. The justification for this is that there will be a common
     expectation for quote data returned from different sites in the
     lineup, even if there are small deviations due to things such as
     Yahoo adjusting for *dividends* as well as splits, so there could be
     slight variations across sites.

ua()
     Accessor method for the LWP::UserAgent object used to process
     HTTP::Request for individual URLs.

   Most of the methods below are utilized during a call to `target_get()'.
Average subclasses will probably have little need of them, but they are
included here just in case.

target_get($target)
     Returns an array reference to the rows that result from a particular
     TARGET query; this is where the network transaction and data
     extraction take place. It will gather the results from each URL
     provided in the corresponding TARGET_urls() method, perform the
     primary and secondary data extraction, and return the catenated
     results as a list. For example, the quote_get() method will call this
     method with 'quote' as the TARGET; during its execution, the methods
     quote_urls() and `quote_labels()' will be invoked to tailor the
     quote-specific retrieval and extraction.

fetch($mode, $url, @new_request_args)
     Returns the web page located at `$url', using request method $mode
     (i.e., GET or POST). The `@new_request_args' list gets passed as
     arguments to the HTTP::Request::new method that handles the request at
     the behest of the LWP::UserAgent accessible via the ua() method.

method
     Returns the method under which HTTP::Request objects are created for
     use by the LWP::UserAgent. By default, this returns 'GET'.

has_non_adjusted($boolean)
     Indicator method that specifies whether a particular site subclass is
     capable of providing non-adjusted quote values. This is assumed to be
     false by default; Yahoo is a significant exception.

rows($data_string)
     Given an data string, returns the extracted rows as either an array or
     array reference, depending on context. The data string is parsed based
     on the type of parser registered for the data type; currently this is
     either HTML via HTML::TableExtract, or CSV using an internal parser.
     If parsing HTML, the corresponding target labels are passed along to
     the HTML::TableExtract class. Rows falling outside of the date range
     specified for the object are discarded.

parse_method($mode, $parse_sub)
     Retrieve or set the reference or name of the parsing routine for the
     specified TARGET. Currently parse methods are registered by default
     for the 'html' and 'csv' modes.

parse_mode($mode)
     Retrieve or set the current parse mode.

html_table_parser($data_string, @column_labels)
     HTML table parser routine registered by default. `column_labels' are
     optional, and will default to the labels provided by the
     `TARGET_labels()' method, where TARGET is the current target mode.

csv_parser($data_string, @column_labels)
     CSV parser routine registered by default. `column_labels' are
     optional, but when present represent the labels that might appear in
     the beginning of the CSV data. They are reordered based on the
     default `column_labels' specified for HTML output.

date_in_range($date)
     Given a date string, test whether it is within the range specified by
     the current start_date and end_date.

dates($start_date, $end_date)
     Returns a list of business days between and including the provided
     boundary dates. If no arguments are provided, start_date and end_date
     default to the currently specified date range.

DISCLAIMER
==========

   The data returned from these modules is in no way guaranteed, nor are
the developers responsible in any way for how this data (or lack thereof)
is used. The interface is based on URLs and page layouts that might change
at any time. Even though these modules are designed to be adaptive under
these circumstances, they will at some point probably be unable to
retrieve data unless fixed or provided with new parameters. Furthermore,
the data from these web sites is usually not even guaranteed by the web
sites themselves, and oftentimes is acquired elsewhere. See the
documentation for each site-specific module for more information regarding
the disclaimer for that site.

   Above all, play nice.

AUTHOR
======

   Matthew P. Sisk, <`sisk@mojotoad.com'>

COPYRIGHT
=========

   Copyright (c) 2000 Matthew P. Sisk.  All rights reserved. All wrongs
revenged. This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

SEE ALSO
========

   Finance::QuoteHist(3), HTML::TableExtract(3), Date::Manip(3),
perlmodlib(1), perl(1).

Site-specific class for retrieving historical stock quotes.
***********************************************************

NAME
====

   Finance::QuoteHist::MotleyFool - Site-specific class for retrieving
historical stock quotes.

SYNOPSIS
========

     use Finance::QuoteHist::MotleyFool;
     $q = new Finance::QuoteHist::MotleyFool
        (
         symbols    => [qw(IBM UPS AMZN)],
         start_date => '01/01/1999',
         end_date   => 'today',
        );

     foreach $row ($q->quotes()) {
       ($symbol, $date, $open, $high, $low, $close, $volume) = @$row;
       ...
     }

DESCRIPTION
===========

   Finance::QuoteHist::MotleyFool is a subclass of
Finance::QuoteHist::Generic, specifically tailored to read historical
quotes from the Motley Fool web site (*http://www.fool.com/*). Motley Fool
does not currently supply information on dividend distributions or splits.

   For quote queries in particular, at the time of this writing, the
Motley Fool web site utilizes start and end dates, but never returns more
than a month worth of data for a particular symbol. The quote_urls()
method provides all the URLs necessary given the date range and symbols.
These are automatically utilized by the native methods of
Finance::QuoteHist::Generic.

   Please see `Finance::QuoteHist::Generic(3)' in this node for more
details on usage and available methods. If you just want to get historical
quotes and are not interested in the details of how it is done, check out
`Finance::QuoteHist(3)' in this node.

METHODS
=======

   The basic user interface consists of a single method, as shown in the
example above. That method is:

quotes()
     Returns a list of rows (or a reference to an array containing those
     rows, if in scalar context). Each row contains the Symbol, Date,
     Open, *High*, Low, Close, and Volume for that date. Quote values are
     pre-adjusted for this site.

REQUIRES
========

   Finance::QuoteHist::Generic

DISCLAIMER
==========

   The data returned from these modules is in no way guaranteed, nor are
the developers responsible in any way for how this data (or lack thereof)
is used. The interface is based on URLs and page layouts that might change
at any time. Even though these modules are designed to be adaptive under
these circumstances, they will at some point probably be unable to
retrieve data unless fixed or provided with new parameters. Furthermore,
the data from these web sites is usually not even guaranteed by the web
sites themselves, and oftentimes is acquired elsewhere.

   In the case of The Motley Fool, as of September 13, 2000, their
statement reads, in part:

     We do our best to get you timely, accurate information,
     but we reserve the right to be late, wrong, stupid, or
     even foolish. Use this data for your own information,
     not for trading. The Fool and its data or content
     providers (such as S&P Comstock, BigCharts, AFX, or
     Comtex) won't be liable for any delays or errors in the
     data, or for any losses you suffer because you relied
     upon it.

   There you have it. If you feel like you might have concerns with this
then first double check the statement on the bottom of this page:

     http://quote.fool.com/historical/historicalquotes.asp

   In addition, you might want to read their disclaimer:

     http://www.fool.com/help/disclaimer.htm

   If you still have concerns, then use another site-specific historical
quote instance, or none at all.

   Above all, play nice.

AUTHOR
======

   Matthew P. Sisk, <`sisk@mojotoad.com'>

COPYRIGHT
=========

   Copyright (c) 2000 Matthew P. Sisk. All rights reserved. All wrongs
revenged. This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

SEE ALSO
========

   Finance::QuoteHist::Generic(3), Finance::QuoteHist(3), perl(1).

Site-specific class for retrieving historical stock quotes.
***********************************************************

NAME
====

   Finance::QuoteHist::SiliconInvestor - Site-specific class for
retrieving historical stock quotes.

SYNOPSIS
========

     use Finance::QuoteHist::SiliconInvestor;
     $q = Finance::QuoteHist::SiliconInvestor->new
        (
         symbols    => [qw(IBM UPS AMZN)],
         start_date => '01/01/1999',
         end_date   => 'today',
        );

     foreach $row ($q->quotes()) {
       ($symbol, $date, $open, $high, $low, $close, $volume) = @$row;
       ...
     }

DESCRIPTION
===========

   Finance::QuoteHist::SiliconInvestor is a subclass of
Finance::QuoteHist::Generic, specifically tailored to read historical
quotes from the Silicon Investor web site
(*http://www.siliconinvestor.com/*). Silicon Investor does not currently
supply information on dividend distributions or splits.

   For quote queries in particular, at the time of this writing, the
Silicon Investor web site utilizes start and end dates, returns data 200
entries at a time. The quote_urls() method provides all the URLs necessary
given the date range and symbols. These are automatically utilized by the
native methods of Finance::QuoteHist::Generic.

   Please see `Finance::QuoteHist::Generic(3)' in this node for more
details on usage and available methods. If you just want to get historical
quotes and are not interested in the details of how it is done, check out
`Finance::QuoteHist(3)' in this node.

METHODS
=======

   The basic user interface consists of a single method, as shown in the
example above. That method is:

quotes()
     Returns a list of rows (or a reference to an array containing those
     rows, if in scalar context). Each row contains the Symbol, Date,
     Open, *High*, Low, Close, and Volume for that date. Quote values are
     pre-adjusted for this site.

REQUIRES
========

   Finance::QuoteHist::Generic

DISCLAIMER
==========

   The data returned from these modules is in no way guaranteed, nor are
the developers responsible in any way for how this data (or lack thereof)
is used. The interface is based on URLs and page layouts that might change
at any time. Even though these modules are designed to be adaptive under
these circumstances, they will at some point probably be unable to
retrieve data unless fixed or provided with new parameters. Furthermore,
the data from these web sites is usually not even guaranteed by the web
sites themselves, and oftentimes is acquired elsewhere.

   In the case of The Silicon Investor, as of November 27, 2000, their
statement reads, in part:

     All information provided by S&P ComStock, Inc. ("ComStock") and its
     affiliates (the "ComStock Information") on Silicon Investor World
     Wide Web site is owned by or licensed to ComStock and its affiliates
     and any user is permitted to store, manipulate, analyze, reformat,
     print and display the ComStock Information only for such user's
     personal use. In no event shall any user publish, retransmit,
     redistribute or otherwise reproduce any ComStock Information in any
     format to anyone, and no user shall use any ComStock Information in
     or in connection with any business or commercial enterprise,
     including, without limitation, any securities, investment,
     accounting, banking, legal or media business or enterprise.

   There you have it. If you feel like you might have concerns with this
then first double check the statement on the bottom of this page:

     http://www.siliconinvestor.com/misc/terms.html

   If you still have concerns, then use another site-specific historical
quote instance, or none at all.

   Above all, play nice.

AUTHOR
======

   Matthew P. Sisk, <`sisk@mojotoad.com'>

COPYRIGHT
=========

   Copyright (c) 2000 Matthew P. Sisk. All rights reserved. All wrongs
revenged. This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

SEE ALSO
========

   Finance::QuoteHist::Generic(3), Finance::QuoteHist(3), perl(1).

Site-specific subclass for retrieving historical stock quotes.
**************************************************************

NAME
====

   Finance::QuoteHist::Yahoo - Site-specific subclass for retrieving
historical stock quotes.

SYNOPSIS
========

     use Finance::QuoteHist::Yahoo;
     $q = new Finance::QuoteHist::Yahoo
        (
         symbols    => [qw(IBM UPS AMZN)],
         start_date => '01/01/1999',
         end_date   => 'today',
        );

     # Adjusted values
     foreach $row ($q->quotes()) {
       ($symbol, $date, $open, $high, $low, $close, $volume) = @$row;
       ...
     }

     # Non adjusted values
     $q->adjusted(0);
     foreach $row ($q->quotes()) {
        ($symbol, $date, $open, $high, $low, $close, $volume, $adj_close) = @$row;
     }

     # Splits
     foreach $row ($q->splits()) {
        ($symbol, $date, $post, $pre) = @$row;
     }

     # Dividends
     foreach $row ($q->dividends()) {
        ($symbol, $date, $dividend) = @$row;
     }

DESCRIPTION
===========

   Finance::QuoteHist::Yahoo is a subclass of Finance::QuoteHist::Generic,
specifically tailored to read historical quotes, dividends, and splits
from the Yahoo web site (*http://charts.yahoo.com/*).

   For quotes and dividends, Yahoo can return data quickly in CSV format.
For quotes, non-adjusted values are available in HTML. Splits are only
found embedded in the non-adjusted HTML produced for quotes. Behind the
scenes, an HTML quote query is performed when splits are requested; quotes
are retained based on the first successful query type. Unless told
otherwise, via the `adjusted()' method, the non-adjusted quotes will be
automatically adjusted by applying the ratio derived from the adjusted
closing value and non-adjusted closing value. This does not apply if
quotes were retrieved using CSV.

   There are no date range restrictions on CSV queries for quotes and
dividends.

   For HTML queries, Yahoo takes arbitrary date ranges as arguments, but
breaks results into pages of 200 entries.

   The quote_urls() and `dividend_urls' methods provide all the URLs
necessary given the target, date range, and symbols, whether they be for
HTML or CSV data. These are automatically utilized by the native methods
of Finance::QuoteHist::Generic.

   Please see `Finance::QuoteHist::Generic(3)' in this node for more
details on usage and available methods. If you just want to get historical
quotes and are not interested in the details of how it is done, check out
`Finance::QuoteHist(3)' in this node.

METHODS
=======

   The basic user interface consists of four methods, as seen in the
example above. Those methods are:

quotes()
     Returns a list of rows (or a reference to an array containing those
     rows, if in scalar context). Each row contains the Symbol, Date,
     Open, *High*, Low, Close, and Volume for that date. Optionally, if
     non-adjusted values were requested, their will be an extra element at
     the end of the row for the *Adjusted* closing price.

dividends()
     Returns a list of rows (or a reference to an array containing those
     rows, if in scalar context). Each row contains the Symbol, Date, and
     amount of the *Dividend*, in that order.

splits()
     Returns a list of rows (or a reference to an array containing those
     rows, if in scalar context). Each row contains the Symbol, Date,
     *Post* split shares, and *Pre* split shares, in that order.

adjusted($boolean)
     Sets whether adjusted or non-adjusted quotes are desired. Quotes are
     pre-adjusted by default.

   There are some extra methods and overridden methods in the Yahoo class
that deserve a little explanation for developers interested in developing
a similar site-specific module:

source_type($type)
     Sets or returns the desired type of output from Yahoo. Valid settings
     are 'csv' and 'html'. By default this is 'csv', where possible, but
     will sometimes be set to 'html' in cases where there is no choice,
     such as when split information is requested. In these cases, the
     desired source type is temporarily saved for the duration of the query
     and restored afterwards.

   The following methods override methods provided by the
Finance::QuoteHist::Generic module; more of this was necessary than is
typical for a basic query site due to the variety of query types and data
formats available on Yahoo.

quote_urls()
dividend_urls()
     Provides the URLs necessary for direct quote and dividend queries;
     depending on the value returned by the `source_type()' method, these
     URLs are either for HTML or CSV data.

dividend_extract()
split_extract()
     The presence of these filters will lift dividend and split information
     from the regular HTML quote output of Yahoo. In the case of splits,
     this is the only way to get the information, hence there is no
     split_urls() method present.

split_get()
     The mere presence of the split_extract() method would normally be
     enough for extraction retrieval. In this case, however, the data must
     be in HTML format. By overriding the method, 'html' can be
     specifically (and temporarily) requested for the duration of the
     query since the split information is not present in the CSV formats.

csv_parser()
     Unfortunate hack. Yahoo just happens to return CSV data from direct
     dividend queries in a mangled format (the CSV separator is different
     for the header row vs. the rest of the rows). This corrects that
     before passing it along to the regular csv_parser() method.

REQUIRES
========

   Finance::QuoteHist::Generic

DISCLAIMER
==========

   The data returned from these modules is in no way guaranteed, nor are
the developers responsible in any way for how this data (or lack thereof)
is used. The interface is based on URLs and page layouts that might change
at any time. Even though these modules are designed to be adaptive under
these circumstances, they will at some point probably be unable to
retrieve data unless fixed or provided with new parameters. Furthermore,
the data from these web sites is usually not even guaranteed by the web
sites themselves, and oftentimes is acquired elsewhere.

   In the case of Yahoo, as of September 13, 2000, their statement reads,
in part:

     Historical chart data and daily updates provided by
     Commodity Systems, Inc. (CSI). Data and information is
     provided for informational purposes only, and is not
     intended for trading purposes. Neither Yahoo nor any of
     its data or content providers (such as CSI) shall be
     liable for any errors or delays in the content, or for
     any actions taken in reliance thereon.

   If you would like to know more, check out where this statement was
found:

     http://chart.yahoo.com/d

   Better yet, you might want to read their disclaimer page:

     http://www.yahoo.com/info/misc/disclaimer.html

   If you still have concerns, then use another site-specific historical
quote instance, or none at all.

   Above all, play nice.

AUTHOR
======

   Matthew P. Sisk, <`sisk@mojotoad.com'>

COPYRIGHT
=========

   Copyright (c) 2000 Matthew P. Sisk. All rights reserved. All wrongs
revenged. This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

SEE ALSO
========

   Finance::QuoteHist::Generic(3), Finance::QuoteHist(3), perl(1).

Get a chart from Yahoo! Finance
*******************************

NAME
====

   Finance::YahooChart - Get a chart from Yahoo! Finance

SYNOPSIS
========

     use Finance::YahooChart;
     %img = getchart(symbol => $symbol, size => $size, type => $type,
     		  include => $include);
     print "<IMG SRC=$img{'url'} WIDTH=$img{'width'} HEIGHT=$img{'height'}>";

DESCRIPTION
===========

   This module gets charts from Yahoo! Finance.  The only function in the
module is the *getchart* function, which takes the stock symbol, size of
the chart (b for big, s for small), the type of chart (i for intraday, w
for week, 3 for 3-month, 1 for 1-year, 2 for 2-year, and 5 for 5-year),
and any extra information to include (s for a comparison to the S&P 500, m
for a moving average).  It returns a hash with the following elements:

     'url' => The URL of the chart
     'width' => The width of the chart
     'height' => The height of the chart

   Note that not all combinations are available for all charts.

   Big charts are available for all types.

   Small charts are only available for i, w, and 1 charts.

   Includes are only available for big 3, 1, 2, and 5 charts.

   In most cases, if an invalid configuration is passed,
*$Finance::YahooChart::Error* will be set to some kind of error message.

COPYRIGHT
=========

   Copyright 1998, Dj Padzensky

   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.

   The information that you obtain with this library may be copyrighted by
Yahoo! Inc., and is governed by their usage license.  See
http://www.yahoo.com/docs/info/gen_disclaimer.html for more information.

AUTHOR
======

   Dj Padzensky (`djpadz@padz.net'), PadzNet, Inc.

   The Finance::YahooChart home page can be found at
http://www.padz.net/~djpadz/YahooChart/

Get a stock quote from Yahoo!
*****************************

NAME
====

   Finance::YahooQuote - Get a stock quote from Yahoo!

SYNOPSIS
========

     use Finance::YahooQuote;
     $Finance::YahooQuote::TIMEOUT = 60;
     @quote = getonequote $symbol;	# Get a quote for a single symbol
     @quotes = getquote @symbols;	# Get quotes for a bunch of symbols

DESCRIPTION
===========

   This module gets stock quotes from Yahoo! Finance.  The *getonequote*
function will return a quote for a single stock symbol, while the
*getquote* function will return a quote for each of the stock symbols
passed to it.  The return value of *getonequote* is an array, with the
following elements:

     0 Symbol
     1 Company Name
     2 Last Price
     3 Last Trade Date
     4 Last Trade Time
     5 Change
     6 Percent Change
     7 Volume
     8 Average Daily Vol
     9 Bid
     10 Ask
     11 Previous Close
     12 Today's Open
     13 Day's Range
     14 52-Week Range
     15 Earnings per Share
     16 P/E Ratio
     17 Dividend Pay Date
     18 Dividend per Share
     19 Dividend Yield
     20 Market Capitalization
     21 Stock Exchange

   The *getquote* function returns an array of pointers to arrays with the
above structure.

   You may optionally override the default LWP timeout of 180 seconds by
setting $Finance::YahooQuote::TIMEOUT to your preferred value.

FAQ
===

   If there's one question I get asked over and over again, it's how did I
figure out the format string?  Having typed the answer in innumerable
emails, I figure sticking it directly into the man page might help save my
fingers a bit...

   If you have a My Yahoo! (http://my.yahoo.com) account, go to the
following URL:

     http://edit.my.yahoo.com/config/edit_pfview?.vk=v1

   Viewing the source of this page, you'll come across the section that
defines the menus that let you select which elements go into a particular
view.  The <option> values are the strings that pick up the information
described in the menu item.  For example, Symbol refers to the string "s"
and name refers to the string "l".  Using "sl" as the format string, we
would get the symbol followed by the name of the security.

   If you have questions regarding this, play around with $QURL, changing
the value of the f parameter.

COPYRIGHT
=========

   Copyright 1998, Dj Padzensky

   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.

   The information that you obtain with this library may be copyrighted by
Yahoo! Inc., and is governed by their usage license.  See
http://www.yahoo.com/docs/info/gen_disclaimer.html for more information.

AUTHOR
======

   Dj Padzensky (`djpadz@padz.net'), PadzNet, Inc.

SEE ALSO
========

   The Finance::YahooQuote home page can be found at
http://www.padz.net/~djpadz/YahooQuote/

   Show Me The Money, a derivative work by Dirk Eddelbüttel, that uses
Finance::YahooQuote in a graphical environment, can be found at
http://rosebud.sps.queensu.ca/~edd/code/smtm.html.

Locate directory of original perl script
****************************************

NAME
====

   FindBin - Locate directory of original perl script

SYNOPSIS
========

     use FindBin;
     use lib "$FindBin::Bin/../lib";

     or

     use FindBin qw($Bin);
     use lib "$Bin/../lib";

DESCRIPTION
===========

   Locates the full path to the script bin directory to allow the use of
paths relative to the bin directory.

   This allows a user to setup a directory tree for some software with
directories <root>/bin and <root>/lib and then the above example will allow
the use of modules in the lib directory without knowing where the software
tree is installed.

   If perl is invoked using the -e option or the perl script is read from
STDIN then FindBin sets both `$Bin' and `$RealBin' to the current
directory.

EXPORTABLE VARIABLES
====================

     $Bin         - path to bin directory from where script was invoked
     $Script      - basename of script from which perl was invoked
     $RealBin     - $Bin with all links resolved
     $RealScript  - $Script with all links resolved

KNOWN BUGS
==========

   if perl is invoked as

     perl filename

   and filename does not have executable rights and a program called
filename exists in the users `$ENV{PATH}' which satisfies both -x and -T
then FindBin assumes that it was invoked via the `$ENV{PATH}'.

   Workaround is to invoke perl as

     perl ./filename

AUTHORS
=======

   FindBin is supported as part of the core perl distribution. Please send
bug reports to <`perlbug@perl.org'> using the perlbug program included
with perl.

   Graham Barr <`gbarr@pobox.com'> Nick Ing-Simmons <`nik@tiuk.ti.com'>

COPYRIGHT
=========

   Copyright (c) 1995 Graham Barr & Nick Ing-Simmons. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

determines first successful URL in list
***************************************

NAME
====

   FirstGoodURL - determines first successful URL in list

SYNOPSIS
========

     use FirstGoodURL;
     use strict;

     my @URLs = (...);
     my $match;

     if ($match = FirstGoodURL->in(@URLs)) {
       print "good URL: $match\n";
     }
     else {
       print "no URL was alive\n";
     }

     if ($match = FirstGoodURL->with('image/png')->in(@URLs)) {
       print "PNG found at $match\n";
     }
     else {
       print "no PNG found\n";
     }

     if ($match = FirstGoodURL->with(200,204)->in(@URLs)) {
       print "Status: OK or No Content at $match\n";
     }
     else {
       print "no 200/204 found\n";
     }

DESCRIPTION
===========

   This module uses the LWP suite to scan through a list of URLs.  It
determines the first URL that returns a specified status code (with
defaults to `200'), and optionally, a specified Content-type.

Methods
=======

   * `FirstGoodURL->in(...)'

     Scans a list of URLs for a specified response code, and possibly a
     requisite Content-type (see the with method below)

   * `FirstGoodURL->with(...)'

     Sets a Content-type and/or Status requisite value for future calls to
     in.  It is destructive to the previous settings given, so you must
     send all settings at once.

     *This is not backward compatible.*

     The argument list can contain a list of Status response codes, and
     either a list of Content-type response values or a regex to match
     acceptable Content-type response values.  These can appear in any
     order.  The regex must be a compiled one (formed by using `qr//').

     This method returns the class name, so that you can daisy-chain calls
     for readability/snazziness:

          my $match = FirstGoodURL->with(qr/image/)->in(@URLs);

TODO
====

   Here is a listing of things that might be added to future versions.

   * Object support (with attributes per object)

AUTHOR
======

     Jeff "japhy" Pinyan
     CPAN ID: PINYAN
     japhy@pobox.com
     http://www.pobox.com/~japhy/

Interface to Adobe Font Metrics files
*************************************

NAME
====

   Font::AFM - Interface to Adobe Font Metrics files

SYNOPSIS
========

     use Font::AFM;
     $h = new Font::AFM "Helvetica";
     $copyright = $h->Notice;
     $w = $h->Wx->{"aring"};
     $w = $h->stringwidth("Gisle", 10);
     $h->dump;  # for debugging

DESCRIPTION
===========

   This module implements the Font::AFM class. Objects of this class are
initialised from an AFM-file and allows you to obtain information about
the font and the metrics of the various glyphs in the font.

   All measurements in AFM files are given in terms of units equal to
1/1000 of the scale factor of the font being used. To compute actual sizes
in a document, these amounts should be multiplied by (scale factor of
font)/1000.

   The following methods are available:

$afm = Font::AFM->new($fontname)
     Object constructor. Takes the name of the font as argument. It will
     croak if the font can not be found.

$afm->latin1_wx_table()
     Returns a 256 element array, where each element contains the width of
     the corresponding character in the iso-8859-1 character set.

$afm->stringwidth($string, [$fontsize])
     Returns the width of the string passed as argument. The string is
     assumed to be encoded in the iso-8859-1 character set.  A second
     argument can be used to scale the width according to the font size.

$afm->FontName
     The name of the font as presented to the PostScript language
     `findfont' operator, for instance "Times-Roman".

$afm->FullName
     Unique, human-readable name for an individual font, for instance
     "Times Roman".

$afm->FamilyName
     Human-readable name for a group of fonts that are stylistic variants
     of a single design. All fonts that are member of such a group should
     have exactly the same FamilyName. Example of a family name is "Times".

$afm->Weight
     Human-readable name for the weight, or "boldness", attribute of a
     font.  Exampes are `Roman', `Bold', `Light'.

$afm->ItalicAngle
     Angle in degrees counterclockwise from the vertical of the dominant
     vertical strokes of the font.

$afm->IsFixedPitch
     If the value is `true', it indicated that the font is a fixed-pitch
     (monospaced) font.

$afm->FontBBox
     A string of four numbers giving the lower-left x, lower-left y,
     upper-right x, and upper-right y of the font bounding box. The font
     bounding box is the smallest rectangle enclosing the shape that would
     result if all the characters of the font were placed with their
     origins coincident, and then painted.

$afm->UnderlinePosition
     Recommended distance from the baseline for positioning underline
     stokes. This number is the y coordinate of the center of the stroke.

$afm->UnderlineThickness
     Recommended stroke width for underlining.

$afm->Version
     Version number of the font.

$afm->Notice
     Trademark or copyright notice, if applicable.

$afm->Comment
     Comments found in the AFM file.

$afm->EncodingScheme
     The name of the standard encoding scheme for the font. Most Adobe
     fonts use the `AdobeStandardEncoding'. Special fonts might state
     `FontSpecific'.

$afm->CapHeight
     Usually the y-value of the top of the capital H.

$afm->XHeight
     Typically the y-value of the top of the lowercase x.

$afm->Ascender
     Typically the y-value of the top of the lowercase d.

$afm->Descender
     Typically the y-value of the bottom of the lowercase p.

$afm->Wx
     Returns a hash table that maps from glyph names to the width of that
     glyph.

$afm->BBox
     Returns a hash table that maps from glyph names to bounding box
     information.  The bounding box consist of 4 numbers: llx, lly, urx,
     ury.

$afm->dump
     Dumps the content of the Font::AFM object to STDOUT.  Might sometimes
     be useful for debugging.

   The AFM specification can be found at:

     ftp://ftp.adobe.com/pub/adobe/DeveloperSupport/TechNotes/PSfiles/5004.AFM_Spec.ps

ENVIRONMENT
===========

METRICS
     Contains the path to seach for AFM-files.  Format is as for the PATH
     environment variable. The default path built into this library is:

          /usr/lib/afm:/usr/local/lib/afm:/usr/openwin/lib/fonts/afm/:.

BUGS
====

   Kerning data and composite character data is not yet parsed.  Ligature
data is not parsed.

COPYRIGHT
=========

   Copyright 1995-1998 Gisle Aas. All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Font REporting Tool
*******************

NAME
====

   Fret - Font REporting Tool

SYNOPSIS
========

     use Font::Fret;
     fret('', @ARGV);

   or

     package myFret;
     use Font::Fret;
     @ISA = qw(Font::Fret::Default);
     fret('myFret', @ARGV);

DESCRIPTION
===========

   Fret is a font reporting tool system which allows for different reports
to be written. A report is a package on which calls are made to give
specific information for a specific report. The rest of Fret does the
housekeeping of generating the report in PDF format.

   The function `fret' which is imported when the Fret moduled is 'use'd,
takes two arguments: the name of the report package and the command line
array. Fret does all the work of parsing the command line, etc. and just
makes call-backs into the package it is asked to use.

   Fret.pm comes with its own default report package (called
Font::Fret::Default) which may be subclassed to generate other reports.

   The overall structure of the interaction between Fret and the reporting
package is that Fret will ask the package for a list of character ids in
the order in which those characters should appear in the report. For each
character, Fret will ask the package to create a glyph id for that
character. This allows a double layer of indirection in arriving at the
list of glyph ids to process, allowing a glyph to appear twice in the
report with different information about it each time.

   There are two important areas in a report: inside the glyph box (where
there are four corners in which information may be displayed) and the
report area, which consists of two independent rows of information for
each glyph. Each row type is columnated independently across all the
glyphs on a page.

   In addition to where the report information is displayed, there is also
a mechanism which allows a limited level of formatting of the information.
The text may be justified left, right or centre and the font styling may
be adjusted between regular, bold, italic and bold italic and the colour
of the text may be changed.  Notice that the font face may not be changed
or the font size or anything else.  A formatted string consists of
formatting information separated from the string by |. If a string needs
to contain a | it should be escaped thus: `\|' (notice that there is no
need to escape \ or any other character).

   The formatting is structured as a comma separated list of 3 elements:
justification, font styling and then colour.

justification
     The values are r: right justified; c: centred and the default of l:
     left justified

font styling
     The values are r: regular (by default); i: italic; b: bold; bi:
     bold-italic

colour
     The colour is a string of 6 hex digits corresponding to 8-bits of
     Red, Green and Blue information

METHODS
=======

make_cids
---------

   This subroutine is called to ask for a list of character ids, which
will be used to generate glyph ids and thence glyphs. The returned list is
rendered in the order of the list.

   The first item on the returned list is used to display the type of
report in the box header. This string may not be formatted.

   This allows a FRET report writer to generate any sequence of glyphs in
their report (e.g. Unicode based, pass/fail conditions, etc.)

cid_gid
-------

   This is called to convert a character id into a glyph id for rendering.

boxhdr
------

   This subroutine is called to ask the report for the headings for the
four items displayed in a box. The headings appear in the box header. The
order of the returned list of string is: bottom left, bottom right, top
left, top right.  The strings may not be formatted in any way.

topdat
------

   This subroutine returns the two strings that constitute what should be
displayed in the top of a glyph box. The two strings allow for per glyph
formatting. Notice that the default action is to render the right hand
element (the second element) right justified.

lowdat
------

   This subroutine returns two elements for the two elements displayed at
the bottom of a glyph box. The elements may be formatted for colour, etc.
and the second should be right formatted.

row1hdr
-------

   This returns the heading information for the first report row. The
value returned is a list of formatted items, which will be used to head
the columns in row 1 of the report area. These will be combined in the
column width calculations.

row2hdr
-------

   Returns a list of formatted items corresponding to the column headers
for row 2 of the report area.

row1
----

   This subroutine is called for each glyph to return the content of each
column in row 1 as a list of formatted items. The values passed in are:

     cid     character id as passed to cid_gid
     gid     glyph id as returned from cid_gid and is an index into the font
             for such tables as hmtx.
     glyph   the glyph object from the font i.e. $font->{'loca'}{glyphs}[$gid]
     uid     unicode reverse lookup of the gid. This is the lowest Unicode value
             which maps to this gid
     font    the font object corresponding to this font

   Each element in the returned list corresponds to an element in the
returned list for row1hdr

row2
----

   As per row 1 for row 2

label
-----

   Given:

     Glyph
     Point number
     [x, y] point co-ordinates
     path number
     on or off point
     font

   Returns a simple string for the label for the point

read information from TeX font metric files
*******************************************

NAME
====

   Font::TFM - read information from TeX font metric files

SYNOPSIS
========

     use Font::TFM;
     ### $Font::TFM::TEXFONTSDIR = 'your directories';
     ### to change the default

     my $cmr = new Font::TFM 'cmr10'
     	or die "Error reading font: $Font::TFM::errstr\n";
     print 'Designsize: ', $cmr->designsize(), "\n";
     print $cmr->width('A'), ', ', $cmr->kern('Wo'), "\n";

   should print

     Designsize: 10
     491521.25, -54613.75

DESCRIPTION
===========

   To read the information from TFM (TeX font metrics) file, you first
create the object of *Font::TFM* class in memory. You do this by calling
method *Font::TFM::new* with font name and it creates a new TFM object in
memory, loading all the necessary information from the `.tfm' file. Second
(optional) parameter means scale of the font. You can also use
*Font::TFM::new_at* and as the second parameter put requested size in pt:

     my $cmr10_12 = new_at Font::TFM 'cmr10', 12;

   The methods new and *new_at* search for the `.tfm' files in the
directories listed colon separated in a variable
*$Font::TFM::TEXFONTSDIR*, and also in all of their subdirectories.  By
default, they use files `ls-R' (this name can be changed in the
*$Font::TFM::LSFILENAME* variable) to speed up the search. This feature
can be disabled by setting variable *$Font::TFM::TEXFONTSUSELS* to 0.
Suffix `.tfm' is appended if necessary.

   If the file is not found (or there is some other problem), new returns
undef and sets error message to *$Font::TFM::errstr*.

   After the file was loaded, you can use the following methods of the
object to query information about the font's properties and about the
characters, etc.

designsize, fontsize
     Returns the design size and the actual size of the font in pt.

          $cmr->designsize;	returns 10
          $cmr->fontsize;			10
          $cmr10_12->fontsize;		12

width, height, depth, italic
     Returns the requested dimension for a specified character of the font.

          $cmr->height("A")		447828.75
          $cmr10_12->height("A")		537394.5
          $cmr->italic("I")		0
          $cmr10_12->italic("f")		61167.75

kern, lig, ligpassover
     For a two-letter string returns kern between them, ligature formed and
     number of characters to pass over after the ligature, respectivelly.

          $cmr->lig("fi")			\014
          $cmr->lig("ff")			\013
          $cmr->lig("\013i")		\016
          $cmr10_12->kern("AV")		-87381.75

expand
     One string parameter undergoes ligature expansion and then kernings
     are inserted. Returns array containing of string, kern, string, ...

          $cmr->expand("AV--fix")		"A", -72818.125, "V{\014x"

word_dimensions
     Returns the width, height and depth of a word. Does the lig/kern
     expansion, so the result is the real space it will take on output.

          $cmr->word_dimensions("AV--fix")
          				1947881.875, 455111.25, 0
          $cmr->word_dimensions("pm")	910225, 282168.75, 127431.25

word_width, word_height, word_depth
     Calls word_dimensions and returns appropriate element. No caching is
     done, so it is better to call word_dimensions yourself if you will
     need more than one dimension of one word.

param
     Returns parameter of the font, indexed from 1.

slant, x_height, em_width, quad
space, space_stretch, space_shrink, extra_space
     Returns the parameter of the font, by name.

          $cmr->slant()			0
          $cmsl10->slant()		0.166671752929688
          $cmr->x_height()		282168.75
          $cmr->height("x")		282168.75
          $cmr->em_width()		655361.875
          $cmr->quad()			655361.875

          $cmr->space()			218453.75
          $cmr->space_stretch()		109226.875
          $cmtt10->space()		344061.25
          $cmtt10->space_stretch()	0

name
     Returns the name of the font.

   Dimensions are multiplied by *$Font::TFM::MULTIPLY* * actual size of
the font. Value of *$Font::TFM::MULTIPLY* defaults to 65536, so the
dimensions can be used directly when writing the `.dvi' file.

   Variable *$Font::TFM::DEBUG* may be set to 1 to get the processing
messages on the standard error output.

   The module is subclassable. You can define you own module that would
provide alternate way of finding and opening the file. Just make new
module and defined your own method open_tfm in it.

VERSION
=======

   0.100

SEE ALSO
========

   TeX::DVI(3), TeX::DVI::Parse(3), perl(1).

AUTHOR
======

   (c) 1996-2000 Jan Pazdziora, adelton@fi.muni.cz,
http://www.fi.muni.cz/~adelton/ at Faculty of Informatics, Masaryk
University, Brno, Czech Republic

easily create CGI form-based applications
*****************************************

NAME
====

   FormMagick - easily create CGI form-based applications

SYNOPSIS
========

     use FormMagick;

     my $f = new FormMagick();
     my $f = new FormMagick(TYPE => FILE,  SOURCE => $myxmlfile, DEBUG => 1);

     $f->add_lexicon("fr", { "Yes" => "Oui", "No" => "Non"});

     $f->display();

DESCRIPTION
===========

   FormMagick is a toolkit for easily building fairly complex form-based
web applications.  It allows the developer to specify the structure of a
multi-page "wizard" style form using XML, then display that form using
only a few lines of Perl.

How it works:
-------------

   You (the developer) provide at least:

   * Form descriptions (XML)

   * HTML templates (Text::Template format) for the page headers and
     footers

   And may optionally provide:

   * L10N lexicon entries

   * Validation routines for user input data

   * Routines to run before or after a page of the form is displayed

   FormMagick brings them all together to create a full application.

METHODS
=======

new()
-----

   The new() method requires no arguments, but may take the following
optional arguments (as a hash):

TYPE
     Defaults to "FILE" (the only currently implemented type).  Eventually
     we'll also allow such things as FILEHANDLE, STRING, etc (c.f.
     Text::Template, which does this quite nicely).

SOURCE
     Defaults to a filename matching that of your script, only with an
     extension of .xml (we got this idea from XML::Simple).

DEBUG
     Defaults to 0 (no debug output).  Setting it to 1 (or any other true
     value) will cause debugging messages to be output.

display()
---------

   The display method displays your form.  It takes no arguments.

add_lexicon()
-------------

   This method takes two arguments.  The first is a two-letter string
representing the language to which entries should be added.  These are
standard ISO language abbreviations, eg "en" for English, "fr" for French,
"de" for German, etc.

   The second argument is a hashref in which the keys of the hash are the
phrases to be translated and the values are the translations.

   For more information about how localization (L10N) works in FormMagick,
see `FormMagick::L10N'.

debug($msg)
-----------

   The debug method prints out a nicely formatted debug message.  It's
usually called from your script as `$f-'debug($msg)>

Form descriptions
-----------------

   Sample form description

   The following is an example of how a form is described in XML. More
complete examples can be found in the `examples/' subdirectory in the
FormMagick distribution.

     <FORM TITLE="My form application" HEADER="myform_header.tmpl"
       FOOTER="myform_footer.tmpl" POST-EVENT="submit_order">
       <PAGE NAME="Personal" TITLE="Personal details" DESCRIPTION="Please
       provide us with the following personal details for our records">
         <FIELD ID="firstname" LABEL="Your first name" TYPE="TEXT"
           VALIDATION="nonblank"/>
         <FIELD ID="lastname" LABEL="Your surname" TYPE="TEXT"
           VALIDATION="nonblank"/>
         <FIELD ID="username" LABEL="Choose a username" TYPE="TEXT"
           VALIDATION="username" DESCRIPTION="Your username must
     	be between 3 and 8 characters in length and contain only letters
     	and numbers."/>
       </PAGE>
       <PAGE NAME="Payment" TITLE="Payment details"
       POST-EVENT="check_credit_card" DESCRIPTION="We need your full credit
       card details to process your order.  Please fill in all fields.
       Your card will be charged within 48 hours.">
         <FIELD ID="cardtype" LABEL="Credit card type" TYPE="SELECT"
           OPTIONS="list_credit_card_types" VALIDATION="credit_card_type"/>
         <FIELD ID="cardnumber" LABEL="Credit card number" TYPE="TEXT"
           VALIDATION="credit_card_number"/>
         <FIELD ID="cardexpiry" LABEL="Expiry date (MM/YY)" TYPE="TEXT"
           VALIDATION="credit_card_expiry"/>
       </PAGE>
     </FORM>

   The XML must comply with the FormMagick DTD (included in the
distribution as FormMagick.dtd).  A command-line tool to test compliance
is planned for a future release.

SEE ALSO
========

   FormMagick::L10N

   FormMagick::Validator

   FormMagick::FAQ

BUGS
====

   There are a number of features which have not yet been implemented.
Also, there are probably mismatches between this perldoc and the actual
functionality.

AUTHOR
======

   Kirrily "Skud" Robert <skud@infotrope.net>

   Contributors:

   Shane R. Landrum <slandrum@turing.csc.smith.edu>

   James Ramirez <jamesr@cogs.susx.ac.uk>

   More information about FormMagick may be found at
http://sourceforge.net/projects/formmagick/

Frequently asked questions about FormMagick
*******************************************

NAME
====

   FormMagick FAQ - Frequently asked questions about FormMagick

HOW DO I...
===========

How do I check that my XML is valid?
------------------------------------

How do I customise the look and feel of my forms?
-------------------------------------------------

   Use cascading style sheets.  Take a look at the HTML source output by
FormMagick, and you'll see that most things have a "label" attribute to
make CSS easier.

How do I make my own validation routines?
-----------------------------------------

   Simply create a routine in your CGI script which accepts the data to
validate as an argument.  Have it return "OK" on success or a detailed
error message on failure.

     sub my_validation {
         my $data = shift;
         if ($data =~ /$some_pattern/) {
             return "OK";
         } else {
             return "That looks wrong to me.";
         }
     }

How do I add translations into another language?
------------------------------------------------

   Use the add_lexicon() method:

     $f->add_lexicon("fr", { "Yes" => "Oui", "No" => "Non" });

How do I do extra processing when a user clicks "Next"?
-------------------------------------------------------

   Use a POST-EVENT on the PAGE element.  Create a subroutine that does
what you want:

     sub process_credit_card {
         my $cgi = shift;
     	my $cardnum = $cgi->param("cardnum");
     	my $response = do_processing($cardnum);
     	print "<p>$response</p>";
     }

How do I choose which page to go to based on user input?
--------------------------------------------------------

   Use a PAGE POST-EVENT and set the value of the "wherenext" CGI
parameter:

     sub my_post_page_event {
         my $cgi = shift;
     	if ($cgi->param("foo") eq "bar") {
             $cgi->param(-name => "wherenext", -value => "GoToThisPageName")
         } elsif ($cgi->param("had_enough") eq "Yes") {
             $cgi->param(-name => "wherenext", -value => "Finish")
         }
     }

TROUBLESHOOTING
===============

General troubleshooting tips
----------------------------

   Try turning on debugging when you invoke FormMagick:

   my $f = new FormMagick( DEBUG => 1 );

Why isn't my data preserved from one page to the next?
------------------------------------------------------

   You probably need to make your `session-tokens' directory writable and
executable by the web server.  Either:

     chown www session-tokens
        (assuming your webserver runs as the www user)
     chmod 700 session-tokens

   Or...

     chown 777 session-tokens

   FormMagick::L10N - localization routines for FormMagick

SYNOPSIS
========

     use FormMagick::L10N;

DESCRIPTION
===========

   L10N (Localisation) is the name given to the process of providing
translations into another language.  The previous step to this is I18N
(internationalisation) which is the process of making an application ready
to accept the translations.

   We've done the work of I18N for you, so all you have to do is provide
translations for your apps.

   FormMagick uses the `Locale::Maketext' module for L10N.  It stores its
translations for each language in a hash like this:

     %Lexicon = (
     	"Hello"		=> "Bonjour",
     	"Click here"	=> "Appuyez ici"
     );

   You can add your own entries to any language lexicon using the
add_lexicon() method (see `FormMagick' for how to call that method).

   Localisation preferences are picked up from the HTTP_ACCEPT_LANGUAGE
environment variable passed by the user's browser.  In Netscape, you set
this by choosing "Edit, Preferences, Navigator, Languages" and then
choosing your preferred language.

   Localisation is performed on:

   * Form titles

   * Page titles and descriptions

   * Field labels and descriptions

   * Validation error messages

   If you wish to localise other textual information such as your HTML
Templates, you will have to explicitly call the l10n routines.

SEE ALSO
========

   The general documentation for FormMagick (`perldoc FormMagick')

   More information about FormMagick may be found at
http://sourceforge.net/projects/formmagick/

Perl module that can create any HTML tags, as well as groups of or just parts of them, and complete html headers or footers.
****************************************************************************************************************************

NAME
====

   HTML::TagMaker - Perl module that can create any HTML tags, as well as
groups of or just parts of them, and complete html headers or footers.

DEPENDENCIES
============

Perl Version
------------

     5.004

Standard Modules
----------------

     I<none>

Nonstandard Modules
-------------------

     Class::ParamParser

SYNOPSIS
========

     use HTML::TagMaker;

     my $html = HTML::TagMaker->new();
     $html->groups_by_default( 1 );

     print
     	'Content-type: text/html'."\n\n",
     	$html->start_html(
     		-title => "This Is My Page",
     		-style => { -code => <<__endquote },
     \nBODY {
     	background-color: #ffffff;
     	background-image: none;
     }
     __endquote
     	),
     	$html->h1( 'A Simple Example' ),
     	$html->p(
     		"Click " .
     		$html->a( href => 'http://search.cpan.org', text => 'here' ) .
     		" for more."
     	),
     	$html->hr,
     	$html->table(
     		$html->tr( [
     			$html->th( [ 'Name', 'Count', 'URL', 'First Access' ] ),
     			$html->td( [ 'Old Page', 33, 'http://www.domain.com',
     				'1999/04/23 13:55:02' ] )
     		] )
     	),
     	$html->hr,
     	$html->form_start( method => 'post', action => 'http://localhost' ),
     	$html->p(
     		"What's your name? " .
     		$html->input( type => 'text', name => 'name' )
     	),
     	$html->p(
     		"What's the combination?" .
     		$html->input_group(
     			-type => 'checkbox',
     			-name => 'words',
     			-value => ['eenie', 'meenie', 'minie', 'moe'],
     			-checked => [1, 0, 1, 0],
     			-text => ['eenie', 'meenie', 'minie', 'moe'] ),
     	),
     	$html->p(
     		"What's your favorite colour? " .
     		$html->select_start( -size => 1, -name => 'color' ) .
     		$html->option_group(
     			-value => ['red', 'green', 'blue', 'chartreuse'],
     			-text => ['Red', 'Green', 'Blue', 'Chartreuse'] ) .
     		$html->select_end
     	),
     	$html->input( type => 'submit' ),
     	$html->form_end,
     	$html->end_html;

DESCRIPTION
===========

   This Perl 5 object class can be used to generate any HTML tags in a
format that is consistent with the W3C HTML 4.0 standard.  There are no
restrictions on what tags are named, however; you can ask for any new or
unsupported tag that comes along from Netscape or Microsoft, and it will
be made.  Additionally, you can generate lists of said tags with one
method call, or just parts of said tags (but not both at once).

   In this implementation, "standard format" means that tags are made as
pairs (<TAG></TAG>) by default, unless they are known to be "no pair"
tags.  Tags that I know to be "no pair" are [basefont, img, area, param,
br, hr, input, option, tbody, frame, comment, isindex, base, link, meta].
However, you can force any tag to be "pair" or "start only" or "end only"
by appropriately modifying your call to the tag making method.

   Also, "standard format" means that tag modifiers are formatted as
"key=value" by default, unless they are known to be "no value" modifiers.
Modifiers that I know to be "no value" are [ismap, noshade, compact,
checked, multiple, selected, nowrap, noresize, param].  These are
formatted simply as "key" because their very presence indicates positive
assertion, while their absense means otherwise.  For modifiers with
values, the values will always become bounded by quotes, which ensures
they work with both string and numerical quantities (eg: key="value").

   Note that this class is a subclass of Class::ParamParser, and inherits
all of its methods, "params_to_hash()" and "params_to_array()".

HTML CODE FROM SYNOPSIS PROGRAM
===============================

     Content-type: text/html

     <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
     <HTML>
     <HEAD>
     <TITLE>This Is My Page</TITLE>
     <STYLE>
     <!--
     BODY {
     	background-color: #ffffff;
     	background-image: none;
     }
      --></STYLE>
     </HEAD>
     <BODY>
     <H1>A Simple Example</H1>
     <P>Click
     <A HREF="http://search.cpan.org">here</A> for more.</P>
     <HR>
     <TABLE>
     <TR>
     <TH>Name</TH>
     <TH>Count</TH>
     <TH>URL</TH>
     <TH>First Access</TH></TR>
     <TR>
     <TD>Old Page</TD>
     <TD>33</TD>
     <TD>http://www.domain.com</TD>
     <TD>1999/04/23 13:55:02</TD></TR></TABLE>
     <HR>
     <FORM METHOD="post" ACTION="http://localhost">
     <P>What's your name?
     <INPUT TYPE="text" NAME="name"></P>
     <P>What's the combination?
     <INPUT TYPE="checkbox" NAME="words" CHECKED VALUE="eenie">eenie
     <INPUT TYPE="checkbox" NAME="words" VALUE="meenie">meenie
     <INPUT TYPE="checkbox" NAME="words" CHECKED VALUE="minie">minie
     <INPUT TYPE="checkbox" NAME="words" VALUE="moe">moe</P>
     <P>What's your favorite colour?
     <SELECT NAME="color" SIZE="1">
     <OPTION VALUE="red">Red
     <OPTION VALUE="green">Green
     <OPTION VALUE="blue">Blue
     <OPTION VALUE="chartreuse">Chartreuse
     </SELECT></P>
     <INPUT TYPE="submit">
     </FORM>
     </BODY>
     </HTML>

SYNTAX
======

   This class does not export any functions or methods, so you need to
call them using indirect notation.  This means using *Class->function()*
for functions and *$object->method()* for methods.

   Methods of this class always "return" their results, rather than
printing them out to a file or the screen.  Not only is this simpler, but
it gives the calling code the maximum amount of control over what happens
in the program.  They may wish to do post-processing with the generated
HTML, or want to output it in a different order than it is generated.  By
default, all results are returned as a scalar, but methods which generate
a list of tags can optionally return an ARRAY ref, with each element
containing a single tag.  This can aid in post-processing and possibly
speed up the program because there is less copying done.

   Through the magic of autoloading, this class can make any html tag by
calling a class method with the same name as the tag you want.  For
examples, use "hr()" to make a "<HR>" tag, or "p('text')" to make
"<P>text</P>".  This also means that if you mis-spell any method name, it
will still make a new tag with the mis-spelled name.  For autoloaded
methods only, the method names are case-insensitive.

   If you call a class method whose name ends in either of ['_start',
'_end', '_pair'], this will be interpreted as an instruction to make just
part of one tag whose name are the part of the method name preceeding that
suffix.  For example, calling "p_start( 'text' )" results in "<P>text"
rather than "<P>text</P>".  Similarly, calling "p_end()" will generate a
"</P>" only.  Using the '_pair' suffix will force tags to be made as a
pair, whether or not they would do so naturally.  For example, calling
"br_pair" would produce a "<BR></BR>" rather than the normal "<BR>".  When
using either of ['_start','_pair'], the arguments you pass the method are
exactly the same as the unmodified method would use, and there are no
other symantec differences.  However, when using the '_end' suffix, any
arguments are ignored, as the latter member of a tag pair never carries any
attributes anyway.

   If you call a class method whose name ends in "_group", this will be
interpreted as an instruction to make a list of tags whose name are the
part of the method name preceeding the "_group".  For example, calling
"td_group( ['here','we','are'] )" results in
"<TD>here</TD><TD>we</TD><TD>are</TD>" being generated.  The arguments
that you call this method are exactly the same as for calling a method to
make a single tag of the same name, except that the extra optional
parameter "list" can be used to force an ARRAY ref of the new tags to be
returned instead of a scalar.  The symantec difference is that any
arguments whose values are ARRAY refs are interpreted as a list of values
where each one is used in a separate tag; for a single tag, the literal
ARRAY ref itself would be used.  The number of tags produced is equal to
the length of the longest ARRAY ref passed as an argument.  For any other
arguments who have fewer than this count, their last value is replicated
and appended enough times as necessary to make them the same length.  The
value of a scalar argument is used for all the tags.  For example, calling
"input_group( type => checkbox, name => 'letters', value => ['a','b','c']
)" produces '<INPUT TYPE="checkbox" NAME="letters" VALUE="a"><INPUT
TYPE="checkbox" NAME="letters" VALUE="b"><INPUT TYPE="checkbox"
NAME="letters" VALUE="c">'.

   All autoloaded methods require their parameters to be in named format.
These names and values correspond to attribute names and values for the
new tags.  Since "no value" attributes are essentially booleans, they can
have any true or false value associated with them in the parameter list,
which won't be printed.  If an autoloaded method is passed exactly one
parameter, it will be interpreted as the "text" that goes between the tag
pair (<TAG>text</TAG>) or after "start tags" (<TAG>text).  The same result
can be had explicitely by passing the named parameter "text".  Most static
(non-autoloaded) methods require positional parameters, except for
start_html(), which can take either format.  The names of any named
parameters can optionally start with a "-".

FUNCTIONS AND METHODS
=====================

   Note that all the methods defined below are static, so information
specific to autoloaded methods won't likely apply to them.  All of these
methods take positional arguments unless otherwise specified.

new()
-----

   This function creates a new HTML::TagMaker object (or subclass thereof)
and returns it.

initialize()
------------

   This method is used by new() to set the initial properties of an object,
that it creates.  All page attributes are wiped clean, resulting in an
empty page.

clone([ CLONE ])
----------------

   This method initializes a new object to have all of the same properties
of the current object and returns it.  This new object can be provided in
the optional argument CLONE (if CLONE is an object of the same class as
the current object); otherwise, a brand new object of the current class is
used.  Only object properties recognized by HTML::TagMaker are set in the
clone; other properties are not changed.

groups_by_default([ VALUE ])
----------------------------

   This method is an accessor for the boolean "automatic grouping"
property of this object, which it returns.  If VALUE is defined, this
property is set to it.  In cases where we aren't told explicitely that
autoloaded methods are making a single or multiple tags (using ['_start',
'_end', '_pair'] and '_group' respectively), we look to this property to
determine what operation we guess.  The default is "single".  When this
property is true, we can make both single and groups of tags by using a
suffix-less method name; however, making single tags this way is slower
than when this property is false.  Also, be aware that when we are making
a "group", arguments that are ARRAY refs are always flattened, and when we
are making a "single", ARRAY ref arguments are always used literally.

positional_by_default([ VALUE ])
--------------------------------

   This method is an accessor for the boolean "positional arguments"
property of this object, which it returns.  If VALUE is defined, this
property is set to it.  With methods whose parameters could be either
named or positional, when we aren't sure what we are given, do we guess
positional?  Default is named.

prologue_tag()
--------------

   This method returns a prologue tag, which is meant to be the very first
thing in an HTML document.  It tells the web browser such things as what
version of the HTML standard we are adhering to, version 4.0 in this case.
The prologue tag we make looks like '<!DOCTYPE HTML PUBLIC "-//W3C//DTD
HTML 4.0//EN">'.

comment_tag( TEXT )
-------------------

   This method returns a comment tag, which is only visible to people
viewing the HTML source of a document, and not otherwise.  It can take
either a scalar or a list or an Array ref as its TEXT argument.  If a
single item of text is passed, then a comment tag that looks like "<!-
text ->" is made.  If more than one item of text is passed, then a
multi-line comment is made, which has each item of text on its own line
and indented with a single tab.  The latter is suitable for displaying CSS
or JavaScript code in an elegant manner.

make_html_tag( NAME[, PARAMS[, TEXT[, PART]]] )
-----------------------------------------------

   This method is used internally to do the actual construction of single
html tags.   You can call it directly when you want faster code and/or
more control over how tags are made.  The first argument, NAME, is a
scalar that defines the actual name of the tag we are making (eg: 'br');
it is case-insensitive.  The optional second argument, PARAMS, is a HASH
ref containing attribute names and values for the new tag; the names
(keys) are case-insensitive.  The attribute values are all printed
literally, so they should be scalars.  The optional third argument, TEXT,
is a scalar containing the text that goes between the tag pairs; it is not
a tag attribute.  The optional fourth argument, PART, is a scalar which
indicates we should make just a certain part of the tag; acceptable values
are ['pair', 'start', 'end'], and it is case-insensitive.  This method
knows which HTML tags are normally paired or not, which tag attributes
take specified values or not, and acts accordingly.

make_html_tag_group( NAME[, PARAMS[, TEXT[, LIST]]] )
-----------------------------------------------------

   This method is used internally to do the actual construction of html
tag groups.  You can call it directly when you want faster code and/or
more control over how tags are made.  The first argument, NAME, is a
scalar that defines the actual name of the tag we are making (eg: 'br');
it is case-insensitive.  The optional second argument, PARAMS, is a HASH
ref containing attribute names and values for the new tag; the names
(keys) are case-insensitive.  Any attribute values which are ARRAY refs
are flattened, and the number of tags made is determined by the length of
the longest one.  The optional third argument, TEXT, is a HASH ref (or
scalar) containing the text that goes between the tag pairs; it is not a
tag attribute, but if its an ARRAY ref then its length will influence the
number of tags that are made as the length of tag attribute arrays do.
The optional fourth argument, LIST, is a boolean/scalar which indicates
whether this method returns the new tags in an ARRAY ref (one tag per
element) or as a scalar (tags are concatenated together); a true value
forces an ARRAY ref, scalar is the default.  This method knows which HTML
tags are normally paired or not, which tag attributes take specified
values or not, and acts accordingly.

start_html([ TITLE[, AUTHOR[, META[, STYLE[, HEAD[, BODY]]]]] ])
----------------------------------------------------------------

   This method returns a canned HTML template that is suitable for use as
the top of an HTML page.  It consists of the prologue tag (<!DOCTYPE...),
the opening 'html' tag, the entire 'head' section, and the opening 'body'
tag.  The prologue tag looks the same as that generated by the class
method prologue_tag().  This method can take its optional six arguments in
either named or positional format; in the first case, the names look the
same as the positional placeholders above, except they must be in lower
case.  The first two arguments, TITLE and AUTHOR, are scalars which
respectively define the title and author for the document.  The default
value for TITLE is 'Untitled Document', and a '<LINK REV="made">' tag is
made if AUTHOR is present.  The third argument, META, is a HASH ref
containing name/value pairs of meta information, and a '<META NAME="n"
VALUE="v">' tag is made for each one.  The fourth argument, STYLE, allows
Cascading Style Sheets to be used in the document.  See the method
*css_for_start_html()*, which handles the particulars of this argument.
The fifth argument, HEAD, is an ARRAY ref (or scalar) containing anything
else you would like to appear in the 'head' section; it is flattened and
the elements used as-is.  The sixth argument, BODY, is a HASH ref
containing attributes and values for the opening 'body' tag.

end_html()
----------

   This method returns a canned HTML template that is suitable for use as
the bottom of an HTML page.  It consists of the closing 'body' and 'html'
tags.

css_for_start_html([ SRC[, CODE] ])
-----------------------------------

   This method returns HTML code that allows Cascading Style Sheets to be
used in the document when the code is included in its "head" section.
This method is used by start_html() to handle its STYLE argument.  This
method can take its optional arguments in either named or positional
format; in the first case, the names look the same as the positional
placeholders above, except they must be in lower case.  The first
argument, SRC, is an Array ref (or scalar) whose elements are urls for
external StyleSheet documents that should be linked to by the browser, and
a '<LINK REL="stylesheet" SRC="url">' tag is made for each one.  The
second argument, CODE, is an Array ref (or scalar) whose elements are
lines of StyleSheet code that are to be embedded in the HTML document
itself; a "<STYLE><!- code -></STYLE>" multi-line tag is made for them.
When both arguments are used, the SRC appears first in the new HTML.

COMPATABILITY WITH OTHER MODULES
================================

   The methods of this class and their parameters are designed to be
compatible with any same-named methods in the popular CGI.pm class.  This
class will produce identical or browser-compatible HTML from such methods,
and this class can accept all the same argument formats.  Exceptions to
this include:

  1. None of our methods are exported and must be called using indirect
     notation, whereas CGI.pm can export any of it's methods.

  2. start_html() doesn't support all the same arguments, but those that
     do have the same names.  However, the effects of the missing
     arguments can be easily replicated by making the appropriate tags
     explicitely and handing them in via either the "head" or "body"
     arguments, where appropriate.  The common arguments are ['title',
     'author', 'meta', 'style', 'head', 'body'], in that order.

  3. Our textarea() method is autoloaded, and doesn't have the special
     symantecs that CGI.pm's textarea() does.  However, any module who
     subclasses from this one can override textarea() with one that
     matches CGI.pm's symantecs.  The "HTML::FormMaker" module does this.

  4. Autoloaded methods do not use the presence or absense of arguments to
     decide whether to make the new tag as a pair or as "start only".

  5. Autoloaded methods that make html tags won't concatenate their
     arguments into a single argument under any circumstances, but in some
     cases the "shortcuts" of CGI.pm will do so.

  6. Currently we don't html-escape any argument values passed to our tag
     making functions, whereas CGI.pm sometimes does.  While we expect our
     caller to do the escaping themselves where necessary, we may do it
     later in an update.

  7. We go further to make the generated HTML human-readable by: 1. having
     each new tag start on a new line; 2. making all tag and attribute
     names uppercase; 3.  ensuring that about 20 often-used tag attributes
     always appear in the same order (eg: 'type' is before 'name' is
     before 'value'), and before any others.

AUTHOR
======

   Copyright (c) 1999-2000, Darren R. Duncan. All rights reserved. This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.  However, I do request that this copyright
information remain attached to the file.  If you modify this module and
redistribute a changed version then please attach a note listing the
modifications.

   I am always interested in knowing how my work helps others, so if you
put this module to use in any of your own code then please send me the
URL.  Also, if you make modifications to the module because it doesn't
work the way you need, please send me a copy so that I can roll desirable
changes into the main release.

   Address comments, suggestions, and bug reports to
*perl@DarrenDuncan.net*.

CREDITS
=======

   Thanks very much to *Kevin Werbach* for publishing "The Bare Bones
Guide to HTML", which I found to be an invaluable resource when writing
this module (and at other times as well).  The latest version of the
document is available at *http://werbach.com/barebones/*.

   This quick reference lists all the HTML tags that current browsers are
likely to recognize, including all the elements of the official HTML 4.0
recommendation, and some Netscape and Microsoft extensions as well.
Common attributes for these tags are also included in context, giving a
good idea on how they are used.

   When writing this module, I used the Bare Bones reference to verify the
consistant formatting used by all HTML tags, including how tag attributes
are formatted.  I could see the proper formatting for prologue and comment
tags as well; their formats are unique compared to all the other tags.
The other main uses I had for the document was in determining all the HTML
tags which were not used as a pair (most use pairs, few don't), and for
determining which tag attributes made a positive assertion just by their
presence, without need for any associated values (most have values, few
don't).

   Thanks also to *Lincoln D. Stein* for publishing the popular CGI.pm
module, which I found very useful in my programs.  Moreover, I have
decided to emulate much of its functionality in some of my own modules, so
I should give credit where its due for implementing that functionality
first.  Lincoln should be pleased that I am following his advice (look
under heading "BUGS" in CGI) and discarding his large and monolithic
module in favor of simpler ones.

SEE ALSO
========

   perl(1), CGI, Class::ParamParser.

   FormMagick::Validator - validate data from FormMagick forms

SYNOPSIS
========

   use FormMagick::Validator;

DESCRIPTION
===========

   This module provides some common validation routines.  Validation
routines return the string "OK" if they succeed, or a descriptive message
if they fail.

Validation routines provided:
-----------------------------

nonblank
     The data is not an empty string : `$data ne ""'

number
     The data is a number (strictly speaking, data is a positive number):
     `$data =~ /^[0-9.]+$/'

word
     The data looks like a single word: `$data !~ /\W/'

minlength(n)
     The data is at least n characters long: `length($data) >= $n'

maxlength(n)
     The data is no more than  n characters long: `length($data) <= $n'

exactlength(n)
     The data is exactly  n characters long: `length($data) E== $n'

lengthrange(n,m)
     The data is between  n and c<m> characters long: `length($data) >= $n'
     and `length($data) <= $m'.  =cut

     sub lengthrange { 	my $data = $_[0]; 	my $minlength= $_[1]; 	my
     $maxlength= $_[2]; 	print "min $minlength, max $maxlength";
     if ( ( length($data) >= $minlength ) and (length($data) <=
     $maxlength) ) { 	        return "OK"; 	} else { 		return
     "This field must be between $minlength and $maxlength characters";
     } }

url
     The data looks like a (normalish) URL: `$data =~
     m!(http|ftp)://[\w/.-/)!'

email
     The data looks more or less like an internet email address: `$data =~
     /\@/'

     Note: not fully compliant with the entire gamut of RFC 822 addressing
     ;)

domain_name
     The data looks like an internet domain name or hostname.

ip_number
     The data looks like a valid IP number.

     The data looks like a good, valid username

password
     The data looks like a good password

date
     The data looks like a date.

iso_country_code
     The data is a standard 2-letter ISO country code.  Uses
     Locale::Country to check.

US_state
     The data is a standard 2-letter US state abbreviation.  Uses
     Geography::State in non-strict mode.

US_zipcode
     The data looks like a valid US zipcode

credit_card_type
     The data looks like a valid type of credit card (eg Visa, Mastercard).
     Uses Business::CreditCard.

credit_card_number
     The data looks like a valid credit card number Uses
     Business::CreditCard.

credit_card_expiry
     The data looks like a valid credit card expiry date Uses
     Business::CreditCard.

   These validation routines may be overridden and others may be added on
a per-application basis.  To do this, simply define a subroutine in your
CGI script that works in a similar way and use its name in the VALIDATION
attribute in your XML.

AUTHOR
======

   Kirrily "Skud" Robert <skud@infotrope.net>

   More information about FormMagick may be found at
http://sourceforge.net/projects/formmagick/

read and write fortune (strfile) databases
******************************************

NAME
====

   Fortune - read and write fortune (strfile) databases

SYNOPSIS
========

     # input
     $ffile = new Fortune ($base_filename);
     $ffile->read_header ();
     $num_fortunes = $ffile->num_fortunes ();
     $fortune = $ffile->read_fortune ($num);
     $fortune = $ffile->get_random_fortune ();

     # create header file from data file -- NOT IMPLEMENTED YET
     $ffile = new Fortune ($base_filename);
     $ffile->write_header ();

     # write to data file -- NOT IMPLEMENTED YET
     $ffile = new Fortune (">>$base_filename");
     $ffile->write_fortune ($fortune);

DESCRIPTION
===========

   The `fortune' program is a small but important part of the Unix
culture, and this module aims to provide support for its "fortune cookie"
databases to Perl programmers.  For efficiency, all versions of `fortune'
rely on a binary header consisting mainly of offsets into the fortune file
proper.  Modern versions of fortune keep this header in a separate file,
and this is the style adopted by the `Fortune' module; the older style of
munging the header and data into one large "compiled" file is not
(currently) supported.

   Using the `Fortune' module makes it trivial to write a simplified
version of the `fortune' program:

     # trivial 'fortune' progam
     my $fortune_filename = $ARGV[0];
     my $fortune_file = new Fortune ($fortune_filename);
     $fortune_file->read_header ();
     my $fortune = $fortune_file->get_random_fortune ();
     print $fortune;

   This can be compressed considerably:

     print new Fortune ($ARGV[0])->read_header()->get_random_fortune();

   Of course, this doesn't provide all of `fortune''s interesting
features, such as parallel databases of offensive fortunes, selection of
long or short fortunes, dealing with multiple fortune files, etc.  If you
want `fortune', use it - but if you just want a simple Perl interface to
its data files, the `Fortune' module is for you.

   Currently, the `Fortune' module does not support writing fortune
databases.  If it did, writing a simplified `strfile' (the program that
processes a fortune database to create the header file) would also be
trivial:

     # trivial (and hypothetical) 'strfile' program
     my $fortune_filename = @ARGV[0];
     my $fortune_file = new Fortune ($fortune_filename);
     $fortune_file->write_header ();

   Note that the header filename is assumed to be just the name of the main
fortune database, with `".dat"' appended.  You can supply an alternate
header filename to the constructor, new(), if you wish.

METHODS
=======

Initialization/cleanup
----------------------

new (FILE [, HEADER_FILE])
     Opens a fortune cookie database.  FILE is the name of the data file to
     open, and HEADER_FILE (if given) the name of the header file that
     contains (or will contain) meta-data about the fortune database.  If
     HEADER_FILE is not given, it defaults to FILE with `".dat"' appended.

     The data file is opened via `open_file()', which dies if the file
     cannot be opened.  The header file is not opened, whether you supply
     its filename or not - after all, it might not exist yet.  Rather, you
     must explicitly call `read_header()' or `write_header()' as
     appropriate.

open_file ()
     Opens the fortune file whose name was supplied to the constructor.
     Dies on failure.

close_file ()
     Closes the fortune file if it's open; does nothing otherwise.

Header functions (read and write)
---------------------------------

read_header ()
     Reads the header file associated with this fortune database.  The name
     of the header file is determined by the constructor new: either it is
     based on the name of the data file, or supplied by the caller.

     If the header file does not exist, this function calls
     `compute_header()' automatically, which has the same effect as
     reading the header from a file.

     The header contains the following values, which are stored as
     attributes of the `Fortune' object:

    version
          version number

    `numstr'
          number of strings (fortunes) in the file

    max_length
          length of longest string in the file

    min_length
          length of shortest string in the file

    flags
          bit field for flags (see strfile(1) man page)

    delim
          character that delimits fortunes

     `numstr' is available via the `num_fortunes()' method; if you're
     interested in the others, you'll have to go grubbing through the
     `Fortune' object, e.g.:

          $fortune_file = new Fortune ('fortunes');
          $fortune_file->read_header ();
          $delim = $fortune_file->{'delim'};

     `read_header()' dies if there are any problems reading the header
     file, e.g. if it seems to be corrupt or truncated.

     `read_header()' returns the current `Fortune' object, to allow for
     sneaky one-liners (see the examples above).

compute_header ([DELIM])
     Reads the contents of the fortune file and computes the header
     information that would normally be found in a header (`.dat') file.
     This is useful if you maintain a file of fortunes by hand and do not
     have the corresponding data file.

     An optional delimiter argument may be passed to this function; if
     present, that delimiter will be used to separate entries in the
     fortune file.  If not provided, the existing delim attribute of the
     Fortune object will be used.  If that is not defined, then a percent
     sign ("%") will be used.

num_fortunes ()
     Returns the number of fortunes found by `read_header()'.

write_header ([DELIM])
     is not yet implemented.

Fortune input
-------------

get_fortune (NUM)
     Reads string number NUM from the open fortune file.  NUM is
     zero-based, ie. it must be between 0 and `num_fortunes()-1'
     (inclusive).  croaks if you haven't opened the file and read the
     header, or if NUM is out of range.  (Opening the file is pretty hard
     to screw up, since it's taken care of for you by the constructor, but
     you have to read the header explicitly with `read_header()'.)
     Returns the text of the fortune as a (possibly) multiline string.

get_random_fortune ()
     Picks a random fortune for you and reads it with `read_fortune()'.

Fortune output
--------------

write_fortune (FORTUNE)
     is not yet implemented.

AUTHOR AND COPYRIGHT
====================

   Written by Greg Ward <gward@python.net>, 20 February 1999.

   Copyright (c) 1999-2000 Gregory P. Ward. All rights reserved.  This is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

AVAILABILITY
============

   You can download the `Fortune' module from my web page:

     http://starship.python.net/~gward/perl/

   and it can also be found on CPAN.

   If you are using an operating system lacking a sufficient sense of
humour to include `fortune' as part of its standard installation (most
commercial Unices seem to be so afflicted), the Linux world has a
solution: the `fortune-mod' distribution.  The latest version as of this
writing is `fortune-mod-9708', and the README file says you can find it at

     http://www.progsoc.uts.edu.au/~dbugger/hacks/hacks.html

   This is the `fortune' implementation on which the `Fortune' module is
based.

converting Perl structures to strings and back.
***********************************************

NAME
====

   FreezeThaw - converting Perl structures to strings and back.

SYNOPSIS
========

     use FreezeThaw qw(freeze thaw cmpStr safeFreeze cmpStrHard);
     $string = freeze $data1, $data2, $data3;
     ...
     ($olddata1, $olddata2, $olddata3) = thaw $string;
     if (cmpStr($olddata2,$data2) == 0) {print "OK!"}

DESCRIPTION
===========

   Converts data to/from stringified form, appropriate for
saving-to/reading-from permanent storage.

   Deals with objects, circular lists, repeated appearence of the same
refence. Does not deal with overloaded stringify operator yet.

EXPORT
======

Default
     None.

Exportable
     `freeze thaw cmpStr cmpStrHard safeFreeze'.

User API
========

`cmpStr'
     analogue of cmp for data. Takes two arguments and compares them as
     separate entities.

`cmpStrHard'
     analogue of cmp for data. Takes two arguments and compares them
     considered as a group.

`freeze'
     returns a string that encupsulates its arguments (considered as a
     group). `thaw'ing this string leads to a fatal error if arguments to
     `freeze' contained references to `GLOB's and CODEs.

`safeFreeze'
     returns a string that encupsulates its arguments (considered as a
     group). The result is `thaw'able in the same process. `thaw'ing the
     result in a different process should result in a fatal error if
     arguments to `safeFreeze' contained references to `GLOB's and CODEs.

`thaw'
     takes one string argument and returns an array. The elements of the
     array are "equivalent" to arguments of the `freeze' command that
     created the string. Can result in a fatal error (see above).

Developer API
=============

   `FreezeThaw' `freeze's and `thaw's data blessed in some package by
calling methods `Freeze' and `Thaw' in the package. The fallback methods
are provided by the `FreezeThaw' itself. The fallback `Freeze' freezes the
"content" of blessed object (from Perl point of view). The fallback `Thaw'
blesses the `thaw'ed data back into the package.

   So the package needs to define its own methods only if the fallback
methods will fail (for example, for a lot of data the "content" of an
object is an address of some C data). The methods are called like

     $newcooky = $obj->Freeze($cooky);
     $obj = Package->Thaw($content,$cooky);

   To save and restore the data the following method are applicable:

     $cooky->FreezeScalar($data,$ignorePackage,$noduplicate);

   during Freeze()ing, and

     $data = $cooky->ThawScalar;

   Two optional arguments $ignorePackage and $noduplicate regulate whether
the freezing should not call the methods even if $data is a reference to a
blessed object, and whether the data should not be marked as seen already
even if it was seen before. The default methods

     sub UNIVERSAL::Freeze {
       my ($obj, $cooky) = (shift, shift);
       $cooky->FreezeScalar($obj,1,1);
     }

     sub UNIVERSAL::Thaw {
       my ($package, $cooky) = (shift, shift);
       my $obj = $cooky->ThawScalar;
       bless $obj, $package;
     }

   call the `FreezeScalar' method of the $cooky since the freezing engine
will see the data the second time during this call. Indeed, it is the
freezing engine who calls UNIVERSAL::Freeze(), and it calls it because it
needs to freeze $obj. The above call to $cooky->FreezeScalar() handles the
same data back to engine, but because flags are different, the code does
not cycle.

   Freezing and thawing $cooky also allows the following additional
methods:

     $cooky->isSafe;

   to find out whether the current freeze was initiated by `freeze' or
`safeFreeze' command. Analogous method for thaw $cooky returns whether the
current thaw operation is considered safe (i.e., either does not contain
cached elsewhere data, or comes from the same application). You can use

     $cooky->makeSafe;

   to prohibit cached data for the duration of the rest of freezing or
thawing of current object.

   Two methods

     $value = $cooky->repeatedOK;
     $cooky->noRepeated;		# Now repeated are prohibited

   allow to find out/change the current setting for allowing repeated
references.

   If you want to flush the cache of saved objects you can use

     FreezeThaw->flushCache;

   this can invalidate some frozen string, so that thawing them will
result in fatal error.

Instantiating
-------------

   Sometimes, when an object from a package is recreated in presense of
repeated references, it is not safe to recreate the internal structure of
an object in one step. In such a situation recreation of an object is
carried out in two steps: in the first the object is `allocate'd, in the
second it is `instantiate'd.

   The restriction is that during the *allocation* step you cannot use any
reference to any Perl object that can be referenced from any other place.
This restriction is applied since that object may not exist yet.

   Correspondingly, during *instantiation* step the previosly *allocated*
object should be `filled', i.e., it can be changed in any way such that
the references to this object remain valid.

   The methods are called like this:

     $pre_object_ref = Package->Allocate($pre_pre_object_ref);
     	# Returns reference
     Package->Instantiate($pre_object_ref,$cooky);
     	# Converts into reference to blessed object

   The reverse operations are

     $object_ref->FreezeEmpty($cooky);
     $object_ref->FreezeInstance($cooky);

   during these calls object can `freezeScalar' some information (in a
usual way) that will be used during `Allocate' and `Instantiate' calls
(via `thawScalar'). Note that the return value of `FreezeEmpty' is cached
during the phase of creation of uninialized objects. This must be used
like this: the return value is the reference to the created object, so it
is not destructed until other objects are created, thus the frozen values
of the different objects will not share the same references. Example of
bad result:

     $o1->FreezeEmpty($cooky)

   freezes `{}', and `$o2->FreezeEmpty($cooky)' makes the same. Now nobody
guaranties that that these two copies of `{}' are different, unless a
reference to the first one is preserved during the call to
`$o2->FreezeEmpty($cooky)'. If `$o1->FreezeEmpty($cooky)' returns the
value of `{}' it uses, it will be preserved by the engine.

   The helper function `FreezeThaw::copyContents' is provided for
simplification of instantiation. The syntax is

     FreezeThaw::copyContents $to, $from;

   The function copies contents the object $from point to into what the
object $to points to (including package for blessed references). Both
arguments should be references.

   The default methods are provided. They do the following:

`FreezeEmpty'
     Freezes an empty object of underlying type.

`FreezeInstance'
     Calls `Freeze'.

`Allocate'
     Thaws what was frozen by `FreezeEmpty'.

`Instantiate'
     Thaws what was frozen by `FreezeInstance', uses `copyContents' to
     transfer this to the $pre_object.

BUGS and LIMITATIONS
====================

   A lot of objects are blessed in some obscure packages by XSUB typemaps.
It is not clear how to (automatically) prevent the UNIVERSAL methods to be
called for objects in these packages.

   The objects which can survive freeze()/thaw() cycle must also survive a
change of a "member" to an equal member.  Say, after

     $a = [a => 3];
     $a->{b} = \ $a->{a};

   $a satisfies

     $a->{b} == \ $a->{a}

   This property will be broken by freeze()/thaw(), but it is also broken
by

     $a->{a} = delete $a->{a};

issue Frontier XML RPC requests to a server
*******************************************

NAME
====

   Frontier::Client - issue Frontier XML RPC requests to a server

SYNOPSIS
========

     use Frontier::Client;

     $server = Frontier::Client->new( I<OPTIONS> );

     $result = $server->call($method, @args);

     $boolean = $server->boolean($value);
     $date_time = $server->date_time($value);
     $base64 = $server->base64($value);

     $value = $boolean->value;
     $value = $date_time->value;
     $value = $base64->value;

DESCRIPTION
===========

   *Frontier::Client* is an XML-RPC client over HTTP.  *Frontier::Client*
instances are used to make calls to XML-RPC servers and as shortcuts for
creating XML-RPC special data types.

METHODS
=======

new( OPTIONS )
     Returns a new instance of *Frontier::Client* and associates it with
     an XML-RPC server at a URL.  OPTIONS may be a list of key, value
     pairs or a hash containing the following parameters:

    url
          The URL of the server.  This parameter is required.  For example:

               $server = Frontier::Client->new( 'url' => 'http://betty.userland.com/RPC2' );

    proxy
          A URL of a proxy to forward XML-RPC calls through.

    encoding
          The XML encoding to be specified in the XML declaration of
          outgoing RPC requests.  Incoming results may have a different
          encoding specified; XML::Parser will convert incoming data to
          UTF-8.  The default outgoing encoding is none, which uses XML
          1.0's default of UTF-8.  For example:

               $server = Frontier::Client->new( 'url' => 'http://betty.userland.com/RPC2',
                                                'encoding' => 'ISO-8859-1' );

    use_objects
          If set to a non-zero value will convert incoming <i4>, <float>,
          and <string> values to objects instead of scalars.  See int(),
          float(), and string() below for more details.

    debug
          If set to a non-zero value will print the encoded XML request
          and the XML response received.

call($method, @args)
     Forward a procedure call to the server, either returning the value
     returned by the procedure or failing with exception.  ``$method'' is
     the name of the server method, and ``@args'' is a list of arguments
     to pass.  Arguments may be Perl hashes, arrays, scalar values, or the
     XML-RPC special data types below.

boolean( $value )
date_time( $value )

base64( $base64 )
     The methods ``boolean()'', ``date_time()'', and ``base64()'' create
     and return XML-RPC-specific datatypes that can be passed to `call()'.
     Results from servers may also contain these datatypes.  The
     corresponding package names (for use with ``ref()'', for example) are
     ``Frontier::RPC2::Boolean'', ``Frontier::RPC2::DateTime::ISO8601'',
     and ``Frontier::RPC2::Base64''.

     The value of boolean, date/time, and base64 data can be set or
     returned using the `value()' method.  For example:

          # To set a value:
          $a_boolean->value(1);

          # To retrieve a value
          $base64 = $base64_xml_rpc_data->value();

     Note: ``base64()'' does not encode or decode base64 data for you, you
     must use MIME::Base64 or similar module for that.

int( 42 );
float( 3.14159 );
string( "Foo" );
     By default, you may pass ordinary Perl values (scalars) to be encoded.
     RPC2 automatically converts them to XML-RPC types if they look like an
     integer, float, or as a string.  This assumption causes problems when
     you want to pass a string that looks like "0096", RPC2 will convert
     that to an <i4> because it looks like an integer.  With these
     methods, you could now create a string object like this:

          $part_num = $server->string("0096");

     and be confident that it will be passed as an XML-RPC string.  You can
     change and retrieve values from objects using value() as described
     above.

SEE ALSO
========

   perl(1), Frontier::RPC2(3)

   <http://www.scripting.com/frontier5/xml/code/rpc.html>

AUTHOR
======

   Ken MacLeod <ken@bitsko.slc.ut.us>

receive Frontier XML RPC requests
*********************************

NAME
====

   Frontier::Daemon - receive Frontier XML RPC requests

SYNOPSIS
========

     use Frontier::Daemon;

     Frontier::Daemon->new(methods => {
         'rpcName' => \&sub_name,
            ...
         });

DESCRIPTION
===========

   *Frontier::Daemon* is an HTTP/1.1 server that listens on a socket for
incoming requests containing Frontier XML RPC2 method calls.
*Frontier::Daemon* is a subclass of *HTTP::Daemon*, which is a subclass of
IO::Socket::INET.

   *Frontier::Daemon* takes a `methods' parameter, a hash that maps an
incoming RPC method name to reference to a subroutine.

SEE ALSO
========

   perl(1), HTTP::Daemon(3), IO::Socket::INET(3), Frontier::RPC2(3)

   <http://www.scripting.com/frontier5/xml/code/rpc.html>

AUTHOR
======

   Ken MacLeod <ken@bitsko.slc.ut.us>

encode/decode RPC2 format XML
*****************************

NAME
====

   Frontier::RPC2 - encode/decode RPC2 format XML

SYNOPSIS
========

     use Frontier::RPC2;

     $coder = Frontier::RPC2->new;

     $xml_string = $coder->encode_call($method, @args);
     $xml_string = $coder->encode_response($result);
     $xml_string = $coder->encode_fault($code, $message);

     $call = $coder->decode($xml_string);

     $response_xml = $coder->serve($request_xml, $methods);

     $boolean_object = $coder->boolean($boolean);
     $date_time_object = $coder->date_time($date_time);
     $base64_object = $coder->base64($base64);
     $int_object = $coder->int(42);
     $float_object = $coder->float(3.14159);
     $string_object = $coder->string("Foo");

DESCRIPTION
===========

   *Frontier::RPC2* encodes and decodes XML RPC calls.

$coder = Frontier::RPC2->new( OPTIONS )
     Create a new encoder/decoder.  The following option is supported:

    encoding
          The XML encoding to be specified in the XML declaration of
          encoded RPC requests or responses.  Decoded results may have a
          different encoding specified; XML::Parser will convert decoded
          data to UTF-8.  The default encoding is none, which uses XML
          1.0's default of UTF-8.  For example:

               $server = Frontier::RPC2->new( 'encoding' => 'ISO-8859-1' );

    use_objects
          If set to a non-zero value will convert incoming <i4>, <float>,
          and <string> values to objects instead of scalars.  See int(),
          float(), and string() below for more details.

$xml_string = $coder->encode_call($method, @args)
     ``encode_call'' converts a method name and it's arguments into an
     RPC2 ``methodCall'' element, returning the XML fragment.

$xml_string = $coder->encode_response($result)
     ``encode_response'' converts the return value of a procedure into an
     RPC2 ``methodResponse'' element containing the result, returning the
     XML fragment.

$xml_string = $coder->encode_fault($code, $message)
     ``encode_fault'' converts a fault code and message into an RPC2
     ``methodResponse'' element containing a `fault' element, returning
     the XML fragment.

$call = $coder->decode($xml_string)
     `decode' converts an XML string containing an RPC2 ``methodCall'' or
     ``methodResponse'' element into a hash containing three members,
     `type', `value', and ``method_name''.  `type' is one of `call',
     `response', or `fault'.  `value' is array containing the parameters
     or result of the RPC.  For a `call' type, `value' contains call's
     parameters and ``method_name'' contains the method being called.  For
     a `response' type, the `value' array contains call's result.  For a
     `fault' type, the `value' array contains a hash with the two members
     ``faultCode'' and ``faultMessage''.

$response_xml = $coder->serve($request_xml, $methods)
     ``serve'' decodes ``$request_xml'', looks up the called method name
     in the ``$methods'' hash and calls it, and then encodes and returns
     the response as XML.

$boolean_object = $coder->boolean($boolean);
$date_time_object = $coder->date_time($date_time);

$base64_object = $coder->base64($base64);
     These methods create and return XML-RPC-specific datatypes that can be
     passed to the encoder.  The decoder may also return these datatypes.
     The corresponding package names (for use with ``ref()'', for example)
     are ``Frontier::RPC2::Boolean'',
     ``Frontier::RPC2::DateTime::ISO8601'', and ``Frontier::RPC2::Base64''.

     You can change and retrieve the value of boolean, date/time, and
     base64 data using the `value' method of those objects, i.e.:

          $boolean = $boolean_object->value;

          $boolean_object->value(1);

$int_object = $coder->int(42);
$float_object = $coder->float(3.14159);
$string_object = $coder->string("Foo");
     By default, you may pass ordinary Perl values (scalars) to be encoded.
     RPC2 automatically converts them to XML-RPC types if they look like an
     integer, float, or as a string.  This assumption causes problems when
     you want to pass a string that looks like "0096", RPC2 will convert
     that to an <i4> because it looks like an integer.  With these
     methods, you could now create a string object like this:

          $part_num = $coder->string("0096");

     and be confident that it will be passed as an XML-RPC string.  You can
     change and retrieve values from objects using value() as described
     above.

SEE ALSO
========

   perl(1), Frontier::Daemon(3), Frontier::Client(3)

   <http://www.scripting.com/frontier5/xml/code/rpc.html>

AUTHOR
======

   Ken MacLeod <ken@bitsko.slc.ut.us>

Add callbacks to existing functions.
************************************

NAME
====

   Function::Override - Add callbacks to existing functions.

SYNOPSIS
========

     use Function::Override;
     use Croak;

     BEGIN {
          override('open',
                   sub {
                       my $wantarray = (caller(1))[5];
                       carp "You didn't check if open() succeeded"
                           unless defined $wantarray;
                   }
                  );
     }

     open(FILE, $filename);      # This produces a warning now.
     print <FILE>;
     close FILE;

DESCRIPTION
===========

   ** THIS IS ALPHA CODE! **

   Function::Override provides a way to conveniently add code to existing
functions.

   You may wrap both user-defined functions and overridable CORE operators
in this way.  Although if you override a CORE function its usually wise to
do it in a BEGIN block so Perl will see it.

TODO
====

   Add a more flexible callback system offering pre and post function
routines.

   Offer more information to the callback, such as the subroutine name.

   Merge Fatal.pm and possiblely Memoize.pm.

ENVIRONMENT
===========

PERL_FUNCTION_OVERRIDE_DEBUG
     If true, this flag turns on debugging output.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com> but its really 99.99% Fatal.pm by
Lionel.Cons@cern.ch

SEE ALSO
========

   See Fatal,

a module which makes Perl slightly more functional (think Haskell)
******************************************************************

NAME
====

   Functional - a module which makes Perl slightly more functional (think
Haskell)

SYNOPSIS
========

     use Functional;
     print 'The first ten primes are: ',
       show(take(10, filter("prime", integers))), "\n";

DESCRIPTION
===========

   Perl already contains some functional-like functions, such as map and
grep. The purpose of this module is to add other functional-like functions
to Perl, such as foldl and foldr, as well as the use of infinite lists.

   Think as to how you would express the first ten prime numbers in a
simple way in your favourite programming language? So the example in the
synopsis is a killer app, if you will (until I think up a better one ;-).

   The idea is mostly based on Haskell, from which most of the functions
are taken. There are a couple of major omissions: currying and types.
Lists (and tuples) are simply Perl list references, none of this 'cons'
business, and strings are simple strings, not lists of characters.

   The idea is to make Perl slightly more functional, rather than
completely replace it. Hence, this slots in very well with whatever else
your program may be doing, and is very Perl-ish. Other modules are
expected to try a much more functional approach.

FUNCTIONS
=========

   The following functions are available. (Note: these should not be
called as methods).

   In each description, I shall give the Haskell definition (if I think it
would help) as well as a useful example.

show
     Show returns a string representation of an object.  It does not like
     infinite lists.

inc k
     Increases the value passed by 1. eg: inc(2) = 3.  In Haskell:

          inc          :: a -> a
          inc k         = 1 + k

double k
     Doubles the passed value. eg: double(3) = 6.  In Haskell:

          double         :: a -> a
          double k        = k * 2

square k
     Returns the square of the passed value. eg: square(3) = 9.  In
     Haskell:

          square          :: a -> a
          square k         = 1 + k

gcd x y
     Returns the greatest common denominator of two numbers. eg: gcd(144,
     1024) = 16. In Haskell:

          gcd :: Integral a => a -> a -> a
          gcd 0 0 = error "gcd 0 0 is undefined"
          gcd x y = gcd' (abs x) (abs y)
                    where gcd' x 0 = x
                    gcd' x y = gcd' y (x `rem` y)

lcm x y
     Returns the lowest common multiple of two numbers.  eg: lcm(144,
     1024) = 9216. In Haskell:

          lcm            :: (Integral a) => a -> a -> a
          lcm _ 0         = 0
          lcm 0 _         = 0
          lcm x y         = abs ((x `quot` gcd x y) * y)

id x
     The identity function - simply returns the argument.  eg: id([1..6])
     = [1, 2, 3, 4, 5, 6]. In Haskell:

          id             :: a -> a
          id x            = x

const k _
     Returns the first argument of 2 arguments.  eg: const(4, 5) = 4. In
     Haskell:

          const          :: a -> b -> a
          const k _       = k

flip f
     Given a function, flips the two arguments it is passed.  Note that
     this returns a CODEREF, as currying does not yet happen. eg: flip(sub
     { $_[0] ** $_[1] })->(2, 3) = 9.  In Haskell (ie this is what it
     should really do):

          flip           :: (a -> b -> c) -> b -> a -> c
          flip f x y      = f y x

Until p f x
     Keep on applying f to x until p(x) is true, and then return x at that
     point. eg: Until(sub { $_[0] % 10 == 0 }, "inc", 1) = 10. In Haskell:

          until          :: (a -> Bool) -> (a -> a) -> a -> a
          until p f x     = if p x then x else until p f (f x)

fst x:xs
     Returns the first element in a tuple.  eg: fst([1, 2]) = 1. In
     Haskell:

          fst            :: (a,b) -> a
          fst (x,_)       = x

snd x:y:xs
     Returns the second element in a tuple.  eg: snd([1, 2]) = 2. In
     Haskell:

          snd            :: (a,b) -> a
          snd (_,y)       = y

head xs
     Returns the head (first element) of a list.  eg: head([1..6]) = 1. In
     Haskell:

          head             :: [a] -> a
          head (x:_)        = x

Last xs
     Returns the last element of a list. Note the capital L, to make it
     distinct from the Perl 'last' command. eg: Last([1..6]) = 6. In
     Haskell:

          last             :: [a] -> a
          last [x]          = x
          last (_:xs)       = last xs

tail xs
     Returns a list minus the first element (head).  eg: tail([1..6]) =
     [2, 3, 4, 5, 6]. In Haskell:

          tail             :: [a] -> [a]
          tail (_:xs)       = xs

init xs
     Returns a list minus its last element.  eg: init([1..6]) = [1, 2, 3,
     4, 5]. In Haskell:

          init             :: [a] -> [a]
          init [x]          = []
          init (x:xs)       = x : init xs

null xs
     Returns whether or not the list is empty. eg: null([1, 2]) = False.
     In Haskell:

          null             :: [a] -> Bool
          null []           = True
          null (_:_)        = False

Map f xs
     Evaluates f for each element of the list xs and returns the list
     composed of the results of each such evaluation. It is very similar to
     the Perl command 'map', hence the capital M, but also copes with
     infinite lists. eg: Map("double", [1..6]) = [2, 4, 6, 8, 10, 12].  In
     Haskell:

          map              :: (a -> b) -> [a] -> [b]
          map f xs          = [ f x | x <- xs ]

filter p xs
     Returns the list of the elements in xs for which p(xs) returns true.
     It is similar to the Perl command 'grep', but it also copes with
     infinite lists.  eg: filter("even", [1..6]) = [2, 4, 6]. In Haskell:

          filter           :: (a -> Bool) -> [a] -> [a]
          filter p xs       = [ x | x <- xs, p x ]

concat
     Concatenates lists together into one list. eg: concat([[1..3],
     [4..6]]) = [1, 2, 3, 4, 5, 6]. In Haskell:

          concat           :: [[a]] -> [a]
          concat            = foldr (++) []

     TODO: Make sure this works with infinite lists!

Length
     Returns the length of a list - only do this with finite lists! eg:
     Length([1..6]) = 6. In Haskell:

     length           :: [a] -> Int length            = foldl' (\n _ -> n
     + 1) 0

     TODO Make sure this works!

foldl f z xs
     Applies function f to the pairs (z, xs[0]), (f(z, xs[0], xs[1]),
     (f(f(z, xs[0], xs[1])), xs[2]) and so on. ie it folds from the left
     and returns the last value.  Note that foldl should not be done to
     infinite lists. eg: the following returns the sum of 1..6: foldl(sub
     { $_[0] + $_[1] }, 0, [1..6]) = 21.  In Haskell:

          foldl            :: (a -> b -> a) -> a -> [b] -> a
          foldl f z []      = z
          foldl f z (x:xs)  = foldl f (f z x) xs

foldl1 f xs
     This is a variant of foldl where the first value of xs is taken as z.
     Applies function f to the pairs (xs[0], xs[1]), (f(xs[0], xs[1],
     xs[2]), (f(f(xs[0], xs[1], xs[2])), xs[3]) and so on. ie it folds
     from the left and returns the last value.  Note that foldl should not
     be done to infinite lists. eg: the following returns the sum of 1..6:
     foldl1(sub { $_[0] + $_[1] }, [1..6]) = 21.  In Haskell:

          foldl1           :: (a -> a -> a) -> [a] -> a
          foldl1 f (x:xs)   = foldl f x xs

scanl f q xs
     Returns a list of all the intermedia values that foldl would compute.
     ie returns the list z, f(z, xs[0]), f(f(z, xs[0]), xs[1]), f(f(f(z,
     xs[0]), xs[1]), xs[2]) and so on.  eg: scanl(sub { $_[0] + $_[1] },
     0, [1..6]) = [0, 1, 3, 6, 10, 15, 21].  In Haskell:

          scanl        :: (a -> b -> a) -> a -> [b] -> [a]
          scanl f q xs  = q : (case xs of
                               []   -> []
                               x:xs -> scanl f (f q x) xs)

scanl1 f xs
     This is a variant of scanl where the first value of xs is taken as q.
     Returns a list of all the intermedia values that foldl would compute.
     ie returns the list f(xs[0], xs[1]), f(f(xs[0], xs[1]), xs[2]),
     f(f(f(xs[0], xs[1]), xs[2]), xs[3]) and so on.  eg: scanl1(sub {
     $_[0] + $_[1] }, [1..6]) = [1, 3, 6, 10, 15, 21].  In Haskell:

          scanl1           :: (a -> a -> a) -> [a] -> [a]
          scanl1 f (x:xs)   = scanl f x xs

foldr f z xs
     This is similar to foldl but is folding from the right instead of the
     left.  Note that foldr should not be done to infinite lists.  eg: the
     following returns the sum of 1..6: foldl(sub { $_[0] + $_[1] }, 0,
     [1..6]) = 21.  In Haskell:

          foldr            :: (a -> b -> b) -> b -> [a] -> b
          foldr f z []      = z
          foldr f z (x:xs)  = f x (foldr f z xs)

foldr1 f xs
     This is similar to foldr1 but is folding from the right instead of
     the left. Note that foldr1 should not be done on infinite lists.  eg:
     foldr1(sub { $_[0] + $_[1] }, [1..6]) = 21.  In Haskell:

          foldr1           :: (a -> a -> a) -> [a] -> a
          foldr1 f [x]      = x
          foldr1 f (x:xs)   = f x (foldr1 f xs)

scanr f z xs
     This is similar to scanl but is scanning and folding from the right
     instead of the left. Note that scanr should not be done on infinite
     lists. eg: scanr(sub { $_[0] + $_[1] }, 0, [1..6]) = [0, 6, 11, 15,
     18, 20, 21].  In Haskell:

          scanr            :: (a -> b -> b) -> b -> [a] -> [b]
          scanr f q0 []     = [q0]
          scanr f q0 (x:xs) = f x q : qs
                              where qs@(q:_) = scanr f q0 xs

scanr1 f xs
     This is similar to scanl1 but is scanning and folding from the right
     instead of the left. Note that scanr1 should not be done on infinite
     lists. eg: scanr1(sub { $_[0] + $_[1] }, [1..6]) = [6, 11, 15, 18,
     20, 21].  In Haskell:

          scanr1           :: (a -> a -> a) -> [a] -> [a]
          scanr1 f [x]      = [x]
          scanr1 f (x:xs)   = f x q : qs
                              where qs@(q:_) = scanr1 f xs

iterate f x
     This returns the infinite list (x, f(x), f(f(x)), f(f(f(x)))...) and
     so on. eg: take(8, iterate(sub { $_[0]*2 }, 1)) = [1, 2, 4, 8, 16,
     32, 64, 128].  In Haskell:

          iterate          :: (a -> a) -> a -> [a]
          iterate f x       = x : iterate f (f x)

repeat x
     This returns the infinite list where all elements are x. eg: take(4,
     repeat(42)) = [42, 42, 42, 42].  In Haskell:

          repeat           :: a -> [a]
          repeat x          = xs where xs = x:xs

replicate n x
     Returns a list containing n times the element x.  eg: replicate(5, 1)
     = [1, 1, 1, 1, 1]. In Haskell:

          replicate        :: Int -> a -> [a]
          replicate n x     = take n (repeat x)

take n xs
     Returns a list containing the first n elements from the list xs.  eg:
     take(2, [1..6]) = [1, 2]. In Haskell:

          take                :: Int -> [a] -> [a]
          take 0 _             = []
          take _ []            = []
          take n (x:xs) | n>0  = x : take (n-1) xs
          take _ _             = error "Prelude.take: negative argument"

drop n xs
     Returns a list containing xs with the first n elements missing. eg:
     drop(2, [1..6]) = [3, 4, 5, 6].  In Haskell:

          drop                :: Int -> [a] -> [a]
          drop 0 xs            = xs
          drop _ []            = []
          drop n (_:xs) | n>0  = drop (n-1) xs
          drop _ _             = error "Prelude.drop: negative argument"

splitAt n xs
     Splits the list xs into two lists at element n. eg: splitAt(2,
     [1..6]) = [[1, 2], [3, 4, 5, 6]].  In Haskell:

          splitAt               :: Int -> [a] -> ([a], [a])
          splitAt 0 xs           = ([],xs)
          splitAt _ []           = ([],[])
          splitAt n (x:xs) | n>0 = (x:xs',xs'') where (xs',xs'') = splitAt (n-1) xs
          splitAt _ _            = error "Prelude.splitAt: negative argument"

takeWhile p xs
     Takes elements from xs while p(that element) is true. Returns the
     list. eg: takeWhile(sub { $_[0] <= 4 }, [1..6]) = [1, 2, 3, 4].  In
     Haskell:

          takeWhile           :: (a -> Bool) -> [a] -> [a]
          takeWhile p []       = []
          takeWhile p (x:xs)
                   | p x       = x : takeWhile p xs
                   | otherwise = []

dropWhile p xs
     Drops elements from the head of xs while p(that element) is true.
     Returns the list. eg: dropWhile(sub { $_[0] <= 4 }, [1..6]) = [5, 6].
     In Haskell:

          dropWhile           :: (a -> Bool) -> [a] -> [a]
          dropWhile p []       = []
          dropWhile p xs@(x:xs')
                   | p x       = dropWhile p xs'
                   | otherwise = xs

span p xs
     Splits xs into two lists, the first containing the first few elements
     for which p(that element) is true. eg: span(sub { $_[0] <= 4 },
     [1..6]) = [[1, 2, 3, 4], [5, 6]].  In Haskell:

          span                :: (a -> Bool) -> [a] -> ([a],[a])
          span p []            = ([],[])
          span p xs@(x:xs')
                   | p x       = (x:ys, zs)
                   | otherwise = ([],xs)
                                 where (ys,zs) = span p xs'

break p xs
     Splits xs into two lists, the first containing the first few elements
     for which p(that element) is false. eg: break(sub { $_[0] >= 4 },
     [1..6]) = [[1, 2, 3], [4, 5, 6]].  In Haskell:

          break         :: (a -> Bool) -> [a] -> ([a],[a])
          break p        = span (not . p)

lines s
     Breaks the string s into multiple strings, split at line boundaries.
     eg: lines("A\nB\nC") = ['A', 'B', 'C'].  In Haskell:

          lines     :: String -> [String]
          lines ""   = []
          lines s    = let (l,s') = break ('\n'==) s
                       in l : case s' of []      -> []
                                         (_:s'') -> lines s''

words s
     Breaks the string s into multiple strings, split at whitespace
     boundaries. eg: words("hey how random") = ['hey', 'how', 'random'].
     In Haskell:

          words     :: String -> [String]
          words s    = case dropWhile isSpace s of
                            "" -> []
                            s' -> w : words s''
                                  where (w,s'') = break isSpace s'

unlines xs
     Does the opposite of unlines, that is: joins multiple strings into
     one, joined by newlines. eg: unlines(['A', 'B', 'C']) = "A\nB\nC"; In
     Haskell:

          unlines   :: [String] -> String
          unlines    = concatMap (\l -> l ++ "\n")

     (note that strings in Perl are not lists of characters, so this
     approach will not actually work...)

unwords ws
     Does the opposite of unwords, that is: joins multiple strings into
     one, joined by a space. eg: unwords(["hey","how","random"]) = 'hey
     how random'.  In Haskell:

          unwords   :: [String] -> String
          unwords [] = []
          unwords ws = foldr1 (\w s -> w ++ ' ':s) ws

Reverse xs
     Returns a list containing the elements of xs in reverse order. Note
     the capital R, so as not to clash with the Perl command 'reverse'.
     You should not try to Reverse an infinite list.  eg: Reverse([1..6])
     = [6, 5, 4, 3, 2, 1]. In Haskell:

          reverse   :: [a] -> [a]
          reverse    = foldl (flip (:)) []

And xs
     Returns true if all the elements in xs are true. Returns false
     otherwise. Note the capital A, so as not to clash with the Perl
     command 'and'. You should not try to And an infinite list (unless you
     expect it to fail, as it will short-circuit).  eg: And([1, 1, 1]) = 1.
     In Haskell:

          and       :: [Bool] -> Bool
          and        = foldr (&&) True

Or xs
     Returns true if one of the elements in xs is true. Returns false
     otherwise. Note the capital O, so as not to clash with the Perl
     command 'or'. You may try to Or an infinite list as it will
     short-circuit (unless you expect it to fail, that is). eg: Or([0, 0,
     1]) = 1. In Haskell:

          or        :: [Bool] -> Bool
          or         = foldr (||) False

any p xs
     Returns true if one of p(each element of xs) are true. Returns false
     otherwise. You should not try to And an infinite list (unless you
     expect it to fail, as it will short-circuit).  eg: any("even", [1, 2,
     3]) = 1.  In Haskell:

          any       :: (a -> Bool) -> [a] -> Bool
          any p      = or  . map p

all p xs
     Returns true if all of the p(each element of xs) is true. Returns
     false otherwise. You may try to Or an infinite list as it will
     short-circuit (unless you expect it to fail, that is). eg: all("odd",
     [1, 1, 3]) = 1. In Haskell:

          all  :: (a -> Bool) -> [a] -> Bool
          all p      = and . map p

elem x xs
     Returns true is x is present in xs.  You probably should not do this
     with infinite lists.  Note that this assumes x and xs are numbers.
     eg: elem(2, [1, 2, 3]) = 1.  In Haskell:

          elem             :: Eq a => a -> [a] -> Bool
          elem              = any . (==)

notElem x xs
     Returns true if x is not present in x. You should not do this with
     infinite lists. Note that this assumes that x and xs are numbers.

          notElem          :: Eq a => a -> [a] -> Bool
          notElem           = all . (/=)

lookup key xys
     This returns the value of the key in xys, where xys is a list of key,
     value pairs. It returns undef if the key was not found. You should
     not do this with infinite lists. Note that this assumes that the keys
     are strings. eg: lookup(3, [1..6]) = 4.  In Haskell:

          lookup           :: Eq a => a -> [(a,b)] -> Maybe b
          lookup k []       = Nothing
          lookup k ((x,y):xys)
                | k==x      = Just y
                | otherwise = lookup k xys

minimum xs
     Returns the minimum value in xs.  You should not do this with a
     infinite list.  eg: minimum([1..6]) = 1. In Haskell:

          minimum          :: Ord a => [a] -> a
          minimum           = foldl1 min

maximum xs
     Returns the maximum value in xs.  You should not do this with an
     infinite list.  eg: maximum([1..6]) = 6. In Haskell:

          maximum          :: Ord a => [a] -> a
          maximum           = foldl1 max

sum xs
     Returns the sum of the elements of xs.  You should not do this with
     an infinite list.  eg: sum([1..6]) = 21. In Haskell:

          sum          :: Num a => [a] -> a
          sum           = foldl' (+) 0

product xs
     Returns the products of the elements of xs.  You should not do this
     with an infinite list.  eg: product([1..6]) = 720. In Haskell:

          product      :: Num a => [a] -> a
          product       = foldl' (*) 1

zip as bs
     Zips together two lists into one list. Should not be done with
     infinite lists.  eg: zip([1..6], [7..12]) = [1, 7, 2, 8, 3, 9, 4, 10,
     5, 11, 6, 12].  In Haskell:

          zip              :: [a] -> [b] -> [(a,b)]
          zip               = zipWith  (\a b -> (a,b))

          zipWith                  :: (a->b->c) -> [a]->[b]->[c]
          zipWith z (a:as) (b:bs)   = z a b : zipWith z as bs
          zipWith _ _      _        = []

zip3 as bs cs
     Zips together three lists into one. Should not be done with infinite
     lists.  eg: zip3([1..2], [3..4], [5..6]) = [1, 3, 5, 2, 4, 6].  In
     Haskell:

          zip3             :: [a] -> [b] -> [c] -> [(a,b,c)]
          zip3              = zipWith3 (\a b c -> (a,b,c))

          zipWith3                 :: (a->b->c->d) -> [a]->[b]->[c]->[d]
          zipWith3 z (a:as) (b:bs) (c:cs)
                                    = z a b c : zipWith3 z as bs cs
          zipWith3 _ _ _ _          = []

unzip abs
     Unzips one list into two. Should not be done with infinite lists.
     eg: unzip([1,7,2,8,3,9,4,10,5,11,6,12]) = ([1, 2, 3, 4, 5, 6], [7, 8,
     9, 10, 11, 12]).

          unzip    :: [(a,b)] -> ([a],[b])
          unzip     = foldr (\(a,b) ~(as,bs) -> (a:as, b:bs)) ([], [])

unzip abcs
     Unzips one list into three. Should not be done with infinite lists.
     eg: unzip3([1,3,5,2,4,6]) = ([1, 2], [3, 4], [5, 6]).  In Haskell:

          unzip3   :: [(a,b,c)] -> ([a],[b],[c])
          unzip3    = foldr (\(a,b,c) ~(as,bs,cs) -> (a:as,b:bs,c:cs))
          		      ([],[],[])

integers
     A useful function that returns an infinite list containing all the
     integers. eg: integers = (1, 2, 3, 4, 5, ...).

factors x
     A useful function that returns the factors of x.  eg: factors(100) =
     [1, 2, 4, 5, 10, 20, 25, 50, 100].  In Haskell:

          factors x = [n | n <- [1..x], x `mod` n == 0]

prime x
     A useful function that returns, rather unefficiently, if x is a prime
     number or not. It is rather useful while used as a filter, eg:
     take(10, filter("prime", integers)) = [2, 3, 5, 7, 11, 13, 17, 19,
     23, 29].  In Haskell:

          primes = [n | n <- [2..], length (factors n) == 2]

AUTHOR
======

   Leon Brocard <`acme@astray.com'>

COPYRIGHT
=========

   Copyright (C) 1999, Leon Brocard

   This module is free software; you can redistribute it or modify it
under the same terms as Perl itself.

Perl module to configure the Linux kernel packet filtering firewall.
********************************************************************

NAME
====

   Fwctl - Perl module to configure the Linux kernel packet filtering
firewall.

SYNOPSIS
========

     use Fwctl;

     my $fwctl = new Fwctl( %opts );
     $fwctl->dump_acct;
     $fwctl->reset_fw;
     $fwctl->configure;

DESCRIPTION
===========

   Fwctl is a module to configure the Linux kernel packet filtering
firewall using higher level abstraction than rules on input, output and
forward chains. It supports masquerading and accounting as well.

   Why Fwctl ? Well, say you are the kind of paranoid firewall
administrator which likes his firewall's rules tight. Very tight. Say the
kind, that likes to distinguish between a SYN and ACK packet when
accepting a TCP connection (anybody configuring packet filters should care
about that last point), or like to specify the interface name on each
rules. (Whether this is really need, or such a stance is relevant, is not
the point.) How would such an administrator proceed ?  First of all you
deny everything on all interfaces and on all chains (input, forward and
output) and turn on logging. Now starting from this configuration (in
which Fwctl puts the firewall on initialization), say you want to enable
ping from the internal network to the internal ip. What rules do you need
? You need a rule on the input chain to accept the echo-request packet and
a rule on the output chain to accept the echo-reply request. Right ? Well,
what about the loopback. For sure, when we say from local net to local ip,
this imply local ip to local ip ? Then you add a rule to the output chain
with the loopback interface, and a rule on the input rule to the loopback
chain. And we didn't even start forwarding yet ! Add masquerading to the
lot and multi connections protocols like FTP and you got something
unmanageable. So you start accepting things you shouldn't to get your job
done and in the end your filters look like emmenthal.

   Fwctl handles all the complexity of this, so that when you say

   accept ftp -src FTP_PROXY -dst INTERNET -noport

   you don't accept too much of what you didn't intend. (Well you just
opened arbitrary TCP connections to unprivileged ports on the Internet
from your proxy server, but that's because of the FTP protocol, not
because your cheating on the firewall rules.)

   Fwctl works with entity known as service. A service can be ftp, netbios,
ping or anything else. The service abstraction handles all the
communication necessary for that application. (The UDP and TCP
communication in DNS, or the control, data and passive connections for
FTP.)

   Additionally, to handle all the special case with ANY specification,
when the src of dst imply a local IP, or masquerading, in short for Fwctl
to be able to deduce the interface implicated by the src and dst portion
of a rules you need to provide it with your network topology.  Fwctl must
guess from your topology the routing decision that will be made in the
kernel. In the best of worlds, Fwctl should contains the same routing
algorithm as the one in the kernel. Well, it doesn't so if you are using
fancy routing feature, Fwctl won't work. In fact, it can only handle
something equivalent to simple static routing. You have been warned.

   So in short, to configure your packet filters with Fwctl you need to

  1. Define your network topology using the `interfaces' file.

  2. (Optional) Define meaningful aliases for hosts and networks which are
     part of your configuration.

  3. Implement your security policy using high level abstract rules in the
     rules file.

        Finally, Fwctl is extensible. You can easily add services modules
using the Fwctl::RuleSet module which contains all the primitive you need
to handle all the special cases involved in the input, forward and output
chain selection.

CONFIGURATION
=============

   Fwctl configures the Linux kernel packet filtering firewall using three
files: the `interfaces' file that describes your network topology, the
aliases file that can contains meaningful aliases and the rules files that
contains the services policy for the firewall.

TOPOLOGY
--------

   The `interfaces' file (default to `/etc/fwctl/interfaces') describes
your firewall topology. This is a text file in which comments (starting by
a # and continuing until the end of line) and blank lines are ignored.

   Each non blank, non comment lines is an interface specification. The
format of the interfaction specification is

     NAME    INTERFACE	IP/MASK	    [NETWORK]*

NAME
     This is the name of the interface. It can be anyting. (Well please
     keep to alphanumeric characters plus underscore). There are two
     reserved names and a magical one. LOCAL refers to the loopback
     interface and shouldn't be redefined. ANY refers to a interface
     matching all the defined interfaces.  You should defined at least an
     interface named EXT which corresponds to the interface connected to
     the default route. This is the interface on which Internet traffic
     usually come and go.

INTERFACE
     This should be set to the kernel interface name. (eth0, ppp0, tunl0,
     etc.)  You may specifiy here alias interface (eth0:0) but the Fwctl
     will canonicalize the name to the master interface (eth0) to match
     the way the kernel 2.2 use them.

IP/MASK
     This is the IP address and Netmask of the interface. The netmask can
     be specified in either netmask notation (255.255.255.0) or CIDR
     notation (24).

NETWORKS
     This is an optional space separated list of IP/MASK networks connected
     to this interface. This is to handle internal network connected to
     WAN link.

   The `interfaces' file should correspond to your firewall network
configuration. It should adequatly represent its runtime interface and
routing configuration or this module is useless.

ALIASES
-------

   The aliases file contains meaningful aliases for use in the rules file.

   Comments (starts with # and continues untill the end of line) and blank
lines are ignored.

   Alias line are of the form :

     ALIAS [:=]+ EXPANSION

ALIAS
     This is the mnemonic alias. For example, you could use MAIL_SERVER,
     CORPORATE_OFFICE, aNotSoUsefulAlias, etc. Please restrict yourself to
     alphanumeric character plus underscore. And be sure to read the
     predefined aliases section.

EXPANSION
     This is what the alias expands to. This can be a space separated list
     of host or network specification or other alias.

     The host or network expansion can also be tagged with an interface
     name which specifies which interface is associated with that alias and
     that will be use for routing logic. If you don't specify an interface
     Fwctl will figure out which interface is associated to the host or
     network using conventional routing logic. Be warned though that if you
     have interfaces that shares the same IP or have the same network
     attached if won't do probably what you intended. If all interfaces
     have distinctive IP and networks it will be probably fine tough.

     Example :

          VPN_CLIENT1 = 192.168.2.10(VPN1)

   Aliases are recursively expanded. Please avoid infinite recursion or you
will get a complaint at parse time.

   Here is a list of predefined aliases. (All those aliases are associated
with their interface for routing pupose).

INTERNET
     This alias represents any host or network connected through the EXT
     interface.

ANY
     This alias represents any host or network connected through any
     interface.

<IF>_IP
     The is an alias name IF_IP for each defined interface which
     corresponds to the IP address of this interface.

     For example, if you have defined the EXT interface and a INTERNAL
     interface, the aliases LOCAL_IP, EXT_IP and INTERNAL_IP. (Remenber
     the automatic LOCAL interface).

<IF>_NET
     The is an alias name IF_NET for each defined interface which
     corresponds to the network attached to this interface.

<IF>_BCAST
     The is an alias name IF_IP for each defined interface which
     corresponds to the broadcast address of this interface.

<IF>_REM_NETS
     The is an alias name IF_IP for each defined interface which
     corresponds to all the networks that are routed through this
     interface excepted the one directly connected.

<IF>_NETS
     The is an alias name IF_IP for each defined interface which
     corresponds to all the networks attached to this interface, not only
     the direct one.

RULES
-----

   The rules file contains your firewall policy implementation. It is a
text file that describes the policy for each services.

   As usual, (do I even need to mention it?) comments (starts with # and
continues until the end of line) and blanks line are ignored.

   Rules format is :

     ACTION  SERVICE OPTIONS

ACTION
     What to do with this service can be one of accept, reject, deny or
     account. See POLICY section for explanation.

SERVICE
     This is the name of the service which is the target of the action. The
     service is handled by a module called Fwctl::Services::<service>.pm
     but see AUTOMATIC SERVICES.

OPTIONS
     This is a space separated list of options which further specify what
     is the actual policy. Option name starts with - or - and can be
     abbreviated to uniquesess. Some options takes a paremeters some are
     flags. Read the doc. These options are module specific but see
     STANDARD OPTIONS section.

POLICY
======

   There are four possible actions for a service. These are ACCEPT, DENY,
REJECT or ACCOUNT. (These are actually case insensitive).

ACCEPT
     This will accept the service.

DENY
     This traffic part of this service will be drop without anyone knowing.
     (Except probably your logs.)

REJECT
     Traffic part of this service will be dropped with a proper message
     being sent to the originating party.

ACCOUNT
     Packets part of this service will be counted. This won't accept or
     deny the service. Use one of the other three actions to define the
     actual fate of this service.

SERVICE
=======

   A service are module that encapsulates the collection of IP traffic
that are part of an application. For example, to accept or account the FTP
service, you must accept two or three TCP connections, the rsh service
uses two. DNS service need 1 TCP connection and an UDP circuit.

   The SERVICE abstraction is needed to insulates the administrator from
the idiosyncrasies of the service. Needless to say that the adminstrator
should be familiar with the idiosyncrasies of the service to be able to
make an appropriate security judgement about the service. It's just that
it is easier once the judgement has been made to accept or deny the
specific service.

   Each service is a perl module named Fwctl::Services::name which knows
the particular IP traffic that is part of this service.

AUTOMATIC SERVICES
------------------

   As a convenience to the administrator (and programmer) simple one way
TCP service are automatically created at runtime. For example, this
distribution doesn't contains a telnet service. But since the telnet
service is only a tcp connection from client to the server's telnet port.
If you use ACCEPT telnet in your rules, a telnet service is automatically
generated as a subclass of tcp_service with a destination port of telnet.
You could use in this way pop-3, imap or any protocol which has only a
client/server TCP connection.

OPTIONS
=======

   Each service can defined a number of options but here are the standard
one that each service should implement.

-src
     Specify the client part of the service. This can be a list of IP or
     network addresses, or aliases. Once the aliases are expanded only IP
     addresses must remains. When you configure your firewall DNS
     shouldn't be available. If you need name, that's what the aliases is
     for.

     If there are more than one IP address, it is equivalent as if you had
     specified a different rule with each address. (i.e.: If you have 4
     IPs, this is transformed in four rules).

     If this option is not present. It is the same as -src ANY.

-dst
     Specify the server part of the service. The syntax of this option is
     identical to the src one.

-masq or -nomasq
     If this option is set, the firewall will masquerade this service on
     behalf of the client. This option is only meaningful with the ACCEPT
     or ACCOUNT action.

     With the ACCOUNT action it properly account for masqueraded traffic.
     That is to say that if you want to accept masqueraded telnet and want
     to turn on accounting for this service, you should also use the masq
     option to the ACCOUNT action. (Or simply use the account option).

-log  or -nolog
     This option turn on or off packet header logging for this service.
     Default to log for DENY or REJECT action and nolog for ACCEPT and
     ACCOUNT.

-copy or -nocopy
     This option turn on or off packet copying to the `/dev/fwmonitor'
     device for reading by a user space program.

-account
     This adds an ACCOUNT rule for this service with the exact same
     options.

-mark
     Marks the packet with the specified integer.

-name
     Sets the accounting name for this rule. This is easier to read than
     the unique name generated internally.

-portfw [local_ip]
     The service will be interpreted as being redirected from a local
     address to another host on a network attached to one of the firewall
     interface. The optional argument is one of the IP of a defined
     interface. If the local_ip from which the service will redirected is
     unspecified, the one attached to the incoming interface will be used.

     When using portfw, the dst parameter can only contains hosts and all
     src must be compatible with the local_ip.

ACCOUNTING
==========

   Accounting data is dump to the file `/var/log/fwctl_acct'. You should
run periodically the *fwctl* program to dump the accumulated accounted
data.

   The format of the file is:

     timestamp chain packets bytes name

timestamp
chain
     The unique internal name identifying this chain. (If you want to
     know, it is acct plus four digit number starting from 0 and
     incremented for each ACCOUNT chain added.)

     If you need to translate this anything meaningful, please use the
     name option.

packets
     The number of packets related to that service.

bytes
     The number of bytes relating to that service.

name
     The value of the name option.

BUGS AND LIMITATIONS
====================

   Please report bugs, suggestions, patches and thanks to
<francis.lacoste@iNsu.COM>.

   This package is probably useless if you have something a topology that
cannot be described adequatly in a simple static routing scheme.

   Documentation on writing services is lacking. But see the standard
services for details.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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, you can get one at
http://www.gnu.org/copyleft/gpl.html

SEE ALSO
========

   fwctl(8) Fwctl::RuleSet(3) IPChains(3) Net::IPv4Addr(3)
Fwctl::Services::all(3) Fwctl::Services::dhcp(3) Fwctl::Services::ftp(3)
Fwctl::Services::http(3) Fwctl::Services::hylafax(3)
Fwctl::Services::netbios(3)  Fwctl::Services::ntp(3)
Fwctl::Services::ping(3) Fwctl::Services::portmap(3)
Fwctl::Services::rsh(3) Fwctl::Services::snmp(3)
Fwctl::Services::tcp_service(3) Fwctl::Services::syslog(3)
Fwctl::Services::tftp(3) Fwctl::Services::timed(3)
Fwctl::Services::traceroute(3) Fwctl::Services::traffic_control(3)
Fwctl::Services::udp_service(3)

Generates reports from `fwctl dump-acct' command.
*************************************************

NAME
====

   Fwctl::AcctReport - Generates reports from `fwctl dump-acct' command.

SYNOPSIS
========

     use Fwctl::AcctReport;

     my $report = new Fwctl::Report( options ... );

     my $r = $report->summary_report;

     foreach my $r ( @$src_alias_sum ) {
     	print $r->{name}, " = ", $r->{bytes_sum}, "\n";
     }

DESCRIPTION
===========

   The Fwctl::AcctReport(3) module can be used to generate packet and
bandwith report from the data generated by the `fwctl dump-acct' command.

   This module can be used as backend for two kinds of report. Summary
which compiles the total number of packets and bytes received by each
accounting chains over the report's period or histogram type report where
you have the packets and bytes total for each sample (hour, day, etc) over
the report's period.

CAVEATS
=======

   The `fwctl dump-acct' commands dumps the packets and bytes total since
the time of the last invocation. If the last invocation wasn't wholly
comprised in the current sample, the total will be interpolated. This
means that you should run the `fwctl dump-acct' command at least as
frequently as the smallest sample period you want to use.

CREATING A NEW REPORT OBJECT
============================

     Ex. my $report = new Fwctl::AcctReport( start  => 'yesterday',
     					    period => '1 day',
     					    sample => '1d',
     					    files  => [ 'log' ] );

PARAMETERS
----------

   The new method accepts the following parameter :

files
     Specifies the file from which to read the dumped acctounting
     informations.  It is an array of file handle or file names. If this
     parameter is not specified the records will be read from STDIN.

start
     Sets the start of the report's period. If the Date::Manip(3) module is
     installed, you can use any format that this module can parse. If that
     module isn't installed you must use the following format YYYY-MM-DD
     HH:MM:SS or any meaningful subset of that format.

     If this option is not used, the report will start with the first
     record.

end
     Sets the end of the report's period. If the Date::Manip(3) module is
     installed, you can use any format that this module can parse. If that
     module isn't installed you must use the following format YYYY-MM-DD
     HH:MM:SS or any meaningful subset of that format.

     If this option is not used, the report will end with the last record.

period
     Sets the length of the report's period. This length is interpreted
     relative to the report's start. This option has priority over the end
     option.

     If you have the Date::Manip module installed, you can use any format
     that this module can parse. If that module isn't available, you can
     use a subset of the following format X weeks X days X hours X mins X
     secs.

sample
     Sets the length the sample's for the report. The sample_report will
     returns results aggregated over that length. For example, if you use
     1d as sample's length, you will get the stats for every day from the
     beginning of the report until the end.

     If you have the Date::Manip module installed, you can use any format
     that this module can parse. If that module isn't available, you can
     use a subset of the following format X weeks X days X hours X mins X
     secs.

names
     Restrict records to those whose name matches names.

     You can use this parameter multiple times to specify multiple
     possibility. The record will be included if it matches any of those.

METHODS
=======

start()
=======

   Return the start of the report in seconds since epoch.

end()
=====

   Returns the end of the report in seconds since epoch.

period()
========

   Returns the length of the report's period ( $report->end() -
$report->start() )

sample()
========

   Returns the length of the sample period.

records()
=========

   Returns an array reference to all the records read and which makes the
report's samples.

RECORD FIELDS
-------------

   Each record is an array ref. You can accessed the individual fields of
the record by using the following constants. (Those can be imported by
using the `:fields' import tag.)

TIME
     The epoch start time of the sample.

NAME
     The name of the accounting chain.

PACKETS
     The number of packets received.

BYTES
     The total number of bytes.

REPORTS
=======

   The following report generation methods are available :

summary_report()
----------------

     my $r = $report->summary_report();

   Generates a report that shows the compiled statistics for every
accounting chain.

   The resulting report is an array ref of hash reference. Each report
record's has the following fields.

name
     The name of the chains.

packets_sum
     The total number of packets over the report's period.

     This number is a Math::BigInt(3) object.

bytes_sum
     The total number of bytes received over the report's period.

     This number is a Math::BigInt(3) object.

packets_avg
     The average number of packets received by that chain by sample.

     This number is a Math::BigInt(3) object.

bytes_avg
     The average number of packets bytes by that chain by sample.

     This number is a Math::BigInt(3) object.

sample_report()
---------------

     my $r = $report->sample_report();

   Generates a report that compiles the stats for each sample for each
chains.

   The resulting report is an hash reference. Each key is a chain and each
value is an array ref to the chain compiled statistics. Each element of
the array is an hash reference comprises of the following elements :

start
     The start time in seconds since epoch for that sample.

packets
     The total number of packets received in that sample.

     This number is a Math::BigInt(3) object.

bytes
     The total number of bytes received in that sample.

     This number is a Math::BigInt(3) object.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   Fwctl(3) Fwctl::RuleSet(3) fwctl(8) fwctllog(8) fwctacctreport(8)
Fwctl::Report(3) Date::Manip(3).

Generates reports from fwctllog output.
***************************************

NAME
====

   Fwctl::Report - Generates reports from fwctllog output.

SYNOPSIS
========

     use Fwctl::Report;

     my $report = new Fwctl::Report( options ... );

     my $src_alias_sum = $report->src_alias_summary_report;

     foreach my $r ( @$src_alias_sum ) {
     	print $r->{host_ip}, " = ", $r->{count}, "\n";
     }

DESCRIPTION
===========

   The Fwctl::Report(3) module can be used to generate various reports from
the output of the *fwctllog* program.

   This module generates two kinds of report summary and <report>. The
summary compiles the number of occurence for an item (source, destination,
service, etc.). The report methods will returns all the log entry that
shares the same key ( source, destination, service, etc.)

CREATING A NEW REPORT OBJECT
============================

     Ex. my $report = new Fwctl::Report( start  => 'yesterday',
     					period => '1 day',
     					files  => [ 'log' ] );

PARAMETERS
----------

   The new method accepts the following parameter :

files
     Specifies the file from which to read the `fwctllog' output. It is an
     array of file handle or file names. If this parameter is not specified
     the records will be read from STDIN.

start
     Sets the start of the report's period. If the Date::Manip(3) module is
     installed, you can use any format that this module can parse. If that
     module is'nt installed you must use the following format YYYY-MM-DD
     HH:MM:SS or any meaningful subset of that format.

     If this option is not used, the report will start with the first
     record.

end
     Sets the end of the report's period. If the Date::Manip(3) module is
     installed, you can use any format that this module can parse. If that
     module is'nt installed you must use the following format YYYY-MM-DD
     HH:MM:SS or any meaningful subset of that format.

     If this option is not used, the report will end with the last record.

period
     Sets the length of the report's period. This length is interpreted
     relative to the report's start. This option has priority over the end
     option.

     If you have the Date::Manip module installed, you can use any format
     that this module can parse. If that module isn't available, you can
     use a subset of the following format X weeks X days X hours X mins X
     secs.

threshold
     This option will removed records identical in protocol, destination
     ports, source addresses and destination addressesses that appears in
     the time window specified by the threshold parameters. Defaults is 120
     (2 minutes). Use 0 to generates reports for all the packets.

limit
     This parameter can be used to restrict the records over which the
     report is generated. It is an expression which will be used to select
     a subset of all the records. You can use the following fields :
     src_ip, dst_ip, src_host, dst_host, action, device, src_port,
     dst_port, src_serv, dst_serv, proto, proto_name, and the following
     operator =, !=, <, >, <=, >=, /regex/, /regex/i. Those operators have
     the same meaning as in perl. You can also use parentheses and the
     following logic operator : or, and, not .

METHODS
=======

start()
=======

   Return the start of the report in seconds since epoch.

end()
=====

   Returns the end of the report in seconds since epoch.

period()
========

   Returns the length of the report's period ( $report->end() -
$report->start() )

records()
=========

   Returns an array reference to all the records read and which makes the
report's sample.

RECORD FIELDS
-------------

   Each record is an array ref. You can accessed the individual fields of
the record by using the following constants. (Those can be imported by
using the `:fields' import tag.)

TIME
     The epoch time of the log entry.

ACTION
     The resulting action (ACCEPT,DENY,REJECT).

DEVICE
     The physical device on which the packet was logged.

IF
     The Fwctl(3) interface to which this device is related.

CHAIN
     The kernel chain on which that packet was logged.

PROTO
     The protocol number.

PROTO_NAME
     The name of the protocol.

SRC_IP
     The source address of the packet.

SRC_HOST
     The source hostname.

SRC_IF
     The Fwct(3) interface related to the source address.

SRC_ALIAS
     The Fwctl(3) alias associated to the source address.

SRC_PORT
     The source port of the logged packet.

SRC_SERV
     The service name associated to the logged packet.

DST_IP
     The destination IP of the packet.

DST_HOST
     The destination hostname.

DST_IF
     The Fwctl(3) interface associated with the destination address.

DST_ALIAS
     The Fwctl(3) alias related to the destination address.

DST_PORT
     The destination port number.

DST_SERV
     The service name of the the destination port.

REPORTS
=======

   The following report generation methods are available :

service_summary_report()
------------------------

     my $r = $report->service_summary_report();

   Generates a report that shows the number of log entries for each
services.

   The resulting report is an array ref of hash reference. Each report
record's has the following fields.

proto
     The protocol number.

proto_name
     The protocol name.

dst_port
     The destination port.

dst_serv
     The destination service's name.

src_port
     If the protocol *is not* UDP or TCP, the source port.

src_serv
     If the protocol *is not* UDP or TCP, the service name associated to
     the source port.

count
     The number of log entries matching the service.

first
     The epoch time of the first occurence.

last
     The epoch time of the last occurence.

service_report()
----------------

     my $r = $report->service_report();

   Generates a report that sort the log entries by service.

   The report is an array of arrays. Each elements of the report is an
array of records which shares the same service.

service_alias_summary_report()
------------------------------

     my $r = $report->service_alias_summary_report();

   Generates a report that shows the number of log entries for each
destination aliases / service.

   The resulting report is an array ref of hash reference. Each report
record's has the following fields.

proto
     The protocol number.

proto_name
     The protocol name.

host_alias
     The alias of the destination hosts.

dst_port
     The destination port.

dst_serv
     The destination's service name.

src_port
     If the protocol *is not* UDP or TCP, the source port.

src_serv
     If the protocol *is not* UDP or TCP, the service name associated to
     the source port.

count
     The number of log entries.

first
     The epoch time of the first occurence.

last
     The epoch time of the last occurence.

service_alias_report()
----------------------

     my $r = $report->service_alias_report();

   Generates a report that sort the log entries by destination alias and
service.

   The report is an array of arrays. Each elements of the report is an
array of records which shares the same destination alias and service.

service_host_summary_report()
-----------------------------

     my $r = $report->service_host_summary_report();

   Generates a report that shows the number of log entries for each
destination aliases / service.

   The resulting report is an array ref of hash reference. Each report
record's has the following fields.

proto
     The protocol number.

proto_name
     The protocol name.

host_ip
     The destination host ip address.

host_name
     The destination host name.

host_alias
     The alias of that host.

dst_port
     The destination port.

dst_serv
     The destination service's name.

src_port
     If the protocol *is not* UDP or TCP, the source port.

src_serv
     If the protocol *is not* UDP or TCP, the service name associated to
     the source port.

count
     The number of log entries.

first
     The epoch time of the first occurence.

last
     The epoch time of the last occurence.

service_host_report()
---------------------

     my $r = $report->service_host_report();

   Generates a report that sort the log entries by destination host and
service.

   The report is an array of arrays. Each elements of the report is an
array of records which shares the same destination host and service.

src_alias_summary_report()
--------------------------

     my $r = $report->service_alias_summary_report();

   Generates a report that shows the number of log entries for each source
aliases.

   The resulting report is an array ref of hash reference. Each report
record's has the following fields.

host_alias
     The source alias.

count
     The number of log entries.

first
     The epoch time of the first occurence.

last
     The epoch time of the last occurence.

src_alias_report()
------------------

     my $r = $report->src_alias_report();

   Generates a report that sort the log entries by source alias.

   The report is an array of arrays. Each elements of the report is an
array of records which shares the same source alias.

src_host_summary_report()
-------------------------

     my $r = $report->src_host_summary_report();

   Generates a report that shows the number of log entries for each source
host.

   The resulting report is an array ref of hash reference. Each report
record's has the following fields.

host_ip
     The source host ip address.

host_name
     The source host name.

host_alias
     The alias of the source host.

count
     The number of log entries.

first
     The epoch time of the first occurence.

last
     The epoch time of the last occurence.

src_host_report()
-----------------

     my $r = $report->src_host_report();

   Generates a report that sort the log entries by source host.

   The report is an array of arrays. Each elements of the report is an
array of records which shares the same source host.

dst_alias_summary_report()
--------------------------

     my $r = $report->dst_alias_summary_report();

   Generates a report that shows the number of log entries for each
destination aliases.

   The resulting report is an array ref of hash reference. Each report
record's has the following fields.

host_alias
     The destination alias.

count
     The number of log entries.

first
     The epoch time of the first occurence.

last
     The epoch time of the last occurence.

dst_alias_report()
------------------

     my $r = $report->dst_alias_report();

   Generates a report that sort the log entries by destination alias.

   The report is an array of arrays. Each elements of the report is an
array of records which shares the same destination alias.

src_host_summary_report()
-------------------------

     my $r = $report->src_host_summary_report();

   Generates a report that shows the number of log entries for each
destination hosts.

   The resulting report is an array ref of hash reference. Each report
record's has the following fields.

host_ip
     The destination host ip address.

host_name
     The destination host name.

host_alias
     The alias of the destination hosts.

count
     The number of log entries.

first
     The epoch time of the first occurence.

last
     The epoch time of the last occurence.

dst_host_report()
-----------------

     my $r = $report->dst_host_report();

   Generates a report that sort the log entries by destination host.

   The report is an array of arrays. Each elements of the report is an
array of records which shares the same destination host.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   Fwctl(3) Fwctl::RuleSet(3) fwctl(8) fwctllog(8) Fwctl::Report(3)
Date::Manip(3).

Module to add sets of rules to the linux firewall.
**************************************************

NAME
====

   Fwctl::RuleSet - Module to add sets of rules to the linux firewall.

SYNOPSIS
========

     use IPChains;
     use Fwctl::RuleSet qw(:masq :tcp_rulesets :ports);

     my $chain = new IPChains( Prot       => 'tcp',
     			    SourcePort => UNPRIVILEGED_PORTS,
     			    DestPort   => 23,
     			    )
     accept_tcp_ruleset( $chain, $src, $src_if, $dst, $dst_if, NOMASQ );

DESCRIPTION
===========

   This module contains primitives to add sets of rules to the Linux
packet filtering firewall implementing a particular policy. It is used
primarly by service modules. The module handle all the special cases for
when the src or dst interface is ANY, when masquerading is involved, when
a local ip is implied by the src or dst address. All this logic has not to
be implemented by the service modules, which only have to specify the kind
of packets and the direction of traffic (using the src and dst paremeter).

   There are 5 tags that can be imported from the modules.

:masq
     Constant used to specify how to handle masquerade.

:ports
     Constants that refers to range of ports.

:tcp_rulesets
     Functions that implements policy rulesets for TCP connection.

:udp_rulesets
     Functions that implements policy rulesets for bidirectional UDP
     traffic.

:ip_rulesets
     Funtions that implements policy rulesets for IP traffic. This are the
     primitives on which the tcp and udp rulesets are built.

:masq
=====

NOMASQ
     Constant used to represent that the traffic shouldn't be masqueraded.

MASQ
     Constant use to denote that this traffic will be masqueraded when
     going throught the forward chain.

UNMASQ
     Constant use to denote that traffic should be unmasqueraded when
     passing the input chain.

   To better understand the way the MASQ and UNMASQ constants works
together lets look at how they would be use to handle a TCP connection.

     accept_ip_rulesets( $chain, $src, $src_if, $dst, $dst_if, MASQ );
     $chain->attribute( SYN => '!' );
     accept_ip_rulesets( $chain, $dst, $dst_if, $src, $src_if, UNMASQ);

:ports
======

RESERVED_PORTS
     Constant that represents the ports 1 through 1023.

UNPRIVILEGED_PORTS
     Constant that represents the ports 1024 through 65535.

MASQ_PORTS
     Constant that represents the ports used when masquerading a
     connection : 61000 through 65096.

:ip_rulesets
============

   This tags imports three functions that are the primitives on which the
others are built. All src or dst can be classified in one of four category.
=over

ANY
     Source or destination is any address on any interface.

LOCAL_IP
     Source or destination is a local interface

LOCAL_IMPLIED
     Source or destination implied a local interface. Example of those
     includes a broadcast address of a local interface or network address
     of a local interface.

REMOTE
     Source or destination doesn't imply a local IP.

   So this means a total of 16 combination of source and destination
address.  Add the parameter MASQ,UNMASQ and NOMASQ and you got 48
possibilities. Those usually can be reduced to between 7 and 16 cases
depending on the policy you want to handle. (REJECT, DENY, ACCEPT or
ACCOUNT). The following functions handle all those possibilities for you,
and adds the appropriate rules with address and interface specification to
the appropriate chains.

accept_ip_ruleset($chain,$src,$src_if,$dst,$dst_if,$masq)
     Adds the necessary rules to accept the kind of traffic specified by
     the $chain parameter.

    $chain
          IPChains objects that contains the prototypes of the rules to
          add to the firewall. Source, Dest and Interface parameter are
          overwritten by the function.

    $src
          The source address of the packet.

    $src_if
          The interface associated to the $src address.

    $dst
          The destination address of the packet.

    $dst_if
          The interface associated to the $dst address.

    $masq
          How the packet should be masqueraded.

     Usually the $src, $src_if, $dst and $dst_if packets are not modified
     by the service modules and are those passed by the Fwctl module. Or
     the module will switch them (dst becomes src), or change them because
     the protocol uses broadcast or other stuff.

block_ip_ruleset( $chain, $src, $src_if, $dst, $dst_if )
     This primitive handles both REJECT and DENY policies. The parameter
     have the same meaning as in the accept_ip_ruleset() function.

account_ip_ruleset( $chain, $src, $src_if, $dst, $dst_if )
     This primitive handles the ACCOUNT policy. The parameter have the
     same meaning as in the accept_ip_ruleset() function.

:tcp_rulesets
=============

   This tags imports three functions: accept_tcp_ruleset(),
block_tcp_ruleset() and account_tcp_ruleset() which have the same
parameters and semantics as their *_ip_ruleset() counterpart.  They are
indeed implemented in terms of these.

   The difference is that the $chain parameter can only be used to
represent a TCP connection. The functions will add rules for the client
and server side of the connection with the SYN and ACK flags handled
properly.

:udp_rulesets
=============

   This tags imports three functions: accept_udp_ruleset(),
block_udp_ruleset() and account_udp_ruleset() which have the same
parameters and semantics as their *_ip_ruleset() counterpart.  They are
indeed implemented in terms of these.

   These functions will add rules to handle client / server UDP connection.
It like calling the *_ip_ruleset() functions two times with the src and
dst inversed (the SourcePort and DestPort are naturally also inversed).

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) IPChains(3)

Fwctl module to handle any IP traffic.
**************************************

NAME
====

   Fwctl::Services::all - Fwctl module to handle any IP traffic.

SYNOPSIS
========

     accept   all -src INTERNAL_NET -dst INTERNET -masq
     deny    all -src BAD_GUYS_NET	--account
     account all -src PERIM_NET -dst INTERNET

DESCRIPTION
===========

   The all module is used to match any IP traffic. It can be used for
accounting all traffic between nets or to create bazooka sized hole in our
filters.

   Needless to say that

     accept all

   is not a really secure use of this module.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle the dhcp protocol.
*****************************************

NAME
====

   Fwctl::Services::dhcp - Fwctl module to handle the dhcp protocol.

SYNOPSIS
========

     accept  dhcp -src INTERNAL_NET -dst DHCP_SERVER
     deny    dhcp -src INTERNAL_NET -nolog
     account dhcp -src INTERNAL_NET

DESCRIPTION
===========

   This module is used to handle the DHCP protocol. It adds rules to
handle the special addresses used by the DHCP protocol. Since DHCP is a
broadcast based protocol restricted to local segment, so which by
definition doesn't cross a firewall, who would want to use such a module ?

   Two use, first to prevent clutter of log files which denied dhcp
broadcast packets when you are using DHCP on the internal network.
Second, when your firewall is acting as a DHCP server to the internal
network. ??? Who would want to do that ??? Someone trying to replace all
WinGate installations with linux based solutions ;-).

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle the FTP service.
***************************************

NAME
====

   Fwctl::Services::ftp - Fwctl module to handle the FTP service.

SYNOPSIS
========

     accept   ftp -src INTERNAL_NET -dst INTERNET -noport -masq
     accept   ftp -src PROXY_SERVER -dst INTERNET -noport --account
     accept   ftp -src INTERNET -d FTP_SERVER -noport
     accept   ftp -src INTERNAL_NET -dst INT_IP --ctrl_port hylafax

DESCRIPTION
===========

   The ftp module is used to handle the FTP protocol. By default it
handles both PORT and PASV based protocol. If maquerading is asked for, it
also loads the proper kernel module.

OPTIONS
=======

   In additions to the standard options it takes the following ones :

-port or -noport
     Sets whether rules for the PORT part of the FTP protocol will be
     added.

-pasv or -nopasv
     Sets whether rules for the PASV part of the FTP protocol will be
     added.

-pasv_ports
     Sets the port accepted for PASV connections. Defaults to
     UNPRIVILEGED_PORTS.

-ctrl_port
     Sets the port used for the control connection. This is the port on
     which the ftp server listens. Defaults to ftp.

-data_port
     Sets the port for the data connection. This is the port from which
     PORT connections of the server originates.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle HTTP protocol.
*************************************

NAME
====

   Fwctl::Services::http - Fwctl module to handle HTTP protocol.

SYNOPSIS
========

     accept   http -src INTERNAL_NET -dst PROXY
     deny    http -dst MICROSOFT	--nolog --account
     account http -src PROXY -dst INTERNET

DESCRIPTION
===========

   The http module is used to control traffic which should be part of an
HTTP connection. It use the option port which should contains a comma
separated list of port which are open for TCP connections.  Defaults to 80.

   THIS IS NOT A PROXY. It only open a bunch of TCP port to which
connection can be attempted. You have been warned.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle the HylaFax protocol.
********************************************

NAME
====

   Fwctl::Services::hylafax - Fwctl module to handle the HylaFax protocol.

SYNOPSIS
========

     accept   hylafax -src INTERNAL_NET -dst INT_IP

DESCRIPTION
===========

   The hylafax module is used to handle the HylaFAX protocol which is a
variant of the FTP protocol.

OPTIONS
=======

   No service specific options.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle arbitrary ICMP packet.
*********************************************

NAME
====

   Fwctl::Services::icmp_pkt - Fwctl module to handle arbitrary ICMP
packet.

SYNOPSIS
========

     accept icmp_pkt -src INT_IP -dst INT_NET --code redirect

DESCRIPTION
===========

   This module can be use to add rules for arbitrary ICMP packets. Use the
-code option to specify the ICMP code of the packet to build the rules for.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle non UDP/TCP/ICMP packets.
************************************************

NAME
====

   Fwctl::Services::ip_pkt - Fwctl module to handle non UDP/TCP/ICMP
packets.

SYNOPSIS
========

     accept  ip_pkt -src LOCAL_NET -dst REMOTE_IPIP --protocol ipip

DESCRIPTION
===========

   This module can be use to add rules for other IP protocols than UDP,
TCP or ICMP.

   Use the -protocol option to specify the protocol.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle the IPSec protocol.
******************************************

NAME
====

   Fwctl::Services::ipsec - Fwctl module to handle the IPSec protocol.

SYNOPSIS
========

     accept ipsec -src INT_NET -dst REMOTE_IPSEC

DESCRIPTION
===========

   This module will implements the rules to accept/block/account the IPSec
tunnelling protocol. In order to be able to masquerade that protocol, you
will need a kernel with the IPSec masquerade patch applied.

   See ftp://ftp.rubyriver.com/pub/jhardin/masquerade/ for informations.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle the Berkeley Line Printer 		       protocol.
*******************************************************************

NAME
====

   Fwctl::Services::lpd - Fwctl module to handle the Berkeley Line Printer
      protocol.

SYNOPSIS
========

     accept   lpd -src INTERNAL_NET -dst PRINTER

DESCRIPTION
===========

   The lpd modules handles the LP protocol. It permits a tcp connection
from the privileged 512 through 1023 to the printer port (515). You can use
the local_port option to specifies another range of port.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle the DNS protocol.
****************************************

NAME
====

   Fwctl::Services::name_service - Fwctl module to handle the DNS protocol.

SYNOPSIS
========

     accept   name_service -src INTERNET -dst NAME_SERVER
     accept   name_service -src NAME_SERVER -dst INTERNET -query-port 5353

DESCRIPTION
===========

   The name_service module handles the DNS protocol. It can handle both
name server and resolver configuration. When using the server option, the
query can be from any ports. You can use the *query-port* option to
specify the client port.

   Default is to use only ports > 1023 as client port. (Usual resolver
situation.)

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle NetBIOS traffic.
***************************************

NAME
====

   Fwctl::Services::netbios - Fwctl module to handle NetBIOS traffic.

SYNOPSIS
========

     deny    netbios -nolog --account

DESCRIPTION
===========

   This module handle the NetBios-NS, NetBios-DGM and NetBios-SSN part of
the NetBIOS protocols. Its primary use is to reduce log clutter when
servicing a Windows Internal Network.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle the NTP protocol.
****************************************

NAME
====

   Fwctl::Services::ntp - Fwctl module to handle the NTP protocol.

SYNOPSIS
========

     accept   ntp -src PROXY -dst NTP_SERVER
     accept   ntp -src PROXY -dst NTP_SERVER -client -masq #For ntpdate

DESCRIPTION
===========

   This module enable NTP traffic between two NTP servers. If you use the
client option, it will use UNPRIVILEGED_PORTS for the SourcePort to enable
ntp clients like *ntpdate*.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle the PC Anywhere protocol.
************************************************

NAME
====

   Fwctl::Services::pcanywhere - Fwctl module to handle the PC Anywhere
protocol.

SYNOPSIS
========

     accept    pcanywhere -src INT_NET -dst REMOTE -masq -account -name PCA

DESCRIPTION
===========

   This module encapsulates the different TCP and UDP connections used by
the PC Anywhere protocol. Use the -old option to use the older set of non
registered ports.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle the ping service.
****************************************

NAME
====

   Fwctl::Services::ping - Fwctl module to handle the ping service.

SYNOPSIS
========

     accept  ping -src INTERNAL_NET -dst INTERNET -masq
     deny    ping -dst BAD_GUYS_NET	--account
     account ping -src INTERNET -dst FIREWALL

DESCRIPTION
===========

   The ping module manages rules for the ICMP echo-request and echo-reply
types used by the ping program.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle the portmapper service.
**********************************************

NAME
====

   Fwctl::Services::portmap - Fwctl module to handle the portmapper
service.

SYNOPSIS
========

     deny    portmap -src INTERNET	--account

DESCRIPTION
===========

   The portmapper handles portmap traffic.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle the PPTP service.
****************************************

NAME
====

   Fwctl::Services::pptp - Fwctl module to handle the PPTP service.

SYNOPSIS
========

     accept pptp -src INT_NET -dst REMOTE_PPTP --masq

DESCRIPTION
===========

   This module will implements the rules to accept/block/account the PPTP
tunnelling protocol. In order to be able to masquerade that protocol, you
will need a kernel with the generic protocol masquerade patch applied.

   See ftp://ftp.rubyriver.com/pub/jhardin/masquerade/ for informations.

   If you want to generates rules for a server behind the firewall, you
will have to use the -portfw option and starts manually the ipfwd daemon.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle ICMP redirect messages.
**********************************************

NAME
====

   Fwctl::Services::redirect - Fwctl module to handle ICMP redirect
messages.

SYNOPSIS
========

     accept  redirect -src INT_IP -dst INT_NET
     account redirect -src INTERNET

DESCRIPTION
===========

   The redirect module can be use to configure policies for ICMP Router
Redirect messages. This module takes no options.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle the rsh protocol.
****************************************

NAME
====

   Fwctl::Services::rsh - Fwctl module to handle the rsh protocol.

SYNOPSIS
========

     accept   rsh -src INTERNAL_NET -dst FIREWALL

DESCRIPTION
===========

   The rsh module handles the remote shell protocol.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle the snmp protocol.
*****************************************

NAME
====

   Fwctl::Services::snmp - Fwctl module to handle the snmp protocol.

SYNOPSIS
========

     accept   snmp -src INTERNAL_NET -dst PERIM_NET
     deny    snmp -src INTERNAL_NET -nolog
     account snmp

DESCRIPTION
===========

   This module handles the SNMP protocol. Its handles SNMP broadcast if
dst is in the same network as src, SNMP traffic between source and
destination, as well as snmp-trap from destination to source.

   Since I don't really know the internals of the SNMP protocol this could
be totally broken. Use only to reduce log file clutter.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle syslog UDP traffic.
******************************************

NAME
====

   Fwctl::Services::syslog - Fwctl module to handle syslog UDP traffic.

SYNOPSIS
========

     accept   syslog -src ROUTER -dst LOGGER

DESCRIPTION
===========

   This modules handles syslog traffic. Syslog traffic is unidirectional
UDP message from client to server.

OPTIONS
=======

   In addition to the standard options, it accepts the following ones.

-client
     This will accepts message coming from a syslog client not bound to
     port 514. The default is to accept messages only coming from port 514.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle simple TCP client/server communication.
**************************************************************

NAME
====

   Fwctl::Services::tcp_service - Fwctl module to handle simple TCP
client/server communication.

SYNOPSIS
========

     accept   tcp_service -src INTERNAL_NET -dst DATABASE_SERVER -port postgres
     # Same as
     accept   postgres -src INTERNAL_NET -dst DATABASE_SERVER
     account tcp_service -src INTERNET -port telnet
     # Same as
     account telnet  -src INTERNET

DESCRIPTION
===========

   This Fwctl module is used to handle single connection TCP
client/server. It takes as options port and *local_port* which are used to
set the destination and source port of the connection.

   This is the module used to auto generate TCP service.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle tftp protocol.
*************************************

NAME
====

   Fwctl::Services::all - Fwctl module to handle tftp protocol.

SYNOPSIS
========

     deny   tftp

DESCRIPTION
===========

   Service module to handle tftp protocol.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle any IP traffic.
**************************************

NAME
====

   Fwctl::Services::timed - Fwctl module to handle any IP traffic.

SYNOPSIS
========

     accept   timed -src INTERNAL_NET -dst FIREWALL
     deny    timed -src INTERNET

DESCRIPTION
===========

   The timed module is used to handle the timed time synchronization
protocol. This modules takes care of the broadcast part of the protocol
and the ICMP part.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle traceroute service.
******************************************

NAME
====

   Fwctl::Services::traceroute - Fwctl module to handle traceroute service.

SYNOPSIS
========

     accept   traceroute -src INTERNAL_NET -dst INTERNET -masq
     deny    traceroute -src INTERNET	--account
     account traceroute -src INTERNET -dst PERIM_NET

DESCRIPTION
===========

   This module handle the usual UDP traffic used by the *traceroute*
program.  You can use the port option to set the range of port used if your
program isn't using the default 33434 and higher.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle the necessary  ICMP traffic.
***************************************************

NAME
====

   Fwctl::Services::traffic_control - Fwctl module to handle the necessary
ICMP traffic.

SYNOPSIS
========

     accept   traffic_control -src INTERNET --account
     accept   traffic_control

DESCRIPTION
===========

   This module handles rules for the necessary ICMP traffic control types:
destination-unreachable, source-quench, ttl-exceeded and parameter-problem.

   You should really accept this with any network you want to communicate.
Failure to do so, will hinder communication severly. YHBW.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to hande unidirectional UDP packets.
*************************************************

NAME
====

   Fwctl::Services::udp_pkt - Fwctl module to hande unidirectional UDP
packets.

SYNOPSIS
========

     accept   udp_pkt -src ROUTER -dst LOGGER --local_port 514 --port 514

DESCRIPTION
===========

   This module will add rules to the firewall for unidrectional UDP
traffic.

OPTIONS
=======

   In addition to the standard options, it accepts the following ones.

-local_port
     This is the source port of the udp packet.

-port
     This is the destination port of the udp packet.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Fwctl module to handle bidirectional UDP traffic.
*************************************************

NAME
====

   Fwctl::Services::udp_service - Fwctl module to handle bidirectional UDP
traffic.

SYNOPSIS
========

     accept   udp_service -src INTERNAL_NET -dst FIREWALL -masq -port 2049

DESCRIPTION
===========

   This module is similar to the tcp_service one, in that it handles
simple bidirectional UDP communication between client and server.  Source
and destination ports are given using the *local_port* and port
respectively. Those defaults to UNPRIVILEGED_PORTS. Enough to shoot you in
the foot, I know.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   fwctl(8) Fwctl(3) Fwctl::RuleSet(3)

Interface to Gd Graphics Library
********************************

NAME
====

   GD.pm - Interface to Gd Graphics Library

SYNOPSIS
========

     use GD;

     # create a new image
     $im = new GD::Image(100,100);

     # allocate some colors
     $white = $im->colorAllocate(255,255,255);
     $black = $im->colorAllocate(0,0,0);
     $red = $im->colorAllocate(255,0,0);
     $blue = $im->colorAllocate(0,0,255);

     # make the background transparent and interlaced
     $im->transparent($white);
     $im->interlaced('true');

     # Put a black frame around the picture
     $im->rectangle(0,0,99,99,$black);

     # Draw a blue oval
     $im->arc(50,50,95,75,0,360,$blue);

     # And fill it with red
     $im->fill(50,50,$red);

     # make sure we are writing to a binary stream
     binmode STDOUT;

     # Convert the image to PNG and print it on standard output
     print $im->png;

DESCRIPTION
===========

   *GD.pm* is a port of Thomas Boutell's gd graphics library (see below).
GD allows you to create color drawings using a large number of graphics
primitives, and emit the drawings as PNG files.

   GD defines the following three classes:

`GD::Image'
     An image class, which holds the image data and accepts graphic
     primitive method calls.

`GD::Font'
     A font class, which holds static font information and used for text
     rendering.

`GD::Polygon'
     A simple polygon object, used for storing lists of vertices prior to
     rendering a polygon into an image.

   A Simple Example:

     #!/usr/local/bin/perl

     use GD;

     # create a new image
     $im = new GD::Image(100,100);

     # allocate some colors
     $white = $im->colorAllocate(255,255,255);
     $black = $im->colorAllocate(0,0,0);
     $red = $im->colorAllocate(255,0,0);
     $blue = $im->colorAllocate(0,0,255);

     # make the background transparent and interlaced
     $im->transparent($white);
     $im->interlaced('true');

     # Put a black frame around the picture
     $im->rectangle(0,0,99,99,$black);

     # Draw a blue oval
     $im->arc(50,50,95,75,0,360,$blue);

     # And fill it with red
     $im->fill(50,50,$red);

     # make sure we are writing to a binary stream
     binmode STDOUT;

     # Convert the image to PNG and print it on standard output
     print $im->png;

   Notes:

  1. To create a new, empty image, send a new() message to GD::Image,
     passing it the width and height of the image you want to create.  An
     image object will be returned.  Other class methods allow you to
     initialize an image from a preexisting PNG, GD or XBM file.

  2. Next you will ordinarily add colors to the image's color table.
     colors are added using a colorAllocate() method call.  The three
     parameters in each call are the red, green and blue (rgb) triples for
     the desired color.  The method returns the index of that color in the
     image's color table.  You should store these indexes for later use.

  3. Now you can do some drawing!  The various graphics primitives are
     described below.  In this example, we do some text drawing, create an
     oval, and create and draw a polygon.

  4. Polygons are created with a new() message to GD::Polygon.  You can
     add points to the returned polygon one at a time using the addPt()
     method. The polygon can then be passed to an image for rendering.

  5. When you're done drawing, you can convert the image into PNG format
     by sending it a png() message.  It will return a (potentially large)
     scalar value containing the binary data for the image.  Ordinarily
     you will print it out at this point or write it to a file.  To ensure
     portability to platforms that differentiate between text and binary
     files, be sure to call binmode() on the file you are writing the
     image to.

Object Constructors: Creating Images
====================================

   The following class methods allow you to create new GD::Image objects.

*$image = GD::Image->new([$width,$height])*
*$image = GD::Image->new(*FILEHANDLE)*
*$image = GD::Image->new($filename)*
*$image = GD::Image->new($data)*
     The new() method is the main constructor for the GD::Image class.
     Called with two integer arguments, it creates a new blank image of the
     specified width and height. For example:

          $myImage = new GD::Image(100,100) || die;

     This will create an image that is 100 x 100 pixels wide.  If you don't
     specify the dimensions, a default of 64 x 64 will be chosen.

     Alternatively, you may create a GD::Image object based on an existing
     image by providing an open filehandle, a filename, or the image data
     itself.  The image formats automatically recognized and accepted are:
     PNG, JPEG, XPM and GD2.  Other formats, including GIF, WBMP, and GD
     version 1, cannot be recognized automatically at this time.

     If something goes wrong (e.g. insufficient memory), this call will
     return undef.

*$image = GD::Image->newFromPng($file)*
*$image = GD::Image->newFromPngData($data)*
     The newFromPng() method will create an image from a PNG file read in
     through the provided filehandle or file path.  The filehandle must
     previously have been opened on a valid PNG file or pipe.  If
     successful, this call will return an initialized image which you can
     then manipulate as you please.  If it fails, which usually happens if
     the thing at the other end of the filehandle is not a valid PNG file,
     the call returns undef.  Notice that the call doesn't automatically
     close the filehandle for you.  But it does call `binmode(FILEHANDLE)'
     for you, on platforms where this matters.

     You may use any of the following as the argument:

          1) a simple filehandle, such as STDIN
          2) a filehandle glob, such as *PNG
          3) a reference to a glob, such as \*PNG
          4) an IO::Handle object
          5) the pathname of a file

     In the latter case, newFromPng() will attempt to open the file for you
     and read the PNG information from it.

          Example1:

          open (PNG,"barnswallow.png") || die;
          $myImage = newFromPng GD::Image(\*PNG) || die;
          close PNG;

          Example2:
          $myImage = newFromPng GD::Image('barnswallow.png');

     To get information about the size and color usage of the information,
     you can call the image query methods described below.

     The newFromPngData() method will create a new GD::Image initialized
     with the PNG format data contained in $data.

*$image = GD::Image->newFromJpeg($file)*
*$image = GD::Image->newFromJpegData($data)*
     These methods will create an image from a JPEG file.  They work just
     like newFromPng() and newFromPngData(), and will accept the same
     filehandle and pathname arguments.

     Bear in mind that JPEG is a 24-bit format, while GD is 8-bit.  This
     means that photographic images will become posterized.

*$image = GD::Image->newFromXbm($file)*
     This works in exactly the same way as `newFromPng', but reads the
     contents of an X Bitmap (black & white) file:

          open (XBM,"coredump.xbm") || die;
          $myImage = newFromXbm GD::Image(\*XBM) || die;
          close XBM;

     There is no newFromXbmData() function, because there is no
     corresponding function in the gd library.

*$image = GD::Image->newFromWMP($file)*
     This creates a new GD::Image object starting from a WBMP-format file
     or filehandle.  There is currently no newFromWMPData() method.

*$image = GD::Image->newFromGd($file)*
*$image = GD::Image->newFromGdData($data)*
     These methods initialize a GD::Image from a Gd file, filehandle, or
     data.  Gd is Tom Boutell's disk-based storage format, intended for the
     rare case when you need to read and write the image to disk quickly.
     It's not intended for regular use, because, unlike PNG or JPEG, no
     image compression is performed and these files can become *BIG*.

          $myImage = newFromGd GD::Image("godzilla.gd") || die;
          close GDF;

*$image = GD::Image->newFromGd2($file)*
*$image = GD::Image->newFromGd2Data($data)*
     This works in exactly the same way as `newFromGd()' and
     newFromGdData, but use the new compressed GD2 image format.

*$image = GD::Image->newFromGd2Part($file,srcX,srcY,width,height)*
     This class method allows you to read in just a portion of a GD2 image
     file.  In additionto a filehandle, it accepts the top-left corner and
     dimensions (width,height) of the region of the image to read.  For
     example:

          open (GDF,"godzilla.gd2") || die;
          $myImage = GD::Image->newFromGd2Part(\*GDF,10,20,100,100) || die;
          close GDF;

     This reads a 100x100 square portion of the image starting from
     position (10,20).

*$image = GD::Image->newFromXpm($filename)*
     This creates a new GD::Image object starting from a filename.  This
     is unlike the other newFrom() functions because it does not take a
     filehandle.  This difference comes from an inconsistency in the
     underlying gd library.

          $myImage = newFromXpm GD::Image('earth.xpm') || die;

     This function is only available if libgd was compiled with XPM
     support.

     NOTE: The libgd library is unable to read certain XPM files, returning
     an all-black image instead.

GD::Image Methods
=================

   Once a GD::Image object is created, you can draw with it, copy it, and
merge two images.  When you are finished manipulating the object, you can
convert it into a standard image file format to output or save to a file.

Image Data Output Methods
-------------------------

   The following methods convert the internal drawing format into standard
output file formats.

*$pngdata = $image->png*
     This returns the image data in PNG format.  You can then print it,
     pipe it to a display program, or write it to a file.  Example:

          $png_data = $myImage->png;
          open (DISPLAY,"| display -") || die;
          binmode DISPLAY;
          print DISPLAY $png_data;
          close DISPLAY;

     Note the use of binmode().  This is crucial for portability to DOSish
     platforms.

*$jpegdata = $image->jpeg([$quality])*
     This returns the image data in JPEG format.  You can then print it,
     pipe it to a display program, or write it to a file.  You may pass an
     optional quality score to jpeg() in order to control the JPEG quality.
     This should be an integer between 0 and 100.  Higher quality scores
     give larger files and better image quality.  If you don't specify the
     quality, jpeg() will choose a good default.

*$gddata = $image->gd*
     This returns the image data in GD format.  You can then print it,
     pipe it to a display program, or write it to a file.  Example:

          binmode MYOUTFILE;
          print MYOUTFILE $myImage->gd;

*$gd2data = $image->gd2*
     Same as gd(), except that it returns the data in compressed GD2
     format.

*$wbmpdata = $image->wbmp([$foreground])*
     This returns the image data in WBMP format, which is a black-and-white
     image format.  Provide the index of the color to become the foreground
     color.  All other pixels will be considered background.

Color Control
-------------

   These methods allow you to control and manipulate the GD::Image color
table.

*$index = $image->colorAllocate(red,green,blue)*
     This allocates a color with the specified red, green and blue
     components and returns its index in the color table, if specified.
     The first color allocated in this way becomes the image's background
     color.  (255,255,255) is white (all pixels on).  (0,0,0) is black (all
     pixels off).  (255,0,0) is fully saturated red.  (127,127,127) is 50%
     gray.  You can find plenty of examples in /usr/X11/lib/X11/rgb.txt.

     If no colors are allocated, then this function returns -1.

     Example:

          $white = $myImage->colorAllocate(0,0,0); #background color
          $black = $myImage->colorAllocate(255,255,255);
          $peachpuff = $myImage->colorAllocate(255,218,185);

*$image->colorDeallocate(colorIndex)*
     This marks the color at the specified index as being ripe for
     reallocation.  The next time colorAllocate is used, this entry will be
     replaced.  You can call this method several times to deallocate
     multiple colors.  There's no function result from this call.

     Example:

          $myImage->colorDeallocate($peachpuff);
          $peachy = $myImage->colorAllocate(255,210,185);

*$index = $image->colorClosest(red,green,blue)*
     This returns the index of the color closest in the color table to the
     red green and blue components specified.  If no colors have yet been
     allocated, then this call returns -1.

     Example:

          $apricot = $myImage->colorClosest(255,200,180);

*$index = $image->colorExact(red,green,blue)*
     This returns the index of a color that exactly matches the specified
     red green and blue components.  If such a color is not in the color
     table, this call returns -1.

          $rosey = $myImage->colorExact(255,100,80);
          warn "Everything's coming up roses.\n" if $rosey >= 0;

*$index = $image->colorResolve(red,green,blue)*
     This returns the index of a color that exactly matches the specified
     red green and blue components.  If such a color is not in the color
     table and there is room, then this method allocates the color in the
     color table and returns its index.

          $rosey = $myImage->colorResolve(255,100,80);
          warn "Everything's coming up roses.\n" if $rosey >= 0;

*$colorsTotal = $image->colorsTotal)* *object method*
     This returns the total number of colors allocated in the object.

          $maxColors = $myImage->colorsTotal;

*$index = $image->getPixel(x,y)* *object method*
     This returns the color table index underneath the specified point.
     It can be combined with rgb() to obtain the rgb color underneath the
     pixel.

     Example:

          $index = $myImage->getPixel(20,100);
          ($r,$g,$b) = $myImage->rgb($index);

*($red,$green,$blue) = $image->rgb($index)*
     This returns a list containing the red, green and blue components of
     the specified color index.

     Example:

          @RGB = $myImage->rgb($peachy);

*$image->transparent($colorIndex)*
     This marks the color at the specified index as being transparent.
     Portions of the image drawn in this color will be invisible.  This is
     useful for creating paintbrushes of odd shapes, as well as for making
     PNG backgrounds transparent for displaying on the Web.  Only one
     color can be transparent at any time. To disable transparency,
     specify -1 for the index.

     If you call this method without any parameters, it will return the
     current index of the transparent color, or -1 if none.

     Example:

          open(PNG,"test.png");
          $im = newFromPng GD::Image(PNG);
          $white = $im->colorClosest(255,255,255); # find white
          $im->transparent($white);
          binmode STDOUT;
          print $im->png;

Special Colors
--------------

   GD implements a number of special colors that can be used to achieve
special effects.  They are constants defined in the GD:: namespace, but
automatically exported into your namespace when the GD module is loaded.

*$image->setBrush($image)*
     You can draw lines and shapes using a brush pattern.  Brushes are just
     images that you can create and manipulate in the usual way. When you
     draw with them, their contents are used for the color and shape of the
     lines.

     To make a brushed line, you must create or load the brush first, then
     assign it to the image using setBrush().  You can then draw in that
     with that brush using the *gdBrushed* special color.  It's often
     useful to set the background of the brush to transparent so that the
     non-colored parts don't overwrite other parts of your image.

     Example:

          # Create a brush at an angle
          $diagonal_brush = new GD::Image(5,5);
          $white = $diagonal_brush->allocateColor(255,255,255);
          $black = $diagonal_brush->allocateColor(0,0,0);
          $diagonal_brush->transparent($white);
          $diagonal_brush->line(0,4,4,0,$black); # NE diagonal

          # Set the brush
          $myImage->setBrush($diagonal_brush);

          # Draw a circle using the brush
          $myImage->arc(50,50,25,25,0,360,gdBrushed);

*$image->setStyle(@colors)*
     Styled lines consist of an arbitrary series of repeated colors and are
     useful for generating dotted and dashed lines.  To create a styled
     line, use setStyle() to specify a repeating series of colors.  It
     accepts an array consisting of one or more color indexes.  Then draw
     using the gdStyled special color.  Another special color,
     *gdTransparent* can be used to introduce holes in the line, as the
     example shows.

     Example:

          # Set a style consisting of 4 pixels of yellow,
          # 4 pixels of blue, and a 2 pixel gap
          $myImage->setStyle($yellow,$yellow,$yellow,$yellow,
          		   $blue,$blue,$blue,$blue,
          		   gdTransparent,gdTransparent);
          $myImage->arc(50,50,25,25,0,360,gdStyled);

     To combine the gdStyled and `gdBrushed' behaviors, you can specify
     `gdStyledBrushed'.  In this case, a pixel from the current brush
     pattern is rendered wherever the color specified in setStyle() is
     neither gdTransparent nor 0.

gdTiled
     Draw filled shapes and flood fills using a pattern.  The pattern is
     just another image.  The image will be tiled multiple times in order
     to fill the required space, creating wallpaper effects.  You must call
     `setTile' in order to define the particular tile pattern you'll use
     for drawing when you specify the gdTiled color.  details.

gdStyled
     The gdStyled color is used for creating dashed and dotted lines.  A
     styled line can contain any series of colors and is created using the
     setStyled() command.

Drawing Commands
----------------

   These methods allow you to draw lines, rectangles, and elipses, as well
as to perform various special operations like flood-fill.

*$image->setPixel($x,$y,$color)*
     This sets the pixel at (x,y) to the specified color index.  No value
     is returned from this method.  The coordinate system starts at the
     upper left at (0,0) and gets larger as you go down and to the right.
     You can use a real color, or one of the special colors gdBrushed,
     gdStyled and gdStyledBrushed can be specified.

     Example:

          # This assumes $peach already allocated
          $myImage->setPixel(50,50,$peach);

*$image->line($x1,$y1,$x2,$y2,$color)*
     This draws a line from (x1,y1) to (x2,y2) of the specified color.  You
     can use a real color, or one of the special colors gdBrushed,
     gdStyled and gdStyledBrushed.

     Example:

          # Draw a diagonal line using the currently defind
          # paintbrush pattern.
          $myImage->line(0,0,150,150,gdBrushed);

*$image->dashedLine($x1,$y1,$x2,$y2,$color)*
     This draws a dashed line from (x1,y1) to (x2,y2) in the specified
     color.  A more powerful way to generate arbitrary dashed and dotted
     lines is to use the setStyle() method described below and to draw with
     the special color gdStyled.

     Example:

          $myImage->dashedLine(0,0,150,150,$blue);

GD::Image::rectangle($x1,$y1,$x2,$y2,$color)
     This draws a rectangle with the specified color.  (x1,y1) and (x2,y2)
     are the upper left and lower right corners respectively.  Both real
     color indexes and the special colors gdBrushed, gdStyled and
     gdStyledBrushed are accepted.

     Example:

          $myImage->rectangle(10,10,100,100,$rose);

*$image->filledRectangle($x1,$y1,$x2,$y2,$color)*
     This draws a rectangle filed with the specified color.  You can use a
     real color, or the special fill color gdTiled to fill the polygon
     with a pattern.

     Example:

          # read in a fill pattern and set it
          $tile = newFromPng GD::Image('happyface.png');
          $myImage->setTile($tile);

          # draw the rectangle, filling it with the pattern
          $myImage->filledRectangle(10,10,150,200,gdTiled);

*$image->polygon($polygon,$color)*
     This draws a polygon with the specified color.  The polygon must be
     created first (see below).  The polygon must have at least three
     vertices.  If the last vertex doesn't close the polygon, the method
     will close it for you.  Both real color indexes and the special
     colors gdBrushed, gdStyled and gdStyledBrushed can be specified.

     Example:

          $poly = new GD::Polygon;
          $poly->addPt(50,0);
          $poly->addPt(99,99);
          $poly->addPt(0,99);
          $myImage->polygon($poly,$blue);

*$image->filledPolygon($poly,$color)*
     This draws a polygon filled with the specified color.  You can use a
     real color, or the special fill color gdTiled to fill the polygon
     with a pattern.

     Example:

          # make a polygon
          $poly = new GD::Polygon;
          $poly->addPt(50,0);
          $poly->addPt(99,99);
          $poly->addPt(0,99);

          # draw the polygon, filling it with a color
          $myImage->filledPolygon($poly,$peachpuff);

*$image->arc($cx,$cy,$width,$height,$start,$end,$color)*
     This draws arcs and ellipses.  (cx,cy) are the center of the arc, and
     (width,height) specify the width and height, respectively.  The
     portion of the ellipse covered by the arc are controlled by start and
     end, both of which are given in degrees from 0 to 360.  Zero is at the
     top of the ellipse, and angles increase clockwise.  To specify a
     complete ellipse, use 0 and 360 as the starting and ending angles.  To
     draw a circle, use the same value for width and height.

     You can specify a normal color or one of the special colors
     *gdBrushed*, gdStyled, or *gdStyledBrushed*.

     Example:

          # draw a semicircle centered at 100,100
          $myImage->arc(100,100,50,50,0,180,$blue);

*$image->fill($x,$y,$color)*
     This method flood-fills regions with the specified color.  The color
     will spread through the image, starting at point (x,y), until it is
     stopped by a pixel of a different color from the starting pixel (this
     is similar to the "paintbucket" in many popular drawing toys).  You
     can specify a normal color, or the special color gdTiled, to
     flood-fill with patterns.

     Example:

          # Draw a rectangle, and then make its interior blue
          $myImage->rectangle(10,10,100,100,$black);
          $myImage->fill(50,50,$blue);

*$image->fillToBorder($x,$y,$bordercolor,$color)*
     Like fill, this method flood-fills regions with the specified color,
     starting at position (x,y).  However, instead of stopping when it
     hits a pixel of a different color than the starting pixel, flooding
     will only stop when it hits the color specified by bordercolor.  You
     must specify a normal indexed color for the bordercolor.  However, you
     are free to use the gdTiled color for the fill.

     Example:

          # This has the same effect as the previous example
          $myImage->rectangle(10,10,100,100,$black);
          $myImage->fillToBorder(50,50,$black,$blue);

Image Copying Commands
----------------------

   Two methods are provided for copying a rectangular region from one
image to another.  One method copies a region without resizing it.  The
other allows you to stretch the region during the copy operation.

   With either of these methods it is important to know that the routines
will attempt to flesh out the destination image's color table to match the
colors that are being copied from the source.  If the destination's color
table is already full, then the routines will attempt to find the best
match, with varying results.

*$image->copy($sourceImage,$dstX,$dstY,$srcX,$srcY,$width,$height)*
     This is the simplest of the several copy operations, copying the
     specified region from the source image to the destination image (the
     one performing the method call).  (srcX,srcY) specify the upper left
     corner of a rectangle in the source image, and (width,height) give the
     width and height of the region to copy.  (dstX,dstY) control where in
     the destination image to stamp the copy.  You can use the same image
     for both the source and the destination, but the source and
     destination regions must not overlap or strange things will happen.

     Example:

          $myImage = new GD::Image(100,100);
          ... various drawing stuff ...
          $srcImage = new GD::Image(50,50);
          ... more drawing stuff ...
          # copy a 25x25 pixel region from $srcImage to
          # the rectangle starting at (10,10) in $myImage
          $myImage->copy($srcImage,10,10,0,0,25,25);

*$image->clone()*
     Make a copy of the image and return it as a new object.  The new image
     will look identical.  However, it may differ in the size of the color
     palette and other nonessential details.

     Example:

          $myImage = new GD::Image(100,100);
          ... various drawing stuff ...
                  $copy = $myImage->clone;

*$image->copyMerge($sourceImage,$dstX,$dstY,$srcX,$srcY,$width,$height,$percent)*
     This copies the indicated rectangle from the source image to the
     destination image, merging the colors to the extent specified by
     percent (an integer between 0 and 100).  Specifying 100% has the same
     effect as copy() - replacing the destination pixels with the source
     image.  This is most useful for highlighting an area by merging in a
     solid rectangle.

     Example:

          $myImage = new GD::Image(100,100);
          ... various drawing stuff ...
          $redImage = new GD::Image(50,50);
          ... more drawing stuff ...
          # copy a 25x25 pixel region from $srcImage to
          # the rectangle starting at (10,10) in $myImage, merging 50%
          $myImage->copyMerge($srcImage,10,10,0,0,25,25,50);

*$image->copyMergeGray($sourceImage,$dstX,$dstY,$srcX,$srcY,$width,$height,$percent)*
     This is identical to copyMerge() except that it preserves the hue of
     the source by converting all the pixels of the destination rectangle
     to grayscale before merging.

*$image->copyResized($sourceImage,$dstX,$dstY,$srcX,$srcY,$destW,$destH,$srcW,$srcH)*
     This method is similar to copy() but allows you to choose different
     sizes for the source and destination rectangles.  The source and
     destination rectangle's are specified independently by (srcW,srcH) and
     (destW,destH) respectively.  copyResized() will stretch or shrink the
     image to accomodate the size requirements.

     Example:

          $myImage = new GD::Image(100,100);
          ... various drawing stuff ...
          $srcImage = new GD::Image(50,50);
          ... more drawing stuff ...
          # copy a 25x25 pixel region from $srcImage to
          # a larger rectangle starting at (10,10) in $myImage
          $myImage->copyResized($srcImage,10,10,0,0,50,50,25,25);

Character and String Drawing
----------------------------

   Gd allows you to draw characters and strings, either in normal
horizontal orientation or rotated 90 degrees.  These routines use a
GD::Font object, described in more detail below.  There are four built-in
fonts, available in global variables gdGiantFont, gdLargeFont,
gdMediumBoldFont, gdSmallFont and gdTinyFont.  Currently there is no way
of dynamically creating your own fonts.

*$image->string($font,$x,$y,$string,$color)*
     This method draws a string startin at position (x,y) in the specified
     font and color.  Your choices of fonts are gdSmallFont,
     gdMediumBoldFont, gdTinyFont, gdLargeFont and gdGiantFont.

     Example:

          $myImage->string(gdSmallFont,2,10,"Peachy Keen",$peach);

*$image->stringUp($font,$x,$y,$string,$color)*
     Just like the previous call, but draws the text rotated
     counterclockwise 90 degrees.

*$image->char($font,$x,$y,$char,$color)*
*$image->charUp($font,$x,$y,$char,$color)*
     These methods draw single characters at position (x,y) in the
     specified font and color.  They're carry-overs from the C interface,
     where there is a distinction between characters and strings.  Perl is
     insensible to such subtle distinctions.

*@bounds = $image->stringTTF($fgcolor,$fontname,$ptsize,$angle,$x,$y,$string)*
*@bounds = GD::Image->stringTTF($fgcolor,$fontname,$ptsize,$angle,$x,$y,$string)*
     This method uses TrueType to draw a scaled, antialiased string using
     the TrueType vector font of your choice.  It requires that libgd to
     have been compiled with TrueType support, and for the appropriate
     TrueType font to be installed on your system.

     The arguments are as follows:

          fgcolor    Color index to draw the string in
          fontname   An absolute or relative path to the TrueType (.ttf) font file
          ptsize     The desired point size (may be fractional)
          angle      The rotation angle, in radians
          x,y        X and Y coordinates to start drawing the string
          string     The string itself

     If successful, the method returns an eight-element list giving the
     boundaries of the rendered string:

          @bounds[0,1]  Lower left corner (x,y)
          @bounds[2,3]  Lower right corner (x,y)
          @bounds[4,5]  Upper right corner (x,y)
          @bounds[6,7]  Upper left corner (x,y)

     In case of an error (such as the font not being available, or TTF
     support not being available), the method returns an empty list and
     sets $@ to the error message.

     You may also call this method from the GD::Image class name, in which
     case it doesn't do any actual drawing, but returns the bounding box
     using an inexpensive operation.  You can use this to perform layout
     operations prior to drawing.

Miscellaneous Image Methods
---------------------------

   These are various utility methods that are useful in some circumstances.

*$image->interlaced([$flag])*
     This method sets or queries the image's interlaced setting.  Interlace
     produces a cool venetian blinds effect on certain viewers.  Provide a
     true parameter to set the interlace attribute.  Provide undef to
     disable it.  Call the method without parameters to find out the
     current setting.

*($width,$height) = $image->getBounds()*
     This method will return a two-member list containing the width and
     height of the image.  You query but not not change the size of the
     image once it's created.

*$flag = $image1->compare($image2)*
     Compare two images and return a bitmap describing the differenes
     found, if any.  The return value must be logically ANDed with one or
     more constants in order to determine the differences.  The following
     constants are available:

          GD_CMP_IMAGE             The two images look different
          GD_CMP_NUM_COLORS        The two images have different numbers of colors
          GD_CMP_COLOR             The two images' palettes differ
          GD_CMP_SIZE_X            The two images differ in the horizontal dimension
          GD_CMP_SIZE_Y            The two images differ in the vertical dimension
          GD_CMP_TRANSPARENT       The two images have different transparency
          GD_CMP_BACKGROUND        The two images have different background colors
          GD_CMP_INTERLACE         The two images differ in their interlace

     The most important of these is GD_CMP_IMAGE, which will tell you
     whether the two images will look different, ignoring differences in
     the order of colors in the color palette and other invisible changes.
     The constants are not imported by default, but must be imported
     individually or by importing the :cmp tag.  Example:

          use GD qw(:DEFAULT :cmp);
          # get $image1 from somewhere
          # get $image2 from somewhere
          if ($image1->compare($image2) & GD_CMP_IMAGE) {
             warn "images differ!";
          }

Polygons
========

   A few primitive polygon creation and manipulation methods are provided.
They aren't part of the Gd library, but I thought they might be handy to
have around (they're borrowed from my qd.pl Quickdraw library).

*$poly = GD::Polygon->new*
     Create an empty polygon with no vertices.

          $poly = new GD::Polygon;

*$poly->addPt($x,$y)*
     Add point (x,y) to the polygon.

          $poly->addPt(0,0);
          $poly->addPt(0,50);
          $poly->addPt(25,25);
          $myImage->fillPoly($poly,$blue);

*($x,$y) = $poly->getPt($index)*
     Retrieve the point at the specified vertex.

          ($x,$y) = $poly->getPt(2);

*$poly->setPt($index,$x,$y)*
     Change the value of an already existing vertex.  It is an error to set
     a vertex that isn't already defined.

          $poly->setPt(2,100,100);

*($x,$y) = $poly->deletePt($index)*
     Delete the specified vertex, returning its value.

          ($x,$y) = $poly->deletePt(1);

*$poly->toPt($dx,$dy)*
     Draw from current vertex to a new vertex, using relative (dx,dy)
     coordinates.  If this is the first point, act like addPt().

          $poly->addPt(0,0);
          $poly->toPt(0,50);
          $poly->toPt(25,-25);
          $myImage->fillPoly($poly,$blue);

*$vertex_count = $poly->length*
     Return the number of vertices in the polygon.

          $points = $poly->length;

*@vertices = $poly->vertices*
     Return a list of all the verticies in the polygon object.  Each member
     of the list is a reference to an (x,y) array.

          @vertices = $poly->vertices;
          foreach $v (@vertices)
             print join(",",@$v),"\n";
          }

*@rect = $poly->bounds*
     Return the smallest rectangle that completely encloses the polygon.
     The return value is an array containing the (left,top,right,bottom) of
     the rectangle.

          ($left,$top,$right,$bottom) = $poly->bounds;

*$poly->offset($dx,$dy)*
     Offset all the vertices of the polygon by the specified horizontal
     (dh) and vertical (dy) amounts.  Positive numbers move the polygon
     down and to the right.

          $poly->offset(10,30);

*$poly->map($srcL,$srcT,$srcR,$srcB,$destL,$dstT,$dstR,$dstB)*
     Map the polygon from a source rectangle to an equivalent position in a
     destination rectangle, moving it and resizing it as necessary.  See
     polys.pl for an example of how this works.  Both the source and
     destination rectangles are given in (left,top,right,bottom)
     coordinates.  For convenience, you can use the polygon's own bounding
     box as the source rectangle.

          # Make the polygon really tall
          $poly->map($poly->bounds,0,0,50,200);

*$poly->scale($sx,$sy)*
     Scale each vertex of the polygon by the X and Y factors indicated by
     sx and sy.  For example scale(2,2) will make the polygon twice as
     large.  For best results, move the center of the polygon to position
     (0,0) before you scale, then move it back to its previous position.

*$poly->transform($sx,$rx,$sy,$ry,$tx,$ty)*
     Run each vertex of the polygon through a transformation matrix, where
     sx and sy are the X and Y scaling factors, rx and ry are the X and Y
     rotation factors, and tx and ty are X and Y offsets.  See the Adobe
     PostScript Reference, page 154 for a full explanation, or experiment.

Font Utilities
==============

   The libgd library (used by the Perl GD library) has built-in support
for about half a dozen fonts, which were converted from public-domain X
Windows fonts.  For more fonts, compile libgd with TrueType support and
use the stringTTF() call.

   If you wish to add more built-in fonts, the directory bdf_scripts
contains two contributed utilities that may help you convert X-Windows
BDF-format fonts into the format that libgd uses internally.  However
these scripts were written for earlier versions of GD which included its
own mini-gd library.  These scripts will have to be adapted for use with
libgd, and the libgd library itself will have to be recompiled and linked!
Please do not contact me for help with these scripts: they are
unsupported.

   Each of these fonts is available both as an imported global (e.g.
gdSmallFont) and as a package method (e.g. *GD::Font->Small*).

gdSmallFont
*GD::Font->Small*
     This is the basic small font, "borrowed" from a well known public
     domain 6x12 font.

gdLargeFont
*GD::Font->Large*
     This is the basic large font, "borrowed" from a well known public
     domain 8x16 font.

gdMediumBoldFont
*GD::Font->MediumBold*
     This is a bold font intermediate in size between the small and large
     fonts, borrowed from a public domain 7x13 font;

gdTinyFont
*GD::Font->Tiny*
     This is a tiny, almost unreadable font, 5x8 pixels wide.

gdGiantFont
*GD::Font->Giant*
     This is a 9x15 bold font converted by Jan Pazdziora from a sans serif
     X11 font.

*$font->nchars*
     This returns the number of characters in the font.

          print "The large font contains ",gdLargeFont->nchars," characters\n";

*$font->offset*
     This returns the ASCII value of the first character in the font

*$width = $font->width*
*$height = $font->height*
height
     These return the width and height of the font.

          ($w,$h) = (gdLargeFont->width,gdLargeFont->height);

Obtaining the C-language version of gd
======================================

   libgd, the C-language version of gd, can be obtained at URL
http://www.boutell.com/gd/.  Directions for installing and using it can be
found at that site.  Please do not contact me for help with libgd.

AUTHOR
======

   The GD.pm interface is copyright 1995-2000, Lincoln D. Stein.  It is
distributed under the same terms as Perl itself.  See the "Artistic
License" in the Perl source code distribution for licensing terms.

   The latest versions of GD.pm are available at

     http://stein.cshl.org/WWW/software/GD

SEE ALSO
========

   Image::Magick

Create barcode image with GD
****************************

NAME
====

   GD::Barcode - Create barcode image with GD

SYNOPSIS
========

   *ex. CGI*

     use GD::Barcode::UPCE;
     binmode(STDOUT);
     print "Content-Type: image/png\n\n";
     print GD::Barcode->new('EAN13', '123456789012')->plot->png;

   *with Error Check*

     my $oGdBar = GD::Barcode->new('EAN13', '12345678901');
     die $GD::Barcode::errStr unless($oGdBar);	#Invalid Length
     $oGdBar->plot->png;

DESCRIPTION
===========

   GD::Barcode is a subclass of GD and allows you to create barcode image
with GD.  This module based on "Generate Barcode Ver 1.02 By Shisei Hanai
97/08/22".

new
---

   *$oGdBar* = GD::Barcode::UPCE->new(*$sType*, *$sTxt*);

   Constructor.  Creates a GD::Barcode::*$sType* object for *$sTxt*.

plot()
------

   *$oGd* = $oGdBar->plot([Height => *$iHeight*, NoText => *0 | 1*]);

   creates GD object with barcode image for the *$sTxt* specified at `new'
in this node method.  *$iHeight* is height of the image. If *NoText* is 1,
the image has no text image of *$sTxt*.

     ex.
      my $oGdB = GD::Barcode->new('EAN13', '123456789012');
      my $oGD = $oGdB->plot(NoText=>1, Height => 20);
      # $sGD is a GD image with Height=>20 pixels, with no text.

barcode()
---------

   *$sPtn* = $oGdBar->barcode();

   returns a barcode pattern in string with '1' and '0'.  '1' means black,
'0' means white.

     ex.
      my $oGdB = GD::Barcode->new('UPCE', '123456789012');
      my $sPtn = $oGdB->barcode();
      # $sPtn = '';

$errStr
-------

   $GD::Barcode::errStr

   has error message.

$text
-----

   $oGdBar->{$text}

   has barcode text based on *$sTxt* specified in `new' in this node
method.

AUTHOR
======

   Kawai Takanori GCD00051@nifty.ne.jp

COPYRIGHT
=========

   The GD::Barocde module is Copyright (c) 2000 Kawai Takanori. Japan.
All rights reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SEE ALSO
========

   GD GD::Barcode subclasses

Create COOP2of5 barcode image with GD
*************************************

NAME
====

   GD::Barcode::COOP2of5 - Create COOP2of5 barcode image with GD

SYNOPSIS
========

   *ex. CGI*

     use GD::Barcode::COOP2of5;
     binmode(STDOUT);
     print "Content-Type: image/png\n\n";
     print GD::Barcode::COOP2of5->new('1234567890')->plot->png;

   *with Error Check*

     my $oGdBar = GD::Barcode::COOP2of5->new('A12345678');
     die $GD::Barcode::COOP2of5::errStr unless($oGdBar);	#Invalid Characters
     $oGdBar->plot->png;

DESCRIPTION
===========

   GD::Barcode::COOP2of5 is a subclass of GD::Barcode and allows you to
create COOP2of5 barcode image with GD.

new
---

   *$oGdBar* = GD::Barcode::COOP2of5->new(*$sTxt*);

   Constructor.  Creates a GD::Barcode::COOP2of5 object for *$sTxt*.
*$sTxt* has numeric characters([0-9]).

plot()
------

   *$oGd* = $oGdBar->plot([Height => *$iHeight*, NoText => *0 | 1*]);

   creates GD object with barcode image for the *$sTxt* specified at `new'
in this node method.  *$iHeight* is height of the image. If *NoText* is 1,
the image has no text image of *$sTxt*.

     ex.
      my $oGdB = GD::Barcode::COOP2of5->new('12345678');
      my $oGD = $oGdB->plot(NoText=>1, Height => 20);
      # $sGD is a GD image with Height=>20 pixels, with no text.

barcode()
---------

   *$sPtn* = $oGdBar->barcode();

   returns a barcode pattern in string with '1' and '0'.  '1' means black,
'0' means white.

     ex.
      my $oGdB = GD::Barcode::COOP2of5->new('12345678');
      my $sPtn = $oGdB->barcode();

$errStr
-------

   $GD::Barcode::COOP2of5::errStr

   has error message.

$text
-----

   $oGdBar->{$text}

   has barcode text based on *$sTxt* specified in `new' in this node
method.

AUTHOR
======

   Kawai Takanori GCD00051@nifty.ne.jp

COPYRIGHT
=========

   The GD::Barocde::COOP2of5 module is Copyright (c) 2000 Kawai Takanori.
Japan.  All rights reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SEE ALSO
========

   GD::Barcode

Create Code39 barcode image with GD
***********************************

NAME
====

   GD::Barcode::Code39 - Create Code39 barcode image with GD

SYNOPSIS
========

   *ex. CGI*

     use GD::Barcode::Code39;
     binmode(STDOUT);
     print "Content-Type: image/png\n\n";
     print GD::Barcode::Code39->new('*CODE39IMG*')->plot->png;

   *with Error Check*

     my $oGdBar = GD::Barcode::Code39->new('*123456789;*');
     die $GD::Barcode::Code39::errStr unless($oGdBar);	#Invalid Characters

DESCRIPTION
===========

   GD::Barcode::Code39 is a subclass of GD::Barcode and allows you to
create CODE-39 barcode image with GD.  This module based on "Generate
Barcode Ver 1.02 By Shisei Hanai 97/08/22".

new
---

   *$oGdBar* = GD::Barcode::Code39->new(*$sTxt*);

   Constructor.  Creates a GD::Barcode::Code39 object for *$sTxt*.

plot()
------

   *$oGd* = $oGdBar->plot([Height => *$iHeight*, NoText => *0 | 1*]);

   creates GD object with barcode image for the *$sTxt* specified at `new'
in this node method.  *$iHeight* is height of the image. If *NoText* is 1,
the image has no text image of *$sTxt*.

     ex.
      my $oGdB = GD::Barcode::Code39->new('*12345*');
      my $oGD = $oGdB->plot(NoText=>1, Height => 20);
      # $sGD is a GD image with Height=>20 pixels, with no text.

barcode()
---------

   *$sPtn* = $oGdBar->barcode();

   returns a barcode pattern in string with '1' and '0'.  '1' means black,
'0' means white.

     ex.
      my $oGdB = GD::Barcode::Code39->new('*12345*');
      my $sPtn = $oGdB->barcode();
      # $sPtn = '';

$errStr
-------

   $GD::Barcode::Code39::errStr

   has error message.

$text
-----

   $oGdBar->{text}

   has barcode text based on *$sTxt* specified in `new' in this node
method.

AUTHOR
======

   Kawai Takanori GCD00051@nifty.ne.jp

COPYRIGHT
=========

   The GD::Barocde::Code39 module is Copyright (c) 2000 Kawai Takanori.
Japan.  All rights reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SEE ALSO
========

   GD::Barcode

Create EAN13(JAN13) barcode image with GD
*****************************************

NAME
====

   GD::Barcode::EAN13 - Create EAN13(JAN13) barcode image with GD

SYNOPSIS
========

   *ex. CGI*

     use GD::Barcode::EAN13;
     binmode(STDOUT);
     print "Content-Type: image/png\n\n";
     print GD::Barcode::EAN13->new('123456789012')->plot->png;

   *with Error Check*

     my $oGdBar = GD::Barcode::EAN13->new('123456789');
     die $GD::Barcode::EAN13::errStr unless($oGdBar);	#Invalid Length

DESCRIPTION
===========

   GD::Barcode::EAN13 is a subclass of GD::Barcode and allows you to
create EAN13(JAN13) barcode image with GD.  This module based on "Generate
Barcode Ver 1.02 By Shisei Hanai 97/08/22".

new
---

   *$oGdBar* = GD::Barcode::EAN13->new(*$sTxt*);

   Constructor.  Creates a GD::Barcode::EAN13 object for *$sTxt*.  *$sTxt*
has 12 or 13 numeric characters([0-9]).  If *$sTxt* has 12 characters,
this module calacurates CD for you.

plot()
------

   *$oGd* = $oGdBar->plot([Height => *$iHeight*, NoText => *0 | 1*]);

   creates GD object with barcode image for the *$sTxt* specified at `new'
in this node method.  *$iHeight* is height of the image. If *NoText* is 1,
the image has no text image of *$sTxt*.

     ex.
      my $oGdB = GD::Barcode::EAN13->new('123456789012');
      my $oGD = $oGdB->plot(NoText=>1, Height => 20);
      # $sGD is a GD image with Height=>20 pixels, with no text.

barcode()
---------

   *$sPtn* = $oGdBar->barcode();

   returns a barcode pattern in string with '1', 'G' and '0'.  '1' means
black, 'G' also means black but little bit long, '0' means white.

     ex.
      my $oGdB = GD::Barcode::EAN13->new('123456789012');
      my $sPtn = $oGdB->barcode();
      # $sPtn = '';

$errStr
-------

   $GD::Barcode::EAN13::errStr

   has error message.

$text
-----

   $oGdBar->{$text}

   has barcode text based on *$sTxt* specified in `new' in this node
method.

AUTHOR
======

   Kawai Takanori GCD00051@nifty.ne.jp

COPYRIGHT
=========

   The GD::Barocde::EAN13 module is Copyright (c) 2000 Kawai Takanori.
Japan.  All rights reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SEE ALSO
========

   GD::Barcode

Create EAN8(JAN8) barcode image with GD
***************************************

NAME
====

   GD::Barcode::EAN8 - Create EAN8(JAN8) barcode image with GD

SYNOPSIS
========

   *ex. CGI*

     use GD::Barcode::EAN8;
     binmode(STDOUT);
     print "Content-Type: image/png\n\n";
     print GD::Barcode::EAN8->new('1234567')->plot->png;

   *with Error Check*

     my $oGdBar = GD::Barcode::EAN8->new('123456789');
     die $GD::Barcode::EAN8::errStr unless($oGdBar);	#Invalid Length

DESCRIPTION
===========

   GD::Barcode::EAN8 is a subclass of GD::Barcode and allows you to create
EAN8(JAN8) barcode image with GD.  This module based on "Generate Barcode
Ver 1.02 By Shisei Hanai 97/08/22".

new
---

   *$oGdBar* = GD::Barcode::EAN8->new(*$sTxt*);

   Constructor.  Creates a GD::Barcode::EAN8 object for *$sTxt*.  *$sTxt*
has 7 or 8 numeric characters([0-9]).  If *$sTxt* has 12 characters, this
module calacurates CD for you.

plot()
------

   *$oGd* = $oGdBar->plot([Height => *$iHeight*, NoText => *0 | 1*]);

   creates GD object with barcode image for the *$sTxt* specified at `new'
in this node method.  *$iHeight* is height of the image. If *NoText* is 1,
the image has no text image of *$sTxt*.

     ex.
      my $oGdB = GD::Barcode::EAN8->new('1234567');
      my $oGD = $oGdB->plot(NoText=>1, Height => 20);
      # $sGD is a GD image with Height=>20 pixels, with no text.

barcode()
---------

   *$sPtn* = $oGdBar->barcode();

   returns a barcode pattern in string with '1', 'G' and '0'.  '1' means
black, 'G' also means black but little bit long, '0' means white.

     ex.
      my $oGdB = GD::Barcode::EAN8->new('1234567');
      my $sPtn = $oGdB->barcode();
      # $sPtn = '';

$errStr
-------

   $GD::Barcode::EAN8::errStr

   has error message.

$text
-----

   $oGdBar->{$text}

   has barcode text based on *$sTxt* specified in `new' in this node
method.

AUTHOR
======

   Kawai Takanori GCD00051@nifty.ne.jp

COPYRIGHT
=========

   The GD::Barocde::EAN8 module is Copyright (c) 2000 Kawai Takanori.
Japan.  All rights reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SEE ALSO
========

   GD::Barcode

Create IATA2of5 barcode image with GD
*************************************

NAME
====

   GD::Barcode::IATA2of5 - Create IATA2of5 barcode image with GD

SYNOPSIS
========

   *ex. CGI*

     use GD::Barcode::IATA2of5;
     binmode(STDOUT);
     print "Content-Type: image/png\n\n";
     print GD::Barcode::IATA2of5->new('1234567890')->plot->png;

   *with Error Check*

     my $oGdBar = GD::Barcode::IATA2of5->new('A12345678');
     die $GD::Barcode::IATA2of5::errStr unless($oGdBar);	#Invalid Characters
     $oGdBar->plot->png;

DESCRIPTION
===========

   GD::Barcode::IATA2of5 is a subclass of GD::Barcode and allows you to
create IATA2of5 barcode image with GD.

new
---

   *$oGdBar* = GD::Barcode::IATA2of5->new(*$sTxt*);

   Constructor.  Creates a GD::Barcode::IATA2of5 object for *$sTxt*.
*$sTxt* has numeric characters([0-9]).

plot()
------

   *$oGd* = $oGdBar->plot([Height => *$iHeight*, NoText => *0 | 1*]);

   creates GD object with barcode image for the *$sTxt* specified at `new'
in this node method.  *$iHeight* is height of the image. If *NoText* is 1,
the image has no text image of *$sTxt*.

     ex.
      my $oGdB = GD::Barcode::IATA2of5->new('12345678');
      my $oGD = $oGdB->plot(NoText=>1, Height => 20);
      # $sGD is a GD image with Height=>20 pixels, with no text.

barcode()
---------

   *$sPtn* = $oGdBar->barcode();

   returns a barcode pattern in string with '1' and '0'.  '1' means black,
'0' means white.

     ex.
      my $oGdB = GD::Barcode::IATA2of5->new('12345678');
      my $sPtn = $oGdB->barcode();

$errStr
-------

   $GD::Barcode::IATA2of5::errStr

   has error message.

$text
-----

   $oGdBar->{$text}

   has barcode text based on *$sTxt* specified in `new' in this node
method.

AUTHOR
======

   Kawai Takanori GCD00051@nifty.ne.jp

COPYRIGHT
=========

   The GD::Barocde::IATA2of5 module is Copyright (c) 2000 Kawai Takanori.
Japan.  All rights reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SEE ALSO
========

   GD::Barcode

Create ITF(Interleaved2of5) barcode image with GD
*************************************************

NAME
====

   GD::Barcode::ITF - Create ITF(Interleaved2of5) barcode image with GD

SYNOPSIS
========

   *ex. CGI*

     use GD::Barcode::ITF;
     binmode(STDOUT);
     print "Content-Type: image/png\n\n";
     print GD::Barcode::ITF->new('1234567890')->plot->png;

   *with Error Check*

     my $oGdBar = GD::Barcode::ITF->new('A12345678');
     die $GD::Barcode::ITF::errStr unless($oGdBar);	#Invalid Characters
     $oGdBar->plot->png;

DESCRIPTION
===========

   GD::Barcode::ITF is a subclass of GD::Barcode and allows you to create
ITF barcode image with GD.

new
---

   *$oGdBar* = GD::Barcode::ITF->new(*$sTxt*);

   Constructor.  Creates a GD::Barcode::ITF object for *$sTxt*.  *$sTxt*
has numeric characters([0-9]).

plot()
------

   *$oGd* = $oGdBar->plot([Height => *$iHeight*, NoText => *0 | 1*]);

   creates GD object with barcode image for the *$sTxt* specified at `new'
in this node method.  *$iHeight* is height of the image. If *NoText* is 1,
the image has no text image of *$sTxt*.

     ex.
      my $oGdB = GD::Barcode::ITF->new('12345678');
      my $oGD = $oGdB->plot(NoText=>1, Height => 20);
      # $sGD is a GD image with Height=>20 pixels, with no text.

barcode()
---------

   *$sPtn* = $oGdBar->barcode();

   returns a barcode pattern in string with '1' and '0'.  '1' means black,
'0' means white.

     ex.
      my $oGdB = GD::Barcode::ITF->new('12345678');
      my $sPtn = $oGdB->barcode();

$errStr
-------

   $GD::Barcode::ITF::errStr

   has error message.

$text
-----

   $oGdBar->{$text}

   has barcode text based on *$sTxt* specified in `new' in this node
method.

AUTHOR
======

   Kawai Takanori GCD00051@nifty.ne.jp

COPYRIGHT
=========

   The GD::Barocde::ITF module is Copyright (c) 2000 Kawai Takanori. Japan.
All rights reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SEE ALSO
========

   GD::Barcode

Create Industrial2of5 barcode image with GD
*******************************************

NAME
====

   GD::Barcode::Industrial2of5 - Create Industrial2of5 barcode image with
GD

SYNOPSIS
========

   *ex. CGI*

     use GD::Barcode::Industrial2of5;
     binmode(STDOUT);
     print "Content-Type: image/png\n\n";
     print GD::Barcode::Industrial2of5->new('1234567890')->plot->png;

   *with Error Check*

     my $oGdBar = GD::Barcode::Industrial2of5->new('A12345678');
     die $GD::Barcode::Industrial2of5::errStr unless($oGdBar);	#Invalid Characters
     $oGdBar->plot->png;

DESCRIPTION
===========

   GD::Barcode::Industrial2of5 is a subclass of GD::Barcode and allows you
to create Industrial2of5 barcode image with GD.

new
---

   *$oGdBar* = GD::Barcode::Industrial2of5->new(*$sTxt*);

   Constructor.  Creates a GD::Barcode::Industrial2of5 object for *$sTxt*.
*$sTxt* has numeric characters([0-9]).

plot()
------

   *$oGd* = $oGdBar->plot([Height => *$iHeight*, NoText => *0 | 1*]);

   creates GD object with barcode image for the *$sTxt* specified at `new'
in this node method.  *$iHeight* is height of the image. If *NoText* is 1,
the image has no text image of *$sTxt*.

     ex.
      my $oGdB = GD::Barcode::Industrial2of5->new('12345678');
      my $oGD = $oGdB->plot(NoText=>1, Height => 20);
      # $sGD is a GD image with Height=>20 pixels, with no text.

barcode()
---------

   *$sPtn* = $oGdBar->barcode();

   returns a barcode pattern in string with '1' and '0'.  '1' means black,
'0' means white.

     ex.
      my $oGdB = GD::Barcode::Industrial2of5->new('12345678');
      my $sPtn = $oGdB->barcode();

$errStr
-------

   $GD::Barcode::Industrial2of5::errStr

   has error message.

$text
-----

   $oGdBar->{$text}

   has barcode text based on *$sTxt* specified in `new' in this node
method.

AUTHOR
======

   Kawai Takanori GCD00051@nifty.ne.jp

COPYRIGHT
=========

   The GD::Barocde::Industrial2of5 module is Copyright (c) 2000 Kawai
Takanori. Japan.  All rights reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SEE ALSO
========

   GD::Barcode

Create Matrix2of5 barcode image with GD
***************************************

NAME
====

   GD::Barcode::Matrix2of5 - Create Matrix2of5 barcode image with GD

SYNOPSIS
========

   *ex. CGI*

     use GD::Barcode::Matrix2of5;
     binmode(STDOUT);
     print "Content-Type: image/png\n\n";
     print GD::Barcode::Matrix2of5->new('1234567890')->plot->png;

   *with Error Check*

     my $oGdBar = GD::Barcode::Matrix2of5->new('A12345678');
     die $GD::Barcode::Matrix2of5::errStr unless($oGdBar);	#Invalid Characters
     $oGdBar->plot->png;

DESCRIPTION
===========

   GD::Barcode::Matrix2of5 is a subclass of GD::Barcode and allows you to
create Matrix2of5 barcode image with GD.

new
---

   *$oGdBar* = GD::Barcode::Matrix2of5->new(*$sTxt*);

   Constructor.  Creates a GD::Barcode::Matrix2of5 object for *$sTxt*.
*$sTxt* has numeric characters([0-9]).

plot()
------

   *$oGd* = $oGdBar->plot([Height => *$iHeight*, NoText => *0 | 1*]);

   creates GD object with barcode image for the *$sTxt* specified at `new'
in this node method.  *$iHeight* is height of the image. If *NoText* is 1,
the image has no text image of *$sTxt*.

     ex.
      my $oGdB = GD::Barcode::Matrix2of5->new('12345678');
      my $oGD = $oGdB->plot(NoText=>1, Height => 20);
      # $sGD is a GD image with Height=>20 pixels, with no text.

barcode()
---------

   *$sPtn* = $oGdBar->barcode();

   returns a barcode pattern in string with '1' and '0'.  '1' means black,
'0' means white.

     ex.
      my $oGdB = GD::Barcode::Matrix2of5->new('12345678');
      my $sPtn = $oGdB->barcode();

$errStr
-------

   $GD::Barcode::Matrix2of5::errStr

   has error message.

$text
-----

   $oGdBar->{$text}

   has barcode text based on *$sTxt* specified in `new' in this node
method.

AUTHOR
======

   Kawai Takanori GCD00051@nifty.ne.jp

COPYRIGHT
=========

   The GD::Barocde::Matrix2of5 module is Copyright (c) 2000 Kawai
Takanori. Japan.  All rights reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SEE ALSO
========

   GD::Barcode

Create NW7 barcode image with GD
********************************

NAME
====

   GD::Barcode::NW7 - Create NW7 barcode image with GD

SYNOPSIS
========

   *ex. CGI*

     use GD::Barcode::NW7;
     binmode(STDOUT);
     print "Content-Type: image/png\n\n";
     print GD::Barcode::NW7->new('123456789012')->plot->png;

   *with Error Check*

     my $oGdBar = GD::Barcode::NW7->new('123456789E');
     die $GD::Barcode::NW7::errStr unless($oGdBar);	#Invalid Characters

DESCRIPTION
===========

   GD::Barcode::NW7 is a subclass of GD::Barcode and allows you to create
NW7 barcode image with GD.  This module based on "Generate Barcode Ver
1.02 By Shisei Hanai 97/08/22".

new
---

   *$oGdBar* = GD::Barcode::NW7->new(*$sTxt*);

   Constructor.  Creates a GD::Barcode::NW7 object for *$sTxt*.  *$sTxt*
has variable length string with (0-9, - $ / . + ABCD).

plot()
------

   *$oGd* = $oGdBar->plot([Height => *$iHeight*, NoText => *0 | 1*]);

   creates GD object with barcode image for the *$sTxt* specified at `new'
in this node method.  *$iHeight* is height of the image. If *NoText* is 1,
the image has no text image of *$sTxt*.

     ex.
      my $oGdB = GD::Barcode::NW7->new('123456789012');
      my $oGD = $oGdB->plot(NoText=>1, Height => 20);
      # $sGD is a GD image with Height=>20 pixels, with no text.

barcode()
---------

   *$sPtn* = $oGdBar->barcode();

   returns a barcode pattern in string with '1' and '0'.  '1' means black,
'0' means white.

     ex.
      my $oGdB = GD::Barcode::NW7->new('123456789012');
      my $sPtn = $oGdB->barcode();
      # $sPtn = '';

$errStr
-------

   $GD::Barcode::NW7::errStr

   has error message.

$text
-----

   $oGdBar->{$text}

   has barcode text based on *$sTxt* specified in `new' in this node
method.

AUTHOR
======

   Kawai Takanori GCD00051@nifty.ne.jp

COPYRIGHT
=========

   The GD::Barocde::NW7 module is Copyright (c) 2000 Kawai Takanori. Japan.
All rights reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SEE ALSO
========

   GD::Barcode

Create UPC-A barcode image with GD
**********************************

NAME
====

   GD::Barcode::UPCA - Create UPC-A barcode image with GD

SYNOPSIS
========

   *ex. CGI*

     use GD::Barcode::UPCA;
     binmode(STDOUT);
     print "Content-Type: image/png\n\n";
     print GD::Barcode::UPCA->new('12345678901')->plot->png;

   *with Error Check*

     my $oGdBar = GD::Barcode::UPCA->new('123456789');
     die $GD::Barcode::UPCA::errStr unless($oGdBar);	#Invalid Length

DESCRIPTION
===========

   GD::Barcode::UPCA is a subclass of GD::Barcode and allows you to create
UPC-A barcode image with GD.  This module based on "Generate Barcode Ver
1.02 By Shisei Hanai 97/08/22".

new
---

   *$oGdBar* = GD::Barcode::UPCA->new(*$sTxt*);

   Constructor.  Creates a GD::Barcode::UPCA object for *$sTxt*.  *$sTxt*
has 11 or 12 numeric characters([0-9]).  If *$sTxt* has 11 characters,
this module calacurates CD for you.

plot()
------

   *$oGd* = $oGdBar->plot([Height => *$iHeight*, NoText => *0 | 1*]);

   creates GD object with barcode image for the *$sTxt* specified at `new'
in this node method.  *$iHeight* is height of the image. If *NoText* is 1,
the image has no text image of *$sTxt*.

     ex.
      my $oGdB = GD::Barcode::UPCA->new('12345678901');
      my $oGD = $oGdB->plot(NoText=>1, Height => 20);
      # $sGD is a GD image with Height=>20 pixels, with no text.

barcode()
---------

   *$sPtn* = $oGdBar->barcode();

   returns a barcode pattern in string with '1', 'G' and '0'.  '1' means
black, 'G' also means black but little bit long, '0' means white.

     ex.
      my $oGdB = GD::Barcode::UPCA->new('12345678901');
      my $sPtn = $oGdB->barcode();
      # $sPtn = '';

$errStr
-------

   $GD::Barcode::UPCA::errStr

   has error message.

$text
-----

   $oGdBar->{$text}

   has barcode text based on *$sTxt* specified in `new' in this node
method.

AUTHOR
======

   Kawai Takanori GCD00051@nifty.ne.jp

COPYRIGHT
=========

   The GD::Barocde::UPCA module is Copyright (c) 2000 Kawai Takanori.
Japan.  All rights reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SEE ALSO
========

   GD::Barcode

Create UPC-E barcode image with GD
**********************************

NAME
====

   GD::Barcode::UPCE - Create UPC-E barcode image with GD

SYNOPSIS
========

   *ex. CGI*

     use GD::Barcode::UPCE;
     binmode(STDOUT);
     print "Content-Type: image/png\n\n";
     print GD::Barcode::UPCE->new('123456')->plot->png;

   *with Error Check*

     my $oGdBar = GD::Barcode::UPCE->new('123456789');
     die $GD::Barcode::UPCE::errStr unless($oGdBar);	#Invalid Length

DESCRIPTION
===========

   GD::Barcode::UPCE is a subclass of GD::Barcode and allows you to create
UPC-E barcode image with GD.  This module based on "Generate Barcode Ver
1.02 By Shisei Hanai 97/08/22".

new
---

   *$oGdBar* = GD::Barcode::UPCE->new(*$sTxt*);

   Constructor.  Creates a GD::Barcode::UPCE object for *$sTxt*.  *$sTxt*
has 6 or 7 or 8 numeric characters([0-9]).  If *$sTxt* has 6 characters,
this module adds '0' at the front of *$sTxt*.  and calculates CD for you.
If *$sTxt* has 7 characters, this module calaculates CD for you.

plot()
------

   *$oGd* = $oGdBar->plot([Height => *$iHeight*, NoText => *0 | 1*]);

   creates GD object with barcode image for the *$sTxt* specified at `new'
in this node method.  *$iHeight* is height of the image. If *NoText* is 1,
the image has no text image of *$sTxt*.

     ex.
      my $oGdB = GD::Barcode::UPCE->new('123456');
      my $oGD = $oGdB->plot(NoText=>1, Height => 20);
      # $sGD is a GD image with Height=>20 pixels, with no text.

barcode()
---------

   *$sPtn* = $oGdBar->barcode();

   returns a barcode pattern in string with '1', 'G' and '0'.  '1' means
black, 'G' also means black but little bit long, '0' means white.

     ex.
      my $oGdB = GD::Barcode::UPCE->new('123456');
      my $sPtn = $oGdB->barcode();
      # $sPtn = '';

$errStr
-------

   $GD::Barcode::UPCE::errStr

   has error message.

$text
-----

   $oGdBar->{$text}

   has barcode text based on *$sTxt* specified in `new' in this node
method.

AUTHOR
======

   Kawai Takanori GCD00051@nifty.ne.jp

COPYRIGHT
=========

   The GD::Barocde::UPCE module is Copyright (c) 2000 Kawai Takanori.
Japan.  All rights reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SEE ALSO
========

   GD::Barcode

Graph Plotting Module for Perl 5
********************************

NAME
====

   GD::Graph - Graph Plotting Module for Perl 5

SYNOPSIS
========

   use GD::Graph::moduleName;

DESCRIPTION
===========

   *GD::Graph* is a *perl5* module to create charts using the GD module.
The following classes for graphs with axes are defined:

`GD::Graph::lines'
     Create a line chart.

`GD::Graph::bars'
     Create a bar chart.

`GD::Graph::points'
     Create an chart, displaying the data as points.

`GD::Graph::linespoints'
     Combination of lines and points.

`GD::Graph::area'
     Create a graph, representing the data as areas under a line.

`GD::Graph::mixed'
     Create a mixed type graph, any combination of the above. At the moment
     this is fairly limited. Some of the options that can be used with some
     of the individual graph types won't work very well. Multiple bar
     graphs in a mixed graph won't display very nicely.

   Additional types:

`GD::Graph::pie'
     Create a pie chart.

EXAMPLES
========

   See the samples directory in the distribution, and read the Makefile
there.

USAGE
=====

   Fill an array of arrays with the x values and the values of the data
sets.  Make sure that every array is the same size, otherwise *GD::Graph*
will complain and refuse to compile the graph.

     @data = (
       ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"],
       [    1,    2,    5,    6,    3,  1.5,    1,     3,     4],
       [ sort { $a <=> $b } (1, 2, 5, 6, 3, 1.5, 1, 3, 4) ]
     );

   If you don't have a value for a point in a certain dataset, you can use
undef, and the point will be skipped.

   Create a new *GD::Graph* object by calling the new method on the graph
type you want to create (*chart* is *bars*, lines, points, *linespoints*,
*mixed* or *pie*).

     $graph = GD::Graph::chart->new(400, 300);

   Set the graph options.

     $graph->set(
         x_label           => 'X Label',
         y_label           => 'Y label',
         title             => 'Some simple graph',
         y_max_value       => 8,
         y_tick_number     => 8,
         y_label_skip      => 2
     );

   and plot the graph.

     my $gd = $my_graph->plot(\@data);

   Then do whatever your current version of GD allows you to do to save the
file. For versions of GD older than 1.19, you'd do something like:

     open(IMG, '>file.gif') or die $!;
     binmode IMG;
     print IMG $gd->gif;
     close IMG;

   and for newer versions (1.20 and up) you'd write

     open(IMG, '>file.png') or die $!;
     binmode IMG;
     print IMG $gd->png;

   or

     open(IMG, '>file.gd2') or die $!;
     binmode IMG;
     print IMG $gd->gd2;

   Then there's also of course the possibility of using a shorter version
(for each of the export functions that GD supports):

     print IMG $my_graph->plot(\@data)->gif;
     print IMG $my_graph->plot(\@data)->png;
     print IMG $my_graph->plot(\@data)->gd;
     print IMG $my_graph->plot(\@data)->gd2;

   If you want to write something that doesn't require your code to 'know'
whether to use gif or png, you could do something like:

     if ($gd->can('png')) { # blabla }

   or you can use the convenience method `export_format':

     my $format = $my_graph->export_format;
     open(IMG, ">file.$format") or die $!;
     binmode IMG;
     print IMG $my_graph->plot(\@data)->$format();
     close IMG;

   or for CGI scripts:

     use CGI qw(:standard);
     #...
     my $format = $my_graph->export_format;
     print header("image/$format");
     binmode STDOUT;
     print $my_graph->plot(\@data)->$format();

   (the parentheses after $format are necessary, to help the compiler
decide that you mean a method name there)

METHODS
=======

Methods for all graphs
----------------------

GD::Graph::chart->new([width,height])
     Create a new object $graph with optional width and heigth.  Default
     width = 400, default height = 300. *chart* is either *bars*, lines,
     points, *linespoints*, area, *mixed* or *pie*.

$graph->set_text_clr(*colour name*)
     Set the colour of the text. This will set the colour of the titles,
     labels, and axis labels to *colour name*. Also see the options
     *textclr*, *labelclr* and *axislabelclr*.

$graph->set_title_font(font specification)
     Set the font that will be used for the title of the chart.  See
     `"FONTS"' in this node.

$graph->plot(*\@data*)
     Plot the chart, and return the GD::Image object.

$graph->set(attrib1 => value1, attrib2 => value2 ...)
     Set chart options. See OPTIONS section.

$graph->get(attrib1, attrib2)
     Returns a list of the values of the attributes. In scalar context
     returns the value of the first attribute only.

$graph->gd()
     Get the GD::Image object that is going to be used to draw on. You can
     do this either before or after calling the plot method, to do your own
     drawing.

     Note that if you draw on the GD::Image object before calling the plot
     method that you are responsible for making sure that the background
     colour is correct and for setting transparency.

$graph->export_format()
     Query the export format of the GD library in use.  In scalar context,
     it returns 'gif', 'png' or undefined, which is sufficient for most
     people's use. In a list context, it returns a list of all the formats
     that are supported by the current version of GD. It can be called as
     a class or object method

$graph->can_do_ttf()
     Returns true if the current GD library supports TrueType fonts, False
     otherwise. Can also be called as a class method or static method.

Methods for Pie charts
----------------------

$graph->set_label_font(font specification)
$graph->set_value_font(font specification)
     Set the font that will be used for the label of the pie or the values
     on the pie.  See `"FONTS"' in this node.

Methods for charts with axes.
-----------------------------

$graph->set_x_label_font(font specification)
$graph->set_y_label_font(font specification)
$graph->set_x_axis_font(font specification)
$graph->set_y_axis_font(font specification)
$graph->set_values_font(font specification)
     Set the font for the x and y axis label, the x and y axis value
     labels, and for the values printed above the data points.  See
     `"FONTS"' in this node.

$graph->get_hotspot($dataset, $point)
     Experimental: Return a coordinate specification for a point in a
     dataset. Returns a list. If the point is not specified, returns a
     list of array references for all points in the dataset. If the
     dataset is also not specified, returns a list of array references for
     each data set.  See `"HOTSPOTS"' in this node.

OPTIONS
=======

Options for all graphs
----------------------

width, height
     The width and height of the canvas in pixels Default: 400 x 300.
     *NB* At the moment, these are read-only options. If you want to set
     the size of a graph, you will have to do that with the new method.

t_margin, b_margin, l_margin, r_margin
     Top, bottom, left and right margin of the canvas. These margins will
     be left blank.  Default: 0 for all.

logo
     Name of a logo file. Generally, this should be the same format as your
     version of GD exports images in. At the moment there is no support for
     reading gd format files or xpm files.  Default: no logo.

logo_resize, logo_position
     Factor to resize the logo by, and the position on the canvas of the
     logo. Possible values for logo_position are 'LL', 'LR', 'UL', and
     'UR'.  (lower and upper left and right).  Default: 'LR'.

transparent
     If set to a true value, the produced image will have the background
     colour marked as transparent (see also option *bgclr*).  Default: 1.

interlaced
     If set to a true value, the produced image will be interlaced.
     Default: 1.

Colours
-------

bgclr, fgclr, boxclr, accentclr, shadowclr
     Drawing colours used for the chart: background, foreground (axes and
     grid), axis box fill colour, accents (bar, area and pie outlines), and
     shadow (currently only for bars).

     All colours should have a valid value as described in `"COLOURS"' in
     this node, except boxclr, which can be undefined, in which case the
     box will not be filled.

shadow_depth
     Depth of a shadow, positive for right/down shadow, negative for
     left/up shadow, 0 for no shadow (default).  Also see the `shadowclr'
     and bar_spacing options.

labelclr, axislabelclr, legendclr, valuesclr, textclr
     Text Colours used for the chart: label (labels for the axes or pie),
     axis label (misnomer: values printed along the axes, or on a pie
     slice), legend text, shown values text, and all other text.

     All colours should have a valid value as described in `"COLOURS"' in
     this node.

dclrs (short for datacolours)
     This controls the colours for the bars, lines, markers, or pie slices.
     This should be a reference to an array of colour names as defined in
     GD/Graph/colour, (`perldoc GD::Graph::colour'
     for the names available).

          $graph->set( dclrs => [ qw(green pink blue cyan) ] );

     The first (fifth, ninth) data set will be green, the next pink, etc.

     A colour can be undef, in which case the data set will not be drawn.
     This can be useful for cumulative bar sets where you want certain data
     series (often the first one) not to show up, which can be used to
     emulate error bars (see examples 1-7 and 6-3 in the distribution).
     Default: [ qw(lred lgreen lblue lyellow lpurple cyan lorange) ]

borderclrs
     This controls the colours of the borders of the bars data sets. Like
     dclrs, it is a reference to an array of colour names as defined in
     GD/Graph/colour.  Setting a border colour to
     undef means the border will not be drawn.

cycle_clrs
     If set to a true value, bars will not have a colour from dclrs per
     dataset, but per point. The colour sequence will be identical for each
     dataset. Note that this may have a weird effect if you are drawing
     more than one data set. If this is set to a value larger than 1 the
     border colour of the bars will cycle through the colours in
     borderclrs.

accent_treshold
     Not really a colour, but it does control a visual aspect: Accents on
     bars are only drawn when the width of a bar is larger than this number
     of pixels. Accents inside areas are only drawn when the horizontal
     distance between points is larger than this number.  Default 4

Options for graphs with axes.
-----------------------------

   options for *bars*, lines, points, *linespoints*, *mixed* and area
charts.

long_ticks, tick_length
     If *long_ticks* is a true value, ticks will be drawn the same length
     as the axes.  Otherwise ticks will be drawn with length
     *tick_length*. if *tick_length* is negative, the ticks will be drawn
     outside the axes.  Default: long_ticks = 0, tick_length = 4.

     These attributes can also be set for x and y axes separately with
     x_long_ticks, y_long_ticks, x_tick_length and y_tick_length.

x_ticks
     If x_ticks is a true value, ticks will be drawm for the x axis.
     These ticks are subject to the values of *long_ticks* and
     *tick_length*.  Default: 1.

y_tick_number
     Number of ticks to print for the Y axis. Use this, together with
     *y_label_skip* to control the look of ticks on the y axis.  Default:
     5.

y_number_format
     This can be either a string, or a reference to a subroutine. If it is
     a string, it will be taken to be the first argument to an sprintf,
     with the value as the second argument:

          $label = sprintf( $s->{y_number_format, $value );

     If it is a code reference, it will be executed with the value as the
     argument:

          $label = &{$s->{y_number_format}}($value);

     This can be useful, for example, if you want to reformat your values
     in currency, with the - sign in the right spot. Something like:

          sub y_format
          {
              my $value = shift;
              my $ret;

          if ($value >= 0)
          {
              $ret = sprintf("\$%d", $value * $refit);
          }
          else
          {
              $ret = sprintf("-\$%d", abs($value) * $refit);
          }

          return $ret;
              }

          $my_graph->set( 'y_number_format' => \&y_format );

     (Yes, I know this can be much shorter and more concise)

     Default: undef.

x_label_skip, y_label_skip
     Print every x_label_skipth number under the tick on the x axis, and
     every *y_label_skip*th number next to the tick on the y axis.
     Default: 1 for both.

x_tick_offset
     When x_label_skip is used, this will skip the first x_tick_offset
     values in the labels before starting to print. Let me give an
     example. If you have a series of X labels like

          qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)

     and you set x_label_skip to 3, you will see ticks on the X axis for
     Jan, Apr, Jul, Oct and Dec. This is not always what is wanted. If you
     set x_tick_offset to 1, you get Feb, May, Aug, Nov and Dec, and if
     you set it to 2, you get Mar, Jun Sep and Dec, and this last one
     definitely looks better. A combination of 6 and 5 also works nice for
     months.

     Note that the value for x_tick_offset is periodical. This means that
     it will have the same effect for each nteger n in x_tick_offset + n *
     x_label_skip.

x_all_ticks
     Force a print of all the x ticks, even if x_label_skip is set to a
     value Default: 0.

x_label_position
     Controls the position of the X axis label (title). The value for this
     should be between 0 and 1, where 0 means aligned to the left, 1 means
     aligned to the right, and 1/2 means centered.  Default: 3/4

y_label_position
     Controls the position of both Y axis labels (titles). The value for
     this should be between 0 and 1, where 0 means aligned to the bottom, 1
     means aligned to the top, and 1/2 means centered.  Default: 1/2

x_labels_vertical
     If set to a true value, the X axis labels will be printed vertically.
     This can be handy in case these labels get very long.  Default: 0.

x_plot_values, y_plot_values
     If set to a true value, the values of the ticks on the x or y axes
     will be plotted next to the tick. Also see *x_label_skip,
     y_label_skip*.  Default: 1 for both.

box_axis
     Draw the axes as a box, if true.  Default: 1.

two_axes
     Use two separate axes for the first and second data set. The first
     data set will be set against the left axis, the second against the
     right axis. If this is set to a true value, trying to use anything
     else than 2 datasets will generate an error.  Default: 0.

zero_axis
     If set to a true value, the axis for y values of 0 will always be
     drawn. This might be useful in case your graph contains negative
     values, but you want it to be clear where the zero value is. (see also
     zero_axis_only and *box_axes*).  Default: 0.

zero_axis_only
     If set to a true value, the zero axis will be drawn (see zero_axis),
     and no axis at the bottom of the graph will be drawn.  The labels for
     X values will be placed on the zero exis.  Default: 0.

y_max_value, y_min_value
     Maximum and minimum value displayed on the y axis. If two_axes is a
     true value, then y1_min_value, y1_max_value (for the left axis), and
     y2_min_value, y2_max_value (for the right axis) take precedence over
     these.

     The range (y_min_value..y_max_value) has to include all the values of
     the data points, or *GD::Graph* will die with a message.

     For bar and area graphs, the range (y_min_value..y_max_value) has to
     include 0. If it doesn't, the values will be adapted before attempting
     to draw the graph.

     Default: Computed from data sets.

axis_space
     This space will be left blank between the axes and the tick value
     text.  Default: 4.

text_space
     This space will be left open between text elements and the graph (text
     elements are title and axis labels.

     Default: 8.

cumulate
     If this attribute is set to a true value, the data sets will be
     cumulated. This means that they will be stacked on top of each other.
     A side effect of this is that overwrite will be set to a true value.

     Notes: This only works for bar and area charts at the moment.

     If you have negative values in your data sets, setting this option
     might produce odd results. Of course, the graph itself would be quite
     meaningless.

overwrite
     If set to 0, bars of different data sets will be drawn next to each
     other. If set to 1, they will be drawn in front of each other.
     Default: 0.

     Note: Setting overwrite to 2 to produce cumulative sets is deprecated,
     and may disappear in future versions of GD::Graph.  Instead see the
     cumulate attribute.

correct_width
     If this is set to a true value and x_tick_number is false, then the
     width of the graph will be recalculated to make sure that each data
     point is exactly an integer number of pixels wide. You probably never
     want to fiddle with this.

     When this value is true, you will need to make sure that the number of
     data points is smaller than the number of pixels in the plotting area
     of the chart. If you get errors saying that your horizontal size if
     too small, you may need to manually switch this off, or consider using
     something else than a bar type for your chart.

     Default: 1 for bar, calculated at runtime for mixed charts, 0 for
     others.

Plotting data point values with the data point
----------------------------------------------

   Sometimes you will want to plot the value of a data point or bar above
the data point for clarity. GD::Graph allows you to control this in a
generic manner, or even down to the single point.

show_values
     Set this to 1 to display the value of each data point above the point
     or bar itself. No effort is being made to ensure that there is enough
     space for the text.

     Set this to a GD::Graph::Data object, or an array reference of the
     same shape, with the same dimensions as your data object that you
     pass in to the plot method. The reason for this option is that it
     allows you to make a copy of your data set, and selectively set
     points to undef to disable plotting of them.

          my $data = GD::Graph::Data->new(
          	[ [ 'A', 'B', 'C' ], [ 1, 2, 3 ], [ 11, 12, 13 ] ]);
          my $values = $data->copy;
          $values->set_y(1, 1, undef);
          $values->set_y(2, 0, undef);

          $graph->set(show_values => $values);
          $graph->plot($data);

     Default: 0.

values_vertical
     If set to a true value, the values will be printed vertically, instead
     of horizontally. This can be handy if the values are long numbers.
     Default: 0.

values_space
     Space to insert between the data point and the value to print.
     Default: 4.

values_format
     How to format the values for display. See y_number_format for more
     information.  Default: undef.

Options for graphs with a numerical X axis
------------------------------------------

   First of all: GD::Graph does not support numerical x axis the way it
should. Data for X axes should be equally spaced. That understood: There
is some support to make the printing of graphs with numerical X axis
values a bit better, thanks to Scott Prahl. If the option x_tick_number is
set to a defined value, GD::Graph will attempt to treat the X data as
numerical.

   Extra options are:

x_tick_number
     If set to *'auto'*, GD::Graph will attempt to format the X axis in a
     nice way, based on the actual X values. If set to a number, that's the
     number of ticks you will get. If set to undef, GD::Graph will treat X
     data as labels.  Default: undef.

x_min_value, x_max_value
     The minimum and maximum value to use for the X axis.  Default:
     computed.

x_number_format
     See y_number_format

x_label_skip
     See y_label_skip

Options for graphs with bars
----------------------------

bar_width
     The width of a bar in pixels. Also see bar_spacing.  Use bar_width If
     you want to have fixed-width bars, no matter how wide the chart gets.
     Default: as wide as possible, within the constraints of the chart size
     and bar_spacing setting.

bar_spacing
     Number of pixels to leave open between bars. This works well in most
     cases, but on some platforms, a value of 1 will be rounded off to 0.
     Use bar_spacing to get a fixed amount of space between bars, with
     variable bar widths, depending on the width of the chart.  Note that
     if bar_width is also set, this setting will be ignored, and
     automatically calculated.  Default: 0

Options for graphs with lines
-----------------------------

line_types
     Which line types to use for lines and *linespoints* graphs. This
     should be a reference to an array of numbers:

          $graph->set( line_types => [3, 2, 4] );

     Available line types are 1: solid, 2: dashed, 3: dotted, 4:
     dot-dashed.

     Default: [1] (always use solid)

line_type_scale
     Controls the length of the dashes in the line types. default: 6.

line_width
     The width of the line used in lines and *linespoints* graphs, in
     pixels.  Default: 1.

skip_undef
     For all other axes graph types, the default behaviour is (by their
     nature) to not draw a point when the Y value is undef. For line
     charts the point gets skipped as well, but the line is drawn between
     the points n-1 to n+1 directly. If skip_undef has a true value, there
     will be a gap in the chart where a Y value is undefined.

     Note that a line will not be drawn unless there are *at least two*
     consecutive data points exist that have a defined value. The following
     data set will only plot a very short line towards the end if
     skip_undef is set:

          @data = (
            [ qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct ) ],
            [ 1, undef, 2, undef, 3, undef, 4, undef, 5, 6 ]
          );

     This option is useful when you have a consecutive gap in your data, or
     with linespoints charts. If you have data where you have intermittent
     gaps, be careful when you use this.  Default value: 0

Options for graphs with points
------------------------------

markers
     This controls the order of markers in points and *linespoints*
     graphs.  This should be a reference to an array of numbers:

          $graph->set( markers => [3, 5, 6] );

     Available markers are: 1: filled square, 2: open square, 3: horizontal
     cross, 4: diagonal cross, 5: filled diamond, 6: open diamond, 7:
     filled circle, 8: open circle.

     Default: [1,2,3,4,5,6,7,8]

marker_size
     The size of the markers used in points and *linespoints* graphs, in
     pixels.  Default: 4.

Options for mixed graphs
------------------------

types
     A reference to an array with graph types, in the same order as the
     data sets. Possible values are:

          $graph->set( types => [qw(lines bars points area linespoints)] );
          $graph->set( types => ['lines', undef, undef, 'bars'] );

     values that are undefined or unknown will be set to default_type.

     Default: all set to default_type

default_type
     The type of graph to draw for data sets that either have no type set,
     or that have an unknown type set.

     Default: lines

Graph legends (axestype graphs only)
------------------------------------

   At the moment legend support is minimal.

   Methods

$graph->set_legend(*@legend_keys*);
     Sets the keys for the legend. The elements of @legend_keys correspond
     to the data sets as provided to plot().

     If a key is undef or an empty string, the legend entry will be
     skipped.

$graph->set_legend_font(*font name*);
     Sets the font for the legend text (see `"FONTS"' in this node).
     Default: GD::gdTinyFont.

   Options

legend_placement
     Where to put the legend. This should be a two letter key of the form:
     'B[LCR]|R[TCB]'. The first letter indicates the placement (Bottom or
     Right), and the second letter the alignment (Left, Right, Center,
     Top, or Bottom).  Default: 'BC'

     If the legend is placed at the bottom, some calculations will be made
     to ensure that there is some 'intelligent' wrapping going on. if the
     legend is placed at the right, all entries will be placed below each
     other.

legend_spacing
     The number of pixels to place around a legend item, and between a
     legend 'marker' and the text.  Default: 4

legend_marker_width, legend_marker_height
     The width and height of a legend 'marker' in pixels.  Defaults: 12, 8

lg_cols
     If you, for some reason, need to force the legend at the bottom to
     have a specific number of columns, you can use this.  Default:
     computed

Options for pie graphs
----------------------

  1. If set to a true value, the pie chart will be drawn with a 3d look.
     Default: 1.

  2. pie_height The thickness of the pie when 3d is true.  Default: 0.1 x
     height.

  3. start_angle The angle at which the first data slice will be
     displayed, with 0 degrees being "6 o'clock".  Default: 0.

  4. suppress_angle If a pie slice is smaller than this angle (in
     degrees), a label will not be drawn on it. Default: 0.

  5. label Print this label below the pie. Default: undef.

COLOURS
=======

   All references to colours in the options for this module have been
shortened to clr. The main reason for this was that I didn't want to
support two spellings for the same word ('colour' and 'color')

   Wherever a colour is required, a colour name should be used from the
package GD/Graph/colour.
`perldoc GD::Graph::colour' should give you the documentation for that
module, containing all valid colour names. I will probably change this to
read the systems rgb.txt file if it is available.

FONTS
=====

   Depending on your version of GD, this accepts both GD builtin fonts or
the name of a TrueType font file. In the case of a TrueType font, you must
specify the font size. See GD/Text, for more details and
other things, since all font handling in GD::Graph is delegated to there.

   Examples:

     $my_graph->set_title_font('/fonts/arial.ttf', 18);
     $my_graph->set_legend_font(gdTinyFont);
     $my_graph->set_legend_font(
         ['verdana', 'arial', gdMediumBoldFont], 12)

   (The above discussion is based on GD::Text 0.65. Older versions have
more restrictive behaviour).

HOTSPOTS
========

   *Note that this is an experimental feature, and its interface may, and
likely will, change in the future*

   GD::Graph keeps an internal set of coordinates for each data point. This
specification is very similar to the HTML image map specification, and in
fact exists mainly for that purpose. You can get at these hotspots with
the `get_hotspot' method. This method accepts two optional arguments, the
number of the dataset you're interested in, and the number of the point in
that dataset you're interested in. When called with two arguments, the
method returns a list of one of the following forms:

     'rect', x1, y1, x2, y2
     'poly', x1, y1, x2, y2, x3, y3, ....
     'line', xs, ys, xe, ye, width

   The parameters for `rect' are the coordinates of the corners of the
rectangle, the parameters for poly are the coordinates of the vertices of
the polygon, and the parameters for the line are the coordinates for the
start and end point, and the line width.  It should be possible to almost
directly translate these lists into HTML image map specifications.

   If the second argument to `get_hotspot' is omitted, a list of
references to arrays will be returned. This list represents all the points
in the dataset specified, and each array referred to is of the form
outlined above.

     ['rect', x1, y1, x2, y2 ], ['rect', x1, y1, x2, y2], ...

   if both arguments to `get_hotspot' are omitted, the list that comes
back will contain references to arrays for each data set, which in turn
contain references to arrays for each point.

     [
       ['rect', x1, y1, x2, y2 ], ['rect', x1, y1, x2, y2], ...
     ],
     [
       ['line', xs, ys, xe, ye, w], ['line', xs, ys, xe, ye, w], ...
     ],...

NOTES
=====

   As with all Modules for Perl: Please stick to using the interface. If
you try to fiddle too much with knowledge of the internals of this module,
you could get burned. I may change them at any time.

BUGS
====

   GD::Graph objects cannot be reused. To create a new plot, you have to
create a new GD::Graph object.

AUTHOR
======

   Martien Verbruggen <mgjv@tradingpost.com.au>

Copyright
---------

   GIFgraph: Copyright (c) 1995-1999 Martien Verbruggen.  Chart::PNGgraph:
Copyright (c) 1999 Steve Bonds.  GD::Graph: Copyright (c) 1999 Martien
Verbruggen.

   All rights reserved. This package is free software; you can redistribute
it and/or modify it under the same terms as Perl itself.

Acknowledgements
----------------

   Thanks to Steve Bonds for releasing Chart::PNGgraph, and keeping the
code alive when GD reached version 1.20, and I didn't have time to do
something about it.

   Thanks to the following people for contributing code, or sending me
fixes: Dave Belcher, Steve Bonds, Mike Bremford, Damon Brodie, Gary
Deschaines brian d foy, Edwin Hildebrand, Ari Jolma, Tim Meadowcroft,
Honza Pazdziora, Scott Prahl, Vegard Vesterheim, Jeremy Wadsack.

   And some people whose real name I don't know, and whose email address
I'd rather not publicise without their consent.

SEE ALSO
========

   See GD/Graph/FAQ, GD/Graph/Data,
GD/Graph/Error, GD/Graph/colour,

Create 3D Graphs with GD and GD::Graph
**************************************

NAME
====

   GD::Graph3D - Create 3D Graphs with GD and GD::Graph

SYNOPSIS
========

     use GD::Graph::moduleName;
     @data = (
        ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
        [ 1203,  3500,  3973,  2859,  3012,  3423,  1230]
     );
     $graph->set(
     	x_label           => 'Day of the week',
     	y_label           => 'Number of hits',
     	title             => 'Daily Summary of Web Site',
     );
     $graph = GD::Graph::moduleName->new( 400, 300 );
     my $gd = $graph->plot( \@data );

   Where *moduleName* is one of `bars3d', `lines3d' or `pie3d'.

DESCRIPTION
===========

   This is the GD::Graph3d extensions module. It provides 3D graphs for the
GD::Graph module by Martien Verbruggen, which in turn generates graph
using Lincoln Stein's GD.pm.

   You use these modules just as you would any of the GD::Graph modules,
except that they generate 3d-looking graphs. Each graph type is described
below with only the options that are unique to the 3d version. The modules
are based on their 2d versions (e.g. GD::Graph::bars3d works like
GD::Graph::bars), and support all the options in those. Make sure to read
the documentation on GD::Graph.

GD::Graph::pie3d
     This is merely a wrapper around GD::Graph::pie for consistency. It
     also sets 3d pie mode by default (which GD::Graph does as of version
     1.22).  All options are exactly as in GD::Graph::pie.

GD::Graph::bars3d
     This works like GD::Graph::bars, but draws 3d bars. The following
     settings are new or changed in GD::Graph::bars3d.

    bar_depth
          Sets the z-direction depth of the bars. This defaults to 10. If
          you have a large number of bars or a small chart width, you may
          want to change this.  A visually good value for this is
          approximately width_of_chart / number_of_bars.

    overwrite
          In GD::Graph::bars, multiple series of bars are normally drawn
          side-by-side.  You can set overwrite to 1 to tell it to draw
          each series behind the previous one. By setting overwrite to 2
          you can have them drawn on top of each other, that is the series
          are stacked.

    shading
          By default this is set to '1' and will shade and highlight the
          bars (and axes).  The light source is at top-left-center which
          scan well for most computer users. You can disable the shading
          of bars and axes by specifiying a false value for this option.

GD::Graph::lines3d
     This works like GD::Graph::lines, but draws 3d line. The following
     settings are new or changed in GD::Graph::line3d.

    line_depth
          Sets the z-direction depth of the lines. This defaults to 10. If
          you have a large number of bars or a small chart width, you may
          want to change this.  A visually good value for this is
          approximately width_of_chart / number_of_bars.

    shading
          By default this is set to '1' and will shade and highlight the
          line (and axes).  The light source is at top-left-center which
          scan well for most computer users. You can disable the shading
          of lines and axes by specifiying a false value for this option.

VERSION
=======

   0.54 (Septemnber 4, 2000)

INSTALLATION
============

   You will need to have the GD::Graph version 1.30 or later installed.
You should also have Perl version 5.005 or 5.6 installed.

   To install, just do the normal:

     perl Makefile.PL
     make
     make install

   The documentation is in GD::Graph::Graph3d.pod.

AUTHOR
======

   Jeremy Wadsack for Wadsack-Allen Digital Group.
<`dgsupport@wadsack-allen.com'>

   Most of the modules are based on the GD::Graph modules by Martien
Verbruggen.

LATEST RELEASE
==============

   The latest release is available from CPAN: http://www.cpan.org/.

COPYRIGHT
=========

   Copyright (c) 1999,2000 Wadsack-Allen. All rights reserved.

   Much of the original code is from GD::Graph:

   GIFgraph: Copyright (c) 1995-1999 Martien Verbruggen.

   Chart::PNGgraph: Copyright (c) 1999 Steve Bonds.

   GD::Graph: Copyright (c) 1999 Martien Verbruggen.

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Data set encapsulation for GD::Graph
************************************

NAME
====

   GD::Graph::Data - Data set encapsulation for GD::Graph

SYNOPSIS
========

   use GD::Graph::Data;

DESCRIPTION
===========

   This module encapsulates the data structure that is needed for GD::Graph
and friends. An object of this class contains a list of X values, and a
number of lists of corresponding Y values. This only really makes sense if
the Y values are numerical, but you can basically store anything.
Undefined values have a special meaning to GD::Graph, so they are treated
with care when stored.

   Many of the methods of this module are intended for internal use by
GD::Graph and the module itself, and will most likely not be useful to
you. Many won't even *seem* useful to you...

EXAMPLES
========

     use GD::Graph::Data;
     use GD::Graph::bars;

     my $data = GD::Graph::Data->new();

     $data->read(file => '/data/sales.dat', delimiter => ',');
     $data = $data->copy(wanted => [2, 4, 5]);

     # Add the newer figures from the database
     use DBI;
     # do DBI things, like connecting to the database, statement
     # preparation and execution

     while (@row = $sth->fetchrow_array)
     {
     	  $data->add_point(@row);
     }

     my $chart = GD::Graph::bars->new();
     my $gd = $chart->plot($data);

   or for quick changes to legacy code

     # Legacy code builds array like this
     @data = ( [qw(Jan Feb Mar)], [1, 2, 3], [5, 4, 3], [6, 3, 7] );

     # And we quickly need to do some manipulations on that
     my $data = GD::Graph::Data->new();
     $data->copy_from(\@data);

     # And now do all the new stuff that's wanted.
     while (@foo = bar_baz())
     {
     	  $data->add_point(@foo);
     }

METHODS
=======

$data = GD::Graph::Data->new()
------------------------------

   Create a new GD::Graph::Data object.

$data->set_x($np, $value);
--------------------------

   Set the X value of point *$np* to $value. Points are numbered starting
with 0. You probably will never need this. Returns undef on failure.

$data->get_x($np)
-----------------

   Get the X value of point *$np*. See `"set_x"' in this node.

$data->set_y($nd, $np, $value);
-------------------------------

   Set the Y value of point *$np* in data set *$nd* to $value. Points are
numbered starting with 0, data sets are numbered starting with 1.  You
probably will never need this. Returns undef on failure.

$data->get_y($nd, $np)
----------------------

   Get the Y value of point *$np* in data set *$nd*. See `"set_y"' in this
node. This will return undef on an error, but the fact that it returns
undef does not mean there was an error (since undefined values can be
stored, and therefore returned).

$data->get_y_cumulative($nd, $np)
---------------------------------

   Get the cumulative value of point *$np* in data set<$nd>. The
cumulative value is obtained by adding all the values of the points *$np*
in the data sets 1 to *$nd*.

$data->get_min_max_x
--------------------

   Returns a list of the minimum and maximum x value or the empty list on
failure.

$data->get_min_max_y($nd)
-------------------------

   Returns a list of the minimum and maximum y value in data set $nd or the
empty list on failure.

$data->get_min_max_y_all()
--------------------------

   Returns a list of the minimum and maximum y value in all data sets or
the empty list on failure.

$data->add_point($X, $Y1, $Y2 ...)
----------------------------------

   Adds a point to the data set. The base for the addition is the current
number of X values. This means that if you have a data set with the
contents

     (X1,  X2)
     (Y11, Y12)
     (Y21)
     (Y31, Y32, Y33, Y34)

   a $data->add_point(Xx, Y1x, Y2x, Y3x, Y4x) will result in

     (X1,    X2,    Xx )
     (Y11,   Y12,   Y1x)
     (Y21,   undef, Y2x)
     (Y31,   Y32,   Y3x,  Y34)
     (undef, undef, Y4x)

   In other words: beware how you use this. As long as you make sure that
all data sets are of equal length, this method is safe to use.

$data->num_sets()
-----------------

   Returns the number of data sets.

$data->num_points()
-------------------

   In list context, returns a list with its first element the number of X
values, and the subsequent elements the number of respective Y values for
each data set. In scalar context returns the number of points that have an
X value set, i.e. the number of data sets that would result from a call to
`make_strict'.

$data->x_values()
-----------------

   Return a list of all the X values.

$data->y_values($nd)
--------------------

   Return a list of the Y values for data set *$nd*. Data sets are
numbered from 1. Returns the empty list if $nd is out of range, or if the
data set at $nd is empty.

$data->reset() OR GD::Graph::Data->reset()
------------------------------------------

   As an object method: Reset the data container, get rid of all data and
error messages. As a class method: get rid of accumulated error messages
and possible other crud.

$data->make_strict()
--------------------

   Make all data set lists the same length as the X list by truncating data
sets that are too long, and filling data sets that are too short with
undef values. always returns a true value.

$data->cumulate(preserve_undef => boolean)
------------------------------------------

   The cumulate parameter will summarise the Y value sets as follows: the
first Y value list will be unchanged, the second will contain a sum of the
first and second, the third will contain the sum of first, second and
third, and so on.  Returns undef on failure.

   if the argument *preserve_undef* is set to a true value, then the sum
of exclusively undefined values will be preserved as an undefined value.
If it is not present or a false value, undef will be treated as zero.
Note that this still will leave undefined values in the first data set
alone.

   Note: Any non-numerical defined Y values will be treated as 0, but you
really shouldn't be using this to store that sort of Y data.

$data->wanted(indexes)
----------------------

   Removes all data sets except the ones in the argument list. It will also
reorder the data sets in the order given. Returns undef on failure.

   To remove all data sets except the first, sixth and second, in that
order:

     $data->wanted(1, 6, 2) or die $data->error;

$data->reverse
--------------

   Reverse the order of the data sets.

$data->copy_from($data_ref)
---------------------------

   Copy an 'old' style GD::Graph data structure or another GD::Graph::Data
object into this object. This will remove the current data. Returns undef
on failure.

$data->copy()
-------------

   Returns a copy of the object, or undef on failure.

$data->read(*arguments*)
------------------------

   Read a data set from a file. This will remove the current data. returns
undef on failure. This method uses the standard module Text::ParseWords to
parse lines. If you don't have this for some odd reason, don't use this
method, or your program will die.

   *Data file format*: The default data file format is tab separated data
(which can be changed with the delimiter argument). Comment lines are any
lines that start with a #. In the following example I have replaced
literal tabs with <tab> for clarity

     # This is a comment, and will be ignored
     Jan<tab>12<tab>24
     Feb<tab>13<tab>37
     # March is missing
     Mar<tab><tab>
     Apr<tab>9<tab>18

   Valid arguments are:

   file, mandatory. The file name of the file to read from.

     $data->read(file => '/data/foo.dat') or die $data->error;

   *no_comment*, optional. Give this a true value if you don't want lines
with an initial # to be skipped.

     $data->read(file => '/data/foo.dat', no_comment => 1);

   delimiter, optional. A regular expression that will become the
delimiter instead of a single tab.

     $data->read(file => '/data/foo.dat', delimiter => '\s+');
     $data->read(file => '/data/foo.dat', delimiter => qr/\s+/);

$data->error() OR GD::Graph::Data->error()
------------------------------------------

   Returns a list of all the errors that the current object has
accumulated. In scalar context, returns the last error. If called as a
class method it works at a class level.

   This method is inherited, see GD/Graph/Error, for
more information.

$data->has_error() OR GD::Graph::Data->has_error()
--------------------------------------------------

   Returns true if the object (or class) has errors pending, false if not.
In some cases (see `"copy"' in this node) this is the best way to check
for errors.

   This method is inherited, see GD/Graph/Error, for
more information.

NOTES
=====

   As with all Modules for Perl: Please stick to using the interface. If
you try to fiddle too much with knowledge of the internals of this module,
you could get burned. I may change them at any time.  Specifically, I
probably won't always keep this implemented as an array reference.

AUTHOR
======

   Martien Verbruggen <mgjv@tradingpost.com.au>

Copyright
---------

   Copyright (c) 2000 Martien Verbruggen.

   All rights reserved. This package is free software; you can redistribute
it and/or modify it under the same terms as Perl itself.

SEE ALSO
========

   See GD/Graph, GD/Graph/Error,

Error handling for GD::Graph classes
************************************

NAME
====

   GD::Graph::Error - Error handling for GD::Graph classes

SYNOPSIS
========

   use GD::Graph::Error_subclass;

DESCRIPTION
===========

   This class is a parent for all GD::Graph classes, including
GD::Graph::Data, and offers error and warning handling and some debugging
control.

   Errors are stored in a lexical hash in this package, so the
implementation of the subclass should be irrelevant.

PUBLIC METHODS
==============

   These methods can be used by users of any of the subclasses of
GD::Graph::Error to get at the errors of objects or classes.

$object->error() OR Class->error()
----------------------------------

   Returns a list of all the errors that the current object has
accumulated. In scalar context, returns the last error. If called as a
class method it works at a class level. This is handy when a constructor
fails, for example:

     my $data = GD::Graph::Data->new()
         or die GD::Graph::Data->error;
     $data->read(file => '/foo/bar.data')
         or die $data->error;

   or if you really are only interested in the last error:

     $data->read(file => '/foo/bar.data')
         or die scalar $data->error;

   This implementation does not clear the error list, so if you don't die
on errors, you will need to make sure to never ask for anything but the
last error (put this in scalar context) or to call `clear_error()' now and
again.

   Errors are more verbose about where the errors originated if the
$GD::Graph::Error::Debug variable is set to a true value, and even more
verbose if this value is larger than 5.

   If $Debug is larger than 3, both of these will always return the full
list of errors and warnings (although the meaning of has_warning and
`has_error' does not change).

$object->has_error() OR Class->has_error()
------------------------------------------

$object->has_warning() OR Class->has_warning()
----------------------------------------------

   Returns true if there are pending errors (warnings) for the object (or
class). To be more precise, it returns a list of errors in list context,
and the number of errors in scalar context.

   This allows you to check for errors and warnings after a large number of
operations which each might fail:

     $data->read(file => '/foo/bar.data') or die $data->error;
     while (my @foo = $sth->fetchrow_array)
     {
         $data->add_point(@foo);
     }
     $data->set_x(12, 'Foo');
     $data->has_warning and warn $data->warning;
     $data->has_error   and die  $data->error;

   The reason to call this, instead of just calling error() or warning()
and looking at its return value, is that this method is much more
efficient and fast.

   If you want to count anything as bad, just set $ErrorLevel to 0, after
which you only need to call `has_error'.

$object->clear_errors() or Class->clear_errors()
------------------------------------------------

   Clears all outstanding errors.

PROTECTED METHODS
=================

   These methods are only to be called from within this class and its
Subclasses.

$object->_set_error(*arg*) or Class->_set_error(*arg*)
------------------------------------------------------

$object->_set_warning(*arg*) or Class->_set_warning(*arg*)
----------------------------------------------------------

   Subclasses call this to set an error. The argument can be a reference
to an array, of which the first element should be the error level, and the
second element the error message. Alternatively, it can just be the
message, in which case the error level will be assumed to be $ErrorLevel.

   If the error level is >= $CriticalLevel the program will die, using
Carp::croak to display the current message, as well as all the other error
messages pending.

   In the current implementation these are almost identical when called
with a scalar argument, except that the default ewrror level is different.
When called with an array reference, they are identical in function. This
may change in the future. They're mainly here for code clarity.

$object->_move_errors
---------------------

   Move errors from an object into the class it belongs to.  This can be
useful if something nasty happens in the constructor, while instantiating
one of these objects, and you need to move these errors into the class
space before returning. (see GD::Graph::Data::new for an example)

VARIABLES
=========

$GD::Graph::Error::Debug
------------------------

   The higher this value, the more verbose error messages will be. At the
moment, any true value will cause the line number and source file of the
caller at the top of the stack to be included, a value of more than 2 will
include the error severity, and a value of more than 5 will also include
the direct caller's (i.e. the spot where the error message was generated)
line number and package. Default: 0.

$GD::Graph::Error::ErrorLevel
-----------------------------

   Errors levels below this value will be counted as warnings, and error
levels above (and inclusive) up to $CriticalLevel will be counted as
errors. This is also the default error level for the `_set_error()'
method. This value should be 0 or larger, and smaller than $CriticalLevel.
Default: 5.

$GD::Graph::Error::CriticalLevel
--------------------------------

   Any errorlevel of or above this level will immediately cause the program
to die with the specified message, using Carp::croak. Default: 10.

NOTES
=====

   As with all Modules for Perl: Please stick to using the interface. If
you try to fiddle too much with knowledge of the internals of this module,
you could get burned. I may change them at any time.

AUTHOR
======

   Martien Verbruggen <mgjv@tradingpost.com.au>

Copyright
---------

   Copyright (c) 2000 Martien Verbruggen.

   All rights reserved. This package is free software; you can redistribute
it and/or modify it under the same terms as Perl itself.

SEE ALSO
========

   See GD/Graph, GD/Graph/Data,

Frequently asked questions
**************************

NAME
====

   GD::Graph - Frequently asked questions

DESCRIPTION
===========

I am drawing a bar chart, and the chart area is a lot smaller than the image. What is going on?
-----------------------------------------------------------------------------------------------

   As of version 1.30, GD::Graph automatically corrects the width of the
plotting area of a chart if it needs to draw bars (i.e. for bars and some
mixed charts). This is necessary, because rounding errors cause irregular
gaps between or overlaps of bars if the bar is not an exact integer number
of pixels wide.

   If you want the old behaviour back, set the correct_with attribute to a
false value.

I have my data in some format that doesn't look at all like the array that I am supposed to give to GD::Graph's plot method.
----------------------------------------------------------------------------------------------------------------------------

   Check out the GD::Graph::Data class.

Where is the ActiveState ppm of GD::Graph?
------------------------------------------

   Ask them. I have asked them, but didn't get an answer. I don't know what
to do to get it included in their set of ppms, and I really do not have
the time to keep asking them.

Do you have some example code for me?
-------------------------------------

   The distribution has a large set of examples in it. If you don't have
the original distribution, please get it from CPAN (http://www.cpan.org/
or some local mirror).

Will you support X or Y?
------------------------

   If you send me a patch that (in a decent manner) adds the functionality
to the latest version, I may very well add it for the next release. If you
don't send me a patch, but just a question, you will have to be patient.

Why does export_format give me a weird string, instead of just 'png' or 'gif'?
------------------------------------------------------------------------------

   As of version 1.31, export_format in a list context returns all formats
that GD can export. If you are only interested in the answer 'gif' or
'png', make sure that you call it in a scalar context.

     $export_format = GD::Graph->export_format;
     $export_format = $graph->export_format;
     print "Export format is ", scalar $graph->export_format, "\n";
     print "Export format is " .  $graph->export_format . "\n";
     @export_formats = $graph->export_format;

AUTHOR
======

   Martien Verbruggen <mgjv@tradingpost.com.au>

   Copyright (c) 2000 Martien Verbruggen.

   All rights reserved. This package is free software; you can redistribute
it and/or modify it under the same terms as Perl itself.

generate HTML map text for GD::Graph diagramms.
***********************************************

NAME
====

   *GD::Graph::Map* - generate HTML map text for GD::Graph diagramms.

SYNOPSIS
========

   use GD::Graph::Map;

   $map = new GD::Graph::Map($gr_object);

   $map->set(key1 => value1, key2 => value2 ...);

   $HTML_map = $map->imagemap($gr_file, \@data);

DESCRIPTION
===========

   This is a *perl5* module to generate HTML map text for following
GD::Graph objects *GD::Graph::pie*, *GD::Graph::bars*, *GD::Graph::lines*,
*GD::Graph::area*, *GD::Graph::point* and *GD::Graph::linespoints*.  As a
result of its work is created HTML code containing IMG and MAP tags.  You
simply need to insert this code into the necessary place of your HTML page.
In the inserted thus image, its certain parts are the references and at a
choice their mouse in a status line of your browser displays the additional
information (see Samples).

SAMPLES
=======

   See the samples directory in the distribution.

USAGE
=====

   First of all you must create the *GD::Graph* object and set options if
it is necessary.  Then create array of data and use plot routine for
create graph image.  For example create *GD::Graph::pie* object:

     $graph = new GD::Graph::pie;

     $graph->set('title'        => 'A Pie Chart',
                 'label'        => 'Label',
                 'axislabelclr' => 'black',
                 'pie_height'   => 80);

     @data = (["1st","2nd","3rd","4th","5th","6th"],
              [    4,    2,    3,    4,    3,  3.5]);

     $GIFimage = 'Demo.gif';
     open GIF, '>$GIFimage';
     print GIF $graph->plot(\@data)->gif;
     close GIF;

   Then create *GD::Graph::Map* object. And set options using set routine,
or set it in constructor immediately. If it is necessary create hrefs and
legend arrays:

     $map = new GD::Graph::Map($graph, newWindow => 1);

     $map->set(info => "%x slice contains %.1p% of %s (%x)");

   Create HTML map text using the same array of data as use
GD::Graph::plot routine and name of the your graph file:

     $HTML_map = $map->imagemap($GIFimage, \@data);

   Now you can insert $HTML_map into the necessary place of your HTML page.
You also can create only MAP tag with determined by you map name. For more
information look at noImgMarkup and mapName options of the set routine.

METHODS AND FUNCTIONS
=====================

Constructor
     Constructor of object has following syntax:

          new GD::Graph::Map($gr_object,
            [key1 => value1, key2 => value2 ...]);

     where $gr_object this is one of the following graph objects:
     *GD::Graph::pie*, *GD::Graph::bars*, *GD::Graph::lines*,
     *GD::Graph::area*, *GD::Graph::point* or *GD::Graph::linespoints*;
     key1, value1 ... the same as using in the set routine.  NOTE: Before
     use constructor you should at first set all properties for graph
     object, because they will be using for generetaing properly HTML map.

imagemap(*$gr_file*, *\@data*)
     Generate HTML map text using the graph file $file and reference to
     array of data - \@data, which must be the same as using in plot
     routine.

set(*key1* => *value1*, *key2* => *value2* .... )
     Set options. See OPTIONS.

OPTIONS
=======

*hrefs*, *lhrefs*
     Sets hyper reference for each data (hrefs), and for each legend
     (lhrefs).  Array @hrefs must the same size as arrays in @data list,
     otherwise null elements of @hrefs will set to default. Similarly
     array @lhrefs must the same size as the legend array. Default uses
     the simple JavaScript code 'javascript:;' instead reference, which do
     nothing (but in the some browsers it can work incorrectly).

     Example of *@hrefs* array:

     for the *GD::Graph::pie* object:

     if     @data  = ([  "1st",  "2nd",  "3rd"],                  [
     4,      2,      3]);

     then   @hrefs =  ["1.htm","2.htm","3.htm"];

     for the other objects:

     if     @data  = ([  "1st",  "2nd",  "3rd"],                  [
     5,     12,     24],                  [      1,      2,      5]);

     then   @hrefs = (["1.htm","2.htm","3.htm"],
     ["4.htm","5.htm","6.htm"]);

     Example of *@lhrefs* array;

     if    @legend = [  'one',  'two','three'];

     then  @lhrefs = ["1.htm","2.htm","3.htm"];

info, legend
     Set information string for the data and for the legend. It will be
     displayed in the status line of your browser. Format of this string
     the same for each data, but you can use special symbols for receive
     individual information. Now available following symbols: *%x* - Will
     be replaced on the x values in @data (first array) *%y* - Will be
     replaced on the y values in @data (other arrays) %s - Will be
     replaced on the sum of all y values.  *%l* - Will be replaced on the
     legend. For all objects, except the *GD::Graph::pie* object.  *%p* -
     Will be replaced on the value, which show what part from all contains
     this data (in percentages).

     %s and *%p* symbols can useing only in the *GD::Graph::pie* object.
     *%l* symbol vice versa available for all objects, except the
     *GD::Graph::pie* object. And *%x*, *%y* symbols available for all
     objects, except the *GD::Graph::lines* and the *GD::Graph::area*
     objects.  For the numerical parameters (%x, %y, %s and %p) you can
     use special format (the same as uses sprintf routine) for round data:
     %.d{x|y|p|s}, where 'd' is a digit from 0 to 9.  For example %.0p or
     %.3x. It is desirable uses if %x, %y, %s or %p is the floating
     numbers.  Default is 'x=%x y=%y' for info, and '%l' for legend.

     You can set any attribute in the IMG tag (except UseMap, Src, Width,
     Height and Border, they will be set automatically) use set routine:
     set(img_option => value), where 'option' is the IMG attribute. For
     instance: routine set(img_Alt => 'Example') will include Alt='Example'
     in the IMG tag.

*newWindow*, *window_**
     If the newWindow attribute is set to the TRUE and link does not
     contains JavaScript code (like javascript:), that link will be open
     in the new navigator window. Parameters of the new window you can
     establish using the window_* parameters, similarly the img_*.

mapName
     If mapName is TRUE the map will have this name. Default is time().

noImgMarkup
     If noImgMarkup is TRUE will be printed only the MAP tag, without the
     <Img UseMap=... > markup. You will have to print your own.  Useful if
     the Graph is generated and poured directly to the a web-browser and
     not plotted to a GIF file.

AUTHOR
======

   Roman Kosenko

Contact info
------------

   E-mail:    ra@amk.lg.ua

   Home page: http://amk.lg.ua/~ra/Map

Copyright
---------

   Copyright (C) 1999-2000 Roman Kosenko.  All rights reserved.  This
package is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Colour manipulation routines for use with GD::Graph
***************************************************

NAME
====

   Colour - Colour manipulation routines for use with GD::Graph

SYNOPSIS
========

   use GD::Graph::colour qw(:colours :lists :files :convert);

DESCRIPTION
===========

   The *GD::Graph::colour* package provides a few routines to work with
colours. The functionality of this package is mainly defined by what is
needed, now and historically, by the GD::Graph modules.

FUNCTIONS
=========

colour_list( *number of colours* )
----------------------------------

   Returns a list of *number of colours* colour names known to the package.
Exported with the :lists tag.

sorted_colour_list( *number of colours* )
-----------------------------------------

   Returns a list of *number of colours* colour names known to the package,
sorted by luminance or hue.  *NB.* Right now it always sorts by luminance.
Will add an option in a later stage to decide sorting method at run time.
Exported with the :lists tag.

_rgb( *colour name* )
---------------------

   Returns a list of the RGB values of *colour name*. if the colour name
is a string of the form that is acceptable to the hex2rgb sub, then the
colour will be added to the list dynamically.  Exported with the :colours
tag.

_hue( *R,G,B* )
---------------

   Returns the hue of the colour with the specified RGB values.  Exported
with the :colours tag.

_luminance( *R,G,B* )
---------------------

   Returns the luminance of the colour with the specified RGB values.
Exported with the :colours tag.

add_colour(colourname => [$r, $g, $b]) or add_colour('#7fe310')
---------------------------------------------------------------

   Self-explanatory.  Exported with the :colours tag.

rgb2hex($red, $green, $blue)
----------------------------

hex2rgb('#7fe310')
------------------

   These functions translate a list of RGB values into a hexadecimal
string, as is commonly used in HTML and the Image::Magick API, and vice
versa.  Exported with the :convert tag.

read_rgb( `file name' )
-----------------------

   Reads in colours from a rgb file as used by the X11 system.

   Doing something like:

     use GD::Graph::bars;
     use GD::Graph::colour;

     GD::Graph::colour::read_rgb("rgb.txt") or die "cannot read colours";

   Will allow you to use any colours defined in rgb.txt in your graph.
Exported with the :files tag.

PREDEFINED COLOUR NAMES
=======================

   white, lgray, gray, dgray, black, lblue, blue, dblue, gold, lyellow,
yellow, dyellow, lgreen, green, dgreen, lred, red, dred, lpurple, purple,
dpurple, lorange, orange, pink, dpink, marine, cyan, lbrown, dbrown.

Text utilities for use with GD
******************************

NAME
====

   GD::Text - Text utilities for use with GD

SYNOPSIS
========

     use GD;
     use GD::Text;

     my $gd_text = GD::Text->new() or die GD::Text::error();
     $gd_text->set_font('funny.ttf', 12) or die $gd_text->error;
     $gd_text->set_font(gdTinyFont);
     $gd_text->set_font(GD::Font::Tiny);
     ...
     $gd_text->set_text($string);
     my ($w, $h) = $gd_text->get('width', 'height');

     if ($gd_text->is_ttf)
     {
     	  ...
     }

   Or alternatively

     my $gd_text = GD::Text->new(
           text => 'Some text',
           font => 'funny.ttf',
           ptsize => 14,
       );

DESCRIPTION
===========

   This module provides a font-independent way of dealing with text in GD,
for use with the GD::Text::* modules and GD::Graph.

NOTES
=====

   As with all Modules for Perl: Please stick to using the interface. If
you try to fiddle too much with knowledge of the internals of this module,
you could get burned. I may change them at any time.

   You can only use TrueType fonts with version of GD > 1.20, and then
only if compiled with support for this. If you attempt to do it anyway,
you will get errors.

METHODS
=======

GD::Text->new( attrib => value, ... )
-------------------------------------

   Create a new object. See the set() method for attributes.

GD::Text::error() or $gd_text->error();
---------------------------------------

   Return the last error that occured in the class. This may be imperfect.

$gd_text->set_font( font, size )
--------------------------------

   Set the font to use for this string. The arguments are either a GD
builtin font (like gdSmallFont or GD::Font->Small) or the name of a
TrueType font file and the size of the font to use. See also `"font_path"'
in this node.

   If you are not using an absolute path to the font file, you can leave of
the .ttf file extension, but you have to append it for absolute paths:

     $gd_text->set_font('cetus', 12);
     # but
     $gd_text->set_font('/usr/fonts/cetus.ttf', 12);

   The first argument can be a reference to an array of fonts. The first
font from the array that can be found will be used. This allows you to do
something like

     $gd_text->font_path( '/usr/share/fonts:/usr/fonts');
     $gd_text->set_font(
       ['verdana', 'arial', gdMediumBoldFont], 14);

   if you'd prefer verdana to be used, would be satisfied with arial, but
if none of that is available just want to make sure you can fall back on
something that will be available.

   Returns true on success, false on error.

$gd_text->set_text('some text')
-------------------------------

   Set the text to operate on.  Returns true on success and false on error.

$gd_text->set( attrib => value, ... )
-------------------------------------

   The set method provides a convenience replacement for the various other
`set_xxx()' methods. Valid attributes are:

text
     The text to operate on, see also `set_text()'.

font, ptsize
     The font to use and the point size. The point size is only used for
     TrueType fonts. Also see `set_font()'.

   Returns true on success, false on any error, even if it was partially
successful. When an error is returned, no guarantees are given about the
correctness of the attributes.

$gd_text->get( attrib, ... )
----------------------------

   Get the value of an attribute.  Return a list of the attribute values
in list context, and the value of the first attribute in scalar context.

   The attributes that can be retrieved are all the ones that can be set,
and:

width, height
     The width (height) of the string in pixels

space
     The width of a space in pixels

char_up, char_down
     The number of pixels that a character can stick out above and below
     the baseline. Note that this is only useful for TrueType fonts. For
     builtins char_up is equal to height, and char_down is always 0.

   Note that some of these parameters (char_up, char_down and space) are
generic font properties, and not necessarily a property of the text that
is set.

$gd_text->width('string')
-------------------------

   Return the length of a string in pixels, without changing the current
value of the text.  Returns the width of 'string' rendered in the current
font and size.  On failure, returns undef.

   The use of this method is vaguely deprecated.

$gd_text->is_builtin
--------------------

   Returns true if the current object is based on a builtin GD font.

$gd_text->is_ttf
----------------

   Returns true if the current object is based on a TrueType font.

$gd_text->can_do_ttf() or GD::Text->can_do_ttf()
------------------------------------------------

   Return true if this object can handle TTF fonts.

   This depends on whether your version of GD is newer than 1.19 and has
TTF support compiled into it.

$gd_text->font_path(path_spec), GD::Text->font_path(path_spec)
--------------------------------------------------------------

   This sets the font path for the class (i.e. not just for the object).
The `set_font' method will search this path to find the font specified if
it is a TrueType font. It should contain a list of paths. The current
directory is always searched first, unless '.' is present in FONT_PATH.
Examples:

     GD::Text->font_path('/usr/ttfonts'); # Unix
     GD::Text->font_path('c:/fonts');     # MS-OS

   Any font name that is not an absolute path will first be looked for in
the current directory, and then in /usr/ttfonts (c:\fonts).

     GD::Text->font_path('/usr/ttfonts:.:lib/fonts'); # Unix
     GD::Text->font_path('c:/fonts;.;f:/fonts');      # MS-OS

   Any font name that is not an absolute path will first be looked for in
/usr/ttfonts (c:\fonts), then in the current directory. and then in
lib/fonts (f:\fonts), relative to the current directory.

     GD::Text->font_path(undef);

   Font files are only looked for in the current directory.

   FONT_PATH is initialised at module load time from the environment
variables FONT_PATH or, if that's not present, TTF_FONT_PATH.

   Returns the value the font path is set to.  If called without arguments
`font_path' returns the current font path.

   Note: This currently only works for unices, and (hopefully) for
Microsoft based OS's. If anyone feels the urge to have a look at the code,
and send me patches for their OS, I'd be most grateful)

BUGS
====

   This module has only been tested with anglo-centric 'normal' fonts and
encodings.  Fonts that have other characteristics may not work well.  If
that happens, please let me know how to make this work better.

   The font height gets estimated by building a string with all printable
characters that pass the POSIX::isgraph() test. If your system doesn't
have POSIX, I make an approximation that may be false.

   The whole font path thing works well on Unix, but probably not very well
on other OS's. This is only a problem if you try to use a font path. If
you don't use a font path, there should never be a problem. I will try to
expand this in the future, but only if there's a demand for it.
Suggestions welcome.

COPYRIGHT
=========

   copyright 1999 Martien Verbruggen (mgjv@comdyn.com.au)

SEE ALSO
========

   GD(3), GD::Text::Wrap(3), GD::Text::Align(3)

Draw aligned strings
********************

NAME
====

   GD::Text::Align - Draw aligned strings

SYNOPSIS
========

     use GD;
     use GD::Text::Align;

     my $gd = GD::Image->new(800,600);
     # allocate colours, do other things.

     my $align = GD::Text::Align->new($gd
       valign => 'top',
       halign => 'right',
     );
     $align->set_font('cetus.ttf', 12);
     $align->set_text('some string');
     @bb = $align->bounding_box(200, 400, PI/3);
     # you can do things based on the bounding box here
     $align->draw(200, 400, PI/3);

DESCRIPTION
===========

   GD::Text::Align provides an object that draws a string aligned to a
coordinate at an angle.

   For builtin fonts only two angles are valid: 0 and PI/2. All other
angles will be converted to one of these two.

METHODS
=======

   This class inherits everything from GD::Text. I will only discuss the
methods and attributes here that are not discussed there, or that have a
different interface or behaviour. Methods directly inherited include
set_text and `set_font'.

GD::Text::Align->new($gd_object, attrib => value, ...)
------------------------------------------------------

   Create a new object. The first argument to new has to be a valid
GD::Image object. The other arguments will be passed on to the set method.

$align->set(attrib => value, ...)
---------------------------------

   Set an attribute. Valid attributes are the ones discussed in
GD/Text, and:

valign, halign
     Vertical and horizontal alignment of the string. See also set_valign
     and set_halign.

colour, color
     Synonyms. The colour to use to draw the string. This should be the
     index of the colour in the GD::Image object's palette. The default
     value is the last colour in the GD object's palette at the time of
     the creation of `$align'.

$align->get(attribute)
----------------------

   Get the value of an attribute.  Valid attributes are all the attributes
mentioned in GD/Text, the attributes mentioned under the
set method and

x, y and angle
     The x and y coordinate and the angle to be used. You can only do this
     after a call to the draw or bounding_box methods. Note that these
     coordinates are not necessarily the same ones that were passed in.
     Instead, they are the coordinates from where the GD methods will start
     drawing. I doubt that this is very useful to anyone.

   Note that while you can set the colour with both 'color' and 'colour',
you can only get it as 'colour'. Sorry, but such is life in Australia.

$align->set_valign(value)
-------------------------

   Set the vertical alignment of the string to one of 'top', 'center',
'base' or 'bottom'. For builtin fonts the last two are the same. The value
'base' denotes the baseline of a TrueType font.  Returns true on success,
false on failure.

$align->set_halign(value)
-------------------------

   Set the horizontal alignment of the string to one of 'left', 'center',
or 'right'.  Returns true on success, false on failure.

$align->set_align(valign, halign)
---------------------------------

   Set the vertical and horizontal alignment. Just here for convenience.
See also `set_valign' and `set_halign'.  Returns true on success, false on
failure.

$align->draw(x, y, angle)
-------------------------

   Draw the string at coordinates x, y at an angle *angle* in radians. The
x and y coordinate become the pivot around which the string rotates.

   Note that for the builtin GD fonts the only two valid angles are 0 and
PI/2.

   Returns the bounding box of the drawn string (see `bounding_box()').

$align->bounding_box(x, y, angle)
---------------------------------

   Return the bounding box of the string to draw. This returns an
eight-element list (exactly like the GD::Image->stringTTF method):

     (x1,y1) lower left corner
     (x2,y2) lower right corner
     (x3,y3) upper right corner
     (x4,y4) upper left corner

   Note that upper, lower, left and right are relative to the string, not
to the canvas.

   The bounding box can be used to make decisions about whether to move the
string or change the font size prior to actually drawing the string.

NOTES
=====

   As with all Modules for Perl: Please stick to using the interface. If
you try to fiddle too much with knowledge of the internals of this module,
you may get burned. I may change them at any time.

   You can only use TrueType fonts with version of GD > 1.20, and then
only if compiled with support for this. If you attempt to do it anyway,
you will get errors.

   In the following, terms like 'top', 'upper', 'left' and the like are all
relative to the string to be drawn, not to the canvas.

BUGS
====

   Any bugs inherited from GD::Text.

COPYRIGHT
=========

   copyright 1999 Martien Verbruggen (mgjv@comdyn.com.au)

SEE ALSO
========

   See GD, GD/Text, GD/Text/Wrap,

Wrap strings in boxes
*********************

NAME
====

   GD::Text::Wrap - Wrap strings in boxes

SYNOPSIS
========

     use GD;
     use GD::Text::Wrap;

     my $gd = GD::Image->new(800,600);
     # allocate colours, do other things.

     my $text = <<EOSTR;
     Lorem ipsum dolor sit amet, consectetuer adipiscing elit,
     sed diam nonummy nibh euismod tincidunt ut laoreet dolore
     magna aliquam erat volutpat.
     EOSTR

     my $wrapbox = GDTextWrap->new( $gd,
         line_space  => 4,
         color       => $black,
         text        => $text,
     );
     $wrapbox->set_font(gdMediumBoldFont);
     $wrapbox->set_font('cetus.ttf', 12);
     $wrapbox->set(align => 'left', width => 120);
     $wrapbox->draw(10,140);

     $gd->rectangle($wrap_box->get_bounds(10,140), $color);

DESCRIPTION
===========

   GD::Text::Wrap provides an object that draws a formatted paragraph of
text in a box on a GD::Image canvas, using either a builtin GD font or a
TrueType font.

METHODS
=======

   This class doesn't inherit from GD::Text directly, but delegates most of
its work to it (in fact to a GD::Text::Align object. That means that most
of the GD::Text::Align methods are available for this class, specifically
`set_font' and `font_path'. Other methods and methods with a different
interface are described here:

GD::Text::Wrap->new( $gd_object, attribute => value, ... )
----------------------------------------------------------

   Create a new object. The first argument to new has to be a valid
GD::Image object. The other arguments will be passed to the set() method
for initialisation of the attributes.

$wrapbox->set( attribute => value, ... )
----------------------------------------

   set the value for an attribute. Valid attributes are:

width
     The width of the box to draw the text in. If unspecified, they will
     default to the width of the GD::Image object.

line_space
     The number of pixels between lines. Defaults to 2.

para_space, paragraph_space
     The number of extra pixels between paragraphs, above line_space.
     Defaults to 0.

color, colour
     Synonyms. The colour to use when drawing the font. Will be initialised
     to the last colour in the GD object's palette.

align, alignment
     Synonyms. One of 'justified' (the default), 'left', 'right' or
     'center'.

text
     The text to draw. This is the only attribute that you absolutely have
     to set.

preserve_nl
     If set to a true value, newlines in the text will cause a line break.
     Note that lines will still be justified. If only one word appears on
     the line, it could get ugly.  Defaults to 0.

   As with the methods, attributes unknown to this class get delegated to
the GD::Text::Align class.

$wrapbox->get( attribute );
---------------------------

   Get the current value of an attribute. All attributes mentioned under
the set() method can be retrieved

$wrapbox->get_bounds()
----------------------

   Returns the bounding box of the box that will be drawn with the current
attribute settings as a list. The values returned are the coordinates of
the upper left and lower right corner.

     ($left, $top, $right, $bottom) = $wrapbox->get_bounds();

   Returns an empty list on error.

   NOTE: The return list of this method may change in a future
implementation that allows angled boxes.

$wrapbox->draw(x, y)
--------------------

   Draw the box, with (x,y) as the top right corner.  Returns the same
values as the `getbounds()' method.

   NOTE: The return list of this method may change in a future
implementation that allows angled boxes.

NOTES
=====

   As with all Modules for Perl: Please stick to using the interface. If
you try to fiddle too much with knowledge of the internals of this module,
you may get burned. I may change them at any time.

   You can only use TrueType fonts with version of GD > 1.20, and then
only if compiled with support for this. If you attempt to do it anyway,
you will get errors.

   Even though this module lives in the GD::Text namespace, it is not a
GD::Text. It does however delegate a lot of its functionality to a
contained object that is one (GD::Text::Align).

BUGS
====

   None that I know of, but that doesn't mean much. There may be some
problems with exotic fonts, or locales and character encodings that I am
not used to.

TODO
====

   Angled boxes.

   At the moment, the only bit of the box that is allowed to be unspecified
and in fact must be unspecified, is the bottom. If there is enough need
for it, I might implement more flexibility, in that that you need to only
specify three of the four sides of the box, and the fourth will be
calculated.

   Automatic resizing of a TrueType font to fit inside a box when four
sides are specified, or maybe some other nifty things.

   More flexibility in the interface. Especially draw needs some thought.

   More and better error handling.

   Warnings for lines that are too long and stick out of the box.  Warning
for emptyish lines?

COPYRIGHT
=========

   copyright 1999 Martien Verbruggen (mgjv@comdyn.com.au)

SEE ALSO
========

   See GD, GD/Text, GD/Text/Align,

Graph Plotting Module (deprecated)
**********************************

NAME
====

   GIFgraph - Graph Plotting Module (deprecated)

SYNOPSIS
========

   use GIFgraph::moduleName;

DESCRIPTION
===========

   *GIFgraph* is a *perl5* module to create and display GIF output for a
graph.

   GIFgraph is nothing more than a wrapper around GD::Graph, and its use is
deprecated. It only exists for backward compatibility. The documentation
for all the functionality can be found in GD/Graph.

   This module should work with all versions of GD, but it has only been
tested with version 1.19 and above. Version 1.19 is the last version that
produces GIF output directly. Any version later than that requires a
conversion step. The default distribution of GIFgraph uses Image::Magick
for this. If you'd like to use something else, please replace the sub
png2gif in GIFgraph::Convert with something more to your liking.

NOTES
=====

   Note that if you use GIFgraph with a GD version 1.20 or up that any
included logos will have to be in the PNG format. The only time that GIF
comes into play is _after_ GD has done its work, and the PNG gets
converted to GIF. There are no plans to change that behaviour; it's too
much work, and for you, the user, it is a one time conversion of these
pictures, when you move from GD < 1.20 to GD >= 1.20.

SEE ALSO
========

   GD::Graph(3), Chart::PNGgraph(3).

AUTHOR
======

   Martien Verbruggen <mgjv@comdyn.com.au>

Copyright
---------

   Copyright (C) 1995-2000 Martien Verbruggen.  All rights reserved.  This
package is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

spaces the data points evenly
*****************************

NAME
====

   GIFgraph::EvenlySpaced - spaces the data points evenly

DESCRIPTION
===========

   This module wraps a GIFgraph object so that the data points become
numericaly spaced (aproximately).

SYNOPSIS
========

   Wrapps a GIFgraph object (probably a GIFgraph::lines) so that the x
values are spaced numericaly. Use exactly as your GIFgraph object. Due to
a problem I had with AUTOLOAD, it must be the outer wrapper class.

Use
===

     $graph = new GIFgraph::lines(400,300);
     $es = new GIFgraph::EvenlySpaced($graph);

   or

     $graph = new GIFgraph::lines(400,300);
     $withmap = new GIFgraph::WithMap($graph);
     $es = new GIFgraph::EvenlySpaced($withmap);

   or even

     $es = new GIFgraph::EvenlySpaced(new GIFgraph::WithMap(new GIFgraph::lines(400,300)));

   etc. etc. etc.

Functions
=========

new
     Returns a new GIFgraph::EvenlySpaced object

          $es = new GIFgraph::EvenlySpaced($parentGraph);

     where $parentGraph is any object that behaves like a GIFgraph::lines
     type object such as a GIFgraph::WithMap.

plot
     This function is overridden to space the data numericaly along the
     x-axis.

Fields
======

fudge
     This is a fudge factor used in checking whether one number roughly
     devides into another. It defaults to 0.1 but if it is obviously doing
     silly things then change it. Good luck - I don't realy know how it
     works.

Guts
====

   This module uses MRP::BaseClass to implement member access functions.

   To make the 'parent' object behave as if it the super class I have done
some magic with AUTOLOAD. This has produced the restriction that you can
not wrap an EvenlySpaced object inside another - such as WithMap - that
also uses magic.

   @ISA does not include the parent type as it is not known. The isa()
method is overridden to account for this.

AUTHOR
======

   Matthew Pocock mrp@sanger.ac.uk

generate HTML map text.
***********************

NAME
====

   *GIFgraph::Map* - generate HTML map text.

SYNOPSIS
========

   use GIFgraph::Map;

   $map = new GIFgraph::Map($gr_object);

   $map->set(key1 => value1, key2 => value2 ...);

   $HTML_map = $map->imagemap($gr_file, \@data);

DESCRIPTION
===========

   Is a *perl5* module to generate HTML map text for following graph
objects *GIFgraph::pie*, *GIFgraph::bars*, *GIFgraph::point* and
*GIFgraph::linespoints*.  As a result of its work is created HTML code
containing IMG and MAP tags.  You simply need to insert this code into the
necessary place of your page.  In the inserted thus image, its certain
parts are the references and at a choice their mouse in a status line of
your browser displays the additional information.(See Samples).

SAMPLES
=======

   See the samples directory in the distribution.

USAGE
=====

   First of all you must create *GIFgraht* object, if it necessary set
options for its, create array of data and use plot_to_gif routine for
create GIF image.  For example create *GIFgraph::pie* object:

     $graphic = new GIFgraph::pie;

     $graphic->set('title'        => 'A Pie Chart',
                   'label'        => 'Label',
     	      'axislabelclr' => 'black',
     	      'pie_height'   => 80);

     @data = (["1st","2nd","3rd","4th","5th","6th"],
              [    4,    2,    3,    4,    3,  3.5]);

     $GIFimage = 'Demo.gif';

     $graphic->plot_to_gif($GIFimage, \@data);

   Then create *Fgraph::Map* object. And set options using set routine, or
set it in constructor immediately:

     $map = new GIFgraph::Map($graphic);

     $map->set(info => "%x slice contains %.1p% of %s (%x)");

     Create HTML map text using the same name of GIF
     image and array of data as use
     B<GIFgraph::plot_to_gif> routine:

     $HTML_map = $map->imagemap($GIFimage, \@data);

   Now you can insert $HTML_map into the necessary place of your HTML page.

METHODS AND FUNCTIONS
=====================

Constructor
     Constructor of object has following syntax:

          new GIFgraph::Map($gr_object,
            [key1 => value1, key2 => value2 ...]);

     where $gr_object this is one of the following graph objects:
     *GIFgraph::pie*, *GIFgraph::bars*,  *GIFgraph::point* or
     *GIFgraph::linespoints*; key1, value1 ... the same as using in set
     routine.  NOTE: Before use constructor you should at first set all
     properties of graph object.

imagemap(file, *\@data*)
     Generate HTML map text using GIF file $file and reference to array of
     data - \@data. This parameters must the same as used in plot_to_gif
     routine.

set(*key1* => *value1*, *key2* => *value2* .... )
     Set options. See OPTIONS.

OPTIONS
=======

*hrefs*, *lhrefs*
     Set hyper reference for each data (hrefs), and for each legend
     (lhrefs).  Array @hrefs must the same size as arrays in @data list,
     otherwise null elements of @hrefs set to default. Similarly array
     @lhrefs must the same size as legend array. Default use the simple
     JavaScript code 'javascript:;' instead reference, which do nothing.

     Example of *@hrefs* array:

     for *GIFgraph::pie*

     if     @data  = ([  "1st",  "2nd",  "3rd"],                  [
     4,      2,      3]);

     then   @hrefs =  ["1.htm","2.htm","3.htm"];

     for *GIFgraph::bars* *GIFgraph::point* and *GIFgraph::linespoints*

     if     @data  = ([  "1st",  "2nd",  "3rd"],                  [
     5,     12,     24],                  [      1,      2,      5]);

     then   @hrefs = (["1.htm","2.htm","3.htm"],
     ["4.htm","5.htm","6.htm"]);

     Example of *@lhrefs* array;

     if    @legend = [  'one',  'two','three'];

     then  @lhrefs = ["1.htm","2.htm","3.htm"];

info, legend
     Set information string for data and for legend. It will be show in
     status line of your browser. Format of this string the same for each
     data, but you may use special symbols for receive individual
     information. Now available following symbols: *%x* - Is replaced on x
     values in @data (first array) *%y* - Is replaced on y values in @data
     (other arrays) %s - Is replaced on sum of all y values. Only for
     GIFgraph::pie object.  *%p* - Is replaced on value, which show what
     part of all contains this data. Only for *GIFgraph::pie* object.  %l
     - Is replaced on legend. Only for *GIFgraph::bars*,
     *GIFgraph::points* and *GIFgraph::linespoints* objects.  For %x, %y,
     %s and %p parameters you may use special format (the same as use
     sprintf routine) for round data: %.d{x|y|p|s}, where d is a digit
     from 0 to 9. For example %.0p or %.3x. It is desirable use if %x, %y,
     %s or %p if floating numbers Default is 'x=%x y=%y' for info, and
     '%l' for legend.

     You can set any attribute in IMG tag (except UseMap, Src, Width,
     Height and Border, they will be set automatically) use set routine:
     set(img_option => value), where option is IMG attribute. For example:
     routine set(img_Alt => 'Example'); include Alt='Example' to IMG tag.

*newWindow*, *window_**
     If newWindow set to TRUE and link does not contain JavaScript code
     (javascript:...), that link will be open in new navigator window,
     Parameters of new window you can set using window_* parameters,
     similarly img_* option.

AUTHOR
======

   Roman Kosenko

Contact info
------------

   E-mail:    ra@amk.al.lg.ua

   Home page: http://amk.al.lg.ua/~ra

Copyright
---------

   Copyright (C) 1999 Roman Kosenko.  All rights reserved.  This package
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

generates HTML map text while plotting graph
********************************************

NAME
====

   GIFgraph::WithMap - generates HTML map text while plotting graph

DESCRIPTION
===========

   Generates the html map block for a graph so that data series become
'clickable',

SYNOPSIS
========

   This module extends GIFgraph objects such as GIFgraph::lines. You can
do everything that you would with a GIFgraph object. In addition, when the
data is plotted, it generates some MAP html text.

   The series will be labeled 'series 1', 'series 2' etc. unless the
$obj->seriesnames has been set. For each series, it will create a polygon
area, with the following structure (assuming series is named 'Green', and
that the links member array is empty:

     <AREA
            alt="Green"
            href="#Green"
            onMouseOver="self.status='Green'; return true"
            onMouseOut="self.status=''; return true"
            shape=polygon
            coords="87, 41, 165, 250, 165, 246, 87, 37">

   So - clicking on the series will take you to #Green. If you don't
specify #Green in the document, clicking on it will do very little. If you
have (e.g. in the key) then it should take you there.

new
===

   Use something like

     $map = new GIFgraph::WithMap(new GIFgraph::lines(400,300));

fields
======

map
     Once plot has been called, map contains the map text.

          print $graphWithMap->map;

fuzz
     This is the up/down fuzz used to construct the ploygon. It defaults to
     1 - so the polygon will be three pixles wide (the pixle drawn and one
     above and below it).

mapname
     Set this before calling plot. This is the name of the map, as given by
     usemap="#mapname" in <img>. It is a fatal error to try to plot without
     a name.

seriesnames
     Array of names for the series. If a name is absent for a series (or
     all series) then it will be named Series #. This must be set before
     the graph is plotted.

          $graphWithMap->seriesnames('name1', 'name2');

     Array of links for the series. If a link is absent for a series (or
     all series) then it will be named #SeriesName (where SeriesName is
     generated as described in `seriwsnames' in this node).

Guts
====

   This module uses MRP::BaseClass to implement member access functions.

   In the constructor, a new object is created that is a meld of an
MRP::BaseClass derived object, and the GIFgraph object passed in. The type
of that object is stoored in _GIFgraph. In AUTOLOAD, first I check to see
if the GIFgraph object's package named in _GIFgraph implements the
function. If it does, then I return the value of that function - i.e. it
behaves as if the object inherits from that package. If that fails, then I
return the value of SUPER::AUTLOLOAD, which will presumably handle it or
die gracefully. Hey presto - dynamic parenting.

   @ISA does not include anything to implement a GIFgraph object as a
parent. However, I have overridden 'isa' to account for this.

Box and Whisker Graph Module for Perl 5.
****************************************

NAME
====

   Boxplot - Box and Whisker Graph Module for Perl 5.

SYNOPSIS
========

   use GIFgraph::boxplot;

DESCRIPTION
===========

   *boxplot* is a *perl5* module that uses GIFgraph, GD, and
Statistics::Descriptive to create and display GIF output for box and
whisker graphs.

EXAMPLES
========

   See the samples directory in the distribution.

USAGE
=====

   Fill an array of arrays with the x values and array references to the
data sets to be used.  Make sure that every array has the same number of
data sets as there are x values, otherwise *GIFgraph* will complain and
refuse to compile the graph.  For example:

     $one = [210..275];
     $two = [180, 190, 200, 220, 235, 245];
     $three = [40, 140..150, 160..180, 250];
     $four = [100..125, 136..140];
     $five = [10..50, 100, 180];

     @data = (
     	["1st", "2nd", "3rd", "4th", "5th"],
     	[$one, $two, $three, $four, $five ],
     	[ [-25, 1..15], [-45, 25..45, 100], [70, 42..125], [undef], [180..250] ],
     	# as many sets of data sets as you like
     	);

   If you don't have any data for a certain dataset, you can use undef as
shown above, and *GIFgraph* will skip that box.

   Create a new *GIFgraph* object by calling the new operator on the type
*boxplot*:

     $my_graph = new GIFgraph::boxplot( );

   Set the graph options:

     $my_graph->set(
     	x_label           => 'X Label',
      		y_label           => 'Y label',
     	title             => 'Some simple graph',
     	upper_percent     => 70,
     	lower_percent     => 35,
     	step_const        => 1.8
     	);

   Output the graph:

     $my_graph->plot_to_gif( "sample01.gif", \@data );

METHODS AND FUNCTIONS
=====================

   See GIFgraph documentation for methods for all GIFgraph graphs.

OPTIONS
=======

Options for all graphs
----------------------

   See GIFgraph documentation for options for all graphs.

Options for graphs with axes
----------------------------

   Boxplot has axes, and has all of the options available to the other
graphs with axes: *bars*, lines, points, *linespoints* and area.  See the
GIFgraph documentation for all of these options.

Options specific to Boxplot graphs
----------------------------------

do_stats, upper_percent, lower_percent
     If *do_stats* is a true value, the program assumes that raw data are
     used for input.  It calculates the statistics for each box's data,
     and draws the box, mean, median, upper and lower whiskers, outliers,
     and far-out-values accordingly.  The top and bottom of the box are
     determined by the numbers given for upper_percent and lower_percent.
     For example, if you wanted to have the box contain all the data from
     the 20% to 80% range, you would use:

          $my_graph->set(
          	lower_percent         => 20,
          	upper_percent         => 80
          	);

     If *do_stats* is set to 0, the program assumes that the user has
     already calculated the required statistics for every box.  The user
     must input these statistics in place of the raw data:

          # data must be in this form:
          # $data = [mean, lowest, lower-percentile, median, upper-precentile, highest];
          $one = [27, -35, 14, 29, 39, 52];
          $two = [41, -140, 29, 45, 62, 125];
          $three = [100, 30, 88, 95, 115, 155];
          $four = [80, -100, 60, 100, 110, 195];

          @data = (
          	["1st", "2nd", "3rd", "4th"],
          	[ $one, $two, $three, $four],
          	# as many sets as you like, all with the required statistical data
          	);

          $my_graph = new GIFgraph::boxplot();

          $my_graph->set(
          	box_spacing       => 35,
          	do_stats          => 0
          	);

     Notice that if do_stats is set to 0, upper_percent and lower_percent
     are not used, because the user is able to input the actual value for
     the lower-percentile and upper-percetile.  Also notice that outliers
     and far-out-values are not drawn, because the program does not have
     the data points to use.  However, the lowest or highest values can be
     drawn as outliers or far-out-values if they fall outside of the
     whiskers.

     Default: do_stats = 1, upper_percent = 75, lower_percent = 25.

box_spacing
     Number of pixels to leave open between boxes. This works well in most
     cases, but on some platforms, a value of 1 will be rounded off to 0.

     Default: box_spacing = 10

warnings
     If set to 1, warnings are printed to the standard out when the user
     sets parameters to questionable values.  For example, if there are
     not enough pixels to draw the boxes properly because there are too
     many data sets for the given image size, or because the box_spacing
     is set too high, then a warning is printed so the user is aware of
     the problem.  If set to 0, all warnings are turned off.  This option
     is for users who do not want anything to be printed to the standard
     output.

     Default: warnings = 1

step_const
     Sets the step size equal to step_const box-heights, where the
     box-height is the distance from the top of the box to the bottom.
     The whiskers are then drawn one step from the top/bottom of the box,
     or to the largest/smallest data value, whichever is closer to the
     box.  If there are values further than one step from the box, then
     the whiskers are drawn to one step from the box, and those values
     further than the whiskers are drawn as either outliers or
     far-out-values as explained below.  step_cont can be any number
     greater than 0.

     Default: step_const = 1.5

fov_const
     Sets the distance that will mark the boundary between outliers and
     far-out-values.  Outliers will be drawn between the whisker and
     fov_const steps from the whisker.  Far-out-values will be drawn for
     values that fall farther than fov_const steps from the whisker.
     fov_const can be any number greater than 0.

     Default: fov_const = 1

box_fill
     When set to 1, the boxes are filled with the color for that data set.
     When set to 0, only the symbols and the outlines of the boxes will
     be drawn.

     Default: box_fill = 1

symbolc
     The color for drawing the symbols and box outlines.

     Default: symbolc = 'dblue'

NOTES
=====

   This module was designed to function in the same way as other GIFgraph
graph types.  It has all of the same functionality (except for mixed
graphs) as the other graphs.  This functionality includes how to set the
colors that fill the boxes (same as Bars), change the size of the margins
between the plot and the edge of the GIF, etc.  Please read the GIFgraph
documentation for the full set of options avaiable.

AUTHOR
======

   Written by:             Nigel Wright.

   Design and Funding:     Mark Landry, Client/Server Architects, Inc.

Contact info
------------

   email: nwright@hmc.edu

Copyright
---------

   Copyright (C) 1999 Nigel Wright.  All rights reserved.  This package is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Colour manipulation routines for use with GIFgraph
**************************************************

NAME
====

   Colour - Colour manipulation routines for use with GIFgraph

SYNOPSIS
========

   use GIFgraph::colour qw( :colours :lists :files );

DESCRIPTION
===========

   The *Colour* Package provides a few routines to convert some colour
names to RGB values. Also included are some functions to calculate the hue
and luminance of the colours, mainly to be able to sort them.

   The :colours tags can be used to import the *_rgb*, *_hue*, and
*_luminance* functions, the :lists tag for *colour_list* and
*sorted_colour_list*, and the :files tag exports the *read_rgb* function.

FUNCTIONS
=========

Colour::colour_list( *number of colours* )
     Returns a list of *number of colours* colour names known to the
     package.

Colour::sorted_colour_list( *number of colours* )
     Returns a list of *number of colours* colour names known to the
     package, sorted by luminance or hue.  *NB.* Right now it always sorts
     by luminance. Will add an option in a later stage to decide sorting
     method at run time.

Colour::_rgb( *colour name* )
     Returns a list of the RGB values of *colour name*.

Colour::_hue( *R,G,B* )
     Returns the hue of the colour with the specified RGB values.

Colour::_luminance( *R,G,B* )
     Returns the luminance of the colour with the specified RGB values.

Colour::read_rgb( `file name' )
     Reads in colours from a rgb file as used by the X11 system.

     Doing something like:

          use GIFgraph::bars;
          use GIFgraph::colour;

          GIFgraph::colour::read_rgb("rgb.txt") or die "cannot read colours";

     Will allow you to use any colours defined in rgb.txt in your graph.

PREDEFINED COLOUR NAMES
=======================

   white, lgray, gray, dgray, black, lblue, blue, dblue, gold, lyellow,
yellow, dyellow, lgreen, green, dgreen, lred, red, dred, lpurple, purple,
dpurple, lorange, orange, pink, dpink, marine, cyan, lbrown, dbrown.

Perl extension for using ORBit with GNOME
*****************************************

NAME
====

   GNOME::GNORBA - Perl extension for using ORBit with GNOME

SYNOPSIS
========

     use GNOME::GNORBA;

DESCRIPTION
===========

   The GNOME::GNORBA module sets up cookies appropriately for using ORBit
in a GNOME environment, and also provides an interface to GOAD. (The GNOME
Object Activation Directory)

AUTHOR
======

   Owen Taylor <otaylor@redhat.com> Copyright Red Hat, Inc, 1999.

SEE ALSO
========

   perl(1).

Perl interface to GPS equipment using the Garmin Protocol
*********************************************************

NAME
====

   GPS::Garmin - Perl interface to GPS equipment using the Garmin Protocol

SYNOPSIS
========

     use GPS::Garmin;
     $gps = new GPS::Garmin(  'Port'      => '/dev/ttyS0',
     				  		   'Baud'      => 9600,
                   );

   To transfer current position, and direction symbols:

     ($latsign,$lat,$lonsign,$lon) = $gps->get_position;

   To transfer current time:

     ($sec,$min,$hour,$mday,$mon,$year) = $gps->get_time;

   To transfer trackpoints:

   $gps->prepare_transfer("trk"); while($gps->records) {
($lat,$lon,$time) = $gps->grab; }

   To transfer Waypoints:

   $gps->prepare_transfer("wpt"); while($gps->records) {
($title,$lat,$lon,$desc) = $gps->grab; }

DESCRIPTION
===========

   GPS::Garmin allow the connection and use of of a GPS receiver in perl
scripts.  Currently only the GRMN/GRMN protocol is implemented but NMEA is
a work in progress.

   This module currently works with Garmin GPS II+ equipments, but should
work on most Garmin receivers that support the GRMN/GRMN protocol.

GETTING STARTED
===============

   Make sure your GPS receiver is in host mode, GRMN/GRMN protocol.  To
start a connection in your script, just:

     use GPS::Garmin;
             $gps = new GPS::Garmin (  'Port'      => '/dev/ttyS0',
                                       'Baud'      => 9600,
                                    ) or die "Unable to connect to receiver: $!";

     Where Port is the port that your GPS is connected to,
     and Baud the speed of connection ( default is 9600 bps).

   To know current coordinates:

     ($latsign,$lat,$lnsign,$lon) = $gps->get_position;

     $ltsign is "S" or "N" (South or North)
     $lat is current latitude in degrees.minutes.
     $lnsign is "W" or "E" (West or East)
     $lon is current longitude in degrees.minutes.

   To transfer the track records:

   $gps->prepare_transfer("trk");

   while($gps->records) { 	($lat,$lon,$time) = $gps->grab; }

   $time is in unix epoch seconds

KNOWN LIMITATIONS
=================

   - Trackpoint transfer won't work in the following Garmin devices, since
they don't support it:

   GPS 50		GPS 55 GPS 150		GPS 150 XL GPS 165		GNC 250
GNC 250XL	GNC 300 GNC 300XL

   You can check you GPS capabilities by looking at the table in page 50
of the Garmin protocol specification at
http://www.garmin.com/support/protocol.html

   - You need to have Win32::SerialPort to have GPS::Garmin working in
Windows.

BUGS
====

   Lacks documentation

AUTHOR
======

   Joao Pedro B Gonçalves , joaop@iscsp.utl.pt

SEE ALSO
========

   Peter Bennett's GPS www and ftp directory:'

     ftp://sundae.triumf.ca/pub/peter/index.html.
     http://vancouver-webpages.com/peter/idx_garmin.html

   Official Garmin Communication Protocol Reference

     http://www.garmin.com/support/protocol.html

Handlers to Garmin data
***********************

NAME
====

   GPS::Garmin::Handler - Handlers to Garmin data

SYNOPSIS
========

     use GPS::Handler;

DESCRIPTION
===========

     Used internally

AUTHOR
======

   Joao Pedro B Gonçalves , joaop@sl.pt

SEE ALSO
========

   Peter Bennett's GPS www and ftp directory:'

     ftp://sundae.triumf.ca/pub/peter/index.html.
     http://vancouver-webpages.com/peter/idx_garmin.html

   Official Garmin Communication Protocol Reference

     http://www.garmin.com/support/protocol.html

Access to the Serial port for the GPS::* modules
************************************************

NAME
====

   GPS::Serial - Access to the Serial port for the GPS::* modules

SYNOPSIS
========

     use GPS::Serial;

DESCRIPTION
===========

     Used internally

AUTHOR
======

   Joao Pedro B Gonçalves , joaop@sl.pt

SEE ALSO
========

   Peter Bennett's GPS www and ftp directory:'

     ftp://sundae.triumf.ca/pub/peter/index.html.
     http://vancouver-webpages.com/peter/idx_garmin.html

   Official Garmin Communication Protocol Reference

     http://www.garmin.com/support/protocol.html

Perl extension providing access to the GSSAPIv2 library
*******************************************************

NAME
====

   GSSAPI - Perl extension providing access to the GSSAPIv2 library

SYNOPSIS
========

     use GSSAPI;

     # lots of complicated stuff here

DESCRIPTION
===========

   This module gives access to the routines of the GSSAPI library, as
described in rfc2743 and rfc2744 and implemented by the Kerberos-1.2
distribution from MIT.

   The API presented by this module is a mildly object oriented
reinterpretation of the C API, where opaque C structures are Perl objects,
but the style of function call has been left mostly untouched.  As a
result, most routines modify one or more of the parameters passed to them,
reflecting the C call-by-reference (or call-by-value-return) semantics.

   All users of this module are therefore strongly advised to localize all
usage of these routines to minimize pain if and when the API changes.

SEE ALSO
========

   RFC2743 RFC2744 GSSAPI::Status(3p) GSSAPI::OID(3p) GSSAPI::OID::Set(3p)
perl(1)

EXPORT
------

     GSS_C_ACCEPT
     GSS_C_AF_APPLETALK
     GSS_C_AF_BSC
     GSS_C_AF_CCITT
     GSS_C_AF_CHAOS
     GSS_C_AF_DATAKIT
     GSS_C_AF_DECnet
     GSS_C_AF_DLI
     GSS_C_AF_DSS
     GSS_C_AF_ECMA
     GSS_C_AF_HYLINK
     GSS_C_AF_IMPLINK
     GSS_C_AF_INET
     GSS_C_AF_LAT
     GSS_C_AF_LOCAL
     GSS_C_AF_NBS
     GSS_C_AF_NS
     GSS_C_AF_NULLADDR
     GSS_C_AF_OSI
     GSS_C_AF_PUP
     GSS_C_AF_SNA
     GSS_C_AF_UNSPEC
     GSS_C_AF_X25
     GSS_C_ANON_FLAG
     GSS_C_BOTH
     GSS_C_CALLING_ERROR_MASK
     GSS_C_CALLING_ERROR_OFFSET
     GSS_C_CONF_FLAG
     GSS_C_DELEG_FLAG
     GSS_C_EMPTY_BUFFER
     GSS_C_GSS_CODE
     GSS_C_INDEFINITE
     GSS_C_INITIATE
     GSS_C_INTEG_FLAG
     GSS_C_MECH_CODE
     GSS_C_MUTUAL_FLAG
     GSS_C_NO_BUFFER
     GSS_C_NO_CHANNEL_BINDINGS
     GSS_C_NO_CONTEXT
     GSS_C_NO_CREDENTIAL
     GSS_C_NO_NAME
     GSS_C_NO_OID
     GSS_C_NO_OID_SET
     GSS_C_PROT_READY_FLAG
     GSS_C_QOP_DEFAULT
     GSS_C_REPLAY_FLAG
     GSS_C_ROUTINE_ERROR_MASK
     GSS_C_ROUTINE_ERROR_OFFSET
     GSS_C_SEQUENCE_FLAG
     GSS_C_SUPPLEMENTARY_MASK
     GSS_C_SUPPLEMENTARY_OFFSET
     GSS_C_TRANS_FLAG
     GSS_S_BAD_BINDINGS
     GSS_S_BAD_MECH
     GSS_S_BAD_NAME
     GSS_S_BAD_NAMETYPE
     GSS_S_BAD_QOP
     GSS_S_BAD_SIG
     GSS_S_BAD_STATUS
     GSS_S_CALL_BAD_STRUCTURE
     GSS_S_CALL_INACCESSIBLE_READ
     GSS_S_CALL_INACCESSIBLE_WRITE
     GSS_S_COMPLETE
     GSS_S_CONTEXT_EXPIRED
     GSS_S_CONTINUE_NEEDED
     GSS_S_CREDENTIALS_EXPIRED
     GSS_S_CRED_UNAVAIL
     GSS_S_DEFECTIVE_CREDENTIAL
     GSS_S_DEFECTIVE_TOKEN
     GSS_S_DUPLICATE_ELEMENT
     GSS_S_DUPLICATE_TOKEN
     GSS_S_FAILURE
     GSS_S_GAP_TOKEN
     GSS_S_NAME_NOT_MN
     GSS_S_NO_CONTEXT
     GSS_S_NO_CRED
     GSS_S_OLD_TOKEN
     GSS_S_UNAUTHORIZED
     GSS_S_UNAVAILABLE
     GSS_S_UNSEQ_TOKEN

Exportable functions
--------------------

     $status = indicate_mechs($oidset)

     # Constant OIDs provided:
     $oid = gss_nt_user_name;
     $oid = gss_nt_machine_uid_name;
     $oid = gss_nt_string_uid_name;
     $oid = gss_nt_service_name;
     $oid = gss_nt_exported_name;
     $oid = gss_nt_service_name_v2;
     $oid = gss_nt_krb5_name;
     $oid = gss_nt_krb5_principal;
     $oid = gss_mech_krb5;
     $oid = gss_mech_krb5_old;
     $oid = gss_mech_krb5_v2;

     # Constant OID sets provided:
     $oidset = gss_mech_set_krb5;
     $oidset = gss_mech_set_krb5_old;
     $oidset = gss_mech_set_krb5_both;
     $oidset = gss_mech_set_krb5_v2;
     $oidset = gss_mech_set_krb5_v1v2;

   All other functions are class or instance methods.

AUTHOR
======

   Philip Guenther, guenther@gac.edu

methods for handling GSSAPI OIDs and some constant OIDs
*******************************************************

NAME
====

   GSSAPI::OID - methods for handling GSSAPI OIDs and some constant OIDs

SYNOPSIS
========

     use GSSAPI;

     #$oid = GSSAPI::OID->new;		# rarely needed or wanted

     $status = GSSAPI::OID->from_str($oid, "{ 1 2 840 113554 1 2 1 1 }");

     $status = $oid->to_str($str);

     $status = $oid->inquire_names($oidset);

     # Constant OIDs provided:
     $oid = gss_nt_user_name;
     $oid = gss_nt_machine_uid_name;
     $oid = gss_nt_string_uid_name;
     $oid = gss_nt_service_name;
     $oid = gss_nt_exported_name;
     $oid = gss_nt_service_name_v2;
     $oid = gss_nt_krb5_name;
     $oid = gss_nt_krb5_principal;
     $oid = gss_mech_krb5;
     $oid = gss_mech_krb5_old;
     $oid = gss_mech_krb5_v2;

DESCRIPTION
===========

   `GSSAPI::OID' objects are used as unique indentifiers/constants for
'mechanisisms' - the particular protocol and version being used - and for
the encodings used to represent names.  In many cases you can request the
default mechanism or encoding for the implmentation by using GSS_C_NO_OID.
Check the description of the routine in rfc2743 if you're not sure.

AUTHOR
======

   Philip Guenther, guenther@gac.edu

SEE ALSO
========

   perl(1) GSSAPI(3p) GSSAPI::OID::Set(3p) RFC2743

methods for handling sets of GSSAPI OIDs, and some constant OID sets.
*********************************************************************

NAME
====

   GSSAPI::OID::Set - methods for handling sets of GSSAPI OIDs, and some
constant OID sets.

SYNOPSIS
========

     use GSSAPI;

     $oidset = GSSAPI::OID::Set->new;

     $status = $oidset->insert($oid);
     $status = $oidset->contains($oid, $isthere);
     if ($status && $isthere) {
       # blah blah blah
     }

     # Constant OID sets provided:
     $oidset = gss_mech_set_krb5;
     $oidset = gss_mech_set_krb5_old;
     $oidset = gss_mech_set_krb5_both;
     $oidset = gss_mech_set_krb5_v2;
     $oidset = gss_mech_set_krb5_v1v2;

DESCRIPTION
===========

   `GSSAPI::OID::Set' objects are simple sets of GSSAPI:OIDs (duh).

BUGS
====

   There's no way to list the OIDs in a set; you can only check to see if
a particular one is present.  This is really a bug in the C API, so any
fix would be implementation specific.

AUTHOR
======

   Philip Guenther, guenther@gac.edu

SEE ALSO
========

   perl(1) GSSAPI(3p) GSSAPI::OID(3p) RFC2743

methods for handlings GSSAPI statuses
*************************************

NAME
====

   GSSAPI::Status - methods for handlings GSSAPI statuses

SYNOPSIS
========

     use GSSAPI;

     $status = GSSAPI::Status->new(GSS_S_COMPLETE, 0);

     if (GSS_ERROR($status->major)) {
       die "a horrible death";
     }
     if (! $status) {			# another way of writing the above
       die "a horrible death";
     }

     $status = $some_GSSAPI->someop($args1, etc);
     if ($status) {
       foreach ($status->generic_message, $status->specific_message) {
         print "GSSAPI error: $_\n";
       }
       die "help me";
     }

DESCRIPTION
===========

   `GSSAPI::Status' objects are returned by most other GSSAPI operations.
Such statuses consist of a GSSAPI generic code and, for most operations, a
mechanism specific code.  These numeric codes can be accessed via the
methods `major' and `minor'.  The standard textual messages that go with
the current status can be obtained via the `generic_message' and
`specific_message' methods.  Each of these returns a list of text which
should presumably be displayed in order.

   The generic code part of a GSSAPI::Status is composed of three
subfields that can be accessed with the `GSS_CALLING_ERROR',
`GSS_ROUTINE_ERROR', and `GSS_SUPPLEMENTARY_INFO' functions.  The returned
values can be compared against the constants whose names start with
`GSS_S_' if your code wants to handle particular errors itself.  The
`GSS_ERROR' function returns true if and only if the given generic code
contains neither a calling error nor a routine error.

   When evaluated in a boolean context, a `GSSAPI::Status' object will be
true if and only if the major status code is `GSS_S_COMPLETE'.

   When evaluated in a string contect, a `GSSAPI::Status' object will
return the generic and specific messages all joined together with
newlines.  This may or may not make `die $status' work usefully.

BUGS
====

   The base objects are currently implmented as a blessed C structure
containing the major and minor status codes.  It should probably be a
blessed array or hash instead, thereby cutting down on the amount of C
code involved and making it more flexible.

AUTHOR
======

   Philip Guenther, guenther@gac.edu

SEE ALSO
========

   perl(1) RFC2743

Perl interface to libgtop
*************************

NAME
====

   GTop - Perl interface to libgtop

SYNOPSIS
========

     use GTop ();
     my $gtop = GTop->new;

DESCRIPTION
===========

   Perl interface to libgtop:

     http://home-of-linux.org/gnome/libgtop/

CLASSES
=======

GTop::Cpu
---------

     my $cpu = $gtop->cpu;

flags
          my $flags = $cpu->flags;

total
          my $total = $cpu->total;

user
          my $user = $cpu->user;

nice
          my $nice = $cpu->nice;

sys
          my $sys = $cpu->sys;

idle
          my $idle = $cpu->idle;

frequency
          my $frequency = $cpu->frequency;

GTop::Fsusage
-------------

     my $fsusage = $gtop->fsusage($disk);

flags
          my $flags = $fsusage->flags;

blocks
          my $blocks = $fsusage->blocks;

bfree
          my $bfree = $fsusage->bfree;

bavail
          my $bavail = $fsusage->bavail;

files
          my $files = $fsusage->files;

ffree
          my $ffree = $fsusage->ffree;

GTop::Loadavg
-------------

     my $loadavg = $gtop->loadavg;

flags
          my $flags = $loadavg->flags;

nr_running
          my $nr_running = $loadavg->nr_running;

nr_tasks
          my $nr_tasks = $loadavg->nr_tasks;

last_pid
          my $last_pid = $loadavg->last_pid;

GTop::Mem
---------

     my $mem = $gtop->mem;

flags
          my $flags = $mem->flags;

total
          my $total = $mem->total;

used
          my $used = $mem->used;

free
          my $free = $mem->free;

shared
          my $shared = $mem->shared;

buffer
          my $buffer = $mem->buffer;

cached
          my $cached = $mem->cached;

user
          my $user = $mem->user;

locked
          my $locked = $mem->locked;

GTop::Mountlist
---------------

     my $mountlist = $gtop->mountlist($all_fs);

flags
          my $flags = $mountlist->flags;

number
          my $number = $mountlist->number;

total
          my $total = $mountlist->total;

size
          my $size = $mountlist->size;

GTop::Netload
-------------

     my $netload = $gtop->netload($interface);

flags
          my $flags = $netload->flags;

if_flags
          my $if_flags = $netload->if_flags;

mtu
          my $mtu = $netload->mtu;

subnet
          my $subnet = $netload->subnet;

address
          my $address = $netload->address;

packets_in
          my $packets_in = $netload->packets_in;

packets_out
          my $packets_out = $netload->packets_out;

packets_total
          my $packets_total = $netload->packets_total;

bytes_in
          my $bytes_in = $netload->bytes_in;

bytes_out
          my $bytes_out = $netload->bytes_out;

bytes_total
          my $bytes_total = $netload->bytes_total;

errors_in
          my $errors_in = $netload->errors_in;

errors_out
          my $errors_out = $netload->errors_out;

errors_total
          my $errors_total = $netload->errors_total;

collisions
          my $collisions = $netload->collisions;

GTop::ProcArgs
--------------

     my $proc_args = $gtop->proc_args($pid);

flags
          my $flags = $proc_args->flags;

size
          my $size = $proc_args->size;

GTop::ProcMap
-------------

     my $proc_map = $gtop->proc_map($pid);

flags
          my $flags = $proc_map->flags;

number
          my $number = $proc_map->number;

total
          my $total = $proc_map->total;

size
          my $size = $proc_map->size;

GTop::ProcMem
-------------

     my $proc_mem = $gtop->proc_mem($pid);

flags
          my $flags = $proc_mem->flags;

size
          my $size = $proc_mem->size;

vsize
          my $vsize = $proc_mem->vsize;

resident
          my $resident = $proc_mem->resident;

share
          my $share = $proc_mem->share;

rss
          my $rss = $proc_mem->rss;

rss_rlim
          my $rss_rlim = $proc_mem->rss_rlim;

GTop::ProcSegment
-----------------

     my $proc_segment = $gtop->proc_segment($pid);

flags
          my $flags = $proc_segment->flags;

text_rss
          my $text_rss = $proc_segment->text_rss;

shlib_rss
          my $shlib_rss = $proc_segment->shlib_rss;

data_rss
          my $data_rss = $proc_segment->data_rss;

stack_rss
          my $stack_rss = $proc_segment->stack_rss;

dirty_size
          my $dirty_size = $proc_segment->dirty_size;

start_code
          my $start_code = $proc_segment->start_code;

end_code
          my $end_code = $proc_segment->end_code;

start_stack
          my $start_stack = $proc_segment->start_stack;

GTop::ProcState
---------------

     my $proc_state = $gtop->proc_state($pid);

flags
          my $flags = $proc_state->flags;

GTop::ProcTime
--------------

     my $proc_time = $gtop->proc_time($pid);

flags
          my $flags = $proc_time->flags;

start_time
          my $start_time = $proc_time->start_time;

rtime
          my $rtime = $proc_time->rtime;

utime
          my $utime = $proc_time->utime;

stime
          my $stime = $proc_time->stime;

cutime
          my $cutime = $proc_time->cutime;

cstime
          my $cstime = $proc_time->cstime;

timeout
          my $timeout = $proc_time->timeout;

it_real_value
          my $it_real_value = $proc_time->it_real_value;

frequency
          my $frequency = $proc_time->frequency;

GTop::ProcUid
-------------

     my $proc_uid = $gtop->proc_uid($pid);

flags
          my $flags = $proc_uid->flags;

uid
          my $uid = $proc_uid->uid;

euid
          my $euid = $proc_uid->euid;

gid
          my $gid = $proc_uid->gid;

egid
          my $egid = $proc_uid->egid;

pid
          my $pid = $proc_uid->pid;

ppid
          my $ppid = $proc_uid->ppid;

pgrp
          my $pgrp = $proc_uid->pgrp;

session
          my $session = $proc_uid->session;

tty
          my $tty = $proc_uid->tty;

tpgid
          my $tpgid = $proc_uid->tpgid;

priority
          my $priority = $proc_uid->priority;

nice
          my $nice = $proc_uid->nice;

GTop::Proclist
--------------

     my $proclist = $gtop->proclist;

flags
          my $flags = $proclist->flags;

number
          my $number = $proclist->number;

total
          my $total = $proclist->total;

size
          my $size = $proclist->size;

GTop::Swap
----------

     my $swap = $gtop->swap;

flags
          my $flags = $swap->flags;

total
          my $total = $swap->total;

used
          my $used = $swap->used;

free
          my $free = $swap->free;

pagein
          my $pagein = $swap->pagein;

pageout
          my $pageout = $swap->pageout;

GTop::Uptime
------------

     my $uptime = $gtop->uptime;

flags
          my $flags = $uptime->flags;

AUTHOR
======

   Doug MacEachern

simple game-tree implementation of a gomoku-like game
*****************************************************

NAME
====

   Games::Alak - simple game-tree implementation of a gomoku-like game

SYNOPSIS
========

     % perl -MGames::Alak -e Games::Alak::play
      ...Or just run Alak.pm as if it were a program...
      ...Program responds with output, and a prompt:

     Lookahead set to 3.  I am X, you are O.
     Enter h for help
     X moves from 1 to 5, yielding .xxxx..oooo
     alak>
      ...and now you enter the commands to play.

DESCRIPTION
===========

   This module implements a simple game-tree system for the computer to
play against the user in a game of Alak.  You can just play the game for
fun; or you can use this module as a starting point for understanding game
trees (and implementing smarter strategy - the module's current logic is
fairly simple-minded), particularly after reading my *Perl Journal* #18
article on trees, which discusses this module's implementation of game
trees as an example of general tree-shaped data structures.

RULES
=====

   Alak was invented by the mathematician A. K.  Dewdney, and described in
his 1984 book *Planiverse*. The rules of Alak are simple - at least as
I've (mis?)understood them and implemented them here:

   * Alak is a two-player game played on a one-dimensional board with
eleven slots on it.  Each slot can hold at most one piece at a time.
There's two kinds of pieces, which I represent here as "x" and "o" - x's
belong to one player (called X - that's the computer), o's to the other
(called O - that's you).

   * The initial configuration of the board is:

     xxxx___oooo

     For sake of reference, the slots are numbered from 1 (on the left) to
     11 (on the right), and X always has the first move.

   * The players take turns moving.  At each turn, each player can move
only one piece, once.  (This is unlike checkers, where you move one piece
per move but get to keep moving it if you jump an your opponent's piece.)
A player cannot pass up on his turn.  A player can move any one of his
pieces to the next unoccupied slot to its right or left, which may involve
jumping over occupied slots.  A player cannot move a piece off the side of
the board.

   * If a move creates a pattern where the opponent's pieces are
surrounded, on both sides, by two pieces of the mover's color (with no
intervening unoccupied blank slot), then those surrounded pieces are
removed from the board.

   * The goal of the game is to remove all of your opponent's pieces, at
which point the game ends.  Removing all-but-one ends the game as well,
since the opponent can't surround you with one piece, and so will always
lose within a few moves anyway.

SAMPLE GAME
===========

   A game between X (computer) and a particularly dim O (human):

     xxxx___oooo
       ^         Move 1: X moves from 3 (shown with caret) to 5
                  (Note that any of X's pieces could move, but
                  that the only place they could move to is 5.)
     xx_xx__oooo
             ^   Move 2: O moves from 9 to 7.
     xx_xx_oo_oo
        ^        Move 3: X moves from 4 to 6.
     xx__xxoo_oo
              ^  Move 4: O (stupidly) moves from 10 to 9.
     xx__xxooo_o
         ^       Move 5: X moves from 5 to 10, making the board
                 "xx___xoooxo".  The three o's that X just
                 surrounded are removed.
     xx___x___xo
                 O has only one piece, so has lost.

INTERFACE
=========

   This module uses Term::ReadLine to give you a prompt at which you can
type commands.

   Entering "h" for help at that prompt will give instructions on how to
interact with the game.

   When in doubt, consult the source - it's made to be fairly clear.

REFERENCES
==========

   Burke, Sean M.  2000.  "Trees".  (In submission: actual article title
may differ.)  Article in *The Perl Journal* #18.  `http://www.tpj.com/'
[Portions of this POD are excerpted from that article.]

   Dewdney, A[lexander] K[eewatin].  1984.  *Planiverse: Computer Contact
with a Two-Dimensional World.*  Poseidon Press, New York.

COPYRIGHT
=========

   Copyright (c) 2000 Sean M. Burke.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Sean M. Burke, sburke@cpan.org

   Thanks to A. K. Dewdney (`http://www.dewdney.com/') for his
encouragement in writing my (abovementioned) TPJ article, as well as for
having written the enjoyable book where he briefly describes it.

Perl module for writing and playing card games
**********************************************

NAME
====

   Games::Cards - Perl module for writing and playing card games

SYNOPSIS
========

     use Games::Cards;
     my $Rummy = new Games::Cards::Game;

     # Create the correct deck for a game of Rummy.
     my $Deck = new Games::Cards::Deck ($Rummy, "Deck");

     # shuffle the deck and create the discard pile
     $Deck->shuffle;
     my $Discard = new Games::Cards::Queue "Discard Pile";

     # Deal out the hands
     foreach my $i (1 .. 3) {
     	my $hand = new Games::Cards::Hand "Player $i" ;
     	$Deck->give_cards($hand, 7);
     	$hand->sort_by_value;
     	push @Hands, $hand;
     }

     # print hands (e.g. "Player 1: AS  2C  3C  3H 10D  QS  KH")
     foreach (@Hands) { print ($_->print("short"), "\n") }

     $Hands[1]->give_a_card ($Discard, "8D"); # discard 8 of diamonds

DESCRIPTION
===========

   This module creates objects and methods to allow easier programming of
card games in Perl. It allows you to do things like create decks of cards,
have piles of cards, hands, and other sets of cards, turn cards face-up or
face-down, and move cards from one set to another. Which is pretty much
all you need for most card games.

   Sub-packages include:

Games::Cards::Undo
     This package handles undoing and redoing moves (important for
     solitaire).

and Games::Cards::Tk
     This package allows you to write games that use a Tk graphical
     interface.  It's designed so that it will be relatively easy to write
     a game that uses i<either> a GUI or a simple text interface,
     depending on the player's circumstances (availability of Tk,
     suspicious boss, etc.). See Games/Cards/Tk, for
     more details on writing Tk games.

Quick Overview of Classes
-------------------------

   A GC::Game stores information like what cards are in the starting deck,
plus pointers to the various Cards and CardSets.

   A GC::Card represents one playing card. Every Card must belong to one
(and only one) CardSet at every point during the game.

   A GC::CardSet is mostly just a set of GC::Cards. A CardSet has a unique
name. Many also have short nicknames, which make it easier to write games
that move cards between the sets. (See Klondike or FreeCell, for example.)

   There are many sorts of CardSet. The basic differentiation is Piles,
for which you only access the top or bottom card (or cards) and Hands,
where you might access any one of the cards in the Hand. Piles are broken
up into Stacks and Queues, and every game starts with a Deck of cards (or
more than one).

Class Games::Cards::Game
------------------------

   This class represents a certain game, like War, or Solitaire. This is
necessary to store the various rules for a given game, like the ranking of
the cards. (Or, for more exotic games, how many cards of what type are in
the deck.) Methods:

current_game
     Returns the current Game object. In almost every case, you'll only be
     working with one at a time.

set_current_game(GAME)
     In theory, these subs let you handle multiple Games at once, as long
     as you set_current_game to the right one. Note that Game->new
     automatically sets the current Game to be that game, so in 99% of
     cases, you won't have to call set_current_game.

new(HASHREF)
     creates a new game. HASHREF is a reference to a hash containing zero
     or more of the keys "suits" and "cards_in_suit". "suits" is a list of
     the suits in a deck, "cards_in_suit" is a reference to a hash whose
     keys are the names of the cards in one suit and whose values are the
     values (or ranks) of those cards. If "suits" is not given, the
     default suits (Clubs, Diamonds, Hearts, Spades) are used. If
     "cards_in_suit" is not given, the default cards (Ace, 2..10, Jack,
     Queen, King with values 1..13) are used.  For example, war would
     require "Ace"=>14.

get_cardset_by_name(NAME)
     Returns the CardSet with name NAME

get_cardset_by_nickname(NAME)
     Returns the CardSet with nickname NAME

get_card_by_truename(NAME)
     Returns the Card with truename NAME

Games::Cards::Deck
------------------

   A deck is a deck of cards. The number of cards and identities of the
cards in the deck depend on the particular Game for which the deck is used.

new (GAME, NAME)
     creates an *unshuffled* deck of cards. For each card in the deck it
     creates a name, suit, value, and suit value. GAME is the GC::Game
     this deck belongs to, and it stipulates the number of cards in the
     deck, etc. NAME is the name to give the deck, e.g.  "Deck".

Class Games::Cards::Queue
-------------------------

   A Queue (cf. computer science terminology, or the C++ stdlib) is a
first-in first-out pile of cards. Cards are removed from the top of the
pile, but new cards are added to the bottom of the pile.  This might
represent, say, a pile of face-down cards, like the player's hand in War.

Class Games::Cards::Stack
-------------------------

   A stack (cf. computer science terminology, or the C++ stdlib) is a
last-in first-out pile of cards. Cards are removed from the top of the
pile, and new cards are also added to the top of the pile. This would
usually represent a pile of cards with its top card (and perhaps all
cards) face up.

Class Games::Cards::Pile
------------------------

   A Pile is a pile of cards. That is, it is a CardSet where we will only
access the beginning or end of the set. (This may include the first N
cards in the set, but we will never reference the 17'th card.) This is a
super class of Queue and Stack, and those classes should be used instead,
so that we know whether the cards in the pile are FIFO or LIFO. Methods:

give_cards(RECEIVER, NUMBER)
     Transfers NUMBER cards from the donor (the object on which this
     method was called) to the CardSet RECEIVER.  This method can used for
     dealing cards from a deck, giving cards to another player (Go Fish),
     putting cards on the table (War), or transferring a card or cards
     between piles in solitaire.

     If NUMBER is "all", then the donor gives all of its cards.

     Returns 1 usually. If the donor has too few cards, it returns 0 and
     does not transfer any cards.

top_card
     Returns the top Card in the CardSet (or 0 if CardSet is empty)

Class Games::Cards::Hand
------------------------

   A Hand represents a player's hand. Most significantly, it's a CardSet
which is different from a Pile because the Cards in it are unordered. We
may reference any part of the CardSet, not just the top or bottom.
Methods:

give_a_card(RECEIVER, DESCRIPTION)
     Transfers Card described by DESCRIPTION from the donor (the Hand on
     which this method was called) to the CardSet RECEIVER.  This method
     can used for discarding a card from a hand, e.g.

     If DESCRIPTION matches /^-?\d+$/, then it is the index in the cards
     array of the Card to give.  Otherwise, DESCRIPTION is passed to
     Hand::index.

     Returns 1 usually. If the donor does not have the card, it returns 0
     and does not transfer anything.

move_card(DESCRIPTION, INDEX)
     Rearrange a Hand by putting Card described by DESCRIPTION at index
     INDEX.

     If DESCRIPTION matches /^-?\d+$/, then it is the index in the cards
     array of the Card to give.  Otherwise, DESCRIPTION is passed to
     Hand::index.

     Returns 1 usually. If the donor does not have the card, it returns 0
     and does not transfer anything.

index(DESCRIPTION)
     Given a card description DESCRIPTION return the index of that Card in
     the Hand, or undef if it was not found. DESCRIPTION may be a Card or
     a string (like "8H" or "KC").

Class Games::Cards::CardSet
---------------------------

   A CardSet is just an array of cards (stored in the "cards" field). It
could be a player's hand, a deck, or a discard pile, for instance. This is
a super class of a number of other classes, and those subclasses should be
used instead.

new(GAME, NAME, NICKNAME)
     create a new (empty) CardSet. GAME is the Game object that this set
     belongs to. NAME is a unique string that e.g. can be output when you
     print the CardSet.  Optionally, NICKNAME is a (unique!) short name
     that will be used to reference the set.

shuffle
     shuffles the cards in the CardSet. Shuffling is not undoable.

sort_by_value
     Sorts the Set by value. This and other sort routines will probably be
     used mostly on Hands, which are "ordered sets", but you might want to
     reorder a deck or something. Sorting is not undoable.

sort_by_suit
     Sorts the Set by suit, but not by value within the suit.

sort_by_suit_and_value
     Sorts the Set by suit, then by value within the suit.

clone(GAME, NAME, NICKNAME)
     Create a copy of this CardSet. That is, create an object with the
     same class as arg0. Then make a copy of each Card in the CardSet
     (true copy, not a reference). arg1 is the Game that the set belongs
     to. arg2 is the name to give the new CardSet. arg3 (optional) is the
     nickname.

face_down
     Makes a whole CardSet face down

face_up
     Makes a whole CardSet face up

print(LENGTH)
     Returns a string containing a printout of the Cards in the CardSet.
     Prints a long printout if LENGTH is "long", short if "short" (or
     nothing).  The CardSet is printed out in reverse order, so that the
     top card of the set is printed first.

name
     Returns the name of the Set

nickname
     Returns the nickname of the Set (or undef if there is none)

cards
     Returns a reference to the array of Cards in the set

size
     Tells how many cards are in the set

Class Games::Cards::Card
------------------------

   A Card is a playing card. Methods:

new(GAME, HASHREF)
     creates a new card. GAME is the Game this card is being created in.
     HASHREF references a hash with keys "suit" and "name".

clone(GAME)
     makes a copy of the Card (not just a reference to it).

print(LENGTH)
     returns a string with the whole card name ("King of Hearts") if
     LENGTH is "long", otherwise a short version ("KH").

truename
     Gives a unique description of this card, i.e., you're guaranteed that
     no other card in the Game will have the same description.

suit(LENGTH)
     Returns the suit of the card. Returns the long version ("Diamonds")
     if LENGTH is "long", else a short version ("D").

color
     Is the card "red" or "black"? Returns the color or undef for unknown
     color.

value
     Calculates the value of a card

suit_value
     Returns the suit_value of a card (1..number of suits)

is_face_up
     Returns true if a card is face up

is_face_down
     Returns true if a card is face down

face_up
     Makes a card face up

face_down
     Makes a card face down

owning_cardset
     Returns the CardSet which this Card is a part of

set_owning_cardset(SET_OR_NAME)
     Makes the Card a part of a CardSet. Arg0 is either an actual CardSet
     ref, or the name of a CardSet.

EXAMPLES
========

   An implementation of Klondike (aka standard solitaire) demonstrates how
to use this module in a simple game. Other card game examples are included
as well.  The Games::Cards README should list them all.

NOTES
=====

How to write your own game
--------------------------

   So you want to write a card game using Games::Cards (or even
Games::Cards::Tk)? Great! That's what the module is for.  Here are some
tips about how to write a game.

Steal code
     Laziness applies in Games::Cards just like in the rest of Perl. It
     will be much easier if you start with an existing game.

Stack vs. Queue
     Think carefully about whether the Piles in your game are Stacks (LIFO)
     or Queues (FIFO). As a general rule, piles of cards that are usually
     face down will be Stacks; face up will be Queues. CardSets where you
     want to access specific cards (i.e., not just the first or last) will
     be Hands.

GUI games
     I've tried to design Games::Cards::Tk and the games that use it so
     that the Tk game is very similar to the text game. This allows the
     most code reuse. GUI games may involve clicking, dragging, and a
     different way to display the game; but the underlying game is still
     the same. Also note that serious timewasters may prefer to use the
     keyboard to play GUI games. See Games/Cards/Tk,
     for more details.

Public and Private
------------------

   This module contains a bunch of methods. The public methods are
documented here. That means any method not documented here is probably
private, which means you shouldn't call it directly.

   There are also a bunch of classes. Most private classes are not
documented here. A couple private classes are mentioned, since they have
methods which public classes inherit. In that case, the privateness is
mentioned.

TODO
----

   See the TODO file in the distribution

Not TODO
--------

   Computer AI and GUI display were left as exercises for the reader. Then
Michael Houghton wrote a Tk card game, so I guess the readers are doing
their exercises.

BUGS
====

   You betcha. It's still alpha.

   test.pl doesn't work with MacPerl, because it uses backticks. However,
(as far as I know) the games released with Games::Cards do work.

AUTHORS
=======

   Amir Karger

   Andy Bach wrote a Free Cell port, and gets points for the first
submitted game, plus some neat ideas like CardSet::clone.

   Michael Houghton herveus@Radix.Net wrote the initial Tk Free Cell (two
days after Andy submitted his Free Cell!)  I changed almost all of the code
eventually, to fit in with Games::Cards::Tk, but he gave me the initial
push (and code to steal).

COPYRIGHT
=========

   Copyright (c) 1999-2000 Amir Karger

LICENSE
=======

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1), Tk(1)

Package to write Tk ports for Games::Cards card games
*****************************************************

NAME
====

   Games::Cards::Tk - Package to write Tk ports for Games::Cards card games

SYNOPSIS
========

   See Games/Cards, for all the non-GUI aspects of
writing card games.

     use Games::Cards;
     use Games::Cards::Tk;

     # Create a canvas and print background etc.
     $My_Game->set_canvas($c); # my game will use canvas $c

     # ... do lots of things you do in Games::Cards anyway
     # Cards' Tk images will be moved automatically!
     $Stock->give_cards($Waste, 3);

     # Mark clicked card
     $card = $My_Game->get_card_by_tag("current");
     $card->mark;

DESCRIPTION
===========

WARNING!!!
----------

   This module is doubleplus alpha. It's entirely possible that large parts
of it will be changing as I learn more Tk, and if you try to write a game
that's much different from the included games, it may break. There's still
some stuff that needs to be better modularized, abstracted, and otherwise
made into good code.  However, the current games seem to be pretty good
for a first try, and I'd like to get comments in case I'm doing anything
really stupid.

Overview
--------

   Each class in Games::Cards had a corresponding Games::Cards::Tk class.
The classes are meant to be exactly the same, except that the Tk ones also
take care of moving actual card images around the screen.

   The card images used were created by Oliver Xymoron
(oxymoron@waste.org).

Class Games::Cards::Tk::Game
----------------------------

   This class ends up holding information - such as the canvas that the
game is played on, card images - and methods like finding a card given its
tag.

card_width
card_height
     The size of card images

load_card_images
     Loads the card images and stores them to draw later.

card_image
     Returns the card image associated with this card.

get_card_by_tag
     Given a tag, return the Card (on this Games' canvas) that has that
     tag, if any.

get_card_by_tag
     Given a tag, return the CardSet (on this Games' canvas) that has that
     tag, if any.

get_marked_card
     Is a card marked? If so, return it.

get_clicked_cardset
     Return the set which was clicked on.  Do so by looking for the
     "current" tag, but note that that tag may apply either to a CardSet
     or to a Card in that set.

canvas
set_canvas(Canvas)
     Return/set the Tk::Canvas associated with this Game

Class Games::Cards::Tk::Card
----------------------------

   A Card is represented in GC::Tk as two rectangles, the front and back,
which are always moved around together. The card is "turned over" by
raising the front or back rectangle (but the face_up/face_down methods do
that automatically for you).

   Lots of methods are basically the same as Games::Cards::Card methods. We
just have to add some GUI changes. But there are also some Tk-specific
methods.

Tk_truename
     This returns a Tk tag that's guaranteed to belong to just one Card.
     (However, note this tag will include the card's front and back
     rectangles.)

     Tk_truename_front and Tk_truename_back return tags that will access
     just the front or back image.

unmark
     Unmark a card that was marked with the "mark" method.

place(X, Y)
     Put a Card's images at X, Y.

redraw
     Redraw (i.e. raise) the card & make sure you're showing front/back
     correctly.

Class Games::Cards::Tk::Deck
----------------------------

   This class exists but isn't terribly interesting. The main point is that
by calling this class' new instead of Games::Cards::Deck::new, you
automatically get a deck filled with Games::Cards::Tk::Cards instead of
regular cards.

Class Games::Cards::Tk::CardSet
-------------------------------

   This class has extra methods to do Tk stuff to CardSets, i.e. drawing
columns, rows, piles, hands of cards.

   There are a few extra fields in the Tk version of the class:

delta_x
     x distance between right side of one card and the next in the Set. 0
     if you want the cards to totally overlap, some number of pixels
     smaller than a card if you want them to overlap some, larger than
     cardsize if you want them to not overlap at all.

border_x
     A column may be slightly wider/higher than the cards in it, for
     example.

   Also delta_y and border_y. Fields are changed by the "attributes"
method.

attributes(HASHREF)
     This is a copout way of setting a bunch of CardSet attributes in one
     shot.  Settable attributes include: delta_x/y and border_x/y.
     Hashref's keys are attributes and values are things to set them to.

redraw
     Redraw the Cards in this CardSet. This is the reason you have to set
     things like delta_y and border_x.

undoing/redoing moves in Games::Cards games
*******************************************

NAME
====

   Games::Cards::Undo - undoing/redoing moves in Games::Cards games

SYNOPSIS
========

     use Games::Cards::Undo;
     $Undo = new Games::Cards::Undo(100); # Make undo engine to save 100 moves
     $Undo->undo; # undo last move
     $Undo->redo; # redo last undone move
     $Undo->end_move; # tell undo engine we're done with a move

DESCRIPTION
===========

   This is the package for methods to undo & redo moves. The GC::Undo
object has no publicly accessible fields.  But it stores an array of the
preceding moves. Note that a "move" is made up of several "atoms" (objects
of the private class GC::Undo::Atom and its subclassess).  For example,
moving a card from one column to another in solitaire involves one or more
Splice atoms (removing or adding card(s) to a CardSet) and possibly a Face
atom (turning a card over).

   Many of the GC::Undo methods (and all of the GC::Undo::Atom methods)
will be called by other Games::Cards methods, but not by the actual games.
Here are the publicly accesssible methods:

new(MOVES)
     Initialize the Undo engine. MOVES is the number of atoms to save.  0
     (or no argument) allows infinite undo.

     This method must be called before any undo-able moves are made (i.e.,
     it can be called after the hands are dealt).  This method will also
     re-initialize the engine for a new game.

end_move
     End the current move. Everything between the last call to end_move
     and now is considered one move. This tells undo how much to undo.

undo
     Undo a move.

redo
     Redo a move that had been undone with undo.

represent chess positions and games
***********************************

NAME
====

   Games::Chess - represent chess positions and games

SYNOPSIS
========

     use Games::Chess qw(:constants);
     my $p = Games::Chess::Position->new;
     $p->at(0,0,BLACK,ROOK);
     $p->at(7,7,WHITE,ROOK);
     print $p->to_text;

DESCRIPTION
===========

   The `Games::Chess' package provides the class `Games::Chess::Piece' to
represent chess pieces, and the class `Games::Chess::Position' to
represent a position in a chess game.  Objects can be instantiated from
data in standard formats and exported to these formats.

NOTATION
========

   See Games/Chess/PGN, for full details of the
notations.

SAN
     Standard Algebraic Notation.  The modern international notation for
     chess games.  For example,

          1. e4 e5
          2. f4 exf4
          3. Nf3 g5

FEN
     Forsythe-Edwards Notation.  A compact representation for chess
     positions.  FEN specifies the piece placement, the active color, the
     castling availability, the en passant target square, the halfmove
     clock, and the fullmove number as six fields separated by spaces.
     For example, the opening position is described in FEN as follows:

          rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1

PGN
     Portable Game Notation.  A notation for chess games, including the
     moves, commentary, variations, and metadata such as the players, the
     event, the round number, and the date of the match.  For example,

          [Event "F/S Return Match"]
          [Site "Belgrade, Serbia JUG"]
          [Date "1992.11.04"]
          [Round "29"]
          [White "Fischer, Robert J."]
          [Black "Spassky, Boris V."]
          [Result "1/2-1/2"]

          1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1
          b5 7. Bb3 d6 8. c3 O-O 9. h3 Nb8 10. d4 Nbd7 11. c4 c6
          12. cxb5 axb5 13. Nc3 Bb7 14. Bg5 b4 15. Nb1 h6 16. Bh4 c5
          17. dxe5 Nxe4 18. Bxe7 Qxe7 19. exd6 Qf6 20. Nbd2 Nxd6
          21. Nc4 Nxc4 22. Bxc4 Nb6 23. Ne5 Rae8 24. Bxf7+ Rxf7
          25. Nxf7 Rxe1+ 26. Qxe1 Kxf7 27. Qe3 Qg5 28. Qxg5 hxg5
          29. b3 Ke6 30. a3 Kd6 31. axb4 cxb4 32. Ra5 Nd5 33. f3 Bc8
          34. Kf2 Bf5 35. Ra7 g6 36. Ra6+ Kc5 37. Ke1 Nf4 38. g3 Nxh3
          39. Kd2 Kb5 40. Rd6 Kc5 41. Ra6 Nf2 42. g4 Bd3 43. Re6
          1/2-1/2

EPD
     Extended Position Description.  An extensible notation based on FEN.
     Intended for data interchange between chess-playing programs and for
     the construction of opening databases.  Not used by `Games::Chess'.

ERROR HANDLING
==============

   All the `Games::Chess::*' packages share a common error-handling
protocol, depending on the debugging level passed to the
`Games::Chess::debug' function.  (The debugging level is 0 by default.)

   At debugging level 0, each function and method returns undefined if it
is passed invalid arguments or if some other error happens.  A description
of the error is available by calling `Games::Chess::errmsg'.

   At debugging level 1, each function and method returns undefined if it
is passed invalid arguments or if some other error happens.  A warning is
also issued.  A description of the error is available by calling
`Games::Chess::errmsg'.

   At debugging level 2, each function and method calls die if it is
passed invalid arguments.

CONSTANTS
=========

   Piece colours are represented by the constants `BLACK' and `WHITE'.
Piece values are represented by the constants `PAWN', `KNIGHT', `BISHOP',
`ROOK', `QUEEN', and `KING'.

   To import these constants into your namespace, include the tags
`:colours' (colours only), `:pieces' (piece values only), or `:constants'
(all constants) in the use statement.  For example:

     use Games::Chess qw(:colours);

   (If you `use strict;', you'll have to write these constants as function
calls like `WHITE()' or `&WHITE' to satisfy the compiler.)

FUNCTIONS
=========

   To import all these functions into your namespace, include the tag
`:functions' in the use statement, for example

     use Games::Chess qw(:functions);

algebraic_to_xy($square)
     If $square represents a square in Standard Algebraic Notation (from a1
     to h8), return a list of two elements ($x,$y) giving the coordinates
     of that square, from (0,0) to (7,7).  Return undefined otherwise.

colour_valid($colour)
     Return 1 if $colour is a valid colour value, `WHITE' or `BLACK'.
     Return undefined otherwise.

debug($level)
     Set the debugging level.  See `ERROR HANDLING' in this node.

errmsg
     Return a description of the most recent error in any of the
     `Games::Chess::*' packages, or the empty string if no errors have
     occurred.  See `ERROR HANDLING' in this node.

halfmove_valid($halfmove)
     Return 1 if $halfmove is a valid value for the halfmove clock, which
     counts the number of ply (moves by either player) since the last pawn
     move or capture.  Return undefined otherwise.

move_valid($move)
     Return 1 if $move is a valid value for the full move count (the number
     of black moves since the start of the game, plus 1).  Return undefined
     otherwise.

piece_valid($piece)
     Return 1 if $piece is a valid piece value, from `PAWN' to `KING'.
     Return undefined otherwise.

xy_to_algebraic($x,$y)
     If ($x,$y) is a valid board position, from (0,0) to (7,7), return the
     algebraic notation for that square, from `a1' to `h8'.  Return
     undefined otherwise.

xy_valid($x,$y)
     Return 1 if ($x,$y) is a valid board position, from (0,0) to (7,7).
     Return undefined otherwise.

CHESS PIECES
============

   A chess piece, or an empty square on a chess board, is represented as an
object belonging to the `Games::Chess::Piece' class.

PIECE REPRESENTATION
--------------------

   A chess piece is represented as a reference to an 8-bit value where bits
0-2 are the piece type (0 = empty square, 1 = pawn, 2 = knight, 3 =
bishop, 4 = rook, 5 = queen and 6 = king) and bits 3-4 are the piece color
(0 = empty square, 1 = white, 2 = black).

   Bits 5-7 are reserved for future use.

   So for example, a black knight is represented as the binary value
00010010 (decimal 18).

PIECE CONSTRUCTORS
------------------

Piece->new
     With no argument, return an object representing an empty square.

Piece->new($piece)
     With a single argument that is a member of the `Games::Chess::Piece'
     class, return an object representing the same piece as $piece.

Piece->new($number)
     With a numeric argument, return an object representing a piece with
     that encoding.  Return undefined if $number is not an integer in the
     range 0 to 255.

Piece->new($character)
     With a single character string as an argument, return an object
     representing a piece with that encoding in the standard
     Forsythe-Edwards Notation.  A space represents an empty square, and
     the letters P, N, B, R, Q, and K represent pawn, knight, bishop,
     rook, queen, and king respectively.  Upper-case letters represent
     white pieces and lower-case letters black pieces.  Return undefined
     if $character does not represent a piece.

Piece->new($color,$piece)
     Return an object representing the piece described.  Return undefined
     if $color is not WHITE or BLACK, or $piece is not PAWN, KNIGHT,
     BISHOP, ROOK, QUEEN or KING.

PIECE METHODS
-------------

Piece->code
     Return the FEN code for the piece as a single character
     (PNBRQKpnbrqk), or a space if the piece represents an empty square.

Piece->colour
     Return EMPTY, `WHITE' or `BLACK' as appropriate.

Piece->colour_name
     Return "empty", "white" or "black" as appropriate.

Piece->name
     Return a string describing the piece, for example "black knight", or
     "white king", or "empty square".

Piece->piece
     Return EMPTY, `PAWN', `KNIGHT', `BISHOP', `ROOK', `QUEEN', or `KING'
     as appropriate.

Piece->piece_name
     Return "square", "pawn", "knight", "bishop", "rook", "queen", or
     "king" as appropriate.

CHESS POSITIONS
===============

   A chess position represented as an object belonging to the
`Games::Chess::Position' class.

POSITION REPRESENTATION
-----------------------

   A chess position is represented as a reference to a hash, whose board
member is a vector of 64 bytes, where the square at FILE,RANK is at byte
(FILE*8)+RANK.  For example, square c7 is at byte (2*8)+6 = 22.  Each byte
is in the format described for the `Games::Chess::Piece' class, above.

   The representation is reasonably compact: a position is represented in
64 bytes.  But more importantly, it is easy and efficient to manipulate in
C; you can cast the vector to a 2-dimensional array using code like

     unsigned char (*position)[8][8]
       = (unsigned char(*)[8][8])vector;

   and then position[x][y] refers to the square at file x, rank y.

POSITION CONSTRUCTORS
---------------------

Position->new
     With no argument, return an object representing a position with all 16
     pieces in their initial positions.

Position->new($position)
     With a single argument that is a member of the
     `Games::Chess::Position' class, return a copy of $position.

Position->new($FEN)
     With one string argument, return an object representing the chess
     position described by the Forsythe-Edwards Notation string $FEN.

     The Position constructor does not require $FEN to contain all six FEN
     fields; only the first (the piece placement) is required.  The
     remaining five fields, if missing, take the values `w - - 0 1'.

POSITION METHODS
----------------

Position->at($x,$y)
     If ($x,$y) is a valid board position, return an object of class
     `Games::Chess::Piece' representing the square at ($x,$y).  Return
     undefined otherwise.

Position->at($x,$y,@piece)
     If ($x,$y) is a valid board position, and @piece would be valid as
     arguments to the `Games::Chess::Piece' constructor (see `PIECE
     CONSTRUCTORS' in this node), put the specified piece on the specified
     square and return 1.  Return undefined otherwise.

Position->board
     Return the board position as a vector of 64 bytes.

Position->can_castle($colour,$piece)
     If $colour is a valid colour, and $piece is `KING' or `QUEEN', return
     true if the player given by $colour can castle on the side given by
     $piece, false if they cannot.  Return undefined otherwise.

Position->can_castle($colour,$piece,$can_castle)
     If $colour is a valid colour, and $piece is `KING' or `QUEEN', set the
     castling availability for the player given by $colour and the side
     given by $piece to the truth value of $can_castle, and return 1.
     Return undefined otherwise.

Position->clear($x,$y)
     If ($x,$y) is a valid board position, clear the specified square and
     return 1.  Return undefined otherwise.  Equivalent to

          Position->at($x,$y,Piece->new);

Position->en_passant
     Return the en passant target square as the list (FILE,RANK), or
     undefined if there is no en passant target square.

Position->en_passant($x,$y)
     If ($x,$y) is a valid board position, set the en passant target square
     to ($x,$y) and return 1.  Return undefined otherwise.

Position->halfmove_clock
     Return the halfmove clock (the number of ply since the last pawn move
     or capture).

Position->halfmove_clock($halfmove)
     If $halfmove is a valid halfmove clock value, set the halfmove clock
     to $halfmove and return 1.  Return undefined otherwise.

Position->move_number
     Return the move number (the number of full moves since the beginning
     of the game, plus 1).

Position->move_number($move)
     If $move is a valid move number, set the move number to $move and
     return 1.  Return undefined otherwise.

Position->player_to_move
     Return `WHITE' if white is to move, `BLACK' otherwise.

Position->player_to_move($colour)
     If $colour is `WHITE' or `BLACK', set the player to move to $colour
     and return 1.  Return undefined otherwise.

Position->to_FEN
     Return a string representing the board position in Forsythe-Edwards
     notation.  For example, the initial position is returned as the string

          rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1

Position->to_GIF(option => value, ...)
     Return a string representing the board position as a GIF (an image in
     Graphics Interchange Format).  The following options can be passed to
     control the image:

    border
          The width of the black border around the chess board, in pixels
          (defaults to 2).

    letters
          If true, draw a margin to the left of the board containing rank
          numbers, and a margin below the board containing file letters
          (defaults to true).

    bmargin
          The height of the margin to draw below the board (containing the
          file letters), in pixels (defaults to 20).  Ignored if the
          letters option is false.

    lmargin
          The width of the margin to draw to the left of the board
          (containing the rank numbers), in pixels (defaults to 20).
          Ignored if the letters option is false.

    font
          A reference to a `GD::Font' object describing the font to use to
          draw the rank numbers and file letters (defaults to
          `GD::Font::Giant').  Ignored if the letters option is false.

Position->to_text
     Return a string representing the board position as an ASCII diagram.
     For example, the initial position is returned as the string

          r n b q k b n r
          p p p p p p p p
            .   .   .   .
          .   .   .   .
            .   .   .   .
          .   .   .   .
          P P P P P P P P
          R N B Q K B N R

Position->validate
     Apply some simple validation tests to the position.  Return 1 if the
     position passes the tests, undefined otherwise.  If the position fails
     to validate, the reason for failure can be found by calling
     `Games::Chess::errmsg'.

     These tests are applied:

       1. The total of pawns plus obviously promoted pieces (for example,
          a second queen or a third rook) must be no more than 8 on each
          side.

       2. Each side must have exactly one king.

       3. There must be no pawns on ranks 1 and 8.

       4. The en passant target square, if specified, must be plausible.
          That is, if white is to move, the ep square must be on rank 6,
          with a black pawn on rank 5 and empty squares on ranks 6 and 7
          in that file.  If black is to move, the ep square must be on
          rank 3, with a white pawn on rank 4 and empty squares on ranks 2
          and 3 in that file.

       5. The castling availability must be plausible.  For example, if
          white can castle queenside, there must be a white rook on a1 and
          a white king on e1.

       6. The halfmove count must be between 0 and 50 (it can't be greater
          than 50 or the game would have been drawn).

       7. The full move number must be 1 or more.

BUGS
====

   * No representation of chess moves.

   * No representation of chess games and no support for PGN.

   * No simple way to clear the en passant target square.

   * No way to choose a different font for the chess pieces when creating a
     GIF (if anyone knows an easy way to do this, I'd love to know about
     it).

   * No way to choose the size of the chess pieces when creating a GIF.

SEE ALSO
========

   See Games/Chess/PGN, - a description of the Portable
Game Notation (PGN) standard, incorporating Standard Algebraic Notation
(SAN), Forsythe-Edwards Notation (FEN) and Extended Position Description
(EPD).  (Steven J. Edwards)

   See GD, - a Perl interface to Tom Boutell's `libgd' graphics
library.  (Lincoln Stein)

AUTHOR
======

   Gareth Rees `<garethr@cre.canon.co.uk>'.

COPYRIGHT
=========

   Copyright (c) 1999 Gareth Rees.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Portable Game Notation for Chess
********************************

NAME
====

   PGN - Portable Game Notation for Chess

DESCRIPTION
===========

   This is the Portable Game Notation Specification and Implementation
Guide, as revised on 12th March 1994.

AUTHOR
======

   Interested readers of the Internet newsgroup rec.games.chess,
coordinated by Steven J. Edwards `<sje@world.std.com>'.

0. PREFACE
==========

   From the Tower of Babel story:

   "If now, while they are one people, all speaking the same language, they
have started to do this, nothing will later stop them from doing whatever
they propose to do."

   Genesis XI, v.6, New American Bible

1. INTRODUCTION
===============

   PGN is "Portable Game Notation", a standard designed for the
representation of chess game data using ASCII text files.  PGN is
structured for easy reading and writing by human users and for easy
parsing and generation by computer programs.  The intent of the definition
and propagation of PGN is to facilitate the sharing of public domain chess
game data among chessplayers (both organic and otherwise), publishers, and
computer chess researchers throughout the world.

   PGN is not intended to be a general purpose standard that is suitable
for every possible use; no such standard could fill all conceivable
requirements.  Instead, PGN is proposed as a universal portable
representation for data interchange.  The idea is to allow the
construction of a family of chess applications that can quickly and easily
process chess game data using PGN for import and export among themselves.

2. CHESS DATA REPRESENTATION
============================

   Computer usage among chessplayers has become quite common in recent
years and a variety of different programs, both commercial and public
domain, are used to generate, access, and propagate chess game data.  Some
of these programs are rather impressive; most are now well behaved in that
they correctly follow the Laws of Chess and handle users' data with
reasonable care.  Unfortunately, many programs have had serious problems
with several aspects of the external representation of chess game data.
Sometimes these problems become more visible when a user attempts to move
significant quantities of data from one program to another; if there has
been no real effort to ensure portability of data, then the chances for a
successful transfer are small at best.

2.1 DATA INTERCHANGE INCOMPATIBILITY
------------------------------------

   The reasons for format incompatibility are easy to understand.  In
fact, most of them are correlated with the same problems that have already
been seen with commercial software offerings for other domains such as
word processing, spreadsheets, fonts, and graphics.  Sometimes a
manufacturer deliberately designs a data format using encryption or some
other secret, proprietary technique to "lock in" a customer.  Sometimes a
designer may produce a format that can be deciphered without too much
difficulty, but at the same time publicly discourage third party software
by claiming trade secret protection.  Another software producer may
develop a non-proprietary system, but it may work well only within the
scope of a single program or application because it is not easily
expandable.  Finally, some other software may work very well for many
purposes, but it uses symbols and language not easily understood by people
or computers available to those outside the country of its development.

2.2 SPECIFICATION GOALS
-----------------------

   A specification for a portable game notation must observe the lessons of
history and be able to handle probable needs of the future.  The design
criteria for PGN were selected to meet these needs.  These criteria
include:

  1. The details of the system must be publicly available and free of
     unnecessary complexity.  Ideally, if the documentation is not
     available for some reason, typical chess software developers and
     users should be able to understand most of the data without the need
     for third party assistance.

  2. The details of the system must be non-proprietary so that users and
     software developers are unrestricted by concerns about infringing on
     intellectual property rights.  The idea is to let chess programmers
     compete in a free market where customers may choose software based on
     their real needs and not based on artificial requirements created by a
     secret data format.

  3. The system must work for a variety of programs.  The format should be
     such that it can be used by chess database programs, chess publishing
     programs, chess server programs, and chessplaying programs without
     being unnecessarily specific to any particular application class.

  4. The system must be easily expandable and scalable.  The expansion
     ability must include handling data items that may not exist currently
     but could be expected to emerge in the future.  (Examples: new opening
     classifications and new country names.)  The system should be scalable
     in that it must not have any arbitrary restrictions concerning the
     quantity of stored data.  Also, planned modes of expansion should
     either preserve earlier databases or at least allow for their
     automatic conversion.

  5. The system must be international.  Chess software users are found in
     many countries and the system should be free of difficulties caused by
     conventions local to a given region.

  6. Finally, the system should handle the same kinds and amounts of data
     that are already handled by existing chess software and by print
     media.

2.3 A SAMPLE PGN GAME
---------------------

   Although its description may seem rather lengthy, PGN is actually fairly
simple.  A sample PGN game follows; it has most of the important features
described in later sections of this document.

     [Event "F/S Return Match"]
     [Site "Belgrade, Serbia JUG"]
     [Date "1992.11.04"]
     [Round "29"]
     [White "Fischer, Robert J."]
     [Black "Spassky, Boris V."]
     [Result "1/2-1/2"]

     1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3
     d6 8. c3 O-O 9. h3 Nb8 10. d4 Nbd7 11. c4 c6 12. cxb5 axb5 13. Nc3
     Bb7 14. Bg5 b4 15.  Nb1 h6 16. Bh4 c5 17. dxe5 Nxe4 18. Bxe7 Qxe7
     19. exd6 Qf6 20. Nbd2 Nxd6 21.  Nc4 Nxc4 22. Bxc4 Nb6 23. Ne5 Rae8
     24. Bxf7+ Rxf7 25. Nxf7 Rxe1+ 26. Qxe1 Kxf7 27. Qe3 Qg5 28. Qxg5
     hxg5 29. b3 Ke6 30. a3 Kd6 31. axb4 cxb4 32. Ra5 Nd5 33.  f3 Bc8
     34. Kf2 Bf5 35. Ra7 g6 36. Ra6+ Kc5 37. Ke1 Nf4 38. g3 Nxh3 39. Kd2
     Kb5 40. Rd6 Kc5 41. Ra6 Nf2 42. g4 Bd3 43. Re6 1/2-1/2

3. FORMATS: IMPORT AND EXPORT
=============================

   There are two formats in the PGN specification.  These are the "import"
format and the "export" format.  These are the two different ways of
formatting the same PGN data according to its source.  The details of the
two formats are described throughout the following sections of this
document.

   Other than formats, there is the additional topic of PGN presentation.
While both PGN import and export formats are designed to be readable by
humans, there is no recommendation that either of these be an ultimate
mode of chess data presentation.  Rather, software developers are urged to
consider all of the various techniques at their disposal to enhance the
display of chess data at the presentation level (i.e., highest level) of
their programs.  This means that the use of different fonts, character
sizes, color, and other tools of computer aided interaction and publishing
should be explored to provide a high quality presentation appropriate to
the function of the particular program.

3.1 IMPORT FORMAT ALLOWS FOR MANUALLY PREPARED DATA
---------------------------------------------------

   The import format is rather flexible and is used to describe data that
may have been prepared by hand, much like a source file for a high level
programming language.  A program that can read PGN data should be able to
handle the somewhat lax import format.

3.2 EXPORT FORMAT USED FOR PROGRAM GENERATED OUTPUT
---------------------------------------------------

   The export format is rather strict and is used to describe data that is
usually prepared under program control, something like a pretty printed
source program reformatted by a compiler.

3.2.1 BYTE EQUIVALENCE
----------------------

   For a given PGN data file, export format representations generated by
different PGN programs on the same computing system should be exactly
equivalent, byte for byte.

3.2.2 ARCHIVAL STORAGE AND THE NEWLINE CHARACTER
------------------------------------------------

   Export format should also be used for archival storage.  Here,
"archival" storage is defined as storage that may be accessed by a variety
of computing systems.  The only extra requirement for archival storage is
that the newline character have a specific representation that is
independent of its value for a particular computing system's text file
usage.  The archival representation of a newline is the ASCII control
character LF (line feed, decimal value 10, hexadecimal value 0x0a).

   Sadly, there are some accidents of history that survive to this day that
have baroque representations for a newline: multicharacter sequences,
end-of-line record markers, start-of-line byte counts, fixed length
records, and so forth.  It is well beyond the scope of the PGN project to
reconcile all of these to the unified world of ANSI C and the those
enjoying the bliss of a single '\n' convention.  Some systems may just not
be able to handle an archival PGN text file with native text editors.  In
these cases, an indulgence of sorts is granted to use the local newline
convention in non-archival PGN files for those text editors.

3.2.3 SPEED OF PROCESSING
-------------------------

   Several parts of the export format deal with exact descriptions of line
and field justification that are absent from the import format details.
The main reason for these restrictions on the export format are to allow
the construction of simple data translation programs that can easily scan
PGN data without having to have a full chess engine or other complex
parsing routines.  The idea is to encourage chess software authors to
always allow for at least a limited PGN reading capability.  Even when a
full chess engine parsing capability is available, it is likely to be at
least two orders of magnitude slower than a simple text scanner.

3.2.4 REDUCED EXPORT FORMAT
---------------------------

   A PGN game represented using export format is said to be in "reduced
export format" if all of the following hold: 1) it has no commentary, 2)
it has only the standard seven tag roster identification information
("STR", see below), 3) it has no recursive annotation variations ("RAV",
see below), and 4) it has no numeric annotation glyphs ("NAG", see below).
Reduced export format is used for bulk storage of unannotated games.  It
represents a minimum level of standard conformance for a PGN exporting
application.

4. LEXICOGRAPHICAL ISSUES
=========================

   PGN data is composed of characters; non-overlapping contiguous sequences
of characters form lexical tokens.

4.1 CHARACTER CODES
-------------------

   PGN data is represented using a subset of the eight bit ISO 8859/1
(Latin 1) character set.  This set is also known as ECMA-94 and is similar
to other ISO Latin character sets.  ISO 8859/1 includes the standard seven
bit ASCII character set for the 32 control character code values from zero
to 31.  The 95 printing character code values from 32 to 126 are also
equivalent to seven bit ASCII usage.  (Code value 127, the ASCII DEL
control character, is a graphic character in ISO 8859/1; it is not used
for PGN data representation.)

   The 32 ISO 8859/1 code values from 128 to 159 are non-printing control
characters.  They are not used for PGN data representation.  The 32 code
values from 160 to 191 are mostly non-alphabetic printing characters and
their use for PGN data is discouraged as their graphic representation
varies considerably among other ISO Latin sets.  Finally, the 64 code
values from 192 to 255 are mostly alphabetic printing characters with
various diacritical marks; their use is encouraged for those languages
that require such characters.  The graphic representations of this last
set of 64 characters is fairly constant for the ISO Latin family.

   Printing character codes outside of the seven bit ASCII range may only
appear in string data and in commentary.  They are not permitted for use
in symbol construction.

   Because some PGN users' environments may not support presentation of
non-ASCII characters, PGN game authors should refrain from using such
characters in critical commentary or string values in game data that may
be referenced in such environments.  PGN software authors should have
their programs handle such environments by displaying a question mark
("?") for non-ASCII character codes.  This is an important point because
there are many computing systems that can display eight bit character
data, but the display graphics may differ among machines and operating
systems from different manufacturers.

   Only four of the ASCII control characters are permitted in PGN import
format; these are the horizontal and vertical tabs along with the linefeed
and carriage return codes.

   The external representation of the newline character may differ among
platforms; this is an acceptable variation as long as the details of the
implementation are hidden from software implementors and users.  When a
choice is practical, the Unix "newline is linefeed" convention is
preferred.

4.2 TAB CHARACTERS
------------------

   Tab characters, both horizontal and vertical, are not permitted in the
export format.  This is because the treatment of tab characters is highly
dependent upon the particular software in use on the host computing
system.  Also, tab characters may not appear inside of string data.

4.3 LINE LENGTHS
----------------

   PGN data are organized as simple text lines without any special bytes or
markers for secondary record structure imposed by specific operating
systems.  Import format PGN text lines are limited to having a maximum of
255 characters per line including the newline character.  Lines with 80 or
more printing characters are strongly discouraged because of the
difficulties experienced by common text editors with long lines.

   In some cases, very long tag values will require 80 or more columns, but
these are relatively rare.  An example of this is the "FEN" tag pair; it
may have a long tag value, but this particular tag pair is only used to
represent a game that doesn't start from the usual initial position.

5. COMMENTARY
=============

   Comment text may appear in PGN data.  There are two kinds of comments.
The first kind is the "rest of line" comment; this comment type starts
with a semicolon character and continues to the end of the line.  The
second kind starts with a left brace character and continues to the next
right brace character.  Comments cannot appear inside any token.

   Brace comments do not nest; a left brace character appearing in a brace
comment loses its special meaning and is ignored.  A semicolon appearing
inside of a brace comment loses its special meaning and is ignored.
Braces appearing inside of a semicolon comments lose their special meaning
and are ignored.

   *** Export format representation of comments needs definition work.

6. ESCAPE MECHANISM
===================

   There is a special escape mechanism for PGN data.  This mechanism is
triggered by a percent sign character ("%") appearing in the first column
of a line; the data on the rest of the line is ignored by publicly
available PGN scanning software.  This escape convention is intended for
the private use of software developers and researchers to embed non-PGN
commands and data in PGN streams.

   A percent sign appearing in any other place other than the first
position in a line does not trigger the escape mechanism.

7. TOKENS
=========

   PGN character data is organized as tokens.  A token is a contiguous
sequence of characters that represents a basic semantic unit.  Tokens may
be separated from adjacent tokens by white space characters.  (White space
characters include space, newline, and tab characters.)  Some tokens are
self delimiting and do not require white space characters.

   A string token is a sequence of zero or more printing characters
delimited by a pair of quote characters (ASCII decimal value 34,
hexadecimal value 0x22).  An empty string is represented by two adjacent
quotes.  (Note: an apostrophe is not a quote.)  A quote inside a string is
represented by the backslash immediately followed by a quote.  A backslash
inside a string is represented by two adjacent backslashes.  Strings are
commonly used as tag pair values (see below).  Non-printing characters
like newline and tab are not permitted inside of strings.  A string token
is terminated by its closing quote.  Currently, a string is limited to a
maximum of 255 characters of data.

   An integer token is a sequence of one or more decimal digit characters.
It is a special case of the more general "symbol" token class described
below.  Integer tokens are used to help represent move number indications
(see below).  An integer token is terminated just prior to the first
non-symbol character following the integer digit sequence.

   A period character (".") is a token by itself.  It is used for move
number indications (see below).  It is self terminating.

   An asterisk character ("*") is a token by itself.  It is used as one of
the possible game termination markers (see below); it indicates an
incomplete game or a game with an unknown or otherwise unavailable result.
It is self terminating.

   The left and right bracket characters ("[" and "]") are tokens.  They
are used to delimit tag pairs (see below).  Both are self terminating.

   The left and right parenthesis characters ("(" and ")") are tokens.
They are used to delimit Recursive Annotation Variations (see below).
Both are self terminating.

   The left and right angle bracket characters ("<" and ">") are tokens.
They are reserved for future expansion.  Both are self terminating.

   A Numeric Annotation Glyph ("NAG", see below) is a token; it is composed
of a dollar sign character ("$") immediately followed by one or more digit
characters.  It is terminated just prior to the first non-digit character
following the digit sequence.

   A symbol token starts with a letter or digit character and is
immediately followed by a sequence of zero or more symbol continuation
characters.  These continuation characters are letter characters
("A-Za-z"), digit characters ("0-9"), the underscore ("_"), the plus sign
("+"), the octothorpe sign ("#"), the equal sign ("="), the colon (":"),
and the hyphen ("-").  Symbols are used for a variety of purposes.  All
characters in a symbol are significant.  A symbol token is terminated just
prior to the first non-symbol character following the symbol character
sequence.  Currently, a symbol is limited to a maximum of 255 characters
in length.

8. PARSING GAMES
================

   A PGN database file is a sequential collection of zero or more PGN
games.  An empty file is a valid, although somewhat uninformative, PGN
database.

   A PGN game is composed of two sections.  The first is the tag pair
section and the second is the movetext section.  The tag pair section
provides information that identifies the game by defining the values
associated with a set of standard parameters.  The movetext section gives
the usually enumerated and possibly annotated moves of the game along with
the concluding game termination marker.  The chess moves themselves are
represented using SAN (Standard Algebraic Notation), also described later
in this document.

8.1 TAG PAIR SECTION
--------------------

   The tag pair section is composed of a series of zero or more tag pairs.

   A tag pair is composed of four consecutive tokens: a left bracket token,
a symbol token, a string token, and a right bracket token.  The symbol
token is the tag name and the string token is the tag value associated
with the tag name.  (There is a standard set of tag names and semantics
described below.)  The same tag name should not appear more than once in a
tag pair section.

   A further restriction on tag names is that they are composed exclusively
of letters, digits, and the underscore character.  This is done to
facilitate mapping of tag names into key and attribute names for use with
general purpose database programs.

   For PGN import format, there may be zero or more white space characters
between any adjacent pair of tokens in a tag pair.

   For PGN export format, there are no white space characters between the
left bracket and the tag name, there are no white space characters between
the tag value and the right bracket, and there is a single space character
between the tag name and the tag value.

   Tag names, like all symbols, are case sensitive.  All tag names used for
archival storage begin with an upper case letter.

   PGN import format may have multiple tag pairs on the same line and may
even have a tag pair spanning more than a single line.  Export format
requires each tag pair to appear left justified on a line by itself; a
single empty line follows the last tag pair.

   Some tag values may be composed of a sequence of items.  For example, a
consultation game may have more than one player for a given side.  When
this occurs, the single character ":" (colon) appears between adjacent
items.  Because of this use as an internal separator in strings, the colon
should not otherwise appear in a string.

   The tag pair format is designed for expansion; initially only strings
are allowed as tag pair values.  Tag value formats associated with the STR
(Seven Tag Roster, see below) will not change; they will always be string
values.  However, there are long term plans to allow general list
structures as tag values for non-STR tag pairs.  Use of these expanded tag
values will likely be restricted to special research programs.  In all
events, the top level structure of a tag pair remains the same: left
bracket, tag name, tag value, and right bracket.

8.1.1 SEVEN TAG ROSTER
----------------------

   There is a set of tags defined for mandatory use for archival storage of
PGN data.  This is the STR (Seven Tag Roster).  The interpretation of
these tags is fixed as is the order in which they appear.  Although the
definition and use of additional tag names and semantics is permitted and
encouraged when needed, the STR is the common ground that all programs
should follow for public data interchange.

   For import format, the order of tag pairs is not important.  For export
format, the STR tag pairs appear before any other tag pairs.  (The STR tag
pairs must also appear in order; this order is described below).  Also for
export format, any additional tag pairs appear in ASCII order by tag name.

   The seven tag names of the STR are (in order):

  1. Event (the name of the tournament or match event)

  2. Site (the location of the event)

  3. Date (the starting date of the game)

  4. Round (the playing round ordinal of the game)

  5. White (the player of the white pieces)

  6. Black (the player of the black pieces)

  7. Result (the result of the game)

        A set of supplemental tag names is given later in this document.

   For PGN export format, a single blank line appears after the last of the
tag pairs to conclude the tag pair section.  This helps simple scanning
programs to quickly determine the end of the tag pair section and the
beginning of the movetext section.

8.1.1.1 THE EVENT TAG
---------------------

   The Event tag value should be reasonably descriptive.  Abbreviations are
to be avoided unless absolutely necessary.  A consistent event naming
should be used to help facilitate database scanning.  If the name of the
event is unknown, a single question mark should appear as the tag value.

   Examples:

     [Event "FIDE World Championship"]

     [Event "Moscow City Championship"]

     [Event "ACM North American Computer Championship"]

     [Event "Casual Game"]

8.1.1.2 THE SITE TAG
--------------------

   The Site tag value should include city and region names along with a
standard name for the country.  The use of the IOC (International Olympic
Committee) three letter names is suggested for those countries where such
codes are available.  If the site of the event is unknown, a single
question mark should appear as the tag value.  A comma may be used to
separate a city from a region.  No comma is needed to separate a city or
region from the IOC country code.  A later section of this document gives
a list of three letter nation codes along with a few additions for
"locations" not covered by the IOC.

   Examples:

     [Site "New York City, NY USA"]

     [Site "St. Petersburg RUS"]

     [Site "Riga LAT"]

8.1.1.3 THE DATE TAG
--------------------

   The Date tag value gives the starting date for the game.  (Note: this is
not necessarily the same as the starting date for the event.)  The date is
given with respect to the local time of the site given in the Event tag.
The Date tag value field always uses a standard ten character format:
"YYYY.MM.DD".  The first four characters are digits that give the year,
the next character is a period, the next two characters are digits that
give the month, the next character is a period, and the final two
characters are digits that give the day of the month.  If the any of the
digit fields are not known, then question marks are used in place of the
digits.

   Examples:

     [Date "1992.08.31"]

     [Date "1993.??.??"]

     [Date "2001.01.01"]

8.1.1.4 THE ROUND TAG
---------------------

   The Round tag value gives the playing round for the game.  In a match
competition, this value is the number of the game played.  If the use of a
round number is inappropriate, then the field should be a single hyphen
character.  If the round is unknown, a single question mark should appear
as the tag value.

   Some organizers employ unusual round designations and have multipart
playing rounds and sometimes even have conditional rounds.  In these
cases, a multipart round identifier can be made from a sequence of integer
round numbers separated by periods.  The leftmost integer represents the
most significant round and succeeding integers represent round numbers in
descending hierarchical order.

   Examples:

     [Round "1"]

     [Round "3.1"]

     [Round "4.1.2"]

8.1.1.5 THE WHITE TAG
---------------------

   The White tag value is the name of the player or players of the white
pieces.  The names are given as they would appear in a telephone
directory.  The family or last name appears first.  If a first name or
first initial is available, it is separated from the family name by a
comma and a space.  Finally, one or more middle initials may appear.
(Wherever a comma appears, the very next character should be a space.
Wherever an initial appears, the very next character should be a period.)
If the name is unknown, a single question mark should appear as the tag
value.

   The intent is to allow meaningful ASCII sorting of the tag value that is
independent of regional name formation customs.  If more than one person
is playing the white pieces, the names are listed in alphabetical order
and are separated by the colon character between adjacent entries.  A
player who is also a computer program should have appropriate version
information listed after the name of the program.

   The format used in the FIDE Rating Lists is appropriate for use for
player name tags.

   Examples:

     [White "Tal, Mikhail N."]

     [White "van der Wiel, Johan"]

     [White "Acme Pawngrabber v.3.2"]

     [White "Fine, R."]

8.1.1.6 THE BLACK TAG
---------------------

   The Black tag value is the name of the player or players of the black
pieces.  The names are given here as they are for the White tag value.

   Examples:

     [Black "Lasker, Emmanuel"]

     [Black "Smyslov, Vasily V."]

     [Black "Smith, John Q.:Woodpusher 2000"]

     [Black "Morphy"]

8.1.1.7 THE RESULT TAG
----------------------

   The Result field value is the result of the game.  It is always exactly
the same as the game termination marker that concludes the associated
movetext.  It is always one of four possible values: "1-0" (White wins),
"0-1" (Black wins), "1/2-1/2" (drawn game), and "*" (game still in
progress, game abandoned, or result otherwise unknown).  Note that the
digit zero is used in both of the first two cases; not the letter "O".

   All possible examples:

     [Result "0-1"]

     [Result "1-0"]

     [Result "1/2-1/2"]

     [Result "*"]

8.2 MOVETEXT SECTION
--------------------

   The movetext section is composed of chess moves, move number
indications, optional annotations, and a single concluding game
termination marker.

   Because illegal moves are not real chess moves, they are not permitted
in PGN movetext.  They may appear in commentary, however.  One would hope
that illegal moves are relatively rare in games worthy of recording.

8.2.1 MOVETEXT LINE JUSTIFICATION
---------------------------------

   In PGN import format, tokens in the movetext do not require any specific
line justification.

   In PGN export format, tokens in the movetext are placed left justified
on successive text lines each of which has less than 80 printing
characters.  As many tokens as possible are placed on a line with the
remainder appearing on successive lines.  A single space character appears
between any two adjacent symbol tokens on the same line in the movetext.
As with the tag pair section, a single empty line follows the last line of
data to conclude the movetext section.

   Neither the first or the last character on an export format PGN line is
a space.  (This may change in the case of commentary; this area is
currently under development.)

8.2.2 MOVETEXT MOVE NUMBER INDICATIONS
--------------------------------------

   A move number indication is composed of one or more adjacent digits (an
integer token) followed by zero or more periods.  The integer portion of
the indication gives the move number of the immediately following white
move (if present) and also the immediately following black move (if
present).

8.2.2.1 IMPORT FORMAT MOVE NUMBER INDICATIONS
---------------------------------------------

   PGN import format does not require move number indications.  It does not
prohibit superfluous move number indications anywhere in the movetext as
long as the move numbers are correct.

   PGN import format move number indications may have zero or more period
characters following the digit sequence that gives the move number; one or
more white space characters may appear between the digit sequence and the
period(s).

8.2.2.2 EXPORT FORMAT MOVE NUMBER INDICATIONS
---------------------------------------------

   There are two export format move number indication formats, one for use
appearing immediately before a white move element and one for use
appearing immediately before a black move element.  A white move number
indication is formed from the integer giving the fullmove number with a
single period character appended.  A black move number indication is
formed from the integer giving the fullmove number with three period
characters appended.

   All white move elements have a preceding move number indication.  A
black move element has a preceding move number indication only in two
cases: first, if there is intervening annotation or commentary between the
black move and the previous white move; and second, if there is no
previous white move in the special case where a game starts from a
position where Black is the active player.

   There are no other cases where move number indications appear in PGN
export format.

8.2.3 MOVETEXT SAN (STANDARD ALGEBRAIC NOTATION)
------------------------------------------------

   SAN (Standard Algebraic Notation) is a representation standard for chess
moves using the ASCII Latin alphabet.

   Examples of SAN recorded games are found throughout most modern chess
publications.  SAN as presented in this document uses English language
single character abbreviations for chess pieces, although this is easily
changed in the source.  English is chosen over other languages because it
appears to be the most widely recognized.

   An alternative to SAN is FAN (Figurine Algebraic Notation).  FAN uses
miniature piece icons instead of single letter piece abbreviations.  The
two notations are otherwise identical.

8.2.3.1 SQUARE IDENTIFICATION
-----------------------------

   SAN identifies each of the sixty four squares on the chessboard with a
unique two character name.  The first character of a square identifier is
the file of the square; a file is a column of eight squares designated by
a single lower case letter from "a" (leftmost or queenside) up to and
including "h" (rightmost or kingside).  The second character of a square
identifier is the rank of the square; a rank is a row of eight squares
designated by a single digit from "1" (bottom side [White's first rank])
up to and including "8" (top side [Black's first rank]).  The initial
squares of some pieces are: white queen rook at a1, white king at e1,
black queen knight pawn at b7, and black king rook at h8.

8.2.3.2 PIECE IDENTIFICATION
----------------------------

   SAN identifies each piece by a single upper case letter.  The standard
English values: pawn = "P", knight = "N", bishop = "B", rook = "R", queen
= "Q", and king = "K".

   The letter code for a pawn is not used for SAN moves in PGN export
format movetext.  However, some PGN import software disambiguation code
may allow for the appearance of pawn letter codes.  Also, pawn and other
piece letter codes are needed for use in some tag pair and annotation
constructs.

   It is admittedly a bit chauvinistic to select English piece letters over
those from other languages.  There is a slight justification in that
English is a de facto universal second language among most chessplayers
and program users.  It is probably the best that can be done for now.  A
later section of this document gives alternative piece letters, but these
should be used only for local presentation software and not for archival
storage or for dynamic interchange among programs.

8.2.3.3 BASIC SAN MOVE CONSTRUCTION
-----------------------------------

   A basic SAN move is given by listing the moving piece letter (omitted
for pawns) followed by the destination square.  Capture moves are denoted
by the lower case letter "x" immediately prior to the destination square;
pawn captures include the file letter of the originating square of the
capturing pawn immediately prior to the "x" character.

   SAN kingside castling is indicated by the sequence "O-O"; queenside
castling is indicated by the sequence "O-O-O".  Note that the upper case
letter "O" is used, not the digit zero.  The use of a zero character is
not only incompatible with traditional text practices, but it can also
confuse parsing algorithms which also have to understand about move
numbers and game termination markers.  Also note that the use of the
letter "O" is consistent with the practice of having all chess move
symbols start with a letter; also, it follows the convention that all
non-pwn move symbols start with an upper case letter.

   En passant captures do not have any special notation; they are formed as
if the captured pawn were on the capturing pawn's destination square.
Pawn promotions are denoted by the equal sign "=" immediately following
the destination square with a promoted piece letter (indicating one of
knight, bishop, rook, or queen) immediately following the equal sign.  As
above, the piece letter is in upper case.

8.2.3.4 DISAMBIGUATION
----------------------

   In the case of ambiguities (multiple pieces of the same type moving to
the same square), the first appropriate disambiguating step of the three
following steps is taken:

   First, if the moving pieces can be distinguished by their originating
files, the originating file letter of the moving piece is inserted
immediately after the moving piece letter.

   Second (when the first step fails), if the moving pieces can be
distinguished by their originating ranks, the originating rank digit of
the moving piece is inserted immediately after the moving piece letter.

   Third (when both the first and the second steps fail), the two character
square coordinate of the originating square of the moving piece is
inserted immediately after the moving piece letter.

   Note that the above disambiguation is needed only to distinguish among
moves of the same piece type to the same square; it is not used to
distinguish among attacks of the same piece type to the same square.  An
example of this would be a position with two white knights, one on square
c3 and one on square g1 and a vacant square e2 with White to move.  Both
knights attack square e2, and if both could legally move there, then a
file disambiguation is needed; the (nonchecking) knight moves would be
"Nce2" and "Nge2".  However, if the white king were at square e1 and a
black bishop were at square b4 with a vacant square d2 (thus an absolute
pin of the white knight at square c3), then only one white knight (the one
at square g1) could move to square e2: "Ne2".

8.2.3.5 CHECK AND CHECKMATE INDICATION CHARACTERS
-------------------------------------------------

   If the move is a checking move, the plus sign "+" is appended as a
suffix to the basic SAN move notation; if the move is a checkmating move,
the octothorpe sign "#" is appended instead.

   Neither the appearance nor the absence of either a check or checkmating
indicator is used for disambiguation purposes.  This means that if two (or
more) pieces of the same type can move to the same square the differences
in checking status of the moves does not allieviate the need for the
standard rank and file disabiguation described above.  (Note that a
difference in checking status for the above may occur only in the case of
a discovered check.)

   Neither the checking or checkmating indicators are considered annotation
as they do not communicate subjective information.  Therefore, they are
qualitatively different from move suffix annotations like "!" and "?".
Subjective move annotations are handled using Numeric Annotation Glyphs as
described in a later section of this document.

   There are no special markings used for double checks or discovered
checks.

   There are no special markings used for drawing moves.

8.2.3.6 SAN MOVE LENGTH
-----------------------

   SAN moves can be as short as two characters (e.g., "d4"), or as long as
seven characters (e.g., "Qa6xb7#", "fxg1=Q+").  The average SAN move
length seen in realistic games is probably just fractionally longer than
three characters.  If the SAN rules seem complicated, be assured that the
earlier notation systems of LEN (Long English Notation) and EDN (English
Descriptive Notation) are much more complex, and that LAN (Long Algebraic
Notation, the predecessor of SAN) is unnecessarily bulky.

8.2.3.7 IMPORT AND EXPORT SAN
-----------------------------

   PGN export format always uses the above canonical SAN to represent moves
in the movetext section of a PGN game.  Import format is somewhat more
relaxed and it makes allowances for moves that do not conform exactly to
the canonical format.  However, these allowances may differ among
different PGN reader programs.  Only data appearing in export format is in
all cases guaranteed to be importable into all PGN readers.

   There are a number of suggested guidelines for use with implementing PGN
reader software for permitting non-canonical SAN move representation.  The
idea is to have a PGN reader apply various transformations to attempt to
discover the move that is represented by non-canonical input.  Some
suggested transformations include: letter case remapping, capture
indicator insertion, check indicator insertion, and checkmate indicator
insertion.

8.2.3.8 SAN MOVE SUFFIX ANNOTATIONS
-----------------------------------

   Import format PGN allows for the use of traditional suffix annotations
for moves.  There are exactly six such annotations available: "!", "?",
"!!", "!?", "?!", and "??".  At most one such suffix annotation may appear
per move, and if present, it is always the last part of the move symbol.

   When exported, a move suffix annotation is translated into the
corresponding Numeric Annotation Glyph as described in a later section of
this document.  For example, if the single move symbol "Qxa8?"  appears in
an import format PGN movetext, it would be replaced with the two adjacent
symbols "Qxa8 $2".

8.2.4 MOVETEXT NAG (NUMERIC ANNOTATION GLYPH)
---------------------------------------------

   An NAG (Numeric Annotation Glyph) is a movetext element that is used to
indicate a simple annotation in a language independent manner.  An NAG is
formed from a dollar sign ("$") with a non-negative decimal integer
suffix.  The non-negative integer must be from zero to 255 in value.

8.2.5 MOVETEXT RAV (RECURSIVE ANNOTATION VARIATION)
---------------------------------------------------

   An RAV (Recursive Annotation Variation) is a sequence of movetext
containing one or more moves enclosed in parentheses.  An RAV is used to
represent an alternative variation.  The alternate move sequence given by
an RAV is one that may be legally played by first unplaying the move that
appears immediately prior to the RAV.  Because the RAV is a recursive
construct, it may be nested.

   *** The specification for import/export representation of RAV elements
needs further development.

8.2.6 GAME TERMINATION MARKERS
------------------------------

   Each movetext section has exactly one game termination marker; the
marker always occurs as the last element in the movetext.  The game
termination marker is a symbol that is one of the following four values:
"1-0" (White wins), "0-1" (Black wins), "1/2-1/2" (drawn game), and "*"
(game in progress, result unknown, or game abandoned).  Note that the
digit zero is used in the above; not the upper case letter "O".  The game
termination marker appearing in the movetext of a game must match the
value of the game's Result tag pair.  (While the marker appears as a
string in the Result tag, it appears as a symbol without quotes in the
movetext.)

9. SUPPLEMENTAL TAG NAMES
=========================

   The following tag names and their associated semantics are recommended
for use for information not contained in the Seven Tag Roster.

9.1 PLAYER RELATED INFORMATION
------------------------------

   Note that if there is more than one player field in an instance of a
player (White or Black) tag, then there will be corresponding multiple
fields in any of the following tags.  For example, if the White tag has
the three field value "Jones:Smith:Zacharias" (a consultation game), then
the WhiteTitle tag could have a value of "IM:-:GM" if Jones was an
International Master, Smith was untitled, and Zacharias was a Grandmaster.

9.1.1 TAGS: WHITETITLE, BLACKTITLE
----------------------------------

   These use string values such as "FM", "IM", and "GM"; these tags are
used only for the standard abbreviations for FIDE titles.  A value of "-"
is used for an untitled player.

9.1.2 TAGS: WHITEELO, BLACKELO
------------------------------

   These tags use integer values; these are used for FIDE Elo ratings.  A
value of "-" is used for an unrated player.

9.1.3 TAGS: WHITEUSCF, BLACKUSCF
--------------------------------

   These tags use integer values; these are used for USCF (United States
Chess Federation) ratings.  Similar tag names can be constructed for other
rating agencies.

9.1.4 TAGS: WHITENA, BLACKNA
----------------------------

   These tags use string values; these are the e-mail or network addresses
of the players.  A value of "-" is used for a player without an electronic
address.

9.1.5 TAGS: WHITETYPE, BLACKTYPE
--------------------------------

   These tags use string values; these describe the player types.  The
value "human" should be used for a person while the value "program" should
be used for algorithmic (computer) players.

9.2 EVENT RELATED INFORMATION
-----------------------------

   The following tags are used for providing additional information about
the event.

9.2.1 TAG: EVENTDATE
--------------------

   This uses a date value, similar to the Date tag field, that gives the
starting date of the Event.

9.2.2 TAG: EVENTSPONSOR
-----------------------

   This uses a string value giving the name of the sponsor of the event.

9.2.3 TAG: SECTION
------------------

   This uses a string; this is used for the playing section of a tournament
(e.g., "Open" or "Reserve").

9.2.4 TAG: STAGE
----------------

   This uses a string; this is used for the stage of a multistage event
(e.g., "Preliminary" or "Semifinal").

9.2.5 TAG: BOARD
----------------

   This uses an integer; this identifies the board number in a team event
and also in a simultaneous exhibition.

9.3 OPENING INFORMATION (LOCALE SPECIFIC)
-----------------------------------------

   The following tag pairs are used for traditional opening names.  The
associated tag values will vary according to the local language in use.

9.3.1 TAG: OPENING
------------------

   This uses a string; this is used for the traditional opening name.  This
will vary by locale.  This tag pair is associated with the use of the EPD
opcode "v0" described in a later section of this document.

9.3.2 TAG: VARIATION
--------------------

   This uses a string; this is used to further refine the Opening tag.
This will vary by locale.  This tag pair is associated with the use of the
EPD opcode "v1" described in a later section of this document.

9.3.3 TAG: SUBVARIATION
-----------------------

   This uses a string; this is used to further refine the Variation tag.
This will vary by locale.  This tag pair is associated with the use of the
EPD opcode "v2" described in a later section of this document.

9.4 OPENING INFORMATION (THIRD PARTY VENDORS)
---------------------------------------------

   The following tag pairs are used for representing opening identification
according to various third party vendors and organizations.  References to
these organizations does not imply any endorsement of them or any
endorsement by them.

9.4.1 TAG: ECO
--------------

   This uses a string of either the form "XDD" or the form "XDD/DD" where
the "X" is a letter from "A" to "E" and the "D" positions are digits; this
is used for an opening designation from the five volume Encyclopedia of
Chess Openings.  This tag pair is associated with the use of the EPD
opcode "eco" described in a later section of this document.

9.4.2 TAG: NIC
--------------

   This uses a string; this is used for an opening designation from the
New in Chess database.  This tag pair is associated with the use of the
EPD opcode "nic" described in a later section of this document.

9.5 TIME AND DATE RELATED INFORMATION
-------------------------------------

   The following tags assist with further refinement of the time and data
information associated with a game.

9.5.1 TAG: TIME
---------------

   This uses a time-of-day value in the form "HH:MM:SS"; similar to the
Date tag except that it denotes the local clock time (hours, minutes, and
seconds) of the start of the game.  Note that colons, not periods, are
used for field separators for the Time tag value.  The value is taken from
the local time corresponding to the location given in the Site tag pair.

9.5.2 TAG: UTCTIME
------------------

   This tag is similar to the Time tag except that the time is given
according to the Universal Coordinated Time standard.

9.5.3 TAG: UTCDATE
------------------

   This tag is similar to the Date tag except that the date is given
according to the Universal Coordinated Time standard.

9.6 TIME CONTROL
----------------

   The follwing tag is used to help describe the time control used with the
game.

9.6.1 TAG: TIMECONTROL
----------------------

   This uses a list of one or more time control fields.  Each field
contains a descriptor for each time control period; if more than one
descriptor is present then they are separated by the colon character
(":").  The descriptors appear in the order in which they are used in the
game.  The last field appearing is considered to be implicitly repeated
for further control periods as needed.

   There are six kinds of TimeControl fields.

   The first kind is a single question mark ("?") which means that the time
control mode is unknown.  When used, it is usually the only descriptor
present.

   The second kind is a single hyphen ("-") which means that there was no
time control mode in use.  When used, it is usually the only descriptor
present.

   The third Time control field kind is formed as two positive integers
separated by a solidus ("/") character.  The first integer is the number
of moves in the period and the second is the number of seconds in the
period.  Thus, a time control period of 40 moves in 2 1/2 hours would be
represented as "40/9000".

   The fourth TimeControl field kind is used for a "sudden death" control
period.  It should only be used for the last descriptor in a TimeControl
tag value.  It is sometimes the only descriptor present.  The format
consists of a single integer that gives the number of seconds in the
period.  Thus, a blitz game would be represented with a TimeControl tag
value of "300".

   The fifth TimeControl field kind is used for an "incremental" control
period.  It should only be used for the last descriptor in a TimeControl
tag value and is usually the only descriptor in the value.  The format
consists of two positive integers separated by a plus sign ("+")
character.  The first integer gives the minimum number of seconds
allocated for the period and the second integer gives the number of extra
seconds added after each move is made.  So, an incremental time control of
90 minutes plus one extra minute per move would be given by "4500+60" in
the TimeControl tag value.

   The sixth TimeControl field kind is used for a "sandclock" or
"hourglass" control period.  It should only be used for the last
descriptor in a TimeControl tag value and is usually the only descriptor
in the value.  The format consists of an asterisk ("*") immediately
followed by a positive integer.  The integer gives the total number of
seconds in the sandclock period.  The time control is implemented as if a
sandclock were set at the start of the period with an equal amount of sand
in each of the two chambers and the players invert the sandclock after
each move with a time forfeit indicated by an empty upper chamber.
Electronic implementation of a physical sandclock may be used.  An example
sandclock specification for a common three minute egg timer sandclock
would have a tag value of "*180".

   Additional TimeControl field kinds will be defined as necessary.

9.7 ALTERNATIVE STARTING POSITIONS
----------------------------------

   There are two tags defined for assistance with describing games that did
not start from the usual initial array.

9.7.1 TAG: SETUP
----------------

   This tag takes an integer that denotes the "set-up" status of the game.
A value of "0" indicates that the game has started from the usual initial
array.  A value of "1" indicates that the game started from a set-up
position; this position is given in the "FEN" tag pair.  This tag must
appear for a game starting with a set-up position.  If it appears with a
tag value of "1", a FEN tag pair must also appear.

9.7.2 TAG: FEN
--------------

   This tag uses a string that gives the Forsyth-Edwards Notation for the
starting position used in the game.  FEN is described in a later section
of this document.  If a SetUp tag appears with a tag value of "1", the FEN
tag pair is also required.

9.8 GAME CONCLUSION
-------------------

   There is a single tag that discusses the conclusion of the game.

9.8.1 TAG: TERMINATION
----------------------

   This takes a string that describes the reason for the conclusion of the
game.  While the Result tag gives the result of the game, it does not
provide any extra information and so the Termination tag is defined for
this purpose.

   Strings that may appear as Termination tag values:

abandoned
     Abandoned game.

adjudication
     Result due to third party adjudication process.

death
     Losing player called to greater things, one hopes.

emergency
     Game concluded due to unforeseen circumstances.

normal
     Game terminated in a normal fashion.

rules infraction
     Administrative forfeit due to losing player's failure to observe
     either the Laws of Chess or the event regulations.

time forfeit
     Loss due to losing player's failure to meet time control requirements.

unterminated
     Game not terminated.

9.9 MISCELLANEOUS
-----------------

   These are tags that can be briefly described and that doon't fit well
inother sections.

9.9.1 TAG: ANNOTATOR
--------------------

   This tag uses a name or names in the format of the player name tags;
this identifies the annotator or annotators of the game.

9.9.2 TAG: MODE
---------------

   This uses a string that gives the playing mode of the game.  Examples:
"OTB" (over the board), "PM" (paper mail), "EM" (electronic mail), "ICS"
(Internet Chess Server), and "TC" (general telecommunication).

9.9.3 TAG: PLYCOUNT
-------------------

   This tag takes a single integer that gives the number of ply (moves) in
the game.

10. NUMERIC ANNOTATION GLYPHS
=============================

   NAG zero is used for a null annotation; it is provided for the
convenience of software designers as a placeholder value and should
probably not be used in external PGN data.

   NAGs with values from 1 to 9 annotate the move just played.

   NAGs with values from 10 to 135 modify the current position.

   NAGs with values from 136 to 139 describe time pressure.

   Other NAG values are reserved for future definition.

   Note: the number assignments listed below should be considered
preliminary in nature; they are likely to be changed as a result of
reviewer feedback.

  1. null annotation

  2. good move (traditional "!")

  3. poor move (traditional "?")

  4. very good move (traditional "!!")

  5. very poor move (traditional "??")

  6. speculative move (traditional "!?")

  7. questionable move (traditional "?!")

  8. forced move (all others lose quickly)

  9. singular move (no reasonable alternatives)

 10. worst move

 11. drawish position

 12. equal chances, quiet position

 13. equal chances, active position

 14. unclear position

 15. White has a slight advantage

 16. Black has a slight advantage

 17. White has a moderate advantage

 18. Black has a moderate advantage

 19. White has a decisive advantage

 20. Black has a decisive advantage

 21. White has a crushing advantage (Black should resign)

 22. Black has a crushing advantage (White should resign)

 23. White is in zugzwang

 24. Black is in zugzwang

 25. White has a slight space advantage

 26. Black has a slight space advantage

 27. White has a moderate space advantage

 28. Black has a moderate space advantage

 29. White has a decisive space advantage

 30. Black has a decisive space advantage

 31. White has a slight time (development) advantage

 32. Black has a slight time (development) advantage

 33. White has a moderate time (development) advantage

 34. Black has a moderate time (development) advantage

 35. White has a decisive time (development) advantage

 36. Black has a decisive time (development) advantage

 37. White has the initiative

 38. Black has the initiative

 39. White has a lasting initiative

 40. Black has a lasting initiative

 41. White has the attack

 42. Black has the attack

 43. White has insufficient compensation for material deficit

 44. Black has insufficient compensation for material deficit

 45. White has sufficient compensation for material deficit

 46. Black has sufficient compensation for material deficit

 47. White has more than adequate compensation for material deficit

 48. Black has more than adequate compensation for material deficit

 49. White has a slight center control advantage

 50. Black has a slight center control advantage

 51. White has a moderate center control advantage

 52. Black has a moderate center control advantage

 53. White has a decisive center control advantage

 54. Black has a decisive center control advantage

 55. White has a slight kingside control advantage

 56. Black has a slight kingside control advantage

 57. White has a moderate kingside control advantage

 58. Black has a moderate kingside control advantage

 59. White has a decisive kingside control advantage

 60. Black has a decisive kingside control advantage

 61. White has a slight queenside control advantage

 62. Black has a slight queenside control advantage

 63. White has a moderate queenside control advantage

 64. Black has a moderate queenside control advantage

 65. White has a decisive queenside control advantage

 66. Black has a decisive queenside control advantage

 67. White has a vulnerable first rank

 68. Black has a vulnerable first rank

 69. White has a well protected first rank

 70. Black has a well protected first rank

 71. White has a poorly protected king

 72. Black has a poorly protected king

 73. White has a well protected king

 74. Black has a well protected king

 75. White has a poorly placed king

 76. Black has a poorly placed king

 77. White has a well placed king

 78. Black has a well placed king

 79. White has a very weak pawn structure

 80. Black has a very weak pawn structure

 81. White has a moderately weak pawn structure

 82. Black has a moderately weak pawn structure

 83. White has a moderately strong pawn structure

 84. Black has a moderately strong pawn structure

 85. White has a very strong pawn structure

 86. Black has a very strong pawn structure

 87. White has poor knight placement

 88. Black has poor knight placement

 89. White has good knight placement

 90. Black has good knight placement

 91. White has poor bishop placement

 92. Black has poor bishop placement

 93. White has good bishop placement

 94. Black has good bishop placement

 95. White has poor rook placement

 96. Black has poor rook placement

 97. White has good rook placement

 98. Black has good rook placement

 99. White has poor queen placement

100. Black has poor queen placement

101. White has good queen placement

102. Black has good queen placement

103. White has poor piece coordination

104. Black has poor piece coordination

105. White has good piece coordination

106. Black has good piece coordination

107. White has played the opening very poorly

108. Black has played the opening very poorly

109. White has played the opening poorly

110. Black has played the opening poorly

111. White has played the opening well

112. Black has played the opening well

113. White has played the opening very well

114. Black has played the opening very well

115. White has played the middlegame very poorly

116. Black has played the middlegame very poorly

117. White has played the middlegame poorly

118. Black has played the middlegame poorly

119. White has played the middlegame well

120. Black has played the middlegame well

121. White has played the middlegame very well

122. Black has played the middlegame very well

123. White has played the ending very poorly

124. Black has played the ending very poorly

125. White has played the ending poorly

126. Black has played the ending poorly

127. White has played the ending well

128. Black has played the ending well

129. White has played the ending very well

130. Black has played the ending very well

131. White has slight counterplay

132. Black has slight counterplay

133. White has moderate counterplay

134. Black has moderate counterplay

135. White has decisive counterplay

136. Black has decisive counterplay

137. White has moderate time control pressure

138. Black has moderate time control pressure

139. White has severe time control pressure

140. Black has severe time control pressure

11. FILE NAMES AND DIRECTORIES
==============================

   File names chosen for PGN data should be both informative and portable.
The directory names and arrangements should also be chosen for the same
reasons and also for ease of navigation.

   Some of suggested file and directory names may be difficult or
impossible to represent on certain computing systems.  Use of appropriate
conversion customs is encouraged.

11.1 FILE NAME SUFFIX FOR PGN DATA
----------------------------------

   The use of the file suffix ".pgn" is encouraged for ASCII text files
containing PGN data.

11.2 FILE NAME FORMATION FOR PGN DATA FOR A SPECIFIC PLAYER
-----------------------------------------------------------

   PGN games for a specific player should have a file name consisting of
the player's last name followed by the ".pgn" suffix.

11.3 FILE NAME FORMATION FOR PGN DATA FOR A SPECIFIC EVENT
----------------------------------------------------------

   PGN games for a specific event should have a file name consisting of the
event's name followed by the ".pgn" suffix.

11.4 FILE NAME FORMATION FOR PGN DATA FOR CHRONOLOGICALLY ORDERED GAMES
-----------------------------------------------------------------------

   PGN data files used for chronologically ordered (oldest first) archives
use date information as file name root strings.  A file containing all the
PGN games for a given year would have an eight character name in the
format "YYYY.pgn".  A file containing PGN data for a given month would
have a ten character name in the format "YYYYMM.pgn".  Finally, a file for
PGN games for a single day would have a twelve character name in the
format "YYYYMMDD.pgn".  Large files are split into smaller files as needed.

   As game files are commonly arranged by chronological order, games with
missing or incomplete Date tag pair data are to be avoided.  Any question
mark characters in a Date tag value will be treated as zero digits for
collation within a file and also for file naming.

   Large quantities of PGN data arranged by chronological order should be
organized into hierarchical directories.  A directory containing all PGN
data for a given year would have a four character name in the format
"YYYY"; directories containing PGN files for a given month would have a
six character name in the format "YYYYMM".

11.5 SUGGESTED DIRECTORY TREE ORGANIZATION
------------------------------------------

   A suggested directory arrangement for ftp sites and CD-ROM
distributions:

PGN
     Master directory of the PGN subtree (pub/chess/Game-Databases/PGN)

PGN/Events
     Directory of PGN files, each for a specific event

PGN/Events/News
     News and status of the event collection

PGN/Events/ReadMe
     Brief description of the local directory contents

PGN/MGR
     Directory of the Master Games Repository subtree

PGN/MGR/News
     News and status of the entire PGN/MGR subtree

PGN/MGR/ReadMe
     Brief description of the local directory contents

PGN/MGR/YYYY
     Directory of games or subtrees for the year YYYY

PGN/MGR/YYYY/ReadMe
     Description of local directory for year YYYY

PGN/MGR/YYYY/News
     News and status for year YYYY data

PGN/News
     News and status of the entire PGN subtree

PGN/Players
     Directory of PGN files, each for a specific player

PGN/Players/News
     News and status of the player collection

PGN/Players/ReadMe
     Brief description of the local directory contents

PGN/ReadMe
     Brief description of the local directory contents

PGN/Standard
     The PGN standard (this document)

PGN/Tools
     Software utilities that access PGN data

12. PGN COLLATING SEQUENCE
==========================

   There is a standard sorting order for PGN games within a file.  This
collation is based on eight keys; these are the seven tag values of the
STR and also the movetext itself.

   The first (most important, primary key) is the Date tag.  Earlier dated
games appear prior to games played at a later date.  This field is sorted
by ascending numeric value first with the year, then the month, and
finally the day of the month.  Query characters used for unknown date
digit values will be treated as zero digit characters for ordering
comparison.

   The second key is the Event tag.  This is sorted in ascending ASCII
order.

   The third key is the Site tag.  This is sorted in ascending ASCII order.

   The fourth key is the Round tag.  This is sorted in ascending numeric
order based on the value of the integer used to denote the playing round.
A query or hyphen used for the round is ordered before any integer value.
A query character is ordered before a hyphen character.

   The fifth key is the White tag.  This is sorted in ascending ASCII
order.

   The sixth key is the Black tag.  This is sorted in ascending ASCII
order.

   The seventh key is the Result tag.  This is sorted in ascending ASCII
order.

   The eighth key is the movetext itself.  This is sorted in ascending
ASCII order with the entire text including spaces and newline characters.

15. INTERNATIONAL OLYMPIC COMMITTEE COUNTRY CODES
=================================================

   International Olympic Committee country codes are employed for Site
nation information because of their traditional use with the reporting of
international sporting events.  Due to changes in geography and linguistic
custom, some of the following may be incorrect or outdated.  Corrections
and extensions should be sent via e-mail to the PGN coordinator whose
address listed near the start of this document.

AFG
     Afghanistan

AIR
     Aboard aircraft

ALB
     Albania

ALG
     Algeria

AND
     Andorra

ANG
     Angola

ANT
     Antigua

ARG
     Argentina

ARM
     Armenia

ATA
     Antarctica

AUS
     Australia

AZB
     Azerbaijan

BAN
     Bangladesh

BAR
     Bahrain

BHM
     Bahamas

BEL
     Belgium

BER
     Bermuda

BIH
     Bosnia and Herzegovina

BLA
     Belarus

BLG
     Bulgaria

BLZ
     Belize

BOL
     Bolivia

BRB
     Barbados

BRS
     Brazil

BRU
     Brunei

BSW
     Botswana

CAN
     Canada

CHI
     Chile

COL
     Columbia

CRA
     Costa Rica

CRO
     Croatia

CSR
     Czechoslovakia

CUB
     Cuba

CYP
     Cyprus

DEN
     Denmark

DOM
     Dominican Republic

ECU
     Ecuador

EGY
     Egypt

ENG
     England

ESP
     Spain

EST
     Estonia

FAI
     Faroe Islands

FIJ
     Fiji

FIN
     Finland

FRA
     France

GAM
     Gambia

GCI
     Guernsey-Jersey

GEO
     Georgia

GER
     Germany

GHA
     Ghana

GRC
     Greece

GUA
     Guatemala

GUY
     Guyana

HAI
     Haiti

HKG
     Hong Kong

HON
     Honduras

HUN
     Hungary

IND
     India

IRL
     Ireland

IRN
     Iran

IRQ
     Iraq

ISD
     Iceland

ISR
     Israel

ITA
     Italy

IVO
     Ivory Coast

JAM
     Jamaica

JAP
     Japan

JRD
     Jordan

JUG
     Yugoslavia

KAZ
     Kazakhstan

KEN
     Kenya

KIR
     Kyrgyzstan

KUW
     Kuwait

LAT
     Latvia

LEB
     Lebanon

LIB
     Libya

LIC
     Liechtenstein

LTU
     Lithuania

LUX
     Luxembourg

MAL
     Malaysia

MAU
     Mauritania

MEX
     Mexico

MLI
     Mali

MLT
     Malta

MNC
     Monaco

MOL
     Moldova

MON
     Mongolia

MOZ
     Mozambique

MRC
     Morocco

MRT
     Mauritius

MYN
     Myanmar

NCG
     Nicaragua

NET
     The Internet

NIG
     Nigeria

NLA
     Netherlands Antilles

NLD
     Netherlands

NOR
     Norway

NZD
     New Zealand

OST
     Austria

PAK
     Pakistan

PAL
     Palestine

PAN
     Panama

PAR
     Paraguay

PER
     Peru

PHI
     Philippines

PNG
     Papua New Guinea

POL
     Poland

POR
     Portugal

PRC
     People's Republic of China

PRO
     Puerto Rico

QTR
     Qatar

RIN
     Indonesia

ROM
     Romania

RUS
     Russia

SAF
     South Africa

SAL
     El Salvador

SCO
     Scotland

SEA
     At Sea

SEN
     Senegal

SEY
     Seychelles

SIP
     Singapore

SLV
     Slovenia

SMA
     San Marino

SPC
     Aboard spacecraft

SRI
     Sri Lanka

SUD
     Sudan

SUR
     Surinam

SVE
     Sweden

SWZ
     Switzerland

SYR
     Syria

TAI
     Thailand

TMT
     Turkmenistan

TRK
     Turkey

TTO
     Trinidad and Tobago

TUN
     Tunisia

UAE
     United Arab Emirates

UGA
     Uganda

UKR
     Ukraine

UNK
     Unknown

URU
     Uruguay

USA
     United States of America

UZB
     Uzbekistan

VEN
     Venezuela

VGB
     British Virgin Islands

VIE
     Vietnam

VUS
     U.S. Virgin Islands

WLS
     Wales

YEM
     Yemen

YUG
     Yugoslavia

ZAM
     Zambia

ZIM
     Zimbabwe

ZRE
     Zaire

16. ADDITIONAL CHESS DATA STANDARDS
===================================

   While PGN is used for game storage, there are other data representation
standards for other chess related purposes.  Two important standards are
FEN and EPD, both described in this section.

16.1 FEN
--------

   FEN is "Forsyth-Edwards Notation"; it is a standard for describing chess
positions using the ASCII character set.

   A single FEN record uses one text line of variable length composed of
six data fields.  The first four fields of the FEN specification are the
same as the first four fields of the EPD specification.

   A text file composed exclusively of FEN data records should have a file
name with the suffix ".fen".

16.1.1 HISTORY
--------------

   FEN is based on a 19th century standard for position recording designed
by the Scotsman David Forsyth, a newspaper journalist.  The original
Forsyth standard has been slightly extended for use with chess software by
Steven Edwards with assistance from commentators on the Internet.  This
new standard, FEN, was first implemented in Edwards' SAN Kit.

16.1.2 USES FOR A POSITION NOTATION
-----------------------------------

   Having a standard position notation is particularly important for chess
programmers as it allows them to share position databases.  For example,
there exist standard position notation databases with many of the
classical benchmark tests for chessplaying programs, and by using a common
position notation format many hours of tedious data entry can be saved.
Additionally, a position notation can be useful for page layout programs
and for confirming position status for e-mail competition.

   Many interesting chess problem sets represented using FEN can be found
at the chess.uoknor.edu ftp site in the directory pub/chess/SAN_testsuites.

16.1.3 DATA FIELDS
------------------

   FEN specifies the piece placement, the active color, the castling
availability, the en passant target square, the halfmove clock, and the
fullmove number.  These can all fit on a single text line in an easily
read format.  The length of a FEN position description varies somewhat
according to the position. In some cases, the description could be eighty
or more characters in length and so may not fit conveniently on some
displays.  However, these positions aren't too common.

   A FEN description has six fields.  Each field is composed only of
non-blank printing ASCII characters.  Adjacent fields are separated by a
single ASCII space character.

16.1.3.1 PIECE PLACEMENT DATA
-----------------------------

   The first field represents the placement of the pieces on the board.
The board contents are specified starting with the eighth rank and ending
with the first rank.  For each rank, the squares are specified from file a
to file h.  White pieces are identified by uppercase SAN piece letters
("PNBRQK") and black pieces are identified by lowercase SAN piece letters
("pnbrqk").  Empty squares are represented by the digits one through
eight; the digit used represents the count of contiguous empty squares
along a rank.  A solidus character "/" is used to separate data of
adjacent ranks.

16.1.3.2 ACTIVE COLOR
---------------------

   The second field represents the active color.  A lower case "w" is used
if White is to move; a lower case "b" is used if Black is the active
player.

16.1.3.3 CASTLING AVAILABILITY
------------------------------

   The third field represents castling availability.  This indicates
potential future castling that may of may not be possible at the moment
due to blocking pieces or enemy attacks.  If there is no castling
availability for either side, the single character symbol "-" is used.
Otherwise, a combination of from one to four characters are present.  If
White has kingside castling availability, the uppercase letter "K"
appears.  If White has queenside castling availability, the uppercase
letter "Q" appears.  If Black has kingside castling availability, the
lowercase letter "k" appears.  If Black has queenside castling
availability, then the lowercase letter "q" appears.  Those letters which
appear will be ordered first uppercase before lowercase and second
kingside before queenside.  There is no white space between the letters.

16.1.3.4 EN PASSANT TARGET SQUARE
---------------------------------

   The fourth field is the en passant target square.  If there is no en
passant target square then the single character symbol "-" appears.  If
there is an en passant target square then is represented by a lowercase
file character immediately followed by a rank digit.  Obviously, the rank
digit will be "3" following a white pawn double advance (Black is the
active color) or else be the digit "6" after a black pawn double advance
(White being the active color).

   An en passant target square is given if and only if the last move was a
pawn advance of two squares.  Therefore, an en passant target square field
may have a square name even if there is no pawn of the opposing side that
may immediately execute the en passant capture.

16.1.3.5 HALFMOVE CLOCK
-----------------------

   The fifth field is a nonnegative integer representing the halfmove
clock.  This number is the count of halfmoves (or ply) since the last pawn
advance or capturing move.  This value is used for the fifty move draw
rule.

16.1.3.6 FULLMOVE NUMBER
------------------------

   The sixth and last field is a positive integer that gives the fullmove
number.  This will have the value "1" for the first move of a game for
both White and Black.  It is incremented by one immediately after each
move by Black.

16.1.4 EXAMPLES
---------------

   Here's the FEN for the starting position:

     rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1

   And after the move 1. e4:

     rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1

   And then after 1. ... c5:

     rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq c6 0 2

   And then after 2. Nf3:

     rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2

   For two kings on their home squares and a white pawn on e2 (White to
move) with thirty eight full moves played with five halfmoves since the
last pawn move or capture:

     4k3/8/8/8/8/8/4P3/4K3 w - - 5 39

16.2 EPD
--------

   EPD is "Extended Position Description"; it is a standard for describing
chess positions along with an extended set of structured attribute values
using the ASCII character set.  It is intended for data and command
interchange among chessplaying programs.  It is also intended for the
representation of portable opening library repositories.

   A single EPD uses one text line of variable length composed of four data
field followed by zero or more operations.  The four fields of the EPD
specification are the same as the first four fields of the FEN
specification.

   A text file composed exclusively of EPD data records should have a file
name with the suffix ".epd".

16.2.1 HISTORY
--------------

   EPD is based in part on the earlier FEN standard; it has added
extensions for use with opening library preparation and also for general
data and command interchange among advanced chess programs.  EPD was
developed by John Stanback and Steven Edwards; its first implementation is
in Stanback's master strength chessplaying program Zarkov.

16.2.2 USES FOR AN EXTENDED POSITION NOTATION
---------------------------------------------

   Like FEN, EPD can also be used for general position description.
However, unlike FEN, EPD is designed to be expandable by the addition of
new operations that provide new functionality as needs arise.

   Many interesting chess problem sets represented using EPD can be found
at the chess.uoknor.edu ftp site in the directory pub/chess/SAN_testsuites.

16.2.3 DATA FIELDS
------------------

   EPD specifies the piece placement, the active color, the castling
availability, and the en passant target square of a position.  These can
all fit on a single text line in an easily read format.  The length of an
EPD position description varies somewhat according to the position and any
associated operations. In some cases, the description could be eighty or
more characters in length and so may not fit conveniently on some
displays.  However, most EPD descriptions pass among programs only and
these are not usually seen by program users.

   (Note: due to the likelihood of future expansion of EPD, implementors
are encouraged to have their programs handle EPD text lines of up to 1024
characters long.)

   Each EPD data field is composed only of non-blank printing ASCII
characters.  Adjacent data fields are separated by a single ASCII space
character.

16.2.3.1 PIECE PLACEMENT DATA
-----------------------------

   The first field represents the placement of the pieces on the board.
The board contents are specified starting with the eighth rank and ending
with the first rank.  For each rank, the squares are specified from file a
to file h.  White pieces are identified by uppercase SAN piece letters
("PNBRQK") and black pieces are identified by lowercase SAN piece letters
("pnbrqk").  Empty squares are represented by the digits one through
eight; the digit used represents the count of contiguous empty squares
along a rank.  A solidus character "/" is used to separate data of
adjacent ranks.

16.2.3.2 ACTIVE COLOR
---------------------

   The second field represents the active color.  A lower case "w" is used
if White is to move; a lower case "b" is used if Black is the active
player.

16.2.3.3 CASTLING AVAILABILITY
------------------------------

   The third field represents castling availability.  This indicates
potential future castling that may or may not be possible at the moment
due to blocking pieces or enemy attacks.  If there is no castling
availability for either side, the single character symbol "-" is used.
Otherwise, a combination of from one to four characters are present.  If
White has kingside castling availability, the uppercase letter "K"
appears.  If White has queenside castling availability, the uppercase
letter "Q" appears.  If Black has kingside castling availability, the
lowercase letter "k" appears.  If Black has queenside castling
availability, then the lowercase letter "q" appears.  Those letters which
appear will be ordered first uppercase before lowercase and second
kingside before queenside.  There is no white space between the letters.

16.2.3.4 EN PASSANT TARGET SQUARE
---------------------------------

   The fourth field is the en passant target square.  If there is no en
passant target square then the single character symbol "-" appears.  If
there is an en passant target square then is represented by a lowercase
file character immediately followed by a rank digit.  Obviously, the rank
digit will be "3" following a white pawn double advance (Black is the
active color) or else be the digit "6" after a black pawn double advance
(White being the active color).

   An en passant target square is given if and only if the last move was a
pawn advance of two squares.  Therefore, an en passant target square field
may have a square name even if there is no pawn of the opposing side that
may immediately execute the en passant capture.

16.2.4 OPERATIONS
-----------------

   An EPD operation is composed of an opcode followed by zero or more
operands and is concluded by a semicolon.

   Multiple operations are separated by a single space character.  If there
is at least one operation present in an EPD line, it is separated from the
last (fourth) data field by a single space character.

16.2.4.1 GENERAL FORMAT
-----------------------

   An opcode is an identifier that starts with a letter character and may
be followed by up to fourteen more characters.  Each additional character
may be a letter or a digit or the underscore character.

   An operand is either a set of contiguous non-white space printing
characters or a string.  A string is a set of contiguous printing
characters delimited by a quote character at each end.  A string value
must have less than 256 bytes of data.

   If at least one operand is present in an operation, there is a single
space between the opcode and the first operand.  If more than one operand
is present in an operation, there is a single blank character between
every two adjacent operands.  If there are no operands, a semicolon
character is appended to the opcode to mark the end of the operation.  If
any operands appear, the last operand has an appended semicolon that marks
the end of the operation.

   Any given opcode appears at most once per EPD record.  Multiple
operations in a single EPD record should appear in ASCII order of their
opcode names (mnemonics).  However, a program reading EPD records may
allow for operations not in ASCII order by opcode mnemonics; the semantics
are the same in either case.

   Some opcodes that allow for more than one operand may have special
ordering requirements for the operands.  For example, the "pv" (predicted
variation) opcode requires its operands (moves) to appear in the order in
which they would be played.  All other opcodes that allow for more than
one operand should have operands appearing in ASCII order.  An example of
the latter set is the "bm" (best move[s]) opcode; its operands are moves
that are all immediately playable from the current position.

   Some opcodes require one or more operands that are chess moves.  These
moves should be represented using SAN.  If a different representation is
used, there is no guarantee that the EPD will be read correctly during
subsequent processing.

   Some opcodes require one or more operands that are integers.  Some
opcodes may require that an integer operand must be within a given range;
the details are described in the opcode list given below.  A negative
integer is formed with a hyphen (minus sign) preceding the integer digit
sequence.  An optional plus sign may be used for indicating a non-negative
value, but such use is not required and is indeed discouraged.

   Some opcodes require one or more operands that are floating point
numbers.  Some opcodes may require that a floating point operand must be
within a given range; the details are described in the opcode list given
below.  A floating point operand is constructed from an optional sign
character ("+" or "-"), a digit sequence (with at least one digit), a
radix point (always "."), and a final digit sequence (with at least one
digit).

16.2.4.2 OPCODE MNEMONICS
-------------------------

   An opcode mnemonic used for archival storage and for interprogram
communication starts with a lower case letter and is composed of only
lower case letters, digits, and the underscore character (i.e., no upper
case letters).  These mnemonics will also all be at least two characters
in length.

   Opcode mnemonics used only by a single program or an experimental suite
of programs should start with an upper case letter.  This is so they may
be easily distinguished should they be inadvertently be encountered by
other programs.  When a such a "private" opcode be demonstrated to be
widely useful, it should be brought into the official list (appearing
below) in a lower case form.

   If a given program does not recognize a particular opcode, that
operation is simply ignored; it is not signaled as an error.

16.2.5 OPCODE LIST
------------------

   The opcodes are listed here in ASCII order of their mnemonics.
Suggestions for new opcodes should be sent to the PGN standard coordinator
listed near the start of this document.

16.2.5.1 OPCODE acn: ANALYSIS COUNT: NODES
------------------------------------------

   The opcode "acn" takes a single non-negative integer operand.  It is
used to represent the number of nodes examined in an analysis.  Note that
the value may be quite large for some extended searches and so use of (at
least) a long (four byte) representation is suggested.

16.2.5.2 OPCODE acs: ANALYSIS COUNT: SECONDS
--------------------------------------------

   The opcode "acs" takes a single non-negative integer operand.  It is
used to represent the number of seconds used for an analysis.  Note that
the value may be quite large for some extended searches and so use of (at
least) a long (four byte) representation is suggested.

16.2.5.3 OPCODE am: AVOID MOVES
-------------------------------

   The opcode "am" indicates a set of zero or more moves, all immediately
playable from the current position, that are to be avoided in the opinion
of the EPD writer.  Each operand is a SAN move; they appear in ASCII order.

16.2.5.4 OPCODE bm: BEST MOVES
------------------------------

   The opcode "bm" indicates a set of zero or more moves, all immediately
playable from the current position, that are judged to the best available
by the EPD writer.  Each operand is a SAN move; they appear in ASCII order.

16.2.5.5 OPCODE c0: COMMENT (PRIMARY, ALSO "c1" THOUGH "c9")
------------------------------------------------------------

   The opcode "c0" (lower case letter "c", digit character zero) indicates
a top level comment that applies to the given position.  It is the first
of ten ranked comments, each of which has a mnemonic formed from the lower
case letter "c" followed by a single decimal digit.  Each of these opcodes
takes either a single string operand or no operand at all.

   This ten member comment family of opcodes is intended for use as
descriptive commentary for a complete game or game fragment.  The usual
processing of these opcodes are as follows:

  1. At the beginning of a game (or game fragment), a move sequence
     scanning program initializes each element of its set of ten comment
     string registers to be null.

  2. As the EPD record for each position in the game is processed, the
     comment operations are interpreted from left to right.  (Actually, all
     operations in n EPD record are interpreted from left to right.)
     Because operations appear in ASCII order according to their opcode
     mnemonics, opcode "c0" (if present) will be handled prior to all
     other opcodes, then opcode "c1" (if present), and so forth until
     opcode "c9" (if present).

  3. The processing of opcode "cN" (0 <= N <= 9) involves two steps.
     First, all comment string registers with an index equal to or greater
     than N are set to null.  (This is the set "cN" though "c9".)  Second,
     and only if a string operand is present, the value of the
     corresponding comment string register is set equal to the string
     operand.

16.2.5.6 OPCODE ce: CENTIPAWN EVALUATION
----------------------------------------

   The opcode "ce" indicates the evaluation of the indicated position in
centipawn units.  It takes a single operand, an optionally signed integer
that gives an evaluation of the position from the viewpoint of the active
player; i.e., the player with the move.  Positive values indicate a
position favorable to the moving player while negative values indicate a
position favorable to the passive player; i.e., the player without the
move.  A centipawn evaluation value close to zero indicates a neutral
positional evaluation.

   Values are restricted to integers that are equal to or greater than
-32767 and are less than or equal to 32766.

   A value greater than 32000 indicates the availability of a forced mate
to the active player.  The number of plies until mate is given by
subtracting the evaluation from the value 32767.  Thus, a winning mate in
N fullmoves is a mate in ((2 * N) - 1) halfmoves (or ply) and has a
corresponding centipawn evaluation of (32767 - ((2 * N) - 1)).  For
example, a mate on the move (mate in one) has a centipawn evaluation of
32766 while a mate in five has a centipawn evaluation of 32758.

   A value less than -32000 indicates the availability of a forced mate to
the passive player.  The number of plies until mate is given by
subtracting the evaluation from the value -32767 and then negating the
result.  Thus, a losing mate in N fullmoves is a mate in (2 * N) halfmoves
(or ply) and has a corresponding centipawn evaluation of (-32767 + (2 *
N)).  For example, a mate after the move (losing mate in one) has a
centipawn evaluation of -32765 while a losing mate in five has a centipawn
evaluation of -32757.

   A value of -32767 indicates an illegal position.  A stalemate position
has a centipawn evaluation of zero as does a position drawn due to
insufficient mating material.  Any other position known to be a certain
forced draw also has a centipawn evaluation of zero.

16.2.5.7 OPCODE dm: DIRECT MATE FULLMOVE COUNT
----------------------------------------------

   The "dm" opcode is used to indicate the number of fullmoves until
checkmate is to be delivered by the active color for the indicated
position.  It always takes a single operand which is a positive integer
giving the fullmove count.  For example, a position known to be a "mate in
three" would have an operation of "dm 3;" to indicate this.

   This opcode is intended for use with problem sets composed of positions
requiring direct mate answers as solutions.

16.2.5.8 OPCODE draw_accept: ACCEPT A DRAW OFFER
------------------------------------------------

   The opcode "draw_accept" is used to indicate that a draw offer made
after the move that lead to the indicated position is accepted by the
active player.  This opcode takes no operands.

16.2.5.9 OPCODE draw_claim: CLAIM A DRAW
----------------------------------------

   The opcode "draw_claim" is used to indicate claim by the active player
that a draw exists.  The draw is claimed because of a third time
repetition or because of the fifty move rule or because of insufficient
mating material.  A supplied move (see the opcode "sm") is also required
to appear as part of the same EPD record.  The draw_claim opcode takes no
operands.

16.2.5.10 OPCODE draw_offer: OFFER A DRAW
-----------------------------------------

   The opcode "draw_offer" is used to indicate that a draw is offered by
the active player.  A supplied move (see the opcode "sm") is also required
to appear as part of the same EPD record; this move is considered played
from the indicated position.  The draw_offer opcode takes no operands.

16.2.5.11 OPCODE draw_reject: REJECT A DRAW OFFER
-------------------------------------------------

   The opcode "draw_reject" is used to indicate that a draw offer made
after the move that lead to the indicated position is rejected by the
active player.  This opcode takes no operands.

16.2.5.12 OPCODE eco: ENCYCLOPEDIA OF CHESS OPENINGS OPENING CODE
-----------------------------------------------------------------

   The opcode "eco" is used to associate an opening designation from the
Encyclopedia of Chess Openings taxonomy with the indicated position.  The
opcode takes either a single string operand (the ECO opening name) or no
operand at all.  If an operand is present, its value is associated with an
"ECO" string register of the scanning program.  If there is no operand,
the ECO string register of the scanning program is set to null.

   The usage is similar to that of the "ECO" tag pair of the PGN standard.

16.2.5.13 OPCODE fmvn: FULLMOVE NUMBER
--------------------------------------

   The opcode "fmvn" represents the fullmove n umber associated with the
position.  It always takes a single operand that is the positive integer
value of the move number.

   This opcode is used to explicitly represent the fullmove number in EPD
that is present by default in FEN as the sixth field.  Fullmove number
information is usually omitted from EPD because it does not affect move
generation (commonly needed for EPD-using tasks) but it does affect game
notation (commonly needed for FEN-using tasks).  Because of the desire for
space optimization for large EPD files, fullmove numbers were dropped from
EPD's parent FEN.  The halfmove clock information was similarly dropped.

16.2.5.14 OPCODE hmvc: HALFMOVE CLOCK
-------------------------------------

   The opcode "hmvc" represents the halfmove clock associated with the
position.  The halfmove clock of a position is equal to the number of
plies since the last pawn move or capture.  This information is used to
implement the fifty move draw rule.  It always takes a single operand that
is the non-negative integer value of the halfmove clock.

   This opcode is used to explicitly represent the halfmove clock in EPD
that is present by default in FEN as the fifth field.  Halfmove clock
information is usually omitted from EPD because it does not affect move
generation (commonly needed for EPD-using tasks) but it does affect game
termination issues (commonly needed for FEN-using tasks).  Because of the
desire for space optimization for large EPD files, halfmove clock values
were dropped from EPD's parent FEN.  The fullmove number information was
similarly dropped.

16.2.5.15 OPCODE id: POSITION IDENTIFICATION
--------------------------------------------

   The opcode "id" is used to provide a simple identifying label for the
indicated position.  It takes a single string operand.

   This opcode is intended for use with test suites used for measuring
chessplaying program strength.  An example "id" operand for the seven
hundred fifty seventh position of the one thousand one problems in
Reinfeld's 1001 Winning Chess Sacrifices and Combinations would be
"WCSAC.0757" while the fifteenth position in the twenty four problem
Bratko-Kopec test suite would have an "id" operand of "BK.15".

16.2.5.16 OPCODE nic: NEW IN CHESS OPENING CODE
-----------------------------------------------

   The opcode "nic" is used to associate an opening designation from the
New In Chess taxonomy with the indicated position.  The opcode takes
either a single string operand (the NIC opening name) or no operand at
all.  If an operand is present, its value is associated with an "NIC"
string register of the scanning program.  If there is no operand, the NIC
string register of the scanning program is set to null.

   The usage is similar to that of the "NIC" tag pair of the PGN standard.

16.2.5.17 OPCODE noop: NO OPERATION
-----------------------------------

   The "noop" opcode is used to indicate no operation.  It takes zero or
more operands, each of which may be of any type.  The operation involves
no processing.  It is intended for use by developers for program testing
purposes.

16.2.5.18 OPCODE pm: PREDICTED MOVE
-----------------------------------

   The "pm" opcode is used to provide a single predicted move for the
indicated position.  It has exactly one operand, a move playable from the
position.  This move is judged by the EPD writer to represent the best
move available to the active player.

   If a non-empty "pv" (predicted variation) line of play is also present
in the same EPD record, the first move of the predicted variation is the
same as the predicted move.

   The "pm" opcode is intended for use as a general "display hint"
mechanism.

16.2.5.19 OPCODE pv: PREDICTED VARIATION
----------------------------------------

   The "pv" opcode is used to provide a predicted variation for the
indicated position.  It has zero or more operands which represent a
sequence of moves playable from the position.  This sequence is judged by
the EPD writer to represent the best play available.

   If a "pm" (predicted move) operation is also present in the same EPD
record, the predicted move is the same as the first move of the predicted
variation.

16.2.5.20 OPCODE rc: REPETITION COUNT
-------------------------------------

   The "rc" opcode is used to indicate the number of occurrences of the
indicated position.  It takes a single, positive integer operand.  Any
position, including the initial starting position, is considered to have
an "rc" value of at least one.  A value of three indicates a candidate for
a draw claim by the position repetition rule.

16.2.5.21 OPCODE resign: GAME RESIGNATION
-----------------------------------------

   The opcode "resign" is used to indicate that the active player has
resigned the game.  This opcode takes no operands.

16.2.5.22 OPCODE sm: SUPPLIED MOVE
----------------------------------

   The "sm" opcode is used to provide a single supplied move for the
indicated position.  It has exactly one operand, a move playable from the
position.  This move is the move to be played from the position.

   The "sm" opcode is intended for use to communicate the most recent
played move in an active game.  It is used to communicate moves between
programs in automatic play via a network.  This includes correspondence
play using e-mail and also programs acting as network front ends to human
players.

16.2.5.23 OPCODE tcgs: TELECOMMUNICATION: GAME SELECTOR
-------------------------------------------------------

   The "tcgs" opcode is one of the telecommunication family of opcodes used
for games conducted via e-mail and similar means.  This opcode takes a
single operand that is a positive integer.  It is used to select among
various games in progress between the same sender and receiver.

16.2.5.24 OPCODE tcri: TELECOMMUNICATION: RECEIVER IDENTIFICATION
-----------------------------------------------------------------

   The "tcri" opcode is one of the telecommunication family of opcodes used
for games conducted via e-mail and similar means.  This opcode takes two
order dependent string operands.  The first operand is the e-mail address
of the receiver of the EPD record.  The second operand is the name of the
player (program or human) at the address who is the actual receiver of the
EPD record.

16.2.5.25 OPCODE tcsi: TELECOMMUNICATION: SENDER IDENTIFICATION
---------------------------------------------------------------

   The "tcsi" opcode is one of the telecommunication family of opcodes used
for games conducted via e-mail and similar means.  This opcode takes two
order dependent string operands.  The first operand is the e-mail address
of the sender of the EPD record.  The second operand is the name of the
player (program or human) at the address who is the actual sender of the
EPD record.

16.2.5.26 OPCODE v0: VARIATION NAME (PRIMARY, ALSO "V1" THOUGH "V9")
--------------------------------------------------------------------

   The opcode "v0" (lower case letter "v", digit character zero) indicates
a top level variation name that applies to the given position.  It is the
first of ten ranked variation names, each of which has a mnemonic formed
from the lower case letter "v" followed by a single decimal digit.  Each
of these opcodes takes either a single string operand or no operand at all.

   This ten member variation name family of opcodes is intended for use as
traditional variation names for a complete game or game fragment.  The
usual processing of these opcodes are as follows:

  1. At the beginning of a game (or game fragment), a move sequence
     scanning program initializes each element of its set of ten variation
     name string registers to be null.

  2. As the EPD record for each position in the game is processed, the
     variation name operations are interpreted from left to right.
     (Actually, all operations in n EPD record are interpreted from left to
     right.)  Because operations appear in ASCII order according to their
     opcode mnemonics, opcode "v0" (if present) will be handled prior to
     all other opcodes, then opcode "v1" (if present), and so forth until
     opcode "v9" (if present).

  3. The processing of opcode "vN" (0 <= N <= 9) involves two steps.
     First, all variation name string registers with an index equal to or
     greater than N are set to null.  (This is the set "vN" though "v9".)
     Second, and only if a string operand is present, the value of the
     corresponding variation name string register is set equal to the
     string operand.

17. ALTERNATIVE CHESSPIECE IDENTIFIER LETTERS
=============================================

   English language piece names are used to define the letter set for
identifying chesspieces in PGN movetext.  However, authors of programs
which are used only for local presentation or scanning of chess move data
may find it convenient to use piece letter codes common in their locales.
This is not a problem as long as PGN data that resides in archival storage
or that is exchanged among programs still uses the SAN (English) piece
letter codes: "PNBRQK".

   For the above authors only, a list of alternative piece letter codes are
provided; the piece codes are given in the order pawn, knight, bishop,
rook, queen, and king.

Czech
     P J S V D K

Danish
     B S L T D K

Dutch
     O P L T D K

English
     P N B R Q K

Estonian
     P R O V L K

Finnish
     P R L T D K

French
     P C F T D R

German
     B S L T D K

Hungarian
     G H F B V K

Icelandic
     P R B H D K

Italian
     P C A T D R

Norwegian
     B S L T D K

Polish
     P S G W H K

Portuguese
     P C B T D R

Romanian
     P C N T D R

Spanish
     P C A T D R

Swedish
     B S L T D K

18. FORMAL SYNTAX
=================

     <PGN-database> ::= <PGN-game> <PGN-database>
     		       <empty>

     <PGN-game> ::= <tag-section> <movetext-section>

     <tag-section> ::= <tag-pair> <tag-section>
     		      <empty>

     <tag-pair> ::= [ <tag-name> <tag-value> ]

     <tag-name> ::= <identifier>

     <tag-value> ::= <string>

     <movetext-section> ::= <element-sequence> <game-termination>

     <element-sequence> ::= <element> <element-sequence>
     			   <recursive-variation> <element-sequence>
     			   <empty>

     <element> ::= <move-number-indication>
     		  <SAN-move>
     		  <numeric-annotation-glyph>

     <recursive-variation> ::= ( <element-sequence> )

     <game-termination> ::= 1-0
     			   0-1
     			   1/2-1/2
     			   *
     <empty> ::=

19. CANONICAL CHESS POSITION HASH CODING
========================================

   *** This section is under development.

20. BINARY REPRESENTATION (PGC)
===============================

   *** This section is under development.

   The binary coded version of PGN is PGC (PGN Game Coding).  PGC is a
binary representation standard of PGN data designed for the dual goals of
storage efficiency and program I/O.  A file containing PGC data should
have a name with a suffix of ".pgc".

   Unlike PGN text files that may have locale dependent representations for
newlines, PGC files have data that does not vary due to local processing
environment.  This means that PGC files may be transferred among systems
using general binary file methods.

   PGC files should be used only when the use of PGN is impractical due to
time and space resource constraints.  As the general level of processing
capabilities increases, the need for PGC over PGN will decrease.
Therefore, implementors are encouraged not to use PGC as the default
representation because it is much more difficult (than PGN) to understand
without proper software.

   PGC data is composed of a sequence of PGC records.  Each record is
composed of a sequence of one or more bytes.  The first byte is the PGN
record marker and it specifies the interpretation of the remaining portion
of the record.  This remaining portion is composed of zero or more PGN
record items.  Item types include move sequences, move sets, and character
strings.

20.1 BYTES, WORDS, AND DOUBLEWORDS
----------------------------------

   At the lowest level, PGC binary data is organized as bytes, words (two
contiguous bytes), and doublewords (four contiguous bytes).  All eight
bits of a byte are used.  Longwords (eight contiguous bytes) are not used.
Integer values are stored using two's complement representation.
Integers may be signed or unsigned depending on context.  Multibyte
integers are stored in low-endian format with the least significant byte
appearing first.

   A one byte integer item is called "int-1".  A two byte integer item is
called "int-2".  A four byte integer item is called "int-4".

   Characters are stored as bytes using the ISO 8859/1 Latin-1 (ECMA-94)
code set.  There is no provision for other characters sets or
representations.

20.2 MOVE ORDINALS
------------------

   A chess move is represented using a move ordinal.  This is a single
unsigned byte quantity with values from zero to 255.  A move ordinal is
interpreted as an index into the list of legal moves from the current
position.  This list is constructed by generating the legal moves from the
current position, assigning SAN ASCII strings to each move, and then
sorting these strings in ascending order.  Note that a seven bit ordinal,
as used by some inferior representation systems, is insufficient as there
are some positions that have more than 128 moves available.

   Examples: From the initial position, there are twenty moves.  Move
ordinal 0 corresponds to the SAN move string "Na3"; move ordinal 1
corresponds to "Nc3", move ordinal 4 corresponds to "a3", and move ordinal
19 corresponds to "h4".

   Moves can be organized into sequences and sets.  A move sequence is an
ordered list of moves that are played, one after another from first to
last.  A move set is a list of moves that are all playable from the
current position.

   Move sequence data is represented using a length header followed by move
ordinal data.  The length header is an unsigned integer that may be a byte
or a word.  The integer gives the number, possibly zero, of following move
ordinal bytes.  Most move sequences can be represented using just a byte
header; these are called "mvseq-1" items.  Move sequence data using a word
header are called "mvseq-2" items.

   Move set data is represented using a length header followed by move
ordinal data.  The length header is an unsigned integer that is a byte.
The integer gives the number, possibly zero, of following move ordinal
bytes.  All move sets are be represented using just a byte header; these
are called "mvset-1" items.  (Note the implied restriction that a move set
can only have a maximum of 255 of the possible 256 ordinals present at one
time.)

20.3 STRING DATA
----------------

   PGC string data is represented using a length header followed by bytes
of character data.  The length header is an unsigned integer that may be a
byte, a word, or a doubleword.  The integer gives the number, possibly
zero, of following character bytes.  Most strings can be represented using
just a byte header; these are called "string-1" items.  String data using
a word header are called "string-2" items and string data using a
doubleword header are called "string-4" items.  No special ASCII NUL
termination byte is required for PGC storage of a string as the length is
explicitly given in the item header.

20.4 MARKER CODES
-----------------

   PGC marker codes are given in hexadecimal format.  PGC marker code zero
(marker 0x00) is the "noop" marker and carries no meaning.  Each
additional marker code defined appears in its own subsection below.

20.4.1 MARKER 0x01: REDUCED EXPORT FORMAT SINGLE GAME
-----------------------------------------------------

   Marker 0x01 is used to indicate a single complete game in reduced export
format.  This refers to a game that has only the Seven Tag Roster data,
played moves, and no annotations or comments.  This record type is used as
an alternative to the general game data begin/end record pairs described
below.  The general marker pair (0x05/0x06) is used to help represent game
data that can't be adequately represented in reduced export format.  There
are eight items that follow marker 0x01 to form the "reduced export format
single game" record.  In order, these are:

  1. string-1 (Event tag value)

  2. string-1 (Site tag value)

  3. string-1 (Date tag value)

  4. string-1 (Round tag value)

  5. string-1 (White tag value)

  6. string-1 (Black tag value)

  7. string-1 (Result tag value)

  8. mvseq-2 (played moves)

20.4.2 MARKER 0x02: TAG PAIR
----------------------------

   Marker 0x02 is used to indicate a single tag pair.  There are two items
that follow marker 0x02 to form the "tag pair" record; in order these are:

  1. string-1 (tag pair name)

  2. string-1 (tag pair value)

20.4.3 MARKER 0x03: SHORT MOVE SEQUENCE
---------------------------------------

   Marker 0x03 is used to indicate a short move sequence.  There is one
item that follows marker 0x03 to form the "short move sequence" record;
this is:

  1. mvseq-1 (played moves)

20.4.4 MARKER 0x04: LONG MOVE SEQUENCE
--------------------------------------

   Marker 0x04 is used to indicate a long move sequence.  There is one item
that follows marker 0x04 to form the "long move sequence" record; this is:

  1. mvseq-2 (played moves)

20.4.5 MARKER 0x05: GENERAL GAME DATA BEGIN
-------------------------------------------

   Marker 0x05 is used to indicate the beginning of data for a game.  It
has no associated items; it is a complete record by itself.  Instead, it
marks the beginning of PGC records used to describe a game.  All records
up to the corresponding "general game data end" record are considered to
be part of the same game.  (PGC record type 0x01, "reduced export format
single game", is not permitted to appear within a general game begin/end
record pair.  The general game construct is to be used as an alternative
to record type 0x01 in those cases where the latter is too restrictive to
contain the data for a game.)

20.4.6 MARKER 0x06: GENERAL GAME DATA END
-----------------------------------------

   Marker 0x06 is used to indicate the end of data for a game.  It has no
associated items; it is a complete record by itself.  Instead, it marks
the end of PGC records used to describe a game.  All records after the
corresponding (and earlier appearing) "general game data begin" record are
considered to be part of the same game.

20.4.7 MARKER 0x07: SIMPLE-NAG
------------------------------

   Marker 0x07 is used to indicate the presence of a simple NAG (Numeric
Annotation Glyph).  This is an annotation marker that has only a short
type identification and no operands.  There is one item that follows
marker 0x07 to form the "simple-nag" record; this is:

  1. int-1 (unsigned NAG value, from 0 to 255)

20.4.8 MARKER 0x08: RAV-BEGIN
-----------------------------

   Marker 0x08 is used to indicate the beginning of an RAV (Recursive
Annotation Variation).  It has no associated items; it is a complete
record by itself.  Instead, it marks the beginning of PGC records used to
describe a recursive annotation.  It is considered an opening bracket for
a later rav-end record; the recursive annotation is completely described
between the bracket pair.  The rav-begin/data/rav-end structures can be
nested.

20.4.9 MARKER 0x09: RAV-END
---------------------------

   Marker 0x09 is used to indicate the end of an RAV (Recursive Annotation
Variation).  It has no associated items; it is a complete record by
itself.  Instead, it marks the end of PGC records used to describe a
recursive annotation.  It is considered a closing bracket for an earlier
rav-begin record; the recursive annotation is completely described between
the bracket pair.  The rav-begin/data/rav-end structures can be nested.

20.4.10 MARKER 0x0A: ESCAPE-STRING
----------------------------------

   Marker 0x0a is used to indicate the presence of an escape string.  This
is a string represented by the use of the percent sign ("%") escape
mechanism in PGN.  The data that is escaped is the sequence of characters
immediately follwoing the percent sign up to but not including the
terminating newline.  As is the case with the PGN percent sign escape, the
use of a PGC escape-string record is limited to use for non-archival data.
There is one item that follows marker 0x0a to form the "escape-string"
record; this is the string data being escaped:

  1. string-2 (escaped string data)

SEE ALSO
========

   New in Chess

   Encyclopedia of Chess Openings

   Reinfeld's 1001 Winning Chess Sacrifices and Combinations

work with chess positions and games, according to the rules of chess.
*********************************************************************

NAME
====

   Games::Chess::Referee - work with chess positions and games, according
to the rules of chess.

SYNOPSIS
========

     use Games::Chess:Referee;
     new_game();
     ply('e2e4');
     ply('e7e5');
     show_board();
     move('d2d3', 'd7d6');
     show_board();

DESCRIPTION
===========

   The `Games::Chess:Referee' module provides a mechanism to interpret
(almost) standard algebraic chess notation and to print out the resulting
positions. It makes use of the Games::Chess::Position and
Games::Chess::Piece classes by Gareth Rees, adding the chess rules and
move application functionality.

ERROR HANDLING
==============

   Where the code does complain, it uses the carp routine. The ply() and
move() routines return zero on failure, one on success.

LIMITATIONS
===========

   In this very early version, many of the rules of chess are not yet
implemented. The code is in a state of flux right now, as it is being
reworked into a class from a simple afternoon proof of concept. See the
README file and comments in the code for more information.

BUGS
====

   There are no known bugs as of this writing, but it would be reasonable
to consider the limitations as bugs.

SEE ALSO
========

   See Games/Chess,

AUTHOR
======

   Gregor N. Purdy (`gregor@focusresearch.com')

COPYRIGHT AND LICENSE
=====================

   Copyright (C) 1999 Gregor N. Purdy. All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

a Dissociated Press algorithm and filter
****************************************

NAME
====

   Games::Dissociate - a Dissociated Press algorithm and filter

SYNOPSIS
========

     use Games::Dissociate;
     ...
     $brilliant_prose = dissociate($normal_prose);

   or

     perl -MGames::Dissociate -e dissociate_filter meno.txt

ABSTRACT
========

   This module provides the function `dissociate', which implements a
Dissociated Press algorithm, well known to Emacs users as "meta-x
dissociate".  The algorithm here is by no means a straight port of Emacs's
`dissociate.el', but is instead merely inspired by it.

   (I actually intended to make it a straight port, but couldn't manage it
- the code in `dissociate.el' is totally uncommented, and is *especially*
obscure Lisp.)

   This module also provides a procedure `dissociate_filter', for use in
the one-liner context:

     perl -MGames::Dissociate -e 'dissociate_filter(2)'
       < thesis.txt  > snip.txt

   or

     perl -MGames::Dissociate -e 'dissociate_filter(-2)'
       < thesis.txt  > snip.txt

   or in a script consisting of

     #!/usr/local/bin/perl
     use Games::Dissociate;  dissociate_filter;

Sample Dissociation
-------------------

   I got this text from feeding the UNIX man page for "regexp" (in
plaintext) to `dissociate' with a $group_size parameter of 3:

   nd of then the full list of the more branch is zero or "*", "."
(matching thand regexp(n) right initional argumented by a pieces of the
left to match that (ab|a) general other worDS match to the first, followed
by "?". It matcheS In of the next start was been could exp. The characters
in expreSSIons belowed in the full matching the in starticular EXpression
in "[0-9]" include a list of sequence of the are may before the regexp
even therwise. REgexp(n) Tcl regular expression to regexp(n) regexp(n)
right. Input string), "\",

About Dissociated Press algorithms
----------------------------------

   "Dissociated Press" algorithms produce text with token-patterns
(patterns of words, or patterns of characters) similar those found to an
input text.

   This may be implemented in terms of Markov chains (basically,
statistical modeling of frequency of token-groups), altho both this module
and Emacs's `dissociate.el' take shortcuts to avoid having to construct
and manipulate a real statistical model of the input text.

   Basically, the way Dissociated Press algorithms (at least mine - I
can't speak for the exact details of all others) work is:

   1. Start at a random point in the text, and read a group of tokens
(characters or words from there - where group size is a parameter you
change) from there.  Call this the last-matched group.

   2. Output the last-matched group.

   3. Look for the other times the last-matched group occurs in the text,
and randomly select one of them.  (Or: select the next time that group
occurs - a shortcut I've made in the code, which seems to still produce
random-looking results).  Look at the group of tokens that occurs right
after that.  Make *that* the last-matched group.  Loop back to Step 2
until we think we've outputted enough.

   4. But if the last-matched group from 2 occurred just that once in the
text, go back to step 1.

   Since the groups of characters or words (at least, when you look at
them as bits of text only group-size tokens long) are all taken from the
input text, you get somewhat natural-looking text - as opposed to what
you'd get if you just randomly outputted single characters or single words
from the input text.

   The process of applying a DissociatedPress algorithm to a bit of text
is called "dissociation".

PARAMETERS AND USAGE
====================

   To use this module after you've installed it, say "use
Games::Dissociate".  This imports the function `dissociate' and the
procedure `dissociate_filter'.  The function `dissociate' takes three
parameters:

     $output = dissociate($input, $group_size, $max);

   $input is the input string, hopefully containing a stretch of
(plaintext) text in a human language, encoded either in just plain
US-ASCII, or in a character-encoding your locale settings know about.
$output will be "dissociated text" (charmingly generated gibberish) based
on that input text.  (Note that output will contain no line-breaks or
tabs.  Yoy may wish, as `dissociate_filter' does, to pass the output thru
Text::Wrap's wrap.)

   You'll get strange output if $input contains markup (HTML, LaTeX,
etc.), or is very short, or is not in a human language.

   $group_size is the number of tokens (words or characters) that must be
in common between bits of text the dissociation algorithm skips between.
A positive value means you want to dissociate by character, with a
group-size of that many characters (4 = 4 characters); a negative value
means you want to dissociate by word, with a group size of that many words
(-2 = 2 words).  I suggest values between -3 and 5; I'm a fan of -2.  A
$group_size value of 0 or 1 is invalid, and currently causes `dissociate'
to use the default value of 2 (2 characters) instead.  A value of -1 is
invalid, and currently causes `dissociate' to use the value of -2 (2
words) instead.  The behavior/validity of $group_size values of 0, 1, or
-1 may change in future versions.

   $max is a parameter used to control the maximum number of iterations of
`dissociate''s central loop - it corresponds roughly to the number of
"chunks" of text you get back, where a chunk is N * -$group_size words for
negative values of $group_size, and N * $group_size characters for
positive values of $group_size.  $max must be greater than 1.

   If you need (!) more precise control over the size of the output text,
try setting set $max high and trim the output to size, and/or try calling
`dissociate' multiple times until you get the amount of output you want.
(But be sure to give up if `dissociate' keeps returning nullstring, as it
will in some strange cases.)

   `dissociate' can also be called with the following syntaxes:

     dissociate($input, $group_size);
      # acts like max of 100

     dissociate($input);
      # acts like group size of 2 (characters) and max of 100

   This library also provides the procedure `dissociate_filter', which
pulls input from "<>" (files specified on the command line, or STDIN), and
sends dissociated output to STDOUT.  It can be called with these syntaxes:

     dissociate_filter($group_size, $max);

     dissociate_filter($group_size);
      # uses a default value for $max

     dissociate_filter();
      # uses a default value for $group_size and $max

   These above-mentioned default values can come from command line
switches, if you make a script consisting of:

     #!/usr/local/bin/perl
     use Games::Dissociate;
     dissociate_filter;

   and call that script, say, `dissociate', and call it as:

     dissociate -c5 -m200 < foo.txt

   or

     dissociate -w2 -m70 foo.txt bar.txt | less

   and so on.

   To explain the switches:

   `-w[number]' specifies a by-word dissociation with that number of words
as the group size, `-c[number]' specifies a by-character dissociation with
that number of characters as the group size, `-m[number]' specifies a
default for $max.

   If you don't specify a default for $group_size or $max, $group_size
defaults to 100 and $max defaults to 2 (characters).

Efficiency Notes
----------------

   This module has to search the input string by performing regexp
searches on it.  In the current version of this module, control over
compilation of regular expressions may not be not optimally efficient.
Perl 5.005 provides options to better control regexp compilation; once
Perl 5.005 is in wider use, I may come out with a new version of
Games::Dissociate requiring Perl 5.005 or later, using these new regexp
compilation control features.

   If you feed this module a lot of text (over 50K, say), it will indeed
get very slow (notably with by-word dissociation), since that whole chunk
of text has to be searched over and over and over.

   If you have an idea for making this module more efficient, feel free to
email it to me.

Internationalization Notes
--------------------------

   When dealing with text in heavily inflected languages (like Finnish -
lots of unique word endings, frequently used), this module will require
longer input text to produce interesting results for by-word dissociation,
compared to relatively inflection-poor languages like English.

   For text written with no inter-word spacing (often the case with Thai,
for example), there's no way for this module to tell where the word breaks
are - in such cases, use only the by-character mode.

   The current version of this library assumes "/./" matches a single
character, for by-character dissociation; and, for by-word dissociation,
that "/\w+/" matches whole words and /\W+/ matches non-word strings.
These are locale-dependent functions, and Games::Dissociate has a "use
locale" in it, hopefully triggering correct behavior for your favorite
locale, language, and character-encoding.  Consult Perllocale (perl.info),
and Locale, for more information on
locales.

   I *have* found "use locale" to do unwelcome things (like
unceremoniously dumping core) on a few very strange, very old (and
otherwise barely-working) machines.  If this is a problem for you, or if
you don't plan to use locales, comment out the "use locale" in the
Games::Dissociate source code.

   The treatment of locales and support for them may change in future
versions of this module, depending on how future Perl versions shape up,
particularly in their support of Unicode.

Randomness Notes
----------------

   This library uses rand extensively, but never calls srand.  If you're
getting the same dissociated output all the time, then you're using an old
(pre-5.004) version of Perl that doesn't do implicit randomness seeding -
just call "srand();", maybe right after you say "use Games::Dissociate";

SEE ALSO
========

   * Emacs's `dissociate.el' (written circa 1985?).

COPYRIGHT
=========

   Copyright (c) 1998-2001, Sean M. Burke. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   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.

REMINDER
========

   It's just a toy.

AUTHOR
======

   Sean M. Burke <sburke@cpan.org>

Create Mazes as Objects.
************************

NAME
====

   Games::Maze - Create Mazes as Objects.

SYNOPSIS
========

     use Games::Maze::MazeD2;
     use Games::Maze::MazeXD2;
     use Games::Maze::MazeD3;
     use Games::Maze::MazeXD3;

     my($minos) = MazeD2->new($columns, $rows);
     my($theseus) = MazeXD2->new($columns, $rows);
     my($minotaur) = MazeD3->new($columns, $rows, $levels);
     my($posiedon) = MazeXD3->new($columns, $rows, $levels);

     $minos->reset();       # Actually, automatically called.
     $minos->make();
     $minos->solve();
     $minos->to_ascii();
     $minos->to_hex_dump();

PREREQUISITES
=============

   Perl 5.003_20 or later. This is the version that is required for the
"use constant" pragma, and constants are used throughout the code.

INSTALLATION
============

     perl Makefile.PL
     make
     make test
     make install

   Note: You may get a warning when running 'make test'.  This may occur
because you have compiled your perl with a value of RANDBITS that is
unknown to the test case. The test files will be written in /tmp. Please
send them and your RANDBITS value to *jgamble@ripco.com* so that they can
be incorporated into the next release.

DESCRIPTION
===========

   Simply put, these packages create mazes. Your choices are the simple
2-dimensional rectangular maze, the 2-dimensional hexagonal maze, the
3-dimensional rectangular maze, and the 3-dimensional hexagonal maze.  The
mazes are objects that you can manipulate using the available methods.

   From a purely functional standpoint, the 2-dimensional packages are
unneeded, as a 3-dimensional maze that is one level deep does mimic a
2-dimensional maze, but the internal functionality of the 2-dimensional
maze is slightly different and somewhat more efficient, and so is retained.

Maze Object Methods
-------------------

new([columns [, rows [, levels] ])
     Creates the object with it's attributes. Columns and rows will
     default to 3 if you don't pass parameters to the method. For
     3-dimensional mazes, *levels* defaults to 2.

reset
     Resets the matrix m. You should not normally need to call this method,
     as the other methods will call it when needed.

make
     Perform a random walk through the walls of the grid. This creates a
     simply-connected maze.

solve
     Finds a solution to the maze by examining a path until a dead end is
     reached.

to_hex_dump
     Returns a formatted string all of the cell values, including the
     border cells, in hexadecimal.

to_ascii
     Translate the maze into a string of ascii 7-bit characters. If called
     in an array context, return as a list of levels. Otherwise returned
     as a single string, each level separated by a single newline. The maze
     created by MazeD2 and MazeXD2 is always a single string.

     Currently, this is the only method available to view the maze. It
     uses underscores, both slash characters, and vertical bars to
     represent the walls of the maze. The asterisk represents the path,
     and the letters 'c', 'f', and 'b' represent entries through the
     ceiling, floor, or both, respectively.

EXAMPLES
========

     use Games::Maze::MazeD3;

     my($minos) = MazeD3->new(8, 6, 3);
     $minos->make();
     $, = "\n\n";
     print $minos->to_ascii();
     print "\nThe Solution...\n";
     $minos->solve();
     print $minos->to_ascii();
     exit(0);

AUTHOR
======

   John M. Gamble may be found at *jgamble@ripco.com*

Create maze objects.
********************

NAME
====

   Games::MazeD2 - Create maze objects.

   Maze creation is done through the maze object's methods, listed below:

new([columns, [rows]])
     Creates the object with it's attributes. Columns and rows will default
     to 3 if you don't pass parameters to the method.

describe
     Returns information about the maze object.

reset
     Resets the matrix m. You should not normally need to call this method,
     as the other methods will call it when needed.

make
     Perform a random walk through the walls of the grid. This creates a
     simply-connected maze.

solve
     Finds a solution to the maze by examining a path until a dead end is
     reached.

to_hex_dump
     Returns a formatted string all of the cell values, including the
     border cells, in hexadecimal.

to_ascii
     Translate the maze into a string of ascii 7-bit characters. If called
     in an array context, return as a list of levels. Otherwise returned
     as a single string, each level separated by a single newline.

Create 3-D maze objects.
************************

NAME
====

   Games::MazeD3 - Create 3-D maze objects.

   Maze creation is done through the maze object's methods, listed below:

new([columns, [rows, [levels]]])
     Creates the object with it's attributes. Columns, rows, and levels
     will default to 3, 3, and 2 if you don't pass parameters to the
     method.

describe
     Returns information about the maze object.

reset
     Resets the matrix m. You should not normally need to call this method,
     as the other methods will call it when needed.

make
     Perform a random walk through the walls of the grid. This creates a
     simply-connected maze.

solve
     Finds a solution to the maze by examining a path until a dead end is
     reached.

to_hex_dump
     Returns a formatted string all of the cell values, including the
     border cells, in hexadecimal.

to_ascii
     Translate the maze into a string of ascii 7-bit characters. If called
     in an array context, return as a list of levels. Otherwise returned
     as a single string, each level separated by a single newline.

Create hexagon maze objects.
****************************

NAME
====

   Games::MazeXD2 - Create hexagon maze objects.

   Maze creation is done through the maze object's methods, listed below:

new([columns, [rows]])
     Creates the object with it's attributes. Columns and rows will default
     to 3 if you don't pass parameters to the method.

describe
     Returns information about the maze object.

reset
     Resets the matrix m. You should not normally need to call this method,
     as the other methods will call it when needed.

make
     Perform a random walk through the walls of the grid. This creates a
     simply-connected maze.

solve
     Finds a solution to the maze by examining a path until a dead end is
     reached.

to_hex_dump
     Returns a formatted string all of the cell values, including the
     border cells, in hexadecimal.

to_ascii
     Translate the maze into a string of ascii 7-bit characters. If called
     in an array context, return as a list of levels. Otherwise returned
     as a single string, each level separated by a single newline.

Create 3-D hexagon maze objects.
********************************

NAME
====

   Games::MazeXD3 - Create 3-D hexagon maze objects.

   Maze creation is done through the maze object's methods, listed below:

new([columns, [rows, [levels]]])
     Creates the object with it's attributes. Columns, rows, and levels
     will default to 3, 3, and 2 if you don't pass parameters to the
     method.

describe
     Returns information about the maze object.

reset
     Resets the matrix m. You should not normally need to call this method,
     as the other methods will call it when needed.

make
     Perform a random walk through the walls of the grid. This creates a
     simply-connected maze.

solve
     Finds a solution to the maze by examining a path until a dead end is
     reached.

to_hex_dump
     Returns a formatted string all of the cell values, including the
     border cells, in hexadecimal.

to_ascii
     Translate the maze into a string of ascii 7-bit characters. If called
     in an array context, return as a list of levels. Otherwise returned
     as a single string, each level separated by a single newline.

Class for generating Word Find type puzzles
*******************************************

NAME
====

   WordFind - Class for generating Word Find type puzzles

SYNOPSIS
========

     use Games::WordFind;
     $puz=Games::WordFind->new({cols=>10});
     @words=qw(perl camel llama linux great);
     $puz->create_puzzle(@words);
     print $puz->get_plain();

     or,
     print $puz->get_latex();

DESCRIPTION
===========

   This module simply provides a class which can be used to generate
WordFind type puzzles. It is simple to use, the relevant methods are:

$puzzle = Games::WordFind->new({cols => 10,intersect=>1});
     Obviously, this returns a WordFind object. By default the puzzle
     created by this object is a 10x10 lattice--you may give an optional
     hash reference with a 'cols' as the key and some number as the value
     for the size of the lattice. You may also provide an 'intersect' key,
     which allows words to intersect in the puzzle (share letters) when
     set to a non-zero value.

$puzzle->create_puzzle(LIST)
     This method takes the LIST of words and creates the puzzle. Any words
     which are longer than the number of columns in the puzzle are dropped
     from the wordlist and a warning is issued. This method will return
     references to three arrays; a two dimensional array of the puzzle, an
     array of the words used, and a two dimensional array of the puzzle
     solution. These are so you can format your puzzle output yourself
     rather than using the latex or html formatting functions described
     next.

$puzzle->get_plain({solution => 1})
     This method gets the puzzle and its solution matrix in a plain text
     format. If you supply the optional hash reference with a non-zero
     value for 'solution', a solution matrix is included immediately
     following the puzzle.

$puzzle->get_latex({solution => 1, wrapper => 1})
     This method a latex formatted version of the puzzle containing
     tabular environments to set the puzzle and solution (a newpage
     separates the two). The optional hash argument can contain the key
     'wrapper' which tells the method to return the puzzle wrapped with a
     latex preamble, and the key 'solution' which will return the solution
     matrix after a `\newpage' command in the latex source.

$puzzle->get_html({solution =>1, wrapper =>1})
     Similar to the latex method, though, of course, there is no newpage
     separation of the solution.

AUTHOR
======

   Andrew L Johnson <ajohnson@gpu.srv.ualberta.ca>

Copyright
=========

   WordFind.pm and wordfind.pl are copyright (c) 1997,1998 Andrew L
Johnson. This is free software and you may redistribute it and/or modify
it under the same terms as Perl itself.

SEE ALSO
========

   perl(1).

a class for creating word-guessing game
***************************************

NAME
====

   Games::WordGuess - a class for creating word-guessing game

SYNOPSIS
========

     use Games::WordGuess;

     $game = new Games::WordGuess;
     $game = new Games::WordGuess("/usr/games/lib/fortunes/startrek");

DESCRIPTION
===========

   Games::WordGuess is a module for word-guessing game.  Scoring is
calculated from the number of chances left for each mystery word.

Constructor
-----------

   Specify the full path to the file containing words to be played at the
new() method, for example:

     $game = new Games::WordGuess("/usr/games/lib/fortunes/startrek");

   otherwise, `Games::WordGuess' uses some internal Indonesian words as the
default.

Simple command line user interface
----------------------------------

   Look at examples/cmdln script on example of using command_interface().

process_guess()
---------------

   This is the core method. Passed a character, `process_guess' will return
undef if there's no matched character in the current mystery word. If it is
passed a previous matched character, it returns undef as well. On success,
it returns 0, or 1 if the mystery word has already revealed.

in_progress()
-------------

   Returns the mystery word in current player's progress. Initially, after
a `Game::WordGuess' object is created, this will return the mystery word
covered with asterisks. On each matched guess, the corresponding asterisk
will be substituted by the real character.

get_chances()
-------------

   Returns the remaining chances left for current player.

get_score()
-----------

   Returns total score for current player.

init_mystery()
--------------

   Provides a new mystery word to current player. Call to this method is
required to continue the game after successful guess of one complete word.

HISTORY
=======

   * August 16, 1999 - Version 0.20:

     process_guess() now returns undef on missed guess. Added
     in_progress() method.  Added documentation, and a CGI script example
     using Apache::Session.

   * July 1999 - Version 0.11:

     Changes to command_interface(), as suggested by Steven Haryanto
     <sh@hhh.indoglobal.com>.

   * April 1999 - Publicly released, Version 0.10

AUTHOR
======

   Edwin Pratomo <*ed.pratomo@computer.org*>

COPYRIGHT
=========

   Copyright (c) 1999 Edwin Pratomo <ed.pratomo@computer.org>.

   All rights reserved. This is a free code; you can redistribute it
and/or modify it under the same terms as Perl itself.

alife simulator for Conway/Patterson/Beeler worms, etc.
*******************************************************

NAME
====

   Games::Worms - alife simulator for Conway/Patterson/Beeler worms, etc.

SYNOPSIS
========

     perl -MGames::Worms -e worms -- -tPS
     perl -MGames::Worms -e worms -- -tPS / / / / > foo1.ps
     perl -MGames::Worms -e worms -- -tTk
     perl -MGames::Worms -e worms -- -tTek4010 / / / Games::Worms::Random2

BUGS, WARNINGS, AND CAVEATS
===========================

   This is an alpha release.  The documentation is incomplete, and the
interface is not yet finalized.

   Occasionally I've seen Perl 5.004_02 for MSWin segfault at global
destruction time.

   The Tk part, I've only tested under pTk.  This's my first hack at Tk,
so lets hope all the code I wrote is portable.  Suggestions welcome!

   I've tested the PostScript part only under GhostScript.

   I've tested the Tek interface under MSKermit.  I hear xterm has a Tek
emulator in it - I'd be interested to hear if it works well with Worms's
Tek interface.

DESCRIPTION
===========

   [elaborate]

   Worms is an implementation of an artificial-life game.  It can output
via Perl-Tk, Tek4010, and PostScript.  It is a game not in the sense of
checkers, but in the sense of Conway's Life.

   In a Worms universe, worms crawl around an isometric grid of triangles,
leaving trails behind them, and turning in accordance to simple rules that
are based upon which way they can move at a each junction.  From the
simple rules emerges surprising complexity.

TO DO
=====

   Allow board-size specifications on the command line.

   Better docs.

   Maybe a GIF output mode?

   More interactive interface in pTk mode?

   Currently the interface is pretty much: specify things on the command
line, then sit back and watch the worms go, until they all die.  Hopefully
I (or someone ambitious who knows Tk better than I do) may add more
interactivity to the interface.

INVOCATION
==========

   Start it up by making a Perl program called `worms', with the content:

     !/usr/bin/perl
     use Games::Worms;
     worms;

   Then start up with the -t switch specifying which interface to use:

     worms -tTk
       ...for Tk mode
     worms -tPS
       ...for PostScript mode
     worms -tTek4010
       ...for Tektronics mode

   Command line arguments thereafter are interpreted as the names of
classes worms should come from.  (Currently, three are provided in this
distribution: Games/Worms/Random,
Games/Worms/Random2, and Games/Worms/Beeler.)
If no arguments are provided, Worms uses two
Random2s and two Beelers.

   For each name you specify, if it contains a slash, the rest of that
name is passed to the worm as an expression of its rules.

   Example specifications:

     Games::Worms::Beeler
     Games::Worms::Random
     Games::Worms::Random2
     Games::Worms::Beeler/1a2d3caaa4b
     Games::Worms::Beeler/1A2B3ACAC4B
     Games::Worms::Beeler/1B2B3AAAB4A

   (A Beeler worm with no rules specified makes up a random rule set when
it starts.  A Random worm obeys no rules.  A Random2 worm is random but
consistent.)

   If you specify a name starting with '/', it's interpreted as short for
'Games::Worms::Beeler/'.  In other words,

     /1a2d3caaa4b   equals   Games::Worms::Beeler/1a2d3caaa4b
     /1A2B3ACAC4B   equals   Games::Worms::Beeler/1A2B3ACAC4B
     /1B2B3AAAB4A   equals   Games::Worms::Beeler/1B2B3AAAB4A

   See the *Scientific American* article on Beeler worms for the meaning
of these Beeler worm rule specifications.  I don't have the citation for
the first run of the article, but it's reproduced with nice addenda in the
book cited below.

   If you don't want to bother making that little script called "worms",
you can just as well invoke Worms via:

     perl -MGames::Worms -e worms -- -tTk

     perl -MGames::Worms -e worms -- -tPS

     perl -MGames::Worms -e worms -- -tTek4010

     perl -MGames::Worms -e worms -- -tTek4010
       Games::Worms::Random  Games::Worms::Random2
       /1a2d3caaa4b /1A2B3ACAC4B /1B2B3AAAB4A

CONCEPTS
========

   [to be written]

REFERENCES
==========

   "Worm Paths", chapter 17 in: Martin Gardner, 1986, *Knotted Doughnuts
and Other Mathematical Entertainments*, W. H. Freeman and Company.

   "Patterson's Worm", M. Beeler, MIT AI Memo #290.  (early 1970s?)

   "Worms?" [sic], David Maynard, Electronic Arts, 1983.  (A game for the
Atari 400 (or 800?), the Commodore 64, and maybe other machines.
Games::Worms isn't based on EOA "Worms?", but "Worms?" is the best known
implementation of Beeler worms.  It uses them as the basis for a very
interesting and abstract interactive game.)

GUTS
====

   Read the source.  It's OOPilicious!

COPYRIGHT
=========

   Copyright 1999, Sean M. Burke `sburke@netadventure.net', all rights
reserved.  This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

AUTHOR
======

   Sean M. Burke `sburke@netadventure.net'

base class for worms
********************

NAME
====

   Games::Worms::Base - base class for worms

SYNOPSIS
========

     package Spunky;
     use Games::Worms::Random;
     @ISA = ('Games::Worms::Random');
     ...stuff...

DESCRIPTION
===========

   This is the base class for all worms in Worms.

class for Conway/Patterson/Beeler worms
***************************************

NAME
====

   Games::Worms::Beeler - class for Conway/Patterson/Beeler worms

SYNOPSIS
========

     perl -MGames::Worms -e worms -- -tTk Games::Worms::Beeler/1a2d3cbaa4b

DESCRIPTION
===========

   This class implements Conway/Patterson/Beeler worms - "Beeler worms"
for short.

   See the *Scientific American* reference in Games/Worms.

   Note that my notation for rule-strings is directly taken from that
article.

random worms
************

NAME
====

   Games::Worms::Random - random worms

SYNOPSIS
========

     perl -MGames::Worms -e worms -- -tTk Games::Worms::Random

DESCRIPTION
===========

   Worms in the class Games::Worms::Random are totally random - they move
at random in whichever way they can, without regard to any rules or past
movement.

class for consistent random worms
*********************************

NAME
====

   Games::Worms::Random2 - class for consistent random worms

SYNOPSIS
========

     perl -MGames::Worms -e worms -- -tTk Games::Worms::Random2

DESCRIPTION
===========

   Worms in the class Games::Worms::Random2 are random, but consistent -
that is, a worm in this class, upon meeting a new context, will choose at
random which way to go, and then will associate that context with that
move; and for the rest of its life, given that context, it will move in
that direction.

   Games::Worms::Random2 is implemented by simply inheriting from
Games::Worms::Random, but setting memoization to true.

   This simple change leads to worms that often behave rather like Beeler
worms, but sometimes behave astonishingly differently.

Perl extension for quick (& dirty) navigation of GEDCOM files
*************************************************************

NAME
====

   GedNav - Perl extension for quick (& dirty) navigation of GEDCOM files

SYNOPSIS
========

     use GedNav;
     blah blah blah

DESCRIPTION
===========

   GedNav is a set of perl modules for navigating a GEDCOM file quickly.
The intent was to make it fast enough for CGI purposes, on large GEDCOM
files.

   I have not yet included the code for the report objects I've written
(outline & register so far), except for the example code in outline.pl.

   I've also not included the Apache::GedNav stuff I've written.  That'll
probably come in a separate lump, when the time comes.

AUTHOR
======

   Rob Fugina, robf@geeks.com

SEE ALSO
========

   perl(1).

a module to manipulate Gedcom genealogy files
*********************************************

NAME
====

   Gedcom - a module to manipulate Gedcom genealogy files

   Version 1.09 - 12th February 2001

SYNOPSIS
========

     use Gedcom;

     my $ged = Gedcom->new(gedcom_file => $gedcom_file);
     my $ged = Gedcom->new(grammar_version => 5.5,
                           gedcom_file     => $gedcom_file,
                           read_only       => 1,
                           callback        => $cb);
     my $ged = Gedcom->new(grammar_file => "gedcom-5.5.grammar",
                           gedcom_file  => $gedcom_file);

     return unless $ged->validate;
     my $xref = $self->resolve_xref($value);
     $ged->resolve_xrefs;
     $ged->unresolve_xrefs;
     $ged->normalise_dates;
     my %xrefs = $ged->renumber;
     $ged->order;
     $ged->write($new_gedcom_file, $flush);
     $ged->write_xml($fh, $level);
     my @individuals = $ged->individuals;
     my @families = $ged->families;
     my $me = $ged->get_individual("Paul Johnson");
     my $xref = $ged->next_xref("I");

DESCRIPTION
===========

   Copyright 1998-2001, Paul Johnson (pjcj@cpan.org)

   This software is free.  It is licensed under the same terms as Perl
itself.

   The latest version of this software should be available from my
homepage: http://www.pjcj.net

   This module provides for manipulation of Gedcom files.  Gedcom is a
format for storing genealogical information designed by The Church of
Jesus Christ of Latter-Day Saints (http://www.lds.org).  Information about
Gedcom is available as a zip file at
ftp://gedcom.org/pub/genealogy/gedcom/gedcom55.zip.  Unfortunately, this
is only usable if you can access a PC running Windows of some description.
Part of the reason I wrote this module is because I don't do that.  Well,
I didn't.  I can now although I prefer not to...

   Requirements:   Perl 5.005 or later   ActivePerl5 Build Number 520 or
later has been reported to work

   Optional Modules:   Date::Manip.pm       to work with dates
Text::Soundex.pm     to use soundex   Parse::RecDescent.pm to use
lines2perl   Roman.pm             to use the LifeLines function roman from
lines2perl

   The Gedcom format is specified in a grammar file (gedcom-5.5.grammar).
Gedcom.pm parses the grammar which is then used to validate and allow
manipulation of the Gedcom file.  I have only used Gedcom.pm with version
5.5 of the Gedcom grammar, which I had to modify slightly to correct a few
errors.  The advantage of this approach is that Gedcom.pm should be useful
if the Gedcom grammar is ever updated.  It also made the software easier
to write, and probably more dependable too.  I suppose this is the virtue
of laziness shining through.

   The vice of laziness is also shining brightly - I need to document how
to use this module in much greater detail.  This is happening - this
release has more documentation than the previous ones - but if you would
like information feel free to send me mail.

   This module provides some functions which work over the entire Gedcom
file, such as reformatting dates, renumbering entries and ordering the
entries.  It also allows access to individuals, and then to relations of
individuals, for example sons, siblings, spouse, parents and so forth.

   This release includes a lines2perl program to convert LifeLines programs
to Perl.  The program works, but it has a few rough edges, and some
missing functionality.  I'll be working on it when it hits the top of my
TODO list.

   This release provides an option for read only access to the gedcom file.
Actually, this doesn't stop you changing or writing the file, but it does
parse the gedcom file lazily, meaning that only those portions of the
gedcom file which are needed will be read.  This can provide a substantial
saving of time and memory providing that not too much of the gedcom file
is read.  If you are going to read the whole gedcom file, this mode is
less efficient.

   Note that this is an early release of this software - caveat emptor.

   Should you find this software useful, or if you make changes to it, or
if you would like me to make changes to it, please send me mail.  I would
like to have some sort of an idea of the use this software is getting.
Apart from being of interest to me, this will guide my decisions when I
feel the need to make changes to the interface.

   There is a low volume mailing list available for discussing the use of
Perl in conjunction with genealogical work.  This is an appropriate forum
for discussing Gedcom.pm.  To subscribe to the regular list, send a
message to majordomo@icomm.ca and put subscribe perl-gedcom as the body of
the message. To get on the digest version of the list, put subscribe
perl-gedcom-digest.

   To store my genealogy I wrote a syntax file (gedcom.vim) and used vim
(http://www.vim.org) to enter the data, and Gedcom.pm to validate and
manipulate it.  I find this to be a nice solution.

GETTING STARTED
===============

   This space is reserved for something of a tutorial.  If you learn best
by looking at examples, take a look at the test directory, t.  The most
simple test is *birthdates.t*.

   The first thing to do is to read in the Gedcom file.  At its most
simple, this will involve a statement such as

     my $ged = Gedcom->new(gedcom_file => $gedcom_file);

   It is now possible to access the records within the gedcom file.  Each
individual and family is a record.  Records can contain other records.
For example, an individual is a record.  The birth information is a
sub-record of the individual, and the date of birth is a sub-record of the
birth record.

   Some records, such as the birth record, are simply containers for other
records.  Some records have a value, such as the date record, whose value
is a date.  This is all defined in the Gedcom standard.

   To access an individual use a statement such as

     my $i = $ged->get_individual("Paul Johnson");

   To access information about the individual, use a function of the same
name as the Gedcom tag, or its description.  Tags and descriptions are
listed at the head of Gedcom.pm.  For example

     for my $b ($i->birth)
     {
     }

   will loop through all the birth records in the individual.  Usually
there will only be one such record, but there may be zero, one or more.
Calling the function in scalar context will return only the first record.

     my $b = $i->birth;

   But the second record may be returned with

     my $b = $i->birth(2);

   If the record required has a value, for example

     my $n = $i->name;

   then the value is returned, in this case the name of the individual.  If
there is no value, as is the case for the birth record, then the record
itself is returned.  If there is a value, but the record itself is
required, then the get_record() function can be used.

   Information must be accesed through the Gedcom structure so, for
example, the birthdate is accessed via the date record from the birth
record within an individual.

     my $d = $b->date;

   Be aware that if you access a record in scalar context, but there is no
such record, then undef is returned.  In this case, $b would be undef if
$i had no birth record.  This is another reason why looping through
records is a nice solution, all else being equal.

   Access to values can also be gained through the get_value() function.
This is a preferable solution where it is necessary to work down the
Gedcom structure.  For example

     my $bd = $i->get_value("birth date");
     my $bd = $i->get_value(qw(birth date));

   will both return an individual's birth date or undef if there is none.
And

     my @bd = $i->get_value("birth date");

   will return all the birth dates.  The second birth date, if there is
one, is

     my $bd2 = $i->get_value(["birth", 2], "date");

   Using the get_record() function in place of the get_value() function, in
all cases will return the record rather than the value.

   All records are of a type derived from Gedcom::Item.  Individuals are of
type Gedcom::Individual.  Families are of type Gedcom::Family.  Events are
of type Gedcom::Event.  Other records are of type Gedcom::Record which is
the base type of Gedcom::Individual, Gedcom::Family and Gedcom::Event.

   As individuals are of type Gedcom::Individual, the functions in
Gedcom::Individual.pm are available.  These allow access to relations and
other information specific to individuals, for example

     my @sons = $i->sons;

   It is possible to get all the individuals in the gedcom file as

     my @individuals = $ged->individuals;

HASH MEMBERS
============

   I have not gone the whole hog with data encapsulation and such within
this module.  Maybe I should have done.  Maybe I will.  For now though,
the data is accessable though hash members.  This is partly because having
functions to do this is a little slow, especially on my old DECstation,
and partly because of laziness again.  I'm not too sure whether this is
good or bad laziness yet.  Time will tell no doubt.

   As of version 1.05, you should be able to access all the data through
functions.  Well, read access anyway.  The TODO list mentions something
about improving the situation as far as write access is concerned.

   Some of the more important hash members are:

$ged->{grammar}
---------------

   This contains the gedcom grammar.

   See Gedcom::Grammar.pm for more details.

$ged->{record}
--------------

   This contains the top level gedcom record.  A record contains a number
of items.  Each of those items are themselves records.  This is the way in
which the hierarchies are modelled.

   If you want to get at the data in the gedcom object, this is where you
start.

   See Gedcom::Record.pm for more details.

METHODS
=======

new
---

     my $ged = Gedcom->new(gedcom_file => $gedcom_file);

     my $ged = Gedcom->new(grammar_version => 5.5,
                           gedcom_file     => $gedcom_file,
                           read_only       => 1,
                           callback        => $cb);

     my $ged = Gedcom->new(grammar_file => "gedcom-5.5.grammar",
                           gedcom_file  => $gedcom_file);

   Create a new gedcom object.

   gedcom_file is the name of the gedcom file to parse.

   You may optionally pass grammar_version as the version number of the
gedcom grammar you want to use.  At the moment only version 5.5 is
available.  If you do not specify a grammar version, you may specify a
grammar file as grammar_file.  Usually, you will do neither of these, and
in this case the grammar version will default to the latest available
version, currently 5.5.

   The read_only parameter indicates that the Gedcom data structure will be
used primarily for read_only operations.  In this mode the gedcom file is
read lazily, such that whenever possible the Gedcom records are not read
until they are needed.  This can save on both memory and CPU usage,
provided that not too much of the gedcom file is needed.  If the whole of
the gedcom file needs to be read, for example to validate it, or to write
it out in a different format, then this option should not be used.

   When using the read_only option an index file is kept which can also
speed up operations.  It's usage should be transparant, but will require
write access to the directory containing the gedcom file.  If you access
individuals only by their xref (eg I20) then the index file will allow
only the relevant parts of the gedcom file to be read.

   With or without the read_only option, the gedcom file is accessed in the
same fashion and the data structures can be changed.  In this respect, the
name read_only is not very accurate, but since changing the Gedcom data
will generally mean that the data will be written which means that the
data will first be read, the read_only option is generally useful when the
data will not be written and when not all the data will be read.  You may
find it useful to experiment with this option and check the amount of CPU
time and memory that your application uses.

   callback is an optional reference to a subroutine which will be called
at various times while the gedcom file (and the grammar file, if
applicable) is being read.  Its purpose is to provide feedback during
potentially long operations.  The subroutine is called with five arguments:

     my ($title, $txt1, $txt2, $current, $total) = @_;

     $title is a brief description of the current operation
     $txt1 and $txt2 provide more information on the current operation
     $current is the number of operations performed
     $total is the number of operations that need to be performed

   If the subroutine returns false, the operation is aborted.

write
-----

     $ged->write($new_gedcom_file, $flush);

   Write out the gedcom file.

   Takes the name of the new gedcom file, and whether or not to indent the
output according to the level of the record.  $flush defaults to false,
but the new file name must be specified.

write_xml
---------

     $ged->write_xml($fh);

   Write the item to a FileHandle as XML.

   Takes the name of the new gedcom file.

   Note that this function is experimental.  The XML output doesn't conform
to any standard that I know of, because I don't know of any standard.  If
and when such a standard surfaces, and probably even if it doesn't, I'll
change the output from this function.  If you make use of this function,
beware.  I'd also be very interested in hearing from you to determine the
requirements for the XML.

collect_xrefs
-------------

     $ged->collect_xrefs($callback);

   Collect all the xrefs into a data structure ($ged->{xrefs}) for easy
location.  $callback is not used yet.

   Called by new().

resolve_xref
------------

     my $xref = $self->resolve_xref($value);

   Return the record $value points to, or undef.

resolve_xrefs
-------------

     $ged->resolve_xrefs($callback);

   Changes all xrefs to reference the record they are pointing to.  Like
changing a soft link to a hard link on a Unix filesystem.  $callback is
not used yet.

unresolve_xrefs
---------------

     $ged->unresolve_xrefs($callback);

   Changes all xrefs to name the record they contained.  Like changing a
hard link to a soft link on a Unix filesystem.  $callback is not used yet.

validate
--------

     return unless $ged->validate($callback);

   Validate the gedcom object.  This performs a number of consistency
checks, but could do even more.  $callback is not properly used yet.

   Any errors found are given out as warnings.  If this is unwanted, use
$SIG{__WARN__} to catch the warnings.

   Returns true iff the gedcom object is valid.

normalise_dates
---------------

     $ged->normalise_dates;
     $ged->normalise_dates("%A, %E %B %Y");

   Change all recognised dates into a consistent format.  This routine used
Date::Manip to do the work, so you can look at it's documentation
regarding formats that are recognised and % sequences for the output.

   Optionally takes a format to use for the output.  The default is
currently "%A, %E %B %Y", but I may change this, as it seems that some
programs don't like that format.

renumber
--------

     $ged->renumber;
     my %xrefs = $ged->renumber(INDI => 34, FAM => 12, xrefs => [$xref1, $xref2]);

   Renumber all the records.

   Optional parameters are:

     tag name => last used number (defaults to 0)
     xrefs    => list of xrefs to renumber first

   As a record is renumbered, it is assigned the next available number.
The husband, wife, children parents and siblings are then renumbered in
that order.  This helps to ensure that families are numerically close
together.

   The hash returned is the updated hash that was passed in.

sort_sub
--------

     $ged->order($ged->sort_sub);

   Default ordering subroutine.

   The sort is by record type in the following order: HEAD, SUBM, INDI,
FAM, NOTE, TRLR, and then by xref within the type.

order
-----

     $ged->order;
     $ged->order($order_sub);

   Order all the records.  Optionally provide a sort subroutine.

   This orders the entries within the gedcom object, which will affect the
order in which they are written out.  The default sort function is
Gedcom::sort_sub.  You will need to ensure that the HEAD record is first
and that the TRLR record is last.

individuals
-----------

     my @individuals = $ged->individuals;

   Return a list of all the individuals.

families
--------

     my @families = $ged->families;

   Return a list of all the families.

get_individual
--------------

     my $me = $ged->get_individual("Paul Johnson");

   Return a list of all individuals matching the specified name.

   There are thirteen matches performed, and the results from the first
successful match are returned.

   The matches are:

     1 - Xref
     2 - Exact
     3 - On word boundaries
     4 - Anywhere
     5 - Exact, case insensitive
     6 - On word boundaries, case insensitive
     7 - Anywhere, case insensitive
     8 - Names in any order, on word boundaries
     9 - Names in any order, anywhere
       10 - Names in any order, on word boundaries, case insensitive
       11 - Names in any order, anywhere, case insensitive
       12 - Soundex code
       13 - Soundex of name

next_xref
---------

     my $xref = $ged->next_xref("I");

   Return the next available xref with the specified prefix.

Basic CGI routines for Gedcom.pm
********************************

NAME
====

   Gedcom::CGI - Basic CGI routines for Gedcom.pm

   Version 1.09 - 12th February 2001

SYNOPSIS
========

     use Gedcom::CGI;

DESCRIPTION
===========

METHODS
=======

a module to manipulate Gedcom events
************************************

NAME
====

   Gedcom::Event - a module to manipulate Gedcom events

   Version 1.09 - 12th February 2001

SYNOPSIS
========

     use Gedcom::Event;

DESCRIPTION
===========

   A selection of subroutines to handle events in a gedcom file.

   Derived from Gedcom::Record.

HASH MEMBERS
============

   None.

METHODS
=======

   None yet.

Individual functions
--------------------

a module to manipulate Gedcom families
**************************************

NAME
====

   Gedcom::Family - a module to manipulate Gedcom families

   Version 1.09 - 12th February 2001

SYNOPSIS
========

     use Gedcom::Family;

     my @rel = $f->husband;
     my @rel = $f->wife;
     my @rel = $f->parents;
     my $nch = $f->number_of_children;
     my @rel = $f->children;
     my @rel = $f->boys;
     my @rel = $f->girls;

DESCRIPTION
===========

   A selection of subroutines to handle families in a gedcom file.

   Derived from Gedcom::Record.

HASH MEMBERS
============

   None.

METHODS
=======

   None yet.

Individual functions
--------------------

     my @rel = $f->husband;
     my @rel = $f->wife;
     my @rel = $f->parents;
     my @rel = $f->children;
     my @rel = $f->boys;
     my @rel = $f->girls;

   Return a list of individuals from family $f.

   Each function, even those with a singular name such as husband(),
returns a list of individuals holding that releation in $f.

number_of_children
------------------

     my $nch = $f->number_of_children;

   Return the number of children in the family, as specified or from
counting.

a module to manipulate Gedcom grammars
**************************************

NAME
====

   Gedcom::Grammar - a module to manipulate Gedcom grammars

   Version 1.09 - 12th February 2001

SYNOPSIS
========

     use Gedcom::Grammar;

     my $st = $grammar->structure("GEDCOM");
     my $sgr = $grammar->item("DATE");
     my @items = $grammar->valid_items;
     my $min = $grammar->min;
     my $max = $grammar->max;
     my @items = $grammar->items;

DESCRIPTION
===========

   A selection of subroutines to handle the grammar of a gedcom file.

   Derived from Gedcom::Item.

HASH MEMBERS
============

   Some of the more important hash members are:

$grammar->{top}
---------------

   The top of the grammar tree.

$grammar->{top}{structures}
---------------------------

   A reference to a hash mapping the names of all structures to the grammar
objects.

METHODS
=======

structures
----------

     my $st = $grammar->structure("GEDCOM");

   Return the grammar item of the specified structure, if it exists, or
undef.

item
----

     my $sgr = $grammar->item("DATE");

   Return the grammar item of the specified sub-item, if it exists, or
undef.

min
---

     my $min = $grammar->min;

   Return the minimum permissible number of $grammar items

max
---

     my $max = $grammar->max;

   Return the maximum permissible number of $grammar items

items
-----

     my @items = $grammar->items;

   Return a list of tags of the grammar's sub-items

valid_items
-----------

     my @items = $grammar->valid_items;

   Return a hash detailing all the valid sub-items of the grammar item.
The key is the tag of the sub-item and the value is another hash with three
members:

     grammar => the sub-item grammar
     min     => the minimum permissible number of these sub-items
     max     => the maximum permissible number of these sub-items

a module to manipulate Gedcom individuals
*****************************************

NAME
====

   Gedcom::Individual - a module to manipulate Gedcom individuals

   Version 1.09 - 12th February 2001

SYNOPSIS
========

     use Gedcom::Individual;

     my $name = $i->name;
     my @rel = $i->father;
     my @rel = $i->mother;
     my @rel = $i->parents;
     my @rel = $i->husband;
     my @rel = $i->wife;
     my @rel = $i->spouse;
     my @rel = $i->siblings;
     my @rel = $i->brothers;
     my @rel = $i->sisters;
     my @rel = $i->children;
     my @rel = $i->sons;
     my @rel = $i->daughters;
     my @rel = $i->descendents;
     my @rel = $i->ancestors;
     my $ok  = $i->delete;

     my @fam = $i->famc;
     my @fam = $i->fams;

DESCRIPTION
===========

   A selection of subroutines to handle individuals in a gedcom file.

   Derived from Gedcom::Record.

HASH MEMBERS
============

   None.

METHODS
=======

name
----

     my $name = $i->name;

   Return the name of the individual, with spaces normalised.

cased_name
----------

     my $cased_name = $i->cased_name;

   Return the name of the individual, with spaces normalised, and surname
in upper case.

surname
-------

     my $surname = $i->surname;

   Return the surname of the individual.

given_names
-----------

     my $given_names = $i->given_names;

   Return the given names of the individual.

soundex
-------

     my $soundex = $i->soundex;

   Return the soundex code of the individual.  This function is only
available if *Text::Soundex.pm* is available.

sex
---

     my $sex = $i->sex;

   Return the sex of the individual, "M", "F" or "U".

Individual functions
--------------------

     my @rel = $i->father;
     my @rel = $i->mother;
     my @rel = $i->parents;
     my @rel = $i->husband;
     my @rel = $i->wife;
     my @rel = $i->spouse;
     my @rel = $i->siblings;
     my @rel = $i->older_siblings;
     my @rel = $i->younger_siblings;
     my @rel = $i->brothers;
     my @rel = $i->sisters;
     my @rel = $i->children;
     my @rel = $i->sons;
     my @rel = $i->daughters;
     my @rel = $i->descendents;
     my @rel = $i->ancestors;

   Return a list of individuals related to $i.

   Each function, even those with a singular name such as father(), returns
a list of individuals holding that relation to $i.

   More complex relationships can easily be found using the map function.
eg:

     my @grandparents = map { $_->parents } $i->parents;

delete
------

     my $ok  = $i->delete;

   Delete $i from the data structure.

   Returns true iff $i was successfully deleted.

Family functions
----------------

     my @fam = $i->famc;
     my @fam = $i->fams;

   Return a list of families to which $i belongs.

   famc() returns those families in which $i is a child.  fams() returns
those families in which $i is a spouse.

a base class for Gedcom::Grammar and Gedcom::Record
***************************************************

NAME
====

   Gedcom::Item - a base class for Gedcom::Grammar and Gedcom::Record

   Version 1.09 - 12th February 2001

SYNOPSIS
========

     use Gedcom::Record;

     $item->{grammar} = Gedcom::Grammar->new(file     => $item->{grammar_file},
                                             callback => $item->{callback});
     my $c = $item->copy;
     $item->read if $item->{file};
     $item->add_items($rec);
     while (my $next = $item->next_item($item))
     my $line = $item->next_line;
     my $line = $item->next_text_line;
     $item->write($fh, $level, $flush);
     $item->write_xml($fh, $level);
     $item->print;
     my $item  = $item->get_item("CHIL", 2);
     my @items = $item->get_item("CHIL");
     $item->delete_item($sub_item);
     my $v = $item->level;
     $item->level(1);
     my $v = $item->xref;
     my $v = $item->tag;
     my $v = $item->value;
     my $v = $item->min;
     my $v = $item->max;
     my $v = $item->gedcom;
     my $v = $item->file;
     my $v = $item->line;
     my $v = $item->full_value;
     my $sub_items = $item->_items;
     my @sub_items = $item->items;
     $item->delete_items;

DESCRIPTION
===========

   A selection of subroutines to handle items in a gedcom file.

HASH MEMBERS
============

   Some of the more important hash members are:

$item->{level}
--------------

   The level of the item.

$item->{xref}
-------------

   The cross reference, either hard or soft.

$item->{tag}
------------

   The name of the tag.

$item->{value}
--------------

   The value of the item.

$item->{min}
------------

   The minimum number of items allowed.

$item->{max}
------------

   The maximum number of items allowed.

$item->{gedcom}
---------------

   The top level gedcom object.

$item->{file}
-------------

   The file from which this object was read, if any.

$item->{line}
-------------

   The line number from which this object was read, if any.

$item->{items}
--------------

   Array of all sub-items of this item.

   It should not be necessary to access these hash members directly.

METHODS
=======

new
---

     $item->{grammar} = Gedcom::Grammar->new(file     => $item->{grammar_file},
                                             callback => $item->{callback});

   Create a new object.

   If file is supplied, it is the name of a file to read.

   If callback is supplied, it is a subroutine reference which is called at
various times while the file is being read.

   The subroutine takes five parameters:   $title:     A title   $txt1:
 One text message   $txt2:      A secondary text message   $current:   A
count of how far through the file we are   $total:     The extent of the
file

   The subroutine should return true iff the file shuld continue to be
read.

copy
----

     my $c = $item->copy;

   Make a copy of the object.  The sub-items are copied too.

read
----

     $item->read if $item->{file};

   Read a file into the object.  Called by the constructor.

add_items
---------

     $item->add_items($rec);

   Read in the sub-items of a item.

next_item
---------

     while (my $next = $item->next_item($item))

   Read the next item from a file.  Return the item or false if it cannot
be read.

next_line
---------

     my $line = $item->next_line;

   Read the next line from the file, and return it or false.

next_text_line
--------------

     my $line = $item->next_text_line;

   Read the next line of text from the file, and return it or false.

write
-----

     $item->write($fh, $level, $flush);

   Write the item to a FileHandle.

   The subroutine takes three parameters:   $fh:        The FileHandle to
which to write   $level:     The level of the item   $flush:     Whether
or not to indent the gedcom output according to the level

write_xml
---------

     $item->write_xml($fh, $level);

   Write the item to a FileHandle as XML.

   The subroutine takes two parameters:   $fh:        The FileHandle to
which to write   $level:     The level of the item

   Note that this function is experimental.  Please read the warnings for
Gedcom::write_xml().

print
-----

     $item->print;

   Print the item.  Used for debugging.  (What?  There are bugs?)

get_item
--------

     my $item  = $item->get_item("CHIL", 2);
     my @items = $item->get_items("CHIL");

   Get specific sub-items from the item.

   The arguments are the name of the tag, and optionally the count.

   In scalar context, returns the sub-item, or undef if it doesn't exist.
In array context, returns all sub-items matching the specified tag.

get_child
---------

   NOTE - This function is deprecated - use get_item instead

     my $child = get_child("CHIL2");

   Get a specific child item from the item.

   The argument contains the name of the tag, and optionally the count.
The regular expression to generate the tag and the count is:

     my ($tag, $count) = $t =~ /^_?(\w+?)(\d*)$/

   Returns the child item, or undef if it doesn't exist

get_children
------------

   NOTE - This function is deprecated - use get_item instead

     my @children = get_children("CHIL");

delete_item
-----------

     $item->delete_item($sub_item);

   Delete the specified sub-item from the item.

Access functions
----------------

     my $v = $item->level;
     $item->level(1);
     my $v = $item->xref;
     my $v = $item->tag;
     my $v = $item->value;
     my $v = $item->min;
     my $v = $item->max;
     my $v = $item->gedcom;
     my $v = $item->file;
     my $v = $item->line;

   Return the eponymous hash element.  If a value if passed into the
function, the element is first assigned that value.

full_value
----------

     my $v = $item->full_value;

   Return the value of the item including all CONT and CONC lines.  This is
probably what you want most of the time, and is the function called by
default from other functions that return values.  If, for some reason, you
want to process CONT and CONC items yourself, you will need to use the
value() function and probably the items() function.

_items
------

     my $sub_items = $item->_items;

   Return a reference to alist of all the sub-items, reading them from the
Gedcom file if they have not already been read.

   It should not be necessary to use this function.  See items().

items
-----

     my @sub_items = $item->items;

   Return a list of all the sub-items, reading them from the Gedcom file if
they have not already been read.

   In general it should not be necessary to use this function.  The
sub-items will usually be accessed by name.  This function is only
necessary if the ordering of the different items is important.  This is
very rare, but is needed for example, when processing CONT and CONC items.

delete_items
------------

     $item->delete_items;

   Delete all the sub-items, allowing the memory to be reused.  If the
sub-items are required again, they will be reread.

   It should not be necessary to use this function.

functions for lines2perl
************************

NAME
====

   Gedcom::LifeLines - functions for lines2perl

   Version 1.09 - 12th February 2001

SYNOPSIS
========

     use Gedcom::LifeLines;

DESCRIPTION
===========

   A selection of subroutines to emulate Lifelines functions.

   For details about the functions, see the Lifelines documentation.

   I general, this module should only be used by the output of the
lines2perl program.  Anything in here that finds a more general use should
probably be abstracted away to one of the more standard modules.

   Functions yet to be implemented include:   parent()   sibling()
getindiset()   choosechild()   choosefam()   chooseindi()   choosesubset()
 menuchoose()   card()   ord()   newfile()   outfile()   gengedcom()
createnode()   addnode()   deletenode()

a module to manipulate Gedcom records
*************************************

NAME
====

   Gedcom::Record - a module to manipulate Gedcom records

   Version 1.09 - 12th February 2001

SYNOPSIS
========

     use Gedcom::Record;

     my $record  = tag_record("CHIL", 2);
     my @records = tag_record("CHIL");
     my @recs = $record->record("birth");
     my @recs = $record->record("birth", "date");
     my $rec  = $record->record("birth date");
     my $rec  = $record->record(["birth", 2], "date");
     my @recs = $record->get_record("birth");
     my $val  = $record->get_value;
     my @vals = $record->get_value("date");
     my @vals = $record->get_value("birth", "date");
     my $val  = $record->get_value("birth date");
     my $val  = $record->get_value(["birth", 2], "date");
     $self->parse($record, $grammar);
     $record->collect_xrefs($callback);
     my $xref = $record->resolve_xref($record->{value});
     my @famc = $record->resolve $record->get_value("FAMC");
     $record->resolve_xrefs($callback);
     $record->unresolve_xrefs($callback);
     return 0 unless $record->validate_semantics;
     $record->normalise_dates($format);
     $record->renumber($args);
     print $record->summary, "\n";
     $record->delete_record($sub_record);

DESCRIPTION
===========

   A selection of subroutines to handle records in a gedcom file.

   Derived from Gedcom::Item.

HASH MEMBERS
============

   Some of the more important hash members are:

$record->{new_xref}
-------------------

   Used by renumber().

$record->{recursed}
-------------------

   Used by renumber().

METHODS
=======

tag_record
----------

     my $record  = tag_record("CHIL", 2);
     my @records = tag_record("CHIL");

   Get specific sub-records from the record.  This function is identical to
Gedcom::Item::get_item().

   The arguments are the name of the tag, and optionally the count.

   In scalar context, returns the sub-record, or undef if it doesn't exist.
In array context, returns all sub-records matching the specified tag.

record
------

     my @recs = $record->record("birth");
     my @recs = $record->record("birth", "date");
     my $rec  = $record->record("birth date");
     my $rec  = $record->record(["birth", 2], "date");
     my @recs = $record->get_record("birth");

   Retrieve a record.

   The get_record() function is identical to the record() function.

   In scalar context, record() returns the specified record, or undef if
there is none.  In list context, record() returns all the specified
records.

   Records may be specified by a list of strings.  Each string is either a
Gedcom tag or a description.  Starting from the first string in the list,
specified records are retrieved.  Then from those records, records
specified by the next string in the list are retrieved.  This continues
until all strings from the list have been used.

   In list context, all specified records are retrieved.  In scalar
context, only the first record is retrieved.  If a record other than the
first is wanted, then instead of passing a string, a reference to an array
containing the string and a count may be passed.

   Instead of specifying a list of strings, it is possible to specify a
single space separated string.  This can make the interface nicer.

get_value
---------

     my $val  = $record->get_value;
     my @vals = $record->get_value("date");
     my @vals = $record->get_value("birth", "date");
     my $val  = $record->get_value("birth date");
     my $val  = $record->get_value(["birth", 2], "date");

   Retrieve a record's value.

   If arguments are specified, record() is first called with those
arguments, and the values of those records are returned.

parse
-----

     $self->parse($record, $grammar);

   Parse a Gedcom record.

   Match a Gedcom::Record against a Gedcom::Grammar.  Warn of any
mismatches, and associate the Gedcom::Grammar with the Gedcom::Record as
$record->{grammar}.  Do this recursively.

collect_xrefs
-------------

     $record->collect_xrefs($callback);

   Recursively collect all the xrefs.  Called by Gedcom::collect_xrefs.
$callback is not used yet.

resolve_xref
------------

     my $xref = $record->resolve_xref($value);

   See Gedcom::resolve_xrefs()

resolve
-------

     my @famc = $record->resolve $record->tag_value("FAMC");

   For each argument, either return it or, if it an xref, return the
referenced record.

resolve_xrefs
-------------

     $record->resolve_xrefs($callback);

   See Gedcom::resolve_xrefs()

unresolve_xrefs
---------------

     $record->unresolve_xrefs($callback);

   See Gedcom::unresolve_xrefs()

validate_semantics
------------------

     return 0 unless $record->validate_semantics;

   Validate the semantics of the Gedcom::Record.  This performs a number of
consistency checks, but could do even more.

   Returns true iff the Record is valid.

normalise_dates
---------------

     $record->normalise_dates($format);

   Change the format of all dates in the record.

   See the documentation for Gedcom::normalise_dates

renumber
--------

     $record->renumber($args);

   Renumber the record.

   See Gedcom::renumber().

child_value
-----------

   NOTE - This function is deprecated - use tag_value instead.

     my $child = $record->child_value("NAME");

child_values
------------

   NOTE - This function is deprecated - use tag_value instead.

     my @children = $record->child_values("CHIL");

summary
-------

     print $record->summary, "\n";

   Return a line of text summarising the record.

delete_record
-------------

     $record->delete_record($sub_record);

   Delete the specified sub-record from the record.

Access functions
----------------

   All the Gedcom tag names can be used as function names.  Depending on
the context in which they are called, the functions return either an array
of the specified sub-items, or the first specified sub-item.

   The descriptions of the tags, with spaces replaced by underscores, can
also be used as function names.  The function names can be of either, or
mixed case.  Unless you use the tag name, in either case, or the
description in lower case, the function will not be pre-declared and you
will need to qualify it or `use subs'.

   use as:   my @items = @{$ged->{record}{items}};   my ($m, $w) =
$ged->{record}->validate_structure($ged->{record}{grammar}, \@items, 1);
warn $w if $w;

   sub validate_grammar {   my $self = shift;   my ($grammar, $items,
$all) = @_;   $I++;   my $min = $grammar->min;   my $max = $grammar->max;
$all++ unless $max;   my $matches = 0;   my $warn = "";   my $value =
$grammar->{tag};   print "  " x $I, " looking for ", $all == 1 ? "all" :
$max if $D;   if ($value)   {     print " $value, $min -> $max\n" if $D;
 for (my $c = 0;          $c <= $#$items && ($all == 1 || !$max ||
$matches < $max);)     {       if ($items->[$c]{tag} eq $value)       {
    my $w = $items->[$c]->validate_syntax2;         $warn .= $w;
splice @$items, $c, 1;         $matches++;       }       else       {
  $c++;       }     }   }   else   {     # TODO - require Data::Dumper
die "What's a " . Data::Dumper->new([$grammar], ["grammar"])       unless
($value) = $grammar->{value} =~ /<<(.*)>>/;     die "Can't find $value in
gedcom structures"       unless my $s = $grammar->structure($value);
$grammar->{structure} = $s;     print " $value, $min -> $max\n" if $D;
my ($m, $w);     do     {       ($m, $w) = $self->validate_structure($s,
$items, $all);       if ($m)       {         $matches += $m;         $warn
.= $w;       }     } while $m && ($all == 1 || !$max || $matches < $max);
}   $I-;   ($matches, $warn) }

   sub validate_structure {   my $self = shift;   my ($structure, $items,
$all) = @_;   $all = 0 unless defined $all;   $I++;   print "  " x $I .
"validate_structure($structure->{structure}, $all)\n" if $D;   my $warn =
"";   my $total_matches = 0;   for my $item (@{$structure->{items}})   {
 my $min = $item->min;     my $max = $item->max;     my ($matches, $w) =
$self->validate_grammar($item, $items, $all);     $warn .= $w;     my
$file = $self->{gedcom}{record}{file};     my $value = $item->{tag} ||
$item->{structure}{structure};     my $msg = "$file:$self->{line}:
$self->{tag}" .                (defined $self->{xref} ? " $self->{xref} "
: "") .                " has $matches $value" . ($matches == 1 ? "" : "s");
   print "  " x $I . "$msg - minimum is $min maximum is $max\n" if $D;
if ($structure->{selection})     {       if ($matches)       {
$warn .= "$msg - minimum is $min\n" if $matches < $min;         $warn .=
"$msg - maximum is $max\n" if $matches > $max && $max;
$total_matches += $matches;                   # only one item is allowed
     last;       }     }     else     {       $warn .= "$msg - minimum is
$min\n" if $matches < $min;       $warn .= "$msg - maximum is $max\n" if
$matches > $max && $max;       $total_matches = 1 if $matches;
     # all items are required     }   }   print "  " x $I . "returning
$total_matches matches\n" if $D;   $I-;   ($total_matches, $warn) }

   sub validate_syntax2 {   my $self = shift;
$self->{gedcom}{validate_callback}->($self)     if defined
$self->{gedcom}{validate_callback};   my $items = [ @{$self->{items}} ];
$I++;   my $grammar = $self->{grammar};   print "  " x $I .
"validate_syntax2($grammar->{tag})\n" if $D;   my $warn = "";   my $file =
$self->{gedcom}{record}{file};   my $here = "$file:$self->{line}:
$self->{tag}" .               (defined $self->{xref} ? " $self->{xref}" :
"");   for my $item (@$items)   {     print "  " x $I . "level
$item->{level} on $self->{level}\n" if $D;     $warn .= "$here: Can't add
level $item->{level} to $self->{level}\n"       if $item->{level} >
$self->{level} + 1;   }   for my $item (@{$grammar->{items}})   {     my
$min = $item->min;     my $max = $item->max;     my ($matches, $w) =
$self->validate_grammar($item, $items, 1);     $warn .= $w;     my $value
= $item->{tag} || $item->{structure}{structure};     my $msg = "$here has
$matches $value" . ($matches == 1 ? "" : "s");     print "  " x $I . "$msg
- minimum is $min maximum is $max\n" if $D;     $warn .= "$msg - minimum
is $min\n" if $matches < $min;     $warn .= "$msg - maximum is $max\n" if
$matches > $max && $max;   }   if (@$items)   {     my %tags = map { $_ =>
1 } $grammar->items;     for my $c (@$items)     {       my $tag =
$c->{tag};       my $msg = exists $tags{$tag} ? "an extra" : "not a";
$warn .= "$file:$c->{line}: $tag is $msg item of $self->{tag}\n"
unless $tag eq "CONT" || $tag eq "CONC" || substr($tag, 0, 1) eq "_";     }
 }   $I-;   $warn } =end

Perl extension for plotting position tracks onto a world map.
*************************************************************

NAME
====

   Geo::GNUPlot - Perl extension for plotting position tracks onto a world
map.

SYNOPSIS
========

     use Geo::GNUPlot;

     $option_HR={
     		'grid_file' => '/home/test/grid_file',
     		'map_file' => '/home/test/map_file',
     		'gnuplot' => '/usr/local/gnuplot',
     		};

     $plot_obj=Geo::GNUPlot->new($option_HR);

     $track_AR=[
     		[15, 50], #x,y pair
     		[5.3, 10.2],
     		[-2, -5]
     	  ];

     or

     $track_AR=[
     		[50, N, 15, E], #latitude, lat. direction, longitude, long. direction
     		[10.2, N, 5.3, E],
     		[5, S, 2, W]
     	  ];

     $output_file='/home/test/plot.gif';

     $plot_option_HR={
     		'x_pad' => 2, #default 0
     		'y_pad' => 3, #default 0
     		'x_scale' => 5, #default 1
     		'y_scale' => 4, #default 1
     		'title' => 'Example Plot', #default 'Storm Tracking Map'
     		'term' => 'gif', #default gif  {any valid gnuplot term argument}
     		'temp_dir' => '/home/tmp/', #default '/tmp/'
     		};

     #Create the plot.
     ($success, $error)=$plot_obj->plot_track($track_AR, $output_file, $plot_option_HR);

     ####
     #For diagnostic purposes, create a contour and surface plot of the radius function.

     $contour_plot='/home/test/radius_contour.gif';

     $surface_plot='/home/test/radius_surface.gif';

     #Only the temp_dir, and term option values will be used.
     ($success,$error)=$plot_obj->plot_radius_function($contour_plot, $surface_plot, $plot_option_HR);

     ####
     #Determine the radius function value at a given position.
     $position_AR=[5.3, 10.2];

     or

     $position_AR=[10.2, N, 5.3, E];

     ($function_value, $error)=$plot_obj->radius_function($position_AR);

DESCRIPTION
===========

   This program plots a set of latitude/longitude pairs as a track on a
world map using gnuplot.  The plot radius is determined by a user defined
radius function.

IMPLEMENTATION
==============

   This program utilizes gnuplot by generating temporary gnuplot
configuration files and then running gnuplot on these files.  The
knowledge of what xrange and yrange to use in the gnuplot configuration
files is determined by a user defined radius function, an x and y padding,
and an x and y scaling of the radius function.

   The radius function is controlled by user defined node values on a user
defined irregular grid.  Values between the nodes are computed using two
dimensional linear interpolation.  I used Numerical Recipes in Fortran 77
page 117 equations 3.6.3, 3.6.4, and 3.6.5 as a reference.  It is a simple
formula and can be derived from scratch without too much effort.  If you
don't like this approach then simply override the radius_function method
with your own.  Better yet, provide your improved version to the current
maintainer of this package.  In the event Jimmy Carpenter (myself) is
still the maintainer, offer to take over!

   The irregular grid and node values are set in the grid_file file.  An
example is shown below:

     #xtics must be numerically ascending
     xtics: -170, -70, -50, -30, -10, 30, 180
     #ytics must be numerically descending
     ytics: 90, 80, 60, 40, 20, 0, -60, -90
     #
     radius_grid:
     5	4	5	5	8	8	9
     5	4	5	5	8	8	9
     5	4	5	5	8	8	2
     5	6	5	5	6	3	9
     5	4	8	5	8	8	2
     5	3	5	5	7	8	9
     5	4	5	5	8	8	6
     5	4	5	5	8	8	9

   To see what this looks like, just cut and paste this example into a file
and generate a contour and surface plot using the plot_radius_function
method.  To see how this function affects the plot window try out the
plot_track method for various positions.

   The objective of the radius function approach is to allow the user to
correlate interest level to plot zoom level. In the event you live in
Houston you probably don't care too much about how close a hurricane is to
some small deserted island in the Atlantic Ocean.  Your concern will be
how close the hurricane is to your home in Houston.  It is also possible
to create a radius function that insures a plot of a hurricane in the
middle of the Atlantic Ocean has a wide enough plot window to show some
land that provides context.

CONSTRUCTOR
===========

new (HASH_REF)
     Creates and returns a new `Geo::GNUPlot' object.  If unsuccessful it
     returns an undefined value.  The mandatory hash reference argument
     should contain the following keys and associated values:

          grid_file:  contains path to the grid file
          map_file:  contains a 2D map of the world (provided with bundle)
          gnuplot:  contains path to gnuplot executable

METHODS
=======

plot_track(TRACK_ARRAY_REF, OUTPUT_FILE, OPTION_HASH_REF)
     Creates a plot of the position track provided by the TRACK_ARRAY_REF
     and outputs it to the OUTPUT_FILE filename.  The plot configuration
     options are contained in the OPTION_HASH_REF.

     The plot_track method returns an array of the form (SUCCESS, ERROR).
     SUCCESS indicates if the method successfully generated a plot.  ERROR
     contains the reason for any failure.  If the method was successful
     ERROR will be undefined.

     The TRACK_ARRAY_REF is an array of position arrays.  The position
     arrays can be either x,y pairs, or an array of the form (LATTITUDE,
     LATTITUDE_DIR, LONGITUDE, LONGITUDE_DIR).  The plot will be centered
     around the first position in the TRACK_ARRAY_REF.

     The OUTPUT_FILE is the full path of the filename to use as output.

     The OPTION_HASH_REF contains configuration options for the plot.  The
     valid option keys, descriptions, and default values are given below.

          x_pad:		Determines the additional X padding for the plot.
          		Defaults to 1.

          y_pad:		Determines the additional Y padding for the plot.
          		Defaults to 1.

          x_scale:	Scales the radius value returned by the
          		radius_function method for use in determining
          		the xrange of the plot.
          		Defaults to 1.

          y_scale:	Scales the radius value returned by the
          		radius_function method for use in determining
          		the yrange of the plot.
          		Defaults to 1.

          title:		Sets the plot title.
          		Defaults to 'Storm Tracking Map'.

          term:		Sets the gnuplot terminal type.  See gnuplot
          		documentation for more details.
          		Defaults to 'gif'.

          temp_dir:	Sets the directory to use for writing temporary
          		configuration and data files.
          		Defaults to '/tmp/'.

plot_radius_function(CONTOUR_OUTPUT_FILE, SURFACE_OUTPUT_FILE, OPTION_HASH_REF)
     Creates a 2D contour and 3D surface plot of the radius function.  This
     enables the user to better visualize the radius function and how it is
     being interpolated from the provided node values.  The 2D contour
     plot overlays the world map provided by the map_file during
     construction of the `Geo::GNUPlot' object.

     The CONTOUR_OUTPUT_FILE is the full path of the filename to use for
     the contour plot.

     The SURFACE_OUTPUT_FILE is the full path of the filename to use for
     the surface plot.

     The OPTION_HASH_REF is identical in format to that used for the
     plot_track method, except only the temp_dir and term key value pairs
     are needed or required.

     The plot_radius_function method returns an array of the form
     (SUCCESS, ERROR).  SUCCESS indicates if the method successfully
     generated the plots.  ERROR contains the reason for any failure.  If
     the method was successful ERROR will be undefined.

radius_function(POSITION_ARRAY_REF)
     Provides direct access to the radius_function internally used to
     compute plot window sizes.  This can be useful for things such as
     sorting positions by interest level or debugging changes to the
     radius function.

     The POSITION_ARRAY_REF has the same two possible forms as each
     element of the TRACK_ARRAY_REF argument of the plot_track method.

AUTHOR
======

   James Lee Carpenter, Jimmy.Carpenter@chron.com

SEE ALSO
========

     Geo::StormTracker
     gnuplot
     perl(1).

ADDITIONAL REFERENCES
=====================

gnuplot
          http://www.cs.dartmouth.edu/gnuplot_info.html
                  http://members.theglobe.com/gnuplot/
                  http://www.geocities.com/SiliconValley/Foothills/6647/

linear interpolation
          Numerical Recipes in Fortran 77
          Second Edition
          (The Art of Scientific Computing)
          Authors:  William H. Press
          	  William T. Vettering
          	  Saul A. Teukolsky
          	  Brian P. Flannery
          Pub:  Cambridge University Press
          ISBN:  0-521-43064-X
          Relevant Page:  117

Process aviation weather reports in the METAR format.
*****************************************************

NAME
====

   Geo::METAR - Process aviation weather reports in the METAR format.

SYNOPSIS
========

     use Geo::METAR;
     use strict;

     my $m = new Geo::METAR;
     $m->metar("KFDY 251450Z 21012G21KT 8SM OVC065 04/M01 A3010 RMK 57014");
     print $m->dump;

     exit;

DESCRIPTION
===========

   METAR reports are available on-line, thanks to the National Weather
Service.  Since reading the METAR format isn't easy for non-pilots, these
reports are relatively useles to the common man who just wants a quick
glace at the weather.

USAGE
=====

How you might use this
----------------------

   Here is how you *might* use the Geo::METAR module.

   One use that I have had for this module is to query the NWS METAR page
(using the LWP modules) at
http://weather.noaa.gov/cgi-bin/mgetmetar.pl?cccc=KFDY to get an
up-to-date METAR. Then, I scan thru the output, looking for what looks
like a METAR string (that's not hard in Perl). Oh, KFDY can be any site
location code where there is a reporting station.

   I then pass the METAR into this module and get the info I want. I can
then update my home page with the current temperature, sky conditions, or
whatnot.

Functions
---------

   The following functions are defined in the AcctInfo module. Most of
them are *public*, meaning that you're supposed to use them. Some are
private, meaning that you're not supposed to use them - but I won't stop
you. Assume that functions are *public* unless otherwise documented.

metar()
     metar() is the function to whwich you should pass a METAR string.  It
     will take care of decomposing it into its component parts converting
     the units and so on.

     Example: `$m->metar("KFDY 251450Z 21012G21KT 8SM OVC065 04/M01 A3010
     RMK 57014");'

debug()
     debug() toggles debugging messages. By default, debugging is turned
     *off*. Turn it on if you are developing METAR or having trouble with
     it.

     debug() understands all of the folloing:

          Enable       Disable
          ------       -------
            1             0
          'yes'         'no'
          'on'          'off'

     If you contact me for help, I'll likely ask you for some debugging
     output.

     Example: `$m->debug(1);'

dump()
     dump() will dump the internal data structure for the METAR in a
     semi-human readable format.

     Example: `$m->dump;'

version()
     version() will print out the current version.

     Example: `print $m->version;'

_tokenize()
     PRIVATE

     Called internally to break the METAR into its component tokens.

_process()
     PRIVATE

     Used to make sense of the tokens found in _tokenize().

Variables
---------

   After you've called metar(), you'd probably like to get at the
individual values for things like temperature, dew point, and so on. You
do that by accessing individual variables via the METAR object.

   This section lists those variables and what they represent.

   If you call dump(), you'll find that it spits all of these out in
roughly this order, too.

VERSION
     The version of METAR.pm that you're using.

METAR
     The actual, raw METAR.

TYPE
     Report type: "METAR or SPECI".

SITE
     4-letter site code.

DATE
     The date on which the report was issued.

TIME
     The time at which the report was issued.

MOD
     Modifier (AUTO/COR) if any.

WIND_DIR_ENG
     The current wind direction in english (Southwest, East, North, etc.)

WIND_DIR_DEG
     The current wind direction in degrees.

WIND_KTS
     The current wind speed in Knots.

WIND_MPH
     The current wind speed in Miles Per Hour.

WIND_GUST_KTS
     The current wind gusting speed in Knots.

WIND_GUST_MPH
     The current wind gusting speed in Miles Per Hour.

VISIBILITY
     Visibility information.

WIND
     Wind information.

RUNWAY
     Runway information.

WEATHER
     Current weather.

SKY
     Current sky conditions.

TEMP_C
     Temperature in Celsius.

TEMP_F
     Temperature in Farenheit.

C_DEW
     Dew point in Celsius.

F_DEW
     Dew point in Farenheit.

ALT
     Altimeter setting (barometric pressure).

REMARKS
     Any remarks in the report.

NOTES
=====

   Test suite is small and incomplete. Needs work yet.

   Older versions of this module were installed as "METAR" instaed of
"Geo::METAR"

Adding a find() method.
-----------------------

   I should add a function called find() which can be passed a big chunk
of text (or a ref to one) and a site identifier. It will scan through the
text and find the METAR. The result can be fed back into this module for
processing.

   That'd be cool, I think.

BUGS
====

   There currently aren't any known BUGS (features which don't work as
advetised). There are lacking features. See the TODO section for more on
that.

TODO
====

   There is a TODO file included in the Geo::METAR distribution listing
the outstanding tasks that I or others have devised. Please check that
list before you submit a bug report or request a new feture. It might
already be on the TODO list.

AUTHOR AND COPYRIGHT
====================

   Copyright 1997-2000, Jeremy D. Zawodny <Jeremy@Zawodny.com>

   Geo::METAR is covered under the GNU Public License (GPL) version 2 or
later.

   The Geo::METAR Web site is located at:

     http://www.wcnet.org/~jzawodn/perl/Geo-METAR/

CREDITS
=======

   In addition to my work on Geo::METAR, I've received ideas, help, and
patches from the following folks:

     * Otterboy <jong@watchguard.com>

     Random script fixes and initial debugging help

     * Remi Lefebvre <remi@solaria.dhis.org>

     Debian packaging as libgeo-metar-perl.deb.

     * Mike Engelhart <mengelhart@earthtrip.com>

     Wind direction naming corrections.

     * Michael Starling <mstarling@logic.bm>

     Wind direction naming corrections.

     * Hans Einar Nielssen <hans.einar@nielssen.com>

     Wind direction naming corrections.

     * Nathan Neulinger <nneul@umr.edu>

     Lots of enhancements and corrections. Too many to list here.

Perl bundle for working with national weather advisories
********************************************************

NAME
====

   Geo::StormTracker - Perl bundle for working with national weather
advisories

SYNOPSIS
========

   See documentation of each module of the bundle.  This currently
includes the following:

     Geo::StormTracker::Main
     Geo::StormTracker::Data
     Geo::StormTracker::Advisory
     Geo::StormTracker::Parser

DESCRIPTION
===========

   The Storm-Tracker perl bundle is designed to track weather events using
the national weather advisories.  The original intent is to track tropical
depressions, storms and hurricanes.

AUTHOR
======

   James Lee Carpenter, Jimmy.Carpenter@chron.com

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

   Thanks to Dr. Paul Ruscher for his assistance in helping me to
understand the weather advisory formats.

SEE ALSO
========

     Geo::StormTracker::Advisory
     Geo::StormTracker::Parser
     Geo::StormTracker::Main
     Geo::StormTracker::Data
     perl(1).

The weather advisory object of the perl Storm-Tracker bundle.
*************************************************************

NAME
====

   Geo::StormTracker::Advisory - The weather advisory object of the perl
Storm-Tracker bundle.

SYNOPSIS
========

     use Geo::StormTracker::Advisory;

     #Create a new advisory object for holding
     #all the various elements of an advisory.
             $adv_obj=StormTracker::Advisory->new();

     #Return the entire advisory as a string.
     #Internally calls stringify_header and
     #stringify_body and joins the result.
     $adv_obj->stringify();

     All of the following methods can be used as both access and as assignment methods.
     The use and functionality of the methods should be obvious.

   It is important to realize that changes to a given attribute do not
affect other attributes.  It is the role of the caller to keep the content
self consistent.

     #Obtain the header as a string.
             $header_string=$adv_obj->stringify_header();

     #Change the contents of the header string.
     #Returns new header contents.
     $header_string=$adv_obj->stringify_header($header_string);

     #Obtain the body as a string.
             $body_string=$adv_obj->stringify_body();

     #Change the contents of the body string.
     #Returns new body contents.
             $body_string=$adv_obj->stringify_body($body_string);

     #Obtain the name string.
             $name=$adv_obj->name();

     #Change the name string.
     #Returns new name string.
             $name=$adv_obj->name($name);

     #Obtain the wmo header string.
             $wmo_header=$adv_obj->wmo_header();

     #Change the wmo header string.
     #Returns new wmo header string.
             $wmo_header=$adv_obj->wmo_header($wmo_header);

     #Obtain the advisory number value.
             $advisory_number=$adv_obj->advisory_number();

     #Change the advisory number value.
     #Returns the new advisory number.
             $advisory_number=$adv_obj->advisory_number($advisory_number);

     #Obtain the release time string.
     $release_time=$adv_obj->release_time();

     #Change the release time string.
     #Returns the new release time string.
     $release_time=$adv_obj->release_time($release_time);

     #Obtain the epoch date in seconds.
     $epoch_date=$adv_obj->epoch_date();

     #Change the epoch date.
     #Returns the new epoch date in seconds.
     $epoch_date=$adv_obj->epoch_date($epoch_date);

     #Obtain the weather service string.
             $weather_service=$adv_obj->weather_service();

     #Change the weather service string.
     #Returns the new weather service string.
             $weather_service=$adv_obj->weather_service($weather_service);

     #Obtain the position array or array reference.
             @position=$adv_obj->position();
     or
     $positon_AR=$adv_obj->position();

     #Change the position array.
     #Returns the new position array or array reference.
             @position=$adv_obj->position($position_AR);
     or
     $position_AR=$adv_obj->position($position_AR);

     #Obtain the maximum wind value.
             $max_winds=$adv_obj->max_winds($max_winds);

     #Change the maximum wind value.
     #Returns the new maximum wind value.
     $max_winds=$adv_obj->max_winds($max_winds);

     #Obtain the minimum central pressure value.
             $min_central_pressure=$adv_obj->min_central_pressure();

     #Change the minimum central pressure value.
     #Returns the new minimum central pressure value.
             $min_central_pressure=$adv_obj->min_central_pressure($min_central_pressure)

     #Determine whether or not the advisory says it is the last one.
             $is_final=$adv_obj->is_final();

     #Change the is_final value.
     #Returns the new is_final value.
             $is_final=$adv_obj->min_central_pressure($is_final)

DESCRIPTION
===========

   The Geo::StormTracker::Advisory module is a component of the
Storm-Tracker perl bundle.  The Storm-Tracker perl bundle is designed to
track weather events using the national weather advisories.  The original
intent is to track tropical depressions, storms and hurricanes.  A
Geo::StormTracker::Advisory object is designed to contain everything about
a single advisory.  The Geo::StormTracker::Advisory objects are typically
created and populated by the read methods of a Geo::StormTracker::Parser
object.

CONSTRUCTOR
===========

new
     Creates a `Geo::StormTracker::Advisory' object and returns a blessed
     reference to it.

METHODS
=======

stringify
     Returns the entire advisory.  Internally calls stringify_header and
     stringify_body and joins the result.

   The remaining methods function as both assignment and access methods.
When called with an argument, they act as assignment methods and when
called without an argument they act as access methods.

   When successfully called as assignment methods the return value is that
of the newly assigned value. If the assignment is unsuccessful the return
value will be undefined.

   The attribute set/retrieved is identical to the method name.

stringify_header ([STRING])
     Returns a string value.

stringify_body ([STRING])
     Returns a string value.

wmo_header ([STRING])
     Returns a string value.

advisory_number ([VALUE])
     Returns a string value.

epoch_date ([STRING])
     Returns a string value.

weather_service ([STRING])
     Returns a string value.

position ([ARRAY_REF])
     Returns an array value when called in array context and an array
     reference when called in a scalar context.

max_winds ([VALUE])
     Returns a string value.

is_final ([BOOLEAN])
     Returns a boolean value.

AUTHOR
======

   James Lee Carpenter, Jimmy.Carpenter@chron.com

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

   Thanks to Dr. Paul Ruscher for his assistance in helping me to
understand the weather advisory formats.

SEE ALSO
========

     Geo::StormTracker::Main
     Geo::StormTracker::Data
     Geo::StormTracker::Parser
     perl(1).

The weather event object of the perl Storm-Tracker bundle.
**********************************************************

NAME
====

   Geo::StormTracker::Data - The weather event object of the perl
Storm-Tracker bundle.

SYNOPSIS
========

     use Geo::StormTracker::Data;

     #The only argument is the path for the data files of
     	#this new data object.
     #If the directory does not exist it will fail.

     ($data_object,$error)=Geo::StormTracker::Data->new('/data/1999/15');

     #The shiny_new method expects to create the last directory level of the path.
     #If the full path already exists it will fail.
     #The 2nd, 3rd, and 4th arguments are the region code, year, and event number respectively.
     ($data_object,$error)=Geo::StormTracker::Data->shiny_new('/data/1999/15', 'NT', 1999, 15);

     #The insert_advisory method inserts an advisory object
     	#into the data object.
     	#Unless the second argument is true, inserting an
     	#advisory with the same advisory number as a previously
     	#inserted advisory will fail.
            	#Second argument can be thought of as a force flag.

     	 ($success,$error)=$data_object->insert_advisory($adv_obj,[0|1])

     #Determine the last known position for this weather event.
     $position_AR=$data_object->current_position()

     ($long,$long_dir,$lat,$lat_dir)=@{$position_AR};

     #The postion_track method will return an
     #array of position array references.
     #sorted in advisory number order.
     #The position from the advisory with the smallest
             #advisory number will be in element 0 of @track.

     @track=$data_object->position_track();

     #Alternatively.

     $track_AR=$data_object->position_track();
     @track=@{$track_AR};

     #Retrieve the most current advisory available
     #for this data object.

     $adv_obj=$data_object->current_advisory;

     #Is this weather event still occurring?
     #$set_to will contain true(1) or false(0)
     #if called without any arguments.
     #Can be used as an assignment operator
     #if given an argument.
     #When used as an assignment operator it
     #returns the value to which it was set
     #if successful and undef otherwise.

     ($set_to,$error)=$data_object->is_active([[0|1]);

     #The all_advisory_objects method returns an array of
     #every weather event advisory available in the referenced
     #data object.
     #The order is identical
     #to that returned by the position_track method.

     @all_advisory_objects=$data_object->all_advisories();

     #Alternatively

     $all_advisory_objects_AR=$data_object->all_advisories();

     #The advisory_by_number method returns an advisory
     #object for the advisory number given as an argument.
     #If the advisory doesn't exist the method returns undef.

     $adv_obj_15=$data_object->advisory_by_number(15);

     #Returns the path to the data file directory of
     #this object.

     $path=$data_object->get_path();

     #Returns the region code corresponding to the data object.

     $region=$data_object->get_region();

     #Returns the year corresponding to the data object.

     $year=$data_object->get_year();

     #Returns the event number corresponding to the data object.

     $event_number=$data_object->get_event_number();

DESCRIPTION
===========

   The `Geo::StormTracker::Data' module is a component of the
Storm-Tracker perl bundle.  The Storm-Tracker perl bundle is designed to
track weather events using the national weather advisories.  The original
intent is to track tropical depressions, storms and hurricanes.  There
should be a `Geo::StormTracker::Data' object for each weather event being
stored and/or tracked.  The `Geo::StormTracker::Data' objects are managed
by `Geo::StormTracker::Main'.

CONSTRUCTOR
===========

new (PATHNAME)
     Creates a Geo::StormTracker::Data object.  This constructor method
     returns an array of the form (OBJECT,ERROR).  OBJECT being the newly
     created object if successful, and ERROR being any errors encountered
     during the attempt.

     The data set for this object is assumed to be contained within the
     directory specified by the mandatory PATHNAME argument.  In the event
     that a directory with the given PATHNAME does not exist, the method
     will fail.  Check to see if the OBJECT returned is defined.

     The motivation for having two constructor methods instead of one, is
     to help the caller maintain data integrity.

shiny_new (PATHNAME, REGION, YEAR, EVENT_NUMBER)
     Creates a Geo::StormTracker::Data object.  This constructor method
     returns an array of the form (OBJECT,ERROR).  OBJECT being the newly
     created object if successful, and ERROR being any errors encountered
     during the attempt.

     The data set for this object will be placed within the directory
     specified by the mandatory PATHNAME argument.  The method will only
     succeed if the directory with the given PATHNAME does not already
     exist.

     The shiny_new method only knows how to create the last level
     directory.  The constructor does not attempt to recursively create a
     new directory and therefore will never succeed unless every directory
     in the path except the last one already exists.  Even then the
     creation of a new directory can fail due to permission problems.  It
     is wise to always check to insure that the OBJECT returned is defined.

     The motivation for having two constructor methods instead of one, is
     to help the caller maintain data integrity.

     The mandatory REGION, YEAR, and EVENT_NUMBER will be persistently
     stored within the Geo::StormTracker::Data object.  Their values can
     be accessed via the get_region, get_year, and get_event_number methods
     of Geo::StormTracker::Data objects.  The REGION, YEAR, and
     EVENT_NUMBER are not implicitly related to the PATH in any way.

METHODS
=======

insert_advisory (ADVISORY_OBJECT)
     Attempts to insert a `Geo::StormTracker::Advisory' object into the
     `Geo::StormTracker::Data' object being referenced.

     The method returns an array of the form (SUCCESS,ERROR).  SUCCESS
     being a boolean value indicating whether or not the operation was
     successful and ERROR being a scalar string reporting what error was
     encountered if any.

current_position
     When called in scalar context current_position returns a reference to
     a position array.

     When called in array context current_position returns a position
     array.

     The position array specifies the longitude and latitude of the most
     recent weather advisory available for this `Geo::StormTracker::Data'
     object.  The position array is of the form (LONGITUDE,N or
     S,LATITUDE, W or E).

     If the `Geo::StormTracker::Data' object being referenced contains no
     advisories at all the return value will be undefined.

position_track
     When called in scalar context position_track returns a reference to
     an array of position array references.

     When called in array context position_track returns an array of
     position array references.

     There is a position returned for each advisory within the
     `Geo::StormTracker::Data' object being referenced.  The position
     arrays returned are sorted by advisory number with the smallest
     advisory number first.

     The position arrays are identical in format to that returned by the
     current_position method.

current_advisory
     Returns a reference to the `Geo::StormTracker::Advisory' object
     within the `Geo::StormTracker::Data' object that has the greatest
     advisory number.

     If the `Geo::StormTracker::Data' object being referenced contains no
     advisories at all the return value will be undefined.

all_advisories
     When called in scalar context all_advisories returns a reference to
     an array of advisory objects.

     When called in array context all_advisories returns an array of
     advisory objects.

     The array of advisories is sorted by advisory number in the same
     order as that used by the position_track method.  The advisory with
     the smallest advisory number will be given first.

     If the `Geo::StormTracker::Data' object being referenced contains no
     advisories at all the return value will be undefined.

advisory_by_number (NUM)
     Returns a reference to the advisory object with the same advisory
     number as given by the mandatory NUM argument.

     If the `Geo::StormTracker::Data' object being referenced does not
     contain an advisory with the requested advisory number the return
     value will be undefined.

get_path
     Returns the path passed to the new method upon creation of the
     referenced `Geo::StormTracker::Data' object.

get_region
     Returns the region passed to the shiny_new method during the first
     creation of the referenced `Geo::StormTracker::Data' object.

get_year
     Returns the 4 digit year passed to the shiny_new method during the
     first creation of the referenced `Geo::StormTracker::Data' object.

get_event_number
     Returns the event number passed to the shiny_new method during the
     first creation of the referenced `Geo::StormTracker::Data' object.

is_active ([BOOLEAN])
     When called with a boolean argument is_active attempts to define the
     referenced `Geo::StormTracker::Data' object as active or inactive.
     is_active returns the array (SET_TO,ERROR).  If successful the SET_TO
     string indicates the value the state to which the data_object was set.
     If unsuccessful SET_TO will be undefined and ERROR will contain the
     reason for the failure.

     When is_active is called without an argument it will return the
     current state of the `Geo::StormTracker::Data' object being
     referenced.

AUTHOR
======

   Jimmy Carpenter, Jimmy.Carpenter@chron.com

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

   Thanks to Dr. Paul Ruscher for his assistance in helping me to
understand the weather advisory formats.

     =head1 SEE ALSO

   Geo::StormTracker::Main Geo::StormTracker::Parser
Geo::StormTracker::Advisory

   perl(1).

Master method of the Storm-Tracker perl bundle for dealing with Weather Advisories.
***********************************************************************************

NAME
====

   Geo::StormTracker::Main - Master method of the Storm-Tracker perl
bundle for dealing with Weather Advisories.

SYNOPSIS
========

     use Geo::StormTracker::Main;

     #Create a new main object.
     #The mandatory path argument determines the base path to
     #all the data files.
     $main_obj=Geo::StormTracker::Main->new('/archives/');

     #Add an advisory object to the database.
     #The advisory being added must be a recent advisory.
     #The add_advisory method will try and determine which
     #storm the advisory belongs to and update it accordingly.
     #Second argument can be thought of as a force flag.
     ($data_obj, $region_code, $year, $event_num, $error)=$main_obj->add_advisory($adv_obj,1);

     #Add an advisory object to the database for a
     #known year and weather event number.
     #Year must have four digits.
     #Weather event number (15th storm of 1999) says
     #which storm of the year this advisory is for.
     #This method can easily corrupt the database if given the wrong information.
     #Designed for use in initially loading and maintaining the database.
     ($data_obj, $year, $event_num,$error)=$main_obj->add_advisory_by_year_and_event($adv_obj,'1999','15');

     #Obtain a listing of data objects for every storm
     #by region (or just one region if desired).
     $region_code='NT'; #North Atlantic
     ($data_HR,$error)=$main_obj->all_storms_by_region($region_code);
     @data_objects_for_region_code=@{$data_HR->{$region_code}};

     #Obtain a listing of data objects for every active storm
     #by region (or just one region if desired).
     $region_code='NT'; #North Atlantic
     ($data_HR,$error)=$main_obj->all_active_storms_by_region($region_code);
     @active_data_objects_for_region_code=@{$data_HR->{$region_code}};

     #Obtain a listing of data objects including every current and active storm
     #keyed by region (or just one region of desired).
     $region_code='NT'; #North Atlantic
     ($mday,$mon,$year)=(gmtime(time))[3,4,5];
     $epoch_date = timegm(0,0,0,$mday,$mon,$year);
     $epoch_retire=$epoch_date-3600*24*5;# 5 days ago or younger
     ($data_HR, $error)=$main_obj->current_storms_by_region($epoch_retire, $region_code);

     #Obtain a listing of data objects for every active storm
             #by region and year (or just one region and/or year if desired).
             $region_code='NT'; #North Atlantic
     $year=1999;
             ($data_HR,$error)=$main_obj->all_storms_by_region_and_year($region_code,$year);
             @active_data_objects_for_region_code_and_year=@{$data_HR->{$region_code}->{$year}};

     #Obtain the data object for a specific storm.
     $region_code='NT'; #North Atlantic
     $year=1999;
     $event_number=15; #15th storm of the year.
     ($data_obj,$error)=$main_obj->specific_storm($region_code,$year,$event_number);

DESCRIPTION
===========

   The `Geo::StormTracker::Main' module is a component of the
Storm-Tracker perl bundle.  The Storm-Tracker perl bundle is designed to
track weather events using the national weather advisories.  The original
intent is to track tropical depressions, storms and hurricanes.  There
should be a `Geo::StormTracker::Data' object for each weather event being
stored and/or tracked.  The `Geo::StormTracker::Data' objects are managed
by `Geo::StormTracker::Main'.

CONSTRUCTOR
===========

new (PATHNAME)
     Creates a Geo::StormTracker::Main object.  This constructor method
     returns an array of the form (OBJECT,ERROR).  OBJECT being the newly
     created object if successful, and ERROR being any errors encountered
     during the attempt.

     The entire data set for this object is assumed to be contained within
     the directory specified by the mandatory PATHNAME argument.  In the
     event that a directory with the given PATHNAME does not exist, the
     method will fail.  Check to see if the OBJECT returned is defined.

     =back

METHODS
=======

add_advisory (ADVISORY_OBJECT,[FORCE])
     Attempts to insert a `Geo::StormTracker::Advisory' object into the
     appropriate `Geo::StormTracker::Data' object.  The
     `Geo::StormTracker::Main' object looks at the most recent storms for
     the advisory's region and tries to figure out which storm it belongs
     to.  Once it determines this it inserts the advisory into the storm
     object it determined was associated with the storm.  If necessary it
     will create a new data object to hold the advisory The optional force
     flag argument is passed on to the insert_advisory method of
     `Geo::StormTracker::Data'.

     The method returns an array of the form (DATA_OBJECT, REGION, YEAR,
     EVENT_NUMBER ,ERROR).  DATA_OBJECT being the
     `Geo::StormTracker::Data' object the advisory was successfully
     inserted into.  If add_advisory was unsuccessful the DATA_OBJECT will
     be undefined.  The REGION, YEAR and EVENT_NUMBER are the region code,
     year and event number of the DATA_OBJECT if the method was successful
     and undefined otherwise.  ERROR is a text string reporting what error
     was encountered if any.

add_advisory_by_year_and_event (ADVISORY_OBJECT, YEAR, EVENT_NUMBER, [FORCE])
     Attempts to insert a `Geo::StormTracker::Advisory' object into the
     appropriate `Geo::StormTracker::Data' object.  The
     `Geo::StormTracker::Main' object uses the data object corresponding
     to the year and event number specified as arguments.  The optional
     force flag argument is passed on to the insert_advisory method of
     `Geo::StormTracker::Data'.  If an appropriate data object can not be
     found, one will be created.

     The method returns an array of the form (SUCCESS, ERROR).  SUCCESS
     being a boolean value indicating whether or not the operation was
     successful and ERROR being a scalar string reporting what error was
     encountered if any.

all_storms_by_region ([REGION_CODE])
     Returns an array of the form (HASH_REF,ERROR).  HASH_REF being a
     reference to a hash of references to arrays of
     `Geo::StormTracker::Data' objects.  HASH_REF will be keyed by region
     code.  If the optional REGION_CODE argument was given then the region
     given will be the only key available in the returned HASH_REF,
     otherwise there will be a key for every region the
     `Geo::StormTracker::Main' object knows about.  The arrays of
     `Geo::StormTracker::Data' objects being referenced will be sorted by
     year and weather event order.  Both inactive and active storms will
     be listed in the data object arrays.

     The scalar ERROR string contains any errors encountered if
     unsuccessful.  The HASH_REF will be undefined in this case.

all_storms_by_region_and_year ([REGION_CODE,[YEAR]])   Returns an array of the form (HASH_REF,ERROR). HASH_REF being a reference to a hash of references to references to arrays of `Geo::StormTracker::Data' objects.  HASH_REF will be keyed by region code and year.  If the optional REGION_CODE argument was given then the region given will be the only key available in the returned HASH_REF, otherwise there will be a key for every region the `Geo::StormTracker::Main' object knows about.  Nested within each region key will be hash reference with a key for every year of data (or just one if the optional YEAR argument was used). The arrays of `Geo::StormTracker::Data' objects being referenced will be sorted by weather event order.  Both inactive and active storms will be listed in the data object arrays.   The scalar ERROR string contains any errors encountered if unsuccessful.  The HASH_REF will be undefined in this case.
all_active_storms_by_region([REGION_CODE])
     Returns an array of the form (HASH_REF,ERROR).  HASH_REF being a
     reference to a hash of references to arrays of
     `Geo::StormTracker::Data' objects.  HASH_REF will be keyed by region
     code.  If the optional REGION_CODE argument was given then the region
     given will be the only key available in the returned HASH_REF,
     otherwise there will be a key for every region the
     `Geo::StormTracker::Main' object knows about.  The arrays of
     `Geo::StormTracker::Data' objects being referenced will be sorted by
     year and weather event order.  Only active storms will be listed in
     the data object arrays.

     The scalar ERROR string contains any errors encountered if
     unsuccessful.  The HASH_REF will be undefined in this case.

all_current_storms_by_region([EPOCH_RETIRE,[REGION_CODE]])   Returns an array of the form (HASH_REF,ERROR). HASH_REF being a reference to a hash of references to arrays of `Geo::StormTracker::Data' objects.  HASH_REF will be keyed by region code.  If the optional REGION_CODE argument was given then the region given will be the only key available in the returned HASH_REF, otherwise there will be a key for every region the `Geo::StormTracker::Main' object knows about.  The arrays of `Geo::StormTracker::Data' objects being referenced will be sorted by year and weather event order.  Only active storms and storms with current advisories whose epoch_date is greater than or equal to EPOCH_RETIRE will be listed in the data object arrays.   The scalar ERROR string contains any errors encountered if unsuccessful.  The HASH_REF will be undefined in this case.
specific_storm (REGION_CODE, YEAR, EVENT_NUMBER)
     Returns an array of the form (DATA_OBJECT, ERROR).  DATA_OBJECT being
     a reference to a `Geo::StormTracker::Data' object for the desired
     REGION_CODE, YEAR, and weather EVENT_NUMBER.

     The scalar ERROR string contains any errors encountered if
     unsuccessful.

AUTHOR
======

   Jimmy Carpenter, Jimmy.Carpenter@chron.com

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

   Thanks to Dr. Paul Ruscher for his assistance in helping me to
understand the weather advisory formats.

SEE ALSO
========

     Geo::StormTracker::Data
     Geo::StormTracker::Advisory
     Geo::StormTracker::Parser
     perl(1).

Perl extension for Parsing Weather Advisories
*********************************************

NAME
====

   Geo::StormTracker::Parser - Perl extension for Parsing Weather
Advisories

SYNOPSIS
========

     use Geo::StormTracker::Parser;

     #Create a parser object
     $parser_obj=Geo::StormTracker::Parser->new();

     #Parse input and return a Geo::StormTracker::Advisory object.
     $adv_obj=$parser_obj->read(\*STDIN);

     #An alternative to the read method above,
     #which accepts the advisory as a string.
     $adv_obj=$parser_obj->read_data($advisory_data);

     #Same as above two methods but reads from a file instead.
     $adv_obj=$parser_obj->read_file($advisory_data);

DESCRIPTION
===========

   The Geo::StormTracker::Parser module is a component of the
Storm-Tracker perl bundle.  The Storm-Tracker perl bundle is designed to
track weather events using the national weather advisories.  The original
intent is to track tropical depressions, storms and hurricanes.  The
various read methods of Geo::StormTracker::Parser take a plain text
advisory as input and return Geo::StormTracker::Advisory objects.

CONSTRUCTOR
===========

new
     Creates a new instance of a Geo::StormTracker::Parser object and
     returns a blessed reference to it.

METHODS
=======

read (TYPEGLOB_REF)
     Reads from the type glob reference passed as an argument and returns
     a Geo::StormTracker::Advisory object if successful.  If unsuccessful
     the method returns an undefined value.

read_data (STRING)
     Attempts to parse the advisory text input as a string argument and
     returns a Geo::StormTracker::Advisory object if successful.  If
     unsuccessful the method returns an undefined value.

read_file (STRING)
     Reads an advisory saved in a file whose path is passed as a string
     argument and returns a Geo::StormTracker::Advisory object if
     successful.  If unsuccessful the method returns an undefined value.

AUTHOR
======

   James Lee Carpenter, Jimmy.Carpenter@chron.com

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

   Thanks to Dr. Paul Ruscher for his assistance in helping me to
understand the weather advisory formats.

SEE ALSO
========

     Geo::StormTracker::Advisory
     Geo::StormTracker::Main
     Geo::StormTracker::Data
     perl(1).

Perl bundle for working with national weather advisories
********************************************************

NAME
====

   Geo::Storm_Tracker - Perl bundle for working with national weather
advisories

SYNOPSIS
========

   See documentation of each module of the bundle.  This currently
includes the following:

     Geo::Storm_Tracker::Main
     Geo::Storm_Tracker::Data
     Geo::Storm_Tracker::Advisory
     Geo::Storm_Tracker::Parser

DESCRIPTION
===========

   The Storm-Tracker perl bundle is designed to track weather events using
the national weather advisories.  The original intent is to track tropical
depressions, storms and hurricanes.

AUTHOR
======

   James Lee Carpenter, Jimmy.Carpenter@chron.com

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

   Thanks to Dr. Paul Ruscher for his assistance in helping me to
understand the weather advisory formats.

SEE ALSO
========

     Geo::Storm_Tracker::Advisory
     Geo::Storm_Tracker::Parser
     Geo::Storm_Tracker::Main
     Geo::Storm_Tracker::Data
     perl(1).

The weather advisory object of the perl Storm-Tracker bundle.
*************************************************************

NAME
====

   Geo::Storm_Tracker::Advisory - The weather advisory object of the perl
Storm-Tracker bundle.

SYNOPSIS
========

     use Geo::Storm_Tracker::Advisory;

     #Create a new advisory object for holding
     #all the various elements of an advisory.
             $adv_obj=Storm_Tracker::Advisory->new();

     #Return the entire advisory as a string.
     #Internally calls stringify_header and
     #stringify_body and joins the result.
     $adv_obj->stringify();

     All of the following methods can be used as both access and as assignment methods.
     The use and functionality of the methods should be obvious.

   It is important to realize that changes to a given attribute do not
affect other attributes.  It is the role of the caller to keep the content
self consistent.

     #Obtain the header as a string.
             $header_string=$adv_obj->stringify_header();

     #Change the contents of the header string.
     #Returns new header contents.
     $header_string=$adv_obj->stringify_header($header_string);

     #Obtain the body as a string.
             $body_string=$adv_obj->stringify_body();

     #Change the contents of the body string.
     #Returns new body contents.
             $body_string=$adv_obj->stringify_body($body_string);

     #Obtain the name string.
             $name=$adv_obj->name();

     #Change the name string.
     #Returns new name string.
             $name=$adv_obj->name($name);

     #Obtain the wmo header string.
             $wmo_header=$adv_obj->wmo_header();

     #Change the wmo header string.
     #Returns new wmo header string.
             $wmo_header=$adv_obj->wmo_header($wmo_header);

     #Obtain the advisory number value.
             $advisory_number=$adv_obj->advisory_number();

     #Change the advisory number value.
     #Returns the new advisory number.
             $advisory_number=$adv_obj->advisory_number($advisory_number);

     #Obtain the release time string.
     $release_time=$adv_obj->release_time();

     #Change the release time string.
     #Returns the new release time string.
     $release_time=$adv_obj->release_time($release_time);

     #Obtain the weather service string.
             $weather_service=$adv_obj->weather_service();

     #Change the weather service string.
     #Returns the new weather service string.
             $weather_service=$adv_obj->weather_service($weather_service);

     #Obtain the position array or array reference.
             @position=$adv_obj->position();
     or
     $positon_AR=$adv_obj->position();

     #Change the position array.
     #Returns the new position array or array reference.
             @position=$adv_obj->position($position_AR);
     or
     $position_AR=$adv_obj->position($position_AR);

     #Obtain the maximum wind value.
             $max_winds=$adv_obj->max_winds($max_winds);

     #Change the maximum wind value.
     #Returns the new maximum wind value.
     $max_winds=$adv_obj->max_winds($max_winds);

     #Obtain the minimum central pressure value.
             $min_central_pressure=$adv_obj->min_central_pressure();

     #Change the minimum central pressure value.
     #Returns the new minimum central pressure value.
             $min_central_pressure=$adv_obj->min_central_pressure($min_central_pressure)

     #Determine whether or not the advisory says it is the last one.
             $is_final=$adv_obj->is_final();

     #Change the is_final value.
     #Returns the new is_final value.
             $is_final=$adv_obj->min_central_pressure($is_final)

DESCRIPTION
===========

   The Geo::Storm_Tracker::Advisory module is a component of the
Storm-Tracker perl bundle.  The Storm-Tracker perl bundle is designed to
track weather events using the national weather advisories.  The original
intent is to track tropical depressions, storms and hurricanes.  A
Geo::Storm_Tracker::Advisory object is designed to contain everything
about a single advisory.  The Geo::Storm_Tracker::Advisory objects are
typically created and populated by the read methods of a
Geo::Storm_Tracker::Parser object.

CONSTRUCTOR
===========

new
     Creates a `Geo::Storm_Tracker::Advisory' object and returns a blessed
     reference to it.

METHODS
=======

stringify
     Returns the entire advisory.  Internally calls stringify_header and
     stringify_body and joins the result.

   The remaining methods function as both assignment and access methods.
When called with an argument, they act as assignment methods and when
called without an argument they act as access methods.

   When successfully called as assignment methods the return value is that
of the newly assigned value. If the assignment is unsuccessful the return
value will be undefined.

   The attribute set/retrieved is identical to the method name.

stringify_header ([STRING])
     Returns a string value.

stringify_body ([STRING])
     Returns a string value.

wmo_header ([STRING])
     Returns a string value.

advisory_number ([VALUE])
     Returns a string value.

weather_service ([STRING])
     Returns a string value.

position ([ARRAY_REF])
     Returns an array value when called in array context and an array
     reference when called in a scalar context.

max_winds ([VALUE])
     Returns a string value.

is_final ([BOOLEAN])
     Returns a boolean value.

AUTHOR
======

   James Lee Carpenter, Jimmy.Carpenter@chron.com

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

   Thanks to Dr. Paul Ruscher for his assistance in helping me to
understand the weather advisory formats.

SEE ALSO
========

     Geo::Storm_Tracker::Main
     Geo::Storm_Tracker::Data
     Geo::Storm_Tracker::Parser
     perl(1).

The weather event object of the perl Storm-Tracker bundle.
**********************************************************

NAME
====

   Geo::Storm_Tracker::Data - The weather event object of the perl
Storm-Tracker bundle.

SYNOPSIS
========

     use Geo::Storm_Tracker::Data;

     #The only argument is the path for the data files of
     	#this new data object.
     #If the directory does not exist it will fail.

     ($data_object,$error)=Geo::Storm_Tracker::Data->new('/data/1999/15');

     #The only argument is the path for the data files of this
     #shiny new data object.
     #The shiny_new method expects to create the last directory level of the path.
     #If the full path already exists it will fail.
     ($data_object,$error)=Geo::Storm_Tracker::Data->shiny_new('/data/1999/15');

     #The insert_advisory method inserts an advisory object
     	#into the data object.
     	#Unless the second argument is true, inserting an
     	#advisory with the same advisory number as a previously
     	#inserted advisory will fail.
            	#Second argument can be thought of as a force flag.

     	 ($success,$error)=$data_object->insert_advisory($adv_obj,[0|1])

     #Determine the last known position for this weather event.
     $position_AR=$data_object->current_position()

     ($long,$long_dir,$lat,$lat_dir)=@{$position_AR};

     #The postion_track method will return an
     #array of position array references.
     #sorted in advisory number order.
     #The position from the advisory with the smallest
             #advisory number will be in element 0 of @track.

     @track=$data_object->position_track();

     #Alternatively.

     $track_AR=$data_object->position_track();
     @track=@{$track_AR};

     #Retrieve the most current advisory available
     #for this data object.

     $adv_obj=$data_object->current_advisory;

     #Is this weather event still occurring?
     #$set_to will contain true(1) or false(0)
     #if called without any arguments.
     #Can be used as an assignment operator
     #if given an argument.
     #When used as an assignment operator it
     #returns the value to which it was set
     #if successful and undef otherwise.

     ($set_to,$error)=$data_object->is_active([[0|1]);

     #The all_advisory_objects method returns an array of
     #every weather event advisory available in the referenced
     #data object.
     #The order is identical
     #to that returned by the position_track method.

     @all_advisory_objects=$data_object->all_advisories();

     #Alternatively

     $all_advisory_objects_AR=$data_object->all_advisories();

     #The advisory_by_number method returns an advisory
     #object for the advisory number given as an argument.
     #If the advisory doesn't exist the method returns undef.

     $adv_obj_15=$data_object->advisory_by_number(15);

     #Returns the path to the data file directory of
     #this object.

     $path=$data_object->get_path();

DESCRIPTION
===========

   The `Geo::Storm_Tracker::Data' module is a component of the
Storm-Tracker perl bundle.  The Storm-Tracker perl bundle is designed to
track weather events using the national weather advisories.  The original
intent is to track tropical depressions, storms and hurricanes.  There
should be a `Geo::Storm_Tracker::Data' object for each weather event being
stored and/or tracked.  The `Geo::Storm_Tracker::Data' objects are managed
by `Geo::Storm_Tracker::Main'.

CONSTRUCTOR
===========

new (PATHNAME)
     Creates a Geo::Storm_Tracker::Data object.  This constructor method
     returns an array of the form (OBJECT,ERROR).  OBJECT being the newly
     created object if successful, and ERROR being any errors encountered
     during the attempt.

     The data set for this object is assumed to be contained within the
     directory specified by the mandatory PATHNAME argument.  In the event
     that a directory with the given PATHNAME does not exist, the method
     will fail.  Check to see if the OBJECT returned is defined.

     The motivation for having two constructor methods instead of one, is
     to help the caller maintain data integrity.

shiny_new (PATHNAME)
     Creates a Geo::Storm_Tracker::Data object.  This constructor method
     returns an array of the form (OBJECT,ERROR).  OBJECT being the newly
     created object if successful, and ERROR being any errors encountered
     during the attempt.

     The data set for this object will be placed within the directory
     specified by the mandatory PATHNAME argument.  The method will only
     succeed if the directory with the given PATHNAME does not already
     exist.

     The shiny_new method only knows how to create the last level
     directory.  The constructor does not attempt to recursively create a
     new directory and therefore will never succeed unless every directory
     in the path except the last one already exists.  Even then the
     creation of a new directory can fail due to permission problems.  It
     is wise to always check to insure that the OBJECT returned is defined.

     The motivation for having two constructor methods instead of one, is
     to help the caller maintain data integrity.

METHODS
=======

insert_advisory (ADVISORY_OBJECT)
     Attempts to insert a `Geo::Storm_Tracker::Advisory' object into the
     `Geo::Storm_Tracker::Data' object being referenced.

     The method returns an array of the form (SUCCESS,ERROR).  SUCCESS
     being a boolean value indicating whether or not the operation was
     successful and ERROR being a scalar string reporting what error was
     encountered if any.

current_position
     When called in scalar context current_position returns a reference to
     a position array.

     When called in array context current_position returns a position
     array.

     The position array specifies the longitude and latitude of the most
     recent weather advisory available for this `Geo::Storm_Tracker::Data'
     object.  The position array is of the form (LONGITUDE,N or
     S,LATITUDE, W or E).

     If the `Geo::Storm_Tracker::Data' object being referenced contains no
     advisories at all the return value will be undefined.

position_track
     When called in scalar context position_track returns a reference to
     an array of position array references.

     When called in array context position_track returns an array of
     position array references.

     There is a position returned for each advisory within the
     `Geo::Storm_Tracker::Data' object being referenced.  The position
     arrays returned are sorted by advisory number with the smallest
     advisory number first.

     The position arrays are identical in format to that returned by the
     current_position method.

current_advisory
     Returns a reference to the `Geo::Storm_Tracker::Advisory' object
     within the `Geo::Storm_Tracker::Data' object that has the greatest
     advisory number.

     If the `Geo::Storm_Tracker::Data' object being referenced contains no
     advisories at all the return value will be undefined.

all_advisories
     When called in scalar context all_advisories returns a reference to
     an array of advisory objects.

     When called in array context all_advisories returns an array of
     advisory objects.

     The array of advisories is sorted by advisory number in the same
     order as that used by the position_track method.  The advisory with
     the smallest advisory number will be given first.

     If the `Geo::Storm_Tracker::Data' object being referenced contains no
     advisories at all the return value will be undefined.

advisory_by_number (NUM)
     Returns a reference to the advisory object with the same advisory
     number as given by the mandatory NUM argument.

     If the `Geo::Storm_Tracker::Data' object being referenced does not
     contain an advisory with the requested advisory number the return
     value will be undefined.

get_path
     Returns the path passed to the new method upon creation of the
     referenced `Geo::Storm_Tracker::Data' object.

is_active ([BOOLEAN])
     When called with a boolean argument is_active attempts to define the
     referenced `Geo::Storm_Tracker::Data' object as active or inactive.
     is_active returns the array (SET_TO,ERROR).  If successful the SET_TO
     string indicates the value the state to which the data_object was set.
     If unsuccessful SET_TO will be undefined and ERROR will contain the
     reason for the failure.

     When is_active is called without an argument it will return the
     current state of the `Geo::Storm_Tracker::Data' object being
     referenced.

AUTHOR
======

   Jimmy Carpenter, Jimmy.Carpenter@chron.com

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

   Thanks to Dr. Paul Ruscher for his assistance in helping me to
understand the weather advisory formats.

     =head1 SEE ALSO

   Geo::Storm_Tracker::Main Geo::Storm_Tracker::Parser
Geo::Storm_Tracker::Advisory

   perl(1).

Master method of the Storm-Tracker perl bundle for dealing with Weather Advisories.
***********************************************************************************

NAME
====

   Geo::Storm_Tracker::Main - Master method of the Storm-Tracker perl
bundle for dealing with Weather Advisories.

SYNOPSIS
========

     use Geo::Storm_Tracker::Main;

     #Create a new main object.
     #The mandatory path argument determines the base path to
     #all the data files.
     $main_obj=Geo::Storm_Tracker::Main->new('/archives/');

     #Add an advisory object to the database.
     #The advisory being added must be a recent advisory.
     #The add_advisory method will try and determine which
     #storm the advisory belongs to and update it accordingly.
     #Second argument can be thought of as a force flag.
     ($success,$error)=$main_obj->add_advisory($adv_obj,[0|1]);

     #Add an advisory object to the database for a
     #known year and weather event number.
     #Year must have four digits.
     #Weather event number (15th storm of 1999) says
     #which storm of the year this advisory is for.
     #This method can easily corrupt the database if given the wrong information.
     #Designed for use in initially loading and maintaining the database.
     ($success,$error)=$main_obj->add_advisory_by_year_and_event($adv_obj,'1999','15');

     #Obtain a listing of data objects for every storm
     #by region (or just one region if desired).
     $region_code='NT'; #North Atlantic
     ($data_HR,$error)=$main_obj->all_storms_by_region([$region_code]);
     @data_objects_for_region_code=@{$data_HR->{$region_code}};

     #Obtain a listing of data objects for every active storm
     #by region (or just one region if desired).
     $region_code='NT'; #North Atlantic
     ($data_HR,$error)=$main_obj->all_storms_by_region([$region_code]);
     @active_data_objects_for_region_code=@{$data_HR->{$region_code}};

     #Obtain the data object for a specific storm.
     $region_code='NT'; #North Atlantic
     $year=1999;
     $event_number=15; #15th storm of the year.
     ($data_obj,$error)=$main_obj->specific_storm($region_code,$year,$event_number);

DESCRIPTION
===========

   The `Geo::Storm_Tracker::Main' module is a component of the
Storm-Tracker perl bundle.  The Storm-Tracker perl bundle is designed to
track weather events using the national weather advisories.  The original
intent is to track tropical depressions, storms and hurricanes.  There
should be a `Geo::Storm_Tracker::Data' object for each weather event being
stored and/or tracked.  The `Geo::Storm_Tracker::Data' objects are managed
by `Geo::Storm_Tracker::Main'.

CONSTRUCTOR
===========

new (PATHNAME)
     Creates a Geo::Storm_Tracker::Main object.  This constructor method
     returns an array of the form (OBJECT,ERROR).  OBJECT being the newly
     created object if successful, and ERROR being any errors encountered
     during the attempt.

     The entire data set for this object is assumed to be contained within
     the directory specified by the mandatory PATHNAME argument.  In the
     event that a directory with the given PATHNAME does not exist, the
     method will fail.  Check to see if the OBJECT returned is defined.

     =back

METHODS
=======

add_advisory (ADVISORY_OBJECT,[FORCE])
     Attempts to insert a `Geo::Storm_Tracker::Advisory' object into the
     appropriate `Geo::Storm_Tracker::Data' object.  The
     `Geo::Storm_Tracker::Main' object looks at the most recent storms for
     the advisory's region and tries to figure out which storm it belongs
     to.  Once it determines this it inserts the advisory into the storm
     object it determined was associated with the storm.  If necessary it
     will create a new data object to hold the advisory The optional force
     flag argument is passed on to the insert_advisory method of
     `Geo::Storm_Tracker::Data'.

     The method returns an array of the form (SUCCESS,ERROR).  SUCCESS
     being a boolean value indicating whether or not the operation was
     successful and ERROR being a scalar string reporting what error was
     encountered if any.

add_advisory_by_year_and_event (ADVISORY_OBJECT, YEAR, EVENT_NUMBER, [FORCE])
     Attempts to insert a `Geo::Storm_Tracker::Advisory' object into the
     appropriate `Geo::Storm_Tracker::Data' object.  The
     `Geo::Storm_Tracker::Main' object uses the data object corresponding
     to the year and event number specified as arguments.  The optional
     force flag argument is passed on to the insert_advisory method of
     `Geo::Storm_Tracker::Data'.  If an appropriate data object can not be
     found, one will be created.

          The method returns an array of the form (SUCCESS,ERROR).
          SUCCESS being a boolean value indicating whether or not
          the operation was successful and ERROR being a scalar
          string reporting what error was encountered if any.

all_storms_by_region ([REGION_CODE])
     Returns an array of the form (HASH_REF,ERROR).  HASH_REF being a
     reference to a hash of references to arrays of
     `Geo::Storm_Tracker::Data' objects.  HASH_REF will be keyed by region
     code.  If the optional REGION_CODE argument was given then the region
     given will be the only key available in the returned HASH_REF,
     otherwise there will be a key for every region the
     `Geo::Storm_Tracker::Main' object knows about.  The arrays of
     `Geo::Storm_Tracker::Data' objects being referenced will be sorted by
     year and weather event order.  Both inactive and active storms will
     be listed in the data object arrays.

     The scalar ERROR string contains any errors encountered if
     unsuccessful.  The HASH_REF will be undefined in this case.

all_active_storms_by_region
     Returns an array of the form (HASH_REF,ERROR).  HASH_REF being a
     reference to a hash of references to arrays of
     `Geo::Storm_Tracker::Data' objects.  HASH_REF will be keyed by region
     code.  If the optional REGION_CODE argument was given then the region
     given will be the only key available in the returned HASH_REF,
     otherwise there will be a key for every region the
     `Geo::Storm_Tracker::Main' object knows about.  The arrays of
     `Geo::Storm_Tracker::Data' objects being referenced will be sorted by
     year and weather event order.  Only active storms will be listed in
     the data object arrays.

     The scalar ERROR string contains any errors encountered if
     unsuccessful.  The HASH_REF will be undefined in this case.

specific_storm (REGION_CODE, YEAR, EVENT_NUMBER)
     Returns an array of the form (DATA_OBJECT, ERROR).  DATA_OBJECT being
     a reference to a `Geo::Storm_Tracker::Data' object for the desired
     REGION_CODE, YEAR, and weather EVENT_NUMBER.

     The scalar ERROR string contains any errors encountered if
     unsuccessful.

AUTHOR
======

   Jimmy Carpenter, Jimmy.Carpenter@chron.com

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

   Thanks to Dr. Paul Ruscher for his assistance in helping me to
understand the weather advisory formats.

SEE ALSO
========

     Geo::Storm_Tracker::Data
     Geo::Storm_Tracker::Advisory
     Geo::Storm_Tracker::Parser
     perl(1).

Perl extension for Parsing Weather Advisories
*********************************************

NAME
====

   Geo::Storm_Tracker::Parser - Perl extension for Parsing Weather
Advisories

SYNOPSIS
========

     use Geo::Storm_Tracker::Parser;

     #Create a parser object
     $parser_obj=Geo::Storm_Tracker::Parser->new();

     #Parse input and return a Geo::Storm_Tracker::Advisory object.
     $adv_obj=$parser_obj->read(\*STDIN);

     #An alternative to the read method above,
     #which accepts the advisory as a string.
     $adv_obj=$parser_obj->read_data($advisory_data);

     #Same as above two methods but reads from a file instead.
     $adv_obj=$parser_obj->read_file($advisory_data);

DESCRIPTION
===========

   The Geo::Storm_Tracker::Parser module is a component of the
Storm-Tracker perl bundle.  The Storm-Tracker perl bundle is designed to
track weather events using the national weather advisories.  The original
intent is to track tropical depressions, storms and hurricanes.  The
various read methods of Geo::Storm_Tracker::Parser take a plain text
advisory as input and return Geo::Storm_Tracker::Advisory objects.

CONSTRUCTOR
===========

new
     Creates a new instance of a Geo::Storm_Tracker::Parser object and
     returns a blessed reference to it.

METHODS
=======

read (TYPEGLOB_REF)
     Reads from the type glob reference passed as an argument and returns
     a Geo::Storm_Tracker::Advisory object if successful.  If unsuccessful
     the method returns an undefined value.

read_data (STRING)
     Attempts to parse the advisory text input as a string argument and
     returns a Geo::Storm_Tracker::Advisory object if successful.  If
     unsuccessful the method returns an undefined value.

read_file (STRING)
     Reads an advisory saved in a file whose path is passed as a string
     argument and returns a Geo::Storm_Tracker::Advisory object if
     successful.  If unsuccessful the method returns an undefined value.

AUTHOR
======

   James Lee Carpenter, Jimmy.Carpenter@chron.com

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

   Thanks to Dr. Paul Ruscher for his assistance in helping me to
understand the weather advisory formats.

SEE ALSO
========

     Geo::Storm_Tracker::Advisory
     Geo::Storm_Tracker::Main
     Geo::Storm_Tracker::Data
     perl(1).

TIGER/Line geographic data
**************************

NAME
====

   Geo::TigerLine - TIGER/Line geographic data

DESCRIPTION
===========

   This is a module around the TIGER/Line geogrpahic data generated by the
U.S. Census.  TIGER/Line data files contain detailed information about
roads, waterways, political and property boundries, addresses, etc...
Basically everything you need to recreate something like Mapquest.

   *IT IS INCOMPLETE*

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

COPYRIGHT
=========

   Copyright (c) 2000 Michael G Schwern

   TIGER is a registered trademark of the US Census.

BUGS, CAVEATS and Other Musings
===============================

   Seeing as how TIGER is trademarked, I might want to call this module
something else.

SEE ALSO
========

   TIGER/Line data, manuals and additional info can be gotten from
ftp://ftp.linuxvc.com/US-map

   Bruce Perens's TIGER/Line mailing list is at
http://lists.perens.com/mailman/listinfo/map

Superclass for all TIGER/Line record classes.
*********************************************

NAME
====

   Geo::TigerLine::Record - Superclass for all TIGER/Line record classes.

SYNOPSIS
========

     package Geo::TigerLine::Record::42;
     use base qw(Geo::TigerLine::Record);

     $record = __PACKAGE__->new(\%fields);

DESCRIPTION
===========

   From this class all the specific TIGER/Line record classes inherit.  It
provides some of the basic methods common to all records.

   You shouldn't be here.

Methods
-------

new
          $record = __PACKAGE__->new(\%fields);

     A simple constructor.  Each field is passed through its accessor and
     sanity checked.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Geo/TigerLine,

TIGER/Line 1998 Complete Chain Basic Data Record
************************************************

NAME
====

   Geo::TigerLine::Record::1 - TIGER/Line 1998 Complete Chain Basic Data
Record

SYNOPSIS
========

     use Geo::TigerLine::Record::1;

     @records = Geo::TigerLine::Record::1->parse_file($fh);
     @records = Geo::TigerLine::Record::1->parse_file($fh, \&callback);

     $record = Geo::TigerLine::Record::1->new(\%fields);

     $record->rt();
     $record->version();
     $record->tlid();
     $record->side1();
     $record->source();
     $record->fedirp();
     $record->fename();
     $record->fetype();
     $record->fedirs();
     $record->cfcc();
     $record->fraddl();
     $record->toaddl();
     $record->fraddr();
     $record->toaddr();
     $record->friaddl();
     $record->toiaddl();
     $record->friaddr();
     $record->toiaddr();
     $record->zipl();
     $record->zipr();
     $record->fairl();
     $record->fairr();
     $record->trustl();
     $record->trustr();
     $record->census1();
     $record->census2();
     $record->statel();
     $record->stater();
     $record->countyl();
     $record->countyr();
     $record->fmcdl();
     $record->fmcdr();
     $record->fsmcdl();
     $record->fsmcdr();
     $record->fpll();
     $record->fplr();
     $record->ctl();
     $record->ctr();
     $record->blkl();
     $record->blkr();
     $record->frlong();
     $record->frlat();
     $record->tolong();
     $record->tolat();

DESCRIPTION
===========

   This is a class representing record type 1 of the TIGER/Line 1998
census geographic database.  Each object is one record.  It also contains
methods to parse TIGER/Line record type 1 files and turn them into objects.

   This is intended as an intermediate format between pulling the raw data
out of the simplistic TIGER/Line data files into something more
sophisticated (a process you should only have to do once).  As such, its
not very fast, but its careful, easy to use and performs some
verifications on the data being read.

   As this class is autogenerated by mk_parsers, think before you modify
this file.  Its OO, so consider sub-classing instead.

Accessors
---------

   These are simple get/set accessors for each field of a record generated
from the TIGER/Line 1998 data dictionary.  They perform some data
validation.

rt
          $data = $record->rt();
          $record->rt($data);

     Record Type.

     Expects alphanumeric data of no more than 1 characters.  $data cannot
     be blank and should be left justified.

version
          $data = $record->version();
          $record->version($data);

     Version Number.

     Expects numeric data of no more than 4 characters.  $data cannot be
     blank and should be left justified.

tlid
          $data = $record->tlid();
          $record->tlid($data);

     TIGER/Line ID, Permanent Record Number.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

side1
          $data = $record->side1();
          $record->side1($data);

     Single-Side Complete Chain Code.

     Expects numeric data of no more than 1 characters.  $data can be blank
     and should be right justified.

source
          $data = $record->source();
          $record->source($data);

     Linear Segment Source Code.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

fedirp
          $data = $record->fedirp();
          $record->fedirp($data);

     Feature Direction, Prefix.

     Expects alphanumeric data of no more than 2 characters.  $data can be
     blank and should be left justified.

fename
          $data = $record->fename();
          $record->fename($data);

     Feature Name.

     Expects alphanumeric data of no more than 30 characters.  $data can
     be blank and should be left justified.

fetype
          $data = $record->fetype();
          $record->fetype($data);

     Feature Type.

     Expects alphanumeric data of no more than 4 characters.  $data can be
     blank and should be left justified.

fedirs
          $data = $record->fedirs();
          $record->fedirs($data);

     Feature Direction, Suffix.

     Expects alphanumeric data of no more than 2 characters.  $data can be
     blank and should be left justified.

cfcc
          $data = $record->cfcc();
          $record->cfcc($data);

     Census Feature Class Code.

     Expects alphanumeric data of no more than 3 characters.  $data can be
     blank and should be left justified.

fraddl
          $data = $record->fraddl();
          $record->fraddl($data);

     Start Address, Left.

     Expects alphanumeric data of no more than 11 characters.  $data can
     be blank and should be right justified.

toaddl
          $data = $record->toaddl();
          $record->toaddl($data);

     End Address, Left.

     Expects alphanumeric data of no more than 11 characters.  $data can
     be blank and should be right justified.

fraddr
          $data = $record->fraddr();
          $record->fraddr($data);

     Start Address, Right.

     Expects alphanumeric data of no more than 11 characters.  $data can
     be blank and should be right justified.

toaddr
          $data = $record->toaddr();
          $record->toaddr($data);

     End Address, Right.

     Expects alphanumeric data of no more than 11 characters.  $data can
     be blank and should be right justified.

friaddl
          $data = $record->friaddl();
          $record->friaddl($data);

     Start Imputed Address Flag, Left.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

toiaddl
          $data = $record->toiaddl();
          $record->toiaddl($data);

     End Imputed Address Flag, Left.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

friaddr
          $data = $record->friaddr();
          $record->friaddr($data);

     Start Imputed Address Flag, Right.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

toiaddr
          $data = $record->toiaddr();
          $record->toiaddr($data);

     End Imputed Address Flag, Right.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

zipl
          $data = $record->zipl();
          $record->zipl($data);

     ZIP Code, Left.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

zipr
          $data = $record->zipr();
          $record->zipr($data);

     ZIP Code, Right.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

fairl
          $data = $record->fairl();
          $record->fairl($data);

     FIPS 55 Code (American Indian/Alaska Native Area), Current Left.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

fairr
          $data = $record->fairr();
          $record->fairr($data);

     FIPS 55 Code (American Indian/Alaska Native Area), Current Right.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

trustl
          $data = $record->trustl();
          $record->trustl($data);

     American Indian Trust Land Flag, Current Left.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

trustr
          $data = $record->trustr();
          $record->trustr($data);

     American Indian Trust Land Flag, Current Right.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

census1
          $data = $record->census1();
          $record->census1($data);

     Census Use 1.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

census2
          $data = $record->census2();
          $record->census2($data);

     Census Use 2.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

statel
          $data = $record->statel();
          $record->statel($data);

     FIPS State Code, Current Left.

     Expects numeric data of no more than 2 characters.  $data can be blank
     and should be left justified.

stater
          $data = $record->stater();
          $record->stater($data);

     FIPS State Code, Current Right.

     Expects numeric data of no more than 2 characters.  $data can be blank
     and should be left justified.

countyl
          $data = $record->countyl();
          $record->countyl($data);

     FIPS County Code, Current Left.

     Expects numeric data of no more than 3 characters.  $data can be blank
     and should be left justified.

countyr
          $data = $record->countyr();
          $record->countyr($data);

     FIPS County Code, Current Right.

     Expects numeric data of no more than 3 characters.  $data can be blank
     and should be left justified.

fmcdl
          $data = $record->fmcdl();
          $record->fmcdl($data);

     FIPS 55 Code (MCD/CCD) Left, Current.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

fmcdr
          $data = $record->fmcdr();
          $record->fmcdr($data);

     FIPS 55 Code (MCD/CCD) Right, Current.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

fsmcdl
          $data = $record->fsmcdl();
          $record->fsmcdl($data);

     FIPS 55 Code (Sub-MCD), Current Left.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

fsmcdr
          $data = $record->fsmcdr();
          $record->fsmcdr($data);

     FIPS 55 Code (Sub-MCD), Current Right.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

fpll
          $data = $record->fpll();
          $record->fpll($data);

     FIPS 55 Code (Incorporated Place), Current Left.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

fplr
          $data = $record->fplr();
          $record->fplr($data);

     FIPS 55 Code (Incorporated Place), Current Right.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

ctl
          $data = $record->ctl();
          $record->ctl($data);

     Census Tract Code, 1990 Left.

     Expects numeric data of no more than 6 characters.  $data can be blank
     and should be left justified.

ctr
          $data = $record->ctr();
          $record->ctr($data);

     Census Tract Code, 1990 Right.

     Expects numeric data of no more than 6 characters.  $data can be blank
     and should be left justified.

blkl
          $data = $record->blkl();
          $record->blkl($data);

     Census Block Number, 1990 Left.

     Expects alphanumeric data of no more than 4 characters.  $data can be
     blank and should be left justified.

blkr
          $data = $record->blkr();
          $record->blkr($data);

     Census Block Number, 1990 Right.

     Expects alphanumeric data of no more than 4 characters.  $data can be
     blank and should be left justified.

frlong
          $data = $record->frlong();
          $record->frlong($data);

     Start Longitude.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

frlat
          $data = $record->frlat();
          $record->frlat($data);

     Start Latitude.

     Expects numeric data of no more than 9 characters.  $data cannot be
     blank and should be right justified.

tolong
          $data = $record->tolong();
          $record->tolong($data);

     End Longitude.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

tolat
          $data = $record->tolat();
          $record->tolat($data);

     End Latitude.

     Expects numeric data of no more than 9 characters.  $data cannot be
     blank and should be right justified.

Data dictionary
---------------

   This is the original TIGER/Line 1998 data dictionary from which this
class was generated.

     Record Type 1 - Complete Chain Basic Data Record

          Field   BV  Fmt  Type  Beg  End  Len  Description
             RT   No    L     A    1    1    1  Record Type
        VERSION   No    L     N    2    5    4  Version Number
           TLID   No    R     N    6   15   10  TIGER/Line ID, Permanent Record Number
          SIDE1  Yes    R     N   16   16    1  Single-Side Complete Chain Code
         SOURCE  Yes    L     A   17   17    1  Linear Segment Source Code
         FEDIRP  Yes    L     A   18   19    2  Feature Direction, Prefix
         FENAME  Yes    L     A   20   49   30  Feature Name
         FETYPE  Yes    L     A   50   53    4  Feature Type
         FEDIRS  Yes    L     A   54   55    2  Feature Direction, Suffix
           CFCC  Yes    L     A   56   58    3  Census Feature Class Code
         FRADDL  Yes    R     A   59   69   11  Start Address, Left
         TOADDL  Yes    R     A   70   80   11  End Address, Left
         FRADDR  Yes    R     A   81   91   11  Start Address, Right
         TOADDR  Yes    R     A   92  102   11  End Address, Right
        FRIADDL  Yes    L     A  103  103    1  Start Imputed Address Flag, Left
        TOIADDL  Yes    L     A  104  104    1  End Imputed Address Flag, Left
        FRIADDR  Yes    L     A  105  105    1  Start Imputed Address Flag, Right
        TOIADDR  Yes    L     A  106  106    1  End Imputed Address Flag, Right
           ZIPL  Yes    L     N  107  111    5  ZIP Code, Left
           ZIPR  Yes    L     N  112  116    5  ZIP Code, Right
          FAIRL  Yes    L     N  117  121    5  FIPS 55 Code (American Indian/Alaska Native Area), Current Left
          FAIRR  Yes    L     N  122  126    5  FIPS 55 Code (American Indian/Alaska Native Area), Current Right
         TRUSTL  Yes    L     A  127  127    1  American Indian Trust Land Flag, Current Left
         TRUSTR  Yes    L     A  128  128    1  American Indian Trust Land Flag, Current Right
        CENSUS1  Yes    L     A  129  129    1  Census Use 1
        CENSUS2  Yes    L     A  130  130    1  Census Use 2
         STATEL  Yes    L     N  131  132    2  FIPS State Code, Current Left
         STATER  Yes    L     N  133  134    2  FIPS State Code, Current Right
        COUNTYL  Yes    L     N  135  137    3  FIPS County Code, Current Left
        COUNTYR  Yes    L     N  138  140    3  FIPS County Code, Current Right
          FMCDL  Yes    L     N  141  145    5  FIPS 55 Code (MCD/CCD) Left, Current
          FMCDR  Yes    L     N  146  150    5  FIPS 55 Code (MCD/CCD) Right, Current
         FSMCDL  Yes    L     N  151  155    5  FIPS 55 Code (Sub-MCD), Current Left
         FSMCDR  Yes    L     N  156  160    5  FIPS 55 Code (Sub-MCD), Current Right
           FPLL  Yes    L     N  161  165    5  FIPS 55 Code (Incorporated Place), Current Left
           FPLR  Yes    L     N  166  170    5  FIPS 55 Code (Incorporated Place), Current Right
            CTL  Yes    L     N  171  176    6  Census Tract Code, 1990 Left
            CTR  Yes    L     N  177  182    6  Census Tract Code, 1990 Right
           BLKL  Yes    L     A  183  186    4  Census Block Number, 1990 Left
           BLKR  Yes    L     A  187  190    4  Census Block Number, 1990 Right
         FRLONG   No    R     N  191  200   10  Start Longitude
          FRLAT   No    R     N  201  209    9  Start Latitude
         TOLONG   No    R     N  210  219   10  End Longitude
          TOLAT   No    R     N  220  228    9  End Latitude

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Geo/TigerLine, `mk_parsers' in this node

TIGER/Line 1998 Complete Chain Shape Coordinates
************************************************

NAME
====

   Geo::TigerLine::Record::2 - TIGER/Line 1998 Complete Chain Shape
Coordinates

SYNOPSIS
========

     use Geo::TigerLine::Record::2;

     @records = Geo::TigerLine::Record::2->parse_file($fh);
     @records = Geo::TigerLine::Record::2->parse_file($fh, \&callback);

     $record = Geo::TigerLine::Record::2->new(\%fields);

     $record->rt();
     $record->version();
     $record->tlid();
     $record->rtsq();
     $record->long1();
     $record->lat1();
     $record->long2();
     $record->lat2();
     $record->long3();
     $record->lat3();
     $record->long4();
     $record->lat4();
     $record->long5();
     $record->lat5();
     $record->long6();
     $record->lat6();
     $record->long7();
     $record->lat7();
     $record->long8();
     $record->lat8();
     $record->long9();
     $record->lat9();
     $record->long10();
     $record->lat10();

DESCRIPTION
===========

   This is a class representing record type 2 of the TIGER/Line 1998
census geographic database.  Each object is one record.  It also contains
methods to parse TIGER/Line record type 2 files and turn them into objects.

   This is intended as an intermediate format between pulling the raw data
out of the simplistic TIGER/Line data files into something more
sophisticated (a process you should only have to do once).  As such, its
not very fast, but its careful, easy to use and performs some
verifications on the data being read.

   As this class is autogenerated by mk_parsers, think before you modify
this file.  Its OO, so consider sub-classing instead.

Accessors
---------

   These are simple get/set accessors for each field of a record generated
from the TIGER/Line 1998 data dictionary.  They perform some data
validation.

rt
          $data = $record->rt();
          $record->rt($data);

     Record Type.

     Expects alphanumeric data of no more than 1 characters.  $data cannot
     be blank and should be left justified.

version
          $data = $record->version();
          $record->version($data);

     Version Number.

     Expects numeric data of no more than 4 characters.  $data cannot be
     blank and should be left justified.

tlid
          $data = $record->tlid();
          $record->tlid($data);

     TIGER/Line ID, Permanent Record Number.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

rtsq
          $data = $record->rtsq();
          $record->rtsq($data);

     Record Sequence Number.

     Expects numeric data of no more than 3 characters.  $data cannot be
     blank and should be right justified.

long1
          $data = $record->long1();
          $record->long1($data);

     Point 1, Longitude.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

lat1
          $data = $record->lat1();
          $record->lat1($data);

     Point 1, Latitude.

     Expects numeric data of no more than 9 characters.  $data cannot be
     blank and should be right justified.

long2
          $data = $record->long2();
          $record->long2($data);

     Point 2, Longitude.

     Expects numeric data of no more than 10 characters.  $data can be
     blank and should be right justified.

lat2
          $data = $record->lat2();
          $record->lat2($data);

     Point 2, Latitude.

     Expects numeric data of no more than 9 characters.  $data can be blank
     and should be right justified.

long3
          $data = $record->long3();
          $record->long3($data);

     Point 3, Longitude.

     Expects numeric data of no more than 10 characters.  $data can be
     blank and should be right justified.

lat3
          $data = $record->lat3();
          $record->lat3($data);

     Point 3, Latitude.

     Expects numeric data of no more than 9 characters.  $data can be blank
     and should be right justified.

long4
          $data = $record->long4();
          $record->long4($data);

     Point 4, Longitude.

     Expects numeric data of no more than 10 characters.  $data can be
     blank and should be right justified.

lat4
          $data = $record->lat4();
          $record->lat4($data);

     Point 4, Latitude.

     Expects numeric data of no more than 9 characters.  $data can be blank
     and should be right justified.

long5
          $data = $record->long5();
          $record->long5($data);

     Point 5, Longitude.

     Expects numeric data of no more than 10 characters.  $data can be
     blank and should be right justified.

lat5
          $data = $record->lat5();
          $record->lat5($data);

     Point 5, Latitude.

     Expects numeric data of no more than 9 characters.  $data can be blank
     and should be right justified.

long6
          $data = $record->long6();
          $record->long6($data);

     Point 6, Longitude.

     Expects numeric data of no more than 10 characters.  $data can be
     blank and should be right justified.

lat6
          $data = $record->lat6();
          $record->lat6($data);

     Point 6, Latitude.

     Expects numeric data of no more than 9 characters.  $data can be blank
     and should be right justified.

long7
          $data = $record->long7();
          $record->long7($data);

     Point 7, Longitude.

     Expects numeric data of no more than 10 characters.  $data can be
     blank and should be right justified.

lat7
          $data = $record->lat7();
          $record->lat7($data);

     Point 7, Latitude.

     Expects numeric data of no more than 9 characters.  $data can be blank
     and should be right justified.

long8
          $data = $record->long8();
          $record->long8($data);

     Point 8, Longitude.

     Expects numeric data of no more than 10 characters.  $data can be
     blank and should be right justified.

lat8
          $data = $record->lat8();
          $record->lat8($data);

     Point 8, Latitude.

     Expects numeric data of no more than 9 characters.  $data can be blank
     and should be right justified.

long9
          $data = $record->long9();
          $record->long9($data);

     Point 9, Longitude.

     Expects numeric data of no more than 10 characters.  $data can be
     blank and should be right justified.

lat9
          $data = $record->lat9();
          $record->lat9($data);

     Point 9, Latitude.

     Expects numeric data of no more than 9 characters.  $data can be blank
     and should be right justified.

long10
          $data = $record->long10();
          $record->long10($data);

     Point 10, Longitude.

     Expects numeric data of no more than 10 characters.  $data can be
     blank and should be right justified.

lat10
          $data = $record->lat10();
          $record->lat10($data);

     Point 10, Latitude.

     Expects numeric data of no more than 9 characters.  $data can be blank
     and should be right justified.

Data dictionary
---------------

   This is the original TIGER/Line 1998 data dictionary from which this
class was generated.

     Record Type 2 - Complete Chain Shape Coordinates

          Field   BV  Fmt  Type  Beg  End  Len  Description
             RT   No    L     A    1    1    1  Record Type
        VERSION   No    L     N    2    5    4  Version Number
           TLID   No    R     N    6   15   10  TIGER/Line ID, Permanent Record Number
           RTSQ   No    R     N   16   18    3  Record Sequence Number
          LONG1   No    R     N   19   28   10  Point 1, Longitude
           LAT1   No    R     N   29   37    9  Point 1, Latitude
          LONG2  Yes    R     N   38   47   10  Point 2, Longitude
           LAT2  Yes    R     N   48   56    9  Point 2, Latitude
          LONG3  Yes    R     N   57   66   10  Point 3, Longitude
           LAT3  Yes    R     N   67   75    9  Point 3, Latitude
          LONG4  Yes    R     N   76   85   10  Point 4, Longitude
           LAT4  Yes    R     N   86   94    9  Point 4, Latitude
          LONG5  Yes    R     N   95  104   10  Point 5, Longitude
           LAT5  Yes    R     N  105  113    9  Point 5, Latitude
          LONG6  Yes    R     N  114  123   10  Point 6, Longitude
           LAT6  Yes    R     N  124  132    9  Point 6, Latitude
          LONG7  Yes    R     N  133  142   10  Point 7, Longitude
           LAT7  Yes    R     N  143  151    9  Point 7, Latitude
          LONG8  Yes    R     N  152  161   10  Point 8, Longitude
           LAT8  Yes    R     N  162  170    9  Point 8, Latitude
          LONG9  Yes    R     N  171  180   10  Point 9, Longitude
           LAT9  Yes    R     N  181  189    9  Point 9, Latitude
         LONG10  Yes    R     N  190  199   10  Point 10, Longitude
          LAT10  Yes    R     N  200  208    9  Point 10, Latitude

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Geo/TigerLine, `mk_parsers' in this node

TIGER/Line 1998 Complete Chain Geographic Entity Codes
******************************************************

NAME
====

   Geo::TigerLine::Record::3 - TIGER/Line 1998 Complete Chain Geographic
Entity Codes

SYNOPSIS
========

     use Geo::TigerLine::Record::3;

     @records = Geo::TigerLine::Record::3->parse_file($fh);
     @records = Geo::TigerLine::Record::3->parse_file($fh, \&callback);

     $record = Geo::TigerLine::Record::3->new(\%fields);

     $record->rt();
     $record->version();
     $record->tlid();
     $record->state90l();
     $record->state90r();
     $record->coun90l();
     $record->coun90r();
     $record->fmcd90l();
     $record->fmcd90r();
     $record->fpl90l();
     $record->fpl90r();
     $record->ctbna90l();
     $record->ctbna90r();
     $record->air90l();
     $record->air90r();
     $record->trust90l();
     $record->trust90r();
     $record->rs1();
     $record->blk90l();
     $record->blk90r();
     $record->airl();
     $record->airr();
     $record->fanrcl();
     $record->fanrcr();
     $record->census3();
     $record->census4();
     $record->rs2();
     $record->vtd90l();
     $record->vtd90r();

DESCRIPTION
===========

   This is a class representing record type 3 of the TIGER/Line 1998
census geographic database.  Each object is one record.  It also contains
methods to parse TIGER/Line record type 3 files and turn them into objects.

   This is intended as an intermediate format between pulling the raw data
out of the simplistic TIGER/Line data files into something more
sophisticated (a process you should only have to do once).  As such, its
not very fast, but its careful, easy to use and performs some
verifications on the data being read.

   As this class is autogenerated by mk_parsers, think before you modify
this file.  Its OO, so consider sub-classing instead.

Accessors
---------

   These are simple get/set accessors for each field of a record generated
from the TIGER/Line 1998 data dictionary.  They perform some data
validation.

rt
          $data = $record->rt();
          $record->rt($data);

     Record Type.

     Expects alphanumeric data of no more than 1 characters.  $data cannot
     be blank and should be left justified.

version
          $data = $record->version();
          $record->version($data);

     Version Number.

     Expects numeric data of no more than 4 characters.  $data cannot be
     blank and should be left justified.

tlid
          $data = $record->tlid();
          $record->tlid($data);

     TIGER/Line ID, Permanent Record Number.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

state90l
          $data = $record->state90l();
          $record->state90l($data);

     FIPS State Code, 1990 Left.

     Expects numeric data of no more than 2 characters.  $data can be blank
     and should be left justified.

state90r
          $data = $record->state90r();
          $record->state90r($data);

     FIPS State Code, 1990 Right.

     Expects numeric data of no more than 2 characters.  $data can be blank
     and should be left justified.

coun90l
          $data = $record->coun90l();
          $record->coun90l($data);

     FIPS County Code, 1990 Left.

     Expects numeric data of no more than 3 characters.  $data can be blank
     and should be left justified.

coun90r
          $data = $record->coun90r();
          $record->coun90r($data);

     FIPS County Code, 1990 Right.

     Expects numeric data of no more than 3 characters.  $data can be blank
     and should be left justified.

fmcd90l
          $data = $record->fmcd90l();
          $record->fmcd90l($data);

     FIPS 55 Code (MCD/CCD), 1990 Left.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

fmcd90r
          $data = $record->fmcd90r();
          $record->fmcd90r($data);

     FIPS 55 Code (MCD/CCD), 1990 Right.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

fpl90l
          $data = $record->fpl90l();
          $record->fpl90l($data);

     FIPS 55 Code (Place/CDP), 1990 Left.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

fpl90r
          $data = $record->fpl90r();
          $record->fpl90r($data);

     FIPS 55 Code (Place/CDP), 1990 Right.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

ctbna90l
          $data = $record->ctbna90l();
          $record->ctbna90l($data);

     Census Tract/BNA Code, 1990 Left.

     Expects numeric data of no more than 6 characters.  $data can be blank
     and should be left justified.

ctbna90r
          $data = $record->ctbna90r();
          $record->ctbna90r($data);

     Census Tract/BNA Code, 1990 Right.

     Expects numeric data of no more than 6 characters.  $data can be blank
     and should be left justified.

air90l
          $data = $record->air90l();
          $record->air90l($data);

     Census American Indian/Alaska Native Area Code 1990, Left.

     Expects numeric data of no more than 4 characters.  $data can be blank
     and should be left justified.

air90r
          $data = $record->air90r();
          $record->air90r($data);

     Census American Indian/Alaska Native Area Code 1990, Right.

     Expects numeric data of no more than 4 characters.  $data can be blank
     and should be left justified.

trust90l
          $data = $record->trust90l();
          $record->trust90l($data);

     American Indian Trust Land Flag 1990, Left.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

trust90r
          $data = $record->trust90r();
          $record->trust90r($data);

     American Indian Trust Land Flag 1990, Right.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

rs1
          $data = $record->rs1();
          $record->rs1($data);

     Reserved Space 1.

     Expects alphanumeric data of no more than 2 characters.  $data can be
     blank and should be left justified.

blk90l
          $data = $record->blk90l();
          $record->blk90l($data);

     Census Block Number, 1990 Left.

     Expects alphanumeric data of no more than 4 characters.  $data can be
     blank and should be left justified.

blk90r
          $data = $record->blk90r();
          $record->blk90r($data);

     Census Block Number, 1990 Right.

     Expects alphanumeric data of no more than 4 characters.  $data can be
     blank and should be left justified.

airl
          $data = $record->airl();
          $record->airl($data);

     Census American Indian/Alaska Native Area Code, Current Left.

     Expects numeric data of no more than 4 characters.  $data can be blank
     and should be left justified.

airr
          $data = $record->airr();
          $record->airr($data);

     Census American Indian/Alaska Native Area Code, Current Right.

     Expects numeric data of no more than 4 characters.  $data can be blank
     and should be left justified.

fanrcl
          $data = $record->fanrcl();
          $record->fanrcl($data);

     FIPS 55 Code (ANRC), Current Left.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

fanrcr
          $data = $record->fanrcr();
          $record->fanrcr($data);

     FIPS 55 Code (ANRC), Current Right.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

census3
          $data = $record->census3();
          $record->census3($data);

     Census Use 3.

     Expects numeric data of no more than 3 characters.  $data can be blank
     and should be left justified.

census4
          $data = $record->census4();
          $record->census4($data);

     Census Use 4.

     Expects numeric data of no more than 3 characters.  $data can be blank
     and should be left justified.

rs2
          $data = $record->rs2();
          $record->rs2($data);

     Reserved Space 2.

     Expects alphanumeric data of no more than 2 characters.  $data can be
     blank and should be left justified.

vtd90l
          $data = $record->vtd90l();
          $record->vtd90l($data);

     Voting District Code, 1990 Left.

     Expects alphanumeric data of no more than 4 characters.  $data can be
     blank and should be left justified.

vtd90r
          $data = $record->vtd90r();
          $record->vtd90r($data);

     Voting District Code, 1990 Right.

     Expects alphanumeric data of no more than 4 characters.  $data can be
     blank and should be left justified.

Data dictionary
---------------

   This is the original TIGER/Line 1998 data dictionary from which this
class was generated.

     Record Type 3 - Complete Chain Geographic Entity Codes

          Field   BV  Fmt  Type  Beg  End  Len  Description
             RT   No    L     A    1    1    1  Record Type
        VERSION   No    L     N    2    5    4  Version Number
           TLID   No    R     N    6   15   10  TIGER/Line ID, Permanent Record Number
       STATE90L  Yes    L     N   16   17    2  FIPS State Code, 1990 Left
       STATE90R  Yes    L     N   18   19    2  FIPS State Code, 1990 Right
        COUN90L  Yes    L     N   20   22    3  FIPS County Code, 1990 Left
        COUN90R  Yes    L     N   23   25    3  FIPS County Code, 1990 Right
        FMCD90L  Yes    L     N   26   30    5  FIPS 55 Code (MCD/CCD), 1990 Left
        FMCD90R  Yes    L     N   31   35    5  FIPS 55 Code (MCD/CCD), 1990 Right
         FPL90L  Yes    L     N   36   40    5  FIPS 55 Code (Place/CDP), 1990 Left
         FPL90R  Yes    L     N   41   45    5  FIPS 55 Code (Place/CDP), 1990 Right
       CTBNA90L  Yes    L     N   46   51    6  Census Tract/BNA Code, 1990 Left
       CTBNA90R  Yes    L     N   52   57    6  Census Tract/BNA Code, 1990 Right
         AIR90L  Yes    L     N   58   61    4  Census American Indian/Alaska Native Area Code 1990, Left
         AIR90R  Yes    L     N   62   65    4  Census American Indian/Alaska Native Area Code 1990, Right
       TRUST90L  Yes    L     A   66   66    1  American Indian Trust Land Flag 1990, Left
       TRUST90R  Yes    L     A   67   67    1  American Indian Trust Land Flag 1990, Right
            RS1  Yes    L     A   68   69    2  Reserved Space 1
         BLK90L  Yes    L     A   70   73    4  Census Block Number, 1990 Left
         BLK90R  Yes    L     A   74   77    4  Census Block Number, 1990 Right
           AIRL  Yes    L     N   78   81    4  Census American Indian/Alaska Native Area Code, Current Left
           AIRR  Yes    L     N   82   85    4  Census American Indian/Alaska Native Area Code, Current Right
         FANRCL  Yes    L     N   86   90    5  FIPS 55 Code (ANRC), Current Left
         FANRCR  Yes    L     N   91   95    5  FIPS 55 Code (ANRC), Current Right
        CENSUS3  Yes    L     N   96   98    3  Census Use 3
        CENSUS4  Yes    L     N   99  101    3  Census Use 4
            RS2  Yes    L     A  102  103    2  Reserved Space 2
         VTD90L  Yes    L     A  104  107    4  Voting District Code, 1990 Left
         VTD90R  Yes    L     A  108  111    4  Voting District Code, 1990 Right

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Geo/TigerLine, `mk_parsers' in this node

TIGER/Line 1998 Index to Alternative Feature Identifiers
********************************************************

NAME
====

   Geo::TigerLine::Record::4 - TIGER/Line 1998 Index to Alternative
Feature Identifiers

SYNOPSIS
========

     use Geo::TigerLine::Record::4;

     @records = Geo::TigerLine::Record::4->parse_file($fh);
     @records = Geo::TigerLine::Record::4->parse_file($fh, \&callback);

     $record = Geo::TigerLine::Record::4->new(\%fields);

     $record->rt();
     $record->version();
     $record->tlid();
     $record->rtsq();
     $record->feat1();
     $record->feat2();
     $record->feat3();
     $record->feat4();
     $record->feat5();

DESCRIPTION
===========

   This is a class representing record type 4 of the TIGER/Line 1998
census geographic database.  Each object is one record.  It also contains
methods to parse TIGER/Line record type 4 files and turn them into objects.

   This is intended as an intermediate format between pulling the raw data
out of the simplistic TIGER/Line data files into something more
sophisticated (a process you should only have to do once).  As such, its
not very fast, but its careful, easy to use and performs some
verifications on the data being read.

   As this class is autogenerated by mk_parsers, think before you modify
this file.  Its OO, so consider sub-classing instead.

Accessors
---------

   These are simple get/set accessors for each field of a record generated
from the TIGER/Line 1998 data dictionary.  They perform some data
validation.

rt
          $data = $record->rt();
          $record->rt($data);

     Record Type.

     Expects alphanumeric data of no more than 1 characters.  $data cannot
     be blank and should be left justified.

version
          $data = $record->version();
          $record->version($data);

     Version Number.

     Expects numeric data of no more than 4 characters.  $data cannot be
     blank and should be left justified.

tlid
          $data = $record->tlid();
          $record->tlid($data);

     TIGER/Line ID, Permanent Record Number.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

rtsq
          $data = $record->rtsq();
          $record->rtsq($data);

     Record Sequence Number.

     Expects numeric data of no more than 3 characters.  $data cannot be
     blank and should be right justified.

feat1
          $data = $record->feat1();
          $record->feat1($data);

     Line Additional Name Identification Number, First.

     Expects numeric data of no more than 8 characters.  $data cannot be
     blank and should be right justified.

feat2
          $data = $record->feat2();
          $record->feat2($data);

     Line Additional Name Identification Number, Second.

     Expects numeric data of no more than 8 characters.  $data can be blank
     and should be right justified.

feat3
          $data = $record->feat3();
          $record->feat3($data);

     Line Additional Name Identification Number, Third.

     Expects numeric data of no more than 8 characters.  $data can be blank
     and should be right justified.

feat4
          $data = $record->feat4();
          $record->feat4($data);

     Line Additional Name Identification Number, Fourth.

     Expects numeric data of no more than 8 characters.  $data can be blank
     and should be right justified.

feat5
          $data = $record->feat5();
          $record->feat5($data);

     Line Additional Name Identification Number, Fifth.

     Expects numeric data of no more than 8 characters.  $data can be blank
     and should be right justified.

Data dictionary
---------------

   This is the original TIGER/Line 1998 data dictionary from which this
class was generated.

     Record Type 4 - Index to Alternative Feature Identifiers

          Field   BV  Fmt  Type  Beg  End  Len  Description
             RT   No    L     A    1    1    1  Record Type
        VERSION   No    L     N    2    5    4  Version Number
           TLID   No    R     N    6   15   10  TIGER/Line ID, Permanent Record Number
           RTSQ   No    R     N   16   18    3  Record Sequence Number
          FEAT1   No    R     N   19   26    8  Line Additional Name Identification Number, First
          FEAT2  Yes    R     N   27   34    8  Line Additional Name Identification Number, Second
          FEAT3  Yes    R     N   35   42    8  Line Additional Name Identification Number, Third
          FEAT4  Yes    R     N   43   50    8  Line Additional Name Identification Number, Fourth
          FEAT5  Yes    R     N   51   58    8  Line Additional Name Identification Number, Fifth

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Geo/TigerLine, `mk_parsers' in this node

TIGER/Line 1998 Complete Chain Feature Identifiers
**************************************************

NAME
====

   Geo::TigerLine::Record::5 - TIGER/Line 1998 Complete Chain Feature
Identifiers

SYNOPSIS
========

     use Geo::TigerLine::Record::5;

     @records = Geo::TigerLine::Record::5->parse_file($fh);
     @records = Geo::TigerLine::Record::5->parse_file($fh, \&callback);

     $record = Geo::TigerLine::Record::5->new(\%fields);

     $record->rt();
     $record->state();
     $record->county();
     $record->feat();
     $record->fedirp();
     $record->fename();
     $record->fetype();
     $record->fedirs();

DESCRIPTION
===========

   This is a class representing record type 5 of the TIGER/Line 1998
census geographic database.  Each object is one record.  It also contains
methods to parse TIGER/Line record type 5 files and turn them into objects.

   This is intended as an intermediate format between pulling the raw data
out of the simplistic TIGER/Line data files into something more
sophisticated (a process you should only have to do once).  As such, its
not very fast, but its careful, easy to use and performs some
verifications on the data being read.

   As this class is autogenerated by mk_parsers, think before you modify
this file.  Its OO, so consider sub-classing instead.

Accessors
---------

   These are simple get/set accessors for each field of a record generated
from the TIGER/Line 1998 data dictionary.  They perform some data
validation.

rt
          $data = $record->rt();
          $record->rt($data);

     Record Type.

     Expects alphanumeric data of no more than 1 characters.  $data cannot
     be blank and should be left justified.

state
          $data = $record->state();
          $record->state($data);

     FIPS State Code for File.

     Expects numeric data of no more than 2 characters.  $data cannot be
     blank and should be left justified.

county
          $data = $record->county();
          $record->county($data);

     FIPS County Code for File.

     Expects numeric data of no more than 3 characters.  $data cannot be
     blank and should be left justified.

feat
          $data = $record->feat();
          $record->feat($data);

     Line Name Identification Number.

     Expects numeric data of no more than 8 characters.  $data cannot be
     blank and should be right justified.

fedirp
          $data = $record->fedirp();
          $record->fedirp($data);

     Feature Direction, Prefix.

     Expects alphanumeric data of no more than 2 characters.  $data can be
     blank and should be left justified.

fename
          $data = $record->fename();
          $record->fename($data);

     Feature Name.

     Expects alphanumeric data of no more than 30 characters.  $data can
     be blank and should be left justified.

fetype
          $data = $record->fetype();
          $record->fetype($data);

     Feature Type.

     Expects alphanumeric data of no more than 4 characters.  $data can be
     blank and should be left justified.

fedirs
          $data = $record->fedirs();
          $record->fedirs($data);

     Feature Direction, Suffix.

     Expects alphanumeric data of no more than 2 characters.  $data can be
     blank and should be left justified.

Data dictionary
---------------

   This is the original TIGER/Line 1998 data dictionary from which this
class was generated.

     Record Type 5 - Complete Chain Feature Identifiers

          Field   BV  Fmt  Type  Beg  End  Len  Description
             RT   No    L     A    1    1    1  Record Type
          STATE   No    L     N    2    3    2  FIPS State Code for File
         COUNTY   No    L     N    4    6    3  FIPS County Code for File
           FEAT   No    R     N    7   14    8  Line Name Identification Number
         FEDIRP  Yes    L     A   15   16    2  Feature Direction, Prefix
         FENAME  Yes    L     A   17   46   30  Feature Name
         FETYPE  Yes    L     A   47   50    4  Feature Type
         FEDIRS  Yes    L     A   51   52    2  Feature Direction, Suffix

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Geo/TigerLine, `mk_parsers' in this node

TIGER/Line 1998 Additional Address Range and ZIP Code Data
**********************************************************

NAME
====

   Geo::TigerLine::Record::6 - TIGER/Line 1998 Additional Address Range
and ZIP Code Data

SYNOPSIS
========

     use Geo::TigerLine::Record::6;

     @records = Geo::TigerLine::Record::6->parse_file($fh);
     @records = Geo::TigerLine::Record::6->parse_file($fh, \&callback);

     $record = Geo::TigerLine::Record::6->new(\%fields);

     $record->rt();
     $record->version();
     $record->tlid();
     $record->rtsq();
     $record->fraddl();
     $record->toaddl();
     $record->fraddr();
     $record->toaddr();
     $record->friaddl();
     $record->toiaddl();
     $record->friaddr();
     $record->toiaddr();
     $record->zipl();
     $record->zipr();

DESCRIPTION
===========

   This is a class representing record type 6 of the TIGER/Line 1998
census geographic database.  Each object is one record.  It also contains
methods to parse TIGER/Line record type 6 files and turn them into objects.

   This is intended as an intermediate format between pulling the raw data
out of the simplistic TIGER/Line data files into something more
sophisticated (a process you should only have to do once).  As such, its
not very fast, but its careful, easy to use and performs some
verifications on the data being read.

   As this class is autogenerated by mk_parsers, think before you modify
this file.  Its OO, so consider sub-classing instead.

Accessors
---------

   These are simple get/set accessors for each field of a record generated
from the TIGER/Line 1998 data dictionary.  They perform some data
validation.

rt
          $data = $record->rt();
          $record->rt($data);

     Record Type.

     Expects alphanumeric data of no more than 1 characters.  $data cannot
     be blank and should be left justified.

version
          $data = $record->version();
          $record->version($data);

     Version Number.

     Expects numeric data of no more than 4 characters.  $data cannot be
     blank and should be left justified.

tlid
          $data = $record->tlid();
          $record->tlid($data);

     TIGER/Line ID, Permanent Record Number.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

rtsq
          $data = $record->rtsq();
          $record->rtsq($data);

     Record Sequence Number.

     Expects numeric data of no more than 3 characters.  $data cannot be
     blank and should be right justified.

fraddl
          $data = $record->fraddl();
          $record->fraddl($data);

     Start Address, Left.

     Expects alphanumeric data of no more than 11 characters.  $data can
     be blank and should be right justified.

toaddl
          $data = $record->toaddl();
          $record->toaddl($data);

     End Address, Left.

     Expects alphanumeric data of no more than 11 characters.  $data can
     be blank and should be right justified.

fraddr
          $data = $record->fraddr();
          $record->fraddr($data);

     Start Address, Right.

     Expects alphanumeric data of no more than 11 characters.  $data can
     be blank and should be right justified.

toaddr
          $data = $record->toaddr();
          $record->toaddr($data);

     End Address, Right.

     Expects alphanumeric data of no more than 11 characters.  $data can
     be blank and should be right justified.

friaddl
          $data = $record->friaddl();
          $record->friaddl($data);

     Start Imputed Address Flag, Left.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

toiaddl
          $data = $record->toiaddl();
          $record->toiaddl($data);

     End Imputed Address Flag, Left.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

friaddr
          $data = $record->friaddr();
          $record->friaddr($data);

     Start Imputed Address Flag, Right.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

toiaddr
          $data = $record->toiaddr();
          $record->toiaddr($data);

     End Imputed Address Flag, Right.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

zipl
          $data = $record->zipl();
          $record->zipl($data);

     ZIP Code, Left.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

zipr
          $data = $record->zipr();
          $record->zipr($data);

     ZIP Code, Right.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

Data dictionary
---------------

   This is the original TIGER/Line 1998 data dictionary from which this
class was generated.

     Record Type 6 - Additional Address Range and ZIP Code Data

          Field   BV  Fmt  Type  Beg  End  Len  Description
             RT   No    L     A    1    1    1  Record Type
        VERSION   No    L     N    2    5    4  Version Number
           TLID   No    R     N    6   15   10  TIGER/Line ID, Permanent Record Number
           RTSQ   No    R     N   16   18    3  Record Sequence Number
         FRADDL  Yes    R     A   19   29   11  Start Address, Left
         TOADDL  Yes    R     A   30   40   11  End Address, Left
         FRADDR  Yes    R     A   41   51   11  Start Address, Right
         TOADDR  Yes    R     A   52   62   11  End Address, Right
        FRIADDL  Yes    L     A   63   63    1  Start Imputed Address Flag, Left
        TOIADDL  Yes    L     A   64   64    1  End Imputed Address Flag, Left
        FRIADDR  Yes    L     A   65   65    1  Start Imputed Address Flag, Right
        TOIADDR  Yes    L     A   66   66    1  End Imputed Address Flag, Right
           ZIPL  Yes    L     N   67   71    5  ZIP Code, Left
           ZIPR  Yes    L     N   72   76    5  ZIP Code, Right

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Geo/TigerLine, `mk_parsers' in this node

TIGER/Line 1998 Landmark  Features
**********************************

NAME
====

   Geo::TigerLine::Record::7 - TIGER/Line 1998 Landmark  Features

SYNOPSIS
========

     use Geo::TigerLine::Record::7;

     @records = Geo::TigerLine::Record::7->parse_file($fh);
     @records = Geo::TigerLine::Record::7->parse_file($fh, \&callback);

     $record = Geo::TigerLine::Record::7->new(\%fields);

     $record->rt();
     $record->version();
     $record->state();
     $record->county();
     $record->land();
     $record->source();
     $record->cfcc();
     $record->laname();
     $record->lalong();
     $record->lalat();
     $record->filler();

DESCRIPTION
===========

   This is a class representing record type 7 of the TIGER/Line 1998
census geographic database.  Each object is one record.  It also contains
methods to parse TIGER/Line record type 7 files and turn them into objects.

   This is intended as an intermediate format between pulling the raw data
out of the simplistic TIGER/Line data files into something more
sophisticated (a process you should only have to do once).  As such, its
not very fast, but its careful, easy to use and performs some
verifications on the data being read.

   As this class is autogenerated by mk_parsers, think before you modify
this file.  Its OO, so consider sub-classing instead.

Accessors
---------

   These are simple get/set accessors for each field of a record generated
from the TIGER/Line 1998 data dictionary.  They perform some data
validation.

rt
          $data = $record->rt();
          $record->rt($data);

     Record Type.

     Expects alphanumeric data of no more than 1 characters.  $data cannot
     be blank and should be left justified.

version
          $data = $record->version();
          $record->version($data);

     Version Number.

     Expects numeric data of no more than 4 characters.  $data cannot be
     blank and should be left justified.

state
          $data = $record->state();
          $record->state($data);

     FIPS State Code for File.

     Expects numeric data of no more than 2 characters.  $data cannot be
     blank and should be left justified.

county
          $data = $record->county();
          $record->county($data);

     FIPS County Code for File.

     Expects numeric data of no more than 3 characters.  $data cannot be
     blank and should be left justified.

land
          $data = $record->land();
          $record->land($data);

     Landmark Identification Number.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

source
          $data = $record->source();
          $record->source($data);

     Source or First Source Code to Update.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

cfcc
          $data = $record->cfcc();
          $record->cfcc($data);

     Census Feature Class Code.

     Expects alphanumeric data of no more than 3 characters.  $data can be
     blank and should be left justified.

laname
          $data = $record->laname();
          $record->laname($data);

     Landmark Name.

     Expects alphanumeric data of no more than 30 characters.  $data can
     be blank and should be left justified.

lalong
          $data = $record->lalong();
          $record->lalong($data);

     Longitude.

     Expects numeric data of no more than 10 characters.  $data can be
     blank and should be right justified.

lalat
          $data = $record->lalat();
          $record->lalat($data);

     Latitude.

     Expects numeric data of no more than 9 characters.  $data can be blank
     and should be right justified.

filler
          $data = $record->filler();
          $record->filler($data);

     Filler (to make even character count).

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

Data dictionary
---------------

   This is the original TIGER/Line 1998 data dictionary from which this
class was generated.

     Record Type 7 - Landmark  Features

          Field   BV  Fmt  Type  Beg  End  Len  Description
             RT   No    L     A    1    1    1  Record Type
        VERSION   No    L     N    2    5    4  Version Number
          STATE   No    L     N    6    7    2  FIPS State Code for File
         COUNTY   No    L     N    8   10    3  FIPS County Code for File
           LAND   No    R     N   11   20   10  Landmark Identification Number
         SOURCE  Yes    L     A   21   21    1  Source or First Source Code to Update
           CFCC  Yes    L     A   22   24    3  Census Feature Class Code
         LANAME  Yes    L     A   25   54   30  Landmark Name
         LALONG  Yes    R     N   55   64   10  Longitude
          LALAT  Yes    R     N   65   73    9  Latitude
         FILLER  Yes    L     A   74   74    1  Filler (to make even character count)

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Geo/TigerLine, `mk_parsers' in this node

TIGER/Line 1998 Polygons Linked to Area Landmarks
*************************************************

NAME
====

   Geo::TigerLine::Record::8 - TIGER/Line 1998 Polygons Linked to Area
Landmarks

SYNOPSIS
========

     use Geo::TigerLine::Record::8;

     @records = Geo::TigerLine::Record::8->parse_file($fh);
     @records = Geo::TigerLine::Record::8->parse_file($fh, \&callback);

     $record = Geo::TigerLine::Record::8->new(\%fields);

     $record->rt();
     $record->version();
     $record->state();
     $record->county();
     $record->cenid();
     $record->polyid();
     $record->land();
     $record->filler();

DESCRIPTION
===========

   This is a class representing record type 8 of the TIGER/Line 1998
census geographic database.  Each object is one record.  It also contains
methods to parse TIGER/Line record type 8 files and turn them into objects.

   This is intended as an intermediate format between pulling the raw data
out of the simplistic TIGER/Line data files into something more
sophisticated (a process you should only have to do once).  As such, its
not very fast, but its careful, easy to use and performs some
verifications on the data being read.

   As this class is autogenerated by mk_parsers, think before you modify
this file.  Its OO, so consider sub-classing instead.

Accessors
---------

   These are simple get/set accessors for each field of a record generated
from the TIGER/Line 1998 data dictionary.  They perform some data
validation.

rt
          $data = $record->rt();
          $record->rt($data);

     Record Type.

     Expects alphanumeric data of no more than 1 characters.  $data cannot
     be blank and should be left justified.

version
          $data = $record->version();
          $record->version($data);

     Version Number.

     Expects numeric data of no more than 4 characters.  $data cannot be
     blank and should be left justified.

state
          $data = $record->state();
          $record->state($data);

     FIPS State Code for File.

     Expects numeric data of no more than 2 characters.  $data cannot be
     blank and should be left justified.

county
          $data = $record->county();
          $record->county($data);

     FIPS County Code for File.

     Expects numeric data of no more than 3 characters.  $data cannot be
     blank and should be left justified.

cenid
          $data = $record->cenid();
          $record->cenid($data);

     Census File Identification Code.

     Expects alphanumeric data of no more than 5 characters.  $data cannot
     be blank and should be left justified.

polyid
          $data = $record->polyid();
          $record->polyid($data);

     Polygon Identification Code.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

land
          $data = $record->land();
          $record->land($data);

     Landmark Identification Number.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

filler
          $data = $record->filler();
          $record->filler($data);

     Filler (to make even character count).

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

Data dictionary
---------------

   This is the original TIGER/Line 1998 data dictionary from which this
class was generated.

     Record Type 8 - Polygons Linked to Area Landmarks

          Field   BV  Fmt  Type  Beg  End  Len  Description
             RT   No    L     A    1    1    1  Record Type
        VERSION   No    L     N    2    5    4  Version Number
          STATE   No    L     N    6    7    2  FIPS State Code for File
         COUNTY   No    L     N    8   10    3  FIPS County Code for File
          CENID   No    L     A   11   15    5  Census File Identification Code
         POLYID   No    R     N   16   25   10  Polygon Identification Code
           LAND   No    R     N   26   35   10  Landmark Identification Number
         FILLER  Yes    L     A   36   36    1  Filler (to make even character count)

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Geo/TigerLine, `mk_parsers' in this node

TIGER/Line 1998 Key Geographic Location Features
************************************************

NAME
====

   Geo::TigerLine::Record::9 - TIGER/Line 1998 Key Geographic Location
Features

SYNOPSIS
========

     use Geo::TigerLine::Record::9;

     @records = Geo::TigerLine::Record::9->parse_file($fh);
     @records = Geo::TigerLine::Record::9->parse_file($fh, \&callback);

     $record = Geo::TigerLine::Record::9->new(\%fields);

     $record->rt();
     $record->version();
     $record->state();
     $record->county();
     $record->cenid();
     $record->polyid();
     $record->source();
     $record->cfcc();
     $record->kglname();
     $record->kgladd();
     $record->kglzip();
     $record->kglzip4();
     $record->feat();
     $record->filler();

DESCRIPTION
===========

   This is a class representing record type 9 of the TIGER/Line 1998
census geographic database.  Each object is one record.  It also contains
methods to parse TIGER/Line record type 9 files and turn them into objects.

   This is intended as an intermediate format between pulling the raw data
out of the simplistic TIGER/Line data files into something more
sophisticated (a process you should only have to do once).  As such, its
not very fast, but its careful, easy to use and performs some
verifications on the data being read.

   As this class is autogenerated by mk_parsers, think before you modify
this file.  Its OO, so consider sub-classing instead.

Accessors
---------

   These are simple get/set accessors for each field of a record generated
from the TIGER/Line 1998 data dictionary.  They perform some data
validation.

rt
          $data = $record->rt();
          $record->rt($data);

     Record Type.

     Expects alphanumeric data of no more than 1 characters.  $data cannot
     be blank and should be left justified.

version
          $data = $record->version();
          $record->version($data);

     Version Number.

     Expects numeric data of no more than 4 characters.  $data cannot be
     blank and should be left justified.

state
          $data = $record->state();
          $record->state($data);

     FIPS State Code for File.

     Expects numeric data of no more than 2 characters.  $data cannot be
     blank and should be left justified.

county
          $data = $record->county();
          $record->county($data);

     FIPS County Code for File.

     Expects numeric data of no more than 3 characters.  $data cannot be
     blank and should be left justified.

cenid
          $data = $record->cenid();
          $record->cenid($data);

     Census File Identification Code.

     Expects alphanumeric data of no more than 5 characters.  $data cannot
     be blank and should be left justified.

polyid
          $data = $record->polyid();
          $record->polyid($data);

     Polygon Identification Code.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

source
          $data = $record->source();
          $record->source($data);

     Source or First Source Code to Update.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

cfcc
          $data = $record->cfcc();
          $record->cfcc($data);

     Census Feature Class Code.

     Expects alphanumeric data of no more than 3 characters.  $data can be
     blank and should be left justified.

kglname
          $data = $record->kglname();
          $record->kglname($data);

     Key Geographic Location Name.

     Expects alphanumeric data of no more than 30 characters.  $data can
     be blank and should be left justified.

kgladd
          $data = $record->kgladd();
          $record->kgladd($data);

     Key Geographic Location Address.

     Expects alphanumeric data of no more than 11 characters.  $data
     cannot be blank and should be right justified.

kglzip
          $data = $record->kglzip();
          $record->kglzip($data);

     Key Geographic Location ZIP Code.

     Expects numeric data of no more than 5 characters.  $data cannot be
     blank and should be left justified.

kglzip4
          $data = $record->kglzip4();
          $record->kglzip4($data);

     +4 Postal Add-On Code for KGL.

     Expects numeric data of no more than 4 characters.  $data cannot be
     blank and should be left justified.

feat
          $data = $record->feat();
          $record->feat($data);

     Line Name Identification Number.

     Expects numeric data of no more than 8 characters.  $data can be blank
     and should be right justified.

filler
          $data = $record->filler();
          $record->filler($data);

     Filler (to make even character count).

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

Data dictionary
---------------

   This is the original TIGER/Line 1998 data dictionary from which this
class was generated.

     Record Type 9 - Key Geographic Location Features

          Field   BV  Fmt  Type  Beg  End  Len  Description
             RT   No    L     A    1    1    1  Record Type
        VERSION   No    L     N    2    5    4  Version Number
          STATE   No    L     N    6    7    2  FIPS State Code for File
         COUNTY   No    L     N    8   10    3  FIPS County Code for File
          CENID   No    L     A   11   15    5  Census File Identification Code
         POLYID   No    R     N   16   25   10  Polygon Identification Code
         SOURCE  Yes    L     A   26   26    1  Source or First Source Code to Update
           CFCC  Yes    L     A   27   29    3  Census Feature Class Code
        KGLNAME  Yes    L     A   30   59   30  Key Geographic Location Name
         KGLADD  No*    R     A   60   70   11  Key Geographic Location Address
         KGLZIP  No*    L     N   71   75    5  Key Geographic Location ZIP Code
        KGLZIP4  No*    L     N   76   79    4  +4 Postal Add-On Code for KGL
           FEAT  Yes    R     N   80   87    8  Line Name Identification Number
         FILLER  Yes    L     A   88   88    1  Filler (to make even character count)

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Geo/TigerLine, `mk_parsers' in this node

TIGER/Line 1998 Polygon Geographic Entity Codes
***********************************************

NAME
====

   Geo::TigerLine::Record::A - TIGER/Line 1998 Polygon Geographic Entity
Codes

SYNOPSIS
========

     use Geo::TigerLine::Record::A;

     @records = Geo::TigerLine::Record::A->parse_file($fh);
     @records = Geo::TigerLine::Record::A->parse_file($fh, \&callback);

     $record = Geo::TigerLine::Record::A->new(\%fields);

     $record->rt();
     $record->version();
     $record->state();
     $record->county();
     $record->cenid();
     $record->polyid();
     $record->fair();
     $record->fmcd();
     $record->fpl();
     $record->ctbna90();
     $record->blk90();
     $record->cd106();
     $record->cd108();
     $record->sdelm();
     $record->ua();
     $record->sdsec();
     $record->sduni();
     $record->taz();
     $record->ua90();
     $record->urbflag();
     $record->ctpp();
     $record->state90();
     $record->coun90();
     $record->air90();

DESCRIPTION
===========

   This is a class representing record type A of the TIGER/Line 1998
census geographic database.  Each object is one record.  It also contains
methods to parse TIGER/Line record type A files and turn them into objects.

   This is intended as an intermediate format between pulling the raw data
out of the simplistic TIGER/Line data files into something more
sophisticated (a process you should only have to do once).  As such, its
not very fast, but its careful, easy to use and performs some
verifications on the data being read.

   As this class is autogenerated by mk_parsers, think before you modify
this file.  Its OO, so consider sub-classing instead.

Accessors
---------

   These are simple get/set accessors for each field of a record generated
from the TIGER/Line 1998 data dictionary.  They perform some data
validation.

rt
          $data = $record->rt();
          $record->rt($data);

     Record Type.

     Expects alphanumeric data of no more than 1 characters.  $data cannot
     be blank and should be left justified.

version
          $data = $record->version();
          $record->version($data);

     Version Number.

     Expects numeric data of no more than 4 characters.  $data cannot be
     blank and should be left justified.

state
          $data = $record->state();
          $record->state($data);

     FIPS State Code for File.

     Expects numeric data of no more than 2 characters.  $data cannot be
     blank and should be left justified.

county
          $data = $record->county();
          $record->county($data);

     FIPS County Code for File.

     Expects numeric data of no more than 3 characters.  $data cannot be
     blank and should be left justified.

cenid
          $data = $record->cenid();
          $record->cenid($data);

     Census File Identification Code.

     Expects alphanumeric data of no more than 5 characters.  $data cannot
     be blank and should be left justified.

polyid
          $data = $record->polyid();
          $record->polyid($data);

     Polygon Identification Code.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

fair
          $data = $record->fair();
          $record->fair($data);

     FIPS 55 Code (American Indian/Alaska Native Area), 1990.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

fmcd
          $data = $record->fmcd();
          $record->fmcd($data);

     FIPS 55 Code (MCD/CCD), 1990.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

fpl
          $data = $record->fpl();
          $record->fpl($data);

     FIPS 55 Code (Place/CDP), 1990.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

ctbna90
          $data = $record->ctbna90();
          $record->ctbna90($data);

     Census Tract/BNA Code, 1990.

     Expects numeric data of no more than 6 characters.  $data can be blank
     and should be left justified.

blk90
          $data = $record->blk90();
          $record->blk90($data);

     Census Block Number, 1990.

     Expects alphanumeric data of no more than 4 characters.  $data can be
     blank and should be left justified.

cd106
          $data = $record->cd106();
          $record->cd106($data);

     Congressional District Number, 106th.

     Expects numeric data of no more than 2 characters.  $data can be blank
     and should be right justified.

cd108
          $data = $record->cd108();
          $record->cd108($data);

     Congressional District Number, 108th.

     Expects numeric data of no more than 2 characters.  $data can be blank
     and should be right justified.

sdelm
          $data = $record->sdelm();
          $record->sdelm($data);

     School District Code, Elementary School.

     Expects alphanumeric data of no more than 5 characters.  $data can be
     blank and should be left justified.

ua
          $data = $record->ua();
          $record->ua($data);

     Census Urbanized Area Code, 2000 (not filled).

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

sdsec
          $data = $record->sdsec();
          $record->sdsec($data);

     School District Code, Secondary School.

     Expects alphanumeric data of no more than 5 characters.  $data can be
     blank and should be left justified.

sduni
          $data = $record->sduni();
          $record->sduni($data);

     School District Code, Unified District.

     Expects alphanumeric data of no more than 5 characters.  $data can be
     blank and should be left justified.

taz
          $data = $record->taz();
          $record->taz($data);

     Traffic Analysis Zone Code, 1990.

     Expects alphanumeric data of no more than 6 characters.  $data can be
     blank and should be left justified.

ua90
          $data = $record->ua90();
          $record->ua90($data);

     Census Urbanized Area Code, 1990.

     Expects numeric data of no more than 4 characters.  $data can be blank
     and should be left justified.

urbflag
          $data = $record->urbflag();
          $record->urbflag($data);

     Urban/Rural Indicator, 1990.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

ctpp
          $data = $record->ctpp();
          $record->ctpp($data);

     Census Transportation Planning Package Area Code, 1990.

     Expects alphanumeric data of no more than 4 characters.  $data can be
     blank and should be left justified.

state90
          $data = $record->state90();
          $record->state90($data);

     FIPS State Code, 1990.

     Expects numeric data of no more than 2 characters.  $data can be blank
     and should be left justified.

coun90
          $data = $record->coun90();
          $record->coun90($data);

     FIPS County Code, 1990.

     Expects numeric data of no more than 3 characters.  $data can be blank
     and should be left justified.

air90
          $data = $record->air90();
          $record->air90($data);

     Census American Indian/Alaska Native Area Code, 1990.

     Expects numeric data of no more than 4 characters.  $data can be blank
     and should be left justified.

Data dictionary
---------------

   This is the original TIGER/Line 1998 data dictionary from which this
class was generated.

     Record Type A - Polygon Geographic Entity Codes

          Field   BV  Fmt  Type  Beg  End  Len  Description
             RT   No    L     A    1    1    1  Record Type
        VERSION   No    L     N    2    5    4  Version Number
          STATE   No    L     N    6    7    2  FIPS State Code for File
         COUNTY   No    L     N    8   10    3  FIPS County Code for File
          CENID   No    L     A   11   15    5  Census File Identification Code
         POLYID   No    R     N   16   25   10  Polygon Identification Code
           FAIR  Yes    L     N   26   30    5  FIPS 55 Code (American Indian/Alaska Native Area), 1990
           FMCD  Yes    L     N   31   35    5  FIPS 55 Code (MCD/CCD), 1990
            FPL  Yes    L     N   36   40    5  FIPS 55 Code (Place/CDP), 1990
        CTBNA90  Yes    L     N   41   46    6  Census Tract/BNA Code, 1990
          BLK90  Yes    L     A   47   50    4  Census Block Number, 1990
          CD106  Yes    R     N   51   52    2  Congressional District Number, 106th
          CD108  Yes    R     N   53   54    2  Congressional District Number, 108th
          SDELM  Yes    L     A   55   59    5  School District Code, Elementary School
             UA  Yes    L     N   60   64    5  Census Urbanized Area Code, 2000 (not filled)
          SDSEC  Yes    L     A   65   69    5  School District Code, Secondary School
          SDUNI  Yes    L     A   70   74    5  School District Code, Unified District
            TAZ  Yes    L     A   75   80    6  Traffic Analysis Zone Code, 1990
           UA90  Yes    L     N   81   84    4  Census Urbanized Area Code, 1990
        URBFLAG  Yes    L     A   85   85    1  Urban/Rural Indicator, 1990
           CTPP  Yes    L     A   86   89    4  Census Transportation Planning Package Area Code, 1990
        STATE90  Yes    L     N   90   91    2  FIPS State Code, 1990
         COUN90  Yes    L     N   92   94    3  FIPS County Code, 1990
          AIR90  Yes    L     N   95   98    4  Census American Indian/Alaska Native Area Code, 1990

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Geo/TigerLine, `mk_parsers' in this node

Accessor generation for Geo::TigerLine::Record::*
*************************************************

NAME
====

   Geo::TigerLine::Record::Accessor - Accessor generation for
Geo::TigerLine::Record::*

SYNOPSIS
========

     package Geo::TigerLine::Record::1001001;

     use base qw(Geo::TigerLine::Record::Accessor);

     # Generate accessors for each field of the record.
     foreach my $def (values %{__PACKAGE__->Fields}) {
         __PACKAGE__->mk_accessor($def);
     }

     # Turn off input checks, makes inserting raw data faster.
     __PACKAGE__->input_checks(0);

DESCRIPTION
===========

   Allows accessor generation for all the fields of each TIGER/Line record
type.  You probabably shouldn't be here.

   This is a subclass of Class::Accessor.

Additional Methods
------------------

input_check
          Class->input_check($true_or_false);
          $true_or_false = Class->input_check;
          $true_or_false = $obj->input_check;

     If true, turns on the input checks done each time a value is set.
     False turns them off.

     This setting is inherited.

     By default, the checks are on.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Class/Accessor, Geo/TigerLine/Record,

TIGER/Line 1998 Geographic Entity Names
***************************************

NAME
====

   Geo::TigerLine::Record::C - TIGER/Line 1998 Geographic Entity Names

SYNOPSIS
========

     use Geo::TigerLine::Record::C;

     @records = Geo::TigerLine::Record::C->parse_file($fh);
     @records = Geo::TigerLine::Record::C->parse_file($fh, \&callback);

     $record = Geo::TigerLine::Record::C->new(\%fields);

     $record->rt();
     $record->version();
     $record->state();
     $record->county();
     $record->fipsyr();
     $record->fips();
     $record->fipscc();
     $record->pdc();
     $record->lasad();
     $record->entity();
     $record->ma();
     $record->sd();
     $record->air();
     $record->vtd();
     $record->ua();
     $record->anrc();
     $record->census5();
     $record->name();

DESCRIPTION
===========

   This is a class representing record type C of the TIGER/Line 1998
census geographic database.  Each object is one record.  It also contains
methods to parse TIGER/Line record type C files and turn them into objects.

   This is intended as an intermediate format between pulling the raw data
out of the simplistic TIGER/Line data files into something more
sophisticated (a process you should only have to do once).  As such, its
not very fast, but its careful, easy to use and performs some
verifications on the data being read.

   As this class is autogenerated by mk_parsers, think before you modify
this file.  Its OO, so consider sub-classing instead.

Accessors
---------

   These are simple get/set accessors for each field of a record generated
from the TIGER/Line 1998 data dictionary.  They perform some data
validation.

rt
          $data = $record->rt();
          $record->rt($data);

     Record Type.

     Expects alphanumeric data of no more than 1 characters.  $data cannot
     be blank and should be left justified.

version
          $data = $record->version();
          $record->version($data);

     Version Number.

     Expects numeric data of no more than 4 characters.  $data cannot be
     blank and should be left justified.

state
          $data = $record->state();
          $record->state($data);

     FIPS State Code.

     Expects numeric data of no more than 2 characters.  $data can be blank
     and should be left justified.

county
          $data = $record->county();
          $record->county($data);

     FIPS County Code.

     Expects numeric data of no more than 3 characters.  $data can be blank
     and should be left justified.

fipsyr
          $data = $record->fipsyr();
          $record->fipsyr($data);

     FIPS Code and Name Relationship Applicable Year.

     Expects numeric data of no more than 4 characters.  $data can be blank
     and should be left justified.

fips
          $data = $record->fips();
          $record->fips($data);

     FIPS PUB 55-3 Code.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

fipscc
          $data = $record->fipscc();
          $record->fipscc($data);

     FIPS 55 Class Code.

     Expects alphanumeric data of no more than 2 characters.  $data can be
     blank and should be left justified.

pdc
          $data = $record->pdc();
          $record->pdc($data);

     Census Place Description Code.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

lasad
          $data = $record->lasad();
          $record->lasad($data);

     Legal/Administrative/Statistical Area Description Code.

     Expects numeric data of no more than 2 characters.  $data can be blank
     and should be left justified.

entity
          $data = $record->entity();
          $record->entity($data);

     Entity Type Code.

     Expects alphanumeric data of no more than 1 characters.  $data cannot
     be blank and should be left justified.

ma
          $data = $record->ma();
          $record->ma($data);

     Metropolitan Area Code.

     Expects numeric data of no more than 4 characters.  $data can be blank
     and should be left justified.

sd
          $data = $record->sd();
          $record->sd($data);

     School District Code.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

air
          $data = $record->air();
          $record->air($data);

     Census American Indian/Alaska Native Area Code.

     Expects numeric data of no more than 4 characters.  $data can be blank
     and should be left justified.

vtd
          $data = $record->vtd();
          $record->vtd($data);

     Voting District Code.

     Expects alphanumeric data of no more than 6 characters.  $data can be
     blank and should be right justified.

ua
          $data = $record->ua();
          $record->ua($data);

     Census Urbanized Area Code.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

anrc
          $data = $record->anrc();
          $record->anrc($data);

     Census Alaska Native Regional Corporation Code.

     Expects numeric data of no more than 2 characters.  $data can be blank
     and should be left justified.

census5
          $data = $record->census5();
          $record->census5($data);

     Census Use 5.

     Expects numeric data of no more than 3 characters.  $data can be blank
     and should be left justified.

name
          $data = $record->name();
          $record->name($data);

     Name of Geographic Area.

     Expects alphanumeric data of no more than 58 characters.  $data
     cannot be blank and should be left justified.

Data dictionary
---------------

   This is the original TIGER/Line 1998 data dictionary from which this
class was generated.

     Record Type C - Geographic Entity Names

          Field   BV  Fmt  Type  Beg  End  Len  Description
             RT   No    L     A    1    1    1  Record Type
        VERSION   No    L     N    2    5    4  Version Number
          STATE  Yes    L     N    6    7    2  FIPS State Code
         COUNTY  Yes    L     N    8   10    3  FIPS County Code
         FIPSYR  Yes    L     N   11   14    4  FIPS Code and Name Relationship Applicable Year
           FIPS  Yes    L     N   15   19    5  FIPS PUB 55-3 Code
         FIPSCC  Yes    L     A   20   21    2  FIPS 55 Class Code
            PDC  Yes    L     A   22   22    1  Census Place Description Code
          LASAD  Yes    L     N   23   24    2  Legal/Administrative/Statistical Area Description Code
         ENTITY   No    L     A   25   25    1  Entity Type Code
             MA  Yes    L     N   26   29    4  Metropolitan Area Code
             SD  Yes    L     N   30   34    5  School District Code
            AIR  Yes    L     N   35   38    4  Census American Indian/Alaska Native Area Code
            VTD  Yes    R     A   39   44    6  Voting District Code
             UA  Yes    L     N   45   49    5  Census Urbanized Area Code
           ANRC  Yes    L     N   50   51    2  Census Alaska Native Regional Corporation Code
        CENSUS5  Yes    L     N   52   54    3  Census Use 5
           NAME   No    L     A   55  112   58  Name of Geographic Area

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Geo/TigerLine, `mk_parsers' in this node

TIGER/Line 1998 TIGER/Line ID History
*************************************

NAME
====

   Geo::TigerLine::Record::H - TIGER/Line 1998 TIGER/Line ID History

SYNOPSIS
========

     use Geo::TigerLine::Record::H;

     @records = Geo::TigerLine::Record::H->parse_file($fh);
     @records = Geo::TigerLine::Record::H->parse_file($fh, \&callback);

     $record = Geo::TigerLine::Record::H->new(\%fields);

     $record->rt();
     $record->version();
     $record->state();
     $record->county();
     $record->tlid();
     $record->hist();
     $record->source();
     $record->tlidfr1();
     $record->tlidfr2();
     $record->tlidto1();
     $record->tlidto2();

DESCRIPTION
===========

   This is a class representing record type H of the TIGER/Line 1998
census geographic database.  Each object is one record.  It also contains
methods to parse TIGER/Line record type H files and turn them into objects.

   This is intended as an intermediate format between pulling the raw data
out of the simplistic TIGER/Line data files into something more
sophisticated (a process you should only have to do once).  As such, its
not very fast, but its careful, easy to use and performs some
verifications on the data being read.

   As this class is autogenerated by mk_parsers, think before you modify
this file.  Its OO, so consider sub-classing instead.

Accessors
---------

   These are simple get/set accessors for each field of a record generated
from the TIGER/Line 1998 data dictionary.  They perform some data
validation.

rt
          $data = $record->rt();
          $record->rt($data);

     Record Type.

     Expects alphanumeric data of no more than 1 characters.  $data cannot
     be blank and should be left justified.

version
          $data = $record->version();
          $record->version($data);

     Version Number.

     Expects numeric data of no more than 4 characters.  $data cannot be
     blank and should be left justified.

state
          $data = $record->state();
          $record->state($data);

     FIPS State Code for File.

     Expects numeric data of no more than 2 characters.  $data cannot be
     blank and should be left justified.

county
          $data = $record->county();
          $record->county($data);

     FIPS County Code for File.

     Expects numeric data of no more than 3 characters.  $data cannot be
     blank and should be left justified.

tlid
          $data = $record->tlid();
          $record->tlid($data);

     TIGER/Line ID, Permanent Record Number.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

hist
          $data = $record->hist();
          $record->hist($data);

     History or Last Source Code to Update.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

source
          $data = $record->source();
          $record->source($data);

     Source or First Source Code to Update.

     Expects alphanumeric data of no more than 1 characters.  $data cannot
     be blank and should be left justified.

tlidfr1
          $data = $record->tlidfr1();
          $record->tlidfr1($data);

     TIGER/Line ID, Created From Number 1.

     Expects numeric data of no more than 10 characters.  $data can be
     blank and should be right justified.

tlidfr2
          $data = $record->tlidfr2();
          $record->tlidfr2($data);

     TIGER/Line ID, Created From Number 2.

     Expects numeric data of no more than 10 characters.  $data can be
     blank and should be right justified.

tlidto1
          $data = $record->tlidto1();
          $record->tlidto1($data);

     TIGER/Line ID, Became Number 1.

     Expects numeric data of no more than 10 characters.  $data can be
     blank and should be right justified.

tlidto2
          $data = $record->tlidto2();
          $record->tlidto2($data);

     TIGER/Line ID, Became Number 2.

     Expects numeric data of no more than 10 characters.  $data can be
     blank and should be right justified.

Data dictionary
---------------

   This is the original TIGER/Line 1998 data dictionary from which this
class was generated.

     Record Type H - TIGER/Line ID History

          Field   BV  Fmt  Type  Beg  End  Len  Description
             RT   No    L     A    1    1    1  Record Type
        VERSION   No    L     N    2    5    4  Version Number
          STATE   No    L     N    6    7    2  FIPS State Code for File
         COUNTY   No    L     N    8   10    3  FIPS County Code for File
           TLID   No    R     N   11   20   10  TIGER/Line ID, Permanent Record Number
           HIST  Yes    L     A   21   21    1  History or Last Source Code to Update
         SOURCE   No    L     A   22   22    1  Source or First Source Code to Update
        TLIDFR1  Yes    R     N   23   32   10  TIGER/Line ID, Created From Number 1
        TLIDFR2  Yes    R     N   33   42   10  TIGER/Line ID, Created From Number 2
        TLIDTO1  Yes    R     N   43   52   10  TIGER/Line ID, Became Number 1
        TLIDTO2  Yes    R     N   53   62   10  TIGER/Line ID, Became Number 2

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Geo/TigerLine, `mk_parsers' in this node

TIGER/Line 1998 Link Between Complete Chains and Polygons
*********************************************************

NAME
====

   Geo::TigerLine::Record::I - TIGER/Line 1998 Link Between Complete
Chains and Polygons

SYNOPSIS
========

     use Geo::TigerLine::Record::I;

     @records = Geo::TigerLine::Record::I->parse_file($fh);
     @records = Geo::TigerLine::Record::I->parse_file($fh, \&callback);

     $record = Geo::TigerLine::Record::I->new(\%fields);

     $record->rt();
     $record->version();
     $record->tlid();
     $record->state();
     $record->county();
     $record->rtlink();
     $record->cenidl();
     $record->polyidl();
     $record->cenidr();
     $record->polyidr();
     $record->filler();

DESCRIPTION
===========

   This is a class representing record type I of the TIGER/Line 1998
census geographic database.  Each object is one record.  It also contains
methods to parse TIGER/Line record type I files and turn them into objects.

   This is intended as an intermediate format between pulling the raw data
out of the simplistic TIGER/Line data files into something more
sophisticated (a process you should only have to do once).  As such, its
not very fast, but its careful, easy to use and performs some
verifications on the data being read.

   As this class is autogenerated by mk_parsers, think before you modify
this file.  Its OO, so consider sub-classing instead.

Accessors
---------

   These are simple get/set accessors for each field of a record generated
from the TIGER/Line 1998 data dictionary.  They perform some data
validation.

rt
          $data = $record->rt();
          $record->rt($data);

     Record Type.

     Expects alphanumeric data of no more than 1 characters.  $data cannot
     be blank and should be left justified.

version
          $data = $record->version();
          $record->version($data);

     Version Number.

     Expects numeric data of no more than 4 characters.  $data cannot be
     blank and should be left justified.

tlid
          $data = $record->tlid();
          $record->tlid($data);

     TIGER/Line ID, Permanent Record Number.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

state
          $data = $record->state();
          $record->state($data);

     FIPS State Code for File.

     Expects numeric data of no more than 2 characters.  $data cannot be
     blank and should be left justified.

county
          $data = $record->county();
          $record->county($data);

     FIPS County Code for File.

     Expects numeric data of no more than 3 characters.  $data cannot be
     blank and should be left justified.

rtlink
          $data = $record->rtlink();
          $record->rtlink($data);

     Record Type of Link.

     Expects alphanumeric data of no more than 1 characters.  $data cannot
     be blank and should be left justified.

cenidl
          $data = $record->cenidl();
          $record->cenidl($data);

     Census File Identification Code, Left.

     Expects alphanumeric data of no more than 5 characters.  $data can be
     blank and should be left justified.

polyidl
          $data = $record->polyidl();
          $record->polyidl($data);

     Polygon Identification Code, Left.

     Expects numeric data of no more than 10 characters.  $data can be
     blank and should be right justified.

cenidr
          $data = $record->cenidr();
          $record->cenidr($data);

     Census File Identification Code, Right.

     Expects alphanumeric data of no more than 5 characters.  $data can be
     blank and should be left justified.

polyidr
          $data = $record->polyidr();
          $record->polyidr($data);

     Polygon Identification Code, Right.

     Expects numeric data of no more than 10 characters.  $data can be
     blank and should be right justified.

filler
          $data = $record->filler();
          $record->filler($data);

     Filler (to make even character count).

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

Data dictionary
---------------

   This is the original TIGER/Line 1998 data dictionary from which this
class was generated.

     Record Type I - Link Between Complete Chains and Polygons

          Field   BV  Fmt  Type  Beg  End  Len  Description
             RT   No    L     A    1    1    1  Record Type
        VERSION   No    L     N    2    5    4  Version Number
           TLID   No    R     N    6   15   10  TIGER/Line ID, Permanent Record Number
          STATE   No    L     N   16   17    2  FIPS State Code for File
         COUNTY   No    L     N   18   20    3  FIPS County Code for File
         RTLINK   No    L     A   21   21    1  Record Type of Link
         CENIDL  Yes    L     A   22   26    5  Census File Identification Code, Left
        POLYIDL  Yes    R     N   27   36   10  Polygon Identification Code, Left
         CENIDR  Yes    L     A   37   41    5  Census File Identification Code, Right
        POLYIDR  Yes    R     N   42   51   10  Polygon Identification Code, Right
         FILLER  Yes    L     A   52   52    1  Filler (to make even character count)

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Geo/TigerLine, `mk_parsers' in this node

TIGER/Line 1998 Polygon Internal Point
**************************************

NAME
====

   Geo::TigerLine::Record::P - TIGER/Line 1998 Polygon Internal Point

SYNOPSIS
========

     use Geo::TigerLine::Record::P;

     @records = Geo::TigerLine::Record::P->parse_file($fh);
     @records = Geo::TigerLine::Record::P->parse_file($fh, \&callback);

     $record = Geo::TigerLine::Record::P->new(\%fields);

     $record->rt();
     $record->version();
     $record->state();
     $record->county();
     $record->cenid();
     $record->polyid();
     $record->polylong();
     $record->polylat();

DESCRIPTION
===========

   This is a class representing record type P of the TIGER/Line 1998
census geographic database.  Each object is one record.  It also contains
methods to parse TIGER/Line record type P files and turn them into objects.

   This is intended as an intermediate format between pulling the raw data
out of the simplistic TIGER/Line data files into something more
sophisticated (a process you should only have to do once).  As such, its
not very fast, but its careful, easy to use and performs some
verifications on the data being read.

   As this class is autogenerated by mk_parsers, think before you modify
this file.  Its OO, so consider sub-classing instead.

Accessors
---------

   These are simple get/set accessors for each field of a record generated
from the TIGER/Line 1998 data dictionary.  They perform some data
validation.

rt
          $data = $record->rt();
          $record->rt($data);

     Record Type.

     Expects alphanumeric data of no more than 1 characters.  $data cannot
     be blank and should be left justified.

version
          $data = $record->version();
          $record->version($data);

     Version Number.

     Expects numeric data of no more than 4 characters.  $data cannot be
     blank and should be left justified.

state
          $data = $record->state();
          $record->state($data);

     FIPS State Code for File.

     Expects numeric data of no more than 2 characters.  $data cannot be
     blank and should be left justified.

county
          $data = $record->county();
          $record->county($data);

     FIPS County Code for File.

     Expects numeric data of no more than 3 characters.  $data cannot be
     blank and should be left justified.

cenid
          $data = $record->cenid();
          $record->cenid($data);

     Census File Identification Code.

     Expects alphanumeric data of no more than 5 characters.  $data cannot
     be blank and should be left justified.

polyid
          $data = $record->polyid();
          $record->polyid($data);

     Polygon Identification Code.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

polylong
          $data = $record->polylong();
          $record->polylong($data);

     Polygon Internal Point Longitude.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

polylat
          $data = $record->polylat();
          $record->polylat($data);

     Polygon Internal Point Latitude.

     Expects numeric data of no more than 9 characters.  $data cannot be
     blank and should be right justified.

Data dictionary
---------------

   This is the original TIGER/Line 1998 data dictionary from which this
class was generated.

     Record Type P - Polygon Internal Point

          Field   BV  Fmt  Type  Beg  End  Len  Description
             RT   No    L     A    1    1    1  Record Type
        VERSION   No    L     N    2    5    4  Version Number
          STATE   No    L     N    6    7    2  FIPS State Code for File
         COUNTY   No    L     N    8   10    3  FIPS County Code for File
          CENID   No    L     A   11   15    5  Census File Identification Code
         POLYID   No    R     N   16   25   10  Polygon Identification Code
       POLYLONG   No    R     N   26   35   10  Polygon Internal Point Longitude
        POLYLAT   No    R     N   36   44    9  Polygon Internal Point Latitude

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Geo/TigerLine, `mk_parsers' in this node

Parsing superclass for TIGER/Line records.
******************************************

NAME
====

   Geo::TigerLine::Record::Parser - Parsing superclass for TIGER/Line
records.

SYNOPSIS
========

     package Geo::TigerLine::Record::23;
     use base qw(Geo::TigerLine::Record::Parser);

     @records = __PACKAGE__->parse_file($fh);
     __PACKAGE__->parse_file($fh, \&callback);

     $record = __PACKAGE__->parse($row);

DESCRIPTION
===========

   Parses raw TIGER/Line data into Geo::TigerLine::Record objects.  This
is intended to be used as a superclass of Geo::TigerLine::Record objects
and not used directly.

   You shouldn't be here.

Methods
-------

parse_file
          @records = __PACKAGE__->parse_file($fh);
          __PACKAGE__->parse_file($fh, \&callback);

     Parses a given filehandle as a TIGER/Line data file.  The data
     definition is taken from __PACKAGE__->Pack_Tmpl, __PACKAGE__->Dict and
     __PACKAGE__->Fields.  Returns an array of objects of type __PACKAGE__.

     &callback will be called for each record and given a record object and
     its position in the file (ie. 1 for the first, 2 for the second,
     etc...).  A sample callback...

          sub callback {
              my($record, $pos) = @_;

          printf "Record #$pos is %s\n", $record->tlid;
              }

     If a &callback is given, a list of records will *NOT* be returned.
     It is assumed you'll be taking care of arrangements to store the
     records in your callback and @records can eat up huge amounds of
     memory for a typical TIGER/Line data file.

parse
          $record = __PACKAGE__->parse($line);

     Parses a single record of TIGER/Line data.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Geo/TigerLine,

TIGER/Line 1998 TIGER/Line ID Record Number Range
*************************************************

NAME
====

   Geo::TigerLine::Record::R - TIGER/Line 1998 TIGER/Line ID Record Number
Range

SYNOPSIS
========

     use Geo::TigerLine::Record::R;

     @records = Geo::TigerLine::Record::R->parse_file($fh);
     @records = Geo::TigerLine::Record::R->parse_file($fh, \&callback);

     $record = Geo::TigerLine::Record::R->new(\%fields);

     $record->rt();
     $record->version();
     $record->state();
     $record->county();
     $record->cenid();
     $record->maxid();
     $record->minid();
     $record->highid();
     $record->filler();

DESCRIPTION
===========

   This is a class representing record type R of the TIGER/Line 1998
census geographic database.  Each object is one record.  It also contains
methods to parse TIGER/Line record type R files and turn them into objects.

   This is intended as an intermediate format between pulling the raw data
out of the simplistic TIGER/Line data files into something more
sophisticated (a process you should only have to do once).  As such, its
not very fast, but its careful, easy to use and performs some
verifications on the data being read.

   As this class is autogenerated by mk_parsers, think before you modify
this file.  Its OO, so consider sub-classing instead.

Accessors
---------

   These are simple get/set accessors for each field of a record generated
from the TIGER/Line 1998 data dictionary.  They perform some data
validation.

rt
          $data = $record->rt();
          $record->rt($data);

     Record Type.

     Expects alphanumeric data of no more than 1 characters.  $data cannot
     be blank and should be left justified.

version
          $data = $record->version();
          $record->version($data);

     Version Number.

     Expects numeric data of no more than 4 characters.  $data cannot be
     blank and should be left justified.

state
          $data = $record->state();
          $record->state($data);

     FIPS State Code for File.

     Expects numeric data of no more than 2 characters.  $data cannot be
     blank and should be left justified.

county
          $data = $record->county();
          $record->county($data);

     FIPS County Code for File.

     Expects numeric data of no more than 3 characters.  $data cannot be
     blank and should be left justified.

cenid
          $data = $record->cenid();
          $record->cenid($data);

     Census File Identification Code.

     Expects alphanumeric data of no more than 5 characters.  $data cannot
     be blank and should be left justified.

maxid
          $data = $record->maxid();
          $record->maxid($data);

     TIGER/Line ID, Maximum Permanent ID for Census File.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

minid
          $data = $record->minid();
          $record->minid($data);

     TIGER/Line ID, Minimum Permanent ID for Census File.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

highid
          $data = $record->highid();
          $record->highid($data);

     TIGER/Line ID, Current High ID for Census File.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

filler
          $data = $record->filler();
          $record->filler($data);

     Filler (to make even character count).

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

Data dictionary
---------------

   This is the original TIGER/Line 1998 data dictionary from which this
class was generated.

     Record Type R - TIGER/Line ID Record Number Range

          Field   BV  Fmt  Type  Beg  End  Len  Description
             RT   No    L     A    1    1    1  Record Type
        VERSION   No    L     N    2    5    4  Version Number
          STATE   No    L     N    6    7    2  FIPS State Code for File
         COUNTY   No    L     N    8   10    3  FIPS County Code for File
          CENID   No    L     A   11   15    5  Census File Identification Code
          MAXID   No    R     N   16   25   10  TIGER/Line ID, Maximum Permanent ID for Census File
          MINID   No    R     N   26   35   10  TIGER/Line ID, Minimum Permanent ID for Census File
         HIGHID   No    R     N   36   45   10  TIGER/Line ID, Current High ID for Census File
         FILLER  Yes    L     A   46   46    1  Filler (to make even character count)

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Geo/TigerLine, `mk_parsers' in this node

TIGER/Line 1998 Polygon Additional Geographic Entity Codes
**********************************************************

NAME
====

   Geo::TigerLine::Record::S - TIGER/Line 1998 Polygon Additional
Geographic Entity Codes

SYNOPSIS
========

     use Geo::TigerLine::Record::S;

     @records = Geo::TigerLine::Record::S->parse_file($fh);
     @records = Geo::TigerLine::Record::S->parse_file($fh, \&callback);

     $record = Geo::TigerLine::Record::S->new(\%fields);

     $record->rt();
     $record->version();
     $record->state();
     $record->county();
     $record->cenid();
     $record->polyid();
     $record->water();
     $record->cmsa();
     $record->ma();
     $record->fair();
     $record->air();
     $record->trust();
     $record->anrc();
     $record->state();
     $record->county();
     $record->fccity();
     $record->fmcd();
     $record->fsmcd();
     $record->fpl();
     $record->ct();
     $record->blk();
     $record->census6();
     $record->cdcu();
     $record->stsenate();
     $record->sthouse();
     $record->census7();
     $record->rs7();
     $record->vtd();
     $record->statecol();
     $record->councol();
     $record->blkcol();
     $record->blksufcol();
     $record->zcta();
     $record->rs8();

DESCRIPTION
===========

   This is a class representing record type S of the TIGER/Line 1998
census geographic database.  Each object is one record.  It also contains
methods to parse TIGER/Line record type S files and turn them into objects.

   This is intended as an intermediate format between pulling the raw data
out of the simplistic TIGER/Line data files into something more
sophisticated (a process you should only have to do once).  As such, its
not very fast, but its careful, easy to use and performs some
verifications on the data being read.

   As this class is autogenerated by mk_parsers, think before you modify
this file.  Its OO, so consider sub-classing instead.

Accessors
---------

   These are simple get/set accessors for each field of a record generated
from the TIGER/Line 1998 data dictionary.  They perform some data
validation.

rt
          $data = $record->rt();
          $record->rt($data);

     Record Type.

     Expects alphanumeric data of no more than 1 characters.  $data cannot
     be blank and should be left justified.

version
          $data = $record->version();
          $record->version($data);

     Version Number.

     Expects numeric data of no more than 4 characters.  $data cannot be
     blank and should be left justified.

state
          $data = $record->state();
          $record->state($data);

     FIPS State Code, Current.

     Expects numeric data of no more than 2 characters.  $data can be blank
     and should be left justified.

county
          $data = $record->county();
          $record->county($data);

     FIPS County Code, Current.

     Expects numeric data of no more than 3 characters.  $data can be blank
     and should be left justified.

cenid
          $data = $record->cenid();
          $record->cenid($data);

     Census File Identification Code.

     Expects alphanumeric data of no more than 5 characters.  $data cannot
     be blank and should be left justified.

polyid
          $data = $record->polyid();
          $record->polyid($data);

     Polygon Identification Code.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

water
          $data = $record->water();
          $record->water($data);

     Water Flag.

     Expects numeric data of no more than 1 characters.  $data can be blank
     and should be left justified.

cmsa
          $data = $record->cmsa();
          $record->cmsa($data);

     FIPS Consolidated Metropolitan Statistical Area Code, Current.

     Expects numeric data of no more than 4 characters.  $data can be blank
     and should be left justified.

ma
          $data = $record->ma();
          $record->ma($data);

     FIPS Metropolitan Area Code, Current.

     Expects numeric data of no more than 4 characters.  $data can be blank
     and should be left justified.

fair
          $data = $record->fair();
          $record->fair($data);

     FIPS 55 Code (American Indian/Alaska Native Area), Current.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

air
          $data = $record->air();
          $record->air($data);

     Census American Indian/Alaska Native Area Code, Current.

     Expects numeric data of no more than 4 characters.  $data can be blank
     and should be left justified.

trust
          $data = $record->trust();
          $record->trust($data);

     American Indian Trust Land Flag, Current.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

anrc
          $data = $record->anrc();
          $record->anrc($data);

     Census Alaska Native Regional Corporation Code, Current.

     Expects numeric data of no more than 2 characters.  $data can be blank
     and should be left justified.

state
          $data = $record->state();
          $record->state($data);

     FIPS State Code, Current.

     Expects numeric data of no more than 2 characters.  $data can be blank
     and should be left justified.

county
          $data = $record->county();
          $record->county($data);

     FIPS County Code, Current.

     Expects numeric data of no more than 3 characters.  $data can be blank
     and should be left justified.

fccity
          $data = $record->fccity();
          $record->fccity($data);

     FIPS 55 Code (Consolidated City), Current.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

fmcd
          $data = $record->fmcd();
          $record->fmcd($data);

     FIPS 55 Code (MCD/CCD), Current.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

fsmcd
          $data = $record->fsmcd();
          $record->fsmcd($data);

     FIPS 55 Code (Sub-MCD), Current.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

fpl
          $data = $record->fpl();
          $record->fpl($data);

     FIPS 55 Code (Place), Current.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be left justified.

ct
          $data = $record->ct();
          $record->ct($data);

     Census Tract Code, 1990.

     Expects numeric data of no more than 6 characters.  $data can be blank
     and should be left justified.

blk
          $data = $record->blk();
          $record->blk($data);

     Census Block Number, 1990.

     Expects alphanumeric data of no more than 4 characters.  $data can be
     blank and should be left justified.

census6
          $data = $record->census6();
          $record->census6($data);

     Census Use 6.

     Expects numeric data of no more than 1 characters.  $data can be blank
     and should be right justified.

cdcu
          $data = $record->cdcu();
          $record->cdcu($data);

     Congressional District Code, Current.

     Expects numeric data of no more than 2 characters.  $data can be blank
     and should be right justified.

stsenate
          $data = $record->stsenate();
          $record->stsenate($data);

     State Senate District Code (not filled).

     Expects alphanumeric data of no more than 3 characters.  $data can be
     blank and should be right justified.

sthouse
          $data = $record->sthouse();
          $record->sthouse($data);

     State House District Code (not filled).

     Expects alphanumeric data of no more than 3 characters.  $data can be
     blank and should be right justified.

census7
          $data = $record->census7();
          $record->census7($data);

     Census Use 7.

     Expects alphanumeric data of no more than 5 characters.  $data can be
     blank and should be left justified.

rs7
          $data = $record->rs7();
          $record->rs7($data);

     Reserved Space 7.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

vtd
          $data = $record->vtd();
          $record->vtd($data);

     Voting District Code (not filled).

     Expects alphanumeric data of no more than 6 characters.  $data can be
     blank and should be left justified.

statecol
          $data = $record->statecol();
          $record->statecol($data);

     Census 2000 Collection State FIPS Code.

     Expects numeric data of no more than 2 characters.  $data can be blank
     and should be left justified.

councol
          $data = $record->councol();
          $record->councol($data);

     Census 2000 Collection County FIPS Code.

     Expects numeric data of no more than 3 characters.  $data can be blank
     and should be left justified.

blkcol
          $data = $record->blkcol();
          $record->blkcol($data);

     Census 2000 Collection Block Number.

     Expects numeric data of no more than 5 characters.  $data can be blank
     and should be right justified.

blksufcol
          $data = $record->blksufcol();
          $record->blksufcol($data);

     Census 2000 Collection Block Number Suffix.

     Expects alphanumeric data of no more than 1 characters.  $data can be
     blank and should be left justified.

zcta
          $data = $record->zcta();
          $record->zcta($data);

     ZIP Code ® Tabulation Area, 2000 (not filled).

     Expects alphanumeric data of no more than 5 characters.  $data can be
     blank and should be left justified.

rs8
          $data = $record->rs8();
          $record->rs8($data);

     Reserved Space 8.

     Expects alphanumeric data of no more than 2 characters.  $data can be
     blank and should be left justified.

Data dictionary
---------------

   This is the original TIGER/Line 1998 data dictionary from which this
class was generated.

     Record Type S - Polygon Additional Geographic Entity Codes

          Field   BV  Fmt  Type  Beg  End  Len  Description
             RT   No    L     A    1    1    1  Record Type
        VERSION   No    L     N    2    5    4  Version Number
          STATE   No    L     N    6    7    2  FIPS State Code for File
         COUNTY   No    L     N    8   10    3  FIPS County Code for File
          CENID   No    L     A   11   15    5  Census File Identification Code
         POLYID   No    R     N   16   25   10  Polygon Identification Code
          WATER  Yes    L     N   26   26    1  Water Flag
           CMSA  Yes    L     N   27   30    4  FIPS Consolidated Metropolitan Statistical Area Code, Current
             MA  Yes    L     N   31   34    4  FIPS Metropolitan Area Code, Current
           FAIR  Yes    L     N   35   39    5  FIPS 55 Code (American Indian/Alaska Native Area), Current
            AIR  Yes    L     N   40   43    4  Census American Indian/Alaska Native Area Code, Current
          TRUST  Yes    L     A   44   44    1  American Indian Trust Land Flag, Current
           ANRC  Yes    L     N   45   46    2  Census Alaska Native Regional Corporation Code, Current
          STATE  Yes    L     N   47   48    2  FIPS State Code, Current
         COUNTY  Yes    L     N   49   51    3  FIPS County Code, Current
         FCCITY  Yes    L     N   52   56    5  FIPS 55 Code (Consolidated City), Current
           FMCD  Yes    L     N   57   61    5  FIPS 55 Code (MCD/CCD), Current
          FSMCD  Yes    L     N   62   66    5  FIPS 55 Code (Sub-MCD), Current
            FPL  Yes    L     N   67   71    5  FIPS 55 Code (Place), Current
             CT  Yes    L     N   72   77    6  Census Tract Code, 1990
            BLK  Yes    L     A   78   81    4  Census Block Number, 1990
        CENSUS6  Yes    R     N   82   82    1  Census Use 6
           CDCU  Yes    R     N   83   84    2  Congressional District Code, Current
       STSENATE  Yes    R     A   85   87    3  State Senate District Code (not filled)
        STHOUSE  Yes    R     A   88   90    3  State House District Code (not filled)
        CENSUS7  Yes    L     A   91   95    5  Census Use 7
            RS7  Yes    L     A   96   96    1  Reserved Space 7
            VTD  Yes    L     A   97  102    6  Voting District Code (not filled)
       STATECOL  Yes    L     N  103  104    2  Census 2000 Collection State FIPS Code
        COUNCOL  Yes    L     N  105  107    3  Census 2000 Collection County FIPS Code
         BLKCOL  Yes    R     N  108  112    5  Census 2000 Collection Block Number
      BLKSUFCOL  Yes    L     A  113  113    1  Census 2000 Collection Block Number Suffix
           ZCTA  Yes    L     A  114  118    5  ZIP Code ® Tabulation Area, 2000 (not filled)
            RS8  Yes    L     A  119  120    2  Reserved Space 8

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Geo/TigerLine, `mk_parsers' in this node

TIGER/Line 1998 ZIP+4 Codes
***************************

NAME
====

   Geo::TigerLine::Record::Z - TIGER/Line 1998 ZIP+4 Codes

SYNOPSIS
========

     use Geo::TigerLine::Record::Z;

     @records = Geo::TigerLine::Record::Z->parse_file($fh);
     @records = Geo::TigerLine::Record::Z->parse_file($fh, \&callback);

     $record = Geo::TigerLine::Record::Z->new(\%fields);

     $record->rt();
     $record->version();
     $record->tlid();
     $record->rtsq();
     $record->zip4l();
     $record->zip4r();

DESCRIPTION
===========

   This is a class representing record type Z of the TIGER/Line 1998
census geographic database.  Each object is one record.  It also contains
methods to parse TIGER/Line record type Z files and turn them into objects.

   This is intended as an intermediate format between pulling the raw data
out of the simplistic TIGER/Line data files into something more
sophisticated (a process you should only have to do once).  As such, its
not very fast, but its careful, easy to use and performs some
verifications on the data being read.

   As this class is autogenerated by mk_parsers, think before you modify
this file.  Its OO, so consider sub-classing instead.

Accessors
---------

   These are simple get/set accessors for each field of a record generated
from the TIGER/Line 1998 data dictionary.  They perform some data
validation.

rt
          $data = $record->rt();
          $record->rt($data);

     Record Type.

     Expects alphanumeric data of no more than 1 characters.  $data cannot
     be blank and should be left justified.

version
          $data = $record->version();
          $record->version($data);

     Version Number.

     Expects numeric data of no more than 4 characters.  $data cannot be
     blank and should be left justified.

tlid
          $data = $record->tlid();
          $record->tlid($data);

     TIGER/Line ID, Permanent Record Number.

     Expects numeric data of no more than 10 characters.  $data cannot be
     blank and should be right justified.

rtsq
          $data = $record->rtsq();
          $record->rtsq($data);

     Record Sequence Number.

     Expects numeric data of no more than 3 characters.  $data cannot be
     blank and should be right justified.

zip4l
          $data = $record->zip4l();
          $record->zip4l($data);

     +4 Postal Add-On Code, Left.

     Expects numeric data of no more than 4 characters.  $data can be blank
     and should be left justified.

zip4r
          $data = $record->zip4r();
          $record->zip4r($data);

     +4 Postal Add-On Code, Right.

     Expects numeric data of no more than 4 characters.  $data can be blank
     and should be left justified.

Data dictionary
---------------

   This is the original TIGER/Line 1998 data dictionary from which this
class was generated.

     Record Type Z - ZIP+4 Codes

          Field   BV  Fmt  Type  Beg  End  Len  Description
             RT   No    L     A    1    1    1  Record Type
        VERSION   No    L     N    2    5    4  Version Number
           TLID   No    R     N    6   15   10  TIGER/Line ID, Permanent Record Number
           RTSQ   No    R     N   16   18    3  Record Sequence Number
          ZIP4L  Yes    L     N   19   22    4  +4 Postal Add-On Code, Left
          ZIP4R  Yes    L     N   23   26    4  +4 Postal Add-On Code, Right

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Geo/TigerLine, `mk_parsers' in this node

An open path representing the shape of a line feature.
******************************************************

NAME
====

   Geo::Walkabout::Chain - An open path representing the shape of a line
feature.

SYNOPSIS
========

     require Geo::Walkabout::Chain;

     my $chain = Geo::Walkabout::Chain->new([1,1],[5,10.2],[12,13]);
     my $chain = Geo::Walkabout::Chain->new_from_pgpath('[(1,1),(5,10.2),(12,13)]');

     my $begin = $chain->begin;
     my $end   = $chain->end;
     my @shape = $chain->shape;
     my @raw_chain = $chain->chain;
     my $pg_path = $chain->as_pgpath;

     $chain->append_shape(@points);

DESCRIPTION
===========

   This is a representation of a complete chain.  Typically, it should not
be used directly, instead Geo::Walkabout::Line encapsulates a single
Geo::Walkabout::Chain.

   A single point in a chain is represented as a two element array
representing a single point of latitude and longitutde.  (OO dogma says
these should be objects, too, but if I wanted to be that silly I'd be
using Java.)

Public Methods
==============

Constructors
------------

new
          my $chain = Geo::Walkabout::Chain->new([$lat1, $long1],
                                                 [$lat2, $long2],
                                                 ...
                                                );

     Creates a new Geo::Walkabout::Chain object from a list of points (two
     element array references).  The first point is the start of the chain,
     the last is the end (or vice-versa depending on which way you look.)
     The rest are "shape" coordinates.

new_from_pgpath
          my $chain = Geo::Walkabout::Chain->new_from_pgpath($postgres_path);

     An alternative constructor, it takes a PostgreSQL style open PATH of
     the form:

          [ ( lat1, long1 ), ... , (latn, longn) ]

     So something like '[(1,1), (-1,2.2), (-2,3)]'.  This is very helpful
     when reading in chains from a PostgreSQL database.

Accessors
---------

begin
          my $beginning_point = $chain->begin;

     Returns the beginning point of this chain as a two element array
     reference.

end
          my $end_point = $chain->end;

     Returns the end point of this chain as a two element array reference.

shape
          my @shape = $chain->shape;

     Returns the shaping points of this chain, ie. those points between the
     start and the end which determine the shape of the chain (without
     them, its just a line segment).

chain
          my @raw_chain = $chain->chain;

     Dumps the chain this object represents as a series of points.  This is
     equivalent to:

          my @raw_chain = ($chain->begin, $chain->shape, $chain->end);

as_pgpath
          my $pg_path = $chain->as_pgpath;

     Returns a representation of the chain as a PostgreSQL open path
     suitable for insertion into the database.

to_pgpoint
          my $pg_point = $chain->to_pgpoint(\@point);

     Translates a two element array reference into a PostgreSQL point.

Modifiers
---------

append_shape
          $chain->append_shape(@points);

     Adds new shaping points to the chain.  They are appended to the end of
     the shape.

Private Methods
---------------

   *PRIVATE!* I document them here because I'm forgetful.  Use of these
may result in *DIRE CONSEQUENCES!* (consequences may contain one or more
of the following: pain, death, dismemberment, yellow dye #5)

_split_pg_path
          my @path = Geo::Walkabout::Chain->_split_pg_path($pg_path);

     Converts a PostgreSQL open PATH into an array of points.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   *Geo::Walkabout*, *Geo::Walkabout::Line*, *Geo::TigerLine*

A "line feature"
****************

NAME
====

   Geo::Walkabout::Line - A "line feature"

SYNOPSIS
========

     require Geo::Walkabout::Line;

     my $line = Geo::Walkabout::Line->retrieve($tlid);
     my $line = Geo::Walkabout::Line->new(\%data);

     $line->delete;

     my $id   = $line->id;
     my $name = $line->name;

     my($zip_left, $zip_right) = $line->zip;

     my @address_ranges = $line->addresses_left;
     my @address_ranges = $line->addresses_right;
     $line->add_addresses($side, @address_ranges);

     my $chain = $line->chain;

     $line->TLID;

     $line->FeDirP;
     $line->FeName;
     $line->FeType;
     $line->FeDirS;

     $line->ZipL;
     $line->Zip4L;
     $line->ZipR;
     $line->Zip4R;

     $line->commit;
     $line->rollback;

DESCRIPTION
===========

   This represents a complete "line feature".  Roads, waterways, fences,
power lines, railroads, boundries...  See chapter 3 of the TIGER/Line
documentation for details.

Public Methods
==============

Constructors and Destructors
----------------------------

   Geo::Walkabout::Line is a subclass of Class::DBI and expects to be
stored in a database.

retrieve
          my $line = Geo::Walkabout::Line->retrieve($id);

     Retrieve an existing line feature from the database by its ID.

new
          my $line = Geo::Walkabout::Line->new(\%data);

     Create a new line feature.  %data must contain the following fields...

          TLID        Unique TIGER/Line ID
          Chain       A Geo::Walkabout::Chain object representing the line

     And optionally contain these...

          FeDirP      See accessor descriptions below
          FeName      for what these are
          FeType
          FeDirS

          ZipL
          Zip4L
          ZipR
          Zip4R

delete
          $line->delete;

     Deletes this line feature from the database *permanently*.

Accessors
---------

id
          my $id = $line->id

     Returns a unique ID for this object, not necessarily the same as TLID.

     NOTE Do *NOT*, I repeat, do *NOT* use attempt to use the TLID as a
     unique identifer for a Geo::Walkabout::Line object.  While the TLID is
     unique, it is not guaranteed that all Geo::Walkabout::Line objects
     will have one.  Geo::Walkabout::Line objects will come from many
     sources.

TLID
          my $tlid = $line->TLID;

     Returns the TIGER/Line ID for this object.

name
          my $name = $line->name;

     The complete name of this feature.  Its roughly equivalent to:

          my $name = join ' ', $line->FeDirP, $line->FeName, $line->FeType,
                               $line->FeDirS;

     For example:  "Elford PL"

zip
          my($zip_left, $zip_right) = $line->zip;

     The zip code for the left and right side of this line.  Zip may be the
     5 digit zip code or the 9 digit zip +4.

addresses_left
addresses_right
          my @address_ranges = $line->addresses_left;
          my @address_ranges = $line->addresses_right;

     The possible addresses on the left side of this line.  @address_ranges
     is a list of range pairs (two element array refs).  A range with the
     same start and end number (such as [146,146]) represents a single
     anomalous address.

     The order is meaningless.

     For example:

          # Represents that the addresses descend from 290 to 200 from the
          # start of the line to the end.  There is also a single outstanding
          # address #146 and an additional range of addresses from 20 to 10.
          # So 10-20, 146 and 200-290.
          ([290,200],[146,146],[20,10])

add_addresses
          $line->add_addresses($side, @address_ranges);

     Addes a new address range to this line on the given $side.  $side is
     either 'R' or 'L'.  @address_range is a list of two element array
     references representing possible addresses on that side of the street.
     The ordering is from the start of the chain to the end.

chain
          my $chain = $line->chain;
          $line->chain($chain);

     The Geo::Walkabout::Chain object representing the shape of this line
     feature.  This is the important bit, the line's actual location in the
     world.  See Geo/Walkabout/Chain, for details.

FeDirP
          my $fedirp = $line->FeDirP;
          $line->FeDirP($fedirp);

     Feature Direction Prefix.  For example, if you had "North Southington
     Road", "N" would be the FeDirP.

     Possible values are "N", "NE", "NW", "S", "SE", "SW", "E", "W", "EX".
     "EX" means "Extended" or "Extension".

FeName
          my $fename = $line->FeName;
          $line->FeName($fename);

     Feature Name.  Continuing the example, "Southington" is the FeName.

FeType
          my $fetype = $line->FeType;
          $line->FeType($fetype);

     Feature Type.  "Rd" would be the feature type from above.  Standard
     abbreviations can be found in Appendix D of the TIGER/Line
     documentation.

FeDirS
          my $fedirs = $line->FeDirS;
          $line->FeDirS($fedirs);

     Feature Type Suffix.  Same as FeDirP, except it follows the feature
     name.  So for "Red Rock West", the FeDirS would be "W".

ZipL
ZipR
          my $zipl = $line->ZipL;
          $line->ZipL($zipl);
          my $zipr = $line->ZipR;
          $line->ZipR($zipr);

     5 digit zip codes for the left and right side of this line.

Zip4L

Zip4R
          my $zip4l = $line->Zip4L;
          $line->Zip4L($zip4l);
          my $zip4r = $line->Zip4R;
          $line->Zip4R($zip4r);

     4 digit +4 zip code extension for the left and right side of this
     line.

Other Methods
-------------

commit
          $line->commit;

     Commit changes made to this line to the database.

rollback
          $line->rollback;

     Throw away changes made to this line and refresh it from the database.
     If an object is changed and destroyed without committing or rolling
     back a warning will be thrown.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   `Geo::Walkabout' in this node, see Geo/TigerLine,
Geo/Walkabout/Chain,

Utility functions for Geo::Walkabout.
*************************************

NAME
====

   Geo::Walkabout::Utils - Utility functions for Geo::Walkabout.

DESCRIPTION
===========

   These are functions I'm playing around with.  Most likely they will be
broken up into other libraries and reworked, so don't be surprised if all
this changes.

Functions
---------

find_address
          my $line = find_address({fedirp       => $dirp,
                                   fename       => $name,
                                   fetype       => $type,
                                   fedirs       => $dirs,

          addr_num     => $num,
          zip          => $zip,
                                    });

     Finds a line feature from its name and zip.  (Eventually city and
     state instead of zip).

     NOTE fedirs and fedirp are currently ignored.

in_range
          my @lines = in_range([$long, $lat], $range);

     Returns all line features in a circular $range of the given point
     ($long, $lat).

get_line_feature
          my @feature = get_line_feature({
                                          fedirp => $fedirp,
                                          fename => $fename,
                                          fetype => $fetype,
                                          fedirs => $fedirs,

          zip    => $zip,
                                           });

     Returns all connected line features of the feature which passes
     through the given zip code.

     NOTE I don't think this quite gets the entire road.

     NOTE zip, fedirp and fedirs are currently ignored.

get_zip
          my @lines = get_zip($zip);

     Get all lines in a given zip code.

bounding_box
          my $box = bounding_box_zip($zip);

     Returns the two point box bounding this zip code.  $box->[0]
     upper-right, $box->[1] is lower-left.

find_intersection
          @lines = find_intersection({fename => $fe_name,
                                      fetype => $fe_type,
                                     },
                                     {fename => $fe_name,
                                      fetype => $fe_type,
                                     },
                                     $zip
                                    );

     Finds the given cross-street, returning all lines which share in this
     intersection.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

Weather retrieval module
************************

NAME
====

   Geo::Weather - Weather retrieval module

SYNOPSIS
========

     use Geo::Weather;

     my $weather = new Geo::Weather;

     $weather->get_weather('Folsom','CA');

     print $weather->report();

     -or-

     use Geo::Weather;

     my $weather = new Geo::Weather;

     my $current = $weather->get_weather('95630');

     print "The current temperature is $current->{temp} degrees\n";

DESCRIPTION
===========

   The *Geo::Weather* module retrieves the current weather from
weather.com when given city and state or a US zip code

FUNCTIONS
=========

   * new

     Create and return a new object.

   * *get_weather*

     Gets the current weather from weather.com

     Arguments

          city - US city or zip code
          state - US state, not needed if using zip code

     *Sample Code*

          my $current = $weather->get_weather('Folsom','CA');
          if (!ref $current) {
          	die "Unable to get weather information\n";
          }

     *Returns*

          On sucess, get_weather returns a hashref  containing the following keys

          city		- City
          state		- State
          pic		- weather.com URL to the current weather image
          cond		- Current condition
          temp		- Current temperature (degees F)
          wind		- Current wind speed
          dewp		- Current dew point (degrees F)
          humi		- Current rel. humidity
          visb		- Current visibility
          baro		- Current barometric pressure
          heat		- Current heat index

          On error, it returns the following exported error variables

     Errors

          $ERROR_QUERY		- Invalid data supplied
          $ERROR_PAGE_INVALID	- No URL, or incorrectly formatted URL for retrieving the information
          $ERROR_CONNECT		- Error connecting to weather.com
          $ERROR_NOT_FOUND	- Weather for the specified city/state or zip could not be found

   * report

     Returns an HTML table containing the current weather. Must call
     get_weather first.

     *Sample Code*

          print $weather->report();

   * lookup

     Gets current weather given a full weather.com URL

     *Sample Code*

          my $current = $weather->lookup('http://www.weather.com/weather/cities/us_ca_folsom.html');

     *Returns*

          On sucess, lookup returns a hashref with the same keys as the get_weather function

          On error, lookup returns the same errors defined for get_weather

AUTHOR
======

     Geo::Weather was wrtten by Mike Machado I<Less_Than_Special_Sequencemike@innercite.comGreater_Than_Special_Sequence> with the main weather.com retrieval code from I<Less_Than_Special_Sequencehawk@redtailedhawk.netGreater_Than_Special_Sequence>

Perl extension for interpreting the NOAA weather data
*****************************************************

NAME
====

   Geo::WeatherNOAA - Perl extension for interpreting the NOAA weather data

SYNOPSIS
========

     use Geo::WeatherNOAA;
     ($date,$warnings,$forecast,$coverage) =
        process_city_zone('newport','ri','','get');

     foreach $key (keys %$forecast) {
     	print "$key: $forecast->{$key}\n";
     }

     print process_city_hourly('newport news', 'va', '', 'get');

   or

     use Geo::WeatherNOAA;
     print print_forecast('newport news','va');

DESCRIPTION
===========

   This module is intended to interpret the NOAA zone forecasts and current
city hourly data files.  It should give a programmer an easy time to use
the data instead of having to mine it.

   Be aware that if the variable $main::opt_v is set to anything (other
than zero or ") then Geo::WeatherNOAA will be verbose  on what it's doing
with messages sent to STDERR.  Useful for debugging.

REQUIRES
========

   * Tie::IxHash

   * LWP::Simple

   * LWP::UserAgent

   * Text::Wrap

FUNCTIONS
=========

   * print_forecast(CITY,STATE,FILENAME,FILEOPT,LWP_UserAgent)

     Returns text of the forecast

   * print_current(CITY,STATE,FILENAME,FILEOPT,LWP_UserAgent)

     Returns text of current weather

   * make_noaa_table(CITY,STATE,FILENAME,FILEOPT,LWP_UserAgent, MaxItems)

     This call gives the basic html table with current data and forecast
     for the next four periods ("tonight", "tomorrow","tomorrow
     night","day after") and warnings in an (I think) attractive, easy to
     read way.

     Max Items is a way to limit the number of items in the table
     returned...  I think it looks best with no more than 4...5 gets
     crowded looking.

   * process_city_hourly(CITY,STATE,FILENAME,FILEOPT,LWP_UserAgent)

     FILENAME is the file read from with FILEOPT "usefile" and written to
     if FILEOPT is "save"

     FILEOPT can be one of the following

          - save
          	will get and save the data to FILENAME
          - get
          	will retrieve new data (not store it)
          - usefile
          	will not retrieve data from URL,
          	use FILENAME for data

     The fifth argument is for a user created LWP::UserAgent(3) which can
     be configured to work with firewalls. See the LWP::UserAgent(3)
     manpage for specific instructions. A basic example is like this:

          my $ua = new LWP::UserAgent;
          $ua->proxy(['http', 'ftp'], 'http://proxy.my.net:8080/');

     If you merely wish to set your proxy data from environment variables
     (as in $ua-env_proxy>), simply set

          $Geo::WeatherNOAA::proxy_from_env = 1;

   * process_city_zone(CITY,STATE,FILENAME,FILEOPT,LWP_UserAgent)

     Call CITY, STATE, FILENAME (explained above), FILEOPT(explained
     above), and UserAgent (Explained above).

     The return is a three element list containing a) a string of the
     date/time of the forecast, b) a reference to the list of warnings (if
     any), and c) a reference to the hash of forecast.  I recommend
     calling it like this:

          ($date, $warnings, $forecast, $coverage) =
              process_city_zone('newport news','va',
          	'/tmp/va_zone.html', 'save');

     Explanation of this call, it returns:

          $date
          - Scalar of the date of the forecast

          $warnings
          - Reference to the warnings list
          - EXAMPLE:
            foreach (@$warnings) { print; }

          $forecast
          - Reference to the forecast KEY, VALUE pairs
          - EXAMPLE:
            foreach $key (keys %$forecast) {
            	print "$key: $forecast->{$key}\n";
            }

          $coverage
          - Scalar of the coverage area of the forecast

   * get_city_zone(CITY,STATE,FILENAME,FILEOPT,LWP_UserAgent)

     This sub is to get the block of data from the data source, which is
     chosen with the FILEOPTswitch.

   * get_city_hourly(CITY,STATE,FILENAME,FILEOPT,LWP_UserAgent)

     This function gets the current weather from the data source, which is
     decided from FILEOPT(explained above).  Input is CITY, STATE,
     FILENAME (filename to read/write from if FILEOPTis "get" or
     "usefile"), and UserAgent.

     This function returns a reference to a hash containing the data. It

     Same FILEOPTand LWP_UserAgent from above, and process the current
     weather data into an english sentence.

AUTHOR
======

   Mark Solomon

   msolomon@seva.net

   http://www.seva.net/~msolomon/

SEE ALSO
========

   perl(1), Tie::IxHash(3), LWP::Simple(3), LWP::UserAgent(3).

2-letter, 3-letter, and numerical codes for countries.
******************************************************

NAME
====

   Geography::Countries - 2-letter, 3-letter, and numerical codes for
countries.

SYNOPSIS
========

     use Geography::Countries;

     $country = country 'DE';  # 'Germany'
     @list    = country  666;  # ('PM', 'SPM', 666,
                               #  'Saint Pierre and Miquelon', 1)

DESCRIPTION
===========

   This module maps country names, and their 2-letter, 3-letter and
numerical codes, as defined by the ISO-3166 maintenance agency [1], and
defined by the UNSD.

The country subroutine.
-----------------------

   This subroutine is exported by default. It takes a 2-letter, 3-letter or
numerical code, or a country name as argument. In scalar context, it will
return the country name, in list context, it will return a list consisting
of the 2-letter code, the 3-letter code, the numerical code, the country
name, and a flag, which is explained below. Note that not all countries
have all 3 codes; if a code is unknown, the undefined value is returned.

   There are 3 categories of countries. The largest category are the
current countries. Then there is a small set of countries that no longer
exist. The final set consists of areas consisting of multiple countries,
like Africa. No 2-letter or 3-letter codes are available for the second
two sets. (ISO 3166-3 [3] defines 4 letter codes for the set of countries
that no longer exist, but the author of this module was unable to get her
hands on that standard.) By default, country only returns countries from
the first set, but this can be changed by giving country an optional
second argument.

   The module optionally exports the constants `CNT_F_REGULAR',
`CNT_F_OLD', `CNT_F_REGION' and `CNT_F_ANY'. These constants can also be
important all at once by using the tag `:FLAGS'. `CNT_F_ANY' is just the
binary or of the three other flags. The second argument of country should
be the binary or of a subset of the flags `CNT_F_REGULAR', `CNT_F_OLD',
and `CNT_F_REGION' - if no, or a false, second argument is given,
`CNT_F_REGULAR' is assumed. If `CNT_F_REGULAR' is set, regular (current)
countries will be returned; if `CNT_F_OLD' is set, old, no longer
existing, countries will be returned, while `CNT_F_REGION' is used in case
a region (not necessarely) a country might be returned.  If country is
used in list context, the fifth returned element is one of
`CNT_F_REGULAR', `CNT_F_OLD' and `CNT_F_REGION', indicating whether the
result is a regular country, an old country, or a region.

   In list context, country returns a 5 element list. To avoid having to
remember which element is in which index, the constants `CNT_I_CODE2',
`CNT_I_CODE3', `CNT_I_NUMCODE', `CNT_I_COUNTRY' and `CNT_I_FLAG' can be
imported. Those constants contain the indices of the 2-letter code, the
3-letter code, the numerical code, the country, and the flag explained
above, respectively. All index constants can be imported by using the
`:INDICES' tag.

The `code2', `code3', `numcode' and `countries' routines.
---------------------------------------------------------

   All known 2-letter codes, 3-letter codes, numerical codes and country
names can be returned by the routines `code2', `code3', `numcode' and
`countries'. None of these methods is exported by default; all need to be
imported if one wants to use them. The tag `:LISTS' imports them all. In
scalar context, the number of known codes or countries is returned.

REFERENCES
==========

   The 2-letter codes come from the ISO 3166-1:1997 standard [2]. ISO 3166
bases its list of country names on the list of names published by the
United Nations. This list is published by the Statistical Division of the
United Nations [4]. The UNSD uses 3-letter codes, and numerical codes [5].
The information about old countries [6] and regions [7] also comes from
the United Nations.

   In a few cases, there was a conflict between the way how the United
Nations spelled a name, and how ISO 3166 spells it. In most cases, is was
word order (for instance whether *The republic of* should preceed the
name, or come after the name. A few cases had minor spelling variations.
In all such cases, the method in which the UN spelled the name was
choosen; ISO 3166 claims to take the names from the UN, so we consider the
UN authoritative.

[1]
     ISO Maintenance Agency (ISO 3166/MA)
     *http://www.din.de/gremien/nas/nabd/iso3166ma/index.html*.

[2]
     *Country codes*,
     *http://www.din.de/gremien/nas/nabd/iso3166ma/codlstp1.html*, 7
     September 1999.

[3]
     ISO 3166-3, *Code for formerly used country names*.
     *http://www.din.de/gremien/nas/nabd/iso3166ma/info_pt3.html*.

[4]
     United Nations, Statistics Division.
     *http://www.un.org/Depts/unsd/statdiv.htm*.

[5]
     *Country or area codes in alphabetical order*.
     *http://www.un.org/Depts/unsd/methods/m49alpha.htm*, 26 August 1999.

[6]
     *Codes added or changed*.
     *http://www.un.org/Depts/unsd/methods/m49chang.htm*, 26 August 1999.

[7]
     *Geographical regions*.
     *http://www.un.org/Depts/unsd/methods/m49regin.htm*, 26 August 1999.

BUGS
====

   Looking up information using country names is far from perfect.  Except
for case and the amount of white space, the exact name as it appears on
the list has to be given. USA will not return anything, but *United
States* will.

HISTORY
=======

     $Log: Countries.pm,v $
     Revision 1.2  2000/09/05 18:22:01  abigail
     Changed typo in "Federal Republic of Germany" (Dan Allen)
     Changed layout of test.pl

     Revision 1.1  1999/09/15 07:27:22  abigail
     Initial revision

AUTHOR
======

   This package was written by Abigail, *abigail@delanet.com*.

COPYRIGHT AND LICENSE
=====================

   This package is copyright 1999 by Abigail.

   This program is free and open software. You may use, copy, modify,
distribute and sell this program (and any modified variants) in any way
you wish, provided you do not restrict others to do the same.

Map states and provinces to their codes, and vica versa.
********************************************************

NAME
====

   Geography::States  -  Map states and provinces to their codes, and vica
versa.

SYNOPSIS
========

     use Geography::States;

     my $obj = Geography::States -> new (COUNTRY [, STRICT]);

EXAMPLES
========

     my $canada = Geography::States -> new ('Canada');

     my  $name          =  $canada -> state 'NF';      # Newfoundland.
     my  $code          =  $canada -> state 'Ontario'; # ON.
     my ($code, $name)  =  $canada -> state 'BC';      # BC, British Columbia.
     my  @all_states    =  $canada -> state;           # List of code/name pairs.

DESCRIPTION
===========

   This module lets you map states and provinces to their codes, and codes
to names of provinces and states.

   The `Geography::States -' new ()> call takes 1 or 2 arguments. The
first, required, argument is the country we are interested in. Current
supported countries are USA, *Brazil*, *Canada*, and *The Netherlands*. If
a second non-false argument is given, we use *strict mode*. In non-strict
mode, we will map territories and alternative codes as well, while we do
not do that in strict mode. For example, if the country is USA, in
non-strict mode, we will map *GU* to *Guam*, while in strict mode, neither
*GU* and *Guam* will be found.

The state() method
------------------

   All queries are done by calling the state method in the object. This
method takes an optional argument. If an argument is given, then in scalar
context, it will return the name of the state if a code of a state is
given, and the code of a state, if the argument of the method is a name of
a state. In list context, both the code and the state will be returned.

   If no argument is given, then the state method in list context will
return a list of all code/name pairs for that country. In scalar context,
it will return the number of code/name pairs. Each code/name pair is a 2
element anonymous array.

   Arguments can be given in a case insensitive way; if a name consists of
multiple parts, the number of spaces does not matter, as long as there is
some whitespace. (That is "NewYork" is wrong, but "new    YORK" is fine.)

ODDITIES AND OPEN QUESTIONS
===========================

   I found conflicting abbreviations for the US *Northern Mariana Islands*,
listed as *NI* and *MP*. I picked *MP* from the USPS site.

   One site listed *Midway Islands* as having code *MD*. It is not listed
by the USPS site, and because it conflicts with *Maryland*, it is not put
in this listing.

   The USPS also has so-called *Military "States"*, with non-unique codes.
Those are not listed here.

   Canada's *Quebec* has two codes, the older *PQ* and the modern *QC*.
Both *PQ* and *QC* will map to *Quebec*, but *Quebec* will only map to
*QC*.  With strict mode, *PQ* will not be listed.

REVISION HISTORY
================

     $Log: States.pm,v $
     Revision 1.3  2000/07/23 09:28:31  abigail
     Fixed dependency on hash ordering when mapping "Quebec" (it worked
        in perl5.005, but failed in perl5.6).
     Fixed typos in state names (Ross Baker).
     Changed email address.
     Changed license to from free prose to X-style license.

     Revision 1.2  1999/09/10 17:12:05  abigail
     Added a 'require 5.005' due to the use of INIT.

     Revision 1.1  1999/09/09 07:33:54  abigail
     Initial revision

AUTHOR
======

   This package was written by Abigail, abigail@foad.org.

COPYRIGHT and LICENSE
=====================

   This package is copyright 1999, 2000 by Abigail.

   Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

USA State Data
**************

NAME
====

   Geography::USStates - USA State Data

SYNOPSIS
========

   use Geography::USStates; # - just getState* functions use
Geography::USStates qw(:areas); # - just getArea* functions use
Geography::USStates qw(:both);  # - just getState*Area* functions use
Geography::USStates qw(:both);  # - all functions

   # ----- US STATES BASED $state = getState('mn');        # - get the
statename 'Minnesota'

   $state = getState('wisconsin'); # - get the abbreviation 'wi'

   @states = getStateNames();      # - return all state names

   @states = getStateAbbrevs();    # - return all state abbrevations (AL,
AK, ..)

   %s = getStates();               # - return hash $states{'MN'} =
'Minnesota'

   %s = getStates(case=>'upper');  # - return hash $states{'MN'} =
'MINNESOTA'

   %s = getStates(case=>'lower');  # - return hash $states{'MN'} =
'minnesota'

   %s = getStates(hashkey=>'name');# - return hash $states{'Minnesota'} =
'MN'

   # ----- US AREAS $area = getArea('gu');          # - get the area name
'Guam'

   $area = getArea('guam');        # - get the abbreviation 'gu'

   @areas = getAreaNames();        # - return all area names

   @areas = getAreaAbbrevs();      # - return all area abbrevations (DC,
GU, ..)

   %a = getAreas();                # - return hash $states{'GU'} = 'Guam'

   %a = getAreas(case=>'upper');   # - return hash $states{'GU'} = 'GUAM'

   %a = getAreas(case=>'lower');   # - return hash $states{'GU'} = 'guam'

   %a = getAreas(hashkey=>'name'); # - return hash $states{'Guam'} = 'GU'

   # ----- Lookup both US States and Dependant areas # - get the statename
'Minnesota' or 'Guam' respectivily $state = getStateOrArea('mn' || 'gu');

   # - get the abbreviation 'wi' or 'gu' respectivily $state =
getStateOrArea('wisconsin' || 'guam');

   # - return all states and areas names together  @states =
getStatesAndAreasNames();

   # - return all states and areas abbreviations together  @states =
getStatesAndAreasAbbrevs();

   # - same as getStates() but it returns the areas in the hash too %s =
getStatesAndAreas(); %s = getStatesAndAreas(case=>'upper'); %s =
getStatesAndAreas(case=>'lower'); %s = getStatesAndAreas(hashkey=>'name');

DESCRIPTION
===========

   This module allows you to get information on US State names, their
abbreviations, and couple the two together (in hashes). As well as states,
the US has "Dependant Area's" like Guam, and the Virgin Islands. Sometimes
you want to offer these areas in your application so you can get access to
those via the getArea*() functions and the getState*Area*() functions.

FUNCTIONS
=========

   o *getState*($statename || $stateabbrev)

     Given an abbreviation a statename is returned.
     Given a name an abbreviatin is returned

     e.g. print getState('MN');
          would print 'Minnesota'

     print getState('wisconsin');
     would print 'WI'

     o B<getStateNames>()

     Return all of the states in an array

     e.g. map { print "$_\n" } getStateNames();
          would print "Alabama\nAlaska\n...";

       o B<getStateAbbrevs>()

     Return all of the abbrevs in an array

     e.g. map { print "$_\n" } getStateAbbrevs();
          would print "AL\nAK\n...";

       o B<getStates>(%hash | $hashref) [keys: case => upper||lower, hashkey=>name]

     A hash is returned with both abbrev and statename. By default it returns
     the state abbrev as the key and the state name as the value

     e.g. $hash{MN} = 'Minnesota';

     You can also pass params in a hash or hashref. To force the state names
     to be lower case, or upper case you do:

     getStates(case => 'upper'); # -- for upper case... lower for lower case

     If you want to return a hash where the name is the key you do:

     my %s = getStates(hashkey => 'name');
     and then
     $s{'Minnesota'} = 'MN';

       =head1 AUTHOR

       Dion Almaer (dion@almaer.com)

     =cut

parse routine arguments
***********************

NAME
====

   Getargs::Long - parse routine arguments

SYNOPSIS
========

     use Getargs::Long;                     # case sensitive
     use Getargs::Long qw(ignorecase);      # case insensitive

     # Simple, args mandatory
     my ($val, $other) = getargs(\@_, qw(val other));

     # Simple, args optional (in [] means optional)
     my ($val, $other) = getargs(\@_, [qw(val other)]);

     # Simple with typechecking, args mandatory
     my ($val, $other) = getargs(\@_, qw(val=Class::X other=ARRAY));

     # Simple with typechecking, args optional
     my ($val, $other) = getargs(\@_, [qw(val=Class::X other=ARRAY)]);

     # Faster version, building dedicated argument parsing routine
     my ($val, $other) = cgetargs(\@_, qw(val other));

     # Other cases, use full specs:
     my ($x, $y, $z, $a, $b, $c) = xgetargs(\@_,

     # Non-mandatory, defaults to undef unless specified otherwise
     'x'     => ['i'],                   # integer, no default
     'y'     => ['ARRAY', ['a', 'b']],   # Has a default
     'z'     => [],                      # No typecheck, can be anything

     # Mandatory arguments
     'a'     => 'i',                     # integer (scalar)
     'b'     => 'TYPE',                  # TYPE or any heir of TYPE
     'c'     => undef,                   # unspecified type but mandatory
      );

     # Extract remaining unparsed args in @extra
     my ($val, $other, @extra) = getargs(\@_, { -strict => 0 }, qw(val other));

     # Alter behaviour of the getargs() routines via switches in hashref
     my ($val, $other) = getargs(\@_,
        {
            -strict         => 1,       # unknown switches are fatal
            -ignorecase     => 1,       # override package's global
            -inplace        => 1,       # edit @_ inplace: remove parsed args
            -extra          => 0,       # suppress return of extra arguments
        },
        qw(val other)
     );

DESCRIPTION
===========

   The `Getargs::Long' module allows usage of named parameters in function
calls, along with optional argument type-checking.  It provides an easy
way to get at the parameters within the routine, and yields concise
descriptions for the common cases of all-mandatory and all-optional
parameter lists.

   The validation of arguments can be done by a structure-driven routine
getargs() which is fine for infrequently called routines (but should be
slower), or via a dedicated routine created and compiled on the fly the
fist time it is needed, by using the cgetargs() family (expected to be
faster).

   The `Log::Agent' module is used to report errors, which leaves to the
application the choice of the final logging method: to a file, to STDERR,
or to syslog.

EXAMPLE
=======

   Before going through the interface specification, a little example will
help illustrate both caller and callee sides.  Let's write a routine that
can be called as either:

     f(-x => 1, -y => 2, -z => 3);  # -switch form
     f(x => 1, y => 2, z => 3);     # concise form (- are optional)
     f(y => 1, x => 2);             # order changed, z may be omitted

   Since we have an optional parameter z but mandatory x and y, we can't
use the short form of getargs() and must therefore use xgetargs():

     sub f {
         my ($x, $y ,$z) = xgetargs(\@_,
             -x => 'i',             # mandatory, integer
             -y => 'i',             # mandatory, integer
             -z => ['i', 0],        # optional integer, defaults to 0
         );
         # code use $x, $y, $z
     }

   That's quite simple and direct if you think of [] as "optional".  Note
that we pass xgetargs() a reference to @_.

   If we had all arguments mandatory and wished to nonethless benefit from
the named specification at call time to avoid having the caller remember
the exact parameter ordering, we could write:

     sub f {
         my ($x, $y ,$z) = getargs(\@_, qw(x=i y=i z=i));
         # code of f
     }

   Without parameter type checking, that would be even more concise.
Besides, if f() is frequently called, it might be more efficient to build
a routine dynamically to parse the arguments rather than letting getargs()
parse the same data structures again and again:

     sub f {
         my ($x, $y ,$z) = cgetargs(\@_, qw(x y z));    # 'c' for cached/compiled
         # code of f
     }

   If you call f() with an improper argument, logcroak() will be called to
issue an exception from the persepective of the caller, i.e. pointing to
the place f() is called instead of within f() at the getargs() call, which
would be rather useless.

INTERFACE
=========

   All the routines take a mandatory first argument, called *arglist_ref*,
which is a reference to an array containing the named arguments for the
routine (i.e. a succession of name => value tuples).  It will usually be
given as `\@_'.

   All the routines take an optional options argument which comes in the
second place.  It is an hash reference containing named options that alter
the behaviour of the routine.  More details given in the `Options' in this
node section.

   All the routines return a list of the arguments in the order they are
specified, each slot in the list being either the argument value, if
present, or undef if missing (and not mandatory).

Simple Cases
------------

   Simple cases are handled by getargs(): named arguments should either be
*all mandatory* or *all optional*, and there is no provision for specifying
a default value for optional parameters.

   The getargs() routine and its cousin cgetargs() have two different
interfaces, depending on whether the arguments are all mandatory or all
optional.  We'll only specify for getargs(), but the signature of
cgetargs() is identical.

getargs *arglist_ref*, options, *arg_spec1*, *arg_spec2*, ...
     We'll be ignoring the options argument from our discussion.  See the
     `Options' in this node section for details.

     All the routine formal arguments specified by *arg_spec1*,
     *arg_spec2*, etc... are mandatory.  If *arg_spec1* is only a name,
     then it specifies a mandatory formal argument of that name, which can
     be of any type, even undef.  If the name is followed by `=type' then
     type specifies the argument type: usually a reference type, unless
     'i', 'n' or 's' is used for integer, natural and string scalars.

     Currently, types 'i', 'n' and 's' all mean the same thing: that the
     argument must be a scalar.  A future implementation will probably
     ensure 'i' and 'n' hold integers and natural numbers respectively,
     's' being the placeholder for anything else that is defined.

     For instance:

          foo               expects mandatory "foo" of "-foo" argument (undef ok)
          foo=s             idem, and argument cannot be undef or reference
          foo=i             value of argument -foo must be an integer
          foo=My::Package   foo is a blessed object, inheriting from My::Package
          foo=ARRAY         foo is an ARRAY reference

     The rule for determing whether `foo=X' means foo is a reference X or
     foo is an object whose class is an heir of X depends on the argument
     value at runtime: if it is an unblessed ref, strict reference
     equality is expected.  If it is a blessed ref, type conformance is
     based on inheritance, as you would expect.

     Example:

          sub f {
              my ($port, $server) = getargs(\@_,
                  qw(port=i server=HTTP::Server));
          }

     Some calls:

          f(-server => $server, port => 80);  # or -port, since - is optional
          f(port => 80, server => $server);
          f(server => $server);               # WRONG: missing mandatory -port
          f(server => 80, port => 80);        # WRONG: -server not an HTTP::Server
          f(server => undef, port => 80);     # WRONG: -server cannot be undef

     By default, named argument processing is case-sensitive but there is
     an option to ignore case.

getargs *arglist_ref*, options, *array_ref*
     This form specifies that all the formal arguments specified in the
     *array_ref* are optional.  Think of the '[' and ']' (which you'll
     probably use to supply the reference as a manifest constant) as
     syntactic markers for optional things.  In the traditional Unix
     command line description, something like:

          cmd [-a] [-o file]

     typically denotes that options -a and -o are optional, and that -o
     takes one argument, a file name.  To specify the same things for
     routine arguments using getargs():

          sub cmd {
              my ($a, $o) = getargs(\@_, [qw(a o=s)]);
          }

     Here however, the -a argument can be anything: we're not specifying
     switches, we're specifying *named* arguments.  Big difference.

     Some calls:

          cmd();                      # OK
          cmd(-a => undef);           # OK -a accepts anything, even undef
          cmd(-a => 1, -o => "..");   # OK
          cmd(-a => 1, -o => undef);  # WRONG: -o does not accept undef
          cmd(-x => 1);               # WRONG: -x is not a known argument name

     It is important to note that there can only be tuples when using named
     arguments, which means that the routine is called with an *even*
     number of arguments.  If you forget a `,' separator between
     arguments, getargs() will complain about an *odd* number of arguments
     (provided the resulting code still parses as valid Perl, naturally,
     or you'll never get a chance to reach the execution of getargs()
     anyway).

cgetargs *same args as getargs*
     The cgetargs() routine behaves exactly as the getargs() routine: it
     takes the same arguments, returns the same list.  The only difference
     is that the first time it is called, it builds a routine to process
     the arguments, and then calls it.

     On subsequent calls to cgetargs() for the same routine, the cached
     argument parsing routine is re-used to analyze the arguments.  For
     frequently called routines, this might be a win, even though Perl
     still needs to construct the argument list to cgetargs() and call it.

Complex Cases
-------------

   The xgetargs() routine and its cousin cxgetargs() (for the caching
version) allow for a more verbose description of named parameters which
allows specifying arguments that are mandatory or optional, and also give
default values to optional arguments.

xgetargs *arglist_ref*, options, name => type, ...
     We'll be ignoring the options argument from our discussion.  See
     `Options' in this node for details.

     There can be as many name => type tuples as necessary to describe all
     the formal arguments of the routine.  The name refers to the argument
     name, and type specifies both the mandatory nature and the expected
     type.  You may use name or *-name* to specify an argument called
     name, and the caller will also be able to spell it as he wishes.  The
     type is encoded as follows:

          "i"      mandatory integer (scalar)
          "s"      mandatory string (scalar)
          "TYPE"   mandatory ref of type TYPE, or heir of type TYPE
          undef    unspecified type, but mandatory argument
          ["i"]    optional integer
          ["s"]    optional string
          ["TYPE"] optional ref of type TYPE, or heir of type TYPE

     For optional parameter, an optional second value may be inserted in
     the list to specify a default value.  For instance, the tupple:

          'y' => ['HASH', { a => 1, b => 2 }]

     specifies an optional named argument y, which is expected to be a HASH
     reference, and whose default value is the hash given.

     You may specify an expression as default value instead of giving a
     manifest constant, but *BEWARE*: the cxgetargs() routine will take a
     snapshot of your expression when building its analyzing routine.
     It's of no consequence when using a manifest constant, but when using
     an expression, it will be evaluated *once* and the result of that
     evaluation will be taken as the manifest constant to use subsequently
     (and this does not mean the *same* reference will be returned, only
     the same topological structure as the one we evaluated during
     caching).

     Example:

          sub f {
              my ($x, $z) = cxgetargs(\@_,
                  -x  => 'i',                 # -x mandatory integer
                  -z  => ['n', -20.4],        # -z optional, defaults to -20.4
              );
          }

          f(x => 1, z => {});     # WRONG: z is not a numerical value
          f(z => 1, x => -2);     # OK
          f(-z => 1);             # WRONG: mandatory x is missing
          f(-z => undef);         # WRONG: z cannot be undef

     Remember that we are dealing with named parameters for a routine call,
     not with option parsing.  Therefore, we are always expecting an *even*
     number of arguments, and those arguments are tuples name => value.

Options
-------

   All the getargs() and xgetargs() routines take an optional hash
reference as second argument.  Keys in this hash define options that apply
locally to the call.  In the case of caching routines, e.g. cxgetargs(),
the options are only considered the first time, when the analyzing routine
is built, and are ignored on subsequent calls.  Therefore, it is wise to
use manifest constants when specifying options, or use the non-caching
function family instead if your options need to be dynamically computed
(please, don't do that).

   Options given there must be spelled out with the leading - and are case
sensitive.  To enable an option, give a true value.  For instance:

     sub f {
         my ($x, $z) = cxgetargs(\@_,
             { -strict => 0, -ignorecase => 1 },
             -x  => 'i',                 # -x mandatory integer
             -z  => ['n', -20.4],        # -z optional, defaults to -20.4
         );
     }

   supplies two options, turning `-ignorecase' on and `-strict' off.

   The available options are, in alphabetical order:

-extra
     Whether to report extra unknown arguments at the end of the argument
     list.  Example:

          my ($x, $y, @extra) = getargs(\@_,
              { -extra => 1, -strict => 0 }, qw(x y));

     Your setting is forced to false when `-strict' is true.  The default
     value is the negation of the boolean `-strict' setting, which means
     the above can be rewritten as:

          my ($x, $y, @extra) = getargs(\@_, { -strict => 0 }, qw(x y));

     which will implicitely set -extra to be true.  This is usually what
     you want when not strict, i.e. get at the other parameters.  Assuming
     we were writing the above for a function f(), calling:

          f(-x => 1, -y => 2, -other => 5);

     would set:

          @extra = (-other => 5);

     An alternative when you are not strict is to make use of the
     `-inplace' option to edit @_ inplace.

-ignorecase
     Turn case-insensitive named parameters.  False by default.  Actually,
     if not explicitely specified, the default setting depends on the way
     `Getargs::Long' was imported within the package scope.  If you said:

          use Getargs::Long;

     then the default is indeed to be case-sensitive.  However, if you
     said:

          use Getargs::Long qw(ignorecase);

     then the default for the package scope is to be case-insensitive.
     You may still specify the `-ignorecase' option to force case
     sensitivity on a per-routine basis, although I would never do such a
     thing and stick to a uniform case sensitivity on a package basis.

-inplace
     Whether to edit the routine's argument list inplace, removing
     processed arguments as they are found and leaving unprocessed ones.
     False by default.

     Your setting is forced to false when `-strict' is true, naturally,
     since an unknown argument is an error.

-strict
     Whether unknown named parameters are fatal.  True by default.  When
     `-strict' is true, the `-inplace' and `-extra' options you may
     specify are ignored and forced to false.

BUGS
====

   Currently, types 'i', 'n' and 's' all mean the same thing, but that will
change.  Don't take the current implementation's deficiency as an excuse
for lamely specifying your scalar types.

   You must be careful in this implementation to list options and variables
in the very same order.  Some day, I will probably add another routine to
take arguments the way Getopt::Long does to cope with this ordering
problem (but it forces to spell out variables twice - once for declaration,
and once for specifying a pointer to it).

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   Log::Agent(3).

interpolates script options from files into @ARGV or another array
******************************************************************

NAME
====

   Getopt::ArgvFile - interpolates script options from files into @ARGV or
another array

VERSION
=======

   This manual describes version *1.04*.

SYNOPSIS
========

     # load the module
     use Getopt::ArgvFile qw(argvFile);
     # load another module to evaluate the options, e.g.:
     use Getopt::Long;
     ...
     # solve option files
     argvFile;
     # evaluate options, e.g. this common way:
     GetOptions(%options, 'any');

   If options should be processed into another array, this can be done
this way:

     # prepare target array
     my @options=('@options1', '@options2', '@options3');
     ...
     # replace file hints by the options stored in the files
     argvFile(array=>\@options);

DESCRIPTION
===========

   This module simply interpolates option file hints in @ARGV by the
contents of the pointed files. This enables option reading from files
instead of or additional to the usual reading from the command line.

   Alternatively, you can process any array instead of @ARGV which is used
by default and mentioned mostly in this manual.

   The interpolated @ARGV could be subsequently processed by the usual
option handling, e.g. by a Getopt::xxx module.  Getopt::ArgvFile does not
perform any option handling itself, it only prepares the array @ARGV.

   Option files can significantly simplify the call of a script.  Imagine
the following:

Breaking command line limits
     A script may offer a lot of options, with possibly a few of them even
     taking parameters. If these options and their parameters are passed
     onto the program call directly, the number of characters accepted by
     your shells command line may be exceeded.

     Perl itself does not limit the number of characters passed to a
     script by parameters, but the shell or command interpreter often sets
     a limit here. The same problem may occur if you want to store a long
     call in a system file like crontab.

     If such a limit restricts you, options and parameters may be moved
     into option files, which will result in a shorter command line call.

Script calls prepared by scripts
     Sometimes a script calls another script. The options passed onto the
     nested script could depend on variable situations, such as a users
     input or the detected environment. In such a case, it can be easier
     to generate an intermediate option file which is then passed to the
     nested script.

     Or imagine two cron jobs one preparing the other: the first may
     generate an option file which is then used by the second.

Simple access to typical calling scenarios
     If several options need to be set, but in certain circumstances are
     always the same, it could become sligthly nerveracking to type them
     in again and again. With an option file, they can be stored *once*
     and recalled easily as often as necessary.

     Further more, option files may be used to group options. Several
     settings may set up one certain behaviour of the program, while others
     influence another. Or a certain set of options may be useful in one
     typical situation, while another one should be used elsewhere. Or
     there is a common set of options which has to be used in every call,
     while other options are added depending on the current needs. Or there
     are a few user groups with different but typical ways to call your
     script.  In all these cases, option files may collect options
     belonging together, and may be combined by the script users to set up
     a certain call.  In conjunction with the possiblity to *nest* such
     collections, this is perhaps the most powerful feature provided by
     this method.

Individual and installationwide default options
     The module allows the programmer to enable user setups of default
     options; for both individual users or generally all callers of a
     script.  This is especially useful for administrators who can
     configure the default behaviour of a script by setting up its
     installationwide startup option file. All script users are free then
     to completely forget every already configured setup option. And if
     one of them regularly adds certain options to every call, he could
     store them in his *individual* startup option file.

     For example, I use this feature to make my scripts both flexible and
     usable. I have several scripts accessing a database via DBI. The
     database account parameters as well as the DBI startup settings
     should not be coded inside the scripts because this is not very
     flexible, so I implemented them by options. But on the other hand,
     there should be no need for a normal user to pass all these settings
     to every script call. My solution for this is to use default option
     files set up and maintained by an administrator.  This is very
     transparent, most of the users know nothing of these (documented ;-)
     configuration settings ... and if anything changes, only the option
     files have to be adapted.

EXPORTS
=======

   No symbol is exported by default, but you may explicitly import the
"argvFile()" function.

   Example:

     use Getopt::ArgvFile qw(argvFile);

FUNCTIONS
=========

argvFile()
----------

   Scans the command line parameters (stored in @ARGV or an alternatively
passed array) for option file hints (see *Basics* below), reads the
pointed files and makes their contents part of the source array (@ARGV by
default) replacing the hints.

   Because the function was intentionally designed to work on @ARGV and
this is still the default behaviour, this manual mostly speaks about
@ARGV. Please note that it is possible to process any other array as well.

   *Basics*

   An option file hint is simply the filename preceeded by (at least) one
"@" character:

     > script -optA argA -optB @optionFile -optC argC

   This will cause argvFile() to scan "optionFile" for options.  The
element "@optionFile" will be removed from the @ARGV array and will be
replaced by the options found.

   Note: you can choose another prefix by using the "prefix" parameter,
see below.

   An option file which cannot be found is quietly skipped.

   Well, what is *within* an option file? It is intended to store *command
line arguments* which should be passed to the called script. They can be
stored exactly as they would be written in the command line, but may be
spread to multiple lines. To make the file more readable, space and
comment lines (starting with a "#") are allowed additionally. POD comments
are supported as well.  For example, the call

     > script -optA argA -optB -optC cArg par1 par2

   could be transformed into

     > script @scriptOptions par1 par2

   where the file "scriptOptions" may look like this:

     # option a
     -optA argA

     =pod
     option b
     =cut
     -optB

     # option c
     -optC cArg

   *Nested option files*

   Option files can be nested. Recursion is avoided globally, that means
that every file will be opened only *once* (the first time argvFile() finds
a hint pointing to it). This is the simplest implementation, indeed, but
should be suitable. (Unfortunately, there are LIMITS.)

   By using this feature, you may combine groups of typical options into a
top level option file, e.g.:

     File ab:

     # option a
     -optA argA
     # option b
     -optB

     File c:

     # option c
     -optC cArg

     File abc:

     # combine ab and c
     @ab @c

   If anyone provides these files, a user can use a very short call:

     > script @abc

   and argvFile() will recursively move all the filed program parameters
into @ARGV.

   *Startup support*

   By setting several named parameters, you can enable default and *home*
option files. Both are searched with the scriptname preceeded by a dot.
The *default option file* is searched in the installation path of the
calling script, while the *home option file* is searched in the users home
(evaluated via environment variable "HOME").

     Examples:
      If called in a script "/path/script" by "user" whoms "HOME"
      variable points to "/homes/user", the following happens:

     argvFile()                    # ignores startup option files;
     argvFile(default=>1)          # searches and expands "/path/.script",
                                   # if available (the "default" settings);
     argvFile(home=>1)             # searches and expands "/homes/user/.script",
                                   # if available (the "home" settings);
     argvFile(default=>1, home=>1) # tries to handle both startups.

   Any true value will activate the setting it is assigned to.

   The contents found in a startup file is placed before all explicitly
set command line arguments. This enables to overwrite a default setting by
an explicit option. If both startup files are read, *home* startup files
can overwrite default ones, so that the default startups are most common.
In other words, if the module would not support startup files, you could
get the same result with "script @/path/.script @/homes/user/.script".

   If there is no HOME environment variable, the *home* setting takes no
effect to avoid trouble accessing the root directory.

   *Cascades*

   The function supports multi-level (or so called *cascaded*) option
files.  If a filename in an option file hint starts with a "@" again, this
complete name is the resolution written back to @ARGV - assuming there
will be another utility reading option files.

     Examples:
      @rfile          rfile will be opened, its contents is
                      made part of @ARGV.
      @@rfile         cascade: "@rfile" is written back to
                      @ARGV assuming that there is a subsequent
                      tool called by the script to which this
                      hint will be passed to solve it by an own
                      call of argvFile().

   The number of cascaded hints is unlimited.

   *Processing an alternative array*

   However the function was designed to process @ARGV, it is possible to
process another array as well if you prefer. To do this, simply pass a
reference to this array by parameter array.

     Examples:
      argvFile()                    # processes @ARGV;
      argvFile(array=>\@options);   # processes @options;

   *Choosing an alternative hint prefix*

   By default, "@" is the prefix used to mark an option file. This can be
changed by using the optional parameter prefix:

     Examples:
      argvFile();                   # use "@";
      argvFile(prefix=>'~');        # use "~";

   Note that the strings "#", "=", "-" and "+" are reserved and *cannot*
be chosen here because they are used to start plain or POD comments or are
typically option prefixes.

LIMITS
======

   If an option file does not exist, argvFile() simply ignores it.  No
message will be displayed, no special return code will be set.

AUTHOR
======

   Jochen Stenzel <mailto://perl@jochen-stenzel.de>

LICENSE
=======

   Copyright (c) 1993-2000 Jochen Stenzel. All rights reserved.

   This program is free software, you can redistribute it and/or modify it
under the terms of the Artistic License distributed with Perl version
5.003 or (at your option) any later version. Please refer to the Artistic
License that came with your Perl distribution for more details.

Declaratively Expressed Command-Line Arguments via Regular Expressions
**********************************************************************

NAME
====

   Getopt::Declare - Declaratively Expressed Command-Line Arguments via
Regular Expressions

VERSION
=======

   This document describes version 1.08 of Getopt::Declare, released May
21, 1999.

SYNOPSIS
========

     use Getopt::Declare;

     $args = new Getopt::Declare ($specification_string, $optional_source);

DESCRIPTION
===========

Overview
--------

   `Getopt::Declare' is *yet another* command-line argument parser, one
which is specifically designed to be powerful but exceptionally easy to
use.

   To parse the command-line in `@ARGV', one simply creates a
`Getopt::Declare' object, by passing `Getopt::Declare::new()' a
specification of the various parameters that may be encountered:

     $args = new Getopt::Declare($specification);

   The specification is a single string such as this:

     $specification = q(

     -a		Process all data

     -b <N:n>	Set mean byte length threshold to <N>
     			{ bytelen = $N; }

     +c <FILE>	Create new file <FILE>

     --del 		Delete old file
     			{ delold() }

     delete 		[ditto]

     e <H:i>x<W:i>	Expand image to height <H> and width <W>
     			{ expand($H,$W); }

     -F <file>...	Process named file(s)
     			{ defer {for (@file) {process()}} }

     =getrand [<N>]	Get a random number
     		(or, optionally, <N> of them)
     			{ $N = 1 unless defined $N; }

     --		Traditionally indicates end of arguments
     			{ finish }
     	);

   in which the syntax of each parameter is declared, along with a
description and (optionally) one or more actions to be performed when the
parameter is encountered. The specification string may also include other
usage formatting information (such as group headings or separators) as
well as standard Perl comments (which are ignored).

   Calling `Getopt::Delare::new()' parses the contents of the array
`@ARGV', extracting any arguments which match the parameters defined in the
specification string, and storing the parsed values as hash elements
within the new `Getopt::Declare' object being created.

   Other features of the `Getopt::Declare' package include:

   * The use of full Perl regular expressions to constrain matching of
     parameter components.

   * Automatic generation of error, usage and version information.

   * Optional conditional execution of embedded actions (i.e. only on
     successful parsing of the entire command-line)

   * Strict or non-strict parsing (unrecognized command-line elements may
     either trigger an error or may simply be left in `@ARGV')

   * Declarative specification of various inter-parameter relationships
     (for example, two parameters may be declared mutually exclusive and
     this relationship will then be automatically enforced).

   * Intelligent clustering of adjacent flags (for example: the
     command-line sequence "-a -b -c" may be abbreviated to "-abc", unless
     there is also a `-abc' flag declared).

   * Selective or global case-insensitivity of parameters.

   * The ability to parse files (especially configuration files) instead of
     the command-line.

Terminology
-----------

   The terminology of command-line processing is often confusing, with
various terms (such as "argument", "parameter", "option", "flag", etc.)
frequently being used interchangeably and inconsistently in the various
`Getopt::' packages available. In this documentation, the following terms
are used consistently:

"command-line"
     The space-separated concatenation of the elements of the array `@ARGV'
     at the time a `Getopt::Declare' object is created.

"parameter specification" (or just "parameter")
     A specification of a single entity which may appear in the
     command-line. Always includes at least one syntax for the entity.
     Optionally may include other (*variant*) syntaxes, one or more
     *descriptions* of the entity, and/or actions to be performed when the
     entity is encountered. For example, the following is a single
     parameter specification (with two variants):

          --window <height> x <width>	    Set window to <height> by <width>
          					{ setwin($width,$height); }

          --window <h>x<w>@<x>,<y>	    Set window size and centroid
          					{ setwin($w,$h,$x,$y); }

"argument"
     A substring of the command-line which matches a single parameter
     variant.  Unlike some other Getopt:: packages, in `Getopt::Declare'
     an argument may be a single element of `@ARGV', or part of a single
     `@ARGV' element, or the concatenation of several adjacent `@ARGV'
     elements.

"parameter definition"
     A specification of one actual syntax variant matched by a parameter.
     Always consists of a leading *parameter flag* or *parameter variable*,
     optionally followed by one or more *parameter components* (that is,
     other parameter variables or *punctuators*). In the above example,
     `--window <height> x <width>' is a parameter definition.

"parameter flag" (or just "flag")
     A sequence of non-space characters which introduces a parameter.
     Traditionally a parameter flag begins with "-" or "-", but
     `Getopt::Declare' allows almost any sequence of characters to be used
     as a flag. In the above example, `--window' is the parameter flag.

"parameter variable"
     A place-holder (within a parameter specification) for a value that
     will appear in any argument matching that parameter. In the above
     example, `<height>', `<width>', `<h>', `<y>', `<x>', and `<y>' are
     all parameter variables.

"parameter punctuator" (or just "punctuator")
     A literal sequence of characters (within a parameter specification)
     which will appear in any argument matching that parameter. In the
     above example, the literals x and `@' are punctuators.

"parameter description"
     A textual description of the purpose and/or use of a particular
     variant of parameter. In the above examples, the string:

          Set window to <height> by <width>

          is a parameter description.

"parameter action" (or just "action")
     A block of Perl code to be executed in response to encountering a
     specific parameter. In the above example:

          { setwin($width,$height); }

     is a parameter action.

"parameter variants"
     One or more different syntaxes for a single parameter, all sharing
     the same leading flag, but having different trailing parameter
     variables and/or punctuators. `Getopt::Declare' considers all
     parameter definitions with the same leading flag to be merely variant
     forms of a single "underlying" parameter. The above example shows two
     parameter variants for the `--window' parameter.

Parameter definitions
---------------------

   As indicated above, a parameter specification consists of three parts:
the parameter definition, a textual description, and any actions to be
performed when the parameter is matched.

   The parameter definition consists of a leading flag or parameter
variable, followed by any number of parameter variables or punctuators,
optionally separated by spaces. The parameter definition is terminated by
one or more tabs (at least one trailing tab must be present).

   For example, all of the following are valid `Getopt::Declare' parameter
definitions:

     -v
     in=<infile>
     +range <from>..<to>
     --lines <start> - <stop>
     ignore bad lines
     <outfile>

   Note that each of the above examples has at least one trailing tab
(even if you can't see them). Note too that this hodge-podge of parameter
styles is certainly not recommended within a single program, but is shown
so as to illustrate some of the range of parameter syntax conventions
`Getopt::Declare' supports.

   The spaces between components of the parameter definition are optional
but significant, both in the definition itself and in the arguments that
the definition may match. If there is no space between components in the
specification, then no space is allowed between corresponding arguments on
the command-line. If there *is* space between components of the
specification, then space between those components is optional on the
command-line.

   For example, the `--lines' parameter above matches:

     --lines1-10
     --lines 1-10
     --lines 1 -10
     --lines 1 - 10
     --lines1- 10

   If it were instead specified as:

     --lines <start>-<stop>

   then it would match only:

     --lines1-10
     --lines 1-10

   Note that the optional nature of spaces in parameter specification
implies that flags and punctuators cannot contain the character '<' (which
is taken as the delimiter for a parameter variable) nor the character '['
(which introduces an optional parameter component - see `"Optional
parameter components"' in this node).

Types of parameter variables
----------------------------

   By default, a parameter variable will match a single blank-terminated
or comma-delimited string. For example, the parameter:

     -val <value>

   would match any of the following the arguments:

     -value			# <value> <- "ue"
     -val abcd		# <value> <- "abcd"
     -val 1234		# <value> <- "1234"
     -val "a value"		# <value> <- "a value"

   It is also possible to restrict the types of values which may be
matched by a given parameter variable. For example:

     -limit <threshold:n>	Set threshold to some (real) value
     -count <N:i>		Set count to <N> (must be an integer)

   If a parameter variable is suffixed with ":n", it will match any
reasonable numeric value, whilst the ":i" suffix restricts a parameter
variable to only matching integer values.  These two "type specifiers" are
the simplest examples of a much more powerful mechanism, which allows
parameter variables to be restricted to matching any specific regular
expression. See `"Defining new parameter variable types"' in this node.

   Parameter variables are treated as scalars by default, but this too can
be altered. Any parameter variable immediately followed by an ellipsis
(...) is treated as a list variable, and matches its specified type
sequentially as many times as possible. For example, the parameter
specification:

     -pages <page:i>...

   would match either of the following arguments:

     -pages 1
     -pages 1 2 7 20

   Note that both scalar and list parameter variables are "respectful" of
the flags of other parameters as well as their own trailing punctuators.
For example, given the specifications:

     -a
     -b <b_list>...
     -c <c_list>... ;

   The following arguments will be parsed as indicated:

     -b -d -e -a		# <b_list>  <-  ("-d", "-e")
     -b -d ; 		# <b_list>  <-  ("-d", ";")
     -c -d ;			# <c_list>  <-  ("-d")

   List parameter variables are also "repectful" of the needs of
subsequent parameter variables. That is, a parameter specification like:

     -copy <files>... <dir>

   will behave as expected, putting all but the last string after the
`-copy' flag into the parameter variable `<files>', whilst the very last
string is assigned to `<dir>'.

Optional parameter components
-----------------------------

   Except for the leading flag, any part of a parameter definition may be
made optional by placing it in square brackets.  For example:

     +range <from> [..] [<to>]

   which matches any of:

     +range 1..10
     +range 1..
     +range 1 10
     +range 1

   List parameter variables may also be made optional (the ellipsis must
follow the parameter variable name immediately, so it goes *inside* the
square brackets):

     -list [<page>...]

   Two or more parameter components may be made jointly optional, by
specifying them in the same pair of brackets. Optional components may also
be nested. For example:

     -range <from> [.. [<to>] ]

   Scalar optional parameter variables (such as `[<to>]') are given
undefined values if they are skipped during a successful parameter match.
List optional parameter variables (such as `[<page>...]') are assigned an
empty list if unmatched.

   One important use for optional punctuators is to provide abbreviated
versions of specific flags. For example:

     -num[eric]		# Match "-num" or "-numeric"
     -lexic[ographic]al	# Match "-lexical" or "-lexicographical"
     -b[ells+]w[histles]	# Match "-bw" or "-bells+whistles"

   Note that the actual flags for these three parameters are `-num',
`-lexic' and -b, respectively.

Parameter descriptions
----------------------

   Providing a textual description for each parameter (or parameter
variant) is optional, but strongly recommended. Apart from providing
internal documentation, parameter descriptions are used in the
automatically-generated usage information provided by `Getopt::Declare'.

   Descriptions may be placed after the tab(s) following the parameter
definition and may be continued on subsequent lines, provided those lines
do not contain any tabs after the first non-whitespace character (because
any such line will instead be treated as a new parameter specification).
The description is terminated by a blank line, an action specification
(see below) or another parameter specification.

   For example:

     -v				Verbose mode
     in=<infile>			Specify input file
     				(will fail if file does not exist)

     +range <from>..<to>		Specify range of columns to consider
     --lines <start> - <stop>	Specify range of lines to process

     ignore bad lines		Ignore bad lines :-)

     <outfile>			Specify an output file

   The parameter description may also contain special directives which
alter the way in which the parameter is parsed. See the various
subsections of `"ADVANCED FEATURES"' in this node for more information.

Actions
-------

   Each parameter specification may also include one or more blocks of
Perl code, specified in a pair of curly brackets (which must start on a
new line).

   Each action is executed as soon as the corresponding parameter is
successfully matched in the command-line (but see `"Deferred actions"' in
this node for a means of delaying this response).

   For example:

     -v	Verbose mode
     		{ $::verbose = 1; }
     -q	Quiet mode
     		{ $::verbose = 0; }

   Actions are executed (as do blocks) in the package in which the
`Getopt::Declare' object containing them was created. Hence they have
access to all variables and functions in that scope.

   In addition, each parameter variable belonging to the corresponding
parameter is made available as a (block-scoped) Perl variable with the
same name. For example:

     +range <from>..<to>	Set range
     				{ setrange($from, $to); }

     -list <page:i>...	Specify pages to list
     				{ foreach (@page)
     				  {
     					list($_) if $_ > 0;
     				  }
     				}

   Note that scalar parameter variables become scalar Perl variables, and
list parameter variables become Perl arrays.

Predefined variables available in actions
-----------------------------------------

   Within an action the following variables are also available:

`$_PARAM_'
     Stores the identifier of the current parameter: either the leading
     flag or, if there is no leading flag, the name of the first parameter
     variable.

`%_PUNCT_'
     Stores the substring matched by each punctuator in the current
     parameter.  The hash is indexed by the punctuator itself. The main
     purpose of this variable is to allow actions to check whether
     optional punctuators were in fact matched.  For example:

          -v[erbose]	Set verbose mode
          		(doubly verbose if full word used)
          		    { if ($_PUNCT_{"erbose"}) { $verbose = 2; }
          		      else		      { $verbose = 1; }
          		    }

`%_FOUND_'
     This hash stores boolean values indicating whether or not a given
     parameter has already been found. The hash keys are the leading flags
     or parameter variables of each parameter. For instance, the following
     specification makes the -q and -v parameters mutually exclusive (but
     see `"Parameter dependencies"' in this node for a *much* easier way
     to achieve this effect):

          -v	Set verbose mode
          		{ die "Can't be verbose *and* quiet!\n"
          			if $_FOUND_{"-q"};
          		}

          -q	Set quiet mode
          		{ die "Can't be quiet *and* verbose!\n"
          			if $_FOUND_{"-v"};
          		}

     For reasons that will be explained in `"Rejection and termination"'
     in this node, a given parameter is not marked as found until after its
     associated actions are executed. That is, `$_FOUND_{$_PARAM_}' will
     not (usually) be true during a parameter action.

   Note that, although numerous other internal variables on which the
generated parser relies are also visible within parameter actions,
accessing any of them may have Dire Consequences. Moreover, these other
variables may no longer be accessible (or even present) in future versions
of `Getopt::Declare'. All such internal variables have names beginning
with an underscore. Avoiding such variables names will ensure there are no
conflicts between actions and the parser itself.

The command-line parsing process
--------------------------------

   Whenever a `Getopt::Declare' object is created, the current command-line
is parsed by sequentially, by attempting to match each parameter in the
object's specification string against the current elements in the `@ARGV'
array (but see `"Parsing from other sources"' in this node). The order in
which parameters are tried against `@ARGV' is determined by three rules:

  1. Parameters with longer flags are tried first. Hence the command-line
     argument "-quiet" would be parsed as matching the parameter `-quiet'
     rather than the parameter `-q <string>', even if the -q parameter was
     defined first.

  2. Parameter *variants* with the most components are matched first.
     Hence the argument "-rand 12345" would be parsed as matching the
     parameter variant `-rand <seed>', rather than the variant `-rand',
     even if the "shorter" `-rand' variant was defined first.

  3. Otherwise, parameters are matched in the order they are defined.

        Elements of `@ARGV' which do not match any defined parameter are
collected during the parse and are eventually put back into `@ARGV' (see
`"Strict and non-strict command-line parsing"' in this node).

ADVANCED FEATURES
=================

Case-insensitive parameter matching
-----------------------------------

   By default, a `Getopt::Declare' object parses the command-line in a
*case-sensitive* manner. The `[nocase]' directive enables a specific
parameter (or, alternatively, all parameters) to be matched
case-insensitively.

   If a `[nocase]' directive is included in the description of a specific
parameter variant, then that variant (only) will be matched without regard
for case. For example, the specification:

     -q	Quiet mode [nocase]

     -v	Verbose mode

   means that the arguments "-q" and "-Q" will both match the -q
parameter, but that only "-v" (and not "-V") will match the -v parameter.

   If a `[nocase]' directive appears anywhere *outside* a parameter
description, then the entire specification is declared case-insensitive
and all parameters defined in that specification are matched without
reagrd to case.

Termination and rejection
-------------------------

   It is sometimes useful to be able to terminate command-line processing
before all arguments have been parsed. To this end, `Getopt::Declare'
provides a special local operator (finish) which may be used within
actions. The finish operator takes a single optional argument. If the
argument is true (or omitted), command-line processing is terminated at
once (although the current parameter is still marked as having been
successfully matched). For example:

     --	Traditional argument list terminator
     		{ finish }

     -no--	Use non-traditional terminator instead
     		{ $nontrad = 1; }

     ##	Non-traditional terminator (only valid if -no-- flag seen)
     		{ finish($nontrad); }

   It is also possible to reject a single parameter match from within an
action (and then continue trying other candidates). This allows actions to
be used to perform more sophisticated tests on the type of a parameter
variable, or to implement complicated parameter interdependencies.

   To reject a parameter match, the `reject' operator is used. The
`reject' operator takes an optional argument.  If the argument is true (or
was omitted), the current parameter match is immediately rejected. For
example:

     -ar <R:n>	Set aspect ratio (must be in the range (0..1])
     			{
     			  $::sawaspect++;
     			  reject $R <= 0 || $R > 1 ;
     			  setaspect($R);
     			}

     -q		Quiet option (not available on Wednesdays)
     			{
     			  reject((localtime)[6] == 3);
     			  $::verbose = 0;
     			}

   Note that any actions performed before the call to `reject' will still
have effect (for example, the variable `$::sawaspect' remains incremented
even if the aspect ratio parameter is subsequently rejected).

   The `reject' operator may also take a second argument, which is used as
an error message if the rejected argument subsequently fails to match any
other parameter. For example:

     -q	Quiet option (not available on Wednesdays)
     		{
     		  reject((localtime)[6] == 3 => "Not today!");
     		  $::verbose = 0;
     		}

Specifying other parameter variable types
-----------------------------------------

   As was mentioned in `"Type of parameter variables"' in this node,
parameter variables can be restricted to matching only numbers or only
integers by using the type specifiers ":n" and ":i". `Getopt::Declare'
provides seven other inbuilt type specifiers, as well as two mechanisms
for defining new restrictions on parameter variables.

   The other inbuilt type specifiers are:

:+i
     which restricts a parameter variable to matching positive, non-zero
     integers (that is: 1, 2, 3, etc.)

:+n
     which restricts a parameter variable to matching positive, non-zero
     numbers (that is, floating point numbers strictly greater than zero).

:0+i
     which restricts a parameter variable to matching non-negative
     integers (that is: 0, 1, 2, 3, etc.)

:0+n
     which restricts a parameter variable to matching non-negative numbers
     (that is, floating point numbers greater than or equal to zero).

:s
     which allows a parameter variable to match any quote-delimited or
     whitespace-terminated string. Note that this specifier simply makes
     explicit the default behaviour.

:if
     which is used to match input file names. Like type ':s', type ':if'
     matches any quote-delimited or whitespace-terminated string. However
     this type does not respect other command-line flags and also requires
     that the matched string is either "-" (indicating standard input) or
     the name of a readable file.

:of
     which is used to match output file names. It is exactly like type
     ':if' except that it requires that the string is either "-"
     (indicating standard output) or the name of a file that is either
     writable or non-existent.

:s
     which allows a parameter variable to match any quote-delimited or
     whitespace-terminated string. Note that this specifier simply makes
     explicit the default behaviour.

   For example:

     -repeat <count:+i>	Repeat <count> times (must be > 0)

     -scale <factor:0+n>	Set scaling factor (cannot be negative)

   Alternatively, parameter variables can be restricted to matching a
specific regular expression, by providing the required pattern explicitly
(in matched "/" delimiters after the ":"). For example:

     -parity <p:/even|odd|both/>	Set parity (<p> must be "even",
     				"odd" or "both")

     -file <name:/\w*\.[A-Z]{3}/>	File name must have a three-
     				capital-letter extension

   If an explicit regular expression is used, there are three "convenience"
extensions available:

%T
     If the sequence %T appears in a pattern, it is translated to a
     negative lookahead containing the parameter variable's trailing
     context.  Hence the parameter definition:

          -find <what:/(%T\.)+/> ;

     ensures that the command line argument "-find abcd;" causes `<what>'
     to match "abcd", not "abcd;".

%D
     If the sequence %D appears in a pattern, it is translated into a
     subpattern which matches any single digit (like a `\d'), but only if
     that digit would not match the parameter variable's trailing context.
     Hence %D is just a convenient short-hand for `(?:%T\d)' (and is
     actually implemented that way).

%F
     By default, any explicit pattern is modified by `Getopt::Declare' so
     that it fails if the argument being matched represents some defined
     parameter flag. If however the sequence %F appears anywhere in a
     pattern, it causes the pattern not to reject strings which would
     otherwise match another flag. For example, the inbuilt types ':if' and
     ':of' use %F to enable them to match filenames which happen to be
     identical to parameter flags.

Defining new parameter variable types
-------------------------------------

   Explicit regular expressions are very powerful, but also cumbersome to
use (or reuse) in some situations. `Getopt::Declare' provides a general
"parameter variable type definition" mechanism to simplify such cases.

   To declare a new parameter variable type, the `[pvtype:...]' directive
is used. A `[pvtype...]' directive specifies the name, matching pattern,
and action for the new parameter variable type (though both the pattern
and action are optional).

   The name string may be any whitespace-terminated sequence of characters
which does not include a ">". The name may also be specified within a pair
of quotation marks (single or double) or within any Perl quotelike
operation. For example:

     [pvtype: num     ]	# Makes this valid: -count <N:num>
     [pvtype: 'a num' ]	# Makes this valid: -count <N:a num>
     [pvtype: q{nbr}  ]	# Makes this valid: -count <N:nbr>

   The pattern is used in initial matching of the parameter variable.
Patterns are normally specified as a "/"-delimited Perl regular expression:

     [pvtype: num      /\d+/        ]
     [pvtype: 'a num'  /\d+(\.\d*)/ ]
     [pvtype: q{nbr}   /[+-]?\d+/   ]

   Alternatively the pattern associated with a new type may be specified
as a ":" followed by the name of another parameter variable type (in
quotes if necessary). In this case the new type matches the same pattern
(and action! - see below) as the named type.  For example:

     [pvtype: num      :+i      ]	# <X:num> is the same as <X:+i>
     [pvtype: 'a num'  :n       ]	# <X:a num> is the same as <X:n>
     [pvtype: q{nbr}   :'a num' ]	# <X:nbr> is also the same as <X:n>

   As a third alternative, the pattern may be omitted altogether, in which
case the new type matches whatever the inbuilt pattern ":s" matches.

   The optional action which may be included in any `[pvtype:...]'
directive is executed after the corresponding parameter variable matches
the command line but before any actions belonging to the enclosing
parameter are executed. Typically, such type actions will call the
`reject' operator (see `"Termination and rejection"' in this node) to test
extra conditions, but any valid Perl code is acceptible. For example:

     [pvtype: num      /\d+/    { reject if (localtime)[6]==3 }	]
     [pvtype: 'a num'  :n       { print "a num!" }		]
     [pvtype: q{nbr}   :'a num' { reject $::no_nbr }		]

   If a new type is defined in terms of another (for example, ":a num" and
":nbr" above), any action specified by that new type is *prepended* to the
action of that other type. Hence:

   * the new type ":num" matches any string of digits, but then rejects the
     match if it's Wednesday.

   * the new type ":a num" matches any string of digits (like its parent
     type ":num"), *then* prints out "a num!", *and then* rejects the
     match if it's Wednesday (like its parent type ":num").

   * the new type ":nbr" matches any string of digits (like its parent type
     ":a num"), but then rejects the match if the global `$::no_nbr'
     variable is true. Otherwise it next prints out "a num!" (like its
     parent type ":a num"), and finally rejects the match if it's
     Wednesday (like its grandparent type ":num").

   When a type action is executed (as part of a particular parameter
match), three local variables are available:

`$_VAL_'
     which contains the value matched by the type's pattern. It is this
     value which is ultimately assigned to the local Perl variable which
     is available to parameter actions. Hence if the type action changes
     the value of `$_VAL_', that changed value becomes the "real" value of
     the corresponding parameter variable (see the Roman numeral example
     below).

`$_VAR_'
     which contains the name of the parameter variable being matched.

`$_PARAM_'
     which contains the name of the parameter currently being matched.

   Here is a example of the use of these variables:

     $args = new Getopt::Declare <<'EOPARAM';

     [pvtype: type  /[OAB]|AB')/	                                ]
     [pvtype: Rh?   /Rh[+-]/					        ]
     [pvtype: days  :+i  { reject $_VAL_<14 " $_PARAM_ (too soon!)"} ]

     -donated <D:days>		  Days since last donation
     -applied <A:days>		  Days since applied to donate

     -blood <type:type> [<rh:Rh?>]	  Specify blood type
     					  and (optionally) rhesus factor
     	EOPARAM

   In the above example, the ":days" parameter variable type is defined to
match whatever the ":+i" type matches (that is positive, non-zero
integers), with the proviso that the matching value (`$_VAL_') must be at
least 14. If a shorter value is specified for `<D>', or `<A>' parameter
variables, then `Getopt::Declare' would issue the following (respective)
error messages:

     Error: -donated (too soon!)
     Error: -applied (too soon!)

   Note that the "inbuilt" parameter variable types ("i", "n", etc.) are
really just predefined type names, and hence can be altered if necessary:

     $args = new Getopt::Declare <<'EOPARAM';

     [pvtype: 'n' /[MDCLXVI]+/ { reject !($_VAL_=to_roman $_VAL_) } ]

     -index <number:n>	Index number
     	{ print $data[$number]; }
     	EOPARAM

   The above `[pvtype:...]' directive means that all parameter variables
specified with a type ":n" henceforth only match valid Roman numerals, but
that any such numerals are *automatically* converted to ordinary numbers
(by passing `$_VAL_') through the `to_roman' function).

   Hence the requirement that all ":n" numbers now must be Roman can be
imposed *transparently*, at least as far as the actual parameter variables
which use the ":n" type are concerned. Thus `$number' can be still used to
index the array `@data' despite the new restrictions placed upon it by the
redefinition of type ":n".

   Note too that, because the ":+n" and ":0+n" types are implicitly
defined in terms of the original ":n" type (as if the directives:

     [pvtype: '+n'  :n { reject if $_VAL <= 0  }  ]
     [pvtype: '0+n' :n { reject if $_VAL < 0   }  ]

   were included in every specification), the above redefinition of ":n"
affects those types as well. In such cases the format conversion is
performed before the "sign" tests (in other words, the "inherited" actions
are performed after any newly defined ones).

   Parameter variable type definitions may appear anywhere in a
`Getopt::Declare' specification and are effective for the entire scope of
the specification. In particular, new parameter variable types may be
defined after they are used.

Undocumented parameters
-----------------------

   If a parameter description is omitted, or consists entirely of
whitespace, or contains the special directive `[undocumented]', then the
parameter is still parsed as normal, but will not appear in the
automatically generated usage information (see `"Usage information"' in
this node).

   Apart from allowing for "secret" parameters (a dubious benefit), this
feature enables the programmer to specify some undocumented action which
is to be taken on encountering an otherwise unknown argument.  For example:

     <unknown>
     		{ handle_unknown($unknown); }

"Dittoed" parameters
--------------------

   Sometimes it is desirable to provide two or more alternate flags for
the same behaviour (typically, a short form and a long form). To reduce
the burden of specifying such pairs, the special directive `[ditto]' is
provided. If the description of a parameter *begins* with a `[ditto]'
directive, that directive is replaced with the description for the
immediately preceding parameter (including any other directives). For
example:

     -v		Verbose mode
     --verbose	[ditto] (long form)

   In the automatically generated usage information this would be
displayed as:

     -v		Verbose mode
     --verbose	   "     "   (long form)

   Furthermore, if the "dittoed" parameter has no action(s) specified, the
action(s) of the preceding parameter are reused. For example, the
specification:

     -v		Verbose mode
     			{ $::verbose = 1; }
     --verbose	[ditto]

   would result in the `--verbose' option setting `$::verbose' just like
the -v option. On the other hand, the specification:

     -v		Verbose mode
     			{ $::verbose = 1; }
     --verbose	[ditto]
     			{ $::verbose = 2; }

   would give separate actions to each flag.

Deferred actions
----------------

   It is often desirable or necessary to defer actions taken in response
to particular flags until the entire command-line has been parsed. The most
obvious case is where modifier flags must be able to be specified after
the command-line arguments they modify.

   To support this, `Getopt::Declare' provides a local operator (`defer')
which delays the execution of a particular action until the command-line
processing is finished. The `defer' operator takes a single block, the
execution of which is deferred until the command-line is fully and
successfully parsed. If command-line processing *fails* for some reason
(see `"DIAGNOSTICS"' in this node), the deferred blocks are never executed.

   For example:

     <files>...	Files to be processed
     		    { defer { foreach (@files) { proc($_); } } }

     -rev[erse]	Process in reverse order
     		    { $::ordered = -1; }

     -rand[om]	Process in random order
     		    { $::ordered = 0; }

   With the above specification, the `-rev' and/or `-rand' flags can be
specified after the list of files, but still affect the processing of
those files. Moreover, if the command-line parsing fails for some reason
(perhaps due to an unrecognized argument), the deferred processing will
not be performed.

Flag clustering
---------------

   Like some other `Getopt::' packages, `Getopt::Declare' allows parameter
flags to be "clustered". That is, if two or more flags have the same "flag
prefix" (one or more leading non-whitespace, non-alphanumeric characters),
those flags may be concatenated behind a single copy of that flag prefix.
For example, given the parameter specifications:

     -+		Swap signs
     -a		Append mode
     -b		Bitwise compare
     -c <FILE>	Create new file
     +del		Delete old file
     +e <NICE:i>	Execute (at specified nice level) when complete

   The following command-lines (amongst others) are all exactly equivalent:

     -a -b -c newfile +e20 +del
     -abc newfile +dele20
     -abcnewfile+dele20
     -abcnewfile +e 20del

   The last two alternatives are correctly parsed because
`Getopt::Declare' allows flag clustering at *any point* where the
remainder of the command-line being processed starts with a non-whitespace
character and where the remaining substring would not otherwise
immediately match a parameter flag.

   Hence the trailing "+dele20" in the third command-line example is
parsed as "+del +e20" and not "-+ del +e20". This is because the previous
"-" prefix is not propagated (since the leading "+del" *is* a valid flag).

   In contrast, the trailing "+e 20del" in the fourth example is parsed as
"+e 20 +del" because, after the " 20" is parsed (as the integer parameter
variable `<NICE>'), the next characters are "del", which *do not* form a
flag themselves unless prefixed with the controlling "+".

   In some circumstances a clustered sequence of flags on the command-line
might also match a single (multicharacter) parameter flag. For example,
given the specifications:

     -a		Blood type is A
     -b		Blood type is B
     -ab	 	Blood type is AB
     -ba	 	Donor has a Bachelor of Arts

   A command-line argument "-aba" might be parsed as "-a -b -a" or
"-a -ba" or "-ab -a". In all such cases, `Getopt::Declare' prefers the
longest unmatched flag first.  Hence the previous example would be parsed
as "-ab -a", unless the `-ab' flag had already appeared in the
command-line (in which case, it would be parsed as "-a -ba").

   These rules are designed to produce consistency and "least surprise",
but (as the above example illustrates) may not always do so. If the idea
of unconstrained flag clustering is too libertarian for a particular
application, the feature may be restricted (or removed completely), by
including a `[cluster:...]' directive anywhere in the specification string.

   The options are:

`[cluster: any]'
     This version of the directive allows any flag to be clustered (that
     is, it merely makes explicit the default behaviour).

`[cluster: flags]'
     This version of the directive restricts clustering to parameters
     which are "pure" flags (that is, those which have no parameter
     variables or punctuators).

`[cluster: singles]'
     This version of the directive restricts clustering to parameters
     which are "pure" flags, and which consist of a flag prefix followed
     by a single alphanumeric character.

`[cluster: none]'
     This version of the directive turns off clustering completely.

   For example:

     $args = new Getopt::Declare <<'EOSPEC';
     	-a		Append mode
     	-b		Back-up mode
     	-bu		[ditto]
     	-c <file>	Copy mode
     	-d [<file>]	Delete mode
     	-e[xec]		Execute mode

     [cluster:singles]
     	EOSPEC

   In the above example, only the -a and -b parameters may be clustered.
The `-bu' parameter is excluded because it consists of more than one
letter, whilst the -c and -d parameters are excluded because they take (or
may take, in -d's case) a variable. The `-e[xec]' parameter is excluded
because it may take a trailing punctuator (`[xec]').

   By comparison, if the directive had been `[cluster: flags]', then `-bu'
*could* be clustered, though -c, -d and `-e[xec]' would still be excluded
since they are not "pure flags").

Strict and non-strict command-line parsing
------------------------------------------

   "Strictness" in `Getopt::Declare' refers to the way in which
unrecognized command-line arguments are handled. By default,
`Getopt::Declare' is "non-strict", in that it simply skips silently over
any unrecognized command-line argument, leaving it in `@ARGV' at the
conclusion of command-line processing.

   However, if a new `Getopt::Declare' object is created with a
specification string containing the `[strict]' directive (at any point in
the specification):

     $args = new Getopt::Declare <<'EOSPEC';

     [strict]

     -a	Append mode
     -b	Back-up mode
     -c	Copy mode
     	EOSPEC

   then the command-line is parsed "strictly". In this case, any
unrecognized argument causes an error message (see `"DIAGNOSTICS"' in this
node) to be written to STDERR, and command-line processing to (eventually)
fail. On such a failure, the call to `Getopt::Declare::new()' returns
undef instead of the usual hash reference.

   The only concession that "strict" mode makes to the unknown is that, if
command-line processing is prematurely terminated via the finish operator,
any command-line arguments which have not yet been examined are left in
`@ARGV' and do not cause the parse to fail (of course, if any unknown
arguments were encountered before the finish was executed, those earlier
arguments *will* cause command-line processing to fail).

   The "strict" option is useful when all possible parameters can be
specified in a single `Getopt::Declare' object, whereas the "non-strict"
approach is needed when unrecognized arguments are either to be quietly
tolerated, or processed at a later point (possibly in a second
`Getopt::Declare' object).

Parameter dependencies
----------------------

   `Getopt::Declare' provides five other directives which modify the
behaviour of the command-line parser in some way. One or more of these
directives may be included in any parameter description. In addition, the
`[mutex:...]' directive may also appear in any usage "decoration" (see
`"Usage information"' in this node).

   Each directive specifies a particular set of conditions that a
command-line must fulfil (for example, that certain parameters may not
appear on the same command-line). If any such condition is violated, an
appropriate error message is printed (see `"DIAGNOSTICS"' in this node).
Furthermore, once the command-line is completely parsed, if any condition
was violated, the program terminates (whilst still inside
`Getopt::Declare::new()').

   The directives are:

`[required]'
     Specifies that an argument matching at least one variant of the
     corresponding parameter must be specified somewhere in the
     command-line. That is, if two or more required parameters share the
     same flag, it suffices that *any one* of them matches an argument
     (recall that `Getopt::Declare' considers all parameter specifications
     with the same flag merely to be variant forms of a single "underlying"
     parameter).

     If an argument matching a "required" flag is not found in the
     command-line, an error message to that effect is issued, command-line
     processing fails, and `Getopt::Declare::new()' returns undef.

`[repeatable]'
     By default, `Getopt::Declare' objects allow each of their parameters
     to be matched only once (that is, once any variant of a particular
     parameter matches an argument, all variants of that same parameter
     are subsequently excluded from further consideration when parsing the
     rest of the command-line).

     However, it is sometimes useful to allow a particular parameter to
     match more than once.  Any parameter whose description includes the
     directive `[repeatable]' is never excluded as a potential argument
     match, no matter how many times it has matched previously:

          -nice		Increase nice value (linearly if repeated)
          		[repeatable]
          			{ set_nice( get_nice()+1 ); }

          -w		Toggle warnings [repeatable] for the rest
          		of the command-line
          			{ $warn = !$warn; }

     As a more general mechanism is a `[repeatable]' directive appears in a
     specification anywhere other than a flag's description, then all
     parameters are marked repeatable:

          [repeatable]

          -nice		Increase nice value (linearly if repeated)
          			{ set_nice( get_nice()+1 ); }

          -w		Toggle warnings for the rest of the command-line
          			{ $warn = !$warn; }

`[mutex: <flag list>]'
     The `[mutex:...]' directive specifies that the parameters whose flags
     it lists are mutually exclusive. That is, no two or more of them may
     appear in the same command-line. For example:

          -case		set to all lower case
          -CASE		SET TO ALL UPPER CASE
          -Case		Set to sentence case
          -CaSe		SeT tO "RAnSom nOTe" CasE

          [mutex: -case -CASE -Case -CaSe]

     The interaction of the `[mutex:...]' and `[required]' directives is
     potentially awkward in the case where two "required" arguments are
     also mutually exclusive (since the `[required]' directives insist
     that both parameters must appear in the command-line, whilst the
     `[mutex:...]' directive expressly forbids this).

     `Getopt::Declare' resolves such contradictory constraints by relaxing
     the meaning of "required" slightly. If a flag is marked "required",
     it is considered "found" for the purposes of error checking if it or
     *any other flag with which it is mutually exclusive* appears on the
     command-line.

     Hence the specifications:

          -case		set to all lower case      [required]
          -CASE		SET TO ALL UPPER CASE      [required]
          -Case		Set to sentence case       [required]
          -CaSe		SeT tO "RAnSom nOTe" CasE  [required]

          [mutex: -case -CASE -Case -CaSe]

     mean that *exactly one* of these four flags must appear on the
     command-line, but that the presence of any one of them will suffice
     to satisfy the "requiredness" of all four.

     It should also be noted that mutual exclusion is only tested for
     after a parameter has been completely matched (that is, after the
     execution of its actions, if any). This prevents "rejected" parameters
     (see `"Termination and rejection"' in this node) from incorrectly
     generating mutual exclusion errors. However, it also sometimes makes
     it necessary to defer the actions of a pair of mutually exclusive
     parameters (for example, if those actions are expensive or
     irreversible).

`[excludes: <flag list>]'
     The `[excludes:...]' directive provides a "pairwise" version of
     mutual exclusion, specifying that the current parameter is mutually
     exclusive with all the other parameters lists, but those other
     parameters are not mutually exclusive with each other. That is,
     whereas the specification:

          -left		Justify to left margin
          -right		Justify to right margin
          -centre		Centre each line

          [mutex: -left -right -centre]

     means that only one of these three justification alternatives can
     ever be used at once, the specification:

          -left		Justify to left margin
          -right		Justify to right margin
          -centre		Centre each line  [excludes: -left -right]

     means that `-left' and `-right' can still be used together (probably
     to indicate "left and right" justification), but that neither can be
     used with `-centre'. Note that the `[excludes:...]'  directive also
     differs from the `[mutex:...]' in that it is always connected with a
     paricular parameter, *implicitly* using the flag of that parameter as
     the target of exclusion.

`[requires: <condition>]'
     The `[requires]' directive specifies a set of flags which must also
     appear in order for a particular flag to be permitted in the
     command-line. The condition is a boolean expression, in which the
     terms are the flags or various parameters, and the operations are
     `&&', `||', !, and bracketting. For example, the specifications:

          -num		Use numeric sort order
          -lex		Use "dictionary" sort order
          -len		Sort on length of line (or field)

          -field <N:+i>	Sort on value of field <N>

          -rev		Reverse sort order
          		[requires: -num || -lex || !(-len && -field)]

     means that the `-rev' flag is allowed only if either the `-num' or the
     `-lex' parameter has been used, or if it is not true that both the
     `-len' and the `-field' parameters have been used.

     Note that the operators `&&', `||', and ! retain their normal Perl
     precedences.

Parsing from other sources
--------------------------

   `Getopt::Declare' normally parses the contents of `@ARGV', but can be
made to parse specified files instead. To accommodate this,
`Getopt::Declare::new()' takes an optional second parameter, which
specifies a file to be parsed. The parameter may be either:

A IO::Handle reference or a filehandle GLOB reference
     in which case `Getopt::Declare::new()' reads the corresponding handle
     until end-of-file, and parses the resulting text (even if it is an
     empty string).

An ARRAY reference containing the single string `'-CONFIG''
     in which case `Getopt::Declare::new()' looks for the files
     `$ENV{HOME}/.${progname}rc' and `$ENV{PWD}/.${progname}rc',
     concatenates their contents, and parses that.

     If neither file is found (or if both are inaccessible)
     `Getopt::Declare::new()' immediately returns zero. If a file is found
     but the parse subsequently fails, undef is returned.

An ARRAY reference containing the single string `'-BUILD''
     in which case `Getopt::Declare::new()' builds a parser from the
     supplied grammar and returns a reference to it, but does not parse
     anything.  See `"The Getopt::Declare::code() method"' in this node and
     `"The Getopt::Declare::parse() method"' in this node.

An ARRAY reference containing the single string `'-SKIP'' or the single value undef or nothing
     in which case `Getopt::Declare::new()' immediately returns zero.
     This alternative is useful when using a FileHandle:

          my $args = new Getopt::Declare($grammar,
          			       new FileHandle ($filename) || -SKIP);

     because it makes explicit what happens if `FileHandle::new()' fails.
     Of course, if the `-SKIP' alternative were omitted,
     <Getopt::Declare::new> would still return immediately, having found
     undef as its second argument.

Any other ARRAY reference
     in which case `Getopt::Declare::new()' treats the array elements as a
     list of filenames, concatenates the contents of those files, and
     parses that.

     If the list does not denote any accessible file(s)
     `Getopt::Declare::new()' immediately returns zero. If matching files
     are found, but not successfully parsed, undef is returned.

A string
     in which case `Getopt::Declare::new()' parses that string directly.

   Note that when `Getopt::Declare::new()' parses from a source other than
`@ARGV', unrecognized arguments are not placed back in `@ARGV'.

Using `Getopt::Declare' objects after command-line processing
-------------------------------------------------------------

   After command-line processing is completed, the object returned by
`Getopt::Declare::new()' will have the following features:

Parameter data
     For each successfully matched parameter, the `Getopt::Declare' object
     will contain a hash element. The key of that element will be the
     leading flag or parameter variable name of the parameter.

     The value of the element will be a reference to another hash which
     contains the names and values of each distinct parameter variable
     and/or punctuator which was matched by the parameter. Punctuators
     generate string values containing the actual text matched. Scalar
     parameter variables generate scalar values. List parameter variables
     generate array references.

     As a special case, if a parameter consists of a single component
     (either a single flag or a single parameter variable), then the value
     for the corresponding hash key is not a hash reference, but the
     actual value matched.

     The following example illustrates the various possibilities:

          $args = new Getopt::Declare, q{

          -v <value> [etc]	One or more values
          <infile>		Input file [required]
          -o <outfiles>...	Output files
          	};

          if ( $args->{'-v'} )
          {
          	print  "Using value: ", $args->{'-v'}{'<value>'};
          	print  " (et cetera)" if $args->{'-v'}{'etc'};
          	print  "\n";
          }

          open INFILE, $args->{'<infile>'} or die;
          @data = <INFILE>;

          foreach $outfile ( @{$args->{'-o'}{'<outfiles>'}} )
          {
          	open  OUTFILE, ">$outfile"  or die;
          	print OUTFILE process(@data);
          	close OUTFILE;
          }

     The values which are assigned to the various hash elements are copied
     from the corresponding blocked-scoped variables which are available
     within actions. In particular, if the value of any of those
     block-scoped variables is changed within an action, that changed
     value is saved in the hash. For example, given the specification:

          $args = new Getopt::Declare, q{

          -ar <R:n>	Set aspect ratio (will be clipped to [0..1])
          			{
          			  $R = 0 if $R < 0;
          			  $R = 1 if $R > 1;
          			}
          };

     then the value of `$args->{'-ar'}{'<R>'}' will always be between zero
     and one.

The `@ARGV' array
     In its "non-strict" mode, once a `Getopt::Declare' object has
     completed its command-line processing, it pushes any unrecognized
     arguments back into the emptied command-line array `@ARGV' (whereas
     all *recognized* arguments will have been removed).

     Note that these remaining arguments will be in sequential elements
     (starting at `$ARGV[0]'), not in their original positions in `@ARGV'.

The `Getopt::Declare::usage()' method
     Once a `Getopt::Declare' object is created, its `usage()' method may
     be called to explicitly print out usage information corresponding to
     the specification with which it was built. See `"Usage information"'
     in this node for more details.  If the `usage()' method is called
     with an argument, that argument is passed to exit after the usage
     information is printed (the no-argument version of `usage()' simply
     returns at that point).

The `Getopt::Declare::version()' method
     Another useful method of a `Getopt::Declare' object is version(),
     which prints out the name of the enclosing program, the last time it
     was modified, and the value of `$::VERSION', if it is defined.  Note
     that this implies that all `Getopt::Declare' objects in a single
     program will print out identical version information.

     Like the `usage()' method, if version is passed an argument, it will
     exit with that value after printing.

The `Getopt::Declare::parse()' method
     It is possible to separate the construction of a `Getopt::Declare'
     parser from the actual parsing it performs. If
     `Getopt::Declare::new()' is called with a second parameter `'-BUILD''
     (see `"Parsing from other sources"' in this node, it constructs and
     returns a parser, without parsing anything.  The resulting parser
     object can then be used to parse multiple sources, by calling its
     parse() method.

     `Getopt::Declare::parse()' takes an optional parameter which specifies
     the source of the text to be parsed (it parses `@ARGV' if the
     parameter is omitted). This parameter takes the same set of values as
     the optional second parameter of `Getopt::Declare::new()' (see
     `"Parsing from other sources"' in this node).

     `Getopt::Declare::parse()' returns true if the source is located and
     parsed successfully. It returns a defined false (zero) if the source
     is not located. An undef is returned if the source is located, but not
     successfully parsed.

     Thus, the following code first constructs a parsers for a series of
     alternate configuration files and the command line, and then parses
     them:

          # BUILD PARSERS
          my $config  = Getopt::Declare::new($config_grammar, -BUILD);
          my $cmdline = Getopt::Declare::new($cmdline_grammar, -BUILD);

          # TRY STANDARD CONFIG FILES
          $config->parse(-CONFIG)

          # OTHERWISE, TRY GLOBAL CONFIG
          or $config->parse('/usr/local/config/.demo_rc')

          # OTHERWISE, TRY OPENING A FILEHANDLE (OR JUST GIVE UP)
          or $config->parse(new FileHandle (".config") || -SKIP);

          # NOW PARSE THE COMMAND LINE

          $cmdline->parse() or die;

The `Getopt::Declare::code()' method
     It is also possible to retreive the command-line parsing code
     generated internally by `Getopt::Declare::new()'. The
     `Getopt::Declare::code()' method returns a string containing the
     complete command-line processing code, as a single do block plus a
     leading package declaration.

     `Getopt::Declare::code()' takes as its sole argument a string
     containing the complete name of the package (for the leading package
     declaration in the generated code). If this string is empty or
     undefined, the package name defaults to "main".

     Since the default behaviour of `Getopt::Declare::new()' is to execute
     the command-line parsing code it generates, if the goal is only to
     generate the parser code, the optional second '-BUILD' parameter (see
     `"Parsing from other sources"' in this node) should be specified when
     calling <Getopt::Declare::new()>.

     For example, the following program "inlines" a `Getopt::Declare'
     specification, by extracting it from between the first "=for
     Getopt::Declare" and the next "=cut" appearing on STDIN:

          use Getopt::Declare;

          sub encode { return new Getopt::Declare (shift,-BUILD)->code() || die }

          undef $/;
          if (<>)
          {
          	s {^=for\s+Getopt::Declare\s*\n(.*?)\n=cut}
          	  {'my (\$self,$source) = ({});'.encode($1).' or die "\n";'}
          	  esm;
          }

          print;

     Note that the generated inlined version expects to find a lexical
     variable named `$source', which tells it what to parse (this variable
     is normally set by the optional parameters of
     `Getopt::Declare::new()' or `Getopt::Declare::parse()').

     The inlined code leaves all extracted parameters in the lexical
     variable `$self' and the does not autogenerate help or version flags
     (since there is no actual `Getopt::Declare' object in the inlined code
     through which to generate them).

AUTOGENERATED FEATURES
======================

Usage information
-----------------

   The specification passed to `Getopt::Declare::new' is used (almost
verbatim) as a "usage" display whenever usage information is requested.

   Such requests may be made either by specifying an argument matching the
help parameter (see `"Help parameters"' in this node) or by explicitly
calling the `Getopt::Declare::usage()' method (through an action or after
command-line processing):

     $args = new Getopt::Declare, q{

     -usage		Show usage information and exit
     			{ $self->usage(0); }

     +usage		Show usage information at end of program
     	};

     # PROGRAM HERE

     $args->usage()  if $args->{'+usage'};

   The following changes are made to the original specification before it
is displayed:

   * All actions and comments are deleted,

   * any `[ditto]' directive is converted to an appropriate set of "ditto"
     marks,

   * any text in matching square brackets (including any directive) is
     deleted,

   * any parameter variable type specifier (":i", ":n", ":/pat/", etc.) is
     deleted.

   Otherwise, the usage information displayed retains all the formatting
present in the original specification.

   In addition to this information, if the input source is @ARGV,
`Getopt::Declare' displays three sample command-lines: one indicating the
normal usage (including any required parameter variables), one indicating
how to invoke help (see `"Help parameters"' in this node), and one
indicating how to determine the current version of the program (see
`"Version parameters"' in this node).

   The usage information is printed to STDOUT and (since `Getopt::Declare'
tends to encourage longer and better-documented parameter lists) if the
`IO::Pager' package is available, an `IO::Pager' object is used to page
out the entire usage documentation.

Usage "decoration"
------------------

   It is sometimes convenient to add other "decorative" features to a
program's usage information, such as subheadings, general notes,
separators, etc. `Getopt::Declare' accommodates this need by ignoring such
items when interpreting a specification string, but printing them when
asked for usage information.

   Any line which cannot be interpreted as either a parameter definition,
a parameter description, or a parameter action, is treated as a
"decorator" line, and is printed verbatim (after any square bracketted
substrings have been removed from it).

   The key to successfully decorating `Getopt::Declare' usage information
is to ensure that decorator lines are separated from any preceding
parameter specification, either by an action or by an empty line. In
addition, like a parameter description, a decorator line cannot contain a
tab character after the first non-whitespace character (because it would
then be treated as a parameter specification).

   The following specification demonstrates various forms of usage
decoration. In fact, there are only four actual parameters (`-in', -r, -p,
and `-out') specified. Note in particular that *leading* tabs are
perfectly acceptible in decorator lines.

     $args = new Getopt::Declare (<<'EOPARAM');

     ============================================================
     Required parameter:

     -in <infile>		Input file [required]

     ------------------------------------------------------------

     Optional parameters:

     (The first two are mutually exclusive) [mutex: -r -p]

     -r[and[om]]		Output in random order
     -p[erm[ute]]		Output all permutations

     ---------------------------------------------------

     -out <outfile>		Optional output file

     ------------------------------------------------------------
     Note: this program is known to run very slowly of files with
           long individual lines.
     ============================================================
     EOPARAM

Help parameters
---------------

   By default, `Getopt::Declare' automatically defines all of the following
parameters:

     -help	Show usage information [undocumented]
     		{ $self->usage(0); }
     -Help	[ditto]
     -HELP	[ditto]
     --help	[ditto]
     --Help	[ditto]
     --HELP	[ditto]
     -h	[ditto]
     -H	[ditto]

   Hence, most attempts by the user to get help will automatically work
successfully.

   Note however that, if a parameter with any of these flags is explicitly
specified in the string passed to `Getopt::Declare::new()', that flag
(only) is removed from the list of possible help flags. For example:

     -w <pixels:+i>	Specify width in pixels
     -h <pixels:+i>	Specify height in pixels

   would cause the -h help parameter to be removed (although help would
still be accessible through the other seven alternatives).

Version parameters
------------------

   `Getopt::Declare' also automatically creates a set of parameters which
can be used to retreive program version information:

     -version	Show version information [undocumented]
     			{ $self->version(0); }
     -Version	[ditto]
     -VERSION	[ditto]
     --version	[ditto]
     --Version	[ditto]
     --VERSION	[ditto]
     -v		[ditto]
     -V		[ditto]

   As with the various help commands, explicitly specifying a parameter
with any of the above flags removes that flag from the list of version
flags.

DIAGNOSTICS
===========

   `Getopt::Declare' may issue the following diagnostics whilst parsing a
command-line. All of them are fatal (the first five, instantly so):

"Error: bad Getopt::Declare parameter variable specification near %s"
     A matching pair of angle brackets were specified as part of a
     parameter definition, but did not form a valid parameter variable
     specification (that is, it wasn't in the form: <name> or <name:type>).

"Error: bad type in Getopt::Declare parameter variable specification near %s"
     An unknown type specifier was used in a parameter variable type
     suffix.

"Error: bad action in Getopt::Declare specification:\n %s"
     A Perl syntax error was detected in the indicated action.

"Error: unattached action in Getopt::Declare specification:\n %s"
     An action was found for which there was no preceding parameter
     specification.  This usually occurs because the trailing tab was
     omitted from the preceding parameter specification.

"Error: incomplete action in Getopt::Declare specification:\n %s"
     An action was found, but it was missing one or more closing '}'s.

"Error: bad condition in directive [requires: %s]\n"
     The condition specified as part of the indicated `[requires:...]'
     directive was not a well-formed boolean expression. Common problems
     include: omitting a `&&'/`||' operator between two flags, mismatched
     brackets, or using and/or instead of `&&'/`||'.

"Error: in generated command-line parser code:\n %s"
     Either there was a Perl syntax error in one some action (which was
     not caught by the previous diagnostic), or (less likely) there is a
     bug in the code generator inside `Getopt::Declare'.

"Error: incorrect specification of %s parameter"
     The flag for the indicated parameter was found, but the argument did
     not then match any of that parameter's variant syntaxes.

"Error: parameter %s not allowed with %s"
     Two mutually exclusive flags were specified together.

"Error: required parameter %s not found"
     No argument matching the specified "required" parameter was found
     during command-line processing.

"Error: parameter %s can only be specified with %s"
     The indicated parameter has a `[requires:...]' directive, which was
     not satisfied.

"Error: unknown command-line argument (%s)"
     A command-line argument was encountered which did not match any
     specified parameter. This diagnostic can only only appear if the
     "strict" option is in effect.

"Error: in parameter %s (%s must be an integer greater than zero)"
     A parameter variable in the indicated parameter was declared with the
     type ":+i" (or a type derived from it), but the corresponding
     argument was not a positive, non-zero integer.

"Error: in parameter %s (%s must be a number greater than zero)"
     A parameter variable in the indicated parameter was declared with the
     type ":+n" (or a type derived from it), but the corresponding
     argument was not a positive, non-zero number.

"Error: in parameter %s (%s must be an positive integer)"
     A parameter variable in the indicated parameter was declared with the
     type ":0+i" (or a type derived from it), but the corresponding
     argument was not a positive integer.

"Error: in parameter %s (%s must be a positive number)"
     A parameter variable in the indicated parameter was declared with the
     type ":0+n" (or a type derived from it), but the corresponding
     argument was not a positive number.

AUTHOR
======

   Damian Conway (damian@cs.monash.edu.au)

BUGS AND ANNOYANCES
===================

   There are undoubtedly serious bugs lurking somewhere in this code.

   If nothing else, it shouldn't take 1500 lines to explain a package that
was designed for intuitive ease of use!

   Bug reports and other feedback are most welcome.

COPYRIGHT
=========

     Copyright (c) 1997, Damian Conway. All Rights Reserved.
          This module is free software. It may be used, redistributed
          and/or modified under the terms of the Perl Artistic License
        (see http://www.perl.com/perl/misc/Artistic.html)

evaluate Perl command line parameters.
**************************************

NAME
====

   Getopt::EvaP - evaluate Perl command line parameters.

SYNOPSIS
========

     use vars qw/@PDT @MM %OPT/;
     use Getopt::EvaP;

     EvaP \@PDT, \@MM, \%OPT;

EXPORT
======

   `use Getopt::EvaP' exports the subs `EvaP' and `EvaP_PAC' into your
name space.

DESCRIPTION
===========

   *@PDT* is the Parameter Description Table, which is a reference to a
list of strings describing the command line parameters, aliases, types and
default values.  *@MM* is the Message Module, which is also a reference to
a list of strings describing the command and it's parameters.  *%OPT* is
an optional hash reference where Evaluate Parameters should place its
results.  If specified, the historical behaviour of modifying the calling
routines' namespace by storing option values in *%Options*, %options and
*$opt** is disabled.

Introduction
------------

   Function Evaluate Parameters parses a Perl command line in a simple and
consistent manner, performs type checking of parameter values, and provides
the user with first-level help.  Evaluate Parameters is also embeddable in
your application; refer to the *evap_pac(2)* man page for complete details.
Evaluate Parameters handles command lines in the following format:

     command [-parameters] [file_list]

   where parameters and file_list are all optional.  A typical example is
the C compiler:

     cc -O -o chunk chunk.c

   In this case there are two parameters and a file_list consisting of a
single file name for the cc command.

Parameter Description Table (PDT) Syntax
----------------------------------------

   Here is the PDT syntax.  Optional constructs are enclosed in [], and the
| character separates possible values in a list.

     PDT [program_name, alias]
       [parameter_name[, alias]: type [ = [default_variable,] default_value]]
     PDTEND [optional_file_list | required_file_list | no_file_list]

   So, the simplest possible PDT would be:

     PDT
     PDTEND

   This PDT would simply define a *-help* switch for the command, but is
rather useless.

   A typical PDT would look more like this:

     PDT frog
       number, n: integer = 1
     PDTEND no_file_list

   This PDT, for command frog, defines a single parameter, number (or n),
of type integer with a default value of 1.  The PDTEND *no_file_list*
indicator indicates that no trailing file_list can appear on the command
line.  Of course, the *-help* switch is defined automatically.

   The *default_variable* is an environment variable - see the section
Usage Notes for complete details.

Usage Notes
-----------

   Usage is similar to getopt/getopts/newgetopt: define a Parameter
Description Table declaring a list of command line parameters, their
aliases, types and default values.  The command line parameter *-help*
(alias -h) is automatically included by Evaluate Parameters.  After the
evaluation the values of the command line parameters are stored in
variable names of the form *$opt_parameter*, except for lists which are
returned as *@opt_parameter*, where parameter is the full spelling of the
command line parameter.  NOTE: values are also returned in the hashes
%options and *%Options*, with lists being passed as a reference to a list.

   Of course, you can specify where you want Evaluate Parameters to return
its results, in which case this historical feature of writing into your
namespace is disabled.

   An optional PDT line can be included that tells Evaluate Parameters
whether or not trailing file names can appear on the command line after
all the parameters.  It can read *no_file_list*, *optional_file_list* or
*required_file_list* and, if not specified, defaults to optional.  Although
placement is not important, this line is by convention the last line of the
PDT declaration.

   Additionally a Message Module is declared that describes the command
and provides examples.  Following the main help text an optional series of
help text messages can be specified for individual command line
parameters.  In the following sample program all the parameters have this
additional text which describes that parameter's type.  The leadin
character is a dot in column one followed by the full spelling of the
command line parameter.  Use *-full_help* rather than *-help* to see this
supplemental information.  This sample program illustrates the various
types and how to use *EvaP()*.  The key type is a special type that
enumerates valid values for the command line parameter.  The boolean type
may be specified as TRUE/FALSE, YES/NO, ON/OFF or 1/0.  Parameters of type
file have ~ and $HOME expanded, and default values stdin and stdout
converted to `-' and `>-', respectively.  Of special note is the default
value *$required*: when specified, Evaluate Parameters will ensure a value
is specified for that command line parameter.

   All types except switch may be *list of*, like the tty parameter below.
A list parameter can be specified multiple times on the command line.
NOTE: in general you should ALWAYS quote components of your lists, even if
they're not type string, since Evaluate Parameters uses eval to parse them.
Doing this prevents eval from evaluating expressions that it shouldn't,
such as file name shortcuts like $HOME, and backticked items like
`hostname`.  Although the resulting PDT looks cluttered, Evaluate
Parameters knows what to do and eliminates superfluous quotes
appropriately.

   Finally, you can specify a default value via an environment variable.
If a command line parameter is not specified and there is a corresponding
environment variable defined then Evaluate Parameters will use the value
of the environment variable.  Examine the command parameter for the syntax.
With this feature users can easily customize command parameters to their
liking.   Although the name of the environment variable can be whatever you
choose,  the following scheme is suggested for consistency and to avoid
conflicts in names:

   * Use all uppercase characters.

   * Begin the variable name with D_, to suggest a default variable.

   * Continue with the name of the command or its alias followed by an
     underscore.

   * Complete the variable name with the name of the parameter or its
     alias.

   So, for example, D_DISCI_DO would name a default variable for the
display_option (do) parameter of the display_command_information (disci)
command.  Works for MS-DOS and Unix.

Example
=======

     #!/usr/local/bin/perl

     use Getopt::EvaP;

     @PDT = split /\n/, <<'end-of-PDT';
     PDT sample
       verbose, v: switch
       command, c: string = D_SAMPLE_COMMAND, "ps -el"
       scale_factor, sf: real = 1.2340896e-1
       millisecond_update_interval, mui: integer = $required
       ignore_output_file_column_one, iofco: boolean = TRUE
       output, o: file = stdout
       queue, q: key plotter, postscript, text, printer, keyend = printer
       destination, d: application = `hostname`
       tty, t: list of name = ("/dev/console", "/dev/tty0", "/dev/tty1")
     PDTEND optional_file_list
     end-of-PDT

     @MM = split /\n/, <<'end-of-MM';
     sample

     A sample program demonstrating typical Evaluate Parameters
     usage.

     Examples:

     sample
     sample -usage_help
     sample -help
     sample -full_help
     sample -mui 1234
      .verbose
             A switch type parameter emulates a typical standalone
             switch. If the switch is specified Evaluate Parameters
             returns a '1'.
      .command
             A string type parameter is just a list of characters,
             which must be quoted if it contains whitespace.
             NOTE:  for this parameter you can also create and
             initialize the environment variable D_SAMPLE_COMMAND to
             override the standard default value for this command
             line parameter.  All types except switch may have a
             default environment variable for easy user customization.
      .scale_factor
             A real type parameter must be a real number that may
             contain a leading sign, a decimal point and an exponent.
      .millisecond_update_interval
             An integer type parameter must consist of all digits
             with an optional leading sign.  NOTE: this parameter's
             default value is $required, meaning that
             Evaluate Parameters ensures that this parameter is
             specified and given a valid value.  All types except
             switch may have a default value of $required.
      .ignore_output_file_column_one
             A boolean type parameter may be TRUE/YES/ON/1 or
             FALSE/NO/OFF/0, either upper or lower case.  If TRUE,
             Evaluate Parameters returns a value of '1', else '0'.
      .output
             A file type parameter expects a filename.  For Unix
             $HOME and ~ are expanded.  For EvaP/Perl stdin and
             stdout are converted to '-' and '>-' so they can be
             used in a Perl open() function.
      .queue
             A key type parameter enumerates valid values.  Only the
             specified keywords can be entered on the command line.
      .destination
             An application type parameter is not type-checked in
             any - the treatment of this type of parameter is
             application specific.  NOTE:  this parameter' default
             value is enclosed in grave accents (or "backticks").
             Evaluate Parameters executes the command and uses it's
             standard output as the default value for the parameter.
      .tty
             A name type parameter is similar to a string except
             that embedded white-space is not allowed.  NOTE: this
             parameter is also a LIST, meaning that it can be
             specified multiple times and that each value is pushed
             onto a Perl LIST variable.  In general you should quote
             all list elements.  All types except switch may be
             'list of'.
      end-of-MM

     EvaP \@PDT, \@MM;		# evaluate parameters

     print "\nProgram name:\n  $Options{'help'}\n\n";

     if (defined $Options{'verbose'}) {print "\nverbose = $Options{'verbose'}\n";}
     print "command = \"$Options{'command'}\"\n";
     print "scale_factor  = $Options{'scale_factor'}\n";
     print "millisecond_update_interval = $Options{'millisecond_update_interval'}\n";
     print "ignore_output_file_column_one = $Options{'ignore_output_file_column_one'}\n";
     print "output = $Options{'output'}\n";
     print "queue = $Options{'queue'}\n";
     print "destination = $Options{'destination'}\n";
     print "'list of' tty = \"", join('", "', @{$Options{'tty'}}), "\"\n";

     print "\nFile names:\n  ", join ' ', @ARGV, "\n" if @ARGV;

   Using the PDT as a guide, Evaluate Parameters parses a user's command
line, returning the results of the evaluation to global variables of the
form *$opt_parameter*, *@opt_parameter*, *%Options{'parameter'}* or
*%options{'parameter'}*, where parameter is the full spelling of the
command line parameter.

   Of course, you can specify where you want Evaluate Parameters to return
its results, in which case this historical feature of writing into your
namespace is disabled.

   Every command using Evaluate Parameters automatically has a *-help*
switch which displays parameter help; no special code is required in your
application.

Customization of EvaP's Help Output
-----------------------------------

   There are several Help Hook strings that can be altered to customize
*EvaP*'s help output.  Currently there is only one general area that can
be customized: usage and error text dealing with the trailing file_list.
For instance, if a command requires one or more trailing file names after
all the command line switches, the default *-help* text is:

     file(s) required by this command

   Some commands do not want trailing "file names", but rather some other
type of information.  An example is *display_command_information* where a
single Program_Name is expected.  The following code snippet shows how to
do this:

     $Getopt::EvaP::evap_Help_Hooks{'P_HHURFL'} = " Program_Name\n";
     $Getopt::EvaP::evap_Help_Hooks{'P_HHBRFL'} =
           "\nA Program_Name is required by this command.\n\n";
     $Getopt::EvaP::evap_Help_Hooks{'P_HHERFL'} =
           "A trailing Program_Name is required by this command.\n";
     EvaP \@PDT, \@MM;

   As you can see, the hash *%evap_Help_Hooks* is indexed by a simple
ordinal.  The ordinals are shown below and are mostly self-explanatory.
In case you don't have access to the source for Evaluate Parameters, here
are the default values of the Help Hook strings.

     $Getopt::EvaP:evap_Help_Hooks{'P_HHURFL'} = " file(s)\n";
     $Getopt::EvaP:evap_Help_Hooks{'P_HHUOFL'} = " [file(s)]\n";
     $Getopt::EvaP:evap_Help_Hooks{'P_HHUNFL'} = "\n";
     $Getopt::EvaP:evap_Help_Hooks{'P_HHBRFL'} =
            "\nfile(s) required by this command\n\n";
     $Getopt::EvaP:evap_Help_Hooks{'P_HHBOFL'} =
           "\n[file(s)] optionally required by this command\n\n";
     $Getopt::EvaP:evap_Help_Hooks{'P_HHBNFL'} = "\n";
     $Getopt::EvaP:evap_Help_Hooks{'P_HHERFL'} =
           "Trailing file name(s) required.\n";
     $Getopt::EvaP:evap_Help_Hooks{'P_HHENFL'} =
           "Trailing file name(s) not permitted.\n";

   The Help Hooks naming convention is rather simple:

     P_HHtf

     where:

     P_HH  implies an Evaluate Parameters Help Hook
          t     type:
             U=Usage Help
             B=Brief and Full Help
             E=error message
     f     file_list:
             RFL=required_file_list
             OFL=optional_file_list
             NFL=no_file_list

   Note to *genPerlTk* and *genTclTk* users:  using these Help Hooks may
cause the "genTk programs" to generate an unuseable Tk script.  This
happens because the "genTk programs" look for the strings "required by
this command" or "optionally required by this command" in order to
generate the file_list Entry widget - if these string are missing the
widget is not created.  An easy solution is to ensure that your Help Hook
text contains said string, just like the code snippet above; otherwise you
must manually add the required Tk code yourself.

Human Interface Guidelines
--------------------------

   To make Evaluate Parameters successful, you, the application developer,
must follow certain conventions when choosing parameter names and aliases.

   Parameter names consist of one or more words, separated by underscores,
and describe the parameter (for example, verbose and *spool_directory*).

   You can abbreviate parameters:  use the first letter of each word in the
parameter name.  Do not use underscores.  For example, you can abbreviate
command as c and *delay_period* as *dp*.

   There are exceptions to this standard:

   * password is abbreviated *pw*.

   * The words minimum and maximum are abbreviated min and max.  So, the
     abbreviation for the parameter *maximum_byte_count* is *maxbc*.

   * There are no abbreviations for the parameters *usage_help* and
     *full_help*; I do not want to prevent *uh* and fh from being used as
     valid command line parameters.

Variables MANPAGER, PAGER and D_EVAP_DO_PAGE
--------------------------------------------

   The environment variable MANPAGER (or PAGER) is used to control the
display of help information generated by Evaluate Parameters.  If defined
and non-null, the value of the environment variable is taken as the name
of the program to pipe the help output through.  If no paging program is
defined then the program more is used.

   The boolean environment variable D_EVAP_DO_PAGE can be set to
FALSE/NO/OFF/0, any case, to disable this automatic paging feature (or you
can set your paging program to cat).

Return Values
-------------

   *EvaP()* behaves differently depending upon whether it's called to
parse an application's command line, or as an embedded command line parser
(for instance, when using *evap_pac()*).

     Application      Embedded
     Command Line     Command Line
      ----------------------------------------
      error      exit(1)          return(0)
      success    return(1)        return(1)
      help       exit(0)          return(-1)

SEE ALSO
========

     evap(2)
     evap.c(2)
     EvaP.pm(2)
     evap.tcl(2)
     evap_pac(2)
     addmm, add_message_modules(1)
     disci, display_command_information(1)
     genmp, generate_man_page(1)
     genpdt, generate_pdt(1)
     genPerlTk, generate_PerlTk_program(1)
     genTclTk, generate_TclTk_program(1)

     All available from directory F<ftp://ftp.Lehigh.EDU:/pub/evap/evap-2.x/>.

BUGS
====

   The code is messy (written in Perl4-ese), and should be redone, but I
can't rationalize the time expenditure for code that still works so well.

AUTHOR
======

   Stephen.O.Lidie@Lehigh.EDU

HISTORY
=======

     lusol@Lehigh.EDU 94/10/28 (PDT version 2.0)  Version 2.2
       . Original release - derived from evap.pl version 2.1.
       . Undef option values for subsequent embedded calls.

     lusol@Lehigh.EDU 95/10/27 (PDT version 2.0)  Version 2.3.0
       . Be a strict as possible.
       . Revert to -h alias rather than -?.  (-? -?? -??? still available.)
       . Move into Getopt class.
       . Format for 80 columns (mostly).
       . Optional third argument on EvaP call can be a reference to your own
         %Options hash.  If specified, the variabes %Options, %options and
         $opt* are not used.

     lusol@Lehigh.EDU 97/01/12 (PDT version 2.0)  Version 2.3.1
       . Fix Makefile.PL so it behaves properly.  Convert nroff man data to pod
         format.

     Stephen.O.Lidie@Lehigh.EDU 98/01/14 (PDT version 2.0)  Version 2.3.2
       . Incorporate Achim Bohnet's POD patch while updating for Win32.

     Stephen.O.Lidie@Lehigh.EDU 98/07/25 (PDT version 2.0)  Version 2.3.3
       . Update Makefile.PL so it works in the standard fashion.
       . Update for perl 5.005 and Tk 800.008.
       . Remove use of ENGLISH.
       . Add genpTk to generate a Perl/TK GUI wrapper around command line
         programs.  Primarily for users of EvaP(), can be used by other codes
         as well.

     Stephen.O.Lidie@Lehigh.EDU 99/04/03 (PDT version 2.0)  Version 2.3.5
       . Update Makefile.PL for ActiveState, fix a -w message found by 5.005_03.

COPYRIGHT
=========

   Copyright (C) 1993 - 1999 Stephen O. Lidie. All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Extended Parameters command line parser.
****************************************

NAME
====

   Getopt::ExPar - Extended Parameters command line parser.

SYNOPSIS
========

     use Getopt::ExPar;

     my(@PDT, @MM, %OPT);
     ExPar \@PDT, \@MM, $OPT;

EXPORT
======

   `use Getopt::ExPar' exports the sub `ExPar' into your name space.

DESCRIPTION
===========

   *ExPar* is a *perl5* module used to parse command line parameters.
This package uses the *@PDT*, Parameter Description Table, and the *@MM*,
Message Module, to return *%OPT* which is a hash reference containing the
command line option data.  The function of *Getopt::ExPar* is based on
*Getopt::EvaP*, created by Stephen O. Lidie.

Introduction
------------

   The ExPar function parses a perl command line.  Using the option
definitions in the *@PDT*, argument types are checked and the arguments
themselves may be checked against a specified range or pattern.  By using
both *@PDT* and *@MM*, several types of help may be retured to the user.
ExPar handles command lines with this format:

     command [-parameters] [file_list]

   where any parameters and file_list are optional.

Parameter Description Table (PDT) Syntax
----------------------------------------

   Here is the PDT syntax.  Optional constructs are enclosed in [], and the
| character separates possible values in a list.

     PDT [program_name, alias]
       [parameter_name[, alias]: type [pattern | range] [ = [default_variable,] default_value]]
     PDTEND [flag_list]

   *flag_list* is one or more of the following flags:
*optional_file_list* | *required_file_list* | *no_file_list*:
specifies condition of list of files at end of command line.  (only
one of these may be specified)   abbreviations: allows for abbreviations
of commands or aliases as long as     enough of the command is given to
make it distinguishable from all others.      If not, a message is printed
so the user may be more specific.    *switchglomming*: allows for multiple
single-letter switch options     to be specified as single option (must be
first option).    *pdt_warnings*: for debugging a *@PDT*, it prints out
messages     that are not necessarily errors, like inconsistent number of
default     values in a list, etc.

   The *default_variable* is an environment variable - see the section
Usage Notes for complete details.

   So, the simplest possible PDT would be:

     PDT
     PDTEND

   This PDT would simply define a *-help* switch for the command, but is
rather useless.

   A typical PDT would look more like this:

     PDT frog
       number, n: integer = 1
       chars, c: string = "default_string"
     PDTEND no_file_list

   This PDT, for command frog, defines two parameters, number (or n), of
type integer with a default value of 1, and chars (or c), of type string
with a default value of "default_string".  The PDTEND *no_file_list*
indicator indicates that no trailing file_list can appear on the command
line.  Of course, the *-help* switch is defined automatically.

   Each of these options may be further refined by using a range and a
pattern, respectively:

     PDT frog
       number, n: integer (((#<5) and (#%2==1)), ((#<20) and (#%2==0)), >100) = 1
       chars, c: string ('default_(optional_)?string') = "default_string"
     PDTEND no_file_list

   Here, a range is given for the number parameter.  This is a list of perl
conditional statements, separated with commas.  Each element in the list is
ORed together to construct a single condition with which the parameter
value is tested.  The '#' is substituted with the actual value, '1' in
this instance.  For simple conditions like '>100', the '#' is implied.
Other simple conditions are '<' and '==' (a single '=' is accepted as
'==', not an assignment).  Ex:   This condition:     (#>10, #<-10, #==5,
#=3, -5 < # <= 2)   Can be reduced to:     (>10, <-10, 5, 3, -5<#<=2)
Notice that the compound condition, '-5<#<=2', MUST contain the '#'.

   As for the 'number' parameter above, the range (or condition) is
translated as: (Less than 5 AND odd) OR (Less than 20 AND even) OR
(Greater than 100) So, '1' fits this condition.  These conditions may be
as complex as you wish.  ENV variables may also be referenced within these
range specifications.

   The pattern is a perl regular expression with which the value, in this
case "default_string", is tested.

Usage Notes
-----------

   Currently, both *@PDT* and *@MM* are required, as is a reference to a
hash into which all parameter values are placed.  A call to ExPar *must*
have this form:

     ExPar(\@PDT, \@MM, \%OPT);

   An optional PDT flag can be included that tells ExPar whether or not
trailing file names can appear on the command line after all the
parameters.  It can read *no_file_list*, *optional_file_list* or
*required_file_list* and, if not specified, defaults to optional.  Any
flags *must* be on the PDTEND line, which is the last line of the *@PDT*
array.  Other flags include *switchglomming* and *pdt_warnings*.

   The *switchglomming* flag allows multiple single-letter switch
parameters to be specified as a single parameter.  Either the option name
or its alias must be a single letter to be used in the switch glom.  Ex:
script.pl -x -f -c -a arga   -->    script.pl -xfc -a arga The switch glo
*must* be the first option on the command line.  Note: this can be changed
if heavily requested.

   Additionally a Message Module is declared that describes the command
and provides examples.  Following the main help text an optional series of
help text messages can be specified for individual command line
parameters.  In the following sample program all the parameters have this
additional text which describes that type of parameter.  The leadin
character is a dot in column one followed by the full spelling of the
command line parameter.  Use *-full_help* rather than *-help* to see this
supplemental information.  This sample program illustrates the various
types and how to use *ExPar()*.  The key type is a special type that
enumerates valid values for the command line parameter.  The boolean type
may be specified as TRUE/FALSE, YES/NO, ON/OFF or 1/0.  Parameters of type
file have ~ and $HOME expanded, and default values stdin and stdout
converted to '-' and '>-', respectively.  Of special note is the default
value *$required*: when specified, ExPar will ensure a value is specified
for that command line parameter.

   All types except switch may be *list of*, like the *real70* parameter
below.  A list parameter can be specified multiple times on the command
line.  NOTE: in general you should ALWAYS quote components of your lists,
even if they are not type string, since Evaluate Parameters uses eval to
parse them.  Doing this prevents eval from evaluating expressions that it
should not, such as file name shortcuts like $HOME, and backticked items
like `hostname`.  Although the resulting PDT looks cluttered, Evaluate
Parameters knows what to do and eliminates superfluous quotes
appropriately.

   Finally, you can specify a default value via an environment variable.
If a command line parameter is not specified and there is a corresponding
environment variable defined then Evaluate Parameters will use the value
of the environment variable.  Examine the command parameter for the syntax.
With this feature users can easily customize command parameters to their
liking.   Although the name of the environment variable can be whatever you
choose,  the following scheme is suggested for consistency and to avoid
conflicts in names:

EXAMPLE
=======

   @PDT = split /\n/, <<'end-of-PDT'; PDT expar_test   switch01, sw01 :
switch   integer13, int13 : integer (5 < # <=  9) = 7   real70 : list of
real = ENV:D_real70, (45, 54)   boolean07, bo07 : list of boolean = (1,
"true")   string17 : list of string ('s(?:tring)?17') = ENV:D_string17,
('string17a', 'string17b')   string20        : list of string
("s(?:tring)?20") = \     ENV:D_string20, (ENV:D_string20a, 'string20b')
string21, str21 : string ("^\\\d{2,3}\\\w\\\d{2,8}\$") = "333x29445"
name21, nm21 : name ('^\d{2,3}\w\d{2,8}') = $required   file05, fl05 :
file = "~"   file06       : file = "$HOME/bin"   file07, fl07 : file =
'~other/bin'   application08 : application = ENV:D_application08, `date`
key13     : list of key ENV:D_keys13, keyend = ENV:D_key13, \
("printer", ENV:D_key13b, ENV:D_keys13c)   set01, st01 : set of     :
integer (5 <= # <= 9)     : real (5.0 <= # <= 9.0)     : string ('pat01')
  : key ak, bk, ck, dk, keyend   end set   set02, st02 : list of set
: integer (5 <= # <= 9) = (5, 7)     : real (5.0 <= # <= 9.0) = (8.3,
5.0001)     : string ('blah') = ("blah", "bbbbblahhhhh")     : key ak, bk,
ck, dk, keyend = ("ak", "dk")   end set PDTEND end-of-PDT

   @MM = split /\n/, <<'end-of-MM'; expar_test.pl

     This script simply tests the ExPar option parsing package.

     Examples:

     expar_test.pl
     expar_test.pl -usage_help
     expar_test.pl -help
     expar_test.pl -full_help
     expar_test.pl -partial_help

     .switch01
        A switch type parameter is either off or on, returning a 0 or 1
        in the B<%OPT>: $OPT{'switch01'}.

     .integer13
        An integer type with a specified range and a default value.  Integers
        are checked against the pattern '[-+]?\d+', and, in this case, would
        check to make sure that any command line value is greater than 5 and
        less than or equal to 9.

     .real70
        An option of type real, checked against the following pattern:
        '[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?'.  The default
        values are 45 and 54.  There are two default values because this
        is a 'list of' type, which means that there may be multiple -real70
        options in the command line.  The value in B<%OPT> is an array
        reference: $OPT{'real70'} = [45, 54].
        Or, $OPT{'real70'}->[0] = 45, and
            $OPT{'real70'}->[1] = 54.

     .boolean07
        A boolean type, also a list, can have be given one of the following
        values: TRUE, FALSE, ON, OFF, 1, 0, YES, NO (case insensitive).
        Returns either a 1 or 0.

     .string17
        A string type, also a list, with a pattern with which to check any
        value specified in the command line.  Any default values are also
        checked against the specified pattern.  In this case, D_string17 is
        the default list, unless it does not exist, then the ending list
        is assigned as the default.  A string type is simply a string of
        characters surrounded by quotes, either single or double quotes.

     .string20
        Another list of string type, showing an ENV variable, D_string20a, in
        the default assignments.  Also, a \ character, backslash, can be placed
        at the end of a line in the B<@PDT> so that multiple lines may be used.

     .string21
        Still another string with a pattern surrounded by double-quotes.  Notice
        the use of multiple backslashes.  Always be careful when pattern matching
        on strings defined with single or double quotes.

     .name21
        The type name is treated identically to the type string.  It is included
        for backward compatibility with Getop::EvaP.

     .file05
        The type file is also the same as string type; however, $HOME and "~" are
        expanded to $ENV{'HOME'}.  Here the single '~' character is expanded.
        Patterns are also allowed in file declaraions.

     .file06
        Here, $HOME is expanded to $ENV{'HOME'}.

     .file07
        In this case, the '~' is followed by a non-slash character.  In UNIX, this
        generally refers to the home directory of another user, and the '~' is
        I<not> expanded.

     .application08
        Treated as strings, but if surrounded by backtick characters, '`', it is
        assumed to be an application and the returned value of this application
        is stored.  In this case, if the ENV variable D_application08 is not
        defined, the default value of $OPT{'application08'} is set to what is
        returned from the 'date' command: 'Mon Nov  9 15:23:47 CST 1998'.

     .key13
        The type key is an enumerated type allowing the programmer to explicitly
        defined the possible values.  Although the key type is functionally
        equivalent to a string with a speicified pattern, it is left in for
        backward compatibility.  In this case, it is a list of keys whose
        key values are defined by the ENV variable D_keys13.

     .set01
        A new 'supertype'.  This allows for having multiple parameters for
        a single option.  From B<%OPT>, a set is an array of arrays, where each
        sub-array holds the value(s) of a sub-type.
        Ex:  script.pl -set01 6 6.5 'pppat011' ck
        $OPT{'set01'} = [ [ 6 ], [ 6.5 ], [ 'pppat011' ], [ 'ck' ] ];

     .set02
        A list of set.  Assuming to -set02 options specified on the command line:
        $OPT{'set01'} = [ [ 5, 7 ], [8.3, 5.0001], ["blah", "bbbbblahhhhh"], ["ak", "dk"] ];

   end-of-MM

     ExPar \@PDT, \@MM, \%OPT; # evaluate parameters

HELP
====

   There are several levels of help created from the *@PDT* and *@MM*.  It
is possible that the programmer may want to use one or more of these key
options in his *@PDT*.  If this is the case, the built in functions can be
accessed by using two '-' characters instead of one.  Built in help
functions include:

   -help (-h) -full_help (-fh) -usage_help (-uh) -partial_help (-ph)

   Currently, with the 0.01 alpha version, there is not much variety in
the help options.  This author wanted to have a rudimentary help
available, while getting the package to end users for evaluation.  Using
any one of these built in help options outputs the *@PDT* and *@MM* in a
text format.

Help
----

   In development...

Full Help
---------

   In development...

Usage Help
----------

   In development...

Partial Help
------------

PLANNED FEATURES
================

   Here are a few ideas for future enhancements.  Currently, there is no
support for platforms other than UNIX and no support for languages other
than Perl.  (What else could there be...:)

Partial Help Request
--------------------

   A user may only want help with a specific option or subset of options.
Using *-partial_help*, the user can view the help for only those options
he/she wishes.  This would be a subset of the *-full_help*.

Required, A Better Specification
--------------------------------

   Whereas currently, to define an option to be required by the user, '=
$required' is placed at the end of a line in the PDT.  However, this
method is limited.  A method of implementing a more explicit and elaborate
definition of *$required* will be defined.  This is the current thought:

   In the PDT, a *$required* line may be placed in this manner:
$required : ((opta and optb) or (opta and not optb and optc) or \
     (optc and optd and not optz))

   This line is simply a Perl condition statement containing the names (or
aliases) of options defined in the PDT.  Multiple *$required* lines may be
ANDed together.

Command Parameter Completion
----------------------------

   Some shells in UNIX allow for command completion where the first few
letters of a command is typed in and a completion-key, ESC or TAB, is
pressed and the shell determines if enough letters have been typed to
distinguish from any other command.  Some shells allow a refinement of
this by completing command parameters.  In *tcsh*, this is done with the
complete command.  For programs with a complex option set, the complete
command can become near unmanagable.  This author proposes that by using
the *@PDT*, a complete command may be defined and returned to the user.

   Perhaps by calling the perl script with a -complete (-complete) option
only, a complete definition would be printed to STDOUT.

POSSIBLE FEATURES
=================

Multiple Aliases
----------------

   Although this would be fairly easy to do, it may not be necessary.
User feedback is welcome.  Entries in *@PDT* would resemble this:
integer01, int01, i01, i1 : integer

User Requests
-------------

   I will entertain any [sane] ideas that users may have...:)

NOTES
=====

   Currently, the help system is minimal, but I wanted to get this
released to see who might use it.

   This is currently *alpha* software.  There are no doubt bugs and
shortcomings.  Please email me at *hlhamilt@aud.alcatel.com* with
questions, comments, feature requests and bug reports.

VERSION HISTORY
===============

0.01
----

   First *alpha* release.  Help funcions are minimal.  Might be buggy...:)

AUTHOR
======

   Harlin L. Hamilton Jr.

Contact Info
------------

   *mailto:hlhamilt@aud.alcatel.com*

Copyright
---------

   Copyright (C) 1998 Harlin L. Hamilton Jr..  All rights reserved.  This
package is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Extended processing of command line options
*******************************************

NAME
====

   Getopt::Long - Extended processing of command line options

SYNOPSIS
========

     use Getopt::Long;
     $result = GetOptions (...option-descriptions...);

DESCRIPTION
===========

   The Getopt::Long module implements an extended getopt function called
GetOptions(). This function adheres to the POSIX syntax for command line
options, with GNU extensions. In general, this means that options have
long names instead of single letters, and are introduced with a double
dash "-". Support for bundling of command line options, as was the case
with the more traditional single-letter approach, is provided but not
enabled by default.

Command Line Options, an Introduction
=====================================

   Command line operated programs traditionally take their arguments from
the command line, for example filenames or other information that the
program needs to know. Besides arguments, these programs often take
command line options as well. Options are not necessary for the program to
work, hence the name 'option', but are used to modify its default
behaviour. For example, a program could do its job quietly, but with a
suitable option it could provide verbose information about what it did.

   Command line options come in several flavours. Historically, they are
preceded by a single dash -, and consist of a single letter.

     -l -a -c

   Usually, these single-character options can be bundled:

     -lac

   Options can have values, the value is placed after the option
character. Sometimes with whitespace in between, sometimes not:

     -s 24 -s24

   Due to the very cryptic nature of these options, another style was
developed that used long names. So instead of a cryptic -l one could use
the more descriptive `--long'. To distinguish between a bundle of
single-character options and a long one, two dashes are used to precede
the option name. Early implementations of long options used a plus +
instead. Also, option values could be specified either like

     --size=24

   or

     --size 24

   The + form is now obsolete and strongly deprecated.

Getting Started with Getopt::Long
=================================

   Getopt::Long is the Perl5 successor of `newgetopt.pl'. This was the
first Perl module that provided support for handling the new style of
command line options, hence the name Getopt::Long. This module also
supports single-character options and bundling. In this case, the options
are restricted to alphabetic characters only, and the characters ? and -.

   To use Getopt::Long from a Perl program, you must include the following
line in your Perl program:

     use Getopt::Long;

   This will load the core of the Getopt::Long module and prepare your
program for using it. Most of the actual Getopt::Long code is not loaded
until you really call one of its functions.

   In the default configuration, options names may be abbreviated to
uniqueness, case does not matter, and a single dash is sufficient, even
for long option names. Also, options may be placed between non-option
arguments. See `Configuring Getopt::Long' in this node for more details on
how to configure Getopt::Long.

Simple options
--------------

   The most simple options are the ones that take no values. Their mere
presence on the command line enables the option. Popular examples are:

     --all --verbose --quiet --debug

   Handling simple options is straightforward:

     my $verbose = '';	# option variable with default value (false)
     my $all = '';	# option variable with default value (false)
     GetOptions ('verbose' => \$verbose, 'all' => \$all);

   The call to GetOptions() parses the command line arguments that are
present in `@ARGV' and sets the option variable to the value 1 if the
option did occur on the command line. Otherwise, the option variable is
not touched. Setting the option value to true is often called *enabling*
the option.

   The option name as specified to the GetOptions() function is called the
option *specification*. Later we'll see that this specification can
contain more than just the option name. The reference to the variable is
called the option *destination*.

   GetOptions() will return a true value if the command line could be
processed successfully. Otherwise, it will write error messages to STDERR,
and return a false result.

A little bit less simple options
--------------------------------

   Getopt::Long supports two useful variants of simple options:
*negatable* options and incremental options.

   A negatable option is specified with a exclamation mark ! after the
option name:

     my $verbose = '';	# option variable with default value (false)
     GetOptions ('verbose!' => \$verbose);

   Now, using `--verbose' on the command line will enable `$verbose', as
expected. But it is also allowed to use `--noverbose', which will disable
`$verbose' by setting its value to 0. Using a suitable default value, the
program can find out whether `$verbose' is false by default, or disabled
by using `--noverbose'.

   An incremental option is specified with a plus + after the option name:

     my $verbose = '';	# option variable with default value (false)
     GetOptions ('verbose+' => \$verbose);

   Using `--verbose' on the command line will increment the value of
`$verbose'. This way the program can keep track of how many times the
option occurred on the command line. For example, each occurrence of
`--verbose' could increase the verbosity level of the program.

Mixing command line option with other arguments
-----------------------------------------------

   Usually programs take command line options as well as other arguments,
for example, file names. It is good practice to always specify the options
first, and the other arguments last. Getopt::Long will, however, allow the
options and arguments to be mixed and 'filter out' all the options before
passing the rest of the arguments to the program. To stop Getopt::Long
from processing further arguments, insert a double dash - on the command
line:

     --size 24 -- --all

   In this example, `--all' will not be treated as an option, but passed
to the program unharmed, in `@ARGV'.

Options with values
-------------------

   For options that take values it must be specified whether the option
value is required or not, and what kind of value the option expects.

   Three kinds of values are supported: integer numbers, floating point
numbers, and strings.

   If the option value is required, Getopt::Long will take the command
line argument that follows the option and assign this to the option
variable. If, however, the option value is specified as optional, this
will only be done if that value does not look like a valid command line
option itself.

     my $tag = '';	# option variable with default value
     GetOptions ('tag=s' => \$tag);

   In the option specification, the option name is followed by an equals
sign = and the letter s. The equals sign indicates that this option
requires a value. The letter s indicates that this value is an arbitrary
string. Other possible value types are i for integer values, and f for
floating point values. Using a colon : instead of the equals sign
indicates that the option value is optional. In this case, if no suitable
value is supplied, string valued options get an empty string " assigned,
while numeric options are set to 0.

Options with multiple values
----------------------------

   Options sometimes take several values. For example, a program could use
multiple directories to search for library files:

     --library lib/stdlib --library lib/extlib

   To accomplish this behaviour, simply specify an array reference as the
destination for the option:

     my @libfiles = ();
     GetOptions ("library=s" => \@libfiles);

   Used with the example above, `@libfiles' would contain two strings upon
completion: `"lib/srdlib"' and `"lib/extlib"', in that order.  It is also
possible to specify that only integer or floating point numbers are
acceptible values.

   Often it is useful to allow comma-separated lists of values as well as
multiple occurrences of the options. This is easy using Perl's split() and
join() operators:

     my @libfiles = ();
     GetOptions ("library=s" => \@libfiles);
     @libfiles = split(/,/,join(',',@libfiles));

   Of course, it is important to choose the right separator string for
each purpose.

Options with hash values
------------------------

   If the option destination is a reference to a hash, the option will
take, as value, strings of the form key=value. The value will be stored
with the specified key in the hash.

     my %defines = ();
     GetOptions ("define=s" => \%defines);

   When used with command line options:

     --define os=linux --define vendor=redhat

   the hash `%defines' will contain two keys, `"os"' with value `"linux'
and `"vendor"' with value `"redhat"'.  It is also possible to specify that
only integer or floating point numbers are acceptible values. The keys are
always taken to be strings.

User-defined subroutines to handle options
------------------------------------------

   Ultimate control over what should be done when (actually: each time) an
option is encountered on the command line can be achieved by designating a
reference to a subroutine (or an anonymous subroutine) as the option
destination. When GetOptions() encounters the option, it will call the
subroutine with two arguments: the name of the option, and the value to be
assigned. It is up to the subroutine to store the value, or do whatever it
thinks is appropriate.

   A trivial application of this mechanism is to implement options that
are related to each other. For example:

     my $verbose = '';	# option variable with default value (false)
     GetOptions ('verbose' => \$verbose,
     	        'quiet'   => sub { $verbose = 0 });

   Here `--verbose' and `--quiet' control the same variable `$verbose',
but with opposite values.

   If the subroutine needs to signal an error, it should call die() with
the desired error message as its argument. GetOptions() will catch the
die(), issue the error message, and record that an error result must be
returned upon completion.

   If the text of the error message starts with an exclamantion mark !  it
is interpreted specially by GetOptions(). There is currently one special
command implemented: `die("!FINISH")' will cause GetOptions() to stop
processing options, as if it encountered a double dash -.

Options with multiple names
---------------------------

   Often it is user friendly to supply alternate mnemonic names for
options. For example `--height' could be an alternate name for `--length'.
Alternate names can be included in the option specification, separated by
vertical bar | characters. To implement the above example:

     GetOptions ('length|height=f' => \$length);

   The first name is called the *primary* name, the other names are called
aliases.

   Multiple alternate names are possible.

Case and abbreviations
----------------------

   Without additional configuration, GetOptions() will ignore the case of
option names, and allow the options to be abbreviated to uniqueness.

     GetOptions ('length|height=f' => \$length, "head" => \$head);

   This call will allow `--l' and `--L' for the length option, but
requires a least `--hea' and `--hei' for the head and height options.

Summary of Option Specifications
--------------------------------

   Each option specifier consists of two parts: the name specification and
the argument specification.

   The name specification contains the name of the option, optionally
followed by a list of alternative names separated by vertical bar
characters.

     length	      option name is "length"
     length|size|l     name is "length", aliases are "size" and "l"

   The argument specification is optional. If omitted, the option is
considered boolean, a value of 1 will be assigned when the option is used
on the command line.

   The argument specification can be

!
     The option does not take an argument and may be negated, i.e. prefixed
     by "no". E.g. `"foo!"' will allow `--foo' (a value of 1 will be
     assigned) and `--nofoo' (a value of 0 will be assigned). If the
     option has aliases, this applies to the aliases as well.

     Using negation on a single letter option when bundling is in effect is
     pointless and will result in a warning.

+
     The option does not take an argument and will be incremented by 1
     every time it appears on the command line. E.g. `"more+"', when used
     with `--more --more --more', will increment the value three times,
     resulting in a value of 3 (provided it was 0 or undefined at first).

     The + specifier is ignored if the option destination is not a scalar.

= type [ *desttype* ]
     The option requires an argument of the given type. Supported types
     are:

    s
          String. An arbitrary sequence of characters. It is valid for the
          argument to start with - or -.

    i
          Integer. An optional leading plus or minus sign, followed by a
          sequence of digits.

    f
          Real number. For example `3.14', `-6.23E24' and so on.

     The *desttype* can be `@' or % to specify that the option is list or
     a hash valued. This is only needed when the destination for the
     option value is not otherwise specified. It should be omitted when
     not needed.

: type [ *desttype* ]
     Like =, but designates the argument as optional.  If omitted, an
     empty string will be assigned to string values options, and the value
     zero to numeric options.

     Note that if a string argument starts with - or -, it will be
     considered an option on itself.

Advanced Possibilities
======================

Object oriented interface
-------------------------

   Getopt::Long can be used in an object oriented way as well:

     use Getopt::Long;
     $p = new Getopt::Long::Parser;
     $p->configure(...configuration options...);
     if ($p->getoptions(...options descriptions...)) ...

   Configuration options can be passed to the constructor:

     $p = new Getopt::Long::Parser
              config => [...configuration options...];

   For thread safety, each method call will acquire an exclusive lock to
the Getopt::Long module. So don't call these methods from a callback
routine!

Documentation and help texts
----------------------------

   Getopt::Long encourages the use of Pod::Usage to produce help messages.
For example:

     use Getopt::Long;
     use Pod::Usage;

     my $man = 0;
     my $help = 0;

     GetOptions('help|?' => \$help, man => \$man) or pod2usage(2);
     pod2usage(1) if $help;
     pod2usage(-exitstatus => 0, -verbose => 2) if $man;

     __END__

     =head1 NAME

     sample - Using GetOpt::Long and Pod::Usage

     =head1 SYNOPSIS

     sample [options] [file ...]

     Options:
       -help            brief help message
       -man             full documentation

     =head1 OPTIONS

     =over 8

     =item B<-help>

     Print a brief help message and exits.

     =item B<-man>

     Prints the manual page and exits.

     =back

     =head1 DESCRIPTION

     B<This program> will read the given input file(s) and do someting
     useful with the contents thereof.

     =cut

   See Pod/Usage, for details.

Storing options in a hash
-------------------------

   Sometimes, for example when there are a lot of options, having a
separate variable for each of them can be cumbersome. GetOptions()
supports, as an alternative mechanism, storing options in a hash.

   To obtain this, a reference to a hash must be passed *as the first
argument* to GetOptions(). For each option that is specified on the
command line, the option value will be stored in the hash with the option
name as key. Options that are not actually used on the command line will
not be put in the hash, on other words, `exists($h{option})' (or
defined()) can be used to test if an option was used. The drawback is that
warnings will be issued if the program runs under `use strict' and uses
`$h{option}' without testing with exists() or defined() first.

     my %h = ();
     GetOptions (\%h, 'length=i');	# will store in $h{length}

   For options that take list or hash values, it is necessary to indicate
this by appending an `@' or % sign after the type:

     GetOptions (\%h, 'colours=s@');	# will push to @{$h{colours}}

   To make things more complicated, the hash may contain references to the
actual destinations, for example:

     my $len = 0;
     my %h = ('length' => \$len);
     GetOptions (\%h, 'length=i');	# will store in $len

   This example is fully equivalent with:

     my $len = 0;
     GetOptions ('length=i' => \$len);	# will store in $len

   Any mixture is possible. For example, the most frequently used options
could be stored in variables while all other options get stored in the
hash:

     my $verbose = 0;			# frequently referred
     my $debug = 0;			# frequently referred
     my %h = ('verbose' => \$verbose, 'debug' => \$debug);
     GetOptions (\%h, 'verbose', 'debug', 'filter', 'size=i');
     if ( $verbose ) { ... }
     if ( exists $h{filter} ) { ... option 'filter' was specified ... }

Bundling
--------

   With bundling it is possible to set several single-character options at
once. For example if a, v and x are all valid options,

     -vax

   would set all three.

   Getopt::Long supports two levels of bundling. To enable bundling, a
call to Getopt::Long::Configure is required.

   The first level of bundling can be enabled with:

     Getopt::Long::Configure ("bundling");

   Configured this way, single-character options can be bundled but long
options must always start with a double dash - to avoid abiguity. For
example, when `vax', a, v and x are all valid options,

     -vax

   would set a, v and x, but

     --vax

   would set `vax'.

   The second level of bundling lifts this restriction. It can be enabled
with:

     Getopt::Long::Configure ("bundling_override");

   Now, `-vax' would set the option `vax'.

   When any level of bundling is enabled, option values may be inserted in
the bundle. For example:

     -h24w80

   is equivalent to

     -h 24 -w 80

   When configured for bundling, single-character options are matched case
sensitive while long options are matched case insensitive. To have the
single-character options matched case insensitive as well, use:

     Getopt::Long::Configure ("bundling", "ignorecase_always");

   It goes without saying that bundling can be quite confusing.

The lonesome dash
-----------------

   Normally, a lone dash - on the command line will not be considered an
option. Option processing will terminate (unless "permute" is configured)
and the dash will be left in `@ARGV'.

   It is possible to get special treatment for a lone dash. This can be
achieved by adding an option specification with an empty name, for example:

     GetOptions ('' => \$stdio);

   A lone dash on the command line will now be a legal option, and using
it will set variable `$stdio'.

Argument call-back
------------------

   A special option 'name' <> can be used to designate a subroutine to
handle non-option arguments. When GetOptions() encounters an argument that
does not look like an option, it will immediately call this subroutine and
passes it the argument as a parameter.

   For example:

     my $width = 80;
     sub process { ... }
     GetOptions ('width=i' => \$width, '<>' => \&process);

   When applied to the following command line:

     arg1 --width=72 arg2 --width=60 arg3

   This will call `process("arg1")' while $width is 80, `process("arg2")'
while $width is 72, and `process("arg3")' while $width is 60.

   This feature requires configuration option permute, see section
`Configuring Getopt::Long' in this node.

Configuring Getopt::Long
========================

   Getopt::Long can be configured by calling subroutine
Getopt::Long::Configure(). This subroutine takes a list of quoted strings,
each specifying a configuration option to be enabled, e.g.  ignore_case,
or disabled, e.g. `no_ignore_case'. Case does not matter. Multiple calls
to Configure() are possible.

   Alternatively, as of version 2.24, the configuration options may be
passed together with the use statement:

     use Getopt::Long qw(:config no_ignore_case bundling);

   The following options are available:

default
     This option causes all configuration options to be reset to their
     default values.

posix_default
     This option causes all configuration options to be reset to their
     default values as if the environment variable POSIXLY_CORRECT had
     been set.

auto_abbrev
     Allow option names to be abbreviated to uniqueness.  Default is
     enabled unless environment variable POSIXLY_CORRECT has been set, in
     which case auto_abbrev is disabled.

getopt_compat
     Allow + to start options.  Default is enabled unless environment
     variable POSIXLY_CORRECT has been set, in which case getopt_compat is
     disabled.

gnu_compat
     gnu_compat controls whether `--opt=' is allowed, and what it should
     do. Without gnu_compat, `--opt=' gives an error. With gnu_compat,
     `--opt=' will give option opt and empty value.  This is the way GNU
     getopt_long() does it.

gnu_getopt
     This is a short way of setting gnu_compat bundling permute
     `no_getopt_compat'. With gnu_getopt, command line handling should be
     fully compatible with GNU getopt_long().

require_order
     Whether command line arguments are allowed to be mixed with options.
     Default is disabled unless environment variable POSIXLY_CORRECT has
     been set, in which case require_order is enabled.

     See also permute, which is the opposite of require_order.

permute
     Whether command line arguments are allowed to be mixed with options.
     Default is enabled unless environment variable POSIXLY_CORRECT has
     been set, in which case permute is disabled.  Note that permute is
     the opposite of require_order.

     If permute is enabled, this means that

          --foo arg1 --bar arg2 arg3

     is equivalent to

          --foo --bar arg1 arg2 arg3

     If an argument call-back routine is specified, `@ARGV' will always be
     empty upon succesful return of GetOptions() since all options have
     been processed. The only exception is when - is used:

          --foo arg1 --bar arg2 -- arg3

     will call the call-back routine for arg1 and arg2, and terminate
     GetOptions() leaving `"arg2"' in `@ARGV'.

     If require_order is enabled, options processing terminates when the
     first non-option is encountered.

          --foo arg1 --bar arg2 arg3

     is equivalent to

          --foo -- arg1 --bar arg2 arg3

     If pass_through is also enabled, options processing will terminate at
     the first unrecognized option, or non-option, whichever comes first.

bundling (default: disabled)
     Enabling this option will allow single-character options to be
     bundled.  To distinguish bundles from long option names, long options
     must be introduced with - and single-character options (and bundles)
     with -.

     Note: disabling bundling also disables bundling_override.

bundling_override (default: disabled)
     If bundling_override is enabled, bundling is enabled as with bundling
     but now long option names override option bundles.

     Note: disabling bundling_override also disables bundling.

     Note: Using option bundling can easily lead to unexpected results,
     especially when mixing long options and bundles. Caveat emptor.

ignore_case  (default: enabled)
     If enabled, case is ignored when matching long option names. Single
     character options will be treated case-sensitive.

     Note: disabling ignore_case also disables ignore_case_always.

ignore_case_always (default: disabled)
     When bundling is in effect, case is ignored on single-character
     options also.

     Note: disabling ignore_case_always also disables ignore_case.

pass_through (default: disabled)
     Options that are unknown, ambiguous or supplied with an invalid option
     value are passed through in `@ARGV' instead of being flagged as
     errors. This makes it possible to write wrapper scripts that process
     only part of the user supplied command line arguments, and pass the
     remaining options to some other program.

     If require_order is enabled, options processing will terminate at the
     first unrecognized option, or non-option, whichever comes first.
     However, if permute is enabled instead, results can become confusing.

prefix
     The string that starts options. If a constant string is not
     sufficient, see prefix_pattern.

prefix_pattern
     A Perl pattern that identifies the strings that introduce options.
     Default is `(--|-|\+)' unless environment variable POSIXLY_CORRECT
     has been set, in which case it is `(--|-)'.

debug (default: disabled)
     Enable debugging output.

Return values and Errors
========================

   Configuration errors and errors in the option definitions are signalled
using die() and will terminate the calling program unless the call to
Getopt::Long::GetOptions() was embedded in `eval { ...  }', or die() was
trapped using `$SIG{__DIE__}'.

   GetOptions returns true to indicate success.  It returns false when the
function detected one or more errors during option parsing. These errors
are signalled using warn() and can be trapped with `$SIG{__WARN__}'.

   Errors that can't happen are signalled using Carp::croak().

Legacy
======

   The earliest development of `newgetopt.pl' started in 1990, with Perl
version 4. As a result, its development, and the development of
Getopt::Long, has gone through several stages. Since backward
compatibility has always been extremely important, the current version of
Getopt::Long still supports a lot of constructs that nowadays are no
longer necessary or otherwise unwanted. This section describes briefly
some of these 'features'.

Default destinations
--------------------

   When no destination is specified for an option, GetOptions will store
the resultant value in a global variable named `opt_'XXX, where XXX is the
primary name of this option. When a progam executes under `use strict'
(recommended), these variables must be pre-declared with our() or `use
vars'.

     our $opt_length = 0;
     GetOptions ('length=i');	# will store in $opt_length

   To yield a usable Perl variable, characters that are not part of the
syntax for variables are translated to underscores. For example,
`--fpp-struct-return' will set the variable `$opt_fpp_struct_return'. Note
that this variable resides in the namespace of the calling program, not
necessarily main. For example:

     GetOptions ("size=i", "sizes=i@");

   with command line "-size 10 -sizes 24 -sizes 48" will perform the
equivalent of the assignments

     $opt_size = 10;
     @opt_sizes = (24, 48);

Alternative option starters
---------------------------

   A string of alternative option starter characters may be passed as the
first argument (or the first argument after a leading hash reference
argument).

     my $len = 0;
     GetOptions ('/', 'length=i' => $len);

   Now the command line may look like:

     /length 24 -- arg

   Note that to terminate options processing still requires a double dash
-.

   GetOptions() will not interpret a leading `< "<'" >> as option starters
if the next argument is a reference. To force `< "<" '> and `< "'" >> as
option starters, use `< "'<" >>. Confusing? Well, *using a starter
argument is strongly deprecated* anyway.

Configuration variables
-----------------------

   Previous versions of Getopt::Long used variables for the purpose of
configuring. Although manipulating these variables still work, it is
strongly encouraged to use the Configure routine that was introduced in
version 2.17. Besides, it is much easier.

Trouble Shooting
================

Warning: Ignoring '!' modifier for short option
-----------------------------------------------

   This warning is issued when the '!' modifier is applied to a short
(one-character) option and bundling is in effect. E.g.,

     Getopt::Long::Configure("bundling");
     GetOptions("foo|f!" => \$foo);

   Note that older Getopt::Long versions did not issue a warning, because
the '!' modifier was applied to the first name only. This bug was fixed in
2.22.

   Solution: separate the long and short names and apply the '!' to the
long names only, e.g.,

     GetOptions("foo!" => \$foo, "f" => \$foo);

GetOptions does not return a false result when an option is not supplied
------------------------------------------------------------------------

   That's why they're called 'options'.

AUTHOR
======

   Johan Vromans <jvromans@squirrel.nl>

COPYRIGHT AND DISCLAIMER
========================

   This program is Copyright 2000,1990 by Johan Vromans.  This program is
free software; you can redistribute it and/or modify it under the terms of
the Perl Artistic License or 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.

   If you do not have a copy of the GNU General Public License write to
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

getopt processing with both long and short options
**************************************************

NAME
====

   Getopt::Mixed - getopt processing with both long and short options

SYNOPSIS
========

     use Getopt::Mixed;
     Getopt::Mixed::getOptions(...option-descriptions...);
     ...examine $opt_* variables...

   or

     use Getopt::Mixed "nextOption";
     Getopt::Mixed::init(...option-descriptions...);
     while (($option, $value) = nextOption()) {
         ...process option...
     }
     Getopt::Mixed::cleanup();

DESCRIPTION
===========

   This package is my response to the standard modules Getopt::Std and
Getopt::Long.  `Std' doesn't support long options, and Long doesn't
support short options.  I wanted both, since long options are easier to
remember and short options are faster to type.

   This package is intended to be the "Getopt-to-end-all-Getop's".  It
combines (I hope) flexibility and simplicity.  It supports both short
options (introduced by -) and long options (introduced by -).  Short
options which do not take an argument can be grouped together.  Short
options which do take an argument must be the last option in their group,
because everything following the option will be considered to be its
argument.

   There are two methods for using Getopt::Mixed:  the simple method and
the flexible method.  Both methods use the same format for option
descriptions.

Option Descriptions
-------------------

   The option-description arguments required by init and getOptions are
strings composed of individual option descriptions.  Several option
descriptions can appear in the same string if they are separated by
whitespace.

   Each description consists of the option name and an optional trailing
argument specifier.  Option names may consist of any characters but
whitespace, =, :, and `>'.

   Values for argument specifiers are:

     <none>   option does not take an argument
     =s :s    option takes a mandatory (=) or optional (:) string argument
     =i :i    option takes a mandatory (=) or optional (:) integer argument
     =f :f    option takes a mandatory (=) or optional (:) real number argument
     >new     option is a synonym for option `new'

   The `>' specifier is not really an argument specifier.  It defines an
option as being a synonym for another option.  For example, "a=i apples>a"
would define -a as an option that requires an integer argument and
*-apples* as a synonym for -a.  Only one level of synonyms is supported,
and the root option must be listed first.  For example, "apples>a a=i" and
"a=i apples>a oranges>apples" are illegal; use "a=i apples>a oranges>a" if
that's what you want.

   For example, in the option description:      "a b=i c:s apple baker>b
charlie:s"          -a and -apple do not take arguments          -b takes
a mandatory integer argument          -baker is a synonym for -b
-c and -charlie take an optional string argument

   If the first argument to init or getOptions is entirely
non-alphanumeric characters with no whitespace, it represents the
characters which can begin options.

User Interface
--------------

   From the user's perspective, short options are introduced by a dash (-)
and long options are introduced by a double dash (-).  Short options may
be combined ("-a -b" can be written "-ab"), but an option that takes an
argument must be the last one in its group, because anything following it
is considered part of the argument.  A double dash by itself marks the end
of the options; all arguments following it are treated as normal
arguments, not options.  A single dash by itself is treated as a normal
argument, not an option.

   Long options may be abbreviated.  An option *-all-the-time* could be
abbreviated *-all*, *-a-tim*, or even *-a*.  Note that *-time* would not
work; the abbreviation must start at the beginning of the option name.  If
an abbreviation is ambiguous, an error message will be printed.

   In the following examples, -i and *-int* take integer arguments, -f and
*-float* take floating point arguments, and -s and *-string* take string
arguments.  All other options do not take an argument.

     -i24            -f24.5               -sHello
     -i=24 --int=-27 -f=24.5 --float=0.27 -s=Hello --string=Hello

   If the argument is required, it can also be separated by whitespace:

     -i 24 --int -27 -f 24.5 --float 0.27 -s Hello --string Hello

   Note that if the option is followed by =, whatever follows the = *is*
the argument, even if it's the null string.  In the example

     -i= 24 -f= 24.5 -s= Hello

   -i and -f will cause an error, because the null string is not a number,
but -s is perfectly legal; its argument is the null string, not "Hello".

   Remember that optional arguments *cannot* be separated from the option
by whitespace.

The Simple Method
-----------------

   The simple method is

     use Getopt::Mixed;
     Getopt::Mixed::getOptions(...option-descriptions...);

   You then examine the `$opt_*' variables to find out what options were
specified and the `@ARGV' array to see what arguments are left.

   If -a is an option that doesn't take an argument, then `$opt_a' will be
set to 1 if the option is present, or left undefined if the option is not
present.

   If -b is an option that takes an argument, then `$opt_b' will be set to
the value of the argument if the option is present, or left undefined if
the option is not present.  If the argument is optional but not supplied,
`$opt_b' will be set to the null string.

   Note that even if you specify that an option requires a string
argument, you can still get the null string (if the user specifically
enters it).  If the option requires a numeric argument, you will never get
the null string (because it isn't a number).

   When converting the option name to a Perl identifier, any non-word
characters in the name will be converted to underscores (_).

   If the same option occurs more than once, only the last occurrence will
be recorded.  If that's not acceptable, you'll have to use the flexible
method instead.

The Flexible Method
-------------------

   The flexible method is

     use Getopt::Mixed "nextOption";
     Getopt::Mixed::init(...option-descriptions...);
     while (($option, $value, $pretty) = nextOption()) {
         ...process option...
     }
     Getopt::Mixed::cleanup();

   This lets you process arguments one at a time.  You can then handle
repeated options any way you want to.  It also lets you see option names
with non-alphanumeric characters without any translation.  This is also
the only method that lets you find out what order the options and other
arguments were in.

   First, you call Getopt::Mixed::init with the option descriptions.
Then, you keep calling nextOption until it returns an empty list.
Finally, you call Getopt::Mixed::cleanup when you're done.  The remaining
(non-option) arguments will be found in @ARGV.

   Each call to nextOption returns a list of the next option, its value,
and the option as the user typed it.  The value will be undefined if the
option does not take an argument.  The option is stripped of its starter
(e.g., you get "a" and "foo", not "-a" or "-foo").  If you want to print
an error message, use the third element, which does include the option
starter.

OTHER FUNCTIONS
===============

   Getopt::Mixed provides one other function you can use.  `abortMsg'
prints its arguments on STDERR, plus your program's name and a newline.
It then exits with status 1.  For example, if `foo.pl' calls `abortMsg'
like this:

     Getopt::Mixed::abortMsg("Error");

   The output will be:

     foo.pl: Error

CUSTOMIZATION
=============

   There are several customization variables you can set.  All of these
variables should be set after calling Getopt::Mixed::init and before
calling nextOption.

   If you set any of these variables, you must check the version number
first.  The easiest way to do this is like this:

     use Getopt::Mixed 1.006;

   If you are using the simple method, and you want to set these
variables, you'll need to call init before calling getOptions, like this:

     use Getopt::Mixed 1.006;
     Getopt::Mixed::init(...option-descriptions...);
     ...set configuration variables...
     Getopt::Mixed::getOptions();      # IMPORTANT: no parameters

$order
     $order can be set to $REQUIRE_ORDER, $PERMUTE, or $RETURN_IN_ORDER.
     The default is $REQUIRE_ORDER if the environment variable
     POSIXLY_CORRECT has been set, $PERMUTE otherwise.

     $REQUIRE_ORDER means that no options can follow the first argument
     which isn't an option.

     $PERMUTE means that all options are treated as if they preceded all
     other arguments.

     $RETURN_IN_ORDER means that all arguments maintain their ordering.
     When nextOption is called, and the next argument is not an option, it
     returns the null string as the option and the argument as the value.
     nextOption never returns the null list until all the arguments have
     been processed.

$ignoreCase
     Ignore case when matching options.  Default is 1 unless the option
     descriptions contain an upper-case letter.

$optionStart
     A string of characters that can start options.  Default is "-".

$badOption
     A reference to a function that is called when an unrecognized option
     is encountered.  The function receives three arguments.  $_[0] is the
     position in @ARGV where the option came from.  $_[1] is the option as
     the user typed it (including the option start character).  $_[2] is
     either undef or a string describing the reason the option was not
     recognized (Currently, the only possible value is 'ambiguous', for a
     long option with several possible matches).  The option has already
     been removed from @ARGV.  To put it back, you can say:

          splice(@ARGV,$_[0],0,$_[1]);

     The function can do anything you want to @ARGV.  It should return
     whatever you want nextOption to return.

     The default is a function that prints an error message and exits the
     program.

$checkArg
     A reference to a function that is called to make sure the argument
     type is correct.  The function receives four arguments.  $_[0] is the
     position in @ARGV where the option came from.  $_[1] is the text
     following the option, or undefined if there was no text following the
     option.  $_[2] is the name of the option as the user typed it
     (including the option start character), suitable for error messages.
     $_[3] is the argument type specifier.

     The function can do anything you want to @ARGV.  It should return the
     value for this option.

     The default is a function that prints an error message and exits the
     program if the argument is not the right type for the option.  You can
     also adjust the behavior of the default function by changing
     $intRegexp or $floatRegexp.

$intRegexp
     A regular expression that matches an integer.  Default is
     '^[-+]?\d+$', which matches a string of digits preceded by an
     optional sign.  Unlike the other configuration variables, this cannot
     be changed after nextOption is called, because the pattern is compiled
     only once.

$floatRegexp
     A regular expression that matches a floating point number.  Default is
     '^[-+]?(\d*\.?\d+|\d+\.)$', which matches the following formats:
     "123", "123.", "123.45", and ".123" (plus an optional sign).  It does
     not match exponential notation.  Unlike the other configuration
     variables, this cannot be changed after nextOption is called, because
     the pattern is compiled only once.

$typeChars
     A string of the characters which are legal argument types.  The
     default is 'sif', for String, Integer, and Floating point arguments.
     The string should consist only of letters.  Upper case letters are
     discouraged, since this will hamper the case-folding of options.  If
     you change this, you should set $checkType to a function that will
     check arguments of your new type.  Unlike the other configuration
     variables, this must be set before calling init(), and cannot be
     changed afterwards.

$checkType
     If you add new types to $typeChars, you should set this to a function
     which will check arguments of the new types.

BUGS
====

   * This document should be expanded.

   * A long option must be at least two characters long.  Sorry.

   * The ! argument specifier of Getopt::Long is not supported, but you
     could have options *-foo* and *-nofoo* and then do something like:

          $opt_foo = 0 if $opt_nofoo;

   * The `@' argument specifier of Getopt::Long is not supported.  If you
     want your values pushed into an array, you'll have to use nextOption
     and do it yourself.

LICENSE
=======

   Getopt::Mixed is distributed 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 means it 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.

   Since Perl scripts are only compiled at runtime, and simply calling
Getopt::Mixed does not bring your program under the GPL, the only real
restriction is that you can't use Getopt::Mixed in an binary-only
distribution produced with dump (unless you also provide source code).

AUTHOR
======

   Christopher J. Madsen <`ac608@yfn.ysu.edu'>

   Thanks are also due to Andreas Koenig for helping Getopt::Mixed conform
to the standards for Perl modules and for answering a bunch of questions.
Any remaining deficiencies are my fault.

     Examples:

   1) #Program: my($x) = { 'a' => { 'a' => [ 'a', 'b', 'c', ],
       'b' => 9,                     'c' => 10, },            'b' =>
'asdf',            'c' => [ 45, 56, 67, ], };

   print "\$x->" . &reference_tree_string($x, "\$x->");

   #Output: $x->{ 'a' => { 'a' => [ a, #0                         b, #1
                    c, ],                'b' => 9,                'c' =>
10, },       'b' => asdf,       'c' => [ 45, #0                56, #1
         67, ], }

   2) #Program: my($x) = { 'a' => { 'a' => [ 'a', 'b', 'c', ],
       'b' => 9,                     'c' => 10, },            'b' =>
'asdf',            'c' => [ 45, 56, 67, ], };

   print "\$x->" . &reference_tree_string($x);

   #Output: $x->{ 'a' => { 'a' => [ a, #0                     b, #1
            c, ],            'b' => 9,            'c' => 10, },   'b' =>
asdf,   'c' => [ 45, #0            56, #1            67, ], }

handle command line options flexibly using regular expressions
**************************************************************

NAME
====

   Getopt::Regex - handle command line options flexibly using regular
expressions

SYNOPSIS
========

     use Getopt::Regex;
     GetOptions(\@ARGV,[$regex,$ref,$takesarg],...);

   *\@ARGV* - reference to array of command line arguments *$regex* -
regular expression for identifying the option $ref - reference to a
variable to be set or a function which is passed the argument if it exists.
*$takesarg* - if 1 subsequent command line argument is taken as its
argument

DESCRIPTION
===========

   This package provides a flexible yet simple method for handling command
line options. It does not stamp over the callers namespace or, currently,
inforce any particular standard for the options - the user can do this if
they want. By using anonymous closures sophisticated option specifications
can be constructed.

   The function GetOptions, exported from the package takes a reference to
the argument list followed by a set of option specifications which are
references to arrays containing at least a regular expression to match for
the option and a reference to a variable to be set or a function to be
called. A third optional argument for each option, if set to 1, pulles off
the following command line argument as an argument for that option.

   The simplest use is to set a boolean variable if an argument is set

     GetOptions(\@ARGV,['-[v|V]',\$bool,0]);

   If the option `'-v'' or `'-V'' occurs $bool will be set to 1, otherwise
it is left unchanged.

   A subsequent command line argument may be used as as an option argument
as follows

     GetOptions(\@ARGV,['-f',\$fname,1]);

     will set $fname to fname if '-f fname' is specified on the command line.

   Processed arguments are removed from the argument list.  Only the first
occurance of an argument is processed, if a variable is being set as in
the above examples

   More complex argument specifications are possible using anonymous
functions as arguments. If the option takes an argument, the argument is
passed to the function.  Parts of the regular expression may also be used
in the anonymous closure being executed. e.g.

     GetOptions(\@ARGV,
      ['-D(.+)=(.+)',sub { diagnostic $1,$2; }    ,0],
      ['-D(.+)',     sub { diagnostic $1; $_[0]; },1]);

   The first option specification will match options in the format
'-DDIAGNOSTIC=VALUE',the second will match occurances of the format
'-DDIAGNOSTIC VALUE'.  As can be seen use of the regex matching variables
can be made in handling the options.

   When GetOptions is called with a function reference the function is
called for all matching occurances of the regular expression, and the
proceesed options are removed from the argument list.

   Another useful example is

     GetOptions(\@ARGV,['-(no-)*optimization',0,sub { $optimization=!$1; }]);

   which identifies the option statements '-optimization' or
'-no-optimization' setting $optimization true or false approptiately.

   The option '-' ends the search for matching options - further arguments
are not searched.

NOTE
====

   Requires at least Perl 5.000 or Perl 5.001m if anonymous closures are
used.

HISTORY
=======

   $Log: Options.pm,v $ Revision 1.3  1995/12/16 09:48:28  willijar Rename
package to be more consistant with guidlines

   Revision 1.2  1995/12/12 22:01:35  willijar Removed unnecessary default
argument. Extended pod documentation.

   Revision 1.1  1995/12/10 15:57:06  willijar Initial revision

BUGS
====

   Please let me know.

TODO
====

   Possibly integrate default behaviour of other option functions in this
package.

AUTHOR
======

   John A.R. Williams, <J.A.R.Williams@aston.ac.uk>

Provide a simple wrapper around Getopt::Long.
*********************************************

NAME
====

   `Getopt::Simple' - Provide a simple wrapper around Getopt::Long.

SYNOPSIS
========

     use Getopt::Simple;

     # Or ...
     # use Getopt::Simple qw($switch);

     my($options) =
     {
     'help' =>
     	{
     	'type'		=> '',
     	'env'		=> '-',
     	'default'	=> '',
     #		'verbose'	=> '',	# Not needed on every key.
     	'order'		=> 1,
     	},
     'username' =>
     	{
     	'type'		=> '=s',			# As per Getopt::Long.
     	'env'		=> '$USER',			# Help text.
     	'default'	=> $ENV{'USER'} || 'RonSavage',	# In case $USER is undef.
     	'verbose'	=> 'Specify the username on the remote machine',
     	'order'		=> 3,				# Help text sort order.
     	},
     'password' =>
     	{
     	'type'		=> '=s',
     	'env'		=> '-',
     	'default'	=> 'password',
     	'verbose'	=> 'Specify the password on the remote machine',
     	'order'		=> 4,
     	},
     };

     my($option) = new Getopt::Simple;

     if (! $option -> getOptions($options, "Usage: testSimple.pl [options]") )
     {
     	exit(-1);	# Failure.
     }

     print "username: $option->{'switch'}{'username'}. \n";
     print "password: $option->{'switch'}{'password'}. \n";

     # Or, after 'use Getopt::Simple qw($switch);' ...
     # print "username: $switch->{'username'}. \n";
     # print "password: $switch->{'password'}. \n";

DESCRIPTION
===========

   The `Getopt::Simple' module provides a simple way of specifying:

   * Command line switches

   * Type information for switch values

   * Default values for the switches

   * Help text per switch

The `getOptions()' function
===========================

   The `getOptions()' function takes 4 parameters:

   * A hash defining the command line switches

   * A string to display as a help text heading

   * A Boolean. 0 = (Default) Use case-sensitive switch names. 1 = Ignore
     case

   * A Boolean. 0 = Return after displaying help. 1 = (Default) Terminate
     with exit(0) after displaying help

The $classRef -> {'switch'} hash reference
==========================================

   Command line option values are accessed in your code by dereferencing
the hash reference $classRef -> {'switch'}. Two examples are given above,
under synopsis.

   Alternately, you can use the hash reference $switch. See below.

The $switch hash reference
==========================

   Command line option values are accessed in your code by dereferencing
the hash reference $switch. Two examples are given above, under synopsis.

   Alternately, you can use the hash reference $classRef -> {'switch'}.
See above.

The `dumpOptions()' function
============================

   `dumpOptions()' prints all your option's keys and their current values.

The `helpOptions()' function
============================

   `helpOptions()' prints nicely formatted help text.

INSTALLATION
============

   You install `Getopt::Simple', as you would install any perl module
library, by running these commands:

     perl Makefile.PL
     make
     make test
     make install

   If you want to install a private copy of `Getopt::Simple' in your home
directory, then you should try to produce the initial Makefile with
something like this command:

     perl Makefile.PL LIB=~/perl
     	or
     perl Makefile.PL LIB=C:/Perl/Site/Lib

   If, like me, you don't have permission to write man pages into unix
system directories, use:

     make pure_install

   instead of make install. This option is secreted in the middle of p 414
of the second edition of the dromedary book.

WARNING re Perl bug
===================

   As always, be aware that these 2 lines mean the same thing, sometimes:

   * $self -> {'thing'}

   * $self->{'thing'}

   The problem is the spaces around the ->. Inside double quotes, "...",
the first space stops the dereference taking place. Outside double quotes
the scanner correctly associates the $self token with the {'thing'} token.

   I regard this as a bug.

REQUIRED MODULES
================

   * Exporter

   * Getopt::Long

RETURN VALUES
=============

   * `dumpOptions()' returns nothing

   * `helpOptions()' returns nothing

   * `getOptions()' returns 0 for failure and 1 for success

AUTHOR
======

   `Getopt::Simple' was written by Ron Savage *<rpsavage@ozemail.com.au>*
in 1997.

LICENCE
=======

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Process single-character switches with switch clustering
********************************************************

NAME
====

   getopt - Process single-character switches with switch clustering

   getopts - Process single-character switches with switch clustering

SYNOPSIS
========

     use Getopt::Std;

     getopt('oDI');    # -o, -D & -I take arg.  Sets opt_* as a side effect.
     getopt('oDI', \%opts);    # -o, -D & -I take arg.  Values in %opts
     getopts('oif:');  # -o & -i are boolean flags, -f takes an argument
     		      # Sets opt_* as a side effect.
     getopts('oif:', \%opts);  # options as above. Values in %opts

DESCRIPTION
===========

   The getopt() functions processes single-character switches with switch
clustering.  Pass one argument which is a string containing all switches
that take an argument.  For each switch found, sets $opt_x (where x is the
switch name) to the value of the argument, or 1 if no argument.  Switches
which take an argument don't care whether there is a space between the
switch and the argument.

   Note that, if your code is running under the recommended `use strict
'vars'' pragma, you will need to declare these package variables with
"our":

     our($opt_foo, $opt_bar);

   For those of you who don't like additional global variables being
created, getopt() and getopts() will also accept a hash reference as an
optional second argument.  Hash keys will be x (where x is the switch
name) with key values the value of the argument or 1 if no argument is
specified.

   To allow programs to process arguments that look like switches, but
aren't, both functions will stop processing switches when they see the
argument -.  The - will be removed from @ARGV.

table-driven argument parsing for Perl 5
****************************************

NAME
====

   Getopt::Tabular - table-driven argument parsing for Perl 5

SYNOPSIS
========

     use Getopt::Tabular;

   (or)

     use Getopt::Tabular qw/GetOptions
                            SetHelp SetHelpOption
                            SetError GetError/;

     ...

     &Getopt::Tabular::SetHelp (long_help, usage_string);

     @opt_table = (
                   [section_description, "section"],
                   [option, type, num_values, option_data, help_string],
                   ...
                  );
     &GetOptions (\@opt_table, \@ARGV [, \@newARGV]) || exit 1;

DESCRIPTION
===========

   *Getopt::Tabular* is a Perl 5 module for table-driven argument parsing,
vaguely inspired by John Ousterhout's Tk_ParseArgv.  All you really need
to do to use the package is set up a table describing all your
command-line options, and call &GetOptions with three arguments: a
reference to your option table, a reference to `@ARGV' (or something like
it), and an optional third array reference (say, to `@newARGV').
&GetOptions will process all arguments in `@ARGV', and copy any leftover
arguments (i.e. those that are not options or arguments to some option) to
the `@newARGV' array.  (If the `@newARGV' argument is not supplied,
GetOptions will replace `@ARGV' with the stripped-down argument list.)  If
there are any invalid options, GetOptions will print an error message and
return 0.

   Before I tell you all about why Getopt::Tabular is a wonderful thing,
let me explain some of the terminology that will keep popping up here.

argument
     any single word appearing on the command-line, i.e. one element of the
     `@ARGV' array.

option
     an argument that starts with a certain sequence of characters; the
     default is "-".  (If you like GNU-style options, you can change this
     to "-".)  In most Getopt::Tabular-based applications, options can
     come anywhere on the command line, and their order is unimportant
     (unless one option overrides a previous option).  Also,
     Getopt::Tabular will allow any non-ambiguous abbreviation of options.

option argument
     (or value) an argument that immediately follows certain types of
     options.  For instance, if `-foo' is a scalar-valued integer option,
     and `-foo 3' appears on the command line, then 3 will be the argument
     to `-foo'.

option type
     controls how GetOptions deals with an option and the arguments that
     follow it.  (Actually, for most option types, the type interacts with
     the num_values field, which determines whether the option is scalar-
     or vector-valued.  This will be fully explained in due course.)

FEATURES
========

   Now for the advertising, i.e. why Getopt::Tabular is a good thing.

   * Command-line arguments are carefully type-checked, both by pattern and
     number--e.g. if an option requires two integers, GetOptions makes sure
     that exactly two integers follow it!

   * The valid command-line arguments are specified in a data structure
     separate from the call to GetOptions; this makes it easier to have
     very long lists of options, and to parse options from multiple
     sources (e.g. the command line, an environment variable, and a
     configuration file).

   * Getopt::Tabular can intelligently generate help text based on your
     option descriptions.

   * The type system is extensible, and if you can define your desired
     argument type using a single Perl regular expression then it's
     particularly easy to extend.

   * To make your program look smarter, options can be abbreviated and
     come in any order.

   *      You can parse options in a "spoof" mode that has no side-effects -- this
          is useful for making a validation pass over the command line without
          actually doing anything.

   In general, I have found that Getopt::Tabular tends to encourage
programs with long lists of sophisticated options, leading to great
flexibility, intelligent operation, and the potential for insanely long
command lines.

BASIC OPERATION
===============

   The basic operation of Getopt::Tabular is driven by an *option table*,
which is just a list of *option descriptions* (otherwise known as option
table entries, or just entries).  Each option description tells GetOptions
everything it needs to know when it encounters a particular option on the
command line.  For instance,

     ["-foo", "integer", 2, \@Foo, "set the foo values"]

   means that whenever `-foo' is seen on the command line, GetOptions is
to make sure that the next two arguments are integers, and copy them into
the caller's `@Foo' array.  (Well, really into the `@Foo' array where the
option table is defined.  This is almost always the same as GetOptions'
caller, though.)

   Typically, you'll group a bunch of option descriptions together like
this:

     @options =
         (["-range", "integer", 2, \@Range,
           "set the range of allowed values"],
          ["-file", "string", 1, \$File,
            "set the output file"],
          ["-clobber", "boolean", 0, \$Clobber,
            "clobber existing files"],
          ...
         );

   and then call GetOptions like this:

     &GetOptions (\@options, \@ARGV) || exit 1;

   which replaces `@ARGV' with a new array containing all the arguments
left-over after options and their arguments have been removed.  You can
also call GetOptions with three arguments, like this:

     &GetOptions (\@options, \@ARGV, \@newARGV) || exit 1;

   in which case `@ARGV' is untouched, and `@newARGV' gets the leftover
arguments.

   In case of error, GetOptions prints enough information for the user to
figure out what's going wrong.  If you supply one, it'll even print out a
brief usage message in case of error.  Thus, it's enough to just `exit 1'
when GetOptions indicates an error by returning 0.

   Detailed descriptions of the contents of an option table entry are given
next, followed by the complete run-down of available types, full details on
error handling, and how help text is generated.

OPTION TABLE ENTRIES
====================

   The fields in the option table control how arguments are parsed, so it's
important to understand each one in turn.  First, the format of entries in
the table is fairly rigid, even though this isn't really necessary with
Perl.  It's done that way to make the Getopt::Tabular code a little easier;
the drawback is that some entries will have unused values (e.g. the
num_values field is never used for boolean options, but you still have to
put something there as a place-holder).  The fields are as follows:

option
     This is the option name, e.g. "-verbose" or "-some_value".  For most
     option types, this is simply an option prefix followed by text; for
     boolean options, however, it can be a little more complicated.  (The
     exact rules are discussed under `"OPTION TYPES"' in this node.)  And
     yes, even though you tell Getopt::Tabular the valid option prefixes,
     you still have to put one onto the option names in the table.

type
     The option type decides what action will be taken when this option is
     seen on the command line, and (if applicable) what sort of values
     will be accepted for this option.  There are three broad classes of
     types: those that imply copying data from the command line into some
     variable in the caller's space; those that imply copying constant
     data into the caller's space without taking any more arguments from
     the command line; and those that imply some other action to be taken.
     The available option types are covered in greater detail below (see
     `OPTION TYPES' in this node), but briefly: string, integer, and float
     all imply copying values from the command line to a variable;
     constant, boolean, copy, arrayconst, and hashconst all imply copying
     some pre-defined data into a variable; call and eval allow the
     execution of some arbitrary subroutine or chunk of code; and help
     options will cause GetOptions to print out all available help text
     and return 0.

num_values
     for string, integer, and float options, this determines whether the
     option is a scalar (num_values = 1) or vector (num_values > 1)
     option.  (Note that whether the option is scalar- or vector-valued
     has an important influence on what you must supply in the option_data
     field!)  For constant, copy, arrayconst, and hashconst option types,
     num_values is a bit of a misnomer: it actually contains the value (or
     a reference to it, if array or hash) to be copied when the option is
     encountered.  For call options, num_values can be used to supply
     extra arguments to the called subroutine.  In any case, though, you
     can think of num_values as an input value.  For boolean and eval
     options, num_values is ignored and should be undef or 0.

option_data
     For string, integer, float, boolean, constant, copy, arrayconst, and
     hashconst types, this must be a reference to the variable into which
     you want GetOptions to copy the appropriate thing.  The "appropriate
     thing" is either the argument(s) following the option, the constant
     supplied as num_values, or 1 or 0 (for boolean options).

     For boolean, constant, copy, and scalar-valued string, integer, and
     float options, this must be a scalar reference.  For vector-valued
     string, integer, and float options (num_values > 1), and for
     arrayconst options, this must be an array reference.  For hashconst
     options, this must be a hash reference.

     Finally, option_data is also used as an input value for call and eval
     options: for call, it should be a subroutine reference, and for eval
     options, it should be a string containing valid Perl code to evaluate
     when the option is seen.  The subroutine called by a call option
     should take at least two arguments: a string, which is the actual
     option that triggered the call (because the same subroutine could be
     tied to many options), and an array reference, which contains all
     command line arguments after that option.  (Further arguments can be
     supplied in the num_values field.)  The subroutine may freely modify
     this array, and those modifications will affect the behaviour of
     GetOptions afterwards.

     The chunk of code passed to an eval option is evaluated in the package
     from which GetOptions is called, and does not have access to any
     internal Getopt::Tabular data.

help_string
     (optional) a brief description of the option.  Don't worry about
     formatting this in any way; when GetOptions has to print out your
     help, it will do so quite nicely without any intervention.  If the
     help string is not defined, then that option will not be included in
     the option help text.  (However, you could supply an empty string -
     which is defined - to make GetOptions just print out the option name,
     but nothing else.)

arg_desc
     (optional) an even briefer description of the values that you expect
     to follow your option.  This is mainly used to supply place-holders
     in the help string, and is specified separately so that GetOptions
     can act fairly intelligently when formatting a help message.  See
     `"HELP TEXT"' in this node for more information.

OPTION TYPES
============

   The option type field is the single-most important field in the table,
as the type for an option `-foo' determines (along with num_values) what
action GetOptions takes when it sees `-foo' on the command line: how many
following arguments become `-foo''s arguments, what regular expression
those arguments must conform to, or whether some other action should be
taken.

   As mentioned above, there are three main classes of argument types:

argument-driven options
     These are options that imply taking one or more option arguments from
     the command line after the option itself is taken.  The arguments are
     then copied into some variable supplied (by reference) in the option
     table entry.

constant-valued options
     These are options that have a constant value associated with them;
     when the option is seen on the command line, that constant is copied
     to some variable in the caller's space.  (Both the constant and the
     value are supplied in the option table entry.)  Constants can be
     scalars, arrays, or hashes.

other options
     These imply some other action to be taken, usually supplied as a
     string to eval or a subroutine to call.

Argument-driven option types
----------------------------

string, integer, float
     These are the option types that imply "option arguments", i.e.
     arguments after the option that will be consumed when that option is
     encountered on the command line and copied into the caller's space
     via some reference.  For instance, if you want an option `-foo' to
     take a single string as an argument, with that string being copied to
     the scalar variable `$Foo', then you would have this entry in your
     option table:

          ["-foo", "string", 1, \$Foo]

     (For conciseness, I've omitted the help_string and *argdesc* entries
     in all of the example entries in this section.  In reality, you should
     religiously supply help text in order to make your programs easier to
     use and easier to maintain.)

     If num_values is some n greater than one, then the option_data field
     must be an array reference, and n arguments are copied from the
     command line into that array.  (The array is clobbered each time
     `-foo' is encountered, not appended to.)  In this case, `-foo' is
     referred to as a *vector-valued* option, as it must be followed by a
     fixed number of arguments.  (Eventually, I plan to add *list-valued*
     options, which take a variable number of arguments.)  For example an
     option table like

          ["-foo", "string", 3, \@Foo]

     would result in the `@Foo' array being set to the three strings
     immediately following any `-foo' option on the command line.

     The only difference between string, integer, and float options is how
     picky GetOptions is about the value(s) it will accept.  For string
     options, anything is OK; for integer options, the values must look
     like integers (i.e., they must match `/[+-]?\d+/'); for float
     options, the values must look like C floating point numbers (trust
     me, you don't want to see the regexp for this).  Note that since
     string options will accept anything, they might accidentally slurp up
     arguments that are meant to be further options, if the user forgets
     to put the correct string.  For instance, if `-foo' and `-bar' are
     both scalar-valued string options, and the arguments `-foo -bar' are
     seen on the command-line, then "-bar" will become the argument to
     `-foo', and never be processed as an option itself.  (This could be
     construed as either a bug or a feature.  If you feel really strongly
     that it's a bug, then complain and I'll consider doing something
     about it.)

     If not enough arguments are found that match the required regular
     expression, GetOptions prints to standard error a clear and useful
     error message, followed by the usage summary (if you supplied one),
     and returns 0.  The error messages look something like "-foo option
     must be followed by an integer", or "-foo option must be followed by
     3 strings", so it really is enough for your program to `exit 1'
     without printing any further message.

User-defined patterns
     Since the three option types described above are defined by nothing
     more than a regular expression, it's easy to define your own option
     types.  For instance, let's say you want an option to accept only
     strings of upper-case letters.  You could then call
     `&Getopt::Tabular::AddPatternType' as follows:

          &Getopt::Tabular::AddPatternType
            ("upperstring", "[A-Z]+", "uppercase string")

     Note that the third parameter is optional, and is only supplied to
     make error messages clearer.  For instance, if you now have a
     scalar-valued option `-zap' of type `upperstring':

          ["-zap", "upperstring", 1, \$Zap]

     and the user gets it wrong and puts an argument that doesn't consist
     of all uppercase letters after `-zap', then GetOptions will complain
     that "-zap option must be followed by an uppercase string".  If you
     hadn't supplied the third argument to `&AddType', then the error
     message would have been the slightly less helpful "-zap option must be
     followed by an upperstring".  Also, you might have to worry about how
     GetOptions pluralizes your description: in this case, it will simply
     add an "s", which works fine much of the time, but not always.
     Alternately, you could supply a two-element list containing the
     singular and plural forms:

          &Getopt::Tabular::AddPatternType
            ("upperstring", "[A-Z]+",
              ["string of uppercase letters", "strings of uppercase letters"])

     So, if `-zap' instead expects three `upperstring's, and the user
     goofs, then the error message would be (in the first example) "-zap
     option must be followed by 3 uppercase strings" or "-zap option must
     be followed by three strings of uppercase letters" (second example).

     Of course, if you don't intend to have vector-valued options of your
     new type, pluralization hardly matters.  Also, while it might seem
     that this is a nice stab in the direction of multi-lingual support,
     the error messages are still hard-coded to English in other places.
     Maybe in the next version...

Constant-valued option types
----------------------------

boolean
     For boolean options, option_data must be a scalar reference;
     num_values is ignored (you can just set it to undef or 0).  Booleans
     are slightly weird in that every boolean option implies *two*
     possible arguments that will be accepted on the command line, called
     the positive and negative alternatives.  The positive alternative
     (which is what you specify as the option name) results in a true
     value, while the negative alternative results in false.  Most of the
     time, you can let GetOptions pick the negative alternative for you:
     it just inserts "no" after the option prefix, so "-clobber" becomes
     "-noclobber".  (More precisely, GetOptions tests all option prefixes
     until one of them matches at the beginning of the option name.  It
     then inserts "no" between this prefix and the rest of the string.
     So, if you want to support both GNU-style options (like `--clobber')
     and one-hyphen options (-c), be sure to give "-" first when setting
     the option patterns with `&SetOptionPatterns'.  Otherwise, the
     negative alternative to "-clobber" will be "-no-clobber", which might
     not be what you wanted.)  Sometimes, though, you want to explicitly
     specify the negative alternative.  This is done by putting both
     alternatives in the option name, separated by a vertical bar, e.g.
     "-verbose|-quiet".

     For example, the above two examples might be specified as

          ["-clobber", "boolean", undef, \$Clobber],
          ["-verbose|-quiet", "boolean", undef, \$Verbose],...);

     If `-clobber' is seen on the command line, `$Clobber' will be set to
     1; if `-noclobber' is seen, then `$Clobber' will be set to 0.
     Likewise, `-verbose' results in `$Verbose' being set to 1, and
     `-quiet' will set `$Verbose' to 0.

const
     For const options, put a scalar value (not reference) in num_values,
     and a scalar reference in option_data.  For example:

          ["-foo", "const", "hello there", \$Foo]

     On encountering `-foo', GetOptions will copy "hello there" to `$Foo'.

arrayconst
     For arrayconst options, put an array reference (input) (not an array
     value) in num_values, and another array reference (output) in
     option_data.  For example:

          ["-foo", "arrayconst", [3, 6, 2], \@Foo]

     On encountering `-foo', GetOptions will copy the array `(3,6,2)' into
     `@Foo'.

hashconst
     For hashconst options, put a hash reference (input) (not a hash
     value) in num_values, and another hash reference (output) in
     option_data.  For example:

          ["-foo", "hashconst", { "Perl"   => "Larry Wall",
                                  "C"      => "Dennis Ritchie",
                                  "Pascal" => "Niklaus Wirth" },
           \%Inventors]

     On encountering `-foo', GetOptions will copy into `%Inventors' a hash
     relating various programming languages to the culprits primarily
     responsible for their invention.

copy
     copy options act just like const options, except when num_values is
     undefined.  In that case, the option name itself will be copied to
     the scalar referenced by option_data, rather than the undef value
     that would be copied under these circumstances with a const option.
     This is useful when one program accepts options that it simply passes
     to a sub-program; for instance, if `prog1' calls `prog2', and `prog2'
     might be run with the -foo option, then `prog1''s argument table
     might have this option:

          ["-foo", "copy", undef, \$Foo,
           "run prog2 with the -foo option"]

     and later on, you would run `prog2' like this:

          system ("prog2 $Foo ...");

     That way, if `-foo' is never seen on `prog1''s command line, `$Foo'
     will be untouched, and will expand to the empty string when building
     the command line for `prog2'.

     If num_values is anything other than undef, then copy options behave
     just like constant options.

Other option types
------------------

call
     For call options, option_data must be a reference to a subroutine.
     The subroutine will be called with at least two arguments: a string
     containing the option that triggered the call (because the same
     subroutine might be activated by many options), a reference to an
     array containing all remaining command-line arguments after the
     option, and other arguments specified using the num_values field.
     (To be used for this purpose, num_values must be an array reference;
     otherwise, it is ignored.)  For example, you might define a subroutine

          sub process_foo
          {
             my ($opt, $args, $dest) = @_;

          $$dest = shift @$args;    # not quite right! (see below)
              }

     with a corresponding option table entry:

          ["-foo", "call", [\$Foo], \&process_foo]

     and then `-foo' would act just like a scalar-valued string option that
     copies into `$Foo'.  (Well, *almost* ... read on.)

     A subtle point that might be missed from the above code: the value
     returned by `&process_foo' *does* matter: if it is false, then
     GetOptions will return 0 to its caller, indicating failure.  To make
     sure that the user gets a useful error message, you should supply one
     by calling `SetError'; doing so will prevent GetOptions from printing
     out a rather mysterious (to the end user, at least) message along the
     lines of "subroutine call failed".  The above example has two subtle
     problems: first, if the argument following `-foo' is an empty string,
     then `process_foo' will return the empty string--a false value--thus
     causing GetOptions to fail confusingly.  Second, if there no
     arguments after `-foo', then `process_foo' will return undef--again,
     a false value, causing GetOptions to fail.

     To solve these problems, we have to define the requirements for the
     `-foo' option a little more rigorously.  Let's say that any string
     (including the empty string) is valid, but that there must be
     something there.  Then `process_foo' is written as follows:

          sub process_foo
          {
             my ($opt, $args, $dest) = @_;

          $$dest = shift @$args;
          (defined $$dest) && return 1;
          &Getopt::Tabular::SetError
            ("bad_foo", "$opt option must be followed by a string");
          return 0;
              }

     The `SetError' routine actually takes two arguments: an error class
     and an error message.  This is explained fully in the `ERROR
     HANDLING' in this node section, below.  And, if you find yourself
     writing a lot of routines like this, `SetError' is optionally
     exported from `Getopt::Tabular', so you can of course import it into
     your main package like this:

          use Getopt::Tabular qw/GetOptions SetError/;

eval
     An eval option specifies a chunk of Perl code to be executed (eval'd)
     when the option is encountered on the command line.  The code is
     supplied (as a string) in the option_data field; again, num_values is
     ignored.  For example:

          ["-foo", "eval", undef,
           'print "-foo seen on command line\n"']

     will cause GetOptions to print out (via an eval) the string "-foo seen
     on the command line\n" when -foo is seen.  No other action is taken
     apart from what you include in the eval string.  The code is evaluated
     in the package from which GetOptions was called, so you can access
     variables and subroutines in your program easily.  If any error occurs
     in the eval, GetOptions complains loudly and returns 0.

     Note that the supplied code is always evaluated in a `no strict'
     environment--that's because `Getopt::Tabular' is itself `use
     strict'-compliant, and I didn't want to force strictness on every
     quick hack that uses the module.  (Especially since eval options seem
     to be used mostly in quick hacks.)  (Anyone who knows how to fetch the
     strictness state for another package or scope is welcome to send me
     hints!)  However, the -w state is untouched.

section
     section options are just used to help formatting the help text.  See
     `HELP TEXT' in this node below for more details.

ERROR HANDLING
==============

   Generally, handling errors in the argument list is pretty transparent:
GetOptions (or one of its minions) generates an error message and assigns
an error class, GetOptions prints the message to the standard error, and
returns 0.  You can access the error class and error message using the
`GetError' routine:

     ($err_class, $err_msg) = &Getopt::Tabular::GetError ();

   (Like `SetError', `GetError' can also be exported from
`Getopt::Tabular'.)  The error message is pretty simple--it is an
explanation for the end user of what went wrong, which is why GetOptions
just prints it out and forgets about it.  The error class is further
information that might be useful for your program; the current values are:

bad_option
     set when something that looks like an option is found on the command
     line, but it's either unknown or an ambiguous abbreviation.

bad_value
     set when an option is followed by an invalid argument (i.e., one that
     doesn't match the regexp for that type), or the wrong number of
     arguments.

bad_call
     set when a subroutine called via a call option or the code evaluated
     for an eval option returns a false value.  The subroutine or eval'd
     code can override this by calling `SetError' itself.

bad_eval
     set when the code evaluted for an eval option has an error in it.

help
     set when the user requests help

   Note that most of these are errors on the end user's part, such as bad
or missing arguments.  There are also errors that can be caused by you,
the programmer, such as bad or missing values in the option table; these
generally result in GetOptions croaking so that your program dies
immediately with enough information that you can figure out where the
mistake is.  bad_eval is a borderline case; there are conceivably cases
where the end user's input can result in bogus code to evaluate, so I
grouped this one in the "user errors" class.  Finally, asking for help
isn't really an error, but the assumption is that you probably shouldn't
continue normal processing after printing out the help--so GetOptions
returns 0 in this case.  You can always fetch the error class with
`GetError' if you want to treat real errors differently from help requests.

HELP TEXT
=========

   One of Getopt::Tabular's niftier features is the ability to generate and
format a pile of useful help text from the snippets of help you include in
your option table.  The best way to illustrate this is with a couple of
brief examples.  First, it's helpful to know how the user can trigger a
help display.  This is quite simple: by default, GetOptions always has a
"-help" option, presence of which on the command line triggers a help
display.  (Actually, the help option is really your preferred option
prefix plus "help".  So, if you like to make GNU-style options to take
precedence as follows:

     &Getopt::Tabular::SetOptionPatterns qw|(--)([\w-]+) (-)(\w+)|;

   then the help option will be "-help".  There is only one help option
available, and you can set it by calling `&SetHelpOption' (another
optional export).

   Note that in addition to the option help embedded in the option table,
GetOptions can optionally print out two other messages: a descriptive text
(usually a short paragraph giving a rough overview of what your program
does, possibly referring the user to the fine manual page), and a usage
text.  These are both supplied by calling `&SetHelp', e.g.

     $Help = <<HELP;
     This is the foo program.  It reads one file (specified by -infile),
     operates on it some unspecified way (possibly modified by
     -threshold), and does absolutely nothing with the results.
     (The utility of the -clobber option has yet to be established.)
     HELP

     $Usage = <<USAGE;
     usage: foo [options]
            foo -help to list options
     USAGE

     &Getopt::Tabular::SetHelp ($Help, $Usage)

   Note that either of the long help or usage strings may be empty, in
which case GetOptions simply won't print them.  In the case where both are
supplied, the long help message is printed first, followed by the option
help summary, followed by the usage.  GetOptions inserts enough blank
lines to make the output look just fine on its own, so you shouldn't pad
either the long help or usage message with blanks.  (It looks best if each
ends with a newline, though, so setting the help strings with
here-documents--as in this example--is the recommended approach.)

   As an example of the help display generated by a typical option table,
let's take a look at the following:

     $Verbose = 1;
     $Clobber = 0;
     undef $InFile;
     @Threshold = (0, 1);

     @argtbl = (["-verbose|-quiet", "boolean", 0, \$Verbose,
                 "be noisy"],
                ["-clobber", "boolean", 0, \$Clobber,
                 "overwrite existing files"],
                ["-infile", "string", 1, \$InFile,
                 "specify the input file from which to read a large " .
                 "and sundry variety of data, to which many " .
                 "interesting operations will be applied", "<f>"],
                ["-threshold", "float", 2, \@Threshold,
                 "only consider values between <v1> and <v2>",
                 "<v1> <v2>"]);

   Assuming you haven't supplied long help or usage strings, then when
GetOptions encounters the help option, it will immediately stop parsing
arguments and print out the following option summary:

     Summary of options:
        -verbose    be noisy [default]
        -quiet      opposite of -verbose
        -clobber    overwrite existing files
        -noclobber  opposite of -clobber [default]
        -infile <f> specify the input file from which to read a large and
                    sundry variety of data, to which many interesting
                    operations will be applied
        -threshold <v1> <v2>
                    only consider values between <v1> and <v2> [default: 0 1]

   There are a number of interesting things to note here.  First, there are
three option table fields that affect the generation of help text: option,
help_string, and *argdesc*.  Note how the *argdesc* strings are simply
option placeholders, usually used to 1) indicate how many values are
expected to follow an option, 2) (possibly) imply what form they take
(although that's not really shown here), and 3) explain the exact meaning
of the values in the help text.  *argdesc* is just a string like the help
string; you can put whatever you like in it.  What I've shown above is
just my personal preference (which may well evolve).

   A new feature with version 0.3 of Getopt::Tabular is the inclusion of
default values with the help for certain options.  A number of conditions
must be fulfilled for this to happen for a given option: first, the option
type must be one of the "argument-driven" types, such as integer, float,
string, or a user-defined type.  Second, the option data field must refer
either to a defined scalar value (for scalar-valued options) or to a list
of one or more defined values (for vector-valued options).  Thus, in the
above example, the `-infile' option doesn't have its default printed
because the `$InFile' scalar is undefined.  Likewise, if the `@Threshold'
array were the empty list `()', or a list of undefined values
`(undef,undef)', then the default value for `-threshold' also would not
have been printed.

   The formatting is done as follows: enough room is made on the right hand
side for the longest option name, initially omitting the argument
placeholders.  Then, if an option has placeholders, and there is room for
them in between the option and the help string, everything (option,
placeholders, help string) is printed together.  An example of this is the
`-infile' option: here, "-infile <f>" is just small enough to fit in the
12-character column (10 characters because that is the length of the
longest option, and 2 blanks), so the help text is placed right after it
on the same line.  However, the `-threshold' option becomes too long when
its argument placeholders are appended to it, so the help text is pushed
onto the next line.

   In any event, the help string supplied by the caller starts at the same
column, and is filled to make a nice paragraph of help.  GetOptions will
fill to the width of the terminal (or 80 columns if it fails to find the
terminal width).

   Finally, you can have pseudo entries of type section, which are
important to make long option lists readable (and one consequence of using
Getopt::Tabular is programs with ridiculously long option lists - not
altogether a bad thing, I suppose).  For example, this table fragment:

     @argtbl = (...,
                ["-foo", "integer", 1, \$Foo,
                 "set the foo value", "f"],
                ["-enterfoomode", "call", 0, \&enter_foo_mode,
                 "enter foo mode"],
                ["Non-foo related options", "section"],
                ["-bar", "string", 2, \@Bar,
                 "set the bar strings (which have nothing whatsoever " .
                 "to do with foo", "<bar1> <bar2>"],
                ...);

   results in the following chunk of help text:

     -foo f         set the foo value
     -enterfoomode  enter foo mode

         -- Non-foo related options ---------------------------------
     -bar b1 b2     set the bar strings (which have nothing
                    whatsoever to do with foo

   (This example also illustrates a slightly different style of argument
placeholder.  Take your pick, or invent your own!)

SPOOF MODE
==========

   Since callbacks from the command line (call and eval options) can do
anything, they might be quite expensive.  In certain cases, then, you
might want to make an initial pass over the command line to ensure that
everything is OK before parsing it "for real" and incurring all those
expensive callbacks.  Thus, `Getopt::Tabular' provides a "spoof" mode for
parsing a command line without side-effects.  In the simplest case, you
can access spoof mode like this:

     use Getopt::Tabular qw(SpoofGetOptions GetOptions);
       .
       .
       .
     &SpoofGetOptions (\@options, \@ARGV, \@newARGV) || exit 1;

   and then later on, you would call GetOptions with the original `@ARGV'
(so it can do what `SpoofGetOptions' merely pretended to do):

     &GetOptions (\@options, \@ARGV, \@newARGV) || exit 1;

   For most option types, any errors that GetOptions would catch should
also be caught by `SpoofGetOptions' - so you might initially think that
you can get away without that `|| exit 1' after calling GetOptions.
However, it's a good idea for a couple of reasons.  First, you might
inadvertently changed `@ARGV' - this is usually a bug and a silly thing to
do, so you'd probably want your program to crash loudly rather than fail
mysteriously later on.  Second, and more likely, some of those expensive
operations that you're initially avoiding by using `SpoofGetOptions' might
themselves fail - which would cause GetOptions to return false where
`SpoofGetOption' completes without a problem.  (Finally, there's the faint
possiblity of bugs in `Getopt::Tabular' that would cause different
behaviour in spoof mode and real mode - this really shouldn't happen,
though.)

   In reality, using spoof mode requires a bit more work.  In particular,
the whole reason for spoof argument parsing is to avoid expensive
callbacks, but since callbacks can eat any number of command line
arguments, you have to emulate them in some way.  It's not possible for
`SpoofGetOptions' to do this for you, so you have to help out by supplying
"spoof" callbacks.  As an example, let's say you have a callback option
that eats one argument (a filename) and immediately reads that file:

     @filedata = ();

     sub read_file
     {
        my ($opt, $args) = @_;

     warn ("$opt option requires an argument\n"), return 0 unless @$args;
     my $file = shift @$args;
     open (FILE, $file) ||
        (warn ("$file: $!\n"), return 0);
     push (@filedata, <FILE>);
     close (FILE);
     return 1;
        }

     @options =
        (['-read_file', 'call', undef, \&read_file]);

   Since `-read_file' could occur any number of times on the command line,
we might end up reading an awful lot of files, and thus it might be a long
time before we catch errors late in the command line.  Thus, we'd like to
do a "spoof" pass over the command line to catch all errors.  A simplistic
approach would be to supply a spoof callback that just eats one argument
and returns success:

     sub spoof_read_file
     {
        my ($opt, $args) = @_;
        (warn ("$opt option requires an argument\n"), return 0)
           unless @$args;
        shift @$args;
        return 1;
     }

   Then, you have to tell `Getopt::Tabular' about this alternate callback
with no side-effects (apart from eating that one argument):

     &Getopt::Tabular::SetSpoofCodes (-read_file => \&spoof_read_file);

   (`SetSpoofCodes' just takes a list of key/value pairs, where the keys
are call or eval options, and the values are the "no side-effects"
callbacks.  Naturally, the replacement callback for an eval option should
be a string, and for a call option it should be a code reference.  This is
not actually checked, however, until you call `SpoofGetOptions', because
`SetSpoofCodes' doesn't know whether options are call or eval or what.)

   A more useful `spoof_read_file', however, would actually check if the
requested file exists - i.e., we should try to catch as many errors as
possible, as early as possible:

     sub spoof_read_file
     {
        my ($opt, $args) = @_;
        warn ("$opt option requires an argument\n"), return 0
           unless @$args;
        my $file = shift @$args;
        warn ("$file does not exist or is not readable\n"), return 0
           unless -r $file;
        return 1;
     }

   Finally, you can frequently merge the "real" and "spoof" callback into
one subroutine:

     sub read_file
     {
        my ($opt, $args, $spoof) = @_;

     warn ("$opt option requires an argument\n"), return 0 unless @$args;
     my $file = shift @$args;
     warn ("$file does not exist or is not readable\n"), return 0
        unless -r $file;
     return 1 if $spoof;
     open (FILE, $file) ||
        (warn ("$file: $!\n"), return 0);
     push (@filedata, <FILE>);
     close (FILE);
     return 1;
        }

   And then, when specifying the replacement callback to `SetSpoofCodes',
just create an anonymous sub that calls read_file with `$spoof' true:

     &Getopt::Tabular::SetSpoofCodes
        (-read_file => sub { &read_file (@_[0,1], 1) });

     Even though this means a bigger and more complicated callback, you only
     need I<one> such callback -- the alternative is to carry around both
     C<read_file> and C<spoof_read_file>, which might do redundant processing
     of the argument list.

AUTHOR
======

   Greg Ward <greg@bic.mni.mcgill.ca>

   Started in July, 1995 as ParseArgs.pm, with John Ousterhout's
Tk_ParseArgv.c as a loose inspiration.  Many many features added over the
ensuing months; documentation written in a mad frenzy 16-18 April, 1996.
Renamed to Getopt::Tabular, revamped, reorganized, and documentation
expanded 8-11 November, 1996.

   Copyright (c) 1995-97 Greg Ward. All rights reserved.  This is free
software; you can redistribute it and/or modify it under the same terms as
Perl itself.

BUGS
====

   The documentation is bigger than the code, and I still haven't covered
option patterns or extending the type system (apart from pattern types).
Yow!

   No support for list-valued options, although you can roll your own with
call options.  (See the demo program included with the distribution for an
example.)

   Error messages are hard-coded to English.

yet another command line argument parsing module
************************************************

NAME
====

   Getopt::Tiny - yet another command line argument parsing module

SYNOPSIS
========

     use Getopt::Tiny;

     my $arg = 'default value';
     my @list;
     my %hash;
     my $flag;
     my %set;

     # begin usage info
     my (%flags) = (
     	'argx' => \$arg,	# set a parameter
     	'listx' => \@list,	# fill in a list
     	'hashx' => \%hash,	# set key/value pairs
     );
     my (%switches) = (
     	'flagx' => \$flag,	# on or off
     }
     # end usage info

     getopt(\@ARGV, \%flags, \%switches);
     Getopt::Tiny::usage(__FILE__, \%flags, \%switches);

   or

     use Getopt::Tiny;
     %flags = ...
     %switches = ...
     getopt()
     Getopt::Tiny::usage();

DESCRIPTION
===========

   Getopt::Tiny is yet another argument parsing module.  The results of
the argument parsing are stored by using references that were provided to
getopt().  Usage information is automatically generated.  Getopt::Tiny
expects all arguments to be switches - no trailing list of files.

   Getopt::Tiny can either call an existing usage() function or it can use
it's own builtin one.   It trys to use the existing one by default.  If
that fails, it will use its own.  It figures out how to describe things by
reading the file where call to getopt() originated.  In the file where
getopt is called, the following two lines must appear exactly as written
here:

     # begin usage info
     # end usage info

   Between these two lines, lines that match the pattern of:

     'someflag' => ...  # a description

   will be noticed and used to document each flag individually.

   The usage() function of Getopt::Tiny can be called on it's own.  It can
either have it's arguments given to it explicitly or it can default them
like getopt().

   If a usage function is provided, it will be called with one parameter:
the argument that didn't parse.

ARGUMENT TYPES
==============

   There are four types of arguments that Getopt::Tiny supports.

switches
     Switches are either on or off. In the example in the synopsis, the
     variable $flag will be respectively set to 1 or 0 if `-flagx' or
     `-noflagx' appears in the argument list .

parameter
     Parameters have values.  In the example above, the $arg variable will
     be set to whatever follows `-argx' in the argument list.

list
     List flags can have multiple values.  If present, they will have at
     least one value.  In the example above, if the argument list
     containted `qw(-listx a b c -listx -d e -argx foo)', the array @list
     would end up with a value of `qw(a b c -d e)'.

hash
     Hashes have multiple key-value pairs.  If present they will have at
     least one value.  In the exmaple above, if the argument list
     containted `qw(-hashx a=b c=d -hashx -e=f -argx bar)', the hash %hash
     would end up with a value of `(a => b, c => d, -e => f)'.

DEFAULT PARAMETERS
==================

   If no arguments are given to getopt() then it assumes that the argument
list to parse is `\@ARGV' and that the flags and switch references are
`\%::flags' and `\%::switches' respectively.

   Likewise, if no arguments are given to usage() then it assumes that
filename to look for information in is `(caller(0))[1]' and that the flags
and switches are as above.

COPYRIGHT
=========

   Copyright (C) 1998, David Muir Sharnoff.   All rights reserved.
License hearby granted for anyone to use this module at their own risk.
Please feed useful changes back to muir@idiom.com.

set constants from command line options
***************************************

NAME
====

   Getopt::constant - set constants from command line options

SYNOPSIS
========

     # Assuming @ARGV is: ('-foo=9,8,7', '-bar', 'wakawaka.txt')
     use Getopt::constant (
       ':prefix' => 'C_',
       'foo' => [3,5],
       'bar' => 0,
       ':usage' =>
     "Usage:
     thingamabob
       -foo=one,two,three  :  fooey on these items
       -bar                :  enable barriness
     ",
     );
     # @ARGV is now 'wakawaka.txt', and you've now got
     #  a constant C_foo with value (9,8,7)
     #  and a constant C_bar with value 1

DESCRIPTION
===========

   Other command-line options processing modules (like Getopt::Std) parse
command-line arguments (from @ARGV) and set either variables or hash
entries based on them.  This module, however, parses command-line
arguments into constants which are put into the current package.

   You provide default values for each constant in the list that you pass
in the "use Getopt::constant (...);" statement.  Values can be a scalar
(in which case you will get a scalar constant) or an arrayref (in which
case you will get a list constant).

OPTIONS
=======

":prefix" => STRING,
     Constants are named by putting the value of the ":prefix" option
     (which can be empty-string) before the option name.  For an example,
     read the SYNOPSIS section above.

     Default is empty-string, "".  A common useful value you should
     consider is `"C_"'.

     You should not use a value, like "*" or "-" or "1" that can't begin a
     legal Perl symbol name.

":permissive" => BOOL,
     Normally, if Getopt::constant is parsing the options in @ARGV and
     finds an unknown item, this causes a fatal error.  For example, if
     your call to `use Getopt::constant (...)' didn't mention a

          'foo' => some_value,

     then when Getopt::constant gets to parsing "-foo=1", it would exit
     with a message to STDERR, as determined by the value of the ":usage"
     parameter.

     However, if the ":permissive" parameter is set to a true value, then
     unknown items are simply ignored.

     The default value is 0.

":usage" => VALUE,
     When Getopt::constant hits a command-line switch that attempts to set
     an option that's not in its list of known options, this is considered
     a fatal error, unless the ":permissive" option has been set to true
     (in which case it is simply ignored).

     What happens in the case of a fatal error is controlled by the
     ":usage" parameter's value:

     If it's a string, then on STDERR we print "Unknown options: ", and the
     list of the unknown options, and a newline and then the string value
     of the ":usage" parameter (which should presumably be something
     explaining what the valid parameters are, and what they mean); and
     then the program exits.

     If it's undef (which is the default value), then on STDERR we print
     "Unknown options: ", and the list of the unknown options and a
     newline, and then on the next line, the list of all permitted options;
     and then the program exits.

     If it's a code ref, then the code ref is called with three options: a
     reference to the array of unknown options found, a reference to the
     array of options allowed, and a reference to the hash consisting of
     the elements passed in the '`use Getopt::constant (...)';' statement.
     For example, if you said:

          use Getopt::constant (
            ':prefix' => 'C_',
            'foo' => [3,5],
            'bar' => 0,
            ':usage' => sub {...},
          );

     and there's a "-baz" in @ARGV, then the specified sub will be called
     as

          $thatsub->(
            ['baz'],
            ['foo','bar'],
            { ':prefix' => 'C_',
              'foo' => [3,5],
              'bar' => 0,
              ':usage' => sub {...},
            }
          );

     and then once that sub returns, the program exits.

":retain" => BOOL,
     This controls whether (1) or not (0) parsed options are removed from
     @ARGV.

     Default is 0 - to remove parsed items from @ARGV.

     If you want to parse the options in @ARGV first with Getopt::constant
     and then with something like Getopt::Std, you should consider:

          ":retain" => 1,  ":retain" => 1,

     (Although note that this is only a partial solution: consider an
     argument list of `qw(-foo 13 -bar)' which you want to be parsed by
     Getopt::constant and then by Getopt::Long.  Getopt::Long will parse it
     as you expect, but Getopt::constant has a more restricted view of
     switch parsing and will stop parsing at "13".)

":*whatever*" => any_value,
     Assignments to parameters beginning with ":", other than the ones
     mentioned above, have no effect.

"option_name" => [ ...list elements... ]
     Specifies a default list value for that option.  The option name
     should be a legal Perl symbol name (e.g., "thing_1", "Thing_1", and
     "THING_1" are all okay - "thing 1", "thing-1", "1thing" are not.)

"option_name" => value
     Specifies a default scalar value for that option.  The option name
     should be a legal Perl symbol name.

SWITCH PARSING
==============

   As Getopt::constant parses thru the items in @ARGV, it expects @ARGV to
start with some number of switches; it stops parsing when it hits the
first non-switch item.

   A switch consists of one of the following syntaxes:

-foo or -foo
     This sets option "foo" to 1 if it's to be a scalar constant (as it
     usually is), or sets "foo" to [1] if it's to be a list constant.
     (Which it is, is determined by whether you said "foo => VALUE" or "foo
     => [...]" in your parameters to "use Getopt::constant (...)").

-foo=VALUE or -foo=VALUE
     This sets option "foo" to VALUE if it's to be a scalar constant (as
     it usually is); or if it's to be a list constant, then it's set to:

          split(",", VALUE, -1)

     Note that VALUE may be empty-string.  I.e., "-foo=", is a legal
     switch which sets foo to empty-string, or empty-list if foo is to be
     a list constant.

-
     (That's two hyphens in a row, not one.)  This signals the end of the
     parameter list.

   Note that switches of the form:

     % progname.pl -foo VALUE

   are not recognized; you need to express that as one of:

     % progname.pl -foo=VALUE
     % progname.pl --foo=VALUE

SEE ALSO
========

   See Constant, Getopt/Long,
Getopt/Std,

WHY?
====

   Consider this:

     use Getopt::constant ('DEBUG' => 0);
       ...
     print "Starting doing things...\n" if DEBUG;
       ...
     foreach $thing (@many_things) {
       print " About to do things with $thing\n" if DEBUG > 1;
       ...
     }
       ...
     DEBUG and printf "Done doing things at %s after %s sec.\n",
       scalar(localtime), time - $^T;

   What's the point of doing this, as opposed to using Getopt::Std to set
a `$DEBUG' that we'd use everywhere where we have a DEBUG above?  Well,
every time an expression consisting of a variable, or involving a variable
(like "`$DEBUG > 1'") is encountered, it has to be evaluated.  That means
that in every iteration of the loop, the expression "`$DEBUG > 1'" would
have to be evaluated anew, since Perl has no assurance that `$DEBUG''s
value can't have changed since the last iteration.  But, with constants,
or expressions involving constants, Perl evaluates them only once, at
compile time.  So if Perl knows that the constant DEBUG has the value 2,
then the expression

     print " About to do things with $thing\n" if DEBUG > 1;

   turns into:

     print " About to do things with $thing\n";

   as Perl compiles it.

   But more importantly, if Perl knows DEBUG is 0 (or anything such that
"DEBUG > 1" is false) then the above statement is actually removed from
the in-memory compiled version of the program, before it is actually run.

   Incidentally, you can, with some doing, use any other Getopt library to
make constants, using something like:

     #...Assuming an @ARGV of qw( -D4 -x9 stuff )...

     use strict;
     my %opts;
     BEGIN { # constants need to be made at compile time!
       %opts = ( 'D' => 0, 'y' => 'nope', 'x' => 3 ); # default values

       use Getopt::Std ();
       Getopt::Std::getopt('Dxy', \%opts);

       require constant;
       # Now make constants from whatever we want:
       constant->import('D',   $opts{'D'});
       constant->import('C_y', $opts{'y'});
     }
     print "ARGV is @ARGV\n";
     printf "D is %s, C_y is %s, and opts-x is %s\n", D, C_y, $opts{'x'};

   That prints:

     ARGV is stuff
     D is 4, C_y is nope, opts-x is 9

   That's obviously a bit circuitous, but it's quite doable.

COPYRIGHT AND DISCLAIMER
========================

   Copyright (c) 2001 Sean M. Burke.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   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.

AUTHOR
======

   Sean M. Burke, sburke@cpan.org

Perl extension for emulating gettext-related API.
*************************************************

NAME
====

   Gettext - Perl extension for emulating gettext-related API.

SYNOPSIS
========

     use Gettext;

DESCRIPTION
===========

   Gettext.pm emulates the gettext library routines in Perl, although it
calls the external utility program gettext to actually read .mo files.

   man gettext on Solaris has pretty good documentation.

   The steps to use this module are:

   * install the gnu gettext package if necessary (not needed on Solaris
     or Red Hat)

   * set TEXTDOMAINDIR, LANGUAGE, LANG, and LC_* if needed in your env.

   * use xgettext on your script that contains gettext calles  to make the
     .po (portable message object) file, run msgfmt to make the .mo
     (message object) file, and move the .mo file to where you want it,
     normally $TEXTDOMAINDIR/lang/LC_MESSAGES.

   * call setlocale before calling these functions.

   use Gettext;

   my $gt = new Gettext;

   $gt->textdomain('domainname');

   $gt->bindtextdomain('domainname', 'dirname');

   $gt->gettext('msgid');

   $gt->dgettext('domainname', 'msgid');

   $gt->dcgettext('domainname', 'msgid', 'category (locale)');

SAMPLE
======

   use strict;

   use diagnostics;

   use POSIX 'locale_h';

   use locale;

   use Gettext;

     setlocale(LC_CTYPE, 'es_ES');

     my $gt = new Gettext();

     $gt->bindtextdomain("messages", "/root/work");

     print $gt->gettext("flower"),"\n";
     print $gt->gettext("yellow"),"\n";

     print $gt->dgettext("messages", "flower"),"\n";
     print $gt->dgettext("messages", "yellow"),"\n";

     print $gt->dcgettext("messages", "flower", "fr_FR"),"\n";
     print $gt->dcgettext("messages", "yellow", "fr_FR"),"\n";

     print $gt->textdomain(),"\n";
     print $gt->textdomain(''),"\n";

   Tested on Solaris 2.6 and Red Hat Linux 6.0

AUTHOR
======

   James Briggs, james@rf.net

SEE ALSO
========

   perldoc perllocale

TO DO
=====

   Gettext.pm calls the external gettext utility program, but someday
should have an internal routine to directory read .mo files.

Generate Perl source from a Glade XML project file.
***************************************************

NAME
====

   Glade::PerlGenerate - Generate Perl source from a Glade XML project
file.

SYNOPSIS
========

   The simplest way to run Glade::PerlGenerate is to use the supplied
script 'glade2perl' that is also called by Glade when you hit the 'Build'
button.

     glade2perl Project.glade

   Otherwise you can control every aspect of the source generation by
calling the same methods that glade2perl calls:

     use Glade::PerlGenerate;

     Glade::PerlGenerate->options(

     'author'        => 'Dermot Musgrove <dermot.musgrove\@virgin.net>',
     'description'   => "This is an example of the Glade-Perl
     source code generator",
     'verbose'       => 2,
     'indent'        => '    ',
     'tabwidth'      => 4,
     'diag_wrap'     => 0,
     'write_source'  => 'True',
     'dont_show_UI'  => 'True',
     'autoflush'     => 'True',
     'use_modules'   => 'Example::BusForm_mySUBS',
     'log_file'      => 'Test.log',

     );

   Then to generate the UI defined in a file

     Glade::PerlGenerate->Form_from_Glade_File(

     'glade_filename'=> "Example/BusForm.glade"

     );

   OR if you want to generate  the UI directly from an XML string

     Glade::PerlGenerate->Form_from_XML(

     'xml'           => $xml_string,
     'use_modules'   => ['Example::Project_mySUBS']

     );

DESCRIPTION
===========

   Glade::PerlGenerate reads a <GTK-Interface> definition from a Glade
file (or a string) using XML::Parser, converts it into a hash of hashes
and works its way through this to show the UI using Gtk-Perl bindings.
The module can also optionally generate Perl source code to show the UI
and handle the signals. Any signal handlers that are specified in the
project file but not visible at Generate time will be hijacked to show a
'missing_handler' message_box and a stub for it will be defined in the the
UI class for dynamic AUTOLOAD()ing.

   The stub will simply show a message_box to prove that the handler has
been called and you can write your own with the same name in another
module. You then quote this module to the next Generate run and
Glade::PerlGenerate will use these handlers and not define stubs.

USER OPTIONS
============

   These options can be specified using the Glade::PerlGenerate->options()
method or with the same name in the options XML files.

   Boolean values can be specified as True|true|Yes|yes|1 or
False|false|No|no|0|"|undef

Project options
---------------

author
     The author's name to appear in generated sources. Backslash-escape any
     @ signs so that they are passed through perl strings correctly.  The
     default is synthesised from some of the values returned by Perl's
     gethostbyname "localhost"

     e.g. 'Dermot Musgrove <dermot.musgrove\@virgin.net'

version - default is 0.01
     Version number to use in generated sources.

     e.g. '0.53-pre1'

date - defaults to build time.
     The date to show in sources.

     e.g. 'Christmas eve 2001'

copying - default is '# Unspecified copying policy, please contact the author\n# '
     Copying text to include in generated sources. Make sure that they are
     specified as perl # comments so that the generated source is valid.

description - default is 'No description'
     A general description of the app to appear in sources and about_boxes

     e.g 'This is a reference form\n that contains all the widgets that
     Glade knows about'

use_modules - default means don't use() any other modules
     When specified as an arg to the options() method, an anonymous array
     of modules to be use()d in the generated classes.

     In an options file, a newline separated list of modules to be use()d
     by generated classes

     e.g ['Existing::mySUBS', 'Some::Other::Module']

allow_gnome - Default is read from the Glade project file
     Bool - whether or not to allow Gnome widgets in the generated source

site_options - Default is /etc/glade2perl.xml
     File name containing options for all projects on this site.  This
     option is only meaningful when set by Glade::PerlGenerate->options()
     although it is logged in the project_options file

user_options - Default is ~/.glade2perl.xml
     File name containing options for all projects in this user.  This
     option is only meaningful when set by Glade::PerlGenerate->options()
     although it is logged in the project_options file

project_options - Default means don't read or save a file
     Filename of project options to read and save.  This option is only
     meaningful when set by Glade::PerlGenerate->options() although it is
     logged in the project_options file

glade_encoding - default 'ISO-8859-1'
     Character encoding of Glade file

     eg 'ISO-8859-1'

glade2perl_encoding - default is glade_encoding option
     Character encoding of glade2perl.xml options files.  This option is
     only meaningful when set by Glade::PerlGenerate->options() although
     it is saved in the file itself.

     eg 'ISO-8859-1'

From the Glade file
-------------------

name
     Name to use for the generated packages. Any spaces, dots or minuses
     will be removed from the name as these are not valid in perl package
     names.

source_directory -
     Directory to contain the generated sources

pixmaps_directory -
     Directory to search for pixmaps

The UI
------

dont_show_UI - default is to show the UI and wait for user action
     Bool - whether to show the UI during the Build. glade2perl sets this
     to 0 so that the UI is not shown.

logo - default 'Logo.xpm'
     Use the specified logo in about boxes or if any pixmap is missing

my_perl_gtk - Default is to use Gtk-Perl's version number
     Version number of my Gtk-Perl module. This overrides the number
     reported by Gtk::Perl so that CVS fixes can be used.

     '0.6123'   I have CPAN version 0.6123

     '19991001' I have the gnome.org CVS version of 'gnome-perl' that I
     downloaded on Oct 1st 1999

my_gnome_libs - Default is to use gnome-libs version no
     Version number of my gnome-libs. This overrides the number reported by
     `gnome-libs-config -version` so that CVS fixes can be used.

     '1.0.58'   I have the released version 1.0.58 of 'gnome-libs'

     '19991001' I have the gnome.org CVS version of 'gnome-libs' that I
     downloaded on Oct 1st 1999

Source code options
-------------------

indent - default is 4 spaces
     Indent to use for 'nested' source code

          e.g. '  ' (2 spaces)

tabwidth - default is 8
     Number of spaces to replace with a tab in generated source code

     e.g. 4

write_source - default is no source
     Where to write the source code. glade2perl sets this to 1.

     'STDOUT'  Write sources to STDOUT but there will be nothing to run
     later

     'File.pm' Write sources to File.pm They will not run from here and
     you must cut-paste them

     True - write the sources to standard files.

     undef     Don't write source code

hierarchy - default means don't generate any hierarchy
     ...widget... generates a widget hierarchy eg
     $hier->{'vbox2'}{'table1'}...

     ...class...  generates a class hierarchy eg
     $hier->{'GtkVBox'}{'vbox2'}{'GtkTable'}{'table1'}...

     ...both...   both widget and class hierarchies generated

     e.g. 'widget_hierarchy'

style - default AUTOLOAD
     AUTOLOAD - OO class implements missing signal handlers with an
     AUTOLOAD sub

     Libglade - generate libglade code and signal handlers

     split - generates each class in its own .pm file.

source_LANG - default $ENV{'LANG'}
     Which language do we want the source to be documented in?

     e.g. 'pt_BR'

Diagnostics options
-------------------

verbose - default is 2
     Level of verbosity of diagnostics

          0  - Quiet/no diagnostics (glade2perl uses this)
          1  - Main project messages and errors only
          2  - also warnings
          4  - also project options and more diagnostics
          6  - also source code as it is generated
          8  - also lookups and conversions
          10 - everything (more than you want?)

diag_wrap - default is 0 (no breaks)
     Maximum diagnostics message line length (approximate)

          0   - no breaks (not easy to read on 80 column displays).
          80  - should display comfortably on 80 column display
          132 - Wrap diagnostics so that lines are about 132 characters long

log_file - Default is to use STDOUT
     Write diagnostics and errors to filename if verbose > 0 glade2perl
     can set this to /path/to/glade/file.glade2perl.log

     e.g. '/home/dermot/Devel/Test/Project1.glade2perl.log'

autoflush - default is False (write at end of block)
     Bool - whether to autoflush the file output.  This is really to force
     errors to be shown by my editor's shellout in the case of a failure.

benchmark - default means don't add time to the diagnostic messages
     Bool - True will cause the time to prefix all diagnostics messages

diag_LANG - default $ENV{'LANG'}
     Which language do we want the diagnostic messages in?

     e.g. 'de'

Run History - for internal use only
-----------------------------------

start_time
     Time that this run started

options_set - default 'DEFAULT'
     Who set the options last.

glade_proto
     This is where Glade::PerlGenerate stores the Glade proto

glade2perl_version
     Version of Glade::PerlGenerate that wrote this file.

glade2perl_logo - default 'glade2perl_logo.xpm'
     Name of the Glade::PerlGenerate logo pixmap used.

EXAMPLE OPTIONS FILES
=====================

This is a typical project_options file  ~/Devel/Glade-Perl/Example/Reference/Existing/Reference.glade2perl.xml
--------------------------------------------------------------------------------------------------------------

     <?xml version="1.0" encoding="ISO-8859-1"?>
     <G2P-Options>
       <allow_gnome>1</allow_gnome>
       <autoflush>1</autoflush>
       <debug>1</debug>
       <description>A reference form containing
     all possible Gtk and Gnome widgets</description>
       <dont_show_UI>1</dont_show_UI>
       <glade2perl_encoding>ISO-8859-1</glade2perl_encoding>
       <glade2perl_version>0.53</glade2perl_version>
       <hierarchy>NONE</hierarchy>
       <log_file>Existing/Reference.glade2perl.log</log_file>
       <options_set>Glade/Build Source</options_set>
       <project_options>Existing/Reference.glade2perl.xml</project_options>
       <start_time>Sat Apr  8 15:29:12 BST 2000</start_time>
       <style>notLibglade</style>
       <tabwidth>8</tabwidth>
       <use_modules>Existing::Reference_mySUBS</use_modules>
       <user_options>/home/dermot/.glade2perl.xml</user_options>
       <version>0.53</version>
     </G2P-Options>

This what I have in my user_options file  ~/.glade2perl.xml
-----------------------------------------------------------

     <G2P-Options>
       <author>Dermot Musgrove <dermot.musgrove\@virgin.net></author>
       <diag_LANG>en</diag_LANG>
       <diag_wrap>0</diag_wrap>
       <indent>  </indent>
       <source_LANG>en</source_LANG>
       <style>AUTOLOAD</style>
       <tabwidth>4</tabwidth>
       <write_source>1</write_source>
     </G2P-Options>

This what I have in my site_options file  /etc/glade2perl.xml
-------------------------------------------------------------

     <G2P-Options>
       <copying># This library is released under the same conditions as Perl, that
     # is, either of the following:
     #
     # a) the GNU General Public License as published by the Free
     # Software Foundation; either version 1, or (at your option) any
     # later version.
     #
     # b) the Artistic License.
     #
     # If you use this library in a commercial enterprise, you are invited,
     # but not required, to pay what you feel is a reasonable fee to cpan.org
     # at http://www.perl.org or contact donors\@perlmongers.org for details.
     # </copying>
       <my_perl_gtk>20000301</my_perl_gtk>
     </G2P-Options>

ERRORS and WARNINGS
===================

   The module will report several errors or warnings that warn of problems
with the Glade file or other unexpected occurences. These are to help me
cater for new widgets or widget properties and not because Glade creates
inconsistent project files but they do point out errors in hand-edited XML.

FILES GENERATED
===============

projectUI.pm
     A perl class/module (projectUI.pm) that contains a class for each
     toplevel window/dialog, each with a standard method (new) that will
     construct the UI.

projectSIGS.pm
     A perl class/module (projectSIGS.pm) that contains a class for each
     toplevel window/dialog, with skeleton signal handlers for any that
     were missing at build time.

     If the 'split' style is used, the typical filename will be
     projectSIGS_class .pm (one file per class).

project.pm
     A perl class/module (project.pm) that is a copy of projectSIGS.pm for
     you to edit to become your "App".  You can generate the UI again and
     again without changing any of your signal handlers as it is only
     written the first time through (if missing). If you add signal
     definitions to your Glade project, skeletons for the handlers will be
     generated in the projectSIGS.pm file and you can cut-and-paste them
     from there into the relevant class in the project.pm "App" module.

     If the 'split' style is used, the typical filename will be
     project_class .pm (one file per class).

Subproject.pm
     A perl class/module (Subproject.pm) that subclasses project.pm that
     you can edit to subclass your "App".  You can generate the UI again
     and again without changing any of your signal handlers as it is only
     written the first time through (if missing).

projectLIBGLADE.pm
     An optional perl class/module (projectLIBGLADE.pm) that initialises
     the Libglade bindings and has skeleton signal handlers that you can
     edit to form your "App".  You can generate the UI again and again
     without changing any of your signal handlers as it is only written
     the first time through (if missing).

SEE ALSO
========

   Documentation that came with the module is in Directory 'Documentation'
in files README, Changelog, FAQ, TODO, NEWS, ROADMAP etc.

   The test file for 'make test' is test.pl which is runnable and has
examples of user options.

   A Perl script to generate source code from the Glade 'Build' button or
menuitem is in file 'Example/glade2perl'.  You can also call this script
from the command line.

   A module that subclasses the test example is in file Example/SubBus.pm.
This module will use (inherit or subclass) the generated perl classes and
also use the supplied signal handlers module (Example/BusForm_mySUBS.pm)

Perl module interface to the GNU Privacy Guard.
***********************************************

NAME
====

   GnuPG - Perl module interface to the GNU Privacy Guard.

SYNOPSIS
========

     use GnuPG qw( :algo );

     my $gpg = new GnuPG();

     $gpg->encrypt(  plaintext	=> "file.txt",	output	    => "file.gpg",
     		    armor	=> 1,		 sign	=> 1,
     		    passphrase  => $secret );

     $gpg->decrypt( ciphertext	=> "file.gpg",	output	    => "file.txt" );

     $gpg->clearsign( plaintext => "file.txt", output => "file.txt.asc",
     		     passphrase => $secret,   armor => 1,
     		    );

     $gpg->verify( signature => "file.txt.asc", file => "file.txt" );

     $gpg->gen_key( name => "Joe Blow",	    comment => "My GnuPG key",
     		   passphrase => $secret,
     		    );

DESCRIPTION
===========

   GnuPG is a perl interface to the GNU Privacy Guard. It uses the shared
memory coprocess interface that gpg provides for its wrappers. It tries
its best to map the interactive interface of the gpg to a more
programmatic model.

API OVERVIEW
============

   The API is accessed through methods on a GnuPG object which is a
wrapper around the *gpg* program.  All methods takes their argument using
named parameters, and errors are returned by throwing an exception (using
croak).  If you wan't to catch errors you will have to use eval.

   There is also a tied file handle interface which you may find more
convenient for encryption and decryption. See GnuPG::Tie(3) for details.

CONSTRUCTOR
===========

new ( [params] )
----------------

   You create a new GnuPG wrapper object by invoking its new method.  (How
original !).  The module will try to finds the *gpg* program in your path
and will croak if it can't find it. Here are the parameters that it
accepts :

gnupg_path
     Path to the *gpg* program.

options
     Path to the options file for *gpg*. If not specified, it will use the
     default one (usually `~/.gnupg/options').

homedir
     Path to the *gpg* home directory. This is the directory that contains
     the default options file, the public and private key rings as well as
     the trust database.

trace
     If this variable is set to true, *gpg* debugging output will be sent
     to stderr.

     Example: my $gpg = new GnuPG();

METHODS
=======

gen_key( [params] )
-------------------

   This methods is used to create a new gpg key pair. The methods croaks
if there is an error. It is a good idea to press random keys on the
keyboard while running this methods because it consumes a lot of entropy
from the computer. Here are the parameters it accepts :

     Ex: $gpg->

algo
     This is the algorithm use to create the key. Can be ELGAMAL,
     DSA_ELGAMAL or DSA. It defaults to DSA_ELGAMAL. To import those
     constant in your name space, use the :algo tag.

size
     The size of the public key. Defaults to 1024. Cannot be less than 768
     bits, and keys longer than 2048 are also discouraged. (You *DO* know
     that your monitor may be leaking sensitive informations ;-).

valid
     How long the key is valid. Defaults to 0 or never expire.

name
     This is the only mandatory argument. This is the name that will used
     to construct the user id.

email
     Optional email portion of the user id.

comment
     Optional comment portion of the user id.

passphrase
     The passphrase that will be used to encrypt the private key. Optional
     but strongly recommended.

     Example: $gpg->gen_key( algo => DSA_ELGAMAL, size => 1024,
     			    name => "My name" );

import_keys( [params] )
-----------------------

   Import keys into the GnuPG private or public keyring. The method croaks
if it encounters an error. It returns the number of keys imported.
Parameters :

keys
     Only parameter and mandatory. It can either be a filename or a
     reference to an array containing a list of files that will be
     imported.

     Example: $gpg->import_keys( keys => [ qw( key.pub key.sec ) ] );

export_keys( [params] )
-----------------------

   Exports keys from the GnuPG keyrings. The method croaks if it
encounters an error. Parameters :

keys
     Optional argument that restricts the keys that will be exported.  Can
     either be a user id or a reference to an array of userid that
     specifies the keys to be exported. If left unspecified, all keys will
     be exported.

secret
     If this argument is to true, the secret keys rather than the public
     ones will be exported.

all
     If this argument is set to true, all keys (even those that aren't
     OpenPGP compliant) will be exported.

output
     This argument specifies where the keys will be exported. Can be either
     a file name or a reference to a file handle. If not specified, the
     keys will be exported to stdout.

armor
     Set this parameter to true, if you want the exported keys to be ASCII
     armored.

     Example: $gpg->export_keys( armor => 1, output => "keyring.pub" );

encrypt( [params] )
-------------------

   This method is used to encrypt a message, either using assymetric or
symmetric cryptography. The methods croaks if an error is encountered.
Parameters:

plaintext
     This argument specifies what to encrypt. It can be either a filename
     or a reference to a file handle. If left unspecified, STDIN will be
     encrypted.

output
     This optional argument specifies where the ciphertext will be output.
     It can be either a file name or a reference to a file handle. If left
     unspecified, the ciphertext will be sent to STDOUT.

armor
     If this parameter is set to true, the ciphertext will be ASCII
     armored.

symmetric
     If this parameter is set to true, symmetric cryptography will be used
     to encrypt the message. You will need to provide a passphrase
     parameter.

recipient
     If not using symmetric cryptography, you will have to provide this
     parameter. It should contains the userid of the intended recipient of
     the message. It will be used to look up the key to use to encrypt the
     message.

sign
     If this parameter is set to true, the message will also be signed. You
     will probably have to use the passphrase parameter to unlock the
     private key used to sign message. This option is incompatible with
     the symmetric one.

local-user
     This parameter is used to specified the private key that will be used
     to sign the message. If left unspecified, the default user will be
     used. This option only makes sense when using the sign option.

passphrase
     This parameter contains either the secret passphrase for the symmetric
     algorithm or the passphrase that should be used to decrypt the private
     key.

     Example: $gpg->encrypt( plaintext => file.txt, output => "file.gpg",
     			    sign => 1, passphrase => $secret
     			    );

sign( [params] )
----------------

   This method is used create a signature for a file or stream of data.
This method croaks on errors. Parameters :

plaintext
     This argument specifies what  to sign. It can be either a filename or
     a reference to a file handle. If left unspecified, the data read on
     STDIN will be signed.

output
     This optional argument specifies where the signature will be output.
     It can be either a file name or a reference to a file handle. If left
     unspecified, the signature will be sent to STDOUT.

armor
     If this parameter is set to true, the signature will be ASCII armored.

passphrase
     This parameter contains the secret that should be used to decrypt the
     private key.

local-user
     This parameter is used to specified the private key that will be used
     to make the signature . If left unspecified, the default user will be
     used.

detach-sign
     If set to true, a digest of the data will be signed rather than the
     whole file.

     Example: $gpg->sign( plaintext => "file.txt", output => "file.txt.asc",
     			 armor => 1,
     			 );

clearsign( [params] )
---------------------

   This methods clearsign a message. The output will contains the original
message with a signature appended. It takes the same parameters as the
sign method.

verify( [params] )
------------------

   This method verifies a signature against the signed message. The
methods croaks if the signature is invalid or an error is encountered. If
the signature is valid, it returns an hash with the signature parameters.
Here are the method's parameters :

signature
     If the message and the signature are in the same file (i.e. a
     clearsigned message), this parameter can be either a file name or a
     reference to a file handle. If the signature doesn't follows the
     message, than it must be the name of the file that contains the
     signature.

file
     This is a file name or a reference to an array of file names that
     contains the signed data.

   When the signature is valid, here are the elements of the hash that is
returned by the method :

sigid
     The signature id. This can be used to protect against replay attack.

date
     The data at which the signature has been made.

timestamp
     The epoch timestamp of the signature.

keyid
     The key id used to make the signature.

user
     The userid of the signer.

fingerprint
     The fingerprint of the signature.

trust
     The trust value of the public key of the signer. Those are values that
     can be imported in your namespace with the :trust tag. They are
     (TRUST_UNDEFINED, TRUST_NEVER, TRUST_MARGINAL, TRUST_FULLY,
     TRUST_ULTIMATE).

     Example : my $sig = $gpg->verify( signature => "file.txt.asc",
     				      file => "file.txt" );

decrypt( [params] )
-------------------

   This method decrypts an encrypted message. It croaks, if there is an
error while decrypting the message. If the message was signed, this method
also verifies the signature. If decryption is sucessful, the method either
returns the valid signature parameters if present, or true. Method
parameters :

ciphertext
     This optional parameter contains either the name of the file
     containing the ciphertext or a reference to a file handle containing
     the ciphertext. If not present, STDIN will be decrypted.

output
     This optional parameter determines where the plaintext will be stored.
     It can be either a file name or a reference to a file handle.  If left
     unspecified, the plaintext will be sent to STDOUT.

symmetric
     This should be set to true, if the message is encrypted using
     symmetric cryptography.

passphrase
     The passphrase that should be used to decrypt the message (in the case
     of a message encrypted using a symmetric cipher) or the secret that
     will unlock the private key that should be used to decrypt the
     message.

     Example: $gpg->decrypt( ciphertext => "file.gpg", output => "file.txt"
     			    passphrase => $secret );

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999,2000 iNsu Innovations. Inc.

   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.

SEE ALSO
========

   gpg(1) GnuPG::Tie(3)

GnuPG Fingerprint Objects
*************************

NAME
====

   GnuPG::Fingerprint - GnuPG Fingerprint Objects

SYNOPSIS
========

     # assumes a GnuPG::Key in $key
     my $fingerprint = $key->fingerprint->hex_data();

DESCRIPTION
===========

   GnuPG::Fingerprint objects are generally part of GnuPG::Key objects,
and are not created on their own.

OBJECT METHODS
==============

Initialization Methods
----------------------

new( *%initialization_args* )
     This methods creates a new object.  The optional arguments are
     initialization of data members; the initialization is done in a
     manner according to the method created as described in
     `"new_hash_init"', see Class/MethodMaker.

hash_init( *%args* ).
     This method works as described in `"new_hash_init"', see
     Class/MethodMaker.

OBJECT DATA MEMBERS
===================

   Note that these data members are interacted with via object methods
created using the methods described in `"get_set"', see
Class/MethodMaker, or `"object"', see
Class/MethodMaker.  Please read there for more
information.

hex_data
     This is the hex value of the fingerprint that the object embodies.

SEE ALSO
========

   See GnuPG/Key, Class/MethodMaker,

GnuPG handles bundle
********************

NAME
====

   GnuPG::Handles - GnuPG handles bundle

SYNOPSIS
========

     use IO::Handle;
     my ( $stdin, $stdout, $stderr,
          $status_fh, $logger_fh, $passphrase_fh,
        )
       = ( IO::Handle->new(), IO::Handle->new(), IO::Handle->new(),
           IO::Handle->new(), IO::Handle->new(), IO::Handle->new(),
         );

     my $handles = GnuPG::Handle->new
       ( stdin      => $stdin,
         stdout     => $stdout,
         stderr     => $stderr,
         status     => $status_fh,
         logger     => $logger_fh,
         passphrase => $passphrase_fh,
       );

DESCRIPTION
===========

   GnuPG::Handles objects are generally instantiated to be used in
conjunction with methods of objects of the class GnuPG::Interface.
GnuPG::Handles objects represent a collection of handles that are used to
communicate with GnuPG.

OBJECT METHODS
==============

Initialization Methods
----------------------

new( *%initialization_args* )
     This methods creates a new object.  The optional arguments are
     initialization of data members; the initialization is done in a
     manner according to the method created as described in
     `"new_hash_init"', see Class/MethodMaker.

hash_init( *%args* ).
     This method works as described in `"new_hash_init"', see
     Class/MethodMaker.

OBJECT DATA MEMBERS
===================

   Note that these data members are interacted with via object methods
created using the methods described in `"get_set"', see
Class/MethodMaker, or `"object"', see
Class/MethodMaker.  Please read there for more
information.

stdin
     This handle is connected to the standard input of a GnuPG process.

stdout
     This handle is connected to the standard output of a GnuPG process.

stderr
     This handle is connected to the standard error of a GnuPG process.

status
     This handle is connected to the status output handle of a GnuPG
     process.

logger
     This handle is connected to the logger output handle of a GnuPG
     process.

passphrase
     This handle is connected to the passphrase input handle of a GnuPG
     process.

command
     This handle is connected to the command input handle of a GnuPG
     process.

options
     This is a hash of hashrefs of settings pertaining to the handles in
     this object.  The outer-level hash is keyed by the names of the
     handle the setting is for, while the inner is keyed by the setting
     being referenced.  For example, to set the setting direct to true for
     the filehandle stdin, the following code will do:

          # assuming $handles is an already-created
          # GnuPG::Handles object, this sets all
          # options for the filehandle stdin in one blow,
          # clearing out all others
          $handles->options( 'stdin', { direct => 1 } );

          # this is useful to just make one change
          # to the set of options for a handle
          $handles->options( 'stdin' )->{direct} = 1;

          # and to get the setting...
          $setting = $handles->options( 'stdin' )->{direct};

          # and to clear the settings for stdin
          $handles->options( 'stdin', {} );

     The currently-used settings are as follows:

    direct
          If the setting direct is true for a handle, the GnuPG process
          spawned will access the handle directly.  This is useful for
          having the GnuPG process read or write directly to or from an
          already-opened file.

SEE ALSO
========

   See GnuPG/Interface, Class/MethodMaker,

Perl interface to GnuPG
***********************

NAME
====

   GnuPG::Interface - Perl interface to GnuPG

SYNOPSIS
========

     # A simple example
     use IO::Handle;
     use GnuPG::Interface;

     # settting up the situation
     my $gnupg = GnuPG::Interface->new();
     $gnupg->options->hash_init( armor   => 1,
     			      homedir => '/home/foobar' );

     # Note you can set the recipients even if you aren't encrypting!
     $gnupg->options->push_recipients( 'ftobin@uiuc.edu' );
     $gnupg->options->meta_interactive( 0 );

     # how we create some handles to interact with GnuPG
     my $input   = IO::Handle->new();
     my $output  = IO::Handle->new();
     my $handles = GnuPG::Handles->new( stdin  => $input,
                                        stdout => $output );

     # Now we'll go about encrypting with the options already set
     my @plaintext = ( 'foobar' );
     $gnupg->encrypt( handles => $handles );

     # Now we write to the input of GnuPG
     print $input @plaintext;
     close $input;

     # now we read the output
     my @ciphertext = <$output>;
     close $output;

     wait;

DESCRIPTION
===========

   GnuPG::Interface and it's associated modules are designed to provide an
object-oriented method for interacting with GnuPG, being able to perform
functions such as but not limited to encrypting, signing, decryption,
verification, and key-listing parsing.

How Data Member Accessor Methods are Created
--------------------------------------------

   Each module in the GnuPG::Interface bundle relies on Class::MethodMaker
to generate the get/set methods used to set the object's data members.
*This is very important to realize.*  This means that any data member
which is a list has special methods assigned to it for pushing, popping,
and clearing the list.

Understanding Bidirectional Communication
-----------------------------------------

   It is also imperative to realize that this package uses interprocess
communication methods similar to those used in IPC/Open3,
and `"Bidirectional Communication with Another Process"', see Perlipc (perl.info),
and that users of this package need to understand how
to use this method because this package does not abstract these methods
for the user greatly.  processes using these methods.  This package is not
designed to abstract this away (partly for security purposes) but rather
to simply creating a 'proper' call to GnuPG, and to implement key-listing
parsing.  Please see `"Bidirectional Communication with Another Process"',
see Perlipc (perl.info), to learn how to deal with these methods.

   Using this package to do message processing generally invovlves
creating a GnuPG::Interface object, creating a GnuPG::Handles object,
setting some options in its options data member, and then calling a method
which invokes GnuPG, such as *clearsign*.  One then interacts with with
the handles appropriately, as described in `"Bidirectional Communication
with Another Process"', see Perlipc (perl.info).

OBJECT METHODS
==============

Initialization Methods
----------------------

new( *%initialization_args* )
     This methods creates a new object.  The optional arguments are
     initialization of data members; the initialization is done in a
     manner according to the method created as described in
     `"new_hash_init"', see Class/MethodMaker.

hash_init( *%args* ).
     This methods work as described in `"new_hash_init"', see
     Class/MethodMaker.

Object Methods which use a GnuPG::Handles Object
------------------------------------------------

list_public_keys( % )
list_sigs( % )
list_secret_keys( % )
encrypt( % )
encrypt_symmetrically( % )
sign( % )
clearsign( % )
detach_sign( % )
sign_and_encrypt( % )
decrypt( % )
verify( % )
import_keys( % )
export_keys( % )
recv_keys( % )
send_keys( % )
     These methods each correspond directly to or are very similar to a
     GnuPG command described in `gpg' in this node.  Each of these methods
     takes a hash, which currently must contain a key of handles which has
     the value of a GnuPG::Handles object.  Another optional key is
     *gnupg_command_args* which should have the value of an array
     reference; these arguments will be passed to GnuPG as command
     arguments.  These command arguments are used for such things as
     determining the keys to list in the *export_keys* method.  *Please
     note that GnuPG command arguments are not the same as GnuPG options*.
     To understand what are options and what are command arguments please
     read `gpg' in this node and `gpg' in this node.

     Each of these calls returns the PID for the resulting GnuPG process.
     One can use this PID in a waitpid call instead of a wait call if more
     precise process reaping is needed.

     These methods will attach the handles specified in the handles object
     to the running GnuPG object, so that bidirectional communication can
     be established.  That is, the optionally-defined stdin, stdout,
     stderr, status, logger, and passphrase handles will be attached to
     GnuPG's input, output, standard error, the handle created by setting
     *status-fd*, the handle created by setting *logger-fd*, and the
     handle created by setting *passphrase-fd* respectively.  This tying
     of handles of similar to the process done in IPC::Open3.

     If you want the GnuPG process read or write directly to an
     already-opened filehandle, you cannot do this via the normal
     IPC::Open3 mechanisms.  In order to accomplish this, set the
     appropriate handles data member to the already-opened filehandle, and
     then set the option direct to be true for that handle, as described
     in `options', see GnuPG/Handles.  For example, to
     have GnuPG read from the file `input.txt' and write to `output.txt',
     the following snippet may do:

          my $infile  = IO::File->new( 'input.txt.' );
          my $outfile = IO::File->new( 'output.txt' );
          my $handles = GnuPG::Handles->new( stdin  => $infile,
                                             stdout => $outfile,
                                           );
          $handles->options( 'stdin'  )->{direct} = 1;
          $handles->options( 'stdout' )->{direct} = 1;

     If any handle in the handles object is not defined, GnuPG's input,
     output, and standard error will be tied to the running program's
     standard error, standard output, or standard error.  If the status or
     logger handle is not defined, this channel of communication is never
     established with GnuPG, and so this information is not generated and
     does not come into play.  If the passphrase data member handle of the
     handles object is not defined, but the the passphrase data member
     handle of GnuPG::Interface object is, GnupG::Interface will handle
     passing this information into GnuPG for the user as a convience.
     Note that this will result in GnuPG::Interface storing the passphrase
     in memory, instead of having it simply 'pass-through' to GnuPG via a
     handle.

Other Methods
-------------

get_public_keys( @search_strings )
get_secret_keys( @search_strings )
get_public_keys_with_sigs( @search_strings )
     These methods create and return objects of the type GnuPG::PublicKey
     or GnuPG::SecretKey respectively.  This is done by parsing the output
     of GnuPG with the option *with-colons* enabled.  The objects created
     do or do not have signature information stored in them, depending if
     the method ends in *_sigs*; this separation of functionality is there
     because of performance hits when listing information with signatures.

test_default_key_passphrase()
     This method will return a true or false value, depending on whether
     GnupG reports a good passphrase was entered while signing a short
     message using the values of the passphrase data member, and the
     default key specified in the options data member.

OBJECT DATA MEMBERS
===================

   Note that these data members are interacted with via object methods
created using the methods described in `"get_set"', see
Class/MethodMaker, or `"object"', see
Class/MethodMaker.  Please read there for more
information.

gnupg_call
     This defines the call made to invoke GnuPG.  Defaults to 'gpg'; this
     should be changed if 'gpg' is not in your path, or there is a
     different name for the binary on your system.

passphrase
     In order to lessen the burden of using handles by the user of this
     package, setting this option to one's passphrase for a secret key
     will allow the package to enter the passphrase via a handle to GnuPG
     by itself instead of leaving this to the user.  See also
     `passphrase', see GnuPG/Handles.

options
     This data member, of the type GnuPG::Options; the setting stored in
     this data member are used to determine the options used when calling
     GnuPG via any of the object methods described in this package.  See
     GnuPG/Options, for more information.

EXAMPLES
========

   The following setup can be done before any of the following examples:

     use IO::Handle;
     use GnupG::Interface;

     my @original_plaintext = ( "How do you doo?" );
     my $passphrsae = "Three Little Pigs";

     my $gnupg = GnupG::Interface->new();

     $gnupg->options->hash_init( armor    => 1,
                                 recipients => [ 'ftobin@uiuc.edu',
                                                 '0xABCD1234' ],
                                 meta_interactive( 0 ),
                               );

Encrypting
----------

     # We'll let standard error to to our standard error
     my ( $input, $output ) = ( IO::Handle->new(),
                                IO::Handle->new() );

     my $handles = GnupG::Handles->new( stdin    => $input,
                                        stdout   => $output );

     # this sets up the communication
     # Note that the recipients were specified earlier
     # in the 'options' data member of the $gnupg object.
     $gnupg->encrypt( handles => $handles );

     # this passes in the plaintext
     print $input @original_plaintext;

     # this closes the communication channel,
     # indicating we are done
     close $input;

     my @ciphertext = <$output>;  # reading the output

     wait;  # clean up the finished GnuPG process

Signing
-------

     # This time we'll catch the standard error for our perusing
     my ( $input, $output, $error ) = ( IO::Handle->new(),
                                        IO::Handle->new(),
                                        IO::Handle->new(),
     				   );

     my $handles = GnupG::Handles->new( stdin    => $input,
                                        stdout   => $output,
                                        stderr   => $error,
     				   );

     # indicate our pasphrase through the
     # convience method
     $gnupg->passphrase( $passphrase );

     # this sets up the communication
     $gnupg->sign( handles => $handles );

     # this passes in the plaintext
     print $input @original_plaintext;

     # this closes the communication channel,
     # indicating we are done
     close $input;

     my @ciphertext   = <$output>;  # reading the output
     my @error_output = <$error>;   # reading the error

     close $output;
     close $error;

     wait;  # clean up the finished GnuPG process

Decryption
----------

     # This time we'll catch the standard error for our perusing
     # as well as passing in the passphrase manually
     # as well as the status information given by GnuPG
     my ( $input, $output, $error, $passphrase_fh, $status_fh )
       = ( IO::Handle->new(),
           IO::Handle->new(),
           IO::Handle->new(),
           IO::Handle->new(),
           IO::Handle->new(),
         );

     my $handles = GnupG::Handles->new( stdin      => $input,
     				     stdout     => $output,
     				     stderr     => $error,
     				     passphrase => $passphrase_fh,
     				     status     => $status_fh,
     				   );

     # this time we'll also demonstrate decrypting
     # a file written to disk
     # Make sure you "use IO::File" if you use this module!
     my $cipher_file = IO::File->new( 'encrypted.gpg' );

     # this sets up the communication
     $gnupg->decrypt( handles => $handles );

     # This passes in the passphrase
     print $passphrase_fd $passphrase;
     close $passphrase_fd;

     # this passes in the plaintext
     print $input $_ while <$cipher_file>

     # this closes the communication channel,
     # indicating we are done
     close $input;
     close $cipher_file;

     my @plaintext    = <$output>;   # reading the output
     my @error_output = <$error>;    # reading the error
     my @status_info  = <$status_fh> # read the status info

     # clean up...
     close $output;
     close $error;
     close $status_fh;

     wait;  # clean up the finished GnuPG process

Printing Keys
-------------

     # This time we'll just let GnuPG print to our own output
     # and read from our input, because no input is needed!
     my $handles = GnuPG::Handles->new();

     my @ids = [ 'ftobin', '0xABCD1234' ];

     # this time we need to specify something for
     # gnupg_command_args because --list-public-keys takes
     # search ids as arguments
     $gnupg->list_public_keys( handles            => $handles,
                               gnupg_command_args => [ @ids ]  );

      wait;

Creating GnuPG::PublicKey Objects
---------------------------------

     my @ids = [ 'ftobin', '0xABCD1234' ];

     my @keys = $gnupg->get_public_keys( @ids );

     # no wait is required this time; it's handled internally
     # since the entire call is encapsulated

FAQ
===

How do I get GnuPG::Interface to read/write directly from a filehandle?
     You need to set GnuPG::Handles direct option to be true for the
     filehandles in concern.  See `options', see GnuPG/Handles,
     and `"Object Methods which use a GnuPG::Handles
     Object"' in this node for more information.

Why do you make it so difficult to get GnuPG to write/read from a filehandle?  In the shell, I can just call GnuPG with the -outfile option!
     There are lots of issues when trying to tell GnuPG to read/write
     directly from a file, such as if the file isn't there, or there is a
     file, and you want to write over it!  What do you want to happen
     then?  Having the user of this module handle these questions
     beforehand by opening up filehandles to GnuPG lets the user know
     fully what is going to happen in these circumstances, and makes the
     module less error-prone.

When having GnuPG process a large message, sometimes it just hanges there.
     Your problem may be due to buffering issues; when GnuPG reads/writes
     to *non-direct* filehandles (those that are sent to filehandles which
     you read to from into memory, not that those access the disk),
     buffering issues can mess things up.  I recommend looking into
     `options', see GnuPG/Handles.

NOTES
=====

   This package is the successor to PGP::GPG::MessageProcessor, which I
found to be too inextensible to carry on further.  A total redesign was
needed, and this is the resulting work.

   After any call to a GnuPG-command method of GnuPG::Interface in which
one passes in the handles, one should all wait to clean up GnuPG from the
process table.

BUGS
====

   Currently there are problems when transmitting large quantities of
information over handles; I'm guessing this is due to buffering issues.
This bug does not seem specific to this package; IPC::Open3 also appears
affected.

   I don't know yet how well this modules handles parsing OpenPGP v3 keys.

SEE ALSO
========

   See GnuPG/Options, GnuPG/Handles,
see GnuPG/PublicKey,
GnuPG/SecretKey, `gpg' in this node, see
Class/MethodMaker, `"Bidirectional Communication with
Another Process"', see Perlipc (perl.info),

AUTHOR
======

   Frank J. Tobin, ftobin@uiuc.edu

PACKAGE UPDATES
===============

   Package updates may be found on http://GnuPG-Interface.sourceforge.net/
or CPAN, http://www.cpan.org/.

GnuPG Key Object
****************

NAME
====

   GnuPG::Key - GnuPG Key Object

SYNOPSIS
========

     # assumes a GnuPG::Interface object in $gnupg
     my @keys = $gnupg->get_public_keys( 'ftobin' );

     # now GnuPG::PublicKey objects are in @keys

DESCRIPTION
===========

   GnuPG::Key objects are generally not instantiated on their own, but
rather used as a superclass of GnuPG::PublicKey, GnuPG::SecretKey, or
GnuPG::SubKey objects.

OBJECT METHODS
==============

Initialization Methods
----------------------

new( *%initialization_args* )
     This methods creates a new object.  The optional arguments are
     initialization of data members; the initialization is done in a
     manner according to the method created as described in
     `"new_hash_init"', see Class/MethodMaker.

hash_init( *%args* ).
     This method works as described in `"new_hash_init"', see
     Class/MethodMaker.

short_hex_id
     This returns the commonly-used short, 8 character short hex id of the
     key.

OBJECT DATA MEMBERS
===================

   Note that these data members are interacted with via object methods
created using the methods described in `"get_set"', see
Class/MethodMaker, or `"object"', see
Class/MethodMaker.  Please read there for more
information.

length
     Number of bits in the key.

algo_num
     They algorithm number that the Key is used for.

hex_data
     The data of the key.

hex_id
     The long hex id of the key.  This is not the fingerprint nor the
     short hex id, which is 8 hex characters.

creation_date_string =item expiration_date_string
     Formatted date of the key's creation and expiration.

fingerprint
     A GnuPG::Fingerprint object.

SEE ALSO
========

   See GnuPG/Fingerprint, Class/MethodMaker,

GnuPG options embodiment
************************

NAME
====

   GnuPG::Options - GnuPG options embodiment

SYNOPSIS
========

     # assuming $gnupg is a GnuPG::Interface object
     $gnupg->options->armor( 1 );
     $gnupg->options->push_recipients( 'ftobin', '0xABCD1234' );

DESCRIPTION
===========

   GnuPG::Options objects are generally not instantiated on their own, but
rather as part of a GnuPG::Interface object.

OBJECT METHODS
==============

new( *%initialization_args* )
     This methods creates a new object.  The optional arguments are
     initialization of data members; the initialization is done in a
     manner according to the method created as described in
     `"new_hash_init"', see Class/MethodMaker.

hash_init( *%args* ).
     This method works as described in `"new_hash_init"', see
     Class/MethodMaker.

copy
     Returns a copy of this object.  Useful for 'saving' options.

get_args
     Returns a list of arguments to be passed to GnuPG based on data
     members which are 'meta_' options, regular options, and then
     extra_args, in that order.

OBJECT DATA MEMBERS
===================

   Note that these data members are interacted with via object methods
created using the methods described in `"boolean"', see
Class/MethodMaker, `"get_set"', see
Class/MethodMaker, `"object"', see
Class/MethodMaker, and `"list"', see
Class/MethodMaker.  Please read there for more
information.

homedir
armor
textmode
default_key
no_greeting
verbose
no_verbose
quiet
batch
always_trust
comment
status_fd
logger_fd
passphrase_fd
compress_algo

force_v3_sigs

rfc1991
openpgp
options
no_options
encrypt_to
recipients
     These options correlate directly to many GnuPG options.  For those
     that are boolean to GnuPG, simply that argument is passed.  For those
     that are associated with a scalar, that scalar is passed passed as an
     argument appropriate.  For those that can be specified more than
     once, such as recipients, those are considered lists and passed
     accordingly.  Each are undefined or false to begin.

Meta Options
------------

   Meta options are those which do not correlate directly to any option in
GnuPG, but rather are generally a bundle of options used to accomplish a
specific goal, such as obtaining compatibility with PGP 5.  The actual
arguments each of these reflects may change with time.  Each defaults to
false unless otherwise specified.

   These options are being designed and to provide a non-GnuPG-specific
abstraction, to help create compatibility with a possible PGP::Interface
module.

   To help avoid confusion, methods with take a form of a key as an object
shall be prepended with *_id(s)* if they only take an id; otherwise assume
an object of type GnuPG::Key is required.

meta_pgp_5_compatible
     If true, arguments are generated to try to be compatible with PGP 5.x.

meta_pgp_2_compatible
     If true, arguments are generated to try to be compatible with PGP 2.x.

meta_interactive
     If false, arguments are generated to try to help the using program
     use GnuPG in a non-interactive environment, such as CGI scripts.
     Default is true.

meta_signing_key_id
     This scalar reflects the key used to sign messages.  Currently this
     is synonymous with *default-key*.

meta_signing_key
     This GnuPG::Key object reflects the key used to sign messages.

meta_recipients_key_ids
     This list of scalar key ids are used to generate the appropriate
     arguments having these keys as recipients.

meta_recipients_keys
     This list of keys of the type GnuPG::Key are used to generate the
     appropriate arguments having these keys as recipients.

Other Data Members
------------------

extra_args
     This is a list of any other arguments used to pass to GnuPG.  Useful
     to pass an argument not yet covered in this package.

SEE ALSO
========

   See GnuPG/Interface, Class/MethodMaker,

GnuPG Public Key Objects
************************

NAME
====

   GnuPG::PublicKey - GnuPG Public Key Objects

SYNOPSIS
========

     # assumes a GnuPG::Interface object in $gnupg
     my @keys = $gnupg->get_public_keys( 'ftobin' );

     # now GnuPG::PublicKey objects are in @keys

DESCRIPTION
===========

   GnuPG::PublicKey objects are generally instantiated through various
methods of GnuPG::Interface.  They embody various aspects of a GnuPG
primary key.

   This package inherits data members and object methods from GnuPG::Key,
which are not described here, but rather in GnuPG/Key.

OBJECT DATA MEMBERS
===================

   Note that these data members are interacted with via object methods
created using the methods described in `"get_set"', see
Class/MethodMaker, `"object"', see
Class/MethodMaker, or `"list"', see
Class/MethodMaker.  Please read there for more
information.

user_ids
     A list of GnuPG::UserId objects associated with this key.

subkeys
     A list of GnuPG::SubKey objects associated with this key.

local_id
     GnuPG's local id for the key.

owner_trust
     The scalar value GnuPG reports as the ownertrust for this key.  See
     GnuPG's DETAILS file for details.

SEE ALSO
========

   See GnuPG/Key, GnuPG/UserId,
GnuPG/SubKey, Class/MethodMaker,

GnuPG Secret Key Objects
************************

NAME
====

   GnuPG::SecretKey - GnuPG Secret Key Objects

SYNOPSIS
========

     # assumes a GnuPG::Interface object in $gnupg
     my @keys = $gnupg->get_public_keys( 'ftobin' );

     # now GnuPG::PublicKey objects are in @keys

DESCRIPTION
===========

   GnuPG::SecretKey objects are generally instantiated through various
methods of GnuPG::Interface.  They embody various aspects of a GnuPG
secret key.

   This package inherits data members and object methods from GnuPG::Key,
which are not described here, but rather in GnuPG/Key.

OBJECT DATA MEMBERS
===================

   Note that these data members are interacted with via object methods
created using the methods described in `"get_set"', see
Class/MethodMaker, `"object"', see
Class/MethodMaker, or `"list"', see
Class/MethodMaker.  Please read there for more
information.

user_ids
     A list of GnuPG::UserId objects associated with this key.

subkeys
     A list of GnuPG::SubKey objects associated with this key.

local_id
     GnuPG's local id for the key.

owner_trust
     The scalar value GnuPG reports as the ownertrust for this key.  See
     GnuPG's DETAILS file for details.

SEE ALSO
========

   See GnuPG/Key, GnuPG/UserId,
GnuPG/SubKey, Class/MethodMaker,

GnuPG Key Signature Objects
***************************

NAME
====

   GnuPG::Signature - GnuPG Key Signature Objects

SYNOPSIS
========

     # assumes a GnuPG::SubKey object in $key
     my $signing_id = $key->signature->hex_id();

DESCRIPTION
===========

   GnuPG::Signature objects are generally not instantiated on their own,
but rather as part of GnuPG::Key objects.  They embody various aspects of
a GnuPG signature on a key.

OBJECT METHODS
==============

new( *%initialization_args* )
     This methods creates a new object.  The optional arguments are
     initialization of data members; the initialization is done in a
     manner according to the method created as described in
     `"new_hash_init"', see Class/MethodMaker.

OBJECT DATA MEMBERS
===================

   Note that these data members are interacted with via object methods
created using the methods described in `"get_set"', see
Class/MethodMaker, `"object"', see
Class/MethodMaker, or `"list"', see
Class/MethodMaker.  Please read there for more
information.

algo_num
     The number of the algorithm used for the signature.

hex_id
     The hex id of the signing key.

user_id_string
     The first user id string on the key that made the signature.  This
     may not be defined if the signing key is not on the local keyring.

date_string
     The formatted date the signature was performed on.

SEE ALSO
========

   See also Class/MethodMaker.

GnuPG Sub Key objects
*********************

NAME
====

   GnuPG::SubKey - GnuPG Sub Key objects

SYNOPSIS
========

     # assumes a GnuPG::PublicKey object in $key
     my @subkeys = $key->subkeys();

     # now GnuPG::SubKey objects are in @subkeys

DESCRIPTION
===========

   GnuPG::SubKey objects are generally instantiated through various
methods of GnuPG::Interface.  They embody various aspects of a GnuPG sub
key.

   This package inherits data members and object methods from GnuPG::Key,
which are not described here, but rather in GnuPG/Key.

OBJECT DATA MEMBERS
===================

   Note that these data members are interacted with via object methods
created using the methods described in `"get_set"', see
Class/MethodMaker, `"object"', see
Class/MethodMaker, or `"list"', see
Class/MethodMaker.  Please read there for more
information.

validity
     A scalar holding the value GnuPG reports for the trust of authenticity
     (a.k.a.) validity of a key.  See GnuPG's DETAILS file for details.

local_id
     GnuPG's local id for the key.

owner_trust
     The scalar value GnuPG reports as the ownertrust for this key.  See
     GnuPG's DETAILS file for details.

signature
     A GnuPG::Signature object holding the representation of the signature
     on this key.

SEE ALSO
========

   See GnuPG/Key, GnuPG/Signature,
Class/MethodMaker,

Tied filehandle interface to encryption with the GNU Privacy Guard.
*******************************************************************

NAME
====

   GnuPG::Tie::Encrypt - Tied filehandle interface to encryption with the
GNU Privacy Guard.

   GnuPG::Tie::Decrypt - Tied filehandle interface to decryption with the
GNU Privacy Guard.

SYNOPSIS
========

     use GnuPG::Tie::Encrypt;
     use GnuPG::Tie::Decrypt;

     tie *CIPHER, 'GnuPG::Tie::Encrypt', armor => 1, recipient => 'User';
     print CIPHER <<EOF
     This is a secret
     EOF
     local $/ = undef;
     my $ciphertext = <CIPHER>;
     close CIPHER;
     untie CIPHER;

     tie *PLAINTEXT, 'GnuPG::Tie::Decrypt', passphrase => 'secret';
     print PLAINTEXT $ciphertext;
     my $plaintext = <PLAINTEXT>;

     # $plaintext should now contains 'This is a secret'
     close PLAINTEXT;
     untie PLAINTEXT

DESCRIPTION
===========

   GnuPG::Tie::Encrypt and GnuPG::Tie::Decrypt provides a tied  file handle
interface to encryption/decryption facilities of the GNU Privacy guard.

   With GnuPG::Tie::Encrypt everyting you write to the file handle will be
encrypted. You can read the ciphertext from the same file handle.

   With GnuPG::Tie::Decrypt you may read the plaintext equivalent of a
ciphertext. This is one can have been written to file handle.

   All options given to the tie constructor will be passed on to the
underlying GnuPG object. You can use a mix of options to ouput directly to
a file or to read directly from a file, only remember than once you start
reading from the file handle you can't write to it anymore.

IMPLEMENTATIONS DETAILS
=======================

   This interface will fork twice, once for the gnupg process and one the
controls the gpg process.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999, 2000 iNsu Innovations Inc.

   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.

SEE ALSO
========

   gpg(1) GnuPG(3)

GnuPG User ID Objects
*********************

NAME
====

   GnuPG::UserId - GnuPG User ID Objects

SYNOPSIS
========

     # assumes a GnuPG::PublicKey object in $publickey
     my $first_userid_string = $publickey->user_ids_ref->[0]->user_id_string;

DESCRIPTION
===========

   GnuPG::UserId objects are generally not instantiated on their own, but
rather as part of GnuPG::PublicKey or GnuPG::SecretKey objects.

OBJECT METHODS
==============

new( *%initialization_args* )
     This methods creates a new object.  The optional arguments are
     initialization of data members; the initialization is done in a
     manner according to the method created as described in
     `"new_hash_init"', see Class/MethodMaker.

OBJECT DATA MEMBERS
===================

   Note that these data members are interacted with via object methods
created using the methods described in `"get_set"', see
Class/MethodMaker, `"object"', see
Class/MethodMaker, or `"list"', see
Class/MethodMaker.  Please read there for more
information.

user_id_string
     A string of the user id.

validity
     A scalar holding the value GnuPG reports for the trust of authenticity
     (a.k.a.) validity of a key.  See GnuPG's DETAILS file for details.

signatures
     A list of GnuPG::Signature objects embodying the signatures on this
     user id.

SEE ALSO
========

   See GnuPG/Signature, Class/MethodMaker,

parse ~/.newsrc.eld files
*************************

NAME
====

   Gnus::Newsrc - parse ~/.newsrc.eld files

SYNOPSIS
========

     $newsrc = Gnus::Newsrc->new;
     ($level, $read, $marks, $server, $group_para) =
        @{$newsrc->alish_hash->{"comp.lang.perl.misc"}};

DESCRIPTION
===========

   The `Gnus::Newsrc' objects represents the content of the ~/newsrc.eld
files that the Gnus newsreader use to store away its state.

   The following methods are provided:

$newsrc = Gnus::Newsrc->new( [$filename] )
     The object constructor takes an optional filename as argument.  The
     file defaults to `~/.newsrc.eld'.  It will read and parse the file
     and return a reference to a `Gnus::Newsrc' object.  The constructor
     will croak if the file can't be found or can't be parsed.

$newsrc->file_version
     Return the version number found in the file
     *(gnus-newsrc-file-version)*.  The version number is a string like
     `"Gnus v5.5"'.

$newsrc->last_checked_date
     Returns a string like `"Sat Oct 18 14:05:53 1997"'
     *(gnus-newsrc-last-checked-date)*.

$newsrc->alist
     Returns a reference to an array that will have one element for each
     active newsgroup *(gnus-newsrc-alist)*.  Each element is a array with
     the following values:

          $group_name
          $group_level
          $read_articles
          \%marks
          \@server
          \%group_parameters

     The `$read_articles' and `%marks' values is a string of integer
     ranges, and it is suitable for initializing a `Set::IntSpan' objects.

$newsrc->alist_hash
     Returns a reference to a hash indexed by group names.  The hash values
     are the same as the `alist' elements, but the `$group_name' is
     missing.

$newsrc->server_alist
     *(gnus-server-alist)*.

$newsrc->killed_list
     A reference to an array that contains all the killed newsgroups
     *(gnus-killed-list)*.

$newsrc->zombie_list
     A reference to an array that contains all zombie newsgroups
     *(gnus-zombie-list)*.

$newsrc->format_specs
SEE ALSO
========

   `Lisp::Reader' in this node, see Set/IntSpan,
http://www.gnus.org

COPYRIGHT
=========

   Copyright 1997 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl extension for the XML Query Interface at xqi.goxml.com.
************************************************************

NAME
====

   GoXML::XQI - Perl extension for the XML Query Interface at
xqi.goxml.com.

SYNOPSIS
========

     use GoXML::XQI;
     $q = new GoXML::XQI(
     	HOST => 'www.goxml.com',
     	PORT => '5910',
     );
     $fh = $q->Query(
     		KEYWORD => $keywd,
     		TAG => $tag,
     		CATEGORY => $categ);

     while (<$fh>) {
     	# Do something with the search results..
     }

     $resp = $q->Submit(
     		HREF => $url,
     		DESCRIPTION => $description,
     		CATEGORY => $category);

     print "Succeeded.\n" if $resp;

DESCRIPTION
===========

   This module was designed to allow authorized third parties to connect
to the XML index at www.goxml.com:5910.  While generally a trivial task,
this module will stay up to date and backwards compatible with newer and
older versions of XQI.

   Everyone is _authorized_ to use this service, but people who are paying
us get first priority :).

CATEGORIES
==========

   Below is a list of categories currently accepted by Submit():

   1 = Arts & Humanities 2 = Health 3 = Business & Economy 4 = News & Media
5 = Computers & Internet 6 = Recreation & Sports 7 = Education 8 =
Reference [DEFAULT] 9 = Entertainment 10 = Science 11 = Family 12 =
Shopping 13 = Government 14 = Society & Culture 15 = News Groups
(XSL-List, ebXML-*, your-list??)

AUTHOR
======

   C. Matthew MacKenzie <matt@xmlglobal.com>

SEE ALSO
========

   http://www.goxml.com

graph operations
****************

NAME
====

   Graph - graph operations

SYNOPSIS
========

     use Graph;

     $g = new Graph;

DESCRIPTION
===========

   This is just a front-end class for Graph::Directed and Graph::Base.

   Instantiated Graph objects (like $g in the the above description) are
in fact Graph::Base objects in disguise, look there for the methods
available.  If you want undirected graphs, create Graph::Undirected
objects.

COPYRIGHT
=========

   Copyright 1999, O'Reilly & Associates.

   This code is distributed under the same copyright terms as Perl itself.

graph breadth-first search
**************************

NAME
====

   Graph::BFS - graph breadth-first search

SYNOPSIS
========

     use Graph::BFS;

DESCRIPTION
===========

     $bfs = Graph::BFS->new($G, %param)

   Returns a new breadth-first search object for the graph $G and the
(optional) parameters %param.

   See also `Graph::Traversal'.

COPYRIGHT
=========

   Copyright 1999, O'Reilly & Associates.

   This code is distributed under the same copyright terms as Perl itself.

graph base class
****************

NAME
====

   Graph::Base - graph base class

SYNOPSIS
========

     use Graph::Directed;
     use Graph::Undirected;

     $d1 = new Graph;
     $d2 = new Graph::Directed;
     $u  = new Graph::Undirected;

DESCRIPTION
===========

   You create new graphs by calling the new constructors of classes Graph,
`Graph::Directed', and `Graph::Undirected'.  The classes Graph and
`Graph::Directed' are identical.  After creating the graph you can modify
and explore the graph with following methods.

     $G = Graph->new(@V)

   Returns a new graph $G with the optional vertices @V.

     $G = $G->add_vertices(@v)

   Adds the vertices to the graph $G, returns the graph.

     $G = $G->add_vertex($v)

   Adds the vertex $v to the graph $G, returns the graph.

     @V = $G->vertices

   In list context returns the vertices @V of the graph $G.  In scalar
context returns the number of the vertices.

     $G->has_vertices(@v)

   In list context returns a list which contains the vertex of the
vertices @v if the vertex exists in the graph $G and undef if it doesn't.
In scalar context returns the number of the existing vertices.

     $b = $G->has_vertex($v)

   Returns true if the vertex $v exists in the graph $G and false if it
doesn't.

     $v = $G->has_vertex($v)

   Returns the vertex $v if the vertex exists in the graph $G or undef if
it doesn't.

     $b = $G->directed($d)

   Set the directedness of the graph $G to $d or return the current
directedness.  Directedness defaults to true.

     $b = $G->undirected($d)

   Set the undirectedness of the graph $G to $u or return the current
undirectedness.  Undirectedness defaults to false.

     $b = $G->has_edge($u, $v)

   Return true if the graph $G has the edge between the vertices $u, $v.

     $G->has_edges($u1, $v1, $u2, $v2, ...)

   In list context returns a list which contains true for each edge in the
graph $G defined by the vertices $u1, $v1, ..., and false for each
non-existing edge.  In scalar context returns the number of the existing
edges.

     $G->has_path($u, $v, ...)

   Return true if the graph $G has the cycle defined by the vertices $u,
$v, ..., false otherwise.

     $G->has_cycle($u, $v, ...)

   Return true if the graph $G has the cycle defined by the vertices $u,
$v, ...,false otherwise.

     $s = $G->vertex_set($v)

   Returns the vertex set of the vertex $v in the graph $G.  A "vertex
set" is represented by its parent vertex.

     $G = $G->add_edge($u, $v)

   Adds the edge defined by the vertices $u, $v, to the graph $G.  Also
implicitly adds the vertices.  Returns the graph.

     $G = $G->add_edges($u1, $v1, $u2, $v2, ...)

   Adds the edge defined by the vertices $u1, $v1, ..., to the graph $G.
Also implicitly adds the vertices.  Returns the graph.

     $G->add_path($u, $v, ...)

   Adds the path defined by the vertices $u, $v, ..., to the graph $G.
Also implicitly adds the vertices.  Returns the graph.

     $G = $G->add_cycle($u, $v, ...)

   Adds the cycle defined by the vertices $u, $v, ..., to the graph $G.
Also implicitly adds the vertices.  Returns the graph.

     @n = $G->neighbors($v)

   Returns the neighbor vertices of the vertex in the graph.  (Also
'neighbours' works.)

     @s = $G->successors($v)

   Returns the successor vertices of the vertex in the graph.

     @p = $G->predecessors($v)

   Returns the predecessor vertices of the vertex in the graph.

     @e = $G->out_edges($v)

   Returns the edges leading out of the vertex $v in the graph $G.  In
list context returns the edges as ($start_vertex, $end_vertex) pairs.  In
scalar context returns the number of the edges.

     @e = $G->in_edges($v)

   Returns the edges leading into the vertex $v in the graph $G.  In list
context returns the edges as ($start_vertex, $end_vertex) pairs; in scalar
context returns the number of the edges.

     @e = $G->edges($u, $v)

   Returns the edges between the vertices $u and $v, or if $v is
undefined, the edges leading into or out of the vertex $u, or if $u is
undefined, returns all the edges, of the graph $G.  In list context
returns the edges as a list of $start_vertex, $end_vertex pairs; in scalar
context returns the number of the edges.

     $G = $G->delete_edge($u, $v)

   Deletes an edge defined by the vertices $u, $v from the graph $G.  Note
that the edge need not actually exist.  Returns the graph.

     $G = $G->delete_edges($u1, $v1, $u2, $v2, ..)

   Deletes edges defined by the vertices $u1, $v1, ..., from the graph $G.
Note that the edges need not actually exist.  Returns the graph.

     $G = $G->delete_path($u, $v, ...)

   Deletes a path defined by the vertices $u, $v, ..., from the graph $G.
Note that the path need not actually exist. Returns the graph.

     $G = $G->delete_cycle($u, $v, ...)

   Deletes a cycle defined by the vertices $u, $v, ..., from the graph $G.
Note that the cycle need not actually exist. Returns the graph.

     $G = $G->delete_vertex($v)

   Deletes the vertex $v and all its edges from the graph $G.  Note that
the vertex need not actually exist.  Returns the graph.

     $G = $G->delete_vertices(@v)

   Deletes the vertices @v and all their edges from the graph $G.  Note
that the vertices need not actually exist.  Returns the graph.

     $d = $G->in_degree($v)

   Returns the in-degree of the vertex $v in the graph $G, or, if $v is
undefined, the total in-degree of all the vertices of the graph, or undef
if the vertex doesn't exist in the graph.

     $d = $G->out_degree($v)

   Returns the out-degree of the vertex $v in the graph $G, or, if $v is
undefined, the total out-degree of all the vertices of the graph, of undef
if the vertex doesn't exist in the graph.

     $d = $G->degree($v)

   Returns the degree of the vertex $v in the graph $G or, if $v is
undefined, the total degree of all the vertices of the graph, or undef if
the vertex $v doesn't exist in the graph.

     $d = $G->average_degree

   Returns the average degree of the vertices of the graph $G.

     $b = $G->is_source_vertex($v)

   Returns true if the vertex $v is a source vertex of the graph $G.

     $b = $G->is_sink_vertex($v)

   Returns true if the vertex $v is a sink vertex of the graph $G.

     $b = $G->is_isolated_vertex($v)

   Returns true if the vertex $v is a isolated vertex of the graph $G.

     $b = $G->is_exterior_vertex($v)

   Returns true if the vertex $v is a exterior vertex of the graph $G.

     $b = $G->is_interior_vertex($v)

   Returns true if the vertex $v is a interior vertex of the graph $G.

     $b = $G->is_self_loop_vertex($v)

   Returns true if the vertex $v is a self-loop vertex of the graph $G.

     @s = $G->source_vertices

   Returns the source vertices @s of the graph $G.

     @s = $G->sink_vertices

   Returns the sink vertices @s of the graph $G.

     @i = $G->isolated_vertices

   Returns the isolated vertices @i of the graph $G.

     @e = $G->exterior_vertices

   Returns the exterior vertices @e of the graph $G.

     @i = $G->interior_vertices

   Returns the interior vertices @i of the graph $G.

     @s = $G->self_loop_vertices

   Returns the self-loop vertices @s of the graph $G.

     ($sparse, $dense, $complete) = $G->density_limits

   Returns the density limits for the number of edges in the graph $G.
Note that reaching $complete edges does not really guarantee completeness
because we can have multigraphs.  The limit of sparse is less than 1/4 of
the edges of the complete graph, the limit of dense is more than 3/4 of
the edges of the complete graph.

     $d = $G->density

   Returns the density $d of the graph $G.

     $d = $G->is_sparse

   Returns true if the graph $G is sparse.

     $d = $G->is_dense

   Returns true if the graph $G is dense.

     $C = $G->complete;

   Returns a new complete graph $C corresponding to the graph $G.

     $C = $G->complement;

   Returns a new complement graph $C corresponding to the graph $G.

     $C = $G->copy;

   Returns a new graph $C corresponding to the graph $G.

     $T = $G->transpose;

   Returns a new transpose graph $T corresponding to the graph $G.

     $G->set_attribute($attribute, $value)
     $G->set_attribute($attribute, $v, $value)
     $G->set_attribute($attribute, $u, $v, $value)

   Sets the $attribute of graph/vertex/edge to $value but only if the
vertex/edge already exists.  Returns true if the attribute is set
successfully, false if not.

     $value = $G->get_attribute($attribute)
     $value = $G->get_attribute($attribute, $v)
     $value = $G->get_attribute($attribute, $u, $v)

   Returns the $value of $attribute of graph/vertex/edge.

     $value = $G->has_attribute($attribute)
     $value = $G->has_attribute($attribute, $v)
     $value = $G->has_attribute($attribute, $u, $v)

   Returns the $value of $attribute of graph/vertex/edge.

     %attributes = $G->get_attributes()
     %attributes = $G->get_attributes($v)
     %attributes = $G->get_attributes($u, $v)

   Returns as a hash all the attribute names and values of
graph/vertex/edge.

     $G->delete_attribute($attribute)
     $G->delete_attribute($attribute, $v)
     $G->delete_attribute($attribute, $u, $v)

   Deletes the $attribute of graph/vertex/edge.

     $G->delete_attributes()
     $G->delete_attributes($v)
     $G->delete_attributes($u, $v)

   Deletes all the attributes of graph/vertex/edge.

     $G->add_weighted_edge($u, $w, $v, $a)

   Adds in the graph $G an edge from vertex $u to vertex $v and the edge
attribute 'weight' set to $w.

     $G->add_weighted_edges($u1, $w1, $v1, $u2, $w2, $v2, ...)

   Adds in the graph $G the weighted edges.

     $G->add_weighted_path($v1, $w1, $v2, $w2, ..., $wnm1, $vn)

   Adds in the graph $G the n edges defined by the path $v1 ... $vn with
the n-1 'weight' attributes $w1 ... $wnm1

     $MST = $G->MST_Kruskal;

   Returns Kruskal's Minimum Spanning Tree (as a graph) of the graph $G
based on the 'weight' attributes of the edges.  (Needs the ->vertex_set()
method.)

     @C = $G->edge_classify(%param)

   Returns the edge classification as a list where each element is a
triplet [$u, $v, $class] the $u, $v being the vertices of an edge and
$class being the class.  The %param can be used to control the search.

     @toposort = $G->toposort

   Returns the vertices of the graph $G sorted topologically.

     @S = $G->strongly_connected_components

   Returns the strongly connected components @S of the graph $G as a list
of anonymous lists of vertices, each anonymous list containing the
vertices belonging to one strongly connected component.

     $T = $G->strongly_connected_graph

   Returns the strongly connected graph $T of the graph $G.  The names of
the strongly connected components are formed from their constituent
vertices by concatenating their names by '+'-characters: "a" and "b" ->
"a+b".

     $APSP = $G->APSP_Floyd_Warshall

   Returns the All-pairs Shortest Paths graph of the graph $G computed
using the Floyd-Warshall algorithm and the attribute 'weight' on the edges.
The returned graph has an edge for each shortest path.  An edge has
attributes "weight" and "path"; for the length of the shortest path and
for the path (an anonymous list) itself.

     $TransitiveClosure = $G->TransitiveClosure_Floyd_Warshall

   Returns the Transitive Closure graph of the graph $G computed using the
Floyd-Warshall algorithm.  The resulting graph has an edge between each
*ordered* pair of vertices in which the second vertex is reachable from
the first.

     @A = $G->articulation_points(%param)

   Returns the articulation points (vertices) @A of the graph $G.  The
%param can be used to control the search.

     $b = $G->is_biconnected

   Returns true is the graph $G is biconnected (has no articulation
points), false otherwise.

     $v = $G->largest_out_degree( @V )

   Selects the vertex $v from the vertices @V having the largest out
degree in the graph $G.

     $MST = $G->MST_Prim($u)

   Returns Prim's Minimum Spanning Tree (as a graph) of the graph $G based
on the 'weight' attributes of the edges.  The optional start vertex is $u,
if none is given, a hopefully good one (a vertex with a large out degree)
is chosen.

     $SSSP = $G->SSSP_Dijkstra($s)

   Returns the Single-source Shortest Paths (as a graph) of the graph $G
starting from the vertex $s using Dijktra's SSSP algorithm.

     $SSSP = $G->SSSP_Bellman_Ford($s)

   Returns the Single-source Shortest Paths (as a graph) of the graph $G
starting from the vertex $s using Bellman-Ford SSSP algorithm.  If there
are one or more negatively weighted cycles, returns undef.

     $SSSP = $G->SSSP_DAG($s)

   Returns the Single-source Shortest Paths (as a graph) of the DAG $G
starting from vertex $s.

     $G->add_capacity_edge($u, $w, $v, $a)

   Adds in the graph $G an edge from vertex $u to vertex $v and the edge
attribute 'capacity' set to $w.

     $G->add_capacity_edges($u1, $w1, $v1, $u2, $w2, $v2, ...)

   Adds in the graph $G the capacity edges.

     $G->add_capacity_path($v1, $w1, $v2, $w2, ..., $wnm1, $vn)

   Adds in the graph $G the n edges defined by the path $v1 ... $vn with
the n-1 'capacity' attributes $w1 ... $wnm1

     $F = $G->Flow_Ford_Fulkerson($S)

   Returns the (maximal) flow network of the flow network $G, parametrized
by the state $S.  The $G must have 'capacity' attributes on its edges.
$S->{ source } must contain the source vertex and $S->{ sink } the sink
vertex, and most importantly $S->{ next_augmenting_path } must contain an
anonymous subroutine which takes $F and $S as arguments and returns the
next potential augmenting path.  Flow_Ford_Fulkerson will do the
augmenting.  The result graph $F will have 'flow' and (residual) 'capacity'
attributes on its edges.

     $F = $G->Flow_Edmonds_Karp($source, $sink)

   Return the maximal flow network of the graph $G built using the
Edmonds-Karp version of Ford-Fulkerson.  The input graph $G must have
'capacity' attributes on its edges; resulting flow graph will have
'capacity' and 'flow' attributes on its edges.

     $G->eq($H)

   Return true if the graphs (actually, their string representations) are
identical.  This means really identical: they must have identical vertex
names and identical edges between the vertices, and they must be similarly
directed.  (Just isomorphism isn't enough.)

COPYRIGHT
=========

   Copyright 1999, O'Reilly & Associates.

   This code is distributed under the same copyright terms as Perl itself.

graph depth-first search
************************

NAME
====

   Graph::DFS - graph depth-first search

SYNOPSIS
========

   *see description*

DESCRIPTION
===========

     $dfs = Graph::DFS->new($G, %param)

     Returns a new depth-first search object for the graph $G
     and the (optional) parameters %param.

   See also `Graph::Traversal'.

COPYRIGHT
=========

   Copyright 1999, O'Reilly & Associates.

   This code is distributed under the same copyright terms as Perl itself.

directed graphs
***************

NAME
====

   Graph::Directed - directed graphs

SYNOPSIS
========

     use Graph::Directed;

     $g = new Graph::Directed;

DESCRIPTION
===========

   See Graph::Base for the available methods.

COPYRIGHT
=========

   Copyright 1999, O'Reilly & Associates.

   This code is distributed under the same copyright terms as Perl itself.

a base class for graph edges
****************************

NAME
====

   Graph::Edge - a base class for graph edges

SYNOPSIS
========

   *Not to be used directly*.

DESCRIPTION
===========

   This class is not to be used directly because an edge always must
belong to a graph.  The graph classes will do this right.  Some useful
public methods exist, though.

RETRIEVING EDGES
----------------

     $edge  = $graph->edge($v1, $v2);

   Return an edge of the graph by its vertex names, or vertices.  If the
edge does not exist, undef is returned.

     @edges = $graph->edges($e1_v1, $e1_v2,
                                    $e2_v1, $e2_v2,
                                    ...,
                                    $en_v1, $en_v2);

   Return the list of n edges of the graph by their vertex names, or
vertices.  If an edge by its vertices does not exist, undef is returned
for that edge.  If no names are specified all the edges are returned, in
pseudorandom order.

RETRIEVING EDGE VERTICES
------------------------

     $start_vertex = $edge->start;
     $stop_vertex  = $edge->stop;

   The start and stop vertices of the edge.

     ( $start_vertex, $stop_vertex ) = $edge->vertices;

   Even in an undirected graph these will be in the order defined
originally by add_edge method.

ADDING AND DELETING EDGES
-------------------------

   See Graph.

SEE ALSO
========

   See Graph, Graph/Element.

VERSION
=======

   See Graph.

AUTHOR
======

   Jarkko Hietaniemi <`jhi@iki.fi'>

COPYRIGHT
=========

   Copyright 1998, O'Reilly and Associates.

   This code is distributed under the same copyright terms as Perl itself.

a base class for all things graph
*********************************

NAME
====

   Graph::Element - a base class for all things graph

SYNOPSIS
========

   *Not to be used directly*.

DESCRIPTION
===========

   This class is a base class for all the graph elements: vertices, edges,
and the graphs themselves.

   Though largely this class is for internal use only and will bite
viciously if approached by strangers it does provide some public methods.

METHODS
=======

     $name = $element->name;

   Get the current name of the element.  Vertices always have names (they
are defined by their names), edges and graphs not necessarily.

     $element->name($new_name);

   Set the name of the element.

VIRTUAL METHODS
===============

   This class also implements a `virtual method' in this node for all the
graph elements: if an unknown method is invoked on an element, it is
assumed to be an attribute get/set method from then onwards.  For example:

     $graph->yabadabadoo('fred');
     $flintstone = $graph->yabadabadoo;

     C<$flintstone> will be now C<'fred'>.  This feature is both very
     comfortable and very uncomfortable: no need to separately
     define methods -- and a pain in nether parts if you are prone to
     typos.

ATTRIBUTE METHODS
=================

   If you want to play safe with the attributes (as opposed to the virtual
attribute methods), you must use explicit language:

     $attribute_value = $element->attribute($attribute_name);

   Get the attribute of the element.

     $element->attribute($attribute_name, $attribute_value);

   Set the attribute of the element.

     $element->delete_attribute($attribute_name);

   Delete the attribute of the element.  You can also

     $element->attribute($attribute_name, undef)

   but that doesn't really get rid of the attribute, the `has_attribute'
method will still find the attribute, but after `delete_attribute' even
that will fail.

   Tests whether the element has the attribute, regardless of the value of
the attribute.

SEE ALSO
========

   See Graph, Graph/Directed,
Graph/Undirected.

VERSION
=======

   See Graph.

AUTHOR
======

   Jarkko Hietaniemi, <`jhi@iki.fi'>

COPYRIGHT
=========

   Copyright 1998, O'Reilly & Associates.

   This code is distributed under the same copyright terms as perl itself.

internal use only
*****************

NAME
====

   Graph::HeapElem - internal use only

SYNOPSIS
========

DESCRIPTION
===========

   *INTERNAL USE ONLY* for the Graph module

COPYRIGHT
=========

   Copyright 1999, O'Reilly & Associates.

   This code is distributed under the same copyright terms as Perl itself.

Kruskal's Algorithm for Minimal Spanning Trees in Graphs
********************************************************

NAME
====

   Graph::Kruskal - Kruskal's Algorithm for Minimal Spanning Trees in
Graphs

   Computes the Minimal Spanning Tree of a given graph according to some
cost function defined on the edges of the graph.

SYNOPSIS
========

   * `use Graph::Kruskal qw(define_vortices define_edges' `heapify
     makeheap heapsort find union kruskal example);'

   * `use Graph::Kruskal qw(:all);'

   * `&define_vortices(2,3,5,7,11,13,17,19,23,29,31);'

     Define a list of vortices (integers > 0)

   * `&define_edges( 2,13,3, 3,13,2, 5,13,1, 3,5,2, 3,29,21 );'

     Define (non-directed) edges on the vortices previously defined (always
     in triplets: "from" vortice, "to" vortice and cost of that edge)

   * `&heapify($i,$n);'

     Main subroutine for sorting the edges according to their costs

   * `&makeheap($n);'

     Routine to initialize sorting of the edges

   * `&heapsort($n);'

     The famous heapsort algorithm (not needed for Kruskal's algorithm as
     a whole but included here for the sake of completeness) for sorting
     the edges according to their costs

   * `&find($i);'

   * `&union($i,$j);'

     Disjoint (!) sets are stored as trees in an array in this algorithm.
     Each element of some set (a cell in the array) contains a pointer to
     (the number of) another element, up to the root element that does not
     point anywhere, but contains the (negative) number of elements the
     set contains. The number of the root element is also used as an
     identifier for the set.

     Example:

          i  : |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |
              -------------+-----+-----+-----+-----+-----+-----+-----+-----+
               parent[i] : | -4  | -3  |  1  |  2  |  1  | -1  |  3  |  4  |

     This array contains the three sets S1, S2 and S6:

          1           2           6
                             / \          |
                            3   5         4
                           /              |
                          7               8

     "find" returns the number of the root element (= the identifier of
     the set) of the tree in which the given element is contained:

          find(a) := i  so that  a in Si

     It also reduces the height of that tree by changing all the pointers
     from the given element up to the root element to point DIRECTLY to
     the root element.

     Example:

          find(7) returns "1" and modifies the array as follows:

          i  : |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |
              -------------+-----+-----+-----+-----+-----+-----+-----+-----+
               parent[i] : | -4  | -3  |  1  |  2  |  1  | -1  |  1  |  4  |

          1           2           6
                             /|\          |
                            3 5 7         4
                      |
                      8

     "union" takes the identifiers of two sets (= the numbers of their
     respective root elements) and merges the two sets by appending one of
     the two trees to the other. It always appends the SMALLER set to the
     LARGER one (to keep the height of the resulting tree as small as
     possible) and updates the number of elements contained in the
     resulting set which is stored in the root element's cell of the array.

     Example:

          union(2,6) does the following:

          i  : |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |
              -------------+-----+-----+-----+-----+-----+-----+-----+-----+
               parent[i] : | -4  | -4  |  1  |  2  |  1  |  2  |  1  |  4  |

          1           2
                             /|\         / \
                            3 5 7       4   6
                    |
                    8

          complexity for O(n) "find" operations: O( G(n) n )

          complexity for one "union" operation: O(1)

          complexity for O(n) ( "find" + "union" ) operations: O( G(n) n )

          where  G(n) := min{ j | F(j) >= n }

          and    F(j) := 1            for j = 0
                 F(j) := 2 ^ F(j-1)   for j > 0

          also,  G(n) <= ld n         for all n

   * `&kruskal();'

     This routine carries out the computations associated with Kruskal's
     algorithm.

     Returns an array of hashes (each hash containing the keys "from",
     "to" and "cost" and the corresponding values) representing the
     minimal spanning tree of the graph previously defined by calls to
     "define_vortices" and "define_edges".

     The result can also be found in @Graph::Kruskal::T.

     See the implementation of the subroutine "example" to see how to
     access this array directly (remember to fully qualify the name of
     this array in your program, i.e., use "@Graph::Kruskal::T" instead of
     just "@T", since this array is not exported - or your program will
     not work!)

   * `&example();'

     Demonstrates how to use the various subroutines in this module.

     Computes the minimal spanning tree of a sample graph.

     Just say "use Graph::Kruskal qw(example);" and "&example();" in a
     little Perl script to see it "in action".

DESCRIPTION
===========

   This algorithm computes the Minimal Spanning Tree of a given graph
according to some cost function defined on the edges of that graph.

   Input: A set of vortices which constitute a graph (some cities on a map,
for example), a set of edges (i.e., roads) between the vortices of the
(non-directed and connected) graph (i.e., the edges can be traveled in
either direction, and a path must exist between any two vortices), and the
cost of each edge (for instance, the geographical distance).

   Output: A set of edges forming a spanning tree (i.e., a set of edges
linking all vortices, so that a path exists between any two vortices)
which is free of circles (because it's a tree) and which is minimal in
terms of the cost function defined on the set of edges.

   See Aho, Hopcroft, Ullman, "The Design and Analysis of Computer
Algorithms" for more details on the algorithm.

SEE ALSO
========

   Math::MatrixBool(3), Math::MatrixReal(3), DFA::Kleene(3),
Set::IntegerRange(3), Set::IntegerFast(3), Bit::Vector(3).

VERSION
=======

   This man page documents "Graph::Kruskal" version 2.0.

AUTHOR
======

   Steffen Beyer <sb@sdm.de>.

COPYRIGHT
=========

   Copyright (c) 1995, 1996, 1997 by Steffen Beyer. All rights reserved.

LICENSE
=======

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

base class for Graph file format readers
****************************************

NAME
====

   Graph::Reader - base class for Graph file format readers

SYNOPSIS
========

     package Graph::Reader::MyFormat;
     use Graph::Reader;
     use vars qw(@ISA);
     @ISA = qw(Graph::Reader);

     sub _read_graph
     {
         my ($self, $graph, $FILE) = @_;

         # read $FILE and populate $graph
     }

DESCRIPTION
===========

   Graph::Reader is a base class for Graph file format readers.  A
particular subclass of Graph::Reader will handle a specific file format,
and generate a Graph, represented using Jarkko Hietaniemi's Graph class.

   You should never create an instance of this class yourself, it is only
meant for subclassing. If you try to create an instance of Graph::Reader,
the constructor will throw an exception.

METHODS
=======

new()
-----

   Constructor - generate a new reader instance. This is a virtual method,
or whatever the correct lingo is.  You're not meant to call this on the
base class, it is inherited by the subclasses. Ie if you do something like:

     $reader = Graph::Reader->new();

   It will throw an exception.

read_graph()
------------

   Read a graph from the specified file:

     $graph = $reader->read_graph($file);

   The $file argument can either be a filename, or a filehandle for a
previously opened file.

SUBCLASSING
===========

   To create your own graph format reader, create a module which
subclasses Graph::Reader. For example, suppose DGF is a directed graph
format - create a *Graph::Reader::DGF* module, with the following
structure:

     package Graph::Reader::DGF;

     use Graph::Reader;
     use vars qw(@ISA);
     @ISA = qw(Graph::Reader);

     sub _read_graph
     {
         my $self  = shift;
         my $graph = shift;
         my $FILE  = shift;

         while (<$FILE>)
         {
     	}

         return 1;
     }

     1;

   Note the leading underscore on the *_read_graph()* method.  The base
class provides the public method, and invokes the private method which
you're expected to provide, as above.

   If you want to perform additional initialisation at construction time,
you can provide an *_init()* method, which will be invoked by the base
class's constructor.  You should invoke the superclass's initialiser as
well, as follows:

     sub _init
     {
         my $self = shift;

         $self->SUPER::_init();

         # your initialisation here
     }

   Someone can then use your class as follows:

     use Graph::Reader::DGF;

     $reader = Graph::Reader::DGF->new();
     $graph = $reader->read_graph('foo.dgf');

SEE ALSO
========

Graph
     Jarkko Hietaniemi's modules for representing directed graphs,
     available from CPAN under modules/by-module/Graph/

Algorithms in Perl
     This O'Reilly book has a chapter on directed graphs, which is based
     around Jarkko's modules.

Graph::Reader::XML
     A simple subclass of this class for reading a simple XML format for
     directed graphs.

Graph::Writer
     A baseclass for Graph file format writers.

AUTHOR
======

   Neil Bowers <neilb@cre.canon.co.uk>

COPYRIGHT
=========

   Copyright (c) 2001, Canon Research Centre Europe. All rights reserved.

   This script is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

class for reading a Graph instance from XML
*******************************************

NAME
====

   Graph::Reader::XML - class for reading a Graph instance from XML

SYNOPSIS
========

     use Graph::Reader::XML;
     use Graph;

     $reader = Graph::Reader::XML->new();
     $graph = $reader->read_graph('mygraph.xml');

DESCRIPTION
===========

   Graph::Reader::XML is a perl class used to read a directed graph stored
as XML, and return an instance of the Graph class.

   The XML format is designed to support the Graph classes: it can be used
to represent a single graph with a collection of nodes, and edges between
those nodes.  The graph, nodes, and edges can all have attributes
specified,

   Graph::Reader::XML is a subclass of Graph::Reader, which defines the
generic interface for Graph reader classes.

METHODS
=======

new()
-----

   Constructor - generate a new reader instance.

     $reader = Graph::Reader::XML->new();

   This doesn't take any arguments.

read_graph()
------------

   Read a graph from a file:

     $graph = $reader->read_graph( $file );

   The $file argument can be either a filename or a filehandle of a
previously opened file.

KNOWN BUGS
==========

   Attribute values must be scalar. If they're not, well, you're on your
own.

SEE ALSO
========

Graph::Reader
     The base class for Graph::Reader::XML.

Graph::Writer::XML
     Used to serialise a Graph instance as XML.

Graph
     Jarkko Hietaniemi's classes for representing directed graphs.

AUTHOR
======

   Neil Bowers <neilb@cre.canon.co.uk>

COPYRIGHT
=========

   Copyright (c) 2001, Canon Research Centre Europe. All rights reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

graph traversal
***************

NAME
====

   Graph::Traversal - graph traversal

SYNOPSIS
========

     use Graph::Traversal;

DESCRIPTION
===========

     $s = Graph::Traversal->new($G, %param)

   Returns a new graph search object for the graph $G and the parameters
%param.

   Usually not used directly but instead via frontends like Graph::DFS for
depth-first searching and Graph::BFS for breadth-first searching:

     $dfs = Graph::DFS->new($G, %param)
     $bfs = Graph::BFS->new($G, %param)

   *%param documentation to be written*

     $S->reset

   Resets a graph search object $S to its initial state.

     $v = $s->next_preorder

   Returns the next vertex in preorder of the graph encapsulated within
the search object $s.

     ($u, $v) = $s->next_edge

   Returns the vertices of the next edge of the graph encapsulated within
the search object $s.

     @V = $S->preorder

   Returns all the vertices in preorder of the graph encapsulated within
the search object $S.

     @V = $S->postorder

   Returns all the vertices in postorder of the graph encapsulated within
the search object $S.

     @V = $S->edges

   Returns all the edges of the graph encapsulated within the search
object $S.

     @R = $S->roots

   Returns all the root vertices of the trees of the graph encapsulated
within the search object $S.  "The root vertices" is ambiguous: what
really happens is that either the roots from the previous search made on
the $s are returned; or a preorder search is done and the roots of this
search are returned.

     %R = $S->vertex_roots

   Returns as a hash of ($vertex, $root) pairs all the vertices and the
root vertices of their search trees of the graph encapsulated within the
search object $S.  "The root vertices" is ambiguous; see the documentation
of the roots() method for more details.

COPYRIGHT
=========

   Copyright 1999, O'Reilly & Associates.

   This code is distributed under the same copyright terms as Perl itself.

directed graphs
***************

NAME
====

   Graph::Directed - directed graphs

SYNOPSIS
========

     use Graph::Directed;

     $g = new Graph::Directed;

DESCRIPTION
===========

   See Graph::Base for the available methods.

COPYRIGHT
=========

   Copyright 1999, O'Reilly & Associates.

   This code is distributed under the same copyright terms as Perl itself.

a base class for graph vertices
*******************************

NAME
====

   Graph::Vertex - a base class for graph vertices

SYNOPSIS
========

   *Not to be used directly*.

DESCRIPTION
===========

   This class is not to be used directly because a vertex always must
belong to a graph.  The graph classes will do this right.  Some useful
public methods exist, though.

ADDING AND DELETING VERTICES
----------------------------

   See Graph.

SEE ALSO
========

   See Graph, Graph/Element.

VERSION
=======

   See Graph.

AUTHOR
======

   Jarkko Hietaniemi <`jhi@iki.fi'>

COPYRIGHT
=========

   Copyright 1998, O'Reilly and Associates.

   This code is distributed under the same copyright terms as Perl itself.

base class for Graph file format writers
****************************************

NAME
====

   Graph::Writer - base class for Graph file format writers

SYNOPSIS
========

     package Graph::Writer::MyFormat;
     use Graph::Writer;
     use vars qw(@ISA);
     @ISA = qw(Graph::Writer);

     sub _write_graph
     {
         my ($self, $graph, $FILE) = @_;

         # write $graph to $FILE
     }

DESCRIPTION
===========

   Graph::Writer is a base class for Graph file format writers.  A
particular subclass of Graph::Writer will handle a specific file format,
and generate a Graph, represented using Jarkko Hietaniemi's Graph class.

   You should never create an instance of this class yourself, it is only
meant for subclassing. If you try to create an instance of Graph::Writer,
the constructor will throw an exception.

METHODS
=======

new()
-----

   Constructor - generate a new writer instance. This is a virtual method,
or whatever the correct lingo is.  You're not meant to call this on the
base class, it is inherited by the subclasses. Ie if you do something like:

     $writer = Graph::Writer->new();

   It will throw an exception.

write_graph()
-------------

   Read a graph from the specified file:

     $graph = $writer->write_graph($file);

   The $file argument can either be a filename, or a filehandle for a
previously opened file.

SUBCLASSING
===========

   To create your own graph format writer, create a module which
subclasses Graph::Writer. For example, suppose DGF is a directed graph
format - create a *Graph::Writer::DGF* module, with the following
structure:

     package Graph::Writer::DGF;

     use Graph::Writer;
     use vars qw(@ISA);
     @ISA = qw(Graph::Writer);

     sub _write_graph
     {
         my $self  = shift;
         my $graph = shift;
         my $FILE  = shift;

         while (<$FILE>)
         {
     	}

         return 1;
     }

     1;

   Note the leading underscore on the *_write_graph()* method.  The base
class provides the public method, and invokes the private method which
you're expected to provide, as above.

   If you want to perform additional initialisation at construction time,
you can provide an *_init()* method, which will be invoked by the base
class's constructor.  You should invoke the superclass's initialiser as
well, as follows:

     sub _init
     {
         my $self = shift;

         $self->SUPER::_init();

         # your initialisation here
     }

   Someone can then use your class as follows:

     use Graph::Writer::DGF;

     $writer = Graph::Writer::DGF->new();
     $writer->write_graph($graph, 'foo.dgf');

SEE ALSO
========

Graph
     Jarkko Hietaniemi's modules for representing directed graphs,
     available from CPAN under modules/by-module/Graph/

Algorithms in Perl
     The O'Reilly book has a chapter on directed graphs, which is based
     around Jarkko's modules.

Graph::Writer::Dot
     A simple subclass of this class for writing graphs in the file format
     used by dot, which is part of the graphviz package from AT&T.

Graph::Writer::VCG
     A simple subclass of this class for writing graphs in the file format
     used by VCG, a tool for visualising directed graphs, initially
     developed for visualising compiler graphs.

Graph::Writer::XML
     A simple subclass of this class for writing graphs as XML, using a
     simple graph markup.

Graph::Reader
     A baseclass for Graph file format readers.

AUTHOR
======

   Neil Bowers <neilb@cre.canon.co.uk>

COPYRIGHT
=========

   Copyright (c) 2001, Canon Research Centre Europe. All rights reserved.

   This script is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

write out directed graph in Dot format
**************************************

NAME
====

   Graph::Writer::Dot - write out directed graph in Dot format

SYNOPSIS
========

     use Graph;
     use Graph::Writer::Dot;

     $graph = Graph->new();
     # add edges and nodes to the graph

     $writer = Graph::Writer::Dot->new();
     $writer->write_graph($graph, 'mygraph.dot');

DESCRIPTION
===========

   Graph::Writer::Dot is a class for writing out a directed graph in the
file format used by the dot tool (part of the AT+T graphviz package).  The
graph must be an instance of the Graph class, which is actually a set of
classes developed by Jarkko Hietaniemi.

METHODS
=======

new()
-----

   Constructor - generate a new writer instance.

     $writer = Graph::Writer::Dot->new();

   This doesn't take any arguments.

write_graph()
-------------

   Write a specific graph to a named file:

     $writer->write_graph($graph, $file);

   The $file argument can either be a filename, or a filehandle for a
previously opened file.

SEE ALSO
========

http://www.graphviz.org/
     The home page for the AT+T graphviz toolkit that includes the dot
     tool.

Graph
     Jarkko Hietaniemi's modules for representing directed graphs,
     available from CPAN under modules/by-module/Graph/

Algorithms in Perl
     The O'Reilly book which has a chapter on directed graphs, which is
     based around Jarkko's modules.

Graph::Writer
     The base-class for Graph::Writer::Dot

AUTHOR
======

   Neil Bowers <neilb@cre.canon.co.uk>

COPYRIGHT
=========

   Copyright (c) 2001, Canon Research Centre Europe. All rights reserved.

   This script is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

write out directed graph in VCG format
**************************************

NAME
====

   Graph::Writer::VCG - write out directed graph in VCG format

SYNOPSIS
========

     use Graph;
     use Graph::Writer::VCG;

     $graph = Graph->new();
     # add edges and nodes to the graph

     $writer = Graph::Writer::VCG->new();
     $writer->write_graph($graph, 'mygraph.vcg');

DESCRIPTION
===========

   Graph::Writer::VCG is a class for writing out a directed graph in the
file format used by the *VCG* tool, originally developed for Visualising
Compiler Graphs.  The graph must be an instance of the Graph class, which
is actually a set of classes developed by Jarkko Hietaniemi.

METHODS
=======

new()
-----

   Constructor - generate a new writer instance.

     $writer = Graph::Writer::VCG->new();

   This doesn't take any arguments.

write_graph()
-------------

   Write a specific graph to a named file:

     $writer->write_graph($graph, $file);

   The $file argument can either be a filename, or a filehandle for a
previously opened file.

KNOWN BUGS
==========

   Currently doesn't do anything with attributes - only the structure of
the graph is written out.

SEE ALSO
========

http://www.cs.uni-sb.de/RW/users/sander/html/gsvcg1.html
     The home page for VCG.

Graph
     Jarkko Hietaniemi's modules for representing directed graphs,
     available from CPAN under modules/by-module/Graph/

Algorithms in Perl
     The O'Reilly book which has a chapter on directed graphs, which is
     based around Jarkko's modules.

Graph::Writer
     The base-class for Graph::Writer::VCG

AUTHOR
======

   Neil Bowers <neilb@cre.canon.co.uk>

COPYRIGHT
=========

   Copyright (c) 2001, Canon Research Centre Europe. All rights reserved.

   This script is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

write out directed graph as XML
*******************************

NAME
====

   Graph::Writer::XML - write out directed graph as XML

SYNOPSIS
========

     use Graph;
     use Graph::Writer::XML;

     $graph = Graph->new();
     # add edges and nodes to the graph

     $writer = Graph::Writer::XML->new();
     $writer->write_graph($graph, 'mygraph.xml');

DESCRIPTION
===========

   Graph::Writer::XML is a class for writing out a directed graph in a
simple XML format.  The graph must be an instance of the Graph class,
which is actually a set of classes developed by Jarkko Hietaniemi.

   The XML format is designed to support the Graph classes: it can be used
to represent a single graph with a collection of nodes, and edges between
those nodes.  The graph, nodes, and edges can all have attributes
specified, where an attribute is a (name,value) pair, with the value being
scalar.

METHODS
=======

new()
-----

   Constructor - generate a new writer instance.

     $writer = Graph::Writer::XML->new();

   This doesn't take any arguments.

write_graph()
-------------

   Write a specific graph to a named file:

     $writer->write_graph($graph, $file);

   The $file argument can either be a filename, or a filehandle for a
previously opened file.

KNOWN BUGS
==========

   No attempt is made to validate the XML in any formal way.

   Attribute values must be scalar. If they're not, well, you're on your
own.

SEE ALSO
========

XML::Writer
     The perl module used to actually write out the XML.  It handles
     entities etc.

Graph
     Jarkko Hietaniemi's modules for representing directed graphs,
     available from CPAN under modules/by-module/Graph/

Algorithms in Perl
     The O'Reilly book which has a chapter on directed graphs, which is
     based around Jarkko's modules.

Graph::Writer
     The base-class for Graph::Writer::XML

AUTHOR
======

   Neil Bowers <neilb@cre.canon.co.uk>

COPYRIGHT
=========

   Copyright (c) 2001, Canon Research Centre Europe. All rights reserved.

   This script is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

baseclass for all graph elements
********************************

NAME
====

   Graph::_element - baseclass for all graph elements

SYNOPSIS
========

   *Not intended for public use*.

DESCRIPTION
===========

VERSION
=======

   Version 0.01.

AUTHOR
======

   Jarkko Hietaniemi, <`jhi@iki.fi'>

COPYRIGHT
=========

   Copyright 1998, O'Reilly & Associates.

   This code is distributed under the same copyright terms as perl itself.

Interface to the GraphViz graphing tool
***************************************

NAME
====

   GraphViz - Interface to the GraphViz graphing tool

SYNOPSIS
========

     use GraphViz;

     my $g = GraphViz->new();

     $g->add_node('London');
     $g->add_node('Paris', label => 'City of\nlurve');
     $g->add_node('New York');

     $g->add_edge('London' => 'Paris');
     $g->add_edge('London' => 'New York', label => 'Far');
     $g->add_edge('Paris' => 'London');

     print $g->as_png;

DESCRIPTION
===========

   This module provides an interface to layout and image generation of
directed and undirected graphs in a variety of formats (PostScript, PNG,
etc.) using the "dot" and "neato" programs from the GraphViz project
(http://www.graphviz.org/).

What is a graph?
----------------

   A (undirected) graph is a collection of nodes linked together with
edges.

   A directed graph is the same as a graph, but the edges have a direction.

What is GraphViz?
-----------------

   This module is an interface to the GraphViz toolset
(http://www.graphviz.org/). The GraphViz tools provide automatic graph
layout and drawing. This module simplifies the creation of graphs and
hides some of the complexity of the GraphViz module.

   Laying out graphs in an aesthetically-pleasing way is a hard problem -
there may be multiple ways to lay out the same graph, each with their own
quirks. GraphViz luckily takes part of this hard problem and does a pretty
good job in a couple of seconds for most graphs.

Why should I use this module?
-----------------------------

   Observation aids comprehension. That is a fancy way of expressing that
popular faux-Chinese proverb: "a picture is worth a thousand words".

   Text is not always the best way to represent anything and everything to
do with a computer programs. Pictures and images are easier to assimilate
than text. The ability to show a particular thing graphically can aid a
great deal in comprehending what that thing really represents.

   Diagrams are computationally efficient, because information can be
indexed by location; they group related information in the same area. They
also allow relations to be expressed between elements without labeling the
elements.

   A friend of mine used this to his advantage when trying to remember
important dates in computer history. Instead of sitting down and trying to
remember everything, he printed over a hundred posters (each with a date
and event) and plastered these throughout his house. His spatial memory is
still so good that asked last week (more than a year since the experiment)
when Lisp was invented, he replied that it was upstairs, around the corner
from the toilet, so must have been around 1958.

   Spreadsheets are also a wonderfully simple graphical representation of
computational models.

METHODS
=======

new
---

   This is the constructor. It currently takes one attribute, 'directed',
which defaults to 1 (true) - this specifies directed (tree-like) graphs.
Setting this to zero produces undirected graphs, which are layed out
differently.

     my $g = GraphViz->new();
     my $g = GraphViz->new(directed => 0);

add_node
--------

   A graph consists of at least one node. All nodes have a name attached
which uniquely represents that node.

   The add_node method creates a new node and optionally assigns it
attributes.

   The simplest form is used when no attributes are required, in which the
string represents the name of the node:

     $g->add_node('Paris');

   Various attributes are possible: "label" provides a label for the node
(the label defaults to the name if none is specified). The label can
contain embedded newlines with '\n', as well as '\c', '\l', '\r' for
center, left, and right justified lines:

     $g->add_node('Paris', label => 'City of\nlurve');

   Note that multiple attributes can be specified. Other attributes
include:

height, width
     sets the minimum height or width

shape
     sets the node shape. This can be one of: 'record', 'plaintext',
     'ellipse', 'circle', 'egg', 'triangle', 'box', 'diamond', 'trapezium',
     'parallelogram', 'house', 'hexagon', 'octagon'

fontsize
     sets the label size in points

fontname
     sets the label font family name

color
     sets the outline colour, and the default fill colour if the 'style' is
     'filled' and 'fillcolor' is not specified

     A colour value may be "h,s,v" (hue, saturation, brightness) floating
     point numbers between 0 and 1, or an X11 color name such as 'white',
     'black', 'red', 'green', 'blue', 'yellow', 'magenta', 'cyan', or
     'burlywood'

fillcolor
     sets the fill colour when the style is 'filled'. If not specified, the
     'fillcolor' when the 'style' is 'filled' defaults to be the same as
     the outline color

style
     sets the style of the node. Can be one of: 'filled', 'solid',
     'dashed', 'dotted', 'bold', 'invis'

URL
     sets the url for the node in image map and PostScript files. The
     string '\N' value will be replaced by the node name. In PostScript
     files, URL information is embedded in such a way that Acrobat
     Distiller creates PDF files with active hyperlinks

   If you wish to add an anonymous node, that is a node for which you do
not wish to generate a name, you may use the following form, where the
GraphViz module generates a name and returns it for you. You may then use
this name later on to refer to this node:

     my $nodename = $g->add_node('label' => 'Roman city');

   Nodes can be clustered together with the "cluster" attribute, which is
drawn by having a labelled rectangle around all the nodes in a cluster.

     $g->add_node('London', cluster => 'Europe');
     $g->add_node('Amsterdam', cluster => 'Europe');

   Also, nodes can consist of multiple parts (known as ports). This is
implemented by passing an array reference as the label, and the parts are
displayed as a label. GraphViz has a much more complete port system, this
is just a simple interface to it. See the 'from_port' and 'to_port'
attributes of add_edge:

     $g->add_node('London', label => ['Heathrow', 'Gatwick']);

add_edge
--------

   Edges are directed (or undirected) links between nodes. This method
creates a new edge between two nodes and optionally assigns it attributes.

   The simplest form is when now attributes are required, in which case
the nodes from and to which the edge should be are specified. This works
well visually in the program code:

     $g->add_edge('London' => 'Paris');

   Attributes such as 'label' can also be used. This specifies a label for
the edge.  The label can contain embedded newlines with '\n', as well as
'\c', '\l', '\r' for center, left, and right justified lines.

     $g->add_edge('London' => 'New York', label => 'Far');

   Note that multiple attributes can be specified. Other attributes
include:

minlen
     sets an integer factor that applies to the edge length (ranks for
     normal edges, or minimum node separation for flat edges)

weight
     sets the integer cost of the edge. Values greater than 1 tend to
     shorten the edge. Weight 0 flat edges are ignored for ordering nodes

fontsize
     sets the label type size in points

fontname
     sets the label font family name

fontcolor
     sets the label text colour

color
     sets the line colour for the edge

     A colour value may be "h,s,v" (hue, saturation, brightness) floating
     point numbers between 0 and 1, or an X11 color name such as 'white',
     'black', 'red', 'green', 'blue', 'yellow', 'magenta', 'cyan', or
     'burlywood'

style
     sets the style of the node. Can be one of: 'filled', 'solid',
     'dashed', 'dotted', 'bold', 'invis'

dir
     sets the arrow direction. Can be one of: 'forward', 'back', 'both',
     'none'

tailclip, headclip
     when set to false disables endpoint shape clipping

arrowhead, arrowtail
     sets the type for the arrow head or tail. Can be one of: 'none',
     'normal', 'inv', 'dot', 'odot', 'invdot', 'invodot.'

arrowsize
     sets the arrow size: (norm_length=10,norm_width=5,
     inv_length=6,inv_width=7,dot_radius=2)

headlabel, taillabel
     sets the text for port labels. Note that labelfontcolor,
     labelfontname, labelfontsize are also allowed

labeldistance, port_label_distance
     sets the distance from the edge / port to the label. Also labelangle

decorateP
     if set, draws a line from the edge to the label

samehead, sametail
     if set aim edges having the same value to the same port, using the
     average landing point

constraint
     if set to false causes an edge to be ignored for rank assignment

   Additionally, adding edges between ports of a node is done via the
'from_port' and 'to_port' parameters, which currently takes in the offset
of the port (ie 0, 1, 2...).

     $g->add_edge('London' => 'Paris', from_port => 0);

as_canon, as_text, as_gif etc. methods
--------------------------------------

   There are a number of methods which generate input for dot / neato or
output the graph in a variety of formats.

as_canon
     The as_canon method returns the canonical dotneato file which
     corresponds to the graph. It does not layout the graph - every other
     as_* method does.

          print $g->as_canon;

          # prints out something like:
          digraph test {
              node [	label = "\N" ];
              London [label=London];
              Paris [label="City of\nlurve"];
              New_York [label="New York"];
              London -> Paris;
              London -> New_York [label=Far];
              Paris -> London;
          }

as_text
     The as_text method returns text which is a layed-out dot /
     neato-format file.

          print $g->as_text;

          # prints out something like:
          digraph test {
              node [	label = "\N" ];
              graph [bb= "0,0,162,134"];
              London [label=London, pos="33,116", width="0.89", height="0.50"];
              Paris [label="City of\nlurve", pos="33,23", width="0.92", height="0.62"];
              New_York [label="New York", pos="123,23", width="1.08", height="0.50"];
              London -> Paris [pos="e,27,45 28,98 26,86 26,70 27,55"];
              London -> New_York [label=Far, pos="e,107,40 49,100 63,85 84,63 101,46", lp="99,72"];
              Paris -> London [pos="s,38,98 39,92 40,78 40,60 39,45"];
          }

as_ps
     Returns a string which contains a layed-out PostScript-format file.

          print $g->as_ps;

as_hpgl
     Returns a string which contains a layed-out HP pen plotter-format
     file.

          print $g->as_hpgl;

as_pcl
     Returns a string which contains a layed-out Laserjet printer-format
     file.

          print $g->as_pcl;

as_mif
     Returns a string which contains a layed-out FrameMaker
     graphics-format file.

          print $g->as_mif;

as_pic
     Returns a string which contains a layed-out PIC-format file.

          print $g->as_pic;

as_gd
     Returns a string which contains a layed-out GD-format file.

          print $g->as_gd;

as_gd2
     Returns a string which contains a layed-out GD2-format file.

          print $g->as_gd2;

as_gif
     Returns a string which contains a layed-out GIF-format file.

          print $g->as_gif;

as_jpeg
     Returns a string which contains a layed-out JPEG-format file.

          print $g->as_jpeg;

as_png
     Returns a string which contains a layed-out PNG-format file.

          print $g->as_png;

as_wbmp
     Returns a string which contains a layed-out Windows BMP-format file.

          print $g->as_wbmp;

as_ismap
     Returns a string which contains a layed-out HTML client-side image map
     format file.

          print $g->as_ismap;

as_imap
     Returns a string which contains a layed-out HTML server-side image map
     format file.

          print $g->as_imap;

as_vrml
     Returns a string which contains a layed-out VRML-format file.

          print $g->as_vrml;

as_vtx
     Returns a string which contains a layed-out VTX (Visual Thought)
     format file.

          print $g->as_vtx;

as_mp
     Returns a string which contains a layed-out MetaPost-format file.

          print $g->as_mp;

as_fig
     Returns a string which contains a layed-out FIG-format file.

          print $g->as_fig;

as_svg
     Returns a string which contains a layed-out SVG-format file.

          print $g->as_svg;

as_plain
     Returns a string which contains a layed-out simple-format file.

          print $g->as_plain;

NOTES
=====

   Older versions of GraphViz used a slightly different syntax for node
and edge adding (with hash references). The new format is slightly
clearer, although for the moment we support both. Use the new, clear
syntax, please.

AUTHOR
======

   Leon Brocard <`acme@astray.com'>

COPYRIGHT
=========

   Copyright (C) 2000-1, Leon Brocard

   This module is free software; you can redistribute it or modify it
under the same terms as Perl itself.

graph database tables and relations
***********************************

NAME
====

   GraphViz::DBI - graph database tables and relations

SYNOPSIS
========

     use GraphViz::DBI;
     print GraphViz::DBI->new($dbh)->graph_tables->as_png;

DESCRIPTION
===========

   This module constructs a graph for a database showing tables and
connecting them if they are related. While or after constructing the
object, pass an open database handle, then call `graph_tables' to
determine database metadata and construct a GraphViz graph from the table
and field information.

METHODS
=======

   The following methods are defined by this class; all other method calls
are passed to the underlying GraphViz object:

new( [$dbh] )
     Constructs the object; also creates a GraphViz object. The constructor
     accepts an optional open database handle.

set_dbh($dbh)
     Sets the database handle.

get_dbh()
     Returns the database handle.

is_table($table)
     Checks the database metadata whether the argument is a valid table
     name.

is_foreign_key($table, $field)
     Determines whether the field belonging to the table is a foreign key
     into some other table. If so, it is expected to return the name of
     that table. If not, it is expected to return a false value.

     For example, if there is a table called "product" and another table
     contains a field called "product_id", then to indicate that this
     field is a foreign key into the product table, the method returns
     "product". This is the logic implemented in this class. You can
     override this method in a subclass to suit your needs.

graph_tables()
     This method goes through all tables and fields and calls appropriate
     methods to determine which tables and which dependencies exist, then
     hand the results over to GraphViz. It returns the GraphViz object.

TODO
====

   * Test with various database drivers to see whether they support the
     metadata interface.

   * Make each table a vertical port with dependencies using those ports.

   * Provide the possibility to name edges to specify the type of
     relationship ('has-a', 'is-a', etc.).

BUGS
====

   None known so far. If you find any bugs or oddities, please do inform
the author.

AUTHOR
======

   Marcel GrE<uuml>nauer <marcel@codewerk.com>

COPYRIGHT
=========

   Copyright 2001 Marcel GrE<uuml>nauer. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1), GraphViz(3pm).

Visualise data structures as a graph
************************************

NAME
====

   GraphViz::Data::Grapher - Visualise data structures as a graph

SYNOPSIS
========

     use GraphViz::Data::Grapher;

     my $graph = GraphViz::Data::Grapher->new($structure);
     print $g->as_png;

DESCRIPTION
===========

   This module makes it easy to visualise Perl data structures. Data
structures can grow quite large and it can be hard to understand the quite
how the structure fits together.

   Data::Dumper can help by representing the structure as a text
heirarchy, but GraphViz::Data::Grapher goes a step further and visualises
the structure by drawing a graph which represents the data structure.

   Arrays are represented by records. Scalars are represented by
themselves. Array references are represented by a '@' symbol, which is
linked to the array. Hash references are represented by a '%' symbol,
which is linked to an array of keys, which each link to their value.
Object references are represented by 'Object', which then links to the
type of the object. Undef is represented by 'undef'.

METHODS
=======

new
---

   This is the constructor. It takes a list, which is the data structure
to be visualised. A GraphViz object is returned.

     my $graph = GraphViz::Data::Grapher->new([3, 4, 5], "Hello");

as_*
----

   The data structure can be visualised in a number of different graphical
formats. Methods include as_ps, as_hpgl, as_pcl, as_mif, as_pic, as_gd,
as_gd2, as_gif, as_jpeg, as_png, as_wbmp, as_ismap, as_imap, as_vrml,
as_vtx, as_mp, as_fig, as_svg. See the GraphViz documentation for more
information. The two most common methods are:

     # Print out a PNG-format file
     print $g->as_png;

     # Print out a PostScript-format file
     print $g->as_ps;

AUTHOR
======

   Leon Brocard <`acme@astray.com'>

COPYRIGHT
=========

   Copyright (C) 2000-1, Leon Brocard

   This module is free software; you can redistribute it or modify it
under the same terms as Perl itself.

Graphing @ISA hierarchies at run-time
*************************************

NAME
====

   GraphViz::ISA - Graphing @ISA hierarchies at run-time

SYNOPSIS
========

     use GraphViz::ISA;
     my $p = Some::Class->new;

     my $g1 = GraphViz::ISA->new($p);
     print $g1->as_png;

     my $g2 = GraphViz::ISA->new('Some::Other::Module');
     print $g2->as_png;

DESCRIPTION
===========

   This class constructs a graph showing the `@ISA' hierarchy (note: not
object hierarchies) from a package name or a blessed scalar.

METHODS
=======

   The following methods are defined by this class; all other method calls
are passed to the underlying GraphViz object:

new()
     This constructs the object itself and takes a parameter. The parameter
     can be either a package name or a scalar blessed into a package. It
     then calls isatree() and hands the result to graph(). Then it returns
     the newly constructed object.

isatree()
     Takes a package name as a parameter and traverses the indicated
     package's `@ISA' recursively, constructing a hash of hashes. If a
     package's `@ISA' is empty, it has an empty hashref as the value in
     the tree.

graph()
     Takes a tree previously constructed by isatree() and traverses it,
     creating nodes and edges as it goes along.

TODO
====

test.pl
BUGS
====

   None known so far. If you find any bugs or oddities, please do inform
the author.

AUTHOR
======

   Marcel GrE<uuml>nauer, <marcel@codewerk.com>

COPYRIGHT
=========

   Copyright 2001 Marcel GrE<uuml>nauer. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1), GraphViz(3pm).

subclass of GraphViz with no nodes
**********************************

NAME
====

   GraphViz::No - subclass of GraphViz with no nodes

SYNOPSIS
========

     use GraphViz::No;

     my $g = GraphViz::No->new();
     # methods as for GraphViz

DESCRIPTION
===========

   Graphs produced by GraphViz are occasionally huge, making it hard to
observe the structure. This subclass removes the nodes, so that only the
edges are visible. This allows the structure to stand out.

METHODS
=======

   As for GraphViz.

AUTHOR
======

   Leon Brocard <`acme@astray.com'>

COPYRIGHT
=========

   Copyright (C) 2000-1, Leon Brocard

   This module is free software; you can redistribute it or modify it
under the same terms as Perl itself.

Visualise grammars
******************

NAME
====

   GraphViz::Parse::RecDescent - Visualise grammars

SYNOPSIS
========

     use GraphViz::Parse::RecDescent;

     # Either pass in the grammar
     my $graph = GraphViz::Parse::RecDescent->new($grammar);
     print $g->as_png;

     # or a Parse::RecDescent parser object
     my $graph = GraphViz::Parse::RecDescent->new($parser);
     print $g->as_ps;

DESCRIPTION
===========

   This module makes it easy to visualise Parse::RecDescent grammars.
Writing Parse::RecDescent grammars is tricky at the best of times, and
grammars almost always evolve in ways unforseen at the start. This module
aims to visualise a grammar as a graph in order to make the structure
clear and aid in understanding the grammar.

   Rules are represented as nodes, which have their name on the left of
the node and their productions on the right of the node. The subrules
present in the productions are represented by edges to the subrule nodes.

   Thus, every node (rule) should be connected to the graph - otherwise a
rule is not part of the grammar.

   This uses the GraphViz module to draw the graph. Thanks to Damian
Conway for the idea.

   Note that the Parse::RecDescent module should be installed.

METHODS
=======

new
---

   This is the constructor. It takes one mandatory argument, which can
either be the grammar text or a Parse::RecDescent parser object of the
grammar to be visualised. A GraphViz object is returned.

     # Either pass in the grammar
     my $graph = GraphViz::Parse::RecDescent->new($grammar);

     # or a Parse::RecDescent parser object
     my $graph = GraphViz::Parse::RecDescent->new($parser);

as_*
----

   The grammar can be visualised in a number of different graphical
formats. Methods include as_ps, as_hpgl, as_pcl, as_mif, as_pic, as_gd,
as_gd2, as_gif, as_jpeg, as_png, as_wbmp, as_ismap, as_imap, as_vrml,
as_vtx, as_mp, as_fig, as_svg. See the GraphViz documentation for more
information. The two most common methods are:

     # Print out a PNG-format file
     print $g->as_png;

     # Print out a PostScript-format file
     print $g->as_ps;

BUGS
====

   Translating the grammar to a graph is accomplished by peeking inside
the internals of a parser object, which is a tad scary. A new version of
Parse::RecDescent with different internals may break this module.

   At the moment, almost all Parse::RecDescent directives are supported.
If you find one that has been missed - let me know!

   Unfortunately, alternations (such as the following) do not produce very
pretty graphs, due to the fact that they are implicit (unamed) rules and
are implemented by new long-named subrules.

     character: 'the' ( good | bad | ugly ) /dude/

   Hopefully Parse::FastDescent will make this all much easier.

AUTHOR
======

   Leon Brocard <`acme@astray.com'>

COPYRIGHT
=========

   Copyright (C) 2001, Leon Brocard

   This module is free software; you can redistribute it or modify it
under the same terms as Perl itself.

use graphviz without installing it
**********************************

NAME
====

   GraphViz::Remote - use graphviz without installing it

SYNOPSIS
========

     use GraphViz::Remote;

     my $g = GraphViz::Remote->new();
     # methods as for GraphViz

DESCRIPTION
===========

   Installing the graphviz tools dot and neato is occasionally tricky.
This module allows you to send your GraphViz object across the Internet to
a GraphViz server which processes the graph with the graphviz tools. That
way, you do not need to install graphviz locally.

METHODS
=======

   As for GraphViz.

NOTES
=====

   This module functions by running dot and neato on my own personal
webserver, so please do not use this script too often or with large
graphs. If you intend to use GraphViz a lot, please install it locally!
Many thanks.

AUTHOR
======

   Leon Brocard <`acme@astray.com'>

COPYRIGHT
=========

   Copyright (C) 2001, Leon Brocard

   This module is free software; you can redistribute it or modify it
under the same terms as Perl itself.

subclass of GraphViz with small nodes
*************************************

NAME
====

   GraphViz::Small - subclass of GraphViz with small nodes

SYNOPSIS
========

     use GraphViz::Small;

     my $g = GraphViz::Small->new();
     # methods as for GraphViz

DESCRIPTION
===========

   Graphs produced by GraphViz are occasionally huge, making it hard to
observe the structure. This subclass simply makes the nodes small and
empty, allowing the structure to stand out.

METHODS
=======

   As for GraphViz.

AUTHOR
======

   Leon Brocard <`acme@astray.com'>

COPYRIGHT
=========

   Copyright (C) 2000-1, Leon Brocard

   This module is free software; you can redistribute it or modify it
under the same terms as Perl itself.

Visualise XML as a tree
***********************

NAME
====

   GraphViz::XML - Visualise XML as a tree

SYNOPSIS
========

     use GraphViz::XML;

     my $graph = GraphViz::XML->new($xml);
     print $g->as_png;

DESCRIPTION
===========

   This module makes it easy to visualise XML as a tree. XML is hard for
humans to grasp, especially if the XML is computer-generated. This modules
aims to visualise the XML as a graph in order to make the structure of the
XML clear and to aid in understanding the XML.

   XML elements are represented as diamond nodes, with links to elements
within them. Character data is represented in round nodes.

   Note that the XML::Twig module should be installed.

METHODS
=======

new
---

   This is the constructor. It takes one mandatory argument, which is the
XML to be visualised. A GraphViz object is returned.

     my $graph = GraphViz::XML->new($xml);

as_*
----

   The XML can be visualised in a number of different graphical formats.
Methods include as_ps, as_hpgl, as_pcl, as_mif, as_pic, as_gd, as_gd2,
as_gif, as_jpeg, as_png, as_wbmp, as_ismap, as_imap, as_vrml, as_vtx,
as_mp, as_fig, as_svg. See the GraphViz documentation for more
information. The two most common methods are:

     # Print out a PNG-format file
     print $g->as_png;

     # Print out a PostScript-format file
     print $g->as_ps;

BUGS
====

   GraphViz tends to reorder the nodes. I hope to find a work around soon
(possibly with ports).

AUTHOR
======

   Leon Brocard <`acme@astray.com'>

COPYRIGHT
=========

   Copyright (C) 2001, Leon Brocard

   This module is free software; you can redistribute it or modify it
under the same terms as Perl itself.

defines RGB values for common color names
*****************************************

NAME
====

   Graphics::ColorNames - defines RGB values for common color names

SYNOPSIS
========

     use Graphics::ColorNames qw( hex2tuple );

     tie %NameTable, 'Graphics::ColorNames', 'X';

     my $rgbhex = $NameTable{'green'};  # returns '00ff00'
     my @rgbtup = hex2tuple( $rgbhex ); # returns (0, 255, 0)

DESCRIPTION
===========

   This module defines RGB values for common color names. The intention is
to (1) provide a common module that authors can use with other modules to
specify colors; and (2) free module authors from having to "re-invent the
wheel" whenever they decide to give the users the option of specifying a
color by name rather than RGB value.

Usage
-----

   The interface is through a tied hash:

     tie %NAMETABLE, 'Graphics::ColorNames', SCHEME

   where `%NAMETABLE' is the tied hash and `SCHEME' is the color scheme.
Currently three schemes are available:

X
     550 color names used in X-Windows. *This is the default naming
     scheme*, since it provides the most names.

HTML
     16 common color names defined in the HTML 4.0 specification. These
     names are also used with CSS and SVG.

Windows
     16 commom color names used with Microsoft Windows and related
     products.  These are actually the same colors as HTML, although with
     different names.

   RGB values can be retrieved with a case-insensitive hash key:

     $rgb = $colors{'AliceBlue'};

   The value returned is in the six-digit hexidecimal format used in HTML
and CSS (without the initial '#'). To convert it to separate red, green,
and blue values (between 0 and 255), use the `hex2tuple' function:

     @rgb = hex2tuple( $colors{'AliceBlue'} );

   The `hex2tuple' function is not exported by default. You must specify it
explicitly when you 'use' the module.

CAVEAT
======

   This module is experimental. The interface may change.

AUTHOR
======

   Robert Rothenberg <rrwo@cpan.org>

LICENSE
=======

   Copyright (c) 2001 Robert Rothenberg. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

HTML color names and equivalent RGB values
******************************************

NAME
====

   Graphics::ColorNames::HTML - HTML color names and equivalent RGB values

SYNOPSIS
========

     require Graphics::ColorNames::HTML;

     $NameTable = Graphics::ColorNames::HTML->NamesRgbTable();
     $RgbBlack  = $NameTable->{black};

DESCRIPTION
===========

   This module defines color names and their associated RGB values from the
HTML 4.0 Specification.

SEE ALSO
========

   `Graphics::ColorNames',  HTML 4.0 Specificiation <http://www.w3.org>

AUTHOR
======

   Robert Rothenberg <rrwo@cpan.org>

Windows color names and equivalent RGB values
*********************************************

NAME
====

   Graphics::ColorNames::Windows - Windows color names and equivalent RGB
values

SYNOPSIS
========

     require Graphics::ColorNames::Windows;

     $NameTable = Graphics::ColorNames::Windows->NamesRgbTable();
     $RgbBlack  = $NameTable->{black};

DESCRIPTION
===========

   This module defines color names and their associated RGB values used in
Microsoft Windows.

SEE ALSO
========

   `Graphics::ColorNames'

AUTHOR
======

   Robert Rothenberg <rrwo@cpan.org>

X-Windows color names and equivalent RGB values
***********************************************

NAME
====

   Graphics::ColorNames::X - X-Windows color names and equivalent RGB
values

SYNOPSIS
========

     require Graphics::ColorNames::X;

     $NameTable = Graphics::ColorNames::X->NamesRgbTable();
     $RgbBlack  = $NameTable->{black};

DESCRIPTION
===========

   This module defines color names and their associated RGB values used in
X-Windows.

SEE ALSO
========

   `Graphics::ColorNames',

AUTHOR
======

   Robert Rothenberg <rrwo@cpan.org>

Perl extension for libplot plotting library
*******************************************

NAME
====

   Graphics::Libplot - Perl extension for libplot plotting library

SYNOPSIS
========

     use Graphics::Libplot ':All';

DESCRIPTION
===========

   This module lets you create plots by calling the routines in the libplot
library.  The libplot library is included in the  plotutils package.
Wrappers for each published C function are present. So the section of the
plotutils info pages  on programming in C should be your main reference.
There are a few possible confusions, which are noted below.

   Some of the C routines require character constants rather than strings.
When using the equivalent perl function, you must wrap the character with
the 'ord' function. For instance,  alabel(ord 'c', ord 'c', "some text");
, will write some centered text.

EXPORTING FUNCTIONS
===================

   None of the libplot functions is exported by default. If you do not
import any functions you must prepend the module name to each function.
To call the openpl() function you would give,

   Graphics::Libplot::openpl();

   However, if you include the library with

   use Graphics::Libplot ':All'

   then all of the functions will be exported, and you do not need to
prepend the module name.  In this case you need to be careful because
there are many function names which may collide with others in your
program.

   On the other hand you can use one of

     use Graphics::Libplot ':INTEGERLOW'
     use Graphics::Libplot ':FLOATLOW'

   to get just integer or just floating point plotting.

   Be aware that the interface is still under development so more names
will be added, and your scripts may need to be changed.

EXAMPLES
========

   There are additional examples included in the source distribution.
This example draws a spiraling box pattern.

     use Graphics::Libplot ':ALL';
     $SIZE=100;
     parampl ("BITMAPSIZE", "700x700");
     $handle = newpl("X", stdin, stdout, stderr); # open xwindow display
     selectpl($handle);
     openpl();
     fspace(-$SIZE,-$SIZE, $SIZE, $SIZE); # specify user coord system
     pencolorname ("blue");
     fontname("HersheySerif");
     $s = 10;
     $f = 10;
     $sf = 1- .0012;
     for($i=1;$i<3000;$i++){
         fscale($sf,$sf);
         fbox(60+$s*sin($i/$f),
     	  60+$s*sin($i/$f),
     	  75-$s*cos($i/$f),
     	  75-$s*cos($i/$f));
        frotate(1);
     }
     closepl();
     selectpl(0);
     deletepl($handle);

   Substituting "ps" for "X" in the above example produces postscript on
the standard output stream.

AUTHOR
======

   John Lapeyre <lapeyre@physics.arizona.edu> wrote this perl interface.

   The libplot C library is developed by Robert Maier.

COPYRIGHT
=========

   libplot-perl is copyrighted by John Lapeyre and may be distributed only
under the terms of either the Gnu General Public License, or of the perl
Artistic License.

SEE ALSO
========

   perl(1).

Perl extension for C++ plotter library from GNU plotutils
*********************************************************

NAME
====

   Graphics::Plotter - Perl extension for C++ plotter library from GNU
plotutils

SYNOPSIS
========

     use Graphics::Plotter::<Type>;
     use Graphics::Plotter::<Type> qw(parampl);
     use Graphics::Plotter::<Type> qw(:marker_symbols :op_codes);
     use Graphics::Plotter::<Type> qw(:all);

EXAMPLE
=======

     $handle = Graphics::Plotter::X->new(STDIN,STDOUT,STDERR);

     if ($handle->openpl() < 0) {
     	die "Could not create plotter: $!\n";
     }

     $handle->fspace(0,0,1000,1000);
     $handle->flinewidth(0.25);
     $handle->pencolorname("red");
     $handle->erase();
     $handle->fmove(600,300);
     $handle->line(0,20,40 80);
     if ($handle->closepl() < 0) { die "closepl: $!\n";}

DESCRIPTION
===========

   Graphics::Plotter module is the Perl implementation of the GNU
plotutils' libplotter library - C++ function library for
device-independent two-dimensional vector graphics.  There is also libplot
library, based on C code, but with C++ library you do not need to switch
between plotters.

   The plotutils distribution is written by         Robert Maier
<rsm@math.arizona.edu>
(http://www.gnu.org/software/plotutils/plotutils.html).  Descriptions of
functions are based on Chapter 8 of plotutils info documentation.

   The latest version of Graphics::Plotter perl module is available at
   http://w3.man.torun.pl/~makler/prog/Plotter/

   The perl program can produce output in one of the following formats:

     X - new window on an X Window System display
     Xdrawable - existed X window or pixmap
     PNM - This is "portable anymap" format (PBM, PGM and PPM)
     GIF - Pseudo GIF (GIF format without LZW compression)
     AI - Adobe Illustrator (parameter ai)
     PS - idraw-editable Postscript (ps)
     Fig - xfig-editable format (fig)
     PCL - HP Printer Control Language format (pcl)
     HPGL - HP Graphics Language (hpgl)
     Tek - understood by Tektronix 4014 terminals (tek)
     Metafile - device-independent GNU graphics format (meta)

   To open a plotter you have to create a plotter object, e.g.:

FUNCTION SUMMARY
================

   This summary is BASED on plotutils info documentation. See plotutils
WWW page for more complete, more current, and more accurate description.
This summary is for the orientation only, and should be enough is you do
not ancounter any problem, and not using specific driver functions.

Construction/Destruction of Plotters
------------------------------------

new ()
new (outfile)
new (infile,outfile,errfile)
     creates a Plotter. You can select output, input and error filehandles
     for that Plotter. It returns the handle which is necessary for
     manipulating the Plotter. E.g.

          $object = Graphics::Plotter::X->new();
          # or even
          $disp_type = 'Meta'; # or 'X', 'AI', 'PS', etc.
          $plotter = "Graphics::Plotter" . $disp_type;
          $object = $plotter->new(STDIN, STDOUT, STDERR);

     The default output is STDOUT.  All the commands should be passed to
     the previously created plotter object, e.g. $object->function().

     First command should be openpl(), which opens a plotter.  Program
     should close that plotter with the command closepl().  If plotter is
     opened then you can manipulate plotter, e.g. drawing lines, cirles,
     changing colors etc.

openpl ()
     opens a plotter, i.e., begins a page of graphics. This resets the
     Plotter's drawing attributes to their default values. A negative
     return value indicates the Plotter could not be opened.

closepl ()
     closepl closes a Plotter, i.e., ends a page of graphics. A negative
     return value indicates the Plotter could not be closed.

flushpl ()
     flushes all plotting commands to the display device.

havecap (s)
     havecap tests whether or not a Plotter, which need not be open, has a
     specified capability. The return value is 0, 1, or 2, signifying
     no/yes/maybe.  For unrecognized capabilities the return value is zero.

parampl (parameter,value)
     Sets the value of the device driver parameter to value. E.g.

     parampl("BG_COLOR", "blue");

     sets the background color.

erase ()
     begins the next frame of a multiframe page, by clearing all previously
     plotted objects from the graphics display, and filling it with the
     background color (if any).

bgcolor (red, green, blue)
     bgcolor sets the background color for the Plotter's graphics display,
     using a 48-bit RGB color model. The arguments red, green and blue
     specify the red, green and blue intensities of the background color.
     Each is an integer in the range 0x0000...0xffff, i.e., 0...65535.

bgcolorname (name)
     bgcolorname sets the background color for the graphics display to be
     name.  unrecognized colors are interpreted as "white". bgcolorname
     and bgcolor has an effect only on X Plotters and X Drawable Plotters.

space (x0,y0,x1,y1) =item fspace (x0, y0, x1, y1)
     take two pairs of arguments, specifying the positions of the lower
     left corner and upper right corner of the graphics display, in user
     coordinates.  One of these operations must be performed at the
     beginning of each page of graphics, i.e., immediately after openpl is
     invoked.

space2 (x0,y0,x1,y1) =item fspace2 (x0, y0, x1, y1, x2, y2)
     space2 and fspace2 are extended versions of space and fspace, and may
     be used instead. Their arguments are the three defining vertices of
     an `Affine window' (a drawing parallelogram), in user coordinates.
     The specified vertices are the lower left, the lower right, and the
     upper left. This window will be mapped affinely onto the graphics
     display.

warning_handler (SUBPTR)
     warning_handler sets the default handler for warning messages (e.g.
     if there are some strange characters in label() function argument).
     SUBPTR means a pointer to subroutine. The warning message is available
     in @_ array variable. By default warning messages are displayed to
     the errfile filehandle specified in new() function, as "libplot:
     message". Example of use:

     warning_handler( sub { print "WARNING: $[$[]\n" } );

error_handler (SUBPTR)
     error_handler sets the default handler for error messages. SUBPTR
     means a pointer to subroutine. The error message is available in @_
     array variable.  By default error messages are displayed to the
     errfile filehandle specified in new() function, as "libplot: error:
     message".  Example of use:

     error_handler( \&print_error );

Drawing functions
-----------------

   The following are the "drawing functions". When invoked on a Plotter,
these functions cause it to draw objects (paths, circles, ellipses,
points, markers, and text strings) on the associated graphics display. A
path is a sequence of line segments and arcs (either circular or
elliptic). Paths may be drawn incrementally, one line segment or arc at a
time.

alabel (x_justify, y_justify, s)
     Draws a justified text string (s). x_justify could be "l", "c" or "r"
     (left, center and right justification. y_justify could be "b", "x",
     "c" or "t" (bottom, baseline, center and top of the string will be
     placed even with the current graphics cursor position.

arc (xc,yc,x0,y0,x1,y1)
farc (xc, yc, x0, y0, x1, y1)
farcrel (dxc, dyc, dx0, dy0, dx1, dy1)
     arc and farc take six arguments specifying the beginning (x0, y0),
     end (x1, y1), and center (xc, yc) of a circular arc. arcrel and
     farcrel use cursor-relative coordinates.

bezier2 (x0, y0, x1, y1, x2, y2);

fbezier2 (double x0, double y0, double x1, double y1, double x2, double y2);

bezier2rel (x0, y0, x1, y1, x2, y2);

fbezier2rel (double x0, double y0, double x1, double y1, double x2, double y2);
     bezier2 and fbezier2 take six arguments specifying the beginning
     p0=(x0, y0) and end p2=(x2, y2) of a quadratic Bezier curve, and its
     intermediate control point p1=(x1, y1). The graphics cursor is moved
     to p2. bezier2rel and fbezier2rel are similar to bezier2 and
     fbezier2, but use cursor-relative coordinates. The quadratic Bezier
     curve is tangent at p0 to the line segment joining p0 to p1, and is
     tangent at p2 to the line segment joining p1 to p2. So it fits snugly
     into a triangle with vertices p0, p1, and p2.

bezier3 (x0, y0, x1, y1, x2, y2, x3, y3);

fbezier3 (x0, y0, x1, y1, x2, y2, x3, y3);

bezier3rel (x0, y0, x1, y1, x2, y2, x3, y3);

fbezier3rel (x0, y0, x1, y1, x2, y2, x3, y3);
     bezier3 and fbezier3 take eight arguments specifying the beginning
     p0=(x0, y0) and end p3=(x3, y3) of a cubic Bezier curve, and its
     intermediate control points p1=(x1, y1) and p2=(x2, y2). The graphics
     cursor is moved to p3. bezier3rel and fbezier3rel are similar to
     bezier3 and fbezier3, but use cursor-relative coordinates. The cubic
     Bezier curve is tangent at p0 to the line segment joining p0 to p1,
     and is tangent at p3 to the line segment joining p2 to p3. So it fits
     snugly into a quadrangle with vertices p0, p1, p2, and p3.

box (x0,y0,x1,y1)
boxrel (dx0, dy0, dx1, dy1)
fbox (x0, y0, x1, y1)
fboxrel (dx0, dy0, dx1, dy1)
     box and fbox take four arguments specifying the lower left corner
     (x1, y1) and upper right corner (x2, y2) of a `box', or rectangle.
     boxrel and fboxrel use cursor-relative coordinates.

circle (x,y,r)
circlerel (dx, dy, r)
fcircle (x, y, r)
fcirclerel (dx, dy, r)
     circle and fcircle take three arguments specifying the center (xc,
     yc) and radius (r) of a circle. circlerel and fcirclerel use
     cursor-relative coordinates for xc and yc.

cont (x,y)
contrel (x, y)
fcont (x, y)
fcontrel (x, y)
     cont and fcont take two arguments specifying the coordinates (x, y)
     of a point. If a path is under construction, the line segment from
     the current graphics cursor position to the point (x, y) is added to
     it. Otherwise the line segment begins a new path. In all cases the
     graphics cursor is moved to (x, y). contrel and fcontrel use
     cursor-relative coordinates.

ellarc (xc, yc, x0, y0, x1, y1)
ellarcrel (dxc, dyc, dx0, dy0, dx1, dy1)
fellarc (xc, yc, x0, y0, x1, y1)
fellarcrel (dxc, dyc, dx0, dy0, dx1, dy1)
     ellarc and fellarc take six arguments specifying the three points
     pc=(xc,yc), p0=(x0,y0), and p1=(x1,y1) that define a so-called
     quarter ellipse. This is an elliptic arc from p0 to p1 with center
     pc. The quarter-ellipse is an affinely transformed version of a
     quarter circle.

ellipse (x, y, rx, ry, angle)
ellipserel (dx, dy, rx, ry, angle)
fellipse (x, y, rx, ry, angle)
fellipserel (dx, dy, rx, ry, angle)
     ellipse and fellipse take five arguments specifying the center (xc,
     yc) of an ellipse, the lengths of its semiaxes (rx and ry), and the
     inclination of the first semiaxis in the counterclockwise direction
     from the  @math{x axis} in the user coordinate system. ellipserel and
     fellipserel use cursor-relative coordinates.

endpath ()
     endpath terminates the path under construction, if any. Paths, which
     are formed by repeated calls to cont or fcont, arc or farc, ellarc or
     fellarc, and line or fline, are also terminated if any other object
     is drawn or any path-related drawing attribute is set. So endpath is
     almost redundant. However, if a Plotter plots objects in real time,
     calling endpath will ensure that a constructed path is drawn on the
     graphics display without delay.

label (s)
     label takes a single text argument s and draws a string at the current
     graphics cursor position with left justification. Graphics cursor is
     moved to the right end of the string. This function is equivalent to
     alabel(`l',`x',s).

labelwidth (s)
flabelwidth (s)
     return the width of a string in the current font, in the user
     coordinate system. The string is not plotted.

line (x0,y0,x1,y1)
linerel (dx0, dy0, dx1, dy1)
fline (x0, y0, x1, y1)
flinerel (dx0, dy0, dx1, dy1)
     line and fline take four arguments specifying the start point (x1,
     y1) and end point (x2, y2) of a line segment. linerel and flinerel
     use cursor-relative coordinates.

marker (x, y, type, size)
markerrel (dx, dy, type, size)
fmarker (x, y, type, size)
fmarkerrel (dx, dy, type, size)
     marker and fmarker take four arguments specifying the location (x,y)
     of a marker symbol, its type, and its size in user coordinates.
     markerrel and fmarkerrel use cursor-relative coordinates for the
     position (x,y).  Marker symbol types 0 through 31 are taken from a
     standard set, and marker symbol types 32 and above are interpreted as
     the index of a character in the current text font. See plotutils
     documentation for more information.

move (x,y)
moverel (x, y)
fmove (x, y)
fmoverel (x, y)
     move and fmove take two arguments specifying the coordinates (x, y)
     of a point to which the graphics cursor should be moved without
     drawing any line.  moverel and fmoverel use cursor-relative
     coordinates.

point (x,y)
pointrel (dx, dy)
fpoint (x, y)
fpointrel (dx, dy)
     point and fpoint take two arguments specifying the coordinates (x, y)
     of a point. The graphics cursor is moved to (x, y). pointrel and
     fpointrel use cursor-relative coordinates.

Attribute-setting functions
---------------------------

   The following are the "attribute functions". When invoked on a Plotter,
these functions set its drawing attributes, or save them or restore them.
Path-related attributes include pen color, fill color, line width, line
style, cap style, and join style. Text-related attributes include pen
color, font name, font size, and text angle.

capmod (s)
     capmod sets the cap mode (i.e., cap style) for all paths subsequently
     drawn on the graphics display. Recognized styles are "butt" (the
     default), "round", and "projecting".

color (red, green, blue)
     calling color is equivalent to calling both pencolor and fillcolor,
     to set both the the pen color and fill color of all objects
     subsequently drawn on the graphics display. Note that the physical
     fill color depends also on the fill fraction, which is specified by
     calling filltype.

colorname (name)
     calling colorname is equivalent to calling both pencolorname and
     fillcolorname, to set both the the pen color and fill color of all
     objects subsequently drawn on the graphics display.

filltype (level)
     filltype sets the fill fraction for all subsequently drawn objects. A
     value of 0 for level indicates that objects should be unfilled, or
     transparent. This is the default. A value in the range
     0x0001...0xffff, i.e., 1...65535, indicates that objects should be
     filled. A value of 1 signifies 100% filling (the fill color will
     simply be the color specified by calling fillcolor or fillcolorname).
     If level=0xffff, the fill color will be white. Values between 0x0001
     and 0xffff are interpreted as specifying a desaturation, or gray
     level.  For example, 0x8000 specifies 50% filling.

fillcolor (red, green, blue)
     fillcolor sets the fill color of all objects subsequently drawn on the
     graphics display, using a 48-bit RGB color model.

fillcolorname (name)
     fillcolorname sets the fill color of all objects subsequently drawn
     on the graphics display to be name.

fillmod (s)
     fillmod sets the fill mode, i.e., fill rule, for all objects
     subsequently drawn on the graphics display.  The fill rule affects
     only filled, self-intersecting paths: it determines which points are
     `inside'.  Two rules are supported: "even-odd" (the default for all
     Plotters), and "nonzero-winding". "alternate" is an alias for
     "even-odd" and "winding" is an alias for "nonzero-winding".

fmiterlimit (limit)
     fmiterlimit sets the miter limit for all paths subsequently drawn on
     the graphics display.  The miter limit controls the treatment of
     corners, if the join mode is set to "miter" (the default).  At a join
     point of a path, the `miter length' is defined to be the distance
     between the inner corner and the outer corner.  The miter limit is the
     maximum value that will be tolerated for the miter length divided by
     the line thickness.  If this value is exceeded, the miter will be cut
     off: the "bevel" join mode will be used instead.

     Examples of typical values for limit are 10.43 (the default, which
     cuts off miters if the join angle is less than 11 degrees), 2.0 (the
     same, for 60 degrees), and 1.414 (the same, for 90 degrees).  In
     general, the miter limit is the cosecant of one-half the minimum angle
     for mitered joins.  The minimum meaningful value for limit is 1.0,
     which converts all mitered joins to beveled joins, irrespective of
     join angle.  Specifying a value less than 1.0 resets the limit to the
     default.

fontname (s)
ffontname (s)
     fontname and ffontname take a single case-insensitive string argument,
     font_name, specifying the name of the font to be used for all text
     strings subsequently drawn on the graphics display. (The font for
     plotting strings is fully specified by calling fontname, fontsize,
     and textangle.) The size of the font in user coordinates is returned.

fontsize (size)
ffontsize (size)
     fontsize and ffontsize take a single argument, interpreted as the
     size, in the user coordinate system, of the font to be used for all
     text strings subsequently drawn on the graphics display. The size of
     the font in user coordinates is returned. A negative value for size
     sets the size to a default value, which depends on the type of
     Plotter.

joinmod (s)
     joinmod sets the join mode (i.e., join style) for all paths
     subsequently drawn on the graphics display. Recognized styles are
     "miter" (the default), "round", and "bevel".

linedash (\@dashes, offset)
flinedash (\@dashes, offset)
     linedash and flinedash set the line style for all paths, circles, and
     ellipses subsequently drawn on the graphics display.  They provide
     much finer control of dash patterns than the linemod function (see
     below) provides. dashes should be an array of length n.  Its
     elements, which should be positive, are interpreted as distances in
     the user coordinate system.  Along any path, circle, or ellipse, the
     elements dashes[0]...dashes[n-1] alternately specify the length of a
     dash and the length of a gap between dashes.  When the end of the
     array is reached, the reading of the array wraps around to the
     beginning.  If the array is empty, i.e., n equals zero, there is no
     dashing: the drawn line is solid.

     The offset argument specifies the `phase' of the dash pattern
     relative to the start of the path.  It is interpreted as the distance
     into the dash pattern at which the dashing should begin.  For example,
     if offset equals zero then the path will begin with a dash, of length
     dashes[0] in user space.  If offset equals dashes[0] then the path
     will begin with a gap of length dashes[1], and so forth. offset is
     allowed to be negative. Example:

     flinedash([30, 4, 10, 3],0)

linemod (s)
     linemod sets the linemode (i.e., line style) for all paths, circles,
     and ellipses subsequently drawn on the graphics display. The
     supported linemodes are "disconnected", "solid", "dotted",
     "dotdashed", "shortdashed", and "longdashed". The final five
     correspond more or less to the following bit patterns:

          "solid"             --------------------------------
          "dotted"            - - - - - - - - - - - - - - - -
          "dotdashed"         -----------  -  -----------  -
          "shortdashed"       --------        --------
          "longdashed"        ------------    ------------

     Circles and ellipses that are drawn when the linemode is
     "disconnected" will be invisible. Disconnected paths, circles, and
     ellipses are not filled.

linewidth (size)
flinewidth (size)
     linewidth and flinewidth set the width, in the user coordinate
     system, of all paths, circles, and ellipses subsequently drawn on the
     graphics display. A negative value means that a default width should
     be used. The default and zero width depends on the type of Plotter.

pencolor (red, green, blue)
     pencolor sets the pen color of all objects subsequently drawn on the
     graphics display, using a 48-bit RGB color model.

pencolorname (name)
     pencolorname sets the pen color of all objects subsequently drawn on
     the graphics display to be name.

restorestate ()
     restorestate pops the current graphics context off the stack of
     drawing states. The graphics context consists largely of libplot's
     drawing attributes, which are set by the attribute functions
     documented in this section. A path under construction is regarded as
     part of the graphics context. For this reason, calling restorestate
     automatically calls endpath to terminate the path under construction.
     All graphics contexts on the stack are popped off when closepl is
     called, as if restorestate had been called repeatedly.

savestate ()
     savestate pushes the current graphics context onto the stack of
     drawing states. When a graphics context is returned to, the path
     under construction may be continued.

textangle (angle)
ftextangle (angle)
     textangle and ftextangle take one argument, which specifies the angle
     in degrees counterclockwise from the @math{x} (horizontal) axis in
     the user coordinate system, for text strings subsequently drawn on
     the graphics display. The default angle is zero. The size of the font
     for plotting strings, in user coordinates, is returned.

Mapping functions
-----------------

   The following are the "mapping functions". When invoked on a Plotter,
these functions affect the affine transformation it employs for mapping
from the user coordinate system to the device coordinate system. They may
be viewed as performing transformations of the user coordinate system.
Their names resemble those of the corresponding functions in the
Postscript language.

fconcat (m0, m1, m2, m3, tx, ty)
     Apply a Postscript-style transformation matrix, i.e., affine map, to
     the user coordinate system. That is, apply the linear transformation
     defined by the two-by-two matrix [m0 m1 m2 m3] to the user coordinate
     system, and also translate by tx units in the @math{x direction} and
     ty units in the  @w{@math{y} direction}, relative to the former user
     coordinate system. The three functions (frotate, fscale, ftranslate)
     are special cases of fconcat.

frotate (theta)
     Rotate the user coordinate system axes about their origin by theta
     degrees, with respect to their former orientation. The position of
     the user coordinate origin and the size of the @math{x} @w{and
     @math{y}} units remain unchanged.

fscale (sx, sy)
     Make the @math{x} and @math{y} units in the user coordinate system be
     the size of sx and sy units in the former user coordinate system. The
     position of the user coordinate origin and the orientation of the
     coordinate axes are unchanged.

ftranslate (tx, ty)
     Move the origin of the user coordinate system by tx units in the
     @math{x direction} and ty units in the @w{@math{y} direction},
     relative to the former user coordinate system. The size of the
     @math{x} and @w{@math{y} units} and the orientation of the coordinate
     axes are unchanged.

Device driver parameters
------------------------

   With the parampl function you can set the following device dependent
driver parameters:

DISPLAY
     (Default NULL.) The X Window System display on which the graphics
     display will be popped up, as an X window. This is relevant only to X
     Plotters.

BITMAPSIZE
     (Default "570x570".) The size of the graphics display in terms of
     pixels. This is relevant only to X Plotters. If this parameter is not
     set, its value will automatically be taken from the X resource
     Xplot.geometry.

PAGESIZE
     (Default "letter".) The size of the page on which the graphics
     display will be positioned. This is relevant only to Illustrator,
     Postscript, Fig, PCL, and HP-GL Plotters. "letter" means an 8.5in by
     11in page. Any ISO page size in the range "a0"..."a4" or ANSI page
     size in the range "a"..."e" may be specified ("letter" is an alias
     for "a" and "tabloid" is an alias for "b"). "legal", "ledger", and
     "b5" are recognized page sizes also.

AI_VERSION
     (Default "5".) Relevant only to Illustrator Plotters. Recognized
     values are "5" and "3". "5" means that the output should be in the
     format used by version 5 of Adobe Illustrator, which is recognized by
     all later versions.

BG_COLOR
     (Default "white".) The initial background color of the graphics
     display, when drawing each page of graphics. This is relevant to X
     Plotters and X Drawable Plotters, although for the latter, the
     background color shows up only if erase is invoked. The background
     color may be changed at any later time by invoking the bgcolor (or
     bgcolorname) and erase operations.

HPGL_ASSIGN_COLORS
     (Default "no".) Relevant only to HP-GL Plotters, and only if the
     value of HPGL_VERSION is "2". "no" means to draw with a fixed set of
     pens, specified by setting the HPGL_PENS parameter. "yes" means that
     pen colors will not restricted to the palette specified in HPGL_PENS:
     colors will be assigned to "logical pens" in the range #1...#31, as
     needed. Other than color LaserJet printers and DesignJet plotters,
     not many HP-GL/2 devices allow the assignment of colors to logical
     pens. So this parameter should be used with caution.

HPGL_OPAQUE_MODE
     (Default "yes".) Relevant only to HP-GL Plotters, and only if the
     value of HPGL_VERSION is "2". "yes" means that the HP-GL/2 output
     device should be switched into opaque mode, rather than transparent
     mode. This allows objects to be filled with opaque white and other
     opaque colors. It also allows the drawing of visible white lines,
     which by convention are drawn with pen #0.

HPGL_PENS
     (Default "1=black:2=red:3=green:4=yellow:5=blue:6=magenta:7=cyan" if
     the value of HPGL_VERSION is "1.5" or "2" and "1=black" if the value
     of HPGL_VERSION is "1". Relevant only to HP-GL Plotters. The set of
     available pens; the format should be self-explanatory. The color for
     any pen in the range #1...#31 may be specified. Pen #1 must always be
     present, though it need not be black. Any other pen in the range
     #1...#31 may be omitted.

HPGL_ROTATE
     (Default "0".) Relevant only to HP-GL Plotters. The angle, in
     degrees, by which the graphics display should be rotated on the page
     relative to the default orientation. Recognized values are "0", "90",
     "180", and "270"; "no" and "yes" are equivalent to "0" and "90"
     respectively. This parameter is provided to facilitate switching
     between portrait and landscape orientations.  "180" and "270" are
     supported only if HPGL_VERSION is "2".

HPGL_VERSION
     (Default "2".) Relevant only to HP-GL Plotters. "1" means that the
     output should be generic HP-GL, "1.5" means that the output should be
     suitable for the HP7550A graphics plotter and the HP758x, HP7595A and
     HP7596A drafting plotters (HP-GL with some HP-GL/2 extensions), and
     "2" means that the output should be modern HP-GL/2. If the version is
     "1" or "1.5" then the only available fonts will be vector fonts, and
     all paths will be drawn with a default width. Additionally, if the
     version is "1" then the filling of arbitrary paths will not be
     supported (circles and rectangles aligned with the coordinate axes
     may be filled).

HPGL_XOFFSET, HPGL_YOFFSET
     (Defaults "0.0cm" and "0.0cm".) Relevant only to HP-GL Plotters.
     Adjustments, in the @math{x and @math{y}} directions, of the position
     of the graphics display on the page. They may be specified in
     centimeters, millimeters, or inches. For example, an offset could be
     specified as "2cm" or "1.2in".

MAX_LINE_LENGTH
     (Default "500".) The maximum number of points that a path may
     contain, before it is flushed to the display device. If this flushing
     occurs, the path will be split into two or more sub-paths, though the
     splitting should not be noticeable. Splitting will not be performed
     if the path is filled. This parameter is relevant to X, X Drawable,
     Illustrator, Postscript, Fig, PCL, and HP-GL Plotters. The reason for
     splitting long paths is that some display devices (e.g., old
     Postscript printers and HP-GL plotters) have limited buffer sizes. It
     is not relevant to Tektronix or Metafile Plotters, since they draw
     paths in real time and have no buffer limitations.

META_PORTABLE
     (Default "no".) Relevant only to Metafile Plotters. "yes" means that
     the output should be in a portable (human-readable) version of the
     metafile format, rather than the default (binary) version.

PCL_ASSIGN_COLORS
     (Default "no".) Relevant only to PCL Plotters. "no" means to draw
     with a fixed set of pens. "yes" means that pen colors will not
     restricted to this palette: colors will be assigned to "logical
     pens", as needed. Other than color LaserJet printers, not many PCL 5
     devices allow the assignment of colors to logical pens. So this
     parameter should be used with caution.

PCL_ROTATE
     (Default "0".) Relevant only to PCL Plotters. See explonation for
     HPGL_ROTATE.

PCL_XOFFSET, PCL_YOFFSET
     (Defaults "0.0cm" and "0.0cm".) Relevant only to PCL Plotters. See
     explonation for HPGL_XOFFSET.

TERM
     (Default NULL.) Relevant only to Tektronix Plotters.

USE_DOUBLE_BUFFERING
     (Default "no".) Relevant only to X Plotters and X Drawable Plotters.
     If the value is "yes", each frame of graphics, within a
     openpl...closepl pair, is written to an off-screen buffer rather than
     to the Plotter's display. When erase is invoked to end a frame, or
     when closepl is invoked, the contents of the off-screen buffer are
     copied to the Plotter's display, pixel by pixel.  This double
     buffering scheme is useful in creating the illusion of smooth
     animation. The "fast" is an alias for "yes". If there are standard
     DBE and MBX extensions to the X11 protocol to communicate with the
     display is available then these extensions are used. It may yield
     much faster animation.

VANISH_ON_DELETE
     (Default "no".) Relevant only to X Plotters. If the value is "yes",
     when a Plotter is deleted, the window or windows that it has popped
     up will vanish.  Otherwise, each such window will remain on the
     screen until it is removed by the user (by typing `q' in it, or by
     clicking with a mouse).

XDRAWABLE_COLORMAP
     (Default NULL.) Relevant only to X Drawable Plotters. If the value is
     non-NULL, it should be a Colormap *, a pointer to a colormap from
     which colors should be allocated. NULL indicates that the colormap to
     be used should be the default colormap of the default screen of the X
     display.

XDRAWABLE_DISPLAY
     (Default NULL.) Relevant only to X Drawable Plotters. The value
     should be a Display *, a pointer to the X display with which the
     drawable(s) to be drawn in are associated.

XDRAWABLE_DRAWABLE1

XDRAWABLE_DRAWABLE2
     (Default NULL.) Relevant only to X Drawable Plotters. If set, the
     value of each of these parameters should be a Drawable *, a pointer
     to a drawable to be drawn in. A `drawable' is either a window or a
     pixmap. At the time an X Drawable Plotter is created, at least one of
     the two parameters must be set. X Drawable Plotters support
     simultaneous drawing in two drawables because it is often useful to
     be able to draw graphics simultaneously in both an X window and its
     background pixmap. If two drawables are specified, they must have the
     same dimensions and depth, and be associated with the same screen of
     the X display.

   For more information on device driver parameters, fonts, strings and
symbols, markers, color names, markers, metafile format see plotutils
documentation.

Exported constants and functions
================================

   You can export the following functions: parampl, warning_handler and
error_handler. parampl is a static function of the Plotter superclass.
warning_handler and error_handler sets the pointer to the error message
handler functions.

   You can import into the main namespace the op codes (for metafile
format) with the command: use Graphics::Plotter qw(:marker_symbols), and
the marker symbols, with the command: use Graphics::Plotter qw(:op_codes),
or both of them with the command: use Graphics::Plotter qw(:all).  See
plotutils documentation for the explanation how to use op codes and marker
symbols.

AUTHOR
======

   Piotr Klaban <makler@man.torun.pl>

SEE ALSO
========

   perl(1), plotutils documentation

a simple , device-independent graphics API for Perl
***************************************************

NAME
====

   Graphics::Simple - a simple , device-independent graphics API for Perl

SYNOPSIS
========

     use Graphics::Simple;

     line 100,100,200,200;
     circle 50,50,25;
     stop(); clear(); # Wait for a button press, clear the page

DESCRIPTION
===========

   Ever had a Commodore C-64 or Vic-20 or some other of the machines of
that era? Where doing graphics was as simple as

     line 20,20,50,30;

   and you didn't have to go through things like `XOpenDisplay' etc.

   This module tries to bring back the spirit of that era in a modern
environment: this module presents a simple, unified API to several
different graphics devices - currently X (using Gtk and Gnome) and
PostScript.

   The interface is primarily made easy-to-use, starting from the idea
that the above line command must work. Therefore, it exports most of the
primitives by default (you can turn this off).

   However, everything is not sacrificed in the name of simplicity:
believing in "simple things simple, complicated things possible", this
module also allows multiple windows (all the primitives also work as
methods of window objects) as well as raw access to the underlying devices
- although the device-independence is then lost.  In future plans are some
sort of interactions with the devices with which it is possible as well as
the addition of more devices.

   The use command currently accepts the forms

     use Graphics::Simple;
     use Graphics::Simple qw/line circle/;
     use Graphics::Simple 300,400; # portrait paper
     use Graphics::Simple 300,400, qw/line circle/;

   i.e. the optional size of the default window first and then normal
Exporter arguments.

   `Graphics::Simple' has several different back-ends, currently
GnomeCanvas, TkCanvas, PostScript and (not fully working yet) Fig.  Other
backends are expected.

   To start `Graphics::Simple' with a given backend, you should set the
environment variable `GSIMPL' to the value, e.g. by running your script
with the command

     GSIMPL='PostScript' perl gt1.pl

   or by setting the environment variable permanently in your shell, by

     GSIMPL=PostScript
     export GSIMPL

   or

     setenv GSIMPL PostScript

   depending on which shell you use.

line [$win_to], [$name], $x1, $y1, $x2, $y2, ...
------------------------------------------------

   Draws a line through the points given.

arrow [$win_to], [$name], $x1, $y1, $x2, $y2, ...
-------------------------------------------------

   Like line, but makes an arrowhead in the end.

line_to [$win], [$name], $x1, $y1, $x2, $y2, ...
------------------------------------------------

   Called several times in a sequence, starts and continues adding points
to a line. If called with no coordinates, finishes the current line. This
is just a convenient wrapper over a line call with all the parameters
given - a faster way would just be to collect your parameters to an array.

circle [$win], [$name], $x, $y, $radius
---------------------------------------

   Duh.

ellipse [$win], [$name], $x1, $y1, $x2, $y2
-------------------------------------------

   The ellipse enclosed in the rectangle given by its two corners

text [$win], [$name], $x, $y, $string
-------------------------------------

   Duh...

image [$win], [$name], $x, $y, $width, $height, $depth, $string
---------------------------------------------------------------

   This command creates a rectangular bit- or pixmap. The $depth parameter
is the number of bytes per pixel (1 for B/W or 3 for RGB) and the string
is a string of packed bytes that describe the image.

   For instance, the module PDL is a good source for such strings.

clear, stop
-----------

     stop [$win]
     clear [$win]

   clear removes all the drawn elements from the window. <wait> waits for
a button press. These are usually coupled:

     stop; clear;

set_window, get_window
----------------------

   See the source - undocumented and potentially changing api

push_window, pop_window
-----------------------

   `Graphics::Simple' maintains a simple window stack so that subroutines
can easily use

     push_window $win;
     line ...
     pop_window();

   to avoid having too many method calls.

color [$win,] $color;
---------------------

   Set the current color to $color. Currently, the colors known are

     red green blue black white

   as well as any RGB color with the X syntax:

     color '#FFFF00';

   is yellow. You can also give an array ref of three numbers between 0
and 1 for RGB colors.

linewidth [$win,] $width
------------------------

BUGS
====

   This is an alpha proof-of-principle version - the API may still change
wildly.

AUTHOR
======

   Copyright(C) Tuomas J. Lukka 1999. All rights reserved.  This software
may be distributed under the same conditions as Perl itself.

implement Graphics::Simple in Fig (e.g. xfig) files
***************************************************

NAME
====

   Graphics::Simple::Fig - implement Graphics::Simple in Fig (e.g. xfig)
files

SYNOPSIS
========

     use Graphics::Simple;
     # use those operations

DESCRIPTION
===========

   The module `Graphics::Simple::Fig' is an implementation of the
`Graphics::Simple' API.

DEVICE-DEPENDENT OPERATIONS
===========================

stop
----

   Waiting is implemented by writing the current image as a snapshot to a
file.  The problem is that this only applies to the one window - code that
has two windows will not show all the upgrades that GnomeCanvas shows.
This should be adressed somehow - the problem is that we don't want to
duplicate all the static images in other windows if only one is changing.

   The files are currently written into `/tmp/'.

BUGS
====

   Writes much too much code, e.g. by setting width and color for each
object.  Should check if it is already set and leave the old setting and
other such optimizations.

AUTHOR
======

   Copyright(C) Tuomas J. Lukka 1999. All rights reserved.  This software
may be distributed under the same conditions as Perl itself.

implement Graphics::Simple using Gnome Canvas
*********************************************

NAME
====

   Graphics::Simple::GnomeCanvas - implement Graphics::Simple using Gnome
Canvas

SYNOPSIS
========

     use Graphics::Simple;
     # use those operations

DESCRIPTION
===========

   The module `Graphics::Simple::GnomeCanvas' is an implementation of the
`Graphics::Simple' API.

DEVICE-DEPENDENT OPERATIONS
===========================

stop
----

   Waiting is implemented by waiting for a button click in any of the
windows managed by this module.

AUTHOR
======

   Copyright(C) Tuomas J. Lukka 1999. All rights reserved.  This software
may be distributed under the same conditions as Perl itself.

Plot PDL data using Graphics::Simple
************************************

NAME
====

   Graphics::Simple::PDLPlot - Plot PDL data using Graphics::Simple

DESCRIPTION
===========

   Functions:

     line $pdl_y;
     line $pdl_x, $pdl_y;

   Methods:

     $g = Graphics::Simple::PDLPlot::Graph->new();

     $g->line($pdl_x, $pdl_y);
     $g->points($pdl_x, $pdl_y);
     $g->x_axis(1.0,2.0);
     $g->y_axis(0.1,1000,LOG);
     $g->plot($win);

BUGS
====

   This module is in the wrong place - it should be in the PDL distribution
and will be in the future.

   Wildly inefficient - there must be more synergy between this module and
the `Graphics::Simple' implementations for vectorization.

AUTHOR
======

   Copyright(C) Tuomas J. Lukka 1999. All rights reserved.  This software
may be distributed under the same conditions as Perl itself.

implement Graphics::Simple in PostScript files
**********************************************

NAME
====

   Graphics::Simple::PostScript - implement Graphics::Simple in PostScript
files

SYNOPSIS
========

     use Graphics::Simple;
     # use those operations

DESCRIPTION
===========

   The module `Graphics::Simple::PostScript' is an implementation of the
`Graphics::Simple' API.

DEVICE-DEPENDENT OPERATIONS
===========================

stop
----

   Waiting is implemented by writing the current image as a snapshot to a
file.  The problem is that this only applies to the one window - code that
has two windows will not show all the upgrades that GnomeCanvas shows.
This should be adressed somehow - the problem is that we don't want to
duplicate all the static images in other windows if only one is changing.

   The files are currently written into `/tmp/'.

BUGS
====

   Writes much too much code, e.g. by setting width and color for each
object.  Should check if it is already set and leave the old setting and
other such optimizations.

AUTHOR
======

   Copyright(C) Tuomas J. Lukka 1999. All rights reserved.  This software
may be distributed under the same conditions as Perl itself.

Perl module for the Gimp Toolkit library
****************************************

NAME
====

   Gtk - Perl module for the Gimp Toolkit library

SYNOPSIS
========

     use Gtk '-init';
     my $window = new Gtk::Window;
     my $button = new Gtk::Button("Quit");
     $button->signal_connect("clicked", sub {Gtk->main_quit});
     $window->add($button);
     $window->show_all;
     Gtk->main;

     =head1 DESCRIPTION

   The Gtk module allows Perl access to the Gtk+ graphical user interface
library. You can find more information about Gtk+ on http://www.gtk.org.
The Perl binding tries to follow the C interface as much as possible,
providing at the same time a fully object oriented interface and
Perl-style calling conventions.

AUTHOR
======

   Kenneth Albanowski, Paolo Molaro

SEE ALSO
========

   perl(1)

Choose a color
**************

NAME
====

   Gtk::ColorSelectButton - Choose a color

SYNOPSIS
========

     use Gtk;
         use Gtk::ColorSelectButton;

         ...
         init Gtk;
         init Gtk::ColorSelectButton;
         ...

     $color_button = Gtk::ColorSelectButton->new();
     $hbox->pack_start($color_button, 1,1,0);
     $color_button->show();

     ...
     print $color_button->color; #shortcut for ->get('color')
     ...
     $color_button->set( color => "10 40 250" ); # R G B

DESCRIPTION
===========

   Gtk::ColorSelectButton shows a button with a uniform color. Pressing
this buton pops up the color_selection dialog in which a new color may be
chosen. When the color selection dialog is closed, the chosen color is
reflected in the color of the button.

   The gtk variable color provides a way to access the chosen color.

AUTHOR
======

   Dov Grobgeld <dov@imagic.weizmann.ac.il>, with modifications by Kenneth
Albanowski <kjahds@kjahds.com>.

COPYRIGHT
=========

   Copyright (c) 1998 Dov Grobgeld. All rights reserved. This program may
be redistributed and copied under the same licence as Perl itself.

A more Perl-friendly Columned List
**********************************

NAME
====

   Gtk::HandyCList - A more Perl-friendly Columned List

SYNOPSIS
========

     use Gtk::HandyCList;
     my $vbox = new Gtk::VBox(0,5);
     my $scrolled_window = new Gtk::ScrolledWindow( undef, undef );
     $vbox->pack_start( $scrolled_window, 1, 1, 0 );
     $scrolled_window->set_policy( 'automatic', 'always' );

     my $list = Gtk::HandyCList->new( qw(Name Date Cost) );
     $list->data( [ "Foo", "29/05/78", 12.33],
                  [ "Bar", "01/01/74", 104.21],
                  # ...
                );
     $list->sizes( Name => 100, Date => "30%", Cost => "40%" );
     $list->sortfuncs( Name => "alpha", Date => \&date_sort, Cost => "number");

DESCRIPTION
===========

   This is a version of `Gtk::CList|Gtk::CList' in this node which takes
care of some common things for the programmer. For instance, it keeps
track of what's stored in the list, so you don't need to keep a separate
array; when the column titles are clicked, the list will be re-sorted
according to user-supplied functions or some default rules. It allows you
to reference columns by name, instead of by number.

METHODS
=======

new(@titles)
     This is equivalent to `< Gtk::CList-'new_with_titles >>, but
     initialises all the data structures required for HandyCList.

data(@data)
     A get-set method to retrieve and/or set the data in the table. The
     data is specified as an array of rows, and each row may either be an
     array reference or a hash reference. If a hash reference, the keys of
     the hash must correspond to the columns of the table.

     Example: You may either say this, using array references:

          my $list = Gtk::HandyCList->new( qw(Name Date Cost) );
          $list->data( [ "Foo", "29/05/78", 12.33],
                       [ "Bar", "01/01/74", 104.21] );

     or this, using hash references:

          my $list = Gtk::HandyCList->new( qw(Name Date Cost) );
          $list->data( { Name => "Foo", Date => "29/05/78", Cost => 12.33 },
                       { Name => "Bar", Date => "01/01/74", Cost =>104.21 } );

     The data will be returned as an array of hash references.

clear
     Remove all entries from the list.

append(@items)
     Append some items to the list; semantics of `@items' are the same as
     for the data method above.

prepend(@items)
     Append some items to the start of the list

sortfuncs(@functions | %functions )
     HandyCList automatically takes care of sorting the columns in the list
     for you when the user clicks on the column titles. To do this, though,
     you need to provide indication of how the data should be sorted. You
     may provide either a list or a hash (keyed to columns as before) of
     subroutine references or the strings "alpha" or "number" for
     alphabetic and numeric comparison respectively.

     Subroutine references here are not the same as you would hand to
     sort: they must take two arguments and compare them, instead of
     comparing the implicit variables `$a' and $b.

refresh
     Make sure that the data displayed in the list is the same as the data
     you'd get back from `< $list-'data >>. You probably won't need to
     call this, unless you're doing freaky things.

sizes(@columns | %columns)
     Set the size of each column as a number of pixels or as a percentage.
     At least one of the columns must be given as a number of pixels.
     Percentages should be strings like `"40%"', not floating point
     numbers.

selection
     Return data regarding what is currently selected.  The return value
     is a hashref, the keys being the (0-based) row numbers selected, the
     values being hashrefs themselves, from column name to column data.

hide (@columns)
     Prevent certain columns from being displayed.

unhide (@columns)
     Re-allow display of certain columns

AUTHOR
======

   Simon Cozens, simon@cpan.org

SEE ALSO
========

   `GNOME' in this node, `Gtk::CList' in this node

Perl module to access HP-200 LX database files
**********************************************

NAME
====

   HP200LX::DB - Perl module to access HP-200 LX database files

SYNOPSIS
========

     use HP200LX::DB;

     interface functions:
       $db= HP200LX::DB::openDB ($fnm)     read database and return an DB object
       $db= HP200LX::DB::new ($fnm)        create database and return an DB object
       $db->saveDB ($fnm)                  save DB object as a (new) file

     array tie implementation to access database data records:
       tie (@dbd, HP200LX::DB, $db);       access database data in array form
       TIEARRAY                            stub to get an tie for the database
       FETCH                               retrieve a record
       STORE                               store a record

     additional data retrieval and storage methods:
       $db->FETCH_data_raw ($idx)          retrieve raw data record
       $db->FETCH_note_raw ($idx)          retrieve raw note record
       $db->STORE_data_raw ($idx, $data)   store raw data record
       $db->STORE_note_raw ($idx, $note)   store raw note record
       $db->get_last_index ()              return highest index

     additional UNIMPLEMENTED data manipulation methods:
       T2D: $db->DELETE ($num)             delete given data record
       T2D: $db->INSERT ($num)             insert a new object at index

     internal methods:
       $db->show_db_def (*FH)              show database definition
       $db->show_card_def (*FH)            show card layout definition
       $db->get_field_def ($num)           retrieve field definition
       $db->print_summary ($header)        print DB summary line;
                                           print also header if $header==1
       show_field_def                      show a field definition
       fetch_data                          used by FETCH to get db record
       store_data                          used by STORE to save db record
       get_recheader                       read gdb internal record structure
       put_recheader                       store gdb internal record structure
       fmt_time_stamp                      create a readable date and time string
       get_fielddef                        decode a field definition record
       get_carddef                         decode a card definiton record

     Diagnostics and Debugging methods:
       $db->dump_db (*FH, $type)           dump a complete data base
       $db->dump_data                      dump all data records
       $db->recover_password               attempt to reconstruct DB password

     Diagnostics and Debugging functions:
       print_recheader (*FH, $txt, $rec)   print details about a record
       dump_def                            dump database definition
       dump_data_record                    print and dump data record
       hex_dump                            perform a hex dump of some data
       decode_password                     attempt to decote the DB password
       decode                              attempt to decode a DB recrod

DESCRIPTION
===========

     DB.pm implements the perl package HP200LX::DB which is intended
     to provide a perl 5 interface for files in the generic database
     format of the HP 200 LX palmtop computer.  The perl modules are
     intended to be used on a work station such as a PC or a Unix
     machine to read and write data records from and to a database
     file.  These modules are not intended to be run directly on the
     palmtop!

     Please see the README file for a few more details or consult
     the examples which can be found at the web site mentioned below.

Copyright
=========

     Copyright (c) 1998 Gerhard Gonter.  All rights reserved.
     This is free software; you can redistribute it and/or modify
     it under the same terms as Perl itself.

AUTHOR
======

     Gerhard Gonter, g.gonter@ieee.org or gonter@wu-wien.ac.at

SEE ALSO
========

     http://falbala.wu-wien.ac.at:8684/pub/english.cgi/0/24065
     perl(1).

Perl function to handle HPUX ioscan command
*******************************************

NAME
====

   HPUX::Ioscan - Perl function to handle HPUX ioscan command

SYNOPSIS
========

     use HPUX::Ioscan ;
     my $result = ioscan ();

     print "All hardware paths: ", join(" ", keys %$result),"\n";

     print "One device file of disk :\n",
           $result->{'2/1.6.0'}{device_files}[0],
           "\n";

DESCRIPTION
===========

   This module works on top of the HP-UX command ioscan. It forks a
process to run the ioscan command and parses its STDOUT. The result is
returned in a hash.

   This module is quite basic but it may be interesting if you need to
write administration program on HP-UX.

   You may call ioscan several time in your program without any problem
sicne the result is cached. Only the first call to ioscan will actually
run the ioscan command. (But you may override the caching of the result)

FUNCTION
========

ioscan ( [force => 1] )
-----------------------

   Will return the result of the ioscan command. The ioscan command is run
the first time or if the force parameter is set to 1.

   This function returns a hash ref. The keys of the hash are all the
hardware paths found on your system.

   The value is another hash ref containing these keys :

     bus_type
     cdio
     is_block
     is_char
     is_pseudo
     block_major_number
     character_major_number
     minor_number
     class
     driver
     hardware_path
     identify_bytes
     instance_number
     module_path
     module_name
     software_state
     hardware_type
     description
     card_instance
     device_files

   See `ioscan' in this node(1M) for the meaning of these keys.

   The value of device_files is an array containing the name of the device
files attached to the hardware path.

EXAMPLE
=======

   Here's an example of the structure returned for 1 disk:

     $result =
      {
        '0/0/2/1.6.0' =>
           {
             'description' => 'SEAGATE ST318203LC',
             'block_major_number' => '31',
             'cdio' => 'wsio',
             'driver' => 'sdisk',
             'instance_number' => '1',
             'is_pseudo' => 'F',
             'character_major_number' => '188',
             'class' => 'disk',
             'bus_type' => 'scsi',
             'hardware_path' => '0/0/2/1.6.0',
             'identify_bytes' => '0 0 2 18 0 0 0 0 95 227 197 13  8 127 87 40 32 ',
             'device_files' => [
                                 '/dev/dsk/c2t6d0',
                                 '/dev/rdsk/c2t6d0'
                               ],
             'module_path' => 'root.sba.lba.c720.tgt.sdisk',
             'minor_number' => '155648',
             'is_block' => 'T',
             'is_char' => 'T',
             'card_instance' => '2',
             'software_state' => 'CLAIMED',
             'hardware_type' => 'DEVICE',
             'module_name' => 'sdisk'
           },
     }

CAVEATS
=======

   The iocan command is run in blocking mode and may indeed block for
several seconds on big systems.

AUTHOR
======

   Dominique Dumont <Dominique_Dumont@hp.com>

   Copyright (c) 2001 Dominique Dumont. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `ioscan' in this node(1M)

dynamically activate HTML links based on URL
********************************************

NAME
====

   HTML::ActiveLink - dynamically activate HTML links based on URL

SYNOPSIS
========

     use HTML::ActiveLink;

     my $al = new HTML::ActiveLink;

     print $al->activelink(@html_doc);

DESCRIPTION
===========

   I don't know about you, but one of the main problems I have with HTML
content is getting images and links to "turn on" depending on the current
URL location. That is, I like authoring one set of templates, something
like this:

     [ <a href="/">Home</a> | <a href="/faq/">FAQ</a>
     | <a href="/about/">About Us</a> ]

   And then having the appropriate link turned on, so that if I'm running
inside the /home/ directory, the above turns into this:

     [ <font color="red">Home</font> | <a href="/faq/">FAQ</a>
     | <a href="/about/">About Us</a> ]

   Without having to write a whole bunch of if's, or writing a bunch of
different sets of templates, etc.

   This module handles the above process automatically. By default, it
will activate any text or images with <a href> tags around them by
stripping the link off and changing the appearance of text and names of
images. All transformations are fully customizable, allowing you to choose
how your active text should look. HTML::ActiveLink can even automatically
construct imagemaps depending on your location.

   In the simplest case, all you have to do is create a new object by a
call to new(), and then call the main activelink() function which takes
care of the transformation. To customize what the output HTML looks like,
keep reading...

FUNCTIONS
=========

new()
-----

   This is the constructor method, and it takes a number of parameters
that determine how the output HTML looks:

     text              -  transform text links?  [1]
     text_prefix       -  prefix to add to text  [<font color="red">]
     text_suffix       -  suffix to add to text  [</font>]
     text_rmlink       -  remove <a href=> tag?  [1]

     image             -  transform image links? [1]
     image_prefix      -  prefix to add to image []
     image_suffix      -  suffix to add to image [_on]
     image_rmlink      -  remove <a href=> tag?  [1]

     imagemap          -  create URL imagemaps?  [1]
     imagemap_prefix   -  prefix for imagemaps   []
     imagemap_suffix   -  suffix for imagemaps   [_on]
     imagemap_joinchar -  join parts with char   [_]
     imagemap_rootname -  imagemap name for /    [home]
     imagemap_dirdepth -  max dir levels to use  [2]

   The first set of args determines how to transform text links. By
default, any text links will be changed into red text when you're in the
directory or document that they point to (see below for more explicit
details). To change this, just change the prefix and suffix, for example:

     my $al = HTML::ActiveLink->new(text_prefix => '<b>',
                                    text_suffix => ' &gt;</b>');

   This will make the active links bold, with a > sign after them as well.
A similar principle works for images. By default, an image link like so:

     <a href="/home/"><img src="/images/home.gif"></a>

   Will be transformed to:

     <img src="/images/home_on.gif">

   Notice that the file type suffix is preserved, and that the image
suffix is properly applied to the name of the image. Again, to change the
suffix or prefix simply change the image_ parameters.

   Finally, this module will automatically *construct* imagemaps based on
the current URL. Unlike the two above methods, which involve parsing and
modifying existing content, the imagemap creation instead creates the name
of the imagemap dynamically.  This is done since imagemaps contain
multiple links, so each one represents many areas to click on.

   For example, if you are running in the directory /faq/, and you have an
imagemap that looks like this:

     <img src="/images/tab.gif" usemap="#nav">

   Then the image src will be rewritten as:

     <img src="/images/tab_faq_on.gif" usemap="#nav">

   Here, the name of the imagemap is rewritten similarly to images, only
depending on your location. The directory information is inserted in after
the name of the image that exists, along with the suffix. The imagemap
name is created by joining together the directory name(s) for your current
location, up to 2 deep by default. More examples:

     /faq/            = tab_faq_on.gif
     /                = tab_home_on.gif (depending on _rootname)
     /name/g.html     = tab_name_on.gif
     /id/N/NW/NWIGER/ = tab_id_N_on.gif (note only first 2 used)

   The second one depends on what you've set imagemap_rootname to, since
this is what is used to determine the name for /. In the last example,
notice that only 2 dir levels are used by default, meaning that huge dir
trees do not result in tons of different imagemap names. To change this,
set imagemap_dirdepth.

activelink()
------------

   This is the function that actually parses the document and activates
all the necessary links. It joins its arguments into a scalar
representation of the file and returns that, which can then be printed out
or manipulated further. Examples:

     print $al->activelink(@doc);
     print $al->activelink($part1, $part2, $part3);
     $doc = $al->activelink(<STDIN>);

   And so on. To change how it works, pass different values to the new()
function described above.

   The activelink() function uses regular expressions to match the
location so that anything deeper than a link is activated.  So, assuming
this link:

     <a href="/news/today/">Today's News</a>

   Then any of the following locations would cause it to be active:

     /news/today/
     /news/today/presidential_election_still_undecided.html
     /news/today/regional/san_diego_headlines.html

   But none of these would:

     /news/
     /news/today.html
     /news/today

   Just like with Apache configs, the path needs to be matched completely,
and then anything beneath that path works as well.

APPLICATIONS
============

   One simple use of this module that I like is creating a simple script
called "header.cgi" that just looks something like this:

     use HTML::ActiveLink;
     my $al = HTML::ActiveLink->new(text_prefix => '<b>',
                                    text_suffix => '</b>');

     my $header = '/path/to/header.html';
     open(HEADER, "<$header") or die $!;
     print $al->activelink(<HEADER>);

   Then, I can use this in my SSI documents like so:

     <!--#include "../cgi-bin/header.cgi"-->

   And presto! All my SSI .shtml documents have a header which has links
that are automatically activated based on the document location.  You
could, of course, beef up the "header.cgi" script so that it used the name
of a file passed as a parameter, etc, depending on what you want to do.

VERSION
=======

   $Id: ActiveLink.pm,v 1.2 2000/11/27 23:46:29 nwiger Exp $

AUTHOR
======

   Copyright (c) 2000 Nathan Wiger, Nateware, Inc. <nate@nateware.com>.
All Rights Reserved.

   This module is free software; you may copy this under the terms of the
GNU General Public License, or the Artistic License, copies of which
should have accompanied your Perl kit.

functions that construct a HTML syntax tree
*******************************************

NAME
====

   HTML::AsSubs - functions that construct a HTML syntax tree

SYNOPSIS
========

     use HTML::AsSubs;
     $h = body(
     	   h1("This is the heading"),
     	   p("This is the first paragraph which contains a ",
     	     a({href=>'link.html'}, "link"),
     	     " and an ",
     	     img({src=>'img.gif', alt=>'image'}),
     	     "."
     	    ),
     	  );
     print $h->as_HTML;

DESCRIPTION
===========

   This module exports functions that can be used to construct various
HTML elements. The functions are named after the tags of the correponding
HTML element and are all written in lower case. If the first argument is a
hash reference then it will be used to initialize the attributes of this
element. The remaining arguments are regarded as content.

   For a similar idea (i.e., it's another case where the syntax tree of
the Perl source mirrors the syntax tree of the HTML produced), see
HTML::Element's `new_from_lol' method.

   For what I now think is a cleaner implementation of this same idea, see
the excellent module `XML::Generator', which is what I suggest for actual
real-life use.  (I suggest this over `HTML::AsSubs' and over `CGI.pm''s
HTML-making functions.)

ACKNOWLEDGEMENT
===============

   This module was inspired by the following message:

     Date: Tue, 4 Oct 1994 16:11:30 +0100
     Subject: Wow! I have a large lightbulb above my head!

     Take a moment to consider these lines:

     %OVERLOAD=( '""' => sub { join("", @{$_[0]}) } );

     sub html { my($type)=shift; bless ["<$type>", @_, "</$type>"]; }

     :-)  I *love* Perl 5!  Thankyou Larry and Ilya.

     Regards,
     Tim Bunce.

     p.s. If you didn't get it, think about recursive data types: html(html())
     p.p.s. I'll turn this into a much more practical example in a day or two.
     p.p.p.s. It's a pity that overloads are not inherited. Is this a bug?

BUGS
====

   The exported link() function overrides the builtin link() function.
The exported tr() function must be called using &tr(...) syntax because it
clashes with the builtin tr/../../ operator.

SEE ALSO
========

   See HTML/Element, XML/Generator,

Perl extension for generating and manipulating HTML calendar months
*******************************************************************

NAME
====

   HTML::CalendarMonth - Perl extension for generating and manipulating
HTML calendar months

SYNOPSIS
========

     use HTML::CalendarMonth;
     use HTML::AsSubs;

     # Using HTML::AsSubs
     $c = HTML::CalendarMonth->new( month => 3, year => 69 );
     $c->item($c->year, $c->month)->attr(bgcolor => 'wheat');
     $c->item($c->year, $c->month)->wrap_content(font({size => '+2'}));
     $c->item(12, 16, 28)->wrap_content(strong());
     print $c->as_HTML;

     # Using regular HTML::Element creation
     $c2 = HTML::CalendarMonth->new( month => 8, year => 79 );
     $c2->item($c2->year, $c2->month)->attr(bgcolor => 'wheat');
     $f = HTML::Element->new('font', size => '+2');
     $c2->item($c2->year, $c2->month)->wrap_content($f);
     $c2->item_daycol('Su', 'Sa')->attr(bgcolor => 'cyan');
     print $c2->as_HTML;

DESCRIPTION
===========

   HTML::CalendarMonth is a subclass of HTML::ElementTable. See
`HTML::ElementTable(3)' in this node for how that class works, for it
affects this module on many levels. Like HTML::ElementTable,
HTML::CalendarMonth behaves as if it were an HTML::ElementSuper, which is
a regular HTML::Element with methods added to easily manipulate the
appearance of the HTML table containing the calendar.

   The primary interaction with HTML::CalendarMonth is through items. An
item is merely a symbol that represents the content of the cell of
interest within the calendar. For instance, the element representing the
14th day of the month would be returned by `$c->item(14)'. Similarly, the
element representing the header for Monday would be returned by
`$c->item('Mo')'. If the year happened to by 1984, then `$c->item(1984)'
would return the cell representing the year. Since years and particular
months change frequently, it is probably more useful to take advantage of
the month() and year() methods, which return the respective item symbol
for the current calendar. In the prior example, using 1984, the following
is equivalent: `$c->item($c->year())'.

   Multiple cells of the calendar can be manipulated as if they were a
single element. For instance, `$c->item(15)->attr(bgcolor => 'cyan')'
would alter the background color of the cell representing the 15th. By the
same token, `$c->item(15, 16, 17, 23)->attr(bgcolor => 'cyan')' would do
the same thing for all cells containing the item symbols passed to the
item() method.

   The calendar structure is still nothing more than a table structure;
the same table structure provided by the HTML::ElementTable class. In
addition to the item based access methods above, calendar cells can still
be accessed using row and column grid coordinates using the `cell()'
method provided by the table class. All coordinate-based methods in the
table class are accessible to the calendar class.

   The module includes support for week-of-the-year numbering, arbitrary
1st day of the week definitions, and aliasing so that you can express any
element in any language HTML can handle.

   Dates that are beyond the range of the built-in time functions of perl
are handled either by the 'cal' command, Date::Calc, or Date::Manip. The
presence of any one of these utilities and modules will suffice for these
far flung date calculations. If you want to use week-of-year numbering,
then either one of the date modules is required.

METHODS
=======

   All arguments appearing in [brackets] are optional, and do not
represent anonymous array references.

   Constructor

new()
     With no arguments, the constructor will return a calendar object
     representing the current month with a default appearance.  The initial
     configuration of the calendar is controlled by special attributes.
     Non-calendar related attributes are passed along to
     HTML::ElementTable. Any non-table related attributes left after that
     are passed to HTML::Element while constructing the <table> tag. See
     HTML/ElementTable, if you are interested in
     attributes that can be passed along to that class.

     Special Attributes for HTML::CalendarMonth:

    month
          1-12, or Jan-Dec.  Defaults to current month.

    year
          Four digit representation. Defaults to current year.

    head_m
          Specifies whether to display the month header. Default 1.

    head_y
          Specifies whether to display the year header. Default 1.

    head_dow
          Specifies whether to display days of the week header. Default 1.

    head_week
          Specifies whether to display the week-of-year numbering. Default
          0.

    week_begin
          Specify first day of the week, which can be 1..7, starting with
          Sunday. Defaults to 1, or Sunday. In order to specify Monday,
          set this to 2, and so on.

    row_offset
          Specifies the offset of the first calendar row within the table
          containing the calendar. This is 0 by default, making the first
          row of the table the same as the first row of the calendar.

    col_offset
          Specifies the offset of the first calendar column within the
          table containing the calendar. This is 0 by default, making the
          first column of the table the same as the first row of the
          calendar.

    historic
          This option is ignored for dates that do not exceed the range of
          the built-in perl time functions. For dates that do exceed these
          ranges, this option specifies the default calculation method.
          When set, if the 'cal' utility is available on your system, that
          will be used rather than the Date::Calc or Date::Manip modules.
          This can be an issue since the date modules blindly extrapolate
          the Gregorian calendar, whereas 'cal' takes some of these quirks
          into account. If 'cal' is not available on your system, this
          attribute is meaningless.  Defaults to 1.

   *Item Query Methods*

   The following methods return lists of item symbols that are related in
some way to the provided list of items. The returned symbols may then be
used as arguments to the glob methods detailed further below.  When these
methods deal with 'rows' and 'columns', they are only concerned with the
cells in the calendar - not the cells that might be present in the
surrounding table if you have extended it. If you have not set row or
column offsets, or extended the span of the containing table, then these
rows and columns are functionally equivalent to the table rows and columns.

row_items(item1, [item2, ...])
     Returns all item symbols in rows shared by the provided item symbols.

col_items(item1, [item2, ...])
     Returns all item symbols in columns shared by the provided item
     symbols.

daycol_items(col_item1, [col_item2, ...])
     Same as col_items(), but the returned item symbols are limited to
     those that are not header items (month, year, day-of-week).

row_of(item1, [item2, ...])
     Returns the row numbers of rows containing the provided item symbols.

col_of(item1, [item2, ...])
     Returns the column numbers of columns containing the provided item
     symbols.

lastday()
     Returns the number of the last day of the month.

dow1st()
     Returns the column number for the first day of the month.

days()
     Returns a list of all days of the month.

dayheaders()
     Returns a list of all day headers (Su..Sa)

headers()
     Returns a list of all headers (month, year, dayheaders)

items()
     Returns a list of all item symbols in the calendar.

first_col()
     Returns the number of the first column of the calendar. This could be
     different from that of the surrounding table if the table was
     extended, but otherwise should be identical.

last_col()
     Returns the number of the last column of the calendar. This could be
     different from that of the surrounding table if the table was
     extended, but should otherwise be identical.

first_row()
     Returns the number of the first row of the calendar. This could be
     different from that of the surrounding table if offsets were made.

first_week_row()
     Returns the number of the first row of the calendar containing day
     items (ie, the first week). This could vary depending on table offsets
     and header modes.

last_row()
     Returns the number of the last row of the calendar. This could be
     different from that of the surrounding table if the table was
     extended, but should otherwise be identical.

   *Glob Methods*

   Glob methods return references that are functionally equivalent to an
individual calendar cell. Mostly, they provide item based analogues to the
glob methods provided in HTML::ElementTable. In methods dealing with rows,
columns, and boxes, the globs include empty calendar cells (which would
otherwise need to be accessed through native HTML::ElementTable methods).
The row and column numbers returned by the item methods above are
compatible with the grid based methods in HTML::ElementTable.

   For details on how these globs work, check out HTML/ElementTable,
and HTML/ElementGlob.

item(item1, [item2, ...])
     Returns all cells containing the provided item symbols.

item_row(item1, [item2, ...])
     Returns all cells in all rows occupied by the provided item symbols.

item_col(item1, [item2, ...])
     Returns all cells in all columns occupied by the provided item
     symbols.

item_daycol(item1, [item2, ...])
     Same as item_col(), except limits the cells to non header cells.

item_box(item1a, item1b, [item2a, item2b, ...])
     Returns all cells in the boxes defined by the item pairs provided.

allheaders()
     Returns all header cells.

alldays()
     Returns all non header cells, including empty cells.

all()
     Returns all cells in the calendar, including empty cells.

   *Transformation Methods*

   The following methods provide ways of translating between various item
symbols, coordinates, and other representations.

coords_of(item)
     Returns the row and column of the provided item symbol, for use with
     the grid based methods in HTML::ElementTable.

item_at(row,column)
     Returns the item symbol of the item at the provided coordinates, for
     use with the item based methods of HTML::CalendarMonth.

monthname(monthnum)
     Returns the name (item symbol) of the month number provided, where
     *monthnum* can be 1..12.

monthnum(monthname)
     Returns the number (1..12) of the month name provided. Only a minimal
     case-insensitive match on the month name is necessary; the proper item
     symbol for the month will be determined from this match.

dayname(daynum)
     Returns the name (item symbol) of the day of week header for a number
     of a day of the week, where *daynum* is 1..7.

daynum(dayname)
     Returns the number of the day of the week given the symbolic name for
     that day (Su..Sa).

daytime(day)
     Returns the number in seconds since the epoch for a given day. The day
     must be present in the current calendar.

Notes On Dates And Spatial Relationships
========================================

   One of the nice things about having a calendar represented as a table
accessible with grid coordinates is that some of the trickier date
calculations become trivial. You can use packages such as Date::Manip or
*Date::Calc* for these sort of things, but the algorithms are often
derived from a common human activity: looking at a calendar on a wall.
Say, for instance, that you are interested in "the third Friday of every
month". If you are using a calendar with Sunday as the first day of the
week, then Fridays will always be in column 5, starting from 0. Likewise,
due to the fact that supressed headers are merely *masked* in the actual
table, the first row with dates in a calendar structure will always be 2,
even if the month, year, or day headers are disabled. The third friday of
every month therefore becomes `$c->cell(2,5)', regardless of the particular
month. Likewise, the "nth dayname/week of the month" can always be mapped
to table coordinates.

   The particulars of this grid mapping are affected if you have redefined
what the first day of the week is, or if you have tweaked the table beyond
the bounds of the calendar itself. There are methods that can help under
these circumstances, though. For instance, in our example where we are
interested in the 3rd Friday of the month, the row number is accessed with
`$c->first_week_row + 2', whereas the column number could be derived with
`$c->last_col - 1'.

REQUIRES
========

   HTML::ElementTable

OPTIONAL
========

   Date::Calc or Date::Manip (only if you want week-of-year numbering or
non-contemporary dates on a system without the *cal* command)

AUTHOR
======

   Matthew P. Sisk, <`sisk@mojotoad.com'>

COPYRIGHT
=========

   Copyright (c) 1998-2000 Matthew P. Sisk. All rights reserved. All
wrongs revenged. This program is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

SEE ALSO
========

   A useful page of examples can be found at
http://www.mojotoad.com/sisk/projects/HTML-CalendarMonth.

   HTML::ElementTable(3), HTML::Element(3), perl(1)

Perl Module for Generating HTML Calendars
*****************************************

NAME
====

   HTML::CalendarMonthSimple - Perl Module for Generating HTML Calendars

SYNOPSIS
========

     use HTML::CalendarMonthSimple;
     $cal = new HTML::CalendarMonthSimple('year'=>2001,'month'=>2);
     $cal->width('50%');
     $cal->border(10);
     $cal->header('Text at the top of the Grid');
     $cal->setcontent(14,"Valentine's Day");
     $cal->setdatehref(14, 'http://www.lovers.com/');
     $cal->addcontent(20,"Twentieth day of the month");
     $cal->addcontent(14,"<p>Don't forget to buy flowers.");
     print $cal->as_HTML;

DESCRIPTION
===========

   HTML::CalendarMonthSimple is a Perl module for generating,
manipulating, and printing a HTML calendar grid for a specified month. It
is intended as a faster and easier-to-use alternative to
HTML::CalendarMonth.

   This module requires the Date::Calc module, which is available from
CPAN if you don't already have it.

INTERFACE METHODS
=================

new(ARGUMENTS)
==============

   Naturally, new() returns a newly constructed calendar object.
Recognized arguments are 'year' and 'month', to specify which month's
calendar will be used. If either is omitted, the current value is used. An
important note is that the month and the year are NOT the standard C or
Perl - use a month in the range 1-12 and a real year, e.g. 2001.

     # Examples:
     # Create a calendar for this month.
     $cal = new HTML::CalendarMonthSimple();
     # One for a specific month/year
     $cal = new HTML::CalendarMonthSimple('month'=>2,'year=>2000);
     # One for "the current date" in 1997
     $cal = new HTML::CalendarMonthSimple('year'=>1997);

setcontent(DATE,STRING)
=======================

addcontent(DATE,STRING)
=======================

getcontent(DATE)
================

   These methods are used to control the content of date cells within the
calendar grid.

     # Examples:
     # The cell for the 15th of the month will now say something.
     $cal->setcontent(15,"An Important Event!");
     # Later down the program, we want the content to be boldfaced.
     $foo = "<b>" . $cal->getcontent(15) . "</b>";
     $cal->setcontent(15,$foo);
     # Or we could get extra spiffy:
     $cal->setcontent(15,"<b>" . $cal->getcontent(15) . "</b>");

     # Example:
     # addcontent() does not clober existing content.
     # Also, if you setcontent() to '', you've deleted the content.
     $cal->setcontent(16,'');
     $cal->addcontent(16,"<p>Hello World</p>");
     $cal->addcontent(16,"<p>Hello Again</p>");
     print $cal->getcontent(16); # Prints 2 sentences

setdatehref(DATE,URL_STRING)
============================

getdatehref(DATE)
=================

   These methods are used to control the content of date cells within the
calendar grid.

     # Example:
     # The date number in the cell for the 15th of the month will
     # be a link to the sourceforge website
     $cal->setdatehref(15,"http://sourceforge.net/");

     # Example:
     # You want to add to an URL
     $cal->setdatehref(15, $getdatehref(15)."projects/perl/");

as_HTML()
=========

   This method returns a string containing the HTML table for the month.

     # Example:
     print $cal->as_HTML();

   It's okay to continue modifying the calendar after calling as_HTML().
My guess is that you'd want to call as_HTML() again to print the
further-modified calendar, but that's your business...

year()
======

month()
=======

monthname()
===========

   These methods simply return the year/month of the calendar. monthname()
returns the text name of the month, e.g. "December".

border([INTEGER])
=================

   This specifies the value of the border attribute to the <TABLE>
declaration for the calendar. As such, this controls the thickness of the
border around the calendar table. The default value is 5.

   If a value is not specified, the current value is returned. If a value
is specified, the border value is changed and the new value is returned.

width([INTEGER][%])
===================

   This sets the value of the width attribute to the <TABLE> declaration
for the calendar. As such, this controls the horizintal width of the
calendar.

   The width value can be either an integer (e.g. 600) or a percentage
string (e.g. "80%"). Most web browsers take an integer to be the table's
width in pixels and a percentage to be the table width relative to the
screen's width. The default width is "100%".

   If a value is not specified, the current value is returned. If a value
is specified, the border value is changed and the new value is returned.

     # Examples:
     $cal->width(600);    # absolute pixel width
     $cal->width("100%"); # percentage of screen size

showdatenumbers([1 or 0])
=========================

   If showdatenumbers() is set to 1, then the as_HTML() method will put
date labels in each cell (e.g. a 1 on the 1st, a 2 on the 2nd, etc.) If
set to 0, then the date labels will not be printed. The default is 1.

   If no value is specified, the current value is returned.

   The date numbers are shown in boldface, normal size font. If you want
to change this, consider setting showdatenumbers() to 0 and using
setcontent()/addcontent() instead.

showweekdayheaders([1 or 0])
============================

   If showweekdayheaders() is set to 1 (the default) then calendars
rendered via as_HTML() will display the names of the days of the week. If
set to 0, the days' names will not be displayed.

   If no value is specified, the current value is returned.

cellalignment([STRING])
=======================

   This sets the value of the align attribute to the <TD> tag for each
day's cell. This controls how text will be centered/aligned within the
cells.

   Any value can be used, if you think the web browser will find it
interesting. Some useful alignments are: left, right, center, top, and
bottom,

   By default, cells are aligned to the left.

header([STRING])
================

   By default, the current month and year are displayed at the top of the
calendar grid. This is called the "header".

   The header() method allows you to set the header to whatever you like.
If no new header is specified, the current header is returned.

   If the header is set to an empty string, then no header will be printed
at all. (No, you won't be stuck with a big empty cell!)

     # Example:
     # Set the month/year header to something snazzy.
     my($y,$m) = ( $cal->year() , $cal->monthname() );
     $cal->header("<center><font size=+2 color=red>$m $y</font></center>\n\n");

BUGS, TODO, CHANGES
===================

   It would be nice if the week didn't have to start on Sunday. It would
also be cool if the weekday headers could be changed (Lunes, Martes,
Miercoles,...)  or suppressed. It'd be nice if the month could be
translated, as well. These features will probably make in into the next
version some time in mid-February.

   Changes in 1.01: Added VALIGN to cells, to make alignment work with
browsers better. Added showweekdayheaders(). Corrected a bug that results
in the month not fitting on the grid (e.g. March 2003).  Added
getdatehref() and setdatehref(). Corrected a bug that causes a blank week
to be printed at the beginning of some months.

AUTHORS, CREDITS, COPYRIGHTS
============================

   HTML::CalendarMonth was written and is copyrighted by Matthew P. Sisk
<sisk@mojotoad.com> and provided inspiration for the module's interface
and features. Frankly, the major inspiration was the difficulty and
unnecessary complexity of the interface. (Laziness is a virtue.)

   HTML::CalendarMonthSimple was written by Gregor Mosheh
<stigmata@blackangel.net> None of Matt Sisk's code appears herein.

   This would have been extremely difficult if not for Date::Calc. Many
thanks to Steffen Beyer <sb@engelschall.com> for a very fine set of
date-related functions!

   Dave Fuller (dffuller@yahoo.com) added the getdatehref() and
setdatehref() methods.

   This Perl module is freeware. It may be copied, derived, used, and
distributed without limitation.

1.3.1 (RELEASE)   13 Feb. 2001
==============================

     - Added new Introduction to EmbperlObject written by
       Neil Gunton. See perldoc IntroEmbperlObject
     - Added new Tips and Tricks pod written by
       Neil Gunton. See perldoc TipsAndTricks. Anybody is invited
       to send me their own Tips and Tricks!
     - Added object and isa parameters to Execute, which allows to get an
       object reference for a certain file and set the Perl inherence
       hierachive. Ideas from Neil Gunton and Angus Lees.
     - Corrected a problem that leads to very strange errors when an
       Embperl sub is called from an in memory source (that is passed
       via the Execute input parameter). Spotted by Neil Gunton.
     - Make EmbperlObject work better with relative paths and drive letters
       on Windows. Based on a patch from Freddy Vulto.
     - Fixed a problem with the cache key, which could cause that the same
       file is compiled within different packages.
     - Fixed a problem that Embperl are in a wired state after an file upload
       has been interrupted. Spotted by Dirk Lutzebaeck.
     - Fixed a problem set @ISA is not correctly setup in case a file is
       compiled in the same package as the base file of EmbperlObject.
       Spotted by Neil Gunton.
     - Fixed problem with including ../foo.html in EmbperlObject. Spotted
       by Neil Gunton.
     - Added warning if @ISA is not correctly setup/corrupted.
     - Fixed a SIGSEGV that occurs when an reference to undef is returned
       from a [+ +] inside a URL.
     - Added warning to Makefile.PL, if File::Spec 0.82 isn't installed, which is
       required by EmbperlObject.
     - Fixed "use of undefined value" warning in make test

1.3.0 (RELEASE)   4 Dec. 2000
=============================

     - Corrected a wrong test, that let make test fail. Spotted by Eddie Lau.
     - Added a Line Feed at the end of epnames.h, which has caused some problems
       with on old SunOS compiler. Spotted by Roman Maeder.
     - Fixed a problem that Perl generated an error when $req_rec and [$ var $] was
       used. Spotted by Michael Stevens.

1.3b7 (BETA)   15. Nov 2000
===========================

     - Fixed problem that the call to close triggers error in Session.pm when using
       Store::File. Spotted by Alvar Freude.
     - Fixed problem that GetSession doesn't return a value for new session.
       Spotted by Angus Lees.
     - Added new function SetSessionCookie, which can be used to set the session cookie
       header in case you use Embperl session management, but don't use a
       Embperl page in that request. Suggested by Alex Schmelkin.
     - Fixed problem that DeleteSession does not work outside the base template, when
       used with EmbperlObject. Spotted by Angus Lees.
     - Fixed problem when use multiple nested ../foo.htm inside EmbperlObject.
       Spotted by Neil Gunton.
     - Included patch from Angus Lees to ease building on debian.
     - make test now works again with BEN-SSL httpsd. With help from Neil Gunton.
     - Included grammaticaly updated Embperl.pod. Many thanks to Ilia Lobsanov
       for doing the proof reading.
     - removed dbgDisableCache to avoid problems with this "feature" that isn't working
       anymore for a long time.
     - Added validaten for session cookie. If Apache::Session 1.53+ is installed
       it uses the validate method from Apache::Session::Generate::xxx. If a invalid
       session id is found a new one is generated. Spotted by Angus Lees.
     - If a not existing session id is received, Embperl generates now a new one.
     - Enhancements of Cookie resending logic. To make sure cookies are send when
       neccessary, but not more often. (Handles now write to session data, after
       a delete in the same request correctly).
     - Added more tests for Sessionhandling.
     - Fixed a bug that Content-Lenght was 2 to much, when escmode was set to zero.
       Spotted by Michael Smith.
     - Added patches from Randy Korbes for ActiveState Support. Most tests with
       Embperl under mod_perl nows passes. The few remaining ones that doesn't pass
       seems to be due to problems of mod_perl's enironment handling.
     - Droped support for Apache::Session 0.17. Embperl now support only
       Apache::Session 1.00 and higher.
     - Added new option: optDisableSelectScan, to allow processing of SELECT tags,
       while processing of TABLE tags is disabled. Suggested by Robert.
     - Carridge Returns are only removed for Perl 5.004. This makes using of
       HERE documents possible on Perl 5.005+, even if the documents has CRLF
       as lineendings.

1.3b6 (BETA)  18. Oct 2000
==========================

     - Embperl now runs on ActiveState Perl. (At least in offline mode,
       mod_perl mode seems to still have some problems). With a lot of help
       from Randy Korbes.
     - Changed EmbperlObject search order:
       * If EMBPERL_OBJECT_STOPDIR is set, this directory is taken as
         the last directory in the normal search path, instead of the
         directory where the base template (EMBPERL_OBJECT_BASE) is found.
       * EMBPERL_OBJECT_ADDPATH is _always_ added to the search path
       * Now Embperl also searches the path for files like
         ../foo.html, or bar/foo.html, which includes a relative path.
     - ../* is now a shortcut for the requested file, but in the
       parent directory (or upper depending on the search path)
     - Added access to Embperl session handling for modules and
       calling scripts (see SetupSession and GetSession)
     - Embperl is now able to output binary data if EMBPERL_ESCMODE
       and/or $escmode is zero. This also include that no CRLF is
       added at the end of the file, if escmode is zero.
     - Added method for deleting session data and cookie
     - Added method for triggering resend of session cookie.
     - Added Test for pnotes ('EMBPERL_ERRORS')
     - Added hash %CLEANUPFILE. All variables defined into the files given
       in this hash, are also cleanup at the end of the request.
       Patch from Todd Eigenschink.
     - Changed the way the C Requestobject is attached to the Perlobject,
       so it should now also work on 64Bit Processor like Alpha.
       Spotted by Andre Landwehr.
     - Fixed a problem with importing files that contains foreach and
       do until loops, which may caused a syntax error or endless
       loop. Spotted by Steffen Geschke.
     - embpcgi* and embpexec* are now geratated out of *.templ instead
       of editied in place to avoid problems with cvs conflicts
       and lower/uppercase on Win32. Suggest by Jens-Uwe Mager.
     - make test works with Apache that has mod_jserv compiled in
     - Embperl now cache same files with relative path, which are located
       in different directories correctly.

1.3b5 (BETA)  20. Aug 2000
==========================

     - Embperl now supports Apache::Session 1.52. See "Session handling"
       in the docs, how the setup has changed.
     - Fixed a problem with POSTed data, which had got lost for the first,
       request when using EmbperlObject handler. Spotted by
       Kaare Rasmussen.
     - Fixed a typo in HTML::Embperl::Mail, spotted by Robert.
     - changed require to use HTML::Embperl in EmbperlObject to avoid problems
       with dynamic loading. Spotted by Robert.
     - Embperl takes the cookie for session handling from the Apache
       request record to make it available in earlier phases then the
       content handler. Suggested by Jack Cushman.
     - added entity decoding for value attribute of radio/checkboxes.
       Spotted by Chris Thorman.
     - %fdat is not resetup when already done and formtype is
       multipart/formdata. Spotted by Michael Slade.
     - Embperl inserts &amp; instead of a signle & inside query strings
       when expaned from array or hash refs.
     - Embperl now also accepts hashref inside a url and expand it
       to a query_string i.e. <a href="foo.html?[+ { a=>1, b=>2 }+]"> will become
       <a href="foo.html?a=1&amp;b=>2">.
     - EMBPERL_COOKIE_EXPIRES now also supports relativ times like:
       +30s +10m +1h -1d +3M +10y
     - $req_rec -> pnotes ('EMBPERL_ERRORS') could be used to retrieve
       error message inside a error document
     - make Embperl compile and run with threaded Perl 5.6. With help
       from Jason Bodnar. NOTE: That doesn't mean that Embperl is
       threadsafe!

1.3b4 (BETA)  17.07.2000
========================

     - New $escmode (or EMBPERL_ESCMODE) to disable the possiblilty
       to turn off escaping with a leading backslash. Adding 4 to
       any escmode will cause Embperl to do no special processing
       on the backslash. This is mainly to avoid problems with
       cross site scripting issuse, where people are able to enter
       aribtary HTML. Spotted by Dirk Lutzebaeck.
     - Characters between 128 and 159 are all HTML escaped now to
       avoid problems with buggy browser, which were reported to
       treat the chars 139 and 141 as < and >.  Spotted by Dirk Lutzebaeck.
     - If a requested file is not found when using EmbperlObject as handler,
       the file given by C<EMBPERL_OBJECT_FALLBACK> is displayed instead.
       If C<EMBPERL_OBJECT_FALLBACK> isn't set a staus 404, NOT_FOUND is
       returned as usual.
     - "perl Makefile.PL debug" will build debugging information for
       gdb/ms-vc++ into Embperl library.
     - test.pl can take a bunch of new options for debugging Embperl itself.
       See make test TESTARGS="--help".
     - Embperl 1.x and 2.x share now the same Makefile.PL and test.pl
     - Added new debug flag dbgObjectSerach which logs the EmbperlObjects
       work when searching the correct file.
     - If import parameter is given to Execute, Perl code is compiled, but
       only [!  !] blocks are executed (to allow sub definitions on import)
     - Space is converted to %20 instead of +, because that is more generic.
       Suggested by Michael Blakely.
     - EmbperlObject now automaticly defines all subs that are declared
       inside the base template and inside the requested page, so it isn't
       neccessary anymore to call Execute with import => 0 for them.
     - Every Embperl Page now get passed a request object (which can be obtained
       from $_[0]). The request object is a hash reference which is blessed
       into the package HTML::Embperl::Req. Embperl itself don't uses the hash, so
       you are free to populate it and pass data between different pages of one request.
     - EmbperlObject now setup the inherence so that
         request page -ISA->
         base template -ISA->
         EMBPERL_OBJECT_HANDLER_CLASS (if defined) -ISA->
         HTML::Embperl::Req
       and the Embperl request object is blessed into the packages of the
       requested page, so you can do methods calls to subs that are defined
       inside the requested page.
     - correct spelling error and renamed ScanEnvironement to ScanEnvironment.
       (ScanEnvironement still works).
     - EmbperlObject can now be used also offline (via HTML::EmbperlObject::Execute)
     - MailFormTo and HTML::Embperl::Mail::Execute now have a configuration
       directive EMBPERL_MAILHELO, can be used to specify the host/domain for the
       HELO/EHLO command. Suggested by Remco Brink.
     - Fixed a bug that caused the default drive to be incorrectly set on Win 32.

1.3b3 (BETA)  25.04.2000
========================

     - Fixed SIGSEGV which occurs in cleanup with Perl 5.6. Spotted by
       Aaron Johnson.
     - Changed make test so it works correctly with new error messages of
       Perl 5.6.
     - Fixed a bug that Execute will always fail when $@ was set before.
       Patch from Francis J. Lacoste.
     - Changed test so it accpects charset in Content-Type header from
       Apache 1.3.12
     - The outputfile parameter now also works when running under
       mod_perl. Spotted by Ilia Lobsanov.
     - Makefile.PL warns if you build with a DSO mod_perl < 1.22
     - make test checks that test files are readable by Apache.
     - Applied a patch from Jens-Uwe Magner to make Embperl work
       with mod_perl 1.22 on AIX. We now require mod_perl 1.22,
       but I should now work as DSO and staticly linked.
     - Applied a patch from Francis J. Lacoste that makes sure
       that when a package name is given the file is always compiled
       into this package. Note: This means that if you specify a
       packagename and the packagename differs from request to
       request, the page is compiled for every package and therfore
       consuming memory on every request.
     - Added EMBPERL_SESSION_HANDLER_CLASS which allows you to overwrite
       Embperl defaults session handling. Idea form Barrie Slaymaker.
     - Added EmbperlLogo.gif to the distribution, which contains
       "Powered by Embperl".
     - Added Patch from Randy Kobes that makes Embperl compile with
       Apache 1.3.12 and Perl 5.6 on Win32.
     - Removed some -w warnings form EmbperlObject
     - Added tests for EmbperlObject
     - Fixed a SIGSEGV that occured when Embperl found [*] inside
       a page. Spotted by Barrie Slaymaker.
     - Added epchar.c.min which contains translation tables which
       let's all chars above 128 untouched. This is usefull for
       processing two byte charsets. Patch from Sangmook Yi.
     - The searchpath (EMBPERL_PATH) now uses semikolons (';') instead
       of colons (':') to avoid problems with Windows drive letters.
       Colons still work on Unix.

1.3b2 (BETA) 11. Feb 2000
=========================

     - added new mod_perl handler EmbperlObject, which helps to build whole
       pages out of small objects, which can be overwritten in "derived"
       pages.
       EmbperlObject allows you to define the standard layout of your site just
       once and includes the neccessary components based on the uri. Your HTML
       documents just have to contain the unique stuff and not the common stuff
       like headers/footers or navigation bars. Also these common elements can
       be overwritten in each subdirectory.
     - added EMBPERL_PATH (and path parameter to Execute), which can contain
       a colon separated search path. Embperl uses it when a file, which does
       not contain a path, is executed.
     - added new module HTML::Embperl::Mail which sends a file processed via
       Embperl by email.
     - Fixed a bug, that the logfile if opened also EMBPERL_DEBUG is set
       to zero. Now if debug is zero, no logfile will be opened. Spotted
       by Jason Bodnar and Christian Gilmore.

1.2.1  5. Jan 2000
==================

     - fdat parameter of Execute function isn´t honoured when
       call from CGI script which has received multipart/formdata.
       Spotted by NHan H. Trinh.
     - @ffld was not correctly setup, when only fdat parameter is
       given in calls to Execute.
     - if mtime parameter is undef or 0, now the pcode really isn't
       cached. Spotted by Neeme Vool.
     - EMBPERL_OPTIONS and EMBPERL_DEBUG (debug, options) accepts
       now decimal, binary, octal and hex values.
     - fix a SIGSEGV that could occur under rare conditions in
       cleanup. With help from Todd Eigenschink and Gary Shea.
     - fix a problem that $req_rec is not correctly setup inside
       imported subs. Reported by Cliff Rayman.
     - specify domain/hostname when sending mail via MailFormTo
     - add EMBPERL_MAILFROM config, to make sender used by
       MailFormTo configurable
     - add EMBPERL_MAILDEBUG config, to allow debugging of email
       problems in MailFormTo
     - ProxyInput now handles posted form data. Spotted by
       Neeme Vool.
     - EMBPERL_INPUT_FUNC now allows to also give the name
       under which the source should cached, to allow correct
       cacheing of data read via EMBPERL_INPUT_FUNC. Spotted by
       Neeme Vool.
     - Fixed a SIGSEGV in OPTION tag which occurs due to
       different integer sizes on 64Bit systems. With help
       from David Waldo.

1.2.0  17 Nov 1999
==================

     - test script had failed in cgi mode on win32. Spotted by
       Randy Korbes.

1.2b11 (BETA)  4 Nov 1999
=========================

     - Added the "Status:" header and error message to embpcgi.pl to
       let Apache return the correct status line. Patch from Jason Holt.
     - Fixed problem that Apache SIGSEGVs when an error message contains
       a %x. Spotted by Ed Park.
     - Added missing BEGIN block in docs for Session handling.
     - Fixed an endless loop that occured when tainting is on and
       the same document is called two times via Execute. With help
       from Jason Holt.
     - Changed access to addtional upload fileinfo. The old syntax
       (${${$fdat{<name_of_field>}}}) isn't available anymore, because
       it doesn't work with filenames that are not a vaild perl
       variable name. Now there is a second field which start with a
       dash that's holds a hash ref to the file info. Spotted by
       Huang-Ming Pan.
     - The Embperl specific part of Apache session (former
       Apache::Session::Embperl) is now part of the Embperl distribution
       (as HTML::Embperl::Session). This makes Embperl independ of
       new releases of Apache::Session. Embperl now works with
       Apache::Session version 1.00 and higher. Apache::Session 0.17 is still
       supported, but the documentation is removed, because it should no
       longer be used.
     - Apache::Session must not be preloaded prior to Embperl. It's
       enought to set EMBPERL_SESSION_CLASSES and Embperl will bring
       the right modules in memory for you.
     - Removed the call to mod_perl_sent_header, which was an workaround
       for an problem with (very) old mod_perl version, because it doesn't
       resolve on (every) IRIX. Spotted by Jearanai Vongsaard.
     - NOT_FOUND, FORBIDDEN now also logged thru Apache, so the LogLevel is
       honoured and log message in Apache error log get a time stamp.
       Spotted by Christian Gilmore.
     - Removed warings that apears when compiling with -Wall.
     - Added URL of better emacs mode for Embperl from Erik Arneson.
     - Added new paramter 'errors' to Execute function which takes an
       array ref, that returns any error messages. Suggested by
       James Elson.
     - Fixed that serveral options where not settable inside an Embperl page.
       Spotted by Ilya Ketris.

1.2b10 (BETA) 7 Oct. 1999
=========================

     - Fixed a great security whole in CGI mode. Because Apache passes
       anything after the first '?' to the cgi script as commandline
       arguments, embpexec.pl could be tricked into offline mode, where
       it returned any file that is readable by the httpd! So if you are
       using CGI mode, I strongly recommend to update to 1.2b10.
       Now you must use embpcgi.pl instead of embpexec.pl in CGI mode.
       Spotted by Jason Holt.
     - Added EMBPERL_ALLOW. If the file doesn't EMBPERL_ALLOW Embperl
       will return forbidden. This is primarly another security
       feature, because dependig on the way you use Embperl in CGI mode,
       it will not honour all Apache access restrictions. With
       EMBPERL_ALLOW, you can now force it to serve only certain
       files. Suggested by Jason Holt.
     - Fixed a problem that had occured with magic SVs (tied scalar)
       as source for the Execute function. Spotted by Todd Eigenschink.
     - Embperl works now with Apache::Session 0.17, 1.02 and 1.04
       (1.03 is errornous)
     - Fixed a SIGSEGV that occurs when the req_rec parameter of the
       Execute functions gets a Apache::Request object instead of a
       Apache object, which occured due to the different ways the
       Apache internal request_rec is stored inside the object.
       Spotted by Francis J. Lacoste.
     - Fixed a SIGSEGV that occured when outputting to a scalar and
       optReturnError is set. Spotted by Francis J. Lacoste.
     - Added a ; after the begin block in startup.pl, which seems had
       cause a syntax error in some situations. Spotted by Oyvind Gjerstad.
     - exit now works the same in offline, mod_perl and cgi mode, it
       ends the execution of the page, but not the programm itself.
     - exit inside a sub will now really exit the page. (but exit inside
       a file called via Execute will only exit this file, not the whole
       request) Spotted by Cliff Rayman.
     - Added new hash %http_headers_out which could be used to set arbitary
       http header under mod_perl _and_ in cgi mode. "Location" header will
       automaticly set status to 301.
     - setting http headers and <META HTTP-EQUIV=..> now works also
       in cgi mode.
     - Session Handling now also works in CGI mode (needs
       Apache::Session >= 1.04)
     - ACTION attribute of Formtag is now URL en/decoded. Spotted by
       Hartmut Palm.

1.2b9 (BETA) 10. Sept 1999
==========================

     - Fixed a problem with loading Apache::Session 1.01, when
       Apache::Session 0.17 is not installed. Spotted by Volker Hess.

1.2b8 (BETA) 9. Sept 1999
=========================

     - Fixed behaviour of <INPUT>. <INPUT> now does not overide
       VALUE="" with the value from %fdat. This seems to has been
       broken, since a couple of versions and the fix may break
       pages that depends on that wrong behaviour. Anyway I have
       to fix it before the release version is out!
     - Added a patch (and a FAQ) from Jens-Uwe Mager, so Embperl compiles
       and links on AIX.
     - Fixed error in URL unescaping, spotted by Hartmut Palm.
     - _WINSOCK2API_ gets defined on Win32, when compiling with
       Apache 1.3.9. Spotted by Randy Korbes.
     - Win32 test uses also embpexec.test.pl (instead of .bat),
       so cgi test runs also with Apache 1.3.9. Spotted by Randy Korbes.
     - Fixed problem with EMBPERL_SESSION_ARGS that splits the arguments
       wrong when, for example, the DataSource contains a '='. Spotted by
       Vince Galloway.
     - Fix a memory leak which eats one SV per <OPTION> tag, introduced
       in 1.2b6.
     - Fix a problem that meta commands also recognized as html tags, i.e.
       now <if x> is no longer the same as [$ if x $]. Spotted by Danielle Gallo.
     - German documentation (IntroD.pod, FeaturesD.pod and EmbperlD.pod)
       are now included in the distribution.

1.2b7 (BETA) 30 Aug 1999
========================

     - Embperl works now with Apache::Session 1.01
       (1.01 _not_ 1.00 or below!)
     - Cookie for session id is only send the first time and not
       resend if it's already known by the browser. Suggested
       by Roman Maeder.
     - Fixed a SIGSEGV that occurs with $optRawInput = 1 and a
       value is in %fdat, but not in the input html tag. Spotted
       by Robert.

1.2b6 (BETA) 19 Aug 1999
========================

     - When call another page via Execute EMBPERL_VIRTLOG will
       automaticly set to the same value as the in the calling page
     - Add parameter 'firstline' to specify the linenumber of the
       first line in the input
     - Defined missing DECLINED constant for non mod_perl environement
       Spotted by James Elson.
     - Inside of an A tag URL escaped characters are translated back
       to their ascii aquivalent inside of perl code, before the code
       is executed. This avoid problems with HTML editors, which
       changes space to %20 inside an URL.
     - '%' is escaped to %25 inside of URLs
     - Inside the A tag only the HREF attribute is URL escaped, instead
       of the whole tag.
     - The SRC attribute of embed, frame, iframe, img, layer now are
       also URL escaped.
     - Giving a an array refernce inside an URL, cause Embperl expand
       it to URL parameter syntax (i.e. [+ \@A +] becomes A=1&B=2, when
       @A = (A, 1, B, 2) ).
     - Embperl checks now for unclosed metacommands (if, while etc.) and
       unclosed HTML tags (table etc.). Suggest by Todd Eigenschink.
     - Fixed a problem when file was not found, which causes in some cases
       a SIGSEGV.
     - Added new configuration directive EMBPERL_MAIL_ERRORS_TO. If set
       all error messages will be send to the given address.
     - input_/output_func parameter can take a code reference as
       argument. Based on a patch from Jon Tobey.
     - Set force PERL_DL_NONLAZY to zero, so make test does not fail
       if dynaloader was initialized with PERL_DL_NONLAZY set.
       Patch from John Tobey.
     - [$ foreach $i(x..y) $] does not require a space before the (
       anymore. Suggested by Jonny Cavell.
     - select <option value="a &amp; b"> works now correctly. Spotted by
       Rick Welykochy.
     - Fixed SegFault when parameter input => is numeric. Spotted by
       Cliff Rayman.
     - Added option optNoUncloseWarn, which disables the warnings
       about unclosed if, while, table etc.

1.2b5 (BETA)  5 July 1999
=========================

     - Renamed __strdup and __strndup so there are no duplicate
       symbols when compiling with glibc. Spotted by Michael Hall.
     - Removed some debugging message from the logfile output.
     - Correct some wrong table entries for html escaping of some
       characters like §
     - Added optReturnError which causes Embperl to return an
       error code and let the calling programm (i.e. Apache)
       handle the error. This is necessary to use the
       ErrorDocument directive together with Embperl. Spotted by
       Michael Smith.
     - Fixed the problem that the output of Execute inside a table
       didn't come out when optEarlyHttpHeader was set. Spotted by
       Chris Alexander.
     - %fdat of a Execute will not be overwritten anymore when the
       %fdat of the main request was empty. Spotted by Chris Alexander.
     - fixed a small memory leak which was caused by not releasing
       memory space for the cookie-name/-domain etc.
     - added the missing -T switch to embpexec.test.bat, which caused the
       taint test in cgi mode to fail on win32
     - Added epchar.c.iso-latin-2 from Jiri Novak, which contains the correct
       escaping for the iso-8859-2 (iso-latin-2) character set. You may use it
       to replace the standard epchar.c
     - Added new metacommand [$ sub <name> $] and [$ endsub $] which allows
       you to define blocks of code an call them mulitple times inside a page,
       either a creating a subrequest Execute('#<name>') or by calling them
       directly as a perl subroutine [- <name> -]. Read the docs for more
       information on the details and differences.
     - Added new parameter "import" to Execute, which let's you import subs
       (defined with [$sub <name>$]) into the current page.
     - @ffld is filled with 'values %fdat' if the ffld parameter in the call
       to the Execute funtion is missing.
     - Filedata will held into memory until the end of the request, so a
       second call to Execute for the same file will not reread the data
       from disk.
     - Added emacs/embperl.el. It's a emacs minor mode for Embperl written
       by Erik Arneson
     - Output of dbgShowCleanup is now sorted by name
     - Update the Faq.pod with new Q&A and removed obsolete Q&A
     - Made Makefile.PL more smarter in DSO situations. It detecteds now
       which of the needed Apache modules are linked staticly and places
       neccessary LoadModule statements in the httpd.conf for make test.
       This way make test should work also where all modules linked at
       runtime, like on RedHat 6. With help form James H. Thompson.
     - Makefile.PL ask´s now if it can´t find any modules. On win32
       it will not try to guess (the maybe wrong) path anymore.
     - Added possibility to get the the uploadInfo from CGI.pm
       (e.g. ${${$fdat{upload}}} -> {'Content-Type'} will return the
        content type). Requested by Brian Reichert.
     - Catch die of CGI.pm when it hit's a 'Malformed multipart POST'.
       Spooted by Chris Alexander.
     - Add optKeepSrcInMemory which tells Embperl to keep the source
       file in memory and not reload it on every request
     - Added the possibility to use recursive calls to Execute.
       NOTE: You can create local variables via [* local $foo ; *]
     - Reworked the cleanup. Now imported values from other modules
       left unchanged. This solves problems with using modules
       inside Embperl pages, which exports some global variables.
     - Added the %CLEANUP hash. Put variables into with should be
       additional cleaned up ($CLEANUP{'var'} = 1) or which shouldn't
       cleaned up ($CLEANUP{'var'} = 0)
     - Special handling for DBIx::Recordset objects, so it's sure
       they are really get destroyed
     - fixed a problem with dynamic tables, that occurs when you
       had tried to repeat multiple table rows
     - Embperl compiles now with perl5.005_57+. Patch from Ask Bjoern Hansen
     - Cleanup now logs any errors that occurs when calling object
       destructors and makes sure errors inside object destructors do
       not break Embperl itself.
     - Embperl now returns DECLINED when called for a directory. This
       way Apache can handle diretories the correct way. This will make
       DiretoryIndex (e.g. index.html) work again with Embperl.
     - Fixed a problem that @ffld contains the same field more then
       one time if posted from a select multiple with multiple items
       selected. This caused problems with [$hidden$]. Spotted by
       Martin Leja.
     - Double quotes (") will be url-encoded to %22 inside URLs.
     - Embperl now never writes to the logfile if EMBPERL_DEBUG is zero
     - make test now runs with newest version of mod_ssl (2.3.5)
     - Added option optKeepSpaces which will disable the removing of spaces
       and empty lines from the output. Suggested from Gary Shea.
     - Added option optOpenLogEarly, which will cause Embperl to open the
       logfile as soon as it is loaded into memory. You can use this when
       you loaded Embperl via PerlModule under Apache, to open the log
       as root instead of the non-privileged user Apache runs as.

1.2b4 (BETA)  15 Feb 1999
=========================

     - fixed a problem that $req_rec was sometimes invalid on the
       second call to the same page causing Embperl to SIGSEGV.
       With help of Todd Eigenschink.
     - Cleanup the variable space inside Embperl pages. Before this
       fix many of the internal my variables were visible to the
       Embperl page. Spotted by Todd Eigenschink.
     - multiple form values with the same name are handled now
       correctly (concated in a tab delimited string) when send
       in a multipart/form-data (file-upload). Spotted by Dirk
       Lutzebaeck.
     - The dbgForm flag works now also for multipart/form-data
     - a missing right *] will be reported as an error.
     - [[* is correctly output as [* and not interpreted as a
       starting of a perl block. Spotted by Dirk Lutzebaeck.
     - fixed a bug that causes the html after an endforeach to be
       skiped, when the foreach loop gets an empty array as argument.
       Spotted by Dirk Lutzebaeck.
     - Makefile.PL checks now for required modules and versions and
       generates warnings if necessary
     - Do not CLEAR %udat and %mdat in cleanup, so Apache::Session
       will not warn anymore about unsupported CLEAR operation.
     - Added tests for session management (%udat, %mdat)
     - Added more tests to see that $req_rec is correctly setup
     - Added module Apache::Session::epDBI which is a subclass of
       Apache::Session::DBI and corrects a problem with locking and
       cares of serializing requests, so %mdat works correctly.
       Please read IMPORTANT NOTE under Session Management in
       Embperl.pod
     - Added the dbgProfile flag which cause the display of the time
       since the request start for every source line in the logfile.
     - Correct a problem that the escape character ('\') was not removed
       when unescaping the input. Now '&lt;' is correctly translated
       to '<'  and '\&lt;' is translated to '&lt;' .
     - When requesting to view the logfile via the browser now all
       lines which does not start with a pid ([<pid>]) are displayed.
     - fixed a problem, that sometimes not all errors are shown in the
       error page, in conjunction with dynamic tables
     - When running under perl 5.005 or higher, the cleanup after the
       every request, now not only cleans up scalars, array and hashs,
       but also closes all open file- and directoryhandles and undef's
       all typglob (which causes for example DBIx::Recordset objects to
       DESTROY correctly)
       NOTE: This also causes imported variables from other packages/modules
       not to be cleanedup anymore!!
       NOTE: That the cleanup behaveiour under perl 5.004 and 5.005 is
       slightly differnt! The new cleanup doesn't work with 5.004 because
       of a bug, which should be corrected in 5.004_05 as soon as available.
     - EMail adress from the form is insert as Reply-To header instead of
       From header in MailFormTo to avoid problems with unresolvable
       EMail adresses.
     - Fixed the problem that session management (%udat, %mdat) didn't
       work when Execute is used in the same page. Spotted by by Simon Lindgren.
     - Fixed a path problem in Makefile.PL. Now pathes on Win32 Systems uses
       blackslash instead of slash. Spotted by Randy Kobes.
     - Win32 batch files will no longer contain path to perl after the #!,
       so cgi tests passes on systems with 4DOS shell. Spotted by Randy Kobes.
     - Added ; as terminator for cookie to correctly parse multiple cookies.
       Patch from Tim Carrol.
     - Changed table_set to table_add when setting the cookie for session data
       to avoid problems with other modules setting also cookies.
     - Corrected the %ENV problem that mod_perl-1.18 introduced, so both
       work together again.
     - Added dbgSession flag to enable/disable logging of session handling
     - Added configuration diretives EMBPERL_COOKIE_NAME, EMBPERL_COOKIE_DOMAIN,
       EMBPERL_COOKIE_PATH and EMBPERL_COOKIE_EXPIRES to configure the cookie
       which holds the session id. Suggested by Cliff Rayman.

1.2b3 (BETA)  22 Nov 1998
=========================

     - fixed an undefined pointer which occurs when using precompiled
       [* ... *] blocks. Spotted by Bruce W. Holyman and Paul J. Schinder
     - removed unwanted 0xa0 characters from tagscan.htm which causes
       the test to fail on sunos. Spotted by Paul J. Schnider.
     - Enhanced the detection of Stronghold, Apache SSL and mod_ssl
       so they are found if they are not in a standard path. Spotted
       by Brad Cox.
     - Convert relativ path for apache source to absolute to avoid
       problems within test script. Spotted by Brad Cox.
     - Make Embperl compile with useperio=defined. Spotted by Todd
       Eigenschink.
     - Makefile.PL does now check if mod_perl is compiled into apache
       and don't create a config for USE_DSO situtation even if
       libperl.so exists.
     - Added a workarround in the Execute('foo.htm') call, to avoid a
       bug in perl5.004 which causes a SIGSEGV. Spotted by Michael J.
       Schout and Chris Alexander.

1.2b2 (BETA) 9 Nov 1998
=======================

     - There is now a short form of the Execute function. You can
       now include a sub page in an Embperl page by simply writing
       [- Execute ('filename.html') -] or use
       [- Execute ('filename.html', 1, 2, 3) -] to pass additional
       parameters
     - Added new block [* ... *]. This block compiles code to an
       outer subroutine which surounds the whole page. This makes
       it possible to define "local" variables with a scope of the
       whole page, which would be necessary for recursive calls
       to Execute.
       Also this let you use perl control structures inside Embperl
       pages:  e.g.
           [* foreach $v (1..5) { *] Cnt = [+ $v +] [* } *]
       NOTE: [* ... *] blocks _must_ always end with a ;,{ or }
             [* ... *] cannot apear inside html tags that are
             interpreted by Embperl (unless you disable the
             interpretation of such tags like table, input etc.)
     - Added a comment block: Everything between [# and #] is a
       comment and is removed from the output.
       NOTE: [* ... *] blocks also interpreted inside of a
             [# ... #] block, all other blocks [+/-/$ $/-/+] are not.
     - Added magic hash %mdat, which can be used to store persitent
       data on a per module basis (needs Apache::Session, with
       path in session.patch applied)
     - Done more tests on session handling, seems to work fine now.
     - Added new option dbgNoHiddenEmptyValue which suppresses
       empty hidden input fields in the [$hidden$] meta command.
       Patch from Steve Willer.
     - Whitespaces after [...] blocks are removed in the output, so
       there will be less empty lines, makeing the output shorter and
       more readable, based on a patch from Todd Eigenschink.
     - Embperl compiles now with mod_ssl (from Ralf Engelschall).
       Spotted by Dirk Lutzebaeck and Randel Schwartz.
     - Added a patch from Todd Eigenschink to build Embperl with
       Stronghold 2.4.1
     - Added patch from Gerald McLarnon so Embperl compiles on AIX
     - Added optAllowZeroFileSize to accept files of length 0,
       without that option Embperl will report NOT_FOUND.
       Suggested by Doug Bagley

     - fixed a wrong call to logerror when OPT_EXECCGI is not on,
       spotted by Dirk Lutzebaeck.
     - fixed the problem that reloads only takes place at the next day,
       because mtime was an int instead of a double (introduced in1.2b1.
       Spotted by Michael Smith and Roman Maeder.
     - fixed a problem that changing of the filesize was ignored, when
       a documents is reloaded (introducted in 1.2b1)
     - cleanup for all subpages are disabled if main request has
       disabled cleanup and subpages does not specify otherwise
     - dbgShowCleanup works again
     - Every package is only cleanuped once, also it's included multiple
       times in one page
     - %fdat and @ffld are setup correctly when optDisableVarCleanup
       is set
     - DEFS=-DEPDEBUGALL compiles again, spotted by Michael Smith
     - fixed that cleanup is never called with Execute nesting, when
       req_rec was not set. Now the parameter req_rec isn't necessary
       anymore. Spotted by Michael J.Schout
     - Changes of $escmode inside a HTML-A tag now handled correctly,
       spotted by Michael Smith
     - fixed problems with links to the logfile and the line break
       in the html log file display
     - fixed a problem with blocks that expand to nothing inside of Embperl
       interpreted HTML tags.
     - Adapted test script to modified error output of Apache 1.3.4.
       Spotted by Eric Cholet.
     - Empty values (VALUE="") in input tags will not be overridden by
       value in %fdat

1.2b1 (BETA)  8 Oct 1998
========================

     - I have reworked the whole source code so Embperl is now
       going to be an object. This means Embperl is reentrant, you
       can call Execute within an Embperl page, for example to include
       the same header on each page.
     - Addeded Session handling via Apache::Session. Simply store data
       to %udat and let Embperl do the rest for you. Experimental!
       NOTE: You need Apache-Session-0.16.1 or higher and must apply
       the patch from session.patch to it.
     - Added test for calling Execute inside a Embperl page
     - Errors of Input/Output function now also log to the httpd error log
     - Added an test for input file not found

1.1.1  15 Sep 1998
==================

     - A lot of documentation updates. Now Embperl ships with most of
       the documentation which is also available on
             http://perl.apache.org/embperl/
       This includes:
       - Intro.pod  an introduction to Embperl
       - Faq.pod    an new very much extented version of the FAQ
       and a lot of spell checking, gramar checking and so on
       Thanks very much to Nora Mikes for putting together the FAQ
       and doing a lot of proof reading.
     - eg/x/upload.htm an example for file upload within Embperl
     - splited documentation out of Embperl.pm into Embperl.pod
       to make it load a little bit faster (Embperl.pm is now 30K
       instead of 90K)
     - Optimized the loading of other modules. Other modules are now
       only loaded when really necessary. This make Embperl in CGI mode
       about 2 times faster then version 1.1.0 was.
     - Added a test for file-upload
     - Embperl compiles and works now with threaded perl, but Embperl
       is currently B<not> threadsafe. So you can use Embperl in a
       threaded environement, but you have to make sure that only one
       thread useses Embperl at a time.
     - Fixed a memory leak which has occured in checkboxes and selects
     - Enhanced test.pl
     - MailFormTo: Send \n after mail header to work correctly with all
       mail servers, added EMBPERL_MAILHOST to specify mail server hostname,
       MailFormTo dies when it can't connect to mailserver. Spotted by
       Steffen Geschke.

1.1.0  28 Jul 98
================

     - Added support for perl5.005 (currently only without threads!)
     - Nesting of metacommands and HTML tags are now independent of
       each other.
     - Added examples in eg/x for do .. until, foreach, if,
       DBI datbase access, DBIx::Recordset database access and a
       input- / confirmation form.
     - Added optUndefToEmptyValue which will cause Embperl to treat non-
       existent values in %fdat as an empty string in input tags, as suggested
       by Steve Willer.
     - Catch "die" within EMBPERL_INPUT/OUTPUT_FUNC and write error
       message to the logfile
     - Write error message of LWP::UserAgent in ProxyInput to logfile
       if any
     - Added test for POST Requests
     - Added support for tests when mod_perl is built with USE_DSO.
       Spotted by Christian Oyarzun.

     - Selects and checkboxes are setup correctly if state is set via %fdat.
       Spotted by Todd Eigenschink and Steve Willer.
     - Changes URL escaping so that only space, '+', '&', '=' and chars < 0x20
       will be escaped to avoid problems with older netscape browsers.
     - Added missing documentation for req_rec parameter of the Execute
       function. Spotted by Eric Cholet.
     - Send correct http header for error page, spotted by Steve Willer
     - Fixed a memory leak in foreach metacommand
     - Removed limit of 2048 Bytes for GET request data (there is no
       limit anymore). Spotted by Steve Willer
     - Read all POSTed data (not just the first 1024 Bytes). Patch from
       Steve Willer.
     - Removed some compiler warnings spotted by Tarang Kumar Patel
     - Make sure all data is flushed to the logfile at the end of
       each request
     - Fixed a bug that causes Init to set DebugFlags to 1 instead of 0.
       Spotted by Eric Cholet.

1.1b2  27 Jun 98
================

     - Added an additional note for input- and output- escaping
       which is described in "Inside Embperl" section.
       It's very important to understand this if you have any
       problems with HTML tags or filehandles in your Perl code.
     - Embperl will recognize Apache::exit. If called inside an
       Embperl page or in a module called from an Embperl page,
       the processing of the document is immediately aborted.
       Everything processed so far is output/sent to the browser.
       Based on a patch from Steve Willer.
     - When running under mod_perl, 'exit' is an alias for Apache::exit
       in every document.
     - Enhanced the format of the Errorpage. Thanks for the patch
       from Steve Willer
     - Added a [$ foreach $] and a [$ do $] ... [$ until $]
       metacommand

     - Now multiple checkboxes with the same name will be set
       correctly, to the values posted to the document. Spotted
       by Todd Eigenschink and Nathan Krislock.
     - [+ local $escmode = 0 .... +] works now. The first setting
       of $escmode in a [+ ... +] block will now applied to the
       whole block. You cannot change $escmode inside a [+ ... +]
       block. Spotted by Chris Thormann.
     - Fixed the return path setting in MailFormFields
     - ProxyInput now passes http headers, so authentification
       will be passed thru.
     - Removed the limit 2048 for the length of HTML tags when [+ ... +]
       are included. Now there is no limit anymore. Spotted by Doug Bagley

1.1b1  14 Jun 98
================

     - Now you can set custom input and/or output functions via
       EMBPERL_INPUT_FUNC and EMBPERL_OUTPUT_FUNC. This can be
       used to chain modules together or to get the input from
       (or put the output to) non-standard locations.
     - Added a function ProxyInput which can be used to fetch
       the input from another URL instead of the disk. One possible
       usage for this is to let mod_include parse the document first
       and then let Embperl process it. Suggested by Steffen Geschke.
     - Added a function LogOutput, which will write every generated
       document to a unique file in addition to sending it to the
       browser. Suggested by Dan Peterson.
     - EMBPERL_FILESMATCH allows you to select which files in
       a Location should be processed by Embperl. The rest are handled
       by the Apache default handler. This allows you to have
       Embperl and non-Embperl documents (like gifs etc.) in
       the same directory.

     - Logfile was displayed at the wrong position when requested via the
       browser the first time after the httpd was started.

1.0.0  12 Jun 98
================

     - Make test runs with Apache 1.3.0, spotted by Eric Cholet
     - Added a definition for MAX_PATH, which is not there on SunOS 4.1.4.
       Spotted by Dan Peterson
     - Fixed a bug that causes Makefile.PL to interpret MakeMaker parameters
       spotted by Jason Bodnar
     - Fixed a bug that caused EMBPERL_PACKAGE not to be recognized.
     - Fixed a bug that caused optDisableFormData not to be recognized for
       multipart formdata.

0.28-beta 19 May 1998
=====================

     - I have added a chapter "Inside Embperl" to the docs, I hope this
       will make it clearer how escaping and unescaping works and how you
       can get desired results. Highly recommended! (Thanks for spell- and
       grammar-checking to Todd Eigenschink)
     - make test now runs under win32 (You need to install LWP and libwin32)
       IMPORTANT: You need a mod_perl version > 1.11 or you get a deadlock.
     - Compiles with apache_1.3b6
     - Added support for Stronghold and Apache_SSL to Makefile.PL and test.pl
     - Changed dbgEarlyHttpHeader to optEarlyHttpHeader because it's not a
       debugging option. dbgEarlyHttpHeader still persists, but will be removed
       in one of the following versions
     - Embperl does not change the current working directory when optDisableChdir
       is set, this saves some milliseconds per request, also the cwd is moved
       to the c code, so it runs faster then Cwd::fastwd.
       Thanks to Doug Bagley for the profile which has shown how much time
       Cwd::fastcwd consumes
     - You can set optDisableHtmlScan in EMBPERL_OPTIONS. If set, Embperl only
       recongizes [+/-/$/! ... !/$/-/+], but will not do anything with HTML tags,
       as suggested by Randy Harmon.
     - optDisableInputScan, optDisableTableScan and optDisableMetaScan can be
       used to disable only some of the HTML tag processing
     - You can set optDisableFormData in EMBPERL_OPTIONS. If set, Embperl
       will not setup the %fdat and @ffld, as suggested by Doug Bagley
     - If you use Execute, the explicit call to Init/Term isn't needed anymore,
       because Embperl performs the Init automatically when it is loaded. The
       Init function can still be used to change the path of logfile. Suggested
       by Honza Jirousek
     - All options and debugging flags can now be read/set at runtime. For
       example $optRawInput = 1 sets the optRawInputFlag. Some of the options
       are read-only, because they must be known before the request.
     - Added more tests
     - Embperl discards all errors which occur in an expression after the end
       of a dynamic table, and which are only evaluated to detect the table end and
       never displayed. This allows usage of object methods in dynamic tables,
       where the table end is caused by an undefined object. (see
       test/html/object.htm for an example). Spotted by Jason Bodnar.
     - Printing to filehandle OUT has the same effect as using [+ .. +]
       (including html-escaping)
     - Setting optRedirectStdout causes Embperl to tie STDOUT to the Embperl
       output stream (same as print OUT ...), suggested by Jason Bodar
     - Setting optAllFormData will make empty formfields occur in %fdat and @ffld
       with an empty string value, suggested by Dan Peterson

     - Embperl now handles SELECT MULTIPLE correct. All OPTIONs which are
       posted to the document will now be selected by Embperl, spotted by
       Todd Eigenschink
     - Fixed a bug that caused a '>' inside a [$/! ... !/$] block to be
       interpreted as the end of a HTML tag, spotted by Todd Eigenschink.
     - Fixed a bug which caused the SELECT/OPTIONS tag to not insert their
       values in %idat and therefore made [$hidden$] work incorrectly, spotted by
       Dave Paris [aka Spider]
     - Fixed a bug that caused the INPUT CHECKBOX tag to not insert its
       value in %idat when the value wasn't in %fdat and therefore made [$hidden$]
       work incorrectly.
     - Fixed a problem that caused magical variables to be handled as if they
       were undefined, which caused dynamic tables to end, sometimes prematurely.
     - Closing HTML tags will be correctly removed form Perl source again
       (when optRawInput is not set)
     - &nbsp; will be translated to space (0x20) instead of 0xf0
     - When EMBPERL_DEBUG is set 0, only errors and warnings will be written to
       the logfile
     - MailFormTo will generate the correct TO header and insert a Return-Path
       from the posted e-mail address
     - Changed detection of mod_perl to $ENV{MOD_PERL}. This makes sure that
       it will work correctly, even if Apache.pm isn't loaded.
     - Re-entered the optDisableEmbperlErrorPage, which was lost in one of the last
       releases, spotted by Doug Bagley.
     - The content_length of the Apache request_rec will only be set when a http
       header is sent.
     - If, Elsif and While metacommands now use SvTRUE instead of a != 0 to test the
       evaluated expression, so they now behave like the Perl ones do. Spotted by Jason
       Bondar

0.27-beta not available
=======================

0.26-beta 16 Mar 98
===================

     - Adapt include pass to compile with apache_1.3b5
     - Applied patch from Dan Walters to make Embperl compile with
       apache_1.3b3 and mod_perl on Win 32
     - Changed the order of included c headers and undef some macros
       inbetween (copied from mod_perl.c) to compile with Apache on Win 32
     - Embperl works with apache_1.3b5 on Win NT ('make test' does not yet)
       (You need the Apache source and must compile Perl with the vc++)

     - Added the 'param' parameter to the 'Execute' function to pass parameters
       from and to the Embperl document.
     - Added the 'fdat' and 'ffld' parameter to the 'Execute' function to
       setup %fdat and @ffld

     - Fixed a problem which displayed tables a second time after the end of
       the document, if dbgEarly HttpHeaders was on, thanks to Ask Bjorn Hansen
       for spotting this.
     - Fixed the return values of CheckFile, which was not correct after a change
       from 0.24 to 0.25. Thanks to Todd Eigenschrink for spotting this.
     - Fixed an error which was causing Embperl to crash on an HTML input tag without
       the 'type' parameter. Thanks to Todd Eigenschrink for the hint.
     - Fixed a problem that caused Embperl to not recognize errors correctly
       when reading the sourcefile

0.25-beta 17 Feb 1998
=====================

     - Included the "translation" of the Embperl POD to a human-readable
       form done by Todd Eigenschink
     - Started a FAQ file from the questions I answered by e-mail
     - Added the function Execute, which can be called from Perl programs
       (or Apache::Registry scripts), and can take input from (and/or
       output to) memory, as suggested by Doug Bagley and Randy Harmon
       (Look at test/html/registry/Execute.htm for an example)
     - Changed the source so that it will compile on aix, spotted by
       Patrick McAuliffe
     - Access sys_errlist via perl macro Strerror to avoid errors with
       redeclaration, thanks for spotting this to Honza Jirousek
     - Changed the tab size from 4 to 8 in my editor to be compatible with
       Unix standard
     - Added warning if dbgLogLink is set and EMBPERL_VIRTLOG is not
     - Changed the delimiter of metacommand from space to any non-alpha char
       to allow writing [$while(a==b)$] as suggested by Michael D. Dowling
     - Added config variable EMBPERL_ESCMODE to set inital values of $escmode
       as suggested by Todd Eigenschink
     - Added [! ... !]. Does just the same as [- ... -] but will only execute
       on the first request for that document. This can be used to do one-time
       initialization and to define subroutines.
     - Changed push_handlers to register_cleanup, so PERL_STACKED_HANDLERS and
       PERL_CLEANUP aren't necessary anymore, as suggested by Doug MacEachern
     - If it exists, the function CLEANUP of the processed document will be called
       before the variable cleanup, but after the connection to the client is closed
     - Added a closing </font> in the logfile which is sent to the browser, otherwise
       MS IE 4 can't handle it
     - Changed Perl constants in Perl part from subroutines to "real" constants
     - Did some general rearranging of code

     - Fixed a memory leak which caused Embperl to lose one sv per Perl
       block when a document is reloaded
     - Fixed a bug which caused [+... +] within the Textarea tag to be ignored,
       spotted by Todd Eigenschink
     - Fixed a bug in sorting hidden fields
     - Fixed a wrong argument to MakeMaker, which was causing Embperl to not be able
       to build statically, spotted by Anatoli Belomestnov (and added a
       description to the Faq on how to build a copy of Embperl which is statically-
       linked to mod_perl)
     - Fixed a problem which was causing the LOG filehandle to not be imported in
       the documents package, this was causing everything printed to LOG to sort
       of disappear

     =head1 0.24-beta 13 Jan 1998

     - Added the option optRawInput which causes Embperl not to pre-process the
       source for a Perl expression (the only exception is that CR will be removed).
       This option should be set when you are writing your code with an ascii editor.
       If you are using a WYSIWYG editor, which inserts unwanted HTML tags in your
       Perl expressions and escapes special characters automatically (i.e.
       < will occur as &lt; in the source), you should not set this option, and
       Embperl will automatically convert the HTML input back to the Perl
       expression you have written. (Thanks to Todd R. Eigenschink for a patch)
     - $0 is set to the filename of the HTML source
     - Change Current Working Directory to directory of HTML source
     - Warning messages are now also logged in logfile at the correct
       position, next to the source line
     - Perl error and warning messages contain the filename and correct
       linenumber of the HTML source
     - Sourcelines in logfile contain linenumbers
     - Output via [+ ... +] of undefined values at the end of a dynamic table
       (which must be there to end the table) do not generate a warning anymore
       NOTE: If you use them in an expression (such as $a = $arr[$row] or simply
       inside " ", you will still get a warning)
     - Open HTML source in binary mode on Win32 to avoid overhead of crlf -> lf
       translation.
     - Use aplog_error for apache_1.3 to avoid senseless os errors written to
       httpd error log

     - Removed some uninitializied value messages when running with
       -w / PerlWarn on, spotted by Todd R. Eigenschink
     - Fixed a bug which has caused nested 'while' loops to execute incorrectly
       if the condition of the outer one is false

0.23-beta 31 Dec 1997
=====================

     - Fixed a bug which caused $req_rec to be not defined anymore (Thanks to
       Todd R. Eigenschink for the hint and debugging)
     - Fixed a bug in escaping special HTML char to normal ascii (Thanks to
       Todd R. Eigenschink for the hint)
     - Makefile.PL now sets the path to your Perl binary in embpexec.pl and
       embpexec.test.pl, so that it works regardless of where your Perl is located
       (Thanks to Randall Schwartz for the hint)
     - Added the SSLDisable to the test config when running an httpsd. (Thanks
       to David Scott for the hint and Ralf S. Engelschall for the Syntax)
     - Fixed a bug in <META> tag interpretation which was causing random errors
       when not compiled for mod_perl

0.22-beta 28 Dec 1997
=====================

     - Changed include path generated in Makefile.PL so Embperl also
       compiles with apache_1.3b3 (Thanks to Doug Bagley for the hint)

0.21-beta 25 Dec 1997
=====================

     - Embperl offline mode now works under Win 32 (mod_perl and cgi mode
       not tested under Win 32 yet, but maybe it works too)
     - Totally reworked safenamespace and operatormask handling. Works now
       without memory leak, is fully configurable and also does p-code
       caching. If you use it, please look at the documentation, because
       the configuration has changed.
     - Embperl now sends its own error document if it detects an error.
       The page contains all the error messages and if you have the
       dbgLogLink enabled, all errors are links to the corresponding
       line in the logfile. (this can be disabled with optDisableEmbperlErrorPage)
     - Added new metacommand [$VAR ... $], which can be used to declare
       variables and apply the strict pragma (same as use strict ; use vars )
     - Added debug flag dbgHeadersIn which causes Embperl to log all http
       headers which are received from the client
     - Don't change any unknown HTML Escapes (i.e. && has been translated
       to ? in versions < 0.21)
     - dbgShowCleanup logs all variables which are automatically undefined at the
       end of a request (for scalars the value is also shown)
     - Error messages will also be cached, so that the compiling of the code
       only takes place once, because erroneous Perl code will cause memory
       leaks in Perl itself if it's compiled on and on and on.
     - Optimized the compiling of the embedded Perl code
     - Changed use Apache::Constants to conform with the new default exports
       introduced in mod_perl-1.07_01
     - Output of the 'hidden' metacommand is sorted in the same order as the input
       from the formfields (sorting order can also be supplied as third argument)
     - <meta http-equiv= ... > will override the corresponding http header
       (this keeps netscape from asking the user to reload the document
       when the content-type differs between the http header and the
       meta http-equiv)
       This can also be used to set http headers

     - Fixed a problem that Embperl magic variables do not work when
       the package exists before the first call to Embperl
     - Fixed a problem that caused a SIGSEGV when retrieving the same document
       containing a Perl error for the second time from the same child
     - Fixed a problem that caused Embperl to terminate in offline/cgi-mode
       when the file was not found or when access was forbidden
     - Fixed a problem with the 'hidden' metacommand, which came up when
       arguments were supplied with surrounding spaces
     - Fixed a problem that Embperl did not handle metacommands correctly
       when HTML tags (e.g. <br>) were embedded

     =head1 0.20-beta 15 Nov 97

     - Every file is executed in a separate package (don't confuse this
       with safe namespaces) to reduce unwanted effects on each other
     - Added the configuration directive EMBPERL_PACKAGE which can be used to override
       the automatically-generated package name
     - The namespace (package) used by a request is cleaned up afterwards.
       That means that every scalar, hash or array is undef'ed after the
       request to make sure nothing is lying around to possibly make the next request
       misbehave.
       This requires mod_perl with PERL_CLEANUP=1 and PERL_STACKED_HANDLER=1!
       NOTE: To get persistent variables, place them in another namespace i.e.
       write $persistent::x instead of $x
     - Added configuration directive EMBPERL_OPTIONS to configure various runtime
       options. Now only the scalar cleanup can be disabled.
     - use log_error for writing to Apache error log to get timestamp
     - Escaping inside an <A> tag is changed from an HTML escape to a URL escape
       i.e. the space is translated to + and & is translated to %26 and so on
     - Escaping can now be turned on and off via $escmode
     - Concats ENV and cgi_env under mod_perl so that PerlSetEnv can be used
       instead of SetEnv for configuration. In contrast to SetEnv, PerlSetEnv
       allows different values per directory/virtual host
     - Added two links to show source-loglines and eval-loglines when dbgLogLink
       is enabled to have a quick jump to the logfile
     - Reget pid for every request, so the correct one will be written to the
       logfile, also when Embperl is loaded at server startup
     - Check error log in make test, added test for error output

     - Fixed a bug which causes Embperl to cause a SIGSEGV when a Perl syntax
       error occurred
     - Fixed a bug so that a '>' inside of [+/- ... -/+] is not detected as the end
       of an HTML tag (Thanks to Todd R. Eigenschink)

0.19-beta 29 Oct 97
===================

     - Rewrote the code for the LOG handle. Now the handle LOG is tied so that every
       print/printf is written to embperl.log at the right position. Use this to
       do logging from your embedded code or modules

     - Fixed a bug which caused garbage to be displayed in dynamic tables (or made
       parts of the table disappear)

0.18-beta 25 Oct 97
===================

     - Added caching of p-code. Now all Perl code is compiled only once. On the
       second request, the compiled p-code is used. This makes, for example, the
       table.htm from the test about 4 times faster on the second run then it was in
       previous versions of Embperl. Also, tables and loops are faster in the first
       request, because the code is only compiled in the first iteration.
     - <Select>/<option> is now handled like <input>, this means that if a value
       for the select exists in %fdat, the corresponding option is automatically
       selected.
     - Added support for table heading (<th> tag). If all cells in a row are surrounded
       by <th>/</th> instead of <td>/</td> the row is interpreted as column headings and
       printed only once. Row headings are not supported yet, but in one of the next versions...
     - Added support for multipart/formdata to support fileupload. Embperl automatically
       detects  multipart/formdata and lets CGI.pm handle it. The results are also
       present in @ffld and %fdat like for normal formdata. See CGI.pm for more docs.
       (Thanks to eigenstr@mixi.net for the idea and material)
     - Now all the output is kept in memory and the http-header are sent when the
       processing is finish. This gives the ability to set http-headers (only under mod_perl)
       within the page. Also now the Content-Length can be sent in the http-header.
       (Thanks to eigenstr@mixi.net for the idea and material)
     - Added tests for mod_perl mode and running as cgi-script, if compilation
       for mod_perl is enabled (Thanks to Doug MacEachern for lots of ideas
       and code I have borrowed from his mod_perl)
     - Removed "= true" in MailFormTo which caused a warning and didn't declare
       syserr_list in ep.h on FreeBSD (Thanks to Michael Fuhr for the hints)
     - Added SYSNOPSIS section to docs to avoid pod2man warning and changed
       apache/src/regx to apache/src/regex in Makefile.PL (Thanks to Bob Wilkinson)
     - Splitted C-sources in some more source files

     - Fixed two minor memory leaks. Now the Embperl test suite can run 1000 times and
       more without making the httpd grow!

0.17-beta  30 Aug 97
====================

     - Removed some Compiler Warnings (Thanks to Ian Kallen for reporting them)

0.16-beta  29 Aug 97
====================

     - Added more restrictive access check when running under mod_perl
       * Option ExecCGI must be set
       * must not be a directory
     - Added a (few) more docs about how to view the Embperl logfile with
       your browser
     - Added a declaration for error-dependent stuff to compile on Solaris, check errno before
       accessing sys_errlist to avoid SIGSEVs, Fixed another warning from Sun Pro C Compiler
       (Thanks to Dan Peterson)
     - Switched I/O to PerlIO if supported by installed Perl version.
       Should now work with sfio (not tested yet)
     - Added possibilty to include Embperl commands in all HTML tags
       (did not work for body, table and tr tags in previous versions)
     - Will now preserve case of HTML tags
     - Do not interpret unknown HTML tags in any way, so as to handle "<" characters
       which do not start a HTML tag better
     - Do not display the time needed for the request if CLOCKS_PER_SEC not
       defined (e.g. SunOS - Thanks to Dan Peterson)
     - Added apache_xx/src/regx to include path, to avoid problems when
       Apache was built with its own regx library
     - Now Embperl shows which tags don't match in error message (table, dir, select etc.)

     - Fixed a bug which caused "[" characters to be printed even in a false
       if path

0.15-beta  11 July 1997
=======================

     - Added interpretation of SELECT Tag to generate dynamic listboxes
       from an arrary
     - Fixed a problem with dynamic lists
     - Fixed some warnings displayed by the Sun Pro C Compiler (Thanks to Dan Peterson)
     - Fixed an error message about missing IO::Handle
     - Changed all // comments to /* */ to be more compatible with compilers other
       than the gnu-c compiler
     - Inserted a missing return in oputc which caused a SIGSEV on Solaris  (Thanks
       to Dan Peterson)
     - Checked return code of Logfile open, to prevent a SIGSEV when Embperl cannot
       write to the logfile (it now writes an error message in server's errorlog)
       (Thanks to Dan Peterson)
     - Errors will also be logged to the server's error log (written to stderr)

0.14-beta 30 Juni 1997
======================

     - adding 8192 to EMBPERL_DEBUG and setting EMBPERL_VIRTLOG will add a link
       to Embperl output, so you can directly view the right part of the logfile
       with your browser
     - Added the LOG filehandle to print to the Embperl logfile
     - Added the possibility to handle multiple form fields with same name
     - chars which are a result of a Perl expression will not be escaped to HTML if
       they are prefixed with a backslash
     - Added support for scanning the parameters of input tags for Perl code i.e.
       [- -] and [+ +] substitution takes place
     - Replaced carriage return in Perl expression with space to avoid Perl 5.004 error
       about carriage return
     - added $req_rec to access the Apache server api when running under mod_perl

     - Fixed a bug in Safe namespace handling which was always causing ERR: 17 Namespace unknown
     - Fixed a bug which caused dynamic tables to end, if a 'if', 'while' and etc. was included
     - Fixed a bug that caused [$cmd$] to be executed only in the first iteration of a 'while'
       or a table
     - Fixed some bugs in input tag interpretation
     - Fixed a bug which occurred when Embperl encountered an input tag with value="" and %ffld=""
     - Fixed a bug in embpexec.pl that caused the options to be ignored when running offline

0.13-beta   April 26 1997
=========================

     - Moved EPENTRY (embperl_init) down to avoid crashing when compiled with
       -DEPDEBUGALL
     - Added #undefs for stdio function to compile with Perl > 5.003
       NOTE: This is a quick hack, and will be changed to use PerlIO in
       one of the next releases, so we can tie stdout of Embperl
     - Added pids (to distinguish between muliplite requests) and time to
       logfile output
     - Made many functions static and names of externals more unique to
       avoid conflicts of symbolnames with other modules
     - If file not found return status 404 instead of 500
     - Add Apache::Embperl so the module shows at CPAN also under
       module/by-module/Apache/ as suggested by Doug MacEachern

0.12-beta not publicly released
===============================

     - The mask has been removed from namespace option so it can be used
       with safe.pm > 2
     - Embperl works with -T / PerlTaintCheck on
     - Add function MailFormTo to send form contents via email
     - The dbgSource option displays only one line for better overview
     - Fixed a bug which caused the Perl operator '<' to be interpreted
       as an HTML tag in tables or while loops after the first iteration
     - Added ffld array for mod_perl mode to get the order of form fields
     - Removed vsnprintf since its not available on all platforms
     - Corrected handling of empty dynamic tables
     - Fixed a bug which was causing a Segmentaion Fault when the first
       table is empty
     - Added a script for make test
     - Fixed Error with nested if
     - Log compilation errors of embedded Perl code
     - Avoid some warnings in Embperl.pm

0.11-beta      March 25 1997
============================

     - Name changed from Embperl to HTML::Embperl!!!!!!!!
     - FORM & ENV debug output now available in all modes
     - Output from [+  +] and INPUT fields are escaped
       (e.g. < is send as &lt; )
     - Added two-dimensional tables
     - Fixed a bug which caused an endless loop when using a \
     - Fixed escaping of special HTML chars above ascii code 128
     - Added support for list tags (dir, menu, ol, ul, dl)
     - Added support for textarea tag
     - Fixed some errors

0.10b-beta	Jan 23 1997
======================

     - fixed some errors

0.10beta 	Jan 18 1997
=====================

     - first public beta release

Cleans up HTML code for web browsers, not humans
************************************************

NAME
====

   HTML::Clean - Cleans up HTML code for web browsers, not humans

SYNOPSIS
========

     use HTML::Clean;
     $h = new HTML::Clean($filename); # or..
     $h = new HTML::Clean($htmlcode);

     $h->compat();
     $h->strip();
     $data = $h->data();
     print $$data;

DESCRIPTION
===========

   The HTML::Clean module encapsulates a number of common techniques for
minimizing the size of HTML files.  You can typically save between 10% and
50% of the size of a HTML file using these methods.  It provides the
following features:

Remove unneeded whitespace (begining of line, etc)
Remove unneeded META elements.
Remove HTML comments (except for styles, javascript and SSI)
Replace tags with equivilant shorter tags (<strong> -> <b>)
etc.
   The entire proces is configurable, so you can pick and choose what you
want to clean.

THE HTML::Clean CLASS
=====================

$h = new HTML::Clean($dataorfile, [$level]);
--------------------------------------------

   This creates a new HTML::Clean object.  A Prerequisite for all other
functions in this module.

   The $dataorfile parameter supplies the input HTML, either a filename,
or a reference to a scalar value holding the HTML, for example:

     $h = new HTML::Clean("/htdocs/index.html");
     $html = "<strong>Hello!</strong>";
     $h = new HTML::Clean(\$html);

   An optional 'level' parameter controls the level of optimization
performed.  Levels range from 1 to 9.  Level 1 includes only simple fast
optimizations.  Level 9 includes all optimizations.

$h->initialize($dataorfile)
---------------------------

   This function allows you to reinitialize the HTML data used by the
current object.  This is useful if you are processing many files.

   $dataorfile has the same usage as the new method.

   Return 0 for an error, 1 for success.

$h->level([$level])
-------------------

   Get/set the optimization level.  $level is a number from 1 to 9.

$myref = $h->data()
-------------------

   Returns the current HTML data as a scalar reference.

strip(\%options);
-----------------

   Removes excess space from HTML

   You can control the optimizations used by specifying them in the
%options hash reference.

   The following options are recognized:

boolean values (0 or 1 values)
          whitespace    Remove excess whitespace
          shortertags   <strong> -> <b>, etc..
          blink         No blink tags.
          contenttype   Remove default contenttype.
          comments      Remove excess comments.
          entities      &quot; -> ", etc.
          dequote       remove quotes from tag parameters where possible.
          defcolor      recode colors in shorter form. (#ffffff -> white, etc.)
          javascript    remove excess spaces and newlines in javascript code.
          htmldefaults  remove default values for some html tags
          lowercasetags translate all HTML tags to lowercase

parameterized values
          meta        Takes a space separated list of meta tags to remove,
                      default "GENERATOR FORMATTER"

          emptytags   Takes a space separated list of tags to remove when there is no
                      content between the start and end tag, like this: <b></b>.
                      The default is 'b i font center'

compat()
--------

   This function improves the cross-platform compatibility of your HTML.
Currently checks for the following problems:

Insuring all IMG tags have ALT elements.
Use of Arial, Futura, or Verdana as a font face.
Positioning the <TITLE> tag immediately after the <head> tag.
defrontpage();
--------------

   This function converts pages created with Microsoft Frontpage to
something a Unix server will understand a bit better.  This function
currently does the following:

Converts Frontpage 'hit counters' into a unix specific format.
Removes some frontpage specific html comments
SEE ALSO
========

Modules
-------

   FrontPage::Web, FrontPage::File

Web Sites
---------

Distribution Site - http://people.itu.int/~lindner/
AUTHORS
=======

   Paul Lindner for the International Telecommunication Union (ITU)

COPYRIGHT
=========

   The HTML::Strip module is Copyright (c) 1998,99 by the ITU, Geneva
Switzerland.  All rights reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

convert between XML::DOM and {XML/HTML}::Element trees
******************************************************

NAME
====

   HTML::DOMbo - convert between XML::DOM and {XML/HTML}::Element trees

SYNOPSIS
========

     use HTML::DOMbo;
     use HTML::TreeBuilder;
     my $tree = HTML::TreeBuilder->new;
     $tree->parse_from_file('foo.html');
     my $dom_tree = $tree->to_XML_DOM;
     # Now you have a DOM element in $dom_tree!

DESCRIPTION
===========

   This class puts a method into HTML::Element called to_XML_DOM, and puts
into the class XML::DOM::Node two methods, `to_HTML_Element' and
`to_XML_Element'.

to_XML_DOM
----------

   The class HTML::TreeBuilder robustly produces parse trees of HTML, but
the trees are made of HTML::Element objects, not W3C DOM objects.  If you
want to access a TreeBuilder-made parse tree (in $tree) with a DOM
interface, use HTML::DOMbo and then call

     my $dom_tree = $tree->to_XML_DOM;

   This returns a new object of the appropriate class (presumably
XML::DOM::Element), in a new DOM document, having the same structure and
content as the given HTML::TreeBuilder/Element tree.  If you want the
elements to be instantiated against an existing document object, instead
call:

     my $dom_tree = $tree->to_XML_DOM($existing_dom_document);

to_HTML_Element and to_XML_Element
----------------------------------

   This module provides two experimental methods (in the XML::DOM::Node
class) called `to_HTML_Element' and `to_XML_Element', which clone a DOM
node (or DOM document, or document fragment) as a new HTML::Element or
XML::Element object.  You need to have the XML::Element module (from the
XML::TreeBuilder dist) installed in order to use the `to_XML_Element'
method.

   It is possible for this to throw a fatal exception.  And it it possible
for this to return a text string instead (if the DOM node given was a text
node).  Moreover, in list context it may return any number of items, if
the source object is a document fragment containing more than one
top-level node, or no nodes.

   Users are encouraged to report to me any problems (or successes) in
using this method.  The behavior of this method may change in response to
your requests.

SEE ALSO
========

   See XML/DOM, HTML/TreeBuilder,
HTML/Element, XML/Element.

COPYRIGHT
=========

   Copyright 2000 Sean M. Burke.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Sean M. Burke, <sburke@cpan.org>

HTML template class.
********************

NAME
====

   HTML::DynamicTemplate - HTML template class.

SYNOPSIS
========

     use HTML::DynamicTemplate;
     my $template = new HTML::DynamicTemplate 'path/to/template';
     $template->set_recursion_limit($integer);
     $template->set(NAME => $value);
     $template->set(NAME_1 => $value_1,
                    NAME_2 => $value_2,
                    NAME_3 => $value_3);

     $template->clear();
     $template->render();
     $template->render(@variables);

     path/to/template
     ----------------
     <html>
     <body>
     <h1>$HEADING</h1>

     <p><font color="$HIGHLIGHT_COLOR">This is standard HTML with
     arbitrary embedded variable references which are substituted
     with actual values when the template is rendered.</font></p>

     <p>Template variables may be set within the template itself
     with the special $SET directive. This is useful when setting
     variables for use by included templates. Example:
     $SET(PAGE_TITLE, "What's New"). Note: Be sure to escape
     quotes (&quot;) and closing parantheses (&#41;) as HTML
     entities.</p>

     <p>Additionally, templates may be recursively included by
     specifying a template with the special $INCLUDE directive.
     Example: $INCLUDE(templates/example.tmpl). Template paths may
     be variable references as in $INCLUDE($EXAMPLE_FILE). Note:
     Any variable references found in included templates will be
     substituted as in the original template.

     <p>Usage note: variable and directive names are always
     specified in uppercase.</p>

     </body>
     </html>

DESCRIPTION
===========

   The `HTML::DynamicTemplate' is a class implementing a HTML template in
perl. Significant features include the ability to set template variables
from within the template itself, the ability to recursively include other
templates, and the ability to selectively render a specified subset of
variables.

METHODS
=======

$template = new HTML::DynamicTemplate $template_filename;
     Constructor for the template. Returns a reference to a
     HTML::DynamicTemplate object based on the specified template file.

$template->set_recursion_limit($integer);
     A default recursion limit for template includes is implemented to
     prevent infinite recursions. Use this method to override the default
     value (10).

$template->set(NAME => $value);
     Sets template variable to given value.

$template->clear();
     Clears template variables. Useful when processing table row templates.

$template->render();
     Renders template by performing variable substitutions.

$template->render(@variables);
     Renders template by performing variable substitutions on only those
     variable names specified in @variables.

AUTHOR
======

   Copyright (c) 1999 Brian Ng. All rights reserved. This program is free
software; you can redistribute it and/or modify it under the same terms as
Perl itself.

   Created May 10, 1999 by Brian Ng <brian@m80.org>.

   Based on original work by Brian Slesinsky.

a system for embedding Perl into HTML
*************************************

NAME
====

     HTML::EP - a system for embedding Perl into HTML

SYNOPSIS
========

     <html><head><title>CGI-Env</title></head>
     <ep-comment>
     	This is an HTML document. You see. Perhaps you wonder about
     	the unknown HTML tags like ep-comment above? They are part
     	of the EP system. For example, this comment section will
     	be removed and you won't see it in your browser.
     </ep-comment>
     <ep-perl>
     	# This is an example of embedding Perl into the page.
     	# We create a variable called time, containing the current
         # time. This variable will be used below.
         my $self = $_;
     	$self->{'time'} = localtime(time());
     	''; # Return an empty string; result becomes embedded into the
             # HTML page
     </ep-perl>
     <body><h1>The current time</h1>
         Your HTML::EP system is up and running: The current time is $time$.
     </body>
     </html>

NEWS
====

   HTML::EP does now have a homepage, a CVS repository and a bug tracking
system. Try

     http://html-ep.sourceforge.net/

DESCRIPTION
===========

   Have you ever written a CGI binary? Easy thing, isn't it? Was just fun!

   Have you written two CGI binaries? Even easier, but not so much fun.

   How about the third, fourth or fifth tool? Sometimes you notice that
you are always doing the same:

     Reading and parsing variables

     Formatting output, in particular building tables

     Sending mail out from the page

     Building a database connection, passing CGI input to the database and
     vice versa

     Talking to HTML designers about realizing their wishes

   You see, it's soon to become a pain. Of course there are little helpers
around, for example the CGI module, the mod_perl suite and lots of it
more. Using them make live a lot easier, but not so much as you like.
`CGI(3)' in this node. `mod_perl(3)' in this node.

   On the other hand, there are tools like PHP or WebHTML. Incredibly easy
to use, but not as powerfull as Perl. Why not get the best from both
worlds? This is what EP wants to give you, similar to ePerl or
HTML::EmbPerl. I personally believe that EP is simpler and better
extendible than the latter two. `ePerl(1)' in this node.
`HTML::EmbPerl(3)' in this node.

   In short, it's a single, but extensible program, that scans an HTML
document for certain special HTML tags. These tags are replaced by
appropriate output generated by the EP. What remains is passed to the
browser. Its just like writing HTML for an enhanced browser!

Prerequisites
-------------

   As far as I know EP depends on no system dependent features. However,
it relies on some other Perl modules:

CGI
     The CGI module should be a part of your Perl core's installation. If
     not, you should definitely upgrade to Perl 5.004. :-) My thanks to
     Lincoln D. Stein <lstein@genome.wi.mit.edu>. Note, you need a late
     version, including the CGI::Cookie module.

HTML::Parser
     This module is used for parsing the HTML templates. My thanks to Gisle
     Aas <aas@sn.no>.

libwww
     The LWP library contains a lot of utility functions, for example HTML
     and URL encoding and decoding. Again, my thanks to Gisle Aas
     <aas@sn.no>. :-)

Mail::Internet
     Graham Barr <gbarr@pobox.com> wrote the MailTools package. Some parts
     of it, in particular the Mail::Internet module is used for sending
     mail from within the HTML page. Thank very much, Graham!

Storable
     Raphael Manfredi's <Raphael_Manfredi@grenoble.hp.com> excellent
     Storable module is used for storing sessions. I owe him much, as
     Storable is usefull in a lot of other modules.

   Perl itself and the above modules are available from any CPAN mirror,
for example

     ftp://ftp.funet.fi/pub/languages/perl/CPAN/modules/by-module

   Note that you don't need to install these manually, the CPAN module will
help you. See the `"Automatic Installation"' in this node below.

Automatic Installation
----------------------

   Installing this module (and the prerequisites from above) is quite
simple, if you have the CPAN module available and network access, you might
try an automatic installation:

     perl -MCPAN -e shell

   If the CPAN prompt appears, asking you for commands, enter

     install Bundle::HTML::EP

   Automatic installation typically doesn't work on Windows, due to a
missing C development environment. However, you might try

     ppm install http://www.cpan.org/authors/id/J/JW/JWIED/HTML-EP.ppd

Manual Installation
-------------------

   If automatic installation doesn't work, you just fetch the archive,
extract it with

     gzip -cd HTML-EP-0.1125.tar.gz | tar xf -

   (this is for Unix users, Windows users would prefer WinZip or something
similar) and then enter the following:

     cd HTML-EP-0.1125
     perl Makefile.PL
     make
     make test

   If any tests fail, let me know. Otherwise go on with

     make install

   This will put the required Perl modules into a destination where Perl
finds it by default. Additionally it will install a single CGI binary,
called `ep.cgi'.

   The docs are available online with

     perldoc HTML::EP

   If you prefer an HTML version of the docs, try

     pod2html lib/HTML/EP.pm

   in the source directory.

Using the CGI binary
--------------------

   You have different options for integrating EP into your WWW server,
depending on which server you are using and the permissions you have.  The
simplest possibility is running an external CGI binary. Another option is
to use mod_perl with Apache, see `"Using mod_perl"' in this node below.

   I suggest that you choose an extension and configure your WWW server for
feeding files with this extension into `ep.cgi'. For example, with Apache,
you can add the following lines to your `srm.conf':

     ScriptAlias /cgi-bin/ep.cgi	/usr/bin/ep.cgi
     AddType x-ep-script .ep
     Action x-ep-script /cgi-bin/ep.cgi

   This tells Apache that files with extension ep.cgi are handled by the
CGI binary `/usr/bin/ep.cgi'.  On Windows, you should replace ep.cgi with
ep.cgi.bat. Make sure, that the ScriptAlias line is entered *before* any
other ScriptAlias instruction! In particular, the following would be wrong:

     ScriptAlias /cgi-bin/ /home/httpd/cgi-bin/
     ...
     ScriptAlias /cgi-bin/ep.cgi /usr/bin/ep.cgi

   The first rule would be applied before our rule, so that it could never
match.

   From now on your server will never return files with extension .ep
directly! Verify your installation by creating the following file:

     <html><head><title>Local time</title></head>
     <body>
     The current time is:
     <ep-perl>scalar(localtime(time))</ep-perl>
     </body>

   (Note that this is a much shorter version of the example in the
synopsis.)  Store it as `/test.ep' on your web server and retrieve the
file via your Web server. If you see the time displayed, you are up and
running.

Using mod_perl
--------------

   The EP package can be integrated into mod_perl, for example by using
the following commands in `srm.conf':

     PerlModule Apache::EP
     <Files *.ep>
       SetHandler perl-script
       PerlHandler Apache::EP->handler
       Options ExecCGI
     </Files>

   Keep in mind, that mod_perl differs in many details from programming CGI
binaries. In particular you might need to restart Apache for loading
changes in modules.

Using the Internet Information Server
-------------------------------------

   I am sure there is a better way of installation, in the sense of
mod_perl, however, I am no IIS expert. I can only recommend using Perl as
an external binary, in the sense of CGI.

   The idea is to advice the IIS, that files with extension .ep have to be
executed by running

     C:\Perl\bin\perl.exe c:\Perl\bin\ep.cgi %s%s

   with %s%s being the path to the EP document. (Of course the paths have
to be adjusted to your local Perl.) This can be done by creating a new
extension in the window "Base directory/Configure". (Window name translated
from the german IIS, it´s "Basisverzeichnis / Konfigurieren" here and might
be different in english.)

Available methods
-----------------

   All EP tags are starting with the prefix *ep-*. Some available tags are:

ep-comment
     This is a multi-line tag for embedding comments into your HTML page.
     But why use this tag, instead of the usual HTML comment, `<!--'? The
     difference is, that the user will never see the former.

     Example:

          <html>
              <!-- This is a comment. I like comments. --!>
              <ep-comment>
          	    This is another comment, but you won't see it
          	    in your browser. The HTML editor will show it
          	    to you, however!
          	</ep-comment>
          </html>

     Do not try to embed EP instructions into the comment section! They
     won't produce output, but they might be executed anyways.

ep-perl
     This is for embedding Perl into your script. There are two versions of
     it: A multiline version is for embedding the Perl code immediately
     into your script. Example:

          <html>
          	<head><title>The Date</title></head>
              <body>
          	    <h1>The Date</h1>
          	    <p>Hello, today its the</p>
          	    <p align=center>
          	    <ep-perl>
          		# This little piece of Perl code will be executed
          		# while scanning the page.
          		#
          		# Let's calculate the date!
          		#
          		my($sec,$min,$hour,$mday,$mon,$year)
                          = localtime(time);
          		# Leave a string with the date as result. Will be
                      # inserted into the HTML stream:
          		sprintf("%02d.%02d.%04d", $mday, $mon+1, $year+1900);
          	    </ep-perl>
          	    </p>
              </body>
          </html>

     If you don't like to embed Perl code, you may store it into a
     different file. That's what the single-line version of ep-perl is for:

          <html>
          	<head><title>The Date</title></head>
              <body>
          	    <h1>The Date</h1>
          	    <p>Hello, today its the</p>
          	    <p align=center>
          	    <ep-perl src="date.pl">
          	    </p>
              </body>
          </html>

     You have noticed, that the little script's result was inserted into
     the HTML page, did you? It did return a date, in other words a string
     consisting of letters, digits and dots. There's no problem with
     inserting such a string into an HTML stream.

     But that's not always the case! Say you have a string like

          Use </html> for terminating the HTML page.

     This cannot be inserted as a raw string, for obvious reasons. Thus the
     ep-perl command has an attribute output. Use it like this:

          <ep-perl output=html>
              'Use </html> for terminating the HTML page.';
          </ep-perl>

     Possible values of the output attribute are raw (default), html (HTML
     encoded) and url (URL encoded).

     It's a common mistake, to use the Perl command return in embedded
     Perl.  Never do that! If you need return (there are of course
     situations where returning can help), do it like this:

          <ep-perl>
          	sub eval_me {
          	    if ($this) {
          		return 'foo';
          	    } elsif ($that) {
          		return 'bar';
          	    }
          	    '';
          	}
          	eval_me();
          </ep-perl>

     See `"Variables"' in this node below for interactions between Perl
     variables and EP variables.

     For security reasons, you might set an attribute safe, as in

          <ep-perl safe=1>...</ep-perl>

     This will create a Safe compartment for you and run the embedded
     script in the compartment. Using this attribute is highly recommended!

ep-mail
     This command will send an e-mail. The attributes will be used for
     creating the email header, in particular the subject, from and to
     attribute should be used. Example:

          <ep-mail subject="Howdy!" from="joe@ispsoft.de"
                   reply-to="joe@ispsoft.de" to="bill@whitehouse.gov">
          	Hello, Bill, old chap. How are you?

          Yours sincerely,
          Jochen
              </ep-mail>

     You can still use EP variables in the E-mail body, for example the
     following works:

          <ep-mail subject="Test" reply-to="$cgi->email$" to="joe@ispsoft.de"
                   from="webmaster@www.mydomain.com">
              Hello, Joe,
              this e-mail was sent to you by $@cgi->name$.
          </ep-mail>

     But note that we suppress conversion into HTML format in the mail
     body!  See `"Variables"' in this node below for details.

     Recent sendmail versions are quite picky about validity of email
     addresses.  Thus it is highly recommended that you use valid
     addresses for the to and from fields. If you want to customize the
     sender, you'd better choose a fixed from field and modify the
     *reply-to* field only, as in the example above.

ep-errhandler
     This command advices EP, what to do in case of errors. See `"Error
     handling"' in this node below. Example:

          <ep-comment>
          	Set the template being used for system errors.
          </ep-comment>
          <ep-errhandler type=system src=/templates/syserr.html>
          <ep-comment>
          	Likewise, set the template for user errors.
          </ep-comment>
          <ep-errhandler type=user src=/templates/usererr.html>

     If an error occurs, the given scripts are loaded and used as templates
     instead of the current one. You don't need external files! Instead
     you can use

          <ep-errhandler type=user>
              <HTML><HEAD><TITLE>User error</TITLE></HEAD>
              <BODY><H1>User error</H1>
              <P>Replace user and continue. :-)</P>
              <P>To be serious, the following problem happened:</P>
              <PRE>$errmsg$</PRE>
              <P>Please return to the calling page, fix the problem
              and retry.</P>
              </BODY></HTML>
          </ep-errhandler>

     However, you might prefer to use a single error template and of course
     it's faster to use external error templates than parsing builtin
     templates. (At least, if no error occurs. :-)

ep-error
     This command forces an error message. See `"Error handling"' in this
     node below.  You can trigger user or system errors by setting the
     type attribute to the values system (default) or user. The msg
     attribute is for setting the error message.

     Example:

          <ep-comment>
          	If no email address was entered, force a user error.
          </ep-comment>
          <ep-if eval="$cgi->email$">
              Email address is ok.
          <ep-else>
          	<ep-error msg="Missing email address" type=user>
          </ep-if>

ep-database
     This command connects to a database. Its attributes are dsn, user and
     password corresponding to the same attributes of the DBI connect
     method. See `DBI(3)' in this node for details on DBI.

     Example:

          <ep-database dsn="DBI:mysql:test" user="joe"
          	         password="Authorized?Me?">

     You can use different database connections by using the dbh attribute:

          <ep-database dbh="dbh2" dsn="DBI:mSQL:test">

     The dbh attribute advices EP to store the DBI handle in the given
     variable. (Default: dbh) See `"Variables"' in this node below.

ep-query
     This command executes an SQL statement. The query attribute will be
     used for passing the SQL statement. Of course a multiline version is
     available, thus

          <ep-query statement="INSERT INTO foo VALUES (1, 'bar')">

     is the same as

          <ep-query>
          	INSERT INTO foo VALUES (1, 'bar')
          </ep-query>

     If your query retrieves a result, use the result attribute to store it
     in a variable, for example like this:

          <ep-query statement="SELECT * FROM employees" result="employees"
                    resulttype="hash" startat=0 limit=-1>

     This will create a variable `employees', an array ref of hash refs.
     You can use the ep-list command for displaying the output. See
     `"Variables"' in this node below.

     When using multiple database connections, use the dbh attribute for
     choosing the connection. (See the *ep-database* method above.)

     If you have big result tables, you might prefer DBI's
     *fetchrow_arrayref* method over creating hash refs, because arrays
     are created faster than hash refs. This is achieved by setting the
     attribute *resulttype* to array. The default is hash. Other
     resulttypes are *single_hash* and *single_array*: If your query will
     return at most a single element, then the result variable will
     contain the first row (or an undefined value) and not an array.

     Sometimes you don't want to retrieve the complete result table. In
     that case you can use the attributes *startat* and limit. For example,
     to retrieve rows 0-19, use *startat=0* and *limit=20*. Likewise you
     would use *startat=20* and *limit=20* for rows 20-39.

     When using the *MySQL* engine, the *startat* and limit attributes are
     directly mapped to MySQL's *LIMIT* clause.

ep-list
     This command is used to display an array of refs. Lets assume, that
     the variable `employees' contains a an array ref of refs with the
     attributes name and *department*. Then you could create a table of
     employees as follows:

          <table><tr><th>Nr.</th><th>Name</th><th>Department</th>
          <ep-list items="employees" item="e">
          	   <tr><td>$i$</td><td>$e->name$</td><td>$e->department$</td>
          </ep-list>
          </table>

     This will be processed as follows: For any item in the array,
     retrieved from the variable `employees', create a variable e and
     display the text between ep-list and /ep-list for it by replacing the
     patterns $e->name$ and $e->department$ with the corresponding values.

     The variable i is initially set to 0 and incremented by one with any
     element.

     As an alternative to the items attribute, you may prefer the range
     attribute: For example

          <ep-list range="1..12" item=month><OPTION>$month$</ep-list>

     will create the options array of a select box for you, where the user
     can select a month. If your prefer month names, you may better choose

          <ep-list range="jan,feb,mar,apr,jun,jul,aug,sep,oct,nov,dec"
           item=month><OPTION>$month$</ep-list>

     It is even possible to mix both versions, as in

          <ep-list range="1..3,6..7,10" item=m><OPTION>$m$</ep-list>

     See the *ep-select* command below for another example of the range
     attribute.

     It is possible to nest multiple ep-list statements, as in

          <ep-list range="1..3" item="i"><ep-list range="4..6"
            item="j">$i$$j$ </ep-list></ep-list>

     This will create the output "14 15 16 24 25 26 34 35 36".

ep-select
     This is similar to ep-list, but it is specifically designed for
     creating SELECT boxes and similar things. We explain it by example:

          <ep-select name="year" range="1991..1995" item="y"
                     selected="$cgi->year$">
              <OPTION $selected$>$y$</ep-select>

     If you supply a *selected* attribute, then a variable *selected* will
     be created for any item. The value will be either an empty string or
     the word SELECTED (configurable via the attribute *selected-text*),
     depending on whether the item matches the *selected* value or not.

ep-input
     This is usefull for reading an objects data out of CGI variables.
     Say you have a form with input fields describing an address, the
     field names being address_t_name, address_t_street, address_n_zip and
     address_t_city. By using the command

          <ep-input prefix="address_" dest="address">

     the EP program will create a variable "address" for you which is an
     hash ref as follows:

          $cgi = $_->{cgi};
          $_->{address} = {
          	name =>   { col => 'name',
          		    val => $cgi->param("address_name"),
          		    type => 't',
          		  },
          	street => { col => 'street',
          		    val => $cgi->param("address_street"),
          		    type => 't',
          		  },
          	zip =>    { col => 'zip',
          		    val => $cgi->param("address_zip"),
          		    type => 'n',
          		  },
          	city =>   { col => 'city',
          		    val => $cgi->param("address_city"),
          		    type => 't'
          		    }
          };

     In general column names beginning with address will be splitted into
     `prefix_type_suffix', the type being one of

    t
          Text columns (CHAR, VARCHAR, BINARY, or whatever), that will be
          quoted using the $self->{'dbh'}->quote() method.

    n
          Numeric columns (INTEGER, REAL, ...) that will be left untouched

    dd
    dm
    dy
          Day, month and year of a date. The combined fields will be
          quoted as 'yyyy-mm-dd'.

    s
          Set columns as created using MultiSelect boxes; the selected
          values will be used for creating a comma separated string.

     The idea is generating SQL queries automatically out of the address
     variable. This task is supported by the *sqlquery* attribute:

          <ep-database dsn="DBI:mysql:test">
          <ep-input prefix="address_" dest="a" sqlquery=1>
          <ep-comment>Create a new record, if no ID is given</ep-comment>
          <ep-if eval="$cgi->id$">
          <ep-query
           statement="INSERT INTO addresses ($@a->names$) VALUES ($@a->values$)">
          <ep-else>
          <ep-query
           statement="UPDATE addresses SET $@a->update$ WHERE id = $@id$">

     The *sqlquery* creates attributes names, values and update for you,
     that may be used in INSERT or UPDATE queries. Note that the *ep-input*
     must be preceeded by an *ep-database* call, because it is using DBI's
     quote method. `DBI(3)' in this node.

     There are situations where you want to fetch not only a single object,
     but a list of objects. Suggest an order form of articles. Then you
     might have input fields *art_0_t_name*, *art_0_n_count*,
     *art_0_n_price*, *art_1_t_name*, ...

     In that case you can give the *ep-input* command an attribute list,
     like this:

          <ep-input prefix="art_" dest="art" list=1>

     The module will read an array ref of objects to the variable dest.
     Any object will have an additional scalar variable i referring to the
     items number, beginning with 0. In other words, you can process the
     order form as follows:

          <ep-input prefix="art_" dest="art" list=1>
          <ep-perl>
            my $self = $_;
            my $sum = 0.0;
            for (my $i = 0;  defined($self->{cgi}->param("art_$i_n_count"));
          	   $i++) {
          	  $sum += $self->{cgi}->param("art_$i_n_count") *
                        $self->{cgi}->param("art_$i_n_price")
            }
            ''
          </ep-perl>
          <ep-mail from="$cgi->email$" to="order@mydomain"
                   subject="Order form">
            The following items have been ordered:

          Nr.    Price   Article

          <ep-list>
            $art->count->val$  $art->price->val$  $art->name->val$
          </ep-list>

          Total sum: $sum$
              </ep-mail>

ep-input-sql-query
          <ep-input-sql-query dest=art>

     This method is internally called by ep-input and implements the
     creation of the names, values and *updates* attributes.

     It takes as input the hash ref given by the variable dest, usually
     created by ep-input. The hash ref consists of column names as keys
     and hash refs with the attributes type and val.

     The main reason for putting this into a separate method is
     subclassing: It is quite usual, that you want ep-input to read the
     data, then do some verification and/or modification on the data (for
     example, canonicalizing dates) and finally create the SQL query. This
     can be done quite easily by subclassing the *_ep_input_sql_query*
     method: Within the method you verify and/or modify data entered by
     the user and then call the super class.

     For example, a typical subclass implementation could look like this:

          sub _ep_input_sql_query {
            my $self = shift;  my $attr = shift;
            # If the user left the MYCOL column empty, set it to NULL.
            my $dest = $attr->{'dest'};
            $self->{$dest}->{'MYCOL'} = undef
          	if $self->{$dest}->{'MYCOL'} eq '';
            $self->SUPER::_ep_input_sql_query($attr);
          }

ep-include
     Sometimes you want to source external files. This can be done by using

          <ep-include file="myfile">

     If a file with the given name doesn't exist, the file name is treated
     as being relative to your WWW servers DOCUMENT_ROOT directory.

ep-exit
     This directive terminates processing of the current HTML page.

ep-set
     This instruction is setting an EP variable. Suggest the following
     example:

          <ep-set var=myvar val=value>

     From now on you can use

          $myvar$

     as an alias for "value". There's also a multiline version:

          <ep-set var=myvar>value</ep-set>

     The main difference between the single and the multiline version is
     that the multiline version allows supressing variable interpretation
     by setting the *noparse* attribute:

          <ep-set var=myvar noparse=1>my $value$</ep-set>

     The above example is indeed setting myvar to "my $value$" *without*
     escaping $value$!

Conditional HTML
----------------

   It is possible to blank out parts of the HTML document. See the
following example:

     <html><head><title>Conditional HTML</title></head>
     <body>
       <h1>Conditional HTML</h1>
       <ep-if eval="$_->{cgi}->param('i') < 0">
         You have entered a negative number for i!
       <ep-else eval="$_->{cgi}->param('i') == 0">
         You have entered zero for i!
       <ep-else>
         <ep-if eval="$_->{cgi}->param('j') < 0">
           You have entered a negative number for j!
         <ep-else eval="$_->{cgi}->param('h') == 0">
           You have entered zero for j!
         <ep-else>
           Ok, both numbers are positive.
         </ep-else>
       </ep-else>
     </body>
     </html>

   The example is of course somewhat unnatural, because you'd better use a
single ep-perl in that case, but it shows that we can use arbitrary
complex structures of conditional HTML.

   The eval attribute is simply treated as a truth value, as in Perl.
Thus empty strings or numeric zeros are FALSE, everything else is TRUE.
This is reversed, if you replace eval with *neval*:

     <ep-if neval="$a$">
       a is not set
     <ep-else>
       a is set
     </ep-if>

   If you'd like to compare numeric values, use the *cnd* attribute, as in

     <ep-if cnd="$a$<$b$">
       a is lower than b
     <ep-else>
       a is greater than or equal to b
     </ep-if>

   You may choose either of ==, !=, <, >, <= or >= for the condition. And
finally you may compare string values like this:

     <ep-if cnd="'$a$' eq '$b$'">
       a is equal to b
     </ep-if>

   Note the use of the single quotes, which is really required here.
Available conditions are eq and ne.

   As with ep-list, you may nest multiple ep-if's or combine them with
ep-list. The following is invalid, though:

     <ep-list range="1..3" item="i">
       <ep-if cnd="$i$<3">ok</ep-list></ep-if>

   As the ep-if starts within the ep-list, it must also be terminated
before the corresponding /ep-list.

Localization
------------

   Localization is available via the HTML::EP::Locale module. Currently it
only offers methods for localizing strings.

   To access the module, let's assume you prefer your visitors reading the
german (de) version of your page, but it is also available in english
(en). Then start your HTML page with

     <ep-package name="HTML::EP::Locale" accept-language="de,en">

   When the package is loaded, it tries to guess your documents language.
The default language is *de* (german) or whatever you choose when
installing the package. Another language can be specified by

   * By setting the CGI variable language, for example by making a link to
     `mypage.ep?language=en'.

   * By setting the environment variable *HTTP_ACCEPT_LANGUAGE*; most
     browsers do this for you. For example with Netscape, this variable is
     configurable via Edit/Preferences/Navigator/Languages.

   Two possibilities are available for localizing strings. For short
strings like titles, headers or Link refs you might prefer this version:

     <ep-language de="Titel" en="Title">

   Obviously this is not appropriate for longer strings and it must not
contain HTML patterns. Thus another version is available:

     <ep-language language=de>
       <p>Dies ist ein Absatz.</p>
       <p>Dies ist der zweite Absatz.</p>
     <ep-language language=en>
       <p>This is one paragraph.</p>
       <p>This is another paragraph.</p>
     </ep-language>

   Note you need not use a /ep-language for terminating the german part,
similar to the ep-if, ep-elseif, ..., ep-else, /ep-if structure.

   A special problem with localization is the choice of a character set.
You can fix a certain character set with something like

     <META HTTP-EQUIV="Content-type"
           CONTENT="text/html; CHARSET: iso-8859-2">

Error handling
--------------

   Error handling with EP is quite simple: All you do in case of errors is
throwing a Perl exception. For example, DBI handles are created with the
RaiseError attribute set to 1, so that SQL errors trigger a Perl
exception. You never care for errors!

   However, what happens in case of errors? In that case, EP will use the
template that you have set with ep-errhandler and treat it like an
ordinary EP document, by setting the variables errmsg and admin.

   If you don't set an error handler, the following template will be used,
which is well suited for creating an own error template:

     <html><head><title>Internal error</title></head>
     <body><h1>Internal error</h1>
     <p>An internal error occurred. The server has not been able to
     fullfill your request. The error message is:</p>
     <pre>
     	$errmsg$
     </pre>
     <p>Please contact the Webmaster,
     <a href="mailto:$admin$">$admin$</a>,
     tell him the URL, the time and error message.
     </p>
     <p>We apologize for any inconvenience, please try again later!</p>
     <br><br><br><p>Yours sincerely,</p><p>The Webmaster</p>
     </body>
     </html>

Variables
---------

   It is important to understand, how EP variables work, in particular when
working with ep-perl.

   You always have an object $_, which is an instance of the HTML::EP
class (a subclass of HTML::Parser). This object has certain attributes, in
particular `$_->{cgi}', a CGI object and `$_->{dbh}', the DBI handle. (Of
course valid after `ep-database' only.) If you want to set or modify a
variable, you have to set `$_->{varname}'. If you want to retrieve the
value, use the same. Note that you cannot use $_ for a long time, as it
will be changed by Perl loops and the like, thus your Perl code typically
starts with

     $_ = $self;

   But how do you access the variable from within EP documents? You just
write

     $varname$

   This will be replaced automatically by the parser with the value of
`$_->{varname}'. Even more, the value will be converted into HTML source!

   If `varname' is a structured variable, for example a hash or array ref,
you may as well use

     $varname->attrname$
     or

     $varname->0$

   to access `$_->{varname}->{attrname}' or `$_->{varname}->[0]',
respectively. A special value of *varname* is cgi: This will access the
CGI variable of the same name, thus the following are equivalent:

     $cgi->email$

   and

     $_->{cgi}->param('email');

   But what, if you don't want your variable to be HTML encoded? You may
as well use

     $@varname$	(Raw)
     $#varname$	(URL encoded)
     $~varname$	(SQL encoded)

   The latter uses the $_->{dbh}->quote() method. In particular this
implies that you have to be connected to a database, before using this tag!

   You can even use these symbols in attributes of EP commands. For
example, the following will be usefull when sending a mail:

     <ep-mail subject="Howdy!" from="$@cgi->email$"
     	     to="bill@whitehouse.gov">

   Attributes may include EP variables, just like ordinary HTML code.
Even more, they may contain Perl code which is evaluated just like code
between `<ep-perl>' and `</ep-perl>'. However, you need to use the
variable $_ in the code, because the package otherwise doesn't detect what
you want it to do.

   See `"Custom variable formatting"' in this node for setting up your own
formats.

   Of course you can set EP variables from within an ep-perl section. But
sometimes it is desirable to set them from within HTML. In such cases you
can do something like

     <ep-set var="a" val="b">

   Now, if you do a

     Variable a has the value $a$.

   the value b will be emitted. It is also possible to set multiline
variables:

     <ep-set var="a">
       This is a template, extending a single line.
     </ep-set>

Custom variable formatting
--------------------------

   Sometimes the builtin formatting methods of HTML::EP are not sufficient.
A good example are currencies. These can be handled with format methods.
For example, see the following method for german currency values:

     <ep-package name="MyPackage">
     <ep-perl>
         package MyPackage;
         sub _format_DM {
     	    my($self, $val) = @_;
     	    sprintf("%.2f DM", $val);
     	    $val =~ s/\./,/;
     	    $val;
         };
         ''
     </ep-perl>

   This can be used as follows, suggest we have the following variables:

     a = 1
     b = 2.4
     c = 34.47

   then we can use

     a = $&DM->a$	       	=>  1,00 DM
     b = $&DM->b$	       	=>  2,40 DM
     c = $&DM->c$	       	=> 34,47 DM

   In other words: Use the special marker &, followed by the custom
formats method name, the dereferencing operator and finally the variable
name.

   The above method is already predefined by the HTML::EP::Locale module.

   As you have seen, the pattern $&METHODNAME->var$ triggers the call of

     $self->_format_METHODNAME($self->{'var'});

   It is not always usefull to fix a method name. In such cases you may
instead store a code ref in

Modifying the CGI headers
-------------------------

   The attribute $self->{'_ep_heaaders'} is containing arguments that you
want to pass to CGI->header(). Use it like this:

     <ep-perl>
       $_->{'_ep_headers'} = { '-status' => '402 Payment required',
     			      '-expires' => '+3d'
     			     }
     </ep-perl>

Doing a redirect
----------------

   A redirect is moving the browser to another page without actually
displaying the current page. You can do it like this:

     <ep-redirect target="http://other.server/other/page">

Producing Non-HTML
------------------

   Say you want a CGI binary that creates a gif and not an HTML document.
(See the `ifgif.ep' file from the SNMP::Monitor distribution for an
example.) Two problems are arising here: First of all you have to create
your own headers. Next you *must* prevent that EP is emitting any output,
because this might trash your images validity. Here's what to do:

     <ep-perl>
         my $self = $_;
         my $cgi = $self->{'cgi'};
         $self->_ep_database({'dsn' => 'DBI:mysql:test',
     			     'user' => 'joe',
     			     'password' => 'joe'});
         $self->_ep_query({'statement' => "SELECT image FROM images WHERE"
     			      . " id = " . $cgi->param('id'),
     			  'result' => 'im',
     			  'resultype' => 'single_hash'});
         $self->print($cgi->header('-type' => 'image/gif'),
                      $self->{im}->{'image'});
         $self->Stop();
     </ep-perl>

   Note the use of $self->Stop()!

NPH Scripts
-----------

   The Apache server and other WWW servers have a nice feature that allows
you to return HTML pages line by line: If your script is called something
like nph-myscript then the server is passing the scripts output to the
browser immediately. This is usefull, for example, if you display the
output of a traceroute command: You'd like to see any line immediately,
but it may take some time untill the next line arrives.

   Unfortunately NPH scripts are not well suited for HTML::EP: One of EP's
major targets is that you need not care for errors: They may occur at any
point but are still catched and handled by creating an error message.
However, there's no other way to guarantee this without buffering output
until the script ends.

   If you really need to use NPH, do it like this:

     <ep-perl>
       my $self = $_;
       local $| = 1; # make sure that Perl isn't buffering
       $self->print($self->{'cgi'}->header('-type' => 'text/html',
     					  '-nph' => 1));
       for (my $i = 0;  $i < 20;  $i++) {
     	$self->print("This is line $i. Waiting one second ...\n")
     	sleep 1;
       }
       $self->Stop();
     </ep-perl>

   Note, that *no* more output will be produced by EP after calling
$self->Stop()!

DEBUGGING
=========

   Debugging CGI applications is always a problem. The EP module does its
best to support you.

   Whenever you supply a CGI variable debug, then the module will enter
debugging mode. For example if your document is `/mypage.ep', then tell
your browser to fetch `/mypage.ep?debug=1'. You won't see the usual HTML
page, but a plain text page with lots of debugging messages and the
created HTML source.

   You may extend the debugging code with sequences like

     <ep-perl>
         my $self = $_;
         $self->print("I'm here!\n") if $self->{debug};
     </ep-perl>

   Note that you should not call the print function directly, but the
print method! The former works well in CGI environments, but EP should
work even in other environments as well.

   But sometimes this is not sufficient: What's inserting debugging
messages compared to using the Perl debugger? In that case you can emulate
a CGI environment as follows:

     export DOCUMENT_ROOT=/usr/local/www/htdocs
     export PATH_TRANSLATED=$DOCUMENT_ROOT/mypage.ep
     export REQUEST_METHOD=GET
     export QUERY_STRING="var1=val1&var2=val2"
     perl -d /usr/bin/ep.cgi

   This allows you single-stepping through your program, displaying
variable values and the like.

   However, the debug variable is obviously a security problem. For that
reason the *debughosts* variable is present in HTML::EP::Config: You
should set it to a regular expression matching the IP numbers of hosts
that are allowed to enable debugging mode. The Makefile.PL should query
for appropriate settings automatically while running.

EXAMPLES
========

   The program comes with a set of examples incorporated. These are:

     - A simple Unix user administration in examples/admin.

     - A generic frontend for editing DBI tables in examples/edit.ep

     - A POP3 client for the web in examples/pop3.

   Other examples are:

     - The SNMP monitor, a utility for watching, logging and displaying
       interface utilization and status of network interfaces via WWW.
       See the directory authors/id/JWIED on any CPAN mirror, for example
       ftp://ftp.funet.fi/pub/languages/perl/CPAN.

     - The EP Explorer, an application I wrote for managing printer queues
       on a Unix hosts. The user can select a file for printing it, much
       like he did within the Windows explorer. Likewise, he can watch
       the printer status.

     - The HTML::EP::Glimpse package, a simple search engine based on
       Glimpse. (In other words, some flavour of WebGlimpse, which is
       much simpler to install and maintain and allows a free design.)

EXTENSIONS
==========

   It is quite easy to write own methods.

Single line extensions
----------------------

   For example, suggest you want a method for setting EP variables:

     <ep-set var="e" value=1>

   Once the variable is created, you can access it via

     $e$

   This can be done like this:

     <ep-perl package="HTML::EP">
       # Write a handler for ep-env:
       sub _ep_set ($$) {
           my($self, $attr) = @_;
     	  my $var = $attr->{'var'};
     	  my $val = $attr->{'value'};
     	  $self->{$var} = $val;
     	  '';
       }

     # Return an empty string:
     '';
         </ep-perl>

   Note that we used the name *_ep_set*: By default the EP module takes
the method name (*ep-env* in out case) translates all hyphens to
underscores and adds a leading underscore. We'll see in the next section
how you can override this behaviour.

Multi line extensions
---------------------

   But how to write methods, that use a `<tag>' .. `</tag>' syntax? As an
example, we write a method for creating external files.  The method
receives two attributes, a file attribute for the files name and a
*contents* attribute for the files contents. The method can be used in two
ways:

     <ep-file file="test.dat" contents="Hi!">

   or like this, in multiline mode:

     <ep-file file="test.dat">
         Hi!
     </ep-file>

   Here it is:

     <ep-perl package="HTML::EP">
     # Write a handler for ep-file:
     sub _ep_file {
         my $self = shift; my $attr = shift;
     	my $contents = $self->AttrVal($attr->{'contents'}, @_);
         my $file = $attr->{'file'};
     	require Symbol;
     	my $fh = Symbol::gensym();
     	(open($fh, ">$file)  &&  (print $fh $contents)  &&
             close($fh)) or die "Error while creating $file: $!";
     	'';
     }
     # Return an empty string:
     '';
     </ep-perl>

   The main difference to the previous example is that our method is that
a special attribute (*contents*) is defined, that may be passed as part of
the ep-file statement. However, if you don't define it as part of the
statement, the *AttrVal* method reads more text from the document untill
it finds a matching /ep-file.

   Note the use of the Symbol package when accessing files: *Never* use
global handles like

     open(FILE, ...)

   as this might break future multithreading code!

   The above example works well, if you don't need to nest your statement.
If this should be the case, you need to deal with EP's token streams. See
the ep-if and ep-list methods for examples.

External extensions
-------------------

   So far we have discussed only minor extensions that we did install as
part of HTML::EP. However, this is somewhat dangerous with mod_perl:
Suggest you have multiple virtual hosts. It might happen, that virtual
host www.foo.com defines a method ep-file, but www.bar.net defines
another. We'd have an immediate name space clash.

   To prevent such a namespace pollution, EP supports external extensions
with an inheritage model that is borrowed from Perl. Suggest we write a
Shop extension. Of course this extension borrows from HTML::EP::Session.
Thus we have the following class design:

     Shop  ---isa--->  HTML::EP::Session  ---isa--->  HTML::EP

   We start writing our Shop extension like any other Perl package:

     package Shop;
     @Shop::ISA = qw(HTML::EP::Session); # HTML::EP::Session inherits
                                         # from HTML::EP

     sub _ep_shop_session {
         my($self, $attr) = @_;
     	# Initialize the session
     	...
     	'';
     }

     sub init {
     	my $self = shift;
     	if (!$self->{'_ep_shop_initialized'}) {
     	    $self->{'_ep_shop_initialized'} = 1;
     	    $self->SUPER::init();
     	    # Do something here
     	    ...
     	}
     }

   In the HTML page we load this package as follows:

     <ep-package name="Shop">
     <ep-shop-session>

   This will do a *require Shop*, bless the object *$self* into the class
*Shop* and call *$self-*init()>. Note that we allow the init method to be
called more than once, this is important for stacking packages.

   By default packages are loaded from Perl's system directories. You can
use the attribute lib to add private directories to the library search
path. This can be relative to the servers document root, as in

     <ep-package name="Shop" lib="/perl-lib">

Inheriting from multiple extensions
-----------------------------------

   You may use multiple ep-package statements, as in

     <ep-package name="HTML::EP::Locale">
     <ep-package name="HTML::EP::Session">

   Your object will be blessed into a new class, that inherits from both.
However, note that the order is reversed: In the above example, your
object will be an instance of class HTML::EP::PACK2 and
HTML::EP::PACK2::ISA will be set to

     qw(HTML::EP::Session HTML::EP::Locale)

CHANGES
=======

   This section describes user visible changes against previous versions.
For details and other modifications see the `ChangeLog' file, that is part
of the distribution.

epparse
epperl
     In previous versions it was not possible to include EP variables or
     Perl code in attributes of EP commands, unless using a prefix
     `epparse-' or `epperl-', as in

          <ep-mail to=joe epparse-from="$cgi->mail$" subject=Hello>

     This is no longer the case, because the package now autodetects
     whether you are using such constructs. (At least it should. :-) The
     obvious disadvantage is an incompatibility, but the new version is
     much better readable and surprisingly even (much!) faster, because
     only hash values are modified and not hash structures.

TODO
====

     Create an EP server that is accessible via a small C wrapper

     Add a preprocessor, that creates Perl code as output.

AUTHOR AND COPYRIGHT
====================

   This module is

     Copyright (C) 1998-1999	Jochen Wiedmann
                           	Am Eisteich 9
                           	72555 Metzingen
                           	Germany

     Phone: +49 7123 14887
     Email: joe@ispsoft.de

   All rights reserved.

   You may distribute this module under the terms of either the GNU
General Public License or the Artistic License, as specified in the Perl
README file.

SEE ALSO
========

   `DBI(3)' in this node, `CGI(3)' in this node, `HTML::Parser(3)' in this
node

An EP interface to the CGI::EncryptForm module
**********************************************

NAME
====

   HTML::EP::CGIEncryptForm - An EP interface to the CGI::EncryptForm
module

SYNOPSIS
========

     <!--
       This is the first page. We receive some complex data
       here from an HTML form and want to pass it to nextpage.ep.
       Start with loading the package.
     -->
     <ep-package name="HTML::EP::CGIEncryptForm">

     <ep-perl>
       # Process some CGI input and store the results in the
       # hash ref $_->{'form'}, aka EP variable "form".
       ...
     </ep-perl>
     <form action=nextpage.ep method=post>
       <ep-cef-encrypt source=form dest=enc_form>
       <input type=hidden name=myform value="$@enc_form$">
       ...
     </form>

     <!--
       This is the second page. We want to get the data from
       the first page, in other words, restore the variable
       "form" and its contents. That's easy.
     -->
     <ep-package name="HTML::EP::CGIEncryptForm">
     <ep-cef-decrypt source="cgi->myform" dest=form>

DESCRIPTION
===========

   This package is rather similar to the HTML::EP::Session module. In fact,
so similar, that they may be merged in the future. It was contributed by
Peter Marelas <maral@phase-one.com.au>, the author of the CGI::Encryptform
module.

   The modules idea is as follows: Suggest you are building a wizard.  In
other words, an application gathering information on several HTML forms.
As HTTP is a stateless protocol, the burden of moving the collected
information from page to page is up to you. The HTML::EP::CGIEncryptForm
module will greatly help you in this.

   The idea is as follows: The collected information is stored in a
single, structured variable, for example a hash ref. For example, you
could have three pages for configuring an hosts network settings: The
first page contains a form where the user enters IP address and network
mask. The second page allows to add the DNS servers and the third page the
routes. With HTML::EP::CGIEncryptForm, these pages could look like this
(most details omitted):

     <!-- This is the first page  -->
     <!-- No EP here, just simple HTML -->
     <form action=page2.ep method=post>
       <table><tr><th>IP address</th>
                  <td><input name="ipaddress" size=15></td></tr>
              <tr><th>Network mask</th>
                  <td><input name="netmask" size=15></td></tr>
       </table>
     </form>

     <!-- This is the second page, page2.ep. We start with
          loading the package:
     -->
     <ep-package name="HTML::EP::CGIEncryptForm">
     <!-- Now, collect the information in $self->{settings}: -->
     <ep-perl>
       my $self = $_;
       my $cgi = $self->{cgi};
       $self->{settings}->{ipaddress} = $cgi->param('ipaddress');
       $self->{settings}->{netmask} = $cgi->param('netmask');
       ''
     </ep-perl>
     <!-- Encode the settings into a string: -->
     <ep-cef-encrypt source=settings dest=enc_settings
                     secret_key="Whatakey?">
     <!-- Finally, pass the settings variable to the next page
          by using a hidden field:
     -->
     <form action=page3.ep method=post>
       <table><tr><th>DNS Server 1:</th>
                  <td><input name="dns1" size=15></td></tr>
              <tr><th>DNS Server 2:</th>
                  <td><input name="dns2" size=15></td></tr>
       </table>
       <input type=hidden name=settings value="$@enc_settings$">
     </form>
     <p>So far, you have created the following settings:</p>
     <table>
       <tr><th>IP address:</th><td>$settings->ipaddress$</td></tr>
       <tr><th>Netmask:</th><td>$settings->netmask$</td></tr>
     </table>

     <!-- And, finally, this is page3.ep. We start with retrieving
          the collected data:
     -->
     <ep-package name="HTML::EP::CGIEncryptForm">
     <ep-cef-decrypt source="cgi->settings" dest="settings"
                     secret_key="Whatakey?">
     <!-- Add the DNS servers to the settings variable:  -->
     <ep-perl>
       my $self = $_;
       my $cgi = $self->{cgi};
       $self->{settings}->{dns1} = $cgi->param('dns1');
       $self->{settings}->{dns2} = $cgi->param('dns2');
       ''
     </ep-perl>
     <p>So far, you have created the following settings:</p>
     <table>
       <tr><th>IP address:</th><td>$settings->ipaddress$</td></tr>
       <tr><th>Netmask:</th><td>$settings->netmask$</td></tr>
       <tr><th>DNS Server 1:</th><td>$settings->dns1$</td></tr>
       <tr><th>DNS Server 2:</th><td>$settings->dns1$</td></tr>
     </table>

   The main advantage of CGI::EncryptForm is that it is not only
serializing data, but encrypting and decrypting as well.

METHOD INTERFACE
================

   These are the methods offered by the HTML::EP::CGIEncryptForm class:

Encrypting a structured variable into a string
----------------------------------------------

     <ep-cef-encrypt source="source_var" dest="dest_var"
                     secret_key="somekey" usecharset=1>

   or, from within ep-perl:

     $self->_ep_cef_encrypt({'source' => 'source_var',
     			  'dest' => 'dest_var',
     			  'secret_key' => 'some_key',
     			  'usecharset' => 1});

   (Instance method) Takes the complex EP variable $source_var$ (aka
$self->{'source_var'}) and encrypts it into a string. The *secret_key*
attribute is used for encrypting the string. The optional attributes
*usecharset* and charset are passed to the corresponding methods of
CGI::EncryptForm.

   If the dest attribute is present, the string is stored in the EP
variable $dest_var$. If not, the output is returned and possibly inserted
into the HTML stream.

Decrypting a structured variable from a string
----------------------------------------------

     <ep-cef-decrypt source="source_var" dest="dest_var"
                     secret_key="somekey" usecharset=1>

   or, from within ep-perl:

     $self->_ep_cef_decrypt({'source' => 'source_var',
     			  'dest' => 'dest_var',
     			  'secret_key' => 'some_key',
     			  'usecharset' => 1});

   (Instance method) Takes the EP variable $source_var$ (aka
$self->{'source_var'}) and decrypts it into a complex Perl object.  The
*secret_key* attribute is used for decrypting the string. The optional
attributes *usecharset* and charset are passed to the corresponding
methods of CGI::EncryptForm.

   If the dest attribute is present, the Perl object is stored in the EP
variable $dest_var$. If not, the output is returned and possibly inserted
into the HTML stream.

SEE ALSO
========

     L<CGI::EncryptForm>, L<HTML::EP>, L<HTML::EP::Session>

An HTML::EP extension for editing a table via WWW
*************************************************

NAME
====

   HTML::EP::EditTable - An HTML::EP extension for editing a table via WWW

SYNOPSIS
========

     <!-- Connect to the database --!>
     <ep-database dsn="DBI:mysql:test">
     <!-- Make HTML::EP edit your table: --!>
     <ep-edittable-edit table=MyTable>

DESCRIPTION
===========

   It is quite usual that you make your database tables editable via a WWW
frontend. Writing such a frontend should be fast and simple for both the
database administrator and the web designer.

   HTML::EP::EditTable comes with a set of ready-to-use HTML files,
suitable for an example table called *Termine* and an example subclass.
Usually the Web designer just picks off the HTML files and modifies them
until they fit his design wishes. Then the database administrator takes
the files and usually just modifies the column names. If he wishes to add
some private data checking or similar things, he can do so by subclassing
the HTML::EP::Edittable class.

AVAILABLE METHODS
=================

     <ep-edittable-edit table=MyTable id=ID what-to-do=insert>

   This method combines the following possibilities:

   * Selecting a record out of the table *MyTable*.

   * Inserting a new record into the table *MyTable*.

   * Updating a record in the table *MyTable*.

   * Deleting a record from the table *MyTable*.

   What the method exactly does, depends on the value of the CGI variable
*what-to-do*: This can be either empty, insert, update or delete.

   If *what-to-do* is insert or update, then the method will first call
the HTML::EP method *ep-input*. If the attributes dest, prefix and
*sqlquery*, which this method expects, are not set, then they will by
default be set to *MyTable*, *MyTable_* and 1, respectively.

   If *what-to-do* is insert, then the query

     INSERT INTO MyTable ($@MyTable->names$) VALUES ($@MyTable->values$)

   will be executed. Likewise, the query

     UPDATE MyTable SET $@MyTable->update WHERE ID = $cgi->ID$

   will be executed for the value update.

   If *what-to-do* is insert or delete, then the method will attempt to
retrieve a row from the table *MyTable*. It does so, by looking at the
column ID (default, you can overwrite this by setting the attribute id
when calling the method) and the CGI variable of the same name, which
contains the column ID, usually the primary key of the table.

   The fetched row will be converted into the same format returned by
*ep-input*: Thus you can always work with the same data format in all HTML
pages.

SEE ALSO
========

   `HTML::EP(3)' in this node, `DBIx::RecordSet(3)' in this node

Web driven browsing of a filesystem
***********************************

NAME
====

     HTML::EP::Explorer - Web driven browsing of a filesystem

SYNOPSIS
========

     <ep-explorer-browse>

DESCRIPTION
===========

   This application was developed for DHW, a german company that wanted to
give its users access to files stored on a file server via certain
applications defined by an administrator. (See

     http://www.dhw.de/

   if you are interested in the sponsor.) The rough idea is as follows:

   The users are presented a view similar to that of the Windows Explorer
or an FTP servers directory listing. On the top they have a list of
so-called actions. The users may select one or more files and then execute
an action on them.

INSTALLATION
============

   The system is based on my embedded HTML system HTML::EP. It should be
available at the same place where you found this file, or at any CPAN
mirror, in particular

     ftp://ftp.funet.fi/pub/languages/perl/CPAN/authors/id/JWIED/

   The installation of HTML::EP is described in detail in the README, I
won't explain it here. However, in short it is just as installing
HTML::EP::Explorer: Assumed you have a file

     HTML-EP-Explorer-0.1003.tar.gz

   then you have to execute the following steps:

     gzip -cd HTML-EP-Explorer-0.1003.tar.gz | tar xf -
     perl Makefile.PL
     make		# You will be prompted some questions here
     make test
     make install

   Installation will in particular create a file

     lib/HTML/EP/Explorer/Config.pm

   which will contain your answers to the following questions:

   *      Install HTML files?

     If you say y here (the default), the installation script will install
     some HTML files at a location choosed by you. Usually you will say
     yes, because the system is pretty useless without it's associated
     HTML files. However, if you already did install the system and
     modified the HTML files you probably want to avoid overriding them.
     In that case say n.

   *      Directory for installing HTML files?

     If you requested installing the HTML files, you have to choose a
     location. By default the program suggests

          F</home/httpd/html/explorer>

     which is fine on a Red Hat Linux box. Users of other systems will
     modify this to some path below your your web servers root directory.

   *      Directory for installing CGI binaries?

     If HTML files are installed, you must install some CGI binaries too.
     This question allows you to select an installation path, by default
     the subdirectory cgi within the directory for installing HTML files.

     Note that you need to configure the httpd so that it treats this
     directory as a CGI directory. For example Apache users may add the
     following to `srm.conf':

          ScriptAlias /home/httpd/html/explorer/cgi

   *      UID the httpd is running as?

     The explorer scripts need write access to some files, in particular
     the configuration created by the site administrator. To enable write
     access, these files are owned by the Unix user you enter here, by
     default the user *nobody*.

     In most cases this will be the same user that your httpd is running
     as, but it might be different, for example if your Apache is using the
     suexec feature. Contact your webmaster for details.

   If you didn't already do so, configure your web server for feeding
files with extension *.ep* into the CGI binary *ep.cgi* or into the
mod_perl module *Apache::EP*. The README of HTML::EP tells you how. See
`HTML::EP(3)' in this node.

   That's it! Assuming the directory `/home/httpd/html/explorer' is
reachable as `/explorer' in your browser, point it to

     http://localhost/explorer/

   You should now see a directory listing. If so, proceed to
`CONFIGURATION' in this node.

CONFIGURATION
=============

   Besides the questions you already answered when installing the explorer,
the system is configurable via any Web browser. Assuming the Explorer is
reachable below http://localhost/explorer/, Point your browser to

     http://localhost/explorer/admin/prefs.ep

Security considerations
-----------------------

   The first thing you probably notice is that you need not supply a
password for accessing this page. This should be changed. A typical
configuration requests that only the user root can visit this page. For
example, with Apache, you could insert the following into your httpd.conf:

     <Location /explorer/admin>
       AuthUserFile /etc/passwd
       AuthName "Explorer Administration"
       AuthTyoe basic
       require user root
     </Location>

   (Of course one can discuss whether this is a secure thing, as it could
allow deducing the root password by using some sort of crack mechanism.
On the systems where I use it there ary typically lots of other
possibilities for doing the same ... :-)

E-Mail address of the administrator
-----------------------------------

   From time to time the system will use this address for sending emails
to you.

Actions
-------

   This is the explorers heart. Actions are merely shell scripts, to which
the files will be fed, that your users have selected.

   To create an action, fill out the following fields:

Name
     This is some short text that your users will see on the web frontend.
     For example, it could be *Printing on the LaserJet*.

Icon
     This (optional) entry means that the explorer will use the named image
     file to display it instead of the name above. For example, this could
     be a small gif with the word *LaserJet* on it.

     You must supply an URL here. If you are using Apache, then a lot of
     nice icons are accessible in your httpd's icons directory. See the
     README file.

Script
     This is a shell command that the explorer will execute for performing
     the action. The command may use the variables file (the filename) or
     user (the users name). For example, one could use

          lpr -Plaserjet -U $user $file

     The user name is deduced by looking at the environment variable
     REMOTE_USER: If your directory */explorer* is password protected,
     then this variable will contain the users name as set by the web
     server. If the variable is empty, then the user name anonymous is
     used.

     Don't try to protect the user or file name with quotes: The Explorer
     will use Perl's quotemeta function to secure these variables. For
     example, if your tricky users supply a file name

          `rm -rf /`

     then the Explorer will run the command

          lpr -Plaserjet -U anonymous \`rm\ -rf \/\`

     which is safe. See Perlsec (perl.info), for more
     details on security considerations with Perl.

     If your script command is able to process multiple files with one
     command, then you may prefer

          lpr -Plaserjet -U $user $files

     The Explorer will detect that you are using *$files* and not $file
     and will run a single command.

Status script
     Similar to the action script, this one will try to guess the current
     status.  A typical command might be

          lpq -Plaserjet -U $user

     The status script is suggested to produce output looking like that of
     lpq.

Logfile
     Path of a logfile to view

   Note that you see only one (empty) action at the start: If you fill it
out and hit *Save settings*, then a second (empty) row will appear
automatically. To be precise, you will always have one empty row at the
bottom.

   Actions can be removed by just blanking out the name and hitting *Save
settings*.

Status cache
------------

   To save CPU time, you might like to make use of the Status cache.  By
setting this variable to a certain number of seconds, say 300, the
Explorer will not always run the status script. Instead it will create a
cache file in the subdirectory status and save the status script's output
there. When the status is queried the next time, this cache file will be
used, unless the cache file's modification time is more that the given
number of seconds in the past. In that case a new cache file will be
created by running the status script again.

Initial directories
-------------------

   In most cases you are not interested in giving your users access to the
whole directory tree. For example, if your users use a Samba server to
place files on your machine, than the Explorer should probably restrict
your users to the Samba servers files.

   To create an initial directory, fill out the following fields:

Name
     This is a verbose name that your users will see instead of the
     directory path. For example, it could be a Samba share name.

Directory
     The real directory path.

   By default your users will still be able to access files outside of the
initial directories and these paths are only suggestions. This can be
changed by disabling *Allow access to other directories*.

   Again, you will always see one empty directory at the bottom of the
list. To create a new directory just fill this out and hit *Save
Settings*. Wipe out the name for removing an existing directory.

File types
----------

   People are used to see only certain files when selecting them for
actions. For example, when opening an existing document in Microsoft Word,
then you will by default see only files with extension *.doc*.

   A file type can be created by filling out the following fields:

Name
     This is a description of the file type, that your users will see. For
     example, it could be

          PostScript files (*.ps)

     or

          All Files (*)

Icon
     This is an (optional) icon to use for showing the file type. For
     example, it could be

          /icons/ps.gif

     or

          /icons/unknown.gif

     (Note that these are indeed meaningful settings with any default
     Apache installation, because Apache has a lot of icons included.  See
     the file icons/README from the Apache distribution.)

Regular Expression
     This is a Perl Regular Expression which files must match in order to
     be of this type. For example it could be

          \.ps$
          \.pdf$
          \.(?:ps|pdf)$
          .*

     for PostScript files, PDF files, PostScript or PDF files or all files.
     See `perlre(3)' in this node for details on Perl's regular
     expressions.

MODIFYING THE EXPLORER
======================

   When modifying the explorer, you should know about the following
methods:

Initializing the Explorer
-------------------------

   Probably any HTML page using the explorer system should contain the
following:

     <ep-package name=HTML::EP::Explorer accept="de,en">
     <ep-explorer-init noprefs=0>

   The *_ep_explorer_init* method is initializing the users cookie.  First
it verifies, whether the user already has an explorer cookie set. If not,
the user will be redirected to the *prefs.ep* page, unless the attribute
*noprefs* is set. This page will allow him to fix his personal settings
and return to the calling page.

   The explorer class is a subclass of both *HTML::EP::Locale* and
*HTML::EP::Session*. That means that the locale settings are still valid
in the *ep-package* call (in particular the accept attribute that tells
this page is ready for either german, aka de, or english). Likewise the
attributes of *ep-session* are valid in the *ep-explorer-init* call.
`HTML::EP(3)' in this node.  `HTML::EP::Session(3)' in this node.

Reading and/or writing the admin settings
-----------------------------------------

   Within `admin/prefs.ep' and some other pages, you find the following
call:

     <ep-explorer-config file="config.pm" maysafe=0>

   which read the admin settings from an external file, by default
`config.pm'. The settings will instead be read from the CGI input and
saved into the same file, if the CGI variable save and the attribute
*maysafe* are true. (The latter should happen within the `amdin' dirctory
only.)

   The method will set the following EP variables:

$config$
     The config hash ref, as read from the file `config.pm'.

$actions$
     The list of actions. Shortcut for $config->actions$.  An action looks
     like

          { 'name' => 'Print to lp',
            'icon' => '/icons/lp.gif', # May be undef
            'script' => 'lpr -Plp -U $user $file'
          }

$directories$
     The list of directories. Shortcut for
     *$self->{'config'}->{'directories'}*. A directory looks like

          { 'name' => 'Root directory',
            'dir' => '/'
          }

$filetypes$
     The list of file types. Shortcut for
     *$self->{'config'}->{'filetypes'}*. A file type looks like

          { 'name' => 'PostScript files (*.ps)'
            'icon' => '/icons/ps.gif', # May be undef
            're' => '\.ps$'
          }

$num_directories$
     The number of elements in *$self->{'directories'}*. May be 0.

Reading and/or writing the users settings
-----------------------------------------

   The users settings can be read and/or written by calling

     <ep-explorer-prefs>

   This will call *_ep_explorer_init* internally, by setting the *noprefs*
attribute to true. If either of the CGI variables save or
*save_and_return* is set, it will read the users new settings from the CGI
environment by running *$self->ReadPrefs* and store the session (that is,
return a cookie) by calling *ep-session-store*.

   If the current oage is called from another page (that is, the CGI
variable *return_to* is set to the calling page) and the CGI variable
*save_and_return* is set, then the calling page is included with
*ep-include*.

Setting the Explorers current directory
---------------------------------------

   The method

     <ep-explorer-basedir>

   will read the users current directory from the session or CGI variable
*basedir*. The current directory will be compared against the list of
initial directories and the following EP variables will be set:

$basedir$
     The selected current directory. If this is different from
     *$session-*basedir> then the latter will be modified and *$modified$*
     will be set.

$in_top_dir$
     True, if the current directory is one of the initial directories or
     in /, False otherwise.

$in_base_dir$
     If the current directory is below one of the initial directories,
     then this variable will contain the associated element from the
     directory list. That is $in_base_dir->name$ is set to the name of
     this initial directory and $in_base_dir->dir$ the path.

     Otherwise the variable is set to undef. If this is the case and the
     administrator has set "Allow access outside initial directories" to
     True, then a system error is triggered.

$display_dir$
     If $in_base_dir$ is set, then this variable is set to the current
     directories path, relative to the directory from $in_base_dir$.  For
     example, if you are in `/usr/local/bin' and the initial directory is
     `/usr/local', then the display directory is `/bin'.

Setting the sorting mode
------------------------

   The method

     <ep-explorer-sortby>

   attempts to guess the requested sorting mode from the CGI or session
variable sortby. The guessed mode (by default name) will be stored in
$sortby$. If this is different from $session->sortby$, then the latter
becomes set to the new value and $modified$ is set.

Setting the file type
---------------------

   The method

     <ep-explorer-filetype>

   attempts to guess the file type that the user requests (That is,
whether the user wants to see only certain files.) by looking at the CGI
or session variable filetype. By default the first file type from the list
$filetypes$ is choosen. If no list is set, then all files become selected.

   If a file type was choosen, the file type is stored in $filetype$.  and
$filetype->selected$ is set to true. (Note, you must not call
*ep-explorer-config* later!) If $filetype->name$ is different from
$session->filetype$, then the latter is modified and $modified$ is set to
true.

Creating the directory listing
------------------------------

   The listing becomes created with

     <ep-set var=dir_template>
       <tr><td><!-- HTML code for listing a directory
       		 You may assume that $l$ is an instance of
                    HTML::EP::Explorer::Dir.
                 -->
           </td></tr>
     </ep-set>
     <ep-set var=file_template>
       <tr><td><!-- HTML code for listing a file
       		 You may assume that $l$ is an instance of
                    HTML::EP::Explorer::File.
                 -->
           </td></tr>
     </ep-set>
     <ep-explorer-browse basedir="$env->DOCUMENT_ROOT$" item=l>

   The method is calling *ep-explorer-basedir*, *ep-explorer-filetype* and
*ep-explorer-sortby* internally. Then a directory listing is created and
sorted, according to these methods results.

   Finally, HTML code is generated for any item in the list by using the
templates $dir_template$ or $file_template$, depending on the items type.

Performing an action
--------------------

   The method

     <p>I will execute the following command:</p>
     <pre>
       <ep-explorer-action action="myaction" file="myfile" execute=0>
     </pre>
     Here you can see the output:
     <pre>
       <ep-explorer-action action="myaction" file="myfile" execute=1>
     </pre>

   performs an action, as requested by the user. The method is reading an
action name from the CGI variable *faction* or the attribute *faction*.
The corresponding action, if any, is stored in $action$.  If no action is
found, a system error is triggered.

   Then the method is looking for either of the CGI variable files or the
attribute files. If this is set, it is treated as a blank separated list
of file names. (Tab, Carriage return etc. are counting as blanks.)

   Otherwise the method expects a single file name in the CGI variable
file or the attribute file. If neither is set, a system error is triggered.

   If the attribute execute is set to false, then no commands are
executed. Instead the method returns the commands being executed.
Otherwise the command is executed and the output returned.

AUTHOR AND COPYRIGHT
====================

   This module is

     Copyright (C) 1998-1999	Jochen Wiedmann
                           	Am Eisteich 9
                           	72555 Metzingen
                           	Germany

     Phone: +49 7123 14887
     Email: joe@ispsoft.de

   All rights reserved.

   You may distribute this module under the terms of either the GNU
General Public License or the Artistic License, as specified in the Perl
README file.

SEE ALSO
========

   `HTML::EP(3)' in this node, `HTML::EP::Session(3)' in this node

A simple search engine using Glimpse
************************************

NAME
====

   HTML::EP::Glimpse - A simple search engine using Glimpse

SYNOPSIS
========

     <!-- Put the following in your EP page: -->
     <!-- Load the Glimpse package: -->
     <ep-package name="HTML::EP::Glimpse">
     <!-- Run glimpse: -->
     <ep-glimpse-search>
     <!-- List the hits: -->
       <ep-list items=files item=f>
         <tr><td><a href="$f->url$">$f->title$</a></td>
       </ep-list>

DESCRIPTION
===========

   This is a simple search engine I wrote for the movie pages of a friend,
Anne Haasis.

   It is based on HTML::EP, my embedded Perl system and Glimpse, the well
known indexing system, as a backend.

INSTALLATION
============

   First of all, you have to install the latest version of HTML::EP, 0.20
or later, and it's prerequisites. Next you have to install this package,
HTML::EP::Glimpse. If you don't know how to install Perl packages, it's
fairly simple: Fetch the required archives from any CPAN mirror, for
example

     ftp://ftp.funet.fi/pub/languages/perl/CPAN/modules/by-module/HTML

   and then do, for example

     gzip -cd HTML-EP-0.20.tar.gz | tar xf -
     perl Makefile.PL
     make
     make test
     make install

   It's even more simple, if you have the CPAN module available:

     perl -MCPAN -e shell
     install HTML::EP
     install HTML::EP::Glimpse

   While running *perl Makefile.PL* in the HTML::EP::Glimpse directory,
you'll be prompted some questions. These are explained in the
CONFIGURATION section below. See `CONFIGURATION' in this node.

   Your web server must be ready for serving EP pages. See the HTML::EP
docs for details of the web server configuration. `HTML::EP(3)' in this
node.

CONFIGURATION
=============

   The module is configured at installation time when running *perl
Makefile.PL*. However, you can repeat the configuration at any later time
by running *perl -MHTML::EP::Glimpse::Install -e Config*.

   Configuration will create a module *HTML::EP::Glimpse::Config*, which
holds a single hash ref with the following keys:

install_html_files
     A TRUE (yes) value means, that the HTML examples will be copied to
     your web servers document root. This is recommended, unless you have
     an existing installation with own modifications in the HTML files.
     Of course you wouln't want to overwrite your own files.

html_base_dir
     Base directory, where you put your HTML files to. The default is
     `/home/httpd/html/Glimpse', which is fine on a Red Hat Linux box.

vardir
     A directory, where the web server is allowed to create files, in
     particular your preferences and the Glimpse index. By default the
     subdirectory `admin/var' of the base directory is choosen.

httpd_user
     The UID under which your web server is running CGI binaries. The
     vardir must have read, execute and write permissions for this user.
     The default is *nobody*, which is fine on a Red Hat Linux box again.

glimpse_path
glimpseindex_path
     Path of the *glimpse* and *glimpseindex* binaries.

The Preferences
---------------

   All other settings are fixed via the Web browser. Assuming your base
directory is accessible via

     http://localhost/Glimpse/

   point your browser to

     http://localhost/Glimpse/admin/index.ep

   and enter the preferences page. The following items must be entered
here:

Web servers root directory
     This is your web servers home directory, for example

          /home/httpd/html

     on a Red Hat Linux box.

Directories being indexed
     Usually you just put the value / here, because you want your whole
     web server being indexed. However, if you want restrict the index to
     some directories, enter them here. For example, if you have a manual
     in `/manual' and want to index the manual directory only, then enter

          /manual

     The directory names are relative to the servers root directory.

Directories being excluded
     If you don't want your whole directory tree being indexed, you can
     also exclude some directories. For example, there's not much sense in
     indexing the Glimpse directory, so I usually enter

          /Glimpse

     here.

Suffixes of files being indexed
     Of course you don't want all files being indexed. For example,
     there's not much sense in indexing GIF's or JPEG's. By default only
     files with the extensions *.htm* and *.html* are indexed. If you want
     your EP files being indexed as well, add a *.ep*. Likewise you might
     want to add *.php* for PHP3 files or *.txt* for text files.

Running glimpseindex
--------------------

   As soon as you modified your preferences, you should create an index.
This is done by returning to the admin menu and calling the index page.

   The same procedure should be repeated each time you modify your HTML
files. If this is happening frequently, you might prefer using a cron job,
for example

     su - nobody -c "/usr/bin/glimpseindex -b -H $vardir -X"

   with *$vardir* being the vardir from above. Note that your job shouln't
run as root, unless you want to disable a manual recreation via the web
browser.

Configuring for multiple virtual servers or multiple directories
----------------------------------------------------------------

   So far configuration is fine, but can you use multiple instances of
HTML::EP::Glimpse on one machine? Of course you can!

   It is quite simple: Just copy the base directory to another location.
Then create a subdirectory `admin/lib/HTML/EP/Glimpse' of the new base
directory. Create a new configuration by running

     cd $basedir/admin/lib/HTML/EP/Glimpse
     perl -MHTML::EP::Glimpse::Install -e Config Config.pm

   That's it!

AUTHOR AND COPYRIGHT
====================

   This module is

     Copyright (C) 1998-1999	Jochen Wiedmann
                           	Am Eisteich 9
                           	72555 Metzingen
                           	Germany

     Phone: +49 7123 14887
     Email: joe@ispsoft.de

   All rights reserved.

   You may distribute this module under the terms of either the GNU
General Public License or the Artistic License, as specified in the Perl
README file.

SEE ALSO
========

   `DBI(3)' in this node, `CGI(3)' in this node, `HTML::Parser(3)' in this
node

Session management for the HTML::EP package
*******************************************

NAME
====

     HTML::EP::Session - Session management for the HTML::EP package

SYNOPSIS
========

     <ep-comment>
       Create a new session or open an existing session
     </ep-comment>
     <ep-session id="$cgi->id$" var="cart">

     <ep-comment>
       Modify the session by putting an item into the shopping cart
     </ep-comment>
     <ep-perl>
       my $_ = $self; my $cart = $self->{'cart'};
       my $items = $cart->{'items'} || {};
       my $cgi = $self->{'cgi'};
       $items->{$cgi->param('item_id')} = $cgi->param('num_items');
     </ep-perl>

     <ep-comment>
       Same thing by using the ep-item command
     </ep-comment>
     <ep-session-item item="$cgi->item_id"
      num="$cgi->num_items">

     <ep-comment>
       Store the session
     </ep-comment>
     <ep-session-store>

DESCRIPTION
===========

   The HTML::EP::Session package is something like a little brother of
Apache::Session: Given an ID and a structured Perl variable called the
session, it stores the session into a DBI database, an external file or
whatever you prefer. For example you like to use this in shopping carts:
The shopping cart could look like this

     $session = {
       'id' => '21A32DE61A092DA1',
       'items' => { '10043-A' => 1, # 1 item of article '10043-A'
                    '10211-C' => 2  # 2 items of article '10211-C'
                  }
     }

   The package takes the session, converts it into a string representation
by using the Storable or *FreezeThaw* module and saves it into some
non-volatile storage space. The storage method is choosen by selecting an
appropriate subclass of HTML::EP::Session, for example
HTML::EP::Session::DBI, the default class using DBI, the database
independent Perl interface or HTML::EP::Session::File for using flat files.

Creating or opening a session
-----------------------------

     <ep-session class="HTML::EP::Session::DBI" table="sessions"
                 var=session id="$@cgi->id$" hex=0>

   If the attribute id is empty or not set, this will create a new and
empty session for you. Otherwise the existing session with the given id
will be opened.

   By default the session will have class *HTML::EP::Session::DBI* and
data will be stored in the table *sessions*, but you can choose another
subclass of *HTML::EP::Session* for saving data.  The session is stored in
the session variable of the object, but that is overridable with the var
attribute.

   Some storage systems don't support NUL bytes. The hex attribute forces
conversion of session strings into hex strings, if set to on.  The default
is off.

   Some session classes, in particular the DBI session class, will
generate an ID for you, if required. That ID can by retrieved by looking at

     $self->{'_ep_session_id'}

   or, within an HTML page with

     $_ep_session_id$

Storing the session
-------------------

     <ep-session-store locked=0>

   This stores the session back into the non-volatile storage. By default
the session is unlocked at the same time and must not be modified in what
follows, unless you set the optional locked attribute to a true value.

Managing a shopping cart
------------------------

   As a helper for shopping carts you might use the following command:

     <ep-session-item item="$cgi->item$" num="$cgi->num$">

   This command uses a hash ref items in the shopping cart, the hash will
be created automatically. The value num is stored in the hashs key item.
Alternatively you might use

     <ep-session-item item="$cgi->item$" add="$cgi->num$">

   which is very much the same, but the item is incremented by add.

Deleting a session
------------------

   You can delete an existing session with

     <ep-session-delete>

LOCKING CONSIDERATIONS
======================

   All subclasses have to implement a locking scheme. To keep this scheme
clean and simple, the following rules must be applied:

  1. First of all, acquire the resources that the respective subclass
     needs.  In the case of the DBI subclass this means that you have to
     execute the *ep-database* command.

  2. Next you create or open the session.

  3. If required, do any modifications and call *ep-session-store* or
     *ep-session-delete*.

  4. Once you have called *ep-session-store* or *ep-session-delete*, you
     most not use any more ep-session commands.

SUBCLASS INTERFACE
==================

   Subclasses of HTML::EP::Session must implement the following methods:

new($ep, $id, \%attr)
     (Class method) This constructor creates a new session with id $id.
     The constructor should configure itself by using the EP object *$ep*
     and the attribute hash ref \%attr.

Open($ep, $id, \%attr)
     (Class method) This constructor must open an existing session.

Store($ep, $id, $locked)
     (Instance method) Stores the session. The *$locked* argument advices
     to keep the session locked (TRUE) or unlocked (FALSE).

Delete($ep, $id)
   Error handling in subclasses is simple: All you need to do is throwing
a Perl exception. If subclasses need to maintain own data, they should
store it in $ep->{'_ep_session_data'}. The id is stored in
$ep->{'_ep_session_id'}.

The DBI subclass
----------------

   This class is using the DBI (Database independent Perl interface),
sessions are stored in a table. The table name is given by the table
attribute and defaults to *sessions*. The table structure is like

     CREATE TABLE SESSIONS (
         ID INTEGER NOT NULL PRIMARY KEY,
         SESSION LONGVARCHAR,
         ACCESSED TIMESTAMP,
         LOCKED INTEGER
     )

   in particular the SESSION column must be sufficiently large. I suggest
using something like up to 65535, for example I am using *SHORT BLOB* with
MySQL.

   The SESSION column must accept binary characters, in particular NUL
bytes.  If it doesn't, you need to replace the Storable package with
*FreezeThaw*.  `Storable(3)' in this node. `FreezeThaw(3)' in this node.

   Ilya Ketris (ilya@gde.to) has pointed out, that these column names are
causing problems from time to time. He suggested to use queries like

     INSERT INTO $table ("ID", "SESSION", ...

   instead. This is of course higly incompatible to other engines. To fix
that problem, I have added a subclass of *HTML::EP::Session::DBI*, called
*HTML::EP::Session::DBIq* (quoted). You use it by just replacing the class
name in the ep-session statement.

The Cookie subclass
-------------------

   This class is using Cookies, as introduced by Netscape 2. When using
Cookies for the session, you have to use a slightly different syntax:

     <ep-session class="HTML::EP::Session::Cookie" id="sessions"
                 var=session id="$@cgi->id$" expires="+1h"
                 domain="www.company.com" path="/"
                 zlib=0 base64=0>

   The attribute id is the cookie's name. (Cookies are name/value pairs.)
The optional attributes expires, domain and path are referring to the
respective attributes of CG::Cookie->new().  `CGI::Cookie(3)' in this node.

   Cookies are unfortunately restricted to a certain size, about 4096
bytes. If your session is getting too large, you might try to reduce the
cookie size by using the Compress::Zlib and/or MIME::Base64 module. This
is enabled by adding the parameters *zlib=1* and/or *base64=1*.

The Dumper subclass
-------------------

   This is, in some sense, an unusual class for sessions: All users are
sharing a single session, unlike the DBI and Cookie subclasses, which
implement one session per user. I enjoy using the Dumper subclass anyways,
for example to implement site wide preferences.

   What the class does is creating a file which holds a single hash ref.
This hash ref is created using the Data::Dumper package. `Data::Dumper(3)'
in this node.

   You create a Dumper session like this:

     <ep-session class="HTML::EP::Session::Dumper"
     	      id="/var/tmp/my.session" var="prefs">

   In other words, the session ID is just the name of the file.

MULTIPLE SESSION
================

   When looking at the Cookie and Dumper subclass, the question arises:
Can I use multiple sessions within a single HTML page? Of course you can!

   However, there are a few drawbacks:

  1. The variable $_ep_session_id$ always contains the ID of the last
     created session. After you have created the first session, it will
     contains this sessions ID. If you create another session, the
     variable will change to the new ID.

  2. You must use the attributes *var=something* and *id=something* with
     any call to *ep-session*, *ep-session-store*, *ep-session-delete* and
     *ep-session-item*.

AUTHOR AND COPYRIGHT
====================

   This module is

     Copyright (C) 1998    Jochen Wiedmann
                           Am Eisteich 9
                           72555 Metzingen
                           Germany

     Phone: +49 7123 14887
     Email: joe@ispsoft.de

   All rights reserved.

   You may distribute this module under the terms of either the GNU
General Public License or the Artistic License, as specified in the Perl
README file.

SEE ALSO
========

   `HTML::EP(3)' in this node, `Apache::Session(3)' in this node, `DBI(3)'
in this node, `Storable(3)' in this node, `FreezeThaw(3)' in this node,
`CGI::Cookie(3)' in this node

An E-Commerce solution, based on HTML::EP
*****************************************

NAME
====

     HTML::EP::Shop - An E-Commerce solution, based on HTML::EP

SYNOPSIS
========

DESCRIPTION
===========

AUTHOR AND COPYRIGHT
====================

   This module is

     Copyright (C) 1998    Jochen Wiedmann
                           Am Eisteich 9
                           72555 Metzingen
                           Germany

     Phone: +49 7123 14887
     Email: joe@ispsoft.de

   All rights reserved.

   You may distribute this module under the terms of either the GNU
General Public License or the Artistic License, as specified in the Perl
README file.

SEE ALSO
========

   `HTML::EP(3)' in this node, see HTML/EP/Session,
`HTML::EP::Locale' in this node

Make proper HTML 4 tags/lists/parts
***********************************

NAME
====

   HTML::EasyTags - Make proper HTML 4 tags/lists/parts

DEPENDENCIES
============

Perl Version
------------

     5.004

Standard Modules
----------------

     I<none>

Nonstandard Modules
-------------------

     Class::ParamParser 1.03

SYNOPSIS
========

     use HTML::EasyTags;

     my $html = HTML::EasyTags->new();
     $html->groups_by_default( 1 );

     print
     	$html->start_html(
     		-title => 'This Is My Page',
     		-head => $html->style( $html->comment_tag( <<__endquote ) ),
     \nBODY {
     	background-color: #ffffff;
     	background-image: none;
     }
     __endquote
     	),
     	$html->h1( 'A Simple Example' ),
     	$html->p(
     		"Click " .
     		$html->a( href => 'http://search.cpan.org', text => 'here' ) .
     		" for more."
     	),
     	$html->hr,
     	$html->table(
     		$html->tr( [
     			$html->th( [ 'Name', 'Count', 'URL', 'First Access' ] ),
     			$html->td( [ 'Old Page', 33, 'http://www.domain.com',
     				'1999/04/23 13:55:02' ] )
     		] )
     	),
     	$html->hr,
     	$html->form_start( method => 'post', action => 'http://localhost' ),
     	$html->p(
     		"What's your name? " .
     		$html->input( type => 'text', name => 'name' )
     	),
     	$html->p(
     		"What's the combination?" .
     		$html->input_group(
     			-type => 'checkbox',
     			-name => 'words',
     			-value => ['eenie', 'meenie', 'minie', 'moe'],
     			-checked => [1, 0, 1, 0],
     			-text => ['Eenie', 'Meenie', 'Minie', 'Moe'] ),
     	),
     	$html->p(
     		"What's your favorite colour? " .
     		$html->select_start( -size => 1, -name => 'color' ) .
     		$html->option_group(
     			-value => ['red', 'green', 'blue', 'chartreuse'],
     			-text => ['Red', 'Green', 'Blue', 'Chartreuse'] ) .
     		$html->select_end
     	),
     	$html->input( type => 'submit' ),
     	$html->form_end,
     	$html->end_html;

DESCRIPTION
===========

   This Perl 5 object class can be used to generate any HTML tags in a
format that is consistent with the W3C HTML 4.0 standard.  There are no
restrictions on what tags are named, however; you can ask for any new or
unsupported tag that comes along from Netscape or Microsoft, and it will
be made.  Additionally, you can generate lists of said tags with one
method call, or just parts of said tags (but not both at once).

   This module's purpose is to be lightweight, easy to use, and whose
results are syntactically correct and nicely formatted (should humans wish
to read or debug it).  At the same time, it is supportive of your existing
knowledge of HTML and as such its interface closely mirrors the actual
appearance of the resulting tags.  This means that methods have the same
name as the actual tags, and named parameters that you pass correspond
directly to  the tag attributes produced.  This module saves you having to
remember the little details on formatting.  For your convenience, a
majority of the methods and their arguments are backwards-compatible with
those in CGI.pm, but you are saved 200K of code size.

   As a reference, I strongly recommend that you check out *Kevin
Werbach's* excellent "The Bare Bones Guide to HTML", which is available at
*http://werbach.com/barebones/*. I found this document invaluable when
making this module, as it provides a comprehensive list of all the HTML
tags along with their formatting and extensions.

   In this implementation, "standard format" means that tags are made as
pairs (<TAG></TAG>) by default, unless they are known to be "no pair"
tags.  Tags that I know to be "no pair" are [basefont, img, area, param,
br, hr, input, option, tbody, frame, comment, isindex, base, link, meta].
However, you can force any tag to be "pair" or "start only" or "end only"
by appropriately modifying your call to the tag making method.

   Also, "standard format" means that tag modifiers are formatted as
"key=value" by default, unless they are known to be "no value" modifiers.
Modifiers that I know to be "no value" are [ismap, noshade, compact,
checked, multiple, selected, nowrap, noresize, param].  These are
formatted simply as "key" because their very presence indicates positive
assertion, while their absense means otherwise.  For modifiers with
values, the values will always become bounded by quotes, which ensures
they work with both string and numerical quantities (eg: key="value").

   Convenience methods start_html() and end_html() are provided to
generate the required HTML that appears above and below your content;
however, you can still make said HTML one tag at a time if you wish.

   Note that this class is a subclass of Class::ParamParser, and inherits
all of its methods, "params_to_hash()" and "params_to_array()".

HTML CODE FROM SYNOPSIS PROGRAM
===============================

     <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
     <HTML>
     <HEAD>
     <TITLE>This Is My Page</TITLE>
     <STYLE>
     <!--
     BODY {
     	background-color: #ffffff;
     	background-image: none;
     }
      --></STYLE>
     </HEAD>
     <BODY>
     <H1>A Simple Example</H1>
     <P>Click
     <A HREF="http://search.cpan.org">here</A> for more.</P>
     <HR>
     <TABLE>
     <TR>
     <TH>Name</TH>
     <TH>Count</TH>
     <TH>URL</TH>
     <TH>First Access</TH></TR>
     <TR>
     <TD>Old Page</TD>
     <TD>33</TD>
     <TD>http://www.domain.com</TD>
     <TD>1999/04/23 13:55:02</TD></TR></TABLE>
     <HR>
     <FORM METHOD="post" ACTION="http://localhost">
     <P>What's your name?
     <INPUT TYPE="text" NAME="name"></P>
     <P>What's the combination?
     <INPUT TYPE="checkbox" NAME="words" CHECKED VALUE="eenie">Eenie
     <INPUT TYPE="checkbox" NAME="words" VALUE="meenie">Meenie
     <INPUT TYPE="checkbox" NAME="words" CHECKED VALUE="minie">Minie
     <INPUT TYPE="checkbox" NAME="words" VALUE="moe">Moe</P>
     <P>What's your favorite colour?
     <SELECT NAME="color" SIZE="1">
     <OPTION VALUE="red">Red
     <OPTION VALUE="green">Green
     <OPTION VALUE="blue">Blue
     <OPTION VALUE="chartreuse">Chartreuse
     </SELECT></P>
     <INPUT TYPE="submit">
     </FORM>
     </BODY>
     </HTML>

SYNTAX
======

   This class does not export any functions or methods, so you need to
call them using object notation.  This means using *Class->function()* for
functions and *$object->method()* for methods.  If you are inheriting this
class for your own modules, then that often means something like
*$self->method()*.

   Methods of this class always "return" their results, rather than
printing them out to a file or the screen.  Not only is this simpler, but
it gives the calling code the maximum amount of control over what happens
in the program.  They may wish to do post-processing with the generated
HTML, or want to output it in a different order than it is generated.  By
default, all results are returned as a scalar, but methods which generate
a list of tags can optionally return an ARRAY ref, with each element
containing a single tag.  This can aid in post-processing and possibly
speed up the program because there is less copying done.

   Through the magic of autoloading, this class can make any html tag by
calling a class method with the same name as the tag you want.  For
examples, use "hr()" to make a "<HR>" tag, or "p('text')" to make
"<P>text</P>".  This also means that if you mis-spell any method name, it
will still make a new tag with the mis-spelled name.  For autoloaded
methods only, the method names are case-insensitive.

   If you call a class method whose name ends in either of ['_start',
'_end', '_pair'], this will be interpreted as an instruction to make just
part of one tag whose name are the part of the method name preceeding that
suffix.  For example, calling "p_start( 'text' )" results in "<P>text"
rather than "<P>text</P>".  Similarly, calling "p_end()" will generate a
"</P>" only.  Using the '_pair' suffix will force tags to be made as a
pair, whether or not they would do so naturally.  For example, calling
"br_pair" would produce a "<BR></BR>" rather than the normal "<BR>".  When
using either of ['_start','_pair'], the arguments you pass the method are
exactly the same as the unmodified method would use, and there are no
other symantec differences.  However, when using the '_end' suffix, any
arguments are ignored, as the latter member of a tag pair never carries any
attributes anyway.

   If you call a class method whose name ends in "_group", this will be
interpreted as an instruction to make a list of tags whose name are the
part of the method name preceeding the "_group".  For example, calling
"td_group( ['here','we','are'] )" results in
"<TD>here</TD><TD>we</TD><TD>are</TD>" being generated.  The arguments
that you call this method are exactly the same as for calling a method to
make a single tag of the same name, except that the extra optional
parameter "list" can be used to force an ARRAY ref of the new tags to be
returned instead of a scalar.  The symantec difference is that any
arguments whose values are ARRAY refs are interpreted as a list of values
where each one is used in a separate tag; for a single tag, the literal
ARRAY ref itself would be used.  The number of tags produced is equal to
the length of the longest ARRAY ref passed as an argument.  For any other
arguments who have fewer than this count, their last value is replicated
and appended enough times as necessary to make them the same length.  The
value of a scalar argument is used for all the tags.  For example, calling
"input_group( type => checkbox, name => 'letters', value => ['a','b','c']
)" produces '<INPUT TYPE="checkbox" NAME="letters" VALUE="a"><INPUT
TYPE="checkbox" NAME="letters" VALUE="b"><INPUT TYPE="checkbox"
NAME="letters" VALUE="c">'.

   All autoloaded methods require their parameters to be in named format.
These names and values correspond to attribute names and values for the
new tags.  Since "no value" attributes are essentially booleans, they can
have any true or false value associated with them in the parameter list,
which won't be printed.  If an autoloaded method is passed exactly one
parameter, it will be interpreted as the "text" that goes between the tag
pair (<TAG>text</TAG>) or after "start tags" (<TAG>text).  The same result
can be had explicitely by passing the named parameter "text".  The names
of any named parameters can upper or lower or mixed case, as is your
preference, and optionally start with a "-".

   All static (non-autoloaded) methods require positional parameters.

FUNCTIONS AND METHODS
=====================

   Note that all the methods defined below are static, so information
specific to autoloaded methods won't likely apply to them.  All of these
methods take positional arguments.

new()
-----

   This function creates a new HTML::EasyTags object (or subclass thereof)
and returns it.

initialize()
------------

   This method is used by new() to set the initial properties of an object,
that it creates.  All page attributes are wiped clean, resulting in an
empty page.

clone([ CLONE ])
----------------

   This method initializes a new object to have all of the same properties
of the current object and returns it.  This new object can be provided in
the optional argument CLONE (if CLONE is an object of the same class as
the current object); otherwise, a brand new object of the current class is
used.  Only object properties recognized by HTML::EasyTags are set in the
clone; other properties are not changed.

groups_by_default([ VALUE ])
----------------------------

   This method is an accessor for the boolean "automatic grouping"
property of this object, which it returns.  If VALUE is defined, this
property is set to it.  In cases where we aren't told explicitely that
autoloaded methods are making a single or multiple tags (using ['_start',
'_end', '_pair'] and '_group' respectively), we look to this property to
determine what operation we guess.  The default is "single".  When this
property is true, we can make both single and groups of tags by using a
suffix-less method name; however, making single tags this way is slower
than when this property is false.  Also, be aware that when we are making
a "group", arguments that are ARRAY refs are always flattened, and when we
are making a "single", ARRAY ref arguments are always used literally.

prologue_tag()
--------------

   This method returns a prologue tag, which is meant to be the very first
thing in an HTML document.  It tells the web browser such things as what
version of the HTML standard we are adhering to, version 4.0 in this case.
The prologue tag we make looks like '<!DOCTYPE HTML PUBLIC "-//W3C//DTD
HTML 4.0//EN">'.

comment_tag( TEXT )
-------------------

   This method returns a comment tag, which is only visible to people
viewing the HTML source of a document, and not otherwise.  It can take
either a scalar or a list or an Array ref as its TEXT argument.  If a
single item of text is passed, then a comment tag that looks like "<!-
text ->" is made.  If more than one item of text is passed, then a
multi-line comment is made, which has each item of text on its own line
and indented with a single tab.  The latter is suitable for displaying CSS
or JavaScript code in an elegant manner.

make_html_tag( NAME[, PARAMS[, TEXT[, PART]]] )
-----------------------------------------------

   This method is used internally to do the actual construction of single
html tags.   You can call it directly when you want faster code and/or
more control over how tags are made.  The first argument, NAME, is a
scalar that defines the actual name of the tag we are making (eg: 'br');
it is case-insensitive.  The optional second argument, PARAMS, is a HASH
ref containing attribute names and values for the new tag; the names
(keys) are case-insensitive.  The attribute values are all printed
literally, so they should be scalars.  The optional third argument, TEXT,
is a scalar containing the text that goes between the tag pairs; it is not
a tag attribute.  The optional fourth argument, PART, is a scalar which
indicates we should make just a certain part of the tag; acceptable values
are ['pair', 'start', 'end'], and it is case-insensitive.  This method
knows which HTML tags are normally paired or not, which tag attributes
take specified values or not, and acts accordingly.

make_html_tag_group( NAME[, PARAMS[, TEXT[, LIST]]] )
-----------------------------------------------------

   This method is used internally to do the actual construction of html
tag groups.  You can call it directly when you want faster code and/or
more control over how tags are made.  The first argument, NAME, is a
scalar that defines the actual name of the tag we are making (eg: 'br');
it is case-insensitive.  The optional second argument, PARAMS, is a HASH
ref containing attribute names and values for the new tag; the names
(keys) are case-insensitive.  Any attribute values which are ARRAY refs
are flattened, and the number of tags made is determined by the length of
the longest one.  The optional third argument, TEXT, is a HASH ref (or
scalar) containing the text that goes between the tag pairs; it is not a
tag attribute, but if its an ARRAY ref then its length will influence the
number of tags that are made as the length of tag attribute arrays do.
The optional fourth argument, LIST, is a boolean/scalar which indicates
whether this method returns the new tags in an ARRAY ref (one tag per
element) or as a scalar (tags are concatenated together); a true value
forces an ARRAY ref, scalar is the default.  This method knows which HTML
tags are normally paired or not, which tag attributes take specified
values or not, and acts accordingly.

start_html([ TITLE[, HEAD[, BODY]] ])
-------------------------------------

   This method returns a canned HTML template that is suitable for use as
the top of an HTML page.  It consists of the prologue tag (<!DOCTYPE...),
the opening 'html' tag, the entire 'head' section, and the opening 'body'
tag.  The prologue tag looks the same as that generated by the class
method prologue_tag().  The first optional argument, TITLE, is a scalar
which defines the title for the document, and its default value is
'Untitled Document'.  The second argument, HEAD, is an ARRAY ref (or
scalar) containing anything else you would like to appear in the 'head'
section; it is flattened and the elements used as-is.  The third argument,
BODY, is a HASH ref containing attributes and values for the opening
'body' tag.

end_html()
----------

   This method returns a canned HTML template that is suitable for use as
the bottom of an HTML page.  It consists of the closing 'body' and 'html'
tags.

COMPARISONS WITH CGI.PM
=======================

   The methods of this class and their parameters are designed to be
compatible with any same-named methods in the popular CGI.pm class. This
class will produce browser-compatible (and often identical) HTML from such
methods, and this class can accept all the same argument formats.
Exceptions to this include:

  1. None of our methods are exported and must be called using object
     notation, whereas CGI.pm can export any of it's methods.

  2. Autoloaded methods do not use the presence or absence of arguments to
     decide whether to make the new tag as a pair or as "start only".
     Also, CGI.pm does not do end-only tags.

  3. Autoloaded methods that make html tags won't concatenate their
     arguments into a single argument under any circumstances, but in some
     cases the "shortcuts" of CGI.pm will do so.

  4. Currently we don't html-escape any argument values passed to our tag
     making functions, whereas CGI.pm sometimes does.  While we expect our
     caller to do the escaping themselves where necessary, perhaps using a
     CPAN module especially designed for HTML escaping, we may do it later
     in an update.

  5. We go further to make the generated HTML human-readable by: 1. having
     each new tag start on a new line; 2. making all tag and attribute
     names uppercase; 3.  ensuring that about 20 often-used tag attributes
     always appear in the same order (eg: 'type' is before 'name' is
     before 'value'), and before any others.

  6. Our textarea() method is autoloaded, and doesn't have the special
     symantecs that CGI.pm's textarea() does.

  7. Our convenience method start_html() is very simple and only accepts
     the three positional arguments ['title', 'head', 'body'].  Title is
     the most commonly used argument by far, and you can easily replicate
     the effects of missing arguments by making appropriate tags
     explicitely and passing them with the "head" argument.

AUTHOR
======

   Copyright (c) 1999-2001, Darren R. Duncan. All rights reserved. This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.  However, I do request that this copyright
information remain attached to the file.  If you modify this module and
redistribute a changed version then please attach a note listing the
modifications.

   I am always interested in knowing how my work helps others, so if you
put this module to use in any of your own code then please send me the
URL.  Also, if you make modifications to the module because it doesn't
work the way you need, please send me a copy so that I can roll desirable
changes into the main release.

   Address comments, suggestions, and bug reports to
*perl@DarrenDuncan.net*.

CREDITS
=======

   Thanks very much to *Kevin Werbach* for publishing "The Bare Bones
Guide to HTML", which I found to be an invaluable resource when writing
this module (and at other times as well).  The latest version of the
document is available at *http://werbach.com/barebones/*.

   This quick reference lists all the HTML tags that current browsers are
likely to recognize, including all the elements of the official HTML 4.0
recommendation, and some Netscape and Microsoft extensions as well.
Common attributes for these tags are also included in context, giving a
good idea on how they are used.

   When writing this module, I used the Bare Bones reference to verify the
consistant formatting used by all HTML tags, including how tag attributes
are formatted.  I could see the proper formatting for prologue and comment
tags as well; their formats are unique compared to all the other tags.
The other main uses I had for the document was in determining all the HTML
tags which were not used as a pair (most use pairs, few don't), and for
determining which tag attributes made a positive assertion just by their
presence, without need for any associated values (most have values, few
don't).

   Thanks to *Lincoln D. Stein* for setting a good interface standard in
the HTML-related methods of his CGI.pm module.  I was heavily influenced
by his interfaces when designing my own.  Thanks also because I borrowed
ideas for my Synopsis program from his aforementioned module.

SEE ALSO
========

   perl(1), Class::ParamParser, HTML::FormTemplate, CGI.

Class for objects that represent HTML elements
**********************************************

NAME
====

   HTML::Element - Class for objects that represent HTML elements

SYNOPSIS
========

     use HTML::Element;
     $a = HTML::Element->new('a', href => 'http://www.perl.com/');
     $a->push_content("The Perl Homepage");

     $tag = $a->tag;
     print "$tag starts out as:",  $a->starttag, "\n";
     print "$tag ends as:",  $a->endtag, "\n";
     print "$tag\'s href attribute is: ", $a->attr('href'), "\n";

     $links_r = $a->extract_links();
     print "Hey, I found ", scalar(@$links_r), " links.\n";

     print "And that, as HTML, is: ", $a->as_HTML, "\n";
     $a = $a->delete;

DESCRIPTION
===========

   Objects of the HTML::Element class can be used to represent elements of
HTML document trees.  These objects have attributes, notably attributes
that designates each element's parent and content.  The content is an array
of text segments and other HTML::Element objects.  A tree with
HTML::Element objects as nodes can represent the syntax tree for a HTML
document.

HOW WE REPRESENT TREES
======================

   It may occur to you to wonder what exactly a "tree" is, and how it's
represented in memory.  Consider this HTML document:

     <html lang='en-US'>
       <head>
         <title>Stuff</title>
         <meta name='author' content='Jojo'>
       </head>
       <body>
        <h1>I like potatoes!</h1>
       </body>
     </html>

   Building a syntax tree out of it makes a tree-structure in memory that
could be diagrammed as:

     html (lang='en-US')
      / \
                         /     \
                       /         \
                     head        body
                    /\               \
                  /    \               \
                /        \               \
              title     meta              h1
               |       (name='author',     |
            "Stuff"    content='Jojo')    "I like potatoes"

   This is the traditional way to diagram a tree, with the "root" at the
top, and it's this kind of diagram that people have in mind when they say,
for example, that "the meta element is under the head element instead of
under the body element".  (The same is also said with "inside" instead of
"under" - the use of "inside" makes more sense when you're looking at the
HTML source.)

   Another way to represent the above tree is with indenting:

     html (attributes: lang='en-US')
       head
         title
           "Stuff"
         meta (attributes: name='author' content='Jojo')
       body
         h1
           "I like potatoes"

   Incidentally, diagramming with indenting works much better for very
large trees, and is easier for a program to generate.  The $tree->dump
method uses indentation just that way.

   However you diagram the tree, it's stored the same in memory - it's a
network of objects, each of which has attributes like so:

     element #1:  _tag: 'html'
                  _parent: none
                  _content: [element #2, element #5]
                  lang: 'en-US'

     element #2:  _tag: 'head'
                  _parent: element #1
                  _content: [element #3, element #4]

     element #3:  _tag: 'title'
                  _parent: element #2
                  _content: [text segment "Stuff"]

     element #4   _tag: 'meta'
                  _parent: element #2
                  _content: none
                  name: author
                  content: Jojo

     element #5   _tag: 'body'
                  _parent: element #1
                  _content: [element #6]

     element #6   _tag: 'h1'
                  _parent: element #5
                  _content: [text segment "I like potatoes"]

   The "treeness" of the tree-structure that these elements comprise is
not an aspect of any particular object, but is emergent from the
relatedness attributes (_parent and _content) of these element-objects and
from how you use them to get from element to element.

   While you could access the content of a tree by writing code that says
"access the 'src' attribute of the root's first child's *seventh* child's
*third* child", you're more likely to have to scan the contents of a tree,
looking for whatever nodes, or kinds of nodes, you want to do something
with.  The most straightforward way to look over a tree is to "traverse"
it; an HTML::Element method ($h->traverse) is provided for this purpose;
and several other HTML::Element methods are based on it.

   (For everything you ever wanted to know about trees, and then some, see
Niklaus Wirth's *Algorithms + Data Structures = Programs* or Donald
Knuth's *The Art of Computer Programming, Volume 1*.)

BASIC METHODS
=============

$h = HTML::Element->new('tag', 'attrname' => 'value', ... )
     This constructor method returns a new HTML::Element object.  The tag
     name is a required argument; it will be forced to lowercase.
     Optionally, you can specify other initial attributes at object
     creation time.

$h->attr('attr') or $h->attr('attr', 'value')
     Returns (optionally sets) the value of the given attribute of $h.  The
     attribute name (but not the value, if provided) is forced to
     lowercase.  If trying to read the value of an attribute not present
     for this element, the return value is undef.  If setting a new value,
     the old value of that attribute is returned.

     If methods are provided for accessing an attribute (like $h->tag for
     "_tag", $h->content_list, etc. below), use those instead of calling
     attr $h->attr, whether for reading or setting.

     Note that setting an attribute to undef (as opposed to "", the empty
     string) actually deletes the attribute.

$h->tag() or $h->tag('tagname')
     Returns (optionally sets) the tag name (also known as the generic
     identifier) for the element $h.  In setting, the tag name is always
     converted to lower case.

     There are four kinds of "pseudo-elements" that show up as
     HTML::Element objects:

    Comment pseudo-elements
          These are element objects with a `$h->tag' value of "~comment",
          and the content of the comment is stored in the "text" attribute
          (`$h->attr("text")').  For example, parsing this code with
          HTML::TreeBuilder...

               <!-- I like Pie.
                  Pie is good
               -->

          produces an HTML::Element object with these attributes:

               "_tag",
               "~comment",
               "text",
               " I like Pie.\n     Pie is good\n  "

    Declaration pseudo-elements
          Declarations (rarely encountered) are represented as
          HTML::Element objects with a tag name of "~declaration", and
          content in the "text" attribute.  For example, this:

               <!DOCTYPE foo>

          produces an element whose attributes include:

               "_tag", "~declaration", "text", "DOCTYPE foo"

    Processing instruction pseudo-elements
          PIs (rarely encountered) are represented as HTML::Element
          objects with a tag name of "~pi", and content in the "text"
          attribute.  For example, this:

               <?stuff foo?>

          produces an element whose attributes include:

               "_tag", "~pi", "text", "stuff foo?"

          (assuming a recent version of HTML::Parser)

    ~literal pseudo-elements
          These objects are not currently produced by HTML::TreeBuilder,
          but can be used to represent a "super-literal" - i.e., a literal
          you want to be immune from escaping.  (Yes, I just made that
          term up.)

          That is, this is useful if you want to insert code into a tree
          that you plan to dump out with `as_HTML', where you want, for
          some reason, to suppress `as_HTML''s normal behavior of
          amp-quoting text segments.

          For expample, this:

               my $literal = HTML::Element->new('~literal',
                 'text' => 'x < 4 & y > 7'
               );
               my $span = HTML::Element->new('span');
               $span->push_content($literal);
               print $span->as_HTML;

          prints this:

               <span>x < 4 & y > 7</span>

          Whereas this:

               my $span = HTML::Element->new('span');
               $span->push_content('x < 4 & y > 7');
                 # normal text segment
               print $span->as_HTML;

          prints this:

               <span>x &lt; 4 &amp; y &gt; 7</span>

          Unless you're inserting lots of pre-cooked code into existing
          trees, and dumping them out again, it's not likely that you'll
          find ~literal pseudo-elements useful.

$h->parent() or $h->parent($new_parent)
     Returns (optionally sets) the parent for this element.  The parent
     should either be undef, or should be another element.

     You *should not* use this to directly set the parent of an element.
     Instead use any of the other methods under "Structure-Modifying
     Methods", below.

     Note that not($h->parent) is a simple test for whether $h is the root
     of its subtree.

$h->content_list()
     Returns a list representing the content of this element - i.e., what
     nodes (elements or text segments) are inside/under this element. (Note
     that this may be an empty list.)

     In a scalar context, this returns the count of the items, as you may
     expect.

$h->content()
     This somewhat deprecated method returns the content of this element;
     but unlike content_list, this returns either undef (which you should
     understand to mean no content), or a *reference to the array* of
     content items, each of which is either a text segment (a string, i.e.,
     a defined non-reference scalar value), or an HTML::Element object.
     Note that even if an arrayref is returned, it may be a reference to an
     empty array.

     While older code should feel free to continue to use $h->content, new
     code should use $h->content_list in almost all conceivable cases.  It
     is my experience that in most cases this leads to simpler code
     anyway, since it means one can say:

          @children = $h->content_list;

     instead of the inelegant:

          @children = @{$h->content || []};

     If you do use $h->content (or $h->content_array_ref), you should not
     use the reference returned by it (assuming it returned a reference,
     and not undef) to directly set or change the content of an element or
     text segment!  Instead use `content_refs_list' or any of the other
     methods under "Structure-Modifying Methods", below.

$h->content_array_ref()
     This is like content (with all its caveats and deprecations) except
     that it is guaranteed to return an array reference.  That is, if the
     given node has no `_content' attribute, the content method would
     return that undef, but `content_array_ref' would set the given node's
     `_content' value to [] (a reference to a new, empty array), and
     return that.

$h->content_refs_list
     This returns a list of scalar references to each element of $h's
     content list.  This is useful in case you want to in-place edit any
     large text segments without having to get a copy of the current value
     of that segment value, modify that copy, then use the
     `splice_content' to replace the old with the new.  Instead, here you
     can in-place edit:

          foreach my $item_r ($h->content_refs_list) {
            next if ref $$item_r;
            $$item_r =~ s/honour/honor/g;
          }

     You *could* currently achieve the same affect with:

          foreach my $item (@{ $h->content_array_ref }) {
           # deprecated!
            next if ref $item;
            $item =~ s/honour/honor/g;
          }

     ...except that using the return value of $h->content or
     $h->content_array_ref to do that is deprecated, and just might stop
     working in the future.

$h->implicit() or $h->implicit($bool)
     Returns (optionally sets) the "_implicit" attribute.  This attribute
     is a flag that's used for indicating that the element was not
     originally present in the source, but was added to the parse tree (by
     HTML::TreeBuilder, for example) in order to conform to the rules of
     HTML structure.

$h->pos() or $h->pos($element)
     Returns (and optionally sets) the "_pos" (for "current position")
     pointer of $h.  This attribute is a pointer used during some parsing
     operations, whose value is whatever HTML::Element element at or under
     $h is currently "open", where $h->insert_element(NEW) will actually
     insert a new element.

     (This has nothing to do with the Perl function called "pos", for
     controlling where regular expression matching starts.)

     If you set $h->pos($element), be sure that $element is either $h, or
     an element under $h.

     If you've been modifying the tree under $h and are no longer sure
     $h->pos is valid, you can enforce validity with:

          $h->pos(undef) unless $h->pos->is_inside($h);

$h->all_attr()
     Returns all this element's attributes and values, as key-value pairs.
     This will include any "internal" attributes (i.e., ones not present
     in the original element, and which will not be represented if/when you
     call $h->as_HTML).  Internal attributes are distinguished by the fact
     that the first character of their key (not value! key!) is an
     underscore ("_").

     Example output of `$h->all_attr()' : `'_parent', '*[object_value]*` ,
     '_tag', 'em', 'lang', 'en-US', '_content', '*[array-ref value]*.

$h->all_attr_names()
     Like all_attr, but only returns the names of the attributes.

     Example output of `$h->all_attr()' : `'_parent', '_tag', 'lang',
     '_content', '.

$h->all_external_attr()
     Like `all_attr', except that internal attributes are not present.

$h->all_external_attr_names()
     Like `all_external_attr_names', except that internal attributes' names
     are not present.

$h->id() or $h->id($string)
     Returns (optionally sets to $string) the "id" attribute.
     `$h->id(undef)' deletes the "id" attribute.

$h->idf() or $h->idf($string)
     Just like the id method, except that if you call `$h-'idf()> and no
     "id" attribute is defined for this element, then it's set to a
     likely-to-be-unique value, and returned.  (The "f" is for "force".)

STRUCTURE-MODIFYING METHODS
===========================

   These methods are provided for modifying the content of trees by adding
or changing nodes as parents or children of other nodes.

$h->push_content($element_or_text, ...)
     Adds the specified items to the end of the content list of the
     element $h.  The items of content to be added should each be either a
     text segment (a string), an HTML::Element object, or an arrayref.
     Arrayrefs are fed thru `$h-E<gh'new_from_lol(that_arrayref)> to
     convert them into elements, before being added to the content list of
     $h.  This means you can say things concise things like:

          $body->push_content(
            ['br'],
            ['ul',
              map ['li', $_]
              qw(Peaches Apples Pears Mangos)
            ]
          );

     See `new_from_lol' method's documentation, far below, for more
     explanation.

     The push_content method will try to consolidate adjacent text segments
     while adding to the content list.  That's to say, if $h's
     content_list is

          ('foo bar ', $some_node, 'baz!')

     and you call

          $h->push_content('quack?');

     then the resulting content list will be this:

          ('foo bar ', $some_node, 'baz!quack?')

     and not this:

          ('foo bar ', $some_node, 'baz!', 'quack?')

     If that latter is what you want, you'll have to override the feature
     of consolidating text by using splice_content, as in:

          $h->splice_content(scalar($h->content_list),0,'quack?');

     Similarly, if you wanted to add 'Skronk' to the beginning of the
     content list, calling this:

          $h->unshift_content('Skronk');

     then the resulting content list will be this:

          ('Skronkfoo bar ', $some_node, 'baz!')

     and not this:

          ('Skronk', 'foo bar ', $some_node, 'baz!')

     What you'd to do get the latter is:

          $h->splice_content(0,0,'Skronk');

$h->unshift_content($element_or_text, ...)
     Just like `push_content', but adds to the *beginning* of the $h
     element's content list.

     The items of content to be added should each be either a text segment
     (a string), an HTML::Element object, or an arrayref (which is fed
     thru `new_from_lol').

     The unshift_content method will try to consolidate adjacent text
     segments while adding to the content list.  See above for a
     discussion of this.

$h->splice_content($offset, $length, $element_or_text, ...)
     Detaches the elements from $h's list of content-nodes, starting at
     $offset and continuing for $length items, replacing them with the
     elements of the following list, if any.  Returns the elements (if any)
     removed from the content-list.  If $offset is negative, then it starts
     that far from the end of the array, just like Perl's normal splice
     function.  If $length and the following list is omitted, removes
     everything from $offset onward.

     The items of content to be added (if any) should each be either a text
     segment (a string), an arrayref (which is fed thru `new_from_lol'),
     or an HTML::Element object that's not already a child of $h.

$h->detach()
     This unlinks $h from its parent, by setting its 'parent' attribute to
     undef, and by removing it from the content list of its parent (if it
     had one).  The return value is the parent that was detached from (or
     undef, if $h had no parent to start with).  Note that neither $h nor
     its parent are explicitly destroyed.

$h->detach_content()
     This unlinks $h all of $h's children from $h, and returns them.  Note
     that these are not explicitly destroyed; for that, you can just use
     $h->delete_content.

$h->replace_with( $element_or_text, ... )
     This replaces $h in its parent's content list with the nodes
     specified.  The element $h (which by then may have no parent) is
     returned.  This causes a fatal error if $h has no parent.  The list
     of nodes to insert may contain $h, but at most once.  Aside from that
     possible exception, the nodes to insert should not already be
     children of $h's parent.

     Also, note that this method does not destroy $h - use
     $h->replace_with(...)->delete if you need that.

$h->preinsert($element_or_text...)
     Inserts the given nodes right BEFORE $h in $h's parent's content list.
     This causes a fatal error if $h has no parent.  None of the given
     nodes should be $h or other children of $h.  Returns $h.

$h->postinsert($element_or_text...)
     Inserts the given nodes right AFTER $h in $h's parent's content list.
     This causes a fatal error if $h has no parent.  None of the given
     nodes should be $h or other children of $h.  Returns $h.

$h->replace_with_content()
     This replaces $h in its parent's content list with its own content.
     The element $h (which by then has no parent or content of its own) is
     returned.  This causes a fatal error if $h has no parent.  Also, note
     that this does not destroy $h - use $h->replace_with_content->delete
     if you need that.

$h->delete_content()
     Clears the content of $h, calling $i->delete for each content element.
     Compare with $h->detach_content.

     Returns $h.

$h->delete()
     Detaches this element from its parent (if it has one) and explicitly
     destroys the element and all its descendants.  The return value is
     undef.

     Perl uses garbage collection based on reference counting; when no
     references to a data structure exist, it's implicitly destroyed -
     i.e., when no value anywhere points to a given object anymore, Perl
     knows it can free up the memory that the now-unused object occupies.

     But this fails with HTML::Element trees, because a parent element
     always holds references to its children, and its children elements
     hold references to the parent, so no element ever looks like it's not
     in use.  So, to destroy those elements, you need to call $h->delete
     on the parent.

$h->clone()
     Returns a copy of the element (whose children are clones (recursively)
     of the original's children, if any).

     The returned element is parentless.  Any '_pos' attributes present in
     the source element/tree will be absent in the copy.  For that and
     other reasons, the clone of an HTML::TreeBuilder object that's in
     mid-parse (i.e, the head of a tree that HTML::TreeBuilder is
     elaborating) cannot (currently) be used to continue the parse.

     You are free to clone HTML::TreeBuilder trees, just as long as: 1)
     they're done being parsed, or 2) you don't expect to resume parsing
     into the clone.  (You can continue parsing into the original; it is
     never affected.)

HTML::Element->clone_list(...nodes...)
or: ref($h)->clone_list(...nodes...)
     Returns a list consisting of a copy of each node given.  Text
     segments are simply copied; elements are cloned by calling $it->clone
     on each of them.

$h->normalize_content
     Normalizes the content of $h - i.e., concatenates any adjacent text
     nodes.  (Any undefined text segments are turned into empty-strings.)
     Note that this does not recurse into $h's descendants.

$h->delete_ignorable_whitespace()
     This traverses under $h and deletes any text segments that are
     ignorable whitespace.  You should not use this if $h under a 'pre'
     element.

$h->insert_element($element, $implicit)
     Inserts (via push_content) a new element under the element at
     $h->pos().  Then updates $h->pos() to point to the inserted element,
     unless $element is a prototypically empty element like "br", "hr",
     "img", etc.  The new $h->pos() is returned.  This method is useful
     only if your particular tree task involves setting $h->pos.

DUMPING METHODS
===============

$h->dump()

; # or *FH{IO} or $fh_obj
     Prints the element and all its children to STDOUT (or to a specified
     filehandle), in a format useful only for debugging.  The structure of
     the document is shown by indentation (no end tags).

$h->as_HTML() or $h->as_HTML($entities)
or $h->as_HTML($entities, $indent_char)
or $h->as_HTML($entities, $indent_char, \%optional_end_tags)
     Returns a string representing in HTML the element and its
     descendants.  The optional argument `$entities' specifies a string of
     the entities to encode.  For compatibility with previous versions,
     specify `'<>&'' here.  If omitted or undef, all unsafe characters are
     encoded as HTML entities.  See HTML/Entities, for
     details.

     If $indent_char is specified and defined, the HTML to be output is
     intented, using the string you specify (which you probably should set
     to "\t", or some number of spaces, if you specify it).  This feature
     is currently somewhat experimental.  But try it, and feel free to
     email me any bug reports.  (Note that output, although indented, is
     not wrapped.  Patches welcome.)

     If `\%optional_end_tags' is specified and defined, it should be a
     reference to a hash that holds a true value for every tag name whose
     end tag is optional.  Defaults to `\%HTML::Element::optionalEndTag',
     which is an alias to `%HTML::Tagset::optionalEndTag', which, at time
     of writing, contains true values for `p, li, dt, dd'.  A useful value
     to pass is an empty hashref, `{}', which means that no end-tags are
     optional for this dump.  Otherwise, possibly consider copying
     `%HTML::Tagset::optionalEndTag' to a hash of your own, adding or
     deleting values as you like, and passing a reference to that hash.

$h->as_text()
$h->as_text(skip_dels => 1)
     Returns a string consisting of only the text parts of the element's
     descendants.

     Text under 'script' or 'style' elements is never included in what's
     returned.  If `skip_dels' is true, then text content under "del"
     nodes is not included in what's returned.

$h->as_XML() or $h->as_XML($entities)
     Returns a string representing in XML the element and its descendants.
     The optional argument `$entities' specifies a string of the entities
     to encode.  If omitted or undef, all unsafe characters are encoded as
     HTML (!) entities.  See HTML/Entities, for
     details.

     This method is experimental.  If you use this method, tell me what you
     use it for, and if you run into any problems.

     The XML is not indented.

$h->as_Lisp_form()
     Returns a string representing the element and its descendants as a
     Lisp form.  Unsafe characters are encoded as octal escapes.

     The Lisp form is indented, and contains external ("href", etc.)  as
     well as internal attributes ("_tag", "_content", "_implicit", etc.),
     except for "_parent", which is omitted.

     Current example output for a given element:

          ("_tag" "img" "border" "0" "src" "pie.png" "usemap" "#main.map")

     This method is experimental.  If you use this method, tell me what you
     use it for, and if you run into any problems.

$h->starttag() or $h->starttag($entities)
     Returns a string representing the complete start tag for the element.
     I.e., leading "<", tag name, attributes, and trailing ">".  Attributes
     values that don't consist entirely of digits are surrounded with
     double-quotes, and appropriate characters are encoded.  If `$entities'
     is omitted or undef, all unsafe characters are encoded as HTML
     entities.  See HTML/Entities, for details.  If
     you specify some value for `$entities', remember to include the
     double-quote character in it.  (Previous versions of this module
     would basically behave as if `'&">'' were specified for `$entities'.)

$h->endtag()
     Returns a string representing the complete end tag for this element.
     I.e., "</", tag name, and ">".

SECONDARY STRUCTURAL METHODS
============================

   These methods all involve some structural aspect of the tree; either
they report some aspect of the tree's structure, or they involve traversal
down the tree, or walking up the tree.

$h->is_inside('tag', ...) or $h->is_inside($element, ...)
     Returns true if the $h element is, or is contained anywhere inside an
     element that is any of the ones listed, or whose tag name is any of
     the tag names listed.

$h->is_empty()
     Returns true if $h has no content, i.e., has no elements or text
     segments under it.  In other words, this returns true if $h is a leaf
     node, AKA a terminal node.  Do not confuse this sense of "empty" with
     another sense that it can have in SGML/HTML/XML terminology, which
     means that the element in question is of the type (like HTML's "hr",
     "br", "img", etc.) that *can't* have any content.

     That is, a particular "p" element may happen to have no content, so
     $that_p_element->is_empty will be true - even though the prototypical
     "p" element isn't "empty" (not in the way that the prototypical "hr"
     element is).

     If you think this might make for potentially confusing code, consider
     simply using the clearer exact equivalent:  not($h->content_list)

$h->pindex()
     Return the index of the element in its parent's contents array, such
     that $h would equal

          $h->parent->content->[$h->pindex]
          or
          ($h->parent->content_list)[$h->pindex]

     assuming $h isn't root.  If the element $h is root, then $h->pindex
     returns undef.

$h->left()
     In scalar context: returns the node that's the immediate left sibling
     of $h.  If $h is the leftmost (or only) child of its parent (or has no
     parent), then this returns undef.

     In list context: returns all the nodes that're the left siblings of $h
     (starting with the leftmost).  If $h is the leftmost (or only) child
     of its parent (or has no parent), then this returns empty-list.

     (See also $h->preinsert(LIST).)

$h->right()
     In scalar context: returns the node that's the immediate right sibling
     of $h.  If $h is the rightmost (or only) child of its parent (or has
     no parent), then this returns undef.

     In list context: returns all the nodes that're the right siblings of
     $h, strting with the leftmost.  If $h is the rightmost (or only) child
     of its parent (or has no parent), then this returns empty-list.

     (See also $h->postinsert(LIST).)

$h->address()
     Returns a string representing the location of this node in the tree.
     The address consists of numbers joined by a '.', starting with '0',
     and followed by the pindexes of the nodes in the tree that are
     ancestors of $h, starting from the top.

     So if the way to get to a node starting at the root is to go to child
     2 of the root, then child 10 of that, and then child 0 of that, and
     then you're there - then that node's address is "0.2.10.0".

     As a bit of a special case, the address of the root is simply "0".

     I forsee this being used mainly for debugging, but you may find your
     own uses for it.

$h->address($address)
     This returns the node (whether element or text-segment) at the given
     address in the tree that $h is a part of.  (That is, the address is
     resolved starting from $h->root.)

     If there is no node at the given address, this returns undef.

     You can specify "relative addressing" (i.e., that indexing is supposed
     to start from $h and not from $h->root) by having the address start
     with a period - e.g., $h->address(".3.2") will look at child 3 of $h,
     and child 2 of that.

$h->depth()
     Returns a number expressing $h's depth within its tree, i.e., how many
     steps away it is from the root.  If $h has no parent (i.e., is root),
     its depth is 0.

$h->root()
     Returns the element that's the top of $h's tree.  If $h is root, this
     just returns $h.  (If you want to test whether $h *is* the root,
     instead of asking what its root is, just test not($h->parent).)

$h->lineage()
     Returns the list of $h's ancestors, starting with its parent, and then
     that parent's parent, and so on, up to the root.  If $h is root, this
     returns an empty list.

     If you simply want a count of the number of elements in $h's lineage,
     use $h->depth.

$h->lineage_tag_names()
     Returns the list of the tag names of $h's ancestors, starting with
     its parent, and that parent's parent, and so on, up to the root.  If
     $h is root, this returns an empty list.  Example output: `('em',
     'td', 'tr', 'table', 'body', 'html')'

$h->descendants()
     In list context, returns the list of all $h's descendant elements,
     listed in pre-order (i.e., an element appears before its
     content-elements).  Text segments DO NOT appear in the list.  In
     scalar context, returns a count of all such elements.

$h->find_by_tag_name('tag', ...)
     In list context, returns a list of elements at or under $h that have
     any of the specified tag names.  In scalar context, returns the first
     (in pre-order traversal of the tree) such element found, or undef if
     none.

$h->find_by_attribute('attribute', 'value')
     In a list context, returns a list of elements at or under $h that have
     the specified attribute, and have the given value for that attribute.
     In a scalar context, returns the first (in pre-order traversal of the
     tree) such element found, or undef if none.

     This method is *deprecated* in favor of the more expressive
     `look_down' method, which new code should use instead.

$h->look_down( ...criteria... )
     This starts at $h and looks thru its element descendants (in
     pre-order), looking for elements matching the criteria you specify.
     In list context, returns all elements that match all the given
     criteria; in scalar context, returns the first such element (or undef,
     if nothing matched).

     There are two kinds of criteria you can specify:

    (attr_name, attr_value)
          This means you're looking for an element with that value for that
          attribute.  Example: `"alt", "pix!"'.  Consider that you can
          search on internal attribute values too: `"_tag", "p"'.

    a coderef
          This means you're looking for elements where
          coderef->(each_element) returns true.  Example:

               my @wide_pix_images
                 = $h->look_down(
                                 "_tag", "img",
                                 "alt", "pix!",
                                 sub { $_[0]->attr('width') > 350 }
                                );

     Note that `(attr_name, attr_value)' criteria are faster than coderef
     criteria, so should presumably be put before them in your list of
     criteria.  That is, in the example above, the sub ref is called only
     for elements that have already passed the criteria of having a "_tag"
     attribute with value "img", and an "alt" attribute with value "pix!".
     If the coderef were first, it would be called on every element, and
     *then* what elements pass that criterion (i.e., elements for which
     the coderef returned true) would be checked for their "_tag" and "alt"
     attributes.

     Note that comparison of string attribute-values against the string
     value in `(attr_name, attr_value)' is case-INsensitive!  A criterion
     of `('align', 'right')' *will* match an element whose "align" value
     is "RIGHT", or "right" or "rIGhT", etc.

     Note also that `look_down' considers "" (empty-string) and undef to
     be different things, in attribute values.  So this:

          $h->look_down("alt", "")

     will find elements with an "alt" attribute, but where the value for
     the "alt" attribute is "".  But this:

          $h->look_down("alt", undef)

     is the same as:

          $h->look_down(sub { !defined($_[0]->attr('alt')) } )

     That is, it finds elements that do not have an "alt" attribute at all
     (or that do have an "alt" attribute, but with a value of undef -
     which is not normally possible).

     Note that when you give several criteria, this is taken to mean you're
     looking for elements that match all your criterion, not just any of
     them.  In other words, there is an implicit "and", not an "or".  So
     if you wanted to express that you wanted to find elements with a
     "name" attribute with the value "foo" or with an "id" attribute with
     the value "baz", you'd have to do it like:

          @them = $h->look_down(
            sub {
              # the lcs are to fold case
              lc($_[0]->attr('name')) eq 'foo'
              or lc($_[0]->attr('id')) eq 'baz'
            }
          );

     Coderef criteria are more expressive than `(attr_name, attr_value)'
     criteria, and all `(attr_name, attr_value)' criteria could be
     expressed in terms of coderefs.  However, `(attr_name, attr_value)'
     criteria are a convenient shorthand.  (In fact, `look_down' itself is
     basically "shorthand" too, since anything you can do with `look_down'
     you could do by traversing the tree, either with the `traverse'
     method or with a routine of your own.  However, `look_down' often
     makes for very concise and clear code.)

$h->look_up( ...criteria... )
     This is identical to $h->look_down, except that whereas $h->look_down
     basically scans over the list:

          ($h, $h->descendants)

     $h->look_up instead scans over the list

          ($h, $h->lineage)

     So, for example, this returns all ancestors of $h (possibly including
     $h itself) that are "td" elements with an "align" attribute with a
     value of "right" (or "RIGHT", etc.):

          $h->look_up("_tag", "td", "align", "right");

$h->traverse(...options...)
     Lengthy discussion of HTML::Element's unnecessary and confusing
     `traverse' method has been moved to a separate file:
     HTML/Element/traverse,

$h->attr_get_i('attribute')
     In list context, returns a list consisting of the values of the given
     attribute for $self and for all its ancestors starting from $self and
     working its way up.  Nodes with no such attribute are skipped.
     ("attr_get_i" stands for "attribute get, with inheritance".)  In
     scalar context, returns the first such value, or undef if none.

     Consider a document consisting of:

          <html lang='i-klingon'>
            <head><title>Pati Pata</title></head>
            <body>
              <h1 lang='la'>Stuff</h1>
              <p lang='es-MX' align='center'>
                Foo bar baz <cite>Quux</cite>.
              </p>
              <p>Hooboy.</p>
            </body>
          </html>

     If $h is the "cite" element, $h->attr_get_i("lang") in list context
     will return the list ('es-MX', 'i-klingon').  In scalar context, it
     will return the value 'es-MX'.

     If you call with multiple attribute names...

$h->attr_get_i('a1', 'a2', 'a3')
     ...in list context, this will return a list consisting of the values
     of these attributes which exist in $self and its ancestors.  In
     scalar context, this returns the first value (i.e., the value of the
     first existing attribute from the first element that has any of the
     attributes listed).  So, in the above example,

          $h->attr_get_i('lang', 'align');

     will return:

          ('es-MX', 'center', 'i-klingon') # in list context
            or
          'es-MX' # in scalar context.

     But note that this:

          $h->attr_get_i('align', 'lang');

     will return:

          ('center', 'es-MX', 'i-klingon') # in list context
            or
          'center' # in scalar context.

$h->tagname_map()
     Scans across $h and all its descendants, and makes a hash (a
     reference to which is returned) where each entry consists of a key
     that's a tag name, and a value that's a reference to a list to all
     elements that have that tag name.  I.e., this method returns:

          {
            # Across $h and all descendants...
            'a'   => [ ...list of all 'a'   elements... ],
            'em'  => [ ...list of all 'em'  elements... ],
            'img' => [ ...list of all 'img' elements... ],
          }

     (There are entries in the hash for only those tagnames that occur
     at/under $h - so if there's no "img" elements, there'll be no "img"
     entry in the hashr(ref) returned.)

     Example usage:

          my $map_r = $h->tagname_map();
          my @heading_tags = sort grep m/^h\d$/s, keys %$map_r;
          if(@heading_tags) {
            print "Heading levels used: @heading_tags\n";
          } else {
            print "No headings.\n"
          }

$h->extract_links() or $h->extract_links(@wantedTypes)
     Returns links found by traversing the element and all of its children
     and looking for attributes (like "href" in an "a" element, or "src" in
     an "img" element) whose values represent links.  The return value is a
     reference to an array.  Each element of the array is reference to an
     array with two items: the link-value and a the element that has the
     attribute with that link-value.  You may or may not end up using the
     element itself - for some purposes, you may use only the link value.

     You might specify that you want to extract links from just some kinds
     of elements (instead of the default, which is to extract links from
     all the kinds of elements known to have attributes whose values
     represent links).  For instance, if you want to extract links from
     only "a" and "img" elements, you could code it like this:

          for (@{  $e->extract_links('a', 'img')  }) {
              my($link, $element) = @$_;
              print
                "Hey, there's a ", $element->tag,
                " that links to $link\n";
          }

$h->same_as($i)
     Returns true if $h and $i are both elements representing the same tree
     of elements, each with the same tag name, with the same explicit
     attributes (i.e., not counting attributes whose names start with "_"),
     and with the same content (textual, comments, etc.).

     Sameness of descendant elements is tested, recursively, with
     `$child1->same_as($child_2)', and sameness of text segments is tested
     with `$segment1 eq $segment2'.

$h = HTML::Element->new_from_lol(ARRAYREF)
     Resursively constructs a tree of nodes, based on the (non-cyclic)
     data structure represented by ARRAYREF, where that is a reference to
     an array of arrays (of arrays (of arrays (etc.))).

     In each arrayref in that structure, different kinds of values are
     treated as follows:

        * Arrayrefs

          Arrayrefs are considered to designate a sub-tree representing
          children for the node constructed from the current arrayref.

        * Hashrefs

          Hashrefs are considered to contain attribute-value pairs to add
          to the element to be constructed from the current arrayref

        * Text segments

          Text segments at the start of any arrayref will be considered to
          specify the name of the element to be constructed from the
          current araryref; all other text segments will be considered to
          specify text segments as children for the current arrayref.

        * Elements

          Existing element objects are either inserted into the treelet
          constructed, or clones of them are.  That is, when the lol-tree
          is being traversed and elements constructed based what's in it,
          if an existing element object is found, if it has no parent,
          then it is added directly to the treelet constructed; but if it
          has a parent, then `$that_node->clone' is added to the treelet
          at the appropriate place.

     An example will hopefully make this more obvious:

          my $h = HTML::Element->new_from_lol(
            ['html',
              ['head',
                [ 'title', 'I like stuff!' ],
              ],
              ['body',
                {'lang', 'en-JP', _implicit => 1},
                'stuff',
                ['p', 'um, p < 4!', {'class' => 'par123'}],
                ['div', {foo => 'bar'}, '123'],
              ]
            ]
          );
          $h->dump;

     Will print this:

          <html> @0
            <head> @0.0
              <title> @0.0.0
                "I like stuff!"
            <body lang="en-JP"> @0.1 (IMPLICIT)
              "stuff"
              <p class="par123"> @0.1.1
                "um, p < 4!"
              <div foo="bar"> @0.1.2
                "123"

     And printing $h->as_HTML will give something like:

          <html><head><title>I like stuff!</title></head>
          <body lang="en-JP">stuff<p class="par123">um, p &lt; 4!
          <div foo="bar">123</div></body></html>

     You can even do fancy things with map:

          $body->push_content(
            # push_content implicitly calls new_from_lol on arrayrefs...
            ['br'],
            ['blockquote',
              ['h2', 'Pictures!'],
              map ['p', $_],
              $body2->look_down("_tag", "img"),
                # images, to be copied from that other tree.
            ],
            # and more stuff:
            ['ul',
              map ['li', ['a', {'href'=>"$_.png"}, $_ ] ],
              qw(Peaches Apples Pears Mangos)
            ],
          );

$h->has_insane_linkage
     This method is for testing whether this element or the elements under
     it have linkage attributes (_parent and _content) whose values are
     deeply aberrant: if there are undefs in a content list; if an element
     appears in the content lists of more than one element; if the _parent
     attribute of an element doesn't match its actual parent; or if an
     element appears as its own descendant (i.e., if there is a cyclicity
     in the tree).

     This returns empty list (or false, in scalar context) if the subtree's
     linkage methods are sane; otherwise it returns two items (or true, in
     scalar context): the element where the error occurred, and a string
     describing the error.

     This method is provided is mainly for debugging and troubleshooting -
     it should be *quite impossible* for any document constructed via
     HTML::TreeBuilder to parse into a non-sane tree (since it's not the
     content of the tree per se that's in question, but whether the tree
     in memory was properly constructed); and it should be impossible for
     you to produce an insane tree just thru reasonable use of normal
     documented structure-modifying methods.  But if you're constructing
     your own trees, and your program is going into infinite loops as
     during calls to traverse() or any of the secondary structural
     methods, as part of debugging, consider calling is_insane on the tree.

BUGS
====

   * If you want to free the memory associated with a tree built of
HTML::Element nodes, then you will have to delete it explicitly.  See the
$h->delete method, above.

   * There's almost nothing to stop you from making a "tree" with
cyclicities (loops) in it, which could, for example, make the traverse
method go into an infinite loop.  So don't make cyclicities!  (If all
you're doing is parsing HTML files, and looking at the resulting trees,
this will never be a problem for you.)

   * There's no way to represent comments or processing directives in a
tree with HTML::Elements.  Not yet, at least.

   * There's (currently) nothing to stop you from using an undefined value
as a text segment.  If you're running under `perl -w', however, this may
make HTML::Element's code produce a slew of warnings.

NOTES ON SUBCLASSING
====================

   You are welcome to derive subclasses from HTML::Element, but you should
be aware that the code in HTML::Element makes certain assumptions about
elements (and I'm using "element" to mean ONLY an object of class
HTML::Element, or of a subclass of HTML::Element):

   * The value of an element's _parent attribute must either be undef or
otherwise false, or must be an element.

   * The value of an element's _content attribute must either be undef or
otherwise false, or a reference to an (unblessed) array.  The array may be
empty; but if it has items, they must ALL be either mere strings (text
segments), or elements.

   * The value of an element's _tag attribute should, at least, be a
string of printable characters.

   Moreover, bear these rules in mind:

   * Do not break encapsulation on objects.  That is, access their
contents only thru $obj->attr or more specific methods.

   * You should think twice before completely overriding any of the
methods that HTML::Element provides.  (Overriding with a method that calls
the superclass method is not so bad, tho.)

SEE ALSO
========

   See HTML/TreeBuilder,; HTML/AsSubs,;
see HTML/Tagset,; and, for the morbidly
curious, see HTML/Element/traverse.

COPYRIGHT
=========

   Copyright 1995-1998 Gisle Aas, 1999-2000 Sean M. Burke.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Original author Gisle Aas <gisle@aas.no>; current maintainer Sean M.
Burke, <sburke@cpan.org>

discussion of HTML::Element's traverse method
*********************************************

NAME
====

   HTML::Element traverse - discussion of HTML::Element's traverse method

SYNOPSIS
========

     # $element->traverse is unnecessary and obscure.
     #   Don't use it in new code.

DESCRIPTION
===========

   `HTML::Element' provides a method `traverse' that traverses the tree
and calls user-specified callbacks for each node, in pre- or post-order.
However, use of the method is quite superfluous: if you want to
recursively visit every node in the tree, it's almost always simpler to
write a subroutine does just that, than it is to bundle up the pre- and/or
post-order code in callbacks for the `traverse' method.

EXAMPLES
========

   Suppose you want to traverse at/under a node $tree and give elements an
'id' attribute unless they already have one.

   You can use the `traverse' method:

     {
       my $counter = 'x0000';
       $start_node->traverse(
         [ # Callbacks;
           # pre-order callback:
           sub {
             my $x = $_[0];
             $x->attr('id', $counter++) unless defined $x->attr('id');
             return HTML::Element::OK; # keep traversing
           },
           # post-order callback:
           undef
         ],
         1, # don't call the callbacks for text nodes
       );
     }

   or you can just be simple and clear (and not have to understand the
calling format for `traverse') by writing a sub that traverses the tree by
just calling itself:

     {
       my $counter = 'x0000';
       sub give_id {
         my $x = $_[0];
         $x->attr('id', $counter++) unless defined $x->attr('id');
         foreach my $c ($x->content_list) {
           give_id($c) if ref $c; # ignore text nodes
         }
       };
       give_id($start_node);
     }

   See, isn't that nice and clear?

   But, if you really need to know:

THE TRAVERSE METHOD
===================

   The traverse() method is a general object-method for traversing a tree
or subtree and calling user-specified callbacks.  It accepts the following
syntaxes:

$h->traverse(\&callback)
or $h->traverse(\&callback, $ignore_text)
or $h->traverse([\&pre_callback,\&post_callback], $ignore_text)
   These all mean to traverse the element and all of its children.  That
is, this method starts at node $h, "pre-order visits" $h, traverses its
children, and then will "post-order visit" $h.  "Visiting" means that the
callback routine is called, with these arguments:

     $_[0] : the node (element or text segment),
     $_[1] : a startflag, and
     $_[2] : the depth

   If the $ignore_text parameter is given and true, then the pre-order
call *will not* be happen for text content.

   The startflag is 1 when we enter a node (i.e., in pre-order calls) and
0 when we leave the node (in post-order calls).

   Note, however, that post-order calls don't happen for nodes that are
text segments or are elements that are prototypically empty (like "br",
"hr", etc.).

   If we visit text nodes (i.e., unless $ignore_text is given and true),
then when text nodes are visited, we will also pass two extra arguments to
the callback:

     $_[3] : the element that's the parent
              of this text node
     $_[4] : the index of this text node
              in its parent's content list

   Note that you can specify that the pre-order routine can be a different
routine from the post-order one:

     $h->traverse([\&pre_callback,\&post_callback], ...);

   You can also specify that no post-order calls are to be made, by
providing a false value as the post-order routine:

     $h->traverse([ \&pre_callback,0 ], ...);

   And similarly for suppressing pre-order callbacks:

     $h->traverse([ 0,\&post_callback ], ...);

   Note that these two syntaxes specify the same operation:

     $h->traverse([\&foo,\&foo], ...);
     $h->traverse( \&foo       , ...);

   The return values from calls to your pre- or post-order routines are
significant, and are used to control recursion into the tree.

   These are the values you can return, listed in descending order of my
estimation of their usefulness:

HTML::Element::OK, 1, or any other true value
     ...to keep on traversing.

     Note that `HTML::Element::OK' et al are constants.  So if you're
     running under `use strict' (as I hope you are), and you say: `return
     HTML::Element::PRUEN' the compiler will flag this as an error (an
     unallowable bareword, specifically), whereas if you spell PRUNE
     correctly, the compiler will not complain.

undef, 0, '0', ", or HTML::Element::PRUNE
     ...to block traversing under the current element's content.  (This is
     ignored if received from a post-order callback, since by then the
     recursion has already happened.)  If this is returned by a pre-order
     callback, no post-order callback for the current node will happen.
     (Recall that if your callback exits with just `return;', it is
     returning undef - at least in scalar context, and `traverse' always
     calls your callbacks in scalar context.)

HTML::Element::ABORT
     ...to abort the whole traversal immediately.  This is often useful
     when you're looking for just the first node in the tree that meets
     some criterion of yours.

HTML::Element::PRUNE_UP
     ...to abort continued traversal into this node and its parent node.
     No post-order callback for the current or parent node will happen.

HTML::Element::PRUNE_SOFTLY
     Like PRUNE, except that the post-order call for the current node is
     not blocked.

   Almost every task to do with extracting information from a tree can be
expressed in terms of traverse operations (usually in only one pass, and
usually paying attention to only pre-order, or to only post-order), or
operations based on traversing. (In fact, many of the other methods in
this class are basically calls to traverse() with particular arguments.)

   The source code for HTML::Element and HTML::TreeBuilder contain several
examples of the use of the "traverse" method to gather information about
the content of trees and subtrees.

   (Note: you should not change the structure of a tree while you are
traversing it.)

   [End of documentation for the traverse() method]

Traversing with Recursive Anonymous Routines
--------------------------------------------

   Now, if you've been reading *Structure and Interpretation of Computer
Programs* too much, maybe you even want a recursive lambda.  Go ahead:

     {
       my $counter = 'x0000';
       my $give_id;
       $give_id = sub {
         my $x = $_[0];
         $x->attr('id', $counter++) unless defined $x->attr('id');
         foreach my $c ($x->content_list) {
           $give_id->($c) if ref $c; # ignore text nodes
         }
       };
       $give_id->($start_node);
       undef $give_id;
     }

   It's a bit nutty, and it's *still* more concise than a call to the
`traverse' method!

   It is left as an exercise to the reader to figure out how to do the
same thing without using a `$give_id' symbol at all.

   It is also left as an exercise to the reader to figure out why I
undefine `$give_id', above; and why I could achieved the same effect with
any of:

     $give_id = 'I like pie!';
        # or...
     $give_id = [];
        # or even;
     $give_id = sub { print "Mmmm pie!\n" };

   But not:

     $give_id = sub { print "I'm $give_id and I like pie!\n" };
        # nor...
     $give_id = \$give_id;
        # nor...
     $give_id = { 'pie' => \$give_id, 'mode' => 'a la' };

Doing Recursive Things Iteratively
----------------------------------

   Note that you may at times see an iterative implementation of pre-order
traversal, like so:

     {
       my @to_do = ($tree); # start-node
       while(@to_do) {
         my $this = shift @to_do;

         # "Visit" the node:
         $this->attr('id', $counter++)
          unless defined $this->attr('id');

         unshift @to_do, grep ref $_, $this->content_list;
          # Put children on the stack -- they'll be visited next
       }
     }

   This can *under certain circumstances* be more efficient than just a
normal recursive routine, but at the cost of being rather obscure.  It
gains efficiency by avoiding the overhead of function-calling, but since
there are several method dispatches however you do it (to attr and
`content_list'), the overhead for a simple function call is insignificant.

Pruning and Whatnot
-------------------

   The `traverse' method does have the fairly neat features of the
`ABORT', `PRUNE_UP' and `PRUNE_SOFTLY' signals.  None of these can be
implemented *totally* straightforwardly with recursive routines, but it is
quite possible.  `ABORT'-like behavior can be implemented either with
using non-local returning with eval/die:

     my $died_on; # if you need to know where...
     sub thing {
       ... visits $_[0]...
       ... maybe set $died_on to $_[0] and die "ABORT_TRAV" ...
       ... else call thing($child) for each child...
       ...any post-order visiting $_[0]...
     }
     eval { thing($node) };
     if($@) {
       if($@ =~ m<^ABORT_TRAV>) {
         ...it died (aborted) on $died_on...
       } else {
         die $@; # some REAL error happened
       }
     }

   or you can just do it with flags:

     my($abort_flag, $died_on);
     sub thing {
       ... visits $_[0]...
       ... maybe set $abort_flag = 1; $died_on = $_[0]; return;
       foreach my $c ($_[0]->content_list) {
         thing($c);
         return if $abort_flag;
       }
       ...any post-order visiting $_[0]...
       return;
     }

     $abort_flag = $died_on = undef;
     thing($node);
     ...if defined $abort_flag, it died on $died_on

SEE ALSO
========

   See HTML/Element,

COPYRIGHT
=========

   Copyright 2000 Sean M. Burke

AUTHOR
======

   Sean M. Burke, <sburke@cpan.org>

Perl extension for managing HTML::Element based objects as a single object.
***************************************************************************

NAME
====

   HTML::ElementGlob - Perl extension for managing HTML::Element based
objects as a single object.

SYNOPSIS
========

     use HTML::ElementGlob;
     $element_a = new HTML::Element 'font', color => 'red';
     $element_b = new HTML::Element 'font', color => 'blue';
     $element_a->push_content('red');
     $element_b->push_content('blue');

     $p = new HTML::Element 'p';
     $p->push_content($element_a, ' and ', $element_b, ' boo hoo hoo');

     # Tag type of the glob is not really relevant unless
     # you plan on seeing the glob as_HTML()
     $eglob = new HTML::ElementGlob 'p';
     $eglob->glob_push_content($element_a, $element_b);
     # Alter both elements at once
     $eglob->attr(size => 5);

     # They still belong to their original parent
     print $p->as_HTML;

DESCRIPTION
===========

   HTML::ElementGlob is a managing object for multiple HTML::Element(3)
style elements.  The children of the glob element retain their original
parental elements and have no knowledge of the glob that manipulates them.
All methods that do not start with 'glob_' will be passed, sequentially,
to all elements contained within the glob element.  Methods starting with
'glob_' will operate on the glob itself, rather than being passed to its
foster children.

   For example, $eglob->attr(size => 3) will invoke attr(size => 3) on all
children contained by $eglob.  $eglob->glob_attr(size => 3), on the other
hand, will set the attr attribute on the glob itself.

   The tag type passed to HTML::Element::Glob is largely irrrelevant as
far as how methods are passed to children.  However, if you choose to
invoke $eglob->as_HTML(), you might want to pick a tag that would sensibly
contain the globbed children for debugging or display purposes.

   The 'glob_*' methods that operate on the glob itself are limited to
those available in an HTML::Element(3).  All other methods get passed
blindly to the globbed children, which can be enhanced elements with
arbitrary methods, such as HTML::ElementSuper(3).

   Element globs can contain other element globs.  In such cases, the
plain methods will cascade down to the leaf children.  'glob_*' methods,
of course, will not be propogated to children globs.  You will have to
rely on glob_content() to access those glob children and access their
'glob_*' methods directly.

REQUIRES
========

   HTML::ElementSuper(3)

AUTHOR
======

   Matthew P. Sisk, <`sisk@mojotoad.com'>

COPYRIGHT
=========

   Copyright (c) 1998-2000 Matthew P. Sisk.  All rights reserved. All
wrongs revenged. This program is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

SEE ALSO
========

   HTML::Element(3), HTML::ElementSuper, HTML::ElementRaw,
HTML::Element::Table(3), perl(1).

Perl extension for HTML::Element(3).
************************************

NAME
====

   HTML::ElementRaw - Perl extension for HTML::Element(3).

SYNOPSIS
========

     use HTML::ElementRaw;
     $er = new HTML::ElementRaw;
     $text = '<p>I would like this &nbsp; HTML to not be encoded</p>';
     $er->push_content($text);
     $h = new HTML::Element 'h2';
     $h->push_content($er);
     # Now $text will appear as you typed it, non-escaped,
     # embedded in the HTML produced by $h.
     print $h->as_HTML;

DESCRIPTION
===========

   Provides a way to graft raw HTML strings into your HTML::Element(3)
structures.  Since they represent raw text, these can only be leaves in
your HTML element tree.  The only methods that are of any real use in this
degenerate element are push_content() and as_HTML().  The push_content()
method will simply prepend the provided text to the current content.  If
you happen to pass an HTML::element to push_content, the output of the
as_HTML() method in that element will be prepended.

REQUIRES
========

   HTML::Element(3)

AUTHOR
======

   Matthew P. Sisk, <`sisk@mojotoad.com'>

COPYRIGHT
=========

   Copyright (c) 1998 Matthew P. Sisk.  All rights reserved. All wrongs
revenged. This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

SEE ALSO
========

   HTML::Element(3), HTML::ElementSuper(3), HTML::Element::Glob(3),
HTML::ElementTable(3), perl(1).

Perl extension for HTML::Element(3)
***********************************

NAME
====

   HTML::ElementSuper - Perl extension for HTML::Element(3)

SYNOPSIS
========

     use HTML::ElementSuper;

     ### Positional extension
     $e = new HTML::ElementSuper 'font';
     $sibling_number = $e->addr();
     $e2 = new HTML::ElementSuper 'p';
     $e2->push_content($e);
     #
     @coords = $e->position();
     $depth_in_pos_tree = $e->depth();

     ### Replacer extension
     $er = new HTML::ElementSuper 'font';
     # Tree beneath $er, if present, is dropped.
     $er->replace_content(new HTML::Element 'p');

     ### Wrapper extension
     $ew = new HTML::ElementSuper;
     $ew->push_content("Tickle me, baby");
     $ew->wrap_content(new HTML::Element 'font', color => 'pink');
     print $ew->as_HTML();

     ### Maskable extension
     $em = new HTML::ElementSuper 'td';
     $em->mask(1);
     print $em->as_HTML; # nada
     $em->mask(0);
     print $em->as_HTML; # $e and its children are visible

     ### Cloning of own tree or another element's tree
     ### (is this the correct clomenature?  :-)
     $a = new HTML::ElementSuper 'font', size => 2;
     $b = new HTML::ElementSuper 'font', color => 'red';
     $a_clone  = $a->clone;
     $b_clone = $a->clone($b);
     # Multiple elements can be cloned
     @clone_clones = $a_clone->clone($a_clone, $b_clone);

DESCRIPTION
===========

   HTML::ElementSuper is an extension for HTML::Element(3) that provides
several new methods to assist in element manipulation.  An
HTML::ElementSuper has the following additional properties:

     * report is coordinate position in a tree of its peers
     * replace its contents
     * wrap its contents in a new element
     * mask itself so that it and its descendants are invisible
       to traverse()
     * clone itself and other HTML::Element based object trees

   Note that these extensions were originally developed to assist in
implementing the HTML::ElementTable(3) class, but were thought to be of
general enough utility to warrant their own package.

METHODS
=======

new('tag', attr => 'value', ...)
     Return a new HTML::ElementSuper object.  Exactly like the constructor
     for HTML::Element(3), takes a tag type and optional attributes.

addr()
     Returns the position of this element in relation to its siblings
     based on the content of the parent, starting with 0.  Returns undef
     if this element has no parent. In other words, this returns the index
     of this element in the content array of the parent.

position()
     Returns the coordinates of this element in the tree it inhabits.
     This is accomplished by succesively calling addr() on ancestor
     elements until either a) an element that does not support these
     methods is found, or b) there are no more parents.  The resulting
     list is the n-dimensional coordinates of the element in the tree.

replace_content(@new_content)
     Simple shortcut method that deletes the current contents of the
     element before adding the new.

wrap_content($wrapper_element)
     Wraps the existing content in the provided element.  If the provided
     element happens to be a non-element, a push_content is performed
     instead.

mask
mask(mode)
     Toggles whether or not this element is visible to parental methods
     that visit the element tree using traverse(), such as as_HTML().
     Valid arguments for mask() are 0 and 1.  Returns the current setting
     without an argument.

     This might seem like a strange method to have, but it helps in
     managing dynamic tree structures.  For example, in
     HTML::ElementTable(3), when you expand a table cell you simply mask
     what it covers rather than destroy it.  Shrinking the table cell
     reveals that content to as_HTML() once again.

clone
clone(@elements)
     Returns a clone of elements and all of their descendants.  Without
     arguments, the element clones itself, otherwise it clones the
     elements provided as arguments. Any element can be cloned as long as
     it is HTML::Element(3) based.  This method is very handy for
     duplicating tree structures since an HTML::Element cannot have more
     than one parent at any given time...hence "tree".

REQUIRES
========

   HTML::Element(3), Data::Dumper(3)

AUTHOR
======

   Matthew P. Sisk, <`sisk@mojotoad.com'>

COPYRIGHT
=========

   Copyright (c) 1998-2000 Matthew P. Sisk.  All rights reserved. All
wrongs revenged. This program is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

SEE ALSO
========

   HTML::Element(3), HTML::ElementGlob(3), HTML::ElementRaw(3),
HTML::ElementTable(3), perl(1).

Perl extension for manipulating a table composed of HTML::Element style components.
***********************************************************************************

NAME
====

   HTML::ElementTable - Perl extension for manipulating a table composed
of HTML::Element style components.

SYNOPSIS
========

     use HTML::ElementTable;
     # Create a table 0..10 x 0..12
     $t = new HTML::ElementTable maxrow => 10, maxcol => 12;

     # Populate cells with coordinates
     $t->table->push_position;

     # Manipulate <TABLE> tag
     $t->attr('cellspacing',0);
     $t->attr('border',1);
     $t->attr('bgcolor','#DDBB00');

     # Manipulate entire table - optimize on <TR> or pass to all <TD>
     $t->table->attr('align','left');
     $t->table->attr('valign','top');

     # Manipulate rows (optimizes on <TR> if possible)
     $t->row(0,2,4,6)->attr('bgcolor','#9999FF');

     # Manipulate columns (all go to <TD> tags within column)
     $t->col(0,4,8,12)->attr('bgcolor','#BBFFBB');

     # Manipulate boxes (all go to <TD> elements
     # unless it contains full rows, then <TR>)
     $t->box(7,1 => 10,3)->attr('bgcolor','magenta');
     $t->box(7,7 => 10,5)->attr('bgcolor','magenta');
     $t->box(8,9 => 9,11)->attr('bgcolor','magenta');
     $t->box(7,10 => 10,10)->attr('bgcolor','magenta');

     # individual <TD> or <TH> attributes
     $t->cell(8,6)->attr('bgcolor','#FFAAAA');
     $t->cell(9,6)->attr('bgcolor','#FFAAAA');
     $t->cell(7,9, 10,9, 7,11, 10,11)->attr('bgcolor','#FFAAAA');

     # Take a look
     print $t->as_HTML;

DESCRIPTION
===========

   HTML::ElementTable provides a highly enhanced HTML::ElementSuper
structure with methods designed to easily manipulate table elements by
using coordinates.  Elements can be manipulated in bulk by individual
cells, arbitrary groupings of cells, boxes, columns, rows, or the entire
table.

PUBLIC METHODS
==============

   Table coordinates start at 0,0 in the upper left cell.

   CONSTRUCTOR

new()
new(maxrow => row, maxcol => col)
     Return a new HTML::ElementTable object.  If the number of rows and
     columns were provided, all elements required for the rows and columns
     will be initialized as well.  See extent().

   TABLE CONFIGURATION

extent()
extent(maxrow, maxcolumn)
     Set or return the extent of the current table.  The *maxrow* and
     *maxcolumn* parameters indicate the maximum row and column coordinates
     you desire in the table.  These are the coordinates of the lower
     right cell in the table, starting from (0,0) at the upper left.
     Providing a smaller extent than the current one will shrink the table
     with no ill effect, provided you do not mind losing the information
     in the clipped cells.

maxrow()
     Set or return the coordinate of the last row.

maxcol()
     Set or return the coordinate of the last column.

   ELEMENT ACCESS

   Unless accessing a single element, most table element access is
accomplished through *globs*, which are collections of elements that
behave as if they were a single element object.

   Whenever possible, globbed operations are optimized into the most
appropriate element.  For example, if you set an attribute for a row glob,
the attribute will be set either on the <TR> element or the collected <TD>
elements, whichever is appropriate.

   See `HTML::ElementGlob(3)' in this node for more information on element
globs.

cell(row,col,[row2,col2],[...])
     Access an individual cell or collection of cells by their coordinates.

row(row,[row2,...])
     Access the contents of a row or collection of rows by row coordinate.

col(col,[col2,...])
     Access the contents of a column or collection of columns by column
     coordinate.

box(row_a1,col_a1,row_a2,col_a2,[row_b1,col_b1,row_b2,col_b2],[...])
     Access the contents of a span of cells, specified as a box consisting
     of two sets of coordinates.  Multiple boxes can be specified.

table()
     Access all cells in the table.  This is different from manipulating
     the table object itself, which is reserved for such things as
     CELLSPACING and other attributes specific to the <TABLE> tag.
     However, since table() returns a glob of cells, if the attribute is
     more appropriate for the top level <TABLE> tag, it will be placed
     there rather than in each <TR> tag or every <TD> tag.

   ELEMENT/GLOB METHODS

   The interfaces to a single table element or a glob of elements are
identical.  All methods available from the HTML::ElementSuper class are
also available to a table element or glob of elements.  See
`HTML::ElementSuper(3)' in this node for details on these methods.

   Briefly, here are some of the more useful methods provided by
HTML::ElementSuper:

attr()
push_content()
replace_content()
wrap_content()
clone([element])
mask([mode])
   TABLE SPECIFIC EXTENSIONS

blank_fill([mode])
     Set or return the current fill mode for blank cells. The default is 0
     for HTML::Element::Table elements.  When most browsers render tables,
     if they are empty you will get a box the color of your browser
     background color rather than the BGCOLOR of that cell.  When enabled,
     empty cells are provided with an '&nbsp;', or invisible content,
     which will trigger the rendering of the BGCOLOR for that cell.

NOTES ON GLOBS
==============

   Globbing was a convenient way to treat arbitrary collections of table
cells as if they were a single HTML element.  Methods are generally passed
blindly and sequentially to the elements they contain.

   Most of the time, this is fairly intuitive, such as when you are
setting the attributes of the cells.

   Other times, it might be problematic, such as with push_content().  Do
you push the same object to all of the cells? HTML::Element based classes
only support one parent, so this breaks if you try to push the same
element into multiple parental hopefuls.  In the specific case of
push_content() on globs, the elements that eventually get pushed are
clones of the originally provided content.  It works, but it is not
necessarily what you expect.  An incestuous HTML element tree is probably
not what you want anyway.

   See `HTML::ElementGlob(3)' in this node for more details on how globs
work.

REQUIRES
========

   HTML::ElementSuper, HTML::ElementGlob

AUTHOR
======

   Matthew P. Sisk, <`sisk@mojotoad.com'>

ACKNOWLEDGEMENTS
================

   Thanks to William R. Ward for some conceptual nudging.

COPYRIGHT
=========

   Copyright (c) 1998-2000 Matthew P. Sisk.  All rights reserved. All
wrongs revenged. This program is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

SEE ALSO
========

   A useful page of HTML::ElementTable examples can be found at
http://www.mojotoad.com/sisk/projects/HTML-Element-Extended/examples.html.

   HTML::ElementSuper(3), HTML::ElementGlob(3), HTML::Element(3), perl(1).

Sends results from Embperl via E-Mail
*************************************

NAME
====

   HTML::Embperl::Mail - Sends results from Embperl via E-Mail

SYNOPSIS
========

     use HTML::Embperl::Mail ;

     HTML::Embperl::Mail::Execute ({inputfile => 'template.epl',
                                    subject   => 'Test HTML::Embperl::Mail::Execute',
                                    to        => 'email@foo.org'}) ;

DESCRIPTION
===========

   *HTML::Embperl::Mail* uses *HTML::Embperl* to process a page template
and send the result out via EMail. Currently only plain text mails are
supported. A later version may add support for HTML mails. Because of that
fact, normal *Embperl* HTML processing is disabled per Default (see
`options' in this node below).

Execute
-------

   The Execute function can handle all the parameter that
`HTML::Embperl::Execute' does. Addtionaly the following parameters are
recognized:

from
     gives the sender e-mail address

to
     gives the recipient address(es). Multiply addresses can either be
     separated by semikolon or given as an array ref.

cc
     gives the recipient address(es) which should receive a carbon copy.
     Multiply addresses can either be separated by semikolon or given as
     an array ref.

bcc
     gives the recipient address(es) which should receive a blind carbon
     copy. Multiply addresses can either be separated by semikolon or
     given as an array ref.

subject
     gives the subject line

reply-to
     the given address is insert as reply address

mailheaders
     Array ref of additional mail headers

mailhost
     Specifies which host to use as SMTP server.  Default is *localhost*.

mailhelo
     Specifies which host/domain to use in the HELO/EHLO command.  A
     reasonable default is normaly choosen by *Net::SMTP*, but depending
     on your installation it may neccessary to set it manualy.

maildebug
     Set to 1 to enable debugging of mail transfer.

options
     If no options are given the following are used per default:
     *optDisableHtmlScan*, *optRawInput*, *optKeepSpaces*, *optReturnError*

escmode
     In contrast to normal *Embperl* escmode defaults to zero (no escape)

errors
     As in `HTML::Embperl::Execute' you can specify an array ref, which
     returns all the error messages from template processing. If you don't
     specify this parameter Execute will die when an error occurs.

Configuration
-------------

   Some default values could be setup via environement variables

EMBPERL_MAILHOST
----------------

   Specifies which host to use as SMTP server.  Default is *localhost*.

EMBPERL_MAILHELO
----------------

   Specifies which host/domain to use in the HELO/EHLO command.  A
reasonable default is normaly choosen by *Net::SMTP*, but depending on
your installation it may neccessary to set it manualy.

EMBPERL_MAILFROM
----------------

   Specifies which the email address that is used as sender.  Default is
*www-server@server_name*.

EMBPERL_MAILDEBUG
-----------------

   Debug setting for Net::SMTP. Default is 0.

Author
======

   G. Richter (richter@dev.ecos.de)

See Also
========

   perl(1), HTML::Embperl, Net::SMTP

HTML::Embperl::Session
**********************

NAME
====

   HTML::Embperl::Session

DESCRIPTION
===========

   An adaptation of Apache::Session to work with HTML::Embperl

SYNOPSIS
========

Addtional Attributes for TIE
----------------------------

lazy
     By Specifing this attribute, you tell Apache::Session to not do any
     access to the object store, until the first read or write access to
     the tied hash. Otherwise the tie function will make sure the hash
     exist or creates a new one.

create_unknown
     Setting this to one causes Apache::Session to create a new session
     with the given id (or a new id, depending on recreate_id) when the
     specified session id does not exists. Otherwise it will die.

recreate_id
     Setting this to one causes Apache::Session to create a new session id
     when the specified session id does not exists.

object_store
     Specify the class for the object store. (The Apache::Session:: prefix
     is optional) Only for Apache::Session 1.00.

lock_manager
     Specify the class for the lock manager. (The Apache::Session:: prefix
     is optional) Only for Apache::Session 1.00.

Store
     Specify the class for the object store. (The Apache::Session::Store
     prefix is optional) Only for Apache::Session 1.5x.

Lock
     Specify the class for the lock manager. (The Apache::Session::Lock
     prefix is optional) Only for Apache::Session 1.5x.

Generate
     Specify the class for the id generator. (The
     Apache::Session::Generate prefix is optional) Only for
     Apache::Session 1.5x.

Serialize
     Specify the class for the data serializer. (The
     Apache::Session::Serialize prefix is optional) Only for
     Apache::Session 1.5x.

   Example using attrubtes to specfiy store and object classes instead of
a derived class:

     use HTML::Embperl::Session;

     tie %session, 'HTML::Embperl::Session', undef,
        {
        object_store => 'DBIStore',
        lock_manager => 'SysVSemaphoreLocker',
        DataSource => 'dbi:Oracle:db'
        };

   NOTE: HTML::Embperl::Session will require the nessecary additional perl
modules for you.

Addtional Methods
-----------------

setid
     Set the session id for futher accesses.

getid
     Get the session id. The difference to using $session{_session_id} is,
     that in lazy mode, getid will not create a new session id, if it
     doesn't exists.

cleanup
     Writes any pending data, releases all locks and deletes all data from
     memory.

AUTHORS
=======

   Gerald Richter <richter@dev.ecos.de> is the current maintainer.

   This class was written by Jeffrey Baker (jeffrey@kathyandjeffrey.net)
but it is taken wholesale from a patch that Gerald Richter
(richter@ecos.de) sent me against Apache::Session.

Extents HTML::Embperl for building whole website with reusable components and objects
*************************************************************************************

NAME
====

   HTML::EmbperlObject - Extents HTML::Embperl for building whole website
with reusable components and objects

SYNOPSIS
========

     <Location /foo>
         PerlSetEnv EMBPERL_OBJECT_BASE base.htm
         PerlSetEnv EMBPERL_FILESMATCH "\.htm.?|\.epl$"
         SetHandler perl-script
         PerlHandler HTML::EmbperlObject
         Options ExecCGI
     </Location>

DESCRIPTION
===========

   *HTML::EmbperlObject* allows you to build object-oriented (OO) websites
using HTML components which implement inheritance via subdirectories. This
enables elegant architectures and encourages code reuse. The use of
inheritance also enables a website-wide "look and feel" to be specified in
a single HTML file, which is then used as a template for every other page
on the site. This template can include other modules which can be
overridden in subdirectories; even the template itself can be overridden.
In a nutshell, EmbperlObject makes the design of large websites much more
intuitive, allowing object-oriented concepts to be utilised to the fullest
while staying within the "rapid application development" model of Perl and
HTML.

   *HTML::EmbperlObject* is basicly a mod_perl handler or could be invoked
offline and helps you to build a whole page out of smaller parts. Basicly
it does the following:

   When a request comes in, a page, which name is specified by
`EMBPERL_OBJECT_BASE' in this node, is searched in the same directory as
the requested page. If the pages isn't found, EmbperlObject walking up the
directory tree until it finds the page, or it reaches `DocumentRoot' or
the directory specified by `EMBPERL_OBJECT_STOPDIR' in this node.

   This page is then called as frame for building the real page.
Addtionaly EmbperlObject sets the search path to contain all directories
it had to walk before finding that page.  If `EMBPERL_OBJECT_STOPDIR' in
this node is set the path contains all directories up to the in
EMBPERL_OBJECT_STOPDIR specified one.

   This frame page can now include other pages, using the
`HTML::Embperl::Execute' method.  Because the search path is set by
EmbperlObject the included files are searched in the directories starting
at the directory of the original request walking up thru the directory
which contains the base page. This means that you can have common files,
like header, footer etc.  in the base directory and override them as
necessary in the subdirectory.

   To include the original requested file, you need to call Execute with a
'*' as filename.  To call the the same file, but in an upper directory you
can use the special shortcut `../*'.

   Additionaly EmbperlObject sets up a inherence hierachie for you: The
requested page inherit from the base page and the base page inherit from a
class which could be specified by EMBPERL_OBJECT_HANDLER_CLASS, or if
EMBPERL_OBJECT_HANDLER_CLASS is not set, from `HTML::Embperl::Req'. That
allows you to define methods in base page and overwrite them as neccessary
in the original requested files. For this purpose a request object, which
is blessed into the package of the requested page, is given as first
parameter to each page (in `$_[0]'). Because this request object is a
hashref, you can also use it to store additional data, which should be
available in all components.  *Embperl* does not use this hash itself, so
you are free to store whatever you want.  Methods can be ordinary Perl
sub's (defined with [! sub foo { ... } !] ) or Embperl sub's (defined with
[$sub foo $] .... [$endsub $]) .

Runtime configuration
=====================

   The runtime configuration is done by setting environment variables, in
your web server's configuration file.

EMBPERL_DECLINE
---------------

   Perl regex which files should be ignored by EmbperlObject

EMBPERL_FILESMATCH
------------------

   Perl regex which files should be processed by EmbperlObject

EMBPERL_OBJECT_BASE
-------------------

   Name of the base page to search for

EMBPERL_OBJECT_STOPDIR
----------------------

   Directory where to stop searching for the base page

EMBPERL_OBJECT_ADDPATH
----------------------

   Additional directories where to search for pages. Directories are
separated by `;' (on Unix : works also). This path is always appended to
the searchpath.

EMBPERL_OBJECT_FALLBACK
-----------------------

   If the requested file is not found the file given by
EMBPERL_OBJECT_FALLBACK is displayed instead. If EMBPERL_OBJECT_FALLBACK
isn't set a staus 404, NOT_FOUND is returned as usual. If the fileame
given in EMBPERL_OBJECT_FALLBACK doesn't contain a path, it is searched
thru the same directories as EMBPERL_OBJECT_BASE.

EMBPERL_OBJECT_HANDLER_CLASS
----------------------------

   If you specify this call the template base and the requested page
inherit all methods from this class. This class must contain
`HTML::Embperl::Req' in his  @ISA array.

Execute
=======

   You can use EmbperlObject also offline. You can do this by calling the
function `HTML::EmbperlObject::Execute'. Execute takes a hashref as
argument, which can contains the same parameters as the
`HTML::Embperl::Execute' function. Additionaly you may specify the
following parameters:

object_base
     same as $ENV{EMBPERL_OBJECT_BASE}

object_addpath
     same as $ENV{EMBPERL_OBJECT_ADDPATH}

object_stopdir
     same as $ENV{EMBPERL_OBJECT_STOPDIR}

object_fallback
     same as $ENV{EMBPERL_OBJECT_FALLBACK}

object_handler_class
     same as $ENV{EMBPERL_OBJECT_HANDLER_CLASS}

   See also the object and isa parameters in Embperl's Execute function,
on how to setup additional inherence and how to create Perl objects out of
Embperl pages.

Basic Example
=============

   With the following setup:

     <Location /foo>
        PerlSetEnv EMBPERL_OBJECT_BASE base.htm
        PerlSetEnv EMBPERL_FILESMATCH "\.htm.?|\.epl$"
        SetHandler perl-script
        PerlHandler HTML::EmbperlObject
        Options ExecCGI
     </Location>

   *Directory Layout:*

     /foo/base.htm
     /foo/head.htm
     /foo/foot.htm
     /foo/page1.htm
     /foo/sub/head.htm
     /foo/sub/page2.htm

   */foo/base.htm:*

     <html>
     <head>
     <title>Example</title>
     </head>
     <body>
     [- Execute ('head.htm') -]
     [- Execute ('*') -]
     [- Execute ('foot.htm') -]
     </body>
     </html>

   */foo/head.htm:*

     <h1>head from foo</h1>

   */foo/sub/head.htm:*

     <h1>another head from sub</h1>

   */foo/foot.htm:*

     <hr> Footer <hr>

   */foo/page1.htm:*

     PAGE 1

   */foo/sub/page2.htm:*

     PAGE 2

   */foo/sub/index.htm:*

     Index of /foo/sub

   If you now request *http://host/foo/page1.htm* you will get the
following page

     <html>
      <head>
      <title>Example</title>
      </head>
      <body>
      <h1>head from foo</h1>
      PAGE 1
      <hr> Footer <hr>
      </body>
      </html>

   If you now request *http://host/foo/sub/page2.htm* you will get the
following page

     <html>
      <head>
      <title>Example</title>
      </head>
      <body>
      <h1>another head from sub</h1>
      PAGE 2
      <hr> Footer <hr>
      </body>
      </html>

   If you now request *http://host/foo/sub/* you will get the following
page

     <html>
      <head>
      <title>Example</title>
      </head>
      <body>
      <h1>another head from sub</h1>
      Index of /foo/sub
      <hr> Footer <hr>
      </body>
      </html>

Example for using method calls
==============================

   (Everything not given here is the same as in the example above)

   */foo/base.htm:*

     [!

     sub new
        {
        my $self = shift ;

     # here we attach some data to the request object
     $self -> {fontsize} = 3 ;
     }

     # Here we give a default title
     sub title { 'Title not given' } ;

     !]

     [-

     # get the request object of the current request
     $req = shift ;

     # here we call the method new
     $req -> new ;

     -]

     <html>
     <head>
     <title>[+ $req -> title +]</title>
     </head>
     <body>
     [- Execute ('head.htm') -]
     [- Execute ('*') -]
     [- Execute ('foot.htm') -]
     </body>
     </html>

   */foo/head.htm:*

     [#
        here we use the fontsize
        Note that
          $foo = $_[0]
        is the same as writing
          $foo = shift
     #]

     <font size=[+ $_[0] -> {fontsize} +]>header</font>

   */foo/sub/page2.htm:*

     [!

     sub new
        {
        my $self = shift ;

     # here we overwrite the new method form base.htm
     $self -> {fontsize} = 5 ;
     }

     # Here we overwrite the default title
     sub title { 'Title form page 2' } ;

     !]

     PAGE 2

Author
======

   G. Richter (richter@dev.ecos.de)

See Also
========

   perl(1), HTML::Embperl, mod_perl, Apache httpd

Encode or decode strings with HTML entities
*******************************************

NAME
====

   HTML::Entities - Encode or decode strings with HTML entities

SYNOPSIS
========

     use HTML::Entities;

     $a = "V&aring;re norske tegn b&oslash;r &#230res";
     decode_entities($a);
     encode_entities($a, "\200-\377");

DESCRIPTION
===========

   This module deals with encoding and decoding of strings with HTML
character entities.  The module provides the following functions:

decode_entities($string)
     This routine replaces HTML entities found in the $string with the
     corresponding ISO-8859/1 (or with perl-5.7 or better Unicode)
     character.  Unrecognized entities are left alone.

encode_entities($string, [$unsafe_chars])
     This routine replaces unsafe characters in $string with their entity
     representation.  A second argument can be given to specify which
     characters to concider as unsafe.  The default set of characters to
     expand are control chars, high-bit chars and the '<', '&', '>' and '"'
     characters.

   Both routines modify the string passed as the first argument if called
in a void context.  In scalar and array contexts the encoded or decoded
string is returned (and the argument string is left unchanged).

   If you prefer not to import these routines into your namespace you can
call them as:

     use HTML::Entities ();
     $encoded = HTML::Entities::encode($a);
     $decoded = HTML::Entities::decode($a);

   The module can also export the %char2entity and the %entity2char hashes
which contain the mapping from all characters to the corresponding
entities.

COPYRIGHT
=========

   Copyright 1995-2001 Gisle Aas. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

embed Perl code in your HTML docs
*********************************

NAME
====

   Embperl FAQ - embed Perl code in your HTML docs

CONTENTS
========

`"Downloading, Compiling & Installing"' in this node
`"Common Problems"' in this node
`"Common Questions"' in this node
`"Escaping & Unescaping"' in this node
`"Debugging"' in this node
`"Customizing"' in this node
`"Optimizing & Fine Tuning"' in this node
`"Additional Help"' in this node
Downloading, Compiling & Installing
===================================

   For basics on downloading, compiling, and installing, please see the
`INSTALL' in this node in the Embperl documentation. Please be sure to
load Embperl at server startup - if you do not, various problems may
result. An exception to that rule is when you have compiled mod_perl with
*USE_DSO*. In this case you *must not* load Embperl at server statup,
neither via an use in your startup.pl file, nor via PerlModule from your
httpd.conf.

Is there a binary distribution of Embperl for Unix?
---------------------------------------------------

   No.

Is there a binary distribution of Embperl for Win32?
----------------------------------------------------

   Win NT/95/98 binarys for Apache/perl/mod_perl/Embperl are available
from ftp://theoryx5.uwinnipeg.ca/pub/other/ . A european mirror is at
http://www.robert.cz/misc/ .

I want to run Embperl with mod_perl under Apache. In what order should I do the compiling?
------------------------------------------------------------------------------------------

   First mod_perl and Apache, then Embperl.

I'm getting:
------------

   ../apache_1.3.0/src/include/conf.h:916: regex.h: No such file or
directory

   Try compiling Embperl again, like this:

     make DEFS=-DUSE_HSREGEX

I'm trying to build HTML::Embperl, and while running 'make' i get:
------------------------------------------------------------------

   cc: Internal compiler error: program cc1 got fatal signal 11 make: ***
[epmain.o] Error 1

   GCC croaking with signal 11 frequently indicates hardware problems.
See http://www.bitwizard.nl/sig11/

I have a lot of errors in 'make test' from mod_perl when using Embperl
----------------------------------------------------------------------

   Try recompiling Perl and all modules - this can sometimes make those
annoying error messages disappear!

How can I prevent 'make test' from running some of the tests?
-------------------------------------------------------------

   For example, I don't allow CGI scripts, so 'make test' fails at CGI. How
do I run just the other tests?

   Try:

     $ make test TESTARGS="--help"
     # and for just offline and mod_perl:
     $ make test TESTARGS="-hoe"

Running 'make test' fails with an error message at loading of Embperl  (even though mod_perl compiled and tested cleanly!)
--------------------------------------------------------------------------------------------------------------------------

   see "I get symbol ap_* undefined/cannot resolve ap_*"

I get symbol ap_* undefined/cannot resolve ap_*
-----------------------------------------------

   This can happen when symbols in the Apache binary can not be found or
are not being resolved correctly.

   Some OS do this (for instance bsdos), and it can also happen if your
Apache binary is set to strip symbol information out from binaries.

   Try:

  1. make clean

  2. perl Makefile.PL NOTE: answer _no_ to mod_perl support. (This is
     important!)

  3. make test
        If that works, it means that your installation of Embperl is OK,
but is having problems resolving symbols with Apache.

   Try rebuilding Apache and mod_perl from scratch, and make sure you do
not strip symbols out of either.

   On some systems/linker you need to tell the linker explicitly to export
such symbols. For example FreeBSD linker needs the `-export-dynamic'
option.

   If you don't succeed with this approach, try statically linking Embperl
to Apache/mod_perl (please see the next question for step-by-step
instructions on how to do this).

How can I build a statically-linked copy of Embperl with mod_perl  support?
---------------------------------------------------------------------------

  1. go to your mod_perl directory, change to src/modules/perl and edit
     the Makefile so that it contains the line
          #STATIC_EXTS = Apache Apache::Constants HTML::Embperl

  2. add a definition for EPDIR and change the ONJ= line so that it looks
     like this: EPDIR=/usr/msrc/embperl OBJS=$(PERLSRC:.c=.o)
     $(EPDIR)/Embperl.o $(EPDIR)/epmain.o $(EPDIR)/epio.o (EP
     DIR)/epeval.o $(EPDIR)/epcmd.o $(EPDIR)/epchar.o $(EPDIR)/eputil.o

  3. go to the mod_perl directory and run
          perl Makefile.PL

  4. go to the Embperl directory and do
          make clean
          perl Makefule.PL
          make

     (to compile in mod_perl support)

  5. go back to the mod_perl directory and remake Apache by typing
          make

     Now you have successfully built a httpd with statically-linked
     Embperl.

     NOTE: If you want to stop here, you can skip to step 11. and run a
     'make install' in the Embperl directory to finish.

     But if you want to run Embperl tests and/or if you want to be able to
     use Embperl in offline or "vanilla" CGI mode, we need to continue:

  6. go back to the Embperl directory

  7. backup the file test/conf/config.pl

  8. now build Embperl again but _without_ mod_perl support
          make clean
          perl Makefile.PL
          make

  9. restore your saved config.pl to test/conf/config.pl (without this
     step, only the offline mode would be tested)

 10. run 'make test' for Embperl

 11. do 'make install' for Embperl
        NOTE: You should do it in this order, or it may not work.

   NOTE: It seems to be necessary to load Embperl at server startup,
either by PerlModule or in a PerlScript. See next question on how to do
this.

How do I load Embperl at server startup?
----------------------------------------

   You can load Embperl at server startup by PerlModule or in a startup.pl:

  1. edit your  srm.conf file to read:
          PerlModule HTML::Embperl

  2. edit your startup.pl file to read:
          use HTML::Embperl

        NOTE 1: Either of these approaches can often 'fix' SIGSEVs in any
mod_perl handler, not just Embperl.

   NOTE 2: When mod_perl is compiled as loadable module (i.e. with USE_DSO)
you *must not* load Embperl at server startup time!

make test fails with a SIGxxxx, how can I obtain a stack backtrace from gdb?
----------------------------------------------------------------------------

   The eaiest way is

     make install            -> if Embperl is installed, it's easier
     gdb perl                -> start the debugger with perl binary
     set args test.pl        -> set the arguments for perl
     r                       -> start the program

     -> Here you should receive the signal

     share                   -> makes sure all symbols are really loaded
     bt                      -> show the backtrace

   To get some more information it would be a good idea to compile Embperl
with debugging infomation enabled. Therefor do

How do I build Embperl with debugging informations
--------------------------------------------------

edit the Makefile
search for the line starting with 'CC = ' add the -g switch to the end of the line
search for the line starting with 'LDDFLAGS = ' add the -g switch to the end of the line
type make to build Embperl with debugging infomation
   now start the gdb as decribed before.

make test fails with SIGXFSZ
----------------------------

   This may occur when the filesize limit for the account, either test is
running as or the test httpd, is too small. Embperl make test generates a
really large logfile! Yu must increase the filesize limit for that
accounts.

Embperl on SCO Unix
-------------------

   >From Red Plait

   My OS is SCO Unix 3.2v4.2, Apache 1.3.4, perl 5.004_4, mod_perl 1.18 and
Embperl-1.1.1

   I done following:

  1. I made HTML-Embperl-1.1.1 with no mod_perl support ( when I builded it
     with mod_perl 1.18 I can`t link it because it don`t finds ap_XXX
     functions.  When I manually insert src/main/libmain.a from Apache
     1.3.4 I got message "Symbol main is multiple defined in
     /src/main/libmain.a. and perlmain.o" ). Then I "make test" - all
     tests was O`k. After this I "make clean", "perl Makefile.pl" with
     mod_perl support and "make install"

  2. I installed mod_perl and "perl Makefile.PL", then "make"

  3. because I have`nt dynamical loading ( very old and buggy OS ) I had to
     manually change src/modules/perl/perlxsi.c to insert bootstraps
     function`s and it`s invocations and also /src/Makefile to manually
     insert libXXX.a libraries

  4. In access.conf I insert code:
          PerlModule HTML::Embperl
          <Directory /my_dir>
           SetHandler perl-script
           PerlHandler HTML::Embperl::handler
          </Directory>

Embperl and mod_perl on AIX
---------------------------

   You need at least mod_perl 1.22. For mod_perl 1.22 and higher Embperl
should compile out of the box on AIX. If you run into problems with
undefined symbols (like `ap_*') make sure you have the newest mod_perl
version (as of this writing this is mod_perl 1.24_01).

Embperl does not write to the logfile, because of missing permissions of the user Apache runs as.
-------------------------------------------------------------------------------------------------

   The apache server is started as root, then set the effective uid to
user "www", who can then write to the embperl logfile (owned by root) file
handle that is passed along.  However, if this log file handle is later
accidentally closed, then reopen, the www user would have problem writing
to it?

   The reopen is only done when the logfile name changes. As log as you
don't change the name on the logfile, the logfile will stay open.

   The problem (in this case) is, that Embperl init function ,(Init in
epmain.c) calls OpenLog will an second argument of zero. Which will only
save the filename. The log will actually opened on the first write to it
(or at the start of the first request). At this time your Apache has
alreay switch to user www. This is done to allow to change the logfile
name before an request, but after the init is already called (which is
done when you or Apache "use" the module)

   The current solutions is to write something to the log, before Apache
changes it's user (i.e. in the startup.pl)

Is it possible to install EmbPerl into a private directory on my Unix/Linux Internet Service Provider account of which I have no root privilege?
------------------------------------------------------------------------------------------------------------------------------------------------

   Like any other Perl module it can. Read "perldoc ExtUtils::MakeMaker",
to see which parameters are needed for Makefile.PL to change the
installation directory. Additionally, you have to change the @INC path to
contain your private directory and possibly paths to other object files.

   Here are the brief details:

   Requirements:

   * At least Perl 5.004_04

   * cc or gcc (your isp must give you access to the gcc compiler)

   * URI

   * MIME::Base64

   * HTML::Parser

   * HTML::HeadParser

   * Digest::MD5

   * libnet

   * libwww

   * File::Spec (I believe you may have to install this too if you are
     using Perl 5.004_04 as it may not be a standard module)

   *Direction*:

   * Get your copy of EmbPerl (HTML-Embperl-x.x.tar.gz)

   * % tar -xvzf HTML-Embperl-x.x.tar.gz

   * % cd HTML-Embperl-x.x

   * % perl Makefile.PL PREFIX=/to/your/private/dir

   * % make

   * % make test

   * % make install

   Replace /to/your/private/dir with the path to the directory you want
the  module to be placed in. Now preface your CGI scripts with something
like  this:

   [Alternative 1]

     #!/usr/bin/perl -wT
     use CGI::Carp qw( fatalsToBrowser ); #recommend using this to report errors on die or warn to browser

     use lib '/to/your/private/dir/lib'; #for FILE::Spec
     use lib '/to/your/private/dir/'; #to find Embperl
     use lib '/to/your/private/dir/i386-linux/auto/HTML/Embperl'; #to find Embperl compiled stuff

     #if for some very weird reason the above 'use lib' pragma directive doesn't work, see Alternative 2

     use HTML::Embperl;

     #your code below ...

   [Alternative 2]

     #!/usr/bin/perl -wT
     use CGI::Carp qw( fatalsToBrowser ); #recommend using this to report errors on die or warn to browser

     BEGIN {
     	unshift @INC, '/to/your/private/dir/lib'; #for FILE::Spec
     	unshift @INC, '/to/your/private/dir/'; #to find Embperl
     	unshift @INC, '/to/your/private/dir/i386-linux/auto/HTML/Embperl'; #to find Embperl compiled stuff
     }

     use HTML::Embperl;

     #your code below ...

   When you make test, you may encounter superfluous warnings, you may
want to change the test.pl that ships with EmbPerl from

     BEGIN
         {
         $fatal  = 1 ;

   to

     BEGIN
         {
         unshift @INC, '/to/your/private/dir/lib';
         $fatal  = 1 ;
         ...

   because the test.pl may not be able to find FILE::Spec if you have it
installed on a private directory for Perl 5.004_04.

   Do something similar to the important file embpcgi.pl as you do for all
your CGI scripts, like modifying the @INC as shown above, to allow perl to
find in particular the EmbPerl shared obj files...

   And when you invoke your CGI scripts like so,

   http://www.yourdomain.com/cgi-bin/embpcgi.pl/templateFiles/myNifty.epl

   the script should work.

Common Problems
===============

   The most common problems of all involve Escaping and Unescaping.  They
are so common, that an entire section on `"Escaping & Unescaping"' in this
node is devoted to them.

When I use a module inside a Embperl page, it behaves weired when the source changes.
-------------------------------------------------------------------------------------

   Nothing weird here. Everything is well defined. Just let us try to
understand how Perl, mod_perl and *Embperl* works together:

     "perldoc -f use" tells us:

     Imports some semantics into the current package from the named module,
     generally by aliasing certain subroutine or variable names into your
     package.  It is exactly equivalent to

        BEGIN { require Module; import Module LIST; }

     except that Module must be a bareword.

   So what's important here for us is, that use executes a require and
this is always done before any other code is executed.

     "perldoc -f require" says (among other things):

     ..., demands that a library file be included if it hasn't already
     been included.

   and

     Note that the file will not be included twice under the same specified
     name.

   So now we know (or should know) that mod_perl starts the Perl
interpreter once when Apache is started and the Perl interpreter is only
terminated when Apache is terminated. Out of these two things follows,
that a module that is loaded via use or require is only loaded once and
will never be reloaded, regardless if the source changes or not.

   So far this is just standard Perl. Things get's a little bit more
difficult when running under mod_perl (only Unix), because Apache forks a
set of child processes as neccessary and from the moment they are forked,
they run on their own and don't know of each other. So if a module is
loaded at server startup time (before the fork), it is loaded in all
childs (this can be used to save memory, because the code will actually
only reside once in memory), but when the modul is loaded inside the child
and the source changes, it could be happen, that one child has loaded an
ealier version and another child has loaded a later version of that
module, depending on the time the module is actualy loaded by the child.

   That explains, why sometimes it works and sometimes it doesn't, simply
because different childs has loaded different versions of the same module
and when you reload your page you hit different childs of Apache!

   Now there is one point that is special to Embperl to add.  Since
Embperl compiles every page in a different namespace, a module that
doesn't contains a `package foo' statement is compiled in the namespace of
the page where it is first loaded.  Because Perl will not load the module
a second time, every other page will not see subs and vars that are
defined in the loaded module. This could be simply avoided by giving every
module that should be loaded via use/require an explicit namespace via the
package statement.

   So what can we do?

   * If a module change, simply restart Apache. That's works always.

   * Use *Apache::StatInc.* This will do a stat on every loaded module and
     compare the modification time. If the source has changed the module
     is reloaded. This works most times (but not all modules can be
     cleanly reloaded) and as the number of loaded modules increase, your
     sever will slow down, because of the stat it has to do for every
     module.

   * Use do instead of require. do will execute your file everytime it is
     used. This also adds overhead, but this may be accpetable for small
     files or in a debugging environement. (NOTE: Be sure to check `$@'
     after a do, because do works like eval)

Why doesn't the following line work?
------------------------------------

     [+ $var . "<b>". $foo . "</b>". $bar +]

   See what we mean? This is an Escaping & Unescaping problem for sure. You
need to escape <b> as ' &lt;b&gt ' and you probably also need to read the
section on `"Escaping & Unescaping"' in this node...

I'm getting: "Glob not terminated at ..."
-----------------------------------------

   This might be a problem with `"Escaping & Unescaping"' in this node as
well.

My HTML is getting stripped out.
--------------------------------

   Sounds like a problem with Escaping & Unescaping again!

   Unless, of course, you have already read the section on Escaping &
Unescaping, and it is still happening... Like if you are using optRawInput
and your HTML is _still_ being stripped out...

I _am_ using optRawInput, and my HTML _is_ still being stripped out!
--------------------------------------------------------------------

   Aha! Well that's different! Never mind..

   It can be easy to accidentally set optRawInput too late in your code...

   Try setting it in an extra Perl block  ( [- $optRawInput = 1 -] )
earlier in the code, or in the server config, and see if that doesn't
solve the problem... (optRawInput must be set before the block that uses
it begins, as the block which uses it shouldn't be translated).

Help! I got a SIGSEGV! Ack!
---------------------------

   If Embperl is not compiled at server startup, it can cause error
messages, SEGfaults, core dumps, buffer overflow, etc - especially if you
are using another module inside an Embperl page. As far as anyone can tell,
this seems to be a Perl/mod_perl problem - but maybe not. If you have any
ideas, let me know.

   To see the steps for loading Embperl at server startup, please see the
section `"Downloading, Compiling & Installing"' in this node.

   NOTE: When mod_perl is compiled with *USE_DSO* it behaves vice versa
and you may get SIGSEGVs when Embper is loaded at server startup time.

I am having troubles with using Embperl in combination with Apache::Include inside a Apache::Registry script.
-------------------------------------------------------------------------------------------------------------

   This is a known problem, but it is a problem with mod_perl rather than
with Embperl. It looks like mod_perl clears the request_rec after the
first subrequest, so that it later doesn't know which subrequest was
intended (unless it's explicitly specified). Try using:

     Apache::Include->virtual("test.epl", $r);

   (instead of just Apache::Include->virtual("test.epl"); where $r is the
apache request rec)

I can't get PerlSendHeader to work under Embperl?
-------------------------------------------------

   You don't need PerlSendHeader when using Embperl - Embperl always sends
its own httpd header.

But how do I customize the header that Embperl is sending?
----------------------------------------------------------

   You'll find the answer to this and many other header issues  in the
`"Common Questions"' in this node section.

I can't figure out how to split a 'while' statement across  two [- -] segments
------------------------------------------------------------------------------

   That isn't surprising, as you cannot split Perl statements across
multiple [- -] blocks in Embperl :) You need to use a metacommand for
that. The [$while$] metacommand comes to mind... :)

   For a list of all possible metacommands, see the section on
`Meta-Commands|Embperl' in this node in the Embperl documentation.

     [$ while $st -> fetch $]
             #some html or other Embperl blocks goes here
     [$ endwhile $]

   Newer Embperl versions (1.2b3 and above) supports the [* *] which can be
used for such purposes.

     [* while ($st -> fetch) { *]
             #some html or other Embperl blocks goes here
     [* } *]

   While the later can use all Perl control structures, the first seems to
me more readable and is better debugable, because Embperl controls the
execution of the control structure it can do a quite better job in debug
logging.

My HTML tags like '<' '>' and '"' are being translated to &lt;, &gt; !!!
------------------------------------------------------------------------

   Hey! Not you again!? I thought we already sent you to the `"Escaping &
Unescaping"' in this node section of the FAQ?!?! ;)

Netscape asks to reload the document
------------------------------------

   If you have something like this in your source, it may be the problem:

     <META HTTP-EQUIV="content-type" CONTENT="text/html;charset=iso-8859-1">

   Netscape seems to have a problem in such cases, because the http header
is only content-type text/html, while the META HTTP-EQUIV has an additional
charset specified. If you turn optEarlyHttpHeader off, Embperl will
automatically set the http header to be the same as the META HTTP-EQUIV.

I get "Stack underflow"
-----------------------

   The problem often occurs, when you have a <table> tag in one file and a
</table> tag in another file and you both include them in a main page
(e.g. as header and footer). There are two workarounds for this problem:

  1. Set optDisableTableScan This will avoid that Embperl takes any action
     on tables. You can disable/enable this (also multiple times) inside
     the page with

          [- $optDisableTableScan = 1 -]

     If you put this at the top of your header/footer which you include
     with Execute, then the main page will still process dynamic tables.

  2. Add a <table> as comment Add the following to the top of the footer
     document:

          <!-- <table><tr><td> -->

     This will work also, because Embperl (1.x) will not scan for html
     comments

Common Questions
================

   The most common questions of all deal with `"Escaping & Unescaping"' in
this node  - they are so common that the whole next section is devoted to
them.  Less common questions are addressed here:

How can I get my HTML files to be converted into Perl code which, as a whole, could then be compiled as function so that I could, for  instance, fetch Perl docs from the Formatter table and compile them the way AUTOLOAD does.
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

   Embperl cannot covert your HTML into one piece of Perl-code, but you can
wrap the call to Execute into a Perl function and let AUTOLOAD call it.

I have an HTML page which is dynamically generated at runtime  and should be post-processed by Embperl. How can I do this?
--------------------------------------------------------------------------------------------------------------------------

  1. Generate the page within a normal CGI/Apache::Registry script and put
     the result into a scalar - then you can call HTML::Embperl::Execute
     to post-process your document. Execute can either send the document
     to the browser or put it into another scalar for further processing.

  2. Use EMBPERL_INPUT_FUNC (1.1b1 and above). With this configuration
     directive, you can specify a custom input function which reads the
     HTML source from the disk or even from a database. Embperl also
     provides the function ProxyInput, which allows you to get input from
     another web server altogether.

  3. Look at the module Apache::EmbperlChain, which is able to chain
     multiple modules, including Embperl, together.

How can I customise the header that Embperl is sending?
-------------------------------------------------------

   You can write it as

     <meta http-equiv="Content-Type" content="text/html">

   (Embperl will automatically insert all meta http-equiv tags into the
http header)

   or use %http_headers_out

     [- $http_headers_out{'Content-Type'} = 'text/html' -]

   or (only when running under mod_perl) you can use

     [- $req_rec -> content_type ('text/html') -]

Can I use Embperl to send cookies?
----------------------------------

   Yes. Embperl sends its own headers, so all you have to do to send
cookies is to remember to print an additional header.

   Example Code:

  1. in documents, add
          <META HTTP-EQUIV="Set-Cookie" CONTENT="[+ $cookie +] = [+ $value +]">

  2. or use %http_headers_out
          [- $http_headers_out{'Set-Cookie'} = "$cookie=$value" -]

  3. or - using mod_perl's functionality - use
          [- $req_rec ->  header_out("Set-Cookie" => "$cookie=$value"); -]

        NOTE: You make also take a look at Embperls (1.2b2 and above)
ability to handle sessions for you inside the %udat and %mdat hashes.

Can I do a Redirect with Embperl?
---------------------------------

   The following way works with mod_perl and as cgi:

     [- $http_headers_out{'Location'} = "http://www.ecos.de/embperl/" -]

   the status of the request will automaticly set to 301.

   or use the mod_perl function Apache::header_out.

   Example Code:

     [-
     use Apache;
     use Apache::Constants qw(REDIRECT);

     $req_rec->header_out("Location" => "http://$ENV{HTTP_HOST}/specials/");
     $req_rec->status(REDIRECT);
     -]

   If there is nothing more to do on this page, you may call exit directly
after setting the status.

Can I serve random GIFs with Embperl? (Will Lincoln Stein's GD.pm module work with Embperl??)
---------------------------------------------------------------------------------------------

   As always, there is more than one way to do this - especially as this
is more of a question of how you are coding your HTML than how you are
coding your Embperl.

   Here are some ideas:

  1. You could include an IMG tag which points to your cgi-bin, where a
     regular CGI script serves the graphics.

  2. You could be running Apache::Registry, which can generate on-the-fly
     GIFs using GD. (This is just the same as if you were including the GD
     image from a static page or from another CGI script, but it allows
     all of the appropriate logic to live in a single document, which
     might be appropriate for some Embperl users).
        If you think of another way, or come up with some sample code, I'd
love to hear from you, so that I could add it to the FAQ...

Can I use Embperl as a template for forms? Can I make form values persist (like with "vanilla" CGI)? Does Embperl rewrite my template file so that parameters of things like INPUT/TEXTAREA/SELECT persist?
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

   Yes. Your page design staff should just be able to say <input
name="foo"> and let the default attributes of "foo" be defined elsewhere -
for instance in a settings file. In this case, %fdat should be pre-set with
your default values. Setting $fdat{foo} = "abc" will cause Embperl to
change the above code to <input name="foo" value="abc">.

Does Embperl automatically add HIDDEN fields?
---------------------------------------------

   The [$hidden$] metacommand creates hidden fields for every entry in
%fdat which was not used by any other input tag so far.

   You can also try something like this:

     [-
     $fdat{foo} = "abc" ;
     $fdat{bar} = "xyz" ;
     -]

     <input name="foo">

     [$hidden$]

   and Embperl will create:

     <input name="foo" value="abc">
     <input type=hidden name="bar" value="xyz">

   For a list of all possible metacommands, see the section on
`Meta-Commands|Embperl' in this node in the Embperl documentation.

What about security? Is Embperl Secure?
---------------------------------------

   Just like anything else, Embperl is as secure as you make it.  Embperl
incorporates Safe.pm, which will make it impossible to accidentally access
other Packages - it also permits the Administrator to disable Perl
opcodes, etc.

   For more on security, please see `Embperl' in this node in the Embperl
documentation.

Is there any plan to make Embperl an Object so someone could subclass it and override certain of its methods?  (For example, I'd like to let it parse the file for me, but then let me control the manipulation of the form tags.)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

   Embperl is going to be an Object from version 1.2b1. This, among other
things, make it re-entrant, so that you will be able to call Execute from
within an Embperl page. It will also mean that Embperl will come with
hooks, which will allow you to alter or change the way Embperl processes
code. The details have not all been worked out yet, but I'm working on
it... :)

Are Embperl routines currently pre-compiled or even cached, or are only fragments cached?
-----------------------------------------------------------------------------------------

   All embedded Perl code is compiled the first time it is executed and
cached for later use. The second time the code is executed, only the
precompiled p-code is called.

   Every code block is compiled as a single subroutine. The HTML text
between the Perl block is still read from the file.

Why are Perl blocks broken up into single subroutines?
------------------------------------------------------

  1. It makes it easier to process the HTML tags between the Perl blocks -
     this gives you more control over what's happening

  2. If you compiled _everything_ to Perl, you would hold all of the HTML
     text in memory, and your Apache child processes would grow and
     grow... But often-accessed documents are still held in memory by
     your os disk cache, which is much more memory-efficient.

  3. There is only so far that you can go with precompiling until you
     reach the point of diminishing returns. My guess is that converting
     dynamic tables and other HTML processing to Perl at this point in
     Embperl's development would actually slow down operation.

Can I pass QUERY_STRING information to an HTML::Embperl::Execute call?
----------------------------------------------------------------------

   With Embperl 1.0 and higher, you can do this. QUERY_STRING is set as
$ENV{QUERY_STRING} by default. Alternatively, you can use the fdat
parameter to pass values to %fdat.

How to include other files into Embperl pages?
----------------------------------------------

   I am using embedded Perl on my site and am curious if I can use it for
server side includes.  I want to embed the contents of file x.html into
file y.html such that whenever I change x.html, displaying y.html will
also reflect this change. How do I do it using embedded perl?

   You need Embperl 1.2b4 or above. Then you can say inside of y.html:

     [- Execute ('x.html') -]

EmbPerl iteration without indexing
----------------------------------

   I have a rather large table in a database which I'd like to display
using EmbPerl.  All of the examples show a process of fetching all the data
first, then iterating through it using $row and $col, like this:

     [-
     $sth = $dbh -> prepare ("select * from $comptbl order by SubSystem");
     $sth -> execute;
     $dref = $sth -> fetchall_arrayref;
     -]
     <TABLE>
        ... $dref -> [$row][0] ...
     </TABLE>

   I'd prefer to fetch the data one row at a time, how can I do this?

   For solution 1 you may write

     <table>
     [$while $rref = $sth -> fetch $]
         <tr>....</tr>
     [$endwhile$]
     </table>

   Solution 2 should work like this

     <table>
        <tr> [- $dummy = $row ; $rref = $sth -> fetch -]
                ....
        </tr>
     </table>

   The table ends when the expression where $row is used in some way
returns <undef>. So also there is no releation between $row and the fetch,
both conditions are met.

How to display arrays with undef values in it?
----------------------------------------------

     I'm doing a search on a table where some of the columns have NULL and
     non-NULL values.  DBIx::Recordset has no problem reading this values
     The problem is that I then tried to print these values
     out in a table using Embperl's  table feature, like this.
      <TABLE>
      <TR>
      <TD>$set[$row]{column_name1}</TD>
      <TD>$set[$row]{column_nameN}</TD>
      </TR>
      The problem is that I got 5 rows instead of the 15 that I was expected.  I
      have been  trying all kinds of tweaks to the arguments to the Search
      function and getting nowwhere, until I re-read the Embperl docs.  Embperl
      will not print out a table row if one of the columns has an
      expression that
      is undefined.  This is a problem since DBIx::Recordset (and DBI)
      natually uses undef to represent a NULL value for a column.  So I made a
      slight modification to my embperl code.
      <TABLE>
      <TR>
      <TD>defined($set[$row]{column_name1}) ? $set[$row]{column_name1} :
      "UNDEF"</TD>
                                      .   .   .
      <TD>$set[$row]{column_nameN} ? $set[$row]{column_nameN} : "UNDEF"</TD>
      </TR>
     Now all 15 rows appear as expected, with "UNDEF" representing the NULL
     values in the database.

   Another way top solve you problem may be:

     <TABLE>
     <TR>
     [- $r = $set[$row] -]
     <TD> [+ $r -> {column_name1} +] </TD>
                                     .   .   .
     <TD> [+ $r -> {column_nameN} +] </TD>
     </TR>

   This will only refer one time to $row and the expression is defined, as
long as the row could be fetched from the db. All NULL fields will be
displayed as empty table cells.

Escaping & Unescaping
=====================

Escaping & Unescaping Input
---------------------------

   By default, Embperl removes all HTML tags from the Perl source. It does
this because many high-end WYSIWYG HTML Editors (like MS Front Page)
insert HTML tags like <FONT> and <COLOR> in rather random places (like in
the middle of your Perl code). This Embperl feature keeps things like

     [- $var  = 1; <br>
         $foo = 2 -]

   permissable, so that you can enter Perl code while you mark up pages in
an editor, all at once.  In this example, Embperl would remove the
unnecessary <br> tag and, therefore, make Perl happy. And if Perl is
happy, we are all happy.

   It is not difficult to change this behavior, if you are the kind of
person who codes HTML in an ascii editor (like vi or emacs).

   If you use a high-level HTML editor, you shouldn't have any problems
with input escaping, because the editor will, for example, write a '<' as
'&lt;' in the HTML code. Embperl translates this back to '<' and therefore
it knows that this wasn't an HTML tag which should be removed.

   Problems with input escaping only occur if you use an ascii editor.
Then you will need to escape input (see the next section for details on
how to do this).

   To see the exact steps taken by Embperl to process a Perl-laden
document, please see the section `Inside Embperl|Embperl' in this node in
the Embperl documentation.

Ways To Escape Input:
---------------------

  1. Escape it ->  \<H1> NOTE: Inside double quotes you will need to use
     \\ (double backslash), since Perl will remove the first Escape itself.

     Example: In most cases '\<tr>' but inside double-quotes "\\<tr>"

  2. Turn off Escaping for all input by setting the optRawInput in
     EMBPERL_OPTIONS

  3. Learn to avoid using HTML tags inside Perl code. Once you get the
     hang of it, you'll love it.
        Here is one example of how to do it:

     [- $output = "<bold>Hello world</bold>" -]
     [+ $output +]

   write

     [- $output = "Hello world<bold>" -]

   this outputs

     Hello world

   or

     <bold>[+ $output +]</bold>

   this outputs

     <bold>Hello world</bold>

   And here is another example of how to do it:

     [-
     @a = ('a', 'b', 'c') ;
     foreach $i (0..2)
         {
         $output. = "<tr><td>Row $a[$i]</td></tr>" ;
         }
     -]
     <table>
     [+ $output +]
     </table>

   The output here would be:

     <table>Row aRow bRow c</table>

   The Embperl version is

     [-
     @a = ('a', 'b', 'c') ;
     -]
     <table>
     <tr><td>Row [+ $a[$row] +]</td></tr>" ;
     </table>

   The output will be

     <table>
     <tr><td>Row a</td></tr>" ;
     <tr><td>Row b</td></tr>" ;
     <tr><td>Row c</td></tr>" ;
     </table>

   And another: This elegant solution shows you how to take advantage of
Embperl's ability to create dynamic tables:

     [-
     use DBI;

     my $dbh =
     DBI->connect("DBI:mysql:database:localhost","Username","Password") ||
     die($!);

     $hstmt = $dbh->prepare("select ID, Heading from Shops order by Heading");
     $hstmt->execute();
     $dat = $hstmt->fetchall_arrayref() ;
     $hstmt->finish();
     $dbh->disconnect();
     -]
     <table border=1>
     <tr><td>[+ $$dat[$row][$col] +]</td></tr>
     </table>

   This HTML code will then display the contents of the whole array.

Escaping & Unescaping Output
----------------------------

   Embperl will also escape the output - so <H1> will be translated to
&lt;H1&gt;

   To see the exact steps taken by Embperl to process a Perl-laden
document, please see `Inside Embperl|Embperl' in this node in the Embperl
documentation.

Ways To Escape Output:
----------------------

  1. Escape it -> \\<H1>
          (You need a double backslash \\, because
          the first one is removed by Perl and the second by Embperl.

  2. set $escmode = 0 -> [- $escmode = 0 ; -]

  3. set SetEnv EMBPERL_ESCMODE 0 in your srm.conf

Debugging
=========

I am having a hard time debugging Embperl code
----------------------------------------------

   Have you, umm, checked the error log? ;)

   Have you tried setting debug flags higher by resetting EMBPERL_DEBUG in
the server config files? (And still higher? :)

   dbgMem isn't usually very useful as it always outputs a lot of
allocation.  dbgFlushLog and dbgFlushOutput should be used if (and only
if) you are debugging SIGSEGVs.

   For easy debugging, you can tell Embperl to display a link at the top of
each page to your log file. Then every error displayed in an error page is
a link to the corresponding position in the logfile, so you can easily
find the place where something is going wrong

   For more on using HTML links to the Embperl error log, see `Embperl' in
this node in the Embperldocs.

Embperl is running slow.
------------------------

   There are some debugging settings which may cause Embperl to drastically
slow down. If you are done with debugging, set debugging bits back to
normal.

   Also, using dbgFlushLog and dbgFlushOutput will make execution much
slower. These are only intended for debugging SIGSEGVs.

   Never set all debugging bits!

How can I improve Embperl's performance?
----------------------------------------

  1. Load Embperl at server startup. This will cause     UNIX systems to
     only allocate memory once, and not     for each child process. This
     reduces memory use,     especially the need to swap additional memory.

  2. Disable all unneeded debugging flags. You should never set
     dbgFlushLog dbgFlushOutput, dbgMem and dbgEvalNoCache in a
     production environment.

  3. You may also want to take a look at the available options     you can
     set via EMBPERL_OPTIONS. For example optDisableChdir, will     speed
     up processing because it avoid the change directory before     every
     request.

Customizing
===========

How can I fiddle with the default values? How can I override or alter this or that behavior?
--------------------------------------------------------------------------------------------

   Usually, defaults are set in a way that is likely to make most sense
for a majority of users. As of version 1.0, Embperl allows much more
flexibility in tweaking your own default values than before. Take a look
at EMBERPL_OPTIONS.

I'd like to (temporarily) disable some of Embperl's features.  What can be customized?
--------------------------------------------------------------------------------------

  1. Use optDisableHtmlScan to disable processing of html tags. If this is
     set, Embperl will only pay attention to these types of  constructs:
     [+/-/!/$ .... $/!/-/+]

  2. optDisableTableScan, optDisableInputScan and optDisableMetaScan can
     be used to disable individual parts of HTML processing.  You may set
     these flags in your server config, or at runtime:

          [+ $optDisableHtmlScan = 1 +]
          <table> foo </table>
          [+ $optDisableHtmlScan = 0 +]

How can I disable auto-tables?
------------------------------

   Set optDisableTableScan in EMBPERL_OPTIONS

How can I change predefined values like $escmode from my Toolbox module?
------------------------------------------------------------------------

     $HTML::Embperl::escmode = 0 ;

   Predefined values in Embperl are simply aliases for $HTML::Embperl::foo
(for instance, $escmode is an alias for $HTML::Embperl::escmode)

How can I customize the header that Embperl is sending?
-------------------------------------------------------

   You'll find the answer to this and many other header issues  in the
`"Common Questions"' in this node section.

How can I use a different character set? ASCII values over 128 are showing up as ? (question marks)!
----------------------------------------------------------------------------------------------------

   This is caused by the translation of characters to HTML escapes.
Embperl translates them to escapes which are then sometimes not understood
by the browser, which may display a "?" instead, because it is using the
wrong character set.

   If you want to use the escaping features of Embperl in this case, you
have to adapt the file `epchar.c' to your character set.

   The distribution contain already an `epchar.c.iso-latin-2' from Jiri
Novak which is an replacement for epchar.c for the iso-8859-2
(iso-latin-2) character set.  If you want to use iso-latin-2, simply
renmae `epchar.c.iso-latin-2' to `epchar.c'.  There is also an file
`epchar.c.min' from Sangmook Yi, which leaves all chars above 128 untouch,
which is especialy usefull for two byte charsets.

   This file contains three tables:

   Char2Html []   Convert characters to html escape

   Char2Url  []   Convert characters to url escapes (do not change this
one!!)

   Html2Char []   Convert html escapes to characters

   You need to change the first and the last tables. Do not change the
second table!!

   Please make sure Char2Html contains one entry (and only one entry) for
each of the 256 ascii codes (with none left undefined) in the right order,
and that Html2Char is sorted by html escape.

   If somebody generates new tables for national character sets, please
send a copy to the author, so it can be included it in future versions of
Embperl.

Optimizing & Fine-Tuning
========================

How can I be sure that Embperl is re-compiling my page template (and the Perl blocks contained in it) only when needed, and not each time?
------------------------------------------------------------------------------------------------------------------------------------------

   As long as your input file's time stamp stays the same, Embperl will
only compile the script the first time it's called. When you use the
Execute function, Embperl will recompile the script only if the input file
and mtime paramenters have changed since the last time the script was
called.

   You can verfiy this by setting dbgDefEval. Now, every time a Perl block
is compiled, Embperl logs a line starting with DEF:. You will see this line
only on the first request.  The cached Perl blocks are stored as a set of
subroutines in the namespace of the document. (HTML::Embperl::DOC::_<n> is
the default) Look at the logfile to see the actual name.

How can I pre-compile pages, so that each httpd child doesn't  have to have its own separate copies of the pre-compiled pages?
------------------------------------------------------------------------------------------------------------------------------

   To pre-compile pages, just call Execute once for every file at server
startup in your startup.pl file.

In what namespace does Embperl store pre-compiled data?
-------------------------------------------------------

   The cached Perl blocks are stored as a set of subroutines in the
namespace of the document. (HTML::Embperl::DOC::_<n> for default) Look at
the logfile to see the actual name.

I have both Embperl and ordinary Perl processes running. The docs  say that Embperl uses a CGI.pm instance in its own internal processing, but they don't say how to control it. How can I get Embperl to use *my*  CGI.pm object instead of creating its own?
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

   Embperl only creates a CGI objects to process multipart form data (from
fileupload). In all other cases Embperl doesn't use CGI.pm. There is no
way to change this behaviour, or access the internal CGI object in case of
file-uploads.

Additional Help
===============

Where can I get more help?
--------------------------

   You can get free support on the mod_perl mailing list. If you need
commercial support (with a guarantee for response time or a solution) for
Embperl, or if you want a web site where you can run your Embperl/mod_perl
scripts without setting up your own web server, please send email to
info@ecos.de.

   Please also see the section `Embperl' in this node in the Embperl
documentation.

SEE ALSO
========

   some links here

AUTHOR
======

   Gerald Richter <richter@ecos.de>

   Edited by Nora Mikes <nora@radio.cz>

Main features of HTML::Embperl 1.3
==================================

   * Lets you embed Perl code into HTML documents. Perl code is evaluated
     at the server side and the result is sent to the browser.

   * Offers various meta-commands for conditional and loop processing of
     the HTML documents.

   * Automatically generates dynamic HTML tables/lists from Perl arrays or
     function calls (e.g. DBI fetch)

   * Form data send to your document is placed in a hash

   * Automatically inserts data from the form hash into HTML input,
     textarea and select tags

   * Understands HTML and URL escaping and unescaping

   * Handles per-user and per-module persistent session data for you.  All
     you need to do is store and retrieve them to and from a special hash.

   * Allows you to build your web-site out of components. Frequently used
     elements can be defined once and included in every page.

   * EmbperlObject allows you to define the standard layout of your site
     just once and includes the neccessary components based on the uri.
     Your HTML documents just have to contain the unique stuff and not the
     common stuff like headers/footers or navigation bars. Also these
     common elements can be overwritten in each subdirectory.

   * Gives you the possibility to build libraries with a set of frequently
     used Elements or components, and make them available to the whole
     web-site in the same way as Perl modules are - well, modularized.

   * Supports debugging of pages by generating a very detailed log file
     and making it accessible via the browser with a single click.

   * Generates verbose error pages in which every error can link to the
     log file. This is ideal for debugging.

   * Offers a lot of options for maximum configurability according to your
     personal tastes and needs.

   * Fully integrated into Apache and mod_perl to acheive the best
     performance. Can also run as a CGI-script, offline or called from
     another Perl program.

   * The Perl module DBIx::Recordset offers high level, easy to handle
     database access for Embperl.

   * If you are concerned about security you can configure Embperl to use
     Safe.pm. This way, your documents can run in a safe namespace which
     can allow or disallow certain Perl opcodes.

   * *HTML::Embperl::Mail* gives you the possibility to send the result
     directly to a email address

Wesentliche Features von HTML::Embperl 1.3
==========================================

   * Erlaubt das Einbetten von Perlcode in HTML Dokumente. Der Perlcode
     wird im Server ausgeführt und das Ergebnis zum Browser geschickt.

   * Stellt verschiedene Meta Commands zur bedingten und iterativen
     Verarbeitung von HTML Dokumenten zur Verfügung.

   * Erzeugt automatisch dynamische Tabellen/Listen aus Perl Arrays oder
     Funktionsaufrufen (z.B. DBI fetch)

   * Formulardaten die an ein Embperl Dokument gesandt werden sind einfach
     über einen Hash zugreifbar.

   * Fügt automatisch Daten aus dem Formularhash in HTML Input, Textarea
     und Select Tags ein.

   * Versteht HTML und URL Kodierung/Dekodierung.

   * Stellt Pro-Benutzer und Pro-Seite persitente Sessiondaten zur
     Verfügung.  Dafür ist es lediglich nötig die Daten in einem spezielle
     Hash abzulegen.

   * Ermöglicht das Erstellen von Websites aus Komponenten. Oft benutzte
     Elemente können einmal definiert und in jede Seite eingefügt werden.

   * EmbperlObject erlaubt es das standart Layout einer Website lediglich
     einmal zu definieren und EmbperlObject sorgt dafür das die passenden
     Komoponeten an die entsprechenden Stellen eingefügt werden. Die
     eigentlichen Seiten enthalten nur noch den tatsächlichen Inhalt und
     nicht gemeinsamme Elemente wie Kopf- und Fußbereich oder
     Navigationsleisten. Diese gemeinsammen Bereiche können weiterhin je
     Unterverzeichnis überschrieben werden.

   * Erlaubt Bibliotheken mit oft benutzten Elementen zu erstellen und
     diese der ganzen Website, wie normale Perlmodule, zur Verfügung zu
     stellen .

   * Unterstüzt das Debuggen von Seiten durch Erzeugen einer detaillierten
     Logdatei, die mittels eines einzigen Klicks vom Browser aus betrachtet
     werden kann.

   * Erzeugt ausführliche Fehlerseiten, wobei jeder Fehler ein Link an die
     richtige Stelle in die Logdatei sein kann.

   * Bietet eine ganze Reihe Optionen zur Konfigurierung entsprechend den
     persönlichen Vorlieben.

   * Vollständig integriert in Apache und mod_perl, um die beste
     Performance zu erreichen. Kann auch als CGI Skript laufen, Offline
     ausgeführt werden oder von anderem Perlprogrammen/-modulen aufgerufen
     werden.

   * Das Perlmodule DBIx::Recordset bietet einen hochwertigen, einfach zu
     handhabenden, Datenbankzugriff für Embperl.

   * Wenn Sicherheit ein Problem darstellt, ist es möglich Embperl so zu
     konfigurieren, daß es Safe.pm nutzt. Dadurch entstehen sichere
     Namensräume und einzelne Perl Opcode können gesperrt werden.

   * *HTML::Embperl::Mail* ermöglicht es das Ergebnis direkt an eine E-Mail
     Adresse zu versenden.

Populates HTML Forms with CGI data.
***********************************

NAME
====

   HTML::FillInForm - Populates HTML Forms with CGI data.

DESCRIPTION
===========

   This module automatically inserts data from a previous HTML form into
the HTML input, textarea and select tags.  It is a subclass of
HTML/Parser, and uses it to parse the HTML and insert the
values into the form tags.

   One useful application is after a user submits an HTML form without
filling out a required field.  HTML::FillInForm can be used to redisplay
the HTML form with all the form elements containing the submitted info.

SYNOPSIS
========

   This examples fills data into a HTML form stored in `$htmlForm' from
CGI parameters that are stored in $q.  For example, it will set the value
of any "name" textfield to "John Smith".

     my $q = new CGI;

     $q->param("name","John Smith");

     my $fif = new HTML::FillInForm;
     my $output = $fif->fill(scalarref => \$html,
     			  fobject => $q);

METHODS
=======

new
     Call new() to create a new FillInForm object:

          $fif = new HTML::FillInForm;

fill
     To fill in a HTML form contained in a scalar $html:

          $output = $fif->fill(scalarref => \$html,
                     fobject => $q);

     Returns filled in HTML form contained in $html with data from $q.  $q
     is required to have a param() method that works like CGI's param().

          $output = $fif->fill(scalarref => \$html,
                     fdat => \%fdat);

     Returns filled in HTML form contained in $html with data from `%fdat'.
     To pass multiple values using `%fdat' use an array reference.

     Alternately you can use

          $output = $fif->fill(arrayref => \@array_of_lines,
                     fobject => $q);

     and

          $output = $fif->fill(file => 'form.tmpl',
                     fobject => $q);

CALLING FROM OTHER MODULES
==========================

Apache::PageKit
---------------

   To use HTML::FillInForm in Apache/PageKit, is
easy.  It is automatically called for any page that includes a <form> tag.

Apache::ASP v2.09 and above
---------------------------

   HTML::FillInForm is now integrated with Apache::ASP.  To activate, use

     PerlSetVar FormFill 1
     $Response->{FormFill} = 1

Apache::ASP v2.08 and below
---------------------------

   To use HTML::FillInForm, put the following in global.asa

     sub fillin {
       my $args = shift;
       my $html = shift;
       my $fif = new HTML::FillInForm;
       my $output = $fif->fill(
                              scalarref => \$html,
                              fdat      => $Apps::Param,
                              );
       $Response->Write($output);
     }

   Note $Apps::Param is set to either the querystring or form data.
Replace with $Request->QueryString or $Request->Form if you wish.

   Then put something like this in your apache configuration:

     XMLSubsMatch fillin

   Finally, surround your forms like this:

     <fillin>
       <form>
         <input name="myfield">
       </form>
     </fillin>

   See http://forum.swarthmore.edu/epigone/modperl/malskalko for more
details.

SEE ALSO
========

   See HTML/Parser,

VERSION
=======

   This documentation describes HTML::FillInForm module version 0.10.

BUGS
====

   This module has not been tested extensively.  Please submit any bug
reports to tjmather@anidea.com.

NOTES
=====

   Requires Perl 5.005 and HTML/Parser, version 3.08.

   I wrote this module because I wanted to be able to insert CGI data into
HTML forms, but without combining the HTML and Perl code.  CGI.pm and
Embperl allow you so insert CGI data into forms, but require that you mix
HTML with Perl.

AUTHOR
======

   (c) 2000 Thomas J. Mather, tjmather@alumni.princeton.edu

   All rights reserved. This package is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

CREDITS
=======

   Fixes, Bug Reports, Docs have been generously provided by:

     Patrick Michael Kane
     Tom Lancaster
     Ade Olonoh
     Tatsuhiko Miyagawa
     Paul Lindner

   Thanks!

Filter HTML text through the parser
***********************************

NAME
====

   HTML::Filter - Filter HTML text through the parser

NOTE
====

   This module is deprecated. HTML::Parser now provides the functionally
of `HTML::Filter' much more efficiently with the the default handler.

SYNOPSIS
========

     require HTML::Filter;
     $p = HTML::Filter->new->parse_file("index.html");

DESCRIPTION
===========

   `HTML::Filter' is an HTML parser that by default prints the original
text of each HTML element (a slow version of cat(1) basically).  The
callback methods may be overridden to modify the filtering for some HTML
elements and you can override output() method which is called to print the
HTML text.

   `HTML::Filter' is a subclass of HTML::Parser. This means that the
document should be given to the parser by calling the $p->parse() or
$p->parse_file() methods.

EXAMPLES
========

   The first example is a filter that will remove all comments from an
HTML file.  This is achieved by simply overriding the comment method to do
nothing.

     package CommentStripper;
     require HTML::Filter;
     @ISA=qw(HTML::Filter);
     sub comment { }  # ignore comments

   The second example shows a filter that will remove any <TABLE>s found
in the HTML file.  We specialize the start() and end() methods to count
table tags and then make output not happen when inside a table.

     package TableStripper;
     require HTML::Filter;
     @ISA=qw(HTML::Filter);
     sub start
     {
        my $self = shift;
        $self->{table_seen}++ if $_[0] eq "table";
        $self->SUPER::start(@_);
     }

     sub end
     {
        my $self = shift;
        $self->SUPER::end(@_);
        $self->{table_seen}-- if $_[0] eq "table";
     }

     sub output
     {
         my $self = shift;
         unless ($self->{table_seen}) {
     	  $self->SUPER::output(@_);
         }
     }

   If you want to collect the parsed text internally you might want to do
something like this:

     package FilterIntoString;
     require HTML::Filter;
     @ISA=qw(HTML::Filter);
     sub output { push(@{$_[0]->{fhtml}}, $_[1]) }
     sub filtered_html { join("", @{$_[0]->{fhtml}}) }

SEE ALSO
========

   See HTML/Parser,

COPYRIGHT
=========

   Copyright 1997-1999 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Class that represents HTML forms
********************************

NAME
====

   HTML::Form - Class that represents HTML forms

SYNOPSIS
========

     use HTML::Form;
     $form = HTML::Form->parse($html, $base_uri);
     $form->value(query => "Perl");

     use LWP;
     LWP::UserAgent->new->request($form->click);

DESCRIPTION
===========

   Objects of the `HTML::Form' class represents a single HTML <form> ...
</form> instance.  A form consist of a sequence of inputs that usually
have names, and which can take on various values.

   The following methods are available:

$form = HTML::Form->new($method, $action_uri, [[$enctype], $input,...])
     The constructor takes a $method and a $uri as argument.  The $enctype
     and and initial inputs are optional.  You will normally use
     HTML::Form->parse() to create new HTML::Form objects.

@forms = HTML::Form->parse($html_document, $base_uri)
     The parse() class method will parse an HTML document and build up
     `HTML::Form' objects for each <form> found.  If called in scalar
     context only returns the first <form>.  Returns an empty list if there
     are no forms to be found.

     The $base_uri is (usually) the URI used to access the $html_document.
     It is needed to resolve relative action URIs.  For LWP this parameter
     is obtained from the $response->base() method.

$form->push_input($type, \%attr)
     Adds a new input to the form.

$form->method( [$new] )
$form->action( [$new] )
$form->enctype( [$new] )
     These method can be used to get/set the corresponding attribute of the
     form.

$form->inputs
     This method returns the list of inputs in the form.

$form->find_input($name, $type, $no)
     This method is used to locate some specific input within the form.  At
     least one of the arguments must be defined.  If no matching input is
     found, undef is returned.

     If $name is specified, then the input must have the indicated name.
     If $type is specified then the input must have the specified type.  In
     addition to the types possible for <input> HTML tags, we also have
     "textarea" and "option".  The $no is the sequence number of the input
     with the indicated $name and/or $type (where 1 is the first).

$form->value($name, [$value])
     The value() method can be used to get/set the value of some input.  If
     no input have the indicated name, then this method will croak.

$form->try_others(\&callback)
     This method will iterate over all permutations of unvisited enumerated
     values (<select>, <radio>, <checkbox>) and invoke the callback for
     each.  The callback is passed the $form as argument.

$form->make_request
     Will return a HTTP::Request object that reflects the current setting
     of the form.  You might want to use the click method instead.

$form->click([$name], [$x, $y])
     Will click on the first clickable input (`input/submit' or
     `input/image'), with the indicated $name, if specified.  You can
     optinally specify a coordinate clicked, which only makes a difference
     if you clicked on an image.  The default coordinate is (1,1).

$form->form
     Returns the current setting as a sequence of key/value pairs.

$form->dump
     Returns a textual representation of the form.  Mainly useful for
     debugging.  If called in void context, then the dump is printed on
     STDERR.

INPUTS
======

   An `HTML::Form' contains a sequence of inputs.  References to the
inputs can be obtained with the $form->inputs or $form->find_input
methods.  Once you have such a reference, then one of the following
methods can be used on it:

$input->type
     Returns the type of this input.  Types are stuff like "text",
     "password", "hidden", "textarea", "image", "submit", "radio",
     "checkbox", "option"...

$input->name([$new])
$input->value([$new])
     These methods can be used to set/get the current name or value of an
     input.  If the input only can take an enumerated list of values, then
     it is an error to try to set it to something else and the method will
     croak if you try.

$input->possible_values
     Returns a list of all values that and input can take.  For inputs that
     does not have discrete values this returns an empty list.

$input->other_possible_values
     Returns a list of all values not tried yet.

$input->form_name_value
     Returns a (possible empty) list of key/value pairs that should be
     incorporated in the form value from this input.

$input->click($form, $x, $y)
     Some input types (currently "sumbit" buttons and "images") can be
     clicked to submit the form.  The click() method returns the
     corrsponding HTTP::Request object.

SEE ALSO
========

   See LWP, HTML/Parser, `webchatpp' in this
node

COPYRIGHT
=========

   Copyright 1998-2000 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Highlights fields in an HTML form.
**********************************

NAME
====

   HTML::FormHighlight - Highlights fields in an HTML form.

SYNOPSIS
========

     use HTML::FormHighlight;

     my $h = new HTML::FormHighlight;

     print $h->highlight( scalarref => \$form, fields => [ 'A', 'B', 'C' ] );

DESCRIPTION
===========

   HTML::FormHighlight can be used to highlight fields in an HTML form.
It uses HTML::Parser to parse the HTML form, and then places an indicator
before each field.  You can specify which fields to highlight, and
optionally supply a CGI object for it to check whether or not an input
value exists before highlighting the field.

   It can be used when displaying forms where a user hasn't filled out a
required field.  The indicator can make it easier for a user to locate the
fields that they've missed.  If you're interested in more advanced form
validation, see HTML/FormValidator.  See
HTML/FillInForm, can also be used to fill form fields
with values that have already been submitted.

METHODS
=======

new()
-----

     Create a new HTML::FormHighlight object.  Example:

         $h = new HTML::FormHighlight;

     =head2 highlight()

   Parse through the HTML form and highlight fields.  The method returns a
scalar containing the parsed form.  Here are a few examples:

     To highlight the fields 'A', 'B' and 'C' (form on disk):

         $h->highlight(
             file   => 'form.html',
             fields => [ 'A', 'B', 'C' ],
         );

     To highlight the fields 'A' and 'B' with a smiley face
     (form as a scalar):

         $h->highlight(
             scalarref => \$form,
             fields    => [ 'A', 'B' ],
             highlight => '<img src="smiley.jpg">',
         );

     To highlight the fields 'A' and 'B' if they haven't been supplied
     by form input (form as an array of lines):

         $q = new CGI;

         $h->highlight(
             arrayref => \@form,
             fields  => [ 'A', 'B' ],
             fobject => $q,
         );

     Note: highlight() will only highlight the first option in a radio or select group.

     Here's a list of possible parameters for highlight() and their descriptions:

   * scalarref - a reference to a scalar that contains the text of the
     form.

   * arrayref - a reference to an array of lines that contain the text of
     the form.

   * file - a scalar that contains the file name where the form is kept.

   * fields - a reference to an array that lists the fields to be
     highlighted.  If used in conjunction with "fobject" or "fdat", only
     the fields listed that are empty will be highlighted.

   * highlight - a scalar that contains the highlight indicator.  Defaults
     to a red asterisk (<font color="#FF0000" size="+1"><b>*</b></font>).

   * fobject - a CGI.pm object, or another object which has a param()
     method that works like CGI.pm's.  HTML::FormHighlight will check to
     see if a parameter does not have a value before highlighting the
     field.

   * fdat - a hash reference, with the field names as keys.
     HTML::FormHighlight will check to see if a parameter does not have a
     value before highlighting the field.

VERSION
=======

   0.01

AUTHOR
======

   Adekunle Olonoh, ade@bottledsoftware.com

CREDITS
=======

   Hiroki Chalfant

COPYRIGHT
=========

   Copyright (c) 2000 Adekunle Olonoh. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   See HTML/Parser, CGI,
HTML/FormValidator, HTML/FillInForm,

Validates user input (usually from an HTML form) based on input profile.
************************************************************************

NAME
====

   HTML::FormValidator - Validates user input (usually from an HTML form)
based on input profile.

SYNOPSIS
========

   In an HTML::Empberl page:

     use HTML::FormValidator;

     my $validator = new HTML::FormValidator( "/home/user/input_profiles.pl" );
     my ( $valid, $missing, $invalid, $unknown ) = $validator->validate(  \%fdat, "customer_infos" );

DESCRIPTION
===========

   HTML::FormValidator's main aim is to make the tedious coding of input
validation expressible in a simple format and to let the programmer focus
on more interesting task.

   When you are coding web application one of the most tedious though
crucial task is to validate user's input (usually submitted by way of an
HTML form). You have to check that each required fields is present and
that some feed have valid data. (Does the phone input looks like a phone
number ? Is that a plausible email address ? Is the YY state valid ? etc.)
For simple form, this is not really a problem but as forms get more
complex and you code more of them this task became really boring and
tedious.

   HTML::FormValidator lets you defines profiles which defines the
required fields and their format. When you are ready to validate the
user's input, you tell HTML::FormValidator the profile to apply to the
user data and you get the valid fields, the name of the fields which are
missing, the name of the fields that contains invalid input and the name
of the fields that are unknown to this profile.

   You are then free to use this information to build a nice display to
the user telling which fields that he forgot to fill.

INPUT PROFILE SPECIFICATION
===========================

   To create a HTML::FormValidator, use the following :

     my $validator = new HTML::FormValidator( $input_profile );

   Where $input_profile may either be an hash reference to an input
profiles specification or a file that will be evaluated at runtime to get
a hash reference to an input profiles specification.

   The input profiles specification is an hash reference where each key is
the name of the input profile and each value is another hash reference
which contains the actual profile elements. If the input profile is
specified as a file name, the profiles will be reread each time that the
disk copy is modified.

   Here is an example of a valid input profiles specification :

     {
     	customer_infos => {
     	    optional     =>
     		[ qw( company fax country ) ],
     	    required     =>
     		[ qw( fullname phone email address city state zipcode ) ],
     	    constraints  =>
     		{
     		    email	=> "email",
     		    fax		=> "american_phone",
     		    phone	=> "american_phone",
     		    zipcode	=> '/^\s*\d{5}(?:[-]\d{4})?\s*$/',
     		    state	=> "state",
     		},
     	    defaults => {
     		country => "USA",
     	    },
     	},
     	customer_billing_infos => {
     	     optional	    => [ "cc_no" ],
     	     dependencies   => {
     		"cc_no" => [ qw( cc_type cc_exp ) ],
     	     },
     	     constraints => {
     		cc_no      => {  constraint  => "cc_number",
     				 params	     => [ qw( cc_no cc_type ) ],
     				},
     		cc_type	=> "cc_type",
     		cc_exp	=> "cc_exp",
     	      }
     	    filters       => [ "trim" ],
     	    field_filters => { cc_no => "digit" },
     	},
     }

   The following are the valid fields for an input specification :

required
     This is an array reference which contains the name of the fields which
     are required. Any fields in this list which are not present in the
     user input will be reported as missing.

optional
     This is an array reference which contains the name of optional fields.
     These are fields which MAY be present and if they are, they will be
     check for valid input. Any fields not in optional or required list
     will be reported as unknown.

dependencies
     This is an hash reference which contains dependencies information.
     This is for the case where one optional fields has other requirements.
     For example, if you enter your credit card number, the field cc_exp
     and cc_type should also be present. Any fields in the dependencies
     list that is missing when the target is present will be reported as
     missing.

defaults
     This is an hash reference which contains defaults which should be
     substituted if the user hasn't filled the fields. Key is field name
     and value is default value which will be returned in the list of valid
     fields.

filters
     This is a reference to an array of filters that will be applied to ALL
     optional or required fields. This can be the name of a builting filter
     (trim,digit,etc) or an anonymous subroutine which should take one
     parameter, the field value and return the (possibly) modified value.

field_filters
     This is a reference to an hash which contains reference to array of
     filters which will be apply to specific input fields. The key of the
     hash is the name of the input field and the valud is a reference to an
     array of filters like for the filters parameter.

constraints
     This is a reference to an hash which contains the constraints that
     will be used to check wheter or not the field contains valid data.
     Constraint can be either the name of a builtin constraint function
     (see below), a perl regexp or an anonymous subroutine which will check
     the input and return true or false depending on the input's validity.

     The constraint function takes one parameter, the input to be validated
     and returns true or false. It is possible to specify the parameters
     that will be passed to the subroutine. For that use an hash reference
     which contains in the constraint element, the anonymous subroutine or
     the name of the builtin and in the params element the name of the
     fields to pass a parameter to the function. (Don't forget to include
     the name of the field to check in that list!) For an example, look at
     the *cc_no* constraint example.

VALIDATING INPUT
================

     my( $valids, $missings, $invalids, $unknowns ) =
     	$validator->validate( \%fdat, "customer_infos" );

   To validate input you use the validate() method. This method takes two
parameters :

data
     Contains an hash which should correspond to the form input as
     submitted by the user. This hash is not modified by the call to
     validate.

profile
     Can be either a name which will be used to lookup the corresponding
     profile in the input profiles specification, or it can be an hash
     reference to the input profile which should be used.

   This method returns a 4 elements array.

valids
     This is an hash reference to the valid fields which were submitted in
     the data. The data may have been modified by the various filters
     specified.

missings
     This is a reference to an array which contains the name of the missing
     fields. Those are the fields that the user forget to fill or filled
     with space. These fields may comes from the required list or the
     dependencies list.

invalids
     This is a reference to an array which contains the name of the fields
     which failed their constraint check.

unknowns
     This is a list of fields which are unknown to the profile. Whether or
     not this indicates an error in the user input is application
     dependant.

INPUT FILTERS
=============

   These are the builtin filters which may be specified as name in the
filters and field_filters parameters of the input profile.

trim
     Remove white space at the front and end of the fields.

strip
     Runs of white space are replaced by a single space.

digit
     Remove non digits characters from the input.

alphanum
     Remove non alphanumerical characters from the input.

integer
     Extract from its input a valid integer number.

pos_integer
     Extract from its input a valid positive integer number.

pos_integer
     Extract from its input a valid negative integer number.

decimal
     Extract from its input a valid decimal number.

pos_decimal
     Extract from its input a valid positive decimal number.

neg_decimal
     Extract from its input a valid negative decimal number.

dollars
     Extract from its input a valid number to express dollars like
     currency.

phone
     Filters out characters which aren't valid for an phone number. (Only
     accept digits [0-9], space, comma, minus, parenthesis, period and
     pound [#].)

sql_wildcard
     Transforms shell glob wildcard (*) to the SQL like wildcard (%).

quotemeta
     Calls the quotemeta (quote non alphanumeric character) builtin on its
     input.

lc
     Calls the lc (convert to lowercase) builtin on its input.

uc
     Calls the uc (convert to uppercase) builtin on its input.

ucfirst
     Calls the ucfirst (Uppercase first letter) builtin on its input.

BUILTIN VALIDATOR
=================

   Those are the builtin constraint that can be specified by name in the
input profiles.

email
     Checks if the email LOOKS LIKE an email address. This checks if the
     input contains one @, and a two level domain name. The address portion
     is checked quite liberally. For example, all those probably invalid
     address would pass the test :

          nobody@top.domain
          %?&/$()@nowhere.net
          guessme@guess.m

state_or_province
     This one checks if the input correspond to an american state or a
     canadian province.

state
     This one checks if the input is a valid two letter abbreviation of an
     american state.

province
     This checks if the input is a two letter canadian province
     abbreviation.

zip_or_postcode
     This constraints checks if the input is an american zipcode or a
     canadian postal code.

postcode
     This constraints checks if the input is a valid Canadian postal code.

zip
     This input validator checks if the input is a valid american zipcode :
     5 digits followed by an optional mailbox number.

phone
     This one checks if the input looks like a phone number, (if it
     contains at least 6 digits.)

american_phone
     This constraints checks if the number is a possible North American
     style of phone number : (XXX) XXX-XXXX. It has to contains more than
     7 digits.

cc_number
     This is takes two parameters, the credit card number and the credit
     cart type. You should take the hash reference option for using that
     constraint.

     The number is checked only for plausibility, it checks if the number
     could be valid for a type of card by checking the checksum and
     looking at the number of digits and the number of digits of the
     number.

     This functions is only good at weeding typos and such. IT DOESN'T
     CHECK IF THERE IS AN ACCOUNT ASSOCIATED WITH THE NUMBER.

cc_exp
     This one checks if the input is in the format MM/YY or MM/YYYY and if
     the MM part is a valid month (1-12) and if that date is not in the
     past.

cc_type
     This one checks if the input field starts by M(asterCard), V(isa),
     A(merican express) or D(iscovery).

CREDITS
=======

   Some of those input validation functions have been taken from MiniVend
by Michael J. Heins <mike@heins.net>

   The credit card checksum validation was taken from contribution by
Bruce Albrecht <bruce.albrecht@seag.fingerhut.com> to the MiniVend program.

AUTHOR
======

   Copyright (c) 1999 Francis J. Lacoste and iNsu Innovations Inc.  All
rights reserved.

   Parts Copyright 1996-1999 by Michael J. Heins <mike@heins.net> Parts
Copyright 1996-1999 by Bruce Albrecht  <bruce.albrecht@seag.fingerhut.com>

   This program is free software; you can redistribute it and/or modify it
under the terms as perl itself.

Format HTML as nroff man page
*****************************

NAME
====

   HTML::FormatNroff - Format HTML as nroff man page

SYNOPSIS
========

     require HTML::FormatNroff;
     $html = parse_htmlfile("test.html");
     $format_nroff = new HTML::FormatNroff(name => 'trial',
                                           project => 'MyProject');
     print $formatter->format($html);

DESCRIPTION
===========

   The HTML::FormatNroff is a formatter that outputs nroff source for the
nroff text processor, using man macros, and tbl commands for table
processing.

   The result of using the formatter must be processed as follows, when
directing output to the screen (assume output is in the file "text.nroff"):

     tbl -TX text.nroff | nroff -man | col

   If the output is to be printed, on an laser printer for example, a
command similar to the following must be used:

     tbl -TX text.nroff | nroff -man -Tlj | lpr

   Meta tags may be placed in the HTML so that portions of the HTML will
be ignored and not processed. Content between the tags

     <META NAME="nroff-control" CONTENT="ignore_start">
     <META NAME="nroff-control" CONTENT="ignore_end">

   will be ignored. In the BODY META is not supported, but DIV may be used
as follows:

     <DIV TYPE="NROFF_IGNORE">
     </DIV>

   In both the META and DIV uses, case is ignored.

METHODS
=======

$format_nroff->dt_start();
--------------------------

   Start a definition term <DT>, using a temporary indent and vertical
space.

$format_nroff->dd_start();
--------------------------

   Start a data definition, <DD>, using a temporary indent.

$format_nroff->configure($arg);
-------------------------------

   Configure the nroff formatter, setting the attributes passed in the
$arg attribute (hash reference)

$format_nroff->begin();
-----------------------

   Begin HTML formatting.

$format_nroff->end();
---------------------

   End HTML formatting.

$format_nroff->html_start();
----------------------------

   Process <HTML> start tag. Create the man page header based on saved
attributes, unless the attribute $format_nroff->{'man_header'} is not set.
This generates the following header:

     .TH "name" section "date" "project"

$format_nroff->font_start($font);
---------------------------------

   Start the font specified by the $font character (e.g. B, or I).  The
font is remembered so nested fonts are handled correctly.

$format_nroff->font_end();
--------------------------

   End the current font, returning to the previous one.

$format_nroff->i_start();
-------------------------

   Process <I> tag.

$format_nroff->i_end();
-----------------------

   Process </I> tag.

$format_nroff->b_start();
-------------------------

   Process <B> tag.

$format_nroff->b_end();
-----------------------

   Process </B> tag.

$format_nroff->table_start($node);
----------------------------------

   Process <TABLE>, start table processing. $node is the current
html_parser node.

     Pass on the $format_nroff->{'page_width'} to FormatTableNroff

$format_nroff->tr_start($node);
-------------------------------

   Process <TR>, add table row.

$format_nroff->tr_end();
------------------------

   End the table row </TR>

$format_nroff->a_start();
-------------------------

   <A> is ignored.

$format_nroff->a_end();
-----------------------

   </A> is ignored.

$format_nroff->td_start($node);
-------------------------------

   Process <TD>, add table cell

$format_nroff->td_end();
------------------------

   Process </TD>, end table cell

$format_nroff->th_start($node);
-------------------------------

   Process <TH>, add table header cell

$format_nroff->table_end();
---------------------------

   Process </TABLE>. Actually output entire table.

$format_nroff->p_start();
-------------------------

   Process <P>.

$format_nroff->p_end();
-----------------------

   Process </P> by doing nothing.

$format_nroff->goto_lm()
------------------------

   goto_lm does nothing.

$format_nroff->br_start();
--------------------------

   Process <BR>.

$format_nroff->hr_start();
--------------------------

   Process <HR>

$format_nroff->header_start();
------------------------------

   Process <H?> simply using .SH

$format_nroff->header_end();
----------------------------

   Process </H?> simply outputing newline

$format_nroff->out($text);
--------------------------

   Output text.

$format_nroff->pre_out($pre);
-----------------------------

   Output <PRE> text.

$format_nroff->nl($cnt);
------------------------

   Output newline.

$format_nroff->adjust_lm($indent);
----------------------------------

   adjust indent (left margin)

$format_nroff->adjust_rm();
---------------------------

   not used.

$format_nroff->bullet($tag);
----------------------------

   output the bullet, using a temporary indent and the $tag

$format_nroff->textflow($node);
-------------------------------

   Output text or add it to table if currently inside a table If centered
add .ce unless inside a table, if underlined add .ul, if the left margin
is adjusted use a .ti for every new line.

$format_nroff->blockquote_start($node);
---------------------------------------

   Start <BLOCKQUOTE>, by making a new paragraph, and indenting.

$format_nroff->blockquote_end($node);
-------------------------------------

   </BLOCKQUOTE>, by ending indent, and making a new paragraph

$format_nroff->div_start($node);
--------------------------------

   Process DIV

     <DIV TYPE="NROFF_IGNORE">
        is used to ignore all subsequent content until the next
     </DIV>

     This allows HTML to be used which is not to be converted to HTML
     (such as navigation controls). Case is ignored in the type.

   In the header you probably should use  <META NAME="nroff-control"
CONTENT="ignore_start">     is used to ignore all subsequent content until
the next  <META NAME="nroff-control" CONTENT="ignore_end">

SEE ALSO
========

   See HTML/Formatter, HTML/FormatTableCell,
see HTML/FormatTableCellNroff,
see HTML/FormatTableNroff,
see HTML/FormatTableRow,
HTML/FormatTableRowNroff,

COPYRIGHT
=========

   Copyright (c) 1997 Frederick Hirsch. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Frederick Hirsch <f.hirsch@opengroup.org>

Test package for testing subclassing of HTML::FormatNroff
*********************************************************

NAME
====

   HTML::FormatNroffSub - Test package for testing subclassing of
HTML::FormatNroff

SYNOPSIS
========

     require HTML::FormatNroffSub;
     use HTML::Parse;
     $html = parse_html("<P><TABLE><TR><TD>1</TD></TR></TABLE>");
     $formatter = new HTML::FormatNroffSub(name => 'test',
                                           project => 'proj') ;
     print $formatter->format($html);

DESCRIPTION
===========

   This is simply a test that HTML::FormatNroff may be subclassed and will
still work.

COPYRIGHT
=========

   Copyright (c) 1997 Frederick Hirsch. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Frederick Hirsch <f.hirsch@opengroup.org>

Format HTML as postscript
*************************

NAME
====

   HTML::FormatPS - Format HTML as postscript

SYNOPSIS
========

     require HTML::TreeBuilder;
     $tree = HTML::TreeBuilder->new->parse_file("test.html");

     require HTML::FormatPS;
     $formatter = new HTML::FormatPS
     		   FontFamily => 'Helvetica',
     		   PaperSize  => 'Letter';
     print $formatter->format($tree);

DESCRIPTION
===========

   The HTML::FormatPS is a formatter that outputs PostScript code.
Formatting of HTML tables and forms is not implemented.

   You might specify the following parameters when constructing the
formatter:

PaperSize
     What kind of paper should we format for.  The value can be one of
     these: A3, A4, A5, B4, B5, Letter, Legal, Executive, Tabloid,
     Statement, Folio, 10x14, Quarto.

     The default is "A4".

PaperWidth
     The width of the paper in points.  Setting PaperSize also defines this
     value.

PaperHeight
     The height of the paper in points.  Setting PaperSize also defines
     this value.

LeftMargin
     The left margin in points.

RightMargin
     The right margin in points.

HorizontalMargin
     Both left and right margin at the same time.  The default value is 4
     cm.

TopMargin
     The top margin in points.

BottomMargin
     The bottom margin in points.

VerticalMargin
     Both top and bottom margin at the same time.  The default value is 2
     cm.

PageNo
     The parameter determines if we should put page numbers on the pages.
     The default is yes, so you have to set this value to 0 in order to
     suppress page numbers.

FontFamily
     The parameter specifies which family of fonts to use for the
     formatting.  Legal values are "Courier", "Helvetica" and "Times".
     The default is "Times".

FontScale
     All fontsizes might be scaled by this factor.

Leading
     How much space between lines.  This is a factor of the fontsize used
     for that line.  Default is 0.1.

SEE ALSO
========

   See HTML/Formatter,

COPYRIGHT
=========

   Copyright (c) 1995-1999 Gisle Aas. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Gisle Aas <gisle@aas.no>

base class for formatting HTML Tables
*************************************

NAME
====

   HTML::FormatTable - base class for formatting HTML Tables

SYNOPSIS
========

     require HTML::FormatTable;
     @ISA = qw(HTML::FormatTable);

DESCRIPTION
===========

   The HTML::FormatTable is a base class for formatting HTML tables.  It
is used by a class such as HTML::FormatTableNroff, which is called by the
formatter HTML::FormatNroff when tables are processed.

METHODS
=======

$table = new HTML::FormatTable($formatter, %attr);
--------------------------------------------------

   Create new table representation. Formatter is used to output table
(e.g. $formatter is `HTML::FormatNroff')

   Attributes include

     align: table alignment (default is 'left'),
     tab: the character used in tbl to separate table cells.
           (the default is '%', and should be a character not included
            in table text)
     page_width: the page width in inches (e.g. "6")
     width: width of table, string including the percent (eg "100%")

$table->end_row();
------------------

   End the current table row.

$table->start_data(%attr);
--------------------------

   Start new table cell.

$table->end_data();
-------------------

   End table cell.

$table->add_text($text);
------------------------

   Add text to table

$table->output();
-----------------

   Output the table - must be overridden by subclass.

SEE ALSO
========

   See HTML/Formatter, HTML/FormatTableCell,
see HTML/FormatTableCellNroff,
see HTML/FormatTableNroff,
see HTML/FormatTableRow,
HTML/FormatTableRowNroff,

COPYRIGHT
=========

   Copyright (c) 1997 Frederick Hirsch. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Frederick Hirsch <f.hirsch@opengroup.org>

Format HTML Table
*****************

NAME
====

   HTML::FormatTableCell - Format HTML Table

SYNOPSIS
========

     require HTML::FormatTableCell;
     @ISA=qw(HTML::FormatTableCell);

DESCRIPTION
===========

   The HTML::FormatTableCell is a base class used to record information
about a table entry as part of FormatTable processing. It is necessary to
record information for formatting into languages such as nroff tbl which
require formatting information ahead of the table data.

METHODS
=======

$cell = new HTML::FormatTableCellNroff(%attr);
----------------------------------------------

   Since FormatTableCell is a base class, a derived class constructor such
as `FormatTableCellNroff' in this node should be called.

   The following attributes are supported:

     header - is a header (default is '')
     	nowrap - do not wrap if defined
     	rowspan - number of rows cell spans (default is 1)
     	colspan - number of columns cell spans (default is 1)
     	align - alignment of cell contents (default is 'left')
     	valign - vertical alignment of cell (default is 'middle')
     	contents - contents of cell (default is '')

$cell->add_text($text);
-----------------------

   Add additional contents to cell.

$alignment = $cell->alignment();
--------------------------------

   Return cell alignment.

$colspan = $cell->colspan();
----------------------------

   Return cell colspan.

$text = $cell->text();
----------------------

   Return cell text.

$width = $cell->width();
------------------------

   Return cell width in characters.

SEE ALSO
========

   See HTML/FormatNroff,
HTML/FormatTableCellNroff,
HTML/FormatTableRow, HTML/FormatTableRowNroff,

COPYRIGHT
=========

   Copyright (c) 1997 Frederick Hirsch. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Frederick Hirsch <f.hirsch@opengroup.org>

Format HTML Table entry
***********************

NAME
====

   HTML::FormatTableCellNroff - Format HTML Table entry

SYNOPSIS
========

     require HTML::FormatTableCellNroff;
     $cell = new HTML::FormatTableCellNroff(%attr);

DESCRIPTION
===========

   The HTML::FormatTableCellNroff is used to record information about a
table entry and produce format information about the entry.  It is used by
FormatTableNroff to process HTML tables.

METHODS
=======

$nroff_cell->format_str($width);
--------------------------------

   Produce a tbl format specification for the current cell, consisting of
an alignment character, width (in inches), and any subsequent colspan
specifications. An example is "cw(2i)".

$nroff_cell->output($formatter);
--------------------------------

     Output a table cell entry using the formatter defined by $formatter.
     The nroff
     T{
     .ad 1
     .fi
         contents
     .nf
     }T
     construct is used to format text inside a cell. Bold is used for a table
     header.

SEE ALSO
========

   See HTML/FormatNroff, HTML/FormatTableCell,
see HTML/FormatTableRow,
HTML/FormatTableRowNroff,

COPYRIGHT
=========

   Copyright (c) 1997 Frederick Hirsch. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Frederick Hirsch <f.hirsch@opengroup.org>

Format HTML Table as nroff
**************************

NAME
====

   HTML::FormatTableNroff - Format HTML Table as nroff

SYNOPSIS
========

     require HTML::FormatTableNroff;
     $table =  new HTML::FormatTableNroff($self, %attr);

DESCRIPTION
===========

   The HTML::FormatTableNroff is a formatter that outputs tbl, nroff and
man macro source for HTML tables. It is called by the HTML::FormatNroff
formatter to process HTML tables.

METHODS
=======

$width = $nroff_table->calculate_width($total, $num);
-----------------------------------------------------

   Calculate the width to use for the cell, using the following data:

     $nroff_table->{'page_width'} is the number of inches available
        on the page (6 if not set)

     $nroff_table->{'width'} specifies the percent of this available to
        the table (e.g. "75%")

     $total is calculated by determining the maximum width cell for each
     column and then adding these maximums for each column.

     $num is the maximum width cell for this column.

   The algorithm attempts to allocate the available table width (the
percentage of the page width) to the rows as the percentage the max width
of the column has with respect to the total.

   In order to make a small width column avoid unnecessary wrapping, if the
result width is less than an inch, a width corresponding to the max number
of characters is used ( aproximately the number/12 since 1em is about 12
points) (See "A TROFF tutorial", by Kernighan)

   The global HTML::FormatTableNroff::$_width_used is use to track the
amount of page width used by previous columns.

$nroff_table->attributes();
---------------------------

   Return tbl attributes associated with table itself as a string.  expand
will be specified if the table width is not explicitly specified or is not
100%. If centering is specified for the document region containing the
table, then the table will have the center attribute.

$nroff_table->output();
-----------------------

   Output the entire table, using the formatter associated with the table,
unless there is no table content - just put out a .sp in this case.

   A table is output as follows:

     .sp
     .TS
     table attributes;
     row specification
     row specification.
     row
     row
     .TE

$nroff_table->add_row(%attr);
-----------------------------

   Add a row to the table, with row attributes specified in %attr.

$nroff_table->row_iterator($method, @args);
-------------------------------------------

   Apply $method to each row of the table, passing @args, as follows:
$row->$method($last_row, @args);

   $last_row is set appropriately and used to signal to method whether
this is the last row in the table.

SEE ALSO
========

   See HTML/FormatNroff, HTML/FormatTable,
see HTML/FormatTableRow,
HTML/FormatTableRowNroff,

COPYRIGHT
=========

   Copyright (c) 1997 Frederick Hirsch. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Frederick Hirsch <f.hirsch@opengroup.org>

Format HTML Table row
*********************

NAME
====

   HTML::FormatTableRow - Format HTML Table row

SYNOPSIS
========

     require HTML::FormatTableRow;
     @ISA = qw(HTML::FormatTableRow);

DESCRIPTION
===========

   The HTML::FormatTableRow is used to record information and process a
table row. This is a base class.

   The following attributes are supported:   align: 'left','center', or
'right' alignment of table row entries   valign: vertical alignment, 'top'
or 'middle'

METHODS
=======

$table_row = new HTML::FormatTableRow(%attr);
---------------------------------------------

   The following attributes are supported:   align: 'left','center', or
'right' alignment of table row entries   valign: vertical alignment, 'top'
or 'middle'

$table_row->add_text($text);
----------------------------

   Add text to cell.

$table_row->text();
-------------------

   Return text associated with current table cell.

$table_row->widths($final, $array_ref);
---------------------------------------

   push the array of cell widths (in characters) onto the array specified
using the array reference $array_ref.

$table_row->output($final, $formatter, $tab);
---------------------------------------------

   Output the row data using the $formatter to do the output, and
separating each cell using the $tab character. $final is not used.

SEE ALSO
========

   See HTML/FormatTable,

COPYRIGHT
=========

   Copyright (c) 1997 Frederick Hirsch. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Frederick Hirsch <f.hirsch@opengroup.org>

Format HTML Table row for nroff
*******************************

NAME
====

   HTML::FormatTableRowNroff - Format HTML Table row for nroff

SYNOPSIS
========

     require HTML::FormatTableRowNroff;
     $row = new HTML::FormatTableRowNroff(%attr);

DESCRIPTION
===========

   The HTML::FormatTableRowNroff class is used to store information about
a single row of a table. Once information about all the rows of the table
has been recorded, an nroff tbl table may be created.

   The following attributes are supported:   align: 'left','center', or
'right' alignment of table row entries   valign: vertical alignment, 'top'
or 'middle'

METHODS
=======

$nroff_row->output_format($last_row, $formatter, @widths);
----------------------------------------------------------

   Create a tbl format line for the row. $last_row is true if this is the
last row in the table.

   $formatter is the formatter being used (e.g.  `HTML::FormatNroff').

   @widths is an array of width information for each cell in the current
row, specified in inches.

$nroff_row->add_element(%attr);
-------------------------------

   Add a new cell to the current row. %attr are the cell attributes, as
defined in `HTML::FormatTableCellNroff'.

$nroff_row->end_element();
--------------------------

   Finish the current cell.

SEE ALSO
========

   See HTML/FormatTable, HTML/FormatTableNroff,
see HTML/FormatTableRow,
HTML/FormatTableCell,
HTML/FormatTableCellNroff,

COPYRIGHT
=========

   Copyright (c) 1997 Frederick Hirsch. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Frederick Hirsch <f.hirsch@opengroup.org>

Format HTML as text
*******************

NAME
====

   HTML::FormatText - Format HTML as text

SYNOPSIS
========

     require HTML::TreeBuilder;
     $tree = HTML::TreeBuilder->new->parse_file("test.html");

     require HTML::FormatText;
     $formatter = HTML::FormatText->new(leftmargin => 0, rightmargin => 50);
     print $formatter->format($tree);

DESCRIPTION
===========

   The HTML::FormatText is a formatter that outputs plain latin1 text.
All character attributes (bold/italic/underline) are ignored.  Formatting
of HTML tables and forms is not implemented.

   You might specify the following parameters when constructing the
formatter:

leftmargin (alias *lm*)
     The column of the left margin. The default is 3.

rightmargin (alias rm)
     The column of the right margin. The default is 72.

SEE ALSO
========

   See HTML/Formatter,

COPYRIGHT
=========

   Copyright (c) 1995-1999 Gisle Aas. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Gisle Aas <gisle@aas.no>

Base class for HTML formatters
******************************

NAME
====

   HTML::Formatter - Base class for HTML formatters

SYNOPSIS
========

     package HTML::FormatXX;
     require HTML::Formatter;
     @ISA=qw(HTML::Formatter);

DESCRIPTION
===========

   HTML formatters are able to format a HTML syntax tree into various
printable formats.  Different formatters produce output for different
output media.  Common for all formatters are that they will return the
formatted output when the format() method is called.  Format() takes a
HTML::Element as parameter.

SEE ALSO
========

   See HTML/FormatText, HTML/FormatPS,
see HTML/Element,

COPYRIGHT
=========

   Copyright (c) 1995-2000 Gisle Aas. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Gisle Aas <gisle@aas.no>

mark up text as HTML
********************

NAME
====

   HTML::FromText - mark up text as HTML

SYNOPSIS
========

     use HTML::FromText;
     print text2html($text, urls => 1, paras => 1, headings => 1);

DESCRIPTION
===========

   The `text2html' function marks up plain text as HTML.  By default it
expands tabs and converts HTML metacharacters into the corresponding
entities.  More complicated transformations, such as splitting the text
into paragraphs or marking up bulleted lists, can be carried out by
setting the appropriate options.

SUMMARY OF OPTIONS
==================

   These options always apply:

     metachars    Convert HTML metacharacters to entity references
     urls         Convert URLs to links
     email        Convert email addresses to links
     bold         Mark up words with *asterisks* in bold
     underline    Mark up words with _underscores_ as underlined

   You can then choose to treat the text according to one of these options:

     pre          Treat text as preformatted
     lines        Treat text as line-oriented
     paras        Treat text as paragraph-oriented

   (If more than one of these is specified, pre takes precedence over
lines which takes precedence over paras.)  The following option applies
when the lines option is specified:

     spaces       Preserve spaces from the original text

   The following options apply when the paras option is specified:

     blockparas   Mark up indented paragraphs as block quote
     blockquotes  Ditto, also preserve lines from original
     blockcode    Ditto, also preserve spaces from original
     bullets      Mark up bulleted paragraphs as unordered list
     headings     Mark up headings
     numbers      Mark up numbered paragraphs as ordered list
     tables       Mark up tables
     title        Mark up first paragraph as level 1 heading

   `text2html' will issue a warning if it is passed nonsensical options,
for example headings but not paras.  These warnings can be supressed by
setting $HTML::FromText::QUIET to true.

OPTIONS
=======

blockparas
blockquotes
blockcode
     These options cause to `text2html' to spot paragraphs where every line
     begins with whitespace, and mark them up as block quotes.  If more
     than one of these options is specified, blockparas takes precedence
     over blockcode, which takes precedence over blockquotes.  All three
     options are ignored unless the paras option is also set.

     The blockparas option marks up the paragraph as a block quote with no
     other changes.  For example,

          Turing wrote,

          I propose to consider the question,
          "Can machines think?"

     becomes

          <P>Turing wrote,</P>
          <BLOCKQUOTE>I propose to consider the question,
          &quot;Can machines think?&quot;</BLOCKQUOTE>

     The blockquotes option preserves line breaks in the original text.
     For example,

          From "The Waste Land":

          Phlebas the Phoenecian, a fortnight dead,
          Forgot the cry of gulls, and the deep sea swell

     becomes

          <P>From &quot;The Waste Land&quot;:</P>
          <BLOCKQUOTE>Phlebas the Phoenecian, a fortnight dead,<BR>
          Forgot the cry of gulls, and the deep sea swell</BLOCKQUOTE>

     The blockcode option preserves line breaks and spaces in the original
     text and renders the paragraph in a fixed-width font.  For example:

          Here's how to output numbers with commas:

          sub commify {
            local $_ = shift;
            1 while s/^(-?\d+)(\d{3})/$1,$2/;
            $_;
          }

     becomes

          <P>Here's how to output numbers with commas:</P>
          <BLOCKQUOTE><TT>sub&nbsp;commify&nbsp;{<BR>
          &nbsp;&nbsp;local&nbsp;$_&nbsp;=&nbsp;shift;<BR>
          &nbsp;&nbsp;1&nbsp;while&nbsp;s/^(-?\d+)(\d{3})/$1,$2/;<BR>
          &nbsp;&nbsp;$_;<BR>
          }</TT></BLOCKQUOTE>

bold
     Words surrounded with asterisks are marked up in bold, so `*abc*'
     becomes `<B>abc</B>'.

bullets
     Spots bulleted paragraphs (beginning with optional whitespace, an
     asterisk or hyphen, and whitespace) and marks them up as an unordered
     list.  Bulleted paragraphs don't have to be separated by blank lines.
     For example,

          Shopping list:

          * apples
          * pears

     becomes

          <P>Shopping list:</P>
          <UL><LI><P>apples</P>
          <LI><P>pears</P>
          </UL>

     This option is ignored unless the paras option is set.

email
     Spots email addresses in the text and converts them to links.  For
     example

          Mail me at web@perl.com.

     becomes

          Mail me at <TT><A HREF="mailto:web@perl.com">web@perl.com</A></TT>.

headings
     Spots headings (paragraphs starting with numbers) and marks them up as
     headings of the appropriate level.  For example,

          1. Introduction

          1.1 Background

          1.1.1 Previous work

          2. Conclusion

     becomes

          <H1>1. Introduction</H1>
          <H2>1.1 Background</H2>
          <H3>1.1.1 Previous work</H3>
          <H1>2. Conclusion</H1>

     This option is ignored unless the paras option is set.

lines
     Formats the text so as to preserve line breaks.  For example,

          Line 1
          Line 2

     becomes

          Line 1<BR>
          Line 2

     If two or more of the options pre, lines and paras are set, then pre
     takes precedence over lines, which takes precedence over paras.

metachars
     Converts HTML metacharacters into their corresponding entity
     references.  Ampersand (`E<amp'>) becomes `E<amp'amp;>, less than
     (`<') becomes `E<amp'lt;>, greater than (`>') becomes `E<amp'gt;>, and
     quote (") becomes `E<amp'quot;>.  This option is 1 by default.

numbers
     Spots numbered paragraphs (beginning with whitespace, digits, an
     optional period/parenthesis/bracket, and whitespace) and marks them up
     as an ordered list.  Numbered paragraphs don't have to be separated by
     blank lines.  For example,

          To do:

          1. Write thesis
          2. Submit it
          3. Celebrate

     becomes

          <P>To do:</P>
          <OL><LI VALUE="1"><P>Write thesis</P>
          <LI VALUE="2"><P>Submit it</P>
          <LI VALUE="3"><P>Celebrate</P>
          </OL>

     This option is ignored unless the paras option is set.

paras
     Format the text into paragraphs.  Paragraphs are separated by one or
     more blank lines.  For example,

          Paragraph 1

          Paragraph 2

     becomes

          <P>Paragraph 1</P>
          <P>Paragraph 2</P>

     If two or more of the options pre, lines and paras are set, then pre
     takes precedence over lines, which takes precedence over paras.

pre
     Wrap the whole input in a `<PRE>' element.  For example,

          preformatted
          text

     becomes

          <PRE>preformatted
          text</PRE>

     If two or more of the options pre, lines and paras are set, then pre
     takes precedence over lines, which takes precedence over paras.

spaces
     Preserves spaces throughout the text.  For example,

          Line 1
           Line  2
            Line   3

     becomes

          Line 1<BR>
          &nbsp;Line&nbsp;&nbsp;2<BR>
          &nbsp;&nbsp;Line&nbsp;&nbsp;&nbsp;3

     This option is ignored unless the lines option is set.

tables
     Spots tables and marks them up appropriately.  Columns must be
     separated by two or more spaces (this prevents accidental incorrect
     recognition of a paragraph where interword spaces happen to line up).
     If there are two or more rows in a paragraph and all rows share the
     same set of (two or more) columns, the paragraph is assumed to be a
     table.  For example

          -e  File exists.
          -z  File has zero size.
          -s  File has nonzero size (returns size).

     becomes

          <P><TABLE>
          <TR><TD>-e</TD><TD>File exists.</TD></TR>
          <TR><TD>-z</TD><TD>File has zero size.</TD></TR>
          <TR><TD>-s</TD><TD>File has nonzero size (returns size).</TD></TR>
          </TABLE></P>

     `text2html' guesses for each column whether it is intended to be left,
     centre or right aligned.

     This option is ignored unless the paras option is set.

title
     Formats the first paragraph of the text as a first-level heading.
     For example,

          Paragraph 1

          Paragraph 2

     becomes

          <H1>Paragraph 1</H1>
          <P>Paragraph 2</P>

     This option is ignored unless the paras option is set.

underline
     Words surrounded with underscores are marked up with underline, so
     `_abc_' becomes `<U>abc</U>'.

urls
     Spots Uniform Resource Locators (URLs) in the text and converts them
     to links.  For example

          See https://perl.com/.

     becomes

          See <TT><A HREF="https://perl.com/">https://perl.com/</A></TT>.

SEE ALSO
========

   The `HTML::Entities' module (part of the LWP package) provides
functions for encoding and decoding HTML entities.

   Tom Christiansen has a complete implementation of RFC 822 structured
field bodies.  See
`http://www.perl.com/CPAN/authors/Tom_Christiansen/scripts/ckaddr.gz'.

   Seth Golub's `txt2html' utility does everything that `HTML::FromText'
does, and a few things that it would like to do.  See
`http://www.thehouse.org/txt2html/'.

   RFC 822: "Standard for the Format of ARPA Internet Text Messages"
describes the syntax of email addresses (the more esoteric features of
structured field bodies, in particular quoted-strings, domain literals and
comments, are not recognized by `HTML::FromText').  See
`ftp://src.doc.ic.ac.uk/rfc/rfc822.txt'.

   RFC 1630: "Universal Resource Identifiers in WWW" lists the protocols
that may appear in URLs.  `HTML::FromText' also recognizes "https:", but
ignores "file:" because experience suggests that it results in too many
false positives.  See `ftp://src.doc.ic.ac.uk/rfc/rfc1630.txt'.

AUTHOR
======

   Gareth Rees `<garethr@cre.canon.co.uk>'.

COPYRIGHT
=========

   Copyright (c) 1999 Canon Research Centre Europe. All rights reserved.
This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Parse <HEAD> section of a HTML document
***************************************

NAME
====

   HTML::HeadParser - Parse <HEAD> section of a HTML document

SYNOPSIS
========

     require HTML::HeadParser;
     $p = HTML::HeadParser->new;
     $p->parse($text) and  print "not finished";

     $p->header('Title')          # to access <title>....</title>
     $p->header('Content-Base')   # to access <base href="http://...">
     $p->header('Foo')            # to access <meta http-equiv="Foo" content="...">

DESCRIPTION
===========

   The *HTML::HeadParser* is a specialized (and lightweight) HTML::Parser
that will only parse the <HEAD>...</HEAD> section of an HTML document.
The parse() method will return a FALSE value as soon as some <BODY>
element or body text are found, and should not be called again after this.

   The *HTML::HeadParser* keeps a reference to a header object, and the
parser will update this header object as the various elements of the
<HEAD> section of the HTML document are recognized.  The following header
fields are affected:

Content-Base:
     The *Content-Base* header is initialized from the <base href="...">
     element.

Title:
     The Title header is initialized from the <title>...</title> element.

Isindex:
     The *Isindex* header will be added if there is a <isindex> element in
     the <head>.  The header value is initialized from the prompt
     attribute if it is present.  If no prompt attribute is given it will
     have '?' as the value.

X-Meta-Foo:
     All <meta> elements will initialize headers with the prefix
     "`X-Meta-'" on the name.  If the <meta> element contains a
     `http-equiv' attribute, then it will be honored as the header name.

METHODS
=======

   The following methods (in addition to those provided by the superclass)
are available:

$hp = HTML::HeadParser->new( [$header] )
     The object constructor.  The optional $header argument should be a
     reference to an object that implement the header() and push_header()
     methods as defined by the *HTTP::Headers* class.  Normally it will be
     of some class that isa or delegates to the *HTTP::Headers* class.

     If no $header is given *HTML::HeadParser* will create an
     *HTTP::Header* object by itself (initially empty).

$hp->header;
     Returns a reference to the header object.

$hp->header( $key )
     Returns a header value.  It is just a shorter way to write
     `$hp->header->header($key)'.

EXAMPLE
=======

     $h = HTTP::Headers->new;
     $p = HTML::HeadParser->new($h);
     $p->parse(<<EOT);
     <title>Stupid example</title>
     <base href="http://www.sn.no/libwww-perl/">
     Normal text starts here.
     EOT
     undef $p;
     print $h->title;   # should print "Stupid example"

SEE ALSO
========

   See HTML/Parser, HTTP/Headers,

   The *HTTP::Headers* class is distributed as part of the *libwww-perl*
package.

COPYRIGHT
=========

   Copyright 1996-1999 Gisle Aas. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

INSTALLATION
============

UNIX
----

   - *Unpack the archive*

   - *perl Makefile.PL*

   You will be asked if you want to compile in support for Apache
mod_perl. If you say yes, the source of Apache is searched (for
headerfiles). If it can't found, please specify the basepath. Please make
sure mod_perl is already installed. If you have installed mod_perl-0.96 or
higher, Makefile.PL automatically suggests the same source path as was
used to build mod_perl.

   - make

   - make test

   - make install

   *NOTE 1:* (only Embperl-1.2b1 or higher) For using session handling you
need Apache::Session-1.00 or higher. If possible use Apache::Session 1.52
or higher.  Starting with Embperl 1.3b7 Apache::Session 0.17 is *NOT*
supported anymore.

   *NOTE 2:* *Embperl* runs without additional Perl modules, but the make
test needs the following modules to work:

   * URI

   * MIME::Base64

   * HTML::Parser

   * HTML::HeadParser

   * Digest::MD5

   * libnet

   * libwww

   * libwin32 (only Win32)

   *NOTE 3:* EmbperlObject needs the following modules to work:

   * File::Spec 0.82 or higher

   If you have already successfully build and tested mod_perl all modules
will already be there.

Options for make test
---------------------

   make test can take several options, with can be given with the
`TESTARGS' parameter:

     make test TESTARGS="--help"

   will show you a list of available option. Most of them you will never
need, they are mainly nesseccary for debugging *Embperl* itself.

Debian packages
---------------

   The Debian packages are maintained by Angus Lees. Here are his
installation hints:

   i've also setup an apt repository for those using stable (potato). to
use it, just add these lines to /etc/apt/sources.list (deb-src line is
only necessary if you want to download the source at some point):

     deb http://www.cse.unsw.edu.au/~gusl/embperl stable/binary-$(ARCH)/
     deb-src http://www.cse.unsw.edu.au/~gusl/embperl stable/source/

   then run "apt-get update" followed by either "apt-get install
libhtml-embperl-perl" or just "apt-get upgrade" if you already have
embperl installed.

   if you don't like apt, and want to do it the old fashioned way, i'm
sure you can work out how to download the .deb manually.

   notes:

   currently i only have i386 packages built for stable. if anyone wants
to build other archs and let me know, i can add them in (else, i can
probably get a sparc and alpha version compiled)

   the package for unstable is compiled against perl5.6, so it has to
conflict with earlier mod_perl packages that are compiled against perl5.5.
unfortunately, there is no perl5.6 apache-perl package yet (drow assures
me he's uploading one soon), so you have to make do with a DSO mod-perl
(ie: apache + libapache-mod-perl) for now.

WIN 32
------

   I have tested the offline mode on Windows 95 with a Microsoft Visual
C++ 4.2 compiler and I have succesfully run Embperl with
apache_1.3b5-1.3.9 / mod_perl-1.12-1.21 / perl5.004_04-perl5.005 (without
threads) on Windows NT with VC++ 5.0.

   NOTE: It was necessary for me to compile perl5.004_04 with the VC++ on
my own to get it to run with Apache and mod_perl, while I was able to use
the binary distribution (/authors/id/GSAR/perl5.00402-bindist04-bc.tar.gz)
of Perl for offline testing under Win 95.

   NOTE: You need mod_perl >= 1.12 on win32

   On Windows 95/NT you have to do the following:

   *perl Makefile.PL*

   *nmake* (you must have the c compiler in your path)

   if you get an error about compiling Embperl.c. Edit Embperl.c and change

   -#line  "Embperl.xs"

   to

   +#line  1 "Embperl.xs"

   now re-run nmake and it should compile.

   *nmake test*

   NOTE: nmake test needs libwin32, libwww and HTML::Parser installed to
work

   *nmake install*

   *NOTE 1:* (only Embperl-1.2b1 or higher) For using session handling you
need Apache::Session-1.00 or higher. If possible use Apache::Session 1.52
or higher.  Starting with Embperl 1.3b7 Apache::Session 0.17 is *NOT*
supported anymore.

   *NOTE 2:* *Embperl* runs without additional Perl modules, but the make
test needs the following modules to work:

   * URI

   * MIME::Base64

   * HTML::Parser

   * HTML::HeadParser

   * Digest::MD5

   * libnet

   * libwww

   * libwin32 (only Win32)

   *NOTE 3:* EmbperlObject needs the following modules to work:

   * File::Spec 0.82 or higher

   If you have already successfully build and tested mod_perl all modules
will already be there.

Further Documentation (english)
-------------------------------

   See `"perldoc Features"|"Features.pod"' in this node for list of
Embperls features

   See `"perldoc Intro"|"Intro.pod"' in this node for an step by step
introduction to Embperl.

   See `"perldoc IntroEmbperlObject"|"IntroEmbperlObject.pod"' in this
node for an step by step introduction to the OO features of Embperl.

   See `"perldoc Embperl"|"Embperl.pod"' in this node for complete
documentation.

   See the `"eg' in this node directory for examples.

   See `"perldoc Faq"|"Faq.pod"' in this node for Frequently Asked
Questions.

   See `"perldoc TipsAndTricks"|"TipsAndTricks.pod"' in this node for Tips
and Tricks around Embperl.

   or you can view it online on http://perl.apache.org/embperl/

Further Documentation (german)
------------------------------

   See *perldoc FeaturesD* for list of Embperls features

   See *perldoc IntroD* for an step by step introduction to Embperl.

   See *perldoc EmbperlD* for complete documentation.

   or you can view it online on http://www.ecos.de/embperl/

Content
=======

What is Embperl?
Embed Perl Code in HTML Documents
Meta-Commands
Dynamic Tables
Form Processing
Maintaining persistent (session) data
Breaking up your code in components
Debugging
Database Access
Security
Escaping/Unescaping
What is Embperl?
================

Embed Perl Code in HTML Documents
---------------------------------

   The main purpose of HTML::Embperl is to embed Perl code in HTML
documents. While Embperl can also be used with non-HTML documents, it has
several features that are specifically for HTML.

How does it compare to ASP, PHP, ePerl?
---------------------------------------

   Embperl is not the only processor for embedded Perl code. ASP used with
ActiveState Perl port provides this for Microsoft IIS, and ePerl is a
solution which does this job very well for all sorts of ASCII files. There
are other Perl solutions around as well.  PHP is a well-known solution for
easily building web pages with embedded code and database connections, but
it's not Perl.

Additional HTML features
------------------------

   The main advantage of Embperl is the built-in HTML awareness. It
provides features for handling form data and HTML tables, along with
converting log files and error pages to HTML and linking them together. It
also allows for escaping and unescaping.

Integration with Apache and mod_perl
------------------------------------

   Embperl can be used offline (as a normal CGI script or as a module from
other Perl code), but its real power comes when running under mod_perl and
Apache. It's directly integrated with Apache and mod_perl to achieve the
best performance by directly using Apache functions and precompiling your
code to avoid a recompile on every request.

For Usage With High Level HTML Editor
-------------------------------------

   Embperl was designed to be used with a high-level HTML editor. The Perl
code can be entered as normal text (the editor need not know any special
HTML tags nor is it necessary to enter special HTML tags via uncomfortable
dialogs); just enter your code as if it were normal text. Embperl takes
care of unescaping the HTML codes and eliminates unwanted HTML tags (like
<BR>) which are entered into your Perl code by the editor (e.g. because
you like to have a line break for better readability).

How to Embed Perl Code in HTML Documents
========================================

   Perl code can be embedded in three ways:

1.)    [- ... -]    Execute code
--------------------------------

     [- $a = 5 -]  [- $b = 6 if ($a == 5) -]

   The code between the [- and the -] is executed. No output will be
generated. This is mainly for assignments, function calls, database
queries, etc.

2.)    [+ ... +]Output the result
---------------------------------

     [+ $a +]  [+ $array[$b] +] [+ "A is $a" +]

   The code between the [+ and the +] is executed and the return value
(the value of the last expression evaluated) is output (sent to the
browser).

3.)    [! ... !]    Execute code once
-------------------------------------

     [! sub foo { my ($a, $b) = @_ ; $a * $b + 7 } !]

   Same as [- ... -], but the code is only executed for the first request.
This is mainly for function definitions and one-time initialization.

Meta-Commands
-------------

   Embperl support some meta commands to control the "program flow" within
the Embperl document. This can be compared to preprocessor commands in C.
The meta commands take the following form:

     [$ <cmd> <arg> $]

if, elsif, else, endif
......................

   The if command is just the same as in Perl.  It is used to
conditionally output/process parts of the document.  Example:

     [$ if $ENV{REQUEST_METHOD} eq 'GET' $]
        This is a GET request
     [$ elsif $ENV{REQUEST_METHOD} eq 'POST' $]
        This is a POST request
     [$ else $]
        This is not GET and not POST
     [$ endif $]

   This will output one of the three lines depending on the setting of
$ENV{REQUEST_METHOD}.

while, endwhile
...............

   The while command can be used to create a loop in the HTML document.
For example:

     [$ while ($k, $v) = each (%ENV) $]
        [+ $k +] = [+ $v +] <BR>
     [$ endwhile $]

   The above example will display all environment variables, each
terminated with a line break.

do, until
.........

   The do until also create a loop, but with a condition at the end.  For
example:

     [- @arr = (3, 5, 7); $i = 0 -]
     [$ do $]
        [+ $arr[ $i++ ] +]
     [$ until $i > $#arr $]

foreach, endforeach
...................

   Create a loop iterating over every element of an array/list.  Example:

     [$ foreach $v (1..10) $]
        [+ $v +]
     [$ endforeach $]

var <var1> <var2> ...
.....................

   By default, you do not need to declare any variables you use within an
Embperl page. Embperl takes care of deleting them at the end of each
request. Sometimes, though, you want to declare them explicitly.  You can
do this by using var:

     [$ var $a @b %c $]

   Has the same effect as the Perl code:

     use strict ;use vars qw {$a @b %c} ;

hidden
......

   hidden is used for creating hidden form fields and is described in the
form field section below.

Dynamic Tables
==============

   A very powerful feature of Embperl is the processing of dynamic tables.
This feature was designed mainly to display Perl arrays (one or two
dimensional, regular and irregular), but can also be used in other ways.

Display a Perl Array
--------------------

     [- @a = ( 'A', 'B', 'C') ; -]
     <TABLE BORDER=1>
       <TR>
            <TD> [+ $a[$row] +] </TD>
       </TR>
     </TABLE>

   The above example simply displays a table with three rows containing A,
B and C.

   The trick is done by using the magical variable $row which contains the
row count and is incremented for every row. The table ends if the
expression which contains $row returns <undef>.  The same can be done with
$col for columns and $cnt can be used if you need a table which wraps
after a certain number of elements.

   This works with table/select/menu/ol/dl/dir

Simple DBI Example
------------------

   Here is a simple DBI example that displays the result of a query as a
two dimension table, with field names as headings in the first row:

     [-
     # connect to database
      $dbh = DBI->connect($DSN) ;

     # prepare the sql select
     $sth = $dbh -> prepare ("SELECT * from $table") ;

     # excute the query
     $sth -> execute ;

     # get the fieldnames for the heading in $head
     $head = $sth -> {NAME} ;

     #continues on the next page...
     # get the result in $dat $dat = $sth -> fetchall_arrayref ;
     -]

     <table>
        <tr><th>[+ $head->[$col] +]</th></tr>
        <tr><td>[+ $dat -> [$row][$col] +]</td></tr>
     </table>

Form fields
===========

Posted form data available in %fdat/@ffld
-----------------------------------------

   The hash %fdat contains all values of  form fields. The array  @ffld
contains the names in the order in which they were submitted.

Input/Textarea/Select tags take values from %fdat
-------------------------------------------------

   If you do not specify a default value for an input tag and a value for
that input tag is available in %fdat, Embperl will automatically insert
this value and send it to the browser. This is similar to the behavior of
CGI.pm.  This means that if you post a form to itself, the browser will
display the values you just entered.

[$ hidden $]
------------

   [$ hidden $] creates hidden form fields for all fields not in another
input field. This can be used to transport data through confirmation
forms.  (For example, a wizard.)

A simple Text input / Confirmation form
---------------------------------------

   The following example shows many of the possibilities of Embperl.  It's
a simple form where you can enter your name, your email address and a
message. If you hit the send button, you see the data you just entered and
can confirm the information by hitting the "send via mail" button, or you
can go back to the input form to change the data. If you confirm your
input, the data will be sent to a predefined e-mail address. The example
also shows how you can implement error checking-if you miss your name or
your e- mail address, you will get a corresponding error message and the
input form is shown again.

   The first part is the error checking; the second part the confirmation
form; the third part sends the mail if the input was ok and is confirmed;
the last part is the input form itself.

   Depending on the values of $fdat{check}, $fdat{send} and if $fdat{name}
and $fdat{email} contains data, the document decides which part to show.

     [-  $MailTo = 'richter\@ecos.de' ;

     @errors = () ;
     if (defined($fdat{check}) || defined($fdat{send}))
       {
       push @errors, "**Please enter your name" if (!$fdat{name}) ;
       push @errors, "**Please enter your e-mail address" if (!$fdat{email}) ;
       }
      -]

     [$if (defined($fdat{check}) and $#errors == -1)$]
     [-
      delete $fdat{input} ;
      delete $fdat{check} ;
      delete $fdat{send}
     -]

     <hr><h3> You have entered the following data:</h3>
     <table>
      <tr><td><b>Name</b></td><td>[+$fdat{name}+]</td></tr>
      <tr><td><b>E-Mail</b></td><td>[+$fdat{email}+]</td></tr>
      <tr><td><b>Message</b></td><td>[+$fdat{msg}+]</td></tr>
      <tr><td align="center" colspan="2">
         <form action="input.htm" method="GET">
           <input type="submit" name="send"
                  value="Send to [+ $MailTo +]">
           <input type="submit" name="input" value="Change your data">
           [$hidden$]
        </form>
        </td></tr>
     </table>

     [$elsif defined($fdat{send}) and $#errors == -1$]

     [- MailFormTo ($MailTo,'Formdata','email') -]
     <hr><h3>Your input has been sent</h3>

     [$else$]

     <hr><h3>Please enter your data</h3>

     <form action="input.htm" method="GET">
      <table>
        [$if $#errors != -1 $]
          <tr><td colspan="2">
          <table>
        <tr><td>[+$errors[$row]+]</td></tr>
          </table>
          </td></tr>
        [$endif$]
        <tr><td><b>Name</b></td> <td><input type="text"
                                            name="name"></td></tr>
        <tr><td><b>E-Mail</b></td> <td><input type="text"
                                              name="email"></td></tr>
        <tr><td><b>Message</b></td> <td><input type="text"
                                               name="msg"></td></tr>
        <tr><td colspan=2><input type="submit"
                                 name="check" value="Send"></td></tr>  </table>
     </form>

     [$endif$]

Maintaining persistent (session) data
=====================================

     (Embperl 1.2 or above)

   While hidden fields are useful when working with forms, it's often
necessary to *store persistent data* in a more general way. Embperl
utilizes *Apache::Session* to do this job. Apache::Session is caple of
storing persistent data in memory, in a textfile or in a database.  More
storage methods may supported in the future. While you can simply call
Apache::Session from an Embperl page, Embperl can do it for you. All you
need to do is to put your data in the hash *%udat*. The next time the same
user requests any Embperl page %udat will contain the same data. You can
simply use this to keep state information for the user. Depending on your
expire settings, the state can also kept between mulitiple sessions. A
second hash, *%mdat*, can be used to keep a state for one page, but for
multiple users. A simple example would be a page hit counter:

     The page is requested [+ $mdat{counter}++ +] times
     since [+ $mdat{date} ||= localtime +]

   The above example counts the page hits and shows the date when the page
is first requested.  You don't need to worry about performance - as long
as you don't touch %udat or %mdat, no action is taken.

Breaking your code up into components
=====================================

     (Embperl 1.2 or above)

Subroutines
-----------

   It is better to write subroutines than to keep placing repetetive
pieces of code in your program many times. You can do this with Embperl
too.  As an example, if you have text input fields with labels, this may
work better for you:

     [$ sub textinput $]
        [- ($label, $name) = @_ -]
        [+ $label +]<input type=text name=[+ $name +]>
     [$ endsub $]

     <form>
        [- textinput ('Last Name', 'lname')  -]<p>
        [- textinput ('First Name', 'fname') -]<p>
     </form>

   The sub metacommand starts the subroutine and the parameters are passed
in the array `@_'. You can do anything in the subroutine that you would
normally be able to do inside normal Embperl pages. Embperl lets you call
this subroutine just like any other Perl subroutine: just write its name
and, if necessary, the parameter list.

Execute
-------

   If you are working on an entire site rather than just a few pages, you
are well aware that there are always elements which occur in every page or
across many pages. Instead of copying the source code to every page, you
can include other Embperl pages in your page - so you have to write the
source only once.  Such an included page could be a header, a footer, a
navigation bar, and so on.  Embperl is not only capable of including such
partial pages, you can also pass arguments -  for example, to tell the
navigation bar which of its own element to highlight:

     Example for a simple navigation bar

     [- @buttons = ('Index', 'Infos', 'Search') -]
     <table><tr><td>
         [$if $buttons[$col] eq $param[0]$] <bold> [$endif$]
         <a href="[+ $buttons[$col] +].html"> [+ $buttons[$col] +] </a>
         [$if $buttons[$col] eq $param[0]$] </bold> [$endif$]
     </td></tr></table>
     <hr>

   Now if you are on the "Info" page you can include the navigation bar
this way:

     [- Execute ('navbar.html', 'Infos') -]

   This will include the navigation bar, which is stored in the file
navbar.html, and pass as its first parameter the string 'Infos'. The
navigation bar module itself uses a dynamic table to display one column -
which contains the text and a link - for every item in the array @buttons.
The text which matches that which is passed as the first parameter is
displayed in bold. There is also a long form of the Execute call, which
allows you to control all of the details of how the called page is
executed.

Creating Component Libraries
----------------------------

   Instead of creating a single file for every piece of HTML-code you wish
to include, you can pack them together in just one library. To do this,
split up every piece of code you want to include separately in one Embperl
subroutine (sub-metacommand). Now, you can use the import parameter of the
Execute function to import all of the subrountines defined in one file,
into the namespace of the current page. Afterwards, you are able to call
them just like any other Perl subroutine.

   Moreover, if you wish to have some systemwide Embperl subroutines, you
can put all the Embperl code in a normal Perl module (a foo.pm file),
install it into your Perl system (or a private library path), and use it
just like any other Perl module - just by saying

     use mymodule;

Debugging
=========

Embperl log file
----------------

   The log file is the main source for debugging. It shows you what
Embperl does while it processes your page. Depending on the debug flag
settings, Embperl logs the following things:

Source
Environment
Form data
Evals (Source + Result)
Table processing
Input tag processing
HTTP headers
Embperl log file can be viewed via the browser
----------------------------------------------

   For debugging, you can tell Embperl to display a link at the top of
each page to your log file. If you follow the link, Embperl will show the
portion of the log file corresponding to that request. The log file lines
are displayed in different colors to give a better overview.

Embperl error page contains links to the log file
-------------------------------------------------

   If you have enabled links to the log file, every error displayed in an
error page is a link to the corresponding position in the logfile, so you
can easily find the place where something is going wrong.

Database access
===============

Plain DBI
---------

   This is another example of using plain DBI within Embperl.  In
opposition to the `example|"Simple DBI Example"' in this node I gave in the
chapter about dynamic tables, this example works with explicit loops.

     [-
     # connect to database
     $dbh = DBI->connect($DSN) ;
     # prepare the sql select
     $sth = $dbh -> prepare ("SELECT * from $table") ;

     # excute the query
     $sth -> execute ;

     # get the fieldnames for the heading in $head
     $head = $sth -> {NAME} ;
     -]

     <table>
        <tr>
        [$ foreach $h @$head $]
            <th>[+ $h +]</th>
        [$ endforeach $]
        </tr>
        [$ while $dat = $sth -> fetchrow_arrayref $]
            <tr>
                [$ foreach $v @$dat $]
                    <td>[+ $v +]</td>
                [$ endforeach $]
            </tr>
        [$ endwhile $]
     </table>

DBIx::Recordset
---------------

   DBIx::Recordset is a module for easy database access.

Search Example
--------------

     [-*set = DBIx::Recordset -> Search ({%fdat,
     				     ('!DataSource'   => $DSN,
     				      '!Table' => $table,
     				      '$max'   => 5,)}) ; -]
     <table>
      <tr><th>ID</th><th>NAME</th></tr>
      <tr>
        <td>[+ $set[$row]{id} +]</td>
        <td>[+ $set[$row]{name} +]</td>
      </tr>
     </table>
     [+ $set -> PrevNextForm ('Previous Records',
     			  'Next Records',
     			  \%fdat) +]

Search sets up a Recordset object
---------------------------------

   Search will take the values from %fdat and use them to build a SQL
WHERE expression. This way, what you search for depends on what is posted
to the document.  For example, if you request the document with
http://host/mydoc.html?id=5 the above example will display all database
records where the field 'id' contains the value 5.  =head2 Data can
accessed as array or via the current record The result of the query can be
accessed as an array (this does not mean that the whole array is actually
fetched from the database).  Alternative, you can directly access the
current record just by accessing the fields.

     set[5]{id}	 access the field 'id' of the sixth found record
     set{id}      access the field 'id' of the current record

Fields can be accessed by name
------------------------------

   While normal DBI let you access your data by column numbers,
DBIx::Recordset uses the field names. This makes your program easier to
write, more verbose and independent of database changes.

PrevNextForm generates no/one/two buttons depending if there are more records to display
----------------------------------------------------------------------------------------

   The PrevNextButtons function can be used to generate button for showing
the previous record or the next records. PrevNextButton generates a small
form and includes all necessary data as hidden fields. To get it to work,
it's enough to feed this data to the next request to Search.

As for Search there are methods for Insert/Update/Delete
--------------------------------------------------------

   Example for Insert

   If %fdat contains the data for the new record, the following code will
insert a new record into the database.

     [-*set = DBIx::Recordset -> Insert ({%fdat,
     				      ('!DataSource'   => $DSN,
     				       '!Table' => $table)}) ; -]

Database table can also tied to a hash
--------------------------------------

   DBIx::Recordset can also tie a database table to a hash. You need to
specify a primary key for the table, which is used as key in the hash.

     $set{5}{name}    access the name with the id=5
     		     (id is primary key)

Security
========

   When running under mod_perl, all Perl code shares the same interpreter.
This means that every application can access data from every other
application. Embperl maintains a separate namespace for every document,
which is enough to avoid accidentally overwriting other applications data,
but there is no real security. You can access anything you like if you
explicitly specify a package name.

Safe namespaces
---------------

   Therefore, Embperl incorporates Safe.pm, which will make it impossible
to access any packages other than your own. This can be used, for example,
to calculate something in a Perl module and then pass the results to an
Embperl document. If the Embperl document runs in a safe namespace, it can
access the data it has received from the browser, but can't access outside
itself.  Therefore, it's safe to let different people create the layouts
for Embperl pages.

Operator restrictions
---------------------

   Safe.pm also permits the administrator to disable every Perl opcode. If
you use this, you are able to decide which Perl opcodes are permitted to
be used by the page creators.

Escaping/Unescaping
===================

Input: unescaping
-----------------

   (disable via optRawInput)

   - convert HTML escapes to characters (e.g. &lt; to <) - remove HTML
tags from Perl code (e.g. <br> insert by high level editor)

Output: escaping
----------------

   (disable via escmode) convert special characters to HTML (e.g. < to
&lt;)

Content
=======

Was ist Embperl?
Perl Code in HTML Dokumente einfügen
Meta-Commands
Dynamische Tabellen
Formularfelder
Persistente Daten (Sessions)
Aufteilen des Codes in mehrere Komponenten
Debugging
Datenbankzugriff
Sicherheit
Escaping/Unescaping
Was ist Embperl?
================

Perl Code in HTML Dokumente einfügen
------------------------------------

   Die Hauptanwendung von HTML::Embperl ist Perlcode in HTML Dokumente
einzufügen. Embperl kann zwar ebenfalls mit nicht HTML Dokumenten benutzt
werden, hat jedoch einige Features speziell für HTML.

Zusätzliche HTML Features
-------------------------

   Einer der Vorteile von Embperl ist, daß es speziell auf HTML
zugeschnitten ist. Es stellt u.a. Funktionen zur Formularbehandlung und für
HTML Tabellen zur Verfügung, einhergehend mit der Fähigkeit Logdateien und
Fehlerseiten in HTML darzustellen. Ebenso erledigt es die HTML und URL
Kodierung. Dies verhindet jedoch nicht das Embperl mit allen Arten von
Textdateien umgehen kann.

Integration mit Apache und mod_perl
-----------------------------------

   Embperl kann offline (als normales CGI Skript oder als Modul dessen
Funktionen sich von anderem Perlprogrammen/-modulen aufrufen lassen)
benutzt werden, aber die meisten Möglichkeiten und beste Performance
entwickelt es unter mod_perl und Apache. Dort werden direkt die Funktionen
der Apache API genutzt und mod_perl erlaubt es den Code vorzukompilieren,
um dadurch den Compilierungsvorgang bei jedem weiterem Request einzusparen.

Embperl arbeitet mit HTML Editoren
----------------------------------

   Embperl ist entworfen worden um direkt mit dem von HTML Editoren
erzeugten Code zu arbeiten. Der Perlcode wird dabei als normaler Text
eingeben.  Es ist nicht nötig, das der HTML Editor spezielle HTML Tags
kennt, noch müssen diese über umständliche Dialoge eingegeben werden.
Embperl kümmert sich darum, z.B. ein vom HTML Editor erzeugtes &lt; in <
umzuwandeln, bevor es dem Perlinterpreter übergeben wird. Außerdem
entfernt es unerwünschte HTML Tags, z.B. ein <BR>, das der Editor
eingefügt hat, weil man eine neue Zeile anfängt, aus dem Perlcode.

Perl Code in HTML Dokumente einfügen
====================================

   Perlcode kann auf drei Arten eingebettet werden:

1.)    [- ... -]    Führt den Code aus
--------------------------------------

     [- $a = 5 -]  [- $b = 6 if ($a == 5) -]

   Der Code zwischen [- und -] wird ausgeführt, dabei wird keine Ausgabe
erzeugt. Diese Form eignet sich für Zuweisungen, Funktionsaufrufe,
Datenbankanfrage, usw.

2.)    [+ ... +] Das Ergebnis ausgeben
--------------------------------------

     [+ $a +]  [+ $array[$b] +] [+ "A is $a" +]

   Der Code zwischen dem [+ und dem +] wird ausgeführt und der Rückgabewert
(der Wert des letzten Perlausdruckes welcher berechnet wurde) wird
ausgegeben (zum Browser gesandt)

3.)    [! ... !]    Code nur einmal ausführen
---------------------------------------------

     [! sub foo { my ($a, $b) = @_ ; $a * $b + 7 } !]

   Genauso wie [- ... -], der Code wird jedoch nur einmal, für den ersten
Request, ausgeführt. Dies ist hauptsächlich für Funktionsdefinitionen und
einmalige Initialisierungen.

Meta-Commands
=============

   Embperl unterstützt einige Meta-Commands um dem "Programmablauf"
innerhalb des Embperldokuments zu steuern. Dies kann mit einem
Preprozessor in  C verglichen werden. Die Meta-Commands haben folgende
Form:

     [$ <cmd> <arg> $]

if, elsif, else, endif
......................

   Der if Befehl hat die selben Auswirkungen wie in Perl. Er kann genutzt
werden um Teile des Dokuments nur unter bestimmten Bedingungen
auszugeben/auszuführen.  Beispiel:

     [$ if $ENV{REQUEST_METHOD} eq 'GET' $]
        <p>Dies ist ein GET Request</p>
     [$ elsif $ENV{REQUEST_METHOD} eq 'POST' $]
        <p>Dies ist ein POST Request</p>
     [$ else $]
        <p>Dies ist weder ein GET noch ein POST Request</p>
     [$ endif $]

   Dieses Beispiel gibt eine der drei Absätze in Abhänigkeit von dem Wert
von $ENV{REQUEST_METHOD} aus.

while, endwhile
...............

   Der while Befehl wird dazu benutzt, um eine Schleife innerhalb des HTML
Dokuments zu erzeugen. Beispiel:

     [$ while ($k, $v) = each (%ENV) $]
        [+ $k +] = [+ $v +] <BR>
     [$ endwhile $]

   Das Beispiel zeigt alle Environementvariablen, jede abgeschlossen mit
einem Zeilenumbruch (<BR>).

do, until
.........

   do `until' erzeugt ebenso eine Schleife, jedoch mit der Bedingung am
Ende.  Beispiel:

     [- @arr = (3, 5, 7); $i = 0 -]
     [$ do $]
        [+ $arr[ $i++ ] +]
     [$ until $i > $#arr $]

foreach, endforeach
...................

   Erzeugt eine Schleife, die über jedes Element einer Liste/Arrays
iteriert.  Beispiel:

     [$ foreach $v (1..10) $]
        [+ $v +]
     [$ endforeach $]

var <var1> <var2> ...
.....................

   Standartmäßig ist es nicht nötig irgenwelche Variablen innerhalb einer
Embperlseite zu deklarieren. Embperl kümmert sich darum nach jedem Request
wieder aufzuräumen. Manchmal möchte man jedoch die zu benutzenden Variablen
explizit deklarieren. Dies ist mit var möglich:

     [$ var $a @b %c $]

   Hat den selben Effekt wie der Perlcode:

     use strict ; use vars qw {$a @b %c} ;

hidden
......

   hidden ermöglicht es versteckte Formularfelder zu erzeugen und wird
weiter unten im Abschnitt über Formularfelder beschrieben.

Dynamische Tabellen
===================

   Ein sehr leistungsfähiges Feature von Embperl ist das Erzeugen von
dynamischen Tabellen. Am einfachsten lassen sich auf diesem Weg Perlarrays
in Tabellen umwandeln (ein- oder zweidimensional, gleich- und
ungleichmäßige), aber auch andere Datenquellen sind möglich.

Anzeigen eines Perlarrays
-------------------------

     [- @a = ( 'A', 'B', 'C') ; -]
     <TABLE BORDER=1>
       <TR>
            <TD> [+ $a[$row] +] </TD>
       </TR>
     </TABLE>

   Das obige Beispiel gibt einfach eine Tabelle mit drei Zeilen, welche A,
B und C enthalten aus.

   Der Trick dabei ist die Benutzung der magischen Variable *$row*, welche
die Zeilennummer innerhalb der Tabelle enthält und automatisch für jede
Zeile um eins erhöht wird. Die Tabelle ist zu Ende, wenn der Block, in dem
*$row* auftaucht, undef zurückgibt. Das funktioniert auch mit *$col* für
Spalten und *$cnt* kann benutzt werden, wenn die Elemente, nach einer
bestimmten Anzahl, in die nächste Reihe rutschen sollen.

   Dies funktioniert ebenso mit table/select/menu/`ol'/`dl'/dir

Einfaches DBI Beispiel
----------------------

   Hier ist ein einfaches DBI Beispiel, welches das Ergebnis einer Anfrage
in einer zwei dimensionalen Tabelle anzeigt, mit den Feldnamen als
Überschrift in der ersten Zeile:

     [-
     # Verbinden mit Datenbank
      $dbh = DBI->connect($DSN) ;

     # SQL Select vorbereiten
     $sth = $dbh -> prepare ("SELECT * from $table") ;

     # Datenbankanfrage ausführen
     $sth -> execute ;

     # $head erhält die Feldnamen für die Tabellenüberschrift
     $head = $sth -> {NAME} ;

     # $dat erhält die Datensätze
     $dat = $sth -> fetchall_arrayref ;
     -]

     <table>
        <tr><th>[+ $head->[$col] +]</th></tr>
        <tr><td>[+ $dat -> [$row][$col] +]</td></tr>
     </table>

Formularfelder
==============

Gesendete Formulardaten sind in %fdat/@ffld verfügbar
-----------------------------------------------------

   Der Hash *%fdat* enthält alle Werte der Formularfelder. Das Array
*@**ffld* enthält die Namen in der Reihenfolge wie sie gesendet wurden.

Input/Textarea/Select tags erhalten ihre Werte aus %fdat
--------------------------------------------------------

   Wenn innerhalb des HTML Codes kein Wert für ein Inputtag angegeben ist
und Daten in *%fdat* dafür verfügbar sind, fügt Embperl automatisch den
Wert aus *%fdat* ein. Dies ist ähnlich dem Verhalten von CGI.pm. Das
bedeutet, daß wenn man die Daten eines Formular (in einer Embperlseite) an
sich selbst schickt, automatisch die Daten wieder angezeigt werden, die
gerade eingegeben wurden.

[$ hidden $]
------------

   [$ hidden $] erzeugt versteckte Formularfelder für alle Werte aus
*%fdat*, die bis dahin nicht in einem anderem Formularfeld ausgegeben
wurden. Dies ist hilfreich, wenn Daten über mehere Formulare hinweg
transportiert werden müssen.

Ein einfaches Texteingabe/Bestätigungs Formular
-----------------------------------------------

   Das folgende Beispiel zeigt viele der Möglichkeiten von Embperl.  Es
ist ein einfaches Formular, in dem man seinen Namen, seine Email Adresse,
sowie eine Nachricht eingeben kann. Wenn man es absendet, werden die Daten
zunächst noch einmal angezeigt.  Von dort kann man zum vorherigen Formular
zurückkehren, um die Daten zu korrigieren oder der Benutzer bestätigt die
Daten, wodurch sie zu einer vordefinierten Email Adresse gesandt werden.
Das Beispiel zeigt auch wie eine Fehlerüberprüfung implementiert werden
kann. Wenn der Name oder die Email Adresse weggelassen wird, wird eine
entsprechende Fehlermeldung angezeigt und das Eingabeformular erscheint
wieder.

   Der erste Teil ist die Fehlerüberprüfung; der zweite Teil die
Bestätigungsseite; der dritte Teil versendet die Email, wenn die Eingaben
bestätigt wurden und der letzte Teil ist das Eingabeformular.

   In Abhängigkeit der Werte von `$fdat{check}', `$fdat{send}' und ob
`$fdat{name}' und `$fdat{email}' Daten enthalten, entscheidet das Dokument
welcher Teil zur Ausführung kommt.

     [-  $MailTo = 'richter\@ecos.de' ;

     @errors = () ;
     if (defined($fdat{check}) || defined($fdat{send}))
       {
       push @errors, "**Bitte Namen eingeben" if (!$fdat{name}) ;
       push @errors, "**Bitte E-Mail Adresse eingeben" if (!$fdat{email}) ;
       }
      -]

     [$if (defined($fdat{check}) and $#errors == -1)$]
     [-
      delete $fdat{input} ;
      delete $fdat{check} ;
      delete $fdat{send}
     -]

     <hr><h3> Sie haben folgende Daten eingegeben:</h3>
     <table>
      <tr><td><b>Name</b></td><td>[+$fdat{name}+]</td></tr>
      <tr><td><b>E-Mail</b></td><td>[+$fdat{email}+]</td></tr>
      <tr><td><b>Nachricht</b></td><td>[+$fdat{msg}+]</td></tr>
      <tr><td align="center" colspan="2">
         <form action="input.htm" method="GET">
           <input type="submit" name="send"
                  value="Send to [+ $MailTo +]">
           <input type="submit" name="input" value="Daten abändern">
           [$hidden$]
        </form>
        </td></tr>
     </table>

     [$elsif defined($fdat{send}) and $#errors == -1$]

     [- MailFormTo ($MailTo,'Formdata','email') -]
     <hr><h3>Ihre Nachricht wurde abgeschickt</h3>

     [$else$]

     <hr><h3>Bitte geben Sie Ihre Daten ein</h3>

     <form action="input.htm" method="GET">
      <table>
        [$if $#errors != -1 $]
          <tr><td colspan="2">
          <table>
        <tr><td>[+$errors[$row]+]</td></tr>
          </table>
          </td></tr>
        [$endif$]
        <tr><td><b>Name</b></td> <td><input type="text"
                                            name="name"></td></tr>
        <tr><td><b>E-Mail</b></td> <td><input type="text"
                                              name="email"></td></tr>
        <tr><td><b>Nachricht</b></td> <td><input type="text"
                                               name="msg"></td></tr>
        <tr><td colspan=2><input type="submit"
                                 name="check" value="Send"></td></tr>  </table>
     </form>

     [$endif$]

Persistente Daten (Sessions)
============================

     (Embperl 1.2 oder neuer)

   Während versteckte Felder gut innerhalb Formularen einsetzbar sind, ist
es oft notwendig *Daten persistent* auf eine allgemeinere Art und Weise zu
speichern. Embperl benutzt *Apache::Session* um dies durchzuführen.
*Apache::Session* ermöglicht die Daten im Speicher, in einem Textfile oder
in einer Datenbank abzuspeichern. Weitere Speichermöglichkeiten sind für
die Zukunft zu erwarten. Man kann zwar einfach *Apache::Session* aus
Embperl Seiten herausaufrufen, aber Embperl ist in der Lage dies für den
Benutzer transparent durchzuführen. Es genügt einfach seine Daten in dem
Hash *%udat* abzuspeichern, sobald der selbe Benutzer wieder eine Embperl
Seite aufruft, stehen in %udat wieder die selben Daten. Dies ermöglicht auf
eine einfache Art und Weise Zustandsinformationen für einen Benutzer zu
speichern.  In Abhängigkeit vom Ablaufzeitpunkt können so
Benutzerspezifische Daten auch über einen längeren Zeitraum hinweg
gespeichert werden. Ein zweiter Hash, *%mdat*, dient dazu, Daten, die zu
einer bestimmten Seite gehören, zu speichern. Ein einfaches Beispiel ist
z.B. ein Zähler der Anzahl der Seitenaufrufe:

     Die Seite wurde seit dem [+ $mdat{date} ||= localtime +]
     [+ $mdat{counter}++ +] mal abgerufen

   Das obige Beispiel zählt die Anzahl der Abrufe und zeigt die Zeit, wann
die Seite zum ersten Mal aufgerufen wurde.  Embperl sorgt dafür, dass die
Daten nur dann wieder abgespeichert werden, wenn sie auch geändert wurden.

Aufteilen des Codes in mehrere Komponenten
==========================================

     (Embperl 1.2 oder neuer)

Funktionen
----------

   Wächst ein Programm, teilt man es in mehere Funktionen auf. Dies ist mit
Embperlseiten ebenfalls möglich. Folgendes Beispiel zeigt dies an Hand von
beschrifteten Texteingabefeldern:

     [$ sub textinput $]
        [- ($label, $name) = @_ -]
        [+ $label +]<input type=text name=[+ $name +]>
     [$ endsub $]

     <form>
        [- textinput ('Nachname', 'lname')  -]<p>
        [- textinput ('Vorname', 'fname') -]<p>
     </form>

   Das sub Meta-Command kennzeichnet den Anfang der Funktion und die
Parameter werden im Array `@_' übergeben. Man kann innerhalb der Funktion
alles tun, was auch in einer normalen *Embperl* Seite möglich ist.
Aufgerufen wird die Funktion, wie jede andere Perlfunktion auch, einfach
durch Schreiben des Namens und ggf. der Parameterliste.

Execute
-------

   Wenn man an einer ganzen Website arbeitet, kommt es meistens vor, daß es
Elemente gibt, die in jeder oder vielen Seiten immer wieder vorkommen.
Anstatt den Quellencode nun in jede Seite zu kopieren, ist es möglich
*Embperl Module* in die Seite einzufügen, so daß der Quellencode nur
einmal existieren muß. So ein Modul könnte z.B. ein Kopf, ein Fuß, eine
Navigationsleiste usw. sein. Es können dabei nicht nur Teile einer Seite
eingefügt, sondern auch, ähnlich einem Unterprogramm, Argumente übergeben
werden - z.B. um der Navigationsleiste mitzuteilen, welches Element
hervorzuheben ist.

   Beispiel für eine einfache Navigationsleiste

     [- @buttons = ('Index', 'Infos', 'Suchen') -]
     <table><tr><td>
         [$if $buttons[$col] eq $param[0]$] <bold> [$endif$]
         <a href="[+ $buttons[$col] +].html"> [+ $buttons[$col] +] </a>
         [$if $buttons[$col] eq $param[0]$] </bold> [$endif$]
     </td></tr></table>
     <hr>

   Wenn man nun auf der Info-Seite ist, kann die Navigationsleiste wie
folgt eingefügt werden:

     [- Execute ('navbar.html', 'Infos') -]

   Dies fügt die Navigationsleiste, welche in der Datei navbar.html
gespeichert ist, an entsprechender Stelle ein und übergibt ihr als
Parameter die Zeichenkette 'Infos'.  Das Navigationsleistenmodul selbst
benutzt eine dynamische Tabelle um die Spalten anzuzeigen, welche den Text
und einen entsprechenden Link enthalten. Die Texte werden dabei dem Array
@buttons entnommen. Wenn der Text gleich dem übergebenen Parameter ist,
wird er fett dargestellt.  Weiterhin gibt es noch eine ausführliche Form
des Executeaufrufes, welche es erlaubt sehr detailiert die Ausführung des
Moduls zu kontrollieren.

Erstellen von Komponenten Libraries
-----------------------------------

   Statt eine extra Datei für jedes bischen HTML Code zu erstellen,
welches in eine andere Seite eingefügt werden soll, ist es möglich diesen
in eine HTML Datei zusammenzufassen. Um dies zuerreichen muß jedes einzelne
Codestück eine eigene *Embperl* Funktion sein. Mittels des import
Parameters der Execute Funktion können nun alle *Embperl* Funktionen in
den Namensraum der aktuellen Seite importiert werden und fortan wie
normale Perlfunktionen aufgerufen werden.

   Weiterhin ist es möglich die *Embperl* Funktionen (zusammen mit
normalen Perl Code) als ein Perl Modul (.pm Datei) zu installieren.
Dadurch stehen sie systemweit zur Verfügung und können wie jedes andere
Perl Modul mittels use genutzt werden.

EmbperlObject
=============

     (ab Embperl 1.3)

   Einen Schritt weiter als das einfache Einbetten von anderen Dateien
mittels Execute geht EmbperlObject. EmbperlObject ist ein mod_perl handler,
der es erlaubt eine Website in konsistenter Weise aus einzelnen
Komponenten zusammenzusetzen.  Dabei definiert man ein Rahmenlayout,
welches "Platzhalter" für einzelne Elemente der Site (z.B. Kopf, Fuß,
Navigation etc.) enthält. Diese "Platzhalter" können nun für
unterschiedliche Bereiche (Unterverzeichnisse) der Site mit verschiedenen
Inhalten gefüllt werden. Definiert ein Bereich (Unterverzeichnis) keinen
eigenen Inhalt, wird automatisch der Inhalt des übergeordneten
Verzeichnisses eingefügt. Konkret heißt das, man identifiziert Bereiche,
die auf allen/vielen Seiten gleich aussehen sollen, macht daraus eine
eigenständige Komponente (HTML Datei) und fügt diese dann nur noch an
passender Stelle ein. Es leuchtet ein, dass dies das Design und Änderungen
wesentlich vereinfacht, da eine Änderung in der Komponente sich auf alle
Seiten auswirkt. Hier ein einfaches Beispiel, um zu verdeutlichen wie
EmbperlObject arbeitet; dabei definert base.htm das Rahmenlayout, head.htm
enthält den Kopf und foot.htm den Fuß für die Seite:

   *Anordnung der Dateien:*

     /foo/base.htm
     /foo/head.htm
     /foo/foot.htm
     /foo/page1.htm
     /foo/sub/head.htm
     /foo/sub/page2.htm

   */foo/base.htm:*

     <html>
     <head>
     <title>Beispiel</title>
     </head>
     <body>
     [- Execute ('head.htm') -]
     [- Execute ('*') -]
     [- Execute ('foot.htm') -]
     </body>
     </html>

   */foo/head.htm:*

     <h1>Kopf aus foo</h1>

   */foo/sub/head.htm:*

     <h1>Hier ein anderer Kopf aus dem Verzeichnis sub</h1>

   */foo/foot.htm:*

     <hr> Fußzeile <hr>

   */foo/page1.htm:*

     Hier steht der Inhalt von Seite 1

   */foo/sub/page2.htm:*

     Hier steht der Inhalt von Seite 2

   */foo/sub/index.htm:*

     Index im Verzeichnis /foo/sub

   Der Request *http://host/foo/page1.htm* führt dann zu folgender Seite:

     <html>
      <head>
      <title>Beispiel</title>
      </head>
      <body>
      <h1>Kopf aus foo</h1>
      Hier steht der Inhalt von Seite 1
      <hr> Fußzeile <hr>
      </body>
      </html>

   Der Request *http://host/foo/sub/page2.htm* führt dann zu folgender
Seite:

     <html>
      <head>
      <title>Beispiel</title>
      </head>
      <body>
      <h1>Hier ein anderer Kopf aus dem Verzeichnis sub</h1>
      Hier steht der Inhalt von Seite 2
      <hr> Fußzeile <hr>
      </body>
      </html>

   Der Request *http://host/foo/sub/* führt dann zu folgender Seite:

     <html>
      <head>
      <title>Beispiel</title>
      </head>
      <body>
      <h1>Hier ein anderer Kopf aus dem Verzeichnis sub</h1>
      Index im Verzeichnis /foo/sub
      <hr> Fußzeile <hr>
      </body>
      </html>

Debugging
=========

Embperl Logdatei
----------------

   Das Logfile ist die Hauptinformationsquelle zum Debuggen. Es zeichnet
auf, was mit der Seite geschieht, während sie von Embperl bearbeitet wird.
In Abhängigkeit von den Debugflags, logged Embperl folgende Dinge:

Quellencode
Umgebungsvariablen
Formular daten
Perlcode (Quelle + Ergebnis)
Tabellenbearbeitung
Eingabe-Tag-Bearbeitung
HTTP headers
Embperl Logdatei kann direkt im Browser angezeigt werden
--------------------------------------------------------

   Zur Fehlersuche kann Embperl veranlasst werden, an jedem Seitenanfang
einen Link zur Logdatei anzuzeigen. Wenn man dem Link folgt, wird der Teil
der Logdatei, welcher zu dem entsprechenden Request gehört angezeigt.
Dabei werden unterschiedliche Einträge zur leichteren Orientierung
verschiedenfarbig dargestellt.

Embperl Fehlerseite enthält Links zum Logfile
---------------------------------------------

   Wenn die Links zur Logdatei freigeschaltet sind, werden auch in jeder
Fehlerseite die Fehler direkt als Link dargestellt, die direkt auf die
richtige Position im Logfile verweisen. So läßt sich einfach feststellen,
was an dieser Stelle schief gelaufen ist.

Datenbankzugriff
================

DBI
---

   Dies ist ein weiteres Beispiel für den Datenbankzugriff mittels DBI.
Im Gegensatz zum vorhergehenden Beispiel arbeitet es aber mit expliziten
Schleifen.

     [-
     # Mit der Datenbank verbinden
     $dbh = DBI->connect($DSN) ;
     # Vorbereiten des SQL Select
     $sth = $dbh -> prepare ("SELECT * from $table") ;

     # Abfrage ausführen
     $sth -> execute ;

     # Ermitteln der Feldnamen für die Überschrift in $head
     $head = $sth -> {NAME} ;
     -]

     <table>
        <tr>
        [$ foreach $h @$head $]
            <th>[+ $h +]</th>
        [$ endforeach $]
        </tr>
        [$ while $dat = $sth -> fetchrow_arrayref $]
            <tr>
                [$ foreach $v @$dat $]
                    <td>[+ $v +]</td>
                [$ endforeach $]
            </tr>
        [$ endwhile $]
     </table>

DBIx::Recordset
---------------

   DBIx::Recordset ist ein Modul welches den Datenbankzugriff vereinfachen
soll.  Eine weiterführende Einführung zu DBIx::Recordset und Embperl
findet sich in der iX 9/1999 unter
http://www.heise.de/ix/artikel/1999/09/137/ .

Datenbankabfrage Beispiel
-------------------------

     [-*set = DBIx::Recordset -> Search ({%fdat,
     				     ('!DataSource'   => $DSN,
     				      '!Table' => $table,
     				      '$max'   => 5,)}) ; -]
     <table>
      <tr><th>ID</th><th>NAME</th></tr>
      <tr>
        <td>[+ $set[$row]{id} +]</td>
        <td>[+ $set[$row]{name} +]</td>
      </tr>
     </table>
     [+ $set -> PrevNextForm ('Previous Records',
     			  'Next Records',
     			  \%fdat) +]

Search erzeugt ein Recordsetobjekt
----------------------------------

   Search nimmt die Werte aus %fdat und benutzt diese um einen SQL WHERE
Ausdruck zu erzeugen. Auf diese Weise hängt es davon ab, was an das
Dokument für Daten gesandt werden, welche Anfrage ausgeführt wird.  z.B.
wenn man das Dokument mit http://host/mydoc.html?id=5 aufruft, werden alle
Datensätze deren Feld id den Wert 5 enthält angezeigt.

Die Daten können als Array oder mittels eines aktuellen Datensatzzeigers angesprochen werden
--------------------------------------------------------------------------------------------

   Das Ergebnis der Abfrage kann wie ein Array angesprochen werden (was
nicht heißt, daß das ganze Array auch tatsächlich von der Datenbank
angefordert wird).  Alternativ können die Felder des aktuellen Record
angesprochen werden.

     set[5]{id}   Zugriff auf das Feld 'id' des sechsten gefundenen Datensatzes
     set{id}      Zugriff auf das Feld 'id' des aktuellen Datensatzes

Felder können mit ihren Namen angesprochen werden
-------------------------------------------------

   Während bei DBI Feldinhalte hauptsächlich über ihre Spaltennummern
angesprochen werden, benutzt DBIx::Recordset Spaltennamen. Dies macht das
Programm einfacher zu schreiben, leichter verständlich und unabhäniger von
Veränderungen in der Datenbankstruktur.

PrevNextForm erzeugt keinen/einen/zwei Schaltflächen je nachdem ob weitere Datensätze angezeigt werden müssen
-------------------------------------------------------------------------------------------------------------

   Die PrevNextButtons Funktion kann dazu benutzt werden um Schaltflächen
zum Anzeigen der vorhergehenden bzw. folgenden Datensätze zu erzeugen.
`PrevNextForm' generiert ein kleines Formular welches alle nötigen Daten
als versteckte Felder enthält.

Wie fürs Suchen, gibt es auch Funktionen für Insert/Update/Delete
-----------------------------------------------------------------

   Beispiel für Insert

   Wenn `%fdat' die Daten für einen neuen Datensatz enthält, fügt der
folgende Code einen diesen der angegebenen Tabelle hinzu.

     [-*set = DBIx::Recordset -> Insert ({%fdat,
     				      ('!DataSource'   => $DSN,
     				       '!Table' => $table)}) ; -]

Datenbanktabellen können ebenso an einen Hash gebunden werden
-------------------------------------------------------------

   DBIx::Recordset kann ebenfalls eine Datenbanktabelle an einen Hash
binden. Man muß lediglich den Primärschlüssel der Tabelle angeben und kann
dann auf die Tabelle mittels eines Perl Hashs zugreifen.

     $set{5}{name}    Zugriff auf Feld 'name' mit id=5
     		     (id ist Primärschlüssel)

Arbeiten mit mehreren Tabellen
------------------------------

   DBIx::Recordset bietet zahlreiche Möglichkeiten um einfach mit mehreren
Tabellen umgehen zu können. DBIx::Recordset versucht auf Grund der Namen
innerhalb der Datenbank selbstständig Zusammenhänge zwischen Tabellen zu
erkennen.  Weitere Zusammenhänge können manuell angegeben werden.  Mit
diesen Informationen kann DBIx::Recordset automatisch Unterobjekte
erzeugen, die die zum entsprechenden Datensatz zugehörigen Datensätze der
verbundenen Tabelle enthalten. Ebenso ist es möglich das DBIx::Recordset
einer Abfrage automatisch Felder hinzufügt, die den referenzierten
Datensatz beschreiben. So ist es z.B. möglich, wenn in einer Tabelle die
Kundennr enthalten ist, aus dem Kundenstammsatz automatisch den Namen des
Kunden hinzuzufügen, ohne das diese jedesmal explizit angeben werden müßte.

Sicherheit
==========

   Bei der Ausführung unter mod_perl, teilt sich jeglicher Perlcode einen
Perlinterpreter. Das bedeutet, das jede Applikation auf alle Daten aller
anderen Applikationen zugreifen kann. Embperl verwaltet einen separaten
Namensraum für jedes Embperl Dokument, was ausreicht um versehentliches
Überschreiben von Daten anderer Applikationen zu verhindern.  Dieses
Verfahren bietet jedoch keine wirkliche Sicherheit.  Der Zugriff auf alle
Daten ist möglich durch die explizite Angabe eines Package Namens.

Safe namespaces
---------------

   Deshalb kann Embperl Safe.pm nutzen, um den Zugriff auf alle Namensräume
außerhalb des eigentlichen Skripts zu unterbinden. Dadurch wird es z.B.
möglich, Berechnungen innerhalb eines Perlmoduls durchzuführen und die
Ergebnisse an ein Embperl Dokument zu übergeben. Wenn dieses in einem
sicheren Namensraum läuft, kann es diese Ergebnisse darstellen, jedoch auf
keine anderen Daten zugreifen. Dadurch wird es sicher, verschiedene
Personen am Layout arbeiteten zu lassen.

Operatoren Einschränkungen
--------------------------

   Safe.pm erlaubt es dem Administrator jeden Perl Opcode zu sperren.
Dadurch wird es möglich zu kontrollieren, welche Perl Opcodes innerhalb
der Seiten genutzt werden dürfen.

Escaping/Unescaping
===================

Quellendaten: Unescaping
------------------------

   (sperren mit optRawInput)

     - konvertiert HTML escapes zu Zeichen (z.B. &lt; zu <)

     - entfernt HTML tags aus dem Perlcode (z.B. <br> welches durch einen
       HTML Editor eingefügt wurde)

Ausgabe: Escaping
-----------------

   (sperren mit escmode)

     - konvertiert Sonderzeichen nach HTML (z.B. < zu &lt;)

Extract links from an HTML document
***********************************

NAME
====

   HTML::LinkExtor - Extract links from an HTML document

SYNOPSIS
========

     require HTML::LinkExtor;
     $p = HTML::LinkExtor->new(\&cb, "http://www.sn.no/");
     sub cb {
         my($tag, %links) = @_;
         print "$tag @{[%links]}\n";
     }
     $p->parse_file("index.html");

DESCRIPTION
===========

   HTML::LinkExtor is an HTML parser that extracts links from an HTML
document.  The HTML::LinkExtor is a subclass of HTML::Parser. This means
that the document should be given to the parser by calling the $p->parse()
or $p->parse_file() methods.

$p = HTML::LinkExtor->new([$callback[, $base]])
     The constructor takes two optional arguments. The first is a reference
     to a callback routine. It will be called as links are found. If a
     callback is not provided, then links are just accumulated internally
     and can be retrieved by calling the $p->links() method.

     The $base argument is an optional base URL used to absolutize all
     URLs found.  You need to have the *URI* module installed if you
     provide $base.

     The callback is called with the lowercase tag name as first argument,
     and then all link attributes as separate key/value pairs.  All
     non-link attributes are removed.

$p->links
     Returns a list of all links found in the document.  The returned
     values will be anonymous arrays with the follwing elements:

          [$tag, $attr => $url1, $attr2 => $url2,...]

     The $p->links method will also truncate the internal link list.  This
     means that if the method is called twice without any parsing between
     them the second call will return an empty list.

     Also note that $p->links will always be empty if a callback routine
     was provided when the HTML::LinkExtor was created.

EXAMPLE
=======

   This is an example showing how you can extract links from a document
received using LWP:

     use LWP::UserAgent;
     use HTML::LinkExtor;
     use URI::URL;

     $url = "http://www.sn.no/";  # for instance
     $ua = new LWP::UserAgent;

     # Set up a callback that collect image links
     my @imgs = ();
     sub callback {
        my($tag, %attr) = @_;
        return if $tag ne 'img';  # we only look closer at <img ...>
        push(@imgs, values %attr);
     }

     # Make the parser.  Unfortunately, we don't know the base yet
     # (it might be diffent from $url)
     $p = HTML::LinkExtor->new(\&callback);

     # Request document and parse it as it arrives
     $res = $ua->request(HTTP::Request->new(GET => $url),
                         sub {$p->parse($_[0])});

     # Expand all image URLs to absolute ones
     my $base = $res->base;
     @imgs = map { $_ = url($_, $base)->abs; } @imgs;

     # Print them out
     print join("\n", @imgs), "\n";

SEE ALSO
========

   See HTML/Parser, HTML/Tagset,
LWP, URI/URL,

COPYRIGHT
=========

   Copyright 1996-2000 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

construct HTML from pleasing Perl data structures
*************************************************

NAME
====

   HTML::LoL - construct HTML from pleasing Perl data structures

SYNOPSIS
========

     use HTML::LoL;

     &hl(sub { print shift },
         [body => {bgcolor => 'white'},
          [p => 'Document body', ...], ...]);

   See EXAMPLE section below.

DESCRIPTION
===========

   This module allows you to use Perl syntax to express HTML.  The function
`hl()' converts Perl list-of-list structures into HTML strings.

   The first argument to `hl()' is a callback function that's passed one
argument: a fragment of generated HTML.  This callback is invoked
repeatedly with successive fragments until all the HTML is generated; the
callback is responsible for assembling the fragments in the desired output
location (e.g., a string or file).

   The remaining arguments to `hl()' are Perl objects representing HTML,
as follows:

[TAG, ...]
     TAG is a string (the name of an HTML element); remaining list items
     are any of the forms described herein.  Corresponds to
     <TAG>...</TAG>.  If TAG is an "empty element" according to
     `%HTML::Tagset::emptyElement', then the </TAG> is omitted.

[TAG => {*ATTR1* => *VAL1*, *ATTR2* => *VAL2*, ...}, ...]
     Corresponds to <TAG *ATTR1*="*VAL1*" *ATTR2*="*VAL2*" ...>...</TAG>.
     (As above, </TAG> is omitted if TAG is an "empty element.")  Each
     *ATTR* is a string.  Each *VAL* is either a string, in which case the
     value gets HTML-entity-encoded when copied to the output, or a list
     reference containing a single string (viz. [*VAL*]) in which case the
     value is copied literally.

     Finally, for boolean-valued attributes, *VAL* may be
     `hl_bool(BOOLEAN)', where BOOLEAN is a Perl expression.  If BOOLEAN
     is true, the attribute is included in the output; otherwise it's
     omitted.

Any string
     Strings are copied verbatim to the output after entity-encoding.

`hl_noquote(...)'
     Suppresses entity-encoding of its arguments.

`hl_requote(...)'
     Reenables entity-encoding of its arguments (use it inside a call to
     `hl_noquote()').

`hl_preserve(...)'
     Normally, HTML::LoL tries to optimize the whitespace in the HTML it
     emits (without changing the meaning of the HTML).  This suppresses
     that behavior within its arguments.

`hl_entity(NAME)'
     Includes the HTML character-entity named NAME.

EXAMPLE
=======

     &hl(sub { print shift },
         [table => {border => 2, width => '80%'},
          [tr =>
           [td => {nowrap => &hl_bool(1)}, 'This & that'],
           [td => {nowrap => &hl_bool(0)}, '<b>This is not bold</b>'],
           [td => [b => 'But this is']],
           [td => &hl_noquote('<b>And so is this</b>')]]]);

   prints:

     <table width="80%" border="2">
      <tr>
       <td nowrap>This &amp; that</td>
       <td>&lt;b&gt;This is not bold&lt;/b&gt;</td>
       <td><b>But this is</b></td>
       <td><b>And so is this</b></td>
      </tr>
     </table>

SEE ALSO
========

   perllol(1), HTML::Tree(3)

   This module was inspired by the `new_from_lol()' function in the
HTML::Tree package by Gisle Aas and Sean M. Burke.

COPYRIGHT
=========

   Copyright 2000 Bob Glickstein.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Bob Glickstein - http://www.zanshin.com/bobg/ - bobg@zanshin.com

High-performance, dynamic web site authoring system
***************************************************

NAME
====

   Mason - High-performance, dynamic web site authoring system

SYNOPSIS
========

     # Directives for your Apache config files.
     # Route all requests to the Mason handler.
     #
     PerlRequire /opt/mason/eg/handler.pl
     <Location />
         SetHandler perl-script
         PerlHandler HTML::Mason
     </Location>

     # Sample handler.pl file.
     # Start Mason and define the mod_perl handler routine.
     #
     package HTML::Mason;
     use HTML::Mason;
     use HTML::Mason::ApacheHandler;
     use strict;

     my $parser = new HTML::Mason::Parser;
     my $interp = new HTML::Mason::Interp (parser=>$parser,
                                    comp_root=>'/opt/www/htdocs',
                                    data_dir=>'/opt/mason/data');
     my $ah = new HTML::Mason::ApacheHandler (interp=>$interp);
     chown ( [getpwnam('nobody')]->[2], [getgrnam('nobody')]->[2],
             $interp->files_written );   # chown nobody

     sub handler
     {
         my ($r) = @_;
         $ah->handle_request($r);
     }

     1;

DESCRIPTION
===========

   Mason is a tool for building, serving and managing large web sites. Its
features make it an ideal backend for high load sites serving dynamic
content, such as online newspapers or database driven e-commerce sites.

   Mason's various pieces revolve around the notion of "components". A
component is a mix of HTML, Perl, and special Mason commands, one
component per file. So-called "top-level" components represent entire
web-pages, while smaller components typically return HTML snippets for
embedding in top-level components. This object-like architecture greatly
simplifies site maintenance: change a shared component, and you instantly
changed all dependant pages that refer to it across a site (or across many
virtual sites).

   Mason's component syntax lets designers separate a web page into
programmatic and design elements. This means the esoteric Perl bits can be
hidden near the bottom of a component, preloading simple variables for use
above in the HTML. In our own experience, this frees content managers
(i.e., non-programmers) to work on the layout without getting mired in
programming details. Techies, however, still enjoy the full power of Perl.

   One of the best ways to learn about Mason is to explore the samples/
directory created during installation. There you will find a collection of
components, simple to complex, illustrating most of Mason's component
syntax.

   Other Mason features include:

Caching
     Mason caches components after compilation, and offers an internal,
     shared, expireable data cache for use by components themselves.

Debugging
     Mason includes a debugging mode whereby HTTP requests can be captured
     to "debug files" for later replay inside Perl's command-line debugger
     (as opposed to the non-interactive mod_perl interpreter).

Templating
     The autohandler and dhandler features make it easy to apply a common
     header, footer, or filtering function to an entire directory or
     hierarchy of pages.

Previewer
     Mason includes a powerful previewing utility which acts as a proxy
     between Mason and incoming requests. Using a web interface, users
     create "port profiles" that massage requests in all kinds of
     interesting ways: different browsers may be simulated, different
     request ports, different times of day, etc.

Standalone Use
     Mason is optimized for use with mod_perl, but can also be used from
     CGI or as a standalone tool to generate other types of dynamic text
     files (similar to Text::Template, ePerl, etc.). To learn more about
     this option see the STANDALONE MODE section in *HTML::Mason::Interp*.

   Mason works by intercepting innocent-looking requests (say,
http://www.yoursite.com/index.html) and mapping them to requests for Mason
components.  Mason then compiles the component, runs it, and feeds the
output back to the client.

   Consider this simple Mason component:

     % my $noun = 'World';
     Hello <% $noun %>!
     How are ya?

   The output of this component is:

     Hello World!
     How are ya?

   In this component you see a mix of standard HTML and Mason elements.
The bare '%' prefixing the first line tells Mason that this is a line of
Perl code. One line below, the embedded <% ... %> tag gets replaced with
the return value of its contents, evaluated as a Perl expression.

   Beyond this trivial example, components can also embed serious chunks
of Perl code (say, to pull records from a database). They can also call
other components, cache results for later reuse, and perform all the
tricks you expect from a regular Perl program. See *HTML::Mason::Devel*
for a full tutorial on building, using and debugging Mason components.

INSTALLATION
============

   Mason has been tested under Linux, FreeBSD, Solaris, HPUX, and Win32.
As an all-Perl solution, it should work on any machine that has working
versions of Perl 5.004+, mod_perl, and the required CPAN modules.

   Mason has a standard MakeMaker-driven installation. See the README file
for details.

CONFIGURING MASON
=================

   Mason's configuration depends on two files: your Apache `conf' files
(httpd.conf or `srm.conf'), into which you insert directives to activate
Mason's request handler, and Mason's handler.pl file which runs at Apache
startup. handler.pl does two things: it starts up Mason (which then runs
persistently within the httpd), and it defines a handler routine to
receive HTTP requests.

   The paragraphs below assume some knowledge of mod_perl, Apache
configuration details, and the Apache request API. If you're rusty on any
these topics, bone up by reading the documentation available at
http://www.apache.org (Apache) and http://perl.apache.org (mod_perl). Here
you will also find subscription details for the mod_perl mailing list-in
my view the best mod_perl resource around.

Single Site Configuration
-------------------------

   The simplest Mason component is one composed of pure HTML, so the fast
track is simply to attach Mason to some branch of your server's
DocumentRoot, like so:

     # Additions to your httpd.conf
     PerlRequire /usr/local/mason/handler.pl

     Alias /mason /usr/local/www/htdocs
     <Location /mason>
         SetHandler perl-script
         PerlHandler HTML::Mason
     </Location>

   These directives tell Apache to first run handler.pl, the Mason startup
file. The "Alias" then maps any "/mason" URLs into the DocumentRoot
(assuming the DocumentRoot is /usr/local/www/htdocs).  Finally, the
<Location> directive routes those requests to the handler routine
`HTML::Mason::handler'.

   If you want to create HTML without necessarily using the .html
extension, change your DefaultType:

     DefaultType text/html

   and make sure mod_mime_magic is not active.

   That's it for the Apache configuration. Next you will need to configure
Mason's handler.pl file, a sample of which is in `eg/handler.pl' in the
Mason distribution. Here you must make some decisions:

Where is the component root (comp_root)?
     Mason introduces the idea of a "component root" which, like the
     DocumentRoot, is a virtual root for the component filesystem. In this
     example we equate the two roots; other configurations will opt to keep
     them separate.

Where is the data directory (data_dir)?
     Mason generates various data files, which live in topical directories
     under Mason's "data directory".

What is the UID and GID that the server runs under?
     If your web server is running on a privileged port like 80, the parent
     process runs as root and spawns children under the 'User' and 'Group'
     IDs listed in your httpd.conf. To prevent ownership and permission
     conflicts, set the chown() parameters to match the UID and GID from
     your httpd.conf. See the handler section in the *Administrator's
     Guide* guide for details.

Do you plan to intermix images and components in the same directory?
     If you use a <Location> or <Directory> directive like the one
     suggested above, then requests to any file under that directory will
     go to the Mason handler. If there are images in the directory, Mason
     will try to treat them like regular components. This is bad: not only
     is there extra overhead, but if an image inadvertently contains a
     Mason character sequence such as "<%", Mason will try to interpret
     that piece and fail with a syntax error.

     The simplest remedy is to have Mason decline image and other non-HTML
     requests, thus letting Apache serve them in the normal way.  The
     following line

          return -1 if $r->content_type && $r->content_type !~ m|^text/|i;

     declines all requests with a content type not starting with "text/".
     This allows text/html and text/plain to pass through but not much
     else.  It is included (commented out) in the default handler.pl.

Are you running with taint checks (e.g. PerlTaintCheck)?
     If so, pass the flag taint_check=>1 when creating the parser; this
     tells Mason to untaint component code and filenames.

   Both comp_root and the data_dir are set when Mason creates a new Interp
object:

     my $interp = new HTML::Mason::Interp (parser=>$parser,
                     comp_root=>'/usr/local/www/htdocs'
                     data_dir=>'/usr/local/mason/');

   Set these to your own locations, then restart the server and go to some
standard URL on your site, prefixing the URL with "/mason". If all goes
well you should see the same page as without the "/mason" prefix. If not,
recheck your Apache config files and handler.pl, and also tail your
server's error log.

   If you are getting erroneous "404 Not Found" errors, Mason may be
having trouble with your document and component root. Remember that all
files handled by Mason must fall underneath the component root.  One
situation that will unfortunately confuse Mason is if your document or
component root goes through a soft link. Try specifying your document and
component root settings in terms of the true path.

   Assuming it worked, you now have a Mason "lens" through which to view
your HTML tree. Try adding a Mason tag to some HTML file, say <% 2+2 %>.
If you hit Reload and see a "4", Mason's up and running. You can now copy
or link the `samples/' directory into your new comp_root and check out the
sample components in your browser.

   Once you feel comfortable with Mason, you can "fully" install it by
deleting the "Alias" directive from your httpd.conf, and changing the
<Location> mapping from "/mason" to just "/". Now all URLs serve through
Mason. If you want to maintain a few directories that don't serve through
Mason (e.g. for images), you can put in overrides like so:

     <Location /plain>
             SetHandler default-handler
     </Location>

   *HTML::Mason::Admin* describes how to configure Mason to work with
multiple virtual servers on the same box.

DOCUMENTATION ROADMAP
=====================

   Once Mason is on its feet, the next step is to write a component or
two. The *Mason Developer's Manual* (*HTML::Mason::Devel*) is a complete
tutorial for writing, using, and debugging components. A reference
companion to the Developer's Manual is the Request API documentation,
*HTML::Mason::Request*.

   Whoever is responsible for setting up and tuning Mason should read the
*Administrator's Manual* (*HTML::Mason::Admin*).  Details of Mason's core
modules can be found in *HTML::Mason::Parser*, *HTML::Mason::Interp*, and
*HTML::Mason::ApacheHandler*.

   Most of this documentation assumes that you're running Mason on top of
mod_perl, since that is the most common configuration.  If you are using
Mason outside of mod_perl, the documentation is still valid; you'll just
have to ignore mod_perl specific references like $r and the ApacheHandler
object, and you'll want to read the STANDALONE MODE section in
*HTML::Mason::Interp*.

AUTHOR
======

   Jonathan Swartz, swartz@pobox.com

SEE ALSO
========

   HTML::Mason::Components, HTML::Mason::Request, HTML::Mason::Parser,
HTML::Mason::Interp, HTML::Mason::ApacheHandler

Mason Administrator's Guide
***************************

NAME
====

   HTML::Mason::Admin - Mason Administrator's Guide

DESCRIPTION
===========

   This guide is intended for the sys admin/web master in charge of
installing, configuring, or tuning a Mason system.

PIECES OF AN INSTALLATION
=========================

   This section discusses the various files and directories that play a
part in Mason's configuration.

Config.pm
---------

   Config.pm contains global configuration options for Mason.  Makefile.PL
will initially create the file based on your environment, placing it in
the `lib/HTML/Mason' subdirectory of the distribution.  After that, you
can edit it by hand, following the comments inside.

   "make install" copies Config.pm to your Perl library directory (e.g.
`/usr/lib/perl5/site_perl/HTML/Mason') along with the other module files.
This allows Mason internally to grab the configuration data with "`use
HTML::Mason::Config'".

   When upgrading from a previous version, "make install" will maintain
the previous Config.pm values.

   Currently this file controls:

   o Whether or not certain optional modules, such as Time::HiRes, should
be loaded for enhanced features.

   o The type of DBM and the serialization method used for Mason's data
caching. If you plan to use data caching, make sure that the DBM package
is a good-quality one (DB_File or GDBM_File).

httpd.conf, srm.conf
--------------------

   Directives must be added to Apache's configuration files to specify
which requests should be handled through Mason, and the handler used for
those requests. As described in *HTML::Mason*, a simple configuration
looks like:

     DocumentRoot /usr/local/www/htdocs
     PerlRequire /usr/local/mason/handler.pl
     DefaultType text/html
     <Location />
         SetHandler perl-script
         PerlHandler HTML::Mason
     </Location>

handler.pl
----------

   This file contains startup code that initializes the parent Apache
process. It also defines the handler used by each child process to field
Mason requests. See the synopsis in *HTML::Mason* for a simple example.
The next section discusses in detail how to configure this file.

CONFIGURING THE HANDLER SCRIPT
==============================

   Handler.pl is the most important file in your Mason configuration.  It
is responsible for creating the three Mason objects and supplying the many
parameters that control how your components are parsed and executed. It
also provides the opportunity to execute arbitrary code at three important
junctures: the server initialization, the beginning of a request, and the
end of a request.  A wide set of behaviors can be implemented with a mere
few lines of well-placed Perl in your handler.pl.  In this section we
present the basics of setting up handler.pl as well as some ideas for more
advanced applications.

Creating the Mason objects
--------------------------

   handler.pl creates three Mason objects: the Parser, Interpreter, and
ApacheHandler. The Parser compiles components into Perl subroutines; the
Interpreter executes those compiled components; and the Apache handler
routes mod_perl requests to Mason.  These objects are created once in the
parent httpd and then copied to each child process.

   These objects have a fair number of possible parameters. Only two of
them are required, comp_root and data_dir; these are discussed in the next
two subsections. The various parameters are documented in the individual
reference manuals for each object: *HTML::Mason::Parser*,
*HTML::Mason::Interp*, and *HTML::Mason::ApacheHandler*.

   The advantage of embedding these parameters in objects is that advanced
configurations can create more than one set of objects, choosing which set
to use at request time.  For example, suppose you have a staging site and
a production site running on the same web server, distinguishing between
them with a configuration variable called version:

     # Create Mason objects for staging site
     my $parser1 = new HTML::Mason::Parser;
     my $interp1 = new HTML::Mason::Interp (parser=>$parser1, ...);
     my $ah1 = new HTML::Mason::ApacheHandler (interp=>$interp1);

     # Create Mason objects for production site
     my $parser2 = new HTML::Mason::Parser;
     my $interp2 = new HTML::Mason::Interp (parser=>$parser2, ...);
     my $ah2 = new HTML::Mason::ApacheHandler (interp=>$interp2);

     sub handler {
         ...

     # Choose the right ApacheHandler
     if ($r->dir_config('version') eq ' staging') {
         $ah1->handle_request($r);
     } else {
         $ah2->handle_request($r);
     }
         }

Component root
--------------

   Given a tree of component source files, the top of the tree is called
the component root and is set via the comp_root parameter. In simple Mason
configurations the component root is the same as the server's
DocumentRoot.  More complex configurations may specify several different
document roots under a single component root.

   When Mason handles a request, the request filename (`$r->filename') must
be underneath your component root - that way Mason has a legitimate
component to start with.  If the filename is not under the component root,
Mason will place a warning in the error logs and return a 404.
Unfortunately if your component root or document root goes through a soft
link, Mason will have trouble comparing the paths and will return 404. To
fix this, set your document root to the true path.

Component roots (multiple)
--------------------------

   If you are just starting out it is probably safe to skip this section
initially.

   Starting in Mason 0.8 it is now possible to specify multiple component
roots to be searched in the spirit of Perl's `@INC'. To do so you must
specify a list of lists:

     comp_root => [[key1, root1], [key2, root2], ...]

   Each pair consists of a key and root.  The key is a string that
identifies the root mnemonically to a component developer. Keys are
case-insensitive and must be distinct.

   For example:

     comp_root => [[private=>'/usr/home/joe/comps'], [main=>'/usr/local/www/htdocs']]

   This specifies two component roots, a main component tree and a private
tree which overrides certain components.  The order is respected ala
`@INC', so private is searched first and main second.  (I chose the `=>'
notation here because it looks cleaner, but note that this is a list of
lists, not a hash.)

   The key has several purposes. Object and data cache filenames use the
(uppercased) key to make sure different components sharing the same path
have different cache and object files. For example, if a component /foo/bar
is found in 'private', then the object file will be

     <data_dir>/obj/PRIVATE/foo/bar

   and the cache file

     <data_dir>/cache/PRIVATE+2ffoo+2fbar

   The key is also included whenever Mason prints the component title, as
in an error message:

     error while executing /foo/bar [private]:
     ...

   This lets you know which version of the component was running.

Data directory
--------------

   The data directory is where Mason keeps various files to help implement
caching, debugging, etc. You specify a single data directory via the
data_dir parameter and Mason creates subdirectories underneath it as
needed:

     cache:    data cache files
     debug:    debug files
     etc:      miscellaneous files
     obj:      compiled components
     preview:  preview settings files

   These directories will be discussed in appropriate sections throughout
this manual.

External modules
----------------

   Components will often need access to external Perl modules. Any such
modules that export symbols should be listed in handler.pl, rather than
the standard practice of using a PerlModule configuration directive. This
is because components are executed inside the *HTML::Mason::Commands*
package, and can only access symbols exported to that package. Here's
sample module list:

     { package HTML::Mason::Commands;
       use CGI ':standard';
       use LWP::UserAgent;
       ... }

   In any case, for optimal memory utilization, make sure all Perl modules
are used in the parent process, and not in components. Otherwise, each
child allocates its own copy and you lose the benefit of shared memory
between parent processes and their children. See Vivek Khera's mod_perl
tuning FAQ (perl.apache.org/tuning) for details.

File ownership
--------------

   Unix web servers that run on privileged ports like 80 start with a root
parent process, then spawn children running as the 'User' and 'Group'
specified in httpd.conf. This difference leads to permission errors when
child processes try to write files or directories created by the parent
process.

   To work around this conflict, Mason remembers all directories and files
created at startup, returning them in response to `interp->files_written'.
This list can be fed to a chown() at the end of the startup code in
handler.pl:

     chown (scalar(getpwnam "nobody"), scalar(getgrnam "nobody"),
             $interp->files_written);

Persistent user sessions
------------------------

   With just a few lines in handler.pl you can make a global hash (e.g.
*%session*) available to all components containing persistent user session
data.  If you set a value in the hash, you will see the change in future
visits by the same user.  The key piece is Jeffrey Baker's
*Apache::Session* module, available from CPAN.

   The file `eg/session_handler.pl' in the distribution contains the lines
to activate cookie-based sessions using Apache::Session and CGI::Cookie.
You can use `eg/session_handler.pl' as your new handler.pl base, or just
copy out the appropriate pieces to your existing handler.pl.

   The session code is customizable; you can change the user ID location
(e.g. URL instead of cookie), the user data storage mechanism (e.g. DBI
database), and the name of the global hash.

Using global variables
----------------------

   Global variables generally make programs harder to read, maintain, and
debug, and this is no less true for Mason.  Due to the persistent mod_perl
environment, globals require extra initialization and cleanup care. And
the highly modular nature of Mason pages does not mix well with globals:
it is no fun trying to track down which of twenty components is stepping
on your variable. With the ability to pass parameters and declare lexical
(my) variables in components, there is very little need for globals at all.

   That said, there are times when it is very useful to make a value
available to all Mason components: a DBI database handler, a hash of user
session information, the server root for forming absolute URLs.  Usually
you initialize the global in your handler.pl, either outside the handler()
subroutine (if you only need to set it once) or inside (if you need to set
it every request).

   Mason by default parses components in strict mode, so you can't simply
start referring to a new global or you'll get a fatal warning. The
solution is to invoke `use vars' inside the package that components
execute in, by default *HTML::Mason::Commands*:

     { package HTML::Mason::Commands;
       use vars qw($dbh %session);
     }

   Alternatively you can use the Parser/allow_globals parameter or method:

     my $parser = new HTML::Mason::Parser (..., allow_globals => [qw($dbh %session)]);
     $parser->allow_globals(qw($foo @bar))

   The only advantage to allow_globals is that it will do the right thing
if you've chosen a different package for components to run in (via the
Parser/in_package Parser parameter.)

   Similarly, to initialize the variable in handler.pl, you need to set it
in the component package:

     $HTML::Mason::Commands::dbh = DBI->connect(...);

   Alternatively you can use the Interp/set_global Interp method:

     $interp->set_global(dbh => DBI->connect(...));

   Again, set_global will do the right thing if you've chosen a different
package for components.

   Now when referring to these globals inside components, you can use the
plain variable name:

     $dbh->prepare...

Declining image requests
------------------------

   Mason should be prevented from serving images, tarballs, and other
binary files as regular components. Such a file may inadvertently contain
a Mason character sequence such as "<%", causing an error.

   There are several ways to restrict which file types are handled by
Mason.  One way is with a line at the top of handler(), e.g.:

     return -1 if $r->content_type && $r->content_type !~ m|^text/|i;

   This line allows text/html and text/plain to pass through but not much
else.  It is included (commented out) in the default handler.pl.

   Another way is specifying a filename pattern in the Apache
configuration, e.g.:

     <FilesMatch "(\.html|\.txt|^[^\.]+)$>
     SetHandler perl-script
     PerlHandler HTML::Mason
     </FilesMatch>

   This directs Mason to handle only files with .html, .txt, or no
extension.

Securing top-level components
-----------------------------

   Users may exploit a server-side scripting environment by invoking
scripts with malicious or unintended arguments. Mason administrators need
to be particularly wary of this because of the tendency to break out
"subroutines" into individually accessible file components.

   For example, a Mason developer might create a helpful shared component
for performing sql queries:

     $m->comp('sql_select', table=>'employee', where=>'id=315');

   This is a perfectly reasonable component to create and call internally,
but clearly presents a security risk if accessible via URL:

     http://www.foo.com/sql_select?table=credit_cards&where=*

   Of course a web user would have to obtain the name of this component
through guesswork or other means, but obscurity alone does not properly
secure a system.  Rather, you should choose a site-wide policy for
distinguishing top-level components from private components, and make sure
your developers stick to this policy. You can then prevent private
components from being served.

   One solution is to place all private components inside a directory, say
/private, that lies under the component root but outside the document root.

   Another solution is to decide on a naming convention, for example, that
all private components begin with "_", or that all top-level components
must end in ".html". Then turn all private requests away with a 404
NOT_FOUND (rather than, say, a 403 FORBIDDEN which would provide more
information than necessary). Use either an Apache directive

     <FilesMatch "^_">
     SetHandler perl-script
     PerlHandler "sub { return 404 }"
     </FilesMatch>

   or a handler.pl directive:

     return 404 if $r->filename =~ m{_[^/]+$};

   Even after you've safely protected internal components, top-level
components that process arguments (such as form handlers) still present a
risk. Users can invoke such a component with arbitrary argument values via
a handcrafted query string. Always check incoming arguments for validity
and never place argument values directly into SQL, shell commands, etc.
Unfortunately, Mason does not yet work with with Perl's taint checking
which would help ensure these principles.

Allowing directory requests
---------------------------

   By default Mason will decline requests for directories, leaving Apache
to serve up a directory index or a FORBIDDEN as appropriate.
Unfortunately this rule applies even if there is a dhandler in the
directory: /foo/bar/dhandler does not get a chance to handle a request for
/foo/bar.

   If you would like Mason to handle directory requests, do the following:

   1. Set the ApacheHandler/decline_dirs ApacheHandler parameter to 0.

   2. If your handler.pl contains the standard "return -1" line to decline
non-text requests (as given in the previous section), add a clause
allowing directory types:

     return -1 if $r->content_type && $r->content_type !~ m|^text/|i
                  && $r->content_type !~ m|directory$|i;

   The dhandler that catches a directory request is responsible for
setting a reasonable content type.

STANDARD FEATURES
=================

   This section explains how standard Mason features work and how to
administer them.

Data caching
------------

Setup
     Cache files are implemented using *MLDBM*, an interface for storing
     persistent multi-level data structures. *MLDBM*, in turn, uses one of
     several DBM packages (DB_File, *GDBM*) and one of several
     serialization mechanisms (Data::Dumper, *FreezeThaw* or Storable).
     Mason's Config.pm controls which packages are used.

     The most important task is selecting a good DBM package.  Most
     standard DBM packages (*SDBM*, *ODBM*, *NDBM*) are unsuitable for
     data caching due to significant limitations on the size of keys and
     values. Perl only comes with *SDBM*, so you'll need to obtain a
     good-quality package if you haven't already. At this time the best
     options are Berkeley DB (DB_File) version 2.x, available at
     www.sleepycat.com, and GNU's gdbm (*GDBM*), available at GNU mirror
     sites everywhere. Stay away from Berkeley DB version 1.x on Linux
     which has a serious memory leak (and is unfortunately pre-installed on
     many distributions).

     As far as the serialization methods, all of them should work fine.
     Data::Dumper is probably simplest: it comes with the latest versions
     of Perl, is required by Mason anyway, and produces readable output
     (possibly useful for debugging cache files).  On the other hand
     Storable is significantly faster than the other options according to
     the MLDBM documentation.

     Data caching will not work on systems lacking flock(), such as Windows
     95 and 98.

Administration
     Once set up, data caching requires little administration. When a
     component calls `$m->cache' or `$m->cache_self' for the first time,
     Mason automatically creates a new cache file under `data_dir/cache'.
     The name of the file is determined by encoding the path as follows:

          s/([^\w\.\-\~])/sprintf('+%02x', ord $1)/eg;

     like URL encoding with a '+' escape character. For example, the cache
     file for component `/foo/bar' is `data_dir/cache/foo+2fbar'.

     Currently Mason never deletes cache files, not even when the
     associated component file is modified.  (This may change in the near
     future.)  Thus cache files hang around and grow indefinitely.  You
     may want to use a cron job or similar mechanism to delete cache files
     that get too large or too old.  For example:

          # Shoot cache files more than 30 days old
          foreach (<data_dir/cache>) {    # path to cache directory
              unlink $_ if (-M >= 30);
          }

     In general you can feel free to delete cache files periodically and
     without warning, because the data cache mechanism is explicitly not
     guaranteed - developers are warned that cached data may disappear
     anytime and components must still function.

     If some reason you want to disable data caching, specify
     use_data_cache=>0 to the Interp object. This will cause all
     `$m->cache' calls to return undef without doing anything.

Debugging
---------

   A debug file is a Perl script that creates a fake Apache request object
($r) and calls the same PerlHandler that Apache called.  Debug files are
created under `data_dir/debug/<username>' for authenticated users,
otherwise they are placed in `data_dir/debug/anon'.  Several ApacheHandler
parameters are required to activate and configure debug files:

debug_mode
     The debug_mode parameter indicates which requests should produce a
     debug file: "all", "none", or "error" (only if a error occurs).

debug_perl_binary
     The full path to your Perl binary - e.g. `/usr/bin/perl'. This is
     used in the Unix "shebang" line at the top of each debug file.

debug_handler_script
     The full path to your handler.pl script. Debug files invoke
     handler.pl just as Apache does as startup, to load needed modules and
     create Mason objects.

debug_handler_proc
     The name of the request handler defined in handler.pl. This routine
     is called with the saved Apache request object.

   Here's a sample `ApacheHandler' constructor with all debug options:

     my $ah = new HTML::Mason::ApacheHandler (interp=>$interp,
                debug_mode=>'all',
                debug_perl_binary=>'/usr/local/bin/perl',
                debug_handler_script=>'/usr/local/mason/eg/handler.pl',
                debug_handler_proc=>'HTML::Mason::handler');

   When replaying a request through a debug file, the global variable
`$HTML::Mason::IN_DEBUG_FILE' will be set to 1.  This is useful if you
want to omit certain flags (like preloading) in handler.pl when running
under debug.  For example:

     my %extra_flags = ($HTML::Mason::IN_DEBUG_FILE) ? () : (preloads=>[...]);
     my $interp = new HTML::Mason::Interp (..., %extra_flags);

Previewer
---------

   The previewer is a web based utility that allows site developers to:

  1. View a site under a variety of simulated client conditions: browser,
     operating system, date, time of day, referer, etc.

  2. View a debug trace of a page, showing the component call tree and
     indicating which parts of the page are generated by which components.

        The web-based previewer interface (a single component, actually)
allows the developer to select a variety of options such as time, browser,
and display mode.  The set of these options together is called a previewer
configuration. Configurations can be saved under one of several preview
ports. For more information on how the previewer is used, see
*HTML::Mason::Devel*.

   Follow these steps to activate the Previewer:

  1. Choose a set of preview ports, for example, 3001 to 3005.

  2. In httpd.conf, put a Listen in for each port.  E.g.

          Listen your.site.ip.address:3001
          ...
          Listen your.site.ip.address:3005

     You'll also probably want to restrict access to these ports in your
     access.conf. If you have multiple site developers, it is helpful to
     use username/password access control, since the previewer will use the
     username to keep configurations separate.

  3. In your handler.pl, add the line

          use HTML::Mason::Preview;

     somewhere underneath "use HTML::Mason". Then add code to your handler
     routine to intercept Previewer requests on the ports defined above.
     Your handler should end up looking like this:

          sub handler {
              my ($r) = @_;

          # Compute port number from Host header
          my $host = $r->header_in('Host');
          my ($port) = ($host =~ /:([0-9]+)$/);
          $port = 80 if (!defined($port));

          # Handle previewer request on special ports
          if ($port >= 3001 && $port <= 3005) {
              my $parser = new HTML::Mason::Parser(...);
              my $interp = new HTML::Mason::Interp(...);
              my $ah = new HTML::Mason::ApacheHandler (...);
              return HTML::Mason::Preview::handle_preview_request($r,$ah);
          } else {
              $ah->handle_request($r);    # else, normal request handler
          }
              }

     The three "new" lines inside the if block should look exactly the same
     as the lines at the top of handler.pl. Note that these separate Mason
     objects are created for a single request and discarded. The reason is
     that the previewer may alter the objects' settings, so it is safer to
     create new ones every time.

  4. Copy the Previewer component ("samples/preview") to your component
     root (you may want to place it at the top level so that
     http://www.yoursite.com/preview calls up the previewer interface).
     Edit the "CONFIGURATION" block at the top to conform to your own Mason
     setup.

        To test whether the previewer is working: restart your server, go
to the previewer interface, and click "View".  You should see your site's
home page.

System logs
-----------

   Mason will log various events to a system log file if you so desire.
This can be useful for performance monitoring and debugging.

   The format of the system log was designed to be easy to parse by
programs, although it is not unduly hard to read for humans.  Every event
is logged on one line. Each line consists of multiple fields delimited by
a common separator, by default ctrl-A. The first three fields are always
the same: time, the name of the event, and the current pid ($$).  These
are followed by one or more fields specific to the event.

   The events are:

     EVENT NAME	DESCRIPTION			EXTRA FIELDS

     REQ_START	start of HTTP request		request number, URL + query string
     REQ_END	end of HTTP request		request number, error flag (1 if
     						error occurred, 0 otherwise)
     CACHE_READ	attempt to read from		component path, cache key, success
     		data cache (C<$m-Greater_Than_Special_Sequencecache>)	flag (1 if item found, 0 otherwise)
     CACHE_STORE	store to data cache		component path, cache key
     COMP_LOAD	component loaded into memory	component path
     		for first time

   The request number is an incremental value that uniquely identifies
each request for a given child process. Use it to match up
REQ_START/REQ_END pairs.

   To turn on logging, specify a string value to system_log_events
containing one or more event names separated by '|'. In additional to
individual event names, the following names can be used to specify
multiple events:

     REQUEST = REQ_START | REQ_END
     CACHE = CACHE_READ | CACHE_STORE
     ALL = All events

   For example, to log REQ_START, REQ_END, and COMP_LOAD events, you could
use     system_log_events => "REQUEST|COMP_LOAD" Note that this is a
string, not a set of constants or'd together.

   Configuration Options

   By default, the system log will be placed in data_dir/etc/system.log.
You can change this with system_log_file.

   The default line separator is ctrl-A. The advantage of this separator
is that it is very unlikely to appear in any of the fields, making it easy
to split() the line.  The disadvantage is that it will not always display,
e.g. from a Unix shell, making the log harder to read casually.  You can
change the separator to any sequence of characters with
system_log_separator.

   The time on each log line will be of the form "seconds.microseconds" if
you are using Time::HiRes, and simply "seconds" otherwise.  See Config.pm
section.

   *Sample Log Parser*

   Here is a code skeleton for parsing the various events in a log.  You
can also find this in `eg/parselog.pl' in the Mason distribution.

     open(LOG,"mason.log");
     while (<LOG>) {
         chomp;
         my (@fields) = split("\cA");
         my ($time,$event,$pid) = splice(@fields,0,3);
         if ($event eq 'REQ_START') {
             my ($reqnum,$url) = @fields;
             ...
         } elsif ($event eq 'REQ_END') {
             my ($reqnum,$errflag) = @fields;
             ...
         } elsif ($event eq 'CACHE_READ') {
             my ($comp,$key,$hitflag) = @fields;
             ...
         } elsif ($event eq 'CACHE_STORE') {
             my ($comp,$key) = @fields;
             ...
         } elsif ($event eq 'COMP_LOAD') {
             my ($comp) = @fields;
             ...
         } else {
             warn "unrecognized event type: $event\n";
         }
     }

   *Suggested Uses*

   Performance: REQUEST events are useful for analyzing the performance of
all Mason requests occurring on your site, and identifying the slowest
requests. `eg/perflog.pl' in the Mason distribution is a log parser that
outputs the average compute time of each unique URL, in order from slowest
to quickest.

   Server activity: REQUEST events are useful for determining what your
web server children are working on, especially when you have a runaway.
For a given process, simply tail the log and find the last REQ_START event
with that process id. (You can also use the Apache status page for this.)

   Cache efficiency: CACHE events are useful for monitoring cache "hit
rates" (number of successful reads over total number of reads) over all
components that use a data cache.  Because stores to a cache are more
expensive than reads, a high hit rate is essential for the cache to have a
beneficial effect. If a particular cache hit rate is too low, you may want
to consider changing how frequently it is expired or whether to use it at
all.

   Load frequency: COMP_LOAD events are useful for monitoring your code
cache. Too many loads may indicate that your code cache is too small.
Also, if you can turn off the code cache for a short time, COMP_LOAD
events will tell you which components are loaded most often and thus good
candidates for preloading.

PERFORMANCE TUNING
==================

   This section explains Mason's various performance enhancements and how
to administer them.

Code cache
----------

   When Mason loads a component, it places it in a memory cache.

   The maximum size of the cache is specified with the
Interp/code_cache_max_size Interp parameter; default is 10MB.  When the
cache fills up, Mason frees up space by discarding a number of components.
The discard algorithm is least frequently used (LFU), with a periodic
decay to gradually eliminate old frequency information. In a nutshell, the
components called most often in recent history should remain in the cache.
Very large components (over 20% of the maximum cache size) never get
cached, on the theory that they would force out too many other components.

   Note that the "size" of a component in memory cannot literally be
measured.  It is estimated by the length of the source text plus some
overhead.  Your process growth will not match the code cache size exactly.

   You can monitor the performance of the memory cache by turning on
system logs and counting the COMP_LOAD events. If these are occurring
frequently even for a long-running process, you may want to increase the
size of your code cache.

   You can prepopulate the cache with components that you know will be
accessed often; see Preloading. Note that preloaded components possess no
special status in the cache and can be discarded like any others.

   Naturally, a cache entry is invalidated if the corresponding component
source file changes.

   To turn off code caching completely, set Interp/code_cache_max_size to
0.

Object files
------------

   The in-memory code cache is only useful on a per-process basis.  Each
process must build and maintain its own cache. Shared memory caches are
conceivable in the future, but even those will not survive between web
server restarts.

   As a secondary, longer-term cache mechanism, Mason stores a compiled
form of each component in an object file under
`data_dir/obj/*component-path*'. Any server process can eval the object
file and save time on parsing the component source file.  The object file
is recreated whenever the source file changes.

   Besides improving performance, object files are essential for debugging
and interpretation of errors.  Line numbers in error messages are given in
terms of the object file. The curious-minded can peek inside an object
file to see exactly how Mason converted a given component to a Perl object.

   If you change any Parser options, you must remove object files
previously created under that parser for the changes to take effect.

   If for some reason you don't want Mason to create object files, set the
Interp/use_object_files Interp parameter to 0.

Preloading
----------

   You can tell Mason to preload a set of components in the parent
process, rather than loading them on demand, using the Interp/preloads
Interp parameter.  Each child server will start with those components
loaded in the memory cache. The trade-offs are:

time
     a small one-time startup cost, but children save time by not having
     to load the components

memory
     a fatter initial server, but the memory for preloaded components are
     shared by all children.  This is similar to the advantage of using
     modules only in the parent process.

   Try to preload components that are used frequently and do not change
often.  (If a preloaded component changes, all the children will have to
reload it from scratch.)

Reload file
-----------

   Normally, every time Mason executes a component, it checks the last
modified time of its source file to see if it needs to be reloaded.  These
file checks are convenient for development, but for a production site they
degrade performance unnecessarily.

   To remedy this, Mason has an accelerated mode that changes its behavior
in two ways:

   1.  Does not check component source files at all, relying solely on
object files.  This means the developer or an automated system is
responsible for recompiling any components that change and recreating
object files, using the Parser/make_component Parser method.

   2.  Rather than continuously checking whether object files have
changed, Mason monitors a "reload file" containing an ever-growing list of
components that have changed.  Whenever a component changes, the developer
or an automated system is responsible for appending the component path to
the reload file. The reload file is kept in `data_dir/etc/reload.lst'.

   You can activate this mode with the Interp/use_reload_file Interp
method.

   The advantage of using this mode is that Mason stats one file per
request instead of ten or twenty.  The disadvantage is a increase in
maintenance costs as the object and reload files have to be kept
up-to-date.  Automated editorial tools, and cron jobs that periodically
scan the component hierarchy for changes, are two possible solutions.  The
Mason content management system automatically handles this task.

STAGING vs. PRODUCTION
======================

   Site builders often maintain two versions of their sites: the
production (published) version visible to the world, and the development
(staging) version visible internally.  Developers try out changes on the
staging site and push the pages to production once they are satisfied.

   The priorities for the staging site are rapid development and easy
debugging, while the main priority for the production site is performance.
This section describes various ways to adapt Mason for each case.

Out mode
--------

   Mason can spew data in two modes. In "batch" mode Mason computes the
entire page in a memory buffer and then transmits it all at once. In
"stream" mode Mason outputs data as soon as it is computed. (This does not
take into account buffering done by Apache or the O/S.) The default mode
is "batch".

   Batch mode has the advantage of better error handling.  Suppose an
error occurs in the middle of a page. In stream mode, the error message
interrupts existing output, often appearing in an awkward HTML context
such as the middle of a table which never gets closed. In batch mode, the
error message is output neatly and alone.

   Batch mode also offers more flexibility in controlling HTTP headers
(see Devel/sending_http_headers) and in handling mid-request error
conditions (see Request/clear_buffer).

   Stream mode may help get data to the browser more quickly, allowing
server and browser to work in parallel. It also prevents memory buildup
for very large responses.

   Since Apache does its own buffering, stream mode does not entail
immediate delivery of output to the client. You must set $|=1 to turn off
Apache buffering completely (generally not a good idea) or call
`$m->flush_buffer' to flush the buffer selectively.

   In terms of making your server seem responsive, the initial bytes are
most important.  You can send these early by calling `$m->flush_buffer' in
key locations such as the common page header. However, this dilutes the
advantages of batch mode mentioned above. Tradeoffs...

   You control output mode by setting `interp->out_mode' to "batch" or
"stream".

Error mode
----------

   When an error occurs, Mason can respond by:

   * showing a detailed error message in the browser

   * die'ing, which sends a 501 to the browser and lets the error message
     go to the error logs.

   The first option is ideal for development, where you want immediate
feedback on the error.  The second option is usually desired for
production so that users are not exposed to messy error messages.  You
control this option by setting ah->error_mode to "html" or "fatal"
respectively.

Debug mode
----------

   As discussed in the debugging section, you can control when Mason
creates a debug file.  While creating a debug file is not incredibly
expensive, it does involves a bit of work and the creation of a new file,
so you probably want to avoid doing it on every request to a frequently
visited site.  I recommend setting debug_mode to 'all' in development, and
'error' or 'none' in production.

Reload files
------------

   Consider reload files only for frequently visited production sites.

CONFIGURING VIRTUAL SITES
=========================

   These examples extend the Mason/single site configuration example in
*HTML::Mason*.

Multiple sites, one component root
----------------------------------

   If you want to share some components between your sites, arrange your
httpd.conf so that all DocumentRoots live under a single component space:

     # httpd.conf
     PerlRequire /usr/local/mason/handler.pl

     # Web site #1
     <VirtualHost www.site1.com>
         DocumentRoot /usr/local/www/htdocs/site1
         <Location />
             SetHandler perl-script
             PerlHandler HTML::Mason
         </Location>
     </VirtualHost>

     # Web site #2
     <VirtualHost www.site2.com>
         DocumentRoot /usr/local/www/htdocs/site2
         <Location />
             SetHandler perl-script
             PerlHandler HTML::Mason
         </Location>
     </VirtualHost>

   In handler.pl:

     my $interp = new HTML::Mason::Interp (parser=>$parser,
                     comp_root=>'/usr/local/www/htdocs'
                     data_dir=>'/usr/local/mason/');

   The directory structure for this scenario might look like:

     /usr/local/www/htdocs/  # component root
         +- shared/          # shared components
         +- site1/           # DocumentRoot for first site
         +- site2/           # DocumentRoot for second site

   Incoming URLs for each site can only request components in their
respective DocumentRoots, while components internally can call other
components anywhere in the component space. The shared/ directory is a
private directory for use by components, inaccessible from the Web.

Multiple sites, multiple component roots
----------------------------------------

   Sometimes your sites need to have completely distinct component
hierarchies, e.g. if you are providing Mason ISP services for multiple
users. In this case the component root must change depending on the site
requested. Since you can't change an interpreter's component root
dynamically, you need to maintain separate Mason objects for each site in
the handler.pl:

     my (%interp,%ah);
     foreach my $site qw(...) {
         $interp{$site} = new HTML::Mason::Interp  (comp_root=>"/usr/local/www/$site",...);
         $ah{$site} = new HTML::Mason::ApacheHandler (interp=>$interp{$site},...);
     }

     ...

     sub handler {
         my $site = $r->dir_config('site');
         $ah{$site}->handle_request($r);
     }

   We assume each virtual server configuration section has a

     PerlSetVar site <site_name>

   Above we pre-create all Mason objects in the parent. Another scheme is
to create objects on demand in the child:

     my (%interp,%ah);

     ...

     sub handler {
         my $site = $r->dir_config('site');
         unless exists($interp{$site}) {
             # get comp_root from PerlSetVar as well
             my $comp_root = $r->dir_config('comp_root');
             $interp{$site} = new HTML::Mason::Interp(comp_root=>$comp_root,...);
             $ah{$site} = new HTML::Mason::ApacheHandler(interp=>$interp{$site},...);
         }
     }

   The advantage of the second scheme is that you don't have to hardcode
as much information in the handler.pl. The disadvantage is a slight memory
and performance impact. On development servers this shouldn't matter; on
production servers you may wish to profile the two schemes.

AUTHOR
======

   Jonathan Swartz, swartz@pobox.com

SEE ALSO
========

   HTML::Mason, HTML::Mason::Parser, HTML::Mason::Interp,
HTML::Mason::ApacheHandler

Mason/mod_perl interface
************************

NAME
====

   HTML::Mason::ApacheHandler - Mason/mod_perl interface

SYNOPSIS
========

     use HTML::Mason::ApacheHandler;

     my $ah = new HTML::Mason::ApacheHandler (..name/value params..);
     ...
     sub handler {
         my $r = shift;
         $ah->handle_request($r);
     }

DESCRIPTION
===========

   The ApacheHandler object links Mason to mod_perl, running components in
response to HTTP requests. It is controlled primarily through parameters
to the new() constructor.

   handle_request() is not a user method, but rather is called from the
HTML::Mason::handler() routine in handler.pl.

PARAMETERS TO THE use() DECLARATION
===================================

   The following are parameters to pass explicitly when using
HTML::Mason::ApacheHandler. e.g.

     use HTML::Mason::ApacheHandler (args_method=>'mod_perl');

args_method
     Method to use for unpacking GET and POST arguments. The valid options
     are 'CGI' and 'mod_perl'; these indicate that a CGI.pm or
     Apache::Request object (respectively) will be created for the purposes
     of argument handling. These objects are, unfortunately, not yet
     accessible from components.

     'CGI' is the default and should work on most Perl systems. However,
     if you have the Apache::Request package (or are inclined to fetch it
     from CPAN), you might switch to 'mod_perl' for speed and memory
     efficiency.

     When specifying args_method='CGI', the Mason request object ($m) will
     have a method called cgi_object available.  This method returns the
     CGI object used in the ApacheHandler code.

     When specifying args_method='mod_perl', the $r global is upgraded to
     an Apache::Request object. This object inherits all Apache methods
     and adds a few of its own, dealing with parameters and file uploads.
     See Apache::Request manual page for more information.

PARAMETERS TO THE new() CONTRUCTOR
==================================

apache_status_title
     Title that you want this ApacheHandler to appear as under
     Apache::Status.  Default is "HTML::Mason status".  This is useful if
     you create more then one ApacheHandler object and want them all
     visible via Apache::Status.

auto_send_headers
     True or undef; default true.  Indicates whether Mason should
     automatically send HTTP headers before sending content back to the
     client. If you set to false, you should call $r->send_http_header
     manually.

     See the Devel/sending_http_headers of the Component Developer's Guide
     for details about the automatic header feature.

debug_handler_proc, debug_handler_script, debug_mode, debug_perl_binary
     The *debug_** parameters control Mason's use of debug files.
     Component Admin/debugging procedures are fully described in the *Mason
     Administrator's Guide*.

decline_dirs
     Indicates whether Mason should decline directory requests, leaving
     Apache to serve up a directory index or a FORBIDDEN error as
     appropriate. Default is 1. See Admin/Allowing directory requests for
     more information about handling directories with Mason.

error_mode
     Specifies one of two ways to handle Perl errors, 'fatal' or 'html'.
     In fatal mode the handler simply dies with the error message. This
     may be caught with an eval around `$ah->handle_request' or left for
     Apache to handle (generally with a return status of 500).  In HTML
     mode the handler sends a readable HTML version of the error message
     to the client. HTML mode is most useful in combination with batch
     output mode for debugging.

output_mode
     This parameter has been replaced by the equivalent Interp parameter
     Interp/out_mode. For backward compatibility, setting
     `$ah->output_mode' will cause `$interp->out_mode' to be set
     appropriately.

top_level_predicate
     Reference to a subroutine that decides whether a component can answer
     top level requests. This allows for private-use components that live
     within the DocumentRoot but are inaccesible from URLs. By default,
     always returns 1.

     The subroutine receives one parameter, the absolute path to the
     component.  It then returns either a true (serve component) or false
     (reject component). In this example, the predicate rejects requests
     for components whose name starts with an "_" character:

          top_level_predicate => sub { $_[0] !~ m{/_[^/]+$}

ACCESSOR METHODS
================

   All of the above properties have standard accessor methods of the same
name: no arguments retrieves the value, and one argument sets it.  For
example:

     my $ah = new HTML::Mason::ApacheHandler;
     my $errmode = $ah->error_mode;
     $ah->error_mode('html');

AUTHOR
======

   Jonathan Swartz, swartz@pobox.com

SEE ALSO
========

   HTML::Mason, HTML::Mason::Parser, HTML::Mason::Interp,
HTML::Mason::Admin

Old Mason command reference
***************************

NAME
====

   HTML::Mason::Commands - Old Mason command reference

DESCRIPTION
===========

   This was the documentation for the `mc_' command set. In Mason 0.8 and
beyond, `mc_' commands have been replaced by the new
*HTML::Mason::Request* API. e.g.

     mc_comp becomes $m->comp
     mc_file becomes $m->file
     etc.

   Below is a description of how to convert your `mc_' commands to $m
methods. There is also a utility provided with the distribution,
`bin/convert0.8.pl', that performs these conversions for you.  For
backwards compatibility `mc_' commands still work for a limited time but
will eventually go away.

     `mc_abort' becomes `$m->abort'

     `mc_auto_comp' becomes `$m->fetch_next->path'

     `mc_auto_next' becomes `$m->call_next'

     `mc_cache' becomes `$m->cache'

     `mc_cache_self' becomes `$m->cache_self'

     `mc_caller' becomes `$m->callers(1)->path'

     `mc_call_self' becomes `$m->call_self'

     `mc_comp' becomes `$m->comp'

     `mc_comp_exists' becomes `$m->comp_exists'

     `mc_comp_source()' becomes `$m->current_comp->source_file'

     `mc_comp_source(path)' becomes `$m->fetch_comp(path)->source_file'.
     This no longer works with nonexistent components as it used to.

     `mc_comp_stack' becomes `map($_->title,$m->callers)'

     `mc_date' goes away, this was a legacy function. Replace by calling
     the date formatting function of your choice on `$m->time'.

     `mc_dhandler_arg' becomes `$m->dhandler_arg'

     `mc_file' becomes `$m->file'

     `mc_file_root' becomes `$m->file_root'

     `mc_out' becomes `$m->out'

     `mc_time' becomes `$m->time'

     `mc_suppress_http_header' (with or without argument) no longer has
     any effect and can simply be removed. See Devel/Sending HTTP Headers
     for more information.

AUTHOR
======

   Jonathan Swartz, swartz@pobox.com

SEE ALSO
========

   HTML::Mason, HTML::Mason::Devel

Mason Component Class
*********************

NAME
====

   HTML::Mason::Component - Mason Component Class

SYNOPSIS
========

     my $comp1 = $m->current_comp;
     my $comp2 = $m->callers(1);
     my $comp3 = $m->fetch_comp('foo/bar');

     foreach ($comp1,$comp2,$comp3) {
        print "My name is ".$_->title.".\n";
     }

DESCRIPTION
===========

   Mason uses the Component class to store components loaded into memory.
Components come from three distinct sources:

  1. File-based: loaded from a source or object file.

  2. Subcomponents: embedded components defined with the `<%def>' tag.

  3. Anonymous: created on-the-fly with the make_component Parser method.

        Some of the methods below return different values (or nothing at
all) depending on the component type.

   The component API is primarily useful for introspection, e.g. "what
component called me" or "does the next component take a certain argument".
You can build complex Mason sites without ever dealing directly with a
component object.

CREATING AND ACCESSING COMPONENTS
---------------------------------

   Common ways to get handles on existing component objects include the
`Request' in this node, `Request' in this node, and `Request' in this node
Request methods.

   There is no published new method, because creating a component requires
a parser. Use the `Parser' in this node Parser method to create a new
component dynamically.

   Similarly, there is no execute or call method, because calling a
component requires a request. All of the interfaces for calling a
component (<& &>, `$m-'comp>, `$interp->exec' which normally take a
component path, will also take a component object.

METHODS
=======

attr (name)
     Looks for the specified attribute in this component and its parents,
     returning the first value found. Dies with an error if not found.
     Attributes are declared in the `<%attr>' section.

attr_exists (name)
     Returns true if the specified attribute exists in this component or
     one of its parents, undef otherwise.

cache_file
     Returns the data cache filename for this component.

create_time
     Returns the time (in Perl time() format) when this component object
     was created.

declared_args
     Returns a reference to a hash of hashes representing the arguments
     declared in the `<%args>' section. The keys of the main hash are the
     variable names including prefix (e.g. `$foo', `@lst'). Each secondary
     hash contains:

        * 'default': the string specified for default value (e.g. 'fido')
          or undef if none specified.  Note that in general this is not
          the default value itself but rather an expression that gets
          evaluated every time the component runs.

     For example:

          # does $comp have an argument called $fido?
          if (exists($comp->declared_args->{'$fido'})) { ... }

          # does $fido have a default value?
          if (defined($comp->declared_args->{'$fido'}->{default})) { ... }

dir_path
     Returns the component's notion of a current directory, relative to the
     component root; this is used to resolve relative component paths. For
     file-based components this is the full component path minus the final
     piece.  For subcomponents this is the same as its parent component.
     Undefined for anonymous components.

first_time
     Returns true if this is the first time the component has executed,
     false otherwise.  Useful for initializing persistent component
     lexicals:

          if ($m->current_comp->first_time) {
             $dbh = DBI->connect(...);

     Note that in a web-based environment, this "first time" will come
     once for each child and every time the component is reloaded.

flag (name)
     Returns the value for the specified system flag.  Flags are declared
     in the `<%flags>' section and affect the behavior of the component.

is_subcomp
     Returns true if this is a subcomponent of another component.

is_file_based
     Returns true if this component was loaded from a source or object
     file.

call_method (name, args...)
     Looks for the specified user-defined method in this component and its
     parents, calling the first one found. Dies with an error if not found.
     Methods are declared in the `<%method>' section.

method_exists (name)
     Returns true if the specified user-defined method exists in this
     component or one of its parents, undef otherwise.

name
     Returns a short name of the component.  For file-based components this
     is the filename without the path. For subcomponents this is the name
     specified in `<%def>'. Undefined for anonymous components.

object_file
     Returns the object filename for this component.

owner
     Defined only for subcomponents; returns the component that this
     subcomponent was defined in.

parent
     Returns the parent of this component for inheritance purposes, by
     default the nearest `autohandler' in or above the component's
     directory.  Can be changed via the `inherit' flag.

path
     Returns the absolute path of this component.

run_count
     Returns the number of times this component has been invoked. In a
     web-based environment, this value is separate for each child and
     resets every time the component is reloaded.

scall_method (name, args...)
     Like `Component' in this node, but returns the method output as a
     string instead of printing it. (Think sprintf versus printf.) The
     method's return value is discarded.

subcomps
     With no arguments, returns a hashref containing the subcomponents
     defined in this component, with names as keys and component objects
     as values.  With one argument, returns the subcomponent of that name
     or undef if no such subcomponent exists. e.g.

          if (my $subcomp = $comp->subcomps('.link')) {
              ...
          }

     Subcomponents are declared in the `<%def>' section.

title
     Returns a printable string denoting this component.  It is intended to
     uniquely identify a component within a given interpreter although this
     is not 100% guaranteed. Mason uses this string in error messages, the
     previewer component trace, and `$m-'comp_stack>.

     For file-based components this is the component path.  For
     subcomponents this is "parent_component_path:subcomponent_name". For
     anonymous components this is a unique label like "[anon 17]".

FILE-BASED METHODS
==================

   The following methods apply only to file-based components (those loaded
from source or object files). They return undef for other component types.

source_file
     Returns the source filename for this component.

source_dir
     Returns the directory of the source filename for this component.

AUTHOR
======

   Jonathan Swartz, swartz@pobox.com

SEE ALSO
========

   See HTML/Mason/Request,

Former Developer's Guide
************************

NAME
====

   Components.pod - Former Developer's Guide

DESCRIPTION
===========

   The Component Developer's Guide is now in HTML::Mason::Devel.

   The HTML::Mason::Component class reference is in HTML::Mason::Component.

AUTHOR
======

   Jonathan Swartz, swartz@pobox.com

Mason Developer's Manual
************************

NAME
====

   Devel.pod - Mason Developer's Manual

DESCRIPTION
===========

   This manual is written for content developers who know HTML and at
least a little Perl. The goal is to write, run, and debug Mason components.

   If you are the webmaster (or otherwise responsible for the Mason
installation), you should also read *HTML::Mason::Admin*. There you will
find information about virtual site configuration, performance tuning,
component caching, and so on.

   We strongly suggest that you have a working Mason to play with as you
work through these examples. Other component examples can be found in the
`samples/' directory.

HOW TO USE THIS MANUAL
======================

   If you are just learning Mason and want to get started quickly, we
recommend the following sections:

   o `What Are Components?' in this node

   o `In-Line Perl Sections' in this node

   o `Calling Components' in this node

   o `Passing Parameters' in this node

   o `Initialization and Cleanup' in this node (mainly `<%init>')

   o `Data Caching' in this node

   o `Sending HTTP Headers' in this node

   o `Common Traps' in this node

WHAT ARE COMPONENTS?
====================

   The component - a mix of Perl and HTML - is Mason's basic building
block and computational unit. Under Mason, web pages are formed by
combining the output from multiple components.  An article page for a news
publication, for example, might call separate components for the company
masthead, ad banner, left table of contents, and article body. Consider
this layout sketch:

     +---------+------------------+
     |Masthead | Banner Ad        |
     +---------+------------------+
     |         |                  |
     |+-------+|Text of Article ..|
     ||       ||                  |
     ||Related||Text of Article ..|
     ||Stories||                  |
     ||       ||Text of Article ..|
     |+-------+|                  |
     |         +------------------+
     |         | Footer           |
     +---------+------------------+

   The top level component decides the overall page layout, perhaps with
HTML tables. Individual cells are then filled by the output of subordinate
components, one for the Masthead, one for the Footer, etc. In practice
pages are built up from as few as one, to as many as twenty or more
components.

   This component approach reaps many benefits in a web environment. The
first benefit is *consistency*: by embedding standard design elements in
components, you ensure a consistent look and make it possible to update
the entire site with just a few edits. The second benefit is
*concurrency*: in a multi-person environment, one person can edit the
masthead while another edits the table of contents.  A last benefit is
*reuseability*: a component produced for one site might be useful on
another. You can develop a library of generally useful components to
employ on your sites and to share with others.

   Most components emit chunks of HTML. "Top level" components, invoked
from a URL, represent an entire web page. Other, subordinate components
emit smaller bits of HTML destined for inclusion in top level components.

   Components receive form and query data from HTTP requests. When called
from another component, they can accept arbitrary parameter lists just
like a subroutine, and optionally return values.  This enables a type of
component that does not print any HTML, but simply serves as a function,
computing and returning a result.

   Mason actually compiles components down to Perl subroutines, so you can
debug and profile component-based web pages with standard Perl tools that
understand the subroutine concept, e.g. you can use the Perl debugger to
step through components, and Devel::DProf to profile their performance.

IN-LINE PERL SECTIONS
=====================

   Here is a simple component example:

     <%perl>
     my $noun = 'World';
     my @time = split /[\s:]/, localtime;
     </%perl>
     Hello <% $noun %>,
     % if ( $time[3] < 12 ) {
     good morning.
     % } else {
     good afternoon.
     % }

   After 12 pm, the output of this component is:

     Hello world, good afternoon.

   This short example demonstrates the three primary "in-line" Perl
sections. In-line sections are generally embedded within HTML and execute
in the order they appear. Other sections (`<%init>', `<%args>', etc.) are
tied to component events like initialization, cleanup, and argument
definition.

   The parsing rules for these Perl sections are as follows:

  1. Blocks of the form <% xxx %> are replaced with the result of
     evaluating xxx as a single Perl expression.  These are often used for
     variable replacement. such as 'Hello, <% $name %>!'.

  2. Lines beginning with a '%' character are treated as Perl.

  3. Multiline blocks of Perl code can be inserted with the `<%perl>' ..
     `</%perl>' tag. The enclosed text is executed as Perl and the return
     value, if any, is discarded.

     The `<%perl>' tag is case-insensitive. It may appear anywhere in the
     text, and may span any number of lines. `<%perl>' blocks cannot be
     nested inside one another.

Examples and Recommended Usage
------------------------------

   *% lines*

   Most useful for conditional and loop structures - if, while, foreach, ,
etc. - as well as side-effect commands like assignments. Examples:

   o Conditional code

     % my $ua = $r->header_in('User-Agent');
     % if ($ua =~ /msie/i) {
     Welcome, Internet Explorer users
     ...
     % } elsif ($ua =~ /mozilla/i) {
     Welcome, Netscape users
     ...
     % }

   o HTML list formed from array

     <ul>
     % foreach $item (@list) {
     <li><% $item %>
     % }
     </ul>

   o HTML list formed from hash

     <ul>
     % while (my ($key,$value) = each(%ENV)) {
     <li>
     <b><% $key %></b>: <% $value %>
     % }
     </ul>

   o HTML table formed from list of hashes

     <table>
     <tr>
     % foreach my $h (@loh) {
     <td><% $h->{foo} %></td>
     <td bgcolor=#ee0000><% $h->{bar} %></td>
     <td><% $h->{baz} %></td>
     % }
     </tr>
     </table>

   *&lt;% xxx %&gt;*

   Most useful for printing out variables, as well as more complex
expressions. Examples:

     Dear <% $name %>: We will come to your house at <% $address %> in the
     fair city of <% $city %> to deliver your $<% $amount %> dollar prize!

     The answer is <% ($y+8) % 2 %>.

     You are <% $age<18 ? 'not' : '' %> permitted to enter this site.

   *&lt;%perl&gt; xxx &lt;%/perl&gt;*

   Useful for Perl blocks of more than a few lines.

MASON OBJECTS
=============

   This section describes the various objects in the Mason universe.  If
you're just starting out, all you need to worry about initially are the
request objects.

Request Objects
---------------

   Two global per-request objects are available to all components: $r and
$m.

   $r, the mod_perl request object, provides a Perl API to the current
Apache request.  It is fully described in Apache.pod. Here is a sampling
of methods useful to component developers:

     $r->uri             # the HTTP request URI
     $r->header_in(..)   # get the named HTTP header line
     $r->content_type    # set or retrieve content-type
     $r->header_out(..)  # set or retrieve an outgoing header

     $r->content         # don't use this one! (see Tips and Traps)

   $m, the Mason request object, provides an analogous API for Mason. All
Mason features not activated by syntactic tags are accessed via $m
methods.  You'll be introduced to these methods throughout this document
as they are needed.  For a description of all methods see *See
HTML/Mason/Request,*.

   Note to pre-0.8 users: The $m API replaces both the old `mc_' command
set and the $REQ variable. See *See HTML/Mason/Commands,
* for a conversion guide.  There is also a utility
provided with the distribution, `bin/convert0.8.pl', that performs
appropriate conversions on your existing component tree.

System Objects
--------------

   Three system objects share the work of serving requests in Mason:
Parser, Interp, and ApacheHandler. The administrator creates these objects
and provides parameters that shape Mason's behavior. As a pure component
developer you shouldn't need to worry about or access these objects, but
occasionally we'll mention a relevant parameter.

Component Objects
-----------------

   Mason provides an object API for components, allowing you to query a
component's various asociated files, arguments, etc. For a description of
all methods see *See HTML/Mason/Component,*.
Typically you get a handle on a component object from request methods like
`$m->current_comp' and `$m->fetch_comp'.

   Note that for many basic applications all you'll want to do with
components is call them, for which no object method is needed. See next
section.

CALLING COMPONENTS
==================

   Mason pages often are built not from a single component, but from
multiple components that call each other in a hierarchical fashion.

Components that output HTML
---------------------------

   To call one component from another, use the <& &> tag:

     <& comp_path, [name=>value, ...] &>

comp_path:
     The component path. With a leading '/', the path is relative to the
     component root (comp_root). Otherwise, it is relative to the location
     of the calling component.

name=>value pairs:
     Parameters are passed as one or more name=>value pairs, e.g.
     `player=>'M. Jordan''.

   comp_path may be a literal string (quotes optional) or a Perl expression
that evaluates to a string. To eliminate the need for quotes in most
cases, Mason employs some magic parsing: If the first character is one of
`[A-Za-z0-9/_.]', comp_path is assumed to be a literal string running up
to the first comma or &>. Otherwise, comp_path is evaluated as an
expression.

   Here are some examples:

     # relative component paths
     <& topimage &>
     <& tools/searchbox &>

     # absolute component path
     <& /shared/masthead, color=>'salmon' &>

     # this component path MUST have quotes because it contains a comma
     <& "sugar,eggs", mix=>1 &>

     # variable component path
     <& $comp &>

     # variable component and arguments
     <& $comp, %args &>

     # you can use arbitrary expression for component path, but it cannot
     # begin with a letter or number; delimit with () to remedy this
     <& (int(rand(2)) ? 'thiscomp' : 'thatcomp'), id=>123 &>

   Several request methods also exist for calling components.  `$m->comp'
performs the equivalent action to <& &>:

     $m->comp('/shared/masthead', color=>'salmon');

   `$m->scomp' is like the sprintf version of `$m->comp': it returns the
component output, allowing the caller to examine and modify it before
printing:

     my $masthead = $m->scomp('/shared/masthead', color=>'salmon');
     $masthead =~ ...;
     $m->out($masthead);

Components that compute values
------------------------------

   So far you have seen components used solely to output HTML.  However,
components may also be used to compute a value. For example, you might
have a component `is_netscape' that analyzes the user agent to determine
whether it is a Netscape browser:

     <%perl>
     my $ua = $r->header_in('User-Agent');
     return ($ua =~ /Mozilla/i && $ua !~ /MSIE/i) ? 1 : 0;
     </%perl>

   Because components are implemented underneath with Perl subroutines,
they can return values and even understand scalar/list context.

   The <& &> notation only calls a component for its side-effect, and
discards its return value, if any.  To get at the return value of a
component, use the `$m->comp' command:

     % if ($m->comp('is_netscape')) {
     Welcome, Netscape user!
     % }

   Mason adds a `return undef' to the bottom of each component to provide
an empty default return value. To return your own value from a component,
you must use an explicit return statement. You cannot rely on the usual
Perl trick of letting return values "fall through".

   Generally components are divided into two types: those that output
HTML, and those that return a value. There is very little reason for a
component to do both. For example, it would not be very friendly for
`is_netscape' to output "hi Mom" while it was computing its value, thereby
surprising the if statement! Conversely, any value returned by an HTML
component would typically be discarded by the <& &> tag that invoked it.

TOP-LEVEL COMPONENTS
====================

   The first component invoked for a page (the "top-level component")
resides within the DocumentRoot and is chosen based on the URL. For
example:

     http://www.foo.com/mktg/products?id=372

   Apache resolves this URL to a filename, e.g.
/usr/local/www/htdocs/mktg/prods.html.  Mason loads and executes that file
as a component. In effect, Mason calls

     $m->comp('/mktg/products', id=>372)

   This component might in turn call other components and execute some Perl
code, or it might be nothing more than static HTML.

dhandlers
---------

   What happens when a user requests a component that doesn't exist? In
this case Mason scans backward through the URI, checking each directory
for a component named *dhandler* ("default handler").  If found, the
dhandler is invoked and is expected to use `$m->dhandler_arg' as the
parameter to some access function, perhaps a database lookup or location
in another filesystem. In a sense, dhandlers are similar in spirit to
Perl's AUTOLOAD feature; they are the "component of last resort" when a URL
points to a non-existent component.

   Consider the following URL, in which `newsfeeds/' exists but not the
subdirectory `LocalNews' nor the component `Story1':

     http://myserver/newsfeeds/LocalNews/Story1

   In this case Mason constructs the following search path:

     /newsfeeds/LocalNews/Story1         => no such thing
     /newsfeeds/LocalNews/dhandler       => no such thing
     /newsfeeds/dhandler                 => found! (search ends)
     /dhandler

   The found dhandler would read "LocalNews/Story1" from
`$m->dhandler_arg' and use it as a retrieval key into a database of
stories.

   Here's how a simple /newsfeeds/dhandler might look:

     <& header &>
     <b><% $headline %></b><p>
     <% $body %>
     <& footer &>

     <%init>
     my $arg = $m->dhandler_arg;                # get rest of path
     my ($section,$story) = split("/",$arg);    # split out pieces
     my $sth = $DBH->prepare
     	("SELECT headline,body FROM news WHERE section='$section' AND story='$story'");
     my ($headline,$body) = $sth->fetchrow_array;
     return 404 if !$headline;                  # return "not found" if no such story
     </%init>

   By default dhandlers do not get a chance to handle requests to a
directory itself (e.g. /newsfeeds). These are automatically deferred to
Apache, which generates an index page or a FORBIDDEN error.  Often this is
desirable, but if necessary the administrator can let in directory
requests as well; see `Admin' in this node.

   A component or dhandler that does not want to handle a particular
request may defer control to the next dhandler by calling `$m->decline'.

   The administrator can customize the file name used for dhandlers, or
turn off dhandlers entirely, with the `Interp' in this node Interp
parameter.

autohandlers
------------

   Autohandlers allow you to grab control and perform some action just
before Mason calls the top-level component.  This might mean adding a
standard header and footer, applying an output filter, or setting up
global variables.

   Autohandlers are directory based.  When Mason determines the top-level
component, it checks that directory and all parent directories for a
component called "autohandler". If found, the autohandler is called first.
After performing its actions, the autohandler typically calls
`$m->call_next' to transfer control to the original intended component.

   `$m->call_next' works just like `$m->comp' except that the component
path and arguments are implicit. You can pass additional arguments to
`$m->call_next'; these are merged with the original arguments, taking
precedence in case of conflict.  This allows you, for example, to override
arguments passed in the URL.

   Here is an autohandler that adds a common header and footer to each
page underneath its directory:

     <HTML>
     <HEAD><TITLE>McHuffy Incorporated</TITLE></HEAD>
     <BODY BGCOLOR="salmon">

     <% $m->call_next %>

     <HR>
     Copyright 1999 McHuffy Inc.
     </BODY>
     </HTML>

   Same idea, using components for the header/footer:

     <& /shared/header &>
     <% $m->call_next %>
     <& /shared/footer &>

   The next autohandler applies a filter to its pages, adding an absolute
hostname to relative image URLs:

     <% $m->call_next %>

     <%filter>
     s{(<img\s+src=\")/} {$1http://images.mysite.com/}ig;
     </%filter>

   Most of the time autohandler can simply call `$m->call_next' without
needing to know what the next component is. However, should you need it,
the component object is available from `$m->fetch_next'. This is useful
for calling the component manually, e.g. if you want to suppress some
original arguments or if you want to use `$m->scomp' to store and process
the output.

   What happens if more than one autohandler applies to a page? Prior to
version 0.85, only the most specific autohandler would execute.  In 0.85
and beyond each autohandler gets a chance to run.  The top-most
autohandler runs first; each `$m->call_next' transfers control to the next
autohandler and finally to the originally called component. This allows
you, for example, to combine general site-wide templates and more specific
section-based templates.

   Autohandlers can be made even more powerful in conjunction with Mason's
object-oriented style features: methods, attributes, and inheritance.  In
the interest of space these are discussed in a separate section, `Devel'
in this node.

   The administrator can customize the file name used for autohandlers, or
turn off autohandlers entirely, with the `Interp' in this node Interp
parameter.

dhandlers vs. autohandlers
--------------------------

   dhandlers and autohandlers both provide a way to exert control over a
large set of URLs. However, each specializes in a very different
application.  The key difference is that dhandlers are invoked only when
no appropriate component exists, while autohandlers are invoked only in
conjunction with a matching component.

   As a rule of thumb: use an autohandler when you have a set of
components to handle your pages and you want to augment them with a
template/filter. Use a dhandler when you want to create a set of "virtual
URLs" that don't correspond to any actual components, or to provide
default behavior for a directory.

   dhandlers and autohandlers can even be used in the same directory. For
example, you might have a mix of real URLs and virtual URLs to which you
would like to apply a common template/filter.

PASSING PARAMETERS
==================

   This section describes Mason's facilities for passing parameters to
components (either from HTTP requests or component calls) and for
accessing parameter values inside components.

In Component Calls
------------------

   Any Perl data type can be passed in a component call:

     <& /sales/header, s=>'dog', l=>[2,3,4], h=>{a=>7,b=>8} &>

   This command passes a scalar ($s), a list (@l), and a hash (%h). The
list and hash must be passed as references, but they will be automatically
dereferenced in the called component.

In HTTP requests
----------------

   Consider a CGI-style URL with a query string:

     http://www.foo.com/mktg/prods.html?str=dog&lst=2&lst=3&lst=4

   or an HTTP request with some POST content. Mason automatically parses
the GET/POST values and makes them available to the component as
parameters.

Accessing Parameters
--------------------

   Component parameters, whether they come from GET/POST or another
component, can be accessed in two ways.

   1.  Declared named arguments: Components can define an `<%args>'
section listing argument names, types, and default values. For example:

     <%args>
     $a
     @b       # a comment
     %c

     # another comment
     $d=>5
     $e=>$d*2
     @f=>('foo','baz')
     %g=>(joe=>1,bob=>2)
     </%args>

   Here, *$a*, *@b*, and %c are required arguments; the component generates
an error if the caller leaves them unspecified. $d, $e, *@f* and *%g* are
optional arguments; they are assigned the specified default values if
unspecified.  All the arguments are available as lexically scoped ("my")
variables in the rest of the component.

   Arguments are separated by one or more newlines. Comments may be used at
the end of a line or on their own line.

   Default expressions are evaluated in top-to-bottom order, and one
expression may reference an earlier one (as $e references $d above).

   Only valid Perl variable names may be used in `<%args>' sections.
Parameters with non-valid variable names cannot be pre-declared and must
be fetched manually out of the %ARGS hash (see below).  One common example
of undeclarable parameters are the "button.x/button.y" parameters sent for
a form submit.

   2. %ARGS hash: This variable, always available, contains all of the
parameters passed to the component (whether or not they were declared).
It is especially handy for dealing with large numbers of parameters,
dynamically named parameters, or parameters with non-valid variable names.
%ARGS can be used with or without an `<%args>' section, and its contents
are unrelated to what you have declared in `<%args>'.

   Here's how to pass all of a component's parameters to another component:

     <& template, %ARGS &>

Parameter Passing Examples
--------------------------

   The following examples illustrate the different ways to pass and
receive parameters.

   1.  Passing a scalar id with value 5.

     In a URL: /my/URL?id=5
     In a component call: <& /my/comp, id => 5 &>
     In the called component, if there is a declared argument named...
       $id, then $id will equal 5
       @id, then @id will equal (5)
       %id, then an error occurs
     In addition, $ARGS{id} will equal 5.

   2.  Passing a list colors with values red, blue, and green.

     In a URL: /my/URL?colors=red&colors=blue&colors=green
     In an component call: <& /my/comp, colors => ['red', 'blue', 'green'] &>
     In the called component, if there is a declared argument named...
       $colors, then $colors will equal ['red', 'blue', 'green']
       @colors, then @colors will equal ('red', 'blue', 'green')
       %colors, then an error occurs
     In addition, $ARGS{colors} will equal ['red', 'blue', 'green'].

   3.  Passing a hash *grades* with pairs Alice => 92 and Bob => 87.

     In a URL: /my/URL?grades=Alice&grades=92&grades=Bob&grades=87
     In an component call: <& /my/comp, grades => {Alice => 92, Bob => 87} &>
     In the called component, if there is a declared argument named...
       $grades, then $grades will equal {Alice => 92, Bob => 87}
       @grades, then @grades will equal ('Alice', 92, 'Bob', 87)
       %grades, then %grades will equal (Alice => 92, Bob => 87)
     In addition, $ARGS{grades} will equal ['Alice',92,'Bob',87] in the
       URL case, or {Alice => 92, Bob => 87} in the component call case.
       (The discrepancy exists because, in a query string, there is no detectable
       difference between a list or hash.)

Using @_ instead
----------------

   If you don't like named parameters, you can pass a traditional list of
ordered parameters:

     <& /mktg/prods.html', 'dog', [2,3,4], {a=>7,b=>8} &>

   and access them as usual through Perl's @_ array:

     my ($scalar, $listref, $hashref) = @_;

   In this case no `<%args>' section is necessary.

   We generally recommend named parameters for the benefits of
readability, syntax checking, and default value automation.  However using
@_ may be convenient for very small components, especially subcomponents
created with `<%def>'.

INITIALIZATION AND CLEANUP
==========================

   The following sections contain blocks of Perl to execute at specific
times.

<%init>
-------

   This section contains initialization code that executes as soon as the
component is called. For example: checking that a user is logged in;
selecting rows from a database into a list; parsing the contents of a file
into a data structure.

   Technically a <%init> block is equivalent to a <%perl> block at the
beginning of the component. However, there is an aesthetic advantage of
placing this block at the end of the component rather than the beginning.

   We've found that the most readable components (especially for
non-programmers) contain HTML in one continuous block at the top, with
simple substitutions for dynamic elements but no distracting blocks of
Perl code.  At the bottom an <%init> block sets up the substitution
variables.  This organization allows non-programmers to work with the HTML
without getting distracted or discouraged by Perl code. For example:

     <html>
     <head><title><% $headline %></title></head>
     <body>
     <h2><% $headline %></h2>
     By <% $author %>, <% $date %><p>

     <% $body %>

     </body></html>

     <%init>
     # Fetch article from database
     my $dbh = DBI::connect ...;
     my $sth = $dbh->prepare("select * from articles where id = $article_id");
     my ($headline,$date,$author,$body) = $sth->fetchrow_array;
     # Massage the fields
     $headline = uc($headline);
     my ($year,$month,$day) = split('-',$date);
     $date = "$month/$day";
     </%init>

     <%args>
     $article_id
     </%args>

<%cleanup>
----------

   This section contains cleanup code that executes just before the
component exits. For example: closing a database connection or closing a
file handle.

   Technically a <%cleanup> block is equivalent to a <%perl> block at the
end of the component. Since a component corresponds a subroutine block,
and since Perl is so darned good at cleaning up stuff at the end of blocks,
<%cleanup> sections are rarely needed.

<%once>
-------

   This code executes once when the component is loaded. Variables
declared in this section can be seen in all of a component's code and
persist for the lifetime of the component.

   Useful for declaring persistent component-scoped lexical variables
(especially objects that are expensive to create), declaring subroutines
(both named and anonymous), and initializing state.

   This code does not run inside a request context. You cannot call
components or access $m from this section.

   Normally this code will execute individually from every HTTP child that
uses the component. However, if the component is preloaded, this code will
only execute once in the parent.  Unless you have total control over what
components will be preloaded, it is safest to avoid initializing variables
that can't survive a fork(), e.g. DBI handles.  Use the following trick to
initialize such variables in the <%init> section:

     <%once>
     my $dbh;    # declare but don't assign
     ...
     </%once>

     <%init>
     if ($m->current_comp->first_time) {
         $dbh = DBI::connect ...
     }
     ...
     </%init>

<%shared>
---------

   As with `<%once>', variables declared in this section can be seen in all
of a component's code: the main component, subcomponents, and methods.
However, the code runs once per request (whenever the component is used)
and its variables last only til the end of the request.

   Useful for initializing variables needed in, say, the main body and one
more subcomponents or methods. See `Devel' in this node for an example of
usage.

   Avoid using `<%shared>' for side-effect code that needs to run at a
predictable time during page generation. You may assume only that
`<%shared>' runs just before the first code that needs it and runs at most
once per request. `<%init>' offers more a predictable execution time.

   Any component with a `<%shared>' section incurs an extra performance
penalty, because (as currently implemented) Mason must recreate its
anonymous subroutines the first time each new request uses the component.
The exact penalty varies between systems and for most applications will be
unnoticeable. However, one should avoid using `<%shared>' when patently
unnecessary, e.g. when an `<%init>' would work as well.

EMBEDDED COMPONENTS
===================

<%def name>
-----------

   Each instance of this section creates a *subcomponent* embedded inside
the current component. Inside you may place anything that a regular
component contains, with the exception of `<%def>', `<%method>',
`<%once>', and `<%shared>' tags.

   The name consists of characters in the set `[A-Za-z0-9._-]'. To call a
subcomponent simply use its name in <& &> or `$m->comp'. A subcomponent
can only be seen from the surrounding component.

   If you define a subcomponent with the same name as a file-based
component in the current directory, the subcomponent takes precedence. You
would need to use an absolute path to call the file-based component. To
avoid this situation and for general clarity, we recommend that you pick a
unique way to name all of your subcomponents that is unlikely to interfere
with file-based components. The author prefers to start subcomponent names
with ".".

   While inside a subcomponent, you may use absolute or relative paths to
call file-based components and also call any of your "sibling"
subcomponents.

   The lexical scope of a subcomponent is separate from the main
component.  However a subcomponent can declare its own `<%args>' section
and have relevant values passed in.  You can also use a `<%shared>'
section to declare variables visible from both scopes.

   In the following example, we create a ".link" subcomponent to produce a
standardized hyperlink:

     <%def .link>
     <font size="4" face="Verdana,Arial,Helvetica">
     <a href="http://www.<% $site %>.com"><% $label %></a>
     </font><br>
     <%args>
     $site
     $label=>ucfirst($site)
     </%args>
     </%def>

     Visit these sites:
     <ul>
     <li><& .link, site=>'yahoo' &><br>
     <li><& .link, site=>'cmp', label=>'CMP Media' &><br>
     <li><& .link, site=>'excite' &>
     </ul>

<%method name>
--------------

   Each instance of this section creates a method embedded inside the
current component. Methods resemble subcomponents in terms of naming,
contents, and scope. However, while subcomponents can only be seen from
the parent component, methods are meant to be called from other components.

   There are two ways to call a method. First, via a path of the form
"comp:method":

     <& /foo/bar:method1 &>

     $m->comp('/foo/bar:method1');

   Second, via the call_method component method:

     my $comp = $m->fetch_comp('/foo/bar');
     ...
     $comp->call_method('method1');

   Methods are commonly used in conjunction with autohandlers to make
templates more flexible. See `Devel' in this node for more information.

FLAGS AND ATTRIBUTES
====================

   The <%flags> and <%attr> sections consist of key/value pairs, one per
line, joined by '=>'.  The key and value in each pair must be valid Perl
hash keys and values respectively. An optional comment may follow each
line.

<%flags>
--------

   Use this section to set official Mason flags that affect the current
component's behavior.

   Currently there is only one flag, <tt>inherit</tt>, which specifies the
component's <i>parent</i> in the form of a relative or absolute component
path. A component inherits methods and attributes from its parent; see
`Devel' in this node for examples.

     <%flags>
     inherit=>'/site_handler'
     </%flags>

<%attr>
-------

   Use this section to assign static key/value attributes that can be
queried from other components.

     <%attr>
     color=>'blue'
     fonts=>[qw(arial geneva helvetica)]
     </%attr>

   To query an attribute of a component, use the attr method:

     my $color = $comp->attr('color')

   where $comp is a component object.

   Mason evaluates attribute values once when loading the component.  This
makes them faster but less flexible than methods.

FILTERING
=========

   This section describes several ways to apply filtering functions over
the results of the current component.  By separating out and hiding a
filter that, say, changes HTML in a complex way, we allow non-programmers
to work in a cleaner HTML environment.

&lt;%filter&gt; section
-----------------------

   The `<%filter>' section allows you to arbitrarily filter the output of
the current component. Upon entry to this code, $_ contains the component
output, and you are expected to modify it in place. The code has access to
component arguments and can invoke subroutines, call other components, etc.

   This simple filter converts the component output to UPPERCASE:

     <%filter>
     tr/a-z/A-Z/
     </%filter>

   The following navigation bar uses a filter to "unlink" and highlight
the item corresponding to the current page:

     <a href="/">Home</a> | <a href="/products/">Products</a> |
     <a href="/bg.html">Background</a> | <a href="/finance/">Financials</a> |
     <a href="/support/">Tech Support</a> | <a href="/contact.html">Contact Us</a>

     <%filter>
     my $uri = $r->uri;
     s{<a href="$uri/?">(.*?)</a>} {<b>$1</b>}i;
     </%filter>

   This allows a designer to code such a navigation bar intuitively
without if statements surrounding each link!  Note that the regular
expression need not be very robust as long as you have control over what
will appear in the body.

$m->call_self command
---------------------

   This command allows you to filter both the output and the return value
of the current component. It is fairly advanced; for most purposes the
`<%filter>' tag above will be sufficient and simpler.

   `$m->call_self' takes two arguments.  The first is a scalar reference
and will be populated with the component output.  The second is either a
scalar or list reference and will be populated with the component return
value; the type of reference determines whether the component will be
called in scalar or list context. Both of these arguments are optional;
you may pass undef if you don't care about one of them.

   `$m->call_self' acts like a fork() in the sense that it will return
twice with different values.  When it returns 0, you allow control to pass
through to the rest of your component.  When it returns 1, that means the
component has finished and you can begin filtering the output and/or
return value. (Don't worry, it doesn't really do a fork! See next section
for explanation.)

   The following examples would generally appear at the top of a `<%init>'
section.  Here is a no-op `$m->call_self' that leaves the output and
return value untouched:

     if ($m->call_self(my \$output, my \$retval)) {  # assumes Perl 5.005 or greater
         $m->out($output);
         return $retval;
     }

   Here is a simple output filter that makes the output all uppercase,
just like the `<%filter>' example above. Note that we ignore both the
original and the final return value.

     if ($m->call_self(my \$output, undef)) {
         $m->out(uc($output));
         return;
     }

   `$m->call_self' can even convert output to a return value or vice versa.
In the next component we provide a nice friendly format for
non-programmers to represent data with, and use a filter to construct and
return a corresponding Perl data structure from it:

     # id        lastname        firstname
     59286       Sherman         Karen
     31776       Dawson          Robert
     29482       Lee             Brenda
     ...

     <%init>
     if ($m->call_self(my \$output, undef)) {
         foreach (split("\n",$output)) {
             next if /^#/ || !/\S/;
             my @vals = split(/\s+/);
             push(@people,{id=>$vals[0],last=>$vals[1],first=>$vals[2]});
         }
         return @people;
     }
     </%init>

   Now we can get a list of hashes directly from this component.

How filtering works
-------------------

   `$m->call_self' (and `<%filter>', which is built on it) uses a bit of
magic to accomplish everything in one line.  If you're curious, here's how
it works:

   o A component foo calls `$m->call_self' for the first time.

   o `$m->call_self' sets an internal flag and calls foo again recursively,
changing the output stream to capture content into a buffer.

   o foo again calls `$m->call_self' which, seeing the flag, returns 0
immediately.

   o foo goes about its business and generates content into the
`$m->call_self' buffer.

   o When control is returned to `$m->call_self', it places the content
and return value in the references provided, and returns 1.

OTHER SYNTAX
============

<%doc>
------

   Text in this section is treated as a comment and ignored. Most useful
for a component's main documentation.  One can easily write a program to
sift through a set of components and pull out their <%doc> blocks to form
a reference page.

   Can also be used for in-line comments, though it is an admittedly
cumbersome comment marker.  Another option is '%#':

     %# this is a comment

   These comments differ from HTML comments in that they do not appear in
the HTML.

<%text>
-------

   Text in this section is passed through unmodified by Mason. Any Mason
syntax inside it is ignored.  Useful, for example, when documenting Mason
itself from a component:

     <%text>
     % This is an example of a Perl line.
     <% This is an example of an expression block. %>
     </%text>

   This works for almost everything, but doesn't let you output </%text>
itself! When all else fails, use `$m->out':

     %$m->out('The tags are <%text> and </%text>.');

Escaping expressions
--------------------

   Mason has facilities for *escaping* the output from <% %> tags, on
either a site-wide or a per-expression basis.

   Any <% %> expression may be terminated by a '|' and one or more
single-letter escape flags (plus arbitrary whitespace):

     <% $file_data |h %>

   The current valid flags are

     h - escape for HTML ('<' => '&lt;', etc.)
     u - escape for URL query parameter (':' => '%3A', etc.) - all chars but [a-zA-Z0-9_.-]
     n - turn off default escape flags

   The administrator may specify a set of default escape flags via the
`Parser' in this node Parser parameter. For example, if the administrator
specifies

     default_escape_flags=>'h'

   then all <% %> expressions will automatically be HTML-escaped.  In this
case you would use the n flag to turn off HTML-escaping for a specific
expression:

     <% $html_block |n %>

   Future Mason versions will allow user-defined and multi-letter escape
flags.

\ at end of line
----------------

   A \ suppresses the newline before %-lines and section tags. In HTML
components, this is mostly useful for fixed width areas like <PRE> tags,
since browsers ignore white space for the most part. An example:

     <PRE>
     foo
     %if ($b == 2) {
     bar
     %}
     baz
     </PRE>

   outputs

     foo
     bar
     baz

   because of the newlines on lines 2 and 4. (Lines 3 and 5 do not
generate a newline because the entire line is taken by Perl.)  To suppress
the newlines:

     <PRE>
     foo\
     %if ($b == 2) {
     bar\
     %}
     baz
     </PRE>

   which prints

     foobarbaz

   The backslash has no special meaning outside this context. In
particular, you cannot use it to escape a newline before a plain text line.

DATA CACHING
============

   Mason's `$m->cache' and `$m->cache_self' methods let components save
and retrieve the results of computation for improved performance.
Anything may be cached, from a block of HTML to a complex data structure.

   Each component gets a private data cache. Except under special
circumstances, one component does not access another component's cache.
Each cached value may be set to expire under certain conditions or at a
certain time.

   To use data caching, your Mason installation must be configured with a
good DBM package like Berkeley DB (DB_File) or GDBM. See *See
HTML/Mason/Admin,* for more information.

Basic Usage
-----------

   Here's the typical usage of `$m->cache':

     my $result = $m->cache(action=>'retrieve');
     if (!defined($result)) {
         ... compute $result> ...
         $m->cache(action=>'store', value=>$result);
     }

   The first `$m->cache' call attempts to retrieve this component's cache
value. If the value is available it is placed in $result. If the value is
not available, $result is computed and stored in the cache by the second
`$m->cache' call.

   The default action for `$m->cache' is 'retrieve', so the first line can
be written as

     my $result = $m->cache;

Multiple Keys/Values
--------------------

   A cache file can store multiple keys and values. A value can be a
scalar, list reference, or hash reference:

     $m->cache(action=>'store',key=>'name',value=>$name);
     $m->cache(action=>'store',key=>'friends',value=>\@lst);
     $m->cache(action=>'store',key=>'map',value=>\%hsh);

   The key defaults to 'main' when unspecified, as in the first example
above.

   Mason uses the *MLDBM* package to store and retrieve from its cache
files, meaning that Mason can cache arbitrarily deep data structures
composed of lists, hashes, and simple scalars.

Expiration
----------

   Typical cache items have a useful lifetime after which they must
expire. Mason supports three types of expiration:

By Time
     (e.g. the item expires in an hour, or at midnight). To expire an item
     by time, pass one of these options to the 'store' action.

     *expire_at*: takes an absolute expiration time, in Perl time() format
     (number of seconds since the epoch)

     *expire_in*: takes a relative expiration time of the form
     "<num><unit>", where <num> is a positive number and <unit> is one of
     seconds, minutes, hours, days, weeks, months, years, or any reasonable
     abbreviation thereof (m=month, min=minute).  E.g. "10min", "1hour".

     *expire_next*: takes a string, either 'hour' or 'day'. It indicates
     an expiration time at the top of the next hour or day.

     Examples:

          $m->cache(action=>'store', expire_in=>'2 hours');
          $m->cache(action=>'store', expire_next=>'hour');

By Condition
     (e.g. the item expires if a certain file or database table changes).
     To expire an item based on events rather than current time, pass the
     'expire_if' option to the 'retrieve' action.

     *expire_if*: calls a given anonymous subroutine and expires if the
     subroutine returns a non-zero value. The subroutine is called with one
     parameter, the time when the cache value was last written.

     Example:

          # expire the cache if 'myfile' is newer
          $m->cache(action => 'retrieve',
                expire_if => sub { (stat 'myfile')[9] > shift });

By Explicit Action
     (e.g. a shell command or web interface is responsible for explicitly
     expiring the item) To expire an item from a Perl script, for any
     component, use *access_data_cache*. It takes the same arguments as
     `$m->cache' plus one additional argument, cache_file.  See the
     administration manual for details on where cache files are stored and
     how they are named.

          use HTML::Mason::Utils 'access_data_cache';
          access_data_cache (cache_file=>'/usr/local/mason/cache/foo+2fbar',
                             action=>'expire' [, key=>'fookey']);

     The 'expire' action can also take multiple keys (as a list reference);
     this can be used in conjunction with the 'keys' action to expire all
     keys matching a particular pattern.

          use HTML::Mason::Utils 'access_data_cache';
          my @keys = access_data_cache (cache_file=>'/usr/local/mason/cache/foo+2fbar',
                                        action=>'keys');
          access_data_cache (cache_file=>'/usr/local/mason/cache/foo+2fbar',
                             action=>'expire', key=>[grep(/^sales/,@keys)]);

Busy Locks
----------

   The code shown in "Basic Usage" above,

     my $result = $m->cache(action=>'retrieve');
     if (!defined($result)) {
         ... compute $result ...
         $m->cache(action=>'store', value=>$result);
     }

   can suffer from a kind of race condition for caches that are accessed
frequently and take a long time to recompute.

   Suppose that a particular cache value is accessed five times a second
and takes three seconds to recompute.  When the cache expires, the first
process comes in, sees that it is expired, and starts to recompute the
value.  The second process comes in and does the same thing.  This
sequence continues until the first process finishes and stores the new
value.  On average, the value will be recomputed and written to the cache
15 times!

   The solution here is to have the first process notify the others that
it has started recomputing.  This can be accomplished with the busy_lock
flag:

     my $result = $m->cache(action=>'retrieve',busy_lock=>'10sec',...);

   With this flag, the first process sets a lock in the cache that
effectively says "I'm busy recomputing his value, don't bother."
Subsequent processes see the lock and return the old value.  The lock is
good for 10 seconds (in this case) and is ignored after that.  Thus the
time value you pass to busy_lock indicates how long you're willing to
allow this component to use an expired cache value.

   Would some of your caches benefit from busy locks?  One way to find out
is to turn on cache logging in the Mason system logs.  If you see large
clusters of writes to the same cache in a short time span, then you might
want to use busy locks when writing to that cache.

Keeping In Memory
-----------------

   The keep_in_memory flag indicates that the cache value should be kept
in memory after it is stored or retrieved.  Since every child process will
store its own copy, this flag should be used only for small, frequently
retrieved cache values. If used, this flag should be passed to both the
store and retrieve commands.

Caching All Output
------------------

   Occasionally you will need to cache the complete output of a component.
One way to accomplish this is to replace the component with a placeholder
that simply calls the component, then caches and prints the result. For
example, if the component were named "foo", we might rename it to
"foo_main" and put this component in its place:

     <% $foo_out %>
     <%init>
         my $foo_out;
         if (!defined ($foo_out = $m->cache)) {
             $m->comp('foo_main', STORE=>\$foo_out);
             $m->cache(action=>'store',
                   expire_in=>'3 hours', value=>$foo_out);
         }
     </%init>

   This works, but is cumbersome. Mason offers a better shortcut: the
`$m->cache_self' command that lets a component cache it's own output and
eliminates the need for a dummy component. It is typically used right at
the top of a `<%init%>' section:

     <%init>
         return if $m->cache_self(expire_in=>'3 hours'[, key=>'fookey']);
         ... <rest of init> ...
     </%init>

   `$m->cache_self' is built on top of `$m->cache', so it inherits all the
expiration options described earlier. `$m->cache_self' can also cache a
component's return value; see the reference for details.

Guarantees (or lack thereof)
----------------------------

   Mason will make a best effort to cache data until it expires, but will
not guarantee it.  The data cache is not a permanent reliable store in
itself; you should not place in the cache critical data (e.g. user session
information) that cannot be regenerated from another source such as a
database.  You should write your code as if the cache might disappear at
any time. In particular,

   o If the 'store' action cannot get a write lock on the cache, it simply
fails quietly.

   o If the 'retrieve' action cannot get a shared lock on the cache, it
simply fails quietly. (This is much more rare.)

   o Your Mason administrator will be required to remove cache files
periodically when they get too large; this can happen any time.

   On the other hand, expiration in its various forms is guaranteed,
because Mason does not want you to rely on bad data to generate your
content. If you use the 'expire' action and Mason cannot get a write lock,
it will repeat the attempt several times and finally die with an error.

SENDING HTTP HEADERS
====================

   Mason automatically sends HTTP headers via $r->send_http_header. It
tries to delay sending headers till the last possible moment, to give
components a chance to affect headers (using $r->header_out,
$r->content_type, etc.) It won't send headers if they've already been sent
manually.

   To determine the exact header behavior on your system, you need to know
whether your server's out_mode is 'batch' (meaning all output is buffered
until the end) or 'stream' (all output is sent immediately). Your
administrator should have this information. If your administrator doesn't
know then it is probably 'batch', the default.

   In batch mode the header situation is extremely simple: Mason waits
until the very end of the request to send headers. Any component can
modify or augment the headers.

   In stream mode the header situation is more complex.  Mason will send
headers just before sending the first non-whitespace output.  Any initial
whitespace output is buffered up until after headers are sent. This means
that if you want to affect the headers in stream mode, you must do so
before any component sends non-whitespace output. Generally this takes
place in an `<%init>' section.

   For example, the following top-level component calls another component
to see whether the user has a cookie; if not, it inserts a new cookie into
the header.

     <%init>
     my $cookie = $m->comp('/shared/get_user_cookie');
     if (!$cookie) {
     	$cookie = new CGI::Cookie (...);
     	$r->headers_out->add('Set-cookie' => $cookie);
     }
     ...
     </%init>

   In batch mode this code will always work.  In stream mode this code
will work as long as *get_user_cookie* doesn't output anything besides
whitespace (and given its functional nature, it shouldn't).

   The administrator can turn off automatic header sending via the
`ApacheHandler' in this node ApacheHandler parameter.

   Note to pre-0.8 users: the mc_suppress_http_header command is no longer
needed.  For backwards compatibility, mc_suppress_http_header is still
defined but does nothing.

   (Rationale: By the nature of HTTP headers mc_suppress_http_header was
only useful up until the first bytes of content were sent. Since Mason now
waits that long to send headers anyway, there is never any justification
for suppressing headers.)

USING THE PERL DEBUGGER
=======================

   The Perl debugger is an indispensable tool for identifying and fixing
bugs in Perl programs.  Unfortunately, in a mod_perl environment one is
normally unable to use the debugger since programs are run from a browser.
Mason removes this limitation by optionally creating a *debug file* for
each page request, allowing the request to be replayed from the command
line or Perl debugger.

   Note: in early 1999 a new module, Apache::DB, was released that makes
it substantially easier to use the Perl debugger directly in conjunction
with a real Apache server.  Since this mechanism is still new, we continue
to support Mason debug files, and there may be reasons to prefer Mason's
method (e.g. no need to start another Apache server).  However we
acknowledge that Apache::DB may eventually eliminate the need for debug
files. For now we encourage you to try both methods and see which one
works best.

Using debug files
-----------------

   Here is a typical sequence for debugging a Mason page:

  1. Find the debug file: When Mason is running in debug mode, requests
     generate "debug files", cycling through filenames "1" through "20".
     To find a request's debug file, simply do a "View Source" in your
     browser after the request and look for a comment like this at the
     very top:

          <!--
          Debug file is '3'.
          Full debug path is '/usr/local/mason/debug/anon/3'.
          -->

  2. Run the debug file: Debug files basically contain two things: a copy
     of the entire HTTP request (serialized with Data::Dumper), and all
     the plumbing needed to route that request through Mason. In other
     words, if you simply run the debug file like this:

          perl /usr/local/mason/debug/anon/3

     you should see the HTTP headers and content that the component would
     normally send to the browser.

  3. Debug the debug file: Now you merely add a -d option to run the debug
     file in Perl's debugger - at which point you have to deal the problem
     of anonymous subroutines.

     Mason compiles components down to anonymous subroutines which are not
     easily breakpoint'able (Perl prefers line numbers or named
     subroutines). Therefore, immediately before each component call,
     Mason calls a nonce subroutine called `debug_hook' just so you can
     breakpoint it like this:

          b HTML::Mason::Request::debug_hook

     debug_hook is called with the component name as the second parameter
     so that you can also breakpoint specific components using a
     conditional on $_[1]:

          b HTML::Mason::Request::debug_hook $_[1] =~ /component name/

     You can avoid all that typing by adding the following to your
     ~/.perldb file:

          # Perl debugger aliases for Mason
          $DB::alias{mb} = 's/^mb\b/b HTML::Mason::Request::debug_hook/';

     which reduces the previous examples to just:

          mb
          mb $_[1] =~ /component name/

        The use of debug files opens lots of other debugging options. For
instance, you can read a debug file into the Emacs editor, with its nifty
interface to Perl's debugger.  This allows you to set break points
visually or (in trace mode) watch a cursor bounce through your code in
single-step or continue mode.

Specifying when to create debug files
-------------------------------------

   Details about configuring debug mode can be found in *See
HTML/Mason/Admin,*. In particular, the administrator
must decide which of three debugging modes to activate:

   never (no debug files)

   always (create debug files for each request)

   error (only generate a debug file when an error occurs)

How debug files work
--------------------

   To create a debug file, Mason calls almost every one of the mod_perl
API methods (`$r->xxx'), trapping its result in a hash.  That hash is then
serialized by Data::Dumper and output into a new debug file along with
some surrounding code.

   When the debug file is executed, a new object is created of the class
"HTML::Mason::FakeApache", passing the saved hash as initialization. The
FakeApache object acts as a fake $r, responding to each method by getting
or setting data in its hash. For most purposes it is indistinguishable
from the original $r except that print methods go to standard output. The
debug file then executes your `handler()' function with the simulated $r.

When debug files don't work
---------------------------

   The vast majority of mod_perl API methods are simple get/set functions
(e.g. `$r->uri', `$r->content_type') which are easy to simulate.  Many
pages only make use of these methods and can be successfully simulated in
debug mode.

   However, a few methods perform tasks requiring the presence of a true
Apache server. These cannot be properly simulated.  Some, such as
log_error and `send_cgi_header', are generally tangential to the debugging
effort; for these Mason simply returns without doing anything and hopes
for the best.  Others, such as `internal_redirect' and `lookup_uri',
perform such integral functions that they cannot be ignored, and for these
FakeApache aborts with an error. This category includes any method call
expected to return an Apache::Table object.

   In addition, FakeApache is playing something of a catch-up game: every
time a new mod_perl release comes out with new API methods, those methods
will not be recognized by FakeApache until it is updated in the next Mason
release.

   The combination of these problems and the existence of the new
Apache::DB package may eventually lead us to stop further work on
FakeApache/debug files.  For now, though, we'll continue to support them
as best we can.

USING THE PERL PROFILER
=======================

   Debug files, mentioned in the previous section, can be used in
conjunction with Devel::DProf to profile a web request.

   To use profiling, pass the -p flag to the debug file:

     % ./3 -p

   This executes the debug file under Devel::DProf and, for convenience,
runs dprofpp.  If you wish you can rerun dprofpp with your choice of
options.

   Because components are implemented as anonymous subroutines, any time
spent in components would normally be reported under an unreadable label
like CODE(0xb6cbc).  To remedy this, the -p flag automatically adjusts the
tmon.out file so that components are reported by their component paths.

   Much of the time spent in a typical debug file is initialization, such
as loading Mason and other Perl modules.  The effects of initialization
can swamp profile results and obscure the time actually spent in
components. One remedy is to run multiple iterations of the request inside
the debug file, thus reducing the influence of initialization time.  Pass
the number of desired iterations via the -r flag:

     % ./3 -p -r20

   Currently there are no special provisions for other profiling modules
such as Devel::SmallProf.  You can try simply:

     % perl -d:SmallProf ./3 -r20

   However, this crashes on our Unix system - apparently some bad
interaction between Mason and SmallProf - so it is unsupported for now.

THE PREVIEWER
=============

   Mason comes with a web-based debugging utility that lets you test your
components by throwing fake requests at them. Adjustable parameters
include: UserAgent, Time, HTTP Referer, O/S and so on. For example,
imagine a component whose color scheme is supposed to change each morning,
noon, and night. Using the Previewer, it would be simple to set the
perceived time forward 1,5 or 8 hours to test the component at various
times of day.

   The Previewer also provides a debug trace of a page, showing all
components being called and indicating the portion of HTML each component
is responsible for. For pages constructed from more than a few components,
these traces are quite useful for finding the component that is outputting
a particular piece of HTML.

   Your administrator will give you the main Previewer URL, and a set of
preview ports that you will use to view your site under various
conditions. For the purpose of this discussion we'll assume the Previewer
is up and working, that the Previewer URL is
http://www.yoursite.com/preview, and the preview ports are 3001 to 3005.

   Take a look at the main Previewer page.  The top part contains the most
frequently used options, such as time and display mode.  The middle part
contains a table of your saved configurations; if this is your first time
using the Previewer, it will be empty.  The bottom part contains less
frequently used options, such as setting the user agent and referer.

   Try clicking "Save".  This will save the displayed settings under the
chosen preview port, say 3001, and redraw the page. Under "Saved Port
Settings", you should see a single row showing this configuration.  Your
configurations are saved permanently in a file. If a username/password is
required to access the Previewer, then each user has his/her own
configuration file.

   The "View" button should display your site's home page.  If not, then
the Previewer may not be set up correctly; contact your administrator or
see the Administrator's Guide.

   Go back to the main Previewer page, change the display mode from "HTML"
to "debug", change the preview port to 3002, and click "Save" again.  You
should now see a second saved configuration.

   Click "View".  This time instead of seeing the home page as HTML,
you'll get a debug trace with several sections.  The first section shows a
numbered hierarchy of components used to generate this page. The second
section is the HTML source, with each line annotated on the left with the
number of the component that generated it.  Try clicking on the numbers in
the first section; this brings you to the place in the second section
where that component first appears.  If there's a particular piece of HTML
you want to change on a page, searching in the annotated source will let
you quickly determine which component is responsible.

   The final section of the debug page shows input and output HTTP
headers.  Note that some of these are simulated due to your Previewer
settings.  For example, if you specified a particular user agent in your
Previewer configuration, then the User-Agent header is simulated;
otherwise it reflects your actual browser.

OBJECT-ORIENTED TECHNIQUES
==========================

   Earlier you learned how to assign a common template to an entire
hierarchy of pages using autohandlers. The basic template looks like:

     header HTML
     <% $m->call_next %>
     footer HTML

   However, sometimes you'll want a more flexible template that adjusts to
the requested page.  You might want to allow each page or subsection to
specify a title, background color, or logo image while leaving the rest of
the template intact. You might want some pages or subsections to use a
different template, or to ignore templates entirely.

   These issues can be addressed with the object-oriented style primitives
introduced in Mason 0.85.

   Note: we use the term object-oriented loosely. Mason borrows concepts
like inheritance, methods, and attributes from object methodology but
implements them in a shallow way to solve a particular set of problems.
Future redesigns may incorporate a deeper object architecture if the
current prototype proves successful.

Determining inheritance
-----------------------

   Every component may have a single parent. The default parent is a
component named `autohandler' in the closest parent directory.  This rule
applies to autohandlers too: an autohandler may not have itself as a
parent but may have an autohandler further up the tree as its parent.

   You can use the `inherit' flag to override a component's parent:

     <%flags>
     inherit=>'/foo/bar'
     </%flags>

   If you specify undef as the parent, then the component inherits from no
one.  This is how to suppress templates.

   Currently there is no way to specify a parent dynamically at run-time,
or to specify multiple parents.

Content wrapping
----------------

   At page execution time, Mason builds a chain of components from the
called component, its parent, its parent's parent, and so on. Execution
begins with the top-most component; calling `$m->call_next' passes control
to the next component in the chain.  This is the familiar autohandler
"wrapping" behavior, generalized for any number of arbitrarily named
templates.

Accessing methods and attributes
--------------------------------

   A template can access methods and/or attributes of the requested page.
First, use `$m->base_comp' to get a handle on the appropriate component:

     my $self = $m->base_comp;

   $self now refers to the component corresponding to the requested page
(the component at the end of the chain).

   To access a method for the page, use call_method:

     $self->call_method('header');

   or alternatively a path of the form 'SELF:method':

     <& SELF:header &>
     $m->comp('SELF:header')

   In the context of a component path, SELF is shorthand for
`$m->base_comp'.

   Each of the above looks for a method named 'header' in the page
component.  If no such method exists, the chain of parents is searched
upwards, until ultimately a "method not found" error occurs. Use
'method_exists' to avoid this error for questionable method calls:

     if ($self->method_exists('header')) { ...

   To defer to the method of your parent, use parent:

     $m->current_comp->parent->call_method('header')

   or alternatively a path of the form 'PARENT:method':

     <& PARENT:header &>
     $m->comp('PARENT:header')

   In the context of a component path, PARENT is shorthand for
`$m->current_comp->parent'.

   The rules for attributes are similar. To access an attribute for the
page, use attr:

     my $color = $self->attr('color')

   This looks for an attribute named 'color' in the $self component. If no
such attribute exists, the chain of parents is searched upwards, until
ultimately an "attribute not found" error occurs. Use 'attr_exists' to
avoid this error for questionable attributes:

     if ($self->attr_exists('color')) { ...

Sharing data
------------

   A component's main body and its methods occupy separate lexical scopes.
Variables declared, say, in the `<%init>' section of the main component
cannot be seen from methods.

   To share variables, declare them either in the `<%once>' or `<%shared>'
section. Both sections have an all-inclusive scope. The `<%once>' section
runs once when the component loads; its variables are persistent for the
lifetime of the component. The `<%shared>' section runs once per request
(when needed), just before any code in the component runs; its variables
last only til the end of the request.

   In the following example, various sections of code require information
about the logged-in user. We use a `<%shared>' section to fetch these in a
single request.

     <%attr>
     title=>sub { "Account for $full_name" }
     </%attr>

     <%method lefttoc>
     <i><% $full_name %></i>
     (<a href="logout.html">Log out</a>)<br>
     ...
     </%method>

     Welcome, <% $fname %>. Here are your options:

     <%shared>
     my $dbh = DBI::connect ...;
     my $user = $r->connection->user;
     my $sth = $dbh->prepare("select lname,fname, from users where user_id = '$user'");
     my ($lname,$fname) = $sth->fetchrow_array;
     my $full_name = "$first $last";
     </%shared>

   `<%shared>' presents a good alternative to `<%init>' when data is needed
across multiple scopes. Outside these situations, `<%init>' is preferred
for its slightly greater speed and predictable execution model.

Example
-------

   Let's say we have three components:

     /autohandler
     /products/autohandler
     /products/index.html

   and that a request comes in for /products/index.html.

   /autohandler contains a general template for the site, referring to a
number of standard methods and attributes for each page:

     <head>
     <title><& SELF:title &></title>
     </head>
     <body bgcolor="<% $self->attr('bgcolor') %>">
     <& SELF:header &>
     <table><tr><td>

     <% $m->call_next %>

     </td></tr></table>
     <& SELF:footer &>
     </body>

     <%init>
     my $self = $m->base_comp;
     ...
     </%init>

     <%attr>
     bgcolor=>'white'
     </%attr>

     <%method title>
     McGuffey Inc.
     </%method>

     <%method header>
     <h2><& SELF:title &></h2><p>
     </%method>

     <%method footer>
     </%method>

   Notice how we provide defaults for each method and attribute, even if
blank.

   /products/autohandler overrides some attributes and methods for the
/products section of the site.

     <%attr>
     bgcolor=>'beige'
     </%attr>
     <%method title>
     McGuffey Inc.: Products
     </%method>

     <% $m->call_next %>

   Note that this component, though it only defines attributes and
methods, must call `$m->call_next' if it wants the rest of the chain to
run.

   /products/index.html might override a few attributes, but mainly
provides a primary section for the body.

COMMON TRAPS
============

Do not use print or $r->print
     Most Mason servers operate in "batch" mode, which means that output
     is stored in a Mason buffer until the end of the request. Output sent
     via print and $r->print, however, skips the Mason buffer and goes
     directly to the client. This will result in output being printed out
     of order. Always use `$m->out' instead of print/$r->print; it does the
     right thing with regards to Mason buffering.

Do not call $r->content or "new CGI"
     Mason calls `$r->content' itself to read request input, emptying the
     input buffer and leaving a trap for the unwary: subsequent calls to
     `$r->content' hang the server. This is a mod_perl "feature" that may
     be fixed in an upcoming release.

     For the same reason you should not create a CGI object like

          my $query = new CGI;

     when handling a POST; the CGI module will try to reread request input
     and hang. Instead, create an empty object:

          my $query = new CGI ("");

     such an object can still be used for all of CGI's useful HTML output
     functions. Or, if you really want to use CGI's input functions,
     initialize the object from %ARGS:

          my $query = new CGI (\%ARGS);

AUTHOR
======

   Jonathan Swartz, swartz@pobox.com

SEE ALSO
========

   See HTML/Mason, HTML/Mason/Request,

Mason Component Interpreter
***************************

NAME
====

   HTML::Mason::Interp - Mason Component Interpreter

SYNOPSIS
========

     my $i = new HTML::Mason::Interp (data_dir=>'/usr/local/mason',
                                      comp_root=>'/usr/local/www/htdocs/',
                                      ...other params...);

DESCRIPTION
===========

   Interp is the Mason workhorse, executing components and routing their
output and errors to all the right places. In a mod_perl environment,
Interp objects are handed off immediately to an ApacheHandler object which
internally calls the Interp implementation methods. In that case the only
user method is the new() constructor.

   If you want to call components outside of mod_perl (e.g. from CGI or a
stand-alone Perl script), see the STANDALONE MODE section below.

PARAMETERS FOR new() CONSTRUCTOR
================================

allow_recursive_autohandlers
     True or undef. Default is true as of verison 0.85. If true,
     autohandlers apply both to their own directories and all
     subdirectories; if undef, only to their own directories. See the
     Devel/autohandlers section of the Component Developer's Guide for a
     discussion of the pros and cons.

autohandler_name
     File name used for autohandlers. Default is "autohandler". If undef,
     Mason will not look for autohandlers.

code_cache_max_size
     Specifies the maximum size, in bytes, of the in-memory code cache
     where components are stored. e.g.

          code_cache_max_size => 20*1024*1024
          code_cache_max_size => 20_000_000

     Default is 10 MB. See the Admin/Code Cache section of the *Admin
     Guide* for further details.

comp_root
     The required Mason component root. All components live under the
     comp_root.

     You may also specify multiple component roots to be searched in the
     spirit of Perl's @INC. To do so you must specify a list of lists:

          comp_root => [[key1, root1], [key2, root2], ...]

     Each pair consists of a key and root.  The key is a string that
     identifies the root mnemonically to a component developer.  Data cache
     and object directories are split up by these keys to make sure
     different components sharing the same path have different cache and
     object files. The key is also included whenever Mason prints the
     component title, as in an error message.

     For example:

          comp_root => [['private', '/usr/home/joe/comps'], ['main', '/usr/local/www/htdocs']]

     This specifies two component roots, a main component tree and a
     private tree which overrides certain components.  The order is
     respected ala @INC, so 'private' is searched first and 'main' second.

current_time
     Overrides the time returned by $m->time with a fixed Perl time() value
     (seconds since the epoch). On time-sensitive sites, this can be used
     to set up port-based time/date simulations, e.g. a port that looks one
     day into the future.

     With no current_time parameter (the default), $m->time reports the
     true time.

data_dir
     The required Mason data directory. Mason's various data directories
     (obj, cache, debug, etc), live within the data_dir.

data_cache_dir
     Specifies an absolute directory for data cache files. By default, it
     lives under data_dir/cache.

dhandler_name
     File name used for dhandlers. Default is "dhandler". If undef, Mason
     will not look for dhandlers.

max_recurse
     The maximum component stack depth the interpreter is allowed to
     descend before signalling an error.  Default is 32.

out_method
     Indicates where to send output. If out_method is a reference to a
     scalar, output is appended to the scalar.  If out_method is a
     reference to a subroutine, the subroutine is called with each output
     string. For example, to send output to a file called "mason.out":

          my $fh = new IO::File ">mason.out";
          ...
          out_method => sub { $fh->print($_[0]) }

     By default, out_method prints to standard output. (In a mod_perl
     environment this is automatically redirected to the HTTP client.)

out_mode
     Specifies one of two ways to send output, 'batch' or 'stream'.  In
     batch mode Mason computes the entire page in a memory buffer and then
     transmits it all at once. In stream mode Mason outputs data as soon as
     it is computed. (This does not take into account buffering done by
     Apache or the O/S.) The default mode is batch.  See the Admin/staging
     vs production section of the *Admin Guide* for a discussion of the
     trade-offs.

parser
     Parser object for compiling components on the fly. If omitted, creates
     a parser with default parameters.

preloads
     A list of component paths, optionally with glob wildcards, to load
     when the interpreter initializes. e.g.

          preloads => ['/foo/index.html','/bar/*.pl']

     Default is the empty list. This should only be used for components
     that are frequently viewed and rarely updated.  See the
     Admin/preloading section of the *Admin Guide* for further details.

static_file_root
     Absolute path to prepend to relative filenames passed to
     `$m->file()'. Does not require a trailing slash. For example, if the
     file root is '/foo/bar', then `$m->file('baz/bap')' will read the file
     '/foo/bar/baz/bap'. Undefined by default; if left undefined, relative
     path names to `$m->file()' are prepended with the current component
     directory.

system_log_events
     A string value indicating one or more events to record in the system
     log, separated by "|". Default is to log nothing.

system_log_file
     Absolute path of system log.  Default is data_dir/etc/system.log.

system_log_separator
     Separator to use between fields on a line in the system log. Default
     is ctrl-A ("\cA").

use_data_cache
     True or undef, default is true. Specifies whether the $m->cache and
     related commands are operational.  You may need to disable data
     caching temporarily for debugging purposes, but normally this should
     be left alone.

use_object_files
     True or undef, default is true.  Specifies whether Mason creates
     object files to save the results of component parsing. You may want to
     turn off object files for disk space reasons, but otherwise this
     should be left alone.

use_reload_file
     True or undef, default is undef. If true, disables Mason's automatic
     timestamp checking on component source files, relying instead on an
     explicitly updated Admin/reload file.

verbose_compile_error
     True or undef, default is undef. If true, component compile errors are
     followed with the full component source, annotated with line numbers,
     to better interpret the error message. Does not affect runtime errors.

ACCESSOR METHODS
================

   All of the above properties have standard accessor methods of the same
name. In general, no arguments retrieves the value, and one argument sets
and returns the value.  For example:

     my $interp = new HTML::Mason::Interp (...);
     my $p = $interp->parser;
     my $comproot = $interp->comp_root;
     $interp->out_method(\$buf);

   The following properties can be queried but not modified: comp_root,
data_dir, system_log_file, system_log_separator, preloads.

OTHER METHODS
=============

   This method sets a global to be used in components. `varname' is a
variable name, optionally preceded with a prefix (`$', `@', or %); if the
prefix is omitted then `$' is assumed. `varname' is followed by a value,
in the case of a scalar, or by one or more values in the case of a list or
hash.  For example:

     # Set a global variable $dbh containing the database handle
     $interp->set_global(dbh => DBI->connect(...));

     # Set a global hash %session from a local hash
     $interp->set_global('%session', %s);

   The global is set in the package that components run in: usually
`HTML::Mason::Commands', although this can be overridden via the Parser
parameter Parser/in_package.  The lines above, for example, are equivalent
to:

     $HTML::Mason::Commands::dbh = DBI->connect(...);
     %HTML::Mason::Commands::session = %s;

   assuming that in_package has not been changed.

   Any global that you set should also be registered with the Parser
parameter Parser/allow_globals; otherwise you'll get warnings from strict.

STANDALONE MODE
===============

   Although Mason is most commonly used in conjunction with mod_perl,
there is also a functional API that allows you to use Mason from CGI
programs or from stand-alone Perl scripts.  In the latter case Mason can be
used as a glorified Text::Template, producing a set of files from
components, or used to generate a flat version of a componentized site.

   When using Mason outside of mod_perl, just create a Parser and Interp
object; you do not need the ApacheHandler object.  Once you've created an
interpreter, the main thing you'll want to do with it is call a component
and do something with the output. To call a component, use Interp's exec()
method:

     $interp->exec(<comp> [,<..list of component params..>]);

   where comp is a component path or component object.

   Component parameters are given as a series of name/value pairs, just as
they are with `$m->comp'. exec returns the return value of the component.
Component output is sent to standard output by default, but you can change
this by specifying out_method.

   Here is a skeleton script that calls a component and places the output
in a file:

     my $outbuf;
     my $parser = new HTML::Mason::Parser;
     my $interp = new HTML::Mason::Interp (parser=>$parser,
     					  comp_root=>'<component root>',
     					  data_dir=>'<data directory>',
     					  out_method=>\$outbuf);
     my $retval = $interp->exec('<component path>',<args>...);
     open(F,">mason.out");
     print F $outbuf;
     close(F);
     print "return value of component was: $retval\n";

AUTHOR
======

   Jonathan Swartz, swartz@pobox.com

SEE ALSO
========

   HTML::Mason, HTML::Mason::Parser, HTML::Mason::ApacheHandler,
HTML::Mason::Admin

Used to create simple get & get/set methods in other classes
************************************************************

NAME
====

   HTML::Mason::MethodMaker - Used to create simple get & get/set methods
in other classes

SYNOPSIS
========

     use HTML::Mason::MethodMaker ( read_only => 'foo',
                                    read_write => [ qw( bar baz ) ] );

DESCRIPTION
===========

   This automates the creation of simple accessor methods.

USAGE
=====

   This module creates methods when it is use'd by another module.  There
are two types of methods: 'read_only' and 'read_write'.

   Attributes specified as 'read_only' get an accessor that only returns
the value of the attribute.  Presumably, these attributes are set via more
complicated methods in the class or as a side effect of one of its methods.

   Attributes specified as 'read_write' will take a single optional
parameter.  If given, this parameter will become the new value of the
attribute.  This value is then returned from the method.  If no parameter
is given, then the current value is returned.

Mason Component Parser
**********************

NAME
====

   HTML::Mason::Parser - Mason Component Parser

SYNOPSIS
========

     my $p = new HTML::Mason::Parser (...params...);

DESCRIPTION
===========

   A Parser object translates components into Perl subroutines. Parsers
are typically embedded within (and used by) Interp objects.

PARAMETERS FOR new() CONSTRUCTOR
================================

   These parameters affect the way that components are translated into
Perl code. If you change a Parser's options, you must remove any
previously created object files for the changes to take effect.  See also
Admin/Object files.

allow_globals
     List of variable names, complete with prefix (`$@%'), that you intend
     to use as globals in components.  Normally global variables are
     forbidden by strict, but any variable mentioned in this list is
     granted a reprieve via a "use vars" statement. For example:

          allow_globals => [qw($DBH %session)]

     In a mod_perl environment, $r (the request object) is automatically
     added to this list.

default_escape_flags
     Escape flags to apply to all <% %> expressions by default. The current
     valid flags are

          h - escape for HTML ('<' => '&lt;', etc.)
          u - escape for URL (':' => '%3A', etc.)

     The developer can override default escape flags on a per-expression
     basis; see Devel/escaping_expressions.

ignore_warnings_expr
     Regular expression indicating which warnings to ignore when compiling
     subroutines. Any warning that is not ignored will prevent the
     component from being compiled and executed. For example:

          ignore_warnings_expr =>
              'Global symbol.*requires explicit package'

     If undef, all warnings are heeded; if '.', all warnings are ignored.

     By default, this is set to 'Subroutine .* redefined'.  This allows you
     to declare global subroutines inside <%once> sections and not receive
     an error when the component is reloaded.

in_package
     Indicates the name of the package you wish your components to run in.
     This way different applications or virtual hosts can be run in
     different name spaces.  Default is `HTML::Mason::Commands'.

postamble
     A piece of Perl code to insert at the end of every compiled
     subroutine. Blank by default. See Parser/preamble.

postprocess
     Sub reference that is called to postprocess the code and text portions
     of a compiled component, just before it is assembled into its final
     subroutine form.  The sub is called with two parameters, a scalar
     reference to the script and a string containing either "perl" or
     "alpha" depending on whether the string is code or text respectively.
     The sub is expected to process the string in-place. It will be called
     multiple times, once for each piece of code and text.

     This is the ideal place to translate accents into HTML entities.  It
     could also be used to strip out comments that you have in your HTML
     files that you don't want the end user to see. See Parser/preprocess.

preamble
     A piece of Perl code to insert at the beginning of every compiled
     subroutine. Blank by default, but ApacheHandler adds the line

          use vars qw($r);

     to suppress strict warnings about uses of global $r (the Apache
     request object). See Parser/postamble.

preprocess
     Sub reference that is called to preprocess each component before
     Parser does it's magic.  The sub is called with a single parameter, a
     scalar reference to the script.  The sub is expected to process the
     script in-place.   This is one way to extend the HTML::Mason syntax
     with new tags, etc. See Parser/postprocess.

taint_check
     This flag allows Mason to work when taint checking is on (e.g.
     PerlTaintCheck or -T flag).  If true, Mason will pass all component
     source and filenames through a dummy regular expression match to
     untaint them. In the future this option may become more sophisticated
     to allow stricter checks. Default is false.

use_strict
     Indicates whether to use strict in compiled subroutines.  Default is
     true.

ACCESSOR METHODS
================

   Most of the above properties have standard accessor methods of the same
name: no arguments retrieves the value, and one argument sets it.  For
example:

     my $parser = new HTML::Mason::Parser;
     my $strictmode = $parser->use_strict;
     $parser->use_strict(1);

   The only exception is Parser/allow_globals, which works a bit
differently.

OTHER METHODS
=============

allow_globals (varnames)
     Called with no arguments, this returns the value of allow_globals as a
     list.  Called with one or more variable names, it appends the names to
     the existing list, removing duplicates if any.

     This method compiles a component source script into an Component
     object.  The source may be passed in as a string in *script*, or as a
     filename in *script_file*.

     Returns the new Component object on success, or undef if an error
     occurred. error is an optional scalar reference filled with the error
     message.

     Example of usage:

          # Make a component
          my $comp = $parser->make_component
              (script=>'<%perl>my $name = "World";</%perl>Hello <% $name %>!',
               error => \my $error)
            or die "error while compiling component: $error";

          # Call it from inside another component
          $m->comp($comp);

     make_dirs traverses a tree of components, compiles any out-of-date
     components into object files, and reports errors.

     comp_root and data_dir contain the Mason component root and data
     directory respectively. These are required.

     *paths* is a reference to a list of component paths to make
     recursively. By default, makes '/' (the entire component tree).

     verbose is a flag indicating whether to report components compiled
     and directories created. True by default.

     *predicate* is a subroutine that takes one argument, the component
     source file, and returns true or false indicating whether or not to
     try to compile it.  By default *predicate* ignores all filenames
     ending with "~".

     *dir_create_mode* contains the permissions mode for creating new
     directories, by default 0775.

     *update_reload_file* is a flag indicating whether to update a reload
     file in the data directory as components are recompiled. False by
     default.

     Example of usage:

          #!/usr/bin/perl
          use HTML::Mason;
          use HTML::Mason::ApacheHandler;  # load explicitly to bring in special $m-> commands

          my $p = new HTML::Mason::Parser;
          $p->allow_globals(qw($r));       # allow Apache $r global
          $p->make_dirs (comp_root=>'/usr/home/swartz/web/comps',
                         data_dir=>'/usr/home/swartz/web/mason');

AUTHOR
======

   Jonathan Swartz, swartz@pobox.com

SEE ALSO
========

   HTML::Mason, HTML::Mason::Interp, HTML::Mason::ApacheHandler,
HTML::Mason::Admin

Mason Request Class
*******************

NAME
====

   HTML::Mason::Request - Mason Request Class

SYNOPSIS
========

     $m->abort (...)
     $m->comp (...)
     etc.

DESCRIPTION
===========

   The Request API is your gateway to all Mason features not provided by
syntactic tags. Mason creates a new Request object for every web request.
Inside a component you access the current request object via the global $m.

COMPONENT PATHS
===============

   The methods `Request' in this node, `Request' in this node, `Request'
in this node, and `Request' in this node take a component path as argument.

   * If the path is absolute (starting with a '/'), then the component is
     found relative to the component root.

   * If the path is relative (no leading '/'), then the component is found
     relative to the current component directory.

   * If the path matches both a subcomponent and file-based component, the
     subcomponent takes precedence.

METHODS
=======

   Ends the current request, finishing the page without returning through
components. The optional argument specifies the return value from
`Interp::exec'; in a web environment, this ultimately becomes the HTTP
status code.

   abort() is implemented via die() and can thus be caught by eval().

   Under the current implementation, any pending `<%filter>' sections will
not be applied to the output after an abort.  This is a known bug but
there is no easy workaround.

   The methods aborted and aborted_value return a boolean indicating
whether the current request was aborted and the argument with which it was
aborted, respectively. These would be used, for example, after an eval()
returned with a non-empty `$@'.

   Returns true or undef indicating whether the current request was aborted
with abort.

   Returns the argument passed to abort when the request was aborted.
Returns undef if the request was not aborted or was aborted without an
argument.

   Returns the current base component for method and attributes.
Generally set to the original page component; however, if you invoke
call_method on a component, base_comp is dynamically set to that component
until call_method exits. See `Devel' in this node for examples of usage.

   `$m->cache' lets you store and retrieve the results of computation for
improved performance. Each component has its own data cache for storing
one or more key/value pairs. The cache is implemented as a DBM database.
See the `Devel' in this node section of the *Component Developer's Guide*
for examples and caching strategies.

   The argument to action is one of:

   o retrieve: returns the cache value if successful, or undef if there
was no value or if it has expired.

   o store: stores a new cache value under the given key.  Default key is
'main'.  Returns the value being stored if successful.

   o expire: expires a given cache value or values.  key may be a single
key or a list reference. Default key is 'main'.

   o keys: returns a list of all the keys in the cache.

   value defines what to store. It can be a scalar or a reference to an
arbitrary data structure. The allowable size depends on your DBM
implementation.

   *keep_in_memory* indicates whether to save the value in memory once it
is retrieved. Default is 0, meaning that the value will be retrieved from
the cache file each time. If 1, each child server that retrieves this
value will save its own copy, which can result in substantial memory usage
for larger values. Use sparingly.

   The various expiration options are:

   o *expire_at*: takes an absolute expiration time, in Perl time() format
(number of seconds since the epoch)

   o *expire_in*: takes a relative expiration time of the form
"<num><unit>", where <num> is a positive number and <unit> is one of
seconds, minutes, hours, days, or weeks, or any abbreviation thereof.
E.g. "10min", "30m", "1hour".

   o *expire_next*: takes a string, either 'hour' or 'day'. It indicates
an expiration time at the top of the next hour or day.

   o *expire_if*: calls a given anonymous subroutine and expires if the
subroutine returns a non-zero value. The subroutine is called with one
parameter, the time when the cache value was last written.

   Uses `$m->cache' to cache the entire output and/or the return value of
the current component.  It is typically used right at the top of an
`<%init%>' section.

   To cache the component's output:

     <%init>
         return if $m->cache_self(expire_in=>'3 hours'[, key=>'fookey']);
         ... <rest of init> ...
     </%init>

   To cache the component's return value:

     <%init>
         my ($retval,$cached) = $m->cache_self(expire_in=>'3 hours'[, key=>'fookey']);
         return $retval if $cached;
         ... <rest of init> ...
     </%init>

   This only works with scalar and reference return values.

   `$m->cache_self' handles both the retrieve and store, so you can pass
both kinds of options to it. See `$m->cache' for an explanation of options.

   `$m->cache_self' uses a bit of magic to accomplish everything in one
line.  You can use it without understanding it, but if you're curious,
here's how it works:

   o A component foo calls `$m->cache_self' for the first time.

   o `$m->cache_self' sees that the cache is empty and calls foo again
recursively, with a STORE option to capture its content into a buffer.

   o foo again calls `$m->cache_self' which immediately returns 0 this
time.

   o foo goes about its business and generates content into the
`$m->cache_self' buffer.

   o When control is returned to `$m->cache_self', it stores the content
and return value in the cache and also outputs the content normally.
Finally `$m->cache_self' returns the list (retval,1) which in turn causes
foo to return immediately.

   Returns the arguments passed by the component at the specified stack
level. Use a positive argument to count from the current component and a
negative argument to count from the component at the bottom of the stack.
e.g.

     $m->caller_args(0)   # arguments passed to current component
     $m->caller_args(1)   # arguments passed to component that called us
     $m->caller_args(-1)  # arguments passed to first component executed

   When called in scalar context, a hash reference is returned.  When
called in list context, a list of arguments (which may be assigned to a
hash) is returned.

   With no arguments, returns the current component stack as a list of
component objects, starting with the current component and ending with the
top-level component. With one numeric argument, returns the component
object at that index in the list. Use a positive argument to count from
the current component and a negative argument to count from the component
at the bottom of the stack. e.g.

     my @comps = $m->callers   # all components
     $m->callers(0)            # current component
     $m->callers(1)            # component that called us
     $m->callers(-1)           # first component executed

   Calls the next component in the content wrapping chain; usually called
from an autohandler. With no arguments, the original arguments are passed
to the component.  Any arguments specified here serve to augment and
override (in case of conflict) the original arguments. Works like
`$m->comp' in terms of return value and scalar/list context.  See the
`Devel' in this node section of the *Component Developer's Guide* for
examples.

   Clears the Mason output buffer. Any output sent before this line is
discarded. Useful for handling error conditions that can only be detected
in the middle of a request.

   clear_buffer only works in batch output mode, and is thwarted by
flush_buffer.

   Calls the component designated by comp with the specified option/value
pairs. comp may be a component path or a component object.

   Components work exactly like Perl subroutines in terms of return values
and context. A component can return any type of value, which is then
returned from the `$m->comp' call.

   The <& &> tag provides a convenient shortcut for `$m->comp'.

   Returns 1 if *comp_path* is the path of an existing component, 0
otherwise.

   Returns the number of this request, which is unique for a given request
and interpreter.

   Returns the current component object.

   Used from a top-level component or dhandler, this method aborts the
current request and restarts with the next applicable dhandler up the
tree. If no dhandler is available, an error occurs.  This method bears no
relation to the Apache DECLINED status except in name.

   Returns the current size of the component stack.  The lowest possible
value is 1, which indicates we are in the top-level component.

   If the request has been handled by a dhandler, this method returns the
remainder of the URI or `Interp::exec' path when the dhandler directory is
removed. Otherwise returns undef.

   dhandler_arg may be called from any component in the request, not just
the dhandler.

   Given a *comp_path*, returns the corresponding component object or
undef if no such component exists.

   Returns the next component in the content wrapping chain, or undef if
there is no next component. Usually called from an autohandler.  See the
`Devel' in this node section of the *Component Developer's Guide* for
usage and examples.

   Returns a list of the remaining components in the content wrapping
chain. Usually called from an autohandler.  See the `Devel' in this node
section of the *Component Developer's Guide* for usage and examples.

   Returns the contents of filename as a string. filename may be an
absolute filesystem path (starting with a '/') or relative (no leading
'/'). If relative, Mason prepends the static file root, or the current
component directory if no static file root is defined.

   Returns the static file root, used by `$m->file' to resolve relative
filenames.

   Flushes the Mason output buffer. Under mod_perl, also sends HTTP
headers if they haven't been sent and calls $r->rflush to flush the Apache
buffer. Flushing the initial bytes of output can make your servers appear
more responsive.

   Returns the Interp object associated with this request.

   Print the given string. Rarely needed, since normally all HTML is just
placed in the component body and output implicitly. `$m->out' is useful if
you need to output something in the middle of a Perl block.

   `$m->out' should be used instead of print or `$r->print', since
`$m->out' may be redirected or buffered depending on the current state of
the interpreter.

   Returns the Parser object associated with this request.

   Given a *comp_path*, returns the corresponding absolute component path.

   Like `$m->comp', but returns the component output as a string instead
of printing it. (Think sprintf versus printf.) The component's return
value is discarded.

   Returns the interpreter's notion of the current time in Perl time()
format (number of seconds since the epoch).

   By using `$m->time' rather than calling time() directly, you enable the
option of previewer or port-based time/date simulations. e.g.  a port that
looks one day into the future.

   Returns the arguments originally passed to the top level component.
When called in scalar context, a hash reference is returned. When called
in list context, a list of arguments (which may be assigned to a hash) is
returned.

   Returns the component originally called in the request. Note: because
of autohandlers this may or may not be the first component executed.

APACHE-ONLY METHODS
===================

   These additional methods are available when running Mason with mod_perl
and the ApacheHandler.

   Returns the ApacheHandler object associated with this request.

   Returns the Apache request object.  This is also available in the
global $r.

   Returns the CGI object used to parse any CGI parameters submitted to
the component, assuming that you have not changed the default value of the
ApacheHandler args_method parameter.  If you are using the 'mod_perl' args
method, then calling this method is a fatal error.  See the
HTML/Mason/ApacheHandler, documentation for more
details.

AUTHOR
======

   Jonathan Swartz, swartz@pobox.com

SEE ALSO
========

   See HTML/Mason/Component,
HTML/Mason/ApacheHandler,

Test harness for testing Mason
******************************

NAME
====

   HTML::Mason::Tests - Test harness for testing Mason

SYNOPSIS
========

     use HTML::Mason::Tests;

     my $group = HTML::Mason::Tests->new( name => 'name of group', description => 'tests something' );
     $group->add_test( name => 'foo',
                       description => 'tests foo',
                       component => <<'EOF'
     <%args>
     $foo => 1
     </%args>
     <% $foo %>
     EOF
                       expect => <<'EOF',
     1
     EOF
                     );

DESCRIPTION
===========

   This module is designed to automate as much as possible of the Mason
test suite.  It does tasks like write component files to disk, call them,
compare the actual results to the expected results, and more.  In
addition, it also is capable of printing out useful information about test
failures when run in verbose mode.  See the ADDITIONAL RUN MODES section
for more information.

   It also makes sure that any given group of tests provides all the
information needed to run them (test names, components and results, etc.).

   Now you have no excuse for writing new tests (and that goes double for
me!).

METHODS
=======

new
---

   Takes the following parameters:

   * name (required)

     The name of the entire group of tests.

   * description (required)

     What this group tests.

add_support
-----------

   Takes the following parameters:

   * path (required)

     The path that other components will expect this component to be
     reachable at.  All paths are prepended with the group name.  So '/bar'
     as a support component in the 'foo' group's ultimate path would be
     '/foo/bar'.

   * component

     Text of the support component.  This parameter must have a value
     unless the skip_component parameter is true.

   * skip_component

     If true, then the test harness will not write a component to disk for
     this test.

add_test
--------

   Takes the following parameters:

   * name (required)

     The name of this test.

   * description (required)

     What this test is testing.

   * component (required)

     Text of the component.

   * path (optional)

     The path that this component should written to.  As with support
     components, this path is prepended with the group's name.  If no path
     is given, the value of the name parameter is used.

   * call_path (optional)

     The path that should be used to call the component.  If none is given,
     then the value is the same as the path option, if that exists,
     otherwise it is /<group name>/<test name>.  If a value is given, it is
     still prepended by /<group name>/.

   * call_args (optional)

     The arguments that should be passed to the component, in list or hash
     reference form. If none is given, no arguments are passed.

   * parser_params

     This is a hash reference of parameters to be passed to the Parser->new
     method.

   * interp_params

     This is a hash reference of parameters to be passed to the Interp->new
     method.

   * interp

     Provide an HTML::Mason::Interp object to be used for the test.

   One of the following three options is required:

   * expect

     The text expected as a result of calling the component.  This
     parameter is _not_ required when running in `Create mode|ADDITIONAL
     RUN MODES' in this node.

   * expect_error

     A regex containing that will be matched against the error returned
     from the component execution.

   * skip_expect

     This causes the component to be run but its output is ignored.
     However, if the component execution causes an error this will cause
     the test to fail.  This is used in a few situations where it is
     necessary to just run a component as part the preparation for another
     test.

run
---

   Run the tests in the group.

Class methods
-------------

   These methods are provided since some tests may need to know these
values.

base_path
---------

   The base path under which the component root and data directory for the
tests are created.

comp_root
---------

   Returns the component root directory.

data_dir
--------

   Return the data directory

check_output ( actual => $actual_output, expect => $expected_output )
---------------------------------------------------------------------

   Given the parameters shown above, this method will check to see if the
two are equal.  If they're not equal, it will print out an error message
attempting to highlight the difference.

ADDITIONAL RUN MODES
====================

   The following additional modes are available for running tests.

Verbose mode
------------

   To turn this on, set the environment variables MASON_VERBOSE or
MASON_DEBUG as true or run the tests as 'make test TEST_VERBOSE=1'.  In
this mode, the run method will output information about tests as they are
run.  If a test fails, then it will also show the cause of the failure.

Debug mode
----------

   To turn this on, set the MASON_DEBUG environment variable to a true
value.  In this mode, the run method will print detailed information of
its actions.  This mode includes the output printed in VERBOSE mode.

Create mode
-----------

   If the individual tests are run from the command line with the
'-create' flag, then instead of checking the output of a component, the
test harness will simply output its results.  This allows you to cut and
paste these results back into the test file (assuming they are correct!).

Module which simplifies the creation of web filters.
****************************************************

NAME
====

   HTML::Munger - Module which simplifies the creation of web filters.

SYNOPSIS
========

     use HTML::Munger;

     $munger = new HTML::Munger;
     $munger->set_munger(\&filter_function);
     $output = $munger->munge($URL, $selfURL, $input);

DESCRIPTION
===========

   HTML::Munger is a simple module which allows easy creation of web page
filtering software.  It was first written to build the pootifier at
http://pootpoot.com/?pootify

   The main task which this module performs is attempting to make all the
relative links on the filtered page absolute, so that images, and
hyperlinks work correctly.  It also makes frames and hyperlinks properly
filter back through the filter.

   This leaves two major tasks for the user of HTML::Munger: fetching the
original page, and building a simple munging function.

API
---

   There are really only three important functions you need to know how to
call in order to use this module:

new
     This is a simple constructor, which takes no arguments aside from the
     implicit class.  It returns a blessed reference which is used to call
     the other methods.

set_munger
     This method registers the filtering function you want to be called to
     produce the filtered text.  The function specified will be called
     repeatedly with short blocks of text.  For example, given the
     following HTML:

          <P>Hello</P><CENTER>The quick brown <I>fox</I></CENTER>

     The filtering function would be called three times, with 'Hello',
     'The quick brown ', and 'fox', respectively, as input.  The filter
     function is expected to return a string which will replace the given
     input in the output of the munge() call.

munge
     This method takes three arguments.  The first is the URL of the page
     which is being munged.  Note that the 'munge' method does NOT fetch
     the page for you!  It needs this information in order to make
     relative links in the page absolute.  The second argument is the URL
     of the filtering program.  This is used to make all hyperlinks and
     frames pass back through the filter.  Finally, it takes the input
     HTML as its third argument.  This method returns the munged HTML
     string, which can then be further parsed or sent to the user.

BUGS
====

   Hopefully none.

AUTHOR
======

   J. David Lowe, dlowe@pootpoot.com

SEE ALSO
========

   perl(1), HTML::Parser(3)

News for HTML::Embperl
======================

   * 22. Dec 2000

     After long time of talking, designing, developing, codeing and
     testing I am now happy to announce the first beta of Embperl 2.0. It
     has a totaly rewritten core and makes the way free for a lot of new
     possibilities...

     At the moment it's mainly a speed improvement and introduces caching
     of the (component) output. In the next releases I successively make
     the possibilities of this new architecture available. (see the readme
     below for some ideas what will happen).

     Since it's not yet ready for production use, it's only available from
     my ftp server at

     ftp://ftp.dev.ecos.de/pub/perl/embperl/HTML-Embperl-2.0b1.tar.gz

   * 4. Dec 2000

     After nearly a year of beta test, the final 1.3.0 release is out.
     Beside a lot of enhancements, EmbperlObject which allows you to build
     your web site out of small reusable objects in a OO-style, is the
     main improvement since 1.2.1.

   * 1. Dec 2000

     The slides from my talk on the O'Reilly Open Source Software
     Convention are now available at
     http://www.ecos.de/embperl/index.htm/ep/pod/oscon2000/index.html .

   * 15. Nov 2000

     Embperl 1.3b7 released

   * 18. Oct 2000

     Embperl 1.3b6 released

   * 20. Aug 2000

     Embperl 1.3b5 released

   * 17. July 2000

     Embperl 1.3b4 released

   * 22. Juni 2000

     On the O'Reilly Open Source Software Convention there is again a talk
     about Embperl Embperl - From Embedding Perl into HTML to Objects and
     XML

     http://www.oreillynet.com/pub/e_sess/863

     Slides are available at

     http://www.ecos.de/embperl/index.htm/ep/pod/oscon2000/index.html

   * 26. May 2000

     Embperl RPMs available

   * 26. Apr 2000

     Embperl 1.3b3 released

   * 25. Apr 2000

     Perlmonth starts a new article series about Embperl

     http://www.perlmonth.com/index.html?issue=11

   * 16. Apr 2000

     Added page about syntaxfiles for various editors

   * 20. Mar 2000

     Embperl now has it's own Mailinglist

   * 13. Mar 2000

     Tallyman is a free content management and shopping system based on
     Embperl

     http://sourceforge.net/projects/tallyman/

   * 13. Mar 2000

     Apache::iNcom is a free Web E-Commerce Application Framework based on
     Embperl.

     http://indev.insu.com/iNcom/incom.html

   * 11. Feb 2000

     Embperl 1.3b2 released. This release contains the new EmbperlObject
     which really simplify building a website out of small reusable pieces

   * 5. Jan 2000

     Embperl 1.2.1 released

   * 20. Dec 99

     Added Introduction to DBIx::Recordset

   * 4. Dec 99

     Added Page with WorldWide Mirrors

   * 17. Nov 99

     Embperl 1.2.0 released

   * 4. Nov 99

     Embperl 1.2b11 released

   * 7. Oct 99

     Embperl 1.2b10 released

   * 10. Sept 99

     Embperl 1.2b9 released

   * 10. Sept 99

     Embperl 1.2b9 released

   * 9. Sept 99

     Embperl 1.2b8 released

   * 8. Sept 99

     German Embperl Website is online

   * 30. Aug 99

     Embperl 1.2b7 released

   * 19. Aug 99

     Embperl 1.2b6 released

   * 12. Aug 99

     Article in german Unix magazine iX 9/99 about Embperl and
     DBIx::Recordset

     http://www.heise.de/ix/artikel/1999/09/137/

   * May/April/June 99

     Perlmonth has a column about Embperl

     http://www.perlmonth.com/columns/backend/server_setup.html?issue=1

   * 5. July 99

     Embperl 1.2b5 released

   * 1. July 99

     On the O'Reilly Open Source Software Convention there are two talks
     about Embperl Embperl and DBIx::Recordset - How to Easily Build a
     Database Driven Web Site

     http://conferences.oreilly.com/apache/conf_desc.html#c13

     New Stuff: Embedding Perl

     http://conferences.oreilly.com/perl3/conf_desc.html#p21

generic HTML navigation structure class
***************************************

NAME
====

   HTML::Navigation - generic HTML navigation structure class

SYNOPSIS
========

     my $nav = new HTML::Navigation();

     # a simple, one-level menu
     $nav->structure([
                      __callbacks__ => [ $callbacks ],
                      __param__ => 'param1',
                      'foo',
                      'bar',
                     ]);

     # output a two-item navigation menu with the `bar' item selected
     print $nav->output({ param1 => 'bar' });

DESCRIPTION
===========

   HTML::Navigation makes it easy to generate an HTML navigation structure
without forcing you into any particular layout or design.  All the output
is done by your own subroutines, which the module invokes as callbacks
(code refs).

   You supply the navigation structure and callbacks for generating
different bits of the output, and the module takes care of the rest.  You
may wonder what "the rest" refers to; what else there is to do except
generate output?  Well, HTML::Navigation really comes into its own with
nested (multi-level) navigation structures, including dynamically
generated ones.  The structures are ordered directed acyclic graphs where
each node is a menu item which can optionally have subnodes.

   See `"EXAMPLES"' in this node for the quickest way to learn how the
module works.

   Please note that parsing of the structure is currently performed when
output() is called rather than when new() is called.  This avoids
unnecessary calls to potentially expensive callbacks which may be given to
dynamically generate parts of the navigation structure.

METHODS
=======

new()
-----

     my $nav = new HTML::Navigation(structure => $structure);

   or

     my $nav = new HTML::Navigation();
     $nav->structure($structure);

   The two forms are identical in results.  Likewise you can specify a
`base_url' parameter instead of setting a base url via the base_url()
method.

structure()
-----------

     my $structure = $nav->structure();

     $nav->structure($new_structure);

   Reads/writes the navigation data structure.  See `"EXAMPLES"' in this
node for an extensive tutorial on how to form these data structures.

output()
--------

     my %CGI_params = map { $_ => $req->param($_) } qw/param1 param2/;
     my $out = $nav->output(\%CGI_params);

   Returns the HTML for a navigation menu, as defined by the `_navigation'
key in the frontend object.

dump_all_params()
-----------------

   Returns an array containing all the combinations of CGI parameters
required to select every element in the navigation structure.  Each
combination is in standard CGI QUERY_STRING format, i.e.

     param1=foo;param2=bar;param3=...

params()
--------

     sub unselected_callback {
       my ($nav, %p) = @_;

     # make unselected menu item a hyperlink
     return $nav->ahref(text   => $p{item},
                        params => [ $nav->params(%p) ]);
       }

   Helper method for figuring out what CGI parameters are needed to point
to the item described by `%p'.

ahref()
-------

     my $html = ahref(url    => 'http://www.foobar.com/baz.pl',
                      text   => 'click me', # defaults to the url parameter
                      params => {
                                 param1 => 'val1',
                                 param2 => 'val2',
                                },
                      # any other parameters get added as attributes, e.g.
                      class  => 'myclass', # <A ... CLASS="myclass" ...>
                      ...
                     );

   Convenient method for generating hyperlinks.  All parameters are
optional, but ahref() will moan if it can't figure out a sensible value
for HREF.  The value for the params key can be a hashref or an arrayref;
in the latter case the order of the parameters is preserved in the output.

query_string()
--------------

     # Set $query_string to `param1=foo%20bar;param2=baz'
     my $query_string = $nav->query_string([
                                            param1 => 'foo bar',
                                            param2 => 'baz',
                                           ]);

   This method provides an easy way of generating a string suitable for
appending to the end of a CGI URL in order to create GET queries.

   You can pass the parameters in either a hashref or an arrayref; in the
latter case the order given is preserved.

base_url()
----------

     my $base_url = $nav->base_url();
     $nav->base_url('foo.pl');

   Read/write a base url for the links generated by ahref() to default to
if no url parameter is given.

debug_level()
-------------

     my $current_level = $self->debug_level();

     $self->debug_level($new_level);

   Read/write debugging verbosity level (defaults to 0).

   Debugging appears on STDOUT.

TUTORIAL
========

   Here are some examples of navigation structures.  I will try to
introduce the concepts in increasing order of complexity.  The structures
are always suitable for passing to the structure() method, and each one
can be found as part of a fully working CGI script in the `eg' directory
so that you can experiment with them more yourself.

   Note that they are always arrayrefs rather than hashrefs so that the
ordering of the items is preserved.

A basic three-item, single-level menu
-------------------------------------

   This structure describes a single-level (no submenus) menu with three
items.  The value following `__param__' is the CGI parameter used to
determine which item is selected, and in this case is innovatively called
`param'.

     # Extract from eg/single.cgi
     [
      __param__ => 'param',
      __callbacks__ => [{
                         pre_items  => sub { "<ol>\n"  },
                         post_items => sub { "</ol>\n" },
                         pre_item   => sub { "  <li> " },
                         post_item  => sub { "\n"      },
                         unselected => sub {
                           my ($nav, %p) = @_;
                           return $nav->ahref(text => $p{item},
                                              params => [ $nav->params(%p) ]);
                         },
                         selected => sub {
                           my ($nav, %p) = @_;
                           return $p{item};
                         },
                        }],
      'item 1',
      'item 2',
      'item 3',
     ]

Basic callback types and ordering
---------------------------------

   The value following __callbacks__ is an arrayref containing one hashref
for each level of the navigation structure.  The example above has only
one level, so there is only one hashref inside the array ref.  The
hashrefs map types of callback to the callbacks themselves, which generate
all the output.  So in this example, the callbacks get invoked in the
following order:

     pre_items
       pre_item for item 1
       selected or unselected for item 1
       post_item for item 1

     pre_item for item 2
     selected or unselected for item 2
     post_item for item 2

     pre_item for item 3
     selected or unselected for item 3
     post_item for item 3
       post_items

   Output occurs when the output() method is called, which takes as its
sole argument a hashref describing the current CGI parameters.  It uses
this to determine whether an item is selected or not, so if it is called as

     $nav->output({ param => 'item 2' });

   then the callbacks will be invoked as follows:

     pre_items
       pre_item for item 1
       unselected for item 1
       post_item for item 1

     pre_item for item 2
     selected for item 2
     post_item for item 2

     pre_item for item 3
     unselected for item 3
     post_item for item 3
       post_items

Invocation of callbacks
-----------------------

   As you can see from the `unselected' and `selected' callbacks in the
above code, when a callback is invoked, it gets passed the
HTML::Navigation object as the first parameter, and the remaining
parameters form a hash which contains all the information you could
possibly need to know about the current item in order to generate suitable
output for it.  The keys for the hash include:

   * item

     The name of the current item, e.g. `item 2'.

   * level

     The depth of the current item in the navigation graph.  This will
     always be 0 until we progress to the multi-level examples below.

   * selected

     True iff the current item is selected.  Normally you won't need this
     because you know whether it's selected depending on whether the
     `selected' or `unselected' callback has been invoked, but you could
     use this to change the behaviour of the pre_item callback depending on
     whether the item is selected, for example.

   * leaf

     True iff the current item is a leaf in the navigation tree.  It will
     always be a leaf unless it's a submenu which is currently selected.

   * parent

     The name of the current item's parent.  This is `top' if we're at
     level 0 (which, as noted above, has always been the case in the
     examples so far).

   *You should not attempt to change any of the values in this hash.  If
you do so, you invalidate the module's warranty and no guarantees about
its behaviour can be made.*

More callback types
-------------------

   There are two more callback types to know about.  The first is
`item_glue', which is invoked in between each item:

     pre_items
       pre_item for item 1
       selected or unselected for item 1
       post_item for item 1

     item_glue

     pre_item for item 2
     selected or unselected for item 2
     post_item for item 2

     item_glue

     pre_item for item 3
     selected or unselected for item 3
     post_item for item 3
       post_items

   The second is `omit', which doesn't generate any output, but decides
whether a particular item should be included in or omitted from the
output.  Say that we used the following omit callback:

     sub {
       my ($nav, %p) = @_;
       return $p{item} eq 'item 2';
     }

   Then the callback order would be:

     pre_items
       pre_item for item 1
       selected or unselected for item 1
       post_item for item 1

     item_glue

     pre_item for item 3
     selected or unselected for item 3
     post_item for item 3
       post_items

__default__
-----------

   If we generate output for our single-level menu with no item selected
like so:

     $nav->output({});

   then the callback invocation order will be

     pre_items
       pre_item for item 1
       unselected for item 1
       post_item for item 1

     pre_item for item 2
     unselected for item 2
     post_item for item 2

     pre_item for item 3
     unselected for item 3
     post_item for item 3
       post_items

   so that no item appears selected.  But what if we always want an item
selected, even when the CGI parameter to select one is missing?  The
answer is to include __default__ in the structure:

     [
      __param__ => 'param',
      __callbacks__ => [ $level_0_callbacks ],
      __default__ => 'item 2',
      'item 1',
      'item 2',
      'item 3',
     ]

   Now if the CGI parameter `param' is missing, `item 2' will be selected.
If you want the default selected item to be the first item in the list,
but you don't necessarily know what the first item is called (see
`"Dynamically generating items"' in this node below) then set __default__
to the empty string.

Dynamically generating items
----------------------------

   If you want, you can dynamically build up the navigation structure at
output time by using coderefs:

     # Extract from eg/dynamic.cgi
     sub dynamic_items { [ 'item 2', 'item 3' ] }

     my $nav = new HTML::Navigation(base_url => 'simple.cgi');
     my $structure =
       [
        __param__ => 'param',
        __callbacks__ => [{
                           pre_items  => sub { "<ol>\n"  },
                           post_items => sub { "</ol>\n" },
                           pre_item   => sub { "  <li> " },
                           post_item  => sub { "\n"      },
                           unselected => sub {
                             my ($nav, %p) = @_;
                             return $nav->ahref(text => $p{item},
                                                params => [ $nav->params(%p) ]);
                           },
                           selected => sub {
                             my ($nav, %p) = @_;
                             return $p{item};
                           },
        'item 1',
        \&dynamic_items,
       ];

   `dynamic_items()' will be invoked during the call to output(), not
before.  This is mostly of use with multi-level navigation, for which see
below.

   You can use this "unpacking coderefs" technique to dynamically generate
as much of the contents of the containing arrayref as you want, i.e. even
the `__param__', `__callbacks__', and __default__ bits.

   You now know everything about single-level navigation!

Multi-level navigation
----------------------

   Again, this is best illustrated with an example of a two-level menu
(`eg/two-level.cgi').

     # Extract from eg/two-level.cgi
     [
      __param__ => 'first',
      __callbacks__ => [
                        # level 0
                        {
                         pre_items  => sub { "<ol>\n"  },
                         post_items => sub { "</ol>\n" },
                         pre_item   => sub { "<li> "   },
                         post_item  => sub { "\n"      },
                         unselected => sub {
                           my ($nav, %p) = @_;
                           return $nav->ahref(text => $p{item},
                                              params => [ $nav->params(%p) ]);
                         },
                         selected => sub {
                           my ($nav, %p) = @_;
                           return $p{item};
                         },
                        },

     # level 1
     {
      pre_items  => sub { "<ul>\n"  },
      post_items => sub { "</ul>\n" },
      pre_item   => sub { "<li> "   },
     },
                         ],
        'item 1' => [
                     __param__ => 'submenu_1',
                     'one',
                     'two',
                     'three',
                    ],
        'item 2',
        'item 3' => [
                     __param__ => 'submenu_2',
                     __default__ => 'five',
                     __callbacks__ => [{
                   pre_item  => sub { "<li> <b>" },
                   post_item => sub { " </b>\n"  },
                  }],
                     'four',
                     'five',
                     'six',
                     'seven',
                    ],
       ]

   This has a top-level menu as before, but now clicking on the first and
third items reveal further submenus containing `one' to `three', and
`four' to `seven' respectively.  Note the difference that __default__
creates between the two submenus: when you click on `item 1' it reveals
the first submenu but none of the sub-items are selected, whereas when you
click on `item 3' then `five' immediately gets selected.

   Also note how the callbacks are defined for the submenus (level 1).
Firstly the `pre_items', `post_items', `pre_item', `post_item',
`unselected', and `selected' callbacks are inherited from level 0.  Then
the `pre_items', `post_items', and `pre_item' callbacks are overriden by
the callbacks in the hashref following the `# level 1' comment.  Finally,
in the `item 3' submenu only, the `pre_item' and `post_item' callbacks are
overriden.  The net effect of all this is that both submenus are unordered
lists, and the items of the second submenu (`four' to `seven') are in bold.

   Finally, note that although in this example each submenu has a
different CGI parameter name determining selection within it (`submenu_1'
and `submenu_2'), everything would still work if they had the same CGI
parameter name (e.g. `submenu').

   Dynamic item generation works as before, except it is now potentially
much more useful, because if you have a submenu whose contains are
generated by a coderef which is an expensive operation (e.g. doing a
complex query on a database), then that expensive operation will only be
performed if the contents of that submenu are visible (i.e. iff the
submenu has been selected).

More complex navigation structures
----------------------------------

   All aspects of the navigation structure syntax have now been covered.
If you really want to, you could take a look at the multi-level structure
in `t/MyTest.pm', which contains some pathological features designed to
test the code to its limits.

BUGS / WISHLIST
===============

   Here are a few things aren't nice, and a few things which might be.
Suggestions and comments welcome.

   * The recursion code is convoluted and should be abstracted out.

   * The dump_all_params() stuff is a nasty hack, which I only included to
     make testing easier.

   * Some of the subroutines are way too long.  I tried breaking them up
     several times but always ended up with something even messier :-(

   * Maybe it would be cleaner to do output in two passes - one for parsing
     the navigation structure, and one for doing the output.  I'm guessing
     that most (all?) navigation structures won't be big enough to worry
     about the cost of doing two passes, but I could be wrong.

   * Recursion is currently depth-first only.

   * There needs to be a sanity check for duplicate `__param__' values at
     different levels.

   * Creation/manipulation/retrieval of specific bits of the navigation
     structure via methods, e.g.

          $nav->top->submenu('foo')->add_item('item under foo submenu');

     Maybe use Tree::DAG_Node?  This would mean some major changes though,
     as the structure is currently described as an arrayref, not a hashref,
     so as to preserve ordering.  If the structure parsing phase was
     separated out, that would make this a lot easier.

   * Optional tree-parsing during new() phase rather than during output()
     phase.  This has to be optional, because it would mean that any
     coderefs given to dynamically generate menu items would have to be run
     here, which is bad if your coderefs point to expensive code.

   * Debugging isn't tested.  But then that's kind of the point.

AUTHOR
======

   Adam Spiers <adam@spiers.net>

Class to create HTML page index objects.
****************************************

NAME
====

   HTML::PageIndex - Class to create HTML page index objects.

SYNOPSIS
========

     use HTML::PageIndex;

     $foo = new HTML::PageIndex;

     $zog = $foo->makeindex([total pages],[current page],[base url],[url arguement],[show prev/next]);

     print $zog;

DESCRIPTION
===========

   Will return an object which will display a dynamic index of html pages.
It would look like:

     [Prev] 1 2 3 4 5 6 [Next]

makeindex([total pages],[current page],[base url],[url arguement],[show prev/next]);
     This is currently the only public method. The args are as follows:

          [total pages] - How many total pages are there.

          [current page] - What the current page is. It is expected that the using script
          		 would generate this.

          [base url] - The base url to link to.

          [url arguement] - May be "", but if it isn't it will build a
          		  URL with ?[URL arguement]=[page number]

          [show prev/next] - Default is 0. If 0 it will not show [Prev] if you are on the
          		first page, or [Next] if you are on the last page. If 1, it will
          		show [Prev] and [Next] as text.

INSTALLATION
============

   You install HTML::PageIndex, as you would install any perl module
library, by running these commands:

     perl Makefile.PL
     make
     make install
     make clean

BUGS
====

   None knows at time of writing.

AVAILABILITY
============

   The latest version of HTML::PageIndex should always be available from:

     $CPAN/modules/by-authors/id/K/KM/KMELTZ/

   Visit <URL:http://www.perl.com/CPAN/> to find a CPAN site near you.

   Or, from <URL:http://www.perlguy.com/perl>.

VERSION
=======

   $Revision: 0.2 $ $Date: 1998/12/23 18:47:22 $

CHANGES
=======

   $Log: PageIndex.pm,v $ Revision 0.2  1998/12/23 18:47:22  meltzek Added
POD.

AUTHOR INFORMATION
==================

   Copyright 1998-99, Kevin Meltzer.  All rights reserved.  It may be used
and modified freely, but I do request that this copyright notice remain
attached to the file.  You may modify this module as you wish, but if you
redistribute a modified version, please attach a note listing the
modifications you have made.

   Address bug reports and comments to: perlguy@perlguy.com

   The author makes no warranties, promises, or gaurentees of this
software. As with all software, use at your own risk.

Perl module to handle CGI HTML paging of arbitary data
******************************************************

NAME
====

   HTML::Pager - Perl module to handle CGI HTML paging of arbitary data

SYNOPSIS
========

     use HTML::Pager;
     use CGI;

     # get CGI query object
     my $query = CGI->new();

     # create a callback subroutine to generate the data to be paged
     my $get_data_sub = sub {
        my ($offset, $rows) = @_;
        my @return_array;

     for (my $x = 0; $x < $rows; $x++) {
        push(@return_array, [ time() ]);
     }
     return \@return_array;
       }

     # create a Pager object
     my $pager = HTML::Pager->new(
                                  # required parameters
                                  query => $query,
                                  get_data_callback => $get_data_sub,
                                  rows => 100,
                                  page_size => 10,

     # some optional parameters
     persist_vars => ['myformvar1',
                      'myformvar2',
                      'myformvar3'],
     cell_space_color => '#000000',
     cell_background_color => '#ffffff',
     nav_background_color => '#dddddd',
     javascript_presubmit => 'last_minute_javascript()',
     debug => 1,
                                   );

     # make it go - send the results to the browser.
     print $pager->output;

DESCRIPTION
===========

   This module handles the paging of data coming from an arbitrary source
and being displayed using HTML::Template and CGI.pm.  It provides an
interface to pages of data similar to many well-known sites, like
altavista.digital.com or www.google.com.

   This module uses HTML::Template to do all its HTML generation.  While
it is possible to use this module without directly using HTML::Template,
it's not very useful.  Modification of the look-and-feel as well as the
functionality of the resulting HTML should all be done through
HTML::Template objects.  Take a look at HTML/Template,
for more info.

METHODS
=======

new()
-----

   The new() method creates a new Pager object and prepares the data for
output().

   new() requires several options, see above for syntax:

   * query - this is the CGI.pm query object for this run.  Pager will
     remove it's state-maintaining parameters from the query.  They all
     begin with PAGER_, so just be careful not to use that prefix.

   * rows - this is the total number of rows in your dataset.  This is
     needed to provide the next-button, prev-button and page-jump
     functionality.

   * page_size - the number of rows to display at one time.

   * get_data_callback - this is a callback that you provide to get the
     pages of data.  It is passed two arguements - the offset and the
     number of rows in the page.  You return an array ref containing array
     refs of row data.  For you DBI-heads, this is very similar to
     selectall_arrayref() - so similar that for very simple cases you can
     just pass the result through.  Example - this is a sub that returns
     data from an in-memory array of hash refs.

          my @data = (
                       { name => sam, age => 10 },
                       { name => saa, age => 11 },
                       { name => sad, age => 12 },
                       { name => sac, age => 13 },
                       { name => sab, age => 14 },
                       # ...
                     );

          my $get_data_sub = sub {
             my ($offset, $rows) = @_;
             my @return_array;

          for (my $x = 0; $x < $rows; $x++) {
             push(@return_array, [ $data[$offset + $x]{name},
                                   $data[$offset + $x]{age}
                                 ]
                 );
          }
          return \@return_array;
            }

            my $pager = HTML::Pager->new(query => $query,
                                    get_data_callback => $get_data_sub,
                                    rows => 100,
                                    page_size => 10
                                   );

     You can also specify arguements to be passed to your callback
     function.  To do this, call new like:

          HTML::Pager->new(query => $query,
                           get_data_callback => [$get_data_sub, $arg, $arg],
                           rows => 100,
                           page_size => 10
                          );

     If you want to use named, rather than numeric TMPL_VARs in your Pager
     template you can return a ref to an array of hashes rather than
     arrays.  This array of hashes will be passed directly to
     HTML::Template to fill in the loop data for your paging area.

   new() supports several optional arguements:

   * debug - if set to 1, debugging information is warn()'d during the
     program run.  Defaults to 0.

   * template - this is an HTML::Template object to use instead of the
     auto-generated HTML::Template used in Pager output.  It must define
     the following TMPL_LOOPs and TMPL_VARs.  Here's what the default
     template looks like, to give you an idea of how to change it to suite
     your purposes:

          <TMPL_VAR NAME="PAGER_JAVASCRIPT">
          <FORM>
          <TABLE BORDER=0 BGCOLOR=#000000 WIDTH=100%>
          <TR><TD><TABLE BORDER=0 WIDTH=100%>
          <TMPL_LOOP NAME="PAGER_DATA_LIST">
            <TR>
              <TD BGCOLOR=#ffffff><TMPL_VAR NAME="PAGER_DATA_COL_0"></TD>
              <TD BGCOLOR=#ffffff><TMPL_VAR NAME="PAGER_DATA_COL_1"></TD>
              <TD BGCOLOR=#ffffff><TMPL_VAR NAME="PAGER_DATA_COL_2"></TD>
              <!--- depends on number of rows in data - so should your replacement! -->
            </TR>
          </TMPL_LOOP>
          <TR><TD BGCOLOR=#DDDDDD COLSPAN=3 ALIGN=CENTER>
            <TMPL_VAR NAME="PAGER_PREV">
            <TMPL_VAR NAME="PAGER_JUMP">
            <TMPL_VAR NAME="PAGER_NEXT">
          </TD></TR>
          </TABLE>
          </TABLE>
          <TMPL_VAR NAME="PAGER_HIDDEN">
          </FORM>

     Make sure you include all the TMPL_LOOPs and TMPL_VARs included above.
     If you get HTML::Template errors about trying to set bad param
     'PAGER_BLAH', that probably means you didn't put the 'PAGER_BLAH'
     variable in your template.  You can put extra state-maintaining
     <INPUT> fields in the paging form - in fact, I think that this is
     probably required for most real-world uses.

     Optionally you can use named parameters inside PAGER_DATA_LIST, and
     return an array of hashes to fill them in from get_data_callback.  If
     you did that your template might look like:

          ...
          <TMPL_LOOP NAME="PAGER_DATA_LIST">
            <TR>
              <TD BGCOLOR=#ffffff><TMPL_VAR NAME="NUMBER"></TD>
              <TD BGCOLOR=#ffffff><TMPL_VAR NAME="FIRST_NAME"></TD>
              <TD BGCOLOR=#ffffff><TMPL_VAR NAME="LAST_NAME"></TD>
            </TR>
          </TMPL_LOOP>
          ...

   * persist_vars - Pass a ref to an array of the names of the CGI form
     parameters you want to store into this fuction, and they will be
     included in the hidden form data of the pager form.

     This method allows you to have hidden form variables which persist
     from page to page.  This is useful when connecting your pager to some
     other function (such as a search form) which needs to keep some data
     around for later use.

     The old $pager->persist_vars() syntax still works but is deprecated.

   * column_names - should be set to an array ref containing the names of
     the columns - this will be used to create column headers.  Without
     this arguement, the columns will have no headers.  This option is only
     useful in very simple cases where all the data is actually in use as
     columns.  Example:

          my $pager = HTML::Pager->new( column_names => [ 'one', 'two' ]);

   * cell_space_color - this specifies the color of the lines separating
     the cells.  If the default template is mostly OK, except for the color
     scheme, this will provide a middle ground between the necessity of
     creating your own Pager template and suffering with bad colors.
     Example:

          my $pager = HTML::Pager->new( cell_space_color => '#222244' );

   * cell_background_color - this specifies the background color of each
     data cell.  If the default template is mostly OK, except for the color
     scheme, this will provide a middle ground between the necessity of
     creating your own Pager template and suffering with bad colors.
     Example:

          my $pager = HTML::Pager->new( cell_background_color => '#000000' );

   * nav_background_color - this specifies the background color of the
     bottom navigation bar.  If the default template is mostly OK, except
     for the color scheme, this will provide a middle ground between the
     necessity of creating your own Pager template and suffering with bad
     colors.  Example:

          my $pager = HTML::Pager->new( nav_background_color => '#222244' );

   * javascript_presubmit - this optional parameter allows you to specify a
     Javascript function which will be called when a user clicks on one of
     the Pager navigation buttons, prior to submitting the form.  Only if
     this function returns 'true' will the form be submitted.

     The Pager navigation calls its 'PAGER_set_offset_and_submit()'
     javascript function when a user clicks the "Next", "Previous" or other
     page buttons.  This normally precludes calling your own javascript
     submit functions to perform some task.

     Through this hook, you can perform client-side functions, such as form
     validation, which can modify the form or actually prevent the user
     from going to the next page.  This is particularly useful for enabling
     some kind of work-flow involving form validation.

          Constructor Example:

          my $pager = HTML::Pager->new(
                         javascript_presubmit => 'last_minute_javascript()'
                      );

          HTML Example:

          <script language=Javascript>
              function last_minute_javascript() {
                  return confirm("Are you sure you want to leave this page?");
              }
          </script>

output()
--------

   This method returns the HTML <FORM> and <TABLE> to create the paging
list-view.  If you used the template option to new() this will output the
entire template.

MAINTAINING PAGING STATE
========================

   Sometimes you'll want to be able to allow the user to leave your paging
list and be able to come back to where they were without requiring that
they use the Back button.  To do this all you have to do is arrange to
save the state of the PAGER_offset parameter, and pass it back to the
paging-list CGI.

CREDITS
=======

   This module was created for Vanguard Media and I'd like to thank my
boss, Jesse Erlbaum, for allowing me to release it to the public.  He also
added the persist_vars functionality, the background colors option and the
javascript_presubmit option.

AUTHOR
======

   Sam Tregar, sam@tregar.com

LICENSE
=======

   HTML::Template : A Perl module to handle CGI HTML paging of arbitary
data Copyright (C) 1999 Sam Tregar (sam@tregar.com)

   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

SEE ALSO
========

   See HTML/Template, CGI,

Deprecated, a wrapper around HTML::TreeBuilder
**********************************************

NAME
====

   HTML::Parse - Deprecated, a wrapper around HTML::TreeBuilder

SYNOPSIS
========

     See the documentation for HTML::TreeBuilder

DESCRIPTION
===========

   Disclaimer: This module is provided only for backwards compatibility
with earlier versions of this library.  New code should not use this
module, and should really use the HTML::Parser and HTML::TreeBuilder
modules directly, instead.

   The `HTML::Parse' module provides functions to parse HTML documents.
There are two functions exported by this module:

parse_html($html) or parse_html($html, $obj)
     This function is really just a synonym for $obj->parse($html) and $obj
     is assumed to be a subclass of HTML::Parser.  Refer to
     HTML/Parser, for more documentation.

     If $obj is not specified, the $obj will default to an internally
     created new HTML::TreeBuilder object configured with strict_comment()
     turned on.  That class implements a parser that builds (and is) a HTML
     syntax tree with HTML::Element objects as nodes.

     The return value from parse_html() is $obj.

parse_htmlfile($file, [$obj])
     Same as parse_html(), but pulls the HTML to parse, from the named
     file.

     Returns undef if the file could not be opened, or $obj otherwise.

   When a HTML::TreeBuilder object is created, the following variables
control how parsing takes place:

$HTML::Parse::IMPLICIT_TAGS
     Setting this variable to true will instruct the parser to try to
     deduce implicit elements and implicit end tags.  If this variable is
     false you get a parse tree that just reflects the text as it stands.
     Might be useful for quick & dirty parsing.  Default is true.

     Implicit elements have the implicit() attribute set.

$HTML::Parse::IGNORE_UNKNOWN
     This variable contols whether unknow tags should be represented as
     elements in the parse tree.  Default is true.

$HTML::Parse::IGNORE_TEXT
     Do not represent the text content of elements.  This saves space if
     all you want is to examine the structure of the document.  Default is
     false.

$HTML::Parse::WARN
     Call warn() with an apropriate message for syntax errors.  Default is
     false.

REMEMBER!
=========

   HTML::TreeBuilder objects should be explicitly destroyed when you're
finished with them.  See HTML/TreeBuilder.

SEE ALSO
========

   See HTML/Parser, HTML/TreeBuilder,
see HTML/Element,

COPYRIGHT
=========

   Copyright 1995-1998 Gisle Aas. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Gisle Aas <gisle@aas.no>.  Current maintainer Sean M. Burke
<sburke@cpan.org>

HTML parser class
*****************

NAME
====

   HTML::Parser - HTML parser class

SYNOPSIS
========

     use HTML::Parser ();

     # Create parser object
     $p = HTML::Parser->new( api_version => 3,
                             start_h => [\&start, "tagname, attr"],
                             end_h   => [\&end,   "tagname"],
                             marked_sections => 1,
                           );

     # Parse document text chunk by chunk
     $p->parse($chunk1);
     $p->parse($chunk2);
     #...
     $p->eof;                 # signal end of document

     # Parse directly from file
     $p->parse_file("foo.html");
     # or
     open(F, "foo.html") || die;
     $p->parse_file(*F);

   HTML::Parser version 2 style subclassing and method callbacks:

     {
        package MyParser;
        use base 'HTML::Parser';

     sub start {
        my($self, $tagname, $attr, $attrseq, $origtext) = @_;
        #...
     }

     sub end {
     	my($self, $tagname, $origtext) = @_;
     	#...
     }

     sub text {
     	my($self, $origtext, $is_cdata) = @_;
     	#...
     }
      }

     my $p = MyParser->new;
     $p->parse_file("foo.html");

DESCRIPTION
===========

   Objects of the HTML::Parser class will recognize markup and separate it
from plain text (alias data content) in HTML documents.  As different
kinds of markup and text are recognized, the corresponding event handlers
are invoked.

   HTML::Parser in not a generic SGML parser.  We have tried to make it
able to deal with the HTML that is actually "out there", and it normally
parses as closely as possible to the way the popular web browsers do it
instead of strictly following one of the many HTML specifications from
W3C.  Where there is disagreement there is often an option that you can
enable to get the official behaviour.

   The document to be parsed may be supplied in arbitrary chunks.  This
makes on-the-fly parsing as documents are received from the network
possible.

   If event driven parsing does not feel right for your application, you
might want to use `HTML::TokeParser'.  It is a HTML::Parser subclass that
allows a more conventional program structure.

METHODS
=======

   The following method is used to construct a new HTML::Parser object:

$p = HTML::Parser->new( %options_and_handlers )
     This class method creates a new HTML::Parser object and returns it.
     Key/value pair arguments may be provided to assign event handlers or
     initialize parser options.  The handlers and parser options can also
     be set or modified later by method calls described below.

     If a top level key is in the form "<event>_h" (e.g., "text_h"} then it
     assigns a handler to that event, otherwise it initializes a parser
     option. The event handler specification value must be an array
     reference.  Multiple handlers may also be assigned with the 'handlers
     => [%handlers]' option.  See examples below.

     If new() is called without any arguments, it will create a parser that
     uses callback methods compatible with version 2 of HTML::Parser.  See
     the section on "version 2 compatibility" below for details.

     Special constructor option 'api_version => 2' can be used to
     initialize version 2 callbacks while still setting other options and
     handlers.  The 'api_version => 3' option can be used if you don't want
     to set any options and don't want to fall back to v2 compatible mode.

     Examples:

          $p = HTML::Parser->new(api_version => 3,
                                 text_h => [ sub {...}, "dtext" ]);

     This creates a new parser object with a text event handler subroutine
     that receives the original text with general entities decoded.

          $p = HTML::Parser->new(api_version => 3,
          			start_h => [ 'my_start', "self,tokens" ]);

     This creates a new parser object with a start event handler method
     that receives the $p and the tokens array.

          $p = HTML::Parser->new(api_version => 3,
          		        handlers => { text => [\@array, "event,text"],
                                               comment => [\@array, "event,text"],
                                             });

     This creates a new parser object that stores the event type and the
     original text in @array for text and comment events.

   The following methods feed the HTML document to the HTML::Parser object:

$p->parse( $string )
     Parse $string as the next chunk of the HTML document.  The return
     value is normally a reference to the parser object (i.e. $p).
     Handlers invoked should not attempt modify the $string in-place until
     $p->parse returns.

     If an invoked event handler aborts parsing by calling $p->eof, then
     $p->parse() will return a FALSE value.

$p->parse_file( $file )
     Parse text directly from a file.  The $file argument can be a
     filename, an open file handle, or a reference to a an open file
     handle.

     If $file contains a filename and the file can't be opened, then the
     method returns an undefined value and $! tells why it failed.
     Otherwise the return value is a reference to the parser object.

     If a file handle is passed as the $file argument, then the file will
     normally be read until EOF, but not closed.

     If an invoked event handler aborts parsing by calling $p->eof, then
     $p->parse_file() may not have read the entire file.

     On systems with multi-byte line terminators, the values passed for the
     offset and length argspecs may be too low if parse_file is called with
     a file handle that is not in binary mode.

$p->eof
     Signals the end of the HTML document.  Calling the $p->eof method
     outside a handler callback will flush any remaining buffered text
     (which triggers the text event if there is any remaining text).

     Calling $p->eof inside a handler will terminate parsing at that point
     and cause $p->parse to return a FALSE value.  This also terminates
     parsing by $p->parse_file().

     The return value is a reference to the parser object.

   Most parser options are controlled by boolean attributes.  Each boolean
attribute is enabled by calling the corresponding method with a TRUE
argument and disabled with a FALSE argument.  The attribute value is left
unchanged if no argument is given.  The return value from each method is
the old attribute value.

   Methods that can be used to get and/or set parser options are:

$p->strict_comment( [$bool] )
     By default, comments are terminated by the first occurrence of "->".
     This is the behaviour of most popular browsers (like Netscape and
     MSIE), but it is not correct according to the official HTML standard.
     Officially, you need an even number of "-" tokens before the closing
     ">" is recognized and there may not be anything but whitespace
     between an even and an odd "-".

     The official behaviour is enabled by enabling this attribute.

$p->strict_names( [$bool] )
     By default, almost anything is allowed in tag and attribute names.
     This is the behaviour of most popular browsers and allows us to parse
     some broken tags with invalid attr values like:

          <IMG SRC=newprevlstGr.gif ALT=[PREV LIST] BORDER=0>

     By default, "LIST]" is parsed as a boolean attribute, not as part of
     the ALT value as was clearly intended.  This is also what Netscape
     sees.

     The official behaviour is enabled by enabling this attribute.  If
     enabled, it will cause the tag above to be reported as text since
     "LIST]" is not a legal attribute name.

$p->boolean_attribute_value( $val )
     This method sets the value reported for boolean attributes inside HTML
     start tags.  By default, the name of the attribute is also used as its
     value.  This affects the values reported for tokens and attr argspecs.

$p->xml_mode( [$bool] )
     Enabling this attribute changes the parser to allow some XML
     constructs such as *empty element tags* and *XML processing
     instructions*.  It disables forcing tag and attribute names to lower
     case when they are reported by the `tagname' and attr argspecs, and
     suppress special treatment of elements that are parsed as CDATA for
     HTML.

     *Empty element tags* look like start tags, but end with the character
     sequence "/>".  When recognized by HTML::Parser they cause an
     artificial end event in addition to the start event.  The text for
     the artificial end event will be empty and the `tokenpos' array will
     be undefined even though the only element in the token array will have
     the correct tag name.

     *XML processing instructions* are terminated by "?>" instead of a
     simple ">" as is the case for HTML.

$p->unbroken_text( [$bool] )
     By default, blocks of text are given to the text handler as soon as
     possible (but the parser makes sure to always break text at the
     boundary between whitespace and non-whitespace so single words and
     entities always can be decoded safely).  This might create breaks that
     make it hard to do transformations on the text. When this attribute is
     enabled, blocks of text are always reported in one piece.  This will
     delay the text event until the following (non-text) event has been
     recognized by the parser.

$p->marked_sections( [$bool] )
     By default, section markings like <![CDATA[...]]> are treated like
     ordinary text.  When this attribute is enabled section markings are
     honoured.

     There are currently no events associated with marked section elements.

   As markup and text is recognized, handlers are invoked.  The following
method is used to set up handlers for different events:

$p->handler( event => \&subroutine, argspec )
$p->handler( event => method_name, argspec )
$p->handler( event => \@accum, argspec )
$p->handler( event => "" );
$p->handler( event => undef );
$p->handler( event );
     This method assigns a subroutine, method, or array to handle an event.

     Event is one of text, start, end, `declaration', comment, process or
     default.

     Subroutine is a reference to a subroutine which is called to handle
     the event.

     *Method_name* is the name of a method of $p which is called to handle
     the event.

     *Accum* is a array that will hold the event information as sub-arrays.

     If the second argument is "", the event is ignored.  If it is undef,
     the default handler is invoked for the event.

     Argspec is a string that describes the information to be reported for
     the event.  Any requested information that does not apply to a
     specific event is passed as undef.  If argspec is omitted, then it is
     left unchanged since last update.

     The return value from $p->handle is the old callback routine or a
     reference to the accumulator array.

     Return values from handler callback routines/methods are always
     ignored.  A handler callback can request parsing to be aborted by
     invoking the $p->eof method.  A handler callback is not allowed to
     invoke $p->parse() or $p->parse_file().

     Examples:

          $p->handler(start =>  "start", 'self, attr, attrseq, text' );

     This causes the "start" method of object $p to be called for 'start'
     events.  The callback signature is $p->start(\%attr, \@attr_seq,
     $text).

          $p->handler(start =>  \&start, 'attr, attrseq, text' );

     This causes subroutine start() to be called for 'start' events.  The
     callback signature is start(\%attr, \@attr_seq, $text).

          $p->handler(start =>  \@accum, '"S", attr, attrseq, text' );

     This causes 'start' event information to be saved in @accum.  The
     array elements will be ['S', \%attr, \@attr_seq, $text].

          $p->handler(start => "");

     This causes 'start' events to be ignored.  It also supresses
     invokations of any default handler for start events.  It is equivalent
     to $p->handler(start => sub {}), but is more efficient.

          $p->handler(start => undef);

     This causes no handler to be assosiated with start events.  If there
     is a default handler it will be invoked.

Argspec
-------

   Argspec is a string containing a comma separated list that describes
the information reported by the event.  The following argspec identifier
names can be used:

`self'
     Self causes the current object to be passed to the handler.  If the
     handler is a method, this must be the first element in the argspec.

tokens
     Tokens causes a reference to an array of token strings to be passed.
     The strings are exactly as they were found in the original text, no
     decoding or case changes are applied.

     For `declaration' events, the array contains each word, comment, and
     delimited string starting with the declaration type.

     For comment events, this contains each sub-comment.  If
     $p->strict_comments is disabled, there will be only one sub-comment.

     For start events, this contains the original tag name followed by the
     attribute name/value pairs.  The value of boolean attributes will be
     either the value set by $p->boolean_attribute_value or the attribute
     name if no value has been set by $p->boolean_attribute_value.

     For end events, this contains the original tag name (one token only).

     For process events, this contains the process instructions (one token
     only).

     This passes undef for text events.

`tokenpos'
     Tokenpos causes a reference to an array of token positions to be
     passed.  For each string that appears in tokens, this array contains
     two numbers.  The first number is the offset of the start of the
     token in the original text and the second number is the length of the
     token.

     Boolean attributes in a start event will have (0,0) for the attribute
     value offset and length.

     This passes undef if there are no tokens in the event (e.g., text)
     and for artifical end events triggered by empty element tags.

     If you are using these offsets and lengths to modify text, you should
     either work from right to left, or be very careful to calculate the
     changes to the offsets.

`token0'
     Token0 causes the original text of the first token string to be
     passed.  This should always be the same as $tokens->[0].

     For `declaration' events, this is the declaration type.

     For start and end events, this is the tag name.

     For process and non-strict comment events, this is everything inside
     the tag.

     This passes undef if there are no tokens in the event.

`tagname'
     This is the element name (or *generic identifier* in SGML jargon) for
     start and end tags.  Since HTML is case insensitive this name is
     forced to lower case to ease string matching.

     Since XML is case sensitive, the tagname case is not changed when
     `xml_mode' is enabled.

     The declaration type of declaration elements is also passed as a
     tagname, even if that is a bit strange.  In fact, in the current
     implementation tagname is identical to `token0' except that the name
     may be forced to lower case.

attr
     Attr causes a reference to a hash of attribute name/value pairs to be
     passed.

     Boolean attributes' values are either the value set by
     $p->boolean_attribute_value or the attribute name if no value has been
     set by $p->boolean_attribute_value.

     This passes undef except for start events.

     Unless `xml_mode' is enabled, the attribute names are forced to lower
     case.

     General entities are decoded in the attribute values and one layer of
     matching quotes enclosing the attribute values are removed.

`attrseq'
     Attrseq causes a reference to an array of attribute names to be
     passed.  This can be useful if you want to walk the attr hash in the
     original sequence.

     This passes undef except for start events.

     Unless `xml_mode' is enabled, the attribute names are forced to lower
     case.

text
     Text causes the source text (including markup element delimiters) to
     be passed.

`dtext'
     Dtext causes the decoded text to be passed.  General entities are
     automatically decoded unless the event was inside a CDATA section or
     was between literal start and end tags (`script', style, `xmp', and
     plaintext).

     The ISO 8859-1 character set (aka Latin1) is assumed for entity
     decoding.

     It is planned that HTML::Parser will get an utf8 option at some point
     that will affect the byte sequence that characters with codes greater
     than 127 will decode into.

     This passes undef except for text events.

is_cdata
     Is_cdata causes a TRUE value to be passed if the event is inside a
     CDATA section or is between literal start and end tags (`script',
     style, `xmp', and plaintext).

     When the flag is FALSE for a text event, then you should normally
     either use `dtext' or decode the entities yourself before the text is
     processed further.

offset
     Offset causes the byte position in the HTML document of the start of
     the event to be passed.  The first byte in the document is 0.

length
     Length causes the number of bytes of the source text of the event to
     be passed.

event
     Event causes the event name to be passed.

     The event name is one of text, start, end, `declaration', comment,
     process or default.

line
     *Note: This is not supported yet!*

     Line causes the line number of the start of the event to be passed.
     The first line in the document is 1.  Line counting doesn't start
     until at least one handler requests this value.

`'...''
     A literal string of 0 to 255 characters enclosed in single (') or
     double (") quotes is passed as entered.

undef
     Pass an undefined value.  Useful as padding.

Events
------

   Handlers for the following events can be registered:

text
     This event is triggered when plain text is recognized.  The text may
     contain multiple lines.  A sequence of text may be broken between
     several text events unless $p->unbroken_text is enabled.

     The parser will make sure that it does not break a word or a sequence
     of whitespace between two text events.

start
     This event is triggered when a start tag is recognized.

     Example:

          <A HREF="http://www.perl.com/">

end
     This event is triggered when an end tag is recognized.

     Example:

          </A>

`declaration'
     This event is triggered when a *markup declaration* is recognized.

     For typical HTML documents, the only declaration you are likely to
     find is <!DOCTYPE ...>.

     Example:

          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
          "http://www.w3.org/TR/html40/strict.dtd">

     DTDs inside <!DOCTYPE ...> will confuse HTML::Parser.

comment
     This event is triggered when a markup comment is recognized.

     Example:

          <!-- This is a comment -- -- So is this -->

process
     This event is triggered when a processing instructions markup is
     recognized.

     The format and content of processing instructions is system and
     application dependent.

     Examples:

          <? HTML processing instructions >
          <? XML processing instructions ?>

default
     This event is triggered for events that do not have a specific
     handler.  You can set up a handler for this event to catch stuff you
     did not want to catch explicitly.

VERSION 2 COMPATIBILITY
=======================

   When an HTML::Parser object is constructed with no arguments, a set of
handlers is automatically provided that is compatible with the old
HTML::Parser version 2 callback methods.

   This is equivalent to the following method calls:

     $p->handler(start   => "start",   "self, tagname, attr, attrseq, text");
     $p->handler(end     => "end",     "self, tagname, text");
     $p->handler(text    => "text",    "self, text, is_cdata");
     $p->handler(process => "process", "self, token0, text");
     $p->handler(comment =>
               sub {
     		 my($self, $tokens) = @_;
     		 for (@$tokens) {$self->comment($_);}},
               "self, tokens");
     $p->handler(declaration =>
               sub {
     		 my $self = shift;
     		 $self->declaration(substr($_[0], 2, -1));},
               "self, text");

   Setup of these handlers can also be requested with the "api_version =>
2" constructor option.

SUBCLASSING
===========

   The HTML::Parser class is subclassable.  Parser objects are plain
hashes and HTML::Parser reserves only hash keys that start with
"_hparser".  The parser state can be set up by invoking the init() method
which takes the same arguments as new().

EXAMPLES
========

   The first simple example shows how you might strip out comments from an
HTML document.  We achieve this by setting up a comment handler that does
nothing and a default handler that will print out anything else:

     use HTML::Parser;
     HTML::Parser->new(default_h => [sub { print shift }, 'text'],
                       comment_h => [""],
                      )->parse_file(shift || die) || die $!;

   The next example prints out the text that is inside the <title> element
of an HTML document.  Here we start by setting up a start handler.  When
it sees the title start tag it enables a text handler that prints any text
found and an end handler that will terminate parsing as soon as the title
end tag is seen:

     use HTML::Parser ();

     sub start_handler
     {
       return if shift ne "title";
       my $self = shift;
       $self->handler(text => sub { print shift }, "dtext");
       $self->handler(end  => sub { shift->eof if shift eq "title"; },
     		           "tagname,self");
     }

     my $p = HTML::Parser->new(api_version => 3);
     $p->handler( start => \&start_handler, "tagname,self");
     $p->parse_file(shift || die) || die $!;
     print "\n";

   More examples are found in the "eg/" directory of the `HTML-Parser'
distribution; the program `hrefsub' shows how you can edit all links found
in a document and `htextsub' how to edid the text only; the program
`hstrip' shows how you can strip out certain tags/elements and/or
attributes; and the program `htext' show how to obtain the plain text, but
not any script/style content.

BUGS
====

   HTML::Parser will leave <plaintext> mode when it sees </plaintext>.
Plaintext mode should not really be escapeable.

   The <style> and <script> sections do not end with the first "</", but
need the complete corresponding end tag.

   When the *strict_comment* option is enabled, we still recognize
comments where there is something other than whitespace between even and
odd "-" markers.

   Once $p->boolean_attribute_value has been set, there is no way to
restore the default behaviour.

   There is currently no way to get both quote characters into the same
literal argspec.

   Empty tags, e.g. "<>" and "</>", are not recognized.  SGML allows them
to repeat the previous start tag or close the previous start tag
respecitvely.

   NET tags, e.g. "code/.../" are not recognized.  This is an SGML
shorthand for "<code>...</code>".

   Unclosed start or end tags, e.g. "<tt<b>...</b</tt>" are not recognized.

DIAGNOSTICS
===========

   The following messages may be produced by HTML::Parser.  The notation
in this listing is the same as used in Perldiag (perl.info),:

Not a reference to a hash
     (F) The object blessed into or subclassed from HTML::Parser is not a
     hash as required by the HTML::Parser methods.

Bad signature in parser state object at %p
     (F) The _hparser_xs_state element does not refer to a valid state
     structure.  Something must have changed the internal value stored in
     this hash element, or the memory has been overwritten.

_hparser_xs_state element is not a reference
     (F) The _hparser_xs_state element has been destroyed.

Can't find '_hparser_xs_state' element in HTML::Parser hash
     (F) The _hparser_xs_state element is missing from the parser hash.
     It was either deleted, or not created when the object was created.

API version %s not supported by HTML::Parser %s
     (F) The constructor option 'api_version' with an argument greater than
     or equal to 4 is reserved for future extentions.

Bad constructor option '%s'
     (F) An unknown constructor option key was passed to the new() or
     init() methods.

Parse loop not allowed
     (F) A handler invoked the parse() or parse_file() method.  This is
     not permitted.

marked sections not supported
     (F) The $p->marked_sections() method was invoked in a HTML::Parser
     module that was compiled without support for marked sections.

Unknown boolean attribute (%d)
     (F) Something is wrong with the internal logic that set up aliases for
     boolean attributes.

Only code or array references allowed as handler
     (F) The second argument for $p->handler must be either a subroutine
     reference, then name of a subroutine or method, or a reference to an
     array.

No handler for %s events
     (F) The first argument to $p->handler must be a valid event name;
     i.e. one of "start", "end", "text", "process", "declaration" or
     "comment".

Unrecognized identifier %s in argspec
     (F) The identifier is not a known argspec name.  Use one of the names
     mentioned in the argspec section above.

Literal string is longer than 255 chars in argspec
     (F) The current implementation limits the length of literals in an
     argspec to 255 characters.  Make the literal shorter.

Backslash reserved for literal string in argspec
     (F) The backslash character "\" is not allowed in argspec literals.
     It is reserved to permit quoting inside a literal in a later version.

Unterminated literal string in argspec
     (F) The terminating quote character for a literal was not found.

Bad argspec (%s)
     (F) Only identifier names, literals, spaces and commas are allowed in
     argspecs.

Missing comma separator in argspec
     (F) Identifiers in an argspec must be separated with ",".

SEE ALSO
========

   See HTML/Entities, HTML/TokeParser,
see HTML/HeadParser,
HTML/LinkExtor, HTML/Form,

   See HTML/TreeBuilder, (part of the *HTML-Tree*
distribution)

   http://www.w3.org/TR/REC-html40

   More information about marked sections and processing instructions may
be found at `http://www.sgml.u-net.com/book/sgml-8.htm'.

COPYRIGHT
=========

     Copyright 1996-2001 Gisle Aas. All rights reserved.
     Copyright 1999-2000 Michael A. Chase.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

generate nice HTML files from HTML syntax trees
***********************************************

NAME
====

     HTML::PrettyPrinter - generate nice HTML files from HTML syntax trees

SYNOPSIS
========

     use HTML::TreeBuilder;
     # generate a HTML syntax tree
     my $tree = new HTML::TreeBuilder;
     $tree->parse_file($file_name);
     # modify the tree if you want

     use HTML::PrettyPrinter;
     my $hpp = new HTML::PrettyPrinter ('linelength' => 130,
                                        'quote_attr' => 1);
     # configure
     $tree->address("0.1.0")->attr(_hpp_indent,0);    # for an individual element
     $hpp->set_force_nl(1,qw(body head));             # for tags
     $hpp->set_force_nl(1,qw(@SECTIONS));             # as above
     $hpp->set_nl_inside(0,'default!');               # for all tags

     # format the source
     my $linearray_ref = $hpp->format($tree);
     print @$linearray_ref;

     # alternative: print directly to filehandle
     use FileHandle;
     my $fh = new FileHandel ">$filenaem2";
     if (defined $fh) {
       $hpp->select($fh);
       $hpp->format();
       undef $fh;
       $hpp->select(undef),
     }

DESCRIPTION
===========

   HTML::PrettyPrinter produces nicely formatted HTML code from a HTML
syntax tree. It is especially usefull if the produced HTML file shall be
read or edited manually afterwards. Various parameters let you adapt the
output to different styles and requirements.

   If you don't care how the HTML source looks like as long as it is valid
and readable by browsers, you should use the as_HTML() method of
HTML::Element instead of the pretty printer. It is about five times faster.

   The pretty printer will handle line wrapping, indention and structuring
by the way the whitespace in the tree is represented in the output.
Furthermore upper/lowercase markup and markup minimization, quoting of
attribute values, the encoding of entities and the presence of optional
end tags are configurable.

   There are two types of parameters to influence the output, individual
parameters that are set on a per element and per tag basis and common
parameters that are set only once for each instance of a pretty printer.

   In order to faciliate the configuration a mechanism to handle tag groups
is provided. Thus, it is possible to modify a parameter for a group of tags
(e.g. all known block elements) without writing each tag name explicitly.
Perhaps the code for tag groups will move to an other Perl module in the
future.

   For HTML::Elements that require a special treatment like <PRE>, <XMP>,
<SCRIPT>, comments and declarations, pretty printer will fall back to the
method as_HTML() of the HTML elements.

INDIVIDUAL PARAMETERS
=====================

   Following individual paramters exist

indent n
     The indent of new lines inside the element is increased by n
     coloumns. Default is 2 for all tags.

skip *bool*
     If *true*, the element and its content is skipped from output.
     Default is false.

nl_before n
     Number of newlines before the start tag. Default is 0 for inline
     elements and 1 for other elements.

nl_inside n
     Number of newlines between the tags and the contents of an element.
     Default is 0.

nl_after n
     Number of newlines after an element. Default is 0 for inline elements
     and 1 for other elements.

force_nl *bool*
     Force linebreaks before and after an element even if the HTML tree
     does not contain whitespace at this place. Default is false for inline
     elements and true for all other elements. This parameter is superseded
     if the common parameter allow_forced_nl is set to false.

endtag *bool*
     Print an optional endtag. Default is *true*.

Access Methods
--------------

   Following access methods exist for each individual paramenter.  Replace
parameter by the respective name.

$hpp->parameter($element)
     Takes a reference to an HTML element as argument. Returns the value
     of the parameter for that element. The priority to retrieve the value
     is:

       1. The value of the element's internal attribute `_hpp_*parameter*'.

       2. The value specified inside the pretty printer for the tag of the
          element.

       3. The value specified inside the pretty printer for `'default!''.

$hpp->parameter('tag')
     Like `*parameter*($element)', except that only priorities 2 and 3 are
     evaluated.

$hpp->set_parameter($value,'tag1','tag2',...)
     Sets the parameter for each tag in the list to $value.

     If $value is undefined, the entries for the tags are deleted.

     Beside individual tags the list may include tag groups like
     '`@BLOCK'' (see below) and '`default!''. Individual tag names are
     written in lower case, the names of tag groups start with an '@' and
     are written in upper case letters. Tag groups are expanded during the
     call of `set_*parameter*()'.  '`default!'' sets the default value,
     which is retrived if no value is defined for the individual element
     or tag.

$hpp->set_parameter($value,'all!')
     Deletes all existing settings for parameter inside the pretty printer
     and sets the default to $value..

COMMON PARAMETERS
=================

tabify n
     If non zero, each n spaces at the beginnig of a line are converted
     into one TAB. Default is 8.

linelength n
     The maximum number of character a line should have. Default is 80.

     The linelength may be exceeded if there is no proper way to break a
     line without modifying the content, e.g. inside <PRE> and other
     special elements or if there is no whitespace.

min_bool_attr *bool*
     Minimize boolean attributes, e.g. print <UL COMPACT> instead of <UL
     COMPACT=COMPACT>. Default is true.

quote_attr *bool*
     Always quote attribute values. If false, attribute values consisting
     entirely of letters, digits, periods and hyphens only are not put into
     quotes. Default is false.

entities string
     The string contains all characters that are escaped to their entity
     names.  Default is the bare minimum of "&<>" plus the non breaking
     space 'nbsp' (because otherwise it is difficult for the human eye to
     distiguish it from a normal space in most editors).

wrap_at_tagend NEVER|AFTER_ATTR|ALWAYS
     May pretty printer wrap lines before the closing ankle of a start tag?
     Supported values are the predifined constants NEVER (allow line wraps
     at white space only ), AFTER_ATTR (allow line wraps at the end of
     tags that contain attributes only) and ALWAYS (allow line wraps at
     the end of every start tag). Default is AFTER_ATTR.

allow_forced_nl *bool*
     Allow the addition of white space, that is not in the HTML tree.  If
     set to false (the default) the force_nl parameter is ignored.  It is
     recomended to set this parameter to true if the HTML tree was
     generated with ignore_ignorable_whitespace set to true.

uppercase *bool*
     Use uppercase letters for markup. Default is the value of
     $HTML::Element::html_uc at the time the constructor is called.

Access Method
-------------

$hpp->*paramter*([value])
     Retrieves and optionaly sets the parameter.

OTHER METHODS
=============

$hpp = HTML::PrettyPrinter->new(%common_paremeters)
     This class method creates a new HTML::PrettyPrinter and returns it.
     Key/value pair arguments may be provided to overwrite the default
     settings of common parameters. There is currently no mechanism to
     overwrite the default values for individual parameters at
     construction. Use the `$hpp-'set_parameter()> methods instead.

$hpp->select($fh)
     Select a FileHandle object for output.

     If a FileHandle is selected the generated HTML is printed directly to
     that file. With $hpp->select(undef) you can switch back to the
     default behaviour.

$line_array_ref = $hpp->format($tree,[$indent],[$line_array_ref])
     Format the HTML syntax (sub-) tree.

     $tree is not restricted to the root of the HTML syntax tree. A
     reference to any HTML::Element will do.

     The optional `$indent' indents the first element by n characters

     Return value is the reference to an array with the generated lines.
     If such a reference is provided as third argument, the lines will be
     appended to that array. Otherwise a new array will be created.

     If a FileHandle is selected by a previous call of the
     `$hpp-'select($fh)> method, the lines are printed to the FileHandle
     object directly.  The array of lines is not changed in this case.

TAG GROUPS
==========

   Tag groups are lists that contain the names of tags and other tag groups
which are considered as subsets. This reflects the way allowed content is
specified in HTML DTDs, where e.g. %flow consists of all %block and
%inline elements and %inline covers several subsets like %phrase.

   If you add a tag name to a group A, it will be seen in any group that
contains group A. Thus, it is easy to maintain groups of tags with similar
properties. (and configure HTML pretty printer for these tags).

   The names of tag groups are written in upper case letters with a leading
'@' (e.g. '@BLOCK'). The names of simple tags are written all lower case.

Functions
---------

   All the functions to handle and modify tag groups are included in the
@EXPORT_OK list of `HTML::PrettyPrinter'.

@tag_groups = list_groups()
     Returns a list with the names of all defined tag groups

@tags = group_expand('tag_or_tag_group0',['tag_or_tag_group1',...])
     Returns a list of every tag in the tag groups and their subgroups
     Each tag is listed once only. The order of the list is not specified.

@tag_groups = sub_group('tag_group0',['tag_group1',...])
     Returns a list of every tag group and sub group in the list.  Each
     group is listed once only. The order of the list is not specified.

group_get('@NAME')
     Return the (unexpanded) contents of a tag group.

`group_set('@NAME',['tag_or_tag_group0',...])'
     Set a tag group.

`group_add('@NAME','tag_or_tag_group0',['tag_or_tag_group1',...])'
     Add tags and tag groups to a group.

`group_remove('@NAME','tag_or_tag_group0',['tag_or_tag_group1',...])'
     Remove tags or tag groups from a group. Subgroups are not expanded.
     Thus, `group_remove('@A','@B')' will remove '@B' from '@A' if it is
     included directly. Tags included in '@B' will not be removed from
     '@A'.  Nor will '@A' be changed if '@B' is included in a aubgroup of
     '@A' but not in '@A' directly.

Predefined Tag Groups
---------------------

   There are a couple of predefined tag groups. Use `  foreach my $tg
(list_groups()) {     print "'$tg' => qw(".join(',',group_get($tg)).")\n";
 } ' to get a list.

Examples for tag groups
-----------------------

  1. create some groups `   group_set('@A',qw(a1 a2 a3));
     group_set('@B',qw(b1 b2));   group_set('@C',qw(@A @B c1 @D));   # @D
     needs to be defined when @C is expannded   group_set('@D',qw(d1 @B));
      group_set('@E',qw(e1 @D));   group_set('@F',qw(f1 @A)); '

  2. add tags `   group_add('@A',qw(a4 a5)); # @A contains (a1 a2 a3 a4 a5)
      group_add('@D',qw(d1));    # @D contains (d1 @B d1)
     group_add('@F',group_exapand('@B'),'@F');   # @F contains (f1 @A b1
     b2 f1 @F) '

  3. evaluate `   group_exapand('@E');    # returns e1, d1, b1, b2
     sub_groups('@E');       # returns @B, @D   sub_groups(qw(@E @F));  #
     returns @A, @B, @D   group_get('@F'));       # returns f1, @A, b1,
     b2, f1, @F '

  4. remove tags `   group_remove('@E','@C');  # @E not changed, because
     it doesn't contain @C   group_remove('@E','@D');  # @D removed from @E
      group_remove('@D','d1');  # all d1's are removed. Now @D contains
     @B only   group_remove('@C','@B');  # @C now contains (@a c1 @D), Thus
      sub_groups('@C');         # still returns @A, @B, @D,
                  # because @B is included in @D, too '

  5. application `   # set the indent for tags b1, b2, e1, g1 to 0
     $hpp->set_indent(0,qw(@D @E g1)); '

     If the groups @D or @E are modified afterwards, the configuration of
     the pretty printer is not affected, because `set_indent()' will
     expand the tag groups.

EXAMPLE
=======

   Consider the following HTML tree

     <html> @0
       <head> @0.0
     	<title> @0.0.0
     	  "Demonstrate HTML::PrettyPrinter"
       <body> @0.1
     	<h1> @0.1.0
     	  "Headline"
     	<p align="JUSTIFY"> @0.1.1
     	  "Some text in "
     	  <b> @0.1.1.1
     	    "bold"
     	  " and "
     	  <i> @0.1.1.3
     	    "italics"
     	  " and with 'ä' & 'ü'."
     	<table align="LEFT" border=0> @0.1.2
     	  <tr> @0.1.2.0
     	    <td align="RIGHT"> @0.1.2.0.0
     	      "top right"
     	  <tr> @0.1.2.1
     	    <td align="LEFT"> @0.1.2.1.0
     	      "bottom left"
     	<hr noshade="NOSHADE" size=5> @0.1.3
     	<address> @0.1.4
     	  <a href="mailto:schotten@gmx.de"> @0.1.4.0
     	    "Claus Schotten"

   and `   $hpp = HTML::PrettyPrinter-'new('uppercase' => 1);   print
@{$hpp->format($tree)}; >

   will print

     <HTML><HEAD><TITLE>Demonstrate
     	HTML::PrettyPrinter</TITLE></HEAD><BODY><H1>Headline</H1><P
     	ALIGN=JUSTIFY>Some text in <B>bold</B> and
     	<I>italics</I> and with 'ä' &amp; 'ü'.</P><TABLE
     	ALIGN=LEFT BORDER=0><TR><TD ALIGN=RIGHT>top
     	    right</TD></TR><TR><TD ALIGN=LEFT>bottom
     	    left</TD></TR></TABLE><HR NOSHADE SIZE=5
     	><ADDRESS><A HREF="mailto:schotten@gmx.de"
     	  >Claus&nbsp;Schotten</A></ADDRESS></BODY></HTML>

   That doesn't look very nice. What went wrong? By default
HTML::PrettyPrinter takes a conservative approach on whitespace. It will
enlarge existing whitespace, but it will not introduce new whitespace
outside of tags, because that might change the way a browser renders the
HTML document. However the HTML tree was constructed with
ignore_ignorable_whitespace> turned on.  Thus, there is no whitespace
between block elements that the pretty printer could format. So pretty
printer does line wrapping and indention only.  E.g. the title is in the
third level of the tree. Thus, the second line is indented six characters.
The table cells in the fifth level are indented by ten characters.
Furthermore, you see that there is a whitespace inserted after the last
attribute of the <A> tag.

   Let's set $hpp->allow_forced_nl(1);. Now the *forced_nl* parameters are
enabled. By default, they are set for all non-inline tags. That creates

     <HTML>
       <HEAD>
         <TITLE>Demonstrate HTML::PrettyPrinter</TITLE>
       </HEAD>
       <BODY>
         <H1>Headline</H1>
         <P ALIGN=JUSTIFY>Some text in <B>bold</B> and
           <I>italics</I> and with 'ä' &amp; 'ü'.</P>
         <TABLE ALIGN=LEFT BORDER=0>
           <TR>
     	 <TD ALIGN=RIGHT>top right</TD>
           </TR>
           <TR>
     	 <TD ALIGN=LEFT>bottom left</TD>
           </TR>
         </TABLE>
         <HR NOSHADE SIZE=5>
         <ADDRESS><A HREF="mailto:schotten@gmx.de"
     	 >Claus&nbsp;Schotten</A></ADDRESS>
       </BODY>
     </HTML>

     Much better, isn't it? Now let's improve the structuring.
      $hpp->set_nl_before(2,qw(body table));
      $hpp->set_nl_after(2,qw(table));
     will require two new lines in front of <body> and <table> tags and after
     <table> tags.

     <HTML>
       <HEAD>
         <TITLE>Demonstrate HTML::PrettyPrinter</TITLE>
       </HEAD>

       <BODY>
         <H1>Headline</H1>
         <P ALIGN=JUSTIFY>Some text in <B>bold</B> and
           <I>italics</I> and with 'ä' &amp; 'ü'.</P>

         <TABLE ALIGN=LEFT BORDER=0>
           <TR>
     	 <TD ALIGN=RIGHT>top right</TD>
           </TR>
           <TR>
     	 <TD ALIGN=LEFT>bottom left</TD>
           </TR>
         </TABLE>

         <HR NOSHADE SIZE=5>
         <ADDRESS><A HREF="mailto:schotten@gmx.de"
     	 >Claus&nbsp;Schotten</A></ADDRESS>
       </BODY>
     </HTML>

   Currently the mail address is the only attribute value which is quoted.
Here the quotes are required by the '@' character. For all other attribute
values quotes are optional and thus ommited by default.
$hpp->quote_attr(1); will turn the quotes on.

   $hpp->set_endtag(0,'all!') turns all optional endtags off.  This
affects the </p> (and should affect </tr> and </td>, see below).
Alternatively, we could use $hpp->set_endtag(0,'default!'). That would
turn the default off, too. But it wouldn't delete settings for individual
tags that supersede the default.

   $hpp->set_nl_after(3,'head') requires three new lines after the <head>
element. Because there are already two new lines required by the start of
<body> only one additional line is added.

   $hpp->set_force_nl(0,'td') will inhibit the introduction of whitespace
alround <td>. Thus, the table cells are now on the same line as the table
rows.

     <HTML>
       <HEAD>
         <TITLE>Demonstrate HTML::PrettyPrinter</TITLE>
       </HEAD>

       <BODY>
         <H1>Headline</H1>
         <P ALIGN="JUSTIFY">Some text in <B>bold</B> and
     	<I>italics</I> and with 'ä' &amp; 'ü'.

         <TABLE ALIGN="LEFT" BORDER="0">
     	<TR><TD ALIGN="RIGHT">top right</TD></TR>
     	<TR><TD ALIGN="LEFT">bottom left</TD></TR>
         </TABLE>

         <HR NOSHADE SIZE="5">
         <ADDRESS><A HREF="mailto:schotten@gmx.de"
     	  >Claus&nbsp;Schotten</A></ADDRESS>
       </BODY>
     </HTML>

   The end tags </td> and </tr> are printed because HTML:Tagset says they
are mandatory.    map {$HTML::Tagset::optionalEndTag{$_}=1} qw(td tr th);
will fix that.

   The additional new line after </head> doesn't look nice. With
$hpp->set_nl_after(undef,'head') we will reset the parameter for the <head>
tag.

   $hpp->entities($hpp->entities().'ä'); will enforce the entity encoding
of 'ä'.

   $hpp->min_bool_attr(0); will inhibt the minimizyation of the NOSHADE
attribute to <hr>.

   Let's fiddle with the indention:   $hpp->set_indent(8,'@TEXTBLOCK');
$hpp->set_indent(0,'html');

   New lines inside text blocks (here inside <h1>, <p> and <address>) will
be indented by 8 characters instead of two, whereas the code directly
under <html> will not be indented.

     <HTML>
     <HEAD>
       <TITLE>Demonstrate HTML::PrettyPrinter</TITLE>
     </HEAD>

     <BODY>
       <H1>Headline</H1>
       <P ALIGN="JUSTIFY">Some text in <B>bold</B> and
     	   <I>italics</I> and with '&auml;' &amp; 'ü'.

       <TABLE ALIGN="LEFT" BORDER="0">
         <TR><TD ALIGN="RIGHT">top right
         <TR><TD ALIGN="LEFT">bottom left
       </TABLE>

       <HR NOSHADE="NOSHADE" SIZE="5">
       <ADDRESS><A HREF="mailto:schotten@gmx.de"
     	     >Claus&nbsp;Schotten</A></ADDRESS>
     </BODY>
     </HTML>

   $hpp->wrap_at_tagend(HTML::PrettyPrinter::NEVER); will disable the line
wrap between the attribute and the '>' of the <a> tag. The resulting line
excedes the target line length by far, but the is no point left, where the
pretty printer could legaly break this line.

   $hpp->set_endtag(1,'tr') will overwrite the default. Thus, the </tr>
appears in the code whereas the other optional endtags are still omitted.

   Finally, we customize some individual elements:

`$tree-'address('0.1.1')->attr('_hpp_skip',1)>
     will skip the <p> and its content from the output

`$tree-'address('0.1.2.1.0')->attr('_hpp_force_nl',1)>
     will force new lines arround the second <td>, but will not affect the
     first.  <td>.

     <HTML>
     <HEAD>
       <TITLE>Demonstrate HTML::PrettyPrinter</TITLE>
     </HEAD>

     <BODY>
       <H1>Headline</H1>

       <TABLE ALIGN="LEFT" BORDER="0">
         <TR><TD ALIGN="RIGHT">top right</TR>
         <TR>
           <TD ALIGN="LEFT">bottom left
         </TR>
       </TABLE>

       <HR NOSHADE="NOSHADE" SIZE="5">
       <ADDRESS><A
     	     HREF="mailto:schotten@gmx.de">Claus&nbsp;Schotten</A></ADDRESS>
     </BODY>
     </HTML>

KNOWN BUGS
==========

   * This is early alpha code. The interfaces are subject to changes.

   * The module is tested with perl 5.005_03 only. It should work with
     perl 5.004 though.

   * The predefined tag groups are incomplete. Several tags need to be
     added.

   * Attribute values from a fixed set given in the DTD (e.g.
     ALIGN=LEFT|RIGHT etc.) should be converted to upper or lower case
     depending on the value of the uppercase parameter. Currently, they
     are printed as given in the HTML tree.

   * No optimization for performance was done.

SEE ALSO
========

   See HTML/TreeBuilder, HTML/Element,
see HTML/Tagset,

COPYRIGHT
=========

   Copyright 2000 Claus Schotten  schotten@gmx.de

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Claus Schotten <schotten@gmx.de>

a simple and fast HTML syntax checking package for perl 4 and perl 5
********************************************************************

NAME
====

   HTMLQuickCheck.pm - a simple and fast HTML syntax checking package for
perl 4 and perl 5

SYNOPSIS          require 'HTMLQuickCheck.pm';
==============================================

     &HTML'QuickCheck'OK($html_text) || die "Bad HTML: $HTML'QuickCheck'Error";

     or for perl 5:
     HTML::QuickCheck::OK($html_text) ||
             die "Bad HTML: $HTML::QuickCheck::Error";

DESCRIPTION
===========

   The objective of the package is to provide a fast and essential HTML
check (esp. for CGI scripts where response time is important) to prevent a
piece of user input HTML code from messing up the rest of a file, i.e., to
minimize and localize any possible damage created by including a piece of
user input HTML text in a dynamic document.

   HTMLQuickCheck checks for unmatched < and >, unmatched tags and improper
nesting, which could ruin the rest of the document.  Attributes and
elements with optional end tags are not checked, as they should not cause
disasters with any decent browsers (they should ignore any unrecognized
tags and attributes according to the standard).  A piece of HTML that
passes HTMLQuickCheck may not necessarily be valid HTML, but it would be
very unlikely to screw others but itself. A valid piece of HTML that
doesn't pass the HTMLQuickCheck is however very likely to screw many
browsers(which are obviously broken in terms of strict conformance).

   HTMLQuickCheck currently supports HTML 1.0, 2.x (draft), 3.0 (draft) and
netscape extensions (1.1).

EXAMPLE
=======

     htmlchk, a simple html checker:

     #!/usr/local/bin/perl
     require 'HTMLQuickCheck.pm';
     undef $/;
     print &HTML'QuickCheck'OK(<>) ? "HTML OK\n" :
             "Bad HTML:\n", $HTML'QuickCheck'Error;
     __END__

     Usage:
     htmlchk [html_file]

AUTHOR
======

   Luke Y. Lu <ylu@mail.utexas.edu>

SEE ALSO
========

   HTML docs at <URL:http://www.w3.org/hypertext/WWW/MarkUp/MarkUp.html>;
HTML validation service at <URL:http://www.halsoft.com/html/>; perlSGML
package at <URL:http://www.oac.uci.edu/indiv/ehood/perlSGML.html>; weblint
at <URL:http://www.khoros.unm.edu/staff/neilb/weblint.html>

BUGS
====

   Please report them to the author.

module to mangle HREF links within HTML files
*********************************************

NAME
====

   HTML::RefMunger - module to mangle HREF links within HTML files

SYNOPSIS
========

     use HTML::RefMunger;
     refmunger( [options] );

DESCRIPTION
===========

ARGUMENTS
=========

   HTML::RefMunger takes the following arguments:

help
          --help

     Displays the usage message.

infile
          --infile=name

     Specify the pod file to convert.  Input is taken from STDIN if no
     infile is specified.

outdir
          --outdir=name

     Specify the output directory to stash the munged HTML files in.
     Defaults to "." ( the current working directory )

outfile
          --convention=[UNIX,MSDOS,MacOS]

     Specify the filename remapping convention to use. Current supported
     formats are UNIX ( 14-character, such as Xenix ), MSDOS ( 8.3 format
     ) and MacOS ( 32 character ).

verbose
          --verbose

     Display progress messages.

EXAMPLE
=======

     refmunger( "refmunger", "--infile=foo.html",
                "--convention=MacOS" );

AUTHOR
======

   Alligator Descartes <descarte@arcana.co.uk>

BUGS
====

LIMITATIONS
===========

   * Passing directories as the -infile current doesn't work. It should
     recursively translate everything in that directory downwards, but it
     doesn't.

   * There should be some sort of funky file renaming thing that happens to
     referenced links, I guess. At the moment, you also need to translate
     those links *via* `HTML::RefMunger' to generate the correct name.

SEE ALSO
========

   `refmunger' in this node

COPYRIGHT
=========

   This program is distributed under the Artistic License.

SYNOPSIS
========

     use HTML::SimpleLinkExtor;

     my $extor = HTML::SimpleLinkExtor->new();
     $extor->parse_file($filename);
     #--or--
     $extor->parse($html);

     #extract all of the links
     @all_links   = $extor->links;

     #extract the img links
     @img_srcs    = $extor->img;

     #extract the frame links
     @frame_srcs  = $extor->frame;

     #extract the hrefs
     @area_hrefs  = $extor->area;
     @a_hrefs     = $extor->a;
     @base_hrefs  = $extor->base;
     @hrefs       = $extor->href;

     #extract the body background link
     @body_bg     = $extor->body;
     @background  = $extor->background;

DESCRIPTION
===========

   This is a simple HTML link extractor designed for the person who does
not want to deal with the intricacies of HTML::Parser or the
de-referencing needed to get links out of HTML::LinkExtor.

   You can extract all the links or some of the links (based on the HTML
tag name or attribute name). If a <BASE HREF> tag is found, all of the
relative URLs will be resolved according to that reference.

   This module is simply a subclass around HTML::LinkExtor.

$extor = HTML::SimpleLinkExtor->new()
     Create the link extractor object.

$extor = HTML::SimpleLinkExtor->new($base)
     Create the link extractor object and resolve the relative URLs
     accoridng to the supplied base URL. The supplied base URL overrides
     any other base URL found in the HTML.

$extor = HTML::SimpleLinkExtor->new(")
     Create the link extractor object and do not resolve relative links.

$extor->parse_file( $filename )
     Parse the file for links.

$extor->parse( $data )
     Parse the HTML in $data.

$extor->links
     Return a list of the links.

$extor->img
     Return a list of the links from all the SRC attributes of the IMG.

$extor->frame
     Return a list of all the links from all the SRC attributes of the
     FRAME.

$extor->src
     Return a list of the links from all the SRC attributes of any tag.

$extor->a
     Return a list of the links from all the HREF attributes of the A tags.

$extor->area
     Return a list of the links from all the HREF attributes of the AREA
     tags.

$extor->base
     Return a list of the links from all the HREF attributes of the BASE
     tags.  There should only be one.

$extor->href
     Return a list of the links from all the HREF attributes of any tag.

$extor->body, $extor->background
     Return the link from the BODY tag's BACKGROUND attribute.

TO DO
=====

   This module doesn't handle all of the HTML tags that might have links.
If someone wants those, I'll add them.

AUTHOR
======

   brian d foy <comdog@panix.com>

a bare-bones HTML parser
************************

NAME
====

   HTML::SimpleParse - a bare-bones HTML parser

SYNOPSIS
========

     use HTML::SimpleParse;

     # Parse the text into a simple tree
     my $p = new HTML::SimpleParse( $html_text );
     $p->output;                 # Output the HTML verbatim

     $p->text( $new_text );      # Give it some new HTML to chew on
     $p->parse                   # Parse the new HTML
     $p->output;

     my %attrs = HTML::SimpleParse->parse_args('A="xx" B=3');
     # %attrs is now ('A' => 'xx', 'B' => '3')

DESCRIPTION
===========

   This module is a simple HTML parser.  It is similar in concept to
HTML::Parser, but it differs in a couple of important ways.

   First, HTML::Parser knows which tags can contain other tags, which
start tags have corresponding end tags, which tags can exist only in the
<HEAD> portion of the document, and so forth.  HTML::SimpleParse does not
know any of these things.  It just finds tags and text in the HTML you
give it, it does not care about the specific content of these tags (though
it does distiguish between different _types_ of tags, such as comments,
starting tags like <b>, ending tags like </b>, and so on).

   Second, HTML::SimpleParse does not create a hierarchical tree of HTML
content, but rather a simple linear list.  It does not pay any attention
to balancing start tags with corresponding end tags, or which pairs of
tags are inside other pairs of tags.

   Because of these characteristics, you can make a very effective HTML
filter by sub-classing HTML::SimpleParse.  For example, to remove all
comments from HTML:

     package NoComment;
     use HTML::SimpleParse;
     @ISA = qw(HTML::SimpleParse);
     sub output_comment {}

     package main;
     NoComment->new($some_html)->output;

Methods
-------

   * new
          $p = new HTML::SimpleParse( $some_html );

     Creates a new HTML::SimpleParse object.  Optionally takes one
     argument, a string containing some HTML with which to initialize the
     object.  If you give it a non-empty string, the HTML will be parsed
     into a tree and ready for outputting.

     Can also take a list of attributes, such as

          $p = new HTML::SimpleParse( $some_html, 'fix_case' => -1);

     See the `parse_args()' method below for an explanation of this
     attribute.

   * text
          $text = $p->text;
          $p->text( $new_text );

     Get or set the contents of the HTML to be parsed.

   * tree
          foreach ($p->tree) { ... }

     Returns a list of all the nodes in the tree, in case you want to step
     through them manually or something.  Each node in the tree is an
     anonymous hash with (at least) three data members, $node->{type} (is
     this a comment, a start tag, an end tag, etc.), $node->{content} (all
     the text between the angle brackets, verbatim), and $node->{offset}
     (number of bytes from the beginning of the string).

     The possible values of $node->{type} are text, `starttag', endtag,
     `ssi', and `markup'.

   * parse
          $p->parse;

     Once an object has been initialized with some text, call $p->parse and
     a tree will be created.  After the tree is created, you can call
     $p->output.  If you feed some text to the new() method, parse will be
     called automatically during your object's construction.

   * parse_args
          %hash = $p->parse_args( $arg_string );

     This routine is handy for parsing the contents of an HTML tag into
     key=value pairs.  For instance:

          $text = 'type=checkbox checked name=flavor value="chocolate or strawberry"';
          %hash = $p->parse_args( $text );
          # %hash is ( TYPE=>'checkbox', CHECKED=>undef, NAME=>'flavor',
          #            VALUE=>'chocolate or strawberry' )

     Note that the position of the last m//g search on the string (the
     value returned by Perl's pos() function) will be altered by the
     parse_args function, so make sure you take that into account if (in
     the above example) you do `$text =~ m/something/g'.

     The parse_args() method can be run as either an object method or as a
     class method, i.e. as either $p->parse_args(...) or
     HTML::SimpleParse->parse_args(...).

     HTML attribute lists are supposed to be case-insensitive with respect
     to attribute names.  To achieve this behavior, parse_args() respects
     the 'fix_case' flag, which can be set either as a package global
     $FIX_CASE, or as a class member datum 'fix_case'.  If set to 0, no
     case conversion is done.  If set to 1, all keys are converted to upper
     case.  If set to -1, all keys are converted to lower case.  The
     default is 1, i.e. all keys are uppercased.

     If an attribute takes no value (like "checked" in the above example)
     then it will still have an entry in the returned hash, but its value
     will be undef.  For example:

          %hash = $p->parse_args('type=checkbox checked name=banana value=""');
          # $hash{CHECKED} is undef, but $hash{VALUE} is ""

     This method actually returns a list (not a hash), so duplicate
     attributes and order will be preserved if you want them to be:

          @hash = $p->parse_args("name=family value=gwen value=mom value=pop");
          # @hash is qw(NAME family VALUE gwen VALUE mom VALUE pop)

   * output
          $p->output;

     This will output the contents of the HTML, passing the real work off
     to the output_text, output_comment, etc. functions.  If you do not
     override any of these methods, this module will output the exact text
     that it parsed into a tree in the first place.

   * get_output
          print $p->get_output

     Similar to $p->output(), but returns its result instead of printing
     it.

   * execute
          foreach ($p->tree) {
             print $p->execute($_);
          }

     Executes a single node in the HTML parse tree.  Useful if you want to
     loop through the nodes and output them individually.

   The following methods do the actual outputting of the various parts of
the HTML.  Override some of them if you want to change the way the HTML is
output.  For instance, to strip comments from the HTML, override the
output_comment method like so:

     # In subclass:
     sub output_comment { }  # Does nothing

   * output_text

   * output_comment

   * output_endtag

   * output_starttag

   * output_markup

   * output_ssi

CAVEATS
=======

   Please do not assume that the interface here is stable.  This is a
first pass, and I'm still trying to incorporate suggestions from the
community.  If you employ this module somewhere, make doubly sure before
upgrading that none of your code breaks when you use the newer version.

BUGS
====

   * Embedded >s are broken

     Won't handle tags with embedded >s in them, like <input name=expr
     value="x > y">.  This will be fixed in a future version, probably by
     using the parse_args method.  Suggestions are welcome.

TO DO
=====

   * extensibility

     Based on a suggestion from Randy Harmon (thanks), I'd like to make it
     easier for subclasses of SimpleParse to pick out other kinds of HTML
     blocks, i.e.  extend the set {text, comment, endtag, starttag,
     markup, ssi} to include more members.  Currently the only easy way to
     do that is by overriding the parse method:

          sub parse {  # In subclass
             my $self = $_[0];
             $self->SUPER::parse(@_);
             foreach ($self->tree) {
                if ($_->{content} =~ m#^a\s+#i) {
                   $_->{type} = 'anchor_start';
                }
             }
          }

          sub output_anchor_start {
             # Whatever you want...
          }

     Alternatively, this feature might be implemented by hanging
     attatchments onto the parsing loop, like this:

          my $parser = new SimpleParse( $html_text );
          $regex = '<(a\s+.*?)>';
          $parser->watch_for( 'anchor_start', $regex );

          sub SimpleParse::output_anchor_start {
             # Whatever you want...
          }

     I think I like that idea better.  If you wanted to, you could make a
     subclass with output_anchor_start as one of its methods, and put the
     ->watch_for stuff in the constructor.

   * reading from filehandles

     It would be nice if you could initialize an object by giving it a
     filehandle or filename instead of the text itself.

   * tests

     I need to write a few tests that run under "make test".

AUTHOR
======

   Ken Williams <ken@forum.swarthmore.edu>

COPYRIGHT
=========

   Copyright 1998 Swarthmore College.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

HTML form generation for CGI or mod_perl
****************************************

NAME
====

   HTML::StickyForms - HTML form generation for CGI or mod_perl

SYNOPSIS
========

     # mod_perl example

     use HTML::StickyForms;
     use Apache::Request;

     sub handler{
       my($r)=@_;
       $r=Apache::Request->new($r);
       my $f=HTML::StickyForms->new($r);

     $r->send_http_header;
     print
       "<HTML><BODY><FORM>",
       "Text field:",
       $f->text(name => 'field1', size => 40, value => 'default value'),
       "<BR>Text area:",
       $r->textarea(name => 'field2', cols => 60, rows => 5, value => 'stuff'),
       "<BR>Radio buttons:",
       $r->radio_group(name => 'field3', values => [1,2,3],
         labels => { 1=>'one', 2=>'two', 3=>'three' }, default => 2),
       "<BR>Single checkbox:",
       $r->checkbox(name => 'field4', value => 'xyz', checked => 1),
       "<BR>Checkbox group:",
       $r->checkbox_group(name => 'field5', values => [4,5,6],
         labels => { 4=>'four', 5=>'five', 6=>'six' }, defaults => [5,6]),
       "<BR>Password field:",
       $r->password(name => 'field6', size => 20),
       '<BR><INPUT type="submit" value=" Hit me! ">',
       '</FORM></BODY></HTML>',
      ;
      return OK;
       }

DESCRIPTION
===========

   This module provides a simple interface for generating HTML <FORM>
fields, with default values chosen from the previous form submission. This
module was written with mod_perl in mind, but works equally well with
CGI.pm, including the new 3.x version.

   The module does not provide methods for generating all possible form
fields, only those which benefit from having default values overridden by
the previous form submission. This means that, unlike CGI.pm, there are no
routines for generating <FORM> tags, hidden fields or submit fields. Also
this module's interface is much less flexible than CGI.pm's. This was done
mainly to keep the size and complexity down.

METHODS
-------

HTML::StickyForms->new($req)
     Creates a new form generation object. The single argument can be an
     Apache::Request object, a CGI object (v2.x), a CGI::State object
     (v3.x), or an object of a subclass of any of the above. As a special
     case, if the argument is undef or ", the object created will behave
     as if a request object with no submitted fields was given.

$f->trim_params()
     Removes leading and trailing whitespace from all submitted values.

$f->text(%args)
     Generates an <INPUT> tag, with a type of "text". All arguments are
     used directly to generate attributes for the tag, with the following
     exceptions:

    type
          Defaults to "text"

    name
          The value passed will have all HTML-special characters escaped.

    default
          Specifies the default value of the field if no fields were
          submitted in the request object passed to new(). The value used
          will have all HTML-special characters escaped.

$f->password(%args)
     As text(), but generates a `"password"' type field.

$f->textarea(%args)
     Generates a <TEXTAREA> container. All arguments are used directly to
     generate attributes for the start tag, except for:

    name
          This value will be HTML-escaped.

    default
          Specifies the default contents of the container if no fields
          were submitted.  The value used will be HTML-escaped.

$f->checkbox(%args)
     Generates a single `"checkbox"' type <INPUT> tag. All arguments are
     used directly to generate attributes for the tag, except for:

    name, value
          The values passed will be HTML-escaped.

    checked
          Specifies the default state of the field if no fields were
          submitted.

$f->checkbox_group(%args)
     Generates a group of `"checkbox"' type <INPUT> tags. If called in
     list context, returns a list of tags, otherwise a single string
     containing all tags. All arguments are used directly to generate
     attributes in each tag, except for the following:

    type
          Defaults to `"checkbox"'.

    name
          This value will be HTML-escaped.

    values or value
          An arrayref of values. One tag will be generated for each
          element. The values will be HTML-escaped. Defaults to label keys.

    labels or label
          A hashref of labels. Each tag generated will be followed by the
          label keyed by the value. If no label is present for a given
          value, no label will be generated. Defaults to an empty hashref.

    escape
          If this value is true, the labels will be HTML-escaped.

    defaults or default
          A single value or arrayref of values to be checked if no fields
          were submitted.  Defaults to an empty arrayref.

    linebreak
          If true, each tag/label will be followed by a <BR> tag.

$f->radio_group(%args)
     As `checkbox_group()', but generates `"radio"' type tags.

$f->select(%args)
     Generates a <SELECT> tags. All arguments are used directly to generate
     attributes in the <SELECT> tag, except for the following:

    name
          This value will be HTML-escaped.

    values or value
          An arrayref of values. One <OPTION> tag will be created inside
          the <SELECT> tag for each element. The values will be
          HTML-escaped.  Defaults to label keys.

    labels or label
          A hashref of labels. Each <OPTION> tag generated will contain the
          label keyed by its value. If no label is present for a given
          value, no label will be generated. Defaults to an empty hashref.

    defaults or default
          A single value or arrayref of values to be selected if no fields
          were submitted. Defaults to an empty arrayref.

    multiple
          If a true value is passed, the MULTIPLE attribute is set.

AUTHOR
======

   Peter Haworth <pmh@edison.ioppublishing.com>

HTML output stream class, and some markup utilities
***************************************************

NAME
====

   HTML::Stream - HTML output stream class, and some markup utilities

SYNOPSIS
========

   Here's small sample of some of the non-OO ways you can use this module:

     use HTML::Stream qw(:funcs);

     print html_tag('A', HREF=>$link);
     print html_escape("<<Hello & welcome!>>");

   And some of the OO ways as well:

     use HTML::Stream;
     $HTML = new HTML::Stream \*STDOUT;

     # The vanilla interface...
     $HTML->tag('A', HREF=>"$href");
     $HTML->tag('IMG', SRC=>"logo.gif", ALT=>"LOGO");
     $HTML->text($copyright);
     $HTML->tag('_A');

     # The chocolate interface...
     $HTML -> A(HREF=>"$href");
     $HTML -> IMG(SRC=>"logo.gif", ALT=>"LOGO");
     $HTML -> t($caption);
     $HTML -> _A;

     # The chocolate interface, with whipped cream...
     $HTML -> A(HREF=>"$href")
           -> IMG(SRC=>"logo.gif", ALT=>"LOGO")
           -> t($caption)
           -> _A;

     # The strawberry interface...
     output $HTML [A, HREF=>"$href"],
                  [IMG, SRC=>"logo.gif", ALT=>"LOGO"],
                  $caption,
                  [_A];

DESCRIPTION
===========

   The *HTML::Stream* module provides you with an object-oriented (and
subclassable) way of outputting HTML.  Basically, you open up an "HTML
stream" on an existing filehandle, and then do all of your output to the
HTML stream.  You can intermix HTML-stream-output and
ordinary-print-output, if you like.

   There's even a small built-in subclass, HTML::Stream::Latin1, which can
handle Latin-1 input right out of the box.   But all in good time...

INTRODUCTION (the Neapolitan dessert special)
=============================================

Function interface
------------------

   Let's start out with the simple stuff.  This module provides a
collection of non-OO utility functions for escaping HTML text and
producing HTML tags, like this:

     use HTML::Stream qw(:funcs);        # imports functions from @EXPORT_OK

     print html_tag(A, HREF=>$url);
     print '&copy; 1996 by', html_escape($myname), '!';
     print html_tag('/A');

   By the way: that last line could be rewritten as:

     print html_tag(_A);

   And if you need to get a parameter in your tag that doesn't have an
associated value, supply the *undefined* value (not the empty string!):

     print html_tag(TD, NOWRAP=>undef, ALIGN=>'LEFT');

          <TD NOWRAP ALIGN=LEFT>

     print html_tag(IMG, SRC=>'logo.gif', ALT=>'');

          <IMG SRC="logo.gif" ALT="">

   There are also some routines for reversing the process, like:

     $text = "This <i>isn't</i> &quot;fun&quot;...";
     print html_unmarkup($text);

          This isn't &quot;fun&quot;...

     print html_unescape($text);

          This isn't "fun"...

   *Yeah, yeah, yeah*, I hear you cry.  *We've seen this stuff before.*
But wait!  There's more...

OO interface, vanilla
---------------------

   Using the function interface can be tedious... so we also provide an
*"HTML output stream"* class.  Messages to an instance of that class
generally tell that stream to output some HTML.  Here's the above example,
rewritten using HTML streams:

     use HTML::Stream;
     $HTML = new HTML::Stream \*STDOUT;

     $HTML->tag(A, HREF=>$url);
     $HTML->ent('copy');
     $HTML->text(" 1996 by $myname!");
     $HTML->tag(_A);

   As you've probably guessed:

     text()   Outputs some text, which will be HTML-escaped.

     tag()    Outputs an ordinary tag, like <A>, possibly with parameters.
              The parameters will all be HTML-escaped automatically.

     ent()    Outputs an HTML entity, like the &copy; or &lt; .
              You mostly don't need to use it; you can often just put the
              Latin-1 representation of the character in the text().

   You might prefer to use `t()' and `e()' instead of text() and `ent()':
they're absolutely identical, and easier to type:

     $HTML -> tag(A, HREF=>$url);
     $HTML -> e('copy');
     $HTML -> t(" 1996 by $myname!");
     $HTML -> tag(_A);

   Now, it wouldn't be nice to give you those text() and `ent()' shortcuts
without giving you one for tag(), would it?  Of course not...

OO interface, chocolate
-----------------------

   The known HTML tags are even given their own *tag-methods,* compiled on
demand.  The above code could be written even more compactly as:

     $HTML -> A(HREF=>$url);
     $HTML -> e('copy');
     $HTML -> t(" 1996 by $myname!");
     $HTML -> _A;

   As you've probably guessed:

     A(HREF=>$url)   ==   tag(A, HREF=>$url)   ==   <A HREF="/the/url">
     _A              ==   tag(_A)              ==   </A>

   All of the autoloaded "tag-methods" use the tagname in *all-uppercase*.
A `"_"' prefix on any tag-method means that an end-tag is desired.  The
`"_"' was chosen for several reasons: (1) it's short and easy to type, (2)
it doesn't produce much visual clutter to look at, (3) `_TAG' looks a
little like `/TAG' because of the straight line.

   * *I know, I know... it looks like a private method.  You get used to
     it.  Really.*

   I should stress that this module will only auto-create tag methods for
*known* HTML tags.  So you're protected from typos like this (which will
cause a fatal exception at run-time):

     $HTML -> IMGG(SRC=>$src);

   (You're not yet protected from illegal tag parameters, but it's a start,
ain't it?)

   If you need to make a tag known (sorry, but this is currently a global
operation, and not stream-specific), do this:

     accept_tag HTML::Stream 'MARQUEE';       # for you MSIE fans...

   *Note: there is no corresponding "reject_tag".*  I thought and thought
about it, and could not convince myself that such a method would do
anything more useful than cause other people's modules to suddenly stop
working because some bozo function decided to reject the `FONT' tag.

OO interface, with whipped cream
--------------------------------

   In the grand tradition of C++, output method chaining is supported in
both the Vanilla Interface and the Chocolate Interface.  So you can (and
probably should) write the above code as:

     $HTML -> A(HREF=>$url)
           -> e('copy') -> t(" 1996 by $myname!")
           -> _A;

   *But wait!  Neapolitan ice cream has one more flavor...*

OO interface, strawberry
------------------------

   I was jealous of the compact syntax of HTML::AsSubs, but I didn't want
to worry about clogging the namespace with a lot of functions like p(),
a(), etc. (especially when markup-functions like tr() conflict with
existing Perl functions).  So I came up with this:

     output $HTML [A, HREF=>$url], "Here's my $caption", [_A];

   Conceptually, arrayrefs are sent to `html_tag()', and strings to
`html_escape()'.

ADVANCED TOPICS
===============

Auto-formatting and inserting newlines
--------------------------------------

   *Auto-formatting* is the name I give to the Chocolate Interface feature
whereby newlines (and maybe, in the future, other things) are inserted
before or after the tags you output in order to make your HTML more
readable.  So, by default, this:

     $HTML -> HTML
           -> HEAD
           -> TITLE -> t("Hello!") -> _TITLE
           -> _HEAD
           -> BODY(BGCOLOR=>'#808080');

   Actually produces this:

     <HTML><HTML>
     <HEAD>
     <TITLE>Hello!</TITLE>
     </HEAD>
     <BODY BGCOLOR="#808080">

   *To turn off autoformatting altogether* on a given HTML::Stream object,
use the `auto_format()' method:

     $HTML->auto_format(0);        # stop autoformatting!

   *To change whether a newline is automatically output* before/after the
begin/end form of a tag at a global level, use `set_tag()':

     HTML::Stream->set_tag('B', Newlines=>15);   # 15 means "\n<B>\n \n</B>\n"
     HTML::Stream->set_tag('I', Newlines=>7);    # 7 means  "\n<I>\n \n</I>  "

   *To change whether a newline is automatically output* before/after the
begin/end form of a tag *for a given stream* level, give the stream its
own private "tag info" table, and then use `set_tag()':

     $HTML->private_tags;
     $HTML->set_tag('B', Newlines=>0);     # won't affect anyone else!

   *To output newlines explicitly*, just use the special nl method in the
Chocolate Interface:

     $HTML->nl;     # one newline
     $HTML->nl(6);  # six newlines

   I am sometimes asked, "why don't you put more newlines in
automatically?"  Well, mostly because...

   * Sometimes you'll be outputting stuff inside a `PRE' environment.

   * Sometimes you really do want to jam things (like images, or table
     cell delimiters and the things they contain) right up against each
     other.

   So I've stuck to outputting newlines in places where it's most likely
to be harmless.

Entities
--------

   As shown above, You can use the `ent()' (or `e()') method to output an
entity:

     $HTML->t('Copyright ')->e('copy')->t(' 1996 by Me!');

   But this can be a pain, particularly for generating output with
non-ASCII characters:

     $HTML -> t('Copyright ')
           -> e('copy')
           -> t(' 1996 by Fran') -> e('ccedil') -> t('ois, Inc.!');

   Granted, Europeans can always type the 8-bit characters directly in
their Perl code, and just have this:

     $HTML -> t("Copyright \251 1996 by Fran\347ois, Inc.!');

   But folks without 8-bit text editors can find this kind of output
cumbersome to generate.  Sooooooooo...

Auto-escaping: changing the way text is escaped
-----------------------------------------------

   *Auto-escaping* is the name I give to the act of taking an "unsafe"
string (one with ">", "&", etc.), and magically outputting "safe" HTML.

   The default "auto-escape" behavior of an HTML stream can be a drag if
you've got a lot character entities that you want to output, or if you're
using the Latin-1 character set, or some other input encoding.
Fortunately, you can use the `auto_escape()' method to change the way a
particular HTML::Stream works at any time.

   First, here's a couple of special invocations:

     $HTML->auto_escape('ALL');      # Default; escapes [<>"&] and 8-bit chars.
     $HTML->auto_escape('LATIN_1');  # Like ALL, but uses Latin-1 entities
                                     #   instead of decimal equivalents.
     $HTML->auto_escape('NON_ENT');  # Like ALL, but leaves "&" alone.

   You can also install your own auto-escape function (note that you might
very well want to install it for just a little bit only, and then
de-install it):

     sub my_auto_escape {
         my $text = shift;
     	HTML::Entities::encode($text);     # start with default
         $text =~ s/\(c\)/&copy;/ig;        # (C) becomes copyright
         $text =~ s/\\,(c)/\&$1cedil;/ig;   # \,c becomes a cedilla
      	$text;
     }

     # Start using my auto-escape:
     my $old_esc = $HTML->auto_escape(\&my_auto_escape);

     # Output some stuff:
     $HTML-> IMG(SRC=>'logo.gif', ALT=>'Fran\,cois, Inc');
     output $HTML 'Copyright (C) 1996 by Fran\,cois, Inc.!';

     # Stop using my auto-escape:
     $HTML->auto_escape($old_esc);

   If you find yourself in a situation where you're doing this a lot, a
better way is to create a *subclass* of HTML::Stream which installs your
custom function when constructed.  For an example, see the
HTML::Stream::Latin1 subclass in this module.

Outputting HTML to things besides filehandles
---------------------------------------------

   As of Revision 1.21, you no longer need to supply new() with a
filehandle: *any object that responds to a print() method will do*.  Of
course, this includes blessed FileHandles, and IO::Handles.

   If you supply a GLOB reference (like `\*STDOUT') or a string (like
`"Module::FH"'), HTML::Stream will automatically create an invisible
object for talking to that filehandle (I don't dare bless it into a
FileHandle, since the underlying descriptor would get closed when the
HTML::Stream is destroyed, and you might not want that).

   You say you want to print to a string?  For kicks and giggles, try this:

     package StringHandle;
     sub new {
     	my $self = '';
     	bless \$self, shift;
     }
     sub print {
         my $self = shift;
         $$self .= join('', @_);
     }

     package main;
     use HTML::Stream;

     my $SH = new StringHandle;
     my $HTML = new HTML::Stream $SH;
     $HTML -> H1 -> t("Hello & <<welcome>>!") -> _H1;
     print "PRINTED STRING: ", $$SH, "\n";

Subclassing
-----------

   This is where you can make your application-specific HTML-generating
code *much* easier to look at.  Consider this:

     package MY::HTML;
     @ISA = qw(HTML::Stream);

     sub Aside {
     	$_[0] -> FONT(SIZE=>-1) -> I;
     }
     sub _Aside {
     	$_[0] -> _I -> _FONT;
     }

   Now, you can do this:

     my $HTML = new MY::HTML \*STDOUT;

     $HTML -> Aside
           -> t("Don't drink the milk, it's spoiled... pass it on...")
           -> _Aside;

   If you're defining these markup-like, chocolate-interface-style
functions, I recommend using mixed case with a leading capital.  You
probably shouldn't use all-uppercase, since that's what this module uses
for real HTML tags.

PUBLIC INTERFACE
================

Functions
---------

html_escape TEXT
     Given a TEXT string, turn the text into valid HTML by escaping
     "unsafe" characters.  Currently, the "unsafe" characters are 8-bit
     characters plus:

          <  >  =  &

     Note: provided for convenience and backwards-compatibility only.  You
     may want to use the more-powerful *HTML::Entities::encode* function
     instead.

html_tag TAG [, PARAM=>VALUE, ...]
     Return the text for a given TAG, possibly with parameters.  As an
     efficiency hack, only the values are HTML-escaped currently: it is
     assumed that the tag and parameters will already be safe.

     For convenience and readability, you can say `_A' instead of `"/A"'
     for the first tag, if you're into barewords.

html_unescape TEXT
     Remove angle-tag markup, and convert the standard ampersand-escapes
     (lt, gt, `amp', quot, and `#ddd') into ASCII characters.

     Note: provided for convenience and backwards-compatibility only.  You
     may want to use the more-powerful *HTML::Entities::decode* function
     instead: unlike this function, it can collapse entities like copy and
     `ccedil' into their Latin-1 byte values.

html_unmarkup TEXT
     Remove angle-tag markup from TEXT, but do not convert
     ampersand-escapes.  Cheesy, but theoretically useful if you want to,
     say, incorporate externally-provided HTML into a page you're
     generating, and are worried that the HTML might contain undesirable
     markup.

Vanilla
-------

new [PRINTABLE]
     *Class method.* Create a new HTML output stream.

     The PRINTABLE may be a FileHandle, a glob reference, or any object
     that responds to a print() message.  If no PRINTABLE is given, does a
     select() and uses that.

auto_escape [NAME|SUBREF]
     *Instance method.* Set the auto-escape function for this HTML stream.

     If the argument is a subroutine reference SUBREF, then that subroutine
     will be used.  Declare such subroutines like this:

          sub my_escape {
          	my $text = shift;     # it's passed in the first argument
              ...
              $text;
          }

     If a textual NAME is given, then one of the appropriate built-in
     functions is used.  Possible values are:

    ALL
          Default for HTML::Stream objects.  This escapes angle brackets,
          ampersands, double-quotes, and 8-bit characters.  8-bit
          characters are escaped using decimal entity codes (like `#123').

    LATIN_1
          Like `"ALL"', but uses Latin-1 entity names (like `ccedil')
          instead of decimal entity codes to escape characters.  This
          makes the HTML more readable but it is currently not advised, as
          "older" browsers (like Netscape 2.0) do not recognize many of
          the ISO-8859-1 entity names (like `deg').

          Warning: If you specify this option, you'll find that it attempts
          to "require" *HTML::Entities* at run time.  That's because I
          didn't want to force you to have that module just to use the
          rest of HTML::Stream.  To pick up problems at compile time, you
          are advised to say:

               use HTML::Stream;
               use HTML::Entities;

          in your source code.

    NON_ENT
          Like `"ALL"', except that ampersands (&) are not escaped.  This
          allows you to use &-entities in your text strings, while having
          everything else safely escaped:

               output $HTML "If A is an acute angle, then A > 90&deg;";

     Returns the previously-installed function, in the manner of select().
     No arguments just returns the currently-installed function.

auto_format ONOFF
     *Instance method.* Set the auto-formatting characteristics for this
     HTML stream.  Currently, all you can do is supply a single defined
     boolean argument, which turns auto-formatting ON (1) or OFF (0).  The
     self object is returned.

     Please use no other values; they are reserved for future use.

comment COMMENT
     *Instance method.* Output an HTML comment.  As of 1.29, a newline is
     automatically appended.

ent ENTITY
     *Instance method.* Output an HTML entity.  For example, here's how
     you'd output a non-breaking space:

          $html->ent('nbsp');

     You may abbreviate this method name as e:

          $html->e('nbsp');

     Warning: this function assumes that the entity argument is legal.

io
     Return the underlying output handle for this HTML stream.  All you
     can depend upon is that it is some kind of object which responds to a
     print() message:

          $HTML->io->print("This is not auto-escaped or nuthin!");

nl [COUNT]
     *Instance method.* Output COUNT newlines.  If undefined, COUNT
     defaults to 1.

tag TAGNAME [, PARAM=>VALUE, ...]
     *Instance method.* Output a tag.  Returns the self object, to allow
     method chaining.  You can say `_A' instead of `"/A"', if you're into
     barewords.

text TEXT...
     *Instance method.* Output some text.  You may abbreviate this method
     name as t:

          $html->t('Hi there, ', $yournamehere, '!');

     Returns the self object, to allow method chaining.

text_nbsp TEXT...
     *Instance method.* Output some text, but with all spaces output as
     non-breaking-space characters:

          $html->t("To list your home directory, type: ")
               ->text_nbsp("ls -l ~yourname.")

     Returns the self object, to allow method chaining.

Strawberry
----------

output ITEM,...,ITEM
     *Instance method.* Go through the items.  If an item is an arrayref,
     treat it like the array argument to html_tag() and output the result.
     If an item is a text string, escape the text and output the result.
     Like this:

          output $HTML [A, HREF=>$url], "Here's my $caption!", [_A];

Chocolate
---------

accept_tag TAG
     *Class method.* Declares that the tag is to be accepted as valid HTML
     (if it isn't already).  For example, this...

          # Make sure methods MARQUEE and _MARQUEE are compiled on demand:
          HTML::Stream->accept_tag('MARQUEE');

     ...gives the Chocolate Interface permission to create (via AUTOLOAD)
     definitions for the MARQUEE and _MARQUEE methods, so you can then say:

          $HTML -> MARQUEE -> t("Hi!") -> _MARQUEE;

     If you want to set the default attribute of the tag as well, you can
     do so via the set_tag() method instead; it will effectively do an
     accept_tag() as well.

          # Make sure methods MARQUEE and _MARQUEE are compiled on demand,
          #   *and*, set the characteristics of that tag.
          HTML::Stream->set_tag('MARQUEE', Newlines=>9);

private_tags
     *Instance method.* Normally, HTML streams use a reference to a global
     table of tag information to determine how to do such things as
     auto-formatting, and modifications made to that table by set_tag will
     affect everyone.

     However, if you want an HTML stream to have a private copy of that
     table to munge with, just send it this message after creating it.
     Like this:

          my $HTML = new HTML::Stream \*STDOUT;
          $HTML->private_tags;

     Then, you can say stuff like:

          $HTML->set_tag('PRE',   Newlines=>0);
          $HTML->set_tag('BLINK', Newlines=>9);

     And it won't affect anyone else's *auto-formatting* (although they
     will possibly be able to use the BLINK tag method without a fatal
     exception `:-(' ).

     Returns the self object.

set_tag TAG, [TAGINFO...]
     *Class/instance method.* Accept the given TAG in the Chocolate
     Interface, and (if TAGINFO is given) alter its characteristics when
     being output.

        * *If invoked as a class method,* this alters the "master tag
          table", and allows a new tag to be supported via an autoloaded
          method:

               HTML::Stream->set_tag('MARQUEE', Newlines=>9);

          Once you do this, all HTML streams you open from then on will
          allow that tag to be output in the chocolate interface.

        * *If invoked as an instance method,* this alters the "tag table"
          referenced by that HTML stream, usually for the purpose of
          affecting things like the auto-formatting on that HTML stream.

          Warning: by default, an HTML stream just references the "master
          tag table" (this makes new() more efficient), so *by default, the
          instance method will behave exactly like the class method.*

               my $HTML = new HTML::Stream \*STDOUT;
               $HTML->set_tag('BLINK', Newlines=>0);  # changes it for others!

          If you want to diddle with one stream's auto-formatting *only,*
          you'll need to give that stream its own private tag table.  Like
          this:

               my $HTML = new HTML::Stream \*STDOUT;
               $HTML->private_tags;
               $HTML->set_tag('BLINK', Newlines=>0);  # doesn't affect other streams

          Note: this will still force an default entry for BLINK in the
          master tag table: otherwise, we'd never know that it was legal
          to AUTOLOAD a BLINK method.   However, it will only alter the
          *characteristics* of the BLINK tag (like auto-formatting) in the
          *object's* tag table.

     The TAGINFO, if given, is a set of key=>value pairs with the following
     possible keys:

    Newlines
          Assumed to be a number which encodes how newlines are to be
          output before/after a tag.   The value is the logical OR (or
          sum) of a set of flags:

               0x01    newline before <TAG>         .<TAG>.     .</TAG>.
               0x02    newline after <TAG>          |     |     |      |
               0x04    newline before </TAG>        1     2     4      8
               0x08    newline after </TAG>

          Hence, to output BLINK environments which are preceded/followed
          by newlines:

               set_tag HTML::Stream 'BLINK', Newlines=>9;

     Returns the self object on success.

tags
     *Class/instance method.* Returns an unsorted list of all tags in the
     class/instance tag table (see set_tag for class/instance method
     differences).

SUBCLASSES
==========

HTML::Stream::Latin1
--------------------

   A small, public package for outputting Latin-1 markup.  Its default
auto-escape function is LATIN_1, which tries to output the mnemonic entity
markup (e.g., `&ccedil;') for ISO-8859-1 characters.

   So using HTML::Stream::Latin1 like this:

     use HTML::Stream;

     $HTML = new HTML::Stream::Latin1 \*STDOUT;
     output $HTML "\253A right angle is 90\260, \277No?\273\n";

   Prints this:

     &laquo;A right angle is 90&deg;, &iquest;No?&raquo;

   Instead of what HTML::Stream would print, which is this:

     &#171;A right angle is 90&#176;, &#191;No?&#187;

   Warning: a lot of Latin-1 HTML markup is not recognized by older
browsers (e.g., Netscape 2.0).  Consider using HTML::Stream; it will output
the decimal entities which currently seem to be more "portable".

   Note: using this class "requires" that you have HTML::Entities.

PERFORMANCE
===========

   Slower than I'd like.  Both the output() method and the various "tag"
methods seem to run about 5 times slower than the old
just-hardcode-the-darn stuff approach.  That is, in general, this:

     ### Approach #1...
     tag  $HTML 'A', HREF=>"$href";
     tag  $HTML 'IMG', SRC=>"logo.gif", ALT=>"LOGO";
     text $HTML $caption;
     tag  $HTML '_A';
     text $HTML $a_lot_of_text;

   And this:

     ### Approach #2...
     output $HTML [A, HREF=>"$href"],
     	         [IMG, SRC=>"logo.gif", ALT=>"LOGO"],
     		 $caption,
     		 [_A];
     output $HTML $a_lot_of_text;

   And this:

     ### Approach #3...
     $HTML -> A(HREF=>"$href")
     	  -> IMG(SRC=>"logo.gif", ALT=>"LOGO")
     	  -> t($caption)
     	  -> _A
           -> t($a_lot_of_text);

   Each run about 5x slower than this:

     ### Approach #4...
     print '<A HREF="', html_escape($href), '>',
           '<IMG SRC="logo.gif" ALT="LOGO">',
       	  html_escape($caption),
           '</A>';
     print html_escape($a_lot_of_text);

   Of course, I'd much rather use any of first three *(especially #3)* if
I had to get something done right in a hurry.  Or did you not notice the
typo in approach #4?  `;-)'

   (BTW, thanks to Benchmark:: for allowing me to... er... benchmark
stuff.)

VERSION
=======

   $Id: Stream.pm,v 1.49 2000/08/16 05:15:43 eryq Exp $

CHANGE LOG
==========

Version 1.47   (2000/06/10)
     No real changes to code; just improved documentation.

Version 1.45   (1999/02/09)
     Cleanup for Perl 5.005: removed duplicate typeglob assignments.

Version 1.44   (1998/01/14)
     Win95 install (5.004) now works.  Added SYNOPSIS to POD.

Version 1.41   (1998/01/02)
     Removed $& for efficiency.  *Thanks, Andreas!*

     Added support for OPTION, and default now puts newlines after SELECT
     and /SELECT.  Also altered "TELEM" syntax to put newline after
     end-tags of list element tags (like /OPTION, /LI, etc.).  In theory,
     this change could produce undesireable results for folks who embed
     lists inside of PRE environments... however, that kind of stuff was
     done in the days before TABLEs; also, you can always turn it off if
     you really need to.  *Thanks to John D Groenveld for these patches.*

     Added text_nbsp().  *Thanks to John D Groenveld for the patch.* This
     method may also be invoked as nbsp_text() as in the original patch,
     but that's sort of a private tip-of-the-hat to the patch author, and
     the synonym may go away in the future.

Version 1.37   (1997/02/09)
     No real change; just trying to make CPAN.pm happier.

Version 1.32   (1997/01/12)
     *NEW TOOL for generating Perl code which uses HTML::Stream!* Check
     your toolkit for *html2perlstream*.

     Added built-in support for escaping 8-bit characters.

     Added LATIN_1 auto-escape, which uses HTML::Entities to generate
     mnemonic entities.  This is now the default method for
     HTML::Stream::Latin1.

     Added `auto_format(),' so you can now turn auto-formatting off/on.

     Added `private_tags()', so it is now possible for HTML streams to
     each have their own "private" copy of the %Tags table, for use by
     `set_tag()'.

     Added `set_tag()'.  The tags tables may now be modified dynamically so
     as to change how formatting is done on-the-fly.  This will hopefully
     not compromise the efficiency of the chocolate interface (until now,
     the formatting was compiled into the method itself), and *will* add
     greater flexibility for more-complex programs.

     Added POD documentation for all subroutines in the public interface.

Version 1.29   (1996/12/10)
     Added terminating newline to comment().  *Thanks to John D Groenveld
     for the suggestion and the patch.*

Version 1.27   (1996/12/10)
     Added built-in HTML::Stream::Latin1, which does a very simple encoding
     of all characters above ASCII 127.

     Fixed bug in accept_tag(), where 'my' variable was shadowing argument.
     *Thanks to John D Groenveld for the bug report and the patch.*

Version 1.26   (1996/09/27)
     Start of history.

ACKNOWLEDGEMENTS
================

   Warmest thanks to...

     John Buckman           For suggesting that I write an "html2perlstream",
                            and inspiring me to look at supporting Latin-1.
     Tony Cebzanov          For suggesting that I write an "html2perlstream"
     John D Groenveld       Bug reports, patches, and suggestions
     B. K. Oxley (binkley)  For suggesting the support of "writing to strings"
                            which became the "printable" interface.

AUTHOR
======

   Eryq, `eryq@zeegee.com'.  President, Zero G Inc.
(`http://www.zeegee.com').

   Enjoy.

Perform text substitutions on an HTML template
**********************************************

NAME
====

   HTML::Subtext - Perform text substitutions on an HTML template

SYNOPSIS
========

     use HTML::Subtext;
     %context = ( ... ); # Hash of names to substitution text
     $p = HTML::Subtext->new('CONTEXT' => \%context);
     $p->parse_file("template.html");

DESCRIPTION
===========

   `HTML::Subtext' is a package for performing text substitutions on a
specially formatted HTML template. The template uses normal HTML markup,
but includes links of the form:

     <a href="subtext:foo/bar">This text will be replaced</a>

   The URI in this link tells `HTML::Subtext' to check in the provided
hash `'CONTEXT'' for a key named `'foo/bar''. If this lookup succeeds in
producing a string value, the text in the body of the link is replaced by
that value.

EXAMPLES
========

   This example performs substitutions into a template embedded into the
Perl code as a *here-document*.

     use HTML::Subtext;

     %context = (
       'author/name' => 'Kaelin Colclasure',
       'author/email' => '<a href="mailto:kaelin@acm.org">kaelin@acm.org</a>'
     );

     $p = HTML::Subtext->new('CONTEXT' => \%context);
     $p->parse(<<EOT);
     <html><head><title>example</title></head><body>
     <a href=\"subtext:author/name\">Author's name here</a>
     <a href=\"subtext:author/email\">mailto: link here</a>
     </body></html>
     EOT

   When run, the example produces the following output:

     <html><head><title>example</title></head><body>
     Kaelin Colclasure
     <a href="mailto:kaelin@acm.org">kaelin@acm.org</a>
     </body></html>

SEE ALSO
========

   See HTML/Filter, HTML/Parser,

COPYRIGHT
=========

   Copyright 1999 Kaelin Colclasure.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

module for generating a summary from a web page.
************************************************

NAME
====

   HTML::Summary - module for generating a summary from a web page.

SYNOPSIS
========

     use HTML::Summary;
     use HTML::TreeBuilder;

     my $tree = new HTML::TreeBuilder;
     $tree->parse( $document );

     my $summarizer = new HTML::Summary(
         LENGTH      => 200,
         USE_META    => 1,
     );

     $summary = $summarizer->generate( $tree );
     $summarizer->option( 'USE_META' => 1 );
     $length = $summarizer->option( 'LENGTH' );
     if ( $summarizer->meta_used( ) )
     {
         do something
     }

DESCRIPTION
===========

   The `HTML::Summary' module produces summaries from the textual content
of web pages. It does so using the location heuristic, which determines
the value of a given sentence based on its position and status within the
document; for example, headings, section titles and opening paragraph
sentences may be favoured over other textual content. A LENGTH option can
be used to restrict the length of the summary produced.

CONSTRUCTOR
===========

new( $attr1 => $value1 [, $attr2 => $value2 ] )
-----------------------------------------------

   Possible attributes are:

VERBOSE
     Generate verbose messages to STDERR.

LENGTH
     Maximum length of summary (in bytes). Default is 500.

USE_META
     Flag to tell summarizer whether to use the content of the `<META'> tag
     in the page header, if one is present, instead of generating a
     summary from the body text. *Note that* if the USE_META flag is set,
     this overrides the LENGTH flag - in other words, the summary provided
     by the `<META'> tag is returned in full, even if it is greater than
     LENGTH bytes. Default is 0 (no).

     my $summarizer = new HTML::Summary LENGTH => 200;

METHODS
=======

option( )
---------

   Get / set HTML::Summary configuration options.

     my $length = $summarizer->option( 'LENGTH' );
     $summarizer->option( 'USE_META' => 1 );

generate( $tree )
-----------------

   Takes an HTML::Element object, and generates a summary from it.

     my $tree = new HTML::TreeBuilder;
     $tree->parse( $document );
     my $summary = $summarizer->generate( $tree );

meta_used( )
------------

   Returns 1 if the META tag description was used to generate the summary.

     if ( $summarizer->meta_used() )
     {
         # do something ...
     }

SEE ALSO
========

     HTML::TreeBuilder
     Text::Sentence
     Lingua::JA::Jcode
     Lingua::JA::Jtruncate

AUTHORS
=======

     Ave Wrigley <wrigley@cre.canon.co.uk>
     Tony Rose <tgr@cre.canon.co.uk>
     Neil Bowers <neilb@cre.canon.co.uk>

COPYRIGHT
=========

   Copyright (c) 1997 Canon Research Centre Europe (CRE). All rights
reserved.  This script and any associated documentation or files cannot be
distributed outside of CRE without express prior permission from CRE.

produces HTML tables
********************

NAME
====

   HTML::Table - produces HTML tables

SYNOPSIS
========

     use HTML::Table;

     $table1 = new HTML::Table($rows, $cols);
       or
     $table1 = new HTML::Table(-rows=>26,
                               -cols=>2,
                               -border=>1,
                               -bgcolor=>"blue",
                               -width=>"50\%",
                               -spacing=>1,
                               -padding=>1);

     $table1->setCell($cellrow, $cellcol, 'This is Cell 1');
     $table1->setCellBGColor('blue');
     $table1->setCellColSpan(1, 1, 2);
     $table1->setRowHead(1);
     $table1->setColHead(1);

     $table1->print;

     $table2 = new HTML::Table;
     $table2->addRow(@cell_values);
     $table2->addCol(@cell_values2);

     $table1->setCell(1,1, "$table2->getTable");
     $table1->print;

REQUIRES
========

   Perl5.002

EXPORTS
=======

   Nothing

DESCRIPTION
===========

   HTML::Table is used to generate HTML tables for CGI scripts.  By using
the methods provided fairly complex tables can be created, manipulated,
then printed from Perl scripts.  The module also greatly simplifies
creating tables within tables from Perl.  It is possible to create an
entire table using the methods provided and never use an HTML tag.

   HTML::Table also allows for creating dynamically sized tables via its
addRow and addCol methods.  These methods automatically resize the table
if passed more cell values than will fit in the current table grid.

   Methods are provided for nearly all valid table, row, and cell tags
specified for HTML 3.0.

   A Japanese translation of the documentation is available at:

     http://member.nifty.ne.jp/hippo2000/perltips/html/table.htm

METHODS
=======

     [] indicate optional parameters. default value will
        be used if no value is specified

Creation
--------

new HTML::Table([num_rows, num_cols])
     Creates a new HTML table object.  If rows and columns are specified,
     the table will be initialized to that size.  Row and Column numbers
     start at 1,1.  0,0 is considered an empty table.

new HTML::Table([-rows=>num_rows,  		 -cols=>num_cols,  		 -border=>border_width,  		 -bgcolor=>back_colour,  		 -width=>table_width,  		 -spacing=>cell_spacing,  		 -padding=>cell_padding])
     Creates a new HTML table object.  If rows and columns are specified,
     the table will be initialized to that size.  Row and Column numbers
     start at 1,1.  0,0 is considered and empty table.

Table Level Methods
-------------------

setBorder([pixels])
     Sets the table Border Width

setWidth([pixels|percentofscreen])
     Sets the table width Remember to escape percent symbol if used

setCellSpacing([pixels])
setCellPadding([pixels])
setCaption("CaptionText" [, TOP|BOTTOM])
setBGColor([colorname|colortriplet])

autoGrow([1|true|on|anything|0|false|off|no|disable])
     Switches on (default) or off automatic growing of the table if row or
     column values passed to setCell exceed current table size.

Cell Level Methods
------------------

setCell(row_num, col_num, "content")
     Sets the content of a table cell.  This could be any string, even
     another table object via the getTable method.  If the row and/or
     column numbers are outside the existing table boundaries extra rows
     and/or columns are created automatically.

setCellAlign(row_num, col_num, [CENTER|RIGHT|LEFT])
     Sets the horizontal alignment for the cell.

setCellVAlign(row_num, col_num, [CENTER|TOP|BOTTOM])
     Sets the vertical alignment for the cell.

setCellWidth(row_num, col_num, [pixels|percentoftable])
     Sets the width of the cell.

setCellHeight(row_num, col_num, [pixels])
     Sets the height of the cell.

setCellHead(row_num, col_num)
     Sets cell to be of type head (Ie <TH></TH>)

setCellNoWrap(row_num, col_num, [0|1])
     Sets the NoWrap attribute of the cell.

setCellBGColor(row_num, col_num, [colorname|colortriplet])
     Sets the background colour for the cell

setCellRowSpan(row_num, col_num, num_cells)
     Causes the cell to overlap a number of cells below it.  If the
     overlap number is greater than number of cells below the cell, a
     false value will be returned.

setCellColSpan(row_num, col_num, num_cells)
     Causes the cell to overlap a number of cells to the right.  If the
     overlap number is greater than number of cells to the right of the
     cell, a false value will be returned.

setCellSpan(upleft_row_num, up_left_col_num,         lowright_row_num, lowrigt_col_num)
     Joins the block of cells with the corners specified.  If the values
     specified are greater than the number of rows or columns, a false
     value will be returned.

setCellFormat(row_num, col_num, start_string, end_string)
     Start_string should be a string of valid HTML, which is output before
     the cell contents, end_string is valid HTML that is output after the
     cell contents.  This enables formatting to be applied to the cell
     contents.

          $table->setCellFormat(1, 2, '<B>', '</B>');

getCell(row_num, col_num)
     Returns the contents of the specified cell as a string.

Column Level Methods
--------------------

addCol("cell 1 content" [, "cell 2 content",  ...])
     Adds a column to the right end of the table.  Assumes if you pass
     more values than there are rows that you want to increase the number
     of rows.

setColAlign(col_num, [CENTER|RIGHT|LEFT])
     Applies setCellAlign over the entire column.

setColVAlign(col_num, [CENTER|TOP|BOTTOM])
     Applies setCellVAlign over the entire column.

setColWidth(col_num, [pixels|percentoftable])
     Applies setCellWidth over the entire column.

setColHeight(col_num, [pixels])
     Applies setCellHeight over the entire column.

setColHead(col_num)
     Applies setCellHead over the entire column.

setColNoWrap(col_num, [0|1])
     Applies setCellNoWrap over the entire column.

setColBGColor(row_num, [colorname|colortriplet])
     Applies setCellBGColor over the entire column.

setColFormat(col_num, start_string, end_sting)
     Applies setCellFormat over the entire column.

Row Level Methods
-----------------

addRow("cell 1 content" [, "cell 2 content",  ...])
     Adds a row to the bottom of the table.  Assumes if you pass more
     values than there are columns that you want to increase the number of
     columns.

setRowAlign(row_num, [CENTER|RIGHT|LEFT])
     Applies setCellAlign over the entire row.

setRowVAlign(row_num, [CENTER|TOP|BOTTOM])
     Applies setCellVAlign over the entire row.

setRowWidth(row_num, [pixels|percentoftable])
     Applies setCellWidth over the entire row.

setRowHeight(row_num, [pixels])
     Applies setCellHeight over the entire row.

setRowHead(row_num)
     Applies setCellHead over the entire row.

setRowNoWrap(col_num, [0|1])
     Applies setCellNoWrap over the entire row.

setRowBGColor(row_num, [colorname|colortriplet])
     Applies setCellBGColor over the entire row.

setRowFormat(row_num, start_string, end_string)
     Applies setCellFormat over the entire row.

Output Methods
--------------

getTable
     Returns a string containing the HTML representation of the table.

     The same effect can also be achieved by using the object reference in
     a string scalar context.

     For example...

          This code snippet:

          $table = new HTML::Table(2, 2);
          print '<P>Start</P>';
          print $table->getTable;
          print '<P>End</P>';

          would produce the same output as:

          $table = new HTML::Table(2, 2);
          print "<P>Start</P>$table<P>End</P>";

print
     Prints HTML representation of the table to STDOUT

CLASS VARIABLES
===============

HISTORY
=======

   This module was originally created in 1997 by Stacy Lacy and whose last
version was uploaded to CPAN in 1998.  The module was adopted in July 2000
by Anthony Peacock in order to distribute a revised version.  This adoption
took place without the explicit consent of Stacy Lacy as it proved
impossible to contact them at the time.  Although explicit consent was not
obtained at the time, there was some evidence that Stacy Lacy was looking
for somebody to adopt the module in 1998.

AUTHOR
======

   Anthony Peacock, a.peacock@chime.ucl.ac.uk Stacy Lacy (Original author)

CONTRIBUTIONS
=============

   Jay Flaherty, fty@mediapulse.com For ROW, COL & CELL HEAD methods.
Modified the new method to allow hash of values.

   John Stumbles, john@uk.stumbles.org For autogrow behaviour of setCell,
and allowing alignment specifications to be case insensitive

COPYRIGHT
=========

   Copyright (c) 1998-2001 Anthony Peacock, CHIME.  Copyright (c) 1997
Stacy Lacy

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1), CGI(3)

Perl extension for extracting the text contained in tables within an HTML document.
***********************************************************************************

NAME
====

   HTML::TableExtract - Perl extension for extracting the text contained
in tables within an HTML document.

SYNOPSIS
========

     # Matched tables are returned as "table state" objects; tables can be
     # matched using column headers, depth, count within a depth, or some
     # combination of the three.

     # Using column header information. Assume an HTML document with
     # tables that have "Date", "Price", and "Cost" somewhere in a
     # row. The columns beneath those headings are what you want to
     # extract. They will be returned in the same order as you specified
     # the headers since 'automap' is enabled by default.

     use HTML::TableExtract;
     $te = new HTML::TableExtract( headers => [qw(Date Price Cost)] );
     $te->parse($html_string);

     # Examine all matching tables
     foreach $ts ($te->table_states) {
       print "Table (", join(',', $ts->coords), "):\n";
       foreach $row ($ts->rows) {
          print join(',', @$row), "\n";
       }
     }

     # Old style, using top level methods rather than table state objects.
     foreach $table ($te->tables) {
       print "Table (", join(',', $te->table_coords($table)), "):\n";
       foreach $row ($te->rows($table)) {
         print join(',', @$row), "\n";
       }
     }

     # Shorthand...top level rows() method assumes the first table found
     # in the document if no arguments are supplied.
     foreach $row ($te->rows) {
        print join(',', @$row), "\n";
     }

     # Using depth and count information. Every table in the document has
     # a unique depth and count tuple, so when both are specified it is a
     # unique table. Depth and count both begin with 0, so in this case we
     # are looking for a table (depth 2) within a table (depth 1) within a
     # table (depth 0, which is the top level HTML document). In addition,
     # it must be the third (count 2) such instance of a table at that
     # depth.

     $te = new HTML::TableExtract( depth => 2, count => 2 );
     $te->parse($html_string);
     foreach $ts ($te->table_states) {
        print "Table found at ", join(',', $ts->coords), ":\n";
        foreach $row ($ts->rows) {
           print "   ", join(',', @$row), "\n";
        }
     }

DESCRIPTION
===========

   HTML::TableExtract is a subclass of HTML::Parser that serves to extract
the textual information from tables of interest contained within an HTML
document. The text from each extracted table is stored in tabe state
objects which hold the information as an array of arrays that represent
the rows and cells of that table.

   There are three constraints available to specify which tables you would
like to extract from a document: Headers, Depth, and Count.

   Headers, the most flexible and adaptive of the techniques, involves
specifying text in an array that you expect to appear above the data in
the tables of interest. Once all headers have been located in a row of
that table, all further cells beneath the columns that matched your
headers are extracted. All other columns are ignored: think of it as
vertical slices through a table. In addition, TableExtract automatically
rearranges each row in the same order as the headers you provided. If you
would like to disable this, set automap to 0 during object creation, and
instead rely on the column_map() method to find out the order in which the
headers were found. Furthermore, TableExtract will automatically
compensate for cell span issues so that columns are really the same
columns as you would visually see in a browser. This behavior can be
disabled by setting the gridmap parameter to 0. HTML is stripped from the
entire textual content of a cell before header matches are attempted.

   Depth and Count are more specific ways to specify tables in relation to
one another. Depth represents how deeply a table resides in other tables.
The depth of a top-level table in the document is 0. A table within a
top-level table has a depth of 1, and so on. Each depth can be thought of
as a layer; tables sharing the same depth are on the same layer. Within
each of these layers, Count represents the order in which a table was seen
at that depth, starting with 0. Providing both a depth and a count will
uniquely specify a table within a document.

   Each of the Headers, Depth, and Count specifications are cumulative in
their effect on the overall extraction. For instance, if you specify only
a Depth, then you get all tables at that depth (note that these could very
well reside in separate higher-level tables throughout the document since
depth extends across tables). If you specify only a Count, then the tables
at that Count from all depths are returned (i.e., the nth occurrence of a
table at each depth). If you only specify Headers, then you get all tables
in the document containing those column headers. If you have specified
multiple constraints of Headers, Depth, and Count, then each constraint
has veto power over whether a particular table is extracted.

   If no Headers, Depth, or Count are specified, then all tables match.

   Text that is gathered from the tables is decoded with HTML::Entities by
default; this can be disabled by setting the decode parameter to 0.

Chains
------

   Make sure you fully understand the notions of depth and count before
proceeding, because it is about to become a bit more involved.

   Table matches using Headers, Depth, or Count can be chained together in
order to further specify tables relative to one another. Links in chains
are successively applied to tables within tables. Top level constraints
(i.e., header, depth, and count parameters for the TableExtract object)
behave as the first link in the chain. Additional links are specified
using the chain parameter. Each link in the chain has its own set of
constraints. For example:

     $te = new HTML::TableExtract
       (
        headers => [qw(Summary Region)],
        chain   => [
                    { depth => 0, count => 2 },
                    { headers => [qw(Part Qty Cost)] }
                   ],
       );

   The matching process in this case will start with all tables in the
document that have "Summary" and "Region" in their headers. For now,
assume that there was only one table that matched these headers. Each
table contained within that table will be compared to the first link in
the chain. Depth 0 means that a matching table must be immediately
contained within the current table; count 2 means that the matching table
must also be the third at that depth (counts and depths start at 0). In
other words, the next link of the chain will match on the third table
immediately contained within our first matched table. Once this link
matches, then all further tables beneath that table that have "Part",
"Qty", and "Cost" in their headers will match. By default, it is only
tables at the end of the chains that are returned to the application, so
these tables are returned.

   Each time a link in a chain matches a table, an additional context for
depth and count is established. It is perhaps easiest to visualize a
context as a brand-new HTML document, with new depths and counts to
compare to the remaining links in the chain. The top level HTML document
is the first context. Each table in the document establishes a new
context. Depth in a chain link is relative to the context that the
matching table creates (i.e., a link depth of 0 would be a table
immediately contained within the table that matched the prior link in the
chain). Likewise, that same context keeps track of *counts* within the new
depth scheme for comparison to the remaining links in the chain. Headers
still apply if they are present in a link, but they are always independent
of context.

   As it turns out, specifying a depth and count provides a unique address
for a table within a context. For non-unique constraints, such as just a
depth, or headers, there can be multiple matches for a given link. In
these cases the chain "forks" and attempts to make further matches within
each of these tables.

   By default, chains are elastic. This means that when a particular link
does not match on a table, it is passed down to subtables unchanged. For
example:

     $te = new HTML::TableExtract
       (
        headers => [qw(Summary Region)],
        chain   => [
                    { headers => [qw(Part Qty Cost)] }
                   ],
       );

   If there are intervening tables between the two header queries, they
will be ignored; this query will extract all tables with "Part", "Qty",
and "Cost" in the headers that are contained in any table with "Summary"
and "Region" in its headers, regardless of how embedded the inner tables
are. If you want a chain to be inelastic, you can set the elastic
parameter to 0 for the whole TableExtract object. Using the same example:

     $te = new HTML::TableExtract
       (
        headers => [qw(Summary Region)],
        chain   => [
                    { headers => [qw(Part Qty Cost)] }
                   ],
        elastic => 0,
       );

   In this case, the inner table (Part, Qty, Cost) must be *immediately*
contained within the outer table (Summary, Region) in order for the match
to take place. This is equivalent to specifying a depth of 0 for each link
in the chain; if you only want particular links to be inelastic, then
simply set their depths to 0.

   By default, only tables that match at the end of the chains are
retained. The intermediate matches along the chain are referred to as
*waypoints*, and are not extracted by default. A waypoint may be retained,
however, by specifiying the keep parameter in that link of the chain. This
parameter may be specified at the top level as well if you want to keep
tables that match the first set of constraints in the object. If you want
to keep all tables that match along the chain, the specify the keepall
parameter at the top level.

   Are chains overkill? Probably. In reality, nested HTML tables tend not
to be very deep, so there will usually not be much need for lots of links
in a chain. Theoretically, however, chains offer precise targeting of
tables relative to one another, no matter how deeply nested they are.

Pop Quiz
--------

   What happens with the following table extraction?

     $te = new HTML::TableExtract(
                                  chain => [ { depth => 0 } ],
                                 );

   Answer: All tables that are contained in another table are extracted
from the document. In this case, there were no top-level constraints
specified, which if you recall means that all tables match the first set
of constraints (or non-constraints, in this case!). A depth of 0 in the
next link of the chain means that the matching table must be immediately
contained within the table from a prior match.

   The following is equivalent:

     $te = new HTML::TableExtract(
                                  depth     => 1,
                                  subtables => 1,
                                 )

   The subtables parameter tells TableExtract to scoop up all tables
contained within the matching tables. In conjunction with a depth of 1,
this has the affect of discarding all top-level tables in the document,
which is exactly what occurred in the prior example.

Advice
------

   The main point of this module was to provide a flexible method of
extracting tabular information from HTML documents without relying to
heavily on the document layout. For that reason, I suggest using Headers
whenever possible - that way, you are anchoring your extraction on what
the document is trying to communicate rather than some feature of the HTML
comprising the document (other than the fact that the data is contained in
a table).

   HTML::TableExtract is a subclass of HTML::Parser, and as such inherits
all of its basic methods. In particular, start(), end(), and text() are
utilized. Feel free to override them, but if you do not eventually invoke
them in the SUPER class with some content, results are not guaranteed.

METHODS
=======

   The following are the top-level methods of the HTML::TableExtract
object. Tables that have matched a query are actually returned as separate
objects of type HTML::TableExtract::TableState. These table state objects
have their own methods, documented further below. There are some top-level
methods that are present for convenience and backwards compatibility that
are nothing more than front-ends for equivalent table state methods.

Constructor
-----------

new()
     Return a new HTML::TableExtract object. Valid attributes are:

    headers
          Passed as an array reference, headers specify strings of
          interest at the top of columns within targeted tables. These
          header strings will eventually be passed through a non-anchored,
          case-insensitive regular expression, so regexp special
          characters are allowed. The table row containing the headers is
          not returned. Columns that are not beneath one of the provided
          headers will be ignored. Columns will, by default, be rearranged
          into the same order as the headers you provide (see the automap
          parameter for more information). Additionally, by default
          columns are considered what you would see visually beneath that
          header when the table is rendered in a browser. See the gridmap
          parameter for more information.

    depth
          Specify how embedded in other tables your tables of interest
          should be. Top-level tables in the HTML document have a depth of
          0, tables within top-level tables have a depth of 1, and so on.

    count
          Specify which table within each depth you are interested in,
          beginning with 0.

    chain
          List of additional constraints to be matched sequentially from
          the top level constraints. This is a reference to an array of
          hash references. Each hash is a link in the chain, and can be
          specified in terms of depth, count, and headers. Further
          modifiers include keep, which means to retain the table if it
          would normally be dropped as a waypoint.

    automap
          Automatically applies the ordering reported by column_map() to
          the rows returned by rows(). This only makes a difference if you
          have specified Headers and they turn out to be in a different
          order in the table than what you specified. Automap will
          rearrange the columns in the same order as the headers appear.
          To get the original ordering, you will need to take another
          slice of each row using column_map(). automap is enabled by
          default.

    gridmap
          Controls whether the table contents are returned as a grid or a
          tree. ROWSPAN and COLSPAN issues are compensated for, and columns
          really are columns. Empty phantom cells are created where they
          would have been obscured by ROWSPAN or COLSPAN settings. This
          really becomes an issue when extracting columns beneath headers.
          Enabled by default.

    keepall
          Keep all tables that matched along a chain, including tables
          matched by top level contraints. By default, waypoints are
          dropped and only the matches at the end of the chain are
          retained. To retain a particular waypoint along a chain, use the
          keep parameter in that link.

    elastic
          When set to 0, all links in chains will be treated as though
          they had a depth of 0 specified, which means there can be no
          intervening unmatched tables between matches on links.

    subtables
          Extract all tables within matched tables.

    decode
          Automatically decode retrieved text with
          HTML::Entities::decode_entities(). Enabled by default.

    br_translate
          Translate <br> tags into newlines. Sometimes the remaining text
          can be hard to parse if the <br> tag is simply dropped. Enabled
          by default.

    debug
          Prints some debugging information to STDOUT, more for higher
          values.

Regular Methods
---------------

depths()
     Returns all depths that contained matched tables in the document.

counts($depth)
     For a particular depth, returns all counts that contained matched
     tables.

table_state($depth, $count)
     For a particular depth and count, return the table state object for
     the table found, if any.

table_states()
     Return table state objects for all tables that matched.

first_table_state_found()
     Return the table state object for the first table matched in the
     document.

TABLE STATE METHODS
-------------------

   The following methods are invoked from an
HTML::TableExtract::TableState object, such as those returned from the
table_states() method.

rows()
     Return all rows within a matched table. Each row returned is a
     reference to an array containing the text of each cell.

depth()
     Return the (absolute) depth at which this table was found.

count()
     Return the count for this table within the depth it was found.

coords()
     Return depth and count in a list.

column_map()
     Return the order (via indices) in which the provided headers were
     found. These indices can be used as slices on rows to either order the
     rows in the same order as headers or restore the rows to their natural
     order, depending on whether the rows have been pre-adjusted using the
     automap parameter.

lineage()
     Returns the path of matched tables that led to matching this table.
     Lineage only makes sense if chains were used. Tables that were not
     matched by a link in the chain are not included in lineage. The
     lineage path is a list of array refs containing depth and count values
     for each table involved.

Procedural Methods
------------------

   The following top level methods are alternatives to invoking methods in
a table state object. If you do not want to deal with table state objects,
then these methods are for you. The "tables" they deal in are actually
just arrays of arrays, which happen to be the current internal data
structure of the table state objects. They are here for backwards
compatibility.

table($depth, $count)
     Same as `table_state()', but returns the internal data structure
     rather than the table state object.

tables()
     Same as table_states(), but returns the data structures rather than
     the table state objects.

first_table_found()
     Same as first_table_state_found(), except returns the data structure
     for first table that matched.

table_coords($table)
     Returns the depth and count for a particular table data structure. See
     the coords() method provided by table state objects.

rows()
rows($table)
     Return a lsit of the rows for a particular table data structure (first
     table found by default). See the rows() method provided by table
     state objects.

column_map()
column_map($table)
     Return the column map for a particular table data structure (first
     found by default). See the column_map() method provided by table
     state objects.

REQUIRES
========

   HTML::Parser(3), HTML::Entities(3)

AUTHOR
======

   Matthew P. Sisk, <`sisk@mojotoad.com'>

COPYRIGHT
=========

   Copyright (c) 2000 Matthew P. Sisk.  All rights reserved. All wrongs
revenged. This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

SEE ALSO
========

   HTML::Parser(3), perl(1).

Layout Manager for cgi-based web applications
*********************************************

NAME
====

   HTML::TableLayout - Layout Manager for cgi-based web applications

DESCRIPTION
===========

   This is a HTML-generating package for making graphical user interfaces
via a web browser using a "Layout Manager" paradigm such as in Tk/Tcl or
Java.  It includes a component heirarchy for making new "widgets".

EXPORT
======

DEFAULT
     `parameters window table cell header text image link list pre'

FORM
     `form choice button hidden input_text password submit radio'

SYNOPSIS
========

     use HTML::TableLayout;
     	$w = window(undef,"Hello World");
     	$w->insert(table()->insert("hello world"));
     	# ...
     	$w->print();

WARNING: DOCUMENTATION INCOMPLETE AND SOMETIMES WRONG.
------------------------------------------------------

   This documentation is incomplete and occassionally wrong.  As always,
the source is the best reference (and, in fact, is relatively well
commented in this case).  This documentation will improve as the API
stabilizes.

   On the other hand, some effort was made to bring it up-to-date with
release 1.1.4.

Weird OO Syntax
---------------

   I thought that "new" was too noisy and took up too much space, so I do
not use it in the API.  When you call, for example,

     window($x,$y,$z),

   you are really doing

     HTML::TableLayout::Window->new($x,$y,$z).

   (but isn't it a whole lot nicer looking?)

User API
========

parameters
     Constructor for default parameters.  This is used for setting up
     application-wide defaults for parameters of various objects.  It takes
     no arguments but has the following methods:

          $p->set($obj, %p);	# destructive
          $p->insert($obj, %p);	# non-destructive
          $p->delete(@tags);

     Where the $obj is any instance of any component.

     The hash %p is a hash of parameters.  In all but a few cases these
     parameters are passed directly through as HTML parameters.  E.g., if I
     write

     $p->set(table(),width=>"100%",border=>undef,foo=>"bar"),

     then all tables will look like

     <TABLE width="100%" border foo="bar">

     (plus other parameters you add later).  Note that it blindly passes
     through what is presumably a meaningless HTML flag-"foo".

     Now, you might find the first argument (an instance of the object)
     passed in a little odd, to say the least.  Once you pass in any
     instance of any object, it "recognizes" that kind of object in the
     future.  This way, it works not only for built-in classes, but also
     any that you choose to derive yourself.  (NOTE: this will change
     w/1.2.x, but it will probably still work this way for backwards
     compatibility)

     One place that this is very useful is a trivial case.  Let's say that
     I want to define a focused table-i.e., a table that I use
     consistently to guide the users attention.  I can make a class like
     such:

          package FocusedTable;
          @ISA=qw(HTML::TableLayout::ComponentTable);

          ## EOF

     and then I can add a setting:

          $p->set(FocusedTable->new(), %focustable_settings);

     Now, whenever you use a FocusedTable, it will use these settings, even
     though in reality it is the same as a table.

     Hmm... you're thinking, but what if I derive a special Checkbox, but I
     want it to get the parameters for a regular checkbox.  I've provided
     for this as well.  In your constructor for this new checkbox (or an
     init() method):

          package myCheckbox;
          @ISA=qw(HTML::TableLayout::FormComponent::Checkbox);

          sub new {
          	my ($class, %params) = @_;
          	my  = {};
          	bless , $class;
          	->tl_inheritParamsFrom(checkbox());
          	return ;
          }

     And the mechanism that sets the parameters will think it is really
     just a Checkbox.

     (It might be nice if instead of having to set this explicitely, the
     mechanism (_obj2tag(), actually) could check based upon inheritance
     and use the settings from the closest parent.  The thing is (a) I
     don't know how to do this efficiently (b) I want to have this
     tl_inheritParamsFrom() anyway so that one can force whichever behavior
     she wants.)

     NOTE: This is one of the things that will probably change/improve for
     version 1.2.x...

window
     Constructor for a window.  The first argument is a parameters object,
     while the third argument is the parameters specific to that window
     instance.

          window($parameters, $title, %params)

`win_header'
     Constructor for a window header.  The first argument is the number of
     the header, as in:

          win_header(2,"some text")

     will produce:

          <H2>some text</H2>

     Similarly,

          win_header(undef,"some text")

     will produce

          some text

     but will place it up at the top of the window.

table
     Constructor for a table.  Other than a few special cases (such as
     scripts and headers) everything is layed out via tables.  Tables can
     be nested inside other tables.  It takes a hash of parameters as an
     argument-these parameters will only be used for this table.  One
     salient example would be "columns".  If you want to have a
     15-columned table, you'd say:

          $t=table(columns=>15);

     This parameter is passed directly out to the HTML, but this layout
     manager also pays attention to it internally.

     Tables have one external method:

          $t->insert($some_component);

     This something can be pretty much anything derived from
     HTML::TableLayout::Component.  It can also be a form-as a general
     rule the table just does the right thing with whatever you stick in
     it.  If it does not, it is a bug (please let me know!)

`cell'
     Constructor for a cell.  You will be using a lot of these-these
     correspond to <TD></TD> in HTML.  (Rows are handled magically by this
     layout manger).  Tables create default cells when you stick something
     in them which is not a cell (or form).  If you want to put more than
     one thing in a cell, or if you want to made a special cell (e.g., with
     some non-default alignment), then you need to create a cell
     explicitely.  You insert "stuff" into cells much like you do into
     tables.  In fact, when you stick something into a table that the table
     does not recognize, it just passes it along to a (new) cell.

`cell_header'
     Constructor for a cell header.  The first argument is the contents
     (usually text), and the next arguments are a hash of parameters. You
     can set the orientation of such with the "Orientation" pseudo-tag.
     E.g., Orientation=>"left" will make the header appear to the left of
     the cell.

text
     Constructor for text.  It looks like:

          $c->insert(text($text,%params));

     The parameters are a bit special-if you put in stuff like bold=>undef
     or size=>"+2", then it will do the following:

          <FONT size=+2><b>whatever</b></FONT>

     Like everything else here, this is supposed to "just work" as you
     expect it to, so I had to do some funky translations of HTML tags
     since HTML is pretty screwed up with this stuff.

image
     Constructor for an image.  Use it like

          $c->insert(image($url,%params));

     Where the url can be relative or absolute (straight HTML story).

link
     Constructor for a link.  Use it like

          $c->insert(link($url,$anchor,%params));

     Note that $anchor might be something interesting, like an image, so:

          $c->insert(link("whatever.html",image("image.gif")));

     should work like a charm.

list
     Constructor for a list.  A list sets up a list environment in HTML.
     Unlike a lot of other components here, it takes two rigid arguments,
     and not just parameters which get passed to HTML and maybe noticed by
     the layout manager.

          $l=list($numbered, $delimited);
          $l->insert("first element");
          $l->insert(text("second element",bold=>undef));
          $l->insert(link($url,"third element"));

pre
     Sets up a preformatted environment in HTML.  Just give it some text;
     it prints it out raw.

`script'
     Sets up an appropriate environment for a script.  Put the script in
     the window if you want it to appear in the preamble; otherwise it will
     appear whereever you call it in the table.

   NOTE there are other classes... see the source for now to find these.

BUGS
====

   See comments in code, particular TODO in TLCore.pm

AUTHOR
======

   Stephen Farrell <stephen@farrell.org>-feel free to write email with any
questions.

data tables useful in parsing HTML
**********************************

NAME
====

   HTML::Tagset - data tables useful in parsing HTML

SYNOPSIS
========

     use HTML::Tagset;
     # Then use any of the items in the HTML::Tagset package
     #  as need arises

DESCRIPTION
===========

   This module contains several data tables useful in various kinds of
HTML parsing operations.

   Note that all tag names used are lowercase.

   In the following documentation, a "hashset" is a hash being used as a
set - the hash conveys that its keys are there, and the actual values
associated with the keys are not significant.  (But what values are there,
are always true.)

hashset %HTML::Tagset::emptyElement
     This hashset has as values the tag-names (GIs) of elements that cannot
     have content.  (For example, "base", "br", "hr".)  So
     `$HTML::Tagset::emptyElement{'hr'}' exists and is true.
     `$HTML::Tagset::emptyElement{'dl'}' does not exist, and so is not
     true.

hashset %HTML::Tagset::optionalEndTag
     This hashset lists tag-names for elements that can have content, but
     whose end-tags are generally, "safely", omissible.  Example:
     `$HTML::Tagset::emptyElement{'li'}' exists and is true.

hash %HTML::Tagset::linkElements
     Values in this hash are tagnames for elements that might contain
     links, and the value for each is a reference to an array of the names
     of attributes whose values can be links.

hash %HTML::Tagset::boolean_attr
     This hash (not hashset) lists what attributes of what elements can be
     printed without showing the value (for example, the "noshade"
     attribute of "hr" elements).  For elements with only one such
     attribute, its value is simply that attribute name.  For elements
     with many such attributes, the value is a reference to a hashset
     containing all such attributes.

hashset %HTML::Tagset::isPhraseMarkup
     This hashset contains all phrasal-level elements.

hashset %HTML::Tagset::is_Possible_Strict_P_Content
     This hashset contains all phrasal-level elements that be content of a
     P element, for a strict model of HTML.

hashset %HTML::Tagset::isHeadElement
     This hashset contains all elements that elements that should be
     present only in the 'head' element of an HTML document.

hashset %HTML::Tagset::isList
     This hashset contains all elements that can contain "li" elements.

hashset %HTML::Tagset::isTableElement
     This hashset contains all elements that are to be found only in/under
     a "table" element.

hashset %HTML::Tagset::isFormElement
     This hashset contains all elements that are to be found only in/under
     a "form" element.

hashset %HTML::Tagset::isBodyMarkup
     This hashset contains all elements that are to be found only in/under
     the "body" element of an HTML document.

hashset %HTML::Tagset::isHeadOrBodyElement
     This hashset includes all elements that I notice can fall either in
     the head or in the body.

hashset %HTML::Tagset::isKnown
     This hashset lists all known HTML elements.

hashset %HTML::Tagset::canTighten
     This hashset lists elements that might have ignorable whitespace as
     children or siblings.

array @HTML::Tagset::p_closure_barriers
     This array has a meaning that I have only seen a need for in
     HTML::TreeBuilder, but I include it here on the off chance that
     someone might find it of use:

     When we see a "<p>" token, we go lookup up the lineage for a p
     element we might have to minimize.  At first sight, we might say that
     if there's a p anywhere in the lineage of this new p, it should be
     closed.  But that's wrong.  Consider this document:

          <html>
            <head>
              <title>foo</title>
            </head>
            <body>
              <p>foo
                <table>
                  <tr>
                    <td>
                       foo
                       <p>bar
                    </td>
                  </tr>
                </table>
              </p>
            </body>
          </html>

     The second p is quite legally inside a much higher p.

     My formalization of the reason why this is legal, but this:

          <p>foo<p>bar</p></p>

     isn't, is that something about the table constitutes a "barrier" to
     the application of the rule about what p must minimize.

     So `@HTML::Tagset::p_closure_barriers' is the list of all such
     barrier-tags.

hashset %isCDATA_Parent
     This hashset includes all elements whose content is CDATA.

CAVEATS
=======

   You may find it useful to alter the behavior of modules (like
`HTML::Element' or HTML::TreeBuilder) that use `HTML::Tagset''s data
tables by altering the data tables themselves.  You are welcome to try,
but be careful; and be aware that different modules may or may react
differently to the data tables being changed.

   Note that it may be inappropriate to use these tables for *producing*
HTML - for example, `%isHeadOrBodyElement' lists the tagnames for all
elements that can appear either in the head or in the body, such as
"script".  That doesn't mean that I am saying your code that produces HTML
should feel free to put script elements in either place!  If you are
producing programs that spit out HTML, you should be *intimately* familiar
with the DTDs for HTML or XHTML (available at `http://www.w3.org/'), and
you should slavishly obey them, not the data tables in this document.

SEE ALSO
========

   See HTML/Element, HTML/TreeBuilder,
see HTML/LinkExtor,

COPYRIGHT
=========

   Copyright 1995-2000 Gisle Aas; copyright 2000 Sean M. Burke.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Current maintainer: Sean M. Burke, <sburke@cpan.org>

   Most of the code/data in this module was adapted from code written by
Gisle Aas <gisle@aas.no> for `HTML::Element', HTML::TreeBuilder, and
HTML::LinkExtor.

Perl module to use HTML Templates from CGI scripts
**************************************************

NAME
====

   HTML::Template - Perl module to use HTML Templates from CGI scripts

SYNOPSIS
========

   First you make a template - this is just a normal HTML file with a few
extra tags, the simplest being <TMPL_VAR>

   For example, test.tmpl:

     <HTML>
     <HEAD><TITLE>Test Template</TITLE>
     <BODY>
     My Home Directory is <TMPL_VAR NAME=HOME>
     <P>
     My Path is set to <TMPL_VAR NAME=PATH>
     </BODY>
     </HTML>

   Now create a small CGI program:

     use HTML::Template;

     # open the html template
     my $template = HTML::Template->new(filename => 'test.tmpl');

     # fill in some parameters
     $template->param(
         HOME => $ENV{HOME},
         PATH => $ENV{PATH},
     );

     # send the obligatory Content-Type
     print "Content-Type: text/html\n\n";

     # print the template
     print $template->output;

   If all is well in the universe this should show something like this in
your browser when visiting the CGI:

   My Home Directory is /home/some/directory My Path is set to
/bin;/usr/bin

DESCRIPTION
===========

   This module attempts to make using HTML templates simple and natural.
It extends standard HTML with a few new HTML-esque tags - <TMPL_VAR>,
<TMPL_LOOP>, <TMPL_INCLUDE>, <TMPL_IF> and <TMPL_ELSE>.  The file written
with HTML and these new tags is called a template.  It is usually saved
separate from your script - possibly even created by someone else!  Using
this module you fill in the values for the variables, loops and branches
declared in the template.  This allows you to separate design - the HTML -
from the data, which you generate in the Perl script.

   A Japanese translation of the documentation is available at:

     http://member.nifty.ne.jp/hippo2000/perltips/html/template.htm

   This module is licensed under the GPL.  See the LICENSE section below
for more details.

MOTIVATION
==========

   It is true that there are a number of packages out there to do HTML
templates.  On the one hand you have things like HTML::Embperl which
allows you freely mix Perl with HTML.  On the other hand lie home-grown
variable substitution solutions.  Hopefully the module can find a place
between the two.

   One advantage of this module over a full HTML::Embperl-esque solution
is that it enforces an important divide - design and programming.  By
limiting the programmer to just using simple variables and loops in the
HTML, the template remains accessible to designers and other non-perl
people.  The use of HTML-esque syntax goes further to make the format
understandable to others.  In the future this similarity could be used to
extend existing HTML editors/analyzers to support HTML::Template.

   An advantage of this module over home-grown tag-replacement schemes is
the support for loops.  In my work I am often called on to produce tables
of data in html.  Producing them using simplistic HTML templates results
in CGIs containing lots of HTML since the HTML itself cannot represent
loops.  The introduction of loop statements in the HTML simplifies this
situation considerably.  The designer can layout a single row and the
programmer can fill it in as many times as necessary - all they must agree
on is the parameter names.

   For all that, I think the best thing about this module is that it does
just one thing and it does it quickly and carefully.  It doesn't try to
replace Perl and HTML, it just augments them to interact a little better.
And it's pretty fast.

The Tags
========

   Note: even though these tags look like HTML they are a little different
in a couple of ways.  First, they must appear entirely on one line.
Second, they're allowed to "break the rules".  Something like:

     <IMG SRC="<TMPL_VAR NAME=IMAGE_SRC>">

   is not really valid HTML, but it is a perfectly valid use and will work
as planned.

   The "NAME=" in the tag is optional, although for extensibility's sake I
recommend using it.  Example - "<TMPL_LOOP LOOP_NAME>" is acceptable.

   If you're a fanatic about valid HTML and would like your templates to
conform to valid HTML syntax, you may optionally type template tags in the
form of HTML comments. This may be of use to HTML authors who would like
to validate their templates' HTML syntax prior to HTML::Template
processing, or who use DTD-savvy editing tools.

     <!-- TMPL_VAR NAME=PARAM1 -->

   In order to realize a dramatic savings in bandwidth, the standard
(non-comment) tags will be used throughout the rest of this documentation.

<TMPL_VAR NAME="PARAMETER_NAME">
--------------------------------

   The <TMPL_VAR> tag is very simple.  For each <TMPL_VAR> tag in the
template you call $template->param(PARAMETER_NAME => "VALUE").  When the
template is output the <TMPL_VAR> is replaced with the VALUE text you
specified.  If you don't set a parameter it just gets skipped in the
output.

   Optionally you can use the "ESCAPE=HTML" option in the tag to indicate
that you want the value to be HTML-escaped before being returned from
output (the old ESCAPE=1 syntax is still supported).  This means that the
", <, >, and & characters get translated into &quot;, &lt;, &gt; and &amp;
respectively.  This is useful when you want to use a TMPL_VAR in a context
where those characters would cause trouble.  Example:

     <INPUT NAME=param TYPE=TEXT VALUE="<TMPL_VAR NAME="param">">

   If you called param() with a value like sam"my you'll get in trouble
with HTML's idea of a double-quote.  On the other hand, if you use
ESCAPE=HTML, like this:

     <INPUT NAME=param TYPE=TEXT VALUE="<TMPL_VAR ESCAPE=HTML NAME="param">">

   You'll get what you wanted no matter what value happens to be passed in
for param.  You can also write ESCAPE="HTML", ESCAPE='HTML' and ESCAPE='1'.
Substitute a 0 for the HTML and you turn off escaping, which is the default
anyway.

   There is also the "ESCAPE=URL" option which may be used for VARs that
populate a URL.  It will do URL escaping, like replacing ' ' with '+' and
'/' with '%2F'.

<TMPL_LOOP NAME="LOOP_NAME"> </TMPL_LOOP>
-----------------------------------------

   The <TMPL_LOOP> tag is a bit more complicated.  The <TMPL_LOOP> tag
allows you to delimit a section of text and give it a name.  Inside the
<TMPL_LOOP> you place <TMPL_VAR>s.  Now you pass to param() a list (an
array ref) of parameter assignments (hash refs).  The loop iterates over
this list and produces output from the text block for each pass.  Unset
parameters are skipped.  Here's an example:

     In the template:

     <TMPL_LOOP NAME=EMPLOYEE_INFO>
           Name: <TMPL_VAR NAME=NAME> <P>
           Job: <TMPL_VAR NAME=JOB> <P>
          <P>
     </TMPL_LOOP>

     In the script:

     $template->param(EMPLOYEE_INFO => [
                                         { name => 'Sam', job => 'programmer' },
                                         { name => 'Steve', job => 'soda jerk' },
                                       ]
                     );
     print $template->output();

     The output:

     Name: Sam <P>
     Job: programmer <P>
     <P>
     Name: Steve <P>
     Job: soda jerk <P>
     <P>

   As you can see above the <TMPL_LOOP> takes a list of variable
assignments and then iterates over the loop body producing output.

   Often you'll want to generate a <TMPL_LOOP>'s contents
programmatically.  Here's an example of how this can be done (many other
ways are possible!):

     # a couple of arrays of data to put in a loop:
     my @words = qw(I Am Cool);
     my @numbers = qw(1 2 3);

     my @loop_data = ();  # initialize an array to hold your loop

     while (@words and @numbers) {
       my %row_data;  # get a fresh hash for the row data

     # fill in this row
     $row_data{WORD} = shift @words;
     $row_data{NUMBER} = shift @numbers;

     # the crucial step - push a reference to this row into the loop!
     push(@loop_data, \%row_data);
        }

     # finally, assign the loop data to the loop param, again with a
     # reference:
     $template->param(THIS_LOOP => \@loop_data);

   The above example would work with a template like:

     <TMPL_LOOP NAME="THIS_LOOP">
        Word: <TMPL_VAR NAME="WORD"><BR>
        Number: <TMPL_VAR NAME="NUMBER"><P>
     </TMPL_LOOP>

   It would produce output like:

     Word: I
     Number: 1

     Word: Am
     Number: 2

     Word: Cool
     Number: 3

   <TMPL_LOOP>s within <TMPL_LOOP>s are fine and work as you would expect.
If the syntax for the param() call has you stumped, here's an example of
a param call with one nested loop:

     $template->param('ROW',[
                             { name => 'Bobby',
                               nicknames => [
                                             { name => 'the big bad wolf' },
                                             { name => 'He-Man' },
                                            ],
                             },
                            ],
                     );

   Basically, each <TMPL_LOOP> gets an array reference.  Inside the array
are any number of hash references.  These hashes contain the name=>value
pairs for a single pass over the loop template.

   Inside a <TMPL_LOOP>, the only variables that are usable are the ones
from the <TMPL_LOOP>.  The variables in the outer blocks are not visible
within a template loop.  For the computer-science geeks among you, a
<TMPL_LOOP> introduces a new scope much like a perl subroutine call.  If
you want your variables to be global you can use 'global_vars' option to
new described below.

<TMPL_INCLUDE NAME="filename.tmpl">
-----------------------------------

   This tag includes a template directly into the current template at the
point where the tag is found.  The included template contents are used
exactly as if its contents were physically included in the master template.

   The file specified can be a full path - beginning with a '/'.  If it
isn't a full path, the path to the enclosing file is tried first.  After
that the path in the environment variable HTML_TEMPLATE_ROOT is tried
next, if it exists.  Next, the "path" new() option is consulted.  As a
final attempt, the filename is passed to open() directly.  See below for
more information on HTML_TEMPLATE_ROOT and the "path" option to new().

   As a protection against infinitly recursive includes, an arbitary limit
of 10 levels deep is imposed.  You can alter this limit with the
"max_includes" option.  See the entry for the "max_includes" option below
for more details.

<TMPL_IF NAME="CONTROL_PARAMETER_NAME"> </TMPL_IF>
--------------------------------------------------

   The <TMPL_IF> tag allows you to include or not include a block of the
template based on the value of a given parameter name.  If the parameter
is given a value that is true for Perl - like '1' - then the block is
included in the output.  If it is not defined, or given a false value -
like '0' - then it is skipped.  The parameters are specified the same way
as with TMPL_VAR.

   Example Template:

     <TMPL_IF NAME="BOOL">
       Some text that only gets displayed if BOOL is true!
     </TMPL_IF>

   Now if you call $template->param(BOOL => 1) then the above block will
be included by output.

   <TMPL_IF> </TMPL_IF> blocks can include any valid HTML::Template
construct - VARs and LOOPs and other IF/ELSE blocks.  Note, however, that
intersecting a <TMPL_IF> and a <TMPL_LOOP> is invalid.

     Not going to work:
     <TMPL_IF BOOL>
        <TMPL_LOOP SOME_LOOP>
     </TMPL_IF>
        </TMPL_LOOP>

   If the name of a TMPL_LOOP is used in a TMPL_IF, the IF block will
output if the loop has at least one row.  Example:

     <TMPL_IF LOOP_ONE>
       This will output if the loop is not empty.
     </TMPL_IF>

     <TMPL_LOOP LOOP_ONE>
       ....
     </TMPL_LOOP>

   WARNING: Much of the benefit of HTML::Template is in decoupling your
Perl and HTML.  If you introduce numerous cases where you have TMPL_IFs
and matching Perl if()s, you will create a maintenance problem in keeping
the two synchronized.  I suggest you adopt the practice of only using
TMPL_IF if you can do so without requiring a matching if() in your Perl
code.

<TMPL_ELSE>
-----------

   You can include an alternate block in your TMPL_IF block by using
TMPL_ELSE.  NOTE: You still end the block with </TMPL_IF>, not
</TMPL_ELSE>!

   Example:

     <TMPL_IF BOOL>
       Some text that is included only if BOOL is true
     <TMPL_ELSE>
       Some text that is included only if BOOL is false
     </TMPL_IF>

<TMPL_UNLESS NAME="CONTROL_PARAMETER_NAME"> </TMPL_UNLESS>
----------------------------------------------------------

   This tag is the opposite of <TMPL_IF>.  The block is output if the
CONTROL_PARAMETER is set false or not defined.  You can use <TMPL_ELSE>
with <TMPL_UNLESS> just as you can with <TMPL_IF>.

     Example:

     <TMPL_UNLESS BOOL>
       Some text that is output only if BOOL is FALSE.
     <TMPL_ELSE>
       Some text that is output only if BOOL is TRUE.
     </TMPL_UNLESS>

   If the name of a TMPL_LOOP is used in a TMPL_UNLESS, the UNLESS block
output if the loop has zero rows.

     <TMPL_UNLESS LOOP_ONE>
       This will output if the loop is empty.
     </TMPL_UNLESS>

     <TMPL_LOOP LOOP_ONE>
       ....
     </TMPL_LOOP>

Methods
=======

new()
-----

   Call new() to create a new Template object:

     my $template = HTML::Template->new( filename => 'file.tmpl',
                                         option => 'value'
                                       );

   You must call new() with at least one name => value pair specifying how
to access the template text.  You can use "filename => 'file.tmpl'" to
specify a filename to be opened as the template.  Alternately you can use:

     my $t = HTML::Template->new( scalarref => $ref_to_template_text,
                                  option => 'value'
                                );

   and

     my $t = HTML::Template->new( arrayref => $ref_to_array_of_lines ,
                                  option => 'value'
                                );

   These initialize the template from in-memory resources.  In almost
every case you'll want to use the filename parameter.  If you're worried
about all the disk access from reading a template file just use mod_perl
and the cache option detailed below.

   The three new() calling methods can also be accessed as below, if you
prefer.

     my $t = HTML::Template->new_file('file.tmpl', option => 'value');

     my $t = HTML::Template->new_scalar_ref($ref_to_template_text,
                                           option => 'value');

     my $t = HTML::Template->new_array_ref($ref_to_array_of_lines,
                                          option => 'value');

   And as a final option, for those that might prefer it, you can call new
as:

     my $t = HTML::Template->new(type => 'filename',
                                 source => 'file.tmpl');

   Which works for all three of the source types.

   If the environment variable HTML_TEMPLATE_ROOT is set and your filename
doesn't begin with /, then the path will be relative to the value of
$HTML_TEMPLATE_ROOT.  Example - if the environment variable
HTML_TEMPLATE_ROOT is set to "/home/sam" and I call HTML::Template->new()
with filename set to "sam.tmpl", the HTML::Template will try to open
"/home/sam/sam.tmpl" to access the template file.  You can also affect the
search path for files with the "path" option to new() - see below for more
information.

   You can modify the Template object's behavior with new.  These options
are available:

   * die_on_bad_params - if set to 0 the module will let you call
     $template->param(param_name => 'value') even if 'param_name' doesn't
     exist in the template body.  Defaults to 1.

   * strict - if set to 0 the module will allow things that look like they
     might be TMPL_* tags to get by without dieing.  Example:

          <TMPL_HUH NAME=ZUH>

     Would normally cause an error, but if you call new with strict => 0,
     HTML::Template will ignore it.  Defaults to 1.

   * cache - if set to 1 the module will cache in memory the parsed
     templates based on the filename parameter and modification date of the
     file.  This only applies to templates opened with the filename
     parameter specified, not scalarref or arrayref templates.  Caching
     also looks at the modification times of any files included using
     <TMPL_INCLUDE> tags, but again, only if the template is opened with
     filename parameter.

     This is mainly of use in a persistent environment like
     Apache/mod_perl.  It has absolutely no benefit in a normal CGI
     environment since the script is unloaded from memory after every
     request.  For a cache that does work for normal CGIs see the
     'shared_cache' option below.

     Note that different new() parameter settings do not cause a cache
     refresh, only a change in the modification time of the template will
     trigger a cache refresh.  For most usages this is fine.  My simplistic
     testing shows that using cache yields a 90% performance increase under
     mod_perl.  Cache defaults to 0.

   * shared_cache - if set to 1 the module will store its cache in shared
     memory using the IPC::SharedCache module (available from CPAN).  The
     effect of this will be to maintain a single shared copy of each parsed
     template for all instances of HTML::Template to use.  This can be a
     significant reduction in memory usage in a multiple server
     environment.  As an example, on one of our systems we use 4MB of
     template cache and maintain 25 httpd processes - shared_cache results
     in saving almost 100MB!  Of course, some reduction in speed versus
     normal caching is to be expected.  Another difference between normal
     caching and shared_cache is that shared_cache will work in a CGI
     environment - normal caching is only useful in a persistent
     environment like Apache/mod_perl.

     By default HTML::Template uses the IPC key 'TMPL' as a shared root
     segment (0x4c504d54 in hex), but this can be changed by setting the
     'ipc_key' new() parameter to another 4-character or integer key.
     Other options can be used to affect the shared memory cache correspond
     to IPC::SharedCache options - ipc_mode, ipc_segment_size and
     ipc_max_size.  See IPC/SharedCache, for a
     description of how these work - in most cases you shouldn't need to
     change them from the defaults.

     For more information about the shared memory cache system used by
     HTML::Template see IPC/SharedCache.

   * double_cache - if set to 1 the module will use a combination of
     shared_cache and normal cache mode for the best possible caching.  Of
     course, it also uses the most memory of all the cache modes.  All the
     same ipc_* options that work with shared_cache apply to double_cache
     as well.  By default double_cache is off.

   * blind_cache - if set to 1 the module behaves exactly as with normal
     caching but does not check to see if the file has changed on each
     request.  This option should be used with caution, but could be of use
     on high-load servers.  My tests show blind_cache performing only 1 to
     2 percent faster than cache under mod_perl.

     NOTE: Combining this option with shared_cache can result in stale
     templates stuck permanently in shared memory!

   * file_cache - if set to 1 the module will store its cache in a file
     using the Storable module.  It uses no additional memory, and my
     simplistic testing shows that it yields a 50% performance advantage.
     Like shared_cache, it will work in a CGI environment. Default is 0.

     If you set this option you must set the "file_cache_dir" option.  See
     below for details.

     NOTE: Storable using flock() to ensure safe access to cache files.
     Using file_cache on a system or filesystem (NFS) without flock()
     support is dangerous.

   * file_cache_dir - sets the directory where the module will store the
     cache files if file_cache is enabled.  Your script will need write
     permissions to this directory.  You'll also need to make sure the
     sufficient space is available to store the cache files.

   * file_cache_dir_mode - sets the file mode for newly created file_cache
     directories and subdirectories.  Defaults to 0700 for security but
     this may be inconvenient if you do not have access to the account
     running the webserver.

   * double_file_cache - if set to 1 the module will use a combination of
     file_cache and normal cache mode for the best possible caching.  The
     file_cache_* options that work with file_cache apply to
     double_file_cache as well.  By default double_file_cache is 0.

   * associate - this option allows you to inherit the parameter values
     from other objects.  The only requirement for the other object is that
     it have a param() method that works like HTML::Template's param().  A
     good candidate would be a CGI.pm query object.  Example:

          my $query = new CGI;
          my $template = HTML::Template->new(filename => 'template.tmpl',
                                             associate => $query);

     Now, $template->output() will act as though

          $template->param('FormField', $cgi->param('FormField'));

     had been specified for each key/value pair that would be provided by
     the $cgi->param() method.  Parameters you set directly take precedence
     over associated parameters.

     You can specify multiple objects to associate by passing an anonymous
     array to the associate option.  They are searched for parameters in
     the order they appear:

          my $template = HTML::Template->new(filename => 'template.tmpl',
                                             associate => [$query, $other_obj]);

     The old associateCGI() call is still supported, but should be
     considered obsolete.

     NOTE: The parameter names are matched in a case-insensitve manner.  If
     you have two parameters in a CGI object like 'NAME' and 'Name' one
     will be chosen randomly by associate.  This behavior can be changed by
     the following option.

   * case_sensitive - setting this option to true causes HTML::Template to
     treat template variable names case-sensitively.  The following example
     would only set one parameter without the "case_sensitive" option:

          my $template = HTML::Template->new(filename => 'template.tmpl',
                                             case_sensitive => 1);
          $template->param(
            FieldA => 'foo',
            fIELDa => 'bar',
          );

     This option defaults to off.

   * loop_context_vars - when this parameter is set to true (it is false by
     default) four loop context variables are made available inside a loop:
     __FIRST__, __LAST__, __INNER__, __ODD__.  They can be used with
     <TMPL_IF>, <TMPL_UNLESS> and <TMPL_ELSE> to control how a loop is
     output.  Example:

          <TMPL_LOOP NAME="FOO">
             <TMPL_IF NAME="__FIRST__">
               This only outputs on the first pass.
             </TMPL_IF>

          <TMPL_IF NAME="__ODD__">
            This outputs every other pass, on the odd passes.
          </TMPL_IF>

          <TMPL_UNLESS NAME="__ODD__">
            This outputs every other pass, on the even passes.
          </TMPL_IF>

          <TMPL_IF NAME="__INNER__">
            This outputs on passes that are neither first nor last.
          </TMPL_IF>

          <TMPL_IF NAME="__LAST__">
            This only outputs on the last pass.
          <TMPL_IF>
             </TMPL_LOOP>

     One use of this feature is to provide a "separator" similar in effect
     to the perl function join().  Example:

          <TMPL_LOOP FRUIT>
             <TMPL_IF __LAST__> and </TMPL_IF>
             <TMPL_VAR KIND><TMPL_UNLESS __LAST__>, <TMPL_ELSE>.</TMPL_UNLESS>
          </TMPL_LOOP>

     Would output (in a browser) something like:

          Apples, Oranges, Brains, Toes, and Kiwi.

     Given an appropriate param() call, of course.  NOTE: A loop with only
     a single pass will get both __FIRST__ and __LAST__ set to true, but
     not __INNER__.

   * path - you can set this variable with a list of paths to search for
     files specified with the "filename" option to new() and for files
     included with the <TMPL_INCLUDE> tag.  This list is only consulted
     when the filename is relative.  The HTML_TEMPLATE_ROOT environment
     variable is always tried first if it exists.  In the case of a
     <TMPL_INCLUDE> file, the path to the including file is also tried
     before path is consulted.

     Example:

          my $template = HTML::Template->new( filename => 'file.tmpl',
                                              path => [ '/path/to/templates',
                                                        '/alternate/path'
                                                      ]
                                             );

     NOTE: the paths in the path list must be expressed as UNIX paths,
     separated by the forward-slash character ('/').

   * no_includes - set this option to 1 to disallow the <TMPL_INCLUDE> tag
     in the template file.  This can be used to make opening untrusted
     templates *slightly* less dangerous.  Defaults to 0.

   * max_includes - set this variable to determine the maximum depth that
     includes can reach.  Set to 10 by default.  Including files to a depth
     greater than this value causes an error message to be displayed.  Set
     to 0 to disable this protection.

   * search_path_on_include - if set to a true value the module will search
     from the top of the array of paths specified by the path option on
     every <TMPL_INCLUDE> and use the first matching template found.  The
     normal behavior is to look only in the current directory for a
     template to include.  Defaults to 0.

   * global_vars - normally variables declared outside a loop are not
     available inside a loop.  This option makes <TMPL_VAR>s like global
     variables in Perl - they have unlimited scope.  This option also
     affects <TMPL_IF> and <TMPL_UNLESS>.

     Example:

          This is a normal variable: <TMPL_VAR NORMAL>.<P>

          <TMPL_LOOP NAME=FROOT_LOOP>
             Here it is inside the loop: <TMPL_VAR NORMAL><P>
          </TMPL_LOOP>

     Normally this wouldn't work as expected, since <TMPL_VAR NORMAL>'s
     value outside the loop is not available inside the loop.

   * filter - this option allows you to specify a filter for your template
     files.  A filter is a subroutine that will be called after
     HTML::Template reads your template file but before it starts parsing
     template tags.

     In the most simple usage, you simply assign a code reference to the
     filter parameter.  This subroutine will recieve a single arguement - a
     reference to a string containing the template file text.  Here is an
     example that accepts templates with tags that look like "!!!ZAP_VAR
     FOO!!!" and transforms them into HTML::Template tags:

          my $filter = sub {
            my $text_ref = shift;
            $$text_ref =~ s/!!!ZAP_(.*?)!!!/<TMPL_$1>/g;
          }

          # open zap.tmpl using the above filter
          my $template = HTML::Template->new(filename => 'zap.tmpl',
                                             filter => $filter);

     More complicated usages are possible.  You can request that your
     filter receieve the template text as an array of lines rather than as
     a single scalar.  To do that you need to specify your filter using a
     hash-ref.  In this form you specify the filter using the "sub" key and
     the desired argument format using the "format" key.  The available
     formats are "scalar" and "array".

          my $template = HTML::Template->new(filename => 'zap.tmpl',
                                             filter => { sub => $filter,
                                                         format => 'array' });

     Using the 'array' format is likely to be more efficient since this is
     how HTML::Template stores the template text internally.  This may
     change in the future.

     You may also have multiple filters.  This allows simple filters to be
     combined for more elaborate functionality.  To do this you specify an
     array of filters.  The filters are applied in the order they are
     specified.

          my $template = HTML::Template->new(filename => 'zap.tmpl',
                                             filter => [
                                                  { sub => \&decompress,
                                                    format => 'scalar' },
                                                  { sub => \&remove_spaces,
                                                    format => 'array' }
                                               ]);

     The specified filters will be called for any TMPL_INCLUDEed files just
     as they are for the main template file.

   * vanguard_compatibility_mode - if set to 1 the module will expect to
     see <TMPL_VAR>s that look like %NAME% in addition to the standard
     syntax.  Also sets die_on_bad_params => 0.  If you're not at Vanguard
     Media trying to use an old format template don't worry about this one.
     Defaults to 0.

   * debug - if set to 1 the module will write random debugging information
     to STDERR.  Defaults to 0.

   * stack_debug - if set to 1 the module will use Data::Dumper to print
     out the contents of the parse_stack to STDERR.  Defaults to 0.

   * cache_debug - if set to 1 the module will send information on cache
     loads, hits and misses to STDERR.  Defaults to 0.

   * shared_cache_debug - if set to 1 the module will turn on the debug
     option in IPC::SharedCache - see IPC/SharedCache,
     for details. Defaults to 0.

   * memory_debug - if set to 1 the module will send information on cache
     memory usage to STDERR.  Requires the GTop module.  Defaults to 0.

param
-----

   param() can be called in a number of ways

   1) To return a list of parameters in the template :

     my @parameter_names = $self->param();

   2) To return the value set to a param :

     my $value = $self->param('PARAM');

   3) To set the value of a parameter :

     # For simple TMPL_VARs:
     $self->param(PARAM => 'value');

     # with a subroutine reference that gets called to get the value of
     # the scalar.
     $self->param(PARAM => sub { return 'value' });

     # And TMPL_LOOPs:
     $self->param(LOOP_PARAM =>
                  [
                   { PARAM => VALUE_FOR_FIRST_PASS, ... },
                   { PARAM => VALUE_FOR_SECOND_PASS, ... }
                   ...
                  ]
                 );

   4) To set the value of a a number of parameters :

     # For simple TMPL_VARs:
     $self->param(PARAM => 'value',
                  PARAM2 => 'value'
                 );

     # And with some TMPL_LOOPs:
     $self->param(PARAM => 'value',
                  PARAM2 => 'value',
                  LOOP_PARAM =>
                  [
                   { PARAM => VALUE_FOR_FIRST_PASS, ... },
                   { PARAM => VALUE_FOR_SECOND_PASS, ... }
                   ...
                  ],
                  ANOTHER_LOOP_PARAM =>
                  [
                   { PARAM => VALUE_FOR_FIRST_PASS, ... },
                   { PARAM => VALUE_FOR_SECOND_PASS, ... }
                   ...
                  ]
                 );

   5) To set the value of a a number of parameters using a hash-ref :

     $self->param(
                  {
                     PARAM => 'value',
                     PARAM2 => 'value',
                     LOOP_PARAM =>
                     [
                       { PARAM => VALUE_FOR_FIRST_PASS, ... },
                       { PARAM => VALUE_FOR_SECOND_PASS, ... }
                       ...
                     ],
                     ANOTHER_LOOP_PARAM =>
                     [
                       { PARAM => VALUE_FOR_FIRST_PASS, ... },
                       { PARAM => VALUE_FOR_SECOND_PASS, ... }
                       ...
                     ]
                   }
                  );

clear_params()
--------------

   Sets all the parameters to undef.  Useful internally, if nowhere else!

output()
--------

   output() returns the final result of the template.  In most situations
you'll want to print this, like:

     print $template->output();

   When output is called each occurrence of <TMPL_VAR NAME=name> is
replaced with the value assigned to "name" via param().  If a named
parameter is unset it is simply replaced with ".  <TMPL_LOOPS> are
evaluated once per parameter set, accumlating output on each pass.

   Calling output() is guaranteed not to change the state of the Template
object, in case you were wondering.  This property is mostly important for
the internal implementation of loops.

   You may optionally supply a filehandle to print to automatically as the
template is generated.  This may improve performance and lower memory
consumption.  Example:

     $template->output(print_to => *STDOUT);

   The return value is undefined when using the "print_to" option.

query()
-------

   This method allow you to get information about the template structure.
It can be called in a number of ways.  The simplest usage of query is
simply to check whether a parameter name exists in the template, using the
name option:

     if ($template->query(name => 'foo')) {
       # do something if a varaible of any type
       # named FOO is in the template
     }

   This same usage returns the type of the parameter.  The type is the
same as the tag minus the leading 'TMPL_'.  So, for example, a TMPL_VAR
parameter returns 'VAR' from query().

     if ($template->query(name => 'foo') eq 'VAR') {
       # do something if FOO exists and is a TMPL_VAR
     }

   Note that the variables associated with TMPL_IFs and TMPL_UNLESSs will
be identified as 'VAR' unless they are also used in a TMPL_LOOP, in which
case they will return 'LOOP'.

   query() also allows you to get a list of parameters inside a loop (and
inside loops inside loops).  Example loop:

     <TMPL_LOOP NAME="EXAMPLE_LOOP">
       <TMPL_VAR NAME="BEE">
       <TMPL_VAR NAME="BOP">
       <TMPL_LOOP NAME="EXAMPLE_INNER_LOOP">
         <TMPL_VAR NAME="INNER_BEE">
         <TMPL_VAR NAME="INNER_BOP">
       </TMPL_LOOP>
     </TMPL_LOOP>

   And some query calls:

   # returns 'LOOP'   $type = $template->query(name => 'EXAMPLE_LOOP');

   # returns ('bop', 'bee', 'example_inner_loop')   @param_names =
$template->query(loop => 'EXAMPLE_LOOP');

     # both return 'VAR'
     $type = $template->query(name => ['EXAMPLE_LOOP', 'BEE']);
     $type = $template->query(name => ['EXAMPLE_LOOP', 'BOP']);

     # and this one returns 'LOOP'
     $type = $template->query(name => ['EXAMPLE_LOOP',
                                       'EXAMPLE_INNER_LOOP']);

     # and finally, this returns ('inner_bee', 'inner_bop')
     @inner_param_names = $template->query(loop => ['EXAMPLE_LOOP',
                                                    'EXAMPLE_INNER_LOOP']);

     # for non existent parameter names you get undef
     # this returns undef.
     $type = $template->query(name => 'DWEAZLE_ZAPPA');

     # calling loop on a non-loop parameter name will cause an error.
     # this dies:
     $type = $template->query(loop => 'DWEAZLE_ZAPPA');

   As you can see above the loop option returns a list of parameter names
and both name and loop take array refs in order to refer to parameters
inside loops.  It is an error to use loop with a parameter that is not a
loop.

   Note that all the names are returned in lowercase and the types are
uppercase.

   Just like param(), query() with no arguements returns all the parameter
names in the template at the top level.

FREQUENTLY ASKED QUESTIONS
==========================

   In the interest of greater understanding I've started a FAQ section of
the perldocs.  Please look in here before you send me email.

   1) Is there a place to go to discuss HTML::Template and/or get help?

   There's a mailing-list for HTML::Template at htmltmpl@lists.vm.com.
Send a blank message to htmltmpl-subscribe@lists.vm.com to join!

   2) I want support for <TMPL_XXX>!  How about it?

   Maybe.  I definitely encourage people to discuss their ideas for
HTML::Template on the mailing list.  Please be ready to explain to me how
the new tag fits in with HTML::Template's mission to provide a fast,
lightweight system for using HTML templates.

   NOTE: Offering to program said addition and provide it in the form of a
patch to the most recent version of HTML::Template will definitely have a
softening effect on potential opponents!

   3) I found a bug, can you fix it?

   That depends.  Did you send me the VERSION of HTML::Template, a test
script and a test template?  If so, then almost certainly.

   If you're feeling really adventurous, HTML::Template has a publically
available CVS server.  See below for more information in the PUBLIC CVS
SERVER section.

   4) <TMPL_VAR>s from the main template aren't working inside a
<TMPL_LOOP>!  Why?

   This is the intended behavior.  <TMPL_LOOP> introduces a separate scope
for <TMPL_VAR>s much like a subroutine call in Perl introduces a separate
scope for "my" variables.

   If you want your <TMPL_VAR>s to be global you can set the 'global_vars'
option when you call new().  See above for documentation of the
'global_vars' new() option.

   5) Why do you use /[Tt]/ instead of /t/i?  It's so ugly!

   Simple - the case-insensitive match switch is very inefficient.
According to _Mastering_Regular_Expressions_ from O'Reilly Press, /[Tt]/
is faster and more space efficient than /t/i - by as much as double
against long strings.  //i essentially does a lc() on the string and keeps
a temporary copy in memory.

   When this changes, and it is in the 5.6 development series, I will
gladly use //i.  Believe me, I realize [Tt] is hideously ugly.

   6) How can I pre-load my templates using cache-mode and mod_perl?

   Add something like this to your startup.pl:

     use HTML::Template;
     use File::Find;

     print STDERR "Pre-loading HTML Templates...\n";
     find(
          sub {
            return unless /\.tmpl$/;
            HTML::Template->new(
                                filename => "$File::Find::dir/$_",
                                cache => 1,
                               );
          },
          '/path/to/templates',
          '/another/path/to/templates/'
        );

   Note that you'll need to modify the "return unless" line to specify the
extension you use for your template files - I use .tmpl, as you can see.
You'll also need to specify the path to your template files.

   One potential problem: the "/path/to/templates/" must be EXACTLY the
same path you use when you call HTML::Template->new().  Otherwise the
cache won't know they're the same file and will load a new copy - instead
getting a speed increase, you'll double your memory usage.  To find out if
this is happening set cache_debug => 1 in your application code and look
for "CACHE MISS" messages in the logs.

   7) What characters are allowed in TMPL_* NAMEs?

   Numbers, letters, '.', '/', '+', '-' and '_'.

   8) How can I execute a program from inside my template?

   Short answer: you can't.  Longer answer: you shouldn't since this
violates the fundamental concept behind HTML::Template - that design and
code should be seperate.

   But, inevitably some people still want to do it.  At times it has even
seemed that HTML::Template development might split over this issue, so I
will attempt a compromise.  Here is a method you can use to allow your
template authors to evaluate arbitrary perl scripts from within the
template.

   First, tell all your designers that when they want to run a perl script
named "program.pl" they should use a tag like:

     <TMPL_VAR NAME="__execute_program.pl__">

   Then, have all your programmers call this subroutine instead of calling
HTML::Template::new directly.  They still use the same parameters, but
they also get the program execution.

     sub new_template {
       # get the template object
       my $template = HTML::Template->new(@_);

       # find program parameters and fill them in
       my @params = $template->param();
       for my $param (@params) {
          if ($param =~ /^__execute_(.*)__$/) {
            $template->param($param, do($1));
          }
       }

     # return the template object
     return $template;
       }

   The programs called in this way should return a string containing their
output.  A more complicated subroutine could be written to capture STDOUT
from the scripts, but this one is simple enough to include in the FAQ.
Another improvement would be to use query() to enable program execution
inside loops.

   9) Can I get a copy of these docs in Japanese?

   Yes you can.  See Kawai Takanori's translation at:

     http://member.nifty.ne.jp/hippo2000/perltips/html/template.htm

BUGS
====

   I am aware of no bugs - if you find one, join the mailing list and tell
us about it (htmltmpl@lists.vm.com).  You can join the HTML::Template
mailing-list by sending a blank email to htmltmpl-subscribe@lists.vm.com.
Of course, you can still email me directly (sam@tregar.com) with bugs, but
I reserve the right to forward bug reports to the mailing list.

   When submitting bug reports, be sure to include full details, including
the VERSION of the module, a test script and a test template demonstrating
the problem!

   If you're feeling really adventurous, HTML::Template has a publically
available CVS server.  See below for more information in the PUBLIC CVS
SERVER section.

CREDITS
=======

   This module was the brain child of my boss, Jesse Erlbaum
(jesse@vm.com) here at Vanguard Media.  The most original idea in this
module - the <TMPL_LOOP> - was entirely his.

   Fixes, Bug Reports, Optimizations and Ideas have been generously
provided by:

     Richard Chen
     Mike Blazer
     Adriano Nagelschmidt Rodrigues
     Andrej Mikus
     Ilya Obshadko
     Kevin Puetz
     Steve Reppucci
     Richard Dice
     Tom Hukins
     Eric Zylberstejn
     David Glasser
     Peter Marelas
     James William Carlson
     Frank D. Cringle
     Winfried Koenig
     Matthew Wickline
     Doug Steinwand
     Drew Taylor
     Tobias Brox
     Michael Lloyd
     Simran Gambhir
     Chris Houser <chouser@bluweb.com>
     Larry Moore
     Todd Larason
     Jody Biggs
     T.J. Mather
     Martin Schroth
     Dave Wolfe
     uchum
     Kawai Takanori
     Peter Guelich
     Chris Nokleberg
     Ralph Corderoy
     William Ward
     Ade Olonoh
     Mark Stosberg

   Thanks!

PUBLIC CVS SERVER
=================

   HTML::Template now has a publicly accessible CVS server provided by
SourceForge (www.sourceforge.net).  You can access it by going to
http://sourceforge.net/cvs/?group_id=1075.  Give it a try!

AUTHOR
======

   Sam Tregar, sam@tregar.com (you can also find me on the mailing list at
htmltmpl@lists.vm.com - join it by sending a blank message to
htmltmpl-subscribe@lists.vm.com).

LICENSE
=======

   HTML::Template : A module for using HTML Templates with Perl Copyright
(C) 2000 Sam Tregar (sam@tregar.com)

   This module is free software; you can redistribute it and/or modify it
under the terms of either:

   a) the GNU General Public License as published by the Free Software
Foundation; either version 1, or (at your option) any later version, or

   b) the "Artistic License" which comes with this module.

   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 either the GNU General Public
License or the Artistic License for more details.

   You should have received a copy of the Artistic License with this
module, in the file ARTISTIC.  If not, I'll be glad to provide one.

   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

Test module to make test files simpler.
***************************************

NAME
====

   HTML::Testing - Test module to make test files simpler.

SYNOPSIS
========

   A test file, simple.t may be created as follows:

     print "1..1\n";
     use strict;

     require HTML::FormatNroff;
     use HTML::Parse;
     require HTML::Testing;

     my $man_date = '20 Dec 97';
     my $name = "simple";

     my $html_source =<<END_INPUT;
     <HTML>
     <BODY>This is the body.</BODY>
     </HTML>
     END_INPUT

     my $expected = ".TH \"$name\" \"1\" \"$man_date\" \"FormatNroff\"  \n";
     $expected .=<<END_EXPECTED;
     .PP
     This is the body.
     END_EXPECTED

     my $tester = new HTML::Testing(name => $name,
     			        man_date => $man_date,
     			        project => 'FormatNroff',
     			        man_header => 1,
     			        expected => $expected,
     			        html_source => $html_source
     				output => 'TestOutput',
     			        );
     $tester->run_test();
     1;

DESCRIPTION
===========

   Running the test harness with this will result in the creation of the
files simple_expected.out, simple_actual.out and an html file
corresponding to the html_source (simple.html). In addition, the test will
return 'ok' if they are the same, and 'not ok' if not.

   If the attribute html_file is specified, then html will be sourced from
that file instead of html_source, and no html file will be created.

$testing = new HTML::Testing();
-------------------------------

   Create new test.

$testing->directory($value);
----------------------------

   Set the directory for output (HTML, actual and expected output files)
to $value.

$testing->run_test();
---------------------

   Run the test.

COPYRIGHT
=========

   Copyright (c) 1997 Frederick Hirsch. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Frederick Hirsch <f.hirsch@opengroup.org>

Contents
========

Tips and Tricks
Alternative Way To Do Global Variables, using __PACKAGE__
Global Variables Via Namespaces
Handling Queries in DBI
Handling Exits
Handling Errors
Development and Production Websites
Tips and Tricks
===============

   This document follows on from the Embperl/EmbperlObject introductory
tutorial. As you can see from that, Embperl/EmbperlObject enables extremely
powerful websites to be built using a very intuitive object-oriented
structure. Now, we'll look at some additional, "unofficial" techniques
which may also be useful in certain circumstances.

   This is a small collection of personal tricks which I have developed
over the course of months using EmbperlObject in my own websites. I hope
they are useful, or at least spur you on to develop your own frameworks
and share these with others.

   If you have any Tips & Tricks you want to share with the public please
send them to richter@dev.ecos.de .

Alternative Way To Do Global Variables, using __PACKAGE__
=========================================================

   In the process of developing a large website I have found it can be a
little onerous at times to use the Request object to pass around global
data. I would like to just create variables like $xxx rather than typing
$req->{xxx} all the time. It may not seem like much, but after a while
your code can start looking a lot more complex because of all the extra
brackets and suchlike. As a typical lazy programmer, I looked for a way to
simplify this.

   The method I am going to describe should be used with caution, because
it can increase memory useage rather dramatically if you're not careful.
The way I use it, no extra memory is used, but you do need to be aware of
the issues.

   Basically, you change the way you include files from `/base.html', so
that they are included into the same package as `/base.html':

     [- Execute ({inputfile => '*', package => __PACKAGE__}) -]

   You should only do this with HTML files which are included from
`/base.html', not with the files such as `subs.html' - those files have to
be in their own packages in order for Perl inheritance to work. You can't
use this technique with any files which are accessed via method calls.

   So how does this make things better? Well, since all these files now
share the same package, any variables which are created in one of the
files is accessible to any of the other files. This means that if you
create $xxx in `/init.html', then you can access $xxx in `/head.html' or
any other file. This effectively gives you global variables across all the
files which are included from `/base.html' into the same package as
`/base.html'.

   The thing you need to be careful of here is that if one of these files
is included more than once elsewhere on the website, then it will be
seperately compiled for that instance - thus taking up more memory. This
is the big caveat. As a rule, if your files are all just included once by
`/base.html', then you should be fine. Note that you'll also need to
change any calls to parent files, for example:

   `/contact/init.html'

     [- Execute ({inputfile => '../init.html', package => __PACKAGE__}) -]

     [-
     	# Do some setup specific to this subdirectory
     -]

   This is ok, since `../init.html' will still be compiled into the same
package as the rest of the files included from `/base.html', and so only
one version of it will exist in the Embperl cache. Thus memory usage is
not increased.

   I like this technique because it simplifies the look of my code, which
is important for projects containing complex algorithms. It is not the
"official" way to implement globals though, and should be used with care.

Global Variables Via Namespaces
===============================

   The previous section described a way to share variables between
different files which are included from `/base.html', by using the same
package across all the files. However this doesn't help us much when
dealing with the method files such as `subs.html', because these files
have to have their own packages - so we are back to square one.

   There is another way to share variables across even different packages,
and that is by using namespaces. For variables that need to be accessible
even from `subs.html', you could use a namespace which is specific to your
website. For example, if your website domain is mydomain.com, then you
could create variables using the form

     $mydomain::xxx = "hello";

   As long as you then make sure that you only use this namespace on this
website (and other websites on the same Apache web server use their own
namespaces), then you shouldn't get any conflicts. Once again, use this
with caution, since you introduce the possibility of inadvertently sharing
variables between completely different websites. For example, if you cut
and paste some useful code from one website to another, you will need to
make sure you change the namespace of any globals. Otherwise, you could
get some very obscure bugs, since different requests to the various
websites could conflict.

   You also need to be careful about variable initialization, since these
globals will now exist between different requests. So, it's possible that
if you don't re-initialize a global variable, then it may contain some
random value from a previous request. This can result in obscure bugs.
Just be careful to initialize all variables properly and you'll be fine.

   Finally, note that Embperl will only clean up variables which don't
have an explicit package (i.e. are in one of the packages automatically
set up by Embperl). Variables in other namespaces are not automatically
cleaned up. As a result, you need to pay closer attention to cleaning up
if you use your own namespaces. The safe way to clean up a variable is
simply to 'undef' it.

Handling Queries in DBI
=======================

   If you are like me, you probably use DBI extensively to enable your
dynamic websites. I have found the cleanup of queries to be onerous - e.g.
calling finish() on queries. If you don't do that, then you tend to get
warnings in your error log about unfinished queries.

   What I do these days is use a global hash, called e.g. %domain::query
(see the previous section for using namespaces to safely implement global
variables). Then, whenever I create a query, I use this variable. For
example:

     $domain::query{first_page} = $domain::dbh->prepare (qq{
     	SELECT *
     	FROM pages
     	WHERE page = 1
     	});
     $domain::query{first_page}->execute();
     my $first_page = $domain::query{first_page}->fetchrow_hashref();

   This little pattern, I find, makes all my queries easier to read and
keep track of. You give each one a name in the %domain::query hash that
makes sense. Then, at the end of each request, in the `/cleanup.html'
file, you can do something like this:

     while (($name, $query) = each (%domain::query))
     {
     	$query->finish();
     }
     $domain::dbh->disconnect();

   Once again, this method is not really the "official" way of doing
things in Embperl. You should use the Request object to pass around global
variables if you're not comfortable with the risks involved with
namespaces (e.g. conflicting websites on the same web server).

Handling Exits
==============

   You will often find that you want to terminate a page before the end.
This doesn't necessarily indicate an error condition; it can be just that
you've done all you want to do. When you do this, it is good to first
clean up, otherwise you can get annoying warnings showing up in your error
logs.

   I use the following framework. `/cleanup.html' is Executed from
`/base.html', and it is the last thing that is done. It calls the
cleanup() function in the `/subs.html' file:

   `/cleanup.html'

     [-
     	$subs->cleanup ();
     -]

   `/subs.html'

     [!
     	sub cleanup
     	{
     		while (($name, $query) = each (%domain::query))
     		{
     			$query->finish();
     		}
     		$domain::dbh->disconnect();
     	}

     sub clean_exit
     {
     	cleanup();
     	exit();
     }
     	!]

   Now, whenever I want to exit prematurely, I use a call to
$subs->clean_exit() rather than just exit(). This makes sure that the
queries and database connections are shut down nicely.

Handling Errors
===============

   The EMBPERL_OBJECT_FALLBACK directive in httpd.conf allows you to set a
file which will be loaded in the event that the requested file is not
found. This file should be relative to the same directory as `base.html'.

   I have found that making a special /errors/ directory is useful,
because it enables that special subdirectory to define its own `head.html'
file, `init.html' and so on.  So, I then just put this in `/notfound.html':

     [-
     	$http_headers_out{'Location'} = "/errors/";
     	clean_exit();
     -]

   See the previous section, "Handling Exits" for more on clean_exit().

Development and Production Websites
===================================

   When I am developing a website, I usually use at least two machines. I
have a workstation where I do developing and testing, and a separate
production server, which is accessed by the public. When I am finished
making changes to the development version of the website, I move it over
to the production server for testing there. However when I do this, I
usually don't copy it immediately over the existing production version,
because there are sometimes issues with Perl modules which haven't been
installed on the server, or other issues which break the code on a
different machine. So I use a separate virtual server and subdomain (which
is easy if you run your own DNS) to test the new version. For example if
the production version of the server is at www.mydomain.com, then I might
do testing on the production server under test.mydomain.com, or beta. or
whatever subdomain you like. This means you have to create a new virtual
server in the httpd.conf file. You also obviously create a new directory
for the test server (see below for an example).

   When you do all this, you end up with a very nice, isolated testing
environment on the same server as production. Obviously you hopefully did
all your major testing on your workstation, where you can crash the
machine and it doesn't matter too much. The production server testbed is a
last staging area before production, to get rid of any lingering glitches
or omissions. When you're sure it's all working correctly you just copy
the files from one directory tree (test) to another (production) on the
same machine. This test server can also be used as a beta of the new
production version. Friendly users can be given access to the new version,
while the old version is still running.

   One issue that comes up when you do this is that of databases. It is
very likely that you will be using a special test database rather than the
live one to test your new version. It would be very unwise to use a
production database for testing. So your production database might be
called "mydatabase", and the test one called "mydatabase_test". This is
fine, but it means that you have to remember to change the database name
in your code when you copy the files over to production. This is very
error prone. The solution is to set variables like the database name in
httpd.conf, by setting an environment variable. You just add it to the
virtual server section.

   Here is a real example of two virtual servers on the same production
machine, which use two different directories, separate log files and
different databases. The website is crazyguyonabike.com, which is a
journal of a bicycle ride I did across America in 1998. I decided to
expand the site to allow other cyclists to upload their own journals,
which resulted in substantial changes to the code. I wanted to keep the
original site up while testing the new version, which I put under
new.crazyguyonabike.com. Here are the relevant apache settings:

   `/etc/apache/httpd.conf'

     # The production server
     <VirtualHost 10.1.1.2:80>
     	ServerName www.crazyguyonabike.com
     	SSLDisable
     	ServerAdmin neil@nilspace.com
     	DocumentRoot /www/crazyguyonabike/com/htdocs
     	DirectoryIndex index.html
     	ErrorLog /www/crazyguyonabike/com/logs/error_log
     	TransferLog /www/crazyguyonabike/com/logs/access_log
     	ErrorDocument 403 /
     	ErrorDocument 404 /
     	PerlSetEnv WEBSITE_DATABASE crazyguyonabike
     	PerlSetEnv WEBSITE_ROOT /www/crazyguyonabike/com/htdocs
     	PerlSetEnv EMBPERL_DEBUG 0
     	PerlSetEnv EMBPERL_ESCMODE 0
     	PerlSetEnv EMBPERL_OPTIONS 16
     	PerlSetEnv EMBPERL_MAILHOST mail.nilspace.com
     	PerlSetEnv EMBPERL_OBJECT_BASE base.html
     	PerlSetEnv EMBPERL_OBJECT_FALLBACK notfound.html
     </VirtualHost>

     <VirtualHost 10.1.1.2:80>
     	ServerName crazyguyonabike.com
     	Redirect / http://www.crazyguyonabike.com
     </VirtualHost>

     # Set EmbPerl handler for main directory
     <Directory "/www/crazyguyonabike/com/htdocs/">
     	<FilesMatch ".*\.html$">
     		SetHandler  perl-script
     		PerlHandler HTML::EmbperlObject
     		Options     ExecCGI
     	</FilesMatch>
     </Directory>

     # The test server
     <VirtualHost 10.1.1.2:80>
     	ServerName new.crazyguyonabike.com
     	SSLDisable
     	ServerAdmin neil@nilspace.com
     	DocumentRoot /www/crazyguyonabike/com/new
     	Alias /pics /www/crazyguyonabike/com/pics
     	DirectoryIndex index.html
     	ErrorLog /www/crazyguyonabike/com/logs/new_error_log
     	TransferLog /www/crazyguyonabike/com/logs/new_access_log
     	ErrorDocument 401 /user/register/
     	ErrorDocument 403 /
     	ErrorDocument 404 /
     	PerlSetEnv WEBSITE_DATABASE crazyguyonabike_new
     	PerlSetEnv WEBSITE_ROOT /www/crazyguyonabike/com/new
     	PerlSetEnv EMBPERL_DEBUG 0
     	PerlSetEnv EMBPERL_ESCMODE 0
     	PerlSetEnv EMBPERL_OPTIONS 16
     	PerlSetEnv EMBPERL_MAILHOST mail.nilspace.com
     	PerlSetEnv EMBPERL_OBJECT_BASE base.html
     	PerlSetEnv EMBPERL_OBJECT_FALLBACK notfound.html
     </VirtualHost>

     # Set EmbPerl handler for new directory
     <Directory "/www/crazyguyonabike/com/new/">
     	<FilesMatch ".*\.html$">
     		SetHandler  perl-script
     		PerlHandler HTML::EmbperlObject
     		Options     ExecCGI
     	</FilesMatch>
     </Directory>

     # Restrict access to test server
     <Directory /www/crazyguyonabike/com/new>
     	AuthType Basic
     	AuthName CrazyTest
     	Auth_MySQL_DB http_auth
     	Auth_MySQL_Encryption_Types Plaintext
     	require valid-user
     	PerlSetEnv EMBPERL_OPTIONS 16
     	PerlSetEnv EMBPERL_MAILHOST mail.nilspace.com
     </Directory>

   Note that the test and production servers each get their own databases,
directories and log files.

   You can also see that I restrict access to the test server (which is
generally wise, unless you actually like hackers potentially screwing with
your head while testing). For basic authentication I use mod_auth_mysql,
which is available from the MySQL website. It is nice because it allows
you to authenticate based on a MySQL database.

   When you use PerlSetEnv to pass in variables, you access these
variables in your code as follows:

     $db_name = $ENV{WEBSITE_DATABASE};

   If you move those constants which differ between the test and
production versions of the same code into the httpd.conf file, then you
can just copy the files over from the test directories to the production
directory without any alterations. This cuts down on editing errors and
also documents specific constants in one place.

Author
======

   Neil Gunton neil@nilspace.com

Alternative HTML::Parser interface
**********************************

NAME
====

   HTML::TokeParser - Alternative HTML::Parser interface

SYNOPSIS
========

     require HTML::TokeParser;
     $p = HTML::TokeParser->new("index.html") || die "Can't open: $!";
     while (my $token = $p->get_token) {
         #...
     }

DESCRIPTION
===========

   The HTML::TokeParser is an alternative interface to the HTML::Parser
class.  It basically turns the HTML::Parser inside out.  You associate a
file (or any IO::Handle object or string) with the parser at construction
time and then repeatedly call $parser->get_token to obtain the tags and
text found in the parsed document.

   Calling the methods defined by the HTML::Parser base class will be
confusing, so don't do that.  Use the following methods instead:

$p = HTML::TokeParser->new( $file_or_doc );
     The object constructor argument is either a file name, a file handle
     object, or the complete document to be parsed.

     If the argument is a plain scalar, then it is taken as the name of a
     file to be opened and parsed.  If the file can't be opened for
     reading, then the constructor will return an undefined value and $!
     will tell you why it failed.

     If the argument is a reference to a plain scalar, then this scalar is
     taken to be the literal document to parse.  The value of this scalar
     should not be changed before all tokens have been extracted.

     Otherwise the argument is taken to be some object that the
     `HTML::TokeParser' can read() from when it needs more data.  Typically
     it will be a filehandle of some kind.  The stream will be read() until
     EOF, but not closed.

$p->get_token
     This method will return the next token found in the HTML document, or
     undef at the end of the document.  The token is returned as an array
     reference.  The first element of the array will be a (mostly) single
     character string denoting the type of this token: "S" for start tag,
     "E" for end tag, "T" for text, "C" for comment, "D" for declaration,
     and "PI" for process instructions.  The rest of the array is the same
     as the arguments passed to the corresponding HTML::Parser v2
     compatible callbacks (see HTML/Parser).  In
     summary, returned tokens look like this:

          ["S",  $tag, $attr, $attrseq, $text]
          ["E",  $tag, $text]
          ["T",  $text, $is_data]
          ["C",  $text]
          ["D",  $text]
          ["PI", $token0, $text]

     where $attr is a hash reference, $attrseq is an array reference and
     the rest is plain scalars.

$p->unget_token($token,...)
     If you find out you have read too many tokens you can push them back,
     so that they are returned the next time $p->get_token is called.

$p->get_tag( [$tag, ...] )
     This method returns the next start or end tag (skipping any other
     tokens), or undef if there are no more tags in the document.  If one
     or more arguments are given, then we skip tokens until one of the
     specified tag types is found.  For example:

          $p->get_tag("font", "/font");

     will find the next start or end tag for a font-element.

     The tag information is returned as an array reference in the same form
     as for $p->get_token above, but the type code (first element) is
     missing. A start tag will be returned like this:

          [$tag, $attr, $attrseq, $text]

     The tagname of end tags are prefixed with "/", i.e. end tag is
     returned like this:

          ["/$tag", $text]

$p->get_text( [$endtag] )
     This method returns all text found at the current position. It will
     return a zero length string if the next token is not text.  The
     optional $endtag argument specifies that any text occurring before the
     given tag is to be returned.  Any entities will be converted to their
     corresponding character.

     The $p->{textify} attribute is a hash that defines how certain tags
     can be treated as text.  If the name of a start tag matches a key in
     this hash then this tag is converted to text.  The hash value is used
     to specify which tag attribute to obtain the text from.  If this tag
     attribute is missing, then the upper case name of the tag enclosed in
     brackets is returned, e.g. "[IMG]".  The hash value can also be a
     subroutine reference.  In this case the routine is called with the
     start tag token content as its argument and the return value is
     treated as the text.

     The default $p->{textify} value is:

          {img => "alt", applet => "alt"}

     This means that <IMG> and <APPLET> tags are treated as text, and that
     the text to substitute can be found in the ALT attribute.

$p->get_trimmed_text( [$endtag] )
     Same as $p->get_text above, but will collapse any sequences of white
     space to a single space character.  Leading and trailing white space
     is removed.

EXAMPLES
========

   This example extracts all links from a document.  It will print one
line for each link, containing the URL and the textual description between
the <A>...</A> tags:

     use HTML::TokeParser;
     $p = HTML::TokeParser->new(shift||"index.html");

     while (my $token = $p->get_tag("a")) {
         my $url = $token->[1]{href} || "-";
         my $text = $p->get_trimmed_text("/a");
         print "$url\t$text\n";
     }

   This example extract the <TITLE> from the document:

     use HTML::TokeParser;
     $p = HTML::TokeParser->new(shift||"index.html");
     if ($p->get_tag("title")) {
         my $title = $p->get_trimmed_text;
         print "Title: $title\n";
     }

SEE ALSO
========

   See HTML/Parser,

COPYRIGHT
=========

   Copyright 1998-2000 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Tree - overview of HTML::TreeBuilder et al
******************************************

NAME
====

   HTML-Tree - overview of HTML::TreeBuilder et al

SYNOPSIS
========

     use HTML::TreeBuilder;
     my $tree = HTML::TreeBuilder->new();
     $tree->parse_file($filename);
      #
      # Then do something with the tree, using HTML::Element
      # methods -- for example $tree->dump
      #
      # Then:
     $tree->delete;

DESCRIPTION
===========

   HTML-Tree is a suite of Perl modules for making parse trees out of HTML
source.  It consists of mainly two modules, whose documentation you should
refer to: HTML/TreeBuilder, and
HTML/Element.

   HTML::TreeBuilder is the module builds the parse trees.  (It uses
HTML::Parser to do the work of breaking the HTML up into tokens.)

   The tree that TreeBuilder builds for you is made up of objects of the
class HTML::Element.

   If you find that you do not properly understand the documentation for
HTML::TreeBuilder and HTML::Element, it may be because you are unfamiliar
with tree-shaped data structures, or with object-oriented modules in
general.  I have written some articles for *The Perl Journal*
(`www.tpj.com') that seek to provide that background: my article "Scanning
HTML" in TPJ19; my article "Trees" in TPJ18, and my article "A User's View
of Object-Oriented Modules" in TPJ17.  The full text of those articles
will likely appear in a later version of this HTML-Tree module
distribution.

SEE ALSO
========

   See HTML/TreeBuilder, HTML/Element,
see HTML/Tagset, HTML/Parser,

   See HTML/DOMbo,

COPYRIGHT
=========

   Copyright 1995-1998 Gisle Aas; copyright 1999-2001 Sean M. Burke.

   The whole HTML-Tree distribution, of which this file is a part, is free
software; you can redistribute it and/or modify it under the same terms as
Perl itself.

AUTHOR
======

   Original HTML-Tree author Gisle Aas <gisle@aas.no>; current maintainer
Sean M. Burke, <sburke@cpan.org>

Parser that builds a HTML syntax tree
*************************************

NAME
====

   HTML::TreeBuilder - Parser that builds a HTML syntax tree

SYNOPSIS
========

     foreach my $file_name (@ARGV) {
       my $tree = HTML::TreeBuilder->new; # empty tree
       $tree->parse_file($file_name);
       print "Hey, here's a dump of the parse tree of $file_name:\n";
       $tree->dump; # a method we inherit from HTML::Element
       print "And here it is, bizarrely rerendered as HTML:\n",
         $tree->as_HTML, "\n";

       # Now that we're done with it, we must destroy it.
       $tree = $tree->delete;
     }

DESCRIPTION
===========

   This class is for HTML syntax trees that get built out of HTML source.
The way to use it is to:

   1. start a new (empty) HTML::TreeBuilder object,

   2. then use one of the methods from HTML::Parser (presumably with
$tree->parse_file($filename) for files, or with
$tree->parse($document_content) and $tree->eof if you've got the content
in a string) to parse the HTML document into the tree $tree.

   3. do whatever you need to do with the syntax tree, presumably
involving traversing it looking for some bit of information in it,

   4. and finally, when you're done with the tree, call $tree->delete to
erase the contents of the tree from memory.  This kind of thing usually
isn't necessary with most Perl objects, but it's necessary for TreeBuilder
objects.  See HTML/Element, for a more verbose
explanation of why this is the case.

METHODS AND ATTRIBUTES
======================

   Objects of this class inherit the methods of both HTML::Parser and
HTML::Element.  The methods inherited from HTML::Parser are used for
building the HTML tree, and the methods inherited from HTML::Element are
what you use to scrutinize the tree.  Besides this (HTML::TreeBuilder)
documentation, you must also carefully read the HTML::Element
documentation, and also skim the HTML::Parser documentation - probably
only its parse and parse_file methods are of interest.

   The following methods native to HTML::TreeBuilder all control how
parsing takes place; they should be set before you try parsing into the
given object.  You can set the attributes by passing a TRUE or FALSE value
as argument.  E.g., $root->implicit_tags returns the current setting for
the implicit_tags option, $root->implicit_tags(1) turns that option on,
and $root->implicit_tags(0) turns it off.

$root->implicit_tags(value)
     Setting this attribute to true will instruct the parser to try to
     deduce implicit elements and implicit end tags.  If it is false you
     get a parse tree that just reflects the text as it stands, which is
     unlikely to be useful for anything but quick and dirty parsing.
     (And, in current versions, $root-> Default is true.

     Implicit elements have the implicit() attribute set.

$root->implicit_body_p_tag(value)
     This controls an aspect of implicit element behavior, if implicit_tags
     is on:  If a text element (PCDATA) or a phrasal element (such as
     "<em>") is to be inserted under "<body>", two things can happen: if
     implicit_body_p_tag is true, it's placed under a new, implicit "<p>"
     tag.  (Past DTDs suggested this was the only correct behavior, and
     this is how past versions of this module behaved.)  But if
     implicit_body_p_tag is false, nothing is implicated - the PCDATA or
     phrasal element is simply placed under "<body>".  Default is false.

$root->ignore_unknown(value)
     This attribute controls whether unknown tags should be represented as
     elements in the parse tree, or whether they should be ignored.
     Default is true (to ignore unknown tags.)

$root->ignore_text(value)
     Do not represent the text content of elements.  This saves space if
     all you want is to examine the structure of the document.  Default is
     false.

$root->ignore_ignorable_whitespace(value)
     If set to true, TreeBuilder will try to avoid creating ignorable
     whitespace text nodes in the tree.  Default is true.  (In fact, I'd
     be interested in hearing if there's ever a case where you need this
     off, or where leaving it on leads to incorrect behavior.)

$root->p_strict(value)
     If set to true (and it defaults to false), TreeBuilder will take a
     narrower than normal view of what can be under a "p" element; if it
     sees a non-phrasal element about to be inserted under a "p", it will
     close that "p".  Otherwise it will close p elements only for other
     "p"'s, headings, and "form" (altho the latter may be removed in
     future versions).

     For example, when going thru this snippet of code,

          <p>stuff
          <ul>

     TreeBuilder will normally (with `p_strict' false) put the "ul" element
     under the "p" element.  However, with `p_strict' set to true, it will
     close the "p" first.

     In theory, there should be strictness options like this for other/all
     elements besides just "p"; but I treat this as a specal case simply
     because of the fact that "p" occurs so frequently and its end-tag is
     omitted so often; and also because application of strictness rules at
     parse-time across all elements often makes tiny errors in HTML coding
     produce drastically bad parse-trees, in my experience.

     If you find that you wish you had an option like this to enforce
     content-models on all elements, then I suggest that what you want is
     content-model checking as a stage after TreeBuilder has finished
     parsing.

$root->store_comments(value)
     This determines whether TreeBuilder will normally store comments found
     while parsing content into $root.  Currently, this is off by default.

$root->store_declarations(value)
     This determines whether TreeBuilder will normally store markup
     declarations found while parsing content into $root.  Currently, this
     is off by default.

     It is somewhat of a known bug (to be fixed one of these days, if
     anyone needs it?) that declarations in the preamble (before the "html"
     start-tag) end up actually *under* the "html" element.

$root->store_pis(value)
     This determines whether TreeBuilder will normally store processing
     instructions found while parsing content into $root - assuming a
     recent version of HTML::Parser (old versions won't parse PIs
     correctly).  Currently, this is off (false) by default.

     It is somewhat of a known bug (to be fixed one of these days, if
     anyone needs it?) that PIs in the preamble (before the "html"
     start-tag) end up actually *under* the "html" element.

$root->warn(value)
     This determines whether syntax errors during parsing should generate
     warnings, emitted via Perl's warn function.

     This is off (false) by default.

HTML AND ITS DISCONTENTS
========================

   HTML is rather harder to parse than people who write it generally
suspect.

   Here's the problem: HTML is a kind of SGML that permits "minimization"
and "implication".  In short, this means that you don't have to close
every tag you open (because the opening of a subsequent tag may implicitly
close it), and if you use a tag that can't occur in the context you seem
to using it in, under certain conditions the parser will be able to
realize you mean to leave the current context and enter the new one, that
being the only one that your code could correctly be interpreted in.

   Now, this would all work flawlessly and unproblematically if: 1) all
the rules that both prescribe and describe HTML were (and had been)
clearly set out, and 2) everyone was aware of these rules and wrote their
code in compliance to them.

   However, it didn't happen that way, and so most HTML pages are
difficult if not impossible to correctly parse with nearly any set of
straightforward SGML rules.  That's why the internals of HTML::TreeBuilder
consist of lots and lots of special cases - instead of being just a
generic SGML parser with HTML DTD rules plugged in.

BUGS
====

   * Hopefully framesets behave correctly now.  Email me if you find a
strange parse of documents with framesets.

   * Bad HTML code will, often as not, make for a bad parse tree.
Regrettable, but unavoidably true.

   * If you're running with implicit_tags off (God help you!), consider
that $tree->content_list probably contains the tree or grove from the
parse, and not $tree itself (which will, oddly enough, be an implicit
'html' element).  This seems counter-intuitive and problematic; but seeing
as how almost no HTML ever parses correctly with implicit_tags off, this
interface oddity seems the least of your problems.

BUG REPORTS
===========

   When a document parses in a way different from how you think it should,
I ask that you report this to me as a bug.  The first thing you should do
is copy the document, trim out as much of it as you can while still
producing the bug in question, and *then* email me that mini-document and
the code you're using to parse it, at `sburke@cpan.org'.  Include a note
as to how it parses (presumably including its $tree->dump output), and
then a *careful and clear* explanation of where you think the parser is
going astray, and how you would prefer that it work instead.

SEE ALSO
========

   See HTML/Parser, HTML/Element,
HTML/Tagset,

   See HTML/DOMbo,

COPYRIGHT
=========

   Copyright 1995-1998 Gisle Aas; copyright 1999, 2000 Sean M. Burke.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Original author Gisle Aas <gisle@aas.no>; current maintainer Sean M.
Burke, <sburke@cpan.org>

HTML validation by using nsgmls
*******************************

NAME
====

   HTML::Validator - HTML validation by using nsgmls

SYNOPSIS
========

     use HTML::Validator;
     $doc = new HTML::Validator($file);
     $doc->validate;
     print "Document is valid\n" if $doc->is_valid;

DESCRIPTION
===========

   This module can be used to validate HTML (or SGML) documents. For the
validation itself, it uses nsgmls and a set of document type definition
files (aka DTDs).

   HTML::Validator uses *libwww-perl* to validate remote files.

$doc->open($file)
     The file or url will be used as the document to validate. This method
     will be called implicitely if the constructor is called with an
     argument.

$doc->doctype
     Returns the document type.

     The return value is undefined if no filename has been passed to the
     object via the constructor or the open method.

     If the file has not been retrieved yet, it will be done.

     If you want to replace the document type, you must do so with the
     first call to this method. The document types are defined in
     $doc->{dtdmap}.

$doc->checkdtd
     Finds out the actual name of document type definition file that is
     used.  The return value is the name of the file, or undefined if the
     document type is not defined.

$doc->validate
     Validates the document. The return value is a reference to an array
     containing the modified output from nsgmls.

$doc->get_file
     Internal method to get the file and process the doctype information.

$doc->substitute_dtd_url
     If there is an URL in the doctype, it will be replaced to support
     nsgmls binaries that do not support URLs

$doc->replace_dtd
     Replaces the document type definition on the file. The new dtd is the
     first argument, or the default dtd if no argument is supplied.

$doc->errors
     Returns an error from nsgmls error output queue.

$doc->parse_errors
     Internal method to parse the raw nsgmsl output to a more readable
     form.  If you want to call this method more than once per object,
     purge the error output queue with $doc->errors first.

     This method will call a parser method to do the actual parsing, which
     is $doc->parser() by default. It can overriden by setting
     $doc->{parser}.

$doc->parser
     The default nsgmls output parser. This is called from parse_errors.
     If the return value is undef, then to parser is assumed to have found
     no errors. Otherwise the parser will return a reference to an array
     containing the errors.

$doc->is_valid
     Returns 1 if document is valid, 0 if document is invalid and undef if
     document hasn't been validated yet.

$doc->source
     Contains the source of the HTML file as a scalar.

$doc->message
     Contains the message queue. If called with an argument, places a new
     message to the queue, without an argument a message (if any) is
     removed.

     If the argument is '-1', the last message on the queue is returned.

$doc->reset
     Resets the object to original state so we can reuse it

VARIABLES
=========

$doc->{nsgmls}
     The used nsgmls binary

$doc->{catalog}
     The used catalog file

$doc->{message}
     Array of messages

$doc->{maxerr}
     The maximum number of errors. This is passed to nsgmls with the -E
     option

$doc->{doctype}
     The document type for the document

$doc->{defaultdtd}
     The default type for the document. By default this is 'html4'.

$doc->{dtdfile}
     The dtd used for the document

$doc->{dtdmap}
     The mapping for document types and the explicit document type
     definition strings

$doc->{parser}
     The custom parser to use. See the information for the parser method.

REQUIREMENTS
============

     HTML::Validator requires that

   * nsgmls is installed. It comes with James Clark's *sp* SGML toolkit,
     *http://www.jclark.com/sp/howtoget.htm*

   * you have a reasonable set of document type files. For this purpose,
     you can use W3C's sgml library at
     *http://validator.w3.org/sgml-lib.tar.gz*

SEE ALSO
========

   See LWP, `nsgmls' in this node

ACKNOWLEDGEMENTS
================

   Thanks go to:

     - Heikki Kantola <hezu@iki.fi>, for his help in the early testing
       phases and his excellent knowledge about HTML standards.

AVAILABILITY
============

   The latest version of HTML::Validator can be found from
*http://www.iki.fi/si/HTML-Validator/*.

   It is also available from CPAN (*http://www.perl.com/CPAN/*).

COPYRIGHT
=========

   HTML::Validator is (c) 1997-1999 Sami Itkonen <si@iki.fi>

   HTML::Validator is distributed under the GNU General Public License.

Standard theme generation, including sidebars and navigation bars
*****************************************************************

NAME
====

   HTML::WWWTheme - Standard theme generation, including sidebars and
navigation bars

SYNOPSIS
========

     use HTML::WWWTheme;
     my $Theme = new HTML::WWWTheme(@args);

REQUIREMENTS
============

   Nothing special - Perl 5 or newer.

DESCRIPTION
===========

   HTML::WWWTheme is a module that creates a standard sidebar and
implements local colour conventions.  It is used by the
Apache::SetWWWTheme module to enforce this through the server.  In fact,
the code in this module was originally contained within the SetWWWTheme
module, but at the suggestion of Tim Jenness, I separated this module to
allow CGI programs to create standard pages that would fit in with the
static pages that are automatically rewritten by the Apache module.  So,
static pages in the web tree are filtered through Apache::SetWWWTheme, and
CGI-generated pages are generated with the help of HTML::WWWTheme.  In
this manner, a consistent look and feel can be maintained in all pages.
Any changes in the structure of WWWTheme are automatically reflected in
both the CGI-generated and static pages.

   The new() function will return a reference to a Theme object.  It will
accept an array of arbitrary length as arguments.  Each element of this
array must be a fully qualified path to a configuration file.

   Configuration is accomplished in three ways.  First, one may pass
arguments to the new() function.  These arguments must be fully qualified
paths to a configuration file.  The syntax of the directives in this file
is simple:

     @DIRECTIVE=value;

     for example,

     @BGCOLOR=#FFFFFF;

   or, in the case of a directive that accepts a list, the values are
comma-separated and semi-colon terminated.  Escaped semi-colons will be
transformed into semi-colons, and will not terminate the directive.

     @DIRECTIVE=value1, value2, value3;

     @DIRECTIVE=value1, value2\; still going, value3;

   In the second example, the value2\; will be replaced with value2; in
the parsed text.

   for example,

     @INFO=<A HREF="here.html">Here</a>, <A HREF="there.html">There</a>;

   Second, the GetConfiguration() function may be passed a list of
full-paths to configuration files.  The GetConfiguration() function will
parse these files and set the appropriate values.

   Finally, one may use methods to directly change the settings of the
page before it is produced.  This is the recommended method, because it is
the most intuitive and the easiest to figure out when you're trying to
figure out someone else's code.  I use these methods extensively in my
Apache::SetWWWTheme module.

METHODS
-------

   The following are all the methods that may be used to control the
behaviour of the module.

GetConfiguration()
     This method takes the names of configuration files as arguments, and
     parses them one by one.  The configuration files contain a series of
     directives of the form

          @DIRECTIVE=value;

     or, in the case of a list-value (for example, with the infolinks that
     make up the links on the sidebar under "More Links" or "More Info")

          @DIRECTIVE=value1, value2, value3;

     Valid directives are listed, along with the corresponding method that
     performs the same method:

          @BLANKGIF          (see SetBlankGif() )
          @NAVBAR            (see SetUseNavBar() )
          @NEXTLINK          (see SetNextLink() )
          @LASTLINK          (see SetLastLink() )
          @UPLINK            (see SetUpLink() )
          @BGCOLOR           (see SetBGColor() )
          @BGPICTURE         (see SetBGPicture() )
          @BACKGROUND        (see SetBGPicture() )
          @ALINK             (see SetALink() )
          @LINK              (see SetLink() )
          @VLINK             (see SetVLink() )
          @SIDEBARTOP        (see SetSideBarTop() )
          @SIDEBARMENUTITLE  (see SetSidebarMenuTitle() )
          @SIDEBARSEARCHBOX  (see SetSideBarSearchBox() )
          @SIDEBARCOLOR      (see SetSideBarColor() )
          @SIDEBARWIDTH      (see SetSideBarWidth() )
          @NOSIDEBAREXTRAS   (see SetNoSideBarExtras() )
          @MORELINKSTITLE    (see SetMoreLinksTitle() )
          @INFO              (see SetInfoLinks() )
          @SIDEBARMENULINKS  (see SetSideBarMenuLinks() )

MakeFooter()
     Returns a footer to end the document.  Should be the last part of a
     dynamically generated HTML page.  See the example.

MakeHeader()
     Returns the header to the page.  Should be the first part of a
     dynamically generated HTML page.  See the example.

MakeNavBar()
     Returns a "previous/up/next" navigation bar.  This bar is designed to
     be sandwiched between the Header and the main body, and then later on
     between the end of the main body and the Footer.  See the example.

SetNextLink()
     Sets the "Next" link on the top/bottom nav bars.  Valid entries must
     be in the form of an HTML link,

          $Theme->SetNextLink('<A HREF="http://somewhere.com">somewhere</a>');

SetLastLink()
     Sets the "Last" or "Previous" link on the top/bottom nav bars.  Valid
     entries must be in the form of an HTML link,

          $Theme->SetLastLink('<A HREF="http://here.com">here</a>');

SetUpLink()
     Sets the "Up" link on the top/bottom nav bars.  Valid entries must be
     in the form of an HTML link,

          $Theme->SetUpLink('<A HREF="http://there.com">there</a>');

SetBGColor()
     Sets the background color for the page generated.  Valid entries must
     be in the form of a hex color code,

          $Theme->SetBGColor("#CCFFFF");

SetBGPicture()
     Sets the background image for the page generated.  Valid entries must
     be in the form of an absolute URL or URI.

          $Theme->SetBGPicture("/WWW/images/wallpaper.gif");

SetALink(), SetLink(), SetVLink()
     Sets the [a|v]link color for the <BODY> tag.  Valid entries must be
     in the form of a hex color code.

          $Theme->SetALink("#FFCCFF");
          $Theme->SetVLink("#FFCCFF");
          $Theme->SetLink ("#FFCCFF");

SetMoreLinksTitle()
     Sets the "More links" title on the sidebar.  By default it says "More
     links", but you may want to change it something else.

          $Theme->SetMoreLinksTitle("More useful links");

SetNoSideBarExtras()
     If this is true, it turns off the sidebar extras - those parts of the
     sidebar that aren't in the "SidebarMenuLinks" bit.

          $Theme->SetNoSideBarExtras("1");

SetHTMLStartString()
     Sets the HTML starting string.  This string should include the <HTML>
     opening tag, the <HEAD></HEAD> tags (and anything inbetween).
     Essentially, it should contain everything before the <BODY> tag.  If
     you are using this module for a CGI program, you should probably
     include the usual Content-Type: text/html sort of thing.

          $Theme->SetHTMLStartString("<HTML><HEAD><TITLE>This is my page.</TITLE></HEAD>");

SetHTMLEndString()
     Sets the HTML ending string.  This string should contain everything
     after the </BODY> tag, including such things as </HTML>.

          $Theme->SetHTMLEndString("</HTML>");

SetPrintableName()
     Sets the URL that is used to produce a printable version of the page.
     This is used to generate the small "click here to produce a printable
     version" link on the themed page.  How this is implemented is left to
     the caller.  Apache::SetWWWTheme produces an un-themed page, with all
     the link tags stripped out to discourage people from browsing in the
     printable pages and thus subverting the theming.

          $Theme->SetPrintableName("/printable/path/to/file.html");

SetText()
     Sets the text color for the <BODY> tag.  Valid entries must be in the
     form of a hex color code.

          $Theme->SetText("#000000");

SetSideBarColor()
     Sets the color of the generated sidebar.  Valid entries must be in
     the form of a hex color code.

          $Theme->SetSideBarColor("#FFCCFF");

SetSideBarWidth()
     Sets the width of the sidebar in pixels.  The default is 150.

          $Theme->SetSideBarWidth("120");

SetBlankGif()
     Sets the location of the blank gif.  A blank gif (blank.gif) is
     included in the distribution of this package.  Valid entries must be
     in the form of a URL or URI pointing to this file.

          $Theme->SetBlankGif("/WWW/images/blank.gif");

SetInfoLinks()
     Sets the value of the "info links".  Info links are designed to be
     user-configurable and fall under the "More Links" or "More
     information" section of the sidebar.  Valid entries must be in the
     form of a reference to an array of valid links.

          @array = ('<a href="here.html">here</a>', '<a href="there.html">there</a>');
          $Theme->SetInfoLinks(\@array);

SetSideBarTop()
     Sets the name appearing at the top of the sidebar.  This may be a
     link, if desired. Valid entries are strings.

          $Theme->SetSideBarTop('<A HREF="/">My Webserver</a>');

SetSearchTemplate()
     Sets the template to insert into the HTML for the side searchbox.  It
     should be self-contained HTML with the appropriate form methods etc.
     to interface with your local search engine.  Here is an example of a
     template:

          <B>Search JAC</B><BR><HR>
          <DIV align="center">
          <form method="POST" action="/cgi-bin/isearch">
          <input name="SEARCH_TYPE" type=hidden  value="ADVANCED">
          <input name="HTTP_PATH" type=hidden value="/WWW">
          <input name="DATABASE" type=hidden value="webindex">
          <input name="FIELD_1" type=hidden value="FULLTEXT">
          <input name="WEIGHT_1" type=hidden value= "1">
          <input name="ELEMENT_SET" type=hidden value="TITLE">
          <input name="MAXHITS" type=hidden value="50">
          <input name="ISEARCH_TERM" size="14" border="0">
          </form>
          </DIV>
          <H6><a href="http://www.yoursite.edu/search.html">More searching....</a></h6>

     Your template must be customized as appropriate for your engine, of
     course.  This template should be passed to the SetSearchTemplate
     function as one big string.

SetSideBarMenuLinks()
     Sets the value of the main sidebar links.  Valid entries must be in
     the form of a reference to an array of valid links.

          @array = ('<a href="here.html">here</a>', '<a href="there.html">there</a>');
          $Theme->SetSideBarMenuLinks(\@array);

SetSideBarMenuTitle()
     Sets the name of the main sidebar links.  Valid entries must be in
     the form of a string,

          $Theme->SetSideBarMenuTitle("Main Sections");

SetSideBarSearchBox()
     Sets the state of the sidebar searchbox.  If this value is set to
     anything true (in the perl sense), the searchbox will appear on the
     sidebar.

          $Theme->SetSideBarSearchBox("1");

SetUseNavBar()
     Sets the state of the top/bottom navbars.  If this value is set to
     anything true (in the perl sense), the top/bottom navbars will be
     place on the page.  These navbars will be created with the values set
     in the Set__Link() methods.

          $Theme->SetUseNavBar("1");

SetTopBottomLinks()
     Sets the links used in the top/bottom link bars.  It takes an array
     reference as data.

          @array = ('<a href="here.html">here</a>', '<a href="there.html">there</a>');
          $Theme->SetTopBottomLinks(\@array);

StartHTML()
     Returns the contents of the string set in SetHTMLStartString.  This
     is mostly just a placeholder for some time in the future when I get
     around to fully implementing this module to mimic the abilities of
     some other well-known modules.

          print $Theme->StartHTML();

EndHTML()
     Returns the contents of the string set in SetHTMLEndString.  This is
     mostly just a placeholder for some time in the future when I get
     around to fully implementing this module to mimic the abilities of
     some other well-known modules.

          print $Theme->EndHTML();

     The MakeNavBar() function may be used to create the top/bottom
     navigation bar.  This bar contains the previous/up/next links.  It
     takes no arguments, but uses the [next|last|up]link keys in the hash.

     Finally, the MakeFooter() function is used to end the html file.
     This function is absolutely necessary, as the page won't render
     without it!  The tables will not be finished, and very few browswers
     can deal with this.

     Here is a simple but functional example.  Notice that there are no
     <BODY> tags.  The header and footer take care of this.  Write your
     HTML as if you were writing between the <BODY> and </BODY> tags.:

          #!/usr/bin/perl -w

          use strict;
          use HTML::WWWTheme;

          # read in a few defaults
          my $Theme = new HTML::WWWTheme("/WWW/LookAndFeel", "/home/chogan/Lookandfeel");

          # set a few things by hand
          $Theme->SetBlankGif("/WWW/images/blank.gif");
          $Theme->SetBGColor("#FFFFFF");
          $Theme->SetHTMLStartString("<HTML><HEAD><TITLE>My Example.</TITLE></HEAD>");
          $Theme->SetHTMLEndString("</HTML>");

          # make the header, navbar, body, navbar, footer.
          print $Theme->StartHTML();
          print $Theme->MakeHeader();
          print $Theme->MakeTopBottomBar();
          print $Theme->MakeNavBar();
          print "This is the body of my file.  Isn't it groovy?";
          print $Theme->MakeNavBar();
          print $Theme->MakeTopBottomBar();
          print $Theme->MakeFooter();
          print $Theme->EndHTML();
          exit 0;

SEE ALSO
========

   See Apache/SetWWWTheme,

AUTHOR
======

   Copyright (C) 2000 Chad Hogan (chogan@uvastro.phys.uvic.ca).  Copyright
(C) 2000 Joint Astronomy Centre

   All rights reserved.  HTML::WWWTheme 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.

   HTML::WWWTheme 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 HTML::WWWTheme; see the file gpl.txt.  If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.

creates date entry widgets for HTML forms.
******************************************

NAME
====

   HTML::Widgets::DateEntry - creates date entry widgets for HTML forms.

SYNOPSIS
========

     use HTML::Widgets::DateEntry;

     $de = new HTML::Widgets::DateEntry(
     				     year      => ['date_year',  $date_year],
     				     month     => ['date_month', $date_month],
     				     day       => ['date_day',   $date_day],
     				     separator => '/',
     				     pre_year  => 1,
     				     post_year => 1,
     				     -iso      => 1,
     				    );

     print $de->render_widget;

DESCRIPTION
===========

   HTML::Widgets::DateEntry is a simple module to generate HTML date entry
widgets.

   Currently generates widgets that look like:

     [YYYY]/[MM]/[DD]

   Will be able to generate

     [MM]/[DD]/[YYYY]

     [YYYY]/[MM]

     [MM]/[YYYY]

     [YYYY]

new(% );
     Use like     $de = new HTML::Widgets::DateEntry(year =>
     ['date_year',$year], month => ['date_month',$month], day =>
     ['date_day',$day]);

     returns a date entry widget object with the fields named as specified.

     if defaults are not provided, values from localtime will be used.

     this will get better :-)

render_widget()
     Use like     print $de->render_widget;

     returns a string representing an HTML date entry widget.  with the
     fields named as specified, and defaults set as specified when the
     object was created.

     this will get better :-)

COPYRIGHT
=========

     COPYRIGHT  2000 THE REGENTS OF THE UNIVERSITY OF MICHIGAN
     ALL RIGHTS RESERVED

     PERMISSION IS GRANTED TO USE, COPY, CREATE DERIVATIVE WORKS
     AND REDISTRIBUTE THIS SOFTWARE AND SUCH DERIVATIVE WORKS FOR
     NON-COMMERCIAL EDUCATION AND RESEARCH PURPOSES, SO LONG AS NO
     FEE IS CHARGED, AND SO LONG AS THE COPYRIGHT NOTICE ABOVE,
     THIS GRANT OF PERMISSION, AND THE DISCLAIMER BELOW APPEAR IN
     ALL COPIES MADE; AND SO LONG AS THE NAME OF THE UNIVERSITY
     OF MICHIGAN IS NOT USED IN ANY ADVERTISING OR PUBLICITY
     PERTAINING TO THE USE OR DISTRIBUTION OF THIS SOFTWARE
     WITHOUT SPECIFIC, WRITTEN PRIOR AUTHORIZATION.

     THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION AS
     TO ITS FITNESS FOR ANY PURPOSE,  AND WITHOUT WARRANTY OF ANY
     KIND,  EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
     LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
     FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF THE
     UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE FOR ANY DAMAGES,
     INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
     DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR IN
     CONNECTION WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN
     OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

     ( This program is free software; you can redistribute it and/or
       modify it under the same terms as Perl itself. )

SEE ALSO
========

   perl(1)

AUTHOR
======

   Hugh Kennedy <kennedyh@engin.umich.edu>

     __|   \   __|  \ |
         (     _ \  _|  .  |
        \___|_/  Web Systems

Builds an HTML menu
*******************

NAME
====

   HTML::Widgets::Menu - Builds an HTML menu

SYNOPSIS
========

     use HTML::Widgets::Menu;
     my $main=HTML::Widgets::Menu->new(
            home	=> "/users/frankie/",

     format	=> {
        default=>{
             # default format options #
        },
        0=>{
           #level 0 format  options#
        }
        # more levels
     },

     menu=> [
        item1=>{
            url=>"url for item 1",
            menu=>[
                  item1_1=>'url for item 1_1'
            ]
        },
        item2=>"url for item 2"
        # more items
     ],

     # this is experimental

     allowed => sub {
         my ($url)=shift;
         my $user=$r->connection->user();
     			return 1 unless defined $user;
     			return ($user eq "frankie"  && $url =~/^intranet/);
     }
           );

     print "<h1>$menu->title</h1>",
     print "<h2>$menu->path</h2>",
         print $menu->html;

DESCRIPTION
===========

   This module will help you build a menu for your HTML site.  You can use
with CGI or any mod_perl module. I use it from HTML::Mason.  Every time
you request to show a menu it will return the HTML tags.  It's smart
enough it will highlight the current active items.

   You can see an example of this here: http://www.etsetb.upc.es/~frankie

   This software is more mature that latest version. It works fine for me
and is used in production sites. The very first version was almost unusable
if you didn't had very strict rules for creating the menu, now it's much
improved and useful. Tell me if you like it or not.

   You can send me patches, bugs or suggestions.

   This software is provided as is and you're using it at your own risk.
You agree to use it with the same license of perl itself.

   Drawing a menu is a matter of :     the items of the menu     the
format you want it to have

   You also must supply the home directory for all the web you want to add
this menu.

ITEMS
-----

   The items is a list.

   For example, a simple menu could be:

     my @menu=(
           homepage   =>'.',
           "my links" =>"links.html"
     );

   You can add depth to the menu:

     my @menu=(
         homepage   => '.',
         "my links" => {
                   url=>"links/",
                   menu=>[
                         perl  =>"perl_link.html",
                         "movies I like"=>'movies.html'
                   ],
          about=>"about.html"
      );

   For every level you add instead of the url you must supply a reference
to a hash with the url and the submenu.  Now you can get this menu printed
in html easily and get the list of active items.

   my $main=HTML::Widgets::Menu->new(menu=>\@menu,home=>"/users/frankie/");

   print $main->html(); # this renders the html my @active_items=
@{$main->active}; # list of active items

   If the url of the item is only the name of a directory (the final / is
not necessary), the path is added to the submenu. For the example above
you must write the files:     index.html     links/index.html
links/perl_link.thml     links/movies.html     about.html

   The format is the way you tell how to show the items of the menu It's a
hash where you define the options.  There should be a default entry and
numbered entries for every level, starting with 0.

   Options available (with defaults):   max_depth => 1,         # max
number of depth shown if items are not active   start => ", #html to put
at the start of the level   end => ", #html to add at the end of the level
 font=>'<FONT>',   active_item_start => '<B><I>',   active_item_end =>
'</B></I>',   inactive_item_start => ",   inactive_item_end => ",
text_placeholder => '<text>',            # example : <IMG SRC="<text>.gif"
ALT="<text>">            #                     -----           -----
link_args=>",            # put javascript options here or other args
    # for the <A HREF tag   indent => 8, 			# pixels for the
indentation

     auto_br => 1, # Adds a <br> at the end of every line [default 1]

   Example: my %format={    default=>{         max_depth=>2,
font=>"<FONT SIZE=2>\n",         active_item_start=>"<IMG
SRC=\"/users/frankie/img/blue_arrow.gif\"             BORDER=0
WIDTH=6><B><I><FONT COLOR=\"BLUE\">",
active_item_end=>"</FONT></I></B>\n",         indent=>20     },     0=>{
     inactive_item_start=>"<FONT SIZE=\"5\">",
inactive_item_end=>"</FONT>",         text_placeholder=>"<IMG
SRC=\"<text>.gif\".gif>",         link_args=>"onmouseover='javascript
thingie'",     },     1=>{         indent=>10     } };

   Try it like this:

   my $main=HTML::Widgets::Menu->new(format=>\%format
              menu=>\@menu,
home=>"/users/frankie");

   When you want to request the html that shows the menu you must call the
html method. It will build it using home, format and menu. The final links
will always be related to the current URL.

   The pixel indentation is done using the url /img/point.gif.

   If you define an active format with an image like this:
active_item_start=> ' <IMG SRC="arrow.gif" WIDTH="10">'

   this WIDTH is added to the indentation so it looks pretty cool in the
screen:

     not active
     another url
         => this is the active
     another one

     The other items have been indented the width of the image, in addition
     to the indent tag in the format.

   The activation of the items work automagically reading the environment
variable provided by the web server: $ENV{REQUEST_URI}

Active Items
------------

   The active method returns a usefull thing: the active items of the
menu. In the former example if the user is in the url:  "movies.html" it
will return a reference to a list like this: 	"my_links"=>"links"
"movies I like "=>"links/movies.html"

   What can I do with the active items ?

   once the menu is built you can retrieve its active items this way:

     $menu->active;

   This method returns an array with the items and links this way:

     item1 , link1 , item2, link2

   You can use it to build a title or path like this:

     print $menu->html; # that builds the menu

     my $title="Main Title";
     my $path="";
     my $item;
     foreach (@{$menu->active}) {
     	$item=$_ and next unless defined $item;

     $title.=" - $item";

     $path.="/" if length $path;
     $path.="<A HREF=\"$_\">$item</A>";

     undef $item;

     }
     # now I have a title and path variables

Experimental Features
---------------------

   * see test.pl file for a cool feature that lets you read menu data from
     a database !

   * There is another new feature that lets you do authorization. So you
     can have some users access some menus and other don't.

PLEASE
------

     Please, tell me you're using it. I'll accept requests, comments,
     suggestions, bug patches.

AUTHOR
======

   Francesc Guasch-Ortiz	 frankie@etsetb.upc.es

SEE ALSO
========

   perl(1).  mod_perl

Perl module for building searches returning HTML
************************************************

NAME
====

   HTML::Widgets::Search - Perl module for building searches returning HTML

SYNOPSIS
========

     <%perl>
     use HTML::Widgets::Search;
     my $search=HTML::Widgets::Search->new(
                query => "SELECT idCustomer,name               ".
                         " FROM customers WHERE name LIKE 'a%' ".
                         " ORDER BY name                       ",
             field_id => "idCustomer",
                limit => 10,
          form_fields => \%ARGS,
                  dbh => $dbh
     );
     </%perl>

     <% $search->n_found %> customers found
     <% $search->current_start %> to <% $search -> current_end %><BR>

     <% $search->head %>
         <TABLE WIDTH="90%">
             <%perl>
                  $search->render_table(
                      link=>"http://www.me.com/show_customer.html"
                  );
             </%perl>
         </TABLE>

     <A HREF="search_customer.html<% $search->next %>">next</A>

     <A HREF="search_customer.html<% $search->prev %>">previous</A>

     <% $search->prev(submit => '<INPUT 	TYPE="IMAGE"
                                 SRC="/img/prev.gif"
                                 NAME="previous" BORDER=0>')
     	%>
     %#################################################################3
     <TABLE>
     % while (my @row=$search->fetchrow) {
         <TR><TD>
             <% join "</TD><TD>", @row %>
         </TD></TR>
     % }
     </TABLE>

DESCRIPTION
===========

     The programmer designs a html form with some field values, then
     you can write a sql query using those fields.

     The constuctor requires a SQL statement and a valid DBI object.

     render_table returns a HTML table with the results , if a link
     is provided every field of the table has that link. If a field_id
     	is provided the link adds that field as a parameter. This field
     	must be the first field of the select query and is discarded in
     	the render.

     Supports native mysql limit clauses. For other DBs skips untill start
     and fetches until limit.

     Give it a try, the synopsis may help you start.
     Let me know if it's useful for or whatever you want to tell me.

TODO
====

     Improve the docs. You can help me !

AUTHOR
======

   Francesc Guasch  frankie@etsetb.upc.es

SEE ALSO
========

   perl(1) , DBI.

Determine the Web browser, version, and platform from an HTTP user agent string
*******************************************************************************

NAME
====

   HTTP::BrowserDetect - Determine the Web browser, version, and platform
from an HTTP user agent string

SYNOPSIS
========

     use HTTP::BrowserDetect;

     my $browser = new HTTP::BrowserDetect($user_agent_string);

     # Detect operating system
     if ($browser->windows) {
       if ($browser->winnt) ...
       if ($brorwser->win95) ...
     }
     print $browser->mac;

     # Detect browser vendor and version
     print $browser->netscape;
     print $browser->ie;
     if (browser->major(4)) {
     	if ($browser->minor() > .5) {
     	    ...
     	}
     }
     if ($browser->version() > 4) {
       ...;
     }

     # Process a different user agent string
     $browser->user_agent($another_user_agent_string);

DESCRIPTION
===========

   The HTTP::BrowserDetect object does a number of tests on an HTTP user
agent string.  The results of these tests are available via methods of the
object.

   This module is based upon the JavaScript browser detection code
available at
*http://www.mozilla.org/docs/web-developer/sniffer/browser_type.html*.

CREATING A NEW BROWSER DETECT OBJECT AND SETTING THE USER AGENT STRING
----------------------------------------------------------------------

new HTTP::BrowserDetect($user_agent_string)
     The constructor may be called with a user agent string specified.
     Otherwise, it will use the value specified by $ENV{'HTTP_USER_AGENT'},
     which is set by the web server when calling a CGI script.

     You may also use a non-object-oriented interface.  For each method,
     you may call HTTP::BrowserDetect::method_name().  You will then be
     working with a default HTTP::BrowserDetect object that is created
     behind the scenes.

user_agent($user_agent_string)
     Returns the value of the user agent string.  When called with a
     parameter, it resets the user agent and reperforms all tests on the
     string.  This way you can process a series of user agent strings (from
     a log file, perhaps) without creating a new HTTP::BrowserDetect object
     each time.

DETECTING BROWSER VERSION
-------------------------

major($major)
     Returns the integer portion of the browser version.  If passed a
     parameter, returns true if it equals the browser major version.

minor($minor)
     Returns the decimal portion of the browser version as a
     *floating-point number* less than 1.  For example, if the version is
     4.05, this method returns .05; if the version is 4.5, this method
     returns .5.  *This is a change in behavior from previous versions of
     this module, which returned a string*.

     If passed a parameter, returns true if equals the minor version.

     On occasion a version may have more than one decimal point, such as
     'Wget/1.4.5'. The minor version does not include the second decimal
     point, or any further digits or decimals.

version($version)
     Returns the version as a floating-point number.  If passed a
     parameter, returns true if it is equal to the version specified by
     the user agent string.

beta($beta)
     Returns any the beta version, consisting of any non-numeric characters
     after the version number.  For instance, if the user agent string is
     'Mozilla/4.0 (compatible; MSIE 5.0b2; Windows NT)', returns 'b2'.  If
     passed a parameter, returns true if equal to the beta version.

DETECTING OS PLATFORM AND VERSION
---------------------------------

   The following methods are available, each returning a true or false
value.  Some methods also test for the operating system version.

     windows win16 win3x win31 win95 win98 winnt win32 win2k winme
     mac mac68k macppc
     os2
     unix
     sun sun4 sun5 suni86 irix irix5 irix6 hpux hpux9 hpux10
     aix aix1 aix2 aix3 aix4 linux sco unixware mpras reliant
     dec sinix freebsd bsd
     vms
     amiga

   It may not be possibile to detect Win98 in Netscape 4.x and earlier.
On Opera 3.0, the userAgent string includes "Windows 95/NT4" on all Win32,
so you can't distinguish between Win95 and WinNT.

os_string()
     Returns one of the following strings, or undef.  This method exists
     solely for compatibility with the *HTTP::Headers::UserAgent* module.

          Win95, Win98, WinNT, Mac, Win3x, OS2, Unix, Linux

DETECTING BROWSER VENDOR
------------------------

   The following methods are available, each returning a true or false
value.  Some methods also test for the browser version, saving you from
checking the version separately.

     netscape nav2 nav3 nav4 nav4up nav45 nav45up navgold nav6 nav6up
     gecko
     ie ie3 ie4 ie4up ie5 ie55
     neoplanet neoplanet2
     mosaic
     aol aol3 aol4 aol5 aol6
     webtv
     opera
     lynx
     emacs
     staroffice
     lotusnotes
     icab
     konqueror
     java

   Netscape 6, even though its called six, in the userAgent string has
version number 5.  The nav6 and nav6up methods correctly handle this quirk.

browser_string()
     Returns one of the following strings, or undef.

     Netscape, MSIE, WebTV, AOL Browser, Opera, Mosaic, Lynx

DETECTING OTHER DEVICES
-----------------------

   The following methods are available, each returning a true or false
value.

     wap
     audrey
     iopener
     palm
     avantgo

DETECTING ROBOTS
----------------

robot()
     Returns true if the user agent appears to be a robot, spider,
     crawler, or other automated Web client.

     The following additional methods are available, each returning a true
     or false value.  This is by no means a complete list of robots that
     exist on the Web.

          wget
          getright
          yahoo
          altavista
          lycos
          infoseek
          lwp
          webcrawler
          linkexchange
          slurp
          google

AUTHOR
======

   Lee Semel, lee@semel.net

SEE ALSO
========

   "The Ultimate JavaScript Client Sniffer, Version 3.0",
*http://www.mozilla.org/docs/web-developer/sniffer/browser_type.html*.

   perl(1), see HTTP/Headers,
HTTP/Headers/UserAgent.

COPYRIGHT
=========

   Copyright 1999-2001 Lee Semel.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Cookie storage and management
*****************************

NAME
====

   HTTP::Cookies - Cookie storage and management

SYNOPSIS
========

     use HTTP::Cookies;
     $cookie_jar = HTTP::Cookies->new;

     $cookie_jar->add_cookie_header($request);
     $cookie_jar->extract_cookies($response);

DESCRIPTION
===========

   Cookies are a general mechanism which server side connections can use
to both store and retrieve information on the client side of the
connection.  For more information about cookies refer to
<URL:http://www.netscape.com/newsref/std/cookie_spec.html> and
<URL:http://www.cookiecentral.com/>.  This module also implements the new
style cookies described in *draft-ietf-http-state-man-mec-08.txt*.  The
two variants of cookies are supposed to be able to coexist happily.

   Instances of the class *HTTP::Cookies* are able to store a collection
of Set-Cookie2: and Set-Cookie: headers and are able to use this
information to initialize Cookie-headers in HTTP::Request objects.  The
state of a *HTTP::Cookies* object can be saved in and restored from files.

METHODS
=======

   The following methods are provided:

$cookie_jar = HTTP::Cookies->new;
     The constructor takes hash style parameters.  The following
     parameters are recognized:

          file:            name of the file to restore cookies from and save cookies to
          autosave:        save during destruction (bool)
          ignore_discard:  save even cookies that are requested to be discarded (bool)

     Future parameters might include (not yet implemented):

          max_cookies               300
          max_cookies_per_domain    20
          max_cookie_size           4096

          no_cookies   list of domain names that we never return cookies to

$cookie_jar->add_cookie_header($request);
     The add_cookie_header() method will set the appropriate Cookie:-header
     for the HTTP::Request object given as argument.  The $request must
     have a valid url attribute before this method is called.

$cookie_jar->extract_cookies($response);
     The extract_cookies() method will look for Set-Cookie: and
     Set-Cookie2: headers in the *HTTP::Response* object passed as
     argument.  Any of these headers that are found are used to update the
     state of the $cookie_jar.

$cookie_jar->set_cookie($version, $key, $val, $path, $domain, $port, $path_spec, $secure, $maxage, $discard, \%rest)
     The set_cookie() method updates the state of the $cookie_jar.  The
     $key, $val, $domain, $port and $path arguments are strings.  The
     $path_spec, $secure, $discard arguments are boolean values. The
     $maxage value is a number indicating number of seconds that this
     cookie will live.  A value <= 0 will delete this cookie.  %rest
     defines various other attributes like "Comment" and "CommentURL".

$cookie_jar->save( [$file] );
     This method file saves the state of the $cookie_jar to a file.  The
     state can then be restored later using the load() method.  If a
     filename is not specified we will use the name specified during
     construction.  If the attribute *ignore_discared* is set, then we
     will even save cookies that are marked to be discarded.

     The default is to save a sequence of "Set-Cookie3" lines.
     "Set-Cookie3" is a proprietary LWP format, not known to be compatible
     with any browser.  The *HTTP::Cookies::Netscape* sub-class can be
     used to save in a format compatible with Netscape.

$cookie_jar->load( [$file] );
     This method reads the cookies from the file and adds them to the
     $cookie_jar.  The file must be in the format written by the save()
     method.

$cookie_jar->revert;
     This method empties the $cookie_jar and re-loads the $cookie_jar from
     the last save file.

$cookie_jar->clear( [$domain, [$path, [$key] ] ]);
     Invoking this method without arguments will empty the whole
     $cookie_jar.  If given a single argument only cookies belonging to
     that domain will be removed.  If given two arguments, cookies
     belonging to the specified path within that domain are removed.  If
     given three arguments, then the cookie with the specified key, path
     and domain is removed.

$cookie_jar->scan( \&callback );
     The argument is a subroutine that will be invoked for each cookie
     stored in the $cookie_jar.  The subroutine will be invoked with the
     following arguments:

          0  version
          1  key
          2  val
          3  path
          4  domain
          5  port
          6  path_spec
          7  secure
          8  expires
          9  discard
           10  hash

$cookie_jar->as_string( [$skip_discard] );
     The as_string() method will return the state of the $cookie_jar
     represented as a sequence of "Set-Cookie3" header lines separated by
     "\n".  If $skip_discard is TRUE, it will not return lines for cookies
     with the *Discard* attribute.

SUB CLASSES
===========

   We also provide a subclass called *HTTP::Cookies::Netscape* which loads
and saves Netscape compatible cookie files.  You should be able to have
LWP share Netscape's cookies by constructing your $cookie_jar like this:

     $cookie_jar = HTTP::Cookies::Netscape->new(
                       File     => "$ENV{HOME}/.netscape/cookies",
                       AutoSave => 1,
                   );

   Please note that the Netscape cookie file format is not able to store
all the information available in the Set-Cookie2 headers, so you will
probably loose some information if you save in this format.

COPYRIGHT
=========

   Copyright 1997-1999 Gisle Aas

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

A WebDAV client library for Perl5
*********************************

NAME
====

   HTTP::DAV - A WebDAV client library for Perl5

SYNOPSIS
========

     use HTTP::DAV;

     $dav = HTTP::DAV->new;
     $dav->credentials( "pcollins", "mypass", "http://localhost/" );
     $resource = $dav->new_resource( -uri => "http://localhost/dav/myfile.txt" );

     $response = $resource->lock;
     $response = $resource->put("New file contents\n");
     print "BAD PUT\n" unless $response->is_success;
     $response = $resource->unlock;

     $resource->propfind;
     print "BAD PROPFIND\n" unless $response->is_success;
     $getlastmodified = $resource->get_property( "getlastmodified" );
     print "Last modified $getlastmodified\n";

     See HTTP::DAV::Resource for all of the operations allowed against a resource.

DESCRIPTION
===========

   This is DAV.pm (or HTTP::DAV), a Perl5 library for interacting and
modifying content on webservers using the WebDAV protocol. Now you can
LOCK, DELETE and PUT files and much more on a DAV-enabled webserver. Learn
more about WebDAV at http://www.webdav.org/

new
     Creates a new DAV client

          $dav = HTTP::DAV->new()

new_resource
     Creates a new resource object with which to play.

          $dav->new_resource( -uri => "http://..." );

as_string
     Method returning a textual representation of the request.  Mainly
     useful for debugging purposes. It takes no arguments.

          e.g.
          $dav->as_string()

COPYRIGHT
=========

   Copyright 2000, Patrick Collins.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Represents a WebDAV Lock.
*************************

NAME
====

   HTTP::DAV::Lock - Represents a WebDAV Lock.

SYNOPSIS
========

     Need example

DESCRIPTION
===========

SEE ALSO
========

   See HTTP/Headers, HTTP/Message,
HTTP/Request/Common,

COPYRIGHT
=========

   Copyright 2000 Patrick Collins.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Represents and interfaces with WebDAV Resources
***********************************************

NAME
====

   HTTP::DAV::Resource - Represents and interfaces with WebDAV Resources

SYNOPSIS
========

   Sample

DESCRIPTION
===========

   Description here

CONSTRUCTORS
============

new
     Returns a new resource represented by the URI.

     $r = HTTP::DAV::Resource->new(         -uri => $uri,
     -LockedResourceList => $locks,         -Comms => $comms      );

     On creation a Resource object needs 2 other objects passed in:

     1. a `ResourceList' Object. This list will be added to if you lock
     this Resource.

     2. a `Comms' Object. This object will be used for HTTP communication.

METHODS
=======

get/GET
     Performs an HTTP GET and returns a DAV::Response object.

          $response = $resource->get;
          print $resource->get_content if ($response->is_success);

put/PUT
     Performs an HTTP PUT and returns a DAV::Response object.

     $response = $resource->put( $string );

     $string is be passed as the body.

          e.g.
          $response = $resource->put($string);
          print $resource->get_content if ($response->is_success);

     Will use a Lock header if this resource was previously locked.

copy
     Not implemented

move
     Not implemented

delete
     Performs an HTTP DELETE and returns a DAV::Response object.

          $response = $resource->delete;
          print "Delete successful" if ($response->is_success);

     Will use a Lock header if this resource was previously locked.

options
     Performs an HTTP OPTIONS and returns a DAV::Response object.

          $response = $resource->options;
          print "Yay for PUT!" if $resource->is_option("PUT");

mkcol
     Performs a WebDAV MKCOL request and returns a DAV::Response object.

          $response = $resource->mkcol;
          print "MKCOL successful" if ($response->is_success);

     Will use a Lock header if this resource was previously locked.

proppatch
     Not implemented

propfind
     Performs a WebDAV PROPFIND request and returns a DAV::Response object.

          $response = $resource->propfind;
          if ($response->is_success) {
             print "PROPFIND successful\n";
             print $resource->get_property("displayname") . "\n";
          }

     A successful PROPFIND fills the object with much data about the
     Resource.  Including:    displayname    ...     TODO

lock
     Performs a WebDAV LOCK request and returns a DAV::Response object.

          $resource->lock(
                 -owner   => "Patrick Collins",
                 -depth   => "Infinity"
                 -scope   => "exclusive",
                 -type    => "write"
                 -timeout => TIMEOUT',
              )

     lock takes the following arguments.

     owner - Indicates who locked this resource

     The default value is:  DAV.pm/v$DAV::VERSION ($$)

          e.g. DAV.pm/v0.1 (123)

     If you use a URL as the owner, the module will automatically indicate
     to the server that is is a URL (<D:href>http://...</D:href>)

     depth - Indicates the depth of the lock.

     Legal values are 0 or Infinity. (1 is not allowed).

     The default value is Infinity.

     A lock value of 0 on a collection will lock just the collection but
     not it's members, whereas a lock value of Infinity will lock the
     collection and all of it's members.

     scope - Indicates the scope of the lock.

     Legal DAV values are "exclusive" or "shared".

     The default value is exclusive.

     See section 6.1 of RFC2518 for a description of shared vs. exclusive
     locks.

     type - Indicates the type of lock (read, write, etc)

     The only legal DAV value currently is "write".

     The default value is write.

     timeout - Indicates when the lock will timeout

     The timeout value may be one of, an Absolute Date, a Time Offset from
     now, or the word "Infinity".

     The default value is "Infinity".

     The following are all valid timeout values:

     Time Offset:     30s          30 seconds from now     10m
     ten minutes from now     1h           one hour from now     1d
       tomorrow     3M           in three months     10y          in ten
     years time

     Absolute Date:

          timeout at the indicated time & date (UTC/GMT)
             2000-02-31 00:40:33

          timeout at the indicated date (UTC/GMT)
             2000-02-31

     You can use any of the Absolute Date formats specified in HTTP::Date
     (see perldoc HTTP::Date)

     Note: the DAV server may choose to ignore your specified timeout.

unlock
     Performs a WebDAV UNLOCK request and returns a DAV::Response object.

          $response = $resource->unlock()
          $response = $resource->unlock( -force => 1 )
          $response = $resource->unlock(
             -token => "opaquelocktoken:1342-21423-2323" )

     This method will automatically use the correct locktoken If: header
     if this resource was previously locked.

     force - Synonymous to calling $resource->forcefully_unlock_all.

forcefully_unlock_all
     Remove all locks from a resource and return the last DAV::Response
     object. This method take no arguments.

     $response = $resource->forcefully_unlock_all;

     This method will perform a lockdiscovery against the resource to
     determine all of the current locks. Then it will UNLOCK them one by
     one. unlock( -token => locktoken ).

     This unlock process is achievable because DAV does not enforce any
     security over locks.

     Note: this method returns the LAST unlock response (this is
     sufficient to indicate the success of the sequence of unlocks). If an
     unlock fails, it will bail and return that response.  For instance,
     In the event that there are 3 shared locks and the second unlock
     method fails, then you will get returned the unsuccessful second
     response. The 3rd unlock will not be attempted.

     Don't run with this knife, you could hurt someone (or yourself).

steal_lock
     Removes all locks from a resource, relocks it in your name and
     returns the DAV::Response object for the lock command. This method
     takes no arguments.

     $response = $resource->steal_lock;

     Synonymous to forcefully_unlock_all() and then lock().

lockdiscovery
     Discover the locks held against this resource and return a
     DAV::Response object. This method take no arguments.

          $response = $resource->lockdiscovery;
          @locks = $resource->get_locks if $response->is_success;

     This method is in fact a simplified version of propfind().

as_string
     Returns a string representation of the object. Mainly useful for
     debugging purposes. It takes no arguments.

     print $resource->as_string

ACCESSOR METHODS (get, set and is)
==================================

is_option
     Returns a boolean indicating whether this resource supports the
     option passed in as a string. The option match is case insensitive
     so, PUT and Put are should both work.

          if ($resource->is_option( "PUT" ) ) {
             $resource->put( ... )
          }

     Note: this routine automatically calls the options() routine which
     makes the request to the server. Subsequent calls to is_option will
     use the cached option list. To force a rerequest to the server call
     options()

is_locked
     Returns a boolean indicating whether this resource is locked.

          @lock = $resource->is_locked( -owned=>[0|1] );

     *owned* - this parameters is used to ask, locked by who?

     Note: You must have already called propfind() or lockdiscovery()

     e.g.  Is the resource locked at all?   print "yes" if
     $resource->is_locked();

     Is the resource locked by me?   print "yes" if $resource->is_locked(
     -owned=>1 );

     Is the resource locked by someone other than me?   print "yes" if
     $resource->is_locked( -owned=>0 );

is_collection
     Returns a boolean indicating whether this resource is a collection.

          print "Directory" if ( $resource->is_collection );

     You must first have performed a propfind.

get_uri
     Returns the URI object for this resource.

          print "URL is: " . $resource->get_uri()->as_string . "\n";

     See the URI manpage from the LWP libraries (perldoc URI)

get_property
     Returns a property value. Takes a string as an argument.

          print $resource->get_property( "displayname" );

     You must first have performed a propfind.

get_options
     Returns an array of options allowed on this resource.  Note: If
     $resource->options has not been called then it will return an empty
     array.

     @options = $resource->get_options

get_content
     Returns the resource's content/body as a string.  The content is
     typically the result of a GET.

     $content = $resource->get_content

get_content_ref
     Returns the resource's content/body as a reference to a string.  This
     is useful and more efficient if the content is large.

     ${$resource->get_content_ref} =~ s/\bfoo\b/bar/g;

     Note: You must have already called get()

get_lock
     Returns the DAV::Lock object if it exists. Requires opaquelocktoken
     passed as a parameter.

          $lock = $resource->get_lock( "opaquelocktoken:234214--342-3444" );

get_locks
     Returns a list of any DAV::Lock objects held against the resource.

          @lock = $resource->get_locks( -owned=>[0|1] );

     *owned* - this parameter indicates which locks you want.   - 1,
     requests any of my locks. (Locked by this DAV instance).   - 0
     ,requests any locks not owned by us.   - any other value or no value,
     requests ALL locks.

     Note: You must have already called propfind() or lockdiscovery()

     e.g.   Give me my locks   @lock = $resource->get_locks( -owned=>1 );

          Give me all locks
           @lock = $resource->get_locks();

get_lockedresourcelist
get_parentresourcelist
get_comms
set_parent_resourcelist
     $resource->set_parent_resourcelist( $resourcelist )

     Sets the parent resource list (ask the question, which collection am
     I a member of?). See `HTTP::DAV::ResourceList' in this node.

a simple http server class
**************************

NAME
====

   HTTP::Daemon - a simple http server class

SYNOPSIS
========

     use HTTP::Daemon;
     use HTTP::Status;

     my $d = new HTTP::Daemon;
     print "Please contact me at: <URL:", $d->url, ">\n";
     while (my $c = $d->accept) {
         while (my $r = $c->get_request) {
     	  if ($r->method eq 'GET' and $r->url->path eq "/xyzzy") {
                 # remember, this is *not* recommened practice :-)
     	      $c->send_file_response("/etc/passwd");
     	  } else {
     	      $c->send_error(RC_FORBIDDEN)
     	  }
         }
         $c->close;
         undef($c);
     }

DESCRIPTION
===========

   Instances of the *HTTP::Daemon* class are HTTP/1.1 servers that listen
on a socket for incoming requests. The *HTTP::Daemon* is a sub-class of
IO::Socket::INET, so you can perform socket operations directly on it too.

   The accept() method will return when a connection from a client is
available. The returned value will be a reference to a object of the
*HTTP::Daemon::ClientConn* class which is another IO::Socket::INET
subclass. Calling the get_request() method on this object will read data
from the client and return an HTTP::Request object reference.

   This HTTP daemon does not fork(2) for you.  Your application, i.e. the
user of the *HTTP::Daemon* is reponsible for forking if that is desirable.
Also note that the user is responsible for generating responses that
conform to the HTTP/1.1 protocol.  The *HTTP::Daemon::ClientConn* class
provides some methods that make this easier.

METHODS
=======

   The following is a list of methods that are new (or enhanced) relative
to the IO::Socket::INET base class.

$d = new HTTP::Daemon
     The constructor takes the same parameters as the IO::Socket::INET
     constructor.  It can also be called without specifying any
     parameters. The daemon will then set up a listen queue of 5
     connections and allocate some random port number.  A server that wants
     to bind to some specific address on the standard HTTP port will be
     constructed like this:

          $d = new HTTP::Daemon
                LocalAddr => 'www.someplace.com',
                LocalPort => 80;

$c = $d->accept([$pkg])
     This method is the same as *IO::Socket::accept* but returns an
     *HTTP::Daemon::ClientConn* reference by default.  It returns undef if
     you specify a timeout and no connection is made within that time.

$d->url
     Returns a URL string that can be used to access the server root.

$d->product_tokens
     Returns the name that this server will use to identify itself.  This
     is the string that is sent with the Server response header.  The main
     reason to have this method is that subclasses can override it if they
     want to use another product name.

   The *HTTP::Daemon::ClientConn* is also a IO::Socket::INET subclass.
Instances of this class are returned by the accept() method of
*HTTP::Daemon*.  The following additional methods are provided:

$c->get_request([$headers_only])
     Read data from the client and turn it into an HTTP::Request object
     which is then returned.  It returns undef if reading of the request
     fails.  If it fails, then the *HTTP::Daemon::ClientConn* object ($c)
     should be discarded, and you should not call this method again.  The
     $c->reason method might give you some information about why
     $c->get_request returned undef.

     The $c->get_request method supports HTTP/1.1 request content bodies,
     including *chunked* transfer encoding with footer and self delimiting
     *multipart/** content types.

     The $c->get_request method will normally not return until the whole
     request has been received from the client.  This might not be what you
     want if the request is an upload of a multi-mega-byte file (and with
     chunked transfer encoding HTTP can even support infinite request
     messages - uploading live audio for instance).  If you pass a TRUE
     value as the $headers_only argument, then $c->get_request will return
     immediately after parsing the request headers and you are responsible
     for reading the rest of the request content.  If you are going to
     call $c->get_request again on the same connection you better read the
     correct number of bytes.

$c->read_buffer([$new_value])
     Bytes read by $c->get_request, but not used are placed in the *read
     buffer*.  The next time $c->get_request is called it will consume the
     bytes in this buffer before reading more data from the network
     connection itself.  The read buffer is invalid after $c->get_request
     has returned an undefined value.

     If you handle the reading of the request content yourself you need to
     empty this buffer before you read more and you need to place
     unconsumed bytes here.  You also need this buffer if you implement
     services like *101 Switching Protocols*.

     This method always return the old buffer content and can optionally
     replace the buffer content if you pass it an argument.

$c->reason
     When $c->get_request returns undef you can obtain a short string
     describing why it happened by calling $c->reason.

$c->proto_ge($proto)
     Return TRUE if the client announced a protocol with version number
     greater or equal to the given argument.  The $proto argument can be a
     string like "HTTP/1.1" or just "1.1".

$c->antique_client
     Return TRUE if the client speaks the HTTP/0.9 protocol.  No status
     code and no headers should be returned to such a client.  This should
     be the same as !$c->proto_ge("HTTP/1.0").

$c->force_last_request
     Make sure that $c->get_request will not try to read more requests off
     this connection.  If you generate a response that is not self
     delimiting, then you should signal this fact by calling this method.

     This attribute is turned on automatically if the client announces
     protocol HTTP/1.0 or worse and does not include a "Connection:
     Keep-Alive" header.  It is also turned on automatically when HTTP/1.1
     or better clients send the "Connection: close" request header.

$c->send_status_line( [$code, [$mess, [$proto]]] )
     Send the status line back to the client.  If $code is omitted 200 is
     assumed.  If $mess is omitted, then a message corresponding to $code
     is inserted.  If $proto is missing the content of the
     $HTTP::Daemon::PROTO variable is used.

$c->send_crlf
     Send the CRLF sequence to the client.

$c->send_basic_header( [$code, [$mess, [$proto]]] )
     Send the status line and the "Date:" and "Server:" headers back to
     the client.  This header is assumed to be continued and does not end
     with an empty CRLF line.

$c->send_response( [$res] )
     Write a *HTTP::Response* object to the client as a response.  We try
     hard to make sure that the response is self delimiting so that the
     connection can stay persistent for further request/response exchanges.

     The content attribute of the *HTTP::Response* object can be a normal
     string or a subroutine reference.  If it is a subroutine, then
     whatever this callback routine returns is written back to the client
     as the response content.  The routine will be called until it return
     an undefined or empty value.  If the client is HTTP/1.1 aware then we
     will use chunked transfer encoding for the response.

$c->send_redirect( $loc, [$code, [$entity_body]] )
     Send a redirect response back to the client.  The location ($loc) can
     be an absolute or relative URL. The $code must be one the redirect
     status codes, and defaults to "301 Moved Permanently"

$c->send_error( [$code, [$error_message]] )
     Send an error response back to the client.  If the $code is missing a
     "Bad Request" error is reported.  The $error_message is a string that
     is incorporated in the body of the HTML entity body.

$c->send_file_response($filename)
     Send back a response with the specified $filename as content.  If the
     file is a directory we try to generate an HTML index of it.

$c->send_file($fd);
     Copy the file to the client.  The file can be a string (which will be
     interpreted as a filename) or a reference to an IO::Handle or glob.

$c->daemon
     Return a reference to the corresponding *HTTP::Daemon* object.

SEE ALSO
========

   RFC 2068

   See IO/Socket, Apache,

COPYRIGHT
=========

   Copyright 1996-1998, Gisle Aas

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

date conversion routines
************************

NAME
====

   HTTP::Date - date conversion routines

SYNOPSIS
========

     use HTTP::Date;

     $string = time2str($time);    # Format as GMT ASCII time
     $time = str2time($string);    # convert ASCII date to machine time

DESCRIPTION
===========

   This module provides functions that deal the date formats used by the
HTTP protocol (and then some more).  Only the first two functions,
time2str() and str2time(), are exported by default.

time2str( [$time] )
     The time2str() function converts a machine time (seconds since epoch)
     to a string.  If the function is called without an argument, it will
     use the current time.

     The string returned is in the format preferred for the HTTP protocol.
     This is a fixed length subset of the format defined by RFC 1123,
     represented in Universal Time (GMT).  An example of a time stamp in
     this format is:

          Sun, 06 Nov 1994 08:49:37 GMT

str2time( $str [, $zone] )
     The str2time() function converts a string to machine time.  It returns
     undef if the format of $str is unrecognized, or the time is outside
     the representable range.  The time formats recognized are the same as
     for parse_date().

     The function also takes an optional second argument that specifies the
     default time zone to use when converting the date.  This parameter is
     ignored if the zone is found in the date string itself.  If this
     parameter is missing, and the date string format does not contain any
     zone specification, then the local time zone is assumed.

     If the zone is not "`GMT'" or numerical (like "`-0800'" or
     "`+0100'"), then the `Time::Zone' module must be installed in order
     to get the date recognized.

parse_date( $str )
     This function will try to parse a date string, and then return it as a
     list of numerical values followed by a (possible undefined) time zone
     specifier; ($year, $month, $day, $hour, $min, $sec, $tz).  The $year
     returned will not have the number 1900 subtracted from it and the
     $month numbers start with 1.

     In scalar context the numbers are interpolated in a string of the
     "YYYY-MM-DD hh:mm:ss TZ"-format and returned.

     If the date is unrecognized, then the empty list is returned.

     The function is able to parse the following formats:

          "Wed, 09 Feb 1994 22:23:32 GMT"       -- HTTP format
          "Thu Feb  3 17:03:55 GMT 1994"        -- ctime(3) format
          "Thu Feb  3 00:00:00 1994",           -- ANSI C asctime() format
          "Tuesday, 08-Feb-94 14:15:29 GMT"     -- old rfc850 HTTP format
          "Tuesday, 08-Feb-1994 14:15:29 GMT"   -- broken rfc850 HTTP format

          "03/Feb/1994:17:03:55 -0700"   -- common logfile format
          "09 Feb 1994 22:23:32 GMT"     -- HTTP format (no weekday)
          "08-Feb-94 14:15:29 GMT"       -- rfc850 format (no weekday)
          "08-Feb-1994 14:15:29 GMT"     -- broken rfc850 format (no weekday)

          "1994-02-03 14:15:29 -0100"    -- ISO 8601 format
          "1994-02-03 14:15:29"          -- zone is optional
          "1994-02-03"                   -- only date
          "1994-02-03T14:15:29"          -- Use T as separator
          "19940203T141529Z"             -- ISO 8601 compact format
          "19940203"                     -- only date

          "08-Feb-94"         -- old rfc850 HTTP format    (no weekday, no time)
          "08-Feb-1994"       -- broken rfc850 HTTP format (no weekday, no time)
          "09 Feb 1994"       -- proposed new HTTP format  (no weekday, no time)
          "03/Feb/1994"       -- common logfile format     (no time, no offset)

          "Feb  3  1994"      -- Unix 'ls -l' format
          "Feb  3 17:03"      -- Unix 'ls -l' format

          "11-15-96  03:52PM" -- Windows 'dir' format

     The parser ignores leading and trailing whitespace.  It also allow the
     seconds to be missing and the month to be numerical in most formats.

     If the year is missing, then we assume that the date is the first
     matching date before current month.  If the year is given with only 2
     digits, then parse_date() will select the century that makes the year
     closest to the current date.

time2iso( [$time] )
     Same as time2str(), but returns a "YYYY-MM-DD hh:mm:ss"-formatted
     string representing time in the local time zone.

time2isoz( [$time] )
     Same as time2str(), but returns a "YYYY-MM-DD hh:mm:ssZ"-formatted
     string representing Universal Time.

SEE ALSO
========

   `time', see Perlfunc (perl.info), `time', see Time/Zone,

COPYRIGHT
=========

   Copyright 1995-1999, Gisle Aas

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Routines to deal with HTML input type file.
*******************************************

NAME
====

   HTTP::File - Routines to deal with HTML input type file.

SYNOPSIS
========

CGI.pm example
--------------

   `savepage.html' looks like this:

   <H1>Upload a webpage</H1>

   <FORM METHOD=POST ENCTYPE="multipart/form-data"
action="/cgi-bin/webplugin/savepage.cgi">

   <INPUT TYPE=file name=FILE_UPLOAD size=35>

   <INPUT TYPE=submit NAME=Action VALUE="Upload Ahoy!">

   </FORM>

   `savepage.cgi' looks like this:

   #!/usr/bin/perl

   use CGI; use HTTP::File;

   $cgi = new CGI;

   $upload_path='/tmp';

   $raw_file = $cgi->param('FILE_UPLOAD'); $basename =
HTTP::File::upload($raw_file,$upload_path);

   print $cgi->header; print $cgi->start_html;

   print "$basename upload successfully.<BR>Upload path: "; print
$upload_path ? $upload_path : '/tmp';

   print $cgi->end_html;

HTML::Mason example
-------------------

   <FORM METHOD=POST ENCTYPE="multipart/form-data"
action="receive-upload.html"> <INPUT TYPE=file name=PHOTO_FILE size=35>
</FORM>

   ... then in receive-upload.html

   <%init>     use HTTP::File; </%init>

   <%perl> $output_path="/var/spool"; $raw_file=$ARGS{PHOTO_FILE};
HTTP::File::upload($raw_file, $output_path); </%perl>

DESCRIPTION
===========

   HTTP::File is a module to facilitate file uploads from HTML file
input.It detects the basename of the raw file across MacOS, Windows, and
Unix/Linux platforms.

sub platform
------------

   Uses a subset of the functionality of HTTP::Headers::UserAgent to
determine the type of machine that uploaded the file.

sub upload
----------

   Upload RAW_FILE to the local disk to a specified PATH, or to /tmp if
PATH is not specified.

     Returns the basename of the uploaded file;

   As of version 3.1, there are two new args to upload():

   * $debug

     A third argument, $debug, if non-zero will send debugging information
     to STDERR.

   * $kludge

     A fourth argument, `$kludge', if non-zero, will also write the read
     data to a file in the temp directory.

AUTHOR
======

   Terrence Brannon tbone@cpan.org

Class encapsulating HTTP Message headers
****************************************

NAME
====

   HTTP::Headers - Class encapsulating HTTP Message headers

SYNOPSIS
========

     require HTTP::Headers;
     $h = new HTTP::Headers;

DESCRIPTION
===========

   The `HTTP::Headers' class encapsulates HTTP-style message headers.  The
headers consist of attribute-value pairs, which may be repeated, and which
are printed in a particular order.

   Instances of this class are usually created as member variables of the
HTTP::Request and `HTTP::Response' classes, internal to the library.

   The following methods are available:

$h = new HTTP::Headers
     Constructs a new `HTTP::Headers' object.  You might pass some initial
     attribute-value pairs as parameters to the constructor.  *E.g.*:

          $h = new HTTP::Headers
              Date         => 'Thu, 03 Feb 1994 00:00:00 GMT',
              Content_Type => 'text/html; version=3.2',
              Content_Base => 'http://www.sn.no/';

$h->header($field [=> $value],...)
     Get or set the value of a header.  The header field name is not case
     sensitive.  To make the life easier for perl users who wants to avoid
     quoting before the => operator, you can use '_' as a synonym for '-'
     in header names (this behaviour can be suppressed by setting
     $HTTP::Headers::TRANSLATE_UNDERSCORE to a FALSE value).

     The header() method accepts multiple ($field => $value) pairs, so you
     can update several fields with a single invocation.

     The optional $value argument may be a scalar or a reference to a list
     of scalars. If the $value argument is undefined or not given, then the
     header is not modified.

     The old value of the last of the $field values is returned.
     Multi-valued fields will be concatenated with "," as separator in
     scalar context.

          $header->header(MIME_Version => '1.0',
          		 User_Agent   => 'My-Web-Client/0.01');
          $header->header(Accept => "text/html, text/plain, image/*");
          $header->header(Accept => [qw(text/html text/plain image/*)]);
          @accepts = $header->header('Accept');

$h->scan(\&doit)
     Apply a subroutine to each header in turn.  The callback routine is
     called with two parameters; the name of the field and a single value.
     If the header has more than one value, then the routine is called once
     for each value.  The field name passed to the callback routine has
     case as suggested by HTTP Spec, and the headers will be visited in the
     recommended "Good Practice" order.

$h->as_string([$endl])
     Return the header fields as a formatted MIME header.  Since it
     internally uses the scan() method to build the string, the result
     will use case as suggested by HTTP Spec, and it will follow
     recommended "Good Practice" of ordering the header fieds.  Long header
     values are not folded.

     The optional parameter specifies the line ending sequence to use.  The
     default is `"\n"'.  Embedded "\n" characters in the header will be
     substitued with this line ending sequence.

$h->push_header($field, $val)
     Add a new field value of the specified header.  The header field name
     is not case sensitive.  The field need not already have a value.
     Previous values for the same field are retained.  The argument may be
     a scalar or a reference to a list of scalars.

          $header->push_header(Accept => 'image/jpeg');

$h->remove_header($field,...)
     This function removes the headers with the specified names.

$h->clone
     Returns a copy of this HTTP::Headers object.

CONVENIENCE METHODS
===================

   The most frequently used headers can also be accessed through the
following convenience methods.  These methods can both be used to read and
to set the value of a header.  The header value is set if you pass an
argument to the method.  The old header value is always returned.

   Methods that deal with dates/times always convert their value to system
time (seconds since Jan 1, 1970) and they also expect this kind of value
when the header value is set.

$h->date
     This header represents the date and time at which the message was
     originated. *E.g.*:

          $h->date(time);  # set current date

$h->expires
     This header gives the date and time after which the entity should be
     considered stale.

$h->if_modified_since
$h->if_unmodified_since
     This header is used to make a request conditional.  If the requested
     resource has (not) been modified since the time specified in this
     field, then the server will return a `"304 Not Modified"' response
     instead of the document itself.

$h->last_modified
     This header indicates the date and time at which the resource was last
     modified. *E.g.*:

          # check if document is more than 1 hour old
          if ($h->last_modified < time - 60*60) {
          	...
          }

$h->content_type
     The Content-Type header field indicates the media type of the message
     content. *E.g.*:

          $h->content_type('text/html');

     The value returned will be converted to lower case, and potential
     parameters will be chopped off and returned as a separate value if in
     an array context.  This makes it safe to do the following:

          if ($h->content_type eq 'text/html') {
             # we enter this place even if the real header value happens to
             # be 'TEXT/HTML; version=3.0'
             ...
          }

$h->content_encoding
     The Content-Encoding header field is used as a modifier to the media
     type.  When present, its value indicates what additional encoding
     mechanism has been applied to the resource.

$h->content_length
     A decimal number indicating the size in bytes of the message content.

$h->content_language
     The natural language(s) of the intended audience for the message
     content.  The value is one or more language tags as defined by RFC
     1766.  Eg. "no" for Norwegian and "en-US" for US-English.

$h->title
     The title of the document.  In libwww-perl this header will be
     initialized automatically from the <TITLE>...</TITLE> element of HTML
     documents.  *This header is no longer part of the HTTP standard.*

$h->user_agent
     This header field is used in request messages and contains information
     about the user agent originating the request.  *E.g.*:

          $h->user_agent('Mozilla/1.2');

$h->server
     The server header field contains information about the software being
     used by the originating server program handling the request.

$h->from
     This header should contain an Internet e-mail address for the human
     user who controls the requesting user agent.  The address should be
     machine-usable, as defined by RFC822.  E.g.:

          $h->from('Gisle Aas <aas@sn.no>');

$h->referer
     Used to specify the address (URI) of the document from which the
     requested resouce address was obtained.

$h->www_authenticate
     This header must be included as part of a "401 Unauthorized" response.
     The field value consist of a challenge that indicates the
     authentication scheme and parameters applicable to the requested URI.

$h->proxy_authenticate
     This header must be included in a "407 Proxy Authentication Required"
     response.

$h->authorization
$h->proxy_authorization
     A user agent that wishes to authenticate itself with a server or a
     proxy, may do so by including these headers.

$h->authorization_basic
     This method is used to get or set an authorization header that use the
     "Basic Authentication Scheme".  In array context it will return two
     values; the user name and the password.  In scalar context it will
     return *"uname:password"* as a single string value.

     When used to set the header value, it expects two arguments.  *E.g.*:

          $h->authorization_basic($uname, $password);

     The method will croak if the $uname contains a colon ':'.

$h->proxy_authorization_basic
     Same as authorization_basic() but will set the "Proxy-Authorization"
     header instead.

COPYRIGHT
=========

   Copyright 1995-1998 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Routine to detect web browser platform from User-Agent HTTP Header
******************************************************************

NAME
====

   HTTP::Headers::UserAgent - Routine to detect web browser platform from
User-Agent HTTP Header

SYNOPSIS
========

     use HTTP::Headers::UserAgent;
     $Platform = new HTTP::Headers::UserAgent::GetPlatform ($ENV{HTTP_USER_AGENT});

DESCRIPTION
===========

   The route will parse parameter string, which must be in HTTP User-Agent
header form, and return the browser platform. The returned value is string
with one of the following values:

     Win95, Win98, WinNT, UNIX, MAC, Win3x, OS2, Linux

   If the platform is not one of these (i.e. one of the robots), the
returned string is empty.

NOTES
=====

   Part of "WWW Cyrillic Encoding Suite" Get docs and newest version from
http://www.neystadt.org/cyrillic/

   Copyright (c) 1997-98, John Neystadt <http://www.neystadt.org/john/>.
You may install this script on your web site for free. To obtain permision
for or any other usage contact john@neystadt.org.

   Drop me a line if you deploy this script on your site.

AUTHOR
======

   Leonid Neishtadt <leonid@neystadt.org>, John Neystadt
<john@neystadt.org>

SEE ALSO
========

   perl(1).

Header value parsing utility functions
**************************************

NAME
====

   HTTP::Headers::Util - Header value parsing utility functions

SYNOPSIS
========

     use HTTP::Headers::Util qw(split_header_words);
     @values = split_header_words($h->header("Content-Type"));

DESCRIPTION
===========

   This module provides a few functions that helps parsing and
construction of valid HTTP header values.  None of the functions are
exported by default.

   The following functions are available:

split_header_words( @header_values )
     This function will parse the header values given as argument into a
     list of anonymous arrays containing key/value pairs.  The function
     knows how to deal with ",", ";" and "=" as well as quoted values after
     "=".  A list of space separated tokens are parsed as if they were
     separated by ";".

     If the @header_values passed as argument contains multiple values,
     then they are treated as if they were a single value separated by
     comma ",".

     This means that this function is useful for parsing header fields that
     follow this syntax (BNF as from the HTTP/1.1 specification, but we
     relax the requirement for tokens).

          headers           = #header
          header            = (token | parameter) *( [";"] (token | parameter))

          token             = 1*<any CHAR except CTLs or separators>
          separators        = "(" | ")" | "<" | ">" | "@"
                            | "," | ";" | ":" | "\" | <">
                            | "/" | "[" | "]" | "?" | "="
                            | "{" | "}" | SP | HT

          quoted-string     = ( <"> *(qdtext | quoted-pair ) <"> )
          qdtext            = <any TEXT except <">>
          quoted-pair       = "\" CHAR

          parameter         = attribute "=" value
          attribute         = token
          value             = token | quoted-string

     Each header is represented by an anonymous array of key/value pairs.
     The value for a simple token (not part of a parameter) is undef.
     Syntactically incorrect headers will not necessary be parsed as you
     would want.

     This is easier to describe with some examples:

          split_header_words('foo="bar"; port="80,81"; discard, bar=baz')
          split_header_words('text/html; charset="iso-8859-1");
          split_header_words('Basic realm="\"foo\\bar\""');

     will return

          [foo=>'bar', port=>'80,81', discard=> undef], [bar=>'baz' ]
          ['text/html' => undef, charset => 'iso-8859-1']
          [Basic => undef, realm => '"foo\bar"']

join_header_words( @arrays )
     This will do the opposite of the conversion done by
     split_header_words().  It takes a list of anonymous arrays as
     arguments (or a list of key/value pairs) and produces a single header
     value.  Attribute values are quoted if needed.

     Example:

          join_header_words(["text/plain" => undef, charset => "iso-8859/1"]);
          join_header_words("text/plain" => undef, charset => "iso-8859/1");

     will both return the string:

          text/plain; charset="iso-8859/1"

COPYRIGHT
=========

   Copyright 1997-1998, Gisle Aas

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Lightweight HTTP implementation
*******************************

NAME
====

   HTTP::Lite - Lightweight HTTP implementation

SYNOPSIS
========

     use HTTP::Lite;
     $http = new HTTP::Lite;
     $req = $http->request("http://www.cpan.org/")
         or die "Unable to get document: $!";
     print $http->body();

DESCRIPTION
===========

     HTTP::Lite is a stand-alone lightweight HTTP/1.1
     implementation for perl.  It is not intended to replace LWP,
     but rather is intended for use in situations where it is
     desirable to install the minimal number of modules to
     achieve HTTP support, or where LWP is not a good candidate
     due to CPU overhead, such as slower processors.

     HTTP::Lite is ideal for CGI (or mod_perl) programs or for
     bundling for redistribution with larger packages where only
     HTTP GET and POST functionality are necessary.

     HTTP::Lite supports basic POST and GET operations only.  As
     of 0.2.1, HTTP::Lite supports HTTP/1.1 and is compliant with
     the Host header, necessary for name based virtual hosting.
     Additionally, HTTP::Live now supports Proxies.

     If you require more functionality, such as FTP or HTTPS,
     please see libwwwperl (LWP).  LWP is a significantly better
     and more comprehensive package than HTTP::Lite, and should
     be used instead of HTTP::Lite whenever possible.

CONSTRUCTOR
===========

new
     This is the constructor for HTTP::Lite.  It presently takes no
     arguments.  A future version of HTTP::Lite might accept parameters.

METHODS
=======

request ( URL )
     Initiates a request to the specified URL.

     Returns undef if an I/O error is encountered, otherwise the HTTP
     status code will be returned.  200 series status codes represent
     success, 300 represent temporary errors, 400 represent permanent
     errors, and 500 represent server errors.

     See `http://www.w3.org/Protocols/HTTP/HTRESP.html' for detailled
     information about HTTP status codes.

prepare_post
add_req_header ( $header, $value ) =item get_req_header ( $header ) =item delete_req_header ( $header )
     Add, Delete, or a HTTP header(s) for the request.  These functions
     allow you to override any header.  Presently, Host, User-Agent,
     Content-Type, Accept, and Connection are pre-defined by the
     HTTP::Lite module.  You may not override Host, Connection, or Accept.

     To provide (proxy) authentication or authorization, you would use:

          use HTTP::Lite;
          use MIME::Base64;
          $http = new HTTP::Lite;
          $encoded = encode_base64('username:password');
          $http->add_req_header("Authorization", $encoded);

     NOTE: The present implementation limits you to one instance of each
     header.

body
     Returns the body of the document retured by the remote server.

headers_array
     Returns an array of the HTTP headers returned by the remote server.

headers_string
     Returns a string representation of the HTTP headers returned by the
     remote server.

get_header ( $header )
     Returns an array of values for the requested header.

     NOTE: HTTP requests are not limited to a single instance of each
     header.  As a result, there may be more than one entry for every
     header.

protocol
     Returns the HTTP protocol identifier, as reported by the remote
     server.  This will generally be either HTTP/1.0 or HTTP/1.1.

proxy ( $proxy_server )
     The URL or hostname of the proxy to use for the next request.

status
     Returns the HTTP status code returned by the server.  This is also
     reported as the return value of request().

status_message
     Returns the textual description of the status code as returned by the
     server.  The status string is not required to adhere to any
     particular format, although most HTTP servers use a standard set of
     descriptions.

response
     Returns the entire unparsed HTTP response as returned by the server.

reset
     You must call this prior to re-using an HTTP::Lite handle, otherwise
     the results are undefined.

EXAMPLES
========

     # Get and print out the headers and body of the CPAN homepage
     use HTTP::Lite;
     $http = new HTTP::Lite;
     $req = $http->request("http://www.cpan.org/")
         or die "Unable to get document: $!";
     die "Request failed ($req): ".$http->status_message()
       if $req ne "200";
     @headers = $http->headers_array();
     $body = $http->body();
     foreach $header (@headers)
     {
       print "$header$CRLF";
     }
     print "$CRLF";
     print "$body$CRLF";

     # POST a query to the dejanews USENET search engine
     use HTTP::Lite;
     $http = new HTTP::Lite;
     %vars = (
              "QRY" => "perl",
              "ST" => "MS",
              "svcclass" => "dncurrent",
              "DBS" => "2"
             );
     $http->prepare_post(\%vars);
     $req = $http->request("http://www.deja.com/dnquery.xp")
       or die "Unable to get document: $!";
     print "req: $req\n";
     print $http->body();

UNIMPLEMENTED
=============

     - FTP
     - HTTPS (SSL)
     - Authenitcation/Authorizaton/Proxy-Authorization
       are not directly supported, and require MIME::Base64.
     - Redirects (Location) are not automatically followed
     - multipart/form-data POSTs are not supported (necessary for
       File uploads).

     =head1 BUGS

     Some bugs likely still exist.  This is a beta version.

     Large requests are stored in ram, potentially more than once
     due to HTTP/1.1 chunked transfer mode support.  A future
     version of this module may support writing requests to a
     filehandle to avoid excessive disk use.

ACKNOWLEDGEMENTS
================

     Marcus I. Ryan	shad@cce-7.cce.iastate.edu
     michael.kloss@de.adp.com

AUTHOR
======

   Roy Hooper <rhooper@thetoybox.org>

SEE ALSO
========

   See LWP, RFC 2068 - HTTP/1.1 -http://www.w3.org/

COPYRIGHT
=========

   Copyright (c) 2000 Roy Hooper.  All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Class encapsulating HTTP messages
*********************************

NAME
====

   HTTP::Message - Class encapsulating HTTP messages

SYNOPSIS
========

     package HTTP::Request;  # or HTTP::Response
     require HTTP::Message;
     @ISA=qw(HTTP::Message);

DESCRIPTION
===========

   A `HTTP::Message' object contains some headers and a content (body).
The class is abstract, i.e. it only used as a base class for HTTP::Request
and `HTTP::Response' and should never instantiated as itself.

   The following methods are available:

$mess = new HTTP::Message;
     This is the object constructor.  It should only be called internally
     by this library.  External code should construct HTTP::Request or
     `HTTP::Response' objects.

$mess->clone()
     Returns a copy of the object.

$mess->protocol([$proto])
     Sets the HTTP protocol used for the message.  The protocol() is a
     string like "HTTP/1.0" or "HTTP/1.1".

$mess->content([$content])
     The content() method sets the content if an argument is given.  If no
     argument is given the content is not touched.  In either case the
     previous content is returned.

$mess->add_content($data)
     The add_content() methods appends more data to the end of the previous
     content.

$mess->content_ref
     The content_ref() method will return a reference to content string.
     It can be more efficient to access the content this way if the content
     is huge, and it can be used for direct manipulation of the content,
     for instance:

          ${$res->content_ref} =~ s/\bfoo\b/bar/g;

$mess->headers;
     Return the embedded HTTP::Headers object.

$mess->headers_as_string([$endl])
     Call the HTTP::Headers->as_string() method for the headers in the
     message.

   All unknown `HTTP::Message' methods are delegated to the
`HTTP::Headers' object that is part of every message.  This allows
convenient access to these methods.  Refer to HTTP/Headers,
for details of these methods:

     $mess->header($field => $val);
     $mess->scan(\&doit);
     $mess->push_header($field => $val);
     $mess->remove_header($field);

     $mess->date;
     $mess->expires;
     $mess->if_modified_since;
     $mess->if_unmodified_since;
     $mess->last_modified;
     $mess->content_type;
     $mess->content_encoding;
     $mess->content_length;
     $mess->content_language
     $mess->title;
     $mess->user_agent;
     $mess->server;
     $mess->from;
     $mess->referer;
     $mess->www_authenticate;
     $mess->authorization;
     $mess->proxy_authorization;
     $mess->authorization_basic;
     $mess->proxy_authorization_basic;

COPYRIGHT
=========

   Copyright 1995-1997 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Web testing application
***********************

NAME
====

   HTTP::Monkeywrench - Web testing application

SYNOPSIS
========

     use HTTP::Monkeywrench;
      $session = [
        {
        name  =Greater_Than_Special_Sequence 'URL Name',
        url   =Greater_Than_Special_Sequence 'http://url',
        }
      ];
      HTTP::Monkeywrench-Greater_Than_Special_Sequencetest($session);

REQUIRES
========

     CGI
     Net::SMTP
     HTTP::Cookies
     LWP::UserAgent
     Time::HiRes
     Data::Dumper

EXPORTS
=======

   None

DESCRIPTION
===========

   HTTP::Monkeywrench is a test-harness application to test the integrity
of a user's path through a web site.

   To run HTTP::Monkeywrench->test(), first set up a Perl script that
contains sessions (described below), settings if desired (also described
below), and a call to HTTP::Monkeywrench->test(), passing it the settings
hashref first, followed by the desired session hashrefs you want to test.
HTTP::Monkeywrench->test($settings, $session1,... $sessionN)

   HTTP::Monkeywrench can also be used in an object-oriented fashion -
simply take the result of HTTP::Monkeywrench->new (optionally passing the
settings hashref) and call the test() method against it as above
(optionally omitting the settings hashref.)

   Each session arrayref contains one or more hashrefs, called clicks,
which contain descriptive elements of a specific web page to be tested.
The elements are described below under SESSION.

SESSION
=======

`$session1' (ARRAYREF of HASHREFS)
     A session is an arrayref of complex hashrefs that can be sent to the
     `HTTP::Monkeywrench->test' application to perform tests on a website
     as a virtual user.

     The following keys can be in each 'Click' hashref.  Fields with a "*"
     are required:

name (SCALAR)
     A name to visually reference that 'click' in the reports

(SCALAR)
     The url for Monkeywrench to test for that click.

params (HASHREF)
     The params to send to dynamic pages and cgi's.  Params should be set
     up as such: { username => 'joe', password => 'blow' }

method (SCALAR)
     'method' should be either 'POST' or 'GET'. If method is left blank,
     method will default to 'GET'.

auth (ARRAYREF)
     'auth' is the username and password if the site your are testing is
     password protected. 'auth' params must be passed to each element of a
     session that is accessing the same site.  Example:
     ['username','password']

success_res (ARRAYREF)
     An arrayref of items for Monkeywrench to test for their existence.
     Each element of the array can either be a text string or a regexp
     object.  If a string from success_res is not found in the page,
     Monkeywrench will report an error.  EXAMPLE:
     ['string',qr/regexp_object/,'etc']

error_res (ARRAYREF)
     The same as success_res, except that an error will only be reported
     if strings in error_res ARE found on the page being tested.

cookies (ARRAYREF of ARRAYREFS)
     A preset cookie can be sent to a page. In order to send a cookie to a
     page the following elements should be included as an arrayref:

     [$version, $key, $val, $path, $domain, $port, $path_spec, $secure,
     $maxage, $discard, \%rest]

     An example cookie would look like:

     [['0', 'sessnum', 'expires&2592000&type&consumer',
     '/','cookiemonster.org', '8014', ", ", '2000-09-11 16:15:15Z', "]],

acceptcookie (BIT)
     A numeric flag set to 1 or 0 to tell Monkeywrench if it should accept
     and save a cookie passed from a server.  Default is 0, cookies will
     not be accepted.

sendcookie (BIT)
     A numeric flag set to 1 or 0 to tell Monkeywrench to send a saved or
     pre made cookie back to the server. Default is 0, cookies will not be
     sent.

showhtml (BIT)
     A numeric flag set to 1 or 0 to have the source html of a page
     displayed within the report. When set to 1 the reports can get messy
     if the page is heavy on html.

SETTINGS HASH
=============

$settings (HASHREF)
     The settings hash is optional as are each of the elements of
     $settings.  Elements that are not declared or set are defaulted to 0
     (off).

match_detail (BIT)
     A numeric flag set to 1 or 0. If set to 1 Match detail shows all of
     the reports of success_res and error_res no matter if they pass or
     fail.

show_cookies (BIT)
     A numeric flag set to 1 or 0. If set to 1 show_cookies will show all
     the cookies in the report, either passed from the session or sent
     from the server.

smtp_server (SCALAR)
     The SMTP server to be used by Net::SMTP. Only required if user wants
     output of Monkeywrench to be sent to an email address.

send_mail (ARRAYREF)
     The send_mail arrayref is also only required if user plans on sending
     output to one or more email addresses.

send_if_err (BIT)
     The send_if_err bit is a flag that should be set to either 1 or 0 and
     is only used if the user wants the Monkeywrench output sent via email.
     If set to 1 the output will only be sent to the email address(es) in
     the event of a failure in the success or error checking or any result
     code other than 200.

print_results (BIT)
     If set to 1, the results will be printed to the screen. If set to 0
     nothing will be printed to the screen. The default setting is 1.

METHODS
=======

new ( [ \%settings ] )
     Returns a new Monkeywrench object.  Optionally takes a settings hash.

`settings' ( $self, [ \%settings ] )
     Returns settings hash.  Passing hashref will change settings in
     object.

test ( [ \%settings ], \@session [ , \@session, ... ] )
     Usable as both a static method and object method.  Runs a series
     Monkeywrench tests on a web server using the parameters set forth in
     the sessions you pass.

`get_response' ($click)
     get_response is a recursive method that loops through all possible
     redirects until a final response is returned, which is then returned
     to the caller.

`send_monkeymail' ( $content, \$smtp_server \@address )
     send_monkeymail is called if the config script has an email address
     and depending on how send_if_err is setup.  $content is the output of
     the session(s) called by the config script and the \@address arrayref
     contains the address(es) that the output will be sent to. $smtp_server
     is the smtp server for Net::SMTP to connect to and is also required
     in order for send_monkeymail to be called.

REVISION HISTORY  $Log: Monkeywrench.pm,v $  Revision 1.13  2000/09/12 00:14:54  david  More POD fixes.
=======================================================================================================

     Revision 1.12  2000/09/08 01:40:23  greg
     removed C<> surrounding SYNOPSIS as it was breaking pod2html.

     Revision 1.10  2000/09/08 01:01:10  greg
     fixed POD

     Revision 1.9  2000/09/08 00:37:49  david
      - Moved and rearranged some POD.

     Revision 1.8  2000/09/07 22:26:26  derek
      - Removed _init method and incoporated code into new method.
      - Added a return obj that is populated during the test method and is returned
        at the end of the test method.
      - Other misc code changes for efficiency and readability.
      - Fixed minor POD problems and added documentation for new settings.

     Revision 1.7  2000/09/06 21:49:35  david
      - Changed POD formatting (looks better in a POD reader, not in an editor.)
      - added some extra sanity to send_monkeymail()

     Revision 1.6  2000/09/01 23:10:51  derek
      - Documentation fixes, additions.

     Revision 1.5  2000/08/23 21:25:37  derek
      - Added send_monkeymail method to handle sending reports via email.
      - Modified test method to put all output data into $content variable instead
        of printing each chunk separately.
      - Added documentation for send_monkeymail method, new oop features, and new
        settings options for the config files.

     Revision 1.4  2000/08/03 01:03:34  david
      now uses strict (no change required)
     OO enhancements
      - initialization portion of test() method moved to methods new(), _init(),
        and settings(), test() works as an object method, but still works as a
        static method. Objects are reusable (you can call test any number of times.)
      - settings(), cgi(), cookie_jar(), and ua() access methods set up to make
        more extensible

     Revision 1.3  2000/02/28 23:52:07  derek
      - Added and changed lots of POD
      - Added new report element, Code, to display the response code of the page

     Revision 1.2  2000/02/18 03:36:18  derek
      - Fixed logic problem in reading the settings from what user passes
      - Fixed minor display issue

     Revision 1.1.1.1  2000/02/17 21:04:05  derek
      - Start

SEE ALSO
========

   perl(1).

KNOWN BUGS
==========

   None

TODO
====

   * *Recorder Utility*

   * *Recorder Utility* - Currently, scenarios must be created
     painstakenly by editing complex conf files.  A better solution would
     be a CGI or mod_perl handler which 'watches' you surf a site and
     creates the  configuration script for you.

   * *Link checking ability* (checks integrity of all links on the pages
     it checks)

   * *HTML checking* - Checks the HTML on pages for HTML compliance (you
     can optionally specify the HTML w3c spec you want to comply to).  We
     might integrate WebLINT or other packages which do this  (they may
     even check links).

   * *Load Testing* - Most load testing tools hit one page over and over
     measuring how many simultaneous requests per second a site can
     handle. This approach is highly flawed since it does not approximate
     true traffic on your site where lots of people might be performing
     different actions on your site at the same time (not just pounding
     one page.)  Monkeywrench is well suited to being a true load testing
     tool where multiple sessions,  mimicking actual users doing lots of
     different things on your site, are run  simultaneously to see how
     many requests a second your site can handle under more realistic
     conditions.  We envision adding a client server componant to the load
     balancing tool that would let you run Monkeywrench clients on lots of
     machines all hitting the same site.  Then a Monkeywrench server would
     collect and report on the results.

   * Configuration - Currently, the test scenarios reside in configuration
     scripts which you run directly.  It would be better if the
     configuration information was separated from the script which reads
     and runs the configuration information.  One idea is to store
     configuration/session info into XML files which you could just pass
     to Monkeywrench at the command line. 		 =item * Write more,
     longer TODOs.

COPYRIGHT
=========

   Copyright (c) 2000, Cnation Inc. All Rights Reserved. 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.

   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.

AUTHORS
=======

     Derek Cline 	<derek@cnation.com>
     Adam Pisoni	<adam@cnation.com>
     David Pisoni	<david@cnation.com>

choose a variant of a document to serve (HTTP content negotiation)
******************************************************************

NAME
====

   choose - choose a variant of a document to serve (HTTP content
negotiation)

SYNOPSIS
========

     use HTTP::Negotiate;

     #  ID       QS     Content-Type   Encoding Char-Set        Lang   Size
     $variants =
      [['var1',  1.000, 'text/html',   undef,   'iso-8859-1',   'en',   3000],
       ['var2',  0.950, 'text/plain',  'gzip',  'us-ascii',     'no',    400],
       ['var3',  0.3,   'image/gif',   undef,   undef,          undef, 43555],
      ];

     @prefered = choose($variants, $request_headers);
     $the_one  = choose($variants);

DESCRIPTION
===========

   This module provides a complete implementation of the HTTP content
negotiation algorithm specified in `draft-ietf-http-v11-spec-00.ps'
chapter 12.  Content negotiation allows for the selection of a preferred
content representation based upon attributes of the negotiable variants
and the value of the various Accept* header fields in the request.

   The variants are ordered by preference by calling the function choose().

   The first parameter is reference to an array of the variants to choose
among.  Each element in this array is an array with the values [$id, $qs,
$content_type, $content_encoding, $charset, $content_language,
$content_length] whose meanings are described below. The $content_encoding
and $content_language can be either a single scalar value or an array
reference if there are several values.

   The second optional parameter is either a HTTP::Headers or a
HTTP::Request object which is searched for "Accept*" headers.  If this
parameter is missing, then the accept specification is initialized from
the CGI environment variables HTTP_ACCEPT, HTTP_ACCEPT_CHARSET,
HTTP_ACCEPT_ENCODING and HTTP_ACCEPT_LANGUAGE.

   In an array context, choose() returns a list of variant
identifier/calculated quality pairs.  The values are sorted by quality,
highest quality first.  If the calculated quality is the same for two
variants, then they are sorted by size (smallest first). *E.g.*:

     (['var1' => 1], ['var2', 0.3], ['var3' => 0]);

   Note that also zero quality variants are included in the return list
even if these should never be served to the client.

   In a scalar context, it returns the identifier of the variant with the
highest score or undef if none have non-zero quality.

   If the $HTTP::Negotiate::DEBUG variable is set to TRUE, then a lot of
noise is generated on STDOUT during evaluation of choose().

VARIANTS
========

   A variant is described by a list of the following values.  If the
attribute does not make sense or is unknown for a variant, then use undef
instead.

identifier
     This is a string that you use as the name for the variant.  This
     identifier for the preferred variants returned by choose().

qs
     This is a number between 0.000 and 1.000 that describes the "source
     quality".  This is what `draft-ietf-http-v11-spec-00.ps' says about
     this value:

     Source quality is measured by the content provider as representing the
     amount of degradation from the original source.  For example, a
     picture in JPEG form would have a lower qs when translated to the XBM
     format, and much lower qs when translated to an ASCII-art
     representation.  Note, however, that this is a function of the source
     - an original piece of ASCII-art may degrade in quality if it is
     captured in JPEG form.  The qs values should be assigned to each
     variant by the content provider; if no qs value has been assigned, the
     default is generally "qs=1".

content-type
     This is the media type of the variant.  The media type does not
     include a charset attribute, but might contain other parameters.
     Examples are:

          text/html
          text/html;version=2.0
          text/plain
          image/gif
          image/jpg

content-encoding
     This is one or more content encodings that has been applied to the
     variant.  The content encoding is generally used as a modifier to the
     content media type.  The most common content encodings are:

          gzip
          compress

content-charset
     This is the character set used when the variant contains text.  The
     charset value should generally be undef or one of these:

          us-ascii
          iso-8859-1 ... iso-8859-9
          iso-2022-jp
          iso-2022-jp-2
          iso-2022-kr
          unicode-1-1
          unicode-1-1-utf-7
          unicode-1-1-utf-8

content-language
     This describes one or more languages that are used in the variant.
     Language is described like this in `draft-ietf-http-v11-spec-00.ps': A
     language is in this context a natural language spoken, written, or
     otherwise conveyed by human beings for communication of information to
     other human beings.  Computer languages are explicitly excluded.

     The language tags are defined by RFC-1766.  Examples are:

          no               Norwegian
          en               International English
          en-US            US English
          en-cockney

content-length
     This is the number of bytes used to represent the content.

ACCEPT HEADERS
==============

   The following Accept* headers can be used for describing content
preferences in a request (This description is an edited extract from
`draft-ietf-http-v11-spec-00.ps'):

Accept
     This header can be used to indicate a list of media ranges which are
     acceptable as a reponse to the request.  The "*" character is used to
     group media types into ranges, with "*/*" indicating all media types
     and "type/*" indicating all subtypes of that type.

     The parameter q is used to indicate the quality factor, which
     represents the user's preference for that range of media types.  The
     parameter mbx gives the maximum acceptable size of the response
     content. The default values are: q=1 and mbx=infinity. If no Accept
     header is present, then the client accepts all media types with q=1.

     For example:

          Accept: audio/*;q=0.2;mbx=200000, audio/basic

     would mean: "I prefer audio/basic (of any size), but send me any audio
     type if it is the best available after an 80% mark-down in quality and
     its size is less than 200000 bytes"

Accept-Charset
     Used to indicate what character sets are acceptable for the response.
     The "us-ascii" character set is assumed to be acceptable for all user
     agents.  If no Accept-Charset field is given, the default is that any
     charset is acceptable.  Example:

          Accept-Charset: iso-8859-1, unicode-1-1

Accept-Encoding
     Restricts the Content-Encoding values which are acceptable in the
     response.  If no Accept-Encoding field is present, the server may
     assume that the client will accept any content encoding.  An empty
     Accept-Encoding means that no content encoding is acceptable.
     Example:

          Accept-Encoding: compress, gzip

Accept-Language
     This field is similar to Accept, but restricts the set of natural
     languages that are preferred in a response.  Each language may be
     given an associated quality value which represents an estimate of the
     user's comprehension of that language.  For example:

          Accept-Language: no, en-gb;q=0.8, de;q=0.55

     would mean: "I prefer Norwegian, but will accept British English (with
     80% comprehension) or German (with 55% comprehension).

COPYRIGHT
=========

   Copyright 1996, Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Gisle Aas <aas@sn.no>

Class encapsulating HTTP Requests
*********************************

NAME
====

   HTTP::Request - Class encapsulating HTTP Requests

SYNOPSIS
========

     require HTTP::Request;
     $request = HTTP::Request->new(GET => 'http://www.oslonett.no/');

DESCRIPTION
===========

   HTTP::Request is a class encapsulating HTTP style requests, consisting
of a request line, some headers, and some (potentially empty) content.
Note that the LWP library also uses this HTTP style requests for non-HTTP
protocols.

   Instances of this class are usually passed to the request() method of
an `LWP::UserAgent' object:

     $ua = LWP::UserAgent->new;
     $request = HTTP::Request->new(GET => 'http://www.oslonett.no/');
     $response = $ua->request($request);

   HTTP::Request is a subclass of `HTTP::Message' and therefore inherits
its methods.  The inherited methods most often used are header(),
push_header(), remove_header(), headers_as_string() and content().  See
HTTP/Message, for details.

   The following additional methods are available:

$r = HTTP::Request->new($method, $uri, [$header, [$content]])
     Constructs a new HTTP::Request object describing a request on the
     object $uri using method `$method'.  The $uri argument can be either
     a string, or a reference to a `URI' object.  The $header argument
     should be a reference to an `HTTP::Headers' object.

$r->method([$val])
$r->uri([$val])
     These methods provide public access to the attributes containing
     respectively the method of the request and the URI object of the
     request.

     If an argument is given the attribute is given that as its new value.
     If no argument is given the value is not touched. In either case the
     previous value is returned.

     The uri() method accept both a reference to a URI object and a string
     as its argument.  If a string is given, then it should be parseable
     as an absolute URI.

$r->as_string()
     Method returning a textual representation of the request.  Mainly
     useful for debugging purposes. It takes no arguments.

SEE ALSO
========

   See HTTP/Headers, HTTP/Message,
HTTP/Request/Common,

COPYRIGHT
=========

   Copyright 1995-1998 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Construct common HTTP::Request objects
**************************************

NAME
====

   HTTP::Request::Common - Construct common HTTP::Request objects

SYNOPSIS
========

     use HTTP::Request::Common;
     $ua = LWP::UserAgent->new;
     $ua->request(GET 'http://www.sn.no/');
     $ua->request(POST 'http://somewhere/foo', [foo => bar, bar => foo]);

DESCRIPTION
===========

   This module provide functions that return newly created HTTP::Request
objects.  These functions are usually more convenient to use than the
standard HTTP::Request constructor for these common requests.  The
following functions are provided.

GET $url, Header => Value,...
     The GET() function returns a HTTP::Request object initialized with the
     GET method and the specified URL.  Without additional arguments it is
     exactly equivalent to the following call

          HTTP::Request->new(GET => $url)

     but is less cluttered.  It also reads better when used together with
     the LWP::UserAgent->request() method:

          my $ua = new LWP::UserAgent;
          my $res = $ua->request(GET 'http://www.sn.no')
          if ($res->is_success) { ...

     You can also initialize header values in the request by specifying
     some key/value pairs as optional arguments.  For instance:

          $ua->request(GET 'http://www.sn.no',
          	           If_Match => 'foo',
                           From     => 'gisle@aas.no',
                      );

     A header key called 'Content' is special and when seen the value will
     initialize the content part of the request instead of setting a
     header.

HEAD $url, [Header => Value,...]
     Like GET() but the method in the request is HEAD.

PUT $url, [Header => Value,...]
     Like GET() but the method in the request is PUT.

POST $url, [$form_ref], [Header => Value,...]
     This works mostly like GET() with POST as the method, but this
     function also takes a second optional array or hash reference
     parameter ($form_ref).  This argument can be used to pass key/value
     pairs for the form content.  By default we will initialize a request
     using the `application/x-www-form-urlencoded' content type.  This
     means that you can emulate a HTML <form> POSTing like this:

          POST 'http://www.perl.org/survey.cgi',
               [ name   => 'Gisle Aas',
                 email  => 'gisle@aas.no',
                 gender => 'M',
                 born   => '1964',
                 perc   => '3%',
               ];

     This will create a HTTP::Request object that looks like this:

          POST http://www.perl.org/survey.cgi
          Content-Length: 66
          Content-Type: application/x-www-form-urlencoded

          name=Gisle%20Aas&email=gisle%40aas.no&gender=M&born=1964&perc=3%25

     The POST method also supports the `multipart/form-data' content used
     for *Form-based File Upload* as specified in RFC 1867.  You trigger
     this content format by specifying a content type of `'form-data'' as
     one of the request headers.  If one of the values in the $form_ref is
     an array reference, then it is treated as a file part specification
     with the following interpretation:

          [ $file, $filename, Header => Value... ]

     The first value in the array ($file) is the name of a file to open.
     This file will be read and its content placed in the request.  The
     routine will croak if the file can't be opened.  Use an undef as $file
     value if you want to specify the content directly.  The $filename is
     the filename to report in the request.  If this value is undefined,
     then the basename of the $file will be used.  You can specify an empty
     string as $filename if you don't want any filename in the request.

     Sending my `~/.profile' to the survey used as example above can be
     achieved by this:

          POST 'http://www.perl.org/survey.cgi',
               Content_Type => 'form-data',
               Content      => [ name  => 'Gisle Aas',
                                 email => 'gisle@aas.no',
                                 gender => 'M',
                                 born   => '1964',
                                 init   => ["$ENV{HOME}/.profile"],
                               ]

     This will create a HTTP::Request object that almost looks this (the
     boundary and the content of your `~/.profile' is likely to be
     different):

          POST http://www.perl.org/survey.cgi
          Content-Length: 388
          Content-Type: multipart/form-data; boundary="6G+f"

          --6G+f
          Content-Disposition: form-data; name="name"

          Gisle Aas
          --6G+f
          Content-Disposition: form-data; name="email"

          gisle@aas.no
          --6G+f
          Content-Disposition: form-data; name="gender"

          M
          --6G+f
          Content-Disposition: form-data; name="born"

          1964
          --6G+f
          Content-Disposition: form-data; name="init"; filename=".profile"
          Content-Type: text/plain

          PATH=/local/perl/bin:$PATH
          export PATH

          --6G+f--

     If you set the $DYNAMIC_FILE_UPLOAD variable (exportable) to some TRUE
     value, then you get back a request object with a subroutine closure as
     the content attribute.  This subroutine will read the content of any
     files on demand and return it in suitable chunks.  This allow you to
     upload arbitrary big files without using lots of memory.  You can even
     upload infinite files like `/dev/audio' if you wish; however, if the
     file is not a plain file, there will be no Content-Length header
     defined for the request.  Not all servers (or server applications)
     like this.  Also, if the file(s) change in size between the time the
     Content-Length is calculated and the time that the last chunk is
     delivered, the subroutine will `Croak'.

SEE ALSO
========

   See HTTP/Request, LWP/UserAgent,

COPYRIGHT
=========

   Copyright 1997-2000, Gisle Aas

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Construct HTTP::Request objects for form processing
***************************************************

NAME
====

   HTTP::Request::Form - Construct HTTP::Request objects for form
processing

SYNOPSIS
========

   use the following as a tool to query Altavista for "perl" from the
commandline:

     use HTML::TreeBuilder;
     use URI::URL;
     use LWP::UserAgent;
     use HTTP::Request;
     use HTTP::Request::Common;
     use HTTP::Request::Form;

     my $ua = LWP::UserAgent->new;
     my $url = url 'http://www.altavista.digital.com/';
     my $res = $ua->request(GET $url);
     my $tb = HTML::TreeBuilder->new;
     $tb->parse($res->content);
     my @forms = @{$tb->extract_links(qw(FORM))};
     my $f = HTTP::Request::Form->new($forms[0][1], $url);
     $f->field("q", "perl");
     my $response = $ua->request($f->press("search"));
     print $response->content if ($response->is_success);

DESCRIPTION
===========

   This is an extension of the HTTP::Request suite. It allows easy
processing of forms in a user agent by filling out fields, querying
fields, selections and buttons and pressing buttons. It uses
HTML::TreeBuilder generated parse trees of documents (especially the forms
parts extracted with extract_links) and generates it's own internal
representation of forms from which it then generates the request objects
to process the form application.

   If you use HTML::TreeBuilder like me, please be aware of the fact that
the extract_links call in the above example returns an array with
alternating URL and FORM-elements, so the first FORM is actually at index
1 and the second FORM is at index 3!

CLASS METHODS
=============

new($form [, $base [, $debug]])
     The new-method constructs a new form processor. It get's an
     HTML::Element object that contains a form as the single parameter. If
     an base-url is given as an additional parameter, this is used to make
     the form-url absolute in regard to the given URL.

     If debugging is true, the following functions will be a bit "talky"
     on stdio.

INSTANCE METHODS
================

base()
     This returns the parameter $base to the "new" constructor.

link()
     This returns the action attribute of the original form structure.
     This value is cached within the form processor, so you can safely
     delete the form structure after you created the form processor.

method()
     This returns the method attribute of the original form structure.
     This value is cached within the form processor, so you can safely
     delete the form structure as soon as you created the form processor.

fields()
     This method delivers a list of fieldnames that are of "open" type.
     This excludes the "hidden" and "submit" elements, because they are
     already filled with a value (and as such declared as "closed") or as
     in the case of "submit" are buttons, of which only one must be used.

allfields()
     This delivers a list of all fieldnames in the order as they occured
     in the form-source excluding the submit fields.

field($name [, $value])
     This method retrieves or sets a field-value. The field is identified
     by it's name. You have to be sure that you only put a allowed value
     into the field.

field_type($name)
     This method gives you the type of the named field, so that you can
     distinguish on this type. (this is the only way to distinguish
     selections and radio buttons).

is_selection($name)
     This tests if a field is a selection or an input. Radio-Buttons are
     used in the same way as standard selection fields, so is_selection
     returns a true value for radio buttons, too! (Of course, only one
     value is submitted for a radio button)

field_selection($name)
     This delivers the array of the options of a selection. The element
     that is marked with selected in the source is given as the default
     value. This works in the same way for radio buttons, as they are just
     handled as a special case of selections!

is_checkbox($name)
     This tells you if a field is a checkbox. If it is, there are several
     support methods to make use of the special features of checkboxes,
     for example the fact that it is only sent if it is checked.

checkboxes()
     This method delivers a list of all checkbox fields much in the same
     way as the buttons method.

checkbox_check($name) =item checkbox_uncheck($name) =item checkbox_toggle($name)
     These methods set, unset or toggle the checkbox checked state.
     Checkbox values are only added to the result if they are checked.

checkbox_ischecked($name)
     This methods tells you wether a checkbox is checked or not. This is
     important if you want to analyze the state of fields directly after
     the parse.

buttons()
     This delivers a list of all defined and named buttons of a form.

button($button [, $value])
     This gets or sets the value of a button. Normally only getting a
     button value is needed. The value of a button is a reference to an
     array of values (because a button can exist multiple times).

button_type($button)
     This gives you the type of a button (submit/reset/image). The result
     is an array of type names, as a button with one name can exist
     multiple times.

button_exists($button)
     This gives true if the named button exists, false (undef) otherwise.

referer([$value])
     This returns or sets the referer header for an request. This is
     usefull if a CGI needs a set referer for authentication.

press([$name [, $coord ] [, $number]])
     This method creates a HTTP::Request object (via
     HTTP::Request::Common) that sends the formdata to the server with the
     requested method. If you give a button-name, that button is used. If
     you give no button name, it assumes a button without a name and just
     leaves out this last parameter. If the number of the button is given,
     that button value is delivered. If the number is not given, 0 (the
     first button of this name) is assumed.

     The "coord" parameter comes in handy if you have an image button. If
     this is the case, the button press will simulate a press at
     coordinates [2,2] unless you provide an anonymous array with
     different coordinates.

dump()
     This method dumps the form-data on stdio for debugging purpose.

SEE ALSO
========

   See HTTP/Request, HTTP/Request/Common,
see LWP/UserAgent,
HTML/Element, URI/URL,

INSTALLATION
============

     perl Makefile.PL
     make install

REQUIRES
========

     Perl version 5.004 or later

     HTTP::Request::Common
     HTML::TreeBuilder
     LWP::UserAgent

VERSION
=======

   HTTP::Request::Form version 0.6, March 2nd, 2000

RESTRICTIONS
============

   Only a subset of all possible form elements are currently supported.
The list of supported tags as of this version includes:

     INPUT/CHECKBOX
     INPUT/HIDDEN
     INPUT/IMAGE
     INPUT/RADIO
     INPUT/RESET
     INPUT/SUBMIT
     INPUT/FILE
     INPUT/* (are all handled as simple text entry)
     OPTION
     SELECT
     TEXTAREA

BUGS
====

   There is currently no support for multiple selections (you can do them
yourself by setting a selection to a comma-delimited list of values).

   If there are several fields with the same name, you can only set the
value of the first of this fields (this is especially problematic with
checkboxes). This does work with buttons that have the same name, though
(you can press each instance identified by number).

   Error-Checking is currently very limited (not to say nonexistant).

   Support for HTML 4.0 optgroup tags is missing (as is with allmost all
current browsers, so that is not a great loss).

   The button tag (HTML 4.0) is just handled as an alias for the input tag
- this is of course incorrect, but sufficient for support of the usual
button types.

COPYRIGHT
=========

   Copyright 1998, 1999, Georg Bauer <Georg_Bauer@muensterland.org>

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Class encapsulating HTTP Responses
**********************************

NAME
====

   HTTP::Response - Class encapsulating HTTP Responses

SYNOPSIS
========

     require HTTP::Response;

DESCRIPTION
===========

   The `HTTP::Response' class encapsulates HTTP style responses.  A
response consists of a response line, some headers, and (potentially
empty) content. Note that the LWP library also uses HTTP style responses
for non-HTTP protocol schemes.

   Instances of this class are usually created and returned by the
request() method of an `LWP::UserAgent' object:

     #...
     $response = $ua->request($request)
     if ($response->is_success) {
         print $response->content;
     } else {
         print $response->error_as_HTML;
     }

   `HTTP::Response' is a subclass of `HTTP::Message' and therefore
inherits its methods.  The inherited methods most often used are header(),
push_header(), remove_header(), headers_as_string(), and content().  The
header convenience methods are also available.  See HTTP/Message,
for details.

   The following additional methods are available:

$r = HTTP::Response->new($rc, [$msg, [$header, [$content]]])
     Constructs a new `HTTP::Response' object describing a response with
     response code $rc and optional message $msg.  The message is a short
     human readable single line string that explains the response code.

$r->code([$code])
$r->message([$message])
$r->request([$request])
$r->previous([$previousResponse])
     These methods provide public access to the object attributes.  The
     first two contain respectively the response code and the message of
     the response.

     The request attribute is a reference the request that caused this
     response.  It does not have to be the same request as passed to the
     $ua->request() method, because there might have been redirects and
     authorization retries in between.

     The previous attribute is used to link together chains of responses.
     You get chains of responses if the first response is redirect or
     unauthorized.

$r->status_line
     Returns the string "<code> <message>".  If the message attribute is
     not set then the official name of <code> (see HTTP/Status)
     is substituted.

$r->base
     Returns the base URI for this response.  The return value will be a
     reference to a URI object.

     The base URI is obtained from one the following sources (in priority
     order):

       1. Embedded in the document content, for instance <BASE HREF="...">
          in HTML documents.

       2. A "Content-Base:" or a "Content-Location:" header in the
          response.

          For backwards compatability with older HTTP implementations we
          will also look for the "Base:" header.

       3. The URI used to request this response. This might not be the
          original URI that was passed to $ua->request() method, because
          we might have received some redirect responses first.

          When the LWP protocol modules produce the HTTP::Response object,
     then any base URI embedded in the document (step 1) will already have
     initialized the "Content-Base:" header. This means that this method
     only performs the last 2 steps (the content is not always available
     either).

$r->as_string
     Returns a textual representation of the response.  Mainly useful for
     debugging purposes. It takes no arguments.

$r->is_info
$r->is_success
$r->is_redirect
$r->is_error
     These methods indicate if the response was informational, sucessful, a
     redirection, or an error.

$r->error_as_HTML()
     Returns a string containing a complete HTML document indicating what
     error occurred.  This method should only be called when $r->is_error
     is TRUE.

$r->current_age
     Calculates the "current age" of the response as specified by
     <draft-ietf-http-v11-spec-07> section 13.2.3.  The age of a response
     is the time since it was sent by the origin server.  The returned
     value is a number representing the age in seconds.

$r->freshness_lifetime
     Calculates the "freshness lifetime" of the response as specified by
     <draft-ietf-http-v11-spec-07> section 13.2.4.  The "freshness
     lifetime" is the length of time between the generation of a response
     and its expiration time.  The returned value is a number representing
     the freshness lifetime in seconds.

     If the response does not contain an "Expires" or a "Cache-Control"
     header, then this function will apply some simple heuristic based on
     'Last-Modified' to determine a suitable lifetime.

$r->is_fresh
     Returns TRUE if the response is fresh, based on the values of
     freshness_lifetime() and current_age().  If the response is no longer
     fresh, then it has to be refetched or revalidated by the origin
     server.

$r->fresh_until
     Returns the time when this entiy is no longer fresh.

COPYRIGHT
=========

   Copyright 1995-1997 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Check the HTTP response code for a link
***************************************

NAME
====

   HTTP::SimpleLinkChecker - Check the HTTP response code for a link

SYNOPSIS
========

     use HTTP::SimpleLinkChecker;

     my $code = HTTP::SimpleLinkChecker::check_link($url);

     unless( defined $code )
     	{
     	print "Error: $HTTP::SimpleLinkChecker::ERROR\n";
     	}

DESCRIPTION
===========

   You don't have to know anything about objected-oriented Perl, LWP, or
the HTTP module to be able to check your links. This module is designed
for the casual user. It has one function, `check_link', that returns the
HTTP response code that it receives when it tries to fetch the web address
passed to it. The undef value is returned for any failure and the
`$HTTP::SimpleLinkChecker::ERROR' variable is set.

   The HEAD method is tried first, although if anything other than a good
status code (those less than 400) is received, another request is made
with the GET method.

AUTHOR
======

   brian d foy <comdog@panix.com>

HTTP Status code processing
***************************

NAME
====

   HTTP::Status - HTTP Status code processing

SYNOPSIS
========

     use HTTP::Status;

     if ($rc != RC_OK) {
         print status_message($rc), "\n";
     }

     if (is_success($rc)) { ... }
     if (is_error($rc)) { ... }
     if (is_redirect($rc)) { ... }

DESCRIPTION
===========

   HTTP::Status is a library of routines for defining and classifying HTTP
status codes for libwww-perl.  Status codes are used to encode the overall
outcome of a HTTP response message.  Codes correspond to those defined in
RFC 2616 and RFC 2518.

CONSTANTS
=========

   The following constant functions can be used as mnemonic status code
names:

     RC_CONTINUE				(100)
     RC_SWITCHING_PROTOCOLS		(101)
     RC_PROCESSING                        (102)

     RC_OK				(200)
     RC_CREATED				(201)
     RC_ACCEPTED				(202)
     RC_NON_AUTHORITATIVE_INFORMATION	(203)
     RC_NO_CONTENT			(204)
     RC_RESET_CONTENT			(205)
     RC_PARTIAL_CONTENT			(206)
     RC_MULTI_STATUS                      (207)

     RC_MULTIPLE_CHOICES			(300)
     RC_MOVED_PERMANENTLY			(301)
     RC_FOUND				(302)
     RC_SEE_OTHER				(303)
     RC_NOT_MODIFIED			(304)
     RC_USE_PROXY				(305)
     RC_TEMPORARY_REDIRECT		(307)

     RC_BAD_REQUEST			(400)
     RC_UNAUTHORIZED			(401)
     RC_PAYMENT_REQUIRED			(402)
     RC_FORBIDDEN				(403)
     RC_NOT_FOUND				(404)
     RC_METHOD_NOT_ALLOWED		(405)
     RC_NOT_ACCEPTABLE			(406)
     RC_PROXY_AUTHENTICATION_REQUIRED	(407)
     RC_REQUEST_TIMEOUT			(408)
     RC_CONFLICT				(409)
     RC_GONE				(410)
     RC_LENGTH_REQUIRED			(411)
     RC_PRECONDITION_FAILED		(412)
     RC_REQUEST_ENTITY_TOO_LARGE		(413)
     RC_REQUEST_URI_TOO_LARGE		(414)
     RC_UNSUPPORTED_MEDIA_TYPE		(415)
     RC_REQUEST_RANGE_NOT_SATISFIABLE     (416)
     RC_EXPECTATION_FAILED		(417)
     RC_UNPROCESSABLE_ENTITY              (422)
     RC_LOCKED                            (423)
     RC_FAILED_DEPENDENCY                 (424)

     RC_INTERNAL_SERVER_ERROR		(500)
     RC_NOT_IMPLEMENTED			(501)
     RC_BAD_GATEWAY			(502)
     RC_SERVICE_UNAVAILABLE		(503)
     RC_GATEWAY_TIMEOUT			(504)
     RC_HTTP_VERSION_NOT_SUPPORTED	(505)
     RC_INSUFFICIENT_STORAGE              (507)

FUNCTIONS
=========

   The following additional functions are provided.  Most of them are
exported by default.

status_message($code)
     The status_message() function will translate status codes to human
     readable strings. The string is the same as found in the constant
     names above.  If the $code is unknown, then undef is returned.

is_info($code)
     Return TRUE if $code is an Informational status code.  This class of
     status code indicates a provisional response which can't have any
     content.

is_success($code)
     Return TRUE if $code is a *Successful* status code.

is_redirect($code)
     Return TRUE if $code is a Redirection status code. This class of
     status code indicates that further action needs to be taken by the
     user agent in order to fulfill the request.

is_error($code)
     Return TRUE if $code is an Error status code.  The function return
     TRUE for both client error or a server error status codes.

is_client_error($code)
     Return TRUE if $code is an *Client Error* status code. This class of
     status code is intended for cases in which the client seems to have
     erred.

     This function is not exported by default.

is_server_error($code)
     Return TRUE if $code is an *Server Error* status code. This class of
     status codes is intended for cases in which the server is aware that
     it has erred or is incapable of performing the request.

     This function is not exported by default.

BUGS
====

   Wished @EXPORT_OK had been used instead of @EXPORT in the beginning.
Now too much is exported by default.

Test remote URLs or local web files
***********************************

NAME
====

   HTTP::WebTest - Test remote URLs or local web files

SYNOPSIS
========

     This module can accept input parameters from a parameter file
     or subroutine arguments.

     TO RUN WEB TESTS DEFINED BY SUBROUTINE ARGUMENTS:

     use HTTP::WebTest;
     run_web_test(\@web_tests, \$num_fail, \$num_succeed, \%test_options)

     or

     use HTTP::WebTest;
     run_web_test(\@web_tests, \$num_fail, \$num_succeed)

     TO RUN WEB TESTS DEFINED BY A PARAMETER FILE:

     use sigtrap qw(die normal-signals); # Recommended, not necessary
     use HTTP::WebTest;
     $webtest = HTTP::WebTest->new();
     $webtest->web_test('my_web_tests.wt', \$num_fail, \$num_succeed);

     The web_test() method has an option to test a local file by
     starting Apache on a private port, copying the file to a temporary
     htdocs directory and fetching the page from Apache.  If you are
     testing with multiple parameter files, you can avoid restarting
     Apache each time by calling new() only once and recycling the object:

     use sigtrap qw(die normal-signals); # Recommended, not necessary
     use HTTP::WebTest;
     $webtest = HTTP::WebTest->new();
     foreach $file (@ARGV) {
        $webtest->web_test($file, \$num_fail, \$num_succeed);
     }

     TO ENABLE DEBUGGING MESSAGES (OUTPUT TO STDOUT):

     If you are calling the web_test method, use the debug parameter.
     If you are calling the run_web_test method, do this:

     use HTTP::WebTest;
     $HTTP::WebTest::Debug = 1; # Diagnostic messages
     $HTTP::WebTest::Debug = 2; # Messages and preserve temp Apache dir
     run_web_test(\@web_tests, \$num_fail, \$num_succeed)

DESCRIPTION
===========

   This module runs tests on remote URLs or local web files containing
Perl/HTML/JavaScript/etc. and generates a detailed test report.  The test
specifications can be read from a parameter file or input as method
arguments.  If you are testing a local file, Apache is started on a
private/dynamic port with a configuration file in a temporary directory.
The module displays the test results on the terminal by default or directs
them to a file.  The module optionally e-mails the test results.  When the
calling program exits, the module stops the local instance of Apache and
deletes the temporary directory.

   Each test consists of literal strings or regular expressions that are
either required to exist or forbidden to exist in the fetched page.  You
can also specify tests for the minimum and maximum number of bytes in the
returned page.  If you are testing a local file, the module checks the
error log in the temporary directory before and after the file is fetched
from Apache.  If messages are written to the error log during the fetch,
the module flags this as an error and writes the messages to the output
test report.

   The wt script is provided for running HTTP::WebTest from the command
line.

   Data flow for WebTest using a remote URL:

     --------------              -------------
     |            |              |           |
     | Input      |------------->|  WebTest  |
     | parameters |              |           |
     |            |              -------------
     --------------                  |   ^
                                     |   |
                                     V   |
     -------------               ------------
     |           |    request    |          |
     | Remote    |<--------------|   HTTP   |
     | webserver |-------------->|   user   |
     |           |    response   |   agent  |
     -------------               |          |
                                 ------------

     Data flow diagram for WebTest using a local web file:

     --------------           ---------------------
     |            |           |                   |
     | Input      |           |  web page code    |
     | parameters |           |  (HTML/perl/etc.  |
     |            |           |                   |
     --------------           ---------------------
           |                            |
           |  ---------------------------
           |  |
           V  V              ------------------------
     -------------           |                      |
     |           |---------->| Temporary Apache     |
     |  WebTest  |           | directories (htdocs, |
     |           |<----------| conf, logs)          |
     -------------           |                      |
         |  ^                ------------------------
         |  |                        |    ^
         V  |                        V    |
     ------------             ----------------------
     |          |   request   |                    |
     |   HTTP   |------------>| Local instance of  |
     |   user   |             | Apache webserver   |
     |   agent  |<------------|                    |
     |          |   response  ----------------------
     ------------

METHODS
=======

     new($proto)
     new()
        Create new HTTP::WebTest object.  $proto (optional) is
        either a reference or a class (package) name.  Returns a new
        HTTP::WebTest object.

     web_test($param_file, \$num_fail, \$num_succeed)
     web_test($param_file, \$num_fail, \$num_succeed, $save_output)
        Reads and validates input parameters, fetches one or more
        web pages, runs tests, writes results to standard output
        or a file.  Optionally e-mails test results if error found.
        If the parameters specify a test of a local web source file,
        starts Apache on a private/dynamic port and copies the file to
        a temporary htdocs directory.

     Input arguments:
     $param_file - A relative or absolute pathname to a parameter
        file.  See the FILES section for a description of the file.
     $save_output (optional) - Option to save program output to a file.
        The routine constructs the file name by taking the value of
        $param_file, removing the file extension if it exists and
        appending ".out".  Error messages are always sent to standard
        error.
        = no       -> Send output to standard output
        = yes      -> Save output to file, overwrite existing file
        = preserve -> Save output to file unless file exists

     Output arguments:
     \$num_fail - The number of tests that failed.
     \$num_succeed - The number of tests that succeeded.

     Return values:
     1 -> All tests ran successfully with no failures.
     0 -> Syntax error in input parameter file, system runtime error or
          one or more of the tests failed.

     run_web_test(\@web_tests, \$num_fail, \$num_succeed, \%test_options)
     run_web_test(\@web_tests, \$num_fail, \$num_succeed)
        Validates input parameters, fetches one or more urls, runs
        tests, writes results to standard output or a file.  Optionally
        e-mails test results.

     Input/output arguments:
     \@web_tests - An arrayref of hashrefs.  Each hashref defines
        tests for one URL.

        Some of the hash keys can override the value of the
        corresponding $test_options keys.  For example, if the
        max_bytes hash key is defined in $test_options and you want
        to disable the max_bytes test a particular URL, set the
        web_tests max_bytes hash key to a value of undef or ''.

     If one of the keys below does not exist in one of the
     web_test hashes on input, the module checks the value for
     the corresponding key in the $test_options hash.  If that
     value is defined, then the value from $test_options is used
     during the tests for that web_test hash.

     All input values and keys are preserved on output, except
     the num_fail and num_succeed keys.

     web_tests keys:
     accept_cookies - Overrides the value of the corresponding
        $test_options key FOR THIS URL ONLY.
     auth - Overrides the value of the corresponding test_options
        key FOR THIS URL ONLY.
     cookies - Arrayref of arrayrefs containing cookies to pass
        with the HTTP request.  See RFC 2965 for details
        (ftp.isi.edu/in-notes/rfc2965.txt).  Each array must have
        an even number of elements and must contain at least 10
        elements.  Each array has the form ( version name value
        path domain port path_spec secure maxage discard name1
        value1 name2 value2 ... ), with the following definitions.
        (Required elements are marked with an asterisk; elements
        that are not required can be specified using the undef
        value or ''.)

     *version: Version number of cookie spec to use, usually 0.
     *name: Name of cookie. Cannot begin with a $ character.
     *value: Value of cookie.
     *path: URL path name for which this cookie applies. Must
         begin with a / character.  See also path_spec.
     *domain: Domain for which cookie is valid. Should begin
         with a period.  Must either contain two periods or be
         equal to '.local'.
      port: List of allowed port numbers that the cookie may be
         returned to.  If not specified, cookie can be returned
         to any port.  Must be specified using the format N or
         N,N ..., where N is one or more digits.
      path_spec: Ignored if version is less than 1.  Option to
         ignore the value of path.  Default value is 0.
         = 1 -> Use the value of path.
         = 0 -> Ignore the specified value of path.
      secure: Option to require secure protocols for cookie
         transmission.  Default value is 0.
         = 1 -> Use only secure protocols to transmit cookie.
         = 0 -> Secure protocols not required for transmission.
      maxage: Number of seconds until cookie expires.
      discard: Option to discard cookie when program exits.
         Default 0.  (The cookie will be discarded regardless
         of the value of this element.)
         = 1 -> Discard cookie.
         = 0 -> Don't discard cookie.
      name/value: Zero, one or several name/value pairs may be
         specified.  The name parameters are words such as
         Comment or CommentURL and the value parameters are
         strings that may contain embedded blanks.

     ignore_case - Option to do case-insensitive string matching
                   for text_forbid and text_require arguments.
                    = 'yes'   -> Ignore case while matching strings.
                    Otherwise -> Do case-sensitive string matching.
     ignore_error_log - Option to ignore messages in Apache error
        log.  (See the error_log key in test_options argument.)
        = 'yes' -> Do not check for messages in the error log
                   FOR THIS URL ONLY.
        Otherwise, check messages if error_log key in test_options
        argument is defined.
     max_bytes - Overrides the value of the corresponding
        $test_options key FOR THIS URL ONLY.
     min_bytes - Overrides the value of the corresponding
        $test_options key FOR THIS URL ONLY.
     method - The type of the HTTP request, either 'get' or 'post'.
        If undefined or key does not exist, 'get' is used.
     num_fail (Output) - The number of tests that failed.  If the
        fetch of the URL fails, one error is counted and the tests
        for that URL are skipped.
     num_succeed (Output) - The number of tests that succeeded.  The
        successful fetch of the URL is not counted, only successful
        tests.  If the error_log argument is specified, the absence
        of errors in the logs is counted as a successful test.
     params - A hashref or arrayref containing name/value pairs to
        be passed as parameters to the URL.  (This element is
        used to test pages that process input from forms.) Unless
        the method key is set to post, these pairs are URI-escaped
        and appended to the requested URL.  (See
        http://www.ietf.org/rfc/rfc2396.txt for URI escapes.)
     proxies - A hashref or arrayref containing service name
        / proxy URL pairs that specify proxy servers to use for
        requests.  For example:
        proxies = ( http => http://http_proxy.mycompany.com
                    ftp  => http://ftp_proxy.mycompany.com )
     regex_forbid - Overrides the value of the corresponding
        $test_options key FOR THIS URL ONLY.
     regex_require - Overrides the value of the corresponding
        $test_options key FOR THIS URL ONLY.
     send_cookies - Overrides the value of the corresponding
        $test_options key FOR THIS URL ONLY.
     show_html - Overrides the value of the corresponding
        $test_options key FOR THIS URL ONLY.
     test_name - Name associated with this url in the test report
        and error messages.
     text_forbid - Overrides the value of the corresponding
        $test_options key FOR THIS URL ONLY.
     text_require - Overrides the value of the corresponding
        $test_options key FOR THIS URL ONLY.
     url - The URL to fetch and test.  This key is REQUIRED. If
        it begins with 'www.', 'http://' is prefixed.

     Output arguments:
     \$num_fail - Total number of tests that failed.
     \$num_succeed - Total number of tests that succeeded.

     Input arguments:
     \%test_options - (Optional) A hashref defining testing options.
        All, some or none of the keys may be defined.  Some of these
        options can also be specified in the web_tests argument.  The
        allowed hash keys are:

     accept_cookies - Option to accept cookies from the web server.
        = 'no'     -> Do not accept cookies.
        Otherwise  -> Accept cookies.
     auth - Arrayref containing a userid and password to be used
        for web page access authorization.
     error_log - The pathname of a local web server error log.
        The module counts the number of lines in the error
        log before and after each request.  If the number of
        lines increases, an error is counted and the additional
        lines are listed in the report.  (This argument should
        be used only when the local web server is running in
        single-process mode.  Otherwise, requests generated by
        other processes/users may add lines to the error log that
        are not related to the requests generated by this module.)
     fh_out - A filehandle for a file that the test report will be
        written to instead of the terminal.
     mail_addresses - Arrayref containing one or more e-mail
        addresses.
     mail - Option to e-mail output to one or more addresses.
        = 'all'     -> Send e-mail containing test results.
        = 'errors'  -> Send e-mail only if one or more tests fails.
        Otherwise   -> Do not send e-mail.
     mail_server - Fully-qualified name of of the mail server
        (e.g., mailhost.mycompany.com).
     max_bytes - Maximum number of bytes expected in returned
        pages.  If this value is exceeded, an error message is
        displayed.
     min_bytes - Minimum number of bytes expected in returned
        pages.  If the number of returned bytes is less than this
        value, an error message is displayed.

     (The regex_forbid and regex_require parameters contain
     one or more Perl regular expressions.  These are compared
     to the fetched page contents as the right hand side of a
     "=~" operator.  If you want to search for a literal string,
     use the text_forbid and text_require arguments.  For more
     information, type "man perlre" or see Programming Perl,
     3rd edition, Chapter 5.)

     regex_forbid - Arrayref of regular expressions that are
        forbidden to exist in the returned page.
     regex_require - Arrayref of regular expressions that are
        required to exist in the returned page.
     send_cookies - Option to send cookies to web server.  This
        applies to cookies received from the web server or cookies
        specified using the cookies key of the web_test argument.
        = 'no'     -> Do not send cookies to the web server.
        Otherwise  -> Send cookies to the web server.
     show_cookies - Option to display any cookies sent or received.
        = 'yes'    -> Display cookies in report.
        Otherwise  -> Do not display.
     show_html - Option to include the returned web page in the
        test report.
        = 'yes'    -> Display the web page in the test report.
        Otherwise  -> Do not display the web page.
     terse - Option to display shorter test report.
        = 'summary'     -> Only a one-line summary for each URL.
        = 'failed_only' -> Only tests that failed and the summary.
        Otherwise       -> Show all tests and the summary.
     text_forbid - Arrayref of text strings that are forbidden to
        exist in the returned page.
     text_require - Arrayref of text strings that are required to
        exist in the returned page.

     Return values:
     1 -> All tests succeeded.
     0 -> Error in input parameters, system runtime error, or one
          or more of the tests failed.

     DESTROY()
        Kills Apache (if started), deletes temporary directories (if
        created).  Returns 1 if clean up tasks were successful, 0
        otherwise.

ENVIRONMENT VARIABLES
=====================

     None.

FILES
=====

     The web_test() method requires (1) one or more input parameter
     files, and (2) if the file_path parameter is specified, a directory
     tree that contains the subdirectories and files described in the
     APACHE DIRECTORY AND FILES section below.

     PARAMETER FILE

     The input parameters are specified in a text file. You must pass
     the name of the file as an argument to the web_test() method.
     If you are running dozens of tests, you may want to divide them
     into several parameter files.  This will organize the tests
     and reduce the size of the output and e-mail messages.  However,
     cookies passed to or received from the web server(s) are not shared
     between tests in different parameter files.

     Parameters - Overview
     =====================
     There are over 30 parameters, but the only required parameters
     are test_name, end_test, and either url or file_path.  Also, if
     you specify the file_path parameter, you will have to specify the
     apache_exec parameter.

     Each parameter is either a test block parameter, a global parameter,
     or both.  TEST BLOCK PARAMETERS are parameters specified between
     a test_name parameter and an end_test directive.  Test block
     parameters apply only to the tests for the file_path or url
     specified in that test block.  You can specify one or many test
     blocks in a parameter file.  GLOBAL PARAMETERS are parameters
     specified outside of a test block.  Global parameters apply to
     every test block in the parameter file.

     You can specify certain parameters as BOTH GLOBAL PARAMETERS AND
     TEST BLOCK PARAMETERS.  These include the parameters accept_cookies,
     auth, ignore_case, ignore_error_log, regex_forbid, regex_require,
     send_cookies, text_forbid and text_require.  If you specify one of
     these within a test block, that value is used instead of the value
     of the corresponding global parameter for that test block only.
     If you specify some, but not all, of these parameters in a test
     block, the global parameter values are used for the unspecified
     test block parameters.

     Parameters - Short descriptions
     ===============================
     Parameters that are always required are marked with an asterisk.
     Parameters that are usually required are marked with a plus sign.

     accept_cookies: Option to accept cookies sent by web server.
     apache_dir: Name of directory containing Apache files.
      +apache_exec: Path name of Apache executable.
     apache_loglevel: Apache logging level.
     apache_max_wait: Maximum seconds to wait for Apache to start.
     apache_options: Additional Apache command line options.
     auth: Two-element list containing userid and password to be passed
        to web server for page access authorization.
     cookie: List specifying a cookie to send to the web server.
     debug: Option to output verbose diagnostic messages.
      *end_test: Signifies the end of a test block.
      +file_path: Two-element list containing name of web file to test and
        subdirectory path relative to the htdocs directory to copy it to.
     ignore_case: Option to do case-insensitive matching with text_forbid
        and text_require parameters.
     ignore_error_log: Option to ignore errors found in Apache error log.
     include_file_path: List containing files to copy and subdirectory
        path relative to the Apache ServerRoot directory to copy them to.
     mail: Option to send e-mail containing results of tests.
     mail_addresses: List of e-mail addresses to send reports to.
     mail_server: Name of mail server.
     method: HTTP request method; either get or post.
     max_bytes: Maximum number of bytes expected in returned page.
     min_bytes: Minimum number of bytes expected in returned page.
     params: List of parameter name/value pairs to be passed to server.
     proxies: List of service name / proxy URL pairs to use for requests.
     regex_forbid: List of strings/regexs that must NOT occur in page.
     regex_require: List of strings/regexs that MUST occur in page.
     save_output: Option to redirect the program output to a file.
     send_cookies: Option to send cookies to the web server.
     show_cookies: Option to list cookies sent or received.
     show_html: Option to display the HTML source with the output.
      *test_name: Name of test.
     text_forbid: List of strings that must NOT occur in page.
     text_require: List of strings that MUST occur in page.
      +url: URL to test.
     terse: Option to display shorter test report.

     Parameter file format
     =====================
     The program ignores:
        * lines consisting of nothing but white space (blanks or tabs)
        * lines beginning with a number sign ("#")
        * lines beginning with white space (blanks or tabs) followed by
          a number sign

     The order of the parameters in the parameter file is arbitrary,
     with the following exceptions:
        * Test block parameters MUST occur between a test_name parameter
          and an end_test directive.
        * Global parameters must NOT occur between a test_name parameter
          and an end_test directive.  (This requirement does not apply to
          parameters that are both global and test block parameters.)
        * The parameter save_output, if specified, should be the first
          parameter in the file.  (This is not required.)

     Parameters are either scalar (single-valued) or lists (single or
     multi-valued).

     You can specify scalar parameters using forms such as:
     name = value
     name =
            value
     name = 'value'

     You can specify list parameters using forms such as:
     name = ( first value
              second value )
     name = ( first value => second value
              third value => fourth value
            )
     name = ( first value => second value )
     name = (
              'first value'
              'second value' )
     name = (
              first value
              second value
              third value => 'fourth value'
            )
     name =
        ( first value
          'second value' )
     name = (
              'first value'
              'second value'
            )
     (The equals sign must be followed by a space, tab or newline; all
     other spaces are optional.)

     PARAMETER VALUES BEGINNING AND ENDING WITH A SINGLE QUOTE WILL HAVE
     THE SINGLE QUOTES REMOVED.  For example, 'foobar' is parsed as a
     value of foobar and ''foobar'' is parsed as a value of 'foobar'.
     To specify a null (placeholder) value, use ''.

     You MUST enclose the parameter value in single quotes if you want
     to specify:
        * A value beginning with a left parenthesis
        * A value ending with a right parenthesis
        * A value beginning with leading white space (blanks or tabs)
        * A value ending with trailing white space (blanks or tabs)
        * A value beginning and ending with single quotes

     Examples of parameter files
     ===========================
     The parameters below specify tests of a local file and a remote
     URL.  The tests specified by the text_forbid parameter apply to
     both the "RayCosoft home page" and the "Yahoo home page" tests.
     Hence, if either returned page contains one of the case-
     insensitive strings in text_forbid, the test fails.  If any test
     fails, an e-mail will be sent to tester@unixscripts.com.

     apache_exec = /usr/sbin/apache
     ignore_case = yes
     mail = errors
     mail_addresses = ( tester@unixscripts.com )
     mail_server = mailhost.unixscripts.com
     text_forbid = ( Premature end of script headers
                     an error occurred while processing this directive
                   )

     test_name = 'RayCosoft home page (static)'
        file_path = ( raycosoft_home.html => . )
        text_require = (
           <a href="/dept/peopledev/new_employee/"><font color="#0033cc">
           <a href="https://www.raycosoft.com/"><font color=
                       )
     end_test

     test_name = Yahoo home page
        url = www.yahoo.com
        text_require = ( <a href=r/qt>Quotations</a>...<br> )
        min_bytes = 13000
        max_bytes = 19000
     end_test

     The parameters below specify a test of a local file containing Perl
     code using the Apache::ASP module.  The includes.htm file requires
     five include files and two Perl modules, which are copied using
     the include_file_path parameter.

     apache_exec = /usr/sbin/apache
     ignore_case = yes
     include_file_path = ( footer.inc => htdocs/apps/myapp/inc
                           header.inc => htdocs/apps/myapp/inc
                           head.inc   => htdocs/apps/myapp/inc
                           go.script  => htdocs/shared/includes
                           go.include => htdocs/shared/includes
                           ../utils/DBconn.pm  => lib/perl/utils
                           ../utils/Window.pm  => lib/perl/utils
                         )

     test_name = includes.htm
         file_path = ( includes.htm => apps/myapp )
         min_bytes = 33000
         max_bytes = 35000
         text_require = ( input type=hidden name=control value= )
         text_forbid  = ( Premature end of script headers
                          an error occurred while processing this directive
                        )
     end_test

     Parameters - Detailed descriptions
     ==================================
     PARAMETER: accept_cookies TYPE: global and/or test block parameter
     DEFAULT: yes  ALLOWED VALUES: no yes  OPTIONAL PARAMETER.
     DESCRIPTION: Option to accept and save cookies sent by the web
     server.  These cookies exist only while the program is executing
     and do not affect subsequent runs.  These cookies do not affect your
     browser or any software other than the test program.  These cookies
     are only accessible to other tests in the same parameter file.

     You can specify this parameter globally or within a test block.
     If you specify it as both a global and a test block parameter, the
     value in the test block applies only to that test block.  See also
     the send_cookies parameter.

     PARAMETER: apache_dir  TYPE: global parameter
     DEFAULT: /usr/local/etc/http-webtest
     DESCRIPTION: Absolute or relative path name of directory containing
     Apache files.  See the APACHE DIRECTORY AND FILES section below.
     This parameter is ignored unless the file_path parameter is specified.

     PARAMETER: apache_exec  TYPE: global parameter
     NO DEFAULT.  REQUIRED if the file_path parameter is specified.
     DESCRIPTION: Path name of Apache executable.  This command must be
     in your $PATH or the path name must start with '/'.  This parameter
     is ignored unless the file_path parameter is specified.

     PARAMETER: apache_loglevel  TYPE: global parameter
     DEFAULT: warn  OPTIONAL PARAMETER.
     ALLOWED VALUES: debug info notice warn error crit alert emerg
     DESCRIPTION: Apache logging level.  If you use a level less than
     warn (i.e., debug, info, or notice), the program may generate
     irrelevant errors.  This parameter is ignored unless the file_path
     parameter is specified.  See also the ignore_error_log parameter.

     PARAMETER: apache_max_wait  TYPE: global parameter
     DEFAULT: 64  ALLOWED VALUES: Any integer > 9 and < 601  OPTIONAL
     PARAMETER.
     DESCRIPTION: Maximum number of seconds to wait for Apache to start.
     The program starts Apache, waits 4 seconds and fetches a test page.
     If this fails, it doubles the wait interval, restarts Apache,
     waits and fetches a test page.  This process repeats until the
     test page is fetched successfully or the wait interval becomes
     greater than apache_max_wait.  This parameter is ignored unless
     the file_path parameter is specified.

     PARAMETER: apache_options  TYPE: global parameter
     DEFAULT: -X  ALLOWED VALUES: See Apache man page.  OPTIONAL PARAMETER.
     DESCRIPTION: Additional Apache command line options.  Many of the
     options cause Apache to exit immediately after starting, so the
     web page tests will not run.  This parameter is ignored unless
     the file_path parameter is specified.

     PARAMETER: auth  TYPE: global and/or test block parameter
     No default.  ALLOWED VALUES: A one or two element list.  OPTIONAL
     PARAMETER.
     DESCRIPTION: Userid and password, in that order, to be passed to the
     web server if needed for authorization.  If you specify only one
     element, it is used as the userid and the program will prompt you
     interactively for the password.  If you specify values of 'prompt'
     and 'userid_password' in that order, the program will prompt you for
     both the userid and password.  If you specify values of 'prompt'
     and 'password' in that order, the program will prompt you for
     the password and use the userid of the user running the program.
     (This last option is probably not what you want, unless your Unix
     userid and web page userid are the same.)

     You can specify this parameter globally or within a test block.
     If you specify it as both a global and a test block parameter,
     the value in the test block applies only to that test block.

     PARAMETER: cookie  TYPE: test block parameter
     NO DEFAULT.  ALLOWED VALUES: A list with an even number of elements
     and at least 10 elements.  The cookie parameter is ignored if the
     send_cookies parameter is set to no.  OPTIONAL PARAMETER.  Multiple
     cookie parameters may be specified.
     DESCRIPTION: List that specifies a cookie to send to the web server.
     See RFC 2965 for details (ftp.isi.edu/in-notes/rfc2965.txt).
     You may specify multiple cookies within each test block by
     specifying multiple instances of the cookie parameter.  The cookie
     parameter has the form:

     ( version
       name
       value
       path
       domain
       port
       path_spec
       secure
       maxage
       discard
       name1
       value1
       name2
       value2
       ...
     )

     Any element not marked below as REQUIRED may be defaulted by
     specifying a null value of ''

     version: Version number of cookie spec to use, usually 0. (REQUIRED)
     name: Name of cookie. (REQUIRED)  Cannot begin with a $ character.
     value: Value of cookie. (REQUIRED)
     path: URL path name for which this cookie applies. (REQUIRED)  Must
        begin with a / character.  See also path_spec.
     domain: Domain for which cookie is valid. (REQUIRED)  Should begin
        with a period.  Must either contain two periods or be equal
        to .local
     port: List of allowed port numbers that the cookie may be returned
        to.  If not specified, cookie can be returned to any port.
        Must be specified using the format N or N,N ..., where N is one
        or more digits.
     path_spec: Ignored if version is less than 1.  Option to ignore the
        value of path.  Default value is 0.
        = 1 -> Use the value of path.
        = 0 -> Ignore the specified value of path.
     secure: Option to require secure protocols for cookie transmission.
        Default value is 0.
        = 1 -> Use only secure protocols to transmit this cookie.
        = 0 -> Secure protocols are not required for transmission.
     maxage: Number of seconds until cookie expires.
     discard: Option to discard cookie when the program finishes.
        Default 0.  (The cookie will be discarded regardless of the value
        of this element.)
        = 1 -> Discard cookie when the program finishes.
        = 0 -> Don't discard cookie.
     name/value: Zero, one or several name/value pairs may be specified.
        The name parameters are words such as Comment or
        CommentURL and the value parameters are strings that
        may contain embedded blanks.

     See RFC 2965 for details (ftp.isi.edu/in-notes/rfc2965.txt).

     An example cookie would look like:
     ( 0
       WebTest cookie #1
       expires&2592000&type&consumer
       /
       .unixscripts.com
       ''
       0
       0
       200
       1
     )

     PARAMETER: debug  TYPE: global parameter
     DEFAULT: no  ALLOWED VALUES: no yes preserve  OPTIONAL PARAMETER.
     DESCRIPTION: This parameter is primarily for use by programmers
     modifying and testing the program code.  The "yes" value makes
     the program display verbose diagnostic messages.  (If you want
     diagnostics on the parameter processing, this parameter should
     preceed all other parameters.)  The "preserve" value makes the
     program display verbose diagnostic messages and prevents the
     program from deleting the temporary Apache directory, which is
     named "/tmp/webtest_x_y", where x and y are arbitrary positive
     integers.

     DIRECTIVE: end_test  TYPE: test block directive
     NO VALUE (i.e. specify end_test with no equals sign or value).
     There MUST be one end_test directive for each test_name parameter.
     Directive is REQUIRED.
     DESCRIPTION: Signifies the end of a test block.

     PARAMETER: file_path  TYPE: test block parameter
     NO DEFAULT.  ALLOWED VALUES: Second list element cannot begin with
     '../' or contain '/../'.  You MUST specify file_path or url, but
     not both, in each test block.
     DESCRIPTION: Two-element list.  First element is the file to test,
     either an absolute or a relative pathname.  Second element is the
     subdirectory pathname, relative to the Apache htdocs directory, to
     copy the file to.  The copied file will have the same basename as
     the first element and the relative pathname of the second element.
     To copy the file directly to the htdocs directory, use a pathname of
     . or './.'.

     For example:
     file_path = ( /home/tester/testfile.html => mydepartment/myproject )
     will copy the file to ./htdocs/mydepartment/myproject/testfile.html.

     PARAMETER: ignore_case  TYPE: global and/or test block parameter
     DEFAULT: no  ALLOWED VALUES: no yes  OPTIONAL PARAMETER.
     DESCRIPTION: Option to do case-insensitive matching for text_forbid
     and text_require parameters.  This does not affect the regex_forbid
     or regex_require parameters.

     PARAMETER: ignore_error_log  TYPE: global and/or test block
     parameter  DEFAULT: no  ALLOWED VALUES: no yes  OPTIONAL PARAMETER.
     DESCRIPTION: Option to ignore any errors found in the Apache error
     log.  The default behavior is to flag an error if the fetch causes
     any errors to be added to the error log and echo the errors to
     the program output. This parameter is ignored unless the file_path
     parameter is specified.  See also the apache_loglevel parameter.
     See also the Restrictions / Bugs section.

     PARAMETER: include_file_path  TYPE: global parameter
     NO DEFAULT.  ALLOWED VALUES: Even-numbered list elements cannot
     begin with '../' or contain '/../'.  OPTIONAL PARAMETER.  You can
     specify more than one instance of this paramter.
     DESCRIPTION: List with an even number of elements.  Odd-numbered
     elements are files to copy to the the temporary Apache directory
     before running the tests.  These files can be specified using
     either an absolute or a relative pathname.  Even-numbered elements
     are the subdirectory pathname, relative to the Apache ServerRoot
     directory, to copy the corresponding file to.  The copied file
     will have the same basename as the odd-numbered element and the
     relative pathname of the corresponding even-numbered element.
     To copy the file directly to the ServerRoot directory, use a
     pathname of . or './.'.

     For example:
     include_file_path = (/home/tester/inc/header.inc => htdocs/includes)
     will copy the file to htdocs/includes/header.inc.

     This parameter is also useful for adding Perl modules that are
     needed by the web page specified by the file_path parameter.  For
     example:
     include_file_path = ( ../apps/myapp/DBconn.pm => lib/perl/apps )
     will copy the Perl module DBconn.pm to a directory that is in the
     Perl @INC array.

     An alternative to using the include_file_path parameter is to
     manually copy the files into the desired subdirectory in the
     directory specified by the apache_dir parameter.

     PARAMETER: mail  TYPE: global parameter
     DEFAULT: no  ALLOWED VALUES: no errors all  OPTIONAL PARAMETER.
     DESCRIPTION: Option to e-mail reports to the addresses in
     the mail_addresses parameter using the server specified by the
     mail_server parameter.  If set to no, no e-mail is sent.  If set to
     errors and one or more of the tests in the parameter file fails,
     an e-mail is sent that contains the results of all tests in the
     parameter file.  If set to all, an e-mail is sent containing the
     results of all tests in the parameter file, regardless of success
     or failure.

     PARAMETER: mail_addresses  TYPE: global parameter
     NO DEFAULT.  REQUIRED unless mail = no.
     DESCRIPTION: List of e-mail addresses to send mail to.  This
     parameter has two uses.  If the mail parameter is set to "errors"
     or "all", the program sends mail containing the program output
     to these addresses.  If the Apache executable specified by the
     apache_exec parameter has the Apache::ASP Perl module configured,
     server errors generated while compiling or running Apache::ASP
     scripts will be e-mailed to the first address in the mail_addresses
     list.

     PARAMETER: mail_server  TYPE: global parameter
     NO DEFAULT.  REQUIRED unless mail = no.
     DESCRIPTION: Name of mail server.

     PARAMETER: method  TYPE: test block parameter
     DEFAULT: get  ALLOWED VALUES: get post  OPTIONAL PARAMETER.
     DESCRIPTION: HTTP method for the request(s).  See RFC 2616
     (HTTP/1.1 protocol).

     PARAMETER: max_bytes  TYPE: test block parameter
     NO DEFAULT   ALLOWED VALUES: Any integer greater that zero and
     greater than min_bytes (if min_bytes is specified).  OPTIONAL
     PARAMETER.
     DESCRIPTION: Maximum number of bytes expected in returned page.
     If this value is exceeded, an error message is displayed.

     PARAMETER: min_bytes  TYPE: test block parameter
     NO DEFAULT   ALLOWED VALUES: Any integer less than max_bytes (if
     max_bytes is specified).  OPTIONAL PARAMETER.
     DESCRIPTION: Minimum number of bytes expected in returned page.
     If the number of returned bytes is less than this value, an error
     message is displayed.

     PARAMETER: params  TYPE: test block parameter
     NO DEFAULT.  ALLOWED VALUES: A list with an even number of
     elements.  OPTIONAL PARAMETER.
     DESCRIPTION: A set of parameter name/value pairs to be passed
     with the request.  (This parameter is used to test pages that
     process forms.)  Unless the method parameter is set to 'post',
     these pairs are URI-escaped and appended to the requested URL.
     For example,
     url = http://www.hotmail.com/cgi-bin/hmhome
     params = ( curmbox
                F001 A005
                from
                HotMail )
     generates the request:
     http://www.hotmail.com/cgi-bin/hmhome?curmbox=F001%20A005&from=HotMail
     The names and values will be URI-escaped as defined by RFC 2396.
     (See http://www.ietf.org/rfc/rfc2396.txt.)

     PARAMETER: proxies  TYPE: global parameter
     NO DEFAULT.  ALLOWED VALUES: A list with an even number of
     elements.  OPTIONAL PARAMETER.
     DESCRIPTION: A set of service name / proxy URL pairs that specify
     proxy servers to use for requests.  For example:
     proxies = ( http => http://http_proxy.mycompany.com
                 ftp  => http://ftp_proxy.mycompany.com )

     -------------------------------------------------------------------

     The regex_forbid and regex_require parameters contain one or more
     Perl regular expressions.  The regex_forbid and regex_require
     parameter values are compared to the fetched page contents as the
     right hand side of a "=~" operator.  If you want to search for a
     literal string, use the text_forbid and text_require parameters.
     For more information, type "man perlre" or see Programming Perl,
     3rd edition, Chapter 5.

     You can specify these parameters globally or within a test block.
     If you specify one as both a global and a test block parameter, the
     value in the test block applies only to that test block.

     PARAMETER: regex_forbid  TYPE: global and/or test block parameter
     NO DEFAULT.  OPTIONAL PARAMETER.
     DESCRIPTION: List of one or more regular expressions that must
     NOT exist on the web page.  See also the text_forbid parameter.

     PARAMETER: regex_require  TYPE: global and/or test block parameter
     NO DEFAULT.  OPTIONAL PARAMETER.
     DESCRIPTION: List of one or more regular expressions that MUST
     exist on the web page.  See also the text_require parameter.

     -------------------------------------------------------------------

     PARAMETER: save_output  TYPE: global parameter
     DEFAULT: no  ALLOWED VALUES: no yes preserve  OPTIONAL PARAMETER.
     DESCRIPTION: Option to redirect the program output to a file.
     (Error messages still go to the terminal.)  The program constructs
     the file name by taking the name of this parameter file, removing
     the file extension if it exists and appending ".out".  If there is
     an existing file with that name, the program overwrites the file if
     save_output is set to 'yes'.  If save_output is set to 'preserve'
     and the file already exists, output is sent to the terminal.
     This parameter should precede all other parameters in the parameter
     file. (This order is not required.)

     PARAMETER: send_cookies TYPE: global and/or test block parameter
     DEFAULT: yes  ALLOWED VALUES: no yes  OPTIONAL PARAMETER.
     DESCRIPTION: Option to send cookies to the web server.  This applies
     to cookies passed by the web server(s) during the test session and
     to cookies created using the cookies parameter.  This does NOT
     give the web server(s) access to cookies created with a browser
     or any user agent software other than this program.  The cookies
     created while this program is running are only accessible to other
     tests in the same parameter file.

     You can specify this parameter globally or within a test block.
     If you specify it as both a global and a test block parameter, the
     value in the test block applies only to that test block.  See also
     the accept_cookies parameter.

     PARAMETER: show_cookies TYPE: global parameter
     DEFAULT: no  ALLOWED VALUES: no yes  OPTIONAL PARAMETER.
     DESCRIPTION: Option to list cookies sent to or received from the web
     server.  Each cookie will be preceded with the string "Set-Cookie3:"
     and the cookie elements will be separated by semicolons.

     PARAMETER: show_html  TYPE: global parameter
     DEFAULT: no  ALLOWED VALUES: no yes  OPTIONAL PARAMETER.
     DESCRIPTION: Option to display the HTML source with the output.
     You can specify this parameter globally or within a test block.
     If you specify it as both a global and a test block parameter,
     the value in the test block applies only to that test block.

     If, and only if, you specify the file_path parameter, the program
     starts a local instance of Apache, copies the file to its htdocs
     directory, fetches the file from Apache and runs the specified
     tests.

     PARAMETER: terse  TYPE: global parameter
     DEFAULT: no  ALLOWED VALUES: no failed_only summary  OPTIONAL
     PARAMETER.
     DESCRIPTION: Option to display short test report.  If you set
     it to 'summary', the program displays only a one-line summary of
     the tests for each URL/file.  If you set terse to 'failed_only',
     the program only displays the results of tests that failed and
     the summary.  If you set terse to 'no', the program displays all
     the test results and the summary.

     PARAMETER: test_name  TYPE: test block parameter
     NO DEFAULT.  Parameter is REQUIRED.
     DESCRIPTION: Name of this test.  This MUST be the first parameter
     in the block for each test.  You may specify multiple test blocks
     within a parameter file.  There MUST be one end_test directive
     for each test_name parameter.

     PARAMETER: text_forbid  TYPE: global and/or test block parameter
     NO DEFAULT.  OPTIONAL PARAMETER.
     DESCRIPTION: List of one or more text strings that must NOT exist
     on the web page.  See also the ignore_case and regex_forbid
     parameters.

     PARAMETER: text_require  TYPE: global and/or test block parameter
     NO DEFAULT.  OPTIONAL PARAMETER.
     DESCRIPTION: List of one or more text strings that MUST exist on
     the web page.  See also the ignore_case and regex_require
     parameters.

     PARAMETER: url  TYPE: test block parameter
     NO DEFAULT.  You MUST specify file_path or url, but not both, in
     each test block.
     DESCRIPTION: URL to test, if value starts with "www.", "http://"
     will be prefixed.  A parameter file can contain some test blocks
     that specify file_path and some that specify url.

     APACHE DIRECTORY AND FILES

     The apache_dir parameter must be set to the name of a directory
     that contains the subdirectories "conf", "logs" and "htdocs".
     The conf subdirectory must contain a file named "httpd.conf-dist".
     The htdocs subdirectory must contain a subdirectory named webtest
     that contains a file named "is_apache_responding.html".  If your
     installation of Apache has the Perl module Apache::ASP configured,
     the apache_dir directory must also contain a subdirectory named
     "asp_tmp".

     The file httpd.conf-dist must contain all the usual Apache
     configuration parameters.  Also, the httpd.conf-dist file must
     contain the following lines INSTEAD OF the lines containing the
     corresponding parameters (i.e., Port, Listen, ServerRoot, etc.):

     Port Please_do_not_modify_PORT
     Listen Please_do_not_modify_PORT
     ServerRoot Please_do_not_modify_SERVER_ROOT
     ErrorLog Please_do_not_modify_SERVER_ROOT/logs/error.log
     LogLevel Please_do_not_modify_LOG_LEVEL
     CustomLog Please_do_not_modify_SERVER_ROOT/logs/access.log common
     PidFile Please_do_not_modify_SERVER_ROOT/apache.pid
     LockFile Please_do_not_modify_SERVER_ROOT/apache.lock
     ServerName Please_do_not_modify_HOST_NAME
     SSLMutex  file:Please_do_not_modify_SERVER_ROOT/ssl_mutex
     SSLLog      Please_do_not_modify_SERVER_ROOT/logs/ssl_engine_log
     DocumentRoot Please_do_not_modify_SERVER_ROOT/htdocs

     At runtime these tags are replaced with the values needed by the
     Apache server that the program starts.  See the Apache documentation
     for details (http://www.apache.org/docs/mod/directives.html).

     Also, if your installation of Apache has the Perl module
     Apache::ASP configured, you must use the following lines instead
     of the lines containing the corresponding parameters (i.e.,
     PERLSETVAR_GLOBAL, PERLSETVAR_MAILHOST, PERLSETVAR_MAILERRORSTO):

     Please_do_not_modify_PERLSETVAR_GLOBAL
     Please_do_not_modify_PERLSETVAR_MAILHOST
     Please_do_not_modify_PERLSETVAR_MAILERRORSTO

     These lines are usually placed in the FileMatch block of the
     VirtualHost block for the PerlHandler Apache::ASP.  At runtime
     these tags are replaced with the the directive PerlSetVar followed
     by the name of the parameter (Global, MailHost, MailErrorsTo)
     and a parameter value derived from other input parameters.  See
     the Apache::ASP documentation for details
     (http://www.apache-asp.org/config.html).

     The subdirectory htdocs must contain a subdirectory named webtest
     that contains a file named "is_apache_responding.html".  This file
     must contain valid HTML and must contain the string
     Please_do_not_modify_TEST_TAG somewhere in the file.  (This file is
     used to verify that Apache has started successfully.)

PREREQUISITES
=============

     Perl version 5.000 or higher is required. The following Perl modules
     are also required.  (These are all part of the base distribution of
     version 5.005_03 and higher.)

     Cwd
     File::Basename
     File::Copy
     File::Find
     File::Path
     HTTP::Cookies
     HTTP::Request::Common
     HTTP::Response
     LWP::UserAgent
     Net::Domain
     Net::SMTP
     Sys::Hostname
     Term::ReadKey
     URI::URL

RESTRICTIONS / BUGS
===================

   This module only works on Unix (e.g., Solaris, Linux, AIX, etc.).  The
module's HTTP requests time out after 3 minutes (the default value for
LWP::UserAgent).  If the file_path parameter is specified, Apache must be
installed.  If the file_path parameter is specified, the directory /tmp
cannot be NFS-mounted, since Apache's lockfile and the SSL mutex file must
be stored on a local disk.

VERSION
=======

   This document describes version 0.20, release date 22 January 2001.

TODO
====

   Add option to validate HTML syntax using HTML::Validator.  Add option
to check links (see
http://world.std.com/~swmcd/steven/perl/pm/lc/linkcheck.html).

AUTHOR
======

     Richard Anderson <Richard.Anderson@unixscripts.com>

COPYRIGHT
=========

   Copyright (c) 2000 Richard Anderson. All rights reserved. This module is
free software.  It may be used, redistributed and/or modified under the
terms of the Perl Artistic License.

SEE ALSO
========

   wt(1), perl(1), perlre(1), perldoc Apache::ASP.

HTTP server authentication class
********************************

NAME
====

   HTTPD::Authen - HTTP server authentication class

SYNOPSIS
========

     use HTTPD::Authen ();

DESCRIPTION
===========

   This module provides methods for authenticating a user.  It uses
HTTPD::UserAdmin to lookup passwords in a database.  Subclasses provide
methods specific to the authentication mechanism.

   Currently, under HTTP/1.0 the only supported authentication mechanism is
Basic Authentication.  NCSA Mosaic and NCSA HTTPd understand the proposed
Message Digest Authentication, which should make it into the HTTP spec
someday.  This module supports both.

METHODS
=======

new ()
------

   Since HTTPD::Authen uses HTTPD::UserAdmin for database lookups it needs
many of the same attributes.  Or, if the first argument passed to the
new() object constructor is a reference to an HTTPD::UserAdmin, the
attributes are inherited.

   The following attributes are recognized from HTTPD::UserAdmin:

   *DBType*, DB, Server, Path, *DBMF*, Encrypt

   And if you wish to query an SQL server: Host, User, Auth, Driver,
*UserTable*, *NameField*, *PasswordField*

   The same defaults are assumed for these attributes, as in
HTTPD::UserAdmin.  See *HTTPD::UserAdmin* for details.

     $authen = new HTTPD::Authen (DB => "www-users");

     =head2 basic()

   Short-cut to return an HTTPD::Authen::Basic object.

     $basic = $authen->basic;

digest()
--------

   Short-cut to return an HTTPD::Authen::Digest object.

     $digest = $authen->digest;

type($authorization_header_value)
---------------------------------

   This method will guess the authorization scheme based on the
'Authorization' header value, and return an object bless into that
scheme's class.

   By using this method, it is simple to authenticate a user without even
knowing what scheme is being used:

     $authtype = HTTPD::Authen->type($authinfo);
     @info = $authtype->parse($authinfo)
     if( $authtype->check(@info) ) {
         #response 200 OK, etc.
     }

SUBCLASSES
==========

HTTPD::Authen::Basic methods
new([$hashref])
---------------

   $hashref should be an HTTPD::Authen object, it must be present when
looking up users.  Optionally, you can pass the attribute USER with the
value of an HTTPD::UserAdmin object.

   Normally, this method is not called directly, but rather by
HTTPD::Authen->basic method.

parse ($authorization_header_value)
-----------------------------------

   This method expects the value of the HTTP 'Authorization' header of type
Basic.  This should look something like:

     'Basic ZG91Z206anN0NG1l'

   This string will be parsed and decoded, returning the username and
password.  Note that the *MIME::Base64* module is required for decoding.

     ($username,$password) = HTTPD::Authen::Basic->parse($authinfo)

     #or, assuming $authen is an HTTPD::Authen object
     ($username,$password) = $authen->basic->parse($authinfo)

     #or check the info at the same time
     $OK = $authen->check($authen->basic->parse($authinfo))

check($username,$password)
--------------------------

   This method expects a username and *clear text* password as arguments.
Returns true if the username was found, and passwords match, otherwise
returns false.

     if($authen->check("JoeUser", "his_clear_text_password")) {
     	print "Well, the passwords match at least\n";
     }
     else {
     	print "Password mismatch! Intruder alert! Intruder alert!\n";
     }

HTTPD::Authen::Digest methods
     NOTE: The MD5 module is required to use these methods.

new([$hashref])
---------------

   $hashref should be an HTTPD::Authen object.  Normally, this method is
not called directly, but rather by HTTPD::Authen->digest method.

parse ($authorization_header_value)
-----------------------------------

   This method expects the value of the HTTP 'Authorization' header of type
Basic.  This should look something like:

     Digest username="JoeUser", realm="SomePlace", nonce="826407380", uri="/test/blah.html", response="0306f29f88690fb9203451556c376ae9", opaque="5e09061a062a271c8fcc686c5be90c2a"

   This method returns a hash ref containing all Name = Value pairs from
the header.

     $mda = HTTPD::Authen::Digest->parse($authinfo);

     #or, assuming $authen is an HTTPD::Authen object
     $mda = $authen->digest->parse($authinfo)

     #or check the info at the same time
     $OK = $authen->check($authen->digest->parse($authinfo))

check ($hashref[, $request [, $seconds [, $client_ip ]]])
---------------------------------------------------------

   This method expects a hashref of Name Value pairs normally found in the
'Authorization' header.  With this argument alone, the method will return
true without checking nonce or the opaque string if the client 'response'
checksum matches ours.

   If $request is present, it must be a hashref or an HTTP::Request
method.  From here, we fetch the request uri and request method.
Otherwise, we default to the value of 'uri' present in $hashref, and 'GET'
for the method.

   If $seconds is present, the value of 'nonce' will be checked, returning
false if it is stale.

   If $client_ip is present, the value of the 'opaque' string will be
checked, returning false if the string is not valid.

   This implementation is based on the Digest Access Authentication
internet-draft http://hopf.math.nwu.edu/digestauth/draft.rfc and NCSA's
implementation http://hoohoo.ncsa.uiuc.edu/docs/howto/md5_auth.html

SEE ALSO
========

   HTTPD::UserAdmin, MD5, HTTP::Request, MIME::Base64

AUTHOR
======

   Doug MacEachern <dougm@osf.org>

   Copyright (c) 1996, Doug MacEachern, OSF Research Institute

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl API for Apache benchmarking and regression testing.
********************************************************

NAME
====

   HTTPD::Bench::ApacheBench - Perl API for Apache benchmarking and
regression testing.

SYNOPSIS
========

     use HTTPD::Bench::ApacheBench;

     my $b = HTTPD::Bench::ApacheBench->new;

     # global configuration
     $b->concurrency(5);
     $b->priority("run_priority");

     # add HTTP request sequences (aka: runs)
     my $run1 = HTTPD::Bench::ApacheBench::Run->new
       ( urls => ["http://localhost/one", "http://localhost/two"] );
     $b->add_run($run1);

     my $run2 = HTTPD::Bench::ApacheBench::Run->new
       ( urls    => ["http://localhost/three", "http://localhost/four"],
         cookies => ["Login_Cookie=b3dcc9bac34b7e60;"],
         order   => "depth_first",
         repeat  => 10,
         memory  => 2 );
     $b->add_run($run2);

     # send HTTP request sequences to server and time responses
     my $ro = $b->execute;

     # calculate hits/sec
     print (1000*$b->total_requests/$b->total_time)." req/sec\n";

     # show request times (in ms) for $run1, 1st repetition
     print join(', ', @{$run1->request_times}) . "\n";

     # show response times (in ms) for $run2, 7th repetition
     print join(', ', @{$run2->iteration(6)->response_times}) . "\n";

     # dump the entire regression object (WARNING, this could be a LOT OF DATA)
     use Data::Dumper;
     my $d = Data::Dumper->new([$ro]);
     print $d->Dumpxs;

GOALS
=====

   This project is meant to be the foundation of a complete benchmarking
and regression testing suite for an advanced, transaction-based mod_perl
site.  We need to be able to stress our server to its limit while also
having a way to verify the HTTP responses for correctness.  Since our site
is transaction-based (as opposed to content-based), we needed to extend
the single-URL ab model to a multiple-URL sequence model.

   ApacheBench is based on the Apache 1.3.12 ab code (src/support/ab.c).

   Note: although this tool was designed to be used on an Apache mod_perl
site, it is generally applicable to any HTTP-compliant server.  Beware,
however, that it sends a high volume of HTTP requests in a very short
period of time, which may overwhelm some weaker HTTP server platforms like
NT/IIS.

DESCRIPTION
===========

   ApacheBench sends sequences of HTTP requests to an HTTP server and keeps
track of the time taken to receive a response, the data that was returned,
the size of the data that was returned, and various other bits of
information.

   Since it is implemented in C, it sends HTTP requests in a tight loop
which can stress your server to 100% capacity, especially if invoked in
multiple concurrent instances.  It gives accurate time measurements down
to the millisecond for each HTTP request-response interval.

   Included is a simplified re-implementation of ab using the ApacheBench
Perl API.  This should help get you started with ApacheBench.

CONFIGURATION METHODS
=====================

   You need to tell ApacheBench what the requests will be, in what order to
send them, and how to prioritize sending them.  ApacheBench was designed
to simulate many users logged in simultaneously, each of whom may be doing
many different transactions at once.

Global configuration
--------------------

   Global configuration methods apply to all benchmarking runs associated
with this ApacheBench object.

$b = HTTPD::Bench::ApacheBench->new()
     Constructor.  Takes no arguments.

$b->concurrency( $concur_level )
     Number of requests to send simultaneously (default: 1)

$b->priority( $priority )
     $priority can be either "*equal_opportunity*" or "*run_priority*".

     If set to "*equal_opportunity*", all benchmark runs that are
     configured (see below) under this ApacheBench object are given equal
     access to the concurrency level.  This means requests are taken from
     each run and sent in parallel (the level of parallelism defined by
     concurrency()).

     If set to "*run_priority*", the benchmark runs that are configured
     first get the highest priority.  This means all requests in
     $b->run(0) will be sent before any requests in $b->run(1) are sent, if
     $b->run(0)->order eq "*breadth_first*" (see below).

     (default: "*equal_opportunity*")

$b->repeat( $n )
     The number of times to repeat the request sequence in each run.  This
     can be overridden on a per-run basis (see below).

     (default: 1)

$b->buffersize( $bufsz )
     The maximum size of the buffer in which to store HTTP response bodies.
     If an HTTP response is received with a size larger than this limit,
     the content is truncated at length $bufsz, and a warning is issued.
     This method has no effect if $b->memory() < 3.  This can be
     overridden on a per-run basis (see below).

     (default: *16384*)

$b->memory( $memlvl )
     The memory level.  Controls how much data ApacheBench will remember
     and return in the regression object.  This can be overridden on a
     per-run basis (see below).

     (default: 1)

     Key:  $memlvl => Description

          0  =>  Remember nothing. (actually still keeps global
                 regression data: total_time, bytes_received,
                 and warnings)

          1  =>  Remember connect/response times and minimal
                 summary information about size of requests and
                 responses.

          2  =>  Remember connect/response times and all
                 information about size of requests and responses.
                 Also keeps an array of all HTTP response
                 headers returned by the server for each request.

          3  =>  Remember connect/response times, all information
                 about request/response sizes, HTTP response
                 headers, and also all content of every HTTP
                 response returned by the server.  Warning:
                 this can quickly eat up all available main
                 memory if used with large runs.

$b->add_run( $run_object )
     Schedule a run for this ApacheBench object.  Returns the run number
     where this object was inserted, or undef on failure.  See below for
     details on $run_object.

$r = $b->run( $run_no, [$run_object] )
     Returns the run object stored in location $run_no.  If a run object
     is passed as the optional second argument, it is stored in location
     $run_no, displacing whatever was there.  The displaced run object is
     then returned.

$b->delete_run( $run_no )
     Delete the run object stored in location $run_no.  The deleted run
     object is returned to the caller for safety sake.

Run configuration methods
-------------------------

   You need to configure one or more benchmark runs.  Each run is defined
as an ordered sequence of HTTP requests to be sent to the server, which can
be repeated multiple times, and scheduled to be sent in different orders.

$r = HTTPD::Bench::ApacheBench::Run->new( { urls => [@url_list] } )
     Construct a run object with the ordered sequence of HTTP requests in
     @url_list.

$r->repeat( $n )
     Number of times to repeat this request sequence.

     (default: 1, or whatever is specified in global configuration)

$r->cookies( \@cookies )
     Set the HTTP Cookie: header for each *repetition* of this run.
     Length of @cookies should equal $n (whatever you set $r->repeat to).
     If this option is omitted, no cookies will be sent in any of the
     requests for this run.

     Example usage:  You could simulate $n users all doing the same
     transaction simultaneously by giving $n different login cookies here.
     Say you have login cookies in an array called @login of length $n.
     Set $r->repeat($n), $r->order("breadth_first"), $r->cookies([map
     {$login[$_]} 0..$n]), and ApacheBench will perform the transaction
     sequence set by $r->urls $n times each with a separate login cookie.

$r->urls( \@url_list )
     Set the HTTP request URLs for this run.  A @url_list must be given for
     each run, otherwise the run will not execute.  Typically @url_list is
     set using the constructor.

$r->postdata( \@postdata )
     Set the HTTP POST request body contents.  If an undef value is
     encountered in @postdata, that request will be a GET request.  If
     this option is omitted, all requests for this run will be GET
     requests.  Length of @postdata should equal the length of @url_list.

$r->content_types( \@ctypes )
     Set the Content-type: header for each POST request in this run.
     Default is "application/x-www-form-urlencoded" which will be used if
     an undef value is encountered in @ctypes.  Length of @ctypes should
     equal the length of @url_list.

$r->order( $order )
     Either "*depth_first*" or "*breadth_first*"

     "*breadth_first*" mode sends $n of the first request in the
     @url_list, then $n of the second request in the @urls_list, then $n
     of the third... and so on.  (e.g. If $n == 3 and @url_list contains
     two requests, then ApacheBench would send the first request 3 times,
     and then the second request 3 times.)

     "*depth_first*" mode ensures that HTTP requests in the sequence are
     sent in order, completing a full sequence before starting again for
     the next repeat() iteration.  (e.g. If $n == 3 and @url_list contains
     two requests, then ApacheBench would send the @url_list sequence in
     order, then send it again, and then again.  A total of six requests
     would be sent.)

     (default: "*breadth_first*")

     Note: if $r->repeat() == 1, or the length of $r->urls() is 1, then the
     order option has no effect

$r->buffersize( $bufsz )
     The maximum size of the buffer in which to store HTTP response bodies.
     If an HTTP response is received with a size larger than this limit,
     the content is truncated at length $bufsz, and a warning is issued.
     This method has no effect if $r->memory() < 3.

     (default: *16384*, or whatever is specified in global configuration)

$r->memory( $memlvl )
     The memory level.  Controls how much data ApacheBench will remember
     and return in the regression object for this run.  See global
     configuration method of same name for detailed description.

     (default: 1, or whatever is specified in global configuration)

EXECUTION METHODS
=================

$b->execute
     Send all scheduled runs to their respective destinations, and record
     response data.

REGRESSION METHODS
==================

   All of the following methods will return undef unless the underlying
ApacheBench object has been execute()'d at least once.

Global regression methods
-------------------------

$b->total_time
     Total time, in milliseconds, between the start of the first request
     in the first run, and the end of the final response in the final run.

$b->bytes_received
     Total bytes received from all responses in all runs.

$b->warnings
     Various warning messages.

Run regression methods
----------------------

$i = $r->iteration( [$iter_no] )
     Return a regression object specific to iteration $iter_no of this run.
     If $iter_no is not given, it assumes 0, or the first iteration of the
     run.

$i->connect_times
     Return a reference to an array the same length as $r->urls() which
     contains connection times, in milliseconds, for each HTTP request in
     this iteration of the sequence.

$i->min_connect_time
     The minimum connect time of all requests in the sequence.

$i->max_connect_time
     The maximum connect time of all requests in the sequence.

$i->avg_connect_time
     The average connect time of all requests in the sequence.

$i->sum_connect_time
     The total connect time of all requests in the sequence (equal to the
     summation of all elements of $i->connect_times).

$i->request_times
     A reference to an array the same length as $r->urls() which contains
     the total times taken to send a request to the server, in
     milliseconds, for each HTTP request in the sequence.

$i->min_request_time
     The minimum request time of all requests in the sequence.

$i->max_request_time
     The maximum request time of all requests in the sequence.

$i->avg_request_time
     The average request time of all requests in the sequence.

$i->sum_request_time
     The total request time of all requests in the sequence (equal to the
     summation of all elements of $i->request_times).

$i->response_times
     A reference to an array the same length as $r->urls() which contains
     the total times taken to receive a response from the server, in
     milliseconds, for each HTTP request in the sequence.

$i->min_response_time
     The minimum response time of all requests in the sequence.

$i->max_response_time
     The maximum response time of all requests in the sequence.

$i->avg_response_time
     The average response time of all requests in the sequence.

$i->sum_response_time
     The total response time of all requests in the sequence (equal to the
     summation of all elements of $i->response_times).

$i->bytes_posted
     A reference to an array the same length as $r->urls() which contains
     the number of bytes posted to the server for each HTTP request in the
     sequence.

     (return value will be undefined if memory < 2)

$i->sum_bytes_posted
     The total number of bytes posted to the server in HTTP requests over
     this iteration of the request sequence.

$i->bytes_read
     A reference to an array the same length as $r->urls() which contains
     the total number of bytes read from the server in each HTTP response
     in the sequence.

     (return value will be undefined if memory < 2)

$i->sum_bytes_read
     The total number of bytes read from the server in HTTP responses over
     this iteration of the request sequence.

$i->response_headers
     A reference to an array the same length as $r->urls() which contains
     the HTTP response headers returned by the server for each URL in the
     sequence.

     (return value will be undefined if memory < 2)

$i->response_body
     A reference to an array the same length as $r->urls() which contains
     the full page content (including HTTP headers) returned by the server
     for each URL in the sequence.

     (return value will be undefined if memory < 3)

$i->response_body_lengths
     A reference to an array the same length as $r->urls() which contains
     the length of the document (in bytes) returned from the server in
     each HTTP response in the sequence.  This should be equivalent to the
     Content-Length: line in the response headers, if the server set them
     correctly.  The following should also be true, for 1 <= $j <=
     size($r->urls()):

     ( $i->response_body_lengths()->[$j] == $i->bytes_read()->[$j] -
     length($i->headers()->[$j]) )

     (return value will be undefined if memory < 2)

EXAMPLES
========

   The following examples of ApacheBench usage are paired with the
resulting output from an Apache access_log.  This should give you a feel
for how the global $b->priority() method and the per-run $r->order()
method affect how HTTP requests are sent.

   First, let's set $b->priority("*equal_opportunity*") (its default).

     my $b = HTTPD::Bench::ApacheBench->new;
     $b->concurrency(1);
     $b->priority("equal_opportunity");

   Add a single run and execute, then look at what gets sent to Apache.

     my $r = HTTPD::Bench::ApacheBench::Run->new
       ({
          repeat    => 3,
          urls      => [ "http://localhost/",
                         "http://localhost/server-status" ],
          order     => "breadth_first",
        });
     $b->add_run($r);
     $b->execute;

   Apache access_log output:

     127.0.0.1 - - [20/Sep/2000:18:43:32 -0400] "GET / HTTP/1.0" 200 5565
     127.0.0.1 - - [20/Sep/2000:18:43:32 -0400] "GET / HTTP/1.0" 200 5565
     127.0.0.1 - - [20/Sep/2000:18:43:32 -0400] "GET / HTTP/1.0" 200 5565
     127.0.0.1 - - [20/Sep/2000:18:43:32 -0400] "GET /server-status HTTP/1.0" 200 5294
     127.0.0.1 - - [20/Sep/2000:18:43:32 -0400] "GET /server-status HTTP/1.0" 200 5294
     127.0.0.1 - - [20/Sep/2000:18:43:32 -0400] "GET /server-status HTTP/1.0" 200 5294

   Let's add another run and execute, and see what Apache sees.

     my $r2 = HTTPD::Bench::ApacheBench::Run->new
       ({
          repeat       => 3,
          urls         => [ "http://localhost/perl-status",
                            "http://localhost/proxy-status" ],
          order        => "breadth_first",
        });
     $b->add_run($r2);
     $b->execute;

   Notice that both the first and second runs get equal opportunity.
Apache access_log output:

     127.0.0.1 - - [20/Sep/2000:18:49:10 -0400] "GET / HTTP/1.0" 200 5565
     127.0.0.1 - - [20/Sep/2000:18:49:11 -0400] "GET / HTTP/1.0" 200 5565
     127.0.0.1 - - [20/Sep/2000:18:49:11 -0400] "GET / HTTP/1.0" 200 5565
     127.0.0.1 - - [20/Sep/2000:18:49:11 -0400] "GET /perl-status HTTP/1.0" 200 848
     127.0.0.1 - - [20/Sep/2000:18:49:11 -0400] "GET /perl-status HTTP/1.0" 200 848
     127.0.0.1 - - [20/Sep/2000:18:49:11 -0400] "GET /perl-status HTTP/1.0" 200 848
     127.0.0.1 - - [20/Sep/2000:18:49:11 -0400] "GET /server-status HTTP/1.0" 200 5294
     127.0.0.1 - - [20/Sep/2000:18:49:11 -0400] "GET /server-status HTTP/1.0" 200 5294
     127.0.0.1 - - [20/Sep/2000:18:49:11 -0400] "GET /server-status HTTP/1.0" 200 5294
     127.0.0.1 - - [20/Sep/2000:18:49:11 -0400] "GET /proxy-status HTTP/1.0" 200 5886
     127.0.0.1 - - [20/Sep/2000:18:49:11 -0400] "GET /proxy-status HTTP/1.0" 200 5888
     127.0.0.1 - - [20/Sep/2000:18:49:11 -0400] "GET /proxy-status HTTP/1.0" 200 5889

   Now let's set $b->priority("*run_priority*").

     $b->priority("run_priority");
     $b->execute;

   Notice that now ApacheBench completes the entire first run before it
starts the second.  Here's the Apache access_log output:

     127.0.0.1 - - [20/Sep/2000:18:52:47 -0400] "GET / HTTP/1.0" 200 5565
     127.0.0.1 - - [20/Sep/2000:18:52:47 -0400] "GET / HTTP/1.0" 200 5565
     127.0.0.1 - - [20/Sep/2000:18:52:47 -0400] "GET / HTTP/1.0" 200 5565
     127.0.0.1 - - [20/Sep/2000:18:52:47 -0400] "GET /server-status HTTP/1.0" 200 5294
     127.0.0.1 - - [20/Sep/2000:18:52:47 -0400] "GET /server-status HTTP/1.0" 200 5294
     127.0.0.1 - - [20/Sep/2000:18:52:47 -0400] "GET /server-status HTTP/1.0" 200 5294
     127.0.0.1 - - [20/Sep/2000:18:52:47 -0400] "GET /perl-status HTTP/1.0" 200 848
     127.0.0.1 - - [20/Sep/2000:18:52:47 -0400] "GET /perl-status HTTP/1.0" 200 848
     127.0.0.1 - - [20/Sep/2000:18:52:47 -0400] "GET /perl-status HTTP/1.0" 200 848
     127.0.0.1 - - [20/Sep/2000:18:52:47 -0400] "GET /proxy-status HTTP/1.0" 200 5858
     127.0.0.1 - - [20/Sep/2000:18:52:47 -0400] "GET /proxy-status HTTP/1.0" 200 5861
     127.0.0.1 - - [20/Sep/2000:18:52:47 -0400] "GET /proxy-status HTTP/1.0" 200 5864

   Let's now set our runs to $r->order("*depth_first*") instead of
"*breadth_first*".  With "*depth_first*", $b->priority() has no effect,
since each run can only use a maximum of one concurrent server (by
definition of "*depth_first*", it can only be sending one request at a
time).

     $b->run(0)->order("depth_first");
     $b->run(1)->order("depth_first");
     $b->execute;

   Notice each sequence gets sent in full before it repeats.  Apache
access_log output:

     127.0.0.1 - - [20/Sep/2000:19:02:01 -0400] "GET / HTTP/1.0" 200 5565
     127.0.0.1 - - [20/Sep/2000:19:02:01 -0400] "GET /server-status HTTP/1.0" 200 5294
     127.0.0.1 - - [20/Sep/2000:19:02:01 -0400] "GET / HTTP/1.0" 200 5565
     127.0.0.1 - - [20/Sep/2000:19:02:01 -0400] "GET /server-status HTTP/1.0" 200 5294
     127.0.0.1 - - [20/Sep/2000:19:02:01 -0400] "GET / HTTP/1.0" 200 5565
     127.0.0.1 - - [20/Sep/2000:19:02:01 -0400] "GET /server-status HTTP/1.0" 200 5294
     127.0.0.1 - - [20/Sep/2000:19:02:01 -0400] "GET /perl-status HTTP/1.0" 200 848
     127.0.0.1 - - [20/Sep/2000:19:02:01 -0400] "GET /proxy-status HTTP/1.0" 200 5858
     127.0.0.1 - - [20/Sep/2000:19:02:01 -0400] "GET /perl-status HTTP/1.0" 200 848
     127.0.0.1 - - [20/Sep/2000:19:02:01 -0400] "GET /proxy-status HTTP/1.0" 200 5860
     127.0.0.1 - - [20/Sep/2000:19:02:01 -0400] "GET /perl-status HTTP/1.0" 200 848
     127.0.0.1 - - [20/Sep/2000:19:02:01 -0400] "GET /proxy-status HTTP/1.0" 200 5860

   Now let's send the same runs, but with a higher concurrency level.

     $b->concurrency(2);
     $b->execute;

   Notice that ApacheBench sends requests from all runs in order to fill up
the specified level of concurrent requests.  Apache access_log output:

     127.0.0.1 - - [20/Sep/2000:19:04:38 -0400] "GET / HTTP/1.0" 200 5565
     127.0.0.1 - - [20/Sep/2000:19:04:38 -0400] "GET /perl-status HTTP/1.0" 200 848
     127.0.0.1 - - [20/Sep/2000:19:04:38 -0400] "GET /server-status HTTP/1.0" 200 5294
     127.0.0.1 - - [20/Sep/2000:19:04:38 -0400] "GET /proxy-status HTTP/1.0" 200 5891
     127.0.0.1 - - [20/Sep/2000:19:04:38 -0400] "GET / HTTP/1.0" 200 5565
     127.0.0.1 - - [20/Sep/2000:19:04:38 -0400] "GET /perl-status HTTP/1.0" 200 848
     127.0.0.1 - - [20/Sep/2000:19:04:38 -0400] "GET /server-status HTTP/1.0" 200 5294
     127.0.0.1 - - [20/Sep/2000:19:04:38 -0400] "GET /proxy-status HTTP/1.0" 200 5878
     127.0.0.1 - - [20/Sep/2000:19:04:38 -0400] "GET / HTTP/1.0" 200 5565
     127.0.0.1 - - [20/Sep/2000:19:04:38 -0400] "GET /perl-status HTTP/1.0" 200 848
     127.0.0.1 - - [20/Sep/2000:19:04:38 -0400] "GET /server-status HTTP/1.0" 200 5294
     127.0.0.1 - - [20/Sep/2000:19:04:38 -0400] "GET /proxy-status HTTP/1.0" 200 5878

   Let's take a look at the regression data from that last execute() call.

     foreach my $run (0..1) {
       foreach my $repeat (0..2) {
         print "response times (in ms) for run $run, iteration ".($repeat+1).":\n  ";
         print join("\n  ", @{$b->run($run)->iteration($repeat)->response_times});
         print "\n";
       }
     }

   Perl output:

     response times (in ms) for run 0, iteration 1:
       69
       39
     response times (in ms) for run 0, iteration 2:
       67
       39
     response times (in ms) for run 0, iteration 3:
       65
       41
     response times (in ms) for run 1, iteration 1:
       67
       40
     response times (in ms) for run 1, iteration 2:
       66
       39
     response times (in ms) for run 1, iteration 3:
       65
       39

BUGS
====

   Error checking is getting better but is still not great.  If you do not
configure correctly, you may experience a segmentation fault on execute().

   The response body of any response which is larger than the *buffersize*
applicable to it will be truncated to zero length.  This is contrary to
what the documentation says above.  This should be fixed soon.  For now,
just set your $r->buffersize() big enough for the largest page you
anticipate receiving.

   Methods total_requests(), total_requests_sent(), and
total_responses_received() are temporary hacks that are correct most of
the time, but not always.

   If you are running in perl's taint-checking mode, and you pass tainted
data to ApacheBench (e.g. a tainted URL), it will barf.  Don't ask me why.

   It has not been tested on any platforms other than Linux / Apache.
Please send ports to other platforms to me (Adi Fairbank).

AUTHORS
=======

   The ApacheBench Perl API is based on code from Apache 1.3.12 ab
(src/support/ab.c), by the Apache group.

   The ApacheBench Perl API was originally written by Ling Wu
<ling@certsite.com>

   Rewritten and currently maintained by Adi Fairbank <adi@certsite.com>

   Please e-mail either Adi or Ling with bug reports, or preferably
patches.

LICENSE
=======

   This package is free software and is provided AS IS without express or
implied warranty.  It may be used, redistributed and/or modified under the
terms of the Perl Artistic License
(http://www.perl.com/perl/misc/Artistic.html)

LAST MODIFIED
=============

   Feb 22, 2001

Management of HTTP server group databases
*****************************************

NAME
====

   HTTPD::GroupAdmin - Management of HTTP server group databases

SYNOPSIS
========

     use HTTPD::GroupAdmin ();

DESCRIPTION
===========

   This software is meant to provide a generic interface that hides the
inconsistencies across HTTP server implementations of user and group
databases.

METHODS
=======

new ()
     Here's where we find out what's different about your server.

     Some examples:

          @DBM = (DBType => 'DBM',
          	    DB     => '.htgroup',
          	    Server => 'apache');

          $group = new HTTPD::GroupAdmin @DBM;

     This creates an object whose database is a DBM file named '.htgroup',
     in a format that the Apache server understands.

          @Text = (DBType => 'Text',
          	     DB     => '.htgroup',
          	     Server => 'ncsa');

          $group = new HTTPD::GroupAdmin @Text;

     This creates an object whose database is a plain text file named
     '.htgroup', in a format that the NCSA server understands.

     Full list of constructor attributes:

     Note: Attribute names are case-insensitive

     Name    - Group name

     *DBType*  - The type of database, one of 'DBM', 'Text', or 'SQL'
     (Default is 'DBM')

     DB      - The database name (Default is '.htpasswd' for DBM & Text
     databases)

     Server  - HTTP server name (Default is the generic class, that works
     with NCSA, Apache and possibly others)

     Note: run 'perl t/support.t matrix' to see what support is currently
     availible

     Path    - Relative DB files are resolved to this value  (Default is
     '.')

     Locking - Boolean, Lock Text and DBM files (Default is true)

     Debug   - Boolean, Turn on debug mode

     Specific to DBM files:

     *DBMF*    - The DBM file implementation to use (Default is 'NDBM')

     Flags   - The read, write and create flags.  There are four modes:
     *rwc* - the default, open for reading, writing and creating.  rw -
     open for reading and writing.  r - open for reading only.  w - open
     for writing only.

     Mode    - The file creation mode, defaults to '0644'

     Specific to DBI: We talk to an SQL server via Tim Bunce's DBI
     interface. For more info see:
     http://www.hermetica.com/technologia/DBI/

     Host      - Server hostname

     Port      - Server port

     User      - Database login name

     Auth      - Database login password

     Driver    - Driver for DBI  (Default is 'mSQL')

     *GroupTable* - Table with field names below

     *NameField* - Field for the name  (Default is 'user')

     *GroupField* - Field for the group  (Default is 'group')

     From here on out, things should look the same for everyone.

add($username[,$groupname])
     Add user $username to group $groupname, or whatever the 'Name'
     attribute is set to.

     Fails if $username exists in the database

          if($group->add('dougm', 'www-group')) {
          	print "Welcome!\n";
          }

delete($username[,$groupname])
     Delete user $username from group $groupname, or whatever the 'Name'
     attribute is set to.

          if($group->delete('dougm')) {
          	print "He's gone from the group\n";
          }

exists($groupname, [$username])
     True if $groupname is found in the database

          if($group->exists('web-heads')) {
          	die "oh no!";
          }
          if($group->exists($groupname, $username) {
          	#$username is a member of $groupname
          }

list([$groupname])
     Returns a list of group names, or users in a group if '$name' is
     present.

     @groups = $group->list;

     @users = $group->list('web-heads');

user()
     Short cut for creating an HTTPD::UserAdmin object.  All applicable
     attributes are inherited, but can be overridden.

          $user = $group->user();

     (See HTTPD::UserAdmin)

convert(@Attributes)
     Convert a database.

          #not yet

remove($groupname)
     Remove group $groupname from the database

name($groupname)
     Change the value of 'Name' attribute.

          $group->name('bew-ediw-dlrow');

debug($boolean)
     Turn debugging on or off

lock([$timeout]) =item unlock()
     These methods give you control of the locking mechanism.

          $group = new HTTPD::GroupAdmin (Locking => 0); #turn off auto-locking
          $group->lock; #lock the object's database
          $group->add($username,$passwd); #write while database is locked
          $group->unlock; release the lock

db($dbname);
     Select a different database.

          $olddb = $group->db($newdb);
          print "Now we're reading and writing '$newdb', done with '$olddb'n\";

flags([$flags])
     Get or set read, write, create flags.

commit
     Commit changes to disk (for Text files).

SEE ALSO
========

   HTTPD::UserAdmin(3)

AUTHOR
======

   Doug MacEachern <dougm@osf.org>

   Copyright (c) 1996, 1997 Doug MacEachern

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Database of HTTPD Security Realms
*********************************

NAME
====

   HTTPD::Realm - Database of HTTPD Security Realms

SYNOPSIS
========

     use HTTPD::Realm;

     # pull out the definition of the "members" realm
     $realms = new HTTPD::Realm(-config_file=>'/home/httpd/conf/realms.conf');
     $def = $realms->realm(-realm=>'members');

     # show info about the realm
     print "realm name = ",     $def->name,"\n";
     print "user database = ",  $def->userdb,"\n";
     print "group database = ", $def->groupdb,"\n";
     print "user type = ",      $def->usertype,"\n";
     print "group type = ",     $def->grouptype,"\n";
     print "web server type = ",$def->server,"\n";
     print "cryptography = ",   $def->crypt,"\n";
     print "other fields = ",   $def->fields,"\n";

     # Connect to the database for the realm,
     # returning a HTTPD::RealmManager object.
     $database = $def->connect(-writable=>1);

DESCRIPTION
===========

   HTTPD::Realm defines high level security realms to be used in
conjunction with Apache, Netscape and NCSA Web servers.  You define the
realms in a central configuration file, and access their underlying
databases via this module and the HTTPD::RealmManager library.  This
allows automated tools to change user passwords, groups and other
information without regard to the underlying database implementation.

   *Important note:* Do not use these modules to adjust the Unix password
or group files.  They do not have the same format as the Web access
databases.

CONFIGURATION FILE
==================

   A typical configuration file is shown below.  It is human readable and
similar in form to conventional Apache and NCSA HTTPD configuration files.
Directives are separated from their arguments by white space (tabs or
spaces), and comments begin with hash marks (#).  By convention, the
standard configuration file is named "realms.conf", but you can give it
any name you prefer.

   # realms.conf <Realm main>         Type            text
Authentication  Basic         Users           /home/httpd/security/passwd
      Groups          /home/httpd/security/group </Realm>

   <Realm development>         Type            DBM         Authentication
Basic         Users           /home/httpd/security/devel.passwd
Groups          /home/httpd/security/devel.group </Realm>

   <Realm members@capricorn.org>         Type            text
Authentication  Digest         Users           /home/httpd/1.1/passwd
  Groups          /home/httpd/1.1/group </Realm>

   <Realm subscriptions>         Type            MSQL
Authentication  Basic         Database        web_accounts@localhost
 Users           table=users uid=name passwd=pass         Groups
table=groups group=group 	Fields          Name Age:i Paid:s1
</Realm>

   realms.conf is made up of one or more <Realm> sections.  The opening
<Realm> tag must contain the realm's name, which can be any set of
non-whitespace characters.  Each section contains directives that tells
the module what type of authentication to use for the realm, what type of
database to use, and where to find the files or database tables used for
the realm.  The users and groups defined in one realm are independent of
those defined in another, giving you a lot of flexibility in setting up
access control for your site.

   The example shown here defines four different security realms.  The
first, named "main", uses human readable text files and the Basic
Authentication protocol.  The second, "development", also uses Basic
Authentication, but stores users and groups in DBM files rather than in
text files.  The realm named "members@capricorn.org" uses Digest
Authentication on top of textfiles.  By convention, Digest realms look
like e-mail addresses, but you don't have to follow this convention.  The
last realm definition uses Basic Authentication on top of an mSQL database.

   The directives allowed within a <Realm> section are listed here:

   Directive    *Example Param*        Description  Type           DBM
         Database type  Authentication Basic             Authentication
scheme  Users          /etc/httpd/passwd Path to user database  Groups
   /etc/httpd/group  Path to group database  Database
www@capricorn.com Location of mSQL db  Server         NCSA
Type of server  Driver         mSQL              DBI driver  Fields
name age paid     Additional user fields  Mode           0644
Mode for new files  Default                          Default realm

Type
     This directive specifies the database type.  It can be any of "text,"
     "DBM," "DB," or "SQL."  Although these are the only databases
     currently recognized by Apache, other Unix DBM-like formats,
     including "GDBM," and "SDBM" are recognized for future compatibility.
     You may use "MSQL" as an alias for "SQL."

Authentication
     This directives specifies the type of authentication to use.  It can
     be either "Basic" or "Digest."

Users
     This is the path to the file or database table that holds user names
     and passwords.  For everything but SQL databases, it's a physical path
     to a file on your system.  If the database file doesn't exist (and the
     process has sufficient privileges), it will be created.  For example:

          Users /home/httpd/security/passwd

     For mSQL databases, the value of the directive should have the format:

          Users table=table_name uid=user_field password=password_field

     The value of table is the name of the table in which to look for the
     user.  The value of uid and password are the fields in which Apache
     will look for the user ID and password.  For lookup efficiency, the
     uid field should be defined as the primary key field in mSQL.

     You may optionally place a colon and field width after any of the
     table names.  These field widths are used as hints by the user_manage
     script to create a nicely-laid out fill-out form.  If not provided,
     reasonable defaults are assumed

     Here's an example of a valid directive in which the user ID field is
     given a width of 40:

          Users table=Members uid=Name:40 password=Pass

     mSQL tables are not created automatically.  You have to define them
     yourself (using the *msql* application) before using them.

Groups
     This is the path to the file or database table that holds group
     assignments.  If you don't need groups, just leave the directive out.
     For everything but MSQL databases, the argument physical path to a
     file on your system.  If the database file doesn't exist (and the
     process has sufficient privileges), it will be created.  For example:

          Groups /home/httpd/security/groups

     For mSQL databases, the directive points to a previously-defined
     table and field in the database in the format

          Groups table=table_name group=group_field

     The value of table is the name of the table in which to look up the
     user.  The value of group is the field in which Apache find the group
     that the user belongs to.  Apache will look for the user name in the
     same field as declared in the Users directive, so don't declare
     another uid field here.  You can use the same table for both Users
     and Groups, or use separate ones.  In the latter case, you can have
     several records for each user, allowing the one user to belong to
     multiple groups.

     As for the User directive, you can provide an optional field width for
     the group field when using mSQL databases.

Database
     This directive is valid for SQL databases only and indicates where the
     authentication database can be found.  It should be in the format
     database@host.  If the hostname is omitted, "localhost" is assumed.
     For mSQL databases, performance will be much better if database and
     Web server are on the same machine because in this case, the client
     and server use a Unix socket to communicate rather than a TCP/IP
     socket.

Server
     Web servers differ slightly in the format of the users and groups
     databases.  This directive indicates which server you are using.
     Recognized values include "apache", "ncsa", "cern" and "netscape."
     Example:

          Server cern

     If no server is specified, "apache" is assumed.  If your server is not
     on this list, try "ncsa".

Driver
     For SQL databases only, this directive specifies what DBD (database
     driver) module to use.  It defaults to "mSQL".  You can use any
     database for which a DBD module is available.  You must also, of
     course, compile and configure the Web server to correctly use the
     driver.

Fields
     This directive lists other fields that can be found in the user table.
     These fields can then be read and set automatically by the user_manage
     application.  Note that this works reliably in SQL databases only.
     Large fields, or fields that contain the "=" character, will fail when
     applied to text or DBM files.

     This directive expects a list of field names in the format
     name[:type][width].  The field type and width are hints used by the
     user_manage application to format the field values correctly.  The
     type can be one of "i", for an integer value, "s" for a string value
     and "f" for a floating point number.  If not specified, the field is
     assumed to be of type string.  The field value must be an integer.

     In this example, we define three fields named "Name", "Age" and
     "Paid".  The first is a string value of default length.  The second is
     an integer.  The third is a string of length one (it's assumed to be a
     "Y" or "N"):

          Fields	Name Age:i Paid:s1

     Other fields may be present in the database.  The Fields directive
     tells the user_manage script which fields should be made visible to
     the user interface.

Mode
     This directive sets the mode that Realm.pm will use to create the
     database files, if it needs to.  The mode should be in octal form.
     This value can be overriden with the -mode argument in the connect()
     method.  The default is 0644 (-rw-r-r-).

Default
     If this directive is present, the current realm becomes the default to
     use when no realm is explicitly indicated.  If no section in the
     configuration file contains this directive, the first defined realm
     becomes the default.  It is a fatal error for Default to appear in
     more than one section.

CLASSES
=======

   There are two closely tied classes in Realm.pm.  HTTPD::Realm parses
the configuration file, maintains lists of realms, responds to inquiries
about realms, and opens up connections to realms' underlying databases.
HTTPD::RealmDef defines the object that holds information about a
particular realm.

HTTPD::Realm METHODS
====================

new()
          $realms = HTTPD::Realm->new(-config=>'/path/to/config/file');

     Create a new set of realm definitions from the given configuration
     file.

exists()
          $exists = $realms->exists(-realm=>'subscribers');

     Returns true if the named realm exists.  Otherwise returns undef.
     Arguments:

          -realm    Name of the realm.

     An alternative form is to use the name of the realm without the named
     argument:

          $exists = $realms->exists('subscribers');

list()
          @realms = $realms->list();

     Returns the list of realm names defined in the configuration file.

realm()
          $realmdef = $realms->realm(-realm=>'subscribers');

     Returns the RealmDef object that defines the realm.  See the
     discussion below for more details.  An alternative form is to use the
     name of the realm alone:

          $realmdef = $realms->realm('subscribers');

connect()
          $database = $realms->connect(-realm=>'subscribers',
                                       -writable=>1,
                                       -mode=>0600);

     Connect to the named realm, returning a database handle (actually, a
     RealmManager object). Recognized named arguments are:

          -realm     Name of the realm.
          -mode      Mode with which to create file, if necessary.
          -writable  Whether this realm is to be writable.

     By default, realms are opened read-only.  If you choose to open it for
     writing, you can provide a mode for creting the file, overriding the
     mode defined in the configuration file.  If the realm is not listed in
     the configuration file, this routine returns undef.

HTTPD::RealmDef METHODS
=======================

new()
          $realmdef = HTTPD::RealmDef->new('subscribers');

     Create a new RealmDef and assign it a name.  This method is usually
     called internally.

name()
          $name = $realmdef->name();

     Return the name of this realm.

userdb()
          $userdata = $realmdef->userdb();

     Return the path to the user database defined in the configuration
     file.  For non-SQL databases, this is the path to the database or text
     file.  For SQL databases, this is the table and field definition line.
     You can get a pre-parsed version of this information using SQLdata(),
     see below.

groupdb()
          $groupdata = $realmdef->groupdb();

     Return the path to the group database defined in the configuration
     file.  For non-SQL databases, this is the path to the database or text
     file.  For SQL databases, this is the table and field definition line.
     You can get a pre-parsed version of this information using SQLdata(),

mode()
          $mode = $realmdef->mode();

     Return the mode for creating the database file.

database()
          $database = $realmdef->database();

     Return the database name and host (SQL databases only).

fields()
          $fields = $realmdef->fields();

     Return the additional field definition line (SQL databases only).  No
     additional parsing is performed.

usertype()
          $type = $realmdef->usertype();

     Return the type of the user/password database, for example "NDBM".

grouptype()
          $type = $realmdef->grouptype();

     Return the type of the group database, for example "NDBM".

authentication()
          $authentication = $realmdef->authentication();

     Returns the authentication in use for this realm.  May be either
     "Basic" or "Digest".

server()              $server = $realmdef->server();
     Return the type of Web server this realm is designed for.

crypt()
          $crypt = $realmdef->crypt();

     Return the cryptography type for this realm, either "crypt" or "MD5".

SQLdata()
          $data = $realmdef->SQLdata();

     For SQL databases only, return the parsed information from the Users
     and Groups directives.  The value returned is an associative array
     containing the following fields:

          database        name of the SQL database
          host            name of the SQL database host
          dblogin
          dbpassword
          usertable       name of the SQL table containing users & passwords
          grouptable      name of the SQL table containing groups
          userfield       name of the field containing the user ID
          groupuserfield
          groupfield      name of the field containing the group name
          passwdfield     name of the field containing the encrypted password
          userfield_len   length of the user ID field
          groupfield_len  length of the group field
          passwdfield_len length of the password field

connect()
          $database = $realmdef->connect(-writable=>1,
                                         -mode=>0600,
                                         -server=>'ncsa');

     Establish a connection to the realm database, returning a RealmManager
     object.  You can open up a connection read-only or read-write.
     Optional arguments allow you to the values of the Mode and Server
     directives.

          -writable      Open read/write if true.
          -mode          Override file creation mode.
          -server        Override server type.

SEE ALSO
========

   HTTPD::RealmManager(3) HTTPD::UserAdmin(3) HTTPD::GroupAdmin(3),
HTTPD::Authen(3)

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>

   Copyright (c) 1997, Lincoln D. Stein

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SYNOPSIS
========

     use HTTPD::RealmManager;

     # open up the database (could also use HTTPD::Realm::connect())
     $database = HTTPD::RealmManager->open(-config_file=>'/home/httpd/conf/realms.conf',
                                           -realm=>'members',
                                           -writable=>1);

     # List functions
     @users = $database->users();
     @groups = $database->groups();

     # Information about users and groups:
     print "Lincoln's groups are @group\n"
         if @group = $database->group(-user=>'lincoln');

     print "Lincoln is a subscriber\n"
         if $database->match_group(-user=>'lincoln',-group=>'subscribers');

     print "Lincoln's password is $pass\n"
         if $pass = $database->passwd(-user=>'lincoln');

     print "Intruder alert.\n"
         unless $database->match_passwd(-user=>'lincoln',
                                        -password=>'xyzzy');

     $lincoln_info = $database->get_fields(-user=>'lincoln');
     print "Lincoln's full name is $lincoln_info->{Name}\n";

     print "The subscribers are @members.\n"
         if @members = $database->members(-group=>'subscribers');

     # Database updates
     print "Added Fred.\n"
         if $database->set_passwd(-user=>'fred',
                                  -password=>'sssh!',
                                  -fields=>{Name=>'Fred Smith',
                                            Nationality=>'French'});

     print "Assigned Fred to 'subscribers' and 'VIPs'\n"
     	if $database->set_group(-user=>'fred',
                                 -group=>['subscribers','VIPs']);

     print "Changed Fred's nationality.\n"
          if $database->set_fields(-user=>'fred',
                                   -fields=>{Nationality=>'German'});

     print "Fred is now gone.\n"
         if $database->delete_user(-user=>'fred');

     print "VIP group is now gone.\n"
         if $database->delete_group(-group=>'VIPs');

     print "Uh oh.  An error occurred: ",$database->errstr,"\n"
         if $database->errstr;

DESCRIPTION
===========

   HTTPD::RealmManager provides a high-level, unified view onto the many
access control databases used by Apache, Netscape, NCSA httpd, CERN and
other Web servers.  It works hand-in-hand with HTTPD::Realm, which
provides access to a standard configuration file for describing security
database setups.  Internally, HTTPD::Realm uses Doug MacEachern's
HTTPD-Tools modules for database access and locking.

   *Important note:* Do not use these modules to adjust the Unix password
or group files.  They do not have the same format as the Web access
databases.

METHODS
=======

   HTTPD::RealmManager provides the following class and instance methods.

new()
          $db = HTTPD::RealmManager->new(-realm    => $realm_def,
                                         -writable => 1,
                                         -mode     => 0644,
                                         -server   => 'ncsa');

     The new() class method creates a new connection to the database
     indicated by the indicated HTTPD::RealmDef object.  Ordinarily it will
     be more convenient to use the open() method (below) or
     HTTPD::RealmDef::connect().  Only the -realm argument is mandatory.
     The others are optional and will default to reasonable values.

     If successful, the function result is an HTTPD::RealmManager object,
     which you can treat as a handle to the database.

     Arguments:

          -realm      Realm definition.  See HTTPD::Realm(3).
          -writable   If true, open database for writing.
          -mode       Override file creation mode.
          -server     Override server type.

open()
          $db = HTTPD::RealmManager->open(-realm       => 'subscribers',
                                          -config_file => '/home/httpd/conf/realms.conf',
                                          -writable => 1,
                                          -mode     => 0644,
                                          -server   => 'ncsa');

     The open() class method creates a new connection to the database
     given the indicated configuration file and realm name.  Internally it
     first creates an HTTPD::Realm object, then queries it for the named
     realm, passing this result to new().  This is probably the easiest way
     to create a new connection.

     Only the -realm and -config_file arguments are mandatory.  The others
     are optional and will default to reasonable values.

     If successful, the function result is an HTTPD::RealmManager object,
     which you can treat as a handle to the database.

     Arguments:

          -config_file Path to realm configuration file. See HTTPD::Realm(3).
          -realm       Realm name.
          -writable    If true, open database for writing.
          -config      An alias for -config_file.
          -mode        Override file creation mode.
          -server      Override server type.

close()
          $db->close()

     When you are done with the database you should close() it.  This will
     commit changes and tidy up.

users()
          @users = $db->users();

     Return all users known to this database as a (potentially very long)
     list.

groups()
          @groups = $db->groups()

     Return all groups known to this database as a (potentially very long)
     list.

group()
          @groups = $db->group(-user=>'username');
          $boolean = $db->group(-user=>'username',-group=>'groupname');

     This method returns information about the groups that a user belongs
     to.  Called with the name of the user only, it returns a list of all
     the groups the user is a member of.  Called with both a user and a
     group name, it returns a boolean value indicating whether the user
     belongs to the group.

     Arguments:

          -user     Name of the user
          -group    Name of the group
          -name     An alias for -user
          -grp      An alias for -group

     You can also call this method with the positional parameters
     (user,group), as in:

          @groups = $db->group('username');

match_group()
          $boolean = $db->match_group(-user=>'username',-group=>'groupname');

     This method is identical to the group() function, except that it
     requires a group name to be provided.

passwd()
          $password = $db->passwd(-user=>'username');
          $boolean = $db->passwd(-user=>'username',-password=>'password');

     Called with a user name this method returns his *encrypted* password.
     Called with a user name and an *unencrypted* password, this routine
     returns a boolean indicating whether this password matches the stored
     password.

     Arguments:

          -user      Name of the user
          -password  Password to check against (optional)
          -name      Alias for -user
          -passwd    Alias for -password

     You can also call this routine using positional arguments, where the
     first argument is the user name and the second is the password to try:

          print "You're OK" if $db->password('Fred','Open sesame');

password()
          $password = $db->password(-user=>'username');
          $boolean = $db->password(-user=>'username',-password=>'password');

     An alias for passwd(), just to make things interesting.

match_passwd()
          $boolean = $db->match_passwd(-user=>'username',-password=>'password');

     This method is identical to the two-argument form of passwd(), except
     that it requires a trial password to be provided.

match()
          $boolean = $db->match(-user=>'username',-password=>'password');

     This method is an alias for match_passwd(), just to make things
     interesting.

get_fields()
          $fields = $db->get_fields(-user=>'username',
                                    -fields=>\@list_of_fields);

     The user database can contain additional information about the user in
     the form of name/value pairs.  This method provides access to these
     "additional fields."

     get_fields() accepts a user name and optionally a list of the fields
     to retrieve.  If no field list is provided, it will retrieve all
     fields defined in the security realm configuration file (see
     HTTPD::Realm (3)).  In practice, it is rarely necessary to limit the
     fields that are retrieved unless you are accessing a SQL database
     table containing an unusually large number of fields.

     Arguments:

          -user    Name of user
          -fields  List reference to fields to retrieve (optional)
          -name    Alias for -user
          -field   Alias for -fields

     The return value is a hash reference.  You can retrieve the actual
     values like this:

          $fields = $db->get_fields(-user=>'fred');
          print $fields->{'Full_Name'};

set_passwd()
          $resultcode = $db->set_passwd(-user=>'username',
                                        -password=>'password',
                                        -fields=>\%extra_fields);

     set_passwd() sets the user's password and/or additional field
     information.  If the user does not already exist in the database, he
     is created.  The method requires the username and one or more of the
     new password and a hash reference to additional user fields.  If
     either the password or the additional fields are absent, they will be
     unchanged.

     When setting field values, the old and new values are merged.  To
     delete a previous field value, you must explicitly set it to undef in
     the hash reference.  Otherwise the previous value will be retained.

     A result code of true indicates a successful update.  The method will
     fail unless the database is opened for writing.

     Arguments:

          -user      Name of the user to update
          -password  New password
          -fields    Hash ref to the fields to update
          -name      Alias for -user
          -passwd    Alias for -password
          -gcos      Alias for -fields

set_password()
          $resultcode = $db->set_password(-user=>'username',
                                          -password=>'password',
                                          -fields=>\%extra_fields);

     This is an alias for set_passwd(), just to make life interesting.

set_fields()
          $resultcode = $db->set_fields(-user=>'username',
                                        -fields=>\%extra_fields);

     set_fields() allows you to adjust the extra field information about
     the designated user.  Its functionality is identical to set_passwd(),
     but the name is a little more appropriate.  This method requires a
     user name and a hash reference containing new field values.

     When setting field values, the old and new values are merged.  To
     delete a previous field value, you must explicitly set it to undef in
     the hash reference.  Otherwise the previous value will be retained.

     Arguments:

          -user      Name of the user to update
          -fields    Hash ref to the fields to update
          -name      Alias for -user
          -gcos      Alias for -fields

     A true result code indicates that the database was successfully
     updated.  The database must be writable for this method to succeed.

set_group()
          $resultcode = $db->set_group(-user=>'username',
                                       -group=>\@list_of_groups);

     This method allows you to set the list of groups that a user belongs
     to without changing any other information about him or her.  It
     expects a user name and a list reference pointing to the groups to
     assign the user to.  The user will be removed from any groups he
     previously participated in.

     Arguments:

          -user      Name of the user to update
          -group     List of groups to assign user to
          -name      Alias for -user
          -grp       Alias for -group

     A true result code indicates that the database was successfully
     updated.  The database must be writable for this method to succeed.

delete_user()
          $resultcode = $db->delete_user(-user=>'username');

     Delete the user and all his associated information from the database.
     If there are any empty groups after this deletion, they are removed as
     well.  This operation is irreversible.

     Arguments:

          -user      Name of the user to remove
          -name      Alias for -user

     A true result code indicates that the database was successfully
     updated.  The database must be writable for this method to succeed.

     You may also call this method with a single positional argument:

          $resultcode = $db->delete_user('username');

delete_group()
          $resultcode = $db->delete_group(-group=>'groupname');

     Delete the group from the database.  Users who participate in the
     deleted group are not deleted.  However, they may find themselves
     orphaned (not participating in any groups).

     Arguments:

          -group      Name of the user to remove
          -grp        Alias for -group

     A true result code indicates that the database was successfully
     updated.  The database must be writable for this method to succeed.

     You may also call this method with a single positional argument:

          $resultcode = $db->delete_group('groupname');

errstr()
          $error = $db->errstr();

     This method returns a string describing the last error encountered by
     RealmManager.pm.  It is not reset by successful function calls, so its
     contents are only valid after a method returns a false result code.

SEE ALSO
========

   HTTPD::Realm(3) HTTPD::UserAdmin(3) HTTPD::GroupAdmin(3),
HTTPD::Authen(3)

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>

   Copyright (c) 1997, Lincoln D. Stein

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Management of HTTP server user databases
****************************************

NAME
====

   HTTPD::UserAdmin - Management of HTTP server user databases

SYNOPSIS
========

     use HTTPD::UserAdmin ();

DESCRIPTION
===========

   This software is meant to provide a generic interface that hides the
inconsistencies across HTTP server implementations of user and group
databases.

METHODS
=======

new ()
     Here's where we find out what's different about your server.

     Some examples:

          @DBM = (DBType => 'DBM',
          	    DB     => '.htpasswd',
          	    Server => 'apache');

          $user = new HTTPD::UserAdmin @DBM;

     This creates an object who's database is a DBM file named
     '.htpasswd', in a format that the Apache server understands.

          @Text = (DBType => 'Text',
          	     DB     => '.htpasswd',
          	     Server => 'ncsa');

          $user = new HTTPD::UserAdmin @Text;

     This creates an object whose database is a plain text file named
     '.htpasswd', in a format that the NCSA server understands.

          @SQL =  (DBType =>    "SQL",
          	     Host =>      "",             #server hostname
          	     Port =>      "",             #server port
          	     DB =>        "www",          #database name
          	     User =>      "", 	  	  #database login name
          	     Auth =>      "",             #database login password
                   Encrypt =>   "crypt",        #encryption method
          	     Driver =>    "mSQL",         #driver for DBI
          	     Server =>    "apache",       #HTTP server type, not required
          	     UserTable => "www-users",    #table with field names below
          	     NameField => "user",         #field for the name
          	     PasswordField => "password", #field for the password
          	     );

          $user = new HTTPD::UserAdmin @SQL;

     This creates an object who's mSQL database is named 'www', with a
     schema that the Apache server (extention) understands.

     Full list of constructor attributes:

     Note: Attribute names are case-insensitive

     *DBType*  - The type of database, one of 'DBM', 'Text', or 'SQL'
     (Default is 'DBM')

     DB      - The database name (Default is '.htpasswd' for DBM & Text
     databases)

     Server  - HTTP server name (Default is the generic class, that works
     with NCSA, Apache and possibly others)

     Note: run 'perl t/support.t matrix' to see what support is currently
     availible

     Encrypt - One of 'crypt', 'MD5', or 'none' (no encryption.  Defaults
     to 'crypt'

     Locking - Boolean, Lock Text and DBM files (Default is true)

     Path    - Relative DB files are resolved to this value  (Default is
     '.')

     Debug   - Boolean, Turn on debug mode

     Flags   - The read, write and create flags.  There are four modes:
     *rwc* - the default, open for reading, writing and creating.  rw -
     open for reading and writing.  r - open for reading only.  w - open
     for writing only.

     Specific to DBM files:

     *DBMF*    - The DBM file implementation to use (Default is 'NDBM')

     Mode    - The file creation mode, defaults to '0644'

     Specific to DBI: We talk to an SQL server via Tim Bunce's DBI
     interface. For more info see:
     http://www.hermetica.com/technologia/DBI/

     Host      - Server hostname

     Port      - Server port

     User      - Database login name

     Auth      - Database login password

     Driver    - Driver for DBI  (Default is 'mSQL')

     *UserTable* - Table with field names below

     *NameField* - Field for the name  (Default is 'user')

     *PasswordField* - Field for the password  (Default is 'password')

     From here on out, things should look the same for everyone.

add($username,$password,[@fields])
add($username,$password,\%fields)
     Add a user.

     Fails if $username exists in the database

          if($user->add('dougm', 'secret')) {
          	print "You have the power!\n";
          }

     You may need to pass additional fields, such as the user's real name.
     This depends on your server of course.

          $user->add('JoeUser', 'try2guess', '', 'Joseph A. User');

     You can also pass a set of field name/value pairs in the form of a
     hash ref.  Example

          $user->add('JoeUser','try2guess','',
                               {'Name'=>'Joseph A. User','Credit_limit'=>2000});

delete($username)
     Delete a user

          if($user->delete('dougm')) {
          	print "He's gone\n";
          }

suspend($username)
     Suspend a user

          if($user->suspend('dougm')) {
          	print "Account suspended\n";
          }

unsuspend($username)
     Unsuspend a suspended user

          if($user->unsuspend('dougm')) {
          	print "Account restored to normal\n";
          }

exists($username)
     True if $username is found in the database

          if($user->exists('dougm')) {
          	die "oh no!";
          }

password()
     Returns the encrypted password for a user

          $passwd = $user->password("dougm");

     Useful for copying users to another database.

fetch($username,@fields)
          Fetch a list of field values from the indicated user.  Field names may
          be provided as a list or as an array reference.  The return value is a
          reference to a hash containing the field/value pairs.

list()
     Returns a list of usernames in the current database

          @users = $user->list

update($username,$password)
update($username,$password,\%fields) *SQL only*
     Update $username with a new $password

          if($user->update('dougm', 'idunno')) {
          	print "Updated\n";
          }

     With SQL servers, you can update other fields in the table by passing
     a hash reference:

          $user->update('dougm','idunno',{'credit_limit'=>1000});

     An undefined value in the password field will leave the field
     unchanged.

group()
     Short cut for creating an HTTPD::GroupAdmin object.  All applicable
     attributes are inherited, but can be overridden.

          $group = $user->group(NAME => 'www-group');

     (See HTTPD::GroupAdmin)

convert(@Attributes)
     Convert a database.

          $dbmuser = $user->convert(@Apache);

lock([$timeout])
unlock()
     These methods give you control of the locking mechanism.

          $user = new HTTPD::UserAdmin (Locking => 0); #turn off auto-locking
          $user->lock; #lock the object's database
          $user->add($username,$passwd); #write while file is locked
          $user->unlock; release the lock

db($dbname);
     Select a different database.

          $olddb = $user->db($newdb);
          print "Now we're reading and writing '$newdb', done with '$olddb'n\";

flags([$flags])
     Get or set read, write, create flags.

commit
     Commit changes to disk (for Text files).

Message Digest User Databases
=============================

   Currently, you can store user info in a format for servers who support
Message Digest Authentication.  Here's an example:

     $user = new HTTPD::UserAdmin (DB => '.htdigest', Encrypt => 'MD5');

     ($username,$realm,$password) = ('JoeUser', 'SomePlace', '14me');

     #The checksum contains more info that just a password
     $user->add($username, "$username:$realm:$password");
     $user->update($username, "$username:$realm:newone");

     $info = $user->password($username);
     ($realm, $checksum) = split(":", $info);

     $user->delete($username);

   See <URL:http://hoohoo.ncsa.uiuc.edu/docs/howto/md5_auth.html> for
NCSA's implementation.

   So, it's a little more work, but don't worry, a nicer interface is on
the way.

SEE ALSO
========

   HTTPD::GroupAdmin(3), HTTPD::Authen(3)

AUTHOR
======

   Doug MacEachern <dougm@osf.org>

   Copyright (c) 1996, Doug MacEachern

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

A complete grammar for parsing Verilog code using perl
******************************************************

NAME
====

   Hardware::Verilog::Parser - A complete grammar for parsing Verilog code
using perl

SYNOPSIS
========

     use Hardware::Verilog::Parser;
     $parser = new Hardware::Verilog::Parser;

     $parser->Filename(@ARGV);

DESCRIPTION
===========

   This module defines the complete grammar needed to parse any Verilog
code.  By overloading this grammar, it is possible to easily create perl
scripts which run through Verilog code and perform specific functions.

   For example, a Hierarchy.pm uses Hardware::Verilog::Parser to overload
the grammar rule for module instantiations. This single modification will
print out all instance names that occur in the file being parsed.  This
might be useful for creating an automatic build script, or a graphical
hierarchical browser of a Verilog design.

   This module is currently in alpha release. All code is subject to
change.  Bug reports are welcome.

   DSLI information:

   D - Development Stage

     a - alpha testing

   S - Support Level

     d - developer

   L - Language used

     p - perl only, no compiler needed, should be platform independent

   I - Interface Style

     O - Object oriented using blessed references and / or inheritance

AUTHOR
======

   Copyright (C) 2000 Greg London   All Rights Reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   email contact: greg42@bellatlantic.net

SEE ALSO
========

   Parse::RecDescent, version 1.77

   perl(1).

A complete grammar for parsing VHDL code using perl
***************************************************

NAME
====

   Hardware::Vhdl::Parser - A complete grammar for parsing VHDL code using
perl

SYNOPSIS
========

     use Hardware::Vhdl::Parser;
     $parser = new Hardware::Vhdl::Parser;

     $parser->Filename(@ARGV);

DESCRIPTION
===========

   This module defines the complete grammar needed to parse any VHDL code.
By overloading this grammar, it is possible to easily create perl scripts
which run through VHDL code and perform specific functions.

   For example, a Hierarchy.pm uses Hardware::Vhdl::Parser to overload the
grammar rule for component instantiations. This single modification will
print out all instance names that occur in the file being parsed.  This
might be useful for creating an automatic build script, or a graphical
hierarchical browser of a VHDL design.

   This module is currently in Beta release. All code is subject to change.
Bug reports are welcome.

   DSLI information:

   D - Development Stage

     a - alpha testing

   S - Support Level

     d - developer

   L - Language used

     p - perl only, no compiler needed, should be platform independent

   I - Interface Style

     O - Object oriented using blessed references and / or inheritance

AUTHOR
======

   Copyright (C) 2000 Greg London   All Rights Reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   email contact: greg42@bellatlantic.net

SEE ALSO
========

   Parse::RecDescent version 1.77

   perl(1).

Programatically fill elements of a hash based in prerequisites
**************************************************************

NAME
====

   HashFiller - Programatically fill elements of a hash based in
prerequisites

SYNOPSIS
========

     use Hash::Filler;

     my $hf = new Hash::Filler;

     # Show how a ->fill() method executes
     # the rules
       $Hash::Filler::DEBUG = 1;

     # Add a set of rules

     $hf->add('key1', sub { my $hr = shift; ... }, ['key2', 'key3'], $pref);
     $hf->add('key1', sub { my $hr = shift; ... }, [], $pref);
     $hf->add('key2', sub { my $hr = shift; ... }, ['key1', 'key3'], $pref);
     $hf->add('key3', sub { my $hr = shift; ... }, ['key1', 'key2'], $pref);
     $hf->add(undef, sub { ... }, [], $pref);

     # Remove rules

     $hf->remove($rule_id);

     $hf->loop(0);			# Don't try to avoid infinite loops

     # Test if a key exists using defined()
       $hf->method($Hash::Filler::DEFINED);

     my %hash;

     $hf->fill(\%hash, 'key1');	# Calculate the value of $hash{key1}
     $hash{'key2'} = 'foo';	# Manually fill a hash position
     $hf->fill(\%hash, 'key2');	# Calculate the value of $hash{key2}
     $hr->dump_r_tree();		# Print the key tree

     my @stats = $hf->stats();	# Obtain statistics about rule invocation
     my @prof = $hf->profile();	# Obtain profiling information about the rules

DESCRIPTION
===========

   `Hash::Filler' provides an interface so that hash elements can be
calculated depending in the existence of other hash elements, using
user-supplied code references.

   One of the first uses of this module was inside a server. In this
server, the responses to commands came from external sources. For each
request, the server needed to contact a number of external sources to
calculate the proper answer. These calculations sometimes attempted
redundant external accesses, thus increased the response time and load.

   To help in this situation, the calculations were rewritten to access a
hash instead of the external sources directly and this module was used to
fill the hash depending on the requirements of the calculations. The
external accesses were also improved so that more than one choice or rule
existed for each datum, depending on wether prerequisites existed already
in the hash or not.

   Hopefully this explanation will make it easier to understand what this
module is about :)

   There are a few relevant methods, described below:

`->add($key, $code, $r_prereq, $pref)'
     Adds a new rule to the `Hash::Filler' object. The rule will be used
     to fill the hash bucket identified with key $key. To fill this bucket,
     the code referenced by $code will be invoked, passing it a reference
     to the hash being worked on and the key that is being filled. This
     will only be called if all of the hash buckets whose keys are in the
     list referenced by $r_prereq `exist'.

     If the user-supplied code returns a false value, failure is assumed.

     An optional preference can be supplied. This is used to help the
     internal rule selection choose the better rule.

     Multiple rules for the same $key and the same $r_prereq can be added.
     The module will attempt to use them both but the execution order will
     be undefined unless you use $pref. The default $pref is 100.

     A special case occurs when $key is undefined. In this case, this rule
     is said to be a 'wildcard'. This means that the rule applies to any
     key that needs to be filled. Wildcard rules are applied after any
     matching rules (ie, after rules that apply specifically to a given
     $key). Multiple wildcard rules are selected based in the preference
     and availability of prerequisites.

     This function returns a 'rule identifier'. This identifier is the
     index that designates a given rule. Generally, it is only used in
     conjunction with profiling.

`->remove($id)'
     Removes the rule whose identifier matches $id. The implementation
     actually does not remove the rule. Instead it marks the rule as
     non-usable.

`->dump_r_tree'
     This method prints out a representation of the rule tree kept by the
     object. The tree lists the rules in the order they would be preferred
     for a given key.

     Output is sent to STDOUT.

`->profile'
     Returns an array containing time profiles for the execution of each
     rule. The index in the array is the identifier assigned for each
     rule. Each slot in the array contain the accumulated time for all the
     invocations of that particular rule.

     Slot 0 in the array contains the accumulated time for ALL the invoked
     rules. This make it easier to find the most important contributors to
     the accumulated time.

     Note that time is only computed if the user-supplied method must be
     called. Whenever the hash bucket to be filled by a rule already has a
     value, this method will not be called and no time will be added to
     this rule.

`->stats'
     This method returns an array which counts the number of times a given
     rule has been invoked and its user-supplied method has been called.
     The index into the array is the rule identifier, just as in the case
     of `->profile'. The 0th element of the array contains the total
     number of times that `->fill' has been called. This is useful to
     deduce how many times the rules needed to be invoked.

`->method($val)'
     Which method to use to decide if a given key is present in the hash.
     The accepted values are:

    `$Hash::Filler::EXISTS' (default)
               The existence of a hash element or key is calculated using a
               construct like C<exists($hash{$key})>.

    `$Hash::Filler::DEFINED'
               The existence of a hash element or key is calculated using a
               construct like C<defined($hash{$key})>.

    `$Hash::Filler::TRUE'
               The existence of a hash element or key is calculated using a
               construct like C<$hash{$key}>.

    Reference to a sub
               This allows the user to specify a function to determine wether a
               hash bucket must be calculated or not. The function is invoked by
               passing it a reference to the hash and the key that must be
               checked. The function must return a TRUE value is the bucket is
               already populated or false if the corresponding rules must be
               applied.

     This allow this module to be customized to the particular application
     in which it is being used. Be advised that changing this might cause a
     change in which and when the rules are invoked for a particular hash
     so probably it should only be used before the first call to `->fill'.

     By defult, the module uses exists() to do this check.

`->loop($val)'
     Controls if the module should try to avoid infinite loops. A true $val
     means that it must try (the default). A false value means otherwise.

`->fill($r_hash, $key)'
     Attempts to fill the bucket $key of the hash referenced by $r_hash
     using the supplied rules.

     This method will return a true value if there are rules that allow the
     requested $key to be calculated (or the $key is in the hash) and the
     user supplied code returned true.

     To avoid infinite loops, the code will not invoke a rule twice unless
     `->loop' is called with a true value. The rules will be used starting
     with the ones with less prerequisites, as these are assumed to be
     lighter. To use a different ordering, specify $pref. Higher values of
     $pref are used first.

CAVEATS
=======

   This code uses recursion to resolve rules. This allows it to figure out
the value for a given key with only an incomplete rule specification. Be
warned that this might be costly if used with large sets of rules.

AUTHOR
======

   Luis E. Munoz < lem@cantv.net>

SEE ALSO
========

   perl(1).

WARRANTY
========

   Absolutely none.

Perl extension for non-vivifying exists and defined functions
*************************************************************

NAME
====

   Hash::NoVivify - Perl extension for non-vivifying exists and defined
functions

SYNOPSIS
========

     use Hash::NoVivify qw(Defined Exists);

     ...

     if (Exists(\%hash, qw(key1 key2 ... keyn ))) {
         ...
     }

     if (Defined(\%hash, qw(key1 key2 ... keyn))) {
         ...
     }

DESCRIPTION
===========

   When used on a hash, the exists() and defined() functions will create
entries in a hash in order to evaluate the function.

   For instance, the code:

     %a = (a => 1, b=> 2);
     print "Doesn't exist\n" unless exists($a{c});
     print "Also Doesn't exist\n" unless exists($a{c}->{d});
     print "Oh, my, not good\n" if exists($a{c});

   will print out:

     Doesn't exist
     Also Doesn't exist
     Oh, my, not good

   The Hash::NoVivify module provides two functions, Defined() and
Exists(), which avoid this, at the cost of a slightly convoluted syntax.
Both functions take a reference to a hash, followed by a list of
descending keys defining the hash entry to be investigated.

AUTHOR
======

   Brent B. Powers (B2Pi), Powers@B2Pi.com

   Copyright(c) 1999 Brent B. Powers. All rights reserved. This program is
free software, you may redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   perl(1), perlfunc(1).

Perl extensions for keeping data partially sorted
*************************************************

NAME
====

   Heap - Perl extensions for keeping data partially sorted

SYNOPSIS
========

     use Heap;

     my $heap = Heap->new;
     my $elem;

     use Heap::Elem::Num(NumElem);

     foreach $i ( 1..100 ) {
         $elem = NumElem( $i );
         $heap->add( $elem );
     }

     while( defined( $elem = $heap->extract_maximum ) ) {
         print "Smallest is ", $elem->val, "\n";
     }

DESCRIPTION
===========

   The Heap collection of modules provide routines that manage a heap of
elements.  A heap is a partially sorted structure that is always able to
easily extract the smallest of the elements in the structure (or the
largest if a reversed compare routine is provided).

   If the collection of elements is changing dynamically, the heap has
less overhead than keeping the collection fully sorted.

   The elements must be objects as described in `"Heap::Elem"' in this node
and all elements inserted into one heap must be mutually compatible -
either the same class exactly or else classes that differ only in ways
unrelated to the *Heap::Elem* interface.

METHODS
=======

$heap = HeapClass::new(); $heap2 = $heap1->new();
     Returns a new heap object of the specified (sub-)class.  This is
     often used as a subroutine instead of a method, of course.

$heap->DESTROY
     Ensures that no internal circular data references remain.  Some
     variants of Heap ignore this (they have no such references).  Heap
     users normally need not worry about it, DESTROY is automatically
     invoked when the heap reference goes out of scope.

$heap->add($elem)
     Add an element to the heap.

$elem = $heap->minimum
     Return the top element on the heap.  It is not removed from the heap
     but will remain at the top.  It will be the smallest element on the
     heap (unless a reversed cmp function is being used, in which case it
     will be the largest).  Returns undef if the heap is empty.

$elem = $heap->extract_minimum
     Delete the top element from the heap and return it.  Returns undef if
     the heap was empty.

$heap1->absorb($heap2)
     Merge all of the elements from *$heap2* into *$heap1*.  This will
     leave *$heap2* empty.

$heap1->decrease_key($elem)
     The element will be moved closed to the top of the heap if it is now
     smaller than any higher parent elements.  The user must have changed
     the value of $elem before *decrease_key* is called.  Only a decrease
     is permitted.  (This is a decrease according to the cmp function - if
     it is a reversed order comparison, then you are only permitted to
     increase the value of the element.  To be pedantic, you may only use
     *decrease_key* if *$elem-*cmp($elem_original) <= 0> if
     *$elem_original* were an elem with the value that $elem had before it
     was *decreased*.)

$elem = $heap->delete($elem)
     The element is removed from the heap (whether it is at the top or
     not).

AUTHOR
======

   John Macdonald, jmm@elegant.com

COPYRIGHT
=========

   Copyright 1998, O'Reilly & Associates.

   This code is distributed under the same copyright terms as perl itself.

SEE ALSO
========

   Heap::Elem(3), Heap::Binary(3), Heap::Binomial(3), Heap::Fibonacci(3).

a Perl extension for keeping data partially sorted
**************************************************

NAME
====

   Heap::Binary - a Perl extension for keeping data partially sorted

SYNOPSIS
========

     use Heap::Binary;

     $heap = Heap::Binary->new;
     # see Heap(3) for usage

DESCRIPTION
===========

   Keeps an array of elements in heap order.  The heap method of an
element is used to store the index into the array that refers to the
element.

   See Heap, for details on using this module.

AUTHOR
======

   John Macdonald, jmm@elegant.com

COPYRIGHT
=========

   Copyright 1998, O'Reilly & Associates.

   This code is distributed under the sme copyright as perl itself.

SEE ALSO
========

   Heap(3), Heap::Elem(3).

a Perl extension for keeping data partially sorted
**************************************************

NAME
====

   Heap::Binomial - a Perl extension for keeping data partially sorted

SYNOPSIS
========

     use Heap::Binomial;

     $heap = Heap::Binomial->new;
     # see Heap(3) for usage

DESCRIPTION
===========

   Keeps elements in heap order using a linked list of binomial trees.
The heap method of an element is used to store a reference to the node in
the list that refers to the element.

   See Heap, for details on using this module.

AUTHOR
======

   John Macdonald, jmm@elegant.com

COPYRIGHT
=========

   Copyright 1998, O'Reilly & Associates.

   This code is distributed under the sme copyright as perl itself.

SEE ALSO
========

   Heap(3), Heap::Elem(3).

Perl extension for elements to be put in Heaps
**********************************************

NAME
====

   Heap::Elem - Perl extension for elements to be put in Heaps

SYNOPSIS
========

     use Heap::Elem::SomeInheritor;

     use Heap::SomeHeapClass;

     $elem = Heap::Elem::SomeInheritor->new( $value );
     $heap = Heap::SomeHeapClass->new;

     $heap->add($elem);

DESCRIPTION
===========

   This is an inheritable class for Heap Elements.  It provides the
interface documentation and some inheritable methods.  Only a child
classes can be used - this class is not complete.

METHODS
=======

$elem = Heap::Elem::SomeInheritor->new( [args] );
     Creates a new Elem.

$elem->heap( $val ); $elem->heap;
     Provides a method for use by the Heap processing routines.  If a
     value argument is provided, it will be saved.  The new saved value is
     always returned.  If no value argument is provided, the old saved
     value is returned.

     The Heap processing routines use this method to map an element into
     its internal structure.  This is needed to support the Heap methods
     that affect elements that are not are the top of the heap -
     *decrease_key* and delete.

$elem1->cmp($elem2)
     A routine to compare two elements.  It must return a negative value
     if this element is less than *$elem2*, 0 if they are equal, or a
     positive value if this element is greater than *$elem2*.  Just as
     with sort, you can negate the meaning to reverse the order - causing
     the heap to always return the largest element instead of the
     smallest.  (That does make the Heap method names minimum,
     *extract_minimum*, and *decrease_key* counter-intuitive, though.)

INHERITING
==========

   This class can be inherited to provide an oject with the ability to be
heaped.  If the object is implemented as a hash, and if it can deal with a
kay of heap, leaving it unchanged for use by the heap routines, then the
following implemetation will work.

     package myObject;

     require Exporter;

     @ISA = qw(Heap::Elem);

     sub new {
         my $self = shift;
         my $class = ref($self) || $self;

     my $self = SUPER::new($class);

     # set $self->{key} = $value;
       }

     sub cmp {
         my $self = shift;
         my $other = shift;

     $self->{key} cmp $other->{key};
       }

     # other methods for the rest of myObject's functionality

AUTHOR
======

   John Macdonald, jmm@elegant.com

SEE ALSO
========

   Heap(3), Heap::Elem::Num(3), Heap::Elem::NumRev(3), Heap::Elem::Str(3),
Heap::Elem::StrRev(3).

Perl extension for Numeric Heap Elements
****************************************

NAME
====

   Heap::Elem::Num - Perl extension for Numeric Heap Elements

SYNOPSIS
========

     use Heap::Elem::Num( NumElem );
     use Heap::Fibonacci;

     my $heap = Heap::Fibonacci->new;
     my $elem;

     foreach $i ( 1..100 ) {
         $elem = NumElem( $i );
         $heap->add( $elem );
     }

     while( defined( $elem = $heap->extract_minimum ) ) {
         print "Smallest is ", $elem->val, "\n";
     }

DESCRIPTION
===========

   Heap::Elem::Num is used to wrap numeric values into an element that can
be managed on a heap.  The top of the heap will have the smallest element
still remaining.  (See Heap/Elem/NumRev, if you
want the heap to always return the largest element.)

   The details of the Elem interface are described in Heap/Elem.

   The details of using a Heap interface are described in Heap.

AUTHOR
======

   John Macdonald, jmm@elegant.com

SEE ALSO
========

   Heap(3), Heap::Elem(3), Heap::Elem::NumRev(3).

Perl extension for Reversed Numeric Heap Elements
*************************************************

NAME
====

   Heap::Elem::NumRev - Perl extension for Reversed Numeric Heap Elements

SYNOPSIS
========

     use Heap::Elem::NumRev( NumRElem );
     use Heap::Fibonacci;

     my $heap = Heap::Fibonacci->new;
     my $elem;

     foreach $i ( 1..100 ) {
         $elem = NumRElem( $i );
         $heap->add( $elem );
     }

     while( defined( $elem = $heap->extract_minimum ) ) {
         print "Largest is ", $elem->val, "\n";
     }

DESCRIPTION
===========

   Heap::Elem::NumRev is used to wrap numeric values into an element that
can be managed on a heap.  The top of the heap will have the largest
element still remaining.  (See Heap/Elem/Num, if you
want the heap to always return the smallest element.)

   The details of the Elem interface are described in Heap/Elem.

   The details of using a Heap interface are described in Heap.

AUTHOR
======

   John Macdonald, jmm@elegant.com

SEE ALSO
========

   Heap(3), Heap::Elem(3), Heap::Elem::Num(3).

Perl extension for Object Reference Heap Elements
*************************************************

NAME
====

   Heap::Elem::Ref - Perl extension for Object Reference Heap Elements

SYNOPSIS
========

     use Heap::Elem::Ref( RefElem );
     use Heap::Fibonacci;

     my $heap = Heap::Fibonacci->new;
     my $elem;

     foreach $i ( 1..100 ) {
         $obj = myObject->new( $i );
         $elem = RefElem( $obj );
         $heap->add( $elem );
     }

     while( defined( $elem = $heap->extract_minimum ) ) {
         # assume that myObject object have a method I<printable>
         print "Smallest is ", $elem->val->printable, "\n";
     }

DESCRIPTION
===========

   Heap::Elem::Ref is used to wrap object reference values into an element
that can be managed on a heap.  Each referenced object must have a method
cmp which can compare itself with any of the other objects that have
references on the same heap.  These comparisons must be consistant with
normal arithmetic.  The top of the heap will have the smallest (according
to cmp) element still remaining.  (See Heap/Elem/RefRev,
if you want the heap to always return the largest
element.)

   The details of the Elem interface are described in Heap/Elem.

   The details of using a Heap interface are described in Heap.

AUTHOR
======

   John Macdonald, jmm@elegant.com

SEE ALSO
========

   Heap(3), Heap::Elem(3), Heap::Elem::RefRev(3).

Perl extension for reversed Object Reverence Heap Elements
**********************************************************

NAME
====

   Heap::Elem::RefRev - Perl extension for reversed Object Reverence Heap
Elements

SYNOPSIS
========

     use Heap::Elem::RefRev( RefRElem );
     use Heap::Fibonacci;

     my $heap = Heap::Fibonacci->new;
     my $elem;

     foreach $i ( 1..100 ) {
         $obj = myObject->new( $i );
         $elem = RefRElem( $obj );
         $heap->add( $elem );
     }

     while( defined( $elem = $heap->extract_minimum ) ) {
         # assume that myObject object have a method I<printable>
         print "Largest is ", $elem->val->printable, "\n";
     }

DESCRIPTION
===========

   Heap::Elem::RefRev is used to wrap object reference values into an
element that can be managed on a heap.  Each referenced object must have a
method cmp which can compare itself with any of the other objects that
have references on the same heap.  These comparisons must be consistant
with normal arithmetic.  The top of the heap will have the largest
(according to cmp) element still remaining.  (See Heap/Elem/Ref,
if you want the heap to always return the smallest element.)

   The details of the Elem interface are described in Heap/Elem.

   The details of using a Heap interface are described in Heap.

AUTHOR
======

   John Macdonald, jmm@elegant.com

SEE ALSO
========

   Heap(3), Heap::Elem(3), Heap::Elem::Ref(3).

Perl extension for String Heap Elements
***************************************

NAME
====

   Heap::Elem::Str - Perl extension for String Heap Elements

SYNOPSIS
========

     use Heap::Elem::Str( StrElem );
     use Heap::Fibonacci;

     my $heap = Heap::Fibonacci->new;
     my $elem;

     foreach $i ( 'aa'..'bz' ) {
         $elem = StrElem( $i );
         $heap->add( $elem );
     }

     while( defined( $elem = $heap->extract_minimum ) ) {
         print "Smallest is ", $elem->val, "\n";
     }

DESCRIPTION
===========

   Heap::Elem::Str is used to wrap string values into an element that can
be managed on a heap.  The top of the heap will have the smallest element
still remaining.  (See Heap/Elem/StrRev, if you
want the heap to always return the largest element.)

   The details of the Elem interface are described in Heap/Elem.

   The details of using a Heap interface are described in Heap.

AUTHOR
======

   John Macdonald, jmm@elegant.com

SEE ALSO
========

   Heap(3), Heap::Elem(3), Heap::Elem::StrRev(3).

Perl extension for Reversed String Heap Elements
************************************************

NAME
====

   Heap::Elem::StrRev - Perl extension for Reversed String Heap Elements

SYNOPSIS
========

     use Heap::Elem::StrRev( StrRElem );
     use Heap::Fibonacci;

     my $heap = Heap::Fibonacci->new;
     my $elem;

     foreach $i ( 'aa'..'bz' ) {
         $elem = StrRElem( $i );
         $heap->add( $elem );
     }

     while( defined( $elem = $heap->extract_minimum ) ) {
         print "Largest is ", $elem->val, "\n";
     }

DESCRIPTION
===========

   Heap::Elem::StrRev is used to wrap string values into an element that
can be managed on a heap.  The top of the heap will have the largest
element still remaining.  (See Heap/Elem/Str, if you
want the heap to always return the smallest element.)

   The details of the Elem interface are described in Heap/Elem.

   The details of using a Heap interface are described in Heap.

AUTHOR
======

   John Macdonald, jmm@elegant.com

SEE ALSO
========

   Heap(3), Heap::Elem(3), Heap::Elem::Str(3).

a Perl extension for keeping data partially sorted
**************************************************

NAME
====

   Heap::Fibonacci - a Perl extension for keeping data partially sorted

SYNOPSIS
========

     use Heap::Fibonacci;

     $heap = Heap::Fibonacci->new;
     # see Heap(3) for usage

DESCRIPTION
===========

   Keeps elements in heap order using a linked list of Fibonacci trees.
The heap method of an element is used to store a reference to the node in
the list that refers to the element.

   See Heap, for details on using this module.

AUTHOR
======

   John Macdonald, jmm@elegant.com

COPYRIGHT
=========

   Copyright 1998, O'Reilly & Associates.

   This code is distributed under the sme copyright as perl itself.

SEE ALSO
========

   Heap(3), Heap::Elem(3).

wrap subs with pre- and post-call hooks
***************************************

NAME
====

   Hook::WrapSub - wrap subs with pre- and post-call hooks

SYNOPSIS
========

     use Hook::WrapSub qw( wrap_subs unwrap_subs );

     wrap_subs \&before, 'some_func', 'another_func', \&after;

     unwrap_subs 'some_func';

DESCRIPTION
===========

wrap_subs
---------

   This function enables intercepting a call to any named function;
handlers may be added both before and after the call to the intercepted
function.

   For example:

     wrap_subs \&before, 'some_func', \&after;

   In this case, whenever the sub named 'some_func' is called, the &before
sub is called first, and the &after sub is called afterwards.  These are
both optional.  If you only want to intercept the call beforehand:

     wrap_subs \&before, 'some_func';

   You may pass more than one sub name:

     wrap_subs \&before, 'foo', 'bar', 'baz', \&after;

   and each one will have the same hooks applied.

   The sub names may be qualified.  Any unqualified names are assumed to
reside in the package of the caller.

   The &before sub and the &after sub are both passed the argument list
which is destined for the wrapped sub.  This can be inspected, and even
altered, in the &before sub:

     sub before {
       ref($_[1]) && $_[1] =~ /\bARRAY\b/
         or croak "2nd arg must be an array-ref!";
       @_ or @_ = qw( default values );
       # if no args passed, insert some default values
     }

   The &after sub is also passed this list.  Modifications to it will
(obviously) not be seen by the wrapped sub, but the caller will see the
changes, if it happens to be looking.

   Here's an example that causes a certain method call to be redirected to
a specific object.  (Note, we use splice to change $_[0], because
assigning directly to $_[0] would cause the change to be visible to the
caller, due to the magical aliasing nature of @_.)

     my $handler_object = new MyClass;

     Hook::WrapSub::wrap_subs
       sub { splice @_, 0, 1, $handler_object },
       'MyClass::some_method';

     my $other_object = new MyClass;
     $other_object->some_method;

     # even though the method is invoked on
     # $other_object, it will actually be executed
     # with a 0'th argument = $handler_obj,
     # as arranged by the pre-call hook sub.

Package Variables
-----------------

   There are some Hook::WrapSub package variables defined, which the
&before and &after subs may inspect.

$Hook::WrapSub::name
     This is the fully qualified name of the wrapped sub.

@Hook::WrapSub::caller
     This is a list which strongly resembles the result of a call to the
     built-in function caller; it is provided because calling caller will
     in fact produce confusing results; if your sub is inclined to call
     caller, have it look at this variable instead.

@Hook::WrapSub::result
     This contains the result of the call to the wrapped sub.  It is empty
     in the &before sub.  In the &after sub, it will be empty if the sub
     was called in a void context, it will contain one value if the sub
     was called in a scalar context; otherwise, it may have any number of
     elements.  Note that the &after function is not prevented from
     modifying the contents of this array; any such modifications will be
     seen by the caller!

   This simple example shows how Hook::WrapSub can be used to log certain
subroutine calls:

     sub before {
       print STDERR <<"    EOF";
         About to call $Hook::WrapSub::name( @_ );
         Wantarray=$Hook::WrapSub::caller[5]
       EOF
     }

     sub after {
       print STDERR <<"    EOF";
         Called $Hook::WrapSub::name( @_ );
         Result=( @Hook::WrapSub::result )
       EOF
       @Hook::WrapSub::result
         or @Hook::WrapSub::result = qw( default return );
       # if the sub failed to return something...
     }

   Much more elaborate uses are possible.  Here's one one way it could be
used with database operations:

     my $dbh; # initialized elsewhere.

     wrap_subs
       sub {
         $dbh->checkpoint
       },

     'MyDb::update',
     'MyDb::delete',

     sub {
       # examine result of sub call:
       if ( $Hook::WrapSub::result[0] ) {
         # success
         $dbh->commit;
       }
       else {
         # failure
         $dbh->rollback;
       }
     };

unwrap_subs
-----------

   This removes the most recent wrapping of the named subs.

   NOTE: Any given sub may be wrapped an unlimited number of times.  A
"stack" of the wrappings is maintained internally.  wrap_subs "pushes" a
wrapping, and unwrap_subs "pops".

AUTHOR
======

   jdporter@min.net (John Porter)

COPYRIGHT
=========

   This is free software.  This software may be modified and/or
distributed under the same terms as Perl itself.

Perl extension for managing ht://Dig configuration files
********************************************************

NAME
====

   HtDig::Config - Perl extension for managing ht://Dig configuration files

SYNOPSIS
========

     use HtDig::Config;
     my $htdig = new HtDig::Config('/opt/www/conf/configdig_sites.pl');
     $htdig->autodetect();
     while (my ($site_name, $path) = each %{$htdig->sites()}) {
       print "Site $site_name found at $path\n";
     }
     my $site = $htdig->sites("default");
     #etc.
     #See the HtDig::Site module for information on using the Site object
     #

DESCRIPTION
===========

   HtDig::Config provides an object-oriented interface to the
configuration files for ht://Dig, a popular, open-source content indexing
and searching system.

   ht://Dig allows you to specify a configuration file to use when
beginning an indexing run or doing a search, thus allowing you to maintain
multiple databases of indexed web pages.  The Config object's main job is
to help you keep track of all the site configuration files you have, using
a sort of "registry" to keep track of sites you've registered with
ConfigDig.  The HtDig::Site object works with the Config object to help
you modify and save each site's configuration settings.

METHODS
=======

   *      my $htdig = new HtDig::Config(conf_path=>'/opt/www/conf/configdig_sites.pl');

     Returns a new Config object.  No required parameters.  If you don't
     pass in conf_path, the value for $DEFAULT_CONFIF_LOCATION is used.
     You can change this to your own preference for convenience if you
     wish, with no ill effects.  You can also pass in auto_create=>1 to
     cause a blank file to be created at conf_path, if one doesn't already
     exist.  Dies on failure.

   *      $htdig->save();

     Causes the current Site registry to be written to the file at
     $config_object->{conf_path};

   *      my @site_list = $htdig->sites();

     Returns an array listing the names of all the sites in the Site
     registry.

   *      my $site = $htdig->get_site("default");

     Returns an HtDig::Site object corresponding to the string name passed
     in.  Returns undef on failure, such as when the site name is not
     found in the Site registry.

   *      $htdig->add_site(site_name=>"My Site", conf_path=>"/opt/www/conf/mysite.conf");

     Adds a new site to the registry, giving it the name specified in
     site_name, and using the config file at conf_path.  Returns the Site
     object on success, undef on failure.

   *      $htdig->delete_site(site_name=>'My Site');

     Removes the site specified in site_name from the registry.  The
     config file itself is not removed.

   *      $htdig->autodetect(paths=>['/users/jtillman/confs/', '/users/bob/htdig'], use_env_path=>1);

     Causes the Config object to search the paths specified in paths for
     .conf files, attempting to add each file found to the registry.  If
     use_env_path is specified, the PATH environment variable is used to
     search for the htdig executable and the base htdig directory is
     determined using its location.  Then the [base_location]/conf
     directory is searched for .conf files.

     The method also searches /opt/www/conf and /usr/local/htdig/conf by
     default.

   *      print $htdig->errstr . "\n";

     Returns the most recently generated error.  The Config object doesn't
     bother with error numbers, since they would be arbitrary and
     difficult to track.  This may change if demand is high enough for
     error numbers.

KNOWN ISSUES
============

   * isn't very clever or clean.  Error reporting could be better, and
     some attempt should be made to detect which .conf files really are
     htdig .conf files

   * get_site require attrib=>value convention?  Nearly all the other
     methods do, even delete_site.

AUTHOR
======

   James Tillman <jtillman@bigfoot.com> CPAN PAUSE ID jtillman

SEE ALSO
========

   HtDig::Site.

   perl(1).

Perl interface Ht://Dig docdb and config files
**********************************************

NAME
====

   Htdig::Database - Perl interface Ht://Dig docdb and config files

SYNOPSIS
========

     use Htdig::Database;

     my $config = Htdig::Database::get_config( $config_file )
     	    or die "$0: Can't access $config_file\n";
     my $record = Htdig::Database::parse_docdb( $docdb_record );
     print "URL = $record->{URL}\n";

DESCRIPTION
===========

Exported functions
------------------

   The following functions are provided by Htdig::Database:

     get_config
     parse_docdb
     encode_url
     decode_url

   By default, functions are not exported into the callers namespace, and
you must invoke them using the full package name, e.g.:

     Htdig::Database::getconfig( $config_file );

   To import all available function names, invoke the module with:

     use Htdig::Database qw(:all);

Parsing a config file
---------------------

   `get_config' parses a config file and returns a hash ref that contains
the configuration attributes.  For example:

     my $config = Htdig::Database::get_config( $config_file )
     	or die "$0: Can't access $config_file\n";
     print "start_url = $config->{start_url}\n";

   All values in the hash are scalars, and any items that are intended to
be lists or booleans must be parsed by the calling program.  `get_config'
returns undef if the config file can't be opened, and carps about various
syntax errors.

Parsing a record from the document database
-------------------------------------------

   `parse_docdb' parses a record from the document database and returns a
hash ref.  For example:

     my %docdb;
     tie( %docdb, 'DB_File', $docdb, O_RDONLY, 0, $DB_BTREE ) ||
     	die "$0: Unable to open $docdb: $!";

     while ( my ( $key, $value ) = each %docdb ) {
     	next if $key =~ /^nextDocID/;
         my %rec = Htdig::Database:parse_docdb( $value );
     	print "     URL: $record->{URL}\n";
     	print "HOPCOUNT: $record->{HOPCOUNT}\n";
     }

   URL's in the database are encoded using two attributes from the
configuration file: *common_url_parts* and *url_part_aliases*.
`parse_docdb' does only rudimentary decoding.  It can't handle more than
25 elements in the *common_url_parts* list, and it currently can't handle
*url_part_aliases* at all.

   `get_config' caches the value of *common_url_parts* that's used for
decoding URL's, and should usually be called before `parse_docdb'.

   Compressed data in the HEAD element will be automatically decompressed
if the Compress::Zlib module is available.  If Compress::Zlib is not
installed, compressed data will be silently replaced by the string:

     "Compressed data: Zlib not available"

   If only a single value is needed from the database record, it can be
specified as a second parameter to `parse_docdb', which then returns the
requested value as a scalar.  For example:

     my $url = Htdig::Database:parse_docdb( $value, 'URL' );

Encoding a URL
--------------

     my $encoded_url = Htdig::Database::encode_url( $url );

   This may be useful for computing database keys, since the keys are
encoded URL's.  `get_config' should be called before `encode_url' or
`decode_url' to initialize the value of `common_url_parts'.

Decoding a URL
--------------

     my $url = Htdig::Database::decode_url( $encoded_url );

   This should seldom be necessary, since URL's are normally decoded by
`parse_docdb'.

AUTHOR
======

   Warren Jones <`wjones@halcyon.com'>

BUGS
====

   Only simple cases of URL encoding are handled correctly.  No more than
25 elements are allowed in *common_url_parts*.  The value of
*url_part_aliases* is not used at all.  Someday this module may implement
the same URL encoding logic found in `HtWordCodec.cc', but a better
solution might be to provide an XSUB interface to the C++ functions.

   This module works with ht://Dig 3.1.4.  It probably works with 3.1.5,
though this hasn't been tested.  Because of changes in the database
format, it *will not work* with version 3.2.

Perl extension for managing a single ht://Dig configuration
***********************************************************

NAME
====

   HtDig::Site - Perl extension for managing a single ht://Dig
configuration

SYNOPSIS
========

     use HtDig::Site;
     $site = new HtDig::Site(conf_path=>"/opt/www/conf/htdig.conf");
     $site->setting("maintainer", "jtillman@bigfoot.com");
     $site->save();
     $site->dig(verbose=>3);

DESCRIPTION
===========

   HtDig::Site provides an object for manipulating configuration files for
ht://Dig, a popular open source content indexing and searching system.
The Site object allows you to open a configuration file, modify settings
in it, including custom settings that don't directly relate to ht://Dig
executibles, and also allows you to perform database operations such as
site index runs, database merges, and fuzzy index creation.

METHODS
=======

   *      $site = new HtDig::Site(conf_path=>"/opt/www/conf/htdig.conf", trace_lvl=>1, site_name=>"Default");

     new creates a new Site object and returns it.  The only required
     parameter is conf_path.  auto_create allows the object to create the
     file specified in conf_path if it doesn't already exist.  trace_lvl
     is mainly for debugging problems, and site_name is really only meant
     to be used by the Config object, which provides you with named access
     to registered configuration files.  Wouldn't you rather be able to
     use the name "My Site", instead of "/opt/www/conf/htdig.conf"?
     That's what Config does for you.  But there's nothing stopping you
     from naming a Site object yourself when you create it explicitly; the
     name just won't persist beyond the current session.

   *      $site->setting("exclude_urls", ["http://localhost/cgi-bin", "http://localhost/images"]);
          @exlude_urls = $site->setting("exclude_urls");

     Allows you to modify or retrieve a setting in the configuration file.
     You must save the file before it will be persisted.

     As illustrated in the example, if the datatype of the setting you are
     attempting to modify is a "string list", you can pass in an array
     reference.  Otherwise, you can pass in a space separated list of
     values, and the Site object will convert it to an array reference by
     splitting on the white space.  The array reference is for internal
     representation only, and will be converted to a space separated list
     when the config file is written to disk.

   *      $site->refresh();

     When a configuration file is first loaded from disk (or saved for the
     first time), its modification time is stored in memory and will be
     compared when the save method is called.  If you suspect someone
     might have touched the file on disk and wish to sync up with its
     current version, you can use the refresh method.  Any changes since
     the last save will be lost.

   *      $site->save();
          $site->save(save_to=>'/opt/www/conf/htdig2.conf');

     Saves the in-memory settings to disk.  If the optional save_to
     parameter is provided, the file is written to that path, otherwise,
     it's written to the original conf_path that was provided when the
     object was created.

   *      $site->dig();

     Initiates a site indexing run.

   *      $site->generate_fuzzy_index();

     Generates a fuzzy_index of the type specified in the parameter type.

   *      $site->merge(merge_site=>"/opt/www/conf/othersite.conf",not_words=>1, not_documents=>0, work_files=>1);

     Performs a merge using htmerge, merging the configuration file
     specified in merge_site into the current Site's database.  not_words,
     not_documents, and work_files correspond to the htmerge command line
     options -w, -d, and -a, respectively.

   *      my @stock_settings = keys %{$site->datatypes};

     Returns a hash that describes ht://Dig configuration file setting
     datatypes.  These are documented at
     http://www.htdig.org/confindex.html.  The example uses the hash to
     get a list of stock settings that htdig recognizes.

     The hash structure looks something like this:

          {
           setting_name => 'DATATYPE'
          }

     ...where setting_name is the name of the configuration file setting,
     such as "maintainer", and DATATYPE is the documented datatype of the
     setting.  There are four currently documented datatypes: string,
     string list, number, and boolean.

     This feature is probably not very useful for the perl scripter using
     the Site object, but it is provided just in case some input
     validation needs to be done, or some options need to be presented to
     the user.  It's a good way to present a list of the stock settings
     that can appear in a configuration file.

   *      print $site->errstr . "\n";

     Returns the most recently generated error.  The Site object doesn't
     bother with error numbers, since they would be arbitrary and
     difficult to track.  This may change if demand is high enough for
     error numbers.

KNOWN ISSUES
============

   * Timed digs are broken.  Needs work.

AUTHOR
======

   James Tillman <jtillman@bigfoot.com> CPAN PAUSE ID: jtillman

SEE ALSO
========

   HtDig::Config.

   perl(1).

Communicate with a HyperWave server
***********************************

NAME
====

   HyperWave::CSP - Communicate with a HyperWave server

SYNOPSIS
========

     use HyperWave::CSP;

     $server = HyperWave::CSP->New("my.hyperwave.server");
     $server->quit;

DESCRIPTION
===========

   `HyperWave' is a class implementing a simple HyperWave client in Perl.

CONSTRUCTOR
===========

new ( [ HOST [, PORT [, USERNAME [, PASSWORD [, ENCRYPT [, LANGUAGE ] ] ] ] ] ] )
     This is the constructor for a new HyperWave object. `HOST' is the
     name of the remote host to which a HyperWave connection is required.
     If not given the environment variables `HWHOST' and then `HGHOST' are
     checked, and if a host is not found then `localhost' is used.

     `PORT' is the HyperWave port to connect to, it defaults to the
     environment variable `HWPORT', then `HGPORT' and then to the standard
     port 418 if nothing else is found.

     USERNAME and PASSWORD are the HyperWave username and password, they
     default to anonymous.  `ENCRYPT' will eventually allow you to pass
     the password in in encrypted form rather than plaintext, but is not
     yet implemented.

     `LANGUGAE' also is not yet used, and defaults to the value of the
     environment variable `HWLANGUAGE' and then to English.

     The constructor returns the open socket, or undef if an error has
     been encountered.

METHODS
=======

   Unless otherwise stated all methods return either a *true* or false
value, with *true* meaning that the operation was a success.  When a
method states that it returns a value, failure will be returned as undef
or an empty list.

command_stat ( )
     Returns string containing various statistics for the server.

command_ftstat ( )
     Returns string containing various statistics for the server.

command_dcstat ( )
     Returns string containing various statistics for the server.

command_who ( )
     Returns string containing current users for the server.

get_objnum_by_name ( NAME )
     Returns object number for the document with NAME as an attribute, or
     false on error.

get_url ( OBJNUM )
     Returns a guess at a URL that might work for the document OBJNUM to be
     retreived via the HyperWave HTTP interface.  Note that it is ONLY a
     guess.  For one thing, it depends on the HyperWave server running a
     web interface on the default HTTP port.

get_attributes ( OBJNUM )
     Returns a string containing the attributes for OBJNUM.  The string is
     in form `key1=value1\nkey2=value2\n...'.

get_attributes_hash ( OBJNUM )
     Like get_attributes() except that the attributes are returned as a
     hash.

get_text ( OBJNUM )
     Returns body text for the objnum passed.  This usually means HTML
     sans anchors in practical terms.

get_html ( OBJNUM )
     Returns HTML text, including anchors, for the objnum passed.

exec_cgi ( OBJNUM )
     Returns output of the CGI, for the objnum passed.  Depends on the CGI
     script not requiring input.

insert_attribute ( OBJNUM, NAME, VALUE )
     Adds an attribute to the given objnum.  Note that HyperWave allows
     multiple attributes of the same name, so if you add an attribute that
     already exists you'll end up with two.  Use change_attribute if you
     want to overwrite the old one.

remove_attribute ( OBJNUM, NAME, VALUE )
     Removes an attribute to the given objnum.  Note that you DO need to
     know the old value because HyperWave allows multiple attributes with
     the same value.

change_attribute ( OBJNUM, NAME, OLD_VALUE, NEW_VALUE )
     Alters an attribute to the given objnum (NB: needs to know old value).

get_children ( OBJNUM )
     Returns objnums for all the children in the objnum passed.  If the
     object was a leaf node (ie: no children) you'll get a 0 back.

get_parents ( OBJNUM )
     Returns objnums for all the parents in the objnum passed.  If the
     object had no parents (it was the root collection) you'll get a 0
     back.

get_anchors ( OBJNUM )
     Returns objnums for all the anchors in the document passed.

insert_object ( OBJRECORD );
     Inserts an object on the HyperWave server.  Returns object ID of the
     new object.

     `OBJRECORD' should be in the form
     `Attribute=AttributeValue\nAttr2=Value2' and must contain certain
     parameters such as the parent object, name, document type, etc.  It is
     suggested that you use one of the other insert_* commands as they
     provide a friendlier interface.  This command is provided primarily
     for completeness.

insert_collection ( PARENT_OBJNUM, NAME [, OTHER_PARAMS ] )
     Inserts a collection on the HyperWave server.  Returns object ID of
     the new collection.

     `PARENT_OBJNUM' is the object number (probably returned from
     get_objnum_by_name() of the collection to insert this collection into.
     NAME is the name attribute, this will become the apparent URL to
     somebody using the WaveMaster interface.

     `OTHER_PARAMS' should be in the form
     `Attribute=AttributeValue\nAttr2=Value2' and so on.  You might
     particularly want to set a Title for the collection.

insert_image ( OBJNUM, PARENT, NAME )
     Adds a new picture.  NOT YET IMPLEMENTED.

insert_text ( OBJNUM, PARENT )
     Adds a new text object (no anchors).  NOT YET IMPLEMENTED.

insert_html ( OBJNUM )
     Adds a new html object (we parse the anchors).  NOT YET IMPLEMENTED.

error ( )
     Returns a human-readable string describing the previous server error.

server_error_message ( )
     Returns a human-readable string describing the previous server error.

SEE ALSO
========

AUTHOR
======

   Bek Oberin <gossamer@tertius.net.au>

COPYRIGHT
=========

   Copyright (c) 1998 Bek Oberin.  All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

IANA Character Set Registry names and Unicode::Map8 conversion scheme names
***************************************************************************

NAME
====

   I18N::Charset - IANA Character Set Registry names and Unicode::Map8
conversion scheme names

SYNOPSIS
========

     use I18N::Charset;

     $sCharset = iana_charset_name('WinCyrillic');
     # $sCharset is now 'windows-1251'
     $sCharset = map8_charset_name('windows-1251');
     # $sCharset is now 'cp1251' which can be passed to Unicode::Map8->new()
     $sCharset = umap_charset_name('Adobe DingBats');  # $sCharset gets ''
     # $sCharset is now 'ADOBE-DINGBATS' which can be passed to Unicode::Map->new()

     I18N::Charset::add_iana_alias('my-japanese' => 'iso-2022-jp');
     I18N::Charset::add_map8_alias('my-arabic' => 'arabic7');
     I18N::Charset::add_umap_alias('my-hebrew' => 'ISO-8859-8');

DESCRIPTION
===========

   The `I18N::Charset' module provides access to the IANA Character Set
Registry names for identifying character encoding schemes.  It also
provides a mapping to the character set names used by the Unicode::Map8
and Unicode::Map modules.

   So, for example, if you get an HTML document with a META CHARSET="..."
tag, you can fairly quickly determine what Unicode:: module can be used to
convert it to Unicode.

   If you don't have the module Unicode::Map8 installed, the map8_
functions will always return undef; similarly for Unicode::Map and the
umap_ functions.

CONVERSION ROUTINES
===================

   There are three conversion routines: iana_charset_name(),
map8_charset_name(), and umap_charset_name().

iana_charset_name()
     This function takes a string containing the name of a character set
     and returns a string which contains the official IANA name of the
     character set identified. If no valid character set name can be
     identified, then undef will be returned.  The case and punctuation
     within the string are not important.

          $sCharset = iana_charset_name('WinCyrillic');

map8_charset_name()
     This function takes a string containing the name of a character set
     (in almost any format) and returns a string which contains a name for
     the character set that can be used to designate a Unicode::Map8
     character code map. If no valid character set name can be identified,
     then undef will be returned.  The case and punctuation within the
     argument string are not important.

          $sCharset = map8_charset_name('windows-1251');

umap_charset_name()
     This function takes a string containing the name of a character set
     (in almost any format) and returns a string which contains a name for
     the character set that can be used to designate a Unicode::Map
     character code mapping. If no valid character set name can be
     identified, then undef will be returned.  The case and punctuation
     within the argument string are not important.

          $sCharset = umap_charset_name('hebrew');

QUERY ROUTINES
==============

   There is one function which can be used to obtain a list of all
IANA-registered character set names.

`all_iana_charset_names()'
     Returns a list of all registered IANA character set names.  The names
     are not in any particular order.

CHARACTER SET NAME ALIASING
===========================

   This module supports three semi-private routines for specifying
character set name aliases.

add_iana_alias()
     This function takes two strings: a new alias, and a target IANA
     Character Set Name (or another alias).  It defines the new alias to
     refer to that character set name (or to the character set name to
     which the second alias refers).

     Returns the target character set name of the successfully installed
     alias.  Returns 'undef' if the target character set name is not
     registered.  Returns 'undef' if the target character set name of the
     second alias is not registered.

          I18N::Charset::add_iana_alias('my-alias1' => 'Shift_JIS');

     With this code, "my-alias1" becomes an alias for the existing IANA
     character set name 'Shift_JIS'.

          I18N::Charset::add_iana_alias('my-alias2' => 'sjis');

     With this code, "my-alias2" becomes an alias for the IANA character
     set name referred to by the existing alias 'sjis' (which happens to
     be 'Shift_JIS').

add_map8_alias()
     This function takes two strings: a new alias, and a target
     Unicode::Map8 Character Set Name (or an exising alias to a Map8 name).
     It defines the new alias to refer to that mapping name (or to the
     mapping name to which the second alias refers).

     If the first argument is a registered IANA character set name, then
     all aliases of that IANA character set name will end up pointing to
     the target Map8 mapping name.

     Returns the target mapping name of the successfully installed alias.
     Returns 'undef' if the target mapping name is not registered.
     Returns 'undef' if the target mapping name of the second alias is not
     registered.

          I18N::Charset::add_map8_alias('normal' => 'ANSI_X3.4-1968');

     With the above statement, "normal" becomes an alias for the existing
     Unicode::Map8 mapping name 'ANSI_X3.4-1968'.

          I18N::Charset::add_map8_alias('normal' => 'US-ASCII');

     With the above statement, "normal" becomes an alias for the existing
     Unicode::Map mapping name 'ANSI_X3.4-1968' (which is what "US-ASCII"
     is an alias for).

          I18N::Charset::add_map8_alias('IBM297' => 'EBCDIC-CA-FR');

     With the above statement, "IBM297" becomes an alias for the existing
     Unicode::Map mapping name 'EBCDIC-CA-FR'.  As a side effect, all the
     aliases for 'IBM297' (i.e. 'cp297' and 'ebcdic-cp-fr') also become
     aliases for 'EBCDIC-CA-FR'.

add_umap_alias()
     This function works identically to add_map8_alias() above, but
     operates on Unicode::Map encoding tables.

EXAMPLES
========

KNOWN BUGS AND LIMITATIONS
==========================

   * There could probably be many more aliases added (for convenience) to
     all the IANA names.  If you have some specific recommendations,
     please email the author!

   * The only character set names which have a corresponding mapping in the
     Unicode::Map8 module are the character sets that Unicode::Map8 can
     convert.

     Similarly, the only character set names which have a corresponding
     mapping in the Unicode::Map module are the character sets that
     Unicode::Map can convert.

   * In the current implementation, all tables are read in and initialized
     when the module is loaded, and then held in memory until the program
     exits.  A "lazy" implementation (or a less-portable tied hash) might
     lead to a shorter startup time.  Suggestions, patches, comments are
     always welcome!

SEE ALSO
========

Unicode::Map
     Convert strings from various multi-byte character encodings to and
     from Unicode.

Unicode::Map8
     Convert strings from various 8-bit character encodings to and from
     Unicode.

Jcode
     Convert strings among various Japanese character encodings and
     Unicode.

Unicode::MapUTF8
     A wrapper around all three of these character set conversion
     distributions.

AUTHOR
======

   Martin Thurn <MartinThurn@iname.com>

COPYRIGHT
=========

   Copyright (c) 1998-2001 TASC, Inc.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

compare 8-bit scalar data according to the current locale
*********************************************************

NAME
====

   I18N::Collate - compare 8-bit scalar data according to the current
locale

     ***

     WARNING: starting from the Perl version 5.003_06
     the I18N::Collate interface for comparing 8-bit scalar data
     according to the current locale

     HAS BEEN DEPRECATED

     That is, please do not use it anymore for any new applications
     and please migrate the old applications away from it because its
     functionality was integrated into the Perl core language in the
     release 5.003_06.

     See the perllocale manual page for further information.

     ***

SYNOPSIS
========

     use I18N::Collate;
     setlocale(LC_COLLATE, 'locale-of-your-choice');
     $s1 = new I18N::Collate "scalar_data_1";
     $s2 = new I18N::Collate "scalar_data_2";

DESCRIPTION
===========

   This module provides you with objects that will collate according to
your national character set, provided that the POSIX setlocale() function
is supported on your system.

   You can compare $s1 and $s2 above with

     $s1 le $s2

   to extract the data itself, you'll need a dereference: $$s1

   This module uses POSIX::setlocale(). The basic collation conversion is
done by strxfrm() which terminates at NUL characters being a decent C
routine.  collate_xfrm() handles embedded NUL characters gracefully.

   The available locales depend on your operating system; try whether
`locale -a' shows them or man pages for "locale" or "nlsinfo" or the
direct approach `ls /usr/lib/nls/loc' or `ls /usr/lib/nls' or `ls
/usr/lib/locale'.  Not all the locales that your vendor supports are
necessarily installed: please consult your operating system's
documentation and possibly your local system administration.  The locale
names are probably something like `xx_XX.(ISO)?8859-N' or
`xx_XX.(ISO)?8859N', for example `fr_CH.ISO8859-1' is the Swiss (CH)
variant of French (fr), ISO Latin (8859) 1 (-1) which is the Western
European character set.

functions for dealing with RFC1766-style language tags
******************************************************

NAME
====

   I18N::LangTags - functions for dealing with RFC1766-style language tags

SYNOPSIS
========

     use I18N::LangTags qw(is_language_tag same_language_tag
                           extract_language_tags super_languages
                           similarity_language_tag is_dialect_of
                           locale2language_tag alternate_language_tags
                           encode_language_tag
                          );

   ...or whatever of those functions you want to import.  Those are all
the exportable functions - you're free to import only some, or none at
all.  By default, none are imported.

   If you don't import any of these functions, assume a `&I18N::LangTags::'
in front of all the function names in the following examples.

DESCRIPTION
===========

   Language tags are a formalism, described in RFC 1766, for declaring
what language form (language and possibly dialect) a given chunk of
information is in.

   This library provides functions for common tasks involving language
tags as they are needed in a variety of protocols and applications.

   Please see the "See Also" references for a thorough explanation of how
to correctly use language tags.

   * the function is_language_tag($lang1)

     Returns true iff $lang1 is a formally valid language tag.

          is_language_tag("fr")            is TRUE
          is_language_tag("x-jicarilla")   is FALSE
              (Subtags can be 8 chars long at most -- 'jicarilla' is 9)

          is_language_tag("i-Klikitat")    is TRUE
              (True without regard to the fact noone has actually
               registered Klikitat -- it's a formally valid tag)

          is_language_tag("fr-patois")     is TRUE
              (Formally valid -- altho descriptively weak!)

          is_language_tag("Spanish")       is FALSE
          is_language_tag("french-patois") is FALSE
              (No good -- first subtag has to match
               /^([xXiI]|[a-zA-Z]{2})$/ -- see RFC1766)

   * the function extract_language_tags($whatever)

     Returns a list of whatever looks like formally valid language tags in
     $whatever.  Not very smart, so don't get too creative with what you
     want to feed it.

          extract_language_tags("fr, fr-ca, i-mingo")
            returns:   ('fr', 'fr-ca', 'i-mingo')

          extract_language_tags("It's like this: I'm in fr -- French!")
            returns:   ('It', 'in', 'fr')
          (So don't just feed it any old thing.)

   * the function same_language_tag($lang1, $lang2)

     Returns true iff $lang1 and $lang2 are acceptable variant tags
     representing the same language-form.

          same_language_tag('x-kadara', 'i-kadara')  is TRUE
             (The x/i- alternation doesn't matter)
          same_language_tag('X-KADARA', 'i-kadara')  is TRUE
             (...and neither does case)
          same_language_tag('en',       'en-US')     is FALSE
             (all-English is not the SAME as US English)
          same_language_tag('x-kadara', 'x-kadar')   is FALSE
             (these are totally unrelated tags)

     `same_language_tag' works by just seeing whether
     `encode_language_tag($lang1)' is the same as
     `encode_language_tag($lang2)'.

     (Yes, I know this function is named a bit oddly.  Call it historic
     reasons.)

   * the function similarity_language_tag($lang1, $lang2)

     Returns an integer representing the degree of similarity between tags
     $lang1 and $lang2 (the order of which does not matter), where
     similarity is the number of common elements on the left, without
     regard to case and to x/i- alternation.

          similarity_language_tag('fr', 'fr-ca')           is 1
             (one element in common)
          similarity_language_tag('fr-ca', 'fr-FR')        is 1
             (one element in common)

          similarity_language_tag('fr-CA-joual',
                                  'fr-CA-PEI')             is 2
          similarity_language_tag('fr-CA-joual', 'fr-CA')  is 2
             (two elements in common)

          similarity_language_tag('x-kadara', 'i-kadara')  is 1
             (x/i- doesn't matter)

          similarity_language_tag('en',       'x-kadar')   is 0
          similarity_language_tag('x-kadara', 'x-kadar')   is 0
             (unrelated tags -- no similarity)

          similarity_language_tag('i-cree-syllabic',
                                  'i-cherokee-syllabic')   is 0
             (no B<leftmost> elements in common!)

   * the function is_dialect_of($lang1, $lang2)

     Returns true iff language tag $lang1 represents a subdialect of
     language tag $lang2.

     *Get the order right!  It doesn't work the other way around!*

          is_dialect_of('en-US', 'en')            is TRUE
            (American English IS a dialect of all-English)

          is_dialect_of('fr-CA-joual', 'fr-CA')   is TRUE
          is_dialect_of('fr-CA-joual', 'fr')      is TRUE
            (Joual is a dialect of (a dialect of) French)

          is_dialect_of('en', 'en-US')            is FALSE
            (all-English is a NOT dialect of American English)

          is_dialect_of('fr', 'en-CA')            is FALSE

          is_dialect_of('en',    'en'   )            is TRUE
          is_dialect_of('en-US', 'en-US')            is TRUE
            (B<Note:> these are degenerate cases)

          is_dialect_of('i-mingo-tom', 'x-Mingo') is TRUE
            (the x/i thing doesn't matter, nor does case)

   * the function super_languages($lang1)

     Returns a list of language tags that are superordinate tags to $lang1
     - it gets this by removing subtags from the end of $lang1 until
     nothing (or just "i" or "x") is left.

          super_languages("fr-CA-joual")  is  ("fr-CA", "fr")

          super_languages("en-AU")  is  ("en")

          super_languages("en")  is  empty-list, ()

          super_languages("i-cherokee")  is  empty-list, ()
           ...not ("i"), which would be illegal as well as pointless.

     If $lang1 is not a valid language tag, returns empty-list in a list
     context, undef in a scalar context.

     A notable and rather unavoidable problem with this method:
     "x-mingo-tom" has an "x" because the whole tag isn't an
     IANA-registered tag - but super_languages('x-mingo-tom') is
     ('x-mingo') - which isn't really right, since 'i-mingo' is
     registered.  But this module has no way of knowing that.  (But note
     that same_language_tag('x-mingo', 'i-mingo') is TRUE.)

     More importantly, you assume *at your peril* that superordinates of
     $lang1 are mutually intelligible with $lang1.  Consider this
     carefully.

   * the function locale2language_tag($locale_identifier)

     This takes a locale name (like "en", "en_US", or "en_US.ISO8859-1")
     and maps it to a language tag.  If it's not mappable (as with,
     notably, "C" and "POSIX"), this returns empty-list in a list context,
     or undef in a scalar context.

          locale2language_tag("en") is "en"

          locale2language_tag("en_US") is "en-US"

          locale2language_tag("en_US.ISO8859-1") is "en-US"

          locale2language_tag("C") is undef or ()

          locale2language_tag("POSIX") is undef or ()

          locale2language_tag("POSIX") is undef or ()

     I'm not totally sure that locale names map satisfactorily to language
     tags.  Think REAL hard about how you use this.  YOU HAVE BEEN WARNED.

   * the function encode_language_tag($lang1)

     This function, if given a language tag, returns an encoding of it such
     that:

     * tags representing different languages never get the same encoding.

     * tags representing the same language always get the same encoding.

     * an encoding of a formally valid language tag always is a string
     value that is defined, has length, and is true if considered as a
     boolean.

     Note that the encoding itself is not a formally valid language tag.
     Note also that you cannot, currently, go from an encoding back to a
     language tag that it's an encoding of.

     Note also that you must consider the encoded value as atomic; i.e.,
     you should not consider it as anything but an opaque, unanalysable
     string value.  (The internals of the encoding method may change in
     future versions, as the language tagging standard changes over time.)

     `encode_language_tag' returns undef if given anything other than a
     formally valid language tag.

     The reason `encode_language_tag' exists is because different language
     tags may represent the same language; this is normally treatable with
     `same_language_tag', but consider this situation:

     You have a data file that expresses greetings in different languages.
     Its format is "[language tag]=[how to say 'Hello']", like:

          en-US=Hiho
          fr=Bonjour
          i-mingo=Hau'

     And suppose you write a program that reads that file and then runs as
     a daemon, answering client requests that specify a language tag and
     then expect the string that says how to greet in that language.  So an
     interaction looks like:

          greeting-client asks:    fr
          greeting-server answers: Bonjour

     So far so good.  But suppose the way you're implementing this is:

          my %greetings;
          die unless open(IN, "<in.dat");
          while(<IN>) {
            chomp;
            next unless /^([^=]+)=(.+)/s;
            my($lang, $expr) = ($1, $2);
            $greetings{$lang} = $expr;
          }
          close(IN);

     at which point %greetings has the contents:

          "en-US"   => "Hiho"
          "fr"      => "Bonjour"
          "i-mingo" => "Hau'"

     And suppose then that you answer client requests for language $wanted
     by just looking up $greetings{$wanted}.

     If the client asks for "fr", that will look up successfully in
     %greetings, to the value "Bonjour".  And if the client asks for
     "i-mingo", that will look up successfully in %greetings, to the value
     "Hau'".

     But if the client asks for "i-Mingo" or "x-mingo", or "Fr", then the
     lookup in %greetings fails.  That's the Wrong Thing.

     You could instead do lookups on $wanted with:

          use I18N::LangTags qw(same_language_tag);
          my $repsonse = '';
          foreach my $l2 (keys %greetings) {
            if(same_language_tag($wanted, $l2)) {
              $response = $greetings{$l2};
              last;
            }
          }

     But that's rather inefficient.  A better way to do it is to start your
     program with:

          use I18N::LangTags qw(encode_language_tag);
          my %greetings;
          die unless open(IN, "<in.dat");
          while(<IN>) {
            chomp;
            next unless /^([^=]+)=(.+)/s;
            my($lang, $expr) = ($1, $2);
            $greetings{
                        encode_language_tag($lang)
                      } = $expr;
          }
          close(IN);

     and then just answer client requests for language $wanted by just
     looking up

          $greetings{encode_language_tag($wanted)}

     And that does the Right Thing.

   * the function alternate_language_tags($lang1)

     This function, if given a language tag, returns all language tags that
     are alternate forms of this language tag.  (There is little
     alternation in the current language tagging formalism, but extensions
     to the formalism are under consideration which could add a great deal
     of alternation.)

     Examples from the current formalism:

          alternate_language_tags('en')           is   ()
          alternate_language_tags('x-mingo-tom')  is   ('i-mingo-tom')
          alternate_language_tags('x-klikitat')   is   ('i-klikitat')
          alternate_language_tags('i-klikitat')   is   ('x-klikitat')

     This function returns undef if given anything other than a formally
     valid language tag.

NOTE ABOUT FUTURE VERSIONS
==========================

   I *will* need to change this library *when* RFC1766 is superceded.
Currently (1999-03-06) there are plans to do just that, by adding a whole
series of *three*-letter language codes like "nav" for Navajo - which
would currently be a formally invalid language code.  Be sure to check
CPAN for updates of this library.

ABOUT LOWERCASING
=================

   I've considered making all the above functions that output language
tags return all those tags strictly in lowercase.  Having all your
language tags in lowercase does make some things easier.  But you might as
well just lowercase as you like, or call `encode_language_tag($lang1)'
where appropriate.

ABOUT UNICODE PLAINTEXT LANGUAGE TAGS
=====================================

   In some future version of I18N::LangTags, I plan to include support for
RFC2482-style language tags - which are basically just normal language
tags with their ASCII characters shifted into Plane 14.

SEE ALSO
========

   * RFC 1766, `ftp://ftp.isi.edu/in-notes/rfc1766.txt', "Tags for the
Identification of Languages".

   * RFC 2277, `ftp://ftp.isi.edu/in-notes/rfc2277.txt', "IETF Policy on
Character Sets and Languages".

   * RFC 2231, `ftp://ftp.isi.edu/in-notes/rfc2231.txt', "MIME Parameter
Value and Encoded Word Extensions: Character Sets, Languages, and
Continuations".

   * RFC 2482, `ftp://ftp.isi.edu/in-notes/rfc2482.txt', "Language Tagging
in Unicode Plain Text".

   * Locale::Codes, in `http://www.perl.com/CPAN/modules/by-module/Locale/'

   * ISO 639, "Code for the representation of names of languages",
`http://www.indigo.ie/egt/standards/iso639/iso639-1-en.html'

   * The IANA list of registered languages (hopefully up-to-date),
`ftp://ftp.isi.edu/in-notes/iana/assignments/languages/'

COPYRIGHT
=========

   Copyright (c) 1998,1999,2000 Sean M. Burke. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Sean M. Burke `sburke@cpan.org'

Perl extension for IETF IDN WG ACE character conversions
********************************************************

NAME
====

   IETF::ACE - Perl extension for IETF IDN WG ACE character conversions

SYNOPSIS
========

     use IETF::ACE qw / ... /;

DESCRIPTION
===========

   IETF::ACE - Perl extension for IETF IDN WG ACE character conversions

     Subroutines

     UCS4toName
     UCS4toUPlus
     UTF5toUCS4
     GetCharFromUTF5
     UCS4toRACE
     RACEtoUCS4
     UCS4toLACE
     LACEtoUCS4
     Base32Encode
     Base32Decode
     CheckForSTD13Name
     CheckForBadSurrogates
     HexOut
     DebugOn
     DebugOff
     DebugOut

     The formats are:

     utf8
     utf16
     ucs4
     utf5      from draft-jseng-utf5-01.txt
     race      draft-ietf-idn-race-03.txt
     lace      draft-ietf-idn-lace-01.txt
     name      The character names; output only
     u+        The character hex values in U+ notation; output only

   Sample Program

     use strict;
     use diagnostics;

     use Unicode::String qw / utf8 /;
     use IETF::ACE qw / &UCS4toRACE /;

     my $TheIn="Ã¡bcde"; # .com

     my $TheUCS4 = utf8($TheIn)->ucs4;

     my $TheOut = &UCS4toRACE($TheUCS4);

     print <<EOD;
     Latin1 Input = $TheIn.com
     RACE Output = $TheOut.com
     EOD

EXPORT
------

   None by default.

AUTHOR
======

   Paul Hoffman, Internet Mail Consortium phoffman@mail.imc.org

   James Briggs, ActiveMessage, Inc.  james@rf.net

SEE ALSO
========

   See Perl (perl.info).

Perl module for basic IMAP server administration
************************************************

NAME
====

   IMAP::Admin - Perl module for basic IMAP server administration

SYNOPSIS
========

     use IMAP::Admin;

     $imap = IMAP::Admin->new('Server' => 'name.of.server.com',
     			   'Login' => 'login_of_imap_administrator',
     			   'Password' => 'password_of_imap_adminstrator',
     			   'Port' => port# (143 is default),
     			   'Separator' => ".", # default is a period
     			   'SSL' => 1, # off by default
     			   # and any of the SSL_ options from IO::Socket::SSL
     			   );

     $err = $imap->create("user.bob");
     if ($err != 0) {
       print "$imap->{'Error'}\n";
     }
     if ($err != 0) {
         print $imap->error;
     }
     $err = $imap->create("user.bob", "green");
     $err = $imap->delete("user.bob");
     $err = $imap->h_delete("user.bob");

     $err = $imap->subscribe("user.bob");
     $err = $imap->unsubscribe("user.bob");

     $err = $imap->rename("bboard", "newbboard");

     @quota = $imap->get_quotaroot("user.bob");
     @quota = $imap->get_quota("user.bob");
     $err = $imap->set_quota("user.bob", 10000);

     @acl = $imap->get_acl("user.bob");
     $err = $imap->set_acl("user.bob", "admin", "lrswipdca", "joe", "lrs");
     $err = $imap->delete_acl("user.bob", "joe", "admin");

     @list = $imap->list("user.bob");
     @list = $imap->list("user.b*");

     $imap->{'Capability'} # this contains the Capabilities reply from the IMAP server

     $imap->close; # close open imap connection

DESCRIPTION
===========

   IMAP::Admin provides basic IMAP server adminstration.  It provides
functions for creating and deleting mailboxes and setting various
information such as quotas and access rights.

   It's interface should, in theory, work with any RFC compliant IMAP
server, but I currently have only tested it against Carnegie Mellon
University's Cyrus IMAP and Mirapoint's IMAP servers.  It does a
CAPABILITY check for specific extensions to see if they are supported.

   Operationally it opens a socket connection to the IMAP server and logs
in with the supplied login and password.  You then can call any of the
functions to perform their associated operation.

   Separator on the new call is the hiearchical separator used by the imap
server.  It is defaulted to a period ("/" might be another popular one).

   SSL on the new call will attempt to make an SSL connection to the imap
server.  It does not fallback to a regular connection if it fails.  It is
off by default.  IO::Socket::SSL requires a ca certificate, a client
certificate, and a client private key. By default these are in
current_directory/certs, respectively named ca-cert.pem, client-cert.pem,
and client-key.pem.  The location of this can be overridden by setting
SSL_ca_file, SSL_cert_file, and SSL_key_file (you'll probably want to also
set SSL_ca_path).

   I generated my ca cert and ca key with openssl:  openssl req -x509
-newkey rsa:1024 -keyout ca-key.pem -out ca-cert.pem

   I generated my client key and cert with openssl:  openssl req -new
-newkey rsa:1024 -keyout client-key.pem -out req.pem -nodes  openssl x509
-CA ca-cert.pem -CAkey ca-key.pem -req -in req.pem -out client-cert.pem
-addtrust clientAuth -days 600

   Setting up SSL Cyrus IMAP v 2.x (completely unofficial, but it worked
for me)  add these to your /etc/imapd.conf (remember to change
/usr/local/cyrus/tls to wherever yours is)   tls_ca_path:
/usr/local/cyrus/tls   tls_ca_file: /usr/local/cyrus/tls/ca-cert.pem
tls_key_file: /usr/local/cyrus/tls/serv-key.pem   tls_cert_file:
/usr/local/cyrus/tls/serv-cert.pem

   For my server key I used a self signed certificate:  openssl req -x509
-newkey rsa:1024 -keyout serv-key.pem -out serv-cert.pem -nodes
-extensions usr_cert (in openssl.cnf I have nsCertType set to server)

   I also added this to my /etc/cyrus.conf, it shouldn't strictly be
necessary as clients that are RFC2595 compliant can issue a STARTTLS to
initiate the secure layer, but currently IMAP::Admin doesn't issue this
command (in SERVICES section):   imap2  cmd="imapd -s" listen="simap"
prefork=0

   where simap in /etc/services is:   simap  993/tcp   # IMAP over SSL

MAILBOX FUNCTIONS
-----------------

   RFC2060 commands.  These should work with any RFC2060 compliant IMAP
mail servers.

   create makes new mailboxes.  Cyrus IMAP, for normal mailboxes, has the
user. prefix.  create returns a 0 on success or a 1 on failure.  An error
message is placed in the object->{'Error'} variable on failure. create
takes an optional second argument that is the partition to create the
mailbox in (I don't know if partition is rfc or not, but it is supported
by Cyrus IMAP and Mirapoint).

   delete destroys mailboxes.  The action delete takes varies from server
to server depending on it's implementation.  On some servers this is a
hierarchical delete and on others this will delete only the mailbox
specified and only if it has no subfolders that are marked \Noselect.  If
you wish to insure a hierarchical delete use the h_delete command as it
deletes starting with the subfolders and back up to the specified mailbox.
delete returns a 0 on success or a 1 on failure.  An error message is
placed in the object->{'Error'} variable on failure.

   h_delete hierarchical delete (I don't believe this is RFC anything)
deletes a mailbox and all sub-mailboxes/subfolders that belong to it.  It
basically gets a subfolder list and does multiple delete calls.  It
returns 0 on sucess or a 1 on failure with the error message from delete
being put into the object->{'Error'} variable.  Don't forget to set your
Separator if it's not a period.

   list lists mailboxes.  list accepts wildcard matching

   subscribe/unsubscribe does this action on given mailbox.

   rename renames a mailbox.  IMAP servers seem to be peculiar about how
they implement this, so I wouldn't necessarily expect it to do what you
think it should.

QUOTA FUNCTIONS
---------------

   RFC2087 imap extensions.  These are supported by Cyrus IMAP and
Mirapoint.

   get_quotaroot and get_quota retrieve quota information.  They return an
array on success and undef on failure.  In the event of a failure the
error is place in the object->{'Error'} variable.  The array has three
elements for each item in the quota.  $quota[0] <- mailbox name $quota[1]
<- quota amount used in kbytes $quota[2] <- quota in kbytes

   set_quota sets the quota.  The number is in kilobytes so 10000 is
approximately 10Meg.  set_quota returns a 0 on success or a 1 on failure.
An error message is placed in the object->{'Error'} variable on failure.

   To delete a quota do a set_quota($mailbox, "none");

ACCESS CONTROL FUNCTIONS
------------------------

   RFC2086 imap extensions.  These are supported by Cyrus IMAP, Mirapoint
and probably many others.

   get_acl retrieves acl information.  It returns an array on success and
under on failure.  In the event of a failure the error is placed in the
object->{'Error'} variable. The array contains a pair for each person who
has an acl on this mailbox $acl[0] user who has acl information $acl[1]
acl information $acl[2] next user ...

   set_acl set acl information for a single mailbox.  You can specify more
the one user's rights on the same set call.  It returns a 0 on success or
a 1 on failure.  An error message is placed in the object->{'Error'}
variable on failure.

   delete_acl removes acl information on a single mailbox for the given
users.  You can specify more the one users rights to be removed in the
same delete_acl call.  It returns a 0 on success or a 1 on failure.  An
error message is placed int the object->{'Error'} variable on failure.

   standard rights (rfc2086):  l - lookup (mailbox is visible to LIST/LSUB
commands)  r - read (SELECT the mailbox, perform CHECK, FETCH, PARTIAL,
SEARCH, and COPY)  s - keep seen/unssen information across sessions (STORE
SEEN flag)  w - write (STORE flags other then SEEN and DELETED)  i -
insert (perform APPEND and COPY into mailbox)  p - post (send mail to
submission address for mailbox)  c - create (CREATE new sub-mailboxes)
(*note* allows for delete of sub mailboxes as well)  d - delete (STORE
DELETED flag, perform EXPUNGE)  a - administer (perform SETACL)

   The access control information is from Cyrus IMAP.    read   = "lrs"
post   = "lrsp"   append = "lrsip"   write  = "lrswipcd"   all    =
"lrswipcda"

KNOWN BUGS
==========

   Currently all the of the socket traffic is handled via prints and
_read.  This means that some of the calls could hang if the socket
connection is broken.  Eventually the will be properly selected and timed.

LICENSE
=======

   This is licensed under the Artistic license (same as perl).  A copy of
the license is included in this package.  The file is called Artistic.  If
you use this in a product or distribution drop me a line, 'cause I am
always curious about that...

CVS REVISION
============

   $Id: Admin.pm,v 1.31 2000/11/29 06:06:44 eric Exp $

AUTHOR
======

   Eric Estabrooks, eric@urbanrage.com

SEE ALSO
========

   perl(1).

Perl extensions to convert INSPEC data from INSPEC::Retriever to BibTeX format
******************************************************************************

NAME
====

   INSPEC::BibTeX - Perl extensions to convert INSPEC data from
INSPEC::Retriever to BibTeX format

SYNOPSIS
========

     use INSPEC::BibTeX;

DESCRIPTION
===========

   These routines allow you to to convert INSPEC data from
INSPEC::Retriever to BibTeX format

EXAMPLES
========

AUTHOR
======

   Vincent LaBella vlabella@uark.edu

COPYRIGHT
=========

   Copyright (C) 2000 Vincent LaBella.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

WARRANTY
========

   THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

SEE ALSO
========

   perl(1).

Perl extensions to extract information from the INSPEC database provided by AXIOM
*********************************************************************************

NAME
====

   INSPEC::Retriever - Perl extensions to extract information from the
INSPEC database provided by AXIOM

SYNOPSIS
========

     use INSPEC::Retriever;

DESCRIPTION
===========

   These routines allow you to extract information about a citation or
paper from a the INSPEC database provided by AXIOM

EXAMPLES
========

AUTHOR
======

   Vincent LaBella vlabella@uark.edu

COPYRIGHT
=========

   Copyright (C) 2000 Vincent LaBella.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

WARRANTY
========

   THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

SEE ALSO
========

   perl(1).

load various IO modules
***********************

NAME
====

   IO - load various IO modules

SYNOPSIS
========

     use IO;

DESCRIPTION
===========

   IO provides a simple mechanism to load some of the IO modules at one go.
Currently this includes:

     IO::Handle
     IO::Seekable
     IO::File
     IO::Pipe
     IO::Socket
     IO::Dir

   For more information on any of these modules, please see its respective
documentation.

write a file which is updated atomically
****************************************

NAME
====

   IO::AtomicFile - write a file which is updated atomically

SYNOPSIS
========

     use IO::AtomicFile;

     # Write a temp file, and have it install itself when closed:
     my $FH = IO::AtomicFile->open("bar.dat", "w");
     print $FH "Hello!\n";
     $FH->close || die "couldn't install atomic file: $!";

     # Write a temp file, but delete it before it gets installed:
     my $FH = IO::AtomicFile->open("bar.dat", "w");
     print $FH "Hello!\n";
     $FH->delete;

     # Write a temp file, but neither install it nor delete it:
     my $FH = IO::AtomicFile->open("bar.dat", "w");
     print $FH "Hello!\n";
     $FH->detach;

DESCRIPTION
===========

   This module is intended for people who need to update files reliably in
the face of unexpected program termination.

   For example, you generally don't want to be halfway in the middle of
writing */etc/passwd* and have your program terminate!  Even the act of
writing a single scalar to a filehandle is not atomic.

   But this module gives you true atomic updates, via rename().  When you
open a file */foo/bar.dat* via this module, you are *actually* opening a
temporary file */foo/bar.dat..TMP*, and writing your output there.   The
act of closing this file (either explicitly via close(), or implicitly via
the destruction of the object) will cause rename() to be called...
therefore, from the point of view of the outside world, the file's
contents are updated in a single time quantum.

   To ensure that problems do not go undetected, the "close" method done
by the destructor will raise a fatal exception if the rename() fails.  The
explicit close() just returns undef.

   You can also decide at any point to trash the file you've been building.

AUTHOR
======

   Eryq (`eryq@zeegee.com').  President, ZeeGee Software Inc
(`http://www.zeegee.com').

REVISION
========

   $Revision: 1.105 $

Emulate IO::File interface for PostgreSQL Large Objects
*******************************************************

NAME
====

   IO::BLOB::Pg - Emulate IO::File interface for PostgreSQL Large Objects

SYNOPSIS
========

     use IO::BLOB::Pg;
     use DBI;

     $dbh = DBI->connect("dbi:Pg:dbname=mah", "", "",
                         {RaiseError=>1,
                          AutoCommit=>0}) # <- Absolutely necessary!
     $io = IO::BLOB::Pg->new($dbi);	# Create a new blob
     tie *IO, 'IO::BLOB::Pg';

     # write data
     print $io "string\n";
     $io->print(@data);
     syswrite($io, $buf, 100);

     select $io;
     printf "Some text %s\n", $str;

     # seek
     $pos = $io->getpos;
     $io->setpos(0);        # rewind
     $io->seek(-30, -1);

     # read data
     <$io>;
     $io->getline;
     read($io, $buf, 100);

     # get the blob's oid
     $oid = $io->oid;

     # close up
     $io->close;

     # open a previously created blob
     $io = IO::BLOB::Pg->new($dbi, $oid);

**** WARNING ****
=================

   To use this module, you *must* feed your DBI connection `AutoCommit =>
0'.  See the PostgreSQL documentation for more details.

DESCRIPTION
===========

   The `IO::BLOB::Pg' module provide the IO::File interface for Large
Objects (aka BLOBs) in a PostgreSQL database.  An `IO::BLOB::Pg' object
can be attached to a Large Object ID, and will make it possible to use the
normal file operations for reading or writing data, as well as seeking to
various locations of the object.

   This provides a tremendous amount of convenience since you can treat
the object just like a regular file and operate on it as you would
normally in Perl instead of doing all sorts of funky stuff like:

     $dbh->func($lobjfd, $buff, $len, "lo_read");

   you get:

     <$lobjfd>

   I based this code on Gisle Aas' IO::String, so the interface is similar.

   The `IO::BLOB::Pg' module provides an interface compatible with
IO::File as distributed with `IO-1.20', but the following methods are not
available; new_from_fd, fdopen, format_write, format_page_number,
format_lines_per_page, format_lines_left, format_name, format_top_name.

   The following methods are specific for the `IO::BLOB::Pg' class:

$io = IO::BLOB::Pg->new( $dbh[, $objid] )
     The constructor returns a newly created `IO::BLOB::Pg' object.  You
     must supply it with a database handle.  It takes an optional argument
     which is oid of the large objectto read from or write into.  If no
     $objid argument is given, then a new large object is created.

     The `IO::BLOB::Pg' object returned will be tied to itself.  This means
     that you can use most perl IO builtins on it too; readline, <>, getc,
     print, printf, syswrite, sysread, close.

$io->open( $dbh[, $objid] )
     Attach an existing IO::BLOB::Pg object to some other $objid, or create
     a new large object if no $objid is given.  The position is reset back
     to 0.

$io->oid
     This method will return the oid of the large object.  This is useful
     for when you create a large object and what to put a reference to it
     in another table.

$io->pad( [$char] )
     *Currently, extending the Blob via seek() or truncate() is not
     possible.*

     The pad() method makes it possible to specify the padding to use if
     the object is extended by either the seek() or truncate() methods.  It
     is a single character and defaults to "\0".

$io->pos( [$newpos] )
     Yet another interface for reading and setting the current read/write
     position within the object (the normal getpos/setpos/tell/seek
     methods are also available).  The pos() method will always return the
     old position, and if you pass it an argument it will set the new
     position.

$io->length
     Convenience method that gives you the size of the Blob.

   One more difference compared to IO::Handle, is that the write() and
syswrite() methods allow the length argument to be left out.

BUGS
====

   The perl TIEHANDLE interface is still not complete.  There are quite a
few file operations that will not yet invoke any method on the tied
object.  See Perltie (perl.info), for details.

SEE ALSO
========

   See IO/File, IO/String,

COPYRIGHT
=========

   Copyright 2000 Mark A. Hershberger, <mah@everybody.org>.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Object-oriented Perl implementation of cat(1)
*********************************************

NAME
====

   IO::Cat - Object-oriented Perl implementation of cat(1)

SYNOPSIS
========

     require IO::Cat;

     my $meow = new IO::Cat '/etc/motd';
     $meow->cat( \*STDOUT, \*STDERR )
     	or die "Can't cat /etc/motd: $!";

DESCRIPTION
===========

   IO::Cat provides an intuitive, scalable, encapsulated interface to the
common task of printing to a filehandle. Use it a few times, and you'll
never know how you lived without it!

METHODS
=======

   * new FILENAME

     This constructor takes the name of a file to be catted and returns a
     brand spanking new IO::Cat object. If you prefer, you can pass it no
     args here and use the file() accessor method to set the filename
     before calling cat().

   * file FILENAME

     An accessor method that lets you set the filename or filehandle which
     a particular IO::Cat object will cat. Returns the open filehandle
     which it will cat from.

   * cat *FILEHANDLE*

     Copies data from a previously specified file to FILEHANDLE, or returns
     false if an error occurred.

   * cattail *FILEHANDLE*

     Prints data from a previously specified file to FILEHANDLE -
     backwards, line by line - or returns false if an error occurred.

AUTHOR
======

   Dennis Taylor, <corbeau@execpc.com>

SEE ALSO
========

   cat(1) and the File::Cat module.

replace select() with $DEFOUT, $DEFERR, $DEFIN
**********************************************

NAME
====

   IO::Default - replace select() with $DEFOUT, $DEFERR, $DEFIN

SYNOPSIS
========

     use IO::Default;

     open LOG, ">/var/log/my.log";
     $DEFOUT = LOG;               # instead of select(LOG);

     open $DEFERR, ">/var/log/my.err";
     warn "Badness!";             # sends to $DEFERR

     $DEFIN = \*STDIN;            # barewords or globs work
     @data = <>;                  # reads from $DEFIN now

     use FileHandle;              # provide OO file methods

     $DEFOUT = \*MYFILE;          # need to use globs if want OO
     $DEFOUT->autoflush(1);       # set $| on whatever $DEFOUT is
     $DEFERR->autoflush(1);       # ditto

     $DEFIN->untaint;             # untaint default input stream

DESCRIPTION
===========

   Currently, Perl provides a somewhat clumsy way of manipulating the
default filehandle, and no easy way of manipulating default error and
input handles. This module serves the dual purpose of providing a means
around this, as well as serving as a prototype for a proposed Perl 6
feature.

   This module replaces the use of select() and the default filehandle
with three variables, $DEFOUT, $DEFERR, and $DEFIN, that are the default
output, input, and error filehandles. By default, they point to STDOUT,
STDERR, and nothing, respectively. The reason $DEFIN doesn't do anything
until you assign to it is because assigning to it wipes out @ARGV. See the
BUGS below.

   To change what the default filehandle is for output, simply assign a
filehandle or filehandle glob to $DEFOUT:

     open LOG, ">/var/log/my.log" or die;
     $DEFOUT = LOG;                       # bare filehandles ok
     print "Here's some data";            # goes to LOG

   The same can be easily done with $DEFERR for default errors:

     open ERR, ">/var/log/my.err" or die;
     $DEFERR = \*ERR unless $have_a_tty;  # glob refs ok too
     warn "Danger, Will Robinson!";       # goes to ERR

   Finally, this module changes the semantics of <> if you assign to
$DEFIN. Normally, the <> ARGV filehandle will iterate through command line
arguments. This is still the default. However, if you explicitly assign a
filehandle to $DEFIN, then this changes the semantics and input is instead
read from the handle:

     open MOTD, "</etc/motd" or die;
     $DEFIN = MOTD;
     print while (<>);                    # just reads /etc/motd

   Why do this? Well, passing filehandles in and out of functions is a
pain in Perl 5, requiring you to use globs. If you simply want to change
the default input for a sub function somewhere, have it read from <>:

     sub get_data {
         my @data = <>;
         # do more stuff
         return @data;
     }

   Then from the top level do something like this:

     # Figure out our input stream
     $DEFIN = get_handle || \*STDIN;
     @data = get_data;

   And now you don't have to pass filehandles in and out of functions
anymore just for dealing with default input and output. Note that here <>
and <$DEFIN> are synonymous.

BUGS
====

   This module should NOT be used in production code because it is
considered unstable and subject to change.

   Unfortunately, getting $DEFIN to work in Perl 5 is hairy, since ARGV is
so special. As such, assigning to $DEFIN will wipe out whatever you have
in @ARGV at the time. It also can't set $ARGV, since the file that was
opened is unknown.

   Luckily, if you never assign or access $DEFIN, then <> retains its
magic powers, so if you don't like this simply don't use $DEFIN.

   This module really just does some trickery to reopen the STD
filehandles and point them to different places. As such, mixing print
calls to $DEFERR and STDERR will send the output to the same place
(contrary to the Perl 6 proposal).

REFERENCES
==========

   For complete details on the Perl 6 proposal, please visit
http://dev.perl.org/rfc/129.html. Comments are welcome.

AUTHOR
======

   Copyright (c) 2000, Nathan Wiger <nate@sun.com>. All Rights Reserved.

   This module is free software; you may copy this under the terms of the
GNU General Public License, or the Artistic License, copies of which
should have accompanied your Perl kit.

supply object methods for directory handles
*******************************************

NAME
====

   IO::Dir - supply object methods for directory handles

SYNOPSIS
========

     use IO::Dir;
     $d = new IO::Dir ".";
     if (defined $d) {
         while (defined($_ = $d->read)) { something($_); }
         $d->rewind;
         while (defined($_ = $d->read)) { something_else($_); }
         undef $d;
     }

     tie %dir, IO::Dir, ".";
     foreach (keys %dir) {
     	print $_, " " , $dir{$_}->size,"\n";
     }

DESCRIPTION
===========

   The IO::Dir package provides two interfaces to perl's directory reading
routines.

   The first interface is an object approach. IO::Dir provides an object
constructor and methods, which are just wrappers around perl's built in
directory reading routines.

new ( [ DIRNAME ] )
     new is the constuctor for IO::Dir objects. It accepts one optional
     argument which,  if given, new will pass to open

   The following methods are wrappers for the directory related functions
built into perl (the trailing `dir' has been removed from the names). See
Perlfunc (perl.info), for details of these functions.

open ( DIRNAME )
read ()
seek ( POS )
tell ()
rewind ()
close ()
   IO::Dir also provides a interface to reading directories via a tied
HASH. The tied HASH extends the interface beyond just the directory
reading routines by the use of lstat, from the File::stat package, unlink,
rmdir and utime.

tie %hash, IO::Dir, DIRNAME [, OPTIONS ]
   The keys of the HASH will be the names of the entries in the directory.
Reading a value from the hash will be the result of calling
`File::stat::lstat'. Deleting an element from the hash will call unlink
providing that DIR_UNLINK is passed in the OPTIONS.

   Assigning to an entry in the HASH will cause the time stamps of the file
to be modified. If the file does not exist then it will be created.
Assigning a single integer to a HASH element will cause both the access and
modification times to be changed to that value. Alternatively a reference
to an array of two values can be passed. The first array element will be
used to set the access time and the second element will be used to set the
modification time.

SEE ALSO
========

   See File/stat,

AUTHOR
======

   Graham Barr <`gbarr@pobox.com'>

COPYRIGHT
=========

   Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

supply object methods for filehandles
*************************************

NAME
====

   IO::File - supply object methods for filehandles

SYNOPSIS
========

     use IO::File;

     $fh = new IO::File;
     if ($fh->open("< file")) {
         print <$fh>;
         $fh->close;
     }

     $fh = new IO::File "> file";
     if (defined $fh) {
         print $fh "bar\n";
         $fh->close;
     }

     $fh = new IO::File "file", "r";
     if (defined $fh) {
         print <$fh>;
         undef $fh;       # automatically closes the file
     }

     $fh = new IO::File "file", O_WRONLY|O_APPEND;
     if (defined $fh) {
         print $fh "corge\n";

     $pos = $fh->getpos;
     $fh->setpos($pos);

     undef $fh;       # automatically closes the file
         }

     autoflush STDOUT 1;

DESCRIPTION
===========

   IO::File inherits from IO::Handle and IO::Seekable. It extends these
classes with methods that are specific to file handles.

CONSTRUCTOR
===========

new ( FILENAME [,MODE [,PERMS]] )
     Creates a IO::File.  If it receives any parameters, they are passed to
     the method open; if the open fails, the object is destroyed.
     Otherwise, it is returned to the caller.

new_tmpfile
     Creates an IO::File opened for read/write on a newly created temporary
     file.  On systems where this is possible, the temporary file is
     anonymous (i.e. it is unlinked after creation, but held open).  If
     the temporary file cannot be created or opened, the IO::File object
     is destroyed.  Otherwise, it is returned to the caller.

METHODS
=======

open( FILENAME [,MODE [,PERMS]] )
     open accepts one, two or three parameters.  With one parameter, it is
     just a front end for the built-in open function.  With two or three
     parameters, the first parameter is a filename that may include
     whitespace or other special characters, and the second parameter is
     the open mode, optionally followed by a file permission value.

     If `IO::File::open' receives a Perl mode string (">", "+<", etc.)  or
     a ANSI C fopen() mode string ("w", "r+", etc.), it uses the basic
     Perl open operator (but protects any special characters).

     If `IO::File::open' is given a numeric mode, it passes that mode and
     the optional permissions value to the Perl sysopen operator.  The
     permissions default to 0666.

     For convenience, IO::File exports the O_XXX constants from the Fcntl
     module, if this module is available.

SEE ALSO
========

   See Perlfunc (perl.info), `"I', see Perlop (perl.info),
`"I', see IO/Handle, `"I', see
IO/Seekable,

HISTORY
=======

   Derived from FileHandle.pm by Graham Barr <`gbarr@pobox.com'>.

Print to multiple filehandles with one output call
**************************************************

NAME
====

   Multi - Print to multiple filehandles with one output call

SYNOPSIS
========

     use IO::File::Multi;
     $mult_obj=new IO::File::Multi;
     $mult_obj->open('>-');
     $mult_obj->open('>file');
     $mult_obj->open(">$file");
     $mult_obj->open('>>file2');
     $mult_obj->print("This will be printed to several filehandles\n");
     $mult_obj->printf("This will be printed to %d filehandles\n",
         scalar @{$mult_obj->{handles}});
     $mult_obj->autoflush();
     @handle_refs = $mult_obj->members();
     $mult_obj->output_field_separator(':');
     $mult_obj->output_record_separator('\n');
     $mult_obj->format_page_number(2);
     $mult_obj->format_lines_per_page(66);
     $mult_obj->format_lines_left(10);
     $mult_obj->format_name('AN_REPORT');
     $mult_obj->format_top_name('AN_REPORT_TOP');
     $mult_obj->format_line_break_characters('\n');
     $mult_obj->format_formfeed('\l');
     $mult_obj->close();

DESCRIPTION
===========

   This module requires that the user have the IO::File module installed
(it comes with the perl distribution).  Create objects for each of the
output filehandles you'll have - then call the print() and printf()
methods to send output to ALL the filehandles associated with an object.

EXAMPLES
========

   Look at the SYNOPSIS section.  Also, here is a simple implementation of
the unix tee(1) program (non-append mode):

     #!/local/bin/perl
     use IO::File::Multi;
     $mh=new IO::File::Multi;
     $mh->open('>-');
     for (@ARGV) { $mh->open(">$_"); }
     while (<STDIN>) { $mh->print($_); }

BUGS
====

   I don't think using my()s the way I am in the open() method is all that
good.  binmode isn't supported, but I don't see anybody using that anyways.
In order to use fcntl(), fileno(), or flock() you'll have to access the
filehandles yourself by calling members().  There's no write() yet (but I'm
working on it!).  Also, any limitations to the IO::File module also apply
here.

   It has been pointed out to me that multiple open() calls on the same
file under MacOS will fail.  Hopefully, the carp() call will help with
catching this.

AUTHOR
======

   Nem W Schlecht (nem@plains.nodak.edu).  Comments, bugs fixes, and
suggestions welcome.

supply object methods for I/O handles
*************************************

NAME
====

   IO::Handle - supply object methods for I/O handles

SYNOPSIS
========

     use IO::Handle;

     $io = new IO::Handle;
     if ($io->fdopen(fileno(STDIN),"r")) {
         print $io->getline;
         $io->close;
     }

     $io = new IO::Handle;
     if ($io->fdopen(fileno(STDOUT),"w")) {
         $io->print("Some text\n");
     }

     use IO::Handle '_IOLBF';
     $io->setvbuf($buffer_var, _IOLBF, 1024);

     undef $io;       # automatically closes the file if it's open

     autoflush STDOUT 1;

DESCRIPTION
===========

   IO::Handle is the base class for all other IO handle classes. It is not
intended that objects of IO::Handle would be created directly, but instead
IO::Handle is inherited from by several other classes in the IO hierarchy.

   If you are reading this documentation, looking for a replacement for
the FileHandle package, then I suggest you read the documentation for
IO::File too.

CONSTRUCTOR
===========

new ()
     Creates a new IO::Handle object.

new_from_fd ( FD, MODE )
     Creates a IO::Handle like new does.  It requires two parameters,
     which are passed to the method fdopen; if the fdopen fails, the
     object is destroyed. Otherwise, it is returned to the caller.

METHODS
=======

   See Perlfunc (perl.info), for complete descriptions of
each of the following supported IO::Handle methods, which are just front
ends for the corresponding built-in functions:

     $io->close
     $io->eof
     $io->fileno
     $io->format_write( [FORMAT_NAME] )
     $io->getc
     $io->read ( BUF, LEN, [OFFSET] )
     $io->print ( ARGS )
     $io->printf ( FMT, [ARGS] )
     $io->stat
     $io->sysread ( BUF, LEN, [OFFSET] )
     $io->syswrite ( BUF, LEN, [OFFSET] )
     $io->truncate ( LEN )

   See Perlvar (perl.info), for complete descriptions of
each of the following supported IO::Handle methods.  All of them return
the previous value of the attribute and takes an optional single argument
that when given will set the value.  If no argument is given the previous
value is unchanged (except for $io->autoflush will actually turn ON
autoflush by default).

     $io->autoflush ( [BOOL] )                         $|
     $io->format_page_number( [NUM] )                  $%
     $io->format_lines_per_page( [NUM] )               $=
     $io->format_lines_left( [NUM] )                   $-
     $io->format_name( [STR] )                         $~
     $io->format_top_name( [STR] )                     $^
     $io->input_line_number( [NUM])                    $.

   The following methods are not supported on a per-filehandle basis.

     IO::Handle->format_line_break_characters( [STR] ) $:
     IO::Handle->format_formfeed( [STR])               $^L
     IO::Handle->output_field_separator( [STR] )       $,
     IO::Handle->output_record_separator( [STR] )      $\

     IO::Handle->input_record_separator( [STR] )       $/

   Furthermore, for doing normal I/O you might need these:

$io->fdopen ( FD, MODE )
     fdopen is like an ordinary open except that its first parameter is
     not a filename but rather a file handle name, a IO::Handle object, or
     a file descriptor number.

$io->opened
     Returns true if the object is currently a valid file descriptor.

$io->getline
     This works like <$io> described in `"I', see Perlop (perl.info),
     except that it's more readable and can be safely
     called in an array context but still returns just one line.

$io->getlines
     This works like <$io> when called in an array context to read all the
     remaining lines in a file, except that it's more readable.  It will
     also croak() if accidentally called in a scalar context.

$io->ungetc ( ORD )
     Pushes a character with the given ordinal value back onto the given
     handle's input stream.  Only one character of pushback per handle is
     guaranteed.

$io->write ( BUF, LEN [, OFFSET ] )
     This write is like write found in C, that is it is the opposite of
     read. The wrapper for the perl write function is called format_write.

$io->error
     Returns a true value if the given handle has experienced any errors
     since it was opened or since the last call to clearerr.

$io->clearerr
     Clear the given handle's error indicator.

$io->sync
     sync synchronizes a file's in-memory state  with  that  on the
     physical medium. sync does not operate at the perlio api level, but
     operates on the file descriptor, this means that any data held at the
     perlio api level will not be synchronized. To synchronize data that is
     buffered at the perlio api level you must use the flush method. sync
     is not implemented on all platforms. See `fsync(3c)' in this node.

$io->flush
     flush causes perl to flush any buffered data at the perlio api level.
     Any unread data in the buffer will be discarded, and any unwritten
     data will be written to the underlying file descriptor.

$io->printflush ( ARGS )
     Turns on autoflush, print ARGS and then restores the autoflush status
     of the IO::Handle object.

$io->blocking ( [ BOOL ] )
     If called with an argument blocking will turn on non-blocking IO if
     `BOOL' is false, and turn it off if `BOOL' is true.

     blocking will return the value of the previous setting, or the
     current setting if `BOOL' is not given.

     If an error occurs blocking will return undef and $! will be set.

   If the C functions setbuf() and/or setvbuf() are available, then
`IO::Handle::setbuf' and `IO::Handle::setvbuf' set the buffering policy
for an IO::Handle.  The calling sequences for the Perl functions are the
same as their C counterparts-including the constants `_IOFBF', `_IOLBF',
and `_IONBF' for setvbuf()-except that the buffer parameter specifies a
scalar variable to use as a buffer.  WARNING: A variable used as a buffer
by `setbuf' or `setvbuf' must not be modified in any way until the
IO::Handle is closed or `setbuf' or `setvbuf' is called again, or memory
corruption may result! Note that you need to import the constants
`_IOFBF', `_IOLBF', and `_IONBF' explicitly.

   Lastly, there is a special method for working under -T and setuid/gid
scripts:

$io->untaint
     Marks the object as taint-clean, and as such data read from it will
     also be considered taint-clean. Note that this is a very trusting
     action to take, and appropriate consideration for the data source and
     potential vulnerability should be kept in mind.

NOTE
====

   A IO::Handle object is a reference to a symbol/GLOB reference (see the
Symbol package).  Some modules that inherit from IO::Handle may want to
keep object related variables in the hash table part of the GLOB. In an
attempt to prevent modules trampling on each other I propose the that any
such module should prefix its variables with its own name separated by
_'s. For example the IO::Socket module keeps a timeout variable in
'io_socket_timeout'.

SEE ALSO
========

   See Perlfunc (perl.info), `"I', see Perlop (perl.info),
`"I', see IO/File,

BUGS
====

   Due to backwards compatibility, all filehandles resemble objects of
class IO::Handle, or actually classes derived from that class.  They
actually aren't.  Which means you can't derive your own class from
IO::Handle and inherit those methods.

HISTORY
=======

   Derived from FileHandle.pm by Graham Barr <`gbarr@pobox.com'>

define a file inside another file
*********************************

NAME
====

   IO::InnerFile - define a file inside another file

SYNOPSIS
========

     ### Read a subset of a file:
     $inner = IO::InnerFile->new($fh, $start, $length);
     while (<$inner>) {
     	...
     }

DESCRIPTION
===========

   If you have a filehandle that can seek() and tell(), then you can open
an IO::InnerFile on a range of the underlying file.

PUBLIC INTERFACE
================

new FILEHANDLE, [START, [LENGTH]]
     *Class method, constructor.* Create a new inner-file opened on the
     given FILEHANDLE, from bytes START to START+LENGTH.  Both START and
     LENGTH default to 0; negative values are silently coerced to zero.

     Note that FILEHANDLE must be able to seek() and tell(), in addition
     to whatever other methods you may desire for reading it.

set_length LENGTH
get_length
add_length NBYTES
     *Instance methods.* Get/set the virtual length of the inner file.

set_start START
get_start
add_start NBYTES
     *Instance methods.* Get/set the virtual start position of the inner
     file.

binmode
close
flush
getc
getline
print LIST
printf LIST
read BUF, NBYTES
readline
seek OFFFSET, WHENCE
tell
write ARGS...
     *Instance methods.* Standard filehandle methods.

AUTHOR
======

   Original version by Doru Petrescu (pdoru@kappa.ro).

   Documentation and current maintenance by Eryq (eryq@zeegee.com).

Perl extension for access to network card configuration information
*******************************************************************

NAME
====

   IO::Interface - Perl extension for access to network card configuration
information

SYNOPSIS
========

     use IO::Socket;
     use IO::Interface;

     my $s = IO::Socket::INET->new(Proto => 'udp');
     my @interfaces = $s->if_list;

     for my $f (@interfaces) {
       print "interface = $f\n";
       my $flags = $s->if_flags($if);
       print "addr =      ",$s->if_addr($if),"\n",
             "broadcast = ",$s->if_broadcast($if),"\n",
             "netmask =   ",$s->if_netmask($if),"\n",
             "dstaddr =   ",$s->if_dstaddr($if),"\n",
             "hwaddr =    ",$s->if_hwaddr($if),"\n";

     print "is running\n"     if $flags & IFF_RUNNING;
     print "is broadcast\n"   if $flags & IFF_BROADCAST;
     print "is p-to-p\n"      if $flags & IFF_POINTOPOINT;
     print "is loopback\n"    if $flags & IFF_LOOPBACK;
     print "is promiscuous\n" if $flags & IFF_PROMISCUOUS;
     print "is multicast\n"   if $flags & IFF_MULTICAST;
     print "is notrailers\n"  if $flags & IFF_NOTRAILERS;
     print "is noarp\n"       if $flags & IFF_NOARP;
       }

       $interface = $s->addr_to_interface('127.0.0.1');

DESCRIPTION
===========

   IO::Interface adds methods to IO::Socket objects that allows them to be
used to retrieve and change information about the network interfaces on
your system.  In addition to the object-oriented access methods, you can
use a function-oriented style.

Creating a Socket to Access Interface Information
-------------------------------------------------

   You must create a socket before you can access interface information.
The socket does not have to be connected to a remote site, or even used
for communication.  The simplest procedure is to create a UDP protocol
socket:

     my $s = IO::Socket::INET->new(Proto => 'udp');

   The various IO::Interface functions will now be available as methods on
this socket.

Methods
-------

@iflist = $s->if_list
     The if_list() method will return a list of active interface names, for
     example "eth0" or "tu0".  If no interfaces are configured and running,
     returns an empty list.

$addr = $s->if_addr($ifname [,$newaddr])
     if_addr() gets or sets the interface address.  Call with the interface
     name to retrieve the address (in dotted decimal format).  Call with a
     new address to set the interface.  In the latter case, the routine
     will return a true value if the operation was successful.

          my $oldaddr = $s->if_addr('eth0');
          $s->if_addr('eth0','192.168.8.10') || die "couldn't set address: $!";

     Special case: the address of the pseudo-device "any" will return the
     IP address "0.0.0.0", which corresponds to the INADDR_ANY constant.

$broadcast = $s->if_broadcast($ifname [,$newbroadcast]
     Get or set the interface broadcast address.  If the interface does not
     have a broadcast address, returns undef.

$mask = $s->if_netmask($ifname [,$newmask])
     Get or set the interface netmask.

$dstaddr = $s->if_dstaddr($ifname [,$newdest])
     Get or set the destination address for point-to-point interfaces.

$hwaddr = $s->if_hwaddr($ifname [,$newhwaddr])
     Get or set the hardware address for the interface. Currently only
     ethernet addresses in the form "00:60:2D:2D:51:70" are accepted.

$flags = $s->if_flags($ifname [,$newflags])
     Get or set the flags for the interface.  The flags are a bitmask
     formed from a series of constants.  See `Exportable constants' in
     this node below.

$ifname = $s->addr_to_interface($ifaddr)
     Given an interface address in dotted form, returns the name of the
     interface associated with it.  Special case: the INADDR_ANY address,
     0.0.0.0 will return a pseudo-interface name of "any".

EXPORT
------

   IO::Interface exports nothing by default.  However, you can import the
following symbol groups into your namespace:

     :functions   Function-oriented interface (see below)
     :flags       Flag constants (see below)
     :all         All of the above

Function-Oriented Interface
---------------------------

   By importing the ":functions" set, you can access IO::Interface in a
function-oriented manner.  This imports all the methods described above
into your namespace.  Example:

     use IO::Socket;
     use IO::Interface ':functions';

     my $sock = IO::Socket::INET->new(Proto=>'udp');
     my @interfaces = if_list($sock);
     print "address = ",if_addr($sock,$interfaces[0]);

Exportable constants
--------------------

   The ":flags" constant imports the following constants for use with the
flags returned by if_flags():

     IFF_ALLMULTI
     IFF_AUTOMEDIA
     IFF_BROADCAST
     IFF_DEBUG
     IFF_LOOPBACK
     IFF_MASTER
     IFF_MULTICAST
     IFF_NOARP
     IFF_NOTRAILERS
     IFF_POINTOPOINT
     IFF_PORTSEL
     IFF_PROMISC
     IFF_RUNNING
     IFF_SLAVE
     IFF_UP

   This example determines whether interface 'tu0' supports multicasting:

     use IO::Socket;
     use IO::Interface ':flags';
     my $sock = IO::Socket::INET->new(Proto=>'udp');
     print "can multicast!\n" if $sock->if_flags & IFF_MULTICAST.

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>

   This module is distributed under the same license as Perl itself.

SEE ALSO
========

   perl(1), IO::Socket(3), IO::Multicast(3)

IO:: interface for reading/writing an array of lines
****************************************************

NAME
====

   IO::Lines - IO:: interface for reading/writing an array of lines

SYNOPSIS
========

     use IO::Lines;

     # See IO::ScalarArray for details

DESCRIPTION
===========

   This class implements objects which behave just like FileHandle (or
IO::Handle) objects, except that you may use them to write to (or read
from) an array of lines.  They can be tiehandle'd as well.

   This is a subclass of `IO::ScalarArray|IO::ScalarArray' in this node in
which the underlying array has its data stored in a line-oriented-format:
that is, every element ends in a `"\n"', with the possible exception of the
final element.  This makes `getline()' *much* more efficient; if you plan
to do line-oriented reading/printing, you want this class.

   The print() method will enforce this rule, so you can print arbitrary
data to the line-array: it will break the data at newlines appropriately.

   See IO/ScalarArray, for full usage.

VERSION
=======

   $Id: Lines.pm,v 1.110 2000/08/16 04:59:02 eryq Exp $

AUTHORS
=======

Principal author
----------------

   Eryq (`eryq@zeegee.com').  President, ZeeGee Software Inc
(`http://www.zeegee.com').

Other contributors
------------------

   Thanks to the following individuals for their invaluable contributions
(if I've forgotten or misspelled your name, please email me!):

   *Morris M. Siegel,* for his $/ patch and the new `getlines()'.

supply object methods for locking files
***************************************

NAME
====

   IO::LockedFile Class - supply object methods for locking files

SYNOPSIS
========

     use IO::LockedFile;

     # create new locked file object. $file will hold a file handle.
     # if the file is already locked, the method will not return until the
     # file is unlocked
     my $file = new IO::LockedFile(">locked1.txt");

     # when we close the file - it become unlocked.
     $file->close();

     # if we delete the object, the file is automatically unlocked and
     # closed.
     $file = undef;

DESCRIPTION
===========

   The IO::LockedFile class gives us the same interface of the IO::File
class to files with the unique difference that those files are locked using
the flock mechanism.

   If during the running of the process, the process crashed - the file
will be automatically unlocked. Actually - if the IO::LockedFile object
goes out of scope, the file is automatically closed and unlocked.

CONSTRUCTOR
===========

new ( FILENAME [,MODE [,PERMS]] )
     Creates a `IO::LockedFile'.  If it receives any parameters, they are
     passed to the method open; if the open fails, the object is
     destroyed. Otherwise, it is returned to the caller.

METHODS
=======

open( FILENAME [,MODE [,PERMS]] )
     The file FILENAME will be opened as a locked file, and the object
     will be the file handle of that opened file. If the file that is
     opened is locked the method will not return until the file is
     unlocked.  The parameters that should be provided are the same as the
     parameters that the method open of  IO::File accepts. (like
     ">file.txt" for example).

close()
     The file will be closed and unlocked. The method does not return
     anything.

is_locked( FILENAME )
     Will return true if the file is locked. Will return false otherwise.

AUTHOR
======

   Rani Pinchuk, rani@cpan.org

COPYRIGHT
=========

   Copyright (c) 2001 EM-TECH (www.em-tech.net) & Rani Pinchuk.  All
rights reserved.  This package is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

SEE ALSO
========

   `IO::File(3)' in this node

Object interface to multiplex-style server implementations.
***********************************************************

NAME
====

   IO::Multiplex - Object interface to multiplex-style server
implementations.

SYNOPSIS
========

   use IO::Multiplex;

DESCRIPTION
===========

   IO::Multiplex is an object interface to classic multiplex server
designs.

   Alarmed by the time I was wasting re-implementing a fairly
straightforward multiplexing server design, I decided it was time I
abstracted the problem into an object for re-use. If the term
'multiplexing' preplexes you, read `select(2)' in this node, or read a
good book on socket communications, I'm pretty sure most of them cover the
subject.

   This implementation is based on an event model. Users (programmers)
control server behaviour by assigning handlers to certain server events
(client connected, disconnected, input from client, server timeout).

CONSTRUCTOR
===========

   Server construction arguments are supplied in a hash format.

   IO::Multiplex->new(arg1 => 'val1', arg2 => 'val2' ...)

ARGUMENTS
---------

   Arguments define how the server will communicate with it's clients.

'loop_timeout'
     Users may sometime find it useful to schedule a handler to be
     re-executed periodicly within the server's main event loop every
     defined number of seconds. Setting this argument will define the time
     interval between executions of the 'timeout' event.

'proto'
     Optional. Setting this argument will define the server's
     communication layer with it's clients. Common values are 'unix' and
     'tcp'.  Other values ('udp' ?) are passed on to the IO::Socket::INET
     object.

     If left undefined, IO::Multiplex will determine the server's transport
     layer by looking at some of the other arguments.

     example: ('proto' => 'tcp', ...)

'localpath'
     Passed on to the IO::Socket::UNIX object constructor, as the 'Local'
     options.

     Warnings: we remove stale sockets by unlinking 'localpath' for you,
     any other file that happens to be there is removed with no warning.

     Sockets are created with full world read-write permissions.  This
     means any local user with execute permissions on the target directory
     can talk to the server.

     Restrictions: Please realize you do need ordinary file write
     permissions to create a socket in a directory of choice.

'localaddr'
     Optional. Passed on to the IO::Socket::INET object constructor, as
     the 'LocalAddr' option.

     Setting this argument will define the server's local bind address,
     which is necessary in the case of multiple local network interfaces
     (routers, firewalls, proxies).

     If left undefined, IO::Socket::INET will assume 'localhost'.

     example: ('localaddr' => 'localhost', ...)

'localport'
     Passed on to the IO::socket::INET object constructor.  Setting this
     argument will define the server's local bind port.

     Restrictions: If your running unix, binding to port numbers below
     1024 is only allowed by root.

     example: ('localport' => 6666, ...)

METHODS
=======

set_handler($event, \&handler)
     Set a handler for an event. See EVENTS further in this manual.

start()
     Start main (infinite) event loop. Don't expect the program to return
     over execution after starting the start method.

     *Snippet*:

     $server->start() # NOT REACHED

disconnect($client_filehandle)
     Disconnect a client_filehandle, envoking the
     $client_filehandle->close method and calling the
     'client_disconnected' method. It is very important for users to
     understand that the server will never call this method on it's own.

     When users decide a client should go, this is the only proper way to
     disconnect it (removing it from the server's internal 'select'
     object).

EVENTS
======

   A brief reference discription of the server's events. With
'loop_timeout' being the exception, all events will be called with one
argument:

   ($client_filehandle).

   Event handlers should **never** block, or the server will (obviously,
since we're under a single process model) deadlock for the duration of the
execution misbehaving handler.

'loop_timeout' ()
     Define a handler for 'loop_timeout'. A time-based event called in
     repeated intervals of every 'loop_timeout' seconds. Useful when a
     server needs to wake up in an inconditional interval and get
     something done.

     Don't forget to assign supply a value for the 'loop_timeout' argument
     in the server's constructor method.

'client_input' ($client_filehandle)
     The select object decided a client has something to say, and handler
     should read from $client_filehandle and handle input.

     Note if input is null, client has most likely disconnected and
     $server->disconnect should be invoked.

'client_connected' ($client_filehandle)
     Called when a new client connects, handler should handle the joyfull
     event, (print a banner, log connection).

     RETURN VALUE: Return true if we keep the connection, false to drop it.

'client_disconnected' ($client_filehandle)
     Called (by the *IO::Multiplex::disconnect* method) when a client
     disconnects.

AUTHOR
======

   Liraz Siri <liraz_siri@usa.net>, Ariel, Israel.

COPYRIGHT
=========

   Copyright 1999 (c) Liraz Siri <liraz_siri@usa.net>, Ariel, Israel,
             All rights reserved.

class for null filehandles
**************************

NAME
====

   IO::Null - class for null filehandles

SYNOPSIS
========

     use IO::Null;
     my $fh = IO::Null->new;
     print $fh "I have nothing to say\n";  # does nothing.
     # or:
     $fh->print("And I'm saying it.\n");   # ditto.
     # or:
     my $old = select($fh);
     print "and that is poetry / as I needed it --John Cage"; # nada!
     select($old);

   Or even:

     tie(*FOO, IO::Null);
     print FOO "Lalalalala!\n";  # does nothing.

DESCRIPTION
===========

   This is a class for null filehandles.

   Calling a constructor of this class always succeeds, returning a new
null filehandle.

   Writing to any object of this class is always a no-operation, and
returns true.

   Reading from any object of this class is always no-operation, and
returns empty-string or empty-list, as appropriate.

WHY
===

   You could say:

     open(NULL, '>/dev/null') || die "WHAAT?! $!";

   and get a null FH that way.  But not everyone is using an OS that has a
`/dev/null'

IMPLEMENTATION
==============

   This is a subclass of IO::Handle.  Applicable methods with subs that do
nothing, and return an appropriate value.

SEE ALSO
========

   See IO/Handle, Perltie (perl.info),
*IO::Scalar*

CAVEATS
=======

   * This:

     use IO::Null;
     $^W = 1;  # turn on warnings
     tie(*FOO, IO::Null);
     print FOO "Lalalalala!\n";  # does nothing.
     untie(*FOO);

   has been known to produce this odd warning:

     untie attempted while 3 inner references still exist.

   and I've no idea why.

   * Furthermore, this:

     use IO::Null;
     $^W = 1;
     *FOO = IO::Null->new;
     print FOO "Lalalalala!\n";  # does nothing.
     close(FOO);

   emits these warnings:

     Filehandle main::FOO never opened.
     Close on unopened file <GLOB>.

   ...which are, in fact, true; the FH behind the FOO{IO} was never opened
on any real filehandle.  (I'd welcome anyone's (working) suggestions on
how to suppress these warnings.)

   You get the same warnings with:

     use IO::Null;
     $^W = 1;
     my $fh = IO::Null->new;
     print $fh "Lalalalala!\n";  # does nothing.
     close $fh;

   Note that this, however:

     use IO::Null;
     $^W = 1;
     my $fh = IO::Null->new;
     $fh->print("Lalalalala!\n");  # does nothing.
     $fh->close();

   emits no warnings.

   * I don't know if you can successfully untaint a null filehandle.

   * This:

     $null_fh->fileno

   will return a defined and nonzero number, but one you're not likely to
want to use for anything.  See the source.

   * These docs are longer than the source itself.  Read the source!

COPYRIGHT
=========

   Copyright (c) 2000 Sean M. Burke. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Sean M. Burke `sburke@cpan.org'

Pipe STDOUT to a pager if STDOUT is a TTY
*****************************************

NAME
====

     IO::Page - Pipe STDOUT to a pager if STDOUT is a TTY

SYNOPSIS
========

   Pipes STDOUT to a pager if STDOUT is a TTY

DESCRIPTION
===========

   IO::Page is designed to programmaticly decide whether or not to point
the STDOUT file handle into a pipe to program specified in $ENV{PAGER} or
one of a standard list of pagers.

USAGE
=====

     use IO::Page ;
     print <<"  HEREDOC" ;
     ...
     A bunch of text later
     HEREDOC

AUTHOR
======

     Monte Mitzelfelt <monte-iopage@gonefishing.org>

supply object methods for pipes
*******************************

NAME
====

   IO::Pipe - supply object methods for pipes

SYNOPSIS
========

     use IO::Pipe;

     $pipe = new IO::Pipe;

     if($pid = fork()) { # Parent
         $pipe->reader();

     while(<$pipe> {
     		....
     }

     }
     elsif(defined $pid) { # Child
         $pipe->writer();

     print $pipe ....
     	}

     or

     $pipe = new IO::Pipe;

     $pipe->reader(qw(ls -l));

     while(<$pipe>) {
         ....
     }

DESCRIPTION
===========

   IO::Pipe provides an interface to createing pipes between processes.

CONSTRCUTOR
===========

new ( [READER, WRITER] )
     Creates a IO::Pipe, which is a reference to a newly created symbol
     (see the Symbol package). `IO::Pipe::new' optionally takes two
     arguments, which should be objects blessed into IO::Handle, or a
     subclass thereof. These two objects will be used for the system call
     to pipe. If no arguments are given then method handles is called on
     the new IO::Pipe object.

     These two handles are held in the array part of the GLOB until either
     reader or writer is called.

METHODS
=======

reader ([ARGS])
     The object is re-blessed into a sub-class of IO::Handle, and becomes a
     handle at the reading end of the pipe. If ARGS are given then fork is
     called and ARGS are passed to exec.

writer ([ARGS])
     The object is re-blessed into a sub-class of IO::Handle, and becomes a
     handle at the writing end of the pipe. If ARGS are given then fork is
     called and ARGS are passed to exec.

handles ()
     This method is called during construction by `IO::Pipe::new' on the
     newly created IO::Pipe object. It returns an array of two objects
     blessed into `IO::Pipe::End', or a subclass thereof.

SEE ALSO
========

   See IO/Handle,

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

COPYRIGHT
=========

   Copyright (c) 1996-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Object interface to system poll call
************************************

NAME
====

   IO::Poll - Object interface to system poll call

SYNOPSIS
========

     use IO::Poll qw(POLLRDNORM POLLWRNORM POLLIN POLLHUP);

     $poll = new IO::Poll;

     $poll->mask($input_handle => POLLRDNORM | POLLIN | POLLHUP);
     $poll->mask($output_handle => POLLWRNORM);

     $poll->poll($timeout);

     $ev = $poll->events($input);

DESCRIPTION
===========

   IO::Poll is a simple interface to the system level poll routine.

METHODS
=======

mask ( IO [, EVENT_MASK ] )
     If EVENT_MASK is given, then, if EVENT_MASK is non-zero, IO is added
     to the list of file descriptors and the next call to poll will check
     for any event specified in EVENT_MASK. If EVENT_MASK is zero then IO
     will be removed from the list of file descriptors.

     If EVENT_MASK is not given then the return value will be the current
     event mask value for IO.

poll ( [ TIMEOUT ] )
     Call the system level poll routine. If TIMEOUT is not specified then
     the call will block. Returns the number of handles which had events
     happen, or -1 on error.

events ( IO )
     Returns the event mask which represents the events that happend on IO
     during the last call to poll.

remove ( IO )
     Remove IO from the list of file descriptors for the next poll.

handles( [ EVENT_MASK ] )
     Returns a list of handles. If EVENT_MASK is not given then a list of
     all handles known will be returned. If EVENT_MASK is given then a list
     of handles will be returned which had one of the events specified by
     EVENT_MASK happen during the last call ti poll

SEE ALSO
========

   `poll(2)' in this node, see IO/Handle, IO/Select,

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

COPYRIGHT
=========

   Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Pseudo TTY object class
***********************

NAME
====

   IO::Pty - Pseudo TTY object class

SYNOPSIS
========

     use IO::Pty;

     $pty = new IO::Pty;

     $slave  = $pty->slave;

     foreach $val (1..10) {
     	print $pty "$val\n";
     	$_ = <$slave>;
     	print "$_";
     }

     close($slave);

DESCRIPTION
===========

   `IO::Pty' provides an interface to allow the creation of a pseudo tty.

   `IO::Pty' inherits from IO::Handle and so provide all the methods
defined by the IO::Handle package.

CONSTRUCTOR
===========

new
     The new contructor take no arguments and returns a new object which
     the master side of the pseudo tty.

METHODS
=======

slave
     The slave method will return a new `IO::Pty' object which represents
     the slave side of the pseudo tty

ttyname
     Returns the name of the pseudo tty. On UNIX machines this will be the
     pathname of the device.

SEE ALSO
========

   See IO/Handle,

AUTHOR
======

   Graham Barr <`gbarr@ti.com'>

   Based on original Ptty module by Nick Ing-Simmons <`nik@tiuk.ti.com'>

COPYRIGHT
=========

   Most of the C code used in the XS file is covered by the GNU GENERAL
PUBLIC LICENSE, See COPYING

   All other code is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

IO:: interface for reading/writing a scalar
*******************************************

NAME
====

   IO::Scalar - IO:: interface for reading/writing a scalar

SYNOPSIS
========

   If you have any Perl5, you can use the basic OO interface...

     use IO::Scalar;

     ### Open a handle on a string:
     $SH = new IO::Scalar;
     $SH->open(\$somestring);

     ### Open a handle on a string, read it line-by-line, then close it:
     $SH = new IO::Scalar \$somestring;
     while ($_ = $SH->getline) { print "Line: $_" }
     $SH->close;

     ### Open a handle on a string, and slurp in all the lines:
     $SH = new IO::Scalar \$somestring;
     print $SH->getlines;

     ### Open a handle on a string, and append to it:
     $SH = new IO::Scalar \$somestring
     $SH->print("bar\n");        ### will add "bar\n" to the end

     ### Get the current position:
     $pos = $SH->getpos;         ### $SH->tell() also works

     ### Set the current position:
     $SH->setpos($pos);          ### $SH->seek(POS,WHENCE) also works

     ### Open an anonymous temporary scalar:
     $SH = new IO::Scalar;
     $SH->print("Hi there!");
     print "I got: ", ${$SH->sref}, "\n";      ### get at value

   If your Perl is 5.004 or later, you can use the TIEHANDLE interface,
and read/write scalars just like files:

     use IO::Scalar;

     ### Writing to a scalar...
     my $s;
     tie *OUT, 'IO::Scalar', \$s;
     print OUT "line 1\nline 2\n", "line 3\n";
     print "s is now... $s\n"

     ### Reading and writing an anonymous scalar...
     tie *OUT, 'IO::Scalar';
     print OUT "line 1\nline 2\n", "line 3\n";
     tied(OUT)->seek(0,0);
     while (<OUT>) { print "LINE: ", $_ }

   Stringification now works, too!

     my $SH = new IO::Scalar \$somestring;
     $SH->print("Hello, ");
     $SH->print("world!");
     print "I've got: <$SH>\n";

   You can also make the objects sensitive to the $/ setting, just like
IO::Handle wants them to be:

     my $SH = new IO::Scalar \$somestring;
     $SH->use_RS(1);           ### perlvar's short name for $/
     ...
     local $/ = "";            ### read paragraph-at-a-time
     $nextpar = $SH->getline;

DESCRIPTION
===========

   This class implements objects which behave just like FileHandle (or
IO::Handle) objects, except that you may use them to write to (or read
from) scalars.  They can be tiehandle'd as well.

   Basically, this:

     my $s;
     $SH = new IO::Scalar \$s;
     $SH->print("Hel", "lo, ");         # OO style
     $SH->print("world!\n");            # ditto

   Or this (if you have 5.004 or later):

     my $s;
     $SH = tie *OUT, 'IO::Scalar', \$s;
     print OUT "Hel", "lo, ";           # non-OO style
     print OUT "world!\n";              # ditto

   Or this (if you have 5.004 or later):

     my $s;
     $SH = IO::Scalar->new_tie(\$s);
     $SH->print("Hel", "lo, ");         # OO style...
     print $SH "world!\n";              # ...or non-OO style!

   Causes $s to be set to:

     "Hello, world!\n"

PUBLIC INTERFACE
================

Construction
------------

new [ARGS...]
     *Class method.* Return a new, unattached scalar handle.  If any
     arguments are given, they're sent to open().

open [SCALARREF]
     *Instance method.* Open the scalar handle on a new scalar, pointed to
     by SCALARREF.  If no SCALARREF is given, a "private" scalar is
     created to hold the file data.

     Returns the self object on success, undefined on error.

opened
     *Instance method.* Is the scalar handle opened on something?

close
     *Instance method.* Disassociate the scalar handle from its underlying
     scalar.  Done automatically on destroy.

Input and output
----------------

flush
     *Instance method.* No-op, provided for OO compatibility.

getc
     *Instance method.* Return the next character, or undef if none remain.

getline
     *Instance method.* Return the next line, or undef on end of string.
     Can safely be called in an array context.  Currently, lines are
     delimited by "\n".

getlines
     *Instance method.* Get all remaining lines.  It will croak() if
     accidentally called in a scalar context.

print ARGS...
     *Instance method.* Print ARGS to the underlying scalar.

     Warning: Currently, this always causes a "seek to the end of the
     string"; this may change in the future.

read BUF, NBYTES, [OFFSET]
     *Instance method.* Read some bytes from the scalar.  Returns the
     number of bytes actually read, 0 on end-of-file, undef on error.

write BUF, NBYTES, [OFFSET]
     *Instance method.* Write some bytes to the scalar.

sysread BUF, LEN, [OFFSET]
     *Instance method.* Read some bytes from the scalar.  Returns the
     number of bytes actually read, 0 on end-of-file, undef on error.

syswrite BUF, NBYTES, [OFFSET]
     *Instance method.* Write some bytes to the scalar.

Seeking/telling and other attributes
------------------------------------

autoflush
     *Instance method.* No-op, provided for OO compatibility.

binmode
     *Instance method.* No-op, provided for OO compatibility.

clearerr
     *Instance method.*  Clear the error and EOF flags.  A no-op.

eof
     *Instance method.*  Are we at end of file?

seek OFFSET, WHENCE
     *Instance method.*  Seek to a given position in the stream.

sysseek OFFSET, WHENCE
     *Instance method.* Identical to `seek OFFSET, WHENCE', *q.v.*

tell
     *Instance method.* Return the current position in the stream, as a
     numeric offset.

use_RS [YESNO]
     *Instance method.* Obey the curent setting of $/, like IO::Handle
     does?  Default is false.

setpos POS
     *Instance method.* Set the current position, using the opaque value
     returned by `getpos()'.

getpos
     *Instance method.* Return the current position in the string, as an
     opaque object.

sref
     *Instance method.* Return a reference to the underlying scalar.

VERSION
=======

   $Id: Scalar.pm,v 1.125 2001/02/23 09:46:22 eryq Exp $

AUTHORS
=======

Principal author
----------------

   Eryq (`eryq@zeegee.com').  President, ZeeGee Software Inc
(`http://www.zeegee.com').

Other contributors
------------------

   The full set of contributors always includes the folks mentioned in
`"CHANGE LOG"', see IO/Stringy.  But just the same, special
thanks to the following individuals for their invaluable contributions (if
I've forgotten or misspelled your name, please email me!):

   *Andy Glew,* for contributing `getc()'.

   *Brandon Browning,* for suggesting `opened()'.

   *David Richter,* for finding and fixing the bug in `PRINTF()'.

   *Eric L. Brine,* for his offset-using read() and write()
implementations.

   *Richard Jones,* for his patches to massively improve the performance
of `getline()' and add sysread and syswrite.

   *B. K. Oxley (binkley),* for stringification and inheritance
improvements, and sundry good ideas.

IO:: interface for reading/writing an array of scalars
******************************************************

NAME
====

   IO::ScalarArray - IO:: interface for reading/writing an array of scalars

SYNOPSIS
========

   If you have any Perl5, you can use the basic OO interface...

     use IO::ScalarArray;

     # Open a handle on an array-of-scalars:
     $AH = new IO::ScalarArray;
     $AH->open(\@a);

     # Open a handle on an array-of-scalars, read it line-by-line,
     # then close it:
     $AH = new IO::ScalarArray \@a;
     while ($_ = $AH->getline) { print "Line: $_" }
     $AH->close;

     # Open a handle on an array-of-scalars, and slurp in all the lines:
     $AH = new IO::ScalarArray \@a;
     print $AH->getlines;

     # Open a handle on an array-of-scalars, and append to it:
     $AH = new IO::ScalarArray \@a;
     $AH->print("bar\n");
     print "some string is now: ", $somestring, "\n";

     # Get the current position:
     $pos = $AH->getpos;         ### $AH->tell() also works

     # Set the current position:
     $AH->setpos($pos);          ### $AH->seek(POS,WHENCE) also works

     # Open an anonymous temporary scalar array:
     $AH = new IO::ScalarArray;
     $AH->print("Hi there!\nHey there!\n");
     $AH->print("Ho there!\n");
     print "I got: ", @{$AH->aref}, "\n";      ### get at value

   If your Perl is 5.004 or later, you can use the TIEHANDLE interface,
and read/write as array-of-scalars just like files:

     use IO::ScalarArray;

     # Writing to a scalar array...
     my @a;
     tie *OUT, 'IO::ScalarArray', \@a;
     print OUT "line 1\nline 2\n", "line 3\n";
     print "s is now... [", join('', @a), "]\n";

     # Reading and writing an anonymous scalar array...
     tie *OUT, 'IO::ScalarArray';
     print OUT "line 1\nline 2\n", "line 3\n";
     tied(OUT)->seek(0,0);
     while (<OUT>) { print "LINE: ", $_ }

DESCRIPTION
===========

   This class implements objects which behave just like FileHandle (or
IO::Handle) objects, except that you may use them to write to (or read
from) scalars.  They can be tiehandle'd as well.

   For writing large amounts of data with individual print() statements,
this is likely to be more efficient than IO::Scalar.

   Basically, this:

     my @a;
     $AH = new IO::ScalarArray \@a;
     $AH->print("Hel", "lo, ");
     $AH->print("world!\n");

   Or this (if you have 5.004 or later):

     my @a;
     $AH = tie *OUT, 'IO::ScalarArray', \@a;
     print OUT "Hel", "lo, ";
     print OUT "world!\n";

   Causes @a to be set to the following arrayt of 3 strings:

     ( "Hel" ,
       "lo, " ,
       "world!\n" )

   Compare this with IO::Scalar.

PUBLIC INTERFACE
================

Construction
------------

new [ARGS...]
     *Class method.* Return a new, unattached array handle.  If any
     arguments are given, they're sent to open().

open [ARRAYREF]
     *Instance method.* Open the array handle on a new array, pointed to
     by ARRAYREF.  If no ARRAYREF is given, a "private" array is created
     to hold the file data.

     Returns the self object on success, undefined on error.

opened
     *Instance method.* Is the array handle opened on something?

close
     *Instance method.* Disassociate the array handle from its underlying
     array.  Done automatically on destroy.

Input and output
----------------

flush
     *Instance method.* No-op, provided for OO compatibility.

getc
     *Instance method.* Return the next character, or undef if none remain.
     This does a read(1), which is somewhat costly.

getline
     *Instance method.* Return the next line, or undef on end of data.
     Can safely be called in an array context.  Currently, lines are
     delimited by "\n".

getlines
     *Instance method.* Get all remaining lines.  It will croak() if
     accidentally called in a scalar context.

print ARGS...
     *Instance method.* Print ARGS to the underlying array.

     Currently, this always causes a "seek to the end of the array" and
     generates a new array entry.  This may change in the future.

read BUF, NBYTES, [OFFSET];
     *Instance method.* Read some bytes from the array.  Returns the
     number of bytes actually read, 0 on end-of-file, undef on error.

write BUF, NBYTES, [OFFSET];
     *Instance method.* Write some bytes into the array.

Seeking/telling and other attributes
------------------------------------

autoflush
     *Instance method.* No-op, provided for OO compatibility.

binmode
     *Instance method.* No-op, provided for OO compatibility.

clearerr
     *Instance method.*  Clear the error and EOF flags.  A no-op.

eof
     *Instance method.*  Are we at end of file?

seek POS,WHENCE
     *Instance method.* Seek to a given position in the stream.  Only a
     WHENCE of 0 (SEEK_SET) is supported.

tell
     *Instance method.* Return the current position in the stream, as a
     numeric offset.

setpos POS
     *Instance method.* Seek to a given position in the array, using the
     opaque getpos() value.  Don't expect this to be a number.

getpos
     *Instance method.* Return the current position in the array, as an
     opaque value.  Don't expect this to be a number.

aref
     *Instance method.* Return a reference to the underlying array.

VERSION
=======

   $Id: ScalarArray.pm,v 1.117 2000/09/28 06:32:28 eryq Exp $

AUTHOR
======

Principal author
----------------

   Eryq (`eryq@zeegee.com').  President, ZeeGee Software Inc
(`http://www.zeegee.com').

Other contributors
------------------

   Thanks to the following individuals for their invaluable contributions
(if I've forgotten or misspelled your name, please email me!):

   *Andy Glew,* for suggesting `getc()'.

   *Brandon Browning,* for suggesting `opened()'.

   *Eric L. Brine,* for his offset-using read() and write()
implementations.

supply seek based methods for I/O objects
*****************************************

NAME
====

   IO::Seekable - supply seek based methods for I/O objects

SYNOPSIS
========

     use IO::Seekable;
     package IO::Something;
     @ISA = qw(IO::Seekable);

DESCRIPTION
===========

   IO::Seekable does not have a constuctor of its own as is intended to be
inherited by other IO::Handle based objects. It provides methods which
allow seeking of the file descriptors.

   If the C functions fgetpos() and fsetpos() are available, then
`$io-<getpos' returns an opaque value that represents the current position
of the IO::File, and `$io->setpos(POS)' uses that value to return to a
previously visited position.

   See Perlfunc (perl.info), for complete descriptions of
each of the following supported IO::Seekable methods, which are just front
ends for the corresponding built-in functions:

     $io->seek( POS, WHENCE )
     $io->sysseek( POS, WHENCE )
     $io->tell

SEE ALSO
========

   See Perlfunc (perl.info), `"I', see Perlop (perl.info),
`"I', see IO/Handle, `"I', see IO/File,

HISTORY
=======

   Derived from FileHandle.pm by Graham Barr <gbarr@pobox.com>

OO interface to the select system call
**************************************

NAME
====

   IO::Select - OO interface to the select system call

SYNOPSIS
========

     use IO::Select;

     $s = IO::Select->new();

     $s->add(\*STDIN);
     $s->add($some_handle);

     @ready = $s->can_read($timeout);

     @ready = IO::Select->new(@handles)->read(0);

DESCRIPTION
===========

   The IO::Select package implements an object approach to the system
select function call. It allows the user to see what IO handles, see
IO/Handle, are ready for reading, writing or have an error
condition pending.

CONSTRUCTOR
===========

new ( [ HANDLES ] )
     The constructor creates a new object and optionally initialises it
     with a set of handles.

METHODS
=======

add ( HANDLES )
     Add the list of handles to the IO::Select object. It is these values
     that will be returned when an event occurs. IO::Select keeps these
     values in a cache which is indexed by the fileno of the handle, so if
     more than one handle with the same fileno is specified then only the
     last one is cached.

     Each handle can be an IO::Handle object, an integer or an array
     reference where the first element is a IO::Handle or an integer.

remove ( HANDLES )
     Remove all the given handles from the object. This method also works
     by the fileno of the handles. So the exact handles that were added
     need not be passed, just handles that have an equivalent fileno

exists ( HANDLE )
     Returns a true value (actually the handle itself) if it is present.
     Returns undef otherwise.

handles
     Return an array of all registered handles.

can_read ( [ TIMEOUT ] )
     Return an array of handles that are ready for reading. TIMEOUT is the
     maximum amount of time to wait before returning an empty list. If
     TIMEOUT is not given and any handles are registered then the call
     will block.

can_write ( [ TIMEOUT ] )
     Same as can_read except check for handles that can be written to.

has_exception ( [ TIMEOUT ] )
     Same as can_read except check for handles that have an exception
     condition, for example pending out-of-band data.

count ()
     Returns the number of handles that the object will check for when one
     of the `can_' methods is called or the object is passed to the select
     static method.

bits()
     Return the bit string suitable as argument to the core select() call.

select ( READ, WRITE, ERROR [, TIMEOUT ] )
     select is a static method, that is you call it with the package name
     like new. READ, WRITE and ERROR are either undef or IO::Select
     objects. TIMEOUT is optional and has the same effect as for the core
     select call.

     The result will be an array of 3 elements, each a reference to an
     array which will hold the handles that are ready for reading, writing
     and have error conditions respectively. Upon error an empty array is
     returned.

EXAMPLE
=======

   Here is a short example which shows how IO::Select could be used to
write a server which communicates with several sockets while also
listening for more connections on a listen socket

     use IO::Select;
     use IO::Socket;

     $lsn = new IO::Socket::INET(Listen => 1, LocalPort => 8080);
     $sel = new IO::Select( $lsn );

     while(@ready = $sel->can_read) {
         foreach $fh (@ready) {
             if($fh == $lsn) {
                 # Create a new socket
                 $new = $lsn->accept;
                 $sel->add($new);
             }
             else {
                 # Process socket

     # Maybe we have finished with the socket
     $sel->remove($fh);
     $fh->close;
                 }
             }
         }

AUTHOR
======

   Graham Barr <`gbarr@pobox.com'>

COPYRIGHT
=========

   Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl extension that implements the sendfile() interface.
********************************************************

NAME
====

   IO::SendFile - Perl extension that implements the sendfile() interface.

SYNOPSIS
========

     use IO::SendFile;
     IO::SendFile::sendfile( fileno(OUT), fileno(IN), $offset, $count );
     # Send file everything from filehandle IN from offset
     # $offset and send $count bytes.

     use IO::SendFile qw( sendfile ); # import the senfile function
     sendfile( fileno(OUT), fileno(IN), $offset, $count );

DESCRIPTION
===========

   IO::SendFile implements the sendfile() function call.  This version
only works on linux.

   IO::SendFile is released under the same conditions as perl itself.

AUTHOR
======

   Arnar M. Hrafnkelsson, addi@umich.edu

SEE ALSO
========

   perl(1).  sendfile(2).

Perl extension for TCP urgent data
**********************************

NAME
====

   IO::Sockatmark - Perl extension for TCP urgent data

SYNOPSIS
========

     use IO::Sockatmark;
     use IO::Socket;

     my $sock = IO::Socket::INET->new('some_server');
     $sock->read(1024,$data) until $sock->atmark;

DESCRIPTION
===========

   This module adds the atmark() method to the standard IO::Socket class.
This can be used to detect the "mark" created by the receipt of TCP urgent
data.

Methods
-------

$flag = $socket->atmark()
     The atmark() method true if the socket is currently positioned at the
     urgent data mark, false otherwise.

Exported functions
------------------

$flag = sockatmark($socket)
     The atmark() function returns true if the socket is currently
     positioned at the urgent data mark, false otherwise.  This will work
     with an IO::Socket object, as well as with a conventional filehandle
     socket.

CAVEATS
=======

   This module is critically dependent on the system ioctl() constant
SIOCATMARK, which is located in different places on different systems.
The module compiles and works correctly on Linux, Solaris and Tru64 Unix
systems, but probably needs tweaking to compile on others.  Please send
patches.

AUTHOR
======

   Copyright 2001, Lincoln Stein <lstein@cshl.org>.

   This module is distributed under the same terms as Perl itself.  Feel
free to use, modify and redistribute it as long as you retain the correct
attribution.

SEE ALSO
========

   perl(1), IO::Socket(3)

Object interface to socket communications
*****************************************

NAME
====

   IO::Socket - Object interface to socket communications

SYNOPSIS
========

     use IO::Socket;

DESCRIPTION
===========

   IO::Socket provides an object interface to creating and using sockets.
It is built upon the IO/Handle, interface and inherits
all the methods defined by IO/Handle.

   IO::Socket only defines methods for those operations which are common
to all types of socket. Operations which are specified to a socket in a
particular domain have methods defined in sub classes of IO::Socket

   IO::Socket will export all functions (and constants) defined by
Socket.

CONSTRUCTOR
===========

new ( [ARGS] )
     Creates an IO::Socket, which is a reference to a newly created symbol
     (see the Symbol package). new optionally takes arguments, these
     arguments are in key-value pairs.  new only looks for one key Domain
     which tells new which domain the socket will be in. All other
     arguments will be passed to the configuration method of the package
     for that domain, See below.

          NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE

          As of VERSION 1.18 all IO::Socket objects have autoflush turned on
          by default. This was not the case with earlier releases.

          NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE

METHODS
=======

   See Perlfunc (perl.info), for complete descriptions of
each of the following supported IO::Socket methods, which are just front
ends for the corresponding built-in functions:

     socket
     socketpair
     bind
     listen
     accept
     send
     recv
     peername (getpeername)
     sockname (getsockname)
     shutdown

   Some methods take slightly different arguments to those defined in
Perlfunc (perl.info), in attempt to make the interface more
flexible. These are

accept([PKG])
     perform the system call accept on the socket and return a new object.
     The new object will be created in the same class as the listen
     socket, unless `PKG' is specified. This object can be used to
     communicate with the client that was trying to connect. In a scalar
     context the new socket is returned, or undef upon failure. In an
     array context a two-element array is returned containing the new
     socket and the peer address, the list will be empty upon failure.

     Additional methods that are provided are

timeout([VAL])
     Set or get the timeout value associated with this socket. If called
     without any arguments then the current setting is returned. If called
     with an argument the current setting is changed and the previous
     value returned.

sockopt(OPT [, VAL])
     Unified method to both set and get options in the SOL_SOCKET level.
     If called with one argument then getsockopt is called, otherwise
     setsockopt is called.

sockdomain
     Returns the numerical number for the socket domain type. For example,
     for a AF_INET socket the value of &AF_INET will be returned.

socktype
     Returns the numerical number for the socket type. For example, for a
     SOCK_STREAM socket the value of &SOCK_STREAM will be returned.

protocol
     Returns the numerical number for the protocol being used on the
     socket, if known. If the protocol is unknown, as with an AF_UNIX
     socket, zero is returned.

connected
     If the socket is in a connected state the the peer address is
     returned.  If the socket is not in a connected state then undef will
     be returned.

SEE ALSO
========

   See Socket, IO/Handle,
IO/Socket/INET, IO/Socket/UNIX,

AUTHOR
======

   Graham Barr <`gbarr@pobox.com'>

COPYRIGHT
=========

   Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Object interface for AF_INET domain sockets
*******************************************

NAME
====

   IO::Socket::INET - Object interface for AF_INET domain sockets

SYNOPSIS
========

     use IO::Socket::INET;

DESCRIPTION
===========

   IO::Socket::INET provides an object interface to creating and using
sockets in the AF_INET domain. It is built upon the IO/Socket,
interface and inherits all the methods defined by
IO/Socket.

CONSTRUCTOR
===========

new ( [ARGS] )
     Creates an IO::Socket::INET object, which is a reference to a newly
     created symbol (see the Symbol package). new optionally takes
     arguments, these arguments are in key-value pairs.

     In addition to the key-value pairs accepted by IO/Socket,
     IO::Socket::INET provides.

          PeerAddr	Remote host address          <hostname>[:<port>]
          PeerHost	Synonym for PeerAddr
          PeerPort	Remote port or service       <service>[(<no>)] | <no>
          LocalAddr	Local host bind	address      hostname[:port]
          LocalHost	Synonym for LocalAddr
          LocalPort	Local host bind	port         <service>[(<no>)] | <no>
          Proto	Protocol name (or number)    "tcp" | "udp" | ...
          Type	Socket type                  SOCK_STREAM | SOCK_DGRAM | ...
          Listen	Queue size for listen
          Reuse	Set SO_REUSEADDR before binding
          Timeout	Timeout	value for various operations
          MultiHomed  Try all adresses for multi-homed hosts

     If Listen is defined then a listen socket is created, else if the
     socket type, which is derived from the protocol, is SOCK_STREAM then
     connect() is called.

     Although it is not illegal, the use of `MultiHomed' on a socket which
     is in non-blocking mode is of little use. This is because the first
     connect will never fail with a timeout as the connaect call will not
     block.

     The `PeerAddr' can be a hostname or the IP-address on the
     "xx.xx.xx.xx" form.  The `PeerPort' can be a number or a symbolic
     service name.  The service name might be followed by a number in
     parenthesis which is used if the service is not known by the system.
     The `PeerPort' specification can also be embedded in the `PeerAddr'
     by preceding it with a ":".

     If Proto is not given and you specify a symbolic `PeerPort' port,
     then the constructor will try to derive Proto from the service name.
     As a last resort Proto "tcp" is assumed.  The Type parameter will be
     deduced from Proto if not specified.

     If the constructor is only passed a single argument, it is assumed to
     be a `PeerAddr' specification.

     Examples:

          $sock = IO::Socket::INET->new(PeerAddr => 'www.perl.org',
                                        PeerPort => 'http(80)',
                                        Proto    => 'tcp');

          $sock = IO::Socket::INET->new(PeerAddr => 'localhost:smtp(25)');

          $sock = IO::Socket::INET->new(Listen    => 5,
                                        LocalAddr => 'localhost',
                                        LocalPort => 9000,
                                        Proto     => 'tcp');

          $sock = IO::Socket::INET->new('127.0.0.1:25');

          NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE

          As of VERSION 1.18 all IO::Socket objects have autoflush turned on
          by default. This was not the case with earlier releases.

          NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE

METHODS
-------

sockaddr ()
     Return the address part of the sockaddr structure for the socket

sockport ()
     Return the port number that the socket is using on the local host

sockhost ()
     Return the address part of the sockaddr structure for the socket in a
     text form xx.xx.xx.xx

peeraddr ()
     Return the address part of the sockaddr structure for the socket on
     the peer host

peerport ()
     Return the port number for the socket on the peer host.

peerhost ()
     Return the address part of the sockaddr structure for the socket on
     the peer host in a text form xx.xx.xx.xx

SEE ALSO
========

   See Socket, IO/Socket,

AUTHOR
======

   Graham Barr <`gbarr@pobox.com'>

COPYRIGHT
=========

   Copyright (c) 1996-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Send and receive multicast messages
***********************************

NAME
====

   IO::Socket::Multicast - Send and receive multicast messages

SYNOPSIS
========

     use IO::Socket::Multicast;

     # create a new UDP socket ready to read datagrams on port 1100
     my $s = IO::Socket::Multicast->new(LocalPort=>1100);

     # Add a multicast group
     $s->mcast_add('225.0.1.1');

     # Add a multicast group to eth0 device
     $s->mcast_add('225.0.0.2','eth0');

     # now receive some multicast data
     $s->recv($data,1024);

     # Drop a multicast group
     $s->mcast_drop('225.0.0.1');

     # Set outgoing interface to eth0
     $s->mcast_if('eth0');

     # Set time to live on outgoing multicast packets
     $s->ttl(10);

     # Turn off loopbacking
     $s->loopback(0);

     # Multicast a message to group 225.0.0.1
     $s->mcast_send('hello world!','225.0.0.1:1200');
     $s->mcast_set('225.0.0.2:1200');
     $s->mcast_send('hello again!');

DESCRIPTION
===========

   The IO::Socket::Multicast module subclasses IO::Socket::INET to enable
you to manipulate multicast groups.  With this module (and an operating
system that supports multicasting), you will be able to receive incoming
multicast transmissions and generate your own outgoing multicast packets.

   This module requires IO::Interface version 0.94 or higher.

INTRODUCTION
------------

   Multicasting is designed for streaming multimedia applications and for
conferencing systems in which one transmitting machines needs to
distribute data to a large number of clients.

   IP addresses in the range 224.0.0.0 and 239.255.255.255 are reserved
for multicasting.  These addresses do not correspond to individual
machines, but to multicast groups.  Messages sent to these addresses will
be delivered to a potentially large number of machines that have
registered their interest in receiving transmissions on these groups.
They work like TV channels.  A program tunes in to a multicast group to
receive transmissions to it, and tunes out when it no longer wishes to
receive the transmissions.

   To receive transmissions from a multicast group, you will use
IO::Socket::INET->new() to create a UDP socket and bind it to a local
network port.  You will then subscribe one or more multicast groups using
the mcast_add() method.  Subsequent calls to the standard recv() method
will now receive messages incoming messages transmitted to the subscribed
groups using the selected port number.

   To send transmissions to a multicast group, you can use the standard
send() method to send messages to the multicast group and port of your
choice.  The mcast_set() and mcast_send() methods are provided as
convenience functions.  Mcast_set() will set a default multicast
destination for messages which you then send with mcast_send().

   To set the number of hops (routers) that outgoing multicast messages
will cross, call mcast_ttl().  To activate or deactivate the looping back
of multicast messages (in which a copy of the transmitted messages is
received by the local machine), call mcast_loopback().

CONSTRUCTORS
------------

$socket = IO::Socket::Multicast->new(LocalPort=>$port)
     The new() method is the constructor for the IO::Socket::Multicast
     class.  It takes the same arguments as IO::Socket::INET, except that
     the Proto argument, rather than defaulting to "tcp", will default to
     "udp", which is more appropriate for multicasting.

     To create a UDP socket suitable for sending outgoing multicast
     messages, call new() without no arguments (or with `Proto=>'udp'').
     To create a UDP socket that can also receive incoming multicast
     transmissions on a specific port, call new() with the LocalPort
     argument.

METHODS
-------

$success = $socket->mcast_add($multicast_address [,$interface])
     The mcast_add() method will add the provided multicast address to the
     list of subscribed multicast groups.  The address may be provided
     either as a dotted-quad decimal, or as a packed IP address (such as
     produced by the inet_aton() function).  On success, the method will
     return a true value.

     The optional $interface argument can be used to specify on which
     network interface to listen for incoming multicast messages.  If the
     IO::Interface module is installed, you may use the device name for the
     interface (e.g. "tu0").  Otherwise, you must use the IP address of the
     desired network interface.  Either dotted quad form or packed IP
     address is acceptable.  If no interface is specified, then the
     multicast group is joined on INADDR_ANY, meaning that multicast
     transmissions received on any of the host's network interfaces will
     be forwarded to the socket.

$success = $socket->mcast_drop($multicast_address)
     This reverses the action of mcast_add(), removing the indicated
     multicast address from the list of subscribed groups.

$loopback = $socket->mcast_loopback
$previous = $socket->mcast_loopback($new)
     The mcast_loopback() method controls whether the socket will receive
     its own multicast transmissions (default yes).  Called without
     arguments, the method returns the current state of the loopback flag.
     Called with a boolean argument, the method will set the loopback
     flag, and return its previous value.

$ttl = $socket->mcast_ttl
$previous = $socket->mcast_ttl($new)
     The mcast_ttl() method examines or sets the time to live (TTL) for
     outgoing multicast messages.  The TTL controls the numbers of routers
     the packet can cross before being expired.  The default TTL is 1,
     meaning that the message is confined to the local area network.
     Values between 0 and 255 are valid.

     Called without arguments, this method returns the socket's current
     TTL.  Called with a value, this method sets the TTL and returns its
     previous value.

$interface = $socket->mcast_if
$previous = $socket->mcast_if($new)
     By default, the OS will pick the network interface to use for outgoing
     multicasts automatically.  You can control this process by using the
     mcast_if() method to set the outgoing network interface explicitly.
     Called without arguments, returns the current interface.  Called with
     the name of an interface, sets the outgoing interface and returns its
     previous value.

     You can use the device name for the interface (e.g. "tu0") if the
     IO::Interface module is present.  Otherwise, you must use the
     interface's dotted IP address.

     NOTE: To set the interface used for *incoming* multicasts, use the
     mcast_add() method.

$dest = $socket->mcast_dest
$previous = $socket->mcast_dest($new)
     The mcast_dest() method is a convenience function that allows you to
     set the default destination group for outgoing multicasts.  Called
     without arguments, returns the current destination as a packed binary
     sockaddr_in data structure.  Called with a new destination address,
     the method sets the default destination and returns the previous one,
     if any.

     Destination addresses may be provided as packed sockaddr_in
     structures, or in the form "XX.XX.XX.XX:YY" where the first part is
     the IP address, and the second the port number.

$bytes = $socket->mcast_send($data [,$dest])
     Mcast_send() is a convenience function that simplifies the sending of
     multicast messages.  $data is the message contents, and $dest is an
     optional destination group.  You can use either the dotted IP form of
     the destination address and its port number, or a packed sockaddr_in
     structure.  If the destination is not supplied, it will default to
     the most recent value set in mcast_dest() or a previous call to
     mcast_send().

     The method returns the number of bytes successfully queued for
     delivery.

     As a side-effect, the method will call mcast_dest() to remember the
     destination address.

     Example:

          $socket->mcast_send('Hi there group members!','225.0.1.1:1900') || die;
          $socket->mcast_send("How's the weather?") || die;

     Note that you may still call IO::Socket::INET->new() with a
     *PeerAddr*, and IO::Socket::INET will perform a connect(), creating a
     default destination for calls to send().

EXAMPLE
=======

   The following is an example of a multicast server.  Every 10 seconds it
transmits the current time and the list of logged-in users to the local
network using multicast group 226.1.1.2, port 2000 (these are chosen
arbitrarily).

     #!/usr/bin/perl
     # server
     use strict;
     use IO::Socket::Multicast;

     use constant DESTINATION => '226.1.1.2:2000';
     my $sock = IO::Socket::INET->new(Proto=>'udp',PeerAddr=>DESTINATION);

     while (1) {
       my $message = localtime;
       $message .= "\n" . `who`;
       $sock->send($message) || die "Couldn't send: $!";
     } continue {
       sleep 10;
     }

   This is the corresponding client.  It listens for transmissions on
group 226.1.1.2, port 2000, and echoes the messages to standard output.

     #!/usr/bin/perl
     # client

     use strict;
     use IO::Socket::Multicast;

     use constant GROUP => '226.1.1.2';
     use constant PORT  => '2000';

     my $sock = IO::Socket::INET->new(Proto=>'udp',LocalPort=>PORT);
     $sock->mcast_add(GROUP) || die "Couldn't set group: $!\n";

     while (1) {
       my $data;
       next unless $sock->recv($data,1024);
       print $data;
     }

EXPORT
------

   None by default.  However, if you wish to call mcast_add(),
mcast_drop(), mcast_if(), mcast_loopback(), mcast_ttl, mcast_dest() and
mcast_send() as functions you may import them explicitly on the use line
or by importing the tag ":functions".

BUGS
----

   The mcast_if(), mcast_ttl() and mcast_loopback() methods will cause a
crash on versions of Linux earlier than 2.2.0 because of a kernel bug in
the implementation of the multicast socket options.

AUTHOR
======

   Lincoln Stein, lstein@cshl.org.

   This module is distributed under the same terms as Perl itself.

SEE ALSO
========

   perl(1), IO::Socket(3), IO::Socket::INET(3).

a SSL socket interface class
****************************

NAME
====

   IO::Socket::SSL - a SSL socket interface class

SYNOPSIS
========

   use IO::Socket::SSL;

DESCRIPTION
===========

   IO::Socket::SSL is a class implementing an object oriented interface to
SSL sockets. The class is a descendent of IO::Socket::INET and provides a
subset of the base class's interface methods as well as SSL specific
methods.

SUPPORTED INTERFACE
===================

   The following methods from the IO::Socket::INET interface are
supported, unimplemented and unsupported respectively:

supported methods
     IO::Socket::INET interface: new, close, fileno, opened, flush,
     socket, socketpair, bind, listen, peername, sockname, timeout,
     sockopt, sockdomain, socktype, protocol, sockaddr, sockport,
     sockhost, peeraddr, peerport, peerhost, sysread, syswrite, read,
     write, DESTROY, accept, connect, print, printf;

     others: context_init, get_cipher, get_peer_certificate;

unimplemented methods
     getline, getlines, fdopen, untaint, error, clearerr, send, recv;

unsupported methods
     getc, eof, truncate, stat, ungetc, setbuf, setvbuf, <$fh>.

CLASS VARIABLES
===============

IO::Socket::SSL::DEBUG
METHODS
=======

context_init ( [ARGS] )
-----------------------

   This class method is used for initializing and setting the global SSL
settings. The following following arguments are supported:

SSL_server
     This option must be used when a SSL_Context is explicitly created for
     server contexts.

SSL_use_cert
     With server sockets a server certificate is always used. For client
     sockets certificate use is optional. This attribute is set to true if
     a certificate is to be used.

SSL_verify_mode
     Type of verification process which is to be performed upon a peer
     certificate. This can be a combination of 0x00 (don't verify), 0x01
     (verify peer), 0x02 (fail verification if there's no peer
     certificate), and 0x04 (verify client once). Default: verify peer.

SSL_key_file
     Filename of the PEM encoded private key file. Default:
     "certs/server-key.pem" or "certs/client-key.pem".

SSL_cert_file
     Filename of the PEM encoded certificate file. Default:
     "certs/server-cert.pem" or "certs/client-cert.pem".

SSL_ca_path
     Pathname to the Certicate Authority certificate directory. If server
     or client certificates are to be verified the trusted CA certificates
     have to reside in this directory. The CA certificate filename that is
     used for finding the certificate is a hash value generated from the
     certificate with a .<serial number> suffix appended to it. The hash
     value can be obtained with the command line: ssleay x509 -hash <
     ca-cert.pem.

SSL_ca_file
     Filename of the CA certificate.

new ( [ARGS] )
--------------

   See IO::Socket::INET constructor's documentation for details. The
following additional per connection SSL options are supported:

SSL_verify_mode
     See above.

SSL_cipher_list
     A list of allowed ciphers. The list is in string form. See
     http://www.modssl.org/docs/2.3/ssl_reference.html#ToC9.

get_cipher
----------

   Get a string representation of the used cipher.

get_peer_certificate
--------------------

   Obtain a reference to the X509_Certificate object representing peer's
certificate.

RELATED CLASSES
===============

   These are internal classes with which the IO::Socket::SSL API user
usually doesn't have to be concerned with.

SSL_Context
-----------

   Encapsulates global SSL options.

METHODS
-------

new ( [ARGS] )
     See context_init arguments.

DESTROY
SSL_SSL
-------

   Encapsulates per connection SSL options.

METHODS
-------

new ( [ARGS] )
DESTROY
X509_Certificate
----------------

   Encapsulates X509 certificate information.

METHODS
-------

subject_name
     Returns a stringified representation of subject's name.

issuer_name
     Returns a stringified representation of issuer's name.

EXAMPLES
========

   See demo and t directories.

RESTRICTIONS
============

   Currently, the IO::Socket::INET interface as implemented by this
package is not quite complete. There can be only one SSL context at a
given time.

SEE ALSO
========

   IO::Socket::INET.

ACKNOWLEDGEMENTS
================

   This package has benefited from the work and help of Gisle Aas and
Sampo Kellomäki.

COPYRIGHT
=========

   Copyright 1999, Marko Asplund

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Object interface for AF_UNIX domain sockets
*******************************************

NAME
====

   IO::Socket::UNIX - Object interface for AF_UNIX domain sockets

SYNOPSIS
========

     use IO::Socket::UNIX;

DESCRIPTION
===========

   IO::Socket::UNIX provides an object interface to creating and using
sockets in the AF_UNIX domain. It is built upon the IO/Socket,
interface and inherits all the methods defined by
IO/Socket.

CONSTRUCTOR
===========

new ( [ARGS] )
     Creates an IO::Socket::UNIX object, which is a reference to a newly
     created symbol (see the Symbol package). new optionally takes
     arguments, these arguments are in key-value pairs.

     In addition to the key-value pairs accepted by IO/Socket,
     IO::Socket::UNIX provides.

          Type    	Type of socket (eg SOCK_STREAM or SOCK_DGRAM)
          Local   	Path to local fifo
          Peer    	Path to peer fifo
          Listen  	Create a listen socket

     If the constructor is only passed a single argument, it is assumed to
     be a `Peer' specification.

          NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE

          As of VERSION 1.18 all IO::Socket objects have autoflush turned on
          by default. This was not the case with earlier releases.

          NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE

METHODS
=======

hostpath()
     Returns the pathname to the fifo at the local end

peerpath()
     Returns the pathanme to the fifo at the peer end

SEE ALSO
========

   See Socket, IO/Socket,

AUTHOR
======

   Graham Barr <`gbarr@pobox.com'>

COPYRIGHT
=========

   Copyright (c) 1996-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Emulate IO::File interface for in-core strings
**********************************************

NAME
====

   IO::String - Emulate IO::File interface for in-core strings

SYNOPSIS
========

     use IO::String;
     $io = IO::String->new;
     $io = IO::String->new($var);
     tie *IO, 'IO::String';

     # read data
     <$io>;
     $io->getline;
     read($io, $buf, 100);

     # write data
     print $io "string\n";
     $io->print(@data);
     syswrite($io, $buf, 100);

     select $io;
     printf "Some text %s\n", $str;

     # seek
     $pos = $io->getpos;
     $io->setpos(0);        # rewind
     $io->seek(-30, -1);

DESCRIPTION
===========

   The `IO::String' module provide the IO::File interface for in-core
strings.  An `IO::String' object can be attached to a string, and will
make it possible to use the normal file operations for reading or writing
data, as well as seeking to various locations of the string.  The main
reason you might want to do this, is if you have some other library module
that only provide an interface to file handles, and you want to keep all
the stuff in memory.

   The `IO::String' module provide an interface compatible with IO::File
as distributed with `IO-1.20', but the following methods are not
available; new_from_fd, fdopen, format_write, format_page_number,
format_lines_per_page, format_lines_left, format_name, format_top_name.

   The following methods are specific for the `IO::String' class:

$io = IO::String->new( [$string] )
     The constructor returns a newly created `IO::String' object.  It
     takes an optional argument which is the string to read from or write
     into.  If no $string argument is given, then an internal buffer
     (initially empty) is allocated.

     The `IO::String' object returned will be tied to itself.  This means
     that you can use most perl IO builtins on it too; readline, <>, getc,
     print, printf, syswrite, sysread, close.

$io->open( [$string] )
     Attach an existing IO::String object to some other $string, or
     allocate a new internal buffer (if no argument is given).  The
     position is reset back to 0.

$io->string_ref
     This method will return a reference to the string that is attached to
     the `IO::String' object.  Most useful when you let the `IO::String'
     create an internal buffer to write into.

$io->pad( [$char] )
     The pad() method makes it possible to specify the padding to use if
     the string is extended by either the seek() or truncate() methods.  It
     is a single character and defaults to "\0".

$io->pos( [$newpos] )
     Yet another interface for reading and setting the current read/write
     position within the string (the normal getpos/setpos/tell/seek
     methods are also available).  The pos() method will always return the
     old position, and if you pass it an argument it will set the new
     position.

     There is (deliberately) a difference between the setpos() and seek()
     methods in that seek() will extend the string (with the specified
     padding) if you go to a location past the end, while setpos() will
     just snap back to the end.  If truncate() is used to extend the
     string, then it works as seek().

   One more difference compared to IO::Handle, is that the write() and
syswrite() methods allow the length argument to be left out.

BUGS
====

   The perl TIEHANDLE interface is still not complete.  There are quite a
few file operations that will not yet invoke any method on the tied
object.  See Perltie (perl.info), for details.

SEE ALSO
========

   See IO/File, IO/Stringy,

COPYRIGHT
=========

   Copyright 1998-2000 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

stringy - I/O on in-core objects like strings and arrays
********************************************************

NAME
====

   IO-stringy - I/O on in-core objects like strings and arrays

SYNOPSIS
========

     IO::
     ::AtomicFile   adpO  Write a file which is updated atomically     ERYQ
     ::Lines        bdpO  I/O handle to read/write to array of lines   ERYQ
     ::Scalar       RdpO  I/O handle to read/write to a string         ERYQ
     ::ScalarArray  RdpO  I/O handle to read/write to array of scalars ERYQ
     ::Wrap         RdpO  Wrap old-style FHs in standard OO interface  ERYQ
     ::WrapTie      adpO  Tie your handles & retain full OO interface  ERYQ

DESCRIPTION
===========

   This toolkit primarily provides modules for performing both traditional
and object-oriented i/o) on things other than normal filehandles; in
particular, `IO::Scalar|IO::Scalar' in this node,
`IO::ScalarArray|IO::ScalarArray' in this node, and `IO::Lines|IO::Lines'
in this node.

   If you have access to tie(), these classes will make use of the
`IO::WrapTie|IO::WrapTie' in this node module to inherit a convenient
new_tie() constructor.  It also exports a nice wraptie() function.

   In the more-traditional IO::Handle front, we have
`IO::AtomicFile|IO::AtomicFile' in this node which may be used to
painlessly create files which are updated atomically.

   And in the "this-may-prove-useful" corner, we have `IO::Wrap|IO::Wrap'
in this node, whose exported wraphandle() function will clothe anything
that's not a blessed object in an IO::Handle-like wrapper... so you can
just use OO syntax and stop worrying about whether your function's caller
handed you a string, a globref, or a FileHandle.

INSTALLATION
============

   Most of you already know the drill...

     perl Makefile.PL
     make test
     make install

   For everyone else out there...  if you've never installed Perl code
before, or you're trying to use this in an environment where your sysadmin
or ISP won't let you do interesting things, *relax:* since this module
contains no binary extensions, you can cheat.  That means copying the
directory tree under my "./lib" directory into someplace where your script
can "see" it.  For example, under Linux:

     cp -r IO-stringy-1.234/lib/* /path/to/my/perl/

     Now, in your Perl code, do this:

     use lib "/path/to/my/perl";
     use IO::Scalar;                   ### or whatever

   Ok, now you've been told.  At this point, anyone who whines about not
being given enough information gets an unflattering haiku written about
them in the next change log.  I'll do it.  Don't think I won't.

VERSION
=======

   $Id: Stringy.pm,v 1.219 2001/02/23 09:46:23 eryq Exp $

TO DO
=====

(2000/08/02)  Finalize $/ support
     Graham Barr submitted this patch half a year ago; Like a moron, I
     lost his message under a ton of others, and only now have the
     experimental implementation done.

     Will the sudden sensitivity to $/ hose anyone out there?  I'm
     worried, so you have to enable it explicitly.

(2000/09/28)  Separate read/write cursors?
     Binkley sent me a very interesting variant of IO::Scalar which
     maintains two separate cursors on the data, one for reading and one
     for writing.  Quoth he:

          Isn't it the case that real operating system file descriptors
          maintain an independent read and write file position (and
          seek(2) resets them both)?

     He also pointed out some issues with his implementation:

          For example, what does eof or tell return?  The read position or
          the write position?  (I assumed read position was more important).

     Your opinions on this are most welcome.  (Me, I'm just squeamish that
     this will break some code which depends on the existing behavior, and
     that attempts to maintain backwards-compatibility will slow down the
     code.  But I'll give it a shot.)

CHANGE LOG
==========

Version 1.219   (2001/02/23)
     IO::Scalar objects can now be made sensitive to $/ .  Pains were
     taken to keep the fast code fast while adding this feature.  *Cheers
     to Graham Barr for submitting his patch; jeers to me for losing his
     email for 6 months.*

Version 1.218   (2001/02/23)
     IO::Scalar has a new sysseek() method.  *Thanks again to Richard
     Jones.*

     New "TO DO" section, because people who submit patches/ideas should
     at least know that they're in the system... and that I won't lose
     their stuff.  Please read it.

     New entries in `"AUTHOR"' in this node.  Please read those too.

Version 1.216   (2000/09/28)
     *IO::Scalar and IO::ScalarArray now inherit from IO::Handle.* I
     thought I'd remembered a problem with this ages ago, related to the
     fact that these IO:: modules don't have "real" filehandles, but the
     problem apparently isn't surfacing now.  If you suddenly encounter
     Perl warnings during global destruction (especially if you're using
     tied filehandles), then please let me know!  *Thanks to B. K. Oxley
     (binkley) for this.*

     *Nasty bug fixed in IO::Scalar::write().* Apparently, the offset and
     the number-of-bytes arguments were, for all practical purposes,
     *reversed.*  You were okay if you did all your writing with print(),
     but boy was *this* a stupid bug!  *Thanks to Richard Jones for
     finding this one.  For you, Rich, a double-length haiku:*

          Newspaper headline
             typeset by dyslexic man
          loses urgency

          BABY EATS FISH is
             simply not equivalent
          to FISH EATS BABY

     *New sysread and syswrite methods for IO::Scalar.* *Thanks again to
     Richard Jones for this.*

Version 1.215   (2000/09/05)
     Added 'bool' overload to '""' overload, so object always evaluates to
     true.  (Whew.  Glad I caught this before it went to CPAN.)

Version 1.214   (2000/09/03)
     Evaluating an IO::Scalar in a string context now yields the
     underlying string.  *Thanks to B. K. Oxley (binkley) for this.*

Version 1.213   (2000/08/16)
     Minor documentation fixes.

Version 1.212   (2000/06/02)
     Fixed IO::InnerFile incompatibility with Perl5.004.  *Thanks to many
     folks for reporting this.*

Version 1.210   (2000/04/17)
     Added flush() and other no-op methods.  *Thanks to Doru Petrescu for
     suggesting this.*

Version 1.209   (2000/03/17)
     Small bug fixes.

Version 1.208   (2000/03/14)
     Incorporated a number of contributed patches and extensions, mostly
     related to speed hacks, support for "offset", and WRITE/CLOSE methods.
     *Thanks to Richard Jones, Doru Petrescu, and many others.*

Version 1.206   (1999/04/18)
     Added creation of ./testout when Makefile.PL is run.

Version 1.205   (1999/01/15)
     Verified for Perl5.005.

Version 1.202   (1998/04/18)
     New IO::WrapTie and IO::AtomicFile added.

Version 1.110
     Added IO::WrapTie.

Version 1.107
     Added IO::Lines, and made some bug fixes to IO::ScalarArray.  Also,
     added getc().

Version 1.105
     No real changes; just upgraded IO::Wrap to have a $VERSION string.

AUTHOR
======

Primary Maintainer
     Eryq (`eryq@zeegee.com').  President, ZeeGee Software Inc
     (`http://www.zeegee.com').

Unofficial Co-Authors
     For all their bug reports and patch submissions, the following are
     officially recognized:

          Richard Jones
          B. K. Oxley (binkley)
          Doru Petrescu

   Enjoy.  Yell if it breaks.

Multiplex output to multiple output handles
*******************************************

NAME
====

   IO::Tee - Multiplex output to multiple output handles

SYNOPSIS
========

     use IO::Tee;

     $tee = IO::Tee->new($handle1, $handle2);
     print $tee "foo", "bar";
     my $input = <$tee>;

DESCRIPTION
===========

   `IO::Tee' objects can be used to multiplex input and output in two
different ways.  The first way is to multiplex output to zero or more
output handles.  The `IO::Tee' constructor, given a list of output
handles, returns a tied handle that can be written to.  When written to
(using print or printf), the `IO::Tee' object multiplexes the output to
the list of handles originally passed to the constructor.  As a shortcut,
you can also directly pass a string or an array reference to the
constructor, in which case `IO::File::new' is called for you with the
specified argument or arguments.

   The second way is to multiplex input from one input handle to zero or
more output handles as it is being read.  The `IO::Tee' constructor, given
an input handle followed by a list of output handles, returns a tied
handle that can be read from as well as written to.  When written to, the
`IO::Tee' object multiplexes the output to all handles passed to the
constructor, as described in the previous paragraph.  When read from, the
`IO::Tee' object reads from the input handle given as the first argument
to the `IO::Tee' constructor, then writes any data read to the output
handles given as the remaining arguments to the constructor.

   The `IO::Tee' class supports certain IO::Handle and IO::File methods
related to input and output.  In particular, the following methods will
iterate themselves over all handles associated with the `IO::Tee' object,
and return TRUE indicating success if and only if all associated handles
returned TRUE indicating success:

close
truncate
write
syswrite
format_write
formline
fcntl
ioctl
flush
clearerr
seek
   The following methods perform input multiplexing as described above:

read
sysread
readline
getc
gets
eof
getline
getlines
   The following methods can be used to set (but not retrieve) the current
values of output-related state variables on all associated handles:

autoflush
output_field_separator
output_record_separator
format_page_number
format_lines_per_page
format_lines_left
format_name
format_top_name
format_line_break_characters
format_formfeed
   The following methods are directly passed on to the input handle given
as the first argument to the `IO::Tee' constructor:

input_record_separator
input_line_number
   Note that the return value of input multiplexing methods (such as
print) is always the return value of the input action, not the return
value of subsequent output actions.  In particular, no error is indicated
by the return value if the input action itself succeeds but subsequent
output multiplexing fails.

EXAMPLE
=======

     use IO::Tee;
     use IO::File;

     my $tee = new IO::Tee(\*STDOUT,
         new IO::File(">tt1.out"), ">tt2.out");

     print join(' ', $tee->handles), "\n";

     $tee->output_field_separator("//");
     for (1..10) { print $tee $_, "\n" }
     for (1..10) { $tee->print($_, "\n") }
     $tee->flush;

     $tee = new IO::Tee('</etc/passwd', \*STDOUT);
     my @lines = <$tee>;
     print scalar(@lines);

AUTHOR
======

   Chung-chieh Shan, ken@digitas.harvard.edu

COPYRIGHT
=========

   Copyright (c) 1998 Chung-chieh Shan.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   See Perlfunc (perl.info), IO/Handle,
IO/File.

wrap raw filehandles in IO::Handle interface
********************************************

NAME
====

   IO::Wrap - wrap raw filehandles in IO::Handle interface

SYNOPSIS
========

     use IO::Wrap;

     # Do stuff with any kind of filehandle (including a bare globref), or
     # any kind of blessed object that responds to a print() message.
     #
     sub do_stuff {
         my $fh = shift;

         ### At this point, we have no idea what the user gave us...
         ### a globref? a FileHandle? a scalar filehandle name?

         $fh = wraphandle($fh);

         ### At this point, we know we have an IO::Handle-like object!

         $fh->print("Hey there!");
         ...
     }

DESCRIPTION
===========

   Let's say you want to write some code which does I/O, but you don't
want to force the caller to provide you with a FileHandle or IO::Handle
object.  You want them to be able to say:

     do_stuff(\*STDOUT);
     do_stuff('STDERR');
     do_stuff($some_FileHandle_object);
     do_stuff($some_IO_Handle_object);

   And even:

     do_stuff($any_object_with_a_print_method);

   Sure, one way to do it is to force the caller to use tiehandle().  But
that puts the burden on them.  Another way to do it is to use *IO::Wrap*,
which provides you with the following functions:

wraphandle SCALAR
     This function will take a single argument, and "wrap" it based on
     what it seems to be...

        * *A raw scalar filehandle name,* like `"STDOUT"' or
          `"Class::HANDLE"'.  In this case, the filehandle name is wrapped
          in an IO::Wrap object, which is returned.

        * *A raw filehandle glob,* like `\*STDOUT'.  In this case, the
          filehandle glob is wrapped in an IO::Wrap object, which is
          returned.

        * *A blessed FileHandle object.* In this case, the FileHandle is
          wrapped in an IO::Wrap object if and only if your FileHandle
          class does not support the read() method.

        * *Any other kind of blessed object,* which is assumed to be
          already conformant to the IO::Handle interface.  In this case,
          you just get back that object.

   If you get back an IO::Wrap object, it will obey a basic subset of the
IO:: interface.  That is, the following methods (note: I said methods, not
named operators) should work on the thing you get back:

     close
     getline
     getlines
     print ARGS...
     read BUFFER,NBYTES
     seek POS,WHENCE
     tell

NOTES
=====

   Clearly, when wrapping a raw external filehandle (like \*STDOUT), I
didn't want to close the file descriptor when the "wrapper" object is
destroyed... since the user might not appreciate that!  Hence, there's no
DESTROY method in this class.

   When wrapping a FileHandle object, however, I believe that Perl will
invoke the FileHandle::DESTROY when the last reference goes away, so in
that case, the filehandle is closed if the wrapped FileHandle really was
the last reference to it.

WARNINGS
========

   This module does not allow you to wrap filehandle names which are given
as strings that lack the package they were opened in. That is, if a user
opens FOO in package Foo, they must pass it to you either as `\*FOO' or as
`"Foo::FOO"'.  However, `"STDIN"' and friends will work just fine.

AUTHOR
======

   Eryq (`eryq@zeegee.com').  President, ZeeGee Software Inc
(`http://www.zeegee.com').

wrap tieable objects in IO::Handle interface
********************************************

NAME
====

   IO::WrapTie - wrap tieable objects in IO::Handle interface

   *This is currently Alpha code, released for comments.    Please give me
your feedback!*

SYNOPSIS
========

   First of all, you'll need tie(), so:

     require 5.004;

   *Function interface (experimental).* Use this with any existing class...

     use IO::WrapTie;
     use FooHandle;                  # implements TIEHANDLE interface

     # Suppose we want a "FooHandle->new(&FOO_RDWR, 2)".
     # We can instead say...

     $FH = wraptie('FooHandle', &FOO_RDWR, 2);

     # Now we can use...
     print $FH "Hello, ";            # traditional operator syntax...
     $FH->print("world!\n");         # ...and OO syntax as well!

   *OO interface (preferred).* You can inherit from the IO::WrapTie::Slave
mixin to get a nifty `new_tie()' constructor...

     #------------------------------
     package FooHandle;                        # a class which can TIEHANDLE

     use IO::WrapTie;
     @ISA = qw(IO::WrapTie::Slave);            # inherit new_tie()
     ...

     #------------------------------
     package main;

     $FH = FooHandle->new_tie(&FOO_RDWR, 2);   # $FH is an IO::WrapTie::Master
     print $FH "Hello, ";                      # traditional operator syntax
     $FH->print("world!\n");                   # OO syntax

   See IO::Scalar as an example.  It also shows you how to create classes
which work both with and without 5.004.

DESCRIPTION
===========

   Suppose you have a class `FooHandle', where...

   * *FooHandle does not inherit from IO::Handle;* that is, it performs
     filehandle-like I/O, but to something other than an underlying file
     descriptor.  Good examples are IO::Scalar (for printing to a string)
     and IO::Lines (for printing to an array of lines).

   * *FooHandle implements the TIEHANDLE interface* (see Perltie (perl.info));
     that is, it provides methods TIEHANDLE, GETC,
     PRINT, PRINTF, READ, and READLINE.

   * *FooHandle implements the traditional OO interface* of FileHandle and
     IO::Handle; i.e., it contains methods like getline(), read(),
     print(), seek(), tell(), eof(), etc.

   Normally, users of your class would have two options:

   * *Use only OO syntax,* and forsake named I/O operators like 'print'.

   * *Use with tie,* and forsake treating it as a first-class object
     (i.e., class-specific methods can only be invoked through the
     underlying object via tied()... giving the object a "split
     personality").

   But now with IO::WrapTie, you can say:

     $WT = wraptie('FooHandle', &FOO_RDWR, 2);
     $WT->print("Hello, world\n");   # OO syntax
     print $WT "Yes!\n";             # Named operator syntax too!
     $WT->weird_stuff;               # Other methods!

   And if you're authoring a class like FooHandle, just have it inherit
from `IO::WrapTie::Slave' and that first line becomes even prettier:

     $WT = FooHandle->new_tie(&FOO_RDWR, 2);

   *The bottom line:* now, almost any class can look and work exactly like
an IO::Handle... and be used both with OO and non-OO filehandle syntax.

HOW IT ALL WORKS
================

The data structures
-------------------

   Consider this example code, using classes in this distribution:

     use IO::Scalar;
     use IO::WrapTie;

     $WT = wraptie('IO::Scalar',\$s);
     print $WT "Hello, ";
     $WT->print("world!\n");

   In it, the wraptie() function creates a data structure as follows:

     * $WT is a blessed reference to a tied filehandle
                   $WT           glob; that glob is tied to the "Slave" object.
                    |          * You would do all your i/o with $WT directly.
                    |
                    |
                    |     ,---isa--> IO::WrapTie::Master >--isa--> IO::Handle
                    V    /
             .-------------.
             |             |
             |             |   * Perl i/o operators work on the tied object,
             |  "Master"   |     invoking the TIEHANDLE methods.
             |             |   * Method invocations are delegated to the tied
             |             |     slave.
             `-------------'
                    |
         tied(*$WT) |     .---isa--> IO::WrapTie::Slave
                    V    /
             .-------------.
             |             |
             |   "Slave"   |   * Instance of FileHandle-like class which doesn't
             |             |     actually use file descriptors, like IO::Scalar.
             |  IO::Scalar |   * The slave can be any kind of object.
             |             |   * Must implement the TIEHANDLE interface.
             `-------------'

   NOTE: just as an IO::Handle is really just a blessed reference to a
*traditional* filehandle glob... so also, an IO::WrapTie::Master is really
just a blessed reference to a filehandle glob *which has been tied to some
"slave" class.*

How wraptie() works
-------------------

  1. The call to function `wraptie(SLAVECLASS, TIEARGS...)' is passed onto
     `IO::WrapTie::Master::new()'.  Note that class IO::WrapTie::Master is
     a subclass of IO::Handle.

  2. The `IO::WrapTie::Master::new' method creates a new IO::Handle object,
     reblessed into class IO::WrapTie::Master.  This object is the master,
     which will be returned from the constructor.  At the same time...

  3. The new method also creates the slave: this is an instance of
     SLAVECLASS which is created by tying the master's IO::Handle to
     SLAVECLASS via `tie(HANDLE, SLAVECLASS, TIEARGS...)'.  This call to
     tie() creates the slave in the following manner:

  4. Class SLAVECLASS is sent the message `TIEHANDLE(TIEARGS...)'; it will
     usually delegate this to `SLAVECLASS::new(TIEARGS...)', resulting in
     a new instance of SLAVECLASS being created and returned.

  5. Once both master and slave have been created, the master is returned
     to the caller.

How I/O operators work (on the master)
--------------------------------------

   Consider using an i/o operator on the master:

     print $WT "Hello, world!\n";

   Since the master ($WT) is really a [blessed] reference to a glob, the
normal Perl i/o operators like print may be used on it.  They will just
operate on the symbol part of the glob.

   Since the glob is tied to the slave, the slave's PRINT method (part of
the TIEHANDLE interface) will be automatically invoked.

   If the slave is an IO::Scalar, that means IO::Scalar::PRINT will be
invoked, and that method happens to delegate to the print() method of the
same class.  So the real work is ultimately done by IO::Scalar::print().

How methods work (on the master)
--------------------------------

   Consider using a method on the master:

     $WT->print("Hello, world!\n");

   Since the master ($WT) is blessed into the class IO::WrapTie::Master,
Perl first attempts to find a print() method there.  Failing that, Perl
next attempts to find a print() method in the superclass, IO::Handle.  It
just so happens that there *is* such a method; that method merely invokes
the print i/o operator on the self object...  and for that, see above!

   But let's suppose we're dealing with a method which *isn't* part of
IO::Handle... for example:

     my $sref = $WT->sref;

   In this case, the intuitive behavior is to have the master delegate the
method invocation to the slave (now do you see where the designations come
from?).  This is indeed what happens: IO::WrapTie::Master contains an
AUTOLOAD method which performs the delegation.

   So: when `sref()' can't be found in IO::Handle, the AUTOLOAD method of
IO::WrapTie::Master is invoked, and the standard behavior of delegating
the method to the underlying slave (here, an IO::Scalar) is done.

   Sometimes, to get this to work properly, you may need to create a
subclass of IO::WrapTie::Master which is an effective master for *your*
class, and do the delegation there.

NOTES
=====

   *Why not simply use the object's OO interface?*     Because that means
forsaking the use of named operators like print(), and you may need to
pass the object to a subroutine which will attempt to use those operators:

     $O = FooHandle->new(&FOO_RDWR, 2);
     $O->print("Hello, world\n");  # OO syntax is okay, BUT....

     sub nope { print $_[0] "Nope!\n" }
      X  nope($O);                     # ERROR!!! (not a glob ref)

   *Why not simply use tie()?*     Because (1) you have to use tied() to
invoke methods in the object's public interface (yuck), and (2) you may
need to pass the tied symbol to another subroutine which will attempt to
treat it in an OO-way... and that will break it:

     tie *T, 'FooHandle', &FOO_RDWR, 2;
     print T "Hello, world\n";     # Operator is okay, BUT...

     tied(*T)->other_stuff;        # yuck! AND...

     sub nope { shift->print("Nope!\n") }
      X  nope(\*T);                    # ERROR!!! (method "print" on unblessed ref)

   *Why a master and slave?    Why not simply write FooHandle to inherit
from IO::Handle?*     I tried this, with an implementation similar to that
of IO::Socket.  The problem is that *the whole point is to use this with
objects that don't have an underlying file/socket descriptor.*.
Subclassing IO::Handle will work fine for the OO stuff, and fine with
named operators if you tie()... but if you just attempt to say:

     $IO = FooHandle->new(&FOO_RDWR, 2);
     print $IO "Hello!\n";

   you get a warning from Perl like:

     Filehandle GEN001 never opened

   because it's trying to do system-level i/o on an (unopened) file
descriptor.  To avoid this, you apparently have to tie() the handle...
which brings us right back to where we started!  At least the IO::WrapTie
mixin lets us say:

     $IO = FooHandle->new_tie(&FOO_RDWR, 2);
     print $IO "Hello!\n";

   and so is not *too* bad.  `:-)'

WARNINGS
========

   Remember: this stuff is for doing FileHandle-like i/o on things
*without underlying file descriptors*.  If you have an underlying file
descriptor, you're better off just inheriting from IO::Handle.

   *Be aware that new_tie() always returns an instance of a kind of
IO::WrapTie::Master...* it does not return an instance of the i/o class
you're tying to!

   Invoking some methods on the master object causes AUTOLOAD to delegate
them to the slave object... so it *looks* like you're manipulating a
"FooHandle" object directly, but you're not.

   I have not explored all the ramifications of this use of tie().  *Here
there be dragons*.

AUTHOR
======

   Eryq (`eryq@zeegee.com').  President, ZeeGee Software Inc
(`http://www.zeegee.com').

IO:: style interface to Compress/Zlib,
***********************************************************

NAME
====

   IO::Zlib - IO:: style interface to Compress/Zlib,

SYNOPSIS
========

   With any version of Perl 5 you can use the basic OO interface:

     use IO::Zlib;

     $fh = new IO::Zlib;
     if ($fh->open("file.gz", "rb")) {
         print <$fh>;
         $fh->close;
     }

     $fh = IO::Zlib->new("file.gz", "wb9");
     if (defined $fh) {
         print $fh "bar\n";
         $fh->close;
     }

     $fh = IO::Zlib->new("file.gz", "rb");
     if (defined $fh) {
         print <$fh>;
         undef $fh;       # automatically closes the file
     }

   With Perl 5.004 you can also use the TIEHANDLE interface to access
compressed files just like ordinary files:

     use IO::Zlib;

     tie *FILE, 'IO::Zlib', "file.gz", "wb";
     print FILE "line 1\nline2\n";

     tie *FILE, 'IO::Zlib', "file.gz", "rb";
     while (<FILE>) { print "LINE: ", $_ };

DESCRIPTION
===========

   `IO::Zlib' provides an IO:: style interface to Compress/Zlib,
and hence to gzip/zlib compressed files. It provides many
of the same methods as the IO/Handle, interface.

CONSTRUCTOR
===========

new ( [ARGS] )
     Creates an `IO::Zlib' object. If it receives any parameters, they are
     passed to the method open; if the open fails, the object is destroyed.
     Otherwise, it is returned to the caller.

METHODS
=======

open ( FILENAME, MODE )
     open takes two arguments. The first is the name of the file to open
     and the second is the open mode. The mode can be anything acceptable
     to Compress/Zlib, and by extension anything
     acceptable to *zlib* (that basically means POSIX fopen() style mode
     strings plus an optional number to indicate the compression level).

opened
     Returns true if the object currently refers to a opened file.

close
     Close the file associated with the object and disassociate the file
     from the handle.  Done automatically on destroy.

getc
     Return the next character from the file, or undef if none remain.

getline
     Return the next line from the file, or undef on end of string.  Can
     safely be called in an array context.  Currently ignores $/
     ($INPUT_RECORD_SEPARATOR or $RS when English, is in
     use) and treats lines as delimited by "\n".

getlines
     Get all remaining lines from the file.  It will croak() if
     accidentally called in a scalar context.

print ( ARGS... )
     Print ARGS to the  file.

read ( BUF, NBYTES, [OFFSET] )
     Read some bytes from the file.  Returns the number of bytes actually
     read, 0 on end-of-file, undef on error.

eof
     Returns true if the handle is currently positioned at end of file?

seek ( OFFSET, WHENCE )
     Seek to a given position in the stream.  Not yet supported.

tell
     Return the current position in the stream, as a numeric offset.  Not
     yet supported.

setpos ( POS )
     Set the current position, using the opaque value returned by
     `getpos()'.  Not yet supported.

getpos ( POS )
     Return the current position in the string, as an opaque object.  Not
     yet supported.

SEE ALSO
========

   See Perlfunc (perl.info), `"I', see Perlop (perl.info),
`"I', see IO/Handle, `"I', see
Compress/Zlib,

HISTORY
=======

   Created by Tom Hughes <`tom@compton.nu'>.

COPYRIGHT
=========

   Copyright (c) 1998-2001 Tom Hughes <`tom@compton.nu'>.  All rights
reserved. This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

a perl module that implements an object storage space where data is persisted across process boundaries
*******************************************************************************************************

NAME
====

   *IPC::Cache* - a perl module that implements an object storage space
where data is persisted across process boundaries

SYNOPSIS
========

   use IPC::Cache;

   # create a cache in the specified namespace, where objects # will
expire in one day

   my $cache = new Cache( { namespace  => 'MyCache',
  expires_in => 86400 } );

   # store a value in the cache (will expire in one day)

   $cache->set("key1", "value1");

   # retrieve a value from the cache

   $cache->get("key1");

   # store a value that expires in one hour

   $cache->set("key2", "value2", 3600);

   # clear this cache's contents

   $cache->clear();

   # delete all namespaces from shared memory

   IPC::Cache::CLEAR();

DESCRIPTION
===========

   IPC::Cache is used to persist data across processes via shared memory.

TYPICAL USAGE
-------------

   A typical scenario for this would be a mod_perl or perl CGI
application.  In a multi-tier architecture, it is likely that a trip from
the front-end to the database is the most expensive operation, and that
data may not change frequently.  Using this module will help keep that
data on the front-end.

   Consider the following usage in a mod_perl application, where a
mod_perl application serves out images that are retrieved from a database.
Those images change infrequently, but we want to check them once an hour,
just in case.

   my $cache = new Cache( { namespace => 'Images',
expires_in => 3600 } );

   my $image = $imageCache->get("the_requested_image");

   if (!$image) {

     # $image = [expensive database call to get the image]

     $cache->set("the_requested_image", $image);

   }

   That bit of code, executed in any instance of the mod_perl/httpd
process will first try the shared memory cache, and only perform the
expensive database call if the image has not been fetched before, has
timed out, or the cache has been cleared.

METHODS
-------

new(\%options)
     Creates a new instance of the cache object.  The constructor takes a
     reference to an options hash which can contain any or all of the
     following:

    $options{namespace}
          Namespaces provide isolation between objects.  Each cache refers
          to one and only one namespace.  Multiple caches can refer to the
          same namespace, however.  While specifying a namespace is not
          required, it is recommended so as not to have data collide.

    $options{expires_in}
          If the "expires_in" option is set, all objects in this cache
          will be cleared in that number of seconds.  It can be overridden
          on a per-object basis.  If expires_in is not set, the objects
          will never expire unless explicitly set.

    $options{cache_key}
          The "cache_key" is used to determine the underlying shared
          memory segment to use.  In typical usage, leaving this unset and
          relying on namespaces alone will be more than adequate.

*set($identifier, $object, $expires_in)*
     Adds an object to the cache.  set takes the following parameters:

    $identifier
          The key the refers to this object.

    $object
          The object to be stored.

    $expires_in *(optional)*
          The object will be cleared from the cache in this number of
          seconds.  Overrides the default expire_in for the cache.

get($identifier)
     Retrieves an object from the cache.  get takes the following
     parameter:

    $identifier
          The key referring to the object to be retrieved.

clear()
     Removes all objects from this cache.

purge()
     Removes all objects that have expired

IPC::Cache::CLEAR($cache_key)
     Removes this cache and all the associated namespaces from shared
     memory.  CLEAR takes the following parameter:

    $cache_key *(optional)*
          Specifies the shared memory segment to be cleared.  Needed only
          if a cache was created in a non-standard shared memory segment.

IPC::Cache::PURGE($cache_key)
     Removes all objects in all namespaces that have expired.  PURGE takes
     the following parameter:

    $cache_key *(optional)*
          Specifies the shared memory segment to be purged.  Needed only
          if a cache was created in a non-standard shared memory segment.

IPC::Cache::SIZE($cache_key)
     Roughly estimates the amount of memory in use.  SIZE takes the
     following parameter:

    $cache_key *(optional)*
          Specifies the shared memory segment to be examined.  Needed only
          if a cache was created in a non-standard shared memory segment.

BUGS
====

   * The SIZE method estimates only the size of the frozen data, not the
     actual shared memory usage

   * There is no mechanism for limiting the amount of memory in use

AUTHOR
======

   DeWitt Clinton <dclinton@eziba.com>

control a child process without blocking
****************************************

NAME
====

   IPC::ChildSafe, ChildSafe - control a child process without blocking

SYNOPSIS
========

     use IPC::ChildSafe;

     # Start a shell process (create a new shell object).
     $SH = IPC::ChildSafe->new('sh', 'echo ++EOT++', '++EOT++');

     # If the ls command succeeds, read lines from its stdout one at a time.
     if ($SH->cmd('ls') == 0) {
        print "Found ", scalar($SH->stdout), " files in current dir ...\n";

     # Another ls cmd - results added to the object's internal stack
     $SH->cmd('ls /tmp');

     # Since we're stuck in this dumb example, let's get the date too.
     $SH->cmd('date');

     # Now dump results to stdout - show how to get 1 line at a time
     for my $line ($SH->stdout) {
     	 print $line;
     }

     # You could also print the output this way:
     # print $SH->stdout;

     # Or even just:
     # $SH->stdout;

     }

     # Send it a command, read back the stdout/stderr/return code
     # into a hash array.
     my(%results) = $SH->cmd('id');		# Send an 'id' cmd
     die if $results{status};			# Expect no errors
     die if @{$results{stdout}} != 1;		# Should be just 1 line
     die if $results{stdout}[0] !~ /^uid=/;	# Check output line

     # (lather, rinse, repeat)

     # Finishing up.
     die if $SH->finish;				# Returns final status

DESCRIPTION
===========

     This was written to address the "blocking problem" inherent in
     most coprocessing designs such as IPC::Open3.pm, which has warnings
     such as this in its documentation:

     ... additionally, this is very dangerous as you may block forever.  It
        assumes it's going to talk to something like bc, both writing to it and
        reading from it.  This is presumably safe because you "know" that
        commands like bc will read a line at a time and output a line at a
        time ...

   or IPC::Open2 which has this warning from its author (Tom Christansen):

     ... I strongly advise against using open2 for almost anything, even
     though I'm its author. UNIX buffering will just drive you up the wall.
     You'll end up quite disappointed ...

   The blocking problem is: once you've sent a command to your coprocess,
how do you know when the output resulting from this command has finished?
If you guess wrong and issue one read too many you can deadlock forever.
This implementation solves the problem, at least for a subset of possible
child programs, by using a little trick:  it sends a 2nd (trivial) command
down the pipe right in back of every real command.  When we see the the
output of this special command in the return pipe, we know the real
command is done.

   This module also returns an "exit status" for each command, which is
really a count of the error messages produced by it.  The programmer can
optionally register his/her own discriminator function for determining
which output to stderr constitutes an error message.

CONSTRUCTOR
===========

   The constructor takes 3 arguments plus an optional 4th and 5th: the 1st
is the program to run, the 2nd is a command to that program which produces
a unique one-line output, and the 3rd is that unique output.  If a 4th arg
is supplied it becomes the mode in which this object will run (default:
NOTIFY, see below), and if a 5th is given it must be a code ref, which
will be registered as the error discriminator.  If no discriminator is
supplied then a standard internal one is used.

   The 2nd arg is called the "tag command". Preferably this would be
something lightweight, e.g. a shell builtin. Unfortunately the current
version has no support for a multi-line return value since it would
require some fairly complex buffering.

DISCRIMINATOR
=============

   The discriminator function is invoked after each command completes, and
is passed a reference to an array containing the stderr generated by that
command in its first parameter. A pointer to the stdout is similarly
supplied in the second param. Normally this function would just apply a
regular expression to one or both of these and indicate by its return
status whether it considers this to constitute an error condition. E.g.
the version provided internally is:

     sub errors {
     	my($r_stderr, $r_stdout) = @_;
     	grep(!/^\+\s|warning:/i, @$r_stderr);
     }

     my $sh = IPC::ChildSafe->new('sh', 'echo ++EOT++', '++EOT++', \&errors);

   which treats ANY output to stderr as indicative of an error, with the
exception of lines beginning with "+ " (shell verbosity) or containing the
string "warning:".

METHODS
=======

   * *notify/store/print/ignore*

     Sets the output-handling mode. The meanings of these are described
     below.

   * cmd

     Send specified command to child process. Return behavior varies with
     context:

    array context
          returns a hash containing an array of stdout results (key:
          'stdout'), an array of stderr messages ('stderr), and the
          "return code" of the command ('status').

    scalar context
          returns command's "return code".  In the default mode (NOTIFY),
          sends stderr results directly to parent's stderr while storing
          stdout in the object for later retrieval via stdout method. In
          PRINT mode both stdout and stderr are sent directly to the
          "real" (parent's) stdout/stderr. STORE mode causes both stdout
          and stderr to be stored for later use, while IGNORE mode throws
          away both.

    void context
          similar to scalar mode but exits on nonzero return code unless in
          IGNORE mode.

    void context and no args
          clears the stdout and stderr buffers

   * stdout

     Return stored output from previous command(s). Behavior varies with
     context:

    array context
          shifts all stored lines off the stdout stack and returns them in
          a list.

    scalar context
          returns the number of lines currently stored in the stdout stack.

    void context
          prints the current stdout stack to actual stdout.

   * stderr

     Similar to stdout method above. Note that by default stderr does not
     go to the accumulator, but rather to the parent's stderr.  Set the
     STORE attribute to leave stderr in the accumulator instead where this
     method can operate on it.

   * status

     Pass the current stdout and stderr buffers to the currently-registered
     error discriminator and return its results (aka the error count).

   * finish

     Ends the child process and returns its final exit status.

   * *dbglevel*

     Sets a debugging (verbosity) level. Current defined levels are 1-4.
     Verbosity lines are printed with a leading '+'.

   * *noexec*

     Sets the 'noexec' attribute, which causes commands to not be run but
     to be printed with a leading '-'.

AUTHOR
======

   David Boyce dsb@world.std.com

   Copyright (c) 1997-1999 David Boyce. All rights reserved. This perl
program is free software; you may redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1), "perldoc IPC::Open3", _Advanced Programming in the Unix
Environment_ by W. R. Stevens

run a bidirectional pipe to a cleartool process
***********************************************

NAME
====

   IPC::ClearTool, ClearTool - run a bidirectional pipe to a cleartool
process

SYNOPSIS
========

     use IPC::ClearTool;

     my $CT = IPC::ClearTool->new;
     $CT->cmd("pwv");
     $CT->cmd("lsview");
     $CT->cmd("lsvob -s");
     for ($CT->stdout) { print }
     $CT->finish;

ALTERNATE SYNOPSES
==================

     use IPC::ClearTool;

     $rc = $CT->cmd("pwv");		# Assign return code to $rc

     $CT->notify;				# "notify mode" is default;
     $rc = $CT->cmd("pwv");		# same as above

     $CT->store;				# "Store mode" - hold stderr for
     $rc = $CT->cmd("pwv -X");		# later retrieval via $CT->stderr
     @errs = $CT->stderr;			# Retrieve it now

     $CT->ignore;				# Discard all stdout/stderr and
     $CT->cmd("pwv");			# ignore nonzero return codes

     $CT->cmd("ls foo@@");			# In void context, store stdout,
     					# print stderr immediately,
     					# exit on error.

     my %results = $CT->cmd("pwv");	# Place all results in %results,
     					# available as:
     					#   @{$results{stdout}}
     					#   @{$results{stderr}}
     					#   @{$results{status}}

     $CT->cmd();				# Clear all accumulators

     $CT->stdout;				# In void context, print stored output

DESCRIPTION
===========

   This module invokes the ClearCase 'cleartool' command as a child
process and opens pipes to its standard input, output, and standard error.
Cleartool commands may be sent "down the pipe" via the $CT->cmd() method.
All stdout resulting from commands is stored in the object and can be
retrieved at any time via the $CT->stdout method. By default, stderr from
commands is sent directly to the real (parent's) stderr but if the store
attribute is set as shown above, stderr will accumulate just like stdout
and must be retrieved via $CT->stderr.

   If $CT->cmd is called in a void context it will exit on error unless
the *ignore* attribute is set, in which case all output is thrown away and
error messages suppressed.  If called in a scalar context it returns the
exit status of the command.

   When used with no arguments and in a void context, $CT->cmd simply
clears the stdout and stderr accumulators.

   The $CT->stdout and $CT-stderr methods behave just like arrays; when
used in a scalar context they return the number of lines currently stored.
When used in an array context they return, well, an array containing all
currently stored lines, and then clear the internal stack.

   The $CT->finish method ends the child process and returns its exit
status.

   This is only a summary of the documentation. There are more advanced
methods for error detection, data return, etc. documented as part of
IPC::ChildSafe. Note that IPC::ClearTool is simply a small subclass of
ChildSafe; it provides the right defaults to ChildSafe's constructor for
running cleartool and adds a few ClearCase-specific methods. In all other
ways it's identical to ChildSafe, and all ChildSafe documentation applies.

BUGS
====

   * Comments

     Comments present a special problem. If a comment is prompted for, it
     will likely hang the child process by interrupting the tag/eot
     sequencing. So we prefer to pass comments on the command line with -c.
     Unfortunately, the quoting rules of cleartool are insufficient to
     allow passing comments with embedded newlines using -c. The result
     being that there's no clean way to handle multi-line comments.

     To work around this, a method `$CT-'comment> is provided which
     registers a comment *to be passed to the next `$CT-'cmd()* command>.
     It's inserted into the stdin stream with a "\n.\n" appended.  The
     subsequent command must have a `-cq' flag, e.g.:

          $CT->comment("Here's a\nmultiple line\ncomment");
          $CT->cmd("ci -cq foo.c");

     If your script hangs and the comment for the last element checked in
     is `"pwd -h"', then you were burned by such a sync problem.

   * UNIX/Win32 Semantics Skew

     On UNIX, this module works by running cleartool as a child process.
     On Windows, the ClearCase Automation Library (a COM API) is used
     instead.  This provides the same interface *but be warned that
     there's a subtle semantic difference!* On UNIX you can send a setview
     command to the child and it will run in the new view while the
     parent's environment remains unchanged. On Windows there's no
     subprocess; thus the setview would change the context of the "parent
     process".  The same applies to chdir commands. It's unclear which
     behavior is "better" overall, but in any case portable applications
     must take extra care in using such stateful techniques.

     As a partial remedy, a chdir method is provided. This simply does the
     cd in both parent and child processes in an attempt to emulate the
     in-process behavior. Emulating an in-process `setview' is harder
     because on UNIX, setview is implemented with a fork/chroot/exec
     sequence so (a) it's hard to know how a single-process setview should
     behave and (b) I wouldn't know how to do it anyway, especially
     lacking the privileges required by chroot(2). Of course in most cases
     you could work around this by using chdir to work in view-extended
     space rather than a set view.

     Of course, in some cases the ability to set the child process into a
     different view or directory is a feature, and no attempt is made to
     stop you from doing that.

   * Win32::OLE Behavior with IClearTool

     Due to the way Win32::OLE works, on Windows the results of each
     command are passed back as a single string, possibly with embedded
     newlines. For consistency, in a list context we split this back into
     lines and return the list. However, it's possible for this to result
     in a different line count for the same command in UNIX and NT, if one
     of the lines would have had embedded newlines in it anyway.

   * Win32/CC 3.2.1 COM Bug

     The ClearCase/COM API wasn't documented until CC 4.0, but it's
     actually present (at least the IClearTool interface, which is what
     IPC::ClearTool uses) in 3.2.1 with one major bug - all output arrives
     backwards! So we provide a class method

          IPC::ClearTool->cc_321_hack;

     which, if called, will determine whether it's running on CC 3.2.1 and
     if so reverse the order of output. This is called once at the start
     of the program to set the state; it's a no-op if CC 4.0 or above is
     in use.

AUTHOR
======

   David Boyce dsb@world.std.com

SEE ALSO
========

   perl(1), "perldoc IPC::ChildSafe"

implements a length based IPC protocol
**************************************

NAME
====

   *IPC::LDT* - implements a length based IPC protocol

SCRIPT DATA
===========

   This manual describes version *2.03*.

DESCRIPTION
===========

   Interprocess communication often uses line (or record) oriented
protocols. FTP, for example, usually is such a protocol: a client sends a
command (e.g. "LS") which is completed by a carriage return. This carriage
return is included in the command which is sent to the server process (FTP
deamon) which could implement its reading in a way like this:

     while ($cmd=<CLIENT>)
      {
       chomp($cmd);
       performCommand($cmd);
      }

   Well, such record oriented, blocked protocols are very useful and
simply to implement, but sometimes there is a need to transfer more
complex data which has no trailing carriage return, or data which may
include more carriage returns inside the message which should not cause
the reciepient to think the message is already complete while it is really
not.  Even if you choose to replace carriage returns by some obscure
delimiters, the same could happen again until you switch to a protocol
which does not flag the end of a message by special strings.

   On the other hand, if there is no final carriage return (or whatever
flag string) within a message, the end of the message has to be marked
another way to avoid blocking by endless waiting for more message parts. A
simple way to provide this is to precede a message by a prefix which
includes the length of the remaining (real) message. A reciepient reads
this prefix, decodes the length information and continues reading until
the announced number of bytes came in.

   *IPC::LDT* provides a class to build objects which transparently
perform such "length driven transfer". A user sends and receives messages
by simple method calls, while the LDT objects perform the complete
translation into and from LDT messages (with prefix) and all the necessary
low level IO handling to transfer stream messages on non blocked handles.

   *IPC::LDT* objects can be configured to transfer simle string messages
as well as complex data structures. Additionally, they allow to delay the
transfer of certain messages in a user defined way.

SYNOPSIS
========

   Load the module as usual:

     use IPC::LDT;

   Make an LDT object for every handle that should be used in an LDT
communication:

     my $asciiClient=new IPC::LDT(handle=>HANDLE);
     my $objectClient=new IPC::LDT(handle=>HANDLE, objectMode=>1);

   Now you can send and receive data:

     $data=$asciiClient->receive;
     @objects=$objectClient->receive;

     $asciiClient=$client->send("This is", " a message.");
     $objectClient=$client->send("These are data:", [qw(a b c)]);

Exports
-------

   No symbol is exported by default.

   You can explicitly import LDT_CLOSED, LDT_READ_INCOMPLETE,
LDT_WRITE_INCOMPLETE, LDT_OK and LDT_INFO_LENGTH which are described in
section CONSTANTS.

Global Variables
================

Settings
--------

Traces
     You may set the module variable *$IPC::LDT::Trace* before the module
     is loaded (that means in a BEGIN block before the "use" statement) to
     activate the built in trace code. If not prepared this way, all
     runtime trace settings (e.g. via the constructor parameter traceMode)
     will take *no effect* because the trace code will have been filtered
     out at compile time for reasons of performance. (This means that no
     trace message will appear.)

     If *$IPC::LDT::Trace* is set before the module is loaded, te builtin
     trace code is active and can be deactivated or reactivated at runtime
     globally (for all objects of this class) by unsetting or resetting of
     this module variable. Alternatively, you may choose to control traces
     for certain objects by using the constructor parameter traceMode.

     So, if you want to trace every object, set *$IPC::LDT::Trace*
     initially and load the module. If you want to trace only certain
     objects, additionally unset *$IPC::LDT::Trace* after the module is
     loaded and construct these certain objects with constructor flag
     traceMode.

Assertions
     It is a good tradition to build self checks into a code. This makes
     code execution more secure and simplifies bug searching after a
     failure.  On the other hand, self checks decrease code performance.
     That's why you can filter out the self checking code (which is built
     in and activated by default) by setting the module variable
     *$IPC::LDT::noAssert* before the module is loaded. The checks will be
     removed from the code before they reach the compiler.

     Setting or unsetting this variable after the module was loaded takes
     *no effect*.

CONSTANTS
=========

Error codes
-----------

LDT_CLOSED
     a handle related to an LDT object was closed when reading or writing
     should be performed on it;

LDT_READ_INCOMPLETE
     a message could not be (completely) read within the set number of
     trials;

LDT_WRITE_INCOMPLETE
     a message could not be (completely) written within the set number of
     trials;

METHODS
=======

new()
-----

   The constructor builds a new object for data transfers. All parameters
except of the class name are passed named (this means, by a hash).

   Parameters:

Class name
     the first parameter as usual - passed implicitly by Perl:

          my $asciiClient=new IPC::LDT(...);

     The method form of construtor calls is not supported.

handle
     The handle to be used to perform the communication. It has to be
     opened already and will not be closed if the object will be destroyed.

          Example:
           handle => SERVER

     A closed handle is not accepted.

     You can use whatever type of handle meets your needs. Usually it is a
     socket or anything derived from a socket. For example, if you want to
     perform secure IPC, the handle could be made by Net::SSL. There is
     only one precondition: the handle has to provide a *fileno()* method.
     (You can enorce this even for Perls default handles by simply using
     FileHandle.)

objectMode
     Pass a true value if you want to transfer data structures. If this
     setting is missed or a "false" value is passed, the object will
     transfer strings.

     Data structures will be serialized via Storable for transfer. Because
     of this, such a communication is usually restricted to partners which
     could use Storable methods as well to reconstruct the data structures
     (which means that they are written in Perl).

     String transfer objects, on the other hand, can be used to
     cimmunicate with any partner who speaks the LDT protocol. We use Java
     and C clients as well as Perl ones, for example.

          Example:
           objectMode => 1

     The transfer mode may be changed while the object is alive by using
     the methods setObjectMode() and setAsciiMode().

startblockLength
     sets the length of the initial info block which preceds every LDT
     message coding the length of the remaining message. This setting is
     done in bytes.

     If no value is provided, the builtin default value *LDT_INFO_LENGTH*
     is used. (This value can be imported in your own code, see section
     "Exports" for details.) *LDT_INFO_LENGTH* is designed to meet usual
     needs.

          Example:
           startblockLength => 4

traceMode
     Set this flag to a true value if you want to trace to actions of the
     module. If set, messages will be displayed on STDERR reporting what
     is going on.

     Traces for <all> objects of this class can be activated (regardless of
     this constructor parameter) via *$IPC::LDT::Trace*. This is described
     more detailed in section "CONSTANTS".

          Example:
           traceMode => 1

   *Return value:*

   A successfull constructor call replies the new object. A failed call
replies an undefined value.

   Examples:

     my $asciiClient=new IPC::LDT(handle=>HANDLE);
     my $objectClient=new IPC::LDT(handle=>HANDLE, objectMode=>1);

setObjectMode()
---------------

   Switches the LDT object to "object trasnfer mode" which means that is
can send and receive Perl data structures now.

   Runtime changes of the transfer mode have to be exactly synchronized
with the partner the object is talking with. See the constructor (new())
description for details.

   Parameters:

object
     An LDT object made by new().

   Example:

     $asciiClient->setObjectMode;

setAsciiMode()
--------------

   Switches the LDT object to "ASCII trasnfer mode" which means that is
sends and receives strings now.

   Runtime changes of the transfer mode have to be exactly synchronized
with the partner the object is talking with. See the constructor (new())
description for details.

   Parameters:

object
     An LDT object made by new().

   Example:

     $objectClient->setAsciiMode;

delay()
-------

   Sometimes you do not want to send messages immediatly but buffer them
for later delivery, e.g. to set up a certain send order. You can use
delay() to install a filter which enforces the LDT object to delay the
delivery of all matching messages until the next call of undelay().

   The filter is implemented as a callback of send(). As long as it is
set, send() calls it to check a message for sending or buffering it.

   You can overwrite a set filter by a subsequent call of delay().
Messages already collected will remain collected.

   To send delayed messages you have to call undelay().

   If the object is detroyed while messages are still buffered, they will
not be delivered but lost.

   Parameters:

object
     An LDT object made by new().

filter
     A code reference. It should await a reference to an array which will
     contain the message (possibly in parts). It should reply a true or
     false value to flag if the passed message has to be delayed.

     It is recommended to provide a fast function because it will be
     called everytime send() will be invoked.

   Example:

     $ldt->delay(\&filter);

   with filter() defined as

     sub filter
      {
       # get and check parameters
       my ($msg)=@_;
       confess "Missed message parameter" unless $msg;
       confess "Message parameter is no array reference"
         unless ref($msg) and ref($msg) eq 'ARRAY';

     # check something
     $msg->[0] eq 'delay me';
        }

   See undelay() for a complete example.

undelay()
---------

   Sends all messages collected by a filter which was set by delay().  The
filter is removed, so that every message will be sent by send() immediatly
afterwards again.

   In case of no buffered message and no set filter, a call of this message
takes no effect.

   Parameters:

object
     An LDT object made by new().

   *Beispiel:*

     $ldt->undelay;

   Here comes a complete example to illustrate how delays can be used.

   filter definition:

     sub filter
      {
       # check something
       $msg->[0] eq 'delay me';
      }

   usage:

     # send messages
     $ldt->send('send me', 1);    # sent;
     $ldt->send('delay me', 2);   # sent;
     # activate filter
     $ldt->delay(\&filter);
     # send messages
     $ldt->send('send me', 3);    # sent;
     $ldt->send('delay me', 4);   # delayed;
     $ldt->send('send me', 5);    # sent;
     $ldt->send('delay me', 6);   # delayed;
     # send collected messages, uninstall filter
     $ldt->undelay;               # sends messages 4 and 6;
     # send messages
     $ldt->send('send me', 7);    # sent;
     $ldt->send('delay me', 8);   # sent;

send(<message>)
---------------

   Sends the passed message via the related handle (which was passed to
new()). The message, which could be passed as a list of parts, is sent as
a (concatenated) string or as serialized Perl data depending on the
settings made by the constructor flag objectMode and calls of
setObjectMode() or *setAsciiMode*, respectively.

   In case of an error, the method replies an undefined value and stores
both an error code and an error message inside the object which could be
accessed via the object variables "rc" and "msg". (See CONSTANTS for a
list of error codes.)

   An error will occur, for example, if the handle related to the LDT
object was closed (possibly outside the module).

   An error is detected as well if a previous call of send() or receive()
already detected an error. This behaviour is implemented for reasons of
security, however, if you want to try it again regardless of the objects
history, you can reset the internal error state by reset().

   For reasons of efficiency, sent messages may be splitted up into parts
by the underlaying (operating or network) system. The reciepient will get
the message part by part. On the other hand, the sender might only be able
to send them part by part as well. That is why this send() method retries
writing attempts to the associated handle until the complete message could
be sent.  Well, in fact it stops retries earlier if an inacceptable long
period of time passed by without being successfull. If that happens, the
method replies undef and provides an error code in the object variable
"rc". *The caller should be* *prepared to handle such cases. Usually
further access to the associated handle* *is useless or even dangerous.*

   Parameters:

object
     An LDT object made by new().

message (a list)
     All list elements will be combined to the resulting message as done
     by print() or *warn()* (that means, *without* separating parts by
     additional whitespaces).

   Examples:

     $asciiClient->send('Silence?', 'Maybe.')
     or die $asciiClient->{'msg'};

     $objectClient->send({oops=>1, beep=>[qw(7)]}, $scalar, \@array);

   Note: If the connection is closed while the message is sent, the signal
*SIGPIPE* might arrive and terminate the complete program. To avoid this,
*SIGPIPE* is ignored while this method is running.

   The handle associated with the LDT object is made *non blocking* during
data transmission. The original mode is restored before the method returns.

reset
-----

   If an error occurs while data are transmitted, further usage of the
associated handle is usually critical. That is why send() and receive()
stop operation after a transmission error, even if you repeat their calls.
This should *protect* your program and make it more stable (e.g. writing
to a closed handle migth cause a fatal error and even terminate your
program).

   Nevertheless, if you really want to retry after an error, here is the
reset() method which resets the internal error flags - unless the
associated handle was not already closed.

   Parameters:

object
     An LDT object made by new().

   Example:

     $ldtObject->reset;

receive()
---------

   reads a message from the associated handle and replies it.

   In case of an error, the method replies an undefined value and provides
both a return code (see CONSTANTS) and a complete message in the object
variables "rc" and "msg", respectively, where you can read them.

   An error will occur, for example, if the handle related to the LDT
object was closed (possibly outside the module).

   An error is detected as well if a previous call of send() or receive()
already detected an error. This behaviour is implemented for reasons of
security, however, if you want to try it again regardless of the objects
history, you can reset the internal error state by reset().

   For reasons of efficiency, sent messages may be splitted up into parts
by the underlaying (operating or network) system. The reciepient will get
the message part by part. That is why this receive() method retries reading
attempts to the associated handle until the complete message could be read.
Well, in fact it stops retries earlier if an inacceptable long period of
time passed by without being successfull. If that happens, the method
replies undef and provides an error code in the object variable "rc". *The
caller should be* *prepared to handle such cases. Usually further access
to the associated handle* *is useless or even dangerous.*

   Parameters:

object
     An LDT object made by new().

   The received message is replied as a string in ASCII mode, and as a
list in object mode.

   Example:

     $msg=$asciiClient->receive or die $asciiClient->{'msg'};

     @objects=$objectClient->receive or die $objectClient->{'msg'};

   Note: If the connection is closed while the message is read, the signal
*SIGPIPE* might arrive and terminate the complete program. To avoid this,
*SIGPIPE* is ignored while this method is running.

   The handle associated with the LDT object is made *non blocking* during
data transmission. The original mode is restored before the method returns.

version()
---------

   replies the modules version. It simply replies $IPC::LDT::VERSION and is
implemented only to provide compatibility to other object modules.

   Example:

     # get version
       warn "[Info] IPC is performed by IPC::LDT ", IPC::LDT::version, ".\n";

ENVIRONMENT
===========

FILES
=====

SEE ALSO
========

NOTES
=====

EXAMPLE
=======

   To share data between processes, you could embed a socket into an LDT
object.

     my $ipc=new IO::Socket(...);
     my $ldt=new IPC::LDT(handle=>$ipc, objectMode=>1);

   Now you are able to send data:

     my $dataRef=[{o=>1, lal=>2, a=>3}, [[qw(4 5 6)], [{oo=>'ps'}, 7, 8, 9]]];
     $ldt->send($dataRef) or die $ldt->{'msg'};

   or receive them:

     @data=$ldt->receive or die $ldt->{'msg'};

AUTHOR
======

   Jochen Stenzel (perl@jochen-stenzel.de)

COPYRIGHT
=========

   Copyright (c) 1998-2000 Jochen Stenzel. All rights reserved.

   This program is free software, you can redistribute it and/or modify it
under the terms of the Artistic License distributed with Perl version
5.003 or (at your option) any later version. Please refer to the Artistic
License that came with your Perl distribution for more details.

Distributed lock handler
************************

NAME
====

   IPC::Locker - Distributed lock handler

SYNOPSIS
========

     use IPC::Locker;

     my $lock = IPC::Locker->lock(lock=>'one_per_machine',
     				  host=>'example.std.com',
     				  port=>223);

     if ($lock->lock()) { something; }
     if ($lock->locked()) { something; }

     $lock->unlock();

DESCRIPTION
===========

   `IPC::Locker' will query a remote server to obtain a lock.  This is
useful for distributed utilities which run on many machines, and cannot use
file locks or other such mechanisms due to NFS or lack of common file
systems.

new ([parameter=>value ...]);
     Create a lock structure.

lock ([parameter=>value ...]);
     Try to obtain the lock, return the lock object if successful, else
     undef.

locked ()
     Return true if the lock has been obtained.

unlock ()
     Remove the given lock.  This will be called automatically when the
     object is destroyed.

break_lock ()
     Remove current locker for the given lock.

owner ([parameter=>value ...]);
     Returns a string of who has the lock or undef if not currently .
     Note that this information is not atomic, and may change
     asyncronously; do not use this to tell if the lock will be available,
     to do that, try to obtain the lock and then release it if you got it.

PARAMETERS
==========

block
     Boolean flag, true indicates wait for the lock when calling lock()
     and die if a error occurs.  False indicates to just return false.
     Defaults to true.

family
     The family of transport to use, either INET or UNIX.  Defaults to
     INET.

host
     The name of the host containing the lock server.  It may also be a
     array of hostnames, where if the first one is down, subsequent ones
     will be tried.

port
     The port number (INET) or name (UNIX) of the lock server.  Defaults to
     'lockerd' looked up via /etc/services, else 1751.

lock
     The name of the lock.

print_broke
     A function to print a message when the lock is broken.  The only
     argument is self.  Defaults to print a message if verbose is set.

print_obtained
     A function to print a message when the lock is obtained after a
     delay.  The only argument is self.  Defaults to print a message if
     verbose is set.

print_waiting
     A function to print a message when the lock is busy and needs to be
     waited for.  The first argument is self, second the name of the lock.
     Defaults to print a message if verbose is set.

print_down
     A function to print a message when the lock server is unavailable.
     The first argument is self.  Defaults to a croak message.

timeout
     The maximum time in seconds that the lock may be held before being
     forced open, passed to the server when the lock is created.  Thus if
     the requestor dies, the lock will be released after that amount of
     time.  Defaults to 10 minutes.

user
     Name to request the lock under, defaults to host_pid_user

verbose
     True to print messages when waiting for locks.  Defaults false.

SEE ALSO
========

   `lockerd',

DISTRIBUTION
============

   This package is distributed via CPAN.

AUTHORS
=======

   Wilson Snyder <wsnyder@wsnyder.org>

Distributed lock handler server
*******************************

NAME
====

   IPC::Locker::Server - Distributed lock handler server

SYNOPSIS
========

     use IPC::Locker::Server;

     IPC::Locker::Server->start_server(port=>1234,);

DESCRIPTION
===========

   `IPC::Locker::Server' provides the server for the IPC::Locker package.

start_server ([parameter=>value ...]);
     Starts the server.  Does not return.

PARAMETERS
==========

family
     The family of transport to use, either INET or UNIX.  Defaults to
     INET.

port
     The port number (INET) or name (UNIX) of the lock server.  Defaults to
     'lockerd' looked up via /etc/services, else 1751.

SEE ALSO
========

   `lockerd', `IPC::Locker',

DISTRIBUTION
============

   This package is distributed via CPAN.

AUTHORS
=======

   Wilson Snyder <wsnyder@wsnyder.org>

Perl interface to Ralf Engelschall's mm library
***********************************************

NAME
====

   IPC::MM - Perl interface to Ralf Engelschall's mm library

SYNOPSIS
========

     use IPC::MM;

     $MMSIZE = 65536;
     $MMFILE = 'mm_file';

     $mm = mm_create($MMSIZE, $MM_FILE);

     $scalar = mm_make_scalar($mm);
     tie $tied_scalar, 'IPC::MM::Scalar', $scalar;
     $tied_scalar = 'hello';

     $btree = mm_make_btree_table($mm);
     tie %tied_hash, 'IPC::MM::BTree', $btree;
     $tied_hash{key} = 'val';

     $hash = mm_make_hash($mm);
     tie %tied_hash, 'IPC::MM::Hash', $hash;
     $tied_hash{key} = 'val';

     $num = mm_maxsize();

     $num = mm_available($mm);

     $errstr = mm_error();

     mm_display_info($mm);

     mm_destroy($mm);

DESCRIPTION
===========

   IPC::MM provides an interface to Ralf Engelschall's mm library, allowing
memory to be shared between multiple processes in a relatively convenient
way.

   IPC::MM provides methods to create and destoy shared memory segments
and to access data structures within those shared memory segments, as well
as miscellaneous methods. Additionally, it provides a tied interface for
scalars and hashes.

METHODS
=======

$mm = mm_create($size, $file)
     This method creates a shared memory segment. It corresponds to the
     function in mm of the same name.

     $size is the size of the shared memory segment, in bytes. A size of 0
     means to allocate the maximum allowed size which is platform
     dependent.

     $file is a filesystem path to a file which may be used as a lock file
     for synchronizing access.

$rc = mm_permission($mm, $mode, $owner, $group)
     This method sets the filesystem mode, owner, and group for the shared
     memory segment mm. It will only do anything when the underlying shared
     memory segment is based on files. It corresponds to the function in mm
     of the same name.

     $mm is the shared memory segment returned by *mm_create*.

     $mode, *$owner*, and *$group* are passed directly to chown and chmod.

mm_destroy($mm)
     This method destroys a shared memory segment created by *mm_create*.

     $mm is the shared memory segment returned by *mm_create*.

$scalar = mm_make_scalar($mm)
mm_free_scalar($scalar)
$val = mm_scalar_get($scalar)
$rc = mm_scalar_set($scalar, $val)
     This family of methods provides a data structure for use by scalar
     variables.

     *mm_make_scalar* allocates the data structure used by the scalar.

     *mm_free_scalar* frees a data structure created by *mm_make_scalar*.

     *mm_scalar_get* returns the contents of the scalar, $scalar.

     *mm_scalar_set* sets the contents of the scalar, $scalar, to $val.

     $val is simply a Perl scalar value, meaning that it can be a string,
     a number, a reference, et al.

     It is possible for *mm_scalar_set* to fail if there is not enough
     shared memory.

     It is possible to make the scalar a tied variable, like so:

          tie $tied_scalar, 'IPC::MM::Scalar', $scalar;

$btree = mm_make_btree_table($mm)
mm_clear_btree_table($btree)
mm_free_btree_table($btree)
$val = mm_btree_table_get($btree, $key)
$rc = mm_btree_table_insert($btree, $key, $val)
$oldval = mm_btree_table_delete($btree, $key)
$rc = mm_btree_table_exists($btree, $key)
$key = mm_btree_table_first_key($btree)
$key = mm_btree_table_next_key($btree, $key)
     This family of methods provides a btree data structure for use by
     hashes.

     *mm_make_btree_table* allocates the data structure.

     *mm_clear_btree_table* clears the data structure, making it empty.

     *mm_free_btree_table* frees the data structure.

     *mm_btree_table_get* returns the value associated with $key.

     *mm_btree_table_insert* inserts a new entry into the btree, with $key
     equal to $val.

     *mm_btree_table_delete* deletes the entry in the btree identified by
     $key.

     *mm_btree_table_exists* tests for the existence of an entry in the
     btree identified by $key.

     *mm_btree_table_first_key* returns the first key in the btree.

     *mm_btree_table_next_key* returns the next key after $key in the
     btree.

     It is possible to tie a btree to a hash, like so:

          tie %tied_hash, 'IPC::MM::BTree', $btree;

     One interesting characteristic of the btree is that it is presorted,
     so keys %tied_hash will return a sorted list of items.

$hash = mm_make_hash($mm)
mm_hash_clear($hash)
mm_free_hash($hash)
$val = mm_hash_get($hash, $key)
$rc = mm_hash_insert($hash, $key, $val)
$oldval = mm_hash_delete($hash, $key)
$rc = mm_hash_exists($hash, $key)
$key = mm_hash_first_key($hash)
$key = mm_hash_next_key($hash, $key)
     This family of methods implements a shared memory hash list. These
     hash lists are not presorted like btrees, but they can be faster than
     btrees (especially unbalanced btrees).

     *mm_make_hash* allocates the data structure.

     *mm_clear_hash* clears the data structure, making it empty.

     *mm_free_hash* frees the data structure.

     *mm_hash_get* returns the value associated with $key.

     *mm_hash_insert* inserts a new entry into the hash, with $key equal
     to $val.

     *mm_hash_delete* deletes the entry in the hash identified by $key.

     *mm_hash_exists* tests for the existence of an entry in the hash
     identified by $key.

     *mm_hash_first_key* returns the first key in the hash.

     *mm_hash_next_key* returns the next key after $key in the hash.

     It is possible to tie a shared-memory hash to a perl hash, like so:

          tie %tied_hash, 'IPC::MM::Hash', $hash;

$rc = mm_lock($mm, $mode)
     This method locks the shared memory pool $mm for the current process
     in order to perform either shared/read-only (mode MM_LOCK_RD) or
     exclusive/read-write (mode MM_LOCK_RW) operations.

$rc = mm_unlock($mm)
     This method unlocks the shared memory pool $mm.

$num = mm_maxsize
     This method returns the maximum allowable size for a shared memory
     segment.  It corresponds to the function of the same name in the mm
     library.

$num = mm_available($mm)
     This method returns the number of free bytes left in a shared memory
     segment.  It corresponds to the function of the same name in the mm
     library.

     $mm is a shared memory segment created by mm_create.

$errstr = mm_error
     This method returns an error string, if any. It corresponds to the
     function of the same name in mm.

mm_display_info($mm)
     This method displays some miscellaneous information about a shared
     memory segment. It corresponds to the function of the same name in mm.

BUGS
====

   No effort is made to balance the btree.

AUTHOR
======

   Copyright (c) 1999, Arthur Choung <arthur@etoys.com>.  All rights
reserved.

   This module is free software; you may redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `mm' in this node, see IPC/Shareable, perl.

   perl(1).

SysV Msg IPC object class
*************************

NAME
====

   IPC::Msg - SysV Msg IPC object class

SYNOPSIS
========

     use IPC::SysV qw(IPC_PRIVATE S_IRWXU S_IRWXG S_IRWXO);
     use IPC::Msg;

     $msg = new IPC::Msg(IPC_PRIVATE, S_IRWXU | S_IRWXG | S_IRWXO);

     $msg->snd(pack("L a*",$msgtype,$msg));

     $msg->rcv($buf,256);

     $ds = $msg->stat;

     $msg->remove;

DESCRIPTION
===========

METHODS
=======

new ( KEY , FLAGS )
     Creates a new message queue associated with KEY. A new queue is
     created if

        * KEY is equal to `IPC_PRIVATE'

        * KEY does not already  have  a  message queue associated with it,
          and `*FLAGS* & IPC_CREAT' is true.

     On creation of a new message queue FLAGS is used to set the
     permissions.

id
     Returns the system message queue identifier.

rcv ( BUF, LEN [, TYPE [, FLAGS ]] )
     Read a message from the queue. Returns the type of the message read.
     See `msgrcv' in this node

remove
     Remove and destroy the message queue from the system.

set ( STAT )
set ( NAME => VALUE [, NAME => VALUE ...] )
     set will set the following values of the stat structure associated
     with the message queue.

          uid
          gid
          mode (oly the permission bits)
          qbytes

     set accepts either a stat object, as returned by the stat method, or
     a list of name-value pairs.

snd ( TYPE, MSG [, FLAGS ] )
     Place a message on the queue with the data from MSG and with type
     TYPE.  See `msgsnd' in this node.

stat
     Returns an object of type `IPC::Msg::stat' which is a sub-class of
     Class::Struct. It provides the following fields. For a description of
     these fields see you system documentation.

          uid
          gid
          cuid
          cgid
          mode
          qnum
          qbytes
          lspid
          lrpid
          stime
          rtime
          ctime

SEE ALSO
========

   See IPC/SysV, Class/Struct,

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

COPYRIGHT
=========

   Copyright (c) 1997 Graham Barr. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

open a process for both reading and writing
*******************************************

NAME
====

   IPC::Open2, open2 - open a process for both reading and writing

SYNOPSIS
========

     use IPC::Open2;

     $pid = open2(\*RDRFH, \*WTRFH, 'some cmd and args');
       # or without using the shell
     $pid = open2(\*RDRFH, \*WTRFH, 'some', 'cmd', 'and', 'args');

     # or with handle autovivification
     my($rdrfh, $wtrfh);
     $pid = open2($rdrfh, $wtrfh, 'some cmd and args');
       # or without using the shell
     $pid = open2($rdrfh, $wtrfh, 'some', 'cmd', 'and', 'args');

DESCRIPTION
===========

   The open2() function runs the given $cmd and connects $rdrfh for
reading and $wtrfh for writing.  It's what you think should work when you
try

     $pid = open(HANDLE, "|cmd args|");

   The write filehandle will have autoflush turned on.

   If $rdrfh is a string (that is, a bareword filehandle rather than a glob
or a reference) and it begins with `< '& >>, then the child will send
output directly to that file handle.  If $wtrfh is a string that begins
with `< <& '>, then $wtrfh will be closed in the parent, and the child
will read from it directly.  In both cases, there will be a dup(2) instead
of a pipe(2) made.

   If either reader or writer is the null string, this will be replaced by
an autogenerated filehandle.  If so, you must pass a valid lvalue in the
parameter slot so it can be overwritten in the caller, or an exception
will be raised.

   open2() returns the process ID of the child process.  It doesn't return
on failure: it just raises an exception matching `/^open2:/'.  However,
exec failures in the child are not detected.  You'll have to trap SIGPIPE
yourself.

   open2() does not wait for and reap the child process after it exits.
Except for short programs where it's acceptable to let the operating system
take care of this, you need to do this yourself.  This is normally as
simple as calling `waitpid $pid, 0' when you're done with the process.
Failing to do this can result in an accumulation of defunct or "zombie"
processes.  See `waitpid', see Perlfunc (perl.info), for more
information.

   This whole affair is quite dangerous, as you may block forever.  It
assumes it's going to talk to something like *bc*, both writing to it and
reading from it.  This is presumably safe because you "know" that commands
like *bc* will read a line at a time and output a line at a time.
Programs like sort that read their entire input stream first, however, are
quite apt to cause deadlock.

   The big problem with this approach is that if you don't have control
over source code being run in the child process, you can't control what it
does with pipe buffering.  Thus you can't just open a pipe to `cat -v' and
continually read and write a line from it.

   The IO::Pty and Expect modules from CPAN can help with this, as they
provide a real tty (well, a pseudo-tty, actually), which gets you back to
line buffering in the invoked command again.

WARNING
=======

   The order of arguments differs from that of open3().

SEE ALSO
========

   See IPC/Open3, for an alternative that handles STDERR
as well.  This function is really just a wrapper around open3().

open a process for reading, writing, and error handling
*******************************************************

NAME
====

   IPC::Open3, open3 - open a process for reading, writing, and error
handling

SYNOPSIS
========

     $pid = open3(\*WTRFH, \*RDRFH, \*ERRFH,
     		    'some cmd and args', 'optarg', ...);

     my($wtr, $rdr, $err);
     $pid = open3($wtr, $rdr, $err,
     		    'some cmd and args', 'optarg', ...);

DESCRIPTION
===========

   Extremely similar to open2(), open3() spawns the given $cmd and
connects RDRFH for reading, WTRFH for writing, and ERRFH for errors.  If
ERRFH is false, or the same file descriptor as RDRFH, then STDOUT and
STDERR of the child are on the same filehandle.  The WTRFH will have
autoflush turned on.

   If WTRFH begins with `< <& '>, then WTRFH will be closed in the parent,
and the child will read from it directly.  If RDRFH or ERRFH begins with
`< '& >>, then the child will send output directly to that filehandle.  In
both cases, there will be a dup(2) instead of a pipe(2) made.

   If either reader or writer is the null string, this will be replaced by
an autogenerated filehandle.  If so, you must pass a valid lvalue in the
parameter slot so it can be overwritten in the caller, or an exception
will be raised.

   open3() returns the process ID of the child process.  It doesn't return
on failure: it just raises an exception matching `/^open3:/'.  However,
exec failures in the child are not detected.  You'll have to trap SIGPIPE
yourself.

   open2() does not wait for and reap the child process after it exits.
Except for short programs where it's acceptable to let the operating system
take care of this, you need to do this yourself.  This is normally as
simple as calling `waitpid $pid, 0' when you're done with the process.
Failing to do this can result in an accumulation of defunct or "zombie"
processes.  See `waitpid', see Perlfunc (perl.info), for more
information.

   If you try to read from the child's stdout writer and their stderr
writer, you'll have problems with blocking, which means you'll want to use
select() or the IO::Select, which means you'd best use sysread() instead
of readline() for normal stuff.

   This is very dangerous, as you may block forever.  It assumes it's
going to talk to something like *bc*, both writing to it and reading from
it.  This is presumably safe because you "know" that commands like *bc*
will read a line at a time and output a line at a time.  Programs like
sort that read their entire input stream first, however, are quite apt to
cause deadlock.

   The big problem with this approach is that if you don't have control
over source code being run in the child process, you can't control what it
does with pipe buffering.  Thus you can't just open a pipe to `cat -v' and
continually read and write a line from it.

WARNING
=======

   The order of arguments differs from that of open2().

Run subprocesses w/ piping, redirection, and pseudo-ttys
********************************************************

NAME
====

   IPC::Run - Run subprocesses w/ piping, redirection, and pseudo-ttys

SYNOPSIS
========

     use IPC::Run (
        qw( run ),                       # Batch mode API
        qw( harness start pump finish ), # Intermittent API
        qw( io timer timeout ),          # Helper objects.
     ) ;

     my @cat = qw( cat in.txt - ) ;

     ## Running a command with stdin closed, output redirected
     ## to scalars and a 10 second timeout:
     run \@cat, \undef, \$out, \$err, timeout( 10 )
        or die "cat returned $?";

     ## Redirecting stdin from various scalars:
     $in = "input" ;
     run \@cat, \$in,      \$out, \$err, ... ;
     run \@cat, \"input",  \$out, \$err, ... ;
     run \@cat, \<<TOHERE, \$out, \$err, ... ;
     input
     TOHERE

     ## I/O redirection using functions, filenames.  You can mix
     ## techniques, too.
     run \@cat, \&in,      \&out, \&err ... ;
     run \@cat, '<', $in_filename, '>', $out_name, '2>', $err_name ... ;

     ## Redirecting using psuedo-terminals.
     run \@cat, '<pty<', \$in,  '>pty>', \$out_and_err ;
     run \@cat, '<pty<', \&in,  '>pty>', \&out_and_err ;

     # Incrementally read from / write to scalars.  Note that $in_q
     # is a queue that is drained as it is used, which is not the
     # way run() treats inputs.  $h is for "harness".
        my $h = start(
           \@cat, \$in_q, \$out_q, \$err_q,
     	 timeout( name => "process timeout", 10 ),
     	 $stall_timeout = timeout( name => "stall timeout", 5 ),
        ) ;

     $in_q .= "some input\n" ;
     $stall_timeout->start ;
     pump $h until $out_q =~ /input/ ;
     warn $err_q ;
     $err_q = '' ;
     $out_q = '' ;

     $stall_timeout->start ;
     $in_q .= "some more input\n" ;
     pump $h until $out_q =~ /input/ ;
     warn $err_q ;
     $err_q = '' ;

     $in_q .= "some final input\n" ;
     $h->timeout( "1:00" ) ;
     $stall_timeout->start ;
     finish $h or die "cat returned $?" ;
     warn $err_q ;
     print $out_q ;

     # Piping between children
        run \@cat, '|', [qw(gzip)] ;

     # Multiple children simultaneously (run() blocks until all
     # children exit, use start() for background execution):
        run [qw(foo1)], '&', [qw(foo2)] ;

     # Spawning a subroutine (only on systems with true fork()/exec())
        run \&child_sub, \$in, \$out ;

     # Calling \&set_up_child in the child before it executes the
     # command (only works on systems with true fork() & exec())
        run \@cat, \$in, \$out,
           init => \&set_up_child ;

     # Append output to named files
        run( \@cat, '>>', $out_f_name, '2>>', $err_f_name ) ;

     # Read from / write to file handles you open and close
        open IN,  '<in.txt'  or die $! ;
        open OUT, '>out.txt' or die $! ;
        print OUT "preamble\n" ;
        run \@cat, \*IN, \*OUT or die "cat returned $?" ;
        print OUT "postamble\n" ;
        close IN ;
        close OUT ;

     # Create pipes for you to read / write (like IPC::Open2 & 3).
        $h = start
           \@cat,
     	    '<pipe', \*IN,
     	    '>pipe', \*OUT,
     	    '2>pipe', \*ERR
     	 or die "cat returned $?" ;
        print IN "some input\n" ;
        close IN ;
        print <OUT>, <ERR> ;
        finish $h ;

     # Mixing input and output modes
        run \@cat, 'in.txt', \&catch_some_out, \*ERR_LOG ) ;

     # Other redirection constructs
        run \@cat, '>&', \$out_and_err ;
        run \@cat, '2>&1' ;
        run \@cat, '0<&3' ;
        run \@cat, '<&-' ;
        run \@cat, '3<', \$in3 ;
        run \@cat, '4>', \$out4 ;
        # etc.

     # Passing options:
        run \@cat, 'in.txt', debug => 1 ;

     # Call this system's shell, returns TRUE on 0 exit code
     # THIS IS THE OPPOSITE SENSE OF system()'s RETURN VALUE
        run "cat a b c" or die "cat returned $?" ;

     # Launch a sub process directly, no shell.  Can't do redirection
     # with this form, it's here to behave like system() with an
     # inverted result.
        $r = run "cat a b c" ;

     # Read from a file in to a scalar
        run io( "filename", 'r', \$recv ) ;
        run io( \*HANDLE,   'r', \$recv ) ;

DESCRIPTION
===========

   IPC::Run allows you run and interact with child processes, files, pipes,
and pseudo-ttys.  Both event-loop and procedural techniques are supported
and may be mixed.  Likewise, functional and OO API styles are both
supported and may be mixed.

   Various redirection operators reminiscent of those seen on common Unix
and DOS command lines are provided.

Harnesses
---------

   Child processes and I/O handles are gathered in to a harness, then run
until the processing is finished or aborted.

run() vs. start(); pump(); finish();
------------------------------------

   There are two modes you can run harnesses in: incremental and batch.
In incremental mode, you use start() and pump() to activate the harness
and interact with it, then switch to batch mode and use run() or finish()
to let the harness run to completion.

   In batch mode, you just use run() or start() and finish() and let things
run to completion.

   In batch mode, all data to be sent to the harness is set up in advance,
the harness is run and all output is collected from it, then any child
processes are waited for:

     run \@cmd, \<<IN, \$out ;
     blah
     IN

   Incremental mode is provided by start(), pump(), and finish():

     my $h = start \@cat, \$in_q, \$out_q, \$err_q ;
     $in_q = "first input\n" ;

     pump $h while length $in_q ;
     warn $err_q if length $err_q ;
     $err_q = '' ;

     $in_q = "second input\n" ;
     pump $h until $out_q =~ /second input/ ;

     $h->finish ;

   You can compile the harness with harness() prior to start()ing, and you
may omit start() between harness() and pump().  You might want to do these
things if you compile your harnesses ahead of time.

   You may call timeout() at any time in this process.  If it is called
before start() (or the first pump(), if start() is omitted), then the
timer is started just after all the child processes have been fork()ed or
spawn()ed.

   If you call it once the children have been start()ed, the timeout timer
is restarted.  So this sequence:

     my $h = harness \@cat, \$in_q, \$out_q, \$err_q ;
     $h->timeout( 10 ) ;
     sleep 11 ;  # No effect: timer not running yet

     start $h ;
     $in_q = "foo\n" ;
     pump $h until ! length $in_q ;
     ## 10 (or little more) may pass til this line.

     $in_q = "bar\n" ;
     $h->timeout( 1 ) ;
     ## Timer is now running, but will elapse after 1 second
     pump $h until ! length $in_q ;
     ## 1 seconds (or a little more) may pass til this line.

     $h->timeout( 30 ) ;
     $h->finish ;

   The timeout does not include the time it takes to wait for the children
to exit, either.

Syntax
------

   run(), start(), and harness() can all take a harness specification as
input.  A harness specification is either a single string to be passed to
the systems' shell:

     run "echo 'hi there'" ;

   or a list of commands, io operations, and/or timers/timeouts to execute.
Consecutive commands must be separated by a pipe operator '|' or an '&'.
External commands are passed in as array references, and, on systems
supporting fork(), Perl code may be passed in as subs:

     run \@cmd ;
     run \@cmd1, '|', \@cmd2 ;
     run \@cmd1, '&', \@cmd2 ;
     run \&sub1 ;
     run \&sub1, '|', \&sub2 ;
     run \&sub1, '&', \&sub2 ;

   '|' pipes the stdout of \@cmd1 the stdin of \@cmd2, just like a shell
pipe.  '&' does not.  Child processes to the right of a '&' will have
their stdin closed unless it's redirected-to.

   See IPC/Run/IO, objects may be passed in as well, whether
or not child processes are also specified:

     run io( "infile", ">", \$in ), io( "outfile", "<", \$in ) ;

     as can L<IPC::Run::Timer> objects:

     run \@cmd, io( "outfile", "<", \$in ), timeout( 10 ) ;

   Commands may be followed by scalar, sub, or i/o handle references for
redirecting child process input & output:

     run \@cmd,  \undef,            \$out ;
     run \@cmd,  \$in,              \$out ;
     run \@cmd1, \&in, '|', \@cmd2, \*OUT ;
     run \@cmd1, \*IN, '|', \@cmd2, \&out ;

   This is known as succinct redirection syntax, since run(), start() and
harness(), figure out which file descriptor to redirect and how.  File
descriptor 0 is presumed to be an input for the child process, all others
are outputs.  The assumed file descriptor always starts at 0, unless the
command is being piped to, in which case it starts at 1.

   To be explicit about your redirects, or if you need to do more complex
things, there's also a redirection operator syntax:

     run \@cmd, '<', \undef, '>',  \$out ;
     run \@cmd, '<', \undef, '>&', \$out_and_err ;
     run(
        \@cmd1,
           '<', \$in,
        '|', \@cmd2,
           \$out
     ) ;

   Operator syntax is required if you need to do something other than
simple redirection to/from scalars or subs, like duping or closing file
descriptors or redirecting to/from a named file.  The operators are
covered in detail below.

   After each \@cmd (or \&foo), parsing begins in succinct mode and
toggles to operator syntax mode when an operator (ie plain scalar, not a
ref) is seen.  Once in operator syntax mode, parseing only reverts to
succinct mode when a '|' or '&' is seen.

   In succinct mode, each parameter after the \@cmd specifies what to do
with the next highest file descriptor. These File descriptor start with 0
(stdin) unless stdin is being piped to (`'|', \@cmd'), in which case they
start with 1 (stdout).  Currently, being on the left of a pipe (`\@cmd,
\$out, \$err, '|'') does not cause stdout to be skipped, though this may
change since it's not as DWIMerly as it could be.  Only stdin is assumed
to be an input in succinct mode, all others are assumed to be outputs.

   If no piping or redirection is specified for a child, it will inherit
the parent's open file descriptors as dictated by your system's
close-on-exec behavior and the $^F flag, except that processes after a '&'
will not inherit the parent's stdin.  Such processes will have their stdin
closed unless it has been redirected-to.

   If you want to close a child processes stdin, you may do any of:

     run \@cmd, \undef ;
     run \@cmd, \"" ;
     run \@cmd, '<&-' ;
     run \@cmd, '0<&-' ;

   Redirection is done by placing redirection specifications immediately
after a command or child subroutine:

     run \@cmd1,      \$in, '|', \@cmd2,      \$out ;
     run \@cmd1, '<', \$in, '|', \@cmd2, '>', \$out ;

   If you omit the redirection operators, descriptors are counted starting
at 0.  Descriptor 0 is assumed to be input, all others are outputs.  A
leading '|' consumes descriptor 0, so this works as expected.

     run \@cmd1, \$in, '|', \@cmd2, \$out ;

     The parameter following a redirection operator can be a scalar ref,
     a subroutine ref, a file name, an open filehandle, or a closed
     filehandle.

   If it's a scalar ref, the child reads input from or sends output to
that variable:

     $in = "Hello World.\n" ;
     run \@cat, \$in, \$out ;
     print $out ;

   Scalars used in incremental (start()/pump()/finish()) applications are
treated as queues: input is removed from input scalers, resulting in them
dwindling to ", and output is appended to output scalars.  This is not
true of harnesses run() in batch mode.

   It's usually wise to append new input to be sent to the child to the
input queue, and you'll often want to zap output queues to " before
pumping.

     $h = start \@cat, \$in_q ;
     $in_q = "line 1\n" ;
     pump $h ;
     $in_q .= "line 2\n" ;
     pump $h ;
     $in_q .= "line 3\n" ;
     finish $h ;

   The final call to finish() must be there: it allows the child
process(es) to run to completion and waits for their exit values.

OBSTINATE CHILDREN
==================

   Interactive applications are usually optimized for human use.  This can
help or hinder trying to interact with them through modules like IPC::Run.
Frequently, programs alter their behavior when they detect that stdin,
stdout, or stderr are not connected to a tty, assuming that they are being
run in batch mode.  Whether this helps or hurts depends on which
optimizations change.  And there's often no way of telling what a program
does in these areas other than trial and error and, occasionally, reading
the source.  This includes different versions and implementations of the
same program.

   All hope is not lost, however.  Most programs behave in reasonably
tractable manners, once you figure out what it's trying to do.

   Here are some of the issues you might need to be aware of.

   * fflush()ing stdout and stderr

     This lets the user see stdout and stderr immediately.  Many programs
     undo this optimization if stdout is not a tty, making them harder to
     manage by things like IPC::Run.

     Many programs decline to fflush stdout or stderr if they do not
     detect a tty there.  Some ftp commands do this, for instance.

     If this happens to you, look for a way to force interactive behavior,
     like a command line switch or command.  If you can't, you will need
     to use a pseudo terminal ('<pty<' and '>pty>').

   * false prompts

     Interactive programs generally do not guarantee that output from user
     commands won't contain a prompt string.  For example, your shell
     prompt might be a '$', and a file named '$' might be the only file in
     a directory listing.

     This can make it hard to guarantee that your output parser won't be
     fooled into early termination of results.

     To help work around this, you can see if the program can alter it's
     prompt, and use something you feel is never going to occur in actual
     practice.

     You should also look for your prompt to be the only thing on a line:

          pump $h until $out =~ /^<SILLYPROMPT>\s?\z/m ;

     (use `(?!\n)\Z' in place of `\z' on older perls).

     You can also take the approach that IPC::ChildSafe takes and emit a
     command with known output after each 'real' command you issue, then
     look for this known output.  See new_appender() and new_chunker() for
     filters that can help with this task.

     If it's not convenient or possibly to alter a prompt or use a known
     command/response pair, you might need to autodetect the prompt in case
     the local version of the child program is different then the one you
     tested with, or if the user has control over the look & feel of the
     prompt.

   * Refusing to accept input unless stdin is a tty.

     Some programs, for security reasons, will only accept certain types
     of input from a tty.  su, notable, will not prompt for a password
     unless it's connected to a tty.

     If this is your situation, use a pseudo terminal ('<pty<' and
     '>pty>').

   * Not prompting unless connected to a tty.

     Some programs don't prompt unless stdin or stdout is a tty.  See if
     you can turn prompting back on.  If not, see if you can come up with
     a command that you can issue after every real command and look for
     it's output, as IPC::ChildSafe does.   There are two filters included
     with IPC::Run that can help with doing this: appender and chunker
     (see new_appender() and new_chunker()).

   * Different output format when not connected to a tty.

     Some commands alter their formats to ease machine parsability when
     they aren't connected to a pipe.  This is actually good, but can be
     suprising.

PSEUDO TERMINALS
================

   On systems providing pseudo terminals under /dev, IPC::Run can use
IO::Pty (available on CPAN) to provide a terminal environment to
subprocesses.  This is necessary when the subprocess really wants to think
it's connected to a real terminal.

CAVEATS
-------

   Psuedo-terminals are not pipes, though they are similar.  Here are some
differences to watch out for.

Echoing
     Sending to stdin will cause an echo on stdout, which occurs before
     each line is passed to the child program.  There is currently no way
     to disable this.

Shutdown
     IPC::Run cannot close a pty until all output has been collected.
     This means that it is not possible to send an EOF to stdin by
     half-closing the pty, as we can when using a pipe to stdin.

     This means that you need to send the child process an exit command or
     signal, or run() / finish() will time out.  Be careful not to expect
     a prompt after sending the exit command.

Command line editing
     Some subprocesses, notable shells that depend on the user's prompt
     settings, will reissue the prompt plus the command line input so far
     once for each character.

'>pty>' means '&>pty>', not '1>pty>'
     The pseudo terminal redirects both stdin and stdout unless you specify
     a file desciptor.  If you want to grab stderr separately, do this:

          start \@cmd, '<pty<', \$in, '>pty>', \$out, '2>', \$err ;

stdin, stdout, and stderr not inherited
     Child processes harnessed to a pseudo terminal have their stdin,
     stdout, and stderr completely closed before any redirection operators
     take effect.  This casts of the bonds of the controlling terminal.
     This is not done when using pipes.

     Right now, this affects all children in a harness that has a pty in
     use, even if that pty would not affect a particular child.  That's a
     bug and will be fixed.  Until it is, it's best not to mix-and-match
     children.

Redirection Operators
---------------------

     Operator       SHNP   Description
     ========       ====   ===========
     <, N<          SHN    Redirects input to a child's fd N (0 assumed)

     >, N>          SHN    Redirects output from a child's fd N (1 assumed)
     >>, N>>        SHN    Like '>', but appends to scalars or named files
     >&, &>         SHN    Redirects stdout & stderr from a child process

     <pty, N<pty    S      Like '<', but uses a pseudo-tty instead of a pipe
     >pty, N>pty    S      Like '>', but uses a pseudo-tty instead of a pipe

     N<&M                  Dups input fd N to input fd M
     M>&N                  Dups output fd N to input fd M
     N<&-                  Closes fd N

     <pipe, N<pipe     P   Pipe opens H for caller to read, write, close.
     >pipe, N>pipe     P   Pipe opens H for caller to read, write, close.

   'N' and 'M' are placehodlers for integer file descriptor numbers.  The
terms 'input' and 'output' are from the child process's perspective.

   The SHNP field indicates what parameters an operator can take:

     S: \$scalar or \&function references.  Filters may be used with
        these operators (and only these).
     H: \*HANDLE or IO::Handle for caller to open, and close
     N: "file name".
     P: \*HANDLE opened by IPC::Run as the parent end of a pipe, but read
        and written to and closed by the caller (like IPC::Open3).

Redirecting input: [n]<, [n]<pipe
     You can input the child reads on file descriptor number n to come
     from a scalar variable, subroutine, file handle, or a named file.  If
     stdin is not redirected, the parent's stdin is inherited.

          run \@cat, \undef          ## Closes child's stdin immediately
             or die "cat returned $?" ;

          run \@cat, \$in ;

          run \@cat, \<<TOHERE ;
          blah
          TOHERE

          run \@cat, \&input ;       ## Calls &input, feeding data returned
                                     ## to child's.  Closes child's stdin
          			      ## when undef is returned.

     Redirecting from named files requires you to use the input
     redirection operator:

          run \@cat, '<.profile' ;
          run \@cat, '<', '.profile' ;

          open IN, "<foo" ;
          run \@cat, \*IN ;
          run \@cat, *IN{IO} ;

     The form used second example here is the safest, since filenames like
     "0" and "&more\n" won't confuse &run:

     You can't do either of

          run \@a, *IN ;      ## INVALID
          run \@a, '<', *IN ; ## BUGGY: Reads file named like "*main::A"

          because perl passes a scalar containing a string that
          looks like "*main::A" to &run, and &run can't tell the difference
          between that and a redirection operator or a file name.  &run guarantees
          that any scalar you pass after a redirection operator is a file name.

     If your child process will take input from file descriptors other
     than 0 (stdin), you can use a redirection operator with any of the
     valid input forms (scalar ref, sub ref, etc.):

          run \@cat, '3<', \$in3_q ;

     When redirecting input from a scalar ref, the scalar ref is used as a
     queue.  This allows you to use &harness and pump() to feed
     incremental bits of input to a coprocess.  See `' in this node below
     for more information.

     The <pipe operator opens the write half of a pipe on the filehandle
     glob reference it takes as an argument:

          $h = start \@cat, '<pipe', \*IN ;
          print IN "hello world\n" ;
          pump $h ;
          close IN ;
          finish $h ;

     Unlike the other '<' operators, IPC::Run does nothing further with
     it: you are responsible for it.  The previous example is functionally
     equivalent to:

          pipe( \*R, \*IN ) or die $! ;
          $h = start \@cat, '<', \*IN ;
          print IN "hello world\n" ;
          pump $h ;
          close IN ;
          finish $h ;

     This is like the behavior of IPC::Open2 and IPC::Open3.

Redirecting output: [n]>, [n]>>, [n]>&[m], [n]>pipe
     You can redirect any output the child emits to a scalar variable,
     subroutine, file handle, or file name.  You can have &run truncate or
     append to named files or scalars.  If you are redirecting stdin as
     well, or if the command is on the receiving end of a pipeline ('|'),
     you can omit the redirection operator:

          @ls = ( 'ls' ) ;
          run \@ls, \undef, \$out
             or die "ls returned $?" ;

          run \@ls, \undef, \&out ;  ## Calls &out each time some output
                                     ## is received from the child's
          			      ## when undef is returned.

          run \@ls, \undef, '2>ls.err' ;
          run \@ls, '2>', 'ls.err' ;

     The two parameter form guarantees that the filename will not be
     interpreted as a redirection operator:

          run \@ls, '>', "&more" ;
          run \@ls, '2>', ">foo\n" ;

     You can pass file handles you've opened for writing:

          open( *OUT, ">out.txt" ) ;
          open( *ERR, ">err.txt" ) ;
          run \@cat, \*OUT, \*ERR ;

     Passing a scalar reference and a code reference requires a little
     more work, but allows you to capture all of the output in a scalar or
     each piece of output by a callback:

     These two do the same things:

          run( [ 'ls' ], '2>', sub { $err_out .= $_[0] } ) ;

     does the same basic thing as:

          run( [ 'ls' ], '2>', \$err_out ) ;

     The subroutine will be called each time some data is read from the
     child.

     The >pipe operator is different in concept than the other '>'
     operators, although it's syntax is similar:

          $h = start \@cat, $in, '>pipe', \*OUT, '2>pipe', \*ERR ;
          $in = "hello world\n" ;
          finish $h ;
          print <OUT> ;
          print <ERR> ;
          close OUT ;
          close ERR ;

     causes two pipe to be created, with one end attached to cat's stdout
     and stderr, respectively, and the other left open on OUT and ERR, so
     that the script can manually read(), select(), etc. on them.  This is
     like the behavior of IPC::Open2 and IPC::Open3.

Duplicating output descriptors: >&m, n>&m
     This duplicates output descriptor number n (default is 1 if n is
     ommitted) from descriptor number m.

Duplicating input descriptors: <&m, n<&m
     This duplicates input descriptor number n (default is 0 if n is
     ommitted) from descriptor number m

Closing descriptors: <&-, 3<&-
     This closes descriptor number n (default is 0 if n is ommitted).  The
     following commands are equivalent:

          run \@cmd, \undef ;
          run \@cmd, '<&-' ;
          run \@cmd, '<in.txt', '<&-' ;

     Doing

          run \@cmd, \$in, '<&-' ;    ## SIGPIPE recipe.

     is dangerous: the parent will get a SIGPIPE if $in is not empty.

Redirecting both stdout and stderr: &>, >&, &>pipe, >pipe&
     The following pairs of commands are equivalent:

          run \@cmd, '>&', \$out ;       run \@cmd, '>', \$out,     '2>&1' ;
          run \@cmd, '>&', 'out.txt' ;   run \@cmd, '>', 'out.txt', '2>&1' ;

     etc.

     File descriptor numbers are not permitted to the left or the right of
     these operators, and the '&' may occur on either end of the operator.

     The '&>pipe' and '>pipe&' variants behave like the '>pipe' operator,
     except that both stdout and stderr write to the created pipe.

Redirection Filters
     Both input redirections and output redirections that use scalars or
     subs as endpoints may have an arbitrary number of filter subs placed
     between them and the child process.  This is useful if you want to
     receive output in chunks, or if you want to massage each chunk of
     data sent to the child.  To use this feature, you must use operator
     syntax:

          run(
             \@cmd
                '<', \&in_filter_2, \&in_filter_1, $in,
                '>', \&out_filter_1, \&in_filter_2, $out,
          ) ;

     This capability is not provided for IO handles or named files.

     Two filters are provided by IPC::Run: appender and chunker.  Because
     these may take an argument, you need to use the constructor fuinctions
     new_appender() and new_chunker() rather than using \& syntax:

          run(
             \@cmd
                '<', new_appender( "\n" ), $in,
                '>', new_chunker, $out,
          ) ;

Just doing I/O
--------------

   If you just want to do I/O to a handle or file you open yourself, you
may specify a filehandle or filename instead of a command in the harness
specification:

     run io( "filename", '>', \$recv ) ;

     $h = start io( $io, '>', \$recv ) ;

     $h = harness \@cmd, '&', io( "file", '<', \$send ) ;

Options
-------

   Options are passed in as name/value pairs:

     run \@cat, \$in, debug => 1 ;

   If you pass the debug option, you may want to pass it in first, so you
can see what parsing is going on:

     run debug => 1, \@cat, \$in ;

debug
     Enables debugging output in parent and child.  Children emit debugging
     info over a separate, dedicated pipe to the parent, so you must
     pump(), pump_nb(), or finish() if you use start().  This pipe is not
     created unless debugging is enabled.

RETURN VALUES
=============

   harness() and start() return a reference to an IPC::Run harness.  This
is blessed in to the IPC::Run package, so you may make later calls to
functions as members if you like:

     $h = harness( ... ) ;
     $h->start ;
     $h->pump ;
     $h->finish ;

     $h = start( .... ) ;
     $h->pump ;
     ...

   Of course, using method call syntax lets you deal with any IPC::Run
subclasses that might crop up, but don't hold your breath waiting for any.

   run() and finish() return TRUE when all subcommands exit with a 0 result
code.  *This is the opposite of perl's system() command*.

   All routines raise exceptions (via die()) when error conditions are
recognized.  A non-zero command result is not treated as an error
condition, since some commands are tests whose results are reported in
their exit codes.

ROUTINES
========

run
     Run takes a harness or harness specification and runs it, pumping all
     input to the child(ren), closing the input pipes when no more input
     is available, collecting all output that arrives, until the pipes
     delivering output are closed, then waiting for the children to exit
     and reaping their result codes.

     You may think of `run( ... )' as being like

          start( ... )->finish() ;

     , though there is one subtle difference: run() does not set
     \$input_scalars to " like finish() does.

harness
     Takes a harness specification and returns a harness.  This harness is
     blessed in to IPC::Run, allowing you to use method call syntax for
     run(), start(), et al if you like.

     harness() is provided so that you can pre-build harnesses if you
     would like to, but it's not required..

     You may proceed to run(), start() or pump() after calling harness()
     (pump() calls start() if need be).  Alternatively, you may pass your
     harness specification to run() or start() and let them harness() for
     you.  You can't pass harness specifications to pump(), though.

close_terminal
     This is used as (or in) an init sub to cast off the bonds of a
     controlling terminal.  It must precede all other redirection ops that
     affect STDIN, STDOUT, or STDERR to be guaranteed effective.

start
          $h = start(
             \@cmd, \$in, \$out, ...,
             timeout( 30, name => "process timeout" ),
             $stall_timeout = timeout( 10, name => "stall timeout"   ),
          ) ;

          $h = start \@cmd, '<', \$in, '|', \@cmd2, ... ;

     start() accepts a harness or harness specification and returns a
     harness after building all of the pipes and launching (via
     fork()/exec(), or, maybe someday, spawn()) all the child processes.
     It does not send or receive any data on the pipes, see pump() and
     finish() for that.

     You may call harness() and then pass it's result to start() if you
     like, but you only need to if it helps you structure or tune your
     application.  If you do call harness(), you may skip start() and
     proceed directly to pump.

     start() also starts all timers in the harness.  See
     IPC/Run/Timer, for more information.

     start() flushes STDOUT and STDERR to help you avoid duplicate output.
     It has no way of asking Perl to flush all your open filehandles, so
     you are going to need to flush any others you have open.  Sorry.

     Here's how if you don't want to alter the state of $| for your
     filehandle:

          $ofh = select HANDLE ; $of = $| ; $| = 1 ; $| = $of ; select $ofh;

     If you don't mind leaving output unbuffered on HANDLE, you can do the
     slightly shorter

          $ofh = select HANDLE ; $| = 1 ; select $ofh;

     Or, you can use IO::Handle's flush() method:

          use IO::Handle ;
          flush HANDLE ;

     Perl needs the equivalent of C's fflush( (FILE *)NULL ).

pump
          pump $h ;
          $h->pump ;

     Pump accepts a single parameter harness.  It blocks until it delivers
     some input or recieves some output.  It returns TRUE if there is
     still input or output to be done, FALSE otherwise.

     pump() will automatically call start() if need be, so you may call
     harness() then proceed to pump() if that helps you structure your
     application.

     Calling pump() when there is no more i/o do be done causes a "process
     ended prematurely" exception to be thrown.  This allows fairly simple
     scripting of external applications without having to add lots of
     error handling code at each step of the script:

          $h = harness \@smbclient, \$in_q, \$out_q, $err_q ;

          $in_q = "cd /foo\n" ;
          $h->pump until $out_q =~ /^smb.*> \Z/m ;
          die "error cding to /foo:\n$out_q" if $out_q =~ "ERR" ;
          $out_q = '' ;

          $in_q = "mget *\n" ;
          $h->pump until $out_q =~ /^smb.*> \Z/m ;
          die "error retrieving files:\n$out_q" if $out_q =~ "ERR" ;

          $h->finish ;

          warn $err_q if $err_q ;

pump_nb
          pump_nb $h ;
          $h->pump_nb ;

     "pump() non-blocking", pumps if anything's ready to be pumped, returns
     immediately otherwise.  This is useful if you're doing some
     long-running task in the foreground, but don't want to starve any
     child processes.

pumpable
     Returns TRUE if calling pump() won't throw an immediate "process ended
     prematurely" exception.  Reflects the value returned from the last
     call to pump().

finish
     This must be called after the last start() or pump() call for a
     harness, or your system will accumulate defunct processes and you may
     "leak" file descriptors.

     finish() returns TRUE if all children returned 0 (and were not
     signaled and did not coredump, ie ! $?), and FALSE otherwise (this is
     like run(), and the opposite of system()).

     Once a harness has been finished, it may be run() or start()ed again,
     including by pump()s auto-start.

result
          $h->result ;

     Returns the first non-zero result code (ie $? >> 8).  See `' in this
     node to get the $? value for a child process.

     To get the result of a particular child, do:

          $h->result( 0 ) ;  # first child's $? >> 8
          $h->result( 1 ) ;  # second child

     or

          ($h->results)[0]
          ($h->results)[1]

     Returns undef if no child processes were spawned and no child number
     was specified.  Throws an exception if an out-of-range child number
     is passed.

results
     Returns a list of child exit values.  See `' in this node if you want
     to know if a signal killed the child.

     Throws an exception if the harness is not in a finished state.

     =cut

     sub results {    &_assert_finished ;    my IPC::Run $self = shift ;

          return map $_->{RESULT} >> 8, @{$self->{KIDS}} ;
          }

full_result
          $h->full_result ;

     Returns the first non-zero $?.  See `' in this node to get the first
     $? >> 8 value for a child process.

     To get the result of a particular child, do:

          $h->full_result( 0 ) ;  # first child's $? >> 8
          $h->full_result( 1 ) ;  # second child

     or

          ($h->full_results)[0]
          ($h->full_results)[1]

     Returns undef if no child processes were spawned and no child number
     was specified.  Throws an exception if an out-of-range child number
     is passed.

full_results
     Returns a list of child exit values as returned by wait.  See `' in
     this node if you don't care about coredumps or signals.

     Throws an exception if the harness is not in a finished state.

     =cut

     sub full_results {    &_assert_finished ;    my IPC::Run $self =
     shift ;

          croak "Harness not run" unless $self->{STATE} >= _finished ;
          croak "Harness not finished running" unless $self->{STATE} == _finished ;

          return map $_->{RESULT}, @{$self->{KIDS}} ;
          }

     ## ## Filter Scaffolding ## use vars ( '$filter_op',        ## The op
     running a filter chain right now '$filter_num'        ## Which filter
     is being run right now.  ) ;

     ## ## A few filters and filter constructors ##

FILTERS
=======

   These filters are used to modify input our output between a child
process and a scalar or subroutine endpoint.

new_chunker
     This breaks a stream of data in to chunks, based on an optional
     scalar or regular expression parameter.  The default is the Perl
     input record separator in $/, which is a newline be default.

          run( \@cmd,
             '>', new_chunker, \&lines_handler,
          ) ;

          run( \@cmd,
             '>', new_chunker( "\r\n" ), \&lines_handler,
          ) ;

     Because this uses $/ by default, you should always pass in a parameter
     if you are worried about other code (modules, etc) modifying $/.

     If this filter is last in a filter chain that dumps in to a scalar,
     the scalar must be set to " before a new chunk will be written to it.

     As an example of how a filter like this can be written, here's a
     chunker that splits on newlines:

          sub line_splitter {
             my ( $in_ref, $out_ref ) = @_ ;

          return 0 if length $$out_ref ;

          return input_avail && do {
          	 while (1) {
          	    if ( $$in_ref =~ s/\A(.*?\n)// ) {
          	       $$out_ref .= $1 ;
          	       return 1 ;
          	    }
                my $hmm = get_more_input ;
          	    unless ( defined $hmm ) {
          	       $$out_ref = $$in_ref ;
          	       $$in_ref = '' ;
          	       return length $$out_ref ? 1 : 0 ;
          	    }
          	    return 0 if $hmm eq 0 ;
          	 }
          }
             } ;

new_appender
     This appends a fixed string to each chunk of data read from the source
     scalar or sub.  This might be useful if you're writing commands to a
     child process that always must end in a fixed string, like "\n":

          run( \@cmd,
             '<', new_appender( "\n" ), \&commands,
          ) ;

     Here's a typical filter sub that might be created by new_appender():

          sub newline_appender {
             my ( $in_ref, $out_ref ) = @_ ;

          return input_avail && do {
          	 $$out_ref = join( '', $$out_ref, $$in_ref, "\n" ) ;
          	 $$in_ref = '' ;
          	 1 ;
          }
             } ;

timer
          $h = start( \@cmd, \$in, \$out, $t = timer( 5 ) ) ;

          pump $h until $out =~ /expected stuff/ || $t->is_expired ;

     Instantiates a non-fatal timer.  pump() returns once each time a timer
     expires.  Has no direct effect on run(), but you can pass a subroutine
     to fire when the timer expires.

     See `' in this node for building timers that throw exceptions on
     expiration.

     See `timer', see IPC/Run/Timer, for details.

timeout
          $h = start( \@cmd, \$in, \$out, $t = timeout( 5 ) ) ;

          pump $h until $out =~ /expected stuff/ ;

     Instantiates a timer that throws an exception when it expires.  If
     you don't provide an exception, a default exception that matches
     /^IPC::Run: .*timed out/ is thrown by default.  You can pass in your
     own exception scalar or reference:

          $h = start(
             \@cmd, \$in, \$out,
             $t = timeout( 5, exception => 'slowpoke' ),
          ) ;

     or set the name used in debugging message and in the default exception
     string:

          $h = start(
             \@cmd, \$in, \$out,
             timeout( 50, name => 'process timer' ),
             $stall_timer = timeout( 5, name => 'stall timer' ),
          ) ;

          pump $h until $out =~ /started/ ;

          $in = 'command 1' ;
          $stall_timer->start ;
          pump $h until $out =~ /command 1 finished/ ;

          $in = 'command 2' ;
          $stall_timer->start ;
          pump $h until $out =~ /command 2 finished/ ;

          $in = 'very slow command 3' ;
          $stall_timer->start( 10 ) ;
          pump $h until $out =~ /command 3 finished/ ;

          $stall_timer->start( 5 ) ;
          $in = 'command 4' ;
          pump $h until $out =~ /command 4 finished/ ;

          $stall_timer->reset; # Prevent restarting or expirng
          finish $h ;

     See `' in this node for building non-fatal timers.

     See `timer', see IPC/Run/Timer, for details.

FILTER IMPLEMENTATION FUNCTIONS
===============================

   These functions are for use from within filters.

input_avail
     Returns TRUE if input is available.  If none is available, then
     &get_more_input is called and it's result returned.

     This is usually used in preference to &get_more_input so that the
     calling filter removes all data from the $in_ref before more data
     gets read in to $in_ref.

     get_more_input is usually used as part of a return expression:

          return input_avail && do {
             ## process the input just gotten
             1 ;
          } ;

     This technique allows get_more_input to return the undef or 0 that a
     filter normally returns when there's no input to process.  If a filter
     stores intermediate values, however, it will need to react to an
     undef:

          my $got = input_avail ;
          if ( ! defined $got ) {
             ## No more input ever, flush internal buffers to $out_ref
          }
          return $got unless $got ;
          ## Got some input, move as much as need be
          return 1 if $added_to_out_ref ;

get_more_input
     This is used to fetch more input in to the input variable.  It returns
     undef if there will never be any more input, 0 if there is none now,
     but there might be in the future, and TRUE if more input was gotten.

     get_more_input is usually used as part of a return expression, see `'
     in this node for more information.

filter_tests
          my @tests = filter_tests( "foo", "in", "out", \&filter ) ;
          $_->() for ( @tests ) ;

     This creates a list of test subs that can be used to test most filters
     for basic functionality.  The first parameter is the name of the
     filter to be tested, the second is sample input, the third is the
     test(s) to apply to the output(s), and the rest of the parameters are
     the filters to be linked and tested.

     If the filter chain is to be fed multiple inputs in sequence, the
     second parameter should be a reference to an array of thos inputs:

          my @tests = filter_tests( "foo", [qw(1 2 3)], "123", \&filter ) ;

     If the filter chain should produce a sequence of outputs, then the
     thrid parameter should be a reference to an array of those outputs:

          my @tests = filter_tests(
             "foo",
             "1\n\2\n",
             [ qr/^1$/, qr/^2$/ ],
             new_chunker
          ) ;

     See t/run.t and t/filter.t for an example of this in practice.

TODO
====

   These will be addressed as needed and as time allows.

   Stall timeout.

   Expose a list of child process objects.  When I do this, each child
process is likely to be blessed into IPC::Run::Proc.

   $kid->abort(), $kid->kill(), $kid->signal( $num_or_name ).

   Write tests for /(full_)?results?/ subs.

   Currently, pump() and run() only work on systems where select() works
on the filehandles returned by pipe().  This does *not* include Win32.  I'd
like to rectify that, suggestions and patches welcome.

   Likewise start() only fully works on fork()/exec() machines (well, just
fork() if you only ever pass perl subs as subprocesses).  There's some
scaffolding for calling Open3::spawn_with_handles(), but that's not that
useful with limited select().

   Support for `\@sub_cmd' as an argument to a command which gets replaced
with /dev/fd or the name of a temporary file containing foo's output.
This is like <(sub_cmd ...) found in bash and csh (IIRC).

   Allow multiple harnesses to be combined as independant sets of processes
in to one 'meta-harness'.

   Allow a harness to be passed in place of an \@cmd.

   Ability to add external file descriptors w/ filter chains and endpoints.

   Ability to add timeouts and timing generators (i.e. repeating timeouts).

   High resolution timeouts.

LIMITATIONS
===========

   No support for ';', '&&', '||', '{ ... }', etc: use perl's, since run()
returns TRUE when the command exits with a 0 result code.

   Does not provide shell-like string interpolation.

   No support for cd, `setenv', or export: do these in an init() sub

     run(
        \cmd,
           ...
     	 init => sub {
     	    chdir $dir or die $! ;
     	    $ENV{FOO}='BAR'
     	 }
     ) ;

   Timeout calculation does not allow absolute times, or specification of
days, months, etc.

INSPIRATION
===========

   Well, select() and waitpid() badly needed wrapping, and open3() isn't
open-minded enough for me.

   API inspired by a message Russ Allbery sent to perl5-porters, which
included:

     I've thought for some time that it would be
     nice to have a module that could handle full Bourne shell pipe syntax
     internally, with fork and exec, without ever invoking a shell.  Something
     that you could give things like:

     pipeopen (PIPE, [ qw/cat file/ ], '|', [ 'analyze', @args ], '>&3');

   Message ylln51p2b6.fsf@windlord.stanford.edu, on 2000/02/04.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>, with numerous suggestions by
p5p.

I/O channels for IPC::Run.
**************************

NAME
====

     IPC::Run::IO -- I/O channels for IPC::Run.

SYNOPSIS
========

     use IPC::Run qw( io ) ;

     ## The sense of '>' and '<' is opposite of perl's open(),
     ## but agrees with IPC::Run.
     $io = io( "filename", '>',  \$recv ) ;
     $io = io( "filename", 'r',  \$recv ) ;

     ## Append to $recv:
     $io = io( "filename", '>>', \$recv ) ;
     $io = io( "filename", 'ra', \$recv ) ;

     $io = io( "filename", '<',  \$send ) ;
     $io = io( "filename", 'w',  \$send ) ;

     $io = io( "filename", '<<', \$send ) ;
     $io = io( "filename", 'wa', \$send ) ;

     ## Handles / IO objects that the caller opens:
     $io = io( \*HANDLE,   '<',  \$send ) ;

     $f = IO::Handle->new( ... ) ; # Any subclass of IO::Handle
     $io = io( $f, '<', \$send ) ;

     require IPC::Run::IO ;
     $io = IPC::Run::IO->new( ... ) ;

     ## Then run(), harness(), or start():
     run $io, ... ;

     ## You can, of course, use io() or IPC::Run::IO->new() as an
     ## argument to run(), harness, or start():
     run io( ... ) ;

DESCRIPTION
===========

   This class and module allows filehandles and filenames to be harnessed
for I/O when used IPC::Run, independant of anything else IPC::Run is doing
(except that errors & exceptions can affect all things that IPC::Run is
doing).

SUBCLASSING
===========

   This class uses the fields pragma, so you need to be aware of the
contraints and strengths that this confers upon subclasses.  See the
Base, and Fields, pragmas for more information.

TODO
====

   Implement bidirectionality.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

filename
     Gets/sets the filename.  Returns the value after the name change, if
     any.

init
     Does initialization required before this can be run.  This includes
     open()ing the file, if necessary, and clearing the destination scalar
     if necessary.

open
     If a filename was passed in, opens it.  Determines if the handle is
     open via fileno().  Throws an exception on error.

close
     Closes the handle.  Throws an exception on failure.

fileno
     Returns the fileno of the handle.  Throws an exception on failure.

mode
     Returns the operator in terms of 'r', 'w', and 'a'.  There is a state
     'ra', unlike Perl's open(), which indicates that data read from the
     handle or file will be appended to the output if the output is a
     scalar.  This is only meaningful if the output is a scalar, it has no
     effect if the output is a subroutine.

     The redirection operators can be a little confusing, so here's a
     reference table:

          >      r      Read from handle in to process
          <      w      Write from process out to handle
          >>     ra     Read from handle in to process, appending it to existing
                        data if the destination is a scalar.
          <<     wa     Write from process out to handle, appending to existing
                        data if IPC::Run::IO opened a named file.

op
     Returns the operation: '<', '>', '<<', '>>'.  See `' in this node if
     you want to spell these 'r', 'w', etc.

Timer channels for IPC::Run.
****************************

NAME
====

     IPC::Run::Timer -- Timer channels for IPC::Run.

SYNOPSIS
========

     use IPC::Run qw( run  timer timeout ) ;
     ## or IPC::Run::Timer ( timer timeout ) ;
     ## or IPC::Run::Timer ( :all ) ;

     ## A non-fatal timer:
     $t = timer( 5 ) ; # or...
     $t = IO::Run::Timer->new( 5 ) ;
     run $t, ... ;

     ## A timeout (which is a timer that dies on expiry):
     $t = timeout( 5 ) ; # or...
     $t = IO::Run::Timer->new( 5, exception => "harness timed out" ) ;

DESCRIPTION
===========

   This class and module allows timers and timeouts to be created for use
by IPC::Run.  A timer simply expires when it's time is up.  A timeout is a
timer that throws an exception when it expires.

   Timeouts are usually a bit simpler to use  than timers: they throw an
exception on expiration so you don't need to check them:

     ## Give @cmd 10 seconds to get started, then 5 seconds to respond
     my $t = timeout( 10 ) ;
     $h = start(
        \@cmd, \$in, \$out,
        $t,
     ) ;
     pump $h until $out =~ /prompt/ ;

     $in = "some stimulus" ;
     $out = '' ;
     $t->time( 5 )
     pump $h until $out =~ /expected response/ ;

   You do need to check timers:

     ## Give @cmd 10 seconds to get started, then 5 seconds to respond
     my $t = timer( 10 ) ;
     $h = start(
        \@cmd, \$in, \$out,
        $t,
     ) ;
     pump $h until $t->is_expired || $out =~ /prompt/ ;

     $in = "some stimulus" ;
     $out = '' ;
     $t->time( 5 )
     pump $h until $out =~ /expected response/ || $t->is_expired ;

   Timers and timeouts that are reset get started by start() and pump().
Timers change state only in pump().  Since run() and finish() both call
pump(), they act like pump() with repect to timers.

   Timers and timeouts have three states: reset, running, and expired.
Setting the timeout value resets the timer, as does calling the reset()
method.  The start() method starts (or restarts) a timer with the most
recently set time value, no matter what state it's in.

Time values
-----------

   All time values are in seconds.  Times may be specified as integer or
floating point seconds, optionally preceded by puncuation-separated days,
hours, and minutes.\

   Examples:

     1           1 second
     1.1         1.1 seconds
     60          60 seconds
     1:0         1 minute
     1:1         1 minute, 1 second
     1:90        2 minutes, 30 seconds
     1:2:3:4.5   1 day, 2 hours, 3 minutes, 4.5 seconds

   Absolute date/time strings are *not* accepted: year, month and
day-of-month parsing is not available (patches welcome :-).

Interval fudging
----------------

   When calculating an end time from a start time and an interval,
IPC::Run::Timer instances add a little fudge factor.  This is to ensure
that no time will expire before the interval is up.

   First a little background.  Time is sampled in discrete increments.
We'll call the exact moment that the reported time increments from one
interval to the next a tick, and the interval between ticks as the time
period.  Here's a diagram of three ticks and the periods between them:

     -0-0-0-0-0-0-0-0-0-0-1-1-1-1-1-1-1-1-1-1-2-...
     ^                   ^                   ^
     |<--- period 0 ---->|<--- period 1 ---->|
     |                   |                   |
       tick 0              tick 1              tick 2

   To see why the fudge factor is necessary, consider what would happen
when a timer with an interval of 1 second is started right at the end of
period 0:

     -0-0-0-0-0-0-0-0-0-0-1-1-1-1-1-1-1-1-1-1-2-...
     ^                ^  ^                   ^
     |                |  |                   |
     |                |  |                   |
       tick 0             |tick 1              tick 2
                      |
                  start $t

   Assuming that check() is called many times per period, then the timer
is likely to expire just after tick 1, since the time reported will have
lept from the value '0' to the value '1':

     -0-0-0-0-0-0-0-0-0-0-1-1-1-1-1-1-1-1-1-1-2-...
     ^                ^  ^   ^               ^
     |                |  |   |               |
     |                |  |   |               |
       tick 0             |tick 1|             tick 2
                      |      |
                  start $t   |
     		            |
     			check $t

   Adding a fudge of '1' in this example means that the timer is guaranteed
not to expire before tick 2.

   The fudge is not added to an interval of '0'.

   This means that intervals guarantee a minimum interval.  Given that the
process running perl may be suspended for some period of time, or that it
gets busy doing something time-consuming, there are no other guarantees on
how long it will take a timer to expire.

SUBCLASSING
===========

   This class uses the fields pragma, so you need to be aware of the
contraints and strengths that this confers upon subclasses.  See the
Base, and Fields, pragmas for more information.

FUNCTIONS & METHODS
===================

timer
     A constructor function (not method) of IPC::Run::Timer instances:

          $t = timer( 5 ) ;
          $t = timer( 5, name => 'stall timer', debug => 1 ) ;

          $t = timer ;
          $t->interval( 5 ) ;

          run ..., $t ;
          run ..., $t = timer( 5 ) ;

     This convenience function is a shortened spelling of

          IPC::Run::Timer->new( ... ) ;

          .  It returns a timer in the reset state with a given interval.

     If an exception is provided, it will be thrown when the timer notices
     that it has expired (in check()).  The name is for debugging usage,
     if you plan on having multiple timers around.  If no name is
     provided, an name like "timer #1" will be provided.

timeout
     A constructor function (not method) of IPC::Run::Timer instances:

          $t = timeout( 5 ) ;
          $t = timeout( 5, exception => "kablooey" ) ;
          $t = timeout( 5, name => "stall", exception => "kablooey" ) ;

          $t = timeout ;
          $t->interval( 5 ) ;

          run ..., $t ;
          run ..., $t = timeout( 5 ) ;

     A This convenience function is a shortened spelling of

          IPC::Run::Timer->new( exception => "IPC::Run: timeout ...", ... ) ;

          .  It returns a timer in the reset state that will throw an
          exception when it expires.

     Takes the same parameters as `' in this node, any exception passed in
     overrides the default exception.

new
          IPC::Run::Timer->new()   ;
          IPC::Run::Timer->new( 5 )   ;
          IPC::Run::Timer->new( 5, exception => 'kablooey' )   ;

     Constructor.  See `' in this node for details.

check
          check $t ;
          check $t, $now ;
          $t->check ;

     Checks to see if a timer has expired since the last check.  Has no
     effect on non-running timers.  This will throw an exception if one is
     defined.

     IPC::Run::pump() calls this routine for any timers in the harness.

     You may pass in a version of now, which is useful in case you have it
     lying around or you want to check several timers with a consistent
     concept of the current time.

     Returns the time left before end_time or 0 if end_time is no longer
     in the future or the timer is not running (unless, of course, check()
     expire()s the timer and this results in an exception being thrown).

     Returns undef if the timer is not running on entry, 0 if check()
     expires it, and the time left if it's left running.

debug
     Sets/gets the current setting of the debugging flag for this timer.
     This has no effect if debugging is not enabled for the current
     harness.

end_time
          $et = $t->end_time ;
          $et = end_time $t ;

          $t->end_time( time + 10 ) ;

     Returns the time when this timer will or did expire.  Even if this
     time is in the past, the timer may not be expired, since check() may
     not have been called yet.

     Note that this end_time is not start_time($t) + interval($t), since
     some small extra amount of time is added to make sure that the timer
     does not expire before interval() elapses.  If this were not so, then

     Changing end_time() while a timer is running will set the expiration
     time.  Changing it while it is expired has no affect, since
     reset()ing a timer always clears the end_time().

exception
          $x = $t->exception ;
          $t->exception( $x ) ;
          $t->exception( undef ) ;

     Sets/gets the exception to throw, if any.  'undef' means that no
     exception will be thrown.  Exception does not need to be a scalar: you
     may ask that references be thrown.

interval
          $i = interval $t ;
          $i = $t->interval ;
          $t->interval( $i ) ;

     Sets the interval.  Sets the end time based on the start_time() and
     the interval (and a little fudge) if the timer is running.

expire
          expire $t ;
          $t->expire ;

     Sets the state to expired (undef).  Will throw an exception if one is
     defined and the timer was not already expired.  You can expire a
     reset timer without starting it.

is_running
is_reset
is_expired
name
     Sets/gets this timer's name.  The name is only used for debugging
     purposes so you can tell which freakin' timer is doing what.

reset
          reset $t ;
          $t->reset ;

     Resets the timer to the non-running, non-expired state and clears the
     end_time().

start
          start $t ;
          $t->start ;
          start $t, $interval ;
          start $t, $interval, $now ;

     Starts or restarts a timer.  This always sets the start_time.  It
     sets the end_time based on the interval if the timer is running or if
     no end time has been set.

     You may pass an optional interval or current time value.

     Not passing a defined interval causes the previous interval setting
     to be re-used unless the timer is reset and an end_time has been set
     (an exception is thrown if no interval has been set).

     Not passing a defined current time value causes the current time to
     be used.

     Passing a current time value is useful if you happen to have a time
     value lying around or if you want to make sure that several timers
     are started with the same concept of start time.  You might even need
     to lie to an IPC::Run::Timer, occasionally.

start_time
     Sets/gets the start time, in seconds since the epoch.  Setting this
     manually is a bad idea, it's better to call `' in this node() at the
     correct time.

state
          $s = state $t ;
          $t->state( $s ) ;

     Get/Set the current state.  Only use this if you really need to
     transfer the state to/from some variable.  Use `' in this node, `' in
     this node, `' in this node, `' in this node, `' in this node, `' in
     this node.

     Note:  Setting the state to 'undef' to expire a timer will not throw
     an exception.

TODO
====

   use Time::HiRes ; if it's present.

   Add detection and parsing of [[[HH:]MM:]SS formatted times and
intervals.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

SysV Semaphore IPC object class
*******************************

NAME
====

   IPC::Semaphore - SysV Semaphore IPC object class

SYNOPSIS
========

     use IPC::SysV qw(IPC_PRIVATE S_IRWXU IPC_CREAT);
     use IPC::Semaphore;

     $sem = new IPC::Semaphore(IPC_PRIVATE, 10, S_IRWXU | IPC_CREAT);

     $sem->setall( (0) x 10);

     @sem = $sem->getall;

     $ncnt = $sem->getncnt;

     $zcnt = $sem->getzcnt;

     $ds = $sem->stat;

     $sem->remove;

DESCRIPTION
===========

METHODS
=======

new ( KEY , NSEMS , FLAGS )
     Create a new semaphore set associated with KEY. `NSEMS' is the number
     of semaphores in the set. A new set is created if

        * KEY is equal to `IPC_PRIVATE'

        * KEY does not already  have  a  semaphore  identifier associated
          with it, and `*FLAGS* & IPC_CREAT' is true.

     On creation of a new semaphore set FLAGS is used to set the
     permissions.

getall
     Returns the values of the semaphore set as an array.

getncnt ( SEM )
     Returns the number of processed waiting for the semaphore `SEM' to
     become greater than it's current value

getpid ( SEM )
     Returns the process id of the last process that performed an operation
     on the semaphore `SEM'.

getval ( SEM )
     Returns the current value of the semaphore `SEM'.

getzcnt ( SEM )
     Returns the number of processed waiting for the semaphore `SEM' to
     become zero.

id
     Returns the system identifier for the semaphore set.

op ( OPLIST )
     OPLIST is a list of operations to pass to semop. OPLIST is a
     concatenation of smaller lists, each which has three values. The
     first is the semaphore number, the second is the operation and the
     last is a flags value. See `semop' in this node for more details. For
     example

          $sem->op(
          	0, -1, IPC_NOWAIT,
          	1,  1, IPC_NOWAIT
          );

remove
     Remove and destroy the semaphore set from the system.

set ( STAT )
set ( NAME => VALUE [, NAME => VALUE ...] )
     set will set the following values of the stat structure associated
     with the semaphore set.

          uid
          gid
          mode (oly the permission bits)

     set accepts either a stat object, as returned by the stat method, or
     a list of name-value pairs.

setall ( VALUES )
     Sets all values in the semaphore set to those given on the `VALUES'
     list.  `VALUES' must contain the correct number of values.

setval ( N , VALUE )
     Set the Nth value in the semaphore set to VALUE

stat
     Returns an object of type `IPC::Semaphore::stat' which is a sub-class
     of Class::Struct. It provides the following fields. For a description
     of these fields see you system documentation.

          uid
          gid
          cuid
          cgid
          mode
          ctime
          otime
          nsems

SEE ALSO
========

   See IPC/SysV, Class/Struct, `semget' in
this node `semctl' in this node `semop' in this node

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

COPYRIGHT
=========

   Copyright (c) 1997 Graham Barr. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Drive interactive shell command sessions, local or remote (like 'expect')
*************************************************************************

NAME
====

   IPC::Session - Drive interactive shell command sessions, local or
remote (like 'expect')

SYNOPSIS
========

     use IPC::Session;

     # open ssh session to fred
     # -- set timeout of 30 seconds for all send() calls
     my $session = new IPC::Session("ssh fred",30);

     $session->send("hostname");  # run `hostname` command on fred
     print $session->stdout();  # prints "fred"
     $session->send("date");  # run `date` within same ssh
     print $session->stdout();  # prints date

     # use like 'expect':
     $session->send("uname -s");
     for ($session->stdout)
     {
     	/IRIX/ && do { $netstat = "/usr/etc/netstat" };
     	/ConvexOS/ && do { $netstat = "/usr/ucb/netstat" };
     	/Linux/ && do { $netstat = "/bin/netstat" };
     }

     # errno returned in scalar context:
     $errno = $session->send("$netstat -rn");
     # try this:
     $session->send("grep '^$user:' /etc/passwd")
     	 && warn "$user not there";

     # hash returned in array context:
     %netstat = $session->send("$netstat -in");
     print "$netstat{'stdout'}\n";  # prints interface table
     print "$netstat{'stderr'}\n";  # prints nothing (hopefully)
     print "$netstat{'errno'}\n";   # prints 0

DESCRIPTION
===========

   This module encapsulates the open3() function call (see
IPC/Open3) and its associated filehandles.  This makes it easy
to maintain multiple interactive command sessions, such as multiple
persistent 'ssh' and/or 'rsh' sessions, within the same perl script.

   The remote shell session is kept open for the life of the object; this
avoids the overhead of repeatedly opening remote shells via multiple ssh
or rsh calls.  This persistence is particularly useful if you are using
ssh for your remote shell invocation; it helps you overcome the high ssh
startup time.

   For applications requiring remote command invocation, this module
provides functionality that is similar to 'expect' or Expect.pm, but in a
lightweight more Perlish package, with discrete STDOUT, STDERR, and return
code processing.

   BTW, There's nothing inherently ssh-ish about IPC::Session - it doesn't
even know anything about ssh, as a matter of fact.  It will work with any
interactive shell that supports 'echo'.  For instance, 'make test' just
drives a local /bin/sh session.

METHODS
=======

my $session = new IPC::Session("ssh fred",30);
----------------------------------------------

   The constructor accepts the command string to be used to open the remote
shell session, such as ssh or rsh; it also accepts an optional timeout
value, in seconds.  It returns a reference to the unique session object.

   If the timeout is not specified then it defaults to 60 seconds.  The
timeout value can also be changed later; see `"timeout()"' in this node.

$commandhandle = $session->send("hostname");
--------------------------------------------

   The send() method accepts a command string to be executed on the remote
host.  The command will be executed in the context of the default shell of
the remote user (unless you start a different shell by sending the
appropriate command...).  All shell escapes, command line terminators,
pipes, redirectors, etc. are legal and should work, though you of course
will have to escape special characters that have meaning to Perl.

   In a scalar context, this method returns the return code produced by the
command string.

   In an array context, this method returns a hash containing the return
code as well as the full text of the command string's output from the
STDOUT and STDERR file handles.  The hash keys are 'stdout', 'stderr', and
'errno'.

print $session->stdout();
-------------------------

   Returns the full STDOUT text generated from the last send() command
string.

   Also available via array context return codes - see `"send()"' in this
node.

print $session->stderr();
-------------------------

   Returns the full STDERR text generated from the last send() command
string.

   Also available via array context return codes - see `"send()"' in this
node.

print $session->errno();
------------------------

   Returns the return code generated from the last send() command string.

   Also available via array context return codes - see `"send()"' in this
node.

$session->timeout(90);
----------------------

   Allows you to change the timeout for subsequent send() calls.

   The timeout value is in seconds.  Fractional seconds are allowed.  The
timeout applies to all send() calls.

   Returns the current timeout.  Can be called with no args.

BUGS/RESTRICTIONS
=================

   * The remote shell command you specify in new() is assumed to not prompt
     for any passwords or present any challenge codes; i.e.; you must use
     .rhosts, authorized_keys, ssh-agent, or the equivalent.  This
     restriction may be removed in future versions of this module, but
     it's there now.

   * There must be a working /bin/sh on the target machine.

AUTHOR
======

     Steve Traugott <stevegt@TerraLuna.Org>

SEE ALSO
========

   See IPC/Open3, `rsh(1)' in this node, `ssh(1)' in this
node, see Expect, `expect(1)' in this node

Light-weight interface to shared memory
***************************************

NAME
====

   IPC::ShareLite - Light-weight interface to shared memory

SYNOPSIS
========

     use IPC::ShareLite;

     $share = new IPC::ShareLite( -key     => 1971,
                                  -create  => 'yes',
                                  -destroy => 'no' ) or die $!;

     $share->store("This is stored in shared memory");
     $str = $share->fetch;

DESCRIPTION
===========

   IPC::ShareLite provides a simple interface to shared memory, allowing
data to be efficiently communicated between processes.  Your operating
system must support SysV IPC (shared memory and semaphores) in order to
use this module.

   IPC::ShareLite provides an abstraction of the shared memory and
semaphore facilities of SysV IPC, allowing the storage of arbitrarily
large data; the module automatically acquires and removes shared memory
segments as needed.  Storage and retrieval of data is atomic, and locking
functions are provided for higher-level synchronization.

   In many respects, this module is similar to IPC::Shareable.  However,
IPC::ShareLite does not provide a tied interface, does not (automatically)
allow the storage of variables, and is written in C for additional speed.

   Construct an IPC::ShareLite object by calling its constructor:

     $share = new IPC::ShareLite( -key     => 1971,
                                          -create  => 'yes',
                                          -destroy => 'no' ) or die $!;

   Once an instance has been created, data can be written to shared memory
by calling the store() method:

     $share->store("This is going in shared memory");

   Retrieve the data by calling the fetch() method:

     $str = $share->fetch();

   The store() and fetch() methods are atomic; any processes attempting to
read or write to the memory are blocked until these calls finish.
However, in certain situations, you'll want to perform multiple operations
atomically.  Advisory locking methods are available for this purpose.

   An exclusive lock is obtained by calling the lock() method:

     $share->lock();

   Happily, the lock() method also accepts all of the flags recognized by
the flock() system call.  So, for example, you can obtain a shared lock
like this:

     $share->lock( LOCK_SH );

   Or, you can make either type of lock non-blocking:

     $share->lock( LOCK_EX|LOCK_NB );

   Release the lock by calling the unlock() method:

     $share->unlock;

METHODS
=======

new($key, $create, $destroy, $exclusive, $mode, $flags, $size)
     This is the constructor for IPC::ShareLite.  It accepts both the
     positional and named parameter calling styles.

     $key is an integer value used to associate data between processes.
     All processes wishing to communicate should use the same $key value.
     $key may also be specified as a four character string, in which case
     it will be converted to an integer value automatically.  If $key is
     undefined, the shared memory will not be accessible from other
     processes.

     $create specifies whether the shared memory segment should be created
     if it does not already exist.  Acceptable values are 1, 'yes', 0, or
     'no'.

     $destroy indicates whether the shared memory segments and semaphores
     should be removed from the system once the object is destroyed.
     Acceptable values are 1, 'yes', 0, or 'no'.

     If $exclusive is true, instantiation will fail if the shared memory
     segment already exists.  Acceptable values are 1, 'yes', 0, or 'no'.

     $mode specifies the permissions for the shared memory and semaphores.
     The default value is 0666.

     $flags specifies the exact shared memory and semaphore flags to use.
     The constants IPC_CREAT, IPC_EXCL, and IPC_PRIVATE are available for
     import.

     $size specifies the shared memory segment size, in bytes.  The
     default size is 65,536 bytes, which is fairly portable.  Linux, as an
     example, supports segment sizes of 4 megabytes.

     The constructor returns the undefined value on error.

store( $scalar )
     This method stores $scalar into shared memory.  $scalar may be
     arbitrarily long.  Shared memory segments are acquired and released
     automatically as the data length changes.  The only limits on the
     amount of data are the system-wide limits on shared memory pages
     (SHMALL) and segments (SHMMNI) as compiled into the kernel.

     Note that unlike IPC::Shareable, this module does not automatically
     allow variables to be stored.  Serializing all data is expensive, and
     is not always necessary.  If you need to store a variable, you should
     employ the Storable module yourself.  For example:

          use Storable qw( freeze thaw );
          ...
          	$hash = { red => 1, white => 1, blue => 1 };
          $share->store( freeze( $hash ) );
          ...
          $hash = thaw( $share->fetch );

     The method raises an exception on error.

fetch()
     This method returns the data that was previously stored in shared
     memory.  The empty string is returned if no data was previously
     stored.

     The method raises an exception on error.

lock( $type )
     Obtains a lock on the shared memory.  $type specifies the type of
     lock to acquire.  If $type is not specified, an exclusive read/write
     lock is obtained.  Acceptable values for $type are the same as for
     the flock() system call.  The method returns true on success, and
     undef on error.  For non-blocking calls (see below), the method
     returns 0 if it would have blocked.

     Obtain an exclusive lock like this:

     	$share->lock( LOCK_EX ); # same as default

     Only one process can hold an exclusive lock on the shared memory at a
     given time.

     Obtain a shared lock this this:

          $share->lock( LOCK_SH );

     Multiple processes can hold a shared lock at a given time.  If a
     process attempts to obtain an exclusive lock while one or more
     processes hold shared locks, it will be blocked until they have all
     finished.

     Either of the locks may be specified as non-blocking:

          $share->lock( LOCK_EX|LOCK_NB );
                  $share->lock( LOCK_SH|LOCK_NB );

          A non-blocking lock request will return 0 if it would have had to
          wait to obtain the lock.

     Note that these locks are advisory (just like flock), meaning that
     all cooperating processes must coordinate their accesses to shared
     memory using these calls in order for locking to work.  See the
     flock() call for details.

     Locks are inherited through forks, which means that two processes
     actually can possess an exclusive lock at the same time.  Don't do
     that.

     The constants LOCK_EX, LOCK_SH, LOCK_NB, and LOCK_UN are available
     for import:

          use IPC::ShareLite qw( :lock );

     Or, just use the flock constants available in the Fcntl module.

unlock()
     Releases any locks.  This is actually equivalent to:

          $share->lock( LOCK_UN );

     The method returns true on success and undef on error.

PERFORMANCE
===========

   For a rough idea of the performance you can expect, here are some
benchmarks.  The tests were performed using the Benchmark module on a
Cyrix PR166+ running RedHat Linux 5.2 with the 2.0.36 kernel, perl
5.005_02 using perl's malloc, and the default shared memory segment size.
Each test was run 5000 times.

     DATA SIZE (bytes)	TIME (seconds)	Op/Sec

     store	16384			2		2500
     fetch	16384			2		2500

     store	32768			3		1666
     fetch	32768			3		1666

     store	65536			6		833
     fetch	65536			5		1000

     store	131072			12		416
     fetch	131072			12		416

     store	262144			28		178
     fetch  262144			27		185

     store	524288			63		79
     fetch  524288			61		81

   Most of the time appears to be due to memory copying.  Suggestions for
speed improvements are welcome.

PORTABILITY
===========

   The module should compile on any system with SysV IPC and an ANSI C
compiler, and should compile cleanly with the -pedantic and -Wall flags.

   The module has been tested under Solaris, FreeBSD, and Linux.  Testing
on other platforms is needed.

   If you encounter a compilation error due to the definition of the semun
union, edit the top of sharelite.c and undefine the semun definition.  And
then please tell me about it.

   I've heard rumors that a SysV IPC interface has been constructed for
Win32 systems.  Support for it may be added to this module.

   IPC::ShareLite does not understand the shared memory data format used
by IPC::Shareable.

AUTHOR
======

   Copyright (C) 1998, Maurice Aubrey <maurice@hevanet.com>.  All rights
reserved.

   This module is free software; you may redistribute it and/or modify it
under the same terms as Perl itself.

CREDITS
=======

   Special thanks to Benjamin Sugars for developing the IPC::Shareable
module.

   See the Changes file for other contributors.

SEE ALSO
========

   See IPC/Shareable, ipc(2), shmget(2), semget(2), perl.

share Perl variables between processes
**************************************

NAME
====

   IPC::Shareable - share Perl variables between processes

SYNOPSIS
========

     use IPC::Shareable (':lock');
     tie SCALAR, 'IPC::Shareable', GLUE, OPTIONS;
     tie ARRAY,  'IPC::Shareable', GLUE, OPTIONS;
     tie HASH,   'IPC::Shareable', GLUE, OPTIONS;

     (tied VARIABLE)->shlock;
     (tied VARIABLE)->shunlock;

     (tied VARIABLE)->shlock(LOCK_SH|LOCK_NB)
            or print "resource unavailable\n";

     (tied VARIABLE)->remove;

     IPC::Shareable->clean_up;
     IPC::Shareable->clean_up_all;

CONVENTIONS
===========

   The occurrence of a number in square brackets, as in [N], in the text
of this document refers to a numbered note in the `' in this node.

DESCRIPTION
===========

   IPC::Shareable allows you to tie a variable to shared memory making it
easy to share the contents of that variable with other Perl processes.
Scalars, arrays, and hashes can be tied.  The variable being tied may
contain arbitrarily complex data structures - including references to
arrays, hashes of hashes, etc.

   The association between variables in distinct processes is provided by
GLUE.  This is an integer number or 4 character string[1] that serves as a
common identifier for data across process space.  Hence the statement

     tie $scalar, 'IPC::Shareable', 'data';

   in program one and the statement

     tie $variable, 'IPC::Shareable', 'data';

   in program two will bind $scalar in program one and $variable in
program two.

   There is no pre-set limit to the number of processes that can bind to
data; nor is there a pre-set limit to the complexity of the underlying
data of the tied variables[2].  The amount of data that can be shared
within a single bound variable is limited by the system's maximum size for
a shared memory segment (the exact value is system-dependent).

   The bound data structures are all linearized (using Raphael Manfredi's
Storable module) before being slurped into shared memory.  Upon retrieval,
the original format of the data structure is recovered.  Semaphore flags
can be used for locking data between competing processes.

OPTIONS
=======

   Options are specified by passing a reference to a hash as the fourth
argument to the tie() function that enchants a variable.  Alternatively
you can pass a reference to a hash as the third argument; IPC::Shareable
will then look at the field named key in this hash for the value of GLUE.
So,

     tie $variable, 'IPC::Shareable', 'data', \%options;

   is equivalent to

     tie $variable, 'IPC::Shareable', { key => 'data', ... };

   Boolean option values can be specified using a value that evaluates to
either true or false in the Perl sense.

   NOTE: Earlier versions allowed you to use the word *yes* for true and
the word no for false, but support for this "feature" is being removed.
*yes* will still act as true (since it is true, in the Perl sense), but
use of the word no now emits an (optional) warning and then converts to a
false value.  This warning will become mandatory in a future release and
then at some later date the use of no will stop working altogether.

   The following fields are recognized in the options hash.

key
     The key field is used to determine the GLUE when using the
     three-argument form of the call to tie().  This argument is then, in
     turn, used as the KEY argument in subsequent calls to shmget() and
     semget().

     The default value is IPC_PRIVATE, meaning that your variables cannot
     be shared with other processes.

create
     create is used to control whether calls to tie() create new shared
     memory segments or not.  If create is set to a true value,
     IPC::Shareable will create a new binding associated with GLUE as
     needed.  If create is false, IPC::Shareable will not attempt to
     create a new shared memory segment associated with GLUE.  In this
     case, a shared memory segment associated with GLUE must already exist
     or the call to tie() will fail and return undef.  The default is
     false.

exclusive
     If exclusive field is set to a true value, calls to tie() will fail
     (returning undef) if a data binding associated with GLUE already
     exists.  If set to a false value, calls to tie() will succeed even if
     a shared memory segment associated with GLUE already exists.  The
     default is false

mode
     The mode argument is an octal number specifying the access
     permissions when a new data binding is being created.  These access
     permission are the same as file access permissions in that 0666 is
     world readable, 0600 is readable only by the effective UID of the
     process creating the shared variable, etc.  The default is 0666 (world
     readable and writable).

destroy
     If set to a true value, the shared memory segment underlying the data
     binding will be removed when the process calling tie() exits
     (gracefully)[3].  Use this option with care.  In particular you
     should not use this option in a program that will fork after binding
     the data.  On the other hand, shared memory is a finite resource and
     should be released if it is not needed.  The default is false

size
     This field may be used to specify the size of the shared memory
     segment allocated.  The default is IPC::Shareable::SHM_BUFSIZ().

   Default values for options are

     key       => IPC_PRIVATE,
     create    => 0,
     exclusive => 0,
     destroy   => 0,
     mode      => 0,
     size      => IPC::Shareable::SHM_BUFSIZ(),

LOCKING
=======

   IPC::Shareable provides methods to implement application-level advisory
locking of the shared data structures.  These methods are called shlock()
and shunlock().  To use them you must first get the object underlying the
tied variable, either by saving the return value of the original call to
tie() or by using the built-in tied() function.

   To lock a variable, do this:

     $knot = tie $sv, 'IPC::Shareable', $glue, { %options };
     ...
     $knot->shlock;

   or equivalently

     tie($scalar, 'IPC::Shareable', $glue, { %options });
     (tied $scalar)->shlock;

   This will place an exclusive lock on the data of $scalar.  You can also
get shared locks or attempt to get a lock without blocking.
IPC::Shareable makes the constants LOCK_EX, LOCK_SH, LOCK_UN, and LOCK_NB
exportable to your address space with the export tags `:lock', `:flock',
or :all.  The values should be the same as the standard flock option
arguments.

     if ( (tied $scalar)->shlock(LOCK_SH|LOCK_NB) ) {
            print "The value is $scalar\n";
            (tied $scalar)->shunlock;
     } else {
            print "Another process has an exlusive lock.\n";
     }

   If no argument is provided to `shlock', it defaults to LOCK_EX.  To
unlock a variable do this:

     $knot->shunlock;

   or

     (tied $scalar)->shunlock;

   or

     $knot->shlock(LOCK_UN);        # Same as calling shunlock

   There are some pitfalls regarding locking and signals about which you
should make yourself aware; these are discussed in `' in this node.

   If you use the advisory locking, IPC::Shareable assumes that you know
what you are doing and attempts some optimizations.  When you obtain a
lock, either exclusive or shared, a fetch and thaw of the data is
performed.  No additional fetch/thaw operations are performed until you
release the lock and access the bound variable again.  During the time
that the lock is kept, all accesses are perfomed on the copy in program
memory.  If other processes do not honor the lock, and update the shared
memory region unfairly, the process with the lock will not be in sync.  In
other words, IPC::Shareable does not enforce the lock for you.

   A similar optimization is done if you obtain an exclusive lock.
Updates to the shared memory region will be postponed until you release
the lock (or downgrade to a shared lock).

   Use of locking can significantly improve performance for operations
such as iterating over an array, retrieving a list from a slice or doing a
slice assignment.

REFERENCES
==========

   When a reference to a non-tied scalar, hash, or array is assigned to a
tie()d variable, IPC::Shareable will attempt to tie() the thingy being
referenced[4].  This allows disparate processes to see changes to not only
the top-level variable, but also changes to nested data.  This feature is
intended to be transparent to the application, but there are some caveats
to be aware of.

   First of all, IPC::Shareable does not (yet) guarantee that the ids
shared memory segments allocated automagically are unique.  The more
automagical tie()ing that happens, the greater the chance of a collision.

   Secondly, since a new shared memory segment is created for each thingy
being referenced, the liberal use of references could cause the system to
approach its limit for the total number of shared memory segments allowed.

OBJECTS
=======

   IPC::Shareable implements tie()ing objects to shared memory too.  Since
an object is just a reference, the same principles (and caveats) apply to
tie()ing objects as other reference types.

DESTRUCTION
===========

   perl(1) will destroy the object underlying a tied variable when then
tied variable goes out of scope.  Unfortunately for IPC::Shareable, this
may not be desirable: other processes may still need a handle on the
relevant shared memory segment.  IPC::Shareable therefore provides an
interface to allow the application to control the timing of removal of
shared memory segments.  The interface consists of three methods -
remove(), clean_up(), and clean_up_all() - and the destroy option to tie().

*destroy option*
     As described in `' in this node, specifying the destroy option when
     tie()ing a variable coerces IPC::Shareable to remove the underlying
     shared memory segment when the process calling tie() exits gracefully.
     Note that any related shared memory segments created automagically by
     the use of references will also be removed.

remove()
          (tied $var)->remove;

     Calling remove() on the object underlying a tie()d variable removes
     the associated shared memory segment.  The segment is removed
     irrespective of whether it has the destroy option set or not and
     irrespective of whether the calling process created the segment.

clean_up()
          IPC::Shareable->clean_up;

     This is a class method that provokes IPC::Shareable to remove all
     shared memory segments created by the process.  Segments not created
     by the calling process are not removed.

clean_up_all()
          IPC::Shareable->clean_up_all;

     This is a class method that provokes IPC::Shareable to remove all
     shared memory segments encountered by the process.  Segments are
     removed even if they were not created by the calling process.

EXAMPLES
========

   In a file called server:

     #!/usr/bin/perl -w
     use strict;
     use IPC::Shareable;
     my $glue = 'data';
     my %options = (
         create    => 'yes',
         exclusive => 0,
         mode      => 0644,
         destroy   => 'yes',
     );
     my %colours;
     tie %colours, 'IPC::Shareable', $glue, { %options } or
         die "server: tie failed\n";
     %colours = (
         red => [
             'fire truck',
             'leaves in the fall',
         ],
         blue => [
             'sky',
             'police cars',
         ],
     );
     ((print "server: there are 2 colours\n"), sleep 5)
         while scalar keys %colours == 2;
     print "server: here are all my colours:\n";
     foreach my $c (keys %colours) {
         print "server: these are $c: ",
             join(', ', @{$colours{$c}}), "\n";
     }
     exit;

   In a file called client

     #!/usr/bin/perl -w
     use strict;
     use IPC::Shareable;
     my $glue = 'data';
     my %options = (
         create    => 0,
         exclusive => 0,
         mode      => 0644,
         destroy   => 0,
         );
     my %colours;
     tie %colours, 'IPC::Shareable', $glue, { %options } or
         die "client: tie failed\n";
     foreach my $c (keys %colours) {
         print "client: these are $c: ",
             join(', ', @{$colours{$c}}), "\n";
     }
     delete $colours{'red'};
     exit;

   And here is the output (the sleep commands in the command line prevent
the output from being interrupted by shell prompts):

     bash$ ( ./server & ) ; sleep 10 ; ./client ; sleep 10
     server: there are 2 colours
     server: there are 2 colours
     server: there are 2 colours
     client: these are blue: sky, police cars
     client: these are red: fire truck, leaves in the fall
     server: here are all my colours:
     server: these are blue: sky, police cars

RETURN VALUES
=============

   Calls to tie() that try to implement IPC::Shareable will return true if
successful, undef otherwise.  The value returned is an instance of the
IPC::Shareable class.

AUTHOR
======

   Benjamin Sugars <bsugars@canoe.ca>

NOTES
=====

Footnotes from the above sections
---------------------------------

  1. If GLUE is longer than 4 characters, only the 4 most significant
     characters are used.  These characters are turned into integers by
     unpack()ing them.  If GLUE is less than 4 characters, it is space
     padded.

  2. IPC::Shareable provides no pre-set limits, but the system does.
     Namely, there are limits on the number of shared memory segments that
     can be allocated and the total amount of memory usable by shared
     memory.

  3. If the process has been smoked by an untrapped signal, the binding
     will remain in shared memory.  If you're cautious, you might try

          $SIG{INT} = \&catch_int;
          sub catch_int {
              die;
          }
          ...
          tie $variable, IPC::Shareable, 'data', { 'destroy' => 'Yes!' };

     which will at least clean up after your user hits CTRL-C because
     IPC::Shareable's END method will be called.  Or, maybe you'd like to
     leave the binding in shared memory, so subsequent process can recover
     the data...

  4. This behaviour is markedly different from previous versions of
     IPC::Shareable.  Older versions would sometimes tie() referenced
     thingies, and sometimes not.  The new approach is more reliable (I
     think) and predictable (certainly) but uses more shared memory
     segments.

General Notes
-------------

o
     When using shlock() to lock a variable, be careful to guard against
     signals.  Under normal circumstances, IPC::Shareable's END method
     unlocks any locked variables when the process exits.  However, if an
     untrapped signal is received while a process holds an exclusive lock,
     DESTROY will not be called and the lock may be maintained even though
     the process has exited.  If this scares you, you might be better off
     implementing your own locking methods.

     One advantage of using flock on some known file instead of the
     locking implemented with semaphores in IPC::Shareable is that when a
     process dies, it automatically releases any locks.  This only happens
     with IPC::Shareable if the process dies gracefully.  The alternative
     is to attempt to account for every possible calamitous ending for your
     process (robust signal handling in Perl is a source of much debate,
     though it usually works just fine) or to become familiar with your
     system's tools for removing shared memory and semaphores.  This
     concern should be balanced against the significant performance
     improvements you can gain for larger data structures by using the
     locking mechanism implemented in IPC::Shareable.

o
     There is a program called ipcs(1/8) (and ipcrm(1/8)) that is
     available on at least Solaris and Linux that might be useful for
     cleaning moribund shared memory segments or semaphore sets produced
     by bugs in either IPC::Shareable or applications using it.

o
     This version of IPC::Shareable does not understand the format of
     shared memory segments created by versions prior to 0.60.  If you try
     to tie to such segments, you will get an error.  The only work around
     is to clear the shared memory segments and start with a fresh set.

o
     Iterating over a hash causes a special optimization if you have not
     obtained a lock (it is better to obtain a read (or write) lock before
     iterating over a hash tied to Shareable, but we attempt this
     optimization if you do not).  The fetch/thaw operation is performed
     when the first key is accessed.  Subsequent key and and value
     accesses are done without accessing shared memory.  Doing an
     assignment to the hash or fetching another value between key accesses
     causes the hash to be replaced from shared memory.  The state of the
     iterator in this case is not defined by the Perl documentation.
     Caveat Emptor.

CREDITS
=======

   Thanks to all those with comments or bug fixes, especially

     Maurice Aubrey      <maurice@hevanet.com>
     Stephane Bortzmeyer <bortzmeyer@pasteur.fr>
     Doug MacEachern     <dougm@telebusiness.co.nz>
     Robert Emmery       <roberte@netscape.com>
     Mohammed J. Kabir   <kabir@intevo.com>
     Terry Ewing         <terry@intevo.com>
     Tim Fries           <timf@dicecorp.com>
     Joe Thomas          <jthomas@women.com>
     Paul Makepeace      <Paul.Makepeace@realprogrammers.com>
     Raphael Manfredi    <Raphael_Manfredi@pobox.com>
     Lee Lindley         <Lee.Lindley@bigfoot.com>
     Dave Rolsky         <autarch@urth.org>

BUGS
====

   Certainly; this is beta software. When you discover an anomaly, send an
email to me at bsugars@canoe.ca.

SEE ALSO
========

   perl(1), perltie(1), Storable(3), shmget(2), ipcs(1), ipcrm(1) and
other SysV IPC man pages.

Object oriented interface to shared memory
******************************************

NAME
====

   IPC::Shareable::SharedMem - Object oriented interface to shared memory

SYNOPSIS
========

     *** No public interface ***

WARNING
=======

   This module is not intended for public consumption.  It is used
internally by IPC::Shareable to access shared memory.  It will probably be
replaced soon by IPC::ShareLite or IPC::SharedMem (when someone writes it).

DESCRIPTION
===========

   This module provides and object-oriented framework to access shared
memory.  Its use is intended to be limited to IPC::Shareable.  Therefore I
have not documented an interface.

AUTHOR
======

   Ben Sugars (bsugars@canoe.ca)

SEE ALSO
========

   IPC::Shareable, IPC::SharedLite

a Perl module to manage a cache in SysV IPC shared memory.
**********************************************************

NAME
====

   IPC::SharedCache - a Perl module to manage a cache in SysV IPC shared
memory.

SYNOPSIS
========

     use IPC::SharedCache;

     # the cache is accessed using a tied hash.
     tie %cache, 'IPC::SharedCache', ipc_key => 'AKEY',
                                     load_callback => \&load,
                                     validate_callback => \&validate;

     # get an item from the cache
     $config_file = $cache{'/some/path/to/some.config'};

DESCRIPTION
===========

   This module provides a shared memory cache accessed as a tied hash.

   Shared memory is an area of memory that is available to all processes.
It is accessed by choosing a key, the ipc_key arguement to tie.  Every
process that accesses shared memory with the same key gets access to the
same region of memory.  In some ways it resembles a file system, but it is
not hierarchical and it is resident in memory.  This makes it harder to
use than a filesystem but much faster.  The data in shared memory persists
until the machine is rebooted or it is explicitely deleted.

   This module attempts to make shared memory easy to use for one specific
application - a shared memory cache.  For other uses of shared memory see
the documentation to the excelent module I use, IPC::ShareLite (see
IPC/ShareLite).

   A cache is a place where processes can store the results of their
computations for use at a later time, possibly by other instances of the
application.  A good example of the use of a cache is a web server.  When
a web server receieves a request for an html page it goes to the file
system to read it.  This is pretty slow, so the web server will probably
save the file in memory and use the in memory copy the next time a request
for that file comes in, as long as the file hasn't changed on disk.  This
certainly speeds things up but web servers have to serve multiple clients
at once, and that means multiple copies of the in-memory data.  If the web
server uses a shared memory cache, like the one this module provides, then
all the servers can use the same cache and much less memory is consumed.

   This module handles all shared memory interaction using the
IPC::ShareLite module (version 0.06 and higher) and all data serialization
using Storable.  See IPC/ShareLite, and
Storable, for details.

MOTIVATION
==========

   This module began its life as an internal piece of HTML::Template (see
HTML/Template).  HTML::Template has the ability to
maintain a cache of parsed template structures when running in a persistent
environment like Apache/mod_perl.  Since parsing a template from disk
takes a fair ammount of time this can provide a big performance gain.
Unfortunately it can also consume large ammounts of memory since each web
server maintains its own cache in its own memory space.

   By using IPC::ShareLite and Storable (see IPC/ShareLite,
and Storable), HTML::Template was able to
maintain a single shared cache of templates.  The downside was that
HTML::Template's cache routines became complicated by a lot of IPC code.
My solution is to break out the IPC cache mechanisms into their own module,
IPC::SharedCache.  Hopefully over time it can become general enough to be
usable by more than just HTML::Template.

USAGE
=====

   This module allows you to store data in shared memory and have it load
automatically when needed.  You can also define a test to screen cached
data for vailidty - if the test fails the data will be reloaded.  This is
useful for defining a max-age for cached data or keeping cached data in
sync with other resources.  In the web server example above the validation
test would look to see wether the file had changed on disk.

   To initialize this module you provide two callback subroutines.  The
first is the "load_callback".  This gets called when a user of the cache
requests an item from that is not yet present or is stale.  It must return
a reference to the data structure that will be stored in the cache.  The
second is the "validate_callback".  This gets called on every cache access
- its job is to check the cached object for freshness (and/or some other
validity, of course).  It must return true or false.  When it returns
true, the cached object is valid and is retained in the cache.  When it
returns false, the object is re-loaded using the "load_callback" and the
result is stored in the cache.

   To use the module you just request entries for the objects you need.
If the object is present in the cache and the "validate_callback" returns
true, then you get the object from the cache.  If not, the object is
loaded into the cache with the "load_callback" and returned to you.

   The cache can be used to store any perl data structures that can be
serialized by the Storable module.  See Storable, for
details.

EXAMPLE
=======

   In this example a shared cache of files is maintained.  The
"load_callback" reads the file from disk into the cache and the
"validate_callback" checks its modification time using stat().  Note that
the "load_callback" stores information into the cached object that
"validate_callback" uses to check the freshness of the cache.

     # the "load_callback", loads the file from disk, storing its stat()
     # information along with the file into the cache.  The key in this
     # case is the filename to load.
     sub load_file {
       my $key = shift;

     open(FILE, $key) or die "Unable to open file named $key : $!");

     # note the modification time of this file - the 9th element of a
     # stat() is the modification time of the file.
     my $mtime = (stat($key))[9];

     # read the file into the variable $contents in 1k chunks
     my ($buffer, $contents);
     while(read(FILE, $buffer, 1024)) { $contents .= $buffer }
     close(FILE);

     # prepare the record to store in the cache
     my %record = ( mtime => $mtime, contents => $contents );

     # this record goes into the cache associated with $key, which is
     # the filename.  Notice that we're returning a reference to the
     # data structure here.
     return \%record;
       }

     # the "validate" callback, checks the mtime of the file on disk and
     # compares it to the cache value.  The $record is a reference to the
     # cached values array returned from load_file above.
     sub validate_file {
       my ($key, $record) = @_;

     # get the modification time out of the record
     my $stored_mtime = $record->{mtime};

     # get the current modification time from the filesystem - the 9th
     # element of a stat() is the modification time of the file.
     my $current_mtime = (stat($key))[9];

     # compare and return the appropriate result.
     if ($stored_mtime == $current_mtime) {
       # the cached object is valid, return true
       return 1;
     } else {
       # the cached object is stale, return false - load_callback will
       # be called to load it afresh from disk.
       return 0;
     }
       }

     # now we can construct the IPC::SharedCache object, using as a root
     # key 'SAMS'.

     tie %cache 'IPC::SharedCache' ipc_key => 'SAMS',
                                   load_callback => \&load_file,
                                   validate_callback => \&validate_file;

     # fetch an object from the cache - if it's already in the cache and
     # validate_file() returns 1, then we'll get the cached file.  If it's
     # not in the cache, or validate_file returns 0, then load_file is
     # called to load the file into the cache.

     $config_file = $cache{'/some/path/to/some.config'};

DETAILS
=======

   The module implements a full tied hash interface, meaning that you can
use exists(), delete(), keys() and each().  However, in normal usage all
you'll need to do is to fetch values from the cache and possible delete
keys.  Just in case you were wondering, exists() doesn't trigger a cache
load - it returns 1 if the given key is already in the cache and 0 if it
isn't.  Similarily, keys() and each() operate on key/value pairs already
loaded into the cache.

   The most important thing to realize is that there is no need to
explicitely store into the cache since the load_callback is called
automatically when it is necessary to load new data.  If you find yourself
using more than just "`$data = $cache{'key'};'" you need to make sure you
really know what you're doing!

OPTIONS
-------

   There are a number parameters to tie that can be used to control the
behavior of IPC::SharedCache.  Some of them are required, and some art
optional. Here's a preview:

     tie %cache, 'IPC::SharedCache',

     # required parameters
     ipc_key => 'MYKI',
     load_callback => \&load,
     validate_callback => \&validate,

     # optional parameters
     ipc_mode => 0666,
     ipc_segment_size => 1_000_000,
     max_size => 50_000_000,
     debug => 1;

ipc_key (required)
------------------

   This is the unique identifier for the particular cache.  It can be
specified as either a four-character string or an integer value.  Any
script that wishes to access the cache must use the same ipc_key value.
You can use the ftok() function from IPC::SysV to generate this value, see
IPC/SysV, for details.  Using an ipc_key value that's
already in use by a non-IPC::SharedCache application will cause an error.
Many systems provide a utility called 'ipcs' to examine shared memory; you
can use it to check for existing shared memory usage before choosing your
ipc_key.

load_callback and validate_callback (required)
----------------------------------------------

   These parameters both specify callbacks for IPC::SharedCache to use
when the cache gets a request for a key.  When you access the cache
(`$data = $cache{$key}'), the cache first looks to see if it already has
an object for the given key.  If it doesn't, it calls the load_callback
and returns the result which is also stored in the cache.  Alternately, if
it does have the object in the cache it calls the validate_callback to
check if the object is still good.  If the validate_callback returns true
then object is good and is returned.  If the validate_callback returns
false then the object is discarded and the load_callback is called.

   The load_callback recieves a single parameter - the requested key.  It
must return a reference to the data object be stored in the cache.
Returning something that is not a reference results in an error.

   The validate_callback recieves two parameters - the key and the
reference to the stored object.  It must return true or false.

   There are two ways to specify the callbacks.  The first is simply to
specify a subroutine reference.  This can be an anonymous subroutine or a
named one.  Example:

     tie %cache, 'IPC::SharedCache',
         ipc_key => 'TEST',
         load_callback => sub { ... },
         validate_callback => \&validate;

   The second method allows parameters to be passed to the subroutine when
it is called.  This is done by specifying a reference to an array of
values, the first being the subroutine reference and the rest are
parameters for the subroutine.  The extra parameters are passed in before
the IPC::SharedCache provided parameters.  Example:

     tie %cache, 'IPC::SharedCache',
         ipc_key => 'TEST',
         load_callback => [\&load, $arg1, $arg2, $arg3]
         validate_callback => [\&validate, $self];

ipc_mode (optional)
-------------------

   This option specifies the access mode of the IPC cache.  It defaults to
0666.  See IPC/ShareLite, for more information on IPC
access modes.  The default should be fine for most applications.

ipc_segment_size (optional)
---------------------------

   This option allows you to specify the "chunk size" of the IPC shared
memory segments.  The default is 65,536, which is 64K.  This is a good
default and is very portable.  If you know that your system supports
larger IPC segment sizes and you know that your cache will be storing
large data items you might get better performance by increasing this value.

   This value places no limit on the size of an object stored in the cache
- IPC::SharedCache automatically spreads large objects across multiple IPC
segments.

   WARNING: setting this value too low (below 1024 in my experience) can
cause errors.

max_size (optional)
-------------------

   By setting this parameter you are setting a logical maximum to the
ammount of data stored in the cache.  When an item is stored in the cache
and this limit is exceded the oldest item (or items, as necessary) in the
cache will be deleted to make room.  This value is specified in bytes.  It
defaults to 0, which specifies no limit on the size of the cache.

   Turning this feature on costs a fair ammount of performance - how much
depends largely on home much data is being stored into the cache versus
the size of max_cache.  In the worst case (where the max_size is set much
too low) this option can cause severe "thrashing" and negate the benefit
of maintaining a cache entirely.

   NOTE: The size of the cache may in fact exceed this value - the
book-keeping data stored in the root segment is not counted towards the
total.  Also, extra padding imposed by the ipc_segment_size is not
counted.  This may change in the future if I learn that it would be
appropriate to count this padding as used memory.  It is not clear to me
that all IPC implementations will really waste this memory.

debug (optional)
----------------

   Set this option to 1 to see a whole bunch of text on STDERR about what
IPC::SharedCache is doing.

UTILITIES
=========

   Two static functions are included in this package that are meant to be
used from the command-line.

walk
----

   Walk prints out a detailed listing of the contents of a shared cache at
a given ipc_key.  It provides information the current keys stored and a
dump of the objects stored in each key.  Be warned, this can be quite a
lot of data!  Also, you'll need the Data::Dumper module installed to use
'walk'.  You can get it on CPAN.

   You can call walk like:

     perl -MIPC::SharedCache -e 'IPC::SharedCache::walk AKEY'"

   Example:

     $ perl -MIPC::SharedCache -e 'IPC::SharedCache::walk MYKI'"
     *===================*
     IPC::SharedCache Root
     *===================*
     IPC_KEY: MYKI
     ELEMENTS: 3
     TOTAL SIZE: 99 bytes
     KEYS: a, b, c

     *=======*
     Data List
     *=======*

     KEY: a
     $CONTENTS = [
                   950760892,
                   950760892,
                   950760892
                 ];

     KEY: b
     $CONTENTS = [
                   950760892,
                   950760892,
                   950760892
                 ];

     KEY: c
     $CONTENTS = [
                   950760892,
                   950760892,
                   950760892
                 ];

remove
------

   This function totally removes an entire cache given an ipc_key value.
This should not be done to a running system!  Still, it's an invaluable
tool during development when flawed data may become 'stuck' in the cache.

     $ perl -MIPC::SharedCache -e 'IPC::SharedCache::remove MYKI'

   This function is silent and thus may be usefully called from within a
script if desired.

BUGS
====

   I am aware of no bugs - if you find one please email me at
sam@tregar.com.  When submitting bug reports, be sure to include full
details, including the VERSION of the module and a test script
demonstrating the problem.

CREDITS
=======

   I would like to thank Maurice Aubrey for making this module possible by
producing the excelent IPC::ShareLite.

   The following people have contributed patches, ideas or new features:

     Tim Bunce
     Roland Mas
     Drew Taylor
     Ed Loehr
     Maverick

   Thanks everyone!

AUTHOR
======

   Sam Tregar, sam@tregar.com (you can also find me on the mailing list
for HTML::Template at htmltmpl@lists.vm.com - join it by sending a blank
message to htmltmpl-subscribe@lists.vm.com).

LICENSE
=======

   IPC::SharedCache - a Perl module to manage a SysV IPC shared cache.
Copyright (C) 2000 Sam Tregar (sam@tregar.com)

   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

AUTHOR
======

   Sam Tregar, sam@tregar.com

SEE ALSO
========

   perl(1).

Utility functions dealing with signals
**************************************

NAME
====

   IPC::Signal - Utility functions dealing with signals

SYNOPSIS
========

     $number = sig_num $name;
     $name   = sig_name $number;

     sig_translate_setup;
     $number = $Sig_num{$name};
     $name   = $Sig_name[$number];

DESCRIPTION
===========

   This module contains utility functions for dealing with signals.

   Nothing is exported by default.

sig_num *chopped-signal-name*
     Returns the signal number of the signal whose name (sans `SIG') is
     *chopped-signal-name*, or undef if there is no such signal.

     This function is prototyped to take a single scalar argument.

sig_name *signal-number*
     Returns the chopped signal name (like `HUP') of signal number
     *signal-number*, or undef if there is no such signal.

     This function is prototyped to take a single scalar argument.

sig_translate_setup
     If you want to use the @Sig_name and %Sig_num variables directly you
     must call sig_translate_setup to initialize them.  This isn't
     necessary if you only use the function interfaces sig_name() and
     sig_num().

     This function is prototyped to take no arguments.

%Sig_num
     A hash with chopped signal name keys (like `HUP') and integer signal
     number values.

*@Sig_name*
     An array mapping signal numbers to chopped signal names (like `HUP').

AUTHOR
======

   Roderick Schertler <`roderick@argon.org'>

SEE ALSO
========

   perl(1).

SysV IPC constants
******************

NAME
====

   IPC::SysV - SysV IPC constants

SYNOPSIS
========

     use IPC::SysV qw(IPC_STAT IPC_PRIVATE);

DESCRIPTION
===========

   IPC::SysV defines and conditionally exports all the constants defined
in your system include files which are needed by the SysV IPC calls.

ftok( PATH, ID )
     Return a key based on PATH and ID, which can be used as a key for
     msgget, semget and shmget. See `ftok' in this node

SEE ALSO
========

   See IPC/Msg, IPC/Semaphore, `ftok' in
this node

AUTHORS
=======

   Graham Barr <gbarr@pobox.com> Jarkko Hietaniemi <jhi@iki.fi>

COPYRIGHT
=========

   Copyright (c) 1997 Graham Barr. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Interface to the XPA messaging system
*************************************

NAME
====

   IPC::XPA - Interface to the XPA messaging system

SYNOPSIS
========

     use IPC::XPA;

     $xpa = IPC::XPA->Open();
     $xpa = IPC::XPA->Open(\%mode);
     $xpa = IPC::XPA->nullXPA;

     %res = $xpa->Get( $template, $paramlist );
     %res = $xpa->Get( $template, $paramlist, \%attrs );

     %res = $xpa->Set( $template, $paramlist );
     %res = $xpa->Set( $template, $paramlist, $buf );
     %res = $xpa->Set( $template, $paramlist, $buf, \%attrs );
     %res = $xpa->Set( $template, $paramlist, \%attrs );

     %res = $xpa->Info( $template, $paramlist );
     %res = $xpa->Info( $template, $paramlist, \%attrs );

     $nservers = IPC::XPA->Access( $name, $type );

     @res = IPC::XPA->NSLookup( $template, $type );

DESCRIPTION
===========

   This class provides access to the XPA messaging system library, `xpa',
developed by the Smithsonian Astrophysical Observatory's High Energy
Astrophysics R&D Group.  The library provides simple inter-process
communication via calls to the `xpa' library as well as via supplied user
land programs.

   The method descriptions below do not duplicate the contents of the
documentation provided with the `xpa' library.

   Currently, only the client side routines are accessible.

METHODS
=======

   Unless otherwise specified, the following methods are simple wrappers
around the similarly named XPA routines (just prefix the Perl routines
with `XPA').

Class Methods
-------------

nullXPA
          $xpa = XPA::IPC->nullXPA;

     This creates an xpa object which is equivalent to a NULL XPA handle as
     far as the underlying XPA routines are concerned.  It can be used to
     create a default XPA object, as it it guaranteed to succeed (the
     *Open()* method may fail).

Open
          $xpa = XPA::IPC->Open();
          $xpa = XPA::IPC->Open( \%mode );

     This creates an XPA object.  mode is a hash containing mode keywords
     and values, which will be translated into the string form used by
     *XPAOpen()*.  The object will be destroyed when it goes out of scope;
     the *XPAClose()* routine will automatically be called.  It returns
     undef upon failure.

     For example,

          $xpa = XPA::IPC->Open( { verify => 'true' } );

Close
          $xpa->Close;

     Close the XPA object.  This is usually not necessary, as it will
     automatically be closed upon destruction.

Access
          $ns = XPA::IPC->Access( $name, $type )

     Returns the number of public access points that match the specified
     name and access type.  See the XPA docs for more information.

NSLookup
          @res = XPA::IPC->NSLookup( $template, $type )

     This calls the XPANSLookup routine.  It returns the results of the
     lookup as a list of references to hashes, one per server. The hashes
     have the keys name class, and method.  For example,

          use Data::Dumper;
          @res = XPA::IPC->NSLookup( 'ds9', 'ls' );
          print Dumper(\@res);

     results in

          $VAR1 = [
                    {
                      'method' => '838e2ab4:46529',
                      'name' => 'ds9',
                      'class' => 'DS9'
                    }
                  ];

     Note that names returned by NSLookup are different than those
     returned by the Set and Get methods; the latter return names which
     are essentially composites of the name and method keys.

     See the XPA docs for more information the template and type
     specification.

Set
     The Set instance method (see `Instance Methods' in this node) can
     also be called as a class method, which is equivalent to calling
     *XPASet()* with a NULL handle to the *xpa* object.

     For example,

          %res = IPC::XPA->Set( $template, $paramlist );

Get
     The Get instance method (see `Instance Methods' in this node) can
     also be called as a class method, which is equivalent to calling
     *XPAGet()* with a NULL handle to the *xpa* object.

     For example,

          %res = IPC::XPA->Get( $template, $paramlist );

Info
     The Info instance method (see `Instance Methods' in this node) can
     also be called as a class method, which is equivalent to calling
     *XPAInfo()* with a NULL handle to the *xpa* object.

     For example,

          %res = IPC::XPA->Info( $template, $paramlist );

Instance Methods
----------------

Set
          %res = $xpa->Set( $template, $paramlist );
          %res = $xpa->Set( $template, $paramlist, $buf );
          %res = $xpa->Set( $template, $paramlist, $buf, \%attrs );
          %res = $xpa->Set( $template, $paramlist, \%attrs );

     Send data to the XPA server(s) specified by $template.  *$xpa* is a
     reference to an XPA object created by `Open()'. *$paramlist*
     specifies the command to be performed.  If additional information is
     to be sent, the *$buf* parameter should be specified.  The *%attrs*
     hash specifies optional parameters and values to be sent.  The
     following are available:

    max_servers
          The maximum number of servers to which the request should be
          sent. This defaults to 1.

    len
          The number of bytes in the buffer to be sent.  If not set, the
          entire contents will be sent.

    mode
          The value of this is a hash containing mode keywords and values,
          which will be translated into the string form used by *XPASet()*.

     It returns a hash keyed off of the server names.  The hash values are
     references to hashes, which will contain the key name (duplicating the
     server name), and if there was an error, the key message.  See the
     *XPASet* documentation for more information on the name and message
     values.

     For example,

          %res = $xpa->Set( 'ds9', 'mode crosshair' );

          use Data::Dumper;
          %res = $xpa->Set( 'ds9', 'array [dim=100,bitpix=-64]', $buf,
          		  { mode => { ack => false } });
          print Dumper \%res, "\n";

     The latter might result in:

          $VAR1 = {
                    'DS9:ds9 838e2ab4:65223' => {
                                                  'name' => 'DS9:ds9 838e2ab4:65223'
                                                },
                  };

Get
          %res = $xpa->Get( $template, $paramlist );
          %res = $xpa->Get( $template, $paramlist, \%attrs );

     Retrieve data from the servers specified by the $template parameter.
     *$xpa* is a reference to an XPA object created by `Open()'.  The
     *$paramlist* indicates which data to return.  The *%attrs* hash
     specifies optional parameters and values to be sent.  The following
     are available:

    max_servers
          The maximum number of servers to which the request should be
          sent. This defaults to 1.

    mode
          The value of this is a hash containing mode keywords and values,
          which will be translated into the string form used by *XPAGet()*

     It returns a hash keyed off of the server names.  The hashe values are
     references to hashes, which will have the keys name, indicating the
     server's name, and `buf' which will contain the returned data.  If
     there was an error, the hashes will also contain the key message.
     See the *XPAGet* documentation for more information on the name and
     message values.

     For example,

          use Data::Dumper;
          %res = $xpa->Get( 'ds9', '-help quit' );
          print Dumper(\%res);

     might result in

          $VAR1 = {
                   'DS9:ds9 838e2ab4:46529' => {
                      'name' => 'DS9:ds9 838e2ab4:46529',
                      'buf' => 'quit:	-- exit application'
                    }
                  };

Info
          %res = $xpa->Info( $template, $paramlist);
          %res = $xpa->Info( $template, $paramlist, \%attrs );

     Send a short message (in *$paramlist*) to the servers specified in
     the $template parameter.  *$xpa* is a reference to an XPA object
     created by `Open()'. The *%attrs* hash specifies optional parameters
     and values to be sent.  The following are available:

    max_servers
          The maximum number of servers to which the request should be
          sent. This defaults to 1.

    mode
          The value of this is a hash containing mode keywords and values,
          which will be translated into the string form used by *XPAGet()*

     It returns a hash keyed off of the server names.  The hash values are
     references to hashes, which will contain the the key name, indicating
     the server's name.  If there was an error or the server replied with
     a message, the hashes will also contain the key message.  See the
     *XPAGet* documentation for more information on the name and message
     values.

The XPA Library
===============

   The XPA library is available at `http://hea-www.harvard.edu/RD/xpa/'.

AUTHOR
======

   Diab Jerius ( djerius@cfa.harvard.edu )

SEE ALSO
========

   perl(1).

Create and Manipulate ipchains via Perl
***************************************

NAME
====

   IPChains - Create and Manipulate ipchains via Perl

SYNOPSIS
========

   use IPChains;

   $fw = IPChains->new(-option => value, ... ); $fw->append('chain');

DESCRIPTION
===========

   This module acts as an interface to the ipchains(8) userspace utility by
Paul "Rusty" Russell (http://www.rustcorp.com/linux/ipchains/). It attempts
to include all the functionality of the original code with a simplified
user interface via Perl. In addition, plans for log parsing facilities, an
integrated interface to ipmasqadm, and possibly traffic shaping are slated
for up and coming versions.

   The new() and attribute() methods support the following options:

Source
     Specifies origination address of packet. Appending hostmask to this
     address using a / is OK, as well as specifying it separately (see
     SourceMask).

SourceMask
     Hostmask for origination address. Can either be in 24 or
     255.255.255.0 style.

SourcePort
     Specific port or port range (use xxx:xxx to denote range), requires
     specific protocol specification.

Dest
     Specifies destination address of packet. Appending hostmask to this
     address using a / is OK, as well as specifying it separately (see
     DestMask)

DestMask
     Destination address, (see SourceMask).

DestPort
     Destination Port, (see SourcePort).

Prot
     Protocol. Can be tcp, udp, icmp, or all. Required for specifying
     specific port(s).

ICMP
     ICMP Name/Code (in place of port when ICMP is specified as protocol).

     Here is a small table of some of the most common ICMP packets:

          Number  Name                     Required by

          0       echo-reply               ping
          3       destination-unreachable  Any TCP/UDP traffic.
          5       redirect                 routing if not running
                                           routing daemon
          8       echo-request             ping
          11      time-exceeded            traceroute

Rule
     Target. Can be ACCEPT, DENY, REJECT, MASQ, REDIRECT, RETURN, or a
     user-defined chain.  Note: This is case sensitive.

Interface
     Specify a specify interface as part of the criteria (ie, eth0, ppp0,
     etc.).

Fragment
     Rule only refers to second and further fragments of fragmented
     packets (1 or 0).

Bidir
     Makes criteria effective in both directions (1 or 0).

Verbose
     Set verbose option for setting rules or list() (1 or 0).

Numeric
     Show output from list() in numeric format. No DNS lookups, etc.. (1
     or 0).

Log
     Enable kernel logging (via syslog, kern.info) of matched packets (1
     or 0).

Output
     Copy matching packets to the userspace device (advanced).

Mark
     Mark matching packets with specified number (advanced).

TOS
     Used for modifying the TOS field in the IP header. Takes 2 args, AND
     and XOR masks, (ie, (TOS => ["0x01", "0x10"])). This feature is
     highly untested.

     The first mask is ANDed with the packet's current TOS, and the second
     mask is XORed with it. Use the following table for reference:

          TOS Name                Value           Typical Uses

          Minimum Delay           0x01 0x10       ftp, telnet
          Maximum Throughput      0x01 0x08       ftp-data
          Maximum Reliability     0x01 0x04       snmp
          Minimum Cost            0x01 0x02       nntp

Exact
     Display exact numbers in byte counters instead of numbers rounded in
     K's, M's, or G's (1 or 0).

SYN
     Only match TCP packets with the SYN bit set and the ACK and FIN bits
     cleared (1 or 0).

METHODS
=======

   The following methods are available to you:

new()
     $fw = IPChains->new(option => value, ...) create new fw object with
     options

attribute()
     $fw->attribute(option, value) to set option to value, OR $value =
     $obj->attribute(option) to get current value of option.

clopts()
     $fw->clopts() clears all option settings (do this before calling
     methods like list(), flush(), delete(), etc. that take only a few
     specific options).

append()
     $fw->append(chain) appends current rule to end of chain

insert()
     $fw->insert(chain, rulenum) inserts rule at position rulenum in
     chain. If rulenum is omitted 1 is assumed.

replace()
     $fw->replace(chain, rulenum) replace rule at rulenum in chain with
     current rule.

delete()
     $fw->delete(chain, rulenum) deletes rule rulenum from chain.

check()
     $fw->check(chain) check given packet against chain for testing.

flush()
     $fw->flush(chain) deletes all rules from chain.

list()
     $fw->list(chain) lists all rules defined for chain.

list_chains()
     $fw->list_chains() returns array with the names of all user-defined
     chains or undef if none exist.

zero()
     $fw->zero(chain) zero's all packet counters for chain. Cannot zero
     counters for chain policy.

masq()
     $fw->masq() lists current masqueraded connections.

new_chain()
     $fw->new_chain(chain) creates new user defined chain.

del_chain()
     $fw->del_chain(chain) delete user defined chain.

set_policy()
     $fw->set_policy(chain) set default policy for chain. Takes Rule
     option only.

EXAMPLES
========

   To set the default policy for the "forward" chain to DENY:

     use IPChains;

     $fw = IPChains->new(Rule => "DENY");
     $fw->set_policy("forward");

   To list current rules in "input" chain to stdout (without parsing
through /proc/net/ip_fw*):

     use IPChains;

     $fw = IPChains->new(Verbose => 1);
     $fw->list("input");

   To create a rule that would allow all traffic on an internal lan, and
deny all tcp traffic from external hosts on relevant ports, and log it,you
could use something like:

     use IPChains;

     $internal = IPChains->new(Source    => "192.168.100.0/24",
                               Rule      => "ACCEPT",
                               Interface => "eth0");
     $external = IPChains->new(Interface => "ppp0",
                               Prot      => "tcp",
                               DestPort  => "0:1024",
                               Log       => 1);
     $internal->append("input");
     $external->append("input");

   You could also create one object, set up the attributes, append() it,
then use clopts() to clear it's options, then use attribute() to
individually specify it's next set of options, then append() it again with
the new rule.  See the examples/ subdirectory in the IPChains.pm source
for more examples.

BUGS
====

   Much of this is highly untested. Masquerading timeout setting and
negative attributes (!) aren't yet implemented.  Much of what's planned to
be done hasn't been yet. This is to be considered nothing more than an
early beta to work out bugs in the basic code, and get feedback on
usefulness and improvements that could be made.

AUTHOR
======

   Jessica Quaintance (j@x25.org). Please feel free to email me with
feedback, questions, or comments (or indeed patches/additions).

COPYRIGHT
=========

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself, with the exception of the libipfwc.c,
ipchains.c, and the files in include/ which have separate terms derived
from those of the original ipchains sources. See COPYING for details of
this license. Please see README.ipchains for the README that was included
with the original source code for ipchains and contains copyrights and
credits for such.

Perl module to manipulate portfw masquerading table.
****************************************************

NAME
====

   IPChains::PortFW - Perl module to manipulate portfw masquerading table.

SYNOPSIS
========

     my $masq = new IPChains::PortFW( option => value, ... );
     $masq->append();

DESCRIPTION
===========

   IPChains::PortFW is an perl interface to the linux kernel port
forwarding facility. You must have ipmasqadm and the portfw module
installed for this module to work. A kernel compiled with
CONFIG_IP_MASQUERADE_IPPORTFW would also helps.

   It has a similar interface than the IPChains(3) module. You create an
IPChains::PortFW object with new(), you can query or set attributes with
the attribute() method and you add or deletes the port forwarding rules
using append() or delete().

ATTRIBUTES
----------

   Here are the attributes valids for IPChains::PortFW.

LocalAddr
     This is the local address from which packets will be redirected.

LocalPort
     This is the port from which packets will be redirected.

RemAddr
     This is the address to which the packets will be forwarded to.

RemPort
     This is the port to which the packets will be forwarded to.

Pref
     This is a preferences value used for load balancing in the case when
     there are many possible remote destinations.

METHODS
-------

new( [options], ... )
     Create a new IPChains::PortFW object and sets its attributes.

attribute( attribute [, value] )
     Get or sets an attribute. Use undef to delete a value.

clopts()
     Unset all attributes.

append()
     Append a rule to the port forwarding masquerade table as specified by
     the attributes of the current objects.

delete()
     Deletes entries in the port forwarding masquerade table. The entries
     matching the attributes will be deleted.

flush()
     Removes all entries from the port forwarding masquerade table.

list()
     Returns an array of IPChains::PortFW objects. One for each entries in
     the port forwarding table.

EXAMPLE
=======

   Redirecting http protocol to internal web server.

   my $portfw = new IPChains::PortFW( Proto     => 'udp',
LocalAddr => '199.168.1.10', 				   LocalPort => 80,
RemAddr   => '10.0.0.1', 				   RemPort   => 80 );

   $portfw->append;

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@insu.com>

COPYRIGHT
=========

   Copyright (C) iNsu Innovations Inc.  All rights reserved.

   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.

SEE ALSO
========

   IPChains(3)

Database connection caching and organization
********************************************

NAME
====

   Ima::DBI - Database connection caching and organization

SYNOPSIS
========

     # Class-wide methods.
     __PACKAGE__->set_db($db_name, $data_source, $user, $password);
     __PACKAGE__->set_db($db_name, $data_source, $user, $password, \%attr);

     __PACKAGE__->set_sql($sql_name, $statement, $db_name);
     __PACKAGE__->set_sql($sql_name, $statement, $db_name, $cache);

     # Object methods.
         $dbh = $obj->db_*;      # Where * is the name of the db connection.
         $sth = $obj->sql_*;     # Where * is the name of the sql statement.
         $sth = $obj->sql_*(@sql_pieces);

     $obj->DBIwarn($what, $doing);

     # Modified statement handle methods.
     $rv = $sth->execute;
     $rv = $sth->execute(@bind_values);
     $rv = $sth->execute(\@bind_values, \@bind_cols);

     # In addition to the normal DBI sth methods...
     $row_ref = $sth->fetch;
     @row     = $sth->fetch;

     $row_ref = $sth->fetch_hash;
     %row     = $sth->fetch_hash;

     $rows_ref = $sth->fetchall;
     @rows     = $sth->fetchall;

     $rows_ref = $sth->fetchall_hash;
     @tbl      = $sth->fetchall_hash;

     $rc = $obj->commit;             #UNIMPLEMENTED
     $rc = $obj->commit(@db_names);  #UNIMPLEMENTED

     $rc = $obj->rollback;            #UNIMPLEMENTED
     $rc = $obj->rollback(@db_names); #UNIMPLEMENTED

     $sth->clear_cache;  #UNIMPLEMENTED

     $obj->clear_db_cache;            #UNIMPLEMENTED
     $obj->clear_db_cache(@db_names); #UNIMPLEMENTED

     $obj->clear_sql_cache;             #UNIMPLMENTED
     $obj->clear_sql_cache(@sql_names); #UNIMPLMENTED

DESCRIPTION
===========

   Ima::DBI attempts to organize and facilitate caching and more efficient
use of database connections and statement handles by storing DBI and SQL
information with your class (instead of as seperate objects).  This allows
you to pass around just one object without worrying about a trail of DBI
handles behind it.

   One of the things I always found annoying about writing large programs
with DBI was making sure that I didn't have duplicate database handles
open.  I was also annoyed by the somewhat wasteful nature of the
prepare/execute/finish route I'd tend to go through in my subroutines.
The new DBI->connect_cached and DBI->prepare_cached helped alot, but I
still had to throw around global datasource, username and password
information.

   So, after a while I grew a small library of DBI helper routines and
techniques.  Ima::DBI is the culmination of all this, put into a nice(?),
clean(?) class to be inherited from.

Why should I use this thing?
----------------------------

   Ima::DBI is a little odd, and it's kinda hard to explain.  So lemme
explain why you'd want to use this thing...

   * Consolidation of all SQL statements and database information

     No matter what, embedding one language into another is messy.  DBI
     alleviates this somewhat, but I've found a tendency to have that
     scatter the SQL around inside the Perl code.  Ima::DBI allows you to
     easily group the SQL statements in one place where they are easier to
     maintain (especially if one developer is writing the SQL, another
     writing the Perl).  Alternatively, you can place your SQL statement
     alongside the code which uses it.  Whatever floats your boat.

     Database connection information (data source, username, password,
     atrributes, etc...) can also be consolidated together and tracked.

     Both the SQL and the connection info are probably going to change
     alot, so having them well organized and easy to find in the code is a
     Big Help.

   * Holds off opening a database connection until necessary.

     While Ima::DBI is informed of all your database connections and SQL
     statements at compile-time, it will not connect to the database until
     you actually prepare a statement on that connection.

     This is obviously very good for programs that sometimes never touch
     the database.  It's also good for code that has lots of possible
     connections and statements, but which typically only use a few.  Kinda
     like an autoloader.

   * Easy integration of the DBI handles into your class

     Ima::DBI causes each database handle to be associated with your class,
     allowing you to pull handles from an instance of your object, as well
     as making many oft-used DBI methods available directly from your
     instance.

     This gives you a cleaner OO design, since you can now just throw
     around the object as usual and it will carry its associated DBI
     baggage with it.

   * Honors taint mode

     It always struck me as a design deficiency that tainted SQL statements
     could be passed to $sth->prepare().  For example:

          # $user is from an untrusted source and is tainted.
          $user = get_user_data_from_the_outside_world;
          $sth = $dbh->prepare('DELETE FROM Users WHERE User = $user');

     Looks innocent enough... but what if $user was the string "1 OR User
     LIKE %".  You just blew away all your users, hope you have backups.

     Ima::DBI turns on the DBI->connect Taint attribute so that all DBI
     methods (except execute()) will no longer accept tainted data.  `DBI'
     in this node for details.

   * Taints returned data

     Databases should be like any other system call.  Its the scary Outside
     World, thus it should be tainted.  Simp.  Ima::DBI turns on DBI's
     Taint attribute on each connection.  This feature is overridable by
     passing your own Taint attribute to set_db as normal for DBI.  `DBI'
     in this node for details.

   * Encapsulation of some of the more repetative bits of everyday DBI
     usage

     I get lazy alot and I forget to do things I really should, like using
     bind_cols(), or rigorous error checking.  Ima::DBI does some of this
     stuff automaticly, other times it just makes it more convenient.

   * Encapsulation of DBI's cache system

     DBI's automatic handle caching system is relatively new, some people
     aren't aware of its use.  Ima::DBI uses it automatically, so you don't
     have to worry your pretty little head about it.  (It even makes it a
     bit more efficient)

   * Sharing of database and sql information amongst inherited classes

     Any SQL statements and connections created by a class is available to
     its children via normal method inheritance.

   * Convenience and orthoganality amongst statement handle methods

     It always struck me odd that DBI didn't take much advantage of Perl's
     context sensitivity.  Ima::DBI redefines some of the various fetch
     methods to fix this oversight; it also adds a few new methods for
     convenience (though not necessarily efficiency).

   * Guarantees one connection per program.

     One program, one database connection (per database user).  One
     program, one prepared statement handle (per statement, per database
     user).  That's what Ima::DBI enforces.  Extremely handy in persistant
     environments (servers, daemons, mod_perl, FastCGI, etc...)

   * Encourages use of bind parameters and columns

     Bind parameters are safer and more efficient than embedding the column
     information straight into the SQL statement.  Bind columns are more
     efficient than normal fetching.  Ima::DBI pretty much requires the
     usage of the former, and eases the use of the latter.

Why shouldn't I use this thing.
-------------------------------

   * It's all about OO

     Although it is possible to use Ima::DBI as a stand-alone module as
     part of a function-oriented design, its generally not to be used
     unless integrated into an object-oriented design.

   * Overkill for small programs

   * Overkill for programs with only one or two SQL statements

     Its up to you whether the trouble of setting up a class and jumping
     through the necessary Ima::DBI hoops is worth it for small programs.
     To me, it takes just as much time to set up an Ima::DBI subclass as it
     would to access DBI without it... but then again I wrote the module.
     YMMV.

   * Overkill for programs that only use their SQL statements once

     Ima::DBI's caching might prove to be an unecessary performance hog if
     you never use the same SQL statement twice (soon caching will become
     optional).  Not sure, I haven't looked into it.

USAGE
=====

   The basic steps to "DBIing" a class are:

  1. Inherit from Ima::DBI

  2. Set up and name all your database connections via set_db()

  3. Set up and name all your SQL statements via set_sql()

  4. Use sql_* to retrieve your statement handles ($sth) as needed and db_*
     to retreive database handles ($dbh).

        Have a look at the `EXAMPLE' in this node below.

TAINTING
========

   Ima::DBI, by default, uses DBI's Taint flag on all connections.

   This means that no Ima::DBI method will accept tainted data and all
data fetched from the database will be tainted.  This may be different
from the DBI behavior you're used to.  `DBI' in this node for details.

METHODS
=======

Class methods
-------------

set_db
          __PACKAGE__->set_db($db_name, $data_source, $user, $password);
          __PACKAGE__->set_db($db_name, $data_source, $user, $password, \%attr);

     This method is used in place of DBI->connect to create your database
     handles.

     Sets up a new DBI database handle associated to $db_name.  All other
     arguments are passed through to DBI->connect_cached.

     A new method is created for each db you setup.  This new method is
     db_$db_name... so, for example, __PACKAGE__->set_db("foo", ...) will
     create a method called db_foo().

     If no %attr is supplied (RaiseError => 1, AutoCommit => 0, PrintError
     => 0) is assumed.  This is a better default IMHO, however it does give
     databases without transactions (such as MySQL) a hard time.  Be sure
     to turn AutoCommit back on if your database does not support
     transactions.

     The actual database handle creation (and thus the database connection)
     is held off until a prepare is attempted with this handle.

     Spaces in $db_name will be translated into underscores ('_')

set_sql
          __PACKAGE__->set_sql($sql_name, $statement, $db_name);
          __PACKAGE__->set_sql($sql_name, $statement, $db_name, $cache);

     This method is used in place of DBI->prepare to create your statement
     handles.

     Sets up a new statement handle using associated to $sql_name using the
     database connection associated with $db_name.  $statement is passed
     through to either DBI->prepare or DBI->prepare_cached (depending on
     $cache) to create the statement handle.

     If $cache is true or isn't given then prepare_cached() will be used to
     prepare the statement handle and it will be cached.  If $cache is
     false then a normal prepare() will be used and the statement handle
     will be recompiled on every sql_*() call.  If you have a statement
     which changes alot or is used very infrequently you might not want it
     cached.

     A new method is created for each statement you set up.  This new
     method is sql_$sql_name... so, as with set_db,
     __PACKAGE__->set_sql("bar", ..., "foo"); will create a method called
     sql_bar() which uses the database connection from db_foo().

     The actual statement handle creation is held off until sql_* is first
     called on this name.

     Spaces in $sql_name will be translated into underscores ('_')

     To make up for the limitations of bind parameters, $statement can
     contain sprintf() style formatting (ie. %s and such) to allow
     dynamically generated SQL statements.  See sql_* below for more
     details.

Object methods
--------------

   *      $dbh = $obj->db_*;

          This is how you directly access a database handle you set up with set_db.

     The actual particular method name is derived from what you told
     set_db.

     db_* will handle all the issues of making sure you're already
     connected to the database.

   *      $sth = $obj->sql_*;
          $sth = $obj->sql_*(@sql_pieces);

     sql_*() is a catch-all name for the methods you set up with set_sql().
     For instance, if you did:

          __PACKAGE__->set_sql('GetAllFoo', 'Select * From Foo', 'SomeDb');

     you'd run that statement with sql_GetAllFoo().

     sql_* will handle all the issues of making sure the database is
     already connected, and the statement handle is prepared.  It returns a
     prepared statement handle for you to use.  (You're expected to
     execute() it)

     If sql_*() is given a list of @sql_pieces it will use them to fill in
     your statement, assuming you have sprintf() formatting tags in your
     statement.  For example:

          __PACKAGE__->set_sql('GetTable', 'Select * From %s', 'Things');

          # Assuming we have created an object... this will prepare the
          # statement 'Select * From Bar'
          $sth = $obj->sql_Search('Bar');

     Be *very careful* with what you feed this function.  It cannot do any
     quoting or escaping for you, so it is totally up to you to take care
     of that.  Fortunately if you have tainting on you will be spared the
     worst.

     It is recommended you only use this in cases where bind parameters
     will not work.

   * clear_db_cache     *UNIMPLEMENTED*
          $obj->clear_db_cache;
          $obj->clear_db_cache(@db_names);

     Ima::DBI uses the DBI->connect_cached to cache open database handles.
     For whatever reason you might want to clear this cache out and start
     over again.

     A call to clear_db_cache with no arguments deletes all database
     handles out of the cache and all associated statement handles.
     Otherwise it only deletes those handles listed in @db_names (and their
     associated statement handles).

     Note that clearing from the cache does not necessarily destroy the
     database handle.  Something else might have a reference to it.

     Alternatively, you may do:  $obj->db_Name->clear_cache;

   * clear_sql_cache    *UNIMPLEMENTED*
          $obj->clear_sql_cache;
          $obj->clear_sql_cache(@sql_names);

     Does the same thing as clear_db_cache, except it does it in relation
     to statement handles.

     Alternatively, you may do:  $obj->sql_Name->clear_cache;

   * DBIwarn    *UNIMPLEMENTED*
          $obj->DBIwarn($what, $doing);

          Produces a useful error for exceptions with DBI.

     *I'm not particularly happy with this interface*

     Most useful like this:

          eval {
              $self->sql_Something->execute($self->{ID}, @stuff);
          };
          if($@) {
              $self->DBIwarn($self->{ID}, 'Something');
                      return;
          }

Modified database handle methods
--------------------------------

   Ima::DBI makes some of the methods available to your object that are
normally only available via the database handle.  In addition, it spices
up the API a bit.

   =over 4

commit         *UNIMPLEMENTED*
          $rc = $obj->commit;
          $rc = $obj->commit(@db_names);

     Derived from $dbh->commit() and basically does the same thing.

     If called with no arguments, it causes commit() to be called on all
     database handles associated with $obj.  Otherwise it commits all
     database handles whose names are listed in @db_names.

     Alternatively, you may like to do:  $rc = $obj->db_Name->commit;

rollback       *UNIMPLEMENTED*
          $rc = $obj->rollback;
          $rc = $obj->rollback(@db_names);

     Derived from $dbj->rollback, it acts just like Ima::DBI->commit,
     except that it calls rollback().

     Alternatively, you may like to do:  $rc = $obj->db_Name->rollback;

clear_cache    *UNIMPLEMENTED*
          $dbh->clear_cache;

          Provides a mechanism to clear a given database handle from the cache.

Modified statement handle methods
---------------------------------

   Ima::DBI overrides the normal DBI statement handle with its own,
slightly modified, version.  Don't worry, it inherits from DBI::st, so
anything not explicitly mentioned here will work just like in normal DBI.

execute
          $rv = $sth->execute;
          $rv = $sth->execute(@bind_values);
          $rv = $sth->execute(\@bind_values, \@bind_cols);

          DBI::st->execute is overridden to enhance execute() a bit.

     If called with no arguments, or with a simple list, execute() operates
     normally.  When when called with two array references, it performs the
     functions of bind_param, execute and bind_columns similar to the
     following:

          $sth->execute(@bind_values);
          $sth->bind_columns(undef, @bind_cols);

     In addition, execute *will accept tainted @bind_values*.  I
     personally found it annoying to have to detaint everything I passed to
     execute() and tended to shut off taint mode rather than go through the
     trouble.  I also can't think of what a malicious user could do with a
     tainted bind value (in the general case.  Your application may vary.)

     Thus a typical idiom would be:

          $sth->execute([$this, $that], [\($foo, $bar)]);

     Of course, this method provides no way of passing bind attributes
     through to bind_param or bind_columns.  If that is necessary, then you
     must perform the bind_param, execute, bind_col sequence yourself.

clear_cache    *UNIMPLEMENTED*
          $sth->clear_cache;

          Provides a mechanism to clear a given statement handle from the cache.

fetching
--------

   The following are modifications or expansions on DBI's various fetch
methods.  Most are simply context sensitive implementations.  Some just
have shorter names.

   Remember that most of the list context versions of the fetch methods
tend to use more memory and be slower.  Same with the fetchall methods.
Use with care.

fetch
          $row_ref = $sth->fetch;
          @row     = $sth->fetch;

     A context sensitive version of fetch().  When in scalar context, it
     will act as fetchrow_arrayref.  In list context it will use
     fetchrow_array.

fetch_hash
          $row_ref = $sth->fetch_hash;
          %row     = $sth->fetch_hash;

     A modification on fetchrow_hashref.  When in scalar context, it acts
     just as fetchrow_hashref() does.  In list context it returns the
     complete hash.

fetchall
          $rows_ref = $sth->fetchall;
          @rows     = $sth->fetchall;

     A modification on fetchall_arrayref.  In scalar context it acts as
     fetchall_arrayref.  In list it returns an array of references to rows
     fetched.

fetchall_hash
          $rows_ref = $sth->fetchall_hash;
          @rows     = $sth->fetchall_hash;

     A mating of fetchall_arrayref() with fetchrow_hashref().  It gets all
     rows from the hash, each as hash references.  In scalar context it
     returns a reference to an array of hash references.  In list context
     it returns a list of hash references.

EXAMPLE
=======

     package Foo;
     use base qw(Ima::DBI);

     # Set up database connections (but don't connect yet)
     __PACKAGE__->set_db('Users', 'dbi:Oracle:Foo', 'admin', 'passwd');
     __PACKAGE__->set_db('Customers', 'dbi:Oracle:Foo', 'Staff', 'passwd');

     # Set up SQL statements to be used through out the program.
     __PACKAGE__->set_sql('FindUser', <<"SQL", 'Users');
         SELECT  *
         FROM    Users
         WHERE   Name LIKE ?
     SQL

     __PACKAGE__->set_sql('ChangeLanguage', <<"SQL", 'Customers');
         UPDATE  Customers
         SET     Language = ?
         WHERE   Country = ?
     SQL

     # rest of the class as usual.

     package main:

     $obj = Foo->new;

     eval {
         # Does connect & prepare
         my $sth = $obj->sql_FindUser;
         # bind_params, execute & bind_columns
         $sth->execute(['Likmi%'], [\($name)]);
         while( $sth->fetch ) {
             print $name;
         }

         # Uses cached database and statement handles
         $sth = $obj->sql_FindUser;
         # bind_params & execute.
         $sth->execute('%Hock');
         @names = $sth->fetchall;

         # connects, prepares
         $rows_altered = $obj->sql_ChangeLanguage->execute(qw(es_MX mx));
     };
     unless ($@) {
         # Everything went okay, commit the changes to the customers.
         $obj->commit('Customers');
     }
     else {
         $obj->rollback('Customers');
         warn "DBI failure:  $@";
     }

TODO, Caveat, BUGS, etc....
===========================

Using undocumented features of DBI
     Using DBI->init_rootclass to pull of subclassing.  This is currently
     an undocumented method (this should change soon).

Unstable Interface
     I haven't totally decided if I'm satisfied with the way this module
     works, so expect the worst, the interface will change.

execute() extensions questionable
     I'm not really sure the additional functionality added to execute() is
     all that useful.

tainting may be too broad
     Having Ima::DBI not accept any tainted data at all is probably too
     general, but I'd rather be too strict to start than be too lax and try
     to restrict later.  In the future, certain methods may accept tainted
     data.

     This is now a joint issue between DBI and Ima::DBI (well, more like a
     master/slave issue.)

should take arguments
     But what?

set_sql() and/or sql_* needs an optional caching flag.
     Right now static SQL (those without sprintf flags) is always prepared
     with prepare_cached() and dynamic with just prepare().  It would be
     nice if there was a way to explicitly set the caching behavior.

I seriously doubt its thread safe.
     You can bet cupcackes to sno-cones that much havoc will be wrought if
     Ima::DBI is used in a threaded Perl.  I don't think DBI is even
     thread-safe.

Should make use of private_* handle method to store information
Having difficulty storing a list of dbh and sth names.
     Storing the association between names and handles is fine, via the
     closures (and thus, the symbol table), but trying to store a complete
     list of all names available to a given object (and thus, inheritable)
     is difficult.  Many minor methods are unimplemented until I figure out
     this problem.

The docs stink.
     The docs were originally written when I didn't have a good handle on
     the module and how it will be used in practical cases.  I need to
     rewrite the docs from the ground up.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

COPYRIGHT
=========

   This module is Copyright (c) 1998-2000 Michael G Schwern.  USA.  All
rights reserved.

   This module is free software.  You may distribute under the same terms
as Perl itself.  IT COMES WITHOUT WARRANTY OF ANY KIND.

THANKS MUCHLY
=============

     Tim Bunce, for enduring all my DBI questions and adding Taint,
     prepare_cached and connect_cached methods to DBI.  It simplified
     my job greatly!

     Arena Networks, for effectively paying for me to finish writing
     this module.

SEE ALSO
========

   DBI

base class for loading, manipulating and saving images.
*******************************************************

NAME
====

   Image::Base - base class for loading, manipulating and saving images.

SYNOPSIS
========

   This class should not be used directly. Known inheritors are Image::Xbm
and Image::Xpm.

     use Image::Xpm ;

     my $i = Image::Xpm->new( -file => 'test.xpm' ) ;
     $i->line( 1, 1, 3, 7, 'red' ) ;
     $i->ellipse( 3, 3, 6, 7, '#ff00cc' ) ;
     $i->rectangle( 4, 2, 9, 8, 'blue' ) ;

   If you want to create your own algorithms to manipulate images in terms
of (x,y,colour) then you could extend this class (without changing the
file), like this:

     # Filename: mylibrary.pl
     package Image::Base ; # Switch to this class to build on it.

     sub mytransform {
         my $self  = shift ;
         my $class = ref( $self ) || $self ;

     # Perform your transformation here; might be drawing a line or filling
     # a rectangle or whatever... getting/setting pixels using $self->xy().
         }

     package main ; # Switch back to the default package.

   Now if you require mylibrary.pl after you've used Image::Xpm or any
other Image::Base inheriting classes then all these classes will inherit
your `mytransform()' method.

DESCRIPTION
===========

new_from_image()
----------------

     my $bitmap = Image::Xbm->new( -file => 'bitmap.xbm' ) ;
     my $pixmap = $bitmap->new_from_image( 'Image::Xpm', -cpp => 1 ) ;
     $pixmap->save( 'pixmap.xpm' ) ;

   Note that the above will only work if you've installed Image::Xbm and
Image::Xpm, but will work correctly for any image object that inherits from
Image::Base and respects its API.

   You can use this method to transform an image to another image of the
same type but with some different characteristics, e.g.

     my $p = Image::Xpm->new( -file => 'test1.xpm' ) ;
     my $q = $p->new_from_image( ref $p, -cpp => 2, -file => 'test2.xpm' ) ;
     $q->save ;

line()
------

     $i->line( $x0, $y0, $x1, $y1, $colour ) ;

   Draw a line from point ($x0,$y0) to point ($x1,$y1) in colour $colour.

ellipse()
---------

     $i->ellipse( $x0, $y0, $x1, $y1, $colour ) ;

   Draw an oval enclosed by the rectangle whose top left is ($x0,$y0) and
bottom right is ($x1,$y1) using a line colour of $colour.

rectangle()
-----------

     $i->rectangle( $x0, $y0, $x1, $y1, $colour, $fill ) ;

   Draw a rectangle whose top left is ($x0,$y0) and bottom right is
($x1,$y1) using a line colour of $colour. If `$fill' is true then the
rectangle will be filled.

new()
-----

   Virtual - must be overridden.

   Recommend that it at least supports `-file' (filename), `-width' and
`-height'.

new_from_serialised()
---------------------

   Not implemented. Recommended for inheritors. Should accept a string
serialised using serialise() and return an object (reference).

serialise()
-----------

   Not implemented. Recommended for inheritors. Should return a string
representation (ideally compressed).

get()           my $width = $i->get( -width ) ;     my( $hotx, $hoty ) = $i->get( -hotx, -hoty ) ;
--------------------------------------------------------------------------------------------------

   Get any of the object's attributes. Multiple attributes may be
requested in a single call.

   See `xy' get/set colours of the image itself.

set()
-----

   Virtual - must be overridden.

   Set any of the object's attributes. Multiple attributes may be set in a
single call; some attributes are read-only.

   See `xy' get/set colours of the image itself.

xy()
----

   Virtual - must be overridden. Expected to provide the following
functionality:

     $i->xy( 4, 11, '#123454' ) ;    # Set the colour at point 4,11
     my $v = $i->xy( 9, 17 ) ;       # Get the colour at point 9,17

   Get/set colours using x, y coordinates; coordinates start at 0.

   When called to set the colour the value returned is class specific; when
called to get the colour the value returned is the colour name, e.g.
'blue' or '#f0f0f0', etc, e.g.

     $colour = xy( $x, $y ) ;  # e.g. #123456
     xy( $x, $y, $colour ) ;   # Return value is class specific

   We don't normally pick up the return value when setting the colour.

load()
------

   Virtual - must be overridden. Expected to provide the following
functionality:

     $i->load ;
     $i->load( 'test.xpm' ) ;

   Load the image whose name is given, or if none is given load the image
whose name is in the `-file' attribute.

save()
------

   Virtual - must be overridden. Expected to provide the following
functionality:

     $i->save ;
     $i->save( 'test.xpm' ) ;

   Save the image using the name given, or if none is given save the image
using the name in the `-file' attribute. The image is saved in xpm format.

CHANGES
=======

   2000/05/05

   Added some basic drawing methods. Minor documentation changes.

   2000/05/04

   Created.

AUTHOR
======

   Mark Summerfield. I can be contacted as <summer@perlpress.com> - please
include the word 'imagebase' in the subject line.

COPYRIGHT
=========

   Copyright (c) Mark Summerfield 2000. All Rights Reserved.

   This module may be used/distributed/modified under the LGPL.

interface to the DS9 image display and analysis program
*******************************************************

NAME
====

   Image::DS9 - interface to the DS9 image display and analysis program

SYNOPSIS
========

     use Image::DS9;
     use Image::DS9 qw( :<group> );  # import constants from group <group>
     use Image::DS9 qw( :all );	  # import all constants

     $dsp = new Image::DS9;
     $dsp = new Image::DS9( \%attrs );

DESCRIPTION
===========

   This class provides access to the *DS9* image display and analysis
program through its *XPA* access points.

   *DS9* is a rather flexible and feature-rich image display program.
Rather than extol its virtues, please consult the website in `' in this
node.

   This class is rather bare at present, providing a low level interface
to the XPA access points.  Eventually these will be hidden by an elegant
framework that will make life wonderful.

   To use this class, first construct a *Image::DS9* object, and then
apply it's methods.  It is possible to both address more than one *DS9*
with a single object, as well as having multiple *Image::DS9* objects
communicate with their own *DS9* invocations.  Eventually there will be
documentation spelling out how to do this.

METHODS
=======

Constants
---------

   Commands sent to DS9 are sent as strings.  To prevent typos (and other
unwanted sideeffects) *Image::DS9* makes many of the commands and
subcommands available as Perl constants - mistype these and the compiler
will complain, not *DS9*.

   Predefined constants may be imported when the *Image::DS9* package is
loaded, by specifying one or more of the following tags: frame, `tile',
filetype, display, scale, `mode_ops', `orient_ops', or all.

   For example:

     use Image::DS9 qw( :frame :tile :filetype :display );

   The frame group imports `FR_active', `FR_all', `FR_center', `FR_clear',
`FR_delete', `FR_first', `FR_hide', `FR_last', `FR_new', `FR_next',
`FR_prev', `FR_refresh', `FR_reset', `FR_show'.

   The `tile' group imports `T_Grid', `T_Column', `T_Row'.

   The filetype group imports `FT_MosaicImage', `FT_MosaicImages',
`FT_Mosaic', `FT_Array'.

   The display group imports `D_blink', `D_tile', `D_single'.

   The scale group imports `S_linear', `S_log', `S_squared', `S_sqrt',
`S_minmax', `S_zscale', `S_user', `S_local', `S_global', `S_limits',
`S_mode', `S_scope'.

   The `mode_ops' group imports `MB_pointer', `MB_crosshair',
`MB_colorbar', `MB_pan', `MB_zoom', `MB_rotate', `MB_examine'.

   The `orient-ops' group imports `OR_X', `OR_Y', `OR_XY'.

   The all group imports all of the above groups, as well as ON, OFF, `YES'
`NO'.

Boolean values
--------------

   Some methods take boolean values; these may be the strings `on', `off',
`yes', no, or the integers 1 or 0.

Return values
-------------

   Because a single *Image::DS9* object may communicate with multiple
instances of *DS9*, most return values are hashes, rather than scalars.
The hash has as keys the names of the servers, with the values being
references to hashes with the keys name, `buf' and message.  The `buf' key
will be present if there are no errors for that server, the message if
there were.

   For example,

     use Data::Dumper;
     %colormaps = $dsp->colormap;
     print Dumper \@colormaps;

   yields

     $VAR1 = {
              'DS9:ds9 838e2ab4:32832' =>
               {
                 'name' => 'DS9:ds9 838e2ab4:32832',
                 'buf' => 'Grey'
               }
             };

   If you know that there is only one server out there  (for example, if
the object was created with max_servers set to 1), you can call a method
in a scalar environment, and it will directly return the value:

     $colormap = $dsp->colormap;

   If there is more than one server, you'll get the results for a randomly
chosen server.

   Sending data usually doesn't result in a return:

     $dsp->colormap( 'Grey' );

Error Returns
-------------

   In case of error, an exception is thrown via *croak()*.  The *res()*
method will return a hash, keyed off of the servers name.  For each server
which had an error, the hash value will be a reference to a hash
containing the keys name and message; the latter will contain error
information.  For those commands which return data, and for those servers
which did not have an error, the `buf' key will be available.

Methods
-------

new
          $dsp = new Image::DS9;
          $dsp = new Image::DS9( \%attrs );

     Construct a new object.  It returns a handle to the object.  It throws
     an exception (catch via eval) upon error.

     The optional hash attrs may contain one of the following keys:

    Server
          An alternate server to which to communicate.  It defaults to
          `ds9'.

    max_servers
          The maximum number of servers to which to communicate.  It
          defaults to the number of `DS9' servers running at the time the
          constructor is called.

    min_servers
          The minimum number of servers which should respond to commands.
          If a response is not received from at least this many servers,
          an exception will be thrown.  It defaults to 1.

     For example,

          $dsp = new Image::DS9( { max_servers => 3 } );

nservers
          $nservers = $dsp->nservers;

     This returns the number of servers which the object is communicating
     with.

array
          $dsp->array( $image );
          $dsp->array( $image, \%attrs );

     This is a simple interface to the array access point, which displays
     images.  If *$image* is a PDL object, all required information is
     extracted from it, and it is passed to *DS9*.  Otherwise, it should
     be binary data suitable for *DS9*, and the attrs hash should be used
     to pass dimensional and size data to *DS9*.  attrs may contain the
     following elements:

    xdim
          The X coordinate array extent.

    ydim
          The Y coordinate array extent.

    bitpix
          The number of bits per pixel.  Negative values indicate a
          floating point number.

colormap
          $dsp->colormap( $colormap );
          @colormaps = $dsp->colormap;

     If an argument is specified, it should be the name of a colormap (case
     is not important).  If no argument is specified, the current colormaps
     for all of the *DS9* instances is returned, as a list containing
     references to hashes with the keys name and `buf'.  The latter will
     contain the colormap name.

display
          $dsp->display( $state );
          %displays = $dsp->display;

     If an argument is specified, this call will change how the data are
     displayed. $state may be one of the constants `D_blink', `D_tile', or
     `D_single' (or, equivalently, 'blink', 'tile', 'single' ).  The
     constants are available by importing the display tag.

     If no argument is specified, the current display states of the *DS9*
     servers are returned (see `' in this node for the format).  The state
     is will be returned as a string equivalent to the constants `D_blink',
     `D_tile' or `D_single'.  For instance:

          my $ds9 = new DS9( { max_servers => 1 } );

          print "We're blinking!\n" if D_blink eq $ds9->display;

file
          $dsp->file( $file );
          $dsp->file( $file, $type );
          %files = $dsp->file;

     Display the specified $file.  The file type is optional, and may be
     one of the following constants: `FT_MosaicImage', `FT_MosaicImages',
     `FT_Mosaic', `FT_Array' (or one of the strings `'mosaicimage'',
     `'mosaicimages'', `'mosaic'', or `'array'' ). (Import the filetype
     tag to get the constants).

     If called without a value, it will return the current file name loaded
     for the current frame.

frame
          @frames = $dsp->frame;

          # perform a frame operation with no arguments
          $dsp->frame( $frame_op );

          # show the specified frame
          $dsp->frame( show => $frame );

          # delete the current frame
          $dsp->frame( FR_delete );

          # delete the specified frame
          $dsp->frame( delete => $frame );

          # delete all of the frames
          $dsp->frame( delete => FR_all );

     Command *DS9* to do frame operations.  Frame operations are nominally
     strings.  As *DS9* will interpret any string which isn't a frame
     operation as the name of frame to switch to (or create, if
     necessary), *Image::DS9* provides constants for the standard
     operations to prevent typos.  See `' in this node.  Otherwise, use
     the strings active, all, center, clear, delete, hide, new, refresh,
     reset, show, first, next, prev, last.

     To load a particular frame, specify the frame name as the operator.

     To show a frame which has been hidden, use the second form with the
     show operator.

     For example,

          $dsp->frame( FR_new );		# use the constant
          $dsp->frame( 'new' );		# use the string literal
          $dsp->frame( '3' );		# load frame 3
          $dsp->frame( FR_hide );		# hide the current frame
          $dsp->frame( show => 3 );	# show frame 3
          $dsp->frame( FR_delete );	# delete the current frame

     If frame() is called with no arguments, it returns a list of the
     current frames for all instances of *DS9*.

iconify
          $iconify_state = $dsp->iconify;
          %iconify_state = $dsp->iconify;
          $dsp->iconify($bool);

     With a boolean argument, specify the iconification state, else return
     it.

mode
          $mode = $dsp->mode;
          $dsp->mode( $state );

     Change (or query) the first mouse button mode state.  Predefined
     states are available via the `mode_ops' group; see `' in this node.

orient
          $state = $dsp->orient;
          $dsp->orient( $state );

     Change (or query) the orientation of the current frame. Predefined
     states are available via the `orient_ops' group; see `' in this node.

rotate
          $rotate = $dsp->rotate;
          $dsp->rotate( abs => $rotate );
          $dsp->rotate( rel => $rotate );
          $dsp->rotate( $rotate );

     Change or query the rotation angle (in degrees) for the current frame.
     A rotatation may be absolute or relative; this is explicitly specified
     in the second and third forms of the method invocation.  If not
     specified (as in the last form) it is relative.

     If no argument is specified, it returns the rotatation angle for the
     current frame.

res
          $res = $dsp->res;

     In case of error, the returned results from the failing *XPA* call
     are available via this method.  It returns a reference to an array of
     hashes, one per instance of *DS9* addressed by the object.  See the
     *IPC::XPA* documentation for more information on what the hashes
     contain.

scale
          $dsp->scale( $algorithm );
          $dsp->scale( S_limits => [ $min, $max ] );
          $dsp->scale( S_mode => $mode );
          $dsp->scale( S_scope => $scope );

          %scale = $dsp->scale;
          %limits = $dsp->scale( S_limits );
          %mode = $dsp->scale( S_mode );
          %scope = $dsp->scale( S_scope );

     This specifies how the data will be scaled.  `$algorithm' may be one
     of the constants `S_linear', `S_log', `S_squared', `S_sqrt' (or,
     equivalently, `'linear'', `'log'', `'squared'', `'sqrt'').

     $mode may be one of `S_minmax', `S_zscale', `S_user' (or,
     equivalently, `'minmax'', `'zscale'', `'user'').

     `$scope' may be on of `S_local', `S_global' (or, equivalently,
     `'local'', `'global'' ).

     The constants are available if the scale tag is imported (see `' in
     this node).  The second set of invocations shown above illustrates
     how to determine the current values of the scale parameters.

tile_mode
          $dsp->tile_mode( $mode );

     The tiling mode may be specified by setting $mode to `T_Grid',
     `T_Column', or `T_Row'.  These constants are available if the
     `tile_op' tags are imported.  Otherwise, use `'grid'', c<'column'>,
     or `'row''.  If called without a value, it will return the current
     tiling mode.

zoom
          $zoom = $dsp->zoom;
          $dsp->zoom( abs => $zoom );
          $dsp->zoom( rel => $zoom );
          $dsp->zoom( $zoom );

     This changes the zoom value for the current frame.  `$zoom' is a
     positive numerical value.  A zoom value may be absolute or relative.
     This is explicitly specified in the second and third forms of the
     method invocation.  If not specified (as in the last form) it is
     absolute.  To zoom such that the image fits with in the frame,
     specify a zoom value of 0.

     If no argument is specified, it returns the zoom value for the current
     frame.

REQUIREMENTS
============

   *Image::DS9* requires *IPC::XPA* to be installed.  At present, both
*DS9* and *xpans* (part of the *XPA* distribution) must be running prior
to any attempts to access *DS9*.  *DS9* will automatically start *xpans*
if it is in the user's path.

   *DS9* is available at `http://hea-www.harvard.edu/RD/ds9/'.

   *XPA* is available at `http://hea-www.harvard.edu/RD/xpa/'.

AUTHOR
======

   Diab Jerius ( djerius@cfa.harvard.edu )

SEE ALSO
========

   perl(1), IPC::XPA.

create static GIF file from animated GIF
****************************************

NAME
====

   Image::DeAnim - create static GIF file from animated GIF

SYNOPSIS
========

     use Image::DeAnim;

     open(G,"animated.gif") or die;
     undef $/;
     $gif = <G>;
     $newgif = Image::DeAnim::gif(\$gif);
     print $$newgif;

     # Using HTTP::Response

     if ($self -> content_type eq 'image/gif') {
        my $gif = $self -> content;
        $self -> content (${&Image::DeAnim::gif(\$gif)});
     }

DESCRIPTION
===========

   Image::DeAnim::gif takes a reference to a scalar conatining a GIF
image, and returns a scalar reference to a filtered GIF image.  If the
input is an animated GIF, the output will be a static GIF of the last
frame of the animation.  If the input is already a static GIF, the output
file should be (mostly) identical.

   Image::DeAnim is intended for use with a HTTP proxy server, in order to
de-animate GIFs before they reach the browser window.

BUGS
====

   Currently only outputs last frame.  Options for first/other shouldn't
be too difficult, though.

   If the last image of the animation is not the same size as the first,
the remaining image is blacked out (no overlay).  It doesn't bother me,
but it may for others.

   Doesn't work with cached animations, although as images work their way
out of the cache, this shouldn't be a problem.

   Not very Perl-ish; can probably use lots of fixing, and better
documentation.  OO in place of references seems to be the next logical
step.

AUTHOR
======

   Ken MacFarlane, <ksm+cpan@universal.dca.net>

COPYRIGHT
=========

   Copyright 1999.  This program may be distributed under the Perl
Artistic License.

Perl extension for Grabbing images off the Internet.
****************************************************

NAME
====

   Image::Grab - Perl extension for Grabbing images off the Internet.

SYNOPSIS
========

     # If you call grab without instantiating an Image::Grab, then you
     # can pass grab args and it will instantiate one for you and return
     # the result.
     use Image::Grab qw(grab);
     $image = grab(URL=>'http://www.example.com/test.gif');

     use Image::Grab;
     $pic = new Image::Grab;

     # You can also pass new arguments:
     use Image::Grab;
     $pic = Image::Grab->new(SEARCH_URL=>'http://www.example.com/',
                             REGEXP    =>'.*\.gif');

     # The simplest OO case of a grab
     use Image::Grab;
     $pic->url('http://www.example.com/someimage.jpg')
     $pic->grab;

     # Now to save the image to disk
     open(IMAGE, ">image.jpg") || die"image.jpg: $!";
     binmode IMAGE;  # for MSDOS derivations.
     print IMAGE $pic->image;
     close IMAGE;

     # A slightly more complicated case
     use Image::Grab;
     $pic->regexp('.*logo.*\.gif');
     $pic->search_url('http://www.example.com');
     $pic->grab;

     # Get a weather forecast
     use Image::Grab;
     $pic->regexp('msy.*\.gif');
     $pic->search_url('http://www.example.com/weather/msy/content.shtml');
     $pic->grab;

DESCRIPTION
===========

   Image::Grab is a simple way to get images with URLs that are either not
predictable or are "hidden" by some method.

RATIONALE
=========

   I created this module so that I would have a uniform API for grabbing
multiple images from multiple sites that use various methods of making
their images difficult to retrieve automatically.

   I've tried to put into code all the ways that website creators will use
to try to "protect" their images.  If you know of any methods I've missed,
please email me.

   This module was born from a script.  The script was born when a certain
Comics Syndicate stopped having a static (or even predictable) url for
their comics.  I generalized the code for a friend when he needed to do
something similar.

   Hopefully, others will find this module useful as well.

Retrieval Methods and Properties
================================

   The following are the retrieval methods and properties available for
any Image::Grab object.

   One of the following should be set to specify the image.  If either
`regexp' in this node or `index' in this node are used to specify the
image, then `search_url' in this node must be set to specify the page to
be searched for the image.

   *Image::Grab* will use the data in the following order: `url' in this
node, `regexp' in this node, `index' in this node.

   `refer' in this node, `regexp' in this node, `search_url' in this node
and `url' in this node all have POSIX time string expansion performed on
them by the `expand_url|' in this node method when `do_posix' in this node
is set.  Thus, if you wish to have a '%' character in your URL, you must
put '%%'.

url
---

   The fully qualified URL of the image.  This method is included simply
for completeness and convenience.  If this is all you need, you might
check out LWP::Simple.  (Although, the date expansion is nice...)

   POSIX time string expansion is performed if `do_posix' in this node is
set.

   Example:

     $url = $image->url("http://www.example.com/%Y/%m/%d.gif");

search_url
----------

   If `regexp' in this node and/or `index' in this node methods are used
to specify an image then the url in the search_url field will be used to
find the image.  For example, if `regexp="mac.*\.gif"' and
`search_url="http://www.example.com"', then when a grab is performed, the
page at www.example.com is searched to see if any images on the page match
the regular expression `"mac.*\.gif"'.

   Also, when Image::Grab finally grabs the image, it uses the
`search_url' in this node as the referer field.

   POSIX time string expansion is performed if `do_posix' in this node is
set.

   Example:

     $image->search_url("http://www.example.com/weather_maps.html");

index
-----

   An integer indicating the image on the page to grab.  For instance, '1'
would find the second image on the page pointed to by `search_url' in this
node.  Used in conjunction with `regexp' in this node, it specifies which
image to grab that the regular expression matches.

   Example:

     $image->search_url("http://www.example.com/index.html");
     $image->regexp(".*\.gif");
     $image->index(1);

regexp
------

   A regular expression that will match the URL of the image.  If `index'
in this node is not set, then the first image that matches will be used.
If `index' in this node is set, then the nth image (base 0) that matches
will be used.

   Set `search_url' in this node to the web page that you want to search
with this regular expression.

   POSIX time string expansion is performed if `do_posix' in this node is
set.

   Example:

     $image->search_url("http://www.example.com/index.html");
     $image->regexp(".*\.gif");

grab ([$tries])
---------------

   Grab the image.  Returns $image->image;

   If the `url' in this node method is not used to give an absolute url,
then `expand_url|' in this node is called before the image is fetched.

   If $tries is specified, then $tries are attempted before giving up.
$tries defaults to 10.

   Example:

     $image->url("http://www.example.com/comic_strip/%Y/%M/%d.gif");
     $pic = $image->grab;

grab_new ([$tries])
-------------------

   If neither `date' in this node nor `md5' in this node are set, than
this method acts identically to `grab|' in this node.

   If `md5' in this node is set, then the grab is performed only if the
checksum of the newer image is different than the current checksum.

   If `date' in this node is set than the grab is performed only if the
image has been modified since `date' in this node.

   If both `date' in this node and `md5' in this node are set then the
conditions are ANDed.  That is, the image is returned only if it has been
modified since `date' in this node and its checksum is different than
`md5' in this node.

Image Properties
================

   These are various properties of the image.  Generally, you don't want
to set these after you've grabbed an image..

image
-----

   Returns the actual image.

date
----

   The date that the image was last updated.  The date is represented in
the number of seconds from epoch.

   If this is set when `grab_new|' in this node is called, then an image
will only be returned if the date of the image is newer than the date set
in this field.  (See `grab_new|' in this node for full details.)

     $image->date(localtime(time));

     # Grab the image if it changes in the past 30 seconds;
     $pic = $image->grab_new;
     $date = $image->date;

md5
---

   The md5 sum for the image.

   If this is set when `grab_new|' in this node is called, then an image
will only be returned if the md5 checksums don't match. (See `grab_new|'
in this node for full details.)

   This will only be used if the MD5 module is available.  Otherwise,
there will be no effect.

type
----

   The Content-Type of information returned.  Usually it will be a MIME
type such as "image/jpeg".

Other Properties
================

   These are miscellaneous properties.  `do_posix' in this node and
`cookiefile' in this node are the only ones you should need to use.

do_posix
--------

   Tells Image::Grab to do POSIX date substitution.  This is on by default
in recentish perls.

   Perl versions 5.005 and up will have this set versions before this will
not in order to avoid buggy behavior on long URLs.  If you have an earlier
version of Perl and wish to use the expansion, then set this on:

     $image->do_posix(1);

cookiefile
----------

   Where the cookiefile is located.  Set this to the file containing the
cookies if you wish to use the cookie file for the image.

   For example, I use this to authenticate on sites that require cookie
authentication.  To do this, first load the cookie file by visiting the
site with Netscape and getting a cookie.  Next, set the cookie file like
this:

     $image->cookiefile($ENV{HOME} ."/.netscape/cookies")

   Image::Grab will automatically send the correct cookie when the remote
server asks for it.

   The cookiefile is assumed to be in Netscape Navigator's format.

cookiejar
---------

   Usually only used internally.  Contains an HTTP::Cookies::Netscape
blessed reference.

ua
--

   This contains an Image::Grab::RequestAgent blessed reference.
Image::Grab::RequestAgent is sub-class of LWP::UserAgent and inherits all
its methods.

refer
-----

   When you do a `grab|' in this node, this url will be given as the
referring URL.

   POSIX time string expansion is performed if `do_posix' in this node is
set.

Other Methods
=============

auth($user, $password)
----------------------

   Provides a username/password pair for grabbing the image.

getAllURLs ([$tries])
---------------------

   Returns a list of URLs pointing to images from the page pointed to by
`search_url' in this node.  Of course, `search_url' in this node must be
set for this method to be of any use.

   If $tries is specified, then $tries are attempted before giving up.
$tries defaults to 10.

   Returns undef if no connection is made in $tries attempts.

expand_url ([$tries])
---------------------

getRealURL ([$tries])
---------------------

   Returns the actual URL of the image specified.  Performs POSIX time
string expansion (see strftime(3)) using the current time if do_posix is
set.

   You can use this method to get the URL for an image if that is all you
need.

   If $tries is specified, then $tries are attempted before giving up.
$tries defaults to 10.

   Returns undef if no connection is made in $tries attempts, if the
`search_url' in this node URL is not of type text/html, or if no image that
matches the specs is found.

   If `url' in this node is given a full URL, then it is returned with
POSIX time string expansion performed if `do_posix' in this node is set.

   The *getRealURL* method is deprecated.

   Example:

     $image->regexp('msy.*\.gif');
     $image->search_url('http://www.example.com/weather/msy/content.shtml');
     $url = $image->expand_url;

     # Grab the image using LWP::Simple.
     use LWP::Simple;
     $pic = get($url);

loadCookieJar
-------------

   Usually used only internally.  Loads up the cookiejar with cookies.

BUGS
====

   getAllURLs and expand_url should really be fixed so that they go out to
the 'net only once if they need to.

   POSIX date substitution screws up strings longer than 127 chars.  At
least on Perl 5.004_04 - Perl 5.005_03 seems to behave properly.

   Ummm... I am sure there are others...

LICENSE
=======

   Same as Perl.

AUTHOR
======

   Mark A. Hershberger (mah@everybody.org), http://everybody.org/mah/

SEE ALSO
========

   See HTTP/Request, HTTP/Cookies,
HTML/TreeBuilder, LWP/UserAgent,
see Digest/MD5, URI/URL,
strftime(3).

Extract meta information from image files
*****************************************

NAME
====

   Image::Info - Extract meta information from image files

SYNOPSIS
========

     use Image::Info qw(image_info dim);

     my $info = image_info("image.jpg");
     if (my $error = $info->{error}) {
         die "Can't parse image info: $error\n";
     }
     my $color = $info->{color_type};

     my($w, $h) = dim($info);

DESCRIPTION
===========

   This module provide functions to extract various kind of meta
information from image files.  The following functions are provided by the
`Image::Info' module:

image_info( $file )
image_info( \$imgdata )
image_info( $file, key => value,... )
     This function takes the name of a file or a file handle as argument
     and will return one or more hashes (actually hash references)
     describing the images inside the file.  If there is only one image in
     the file only one hash is returned.  In scalar context, only the hash
     for the first image is returned.

     In case of error, and hash containing the "error" key will be
     returned.  The corresponding value will be an appropriate error
     message.

     If a reference to a scalar is passed as argument to this function,
     then it is assumed that this scalar contains the raw image data
     directly.

     The image_info() function also take optional key/value style arguments
     that can influence what information is returned.

dim( $info_hash )
     Takes an hash as returned from image_info() and returns the dimensions
     ($width, $height) of the image.  In scalar context returns the
     dimensions as a string.

html_dim( $info_hash )
     Returns the dimensions as a string suitable for embedding directly
     into HTML <img>-tags. E.g.:

          print "<img src="..." @{[html_dim($info)]}>\n";

Image descriptions
==================

   The image_info() function returns meta information about each image in
the form of a reference to a hash.  The hash keys used are in most cases
based on the TIFF element names.  All lower case keys are mandatory for
all file formats and will always be there unless an error occured (in
which case the "error" key will be present.)  Mixed case keys will only be
present when the corresponding information element is available in the
image.

   The following key names are common for any image format:

file_media_type
     This is the MIME type that is appropriate for the given file format.
     The corresponding value is a string like: "image/png" or "image/jpeg".

file_ext
     The is the suggested file name extention for a file of the given file
     format.  The value is a 3 letter, lowercase string like "png", "jpg".

width
     This is the number of pixels horizontally in the image.

height
     This is the number of pixels vertically in the image.  (TIFF use the
     name ImageLength for this field.)

color_type
     The value is a short string describing what kind of values the pixels
     encode.  The value can be one of the following:

          Gray
          GrayA
          RGB
          RGBA
          CMYK
          YCbCr
          CIELab

     These names can also be prefixed by "Indexed-" if the image is
     composed of indexes into a palette.  Of these, only "Indexed-RGB" is
     likely to occur.

     (It is similar to the TIFF field PhotometricInterpretation, but this
     name was found to be too long, so we used the PNG inpired term
     instead.)

resolution
     The value of this field normally gives the physical size of the image
     on screen or paper. When the unit specifier is missing then this field
     denotes the squareness of pixels in the image.

     The syntax of this field is:

          <res> <unit>
          <xres> "/" <yres> <unit>
          <xres> "/" <yres>

     The <res>, <xres> and <yres> fields are numbers.  The <unit> is a
     string like `dpi', `dpm' or `dpcm' (denoting "dots per inch/cm/meter).

SamplesPerPixel
     This says how many channels there are in the image.  For some image
     formats this number might be higher than the number implied from the
     color_type.

BitsPerSample
     This says how many bits are used to encode each of samples.  The value
     is a reference to an array containing numbers. The number of elements
     in the array should be the same as SamplesPerPixel.

Comment
     Textual comments found in the file.  The value is a reference to an
     array if there are multiple comments found.

Interlace
     If the image is interlaced, then this tell which interlace method is
     used.

Compression
     This tell which compression algorithm is used.

Gamma
     A number.

LastModificationTime
     A ISO date string

Supported Image Formats
=======================

   The following image file formats are currently supported:

ASCII
     For more information see Image/Info/ASCII.

BMP
     This module supports the Microsoft Device Independent Bitmap format
     (BMP, DIB, RLE).

     For more information see Image/Info/BMP.

GIF
     Both GIF87a and GIF89a are supported and the version number is found
     as `GIF_Version' for the first image.  GIF files can contain multiple
     images, and information for all images will be returned if
     image_info() is called in list context.  The Netscape-2.0 extention to
     loop animation sequences is represented by the `GIF_Loop' key for the
     first image.  The value is either "forever" or a number indicating
     loop count.

JPEG
     For JPEG files we extract information both from JFIF and `Exif'
     application chunks.

     `Exif' is the file format written by most digital cameras.  This
     encode things like timestamp, camera model, focal length, exposure
     time, aperture, flash usage, GPS position, etc.  The following web
     page contain description of the fields that can be present:

          http://www.butaman.ne.jp/~tsuruzoh/Computer/Digicams/exif-e.html

PNG
     Information from IHDR, PLTE, gAMA, pHYs, tEXt, tIME chunks are
     extracted.  The sequence of chunks are also given by the `PNG_Chunks'
     key.

PBM/PGM/PPM
     All information available is extracted.

SVG
     SVG also provides (for) a plethora of attributes and metadata of an
     image.  See Image/Info/SVG, for details.

XBM
     See Image/Info/XBM, for details.

XPM
     See Image/Info/XPM, for details.

SEE ALSO
========

   See Image/Size,

AUTHOR
======

   Copyright 1999-2000 Gisle Aas.

   GIF fixes by Ralf Steines <metamonk@yahoo.com>

   ASCII, BMP SVG, XPM and XBM support added by Jerrad Pierce
<belg4mit@mit.edu>/<webmaster@pthbb.org>

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

ASCII support for Image::Info
*****************************

NAME
====

   Image::Info::ASCII - ASCII support for Image::Info

SYNOPSIS
========

     use Image::Info qw(image_info dim);

     my $info = image_info("image.txt");
     if (my $error = $info->{error}) {
         die "Can't parse image info: $error\n";
     }
     my $color = $info->{color_type};

     my($w, $h) = dim($info);

DESCRIPTION
===========

   This modules supplies the standard key names except for Compression,
Gamma, Interlace, LastModificationTime, as well as:

ColorPalette
     Reference to an array of all colors used.  This key is only present
     if `image_info' is invoked as `image_info({ColorPalette=>1})'.

ColorTableSize
     The number of colors the image uses.

L1D_Histogram
     Reference to an array representing a one dimensioanl luminance
     histogram. This key is only present if `image_info' is invoked as
     `image_info($file, L1D_Histogram=>1)'. The range is from 0 to 127,
     however auto-vivification is used so a null field is also 0, and the
     array may not actually contain 127 fields. The index in the array
     corresponds to the ord of the character and thusly fields
     0-8,11,12,14-31 should always be blank.

     While not immediately obvious, this could be used to accquire
     information about a normal text file and it's language.  Though it
     would likely have to be English, Hawaiian, Swahili, or Latin (unless
     you can be assured that no 8th bit characters occur in the first 32
     bytes of the source).

SEE ALSO
========

   See Image/Info, `ascii' in this node,
`http://czyborra.com/charsets/iso646.html'

NOTES
=====

   For more information about ASCII art see:

     news:alt.ascii-art

BUGS
====

   Other than being completely functional yet potentially useless?

AUTHOR
======

   Jerrad Pierce <belg4mit@mit.edu>/<webmaster@pthbb.org>

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   MAGIC: /^[\011\012\015\040-\176]*$/ && $_ !~
m%(^<\?xml)|(^#define\s+)|(^/\* XPM
\*/)|(static\s+char\s+\*\w+\[\]\s*=\s*{\s*"\d+)%

   For more information see Image/Info/ASCII.

Windows Device Indepdent Bitmap support for Image::Info
*******************************************************

NAME
====

   Image::Info:BMP - Windows Device Indepdent Bitmap support for
Image::Info

SYNOPSIS
========

     use Image::Info qw(image_info dim);

     my $info = image_info("image.bmp");
     if (my $error = $info->{error}) {
         die "Can't parse image info: $error\n";
     }
     my $color = $info->{color_type};

     my($w, $h) = dim($info);

DESCRIPTION
===========

   This modules supplies the standard key names except for Gamma,
Interlace, LastModificationTime, as well as:

BMP_ColorsImportant
     Specifies the number of color indexes that are required for
     displaying the bitmap. If this value is zero, all colors are required.

BMP_Origin
     If true the bitmap is a bottom-up DIB and its origin is the
     lower-left corner.  Otherwise, the bitmap is a top-down DIB and its
     origin is the upper-left corner.

ColorPalette
     Reference to an array of all colors used.  This key is only present
     if `image_info' is invoked as `image_info($file, ColorPalette=>1)'.

ColorTableSize
     The number of colors the image uses.  If 0 then this is a true color
     image.  The number of color *available* is 2 ^ BitsPerSample.

SEE ALSO
========

   See Image/Info,

NOTES
=====

   For more information about BMP see:

     http://msdn.microsoft.com

DIAGNOSTICS
===========

Size mismatch
     The image may be correct, the filesize does not match the internally
     stored value.

BUGS
====

   The current implementation only function on little-endian architectures.
Consequently erroneous data concerning compression (including file_ext and
*file_mime_type*) may be reported.

AUTHOR
======

   Jerrad Pierce <belg4mit@mit.edu>/<webmaster@pthbb.org>

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   MAGIC: /^BM/

   This module supports the Microsoft Device Independent Bitmap format
(BMP, DIB, RLE).

   For more information see Image/Info/BMP.

SVG support for Image::Info
***************************

NAME
====

   Image::Info::SVG - SVG support for Image::Info

SYNOPSIS
========

     use Image::Info qw(image_info dim);

     my $info = image_info("image.svg");
     if (my $error = $info->{error}) {
         die "Can't parse image info: $error\n";
     }
     my $color = $info->{color_type};

     my($w, $h) = dim($info);

DESCRIPTION
===========

   A functional yet thus far rudimentary SVG implementation.  SVG also
provides (for) a plethora of attributes and metadata of an image.

   This modules supplies the standard key names except for BitsPerSample,
Compression, Gamma, Interlace, LastModificationTime, as well as:

ImageDescription
     The image description, corresponds to <desc>.

SVG_Image
     A scalar or reference to an array of scalars containing the URI's of
     embedded images (JPG or PNG) that are embedded in the image.

SVG_StandAlone
     Whether or not the image is standalone.

SVG_Title
     The image title, corresponds to <title>

SVG_Version
     The URI of the DTD the image conforms to.

FILES
     This module requires XML/Simple,

SEE ALSO
========

   See Image/Info, XML/Simple, `expat'
in this node

NOTES
=====

   SVG is not yet a standard, though much software exists which is capable
of creating and displaying SVG images.  For more information about SVG see:

     http://www.w3.org/Graphics/SVG/

AUTHOR
======

   Jerrad Pierce <belg4mit@mit.edu>/<webmaster@pthbb.org>

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   MAGIC: /^<\?xml/

   SVG also provides (for) a plethora of attributes and metadata of an
image.  See Image/Info/SVG, for details.

XBM support for Image::Info
***************************

NAME
====

   Image::Info::XBM - XBM support for Image::Info

SYNOPSIS
========

     use Image::Info qw(image_info dim);

     my $info = image_info("image.xbm");
     if (my $error = $info->{error}) {
         die "Can't parse image info: $error\n";
     }
     my $color = $info->{color_type};

     my($w, $h) = dim($info);

DESCRIPTION
===========

   This modules supplies the standard key names except for Compression,
Gamma, Interlace, LastModificationTime, as well as:

HotSpotX
     The x-coord of the image's hotspot.  Set to -1 if there is no hotspot.

HotSpotY
     The y-coord of the image's hotspot.  Set to -1 if there is no hotspot.

L1D_Histogram
     Reference to an array representing a one dimensioanl luminance
     histogram. This key is only present if `image_info' is invoked as
     `image_info($file, L1D_Histogram=>1)'. The range is from 0 to 1.

FILES
     This module requires Image/Xbm,

SEE ALSO
========

   See Image/Info, Image/Xbm,

NOTES
=====

   For more information about XBM see:

     http://www.dcs.ed.ac.uk/home/mxr/gfx/2d/XBM.txt

AUTHOR
======

   Jerrad Pierce <belg4mit@mit.edu>/<webmaster@pthbb.org>

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   MAGIC: /^#define\s+/

   See Image/Info/XBM, for details.

XPM support for Image::Info
***************************

NAME
====

   Image::Info::XPM - XPM support for Image::Info

SYNOPSIS
========

     use Image::Info qw(image_info dim);

     my $info = image_info("image.xpm");
     if (my $error = $info->{error}) {
         die "Can't parse image info: $error\n";
     }
     my $color = $info->{color_type};

     my($w, $h) = dim($info);

DESCRIPTION
===========

   This modules supplies the standard key names except for Compression,
Gamma, Interlace, LastModificationTime, as well as:

ColorPalette
     Reference to an array of all colors used.  This key is only present
     if `image_info' is invoked as `image_info({ColorPalette>=1})'.

ColorTableSize
     The number of colors the image uses.

HotSpotX
     The x-coord of the image's hotspot.  Set to -1 if there is no hotspot.

HotSpotY
     The y-coord of the image's hotspot.  Set to -1 if there is no hotspot.

L1D_Histogram
     Reference to an array representing a one dimensioanl luminance
     histogram. This key is only present if `image_info' is invoked as
     `image_info($file, L1D_Histogram=>1)'. The range is from 0 to 255,
     however auto-vivification is used so a null field is also 0, and the
     array may not actually contain 255 fields.

XPM_CharactersPerPixel
     This is typically 1 or 2. See Image/Xpm.

     XPM Extensions (the most common is XPMEXT) if present.

FILES
     This module requires Image/Xpm,

     *$Image::Info::XPM::RGBLIB* is set to `/usr/X11R6/lib/X11/rgb.txt' by
     default, this is used to resolve textual color names to their RGB
     counterparts.

SEE ALSO
========

   See Image/Info, Image/Xpm,

NOTES
=====

   For more information about XPM see:

     ftp://ftp.x.org/contrib/libraries/xpm-README.html

CAVEATS
=======

   While the module attempts to be as robust as possible, it may not
recognize older XBMs (Versions 1-3), if this is the case try inserting
/* XPM */ as the first line.

AUTHOR
======

   Jerrad Pierce <belg4mit@mit.edu>/<webmaster@pthbb.org>

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   MAGIC: /(^\/\* XPM \*\/)|(static\s+char\s+\*\w+\[\]\s*=\s*{\s*"\d+)/

   See Image/Info/XPM, for details.

Perl extension for calling ImageMagick's libmagick routines
***********************************************************

NAME
====

   Image::Magick - Perl extension for calling ImageMagick's libmagick
routines

SYNOPSIS
========

     use Image::Magick;
     p = new Image::Magick;
     p->Read("imagefile");
     p->Set(attribute => value, ...)
     ($a, ...) = p->Get("attribute", ...)
     p->routine(parameter => value, ...)
     p->Mogrify("Routine", parameter => value, ...)
     p->Write("filename");

DESCRIPTION
===========

   This Perl extension allows the reading, manipulation and writing of a
large number of image file formats using the magick library from
ImageMagick by John Cristy (magick@wizards.dupont.com).  It was originally
developed to be used by CGI scripts for Web pages.

   A Web page has been set up for this extension. See:

     http://www.simplesystems.org/ImageMagick/www/perl.html

AUTHOR
======

   Kyle Shorter	magick@wizards.dupont.com

BUGS
====

   Has all the bugs of ImageMagick and much, much more!

SEE ALSO
========

   perl(1).

Parse a GIF image into its compenent parts.
*******************************************

NAME
====

   Image::ParseGIF - Parse a GIF image into its compenent parts.

SYNOPSIS
========

     use Image::ParseGIF;

     $gif = new Image::ParseGIF ("image.gif") or die "failed to parse: $@\n";

     # write out a deanimated version, showing only the first frame
     $gif->deanimate(0);

     #  same again, manually printing each part
     print $gif->header;
     print $gif->part(0);
     print $gif->trailer;
     #  or, without passing scalars around:
     $gif->print_header;
     $gif->print_part(0);
     $gif->print_trailer;

     # send an animated gif frame by frame
     #  - makes for a progress bar which really means something
     $gif = new Image::ParseGIF ("progress.gif") or die "failed to parse: $@\n";

     $gif->print_header;

     $gif->print_percent(0.00);	# starting...
     do_some_work_stage1();

     $gif->print_percent(0.10);	# 10% complete
     do_some_work_stage2();

     $gif->print_percent(0.25);	# 25% complete
     do_some_work_stage3();

     $gif->print_percent(0.70);	# 70% complete
     do_some_work_stage4();

     $gif->print_percent(1.00);	# done!

     $gif->print_trailer;

DESCRIPTION
===========

   This module parses a Graphics Interchange Format (GIF) image into its
component 'parts'. A GIF is essentially made up of one or more images -
multiple images typically are used for animated gifs.

PURPOSE
-------

   This module was written to allow a web application to display the status
of a request, without resorting to scripting or polling the server via
client refresh.

   Most web browsers (at least Netscape 2.02 & 4.05, Opera 3.21 and
Internet Explorer 4.0) show each frame as soon as it is received.
(Indeed, the GIF format is block-based so any image viewer which can
handle animated GIFs should operate similarly.) So, if we can arrange for
the parts of a progress bar image to be delivered to the client in
sympathy with the request's progress, we'll have made a dandy real-time
feedback mechanism. Contrast this with the common fixed animation used at
many sites, which are uncorrelated to the request state and not at all
realistic.

   One implementation of this status mechanism involves the main
application returning a page containing an image tag to a 'status' script
(e.g.  <img src="status.cgi?id="request_id">). The status script
interrogates the request's status (perhaps by reading from a pipe), and
prints image frames as the request progresses.

   At the moment the image is wholly read into memory. File pointers could
be used to operate from disk, however, given that most web images are on
the order of 1-100k, I don't see a lot of benefit in bothering to do so.
Also, if a persistant application is used (i.e. FCGI), the same image can
be reused for many requests.

BACKGROUND
----------

   A gif image consists of:

  1. a 'header' (including the GIF header (signature string) and logical
     screen descriptor)

  2. a global colour map

  3. zero or more 'graphic blocks' or 'extensions'

        * a block/extension header

        * one or more sub-blocks per part

  4. a trailer

        Note that this module groups the GIF header, logical screen
descriptor and any global colour map into the 'header' part.

   There are two types of 'descriptor blocks/extensions' defined in the GIF
specification [1]: an image descriptor; or an extension. Extensions can
contain 'control' information for things like animated gifs. Each
descriptor block/extension has its own 'header', often followed by one or
more data blocks. This module extracts only image descriptors and graphic
control extensions. Moreover, this module treats associated descriptor
blocks and extensions as a 'part' - an image 'part' is considered to be
the extension/s leading up to an image descriptor, plus the image
descriptor.

CONSTRUCTOR / CLASS METHODS
===========================

   In general, all `Image::ParseGIF' methods return undef on error,
possibly with an explanatory message in $@.

autoflush ( STATE )
     Class method (i.e. Image::ParseGIF::autoflush(0)). Sets default
     autoflush() state for new output streams. On by default.

new ( [FILENAME] )
new ( FILENAME [,  ARGUMENTS ] )
new ( FILENAME [, {ARGUMENTS}] )
     Creates a new `Image::ParseGIF' object.

     If FILENAME is supplied, opens and parses the given file.

     ARGUMENTS may be:

    'debug' (natural number)
          Set the debug level.

    'output' (IO::Handle/filehandle/glob)
          Sets the default output stream (default STDOUT). (See perl's
          binmode() regarding writing binary output.)

    'invert' (natural number)
          Adjusts the colour inversion feature (default 0 is off).

    'posterize' (natural number) =item 'posterise' (natural number)
          Adjusts the colour posterization (high pass filtering) feature
          (default 0 is off, positive values increase the resulting gamut).

    'desaturate' (natural number)
          Adjusts the colour-to-grayscale feature (default 0 is off).

METHODS
=======

debug ( LEVEL )
     If LEVEL is omitted, returns the current debug level setting.

     If LEVEL is defined, sets the current debug level.  The higher the
     debug level, the more output.

invert ( EXPR )
     If EXPR is omitted, returns the current colour inversion setting.

     If EXPR is defined, sets the current colour inversion setting.  Zero
     is off, nonzero inverts RGB colour table values, leaving each one as
     a photo-negative colour instead.  Default is 0.

posterize ( EXPR ) =item posterise ( EXPR )
     If EXPR is omitted, returns the current colour posterization setting.

     If EXPR is defined (N), sets the current colour posterization setting.
     Zero is off, nonzero posterizes RGB colour table values, leaving each
     one to be one of N colors. Default is 0.

desaturate ( EXPR )
     If EXPR is omitted, returns the current colour desaturization setting.

     If EXPR is defined, sets the current colour desaturization setting.
     Zero is off, nonzero desaturizes RGB colour table values, leaving
     each one as a mean grayscale value.  Default is 0.

open ( FILENAME )
     Opens the given file and parses it.

parse ( IO )
     Parse a GIF, reading from a given filehandle / IO::Handle.

(header|trailer)
     Returns the image (header|trailer) as a scalar.

parts
     Returns a list of the image parts in array context, or the number of
     parts in scalar context. Does not include header or trailer.

part ( PART )
     Returns an image part as a scalar. If PART == undef, returns header;
     if PART > number of parts, returns trailer.

output ( IO )
     Specifies the default output filehandle / IO::Handle for all
     subsequent print_ calls. (See perl's binmode() regarding writing
     binary output.)

print_(header|trailer) ( [IO] )
     Prints the (header|trailer) to the supplied / default output stream.

print_part ( [PART] [, IO] )
     Prints the given PART to the supplied / default output stream.

print_parts ( [PART] [, IO] )
     Remembers which part it was up to (PreviousPART), prints from from
     PreviousPART to PART to the supplied / default output stream.

print_percent ( PERCENT [, IO ] )
     Prints PERCENT percent of the image frames. Remembers where it was up
     to, and will only print increasing part numbers (i.e. it won't
     duplicate parts). Note you'll still need to print the header and
     trailer.

deanimate ( [PART] [, IO ] )
     Prints header, given part (or part 0 if unspecified) and trailer to
     the supplied / default output stream.

NOTES
=====

   You should be able to parse an image contained in any object which has
a read() method (e.g. IO::Scalar), however the object will have to support
the OFFSET read() argument. As at version 1.114, IO::Scalar does not.

   For example:   $io = new IO::File ('blah');   $gif = new
Image::ParseGIF;   $gif->parse($io) or die "failed to parse: $@\n";

"BUGS"
======

     It'd be nice to have a more generic interface to handle all GIF
     extensions, etc.

     And from the "In case you've ever wondered" department:

     Natural Number (http://mathworld.wolfram.com/NaturalNumber.html)

     "A positive integer 1, 2, 3, ... ([ref]). The set of natural numbers
     is denoted N or Z+. Unfortunately, 0 is sometimes also included in the
     list of "natural" numbers (Bourbaki 1968, Halmos 1974), and there
     seems to be no general agreement about whether to include it.  In
     fact, Ribenboim (1996) states "Let [P] be a set of natural numbers;
     whenever convenient, it may be assumed that [0 <element of> P].""

COPYRIGHT
=========

   Copyright (c) 1999/2000 University of New South Wales Benjamin Low
<b.d.low@unsw.edu.au>. All rights reserved.

   Colour-table portions added 1 June 2000 Ed Halley <ed@explorati.com>.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   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 Artistic License for more
details.

AUTHORS
=======

   Benjamin Low <b.d.low@unsw.edu.au>

   Ed Halley <ed@explorati.com>

SEE ALSO
========

   This code was based on the CGI 89a spec [1] and the Image::DeAnim module
by Ken MacFarlane.

   [1] http://member.aol.com/royalef/gif89a.txt

Perl module to easily grab images from the 'net.
************************************************

NAME
====

   Image::Grab - Perl module to easily grab images from the 'net.

Behavior Changes:
=================

   Since 1.1, I've made Image::Grab look for background images.  This
could cause you problems if the background images match your regexps or if
you use indexes.

   Since 0.9.5, I've added the search_url method in lieu of overloading
regexp.  This means that you'll have to check your scripts.

   Since 0.9.3, I've added the do_posix method and changed the behavior so
that POSIX date substitution is only done if do_posix is set.  This is
because strftime appears to garble the 128th character and on in long
string substitutions.  I've seen this in Digital Unix, Linux and Solaris.

Installation:
=============

   You must have the following modules already installed:

     Digest::MD5 2.07
     HTML::Parser 2.20
     HTML::Tree 0.51
     MIME::Base64 2.11
     URI 1.02
     libnet 1.0606
     libwww-perl 5.43

   (Earlier versions of some packages may work, but I haven't tested them.)

     $ perl Makefile.PL
     $ make test
     $ make install

   And that should do it.  Let me know of any problems
(<mah@everybody.org>)

Testing:
========

   Unless you have cookies for www.chron.com, the cookies.t test will be
skipped.  The tests rely on cookies being set in your ~/.netscape/cookies
file.  You could set these yourself by visiting the Huston Chronicle
website (http://www.chron/content/comics) and getting an account.  If you
don't do this, these tests won't even run.

   If you are testing this from behind a firewall, be sure that your proxy
environment variables are set correctly (e.g.
http_proxy=http://wwwproxy:80/).

Response:
=========

   If you care to, let me know how you are using this module.  It's nice
to know what different people are using this for.

read the dimensions of an image in several popular formats
**********************************************************

NAME
====

   Image::Size - read the dimensions of an image in several popular formats

SYNOPSIS
========

     use Image::Size;
     # Get the size of globe.gif
     ($globe_x, $globe_y) = imgsize("globe.gif");
     # Assume X=60 and Y=40 for remaining examples

     use Image::Size 'html_imgsize';
     # Get the size as 'width="X" height="Y"' for HTML generation
     $size = html_imgsize("globe.gif");
     # $size == 'width="60" height="40"'

     use Image::Size 'attr_imgsize';
     # Get the size as a list passable to routines in CGI.pm
     @attrs = attr_imgsize("globe.gif");
     # @attrs == ('-width', 60, '-height', 40)

     use Image::Size;
     # Get the size of an in-memory buffer
     ($buf_x, $buf_y) = imgsize($buf);

DESCRIPTION
===========

   The *Image::Size* library is based upon the `wwwis' script written by
Alex Knowles *(alex@ed.ac.uk)*, a tool to examine HTML and add 'width' and
'height' parameters to image tags. The sizes are cached internally based on
file name, so multiple calls on the same file name (such as images used in
bulleted lists, for example) do not result in repeated computations.

   *Image::Size* provides three interfaces for possible import:

imgsize(stream)
     Returns a three-item list of the X and Y dimensions (width and
     height, in that order) and image type of stream. Errors are noted by
     undefined (undef) values for the first two elements, and an error
     string in the third.  The third element can be (and usually is)
     ignored, but is useful when sizing data whose type is unknown.

html_imgsize(stream)
     Returns the width and height (X and Y) of stream pre-formatted as a
     single string `'width="X" height="Y"'' suitable for addition into
     generated HTML IMG tags. If the underlying call to `imgsize' fails,
     undef is returned. The format returned should be dually suited to
     both HTML and XHTML.

attr_imgsize(stream)
     Returns the width and height of stream as part of a 4-element list
     useful for routines that use hash tables for the manipulation of
     named parameters, such as the Tk or CGI libraries. A typical return
     value looks like `("-width", X, "-height", Y)'. If the underlying
     call to `imgsize' fails, undef is returned.

   By default, only `imgsize()' is imported. Any one or combination of the
three may be imported, or all three may be with the tag :all.

Input Types
-----------

   The sort of data passed as stream can be one of three forms:

string
     If an ordinary scalar (string) is passed, it is assumed to be a file
     name (either absolute or relative to the current working directory of
     the process) and is searched for and opened (if found) as the source
     of data.  Possible error messages (see DIAGNOSTICS below) may include
     file-access problems.

scalar reference
     If the passed-in stream is a scalar reference, it is interpreted as
     pointing to an in-memory buffer containing the image data.

          # Assume that &read_data gets data somewhere (WWW, etc.)
          $img = &read_data;
          ($x, $y, $id) = imgsize(\$img);
          # $x and $y are dimensions, $id is the type of the image

Open file handle
     The third option is to pass in an open filehandle (such as an object
     of the IO::File class, for example) that has already been associated
     with the target image file. The file pointer will necessarily move,
     but will be restored to its original position before subroutine end.

          # $fh was passed in, is IO::File reference:
          ($x, $y, $id) = imgsize($fh);
          # Same as calling with filename, but more abstract.

Recognizd Formats
-----------------

   Image::Size understands and sizes data in the following formats:

     GIF

     JPG

     XBM

     XPM

     PPM family (PPM/PGM/PBM)

     PNG

     TIF

     BMP

   When using the `imgsize' interface, there is a third, unused value
returned if the programmer wishes to save and examine it. This value is
the three- letter identity of the data type. This is useful when operating
on open file handles or in-memory data, where the type is as unknown as
the size.  The two support routines ignore this third return value, so
those wishing to use it must use the base `imgsize' routine.

DIAGNOSTICS
===========

   The base routine, `imgsize', returns undef as the first value in its
list when an error has occured. The third element contains a descriptive
error message.

   The other two routines simply return undef in the case of error.

MORE EXAMPLES
=============

   The *attr_imgsize* interface is also well-suited to use with the Tk
extension:

     $image = $widget->Photo(-file => $img_path, attr_imgsize($img_path));

   Since the Tk::Image classes use dashed option names as CGI does, no
further translation is needed.

   This package is also well-suited for use within an Apache web server
context.  File sizes are cached upon read (with a check against the
modified time of the file, in case of changes), a useful feature for a
mod_perl environment in which a child process endures beyond the lifetime
of a single request.  Other aspects of the mod_perl environment cooperate
nicely with this module, such as the ability to use a sub-request to fetch
the full pathname for a file within the server space. This complements the
HTML generation capabilities of the CGI module, in which `CGI::img' wants
a URL but `attr_imgsize' needs a file path:

     # Assume $Q is an object of class CGI, $r is an Apache request object.
     # $imgpath is a URL for something like "/img/redball.gif".
     $r->print($Q->img({ -src => $imgpath,
                         attr_imgsize($r->lookup_uri($imgpath)->filename) }));

   The advantage here, besides not having to hard-code the server document
root, is that Apache passes the sub-request through the usual request
lifecycle, including any stages that would re-write the URL or otherwise
modify it.

CAVEATS
=======

   Caching of size data can only be done on inputs that are file names.
Open file handles and scalar references cannot be reliably transformed
into a unique key for the table of cache data. Buffers could be cached
using the MD5 module, and perhaps in the future I will make that an
option. I do not, however, wish to lengthen the dependancy list by another
item at this time.

SEE ALSO
========

   `http://www.tardis.ed.ac.uk/~ark/wwwis/' for a description of `wwwis'
and how to obtain it.

AUTHORS
=======

   Perl module interface by Randy J. Ray *(rjray@tsoft.com)*, original
image-sizing code by Alex Knowles *(alex@ed.ac.uk)* and Andrew Tong
*(werdna@ugcs.caltech.edu)*, used with their joint permission.

   Some bug fixes submitted by Bernd Leibing
*(bernd.leibing@rz.uni-ulm.de)*.  PPM/PGM/PBM sizing code contributed by
Carsten Dominik *(dominik@strw.LeidenUniv.nl)*. Tom Metro
*(tmetro@vl.com)* re-wrote the JPG and PNG code, and also provided a PNG
image for the test suite. Dan Klein *(dvk@lonewolf.com)* contributed a
re-write of the GIF code.  Cloyce Spradling *(cloyce@headgear.org)*
contributed TIFF sizing code and test images. Aldo Calpini
*(a.calpini@romagiubileo.it)* suggested support of BMP images (which I
*really* should have already thought of :-) and provided code to work
with. A patch to allow html_imgsize to produce valid output for XHTML, as
well as some documentation fixes was provided by Charles Levert
*(charles@comm.polymtl.ca)*.

Load, create, manipulate and save xbm image files.
**************************************************

NAME
====

   Image::Xbm - Load, create, manipulate and save xbm image files.

SYNOPSIS
========

     use Image::Xbm ;

     my $j = Image::Xbm->new( -file, 'balArrow.xbm' ) ;

     my $i = Image::Xbm->new( -width => 10, -height => 16 ) ;

     my $h = $i->new ; # Copy of $i

     my $p = Image::Xbm->new_from_string( "###\n#-#\n###" ) ;

     my $q = $p->new_from_string( "H##", "#-#", "###" ) ;

     my $s = $q->serialse ; # Compresses a little too.
     my $t = Image::Xbm->new_from_serialsed( $s ) ;

     $i->xybit( 5, 8, 1 ) ;           # Set a bit
     print '1' if $i->xybit( 9, 3 ) ; # Get a bit
     print $i->xy( 4, 5 ) ;           # Will print black or white

     $i->vec( 24, 0 ) ;            # Set a bit using a vector offset
     print '1' if $i->vec( 24 ) ;  # Get a bit using a vector offset

     print $i->get( -width ) ;     # Get and set object and class attributes
     $i->set( -height, 15 ) ;

     $i->load( 'test.xbm' ) ;
     $i->save ;

     print "equal\n" if $i->is_equal( $j ) ;

     print $j->as_string ;

     #####-
     ###---
     ###---
     #--#--
     #---#-
     -----#

     print $j->as_binstring ;

     1111101110001110001001001000100000010000

   View an xbm file from the command line:

     % perl -MImage::Xbm -e'print Image::Xbm->new(-file,shift)->as_string' file

   Create an xbm file from the command line:

     % perl -MImage::Xbm -e'Image::Xbm->new_from_string("###\n#-#\n-#-")->save("test.xbm")'

DESCRIPTION
===========

   This class module provides basic load, manipulate and save
functionality for the xbm file format. It inherits from `Image::Base'
which provides additional manipulation functionality, e.g.
new_from_image(). See the `Image::Base' pod for information on adding your
own functionality to all the `Image::Base' derived classes.

new()
-----

     my $i = Image::Xbm->new( -file => 'test.xbm' ) ;
     my $j = Image::Xbm->new( -width => 12, -height => 18 ) ;
     my $k = $i->new ;

   We can create a new xbm image by reading in a file, or by creating an
image from scratch (all the bits are unset by default), or by copying an
image object that we created earlier.

   If we set `-file' then all the other arguments are ignored (since
they're taken from the file). If we don't specify a file, `-width' and
`-height' are mandatory.

`-file'
     The name of the file to read when creating the image. May contain a
     full path.  This is also the default name used for loading and
     saveing, though it can be overridden when you load or save.

`-width'
     The width of the image; taken from the file or set when the object is
     created; read-only.

`-height'
     The height of the image; taken from the file or set when the object
     is created; read-only.

`-hotx'
     The x-coord of the image's hotspot; taken from the file or set when
     the object is created. Set to -1 if there is no hotspot.

`-hoty'
     The y-coord of the image's hotspot; taken from the file or set when
     the object is created. Set to -1 if there is no hotspot.

`-bits'
     The bit vector that stores the image; read-only.

new_from_string()
-----------------

     my $p = Image::Xbm->new_from_string( "###\n#-#\n###" ) ;
     my $q = $p->new_from_string( "H##", "#-#", "###" ) ;
     my $r = $p->new_from_string( $p->as_string ) ;

   Create a new bitmap from a string or from an array or list of strings.
If you want to use different characters you can:

     Image::Xbm->set( -setch => 'X', -unsetch => ' ' ) ;
     my $s = $p->new_from_string( "XXX", "X X", "XhX" ) ;

   You can also specify a hotspot by making one of the characters a 'H'
(set bit hotspot) or 'h' (unset bit hotspot) - you can use different
characters by setting `-sethotch' and `-unsethotch' respectively.

new_from_serialised()
---------------------

     my $i = Image::Xbm->new_from_serialised( $s ) ;

   Creates an image from a string created with the `serialse()' method.
Since such strings are a little more compressed than xbm files or
Image::Xbm objects they might be useful if storing a lot of bitmaps, or
for transferring bitmaps over comms links.

serialise()
-----------

     my $s = $i->serialise ;

   Creates a string version of the image which can be completed recreated
using the `new_from_serialised' method.

get()          my $width = $i->get( -width ) ;     my( $hotx, $hoty ) = $i->get( -hotx, -hoty ) ;
-------------------------------------------------------------------------------------------------

   Get any of the object's attributes. Multiple attributes may be
requested in a single call.

   See `xy' and vec to get/set bits of the image itself.

set()
-----

     $i->set( -hotx => 120, -hoty => 32 ) ;

   Set any of the object's attributes. Multiple attributes may be set in a
single call. Except for `-setch' and `-unsetch' all attributes are object
attributes; some attributes are read-only.

   See `xy' and vec to get/set bits of the image itself.

class attributes
----------------

     Image::Xbm->set( -setch => 'X' ) ;
     $i->set( -setch => '@', -unsetch => '*' ) ;

`-setch'
     The character to print set bits as when using as_string, default is
     '#'.  This is a class attribute accessible from the class or an
     object via get and set.

`-unsetch'
     The character to print set bits as when using as_string, default is
     '-'.  This is a class attribute accessible from the class or an
     object via get and set.

`-sethotch'
     The character to print set bits as when using as_string, default is
     'H'.  This is a class attribute accessible from the class or an
     object via get and set.

`-unsethotch'
     The character to print set bits as when using as_string, default is
     'h'.  This is a class attribute accessible from the class or an
     object via get and set.

xybit()
-------

     $i->xy( 4, 11, 1 ) ;      # Set the bit at point 4,11
     my $v = $i->xy( 9, 17 ) ; # Get the bit at point 9,17

   Get/set bits using x, y coordinates; coordinates start at 0.

xy()
----

     $i->xy( 4, 11, 'black' ) ;  # Set the bit from a colour at point 4,11
     my $v = $i->xy( 9, 17 ) ;   # Get the bit as a colour at point 9,17

   Get/set bits using colours using x, y coordinates; coordinates start at
0.

   If set with a colour of 'black' or a numeric value > 0 or a string not
matching /^#0+$/ then the bit will be set, otherwise it will be cleared.

   If you get a colour you will always get 'black' or 'white'.

vec()
-----

     $i->vec( 43, 0 ) ;      # Unset the bit at offset 43
     my $v = $i->vec( 87 ) ; # Get the bit at offset 87

   Get/set bits using vector offsets; offsets start at 0.

load()
------

     $i->load ;
     $i->load( 'test.xbm' ) ;

   Load the image whose name is given, or if none is given load the image
whose name is in the `-file' attribute.

save()
------

     $i->save ;
     $i->save( 'test.xbm' ) ;

   Save the image using the name given, or if none is given save the image
using the name in the `-file' attribute. The image is saved in xbm format,
e.g.

     #define test_width 6
     #define test_height 6
     static unsigned char test_bits[] = {
      0x1f, 0x07, 0x07, 0x09, 0x11, 0x20 } ;

is_equal()
----------

     print "equal\n" if $i->is_equal( $j ) ;

   Returns true (1) if the images are equal, false (0) otherwise. Note that
hotspots and filenames are ignored, so we compare width, height and the
actual bits only.

as_string()
-----------

     print $i->as_string ;

   Returns the image as a string, e.g.

     #####-
     ###---
     ###---
     #--#--
     #---#-
     -----#

   The characters used may be changed by setting the `-setch' and
`-unsetch' characters. If you give as_string a parameter it will print out
the hotspot if present using `-sethotch' or `-unsethotch' as appropriate,
e.g.

     print $n->as_string( 1 ) ;

     H##
     #-#
     ###

as_binstring()
--------------

     print $i->as_binstring ;

   Returns the image as a string of 0's and 1's, e.g.

     1111101110001110001001001000100000010000

CHANGES
=======

   2000/11/09

   Added Jerrad Pierce's patch to allow load() to accept filehandles or
strings; will document in next release.

   2000/05/05

   Added new_from_serialised() and serialise() methods.

   2000/05/04

   Made xy() compatible with Image::Base, use xybit() for the earlier
functionality.

   2000/05/01

   Improved speed of vec(), xy() and as_string().

   Tried use integer to improve speed but according to Benchmark it made
the code slower so I dropped it; interestingly perl 5.6.0 was around 25%
slower than perl 5.004 with and without use integer.

   2000/04/30

   Created.

AUTHOR
======

   Mark Summerfield. I can be contacted as <summer@perlpress.com> - please
include the word 'xbm' in the subject line.

COPYRIGHT
=========

   Copyright (c) Mark Summerfield 2000. All Rights Reserved.

   This module may be used/distributed/modified under the LGPL.

Load, create, manipulate and save xpm image files.
**************************************************

NAME
====

   Image::Xpm - Load, create, manipulate and save xpm image files.

SYNOPSIS
========

     use Image::Xpm;

     my $j = Image::Xpm->new(-file, 'Camel.xpm');

     my $i = Image::Xpm->new(-width => 10, -height => 16);

     my $h = $i->new; # Copy of $i

     $i->xy(5, 8, 'red');       # Set a colour (& add to palette if necessary)
     print $i->xy(9, 3);        # Get a colour

     $i->xy(120, 130, '#1256DD');
     $i->xy(120, 130, $i->rgb2colour(66, 0x4D, 31));

     $i->vec(24, '#808080');    # Set a colour using a vector offset
     print $i->vec(24);         # Get a colour using a vector offset

     print $i->get(-width);     # Get and set object attributes
     $i->set(-height, 15);

     $i->load('test.xpm');
     $i->save;

     # Changing just the palette
     $i->add_colours(qw(red green blue #123456 #C0C0C0));
     $i->del_colour('blue');

DESCRIPTION
===========

   This class module provides basic load, manipulate and save
functionality for the xpm file format. It inherits from `Image::Base'
which provides additional manipulation functionality, e.g.
new_from_image(). See the `Image::Base' pod for information on adding your
own functionality to all the Image::Base derived classes.

new()
-----

     my $i = Image::Xpm->new(-file => 'test.xpm');
     my $j = Image::Xpm->new(-width => 12, -height => 18);
     my $k = $i->new;

   We can create a new xpm image by reading in a file, or by creating an
image from scratch (all the pixels are white by default), or by copying an
image object that we created earlier.

   If we set `-file' then all the other arguments are ignored (since
they're taken from the file). If we don't specify a file, `-width' and
`-height' are mandatory and `-cpp' will default to 1 unless specified
otherwise.

`-file'
     The name of the file to read when creating the image. May contain a
     full path.  This is also the default name used for loading and
     saveing, though it can be overridden when you load or save.

`-width'
     The width of the image; taken from the file or set when the object is
     created; read-only.

`-height'
     The height of the image; taken from the file or set when the object
     is created; read-only.

`-cpp'
     Characters per pixel. Commonly 1 or 2, default is 1 for images
     created by the module; read-only.

     See the example for how to change an image's cpp.

`-hotx'
     The x-coord of the image's hotspot; taken from the file or set when
     the object is created. Set to -1 if there is no hotspot.

`-hoty'
     The y-coord of the image's hotspot; taken from the file or set when
     the object is created. Set to -1 if there is no hotspot.

`-ncolours'
     The number of unique colours in the palette. The image may not be
     using all of them; read-only.

`-cindex'
     An hash whose keys are colour names, e.g. '#123456' or 'blue' and
     whose values are the palette names, e.g. ' ', '#', etc; read-only. If
     you want to add more colours to the image itself simply write pixels
     with the new colours using `xy'; if you want to add more colours to
     the palette without necessarily using them in the image use
     `add_colours'.

`-palette'
     A hash whose keys are the palette names, e.g. ' ', '#', etc. and
     whose values are hashes of colour type x colour name pairs, e.g. `c
     => red', etc; read-only. If you want to add more colours to the image
     itself simply write pixels with the new colours using `xy'; if you
     want to add more colours to the palette without necessarily using
     them in the image use `add_colours'.

`-pixels'
     A string of palette names which constitutes the data for the image
     itself; read-only.

`-extname'
     The name of the extension text if any; commonly XPMEXT; read-only.

`-extlines'
     The lines of text of any extensions; read-only.

`-comments'
     An array (possibly empty) of comment lines that were in a file that
     was read in; they will be written out although we make no guarantee
     regarding their placement; read-only.

get()          my $width = $i->get(-width);     my ($hotx, $hoty) = $i->get(-hotx, -hoty);
------------------------------------------------------------------------------------------

   Get any of the object's attributes. Multiple attributes may be
requested in a single call.

   See `xy' and vec to get/set colours of the image itself.

set()
-----

     $i->set(-hotx => 120, -hoty => 32);

   Set any of the object's attributes. Multiple attributes may be set in a
single call; some attributes are read-only.

   See `xy' and vec to get/set colours of the image itself.

xy()
----

     $i->xy(4, 11, '#123454');    # Set the colour at point 4,11
     my $v = $i->xy(9, 17);       # Get the colour at point 9,17

   Get/set colours using x, y coordinates; coordinates start at 0. If the
colour does not exist in the palette it will be added automatically.

   When called to set the colour the value returned is characters used for
that colour in the palette; when called to get the colour the value
returned is the colour name, e.g. 'blue' or '#f0f0f0', etc, e.g.

     $colour = xy($x, $y);            # e.g. #123456
     $cc     = xy($x, $y, $colour);   # e.g. !

   We don't normally pick up the return value when setting the colour.

vec()
-----

     $i->vec(43, 0);      # Unset the bit at offset 43
     my $v = $i->vec(87); # Get the bit at offset 87

   Get/set bits using vector offsets; offsets start at 0. The offset of a
pixel is ((y * width * cpp) + (x * cpp)).

   The sort of return value depends on whether we are reading (getting) or
writing (setting) the colour - see `xy' for an explanation.

rgb2colour() and rgb2color()          $i->rgb2colour(0xff, 0x40, 0x80);    # Returns #ff4080     Image::Xpm->rgb2colour(10, 20, 30);  # Returns #0a141e
-------------------------------------------------------------------------------------------------------------------------------------------------------

   Convenience class or object methods which accept three integers and
return a colour name string.

load()
------

     $i->load;
     $i->load('test.xpm');

   Load the image whose name is given, or if none is given load the image
whose name is in the `-file' attribute.

save()
------

     $i->save;
     $i->save('test.xpm');

   Save the image using the name given, or if none is given save the image
using the name in the `-file' attribute. The image is saved in xpm format.

add_colours() and add_colors()
------------------------------

     $i->add_colours(qw(#C0C0DD red blue #123456));

   These are for adding colours to the palette; you don't need to use them
to set a pixel's colour - use `xy' for that.

   Add one or more colour names either as hex strings or as literal colour
names.  These are always added as type 'c' colours; duplicates are ignored.

   NB If you just want to set some pixels in colours that may not be in the
palette, simply do so using `xy' since new colours are added automatically.

del_colour() and del_color()
----------------------------

     $i->del_colour('green');

   Delete a colour from the palette; returns undef if the colour isn't in
the palette, false (0) if the colour is in the palette but also in the
image, or true (1) if the colour has been deleted (i.e. it was in the
palette but not in use in the image).

EXAMPLE
=======

Changing the -cpp of an image:
------------------------------

     my $i = Image::Xpm(-file => 'test1.xpm'); # test1.xpm has cpp == 1
     my $j = $i->new_from_image('Image::xpm', -cpp => 2);
     $j->save('test2.xpm');

     # Could have written 2nd line above as:
     my $j = $i->new_from_image(ref $i, -cpp => 2);

CHANGES
=======

   2000/11/09

   Added Jerrad Pierce's patch to allow load() to accept filehandles or
strings; will document in next release.

   2000/10/19

   Fixed bugs in xy() and vec() reported by Pat Gunn.

   2000/05/25

   Fixed a bug in the test file; fixed a bug in save() which affected xpm
extensions.

   2000/05/04

   Fixed bugs in xy(), vec(), save() and load().  Improved the test
program.

   2000/05/03

   Created.

AUTHOR
======

   Mark Summerfield. I can be contacted as <summer@perlpress.com> - please
include the word 'xpm' in the subject line.

COPYRIGHT
=========

   Copyright (c) Mark Summerfield 2000. All Rights Reserved.

   This module may be used/distributed/modified under the GPL.

Perl extension for Generating 24 bit Images
*******************************************

NAME
====

   Imager - Perl extension for Generating 24 bit Images

SYNOPSIS
========

     use Imager;

     init();
     $img = Imager->new();
     $img->open(file=>'image.ppm',type=>'ppm')
       || print "failed: ",$img->{ERRSTR},"\n";
     $scaled=$img->scale(xpixels=>400,ypixels=>400);
     $scaled->write(file=>'sc_image.ppm',type=>'ppm')
       || print "failed: ",$scaled->{ERRSTR},"\n";

DESCRIPTION
===========

   Imager is a module for creating and altering images - It is not meant
as a replacement or a competitor to ImageMagick or GD. Both are excellent
packages and well supported.

API
---

   Almost all functions take the parameters in the hash fashion.  Example:

     $img->open(file=>'lena.png',type=>'png');

   or just:

     $img->open(file=>'lena.png');

Basic concept
-------------

   An Image object is created with `$img = Imager->new()' Should this fail
for some reason an explanation can be found in `$Imager::ERRSTR' usually
error messages are stored in `$img->{ERRSTR}', but since no object is
created this is the only way to give back errors.  `$Imager::ERRSTR' is
also used to report all errors not directly associated with an image
object. Examples:

     $img=Imager->new(); # This is an empty image (size is 0 by 0)
     $img->open(file=>'lena.png',type=>'png'); # initializes from file

   or if you want to create an empty image:

     $img=Imager->new(xsize=>400,ysize=>300,channels=>3);

   The latter example creates a completely black image of width 400 and
height 300 and 4 channels.

   To create a color object call the function i_color_new,
`$color=i_color_new($r,$g,$b,$a)'. The parameters are all from 0 to 255
and are all converted to integers. Each is the red, green, blue, and alpha
component of the color respectively.  This object can then be passed to
functions that require a color parameter.

   Coordinates in Imager have the origin in the upper left corner.  The
horizontal coordinate increases to the left and the vertical downwards.

Reading and writing images
--------------------------

   `$img->read()' generally takes two parameters, 'file' and 'type'.  If
the type of the file can be determined from the suffix of the file it can
be omitted.  Format dependant parameters are: For images of type 'raw' two
extra parameters are needed 'xsize' and 'ysize', if the 'channel'
parameter is omitted for type 'raw' it is assumed to be 3.  gif and png
images might have a palette are converted to truecolor bit when read.
Alpha channel is preserved for png images irregardless of them being in
RGB or gray colorspace.  Similarly grayscale jpegs are one channel images
after reading them.  For jpeg images the iptc header information (stored
in the APP13 header) is avaliable to some degree. You can get the raw
header with `$img->{IPTCRAW}', but you can also retrieve the most basic
information with `%hsh=$img->parseiptc()' as always patches are welcome.
Neither ppm nor tiff have extra options. Examples:

     $img = Imager->new();
     $img->read(file=>"cover.jpg") or die $img->errstr; # gets type from name

     $img = Imager->new();
     { local(*FH,$/); open(FH,"file.gif") or die $!; $a=<FH>; }
     $img->read(data=>$a,type=>'gif') or die $img->errstr;

   The second example shows how to read an image from a scalar, this is
usefull if your data originates from somewhere else than a filesystem such
as a database over a DBI connection.

   *Note that load() is now an alias for read but will be removed later*

   `$img->write' has the same interface as read().  The earlier comments
on read() for autodetecting filetypes apply.  For jpegs quality can be
adjusted via the 'jpegquality' parameter (0-100).  The number of
colorplanes in gifs are set with 'gifplanes' and should be between 1 (2
color) and 8 (256 colors).  It is also possible to choose between two
quantizing methods with the parameter 'gifquant'. If set to mc it uses the
mediancut algorithm from either giflibrary. If set to lm it uses a local
means algorithm. It is then possible to give some extra settings. lmdither
is the dither deviation amount in pixels (manhattan distance).  lmfixed
can be an array ref who holds an array of i_color objects.  Note that the
local means algorithm needs much more cpu time but also gives considerable
better results than the median cut algorithm.

   Currently just for gif files, you can specify various options for the
conversion from Imager's internal RGB format to the target's indexed file
format.  If you set the gifquant option to 'gen', you can use the options
specified under `Quantization options' in this node.

   To see what Imager is compiled to support the following code snippet is
sufficient:

     use Imager;
     print "@{[keys %Imager::formats]}";

Multi-image files
-----------------

   Currently just for gif files, you can create files that contain more
than one image.

   To do this:

     Imager->write_multi(\%opts, @images)

   Where %opts describes 3 possible types of outputs:

callback
     A code reference which is called with a single parameter, the data to
     be written.  You can also specify $opts{maxbuffer} which is the
     maximum amount of data buffered.  Note that there can be larger writes
     than this if the file library writes larger blocks.  A smaller value
     maybe useful for writing to a socket for incremental display.

fd
     The file descriptor to save the images to.

file
     The name of the file to write to.

     %opts may also include the keys from `Gif options' in this node and
     `Quantization options' in this node.

   The current aim is to support other multiple image formats in the
future, such as TIFF, and to support reading multiple images from a single
file.

Gif options
-----------

   These options can be specified when calling write_multi() for gif
files, when writing a single image with the gifquant option set to 'gen',
or for direct calls to i_writegif_gen and i_writegif_callback.

   Note that some viewers will ignore some of these options
(gif_user_input in particular).

gif_each_palette
     Each image in the gif file has it's own palette if this is non-zero.
     All but the first image has a local colour table (the first uses the
     global colour table.

interlace
     The images are written interlaced if this is non-zero.

gif_delays
     A reference to an array containing the delays between images, in 1/100
     seconds.

gif_user_input
     A reference to an array contains user input flags.  If the given flag
     is non-zero the image viewer should wait for input before displaying
     the next image.

gif_disposal
     A reference to an array of image disposal methods.  These define what
     should be done to the image before displaying the next one.  These are
     integers, where 0 means unspecified, 1 means the image should be left
     in place, 2 means restore to background colour and 3 means restore to
     the previous value.

gif_tran_color
     A reference to an Imager::Color object, which is the colour to use for
     the palette entry used to represent transparency in the palette.

gif_positions
     A reference to an array of references to arrays which represent screen
     positions for each image.

gif_loop_count
     If this is non-zero the Netscape loop extension block is generated,
     which makes the animation of the images repeat.

     This is currently unimplemented due to some limitations in giflib.

Quantization options
--------------------

   These options can be specified when calling write_multi() for gif
files, when writing a single image with the gifquant option set to 'gen',
or for direct calls to i_writegif_gen and i_writegif_callback.

colors
     A arrayref of colors that are fixed.  Note that some color generators
     will ignore this.

transp
     The type of transparency processing to perform for images with an
     alpha channel where the output format does not have a proper alpha
     channel (eg. gif).  This can be any of:

    none
          No transparency processing is done. (default)

    threshold
          Pixels more transparent that tr_threshold are rendered as
          transparent.

    errdiff
          An error diffusion dither is done on the alpha channel.  Note
          that this is independent of the translation performed on the
          colour channels, so some combinations may cause undesired
          artifacts.

    ordered
          The ordered dither specified by tr_orddith is performed on the
          alpha channel.

tr_threshold
     The highest alpha value at which a pixel will be made transparent when
     transp is 'threshold'. (0-255, default 127)

tr_errdiff
     The type of error diffusion to perform on the alpha channel when
     transp is 'errdiff'.  This can be any defined error diffusion type
     except for custom (see errdiff below).

tr_ordered
     The type of ordered dither to perform on the alpha channel when transp
     is 'orddith'.  Possible values are:

    random
          A semi-random map is used.  The map is the same each time.
          Currently the default (which may change.)

    dot8
          8x8 dot dither.

    dot4
          4x4 dot dither

    hline
          horizontal line dither.

    vline
          vertical line dither.

    "/line"
    slashline
          diagonal line dither

    '\line'
    backline
          diagonal line dither

    custom
          A custom dither matrix is used - see tr_map

tr_map
     When tr_orddith is custom this defines an 8 x 8 matrix of integers
     representing the transparency threshold for pixels corresponding to
     each position.  This should be a 64 element array where the first 8
     entries correspond to the first row of the matrix.  Values should be
     betweern 0 and 255.

make_colors
     Defines how the quantization engine will build the palette(s).
     Currently this is ignored if 'translate' is 'giflib', but that may
     change.  Possible values are:

    none
          Only colors supplied in 'colors' are used.

    webmap
          The web color map is used (need url here.)

    addi
          The original code for generating the color map (Addi's code) is
          used.

     Other methods may be added in the future.

colors
     A arrayref containing Imager::Color objects, which represents the
     starting set of colors to use in translating the images.  webmap will
     ignore this.  The final colors used are copied back into this array
     (which is expanded if necessary.)

max_colors
     The maximum number of colors to use in the image.

translate
     The method used to translate the RGB values in the source image into
     the colors selected by make_colors.  Note that make_colors is ignored
     whene translate is 'giflib'.

     Possible values are:

    giflib
          The giflib native quantization function is used.

    closest
          The closest color available is used.

    perturb
          The pixel color is modified by perturb, and the closest color is
          chosen.

    errdiff
          An error diffusion dither is performed.

     It's possible other transate values will be added.

errdiff
     The type of error diffusion dither to perform.  These values (except
     for custom) can also be used in tr_errdif.

    floyd
          Floyd-Steinberg dither

    jarvis
          Jarvis, Judice and Ninke dither

    stucki
          Stucki dither

    custom
          Custom.  If you use this you must also set errdiff_width,
          errdiff_height and errdiff_map.

errdiff_width
errdiff_height
errdiff_orig
errdiff_map
     When translate is 'errdiff' and errdiff is 'custom' these define a
     custom error diffusion map.  errdiff_width and errdiff_height define
     the size of the map in the arrayref in errdiff_map.  errdiff_orig is
     an integer which indicates the current pixel position in the top row
     of the map.

perturb
     When translate is 'perturb' this is the magnitude of the random bias
     applied to each channel of the pixel before it is looked up in the
     color table.

Obtaining/setting attributes of images
--------------------------------------

   To get the size of an image in pixels the `$img->getwidth()' and
`$img->getheight()' are used.

   To get the number of channels in an image `$img->getchannels()' is
used.  $img->getmask() and $img->setmask() are used to get/set the channel
mask of the image.

     $mask=$img->getmask();
     $img->setmask(mask=>1+2); # modify red and green only
     $img->setmask(mask=>8); # modify alpha only
     $img->setmask(mask=>$mask); # restore previous mask

   The mask of an image describes which channels are updated when some
operation is performed on an image.  Naturally it is not possible to apply
masks to operations like scaling that alter the dimensions of images.

   It is possible to have Imager find the number of colors in an image by
using `$img->getcolorcount()'. It requires memory proportionally to the
number of colors in the image so it is possible to have it stop sooner if
you only need to know if there are more than a certain number of colors in
the image.  If there are more colors than asked for the function return
undef.  Examples:

     if (!defined($img->getcolorcount(maxcolors=>512)) {
       print "Less than 512 colors in image\n";
     }

Drawing Methods
---------------

   IMPLEMENTATION MORE OR LESS DONE CHECK THE TESTS

   DOCUMENTATION OF THIS SECTION OUT OF SYNC

   It is possible to draw with graphics primitives onto images.  Such
primitives include boxes, arcs, circles and lines.  A reference oriented
list follows.

   Box:
$img->box(color=>$blue,xmin=>10,ymin=>30,xmax=>200,ymax=>300,filled=>1);

   The Above example calls the box method for the image and the box covers
the pixels with in the rectangle specified.  If `filled' is ommited it is
drawn as an outline.  If any of the edges of the box are ommited it will
snap to the outer edge of the image in that direction.  Also if a color is
omitted a color with (255,255,255,255) is used instead.

   Arc:   $img->arc(color=>$red, r=20, x=>200, y=>100, d1=>10, d2=>20 );

   This creates a red arc with a 'center' at (200, 100) and spans 10
degrees and the slice has a radius of 20. SEE section on BUGS.

   Circle:   $img->circle(color=>$green, r=50, x=>200, y=>100);

   This creates a green circle with its center at (200, 100) and has a
radius of 20.

   Line:   $img->line(color=>$green, x1=10, x2=>100,
     y1=>20, y2=>50, antialias=>1 );

   That draws an antialiased line from (10,100) to (20,50).

   Polyline:
$img->polyline(points=>[[$x0,$y0],[$x1,$y1],[$x2,$y2]],color=>$red);
$img->polyline(x=>[$x0,$x1,$x2], y=>[$y0,$y1,$y2], antialias=>1);

   Polyline is used to draw multilple lines between a series of points.
The point set can either be specified as an arrayref to an array of array
references (where each such array represents a point).  The other way is
to specify two array references.

Text rendering
--------------

   To create a font object you can use:

     $t1font = Imager::Font->new(file=>'pathtofont.pfb');
     $ttfont = Imager::Font->new(file=>'pathtofont.ttf');

   As is two types of font types are supported t1 postscript fonts and
truetype fonts.  You can see if they are supported in your binary with the
`%Imager::formats' hash.  It is possible to control other attributes the
font such as default color, size and anti aliasing.

     $blue = Imager::Color->new(10,10,255,0);
     $t1font = Imager::Font->new(file=>'pathtofont.pfb',
                                 color=>$blue,
                                 size=30);

   To draw text on images the string method of the images is used.  A font
must be passed to the method.

     $img=Imager->new();
     $img=read(file=>"test.jpg");
     $img->string(font=>$t1font,
                  text=>"Model-XYZ",
                  x=>0,
                  y=>40,
                  size=>40,
                  color=>$red);
     $img->write(file=>"testout.jpg");

   This would put a 40 pixel high text in the top left corner of an image.
If you measure the actuall pixels it varies since the fonts usually do
not use their full height.  It seems that the color and size can be
specified twice.  When a font is created only the actual font specified
matters.  It his however convenient to store default values in a font,
such as color and size.  If parameters are passed to the string function
they are used instead of the defaults stored in the font.

   If string() is called with the channel parameter then the color isn't
used and the font is drawn in only one channel.  This can be quite handy
to create overlays.  See the examples for tips about this.

   Sometimes it is necessary to know how much space a string takes before
rendering it.  The bounding_box() method of a font can be used for that.
examples:

     @bbox=$font->bounding_box(string=>"testing",size=>15);
     @bbox=$font->bounding_box(string=>"testing",size=>15,canon=>1);
     @bbox=$font->bounding_box(string=>"testing",size=>15,x=50,y=>20);

   The first example gets the so called glyph metrics.  First is the

Image resizing
--------------

   To scale an image so porportions are maintained use the `$img->scale()'
method.  if you give either a xpixels or ypixels parameter they will
determine the width or height respectively.  If both are given the one
resulting in a larger image is used.  example: `$img' is 700 pixels wide
and 500 pixels tall.

     $img->scale(xpixels=>400); # 400x285
     $img->scale(ypixels=>400); # 560x400

     $img->scale(xpixels=>400,ypixels=>400); # 560x400
     $img->scale(xpixels=>400,ypixels=>400,type=>min); # 400x285

     $img->scale(scalefactor=>0.25); 175x125 $img->scale(); # 350x250

   if you want to create low quality previews of images you can pass
`qtype=>'preview'' to scale and it will use nearest neighbor sampling
instead of filtering. It is much faster but also generates worse looking
images - especially if the original has a lot of sharp variations and the
scaled image is by more than 3-5 times smaller than the original.

   If you need to scale images per axis it is best to do it simply by
calling scaleX and scaleY.  You can pass either 'scalefactor' or 'pixels'
to both functions.

   Another way to resize an image size is to crop it.  The parameters to
crop are the edges of the area that you want in the returned image.  If a
parameter is omited a default is used instead.

     $newimg = $img->crop(left=>50, right=>100, top=>10, bottom=>100);
     $newimg = $img->crop(left=>50, top=>10, width=>50, height=>90);
     $newimg = $img->crop(left=>50, right=>100); # top

Copying images
--------------

   To create a copy of an image use the copy() method.  This is usefull if
you want to keep an original after doing something that changes the image
inplace like writing text.

     $img=$orig->copy();

   To copy an image to onto another image use the `paste()' method.

     $dest->paste(left=>40,top=>20,img=>$logo);

   That copies the entire `$logo' image onto the $dest image so that the
upper left corner of the `$logo' image is at (40,20).

Blending Images   To put an image or a part of an image directly into another it is best to call the `paste()' method on the image you want to add to.
------------------------------------------------------------------------------------------------------------------------------------------------------

     $img->paste(img=>$srcimage,left=>30,top=>50);

   That will take paste `$srcimage' into `$img' with the upper left corner
at (30,50).  If no values are given for left or top they will default to 0.

   A more complicated way of blending images is where one image is put
'over' the other with a certain amount of opaqueness.  The method that
does this is rubthrough.

     $img->rubthrough(src=>$srcimage,tx=>30,ty=>50);

   That will take the image `$srcimage' and overlay it with the upper left
corner at (30,50).  The `$srcimage' must be a 4 channel image.  The last
channel is used as an alpha channel.

Filters
-------

   A special image method is the filter method. An example is:

     $img->filter(type=>'autolevels');

   This will call the autolevels filter.  Here is a list of the filters
that are always avaliable in Imager.  This list can be obtained by running
the `filterlist.perl' script that comes with the module source.

     Filter          Arguments
     turbnoise
     autolevels      lsat(0.1) usat(0.1) skew(0)
     radnoise
     noise           amount(3) subtype(0)
     contrast        intensity
     hardinvert

   The default values are in parenthesis.  All parameters must have some
value but if a parameter has a default value it may be omitted when
calling the filter function.

Transformations
---------------

   Another special image method is transform.  It can be used to generate
warps and rotations and such features.  It can be given the operations in
postfix notation or the module Affix::Infix2Postfix can be used.  Look in
the test case t/t55trans.t for an example.

   Later versions of Imager also support a transform2() class method which
allows you perform a more general set of operations, rather than just
specifying a spatial transformation as with the transform() method, you
can also perform colour transformations, image synthesis and image
combinations.

   transform2() takes an reference to an options hash, and a list of
images to operate one (this list may be empty):

     my %opts;
     my @imgs;
     ...
     my $img = Imager::transform2(\%opts, @imgs)
         or die "transform2 failed: $Imager::ERRSTR";

   The options hash may define a transformation function, and optionally:

   * width - the width of the image in pixels.  If this isn't supplied the
     width of the first input image is used.  If there are no input images
     an error occurs.

   * height - the height of the image in pixels.  If this isn't supplied
     the height of the first input image is used.  If there are no input
     images an error occurs.

   * constants - a reference to hash of constants to define for the
     expression engine.  Some extra constants are defined by Imager

   The tranformation function is specified using either the expr or
rpnexpr member of the options.

Infix expressions
     You can supply infix expressions to transform 2 with the expr keyword.

     $opts{expr} = 'return getp1(w-x, h-y)'

     The 'expression' supplied follows this general grammar:

          ( identifier '=' expr ';' )* 'return' expr

     This allows you to simplify your expressions using variables.

     A more complex example might be:

     $opts{expr} = 'pix = getp1(x,y); return
     if(value(pix)>0.8,pix*0.8,pix)'

     Currently to use infix expressions you must have the Parse::RecDescent
     module installed (available from CPAN).  There is also what might be a
     significant delay the first time you run the infix expression parser
     due to the compilation of the expression grammar.

Postfix expressions
     You can supply postfix or reverse-polish notation expressions to
     transform2() through the rpnexpr keyword.

     The parser for rpnexpr emulates a stack machine, so operators will
     expect to see their parameters on top of the stack.  A stack machine
     isn't actually used during the image transformation itself.

     You can store the value at the top of the stack in a variable called
     foo using !foo and retrieve that value again using @foo.  The !foo
     notation will pop the value from the stack.

     An example equivalent to the infix expression above:

          $opts{rpnexpr} = 'x y getp1 !pix @pix value 0.8 gt @pix 0.8 * @pix ifp'

   transform2() has a fairly rich range of operators.

+, *, -, /, %, **
     multiplication, addition, subtraction, division, remainder and
     exponentiation.  Multiplication, addition and subtraction can be used
     on colour values too - though you need to be careful - adding 2 white
     values together and multiplying by 0.5 will give you grey, not white.

     Division by zero (or a small number) just results in a large number.
     Modulo zero (or a small number) results in zero.

sin(N), cos(N), atan2(y,x)
     Some basic trig functions.  They work in radians, so you can't just
     use the hue values.

distance(x1, y1, x2, y2)
     Find the distance between two points.  This is handy (along with
     atan2()) for producing circular effects.

sqrt(n)
     Find the square root.  I haven't had much use for this since adding
     the distance() function.

abs(n)
     Find the absolute value.

getp1(x,y), getp2(x,y), getp3(x, y)
     Get the pixel at position (x,y) from the first, second or third image
     respectively.  I may add a getpn() function at some point, but this
     prevents static checking of the instructions against the number of
     images actually passed in.

value(c), hue(c), sat(c), hsv(h,s,v)
     Separates a colour value into it's value (brightness), hue (colour)
     and saturation elements.  Use hsv() to put them back together (after
     suitable manipulation).

red(c), green(c), blue(c), rgb(r,g,b)
     Separates a colour value into it's red, green and blue colours.  Use
     rgb(r,g,b) to put it back together.

int(n)
     Convert a value to an integer.  Uses a C int cast, so it may break on
     large values.

if(cond,ntrue,nfalse), if(cond,ctrue,cfalse)
     A simple (and inefficient) if function.

<=,<,==,>=,>,!=
     Relational operators (typically used with if()).  Since we're working
     with floating point values the equalities are 'near equalities' - an
     epsilon value is used.

&&, ||, not(n)
     Basic logical operators.

   A few examples:

rpnexpr=>'x 25 % 15 * y 35 % 10 * getp1 !pat x y getp1 !pix @pix sat 0.7 gt @pat @pix ifp'
     tiles a smaller version of the input image over itself where the
     colour has a saturation over 0.7.

rpnexpr=>'x 25 % 15 * y 35 % 10 * getp1 !pat y 360 / !rat x y getp1 1 @rat - pmult @pat @rat pmult padd'
     tiles the input image over itself so that at the top of the image the
     full-size image is at full strength and at the bottom the tiling is
     most visible.

rpnexpr=>'x y getp1 !pix @pix value 0.96 gt @pix sat 0.1 lt and 128 128 255 rgb @pix ifp'
     replace pixels that are white or almost white with a palish blue

rpnexpr=>'x 35 % 10 * y 45 % 8 * getp1 !pat x y getp1 !pix @pix sat 0.2 lt @pix value 0.9 gt and @pix @pat @pix value 2 / 0.5 + pmult ifp'
     Tiles the input image overitself where the image isn't white or almost
     white.

rpnexpr=>'x y 160 180 distance !d y 180 - x 160 - atan2 !a @d 10 / @a + 3.1416 2 * % !a2 @a2 180 * 3.1416 / 1 @a2 sin 1 + 2 / hsv'
     Produces a spiral.

rpnexpr=>'x y 160 180 distance !d y 180 - x 160 - atan2 !a @d 10 / @a + 3.1416 2 * % !a2 @a 180 * 3.1416 / 1 @a2 sin 1 + 2 / hsv'
     A spiral built on top of a colour wheel.

   For details on expression parsing see Imager/Expr.
For details on the virtual machine used to transform the images, see
`Imager::regmach.pod' in this node.

Plugins
-------

   It is possible to add filters to the module without recompiling the
module itself.  This is done by using DSOs (Dynamic shared object)
avaliable on most systems.  This way you can maintain our own filters and
not have to get me to add it, or worse patch every new version of the
Module.  Modules can be loaded AND UNLOADED at runtime.  This means that
you can have a server/daemon thingy that can do something like:

     load_plugin("dynfilt/dyntest.so")  || die "unable to load plugin\n";
     %hsh=(a=>35,b=>200,type=>lin_stretch);
     $img->filter(%hsh);
     unload_plugin("dynfilt/dyntest.so") || die "unable to load plugin\n";
     $img->write(type=>'ppm',file=>'testout/t60.jpg')
       || die "error in write()\n";

   Someone decides that the filter is not working as it should - dyntest.c
modified and recompiled.

     load_plugin("dynfilt/dyntest.so") || die "unable to load plugin\n";
     $img->filter(%hsh);

   An example plugin comes with the module - Please send feedback to
addi@umich.edu if you test this.

   Note: This seems to test ok on the following systems: Linux, Solaris,
HPUX, OpenBSD, FreeBSD, TRU64/OSF1, AIX.  If you test this on other
systems please let me know.

BUGS
====

   box, arc, circle do not support antialiasing yet.  arc, is only filled
as of yet.  Some routines do not return $self where they should.  This
affects code like this, `$img->box()->arc()' where an object is expected.

   When saving Gif images the program does NOT try to shave of extra
colors if it is possible.  If you specify 128 colors and there are only 2
colors used - it will have a 128 colortable anyway.

AUTHOR
======

   Arnar M. Hrafnkelsson, addi@umich.edu And a great deal of help from
others - see the README for a complete list.  =head1 SEE ALSO

   perl(1), Affix::Infix2Postfix(3).
http://www.eecs.umich.edu/~addi/perl/Imager/

implements expression parsing and compilation for the  expression evaluation engine used by Imager::transform2()
****************************************************************************************************************

NAME
====

   Imager::Expr - implements expression parsing and compilation for the
expression evaluation engine used by Imager::transform2()

SYNOPSIS
========

   my $code = Imager::Expr->new({rpnexpr=>$someexpr})   or die "Cannot
compile $someexpr: ",Imager::Expr::error();

DESCRIPTION
===========

   This module is used internally by the Imager::transform2() function.
You shouldn't have much need to use it directly, but you may want to
extend it.

   To create a new Imager::Expr object, call:

     my %options;
     my $expr = Imager::Expr->new(\%options)
       or die Imager::Expr::error();

   You will need to set an expression value and you may set any of the
following:

constants
     A hashref defining extra constants for expression parsing.  The names
     of the constants must be valid identifiers (/[^\W\d]\w*/) and the
     values must be valid numeric constants (that Perl recognizes in
     scalars).

     Imager::Expr may define it's own constants (currently just pi.)

variables
     A reference to an array of variable names.  These are allocated
     numeric registers starting from register zero.

   By default you can define a 'rpnexpr' key (which emulates RPN) or
'expr' (an infix expression).  It's also possible to write other
expression parsers that will use other keys.  Only one expression key
should be defined.

Instance methods
----------------

   The Imager::Expr::error() method is used to retrieve the error if the
expression object cannot be created.

Methods
-------

   Imager::Expr provides only a few simple methods meant for external use:

$expr->code()
     Returns the compiled code.

$expr->nregs()
     Returns a reference to the array of numeric registers.

$expr->cregs()
     Returns a reference to the array of colour registers.

$expr->dumpops()
     Returns a string with the generated VM "machine code".

$expr->dumpcode()
     Returns a string with the unassembled VM "machine code".

Creating a new parser
---------------------

   I'll write this one day.

   Methods used by parsers:

@vars = $self->_variables()
     A list (not a reference) of the input variables.  This should be used
     to allocate as many registers as there are variable as input
     registers.

$self->error($message)
     Set the return value of Imager::Expr::error()

@ops = $self->stack_to_reg(@stack_ops)
     Converts marginally parsed RPN to register code.

Future compatibility
--------------------

   Try to avoid doing your own optimization beyond literal folding - if we
add some sort of jump, the existing optimizer will need to be rewritten,
and any optimization you perform may well be broken too (well, your code
generation will probably be broken anyway <sigh>).

generated information about the register based VM
*************************************************

NAME
====

   Imager::Regops - generated information about the register based VM

SYNOPSIS
========

     use Imager::Regops;
     $Imager::Regops::Attr{$opname}->{opcode} # opcode for given operator
     $Imager::Regops::Attr{$opname}->{parms} # number of parameters
     $Imager::Regops::Attr{$opname}->{types} # types of parameters
     $Imager::Regops::Attr{$opname}->{func} # operator is a function
     $Imager::Regops::Attr{$opname}->{result} # r for numeric, p for pixel result
     $Imager::Regops::MaxOperands; # maximum number of operands

DESCRIPTION
===========

   This module is generated automatically from regmach.h so we don't need
to maintain the same information in at least one extra place.

   At least that's the idea.

AUTHOR
======

   Tony Cook, tony@develop-help.com

SEE ALSO
========

   perl(1), Imager(3), http://www.eecs.umich.edu/~addi/perl/Imager/

documents the register virtual machine used by Imager::transform2().
********************************************************************

NAME
====

   Imager::regmach - documents the register virtual machine used by
Imager::transform2().

SYNOPSIS
========

   The register machine is a complete rewrite of the stack machine
orginally used by Imager::transform(), written for use by
Imager::transform2().

DESCRIPTION
===========

   (This document might be a little incoherent.)

   The register machine is a fast implementation of a small instruction
set designed for evaluating an arithmetic expression to produce a colour
for an image.

   The machine takes as input:

instructions
     An array of instructions

numeric registers
     An array of numeric registers.  Some registers are initialized as
     literals.

colour registers
     An array of colour registers.  Currently these registers aren't
     initialized.

input images
     An array of Imager i_img pointers.  The getpn operators read pixels
     from these images.

   The instructions supplied each take up to 4 input numeric or colour
registers with a single output numeric or colour register.  The machine
attempts to execute instructions as safely as possible, assuming that
correct instructions have been provided, eg. the machine protects against
divide by zero, but doesn't check register numbers for validity.

   The final instruction must be a 'ret' instruction, which returns the
result ;)

Adding new instructions
-----------------------

   To add a new instruction:

  1. Add a new opcode to the enumeration in regmach.h - make sure to add
     comment after the enum name giving the input registers (rX for
     numeric, pX for colour) that the instruction takes.  These must be in
     the order that the instruction expects to take the.  Put a letter (r
     or p) after -> to indicate the result type.

  2. Add a case to regmach.c that executes the instruction.

  3. make

        The makefile should rebuild the Regops.pm file, and your new
instruction will be added as a function.

   If you want to add a single alternative instruction that might take
different argument types (it must take the same number of parameters),
create another instruction with that name followed by a p.  The current
expression parsers explicitly look for such instruction names.

Future directions
-----------------

   Conditional and non-conditional jumps to implement iteration.  This
will break the current optimizer in Imager/Expr, (and
the compilers for both expression compilers, for that matter.)

   Complex arithmetic (Addi suggested this one).  This would most likely
be a separate machine.  Otherwise we'll have a very significant
performance loss.

WARNINGS
========

   If you feed bad 'machine code' to the register machine, you have a good
chance of a SIGSEGV.

Perl extension for printing envelopes for Infobrief mailings according to the standards of the Deutsche Bundespost
******************************************************************************************************************

NAME
====

   InfoBrief - Perl extension for printing envelopes for Infobrief
mailings according to the standards of the Deutsche Bundespost

SYNOPSIS
========

     use InfoBrief;
     $x = new InfoBrief %OPTIONS;
     print $x->preamble;
     print $x->page(@address);
     print $x->trailer;

DESCRIPTION
===========

   This modules is probably not very useful outside of Germany. It is a
tool dedicated for printing envelopes for Infobrief mailings according to
the standards of the Deutsche Bundespost. You may customize it for other
standards though.

   The output generated is Postscript level 2 and conforms to EPSF 1.2.
Since `copypage' ist used, the single pages contain only the new address
and running number and the size of the postscript file is modest.

OPTIONS
=======

   The Constructor new take a few options to customize the output:

a4

a5
     Generate A4 rsp. A5 output. Default is C5.

width number
height number
     Custom output size. Units are Postscript dots (72 dpi).

border number
     Set custom border size. Default is 20.

amt string
     Set the Postamt for the "Entgelt bezahlt" stamp. Default is `'44227
     Dortmund 52''.

stempel
     Add/Omit the "Entgelt bezahlt" stamp. Default is `true'.

infobrief
     Add/Omit the "Infobrief" banner. Default is false since the banner is
     not required.

numbering
     Add/Omit a running number on each envelope. Default is `true'.

AUTHOR
======

   Ulrich Pfeifer <`pfeifer@ls6.informatik.uni-dortmund.de'>

SEE ALSO
========

   perl(1).

Write Perl subroutines in other programming languages.
******************************************************

NAME
====

   Inline - Write Perl subroutines in other programming languages.

SYNOPSIS
========

     print "9 + 16 = ", add(9, 16), "\n";
     print "9 - 16 = ", subtract(9, 16), "\n";

     use Inline C => <<'END_OF_C_CODE';

     int add(int x, int y) {
       return x + y;
     }

     int subtract(int x, int y) {
       return x - y;
     }

     END_OF_C_CODE

DESCRIPTION
===========

   The Inline module allows you to put source code from other programming
languages directly "inline" in a Perl script or module. The code is
automatically compiled as needed, and then loaded for immediate access
from Perl.

   Inline saves you from the hassle of having to write and compile your
own glue code using facilities like XS or SWIG. Simply type the code where
you want it and run your Perl as normal. All the hairy details are handled
for you. The compilation and installation of your code chunks all happen
transparently; all you will notice is the delay of compilation.

   The Inline code only gets compiled the first time you run it (or
whenever it is modified) so you only take the performance hit once. Code
that is Inlined into distributed modules (like on the CPAN) will get
compiled when the module is installed, so the end user will never notice
the compilation time.

   Best of all, it works the same on both Unix and Microsoft Windows. See
Inline-Support, for support information.

Why Inline?
-----------

   Do you want to know "Why would I use other languages in Perl?" or "Why
should I use Inline to do it?"? I'll try to answer both.

Why would I use other languages in Perl?
     The most obvious reason is performance. For an interpreted language,
     Perl is very fast. Many people will say "Anything Perl can do, C can
     do faster". (They never mention the development time :-) Anyway, you
     may be able to remove a bottleneck in your Perl code by using another
     language, without having to write the entire program in that
     language. This keeps your overall development time down, because
     you're using Perl for all of the non-critical code.

     Another reason is to access functionality from existing API-s that
     use the language. Some of this code may only be available in binary
     form. But by creating small subroutines in the native language, you
     can "glue" existing libraries to your Perl. As a user of the CPAN,
     you know that code reuse is a good thing. So why throw away those
     Fortran libraries just yet?

     If you are using Inline with the C language, then you can access the
     full internals of Perl itself. This opens up the floodgates to both
     extreme power and peril.

     Maybe the best reason is "Because you want to!". Diversity keeps the
     world interesting. TMTOWTDI!

Why should I use Inline to do it?
     There are already two major facilities for extending Perl with C.
     They are XS and SWIG. Both are similar in their capabilities, at
     least as far as Perl is concerned. And both of them are quite
     difficult to learn compared to Inline.

     There is a big fat learning curve involved with setting up and using
     the XS environment. You need to get quite intimate with the following
     docs:

          * perlxs
          * perlxstut
          * perlapi
          * perlguts
          * perlmod
          * h2xs
          * xsubpp
          * ExtUtils::MakeMaker

     With Inline you can be up and running in minutes. There is a C
     Cookbook with lots of short but complete programs that you can extend
     to your real-life problems. No need to learn about the complicated
     build process going on in the background. You don't even need to
     compile the code yourself. Inline takes care of every last detail
     except writing the C code.

     Perl programmers cannot be bothered with silly things like compiling.
     "Tweak, Run, Tweak, Run" is our way of life. Inline does all the
     dirty work for you.

     Another advantage of Inline is that you can use directly it in a
     script. You can even use it in a Perl one-liner. With XS and SWIG,
     you always set up an entirely separate module. Even if you only have
     one or two functions. Inline makes easy things easy, and hard things
     possible. Just like Perl.

     Finally, Inline supports several programming languages (not just C
     and C++). As of this writing, Inline has support for C, C++, Python,
     and CPR. There are plans to add many more. See `"SUPPORTED
     LANGUAGES"' in this node below.

Using the Inline.pm Module
==========================

   Inline is a little bit different than most of the Perl modules that you
are used to. It doesn't import any functions into your namespace and it
doesn't have any object oriented methods. Its entire interface (with one
exception) is specified through the `'use Inline ...'' command.

   This section will explain all of the different ways to `use Inline'. If
you want to begin using Inline immediately, see Inline/C-Cookbook.

The Basics
----------

   The most basic form for using Inline is:

     use Inline X => "X source code";

   where 'X' is one of the supported Inline programming languages. The
second parameter specifies the source code that you want to bind to Perl.
The source code can be specified in many ways, but most commonly it's a
quoted string. A handy way to write the string is to use Perl's "here
document" style of quoting. Like this:

     use Inline X => <<'END_OF_X';

        X source code goes here.

     END_OF_X

   The source code can also be specified as a filename, a reference to a
subroutine that returns source code, or a reference to an array that
contains lines of source code.

   If you want to specify the source code in a Perl variable, remember
that `'use'' is a compile time directive, so you'll need to set that
variable in a BEGIN block, before the use.

     BEGIN {
         $X = "X source code";
     }
     use Inline X => $X;

   An alternative to doing this is to specify the source code at run time
using the 'Inline->bind()' method. (This is the one interface exception
mentioned above) The bind() method takes the same arguments as `'use
Inline ...''.

     use Inline;
     $X = "X source code";
     bind Inline X => $X;  # or Inline->bind(X => $X);

Alternate Syntaxes
------------------

   Instead of specifying the source code as a here-document string, you
may want to put it at the end of your script, after the `__END__'
statement. Then you can tell Inline to read it in from the DATA
filehandle, like this:

     use Inline C => 'DATA';

     print "9 + 16 = ", add(9, 16), "\n";
     print "9 - 16 = ", subtract(9, 16), "\n";

     __END__

     __C__

     int add(int x, int y) {
       return x + y;
     }

     int subtract(int x, int y) {
       return x - y;
     }

   This syntax makes use of the source-file keyword, `'DATA'', and a
special marker: `__C__'. 'C' is the programming language you are binding
to. Inline will read through the DATA filehandle and look for the special
marker. It will use everything up until the next marker, a POD command, or
the end of the file.

   NOTE: The 'DATA' keyword can be ommitted if there are no extra
parameters following it.

   This allows you to specify multiple Inline sections, possibly in
different programming languages, and POD documentation all in the same
place. If you want to specify AutoLoader subroutines as well, put them
before the first Inline marker. Here is another example:

     # The module Foo.pm
     package Foo;
     use AutoLoader;

     use Inline C;
     use Inline C;
     use Inline Python;

     1;

     __DATA__

     sub marine {
         # This is an autoloaded subroutine
     }

     __C__
     /* First C section */

     __C__
     /* Second C section */

     =head1

     Some POD doc.

     =cut

     __Python__
     """A Python Section"""

   With a module you need to use `__DATA__' instead of `__END__'. An
important thing to remember is that you need to have one "use Inline Foo
=> 'DATA'" for each "__Foo__" marker, and they must be in the same order.
This allows you to apply different configuration options to each section.

   NOTE: Versions of Inline prior to 0.30 suggested a syntax of:

     use Inline;
     Inline->import(C => <DATA>);

   to read source code from the DATA filehandle. This syntax has been
deprecated. It will still work, but you will get a warning if $^W is true.
It will eventually be removed from the syntax. Use the new syntax for
getting source code from the DATA filehandle. If you really need to access
Inline at run time, use the bind() method instead. This (supported) code
would do the same thing as the deprecated syntax:

     use Inline;
     Inline->bind(C => [<DATA>]);

   But the preferred practice is:

     use Inline C => 'DATA';

   or just:

     use Inline C;

Configuration Options
---------------------

   Inline trys to do the right thing as often as possible. But sometimes
you may need to override the default actions. This is easy to do. Simply
list the Inline configuration options after the regular Inline parameters.
All congiguration options are specified as (key, value) pairs.

     use Inline (C => 'DATA',
                 DIRECTORY => './inline_dir',
                 LIBS => '-lfoo',
                 INC => '-I/foo/include',
                 PREFIX => 'XXX_',
                 NOWARN => 1,
                );

   You can also specify the configuration options on a separate Inline
call like this:

     use Inline (C => Config =>
                 DIRECTORY => './inline_dir',
                 LIBS => '-lfoo',
                 INC => '-I/foo/include',
                 PREFIX => 'XXX_',
                 NOWARN => 1,
                );
     use Inline C => <<'END_OF_C_CODE';

   The special keyword `'Config'' tells Inline that this is a
configuration-only call. No source code will be compiled or bound to Perl.

   If you want to specify global configuration options that don't apply to
a particular language, just leave the language out of the call. Like this:

     use Inline Config => DIRECTORY => './inline_dir';

   The Config options are inherited and additive. You can use as many
Config calls as you want. And you can apply different options to different
code sections. When a source code section is passed in , Inline will apply
whichever options have been specified up to that point. Here is a complex
configuration example:

     use Inline (Config =>
                 DIRECTORY => './inline_dir',
                );
     use Inline (C => Config =>
                 LIBS => '-lglobal',
                );
     use Inline (C => 'DATA',         # First C Section
                 LIBS => ['-llocal1', '-llocal2'],
                );
     use Inline (Config =>
                 NOWARN => 1,
                );
     use Inline (Python => 'DATA',    # First Python Section
                 LIBS => '-lmypython1',
                );
     use Inline (C => 'DATA',         # Second C Section
                 LIBS => [undef, '-llocal3'],
                );

   The first Config applies to all subsequent calls. The second Config
applies to all subsequent C sections (but not `Python' sections). In the
first C section, the external libraries global, `local1' and `local2' are
used. (Most options allow either string or array ref forms, and do the
right thing.) The `Python' section does not use the global library, but
does use the same DIRECTORY, and has warnings turned off. The second C
section only uses the `local3' library. That's because a value of undef
resets the additive behaviour.

   The DIRECTORY and NOWARN options are generic Inline options. All other
options are language specific. To find out what the C options do, see
`Inline::C'.

   NOTE - Versions of Inline prior to 0.30, used a module called
`Inline::Config' to configure Inline. This module is no longer supported
and will no longer work with Inline. If you have it installed, remove it
from your system to avoid occasional warnings. Everything that you could
do with `Inline::Config' is still possible through the new configuration
syntax.

Playing 'with' Others
---------------------

   Inline has a special configuration syntax that tells it to get more
configuration options from other Perl modules. Here is an example:

     use Inline with => 'Event';

   This tells Inline to load the module `Event.pm' and ask it for
configuration information. Since Event has a C API of its own, it can pass
Inline all of the information it needs to be able to use Event C callbacks
seamlessly.

   That means that you don't need to specify the typemaps, shared
libraries, include files and other information required to get this to
work.

   You can specify a single module or a list of them. Like:

     use Inline with => qw(Event Foo Bar);

   Currently, Event is the only module that works with Inline.

Inline Shortcuts
----------------

   Inline lets you set many configuration options from the command line.
These options are called 'shortcuts'. They can be very handy, especially
when you only want to set the options temporarily, for say, debugging.

   For instance, to get some general information about your Inline code in
the script `Foo.pl', use the command:

     perl -MInline=INFO Foo.pl

   If you want to force your code to compile, even if its already done,
use:

     perl -MInline=FORCE Foo.pl

   If you want to do both, use:

     perl -MInline=INFO -MInline=FORCE Foo.pl

   or better yet:

     perl -MInline=INFO,FORCE Foo.pl

The Inline DIRECTORY
--------------------

   Inline needs a place to build your code and to install the results of
the build. It uses a single directory named `'.Inline/'' under normal
circumstances. If you create this directory in your home directory, the
current directory or in the directory where your program resides, Inline
will find and use it. You can also specify it in the environment variable
`PERL_INLINE_DIRECTORY' or directly in your program, by using the
DIRECTORY keyword option. If Inline cannot find the directory in any of
these places it will create a `'_Inline/'' directory in either your
current directory or the directory where your script resides.

   One of the key factors to using Inline successfully, is understanding
this directory. When developing code it is usually best to create this
directory (or let Inline do it) in your current directory. Remember that
there is nothing sacred about this directory except that it holds your
compiled code. Feel free to delete it at any time. Inline will simply
start from scratch and recompile your code on the next run. If you have
several programs that you want to force to recompile, just delete your
`'.Inline/'' directory.

   It is probably best to have a separate `'.Inline/'' directory for each
project that you are working on. You may want to keep stable code in the
<.Inline/> in your home directory. On multi-user systems, each user should
have their own `'.Inline/'' directories. It could be a security risk to
put the directory in a shared place like `/tmp/'.

Debugging Inline Errors
-----------------------

   All programmers make mistakes. When you make a mistake with Inline,
like writing bad C code, you'll get a big error report on your screen.
This report tells you where to look to do the debugging.

   When Inline needs to compile something it creates a subdirectory under
your `DIRECTORY/build/' directory. This is where it writes all the
components it needs to build your extension. Things like XS files,
Makefiles and output log files.

   If everything goes OK, Inline will delete this subdirectory. If there
is an error, Inline will leave the directory intact and print its
location. The idea is that you are supposed to go into that directory and
figure out what happened.

   As a convenience, Inline copies your latest error directory to
`DIRECTORY/errors' and strips all of the MD5 hash codes out of the names.
More debugging improvements are coming in future releases.

   Read the doc for your particular Inline language module for more
information.

The 'config' Registry File
--------------------------

   Inline keeps a cached file of all of the Inline Language Support
Module's meta data in a file called config. This file can be found in your
DIRECTORY directory. If the file does not exist, Inline creates a new one.
It will search your system for any module beginning with `Inline::'. It
will then call that module's register() method to get useful information
for future invocations.

   Whenever you add a new ILSM, you should delete this file so that Inline
will auto-discover your newly installed language module.

Configuration Options
=====================

   This section lists all of the generic Inline configuration options. For
language specific configuration, see the doc for that language.

DIRECTORY
---------

   The DIRECTORY config option is the directory that Inline uses to both
build and install an extension.

   Normally Inline will search in a bunch of known places for a directory
called `'.Inline/''. Failing that, it will create a directory called
`'_Inline/''

   If you want to specify your own directory, use this configuration
option.

   Note that you must create the DIRECTORY directory yourself. Inline will
not do it for you.

WITH
----

   WITH can also be used as a configuration option instead of using the
special 'with' syntax. Do this if you want to use different sections of
Inline code with different modules. (Probably a very rare usage)

     use Event;
     use Inline C => DATA => WITH => 'Event';

   Modules specified using the config form of WITH will not be
automatically required. You must use them yourself.

GLOBAL_LOAD
-----------

   This option is for compiled languages only. It tells Inline to tell
DynaLoader to load an object file in such a way that its symbols can be
dynamically resolved by other object files. May not work on all platforms.

UNTAINT
-------

   You must use this option  whenever you use Perl's -T switch, for taint
checking. This option tells Inline to blindly untaint all tainted
variables. It also turns on SAFEMODE by default.

SAFEMODE
--------

   Perform extra safety checking, in an attempt to thwart malicious code.
This option cannot guarantee security, but it does turn on all the
currently implemented checks.

   There is a slight startup penalty by using SAFEMODE. Also, using
UNTAINT automatically turns this option on. If you need your code to start
faster under -T (taint) checking, you'll need to turn this option off
manually. Only do this if you are not worried about security risks.

NOWARN
------

     use Inline C => DATA => NOWARN => 1;

   This option tells Inline to turn off any warnings.

   It is *NOT* yet implemented.

Inline Configuration Shortcuts
------------------------------

   This is a list of all the shorcut configuration options  currently
available for Inline. Specify them from the command line when running
Inline scripts.

     perl -MInline=NOCLEAN inline_script.pl

   or

     perl -MInline=Info,force,NoClean inline_script.pl

   You can specify multiple shortcuts separated by commas. They are not
case sensitive.

CLEAN
     Tells Inline to remove any build directories that may be lying around
     in your build area. Normally these directories get removed
     immediately after a successful build. Exceptions are when the build
     fails, or when you use the NOCLEAN or REPORTBUG options.

FORCE
     Forces the code to be recompiled, even if everything is up to date.

GLOBAL
     Turns on the GLOBAL_LOAD option.

INFO
     This is a very useful option when you want to know what's going on
     under the hood. It tells Inline to print helpful information to
     `STDERR'. Among the things that get printed is a list of which Inline
     functions were successfully bound to Perl.

NOCLEAN
     Tells Inline to leave the build files after compiling.

REPORTBUG
     Puts Inline into 'REPORTBUG' mode, which does special processing when
     you want to report a bug. REPORTBUG also automatically forces a
     build, and doesn't clean up afterwards. This is so that you can tar
     and mail the build directory to me. REPORTBUG will print exact
     instructions on what to do. Please read and follow them carefully.

     NOTE: REPORTBUG informs you to use the tar command. If your system
     does not have tar, please use the equivalent zip command.

SAFE
     Turns SAFEMODE on. UNTAINT will turn this on automatically. While
     this mode performs extra security checking, it does not guarantee
     safety.

SITE_INSTALL
     Says that compiled code should be installed in the Perl
     installation's "`site_perl'" directory. Use this to permanently
     install an Inlined module.

     This is the one shortcut that is not normally used from the command
     line. You put a line like this at the top of a `'test.pl'':

          use Inline SITE_INSTALL;

     This causes 'make test' to put the compiled results in the right
     place.

UNSAFE
     Turns SAFEMODE off. Use this in combination with UNTAINT for slightly
     faster startup time under -T. Only use this if you are sure the
     environment is safe.

UNTAINT
     Turn the UNTAINT option on. Used with -T switch.

VERSION
     Tells Inline to report it's release version. Program will exit
     immediately after version is printed.

Writing Modules with Inline
===========================

   Writing CPAN modules that use other programming languages is easy with
Inline. Let's say that you wanted to write a module called `Math::Simple'.
Start by using the following command:

     h2xs -AXn Math::Simple

   This will generate a bunch of files that form a skeleton of what you
need for a distributable module. Next, modify the `Simple.pm' file to look
like this:

     package Math::Simple;

     use strict;
     use vars qw($VERSION @ISA @EXPORT_OK);
     require Exporter;
     @ISA = qw(Exporter);
     @EXPORT_OK = qw(add subtract);
     BEGIN {
         $VERSION = '0.01';
     }

     use Inline C => 'DATA';

     1;

     __DATA__

     =pod

     =cut

     __C__
     int add(int x, int y) {
       return x + y;
     }

     int subtract(int x, int y) {
       return x - y;
     }

   Finally, you need to add the following line to the top of your test.pl
file:

     use Inline SITE_INSTALL;

   When the person installing `Math::Simple' does a "make test", the
Inline module will compile the Inlined code and place the executable code
into the `./blib' directory. Then when a "make install" is done, the
module will be copied into Perl's `$Config{installsitearch}' directory
(which is where an installed module should go).

   Now all you need to do is:

     perl Makefile.PL
     make dist

   That will generate the file `Math-Simple-0.01.tar.gz' which is a
distributable package.

How Inline Works
================

   In reality, Inline just automates everything you would need to do if
you were going to do it by hand (using XS, etc).

   Inline performs the following steps:

  1. Receive the Source Code Inline gets the source code from your script
     or module with a statements like the following:

          use Inline C => "Source-Code";

     or

          use Inline;
          bind Inline C => "Source-Code";

     where C is the programming language of the source code, and
     `Source-Code' is a string (most easily represented by using the "Here
     Document" quoting style; see `"SYNOPSIS"' in this node above), a file
     name, an array reference, or a reference to a subroutine.

     Since Inline is coded in a "use" statement, everything is done during
     Perl's compile time. If anything needs to be done that will affect
     the `Source-Code' string, it needs to be done in a BEGIN block that
     is before the "`use Inline ...'" statement. If you really need to
     specify code to Inline at runtime, you can use the bind() method.

     Source code that is stowed in the 'DATA' section of your code, is
     read in by an `INIT' subroutine in Inline. That's because the DATA
     filehandle is not available at compile time.

  2. Check if the Source Code has been Compiled Inline only needs to
     compile the source code if it has not yet been compiled. It
     accomplishes this seemingly magical task in an extremely simple and
     straightforward manner. It runs the source text through the
     Digest::MD5 module to produce a 128-bit "fingerprint" which is
     virtually unique. The fingerprint (in hex) is *mangled* with the
     current package name (and the script name, if the package is "main")
     along with the name of the programming language, to form a unique
     name for the executable module. For instance, the C code from
     `examples/example001.pl' (see `"Examples In C"' in this node) would
     mangle into:

          main_C_example001_pl_3a9a7ba88a8fb10714be625de5e701f1.so

     If an executable with that name already exists, then proceed to step
     8. (No compilation is necessary)

  3. Find a Place to Build and Install At this point Inline knows it needs
     to compile the source code. The first thing to figure out is where to
     create the great big mess associated with compilation, and where to
     put the object when it's done.

     By default Inline will try to build and install under the first place
     that meets one of the following conditions:

          A) The DIRECTORY= config option; if specified
          B) The PERL_INLINE_DIRECTORY environment variable; if set
          C) .Inline/ (in current directory); if exists and $PWD != $HOME
          D) bin/.Inline/ (in directory of your script); if exists
          E) ~/.Inline/; if exists
          F) ./_Inline/; if exists
          G) bin/_Inline; if exists
          H) Create ./_Inline/; if possible
          I) Create bin/_Inline/; if possible

     Failing that, Inline will croak. This is rare and easily remedied by
     just making a directory that Inline will use;

     If the SITE_INSTALL option is in effect, then Inline will only use
     `./_Inline/' to build in, and the `$Config{installsitearch}'
     directory to install the executable in. This option is intended to be
     used in modules that are to be distributed on the CPAN, so that they
     get installed in the proper place.

  4. Parse the Source for Semantic Cues Inline uses the module
     Parse::RecDescent to parse through your chunks of source code and
     look for things that it can create run-time bindings to. For
     instance, in C it looks for all of the function definitions and
     breaks them down into names and data types. These elements are used
     to correctly bind the C function to a Perl subroutine.

  5. Create the Build Environment Now Inline can take all of the gathered
     information and create an environment to build your source code into
     an executable. Without going into all the details, it just creates
     the appropriate directories, creates the appropriate source files
     including an XS file and a Makefile.PL.

  6. Compile the Code and Install the Executable The planets are in
     alignment. Now for the easy part. Inline just does what you would do
     to install a module. "`perl Makefile.PL && make && make test && make
     install'". If something goes awry, Inline will croak with a message
     indicating where to look for more info.

  7. Tidy Up By default, Inline will remove all of the mess created by the
     build process, assuming that everything worked. If the compile fails,
     Inline will leave everything intact, so that you can debug your
     errors. Setting the NOCLEAN shortcut option will also stop Inline
     from cleaning up.

  8. DynaLoad the Executable Inline uses the `DynaLoader::bootstrap'
     method to pull your external module into Perl space. Now you can call
     all of your external functions like Perl subroutines.

SUPPORTED LANGUAGES
===================

   This section has been moved to Inline-Support.

SUPPORTED PLATFORMS
===================

   This section has been moved to Inline-Support.

SEE ALSO
========

   For information about using Inline with C see Inline/C.

   For sample programs using Inline with C see Inline/C-Cookbook.

   For information on supported languages and platforms see
Inline-Support.

   For information on writing your own Inline Language Support Module, see
Inline-API.

   Inline's mailing list is inline@perl.org

   To subscribe, send email to inline-subscribe@perl.org

BUGS AND DEFICIENCIES
=====================

   When reporting a bug, please do the following:

     - Put "use Inline REPORTBUG;" at the top of your code, or
       use the command line option "perl -MInline=REPORTBUG ...".
     - Run your code.
     - Follow the printed directions.

   Here are some things to watch out for:

  1. While Inline does attempt to clean up after itself, there is
     currently no functionality to remove a shared object when a new
     version is compiled. This shouldn't be hard to do, but I want to
     think about it a little more.

  2. If you use function names that happen to be used internally by Perl,
     you will get a load error at run time. There is currently no
     functionality to prevent this or to warn you. For now, a list of
     Perl's internal symbols is packaged in the Inline module distribution
     under the filename `'symbols.perl''. Avoid using these in your code.

AUTHOR
======

   Brian Ingerson <INGY@cpan.org>

   Neil Watkiss <NEILW@cpan.org> is the author of `Inline::CPP' and
`Inline::Python'. He also provided assistance for the major reworking in
version 0.30. It is largely because of Neil, that Inline is evolving at a
rapid pace.

COPYRIGHT
=========

   Copyright (c) 2000 - 2001, Brian Ingerson.

   All Rights Reserved.  This module is free software. It may be used,
redistributed and/or modified under the terms of the Perl Artistic License.

   See http://www.perl.com/perl/misc/Artistic.html

API - How to bind a programming language to Perl using Inline.pm
****************************************************************

NAME
====

   Inline-API - How to bind a programming language to Perl using Inline.pm

SYNOPSIS
========

     #!/usr/bin/perl

     say_it('foo');  # Use Foo++ to print "Hello, Foo"

     use Inline Foo => <<'EOFOO';

       /FOO  This is a function written in Foo++  OOF/

       deefoon foonkshun say_it
         < fooprint "Hello,", arrrg(0) >

     EOFOO

DESCRIPTION
===========

   So you think Inline C is pretty cool, but what you really need is for
Perl to work with the brand new programming language "Foo++". Well you're
in luck. `Inline.pm' has support for adding your own Inline Language
Support Module (*ILSM*), like `Inline::Foo'.

   Inline has always been intended to work with lots of different
programming languages. Many of the details can be shared between
implementations, so that `Inline::Java' has a similar interface to
`Inline::Fortran'. All of the common code is in `Inline.pm'.

   Language specific modules like `Inline::Python' are subclasses of
`Inline.pm'. They can inherit as much of the common behaviour as they
want, and provide specific behaviour of their own. This usually comes in
the form of Configuration Options and language specific compilation.

   The Inline C support is probably the best boilerplate to copy from.
Since version 0.30 all C support was isolated into the module `Inline::C'
and the parsing grammar is further broken out into `Inline::C::grammar'.
All of these components come with the Inline distribution.

   This POD gives you all the details you need for implementing an ILSM.
For further assistance, contact inline@perl.org See `"SEE ALSO"' in this
node below.

A Skeleton
==========

   For the remainder of this tutorial, let's assume we're writing an ILSM
for the ficticious language `Foo++'. We'll call it `Inline::Foo'. Here is
the skeleton Perl code you'll need to implement it.

     package Inline::Foo;

     use strict;
     require Inline;
     require Inline::Foo::grammar;
     use Parse::RecDescent;
     use Config;
     use Carp;

     $Inline::Foo::VERSION = '0.05';
     @Inline::Foo::ISA = qw(Inline);

     #===========================================================
     # Register Foo++ as an Inline Language Support Module (ILSM)
     #===========================================================
     sub register {
         return {
                 language => 'Foo',
                 aliases => ['Foo++', 'F++'],
                 type => 'compiled',
                 suffix => $Config{so},
                };
     }

     #==================================
     # Validate the Foo++ Config Options
     #==================================
     sub validate {
         my $o = shift; # This is the Inline object

         $o->{Foo} = {};
         while (@_) {
         my ($key, $value) = (shift, shift);
         if ($key eq 'BAR') {
             $o->{Foo}{BAR} = $value;  # Store config value in object
             next;
         }
         if ($key eq 'BAZ') {
             $o->{Foo}{BAZ} = $value;
             next;
         }
         croak "'$key' is not a valid config option for Inline::Foo\n";
         }
     }

     #=============================
     # Parse and compile Foo++ code
     #=============================
     sub build {
         my $o = shift;
         $o->parse;
         $o->compile;
     }

     #======================================
     # Only needed for interpreted languages
     #======================================
     sub load {
         my $o = shift;
     }

     #============================================
     # Return a small report about the Foo++ code.
     #============================================
     sub info {
         my $o = shift;
         my $text = <<'END';
     This is a small report about the Foo++ code. Perhaps it contains
     information about the functions the parser found which will be
     bound to Perl. It will get included in the text produced by the
     Inline 'INFO' command.
     END
         return $text;
     }

   Except for load(), the subroutines in this code are mandatory for an
ILSM. What they do is described below. A few things to note:

  1. `Inline::Foo' must be a subclass of Inline. This is accomplished with:

          @Inline::Foo::ISA = qw(Inline);

  2. The line '`require Inline;'' is not necessary. But it is there to
     remind you not to say '`use Inline;''. This will not work.

  3. Remember, it is not valid for a user to say:

          use Inline::Foo;

     `Inline.pm' will detect such usage for you in its import method,
     which is automatically inherited since `Inline::Foo' is a subclass.

  4. It is not necessary to implement your parsing with Parse::RecDescent.
     But I recommend it. :-)

The Inline API
==============

   This section is a more formal specification of what functionality
you'll need to provide to implement an ILSM.

   When Inline determines that some `Foo++' code needs to be compiled it
will automatically load your module. It will then call various subroutines
which you need to supply. We'll call these subroutines "callbacks".

   You will need to provide the following 5 callback subroutines.

The register() Callback
-----------------------

   This subroutine receives no arguments. It returns a reference to a hash
of ILSM meta-data. Inline calls this routine only when it is trying to
detect new ILSM-s that have been installed on a given system. Here is an
example of the has ref you would return for Foo++:

     {
      language => 'Foo',
      aliases => ['Foo++', 'F++'],
      type => 'compiled',
     };

   The meta-data items have the following meanings:

language
     This is the proper name of the language. It is usually implemented as
     `Inline::X' for a given language 'X'.

aliases
     This is a reference to an array of language name aliases. The proper
     name of a language can only contain word characters. [A-Za-z0-9_] An
     alias can contain any characters except whitespace and quotes. This
     is useful for names like 'C++' and 'C#'.

type
     Must be set to 'compiled' or 'interpreted'. Indicates the category of
     the language.

suffix
     This is the file extension for the cached object that will be
     created. For 'compiled' languages, it will probably be 'so' or 'dll'.
     The appropriate value is in Config.pm.

     For interpreted languages, this value can be whatever you want.
     Python uses `pydat'.

The validate() Callback
-----------------------

   This routine gets passed all configuration options that were not
already handled by the base Inline module. The options are passed as
key/value pairs. It is up to you to validate each option and store its
value in the Inline object (which is also passed in). If a particular
option is invalid, you should croak with an appropriate error message.

The build() Callback
--------------------

   This subroutine is responsible for doing the parsing and compilation of
the Foo++ source code. The Inline is passed as the only argument. All
pertinent information will be stored in this object. `build()' is required
to create a shared object of a specific name, or to croak with an
appropriate error message.

   This is the meat of your ILSM. Since it will most likely be quite
complicated, it is probably best that you study an existing ILSM like
`Inline::C'.

The load() Callback
-------------------

   This method only needs to be provided for interpreted languages. It's
responsibility is to start the interpreter.

   For compiled languages, the load routine from `Inline.pm' is called
which uses DynaLoader to load the shared object or DLL.

The info() Callback
-------------------

   This method is called when the user makes use of the INFO shortcut. You
should return a string containing a small report about the Inlined code.

The Inline Object
=================

   `Inline.pm' creates a hash based Perl object for each section of
Inlined source code it receives. This object contains lots of information
about the code, the environment, and the configuration options used. You
are free to store any additional information in the object.

   To prevent naming clashes with future version of Inline you use a
subhash under the key 'Foo' (The name of your language). This is the
convention.

   This section will describe all of the Inline object attributes.

The code Attribute
------------------

   This the actual source code passed in by the user. It is stored as one
long string.

The language Attribute
----------------------

   The proper name of the language being used.

The language_id Attribute
-------------------------

   The language name specified by the user. Could be 'Foo++' instead of
'Foo'.

The module Attribute
--------------------

   This is the shared object's file name.

The modfname Attribute
----------------------

   This is the shared object's file name.

The modpname Attribute
----------------------

   This is the shared object's installation path extension.

The version Attribute
---------------------

   The version of `Inline.pm' being used.

The pkg Attribute
-----------------

   The Perl package from which this invocation pf Inline was called.

The parser Attribute
--------------------

   This is the place where the Parse::RecDescent parser object is normally
stored.

The install_lib Attribute
-------------------------

   This is the directory to write the shared object into.

The build_dir Attribute
-----------------------

   This is the directory under which you should write all of your build
related files.

The script Attribute
--------------------

   This is the name of the script that invoked Inline.

The location Attribute
----------------------

   This is the full path name of the executable object in question.

The suffix Attribute
--------------------

   This is the shared library extension name. (Usually 'so' or 'dll').

The mod_exists Attribute
------------------------

   This is a flag indicating whether or not this module has already been
compiled. (1 for true and 0 for false)

The config Attribute
--------------------

   This is where all of the non-language specific configuration options
are stored.

FORCE_BUILD
     Flag indicating whether or not Inline should call the
     `Inline::Foo::build()' method even if the code has already been
     compiled. (0 or 1)

PRINT_VERSION
     Flag indicating whether or not Inline should print a version message.
     (0 or 1)

CLEAN_AFTER_BUILD
     Flag indicating whether or not Inline should delete the contents of
     the build directory after a successful compilation (0 or 1)

PRINT_INFO
     Flag indicating whether or not Inline should print an informational
     report about the code being compiled. (0 or 1)

DIRECTORY
     The name of the base directory for building and installing Inline
     executables.

REPORTBUG
     Flag indicating whether or not Inline is in REPORTBUG mode. (0 or 1)

CLEAN_BUILD_AREA
     Flag indicating whether or not Inline should perform a special
     cleanup function on the BLIB directory. (0 or 1)

SITE_INSTALL
     Flag indicating whether or not the Inline code is meant to be part of
     a permanent module installation. (0 or 1)

WITH
     A reference to an array of module names that Inline should poll for
     configuration hints.

The Inline Namespace
====================

   `Inline.pm' has been set up so that anyone can write their own language
support modules. It further allows anyone to write a different
implementation of an existing Inline language, like C for instance. You
can distribute that module on the CPAN.

   If you have plans to implement and distribute an Inline module, I would
ask that you please work with the Inline community. We can be reached at
the Inline mailing list: inline@perl.org (Send mail to
inline-subscribe@perl.org to subscribe). Here you should find the advice
and assistance needed to make your module a success.

   The Inline community will decide if your implementation of COBOL will
be distributed as the official `Inline::COBOL' or should use an alternate
namespace. In matters of dispute, I (Brian Ingerson) retain final
authority. (and I hope not to need use of it :-) Actually modules@perl.org
retains the *final* authority.

   But even if you want to work alone, you are free and welcome to write
and distribute Inline language support modules on CPAN. You'll just need
to distribute them under a different package name.

SEE ALSO
========

   For generic information about Inline, see Inline.

   For information about using Inline with C see Inline/C.

   For information on supported languages and platforms see
Inline-Support.

   Inline's mailing list is inline@perl.org

   To subscribe, send email to inline-subscribe@perl.org

AUTHOR
======

   Brian Ingerson <INGY@cpan.org>

COPYRIGHT
=========

   Copyright (c) 2001, Brian Ingerson. All Rights Reserved.  This module
is free software. It may be used, redistributed and/or modified under the
terms of the Perl Artistic License.

   See http://www.perl.com/perl/misc/Artistic.html

Support - Support Information for Inline.pm and related modules.
****************************************************************

NAME
====

   Inline-Support - Support Information for Inline.pm and related modules.

DESCRIPTION
===========

   This document contains all of the latest support information for
`Inline.pm' and the recognized Inline Language Support Modules (ILSMs)
available on CPAN.

SUPPORTED LANGUAGES
===================

   The most important language that Inline supports is C. That is because
Perl itself is written in C. By giving a your Perl scripts access to C,
you in effect give them access to the entire glorious internals of Perl.
(Caveat scriptor :-)

   As of this writing, Inline also supports:

     - C++
     - Python
     - CPR

   Projects that I would most like to see happen in the year 2001 are:

     - Java
     - Fortran
     - Ruby
     - Bash

   Note: Since many C compilers allow the use of assembly code within C,
you may want to consider Assembly Language as supported. Ready to start
scripting out new device drivers?

SUPPORTED PLATFORMS
===================

   `Inline::C' should work anywhere that CPAN extension modules (those
that use XS) can be installed, using the typical install format of:

     perl Makefile.PL
     make
     make test
     make install

   It has been tested on many Unix variants and Windows NT.

   NOTE: `Inline::C' requires Perl 5.005 or higher because
Parse::RecDescent requires it. (Something to do with the qr operator)

   Inline has been tested on the following platforms:

     V#   OS      OS V#   Perl V# Human              Email
     0.20 FreeBSD 3.4     5.00503 Timothy A Gregory  tgregory@tarjema.com
     0.20 FreeBSD 4.0     5.00503 Timothy A Gregory  tgregory@tarjema.com
     0.20 FreeBSD 4.0     5.6     Timothy A Gregory  tgregory@tarjema.com
     0.20 Linux   2.0.36  5.00503 Prakasa Bellam     pbellam@cobaltgroup.com
     0.20 HPUX    B.10.20 5.00503 Jamie Shaffer      jshaffer@chronology.com
     0.20 SunOS   5.6     5.6.0   Jamie Shaffer      jshaffer@chronology.com
     0.20 SunOS   5.5.1   5.6.0   Jamie Shaffer      jshaffer@chronology.com
     0.22 OpenBSD 2.7     5.6.0   Jeremy Devenport   jeremy@weezel.com
     0.22 FreeBSD 3.1     5.00503 Doug Beaver        dougb@scalar.org
     0.25 Linux   2.2.13  5.00503 Brian Ingerson     ingy@cpan.org
     0.25 Linux   2.2.13  5.6     Brian Ingerson     ingy@cpan.org
     0.25 WinNT   4.0 sp6 5.00503 Brian Ingerson     ingy@cpan.org
     0.26 Cygwin  1.1.1   5.6.0   Leo Schalkwyk      L.Schalkwyk@iop.kcl.ac.uk
     0.26 AIX     4.3.3   5.00502 Norbert E. Gruener nog@MPA-Garching.MPG.DE
     0.26 BeOS    5.03Pro 5.00503 Daniel J. Berger   djberge@uswest.com

   The Microsoft tests deserve a little more explanation. I used the
following:

     Windows NT 4.0 (service pack 6)
     Perl 5.005_03 (ActiveState build 522)
     MS Visual C++ 6.0
     The "nmake" make utility (distributed w/ Visual C++)

   `Inline::C' pulls all of its base configuration (including which make
utility to use) from Config.pm. Since your MSWin32 version of Perl
probably came from ActiveState (as a binary distribution) the Config.pm
will indicate that `nmake' is the system's make utility. That is because
ActiveState uses Visual C++ to compile Perl.

   To install `Inline.pm' (or any other CPAN module) on MSWin32 w/ Visual
C++, use these:

     perl Makefile.PL
     nmake
     nmake test
     nmake install

   The "Cygwin" test was done on a Windows 98 machine using the Cygwin
Unix/Win32 porting layer software from Cygnus. The `perl' binary on this
machine was also compiled using the Cygwin tool set (`gcc'). This software
is freely available from http://sources.redhat.com/cygwin/

   If Inline works on your platform, you can email me the info above. If
it doesn't work, let me know as well and I'll see what can be done.

SEE ALSO
========

   For general information about Inline see Inline.

   For information about using Inline with C see Inline/C.

   For sample programs using Inline with C see Inline/C-Cookbook.

   For information on writing your own Inline Language Support Module, see
Inline-API.

   Inline's mailing list is inline@perl.org

   To subscribe, send email to inline-subscribe@perl.org

AUTHOR
======

   Brian Ingerson <INGY@cpan.org>

COPYRIGHT
=========

   Copyright (c) 2001, Brian Ingerson.

   All Rights Reserved.  This module is free software. It may be used,
redistributed and/or modified under the terms of the Perl Artistic License.

   See http://www.perl.com/perl/misc/Artistic.html

Write Perl Subroutines in C
***************************

NAME
====

   Inline::C - Write Perl Subroutines in C

DESCRIPTION
===========

   `Inline::C' is a module that allows you to write Perl subroutines in C.
Since version 0.30 the Inline module supports multiple programming
languages and each language has its own support module. This document
describes how to use Inline with the C programming language. It also goes
a bit into Perl C internals.

   If you want to start working with programming examples right away,
check out Inline/C-Cookbook. For more
information on Inline in general, see Inline.

Usage
=====

   You never actually use `Inline::C' directly. It is just a support
module for using `Inline.pm' with C. So the usage is always:

     use Inline C => ...;

   or

     bind Inline C => ...;

Function Definitions
====================

   The Inline grammar for C recognizes certain function definitions (or
signatures) in your C code. If a signature is recognized by Inline, then
it will be available in Perl-space. That is, Inline will generate the
"glue" necessary to call that function as if it were a Perl subroutine. If
the signature is not recognized, Inline will simply ignore it, with no
complaints. It will not be available from Perl-space, although it *will*
be available from C-space.

   Inline looks for ANSI/prototype style function definitions. They must
be of the form:

     return-type function-name ( type-name-pairs ) { ... }

   They also may only use the types: int, long, double, `char*', and
`SV*'. A return type of void may also be used. The following are examples
of valid function definitions.

     int Foo(double num, char* str) {
     void Foo(double num, char* str) {
     SV* Foo() {
     void Foo(SV*, ...) {
     long Foo(int i, int j, ...) {

   The following definitions would not be recognized:

     Foo(int i) {               # no return type
     unsigned int Foo(int i) {  # 'unsigned int' not recognized
     int Foo(num, str) double num; char* str; {
     void Foo(void) {           # void only valid for return type

   Notice that Inline only looks for function *definitions*, not function
*prototypes*. Definitions are the syntax directly preceeding a function
body. Also Inline does not scan external files, like headers. Only the
code passed to Inline is used to create bindings; although other libraries
can linked in, and called from C-space.

C Configuration Options
=======================

   For information on how to specify Inline configuration options, see
Inline. This section describes each of the configuration
options available for C. Most of the options correspond either to
MakeMaker or XS options of the same name. See ExtUtils/MakeMaker,
and Perlxs (perl.info).

AUTO_INCLUDE
------------

   Specifies extra statements to automatically included. They will be
added onto the defaults. A newline char will be automatically added.

     use C => Config => AUTO_INCLUDE => '#include "yourheader.h"';

BOOT
----

   Specifies C code to be executed in the XS BOOT section. Corresponds to
the XS parameter.

CC
--

   Specify which compiler to use.

CCFLAGS
-------

   Specify extra compiler flags.

INC
---

   Specifies an include path to use. Corresponds to the MakeMaker
parameter.

     use C => Config => INC => '-I/inc/path';

LD
--

   Specify which linker to use.

LDDLFLAGS
---------

   Specify which linker flags to use.

   NOTE: These flags will completely override the existing flags, instead
of just adding to them. So if you need to use those too, you must
respecify them here.

LIBS
----

   Specifies external libraries that should be linked into your code.
Corresponds to the MakeMaker parameter.

     use C => Config => LIBS => '-lyourlib';

   or

     use C => Config => LIBS => '-L/your/path -lyourlib';

MAKE
----

   Specify the name of the 'make' utility to use.

MYEXTLIB
--------

   Specifies a user compiled object that should be linked in. Corresponds
to the MakeMaker parameter.

     use C => Config => MYEXTLIB => '/your/path/yourmodule.so';

PREFIX
------

   Specifies a prefix that will be automatically stripped from C functions
when they are bound to Perl. Useful for creating wrappers for shared
library API-s, and binding to the original names in Perl. Also useful when
names conflict with Perl internals. Corresponds to the XS parameter.

     use C => Config => PREFIX => 'ZLIB_';

TYPEMAPS
--------

   Specifies extra typemap files to use. These types will modify the
behaviour of the C parsing. Corresponds to the MakeMaker parameter.

     use C => Config => TYPEMAPS => '/your/path/typemap';

C-Perl Bindings
===============

   This section describes how the Perl variables get mapped to C variables
and back again.

   First, you need to know how Perl passes arguments back and forth to
subroutines. Basically it uses a stack (also known as the Stack). When a
sub is called, all of the parenthesized arguments get expanded into a list
of scalars and pushed onto the Stack. The subroutine then pops all of its
parameters off of the Stack. When the sub is done, it pushes all of its
return values back onto the Stack.

   The Stack is an array of scalars known internally as SV's. The Stack is
actually an array of *pointers to SV* or `SV*'; therefore every element of
the Stack is natively a `SV*'. For *FMTYEWTK* about this, read `perldoc
perlguts'.

   So back to variable mapping. XS uses a thing known as "typemaps" to
turn each `SV*' into a C type and back again. This is done through various
XS macro calls, casts and the Perl API. See `perldoc perlapi'. XS allows
you to define your own typemaps as well for fancier non-standard types
such as `typedef'-ed structs.

   Inline uses the default Perl typemap file for its default types. This
file is called `/usr/local/lib/perl5/5.6.1/ExtUtils/typemap', or something
similar, depending on your Perl installation. It has definitions for over
40 types, which are automatically used by Inline. (You should probably
browse this file at least once, just to get an idea of the possibilities.)

   Inline parses your code for these types and generates the XS code to
map them. The most commonly used types are:

     - int
     - long
     - double
     - char*
     - void
     - SV*

   If you need to deal with a type that is not in the defaults, just use
the generic `SV*' type in the function definition. Then inside your code,
do the mapping yourself. Alternatively, you can create your own typemap
files and specify them using the TYPEMAPS configuration option.

   A return type of void has a special meaning to Inline. It means that
you plan to push the values back onto the Stack yourself. This is what you
need to do to return a list of values. If you really don't want to return
anything (the traditional meaning of void) then simply don't push anything
back.

   If ellipsis or ... is used at the end of an argument list, it means
that any number of `SV*'s may follow. Again you will need to pop the
values off of the Stack yourself.

   See `"Examples"' in this node below.

The Inline Stack Macros
=======================

   When you write Inline C, the following lines are automatically
prepended to your code (by default):

     #include "EXTERN.h"
     #include "perl.h"
     #include "XSUB.h"
     #include "INLINE.h"

   The file `INLINE.h' defines a set of macros that are useful for
handling the Perl Stack from your C functions.

Inline_Stack_Vars
     You'll need to use this one, if you want to use the others. It sets
     up a few local variables: `sp', items, `ax' and mark, for use by the
     other macros. It's not important to know what they do, but I mention
     them to avoid possible name conflicts.

     NOTE: Since this macro declares variables, you'll need to put it with
     your other variable declarations at the top of your function. It must
     come before any executable statements and before any other
     `Inline_Stack' macros.

Inline_Stack_Items
     Returns the number of arguments passed in on the Stack.

Inline_Stack_Item(i)
     Refers to a particular `SV*' in the Stack, where i is an index number
     starting from zero. Can be used to get or set the value.

Inline_Stack_Reset
     Use this before pushing anything back onto the Stack. It resets the
     internal Stack pointer to the beginning of the Stack.

Inline_Stack_Push(sv)
     Push a return value back onto the Stack. The value must be of type
     `SV*'.

Inline_Stack_Done
     After you have pushed all of your return values, you must call this
     macro.

Inline_Stack_Return(n)
     Return n items on the Stack.

Inline_Stack_Void
     A special macro to indicate that you really don't want to return
     anything. Same as:

          Inline_Stack_Return(0);

   Each of these macros is available in 3 different styles to suit your
coding tastes. The following macros are equivalent.

     Inline_Stack_Vars
     inline_stack_vars
     INLINE_STACK_VARS

   All of this functionality is available through XS macro calls as well.
So why duplicate the functionality? There are a few reasons why I decided
to offer this set of macros. First, as a convenient way to access the
Stack. Second, for consistent, self documenting, non-cryptic coding.
Third, for future compatibility. It occured to me that if a lot of people
started using XS macros for their C code, the interface might break under
Perl6. By using this set, hopefully I will be able to insure future
compatibility of argument handling.

   Of course, if you use the rest of the Perl API, your code will most
likely break under Perl6. So this is not a 100% guarantee. But since
argument handling is the most common interface you're likely to use, it
seemed like a wise thinng to do.

Writing C Subroutines
=====================

   The definitions of your C functions will fall into one of the following
four categories. For each category there are special considerations.

  1.      int Foo(int arg1, char* arg2, SV* arg3) {

     This is the simplest case. You have a non void return type and a
     fixed length argument list. You don't need to worry about much. All
     the conversions will happen automatically.

  2.      void Foo(int arg1, char* arg2, SV* arg3) {

     In this category you have a void return type. This means that either
     you want to return nothing, or that you want to return a list. In the
     latter case you'll need to push values onto the Stack yourself. There
     are a few Inline macros that make this easy. Code something like this:

          int i, max; SV* my_sv[10];
          Inline_Stack_Vars;
          Inline_Stack_Reset;
          for (i = 0; i < max; i++)
            Inline_Stack_Push(my_sv[i]);
          Inline_Stack_Done;

     After resetting the Stack pointer, this code pushes a series of
     return values. At the end it uses Inline_Stack_Done to mark the end
     of the return stack.

     If you really want to return nothing, then don't use the
     `Inline_Stack_' macros. If you must use them, then set use
     Inline_Stack_Void at the end of your function.

  3.      char* Foo(SV* arg1, ...) {

     In this category you have an unfixed number of arguments. This means
     that you'll have to pop values off the Stack yourself. Do it like
     this:

          int i;
          Inline_Stack_Vars;
          for (i = 0; i < Inline_Stack_Items; i++)
            handle_sv(Inline_Stack_Item(i));

     The return type of Inline_Stack_Item(i) is `SV*'.

  4.      void* Foo(SV* arg1, ...) {

     In this category you have both a void return type and an unfixed
     number of arguments. Just combine the techniques from Categories 3
     and 4.

Examples
========

   Here is a few examples. Each one is a complete program that you can try
running yourself. For many more examples see Inline/C-Cookbook.

Example #1 - Greetings
----------------------

   This example will take one string argument (a name) and print a
greeting. The function is called with a string and with a number. In the
second case the number is forced to a string.

   Notice that you do not need to `#include <stdio.h'>. The `perl.h'
header file which gets included by default, automatically loads the
standard C header files for you.

     greet('Ingy');
     greet(42);

     use Inline C => <<'END_OF_C_CODE';

     void greet(char* name) {
       printf("Hello %s!\n", name);
     }

     END_OF_C_CODE

Example #2 - and Salutations
----------------------------

   This is similar to the last example except that the name is passed in
as a `SV*' (pointer to Scalar Value) rather than a string (`char*'). That
means we need to convert the SV to a string ourselves. This is
accomplished using the SvPVX function which is part of the Perl internal
API. See `perldoc perlapi' for more info.

   One problem is that SvPVX doesn't automatically convert strings to
numbers, so we get a little surprise when we try to greet 42. The program
segfaults, a common occurence when delving into the guts of Perl.

     greet('Ingy');
     greet(42);

     use Inline C => <<'END_OF_C_CODE';

     void greet(SV* sv_name) {
       printf("Hello %s!\n", SvPVX(sv_name));
     }

     END_OF_C_CODE

Example #3 - Fixing the problem
-------------------------------

   We can fix the problem in Example #2 by using the SvPV function
instead. This function will stringify the SV if it does not contain a
string. SvPV returns the length of the string as it's second parameter.
Since we don't care about the length, we can just put PL_na there, which
is a special variable designed for that purpose.

     greet('Ingy');
     greet(42);

     use Inline C => <<'END_OF_C_CODE';

     void greet(SV* sv_name) {
       printf("Hello %s!\n", SvPV(sv_name, PL_na));
     }

     END_OF_C_CODE

SEE ALSO
========

   For general information about Inline see Inline.

   For sample programs using Inline with C see Inline/C-Cookbook.

   For information on supported languages and platforms see
Inline-Support.

   For information on writing your own Inline Language Support Module, see
Inline-API.

   Inline's mailing list is inline@perl.org

   To subscribe, send email to inline-subscribe@perl.org

AUTHOR
======

   Brian Ingerson <INGY@cpan.org>

COPYRIGHT
=========

   Copyright (c) 2001, Brian Ingerson. All Rights Reserved.  This module
is free software. It may be used, redistributed and/or modified under the
terms of the Perl Artistic License.

   See http://www.perl.com/perl/misc/Artistic.html

A Cornucopia of Inline C Recipes
********************************

NAME
====

   C Cookbook - A Cornucopia of Inline C Recipes

DESCRIPTION
===========

   It's a lot easier for most of us to cook a meal from a recipe, rather
than just throwing things into a pot until something edible forms. So it
is with programming as well. `Inline.pm' makes C programming for Perl as
easy as possible. Having a set of easy to understand samples, makes it
simpler yet.

   This Cookbook is intended to be an evergrowing repository of small yet
complete coding examples; each showing how to accomplish a particular task
with Inline. Each example is followed by a short discussion, explaining in
detail the particular features that are being demonstrated.

   Many of these recipes are apdapted from email discussions I have had
with Inline users around the world. It has been my experience so far, that
Inline provides an elegant solution to almost all problems involving Perl
and C.

   Bon Appetit!

Appetizers
==========

Hello, world
------------

Problem
     It seems that the first thing any programmer wants to do when he
     learns a new programming technique is to use it to greet the Earth.
     How can I do this using Inline?

Solution
          use Inline C => <<'END_C';

          void greet() {
          	printf("Hello, world\n");
          }
          END_C

          greet;

Discussion
     Nothing too fancy here. We define a single C function `greet()' which
     prints a message to STDOUT. One thing to note is that since the
     Inline code comes before the function call to `greet', we can call it
     as a bareword (no parentheses).

See Also
     See Inline, and Inline/C, for basic
     info about `Inline.pm'.

Credits
     Brian Kernigan

     Dennis Ritchie

One Liner
---------

Problem
     A concept is valid in Perl only if it can be shown to work in one
     line. Can Inline reduce the complexities of Perl/C interaction to a
     one-liner?

Solution
          perl -e 'use Inline C=>q{void greet(){printf("Hello, world\n");}};greet'

Discussion
     Try doing that in XS :-)

See Also
     My email signature of late is:

          perl -le 'use Inline C=>q{SV*JAxH(char*x){return newSVpvf("Just Another %s Hacker",x);}};print JAxH+Perl'

     A bit fancier but a few bytes too long to qualify as a true one liner
     :-(

Credits
     "Eli the Bearded" <elijah@workspot.net> gave me the idea that I
     should have an Inline one-liner as a signature.

Meat & Potatoes
===============

Data Types
----------

Problem
     How do I pass different types of data to and from Inline C functions;
     like strings, numbers and integers?

Solution
          # vowels.pl
          use Inline C;

          $filename = $ARGV[0];
          die "Usage: perl vowels.pl filename\n" unless -f $filename;

          $text = join '', <>;           # slurp input file
          $vp = vowel_scan($text);       # call our function
          $vp = sprintf("%03.1f", $vp * 100);  # format for printing
          print "The letters in $filename are $vp% vowels.\n";

          __END__
          __C__

          /* Find percentage of vowels to letters */
          double vowel_scan(char* str) {
              int letters = 0;
              int vowels = 0;
              int i = 0;
              char c;
              char normalize = 'a' ^ 'A';
              /* normalize forces lower case in ASCII; upper in EBCDIC */
              char A = normalize | 'a';
              char E = normalize | 'e';
              char I = normalize | 'i';
              char O = normalize | 'o';
              char U = normalize | 'u';
              char Z = normalize | 'z';

              while(c = str[i++]) {
                  c |= normalize;
                  if (c >= A && c <= Z) {
                       letters++;
                       if (c == A || c == E || c == I || c == O || c == U)
                           vowels++;
                  }
              }

          return letters ? ((double) vowels / letters) : 0.0;
              }

Discussion
     This script takes a file name from the command line and prints the
     ratio of vowels to letters in that file. `vowels.pl' uses an Inline C
     function called `vowel_scan', that takes a string argument, and
     returns the percentage of vowels as a floating point number between 0
     and 1. It handles upper and lower case letters, and works with ASCII
     and EBCDIC. It is also quite fast.

     Running this script produces:

          > perl vowels.pl /usr/dict/words
          The letters in /usr/dict/words are 37.5% vowels.

See Also
     The Perl Journal vol #19 has an article about Inline which uses this
     example.

Credits
     This example was reprinted by permission of The Perl Journal. It was
     edited to work with Inline v0.30 and higher.

Variable Argument Lists
-----------------------

Problem
     How do I pass a variable-sized list of arguments to an Inline C
     function?

Solution
          greet(qw(Sarathy Jan Sparky Murray Mike));

          use Inline C => <<'END_OF_C_CODE';

          void greet(SV* name1, ...) {
              Inline_Stack_Vars;
              int i;

              for (i = 0; i < Inline_Stack_Items; i++)
                  printf("Hello %s!\n", SvPV(Inline_Stack_Item(i), PL_na));

              Inline_Stack_Void;
          }

          END_OF_C_CODE

Discussion
     This little program greets a group of people, such as my coworkers.
     We use the C ellipsis syntax: "...", since the list can be of any
     size.

     Since there are no types or names associated with each argument, we
     can't expect XS to handle the conversions for us. We'll need to pop
     them off the Stack ourselves. Luckily there are two functions
     (macros) that make this a very easy task.

     First, we need to begin our function with a "Inline_Stack_Vars"
     statement. This defines a few internal variables that we need to
     access the Stack. Now we can use "Inline_Stack_Items", which returns
     an integer containing the number of arguments passed to us from Perl.

     NOTE: It is important to *only* use "`Inline_Stack_'" macros when
     there is an ellipsis (...) in the argument list, or the function has
     a return type of void.

     Second, we use the `Inline_Stack_Item(x)' function to access each
     argument where "0 <= x < items".

     NOTE: When using a variable length argument list, you have to specify
     at least one argument before the ellipsis. (On my compiler, anyway.)
     When XS does it's argument checking, it will complain if you pass in
     less than the number of defined arguments. Therefore, there is
     currently no way to pass an empty list when a variable length list is
     expected.

See Also
Credits
Multiple Return Values
----------------------

Problem
     How do I return a list of values from a C function?

Solution
          print map {"$_\n"} get_localtime(time);

          use Inline C => <<'END_OF_C_CODE';

          #include <time.h>

          void get_localtime(int utc) {
            struct tm *ltime = localtime(&utc);
            Inline_Stack_Vars;

            Inline_Stack_Reset;
            Inline_Stack_Push(newSViv(ltime->tm_year));
            Inline_Stack_Push(newSViv(ltime->tm_mon));
            Inline_Stack_Push(newSViv(ltime->tm_mday));
            Inline_Stack_Push(newSViv(ltime->tm_hour));
            Inline_Stack_Push(newSViv(ltime->tm_min));
            Inline_Stack_Push(newSViv(ltime->tm_sec));
            Inline_Stack_Push(newSViv(ltime->tm_isdst));
            Inline_Stack_Done;
          }
          END_OF_C_CODE

Discussion
     Perl is a language where it is common to return a list of values from
     a subroutine call instead of just a single value. C is not such a
     language. In order to accomplish this in C we need to manipulate the
     Perl call stack by hand. Luckily, Inline provides macros to make this
     easy.

     This example calls the system localtime, and returns each of the
     parts of the time struct; much like the perl builtin `localtime()'.

     NOTE: The `#include' statement is not really needed, because Inline
     automatically includes the Perl headers which include almost all
     standard system calls.

See Also
     For more information on the Inline stack macros, see Inline/C.

Credits
     Richard Anderson <starfire@zipcon.net> contributed the original idea
     for this snippet.

Using Memory
------------

Problem
     How should I allocate buffers in my Inline C code?

Solution
          print greeting('Ingy');

          use Inline C => <<'END_OF_C_CODE';

          SV* greeting(SV* sv_name) {
              return (newSVpvf("Hello %s!\n", SvPV(sv_name, PL_na)));
          }

          END_OF_C_CODE

Discussion
     In this example we will return the greeting to the caller, rather
     than printing it. This would seem mighty easy, except for the fact
     that we need to allocate a small buffer to create the greeting.

     I would urge you to stay away from mallocing your own buffer. Just
     use Perl's built in memory management. In other words, just create a
     new Perl string scalar. The function newSVpv does just that. And
     newSVpvf includes sprintf functionality.

     The other problem is getting rid of this new scalar. How will the ref
     count get decremented after we pass the scalar back? Perl also
     provides a function called sv_2mortal. Mortal variables die when the
     context goes out of scope. In other words, Perl will wait until the
     new scalar gets passed back and then decrement the ref count for you,
     thereby making it eligible for garbage collection. See `perldoc
     perlguts'.

     In this example the sv_2mortal call gets done under the hood by XS,
     because we declared the return type to be `SV*'.

     To view the generated XS code, run the command "`perl
     -MInline=INFO,FORCE,NOCLEAN example004.pl'". This will leave the
     build directory intact and tell you where to find it.

See Also
Credits
Fast Food
=========

Inline CGI
----------

Problem
     How do I use Inline securely in a CGI environment?

Solution
          #!/usr/bin/perl

          use CGI qw(:standard);
          use Inline (Config =>
                      DIRECTORY => '/usr/local/apache/Inline',
                     );

          print (header,
                 start_html('Inline CGI Example'),
                 h1(JAxH('Inline')),
                 end_html
                );

          use Inline C => <<END;
          SV* JAxH(char* x) {
              return newSVpvf("Just Another %s Hacker", x);
          }
          END

Discussion
     The problem with running Inline code from a CGI script is that Inline
     *writes* to a build area on your disk whenever it compiles code. Most
     CGI scripts don't (and shouldn't) be able to create a directory and
     write into it.

     The solution is to explicitly tell Inline which directory to use with
     the 'use Inline Config => DIRECTORY => ...' line. Then you need to
     give write access to that directory from the web server (CGI script).

     If you see this as a security hole, then there is another option.
     Give write access to yourself, but read-only access to the CGI
     script. Then run the script once by hand (from the command line).
     This will cause Inline to precompile the C code. That way the CGI
     will only need read access to the build directory (to load in the
     shared library from there).

     Just remember that whenever you change the C code, you need to
     precompile it again.

See Also
     See CGI, for more information on using the `CGI.pm' module.

Credits
Object Oriented Inline
----------------------

Problem
     How do I implement Object Oriented programming in Perl using C
     objects?

Solution
          my $obj1 = Soldier->new('Benjamin', 'Private', 11111);
          my $obj2 = Soldier->new('Sanders', 'Colonel', 22222);
          my $obj3 = Soldier->new('Matt', 'Sergeant', 33333);

          for my $obj ($obj1, $obj2, $obj3) {
              print ($obj->get_serial, ") ",
                     $obj->get_name, " is a ",
                     $obj->get_rank, "\n");
          }

          #---------------------------------------------------------

          package Soldier;

          use Inline C => <<'END';

          typedef struct {
              char* name;
              char* rank;
              long  serial;
          } Soldier;

          SV* new(char* class, char* name, char* rank, long serial) {
              Soldier* soldier = malloc(sizeof(Soldier));
              SV*      obj_ref = newSViv(0);
              SV*      obj = newSVrv(obj_ref, class);

          soldier->name = strdup(name);
          soldier->rank = strdup(rank);
          soldier->serial = serial;

          sv_setiv(obj, (IV)soldier);
          SvREADONLY_on(obj);
          return obj_ref;
              }

              char* get_name(SV* obj) {
          return ((Soldier*)SvIV(SvRV(obj)))->name;
              }

              char* get_rank(SV* obj) {
          return ((Soldier*)SvIV(SvRV(obj)))->rank;
              }

              long get_serial(SV* obj) {
          return ((Soldier*)SvIV(SvRV(obj)))->serial;
              }

          void DESTROY(SV* obj) {
              Soldier* soldier = (Soldier*)SvIV(SvRV(obj));
              free(soldier->name);
              free(soldier->rank);
              free(soldier);
          }
          END

Discussion
     Damian Conway has given us myriad ways of implementing OOP in Perl.
     This is one he might not have thought of.

     The interesting thing about this example is that it uses Perl for all
     the OO bindings while using C for the attributes and methods.

     If you examine the Perl code everything looks exactly like a regular
     OO example. There is a new method and several accessor methods. The
     familiar 'arrow syntax' is used to invoke them.

     In the class definition (second part) the Perl package statement is
     used to name the object class or namespace. But that's where the
     similarities end Inline takes over.

     The idea is that we call a C subroutine called new() which returns a
     blessed scalar. The scalar contains a readonly integer which is a C
     pointer to a Soldier struct. This is our object.

     The new() function needs to malloc the memory for the struct and then
     copy the initial values into it using `strdup()'. This also allocates
     more memory (which we have to keep track of).

     The accessor methods are pretty straightforward. They return the
     current value of their attribute.

     The last method DESTROY() is called automatically by Perl whenever an
     object goes out of scope. This is where we can free all the memory
     used by the object.

     That's it. It's a very simplistic example. It doesn't show off any
     advanced OO features, but it is pretty cool to see how easy the
     implementation can be. The important Perl call is `newSVrv()' which
     creates a blessed scalar.

See Also
     Read "Object Oriented Perl" by Damian Conway, for more useful ways of
     doing OOP in Perl.

     You can learn more Perl calls in Perlapi (perl.info).
     If you don't have Perl 5.6.0 or higher, visit
     http://www.perldoc.com/perl5.6/pod/perlapi.html

Credits
The Main Course
===============

Exposing Shared Libraries
-------------------------

Problem
     You have this great C library and you want to be able to access parts
     of it with Perl.

Solution
          print get('http://www.axkit.org');

          use Inline C => Config =>
                     LIBS => '-lghttp';
          use Inline C => <<'END_OF_C_CODE';

          #include <ghttp.h>

          char *get(SV* uri) {
             SV* buffer;
             ghttp_request* request;

             buffer = NEWSV(0,0);
             request = ghttp_request_new();
             ghttp_set_uri(request, SvPV(uri, PL_na));

             ghttp_set_header(request, http_hdr_Connection, "close");

             ghttp_prepare(request);
             ghttp_process(request);

             sv_catpv(buffer, ghttp_get_body(request));

             ghttp_request_destroy(request);

             return SvPV(buffer, PL_na);
          }

          END_OF_C_CODE

Discussion
     This example fetches and prints the HTML from http://www.axkit.org It
     requires the GNOME http libraries. http://www.gnome.org

     One of the most common questions I get is "How can I use Inline to
     make use of some shared library?". Although it has always been
     possible to do so, the configuration was ugly, and there were no
     specific examples.

     With version 0.30 and higher, you can specify the use of shared
     libraries easily with something like this:

          use Inline C => Config => LIBS => '-lghttp';
          use Inline C => "code ...";

     or

          use Inline C => "code ...", LIBS => '-lghttp';

     To specify a specific library path, use:

          use Inline C => "code ...", LIBS => '-L/your/lib/path -lyourlib';

     To specify an include path use:

          use Inline C => "code ...",
                     LIBS => '-lghttp',
                     INC => '-I/your/inc/path';

See Also
     The LIBS and INC configuration options are formatted and passed into
     MakeMaker. For more info see ExtUtils/MakeMaker.
     For more options see Inline/C.

Credits
     This code was written by Matt Sergeant <matt@sergeant.org>, author of
     many CPAN modules. The configuration syntax has been modified for use
     with Inline v0.30.

Complex Data
------------

Problem
     How do I deal with complex data types like hashes in Inline C?

Solution
          use Inline C => <<'END_OF_C_CODE';

          void dump_hash(SV* hash_ref) {
              HV* hash;
              HE* hash_entry;
              int num_keys, i;
              SV* sv_key;
              SV* sv_val;

              if (! SvROK(hash_ref))
                  croak("hash_ref is not a reference");

              hash = (HV*)SvRV(hash_ref);
              num_keys = hv_iterinit(hash);
              for (i = 0; i < num_keys; i++) {
                  hash_entry = hv_iternext(hash);
                  sv_key = hv_iterkeysv(hash_entry);
                  sv_val = hv_iterval(hash, hash_entry);
                  printf("%s => %s\n", SvPV(sv_key, PL_na), SvPV(sv_val, PL_na));
              }
              return;
          }

          END_OF_C_CODE

          my %hash = (
          	        Author => "Brian Ingerson",
          	        Nickname => "INGY",
          	        Module => "Inline.pm",
          	        Version => "0.30",
          	        Language => "C",
          	       );

          dump_hash(\%hash);

Discussion
     The world is not made of scalars alone, although they are definitely
     the easiest creatures to deal with, when doing Inline stuff.
     Sometimes we need to deal with arrays, hashes, and code references,
     among other things.

     Since Perl subroutine calls only pass scalars as arguments, we'll
     need to use the argument type `SV*' and pass references to more
     complex types.

     The above program dumps the key/value pairs of a hash. To figure it
     out, just curl up with Perlapi (perl.info), for a
     couple hours. Actually, its fairly straight forward once you are
     familiar with the calls.

     Note the croak function call. This is the proper way to die from your
     C extensions.

See Also
     See Perlapi (perl.info), for information about the
     Perl5 internal API.

Credits
Hash of Lists
-------------

Problem
     How do I create a Hash of Lists from C?

Solution
          use Inline C;
          use Data::Dumper;

          $hash_ref = load_data("./cartoon.txt");
          print Dumper $hash_ref;

          __END__
          __C__

          static int next_word(char**, char*);

          SV* load_data(char* file_name) {
              char buffer[100], word[100], * pos;
              AV* array;
              HV* hash = newHV();
              FILE* fh = fopen(file_name, "r");

              while (fgets(pos = buffer, sizeof(buffer), fh)) {
                  if (next_word(&pos, word)) {
                      hv_store(hash, word, strlen(word),
                              newRV_noinc((SV*)array = newAV()), 0);
                      while (next_word(&pos, word))
                          av_push(array, newSVpvf("%s", word));
                  }
              }
              fclose(fh);
              return newRV_noinc((SV*) hash);
          }

          static int next_word(char** text_ptr, char* word) {
              char* text = *text_ptr;
              while(*text != '\0' &&
                    *text <= ' ')
                  text++;
              if (*text <= ' ')
                  return 0;
              while(*text != '\0' &&
                    *text > ' ') {
                  *word++ = *text++;
              }
              *word = '\0';
              *text_ptr = text;
              return 1;
          }

Discussion
     This is one of the larger recipes. But when you consider the number
     of calories it has, it's not so bad. The function `load_data' takes
     the name of a file as it's input. The file `cartoon.text' might look
     like:

          flintstones fred barney
          jetsons     george jane elroy
          simpsons    homer marge bart

     The function will read the file, parsing each line into words. Then
     it will create a new hash, whereby the first word in a line becomes a
     hash key and the remaining words are put into an array whose
     reference becomes the hash value. The output looks like this:

          $VAR1 = {
                    'flintstones' => [
                                       'fred',
                                       'barney'
                                     ],
                    'simpsons' => [
                                    'homer',
                                    'marge',
                                    'bart'
                                  ],
                    'jetsons' => [
                                   'george',
                                   'jane',
                                   'elroy'
                                 ]
                  };

See Also
     See Perlapi (perl.info), for information about the
     Perl5 internal API.

Credits
     Al Danial <alnd@pacbell.net> requested a solution to this on
     comp.lang.perl.misc. He borrowed the idea from the "Hash of Lists"
     example in the Camel book.

Just Desserts
=============

Win32
-----

Problem
     How do I access Win32 DLL-s using Inline?

Solution
          use Inline C => DATA =>
                     LIBS => '-luser32';

          $text = "@ARGV" || 'Inline.pm works with MSWin32. Scary...';

          WinBox('Inline Text Box', $text);

          __END__
          __C__

          #include <windows.h>

          int WinBox(char* Caption, char* Text) {
            return MessageBoxA(0, Text, Caption, 0);
          }

Discussion
     This example runs on MS Windows. It makes a text box appear on the
     screen which contains a message of your choice.

     The important thing is that its proof that you can use Inline to
     interact with Windows DLL-s. Very scary indeed. 8-o

     To use Inline on Windows with ActivePerl ( http://www.ActiveState.com
     ) you'll need MS Visual Studio. You can also use the Cygwin
     environment, available at http://www.cygwin.com .

See Also
     See Inline-Support, for more info on MSWin32
     programming with Inline.

Credits
     This example was adapted from some sample code written by Garrett
     Goebel <garrett@scriptpro.com>

Embedding Perl in C
-------------------

Problem
     How do I use Perl from a regular C program?

Solution
          #!/usr/bin/cpr

          int main(void) {

          printf("Using Perl version %s from a C program!\n\n",
                         CPR_eval("use Config; $Config{version};"));

          CPR_eval("use Data::Dumper;");
          CPR_eval("print Dumper \\%INC;");

          return 0;

          }

Discussion
     By using CPR. (C Perl Run)

     This example uses another Inline module, `Inline::CPR', available
     separately on CPAN. When you install this module it also installs a
     binary interpreter called `/usr/bin/cpr'. (The path may be different
     on your system)

     When you feed a C program to the CPR interpreter, it automatically
     compiles and runs your code using Inline. This gives you full access
     to the Perl internals. CPR also provides a set of easy to use C
     macros for calling Perl internals.

     This means that you can effectively "run" C source code by putting a
     CPR hashbang as the first line of your C program.

See Also
     See Inline/CPR, for more information on using CPR.

     `Inline::CPR' can be obtained from
     http://search.cpan.org/search?dist=Inline-CPR

Credits
     Randal Schwartz <merlyn@stonehenge.com>, Randolph Bentson
     <bentson@grieg.holmsjoen.com>, Richard Anderson
     <starfire@zipcon.net>, and Tim Maher <tim@consultix-inc.com> helped
     me figure out how to write a program that would work as a hashbang.

Entertaining Guests
===================

   As of version 0.30, Inline has the ability to work in cooperation with
other modules that want to expose a C API of their own. The general syntax
for doing this is:

     use Inline with => 'Module';
     use Inline C => ... ;

   This tells Module to pass configuration options to Inline. Options like
typemaps, include paths, and external libraries, are all resolved
automatically so you can just concentrate on writing the functions.

Event handling with Event.pm
----------------------------

Problem
     You need to write a C callback for the `Event.pm' module. Can this be
     done more easily with Inline?

Solution
          use Inline with => 'Event';

          Event->timer(desc     => 'Timer #1',
                       interval => 2,
                       cb       => \&my_callback,
                      );

          Event->timer(desc     => 'Timer #2',
                       interval => 3,
                       cb       => \&my_callback,
                      );

          print "Starting...\n";
          Event::loop;

          use Inline C => <<'END';
          void my_callback(pe_event* event) {
              pe_timer * watcher = event->up;

              printf("%s\n\tEvent priority = %d\n\tWatcher priority = %d\n\n",
                     SvPVX(watcher->base.desc),
                     event->prio,
                     watcher->base.prio
                    );
          }
          END

Discussion
     The first line tells Inline to load the `Event.pm' module. Inline
     then queries Event for configuration information. It gets the name
     and location of Event's header files, typemaps and shared objects.
     The parameters that Event returns look like:

          INC => "-I $path/Event",
          TYPEMAPS => "$path/Event/typemap",
          MYEXTLIB => "$path/auto/Event/Event.$so",
          AUTO_INCLUDE => '#include "EventAPI.h"',
          BOOT => 'I_EVENT_API("Inline");',

     Doing all of this automatically allows you, the programmer, to simply
     write a function that receives a pointer of type `'pe_event*''. This
     gives you access to the Event structure that was passed to you.

     In this example, I simply print values out of the structure. The Perl
     code defines 2 timer events which each invoke the same callback. The
     first one, every two seconds, and the second one, every three seconds.

     As of this writing, `Event.pm' is the only CPAN module that works in
     cooperation with Inline.

See Also
     Read the `Event.pm' documentation for more information. It contains a
     tutorial showing several examples of using Inline with Event.

Credits
     Jochen Stenzel <perl@jochen-stenzel.de> originally came up with the
     idea of mixing Inline and Event. He also authored the Event tutorial.

     Joshua Pritikin <joshua.pritikin@db.com> is the author of `Event.pm'.

Food for Thought
================

Calling C from both Perl and C
------------------------------

Problem
     I'd like to be able to call the same C function from both Perl and C.
     Also I like to define a C function that *doesn't* get bound to Perl.
     How do I do that?

Solution
          print "9 + 5 = ", add(9, 5), "\n";
          print "SQRT(9^2 + 5^2) = ", pyth(9, 5), "\n";
          print "9 * 5 = ", mult(9, 5), "\n";

          use Inline C => <<'END_C';
          int add(int x, int y) {
              return x + y;
          }
          static int mult(int x, int y) {
              return x * y;
          }
          double pyth(int x, int y) {
              return sqrt(add(mult(x, x), mult(y, y)));
          }
          END_C

Discussion
     The program produces:

          9 + 5 = 14
          SQRT(9^2 + 5^2) = 10.295630140987
          Can't locate auto/main/mult.al in @INC ...

     Every Inline function that is bound to Perl is also callable by C.
     You don't have to do anything special. Inline arranges it so that all
     the typemap code gets done by XS and is out of sight. By the time the
     C function receives control, everything has been converted from Perl
     to C.

     Of course if your function manipulates the Perl Stack, you probably
     don't want to call it from C (unless you *really* know what you're
     doing).

     If you declare a function as static, Inline won't bind it to Perl.
     That's why we were able to call `mult()' from C but the call failed
     from Perl.

See Also
Credits
Calling Perl from C
-------------------

Problem
     So now that I can call C from Perl, how do I call a Perl subroutine
     from an Inline C function.

Solution
          use Inline C;

          c_func_1('This is the first line');
          c_func_2('This is the second line');

          sub perl_sub_1 {
              print map "$_\n", @_;
          }

          __DATA__
          __C__

          void c_func_1(SV* text) {
              c_func_2(text);
          }

          void c_func_2(SV* text) {
              Inline_Stack_Vars;
              Inline_Stack_Push(newSVpvf("Plus an extra line"));
              Inline_Stack_Done;
              perl_call_pv("main::perl_sub_1", 0);
              Inline_Stack_Void;
          }

Discussion
     Actually, this program demonstrates calling a C function which calls
     another C function which in turn calls a Perl subroutine.

     The nice thing about Inline C functions is that you can call them
     from both Perl-space and C-space. That's because Inline creates a
     wrapper function around each C function. When you use Perl to call C
     you're actually calling that function's wrapper. The wrapper handles
     typemapping and Stack management, and then calls your C function.

     The first time we call `c_func_1' which calls `c_func_2'. The second
     time we call `c_func_2' directly. `c_func_2' calls the Perl
     subroutine (`perl_sub_1') using the internal `perl_call_pv' function.
     It has to put arguments on the stack by hand. Since there is already
     one argument on the stack when we enter the function, the
     `Inline_Stack_Push' adds a second argument. Inline_Stack_Void makes
     sure that nothing is returned from the function.

See Also
     See Inline/C, for more information about Stack macros.

     See Perlapi (perl.info), for more information about the
     Perl5 internal API.

Credits
Evaling C
---------

Problem
     I've totally lost my marbles and I want to generate C code at run
     time, and eval it into Perl. How do I do this?

Solution
          use Inline;
          use Code::Generator;

          my $c_code = generate('foo_function');

          Inline->bind(C => $c_code);

          foo_function(1, 2, 3);

Discussion
     I can't think of a real life application where you would want to
     generate C code on the fly, but at least I know know how I would do
     it. :)

     The bind() function of Inline let's you bind (compile/load/execute) C
     functions at run time. It takes all of the same arguments as 'use
     Inline C => ...'.

     The nice thing is that once a particular snippet is compiled, it
     remains cached so that it doesn't need to be compiled again. I can
     imagine that someday a mad scientist will dream up a self generating
     modeling system that would run faster and faster over time.

     If you know such a person, have them drop me a line.

See Also
Credits
SEE ALSO
========

   For generic information about Inline, see Inline.

   For information about using Inline with C see Inline/C.

   For information on supported languages and platforms see
Inline-Support.

   For information on writing your own Inline language support module, see
Inline-API.

   Inline's mailing list is inline@perl.org

   To subscribe, send email to inline-subscribe@perl.org

AUTHOR
======

   Brian Ingerson <INGY@cpan.org>

COPYRIGHT
=========

   Copyright (c) 2001, Brian Ingerson.

   All Rights Reserved.  This module is free software. It may be used,
redistributed and/or modified under the terms of the Perl Artistic License.

   See http://www.perl.com/perl/misc/Artistic.html

Write Perl subroutines and classes in C++.
******************************************

NAME
====

   Inline::CPP - Write Perl subroutines and classes in C++.

SYNOPSIS
========

     print "9 + 16 = ", add(9, 16), "\n";
     print "9 - 16 = ", subtract(9, 16), "\n";

     use Inline CPP => <<'END_OF_CPP_CODE';

     int add(int x, int y) {
        return x + y;
     }

     int subtract(int x, int y) {
        return x - y;
     }

     END_OF_CPP_CODE

DESCRIPTION
===========

   The `Inline::CPP' module allows you to put C++ source code directly
"inline" in a Perl script or module. You code classes or functions in C++,
and you can use them as if they were written in Perl.

Using Inline::CPP
=================

   Inline::CPP is very similar to Inline::C. It uses a grammar to parse
your C++ code, and binds to functions or classes which are recognized. If
a function is recognized, it will be available from Perl space. If the
function's signature is not recognized, it will not be available from Perl
space, but will be available from other functions in C++.

   Inline::CPP binds to functions using the same grammar as Inline::C.
However, it contains an extended grammar for dealing with classes. Several
features of C++ are simply not supported, such as template classes and
inline function definitions.

   The following example shows how C++ snippets map into the Perl
namespace:

   Example 1:

     use Inline CPP => <<'END';

     int doodle() { }

     class Foo {
       public:
         Foo();
         ~Foo();

     int get_data();
     void set_data(int a);
          private:
     int data;
        };

     Foo::Foo() { cout << "creating a Foo()" << endl; }
     Foo::~Foo() { cout << "deleting a Foo()" << endl; }

     int Foo::get_data() { return data; }
     int Foo::set_data(int a) { data = a; }

     END

   After running the code above, Perl's namespace would look similar to if
following code had been run:

     sub main::doodle { }

     package main::Foo;

     sub new { print "creating a Foo()\n"; bless {}, shift }
     sub DESTROY { print "deleting a Foo()\n" }

     sub get_data { my $o=shift; $o->{data} }
     sub set_data { my $o=shift; $o->{data} = shift }

   The difference, of course, is that in the latter, Perl does the work.
In the Inline::CPP example, all function calls get sent off to your C++
code. That means that things like this won't work:

     my $obj = new Foo;
     $obj->{extrafield} = 10;

   It doesn't work because $obj is not a blessed hash. It's a blessed
reference to a C++ object (and anyway, C++ wouldn't let you do that either,
since extrafield wasn't defined).

C++ Configuration Options
=========================

   For information on how to specify Inline configuration options, see
Inline. This section describes each of the configuration
options available for C. Most of the options correspond either the
MakeMaker or XS options of the same name. See ExtUtils/MakeMaker,
and Perlxs (perl.info).

AUTO_INCLUDE
------------

   Specifies extra statements to be automatically included. They will be
added on to the defaults. A newline char will automatically be added.

     use Inline CPP => Config => AUTO_INCLUDE => '#include "something.h"';

BOOT
----

   Specifies code to be run when your code is loaded. May not contain any
blank lines. See Perlxs (perl.info), for more information.

     use Inline CPP => Config => BOOT => 'foo();';

CC
--

   Specifies which compiler to use.

CCFLAGS
-------

   Specifies extra compiler flags. Corresponds to the MakeMaker option.

INC
---

   Specifies extra include directories. Corresponds to the MakeMaker
parameter.

     use Inline CPP => Config => INC => '-I/my/path';

LD
--

   Specifies the linker to use.

LDDLFLAGS
---------

   Specifies which linker flags to use.

   NOTE: These flags will completely override the existing flags, instead
of just adding to them. So if you need to use those too, you must
respecify them here.

LIBS
----

   Specifies external libraries that should be linked into your code.
Corresponds to the MakeMaker parameter.

     use Inline CPP => Config => LIBS => '-L/your/path -lyourlib';

MAKE
----

   Specifies the name of the 'make' utility to use.

MYEXTLIB
--------

   Specifies a user compiled object that should be linked in. Corresponds
to the MakeMaker parameter.

     use Inline CPP => Config => MYEXTLIB => '/your/path/something.o';

PREFIX
------

   Specifies a prefix that will automatically be stripped from C++
functions when they are bound to Perl. Less useful than in C, because C++
mangles its function names so they don't conflict with C functions of the
same name.

     use Inline CPP => Config => PREFIX => 'ZLIB_';

TYPEMAPS
--------

   Specifies extra typemap files to use. These types will modify the
behaviour of C++ parsing. Corresponds to the MakeMaker parameter.

     use Inline CPP => Config => TYPEMAPS => '/your/path/typemap';

C++-Perl Bindings
-----------------

   This section describes how the Perl variables get mapped to `C++'
variables and back again.

   Perl uses a stack to pass arguments back and forth to subroutines. When
a sub is called, it pops off all its arguments from the stack; when it's
done, it pushes its return values back onto the stack.

   XS (Perl's language for creating C or C++ extensions for Perl) uses
"typemaps" to turn SVs into C types and back again. This is done through
various XS macro calls, casts, and the Perl API. XS also allows you to
define your own mappings.

   `Inline::CPP' uses a much simpler approach. It parses the system's
typemap files and only binds to functions with supported types. You can
tell `Inline::CPP' about custom typemap files too.

   If you have very complicated data structures in either C++ or Perl, you
should just pass them as an SV* and do the conversion yourself in your C++
function.

SEE ALSO
========

   For general information about how Inline binds code to Perl, see
Inline.

   For information on using C with Perl, see Inline/C, and
Inline/C-Cookbook. For `WMTYEWTK', see
Perlxs (perl.info), Perlxstut (perl.info),
Perlapi (perl.info), and Perlguts (perl.info).

BUGS AND DEFICIENCIES
=====================

   When reporting a bug, please do the following:

     - Put "use Inline REPORTBUG;" at the top of your code, or
       use the command line option "perl -MInline=REPORTBUG ...".
     - Run your code.
     - Follow the printed instructions.

   Here are some things to watch out for:

  1. The grammar used for parsing C++ is very simple, and does not allow
     several important features of C++:

          o templates;
          o inheritance; and,
          o inline class methods.

     Other grammar problems will probably be noticed quickly.

AUTHOR
======

   Neil Watkiss <NEILW@cpan.org>

   Brian Ingerson <INGY@cpan.org> is the author of Inline, Inline::C and
Inline::CPR. His antics with object-oriented Perl using C convinced me it
was time to add support for C++. He was responsible for much encouragement
and many suggestions throughout the development of Inline::CPP.

COPYRIGHT
=========

   Copyright (c) 2000 - 2001, Neil Watkiss.

   All Rights Reserved. This module is free software. It may be used,
redistributed and/or modified under the terms of the Perl Artistic License.

   See http://www.perl.com/perl/misc/Artistic.html

C Perl Run. Embed Perl in C, ala Inline
***************************************

NAME
====

   Inline::CPR - C Perl Run. Embed Perl in C, ala Inline

SYNOPSIS
========

     #!/usr/local/bin/cpr

     int main(void) {

         printf("Hello World, I'm running under Perl version %s\n",
                CPR_eval("use Config; $Config{version}")
               );

     return 0;
         }

DESCRIPTION
===========

   Is it C? Is it Perl? It's neither, it's both. It's CPR!

   CPR (C Perl Run) is a "new language" that looks like C. You don't need
to compile it. You just run it, much like Perl. As an added bonus, you'll
get access to the full internals of Perl via the CPR API.

   The idea is that you just put a CPR hashbang at the top of your C
program and run it like a script. The CPR interpreter will run your C code
under Perl.

   If your 'hash' doesn't 'bang', you can run your program like this:

     cpr synopsis.cpr

How does it work?
=================

   To understand CPR, you need to understand the Perl module, `Inline.pm'.
Inline lets you write Perl subroutines in other languages, like C. CPR is
a natural extension of this.

   The CPR interpreter (`/usr/local/bin/cpr') is a small binary program
which performs a bootstrap process that goes like this:

   - The `cpr' interpreter execs `perl' and tells it to run the script
`/usr/local/bin/cpr.pl'.

   - The name of your CPR program is passed to `cpr.pl'.

   - `cpr.pl' loads your CPR source code and uses `Inline::CPR' to compile
it and bind your `main()' function to Perl.

   - Then `cpr.pl' simply invokes the `main()' function and you're off and
running.

Notes on Usage
==============

  1. The CPR tools will get installed in the same directory as the `perl'
     binary on your system. (I just used `/usr/local/bin/' as an example)

  2. If you installed `Inline::CPR' by hand, the make command will have
     created the file `'./examples/synopsis.cpr''. This is a sample CPR
     program that you can try running. It's the same as the SYNOPSIS
     example above, except that the hashbang will point to your newly
     installed CPR interpreter.

  3. Although Inline::CPR is a module, it is only used to support the
     `cpr' interpreter program. You don't ever actually use it in a Perl
     script.

  4. You must have a `main()' function in your CPR program. This is what
     `cpr' binds to.

  5. The `cpr' interpreter internally changes your function `main()' to
     `cpr_main()'. Otherwise it would conflict with Perl's `main()'
     function.

  6. The first time you run a CPR program it will seem to "hang" for
     several seconds. This is normal. The C code is being compiled.
     Experienced Inline users will be familiar with this. (Since your
     compiled code is cached to disk, subsequent runs will be fast)

  7. CPR builds and caches your compiled CPR code in the directory
     `'./.cpr/''.

  8. CPR will return (to the system) whatever integer value your `main()'
     function returns.

  9. You don't need to `#include' most of the standard header files. These
     are automatically included by Inline::CPR.

 10. CPR will work with Perl 5.005 and higher. The CPR API will be made to
     work with those versions. (Maybe even with Perl6)

The CPR API
===========

   The CPR API is just a set of C macros that you can use to access the
internals of Perl5. You can also use the Perl5 API. See `perldoc perlapi'.

   The main focus of CPR will be to develop a wrapper API around the
current Perl5 one. It will be more consistent, flexible and easy to use.

   Since it should be well thought out, I have currently only implemented
one function: CPR_eval. But you should be able to do quite a bit with just
that one.

CPR_eval()
----------

   Eval a string (char*) in Perl and return the result as a string.

     const char* CPR_eval(char*);

Why?
====

   Several reasons, (none great).

  1. It's a cute Perl trick. After explaining CPR to an uninitiated
     friend, he said "My head feels like it's been wrapped around a
     brick". That should be reason enough :)

  2. A dead simple way to embed Perl into C. You're not really embedding
     Perl into C. Your C is being embedded seamlessly into Perl. But since
     you never see the Perl, you can just *think* of it the first way.

  3. A mechanism for designing a new Perl5 API. The current one is very
     adhoc. Some macros come from XS and others from the P5P. There's a
     lot of room for improvement. Also, with Perl6 looming, finding a
     wrapper API for Perl5 that might possibly be upwards compatible, is
     at least worth considering.

  4. Inline::CPR is a good example of how a CPAN module can be used to
     build and install a binary program. It is interesting to note that
     the C program `cpr.c' is actually generated by the Perl script
     `cpr.plc' at make time.

        Even if there is no "real world" use for the CPR language, it is
at least an easy-to-use tool for playing around with the internals of
Perl5. The more "regular people" there are playing in the guts, the more
useful we'll be for helping improve our language.

LIMITATIONS
===========

  1. CPR only binds to a `main()' function with a signature of:

          int main(void);

     It will not yet bind to:

          int main(int argc, char* argv[]);

     and friends.

  2. There is currently no way to specify configuration options. This will
     be added soon. Then you'll be able to link in shared libraries and
     such.

  3. Does not yet support MSWin32.

MAILING LIST
============

   The mailing list for `Inline.pm' and related projects is:
inline@perl.org

   To subscribe, send a message to inline-subscribe@perl.org

AUTHOR
======

   Brian Ingerson <INGY@cpan.org>

COPYRIGHT
=========

   Copyright (c) 2001, Brian Ingerson. All Rights Reserved.

   This module is free software. It may be used, redistributed and/or
modified under the terms of the Perl Artistic License.

   (see http://www.perl.com/perl/misc/Artistic.html)

Write Perl subroutines and classes in Python.
*********************************************

NAME
====

   Inline::Python - Write Perl subroutines and classes in Python.

SYNOPSIS
========

     print "9 + 16 = ", add(9, 16), "\n";
     print "9 - 16 = ", subtract(9, 16), "\n";

     use Inline Python => <<'END_OF_PYTHON_CODE';
     def add(x,y):
        return x + y

     def subtract(x,y):
        return x - y

     END_OF_PYTHON_CODE

DESCRIPTION
===========

   The `Inline::Python' module allows you to put Python source code
directly "inline" in a Perl script or module. A Python interpreter is
loaded and the Python code is interpreted, then Perl asks the Python
interpreter what global functions and classes have been defined. Those
functions and classes are made available to your Perl program as if they
had been written in Perl.

   The process of interrogating the Python interpreter for globals only
occurs the first time you run your Python code. The namespace is cached,
and subsequent calls use the cached version.

Using the Inline::Python Module
===============================

   `Inline::Python' is driven by fundamentally the same idea as other
Inline language modules, like `Inline::C' or `Inline::CPP'.  Because
Python is interpreted, the method of getting your code is different, but
overall, using `Inline::Python' is very similar to any other Inline
language module.

   This section will explain the different ways to use Inline::Python.
For more details on Inline, see 'perldoc Inline'.

The Basics: Functions
---------------------

   The most basic form for using `Inline::Python' is:

     use Inline Python => 'Python source code';

   Of course, you can use Perl's "here document" style of quoting to make
the code slightly easier to read:

     use Inline Python => <<'END';

     Python source code goes here.

     END

   The source code can also be specified as a filename, a subroutine
reference (sub routine should return source code), or an array reference
(array contains lines of source code). This information is detailed in
'perldoc Inline'.

More Advanced: Classes and Objects
----------------------------------

   Because Python is object oriented, any interface between Perl and Python
needs to support Python classes adequately.

   Example:

     use Inline Python => <<'END';

     class Foo:
        def __init__(self):
           print "new Foo object being created"
           self.data = {}
        def get_data(self): return self.data
        def set_data(self,dat):
           self.data = dat

     END

     use Data::Dumper;
     my $obj = new Foo;
     print Dumper $obj;
     print Dumper $obj->get_data();
     $obj->set_data({string => 'hello',
                     number => 0.7574,
                     array => [1, 2, 3],
                    });
     print Dumper $obj->get_data();

   The output from this program is:

     new Foo object being created
     $VAR1 = bless( do{\(my $o = 135870536)}, 'main::Foo' );
     $VAR1 = {};
     $VAR1 = {
               'string' => 'hello',
               'array' => [
                            '1',
                            '2',
                            '3'
                          ],
               'number' => '0.7574'
             };

   `Inline::Python' created a new namespace called `main::Foo' and created
the following functions:

     sub main::Foo::new { ... }
     sub main::Foo::DESTROY { ... }
     sub main::Foo::set_data { ... }
     sub main::Foo::get_data { ... }
     sub main::Foo::__init__ { ... }

   If you don't like the fact that the "private" method __init__() was
bound to Perl, you can feed `Inline::Python' options to disable binding to
private functions. You can even specify what a private function looks like.

   Example:

     use Inline Python => <<'END', PRIVATE_PREFIXES => ['__'];

     class Foo:
        def __init__(self):
           print "new Foo object being created"
           self.data = {}
        def get_data(self): return self.data
        def set_data(self,dat):
           self.data = dat

     END

   `Inline::Python' created a new namespace called `main::Foo' and only
created the following functions:

     sub main::Foo::new { ... }
     sub main::Foo::DESTROY { ... }
     sub main::Foo::set_data { ... }
     sub main::Foo::get_data { ... }

   By default, "private" symbols are ones which begin with one underscore,
or ones that begin with two underscores. You can redefine the "prefix"
used to filter out private functions by using the `PRIV_STRING' option,
which adds new prefixes to the list of bad prefixes. You can pass a string
or an array as the argument to `PRIV_STRING'.

   Example:

     use Inline Python => <<END, PRIVATE_PREFIXES => [undef, "_priv_"];

     def _priv_function(): return None
     def public_function(): return None

     END

   This code will not bind to `_priv_function'. Notice that undef clears
the list `PRIVATE_PREFIXES'.

   If you're like every other Perl hacker, though, you'll just leave all
the functions available and let people use their own judgement.

What happens when I call a Python function?
-------------------------------------------

   When you call a "Python" function, you're actually calling a Perl
function which knows how to get into Python space and back again. For
instance, earlier we saw this example:

     use Inline Python => <<'END';

     class Foo:
        def __init__(self):
           print "new Foo object being created"
           self.data = {}
        def get_data(self): return self.data
        def set_data(self,dat):
           self.data = dat

     END

   The code which is passed to eval() is this: (beautified slightly)

     package main::Foo;

     sub new {
        shift;
        Inline::Python::_eval_python_function(__PACKAGE__,"Foo", @_)
     }

     sub DESTROY {
       Inline::Python::_destroy_python_object(@_)
     }

     sub set_data {
       Inline::Python::_eval_python_method(__PACKAGE__,"set_data",@_)
     }

     sub get_data {
       Inline::Python::_eval_python_method(__PACKAGE__,"get_data",@_);
     }

     sub __init__ {
       Inline::Python::_eval_python_method(__PACKAGE__,"__init__",@_);
     }

Can I do it myself?
-------------------

   If you just want access to Python's interpreter, `Inline::Python'
provides a function you can use to interact with Python. There are three
usages: the first one emulates Perl's own eval() - you just pass it Python
code as a string and Python runs it. The major difference between eval()
and eval_python() is that Python's eval_python returns 1 or 0, depending
on whether the code passed or failed. This may be changed in a subsequent
release.

     eval_python("python source code")

   If you want to send data between Python and Perl, you'll need more than
just a success flag. Two other usages of eval_python() are provided which
return the results of running Python code:

     eval_python("perl package", "python function", args...)

     eval_python("perl package", "python method", object, args...)

   The first argument, "perl package", is what package into which to bless
an instance of a Python class. This is required to support Object Oriented
programming properly.

   To import eval_python() into your namespace, use the following syntax:

     use Inline::Python qw(eval_python);

   This will import eval_python() into your namespace, and do nothing
else. (NB: most Inline language extensions do not support this syntax. For
instance, 'use Inline::C' will generate an error.)

SUPPORTED PLATFORMS
===================

   This is an ALPHA release of Inline::Python. Further testing and
expanded support for other operating systems and platforms will be a focus
for future releases. It has been tested on RedHat Linux 6.2 with a variety
of different Perl and Python configurations. It likely will work with many
flavours of Unix, and possibly in Windows.

SEE ALSO
========

   For information about using Inline, see Inline.

   For information about other Inline languages, see Inline-Support.

   Inline::Python's mailing list is inline@perl.org

   The subscribe, send email to inline-subscribe@perl.org

BUGS AND DEFICIENCIES
=====================

   When reporting a bug, please do the following:

     - Put "use Inline REPORTBUG;" at the top of your code, or
       use the command line option "perl -MInline=REPORTBUG ...".
     - Run your code.
     - Follow the printed instructions.

   Here are some things to watch out for:

  1. The eval_python() function only returns the result of the compilation,
     not the result of running the code. You can only get the results of
     running Python code by putting code in a function and running that.

     Example:

          use Inline::Python qw(eval_python);

          eval_python("def foo(): return {'apples': 1, 'oranges': 2}"); # returns 1
          eval_python("foo()"); # returns 1 (NOT a hash)

     What you need to do:

          use Inline::Python qw(eval_python);

          eval_python("def foo(): return {'apples': 1, 'oranges': 2}"); # returns 1
          eval_python(__PACKAGE__, "foo"); # returns a hash

     This bug will probably be fixed in a future release.

  2. Note that the namespace imported into Perl is NOT recursively
     traversed. Only Python *globals* are imported into Perl - subclasses,
     subfunctions, and other modules are not imported.

     Example:

          use Inline Python => <<'END';

          import mymodule

          class A: pass

          END

     The namespace imported into perl is ONLY that related to A. Nothing
     related to mymodule is imported, unless some Python code explictly
     copies variables from the mymodule namespace into the global namespace
     before Perl binds to it.

AUTHOR
======

   Neil Watkiss <NEILW@cpan.org>

   Brian Ingerson <INGY@cpan.org> is the author of Inline, Inline::C and
Inline::CPR. He was responsible for much encouragement and many
suggestions throughout the development of Inline::Python.

COPYRIGHT
=========

   Copyright (c) 2000, Neil Watkiss.

   All Rights Reserved. This module is free software. It may be used,
redistributed and/or modified under the terms of the Perl Artistic License.

   (see http://www.perl.com/perl/misc/Artistic.html)

Arbitrary string interpolation semantics
****************************************

NAME
====

   Interpolation - Arbitrary string interpolation semantics

SYNOPSIS
========

     use Interpolation name => \&function, ...;
     print "la la la la $name{blah blah blah}";

     # This is like doing:
     $VAR = &function(blah blah blah);
     print "la la la la $VAR";

DESCRIPTION
===========

   Beginners always want to write this:

     print "The sum of three and four is: 3+4";

   And they want the `3+4' part to be evaluated, so that it prints this:

     The sum of three and four is: 7

   Of course, it's a double-quoted string, so it's not evaluated.  The
only things that are evaluated in double-quoted strings are variable
references.

   There are solutions to this, but most of them are ugly.  This module is
less ugly.  It lets you define arbitrary interpolation semantics.

   For example, you can say

     use Interpolation money => \&commify_with_dollar_sign,
                       E     => 'eval',
                       placename => 'ucwords',
         ;

   And then you can write these:

     print "3 + 4 = $E{3+4}";
     # Prints  ``3 + 4 = 7''

     $SALARY = 57500;
     print "The salary is $money{$SALARY}";
     # Prints  ``The salary is $57,500.00''

     $PLACE1 = 'SAN BERNADINO HIGH SCHOOL';
     $PLACE2 = 'n.y. state';
     print "$placename{$PLACE1} is not near $placename{$PLACE2}";
     # Prints  ``San Bernadino High School is not near N.Y. State";

DETAILS
=======

   The arguments to the use call should be name-function pairs.  If the
pair is `($n, $f)', then $n will be the name for the semantics provided by
$f.  $f must either be a reference to a function that you supply, or it
can be the name of one of the built-in formatting functions provided by
this package.  Interpolation will take over the `%n' hash in your package,
and tie it so that acessing `$n{X}' calls `f(X)' and yields its return
value.

   If for some reason you want to, you can add new semantics at run time
by using

     import Interpolation name => function, ...

   You can remove them again with

     unimport Interpolation 'name', ...

Built-ins
---------

   Interpolation provides a few useful built-in formatting functions; you
can refer to these by name in the use or import line.  They are:

     eval     Evaluate argument
     null     Same as eval
     identity Also the same as eval
     ucwords  Capitalize Input String Like This
     commify  1428571 => 1,428,571.00
     reverse  reverse string
     sprintf  makes "$S{'%.2f %03d'}{37.5,42}" turn into "37.50 042".
     sprintf1 makes "$S{'%.2f %03d', 37.5,42}" turn into "37.50 042".

   It's easy to forget that the index to a `$hash{...}' is an arbitrary
expression, unless it looks like an identifier.  There are two gotchas
here.

Trap 1.
          print "$X{localtime}";

     Here the X formatter is used to format the literal string localtime;
     the localtime built-in function is not invoked.  If you really want
     the current time, use one of these:

          print "$X{+localtime}";
          print "$X{localtime()}";

Trap 2.
          print "$X{What ho?}";

     This won't compile--you get `search pattern not terminated'.  Why?
     Because Perl sees the ? and interprets it as the beginning of a
     pattern match operator, similar to /.  (Ah, you forgot that ?  could
     be a pattern match delimiter even without a leading m, didn't you?)
     You really need

          print "$X{'What ho?'}";

   The rule is simple: That thing in the braces that looks like a hash key
really is a hash key, and so you need to put it in quotes under the same
circumstances that you need to put any other hash key in quotes.  You
probably wouldn't expect this to work either:

     $V = $X{What ho?};

Author
======

   Mark-Jason Dominus (`mjd-perl-interpolation@plover.com'), Plover
Systems co.

   See the `Interpolation.pm' Page at
http://www.plover.com/~mjd/perl/Interpolation for news and upgrades.

   Mark-Jason Dominus (`mjd-perl-interpolation@plover.com'), Plover
Systems co.

   See the `Interpolation.pm' Page at
http://www.plover.com/~mjd/perl/Interpolation for news and upgrades.

handling of temporal intervals based on Date::Manip
***************************************************

NAME
====

   Interval - handling of temporal intervals based on Date::Manip

SYNOPSIS
========

     use Interval;

     ### class methods ###
     Interval->setDefaultIntervalType ($OPEN_INT);
     $int_open = new Interval ("10/10/97", "20/10/97");
     print "$int_open\n"        # prints  '(1997-10-10, 1997-10-20)'

     $nDefaultType = Interval->getDefaultIntervalType;

     ### constructor ###
     $i1 = new Interval ("30/10/97", "01/12/98");
     $i2 = new Interval ("20/01/96", "01/11/97", $RIGHT_OPEN_INT);

     use Date::Manip;
     $date1 = &ParseDate ("10/10/97");
     $date2 = &ParseDate ("15/10/97");
     $int = new Interval ($d1, $d2);

     ### Overload operators ###
     $i3 = $i1 + $i2;          # + gives the sum of intervals if the overlap
     print "$i3\n";            # prints '[1997-01-20, 1998-12-01)'

     $i4 = $i1 - $i2;          # - gives difference of intervals of intervals
     print "$i4\n";            # prints '[1997-11-01, 1998-12-01)'

     $i5 = $i1 - $i1;
     print "$i5\n";            # prints '<empty>'

     ### <Allen overlap type> ###
     $X = new Interval (<parameters>);
     $Y = new Interval (<parameters>);
                               ###  relationship between intervals ###
     $Y->AllenBefore ($X);             YYYYYY XXXXXX

     $Y->AllenMeets ($X);              YYYYYYXXXXXX

     $Y->AllenLeftOverlaps ($X);          XXXXXX
                                       YYYYYY

     $Y->AllenLeftCovers ($X);            XXXXXX
                                       YYYYYYYYY

     $Y->AllenCovers ($X);                XXXXXX
                                       YYYYYYYYYYYY

     $Y->AllenStarts ($X);             XXXXXX
                                       YYY

     $Y->AllenEquals ($X);             XXXXXX
                                       YYYYYY

     $Y->AllenRightCovers ($X);        XXXXXX
                                       YYYYYYYYY

     $Y->AllenDuring ($X);             XXXXXX
                                        YYYY

     $Y->AllenFinishes ($X);           XXXXXX
     				        YYYY

     $Y->AllenRightOverlaps ($X);      XXXXXX
                                          YYYYYY

     $Y->AllenExtends ($X);            XXXXXXYYYYYY

     $Y->AllenAfter ($X):              XXXXXX YYYYYY

     ### <overlap type> ###
     $Y->before ($X)         same as  $Y->AllenBefore ($X)
     $Y->meets  ($X)         same as  $Y->AllenMeets ($X)

     $Y->leftOverlaps ($X)   same as  $Y->AllenLeftOverlaps ($X)  or
                                      $Y->AllenStarts ($X)

     $Y->totalOverlaps ($X)  same as  $Y->AllenCovers ($X)        or
                                      $Y->AllenLeftCovers ($X)    or
                                      $Y->AllenRightCovers ($X)   or
                                      $Y->AllenEquals ($X)

     $Y->rightOverlaps ($X)  same as  $Y->AllenFinishes ($X)      or
                                      $Y->AllenRightCovers

     $Y->during ($X)         same as  $Y->AllenDuring ($X)
     $Y->extends ($X)        same as  $Y->AllenExtends ($X)
     $Y->after ($X)          same as  $Y->AllenAfter ($X)

     ### <interval type> ###
     $closed_int = new Interval ("10/10/97", "20/10/97", $CLOSED_INT);
     print "$closed_int\n";      # prints [1997-10-10, 1997-10-20]

     $left_open_int = new Interval ("10/10/97", "20/10/97", $LEFT_OPEN_INT);
     print "$left_open_int\n";   # prints (1997-10-10, 1997-10-20]

     $right_open_int = new Interval ("10/10/97", "20/10/97", $RIGHT_OPEN_INT);
     print "$right_open_int\n";  # prints [1997-10-10, 1997-10-20)

     $open_int = new Interval ("10/10/97", "20/10/97", $OPEN_INT);
     print "$open_int\n";         # prints (1997-10-10, 1997-10-20)

     ### check and get overlapping interval ###
      $i1 = new Interval ("30/10/97", "01/12/98");
      $i2 = new Interval ("20/01/96", "01/11/97");
      $i3 = new Interval ("01/01/95", "30/04/95");

     if ($i1->overlaps ($i2)) {
         $i4 = $i1->getOverlap($i2);
         print "$i4\n";              # prints [1997-10-30, 1997-11-01)
     }
     if ($i1->overlaps ($i3)){       # tests fails, does not print anything
         $i5 = $i1->getOverlap($i2);
         print "$i5\n";
     }

DESCRIPTION
===========

     All strings which can be used to create a Date::Manip can be used
     to create an Interval. However, the start date must be larger than
     the stop date.

     The comparison of intervals is based on the 13 ways intervals can
     overlap as defined by J.F. Allen (See litteratur). Further, I have
     included a small number of interval comparison which are handy if
     you are only interested in getting the overlapping interval of two
     intervals.

Defaults
--------

     The default input format is non-us date format "10/12/97" is the
     10th of December 1997, not the 12 of October 1997. It can be
     changed by calling Date::Manip::DateInit().

     The default output format is YYYY-MM-DD. Can be changed by calling
     Interval->setDisplayFormat(<string>).

BUGS
====

     Tried my best to avoid them send me an email if you are bitten by
     a bug

TODO
====

     - Cannot take references to dates as input parameters for the
       constructors

     - Cannot subtract intervals which overlap with "during" overlaps,
       this results in two intervals (currently results in an empty interval)

LITTERATURE
===========

     Allen, J. F., "An Interval-Based Representation of Temporal Knowledge",
     Communication of the ACM, 26(11) pp. 832-843, November 1983.

AUTHOR
======

   Kristian Torp <`torp@cs.auc.dk'>

Perl extension for ISAM files
*****************************

NAME
====

   Isam - Perl extension for ISAM files

SYNOPSIS
========

   use Isam;

DESCRIPTION
===========

   Isam.pm is a thin wrapper to the C-ISAM functions calls.  IsamData.pm
is a facility to access the record's fields.

Exported constants
==================

     AUDGETNAME
     AUDHEADSIZE
     AUDINFO
     AUDSETNAME
     AUDSTART
     AUDSTOP
     CHARTYPE
     DECIMALTYPE
     DOUBLETYPE
     FLOATTYPE
     INTTYPE
     LONGTYPE
     MINTTYPE
     MLONGTYPE
     STRINGTYPE
     ISAUTOLOCK
     ISCLOSED
     ISCURR
     ISD1
     ISD2
     ISDD
     ISDESC
     ISDUPS
     ISEQUAL
     ISEXCLLOCK
     ISFIRST
     ISFIXLEN
     ISGREAT
     ISGTEQ
     ISINOUT
     ISINPUT
     ISLAST
     ISLCKW
     ISLOCK
     ISMANULOCK
     ISMASKED
     ISNEXT
     ISNOCARE
     ISNODUPS
     ISNOLOG
     ISOUTPUT
     ISPREV
     ISRDONLY
     ISSYNCWR
     ISTRANS
     ISVARCMP
     ISVARLEN
     ISWAIT

AUTHOR
======

   Philippe Chane-You-Kaye, philippe.cyk@wanadoo.fr

METHODS
=======

   Isam.pm module include class methods indicated by Isam->method and
object methods indicated by $fd->method where $fd is a reference to an
instance obtained by isopen, isbuild or iscluster eg. my $fd =
Isam->isopen("myfile",&ISINOUT);

Isam->iserrno([INTVALUE])
     Returns the value of the global Isam variable iserrno unless
     `INTVALUE' is specified, in which case, sets the value of iserrno.

Isam->isrecnum([LONGVALUE])
     Returns the value of the global Isam variable isrecnum unless
     `LONGVALUE' is specified, in which case, sets the value of isrecnum.

Isam->isreclen([INTVALUE])
     Returns the value of the global Isam variable isreclen unless
     `INTVALUE' is specified, in which case, sets the value of isreclen.

Isam->iserrio([INTVALUE])
     Returns the value of the global Isam variable iserrio unless
     `INTVALUE' is specified, in which case, sets the value of iserrio.

$fd->fd
     Returns Isam file descriptor

$fd->name   Returns the filename
$fd->isaddindex(KEYDESC)
     Returns TRUE if successfully adds an index to $fd

Isam->isbuild(NAME, LEN, KEYDESC, MODE)
     Returns a reference to an Isam object or undef if unsuccessful

Isam->iscleanup
     Returns TRUE if successful

$fd->isclose
     Returns TRUE if successful

$fd->iscluster(KEYDESC)
     KEYDESC is a reference to a Keydesc object.  Returns a reference to
     an Isam object or undef if unsuccessful

Isam->iscommit
     Returns TRUE if successful

$fd->isdelcurr
     Returns TRUE if successful

$fd->isdelete(DATA)
     DATA is a reference to a scalar. Returns TRUE if successful

$fd->isdelindex(KEYDESC)
     KEYDESC is a reference to a Keydesc object.  Returns TRUE if
     successful

$fd->isdelrec(RECNUM)
     RECNUM is a long integer Returns TRUE if successful

Isam->iserase(NAME)
     NAME is a filename. Returns TRUE if successful

$fd->isflush
     Returns TRUE if successful

$fd->isindexinfo(IDX)
     IDX is an integer. returns undef if unsuccessful.  If IDX == 0,
     returns a reference to a Dictinfo object.  If IDX > 0, returns a
     reference to a Keydesc object

$fd->islock
     Returns TRUE if successful

Isam->islogclose
     Returns TRUE if successful

Isam->islogopen
     Returns TRUE if successful

Isam->isopen(NAME, MODE)
     NAME is a filename, MODE is an integer Returns undef if unsuccessful,
     otherwise returns a reference to an Isam object

$fd->isread(DATA, MODE)
     DATA is a reference to a scalar. MODE is an integer.  Returns TRUE if
     successful

Isam->isrecover
     Returns TRUE if successful

$fd->isrelease
     Returns TRUE if successful

Isam->isrename(OLDNAME, NEWNAME)
     Returns TRUE if successful

$fd->isrewcurr(DATA)
     DATA is a reference to a scalar. Returns TRUE if successful

$fd->isrewrec(RECNUM, DATA)
     RECNUM is the record number, DATA is a reference to the Data.
     Returns TRUE if successful

$fd->isrewrite(DATA)
     DATA is a reference to the Data. Returns TRUE if successful

Isam->isrollback
     Returns TRUE if successful

$fd->issetunique(UNIQUEID)
     UNIQUEID is an integer scalar. Returns TRUE if successful

$fd->isstart(KEYDESC, LENGTH, DATA, MODE)
     KEYDESC is a reference to a Keydesc object, LENGTH is 0 or the number
     of bytes of the key, DATA is a reference to a scalar, MODE is an
     integer value.

     Returns TRUE if successful

$fd->isuniqueid
     Returns undef if unsuccessful or an long value

$fd->isunlock
     Returns TRUE if successful

$fd->iswrcurr(DATA)
     DATA is a reference to a scalar. Returns TRUE if successful

$fd->iswrite(DATA)   DATA is a reference to a scalar. Returns TRUE if successful
SEE ALSO
========

   perl(1).  IsamData.

Perl extension for Interactive Voice Response System.
*****************************************************

NAME
====

   Ivrs - Perl extension for Interactive Voice Response System.

SYNOPSIS
========

   $iv = new Ivrs($portname,$vdir);

DESCRIPTION
===========

   This module provides the complete interface to voice modem for
Interactive Voice Response System (IVRS). The IVRS are widely used for
telebanking, product inforamtion, tele marketing, voice mail, fax servers,
and many more.  All these can be implemented using this module and with
very few lines of Perl code. This module takes care of all low level
functions of serial port and modem.  A log file defined by the
$logfile="/var/log/Ivrs_Log.ttyS*" will be opened for logging IVRS
activity. Set $Babble =0 if you do not want to log all the messages
(default is 1).

EXAMPLE
=======

   The demo files explains the working of various subroutines of the
module.

   demo1 - A simple voice interaction.

   demo2 - Message recording and playback.

   demo3 - Fax server.

METHODS
=======

   $iv = new Ivrs('ttyS1',$vdir);

   The first variable is the port name for modem and serial port (ttyS0 or
ttyS1)

   The second variable $vdir is voice file directory.  You must specify
$vdir if you want to use other than  default directory ( sfiles/ ). If you
are running IVRS from /etc/inittab (YES!! you can do) then absolute path
for voice files will be rquired.

Initilization.
--------------

   $iv->setport('38400','none','8','1','rts','8096');

   The serial port parameters are set here. These parameters are carefully
worked out after extensive trials. Change these only if you know what are
you doing or if these settings do not work on your modem.

   $iv->initmodem;

   This will put the modem in voice mode. Number of AT commands are
required to set this. You may comment out the AT commands which do not
start with AT# if your modem fails to respond. Some modem uses AT+ for
voice commands.  In that case you will have to replace all AT# with AT+.

   $cid=$iv->waitring;

   This will put the modem in answer mode and wait for the ring. When the
ring comes, call will be received on the first ring and Caller ID will be
returned in $cid (not tested so far).

   If you want to play a message directly (without some one calling)
through Modem speaker then skip it and put $iv->atcomm("AT#VTX","CONNECT");
but then you will not be able to punch DTMF codes.

Play messages.
--------------

   $iv->playfile("$msgfile","$dtmf")

   This requires a bit of explanation.  From version 0.06, the use of lin
file is removed and all files are raw modem data (Rockwell Modem, 7200
samples per second with compression Type 4) type only, So pvftools are no
longer required to run the IVRS.

   The $msgfile contains the message file to be played.  You can specify
the full path of the file like, /home/Ivrs-0.07/sfiles/greet or only file
name (like greet) from voice file directory. If no file name is specified,
it will play special file contained in $tmpmsg. I will discuss this file
in next section.

   Another variable required is $dtmf, which is number of dtmf codes to be
accpeted from the user while playing the file.

   If $dtmf=0 then playing of file will not be stopped even if caller
presses any key.

   If $dtmf=1, then playing of file will be immidiately stopped if the
caller presses first dtmf code and $iv->playfile will return the digit
pressed.

   If $dtmf=2 or more, then playing of specified file will be stopped when
caller presses first digit and next a silence (tsil15) of 15 seconds will
played, for caller to enter remaining digits. When caller has pressed
required number of digits ($dtmf) then playing will be stopped and
$iv->playfile will return with complete dtmf digits.

   $iv->addmsg($msg)

   $iv->addval($val)

   $iv->addmil($val)

   $iv->addtxt("ABCDEF")

   $iv->addate("20001212")

   IVRS requires many messages to generated on the fly and then played to
caller, like numbers in numerical format, date etc. The default voice
directory sfiles/ has number of rmd files with 32 bytes of header striped.
These header less files can be cut and pasted as required. The rmd file
header ( $rmdhdr ) is added to it before playing these file in
$iv-playfile.  The above mentioned routines adds up various rmd files to a
file specified by $tmpmsg, and finally this file along with header is
played to caller.  For example to play number 123 to caller, files (from
sfiles/) '1','hundred', '20' and '3' will be added to $tmpmsg, and then
played.

   $iv->addmsg($msg)

   Add a message from sfiles/

   $iv->addval($val)

   Add a numeric value in Indian format (using lacs and crore)

   $iv->addmil($val)

   Same as above but with International format (using milions and billions)

   $iv->addtxt("ABCDEF")

   Add characters (A-Z and 0-9)

   $iv->addate("20001212")

   Add date in yyyymmdd format.

Record Messages.
----------------

   $iv->recfile($filename,$duration)

   This will record the file $filename in rmd format with proper header
for a period of $duration seconds. This rmd file can be converted to any
format using pvftools.

Other Functions.
----------------

   $iv->dialout

   For dialing out a number - NOT IMPLEMENTED YET.

   $iv->callxfer

   For transfering the call to another extension - NOT IMPLEMENTED YET.

   $iv->faxmode

   This will put the modem in fax mode and you can run efix and efax to
send the fax. This should be last instruction in your script. Also install
efax or copy these files from bin/ directory to your /usr/bin.

Close.
------

   $iv->closep

   This will do some cleanup, hangup the line and reset the modem.

THANKS
======

   I thank Bill Birthisel, wcbirthisel@alum.mit.edu, for serial port code
taken from SerialPort.pm,

COPYRIGHT
=========

   Copyright (c) 2000 Mukund Deshmukh. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

AUTHOR
======

   Mukund Deshmukh <betacomp@nagpur.dot.net.in>

SEE ALSO
========

   SerialPort.pm, pvftools

JListbox
========

   JListbox - justify text within a Listbox

SYNOPSIS
========

     use JListbox;
     $dw = $parent->JListbox(-justify=>'center', -popupmenu=>1);
     $dw->pack;

DESCRIPTION
===========

   JListbox is identical to a Listbox, but has two addtional options:
-justify and -popupmenu.

-justify
........

   Possible values for '-justify' are 'left', 'center' and 'right'.  The
default is 'left'.  All text within the Listbox will be justified
according to the option you set.

   The widget automatically checks for variable or fixed width fonts and
adjusts accordingly.

   You cannot justify individual entries separately (as of version .02).

   Your text will remain justified appropriately, even if you set the
'-expand' and '-fill' options.

   The justification ability is provided via plain old pixel and character
counting (depending on whether you are using a variable or fixed width
font).  There have been no underlying changes in the C code to the Tcl
Listbox.

-popupmenu
..........

   If the -popupmenu option is used, a "Cut, Copy, Paste" menu will appear
when the user right-clicks anywhere on the JListbox.

   The "Cut" option will remove the item from the JListbox, copy it to the
clipboard and the remaining items will shift up automatically.

   The "Copy" option simply copies the selected value to the clipboard.

   The "Paste" option, if selected, will bring up a Dialog window that
gives the user the option to paste (insert) above or below the selected
item, as well as on the same line, either to the left or right of the
selected item.

   One whitespace character is automatically separates the pasted value if
the 'left' or 'right' option is chosen.

   If you wish to modify the popup menu itself, you can retrieve it using
the Subwidget method with 'popupmenu' as the widget name.

   $menu = $dw->Subwidget('popupmenu');

KNOWN BUGS
==========

   If using a variable width font, you may encounter a problem with the
last character disappearing off the right side of the listbox when you use
right justify.  I think I fixed this, so let me know if you have any
problems.

   If the text you insert into the listbox includes characters that have
special meaning in regular expressions (e.g. '*', '?'), you will need to
escape them using the '\' character or your app may crash.

   e.g. $dw->insert('end', "What did you say\?");

PLANNED CHANGES
===============

   Fix the regular expression issue mentioned above.

   Allow individual entries to be justified.

   Add the 'addMenuItem' and 'deleteMenuItem' methods to allow greater
configurability of the right-click menu.

AUTHOR
======

   Daniel J. Berger djberg96@hotmail.com

   Thanks goes to Damion K. Wilson for his help with creating widgets.

SEE ALSO
========

   Listbox

SGIPerl extension for grabbing video, modifying images and display images
*************************************************************************

NAME
====

   Jail - SGIPerl extension for grabbing video, modifying images and
display images

SYNOPSIS
========

   `use Jail;'

   `$font = openBDF Font ("helvetica50.bdf");' `if ($font->getStatus) {' `
  print $font->getErrorString() . "\n";' `    exit(1);' `}'

   `$dateStr = localtime(time);' `$glArray =
$font->`getText("$dateStr",$count)';' `$glyph   = merge Glyph ($glArray,
$count);'

   `$glyph->setForeground(255,255,255,0);'

   `$jg = new JailGlyph();' `$jg->addGlyph($glyph);' `if
($jg->getStatus()) {' `    print $jg->getErrorString() . "\n";' `
exit(1);' `}'

   `$imgStream = new JailArray();' `if (!$imgStream->getVideoStream(2)) {'
`    $imgStream->printError();' `    exit(1);' `}'

   `$image = $imgStream->pop();'

   `$wi = $image->getWidth();' `$hi = $image->getHeight();' `$wg =
$jg->getWidth();' `$hg = $jg->getHeight();'

   `if (!$jg->blittInImage($image, $wi - $wg, $hi - $hg)) {' `    print
"BLITT1: ";' `    print $jg->getErrorString() . "\n";' `    print
$image->getErrorString() . "\n";' `    exit(1);' `}
C<$image->blur(180,5,5);' `$image->rotateZoom(45, 0.6, 0.6);' ` C<if
(!$image->save("/tmp/jail_2.sgi","SGI")) {' `    $image->printError();' `
 exit(1);' C<}

   `$image = $imgStream->pop();' `$image->sharp(2.5);' `$wi =
$image->getWidth();' `$hi = $image->getHeight();'

   `if (!$jg->blittInImage($image, $wi - $wg, $hi - $hg)) {' `    print
"BLITT2: ";' `    print $jg->getErrorString() . "\n";' `    print
$image->getErrorString() . "\n";' `    exit(1);' `} C<if
(!$image->save("/tmp/jail_1.gif","GIF")) {' `    $image->printError();' `
 exit(1);' `}'

DESCRIPTION
===========

     Jail - Just an_other Image Library

     This extension is running _only_ on SGI IRIX systems. You need the
     Image Vision Library, Video Library and STL.
     You need a X11 Display _only_ if you want to display an image.

     The newest version you can get under http://www.artcom.net/~karo/Jail/.
     You can get there also a precompiled version.

CLASS INTERFACE
===============

   A 'better' documentation are may be the examples.

Exported functions and flags
============================

     The package C<Jail> exports the following functions

Jail Object
-----------

new Jail(...)
load(filename)
     Load an existing image. The method guesses the right file type.

save(filename, imgFormat)
     Save this image with a given filename. The imgFormat is one of the
     supported file formats from the *Image Vision Library*. Have a look
     under `File Formats' or execute the *imgformats* command.

saveFile(filehandle, imgFormat)
     Save this image to a already opened filehandle. For the imgFormat see
     above.  This function works only for the GIF format. The *IL* seeks
     during saving on the filedescriptor, I try to get the *IL* output
     over a pipe. That does not work. YET

getWidth()
     Returns the width of the image in pixels.

getHeight()
     Returns the height of the image in pixels.

getChannels()
     Returns for the image the amount of channels.

getImageFormatName()
     This method is usefull if you have loaded an image. So you can get
     the file format for that image.

copyTile(destX, destY, width, height, srcImage, srcX, srcY)
     Copy a tile from `srcImage' with the given coord. to this image.

add(addImg, [bias])
     Add a image logical to this image.

setPixel(x,y, r,g,b,[a])
     Set a pixel with the given color

duplicate()
     Get a copy of this image.

getVideoSnapshot()
     Get a image from the default video input.  See also videoin(1) and
     videopanel(1).

rotateZoom(angle, zoomX, zoomY, [resample])
     Rotate this image with a given angle. And/Or zoom this image.   0 <=
     angle < 360  0.0 < zoomFactor <= 1.0 See also ilRotZoomImg(3)

blur(blur, width, height, [bias], [edgeMode])
     This method blurs an image by convolving it with a 2D gaussian kernel.
     Parameter:   blur         : the degree of blur   width,height : the
     kernel size

     See also ilGBlurImg(3)

sharp(sharpness, [radius], [edgeMode])
     This method sharpens the source image, by convolving it with a special
     sharpening kernel.  The size of the kernel and the degree of sharpness
     can be controlled by the radius and sharpness parameters.

     See also ilSharpenImg(3)

compass(angle, [bias], [kernSize], [edgeMode])
     This method performs a directional gradient transform of the image.
     This is similar to doing a first derivative operation in the
     direction of the gradient.  Given a direction, a square kernel is
     generated and then the source image is convolved with this kernel.  A
     kernel size and additive bias can be supplied.

     See also ilCompassImg(3)

laplace([bias], [edgeMode], [kern])
     This method performs a 2D convolution on an image using one of two
     predefined 3x3 Laplacian kernels. The resulting image is
     edge-enhanced.

     kern := 1 | 2

     See also ilLaplaceImg(3)

edgeDetection([biasVal], [edgeMode])
     This method performs two orthogonal 2D convolutions on an image using
     two predefined 2x2 Roberts kernels. The resulting image is edge
     enhanced.

     See also ilRobertsImg(3)

blendImg(doImg, alphaValue | alphaImg,[compose])
     This method takes an other image which will be blend into this image.
     If you specify the alphaValue indicate thatthe alpha values are to be
     taken from the alpha channel of the foreground and background images.
     The alpha pixels are normalized to the range (0.0-1.0), based on the
     minimum and maximum pixel values of the foreground and background
     images.  If you specify an alphaImg the first channel of that is
     interpreted as alpha channel for the blending.

     See also ilBlendImg(3)

display()
     This displays the image in a window.. damn this is totaly buggy

printError()
getStatus()
     Normaly the return value is 0. Otherwise an error occured.

getErrorString()
JailArray Object
----------------

new JailArray
size()
     Returns the amount of images.

push(Jail)
     Push an image to the end of the array.

Jail pop()
     Pops and returns the last image in the array.

Jail shift()
     Shifts the first image of the array off and returns it.

unshift(Jail)
     Prepends an other image to the front of the array.

loadIndexed(prefix,startSuffix,suffix,amount)
     Loads images with a given prefix, an additional number and a given
     suffix.  For Example:   prefix:      blub   startSuffix: 23   suffix:
         .gif   amount:      3

          So the method would load 3 images: blub23.gif, blub24.gif and blub25.gif

saveIndexed(prefix,startSuffix,suffix)
     Saves images with the same name convention as loadIndexed.

getVideoStream(amount)
     Get a videostream of `amount' images.

printError()
getStatus()
getErrorString()
Font Object
-----------

openBDF(filename)
     This static factory method loads a BDF font with the given filename
     and returns a Font Object. BDF stands for Glyph Bitmap Distribution
     Format.  See:
     http://www.adobe.com/supportservice/devrelations/typeforum/ftypes.html
     You can get BDF fonts from the X source or get them from your X
     server, have a look: fstobdf(1), xfontsel(1)

getText(text, countVar)
     This methods builds a GlyphArray Object from a given text. In the
     countVar Variable will be the amount of found Glyphs returned.

getCharsetEncoding()
     Returns the encoding value for the font.

getName()
     Returns the name.

getStatus()
getErrorString()
Glyph Object
------------

merge(GlyphArray, count)
     This static factory method returns a new Glyph Object which is build
     from the given GlyphArray.

setName(name)
     You set the Name for the Glyph object.

getName()
getEncoding()
     Get the char encoding for the Glyph. For a merged Glyph it is always
     0.

getBBXW()
     Get the width of the Bounding Box.

getBBXH()
     Get the height of the Bounding Box.

getBBXXO()
     Get the X coord. of the virtual point Zero of the BBX.

getBBXYO()
     Get the Y coord. of the virtual point Zero of the BBX.

setForeground(r,g,b,[a])
     Select a color for the foreground of the Glyph. Every '1' in the
     Glyph will be treated as foreground.If you select for 'a' color a
     255, the foreground will not be painted.

setBackground(r,g,b,[a])
     Select a color for the background of the Glyph. Every '0' in the
     Glyph will be treated as background.If you select for 'a' color a
     255, the background will not be painted.

getForegroundR()
getForegroundG()
getForegroundB()
getForegroundA()
getBackgroundR()
getBackgroundG()
getBackgroundB()
getBackgroundA()
print()
     This is for debuging. This prints the glyph in ascii.

GlyphArray Object
-----------------

JailGlyph Object
----------------

new JailGlyph()
addGlyph(glyph)
     This method collects Glyph objects.

createImg()
     This method returns a Jail object. The returned object depends on the
     added Glyphs.

blittInImage(img, x, y)
     This method expect a Jail object and a x and y coord. The added
     Glyphs will be rendered in the given Jail image.

getWidth()
     This returns the witdh, for that the JailGlyph will create a Imgage.
     Thats the same as:     $jailObj = $JailglyphObj->createImg();  ->>
     $jailObj->getWidth();

getHeight()
getCurX()
     Get the X coord of the virtual point zero.

getCurY()
printError()
getStatus()
getErrorString()
Special Parameter
-----------------

bias
     In general, bias is a constant value added to each pixel luminance
     value to make it scale correctly. If, for example, the raw pixel
     luminance covers values between 100 and 200, some operators are able
     to scale the luminance values over the entire depth of pixel
     luminance values, for example, 0 - 255.  When you scale the luminance
     values in this way, you need a bias value that adjusts the initial,
     raw luminance value, 100, in this example, to zero.

edgeMode
     Specifies how the neighborhood is defined for pixels at the edge of
     the image.  Have look at the EDGE_* Flags.

resample
     Determining the procedure used by IL to alter the geometric aspects
     of an image Have a look under Flags RT_*

kernSize
     SGI Docs: The kernel is the group or neighborhood of pixels used in
     calculations to sharpen or blur an image. Generally, the larger the
     kernel radius, the more pronounced the effect of either sharpening or
     blurring the image using the Enhance subpanel. However, using a
     larger kernel radius also results in a more time-consuming process.

compose
     arg, thats heavy to explain shortly please have look at ilBlendImg(3)
     and in /usr/include/il/ilTypes.h

Flags
-----

EDGE_NOPAD
     No padding is done, and the output image shrinks by the size of the
     kernel minus one in each dimension.

EDGE_PADSRC
     The edge of the input image is padded with the input images fill
     value so that a full-sized output image can be processed.

EDGE_PADDST
     Similar to ilNoPad, except that the output, images border is
     sufficiently padded with its fill value so that the final image is
     the same size as the source image.

EDGE_WRAP
     Sufficient data is taken from the opposite edge of the source image
     so that a full-sized output image can be processed.

EDGE_REFLECT
     Sufficient data near the edge of the image is reflected so that a
     full-sized output image can be processed without producing artifacts
     at the image edge.  This mode gives the best results for most
     operators.

RT_NEARNB
     Nearest, standing for Nearest Neighbor, works quickly but produces
     lower-quality results.

RT_BILINEAR
     Bilinear uses more complex, time-consuming methods than Nearest
     Neighbor, but produces higher-quality results.

RT_BIBUBIC
     Bicubic is more time-consuming than either Nearest Neighbor or
     Bilinear, but produces the best results.

     If you choose the Bicubic resampling method, you can also choose the
     specific Bicubic Family, each of which produces a somewhat different
     effect: B-Spline, which is the default option, produces smoother
     images.  Catmul produces more sharpening. Mitchell results in an
     effect between that of the other two.

RT_MINIFY
     The Minify method produces the best results if you are reducing the
     magnification of an image. Again, however, it is a more
     time-consuming process.

Image Formats
-------------

   See also imgformats(1)

PNG
     PNG implements the PNG file format using version 0.88 of the Portable
     Network Graphics library, libpng, and version 1.0 of the ZIP
     deflate/inflate compression library, libzlib.

GIF
     The GIF file format is used to read image files stored in the
     CompuServe Graphics Image File (GIF) format. GIF does not support
     paging. It stores images in palette-color-compressed using the
     Lempel-Ziv & Welch algorithmThe compression algorithm has become the
     focus of patent infringement litigation which has inspired the
     creation of a new image format to replace GIF. This new format is the
     Portable Network Graphics (PNG) image format. It is also supported by
     Jail.

RGB
SGI
     SGI is the first format defined by Silicon Graphics for storing image
     data. SGI files are typically stored in files suffixed by .bw, .rgb,
     .rgba, .sgi, or .screen. SGI files support full color, color palette,
     and monochrome images of either one or two bytes per color component.
     Image data can be stored in either raw form or run-length encoding
     (RLE) compression. You can create SGI files with RLE compression but
     you cannot later rewrite a portion of a compressed SGI file.

TIFF
     The TIFF file format, created by Aldus Corporation, is an extended
     version of the Tag Image File Format, using version 3.4beta24 of Sam
     Lefflers TIFF library, libtiff. This library implements version 6.0
     of the TIFF specification.

JFIF
     JFIF implements the JPEG file format using the JPEG library, libjpeg,
     made available by the Independent JPEG Group. In addition to
     providing the IFL image I/O abstraction, the entire JPEG library is
     provided as is for use by software that has been developed for use
     with libjpeg.

PPM
     PPM, PGM, and PBM implement the PPM, PGM, and PBM file formats using
     release 7, December 1993 of the NETPBM libraries, libppm, libpgm, and
     libpbm.

Alias
     The Alias file format supports both variations of the format: 8-bit
     RGB  and 8-bit matte.

SOFTIMAGE
     The SOFTIMAGE file format supports reading all types of image files
     and writes only mixed RLE compressed. There is no current support for
     depth buffer files or rendered subregions.

YUV
     The YUV file format is the standard 8-bit 4:2:2 (YUV) format used by
     the Sirius board and almost all digital disk recorders ( Abekas,
     Accom etc ).

PCD
     The PCD file format supports image files produced by the Kodak Photo
     CD system.  Photo CD establishes a system for storing
     high-resolution, digital photographic images on compact discs.

PCDO
     Every Kodak Photo CD contains a file in the Kodak Photo CD Overview
     Pac format.  This format contains a low resolution representation of
     each image on the Photo CD.

FIT
Todo
----

search for memory leaks
     There is a small memory leak somewhere in the save routine. Do not
     know if it is in my or in the SGI IL routines.

thrash hold
     add a thrash hold operator

more filter

Bit dithering
add some primitive geometry painting
Display
     The display object is _VERY_ buggy and not finished yet.

Jail::saveFile() can only save GIF\'s and JPG\'s
     Thats a SGI IFL Bug.

GIF -> GIF improvement
     The Problem is the IL core dumpes if I am trying to copy a GIF. So i
     have to convert GIF->RGB->GIF.

documentation
     Write a better documentation

BUGS
====

     Oh, yes there are some. Especially in the display routine.
     Please, please, please, send me a short note if you found a bug.

AUTHOR
======

     This module has been written by Benjamin Pannier (B<karo@artcom.net>).

SEE ALSO
========

   http://www.artcom.net/~karo/Jail/ perl(1), il(3), ifl(3), vl(3)

Perl extension for accessing a JVM remotely or locally
******************************************************

NAME
====

   Java - Perl extension for accessing a JVM remotely or locally

SYNOPSIS
========

     use Java;
     $java = new Java;
     $frame = $java->create_object("java.awt.Frame","Frame's Title");
     $frame->setSize(400,400);
     $frame->show();
     $java->do_event($frame,"addWindowListener",\&event_handler);

     $array = $java->create_array("java.lang.String",5);
     // Set array element 3 to "Java is lame"
     $array->set_field(3,"Java is lame");
     $element = $array->get_field(3)->get_value();

     $button = $java->create_object("java.awt.Button","Push Me");
     // Listen for 'Action' events from $button object
     $java->do_event($button,"addActionListener",\&event_handler);

     // Loop & wait mode
     while(1)
     {
          my $continue = $java->go;
          last if (!defined $continue);
     }

     // Got an event!
     sub event_handler
     {
     	my($object_that_caused_event,$event_object) = @_;
           if ($object_that_caused_event->same($button))
     	{
     		// From $button!
     		print "You pushed my button!!\n";
     	}
     }

DESCRIPTION
===========

   This module allows you to talk to a JVM on a local or remote machine.
You can create objects, call functions, access fields, deal with arrays,
get events & all the nonsense you can do in Java - from Perl!

Starting a JVM server
---------------------

   First you must run 'JavaServer' on the machine to which you will make
connections.  Simply to a 'java JavaServer' to start the server.  By
default it will start listening on port 2000.  Make sure the
'JavaServer.jar' is in your classpath - also make sure the Swing stuff
(JFC if you prefer) is in your classpath as well if you want to use Swing
stuff (note this does not apply to JVM 1.2+).

Creating the root Java object
-----------------------------

   You connect to a remote (or local) JVM when you create a new Java
instance.  The new call accepts a hash with the following keys:

     host => hostname of remote machine to connect to
     		default is 'localhost'
     port => port the JVM is listening on (JavaServer)
     		default is 2000
     event_port => port that the remote JVM will send events to
     		default is 2001

   For example:

     $java = new Java(host => "java.zzo.com", event_port => 4032);
     $java2 = new Java(port => 8032);

   You can have any number of java 'environments' in a Perl program.

   Also if you 'use strict' you must do a 'no struct 'subs" 'cuz all Java
method calls are AUTOLOAD'ed - sorry.

Creating java primitives
------------------------

   The Java.pm module will treat all integers encountered in parameter
lists as integer and strings as java Strings.  All other primitive types
must be suffixed with an identifier so Java.pm knows what primitive Java
type to convert it to - for instance boolean types are tagged like:
"true:b" or "false:b"

   Here's a complete list of supported Java primitives:

     Perl String Value  -> (converted to) -> Java Primitive
     -----------------			--------------
     2344					int
     "23:short"				short
     "23:byte"				byte
     "a:char"				char
     "23445:long"				long
     "3.42:float"				float
     "3.14159:double"			double
     "true:b" or "false:b"			boolean
     "Anything else"				String
     	or
     "Anything else:string"			String

   So... if you need to use an integer as a String say "343:string".

Localization and String encoding
--------------------------------

   Quick note on String encodings, you can specify that your strings are
encoded in a specific format using the ":string_<ENCODING>" syntax like:

     my $label = $java->create_object("java.awt.Label","Label:string_UTF8");

   This specifies that this String uses Unicode encoding.  See
http://www.javasoft.com/products/jdk/1.1/docs/guide/intl/encoding.doc.html
for the complete list of valid Java String encodings.

Creating java objects
---------------------

   Once you've connected to a JVM via the 'new Java' call you can start
creating Java objects.  This is accomplished via the 'create_object'
function.  The first argument must be the 'fully-qualified'/'full path' of
the Java object you want to create - like 'java.lang.String' or
'java.awt.Frame'.  The remaining arguments are passed to that object's
constructor.

   For example:

     my $frame = $java->create_object("java.awt.Frame","Frame Title");
     my $dialog = $java->create_object("java.awt.Dialog",$frame,
     		"Dialog Title","true:b");

   Note the use of "true:b" in the constructor to tell Java.pm that that
value should be a 'true' Java boolean value.

   In these cases a 'java.awt.Frame' takes a String as the lone parameter,
whereas a 'java.awt.Dialog' takes a Frame, a String, and a boolean value
in its constructor.

Calling java methods
--------------------

   You can make both static and instantiated method calls on java objects.
The parameter lists work exactly like constructor parameter lists - if you
want to pass a java primitive anything other than integers or Strings need
to be tagged accordingly.  All function calls that return something return
a java object - so even if the java function returns an 'int' it is
returned to perl as a 'java.lang.Integer'.  To get the value of that
Integer you must use the 'get_value' function.  The syntax is exactly what
you'd expect (I hope!).

   For example:

     $frame->setSize(200,500);
     $frame->show();  (or $frame->show)

   Note functions that don't take any parameters don't need the
parentheses!

     To call static functions the syntax is slightly different.

   For example:

   To call the static method 'forName' in the object 'java.lang.Class' it
looks like this:

     my $class = $java->java_lang_Class("forName","Test");

   Note you use the '$java' object returned from the call to 'new Java' to
access static methods - the static object must be fully-qualified
separated by '_'s instead of '.'s.  And finally the first parameter is the
name of the static function followed by any parameters to it.

   If your static class is NOT in a package you MUST use the 'static_call'
function like:

     my $return_value = $java->static_call("MyStaticClass","<function_name>",@params);

Getting and Setting java object fields
--------------------------------------

   You can get and set individual fields in java objects (static or
instantiated) using the 'get_field' and 'set_field' methods.  All
'get_field' calls return java objects just like calling java functions.
You must use the 'get_value' function to 'unwrap' primitive types to their
actual values.

   For example:

   Get a static field

     my $win_act = $java->get_field("java.awt.event.WindowEvent",
     					"WINDOW_ACTIVATED");

   Note the first parameter must be the fully qualified java object name
and the second parameter is the static field.

   Get an instantiated field

     my $obj = $java->create_object("java.my.Object");
     my $field = $obj->get_field("my_field");

   Similarly to set a field another parameter is added to the 'set_field'
call with the object that the specified field is to be set to:

   Set a static field

     $java->set_field("java.static.Object","field_name",$obj);

   Set an instantiated field

     $obj->set_field("integer_field_name",400);

Exceptions
----------

   Currently Java.pm will 'croak' when an Exception is encountered in
JavaServer.  So the way to deal with them is to enclose your Java
expression that might throw an exception in an 'eval' block & then check
the $@ variable to see if an Exception was indeed thrown.  You then need
to parse the $@ variable to see exactly what Exception was thrown.
Currently the format of the $@ string is:

     ERROR: java.lang.Exception: some.java.Exception: <more info> at $0 line XX

   Note the '<more info>' part is the result of the getMessage() function
of that Exception.  Everything after that is the stuff put in there by
croak; the filename & line number of your Perl program.  So here's what an
Exception handler can look like:

     my $I;
     eval
     {
     	$I = $java->java_lang_Integer("parseInt","$some_string:string");
     };
     if ($@)
     {
     	# An exception was thrown!!
     	$@ =~ s/ERROR: //;	# Gets rid of 'ERROR: '
     	$@ =~ s/at $0.*$//;	# Gets rid of 'croak' generated stuff

     # Print just the Java stuff
     print "$@\n";

     }

   So in this example if the scalar $some_string did NOT contain a parsable
integer - say 'dd' - the printed error message would be:

     java.lang.Exception: java.lang.NumberFormatException: dd

Comparing Java objects
----------------------

   You can see if two references to java objects actually point to the same
object by using the 'same' function like:

     if ($object1->same($object2))
     {
     	# They're the same!
     }
     else
     {
     	# Nope, not the same
     }

   You'll see why this is useful in the next section 'Events'.

Events
------

   Events are passed from the remote JVM to Perl5 via a separate event
port.  To enable events on an object use the 'do_event' function.  Your
callback function will receive the object that caused the event as its
first parameter and the event object itself as the second parameter.
Here's where ya wanna use the 'same' function to see what object caused
this event if you set up multiple objects to call the same event function.

   For example:

     my $frame = $java->create_object("java.awt.Frame","Title");
     $java->do_event($frame,"addWindowListener",\&event_handler);
     my $button = $java->create_object("java.awt.Button","Push Me");
     $java->do_event($button,"addActionListener",\&event_handler);

   To stop listening for events do:

     $java->do_event($frame,"removeWindowListener");

   Where: - $frame is the object for which you'd like to receive events -
"addWindowListener" specifies the types of events you want to listen for -
\&event_handler is your event callback routing that will handle these
events

   You will keep receiving events you registered for until you make a
"remove" call or your Java object goes away (out of scope, you destroy it,
whatever).

   Note the second parameter MUST be of the form:

     "<add | remove><Event Type>Listener"

   Default <Event Types> are:

     Component
     Container
     Focus
     Key
     Mouse
     MouseMotion
     Window
     Action
     Item
     Adjustment
     Text

   Swing <Event Types> are:

     Ancestor
     Caret
     CellEditor
     Change
     Hyperlink
     InternalFrame
     ListData
     ListSelection
     MenuDragMouse
     MenuKey
     Menu
     PopupMenu
     TreeExpansion
     TreeSelection
     TreeWillExpand

   And within most of these <Event Types> there are a number of specific
events.  Check out the Java event docs if you don't know what I'm talking
about...

   Here's what an event handler looks like:

   	sub event_handler 	{ 		my($object,$event) = @_; 		if ($object->same($frame))
{ 			# Event caused by our frame object!

   			# This will get this event's ID value 			my $event_id =
$event->getID->get_value;

     # Get value for a WINDOW_CLOSING event
     my $closing_id = $java->get_field("java.awt.event.WindowEvent","WINDOW_CLOSING")->get_value;

     if ($event_id == $closing_id)
     {
     	# Close our frame @ user request
     	$object->dispose;
     }
     		}
     		if ($object->same($button))
     		{
     print "You Pushed My Button!\n";
     		}
     	}

   Note return values from event handlers are ignored by Java.pm BUT are
returned from the Event Loop as you'll see in a bit.

   Note also how I had to call 'get_value' to get the actualy integer
values of the 'getID' function return value and the field value of
WINDOW_CLOSING.

Event Loops
-----------

   Once you've set up your event handlers you must start the event loop to
begin getting events - there are two ways to do this.

     1. Have Java.pm handle the event loop
     2. Roll your own.

   Java.pm's event loop will block until an events happens - typically this
is what you want but sometimes you might want more control, so I've decided
to be nice this _one_ time & let you roll your own too.

   Here's how Java.pm's event loop works for ya:

     #
     # Set up a bunch of events...
     #

     while(1)
     {
     	my $cont = $java->go;
     	last if (!defined $cont);
     }

   Note this works similarly to Tk's event loop.  Your program will now
just sit & respond to events via your event handlers.  Also note that
Java.pm's event loop only handles ONE event & then returns - the return
value is whatever your event handler returned OR undef if there was an
error (like you lost yer connexion to the JVM).

   Here's how you can create yer own Event Loop:

   You ask Java.pm for a FileHandle that represents the incoming event
stream.  You can then select on this FileHandle or do whatever else you
want - remember this is a READ ONLY FileHandle so writing to it ain't
going to do anything.  Once you get a 'line' from this FileHandle you can
(and probably should) call 'decipher_event' & the event will be dispatched
to your event handler appropriately - the return value being the return
value of your event handler.  This can look something like this:

     ## Roll my own event loop

     # Get event FileHandle
     my $event_file_handle = $java->get_event_FH;

     # Set up my select loop
     my $READBITS = 0;
     vec($READBITS,$event_file_handle->fileno,1) = 1;

     # Suck in lines forever & dispatch events
     while(1)
     {
     	my $nf = select(my $rb = $READBITS,undef,undef,undef);
     	if ($nf)
     	{
     		my $event_line = <$event_file_handle>;
     		$java->decipher_event($event_line);
     	}
     }

   Note this example is EXACTLY what Java.pm's 'go' function does - if you
roll yer own Event Loop you prolly want to do something more interesting
than this!

   The upshot is you'll probably just want to use the 'go' function but if
you've got some other FileHandles going on & you don't want to block on
just this one you can (and should) use the 'roll your own' method.

Getting values
--------------

   To 'unwrap' java primitives (including Strings) you need to call the
'get_value' function.  This will stringify any object given to it -
typcially this is only useful for 'unwrapping' java primitives and Strings.

   For example:

     my $string1 = $java->create_object("java.lang.String","Mark");
     my $string2 = $java->create_object("java.lang.String","Jim");

     if ($string1 eq $string2)
     {
     	# WRONG!!!
     	# $string1 & $string2 are objects!
     }

     if ($string1->get_value eq $string2->get_value)
     {
     	# RIGHT!!!
     	# now you're comparing actual strings...
     }

     =head2 Arrays

   Arrays are created with the 'create_array' function call.  It needs a
fully-qualified java object or primitive name and a dimension.

   For example:

     # This will create a char array with 100 elements
     my $char_array  = $java->create_array("char",100);

     # This will create a String array with 5 elements
     my $string_array = $java->create_array("java.lang.String",5);

     Array elements are get and set using the 'get_field' and 'set_field' function calls.

   For example:

     # Set element #22 to 'B'
     # Don't forget on primitive arrays to use the ':' notation!
     $char_array->set_field(22,"B:char");

     # Set element #3 to 'Mark Rox'
     $string_array->set_field(3,"Mark Rox");

     # Get element #99
     my $element_99 = $char_array->get_field(99);

     # Get element #4
     my $element_4 = $string_array->get_field(4);

     # Don't forget to get the actual string value you gotta call
     #	'get_value'!
     my $char_value = $char_element_99->get_value;
     my $string_value = $string_element_4->get_value;

   To get the length of an array use the get_length function.

   For example:

     my $length = $string_array->get_length;

   Note this will return an actual integer!  You do not need to call
'get_value' on 'get_length's return value!

EXPORT
------

   None by default.

AUTHOR
======

   Mark Ethan Trostler, mark@zzo.com

SEE ALSO
========

   perl(1).  http://www.javasoft.com/.  Any sorta Java documentation you
can get yer hands on!  http://www.zzo.com/Java/getit.html

Japanese Charset Handler
************************

NAME
====

   Jcode - Japanese Charset Handler

SYNOPSIS
========

     use Jcode;

     # traditional
     Jcode::convert(\$str, $ocode, $icode, "z");
     # or OOP!
     print Jcode->new($str)->h2z->tr($from, $to)->utf8;

DESCRIPTION
===========

   Jcode.pm supports both object and traditional approach.  With object
approach, you can go like;

   $iso_2022_jp = Jcode->new($str)->h2z->jis;

   Which is more elegant than;

   $iso_2022_jp = &jcode::convert(\$str,'jis',jcode::getcode(\str), "z");

   For those unfamiliar with objects, Jcode.pm still supports getcode()
and convert().

Methods
=======

   Methods mentioned here all return Jcode object unless otherwise
mentioned.

$j = Jcode->new($str [, $icode]);
     Creates Jcode object $j from $str.  Input code is automatically
     checked unless you explicitly set $icode. For available charset, see
     `getcode()' in this node below.

     The object keeps the string in EUC format enternaly.  When the object
     itself is evaluated, it returns the EUC-converted string so you can
     "print $j;" without calling access method if you are using EUC
     (thanks to function overload).

Passing Reference
     Instead of scalar value, You can use reference as

     Jcode->new(\$str);

     This saves time a little bit.  In exchange of the value of $str being
     converted. (In a way, $str is now "tied" to jcode object).

$j->set($str [, $icode]);
     Sets $j's internal string to $str.  Handy when you use Jcode object
     repeatedly (saves time and memory to create object).

          # converts mailbox to SJIS format
          my $jconv = new Jcode;
          while(&lt;&gt;){
              print $jconv->set(\$_)->mime_decode->sjis;
          }

$j->append($str [, $icode]);
     Appends $str to $j's internal string.

$j = jcode($str [, $icode]);
     shortcut for Jcode->new() so you can go like;

     $sjis = jcode($str)->sjis;

$euc = $j->euc;
$jis = $j->jis;
$sjis = $j->sjis;
     What you code is what you get :)

$iso_2022_jp = $j->iso_2022_jp
     Same as $j->z2h->jis.  Hankaku Kanas are forcibly converted to
     Zenkaku.

[@lines =] $jcode->jfold([$bytes_per_line, $newline_str]);
     folds lines in jcode string every $bytes_per_line (default: 72) in a
     way that does not clobber the multibyte string.  (Sorry, no Kinsoku
     done!)  with a newline string spified by $newline_str (default: \n).

Methods that use MIME::Base64
-----------------------------

   To use methods below, you need MIME::Base64.  To install, simply

     perl -MCPAN -e 'CPAN::Shell->install("MIME::Base64")'

$mime_header = $j->mime_encode([$lf, $bpl]);
     Converts $str to MIME-Header documented in RFC1522.  When $lf is
     specified, it uses $lf to fold line (default: \n); When $bpl is
     specified, it uses $bpl for the number of bytes (default: 76);

$j->mime_decode;
     Decodes MIME-Header in Jcode object.

     You can retrieve the number of matches via $j->nmatch;

Methods implemented by Jcode::H2Z
---------------------------------

   Methods below are actually implemented in Jcode::H2Z.

$j->h2z([$keep_dakuten]);
     Converts X201 kana (Hankaku) to X208 kana (Zenkaku).  When
     $keep_dakuten is set, it leaves dakuten as is (That is, "ka +
     dakuten" is left as is instead of being converted to "ga")

     You can retrieve the number of matches via $j->nmatch;

$j->z2h;
     Converts X208 kana (Zenkaku) to X201 kana (Hankazu).

     You can retrieve the number of matches via $j->nmatch;

Methods implemented in Jcode::Tr
--------------------------------

   Methods here are actually implemented in Jcode::Tr.

$j->tr($from, $to);
     Applies tr on Jcode object. $from and $to can contain EUC Japanese.

     You can retrieve the number of matches via $j->nmatch;

Methods implemented in Jcode::Unicode
-------------------------------------

   If your perl does not support XS (or you can't `perl Makefile.PL',
Jcode::Unicode::NoXS will be used.

   See Jcode/Unicode, and Jcode/Unicode/NoXS,
for details

$ucs2 = $j->ucs2;
     Returns UCS2 (Raw Unicode) string.

$ucs2 = $j->utf8;
     Returns utf8 String.

Instance Variables
------------------

   If you need to access instance variables of Jcode object, use access
methods below instead of directly accessing them (That's what OOP is all
about)

   FYI, Jcode uses a ref to array instead of ref to hash (common way) to
optimize speed (Actually you don't have to know as long as you use access
methods instead;  Once again, that's OOP)

$j->r_str
     Reference to the EUC-coded String.

$j->icode
     Input charcode in recent operation.

$j->nmatch
     Number of matches (Used in $j->tr, etc.)

Subroutines
===========

($code, [$nmatch]) = getcode($str);
     Returns char code of $str. Return codes are as follows

          ascii   Ascii (Contains no Japanese Code)
          binary  Binary (Not Text File)
          euc     EUC-JP
          sjis    SHIFT_JIS
          jis     JIS (ISO-2022-JP)
          ucs2    UCS2 (Raw Unicode)
          utf8    UTF8

     When array context is used instead of scaler, it also returns how many
     character codes are found.  As mentioned above, $str can be \$str
     instead.

jcode.pl Users:
     This function is 100% upper-conpatible with jcode::getcode() - well,
     almost;

          * When its return value is an array, the order is the opposite;
            jcode::getcode() returns $nmatch first.

          * jcode::getcode() returns 'undef' when the number of EUC characters
            is equal to that of SJIS.  Jcode::getcode() returns EUC.  for
            Jcode.pm is no in-betweens.

Jcode::convert($str, [$ocode, $icode, $opt]);
     Converts $str to char code specified by $ocode.  When $icode is
     specified also, it assumes $icode for input string instead of the one
     checked by getcode(). As mentioned above, $str can be \$str instead.

jcode.pl Users:
     This function is 100% upper-conpatible with jcode::convert() !

BUGS
====

Unicode support by Jcode is far from efficient!
ACKNOWLEDGEMENTS
================

   This package owes a lot in motivation, design, and code, to the jcode.pl
for Perl4 by Kazumasa Utashiro <utashiro@iij.ad.jp>.

   Hiroki Ohzaki <ohzaki@iod.ricoh.co.jp> has helped me polish regexp from
the very first stage of development.

   And folks at Jcode Mailing list <jcode5@ring.gr.jp>.  Without them, I
couldn't have coded this far.

SEE ALSO
========

Jcode/Unicode
See Jcode/Unicode/NoXS,
COPYRIGHT
=========

   Copyright 1999 Dan Kogai <dankogai@dan.co.jp>

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Aux. routines for Jcode
***********************

NAME
====

   Jcode::Unicode - Aux. routines for Jcode

SYNOPSIS
========

   NONE

DESCRIPTION
===========

   This module implements following subs as XS.  Used via Jcode.pm.

   This module is called by Jcode.pm on demand.  This module is not
intended for direct use by users.  This modules implements functions
related to Unicode.  Following functions are defined here;

Jcode::ucs2_euc();

Jcode::euc_ucs2();

Jcode::ucs2_utf8();

Jcode::utf8_ucs2();

Jcode::euc_utf8();

Jcode::utf8_euc();
VARIABLES
=========

$Jcode::Unicode::PEDANTIC
     When set to non-zero, x-to-unicode conversion becomes pedantic.  That
     is, '\' (chr(0x5c)) is converted to zenkaku backslash and '~"
     (chr(0x7e)) to JIS-x0212 tilde.

     By Default, Jcode::Unicode leaves ascii ([0x00-0x7f]) as it is.

BUGS
====

   If any, that is Unicode, Inc. to Blame (Especially JIS0201.TXT).

SEE ALSO
========

http://www.unicode.org/
COPYRIGHT
=========

   Copyright 1999 Dan Kogai <dankogai@dan.co.jp>

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Unicode conversion table used here are based uponon files at
ftp://ftp.unicode.org/Public/MAPPINGS/EASTASIA/JIS/, Copyright (c)
1991-1994 Unicode, Inc.

UCS2-EUC conversion table
*************************

NAME
====

   Jcode::Unicode::Constants - UCS2-EUC conversion table

SYNOPSIS
========

   NONE

DESCRIPTION
===========

   This module just contains a huge hash that converts UCS2 from/to EUC.

SEE ALSO
========

ftp://ftp.unicode.org/Public/MAPPINGS/EASTASIA/JIS/
     Unicode mapping data

COPYRIGHT
=========

   Copyright 1999 Dan Kogai <dankogai@dan.co.jp>

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Unicode conversion table here is based on files at
ftp://ftp.unicode.org/Public/MAPPINGS/EASTASIA/JIS/, Copyright (c)
1991-1994 Unicode, Inc.

Non-XS version of Jcode::Unicode
********************************

NAME
====

   Jcode::Unicode::NoXS - Non-XS version of Jcode::Unicode

SYNOPSIS
========

   NONE

DESCRIPTION
===========

   This module is called by Jcode.pm on demand.  This module is not
intended for direct use by users.  This modules implements functions
related to Unicode.  Following functions are defined here;

Jcode::ucs2_euc();

Jcode::euc_ucs2();

Jcode::ucs2_utf8();

Jcode::utf8_ucs2();

Jcode::euc_utf8();

Jcode::utf8_euc();
VARIABLES
=========

$Jcode::Unicode::PEDANTIC
     When set to non-zero, x-to-unicode conversion becomes pedantic.  That
     is, '\' (chr(0x5c)) is converted to zenkaku backslash and '~"
     (chr(0x7e)) to JIS-x0212 tilde.

     By Default, Jcode::Unicode leaves ascii ([0x00-0x7f]) as it is.

MODULES
=======

Jcode::Unicode::Constants
     Jumbo hash that contains UCS2-EUC conversion table is there.

BUGS
====

     * It's very slow to initialize, due to the size of the conversion
       table it has to load.  Once loaded, however, the perfomance is not
       too bad (But still much slower than XS version).
     * Besides that, that is Unicode, Inc. to Blame (Especially JIS0201.TXT).

SEE ALSO
========

http://www.unicode.org/
COPYRIGHT
=========

   Copyright 1999 Dan Kogai <dankogai@dan.co.jp>

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Unicode conversion table used here are based uponon files at
ftp://ftp.unicode.org/Public/MAPPINGS/EASTASIA/JIS/, Copyright (c)
1991-1994 Unicode, Inc.

collection of modules useful in Kite design and construction.
*************************************************************

NAME
====

   Kite - collection of modules useful in Kite design and construction.

SYNOPSIS
========

     use Kite;

     my $profile = Kite->profile(...)
     	|| die $Kite::ERROR;

     my $xml2ps = Kite->xml2ps(...)
         || die $Kite::ERROR;

     my $xml_parser = Kite->xml_parser(...)
         || die $Kite::ERROR;

DESCRIPTION
===========

   The Kite::* modules are a collection of Perl modules and scripts
written to help with various tasks in the design and construction of
traction kites.

   The Kite module acts as a general interface to the other modules in the
collection, providing factory methods for loading and instantiating them.

METHODS
=======

profile()
---------

   Loads the Kite::Profile module and calls the new() constructor.  All
parameters are forwarded to the constructor.

   This example:

     use Kite;

     my $profile = Kite->profile( name => 'My Profile', ... )
         || die $Kite::ERROR, "\n";

   is equivalent to:

     use Kite::Profile;

     my $profile = Kite::Profile->new( name => 'My Profile', ... )
         || die $Kite::Profile::ERROR, "\n";

xml2ps()
--------

   Loads the Kite::XML2PS module and calls the new() constructor.  All
parameters are forwarded to the constructor as per the previous example.

xml_parser()
------------

   Loads the Kite::XML::Parser module and calls the new() constructor.  All
parameters are forwarded to the constructor as per the previous examples.

MODULES
=======

   The following modules are distributed with the Kite bundle.

Kite
----

   Front-end for the Kite::* modules.  Contains factory methods for loading
modules and instantiating objects of other Kite::* classes.

Kite::Base
----------

   Base class implementing common functionality such as error reporting.

Kite::Profile
-------------

   Module defining an object class used to represent and manipulate 2D
profiles.

Kite::XML2PS
------------

   Module to convert a curve definition from OpenKite XML format to
PostScript.  Provides automatic page tiling, path following text,
registration marks, etc.

Kite::XML::Parser
-----------------

   Module for parsing an XML file and generating a representative tree of
node (element) objects.

Kite::XML::Node
---------------

   Base class for XML element nodes created by Kite::XML::Parser.

Kite::XML::Node::Kite
---------------------

   Derived node elements specific to Kite markup (e.g. Kite, Part,
Outline, Curve, Point, etc.)

Kite::PScript::Defs
-------------------

   Module defining a number of PostScript definitions useful for
generating PostScript documents for kite part layout, etc.

SCRIPTS
=======

   The following scripts are distributed with the Kite bundle.

okprof
------

   Utility script providing a user interface to the Kite::Profile module.
Allows 2D profiles to be loaded and manipulated via simple commands.  See
'*perldoc okprof*' or '*okprof -h*'.

okxml2ps
--------

   Utility script for converting XML kite part definition and layout
markup to PostScript.  Uses the Kite::XML2PS module.

AUTHORS
=======

   Andy Wardley <abw@kfs.org> is the primary author and current maintainer
of the Kite::* bundle.

   Simon Stapleton <simon@tufty.co.uk> is another key contributor.

VERSION
=======

   This is version 0.4 of the Kite bundle.

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   See also Kite/Profile, Kite/XML2PS,
see Kite/XML/Parser,
Kite/XML/Node, Kite/XML/Node/Kite,
see Kite/PScript/Defs,
Kite/Base, `okprof' in this node and `okxml2ps' in this node.

base class module implementing common functionality
***************************************************

NAME
====

   Kite::Base - base class module implementing common functionality

SYNOPSIS
========

     package Kite::MyModule;

     use Kite::Base;
     use base qw( Kite::Base );
     use vars qw( $PARAMS $ERROR );

     $PARAMS = {
     	TITLE => 'Default Title',
     	ALPHA => 3.14,
     	OMEGA => 2.718,
     };

     package main;

     # specify config as a hash reference...
     my $module = Kite::MyModule->new({
     	TITLE => 'Grand Title',
     	ALPHA => 3,
     }) || die $Kite::MyModule::ERROR, "\n";

     # ...or as a list of items;  parameter case is insignificant
     my $module = Kite::MyModule->new( TITLE => 'Grand Title' )
     	|| die $Kite::MyModule::ERROR, "\n";

     print $module->title();
     print $module->alpha();
     print $module->omega();

DESCRIPTION
===========

   Base class module which implements a constructor and error reporting
functionality for various Kite modules.

PUBLIC METHODS
==============

new(\%config)
-------------

   Constructor method which accepts a reference to a hash array or a list
of `name => value' parameters which are folded into a hash.  The init()
method is then called, passing the configuration hash and should return
true/false to indicate success or failure.  A new object reference is
returned, or undef on error.  Any error message raised can be examined via
the error() class method or directly via the package variable ERROR in the
derived class.

     package Kite::MyModule;

     use Kite::Base;
     use base qw( Kite::Base );

     package main;

     my $module1 = Kite::MyModule->new({ param => 'value' })
         || die Kite::MyModule->error(), "\n";

     my $module2 = Kite::MyModule->new( param => 'value' )
         || die "constructor error: $Kite::MyModule::ERROR\n";

init(\%config)
--------------

   This method is called by the new() constructor to initialise the object.
A reference to a hash array of configuration items is passed as a
parameter.

   The method looks for a hash reference defined as the $PARAMS package
variable in the package of the derived class.  If defined, this hash array
should contain keys which define the acceptable configuration paramaters
and values which provide default values for that item.  The method then
iterates through the items in this hash, copying any defined value in the
$config hash or otherwise the default value in the $PARAMS hash, into the
$self object.

   All parameter names should be specified in the $PARAMS hash in UPPER
CASE.  The user may specify UPPER or lower case parameters names and these
will both be correctly handled.   Parameter names which are prefixed with
an underscore will be considered 'private'.  The default value, defined in
the $PARAMS hash will be copied into the $self object, but any value
provided in the $config hash will be ignored.

     package Kite::MyModule;

     use Kite::Base;
     use base qw( Kite::Base );
     use vars qw( $ERROR $PARAMS );

     $PARAMS = {
     	TITLE  => 'Default Title',
     	AUTHOR => undef,		# no default
     	_COUNT => 1,			# private variable
     };

     package main;

     my $mod = Kite::MyModule->new(title => 'The Title')
     	|| die $Kite::MyModule::ERROR;

   Derived classes may elect to redefine the init() subroutine to provide
their own custom initialisation routines.  They can, of course, explicitly
call the init() method on the parent class if they need to do so.

     package Kite::MyModule;

     ...

     sub init {
     	my ($self, $config) = @_;

     	$self->SUPER::init($config)
     	    || return undef;

     # more configuration...

     return $self;
         }

error($msg)
-----------

   May be called as an object method to get/set the internal _ERROR member
or as a class method to get/set the $ERROR variable in the derived class's
package.

     my $module = Kite::MyModule->new({ ... })
         || die Kite::MyModule->error(), "\n";

     $module->do_something()
     	|| die $module->error(), "\n";

   When called with parameters (multiple params are concatenated), this
method will set the relevant variable and return undef.  This is most
often used within object methods to report errors to the caller.

     package Kite::MyModule;

     ...

     sub foobar {
     	my $self = shift;
     	...
     	return $self->error('some kind of error...')
     	    if $some_condition;
     	...
     }

AUTHOR
======

   Andy Wardley <abw@kfs.org>

REVISION
========

   $Revision: 1.3 $

COPYRIGHT
=========

   Copyright (C) 2000 Andy Wardley.  All Rights Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Kite|Kite' in this node

useful PostScript definitions for kite layout et al
***************************************************

NAME
====

   Kite::PScript::Defs - useful PostScript definitions for kite layout et
al

SYNOPSIS
========

     use Kite::PScript::Defs;

     # access package variables directly
     print $Kite::PScript::Defs::mm;

     # or as package subs
     print Kite::PScript::Defs::mm();

     # or as class methods
     print Kite::PScript::Defs->mm();

     # here's a convenient shorthand
     my $ps = 'Kite::PScript::Defs';
     print $ps->mm;

     # import various definitions
     use Kite::PScript::Defs qw( mm clip );
     print mm, clip;

     # or specify :all tag to import all definitions as subs
     use Kite::PScsript::Defs qw( :all );
     print mm, reg, clip, pathtext;

DESCRIPTION
===========

   Module defining a number of useful PostScript definitions for kite part
layout and other similar tasks.

   The definitions are provided as package variables which can be accessed
directly:

     use Kite::PScript::Defs;

     print $Kite::PScript::Defs::mm;

   An AUTOLOAD method is provided which translates any subroutine or method
calls into accesses to the appropriate variable.  Thus, the PostScript
definition specified in the $mm package variable can be accessed by calling
either of:

     Kite::PScript::mm();
     Kite::PScript->mm();

   The latter use allows a 'factory' variable to be defined to make this
less tedious.

     my $ps = 'Kite::PScript::Defs';
     print $ps->mm, $ps->clip, $ps->pathtext;

   You can specify import parameters when loading the module.  Any
definitions specified will be imported as subroutines into the caller's
namespace.

     use Kite::PScript::Defs qw( mm clip );
     print mm, clip;

   The ':all' import tag can be specified to import all the PoscScript
definitions.

     use Kite::PScript::Defs qw( :all );
     print mm, clip, pathtext;

TEMPLATE TOOLKIT
================

   The module is defined to be intimately useful when used in conjunction
with the Template Toolkit.  To use the PostScript definitions within a
template, simply ensure that the module is loaded and bless an empty hash
into the Kite::PScript::Defs package.  This will allow the Template
Toolkit to resolve to the correct class methods.

     use Template;
     use Kite::PScript::Defs;

     my $tt2  = Template->new();
     my $vars = {
     	psdefs => bless({ }, 'Kite::PScript::Defs'),
     };

     $tt2->process(\*DATA, $vars)
     	|| die $tt2->error();

     __END__
     %!PS-Adobe-3.0
     %%EndComments

     [% psdefs.mm %]
     [% psdefs.lines %]
     [% psdefs.cross %]
     [% psdefs.dot %]
     [% psdefs.circle %]
     [% psdefs.crop %]
     [% psdefs.reg %]

     0 mm 0 mm moveto	% /mm defined in psdefs.mm
     crop		% /crop defined in psdefs.crop
     regmarks		% /regmarks defined in psdefs.reg
     ...etc...

POSTSCRIPT DEFINITION METHODS
=============================

mm
     Defines millimetres /mm.

          [% psdefs.mm %]
          10 mm 10 mm moveto
          50 mm 10 mm lineto

lines
     Defines the following line styles:

          linelight		% 0.25 setlinewidth
          linenormal		% 0.5  setlinewidth
          lineheavy		% 0.75 setlinewidth
          linedotted		% 0.5  setlinewidth + dotted
          linedashed		% 0.5  setlinewidth + dashed

     Example:

          [% psdefs.mm %]
          [% psdefs.lines %]
          linenormal
          newpath
          0 mm 0 mm moveto
          100 mm 0 mm lineto
          stroke

          =item cross

     Defines a procedure to generate a cross from vertical and horizontal
     lines 10mm in length, crossing at the current point.  Requires 'mm'
     and 'lines'.

          [% psdefs.mm %]
          [% psdefs.lines %]
          [% psdefs.cross %]
          50 mm 50 mm		% move to a point
          cross		% draw cross

dot
     Defines a procedure to generate a small filled dot at the current
     point.  Requires 'mm' and 'lines'.

          [% psdefs.mm %]
          [% psdefs.lines %]
          [% psdefs.dot %]
          50 mm 50 mm		% move to a point
          dot			% draw dot

circle
     Defines a procedure to generate a small circle at the current point.
     Requires 'mm' and 'lines'.

          [% psdefs.mm %]
          [% psdefs.lines %]
          [% psdefs.circle %]
          50 mm 50 mm		% move to a point
          circle		% draw circle

crop
     Defines a procedure to generate a crop mark at the current point,
     built from a combination of /cross and /circle.  Requires 'mm',
     'lines', 'cross' and 'circle'.

          [% psdefs.mm %]
          [% psdefs.lines %]
          [% psdefs.cross %]
          [% psdefs.circle %]
          0 mm 0 mm		% move to a point
          circle		% draw crop mark

clip
     Defines /cliprect as a procedure to return a clipping rectangle set to
     the imageable size.  Defines a number of other variables containing
     information about the clipping rectangle.

          cliprect		% clipping rectangle
          cliptrx		% top right x
          cliptry		% top right y
          clipblx		% bottom left x
          clipbly		% bottom left y
          clipxsize		% width
          clipysize		% height

reg
     Defines /regmarks to generate registration marks (crop) at the corners
     of the clipping rectangle, /cliprect.  Requires 'mm', 'lines',
     'cross', 'circle', 'crop' and 'clip'.

          [% psdefs.mm %]
          [% psdefs.lines %]
          [% psdefs.cross %]
          [% psdefs.circle %]
          [% psdefs.crop %]
          [% psdefs.clip %]

          regmarks		% draw registration marks

noreg
     Defines /regmarks as a no-op procedure to prevent registration marks
     from being produced.

          regmarks		% null registration marks

pathtext
     Defines /pathtext to draw text along an arbitrary path.

          path text pathtext	% draw text along path

          ** TODO - see Blue Book for examples **

tiles
     Defines /tiles as a procedure which calculates the number of pages
     required to display the current path on the output device.  Also
     calculates the X/Y origin required for the path to be centered within
     the tile set.  Defines the following items.

          tilesnx		% no. of tiles in x
          tilesny		% no. of tiles in y
          tilesxorg		% suggested x origin
          tilesyorg		% suggested y origin

     See next item for example of use.

dotiles
     Generates PostScript to tile an image into multiple pages.  It
     requires that a number of items be pre-defined.  The first,
     /tileimage, should be a procedure defined to generate the image
     itself.

          /tileimage {
          	...PostScript to generate your image...
          } def

     The next item, /tilepath, should be a procedure defined to generate a
     path which encloses the image.  This is used to calculate the
     bounding box for the image.

          /tilepath {
          	...PostScript path to bound your image...
          } def

     Finally, the /tilepage item should be a procedure defined to generate
     any output required on each tiled page (i.e. independant of the main
     image which ends up split across many pages).

          [% psdefs.mm %]
          [% psdefs.reg %]
          [% psdefs.clip %]

          /tilepage {
          	regmarks		% generate registration marks
          	/Times-Roman findfont
          	24 scalefont setfont	% set font
          	clipblx 3 mm add
          	clipbly 3 mm add moveto	% move to lower left corner
          	([% title %]) show	% print title
          	tilemap			% generate tiling map
          } def

     To tile the image onto multiple pages, the /tiles procedure should be
     called to determine the tiling requirements.  The /tilepath item
     should be on the stack (i.e. precede the call).

          [% psdefs.tiles %]

          tilepath tiles

     Then, the 'dotiles' method can be called to generate the appropriate
     PostScript code to tile the image onto multiple pages.

          [% defs.dotiles %]

Box
     This item generates a PostScript definition for a Box object which can
     be used for all kinds of things boxlike.  The following documentation
     items describe the available Box "methods" in more detail, but for
     now, here's a complete example.

          %!PS-Adobe-3.0
          %%Title: Box Example
          %%EndComments

          [% defs.mm %]
          [% defs.lines %]
          [% defs.cross %]
          [% defs.dot %]
          [% defs.circle %]
          [% defs.crop %]
          [% defs.box %]

          # define a general border value
          /border [% border %] mm def

          % convert the clipping path into a Box
          clippath pathbbox Box

          % inset this Box by /border
          border Box_border

          % and define /page to be this slightly smaller Box
          /page exch def

          % split /page into 3 vertical boxes
          page 3 border 0 Box_vsplit
          /upper  exch def
          /middle exch def
          /lower  exch def

          % inset upper box by border and define /inner
          upper border Box_border
          /inner exch def

          % split it horizontally into /left and /right
          inner 2 border 0 Box_hsplit
          /right exch def
          /left  exch def

          % stroke /upper, /middle and /lower boxes.
          linenormal
          upper  Box_rect rectstroke
          middle Box_rect rectstroke
          lower  Box_rect rectstroke

          % focus the drawing context on the /middle box
          middle Box_focus
          newpath
          0 0 moveto
          100 mm 100 mm lineto
          ...more complicated stuff here...
          stroke
          middle Box_defocus

          showpage

Box_select
     Unpacks a Box structure to define various Box_* variables.

          Box_try	    % top right y
          Box_trx	    % top right x
          Box_bly	    % bottom left y
          Box_blx	    % bottom left x
          Box_width	    % width of Box
          Box_height	    % height of Box

     Example:

          mybox Box_select

Box_rect
     Unpacks a Box structure to a rect suitable for rectstroke, etc.

          mybox Box_rect rectstroke

Box_path
     Unpacks a Box structure to a path suitable for stroke, clip, etc.

          mybox Box_path stroke

Box_border
     Creates a new Box within a specified border of an existing Box.

          mybox 10 mm Box_bqorder
          /smallbox exch def

Box_vsplit
     Splits a box vertically into a number of equal sized boxes.  Spacing
     and padding variables should also be specified to control the sizes
     and relative positions of the new boxes.

          % split /mybox into 3 new Box objects, /upper, /middle and
          % /lower, padded 10 mm within existing /mybox and spaced
          % 5 mm apart from each other
          mybox 3 10 mm 5 mm Box_vsplit
          /upper  exch def
          /middle exch def
          /lower  exch def

Box_hsplit
     As per Box_Vsplit but splitting a Box horizontally.

          middle 2 10 mm 5 mm Box_hsplit
          /right exch def
          /left  exch def

Box_focus
     Creates a new drawing context which is focussed on a particular Box.
     That is, all drawing will happen relative to the origin of the Box and
     be clipped within its bounds.

          middle Box_focus

Box_defocus
     Restores the previous drawing context saved by a prior Box_focus.

     =back

AUTHOR
======

   Simon Stapleton <simon@tufty.co.uk> wrote the original xml2ps.pl
utility which inspired much of the original PostScript contained herein.
Most of that, he freely admits, was gleaned from the Blue Book (PostScript
Language Tutorial and Cookbook, Adobe).

   Andy Wardley <abw@kfs.org> re-packaged it into a module for integration
into the Kite bundle.  Various features and more advanced defintions have
been added along the way.

REVISION
========

   $Revision: 1.3 $

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

TODO
====

   It would be nice to have some way of automatically managing all
dependencies between different procedures.  For example, if you call the
'circle' method then it should ensure that 'mm' and 'lines' are first
called if they haven't been called previously.

   It may make more sense to package this module as a general purpose
PostScript library and/or plugin for the Template Toolkit.

SEE ALSO
========

   For further information on the Kite::* modules, see Kite.
For further information on the Template Toolkit, see Template,
or http://www.template-toolkit.org/ .

represent and manipulate a 2d profile
*************************************

NAME
====

   Kite::Profile - represent and manipulate a 2d profile

SYNOPSIS
========

     use Kite::Profile;

     # create new profile
     my $profile = Kite::Profile->new({
     	NAME => "Profile Name",
         X    => [ $x1, $x2, $x3 ... $xn ],
         Y    => [ $y1, $y2, $y3 ... $yn ]
     });

     # load profile from file (plotfoil format)
     my $profile = Kite::Profile->new({
     	FILE => 'profiles/S2091'
     }) || die Kite::Profile->error(), "\n";

     # create profile from text string (plotfoil format)
     my $profile = Kite::Profile->new({
     	TEXT => "Profile Name\n x1 y1\n x2 y2\n ...\n"
     }) || die Kite::Profile->error(), "\n";

     # get/set the profile name
     print $profile->name();
     $profile->name("New name for this profile");

     # methods for general information and data output
     print $profile->about();
     print $profile->output();

     # methods to return specific profile characteristics
     print $profile->height();
     print $profile->length();
     print $profile->max_x();
     print $profile->min_x();
     print $profile->max_y();
     print $profile->min_y();

     # move (translate) the x or y values by a given amount
     $profile->translate_x($amount);
     $profile->translate_y($amount);

     # move the profile to zero it at the origin (minx = miny = 0)
     $profile->origin();
     $profile->origin_x();
     $profile->origin_y();

     # scale the profile by a given factor
     $profile->scale_xy($factor);
     $profile->scale_x($factor);
     $profile->scale_y($factor);

     # scale the profile to a length (x) or height (y) of 1
     $profile->normalise();
     $profile->normalise_x();
     $profile->normalise_y();

     # insert a node $n with values $x and $y
     $profile->insert($n, $x, $y)
         || warn $profile->error(), "\n";

     # delete node $n
     $profile->delete($n)
         || warn $profile->error(), "\n";

     # discard all but a sub-section of nodes
     $profile->keep($from, $to)
         || warn $profile->error(), "\n";

     # test if profile is closed (first node == last node)
     print "profile is closed\n"
         if $profile->closed();

     # add final node if necessary to ensure a closed profile
     $profile->close();

     # find set of X/Y values where profile crosses point on Y/X axis
     my $xpoints = $profile->x_at_y($y);
     print "profile crosses X at Y=$y at [ @$xpoints ]\n";

     my $ypoints = $profile->y_at_x($x);
     print "profile crosses Y at X=$x at [ @$ypoints ]\n";

     # retrieve number of nodes and lists of node values
     my $no_of_nodes = $profile->n_nodes();
     my ($x, $y) = $profile->nodes();
     for (my $i = 0; $i < $no_of_nodes; $i++) {
     	print "$i  x: $x->[$i]  y: $y->[$i]\n";
     }

DESCRIPTION
===========

   This module defines an object class which can be used to represent and
manipulate 2D profiles.  In this context, a profile is a set of X,Y
co-ordinates (nodes) that define the outline of a shape.

   For the original intended use in kite construction, these profiles
ultimately represent cutting patterns for pieces of fabric which are sewn
together to form the kite.  However, this module is not specific to kite
design and can be applied to any situation where you wish to represent a
2-dimensional shapes  by a set of co-ordinates and perform simple
manipulations on it (e.g. scale, translate, sub-section, etc.)

   The profile data can be output in a simple format which can be
subsequently processed (e.g. convert to Postscript) by other tools (e.g.
plotfoil).

METHODS
=======

new(\%params)
-------------

   Class constructor method to create a new profile object based on data
provided as configuration items, read from a file or provided as a text
string.  The method should be passed a reference to a hash array
containing one of the following items or sets of items.

NAME, X, Y
     Specify the profile name, and X and Y values for each of the points
     that constitute the profile.  The X and Y values should be specified
     as references to lists.

          my $profile = Kite::Profile->new({
          	NAME => 'Peter Lynn "Pilot" 4m^2 - Flare'
              X    => [ 2250, 985, 110, 0, 2250 ],
          	Y    => [ 0, 480, 280, 0, 0 ],
          });

FILE
     Specify a filename from which the profile data should be read.

          my $profile = Kite::Profile->new({
          	FILE => '/home/abw/kites/pilot/rib'
          });

     The constructor returns undef if the file cannot be opened.  The
     error() class method can be called to retrieve the specific error
     message.

          my $profile = Kite::Profile->new({
          	FILE => '/home/abw/kites/pilot/rib'
          }) || die Kite::Profile->error();

     The expected file format is as per Plotfoil:

          Name of the profile
          x1  y1
          x2  y2
          .   .
          .   .
          xn  yn

     Comments (lines starting with # or %) are ignored, as are blank lines.

     Example:

          Peter Lynn "Pilot" 4m^2 - Rib
          # either:
          #   cut 5 of these
          # or:
          #   cut 2 of these and cut the other 3 with the flares (30mm overlap)
          2330    0
          2330   20
           350  270
           300  277
             .    .
             .    .
          2330    0

TEXT
     This option allows you to specify the profile data as a text string.
     The format should be as above.

          my $text =

          my $profile = Kite::Profile->new({
          	TEXT => "Peter Lynn \"Pilot\" 4m^2 - Rib\n2330 0\n2330 20\n...";
          });

name()
------

   Returns the profile name.  Can also be called with an argument to set a
new name.

     $profile->name("New name for the profile");

length()
--------

   Returns the profile length (max_x - min_x).

height()
--------

   Returns the profile height (max_y - min_y).

min_x()
-------

   Returns the smallest X value.

max_x()
-------

   Returns the largest X value.

min_y()
-------

   Returns the smallest Y value.

max_y()
-------

   Returns the largest Y value.

translate_x($amount)
--------------------

   Add a given amount to all the X values, effectively moving the profile
in the X direction.

translate_y($amount)
--------------------

   Add a given amount to all the Y values, effectively moving the profile
in the Y direction.

origin()
--------

   Translates the profile to the origin so that both minx and max are 0.

origin_x()
----------

   Translates the profile X values so that minx is 0.

origin_y()
----------

   Translates the profile Y values so that miny is 0.

scale_x($factor)
----------------

   Multiply all the X values by a given amount, effectively scaling the
profile in the X direction.

scale_y($factor)
----------------

   Multiply all the Y values by a given amount, effectively scaling the
profile in the Y direction.

scale_xy($factor)
-----------------

   Multiply all the X and Y values by a given amount, effectively scaling
the profile in both X and Y directions.

normalise_x()
-------------

   Scales the X values (by 1/length) to achieve a profile length of 1.
The profile is moved along the X axis to ensure that min_x is 0.  The
max_x value is then 1 and all other values lie proportionately between 0
and 1.

normalise_y()
-------------

   Scales the Y values (by 1/height) to acheive a profile height of 1.
The profile is *NOT* translated to min_x = 0 to ensure that the original
centre line position of the profile is preserved.  range 0 - 1.

normalise()
-----------

   Normalises the profile to a length of 1 (see normalise_x()) and then
scales the Y values by the same factor (1/length).  The end result is a
proportionately scaled profile of length 1.

insert($node, $x, $y)
---------------------

   Inserts a new node at the position specified by $node with the $x and $y
values.  The value for $node should be in the range 0 - $nnodes.  The
existing node $n and any elements following will be shifted futher down
the list by one to make room for the new element.  An element inserted at
$node position 0 is added to the front of the list.  An element inserted
at a $node position one greater than the last current node will be added to
the end of the list.

   Returns 1 if the new node was successfully inserted or undef on error.

delete($node)
-------------

   Deletes the node at the position specified by $node and moves the
remaining items in the list up by one to close the gap.

   Returns 1 if the node was sucessfully inserted or undef on error.

keep($from, $to)
----------------

   Reduces the profile to a sub-section of nodes identified by $from and
$to.  These should be specified as node numbers from 0 to n_nodes-1.  The
nodes in this range (inclusively) are kept to form the new profile and the
others are discarded.

closed()
--------

   Returns a true/false value to indicate if the profile is closed.  That
is, if the first and last nodes contain identical X and Y values.

close()
-------

   Duplicates the first node at the end of the list to ensure that the
profile is closed.  Has no effect if the profile is already closed.

x_at_y($y)
----------

   Returns a reference to a list of X values where the profile crosses
point $y on the Y axis.  The profile must be closed.  The list returned
will be empty if the profile does not cross the specified point or will
contain an even number of items if it does.  Each pair of items thus
represents an entry/exit transition into/out of the enclosed profile area
for increasing values of X at a fixed Y.

   Returns undef on error (e.g. profile not closed).

y_at_x($x)
----------

   Returns a reference to a list of Y values where the profile crosses
point $y on the X axis.  Otherwise similar to x_at_y() above.

AUTHOR
======

   Andy Wardley <abw@kfs.org>

VERSION
=======

   $Revision: 1.3 $

COPYRIGHT
=========

   Copyright (C) 2000 Andy Wardley.  All Rights Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `okprof|okprof' in this node, `Kite|Kite' in this node,
`Kite::Base|Kite::Base' in this node

reads an XML curve definition file and generates PostScript
***********************************************************

NAME
====

   Kite::XML2PS - reads an XML curve definition file and generates
PostScript

SYNOPSIS
========

     use Kite::XML2PS;

     my $ps = Kite::XML2PS( filename => 'example.xml' )
         || die $Kite::XML2PS::ERROR, "\n";

     # return PostScript definitions for image and image path
     print "image definition: ", $ps->image();
     print "image path: ", $ps->path();

     # generate entire PostScript document with tiling, etc.
     print $ps->doc();

DESCRIPTION
===========

   Module for converting an XML file containing curve definitions (see
xml/kiteparts.dtd) into PostScript.

PUBLIC METHODS
==============

new(\%config)
-------------

   Constuctor method called to create a new Kite::XML2PS object.  Accepts
a reference to a hash array of configuration items or a list of `name =>
value' pairs.  The following items may be specified:

filename
     Specifies a filename from which the XML definition should be read.
     This parameter is mandatory.  The XML content of this document should
     conform to the OpenKite layout format as specified in the
     xml/kiteparts.dtd file (relative to the distribution root directory).

title
     Optional parameter which can be used to set the title for the
     document.  Setting this value will override any title defined in the
     XML document.

regmarks
     Enables registration marks when set to any true value.

border
     Specifies a border width in mm (default: 5mm).  The clipping area
     will be inset this distance from the imageable area on the page.  This
     is useful for printers that can't actually print to the edge of the
     area that they think they can.

map
     The tiling procedure adds a small map to the top left hand corner of
     each page, indicating the position of the current page within the
     tiling set.  This option can be set to 0 to disable this feature.

   The file specified via the filename option will be parsed and converted
into PostScript definitions for the image as a whole (IMAGE) and the
outline path (PATH).  These can then be retrieved via the image() and
path() method calls.

   On error, the constructor returns undef.  The error message generated
can be retrieved by calling the error() class method, or by examining the
$Kite::XML2PS::ERROR variable.

doc()
-----

   Returns a PostScript document containing the kite parts layed out as
specified in the input file.  The output is automatically tiled onto
multiple pages.

image()
-------

   Returns a PostScript string defining the image for the parts parsed from
the input file.

path()
------

   Returns a PostScript string defining the the outline path of the parts
parsed from the input file.

AUTHORS
=======

   Simon Stapleton <simon@tufty.co.uk> wrote the original xml2ps.pl
utility which performs the XML -> PostScript conversion.

   Andy Wardley <abw@kfs.org> re-packaged it into a module for integration
into the Kite bundle.

REVISION
========

   $Revision: 1.3 $

COPYRIGHT
=========

   Copyright (C) 2000 Simon Stapleton, Andy Wardley.  All Rights Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   See also Kite, Kite/PScript/Defs,
and `okxml2ps' in this node.

base class for XML parser nodes
*******************************

NAME
====

   Kite::XML::Node - base class for XML parser nodes

SYNOPSIS
========

     package Kite::XML::Node::Foo;

     use base qw( Kite::XML::Node );
     use vars qw( $ATTRIBUTES $ELEMENTS $ERROR );

     # define some attributes for the element node
     $ATTRIBUTES = {
     	id    => undef,		# mandatory
     	lang  => 'en',		# default value
     	title => '',		# optional attribute
     };

     # define permitted child elements
     $ELEMENTS = {
     	# single 'bar' child element
         bar => 'Kite::XML::Node::Bar',
     	# multiple 'baz' child elements
         baz => 'Kite::XML::Node::Baz+',
         # require "Kite/XML/Node/Baz.pm"
         wiz => [ 'Kite::XML::Node::Wiz' => 1 ]
     	# require some other module, accept multiple children
         waz => [ 'Kite::XML::Node::Waz+' => 'some/other/module.pm' ],
     	# accept character content
     	CDATA => 1,
     };

     package main;

     my $foo = Kite::XML::Node::Foo->new(id => 12345)
         || die Kite::XML::Node::Foo->error(), "\n";

     # set/get attributes via AUTOLOAD accessor methods...
     $foo->title('New Title');
     print $foo->id();		# 12345
     print $foo->lang();		# 'en'
     print $foo->title();	# 'New Title'

     # ...or using explicit attr() (or attribute()) method
     $foo->attr('title', 'New Title');
     $foo->attribute('title', 'New Title');
     print $foo->attr('title');	# 'New Title'

     # create new 'bar' child element
     $foo->child('bar', @some_bar_args)
         || die $foo->error(), "\n";

     # same, using AUTOLOAD method (_must_ pass additional args)
     $foo->bar(@some_bar_args)
         || die $foo->error(), "\n";

     # retrieve elements via AUTOLOAD methods (_don't_ pass any args)
     my $bar = $foo->bar();

     # ...or using explicit elem() (or element()) method
     $bar = $foo->elem('bar');
     $bar = $foo->element('bar');

     # create multiple 'baz' children
     $foo->child('baz', @some_baz_args)
         || die $foo->error(), "\n";
     $foo->child('baz', @more_baz_args)
         || die $foo->error(), "\n";

     # multiple elements returned as (possibly empty) list reference
     foreach my $baz (@{ $foo->baz() }) {
     	print $baz->some_attribute();
     }

     # append/retrieve character content
     $foo->char('Character Content');
     print $foo->char();

DESCRIPTION
===========

   This module implements a base class for objects that are constructed
automatically by the Kite::XML::Parser to represented parsed XML nodes
(i.e. elements).

   Other modules may be derived from base class to represent specific XML
element nodes.

     package Kite::XML::Node::Foo;
     use base qw( Kite::XML::Node );

   The base class methods examine variables in the package of the subclass
to determine the permitted attributes and elements of the node.  The
$ERROR variable is also used for reporting class errors.

     use vars qw( $ATTRIBUTES $ELEMENTS $ERROR );

   The $ATTRIBUTES package variable may be defined as hash reference
containing valid attributes for the node.  Default values may be provided.
Any values left undefined are mandatory and must be provided to the new()
constructor.

     # define some attributes for the element node
     $ATTRIBUTES = {
     	id    => undef,		# mandatory
     	lang  => 'en',		# default value
     	title => '',		# optional attribute
     };

   The $ELEMENTS package variable may also be defined as a hash reference
detailing valid child elements of the node.  The keys represent the
element names and the relevant values should be the package names of other
Kite::XML::Node subclasses.  The package name may be suffixed by a '+' to
indicate that multiple child elements of this type are permitted.  It may
also be defined as a reference to an array containing the package name as
before, followed by the name of a specific module to load (via require())
before instantiating objects of that type.  This value may also be
specified as '1' to indicate that the relevant module for the package
should be required (i.e. change '::' to '/' and append '.pm').  The CDATA
key can also be specified to contain any true to indicate that the element
should also accept character content.

     # define permitted child elements
     $ELEMENTS = {
     	# single 'bar' child element
         bar => 'Kite::XML::Node::Bar',

     # multiple 'baz' child elements
             baz => 'Kite::XML::Node::Baz+',

     # require "Kite/XML/Node/Baz.pm"
     wiz => [ 'Kite::XML::Node::Wiz' => 1 ]

     # require some other module, accept multiple children
             waz => [ 'Kite::XML::Node::Waz+' => 'some/other/module.pm' ],

     # accept character content
     CDATA => 1,
         };

   The derived class can then be used to instantiate XML node objects to
represent XML elements.  Any mandatory attributes (i.e. $ATTRIBUTES set to
undef) must be provided to the constructor.

     package main;

     my $foo = Kite::XML::Node::Foo->new(id => 12345)
         || die Kite::XML::Node::Foo->error(), "\n";

   Any optional attributes may also be provided.  Any default values
specified in $ATTRIBUTES will be set if otherwise undefined.

     my $foo = Kite::XML::Node::Foo->new(id => 12345, title => 'test')
         || die Kite::XML::Node::Foo->error(), "\n";

   Attribute arguments may also be specified as a hash reference for
convenience.

     my $foo = Kite::XML::Node::Foo->new({
     	id => 12345,
     	title => 'test',
     }) || die Kite::XML::Node::Foo->error(), "\n";

   The new() constructor returns undef on failure and sets the $ERROR
package variable in the subclass.  This can then be inspected directly or
by calling error() as a class method.

     my $foo = Kite::XML::Node::Foo->new(...)
         || die $Kite::XML::Node::Foo::ERROR;

     my $foo = Kite::XML::Node::Foo->new(...)
         || die Kite::XML::Node::Foo->error();

   An AUTOLOAD method is provided to allow attributes to be accessed as
methods.  Arguments passed to these methods will be used to set the
attribute, otherwise the attribute value will be returned.

     $foo->title('New Title');
     print $foo->id();		# 12345
     print $foo->lang();		# 'en'
     print $foo->title();	# 'New Title'

   The attr() method can also be used explicitly.  This is also aliased to
attribute().

     $foo->attr('title', 'New Title');
     $foo->attribute('title', 'New Title');
     print $foo->attr('title');	# 'New Title'

   The child() method is used to create a new child element.  The first
argument specifies the element type and should be defined in $ELEMENTS.
Any additional arguments are passed to the new() constructor method for
that element.  The instantiated child node is stored internally by the
element name.  Single elements (i.e. those that aren't suffixed by '+' in
$ELEMENTS) may only be defined once and will generate an error (returning
undef) if an attempt is made to redefine an existing element.

     # create new 'bar' child element
     $foo->child('bar', @some_bar_args)
         || die $foo->error(), "\n";

   Multiple elements (i.e. those suffixed '+' in $ELEMENTS) may be added
any number of times.

     $foo->child('baz', @some_baz_args)
         || die $foo->error(), "\n";
     $foo->child('baz', @more_baz_args)
         || die $foo->error(), "\n";

   The AUTOLOAD method can be used to return element values.  Single
elements return a single object (or undef), multiple elements return a
reference to a list which may be empty (no children defined).

     my $bar = $foo->bar();
     print $bar->some_attribute();

     foreach my $baz (@{ $foo->baz() }) {
     	print $baz->some_attribute();
     }

   The elem() method can also be used explicitly.  This is also aliased to
element().

     my $bar = $foo->elem('bar');
     my $baz = $foo->element('bar');

   Additional arguments may be passed to the elem() method to create a new
child element.  This is then delegated to the child() method.

     $foo->elem('bar', @some_bar_args)
     	|| die $foo->error(), "\n";

     # same as
     $foo->child('bar', @some_bar_args)
     	|| die $foo->error(), "\n";

   The AUTOLOAD method can be used in the same way.  Note that both these
uses require additional arguments to be passed to distinguish them from
simple retrieval calls.

     $foo->bar(@some_bar_args)
         || die $foo->error(), "\n";

   The char() method is provided to retrieve and update character content
for the element.  The CDATA item should be defined to any true value in
$ELEMENTS for character data to be accepted.  Note however, that any node
which doesn't defined CDATA true will accept and ignore any character data
consisting of nothing but whitespace.  Any text data passed as the first
argument is appended to the current character content buffer.  The buffer
is then returned.

     # append/retrieve character content
     $foo->char('Character Content');
     print $foo->char();

AUTHOR
======

   Andy Wardley <abw@kfs.org>

REVISION
========

   $Revision: 1.1 $

COPYRIGHT
=========

   Copyright (C) 2000 Andy Wardley.  All Rights Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   See also <Kite::XML::Parser>.

XML nodes to represent kite markup
**********************************

NAME
====

   Kite::XML::Node::Kite - XML nodes to represent kite markup

SYNOPSIS
========

     package Kite::XML::Node::Kite;

DESCRIPTION
===========

   TODO

AUTHOR
======

   Andy Wardley <abw@kfs.org>

REVISION
========

   $Revision: 1.2 $

COPYRIGHT
=========

   Copyright (C) 2000 Andy Wardley.  All Rights Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   See also Kite/XML/Node, <Kite::XML::Node::Curve>
and Kite/XML/Parser.

XML parser for kite related markup
**********************************

NAME
====

   Kite::XML::Parser - XML parser for kite related markup

SYNOPSIS
========

     package Kite::XML::Parser;

     my $parser = Kite::XML::Parser->new();
     my $kite   = $parser->parsefile($filename);

DESCRIPTION
===========

   This is a simple stack based parser built around the XML::Parser module.
It parses XML text and instantiates Kite::XML::Node::* objects as it
identifies various elements in the markup.  These are automatically
constructed into a tree (a.k.a 'grove').  A node object representing the
root object is returned.

AUTHOR
======

   Andy Wardley <abw@kfs.org>

REVISION
========

   $Revision: 1.1 $

COPYRIGHT
=========

   Copyright (C) 2000 Andy Wardley.  All Rights Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   See also <Kite::XML::Node> and <Kite::XML::Node::Kite>

Perl extension for Kerberos 4
*****************************

NAME
====

   Krb4 - Perl extension for Kerberos 4

SYNOPSIS
========

   use Krb4;

DESCRIPTION
===========

   Krb4 is an object oriented extension to Perl 5 which implements several
user-level Kerberos 4 functions.  With this module, you can create
Kerberized clients and servers written in Perl.  It is compatible with
both AFS and MIT Kerberos.

VARIABLES & FUNCTIONS
---------------------

   NOTE: No methods or variables are exported, so each variable and
function should be preceded by 'Krb4::'

error
     Contains the error code of the most recent Kerberos function call.

get_phost(alias)
     Returns the instance name of the host 'alias'

get_lrealm(n)
     Returns the nth realm of the host machine.  n is zero by default.

realmofhost(host)
     Returns the realm of the machine 'host'.

mk_req(service,instance,realm,checksum)
     Returns a Krb4::Ticket object for the specified service, instance, and
     realm.  It will return undef if there was an error.

rd_req(ticket,service,instance,fn)
     Returns a Krb4::AuthDat object, which contains information obtained
     from the ticket, or undef upon failure.  Ticket is a variable of the
     class Krb4::Ticket, which can be obtained from mk_req().  fn is a
     path to the appropriate srvtab.  /etc/srvtab will be used if fn is
     null.

get_cred(service,instance,realm)
     Search the caller's ticket file for a ticket for the service and
     instance in the given realm.  Returns a Krb4::Creds object, or undef
     upon failure.  This method can be used to extract a ticket's session
     key.

get_key_sched(session)
     Returns the key schedule for the session key 'session', which can be
     obtained from rd_req() or get_cred().  The key schedule is a
     Krb4::KeySchedule object.

mk_priv(in,schedule,key,sender,receiver)
     Encrypts the data stored in 'in' and returns the encrypted data.
     sender and receiver should be in standard internet format, which can
     be achieved using the inet_aton and sockaddr_in functions in the
     Socket module.

rd_priv(in,schedule,key,sender,receiver)
     Decrypts the variable 'in' and returns the original data.  Other
     parameters are as described in mk_priv()

sendauth(options,fh,service,inst,realm,checksum,laddr,faddr,version)
     Obtains a ticket for the specified service, instance, and realm, and
     writes it to the socket 'fh'.  Use recvauth to read the ticket on the
     server.  'laddr' is the packed network address of the client, and
     'faddr' is the packed network address of the server.  'options' can
     be any of the following:

          Krb4::KOPT_DONT_MK_REQ
          Krb4::KOPT_DO_MUTUAL
          Krb4::KOPT_DONT_CANON

     Use Krb4::KOPT_DO_MUTUAL if you plan to do any encryption.  This
     function returns a list containing the service ticket, the
     credentials, and the key schedule.

recvauth(options,fh,service,inst,faddr,laddr,fn)
     Reads a ticket/authenticator pair from the socket 'fh'.  'options'
     can be set as described above.  'faddr' is the packed network address
     of the client, and 'laddr' is the packed network address of the
     server.  This function returns a list containing the ticket, an
     AuthDat object, the key schedule, and the version string.

get_pw_in_tkt(user,inst,realm,service,srealm,lifetime,password)
     Tries to get an initial ticket for 'user' using 'password'.  This
     function is especially useful for verifying a user's password. See
     the Kerberos documentation for details.

get_svc_in_tkt(user,inst,realm,service,srealm,lifetime,srvtab)
     Tries to get an initial ticket for 'user' using the private key
     stored in 'srvtab'.

read_service_key(user,inst,realm,kvno,srvtab)
     Extracts the private key from a srvtab and returns it.  Use a kvno of
     0 to extract the first matching entry.

dest_tkt()
     Destroys the ticket file, much like kdestroy.

get_err_txt(n)
     Returns a string containing a textual description of the kerberos
     error number n.

CLASSES & METHODS
-----------------

   There are four classes in the Krb4 module, Ticket, AuthDat, Creds, and
KeySchedule.  They are all simply abstractions of Kerberos 4 structures.
You almost never need to worry about creating new objects-the functions
which return these objects create them for you.  The one exception is when
you need to construct a Ticket object for rd_req().  See below for details.

Ticket
     Contains a ticket for a specified service, instance, and realm.

new(dat)
     Returns a new Ticket object containing the data in 'dat'.  You must
     create a new Ticket object on the server side for passing to rd_req().

dat
     The data contained in the ticket.  Looks like junk to the naked eye.

length
     The length of the data contained in 'dat'.

AuthDat
     Contains the contents of the AUTH_DAT structure returned by rd_req().
     See below for the goodies.

pname
     Returns the principal's name.

pinst
     Returns the principal's instance.

prealm
     Returns the principal's realm.

session
     The session key.  Pass this to get_key_sched() to obtain a key
     schedule for encryption.

k_flags
     Flags from the ticket.

checksum
     The checksum from the ticket.  See mk_req().

life
     Life of the ticket.

time_sec
     The time the ticket was issued.  localtime() can convert this to a
     nicer format.

address
     The address in the ticket.  Useful for mutual authentication.

reply
     Reply to send to the client (not implemented yet).

Creds
     Contains information retreived from your ticket file.

service
     The service name.

instance
     The instance

realm
     The realm

session
     Returns the session key.  Pass this to get_key_sched() to obtain a key
     schedule for encryption.

lifetime
     The lifetime of the ticket.

kvno
     The key version number.

ticket
     The ticket itself.

issue_date
     The date the ticket was issued.

pname
     The name of the principal.

pinst
     The instance of the principal.

KeySchedule
     You don't need to fool around with this.

AUTHOR
======

   Jeff Horwitz <jhorwitz@umich.edu>

SEE ALSO
========

   perl(1).

Perl extension for Kerberos 5
*****************************

NAME
====

   Krb5 - Perl extension for Kerberos 5

SYNOPSIS
========

   use Krb5;

   Krb5::init_context(); Krb5::init_ets();

DESCRIPTION
===========

   Krb5 is an object oriented interface to the Kerberos 5 API.  Both the
implementation and documentation are nowhere near complete, and may require
previous experience with Kerberos 5 programming.  Most of the functions
here are documented in detail in the Kerberos 5 API documentation.

FUNCTIONS
---------

error(n)
     Returns the error code from the most recent Krb5 call.  If provided
     with an error code 'n', this function will return a textual
     description of the error.

init_context()
     Initializes a context for the application.  Returns a Krb5::Context
     object, or undef if there was an error.  Should be called along with
     init_ets at the beginning of a script.

init_ets()
     Initializes the Kerberos error tables.  Should be called along with
     init_context at the beginning of a script.

get_default_realm()
     Returns the default realm of your host.

get_host_realm(host)
     Returns the realm of the specified host.

get_krbhst(realm)
     Returns a list of the Kerberos servers from the specified realm.

build_principal_ext(p)
     Not like the actual krb5_build_principal_ext.  This is legacy code
     from Malcolm's code, which I'll probably change in future releases.
     In any case, it creates a 'server' principal for use in getting a
     TGT.  Pass it the principal for which you would like a TGT.

parse_name(name)
     Converts a string representation of a principal to a principal
     object.  You can use this to create a principal from your username.

sname_to_principal(hostname,sname,type)
     Generates a server principal from the given hostname, service, and
     type.  Type can be one of the following: NT_UNKNOWN, NT_PRINCIPAL,
     NT_SRV_INST, NT_SRV_HST, NT_SRV_XHST, NT_UID.  See the Kerberos
     documentation for details.

cc_resolve(name)
     Returns a credentials cache identifier which corresponds to the given
     name.  'name' must be in the form TYPE:RESIDUAL.  See the Kerberos
     documentation for more information.

cc_default_name()
     Returns the name of the default credentials cache, which may be
     equivalent to KRB5CCACHE.

cc_default()
     Returns a Krb5::Ccache object representing the default credentials
     cache.

kt_resolve(name)
     Returns a Krb5::Keytab object representing the specified keytab name.

get_in_tkt_with_password(client,server,password,cc)
     Attempt to get an initial ticket for the client.  'client' is a
     principal object for which you want an initial ticket.  'server' is a
     principal object for the service (usually krbtgt/REALM@REALM).
     'password' is the password for the client, and 'cc' is a Krb5::Ccache
     object representing the current credentials cache.  Returns a
     Kerberos error code.

mk_req(auth_context,ap_req_options,service,hostname,in,cc)
     Obtains a ticket for a specified service and returns a KRB_AP_REQ
     message suitable for passing to rd_req.  'auth_context' is the
     Krb5::AuthContext object you want to use for this connection,
     'ap_req_options' is an OR'ed representation of the possible options
     (see Kerberos docs), 'service' is the name of the service for which
     you want a ticket (like 'host'), hostname is the hostname of the
     server, 'in' can be any user-specified data that can be verified at
     the server end, and 'cc' is your credentials cache object.

rd_req(auth_context,in,server,keytab)
     Parses a KRB_AP_REQ message and returns its contents in a
     Krb5::Ticket object.  'auth_context' is the connection's
     Krb5::AuthContext object, 'in' is the KRB_AP_REQ message (usually
     from mk_req), and server is the expected server's name for the
     ticket.  'keytab' is a Krb5::Keytab object for the keytab you want to
     use.  Specify 'undef' or leave off to use the default keytab.

mk_priv(auth_context,in)
     Encrypts 'in' using parameters specified in auth_context, and returns
     the encrypted data.  Requires use of a replay cache.

rd_priv(auth_context,in)
     Decrypts 'in' using parameters specified in auth_context, and returns
     the decrypted data.

sendauth(auth_context,fh,version,client,server,options,in,in_creds,cc)
     Obtains and sends an authenticated ticket from a client program to a
     server program using the filehandle 'fh'.  'version' is an
     application-defined version string that recvauth compares to its own
     version string.  'client' is the client principal, e.g.
     username@REALM.  'server' is the service principal to which you are
     authenticating, e.g. service.hostname@REALM.  The only useful option
     right now is AP_OPTS_MUTUAL_REQUIRED, which forces sendauth to
     perform mutual authentication with the server.  'in' is a string that
     will be received by recvauth and verified by the server-it's up to the
     application.  'in_creds' is not yet supported, so just use 'undef'
     here.  'cc' should be set to the current credentials cache.  sendauth
     returns true on success and undefined on failure.

recvauth(auth_context,fh,version,server,keytab)
     Receives authentication data from a client using the sendauth
     function through the filehandle 'fh'.  'version' is as described in
     the sendauth section.  'server' is the server principal to which the
     client will be authenticating.  'keytab' is a Krb5::Keytab object
     specifying the keytab to use for this service.  recvauth returns a
     Krb5::Ticket object on success or undefined on failure.

genaddrs(auth_context,fh,flags)
     Uses the open socket filehandle 'fh' to generate local and remote
     addresses for auth_context.  Flags should be one of the following,
     depending on the type of address you want to generate (flags can be
     OR'ed):

     KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR
     KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR
     KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR
     KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR

gen_portaddr(addr,port)
     Generates a local port address that can be used to name a replay
     cache.  'addr' is a Krb5::Address object, and port is a port number
     in network byte order.  For generateing a replay cache name, you
     should supply the local address of the client and the socket's local
     port number.  Returns a Krb5::Address object containing the address.

gen_replay_name(addr,string)
     Generate a unique replay cache name.  'addr' is a Krb5::Address object
     created by gen_portaddr.  'string' is used as a unique identifier for
     the replay cache.  Returns the replay cache name.

get_server_rcache(name)
     Returns a Krb5::Rcache object using the replay cache name 'name.'

CLASSES & METHODS
-----------------

Krb5::Principal
     Kerberos 5 princpal object.

    o realm
          Returns the realm of the principal.

    o type
          Returns the type of the principal.

    o data
          Returns a list containing the components of the principal
          (everything before the realm).

Krb5::Ccache
     Kerberos 5 credentials cache object.

    o initialize(p)
          Creates/refreshes a credentials cache for the primary principal
          'p'.  If the cache already exists, its contents are destroyed.

    o get_name
          Returns the name of the credentials cache.

    o get_principal
          Returns the primary principal of the credentials cache.

    o destroy
          Destroys the credentials cache and releases all resources it
          used.

Krb5::AuthContext
     Kerberos 5 auth_context object.

    o new
          Allocates memory for a new Krb5::AuthContext object and returns
          it.

    o setaddrs(localaddr,remoteaddr)
          Sets the local and remote addresses for the AuthContext object.
          'localaddr' and 'remoteaddr' are Krb5::Address objects, usually
          of type ADDRTYPE_INET.

    o getaddrs()
          Returns a list containing the local and the remote address of the
          AuthContext object.

    o setrcache(rc)
          Sets the replay cache for auth_context.  'rc' is a Krb5::Rcache
          object generated by get_server_rcache.

Krb5::Ticket
     Kerberos 5 ticket object.

    o server
          Returns the server stored in the ticket.

    o enc_part2
          Returns a Krb5::EncTktPart object representation of the ticket
          data.  See below.

Krb5::EncTktPart
     Object representation of the krb5_enc_tkt_part structure.

    o client
          The client principal contained in the ticket.

AUTHOR
======

   Jeff Horwitz (jhorwitz@umich.edu)

ACKNOWLEDGEMENTS
================

   Based on the original work by Doug MacEachern and Malcolm Beattie.  Code
contributions from Scott Hutton (shutton@indiana.edu).

SEE ALSO
========

   perl(1), kerberos(1).

RCX
***

NAME
====

   RCX

SYNOPSIS
========

     use LOGO::RCX;

     $rcx = new LEGO::RCX();

     #
     # Turn motor A on for 10 seconds, then turn
     # it off
     #

     $rcx->motorOn( "A" );

     sleep( 10 );

     $rcx->motorOff( "A" );

DESCRIPTION
===========

   This module allows one to communicate with the Lego MindStorms(R) RCX
brick from a workstation through the IR tower.

   The internals of this module are based of the *rcx.tcl* by Peter
Pletcher <peterp@autobahn.org> and Laurent Demailly <L@Demailly.com>.  I
have hower made my external interface to this module OO based, and changed
the way a few things are done.

   Without there tcl module I would have never been able to complete this
in a timely manner.  Thanks guys.

METHODS
=======

ping() or alive()
     Check to see if RCX is on and responding.  A defined value on the
     return means it is alive, an undef means it is not alive.

motorOn( motors )
     Turns motor(s) on

     Motors are specifed in string format    eg: "A"    eg: "bc"

motorOff( motors )
     Turns motor(s) off

     Motors are specifed in string format    eg: "A"    eg: "bc"

motorFloat( motors )
     Floats motor(s) output

     Motors are specifed in string format    eg: "A"    eg: "bc"

motorPower( motors, power )
     Sets the motors power to value from 0-7

     Motors are specifed in string format    eg: "A"    eg: "bc"

motorDir( motors, direction
     Sets the motors direction which can be "forward", "reverse", or
     "toggle"

     Motors are specifed in string format    eg: "A"    eg: "bc"

beep( sound );
     Plays on of the following sounds

          0  Blip
          1  Beep beep
          2  Downward tones
          3  Upward tones
          4  Low buzz
          5  Fast upward tones

tone( frequence, duration )
     Plays a tone of a specific frequency for a length of duration

     frequency is in Hz and duration is in 1/100th of a second.

display( display )
     Selects the display for the RCX.

     The valid display values are:

          0 Watch
          1 Sensor 1
          2 Sensor 2
          3 Sensor 3
          4 Motor A
          5 Motor B
          6 Motor C

powerOff()
     Powers the RCX off.

powerDelay( delay )
     Sets the power off delay time for the RCX.  The delay is measured in
     minutes.  A 0 value tells the RCX to never power off, and vuture
     powerOff() calls will fail.

program( program_number )
     Sets the RCX to be on the specified program number.  The valid
     program_number values ares 1-5.

watch( hour, minutes)
     Sets the RCX's watch to hour house and minute mintutes. hour is 0-23
     and minutes is 0-59.

messageSet( message )
     Set a message in the RCX.  Valid message values are 0-255.

start( task|name ) || start()
     Starts a specific task running.  If no task is specified it defaults
     to task 0.  Valid task values are 0-9.

     If the *loadNQClist* method has been called then you can specify a
     task name

stop( task|name ) || stop();
     Stops a specific task.  If no task is specified it will stop all
     running tasks.

     If the *loadNQClist* method has been called then you can specify a
     task name

call( subnumber|name )
     Call a subroutine.

     If the *loadNQClist* method has been called then you can specify a
     subroutine name.

clearTimer( timer )
     This will clear the selected RCX timer.  The timer values are from
     0-3.

clearSensor( sensor_number )
     This will clear the counter associated with sensor_number sensor.

setSensorType( sensor_number, sensor_type )
     This will set the sensor sensor_number's type to sensor_type.  The
     type value can be any one of the following.

          $SENSOR_TYPE_RAW
          $SENSOR_TYPE_TOUCH
          $SENSOR_TYPE_TEMPERATURE
          $SENSOR_TYPE_LIGHT
          $SENSOR_TYPE_ROTATION

setSensorMode( sensor_number, sensor_mode, [ slope ] )
     This will set the sensor sensor_number's mode to sensor_mode, with
     said slope.  If slope is omited it defaults to 0.  This is like NQC.

     The mode value can be any one of the following.

          $SENSOR_MODE_RAW
          $SENSOR_MODE_BOOL
          $SENSOR_MODE_EDGE
          $SENSOR_MODE_PULSE
          $SENSOR_MODE_PERCENT
          $SENSOR_MODE_CELSIUS
          $SENSOR_MODE_FAHRENHEIT
          $SENSOR_MODE_ROTATION

setSensor( sensor_number, sensor_kind )
     This will set the sensor sensor_number's kind to sensor_kind. This is
     like the NQC function *SetSensor*.

     The kind value can be any one of the following.

          $SENSOR_TOUCH
          $SENSOR_LIGHT
          $SENSOR_ROTATION
          $SENSOR_CELSIUS
          $SENSOR_FAHRENHEIT
          $SENSOR_PULSE
          $SENSOR_EDGE

getReg( register ) | getVar( variable )
     Get the value of a variable/register (the same thing) in the RCX.
     The register/variable can be from 0-31.

     If the *loadNQClist* method has been called then you can specify a
     variable name instead of a number.

setReg( register, value ) | setVar( variable, value );
     Set the value of a variable/register (the same thing) in the RCX to
     value.  The register/variable can be from 0-31.

     If the *loadNQClist* method has been called then you can specify a
     variable name instead of a number.

addReg( register, value ) | addVar( register, value )
     Add value to a register and store back in register.

subReg( register, value ) | subVar( register, value )
     Subtract value from a register and store back in register.

mulReg( register, value ) | mulVar( register, value )
     Multiply value to a register and store back in register.

divReg( register, value ) | divVar( register, value )
     Divide value into a register and store back in register.

andReg( register, value ) | andVar( register, value )
     And value with a register and store back in register.

orReg( register, value ) | orVar( register, value )
     Or value with a register and store back in register.

getSensor( sensor_number )
     Get value of a sensor sensor_number.  sensor_number can be 1-3.

getSensorType( sensor_number )
     Get type of a sensor  sensor_number.  sensor_number can be 1-3.

getSensorMode( sensor_number )
     Get mode of a sensor  sensor_number.  sensor_number can be 1-3.

getSensorRaw( sensor_number )
     Get raw value of a sensor  sensor_number.  sensor_number can be 1-3.

getSensorBool( sensor_number )
     Get boolean value of a sensor  sensor_number.  sensor_number can be
     1-3.

setTXRange( range )
     Set the Transmit range of the RCX.  Ranges are eithor "short" or
     "long"

deleteAllTasks()
     Delete all tasks in current program

deleteTask( task )
     Delete <task> task in current program.

     If the *loadNQClist* method has been called then you can specify a
     task name.

deleteAllSubs()
     Delete a subroutines in current program

deleteSub( sub )
     Delete all subroutines in current program

     If the *loadNQClist* method has been called then you can specify a
     subroutine name.

getBattery()
     Returns the battery voltage in volts.

getVersion()
     Returns the version of the ROM and Firmware in the following order.
     ( $ROMMajor, $ROMMinor, $FIRMMajor, $FIRMMinor );

setCommTimeout( timeout )
     Sets the timeout in seconds for all commands sent to the RCX.
     Default is 2 seconds.

uploadDatalog()
     Returns an array of the datalog.  Each item in the data log has two
     elements in the array. The first is the type of data being loged, and
     the second is the value of the data.  The different types are listed
     as follows (taken from
     http://graphics.stanford.edu/~kekoa/rcx/opcodes.html

          0x00-0x1f
                  Variable value (source 0, variables 0..31)
          0x20-0x23
                  Timer value (source 1, timers 0..3)
          0x40-0x42
                  Sensor reading (source 9, sensors 0..2)
          0x80
                  Clock reading (source 14)

loadNQClist( nqc_list_file_name )
     This method will read in a list file produced by nqc version 2.0.  It
     parses out the variable, task, and subrouting information to allow
     you to use names in the related calls instead of just the numbers.
     This will also allow the fredom to move things around with out
     impacting the code.

NOTES
=====

   I have developed this software under Linux.  I know it works there.

AUTHORS
=======

   John C. Quillan quillan@doitnow.com

MODIFICATION HISTORY
====================

     01/29/2000   VER 0.5   First Version
     02/04/2000   VER 0.6   Removed some commented code
                            Added posix serial code.
     02/06/2000   VER 0.7   Added the alive/ping method
                            Added the time out for communications.
                            Added the setCommTimeout method
                            Added the uploadDatalog method
     02/22/2000   VER 0.8   Fixed wrong named method in NQC translation
                            Added getVersion
                            Added clearSensor
                            Started sensor config code
                            Moved package RCX to Lego::RCX
                            Made a real perl module with Makefile.PL
                            Added div,mul,add,sub,and,or
                              variable
                            Added setTXRange
                            Added deleteAllTasks and deleteAllSubs
                            Added deleteTask and deleteSub
     02/29/2000   VER 0.9   Moved package from Lego::RCX to LEGO::RCX
                            Added setSensor, setSensorMode, setSensorType
                            Fixed / 1000 bug in getReg.
                            Fixed bug in pattern matches that was not catching
                             0x0a characters.  Now a single line match.

     04/16/2000   VER 1.00  Clean up source a little bit.
                            Made README more descriptive for CPAN users.
                            Fixed some typo in the pod documentation for the
                             usage. Sorry for any problems this may have
                             caused.
                            Fixed a typo in the warning.
                            Added a few samples to start off with

Perl extension for blah blah blah
*********************************

NAME
====

   LISP - Perl extension for blah blah blah

SYNOPSIS
========

     use LISP;

     my $list = LISP->new(\@array);
     my $lambda = LISP->new(\&function);

     my $cons_cell = LISP->cons($car, $cdr);
     my $list = LISP::list(@array);

DESCRIPTION
===========

   Implements Lisp-like linked-lists and functions/methods.

Methods     new ([ARRAYREF|CODEREF])         If given an array reference, returns a linked list with every array reference         within the given array reference also expanded into another list.
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

     If given a subroutine reference, blesses the reference into LISP::Lamba and
     returns the reference.

     cons (CAR, CDR)
         Creates a new cons-cell and returns it.

     list (ARRAY)
         Like the new method, but called with an array as an argument instead of an
         array reference, and is more meant to be called as a function rather than a
         method (This could change).

EXPORT
------

   None by default.

     :all
         This will export cons and list from this package, listp and nilp from
         LISP::List, and mapcar and apply from LISP::Lambda.

AUTHOR
======

   Douglas Wilson, dwilson@gtemail.net

SEE ALSO
========

   LISP::List, LISP::Lambda, perl(1).

Perl extension for implementing Lisp Lambda expressions
*******************************************************

NAME
====

   LISP::Lambda - Perl extension for implementing Lisp Lambda expressions

SYNOPSIS
========

     use LISP::Lambda;

     my $lambda = LISP::Lambda->new(\&sub);

     $lambda->mapcar(@lists)
     $lambda->apply($list);

DESCRIPTION
===========

   Lambda expressions are Lisp's version of anonymous subroutines, and may
be blessed into this package so that you can use them or the provided
'meta-methods' in an object oriented way. If you want to want to use them
as regular functions, you may export them. Any reference to lists here
refers to linked lists ala Lisp, and not to perl lists/arrays.

Methods
-------

     mapcar(FUNCTION, LISTS)
     	mapcar applies the FUNCTION to the list formed by the first
     	element of each list, then to the second, etc., up to the
     	length of the shortest list, and returns a list of the results.

     $list = LISP->new([[a],[b],[c],[d]]); # ((a) (b) (c) (d))
     $car  = $list->can('car');
     $cars = $car->mapcar($list);
     print   $cars->string;                # Prints (a b c d);

     $list1  = LISP->new([qw(1 2 3)]]);
     $list2  = LISP->new([qw(4 5 6)]]);
     $lister = $list1->can('list');
     $list3  = mapcar($lister, $list1, $list2);
     print $list3->string       # Prints ((1 4) (2 5) (3 6))

     apply(FUNCTION, LIST)
     	apply returns the result of executing FUNCTION using the subnodes of
     	LIST as arguments.

     $list      = LISP->new([qw(1 2 3)]);
     $totaller  = sub { my $total=0; $total += $_ for @_; $total };
     print apply($totaller, $list);   # Prints 6

     $inc = LISP->new(sub { map {$_ + 1} @_ });
     my @ary = $inc->apply($list);
     print "@ary";     # Prints 2 3 4

EXPORT
------

     :all
     	 exports methods mapcar and apply, and each may be exported individually.

AUTHOR
======

   Douglas Wilson, dwilson@gtemail.net

SEE ALSO
========

   perl(1).

Perl extension for implementing linked lists as in Lisp
*******************************************************

NAME
====

   LISP::List - Perl extension for implementing linked lists as in Lisp

SYNOPSIS
========

     use LISP::List;

     $list = LISP->new([qw(1 2 3)]);

     $car = $list->car;
     $cdr = $list->cdr;

     $caar = $list->cddr;
     $cddr = $list->cddr;
     $cadr = $list->cadr; # etc.

     $list->rplaca($car);
     $list->rplacd($cdr);

     @sub_nodes = $list->sub_nodes;
     $rev_list = $list->reverse;
     $new_list = $list->append(@lists);

     $scalar = $list->pop;
     $list->push($element);
     $last_list   = $list->last;
     $length      = $list->length;
     $is_a_list     = $list->listp;
     $is_empty_list = $list->nilp;

     $new_list = $list->mapcar($code_ref, [@more_lists]);
     $result   = $list->apply($code_ref);

     $string   = $list->string;

DESCRIPTION
===========

   This is an implementation of linked lists, with Lisp-like functionality.
Any reference to lists here refers to Lisp-like linked lists, while
@variables in perl will be called arrays.

Explanation     Here is a brief description of linked lists in Lisp.
--------------------------------------------------------------------

     (1 2 3 4) is short hand for:
     (1 . (2 . (3 . (4 . NIL))))
     which graphically represented as:
     .--.--.--.--NIL
     |  |  |  |
     1  2  3  4

     The list 'starts' with the node in the upper-left corner.
     The car of a list node is the element below a node, and the cdr of a
     node is the element to the right of a node. In a 'true' list, the cdr of
     a list is always a list, and the 'last' cdr is NIL, which represents
     the empty list.

     List nodes are also called 'cons' cells. Cons cells do not have to have
     a list (NIL or otherwise) as their cdr. Things referred to as lists below
     do not always refer to a 'true' list necessarily, and may also apply to cons cells.

Methods
-------

     new (ARRAY_REF)
         Calling LISP::List->new($array_ref), or LISP->new($array_ref) for short,
         will create a new linked list of the elements of $array_ref, with each
         array reference within $array_ref itself becoming a linked list.

     car
         Returns the car of a list.

     cdr
         Returns the cdr of a list.

     caar, cddr, cadr, etc.
         E.g. cadr returns the car of the cdr of a list, any method matching
         /c[ad][ad]+r/ is autoloaded to return the appropriate chaining of car and cdr.

     sub_nodes
         Returns all of the car's of the top-level nodes of a list in an array.

     reverse
         Returns a copy of the top-level nodes of a list in reverse.

     append (LISTS)
         Copies the top-level nodes of all but the last list and appends all of the
         copies, including the last list, together into a new list.

     pop
         Returns the car of a list and sets the list to the cdr of itself.

     push (ELEMENT)
         Creates a new cons cell with the given element as its car, and the list as
         its cdr, and sets the list to the new cons cell.

     last
         Returns the last non-NIL top-level node of the LIST.

     length
         Returns the number of non-NIL top-level nodes of a list.

     listp
         Returns true if its argument is a list (This method may be exported and used as
         a function).

     nilp
         Returns true if its argument is NIL (This method may be exported and used as
         a function).

     string
         Returns a string representation of a list.

     apply (CODEREF)
         Same as apply in LISP::Lambda but takes the arguments in a different order, so
         the list is the object instead of the subroutine.

     mapcar (CODEREF, [@MORE_LISTS])
         Same as mapcar in LISP::Lambda but takes arguments in a different order, so the
         list is the object instead of the subroutine.

EXPORT
------

   Nothing exported by default.

     :all
         exports the methods/functions listp and nilp so they can be used as functions on
         values other than lists.

AUTHOR
======

   Douglas Wilson, dwilson@gtemail.net

SEE ALSO
========

   perl(1).

Library for WWW access in Perl
******************************

NAME
====

   LWP - Library for WWW access in Perl

SYNOPSIS
========

     use LWP;
     print "This is libwww-perl-$LWP::VERSION\n";

DESCRIPTION
===========

   Libwww-perl is a collection of Perl modules which provides a simple and
consistent application programming interface (API) to the World-Wide Web.
The main focus of the library is to provide classes and functions that
allow you to write WWW clients, thus libwww-perl is a WWW client library.
The library also contain modules that are of more general use.

   Most modules in this library are object oriented.  The user agent,
requests sent and responses received from the WWW server are all
represented by objects.  This makes a simple and powerful interface to
these services.  The interface should be easy to extend and customize for
your needs.

   The main features of the library are:

   * Contains various reusable components (modules) that can be used
     separately or together.

   * Provides an object oriented model of HTTP-style communication.  Within
     this framework we currently support access to http, https, gopher,
     ftp, news, file, and mailto resources.

   * Provides a full object oriented interface or a very simple procedural
     interface.

   * Supports the basic and digest authorization schemes.

   * Supports transparent redirect handling.

   * Supports access through proxy servers.

   * Provides parser for `robots.txt' files and a framework for
     constructing robots.

   * Cooperates with Tk.  A simple Tk-based GUI browser called 'tkweb' is
     distributed with the Tk extension for perl.

   * Implements HTTP content negotiation algorithm that can be used both
     in protocol modules and in server scripts (like CGI scripts).

   * Supports HTTP cookies.

   * A simple command line client application called `lwp-request'.

HTTP STYLE COMMUNICATION
========================

   The libwww-perl library is based on HTTP style communication. This
section tries to describe what that means.

   Let us start with this quote from the HTTP specification document
<URL:http://www.w3.org/pub/WWW/Protocols/>:

     The HTTP protocol is based on a request/response paradigm. A client
     establishes a connection with a server and sends a request to the
     server in the form of a request method, URI, and protocol version,
     followed by a MIME-like message containing request modifiers, client
     information, and possible body content. The server responds with a
     status line, including the message's protocol version and a success or
     error code, followed by a MIME-like message containing server
     information, entity meta-information, and possible body content.

   What this means to libwww-perl is that communication always take place
through these steps: First a request object is created and configured.
This object is then passed to a server and we get a response object in
return that we can examine. A request is always independent of any
previous requests, i.e. the service is stateless.  The same simple model
is used for any kind of service we want to access.

   For example, if we want to fetch a document from a remote file server,
then we send it a request that contains a name for that document and the
response will contain the document itself.  If we access a search engine,
then the content of the request will contain the query parameters and the
response will contain the query result.  If we want to send a mail message
to somebody then we send a request object which contains our message to
the mail server and the response object will contain an acknowledgment
that tells us that the message has been accepted and will be forwarded to
the recipient(s).

   It is as simple as that!

The Request Object
------------------

   The libwww-perl request object has the class name HTTP::Request.  The
fact that the class name uses `HTTP::' as a prefix only implies that we
use the HTTP model of communication.  It does not limit the kind of
services we can try to pass this request to.  For instance, we will send
HTTP::Requests both to ftp and gopher servers, as well as to the local
file system.

   The main attributes of the request objects are:

   * The method is a short string that tells what kind of request this is.
     The most used methods are GET, PUT, POST and HEAD.

   * The url is a string denoting the protocol, server and the name of the
     "document" we want to access.  The url might also encode various
     other parameters.

   * The headers contain additional information about the request and can
     also used to describe the content.  The headers are a set of
     keyword/value pairs.

   * The content is an arbitrary amount of data.

The Response Object
-------------------

   The libwww-perl response object has the class name `HTTP::Response'.
The main attributes of objects of this class are:

   * The code is a numerical value that indicates the overall outcome of
     the request.

   * The message is a short, human readable string that corresponds to the
     code.

   * The headers contain additional information about the response and
     describe the content.

   * The content is an arbitrary amount of data.

   Since we don't want to handle all possible code values directly in our
programs, a libwww-perl response object has methods that can be used to
query what kind of response this is.  The most commonly used response
classification methods are:

is_success()
     The request was was successfully received, understood or accepted.

is_error()
     The request failed.  The server or the resource might not be
     available, access to the resource might be denied or other things
     might have failed for some reason.

The User Agent
--------------

   Let us assume that we have created a request object. What do we
actually do with it in order to receive a response?

   The answer is that you pass it to a *user agent* object and this object
takes care of all the things that need to be done (like low-level
communication and error handling) and returns a response object. The user
agent represents your application on the network and provides you with an
interface that can accept *requests* and return *responses*.

   The user agent is an interface layer between your application code and
the network.  Through this interface you are able to access the various
servers on the network.

   The libwww-perl class name for the user agent is `LWP::UserAgent'.
Every libwww-perl application that wants to communicate should create at
least one object of this class. The main method provided by this object is
request(). This method takes an HTTP::Request object as argument and
(eventually) returns a `HTTP::Response' object.

   The user agent has many other attributes that let you configure how it
will interact with the network and with your application.

   * The timeout specifies how much time we give remote servers to respond
     before the library disconnects and creates an internal timeout
     response.

   * The *agent* specifies the name that your application should use when
     it presents itself on the network.

   * The from attribute can be set to the e-mail address of the person
     responsible for running the application.  If this is set, then the
     address will be sent to the servers with every request.

   * The *parse_head* specifies whether we should initialize response
     headers from the <head> section of HTML documents.

   * The proxy and *no_proxy* attributes specify if and when to go through
     a proxy server. <URL:http://www.w3.org/pub/WWW/Proxies/>

   * The *credentials* provide a way to set up user names and passwords
     needed to access certain services.

   Many applications want even more control over how they interact with
the network and they get this by sub-classing `LWP::UserAgent'.  The
library includes a sub-class, LWP::RobotUA, for robot applications.

An Example
----------

   This example shows how the user agent, a request and a response are
represented in actual perl code:

     # Create a user agent object
     use LWP::UserAgent;
     $ua = new LWP::UserAgent;
     $ua->agent("AgentName/0.1 " . $ua->agent);

     # Create a request
     my $req = new HTTP::Request POST => 'http://www.perl.com/cgi-bin/BugGlimpse';
     $req->content_type('application/x-www-form-urlencoded');
     $req->content('match=www&errors=0');

     # Pass request to the user agent and get a response back
     my $res = $ua->request($req);

     # Check the outcome of the response
     if ($res->is_success) {
         print $res->content;
     } else {
         print "Bad luck this time\n";
     }

   The $ua is created once when the application starts up.  New request
objects should normally created for each request sent.

NETWORK SUPPORT
===============

   This section discusses the various protocol schemes and the HTTP style
methods that headers may be used for each.

   For all requests, a "User-Agent" header is added and initialized from
the $ua->agent attribute before the request is handed to the network
layer.  In the same way, a "From" header is initialized from the $ua->from
attribute.

   For all responses, the library adds a header called "Client-Date".
This header holds the time when the response was received by your
application.  The format and semantics of the header are the same as the
server created "Date" header.  You may also encounter other "Client-XXX"
headers.  They are all generated by the library internally and are not
received from the servers.

HTTP Requests
-------------

   HTTP requests are just handed off to an HTTP server and it decides what
happens.  Few servers implement methods beside the usual "GET", "HEAD",
"POST" and "PUT", but CGI-scripts may implement any method they like.

   If the server is not available then the library will generate an
internal error response.

   The library automatically adds a "Host" and a "Content-Length" header
to the HTTP request before it is sent over the network.

   For GET request you might want to add the "If-Modified-Since" header to
make the request conditional.

   For POST request you should add the "Content-Type" header.  When you
try to emulate HTML <FORM> handling you should usually let the value of
the "Content-Type" header be "application/x-www-form-urlencoded".  See
Lwpcook, for examples of this.

   The libwww-perl HTTP implementation currently support the HTTP/1.0
protocol.  HTTP/0.9 servers are also handled correctly.

   The library allows you to access proxy server through HTTP.  This means
that you can set up the library to forward all types of request through
the HTTP protocol module.  See LWP/UserAgent, for
documentation of this.

HTTPS Requests
--------------

   HTTPS requests are HTTP requests over an encrypted network connection
using the SSL protocol developed by Netscape.  Everything about HTTP
requests above also apply to HTTPS requests.  In addition the library will
add the headers "Client-SSL-Cipher", "Client-SSL-Cert-Subject" and
"Client-SSL-Cert-Issuer" to the response.  These headers denote the
encryption method used and the name of the server owner.

   The request can contain the header "If-SSL-Cert-Subject" in order to
make the request conditional on the content of the server certificate.  If
the certificate subject does not match, no request is sent to the server
and an internally generated error response is returned.  The value of the
"If-SSL-Cert-Subject" header is interpreted as a Perl regular expression.

FTP Requests
------------

   The library currently supports GET, HEAD and PUT requests.  GET
retrieves a file or a directory listing from an FTP server.  PUT stores a
file on a ftp server.

   You can specify a ftp account for servers that want this in addition to
user name and password.  This is specified by including an "Account"
header in the request.

   User name/password can be specified using basic authorization or be
encoded in the URL.  Failed logins return an UNAUTHORIZED response with
"WWW-Authenticate: Basic" and can be treated like basic authorization for
HTTP.

   The library supports ftp ASCII transfer mode by specifying the "type=a"
parameter in the URL.

   Directory listings are by default returned unprocessed (as returned
from the ftp server) with the content media type reported to be
"text/ftp-dir-listing". The `File::Listing' module provides methods for
parsing of these directory listing.

   The ftp module is also able to convert directory listings to HTML and
this can be requested via the standard HTTP content negotiation mechanisms
(add an "Accept: text/html" header in the request if you want this).

   For normal file retrievals, the "Content-Type" is guessed based on the
file name suffix. See LWP/MediaTypes.

   The "If-Modified-Since" request header works for servers that implement
the MDTM command.  It will probably not work for directory listings though.

   Example:

     $req = HTTP::Request->new(GET => 'ftp://me:passwd@ftp.some.where.com/');
     $req->header(Accept => "text/html, */*;q=0.1");

News Requests
-------------

   Access to the USENET News system is implemented through the NNTP
protocol.  The name of the news server is obtained from the NNTP_SERVER
environment variable and defaults to "news".  It is not possible to
specify the hostname of the NNTP server in news: URLs.

   The library supports GET and HEAD to retrieve news articles through the
NNTP protocol.  You can also post articles to newsgroups by using
(surprise!) the POST method.

   GET on newsgroups is not implemented yet.

   Examples:

     $req = HTTP::Request->new(GET => 'news:abc1234@a.sn.no');

     $req = HTTP::Request->new(POST => 'news:comp.lang.perl.test');
     $req->header(Subject => 'This is a test',
                  From    => 'me@some.where.org');
     $req->content(<<EOT);
     This is the content of the message that we are sending to
     the world.
     EOT

Gopher Request
--------------

   The library supports the GET and HEAD methods for gopher requests.  All
request header values are ignored.  HEAD cheats and returns a response
without even talking to server.

   Gopher menus are always converted to HTML.

   The response "Content-Type" is generated from the document type encoded
(as the first letter) in the request URL path itself.

   Example:

     $req = HTTP::Request->new(GET => 'gopher://gopher.sn.no/');

File Request
------------

   The library supports GET and HEAD methods for file requests.  The
"If-Modified-Since" header is supported.  All other headers are ignored.
The host component of the file URL must be empty or set to "localhost".
Any other host value will be treated as an error.

   Directories are always converted to an HTML document.  For normal
files, the "Content-Type" and "Content-Encoding" in the response are
guessed based on the file suffix.

   Example:

     $req = HTTP::Request->new(GET => 'file:/etc/passwd');

Mailto Request
--------------

   You can send (aka "POST") mail messages using the library.  All headers
specified for the request are passed on to the mail system.  The "To"
header is initialized from the mail address in the URL.

   Example:

     $req = HTTP::Request->new(POST => 'mailto:libwww@perl.ord');
     $req->header(Subject => "subscribe");
     $req->content("Please subscribe me to the libwww-perl mailing list!\n");

OVERVIEW OF CLASSES AND PACKAGES
================================

   This table should give you a quick overview of the classes provided by
the library. Indentation shows class inheritance.

     LWP::MemberMixin   -- Access to member variables of Perl5 classes
       LWP::UserAgent   -- WWW user agent class
         LWP::RobotUA   -- When developing a robot applications
       LWP::Protocol          -- Interface to various protocol schemes
         LWP::Protocol::http  -- http:// access
         LWP::Protocol::file  -- file:// access
         LWP::Protocol::ftp   -- ftp:// access
         ...

     LWP::Authen::Basic -- Handle 401 and 407 responses
     LWP::Authen::Digest

     HTTP::Headers      -- MIME/RFC822 style header (used by HTTP::Message)
     HTTP::Message      -- HTTP style message
       HTTP::Request    -- HTTP request
       HTTP::Response   -- HTTP response
     HTTP::Daemon       -- A HTTP server class

     WWW::RobotRules    -- Parse robots.txt files
       WWW::RobotRules::AnyDBM_File -- Persistent RobotRules

   The following modules provide various functions and definitions.

     LWP                -- This file.  Library version number and documentation.
     LWP::MediaTypes    -- MIME types configuration (text/html etc.)
     LWP::Debug         -- Debug logging module
     LWP::Simple        -- Simplified procedural interface for common functions
     HTTP::Status       -- HTTP status code (200 OK etc)
     HTTP::Date         -- Date parsing module for HTTP date formats
     HTTP::Negotiate    -- HTTP content negotiation calculation
     File::Listing      -- Parse directory listings

MORE DOCUMENTATION
==================

   All modules contain detailed information on the interfaces they
provide.  The *lwpcook* manpage is the libwww-perl cookbook that contain
examples of typical usage of the library.  You might want to take a look
at how the scripts `lwp-request', `lwp-rget' and `lwp-mirror' are
implemented.

BUGS
====

   The library can not handle multiple simultaneous requests yet.  Also,
check out what's left in the TODO file.

ACKNOWLEDGEMENTS
================

   This package owes a lot in motivation, design, and code, to the
libwww-perl library for Perl 4, maintained by Roy Fielding
<fielding@ics.uci.edu>.

   That package used work from Alberto Accomazzi, James Casey, Brooks
Cutter, Martijn Koster, Oscar Nierstrasz, Mel Melchner, Gertjan van
Oosten, Jared Rhine, Jack Shirazi, Gene Spafford, Marc VanHeyningen,
Steven E. Brenner, Marion Hakanson, Waldemar Kebsch, Tony Sanders, and
Larry Wall; see the libwww-perl-0.40 library for details.

   The primary architect for this Perl 5 library is Martijn Koster and
Gisle Aas, with lots of help from Graham Barr, Tim Bunce, Andreas Koenig,
Jared Rhine, and Jack Shirazi.

COPYRIGHT
=========

     Copyright 1995-2000, Gisle Aas
     Copyright 1995, Martijn Koster

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AVAILABILITY
============

   The latest version of this library is likely to be available from CPAN
as well as:

     http://www.linpro.no/lwp/

   The best place to discuss this code is on the <libwww@perl.org> mailing
list.

a simple subclass of LWP::UserAgent to allow the user to type in username / password information if required for autentication.
*******************************************************************************************************************************

NAME
====

   LWP::AuthenAgent - a simple subclass of LWP::UserAgent to allow the
user to type in username / password information if required for
autentication.

SYNOPSIS
========

     use LWP::AuthenAgent;

     my $ua = new LWP::AuthenAgent;
     my $response = $ua->request( new HTTP::Request 'GET' => $url );

DESCRIPTION
===========

   LWP::AuthenAgent simple overloads the get_basic_credentials method of
LWP::UserAgent. It prompts the user for username / passsword for a given
realm, supressing tty echoing of the password. Authentication details are
stored in the object for each realm, so that they can be re-used in
subsequest requests for the same realm, if necessary.

METHODS
=======

   LWP::AuthenAgent inherits all the methods available in LWP::UserAgent.

SEE ALSO
========

     LWP::UserAgent
     Term::ReadKey

AUTHOR
======

   Ave Wrigley <Ave.Wrigley@itn.co.uk>

COPYRIGHT
=========

   Copyright (c) 1997 Canon Research Centre Europe (CRE). All rights
reserved.  This script and any associated documentation or files cannot be
distributed outside of CRE without express prior permission from CRE.

event driven protocol module interface
**************************************

NAME
====

   LWP::Conn - event driven protocol module interface

SYNOPSIS
========

     use LWP::Conn::XXX;
     $conn = LWP::Conn::XXX->new(ManagedBy => $mgr,
                                 Host      => $host,
                                 Port      => $port,
     	                      #...
                                );

DESCRIPTION
===========

   The *LWP::Conn* objects represent a connection to some server where one
or more request/response exchanges can take place.  There are different
subclasses for various types of the underlying (network) protocols.
(Talking about 'subclasses' is kind of a lie, since the base-class does
not really manifest itself as any real code.)

   *LWP::Conn* objects conform to the following interfaces when interacting
with their manager object (passed in as parameter during creation).  For
the normal setup, then manager will be a *LWP::Server* object.

   An *LWP::Conn* object is contructed with the new() method.  It takes
hash-style arguments and the 'ManagedBy' parameter is the only which is
mandatory for any LWP::Conn subclass.  It should be an reference to the
manager object that will get method callbacks when various events happen.
Other parameters might be mandatory depending on the specific subclass.

     $conn = LWP::Conn::XXX->new(MangagedBy => $mgr,
                                 Host => $host,
                                 Port => $port,
                                 ...);

   The constructor will return a reference to the *LWP::Conn* object or
undef.  If a connection object is returned, then the manager should wait
for callbacks methods to be invoked on itself.  A return of undef will
either indicate than we can't connect to the specified server or that all
requests has already been processed.  A manager can know the difference
based on whether get_request() has been invoked on it or not.

   The following methods are invoked by the created *LWP::Conn* object on
their manager.  The first two manage the request queue.  The last three
let the manager be made aware of the state of the connection.

     $mgr->get_request($conn);
     $mgr->pushback_request($conn, @requests);

     $mgr->connection_active($conn);
     $mgr->connection_idle($conn);
     $mgr->connection_closed($conn);

   The get_request() method should return a single `LWP::Request' object
or undef if there are no more requests to process.  It is passed a
reference to the connection object as argument.  If the connection objects
discover that it has been too greedy (calling get_request() too many
times), then it might want to return unprocessed request back to the
mangager.  It does so by calling the pushback_request() method with a
reference to itself and one or more request objects as arguments.  The
first request obtained by get_request() should never be pushed back.

   The following two methods can be invoked (usually by the manager) on a
living $conn object.  The activate() method can be invoked on a (usually
'idle') connection to make it start calling get_request() again.  The
stop() kills the connection (whatever state it is in).

     $conn->activate;
     $conn->stop;

   When a connection has received a response, then it will invoke the
following two methods on the request object (obtained using get_request()).

     $req->response_data($data, $res);
     $req->response_done($res);

   The response_data() method is invoked repeatedly as the body content of
the response is received from the network.  Invocation of this method is
optional and depends on the kind of connection object this is.  The
response_done() method is always invoked once for each request obtained.
It is called when the complete response has been received.

COPYRIGHT
=========

   Copyright 1998, Gisle Aas

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

event driven connection establishment
*************************************

NAME
====

   LWP::Conn::_Connect - event driven connection establishment

SYNOPSIS
========

     require LWP::Conn::_Connect;
     $conn = LWP::Conn::_Connect->new($host, $port, $timeout, $class, $opaque);

DESCRIPTION
===========

   The LWP::Conn::_Connect class encapsulate event driven Internet socket
connection establishment.  The constructor is called with a hostname and a
port to connect to, and will return an object derived from
IO::Socket::INET if connection establishment has been performed or is in
progress.  If the connection attempt fails right away then undef is
returned and $! will be the errno that connect(2) set.

   When the outcome of the connection attempt has been determined, then
the LWP::Conn::_Connect object will be re-blessed into the given $class
and one of the following methods will be called on it:

$conn->connected($opaque)
     Successful connection establishment.  The $conn is now connected.
     This call can even by made before the LWP::Conn::_Connect constructor
     returns.  The $opaque value passed to the LWP::Conn::_Connect
     constructor is passed as argument.

$conn->connect_failed($errmsg, $opaque)
     All addresses has been tried and all of them failed.  The error from
     the last connection attempt is passed as the first argument.  The
     $opaque value passed to the LWP::Conn::_Connect constructor is passed
     as the second.

   The $timeout value says how many seconds to allow for each connection
attempt.  A value of 0 indicate no timeout.  The $host argument can be a
single scalar or an array of scalar host names.  The $port argument must
be numeric.

BUGS
====

   The gethostbyname(3) call used in the constructor is blocking.

COPYRIGHT
=========

   Copyright 1998, Gisle Aas

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

debug routines for the libwww-perl library
******************************************

NAME
====

   LWP::Debug - debug routines for the libwww-perl library

SYNOPSIS
========

     use LWP::Debug qw(+ -conns);

     # Used internally in the library
     LWP::Debug::trace('send()');
     LWP::Debug::debug('url ok');
     LWP::Debug::conns("read $n bytes: $data");

DESCRIPTION
===========

   LWP::Debug provides tracing facilities. The trace(), debug() and
conns() function are called within the library and they log information at
increasing levels of detail. Which level of detail is actually printed is
controlled with the `level()' function.

   The following functions are available:

level(...)
     The `level()' function controls the level of detail being logged.
     Passing '+' or '-' indicates full and no logging respectively.
     Inidividual levels can switched on and of by passing the name of the
     level with a '+' or '-' prepended.  The levels are:

          trace   : trace function calls
          debug   : print debug messages
          conns   : show all data transfered over the connections

     The LWP::Debug module provide a special import() method that allows
     you to pass the level() arguments with initial use statement.  If a
     use argument start with '+' or '-' then it is passed to the level
     function, else the name is exported as usual.  The following two
     statements are thus equivalent (if you ignore that the second pollutes
     your namespace):

          use LWP::Debug qw(+);
          use LWP::Debug qw(level); level('+');

trace($msg)
     The `trace()' function is used for tracing function calls. The
     package and calling subroutine name is printed along with the passed
     argument. This should be called at the start of every major function.

debug($msg)
     The debug() function is used for high-granularity reporting of state
     in functions.

conns($msg)
     The `conns()' function is used to show data being transferred over
     the connections. This may generate considerable output.

Watch file descriptors and timers
*********************************

NAME
====

   LWP::EventLoop - Watch file descriptors and timers

SYNOPSIS
========

     use LWP::EventLoop;
     $mainloop = LWP::EventLoop->new;
     $mainloop->readable(\*STDIN, sub {sysread(STDIN, $buf, 100)});
     $mainloop->after(10, sub { print "10 sec later"} );
     $mainloop->run;

DESCRIPTION
===========

   The *LWP::EventLoop* class define objects that can watch file
descriptors and timers and will invoke callback methods when events on
these happens.  Usually you will only have a single instance of this class
in any application.  The *LWP::MainLoop* module creates a single instance
and provide an interface to it.  The *LWP::EventLoop* is really just a
wrapping of the select() function.

   The following methods are provided:

$e = LWP::EventLoop->new
     The constructor takes now arguments.

$e->readable($io, [$callback])
     Register the specified IO handle as being monitored for readable
     status.  When the handle becomes readable the specified callback will
     be invoked.  The handle can be unregistered by giving an undef
     argument as the $callback.

     Callbacks can either by an CODE reference (which is called with the
     handle as argument) or they can be a plain scalar strings which are
     taken to be method names that are called on the given handle object.
     The callback can also be an array reference.  The first element of the
     array must be a CODE reference or a method name.  The rest is taken to
     be additional arguments passed during callback invocation.

     The default callback is to invoke the $io->readable method.

$e->writable($io, [$callback])
     Like $e->readable, but watch the handle for writable status.  The
     default callback to invoke is the $io->writable method.

$e->timeout($io, $secs, [$callback])
     Register a callback to be invoked if nothing happens on the given IO
     handle for some number of seconds.  Callbacks take the same form as
     for $e->readable.  The default callback is to invoke the $io->inactive
     method.  Pass 0 as the $secs argument to disable timeout for this
     handle.

$e->activity($io, [$time]);
     Return time of last activity on the specified handle.  This is only
     valid if you have asked for a timeout() callback on the specified
     handle previously.

     The optional $time argument can be used to set this to some specified
     value.  If no $time argument is provided then the current time is
     recorded.  If the $time value is undef then the activity timestamp is
     not changed.

$e->after($secs, $timer_callback)
     Set up a callback to be invoked after the given number of seconds.
     The callback must be a CODE reference.  This method returns an
     identifier that can be used to cancel this timer using the $e->forget
     method.

$e->at($time, $timer_callback)
     Set up a callback to be invoked at the given time.  The $e->after is
     really the same as $e->at(time + $secs, $timer_callback).

$e->forget($io_timer,...)
     Unregister all callbacks for the given IO handles and timers.  One or
     more arguments can be given.  Each argument can either be an IO handle
     reference or an identifier as returned by $e->after or $e->at.

$e->forget_all
     Unregister all callbacks.  The state of the LWP::EventLoop will be as
     after construction.

$e->empty
     Return TRUE if no timer callbacks or IO handles to watch are
     registered.

$e->one_event( [$timeout] )
     Wait for a single event to happen (but no longer than $timeout
     seconds) and call the corresponding callback routine.  Can also return
     without calling any callback routine.

$e->run( [$timeout] )
     Call $e->one_event until either all timer callbacks and IO handles are
     gone or until the specified number of seconds has elapsed.

$e->dump
     Will print the state of the *LWP::EventLoop* object to the currently
     selected file handle.  Mainly useful for debugging.  Setting the
     $LWP::EventLoop::DEBUG variable to an TRUE value can also be useful
     while debugging.

SEE ALSO
========

   See LWP/MainLoop,

COPYRIGHT
=========

   Copyright 1997-1998, Gisle Aas

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Low level I/O capability
************************

NAME
====

   LWP::IO - Low level I/O capability

SYNOPSIS
========

     use LWP::IO ();

DESCRIPTION
===========

   The following functions are available:

LWP::IO::read($fd, $data, $size, $offset, $timeout)
LWP::IO::write($fd, $data, $timeout)
   These routines provide low level I/O with timeout capability for the
LWP library.  These routines will only be installed if they are not
already defined.  This fact can be used by programs that need to override
these functions.  Just provide replacement functions before you require
LWP. See also LWP/TkIO.

Give access to an single instance of LWP::EventLoop
***************************************************

NAME
====

   LWP::MainLoop - Give access to an single instance of LWP::EventLoop

SYNOPSIS
========

     use LWP::MainLoop qw(mainloop);
     mainloop->readable(\*STDIN, sub {sysread(STDIN, $buf, 100)});
     mainloop->after(10, sub { print "10 sec later"} );
     mainloop->run;

   or

     use LWP::MainLoop qw(readable after run);
     readable(\*STDIN, sub {sysread(STDIN, $buf, 100)});
     after(10, sub { print "10 sec later"} );
     run;

DESCRIPTION
===========

   This module gives you access to an single instance of the
*LWP::EventLoop* class.  All methods of *LWP::EventLoop* can be exported
and used as a procedural interface.  The function mainloop() returns a
reference to the single instance.

   No functions are exported by default.

SEE ALSO
========

   See LWP/EventLoop,

COPYRIGHT
=========

   Copyright 1997-1998, Gisle Aas

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

guess media type for a file or a URL
************************************

NAME
====

   LWP::MediaTypes - guess media type for a file or a URL

SYNOPSIS
========

     use LWP::MediaTypes qw(guess_media_type);
     $type = guess_media_type("/tmp/foo.gif");

DESCRIPTION
===========

   This module provides functions for handling media (also known as MIME)
types and encodings.  The mapping from file extentions to media types is
defined by the `media.types' file.  If the `~/.media.types' file exists it
is used instead.  For backwards compatability we will also look for
`~/.mime.types'.

   The following functions are exported by default:

guess_media_type($filename_or_url, [$header_to_modify])
     This function tries to guess media type and encoding for a file or
     url.  It returns the content-type, which is a string like
     `"text/html"'.  In array context it also returns any
     content-encodings applied (in the order used to encode the file).
     You can pass a URI object reference, instead of the file name.

     If the type can not be deduced from looking at the file name, then
     guess_media_type() will let the -T Perl operator take a look.  If
     this works (and -T returns a TRUE value) then we return *text/plain*
     as the type, otherwise we return *application/octet-stream* as the
     type.

     The optional second argument should be a reference to a HTTP::Headers
     object or any object that implements the $obj->header method in a
     similar way.  When it is present the values of the 'Content-Type' and
     'Content-Encoding' will be set for this header.

media_suffix($type,...)
     This function will return all suffixes that can be used to denote the
     specified media type(s).  Wildcard types can be used.  In a scalar
     context it will return the first suffix found.

     Examples:

          @suffixes = media_suffix('image/*', 'audio/basic');
          $suffix = media_suffix('text/html');

   The following functions are only exported by explict request:

add_type($type, @exts)
     Associate a list of file extensions with the given media type.

     Example:

          add_type("x-world/x-vrml" => qw(wrl vrml));

add_encoding($type, @ext)
     Associate a list of file extensions with an encoding type.

     Example:

          add_encoding("x-gzip" => "gz");

read_media_types(@files)
     Parse media types files and add the type mappings found there.

     Example:

          read_media_types("conf/mime.types");

COPYRIGHT
=========

   Copyright 1995-1999 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Member access mixin class
*************************

NAME
====

   LWP::MemberMixin - Member access mixin class

SYNOPSIS
========

     package Foo;
     require LWP::MemberMixin;
     @ISA=qw(LWP::MemberMixin);

DESCRIPTION
===========

   A mixin class to get methods that provide easy access to member
variables in the %$self.  Ideally there should be better Perl langauge
support for this.

   There is only one method provided:

_elem($elem [, $val])
     Internal method to get/set the value of member variable $elem. If
     $val is defined it is used as the new value for the member variable.
     If it is undefined the current value is not touched. In both cases
     the previous value of the member variable is returned.

Extension for LWP to allow parallel HTTP and FTP access
*******************************************************

NAME
====

   LWP::Parallel - Extension for LWP to allow parallel HTTP and FTP access

SYNOPSIS
========

     use LWP::Parallel;
     print "This is LWP::Parallel_$LWP::Parallel::VERSION\n";

DESCRIPTION
===========

Introduction
------------

   ParallelUserAgent is an extension to the existing libwww module. It
allows you to take a list of URLs (currently supports only HTTP and FTP
protocol) and connect to all of them _in parallel_, then wait for the
results to come in.

   See the Parallel::UserAgent for how to create a LWP UserAgent that will
access multiple Web resources in parallel. The Parallel::RobotUA module
will additionally offer proper handling of robot.txt file, the de-facto
exclusion protocol for Web Robots.

Examples
--------

   The following examples might help to get you started:

     require LWP::Parallel::UserAgent;
     use HTTP::Request;

     # display tons of debugging messages. See 'perldoc LWP::Debug'
     #use LWP::Debug qw(+);

     # shortcut for demo URLs
     my $url = "http://localhost/";

     my $reqs = [
        HTTP::Request->new('GET', $url),
        HTTP::Request->new('GET', $url."homes/marclang/"),
     ];

     my $pua = LWP::Parallel::UserAgent->new();
     $pua->in_order  (1);  # handle requests in order of registration
     $pua->duplicates(0);  # ignore duplicates
     $pua->timeout   (2);  # in seconds
     $pua->redirect  (1);  # follow redirects

     foreach my $req (@$reqs) {
       print "Registering '".$req->url."'\n";
       if ( my $res = $pua->register ($req) ) {
     	print STDERR $res->error_as_HTML;
       }
     }
     my $entries = $pua->wait();

     foreach (keys %$entries) {
       my $res = $entries->{$_}->response;

     print "Answer for '",$res->request->url, "' was \t", $res->code,": ",
           $res->message,"\n";
       }

   Parallel::UserAgent (as well as the Parallel::RobotUA) offer three
default methods that will be called at certain points during the
connection: `on_connect', `on_return' and `on_failure'.

     #
     # provide subclassed UserAgent to override on_connect, on_failure and
     # on_return methods
     #
     package myUA;

     use Exporter();
     use LWP::Parallel::UserAgent qw(:CALLBACK);
     @ISA = qw(LWP::Parallel::UserAgent Exporter);
     @EXPORT = @LWP::Parallel::UserAgent::EXPORT_OK;

     # redefine methods: on_connect gets called whenever we're about to
     # make a a connection
     sub on_connect {
       my ($self, $request, $response, $entry) = @_;
       print "Connecting to ",$request->url,"\n";
     }

     # on_failure gets called whenever a connection fails right away
     # (either we timed out, or failed to connect to this address before,
     # or it's a duplicate). Please note that non-connection based
     # errors, for example requests for non-existant pages, will NOT call
     # on_failure since the response from the server will be a well
     # formed HTTP response!
     sub on_failure {
       my ($self, $request, $response, $entry) = @_;
       print "Failed to connect to ",$request->url,"\n\t",
             $response->code, ", ", $response->message,"\n"
     	    if $response;
     }

     # on_return gets called whenever a connection (or its callback)
     # returns EOF (or any other terminating status code available for
     # callback functions). Please note that on_return gets called for
     # any successfully terminated HTTP connection! This does not imply
     # that the response sent from the server is a success!
     sub on_return {
       my ($self, $request, $response, $entry) = @_;
       if ($response->is_success) {
          print "\n\nWoa! Request to ",$request->url," returned code ", $response->code,
             ": ", $response->message, "\n";
          print $response->content;
       } else {
          print "\n\nBummer! Request to ",$request->url," returned code ", $response->code,
             ": ", $response->message, "\n";
          # print $response->error_as_HTML;
       }
       return;
     }

     package main;
     use HTTP::Request;

     # shortcut for demo URLs
     my $url = "http://localhost/";

     my $reqs = [
        HTTP::Request->new('GET', $url),
        HTTP::Request->new('GET', $url."homes/marclang/"),
     ];

     my $pua = myUA->new();

     foreach my $req (@$reqs) {
       print "Registering '".$req->url."'\n";
       $pua->register ($req);
     }
     my $entries = $pua->wait(); # responses will be caught by on_return, etc

   The final example will demonstrate a simple Web Robot that keeps a
cache of the "robots.txt" permission files it has encountered so far. This
example also uses callbacks to handle the response as it comes in.

     require LWP::Parallel::UserAgent;
     use HTTP::Request;

     # persistent robot rules support. See 'perldoc WWW::RobotRules::AnyDBM_File'
     require WWW::RobotRules::AnyDBM_File;

     # shortcut for demo URLs
     my $url = "http://www.cs.washington.edu/";

     my $reqs = [
        HTTP::Request->new('GET', $url),
     	    # these are all redirects. depending on how you set
               # 'redirect_ok' they either just return the status code for
               # redirect (like 302 moved), or continue to follow redirection.
        HTTP::Request->new('GET', $url."research/ahoy/"),
        HTTP::Request->new('GET', $url."research/ahoy/doc/paper.html"),
        HTTP::Request->new('GET', "http://metacrawler.cs.washington.edu:6060/"),
     	    # these are all non-existant server. the first one should take
               # some time, but the following ones should be rejected right
               # away
        HTTP::Request->new('GET', "http://www.foobar.foo/research/ahoy/"),
        HTTP::Request->new('GET', "http://www.foobar.foo/foobar/foo/"),
        HTTP::Request->new('GET', "http://www.foobar.foo/baz/buzz.html"),
     	    # although server exists, file doesn't
        HTTP::Request->new('GET', $url."foobar/bar/baz.html"),
     	    ];

     my ($req,$res);

     # establish persistant robot rules cache. See WWW::RobotRules for
     # non-permanent version. you should probably adjust the agentname
     # and cache filename.
     my $rules = new WWW::RobotRules::AnyDBM_File 'ParallelUA', 'cache';

     # create new UserAgent (actually, a Robot)
     my $pua = new LWP::Parallel::RobotUA ("ParallelUA",
                                           'yourname@your.site.com', $rules);

     $pua->timeout   (2);  # in seconds
     $pua->delay    ( 5);  # in seconds
     $pua->max_req  ( 2);  # max parallel requests per server
     $pua->max_hosts(10);  # max parallel servers accessed

     # for our own print statements that follow below:
     local($\) = ""; # ensure standard $OUTPUT_RECORD_SEPARATOR

     # register requests
     foreach $req (@$reqs) {
       print "Registering '".$req->url."'\n";
       $pua->register ($req , \&handle_answer);
       #  Each request, even if it failed to # register properly, will
       #  show up in the final list of # requests returned by $pua->wait,
       #  so you can examine it # later.
     }

     # $pua->wait returns a pointer to an associative array, containing
     # an '$entry' for each request made, sorted by its url. (as returned
     # by $request->url->as_string)
     my $entries = $pua->wait(); # give another timeout here, 25 seconds

     # let's see what we got back (see also callback function!!)
     foreach (keys %$entries) {
       $res = $entries->{$_}->response;

     # examine response to find cascaded requests (redirects, etc) and
     # set current response to point to the very first response of this
     # sequence. (not very exciting if you set '$pua->redirect(0)')
     my $r = $res; my @redirects;
     while ($r) {
     	$res = $r;
     	$r = $r->previous;
     	push (@redirects, $res) if $r;
     }

     # summarize response. see "perldoc HTTP::Response"
     print "Answer for '",$res->request->url, "' was \t", $res->code,": ",
           $res->message,"\n";
     # print redirection history, in case we got redirected
     foreach (@redirects) {
     	print "\t",$_->request->url, "\t", $_->code,": ", $_->message,"\n";
     }
       }

     # our callback function gets called whenever some data comes in
     # (same parameter format as standard LWP::UserAgent callbacks!)
     sub handle_answer {
       my ($content, $response, $protocol, $entry) = @_;

     print "Handling answer from '",$response->request->url,": ",
           length($content), " bytes, Code ",
           $response->code, ", ", $response->message,"\n";

     if (length ($content) ) {
     	# just store content if it comes in
     	$response->add_content($content);
     } else {
         # Having no content doesn't mean the connection is closed!
         # Sometimes the server might return zero bytes, so unless
         # you already got the information you need, you should continue
         # processing here (see below)

     	# Otherwise you can return a special exit code that will
         # determins how ParallelUA will continue with this connection.

     # Note: We have to import those constants via "qw(:CALLBACK)"!

     # return C_ENDCON;  # will end only this connection
     		    # (silly, we already have EOF)
     # return C_LASTCON; # wait for remaining open connections,
     		    # but don't issue any new ones!!
     # return C_ENDALL;  # will immediately end all connections
     		    # and return from $pua->wait
         }

     # ATTENTION!! If you want to keep reading from your connection,
     # you should have a final 'return undef' statement here. Even if
     # you think that all data has arrived, it does not hurt to return
     # undef here. The Parallel UserAgent will figure out by itself
     # when to close the connection!

     return undef;	    # just keep on connecting/reading/waiting
                             # until the server closes the connection.
       }

AUTHOR
======

   Marc Langheinrich, marclang@cs.washington.edu

SEE ALSO
========

   See LWP, for an overview on Web communication using Perl. See
LWP/Parallel/UserAgent, and
LWP/Parallel/RobotUA, for details on how to use this
library.

COPYRIGHT
=========

   Copyright 1997-2001 Marc Langheinrich.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Base class for parallel LWP protocols
*************************************

NAME
====

   LWP::Parallel::Protocol - Base class for parallel LWP protocols

SYNOPSIS
========

     package LWP::Parallel::Protocol::foo;
     require LWP::Parallel::Protocol;
     @ISA=qw(LWP::Parallel::Protocol);

DESCRIPTION
===========

   This class is used a the base class for all protocol implementations
supported by the LWP::Parallel library. It mirrors the behavior of the
original LWP::Parallel library by subclassing from it and adding a few
subroutines of its own.

   Please see the LWP::Protocol for more information about the usage of
this module.

   In addition to the inherited methods from LWP::Protocol, The following
methods and functions are provided:

ADDITIONAL METHODS AND FUNCTIONS
================================

$prot = new HTTP::Protocol;
     The LWP::Protocol constructor is inherited by subclasses. As this is a
     virtual base class this method should not be called directly.

$prot = LWP::Parallel::Protocol::create($url)
     Create an object of the class implementing the protocol to handle the
     given scheme. This is a function, not a method. It is more an object
     factory than a constructor. This is the function user agents should
     use to access protocols.

$class = LWP::Parallel::Protocol::implementor($scheme, [$class])
     Get and/or set implementor class for a scheme.  Returns " if the
     specified scheme is not supported.

$prot->receive ($arg, $response, $content)
     Called to store a piece of content of a request, and process it
     appropriately into a scalar, file, or by calling a callback.  If $arg
     is undefined, then the content is stored within the $response.  If
     $arg is a simple scalar, then $arg is interpreted as a file name and
     the content is written to this file.  If $arg is a reference to a
     routine, then content is passed to this routine.

     $content must be a reference to a scalar holding the content that
     should be processed.

     The return value from receive() is the $response object reference.

     Note: We will only use the file or callback argument if
     $response->is_success().  This avoids sendig content data for
     redirects and authentization responses to the file or the callback
     function.

$prot->receive_once($arg, $response, $content, $entry)
     Can be called when the whole response content is available as
     $content.  This will invoke receive() with a collector callback that
     returns a reference to $content the first time and an empty string the
     next.

SEE ALSO
========

   Inspect the `LWP/Parallel/Protocol/http.pm' file for examples of usage.

COPYRIGHT
=========

   Copyright 1997-2001 Marc Langheinrich.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

A class for Parallel Web Robots
*******************************

NAME
====

   LWP::Parallel::RobotUA - A class for Parallel Web Robots

SYNOPSIS
========

     require LWP::Parallel::RobotUA;
     $ua = new LWP::Parallel::RobotUA 'my-robot/0.1', 'me@foo.com';
     $ua->delay(20);  # in seconds!
     ...
     # just use it just like a normal LWP::Parallel::UserAgent
     $ua->register ($request, \&callback, 4096); # or
     $ua->wait ( $timeout );

DESCRIPTION
===========

   This class implements a user agent that is suitable for robot
applications.  Robots should be nice to the servers they visit.  They
should consult the `/robots.txt' file to ensure that they are welcomed and
they should not make requests too frequently.

   But, before you consider writing a robot take a look at
<URL:http://info.webcrawler.com/mak/projects/robots/robots.html>.

   When you use a *LWP::Parallel::RobotUA* as your user agent, then you do
not really have to think about these things yourself.  Just send requests
as you do when you are using a normal *LWP::Parallel::UserAgent* and this
special agent will make sure you are nice.

METHODS
=======

   The LWP::Parallel::RobotUA is a sub-class of LWP::Parallel::UserAgent
and LWP::RobotUA and implements a mix of their methods.

   In addition to LWP::Parallel::UserAgent, these methods are provided:

$ua = LWP::RobotUA->new($agent_name, $from, [$rules])
-----------------------------------------------------

   Your robot's name and the mail address of the human responsible for the
robot (i.e. you) are required by the constructor.

   Optionally it allows you to specify the *WWW::RobotRules* object to
use. (See WWW/RobotRules/AnyDBM_File,
for persistent caching of robot rules in a local file)

$ua->delay([$seconds])
----------------------

   Set/Get the minimum delay between requests to the same server.  The
default is 60 seconds.

   Note: The original LWP Robot uses *Minutes* instead of *Seconds* here!

$ua->host_wait($netloc)
-----------------------

   Returns the number of seconds you must wait before you can make a new
request to this server. This method keeps track of all of the robots
connection, and enforces the delay constraint specified via the delay
method above for each server individually.

   Note: Although it says 'host', it really means 'netloc/server', i.e. it
differentiates between individual servers running on different ports, even
though they might be on the same machine ('host'). This function is mostly
used internally, where RobotUA calls it to find out when to send the next
request to a certain server.

$ua->as_string
--------------

   Returns a string that describes the state of the UA.  Mainly useful for
debugging.

SEE ALSO
========

   See LWP/Parallel/UserAgent,
LWP/RobotUA, WWW/RobotRules,

COPYRIGHT
=========

   Copyright 1997-2001 Marc Langheinrich <marclang@cs.washington.edu>

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

A class for parallel User Agents
********************************

NAME
====

   LWP::Parallel::UserAgent - A class for parallel User Agents

SYNOPSIS
========

     require LWP::Parallel::UserAgent;
     $ua = LWP::Parallel::UserAgent->new();
     ...

     $ua->redirect (0); # prevents automatic following of redirects
     $ua->max_hosts(5); # sets maximum number of locations accessed in parallel
     $ua->max_req  (5); # sets maximum number of parallel requests per host
     ...
     $ua->register ($request); # or
     $ua->register ($request, '/tmp/sss'); # or
     $ua->register ($request, \&callback, 4096);
     ...
     $ua->wait ( $timeout );
     ...
     sub callback { my($data, $response, $protocol) = @_; .... }

DESCRIPTION
===========

   This class implements a user agent that access web sources in parallel.

   Using a *LWP::Parallel::UserAgent* as your user agent, you typically
start by registering your requests, along with how you want the Agent to
process the incoming results (see $ua->register).

   Then you wait for the results by calling $ua->wait.  This method only
returns, if all requests have returned an answer, or the Agent timed out.
Also, individual callback functions might indicate that the Agent should
stop waiting for requests and return. (see $ua->register)

   See the file LWP/Parallel, for a set of simple
examples.

METHODS
=======

   The LWP::Parallel::UserAgent is a sub-class of LWP::UserAgent, but not
all of its methods are available here. However, you can use its main
methods, $ua->simple_request and $ua->request, in order to simulate
singular access with this package. Of course, if a single request is all
you need, then you should probably use LWP::UserAgent in the first place,
since it will be faster than our emulation here.

   For parallel access, you will need to use the new methods that come with
LWP::Parallel::UserAgent, called $pua->register and $pua->wait. See below
for more information on each method.

$ua = LWP::Parallel::UserAgent->new();
     Constructor for the parallel UserAgent.  Returns a reference to a
     LWP::Parallel::UserAgent object.

     Optionally, you can give it an existing LWP::Parallel::UserAgent (or
     even an LWP::UserAgent) as a first argument, and it will "clone" a
     new one from this (This just copies the behavior of LWP::UserAgent.
     I have never actually tried this, so let me know if this does not do
     what you want).

$ua->initialize;
     Takes no arguments and initializes the UserAgent. It is automatically
     called in LWP::Parallel::UserAgent::new, so usually there is no need
     to call this explicitly.

     However, if you want to re-use the same UserAgent object for a number
     of "runs", you should call $ua->initialize after you have processed
     the results of the previous call to $ua->wait, but before registering
     any new requests.

$ua->redirect ( $ok )
     Changes the default value for permitting Parallel::UserAgent to follow
     redirects and authentication-requests.  The standard value is 'true'.

     See `$ua-'register> for how to change the behaviour for particular
     requests only.

$ua->duplicates ( $ok )
     Changes the default value for permitting Parallel::UserAgent to ignore
     duplicate requests.  The standard value is 'false'.

$ua->in_order ( $ok )
     Changes the default value to restricting Parallel::UserAgent to
     connect to the registered sites in the order they were registered. The
     default value FALSE allows Parallel::UserAgent to make the connections
     in an apparently random order.

$ua->remember_failures ( $yes )
     If set to one, enables ParalleUA to ignore requests or connections to
     sites that it failed to connect to before during this "run". If set to
     zero (the dafault) Parallel::UserAgent will try to connect to every
     single URL you registered, even if it constantly fails to connect to a
     particular site.

$ua->max_hosts ( $max )
     Changes the maximum number of locations accessed in parallel. The
     default value is 7.

     Note: Although it says 'host', it really means 'netloc/server'! That
     is, multiple server on the same host (i.e. one server running on port
     80, the other one on port 6060) will count as two 'hosts'.

$ua->max_req ( $max )
     Changes the maximum number of requests issued per host in parallel.
     The default value is 5.

$ua->register ( $request [, $arg [, $size [, $redirect_ok]]] )
     Registers the given request with the User Agent.  In case of an error,
     a HTTP::Request object containing the HTML-Error message is returned.
     Otherwise (that is, in case of a success) it will return undef.

     The $request should be a reference to a HTTP::Request object with
     values defined for at least the method() and url() attributes.

     $size specifies the number of bytes Parallel::UserAgent should try to
     read each time some new data arrives.  Setting it to '0' or 'undef'
     will make Parallel::UserAgent use the default. (8k)

     Specifying `$redirect_ok' will alter the redirection behaviour for
     this particular request only. '1' or any other true value will force
     Parallel::UserAgent to follow redirects, even if the default is set to
     'no_redirect'. (see `$ua-'redirect>) '0' or any other false value
     should do the reverse.  Please note that POST requests are not being
     followed, regardless of the $redirect_ok value!

     If $arg is a scalar it is taken as a filename where the content of
     the response is stored.

     If $arg is a reference to a subroutine, then this routine is called
     as chunks of the content is received.  An optional $size argument is
     taken as a hint for an appropriate chunk size. The callback function
     is called with 3 arguments: the data received this time, a reference
     to the response object and a reference to the protocol object. The
     callback can use the predefined constants C_ENDCON, C_LASTCON and
     C_ENDALL as a return value in order to influence pending and active
     connections. C_ENDCON will end this connection immediately, whereas
     C_LASTCON will inidicate that no further connections should be made.
     C_ENDALL will immediately end all requests and let the
     Parallel::UserAgent return from $pua->wait().

     If $arg is omitted, then the content is stored in the response object
     itself.

     If $arg is a `LPW::Parallel::UserAgent::Entry' object, then this
     request will be registered as a follow-up request to this particular
     entry. This will not create a new entry, but instead link the current
     response (i.e. the reason for re-registering) as $response->previous
     to the new response of this request.  All other fields are either
     re-initialized ($request, $fullpath, $proxy) or left untouched ($arg,
     $size). (This should only be use internally)

     LWP::Parallel::UserAgent->request also allows the registration of
     follow-up requests to existing requests, that required redirection or
     authentication. In order to do this, an Parallel::UserAgent::Entry
     object will be passed as the second argument to the call. Usually,
     this should not be used directly, but left to the internal
     $ua->handle_response method!

$ua->on_connect ( $request, $response, $entry )
     This method should be overridden in an (otherwise empty) subclass in
     order to present customized messages for each connection attempted by
     the User Agent.

$ua->on_failure ( $request, $response, $entry )
     This method should be overridden in an (otherwise empty) subclass in
     order to present customized messages for each connection or
     registration that failed.

$ua->on_return ( $request, $response, $entry )
     This method should be overridden in an (otherwise empty) subclass in
     order to present customized messages for each request returned. If a
     callback function was registered with this request, this callback
     function is called before $pua->on_return.

     Please note that while $pua->on_return is a method (which should be
     overridden in a subclass), a callback function is NOT a method, and
     does not have $self as its first parameter. (See more on callbacks
     below)

     The purpose of $pua->on_return is mainly to provide messages when a
     request returns. However, you can also re-register follow-up requests
     in case you need them.

     If you need specialized follow-up requests depending on the request
     that just returend, use a callback function instead (which can be
     different for each request registered). Otherwise you might end up
     writing a HUGE if..elsif..else.. branch in this global method.

$us->discard_entry ( $entry )
     Completely removes an entry from memory, in case its output is not
     needed. Use this in callbacks such as `on_return' or <on_failure> if
     you want to make sure an entry that you do not need does not occupy
     valuable main memory.

$ua->wait ( $timeout )
     Waits for available sockets to write to or read from.  Will timeout
     after $timeout seconds. Will block if $timeout = 0 specified. If
     $timeout is omitted, it will use the Agent default timeout value.

$ua->handle_response($request, $arg [, $size])
     Analyses results, handling redirects and security.  This method may
     actually register several different, additional requests.

     This method should not be called directly. Instead, indicate for each
     individual request registered with `$ua-'register()> whether or not
     you want Parallel::UserAgent to handle redirects and security, or
     specify a default value for all requests in Parallel::UserAgent by
     using `$ua-'redirect()>.

$ua->simple_request($request, [$arg [, $size]])
     This method simulates the behavior of LWP::UserAgent->simple_request.
     It is actually kinda overkill to use this method in
     Parallel::UserAgent, and it is mainly here for testing backward
     compatibility with the original LWP::UserAgent. The following
     description is taken directly from the corresponding libwww pod:

     $ua->simple_request dispatches a single WWW request on behalf of a
     user, and returns the response received.  The $request should be a
     reference to a HTTP::Request object with values defined for at least
     the method() and url() attributes.

     If $arg is a scalar it is taken as a filename where the content of
     the response is stored.

     If $arg is a reference to a subroutine, then this routine is called
     as chunks of the content is received.  An optional $size argument is
     taken as a hint for an appropriate chunk size.

     If $arg is omitted, then the content is stored in the response object
     itself.

$ua->request($request, $arg [, $size])
     Included for compatibility testing with LWP::UserAgent. Every day
     usage is depreciated! Here is what LWP::UserAgent has to say about it:

     Process a request, including redirects and security.  This method may
     actually send several different simple reqeusts.

     The arguments are the same as for `simple_request()'.

     sub request {   my $self = shift;

     my $ua = LWP::Parallel::UserAgent->new();   $ua->agent($self->agent);
      $ua->from ($self->from);   $ua->redirect(1);
     &_single_request($ua, @_); }

$ua->as_string
     Returns a text that describe the state of the UA.  Should be useful
     for debugging, if it would print out anything important. But it does
     not (at least not yet). Try using LWP::Debug...

ADDITIONAL METHODS
==================

$ua->use_alarm([$boolean])
     This function is not in use anymore and will display a warning when
     called and warnings are enabled.

Callback functions
==================

   You can register a callback function. See LWP::UserAgent for details.

BUGS
====

   Probably lots! This was meant only as an interim release until this
functionality is incorporated into LWPng, the next generation libwww
module (though it has been this way for over 2 years now!)

   Needs a lot more documentation on how callbacks work!

SEE ALSO
========

   See LWP/UserAgent,

COPYRIGHT
=========

   Copyright 1997-2001 Marc Langheinrich <marclang@cs.washington.edu>

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Parallel LWP::UserAgent
***********************

NAME
====

   LWP::ParallelUA - Parallel LWP::UserAgent

SYNOPSIS
========

     require LWP::ParallelUA;
     $ua = LWP::ParallelUA->new();

     (see description of LWP::Parallel::UserAgent)

DESCRIPTION
===========

   *ParallelUA* is a simple frontend to the *LWP::Parallel::UserAgent*
module. It is here in order to maintain the compatibility with previous
releases. However, in order to prevent the previous need for changing the
original LWP sources, all extension files have been moved to the
LWP::Parallel subtree.

   If you start from scratch, maybe you should start using LWP::Parallel
and its submodules directly.

   See the LWP/Parallel/UserAgent, for the
documentation on this module.

AUTHOR
======

   Marc Langheinrich, marclang@cs.washington.edu

SEE ALSO
========

   See LWP/Parallel/UserAgent,

COPYRIGHT
=========

   Copyright 1997-2001 Marc Langheinrich.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Base class for LWP protocols
****************************

NAME
====

   LWP::Protocol - Base class for LWP protocols

SYNOPSIS
========

     package LWP::Protocol::foo;
     require LWP::Protocol;
     @ISA=qw(LWP::Protocol);

DESCRIPTION
===========

   This class is used a the base class for all protocol implementations
supported by the LWP library.

   When creating an instance of this class using
`LWP::Protocol::create($url)', and you get an initialised subclass
appropriate for that access method. In other words, the
LWP::Protocol::create() function calls the constructor for one of its
subclasses.

   All derived LWP::Protocol classes need to override the request() method
which is used to service a request. The overridden method can make use of
the collect() function to collect together chunks of data as it is
received.

   The following methods and functions are provided:

$prot = LWP::Protocol->new()
     The LWP::Protocol constructor is inherited by subclasses. As this is a
     virtual base class this method should not be called directly.

$prot = LWP::Protocol::create($url)
     Create an object of the class implementing the protocol to handle the
     given scheme. This is a function, not a method. It is more an object
     factory than a constructor. This is the function user agents should
     use to access protocols.

$class = LWP::Protocol::implementor($scheme, [$class])
     Get and/or set implementor class for a scheme.  Returns " if the
     specified scheme is not supported.

$prot->request(...)
          $response = $protocol->request($request, $proxy, undef);
          $response = $protocol->request($request, $proxy, '/tmp/sss');
          $response = $protocol->request($request, $proxy, \&callback, 1024);

     Dispactches a request over the protocol, and returns a response
     object. This method needs to be overridden in subclasses.  Referer to
     LWP/UserAgent, for description of the arguments.

$prot->timeout($seconds)
     Get and set the timeout value in seconds

$prot->parse_head($yesno)
     Should we initialize response headers from the <head> section of HTML
     documents.

$prot->collect($arg, $response, $collector)
     Called to collect the content of a request, and process it
     appropriately into a scalar, file, or by calling a callback.  If $arg
     is undefined, then the content is stored within the $response.  If
     $arg is a simple scalar, then $arg is interpreted as a file name and
     the content is written to this file.  If $arg is a reference to a
     routine, then content is passed to this routine.

     The $collector is a routine that will be called and which is
     reponsible for returning pieces (as ref to scalar) of the content to
     process.  The $collector signals EOF by returning a reference to an
     empty sting.

     The return value from collect() is the $response object reference.

     Note: We will only use the callback or file argument if
     $response->is_success().  This avoids sendig content data for
     redirects and authentization responses to the callback which would be
     confusing.

$prot->collect_once($arg, $response, $content)
     Can be called when the whole response content is available as
     $content.  This will invoke collect() with a collector callback that
     returns a reference to $content the first time and an empty string the
     next.

SEE ALSO
========

   Inspect the `LWP/Protocol/file.pm' and `LWP/Protocol/http.pm' files for
examples of usage.

COPYRIGHT
=========

   Copyright 1995-2000 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

BBS/RPC support for LWP
***********************

NAME
====

   LWP::Protocol::bbs - BBS/RPC support for LWP

SYNOPSIS
========

     # start daemon
     % bbscomd MAPLE2 /srv/bbs

     # fetch some property
     % lwp-download bbs://localhost/boards/sysop/articles/1/body

DESCRIPTION
===========

     This is an attempt to combine raw BBS fetch with LWP protocol,
     intended to be used as the bridge to foreign renderes.

     It's still in early alpha stage, and the interface remains
     undecided as of now.

COPYRIGHT
=========

   Copyright 2001 by Autrijus Tang <autrijus@autrijus.org>.

   All rights reserved.  You can redistribute and/or modify this module
under the same terms as Perl itself.

Parallel LWP::RobotUA
*********************

NAME
====

   LWP::RobotPUA - Parallel LWP::RobotUA

SYNOPSIS
========

     require LWP::RobotPUA;
     $ua = new LWP::RobotPUA 'my-robot/0.1', 'me@foo.com';

     (see description of LWP::Parallel::RobotUA)

DESCRIPTION
===========

   RobotPUA is a simple frontend to the LWP::Parallel::RobotUA module. It
is here in order to maintain the compatibility with previous releases.
However, in order to prevent the previous need for changing the original
LWP sources, all extension files have been moved to the LWP::Parallel
subtree.

   If you start from scratch, maybe you should start using LWP::Parallel
and its submodules directly.

   See the LWP/Parallel/RobotUA, for the
documentation on this module.

AUTHOR
======

   Marc Langheinrich, marclang@cs.washington.edu

SEE ALSO
========

   See LWP/Parallel/RobotUA,
LWP/Parallel/UserAgent, LWP/RobotUA,

COPYRIGHT
=========

   Copyright 1997-2001 Marc Langheinrich.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

A class for Web Robots
**********************

NAME
====

   LWP::RobotUA - A class for Web Robots

SYNOPSIS
========

     require LWP::RobotUA;
     $ua = new LWP::RobotUA 'my-robot/0.1', 'me@foo.com';
     $ua->delay(10);  # be very nice, go slowly
     ...
     # just use it just like a normal LWP::UserAgent
     $res = $ua->request($req);

DESCRIPTION
===========

   This class implements a user agent that is suitable for robot
applications.  Robots should be nice to the servers they visit.  They
should consult the `/robots.txt' file to ensure that they are welcomed and
they should not make requests too frequently.

   But, before you consider writing a robot take a look at
<URL:http://info.webcrawler.com/mak/projects/robots/robots.html>.

   When you use a LWP::RobotUA as your user agent, then you do not really
have to think about these things yourself.  Just send requests as you do
when you are using a normal *LWP::UserAgent* and this special agent will
make sure you are nice.

METHODS
=======

   The LWP::RobotUA is a sub-class of LWP::UserAgent and implements the
same methods. In addition the following methods are provided:

$ua = LWP::RobotUA->new($agent_name, $from, [$rules])
     Your robot's name and the mail address of the human responsible for
     the robot (i.e. you) are required by the constructor.

     Optionally it allows you to specify the *WWW::RobotRules* object to
     use.

$ua->delay([$minutes])
     Set the minimum delay between requests to the same server.  The
     default is 1 minute.

$ua->use_sleep([$boolean])
     Get/set a value indicating whether the UA should sleep() if requests
     arrive too fast (before $ua->delay minutes has passed).  The default
     is TRUE.  If this value is FALSE then an internal SERVICE_UNAVAILABLE
     response will be generated.  It will have an Retry-After header that
     indicates when it is OK to send another request to this server.

$ua->rules([$rules])
     Set/get which *WWW::RobotRules* object to use.

$ua->no_visits($netloc)
     Returns the number of documents fetched from this server host. Yes I
     know, this method should probably have been named num_visits() or
     something like that. :-(

$ua->host_wait($netloc)
     Returns the number of seconds (from now) you must wait before you can
     make a new request to this host.

$ua->as_string
     Returns a string that describes the state of the UA.  Mainly useful
     for debugging.

SEE ALSO
========

   See LWP/UserAgent, WWW/RobotRules,

COPYRIGHT
=========

   Copyright 1996-2000 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SSL TCP/IP socket interface
***************************

NAME
====

   LWP::SecureSocket - SSL TCP/IP socket interface

SYNOPSIS
========

     $socket = new LWP::SecureSocket;
     $socket->connect('localhost', 7); # echo
     $quote = 'I dunno, I dream in Perl sometimes...';
     $socket->write("$quote\n");
     $socket->read_until("\n", \$buffer);
     $socket->read(\$buffer);
     $socket = undef;  # close

DESCRIPTION
===========

   *Beware:* New code should not use this depreciated module.

   This class implements SSL TCP/IP sockets.  It groups socket generation,
TCP address manipulation and buffered reading. Errors are handled by dying
(throws exceptions).

   The following methods are provided:

$sock = new LWP::SecureSocket()
     Constructs a new socket object.

$sock->connect($host, $port)
     Connect the socket to given host and port.

$sock->shutdown()
     Shuts down the connection.

$sock->bind($host, $port)
     Binds a name to the socket.

$sock->listen($queuesize)
     Set up listen queue for socket.

$sock->accept($timeout)
     Accepts a new connection.  Returns a new LWP::SecureSocket object if
     successful.  Timeout not implemented yet.  would require modifying
     new, and not     necessary for app, so I\'m not bothering to modify.
     Might work anyways, though.

$sock->getsockname()
     Returns a 2 element array ($host, $port)

$sock->read_until($delim, $data_ref, $size, $timeout)
     Reads data from the socket, up to a delimiter specified by a regular
     expression.  If $delim is undefined all data is read.  If $size is
     defined, data will be read internally in chunks of $size bytes.  This
     does not mean that we will return the data when size bytes are read.

     Note that $delim is discarded from the data returned.

$sock->read($bufref, [$size, $timeout])
     Reads data of the socket.  Not more than $size bytes.  Might return
     less if the data is available.  Dies on timeout.

$sock->pushback($data)
     Put data back into the socket.  Data will returned next time you
     read().  Can be used if you find out that you have read too much.

$sock->write($data, [$timeout])
     Write data to socket.  The $data argument might be a scalar or code.

     If data is a reference to a subroutine, then we will call this routine
     to obtain the data to be written.  The routine will be called until it
     returns undef or empty data.  Data might be returned from the callback
     as a scalar or as a reference to a scalar.

     Write returns the number of bytes written to the socket.

$sock->_getaddress($h, $p)
     Given a host and a port, it will return the address (sockaddr_in)
     suitable as the name argument for connect() or bind(). Might return
     several addresses in array context if the hostname is bound to several
     IP addresses.

AUTHOR
======

   Derived by Joshua Kronengold from Socket.pm and SSLeay

Procedural LWP interface
************************

NAME
====

   get, head, getprint, getstore, mirror - Procedural LWP interface

SYNOPSIS
========

     perl -MLWP::Simple -e 'getprint "http://www.sn.no"'

     use LWP::Simple;
     $content = get("http://www.sn.no/")
     if (mirror("http://www.sn.no/", "foo") == RC_NOT_MODIFIED) {
         ...
     }

     if (is_success(getprint("http://www.sn.no/"))) {
         ...
     }

DESCRIPTION
===========

   This interface is intended for those who want a simplified view of the
libwww-perl library.  It should also be suitable for one-liners.  If you
need more control or access to the header fields in the requests sent and
responses received you should use the full object oriented interface
provided by the `LWP::UserAgent' module.

   The following functions are provided (and exported) by this module:

get($url)
     The get() function will fetch the document identified by the given URL
     and return it.  It returns undef if it fails.  The $url argument can
     be either a simple string or a reference to a URI object.

     You will not be able to examine the response code or response headers
     (like 'Content-Type') when you are accessing the web using this
     function.  If you need that information you should use the full OO
     interface (see LWP/UserAgent).

head($url)
     Get document headers. Returns the following 5 values if successful:
     ($content_type, $document_length, $modified_time, $expires, $server)

     Returns an empty list if it fails.  In scalar context returns TRUE if
     successful.

getprint($url)
     Get and print a document identified by a URL. The document is printed
     to STDOUT as data is received from the network.  If the request fails,
     then the status code and message are printed on STDERR.  The return
     value is the HTTP response code.

getstore($url, $file)
     Gets a document identified by a URL and stores it in the file. The
     return value is the HTTP response code.

mirror($url, $file)
     Get and store a document identified by a URL, using
     *If-modified-since*, and checking the *Content-Length*.  Returns the
     HTTP response code.

   This module also exports the HTTP::Status constants and procedures.
These can be used when you check the response code from getprint(),
getstore() and mirror().  The constants are:

     RC_CONTINUE
     RC_SWITCHING_PROTOCOLS
     RC_OK
     RC_CREATED
     RC_ACCEPTED
     RC_NON_AUTHORITATIVE_INFORMATION
     RC_NO_CONTENT
     RC_RESET_CONTENT
     RC_PARTIAL_CONTENT
     RC_MULTIPLE_CHOICES
     RC_MOVED_PERMANENTLY
     RC_MOVED_TEMPORARILY
     RC_SEE_OTHER
     RC_NOT_MODIFIED
     RC_USE_PROXY
     RC_BAD_REQUEST
     RC_UNAUTHORIZED
     RC_PAYMENT_REQUIRED
     RC_FORBIDDEN
     RC_NOT_FOUND
     RC_METHOD_NOT_ALLOWED
     RC_NOT_ACCEPTABLE
     RC_PROXY_AUTHENTICATION_REQUIRED
     RC_REQUEST_TIMEOUT
     RC_CONFLICT
     RC_GONE
     RC_LENGTH_REQUIRED
     RC_PRECONDITION_FAILED
     RC_REQUEST_ENTITY_TOO_LARGE
     RC_REQUEST_URI_TOO_LARGE
     RC_UNSUPPORTED_MEDIA_TYPE
     RC_INTERNAL_SERVER_ERROR
     RC_NOT_IMPLEMENTED
     RC_BAD_GATEWAY
     RC_SERVICE_UNAVAILABLE
     RC_GATEWAY_TIMEOUT
     RC_HTTP_VERSION_NOT_SUPPORTED

   The HTTP::Status classification functions are:

is_success($rc)
     True if response code indicated a successful request.

is_error($rc)
     True if response code indicated that an error occured.

   The module will also export the LWP::UserAgent object as $ua if you ask
for it explicitly.

   The user agent created by this module will identify itself as
"LWP::Simple/#.##" (where "#.##" is the libwww-perl version number) and
will initialize its proxy defaults from the environment (by calling
$ua->env_proxy).

SEE ALSO
========

   See LWP, LWP/UserAgent,
HTTP/Status, `lwp-request' in this node, `lwp-mirror' in
this node

Something that receive data
***************************

NAME
====

   LWP::Sink - Something that receive data

SYNOPSIS
========

     require LWP::Sink;
     @ISA=qw(LWP::Sink);

DESCRIPTION
===========

   The *LWP::Sink* class is an abstraction similar to writeable files.
You can send data to it.  Different variations of sinks are available that
all conform to this simple interface:

$s = LWP::Sink::Foo->new
     The object constructor.  The *LWP::Sink* class is abstract, so you
     will create some subclass normally.

$s->put($data)
     Data is given to a sink by calling the put() method with suitable
     sized chunkes of data.  The return value from $s->put will be a
     reference to the object itself.

$s->flush
     Buffered data should be processed/sent off.

$s->close
     Invoking the close() method signals that the last chunk of data has
     been put()ed.  Resources associated with the sink can now be freed.

   One important class of sinks are those that transform data in some way.
These will be subclasses of *LWP::Sink::_Pipe* which means that they have
a attribute called *sink* that reference the sink that will received data
after processing.  By convention call transformation sink classes have all
lowercase names within the LWP::Sink::* namespace.  They also have
variations suffixed with ::encode and ::decode that performs the
transformations forwards or backwards.

BUGS
====

   Perhaps *LWP::Sink* should provide an interface to load sink subclasses
on demand and return references to them.  Similar to how URI works.

COPYRIGHT
=========

   Copyright 1998, Gisle Aas

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

TCP/IP socket interface
***********************

NAME
====

   LWP::Socket - TCP/IP socket interface

SYNOPSIS
========

     $socket = new LWP::Socket;
     $socket->connect('localhost', 7); # echo
     $quote = 'I dunno, I dream in Perl sometimes...';
     $socket->write("$quote\n");
     $socket->read_until("\n", \$buffer);
     $socket->read(\$buffer);
     $socket = undef;  # close

DESCRIPTION
===========

   *Beware:* New code should not use this module.  The IO::Socket::INET
module provide the standard Perl interface to OO Internet sockets.  Even
LWP is now rewritten to use IO::Socket::INET throughout.

   This class implements TCP/IP sockets.  It groups socket generation, TCP
address manipulation and buffered reading. Errors are handled by dying
(throws exceptions).

   Running this module standalone executes a self test which requires
localhost to serve chargen and echo protocols.

   The following methods are available:

$sock = new LWP::Socket()
     Constructs a new socket object.

$sock->connect($host, $port)
     Connect the socket to given host and port.

$sock->shutdown()
     Shuts down the connection.

$sock->bind($host, $port)
     Binds a name to the socket.

$sock->listen($queuesize)
     Set up listen queue for socket.

$sock->accept($timeout)
     Accepts a new connection.  Returns a new LWP::Socket object if
     successful.  Timeout not implemented yet.

$sock->getsockname()
     Returns a 2 element array ($host, $port)

$sock->read_until($delim, $data_ref, $size, $timeout)
     Reads data from the socket, up to a delimiter specified by a regular
     expression.  If $delim is undefined all data is read.  If $size is
     defined, data will be read internally in chunks of $size bytes.  This
     does not mean that we will return the data when size bytes are read.

     Note that $delim is discarded from the data returned.

$sock->read($bufref, [$size, $timeout])
     Reads data of the socket.  Not more than $size bytes.  Might return
     less if the data is available.  Dies on timeout.

$sock->pushback($data)
     Put data back into the socket.  Data will returned next time you
     read().  Can be used if you find out that you have read too much.

$sock->write($data, [$timeout])
     Write data to socket.  The $data argument might be a scalar or code.

     If data is a reference to a subroutine, then we will call this routine
     to obtain the data to be written.  The routine will be called until it
     returns undef or empty data.  Data might be returned from the callback
     as a scalar or as a reference to a scalar.

     Write returns the number of bytes written to the socket.

$sock->_getaddress($h, $p)
     Given a host and a port, it will return the address (sockaddr_in)
     suitable as the name argument for connect() or bind(). Might return
     several addresses in array context if the hostname is bound to several
     IP addresses.

SELF TEST
=========

   This self test is only executed when this file is run standalone. It
tests its functions against some standard TCP services implemented by
inetd. If you do not have them around the tests will fail.

Tk I/O routines for the LWP library
***********************************

NAME
====

   LWP::TkIO - Tk I/O routines for the LWP library

SYNOPSIS
========

     use Tk;
     require LWP::TkIO;
     require LWP::UserAgent;

DESCRIPTION
===========

   This module provide replacement functions for the LWP::IO functions.
Require this module if you use Tk and want non exclusive IO behaviour from
LWP.  This does not allow LWP to run simultaneous requests though.

   See also LWP/IO.

A WWW UserAgent class
*********************

NAME
====

   LWP::UserAgent - A WWW UserAgent class

SYNOPSIS
========

     require LWP::UserAgent;
     $ua = LWP::UserAgent->new;

     $request = HTTP::Request->new('GET', 'file://localhost/etc/motd');

     $response = $ua->request($request); # or
     $response = $ua->request($request, '/tmp/sss'); # or
     $response = $ua->request($request, \&callback, 4096);

     sub callback { my($data, $response, $protocol) = @_; .... }

DESCRIPTION
===========

   The `LWP::UserAgent' is a class implementing a simple World-Wide Web
user agent in Perl. It brings together the HTTP::Request, HTTP::Response
and the LWP::Protocol classes that form the rest of the core of
libwww-perl library. For simple uses this class can be used directly to
dispatch WWW requests, alternatively it can be subclassed for
application-specific behaviour.

   In normal use the application creates a UserAgent object, and then
configures it with values for timeouts, proxies, name, etc. It next
creates an instance of HTTP::Request for the request that needs to be
performed. This request is then passed to the UserAgent request() method,
which dispatches it using the relevant protocol, and returns a
`HTTP::Response' object.

   The basic approach of the library is to use HTTP style communication
for all protocol schemes, i.e. you also receive an `HTTP::Response' object
for gopher or ftp requests.  In order to achieve even more similarity to
HTTP style communications, gopher menus and file directories are converted
to HTML documents.

   The request() method can process the content of the response in one of
three ways: in core, into a file, or into repeated calls to a subroutine.
You choose which one by the kind of value passed as the second argument to
request().

   The in core variant simply stores the content in a scalar 'content'
attribute of the response object and is suitable for small HTML replies
that might need further parsing.  This variant is used if the second
argument is missing (or is undef).

   The filename variant requires a scalar containing a filename as the
second argument to request() and is suitable for large WWW objects which
need to be written directly to the file without requiring large amounts of
memory. In this case the response object returned from request() will have
an empty content attribute.  If the request fails, then the content might
not be empty, and the file will be untouched.

   The subroutine variant requires a reference to callback routine as the
second argument to request() and it can also take an optional chuck size
as the third argument.  This variant can be used to construct "pipe-lined"
processing, where processing of received chuncks can begin before the
complete data has arrived.  The callback function is called with 3
arguments: the data received this time, a reference to the response object
and a reference to the protocol object.  The response object returned from
request() will have empty content.  If the request fails, then the the
callback routine is not called, and the response->content might not be
empty.

   The request can be aborted by calling die() in the callback routine.
The die message will be available as the "X-Died" special response header
field.

   The library also allows you to use a subroutine reference as content in
the request object.  This subroutine should return the content (possibly
in pieces) when called.  It should return an empty string when there is no
more content.

METHODS
=======

   The following methods are available:

$ua = LWP::UserAgent->new;
     Constructor for the UserAgent.  Returns a reference to a
     LWP::UserAgent object.

$ua->simple_request($request, [$arg [, $size]])
     This method dispatches a single WWW request on behalf of a user, and
     returns the response received.  The $request should be a reference to
     a HTTP::Request object with values defined for at least the method()
     and uri() attributes.

     If $arg is a scalar it is taken as a filename where the content of
     the response is stored.

     If $arg is a reference to a subroutine, then this routine is called
     as chunks of the content is received.  An optional $size argument is
     taken as a hint for an appropriate chunk size.

     If $arg is omitted, then the content is stored in the response object
     itself.

$ua->request($request, $arg [, $size])
     Process a request, including redirects and security.  This method may
     actually send several different simple requests.

     The arguments are the same as for `simple_request()'.

$ua->redirect_ok
     This method is called by request() before it tries to do any
     redirects.  It should return a true value if a redirect is allowed to
     be performed. Subclasses might want to override this.

     The default implementation will return FALSE for POST request and TRUE
     for all others.

$ua->credentials($netloc, $realm, $uname, $pass)
     Set the user name and password to be used for a realm.  It is often
     more useful to specialize the get_basic_credentials() method instead.

$ua->get_basic_credentials($realm, $uri, [$proxy])
     This is called by request() to retrieve credentials for a Realm
     protected by Basic Authentication or Digest Authentication.

     Should return username and password in a list.  Return undef to abort
     the authentication resolution atempts.

     This implementation simply checks a set of pre-stored member
     variables. Subclasses can override this method to e.g. ask the user
     for a username/password.  An example of this can be found in
     `lwp-request' program distributed with this library.

$ua->agent([$product_id])
     Get/set the product token that is used to identify the user agent on
     the network.  The agent value is sent as the "User-Agent" header in
     the requests. The default agent name is "libwww-perl/#.##", where
     "#.##" is substitued with the version numer of this library.

     The user agent string should be one or more simple product identifiers
     with an optional version number separated by the "/" character.
     Examples are:

          $ua->agent('Checkbot/0.4 ' . $ua->agent);
          $ua->agent('Mozilla/5.0');

$ua->from([$email_address])
     Get/set the Internet e-mail address for the human user who controls
     the requesting user agent.  The address should be machine-usable, as
     defined in RFC 822.  The from value is send as the "From" header in
     the requests.  There is no default.  Example:

          $ua->from('gaas@cpan.org');

$ua->timeout([$secs])
     Get/set the timeout value in seconds. The default timeout() value is
     180 seconds, i.e. 3 minutes.

$ua->cookie_jar([$cookies])
     Get/set the *HTTP::Cookies* object to use.  The default is to have no
     cookie_jar, i.e. never automatically add "Cookie" headers to the
     requests.

$ua->parse_head([$boolean])
     Get/set a value indicating wether we should initialize response
     headers from the <head> section of HTML documents. The default is
     TRUE.  Do not turn this off, unless you know what you are doing.

$ua->max_size([$bytes])
     Get/set the size limit for response content.  The default is undef,
     which means that there is no limit.  If the returned response content
     is only partial, because the size limit was exceeded, then a
     "X-Content-Range" header will be added to the response.

$ua->clone;
     Returns a copy of the LWP::UserAgent object

$ua->is_protocol_supported($scheme)
     You can use this method to query if the library currently support the
     specified scheme.  The scheme might be a string (like 'http' or
     'ftp') or it might be an URI object reference.

$ua->mirror($url, $file)
     Get and store a document identified by a URL, using If-Modified-Since,
     and checking of the Content-Length.  Returns a reference to the
     response object.

$ua->proxy(...)
     Set/retrieve proxy URL for a scheme:

          $ua->proxy(['http', 'ftp'], 'http://proxy.sn.no:8001/');
          $ua->proxy('gopher', 'http://proxy.sn.no:8001/');

     The first form specifies that the URL is to be used for proxying of
     access methods listed in the list in the first method argument, i.e.
     'http' and 'ftp'.

     The second form shows a shorthand form for specifying proxy URL for a
     single access scheme.

$ua->env_proxy()
     Load proxy settings from *_proxy environment variables.  You might
     specify proxies like this (sh-syntax):

          gopher_proxy=http://proxy.my.place/
          wais_proxy=http://proxy.my.place/
          no_proxy="localhost,my.domain"
          export gopher_proxy wais_proxy no_proxy

     Csh or tcsh users should use the `setenv' command to define these
     environment variables.

$ua->no_proxy($domain,...)
     Do not proxy requests to the given domains.  Calling no_proxy without
     any domains clears the list of domains. Eg:

          $ua->no_proxy('localhost', 'no', ...);

SEE ALSO
========

   See LWP, for a complete overview of libwww-perl5.  See
`lwp-request' and `lwp-mirror' for examples of usage.

COPYRIGHT
=========

   Copyright 1995-2000 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl extension to parse LaTeX files
***********************************

NAME
====

   LaTeX::Parser - Perl extension to parse LaTeX files

SYNOPSIS
========

     use LaTeX::Parser;
     my $l = new LaTeX::Parser 'file' => 'file.tex';
     my $p = $l->latex; # $p now hold a reference to an array of
                        # file.tex parsed

   Or use it to break up LaTeX in a variable:

     my $l = new LaTeX::Parser 'content' =>
       '\textit{Three Lives} by Gertrude Stein.';

   Contents of nested braces are extracted as a single element.  Another
`LaTeX::Parser' will have to be created to parse nested braces.

   This is a very early version of `LaTeX::Parser', there are many bugs.
I think this will work fine with plain TeX files but I do not plan on ever
support that.

DESCRIPTION
===========

   For now, only simple descriptions of the modules functions.

LaTeX::Parser->new %hash
     Creates a LaTeX::Parser object.  All values in `%hash' are initialize
     to the values in the object.  The only two tested values to set are
     `file' and `content'.  `file' is the name of the file to load the
     LaTeX file from, and it get copied into `content'.  If content is set
     by then `%hash' then `file' will never be called.

LaTeX::Parser->latex
     No arguments.  Actualy does all the work.  Loads the LaTeX file if not
     content was specified, and returns a reference to all parsed
     information.

BUGS
====

   Many bugs i'll find soon enough.  Off the top of my head, I know
backslashed brackes in LaTeX are considered normal brackets.  I haven't
even thought about math things, and don't think I will think about that
any time soon.

AUTHOR
======

   Sven Heinicke, <sven@zen.org>

SEE ALSO
========

   perl(1), latex(1).

A LabEntry widget with an automatic, configurable right-click menu built in, plus input masks.
**********************************************************************************************

NAME
====

   LabPopEntry - A LabEntry widget with an automatic, configurable
right-click menu built in, plus input masks.

SYNOPSIS
--------

     use LabPopEntry;
     $dw = $parent->LabPopEntry(
         -pattern   => 'alpha', 'alphanum', 'capsonly', 'signed_int',
                    'unsigned_int', 'float', 'nondigit', or any supplied regexp.
         -nomenu    => 0 or 1,
         -case      => 'upper', 'lower', 'capitalize',
         -maxwidth  => int,
         -minvalue  => int,
         -maxvalue  => int,
         -nospace   => 0 or 1,
         -menuitems => ['string', 'callback', 'binding', 'index'],
      );
      $dw->pack;

DESCRIPTION
-----------

   LabPopEntry is a LabEntry widget with a right-click menu automatically
attached.  In addition, certain field masks can easily be applied to the
entry widget in order to force the end-user into entering only the values
you want him or her to enter.

   By default, there are five items attached to the right-click menu: Cut,
Copy, Paste, Delete and Sel. All.  The default bindings for the items are
Control-x, Control-c, Control-v, Control-d, and Control-a, respectively.

   The difference between 'Cut' and 'Delete' is that the former
automatically copies the contents that were cut to the clipboard, while
the latter does not.

OPTIONS
-------

   *-pattern =>* string

   The pattern specified here creates an input mask for the LabPopEntry widget.  There are seven pre-defined masks:

   * alpha - Upper and lower case a-z only.

   * alphanum - Alpha-numeric characters only.

   * capsonly - Upper case A-Z only.

   * nondigit - Any characters except 0-9.

   * float - A float value, which may or may not include a decimal.

   * signed_int - A signed integer value, which may or may not include a
     '+'.

   * unsigned_int - An unsigned integer value.

You may also specify a regular expression of your own design using Perl's standard regular expression mechanisms.  Be sure to use single quotes, e.g.  '/\d\w\d/'

   *-nomenu =>* **0* or 1*

   If set to true, then no right-click menu will appear.  Presumably, you would set this if you were only interested in the input-mask functionality.  The default is, of course, 0.

   *-nospace =>* **0* or 1*

   If set to true (1), the user may not enter whitespace before, after or between words within that LabPopEntry widget.  The default is 0.

   *-maxwidth =>* int

   Specifies the maximum number of characters that the user can enter in that particular LabPopEntry widget.  Note that this is not the same as the width of the widget itself.

   *-maxvalue =>* *int or float*

   If one of the pre-defined numeric patterns is chosen, this specifies the maximum allowable value that may be entered by a user for the widget.

   *-minvalue =>* *int or float*

   If one of the pre-defined numeric patterns is chosen, this specifies the minimum allowable value for the first digit (0-9).  This should work better.

   *-menuitems =>* *['string', 'callback', '<binding>', 'underline_index']*

   If specified, this creates a user-defined right-click menu rather than the one that is provided by default.  The value specified must be a four element nested anonymous array that contains (in this order):

  1. a string that appears on the menu,

  2. a callback (in 'package::callback' syntax format),

  3. a binding for that option (see below),

  4. an index value specifying the character in the string to be
     underlined.

The binding specified need only be in the form, '<Control-x>'.  You needn't explicitly bind it yourself.  Your callback will automatically be bound to the event sequence you specified.

METHODS
-------

   *$lpe->deleteItem(index, ?index?)*

   Deletes the menu option at the specified index.  A range of values may be deleted as well, e.g. $lpe->deleteItem(3,'end');  Returns an array reference if a single item is deleted, or a reference to an array of references if more than one item is deleted.

   *$lpe->addItem(?index?, $item)*

   Adds a menu option at the specified index, where $item is an anonymous array consisting of four elements (see the -menuitems option for details).  If no index is specified, the new item will be added at the end of the menu.  If an item already exists at that index, the current menu items will be "bumped" down.  Returns the list of menuitems.

ADVERTISED SUBWIDGETS
---------------------

   *$lpe->Subwidget('popupmenu')*

   Returns a reference to the popupmenu (a toplevel widget).

KNOWN BUGS
----------

   The -minvalue only works for the first digit.

   There is still potential for odd results if your bind happens to
coincide with a binding already used by the Window Manager.  In windows,
where I did most of my testing, this meant that Control-v would paste
twice, once because MS Windows told it to, and once because I told it to.

PLANNED CHANGES
---------------

   Fix the issues mentioned above.

   Automatically bind the 'Alt' key to the underlined character.

   Give the option to remove bindings completely.

AUTHOR
------

   Daniel J. Berger djberg96@hotmail.com

SEE ALSO
--------

   Entry, LabEntry

Perl Module to interpret BASIC
******************************

NAME
====

   Language::Basic - Perl Module to interpret BASIC

SYNOPSIS
========

     use Language::Basic;

     my $Program = new Language::Basic::Program;
     $Program->input("program.bas"); # Read lines from a file
     $Program->parse; # Parse the Program
     $Program->implement; # Run the Program
     $Program->output_perl; # output Program as a Perl program

     $Program->line("20 PRINT X"); # add one line to existing Program

   Featured scripts:

basic.pl
     Runs BASIC programs from the command line.

termbasic.pl
     Term::Readline program. Input one line of BASIC at a time, then run
     the program.

basic2pl.pl
     Outputs a Perl program that does the same thing as the input BASIC
     program.

DESCRIPTION
===========

   This module lets you run any BASIC programs you may have lying around,
or may inspire you to write new ones!

   The aspects of the language that are supported are described below. Note
that I was pretty much aiming for Applesoft BASIC (tm) ca. 1985, not some
modern BASIC with real subroutines.

Class Language::Basic::Program
------------------------------

   This class handles a whole program. A Program is just a bunch of Lines,
each of which has one or more Statements on it. Running the program
involves moving through the lines, usually in numerical order, and
implementing each line.

   Methods:

current_program
     Returns the program currently being parsed/implemented/whatever

set_current_program
     Sets arg0 to be the Current Program

current_line
     Returns the LB::line currently being parsed/implemented/whatever

set_current_line
     Sets the current line in Program arg0 to be line number arg1

first_line_number
     Returns (not surprisingly) the first line number in Program arg0

current_line_number
     What line number in Program arg0 are we currently on?

input
     This method reads in a program from a file, whose name is the string
     arg0. It doesn't do any parsing, except for taking the line number
     out of the line.

line
     This method takes a line of BASIC (arg1, already chomped), forms a
     new LB::Line with it, and adds it to the Program (arg0). It doesn't
     do any parsing, except for taking the line number out of the line.

parse
     This method parses the program, which just involves looping over the
     lines in the program and parsing each line.

implement
     This method actually runs the program. That is, it starts on the
     first line, and implements statements one at a time. It performs the
     statements on a line in order, and goes from line to line in
     numerical order, unless a GOTO, NEXT, etc. sends it somewhere else.
     It stops when it hits an END statement or "falls off" the end of the
     program.

start
     This method erases program stack and moves line pointer to beginning
     of program

     It should be called any time we start going through the program.
     (Either implement or output_perl.)

goto_line
     Continue Program execution at the first Statement on line number arg1.

goto_after_statement
     Kind of like goto_line, except go to the Statement after Statement
     arg1.  (Or the first statement on the line just after Statement arg1,
     if it's the last Statement on its line.) E.g., when you RETURN from a
     GOSUB, you want to return to the GOSUB line but start execution after
     the GOSUB. Same with FOR.

   The following methods are called from LB::Statement parse or implement
methods to implement various BASIC commands.

push_stack
     (GOSUB) Call a subroutine, i.e. push the current Statement::Gosub
     onto the Program's calling stack

pop_stack
     (RETURN) Return from a subroutine, i.e., pop the top Statement::Gosub
     off of the Program's calling stack

store_for
     (FOR) Store a Statement::For arg1, so that when we get to the
     corresponding Statement::Next, we know where to go back to

pop_stack
     (NEXT) Get the Statement::For corresponding to Statement::Next arg1

add_data
     (DATA) Add a piece of data to the Program's data storage, to be
     accessed later.

get_data
     (READ) Get a piece of data that was stored earlier.

   Finally, there are methods for translating a Program to Perl.

output_perl
     This method translates a program to Perl and outputs it. It does so by
     looping through the Lines of the program in order, and calling
     output_perl on each one.  It also prints some pre- and post- data,
     such as any subroutines it needs to declare (e.g., subs that imitate
     BASIC functionality, as well as subs that correspond to BASIC DEF
     statements).

     It attempts to print everything out nicely, with added whitespace et
     al.  to make the code somewhat readable.  (Note that all of the
     subpackages' output_perl methods return strings rather than printing
     them, so we can handle all of the printing, indenting, etc. here.)

need_sub
     Tells the Program that it needs to use the sub named arg0 (whose
     definition is in arg1). This is used for outputting a Perl
     translation of a BASIC program, so that you only write "sub mid_str
     {...}" if MID$ is used in the BASIC program.

Class Language::Basic::Line
---------------------------

   This class handles one line of a BASIC program, which has one or more
Statements on it.

   This class has no implement method. The reason is that sometimes, you'll
jump to the middle of a line. (E.g., returning from the GOSUBs in 10 FOR
A=1 TO 10: GOSUB 1000: NEXT A)

   Methods:

get_next
     Returns the Line's line number

get_next
     Returns the next line number in the Program

set_next
     Sets the next line number in the Program to be arg1.

parse
     This method breaks the line up into Statements (and removes
     whitespace, except in strings), then parses the Statements in order.

output_perl
     This method simply calls output_perl on each of the Line's Statements
     in order.

BASIC LANGUAGE REFERENCE
========================

   This is a (hopefully current) description of what Language::Basic
supports.  For each command, I give an example use of that command, and
possible a comment or two about it.

   Also see Language/Basic/Syntax, which
describes the exact syntax for each statement, expressions, variable
names, etc.

Commands
--------

DATA
     DATA 1,2,"HI". These will be read sequentially by READ statements.
     Note that currently all string constants must be quoted.

DEF
     DEF FNA(X)= INT(X + .5).

DIM
     DIM A(20), B(10,10). Arrays default to size 10 (or actually 11 since
     they start at zero.)

END
     END.

FOR
     FOR I = 1 TO 10 STEP 3. STEP defaults to 1 if not given, and may be
     negative.  (For loops are always implemented at least once.)

GOTO
     GOTO 30. Note that GOTO 30+(X*3) is also supported.

GOSUB
     GOSUB 10+X. Gosub is just like GOTO, except that when the program
     gets to a RETURN statement, it will come back to the statement just
     after the GOSUB.

IF
     IF X > Y THEN 30 ELSE X = X + 1. ELSE is not required. In a THEN or
     ELSE, a lone number means GOTO that number (also known as an implied
     GOTO).

INPUT
     INPUT A$, B$. Also allowed is INPUT "FOO"; BAR. This prints "FOO?"
     instead of just "?" as the input prompt.

LET
     LET X=4. The word "LET" isn't required; i.e. X=4 is just like LET X=4.

NEXT
     NEXT I. Increment I by STEP, test against its limit, go back to the
     FOR statement if it's not over (or under, for a descending loop) its
     limit.

ON
     ON X-3 GOSUB 10,20. This is equivalent to:   IF X-3 = 1 THEN GOSUB 10
      IF X-3 = 2 THEN GOSUB 20

     ON ... GOTO is also allowed.

PRINT
     PRINT FOO; BAR$, 6*BLAH. semicolon means no space (or one space after
     printing numbers!), comma is like a 14-character tab (or \n past
     column 56).  Print \n after the last expression unless there's a
     semicolon after it.

READ
     READ A, B(I), C$. Reads data from DATA statements into variables

REM
     REM WHATEVER. Anything after the REM is ignored (including colons and
     succeeding statements!)

RETURN
     RETURN. Return to the statement after the last GOSUB.

Intrinsic functions
-------------------

   The following functions are currently supported:

   Numeric Functions: INT (like Perl's int), RND (rand), ASC (ord), LEN
(length), VAL (turn a string into a number; in Perl you just + 0 :))

   RND just calls Perl's rand; you can't seed it or anything.

   String functions: CHR$, MID$, STR$

Overall Coding Issues
---------------------

   * Multiple statements can appear on one line, separated by colons. E.g.:
     10 FOR I = 1 TO 10: PRINT I: NEXT I, or 20 FOR A = 1 TO 4: GOSUB
     3000: NEXT A.  Note that after a THEN, all statements are considered
     part of the THEN, until a statement starting with ELSE, after which
     all remaining statements are part of the ELSE. A REM slurps up
     everything until the end of the line, including colons.

   * Hopefully your code doesn't have many bugs, because there isn't much
     error checking.

   * Everything except string constants is converted to upper case, so 'a'
     and 'A' are the same variable. (But note that the string "Yes" <>
     "YES", at least for now.)

   * Spaces are (currently) required around various pieces of the program,
     like THEN, ELSE, GOTO. That is, GOTO20 won't work. This may or may
     not change in the future.

   * When you use basic.pl (&LB::Program::input), the lines in the input
     file must be in numerical order. When using termbasic.pl
     (&LB::Program::line), this rule doesn't apply.

BUGS
====

   This is an alpha release and likely contains many bugs; these are merely
the known ones.

   If you use multiple *Language::Basic::Program* objects in a Perl
program, functions and variables can leak over from one to another.

   It is possible to get some Perl warnings; for example, if you input a
string into a numerical variable and then do something with it.

   PRINT and so forth all go to the select-ed output handle; there really
ought to be a way to set for a *Program* the output handle.

   There needs to be better and consistent error handling, and a more
extensive test suite.

AUTHOR
======

   Amir Karger (akarger@cpan.org)

   David Glasser gave ideas and feedback, hunted down bugs, and sent in a
major patch to help the LB guts.

COPYRIGHT
=========

   Copyright (c) Amir Karger 2000

LICENSE
=======

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

HISTORY
=======

   BASIC stands for Beginner's All-purpose Symbolic Instruction Code.
Since it was considered pretty hot stuff in the early 80's, it's the first
language that I and a lot of folks my age learned, so it holds a special
place in my heart.  Which is the only reason I spent so many hours writing
an interpreter for it long after it was superseded by real interpreted
languages that had subroutines and didn't rely quite so much on GOTO.

   I originally wrote this interpreter in C, as the final project for my
first C programming class in college. Its name at that point was COMPLEX,
which stood for "C-Oriented Major Project which did not use LEX".

   When I learned Perl, I felt like its string handling capabilities would
be much better for an interpreter, so eventually I ported and expanded it.
(Incidentally, I was right. I had surpassed the original program's
functionality in less than a week, and I was able to run wumpus in 2.)

   A big goal for the Perl port is to support enough of the language that
I can run wumpus, another legacy from my childhood.  The interpreter's
name could be changed from COMPLEX to "Perl Eclectic Retro interpreter
which did not use Parse::LEX", or PERPLEX, but I settled for
Language::Basic instead.

SEE ALSO
========

   All of the `Language::Basic::*' in this nodes associated with
Language::Basic sub-modules

   See Language/Basic/Syntax, which describes
the syntax supported by the Language::Basic module

   perl(1), wump(6)

Package to handle string, numeric, and boolean expressions.
***********************************************************

NAME
====

   Language::Basic::Expression - Package to handle string, numeric, and
boolean expressions.

SYNOPSIS
========

   See Language/Basic, for the overview of how the
Language::Basic module works. This pod page is more technical.

     # Given an LB::Token::Group, create an expression I<and> parse it
     my $exp = new LB::Expression::Arithmetic $token_group;
     # What's the value of the expression?
     print $exp->evaluate;
     # Perl equivalent of the BASIC expression
     print $exp->output_perl;

   Expressions are basically the building blocks of Statements, in that
every BASIC statement is made up of keywords (like GOTO, TO, STEP) and
expressions.  So expressions include not just the standard arithmetic and
boolean expressions (like 1 + 2), but also lvalues (scalar variables or
arrays), functions, and constants. See Language/Basic/Syntax,
for details on the way expressions are built.

DESCRIPTION
===========

   BASIC expressions are represented by various objects of subclasses of
Language::Basic::Expression. Most LB::Expressions are in turn made up of
other LB::Expressions. For example an LBE::Arithmetic may be made up of two
LBE::Multiplicative and a "plus". "Atoms" (indivisible LBE's) include
things like LBE::Constants and LBE::Lvalues (variables).

The LBE hierarchy
-----------------

   A bunch of LBE subclasses represent various kinds of BASIC expressions.
These subclasses closely follow the BASIC syntax diagram.

   Expressions can be classified in two ways, which are sort of vertical
and horizontal. One classification method is what subexpressions (if any)
an expression is made of. For example, an Arith. Exp. is made up of one or
more Mult. Exps. connected by plus or minus signs, while a Mult. Exp. is
made up of one or more Unary Exps. This is a hierarchical (or vertical)
distinction, important for building up the tree of objects that represent
a BASIC expression.

   (Note that not all levels in the hierarchy have to be filled. We don't
bother making an Arith. Exp. which contains just one Mult. Exp. which
contains just one Unary Exp. Instead, we just use the Unary Exp. itself
(when it's safe to do so!)

   The second way of classifying expressions is by their return type. A
String Exp. is a string constant, a string variable, a string function, or
some other expression whose value when evaluated will be a string. A
Numeric Exp.  evaluates to a number, and a Boolean to a True or False
value.  This distinction is important for typechecking and finding syntax
errors in BASIC code.  (Note that in BASIC - unlike Perl or C - you can't
"cast" a boolean value into an integer or string. This actually makes
parsing more difficult.)

   Some expressions don't exactly fit any of these distinctions.  For
example, an Arglist evaluates to a list of expressions, each of which may
be Numeric or Boolean.

subclass methods
----------------

   Each subclass has (at least) three methods:

new
     The "new" method takes a class and a Token::Group (and possibly some
     other args).  It eats one or more Tokens from it, parsing them,
     creating a new object of that class I, and setting various fields in
     that object, which it returns.  If the tokens don't match the class,
     "new" returns undef.

     If an expression contains just one subexpression often we'll just
     return the subexpression.  So if an Arith. Exp.  contains just one
     Mult. Exp., we'll just return the LBE::Multiplicative object and not
     an LBE::Arithmetic object.

evaluate
     Actually calculates the value of the expression. For a string or
     numeric constant or variable, that just means taking the stored value
     of that object. For other Expressions, you actually need to do math.

output_perl
     Gives a string with the Perl equivalent to a BASIC expression. "1+2"
     is converted to "1+2", but "A" becomes "$a", "A$" becomes "$a_str",
     and function calls may be even more complicated.

LBE subclasses
--------------

   The hierarchical list of subclasses follows:

Arithmetic
     An arithmetic expression is a set of multiplicative expressions
     connected by plus or minus signs. (String expressions can only be
     connected by plus, which is the BASIC concatenation operator.)

Multiplicative
     a set of unary expressions connected by '*' or '/'.

Unary
     a variable, a function, a string or numeric constant, or an arithmetic
     expression in parentheses, potentially with a unary minus sign.

Constant
     a string or numeric constant, like "17" or 32.4

Lvalue
     a settable expression: a variable, X, or one cell in an array,
     A(17,Q). The "variable" method returns the actual
     LB::Variable::Scalar object referenced by this Lvalue.

Function
     Either an Intrinsic or a User-Defined function.

Arglist
     a list of arguments to an array or function

Logical_Or
     a set of Logical_And expressions connected by "OR"

Logical_And
     a set of Relational expressions connected by "AND"

Relational
     A relational expression, like "A>B+C", optionally with a NOT in front
     of it.

Package to handle user-defined and intrinsic Functions in BASIC.
****************************************************************

NAME
====

   Language::Basic::Function - Package to handle user-defined and intrinsic
Functions in BASIC.

SYNOPSIS
========

   See Language/Basic, for the overview of how the
Language::Basic module works. This pod page is more technical.

   A Function can be either an intrinsic BASIC function, like INT or CHR$,
or a user-defined function, like FNX (defined with the DEF command).

DESCRIPTION
===========

   The check_args method checks that the right number and type of function
arguments were input.

   The evaluate method actually calculates the value of the function, given
certain arguments.

   The lookup method looks up the function in the function lookup table.

   The output_perl method returns a string that's the Perl equivalent to
the BASIC function.

   Class Language::Basic::Function::Intrinsic

   This class handles intrinsic BASIC functions.

   The initialize method sets up BASIC's supported functions at the
beginning of the program. The all-important @Init holds a ref for each
function to an array holding: - the function name, - the number and type
of arguments (in a Perl function prototype-like style), - a subref that
performs the equivalent of the BASIC function, and - a string for the
output_perl method. That string is either the name of an   equivalent Perl
function, like "ord" for BASIC's "ASC", or (if there is no   exact
equivalent) a BLOCK that performs the same action.  Adding intrinsic BASIC
functions therefore involves adding to this array.

   Class Language::Basic::Function::Defined

   This class handles functions defined by the user in DEF statements.

Package to handle parsing and implementing single BASIC statements.
*******************************************************************

NAME
====

   Language::Basic::Statement - Package to handle parsing and implementing
single BASIC statements.

SYNOPSIS
========

   See Language/Basic, for the overview of how the
Language::Basic module works. This pod page is more technical.

   A Statement is something like 'GOTO 20' or 'PRINT "HELLO"'. A line of
BASIC code is made up of one or more Statements.

     # Create the statement from an LB::Token::Group and
     # bless it to an LBS::* subclass
     my $statement = new Language::Basic::Statement $token_group;
     $statement->parse; # Parse the statement
     $statement->implement; # Implement the statement

     # Return a string containing the Perl equivalent of the statement
     $str = $statement->output_perl;

DESCRIPTION
===========

   Take a program like:

     5 LET A = 2

     10 IF A >= 3 THEN GOTO 20 ELSE PRINT "IT'S SMALLER"

   Line 5 has just one statement. Line 10 actually contains three. The
first is an IF statement, but the results of the THEN and the ELSE are
entire statements in themselves.

   Each type of statement in BASIC has an associated LB::Statement class.
For example, there's LB::Statement::Let and LB::Statement::If. (But no
LB::Statement::Then! Instead the "then" field of the LB::Statement::If
object will point to another statement. In the above program, it would
point to a LB::Statement::Goto.)

   Parsing a line of BASIC starts with removing the line number and lexing
the line, breaking it into Tokens which are held in an LB::Token::Group.
LB::Statement::new, refine, and parse, are all called with a Token::Group
argument. These methods gradually "eat" their way through the Tokens.

   LBS::new simply creates an LBS object. However, it then calls
LBS::refine, which looks at the first Token of the command and blesses the
object to the correct LBS::* subclass.

   Each LBS subclass then has (at least) the methods parse, implement, and
output_perl.

   The parse method goes through the text and digests it and sets various
fields in the object, which are used by implement and output_perl.  The
implement method actually implements the BASIC command.  The output_perl
method returns a string (with ; but not \n at the end) of the Perl
equivalent of the BASIC statement.

Pod file describing syntax understood by Language::Basic module
***************************************************************

NAME
====

   Syntax - Pod file describing syntax understood by Language::Basic module

SYNOPSIS
========

   There is no Language::Basic::Syntax module. This is just a pod file
describing the syntax that's supported by the Language::Basic module.

DESCRIPTION
===========

   Things in *italics* are objects. Things in *boldface* are actual strings
(reserved words or punctuation).  "[]" means optional, "..." means
optionally more copies of the same thing, and things between slashes that
look like Perl regexps are Perl regexps.

   This syntax description probably isn't exactly correct from a computer
science standpoint, but the idea is just to show what LB supports.

Line Syntax
-----------

Line:
     *Line_Num* Statement [: Statement ...]

Statement Syntax
----------------

   * DATA Constant [ *,* Constant ...]

   * DIM *Var-Name* [ Arglist ] [ *,* *Var-Name* [ Arglist ] ...]

     Arglist must be made up of constant arithmetic expressions.

   * DEF *Func-Name* ( *Var-Name* [ *,* *Var-Name* ...] )  = *Arith-Exp*

     *Var-Name*s must be scalar variables.

   * END

   * FOR Lvalue = *Arith-Exp* TO *Arith-Exp* [ *STEP* *Arith-Exp*]

   * GOTO *Arith-Exp*

   * IF *Or-Exp* *THEN* Statement [ : Statement ...] [ ELSE Statement [ :
     Statement ...]]

     IF *Or-Exp* *THEN* *Line_Num* [ ELSE *Line_Num* ]

   * INPUT [ *Str-Const* *;* ] Lvalue [ *,* Lvalue ...]

   * [LET] Lvalue = *Arith-Exp*

   * NEXT Lvalue

   * ON *Arith-Exp* GOTO/GOSUB *Arith-Exp* [ *,* *Arith-Exp* ...]

   * PRINT [ Expression [ *Print_Sep* ] [  Expression [ *Print_Sep* ] ...]
     ]

   * READ Lvalue [ *,* Lvalue ...]

   * Comment

Expression Syntax
-----------------

   Note that, unlike C or Perl, Boolean values cannot be "cast" to
non-Boolean (string or numeric) values and vice versa.

   By the way, the classes in module Language::Basic::Expression rather
closely mimic this syntax description.

Expression:
     *Arith-Exp*

     *Or-Exp*

*Arithmetic Expression*:
     *Mult-Exp* *Arith-Op* *Mult-Exp*

     *String-Exp* + *String-Exp*

*Multiplicative Expression*:
     *Unary-Exp* *Mult-Op* *Unary-Exp*

*Unary Expression*:
     - *Unary-Exp*

     (*Arith-Exp*)

     Lvalue

     Function

     Constant

Lvalue:
     *Var-Name* [ Arglist ]

Arglist:
     ( Expression [ *,* Expression ...] )

Function:
     *Func-Name* Arglist

Constant:
     *Str-Const*

     *Num-Const*

*String Expression*:
     *Str-Const*

     *Arith-Exp*

     The *Arith-Exp* must be made from *Str-Exp*s.

*Logical Or Expression*:
     *And-Exp* [ *OR* *Or-Exp* ]

*Logical And Expression*:
     *Rel-Exp* [ AND *And-Exp* ]

*Relational Expression*:
     *NOT* *Rel-Exp*

     *Arith-Exp*  *Rel-Op*  *Arith-Exp*

     *String-Exp*  *Rel-Op*  *String-Exp*

     ( *Or-Exp* )

Identifier Syntax
-----------------

*Variable Name*:
     *Numeric Identifier*

     *String Identifier*

*Function Name*:
     /FN[A-Z]\w+/

*Numeric Identifier*:
     /[A-Z]\w*/

*String Identifier*:
     /[A-Z]\w*\$/

Token Syntax
------------

   Tokens, or atoms, are indivisible pieces of text making up a BASIC
program

   (Note: Language::Basic only pays attention to case in string constants.)

*Line Number*:
     /\d+/

Comment:
     REM /.*/

     Note that a comment goes all the way to the end of a line. Colons in
     a comment do not start a new statement.

Keyword:
     DATA | DIM | DEF | END | FOR | GOSUB | GOTO | IF | INPUT | LET | NEXT
     | ON | PRINT | READ | RETURN | *THEN* | ELSE | TO | *STEP*

*Numeric Constant*:
     /(\d*)?\.?\d+/

*String Constant*:
     /".*?"/

*Relational Operator*:
     *<* | *<=* | *>* | *>=* | = | *<>*

*Arithmetic Operator*:
     + | -

*Multiplicative Operator*:
     * | /

*Print Separator*:
     *,* | *;*

Module to handle lexing BASIC statements.
*****************************************

NAME
====

   Language::Basic::Token - Module to handle lexing BASIC statements.

SYNOPSIS
========

   See Language/Basic, for the overview of how the
Language::Basic module works. This pod page is more technical.

     # lex a line of basic into a bunch of tokens.
     my $token_group = new Language::Basic::Token::Group;
     $token_group->lex('PRINT "YES","NO" : A=A+1');

     # Look at tokens
     my $tok = $token_group->lookahead && print $tok->text;
     # Eat expected tokens
     my $tok = $token_group->eat_if_string(",");
     my $tok = $token_group->eat_if_class("Keyword");

DESCRIPTION
===========

   BASIC tokens are pretty simple. They include Keywords, Identifiers
(Variable or Function names), String and Numeric Constants, and a few one-
or two-character operators, like ':' and '<='. Tokens aren't very
ambiguous, so for example, you don't need to know what type of Statement
you're looking at in order to lex a line of BASIC. (The only remotely
ambiguous thing is that '=' can be either a Relational Operator or an
Assignment statement.)

   The subclasses of LB::Token represent the various sorts of tokens. The
Token::Group class isn't really a subclass at all; it's a group of tokens.
See `"Language::Basic::Token::Group"' in this node for more info.

   The "text" method returns the text that makes up the token. Note that
text is stored in upper case (except for string constants, which are stored
exactly as entered).

class Language::Basic::Token::Group
-----------------------------------

   This important class handles a group of tokens. Text from the BASIC
program is lexed and turned into LB::Tokens which are stored in a
Token::Group. Any access to these Tokens (including creating them) is
through the Token::Group methods. Other classes' parse methods will
usually eat their way through the tokens in the Token::Group until it's
empty.

new
     This method just creates a new LBT::Group.

lex
     This method breaks BASIC text arg1 into LB::Tokens and puts them in
     Token::Group arg0.

lookahead
     This method returns the next token in the Token::Group without
     removing it from the group. That means lookahead can be called many
     times and keep getting the same token (as long as eat is never
     called).  It returns undef if there are no more Tokens left.

eat
     This method eats the next Token from the Token::Group and returns it.
     It returns undef if there are no more Tokens left.

eat_if_string
     This method eats the next token from Group arg0 if it matches string
     arg1 If it ate a token, it returns it. Otherwise (or if there are no
     tokens left) it returns undef.

     Note that the string to match should be upper case, since all \w
     tokens are stored as uppercase.

eat_if_class
     This method eats the next token from Group arg0 if the token is of
     class "Language::Basic::Token::" . arg1. (I.e., it's called with
     "Keyword" to get a Language::Basic::Token::Keyword Token.) If it ate
     a token, it returns it.  Otherwise (or if there are no tokens left)
     it returns undef.

slurp
     Eats tokens from Group arg1 and puts them in Group arg0 until it gets
     to a Token whose text matches string arg2 or it reaches the end of
     arg1. (The matching Token is left in arg1.)

stuff_left
     Returns true if there's stuff left in the Statement we're parsing
     (i.e. if there are still tokens left in the Token::Group and the next
     token isn't a colon)

print
     For debugging purposes. Returns the Tokens in Group arg0 nicely
     formatted.

Other Language::Basic::Token subclasses
---------------------------------------

   The other subclasses are actually kinds of Tokens, unlike Token::Group.
There are no "new" methods for these classes. Creation of Tokens is done
by Token::Group::lex. In fact, these classes don't have any public
methods. They're mostly there to use "isa" on.

Keyword
     A BASIC keyword (reserved word)

Identifier
     An Identifier matches /[A-Z][A-Z0-9]*\$?/. It's a variable or function
     name.

String_Constant
     Stuff inside double quotes.

Numeric_Constant
     A float (or integer, currently)

Left_Paren
     A "("

Right_Paren
     A ")"

Separator
     Comma or semicolon (separators in arglists, PRINT statements)

Arithmetic_Operator
     Plus or minus

Multiplicative_Operator
     Multiply or divide operators ('*' and '/')

Relational_Operator
     Greater than, less than, equals, and their combinations. Note that
     equals sign is also used to assign values in BASIC.

Logical_Operator
     AND, OR, NOT

Comment
     REM statement (includes the whole rest of the line, even if there are
     colons in it)

Statement_End
     End of a statement (i.e., a colon)

Module to handle parsing and implementing BASIC variables.
**********************************************************

NAME
====

   Language::Basic::Variable - Module to handle parsing and implementing
BASIC variables.

SYNOPSIS
========

   See Language/Basic, for the overview of how the
Language::Basic module works. This pod page is more technical.

   There are two sorts of variables: Arrays and Scalars. Each of those
classes has a subclass for Numeric or String variables.

DESCRIPTION
===========

   An Array needs to have full LBV::Scalar objects in it, rather than just
having an array of values. The reason is that, for example, you might use
ARR(3) as the variable in a FOR loop. Also, the "set" and "value" methods
apply to a LBV::Scalar (since you can't set an array to a value (in BASIC
:)) so in order to be handle A(3)=3, A(3) needs to be an LBV::Scalar.

   The lookup method looks up a variable in the Array or Scalar lookup
table (depending on whether there were parentheses after the variable
name). BASIC allows undeclared variables, so if the variable name hasn't
been seen before, a new variable is created.

Language::Basic::Variable::Scalar class
---------------------------------------

   This class handles a variable or one cell in an array.

   Methods include "value", which gets the variable's value, and "set",
which sets it.

Language::Basic::Variable::Array class
--------------------------------------

   This class handles a BASIC array. Each cell in the array is a
LBV::Scalar object.

   Methods include "dimension", which dimensions the array to a given size
(or a default size) and get_cell, which returns the LBV::Scalar object in a
given array location.

   Note that BASIC arrays start from 0!

a module which makes Perl slightly more functional
**************************************************

NAME
====

   Language::Functional - a module which makes Perl slightly more
functional

SYNOPSIS
========

     use Language::Functional ':all';
     print 'The first ten primes are: ',
       show(take(10, filter { prime(shift) } integers)), "\n";

DESCRIPTION
===========

   Perl already contains some functional-like functions, such as map and
grep. The purpose of this module is to add other functional-like functions
to Perl, such as foldl and foldr, as well as the use of infinite lists.

   Think as to how you would express the first ten prime numbers in a
simple way in your favourite programming language? So the example in the
synopsis is a killer app, if you will (until I think up a better one ;-).

   The idea is mostly based on Haskell, from which most of the functions
are taken. There are a couple of major omissions: currying and types.
Lists (and tuples) are simply Perl list references, none of this 'cons'
business, and strings are simple strings, not lists of characters.

   The idea is to make Perl slightly more functional, rather than
completely replace it. Hence, this slots in very well with whatever else
your program may be doing, and is very Perl-ish. Other modules are
expected to try a much more functional approach.

FUNCTIONS
=========

   The following functions are available. (Note: these should not be
called as methods).

   In each description, I shall give the Haskell definition (if I think it
would help) as well as a useful example.

show
     Show returns a string representation of an object.  It does not like
     infinite lists.

inc k
     Increases the value passed by 1.

          $x = inc 2; # 3

     In Haskell:

          inc          :: a -> a
          inc k         = 1 + k

double k
     Doubles the passed value.

          $x = double 3; # 6

     In Haskell:

          double         :: a -> a
          double k        = k * 2

square k
     Returns the square of the passed value. eg:

          $x = square 3; # 9

     In Haskell:

          square          :: a -> a
          square k         = k * k

gcd x y
     Returns the greatest common denominator of two numbers. eg:

          $x = gcd(144, 1024); # 16

     In Haskell:

          gcd :: Integral a => a -> a -> a
          gcd 0 0 = error "gcd 0 0 is undefined"
          gcd x y = gcd' (abs x) (abs y)
                    where gcd' x 0 = x
                    gcd' x y = gcd' y (x `rem` y)

lcm x y
     Returns the lowest common multiple of two numbers.  eg:

          $x = lcm(144, 1024); # 9216

     In Haskell:

          lcm            :: (Integral a) => a -> a -> a
          lcm _ 0         = 0
          lcm 0 _         = 0
          lcm x y         = abs ((x `quot` gcd x y) * y)

id x
     The identity function - simply returns the argument.  eg:

          $x = id([1..6]); # [1, 2, 3, 4, 5, 6].

     In Haskell:

          id             :: a -> a
          id x            = x

const k _
     Returns the first argument of 2 arguments. eg:

          $x = const(4, 5); # 4

     In Haskell:

          const          :: a -> b -> a
          const k _       = k

flip f
     Given a function, flips the two arguments it is passed.  Note that
     this returns a CODEREF, as currying does not yet happen. eg: flip(sub
     { $_[0] ** $_[1] })->(2, 3) = 9.  In Haskell (ie this is what it
     should really do):

          flip           :: (a -> b -> c) -> b -> a -> c
          flip f x y      = f y x

Until p f x
     Keep on applying f to x until p(x) is true, and then return x at that
     point. eg:

          $x = Until { shift() % 10 == 0 } \&inc, 1; # 10

     In Haskell:

          until          :: (a -> Bool) -> (a -> a) -> a -> a
          until p f x     = if p x then x else until p f (f x)

fst x:xs
     Returns the first element in a tuple. eg:

          $x = fst([1, 2]); # 1

     In Haskell:

          fst            :: (a,b) -> a
          fst (x,_)       = x

snd x:y:xs
     Returns the second element in a tuple. eg:

          $x = snd([1, 2]); # 2

     In Haskell:

          snd            :: (a,b) -> a
          snd (_,y)       = y

head xs
     Returns the head (first element) of a list. eg:

          $x = head([1..6]); # 1

     In Haskell:

          head             :: [a] -> a
          head (x:_)        = x

Last xs
     Returns the last element of a list. Note the capital L, to make it
     distinct from the Perl 'last' command. eg:

          $x = Last([1..6]); # 6

     In Haskell:

          last             :: [a] -> a
          last [x]          = x
          last (_:xs)       = last xs

tail xs
     Returns a list minus the first element (head). eg:

          $x = tail([1..6]); # [2, 3, 4, 5, 6]

     In Haskell:

          tail             :: [a] -> [a]
          tail (_:xs)       = xs

init xs
     Returns a list minus its last element. eg:

          $x = init([1..6]); # [1, 2, 3, 4, 5]

     In Haskell:

          init             :: [a] -> [a]
          init [x]          = []
          init (x:xs)       = x : init xs

null xs
     Returns whether or not the list is empty. eg:

          $x = null([1, 2]); # False

     In Haskell:

          null             :: [a] -> Bool
          null []           = True
          null (_:_)        = False

Map f xs
     Evaluates f for each element of the list xs and returns the list
     composed of the results of each such evaluation. It is very similar to
     the Perl command 'map', hence the capital M, but also copes with
     infinite lists. eg:

          $x = Map { double(shift) } [1..6]; # [2, 4, 6, 8, 10, 12]

     In Haskell:

          map              :: (a -> b) -> [a] -> [b]
          map f xs          = [ f x | x <- xs ]

filter p xs
     Returns the list of the elements in xs for which p(xs) returns true.
     It is similar to the Perl command 'grep', but it also copes with
     infinite lists. eg:

          $x = filter(\&even, [1..6]); # [2, 4, 6]

     In Haskell:

          filter           :: (a -> Bool) -> [a] -> [a]
          filter p xs       = [ x | x <- xs, p x ]

concat
     Concatenates lists together into one list. eg:

          concat([[1..3], [4..6]]); # [1, 2, 3, 4, 5, 6]

     In Haskell:

          concat           :: [[a]] -> [a]
          concat            = foldr (++) []

     TODO: Make sure this works with infinite lists!

Length
     Returns the length of a list - only do this with finite lists! eg:

          $x = Length([1..6]); # 6

     In Haskell:

          length           :: [a] -> Int
          length            = foldl' (\n _ -> n + 1) 0

     TODO Make sure this works!

foldl f z xs
     Applies function f to the pairs (z, xs[0]), (f(z, xs[0], xs[1]),
     (f(f(z, xs[0], xs[1])), xs[2]) and so on. ie it folds from the left
     and returns the last value.  Note that foldl should not be done to
     infinite lists. eg: the following returns the sum of 1..6:

          $x = foldl { shift() + shift() } 0, [1..6]; # 21

     In Haskell:

          foldl            :: (a -> b -> a) -> a -> [b] -> a
          foldl f z []      = z
          foldl f z (x:xs)  = foldl f (f z x) xs

foldl1 f xs
     This is a variant of foldl where the first value of xs is taken as z.
     Applies function f to the pairs (xs[0], xs[1]), (f(xs[0], xs[1],
     xs[2]), (f(f(xs[0], xs[1], xs[2])), xs[3]) and so on. ie it folds
     from the left and returns the last value.  Note that foldl should not
     be done to infinite lists. eg: the following returns the sum of 1..6:

          $x = foldl1 { shift() + shift() } [1..6]; # 21

     In Haskell:

          foldl1           :: (a -> a -> a) -> [a] -> a
          foldl1 f (x:xs)   = foldl f x xs

scanl f q xs
     Returns a list of all the intermedia values that foldl would compute.
     ie returns the list z, f(z, xs[0]), f(f(z, xs[0]), xs[1]), f(f(f(z,
     xs[0]), xs[1]), xs[2]) and so on. eg:

          $x = scanl { shift() + shift() }, 0, [1..6]; # [0, 1, 3, 6, 10, 15, 21]

     In Haskell:

          scanl        :: (a -> b -> a) -> a -> [b] -> [a]
          scanl f q xs  = q : (case xs of
                               []   -> []
                               x:xs -> scanl f (f q x) xs)

scanl1 f xs
     This is a variant of scanl where the first value of xs is taken as q.
     Returns a list of all the intermedia values that foldl would compute.
     ie returns the list f(xs[0], xs[1]), f(f(xs[0], xs[1]), xs[2]),
     f(f(f(xs[0], xs[1]), xs[2]), xs[3]) and so on. eg:

          $x = scanl1 { shift() + shift() } [1..6]; # [1, 3, 6, 10, 15, 21]

     In Haskell:

          scanl1           :: (a -> a -> a) -> [a] -> [a]
          scanl1 f (x:xs)   = scanl f x xs

foldr f z xs
     This is similar to foldl but is folding from the right instead of the
     left.  Note that foldr should not be done to infinite lists.  eg: the
     following returns the sum of 1..6

          $x = foldr { shift() + shift() } 0, [1..6] ; # 21

     In Haskell:

          foldr            :: (a -> b -> b) -> b -> [a] -> b
          foldr f z []      = z
          foldr f z (x:xs)  = f x (foldr f z xs)

foldr1 f xs
     This is similar to foldr1 but is folding from the right instead of the
     left. Note that foldr1 should not be done on infinite lists. eg:

          $x = foldr1 { shift() + shift() } [1..6]; # 21

     In Haskell:

          foldr1           :: (a -> a -> a) -> [a] -> a
          foldr1 f [x]      = x
          foldr1 f (x:xs)   = f x (foldr1 f xs)

scanr f z xs
     This is similar to scanl but is scanning and folding from the right
     instead of the left. Note that scanr should not be done on infinite
     lists. eg:

          $x = scanr { shift() + shift() } 0, [1..6];
          # [0, 6, 11, 15, 18, 20, 21]

     In Haskell:

          scanr            :: (a -> b -> b) -> b -> [a] -> [b]
          scanr f q0 []     = [q0]
          scanr f q0 (x:xs) = f x q : qs
                              where qs@(q:_) = scanr f q0 xs

scanr1 f xs
     This is similar to scanl1 but is scanning and folding from the right
     instead of the left. Note that scanr1 should not be done on infinite
     lists. eg:

          $x = scanr1 { shift() + shift() } [1..6];
          # [6, 11, 15, 18, 20, 21]

     In Haskell:

          scanr1           :: (a -> a -> a) -> [a] -> [a]
          scanr1 f [x]      = [x]
          scanr1 f (x:xs)   = f x q : qs
                              where qs@(q:_) = scanr1 f xs

iterate f x
     This returns the infinite list (x, f(x), f(f(x)), f(f(f(x)))...) and
     so on. eg:

          $x = take(8, iterate { shift() * 2 } 1);
          # [1, 2, 4, 8, 16, 32, 64, 128]

     In Haskell:

          iterate          :: (a -> a) -> a -> [a]
          iterate f x       = x : iterate f (f x)

repeat x
     This returns the infinite list where all elements are x. eg:

          $x = take(4, repeat(42)); # [42, 42, 42, 42].

     In Haskell:

          repeat           :: a -> [a]
          repeat x          = xs where xs = x:xs

replicate n x
     Returns a list containing n times the element x. eg:

          $x = replicate(5, 1); # [1, 1, 1, 1, 1]

     In Haskell:

          replicate        :: Int -> a -> [a]
          replicate n x     = take n (repeat x)

take n xs
     Returns a list containing the first n elements from the list xs. eg:

          $x = take(2, [1..6]); # [1, 2]

     In Haskell:

          take                :: Int -> [a] -> [a]
          take 0 _             = []
          take _ []            = []
          take n (x:xs) | n>0  = x : take (n-1) xs
          take _ _             = error "Prelude.take: negative argument"

drop n xs
     Returns a list containing xs with the first n elements missing. eg:

          $x = drop(2, [1..6]); # [3, 4, 5, 6]

     In Haskell:

          drop                :: Int -> [a] -> [a]
          drop 0 xs            = xs
          drop _ []            = []
          drop n (_:xs) | n>0  = drop (n-1) xs
          drop _ _             = error "Prelude.drop: negative argument"

splitAt n xs
     Splits the list xs into two lists at element n. eg:

          $x = splitAt(2, [1..6]);# [[1, 2], [3, 4, 5, 6]]

     In Haskell:

          splitAt               :: Int -> [a] -> ([a], [a])
          splitAt 0 xs           = ([],xs)
          splitAt _ []           = ([],[])
          splitAt n (x:xs) | n>0 = (x:xs',xs'') where (xs',xs'') = splitAt (n-1) xs
          splitAt _ _            = error "Prelude.splitAt: negative argument"

takeWhile p xs
     Takes elements from xs while p(that element) is true. Returns the
     list. eg:

          $x = takeWhile { shift() <= 4 } [1..6]; # [1, 2, 3, 4]

     In Haskell:

          takeWhile           :: (a -> Bool) -> [a] -> [a]
          takeWhile p []       = []
          takeWhile p (x:xs)
                   | p x       = x : takeWhile p xs
                   | otherwise = []

dropWhile p xs
     Drops elements from the head of xs while p(that element) is true.
     Returns the list. eg:

          $x = dropWhile { shift() <= 4 } [1..6]; # [5, 6]

     In Haskell:

          dropWhile           :: (a -> Bool) -> [a] -> [a]
          dropWhile p []       = []
          dropWhile p xs@(x:xs')
                   | p x       = dropWhile p xs'
                   | otherwise = xs

span p xs
     Splits xs into two lists, the first containing the first few elements
     for which p(that element) is true. eg:

          $x = span { shift() <= 4 }, [1..6];
          # [[1, 2, 3, 4], [5, 6]]

     In Haskell:

          span                :: (a -> Bool) -> [a] -> ([a],[a])
          span p []            = ([],[])
          span p xs@(x:xs')
                   | p x       = (x:ys, zs)
                   | otherwise = ([],xs)
                                 where (ys,zs) = span p xs'

break p xs
     Splits xs into two lists, the first containing the first few elements
     for which p(that element) is false. eg:

          $x = break { shift() >= 4 }, [1..6]; # [[1, 2, 3], [4, 5, 6]]

     In Haskell:

          break         :: (a -> Bool) -> [a] -> ([a],[a])
          break p        = span (not . p)

lines s
     Breaks the string s into multiple strings, split at line boundaries.
     eg:

          $x = lines("A\nB\nC"); # ['A', 'B', 'C']

     In Haskell:

          lines     :: String -> [String]
          lines ""   = []
          lines s    = let (l,s') = break ('\n'==) s
                       in l : case s' of []      -> []
                                         (_:s'') -> lines s''

words s
     Breaks the string s into multiple strings, split at whitespace
     boundaries. eg:

          $x = words("hey how random"); # ['hey', 'how', 'random']

     In Haskell:

          words     :: String -> [String]
          words s    = case dropWhile isSpace s of
                            "" -> []
                            s' -> w : words s''
                                  where (w,s'') = break isSpace s'

unlines xs
     Does the opposite of unlines, that is: joins multiple strings into
     one, joined by newlines. eg:

          $x = unlines(['A', 'B', 'C']); # "A\nB\nC";

     In Haskell:

          unlines   :: [String] -> String
          unlines    = concatMap (\l -> l ++ "\n")

     (note that strings in Perl are not lists of characters, so this
     approach will not actually work...)

unwords ws
     Does the opposite of unwords, that is: joins multiple strings into
     one, joined by a space. eg:

          $x = unwords(["hey","how","random"]); # 'hey how random'

     In Haskell:

          unwords   :: [String] -> String
          unwords [] = []
          unwords ws = foldr1 (\w s -> w ++ ' ':s) ws

Reverse xs
     Returns a list containing the elements of xs in reverse order. Note
     the capital R, so as not to clash with the Perl command 'reverse'.
     You should not try to Reverse an infinite list.  eg:

          $x = Reverse([1..6]); # [6, 5, 4, 3, 2, 1]

     In Haskell:

          reverse   :: [a] -> [a]
          reverse    = foldl (flip (:)) []

And xs
     Returns true if all the elements in xs are true. Returns false
     otherwise. Note the capital A, so as not to clash with the Perl
     command 'and'. You should not try to And an infinite list (unless you
     expect it to fail, as it will short-circuit).  eg:

          $x = And([1, 1, 1]); # 1

     In Haskell:

          and       :: [Bool] -> Bool
          and        = foldr (&&) True

Or xs
     Returns true if one of the elements in xs is true. Returns false
     otherwise. Note the capital O, so as not to clash with the Perl
     command 'or'. You may try to Or an infinite list as it will
     short-circuit (unless you expect it to fail, that is). eg:

          $x = Or([0, 0, 1]); # 1

     In Haskell:

          or        :: [Bool] -> Bool
          or         = foldr (||) False

any p xs
     Returns true if one of p(each element of xs) are true. Returns false
     otherwise. You should not try to And an infinite list (unless you
     expect it to fail, as it will short-circuit).  eg:

          $x = any { even(shift) } [1, 2, 3]; # 1

     In Haskell:

          any       :: (a -> Bool) -> [a] -> Bool
          any p      = or  . map p

all p xs
     Returns true if all of the p(each element of xs) is true. Returns
     false otherwise. You may try to Or an infinite list as it will
     short-circuit (unless you expect it to fail, that is). eg:

          $x = all { odd(shift) } [1, 1, 3]; # 1

     In Haskell:

          all  :: (a -> Bool) -> [a] -> Bool
          all p      = and . map p

elem x xs
     Returns true is x is present in xs.  You probably should not do this
     with infinite lists.  Note that this assumes x and xs are numbers.
     eg:

          $x = elem(2, [1, 2, 3]); # 1

     In Haskell:

          elem             :: Eq a => a -> [a] -> Bool
          elem              = any . (==)

notElem x xs
     Returns true if x is not present in x. You should not do this with
     infinite lists. Note that this assumes that x and xs are numbers. eg:

          $x = notElem(2, [1, 1, 3]); # 1

     In Haskell:

          notElem          :: Eq a => a -> [a] -> Bool
          notElem           = all . (/=)

lookup key xys
     This returns the value of the key in xys, where xys is a list of key,
     value pairs. It returns undef if the key was not found. You should not
     do this with infinite lists. Note that this assumes that the keys are
     strings. eg:

          $x = lookup(3, [1..6]); # 4

     In Haskell:

          lookup           :: Eq a => a -> [(a,b)] -> Maybe b
          lookup k []       = Nothing
          lookup k ((x,y):xys)
                | k==x      = Just y
                | otherwise = lookup k xys

     TODO: Make sure this works with infinite lists

minimum xs
     Returns the minimum value in xs.  You should not do this with a
     infinite list.  eg:

          $x = minimum([1..6]); # 1

     In Haskell:

          minimum          :: Ord a => [a] -> a
          minimum           = foldl1 min

maximum xs
     Returns the maximum value in xs.  You should not do this with an
     infinite list.  eg: maximum([1..6]) = 6. In Haskell:

          maximum          :: Ord a => [a] -> a
          maximum           = foldl1 max

sum xs
     Returns the sum of the elements of xs.  You should not do this with
     an infinite list.  eg: sum([1..6]) = 21. In Haskell:

          sum          :: Num a => [a] -> a
          sum           = foldl' (+) 0

product xs
     Returns the products of the elements of xs.  You should not do this
     with an infinite list.  eg: product([1..6]) = 720. In Haskell:

          product      :: Num a => [a] -> a
          product       = foldl' (*) 1

zip as bs
     Zips together two lists into one list. Should not be done with
     infinite lists.  eg: zip([1..6], [7..12]) = [1, 7, 2, 8, 3, 9, 4, 10,
     5, 11, 6, 12].  In Haskell:

          zip              :: [a] -> [b] -> [(a,b)]
          zip               = zipWith  (\a b -> (a,b))

          zipWith                  :: (a->b->c) -> [a]->[b]->[c]
          zipWith z (a:as) (b:bs)   = z a b : zipWith z as bs
          zipWith _ _      _        = []

zip3 as bs cs
     Zips together three lists into one. Should not be done with infinite
     lists.  eg: zip3([1..2], [3..4], [5..6]) = [1, 3, 5, 2, 4, 6].  In
     Haskell:

          zip3             :: [a] -> [b] -> [c] -> [(a,b,c)]
          zip3              = zipWith3 (\a b c -> (a,b,c))

          zipWith3                 :: (a->b->c->d) -> [a]->[b]->[c]->[d]
          zipWith3 z (a:as) (b:bs) (c:cs)
                                    = z a b c : zipWith3 z as bs cs
          zipWith3 _ _ _ _          = []

unzip abs
     Unzips one list into two. Should not be done with infinite lists.
     eg: unzip([1,7,2,8,3,9,4,10,5,11,6,12]) = ([1, 2, 3, 4, 5, 6], [7, 8,
     9, 10, 11, 12]).

          unzip    :: [(a,b)] -> ([a],[b])
          unzip     = foldr (\(a,b) ~(as,bs) -> (a:as, b:bs)) ([], [])

unzip abcs
     Unzips one list into three. Should not be done with infinite lists.
     eg: unzip3([1,3,5,2,4,6]) = ([1, 2], [3, 4], [5, 6]).  In Haskell:

          unzip3   :: [(a,b,c)] -> ([a],[b],[c])
          unzip3    = foldr (\(a,b,c) ~(as,bs,cs) -> (a:as,b:bs,c:cs))
          		      ([],[],[])

integers
     A useful function that returns an infinite list containing all the
     integers. eg: integers = (1, 2, 3, 4, 5, ...).

factors x
     A useful function that returns the factors of x.  eg: factors(100) =
     [1, 2, 4, 5, 10, 20, 25, 50, 100].  In Haskell:

          factors x = [n | n <- [1..x], x `mod` n == 0]

prime x
     A useful function that returns, rather unefficiently, if x is a prime
     number or not. It is rather useful while used as a filter, eg:
     take(10, filter("prime", integers)) = [2, 3, 5, 7, 11, 13, 17, 19,
     23, 29].  In Haskell:

          primes = [n | n <- [2..], length (factors n) == 2]

AUTHOR
======

   Leon Brocard <`acme@astray.com'>

COPYRIGHT
=========

   Copyright (C) 1999, Leon Brocard

   This module is free software; you can redistribute it or modify it
under the same terms as Perl itself.

SYNOPSIS
========

   use Language::Mumps;

   $pcode = Language::Mumps::compile(qq{\tw "Hello world!",!\n\th}); eval
$pcode;

   Language::Mumps::evaluate(qq{\ts x=1 w x});

   Language::Mumps::interprete("example.mps");

   Mumps:translate("example.mps", "example.pl"); *prompt %* `perl
example.pl'

DESCRIPTION
===========

   This module compiles Mumps code to Perl code. The API is simillar to
MumpsVM.

ENVIRONMENT
===========

   Edit ~/.pmumps or /etc/pmumps to set up persistent arrays.

FILES
=====

`$BINDIR/pmumps'  Interpreter
`~/.pmumps'  User configuration
`/etc/pmumps.cf'  Site configuration
AUTHOR
======

   Ariel Brosh, *schop@cpan.org*

SEE ALSO
========

   `pmumps' in this node, see DB_File.

Write XS code on the fly and load it dynamically.
*************************************************

NAME
====

   Language::XS - Write XS code on the fly and load it dynamically.

SYNOPSIS
========

     use Language::XS;

DESCRIPTION
===========

   This module allows C & XS-code creation "on-the-fly", i.e. while your
script is running.

   Here is a very simple example:

     # create a Language::XS-object
     my $xs = new Language::XS cachedir => undef;
     # add plain C to the header
     $xs->hdr("#include <stdio.h>");
     # add a c function (not using xs syntax)
     $xs->cfun('printf ("I was called with %d arguments\n", items);');

     # now compile and find the code-reference
     my $coderef = $xs->find;
     # Now call it
     $coderef->(1, "Zwei", 1/3);

METHODS
=======

new attr => value, ...
----------------------

   Creates a new Language::XS object. Known attributes are:

     id		a unique id that woill be shared among all modules
     cachedir	the common directory where shared objects should be cached.
                    set to undef when you want to disable sharing (must be
                    an  absolute path)

   Default values will be supplied when necessary. Two common idioms are:

     $xs = new Language::XS;			# caching enabled
     $xs = new Language::XS cachedir => undef;	# caching disabled

cached
------

   Returns true when as shared object with the given id already exists.
This obviously only makes sense when you gave the module a unique id.

hdr sourcecode, [id]
--------------------

   Add `sourcecode' to the header portion. Similar to the header portion of
an XS module, you can insert any valid C-code here. Most often you'd add
some include directives, though.

   id can be used to identify this portion (for error messages).

cfun functionbody, [id], [prototype]
------------------------------------

   Adds a XS function whose body is given in `functionbody'. Unlike XS,
you have to do argument processing (i.e. fiddling with `ST(0)') yourself.
id specifies the function name (for `find()' or error messages), and can
be omitted (which results in a default name).

   prototype is an optional string that specifies the perl protoype.
Remember that only the parser will evaluate prototypes.

xsfun xs-source
---------------

   Similar to `cfun', but is able to parse normal XS syntax (most of it,
that is).  Pity that I haven't yet implemented this function, since that
would require serious recoding of xsubpp.

uselib lib...
-------------

   Link against all the libraries given as arguments. The libraries should
be specified as strings of the form `-llibrary'. Additional search paths
can be given using `-L/path/to/libs'. See ExtUtils/Liblist.

incpath path...
---------------

   Add additional include paths. These paths are prepended to the other
include paths.

gen
---

   Create the shared object file. This method is called automatically by
load and even by find. This function returns a truth status and fills the
messages attribute (see messages) with any compiler/linker warnings or
errors.

messages
--------

   Returns the compiler messages (created & updated by gen).

load
----

   Tries to load the shared object, generating it if necessary. Returns a
truth status.

find [id]
---------

   Find the function (either xs or c) with id id and return a code-ref to
it. If id is omitted, the default function (see `cfun') is returned
instead. If no shared object is loaded, calls load.

BUGS/PROBLEMS
=============

   Requires a C compiler (or even worse: the same C compiler perl was
compiled with).

   Does (most probably) not work on many os's, especially non-unix ones.

   You cannot yet use normal XS syntax.

   Line number handling could be better.

AUTHOR
======

   Marc Lehmann <pcg@goof.com>.

SEE ALSO
========

   perl(1).

Perl library browser.
*********************

NAME
====

   Tk::Browser.pm - Perl library browser.

SYNOPSIS
========

   # Call from a shell prompt:

     # browser <module_pathname>  # Open a library file by name
     # browser <package_name>     # Open a package(s) matching
                                  # <package_name> (Unix specific);
     # browser                    # Browse the entire library.

   # Call from a Perl Script:

     use Tk::Browser;
     use Lib::Module;

     # Construct Browser object:
     $b = new Browser;

     # Browse entire library:
     $b -> open();

     # Browse a package by name:
     $b -> open(package => IO::File);

     # Browse a package by module path name:
     $b -> open(pathname =>"/usr/local/lib/perl5/5.6.0/open.pm");

DESCRIPTION
===========

   Tk::Browser.pm creates a library browser for Perl modules.  A browser
has three sub-windows, a module listing at the upper left, a symbol
listing at the upper right, and a text display in the bottom half of the
browser main window.

   The Tk::Browser.pm module contains mainly the window and user interface
code.  The Lib:: modules, included in the distribution archive, do the
actual scanning of the library files and keep track of symbol reference
information.

   Clicking with the left mouse button in the upper left-hand pane selects
a package module.  If no module was specified when the browser was opened
with the Tk::Browser::open method, the the Lib::Module package scans first
instance of each .pm and .pl file in the Perl library's @INC array of
directories.  Duplicate library modules and symlinked directories are
skipped.

   Default Perl configurations include '.' in the @INC path, so that
modules in the current directory and its subdirectories are also scanned.

   The window in the upper right-hand corner of the browser lists all of
the symbols and their values of the currently selected package's symbol
table hash (stash), a lexical scan of the source file, and, optionally,
records the results of a cross-reference scan, depending on the settings
of the Symbol menu options.

   A text window in the lower half of the frame optionally displays the
module source code, POD documentation, or version and file information,
depending on the setting of the View menu options.

   All of the menu bar commands are described in section, MENU FUNCTIONS,
below.

   Clicking the right mouse button in a subwindow displays a pop-up menu
for that pane.  Popup menu functions are also described below.

   By default, the browser lists all Perl source modules, when no modules
are specified to the open() method.  The module class hierarchy then
starts with UNIVERSAL, the abstract superclass of all Perl modules, the
default Perl class.  Selecting the main:: Symbol Table display from the
View menu displays all of the symbols in the default stash, including
those of the the Browser itself.  In this stash also are the path names of
library modules that are imported at run time.

   All imported modules, not only source modules with the *.pm and *.pl
extension can be listed and browsed separately using the Modules ==> List
Imports menu option.

   Opening a browser with the open() method's 'package' option browses the
first package which has a matching name, after locating it in the Perl
library's @INC directories.  The 'pathname' argument specifies the path
name of a single Perl module to browse.

   The Perl script 'browser', listed below, is included in the archive.
It will open a Browser from a shell prompt.  If a the pathname of a module
is supplied as the argument it will open that module.  If the argument is
a package name, if will search the library and open that package:

     #!/usr/bin/perl
     # browser -- Launcher for Browser.pm
     # Substitute path of the perl binary on your system
     # in the line above.
     # When installing, change permissions to executable:
     #  'chmod +x browser'.

     use Tk;
     use Tk::Browser;
     use Lib::Module;
     use Env qw(_);

     my $b;

     $b = new Tk::Browser;

     if( -e $ARGV[0] ) { # assume it's a file name;
       $b -> open(pathname => $ARGV[0]);
     } elsif( $ARGV[0] ) { # assume the arg's a package name and
                           # we have to scan for it.
       $b -> open(package => $ARGV[0]);
     } else {  # No argument: open everything.
       $b -> open;
     }

     MainLoop;

     # End of browser listing

MENU FUNCTIONS
==============

File Menu
---------

   Open Selected Module - Open a new browser for the module selected in
the module list window.

   Save Info... - Open a FileBrowser and prompt for a file name.  Save the
information in each of the browser windows to the text file.

   Exit - Close the browser and exit the program.

Edit Menu
---------

   Cut - Move selected text from the editor pane to the X clipboard.

   Copy - Copy selected text from the editor pane to the X clipboard.

   Paste - Insert text from the X clipboard at the text editor pane's
insertion point.

View Menu
---------

   Source - View module source code of selected module.

   POD Documentation - Format and view the selected module's POD
documentation, if any.

   Module Info - List the selected module's package name, module filename,
version, and superclasses.

   main:: Stash - List symbols in the current main:: Stash.  (That is the
stash of the browser.)

   Package Stashes - Filter current symbol list to show only secondary
stashes and their symbols.

Library Menu
------------

   Read Again - Re-scan the Perl library directories and files.

   View Imported - List and optionally open files listed in the main::
stash that were imported by Perl.

Packages Menu
-------------

   Stash - View symbols that are in the module's symbol table hash.

   Lexical - View symbols parsed from the module's source code.

   Cross References - For non-local stash symbols, check for cross
references in other modules that have been loaded by the interpreter.
Warning: Cross referencing can take a considerable amount of time.

Help Menu
---------

   About - Display the version number and authorship of the Browser
library.

   Help - View the Browser's POD documentation.

Popup Menus
-----------

   Find - Search for text in that pane where the menu is popped up by
pressing the right mouse button.

   Open Module - In the module list window, query for the module name on
which to open a new browser.

COPYRIGHT
=========

   The software in this package is distributed under the terms of the Perl
Artistic License.  Please refer to the file "Artistic" in the distribution
archive file.

REVISION
========

   $Id: Browser.pm,v 0.80 2000/09/22 19:45:53 kiesling Exp $

SEE ALSO
========

   The manual pages for: Lib::Module(3), Tk(3), perl(1), perlmod(1),
perlmodlib(1), perlreftut(1), and perlref(1)

Lib::Module.pm
==============

SYNOPSIS
========

     use Lib::Module;
     use Lib::ModuleSym;
     use Lib::SymbolRef;

DESCRIPTION
===========

   Provides a hierarchical object reference for a Perl library module,
including the package name, file name, version, an array of stash
references, and superclasses, if any.

   Module objects can be stored in a tree similar to the Perl class
hierarchy.  At this time, the hierarchy tree used is only two deep,
because of the many different ways modules can communicate with each
other.  Every module is a subclass of UNIVERSAL, which is the default
abstract superclass of all Perl packages.

   The Lib::ModuleSym.pm module provides lexical scanning and lookup, and
provides cross referencing subroutines.

   The Lib::SymbolRef module provides tied objects that correspond to
stash references, but this needs to be expanded.

Running Under Perl/Tk
---------------------

   This module can call Tk::Event::DoOneEvent() function to provide window
updates.  The function usesTk() checks whether the this module is called
from a program that uses Perl/Tk and returns true if running in a
Tk::MainWindow, false if not.

REVISION
========

   $Id: Module.pm,v 0.65 2000/09/19 21:27:15 kiesling Exp $

SEE ALSO
========

   The manual pages: Tk::Browser(3), perlmod(1), perlmodlib(1), perl(1).

Lexical scanning of Perl library modules.
*****************************************

NAME
====

   Lib::ModuleSym.pm - Lexical scanning of Perl library modules.

DESCRIPTION
===========

   Refer to the Lib::Module(3) manual page.

Running Under Perl/Tk
---------------------

   This module can call Tk::Event::DoOneEvent() function to provide window
updates.  The function usesTk() checks whether the this module is called
from a program that uses Perl/Tk and returns true if running in a
Tk::MainWindow, false if not.

REVISION
========

   $Id: ModuleSym.pm,v 0.52 2000/09/19 21:28:06 kiesling Exp $

SEE ALSO
========

   Refer to the manual pages: Lib::Module(3), Tk::Browser(3), perlmod(1),
perlmodlib(1), perl(1).

VERSION $Id: SelfHelp.pm,v 1.3 2000/08/19 01:04:22 kiesling Exp $ =cut
======================================================================

   @ISA=qw{Exporter}; use vars qw( @ISA @EXPORT @EXPORT_OK );
@EXPORT=qw(self_help);

   use Tk; use Tk::MainWindow; use Tk::Button;

   my $defaulttextfont="*-courier-medium-r-*-*-12-*"; my
$menufont="*-helvetica-medium-r-*-*-12-*";

   sub self_help {     my ($appfilename) = @_;     my $help_text;     my
$helpwindow;     my $textwidget;

     open( HELP, ("pod2text < $appfilename |") ) or $help_text =
     "Unable to process help text for $appfilename.";
     while (<HELP>) {
     	$help_text .= $_;
     }
     close( HELP );

     $helpwindow = new MainWindow( -title => "$appfilename Help" );
     my $textframe = $helpwindow -> Frame( -container => 0,
     					  -borderwidth => 1 ) -> pack;
     my $buttonframe = $helpwindow -> Frame( -container => 0,
     					  -borderwidth => 1 ) -> pack;
     $textwidget = $textframe
     	-> Scrolled( 'Text',
     		     -font => $defaulttextfont,
     		     -scrollbars => 'e' ) -> pack( -fill => 'both',
     						   -expand => 1 );
     $textwidget -> insert( 'end', $help_text );

     $buttonframe -> Button( -text => 'Close',
     			    -font => $menufont,
     			    -command => sub{$helpwindow -> DESTROY} ) ->
     				pack;
     }

   1;

Manage tied references to symbol table hash   entries.
******************************************************

NAME
====

     Tk::Symbolref.pm -- Manage tied references to symbol table hash
     entries.

SYNOPSIS
========

     use Lib::Module;
     use Lib::ModuleSym;
     use Lib::SymbolRef;

     tie *Package::symbol, 'Lib::SymbolRef,

DESCRIPTION
===========

   Much room for further expansion using these methods.

REVISION
========

   $Id: SymbolRef.pm,v 0.51 2000/09/18 20:23:59 kiesling Exp kiesling $

SEE ALSO
========

   The manual pages for Lib::Module(3), Tk::Browser(3), perltie(1).

User authentication for libweb applications
*******************************************

NAME
====

   LibWeb::Admin - User authentication for libweb applications

SUPPORTED PLATFORMS
===================

BSD, Linux, Solaris and Windows.
REQUIRE
=======

   * LibWeb::Database

ISA
===

   * LibWeb::Session

SYNOPSIS
========

     use LibWeb::Admin;
     my $a = LibWeb::Admin->new();

     $a->login( $user_name, $guess_password );

     ...

     my ($user_name,$uid) = $a->get_user();

     ...

     $a->logout();

     ...

     $a->is_logout();

ABSTRACT
========

   This class manages user authentication for web applications written
based on the interfaces and frameworks defined in LibWeb, a Perl
library/toolkit for programming web applications.  It is responsible for
managing user login, logout and new sign-up.  Therefore you may want to
use this module in the login script for your site.

   The current version of LibWeb::Admin.pm is available at

     http://libweb.sourceforge.net

   Several LibWeb applications (LEAPs) have be written, released and are
available at

     http://leaps.sourceforge.net

TYPOGRAPHICAL CONVENTIONS AND TERMINOLOGY
=========================================

   Variables in all-caps (e.g. MAX_LOGIN_ATTEMPT_ALLOWED) are those
variables set through LibWeb's rc file.  Please read LibWeb/Core,
for more information.  `Sanitize' means escaping any illegal
character possibly entered by user in a HTML form.  This will make Perl's
taint mode happy and more importantly make your site more secure.
Definition for illegal characters is given in LibWeb/Core.
All `error/help messages' mentioned can be found at
LibWeb/HTML/Error, and they can be customized by ISA
(making a sub-class of) LibWeb::HTML::Default.  Please see
LibWeb/HTML/Default, for details.

DESCRIPTION
===========

HANDLING USER LOGIN
-------------------

   Fetch the user name and password from a HTML form and pass them to
login(),

     $a->login( $user_name, $guess );

   If the password is correct and the user name exists in the database,
this will send an authentication cookie to the client web browser and
return 1; send an alert e-mail to the site administrator (*ADMIN_EMAIL*)
and print out an error message and exit otherwise.

HANDLING USER SESSION AFTER LOGIN
---------------------------------

   At the top of every web application that requires user authentication,

     my ($user_name,$uid) = $a->get_user();

   to retrieve user name and user ID from cookie.  This will send an alert
e-mail to the site administrator (*ADMIN_EMAIL*) and redirect the user to
the login page (*LM_IN*) if no authentication cookie is found or it has
been tampered with.  I would recommend you use LibWeb::Session instead
which is specifically designed for that purpose and therefore runs a
little bit faster,

     use LibWeb::Session;
     my $s = new LibWeb::Session();

     my ($user_name,$uid) = $s->get_user();

   LibWeb::Admin should be used by login scripts; whereas LibWeb::Session
should be used by any web applications once the user has logged in.  Read
LibWeb/Session, for details.

   To update the database (set the login indicator to *LOGIN_INDICATOR*)
when the user is first logged in,

     my ($user_name,$uid)
         = $s->get_user( -is_update_db => 1 );

   This is probably done in `my control panel' or `my page' of some sorts
which is the first script invoked after password authentication.

HANDLING USER LOGOUT
--------------------

     $a->logout();

   This will check to see if the user is logged in.  Send an alert e-mail
to the site administrator (*ADMIN_EMAIL*) and redirect user to the login
page (*LM_IN*) if the remote user is not logged in or has no
authentication cookie.  Otherwise, this will flush *NUM_LOGIN_ATTEMPT* to
0 in database (indicating that the user has logged out).  This will also
send de-authentication cookies to nullify all authentication cookies on
client web browser.  Return 1 upon success.

PARANOIA
--------

     $a->is_logout();

   Check to see if authentication cookies are indeed removed from the
client Web browser and return true (1).  Otherwise, print an error
message, send an alert e-mail to *ADMIN_EMAIL* and exit the program.

ADDING NEW USER TO DATABASE
---------------------------

     $a->add_new_user(
                      -user => 'user_name',
                      -password => 'password',
                      -email => 'user_email'
                     );

   Print out an error message and abort if,

   * `user_name' contains illegal characters other than `_' and `-' or

   * `user_name' is already registered or

   * `user_email' does not conform to the standard format defined in
     LibWeb/Core, or

   * `user_email' is already registered if *IS_ALLOW_MULTI_REGISTRATION*
     is set to 0.

   If the parameters pass all the tests, this will encrypt the password,
add that with the user name to the database, notify the site administrator
(*ADMIN_EMAIL*) by e-mail if *IS_NOTIFY_ADMIN_WHEN_ADDED_NEW_USER* is set
to 1 and log that event in *FATAL_LOG* if *FATAL_LOG* is defined.  Return
the registered user_name upon success.

AUTHORS
=======

Colin Kong (colin.kong@toronto.edu)
CREDITS
=======

BUGS
====

SEE ALSO
========

   See LibWeb/Core, LibWeb/CGI,
LibWeb/Crypt, LibWeb/Database,
LibWeb/Digest, LibWeb/HTML/Default,
see LibWeb/Session,
LibWeb/Themes/Default.

Extra cgi supports for libweb applications
******************************************

NAME
====

   LibWeb::CGI - Extra cgi supports for libweb applications

SUPPORTED PLATFORMS
===================

BSD, Linux, Solaris and Windows.
REQUIRE
=======

   * LibWeb::Core

ISA
===

   * CGI

   * LibWeb::Class

SYNOPSIS
========

     use LibWeb::CGI;
     my $q = new LibWeb::CGI();

     my $parameter = $q->parameter('cgi_param_to_fetch');

     my $param = $q->param('cgi_param_to_fetch');

     print $q->header();

     $q->redirect( -url => '/cgi-bin/logout.cgi', -cookie => 'auth=0' );

     $q->send_cookie( [$cookie1, $cookie2] );

     $q->sanitize( -text => $user_input, -allow => ['_', '-'] );

     $q->fatal(
                -msg => 'Password not entered.',
                -alertMsg => '$user did not enter password!',
                -helpMsg => \('Please hit back and edit.')
              );

ABSTRACT
========

   This class ISA the vanilla CGI.pm to provide some additional features.
It is still considered to be experimental but used internally by
LibWeb::Session and LibWeb::Admin.

   The current version of LibWeb::CGI is available at

     http://libweb.sourceforge.net

   Several LibWeb applications (LEAPs) have be written, released and are
available at

     http://leaps.sourceforge.net

TYPOGRAPHICAL CONVENTIONS AND TERMINOLOGY
=========================================

   Variables in all-caps (e.g. MAX_LOGIN_ATTEMPT_ALLOWED) are those
variables set through LibWeb's rc file.  Please read LibWeb/Core,
for more information.  `Sanitize' means escaping any illegal
character possibly entered by user in a HTML form.  This will make Perl's
taint mode happy and more importantly make your site more secure.
Definition for illegal characters is given in LibWeb/Core.
All `error/help messages' mentioned can be found at
LibWeb/HTML/Error, and they can be customized by ISA
(making a sub-class of) LibWeb::HTML::Default.  Please see
LibWeb/HTML/Default, for details.  Method's
parameters in square brackets means optional.

DESCRIPTION
===========

METHODS
-------

   new()

   args: [ -post_max=>, -disable_uploads=>, -auto_escape=> ]

   * `-post_max' is the ceiling on the size of POSTings, in bytes.  The
     default for LibWeb::CGI is 100 Kilobytes.

   * `-disable_uploads', if non-zero, will disable file uploads completely
     which is the default for LibWeb::CGI.

   * `-auto_escape' determines whether the text and labels that you
     provide for form elements are escaped according to HTML rules.
     Non-zero value will enable auto escape, and undef will disable auto
     escape (default for LibWeb::CGI).

   header()

   If you provide parameter to that method, it will delegate to the
vanilla CGI's header(); otherwise, it will print out "Content-Type:
text/html$CRLF$CRLF" immediately (faster?).  $CRLF will depend on the
machine you are running LibWeb and LibWeb will determine it automatically.

   *parameter()*

     my $param = $q->parameter('cgi_parameter_to_fetch');

   * `cgi_parameter_to_fetch' is the parameter passed by either `GET' or
     `POST' via a HTML form.

   * If `cgi_parameter_to_fetch' is a mandatory form value (one without `.'
     as prefix in the parameter's name) and it is null, it will print out
     an error message, abort the program and send the site administrator an
     alert e-mail.  It is intended so save the effort to check whether the
     user has entered something for mandatory HTML form values.  To use
     this nice feature, you name mandatory form value without `.' as
     prefix, for example,

          <input type="text" name="email">

     For non-mandatory form values, you name them by attaching `.' as a
     prefix to skip the test, for example,

          <input type="text" name=".salary_range">

     If you find this not really helpful, you should use the vanilla
     param() which is totally unaltered in LibWeb::CGI.  For example,

          my $param = $q->param('param_to_fetch');

     and LibWeb::CGI will delegate the call to the vanilla CGI's param().
     Another reason to use parameter() (or not to use it) is that it
     automatically checks for any possible denial of service attack by
     calling CGI::cgi_error().  If the POST is too large, it will print out
     an error message and send an e-mail alerting the site administrator.
     CGI::cgi_error() is available since CGI 2.47 but seems to be
     disappeared in new release of CGI.pm 3.01 alpha (24/04/2000).

   *redirect()*

   Params:

     -url=> [, -cookie=> ]

   This will redirect the client web browser to the specified url and send
it the cookie specified.  An example of a cookie to pass to that method
will be,

     $cookie1 = 'auth1=0; path=/; expires=Thu, 01-Jan-1970 00:00:01 GMT';
     $cookie2 = 'auth2=0; path=/; expires=Thu, 01-Jan-1970 00:00:01 GMT';

     $q->redirect(
                  -url => '/logged_out.htm',
                  -cookie => [ $cookie1, $cookie2 ]
                 );

   For `-cookie', you can pass either a scalar or an ARRAY reference.
This method will eventually delegate to the vanilla CGI's redirect().  Why
bother doing this is because the vanilla CGI's redirect() does not
guarantee to work if you pass relative url; whereas
LibWeb::CGI::redirect() guarantees that partial url will still work.

   *send_cookie()*

   This delegates to LibWeb::Core::send_cookie().  See LibWeb/Core.

   *fatal()*

   This delegates to LibWeb::Core::fatal().  See LibWeb/Core.

   *sanitize()*

   This delegates to LibWeb::Core::sanitize().  See LibWeb/Core.

AUTHORS
=======

Colin Kong (colin.kong@toronto.edu)
CREDITS
=======

Lincoln Stein (lstein@cshl.org)
BUGS
====

Bug number 1
------------

   When you delegate subroutine calls within a cgi script,
$q->param(_variable_) or $q->parameter(_variable_) may not give you the
value of `_variable_' even you have passed a value for that variable in a
HTML form.  I do not know why.  My two workarounds,

   * Instantiate another CGI or LibWeb::CGI object within the subroutine
     where you want to fetch the parameter and use that object to call
     param() or `parameter()', or

   * Initiate all CGI variables and/or fetch all CGI parameters at the
     beginning of your script.

Bug number 2
------------

   new()

   args: [ -post_max=>, -disable_uploads=>, -auto_escape=> ]

   The `-auto_escape' doesn't seems to work as expected.  Hopefully it
will be resolved after I get a better understanding of how auto escape
works in the vanilla CGI.

Bug number 3
------------

   There is no selfloaded method in LibWeb::CGI since whenever I try to
put "use SelfLoader;" in this module, it just doesn't work well with the
vanilla CGI.  This has to be figured out.

   Miscellaneous OO issues with the vanilla CGI have yet to be resolved.

SEE ALSO
========

   See CGI, LibWeb/Class, LibWeb/Core,
see LibWeb/HTML/Default,
LibWeb/HTML/Error.

A base class for libweb modules
*******************************

NAME
====

   LibWeb::Class - A base class for libweb modules

SUPPORTED PLATFORMS
===================

BSD, Linux, Solaris and Windows.
REQUIRE
=======

   * perl 5.004

ISA
===

   * None

SYNOPSIS
========

     require LibWeb::Class;
     @ISA = qw(LibWeb::Class);

ABSTRACT
========

   This class contains common object-oriented methods inherited by all
LibWeb modules.  It is intended to be ISA by LibWeb modules and extensions
and not used by client codes outside LibWeb.

   The current version of LibWeb::Class is available at

     http://libweb.sourceforge.net

   Several LibWeb applications (LEAPs) have be written, released and are
available at

     http://leaps.sourceforge.net

DESCRIPTION
===========

METHODS
-------

rearrange()
   This is not really OO related but makes LibWeb's API look sexy.  This
is stolen from CGI.pm and modified.  It allows smart rearrangement of
parameters for named parameter calling.  This does the rearrangement if
the first parameter begins with a `-'.  For example,

     sub your_class_method {

     my $self = shift;
     my ($parameter1, $parameter2, $parameter3);
       = $self->rearrange( ['PARA1', 'PARA2', 'PARA3'], @_ );

     ....

     }

   and your method will be called as

     use your_class;
     my $object = new your_class();

     $object->your_class_method(
                                 -para1 => $para1,
                                 -para2 => $para2,
                                 -para3 => $para3
                               );

AUTHORS
=======

Colin Kong (colin.kong@toronto.edu)
CREDITS
=======

Lincoln Stein (lstein@cshl.org)
BUGS
====

SEE ALSO
========

The core class for libweb modules
*********************************

NAME
====

   LibWeb::Core - The core class for libweb modules

SUPPORTED PLATFORMS
===================

BSD, Linux, Solaris and Windows.
REQUIRE
=======

   * LibWeb::Crypt

   * LibWeb::HTML::Error

   * Mail::Sendmail

ISA
===

   * LibWeb::Class

SYNOPSIS
========

     require LibWeb::Core;
     @ISA = qw(LibWeb::Core);

ABSTRACT
========

   This class is responsible for reading the LibWeb's rc file, handling
portability issues, printing and logging error and debug messages and
sending alert e-mail to the site administrator should error occur.  You
are not supposed to use or ISA this class directly.  It is ISAed
internally by other modules in LibWeb, e.g. LibWeb::Admin, LibWeb::CGI,
LibWeb::Database, LibWeb::HTML::Default and LibWeb::Themes::Default.  You
should call the methods presented in this man page through one of those
sub-classes.

   The current version of LibWeb::Core is available at

     http://libweb.sourceforge.net

   Several LibWeb applications (LEAPs) have be written, released and are
available at

     http://leaps.sourceforge.net

TYPOGRAPHICAL CONVENTIONS AND TERMINOLOGY
=========================================

   Variables in all-caps (e.g. ADMIN_EMAIL) are those variables set
through LibWeb's rc file.  `Sanitize' means escaping any illegal character
possibly entered by user in a HTML form.  This will make Perl's taint mode
happy and more importantly make your site more secure.  All `error/help
messages' mentioned can be found at LibWeb/HTML/Error,
and they can be customized by ISA (making a sub-class
of) LibWeb::HTML::Default.  Please see LibWeb/HTML/Default,
for details.  Method's parameters in square brackets
means optional.

DESCRIPTION
===========

READING THE LIBWEB RC FILE
--------------------------

   You should place your LibWeb rc (config) file outside your WWW document
root.  The following shows how a cgi script using LibWeb will typically
look like,

     use LibWeb::Session;
     use LibWeb::Database;
     use LibWeb::CGI;
     use LibWeb::Themes::Default;
     use LibWeb::HTML::Default;

     my $rc_file = '/home/me/dot_lwrc';

     my $html = new LibWeb::HTML::Default($rc_file);
     my $themes = new LibWeb::Themes::Default();
     my $session = new LibWeb::Session();
     my $db = new LibWeb::Database();
     my $q = new LibWeb::CGI();

     ...

   It is recommended that you pass the absolute path of LibWeb's rc file
to LibWeb::HTML::Default and make it the *first* LibWeb object
initialized.  This will ensure other LibWeb objects can "see" the rc file
and be initialized properly.

   However, LibWeb::Admin, LibWeb::CGI, LibWeb::Database,
LibWeb::Themes::Default, and LibWeb::Session all can take $rc_file as the
argument to their new() methods (constructor).  You will never need this
unless you do not want LibWeb::HTML::Default to manage HTML page display
for you.

   You still do *not* need this even if you have ISAed
LibWeb::HTML::Default.  The reason to ISA LibWeb::HTML::Default is to
customize the normal and error HTML page display and error messages built
into LibWeb.  If you have ISAed LibWeb::HTML::Default, you just have to
replace the following two lines,

     use LibWeb::HTML::Default;
     my $html = new LibWeb::HTML::Default($rc_file);

   with

     use MyHTML;
     my $html = new MyHTML($rc_file);

   where MyHTML is your class which ISAs LibWeb::HTML::Default.  Please
read LibWeb/HTML/Default, for details.  A
sample rc file has been included in the ./eg directory.  If you could not
find it, please go to http:://libweb.sourceforge.net and download a
standard LibWeb distribution.

SANITY - REMOVING ILLEGAL CHARACTERS ENTERED BY USERS
-----------------------------------------------------

   LibWeb::Core provides *sanitize()* method to escape illegal characters
entered by users in HTML forms.  LibWeb's definition of illegal characters
is as follows,

     `~!@#$%^&*,.:;?"'<>{}[]()\|/-_+=\a\n\r\t\f\e\b

   *sanitize()* also has the ability to escape HTML tags and detect dirty
e-mail addresses (format).  Please see below for details on *sanitize()*.

METHODS
-------

   new()

   Params:

   class [, *rc_file*, *error_object*]

   Usage:

     No, you do not call LibWeb::Core::new()
     directly in client codes.

   * class is the class/package name of this package, be it a string or a
     reference.

   * *rc_file* is the absolute path to the rc file for LibWeb.

   * *error_object* is a reference to a perl object for printing out
     error/help message to users should error occur.

   *debug_print()*

   Usage:

     debug_print('you debug message');

   * If `DEBUG' == 1, print *debug_msg* and return undef.  Do nothing
     otherwise.

   *fatal()*

   Params:

     -msg [, -input=>, -helpMsg=>, -alertMsg=>,
             -isAlert=>, -isDisplay=>, -cookie=> ]

   Usage:

     fatal(
            -msg => 'You have not entered your password.',
            -alertMsg => "$user did not enter password!",
            -helpMsg => \('Please hit back and edit.')
          );

     fatal(
            -alertMsg =>
            'Possible denial of service attack detected!',
            -isDisplay => 0
          );

   Pre:

   * `-msg', `-input', `-alertMsg' must be scalar and `-helpMsg' must be a
     SCALAR reference.  `-cookie' can be a scalar or an ARRAY reference to
     scalars,

   * `-input' is the user input that triggers this fatal error,

   * `-helpMsg' is any instruction to guide the remote user, which can be
     HTML,

   Post:

   * Send `-cookie', print `-msg', `-input' and `-helpMsg' to the viewing
     web browser and abort the current running program if `-isDisplay' is
     defined and is equal to 1 (default),

   * if `-isAlert' is defined and is equal to 1 (default),

        * append `-alertMsg' to `FATAL_LOG' if `FATAL_LOG' is defined,

        * send an alert e-mail, with `-alertMsg' as the message body, to
          `ADMIN_EMAIL' if `IS_MAIL_DEBUG_TO_ADMIN' is 1, and

        * print `-alertMsg' to the viewing web browser if `DEBUG' is 1.

   *sanitize()*: sanitizes Web client inputs

   Params:

     -text=>'plain_text' || -html=>'html_text' ||
     -email=>'email_here' [, -allow=>[characters allowed] ]

   Usage:

     $sanitized_input =
         sanitize( -text => $user_input, -allow => ['-', '_'] );

     @sanitized_emails =
         sanitize( -email => [$email1,$email2, $email3] );

     $sanitized_input =
         sanitize( -html => $user_input );

   Pre:

   * For `-text', `-html' and `-email', each must be a scalar or an ARRAY
     reference to scalars,

   * `-allow' is an ARRAY reference to special characters allowed.  It's
     effective only when you use it with `-text'.

   Post:

   * `-text': sanitize text by escaping all illegal characters
     (`~!@#$%^&*,.:;?"'<>{}[]()\|/-_+=\a\n\r\t\f\e\b),

   * `-html': escape all html <> tags,

   * `-email': sanitize email addresses.  Print an error message and abort
     the current running program if email is dirty ( $email !~
     m:(\w{1}[\w-.]*)\@([\w-.]+): )

   * array is returned if want array,

   * this can only process one type of sanity at a time (i.e. per method
     call).

   *send_cookie()* - this one is here due to inheritance (backward?)
issues not yet resolved with LibWeb::CGI.

   Usage:

     my $cookie1 =
       'auth1=0; path=/; expires=Thu, 01-Jan-1970 00:00:01 GMT';
     my $cookie2 =
       'cook2=value; path=/';

     send_cookie( $cookie1 ); # or

     send_cookie( [$cookie1, $cookie2] );

   Pre:

   * Parameter must be either a scalar or an ARRAY reference to scalars,

   * no other HTTP headers should be sent before this in a single CGI
     session.

   Post:

   * Send the cookie to client Web browser.

   *send_mail()*

   Params:

     -to=>, -from=>, -subject=>, -msg=>
     [, -replyTo=>, -cc=>, -bcc=>, -smtp=> ]

   Pre:

   * `-msg' must be a SCALAR reference and others must be scalars.

   Post:

   * Send an e-mail to the recipients specified.  It will try to use
     Mail::Sendmail and then the primitive unix sendmail if the former
     fails.

AUTHORS
=======

Colin Kong (colin.kong@toronto.edu)
CREDITS
=======

BUGS
====

SEE ALSO
========

   See LibWeb/Admin, LibWeb/Class,
LibWeb/Core, LibWeb/CGI,
LibWeb/Crypt, LibWeb/Database,
LibWeb/File, LibWeb/HTML/Error,
LibWeb/HTML/Site, LibWeb/HTML/Default,
see LibWeb/Session,
LibWeb/Themes/Default, LibWeb/Time.

Encryption for libweb applications
**********************************

NAME
====

   LibWeb::Crypt - Encryption for libweb applications

SUPPORTED PLATFORMS
===================

BSD, Linux, Solaris and Windows.
REQUIRE
=======

   * Crypt::CBC

   * Crypt::Blowfish (recommended), Crypt::DES or Crypt::IDEA

ISA
===

   * LibWeb::Class

SYNOPSIS
========

     use LibWeb::Crypt;
     my $c = new LibWeb::Crypt();

     my $cipher =
         $c->encrypt_cipher(
     			 -data => $plain_text,
     			 -key => $key,
     			 -algorithm => 'Crypt::Blowfish',
     			 -format => 'hex'
     			);

     my $plain_text =
         $c->decrypt_cipher(
     			 -cipher => $cipher,
     			 -key => $key,
     			 -algorithm => 'Crypt::Blowfish',
     			 -format => 'hex'
     			);

     my $encrypted_pass =
         $c->encrypt_password('password_in_plain_text');

ABSTRACT
========

   This class provides methods to

   * encrypt data of arbitrary length into cipher (binary or hex) by using
     the algorithm provided by Crypt::Blowfish, Crypt::DES or Crypt::IDEA,
     and chained by using Crypt::CBC,

   * decrypt ciphers generated by this class,

   * encrypt plain text password by using the perl's crypt() routine with
     randomly chosen salt.

   The current version of LibWeb::Crypt is available at

     http://libweb.sourceforge.net

   Several LibWeb applications (LEAPs) have be written, released and are
available at

     http://leaps.sourceforge.net

DESCRIPTION
===========

METHODS
-------

   *encrypt_cipher()*

   Params:

     -data=>, -key=>, -algorithm=>, -format=>

   Pre:

   * `-data' is the data to be encrypted as cipher,

   * `-key' is the private key such the same key is needed to decrypt the
     cipher (sorry, I do not have a rigorous definition for that right
     now),

   * `-algorithm' must be 'Crypt::Blowfish', 'Crypt::DES' or 'Crypt::IDEA',

   * `-format' is the format of the cipher, which must be either 'binary'
     or 'hex'.

   Post:

   * Encrypt `-data' and return the cipher.

   Note: this makes use of the Crypt::CBC module and therefore can accept
data of arbitrary length.

   *decrypt_cipher()*

   Params:

     -cipher=>, -key=>, -algorithm=>, -format=>

   Pre:

   * `-cipher' is the cipher to be decrypted,

   * `-key' is the private key such that it is the same key used to
     encrypt the original data of `-cipher' (sorry, I do not have a
     rigorous definition for that right now),

   * `-algorithm' must be 'Crypt::Blowfish', 'Crypt::DES' or 'Crypt::IDEA'
     and it must match the algorithm used when preparing the cipher,

   * `-format' is the format of the cipher, which must be either 'binary'
     or 'hex'.

   Post:

   * Decrypt `-cipher' and return the original data.

   *encrypt_password()*

   Usage:

     my $encrypted_password =
         $crypt->encrypt_password($password_in_plain_text);

   Encrypts the parameter (usually a password) and returns a 13-character
long string using the perl's crypt() routine and randomly chosen salt.

AUTHORS
=======

Colin Kong (colin.kong@toronto.edu)
CREDITS
=======

Lincoln Stein (lstein@cshl.org)
BUGS
====

SEE ALSO
========

   See Digest/HMAC, Digest/SHA1,
Digest/MD5, Crypt/CBC,
Crypt/Blowfish, Crypt/DES,
Crypt/IDEA, LibWeb/Admin,
LibWeb/Digest, LibWeb/Session.

A generic database driver for libweb applications
*************************************************

NAME
====

   LibWeb::Database - A generic database driver for libweb applications

SUPPORTED PLATFORMS
===================

BSD, Linux, Solaris and Windows.
REQUIRE
=======

   * DBI

ISA
===

   * LibWeb::Core

SYNOPSIS
========

     use LibWeb::Database;
     my $db = new LibWeb::Database();

     my ($sql, $user, $host, $fetch, $result);
     $sql = "select USER_NAME, USER_HOST ".
            "from USER_TABLE ".
            "where USER_LOGIN_STATUS = ".
            "LOGIN_INDICATOR";

     $fetch = $db->query(
                          -sql => $sql,
                          -bind_cols => [\$user, \$host]
                        );

     while ( &$fetch ) {
         $result .= "$user $host <BR>\n";
     }

     $db->done();

     print "Content-Type: text/html\n\n";
     print "<P> The following users have logged in: $result";

ABSTRACT
========

   As long as you have the proper DBD installed for your database, you can
use this class to interact with your database in your LibWeb applications.

   The current version of LibWeb::Database is available at

     http://libweb.sourceforge.net

   Several LibWeb applications (LEAPs) have be written, released and are
available at

     http://leaps.sourceforge.net

TYPOGRAPHICAL CONVENTIONS AND TERMINOLOGY
=========================================

   Variables in all-caps (e.g. USER_TABLE) are those variables set through
LibWeb's rc file.  Please read LibWeb/Core, for more
information.  Method's parameters in square brackets means optional.

DESCRIPTION
===========

   *do()*

   Params:

     -sql =>

   Pre:

   * `-sql' is a valid sql statement.

   Post:

   * Return the number of rows affected by the SQL statement, `-sql'.

   query()

   Params:

     -sql=>, -bind_cols=> [, -want_hash=> ]

   Pre:

   * `-sql' is the sql statement to perform the query,

   * `-bind_cols' is an ARRAY reference to SCALAR references to fields to
     be bound in the table specified in `-sql',

   * `-want_hash' indicates whether the returning function (a reference)
     is a reference to DBI's fetchrow_hashref() or fetchrow_arrayref().

   Post:

   * Returns a reference to a fetching function based on `-sql'.  A
     reference to DBI's fetchrow_arrayref() is returned if `-want_hash' is
     not defined; otherwise a reference to DBI's fetchrow_hashref() is
     returned.

   finish()

   Finish a statement execution.

   disconnect()

   Disconnect the current database session.

   *done()*

   Finish a statement execution and disconnect the current database
session.

AUTHORS
=======

Colin Kong (colin.kong@toronto.edu)
CREDITS
=======

BUGS
====

SEE ALSO
========

   `DBI' in this node, see LibWeb/Core.

Mysql database API for libweb applications
******************************************

NAME
====

   LibWeb::Database::Mysql - Mysql database API for libweb applications

SUPPORTED PLATFORMS
===================

BSD, Linux, Solaris and Windows.
REQUIRE
=======

   * No non-standard Perl's library is required.

ISA
===

   * LibWeb::Database

SYNOPSIS
========

     use LibWeb::Database::Mysql;
     my $db = new LibWeb::Database::Mysql();

     my ($where, $count);

     $where = 'LOGIN_STATUS = LOGGED_IN';
     $count = $db->get_count(
                              -table => USER_TABLE,
                              -where => $where
                            );

     print "Content-Type: text/html\n\n";
     print "$count users have logged in.";

ABSTRACT
========

   This class provides enhanced support to MySQL database interaction in
you LibWeb applications.  This class also ISAs LibWeb::Database so you can
use all the methods provided in LibWeb::Database via objects created from
this class.  See LibWeb/Database.  This module is
still in the stage of planning as you can tell from the number of methods
available.

   The current version of LibWeb::Database::Mysql is available at

     http://libweb.sourceforge.net

   Several LibWeb applications (LEAPs) have be written, released and are
available at

     http://leaps.sourceforge.net

TYPOGRAPHICAL CONVENTIONS AND TERMINOLOGY
=========================================

   Variables in all-caps (e.g. USER_TABLE) are those variables set through
LibWeb's rc file.  Please read LibWeb/Core, for more
information.  Method's parameters in square brackets means optional.

DESCRIPTION
===========

METHODS
-------

   *get_count()*

   Params:

     -table =>, -where =>

   Pre:

   * `-table' is a scalar indicating a database table's name,

   * `-where' is a scalar describing the `where' phrase of a SQL query.

   Post:

   * Return the number of counts satisfying the criteria specified in the
     `-where' parameter.

AUTHORS
=======

Colin Kong (colin.kong@toronto.edu)
CREDITS
=======

BUGS
====

SEE ALSO
========

   See LibWeb/Database.

Digest generation for libweb applications
*****************************************

NAME
====

   LibWeb::Digest - Digest generation for libweb applications

SUPPORTED PLATFORMS
===================

BSD, Linux, Solaris and Windows.
REQUIRE
=======

   * Digest::HMAC

   * Digest::SHA1

   * Digest::MD5

ISA
===

   * LibWeb::Class

SYNOPSIS
========

     use LibWeb::Digest;
     my $d = new LibWeb::Digest();

     my $mac = $d->generate_MAC(
     			     -data => $data,
     			     -key => $key,
     			     -algorithm => 'Digest::SHA1',
     			     -format => 'b64'
     			    );

     my $digest
         = $d->generate_digest(
     			    -data => $data,
     			    -key => $key,
     			    -algorithm => 'Digest::MD5',
     			    -format => 'b64'
     			   );

ABSTRACT
========

   This class provides methods to

   * Generate message authenticity check (MAC) code which is mostly used in
     authentication cookies sent to browsers, and

   * generate digest code (binary, hex or B64) by using the algorithm
     provided by either Digest::MD5 or Digest::SHA1,

   The current version of LibWeb::Digest is available at

     http://libweb.sourceforge.net

   Several LibWeb applications (LEAPs) have be written, released and are
available at

     http://leaps.sourceforge.net

DESCRIPTION
===========

GENERATING A MAC FOR USER/SESSION AUTHENTICATION
------------------------------------------------

   The following discussion on MAC is extracted from a WWW security FAQ
written by Lincoln Stein,

     http://www.w3.org/Security/Faq/wwwsf7.html#Q66

   "If possible, cookies should contain information that allows the system
to verify that the person using them is authorized to do so. A popular
scheme is to include the following information in cookies:

     1.the session ID or authorization information
     2.the time and date the cookie was issued
     3.an expiration time
     4.the IP address of the browser the cookie was issued to
     5.a message authenticity check (MAC) code

   By incorporating an expiration date and time into the cookie, system
designers can limit the potential damage that a hijacked cookie can do. If
the cookie is intercepted, it can only be used for a finite time before it
becomes invalid.  The idea of including the browser's IP address into the
cookie is that the cookie will only be accepted if the stored IP address
matches the IP address of the browser submitting it.  This makes it
difficult for an interloper to hijack the cookie, because it is hard
(although not impossible) to spoof an IP address.

   The MAC code is there to ensure that none of the fields of the cookie
have been tampered with.  There are many ways to compute a MAC, most of
which rely on one-way hash algorithms such as MD5 or SHA to create a
unique fingerprint for the data within the cookie. Here's a simple but
relatively secure technique that uses MD5:

     MAC = MD5("secret key " +
                MD5("session ID" + "issue date" +
                    "expiration time" + "IP address" +
                    "secret key")
               )

   This algorithm first performs a string concatenation of all the data
fields in the cookie, then adds to it a secret string known only to the
Web server. The whole is then passed to the MD5 function to create a
unique hash. This value is again concatenated with the secret key, and the
whole thing is rehashed. (The second round of MD5 hashing is necessary in
order to avoid an attack in which additional data is appended to the end
of the cookie and a new hash recalculated by the attacker.)

   This hash value is now incorporated into the cookie data. Later, when
the cookie is returned to the server, the software should verify that the
cookie hasn't expired and is being returned by the proper IP address. Then
it should regenerate the MAC from the data fields, and compare that to the
MAC in the cookie. If they match, there's little chance that the cookie
has been tampered with." - Lincoln Stein.

   In fact, this is the technique used by LibWeb to handle user/session
authentication via cookies.  LibWeb::Admin and LibWeb::Session use
LibWeb::Digest::generate_MAC() to generate MACs.
LibWeb::Digest::generate_MAC() uses Digest::HMAC and uses either
Digest::MD5 or Digest::SHA1 as the digest algorithm.

METHODS
-------

   *generate_MAC()*

   Params:

     -data=>, -key=>, -algorithm=>, -format=>

   Pre:

   * `-data' is the data from which the MAC is to be generated,

   * `-key' is the private key such that the MAC generated is unique to
     that key (sorry, I do not have a rigorous definition for that right
     now),

   * `-algorithm' must be either 'Digest::MD5' or 'Digest::SHA1',

   * `-format' is the format of the generated MAC, which must be 'binary',
     'hex' or 'b64'.

   Post:

   * Generate a MAC and return it.

   *generate_digest()*

   Params:

     -data=>, -key=>, -algorithm=>, -format=>

   Pre:

   * `-data' is the data from which the digest is to be generated,

   * `-key' is the private key such that the digest generated is unique to
     that key (sorry, I do not have a rigorous definition for that right
     now),

   * `-algorithm' must be either 'Digest::MD5' or 'Digest::SHA1',

   * `-format' is the format of the digest, which must be 'binary', 'hex'
     or 'b64'.

   Post:

   * Generate a digest and return it.

AUTHORS
=======

Colin Kong (colin.kong@toronto.edu)
CREDITS
=======

Lincoln Stein (lstein@cshl.org)
BUGS
====

SEE ALSO
========

   See Digest/HMAC, Digest/SHA1,
Digest/MD5, Crypt/CBC,
Crypt/Blowfish, Crypt/DES,
Crypt/IDEA, LibWeb/Admin,
LibWeb/Crypt, LibWeb/Session.

File manipulations for libweb applications
******************************************

NAME
====

   LibWeb::File - File manipulations for libweb applications

SUPPORTED PLATFORMS
===================

BSD, Linux, Solaris and Windows.
REQUIRE
=======

   * No non-standard Perl's library is required.

ISA
===

   * LibWeb::Class

SYNOPSIS
========

     use LibWeb::File;
     my $fh = new LibWeb::File();

     $lines = $fh->read_lines_from_file( -file => '/home/me/file1' );

     $fh->write_lines_to_file(
                               -file => '/home/me/file2',
                               -lines => $lines
                             );

ABSTRACT
========

   This class provides several methods to manipulate text files.

   The current version of LibWe LibWeb::File is available at

     http://libweb.sourceforge.net

   Several LibWeb applications (LEAPs) have be written, released and are
available at

     http://leaps.sourceforge.net

DESCRIPTION
===========

METHODS
-------

   *read_lines_from_file()*

   Params:

     -file =>

   Open, read all lines, close `-file' and return the lines in an ARRAY
reference.

   *write_lines_to_file()*

   Params:

     -file =>, -lines =>

   Pre:

   * `-lines' is an ARRAY reference to lines which are scalars.

   Post:

   * Overwrite `-file' with the lines.

AUTHORS
=======

Colin Kong (colin.kong@toronto.edu)
CREDITS
=======

BUGS
====

SEE ALSO
========

   See LibWeb/Class.

HTML display for libweb applications
************************************

NAME
====

   LibWeb:: - HTML display for libweb applications

SUPPORTED PLATFORMS
===================

BSD, Linux, Solaris and Windows.
REQUIRE
=======

   * No non-standard Perl's library is required.

ISA
===

   * LibWeb::HTML::Standard

   * LibWeb::HTML::Error

   * LibWeb::Themes::Default

SYNOPSIS
========

     use LibWeb::HTML::Default;

     my $rc_file = '/absolute/path/to/dot_lwrc';
     my $html = new LibWeb::HTML::Default($rc_file);

     $html->fatal(
                   -msg =>
                     'You have not typed in the stock symbol.',
                   -alertMsg =>
                     'Try to view stock quotes without a symbol.',
                   -helpMsg =>
                     $html->hit_back_and_edit()
                 )
         unless ($stock_symbol);

     my $display =
         $html->display(
                         -content =>
                           [ $news, $stock_quotes, $weather ],
                         -sheader=> [ $tabbed_navigation_bar ],
                         -lpanel=> [ $banner_ad ],
                         -rpanel=> [ $back_issues, $downloads ],
                         -header=> undef,
                         -footer=> undef
                       );

     print "Content-Type: text/html\n\n";
     print $$display;

   I pass the absolute path to my LibWeb's rc (config) file to
`LibWeb::HTML::Default::new()' so that LibWeb can do things according to
my site's preferences.  A sample rc file is included in the eg directory,
if you could not find that, go to the following address to down load a
standard distribution of LibWeb,

     http://libweb.sourceforge.net

   This synopsis also demonstrated how I have handled error by calling the
`fatal()' method.  For the display() call, I passed undef to `-header' and
`-footer' to demonstrate how to tell the display to use default header and
footer.

   Finally, I de-referenced `$display' (by appending `$' in front of the
variable) to print out the HTML page.  Please see the synopsis of
LibWeb/Themes/Default, to see how I have prepared
`$news, $weather, $stock_quotes, $back_issues and $tabbed_navigation_bar'.

   If I would like to customize the HTML display of LibWeb, I would have
ISAed LibWeb::HTML::Default, say a class called `MyHTML' and I just have
to replace the following two lines,

     use LibWeb::HTML::Default;
     my $html = new LibWeb::HTML::Default( $rc_file );

   with

     use MyHTML;
     my $html = new MyHTML( $rc_file );

   A sample MyHTML.pm is included in the distribution for your hacking
pleasure.

ABSTRACT
========

   This class is a sub-class of LibWeb::HTML::Standard,
LibWeb::HTML::Error and LibWeb::Themes::Default and therefore it handles
both standard and error display (HTML) for a LibWeb application.  To
customize the behavior of display(), `display_error()' and built-in
error/help messages, you can make a sub-class of LibWeb::HTML::Default (an
example can be found in the eg directory.  If you could not find it,
download a standard distribution from the following address).  In the
sub-class you made, you can also add your own error messages.  You may
want to take a look at LibWeb/HTML/Error, to see
what error messages are built into LibWeb.  To override the standard error
messages, you re-define them in the sub-class you made.

   The current version of LibWeb::HTML::Default is available at

     http://libweb.sourceforge.net

   Several LibWeb applications (LEAPs) have be written, released and are
available at

     http://leaps.sourceforge.net

TYPOGRAPHICAL CONVENTIONS AND TERMINOLOGY
=========================================

   All `error/help messages' mentioned can be found at
LibWeb/HTML/Error, and they can be customized by ISA
(making a sub-class of) LibWeb::HTML::Default.  Error/help messages are
used when you call LibWeb::Core::fatal, see LibWeb/Core,
for details.  Method's parameters in square brackets means
optional.

DESCRIPTION
===========

   new()

   Params:

class, *rc_file*
   Usage:

     my $html = new LibWeb::HTML::Default( $rc_file );

   Pre:

   * class is the class/package name of this package, be it a string or a
     reference.

   * *rc_file* is the absolute path to the rc file for LibWeb.

   display()

   This implements the base class method:
LibWeb::HTML::Standard::display().

   Params:

     -content=>, [ -sheader=>, -lpanel=>, -rpanel=>,
                   -header=>, -footer=> ]

   Pre:

   * `-content', `-sheader', `-lpanel', `-rpanel', `-header' and `-footer'
     each must be an ARRAY reference to elements which are scalars/SCALAR
     references/ARRAY references,

   * if the elements are ARRAY references, then the elements in those
     ARRAY references must be scalars and NOT references,

   * `-content' default is `content()',

   * `-sheader' stands for "sub header" and default is `sheader()',

   * `-lpanel' default is `lpanel()',

   * `-rpanel' default is `rpanel()',

   * `-header' default is header(),

   * `-footer' default is `footer()'.

   Post:

   * Return a SCALAR reference to a formatted HTML page suitable for
     display to a Web browser.

   Each of the following methods return an ARRAY reference to partial
HTML.  These are the defaults used by the display() method.

   header()

   *sheader()*

   *lpanel()*

   *content()*

   *rpanel()*

   *footer()*

AUTHORS
=======

Colin Kong (colin.kong@toronto.edu)
CREDITS
=======

BUGS
====

SEE ALSO
========

   See LibWeb/Core, LibWeb/HTML/Error,
see LibWeb/HTML/Standard,
LibWeb/Themes/Default.

Displaying error messages in html for libweb applications
*********************************************************

NAME
====

   LibWeb::HTML::Error - Displaying error messages in html for libweb
applications

SUPPORTED PLATFORMS
===================

BSD, Linux, Solaris and Windows.
REQUIRE
=======

   * No non-standard Perl's library is required.

ISA
===

   * None.

SYNOPSIS
========

   You do not use this class directly; use LibWeb::HTML::Default instead.
See LibWeb/HTML/Default.

ABSTRACT
========

   This class defines a method for displaying error messages in HTML.
Several basic error messages are also defined.

   The current version of LibWeb::HTML::Error is available at

     http://libweb.sourceforge.net

   Several LibWeb applications (LEAPs) have be written, released and are
available at

     http://leaps.sourceforge.net

DESCRIPTION
===========

METHODS
-------

   *display_error()*

   Params:

caller, *error_msg*, error_input, *help_msg*
   Pre:

   * caller is a reference to the calling object.  All other parameters
     are scalars except *help_msg* which must be a SCALAR reference.

   Post:

   * Display a HTML page with the error message, error input and help
     message.

   NOTE:

   Do not call this method directly, call LibWeb::Core::fatal() instead.
See LibWeb/Core, for details.

   All of the following methods return a SCALAR reference to an error
message in HTML.

   *mysterious_error()*

   *special_characters_not_allowed()*

   *hit_back_and_edit()*

   *post_too_large()*

   *database_error()*

   *login_failed()*

   *logout_failed()*

   *login_expired()*

   *exceeded_max_login_attempt()*

   *registration_failed()*

   *cookie_error()*

AUTHORS
=======

Colin Kong (colin.kong@toronto.edu)
CREDITS
=======

BUGS
====

SEE ALSO
========

   See LibWeb/Core, LibWeb/HTML/Standard,
see LibWeb/HTML/Default.

AN INTERFACE FOR LIBWEB APPLICATIONS' HTML DISPLAY
**************************************************

NAME
====

   LibWeb::HTML::Site - AN INTERFACE FOR LIBWEB APPLICATIONS' HTML DISPLAY

SUPPORTED PLATFORMS
===================

BSD, Linux, Solaris and Windows.
REQUIRE
=======

   * No non-standard Perl's library is required.

ISA
===

   * LibWeb::Core

SYNOPSIS
========

   This is an interface and actual implementation is done by
LibWeb::HTML::Default.

ABSTRACT
========

   This is an interface describing how a HTML page should be displayed.
Please see LibWeb/HTML/Default, for the actual
implementation.

   The current version of LibWeb::HTML::Site is available at

     http://libweb.sourceforge.net
     ftp://libweb.sourceforge/pub/libweb

   Several LibWeb applications (LEAPs) have be written, released and are
available at

     http://leaps.sourceforge.net
     ftp://leaps.sourceforge.net/pub/leaps

DESCRIPTION
===========

   See LibWeb/HTML/Default.

AUTHORS
=======

Colin Kong (colin.kong@toronto.edu)
CREDITS
=======

BUGS
====

SEE ALSO
========

   See LibWeb/HTML/Default.

An interface defining HTML display for libweb applications
**********************************************************

NAME
====

   LibWeb::HTML::Standard - An interface defining HTML display for libweb
applications

SUPPORTED PLATFORMS
===================

BSD, Linux, Solaris and Windows.
REQUIRE
=======

   * No non-standard Perl's library is required.

ISA
===

   * LibWeb::Core

SYNOPSIS
========

   This is an interface and actual implementation is done by
LibWeb::HTML::Default.

ABSTRACT
========

   This is an interface describing how a HTML page should be displayed.
Please see LibWeb/HTML/Default, for the actual
implementation.

   The current version of LibWeb::HTML::Standard is available at

     http://libweb.sourceforge.net

   Several LibWeb applications (LEAPs) have be written, released and are
available at

     http://leaps.sourceforge.net

DESCRIPTION
===========

   See LibWeb/HTML/Default.

AUTHORS
=======

Colin Kong (colin.kong@toronto.edu)
CREDITS
=======

BUGS
====

SEE ALSO
========

   See LibWeb/HTML/Default,
LibWeb/HTML/Error,

Sessions management for libweb applications
*******************************************

NAME
====

   LibWeb:: - Sessions management for libweb applications

SUPPORTED PLATFORMS
===================

BSD, Linux, Solaris and Windows.
REQUIRE
=======

   * LibWeb::CGI

   * LibWeb::Crypt

   * LibWeb::Database

   * LibWeb::Digest

ISA
===

   * LibWeb::Core

SYNOPSIS
========

     use LibWeb::Session;
     my $s = new LibWeb::Session();

     my ($user_name, $user_id) = $s->get_user();

     #or

     my ($user_name, $user_id)
         = $s->get_user( -is_update_db => 1 );

ABSTRACT
========

   This class manages session authentication after the remote user has
logged in.

   The current version of LibWeb::Session is available at

     http://libweb.sourceforge.net

   Several LibWeb applications (LEAPs) have be written, released and are
available at

     http://leaps.sourceforge.net

TYPOGRAPHICAL CONVENTIONS AND TERMINOLOGY
=========================================

   Variables in all-caps (e.g. MAX_LOGIN_ATTEMPT_ALLOWED) are those
variables set through LibWeb's rc file.  Please read LibWeb/Core,
for more information.  All `error/help messages' mentioned
can be found at LibWeb/HTML/Error, and they can
be customized by ISA (making a sub-class of) LibWeb::HTML::Default. Please
see LibWeb/HTML/Default, for details.  Method's
parameters in square brackets means optional.

DESCRIPTION
===========

METHODS
-------

   *get_user()*

   Check to see if the viewing Web browser has logged in by checking
expiration time, IP and MAC in the authentication cookie, and return the
user name and the user ID if it passes all the authentication checks.

   Params:

     [ -no_auth=>, -mac_mismatch=>, -ip_mismatch=>,
       -expired=>, -is_update_db=> ]

   Pre:

   * *-no_auth* is a CODE reference for callback if the viewing browser
     does not return an authentication cookie.

   * *-mac_mismatch* is a CODE reference for callback if the
     authentication cookie has been tampered with.

   * *-ip_mismatch* is a CODE reference for callback if the IP in the
     authentication cookie does not correspond to the IP address of the
     viewing browser.

   * *-expired* is a CODE reference for callback if the authentication
     cookie is expired.

   * *-is_update_db* is either 1 or 0 (default).  Use this to indicate
     whether this is the first login check.  This parameter should be 1 in
     order to update database's *NUM_LOGIN_ATTEMPT* when a user first
     logged in.

   Post:

   * Retrieve authentication cookies from the viewing Web browser,

   * All *-no_auth*, *-mac_mismatch*, *-ip_mismatch* and *-expired*
     default to the following actions if you do not provide the callbacks:

        * Nullify and delete all authentication cookies resided on the
          viewing Web browser,

        * send an alert e-mail to *ADMIN_EMAIL*,

        * log that event in *FATAL_LOG*,

        * redirect the remote user to the login page (*LM_IN*), and

        * abort the current running program.

   * Check to see If cookie values are null/zero, call *-no_auth* if no
     authentication cookie is retrieved,

   * Check to see If MAC matches, call *-mac_mismatch* if not,

   * Check to see if If IP matches, call *-ip_mismatch* if not,

   * update database: Set *NUM_LOGIN_ATTEMPT* to 0 and call *-expired* if
     the login has expired,

   * If the retrieved cookie passes all the above authentication checks,
     set database's *NUM_LOGIN_ATTEMPT* to *LOGIN_INDICATOR* if parameter
     *-is_update_db* is defined and is equal to 1.  This helps indicate
     that the user is online (currently login),

   * and finally return an array (user name and uid) in plain text.

   Note:

   *USER_LOG_TABLE.NUM_LOGIN_ATTEMPT* != 0 && != *LOGIN_INDICATOR* means
there were several attempts to login but unsuccessful solely because
incorrect password were entered by the remote user.  You need to re-flush
database's *USER_LOG_TABLE.NUM_LOGIN_ATTEMPT* to 0 manually after
receiving the alert e-mail if this value == *MAX_LOGIN_ATTEMPT_ALLOWED*;
otherwise, the user will never be able to sign into your site even he/she
enters the correct password afterwards.

DEPRECATED METHODS
------------------

   *is_login()*

   Note:

   This method is deprecated as of LibWeb-0.02.  You are encouraged to use
*get_user()* instead.  *is_login()* is mainly for backward compatible with
client codes written using LibWeb-0.01.

   Params:

     [ is_just_logged_in ]

   Pre:

   * Parameter `is_just_logged_in' is either 1 or undef.  This is to
     indicate whether this is the first login check.  This parameter should
     be defined in order to update database's
     USER_LOG_TABLE.NUM_LOGIN_ATTEMPT when user first logged in; possibly
     in the first script invoked after the user has been authenticated.

   Post:

   * Retrieve authentication cookies from client Web browser,

   * if cookie values are null/zero, send an alert e-mail to ADMIN_EMAIL
     and redirect the remote user to the login page (LM_IN),

   * if MAC mis-match (this means possible spoofing from remote host), send
     an alert e-mail to ADMIN_EMAIL and redirect the remote user to the
     login page (LM_IN),

   * if IP mis-match (this means possible spoofing from remote host), send
     an alert e-mail to ADMIN_EMAIL and redirect the remote user to the
     login page (LM_IN),

   * login is expired if expiration time reached.  Update database: set
     USER_LOG_TABLE.NUM_LOGIN_ATTEMPT to 0, send an alert e-mail to
     ADMIN_EMAIL and redirect the remote user to the login page (LM_IN),

   * nullify and delete all cookies reside on client Web browser
     immediately if any of item 2, 3, 4 or 5 happens.  Send an alert e-mail
     to ADMIN_EMAIL and redirect the remote user to the login page (LM_IN),

   * if client has officially logged in and none of item 2, 3, 4 or 5
     happens, set USER_LOG_TABLE.NUM_LOGIN_ATTEMPT to LOGIN_INDICATOR if
     parameter `is_just_logged_in' is defined.  This helps to indicate that
     the user is online (currently logged in), and

   * finally return an array (user name and uid) in plain text.

   Note: USER_LOG_TABLE.NUM_LOGIN_ATTEMPT != 0 && != LOGIN_INDICATOR means
there were several attempts to login but unsuccessful solely because
incorrect password were entered by the remote user.  You need to re-flush
NUM_LOGIN_ATTEMPT to 0 manually after 24 hours (no rigorous reason why it
should be 24 hours) of receiving the alert e-mail if this value ==
MAX_LOGIN_ATTEMPT_ALLOWED.

AUTHORS
=======

Colin Kong (colin.kong@toronto.edu)
CREDITS
=======

BUGS
====

SEE ALSO
========

   See LibWeb/Admin, LibWeb/Core,
LibWeb/Crypt, LibWeb/Digest.

Default HTML widgets and theme for libweb applications
******************************************************

NAME
====

   LibWeb::Themes::Default - Default HTML widgets and theme for libweb
applications

SUPPORTED PLATFORMS
===================

BSD, Linux, Solaris and Windows.
REQUIRE
=======

   * No non-standard Perl's library is required.

ISA
===

   * LibWeb::Core

SYNOPSIS
========

     use LibWeb::Themes::Default;
     my $theme = new LibWeb::Themes::Default();

     my $tabs = [
                  '<A HREF="/"><IMG SRC="/img/icon_home.png">Home</A>',
                  '<A HREF="/reports">Featured reports</A>',
                  '<A HREF="/shopping">Best buy</A>',
                  '<A HREF="/log">Login</A>'
                ];

     my $tabbed_navigation_bar =
         $theme->tabber( -tabs => $tabs, -active => 2 );

     my $stock_quotes =
         $theme->bordered_table(
                                 -content => [ $fetched_stock_quotes ]
                               );

     my $weather =
         $theme->bordered_titled_table(
                                        -title => "Today's weather",
                                        -content => [ $fetched_weather ]
                                      );

     my $back_issues =
         $theme->titled_table(
                               -title => "Looking for back issues?",
                               -content => [ $back_issues_archive_list ]
                             );

     my $news =
         $theme->enlighted_titled_table(
                                         -title => "Today's news",
                                         -content => [ $fetched_news ]
                                       );

   Please see the synopsis of LibWeb/HTML/Default,
to see how those HTML constructs can be displayed.

ABSTRACT
========

   This class provides several common table templates for HTML display.
This allows Web application designers focus their efforts on the logic of
programs; while Web page designers spend their efforts on customizing this
default by ISAing this class, say LibWeb::Themes::Futuristic, and writing
different themes.  A sample MyTheme.pm is included in the distribution for
your hacking pleasure.

   The current version of LibWeb::Themes::Default is available at

     http://libweb.sourceforge.net

   Several LibWeb applications (LEAPs) have be written, released and are
available at

     http://leaps.sourceforge.net

TYPOGRAPHICAL CONVENTIONS AND TERMINOLOGY
=========================================

   Variables in all-caps (e.g. SITE_BG_COLOR) are those variables set
through LibWeb's rc file.  Please read LibWeb/Core, for
more information.  Method's parameters in square brackets means optional.

DESCRIPTION
===========

   *bordered_table()*

   Params:

     -content=> [, -border_color=>, -bg_color=>, align=>,
     -valign=>, -cellpadding=>, -width=> ]

   Pre:

   * `-content' must be an ARRAY reference to elements which are
     scalars/SCALAR references/ARRAY references to plain HTML.

   * `-border_color' default is SITE_LIQUID_COLOR2,

   * `-bg_color' default is SITE_BG_COLOR,

   * `-align' is the content's horizontal alignment; default is `left',

   * `-valign' is the content's vertical alignment; default is `top',

   * `-cellpadding' is the distance between the content and the `border'
     of table, default is 2,

   * `-width' default is 100%.

   Post:

   * Return a SCALAR reference to a formatted table in HTML.

   *bordered_titled_table()*

   Params:

     -title=>, -content=> [, -title_space=>, -title_align=>,
     -border_color=>, -title_txt_color=>, -bg_color=>, -align=>,
     -valign=>, -cellpadding=>, -width=> ]

   Pre:

   * -title is a scalar,

   * `-content' must be an ARRAY reference to elements which are
     scalars/SCALAR references/ARRAY references to plain HTML.

   * `-title_space' is the space (&nbsp;) prepended before (if
     `-title_align' is `left') or append after (if `-title_align' is
     `right') the title; default is 2, i.e.  `&nbsp;&nbsp;'.  If
     `-title_align' is `center', -title_space is always 0,

   * `-title_align' default is `center',

   * `-border_color' default is SITE_1ST_COLOR,

   * `-title_txt_color' default is SITE_BG_COLOR,

   * `-bg_color' default is SITE_BG_COLOR,

   * `-align' is the content's horizontal alignment; default is `left',

   * `-valign' is the content's vertical alignment; default is `top',

   * `-cellpadding' is the distance between the content and the `border'
     of table, default is 1,

   * `-width' default is 100%.

   Post:

   * Return a SCALAR reference to a formatted table in HTML.

   *enlighted_titled_table()*

   Params:

     -title=>, -content=> [, -title_space=>, -title_align=>,
     -title_bg_color=>, -title_txt_color=>, -title_border_color=>,
     -bg_color=>, -align=>, -valign=>, -cellpadding=>, -width=> ]

   Pre:

   * `-title' is a scalar,

   * `-content' must be an ARRAY reference to elements which are
     scalars/SCALAR references/ARRAY references to plain HTML,

   * `-title_space' is the space (&nbsp;) prepended before (if
     `-title_align' is `left') or append after (if `-title_align' is
     `right') the title; default is 2, i.e. `&nbsp;&nbsp;'.  It is always 0
     if `-title_align' is `center',

   * `-title_align' default is `center',

   * `-title_bg_color' default is SITE_LIQUID_COLOR3,

   * `-title_txt_color' default is SITE_LIQUID_COLOR5,

   * `-title_border_color' default is SITE_LIQUID_COLOR5,

   * `-bg_color' default is SITE_BG_COLOR,

   * `-align' is the content's horizontal alignment; default is `left',

   * `-valign' is the content's vertical alignment; default is `top',

   * `-cellpadding' is the distance between the content and the `border'
     of table, default is 1.

   * `-width' default is 100%.

   Post:

   * Return a SCALAR reference to a formatted table in HTML.

   *tabber()*

   Params:

     -tabs=>, -active=> [, -active_color=>, -fade_color=>,
     -tab_padding=>, -tab_width=>, -gap_width=>, -total_width=>,
     -base=>, -base_height=>, -base_align, -left_stub=>,
     -right_stub=>, -left_stub_align=>, -right_stub_align=>,
     -left_stub_width=>, -right_stub_width=> ]

   Pre:

   * `-tabs' is an ARRAY reference to scalar or SCALAR reference

   * `-active' is a number indicating which tab is currently active (count
     from 0)

   * `-active_color' is the color for the active tab; default is
     SITE_1ST_COLOR

   * `-fade_color' is the color for non-active tabs; default is
     SITE_LIQUID_COLOR3

   * `-tab_padding' is the distance between a tab's content to its border,
     either in pixel or percentage; default is 0

   * `-tab_width' is the width of each tab, either in pixel or percentage;
     default is ( total_width / (2 * number of tabs) )

   * `-gap_width' is the distance between two adjacent tabs, either in
     pixel or percentage; default if 1%

   * `-total_width' is the width of the whole tabber, either in pixel or
     percentage; default is 100%

   * `-base' is a SCALAR reference to HTML to be put under the tabs

   * `-base_height' is the height of -base, either in pixel or percentage;
     default is 5.  You do not want to specify this if you specify `-base'

   * `-base_align' default is `left'

   * `-left_stub' is a SCALAR reference to HTML to be put to the left of
     the tabs

   * `-right_stub' is a SCALAR reference to HTML to be put to the right of
     the tabs

   * `-left_stub_align' is 'left', 'center' or 'right'; default is 'left'

   * `-right_stub_align' is 'left', 'center' or 'right'; default is 'right'

   * `-left_stub_width' is either in pixel or percentage, you may want to
     specify this if you specify `-left_stub'

   * `-right_stub_width' is either in pixel or percentage

   Post:

   * Return a SCALAR reference to a formatted tabbing navigation bar in
     HTML format.

   table()

   Params:

     -content=> [, -bg_color=>, -align=>, -valign=>, -width=> ]

   Pre:

   * `-content' must be an ARRAY reference to elements which are
     scalars/SCALAR references/ARRAY references to plain HTML,

   * `-bg_color' default is SITE_BG_COLOR,

   * `-align' is the content's horizontal alignment; default is `left',

   * `-valign' is the content's vertical alignment; default is `top',

   * `-width' default is 100%.

   Post:

   * Return a SCALAR reference to a formatted table in HTML.

   *titled_table()*

   Params:

     -title=>, -content=> [, -title_space=>, -title_align=>,
     -title_bg_color=>, -title_txt_color=>, -bg_color=>, align=>,
     -valign=>, -cellpadding=>, -width=> ]

   Pre:

   * -title is a scalar,

   * `-content' must be an ARRAY reference to elements which are
     scalars/SCALAR references/ARRAY references to plain HTML,

   * `-title_space' is the space (&nbsp;) prepended before (if
     `-title_align' is `left') or append after (if `-title_align' is
     `right') the title.  It is always 0 if `-title_align' is `center'.
     Default is 2, i.e. `&nbsp;&nbsp;',

   * `-title_align' default is `center',

   * `-title_bg_color' default is SITE_1ST_COLOR,

   * `-title_txt_color' default is SITE_BG_COLOR,

   * `-bg_color' default is SITE_BG_COLOR,

   * `-align' is the content's horizontal alignment; default is `left',

   * `-valign' is the content's vertical alignment; default is `top',

   * `-cellpadding' is the distance between the content and the `border' of
     table, default is 1.

   * `-width' default is 100%.

   Post:

   * Return a SCALAR reference to a formatted table in HTML.

AUTHORS
=======

Colin Kong (colin.kong@toronto.edu)
CREDITS
=======

BUGS
====

   This release does not provide a lot of table templates and only a
default theme is available.  Hopefully more people can write more themes
for LibWeb and make them available at http://libweb.sourceforge.net.

SEE ALSO
========

   See LibWeb/HTML/Error, LibWeb/HTML/Site,
see LibWeb/HTML/Default,

Various time formats for libweb applications
********************************************

NAME
====

   LibWeb::Time - Various time formats for libweb applications

SUPPORTED PLATFORMS
===================

BSD, Linux, Solaris and Windows.
REQUIRE
=======

   * No non-standard Perl's library is required.

ISA
===

   * None.

SYNOPSIS
========

     use LibWeb::Time();
     my $time = new LibWeb::Time();

     my $wday_mon_mday = $time->get_date();

     my $hh_mm_ss = $time->get_time();

     my $wday_mon_dd_hh_mm_ss_yyyy = $time->get_datetime();

     my $yyyymmddhhmmss = $time->get_timestamp();

     my $yyyy = $time->get_year();

ABSTRACT
========

   This class uses the perl's localtime() routine to provide several
methods which return time in several formats.

   The current version of LibWeb::Time is available at

     http://libweb.sourceforge.net

   Several LibWeb applications (LEAPs) have be written, released and are
available at

     http://leaps.sourceforge.net

DESCRIPTION
===========

METHODS
-------

   *get_date()*

   Return 'wday mon mday' as a string, e.g. 'Sun May 28'.

   *get_time()*

   Return 'hh:mm:ss' as a string, e.g. '14:35:47'.

   *get_datetime()*

   Return 'wday mon dd hh:mm:ss yyyy' as a string, e.g. 'Sun May 28
14:35:47 2000'.  This is the same as using the perl's localtime() directly
in scalar context.

   *get_timestamp()*

   Return 'yyyymmddhhmmss' as a string, e.g. '20000528133547'.

   *get_year()*

   Return 'yyyy' as a string, e.g. '2000'.

AUTHORS
=======

Colin Kong (colin.kong@toronto.edu)
CREDITS
=======

BUGS
====

SEE ALSO
========

Perl extension for direct-to-lpd printing.
******************************************

NAME
====

   LinePrinter - Perl extension for direct-to-lpd printing.

SYNOPSIS
========

     use LinePrinter;

     # Create new LinePrinter
     $lineprinter = new LinePrinter(
     				 filename    => "/home/jdoe/myfile.txt",
     				 printer     => "lp",
     				 server      => "printserver",
     				 port        => 515,
     				 lineconvert => "YES"
     				 );
     # Print the file
     $result = $lineprinter->printfile();

     # Print a string
     $result =
       $lineprinter->printstring("Smoke me a kipper, I'll be back for breakfast.");

     # Get Queue Status
     $result = $lineprinter->queuestatus();

DESCRIPTION
===========

     Perl module for directly printing to a print server/printer without
     having to create a pipe to either lpr or lp.  This essentially
     mimics what the BSD LPR program does by connecting directly to the
     line printer printer port (almost always 515), and transmitting
     the data and control information to the print server.

     Please note that this module only talks to print servers that
     speak BSD.  It will not talk to printers using SMB or SysV unless
     they are set up as BSD printers.

Parameters
----------

     filename    - [optional] absolute path to the file you wish to print.

     printer     - [optional] Name of the printer you wish to print to.
                   Default "lp".

     server      - [optional] Name of the server that is running
                   lpd/lpsched.  Default "localhost".

     port        - [optional] The port you wish to connect to.
                   Default "515".

     lineconvert - [optional] Perform LF -> LF/CR translation.
                   Default "NO"

Functions
---------

     I<printfile> prints a specified file to the printer.  Returns a 1 on
     success, otherwise returns a string containing the error.

     I<printstring> prints a specified string to the printer.  Returns
     a 1 on success, otherwise returns a string containing the error.

     I<queuestatus> returns the current status of the print queue.  I
     recommend waiting a short period of time between printing and
     issueing a queuestatus to give your spooler a chance to do it's
     thing.  5 seconds tends to work for me.

NOTES
=====

     When printing text, if you have the infamous "stair-stepping"
     problem, try setting lineconvert to "YES".  This should, in most
     cases, rectify the problem.

AUTHOR
======

   C. M. Fuhrman, cfuhrman@tfcci.com

SEE ALSO
========

   Socket, lpr(1), lp(1), perl(1).

Expand or Contract Amharic Abbreviations
****************************************

NAME
====

   AM::Abbreviate - Expand or Contract Amharic Abbreviations

SYNOPSIS
========

     use Lingua::AM::Abbreviate;

     while ( $string = <> ) {  # some UTF8 string
     	if ( $contracted = Contract ( $string ) ) {
     		print "$string => $contracted\n";
     	} elsif ( $expanded = Expand ( $string ) ) {
     		print "$string => $expanded\n";
     	}
     }

DESCRIPTION
===========

   AM::Abbreviate provides two routines, "Expand" and "Contract", to assist
in Amharic translation or spell checking.  Each routine expects an Amharic
string in UTF8 encoding as an argument and returns an expansion or
contraction if found.

AUTHOR
======

   Daniel Yacob,
`LibEth@EthiopiaOnline.Net|mailto:LibEth@EthiopiaOnline.Net' in this node

SEE ALSO
========

   perl(1).  Ethiopic(3), `http:' in this node

Convert Perl lists into linguistic conjunctions
***********************************************

NAME
====

   Lingua::Conjunction - Convert Perl lists into linguistic conjunctions

SYNOPSIS
========

     use Lingua::Conjunction;

     # emits "Jack"
     $name_list = conjunction('Jack');

     # emits "Jack and Jill"
     $name_list = conjunction('Jack', 'Jill');

     # emits "Jack, Jill, and Spot"
     $name_list = conjunction('Jack', 'Jill', 'Spot');

     # emits "Jack, a boy; Jill, a girl; and Spot, a dog"
     $name_list = conjunction('Jack, a boy', 'Jill, a girl', 'Spot, a dog');

     # emits "Jacques, un garcon; Jeanne, une fille; et Spot, un chien"
     Lingua::Enlist->lang('fr');
     $name_list = conjunction('Jacques, un garcon', 'Jeanne, une fille', 'Spot, un chien');

DESCRIPTION
===========

   Lingua::Conjunction exports a single subroutine, `conjunction', that
converts a list into a properly punctuated text string.

   You can cause `conjunction' to use the connectives of other languages,
by calling the appropriate subroutine:

     Lingua::Conjunction->lang('en');   # use 'and' (default)
     Lingua::Conjunction->lang('es');   # use 'y'

   Supported languages in this version are English, Spanish, French,
Italian, German, Portuguese, Norwiegian, and Danish.

   You can also set connectives individually:

     Lingua::Conjunction->separator("...");
     Lingua::Conjunction->separator_phrase("--");
     Lingua::Conjunction->connector_type("or");

     # emits "Jack... Jill... or Spot"
     $name_list = conjunction('Jack', 'Jill', 'Spot');

   The "separator_phrase" is used whenever the separator already appears in
an item of the list. For example:

     # emits "Doe, a deer; Ray; and Me"
     $name_list = conjunction('Doe, a deer', 'Ray', 'Me');

REVISION HISTORY
================

   Originally this modules was uploaded to CPAN as `Text::List'. After some
criticism, this module was renamed.

   As per suggestions, other features were added. Probably too many
features for what amounts to a simple hack.

SEE ALSO
========

   Locale::Language

AUTHORS
=======

   Robert Rothenberg <wlkngowl@unix.asb.com>

   Damian Conway <damian@csse.monash.edu.au>

Routine for automatically detecting cyrillic charset.
*****************************************************

NAME
====

   Lingua::DetectCharset - Routine for automatically detecting cyrillic
charset.

SYNOPSIS
========

   use Lingua::DetectCharset;

   $Charset = Lingua::DetectCharset::Detect ($Buffer);

   The returned $Ecoding is either 'WIN', 'KOI8' or 'ENG'. The last is
return when no single cyrillic token are found in buffer.

DESCRIPTION
===========

   This package implements routine for detection charset of the given text
snippet.  Snippet may contain anything from few words to many kilobytes of
text, and may have line breaks, English text and html tags embedded.

   This routine is implemented using algorithm of statistical analysis of
text, which was proved to be very efficient and showed around *99.98%
acccuracy* in tests.

AUTHOR
======

   John Neystadt <john@neystadt.org>

SEE ALSO
========

   perl(1), Convert::Cyrillic(3).

NOTES
=====

   Part of "WWW Cyrillic Encoding Suite" Get docs and newest version from
http://www.neystadt.org/cyrillic/

   Copyright (c) 1997-98, John Neystadt <http://www.neystadt.org/john/>
You may install this script on your web site for free To obtain permision
for redistribution or any other usage contact john@neystadt.org.

   Drop me a line if you deploy this script on your site.

manipulate geographical addresses
*********************************

NAME
====

   Lingua::EN::AddressParse -  manipulate geographical addresses

SYNOPSIS
========

     use Lingua::EN::AddressParse;

     my %args =
     (
     	country     => 'Australia',
        auto_clean  => 1,
        force_case  => 1
     );

     my $address = new Lingua::EN::AddressParse(%args);

     $error = $address->parse("14A MAIN RD. ST JOHNS WOOD NSW 2000");

     %my_address = $address->components;
     $suburb = $my_address{suuburb};

     $correct_casing = $address->case_all;

REQUIRES
========

   Perl, version 5.001 or higher, Lingua::EN::NameParse and
Parse::RecDescent

DESCRIPTION
===========

   This module takes as input an address or post box in free format text
such as,

     12/3-5 AUBREY ST VERMONT VIC 3133
     "OLD REGRET" WENTWORTH FALLS NSW 2782 AUSTRALIA
     2A LOW ST. KEW NSW 2123
        GPO Box K318, HAYMARKET, NSW 2000

   and attempts to parse it. If successful, the address is broken down
into components and useful functions can be performed such as :

     converting upper or lower case values to name case (2 Low St. Kew NSW 2123 )
     extracting the addresses individual components     (2,Low St.,KEW,NSW,2123 )
     determining the type of format the address is in   ('suburban')

   If the address cannot be parsed you have the option of cleaning the
address of bad characters, or extracting any portion that was parsed and
the portion that failed.

   This module can be used for analysing and improving the quality of
lists of addresses.

DEFINITIONS
===========

   The following terms are used by AddressParse to define the components
that can make up an address or post box.

     Post Box - 	GP0 Box K123, LPO 2345, RMS 23 ...

        Property Identifier
        	Sub property description  -  Level, Unit, Apartment, Lot ...
        Property number           - 12/66A, 24-34, 2A, 23B/12C, 12/42-44

        Property name - "Old Regret"

     Street
     	   Street name   - O'Hare, New South Head, The Causeway
     	   Street type   - Road, Rd., St, Lane, Highway, Crescent, Circuit ...

     Suburb	     - Dee Why, St. John's Wood ...
     State			  - NSW, ACT, NY, AZ ...
     Post code	  - 2062, 34532, SG12A 9ET
     Country		  - Australia, UK, Papua New Guinea ....

     Refer to the component grammar defined within the code for a complete
     list of combinations.

   The following address formats are currently supported :

     'suburban' - property_identifier street suburb state post_code country(?)
     'post_box' - post_box suburb_subcountry post_code country(?)
     'rural'    - property_name suburb_subcountry post_code country(?)

METHODS
=======

new
---

   The new method creates an instance of an address object and sets up the
grammar used to parse addresses. This must be called before any of the
following methods are invoked. Note that the object only needs to be
created once, and can be reused with new input data.

   Various setup options may be defined in a hash that is passed as an
optional argument to the new method.

     my %args =
     (
     	country     => 'Australia',
        auto_clean  => 1,
        force_case  => 1
     );

     my $address = new Lingua::EN::AddressParse(%args);

country
.......

   The country argument must be specified. It determines the possible list
of valid subcountries (states, counties etc, defined in the
Locale::SubCountry module) and post code formats.The current list of
coutries is

     Australia
     Brazil
     Canada
     Netherlands
     UK
     USA

     All forms of upper/lower case are acceptable in the country's spelling. If a
     country name is supplied that the module doesn't recognise, it will die.

     =head3 force_case

   This option will force the case_all method to address case the entire
input string, including any unmatched sections that failed parsing.   This
option is useful when you know you data has invalid addresses, but you
cannot filter out or reject them.

auto_clean
..........

   When this option is set to a positive value, any call to the parse
method that fails will attempt to 'clean' the address and then reparse it.
See the clean method for  details. This is useful for dirty data with
embedded unprintable or non alphabetic characters.

parse
-----

     $error = $address->parse("12/3-5 AUBREY ST VERMONT VIC 3133");

   The parse method takes a single parameter of a text string containing a
address. It attempts to parse the address and break it down into the
components described above. If the address was parsed successfully, a 0 is
returned, otherwise a 1. This step is a prerequisite for the following
functions.

case_all
--------

     $correct_casing = $address->case_all;

   The case_all method converts the first letter of each component to
capitals and the remainder to lower case, with the following exceptions-

     Proper names capitalisation such  as MacNay and O'Brien are observed

   The method returns the entire cased address as text.

case_components
---------------

     %my_address = $address->components;
     $cased_suburb = $my_address{suburb};

   The case_components method  does the same thing as the case_all method,
but returns the addresses cased components in a hash. The following keys
are used for each component-

   	post_box 	property_identifier    property_name    street
suburb    post_code    country

   Entries only occur in the hash for each component that the currently
parsed address contains, meaning there are no keys with undefined values.

components
----------

     %address = $address->components;
     $surburb = $address{suburb};

   The components method  does the same thing as the case_components
method, but each component is returned as it appears in the input string,
with no case conversion.

properties
----------

   The properties method return several properties of the address as a
hash.

type
....

   The type of format a name is in, as one of the following strings:

     suburban
     rural
     post_box
     unknown

non_matching
............

   Returns any unmatched section that was found.

LIMITATIONS
===========

   The huge number of character combinations that can form a valid address
makes it is impossible to correctly identify them all.

   Valid addresses must contain a suburb, subcountry (state) and post code,
in that order. This format is widely accepted in Australia and the US. UK
addresses will often include suburb, town, city and county, formats that
are very difficult to parse.

   Subcountries must be in abbreviated form such as NSW, VIC, NY, CA,
LEICS.  I could add a pre-parse step to detect and abbreivate subcountry
names, so data sych as "New South Wales" can be parsed.

   Property names must be enclosed in quotes like "Old Regret"

   Because of the large combination of possible addresses defined in the
grammar, the program is not very fast.

REFERENCES
==========

   "The Wordsworth Dictionary of Abbreviations & Acronyms" (1997)

   Australian Standard AS4212-1994 "Geographic Information Systems - Data
Dictionary for transfer of street addressing information"

FUTURE DIRECTIONS
=================

   Define grammar for other languages. Hopefully, all that would be needed
is to specify a new module with its own grammar, and inherit all the
existing methods. I don't have the knowledge of the naming conventions for
non-english languages.

SEE ALSO
========

   Locale::Subcountry Lingua::EN::NameParse Parse::RecDescent

TO DO
=====

BUGS
====

CHANGES
=======

   0.01 28 Dec 1999: First Release

     =head1 COPYRIGHT

   Copyright (c) 2000 Kim Ryan. All rights reserved.  This program is free
software; you can redistribute it and/or modify it under the terms of the
Perl Artistic License (see http://www.perl.com/perl/misc/Artistic.html).

AUTHOR
======

   AddressParse was written by Kim Ryan <kimaryan@ozemail.com.au> in 2000.

readability and general measurements of English text
****************************************************

NAME
====

   Lingua::EN::Fathom - readability and general measurements of English
text

SYNOPSIS
========

     use Lingua::EN::Fathom;

     my $text = new Lingua::EN::Fathom;

     $text->analyse_file("sample.txt");

     $accumulate = 1;
     $text->analyse_block($text_string,$accumulate);

     $num_chars       = $text->num_chars;
     $num_words       = $text->num_words;
     $num_sentences   = $text->num_sentences;
     $num_text_lines  = $text->num_text_lines;
     $num_blank_lines = $text->num_blank_lines;
     $num_paragraphs  = $text->num_paragraphs;

     %words = $text->unique_words;
     foreach $word ( sort keys %words )
     {
        print("$words{$word} :$word\n");
     }

     $fog     = $text->fog;
     $flesch  = $text->flesch;
     $kincaid = $text->kincaid;

     print($text->report);

REQUIRES
========

   Perl, version 5.001 or higher, Lingua::EN::Syllable

DESCRIPTION
===========

   This module analyses English text in either a string or file. Totals are
then calculated for the number of characters, words, sentences, blank and
non blank (text) lines and paragraphs.

   Three common readability statistics are also derived, the Fog, Flesch
and Kincaid indices.

   All of these properties can be accessed through individual methods, or
by generating a text report.

   A hash of all unique words and the number of times they occur is
generated.

METHODS
=======

new
---

   The new method creates an instance of an text object This must be called
before any of the following methods are invoked. Note that the object only
needs to be created once, and can be reused with new input data.

     my $text = new Lingua::EN::Fathom;

analyse_file
------------

   The analyse_file method takes as input the name of a text file. Various
text based statistics are calculated for the file. This method and
analyse_block are prerequisites for all the following methods.	An
optional argument may be supplied to control accumualtion of statisitics.
If set to a non zero value, all statistics are accumulated with each
successive call.

analyse_block
-------------

   The analyse_block method takes as input the name of a text file. Various
text based statistics are calculated for the file. This method and
analyse_file are prerequisites for all the following methods. An optional
argument may be supplied to control accumualtion of statisitics. If set to
a non zero value, all statistics are accumulated with each successive call.

num_chars
---------

   Returns the number of characters in the analysed text file or block.
This includes characters such as spaces, and punctuation marks.

num_words
---------

   Returns the number of words in the analysed text file or block. A word
must consist of letters a-z with at least one vowel sound, and optionally
an apostrophe or hyphen. Items such as "&, K108, NSW" are not counted as
words.

num_sentences
-------------

   Returns the number of sentences in the analysed text file or block. A
sentence is any group of words and non words terminated with a single full
stop. Spaces may occur before and after the full stop.

num_text_lines
--------------

   Returns the number of lines containing some text in the analysed text
file or block.

num_blank_lines
---------------

   Returns the number of lines NOT containing any text in the analysed
text file or block.

num_paragraphs
--------------

   Returns the number of paragraphs in the analysed text file or block.

READABILITY
-----------

   Three indices of text readability are calculated. They all measure
complexity as a function of syllables per word and words per sentence.
They assume the text	is well formed and logical. You could analyse a
passage of nonsensical English and find the readability is quite good,
provided the words are not too complex and the sentences not too long.

   For more information see:
http://www.plainlanguage.com/Resources/readability.html

fog
---

   Returns the Fog index for the analysed text file or block.
words_per_sentence +  percent_complex_words ) * 0.4

   The Fog index, developed by Robert Gunning, is a well known and simple
formula for measuring readability. The index indicates the number of years
of formal education a reader of average intelligence would need to read the
text once and understand that piece of writing with its word sentence
workload.

     18 unreadable
     14 difficult
     12 ideal
     10 acceptable
      8 childish

flesch
------

   Returns the Flesch reading ease score for the analysed text file or
block.  	206.835 - (1.015 * words_per_sentence) - (84.6 *
syllables_per_word)

   This score rates text on a 100 point scale. The higher the score, the
easier it is to understand the text. A score of 60 to 70 is considered to
be optimal.

kincaid
-------

   Returns the Flesch-Kincaid grade level score for the analysed text file
or block.

     (11.8 * syllables_per_word) +  (0.39 * words_per_sentence) - 15.59;

   This score rates text on  U.S. grade school level. So a score of 8.0
means that the document can be understood by an eighth grader. A score of
7.0 to 8.0 is considered to be optimal.

unique_words
------------

   Returns a hash of unique words. The words (in lower case) are held in
the hash keys while the number of occurrences are held in the hash values.

report
------

   print($text->report);

   Produces a text based report containing the following statistics for
the currently analysed text block or file:

     Number of characters
     	Number of words
     	Average syllables per word
     	Number of sentences
     	Average words per sentence
     	Number of text lines
     	Number of blank lines
     	Number of paragraphs

     Fog Index
     Flesch Index
     Flesch-Kincaid Index

   The return value is a string containing the report contents

SEE ALSO
========

     Lingua::EN::Syllable
     B::Fathom

POSSIBLE EXTENSIONS
===================

     Analyse many files at once
     Analyse HTML and other formats
     Allow user control over what strictly defines a word
     Provide a density measure of white space to characters

LIMITATIONS
===========

   Common abbreviations such as St. or Pty. Ltd. will trick the module into
inflating the number of sentences it finds.

   The syllable count provided in Lingua::EN::Syllable is about 90%
accurate

   Acronyms that contain vowels, like GPO, will be counted as words.

   The fog index should exclude proper names

BUGS
====

COPYRIGHT
=========

   Copyright (c) 2000-1 Kim Ryan. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the terms of
the Perl Artistic License (see
http://www.perl.com/perl/misc/Artistic.html).

AUTHOR
======

   Lingua::EN::Fathom was written by Kim Ryan <kimaryan@ozemail.com.au> in
2000.

Inflect pronouns for gender
***************************

NAME
====

   Lingua::EN::Gender - Inflect pronouns for gender

SYNOPSIS
========

     use Lingua::EN::Gender;

     print &genders();

     if (&is_valid_gender("male")) { ...

DESCRIPTION
===========

   Small module for inflecting pronouns for a bunch of different genders.

   Genders currently supported are:    neuter    male    female    either
 spivak    splat    plural    egotistical    royal    2nd    sie/hir
zie/zir

FUNCTIONS
=========

pronoun ( TYPE, GENDER )
     Returns the appropriate pronoun word for that pronoun type and gender.

     The types (examples for the male gender in brackets) are:
     subjective ("he")    objective ("him")    posessive-subjective ("his")
       posessive-objective ("his")    reflexive ("himself")

     Simply returns an array containing all the valid genders.

     Returns true/false depending if the argument is a gender we know
     about.  Case is not significant.

AUTHOR
======

   Bek Oberin <bekj@netizen.com.au>

COPYRIGHT
=========

   Copyright (c) 1999 Bek Oberin.  All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl extension for syllable-based hyphenation
*********************************************

NAME
====

   Lingua::En::Hyphenate - Perl extension for syllable-based hyphenation

SYNOPSIS
========

     use Lingua::En::Hyphenate;

DESCRIPTION
===========

AUTHOR
======

Determine the infinitive form of a conjugated word
**************************************************

NAME
====

   `Lingua::EN::Infinitive' - Determine the infinitive form of a
conjugated word

SYNOPSIS
========

     use Lingua::EN::Infinitive;

     my($spell) = Lingua::EN::Infinitive -> new();
     my($word)  = 'rove';

     # Method 1:
     my($word1, $word2, $suffix, $rule) = $spell -> stem($word);

     # Method 2:
     $spell -> stem($word);
     my($word1, $word2, $suffix, $rule) =
     (
     	$spell -> {'word1'},  # A possibility.
     	$spell -> {'word2'},  # A possibility, or ''.
     	$spell -> {'suffix'},
     	$spell -> {'rule'},
     );

     print "Conjugated: $word. Infinitive: $word1. \n";

DESCRIPTION
===========

   Determine the infinitive form of a conjugated word. Also, determine the
suffix used to identify which rule to apply to transform the conjugated
word into the infinitive form.

   Either 1 or 2 possible infinitives are returned. You must check that
the first is really an English word. If it is, then it is the result. If
it is not valid, then check the second.

   Failure to deconjugate is indicated by $word1 eq ".

   In general, you can ignore the 3rd and 4th values returned from stem().

   The algorithm is based on McIlroy's article (see below), after first
checking for irregular words.

   In the hash 'suffix2Rule', you'll see the key 'order'. This specifies
the sort order in which to check McIlroy's rules. I've changed his
ordering in a number of places.

INSTALLATION
============

   You install `Lingua::EN::Infinitive', as you would install any perl
module library, by running these commands:

     perl Makefile.PL
     make
     make test
     make install

   If you want to install a private copy of `Lingua::EN::Infinitive' in
your home directory, then you should try to produce the initial Makefile
with something like this command:

     perl Makefile.PL LIB=~/perl
     	or
     perl Makefile.PL LIB=C:/Perl/Site/Lib

   If, like me, you don't have permission to write man pages into unix
system directories, use:

     make pure_install

   instead of make install. This option is secreted in the middle of p 414
of the second edition of the dromedary book.

WARNING
=======

   Don't make the false assumption that

     "$word1$suffix" eq $word
     	or
     "$word2$suffix" eq $word

REFERENCE
=========

     Title:   Development of a Spelling List
     Author:  M. Douglas McIlroy
     Journal: IEEE Transactions on Communications
     Issue:   Vol COM-30, No 1, January 1982

AUTHOR
======

   `Lingua::EN::Infinitive' was written by Ron Savage
*<rpsavage@ozemail.com.au>* in 1998.

LICENCE
=======

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Convert singular to plural. Select "a" or "an".
***********************************************

NAME
====

   Lingua::EN::Inflect - Convert singular to plural. Select "a" or "an".

VERSION
=======

   This document describes version 1.86 of Lingua::EN::Inflect, released
October 20, 2000.

SYNOPSIS
========

     use Lingua::EN::Inflect qw ( PL PL_N PL_V PL_ADJ NO NUM
     			      PL_eq PL_N_eq PL_V_eq PL_ADJ_eq
     			      A AN
     			      PART_PRES
     			      ORD NUMWORDS
     			      inflect classical
     			      def_noun def_verb def_adj def_a def_an );

     # UNCONDITIONALLY FORM THE PLURAL

     print "The plural of ", $word, " is ", PL($word), "\n";

     # CONDITIONALLY FORM THE PLURAL

     print "I saw $cat_count ", PL("cat",$cat_count), "\n";

     # FORM PLURALS FOR SPECIFIC PARTS OF SPEECH

     print PL_N("I",$N1), PL_V("saw",$N1),
     	    PL_ADJ("my",$N2), PL_N("saw",$N2), "\n";

     # DEAL WITH "0/1/N" -> "no/1/N" TRANSLATION:

     print "There ", PL_V("was",$errors), NO(" error",$errors), "\n";

     # USE DEFAULT COUNTS:

     print NUM($N1,""), PL("I"), PL_V(" saw"), NUM($N2), PL_N(" saw");
     print "There ", NUM($errors,''), PL_V("was"), NO(" error"), "\n";

     # COMPARE TWO WORDS "NUMBER-INSENSITIVELY":

     print "same\n"      if PL_eq($word1, $word2);
     print "same noun\n" if PL_eq_N($word1, $word2);
     print "same verb\n" if PL_eq_V($word1, $word2);
     print "same adj.\n" if PL_eq_ADJ($word1, $word2);

     # ADD CORRECT "a" OR "an" FOR A GIVEN WORD:

     print "Did you want ", A($thing), " or ", AN($idea), "\n";

     # CONVERT NUMERALS INTO ORDINALS (i.e. 1->1st, 2->2nd, 3->3rd, etc.)

     print "It was", ORD($position), " from the left\n";

     # CONVERT NUMERALS TO WORDS (i.e. 1->"one", 101->"one hundred and one", etc.)
     # IN A SCALAR CONTEXT: GET BACK A SINGLE STRING...

     $words = NUMWORDS(1234);	# "one thousand, two hundred and thirty-four"

     # IN A LIST CONTEXT: GET BACK A LIST OF STRINGSi, ONE FOR EACH "CHUNK"...

     @words = NUMWORDS(1234);	# ("one thousand","two hundred and thirty-four")

     # OPTIONAL PARAMETERS CHANGE TRANSLATION:

     $words = NUMWORDS(12345, group=>1);
     				# "one, two, three, four, five"

     $words = NUMWORDS(12345, group=>2);
     				# "twelve, thirty-four, five"

     $words = NUMWORDS(12345, group=>3);
     				# "one twenty-three, forty-five"

     $words = NUMWORDS(1234, 'and'=>'');
     				# "one thousand, two hundred thirty-four"

     $words = NUMWORDS(1234, 'and'=>', plus');
     				# "one thousand, two hundred, plus thirty-four"

     $words = NUMWORDS(555_1202, group=>1, zero=>'oh');
     				# "five, five, five, one, two, oh, two"

     $words = NUMWORDS(123.456, group=>1, decimal=>'mark');
     				# "one two three mark four five six"

     # REQUIRE "CLASSICAL" PLURALS (EG: "focus"->"foci", "cherub"->"cherubim")

     classical;	# USE CLASSICAL PLURALS

     classical 1;	# USE CLASSICAL PLURALS
     classical 0;	# USE MODERN PLURALS (DEFAULT)

     # INTERPOLATE "PL()", "PL_N()", "PL_V()", "PL_ADJ()", A()", "AN()"
     # "NUM()" AND "ORD()" WITHIN STRINGS:

     print inflect("The plural of $word is PL($word)\n");
     print inflect("I saw $cat_count PL("cat",$cat_count)\n");
     print inflect("PL(I,$N1) PL_V(saw,$N1) PL(a,$N2) PL_N(saw,$N2)");
     print inflect("NUM($N1,)PL(I) PL_V(saw) NUM($N2,)PL(a) PL_N(saw)");
     print inflect("I saw NUM($cat_count) PL("cat")\nNUM()");
     print inflect("There PL_V(was,$errors) NO(error,$errors)\n");
     print inflect("There NUM($errors,) PL_V(was) NO(error)\n";
     print inflect("Did you want A($thing) or AN($idea)\n");
     print inflect("It was ORD($position) from the left\n");

     # ADD USER-DEFINED INFLECTIONS (OVERRIDING INBUILT RULES):

     def_noun  "VAX"  => "VAXen";	# SINGULAR => PLURAL

     def_verb  "will" => "shall",	# 1ST PERSON SINGULAR => PLURAL
               "will" => "will",	# 2ND PERSON SINGULAR => PLURAL
               "will" => "will",	# 3RD PERSON SINGULAR => PLURAL

     def_adj   "hir"  => "their",	# SINGULAR => PLURAL

     def_a	"h"			# "AY HALWAYS SEZ 'HAITCH'!"

     def_an	"horrendous.*"		# "AN HORRENDOUS AFFECTATION"

DESCRIPTION
===========

   The exportable subroutines of Lingua::EN::Inflect provide plural
inflections, "a"/"an" selection for English words, and manipulation of
numbers as words

   Plural forms of all nouns, most verbs, and some adjectives are
provided. Where appropriate, "classical" variants (for example: "brother"
-> "brethren", "dogma" -> "dogmata", etc.) are also provided.

   Pronunciation-based "a"/"an" selection is provided for all English
words, and most initialisms.

   It is also possible to inflect numerals (1,2,3) to ordinals (1st, 2nd,
3rd) and to english words ("one", "two", "three).

   In generating these inflections, Lingua::EN::Inflect follows the Oxford
English Dictionary and the guidelines in Fowler's Modern English Usage,
preferring the former where the two disagree.

   The module is built around standard British spelling, but is designed
to cope with common American variants as well. Slang, jargon, and other
English dialects are not explicitly catered for.

   Where two or more inflected forms exist for a single word (typically a
"classical" form and a "modern" form), Lingua::EN::Inflect prefers the
more common form (typically the "modern" one), unless "classical"
processing has been specified (see `"MODERN VS CLASSICAL INFLECTIONS"' in
this node).

FORMING PLURALS
===============

Inflecting Plurals
------------------

   All of the `PL_...' plural inflection subroutines take the word to be
inflected as their first argument and return the corresponding inflection.
Note that all such subroutines expect the *singular* form of the word. The
results of passing a plural form are undefined (and unlikely to be
correct).

   The `PL_...' subroutines also take an optional second argument, which
indicates the grammatical "number" of the word (or of another word with
which the word being inflected must agree). If the "number" argument is
supplied and is not 1 (or `"one"' or `"a"', or some other adjective that
implies the singular), the plural form of the word is returned. If the
"number" argument *does* indicate singularity, the (uninflected) word
itself is returned. If the number argument is omitted, the plural form is
returned unconditionally.

   The various subroutines are:

`PL_N($;$)'
     The exportable subroutine `PL_N()' takes a *singular* English noun or
     pronoun and returns its plural. Pronouns in the nominative ("I" ->
     "we") and accusative ("me" -> "us") cases are handled, as are
     possessive pronouns ("mine" -> "ours").

`PL_V($;$)'
     The exportable subroutine `PL_V()' takes the *singular* form of a
     conjugated verb (that is, one which is already in the correct "person"
     and "mood") and returns the corresponding plural conjugation.

`PL_ADJ($;$)'
     The exportable subroutine `PL_ADJ()' takes the *singular* form of
     certain types of adjectives and returns the corresponding plural form.
     Adjectives that are correctly handled include: "numerical" adjectives
     ("a" -> "some"), demonstrative adjectives ("this" -> "these", "that"
     -> "those"), and possessives ("my" -> "our", "cat's" -> "cats'",
     "child's" -> "childrens'", etc.)

`PL($;$)'
     The exportable subroutine `PL()' takes a *singular* English noun,
     pronoun, verb, or adjective and returns its plural form. Where a word
     has more than one inflection depending on its part of speech (for
     example, the noun "thought" inflects to "thoughts", the verb "thought"
     to "thought"), the (singular) noun sense is preferred to the
     (singular) verb sense.

     Hence `PL("knife")' will return "knives" ("knife" having been treated
     as a singular noun), whereas `PL("knifes")' will return "knife"
     ("knifes" having been treated as a 3rd person singular verb).

     The inherent ambiguity of such cases suggests that, where the part of
     speech is known, `PL_N', `PL_V', and `PL_ADJ' should be used in
     preference to `PL'.

   Note that all these subroutines ignore any whitespace surrounding the
word being inflected, but preserve that whitespace when the result is
returned. For example, `PL(" cat  ")' returns " cats  ".

Numbered plurals
----------------

   The `PL_...' subroutines return only the inflected word, not the count
that was used to inflect it. Thus, in order to produce "I saw 3 ducks", it
is necessary to use:

     print "I saw $N ", PL_N($animal,$N), "\n";

   Since the usual purpose of producing a plural is to make it agree with
a preceding count, Lingua::EN::Inflect provides an exportable subroutine
(`NO($;$)') which, given a word and a(n optional) count, returns the count
followed by the correctly inflected word. Hence the previous example can
be rewritten:

     print "I saw ", NO($animal,$N), "\n";

   In addition, if the count is zero (or some other term which implies
zero, such as `"zero"', `"nil"', etc.) the count is replaced by the word
"no". Hence, if `$N' had the value zero, the previous example would print
the somewhat more elegant:

     I saw no animals

   rather than:

     I saw 0 animals

   Note that the name of the subroutine is a pun: the subroutine returns
either a number (a *No.*) or a "no", in front of the inflected word.

Reducing the number of counts required
--------------------------------------

   In some contexts, the need to supply an explicit count to the various
`PL_...' subroutines makes for tiresome repetition. For example:

     print PL_ADJ("This",$errors), PL_N(" error",$errors),
           PL_V(" was",$errors), " fatal.\n";

   Lingua::EN::Inflect therefore provides an exportable subroutine
(`NUM($;$)') which may be used to set a persistent "default number" value.
If such a value is set, it is subsequently used whenever an optional
second "number" argument is omitted. The default value thus set can
subsequently be removed by calling `NUM()' with no arguments.  Hence we
could rewrite the previous example:

     NUM($errors);
     print PL_ADJ("This"), PL_N(" error"), PL_V(" was"), "fatal.\n";
     NUM();

   Normally, `NUM()' returns its first argument, so that it may also be
"inlined" in contexts like:

     print NUM($errors), PL_N(" error"), PL_V(" was"), " detected.\n"
     print PL_ADJ("This"), PL_N(" error"), PL_V(" was"), "fatal.\n"
     	if $severity > 1;

   However, in certain contexts (see `"INTERPOLATING INFLECTIONS IN
STRINGS"' in this node) it is preferable that `NUM()' return an empty
string. Hence `NUM()' provides an optional second argument. If that
argument is supplied (that is, if it is defined) and evaluates to false,
`NUM' returns an empty string instead of its first argument. For example:

     print NUM($errors,0), NO("error"), PL_V(" was"), " detected.\n";
     print PL_ADJ("This"), PL_N(" error"), PL_V(" was"), "fatal.\n"
     	if $severity > 1;

Number-insensitive equality
---------------------------

   Lingua::EN::Inflect also provides a solution to the problem of
comparing words of differing plurality through the exportable subroutines
`PL_eq($$)', `PL_N_eq($$)', `PL_V_eq($$)', and `PL_ADJ_eq($$)'.  Each  of
these subroutines takes two strings, and  compares them using the
corresponding plural-inflection subroutine (`PL()', `PL_N()', `PL_V()',
and `PL_ADJ()' respectively).

   The comparison returns true if:

   * the strings are eq-equal, or

   * one string is eq-equal to a plural form of the other, or

   * the strings are two different plural forms of the one word.

   Hence all of the following return true:

     PL_eq("index","index")		# RETURNS "eq"
     PL_eq("index","indexes")	# RETURNS "s:p"
     PL_eq("index","indices")	# RETURNS "s:p"
     PL_eq("indexes","index")	# RETURNS "p:s"
     PL_eq("indices","index")	# RETURNS "p:s"
     PL_eq("indices","indexes")	# RETURNS "p:p"
     PL_eq("indexes","indices")	# RETURNS "p:p"
     PL_eq("indices","indices")	# RETURNS "eq"

   As indicated by the comments in the previous example, the actual value
returned by the various `PL_eq_...' subroutines encodes which of the three
equality rules succeeded: "eq" is returned if the strings were identical,
"s:p" if the strings were singular and plural respectively, "p:s" for
plural and singular, and "p:p" for two distinct plurals.  Inequality is
indicated by returning an empty string.

   It should be noted that two distinct singular words which happen to take
the same plural form are not considered equal, nor are cases where one
(singular) word's plural is the other (plural) word's singular.  Hence all
of the following return false:

     PL_eq("base","basis")	    # ALTHOUGH BOTH -> "bases"
     PL_eq("syrinx","syringe")   # ALTHOUGH BOTH -> "syringes"
     PL_eq("she","he")	    # ALTHOUGH BOTH -> "they"

     PL_eq("opus","operas")	    # ALTHOUGH "opus" -> "opera" -> "operas"
     PL_eq("taxi","taxes")	    # ALTHOUGH "taxi" -> "taxis" -> "taxes"

   Note too that, although the comparison is "number-insensitive" it is not
case-insensitive (that is, `PL("time","Times")' returns false. To obtain
both number and case insensitivity, prefix both arguments with lc (that
is, `PL(lc "time", lc "Times")' returns true).

OTHER VERB FORMS
================

Present participles
-------------------

   `Lingua::EN::Inflect' also provides the `PART_PRES' subroutine, which
can take a 3rd person singular verb and correctly inflect it to its
present participle:

     PART_PRES("runs")	# "running"
     PART_PRES("loves")	# "loving"
     PART_PRES("eats")	# "eating"
     PART_PRES("bats")	# "batting"
     PART_PRES("spies")	# "spying"

PROVIDING INDEFINITE ARTICLES
=============================

Selecting indefinite articles
-----------------------------

   Lingua::EN::Inflect provides two exportable subroutines (`A($;$)' and
`AN($;$)') which will correctly prepend the appropriate indefinite article
to a word, depending on its pronunciation. For example:

     A("cat")		# -> "a cat"
     AN("cat")		# -> "a cat"
     A("euphemism")		# -> "a euphemism"
     A("Euler number")	# -> "an Euler number"
     A("hour")		# -> "an hour"
     A("houri")		# -> "a houri"

   The two subroutines are *identical* in function and may be used
interchangeably. The only reason that two versions are provided is to
enhance the readability of code such as:

     print "That is ", AN($errortype), " error\n;
     print "That is ", A($fataltype), " fatal error\n;

   Note that in both cases the actual article provided depends *only* on
the pronunciation of the first argument, not on the name of the subroutine.

   `A()' and `AN()' both take an optional second argument. As with the
`PL_...' subroutines, this second argument is a "number" specifier. If its
value is 1 (or some other value implying singularity), `A()' and `AN()'
insert "a" or "an" as appropriate. If the number specifier implies
plurality, (`A()' and `AN()' insert the actual second argument instead.
For example:

     A("cat",1)		# -> "a cat"
     A("cat",2)		# -> "2 cat"
     A("cat","one")		# -> "one cat"
     A("cat","no")		# -> "no cat"

   Note that, as implied by the previous examples, `A()' and `AN()' both
assume that their job is merely to provide the correct qualifier for a
word (that is: "a", "an", or the specified count).  In other words, they
assume that the word they are given has already been correctly inflected
for plurality. Hence, if `$N' has the value 2, then:

     print A("cat",$N);

   prints "2 cat", instead of "2 cats". The correct approach is to use:

     print A(PL("cat",$N),$N);

   or, better still:

     print NO("cat",$N);

   Note too that, like the various `PL_...' subroutines, whenever `A()'
and `AN()' are called with only one argument they are subject to the
effects of any preceding call to `NUM()'. Hence, another possible solution
is:

     NUM($N);
     print A(PL("cat"));

Indefinite articles and initialisms
-----------------------------------

   "Initialisms" (sometimes inaccurately called "acronyms") are terms which
have been formed from the initial letters of words in a phrase (for
example, "NATO", "NBL", "S.O.S.", "SCUBA", etc.)

   Such terms present a particular challenge when selecting between "a"
and "an", since they are sometimes pronounced as if they were a single
word ("nay-tow", "sku-ba") and sometimes as a series of letter names
("en-eff-ell", "ess-oh-ess").

   `A()' and `AN()' cope with this dichotomy using a series of inbuilt
rules, which may be summarized as:

  1. If the word starts with a single letter, followed by a period or dash
     (for example, "R.I.P.", "C.O.D.", "e-mail", "X-ray", "T-square"), then
     choose the appropriate article for the sound of the first letter ("an
     R.I.P.", "a C.O.D.", "an e-mail", "an X-ray", "a T-square").

  2. If the first two letters of the word are capitals, consonants, and do
     not appear at the start of any known English word, (for example,
     "LCD", "XML", "YWCA"), then once again choose "a" or "an" depending
     on the sound of the first letter ("an LCD", "an XML", "a YWCA").

  3. Otherwise, assume the string is a capitalized word or a pronounceable
     initialism (for example, "LED", "OPEC", "FAQ", "UNESCO"), and
     therefore takes "a" or "an" according to the (apparent) pronunciation
     of the entire word ("a LED", "an OPEC", "a FAQ", "a UNESCO").

        Note that rules 1 and 3 together imply that the presence or
absence of punctuation may change the selection of indefinite article for a
particular initialism (for example, "a FAQ" but "an F.A.Q.").

Indefinite articles and "soft H's"
----------------------------------

   Words beginning in the letter 'H' present another type of difficulty
when selecting a suitable indefinite article. In a few such words (for
example, "hour", "honour", "heir") the 'H' is not voiced at all, and so
such words inflect with "an". The remaining cases ("voiced H's") may be
divided into two categories: "hard H's" (such as "hangman", "holograph",
"hat", etc.) and "soft H's" (such as "hysterical", "horrendous", "holy",
etc.)

   Hard H's always take "a" as their indefinite article, and soft H's
normally do so as well. But some English speakers prefer "an" for soft H's
(although the practice is now generally considered an affectation, rather
than a legitimate grammatical alternative).

   At present, the `A()' and `AN()' subroutines ignore soft H's and use
"a" for any voiced 'H'. The author would, however, welcome feedback on
this decision (envisaging a possible future "soft H" mode).

INFLECTING ORDINALS
===================

   Occasionally it is useful to present an integer value as an ordinal
rather than as a numeral. For example:

     Enter password (1st attempt): ********
     Enter password (2nd attempt): *********
     Enter password (3rd attempt): *********
     No 4th attempt. Access denied.

   To this end, Lingua::EN::Inflect provides the `ORD()' subroutine.
<ORD()> takes a single argument and forms its ordinal equivalent.  If the
argument isn't a numerical integer, it just adds "-th".

CONVERTING NUMBERS TO WORDS
===========================

   The exportable subroutine `NUMWORDS' takes a number and returns an
English representation of that number. In a scalar context a string is
returned. Hence:

     use Lingua::EN::Inflect qw( NUMWORDS );

     $words = NUMWORDS(1234567);

   puts the string:

     "one million, two hundred and thirty-four thousand, five hundred and sixty-seven"

     into $words.

   In a list context each comma-separated chunk is returned as a separate
element.  Hence:

     @words = NUMWORDS(1234567);

   puts the list:

     ("one million",
      "two hundred and thirty-four thousand",
      "five hundred and sixty-seven")

   into @words.

   Non-digits (apart from an optional leading plus or minus sign and any
decimal points) are silently ignored, so the following all produce
identical results:

     NUMWORDS(5551202);
     NUMWORDS(5_551_202);
     NUMWORDS("5,551,202");
     NUMWORDS("555-1202");

   That last case is a little awkward since it's almost certainly a phone
number, and "five million, five hundred and fifty-one thousand, two
hundred and two" probably isn't what's wanted.

   To overcome this, `NUMWORDS()' takes an optional named argument,
'group', which changes how numbers are translated. The argument must be a
positive integer less than four, which indicated how the digits of the
number are to be grouped. If the argument is 1, then each digit is
translated separately. If the argument is 2, pairs of digits (starting
from the left) are grouped together. If the argument is 3, triples of
numbers (again, from the left) are grouped. Hence:

     NUMWORDS("555-1202", group=>1)

   returns `"five, five, five, one, two, zero, two"', whilst:

     NUMWORDS("555-1202", group=>2)

   returns `"fifty-five, fifty-one, twenty, two"', and:

     NUMWORDS("555-1202", group=>3)

   returns `"five fifty-five, one twenty, two"'.

   Phone numbers are often written in words as
`"five..five..five..one..two..zero..two"', which is also easy to achieve:

     join '..', NUMWORDS("555-1202", group=>1)

   `NUMWORDS' also handles decimal fractions. Hence:

     NUMWORDS("1.2345")

   returns `"one point two three four five"' in a scalar context and
`("one","point","two","three","four","five")') in an array context.
Exponent form (`"1.234e56"') is not yet handled.

   Multiple decimal points are only translated in one of the "grouping"
modes.  Hence:

     NUMWORDS(101.202.303)

   returns `"one hundred and one point two zero two three zero three"',
whereas:

     NUMWORDS(101.202.303, group=>1)

   returns `"one zero one point two zero two point three zero three"'.

   The digit `'0'' is unusual in that in may be translated to English as
"zero", "oh", or "nought". To cater for this diversity, `NUMWORDS' may be
passed a named argument, 'zero', which may be set to the desired
translation of `'0''. For example:

     print join "..", NUMWORDS("555-1202", group=>3, zero=>'oh')

   prints `"five..five..five..one..two..oh..two"'.  By default, zero is
rendered as "zero".

   Another major regional variation in number translation is the use of
"and" in certain contexts. The named argument 'and' allows the programmer
to specify how "and" should be handled. Hence:

     print scalar NUMWORDS("765", 'and'=>'')

   prints "seven hundred sixty-five", instead of "seven hundred and
sixty-five".  By default, the "and" is included.

   The translation of the decimal point is also subject to variation (with
"point", "dot", and "decimal" being the favorites).  The named argument
'decimal' allows the programmer to how the decimal point should be
rendered. Hence:

     print scalar NUMWORDS("666.124.64.101", group=>3, decimal=>'dot')

   prints "six sixty-six, dot, one twenty-four, dot, sixty-four, dot, one
zero one" By default, the decimal point is rendered as "point".

INTERPOLATING INFLECTIONS IN STRINGS
====================================

   By far the commonest use of the inflection subroutines is to produce
message strings for various purposes. For example:

     print NUM($errors), PL_N(" error"), PL_V(" was"), " detected.\n";
     print PL_ADJ("This"), PL_N(" error"), PL_V(" was"), "fatal.\n"
     	if $severity > 1;

   Unfortunately the need to separate each subroutine call detracts
significantly from the readability of the resulting code. To ameliorate
this problem, Lingua::EN::Inflect provides an exportable
string-interpolating subroutine (`inflect($)'), which recognizes calls to
the various inflection subroutines within a string and interpolates them
appropriately.

   Using `inflect' the previous example could be rewritten:

     print inflect "NUM($errors) PL_N(error) PL_V(was) detected.\n";
     print inflect "PL_ADJ(This) PL_N(error) PL_V(was) fatal.\n"
     	if $severity > 1;

   Note that `inflect' also correctly handles calls to the `NUM()'
subroutine (whether interpolated or antecedent). The `inflect()'
subroutine has a related extra feature, in that it *automatically* cancels
any "default number" value before it returns its interpolated string. This
means that calls to `NUM()' which are embedded in an
`inflect()'-interpolated string do not "escape" and interfere with
subsequent inflections.

MODERN VS CLASSICAL INFLECTIONS
===============================

   Certain words, mainly of Latin or Ancient Greek origin, can form
plurals either using the standard English "-s" suffix, or with their
original Latin or Greek inflections. For example:

     PL("stigma")		# -> "stigmas" or "stigmata"
     PL("torus")		# -> "toruses" or "tori"
     PL("index")		# -> "indexes" or "indices"
     PL("millennium")	# -> "millenniums" or "millennia"
     PL("ganglion")		# -> "ganglions" or "ganglia"
     PL("octopus")		# -> "octopuses" or "octopodes"

   Lingua::EN::Inflect caters to such words by providing an "alternate
state" of inflection known as "classical mode".  By default, words are
inflected using their contemporary English plurals, but if classical mode
is invoked, the more traditional plural forms are returned instead.

   The exportable subroutine `classical()' controls this feature.  If
`classical()' is called with no arguments, it unconditionally invokes
classical mode. If it is called with an argument, it invokes classical
mode only if that argument evaluates to true.  If the argument is false,
classical mode is switched off. Thus:

     classical;		# SWITCH ON CLASSICAL MODE
     print PL("formula");	# -> "formulae"

     classical 0;		# SWITCH OFF CLASSICAL MODE
     print PL("formula");	# -> "formulas"

     classical $cmode;	# CLASSICAL MODE IFF $cmode
     print PL("formula");	# -> "formulae" (IF $cmode)
     			# -> "formulas" (OTHERWISE)

   Note however that `classical()' has no effect on the inflection of
words which are now fully assimilated. Hence:

     PL("forum")		# ALWAYS -> "forums"
     PL("criterion")		# ALWAYS -> "criteria"

USER-DEFINED INFLECTIONS
========================

Adding plurals at run-time
--------------------------

   Lingua::EN::Inflect provides five exportable subroutines which allow
the programmer to override the module's behaviour for specific cases:

`def_noun($$)'
     The `def_noun' subroutine takes a pair of string arguments: the
     singular and plural forms of the noun being specified. The singular
     form specifies a pattern to be interpolated (as
     `m/^(?:$first_arg)$/i').  Any noun matching this pattern is then
     replaced by the string in the second argument. The second argument
     specifies a string which is interpolated after the match succeeds,
     and is then used as the plural form. For example:

          def_noun  'cow'        => 'kine';
          def_noun  '(.+i)o'     => '$1i';
          def_noun  'spam(mer)?' => '\\$\\%\\@#\\$\\@#!!';

     Note that both arguments should usually be specified in single quotes,
     so that they are not interpolated when they are specified, but later
     (when words are compared to them). As indicated by the last example,
     care also needs to be taken with certain characters in the second
     argument, to ensure that they are not unintentionally interpolated
     during comparison.

     The second argument string may also specify a second variant of the
     plural form, to be used when "classical" plurals have been requested.
     The beginning of the second variant is marked by a '|' character:

          def_noun  'cow'	     => 'cows|kine';
          def_noun  '(.+i)o'     => '$1os|$1i';
          def_noun  'spam(mer)?' => '\\$\\%\\@#\\$\\@#!!|varmints';

     If no classical variant is given, the specified plural form is used in
     both normal and "classical" modes.

     If the second argument is undef instead of a string, then the current
     user definition for the first argument is removed, and the standard
     plural inflection(s) restored.

     Note that in all cases, later plural definitions for a particular
     singular form replace earlier definitions of the same form. For
     example:

          # FIRST, HIDE THE MODERN FORM....
          def_noun  'aviatrix' => 'aviatrices';

          # LATER, HIDE THE CLASSICAL FORM...
          def_noun  'aviatrix' => 'aviatrixes';

          # FINALLY, RESTORE THE DEFAULT BEHAVIOUR...
          def_noun  'aviatrix' => undef;

     Special care is also required when defining general patterns and
     associated specific exceptions: put the more specific cases after the
     general pattern. For example:

          def_noun  '(.+)us' => '$1i';	# EVERY "-us" TO "-i"
          def_noun  'bus'    => 'buses';	# EXCEPT FOR "bus"

     This "try-most-recently-defined-first" approach to matching
     user-defined words is also used by `def_verb', `def_a' and `def_an'.

`def_verb($$$$$$)'
     The `def_verb' subroutine takes three pairs of string arguments (that
     is, six arguments in total), specifying the singular and plural forms
     of the three "persons" of verb. As with `def_noun', the singular
     forms are specifications of run-time-interpolated patterns, whilst
     the plural forms are specifications of (up to two)
     run-time-interpolated strings:

          def_verb 'am'       => 'are',
          		'are'      => 'are|art",
          		'is'       => 'are';

          def_verb 'have'     => 'have',
          		'have'     => 'have",
          		'ha(s|th)' => 'have';

     Note that as with `def_noun', modern/classical variants of plurals
     may be separately specified, subsequent definitions replace previous
     ones, and undef'ed plural forms revert to the standard behaviour.

`def_adj($$)'
     The `def_adj' subroutine takes a pair of string arguments, which
     specify the singular and plural forms of the adjective being defined.
     As with `def_noun' and `def_adj', the singular forms are
     specifications of run-time-interpolated patterns, whilst the plural
     forms are specifications of (up to two) run-time-interpolated strings:

          def_adj  'this'     => 'these',
          def_adj  'red'      => 'red|gules',

     As previously, modern/classical variants of plurals may be separately
     specified, subsequent definitions replace previous ones, and undef'ed
     plural forms revert to the standard behaviour.

`def_a($)' and `def_an($)'
     The `def_a' and `def_an' subroutines each take a single argument,
     which specifies a pattern. If a word passed to `A()' or `AN()'
     matches this pattern, it will be prefixed (unconditionally) with the
     corresponding indefinite article. For example:

          def_a  'error';
          def_a  'in.+';

          def_an 'mistake';
          def_an 'error';

     As with the other `def_...' subroutines, such redefinitions are
     sequential in effect so that, after the above example, "error" will
     be inflected with "an".

The `$HOME/.inflectrc' file
---------------------------

   When it is imported, Lingua::EN::Inflect executes (as Perl code) the
contents of any file named `.inflectrc' which it finds in the in the
directory where `Lingua/EN/Inflect.pm' is installed, or in the current
home directory (`$ENV{HOME}'), or in both.  Note that the code is executed
within the Lingua::EN::Inflect namespace.

   Hence the user or the local Perl guru can make appropriate calls to
`def_noun', `def_verb', etc. in one of these `.inflectrc' files, to
permanently and universally modify the behaviour of the module. For example

     > cat /usr/local/lib/perl5/Text/Inflect/.inflectrc

     def_noun  "UNIX"  => "UN*X|UNICES";

     def_verb  "teco"  => "teco",	# LITERALLY: "to edit with TECO"
     	  	"teco"  => "teco",
     	  	"tecos" => "teco";

     def_a     "Euler.*";		# "Yewler" TURNS IN HIS GRAVE

   Note that calls to the `def_...' subroutines from within a program will
take precedence over the contents of the home directory `.inflectrc' file,
which in turn takes precedence over the system-wide `.inflectrc' file.

DIAGNOSTICS
===========

   On loading, if the Perl code in a `.inflectrc' file is invalid
(syntactically or otherwise), an appropriate fatal error is issued.  A
common problem is not ending the file with something that evaluates to
true (as the five `def_...' subroutines do).

   Using the five `def_...' subroutines directly in a program may also
result in fatal diagnostics, if a (singular) pattern or an interpolated
(plural) string is somehow invalid.

   Specific diagnostics related to user-defined inflections are:

`"Bad user-defined singular pattern:\n\t %s"'
     The singular form of a user-defined noun or verb (as defined by a
     call to `def_noun', `def_verb', `def_adj', `def_a' or `def_an') is
     not a valid Perl regular expression. The actual Perl error message is
     also given.

`"Bad user-defined plural string: '%s'"'
     The plural form(s) of a user-defined noun or verb (as defined by a
     call to `def_noun', `def_verb' or `def_adj') is not a valid Perl
     interpolated string (usually because it interpolates some undefined
     variable).

`"Bad .inflectrc file (%s):\n %s"'
     Some other problem occurred in loading the named local or global
     `.inflectrc' file. The Perl error message (including the line number)
     is also given.

   There are no diagnosable run-time error conditions for the actual
inflection subroutines, except `NUMWORDS' and hence no run-time
diagnostics. If the inflection subroutines are unable to form a plural via
a user-definition or an inbuilt rule, they just "guess" the commonest
English inflection: adding "-s" for nouns, removing "-s" for verbs, and no
inflection for adjectives.

   `Lingua::EN::Inflect::NUMWORDS()' can die with the following messages:

`"Bad grouping option: %s"'
     The optional argument to `NUMWORDS()' wasn't 1, 2 or 3.

`"Number out of range"'
     `NUMWORDS()' was passed a number larger than
     999,999,999,999,999,999,999,999,999,999,999,999 (that is: nine hundred
     and ninety-nine decillion, nine hundred and ninety-nine nonillion,
     nine hundred and ninety-nine octillion, nine hundred and ninety-nine
     septillion, nine hundred and ninety-nine sextillion, nine hundred and
     ninety-nine quintillion, nine hundred and ninety-nine quadrillion,
     nine hundred and ninety-nine trillion, nine hundred and ninety-nine
     billion, nine hundred and ninety-nine million, nine hundred and
     ninety-nine thousand, nine hundred and ninety-nine :-)

     The problem is that `NUMWORDS' doesn't know any words for number
     components bigger than "decillion".

OTHER ISSUES
============

2nd Person precedence
---------------------

   If a verb has identical 1st and 2nd person singular forms, but
different 1st and 2nd person plural forms, then when its plural is
constructed, the 2nd person plural form is always preferred.

   The author is not currently aware of any such verbs in English, but is
not quite arrogant enough to assume *ipso facto* that none exist.

Nominative precedence
---------------------

   The singular pronoun "it" presents a special problem because its plural
form can vary, depending on its "case". For example:

     It ate my homework	 ->  They ate my homework
             It ate it		 ->  They ate them
     I fed my homework to it	 ->  I fed my homework to them

   As a consequence of this ambiguity, `PL()' or `PL_N' have been
implemented so that they always return the *nominative* plural (that is,
"they").

   However, when asked for the plural of an unambiguously *accusative*
"it" (namely, `PL("to it")', `PL_N("from it")', `PL("with it")', etc.),
both subroutines will correctly return the accusative plural ("to them",
"from them", "with them", etc.)

The plurality of zero
---------------------

   The rules governing the choice between:

     There were no errors.

   and

     There was no error.

   are complex and often depend more on *intent* rather than content.
Hence it is infeasible to specify such rules algorithmically.

   Therefore, Lingua::EN::Text contents itself with the following
compromise: If the governing number is zero, inflections always return the
plural form unless "classical" inflections are in effect, in which case the
singular form is always returned.

   Thus, the sequence:

     NUM(0);
     print inflect "There PL(was) NO(choice)";

   produces "There were no choices", unless `classical(1)' has been
called, in which case it will print "There was no choice".

Homographs with heterogeneous plurals
-------------------------------------

   Another context in which intent (and not content) sometimes determines
plurality is where two distinct meanings of a word require different
plurals. For example:

     Three basses were stolen from the band's equipment trailer.
     Three bass were stolen from the band's aquarium.

     I put the mice next to the cheese.
     I put the mouses next to the computers.

     Several thoughts about leaving crossed my mind.
     Several thought about leaving across my lawn.

   Lingua::EN::Inflect handles such words in two ways:

   * If both meanings of the word are the *same* part of speech (for
     example, "bass" is a noun in both sentences above), then one meaning
     is chosen as the "usual" meaning, and only that meaning's plural is
     ever returned by any of the inflection subroutines.

   * If each meaning of the word is a different part of speech (for
     example, "thought" is both a noun and a verb), then the noun's plural
     is returned by `PL()' and `PL_N()' and the verb's plural is returned
     only by `PL_V()'.

   Such contexts are, fortunately, uncommon (particularly
"same-part-of-speech" examples). An informal study of nearly 600
"difficult plurals" indicates that `PL()' can be relied upon to "get it
right" about 98% of the time (although, of course, ichthyophilic
guitarists or cyber-behaviouralists may experience higher rates of
confusion).

   If the choice of a particular "usual inflection" is considered
inappropriate, it can always be reversed with a preliminary call to the
corresponding `def_...' subroutine.

AUTHORS
=======

   Damian Conway (damian@conway.org) Matthew Persico (ORD inflection)

BUGS AND IRRITATIONS
====================

   The endless inconsistencies of English.

   (Please report words for which the correct plural or indefinite article
is not formed, so that the reliability of Lingua::EN::Inflect can be
improved.)

COPYRIGHT
=========

     Copyright (c) 1997-2000, Damian Conway. All Rights Reserved.
     This module is free software. It may be used, redistributed
     and/or modified under the terms of the Perl Artistic License
         (see http://www.perl.com/perl/misc/Artistic.html)

Smart matching for human names.
*******************************

NAME
====

   Lingua::EN::MatchNames - Smart matching for human names.

SYNOPSIS
========

     use Lingua::EN::MatchNames qw(matchnames);

     $score= name_eq( $firstn_0, $lastn_0, $firstn_1, $lastn_1 );

DESCRIPTION
===========

   You have two databases of person records that need to be synchronized
or matched up, but they use different keys-maybe one uses SSN and the
other uses employee id.  The only fields you have to match on are first
and last name.

   That's what this module is for.

   Just feed the first and last names to the `name_eq()' function, and it
returns undef for no possible match, and a percentage of certainty (rank)
otherwise.  The ranking system isn't very scientific, and gender isn't
considered, though it probably should be.

   The `name_eq()' function, checks for:

   * inconsistent case (MacHenry = Machenry = MACHENRY)

   * inconsistent symbols (O'Brien = Obrien = O BRIEN)

   * misspellings (Grene = Green)

   * last name hyphenation (Smith-Curry = Curry)

   * similar phonetics (Hanson = Hansen)

   * nicknames (Midge = Peggy = Margaret)

   * extraneous initials (H. Ross = Ross)

   * extraneous suffixes (Reed, Jr. = Reed II = Reed)

   * and more...

Preliminary Tests:
------------------

     Homer Simpson HOMER SIMPOSN: 77
     Marge Simpson MIDGE SIMPSON: 81
     Brian Lalonde BRYAN LA LONDE: 82
     Brian Lalonde RYAN LALAND: 72
     Peggy MacHenry Midge Machenry: 81
     Liz Grene Elizabeth Green: 72
     Chuck Reed, Jr. Charles Reed II: 82
     Kathy O'Brien Catherine Obrien: 81
     Lizzie Hanson Lisa Hanson: 91
     H. Ross Perot Ross PEROT: 88
     Kathy Smith-Curry KATIE CURRY: 81
     Dina Johnson-Warner Dinah J-Warner: 80
     Leela Miles-Conrad Leela MilesConrad: 86
     C. Renee Smythe Cathy Smythe: 71
     Victoria (Honey) Rider HONEY RIDER: 88
     Bart Simpson El Barto Simpson: 80
     Bart Simpson Lisa Simpson: (no match)
     Arthur Dent Zaphod Beeblebrox: (no match)

WARNING
=======

   The scoring in this version is utterly arbitrary.  I made all of the
numbers up.  The certainty percentages should be OK relative to each
other, but would be better if someone could give me some statistical data.

   Be sure and test this against your data first!  Your data may not look
like my test data.

   And although I hope this is useful to many, I do not provide any kind
of warranty (expressed or implied), and do not suggest the suitability of
this module to any particular purpose.  This module probably should not be
used for life support or military purposes, and it must not be used for
unsolicited commercial email or other bulk advertising.

AUTHOR
======

   Brian Lalonde, <brianl@sd81.k12.wa.us>

REQUIREMENTS
============

   Lingua::EN::NameParse, Lingua::EN::Nickname, Parse::RecDescent,
String::Approx, Text::Metaphone, Text::Soundex

SEE ALSO
========

   perl(1), see Lingua/EN/NameParse,
Lingua/EN/Nickname, String/Approx,
see Text/Metaphone, Text/Soundex,

Perl module to fix the case of people's names.
**********************************************

NAME
====

   NameCase - Perl module to fix the case of people's names.

SYNOPSIS
========

     # Working with scalars; complementing lc and uc.

     use Lingua::EN::NameCase qw( nc ) ;

     $FixedCasedName  = nc( $OriginalName ) ;

     $FixedCasedName  = nc( \$OriginalName ) ;

     # Working with arrays or array references.

     use Lingua::EN::NameCase 'NameCase' ;

     $FixedCasedName  = NameCase( $OriginalName ) ;
     @FixedCasedNames = NameCase( @OriginalNames ) ;

     $FixedCasedName  = NameCase( \$OriginalName ) ;
     @FixedCasedNames = NameCase( \@OriginalNames ) ;

     NameCase( \@OriginalNames ) ; # In-place.

     # NameCase will not change a scalar in-place, i.e.
     NameCase( \$OriginalName ) ; # WRONG: null operation.

DESCRIPTION
===========

   Forenames and surnames are often stored either wholly in UPPERCASE or
wholly in lowercase. This module allows you to convert names into the
correct case where possible.

   Although forenames and surnames are normally stored separately if they
do appear in a single string, whitespace separated, NameCase and nc deal
correctly with them.

   NameCase currently correctly name cases names which include any of the
following:     Mc, Mac, al, el, ap, da, de, delle, della, di, du, del, der,
   la, le, lo, van and von.

   It correctly deals with names which contain apostrophies and hyphens
too.

EXAMPLE FIXES
-------------

     Original            Name Case
     --------            ---------
     KEITH               Keith
     LEIGH-WILLIAMS      Leigh-Williams
     MCCARTHY            McCarthy
     O'CALLAGHAN         O'Callaghan
     ST. JOHN            St. John

   plus "son (daughter) of" etc. in various languages, e.g.:

     VON STREIT          von Streit
     VAN DYKE            van Dyke
     AP LLWYD DAFYDD     ap Llwyd Dafydd
     etc.

   plus names with roman numerals (up to 89, LXXXIX), e.g.:

     henry viii          Henry VIII
     louis xiv           Louis XIV

BUGS
====

   The module covers the rules that I know of. There are probably a lot
more rules, exceptions etc. for "Western"-style languages which could be
incorporated.

   We don't fix "ben" - for hebrew names this means son of, but it can
mean "Ben" as a name in itself or as a form of "Benjamin". However we do
fix "al" - for arabic names this means son of, even though it can also
mean "Al" as a name in itself.

   There are probably lots of exceptions and problems - but as a general
data 'cleaner' it may be all you need.

   Use Kim Ryan's NameParse.pm for any really sophisticated name parsing.

CHANGES
=======

   1998/04/20  First release.

   1998/06/25  First public release.

   1999/01/18  Second public release.

   1999/02/08  Added Mac with Mack as an exception, thanks to Kim Ryan for
this.

   1999/05/05  Copied Kim Ryan's Mc/Mac solution from his NameParse.pm and
           replaced my Mc/Mac solution with his.

   1999/05/08  nc can now use $_ as its default argument             e.g.
"$ans = nc ;" and "nc ;", both of which set $_, with the             first
one setting $ans also.

   1999/07/30  Modified for CPAN and automatic testing. Stopped using $_
as the             default argument.

   1999/08/08  Changed licence to LGPL.

   1999/09/07  Minor change to packaging for CPAN.

   1999/09/09  Renamed package Lingua::EN::NameCase.pm as per John Porter's
           (CPAN) suggestion.

   1999/11/13  Added code for names with roman numerals, thanks to David
Lynn             Rice for this suggestion. (If you need to go beyond
LXXXIX let me             know.)

   2000/11/22  Added use locale at the suggestion of Eric Kolve. It should
have 	    been there in the first place.

AUTHOR
======

   Mark Summerfield. I can be contacted as <summer@perlpress.com> - please
include the word 'namecase' in the subject line.

   Thanks to Kim Ryan <kimaryan@ozemail.com.au> for his Mc/Mac solution.

COPYRIGHT
=========

   Copyright (c) Mark Summerfield 1998-2000. All Rights Reserved.

   This module may be used/distributed/modified under the LGPL.

Lingua::EN::NameGrammar
***********************

NAME
====

   Lingua::EN::NameGrammar

DESCRIPTION
===========

   Grammar tree of personal name syntax for Lingua::EN::NameParse module.

   The grammar defined here is for use with the Parse::RecDescent module.
Note that parsing is done depth first, meaning match the shortest string
first.  To avoid premature matches, when one rule is a sub set of another
longer rule, it must appear after the longer rule. See the
Parse::RecDescent documentation for more details.

COPYRIGHT
=========

   Copyright (c) 1999-2001 Kim Ryan. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the terms of
the Perl Artistic License (see
http://www.perl.com/perl/misc/Artistic.html).

AUTHOR
======

   NameGrammar was written by Kim Ryan <kimaryan@ozemail.com.au> in 1999.

routines for manipulating a persons name
****************************************

NAME
====

   Lingua::EN::NameParse - routines for manipulating a persons name

SYNOPSIS
========

     use Lingua::EN::NameParse qw(clean case_surname);

     # optional configuration arguments
     my %args =
     (
        salutation     => 'Dear',
        sal_default    => 'Friend',
        auto_clean     => 1,
        force_case     => 1,
        lc_prefix      => 1,
        initials       => 3,
        allow_reversed => 1
     );

     my $name = new Lingua::EN::NameParse(%args);

     $error = $name->parse("MR AC DE SILVA");

     %name_comps = $name->components;
     $surname = $name_comps{surname_1}; # DE SILVA

     $correct_casing = $name->case_all; # Mr AC de Silva

     $good_name = &clean("Bad Na9me   "); # "Bad Name"

     $name->salutation; # Dear Mr de Silva

     %my_properties = $name->properties;
     $number_surnames = $my_properties{number}; # 1
     $bad_input = $my_properties{non_matching};

     $lc_prefix = 0;
     $correct_case = &case_surname("DE SILVA-MACNAY",$lc_prefix); # De Silva-MacNay

REQUIRES
========

   Perl, version 5.001 or higher and Parse::RecDescent

DESCRIPTION
===========

   This module takes as input a person or persons name in free format text
such as,

     Mr AB & M/s CD MacNay-Smith
     MR J.L. D'ANGELO
     Estate Of The Late Lieutenant Colonel AB Van Der Heiden

   and attempts to parse it. If successful, the name is broken down into
components and useful functions can be performed such as :

     converting upper or lower case values to name case (Mr AB MacNay   )
     creating a personalised greeting or salutation     (Dear Mr MacNay )
     extracting the names individual components         (Mr,AB,MacNay   )
     determining the type of format the name is in      (Mr_A_Smith     )

   If the name cannot be parsed you have the option of cleaning the name
of bad characters, or extracting any portion that was parsed and the
portion that failed.

   This module can be used for analysing and improving the quality of
lists of names.

DEFINITIONS
===========

   The following terms are used by NameParse to define the components that
can make up a name.

     Precursor   - Estate of (The Late), Right Honourable ...
     Title       - Mr, Mrs, Ms., Sir, Dr, Major, Reverend ...
     Conjunction - word to separate names or initials, such as "And"
     Initials    - 1-3 letters, each with an optional space and/or dot
     Surname     - De Silva, Van Der Heiden, MacNay-Smith, O'Reilly ...
     Suffix      - Senior, Jnr, III, V ...

   Refer to the component grammar defined within the code for a complete
list of combinations.

   'Name casing' refers to the correct use of upper and lower case letters
in peoples names, such as Mr AB McNay.

   To describe the formats supported by NameParse, a short hand
representation of the name is used. The following formats are currently
supported :

     Mr_A_Smith_&_Ms_B_Jones
     Mr_&_Ms_A_&_B_Smith
     Mr_A_&_Ms_B_Smith
     Mr_&_Ms_A_Smith
     Mr_A_&_B_Smith
     Mr_John_A_Smith
     Mr_John_Smith
     Mr_A_Smith
     John_Adam_Smith
     John_A_Smith
     John_Smith
     A_Smith

   Precursors are only applied to the Mr_John_A_Smith, Mr_John_Smith,
John_Adam_Smith, Mr_A_Smith, Mr_John_Smith, John_Smith and A_Smith formats.

   Suffixes are only applied to the Mr_John_A_Smith,Mr_John_Smith,
Mr_A_Smith, John_Adam_Smith, John_A_Smith and John_Smith formats.

METHODS
=======

new
---

   The new method creates an instance of a name object and sets up the
grammar used to parse names. This must be called before any of the
following methods are invoked. Note that the object only needs to be
created ONCE, and can be reused with new input data. Calling new
repeatedly will significantly slow your program down.

   Various setup options may be defined in a hash that is passed as an
optional argument to the new method. Note that all the arguments are
optional. You need to define the combination of arguments that are
appropriate for your usage.

     my %args =
     (
        salutation     => 'Dear',
        sal_default    => 'Friend',
        auto_clean     => 1,
        force_case     => 1,
        lc_prefix      => 1,
        initials       => 3,
        allow_reversed => 1
     );

     my $name = new Lingua::EN::NameParse(%args);

     =item salutation

   The option defines the salutation word, such as "Dear" or "Greetings".
It must be defined if you are planning to use the salutation method.

sal_default
     This option defines the defaulting word to substitute for the title
     and surname(s), when parsing fails to identify them. It is also used
     when a precursor occurs. Examples are "Friend" or "Member". It must
     be defined if you are planning to use the salutation method. If an
     '&' or 'and' occurs in the unmatched section then it is assumed that
     we are dealing with more than one person, and an 's' is appended to
     the defaulting word.

force_case
     This option will force the case_all method to name case the entire
     input string, including any unmatched sections that failed parsing.
     For example, in "MR A JONES & ASSOCIATES", "& ASSOCIATES" will also
     be name cased. The casing rules for unmatched sections are the same
     as for surnames. This is usually the best option, although any
     initials in the unmatched section will not be correctly cased. This
     option is useful when you know you data has invalid names, but you
     cannot filter out or reject them.

auto_clean
     When this option is set to a positive value, any call to the parse
     method that fails will attempt to 'clean' the name and then reparse
     it. See the clean method for details. This is useful for dirty data
     with embedded unprintable or non alphabetic characters.

     =item lc_prefix

     When this option is set to a positive value, it will force the
     case_all and `case_component' methods to lower case the first letter
     of each word that occurs in the prefix portion of a surname. For
     example, Mr AB de Silva, or Ms AS von der Heiden.

initials
     Allows the user to control the number of letters that can occur in
     the initials.  Valid settings are 1,2 or 3. If no value is supplied a
     default of 2 is used.

allow_reversed
     When this option is set to a positive value, names in reverse order
     will be processed. The only valid format is the surname followed by a
     comma and the rest of the name, which can be in any of the
     combinations allowed by non reversed names. Some examples are:

     Smith, Mr AB Jones, Jim De Silva, Professor A.B.

     The program change the order of the name back to the non reversed
     format, and then performs the normal parsing. Note that if the name
     can be parsed, the fact that it's order was originally reversed, is
     not recorded as a property of the name object.

parse
-----

     $error = $name->parse("MR AC DE SILVA");

   The parse method takes a single parameter of a text string containing a
name. It attempts to parse the name and break it down into the components
described above. If the name was parsed successfully, a 0 is returned,
otherwise a 1. This step is a prerequisite for the following functions.

case_all
--------

     $correct_casing = $name->case_all;

   The case_all method converts the first letter of each component to
capitals and the remainder to lower case, with the following exceptions-

     initials remain capitalised
     surname spelling such as MacNay-Smith, O'Brien and Van Der Heiden are preserved
     - see C<surname_prefs.txt> for user defined exceptions

   A complete definition of the capitalising rules can be found by studying
the component grammar defined within the code.

   The method returns the entire cased name as text.

case_components
---------------

     %my_name = $name->components;
     $cased_surname = $my_name{surname_1};

   The case_components method does the same thing as the case_all method,
but returns the name cased components in a hash. The following keys are
used for each component-

     precursor
     title_1
     title_2
     given_name_1
     initials_1
     initials_2
     middle_name
     conjunction_1
     conjunction_2
     surname_1
     surname_2
     suffix

   Entries only occur in the hash for each component that the currently
parsed name contains, meaning there are no keys with undefined values.

components
----------

     %name = $name->components;
     $surname = $my_name{surname_1};

   The components method does the same thing as the case_components method,
but each component is returned as it appears in the input string, with no
case conversion.

case_surname
------------

     $correct_casing = &case_surname("DE SILVA-MACNAY" [,$lc_prefix]);

   case_surname is a stand alone function that does not require a name
object. The input is a text string and the output is a string converted to
the correct casing for surnames. An optional argument controls the casing
rules for prefix portions of a surname, as described above in the
`lc_prefix' section.

   See surname_prefs.txt for user defined exceptions

   This function is useful when you know you are only dealing with names
that do not have initials like "Mr John Jones". It is much faster than the
case_all method, but does not understand context, and cannot detect errors
on strings that are not personal names.

surname_prefs.txt
-----------------

   Some surnames can have more than one form of valid capitalisation, such
as MacQuarie or Macquarie. Where the user wants to specify one form as the
default, a text file called surname_prefs.txt should be created and placed
in the same location as the NameParse module. The text file should contain
one surname per line, in the capitalised form you want, such as

     Macquarie
     MacHado

     NameParse will still operate if the file does not exist

salutation
----------

   The salutation method converts a name into a personal greeting, such as
"Dear Mr & Mrs O'Brien".

   If an error is detected during parsing, such as with the name "AB Smith
& Associates", the title (if it occurs) and the surname(s) are replaced
with a default word like "Friend" or "Member". If the input string
contains a conjunction, an 's' is added to the default.

   If the name contains a precursor, a default salutation is also produced.

clean
-----

     $good_name = &clean("Bad Na9me");

   clean is a stand alone function that does not require a name object.
The input is a text string and the output is the string with:

     all repeating spaces removed
     all characters not in the set (A-Z a-z - ' , . &) removed

properties
----------

   The properties method returns all the properties of the name,
non_matching, number and type, as a hash.

type
     The type of format a name is in, as one of the following strings:

          Mr_A_Smith_&_Ms_B_Jones
          Mr_&_Ms_A_&_B_Smith
          Mr_A_&_Ms_B_Smith
          Mr_&_Ms_A_Smith
          Mr_A_&_B_Smith
          Mr_John_A_Smith
          Mr_John_Smith
          Mr_A_Smith
          John_Adam_Smith
          John_A_Smith
          John_Smith
          A_Smith
          unknown

          =item non_matching

     Returns any unmatched section that was found.

LIMITATIONS
===========

   The huge number of character combinations that can form a valid names
makes it is impossible to correctly identify them all. Firstly, there are
many ambiguities, which have no right answer.

     Macbeth or MacBeth, are both valid spellings
     Is ED WOOD E.D. Wood or Edward Wood
     Is 'Mr Rapid Print' a name or a company

   One approach is to have large lookup files of names and words,
statistical rules and fuzzy logic to attempt to derive context. This
approach gives high levels of accuracy but uses a lot of your computers
time and resources.

   NameParse takes the approach of using a limited set of rules, based on
the formats that are commonly used by business to represent peoples names.
This gives us fairly high accuracy, with acceptable speed and program size.

   NameParse will accept names from many countries, like Van Der Heiden,
De La Mare and Le Fontain. Having said that, it is still biased toward
English, because the precursors, titles and conjunctions are based on
English usage.

   Names with two or more words, but no separating hyphen are not
recognized.  This is a real quandary as Indian, Chinese and other names
can have several components. If these are allowed for, any component after
the surname will also be picked up. For example in "Mr AB Jones Trading As
Jones Pty Ltd" will return a surname of "Jones Trading".

   Because of the large combination of possible names defined in the
grammar, the program is not very fast, except for the more limited
case_surname subroutine.  See the "Future Directions" section for possible
speed ups.

REFERENCES
==========

   "The Wordsworth Dictionary of Abbreviations & Acronyms" (1997)

   Australian Standard AS4212-1994 "Geographic Information Systems - Data
Dictionary for transfer of street addressing information"

FUTURE DIRECTIONS
=================

     Add filtering of very long names
     Add diagnostic messages explaining why parsing failed
     Add transforming methods to do things like remove dots from initials
     Try to derive gender (Mr... is male, Ms, Mrs... is female)

   Let the user select what level of complexity of grammar they need for
their data. For example, if you know most of your names are in a "John
Smith" format, you can avoid the ambiguity between two letter given names
and initials. Using a limited grammar subset will also be much faster.

   Define grammar for other languages. Hopefully, all that would be needed
is to specify a new module with its own grammar, and inherit all the
existing methods. I don't have the knowledge of the naming conventions for
non-english languages.

SEE ALSO
========

   Lingua::EN::AddressParse Lingua::EN::MatchNames Lingua::EN::NickNames
Lingua::EN::NameCase Parse::RecDescent

TO DO
=====

   Add regression tests for all combinations of each component

BUGS
====

COPYRIGHT
=========

   Copyright (c) 1999-2001 Kim Ryan. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the terms of
the Perl Artistic License (see
http://www.perl.com/perl/misc/Artistic.html).

AUTHOR
======

   NameParse was written by Kim Ryan <kimaryan@ozemail.com.au> in 1999.
Thanks to all the people who provided ideas and suggestions, including -

     QM Industries <http://www.qmi.com.au>
     Damian Conway <damian@cs.monash.edu.au> author of Parse::RecDescent
     <mark.summerfield@chest.ac.uk>, author of Lingua::EN::NameCase,
     Ron Savage <rpsavage@ozemail.com.au>
     <alastair@calliope.demon.co.uk>, Adam Huffman, Douglas Wilson

Genealogical nickname matching (Liz=Beth)
*****************************************

NAME
====

   Lingua::EN::Nickname - Genealogical nickname matching (Liz=Beth)

SYNOPSIS
========

     use Lingua::EN::Nickname;

     # Equivalent first names?
     $score= nickname_eq( $firstn_0, $firstn_1 );

     # Full, expanded, name(s)
     @roots= rootname( $firstn );

DESCRIPTION
===========

   Nicknames, alternate spellings, and alternate etymological derivations
make checking first name equivalence nearly impossible.  This module will
tell you that 'Maggie', 'Peg', and 'Margaret' are all probably the same
name.

SOURCES
=======

   * USGenWeb Project  `http:' in this node

   * TNGenWeb Project  `http:' in this node

   * Chesnut Family Pages  `http:' in this node

   * Ultimate Family Tree  `http:' in this node

TODO
====

   * Hire a team of experts to provide a more scientific,  statistically
     accurate Name Etymology source file.

   * Create more phoenetically-based sub-regexes.

   * Detect simple monosyllabic truncation nicknames,  be less certain
     about them, but match more.

   * Pay more attention to gender.

AUTHOR
======

   Brian Lalonde, <brianl@sd81.k12.wa.us>

SEE ALSO
========

   perl(1)

Converts numeric values into their English string equivalents.
**************************************************************

NAME
====

   Lingua::EN::Numbers - Converts numeric values into their English string
equivalents.

SYNOPSIS
========

     ## EXAMPLE 1

     use Lingua::EN::Numbers qw(American);

     $n = new Lingua::EN::Numbers(313721.23);
     if (defined $n) {
     	$s = $n->get_string;
     	print "$s\n";
     }

     ## EXAMPLE 2

     use Lingua::EN::Numbers;

     $n = new Lingua::EN::Numbers;
     $n->parse(-1281);
     print "N = " . $n->get_string . "\n";

REQUIRES
========

   Perl 5, Exporter, Carp

DESCRIPTION
===========

   Lingua::EN::Numbers converts arbitrary numbers into human-oriented
English text. Limited support is included for parsing standardly formatted
numbers (i.e. '3,213.23'). But no attempt has been made to handle any
complex formats. Support for multiple variants of English are supported.
Currently only "American" formatting is supported.

   To use the class, an instance is generated. The instance is then loaded
with a number. This can occur either during construction of the instance
or later, via a call to the parse method. The number is then analyzed and
parsed into the english text equivalent.

   The instance, now initialized, can be converted into a string, via the
*get_string* method. This method takes the parsed data and converts it
from a data structure into a formatted string. Elements of the string's
formatting can be tweaked between calls to the *get_string* function.
While such changes are unlikely, this has been done simply to provide
maximum flexability.

METHODS
=======

Creation
--------

new Lingua::EN::Numbers $numberString
     Creates, optionally initializes, and returns a new instance.

Initialization
--------------

$number->parse $numberString
     Parses a number and (re)initializes an instance.

Output
------

$number->get_string
     Returns a formatted string based on the most recent parse.

CLASS VARIABLES
===============

$Lingua::EN::Numbers::VERSION
     The version of this class.

$Lingua::EN::Numbers::MODE
     The current locale mode. Currently only *American* is supported.

%Lingua::EN::Numbers::INPUT_GROUP_DELIMITER
     The delimiter which seperates number groups.  Example:
     "1*,*321*,*323" uses the comma '*,*' as the group delimiter.

%Lingua::EN::Numbers::INPUT_DECIMAL_DELIMITER
     The delimiter which seperates the main number from its decimal part.
     Example: "132.2" uses the period '.' as the decimal delimiter.

%Lingua::EN::Numbers::OUTPUT_BLOCK_DELIMITER
     A character used at output time to convert the number into a string.
     Example: One Thousand, Two-Hundred and Twenty-Two point Four.  Uses
     the space character ' ' as the block delimiter.

%Lingua::EN::Numbers::OUTPUT_GROUP_DELIMITER
     A character used at output time to convert the number into a string.
     Example: One Thousand*,* Two-Hundred and Twenty-Two point Four.  Uses
     the comma '*,*' character as the group delimiter.

%Lingua::EN::Numbers::OUTPUT_NUMBER_DELIMITER
     A character used at output time to convert the number into a string.
     Example: One Thousand, Two-Hundred and Twenty-Two point Four.  Uses
     the dash '-' character as the number delimiter.

%Lingua::EN::Numbers::OUTPUT_DECIMAL_DELIMITER
     A character used at output time to convert the number into a string.
     Example: One Thousand, Two-Hundred and Twenty-Two point Four.  Uses
     the 'point' string as the decimal delimiter.

%Lingua::EN::Numbers::NUMBER_NAMES
     A list of names for numbers.

%Lingua::EN::Numbers::SIGN_NAMES
     A list of names for positive and negative signs.

$Lingua::EN::Numbers::SIGN_POSITIVE
     A constant indicating the the current number is positive.

$Lingua::EN::Numbers::SIGN_NEGATIVE
     A constant indicating the the current number is negative.

DIAGNOSTICS
===========

Error: Lingua::EN::Numbers does not support tag: '$tag'.
     (F) The module has been invoked with an invalid locale.

Error: bad number format: '$number'.
     (F) The number specified is not in a valid numeric format.

Error: bad number format: '.$number'.
     (F) The decimal portion of number specified is not in a valid numeric
     format.

AUTHOR
======

   Stephen Pandich, pandich@yahoo.com

Hash access to Lingua::EN::Numbers objects.
*******************************************

NAME
====

   Lingua::EN::Numbers::Easy  -  Hash access to Lingua::EN::Numbers
objects.

SYNOPSIS
========

     use Lingua::EN::Numbers::Easy;

     print "$N{1} fish, $N{2} fish, blue fish, red fish";
                          # one fish, two fish, blue fish, red fish.

DESCRIPTION
===========

   `Lingua::EN::Numbers' is a module that translates numbers to English
words. Unfortunally, it has an object oriented interface, which makes it
hard to interpolate them in strings. `Lingua::EN::Numbers::Easy'
translates numbers to words using a tied hash, which can be interpolated.

   By default, `Lingua::EN::Numbers::Easy' exports a hash `%N' to the
importing package. Also, by default, `Lingua::EN::Numbers::Easy' uses the
British mode of `Lingua::EN::Numbers'. Both defaults can be changed by
optional arguments to the `use Lingua::EN::Numbers::Easy;' statement.

   The first argument determines the parsing mode of `Lingua::EN::Numbers'.
Currently, `Lingua::EN::Numbers' supports *British* and *American*.  The
second argument determines the name of the hash in the importing package.

     use Lingua::EN::Numbers::Easy qw /American %nums/;

   would use *American* parsing mode, and `%nums' as the tied hash.

   See also the `Lingua::EN::Numbers' man page.

   `Lingua::EN::Numbers::Easy' caches results - numbers will only be
translated once.

   Any other operation on the exported hash than fetches will throw an
exception.

REVISION HISTORY
================

     $Log: Easy.pm,v $
     Revision 1.2  1999/11/07 15:17:34  abigail
     Worked around a bug (0 -> 'zero') in Lingua::EN::Numbers.

     Revision 1.1  1999/11/07 14:59:14  abigail
     Initial revision

AUTHOR
======

   This package was written by Abigail, abigail@delanet.com.

COPYRIGHT and LICENSE
=====================

   This package is copyright 1999 by Abigail.

   Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

go from cardinal number (3) to ordinal ("3rd")
**********************************************

NAME
====

   Lingua::EN::Numbers::Ordinate - go from cardinal number (3) to ordinal
("3rd")

SYNOPSIS
========

     use Lingua::EN::Numbers::Ordinate;
     print ordinate(4), "\n";
      # prints 4th
     print ordinate(-342), "\n";
      # prints -342nd

     # Example of actual use:
     ...
     for(my $i = 0; $i < @records; $i++) {
       unless(is_valid($record[$i]) {
         warn "The ", ordinate($i), " record is invalid!\n";
         next;
       }
       ...
     }

DESCRIPTION
===========

   There are two kinds of numbers in English - cardinals (1, 2, 3...), and
ordinals (1st, 2nd, 3rd...).  This library provides functions for giving
the ordinal form of a number, given its cardinal value.

FUNCTIONS
=========

ordinate(SCALAR)
     Returns a string consisting of that scalar's string form, plus the
     appropriate ordinal suffix.  Example: `ordinate(23)' returns "23rd".

     As a special case, `ordinate(undef)' and `ordinate("")' return "0th",
     not "th".

     This function is exported by default.

th(SCALAR)
     Merely an alias for `ordinate', but not exported by default.

ordsuf(SCALAR)
     Returns just the appropriate ordinal suffix for the given scalar
     numeric value.  This is what `ordinate' uses to actually do its work.
     For example, `ordsuf(3)' is "rd".

     Not exported by default.

   The above functions are all prototyped to take a scalar value, so
`ordinate(@stuff)' is the same as `ordinate(scalar @stuff)'.

CAVEATS
=======

   * Note that this library knows only about numbers, not number-words.
`ordinate('seven')' might just as well be `ordinate('superglue')' or
`ordinate("\x1E\x9A")' - you'll get the fallthru case of the input string
plus "th".

   * As is unavoidable, `ordinate(0256)' returns "174th" (because ordinate
sees the value 174). Similarly, `ordinate(1E12)' returns
"1000000000000th".  Returning "trillionth" would be nice, but that's an
awfully atypical case.

   * Note that this library's algorithm (as well as the basic concept and
implementation of ordinal numbers) is totally language specific.

   To pick a trivial example, consider that in French, 1 ordinates as
"1ier", whereas 41 ordinates as "41ieme".

STILL NOT SATISFIED?
====================

   Bored of this...?

     use Lingua::EN::Numbers::Ordinate qw(ordinate th);
     ...
     print th($n), " entry processed...\n";
     ...

   Try this bit of lunacy:

     {
       my $th_object;
       sub _th () { $th_object }

     package Lingua::EN::Numbers::Ordinate::Overloader;
     my $x; # Gotta have something to bless.
     $th_object = bless \$x; # Define the object now, which _th returns
     use Carp ();
     use Lingua::EN::Numbers::Ordinate ();
     sub overordinate {
       Carp::croak "_th should be used only as postfix!" unless $_[2];
       Lingua::EN::Numbers::Ordinate::ordinate($_[1]);
     }
     use overload '&' => \&overordinate;
       }

   Then you get to do:

     print 3 & _th, "\n";
       # prints "3rd"

     print 1 + 2 & _th, "\n";
       # prints "3rd" too!
       # Because of the precedence of & !

     print _th & 3, "\n";
       # dies with: "th should be used only as postfix!"

   Kooky, isn't it?  For more delightful deleria like this, see Damian
Conway's *Object Oriented Perl* from Manning Press.

   Kinda makes you like `th(3)', doesn't it?

COPYRIGHT
=========

   Copyright (c) 2000 Sean M. Burke.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Sean M. Burke `sburke@cpan.org'

compute English verbage from numerical values
*********************************************

NAME
====

   Nums2Words - compute English verbage from numerical values

SYNOPSIS
========

use Nums2Words;
$Verbage = &num2word($Number);
$Verbage = &num2word_ordinal($Number);
$Verbage = &num2word_short_ordinal($Number);
$Verbage = &num2usdollars($Number);
DESCRIPTION
===========

   To the best of my knowledge, this code has the potential for generating
US English verbage representative of every real value from negative
infinity to positive infinity if the module's private variables
@Classifications and @Categories are filled appropriately.  This module
generates verbage based on the thousands system.

   See http://www.quinion.demon.co.uk/words/numbers.htm for details of the
thousands system versus millions system of linguistically representing
large numbers.

   Copyright (C) 1996-1998, Lester H. Hightower, Jr.
hightowe@united-railway.com 				hightowe@progressive-comp.com
hightowe@railwayex.com

LICENSE
=======

   A license is hereby granted for anyone to reuse this Perl module in its
original, unaltered form for any purpose, including any commercial
software endeavor.  However, any modifications to this code or any
derivative work (including ports to other languages) must be submitted to
the original author, Lester H. Hightower Jr., before the modified software
or derivative work is used in any commercial application.  All
modifications or derivative works must be submitted to the author with 30
days of completion.  The author reserves the right to incorporate any
modifications or derivative work into future releases of this software.

   This software cannot be placed on a CD-ROM or similar media for
commercial distribution without the prior approval of the author.

Module for splitting text into sentences.
*****************************************

NAME
====

   Lingua::EN::Sentence - Module for splitting text into sentences.

SYNOPSIS
========

     use Lingua::EN::Sentence qw( get_sentences add_acronyms );

     add_acronyms(('lt','gen'));		## adding support for 'Lt. Gen.'
     my $sentences=get_sentences($text);	## Get the sentences.
     foreach my $sentence (@$sentences) {
     	## do something with $sentence
     }

DESCRIPTION
===========

   The `Lingua::EN::Sentence' module contains the function get_sentences,
which splits text into its constituent sentences, based on a regular
expression and a list of abbreviations (built in and given).

   Certain well know exceptions, such as abreviations, may cause incorrect
segmentations.  But some of them are already integrated into this code and
are being taken care of.  Still, if you see that there are words causing
the get_sentences() to fail, you can add those to the module, so it
notices them.

ALGORITHM
=========

   Basically, I use a 'brute' regular expression to split the text into
sentences.  (Well, nothing is yet split - I just mark the
end-of-sentence).  Then I look into a set of rules which decide when an
end-of-sentence is justified and when it's a mistake. In case of a
mistake, the end-of-sentence mark is removed.

   What are such mistakes? Cases of abbreviations, for example. I have a
list of such abbreviations (Please see `Acronym/Abbreviations list'
section), and more general rules (for example, the abbreviations 'i.e.'
and '.e.g.' need not to be in the list as a special rule takes care of all
single letter abbreviations).

FUNCTIONS
=========

   All functions used should be requested in the 'use' clause. None is
exported by default.

get_sentences( $text )
     The get sentences function takes a scalar containing ascii text as an
     argument and returns a reference to an array of sentences that the
     text has been split into.  Returned sentences will be trimmed
     (beginning and end of sentence) of white-spaces.  Strings with no
     alpha-numeric characters in them, won't be returned as sentences.

add_acronyms( @acronyms )
     This function is used for adding acronyms not supported by this code.
     Please see `Acronym/Abbreviations list' section for the
     abbreviations already supported by this module.

get_acronyms(	)
     This function will return the defined list of acronyms.

set_acronyms( @my_acronyms )
     This function replaces the predefined acroym list with the given list.

get_EOS(	)
     This function returns the value of the string used to mark the end of
     sentence. You might want to see what it is, and to make sure your
     text doesn't contain it. You can use set_EOS() to alter the
     end-of-sentence string to whatever you desire.

set_EOS( $new_EOS_string )
     This function alters the end-of-sentence string used to mark the end
     of sentences.

Acronym/Abbreviations list
==========================

   Currently supported acronym lists are:

     PEOPLE ( 'jr', 'mr', 'mrs', 'ms', 'dr', 'prof' )
     INSTITUTES ( 'dept', 'univ' )
     COMPANIES ( 'inc', 'ltd' )
     MISC ( 'vs', 'etc', 'no' )

   If I come across a good general-purpose list - I'll incorporate it into
this module.  Feel free to suggest such lists.

SEE ALSO
========

     Text::Sentence

AUTHOR
======

   Shlomo Yona <Shlomo.Yona@Siftology.com>

COPYRIGHT
=========

   Copyright (c) 2001 Siftology Inc.. All rights reserved.

   This library is free software.  You can redistribute it and/or modify
it under the same terms as Perl itself.

Shorten text to minimum syllables by using hash table and vowel deletion
************************************************************************

NAME
====

   Squeeze.pm - Shorten text to minimum syllables by using hash table and
vowel deletion

REVISION
========

   $Id: Squeeze.pm,v 1.25 1998/12/04 10:00:08 jaalto Exp $

SYNOPSIS
========

     use Squeeze.pm;	    # imnport only function
     use Squeeze qw( :ALL ); # import all functions and variables
     use English;

     while (<>)
     {
     	print SqueezeText $ARG;
     }

DESCRIPTION
===========

   Squeeze English text to most compact format possibly so that it is
barely readable. You should convert all text to lowercase for maximum
compression, because optimizations have been designed mostly fr
uncapitalised letters.

   `Warning: Each line is processed multiple times, so prepare for slow
conversion time'

   You can use this module e.g. to preprocess text before it is sent to
electronic media that has some maximum text size limit. For example pagers
have an arbitrary text size limit, typically 200 characters, which you want
to fill as much as possible. Alternatively you may have GSM cellular phone
which is capable of receiving Short Messages (SMS), whose message size
limit is 160 characters. For demonstration of this module's SqueezeText()
function , the description text of this paragraph has been converted below.
See yourself if it's readable (Yes, it takes some time to get used to). The
compress ratio is typically 30-40%

     u _n use thi mod e.g. to prprce txt bfre i_s snt to
     elrnic mda has som max txt siz lim. f_xmple pag
     hv  abitry txt siz lim, tpcly 200 chr, W/ u wnt
     to fll as mch as psbleAlternatvly u may hv GSM cllar P8
     w_s cpble of rcivng Short msg (SMS), WS/ msg siz
     lim is 160 chr. 4 demonstrton of thi mods SquezText
     fnc ,  dsc txt of thi prgra has ben cnvd_ blow
     See uself if i_s redble (Yes, it tak som T to get usdto
     compr rat is tpcly 30-40

   And if $SQZ_OPTIMIZE_LEVEL is set to non-zero

     u_nUseThiModE.g.ToPrprceTxtBfreI_sSntTo
     elrnicMdaHasSomMaxTxtSizLim.F_xmplePag
     hvAbitryTxtSizLim,Tpcly200Chr,W/UWnt
     toFllAsMchAsPsbleAlternatvlyUMayHvGSMCllarP8
     w_sCpbleOfRcivngShortMsg(SMS),WS/MsgSiz
     limIs160Chr.4DemonstrtonOfThiModsSquezText
     fnc,DscTxtOfThiPrgraHasBenCnvd_Blow
     SeeUselfIfI_sRedble(Yes,ItTakSomTToGetUsdto
     comprRatIsTpcly30-40

   The comparision of these two show

     Original text   : 627 characters
     Level 0	    : 433 characters	reduction 31 %
     Level 1	    : 345 characters	reduction 45 %	(+14 improvement)

   There are few grammar rules which are used to shorten some English
tokens very much:

     Word that has _ is usually a verb

     Word that has / is usually a substantive, noun,
     		    pronomine or other non-verb

   For example, these tokens must be understood before text can be read.
This is not yet like Geek code, because you don't need external parser to
understand this, but just some common sense and time to adapt yourself to
this text. *For a complete up to date list, you have to peek the source
code*

     automatically => 'acly_'

     for           => 4
     for him       => 4h
     for her       => 4h
     for them      => 4t
     for those     => 4t

     can           => _n
     does          => _s

     it is         => i_s
     that is       => t_s
     which is      => w_s
     that are      => t_r
     which are     => w_r

     less          => -/
     more          => +/
     most          => ++

     however       => h/ver
     think         => thk_

     useful        => usful

     you           => u
     your          => u/
     you'd         => u/d
     you'll        => u/l
     they          => t/
     their         => t/r

     will          => /w
     would         => /d
     with          => w/
     without       => w/o
     which         => W/
     whose         => WS/

   Time is expressed with big letters

     time          => T
     minute        => MIN
     second        => SEC
     hour          => HH
     day           => DD
     month         => MM
     year          => YY

   Other Big letter acronyms

     phone	  => P8

EXAMPLES
========

   To add new words e.g. to word conversion hash table, you'd define your
custom set and merge them to existing ones. Do similarly to
%SQZ_WXLATE_MULTI_HASH and $SQZ_ZAP_REGEXP and then start using the
conversion function.

     use English;
     use Squeeze qw( :ALL );

     my %myExtraWordHash =
     (
     	  new-word1  => 'conversion1'
     	, new-word2  => 'conversion2'
     	, new-word3  => 'conversion3'
     	, new-word4  => 'conversion4'
     );

     #	First take the existing tables and merge them with my
     #	translation table

     my %mySustomWordHash =
     (
     	  %SQZ_WXLATE_HASH
     	, %SQZ_WXLATE_EXTRA_HASH
     	, %myExtraWordHash
     );

     my $myXlat = 0;				# state flag

     while (<>)
     {
     	if ( $condition )
     	{
     	    SqueezeHashSet \%mySustomWordHash;	# Use MY conversions
     	    $myXlat = 1;
     	}

     if ( $myXlat and $condition )
     {
         SqueezeHashSet "reset";		# Back to default table
         $myXlat = 0;
     }

     print SqueezeText $ARG;
         }

   Similarly you can redefine the multi word translate table by supplying
another hash reference in call to SqueezeHashSet(). To kill more text
immediately in addtion to default, just concatenate the regexps to
$SQZ_ZAP_REGEXP

KNOWN BUGS
==========

   There may be lot of false conversions and if you think that some word
squeezing went too far, please 1) turn on the debug 2) send you example
text 3) debug log log to the maintainer. To see how the conversion goes
e.g. for word *Messages*:

     use English;
     use Lingua::EN:Squeeze;

     #	activate debug when case-insensitive worj "Messages" is found from the
     #	line.

     SqueezeDebug( 1, '(?i)Messages' );

     $ARG = "This line has some Messages in it";
     print SqueezeText $ARG;

EXPORTABLE VARIABLES
====================

   The defaults may not conquer all possible text, so you may wish to
extend the hash tables and $SQZ_ZAP_REGEXP to cope with your typical text.

$SQZ_ZAP_REGEXP
---------------

   Text to kill immediately, like "Hm, Hi, Hello..." You can only set this
once, because this regexp is compiled immediately when `SqueezeText()' is
caller for the first time.

$SQZ_OPTIMIZE_LEVEL
-------------------

   This controls how optimized the text will be. Curretly there is only
levels 0 (default) and level 1, which squeezes out all spaces. This
improves compression by average of 10%, but the text is more harder to
read. If space is tight, use this extended compression optimization.

%SQZ_WXLATE_MULTI_HASH
----------------------

   *Multi Word* conversion hash table:  "for you" => "4u" ...

%SQZ_WXLATE_HASH
----------------

   *Single Word* conversion hash table: word => conversion. This table is
applied after %SQZ_WXLATE_MULTI_HASH has been used.

%SQZ_WXLATE_EXTRA_HASH
----------------------

   Aggressive *Single Word* conversions like: without => w/o. Applied last.

INTERFACE FUNCTIONS
===================

   # **********************************************************************
# #   PUBLIC FUNCTION # #
*********************************************************************

SqueezeText($)
--------------

Description
     Squeeze text by using vowel substitutions and deletions and hash
     tables that guide text substitutions. The line is parsed multiple
     times and this will take some time.

arg1: $text
     String. Line of Text.

Return values
     String, squeezed text.

new()
-----

Description
     Return class object.

Return values
     object.

SqueezeHashSet($;$)
-------------------

Description
     Set hash tables to use for converting text. The multiple word
     conversion is done first and after that the single words conversions.

arg1: \%wordHashRef
     Pointer to be used to convert single words.  If "reset", use default
     hash table.

arg2: \%multiHashRef [optional]
     pointer to be used to convert multiple words.  If "reset", use
     default hash table.

Return values
     None.

SqueezeControl(;$)
------------------

Description
     Select level of text squeezing: noconv, enable, medium, maximum.

arg1: $state
     String. If nothing, set maximum squeeze level (kinda: restore
     defualts).

          noconv	Turn off squeeze
          conv	Turn on squeeze
          med		Set squeezing level to medium
          max		Set squeezing level to maximum

Return values
     None.

SqueezeDebug(;$$)
-----------------

Description
     Activate or deactivate debug.

arg1: $state [optional]
     If not given, turn debug off. If non-zero, turn debug on.  You must
     also supply regexp if you turn on debug, unless you have given it
     previously.

arg1: $regexp [optional]
     If given, use regexp to trigger debug output when debug is on.

Return values
     None.

   Author can be reached at jari.aalto@poboxes.com HomePage via forwarding
service is at http://www.netforward.com/poboxes/?jari.aalto or
alternatively absolute url is at ftp://cs.uta.fi/pub/ssjaaa/ but this may
move without notice. Prefer keeping the forwarding service link in your
bookmark.

   Latest version of this module can be found at
$CPAN/modules/by-module/Lingua/

AUTHOR
======

   Copyright (C) 1998-1999 Jari Aalto. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself or in terms of Gnu General Public licence v2 or later.

A simple tool for summarizing bodies of English text.
*****************************************************

NAME
====

   Lingua::EN::Summarize - A simple tool for summarizing bodies of English
text.

SYNOPSIS
========

     use Lingua::EN::Summarize;
     my $summary = summarize( $text );                    # Easy, no? :-)
     my $summary = summarize( $text, maxlength => 500 );  # 500-byte summary
     my $summary = summarize( $text, filter => 'html' );  # Strip HTML formatting
     my $summary = summarize( $text, wrap => 75 );        # Wrap output to 75 col.

DESCRIPTION
===========

   This is a simple module which makes an unscientific effort at
summarizing English text. It recognizes simple patterns which look like
statements, abridges them, and concatenates them into something vaguely
resembling a summary. It needs more work on large bodies of text, but it
seems to have a decent effect on small inputs at the moment.

   Lingua::EN::Summarize exports one function, `summarize()', which takes
the text to summarize as its first argument, and any number of optional
directives in `name => value' form. The options it'll take are:

maxlength
     Specifies the maximum length, in bytes, of the generated summary.

wrap
     Prettyprints the summary output by wrapping it to the number of
     columns which you specify.

filter
     Passes the text through a filter before handing it to the summarizer.
     Currently, only two filters are implemented: `"html"', which uses
     HTML::TreeBuilder and HTML::FormatText to strip all HTML formatting
     from a document, and `"easyhtml"', which quickly (and less accurately)
     strips all HTML from a document using a simple regular expression, if
     you don't have the abovementioned modules. An `"email"' filter, for
     converting mail and news messages to easily-summarizable text, is in
     the works for the next version.

   Unlike the HTML::Summarize module (which is quite interesting, and worth
a look), this module considers its input to be plain English text, and
doesn't try to gather any information from the formatting. Thus, without
any cues from the document's format, the scheme that HTML::Summarize uses
isn't applicable here. The current scheme goes something like this:

   "Filter the text according to the user's filter option. Split the text
into discrete sentences with the Text::Sentence module, then further split
them into clauses on commas and semicolons. Keep only the ones that have a
(subject very-simple-verb object) structure. Construct the summary out of
the first sentences in the list, staying within the maxlength limit, or
under 30% of the size of the original text, whichever is smaller."

   Needless to say, this is a very simple and not terribly universally
effective scheme, but it's good enough for a first draft, and I'll bang on
it more later. Like I said, it's not a scientific approach to the problem,
but it's better than nothing (and often better than HTML::Summarize!), and
I don't really need A.I. quality output from it.

AUTHOR
======

   Dennis Taylor, <dennis@funkplanet.com>

SEE ALSO
========

   HTML::Summarize, Text::Sentence,
http://www.vancouvertoday.com/city_guide/dining/reviews/barbers_modern_club.html

Helper functions for the Summarize module
*****************************************

NAME
====

   Lingua::EN::Summarize::Filters - Helper functions for the Summarize
module

SYNOPSIS
========

     See the Lingua::EN::Summarize documentation.

DESCRIPTION
===========

   See the Lingua::EN::Summarize documentation.

AUTHOR
======

   Dennis Taylor, <dennis@funkplanet.com>

SEE ALSO
========

   Lingua::EN::Summarize (got the point yet? :-)

Routine for estimating syllable count in words.
***********************************************

NAME
====

   Lingua::EN::Syllable - Routine for estimating syllable count in words.

SYNOPSIS
========

     use Lingua::EN::Syllable;

     $count = syllable('supercalifragilisticexpialidocious'); # 14

DESCRIPTION
===========

   Lingua::EN::Syllable::syllable() estimates the number of syllables in
the word passed to it.

   Note that it isn't entirely accurate...  it fails (by one syllable) for
about 10-15% of my /usr/dict/words.  The only way to get a 100% accurate
count is to do a dictionary lookup, so this is a small and fast alternative
where more-or-less accurate results will suffice, such as estimating the
reading level of a document.

   I welcome pointers to more accurate algorithms, since this one is
pretty quick-and-dirty.  This was designed for English (well, American at
least) words, but sometimes guesses well for other languages.

KNOWN LIMITATIONS
=================

   Accuracy for words with non-alpha characters is somewhat undefined.  In
general, punctuation characters, et al, should be trimmed off before
handing the word to syllable(), and hyphenated compounds should be broken
into their separate parts.

   Syllables for all-digit words (eg, "1998";  some call them "numbers")
are often counted as the number of digits.  A cooler solution would be
converting "1998" to "nineteen eighty eight" (or "one thousand nine
hundred eighty eight", or...), but that is left as an exercise for the
reader.

   Contractions are not well supported.

   Compound words (like "lifeboat"), where the first word ends in a silent
'e' are counted with an extra syllable.

COPYRIGHT
=========

   Distributed under the same terms as Perl.  Contact the author with any
questions.

AUTHOR
======

   Greg Fast (gdf@imsa.edu)

convert number to Indonesian verbage.
*************************************

NAME
====

   Lingua::ID::Nums2Words - convert number to Indonesian verbage.

SYNOPSIS
========

     use Lingua::ID::Nums2Words ;

     print nums2words(123)        ; # "seratus dua puluh tiga"
     print nums2words_simple(123) ; # "satu dua tiga"

DESCRIPTION
===========

   *nums2words* currently can handle real numbers in normal and scientific
form in the order of hundreds of trillions. It also preserves formatting
in the number string (e.g, given "1.00" *nums2words* will pronounce the
zeros).

AUTHOR
======

   Steven Haryanto <sh@hhh.indoglobal.com>

SEE ALSO
========

   See Lingua/ID/Words2Nums,

convert Indonesian verbage to number.
*************************************

NAME
====

   Lingua::ID::Words2Nums - convert Indonesian verbage to number.

SYNOPSIS
========

     use Lingua::ID::Words2Nums ;

     print words2nums("seratus dua puluh tiga") ; # 123
     print words2nums_simple("satu dua tiga") ;   # 123

DESCRIPTION
===========

   *words2nums* currently can handle real numbers in normal and scientific
form in the order of hundreds of trillions.

   *words2nums* will return undef is its argument contains unknown verbage
or "syntax error".

   *words2nums* will produce unexpected result if you feed it stupid
verbage.

AUTHOR
======

   Steven Haryanto <sh@hhh.indoglobal.com>

SEE ALSO
========

   See Lingua/ID/Nums2Words,

module for working with logical and visual hebrew
*************************************************

NAME
====

   Lingua::IW::Logical - module for working with logical and visual hebrew

SYNOPSIS
========

   use Lingua::IW::Logical;

   $visual = log2vis_string($logical)

   $vistext = log2vis_text($logtext)

   $vistext = log2vis_text($logtext,$linelength)

   $vistext = log2vis_text($logtext,$linelength,$start)

   $vistext = log2vis_text($logtext,$linelength,$start,$end)

DESCRIPTION
===========

   This module is intended to automate task of converting logical Hebrew
to visual Hebrew.

log2vis_string STRING
---------------------

   This function converts it's argument from logical representaion to
visual (renders it like it should be printed).

log2vis_text STRING,LENGTH,START,END
------------------------------------

   This function allows to convert blocks of text, using `log2vis_string'.
All arguments except the first are optional. LENGTH defines the maximal
length of the resulting line, with default of 80. START defines the text
added before each line of the resulting text. If START is undefined, the
line is padded so that the text is right-aligned. END defines what is
added after each line of text. Default is newline.

   Example 1:

     #!/usr/bin/perl
     use Lingua::IW::Logical;

     while(<>)
     {
       print log2vis_text($_);
     }

   This short program will convert any text in logical Hebrew to readable
visual Hebrew.

   Example 2:

     #!/usr/bin/perl
     use Lingua::IW::Logical;

     while(<>)
     {
       print log2vis_text($_,80,"<nobr>","</nobr><br>\n");
     }

   This example show how you can HTML-ize file in logical hebrew, so that
you can put it on the web page.

KNOWN BUGS
==========

   Bug reports are welcome.  There are some unresolved things with
constructions like "H-1", where H is hebrew letter. The parser now thinks
it's number "-1", while in this context it might as well be dash. Also, it
seems that Word likes to write percents as "%12.5". This is also not
rendered well. I'm thinking how to resolve these issues.

AUTHOR
======

   Stanislav Malyshev (frodo@sharat.co.il)

Statistical language identification
***********************************

NAME
====

   Lingua::Ident - Statistical language identification

SYNOPSIS
========

     use Lingua::Ident;
     $i    = new Lingua::Ident("filename 1" ... "filename n");
     $lang = $i->identify("text to classify"), "\n";

DESCRIPTION
===========

   This module implements a statistical language identifier.

   The filename attributes to the constructor must refer to files
containing tables of n-gram probabilites for languages. These tables can
be generated using the trainlid(1) utility program.

RETURN VALUE
============

   The identify() method returns the value specified in the *_LANG* field
of the probabilities table of the language to which the text most likely
belongs (see `"WARNINGS"' in this node).

   It is recommended to be a POSIX locale name constructed from an ISO 639
2-letter language code, possibly extended by an ISO 3166 2-letter country
code and a character set identifier. Example: *de_DE.iso88591*.

WARNINGS
========

   Since Lingua::Ident is based on statistics it cannot be 100 % accurate.
More precisely, Dunning (see below) reports his implementation to achieve
92 % accuracy with 50K of training text for 20 character strings
discriminating bewteen English and Spanish. This implementation should be
as accurate as Dunning's. However, not only the size but also the quality
of the training text play a role.

   The current implementation doesn't use a threshold to determine if the
most probable language has a high enough probability; if you're trying to
classify a text in a language for which there is no probability table,
this results in getting an incorrect language.

AUTHOR
======

   Lingua::Ident was developed by Michael Piotrowski <mxp@dynalabs.de>.

SEE ALSO
========

   Dunning, Ted (1994). *Statistical Identification of Language.*
Technical report CRL MCCS-94-273. Computing Research Lab, New Mexico State
University.

a module encapsulating access to the Ispell program.
****************************************************

NAME
====

   Lingua::Ispell.pm - a module encapsulating access to the Ispell program.

   Note: this module was previously known as Text::Ispell; if you have
Text::Ispell installed on your system, it is now obsolete and should be
replaced by Lingua::Ispell.

NOTA BENE
=========

   ispell, when reporting on misspelled words, indicates the string it was
unable to verify, as well as its starting offset in the input line.  No
such information is returned for words which are deemed to be correctly
spelled.  For example, in a line like "Can't buy a thrill", ispell simply
reports that the line contained four correctly spelled words.

   Lingua::Ispell would like to identify which substrings of the input
line are words - correctly spelled or otherwise.  It used to attempt to
split the input line into words according to the same rules ispell uses;
but that has proven to be very difficult, resulting in both slow and
error-prone code.

Consequences
------------

   Lingua::Ispell now operates only in "terse" mode.  In this mode, only
misspelled words are reported.  Words which ispell verifies as correctly
spelled are silently accepted.

   In the report structures returned by `spellcheck()', the `'term'' member
is now always identical to the `'original'' member; of the two, you should
probably use the `'term'' member.  (Also consider the `'offset'' member.)
ispell does not report this information for correctly spelled words; if at
some point in the future this capability is added to ispell, Lingua::Ispell
will be updated to take advantage of it.

   Use of the `$word_chars' variable has been removed; setting it no longer
has any effect.

   `terse_mode()' now does nothing.

SYNOPSIS
========

     # Brief:
     use Lingua::Ispell;
     Lingua::Ispell::spellcheck( $string );
     # or
     use Lingua::Ispell qw( spellcheck ); # import the function
     spellcheck( $string );

     # Useful:
     use Lingua::Ispell qw( :all );  # import all symbols
     for my $r ( spellcheck( "hello hacking perl shrdlu 42" ) ) {
       print "$r->{'type'}: $r->{'term'}\n";
     }

DESCRIPTION
===========

   Lingua::Ispell::spellcheck() takes one argument.  It must be a string,
and it should contain only printable characters.  One allowable exception
is a terminal newline, which will be chomped off anyway.  The line is fed
to a coprocess running ispell for analysis.  ispell parses the line into
"terms" according to the language-specific rules in effect.

   The result of ispell's analysis of each term is a categorization of the
term into one of six types: ok, compound, root, miss, none, and guess.
Some of these carry additional information.  The first three types are
"correctly" spelled terms, and the last three are for "incorrectly"
spelled terms.

   Lingua::Ispell::spellcheck returns a list of objects, each
corresponding to a term in the spellchecked string.  Each object is a hash
(hash-ref) with at least two entries: 'term' and 'type'.  The former
contains the term ispell is reporting on, and the latter is ispell's
determination of that term's type (see above).  For types 'ok' and 'none',
that is all the information there is.  For the type 'root', an additional
hash entry is present: 'root'.  Its value is the word which ispell
identified in the dictionary as being the likely root of the current term.
For the type 'miss', an additional hash entry is present: 'misses'.  Its
value is an ref to an array of words which ispell identified as being
"near-misses" of the current term, when scanning the dictionary.

NOTE
----

   As mentioned above, `Lingua::Ispell::spellcheck()' currently only
reports on misspelled terms.

EXAMPLE
-------

     use Lingua::Ispell qw( spellcheck );
     Lingua::Ispell::allow_compounds(1);
     for my $r ( spellcheck( "hello hacking perl salmoning fruithammer shrdlu 42" ) ) {
       if ( $r->{'type'} eq 'ok' ) {
         # as in the case of 'hello'
         print "'$r->{'term'}' was found in the dictionary.\n";
       }
       elsif ( $r->{'type'} eq 'root' ) {
         # as in the case of 'hacking'
         print "'$r->{'term'}' can be formed from root '$r->{'root'}'\n";
       }
       elsif ( $r->{'type'} eq 'miss' ) {
         # as in the case of 'perl'
         print "'$r->{'term'}' was not found in the dictionary;\n";
         print "Near misses: @{$r->{'misses'}}\n";
       }
       elsif ( $r->{'type'} eq 'guess' ) {
         # as in the case of 'salmoning'
         print "'$r->{'term'}' was not found in the dictionary;\n";
         print "Root/affix Guesses: @{$r->{'guesses'}}\n";
       }
       elsif ( $r->{'type'} eq 'compound' ) {
         # as in the case of 'fruithammer'
         print "'$r->{'term'}' is a valid compound word.\n";
       }
       elsif ( $r->{'type'} eq 'none' ) {
         # as in the case of 'shrdlu'
         print "No match for term '$r->{'term'}'\n";
       }
       # and numbers are skipped entirely, as in the case of 42.
     }

ERRORS
------

   `Lingua::Ispell::spellcheck()' starts the ispell coprocess if the
coprocess seems not to exist.  Ordinarily this is simply the first time
it's called.

   ispell is spawned via the `Open2::open2()' function, which throws an
exception (i.e. dies) if the spawn fails.  The caller should be prepared
to catch this exception - unless, of course, the default behavior of die
is acceptable.

Nota Bene
---------

   The full location of the ispell executable is stored in the variable
`$Lingua::Ispell::path'.  The default value is `/usr/local/bin/ispell'.
If your ispell executable has some name other than this, then you must set
`$Lingua::Ispell::path' accordingly before you call
`Lingua::Ispell::spellcheck()' (or any other function in the module) for
the first time!

AUX FUNCTIONS
=============

add_word(word)
--------------

   Adds a word to the personal dictionary.  Be careful of capitalization.
If you want the word to be added "case-insensitively", you should call
`add_word_lc()'

add_word_lc(word)
-----------------

   Adds a word to the personal dictionary, in lower-case form.  This
allows ispell to match it in a case-insensitive manner.

accept_word(word)
-----------------

   Similar to adding a word to the dictionary, in that it causes ispell to
accept the word as valid, but it does not actually add it to the
dictionary.  Presumably the effects of this only last for the current
ispell session, which will mysteriously end if any of the
coprocess-restarting functions are called...

parse_according_to(formatter)
-----------------------------

   Causes ispell to parse subsequent input lines according to the
specified formatter.  As of ispell v. 3.1.20, only 'tex' and 'nroff' are
supported.

set_params_by_language(language)
--------------------------------

   Causes ispell to set its internal operational parameters according to
the given language.  Legal arguments to this function, and its effects,
are currently unknown by the author of Lingua::Ispell.

save_dictionary()
-----------------

   Causes ispell to save the current state of the dictionary to its disk
file.  Presumably ispell would ordinarily only do this upon exit.

terse_mode(bool:terse)
----------------------

   **NOTE:* This function has been disabled!  Lingua::Ispell now always
operates in terse mode.*

   In terse mode, ispell will not produce reports for "correct" words.
This means that the calling program will not receive results of the types
'ok', 'root', and 'compound'.

FUNCTIONS THAT RESTART ISPELL
=============================

   The following functions cause the current ispell coprocess, if any, to
terminate.  This means that all the changes to the state of ispell made by
the above functions will be lost, and their respective values reset to
their defaults.  The only function above whose effect is persistent is
save_dictionary().

   Perhaps in the future we will figure out a good way to make this state
information carry over from one instantiation of the coprocess to the next.

allow_compounds(bool)
---------------------

   When this value is set to True, compound words are accepted as legal -
as long as both words are found in the dictionary; more than two words are
always illegal.  When this value is set to False, run-together words are
considered spelling errors.

   The default value of this setting is dictionary-dependent, so the
caller should set it explicitly if it really matters.

make_wild_guesses(bool)
-----------------------

   This setting controls when ispell makes "wild" guesses.

   If False, ispell only makes "sane" guesses, i.e.  possible root/affix
combinations that match the current dictionary; only if it can find none
will it make "wild" guesses, which don't match the dictionary, and might
in fact be illegal words.

   If True, wild guesses are always made, along with any "sane" guesses.
This feature can be useful if the dictionary has a limited word list, or a
word list with few suffixes.

   The default value of this setting is dictionary-dependent, so the
caller should set it explicitly if it really matters.

use_dictionary([dictionary])
----------------------------

   Specifies what dictionary to use instead of the default.  Dictionary
names are actually file names, and are searched for according to the
following rule: if the name does not contain a slash, it is looked for in
the directory containing the default dictionary, typically /usr/local/lib.
Otherwise, it is used as is: if it does not begin with a slash, it is
construed from the current directory.

   If no argument is given, the default dictionary will be used.

use_personal_dictionary([dictionary])
-------------------------------------

   Specifies what personal dictionary to use instead of the default.

   Dictionary names are actually file names, and are searched for
according to the following rule: if the name begins with a slash, it is
used as is (i.e. it is an absolute path name). Otherwise, it is construed
as relative to the user's home directory ($HOME).

   If no argument is given, the default personal dictionary will be used.

FUTURE ENHANCEMENTS
===================

   ispell options:

     -w chars
            Specify additional characters that can be part of a word.

DEPENDENCIES
============

   Lingua::Ispell uses the external program ispell, which is the
"International Ispell", available at

     http://fmg-www.cs.ucla.edu/geoff/ispell.html

   as well as various archives and mirrors, such as

     ftp://ftp.math.orst.edu/pub/ispell-3.1/

   This is a very popular program, and may already be installed on your
system.

   Lingua::Ispell also uses the standard perl modules FileHandle,
IPC::Open2, and Carp.

AUTHOR
======

   jdporter@min.net (John Porter)

COPYRIGHT
=========

   This module is free software; you may redistribute it and/or modify it
under the same terms as Perl itself.

module to truncate Japanese encoded text.
*****************************************

NAME
====

   Lingua::JA::Jtruncate - module to truncate Japanese encoded text.

SYNOPSIS
========

     use Lingua::JA::Jtruncate qw( jtruncate );
     $truncated_jtext = jtruncate( $jtext, $length );

DESCRIPTION
===========

   The jtruncate function truncates text to a length $length less than
bytes. It is designed to cope with Japanese text which has been encoded
using one of the standard encoding schemes - EUC, JIS, and Shift-JIS. It
uses the Lingua::JA::Jcode module to detect what encoding is being used.
If the text is none of the above Japanese encodings, the text is just
truncated using substr.  If it is detected as Japanese text, it tries to
truncate the text as well as possible without breaking the multi-byte
encoding.  It does this by detecting the character encoding of the text,
and recursively deleting Japanese (possibly multi-byte) characters from
the end of the text until it is underneath the length specified. It should
work for EUC, JIS and Shift-JIS encodings.

FUNCTIONS
=========

jtruncate( $jtext, $length )
----------------------------

   *jtruncate* takes some japanese text and a byte length as arguments, and
returns the japanese text truncated to that byte length.

     $truncated_jtext = jtruncate( $jtext, $length );

SEE ALSO
========

     Lingua::JA::Jcode

AUTHOR
======

   Ave Wrigley <wrigley@cre.canon.co.uk>

COPYRIGHT
=========

   Copyright (c) 1997 Canon Research Centre Europe (CRE). All rights
reserved.  This script and any associated documentation or files cannot be
distributed outside of CRE without express prior permission from CRE.

Recognition of the conjugated forms of portuguese verbs.
********************************************************

NAME
====

   Lingua::PT::UnConjugate - Recognition of the conjugated forms of
portuguese verbs.

DESCRIPTION
===========

   This module provides functions for the recognition of the conjugated
forms of portuguese verbs.

BUGS
====

   Composed tenses are not recognized. The verb list contains many
non-verbs that I have not removed yet.

SYNOPSIS
========

`$verb_forms = unconj( [-a] , $string )'
========================================

   Attempts to recognize a conjugated form of a Portuguese verb, and
returns the result as a reference to hash : if the element

     C<$verb_forms-Greater_Than_Special_Sequence{$infinitive}-Greater_Than_Special_Sequence{$tense}-Greater_Than_Special_Sequence[$person]>

   is true, then the conjugation of the verb "$infinitive" at the tense
"$tense" and the person "$person" should yield "$string".

OPTIONS
-------

   The first argument may an option :

-a : Try to match accentuation errors.
-A : If no match is found, try matching with option -a.
`@res = string_entries( ['l'], \%verb_forms )'
==============================================

   Convert a hash of recognized forms into a list of strings `"$verb,
$tense, $person"'.

   If the first argument is a 'l', then long forms of verb names will be
used.

`@res = list_entries( ['l'], \%verb_forms )'
============================================

   Convert a hash of recognized forms into a list of triplets `[ $verb,
$tense, $person ]'.

   If the first argument is a 'l', then long forms of verb names will be
used.

SEE ALSO : unconj, conjug, treinar.
===================================

AUTHOR Etienne Grossmann, 1999 [etienne@isr.ist.utl.pt]
=======================================================

CREDITS
=======

   Thanks to Soraia Almeida (salmeida@logos.it) from the Logos project
(http://www.logos.it) and Ulisses Pinto and José João Almeida from
Projecto Natura (http://shiva.di.uminho.pt/~jj/pln) who made Ispell
available.

   A big part of the list of verb infinitives comes from files used in
Ispell (http://shiva.di.uminho.pt/~jj/pln) and in Logos
(http://www.verba.org, http://www.logos.it).  these projects. Some verbs
were removed and others added by hand.

Perl extension to choose a language
***********************************

NAME
====

   Lingua::Preferred - Perl extension to choose a language

SYNOPSIS
========

     use Lingua::Preferred qw(which_lang);
     my @wanted = qw(en de fr it de_CH);
     my @available = qw(fr it de);
     my $which = which_lang(\@wanted, \@available);

DESCRIPTION
===========

   Often human-readable information is available in more than one
language.  Which should you use?  This module provides a way for the user
to specify possible languages in order of preference, and then to pick the
best language of those available.  Different 'dialects' given by the
'territory' part of the language specifier (such as en, en_GB, and en_US)
are also supported.

   One routine is provided, called `which_lang()'.  The two arguments are:

     a reference to a list of preferred languages (first is best).  Here, a
     language is a string like `'en'' or `'fr_CA''.  (`'fr_*'' can also be
     given - see below.)

     a reference to non-empty list of available languages.  Here, a
     language can be like `'en'', `'en_CA'', or undef meaning 'unknown'.

   The return code is which language to use.  This will always be an
element of the available languages list.

   The cleverness of this module (if you can call it that) comes from
inferring implicit language preferences based on the explicit list passed
in.  For example, if you say that en is acceptable, then en_IE and en_DK
will presumably be acceptable too (but not as good as just plain en).  If
you give your language as en_US, then en is almost as good, with the other
dialects of en following soon afterwards.

   If there is a tie between two choices, as when two dialects of the same
language are available and neither is explicitly preferred, or when none
of the available languages appears in the userE<39>s list, then the choice
appearing earlier in the available list is preferred.

   Sometimes, the automatic inferring of related dialects is not what you
want, because a language dialect may be very different to the 'main'
language, for example Swiss German or some forms of English.  For this
case, the special form 'XX_*' is available. If you dislike Mexican Spanish
(as a completely arbitrary example), then `[ 'es', 'es_*', 'es_MX' ]'
would rank this dialect below any other dialect of es (but still
acceptable).  You donE<39>t have to explicitly list every other dialect of
Spanish before es_MX.

   So for example, supposing `@avail' contains the languages available:

     You know English and prefer US English:

          $which = which_lang([ 'en_US' ], \@avail);

You know English and German, German/Germany is preferred:
          $which = which_lang([ 'en', 'de_DE' ], \@avail);

     You know English and German, but preferably not Swiss German:

          $which = which_lang([ 'en', 'de', 'de_*', 'de_CH' ], \@avail);

     Here any dialect of German (eg de_DE, de_AT) is preferable to de_CH.

AUTHOR
======

   Ed Avis, epa98@doc.ic.ac.uk

SEE ALSO
========

   perl(1).

Perl extension for detecting and converting various russian character sets: KOI8-r, Windows-1251, CP866, ISO-8859-5, X-Mac-Cyrillic, russian text in english letters, russian part of Unicode and UTF-8. This module can be especially useful for computers with broken cyrillic locales (like foreign web hosts).
******************************************************************************************************************************************************************************************************************************************************************************************************************

NAME
====

   Lingua::RU::Charset - Perl extension for detecting and converting
various russian character sets: KOI8-r, Windows-1251, CP866, ISO-8859-5,
X-Mac-Cyrillic, russian text in english letters, russian part of Unicode
and UTF-8. This module can be especially useful for computers with broken
cyrillic locales (like foreign web hosts).

SYNOPSIS
========

     use Lingua::RU::Charset qw (:CHARSET);
     use Lingua::RU::Charset qw (:CONVERT);
     use Lingua::RU::Charset qw (:CONVERT :CHARCASE);
     use Lingua::RU::Charset qw (any2koi koi2lc koi2uc);

DESCRIPTION
===========

   More documentation and examples coming soon...

NOTE
====

   Unfortunately I don't have time to implement the Unicode and UTF-8
subroutines.  But I am sure that such functions would be useful for
interesting Perl scripts exchanging russian data with Java servlets. So
you are welcome to submit some code!

AUTHOR
======

   Alex Farber, <alex@kawo2.rwth-aachen.de>

SEE ALSO
========

   "The Cyrillic Charset Soup" article by Roman Czyborra located at
http://czyborra.com/charsets/cyrillic.html lists various cyrillic charsets.
The russian texts for counting frequencies of letter pairs have been taken
from "The Eugene Peskin's Electronic Library" located at
http://www.online.ru/sp/rel/russian/ Please consider also visiting my home
page at http://simplex.ru/news/ where I collect links to articles and news
about Perl, Python, JavaScript, databases etc.

NOMEN
=====

   Lingua::Romana::Perligata - Perl in Latin

EDITIO
======

   This document describes version 0.01 of Lingua::Romana::Perligata,
released December  8, 2000.

SUMMARIUM
=========

     #! /usr/local/bin/perl -w

     use Lingua::Romana::Perligata;

     adnota Illud Cribrum Eratothenis

     maximum tum val inquementum tum biguttam tum stadium egresso scribe.
     vestibulo perlegementum da meo maximo .
     maximum tum novumversum egresso scribe.
     da II tum maximum conscribementa meis listis.
     dum damentum nexto listis decapitamentum fac sic
            lista sic hoc tum nextum recidementum cis vannementa da listis.
            next tum biguttam tum stadium tum nextum tum novumversum
                     scribe egresso.
        cis

DESCRIPTIO
==========

   The Lingua::Romana::Perligata makes it makes it possible to write Perl
programs in Latin. (If you have to ask "Why?", then the answer probably
won't make any sense to you either.)

   The linguistic principles behind Perligata are described in:

     http://www.csse.monash.edu.au/~damian/papers/HTML/Perligata.html

   The module is used at the start of the program, and installs a filter
which allows the rest of the program to be written in (modified) Latin, as
described in the following sections.

GRAMMATICA PERLIGATA
====================

Variables
---------

   To simplify the mind-numbingly complex rules of declension and
conjugation that govern inflexions in Latin, Perligata treats all
user-defined scalar and array variables as neuter nouns of the second
declension - singular for scalars, plural for arrays.

   Hashes represent something of a difficulty in Perligata, as Latin lacks
an obvious way of distinguishing these "plural" variables from arrays. The
solution that has been adopted is to depart from the second declension and
represent hashes as masculine plural nouns of the fourth declension.

   Hence, the type and role of all types variables are specified by their
number and case.

   When elements of arrays and hashes are referred to directly in Perl, the
prefix of the container changes from `@' or % to `$'. So it should not be
surprising that Perligata also makes use of a different inflexion to
distinguish these cases.

   Indexing operations such as `$array[$elem]' or `$hash{$key}' might be
translated as "elem of array" or "key of hash". This suggests that when
arrays or hashes are indexed, their names should be rendered in the
genitive (or possessive) case. Multi-level indexing operations
(`$array[$row][$column]') mean "column of row of array", and hence the
first indexing variable must also be rendered in the genitive.

   Note that the current release of Perligata only supports homogeneous
multi-level indexing. That is: `$lol[$row][$column]' or
`$hoh{key}{subkey}{subsubkey}', but not $lohol[$index1]{key}[$index2]>.

   The rules for specifying variables may be summarized as follows:

     Perligata    Number, Case, and Declension    Perl         Role
     =========    ============================    ====         ====
     nextum       accusative singular 2nd         $next        scalar rvalue
     nexta        accusative plural 2nd           @next        array rvalue
     nextus       accusative plural 4th           %next        hash rvalue
     nexto        dative singular 2nd             $next        scalar lvalue
     nextis       dative plural 2nd               @next        array lvalue
     nextibus     dative plural 4th               %next        hash lvalue
     nexti        genitive singular 2nd           [$next]...   scalar index
     nextorum     genitive plural 2nd             $next[...]   array element
     nextuum      genitive plural 4th             $next{...}   hash entry

   In other words, scalars are always singular nouns, arrays and hashes are
always plural (but of different declensions), and the case of the noun
specifies its syntactic role in a statement : accusative for an rvalue,
dative for an lvalue, genitive when being index. Of course, because the
inflection determines the syntactic role, the various components of a
statement can be given in any order. For example, the Perl statement:

     $last = $next;

   could be expressed in Perligata as any of the following (`da' is the
Perligata assignment operator - see `"Built-in functions and operators"'
in this node):

     lasto da nextum.
     lasto nextum da.
     nextum da lasto.
     nextum lasto da.
     da lasto nextum.
     da nextum lasto.

   The special form `$#array' is rendered via the Perligata verb *admeta*
("measure out"). See `"Subroutines, operators, and functions"' in this
node.

   The common punctuation variables $_ and `@_' are special cases.  $_ is
often the value under implicit consideration (e.g. in pattern matches, or
for loops) and so it is rendered as "this thing": *hoc* as an rvalue,
*huic* as an lvalue, *huius* used as an intermediate index.

   Similarly, `@_' is implicitly the list of things passed into a
subroutine, and so is rendered as "these things": *haec* as an rvalue,
*his* as an lvalue, *horum* when indexed.

   Other punctuation variables take the Latin forms of their English.pm
equivalents (see `"THESAURUS PERLIGATUS"' in this node), often with a
large measure of poetic licence. For example, in Perligata, $/ is rendered
as *ianitorem* or "gatekeeper".

   The "numeral" variables - $1, $2, etc. - are rendered as synthetic
compounds: *parprimum* ("the equal of the first"), *parsecundum* ("the
equal of the second"), etc. When used as interim indices, they take their
genitive forms: *parprimi*, *parsecundi*, etc.  Since they cannot be used
as an lvalue, they have no dative forms.

my, our, and local
------------------

   In Perligata, the my modifier is rendered - not surprisingly - by the
first person possessive pronouns: *meo* (conferring a scalar context) and
*meis* (for a list context). Note that the modifier is always applied to a
dative (lvalue), and hence is itself declined in that case. Thus:

     meo varo haec da.                # my $var = @_;
     meis varo haec da.               # my ($var) = @_
     meis varis haec da.              # my @var = @_;

   Similarly the our modifier is rendered as *nostro* or *nostris*,
depending on the desired context.

   The Perl local modifier is *loco* or *locis* in Perligata:

     loco varo haec da.               # local $var = @_;
     locis varo haec da.              # local ($var) = @_
     locis varis haec da.             # local @var = @_;

   This is particularly felicitous: not only is *loco* the Latin term from
which the word "local" derives, it also means "in place of" (as in: *in
loco parentis*). This meaning is much closer to the actual behaviour of
the local modifier, namely to temporarily install a new symbol table entry
in place of the current one.

Subroutines, operators, and functions
-------------------------------------

   Functions, operators, and user-defined subroutines are represented as
verbs or, in some situations, verbal nouns. The inflexion of the verb
determines not only its syntactic role, but also its call context.

   User-defined subroutines are the simplest group. To avoid ambiguities,
they are all treated as verbs of the third conjugation. For example, here
are the various conjugations for different usages for a user-defined
subroutine count():

     Perligata       Number, Mood, etc       Perl        Role    Context
     =========       =================       ====        ====    =======
     countere        infinitive              sub count   defn    -
     counte          imperative sing.        count()     call    void
     countementum    acc. sing. resultant    count()     call    scalar
     countementa     acc. plur. resultant    count()     call    list
     countemento     dat. sing. resultant    count()     call    scalar lvalue
     countementis    dat. plur. resultant    count()     call    list lvalue

   The use of the infinitive as a subroutine definition is obvious:
*accipere* would tell Perligata how "to accept"; *spernere*, how "to
reject". So *countere* specifies how "to count".

   The use of the imperative for void context is also straightforward:
*accipe* commands Perligata to "accept!", *sperne* tells it to "reject!",
and *counte* bids it "count!". In each case, an instruction is being given
(and in a void context too, so no backchat is expected).

   Handling scalar and list contexts is a little more challenging. The
corresponding Latin must still have verbal properties, since an action is
being performed upon objects. But it must also have the characteristics of
a noun, since the result of the call will itself be used as the object
(i.e. target or data) of some other verb. Fortunately, Latin has a rich
assortment of verbal nouns - far more than English - that could fill this
role.

   Since it is the result of the subroutine call that is of interest here,
the chosen solution was to use the *-ementum* suffix, which specifies the
(singular, accusative) outcome of an action. This corresponds to the
result of a subroutine called in a scalar context and used as data. For a
list data context, the plural suffix *-ementa* is used, and for targets,
the dative forms are used: *-emento* and *-ementis*.  Of course, Perl does
not (yet) support lvalue subroutines that return a list/array, so the
*-mentis* suffix currently triggers an error.

   Note that these resultative endings are completely consistent with those
for variables.

Built-in functions and operators
--------------------------------

   Built-in operators and functions could have followed the same
"dog-latin" pattern as subroutines. For example shift might have been
*shifte* in a void context, *shiftementa* when used as data in an array
context, *shiftemento* when used as a target in a scalar context, etc.

   However, Latin already has a perfectly good verb with the same meaning
as shift: *decapitare* ("to behead"). Unfortunately, this verb is of the
first conjugation, not the second, and hence has the imperative form
*decapita*, which makes it look like a Perligata array in a data role.

   Orthogonality has never been Perl's highest design criterion, so
Perligata follows suit by eschewing bland consistency in favour of
aesthetics. All Perligata keywords - including function and operator names
- are therefore specified as correct Latin verbs, of whatever conjugation
is required.  For example:

     Operator/  Literal        In void     When used as      When used as
     function   meaning        context     scalar rvalue     list rvalue
     ========   =======        =======     =============     ============
     +          "add"          adde        addementum        addementa
     =          "give"         da          damentum          damenta
     .          "conjoin"      sere        serementum        serementa
     ..         "enlist"       conscribe   conscribementum   conscribementa

     shift      "behead"       decapita    decapitamentum    decapitamenta

     push       "stack"        cumula      cumulamentum      cumulamenta
     pop        "unstack"      decumula    decumulamentum    decumulamenta

     grep       "winnow"       vanne       vannementum       vannementa
     print      "write"        scribe      scribementum      scribementa
     write      "write below"  subscribe   subscribementum   subscribementa

     die        "die"          mori        morimentum        morimenta

   The full list of Perligata keywords is provided in `THESAURUS
PERLIGATUS' in this node.

   Note, however, that consistency has not been entirely forsaken. The
back-formations of inflexions for scalar and list context are entirely
regular, and consistent with those for user-defined subroutines (described
above).

   A few Perl built-in functions - pos, substr, keys - can be used as
lvalues. That is, they can be the target of some other action (typically
of an assignment). In Perligata such cases are written in the dative
singular (since the lvalues are always scalar). Note too that, because an
assignment to an lvalue function modifies its first argument, that
argument must be a target too, and hence must be written in the dative as
well.

   Thus:

     nexto stringum reperimentum da.     # $next = pos $string;
     nextum stringo reperimento da.      # pos $string = $next;

     inserto stringum tum unum tum duo excerpementum da.
                                 	    # $insert = substr($string,1,2);
     insertum stringo unum tum duo excerpemento da.
                                 	    # substr($string,1,2) = $insert;

     clavis hashus nominamentum da.      # @keys = keys %hash;
     clava hashibus nominamento da.      # keys %hash = @keys;

   An interesting special case is the `$#array' construction, which in
Perligata is rendered via the verb *admeta*:

     counto da arraya admetamentum.	    # $count = $#array;

Comments
--------

   In Perligata, comments are rendered by the verb *adnota* ("annotate").
For example:

     nexto da prevum.    adnota mensuram antiquam reserva

   means:

     $next = $prev;      # remember old amount

Blocks and control structures
-----------------------------

   Natural languages generally use some parenthetical device - such as
parentheses, commas, or (as here) dashes - to group and separate
collections of phrases or statements.

   Some such mechanism would be an obvious choice for denoting Perligata
code blocks, but there is a more aesthetically pleasing solution.  Perl's
block delimiters (`{'..`}') have two particularly desirable properties:
they are individually short, and collectively symmetrical.  It was
considered important to retain those characteristics in Perligata.

   In Latin, the word *sic* has a sense that means "as follows".  Happily,
its contranym, *cis*, has the meaning (among others) "to here". The allure
of this kind of wordplay being impossible to resist, Perligata delimits
blocks of statements with these two words. For example:

     sic                                     # {
         loco inanitori.                     #   local $/;
         dato nuntio perlegementum da.       #   $data = <DATA>;
     cis                                     # }

   Control structures in Perligata are rendered as conditional clauses, as
they are in Latin, English, and Perl. And as in those other languages, they
may precede or follow the code blocks they control.

   Perligata provides the following control structures:

     Perligata                        Perl
     =========                        ====
     si ... fac                       if ...
     nisi ... fac                     unless ...
     dum ... fac                      while ...
     donec ... fac                    until ...
     per (quisque) ... in ... fac     for(each) ...
     posterus                         next
     ultimus                          last
     reconatus                        redo
     confectus                        continue

   The trailing *fac* is the imperative form of *facere* ("to do") and is
used as a delimiter on the control statement's condition.  It is required,
regardless of whether the control statement precedes or follows its block.

   The choice of *dum* and *donec* is completely arbitrary, since Latin
does not distinguish "while" and "until" as abstractions in the way
English does. *Dum* and *donec* each mean both "while" and "until", and
Latin relies on context (i.e. semantics) to distinguish them. This is
impractical for Perligata, so it always treats *dum* as while and *donec*
as `until'. This choice was made in order to favour the shorter term for
the more common type of loop.

   The choice of *confectus* for continue seeks to convey the function of
the control structure, not the literal meaning of the English word.  That
is, a continue block specifies how to complete (*conficere*) an iteration.

   Perligata only supports the pure iterative form of `for(each)', not the
C-like three-part syntax.

   Because:

     foreach $var (@list) {...}

   means "for each variable in the list...", the scalar variable must be in
the accusative (as it is governed by the preposition "for"), and the list
must be in the ablative (denoting inclusion). Fortunately, in the second
declension, the inflexion for ablatives is exactly the same as for
datives, giving:

     per quisque varum in listis sic ... cis

   This means that no extra inflexions have to be learned just to use the
*per* loop. Better still, the list (*listis*) looks like a Perligata array
variable in a target role, which it clearly is, since its contents may be
modified within the loop.

   Note that you can also omit the accusative variable completely:

     per quisque in listis sic ... cis

   and leave *hoc* ($_) implied, as in regular Perl.

Data
----

   The `__END__' and `__DATA__' markers in Perligata are *finis*
("boundary") and *nuntius* ("information") respectively. Data specified
after either of these markers is available via the input stream *nuntio*.
For example:

     dum perlege nuntio fac sic		# while (<DATA>) {
             scribe egresso hoc.		#	print $_;
     cis					# }
     						#
     	finis					# __END__
     	post					# post
     	hoc					# hoc
     	ergo					# ergo
     	propter					# propter
     	hoc					# hoc

Numbers
-------

   Numeric literals in Perligata are rendered by Roman numerals - I, *II*,
*III*, IV...*XV*...*XLII*, etc. However, the first 10 numbers may also be
referred to by name: *unum*/*unam*, *duo*/*duas*, *tres*, *quattuor*,
*quinque*, sex, *septem*, *octo*, *novem*, *decem*. Zero, for which there
is no Latin numeral, is rendered by *nullum* ("no-one"). *Nihil*
("nothing") might have been a closer rendering, but it is indeclinable and
hence indistinguishable in the accusative and genitive.

   When a numeric literal is used in an indexing operation, it must be an
ordinal: "zeroth (element)", "first (element)", "second (element)", etc.

   The first ten ordinals are named (in the accustive): *primum*/*primam*,
*secundum*/*secundam*, *tertium*/*tertiam*, *quartum*/*quartam*,
*quintum*/*quintam*, *sextum*/*sextam*, *septimum*/*septimam*,
*octavum*/*octavam*, *nonum*/*nonam*, *decimum*/*decimam*.  Ordinals
greater than ten are represented by their corresponding numeral with the
suffix *-imum*: *XVimum* ("15th"), *XLIIimum* ("42nd"), etc.  By analogy,
ordinal zero is rendered by the invented form *nullimum*.

   If the element being indexed is used as an lvalue, then the ordinal must
of course be in the dative instead: *nullimo*, *primo*, *secundo*,
*tertio*, *quarto*, *quinto*, *sexto*, *septimo*, *octavo*, *nono*,
*decimo*, *XIimo*, etc. Note that the feminine dative forms are not
available in Perligata, as they are ambiguous with the feminine genitive
singular forms.

   In a multi-level indexing operation, ordinals may need to be specified
in the genitive: *nulli*/*nullae*, *primi*/*primae*, *secundi*/*secundae*,
*tertii*/*tertiae*...*XVimi*/*XVimae*, etc.

   For example:

     $unimatrix[1][3][9][7];

   would be:

     septimum noni tertii primi unimatrixorum

   which is literally:

     seventh of ninth of third of first of unimatrix

   Note that the order of the genitives is significant here, and is the
reverse of that required in Perl.

   As mentioned in `"Variables"' in this node, Perligata currently only
supports homogeneous multi-level indexing. If the final genitive indicates
an array (e.g. *unimatrixorum* in the previous example), then preceding
index is assumed to be an array index. If the final genitive indicates a
hash, every preceding genitive, and the original ordinal are presumed to be
keys.  For example:

     septimum noni tertii primi unimatrixorum   # $unimatrix[1][3][9][7];
     septimum noni tertii primi unimatrixuum    # $unimatrix{1}{3}{9}{7};

   Floating point numbers are expressed in Perligata as Latin fractions:

     unum quartum                  # 0.25
     MMMCXLI Mimos                 # 3.141

   Note that the numerator is always a cardinal and the denominator a
(singular or plural) ordinal ("one fourth", "3141 1000ths"). The plural of
a Latin accusative ordinal is formed by replacing the *-um* suffix by
*-os*.  This nicety can be ignored, as Perligata will accept fractions in
the form *MMMCXLI Mimum* ("3141 1000th")

   Technically, both numerator and denominator should also be in the
feminine gender - *una quartam*, *MMMCXLI Mimas*. This Latin rule is not
enforced in Perligata (to help minimize the number of suffixes that must
be remembered), but Perligata *does* accept the feminine forms.

Strings
-------

   Classical Latin does not use punctuation to denote direct quotation.
Instead the verb *inquit* ("said") is used to report a direct utterance.
Hence in Perligata, a literal character string is constructed, not with
quotation marks, but by invoking the verbal noun *inquementum* ("the
result of saying"), with a data list of literals to be interpolated. For
example:

     print STDOUT 'Enter next word:';

   becomes:

     Enter tum next tum word inquementum tum biguttam egresso scribe.

   Note that the arguments to *inquementum* are special, in that they are
treated as literals. Punctuation strings have special names, such as
*lacunam* ("a hole") for space, *stadium* ("a stride") for tabspace,
*novumversum* ("new verse") for newline, or *biguttam* ("two spots") \ for
colon.

   Perligata does not provide an interpolated quotation mechanism. Instead,
variables must be concatenated into a string. So:

     print STDERR "You entered $word\n";
     $mesg = "You entered $word";

   becomes:

     You tum entered inquementum tum wordum tum novumversum oraculo scribe.
     mesgo da You tum entered inquementum tum wordum serementum.

Regular expressions
-------------------

   **[Perligata's regular expression mechanism is not yet implemented.
This section outlines how it will work in a future release.]**

   In Perligata, patterns will be specified in a constructive syntax (as
opposed to Perl's declarative approach). Literals will regular strings and
other components of a pattern will be adjectives, verbs, nouns, or a
connective:

     Perl        Perligata       Meaning
     ====        =========       =======
     ...+?       multum          "many"
     ...+        plurissimum     "most"
     ...??       potis           "possible"
     ...?        potissimum      "most possible"
     (...)       captivum        "captured"
     (?=...)     excuba          "keep watch"
     [...]       opta            "choose between"
     .           quidlibet       "anything"
     \d          digitum         "a finger"
     \s          lacunam albam   "a white space"
     \w          litteram        "a character"
     |           an              interrogative "or"

   The final pattern will be produced using the supine *desideratum*.  For
example:

     pato da desideratum                         # $pat = qr/(?x)
         C tum plurissimum A tum O opta tum T    #          C[AO]+T
         an DOG tum potis GY.                    #          |DOG(?:GY)?/;

   Actual matching against a pattern will be done via the *compara*
("match") and *substitue* ("substitute") verbs:

     si stringum patum comparamentum fac sic   # if ($string =~ /$pat/) {
             scribe egresso par inquementum    #    print "match"
     cis                                       #

     huic substitue patum tum valum            # s/$pat/$val/
             per quisque in listis.            #    foreach @list;

   Note that the string being modified by *substitue* will have to be
dative.

References
----------

   To create a reference to a variable, the variable is written in the
ablative (which looks exactly like the dative in Perligata's restricted
Latin syntax) and prefaced with the preposition *ad* ("to"). To create a
reference to a subroutine, the associated verb is inflected with the
accusative suffix *-torem* ("one who...") to produce the corresponding
noun-of-agency.

   For example:

     val inquemento hashuum ad dato da.       # $hash{'val'} = \$dat;
     arg inquemento hashuum ad argis da.      # $hash{'arg'} = \@arg;
     act inquemento hashuum functorem da.     # $hash{'act'} = \&func;

     ad val inquemento hashuum dato da.       # $dat   = \$hash{'val'};
     ad inquemento arg hashuum argis da.      # @arg   = \$hash{'arg'};
     funcemento da ad inquemento act hashuum. # func() = \$hash{'act'};

   A special case of this construction is the anonymous subroutine
constructor *factorem* ("one who does..."), which is the equivalent of
`sub {...}' in Perl:

     anonymo da factorem sic haec mori cis.    # $anon = sub { die @_ };

   As in Perl, such subroutines may be invoked by concatenating a call
specifier to the name of the variable holding the reference:

     anonymume nos tum morituri inquementum.   # &$anon('Nos morituri');

   Note that the variable holding the reference (*anonymum*) is being used
as data, so it is named in the accusative.

   In the few cases where a subroutine reference can be the target of an
action, the dative suffix (*-tori*) is used instead:

     benedictum functori classum.              # bless \&func, $class;
     benedictum factori sic mori cis classum.  # bless sub{die}, $class;

   To dereference other types of references, a resultative of the verb
*arcesse* ("fetch") is used:

     Ref type        Perligata               Perl            Context
     ========        =========               ====            =======
     scalar          arcessementum varum     $$var           rvalue
     scalar          arcessemento varum      $$var           lvalue
     array           arcessementi varum      ...[$$var]      rvalue

     array           arcessementa varum      @$var           rvalue
     array           arcessementis varum     @$var           lvalue
     array           arcessementorum varum   $var->[...]     either

     hash            arcessementus varum     %$var           rvalue
     hash            arcessementibus varum   %$var           lvalue
     array           arcessementuum varum    $var->{...}     either

   Note that the first six forms are just the standard resultatives (in
accusative, dative, and genitive) for the regular Perligata verb
*arcesse*. The last three forms are ungrammatical inflections (*-mentum*
is 2nd declension, not 4th), but are plausible extensions of the
resultative to denote a hash return value.

   Multiple levels of dereferencing are also possible:

     valo da arcessementa arcessementum varum    # $val = @$$var;

   as is appropriate indexing (using the genitive forms):

     valo da primum varum arcessementorum        # $val = $var->[1];
     valo da primum varum arcessementuum         # $val = $var->{1};
     valo da primum varum arcessementi arrorum   # $val = $arr[$$var][1];

Boolean logic
-------------

   Perl's logical conjunctive and disjunctive operators come in two
precedences, and curiously, so do those of Latin. The higher precedence
Perl operators - `&&' and `||' - are represented in Perligata by the
emphatic Latin conjunctions *atque* and *vel* respectively. The lower
precedence operators - and and or - are represented by the unemphatic
conjunctive suffixes *-que* and *-ve*. Hence:

     reso damentum foundum atque runementum.   # $res = $found && run();
     reso damentum foundum runementumque.      # $res = $found and run();
     reso damentum foundum vel runementum.     # $res = $found || run();
     reso damentum foundum runementumve.       # $res = $found or run();

   Note that, as in Latin, the suffix of the unemphatic conjunction is
always appended to the first word after the point at which the conjunction
would appear in English. Thus:

     $result = $val or max($1,$2);

   is rendered as:

     resulto damentum valum parprimumque tum parsecundum maxementum.

   or:

     resulto damentum valum maxementumque parprimum tum parsecundum.

   Proper Latinate comparisons would be odious in Perligata, because they
require their first argument to be expressed in the nominative and would
themselves have to be indicative. This would, of course, improve the
positional independence of the language even further, allowing:

     si valus praecedit datum...              # if $val < $dat...
     si praecedit datum valus...              # if $val < $dat...
     si datum valus praecedit...              # if $val < $dat...

   Unfortunately, it also introduces another set of case inflexions and
another verbal suffix. Worse, it would mean that noun suffixes are no
longer unambiguous. In the 2nd declension, the nominative plural ends in
the same -i as the genitive singular, and the nominative singular ending
(*-us*) is the same as the accusative plural suffix for the fourth
declension. So if nominatives were used, scalars could no longer always be
distinguished from arrays or from hashes, except by context.

   To avoid these problems, Perligata represents the equality and simple
inequality operators by three pairs of verbal nouns:

     Perligata       Meaning                     Perl
     =========       =======                     ====
     aequalitam      "equality (of...)"          ==
     aequalitas      "equalities (of...)"        eq
     praestantiam    "precedence (of...)"        <
     praestantias    "precedences (of...)"       lt
     comparitiam     "comparison (of...)"        <=>
     comparitias     "comparisons (of...)"       cmp

   Each operator takes two data arguments, which it compares:

     si valum tum datum aequalitam           # si $val == $dat
     si valum tum datum praestantias         # si $val lt $dat
     si aum tum bum comparitiam              # si $a <=> $b

   The effects of the other comparison operators - `>', `<=', `!=', ne,
ge, etc. - are all achieved by appropriate ordering of the two arguments
and combination with the the logical negation operator *non*:

     si valum tum datum non aequalitam     # if $val != $dat
     si datum tum valum praestantiam       # if $val > $dat
     si valum non praestantias datum       # if $val ge $dat

Packages and classes
--------------------

   The Perligata keyword to declare a package is *domus*, literally "the
house of". In this context, the name of the class follows the keyword and
is treated as a literal; as if it were the data argument of an
*inquementum*.

   To explicitly specify a variable or subroutine as belonging to a
package, the preposition *intra* ("within") is used. To call a subroutine
as a method of a particular package (or of an object), the preposition
*apud* ("of the house of") is used. Thus *intra* is Perligata's `::' and
*apud* is it's `->'.

   The Perl bless function is *benedice* in Perligata, but almost
invariably used in the scalar accusative form *benedicementum*. Perligata
also understands the correct (contracted) Latin form of this verb:
*benedictum*.

   Thus:

     domus Specimen.                             # package Specimen;

     newere                                      # sub new
     sic                                         # {
         meis datibus.                           #   my %data;
         counto intra Specimen
             postincresce.                       #   $Specimen::count++;
         datibus primum horum benedictum.        #   bless \%data, $_[0];
     cis                                         # }

     printere                                    # sub print
     sic                                         # {
         modus tum indefinitus inquementum mori. #   die 'method undefined';
     cis                                         # }

     domus princeps.                             # package main;

     meo objecto da                              # my $object =
             newementum apud Specimen.           #       Specimen->new;

     printe apud objectum;                       # $object->print;

THESAURUS PERLIGATUS
====================

   This section lists the complete Perligata vocabulary, except for Roman
numerals (I, *II*, *III*, etc.)

   In each of the following tables, the three columns are always the same:
"Perl construct", "Perligata equivalent", "Literal meaning of Perligata
equivalent".

   Generally, only the accusative form is shown for nouns and adjectives,
and only the imperative for verbs.

Values and variables           0            nullum           "no-one"         1            unum             "one"         2            duo              "two"         3            tres             "three"         4            quattuor         "four"         5            quinque          "five"         6            sex              "six"         7            septem           "seven"         8            octo             "eight"         9            novem            "nine"         10           decem            "ten"         [0]          nullimum         "zeroth"         [1]          primum           "first"         [2]          secundum         "second"         [3]          tertium          "third"         [4]          quartum          "fourth"         [5]          quintum          "fifth"         [6]          sextum           "sixth"         [7]          septimum         "seventh"         [8]          octavum          "eighth"         [9]          nonum            "ninth"         [10]         decimum          "tenth"         $1           parprimum        "equal of the first"         $2           parsecundum      "equal of the first"         $3           partertium       "equal of the third"         $4           parquartum       "equal of the fourth"         $5           parquintum       "equal of the fifth"         $6           parsextum        "equal of the sixth"         $7           parseptimum      "equal of the seventh"         $8           paroctavum       "equal of the eighth"         $9           parnonum         "equal of the ninth"         $10          pardecimum       "equal of the tenth"         $/           ianitorem        "gatekeeper"         $#var        admeta varum     "measure out"         $_           hoc/huic         "this thing"         @_           his/horum        "these things"         ":"          biguttam         "two spots"         " "          lacunam          "a gap"         "\t"         stadium          "a stride"         "\n"         novumversum      "new line"         local        loco             "in place of"         my           meo              "my"         our          nostro           "our"         main         princeps         "principal"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Quotelike operators
-------------------

     '...'        inque        "say"
     q//          inque        "say"
     m//          compara      "match"
     s///         substitue    "substitute"
     tr///        converte     "translate"

Mathematical operators and functions
------------------------------------

     +            adde         "add"
     -            deme         "subtract"
     -            nega         "negate"
     *            multiplica   "multiply"
     /            divide       "divide"
     %            recide       "lop off"
     **           eleva        "raise"
     ++           preincresce  "increase beforehand"
     ++           postincresce "increase afterwards"
     --           predecresce  "decrease beforehand"
     --           postdecresce "decrease afterwards"
     abs          priva        "strip from"
     atan2        angula       "create an angle"
     sin          oppone       "oppose"
     cos          accuba       "lie beside"
     int          decolla      "behead"
     log          succide      "log a tree"
     sqrt         fode         "root into"
     rand         conice       "guess, cast lots"
     srand        prosemina    "to scatter seed"

Logical and comparison operators
--------------------------------

     !            non             "general negation"
     &&           atque           "empathic and"
     ||           vel             "emphatic or"
     and          -que            "and"
     or           -ve             "or"
     <            praestantiam    "precedence of"
     lt           praestantias    "precedences of"
     <=>          comparitiam     "comparison of"
     cmp          comparitias     "comparisons of"
     ==           aequalitam      "equality of"
     eq           aequalitas      "equalities of"

Strings
-------

     chomp        morde        "bite"
     chop         praecide     "cut short"
     chr          inde         "give a name to"
     hex          senidemi     "sixteen at a time"
     oct          octoni       "eight at a time"
     ord          numera       "number"
     lc           deminue      "diminish"
     lcfirst      minue        "diminish"
     uc           amplifica    "increase"
     ucfirst      amplia       "increase"
     quotemeta    excipe       "make an exception"
     crypt        huma         "inter"
     length       meta         "measure"
     pos          reperi       "locate"
     pack         convasa      "pack baggage"
     unpack       deconvasa    "unpack"
     split        scinde       "split"
     study        stude        "study"
     index        scruta       "search"
     join         coniunge     "join"
     substr       excerpe      "extract"

Scalars, arrays, and hashes
---------------------------

     defined      confirma     "verify"
     undef        iani         "empty, make void"
     scalar       secerna      "to distinguish, isolate"
     reset        lusta        "cleanse"
     pop          decumula     "unstack"
     push         cumula       "stack"
     shift        decapita     "behead"
     unshift      capita       "crown"
     splice       iunge        "splice"
     grep         vanne        "winnow"
     map          applica      "apply to"
     sort         digere       "sort"
     reverse      retexe       "reverse"
     delete       dele         "delete"
     each         quisque      "each"
     exists       adfirma      "confirm"
     keys         nomina       "name"
     values       argue        "to disclose the contents"

I/O
---

     open         evolute      "open a book"
     close        claude       "close a book"
     eof          extremus     "end of"
     read         lege         "read"
     getc         sublege      "pick up something"
     readline     perlege      "read through"
     print        scribe       "write"
     printf       describe     "describe"
     sprintf      rescribe     "rewrite"
     write        subscribe    "write under"
     pipe         inriga       "irrigate"
     tell         enunta       "tell"
     seek         conquire     "to seek out"
     STDIN        vestibulo    "an entrance"
     STDOUT       egresso      "an exit"
     STDERR       oraculo      "a place were doom is pronounced"
     DATA         nuntio       "information"

Control structures
------------------

     {...}        sic...cis                "as follows...to here"
     do           fac                      "do"
     sub {...}    factorem sic...cis       "one who does ...
     eval         aestima                  "evaluate"
     exit         exi                      "exit"
     for          per...in...fac           "for...in...do"
     foreach      per quisque...in...fac   "for each...in...do"
     goto         adi                      "go to"
     <label>:     inscribe <label>         "make a mark"
     return       redde                    "return"
     if           si...fac                 "if"
     unless       nisi...fac               "if not"
     until        donec...fac              "until"
     while        dum...fac                "while"
     wantarray    deside                   "want"
     last         ultimus                  "final"
     next         posterus                 "following"
     redo         reconatus                "trying again"
     continue     confectus                "complete"
     die          mori                     "die"
     warn         mone                     "warn"
     croak        coaxa                    "croak (like a frog)"
     carp         carpe                    "carp at"
     __DATA__     nuntius                  "information"
     __END__      finis                    "a boundary"

Packages, classes, and modules
------------------------------

     ->           apud         "of the house of"
     ::           intra        "within"
     bless        benedice     "bless"
     caller       memora       "recount a history"
     package      domus        "house of "
     ref          agnosce      "identify"
     tie          liga         "tie"
     tied         exhibe       "display something"
     untie        solve        "to untie"
     require      require      "require"
     use          ute          "use"

System and filesystem interaction
---------------------------------

     chdir        demigrare    "migrate"
     chmod        permitte     "permit"
     chown        vende        "sell"
     fcntl        modera       "control"
     flock        confluee     "flock together"
     glob         inveni       "search"
     ioctl        impera       "command"
     link         copula       "link"
     unlink       decopula     "unlink"
     mkdir        aedifica     "build"
     rename       renomina     "rename"
     rmdir        excide       "raze"
     stat         exprime      "describe"
     truncate     trunca       "shorten"
     alarm        terre        "frighten"
     dump         mitte        "drop"
     exec         commuta      "transform"
     fork         furca        "fork"
     kill         interfice    "kill"
     sleep        dormi        "sleep"
     system       obsecra      "entreat a higher power"
     umask        dissimula    "mask"
     wait         manta        "wait for"

Miscellaneous
-------------

     ,            tum          "and then"
     .            sere         "conjoin"
     ..           conscribe    "enlist"
     \            ad           "towards"
     =            da           "give"
     #...         adnota       "annotate"

DIIUDICATORES
=============

   The Lingua::Romana::Perligata module may issue the following diagnostic
messages:

Aliquod barbarum inveni: '%s'
     Some foreign (non-Perligata) symbol was encountered. Commonly this is
     a semi-colon where a period should have been used, but any other
     non-alphanumeric will trigger the same error.

'-mentis' illicitum: '%s'
     Perl does not (yet) support lvalue subroutines that return arrays.
     Hence Perligata does not allow the *-mentis* suffix to be used on
     user-defined verbs.

Index '%s' ordinalis non est
     An index or key was specified as a numeral (e.g. *unum*), rather than
     an ordinal (e.g. *primum*).

'%s' immaturum est
     The symbol indicated (typically *tum*) appeared too early in the
     command (e.g. before any accusative).

Iussum nefastum: '%s'
     The indicated imperative verb was encountered where a resultative was
     expected (e.g. the imperative was incorrectly used as an argument to
     another subroutine or a conjunction).

Accusativum non junctum: '%s'
     The indicated accusative noun or clause appears in a command, but does
     not belong to any verb in the command.

Dativum non junctum: '%s'
     The indicated dative noun or clause appears in a command, but does not
     belong to any verb in the command.

Genitivum non junctum: '%s'
     The indicated genitive noun or clause appears in a command, but does
     not belong to any verb in the command.

Sententia imperfecta prope '%s'
     The command or clause is missing an imperative verb.

Exspectavi 'sic' sed inveni '%s'
     The beginning of a code block was expected at the point where the
     indicated word was found.

Exspectavi 'cis' sed inveni '%s'
     The end of a code block was expected at the point where the indicated
     word was found.

Exspectavi accusativum post 'per' sed inveni '%s'
     The *per* control structure takes an accusative noun after it.  The
     indicated symbol was found instead.

'in' pro 'per' afuit
     The in in a *per* statement was missing.

'%s' dativus non est in 'per'
     After the in of a *per* statement a dative noun or clause is
     required. It was not found.

Iussa absentia per '%s'
     The block of the indicated control statement was missing.

Non intellexi: '%s'
     A general error message indicating the symbol was not understood in
     the context it appeared.

   In addition to these diagnostics, additional debugging support is
provided in the form of three arguments that may be passed to the call to
`use Lingua::Romana::Perligata'.

   The first of these - `'converte'' ("translate") - causes the module to
translate the Perligata code into Perl and write it to STDOUT instead of
executing it. This is useful when your Perligata compiles and runs, but
does not execute as you expected.

   The second argument that may be passed when loading the module is
`'discribe'' ("classify"), which causes the module to print a lexical
analysis of the original Latin program. This is very handy for identifying
incorrect inflections, etc.

   The final argument - `'investiga'', ("trace") - provides a blow-by-blow
trace of the translation process, tracking eack of the internal stacks
(the verb stack, the accusative stack, the dative stack, the block stack),
and showing where each reduction is performed. This wealth of information
tends to be useful only to those familiar with the internals of the module.

GRATIAE
=======

   Special thanks to Marc Moskowitz, John Crossley, Tom Christiansen, and
Bennett Todd, for their invaluable feedback and suggestions. And my
enduring gratitude to David Secomb and Deane Blackman for their heroic
patience in helping me struggle with the perplexities of the *lingua
Romana*.

SCRIPTOR
========

   Damian Conway (damian@conway.org)

CIMICES
=======

   There are undoubtedly some very serious bugs lurking somewhere in code
this funky :-) Bug reports and other feedback are most welcome.

   Corrections to my very poor Latin are doubly welcome.

IUS TRANSCRIBENDI
=================

   Copyright (c) 2000, Damian Conway. All Rights Reserved.  This module is
free software. It may be used, redistributed and/or modified under the
terms of the Perl Artistic License   (see
http://www.perl.com/perl/misc/Artistic.html)

Stemming of words
*****************

NAME
====

   Lingua::Stem - Stemming of words

SYNOPSIS
========

     use Lingua::Stem qw(stem);
     my $stems   = stem(@words);

     or for the OO inclined,

     use Lingua::Stem;
     my $stemmer = Lingua::Stem->new(-locale => 'EN-UK');
     my $stems   = $stemmer->stem(@words);

DESCRIPTION
===========

   This routine applies stemming algorithms to its parameters, returning
the stemmed words as appropriate to the selected locale.

   You can import some or all of the class methods.

   use Lingua::Stem qw (stem clear_stem_cache stem_caching
    add_exceptions delete_exceptions                      get_exceptions
set_locale get_locale                      :all :locale :exceptions :stem
:caching);

     :all        - imports  stem add_exceptions delete_exceptions get_exceptions
                   set_locale get_locale
     :stem       - imports  stem
     :caching    - imports  stem_caching clear_stem_cache
     :locale     - imports  set_locale get_locale
     :exceptions - imports  add_exceptions delete_exceptions get_exceptions

CHANGES
=======

     0.50 2000.09.14 - Fixed major implementation error. Starting with
                       version 0.30 I forgot to include rulesets 2,3 and 4
                       for Porter's algorithm. The resulting stemming results
                       were very poor. Thanks go to <csyap@netfision.com>
                       for bringing the problem to my attention. Unfortunately,
                       the fix inherently generates *different*
                       stemming results than 0.30 and 0.40 did. If you
                       need identically broken output - use locale 'en-broken'.

     0.40 2000.08.25 - Added stem caching support as an option. This
                       can provide a large speedup to the operation
                       of the stemmer. Caching is default turned off
                       to maximize compatibility with previous versions.

     0.30 1999.06.24 - Replaced core of 'En' stemmers with code from
                       Jim Richardson <jimr@maths.usyd.edu.au>
                       Aliased 'en-us' and 'en-uk' to 'en'
                       Fixed 'SYNOPSIS' to correct return value
                       type for stemmed words (SYNOPIS error spotted
                       by <Arved_37@chebucto.ns.ca>)

     0.20 1999.06.15 - Changed to '.pm' module, moved into Lingua:: namespace,
                       added OO interface, optionalized the export of routines
                       into the caller's namespace, added named parameter
                       initialization, stemming exceptions, autoloaded
                       locale support and isolated case flattening to
                       localized stemmers prevent i18n problems later.

     Input and output text are assumed to be in UTF8
     encoding (no operational impact right now, but
     will be important when extending the module to
     non-English).

METHODS
=======

new(...);
     Returns a new instance of a Lingua::Stem object and, optionally,
     selection of the locale to be used for stemming.

     Examples:

          # By default the locale is us-en
          $us_stemmer = Lingua::Stem->new;

          # Overriding the default for a specific instance
          $uk_stemmer = Lingua::Stem->new({ -locale => 'en-uk' });

          # Overriding the default for a specific instance and changing the default
          $uk_stemmer = Lingua::Stem->new({ -default_locale => 'en-uk' });

set_locale($locale);
     Sets the locale to one of the recognized locales. Currently, 'en',
     'en-us' and 'en-uk' are the only recognized locales. All locale
     identifiers are converted to lowercase.

     Called as a class method, it changes the default locale for all
     subseqently generated object instances.

     Called as an instance method, it only changes the locale for that
     particular instance.

     'croaks' if passed an unknown locale.

     Examples:

          # Change default locale
          Lingua::Stem::set_locale('en-uk'); # UK's spellings

          # Change instance locale
          $self->set_locale('en-us');  # US's spellings

get_locale;
     Called as a class method, returns the current default locale.

     Example:

          $default_locale = Lingua::Stem::get_locale;

     Called as an instance method, returns the locale for the instance

          $instance_locale = $stemmer->get_locale;

add_exceptions($exceptions_hash_ref);
     Exceptions allow overriding the stemming algorithm on a case by case
     basis. It is done on an exact match and substitution basis: If a
     passed word is identical to the exception it will be replaced by the
     specified value. No case adjustments are performed.

     Called as a class method, adds exceptions to the default exceptions
     list used for subsequently instantations of Lingua::Stem objects.

     Example:

          # adding default exceptions
          Lingua::Stem::add_exceptions({ 'emily' => 'emily',
                                         'driven' => 'driven',
                                     });

     Called as an instance method, adds exceptions only to the specific
     instance.

          # adding instance exceptions
          $stemmer->add_exceptions({ 'steely' => 'steely' });

     The exceptions shortcut the normal stemming - if an exception matches
     no further stemming is performed after the substitution.

     Adding an exception with the same key value as an already defined
     exception replaces the pre-existing exception with the new value.

delete_exceptions(@exceptions_list);
     The mirror of add_exceptions, this allows the _removal_ of exceptions
     from either the defaults for the class or from the instance.

          # Deletion of exceptions from class default exceptions
          Lingua::Stem::delete_exceptions('aragorn','frodo','samwise');

          # Deletion of exceptions from instance
          $stemmer->delete_exceptions('smaug','sauron','gollum');

          # Deletion of all class default exceptions
          delete_exceptions;

          # Deletion of all exceptions from instance
          $stemmer->delete_exceptions;

get_exceptions;
     As a class method with no parameters it returns all the default
     exceptions as an anonymous hash of 'exception' => 'replace with'
     pairs.

     Example:

          # Returns all class default exceptions
          $exceptions = Lingua::Stem::get_exceptions;

     As a class method with parameters, it returns the default exceptions
     listed in the parameters as an anonymous hash of 'exception' =>
     'replace with' pairs.  If a parameter specifies an undefined
     'exception', the value is set to undef.

          # Returns class default exceptions for 'emily' and 'george'
          $exceptions = Lingua::Stem::get_exceptions('emily','george');

     As an instance method, with no parameters it returns the currently
     active exceptions for the instance.

          # Returns all instance exceptions
          $exceptions = $stemmer->get_exceptions;

     As an instance method with parameters, it returns the instance
     exceptions listed in the parameters as an anonymous hash of
     'exception' => 'replace with' pairs.  If a parameter specifies an
     undefined 'exception', the value is set to undef.

          # Returns instance exceptions for 'lisa' and 'bart'
          $exceptions = $stemmer->get_exceptions('lisa','bart');

stem(@list);
     Called as a class method, it applies the default settings and stems
     the list of passed words, returning an anonymous array with the
     stemmed words in the same order as the passed list of words.

     Example:

          # Default settings applied
          my $stemmed_words = Lingua::Stem::stem(@words);

     Called as an instance method, it applies the instance's settings and
     stems the list of passed words, returning an anonymous array with the
     stemmed words in the same order as the passed list of words.

          # Instance's settings applied
          my $stemmed_words = $stemmer->stem(@words);

clear_stem_cache;
     Clears the stemming cache for the current locale. Can be called as
     either a class method or an instance method.

          $stemmer->clear_stem_cache;

          clear_stem_cache;

stem_caching ({ -level => 0|1|2 });
     Sets stemming cache level for the current locale. Can be called as
     either a class method or an instance method.

          $stemmer->stem_caching({ -level => 1 });

          stem_caching({ -level => 1 });

     For the sake of maximum compatibility with previous versions, stem
     caching is set to '-level => 0' initially.

     '-level' definitions

          '0' means 'no caching'. This is the default level.

          '1' means 'cache per run'. This caches stemming results during each
             call to 'stem'.

          '2' means 'cache indefinitely'. This caches stemming results until
             either the process exits or the 'clear_stem_cache' method is called.

     stem caching is global to the locale. If you turn on stem caching for
     one instance of a locale stemmer, all instances using the same locale
     will have it turned on as well.

NOTES
=====

   This is version 0.40.

   It started with the 'Text::Stem' module which has been adapted into a
more general framework and moved into the more language oriented 'Lingua'
namespace and re-organized to support a OOP interface as well as switch
core 'En' locale stemmers.

   Version 0.40 added a cache for stemmed words. This can provide up to a
4 fold performance improvement.

   Organization is such that extending this module to any number of
languages should be direct and simple.

   Case flattening is a function of the language, so the 'exceptions'
methods have to be used appropriately to the language. For 'En' family
stemming, use lower case words, only, for exceptions.

AUTHORS
=======

     Benjamin Franz <snowhare@nihongo.org>
     Jim Richardson <imr@maths.usyd.edu.au>

SEE ALSO
========

     Lingua::Stem::En Lingua:Stem::En_Us Lingua::Stem::En_Uk

COPYRIGHT
=========

   Copyright 1999

   FreeRun Technologies, Inc (FreeRun), Jim Richardson, University of
Sydney <imr@maths.usyd.edu.au> and Benjamin Franz <snowhare@nihongo.org>.
All rights reserved.

   This software may be freely copied and distributed under the same terms
and conditions as Perl.

BUGS
====

   None known.

TODO
====

   Add more languages. Specifically integrate Text::German for 'de' locale.

A manager for autoloading Lingua::Stem modules
**********************************************

NAME
====

   Lingua::Stem::AutoLoader - A manager for autoloading Lingua::Stem
modules

SYNOPSIS
========

   use Lingua::Stem::AutoLoader;

DESCRIPTION
===========

   Sets up the autoloader to load the modules in the Lingua::Stem system
on demand.

COPYRIGHT
=========

   Copyright 1999, Benjamin Franz (<URL:http://www.nihongo.org/snowhare/>)
and FreeRun Technologies, Inc. (<URL:http://www.freeruntech.com/>). All
Rights Reserved.  This software may be copied or redistributed under the
same terms as Perl itelf.

AUTHOR
======

   Benjamin Franz

TODO
====

   Nothing.

Porter's stemming algorithm for 'generic' English
*************************************************

NAME
====

   Lingua::Stem::En - Porter's stemming algorithm for 'generic' English

SYNOPSIS
========

     use Lingua::Stem::En;
     my $stems   = Lingua::Stem::En::stem({ -words => $word_list_reference,
                                         -locale => 'en',
                                     -exceptions => $exceptions_hash,
                                      });

DESCRIPTION
===========

   This routine applies the Porter Stemming Algorithm to its parameters,
returning the stemmed words.

   It is derived from the C program "stemmer.c" as found in freewais and
elsewhere, which contains these notes:

     Purpose:    Implementation of the Porter stemming algorithm documented
                 in: Porter, M.F., "An Algorithm For Suffix Stripping,"
                 Program 14 (3), July 1980, pp. 130-137.
     Provenance: Written by B. Frakes and C. Cox, 1986.

   I have re-interpreted areas that use Frakes and Cox's "WordSize"
function. My version may misbehave on short words starting with "y", but I
can't think of any examples.

   The step numbers correspond to Frakes and Cox, and are probably in
Porter's article (which I've not seen).  Porter's algorithm still has
rough spots (e.g current/currency, -ings words), which I've not attempted
to cure, although I have added support for the British -ise suffix.

CHANGES
=======

     1999.06.15 - Changed to '.pm' module, moved into Lingua::Stem namespace,
                   optionalized the export of the 'stem' routine
                   into the caller's namespace, added named parameters

     1999.06.24 - Switch core implementation of the Porter stemmer to
                  the one written by Jim Richardson <jimr@maths.usyd.edu.au>

     2000.08.25 - 2.11 Added stemming cache

     2000.09.14 - 2.12 Fixed *major* :( implementation error of Porter's algorithm
                  Error was entirely my fault - I completely forgot to include
                  rule sets 2,3, and 4 starting with Lingua::Stem 0.30.
                  -- Benjamin Franz

METHODS
=======

stem({ -words => \@words, -locale => 'en', -exceptions => \%exceptions });
     Stems a list of passed words using the rules of US English. Returns
     an anonymous hash reference to the stemmed words.

     Example:

          my $stemmed_words = Lingua::Stem::En::stem({ -words => \@words,
                                                      -locale => 'en',
                                                  -exceptions => \%exceptions,
                                  });

stem_caching({ -level => 0|1|2 });
     Sets the level of stem caching.

     '0' means 'no caching'. This is the default level.

     '1' means 'cache per run'. This caches stemming results during a
     single     call to 'stem'.

     '2' means 'cache indefinitely'. This caches stemming results until
     either the process exits or the 'clear_stem_cache' method is called.

clear_stem_cache;
     Clears the cache of stemmed words

NOTES
=====

   This code is almost entirely derived from the Porter 2.1 module written
by Jim Richardson.

SEE ALSO
========

     Lingua::Stem

AUTHOR
======

     Jim Richardson, University of Sydney
     jimr@maths.usyd.edu.au or http://www.maths.usyd.edu.au:8000/jimr.html

     Integration in Lingua::Stem by
     Benjamin Franz, FreeRun Technologies,
     snowhare@nihongo.org or http://www.nihongo.org/snowhare/

COPYRIGHT
=========

   Jim Richardson, University of Sydney Benjamin Franz, FreeRun
Technologies

   This code is freely available under the same terms as Perl.

BUGS
====

TODO
====

Porter's stemming algorithm for 'generic' English
*************************************************

NAME
====

   Lingua::Stem::EnBroken - Porter's stemming algorithm for 'generic'
English

SYNOPSIS
========

     use Lingua::Stem::EnBroken;
     my $stems   = Lingua::Stem::EnBroken::stem({ -words => $word_list_reference,
                                         -locale => 'en',
                                     -exceptions => $exceptions_hash,
                                      });

DESCRIPTION
===========

   This routine MIS-applies the Porter Stemming Algorithm to its
parameters, returning the stemmed words. It is an intentionally broken
version of Lingua::Stem::En for people needing backwards compatibility with
Lingua::Stem 0.30 and Lingua::Stem 0.40. Do not use it if you aren't one
of those people.

   It is derived from the C program "stemmer.c" as found in freewais and
elsewhere, which contains these notes:

     Purpose:    Implementation of the Porter stemming algorithm documented
                 in: Porter, M.F., "An Algorithm For Suffix Stripping,"
                 Program 14 (3), July 1980, pp. 130-137.
     Provenance: Written by B. Frakes and C. Cox, 1986.

   I have re-interpreted areas that use Frakes and Cox's "WordSize"
function. My version may misbehave on short words starting with "y", but I
can't think of any examples.

   The step numbers correspond to Frakes and Cox, and are probably in
Porter's article (which I've not seen).  Porter's algorithm still has
rough spots (e.g current/currency, -ings words), which I've not attempted
to cure, although I have added support for the British -ise suffix.

CHANGES
=======

     2000.09.14 -  Forked from the Lingua::Stem::En.pm module to provide
                    a backward compatibly broken version for people needing
                    consistent behavior with 0.30 and 0.40 more than accurate
                    stemming.

METHODS
=======

stem({ -words => \@words, -locale => 'en', -exceptions => \%exceptions });
     Stems a list of passed words using the rules of US English. Returns
     an anonymous hash reference to the stemmed words.

     Example:

          my $stemmed_words = Lingua::Stem::EnBroken::stem({ -words => \@words,
                                                      -locale => 'en',
                                                  -exceptions => \%exceptions,
                                  });

stem_caching({ -level => 0|1|2 });
     Sets the level of stem caching.

     '0' means 'no caching'. This is the default level.

     '1' means 'cache per run'. This caches stemming results during a
     single     call to 'stem'.

     '2' means 'cache indefinitely'. This caches stemming results until
     either the process exits or the 'clear_stem_cache' method is called.

clear_stem_cache;
     Clears the cache of stemmed words

NOTES
=====

   This code is almost entirely derived from the Porter 2.1 module written
by Jim Richardson.

SEE ALSO
========

     Lingua::Stem

AUTHOR
======

     Jim Richardson, University of Sydney
     jimr@maths.usyd.edu.au or http://www.maths.usyd.edu.au:8000/jimr.html

     Integration in Lingua::Stem by
     Benjamin Franz, FreeRun Technologies,
     snowhare@nihongo.org or http://www.nihongo.org/snowhare/

COPYRIGHT
=========

   Jim Richardson, University of Sydney Benjamin Franz, FreeRun
Technologies

   This code is freely available under the same terms as Perl.

BUGS
====

TODO
====

Perl extension for accessing and manipulating Wordnet databases.
****************************************************************

NAME
====

   Lingua::Wordnet - Perl extension for accessing and manipulating Wordnet
databases.

SYNOPSIS
========

     use Lingua::Wordnet;
     use Lingua::Wordnet::Analysis;

     $wn->unlock();
     $synset = $wn->lookup_synset("canary","n",4);
     $synset2 = $wn->lookup_synset("small","a",1);
     $synset->add_attributes($synset2);
     $synset->write();
     print $synset, "\n";
     $wn->close();

DESCRIPTION
===========

   Wordnet is a lexical reference system inspired by current
psycholinguitics theories of human lexical memory. This module allows
access to the Wordnet lexicon from Perl applications, as well as
manipulation and extension of the lexicon. Lingua::Wordnet::Analysis
provides numerous high-level extensions to the system.

   Version 0.1 was a complete rewrite of the module in pure Perl, whereas
the old module embedded the Wordnet C API functions. In order to use the
module, the database files must first be converted to Berkeley DB files
using the 'scripts/convertdb.pl' file. Why did I do that?

   - The Wordnet API consists mostly of searching and text manipulation
functions, something Perl is, um .. well suited for.

   - Data retrieval is more fast with the hash lookup than with the binary
searches

   - Converting the databases allows optional manipulation of the data,
including adding and editing synsets, as well as extension of the system
to allow for more pointer types (including noun attributes and
'functions').

     - Developers can use the Wordnet databases without needing to compile the Wordnet API and browsers, allowing Wordnet to run on any Perl/Berkeley DB-capable platform (the database files are still needed for the conversion, of course)

   - A pure Perl implementation allows easier debugging and modification
for people who want to experiment or alter the processing.

   With that said, there are actually two modules. Lingua::Wordnet
impersonates the basic Wordnet API functions for searching and retrieving
data, as well as adding, editing, and deleting synsets.
Lingua::Wordnet::Analysis brings the interface up a level, allowing
commands like "is 'yellow' an attribute of any 'birds'", and taking care
of the recursive analysis.

Lingua::Wordnet functions
=========================

$wn = new Lingua::Wordnet( [DATA_DIR] );
     Creates and assigns a new object of class Lingua::Wordnet. DATA_DIR
     is optional, and indicates the location of the index and data files.

$wn->unlock()
     Allows files to be written to when data is added/edited/deleted.

$wn->lock()
     Locks files to prohibit write permissions (default).

$wn->grep(TEXT)
     Returns an array of compound words matching TEXT.

@synsets = $wn->lookup_synset( TEXT, POS [,NUMBER] )
     Assigns a list of synset objects (Lingua::Wordnet::Synset) matching
     TEXT within POS, where POS is 'n', 'v', 'a', 's' or 'r'. Without
     NUMBER, lookup_synset() will return all matches in POS. NUMBER is the
     sequential order of the desired synset within POS.

$synset = $wn->lookup_synset_offset(SYNSET_OFFSET)
     Assigns a synset object SYNSET_OFFSET.

$synset = $wn->new_synset(WORD,POS);
     Creates a new (empty) synset entry in the database. Both WORD and POS
     are required. An offset will be assigned when write() is called.

Lingua::Wordnet::Synset functions
=================================

@words = $synset->words([TEXT ..)]
     Retrieves or sets the list of words for this synset. add_words()
     should be used if you are only adding an entry, rather than setting
     all entries. Each word is in the format: TEXT%SENSE, where TEXT is
     the word, and SENSE is the sense number for the word. If SENSE is not
     supplied when assigning words to a synset, Lingua::Wordnet will
     assign the appropriate sense numbers to the words when
     $synset->write() is called (since they must be unique). In this case,
     the word list should consist only of the word text, without the '%'.
     The new words will be written to the data and index files.

$wn->familiarity(WORD, POS [, POLY_CNT])
     Returns an integer of the familiarity/polysemy count for WORD in POS.
     Given a third value POLY_CNT, sets the polysemy count for WORD in
     POS. In Lingua::Wordnet, this is a value which must be updated by the
     user, and is not automatically modified. This makes it useful for
     recording familiarity or frequency counts outside of the Wordnet
     lexicons. Note that polysemy within Lingua::Wordnet can be identified
     for a given word by counting the synsets returned by lookup_synset().

$wn->morph(WORD, POS)
     Returns a form of WORD in POS as found in the Wordnet morph files.
     The synset_lookup() functions performs morphological conversion
     automatically, so a call to morph() is not required.

$synset->overview()
     Returns the terms and gloss for the synset in a format for printing.
     This method is also used to overload a print performed on the synset.
     Note that this is different from the "overview" parameter of the 'wn'
     executable, since it only returns information about the current
     synset.

$synset->write()
     Writes any changes made to $synset to the database and updates all
     affected synset data and indexes. If $synset passes out of scope
     before write() is called, the changes are lost.

     All of following functions retrieve data in synsets. Each has two
     corresponding functions which can be called by prepending 'add_' or
     'delete_' before the function name. These functions accept a synset
     object or objects as input. Unless noted otherwise in the following
     functions, any returned data is a synset object or array of synset
     objects. See below for examples usages.

          $synset->antonyms()
          $synset->add_antonyms($synset2[, ...])
          $synset->delete_antonyms($synset2[, ...])

     Returns, adds, or deletes antonyms for $synset. WARNING: When
     adding/deleting synset pointers to Wordnet, it is important to add
     pointer entries to the corresponding synset in order to maintain
     database accuracy. Earlier versions of this module planned to
     automate this function, however, they have been abandoned in favor of
     having control over database writes with the 'write()' function, and
     are now considered functionality which belongs outside of the module.
     Thus, your program must implement the functionality to, in the above
     examples, add an antonym entry to '$synset' for '$synset2', in
     addition to adding an antonym entry to '$synset2' for '$synset'.

$synset->hypernyms()
     Returns hypernyms for $synset.

$synset->hyponyms()
     Returns hyponyms for $synset.

$synset->entailment()
     Returns verb entailment pointers.

$synset->synonyms()
     Returns synonyms for $synset. Note that all words within $synset are
     synonyms.

$synset->comp_meronyms()
     Returns component-object meronyms for $synset.

$synset->member_meronyms()
     Returns member-collection meronyms for $synset.

$synset->stuff_meronyms()
     Returns stuff-object meronyms for $synset (a.k.a. substance-object).

$synset->portion_meronyms()
     Returns portion-mass meronyms for $synset.

$synset->feature_meronyms()
     Returns feature-activity meronyms for $synset.

$synset->place_meronym()
     Returns place-area meronyms for $synset.

$synset->phase_meronym()
     Sets or returns phase-process meronyms for $synset.

$synset->all_meronyms()
     Returns an array of synset objects for all meronyms types of $synset.

$synset->all_holonyms()
     Returns an array of synset objects for all holonyms of $synset.

     The following seven functions mirror the above functionality for
     holonyms, and accordingly have corresponding add_ and delete_
     functions which update any set values to the corresponding meronym
     pointers:

$synset->comp_holonym()
$synset->member_holonym()
$synset->stuff_holonym()
$synset->portion_holonym()
$synset->feature_holonym()
$synset->place_holonym()
$synset->phase_holonym()
$synset->gloss([TEXT])
     Returns the glass for $synset. If TEXT is present, the gloss for
     $synset will be assigned that value.

$synset->attributes()
     Returns a list of synset objects of attribute pointers for $synset.

$synset->functions()
     Returns a list of synset objects of function pointers for $synset.

$synset->causes()
     Returns the 'cause to' pointers for verbs.

$synset->pertainyms()
     Returns the 'pertains to' pointers for adj and adv.

$synset->frames()
     Returns a text array of verb frames for $synset. The add_frames() and
     delete_frames() functions accept only integers corresponding to the
     frames. The list of frames can be edited in Wordnet.pm directly, but
     probably shouldn't be.

$synset->lex_info([INT])
     Returns a string containing lexicographer file information. The
     optional INT assigns the lexicographer file information, and should
     correspond to the file list in Wordnet.pm.

$synset->offset()
     Returns the synset offset of $synset.

EXAMPLES
========

   Extensive examples can be found in the 'scripts/' directory; here I will
summarize the basic functionality. There are also some examples in the pod
documentation for Lingua::Wordnet::Analysis.

   This will display a hypernym tree for $synset:

     my $synset = $wn->lookup_synset_offset("00300911%n");
     while ($synset = ($synset->hypernyms)[0]) {
        $i++;
        print " "x$i, "->", $synset->words, "\n";
     }

   Outputting the following for synset "baseball":

     -> field_game%0
      -> outdoor_game%0
       -> athletic_game%0
        -> sport%0athletics%0
         -> diversion%0recreation%0
          -> activity%0
           -> act%0human_action%0human_activity%0

   The example below will create a synset object and print a list of the
hyponyms for that object:

   use Lingua::Wordnet;  my $wn = new Lingua::Wordnet;  my $synset =
$wn->lookup_synset("baseball","n",1);  print "The following are kinds of
baseball games:\n";  foreach $bb_synset ($synset->hyponyms) {      my
$words;      foreach $word ($bb_synset->words) {          $word =~
s/\%\d+$//; $word =~ s/\_/ /g;          $words .= "$word, ";      }
$words =~ s/\,\s*$//;      print "  $words\n";  }  $wn->close();

   This will output:

     The following are kinds of baseball games:
       professional baseball
       hardball
       perfect game
       no-hit game, no-hitter
       one-hitter, 1-hitter
       two-hitter, 2-hitter
       three-hitter, 3-hitter
       four-hitter, 4-hitter
       five-hitter, 5-hitter
       softball, softball game
       rounders
       stickball, stickball game

   And an assignment example. This will create a new synset and add it to
the kinds of baseball games. We unlock the Wordnet files to enable changes
to the database:

     use Lingua::Wordnet;
     my $wn = new Lingua::Wordnet;
     $wn->unlock();
     my $synset = $wn->lookup_synset("baseball","n",1);
     my $newsynset = $wn->new_synset("fooball","n");
     $newsynset->gloss("A baseball game in which a foo is used.");
     $synset->add_hyponym($newsynset);
     $wn->close();

   Remember, proceeded most synset functions with "add" will append the
supplied data to the corresponding field, rather than replacing its value.

   We could add an attribute 'fun' to "fooball" thus (not necessarily
recommended pointer, but it will suffice for an example):

     $fun_synset = $wn->lookup_synset("fun","adj",1);
     $newsynset->add_attributes($fun_synset);

   See the Lingua::Wordnet::Analysis documentation for examples to
retrieving and searching entire trees and inheritance functions.

BUGS/TODO
=========

   Please send bugs and suggestions/requests to dbrian@brians.org.
Development on this module is active as of Spring 2001.

   Clean up code, put references where beneficial.

AUTHOR
======

   Dan Brian <dbrian@brians.org>

SEE ALSO
========

   Lingua::Wordnet::Analysis.

Perl extension for high-level processing of Wordnet databases.
**************************************************************

NAME
====

   Lingua::Wordnet::Analysis - Perl extension for high-level processing of
Wordnet databases.

SYNOPSIS
========

     use Lingua::Wordnet::Analysis;

     $analysis = new Lingua::Wordnet::Analysis;

     # How many articles of clothing have 'tongues'?
     $tongue = $wn->lookup_synset("tongue","n",2);
     @articles = $analysis->search($clothes,$tongue,"all_meronyms");

     # Are there any parts, of any kinds, of any shoes, made of glass?
     @shoe_types = $analysis->traverse("hyponyms",$shoes);
     $count = $analysis->search(@shoe_types,$glass,"stuff_meronyms");

     # Compute the intersection of two lists of synsets
     @array1 = $shoes->all_holonyms;
     @intersect = $analysis->intersection
           (\@{$shoes->attributes},\@{$socks->attributes});

     # Generate a list of the inherited comp_meronyms for "apple"
     @apple_hypernyms = $analysis->traverse("hypernyms",$apple);
     @apple_parts = $analysis->traverse("comp_meronyms",@apple_hypernyms);

DESCRIPTION
===========

   Lingua::Wordnet::Analysis supplies high-level functions for analysis of
word relationships. Most of these functions process and return potentially
large amounts of data, so only use them if you "know what you are doing."

   These functions could have been put into Lingua::Wordnet::Synset
objects, but I wanted to keep those limited to core functionality.
Besides, many of these functions have unproven usefulness.

Lingua::Wordnet::Analysis functions
===================================

$analysis->match(SYNSET,ARRAY)
     Finds any occurance of SYNSET in the synset list ARRAY and the list's
     pointers. Returns a positive value if a match is found. match() does
     not traverse.

$analysis->search(SYNSET1,SYNSET2,POINTER)
     Searches all pointers of type POINTER in SYNSET1 for SYNSET2.
     search() is recursive, and will traverse all depths. Returns the
     number of matches.

$analysis->traverse(POINTER,SYNSET)
     Traverses all pointer types of POINTER in SYNSET and returns a list
     of all synsets found in the tree.

$analysis->coordinates(SYNSET)
     Returns a list of the coordinate sisters of SYNSET.

$analysis->union(LIST)
     Returns a list of synsets which is the union of synsets LIST. The
     union consists of synsets which occur in any lists. This is useful,
     for example, for determining all the holonyms for two or more synsets.

$analysis->intersection(ref LIST)
     Returns a list of synsets of the intersection of ARRAY1 list of
     synsets with ARRAY2 list of synsets. The intersection consists of
     synsets which occur in both lists. This is useful, for example, to
     determine which meronyms are shared by two synsets:

          @synsets = $analysis->intersection
              (\@{$synset1->all_meronyms},\@{$synset2->all_meronyms});

$analysis->distance(SYNSET1,SYNSET2,POINTER)
     Returns an integer value representing the distance in pointers
     between SYNSET1 and SYNSET2 using POINTER as the search path.

EXAMPLES
========

   To print out an inherited meronym list, use traverse():

     $orange = $wn->lookup_synset("orange","n",1);
     @orange_hypernyms = $analysis->traverse("hypernyms",$orange);
     foreach ($analysis->traverse("all_meronyms",@orange_hypernyms)) {
         print $_->words, "\n";
     }

   Note that the inherited meronyms will not contain the direct meronyms of
$orange.

BUGS/TODO
=========

   There is tons that could go in this module ... submissions are welcome!

   Lots of cleanup.

   Need to add a search_path function that will return a path to a match
as a linked list or hash of hashes.

   Some might want inherited meronym/holonym trees.

   Please send bugs and suggestions/requests to dbrian@brians.org.
Development on this module is active as of Winter 2000.

AUTHOR
======

   Dan Brian <dbrian@brians.org>

SEE ALSO
========

   Lingua::Wordnet.

Determine which processes have a file open
******************************************

NAME
====

   Linux::Fuser - Determine which processes have a file open

SYNOPSIS
========

     use Linux::Fuser;

     my $fuser = Linux::Fuser->new();

     my @procs = $fuser->fuser('foo');

     foreach my $proc ( @procs )
     {
       print $proc->pid(),"\t", $proc->user(),"\n",@{$proc->cmd()},"\n";
     }

DESCRIPTION
===========

   This module provides information similar to the Unix command 'fuser'
about which processes have a particular file open.  The way that this
works is highly unlikely to work on any other OS other than Linux and even
then it may not work on other than 2.2.* kernels.

   It should also be borne in mind that this may not produce entirely
accurate results unless you are running the program as the Superuser as
the module will require access to files in /proc that may only be readable
by their owner.

METHODS
-------

new
     The constructor of the object. It takes no arguments and returns a
     blessed reference suitable for calling the methods on.

fuser SCALAR $file
     Given the name of a file it will return a list of
     Linux::Fuser::Procinfo objects, one for each process that has the
     file open - this will be the empty list if no processes have the file
     open or undef if the file doesnt exist.

PER PROCESS METHODS
-------------------

   The fuser() method will return a list of objects of type
Linux::Fuser::Procinfo which itself has methods to return information
about the process.

user
     The login name of the user that started this process ( or more
     precisely that owns the file descriptor that the file is open on ).

pid
     The process id of the process that has the file open.

cmd
     The command line of the program that opened the file.  This actually
     returns a reference to an array containing the individual elements of
     the command line.

AUTHOR
======

   Jonathan Stowe, <jns@gellyfish.com>

SEE ALSO
========

   See Perl (perl.info). `proc(5)' in this node

   Lip::Pod - Literate Perl filter

   Leaves all pod code intact, and indents all non-pod code by two spaces.
=cut directives are eaten. An =head1, =cut pair is wrapped around the
output.  Lines consisting entirely of '#' (and at least 3 of them) are
ignored in the non-pod zones (to allow for dividing lines in the source
code).

   Defines a subclass of Pod::Parser which implements the indentation and
=cut skipping described in `SYNOPSIS' in this node.

   Print out the Literate Perl preamble.

   Pass through all commands, except =cut, which is not passed through so
that the entire output is POD.

   Print out the Literate Perl postamble.

   Indents non-POD paragraphs by two spaces.

   Lip::Pod - Literate Perl to POD conversion

     #!/usr/bin/perl -w
     use strict;
     use Lip::Pod;
     package main;
     my $parser = new Lip::Pod;
     $parser->parseopts( -want_nonPODs => 1, -process_cut_cmd => 1 );
     push @ARGV, '-' unless @ARGV;
     for (@ARGV) { $parser->parse_from_file($_); }
     exit 0;

   Donald Knuth introduced Literate Programming, which is the idea that
computer programs should be written in an expository style, as works of
literature.  He created a system called *web*, which implemented his ideas
for Pascal and TeX. Later, a derivative system, *cweb* was created for the
C programming language (with text still in TeX).

   Full Literate Programming in the style of Knuth involves disconnecting
the order of presentation to humans from the order of presentation to a
machine.  The input files written by the author/programmer are in an order
convenient for instructing the reader, not necessarily in the order
required to build an executable program. Programs then process the
combined text/code input to create human-readable output (the program is
called *weave* in Knuth's system), or compiler-appropriate output
(*tangle* in *web*).

   This module implements a very simple Literate Programming capability for
Perl. Just as Perl's Plain Old Documentation (POD) is intended to be just
powerful enough to be useful, and easy for the programmer, Literate Perl
(LIP) is intended to bring the basic benefits of Literate Programming to
Perl without radically altering the way programmers/authors work.

   When you use LIP, you put the contents of your source file in the best
order you can for exposition that does not interfere with its function.
This may involve, for example, alphabetizing subroutines and/or grouping
them by some criteria. Here is a simple example:

     #!/usr/bin/perl -w
     use strict;

     =begin lip

     =head1 NAME

     hello - LIP example

     =head1 IMPLEMENTATION

     Print a friendly message to standard output.

     =cut

     print "Hello, world!\n";

     exit 0;

     =end lip

     =cut

   Running this program will have the expected result. Running it through
*lip2pod* will select the internal documenation and include the code itself
as verbatim paragraphs. This results in POD output that can be formatted
nicely by one of the *pod2** "podlators".

   External documenation (like this) can be tacked on to the end of a file
as usual. So, adding these lines to the end of the example above:

     __END__

     =head1 NAME

     hello - LIP example

     =head1 SYNOPSIS

     hello

     =head1 DESCRIPTION

     A simple example used to demonstrate the use of B<Lip::Pod> and B<lip2pod>.

     =cut

   results in a single file that

   * is executable; and

   * contains internal documentation that can be formatted nicely (after
     conversion via *lip2pod*; and

   * contains external documentation using the same mechanism as non-LIP
     files.

   This module leverages the Pod::Parser and *Text::Tabs* modules.
Pod::Parser is a standard module as of Perl version 5.6. For use with
prior versions of Perl, download the latest copy from the CPAN.

   * Knuth, Donald Ervin. *Literate Programming*, Center for the Study of
     Language and Information, 1992. ISBN 0-987073-80-6 (paper).

   Gregor N. Purdy <gregor@focusresearch.com>

   This program is free software. You may copy or redistribute it under the
same terms as Perl itself.

Intersperse / unsort / disperse a list
**************************************

NAME
====

   List::Intersperse - Intersperse / unsort / disperse a list

SYNOPSIS
========

     use List::Intersperse qw/intersperseq/;

     @ispersed = intersperseq {substr($_[0],0,1)} qw/A1 A2 B1 B2 C1 C2/;

     @ispersed = List::Intersperse::intersperse qw/A A B B B B B B C/;

DESCRIPTION
===========

   intersperse and intersperseq evenly distribute elements of a list.
Elements that are considered equal are spaced as far apart from each other
as possible.

FUNCTIONS
=========

intersperse LIST
     This function returns a list of elements interspersed so that
     equivalent items are evenly distributed throughout the list.

intersperseq BLOCK LIST
     intersperseq works like intersperse but it applies BLOCK to the
     elements of LIST to determine the equivalance key.

AUTHORS
=======

     This module was written by
     Tim Ayers (http://search.cpan.org/search?mode=author&query=tayers) and
     John Porter (http://search.cpan.org/search?mode=author&query=jdporter).

ACKNOWLEDGEMENTS
================

   Thanks to John Porter for providing and implementing an improved
algorithm for solving the problem.

COPYRIGHT
=========

   Copyright (c) 2001 Tim Ayers and John Porter.

   All rights reserved. This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

Process all possible permutations of a list
*******************************************

NAME
====

   List::Permutor - Process all possible permutations of a list

SYNOPSIS
========

     use List::Permutor;
     my $perm = new List::Permutor qw/ fred barney betty /;
     while (my @set = $perm->next) {
         print "One order is @set.\n";
     }

DESCRIPTION
===========

   Make the object by passing a list of the objects to be permuted. Each
time that next() is called, another permutation will be returned. When
there are no more, it returns the empty list.

METHODS
=======

new LIST
     Returns a permutor for the given items.

next
     Returns a list of the items in the next permutation. Permutations are
     returned "in order". That is, the permutations of (1..5) will be
     sorted numerically: The first is (1, 2, 3, 4, 5) and the last is (5,
     4, 3, 2, 1).

peek
     Returns the list of items which would be returned by next(), but
     doesn't advance the sequence. Could be useful if you wished to skip
     over just a few unwanted permutations.

reset
     Resets the iterator to the start. May be used at any time, whether the
     entire set has been produced or not. Has no useful return value.

AUTHOR
======

   Tom Phoenix <rootbeer@redcat.com>

A selection of general-utility list subroutines
***********************************************

NAME
====

   List::Util - A selection of general-utility list subroutines

SYNOPSIS
========

     use List::Util qw(first sum min max minstr maxstr reduce);

DESCRIPTION
===========

   `List::Util' contains a selection of subroutines that people have
expressed would be nice to have in the perl core, but the usage would not
really be high enough to warrant the use of a keyword, and the size so
small such that being individual extensions would be wasteful.

   By default `List::Util' does not export any subroutines. The
subroutines defined are

first BLOCK LIST
     Similar to grep in that it evaluates BLOCK setting $_ to each element
     of LIST in turn. first returns the first element where the result from
     BLOCK is a true value. If BLOCK never returns true or LIST was empty
     then undef is returned.

          $foo = first { defined($_) } @list    # first defined value in @list
          $foo = first { $_ > $value } @list    # first value in @list which
                                                # is greater than $value

          This function could be implemented using C<reduce> like this

          $foo = reduce { defined($a) ? $a : wanted($b) ? $b : undef } undef, @list

     for example wanted() could be defined() which would return the first
     defined value in @list

max LIST
     Returns the entry in the list with the highest numerical value. If the
     list is empty then undef is returned.

          $foo = max 1..10                # 10
          $foo = max 3,9,12               # 12
          $foo = max @bar, @baz           # whatever

     This function could be implemented using reduce like this

          $foo = reduce { $a > $b ? $a : $b } 1..10

maxstr LIST
     Similar to max, but treats all the entries in the list as strings and
     returns the highest string as defined by the gt operator.  If the
     list is empty then undef is returned.

     $foo = maxstr 'A'..'Z'     	    # 'Z'     $foo = maxstr
     "hello","world"   # "world"     $foo = maxstr @bar, @baz        #
     whatever

     This function could be implemented using reduce like this

          $foo = reduce { $a gt $b ? $a : $b } 'A'..'Z'

min LIST
     Similar to max but returns the entry in the list with the lowest
     numerical value. If the list is empty then undef is returned.

          $foo = min 1..10                # 1
          $foo = min 3,9,12               # 3
          $foo = min @bar, @baz           # whatever

     This function could be implemented using reduce like this

          $foo = reduce { $a < $b ? $a : $b } 1..10

minstr LIST
     Similar to min, but treats all the entries in the list as strings and
     returns the lowest string as defined by the lt operator.  If the list
     is empty then undef is returned.

          $foo = maxstr 'A'..'Z'     	    # 'A'
          $foo = maxstr "hello","world"   # "hello"
          $foo = maxstr @bar, @baz        # whatever

     This function could be implemented using reduce like this

          $foo = reduce { $a lt $b ? $a : $b } 'A'..'Z'

reduce BLOCK LIST
     Reduces LIST by calling BLOCK multiple times, setting `$a' and $b
     each time. The first call will be with `$a' and $b set to the first
     two elements of the list, subsequent calls will be done by setting
     `$a' to the result of the previous call and $b to the next element in
     the list.

     Returns the result of the last call to BLOCK. If LIST is empty then
     undef is returned. If LIST only contains one element then that
     element is returned and BLOCK is not executed.

          $foo = reduce { $a < $b ? $a : $b } 1..10       # min
          $foo = reduce { $a lt $b ? $a : $b } 'aa'..'zz' # minstr
          $foo = reduce { $a + $b } 1 .. 10               # sum
          $foo = reduce { $a . $b } @bar                  # concat

sum LIST
     Returns the sum of all the elements in LIST.

          $foo = sum 1..10                # 55
          $foo = sum 3,9,12               # 24
          $foo = sum @bar, @baz           # whatever

     This function could be implemented using reduce like this

          $foo = reduce { $a + $b } 1..10

SUGGESTED ADDITIONS
===================

   The following are additions that have been requested, but I have been
reluctant to add due to them being very simple to implement in perl

     # One argument is true

     sub any { $_ && return 1 for @_; 0 }

     # All arguments are true

     sub all { $_ || return 0 for @_; 1 }

     # All arguments are false

     sub none { $_ && return 0 for @_; 1 }

     # One argument is false

     sub notall { $_ || return 1 for @_; 0 }

     # How many elements are true

     sub true { scalar grep { $_ } @_ }

     # How many elements are false

     sub false { scalar grep { !$_ } @_ }

COPYRIGHT
=========

   Copyright (c) 1997-2000 Graham Barr <gbarr@pobox.com>. All rights
reserved.  This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

HTML Conversion for LiveGe'ez
*****************************

NAME
====

   LiveGeez::CacheAsSERA - HTML Conversion for LiveGe'ez

SYNOPSIS
========

   $cacheFile = LiveGeez::CacheAsSERA::HTML($f, $sourceFile)

   Where $f is a File.pm object and $sourceFile is the pre-cached file
name.

DESCRIPTION
===========

   CacheAsSERA.pm contains the routines for conversion of HTML document
content from Ethiopic encoding systems into SERA for document caching and
later conversion into other Ethiopic systems.

AUTHOR
======

   Daniel Yacob,
`LibEth@EthiopiaOnline.Net|mailto:LibEth@EthiopiaOnline.Net' in this node

SEE ALSO
========

   perl(1).  Ethiopic(3).  `http:' in this node

Parse a LiveGe'ez CGI Query
***************************

NAME
====

   LiveGeez::Request - Parse a LiveGe'ez CGI Query

SYNOPSIS
========

     use LiveGeez::Request;
     use LiveGeez::Services;

     main:
     {

     my $r = LiveGeez::Request->new;

     ProcessRequest ( $r ) || $r->DieCgi ( "Unrecognized Request." );

     exit (0);

     }

DESCRIPTION
===========

   Request.pm instantiates an object that contains a parsed LiveGe'ez
query.  Upon instantiation the environment is checked for CGI info and
cookie data is read and used.  This does *NOT* happen if a populated hash
table is passed (in which case the hash data is applied) or if "0" is
passed as an arguement.  The request object is required by any other
LiveGe'ez function of object.

AUTHOR
======

   Daniel Yacob,
`LibEth@EthiopiaOnline.Net|mailto:LibEth@EthiopiaOnline.Net' in this node

SEE ALSO
========

   perl(1).  Ethiopic(3).  `http:' in this node

File Openning and Caching for LiveGe'ez
***************************************

NAME
====

   LiveGeez::File - File Openning and Caching for LiveGe'ez

SYNOPSIS
========

     use LiveGeez::Request;
     use LiveGeez::File;

     main:
     {

     my $r = LiveGeez::Request->new;

     my $f = LiveGeez::File->new ( $r );

     $f->Display;

     exit (0);

     }

DESCRIPTION
===========

   File.pm instantiates an object for processing an Ethiopic text or HTML
document.  The constructor requires a LiveGeez::Request object as an
argument.

AUTHOR
======

   Daniel Yacob,
`LibEth@EthiopiaOnline.Net|mailto:LibEth@EthiopiaOnline.Net' in this node

SEE ALSO
========

   perl(1).  Ethiopic(3).  `http:' in this node

HTML Conversions for LiveGe'ez
******************************

NAME
====

   LiveGeez::HTML - HTML Conversions for LiveGe'ez

SYNOPSIS
========

   FileBuffer ( $f );  # Where $f is a File.pm object.

DESCRIPTION
===========

   HTML.pm contains the routines for conversion of HTML document content
between Ethiopic encoding systems and for pre-interpretation of HTML
markups for compliance with the LiveGe'ez Remote Processing Protocol.

AUTHOR
======

   Daniel Yacob,
`LibEth@EthiopiaOnline.Net|mailto:LibEth@EthiopiaOnline.Net' in this node

SEE ALSO
========

   perl(1).  Ethiopic(3).  `http:' in this node

Site Specific Settings for Your LiveGe'ez Installation
******************************************************

NAME
====

   Local - Site Specific Settings for Your LiveGe'ez Installation

SYNOPSIS
========

   use LiveGeez::Local;

DESCRIPTION
===========

   Local.pm is a required module by all other LiveGe'ez modules.  Local.pm
contains site specific settings for default encoding systems, language,
and paths:

'$webRoot'
     Full file system path to where you publish HTML documents.

'$cgiDir'
     Full file system path to where you keep CGI files.

'$scriptURL'
     Complete URL to your Zobel front end script.

'$scriptBase'
     The same front end script with respect to the server root.

'$URLCacheDir'
     Directory where to cache converted documents downloaded by URL.  The
     path may be absolute or relative to where Zobel executes.

'$FileCacheDir'
     Directory where to cache local converted documents.  The path may be
     absolute or relative to where Zobel executes.

'$defaultLang'
     Assumed language for processing transliterated documents and
     performing date conversions.

'$defaultSysIn'
     Assume local files are in this system for conversion input.

'$defaultSysOut'
     The font system for outputting converted documents when no system has
     been specified.

'$processURLs'
     A 0 or 1 value to permit the processing of remote documents.  "1" is a
     friendly value but heavy usage by external websites can impact your
     bandwidth costs and may slow down the processing of local documents
     as more Perl modules are loaded.  "0" restricts Zobel to processing
     only local documents.

'$checkFileDates'
     A 0 or 1 value to force Zobel to compare cached file dates to the
     original documents.  "1" makes Zobel compare dates, slightly
     impacting performance.  "0" prevents Zobel from checking file dates
     -you will then have to delete cache by hand or use the "no-cache"
     pragma to refresh cached documents.

'$iPath'
     Path with respect to the $webRoot where "Image" fidels are stored, if
     any.

'$defaultBGColor'
     The font system for outputting converted documents when no system has
     been specified.

'$cookieDomain'
     Your site name or domain for setting cookies.  Ethiopia Online uses
     ".ethiopiaonline.net".

'$cookieExpires'
     Date when domain cookie should expire.  Such as Menasse Zaudou's
     birthday "Thu, 11-Nov-99 00:00:00 GMT".

AUTHOR
======

   Daniel Yacob,
`LibEth@EthiopiaOnline.Net|mailto:LibEth@EthiopiaOnline.Net' in this node

SEE ALSO
========

   perl(1).  Ethiopic(3).  `http:' in this node

Parse a LiveGe'ez CGI Query
***************************

NAME
====

   LiveGeez::Request - Parse a LiveGe'ez CGI Query

SYNOPSIS
========

     use LiveGeez::Request;
     use LiveGeez::Services;

     main:
     {

     my $r = LiveGeez::Request->new;

     ProcessRequest ( $r ) || $r->DieCgi ( "Unrecognized Request." );

     exit (0);

     }

DESCRIPTION
===========

   Request.pm instantiates an object that contains a parsed LiveGe'ez
query.  Upon instantiation the environment is checked for CGI info and
cookie data is read and used.  This does *NOT* happen if a populated hash
table is passed (in which case the hash data is applied) or if "0" is
passed as an arguement.  The request object is required by any other
LiveGe'ez function of object.

AUTHOR
======

   Daniel Yacob,
`LibEth@EthiopiaOnline.Net|mailto:LibEth@EthiopiaOnline.Net' in this node

SEE ALSO
========

   perl(1).  Ethiopic(3).  `http:' in this node

Request Processing Services for LiveGe'ez
*****************************************

NAME
====

   LiveGeez::Services - Request Processing Services for LiveGe'ez

SYNOPSIS
========

     use LiveGeez::Request;
     use LiveGeez::Services;

     main:
     {

     my $r = LiveGeez::Request->new;

     ProcessRequest ( $r ) || $r->DieCgi ( "Unrecognized Request." );

     exit (0);

     }

DESCRIPTION
===========

   Services.pm provides request processing services for a LiveGe'ez query
as specified in the LiveGe'ez Remote Processing Protocol.  "ProcessRequest"
takes a LiveGe'ez LiveGeez::Request object and performs the appropriate
service.

AUTHOR
======

   Daniel Yacob,
`LibEth@EthiopiaOnline.Net|mailto:LibEth@EthiopiaOnline.Net' in this node

SEE ALSO
========

   perl(1).  Ethiopic(3).  `http:' in this node

WebSite Stress and Validation Tool
**********************************

NAME
====

   LoadWorm - WebSite Stress and Validation Tool

DESCRIPTION
===========

   The LoadWorm is a tool to load a website with requests, and to record
the resultant performance, from a web client's perspective.  It can also
be used for various investigative purposes, such as validation of the
website, or discovering all the referrers to a page, etc.

   It consists of two main parts -

     LoadWorm - traverses a website, pushing all the buttons, and entering
     data according to specific input instructions.  It will ignore
     specified URL's, limit the number of times a single page is visited,
     and limit the depth of the entire search.  The amount of processing
     required to perform all these tricks makes it too slow to act directly
     as a web-loading tool, so the LoadMaster/Slave was invented to handle
     that job.

     LoadMaster/Slave - Takes a list of URL's (such as that produced by
     the LoadWorm), and directs several "slaves", usually on seperate host
     computers, to make hits on these URL's at a tunable rate.  The
     "slaves" collect data on the response times (and successes/fails),
     which can be harvested and analyzed by the LoadMaster.

   The LoadWorm's operation is controlled by a configuration file.  The
LoadMaster/Slave reads the same configuration file for some of it's
configurables (proxy, verbosity, etc), but is controlled mainly through a
Tk based GUI.

   The LoadWorm and LoadMaster/Slave works on Windows NT and Unix (tested
on Solaris and Linux), or any combination of these systems.

WEBSITE TRAVERSAL
=================

   The LoadWorm takes one or more URLs as input (specified in its
configuration file, `loadworm.cfg').

   * It follows all links, down to a configurable depth.  You may specify
     a different depth limit for different branches of the website(s).

   * Ignores specific links, as specified by matching the URL to regular
     expressions in the configuration file.

   * Generates INPUT data for FORMs, and traverses every possible 'SELECT'
     option and 'SUBMIT' button (filterable by the 'ignore' statements in
     the configuration file).  (Non-multiple type of SELECT, only, in
     version 1.0).

   * The user may specify lists of values for each INPUT field of any of
     the FORMs.  (Text type, only, in version 1.0).

   * A check for a valid response can be customized for each URL (selected
     by a regular expression).  The validation routine can be written by
     the user, in Perl, and is automatically embedded into the process.

   * The results of a LoadWorm session are recorded in a Perl accessible
     database, including a list of all links (child to parent(s)), all
     errors encountered, all links that were ignored, all images that were
     downloaded, and the timings for every download.  The user's
     validation routine may also write to any of these tables.

   * A seperate program (LoadMaster/Slave) is a high intensity web loader
     that will take the route charted by the LoadWorm and repeat the whole
     route, performing the request, response and validation steps without
     the overhead of the route calculations inherent in the LoadWorm's
     configuration.

   * For known bugs and limitations, see `NOTES' in this node, at the
     bottom of this document.

WEBSITE LOADING
===============

   Website loading is performed by the LoadMaster program. The LoadMaster
runs on a master computer.  One or more LoadSlaves may run on the same
computer, or different computers on the same network.  The operator can
control all LoadSlaves from the LoadMaster.  He can start them, pause them,
and tune the loading rate (e.g., total hits per second).

   Which URL's are actually loaded by the LoadSlaves is specified in a
file named `visits.txt'.  This is simply a list of fully specified URL's,
with CGI parameters, such as the one generated by the LoadWorm.  (The PUT
method is not yet implemented here).

   The LoadMaster also reads some parameters from the same configuration
file that serves the LoadWorm.  It conveys these parameters to all the
LoadSlaves, as well as transmitting to them the visits list.

   Each LoadSlave can be configured with a simple rewrite mechanism to
replace specified parameters in each URL with a value received from a
previous response.  Thus, if the website supports it's session state via a
CGI parameter, each slave can log itself in as a seperate session.  This
simple mechanism can be enhanced by working over the Perl code.

   Since it does not need to do any special calculations for laying down
the route, the LoadSlave can perform its operations quickly, utilizing
less memory, than the LoadWorm.  This makes it possible to run several
slaves on the same host computer.  Each LoadSlave must be started manually
on each of the several hosts.  This simplifies the security situation, as
the LoadMaster does not need to directly control anyone else's computer.
Give each LoadSlave the IP address of the LoadMaster when you start each
LoadSlave.  You can start the LoadMaster first, or all the LoadSlaves
first, or in any combination.

   Thus, on the master host computer, use the command:

     `perl loadmaster.pl'

   and on each slave computer, use the command:

     `perl loadslave.pl {IP_ADDR:port_number of LoadMaster}'

   The IP_ADDR and port number of the LoadMaster is displayed on the
LoadMaster GUI when you start it up.  The default port number of the
LoadMaster is 9676 ("WORM" on a phone pad), but it's possible to come up
differently, especially if you're running two LoadMasters on the same
computer.

   If the LoadMaster crashes, or is turned off, the LoadSlaves will wait
patiently for it to come back up, and each will reconnect when it does.
To finish a test, you can terminate all the LoadSlaves from the LoadMaster
GUI, then terminate the LoadMaster.  The owners of the host computers
you've borrowed for the load test might want to terminate the test on
their computer.  They can do that by closing the LoadSlave on their
computer, with no ill effect on your test except for the lost data and
load.

THE CONFIGURATION FILE
======================

   The process of the LoadWorm is controlled by its configuration file.
This file is named `loadworm.cfg', and is found in the current working
directory.  It is structured like a profile.ini file, with [section]
specifying seperate sections, and with parameters and attribute=value
pairs within each section.  The sections include:

[Mode]
     Various modes are set here; depth, timeouts, printing, error
     management, etc.  See `"[Mode]"' in this node.

[Traverse]
     URLs listed here are the anchor(s) of the target website.  See
     `"[Traverse]"' in this node.

[Ignore]
     URLs listed here will be ignored in the traversal.  See `"[Ignore]"'
     in this node.

[Input]
     The user may specify values to be tried as input to each INPUT field
     in each FORM.  See `"[Input]"' in this node.

[Limit]
     To prevent infinite recursion, each page is visited a limited number
     of times (see "Recurse" in `"[Mode]"' in this node).  In the section
     you can specify different limits for different pages.  See
     `"[Limit]"' in this node.

[ReferersReport]
     The webpages that link to the URLs listed here will be recorded as
     such in a "links" database.  See `"[ReferersReport]"' in this node.

[Validation]
     User customizable routines to validate the data that is returned for
     each URL requested.  See `"[Validation]"' in this node.

[Proxy]
     A URL specifying the location of the proxy for web access, if any.
     See `"[Proxy]"' in this node.

[NoProxy]
     Domain names for which the proxy is not to be used.  See
     `"[NoProxy]"' in this node.

[Credentials]
     Authentication credentials for different net locations and realms.
     See `"[Credentials]"' in this node.

[Mode]
------

Depth = n
     The loadworm will go to a maximum of 'n' links down from the anchor
     URL.  Depth=1 would load only the anchor page, and none of its links.

Random = {0,1}
     If non-zero, then links will be traversed in random order, rather
     than in the order that they appear in the visits file.  A value of 1
     will traverse all links in random order.

Recurse = n
     Each URL will be traversed only once, unless the Recurse value is
     more than one.  Then each URL will be traversed the number of times
     specified by Recurse.

Timeout = secs
     Specifies the timeout period for all links (in seconds).  If a link
     does not download completely within the time specified by this value,
     then it is considered a timeout error.  Default = 120 seconds.

NoImages = {0,1}
     If non-zero, ignores all image links.

Verbose = {0,1}
     Controls the verbosity of standard output as the loadworm processes.
     Use 0 for the greatest degree of quiet. Reports on the actual
     performance of the loadworm are created from a database the loadworm
     creates.

Harvest = {0,1}
     Turns off/on the option to harvest the results from the loadslaves.
     Turning it off improves managability, since the slaves then do not
     need to maintain a record of the results.  This also reduces disk
     thrashing when multiple loadslaves are running on a host.  Harvest=0
     is useful if you are monitoring the load on the server's side.

[Traverse]
----------

   Specifies the URL(s) that are the anchor(s) of this test.  These are
the URL(s) that are the anchor(s) of the website to be tested by this
loadworm execution.

[Ignore]
--------

   A list of regular expressions which, if matching a generated URL, will
cause that URL to be ignored.  For instance, .*\.netscape\.com would
prevent the loadworm from traversing any link to the websites of Netscape.
Note that if the URL is explicitly listed in the [Traverse] section, then
any [Ignore] match will, in its turn, be ignored.

[ReferersReport]
----------------

   A list of regular expressions which, when they match a generated URL,
will record in a database all webpages that link to that URL.

[Validation]
------------

   Each link can be validated with a custom Perl subroutine.  The
subroutine is selected by matching the URL to a regex.  The subroutine is
given the URL and the resultant webpage.  The validation routine can then
verify the accuracy of the response, and can write to the loadworm
database files to record successes and/or errors.  Particularly, the
checks table is reserved for this.  It is tied to the hash
`%main::Checks', which is conventionally a hash whose keys are the URLs,
and whose values are whatever string the validation routine wishes to
report about this URL/response pair.  A zero returned from the validation
routine will tell the loadworm to ignore all links within this page.  A
non-zero return will allow normal processing to continue.  For example:

     `.*=AnyURL.pm::Check'

   This will match any URL, and will call your subroutine, "Check", in
your package "AnyURL.pm".  AnyURL.pm must be in the @INC path, and must
include a package statement (e.g. package AnyURL).  See the example,
AnyURL.pm. for details.

[Proxy]
-------

   A URL specifying the location of the proxy for web access, if any.

[NoProxy]
---------

   Domain names for which the proxy is not to be used.

[Credentials]
-------------

   Specifies a list of user ids and passwords for each of the realms that
may require authentication.  The "net location" and "realm" are seperated
by a slash, then "user id" and "password" are seperated by a comma.
"Netlocation/realm" and "userid,password" are then associated with an
equals sign, as in:

     webdev.savesmart.com/Test Server=MyID,twi9y

   "webdev.savemart.com" is the net location, "Test Server" is the realm,
"MyID" is the user id, and "twi9y" is the password.

[Input]
-------

   Each line specifies a list of values to be iterated across whenever a
URL and INPUT line name match the specified regular expression.  The list
is specified as a Perl statement suitable for eval.  This feature will
later allow more elaborate input generation, but for now it allows the
specification of a list of values via qw(list).  For example:

     `login.get, name = qw(test1)'

     `login.get, cardnumber = qw(test1234)'

     `login.get, email = NULL'

   The URL is matched to the first regex (before the comma), then the NAME
of the INPUT field is matched to the second regex (following the comma).
Then the list of values specified by the perl statement (following the
equals sign) is iterated on the matched URL.  The special syntax of NULL
is provided to allow the field to have a null value.

[Limit]
-------

   Each line specifies a regex that will match a URL, and the number of
times that that URL should be visited in a LoadWorm traversal.  Thus,

     `owa/categories\.get=50'

     `owa/favorite\.get=10'

     `owa/cart\.get=5'

     `owa/specials\.get=10'

     `owa/search\.get=10'

   The *owa/categories.get* CGI script will be called only 50 times in the
traversal, *owa/favorite.get* only 10, *owa/cart.get* only 5, etc.  The
count is for all URLs that match these regular expressions.  Thus, it
doesn't matter what the CGI parameters might be to these CGI scripts, the
scripts themselves will be called only as many times as the [Limit]
section specifies.

Example of a Configuration File
-------------------------------

     [Mode]
     Harvest=1
     Depth=10
     Random=1
     Recurse=
     Timeout=30
     Verbose=0
     NoImages=0
     UserAgent=Mozilla/4.01 [en] (WinNT; I)
     Editor="C:\Program Files\TextPad\TxtPad32.exe"

     [Traverse]
     http://webdev.savesmart.com

     [Credentials]
     webdev.savesmart.com/Test Server=MyID,twi9y

     [Ignore]
     www\.
     www6\.
     maps\.
     justgo\.com
     netscape\.com
     /owa/go_home\.get.*

     [Limit]
     owa/categories\.get=50
     owa/favorite\.get=10
     owa/cart\.get=5
     owa/specials\.get=10
     owa/search\.get=10

     [ReferersReport]
     \.savesmart\.com:900\/
     favorite\.get

     [Validation]

     [Proxy]
     http://ssgw.savesmart.com

     [NoProxy]
     admin
     webdev.savesmart.com

     [Input]
     login.get,name=qw(test1)
     login.get,cardnumber=qw(test1234)
     login.get,email=NULL

THE RESULTS DATABASE
====================

   *NOTE: This information is not current, but it gives you the general
idea of what is possible once we tie up a few loose ends.*

   The results of a session of LoadWorm are recorded in a Perl accessible
database.  Although some information is printed to standard output as the
session progresses, the most interesting results should be discovered by
scanning the LoadWorm database for that session.  The database consists of
several hash-tied tables.  Each table is keyed by the URL associated with
it, and the value will be a string representing the result.  For some of
these tables, the result is an array of strings representing several
interactions with that URL.  Unfortunately, Perl's built-in Tie::Hash will
not record arrays in a tied table.  For these tables, the data is
converted to ASCII text data and written to a sequential file.  The Perl
code listed below can be used to pull this sequential file back into a
hashed array in your Perl report generator.

referers
     This relates URLs of the website to the parent pages that contain
     them.  @referers{$childURL} is an array of URLs of pages that link to
     $childURL.  (This table does not include images.  These are recorded
     in the images table.  It does include all ignored URLs.)  Note: this
     file is not a hash-tied database file, but a sequential file
     containing data that can be imported into a hashed table with the
     Perl code listed below (tbl2hash.pl).

errors
     This is a list of all the URLs that failed to download.
     $errors{$URL} is the error message associated with the attempt to
     download $URL.

ignores
     This is a list of all URLs that were encountered in the website, but
     were ignored because they match some regular expression in the
     [Ignore] section of the configuration file.  $ignore{$URL} is the
     regular expression that caused $URL to be included in this list.

timings
     This text file records the time of each request, and the time of
     completion of that request.  Each record consists of two (or more)
     lines.  The first line contains the URL.  The second line contains
     the start time, the finish time, and the size in a string like
     (hh:mm:ss.hh,hh:mm:ss.hh size).  The size might be the string
     "FAILED", instead, indicating that the request failed.  Then, the
     following lines will contain the reason for the failure, until a line
     containing a copy of the original "FAILED" line.  Thus, timings
     includes the time for failed downloads as well as successful ones.

checks
     This table is written by the user-customized validation routine(s).

          tbl2hash.pl

          %Linkages = ();
          open TBL, "<linkages";
          while ( <TBL> )  {
          	if ( $_ !~ /^\s/ )  {
          		$ky = $_;
          	}
          	else {
          		s/^\s*//;
          		push @{  $Linkages{$ky}  }, $_;
          	}
          }

NOTES
=====

   * Watch for #tag in CGI function names.

   * To specify an image click position, define the key as the image name,
     and the value as "image.x=x&image.y=y".

   * Due to our as yet incomplete control of the TCP/IP layer in this
     program, we can not actually duplicate the conditions of modem (or
     any other low data rate) access to the website.  Some conditions of
     our multiple client, high speed data transfers will be different than
     when many clients are accessing the website at lower speeds.

   * Each loadslave is limited to twenty-three simultaneous connections.
     Subsequent connections fail when trying to register (or is it when
     trying to connect?).  This is a limitation imposed by the operating
     system when the Perl executable was compiled.  We have hard-coded a
     governor at 20 connections to avoid this limit.  Multiple instances
     may be run on a single host, but each one has the same limit.

   * The LoadMaster can not accept connections from more that 28
     LoadSlaves (for the same reason).

   * Consequently, the upper limit to the loadtest is 28x23, or 644
     simultaneous connections to the web-server.  Is there anyway to
     increase this?  We can run multiple loadmasters, I suppose; does it
     make sense, then, to have a super-loadmaster, or perhaps loadslave
     monitors, so that the load master talks to one slave monitor, which
     deals with the (up to twenty-eight) loadslaves on it's own NT?  Etc.

PREREQUESITES
=============

   These are the versions of Perl modules under which LoadWorm is known to
work.  It may be just fine with earlier or later versions.

   * Perl 5.004 (thanks, Larry!)

   * `LWP' from libwww-perl-5_20

   * `LWP::Parallel' from ParallelUserAgent-v2_31 (a special thanks to
     Marc Langheinrich!)

   * Tk from Tk402_003

   * Time::Local and `Time::HiRes' for Unix OS.

   * Win32 for Win32 OS.

   * And various core Perl modules, including English, File::Path,
     File::Copy, Socket, Carp, FileHandle, and Sys::Hostname.

AUTHOR
======

   Glenn Wood, Glenn.Wood@SaveSmart.com

   Copyright 1997-1998 SaveSmart, Inc.

   Released under the Perl Artistic License.

   $Id: loadworm.pm 1.26 1998/07/01 05:17:24 Glenn dev $

constants for Locale codes
**************************

NAME
====

   Locale::Constants - constants for Locale codes

SYNOPSIS
========

     use Locale::Constants;

     $codeset = LOCALE_CODE_ALPHA_2;

DESCRIPTION
===========

   *Locale::Constants* defines symbols which are used in the three modules
from the Locale-Codes distribution:

     Locale::Language
     Locale::Country
     Locale::Currency

   Note: at the moment only Locale::Country supports more than one code
set.

   The symbols defined are used to specify which codes you want to be used:

     LOCALE_CODE_ALPHA_2
     LOCALE_CODE_ALPHA_3
     LOCALE_CODE_NUMERIC

   You shouldn't have to use this module directly yourself - it is used by
the three Locale modules, which in turn export the symbols.

KNOWN BUGS AND LIMITATIONS
==========================

   None at the moment.

SEE ALSO
========

Locale::Language
     Codes for identification of languages.

Locale::Country
     Codes for identification of countries.

Locale::Currency
     Codes for identification of currencies and funds.

AUTHOR
======

   Neil Bowers <neilb@cre.canon.co.uk>

COPYRIGHT
=========

   Copyright (C) 2001, Canon Research Centre Europe (CRE).

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

ISO codes for country identification (ISO 3166)
***********************************************

NAME
====

   Locale::Country - ISO codes for country identification (ISO 3166)

SYNOPSIS
========

     use Locale::Country;

     $country = code2country('jp');               # $country gets 'Japan'
     $code    = country2code('Norway');           # $code gets 'no'

     @codes   = all_country_codes();
     @names   = all_country_names();

     # add "uk" as a pseudo country code for United Kingdom
     Locale::Country::_alias_code('uk' => 'gb');

DESCRIPTION
===========

   The Locale::Country module provides access to the ISO codes for
identifying countries, as defined in ISO 3166.  You can either access the
codes via the `conversion routines' in this node (described below), or
with the two functions which return lists of all country codes or all
country names.

   There are three different code sets you can use for identifying
countries:

alpha-2
     Two letter codes, such as 'tv' for Tuvalu.  This code set is
     identified with the symbol `LOCALE_CODE_ALPHA_2'.

alpha-3
     Three letter codes, such as 'brb' for Barbados.  This code set is
     identified with the symbol `LOCALE_CODE_ALPHA_3'.

numeric
     Numeric codes, such as 064 for Bhutan.  This code set is identified
     with the symbol `LOCALE_CODE_NUMERIC'.

   All of the routines take an optional additional argument which
specifies the code set to use.  If not specified, it defaults to the
two-letter codes.  This is partly for backwards compatibility (previous
versions of this module only supported the alpha-2 codes), and partly
because they are the most widely used codes.

   The alpha-2 and alpha-3 codes are not case-dependent, so you can use
'BO', 'Bo', 'bO' or 'bo' for Bolivia.  When a code is returned by one of
the functions in this module, it will always be lower-case.

CONVERSION ROUTINES
===================

   There are three conversion routines: `code2country()', `country2code()',
and `country_code2code()'.

code2country( CODE, [ CODESET ] )
     This function takes a country code and returns a string which
     contains the name of the country identified.  If the code is not a
     valid country code, as defined by ISO 3166, then undef will be
     returned:

          $country = code2country('fi');

country2code( STRING, [ CODESET ] )
     This function takes a country name and returns the corresponding
     country code, if such exists.  If the argument could not be
     identified as a country name, then undef will be returned:

          $code = country2code('Norway', LOCALE_CODE_ALPHA_3);
          # $code will now be 'nor'

     The case of the country name is not important.  See the section
     `KNOWN BUGS AND LIMITATIONS' in this node below.

country_code2code( CODE, CODESET, CODESET )
     This function takes a country code from one code set, and returns the
     corresponding code from another code set.

          $alpha2 = country_code2code('fin',
          		 LOCALE_CODE_ALPHA_3 => LOCALE_CODE_ALPHA_2);
          # $alpha2 will now be 'fi'

     If the code passed is not a valid country code in the first code set,
     or if there isn't a code for the corresponding country in the second
     code set, then undef will be returned.

QUERY ROUTINES
==============

   There are two function which can be used to obtain a list of all codes,
or all country names:

`all_country_codes( [ CODESET ] )'
     Returns a list of all two-letter country codes.  The codes are
     guaranteed to be all lower-case, and not in any particular order.

`all_country_names( [ CODESET ] )'
     Returns a list of all country names for which there is a corresponding
     country code in the specified code set.  The names are capitalised,
     and not returned in any particular order.

     Not all countries have alpha-3 and numeric codes - some just have an
     alpha-2 code, so you'll get a different number of countries depending
     on which code set you specify.

CODE ALIASING
=============

   This module supports a semi-private routine for specifying two letter
code aliases.

     Locale::Country::_alias_code( ALIAS => CODE [, CODESET ] )

   This feature was added as a mechanism for handling a "uk" code. The ISO
standard says that the two-letter code for "United Kingdom" is "gb",
whereas domain names are all .uk.

   By default the module does not understand "uk", since it is implementing
an ISO standard. If you would like 'uk' to work as the two-letter code for
United Kingdom, use the following:

     use Locale::Country;

     Locale::Country::_alias_code('uk' => 'gb');

   With this code, both "uk" and "gb" are valid codes for United Kingdom,
with the reverse lookup returning "uk" rather than the usual "gb".

EXAMPLES
========

   The following example illustrates use of the `code2country()' function.
The user is prompted for a country code, and then told the corresponding
country name:

     $| = 1;   # turn off buffering

     print "Enter country code: ";
     chop($code = <STDIN>);
     $country = code2country($code, LOCALE_CODE_ALPHA_2);
     if (defined $country)
     {
         print "$code = $country\n";
     }
     else
     {
         print "'$code' is not a valid country code!\n";
     }

DOMAIN NAMES
============

   Most top-level domain names are based on these codes, but there are
certain codes which aren't.  If you are using this module to identify
country from hostname, your best bet is to preprocess the country code.

   For example, *edu*, *com*, *gov* and friends would map to *us*; *uk*
would map to *gb*. Any others?

KNOWN BUGS AND LIMITATIONS
==========================

   * When using `country2code()', the country name must currently appear
     exactly as it does in the source of the module. For example,

          country2code('United States')

     will return *us*, as expected. But the following will all return
     undef:

          country2code('United States of America')
          country2code('Great Britain')
          country2code('U.S.A.')

     If there's need for it, a future version could have variants for
     country names.

   * In the current implementation, all data is read in when the module is
     loaded, and then held in memory.  A lazy implementation would be more
     memory friendly.

SEE ALSO
========

Locale::Language
     ISO two letter codes for identification of language (ISO 639).

Locale::Currency
     ISO three letter codes for identification of currencies and funds
     (ISO 4217).

ISO 3166
     The ISO standard which defines these codes.

http://www.din.de/gremien/nas/nabd/iso3166ma/
     Official home page for ISO 3166

http://www.egt.ie/standards/iso3166/iso3166-1-en.html
     Another useful, but not official, home page.

http://www.cia.gov/cia/publications/factbook/docs/app-f.html
     An appendix in the CIA world fact book which lists country codes as
     defined by ISO 3166, FIPS 10-4, and internet domain names.

AUTHOR
======

   Neil Bowers <neilb@cre.canon.co.uk>

COPYRIGHT
=========

   Copyright (c) 1997-2001 Canon Research Centre Europe (CRE).

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

ISO three letter codes for currency identification (ISO 4217)
*************************************************************

NAME
====

   Locale::Currency - ISO three letter codes for currency identification
(ISO 4217)

SYNOPSIS
========

     use Locale::Currency;

     $curr = code2currency('usd');     # $curr gets 'US Dollar'
     $code = currency2code('Euro');    # $code gets 'eur'

     @codes   = all_currency_codes();
     @names   = all_currency_names();

DESCRIPTION
===========

   The Locale::Currency module provides access to the ISO three-letter
codes for identifying currencies and funds, as defined in ISO 4217.  You
can either access the codes via the `conversion routines' in this node
(described below), or with the two functions which return lists of all
currency codes or all currency names.

   There are two special codes defined by the standard which aren't
understood by this module:

XTS
     Specifically reserved for testing purposes.

XXX
     For transactions where no currency is involved.

CONVERSION ROUTINES
===================

   There are two conversion routines: code2currency() and currency2code().

code2currency()
     This function takes a three letter currency code and returns a string
     which contains the name of the currency identified. If the code is
     not a valid currency code, as defined by ISO 4217, then undef will be
     returned.

          $curr = code2currency($code);

currency2code()
     This function takes a currency name and returns the corresponding
     three letter currency code, if such exists.  If the argument could
     not be identified as a currency name, then undef will be returned.

          $code = currency2code('French Franc');

     The case of the currency name is not important.  See the section
     `KNOWN BUGS AND LIMITATIONS' in this node below.

QUERY ROUTINES
==============

   There are two function which can be used to obtain a list of all
currency codes, or all currency names:

`all_currency_codes()'
     Returns a list of all three-letter currency codes.  The codes are
     guaranteed to be all lower-case, and not in any particular order.

`all_currency_names()'
     Returns a list of all currency names for which there is a
     corresponding three-letter currency code. The names are capitalised,
     and not returned in any particular order.

EXAMPLES
========

   The following example illustrates use of the code2currency() function.
The user is prompted for a currency code, and then told the corresponding
currency name:

     $| = 1;    # turn off buffering

     print "Enter currency code: ";
     chop($code = <STDIN>);
     $curr = code2currency($code);
     if (defined $curr)
     {
         print "$code = $curr\n";
     }
     else
     {
         print "'$code' is not a valid currency code!\n";
     }

KNOWN BUGS AND LIMITATIONS
==========================

   * In the current implementation, all data is read in when the module is
     loaded, and then held in memory.  A lazy implementation would be more
     memory friendly.

   * This module also includes the special codes which are not for a
     currency, such as Gold, Platinum, etc.  This might cause a problem if
     you're using this module to display a list of currencies.  Let Neil
     know if this does cause a problem, and we can do something about it.

   * ISO 4217 also defines a numeric code for each currency.  Currency
     codes are not currently supported by this module.

   * There are three cases where there is more than one code for the same
     currency name.  Kwacha has two codes: mwk for Malawi, and zmk for
     Zambia.  The Russian Ruble has two codes: rub and rur.  The
     Belarussian Ruble has two codes: byr and byb.  The currency2code()
     function only returns one code, so you might not get back the code
     you expected.

SEE ALSO
========

Locale::Country
     ISO codes for identification of country (ISO 3166).  Supports
     alpha-2, alpha-3, and numeric codes.  The currency codes use the
     alpha-2 codeset.

ISO 4217:1995
     Code for the representation of currencies and funds.

http://www.bsi-global.com/iso4217currency
     Official web page for the ISO 4217 maintenance agency.  This has the
     latest list of codes, in MS Word format. Boo.

AUTHOR
======

   Michael Hennecke <hennecke@rz.uni-karlsruhe.de> and Neil Bowers
<neilb@cre.canon.co.uk>

COPYRIGHT
=========

   Copyright (c) 2001 Michael Hennecke and Canon Research Centre Europe
(CRE).

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

ISO two letter codes for language identification (ISO 639)
**********************************************************

NAME
====

   Locale::Language - ISO two letter codes for language identification
(ISO 639)

SYNOPSIS
========

     use Locale::Language;

     $lang = code2language('en');        # $lang gets 'English'
     $code = language2code('French');    # $code gets 'fr'

     @codes   = all_language_codes();
     @names   = all_language_names();

DESCRIPTION
===========

   The Locale::Language module provides access to the ISO two-letter codes
for identifying languages, as defined in ISO 639. You can either access
the codes via the `conversion routines' in this node (described below), or
with the two functions which return lists of all language codes or all
language names.

CONVERSION ROUTINES
===================

   There are two conversion routines: code2language() and language2code().

code2language()
     This function takes a two letter language code and returns a string
     which contains the name of the language identified. If the code is
     not a valid language code, as defined by ISO 639, then undef will be
     returned.

          $lang = code2language($code);

language2code()
     This function takes a language name and returns the corresponding two
     letter language code, if such exists.  If the argument could not be
     identified as a language name, then undef will be returned.

          $code = language2code('French');

     The case of the language name is not important.  See the section
     `KNOWN BUGS AND LIMITATIONS' in this node below.

QUERY ROUTINES
==============

   There are two function which can be used to obtain a list of all
language codes, or all language names:

`all_language_codes()'
     Returns a list of all two-letter language codes.  The codes are
     guaranteed to be all lower-case, and not in any particular order.

`all_language_names()'
     Returns a list of all language names for which there is a
     corresponding two-letter language code. The names are capitalised,
     and not returned in any particular order.

EXAMPLES
========

   The following example illustrates use of the code2language() function.
The user is prompted for a language code, and then told the corresponding
language name:

     $| = 1;    # turn off buffering

     print "Enter language code: ";
     chop($code = <STDIN>);
     $lang = code2language($code);
     if (defined $lang)
     {
         print "$code = $lang\n";
     }
     else
     {
         print "'$code' is not a valid language code!\n";
     }

KNOWN BUGS AND LIMITATIONS
==========================

   * In the current implementation, all data is read in when the module is
     loaded, and then held in memory.  A lazy implementation would be more
     memory friendly.

   * Currently just supports the two letter language codes - there are
     also three-letter codes, and numbers.  Would these be of any use to
     anyone?

SEE ALSO
========

Locale::Country
     ISO codes for identification of country (ISO 3166).  Supports
     2-letter, 3-letter, and numeric country codes.

Locale::Currency
     ISO three letter codes for identification of currencies and funds
     (ISO 4217).

ISO 639:1988 (E/F)
     Code for the representation of names of languages.

http://lcweb.loc.gov/standards/iso639-2/langhome.html
     Home page for ISO 639-2

AUTHOR
======

   Neil Bowers <neilb@cre.canon.co.uk>

COPYRIGHT
=========

   Copyright (c) 1997-2001 Canon Research Centre Europe (CRE).

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

framework for software localization
***********************************

NAME
====

   Locale::Maketext - framework for software localization

SYNOPSIS
========

     [to be written]

DESCRIPTION
===========

   Locale::Maketext is a base class providing a framework for
inheritance-based lexicons for software localization.

   Further documentation is forthcoming.

Methods You May Override
========================

   These are all simple methods you should feel welcome to override as you
like.

the method $LH->encoding
     [to be written]

the method $LH->fallback_languages
     [to be written]

the method $LH->sprintf(FORMAT, PARAMS)
     Just a wrapper for the normal Perl builtin function sprintf - it's
     here so you can use sprintf in bracketish notation.

the method $LH->quant
     [to be written]

the method $LH->numerate
     [to be written]

the method $LH->numf(NUMBER)
     This returns NUMBER formatted appropriately for the conventions of
     $LH's language.  The default behavior for this is just to get
     sprintf("%g", NUMBER), then to tr/,./.,/ it if $LH->{'numf_comma'} is
     true, and then to return it.

the method CLASS->new
     This is used by CLASS->get_handle to actually perform the
     instantiation of each language-handle object into its class.
     Currently it just creates and blesses an empty hashref, and calls
     $LH->init on it.

the method $LH->init
     This is used by CLASS->new to initialize newly instantiated
     language-handle objects.  Currently this is a no-op.

STUFF
-----

the method $LH->maketext(TEXT, PARAMS)
     This looks up the entry for TEXT in the the lexicon for $LH's class
     and its superclasses (via $LH->lookup(TEXT)), and, assuming it's a
     coderef, returns the return value of &$coderef($LH, PARAMS), which is
     presumably a single scalar.

     If $LH->lookup(TEXT) failed (i.e., returned undef), then `maketext'
     fails according to whatever mechanism is set in $LH's "fail" attribute
     - if the 'fail' attribute is set to a coderef, maketext returns the
     output of `&{$fail_coderef}($LH, TEXT, PARAMS)'.  If $LH's "fail"
     attribute is set to a contentful string (i.e., not undef or ""),
     that's considered to be a method name, and maketext returns the output
     of $handle->methodname(TEXT, PARAMS).  Otherwise, maketext returns
     undef.

     (Actually, in all the cases above where maketext passes values to
     other subs, it passes *copies* of TEXT and/or PARAMS, so that the
     actual values passed to maketext can't be altered in-place.  This is
     to parallel the way Perl copies @_ for method calls.)

the constructor CLASS->get_handle(LANGUAGES)
     Constructs a language handle based on the list of locale IDs and/or
     language tags in the list LANGUAGES.

the method $LH->fail_with(FAILSPEC)
     This sets the "fail" attribute of a given language handle.  See the
     docs for $LH->maketext(TEXT, PARAMS).

the method $LH->fail_with
     This returns the value of $LH's "fail" attribute.

the method 'failure_handler_auto'
     [to be written]

the method $LH->lookup(TEXT)
     This looks up the entry TEXT in the lexicons for the handle $LH.  This
     is used by $LH->maketext(TEXT).

     If $LH->lookup(TEXT) looks across the lexicons for $LH (which are
     gotten via $LH->lex_refs), this returns undef.  Otherwise:

     For the first lexicon containing an entry for TEXT, if that entry is a
     coderef (presumably thru being an anonymous sub, but it doesn't
     matter), it's returned.

     If, however, the entry for TEXT is a string, that entry is *replaced*
     with the contents of $LH->compile($that_lexicon{TEXT}), and that value
     is returned.

     Magic happens when lookup looks in a lexicon where you have set
     $Lexicon{'_AUTO'} = 1.  This `_AUTO' flag means that a lookup in that
     lexicon can't really fail - if there is no entry for TEXT,
     $LH->lookup(TEXT) will set $Lexicon{TEXT} = $LH->compile(TEXT), and
     return that value.  This is generally useful only in base classes, as
     a way to mitigate lookup failures.

the method $LH->compile(TEXT) or CLASS->compile(TEXT)
     This takes text in bracketish notation (presumably just retrieved via
     a lexicon returned from $LH->lex_refs), and returns an anonymous sub
     that is that text compiled into Perl.

     Used by $LH->lookup(TEXT).

the method $LH->lex_refs
     This returns a list of hashrefs which are the lexicons for the class
     that this handle belongs to.  This is figured out by looking in the
     package for $LH's class, and the packages of the classes in its @ISA
     tree.  The results of this are memoized for each class.  This assumes
     that no class's @ISA will change after you've started calling maketext
     methods.  I think this is a sane assumption, but in the *very*
     surprising case of you modifying @ISAs dynamically, you can call
     clear_isa_scan to clear all the memoization.

     You should not override this method.

the routine Locale::Maketext::clear_isa_scan
also: the routine $LH->clear_isa_scan
also: the routine CLASS->clear_isa_scan
     This clears all of `lex_ref''s memoization of all @ISA trees.

     You should not override this method.

COPYRIGHT
=========

   Copyright 1999-2000, Sean M. Burke `sburke@cpan.org', all rights
reserved.  This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

AUTHOR
======

   Sean M. Burke, `sburke@cpan.org'

Perl extension for blah blah blah
*********************************

NAME
====

   Locale::Msgcat - Perl extension for blah blah blah

SYNOPSIS
========

     use Locale::Msgcat;

     $cat = new Locale::Msgcat;

     $rc  = $cat->catopen(name, oflag);
     $msg = $cat->catgets(set_number, message_number, string);
     $rc  = $cat->catclose();

DESCRIPTION
===========

   The *Locale::Msgcat* module allows access to the message catalog
functions which are available on some systems. A new Locale::Msgcat object
must first be created for each catalog which has to be open at a given
time.

   The *catopen* operation opens the catalog whose name is given as
argument.  The oflag can be either 0 or NL_CAT_LOCALE (usually 1) which is
the recommended value.

   The *catgets* message retrieves message_number for the set_number
message set, and if not found returns string.

   The *catclose* function should be used when access to a catalog is not
needed anymore.

EXAMPLES
========

     use Locale::Msgcat;

     $cat = new Locale::Msgcat;
     unless ($cat->catopen("whois.cat", 1)) {
         print STDERR "Can't open whois catalog.\n";
         exit(1);
     }
     printf "First message, first set : %s\n", $cat->catgets(1, 1, "not found");
     unless ($cat->catclose()) {
         print STDERR "Can't close whois catalog.\n";
         exit(1);
     }

   The above example would print the first message from the first message
set found in the whois catalog, or if not found it would print "not found".

AUTHOR
======

   Christophe Wolfhugel, wolf@pasteur.fr

SEE ALSO
========

   catopen(3), catclose(3), catgets(3), perl(1).

pure perl i18n routines
***********************

NAME
====

   PGetText - pure perl i18n routines

SYNOPSIS
========

     use Locale::PGetText;

     Locale::PGetText::setLocaleDir('/usr/local/perl/locale');
     Locale::PGetText::setLanguage('ru-koi8r');

     print gettext("Welcome!"), "\n";

DESCRIPTION
===========

   PGetText provides the same functionality as GNU gettext does, but it is
written in pure perl and doesn't require any system locale stuff.

   *setLocaleDir()* sets directory where messages database is stored
(there are no default and no domains).

   *setLanguage()* switches languages.

   *gettext()* retrieves message in local language corresponding to given
message.

SEE ALSO
========

   MsgFormat(1)

AUTHOR
======

   Mike Shoyher <msh@corbina.net>, <msh@apache.lexa.ru>

Perl module for manipulating .po entries from GNU gettext
*********************************************************

NAME
====

   Locale::PO - Perl module for manipulating .po entries from GNU gettext

SYNOPSIS
========

     use Locale::PO;

     $po = new Locale::PO([-option=>value,...])
     [$string =] $po->msgid([new string]);
     [$string =] $po->msgstr([new string]);
     [$string =] $po->comment([new string]);
     [$string =] $po->automatic([new string]);
     [$string =] $po->reference([new string]);
     [$value =] $po->fuzzy([value]);
     [$value =] $po->c_format([value]);
     print $po->dump;

     $quoted_string = $po->quote($string);
     $string = $po->dequote($quoted_string);

     $aref = Locale::PO->load_file_asarray(<filename>);
     $href = Locale::PO->load_file_ashash(<filename>);
     Locale::PO->save_file_fromarray(<filename>,$aref);
     Locale::PO->save_file_fromhash(<filename>,$href);

DESCRIPTION
===========

   This module simplifies management of GNU gettext .po files and is an
alternative to using emacs po-mode. It provides an object-oriented
interface in which each entry in a .po file is a Locale::PO object.

METHODS
=======

new
     Create a new Locale::PO object to represent a po entry.  You can
     optionally set the attributes of the entry by passing a list/hash of
     the form:

          -option=>value, -option=>value, etc.

     Where options are msgid, msgstr, comment, automatic, reference,
     fuzzy, and c-format. See accessor methods below.

msgid
     Set or get the untranslated string from the object.

msgstr
     Set or get the translated string from the object.

comment
     Set or get translator comments from the object.

automatic
     Set or get automatic comments from the object (inserted by emacs
     po-mode or xgettext).

reference
     Set or get reference marking comments from the object (inserted by
     emacs po-mode or gettext).

fuzzy
     Set or get the fuzzy flag on the object ("check this translation").
     When setting, use 1 to turn on fuzzy, and 0 to turn it off.

c_format
     Set or get the c-format or no-c-format flag on the object.  This can
     take 3 values: 1 implies c-format, 0 implies no-c-format, and blank
     or undefined implies neither.

dump
     Returns the entry as a string, suitable for output to a po file.

quote
     Applies po quotation rules to a string, and returns the quoted
     string. The quoted string will have all existing double-quote
     characters escaped by backslashes, and will be enclosed in double
     quotes.

dequote
     Returns a quoted po string to its natural form.

load_file_asarray
     Given the filename of a po-file, reads the file and returns a
     reference to a list of Locale::PO objects corresponding to the
     contents of the file, in the same order.

load_file_ashash
     Given the filename of a po-file, reads the file and returns a
     reference to a hash of Locale::PO objects corresponding to the
     contents of the file. The hash keys are the untranslated strings, so
     this is a cheap way to remove duplicates. The method will prefer to
     keep entries that have been translated.

save_file_fromarray
     Given a filename and a reference to a list of Locale::PO objects,
     saves those objects to the file, creating a po-file.

save_file_fromhash
     Given a filename and a reference to a hash of Locale::PO objects,
     saves those objects to the file, creating a po-file. The entries are
     sorted alphabetically by untranslated string.

AUTHOR
======

   Alan Schwartz, alansz@pennmush.org

BUGS
====

   If you load_file then save_file, the output file may have slight
cosmetic differences from the input file (an extra blank line here or
there).

SEE ALSO
========

   xgettext(1).

convert state, province, county etc. names to/from code
*******************************************************

NAME
====

   Locale::SubCountry - convert state, province, county etc. names to/from
code

SYNOPSIS
========

     use Locale::SubCountry;

     $UK_counties = new Locale::SubCountry('GB');
     print($UK_counties->full_name('DUMGAL'));  # Dumfries & Galloway

     $country = 'AUSTRALIA';
     @all_countries = &all_country_names;
     if ( grep(/$country/, @all_countries) )
     {
        $australia = new Locale::SubCountry($country);
     }
     else
     {
        die "No data for $country";
     }

     print($australia->code('New South Wales ')); # NSW
     print($australia->full_name('S.A.'));        # South Australia

     $upper_case = 1;
     print($australia->full_name('Qld',$upper_case)); # QUEENSLAND
     print $australia->country;          # AUSTRALIA
     print $australia->country_code;     # AU
     print $australia->sub_country_type; # State

     @all_country_codes = &all_country_codes;

     %all_australian_states = $australia->full_name_code_hash;
     foreach $abbrev ( sort keys %australian_states )
     {
        printf("%-3s : %s\n",$abbrev,%all_australian_states{$abbrev});
     }

     %all_australian_codes = $australia->code_full_name_hash;

     @all_australian_states = $australia->all_full_names;
     @all_australian_codes = $australia->all_codes;

REQUIRES
========

   Perl 5.005 or above

DESCRIPTION
===========

   This module allows you to convert the full name for a countries
administrative region to the code commonly used for postal addressing. The
reverse lookup can also be done.

   Sub countries are termed as states in the US and Australia, provinces
in Canada and counties in the UK and Ireland.

   Additionally, names and codes for all sub countries in a country can be
returned as either a hash or an array.

METHODS
=======

new
---

   The new method creates an instance of a sub country object. This must be
called before any of the following methods are invoked. The method takes a
single argument, the name of the country that contains the sub country
that you want to work with. It may be specified either by the ISO 3166 two
letter code or the full name. These are currently:

     AF - AFGHANISTAN
     DZ - ALGERIA
     AO - ANGOLA
     AR - ARGENTINA
     AM - ARMENIA
     AU - AUSTRALIA
     AT - AUSTRIA
     AZ - AZERBAIJAN
     BS - BAHAMAS
     BH - BAHRAIN
     BD - BANGLADESH
     BY - BELARUS
     BE - BELGIUM
     BZ - BELIZE
     BJ - BENIN
     BT - BHUTAN
     BO - BOLIVIA
     BA - BOSNIA AND HERZEGOVINA
     BW - BOTSWANA
     BR - BRAZIL
     BN - BRUNEI DARUSSALAM
     BG - BULGARIA
     BF - BURKINA FASO
     KH - CAMBODIA
     CM - CAMEROON
     CA - CANADA
     CV - CAPE VERDE
     CF - CENTRAL AFRICAN REPUBLIC
     TD - CHAD
     CL - CHILE
     CN - CHINA
     CO - COLOMBIA
     KM - COMOROS
     CO - CONGO
     CR - COSTA RICA
     CI - COTE D'IVOIRE
     HR - CROATIA
     CU - CUBA
     CY - CYPRUS
     CX - CZECH REPUBLIC
     CO - DEMOCRATIC REPUBLIC OF CONGO
     DK - DENMARK
     DJ - DJIBOUTI
     DO - DOMINICAN REPUBLIC
     EC - ECUADOR
     EG - EGYPT
     SV - EL SALVADOR
     QQ - EQUATORIAL GUINEA
     ER - ERITREA
     EE - ESTONIA
     ET - ETHIOPIA
     FJ - FIJI
     FR - FRANCE
     GA - GABON
     GM - GAMBIA
     GE - GEORGIA
     DE - GERMANY
     GH - GHANA
     GR - GREECE
     GT - GUATEMALA
     GN - GUINEA
     GW - GUINEA BISSAU
     GY - GUYANA
     HT - HAITI
     HN - HONDURAS
     HU - HUNGARY
     IE - ICELAND
     IN - INDIA
     ID - INDONESIA
     IN - IRAN (ISLAMIC REPUBLIC OF)
     IQ - IRAQ
     IE - IRELAND
     IT - ITALY
     JM - JAMAICA
     JP - JAPAN
     JO - JORDAN
     KZ - KAZAKHSTAN
     KE - KENYA
     KI - KIRIBATI
     KP - KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF
     KR - KOREA, REPUBLIC OF
     KW - KUWAIT
     KG - KYRGYZSTAN
     LA - LAO PEOPLE'S DEMOCRATIC REPUBLIC
     LV - LATVIA
     LB - LEBANON
     LS - LESOTHO
     LR - LIBERIA
     LY - LIBYAN ARAB JAMAHIRIYA
     LT - LITHUANIA
     MG - MADAGASCAR
     MW - MALAWI
     MY - MALAYSIA
     MV - MALDIVES
     ML - MALI
     MH - MARSHALL ISLANDS
     MR - MAURITANIA
     MU - MAURITIUS
     MX - MEXICO
     FM - MICRONESIA (FEDERATED STATES OF)
     MD - MOLDOVA, REPUPLIC OF
     MN - MONGOLIA
     MA - MOROCCO
     MZ - MOZAMBIQUE
     MM - MYANMAR
     NA - NAMIBIA
     NL - NETHERLANDS
     NZ - NEW ZEALAND
     NI - NICARAGUA
     NE - NIGER
     NG - NIGERIA
     NO - NORWAY
     OM - OMAN
     PK - PAKISTAN
     PA - PANAMA
     PG - PAPUA NEW GUINEA
     PY - PARAGUAY
     PE - PERU
     PH - PHILIPPINES
     PL - POLAND
     PT - PORTUGAL
     QA - QATAR
     RO - ROMANIA
     RU - RUSSIA
     RW - RWANDA
     ST - SAO TOME AND PRINCIPE
     SA - SAUDI ARABIA
     SN - SENEGAL
     SL - SIERRA LEONE
     SK - SLOVAKIA
     SI - SLOVENIA
     SB - SOLOMON ISLANDS
     SO - SOMALIA
     ZA - SOUTH AFRICA
     ES - SPAIN
     LK - SRI LANKA
     SH - ST HELENA
     SD - SUDAN
     SR - SURINAME
     SZ - SWAZILAND
     SE - SWEDEN
     CH - SWITZERLAND
     SY - SYRIAN ARAB REPUBLIC
     TW - TAIWAN, PROVINCE OF CHINA
     TJ - TAJIKISTAN
     TZ - TANZANIA, UNITED REPUBLIC OF
     TH - THAILAND
     TG - TOGO
     TT - TRINIDAD AND TOBAGO
     TN - TUNISIA
     TR - TURKEY
     TM - TURKMENISTAN
     UG - UGANDA
     UA - UKRAINE
     AE - UNITED ARAB EMIRATES
     GB - UNITED KINGDOM
     US - UNITED STATES
     UM - UNITED STATES MINOR OUTLYING ISLANDS
     UY - URUGUAY
     UZ - UZBEKISTAN
     VU - VANUATU
     VE - VENEZUELA
     VN - VIET NAM
     WF - WALLIS AND FUTUNA ISLANDS
     YE - YEMEN
     YU - YUGOSLAVIA
     ZM - ZAMBIA
     ZW - ZIMBABWE

     All forms of upper/lower case are acceptable in the country's spelling. If a
     country name is supplied that the module doesn't recognise, it will die.

country
-------

   Returns the current country of the sub country object

country_code
------------

   Returns the two lwttwr current country of the sub country object

sub_country_type
----------------

   Returns the current sub country type (state, county etc) for the sub
country object, or 'unknown' if a value is not defined. Currently sub
country types are defined for:

   Australia : State Canada    : Province France    : Department Germany
: Lander Ireland   : County UK        : County USA       : State

code
----

   The code method takes the full name of a sub country in the currently
assigned country and returns the sub country's code. The full name can
appear in mixed case. All white space and non alphabetic characters are
ignored, except the single space used to separate sub country names such as
"New South Wales". The code is returned as a capitalised string, or
"unknown" if no match is found.

full_name
---------

   The full_name method takes the code of a sub country in the currently
assigned country and returns the sub country's full name. The code can
appear in mixed case. All white space and non alphabetic characters are
ignored. The full name is returned as a title cased string, such as "South
Australia".

   If an optional argument is supplied and set to a true value, the full
name is returned as an upper cased string.

full_name_code_hash
-------------------

   Returns a hash of name/code pairs for the currently assigned country,
keyed by sub country name.

code_full_name_hash
-------------------

   Returns a hash of code/name pairs for the currently assigned country,
keyed by sub country code.

all_full_names
--------------

   Returns an array of sub country names for the currently assigned
country, sorted alphabetically.

all_codes
---------

   Returns an array of sub country codes for the currently assigned
country, sorted alphabetically.

all_country_names
-----------------

   Returns an array of all country names that this module can do lookups
for, sorted alphabetically. This is implemented as a conventional
subroutine rather than a method. This allows us to check if lookups can be
done for a given country before actually creating the lookup object.

all_country_codes
-----------------

   Returns an array of all country 2 leteer codes that this module can do
lookups for, sorted alphabetically. This is implemented as a conventional
subroutine rather than a method. This allows us to check if lookups can be
done for a given country code before actually creating the lookup object.

SEE ALSO
========

   ISO 3166-2:1998, Standard for naming sub country codes Locale::Country
Locale::US

LIMITATIONS
===========

   If a sub country's full name contains the word 'and', it is represented
by an ampersand, as in 'Dumfries & Galloway'.

   ISO 3166-2:1998 defines all sub country codes as being 2 letters. This
works for USA, Canada etc. In Australia and the UK, this method of
abbreviation is not widely accepted. For example, the ISO code for 'New
South Wales' is 'NS', but 'NSW' is the only abbreviation that is actually
used. I could add an enforce ISO-3166 flag if needed.

   The ISO 3166-2 standard romanizes the names of provinces and regions in
non-latin script areas, such as Russia and South Korea. One Romanisation
is given for each province name. For Russia, the BGN (1947) Romanization
is used.

   The ISO 3166-2 standard for Italy lists alphabetic codes for provinces
and numeric codes for the regions they belong to, both are listed.

   The following sub country names have more than one code, and may not
return the correct code for that sub country.

   AZERBAIJAN : Länkäran; LA,LAN AZERBAIJAN : Säki; SA,SAK AZERBAIJAN :
Susa; SS,SUS AZERBAIJAN : Yevlax; YE,YEV INDONESIA  : Kalimantan Timur;
KI,KT LAOS       : Vientiane VI,VT MOLDOVA    : Hahul; CA,CHL MOLDOVA    :
Bubasari; DU,DBI MOLDOVA    : Hrhei; OR,OHI MOLDOVA    : Coroca; SO,SOA
MOLDOVA    : Gngheni; UN,UGI MOZAMBIQUE : Maputo; MPM,L

BUGS
====

COPYRIGHT
=========

   Copyright (c) 2000-1 Kim Ryan. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the terms of
the Perl Artistic License (see
http://www.perl.com/perl/misc/Artistic.html).

AUTHOR
======

   Locale::SubCountry was written by Kim Ryan <kimaryan@ozemail.com.au> in
2000.

CREDITS
=======

   Alastair McKinstry provided nearly all the sub country codes and names.

   Terrence Brannon produced Locale::US, which was the starting point for
this module. Some of the ideas in Geography::States were also used.

   Mark Summerfield and Guy Fraser provided the list of UK counties.

   Code/Sub country data. Comments (lines starting with #) and blank lines
are ignored. Read in at start up by INIT subroutine.

   Format is: Country=<COUNTRY NAME> Code=<COUNTRY CODE> # from ISO 3166
format SubCountryType=<Sub Country Type>  # optional field, specify state,
county etc CODE:Full Name CODE:Full Name CODE:Full Name ...

   Country=<COUNTRY NAME> ...

message handling functions
**************************

NAME
====

   gettext - message handling functions

SYNOPSIS
========

     use Locale::gettext;
     use POSIX;     # Needed for setlocale()

     setlocale(LC_MESSAGES, "");
     textdomain("my_program");

     print gettext("Welcome to my program"), "\n";
             # (printed in the local language)

DESCRIPTION
===========

   The gettext module permits access from perl to the gettext() family of
functions for retrieving message strings from databases constructed to
internationalize software.

   gettext(), dgettext(), and dcgettext() attempt to retrieve a string
matching their msgid parameter within the context of the current locale.
dcgettext() takes the message's category and the text domain as parameters
while dcgettext() defaults to the LC_MESSAGES category and gettext()
defaults to LC_MESSAGES and uses the current text domain.  If the string
is not found in the database, then msgid is returned.

   textdomain() sets the current text domain and returns the previously
active domain.

   *bindtextdomain(domain, dirname)* instructs the retrieval functions to
look for the databases belonging to domain domain in the directory
`dirname'

VERSION
=======

   1.01.

   1.00 was not under the Locale/ directory.

SEE ALSO
========

   gettext(3i), gettext(1), msgfmt(1)

AUTHOR
======

   Phillip Vandry <vandry@Mlink.NET>

simple file locking scheme
**************************

NAME
====

   LockFile::Simple - simple file locking scheme

SYNOPSIS
========

     use LockFile::Simple qw(lock trylock unlock);

     # Simple locking using default settings
     lock("/some/file") || die "can't lock /some/file\n";
     warn "already locked\n" unless trylock("/some/file");
     unlock("/some/file");

     # Build customized locking manager object
     $lockmgr = LockFile::Simple->make(-format => '%f.lck',
     	-max => 20, -delay => 1, -nfs => 1);

     $lockmgr->lock("/some/file") || die "can't lock /some/file\n";
     $lockmgr->trylock("/some/file");
     $lockmgr->unlock("/some/file");

     $lockmgr->configure(-nfs => 0);

     # Using lock handles
     my $lock = $lockmgr->lock("/some/file");
     $lock->release;

DESCRIPTION
===========

   This simple locking scheme is not based on any file locking system calls
such as flock() or `lockf()' but rather relies on basic file system
primitives and properties, such as the atomicity of the write() system
call. It is not meant to be exempt from all race conditions, especially
over NFS. The algorithm used is described below in the ALGORITHM section.

   It is possible to customize the locking operations to attempt locking
once every 5 seconds for 30 times, or delete stale locks (files that are
deemed too ancient) before attempting the locking.

ALGORITHM
=========

   The locking alogrithm attempts to create a *lockfile* using a
temporarily redefined umask (leaving only read rights to prevent further
create operations). It then writes the process ID (PID) of the process and
closes the file. That file is then re-opened and read. If we are able to
read the same PID we wrote, and only that, we assume the locking is
successful.

   When locking over NFS, i.e. when the one of the potentially locking
processes could access the *lockfile* via NFS, then writing the PID is not
enough.  We also write the hostname where locking is attempted to ensure
the data are unique.

CUSTOMIZING
===========

   Customization is only possible by using the object-oriented interface,
since the configuration parameters are stored within the object. The
object creation routine make can be given configuration parmeters in the
form a "hash table list", i.e. a list of key/value pairs. Those parameters
can later be changed via configure by specifying a similar list of
key/value pairs.

   To benefit from the bareword quoting Perl offers, all the parameters
must be prefixed with the - (minus) sign, as in `-format' for the format
parameter..  However, when querying the object, the minus must be omitted,
as in `$obj->format'.

   Here are the available configuration parmeters along with their meaning,
listed in alphabetical order:

autoclean
     When true, all locks are remembered and pending ones are automatically
     released when the process exits normally (i.e. whenever Perl calls the
     END routines).

delay
     The amount of seconds to wait between locking attempts when the file
     appears to be already locked. Default is 2 seconds.

efunc
     A function pointer to dereference when an error is to be reported. By
     default, it redirects to the logerr() routine if you have Log::Agent
     installed, to Perl's warn() function otherwise.

     You may set it explicitely to `\&LockFile::Simple::core_warn' to
     force the use of Perl's warn() function, or to undef to suppress
     logging.

ext
     The locking extension that must be added to the file path to be
     locked to compute the *lockfile* path. Default is `.lock' (note that
     . is part of the extension and can therefore be changed). Ignored
     when format is also used.

format
     Using this parmeter supersedes the ext parmeter. The formatting string
     specified is run through a rudimentary macro expansion to derive the
     *lockfile* path from the file to be locked. The following macros are
     available:

          %%	A real % sign
          %f	The full file path name
          %D	The directory where the file resides
          %F	The base name of the file
          %p	The process ID (PID)

     The default is to use the locking extension, which itself is `.lock',
     so it is as if the format used was `%f.lock', but one could imagine
     things like `/var/run/%F.%p', i.e. the *lockfile* does not
     necessarily lie besides the locked file (which could even be missing).

     When locking, the locking format can be specified to supersede the
     object configuration itself.

hold
     Maximum amount of seconds we may hold a lock. Past that amount of
     time, an existing *lockfile* is removed, being taken for a stale
     lock. Default is 3600 seconds. Specifying 0 prevents any forced
     unlocking.

max
     Amount of times we retry locking when the file is busy, sleeping delay
     seconds between attempts. Defaults to 30.

nfs
     A boolean flag, false by default. Setting it to true means we could
     lock over NFS and therefore the hostname must be included along with
     the process ID in the stamp written to the lockfile.

stale
     A boolean flag, false by default. When set to true, we attempt to
     detect stale locks and break them if necessary.

wafter
     Stands for *warn after*. It is the number of seconds past the first
     warning during locking time after which a new warning should be
     emitted.  See warn and wmin below. Default is 20.

warn
     A boolean flag, true by default. To suppress any warning, set it to
     false.

wfunc
     A function pointer to dereference when a warning is to be issued. By
     default, it redirects to the logwarn() routine if you have Log::Agent
     installed, to Perl's warn() function otherwise.

     You may set it explicitely to `\&LockFile::Simple::core_warn' to
     force the use of Perl's warn() function, or to undef to suppress
     logging.

wmin
     The minimal amount of time when waiting for a lock after which a first
     warning must be emitted, if warn is true. After that, a warning will
     be emitted every wafter seconds. Defaults to 15.

   Each of those configuration attributes can be queried on the object
directly:

     $obj = LockFile::Simple->make(-nfs => 1);
     $on_nfs = $obj->nfs;

   Those are pure query routines, i.e. you cannot say:

     $obj->nfs(0);                  # WRONG
     $obj->configure(-nfs => 0);    # Right

   to turn of the NFS attribute. That is because my OO background chokes
at having querying functions with side effects.

INTERFACE
=========

   The OO interface documented below specifies the signature and the
semantics of the operations. Only the lock, `trylock' and unlock operation
can be imported and used via a non-OO interface, with the exact same
signature nonetheless.

   The interface contains all the attribute querying routines, one for
each configuration parmeter documented in the CUSTOMIZING section above,
plus, in alphabetical order:

configure(*-key => value, -key2 => value2, ...*)
     Change the specified configuration parameters and silently ignore the
     invalid ones.

lock(file, format)
     Attempt to lock the file, using the optional locking format if
     specified, otherwise using the default format scheme configured in
     the object, or by simply appending the ext extension to the file.

     If the file is already locked, sleep delay seconds before retrying,
     repeating try/sleep at most max times. If warning is configured, a
     first warning is emitted after waiting for wmin seconds, and then
     once every wafter seconds, via  the wfunc routine.

     Before the first attempt, and if hold is non-zero, any existing
     *lockfile* is checked for being too old, and it is removed if found
     to be stale. A warning is emitted via the wfunc routine in that case,
     if allowed.

     Likewise, if stale is non-zero, a check is made to see whether any
     locking process is still around (only if the lock holder is on the
     same machine when NFS locking is configured). Should the locking
     process be dead, the *lockfile* is declared stale and removed.

     Returns a lock handle if the file has been successfully locked, which
     does not necessarily needs to be kept around. For instance:

          $obj->lock('ppp', '/var/run/ppp.%p');
          <do some work>
          $obj->unlock('ppp');

     or, using OO programming:

          my $lock = $obj->lock('ppp', '/var/run/ppp.%p') ||;
              die "Can't lock for ppp\n";
          <do some work>
          $lock->relase;   # The only method defined for a lock handle

     i.e. you don't even have to know which file was locked to release it,
     since there is a lock handle right there that knows enough about the
     lock parameters.

lockfile(file, format)
     Simply compute the path of the *lockfile* that would be used by the
     lock procedure if it were passed the same parameters.

make(*-key => value, -key2 => value2, ...*)
     The creation routine for the simple lock object. Returns a blessed
     hash reference.

trylock(file, format)
     Same as lock except that it immediately returns false and does not
     sleep if the to-be-locked file is busy, i.e. already locked. Any
     stale locking file is removed, as lock would do anyway.

     Returns a lock hande if the file has been successfully locked.

unlock(file)
     Unlock the file.

BUGS
====

   The algorithm is not bullet proof.  It's only reasonably safe.  Don't
bet the integrity of a mission-critical database on it though.

   The sysopen() call should probably be used with the `O_EXCL|O_CREAT'
flags to be on the safer side. Still, over NFS, this is not an atomic
operation anyway.

   *BEWARE*: there is a race condition between the time we decide a lock is
stale or too old and the time we unlink it. Don't use `-stale' and set
`-hold' to 0 if you can't bear with that idea, but recall that this race
only happens when something is already wrong. That does not make it right,
nonetheless. ;-)

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   File::Flock(3).

logging agent
*************

NAME
====

   Log::Agent - logging agent

SYNOPSIS
========

     use Log::Agent;            # in all reusable components
     logerr "error";
     logtrc "notice:12", "notice that" if ...;
     logdie "log and die";

     use Log::Agent;            # in application's main
     logconfig(-prefix => $0);  # simplest, uses default driver

     use Log::Agent;                    # another more complex example
     require Log::Agent::Driver::File;  # logging made to file
     logconfig(-driver =>
         Log::Agent::Driver::File->make(
             -prefix      => $0,
             -showpid     => 1,
             -channels    => {
                 'error'  => "$0.err",
                 'output' => "$0.out",
                 'debug'  => "$0.dbg",
             },
         )
     );

DESCRIPTION
===========

   The `Log::Agent' module provides an abstract layer for logging and
tracing, which is independant from the actual method used to physically
perform those activities. It acts as an agent (hence the name) that
collects the requests and delegates processing to a sublayer: the logging
driver.

   The `Log::Agent' module is meant to be used in all reusable components,
since they cannot know in advance how the application which ends up using
them will perform its logging activities: either by emitting messages on
stdout and errors on stderr, or by directing messages to logfiles, or by
using syslog(3).

   The logging interface is common for all the logging drivers, and is
therefore the result of a compromise between many logging schemes: any
information given at this level must be either handled by all drivers, or
may be ignored depending on the application's final choice.

   WARNING: THIS INTERFACE IS STILL SOMEWHAT ALPHA AND COULD STILL CHANGE
DEPENDING ON THE FEEDBACK I SHALL GET FROM USERS AND FROM MY OWN
EXPERIENCE USING IT, WITHOUT ANY BACKWARD COMPATIBILITY ASSURANCE.

PRIORITIES AND LEVEL
====================

   The `Log::Agent' module can use both priorities (as defined by
syslog(3)) or logging levels, or either, in which case there is an
implicit computation of the missing item (i.e. the level 4, for instance,
corresponds to the "warning" priority, and vice-versa).  See
Log/Agent/Priorities, for more details.

   A logging level is defined as being a threshold: any level lesser than
or equal to that threshold will be logged.

   At the `Log::Agent' level, it is possible to define a trace level and a
debug level. Only the messages below those levels (inclusive) will be
handed out to the underlying driver for logging. They are used by the
logtrc() and logdbg() routines, respectively.

CHANNELS
========

   The `Log::Agent' class defines three logging channels, which are error,
output and debug. Depending on the driver used for logging, those channels
are ignored (typically with syslog()) or may be implicitely defined
(default logging, i.e. the one achieved by the Log::Agent::Driver::Default
driver, remaps error and debug to stderr, output to stdout).

INTERFACE
=========

   Anywhere a message is expected, it can be a single string, or a
printf()-like format string followed by the required arguments. The
special macro `%m' is handled directly by `Log::Agent' and is replaced by
the string version of $!, which is the last error message returned by the
last failing system call.

   NOTE: There should not be any trailing "\n" in the message strings, nor
any embededed one, although this is not enforced. Remember that the main
purpose of `Log::Agent' is to specify logging messages in a standard way!
Therefore, most of the time, a "should" should be read as "must" and
"should not" as "must not", which is the strongest interdiction form
available in English, as far as I know.

   Here are valid message examples:

     "started since $time"
     "started since %s", $time
     "fork: %m"

   The follwing logging interface is made available to modules:

logdbg priority, message
     Debug logging of message to the debug channel.

     You may specify any priority you want, i.e.  a debug priority is not
     enforced here. You may even specify `"notice:4"' if you wish, to have
     the message logged if the debug level is set to 4 or less.  If handed
     over to syslog(3), the message will nonetheless be logged at the
     notice priority.

logtrc priority, message
     Trace logging of message to the output channel.

     Like logdbg() above, you are not restricted to the info priority. This
     routine checks the logging level (either explicit as in `"info:14"'
     or implicit as in `"notice"') against the trace level.

logsay message
     Log the message at the notice priority to the output channel.  The
     logging always takes place under the default `-trace' settings, but
     only if the routine is called, naturally.  This means you can still
     say:

          logsay "some trace message" if $verbose;

     and control whether the message is emitted by using some external
     configuration for your module (e.g. by adding a -verbose flag to the
     creation routine of your class).

logwarn message
     Log a warning message at the warning priority to the error channel.

logcarp message
     Same as logwarn(), but issues a Carp::carp(3) call instead, which will
     warn from the perspective of the routine's caller.

logerr message
     Log an error message at the error priority to the error channel.

logdie message
     Log a fatal message at the critical priority to the error channel,
     and then dies.

logconfess message
     Same as logdie(), but issues a Carp::confess(3) call instead.  It is
     possible to configure the `Log::Agent' module via the `-confess'
     switch to automatically redirect a logdie() to logconfess(), which is
     invaluable during unit testing.

logcroak message
     Same as logdie(), but issues a Carp::croak(3) call instead.  It is
     possible to configure the `Log::Agent' module via the `-confess'
     switch to automatically redirect a logcroak() to logconfess(), which
     is invaluable during unit testing.

Log::Agent::inited
     Returns true when `Log::Agent' was initialized, either explicitely via
     a logconfig() or implicitely via any logxxx() call.

   Modules sometimes wish to report errors from the perspective of their
caller's caller, not really their caller.  The following interface is
therefore provided:

logxcarp offset, message
     Same a logcarp(), but with an additional offset to be applied on the
     stack.  To warn one level above your caller, set it to 1.

logxcroak offset, message
     Same a logcroak(), but with an additional offset to be applied on the
     stack.  To report an error one level above your caller, set it to 1.

   For applications that wish to implement a debug layer on top of
`Log::Agent', the following routine is provided.  Note that it is not
imported by default, i.e. it needs to be explicitely mentionned at use
time, since it is not meant to be used directly under regular usage.

logwrite channel, priority, message
     Unconditionally write the message at the given priority on channel.
     The channel can be one of debug, error or output.

   At the application level, one needs to commit once and for all about the
logging scheme to be used. This is done thanks to the logconfig() routine
which takes the following switches, in alphabetical order:

`-caller' => [ parameters ]
     Request that caller information (relative to the logxxx() call) be
     part of the log message. The given parameters are handed off to the
     creation routine of Log::Agent::Caller(3) and are documented there.

     I usually say something like:

          -caller => [ -display => '($sub/$line)' ]

     which I find informative enough. On occasion, I found myself using
     more complex sequences.

`-confess' => flag
     When true, all logdie() calls will be automatically masqueraded as
     logconfess().

`-debug' => *priority or level*
     Sets the priority threshold (can be expressed as a string or a
     number, the string being mapped to a logging level as described above
     in PRIORITIES AND LEVEL) for logdbg() calls.

     Calls tagged with a level less than or equal to the given threshold
     will pass through, others will return prematurely without logging
     anything.

`-driver' => *driver_object*
     This switch defines the driver object to be used, which must be an
     heir of the `Log::Agent::Driver' class. See `Log::Agent::Driver(3)'
     in this node for a list of the available drivers.

`-level' => *priority or level*
     Specifies both `-debug' and `-trace' levels at the same time, to a
     common value.

`-prefix' => name
     Defines the application name which will be pre-pended to all messages,
     followed by `": "' (a colon and a space). Using this switch alone will
     configure the default driver to use that prefix (stripped down to its
     basename component).

     When a driver object is used, the `-prefix' switch is kept at the
     `Log::Agent' level only and is not passed to the driver: it is up to
     the driver's creation routine to request the `-prefix'. Having this
     information in Log::Agent enables the module to die on critical errors
     with that error prefix, since it cannot rely on the logging driver for
     that, obviously.

`-trace' => *priority or level*
     Same a `-debug' but applies to logsay(), logwarn(), logerr() and
     logtrc().

     When unspecified, `Log::Agent' runs at the "notice" level.

KNOWN LIMITATIONS
=================

   The following limitations exist in this early version. They might be
addressed in future versions if they are perceived as annoying limitatons
instead of being just documented ones. :-)

   * A module which calls logdie() may have its die trapped if called from
     within an eval(), but unfortunately, the value of $@ is unpredictable:
     it may be prefixed or not depending on the driver used. This is
     harder to fix as one might think of at first glance.

   * Some drivers lack customization and hardwire a few things that come
     from my personal taste, like the prefixing done when *duperr* is set
     in Log::Agent::Driver::File, or the fact that the debug and stderr
     channels are merged as one in the Log::Agent::Driver::Default driver.

   * When using logcroak() or logconfess(), the place where the call was
     made can still be visible when -caller is used, since the addition of
     the caller information to the message is done before calling the
     logging driver.  Is this a problem?

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   Log::Agent::Driver(3), Carp(3).

formats caller information
**************************

NAME
====

   Log::Agent::Caller - formats caller information

SYNOPSIS
========

     Not intended to be used directly

DESCRIPTION
===========

   This class handles caller information for Log::Agent services and is not
meant to be used directly.

   This manpage therefore only documents the creation routine parameters
that can be specified at the Log::Agent level via the `-caller' switch in
the logconfig() routine.

CALLER INFORMATION ENTITIES
===========================

   This class knows about four entities: package, filename, line and
subroutine, which are to be understood within the context of the
Log::Agent routine being called (e.g. a logwarn() routine), namely:

package
     This is the package name where the call to the logwarn() routine was
     made.  It can be specified as "pack" for short, or spelled out
     completely.

filename
     This is the file where the call to the logwarn() routine was made.
     It can be specified as "file" for short, or spelled out completely.

line
     This is the line number where the call to the logwarn() routine was
     made, in file filename. The name is short enough to be spelled out
     completely.

subroutine
     This is the subroutine where the call to the logwarn() routine was
     made.  If the call is made outside a subroutine, this will be empty.
     The name is long enough to warrant the "sub" abbreviation if you
     don't wish to spell it out fully.

CREATION ROUTINE PARAMETERS
===========================

   The purpose of those parameters is to define how caller information
entities (as defined by the previous section) will be formatted within the
log message.

`-display' => string
     Specifies a string with minimal variable substitution: only the caller
     information entities specified above, or their abbreviation, will be
     interpolated. For instance:

          -display => '($package::$sub/$line)'

     Don't forget to use simple quotes to avoid having Perl interpolate
     those as variables, or escape their leading `$' sign otherwise. Using
     this convention was deemed to more readable (and natural in Perl)
     than SGML entities such as "&pack;".

     Using this switch supersedes the `-info' and `-format' switches.

`-format' => *printf format*
     Formatting instructions for the caller information entities listed by
     the `-info' switch. For instance:

          -format => "%s:%4d"

     if you have specified two entities in `-info'.

     The special formatting macro `%a' stands for all the entities
     specified by `-info' and is rendered by a string where values are
     separated by ":".

`-info' => *"space separated list of parameters"*
     Specifies a list of caller information entities that are to be
     formated using the `-format' specification. For instance:

          -info => "pack sub line"

     would only report those three entites.

`-postfix' => flag
     Whether the string resulting from the formatting of the caller
     information entities should be appended to the regular log message or
     not (i.e. prepended, which is the default).

     Separation from the remaining of the log message is a single space.

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   Log::Agent(3), Log::Agent::Message(3).

ancestor class for all Log::Agent channels
******************************************

NAME
====

   Log::Agent::Channel - ancestor class for all Log::Agent channels

SYNOPSIS
========

     @Log::Agent::Channel::XXX::ISA = qw(Log::Agent::Channel);

DESCRIPTION
===========

   The `Log::Agent::Channel' class is the root class from which all
`Log::Agent' channels inherit. It is a *deferred* class, meaning that it
cannot be instantiated directly. All the deferred routines need to be
implemented by its heirs to form a valid driver.

   Internally, the various `Log::Agent::Driver' objects create
`Log::Agent::Channel' instances for each logging channel defined at driver
creation time.  The channels are therefore architecturally hidden within
`Log::Agent', since this module only provides redefined mappings for the
various logxxx() routines (logerr(), logwarn(), logdie(), etc...).

   However, this does not mean that channel classes cannot be used
externally: the `Log::Agent::Logger' extension makes `Log::Agent::Channel'
objects architecturally visible, thereby offering an application-level
logging API that can be redirected to various places transparently for the
application.

CHANNEL LIST
============

   The following channels are currently made available by `Log::Agent'.
More channels can be defined by the `Log::Agent::Logger' extension:

Log::Agent::Channel::File
     This channel writes logs to files, defined by their path or via a
     magical opening sequence such as "|cmd".

Log::Agent::Channel::Handle
     This channel writes logs to an already opened descriptor, as
     specified by its file handle: an IO::Handle object, or a GLOB
     reference such as \*FILE.

Log::Agent::Channel::Syslog
     This channel redirects logs to the syslogd(8) daemon, which will then
     handle the dispatching to various logfiles, based on its own
     configuration.

INTERFACE
=========

   You need not read this section if you're only using `Log::Agent'.
However, if you wish to implement another channel, then this section might
be of interest.

   The following routines are *deferred* and therefore need to be defined
by the heir:

write($priority, $logstring)
     Emit the log entry held in $logstring, at priority $priority.  A
     trailing "\n" is added to the $logstring, if needed (i.e. if the
     physical entity does not do it already, like syslog does).

     The $priority argument must be a valid syslog priority, i.e. one of
     the following strings: "emerg", "alert", "crit", "err", "warning",
     "notice", "info", "debug".

     The $logstring may not really be a plain string. It can actually be a
     Log::Agent::Message object with an overloaded stringification
     routine, so the illusion should be complete.

close
     Close the channel.

make
     This is the creation routine. Its signature varies for each channel,
     naturally.

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   Log::Agent::Channel::File(3), Log::Agent::Channel::Handle(3),
Log::Agent::Channel::Syslog(3), Log::Agent::Logger(3).

file logging channel for Log::Agent
***********************************

NAME
====

   Log::Agent::Channel::File - file logging channel for Log::Agent

SYNOPSIS
========

     require Log::Agent::Channel::File;

     my $driver = Log::Agent::Channel::File->make(
         -prefix     => "prefix",
         -stampfmt   => "own",
         -showpid    => 1,
         -magic_open => 0,
         -filename   => "/tmp/output.err",
         -share      => 1,
     );

DESCRIPTION
===========

   The file channel performs logging to a file, along with the necessary
prefixing and stamping of the messages.

   Internally, the Log::Agent::Driver::File driver creates such objects
for each logging channel defined at driver creation time.

   The creation routine make() takes the following arguments:

`-filename' => file
     The file name where output should go.  The file is opened in append
     mode and autoflushing is turned on.  See also the `-magic_open' flag.

`-magic_open' => flag
     When true, channel filenames beginning with '>' or '|' are opened
     using Perl's open(). Otherwise, sysopen() is used, in append mode.

     Default is false.

`-no_newline' => flag
     When set to *true*, never append any "\n" (on Unix) or "\r\n" (on
     Windows) to log messages.

     Internally, Log::Agent relies on the channel to delimit logged lines
     appropriately, so this flag is not used.  However, it might be useful
     for `Log::Agent::Logger' users.

     Default is false, meaning newline markers are systematically appended.

`-no_prefixing' => flag
     When set to *true*, disable the prefixing logic entirely, i.e. the
     following options are ignored completely: `-prefix', `-showpid',
     `-no_ucfirst', `-stampfmt'.

     Default is false.

`-no_ucfirst' => flag
     When set to *true*, don't upper-case the first letter of the log
     message entry when there's no prefix inserted before the logged line.
     When there is a prefix, a ":" character follows, and therefore the
     leading letter of the message should not be upper-cased anyway.

     Default is false, meaning uppercasing is performed.

`-prefix' => prefix
     The application prefix string to prepend to messages.

`-rotate' => object
     This sets a default logfile rotation policy.  You need to install the
     additional `Log::Agent::Rotate' module to use this switch.

     object is the `Log::Agent::Rotate' instance describing the rotating
     policy for the channel.  Only files which are not opened via a
     so-called *magic open* can be rotated.

`-share' => flag
     When *true*, this flag records the channel in a global pool indexed by
     filenames.  An existing file handle for the same filename may be then
     be shared amongst several file channels.

     However, you will get this message in the file

          Rotation for 'filename' may be wrong (shared with distinct policies)

     when a rotation policy different from the one used during the initial
     opening is given.  Which policy will be used is unspecified, on
     purpose.

`-showpid' => flag
     If set to true, the PID of the process will be appended within square
     brackets after the prefix, to all messages.

     Default is false.

`-stampfmt' => (name | CODE)
     Specifies the time stamp format to use. By default, my "own" format
     is used.  See Log/Agent/Stamping, for a
     description of the available format names.

     You may also specify a CODE ref: that routine will be called every
     time we need to compute a time stamp. It should not expect any
     parameter, and should return a string.

CAVEAT
======

   Beware of chdir().  If your program uses chdir(), you should always
specify logfiles by using absolute paths, otherwise you run the risk of
having your relative paths become invalid: there is no anchoring done at
the time you specify them.  This is especially true when configured for
rotation, since the logfiles are recreated as needed and you might end up
with many logfiles scattered throughout all the directories you chdir()ed
to.

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   Log::Agent::Logger(3), Log::Agent::Channel(3).

I/O handle logging channel for Log::Agent
*****************************************

NAME
====

   Log::Agent::Channel::Handle - I/O handle logging channel for Log::Agent

SYNOPSIS
========

     require Log::Agent::Channel::Handle;

     my $driver = Log::Agent::Channel::Handle->make(
         -prefix     => "prefix",
         -stampfmt   => "own",
         -showpid    => 1,
         -handle     => \*FILE,
     );

DESCRIPTION
===========

   The handle channel performs logging to an already opened I/O handle,
along with the necessary prefixing and stamping of the messages.

   The creation routine make() takes the following arguments:

`-handle' => handle
     Specifies the I/O handle to use.  It can be given as a GLOB reference,
     such as `\*FILE', or as an IO::Handle object.

     NOTE: Auto-flushing is not enabled on the handle.  Even when the
     channel is closed, the handle is left as-is: we simply stop sending
     log messages to it.

`-no_newline' => flag
     When set to *true*, never append any "\n" (on Unix) or "\r\n" (on
     Windows) to log messages.

     Internally, Log::Agent relies on the channel to delimit logged lines
     appropriately, so this flag is not used.  However, it might be useful
     for `Log::Agent::Logger' users.

     Default is false, meaning newline markers are systematically appended.

`-no_prefixing' => flag
     When set to *true*, disable the prefixing logic entirely, i.e. the
     following options are ignored completely: `-prefix', `-showpid',
     `-no_ucfirst', `-stampfmt'.

     Default is false.

`-no_ucfirst' => flag
     When set to *true*, don't upper-case the first letter of the log
     message entry when there's no prefix inserted before the logged line.
     When there is a prefix, a ":" character follows, and therefore the
     leading letter of the message should not be upper-cased anyway.

     Default is false, meaning uppercasing is performed.

`-prefix' => prefix
     The application prefix string to prepend to messages.

`-showpid' => flag
     If set to true, the PID of the process will be appended within square
     brackets after the prefix, to all messages.

     Default is false.

`-stampfmt' => (name | CODE)
     Specifies the time stamp format to use. By default, my "own" format
     is used.  See Log/Agent/Stamping, for a
     description of the available format names.

     You may also specify a CODE ref: that routine will be called every
     time we need to compute a time stamp. It should not expect any
     parameter, and should return a string.

CAVEAT
======

   Beware of chdir().  If your program uses chdir(), you should always
specify logfiles by using absolute paths, otherwise you run the risk of
having your relative paths become invalid: there is no anchoring done at
the time you specify them.  This is especially true when configured for
rotation, since the logfiles are recreated as needed and you might end up
with many logfiles scattered throughout all the directories you chdir()ed
to.

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   Log::Agent::Logger(3), Log::Agent::Channel(3).

syslog logging channel for Log::Agent::Logger
*********************************************

NAME
====

   Log::Agent::Channel::Syslog - syslog logging channel for
Log::Agent::Logger

SYNOPSIS
========

     require Log::Agent::Channel::Syslog;

     my $channel = Log::Agent::Channel::Syslog->make(
         # Specific attributes
         -prefix     => prefix,
         -facility   => "user",
         -showpid    => 1,
         -socktype   => "unix",
         -logopt     => "ndelay",
     );

DESCRIPTION
===========

   The syslog logging channels directs operations to syslog() via the
Sys::Syslog(3) interface.

   The creation routine make() takes the following switches:

`-facility' => facility
     Tell syslog() which facility to use (e.g. "user", "auth", "daemon").
     Unlike the Sys::Syslog(3) interface, the facility is set once and for
     all: every message logged through this channel will use the same
     facility.

`-logopt' => *syslog options*
     Specifies logging options, under the form of a string containing zero
     or more of the words *ndelay*, *cons* or nowait.

`-prefix' => prefix
     The prefix here is syslog's identification string.

`-showpid' => flag
     Set to true to have the PID of the process logged. It is false by
     default.

`-socktype' => (*unix* | *inet*)
     Specifies the logging socket type to use. The default behaviour is to
     use Sys:Syslog's default.

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   Log::Agent::Logger(3).

ancestor class for all Log::Agent drivers
*****************************************

NAME
====

   Log::Agent::Driver - ancestor class for all Log::Agent drivers

SYNOPSIS
========

     @Log::Agent::Driver::XXX::ISA = qw(Log::Agent::Driver);

DESCRIPTION
===========

   The Log::Agent::Driver class is the root class from which all Log::Agent
drivers inherit. It is a *deferred* class, meaning that it cannot be
instantiated directly. All the deferred routines need to be implemented by
its heirs to form a valid driver.

   A *deferred* routine is a routine whose signature and semantics (pre and
post conditions, formally) are specified, but not implemented. It allows
specification of high-level processings in terms of them, thereby
factorizing common code in the ancestors without loosing specialization
benefits.

DRIVER LIST
===========

   The following drivers are currently fully implemented:

Log::Agent::Driver::Default
     This is the default driver which remaps to simple print(), warn() and
     die() Perl calls.

Log::Agent::Driver::File
     This driver redirects logs to files. Each logging channel may go to a
     dedicated file.

Log::Agent::Driver::Silent
     Silence all the logxxx() routines.

Log::Agent::Driver::Syslog
     This driver redirects logs to the syslogd(8) daemon, which will then
     handle the dispatching to various logfiles, based on its own
     configuration.

INTERFACE
=========

   You need not read this section if you're only using Log::Agent.
However, if you wish to implement another driver, then you should probably
read it a few times.

   The following routines are *deferred* and therefore need to be defined
by the heir:

channel_eq($chan1, $chan2)
     Returns true when both channels $chan1 and $chan2 send their output to
     the same place.  The purpose is not to have a 100% accurate
     comparison, which is almost impossible for the
     Log::Agent::Driver::File driver, but to reasonably detect
     similarities to avoid duplicating messages to the same output when
     Devel::Datum is installed and activated.

write($channel, $priority, $logstring)
     Emit the log entry held in $logstring, at priority $priority and
     through the specfied $channel name. A trailing "\n" is to be added if
     needed, but the $logstring should not already have one.

     The $channel name is just a string, and it is up to the driver to map
     that name to an output device using its own configuration
     information. The generic logxxx() routines use only error, output or
     debug for channel names.

     The $priority entry is assumed to have passed through the map_pri()
     routine, which by default returns an empty string (only the
     Log::Agent::Driver::Syslog driver needs a priority, for now). Ignore
     if you don't need that, or redefine map_pri().

     The $logstring may not really be a plain string. It can actually be a
     Log::Agent::Message object with an overloaded stringification
     routine, so the illusion should be complete.

make
     This is the creation routine. Its signature varies for each driver,
     naturally.

prefix_msg($str)
     Prefix the log message string (a Log::Agent::Message object) with
     driver-specific information (like the configured prefix, the PID of
     the process, etc...).

     Must return the prefixed string, either as a Log::Agent::Message
     object or as a plain string. This means you may use normal string
     operations on the $str variable and let the overloaded
     stringification perform its magic. Or you may return the $str
     parameter without modification.

     There is no default implementation here because this is too
     driver-specific to choose one good default. And I like making things
     explicit sometimes.

   The following routines are implemented in terms of write(), map_pri()
and prefix_msg(). The default implementation may need to be redefined for
performance or tuning reasons, but simply defining the deferred routines
above should bring a reasonable behaviour.

   As an example, here is the default logsay() implementation, which uses
the emit() wrapper (see below):

     sub logsay {
         my $self = shift;
     		my ($str) = @_;
         $self->emit('output', 'notice', $str);
     }

   Yes, we do show the gory details in a manpage, but inheriting from a
class is not for the faint of heart, and requires getting acquainted with
the implementation, most of the time.

   The order is not alphabetical here but by increased level of severity
(as expected, anyway):

logwrite($channel, $priority, $level, $str)
     Log message to the given channel, at the specified priority/level,
     obtained through a call to map_pri().

logsay($str)
     Log message to the output channel, at the notice priority.

logwarn($str)
     Log warning to the error channel at the warning priority.

logxcarp($offset, $str)
     Log warning to the error channel at the warning priority, from the
     perspective of the caller.  An additional $offset stack frames are
     skipped to find the caller (added to the hardwired fixed offset
     imposed by the overall Log::Agent architecture).

logerr($str)
     Log error to the error channel at the error priority.

logdie($str)
     Log fatal error to the error channel at the critical priority and
     then call die() with "$str\n" as argument.

logxcroak($offset, $str)
     Log a fatal error, from the perspective of the caller. The error is
     logged to the error channel at the critical priority and then
     Carp::croak() is called with "$str\n" as argument.  An additional
     $offset stack frames are skipped to find the caller (added to the
     hardwired fixed offset imposed by the overall Log::Agent
     architecture).

logconfess($str)
     Confess a fatal error. The error is logged to the error channel at
     the critical priority and then Carp::confess() is called with "$str\n"
     as argument.

   The following routines have a default implementation but may be
redefined for specific drivers:

emit($channel, $prio, $str)
     This is a convenient wrapper that calls:

          write($channel, $self->priority($prio), $self->prefix_msg($str))

     using dynamic binding.

map_pri($priority, $level)
     Converts a ("priority", level) tupple to a single priority token
     suitable for emit(). By default, returns an empty string, which is OK
     only when emit() does not care!

   The following routine is frozen. There is no way in Perl to freeze a
routine, i.e. to explicitely forbid any redefinition, so this is an
informal notification:

priority($priority)
     This routine returns the proper priority for emit() for each of the
     following strings: "critical", "error", "warning" and "notice", which
     are the hardwired priority strings, as documented above.

     It derives a logging level from the $priority given and then returns
     the result of:

          map_pri($priority, $level);

     Therefore, only map_pri() should be redefined.

   Finally, the following initialization routine is provided: to record the

_init($prefix, $penalty)
     Records the prefix attribute, as well as the Carp `penalty' (amount
     of extra stack frames to skip). Should be called in the constructor of
     all the drivers.

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   Log::Agent(3), Log::Agent::Driver::Default(3),
Log::Agent::Driver::File(3), Log::Agent::Driver::Silent(3),
Log::Agent::Driver::Syslog(3), Devel::Datum(3).

interceptor driver to cooperate with Devel::Datum
*************************************************

NAME
====

   Log::Agent::Driver::Datum - interceptor driver to cooperate with
Devel::Datum

SYNOPSIS
========

   NONE

DESCRIPTION
===========

   The purpose of the interceptor is to cooperate with Devel::Datum by
emitting traces to the debug channel via Devel::Datum's traces facilities.

   This driver is automatically installed by Log::Agent when Devel::Datum
is in use and debug was activated through it.

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   Devel::Datum(3).

default logging driver for Log::Agent
*************************************

NAME
====

   Log::Agent::Driver::Default - default logging driver for Log::Agent

SYNOPSIS
========

     # Implicit use
     use Log::Agent;
     logconfig(-prefix => "prefix");   # optional

     # Explicit use
     use Log::Agent;
     require Log::Agent::Driver::Default;

     my $driver = Log::Agent::Driver::Default->make("prefix");
     logconfig(-driver => $driver);

DESCRIPTION
===========

   The default logging driver remaps the logxxx() operations to their
default Perl counterpart. For instance, logerr() will issue a warn() and
logwarn() will call warn() with a clear "WARNING: " emphasis (to
distinguish between the two calls).

   The only routine of interest here is the creation routine:

make($prefix)
     Create a Log::Agent::Driver::Default driver whose prefix string will
     be $prefix. When no prefix is configured, the first letter of each
     logged string will be uppercased.

CHANNELS
========

   The error, output and debug channels all go to STDERR.

BUGS
====

   If logdie() is used within an eval(), the string you will get in $@ will
be prefixed. It's not really a bug, simply that wrapping a code into
eval() and parsing $@ is poor's man exception handling which shows its
limit here: since the programmer using logdie() cannot foresee which
driver will be used, the returned string cannot be determined precisely.
Morality: use die() if you mean it, and document the string as an
exception.

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   Log::Agent::Driver(3), Log::Agent(3).

file logging driver for Log::Agent
**********************************

NAME
====

   Log::Agent::Driver::File - file logging driver for Log::Agent

SYNOPSIS
========

     use Log::Agent;
     require Log::Agent::Driver::File;

     my $driver = Log::Agent::Driver::File->make(
         -prefix     => "prefix",
         -duperr     => 1,
         -stampfmt   => "own",
         -showpid    => 1,
         -magic_open => 0,
         -channels   => {
            'error'   => '/tmp/output.err',
            'output'  => 'log.out',
            'debug'   => '../appli.debug',
         },
     );
     logconfig(-driver => $driver);

DESCRIPTION
===========

   The file logging driver redirects logxxx() operations to specified
files, one per channel usually (but channels may go to the same file).

   The creation routine make() takes the following arguments:

`-channels' => *hash ref*
     Specifies where channels go. The supplied hash maps channel names
     (error, output and debug) to filenames. When `-magic_open' is set to
     true, filenames are allowed magic processing via perl's open(), so
     this allows things like:

          -channels => {
              'error'   => '>&FILE',
              'output'  => '>newlog',   # recreate each time, don't append
              'debug'  => '|mailx -s whatever user',
          }

     If a channel (e.g. 'output') is not specified, it will go to the
     'error' channel, and if that one is not specified either, it will go
     to STDERR instead.

     If you have installed the additional `Log::Agent::Rotate' module, it
     is also possible to override any default rotating policy setup via
     the `-rotate' argument: instead of supplying the channel as a single
     string, use an array reference where the first item is the channel
     file, and the second one is the `Log::Agent::Rotate' configuration:

          my $rotate = Log::Agent::Rotate->make(
              -backlog     => 7,
              -unzipped    => 2,
              -max_write   => 100_000,
              -is_alone    => 1,
          );

          my $driver = Log::Agent::Driver::File->make(
              ...
              -channels => {
                  'error'  => ['errors', $rotate],
                  'output' => ['output, $rotate],
                  'debug'  => ['>&FILE, $rotate],    # WRONG
              },
              -magic_open => 1,
              ...
          );

     In the above example, the rotation policy for the debug channel will
     not be activated, since the channel is opened via a magic method.
     See Log/Agent/Rotate, for more details.

`-duperr' => flag
     When true, all messages normally sent to the error channel are also
     copied to the output channel with a prefixing made to clearly mark
     them as such: "FATAL: " for logdie(), logcroak() and logconfess(),
     "ERROR: " for logerr() and "WARNING: " for logwarn().

     Note that the "duplicate" is the original error string for
     logconfess() and logcroak(), and is not strictly identical to the
     message that will be logged to the error channel.  This is a an
     accidental feature.

     Default is false.

`-file' => file
     This switch supersedes both `-duperr' and `-channels' by defining a
     single file for all the channels.

`-magic_open' => flag
     When true, channel filenames beginning with '>' or '|' are opened
     using Perl's open(). Otherwise, sysopen() is used, in append mode.

     Default is false.

`-prefix' => prefix
     The application prefix string to prepend to messages.

`-rotate' => object
     This sets a default logfile rotation policy.  You need to install the
     additional `Log::Agent::Rotate' module to use this switch.

     object is the `Log::Agent::Rotate' instance describing the default
     policy for all the channels.  Only files which are not opened via a
     so-called *magic open* can be rotated.

`-showpid' => flag
     If set to true, the PID of the process will be appended within square
     brackets after the prefix, to all messages.

     Default is false.

`-stampfmt' => (name | CODE)
     Specifies the time stamp format to use. By default, my "own" format
     is used.  The following formats are available:

          date      "[Fri Oct 22 16:23:10 1999]"
          none
          own       "99/10/22 16:23:10"
          syslog    "Oct 22 16:23:10".

     You may also specify a CODE ref: that routine will be called every
     time we need to compute a time stamp. It should not expect any
     parameter, and should return a string.

CHANNELS
========

   All the channels go to the specified files. If a channel is not
configured, it is redirected to 'error', or STDERR if no 'error' channel
was configured either.

   Two channels not opened via a magic open and whose logfile name is the
same are effectively shared, i.e. the same file descriptor is used for
both of them. If you supply distinct rotation policies (e.g. by having a
default policy, and supplying another policy to one of the channel only),
then the final rotation policy will depend on which one was opened first.
So don't do that.

CAVEAT
======

   Beware of chdir().  If your program uses chdir(), you should always
specify logfiles by using absolute paths, otherwise you run the risk of
having your relative paths become invalid: there is no anchoring done at
the time you specify them.  This is especially true when configured for
rotation, since the logfiles are recreated as needed and you might end up
with many logfiles scattered throughout all the directories you chdir()ed
to.

   Logging channels with the same pathname are shared, i.e. they are only
opened once by Log::Agent::Driver::File.  Therefore, if you specify
different rotation policy to such channels, the channel opening order will
determine which of the policies will be used for all such shared channels.
Such errors are flagged at runtime with the following message:

     Rotation for 'logfile' may be wrong (shared with distinct policies)

   emitted in the logs upon subsequent sharing.

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   Log::Agent::Driver(3), Log::Agent(3), Log::Agent::Rotate(3).

silent logging driver for Log::Agent
************************************

NAME
====

   Log::Agent::Driver::Silent - silent logging driver for Log::Agent

SYNOPSIS
========

     use Log::Agent;
     require Log::Agent::Driver::Silent;

     my $driver = Log::Agent::Driver::Silent->make();
     logconfig(-driver => $driver);

DESCRIPTION
===========

   The silent logging driver remaps most of the logxxx() operations to
NOPs.  Only logconfess() and logdie() respectively call Carp::confess()
and die().

CHANNELS
========

   All the channels go to /dev/null, so to speak.

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   Log::Agent::Driver(3), Log::Agent(3).

syslog logging driver for Log::Agent
************************************

NAME
====

   Log::Agent::Driver::Syslog - syslog logging driver for Log::Agent

SYNOPSIS
========

     use Log::Agent;
     require Log::Agent::Driver::Syslog;

     my $driver = Log::Agent::Driver::Syslog->make(
         -prefix     => prefix,
         -facility   => "user",
         -showpid    => 1,
         -socktype   => "unix",
         -logopt     => "ndelay",
     );
     logconfig(-driver => $driver);

DESCRIPTION
===========

   The syslog logging driver delegates logxxx() operations to syslog() via
the Sys::Syslog(3) interface.

   The creation routine make() takes the following switches:

`-facility' => facility
     Tell syslog() which facility to use (e.g. "user", "auth", "daemon").
     Unlike the Sys::Syslog(3) interface, the facility is set once and for
     all: every logging message will use the same facility.

     If you wish to log something to "auth" for instance, then do so via
     Sys::Syslog directly: there is no guarantee that the application will
     configure its Log::Agent to use syslog anyway!

`-logopt' => *syslog options*
     Specifies logging options, under the form of a string containing zero
     or more of the words *ndelay*, *cons* or nowait.

`-prefix' => prefix
     The prefix here is syslog's identification string.

`-showpid' => flag
     Set to true to have the PID of the process logged. It is false by
     default.

`-socktype' => (*unix* | *inet*)
     Specifies the logging socket type to use. The default behaviour is to
     use Sys:Syslog's default.

CHANNELS
========

   All the channels go to syslog(), of course.

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   Log::Agent::Driver(3), Log::Agent::Channel::Syslog(3).

low-overhead IO::File
*********************

NAME
====

   Log::Agent::File::Native - low-overhead IO::File

SYNOPSIS
========

     require Log::Agent::File::Native;

     my $fh = Log::Agent::File::Native->make(\*main::STDERR);

DESCRIPTION
===========

   This class is a stripped down implementation of IO::File, to avoid using
the IO::* hierarchy which does not work properly for my simple needs.

make glob
     This is the creation routine. Encapsulates the glob reference so that
     we can use object-oriented calls on it.

print args
     Prints args to the file.

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   Log::Agent::File::Rotate(3), Log::Agent::Driver::File(3).

a rotating logfile set
**********************

NAME
====

   Log::Agent::File::Rotate - a rotating logfile set

SYNOPSIS
========

     #
     # This class is not user-visible.
     #
     # It is documented only for programmers wishing to inherit
     # from it to further extend its behaviour.
     #

     require Log::Agent::Driver::File;
     require Log::Agent::Rotate;
     require Log::Agent::File::Rotate;

     my $config = Log::Agent::Rotate->make(...);
     my $driver = Log::Agent::Driver::File->make(...);
     my $fh = Log::Agent::File::Rotate->make("file", $config, $driver);

DESCRIPTION
===========

   This class represents a rotating logfile and is used drivers wishing to
rotate their logfiles periodically.  From the outside, it exports a single
print routine, just like `Log::Agent::File::Native'.

   Internally, it uses the parameters given by a `Log::Agent::Rotate'
object to transparently close the current logfile and cycle the older logs.

   Its exported interface is:

make file, config
     This is the creation routine.  The config object is an instance of
     `Log::Agent::Rotate'.

print args
     Prints args to the file.  After having printed the data, monitor the
     file against the thresholds defined in the configuration, and
     possibly rotate the logfiles according to the parameters held in the
     same configuration object.

     When the is_alone flag is not set in the configuration, the logfile is
     checked everytime a print is issued to see if its inode changed.
     Indeed, when several instances of the same program using rotating
     logfiles are running, each of them may decide to cycle the logs at
     some point in time, and therefore our opened handle could point to an
     already renamed or unlinked file.

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   Log::Agent::Rotate(3), Log::Agent::Driver::File(3).

a logging interface
*******************

NAME
====

   Log::Agent::Logger - a logging interface

SYNOPSIS
========

     require Log::Agent::Logger;

     my $log = Log::Agent::Logger->make(
         -channel    => $chan,
         -max_prio   => 'info',
         -min_prio   => 'emerg',
     );
     $log->error("can't open file %s: $!", $file);
     $log->warning("can't open file: $!");

DESCRIPTION
===========

   The `Log::Agent::Logger' class defines a generic interface for
application logging.  It must not be confused with the interface provided
by Log::Agent, which is meant to be used by re-usable modules that do not
wish to commit on a particular logging method, so that they remain true
building blocks.

   By contrast, `Log::Agent::Logger' explicitely requests an object to be
used, and that object must commit upon the logging channel to be used, at
creation time.

   Optionally, minimum and maximum priority levels may be defined (and
changed dynamically) to limit the messages to effectively log, depending
on the advertised priority.  The standard syslog(3) priorities are used.

CHANNEL LIST
============

   The following channels are available:

Standard Log::Agent Channels
----------------------------

   Those channels are documented in Log/Agent/Channel.

Other Channels
--------------

   Future `Log::Agent::Logger' extension will extend the set of available
channels.

INTERFACE
=========

Creation Routine
----------------

   The creation routine is called make and takes the following switches:

`-channel'
     This defines the `Log::Agent::Channel' to be used for logging.
     Leaving this undefined will create a logger object that will never
     output anything.

`-min_prio'
     Defines the minimum priority to be logged (included).  Defaults to
     "emerg".

`-max_prio'
     Defines the maximum priority to be logged (included).  Defaults to
     "debug".

Logging Interface
-----------------

   Each routine is documented to take a single string, but you may also
supply a code reference as the first argument, followed by extra
arguments.  That routine will be called, along with the extra arguments,
to generate the message to be logged.  If that sounds crazy, think about
the CPU time we save by NOT calling the routine.  If nothing is returned
by the routine, nothing is logged.

   If more than one argument is given, and the first argument is not a
code reference, then it is taken as a printf() format, and the remaining
arguments are used to fill the various "%" placeholders in the format.
The special "%m" placeholder does not make use of any extra argument and
is replaced by a stringification of the error message contained in $!, aka
errno.

   There is a logging routine defined for each syslog(3) priority, along
with aliases for some of them.  Here is an exhaustive table, sorted by
decreasing priority.

     Syslog     Alias
     --------   ---------
     emerg      emergency
     alert
     crit       critical
     err        error
     warning    warn
     notice
     info
     debug

   We shall document only one routine for a given level: for instance, we
document warn but you could also use the standard warning to achieve
exactly the same funciton.

`emergency($str)'
     Log at the "emerg" level, usually just before panicing.  Something
     terribly bad has been detected, and the program might crash soon after
     logging this.

`alert($str)'
     Log at the "alert" level, to signal a problem requiring immediate
     attention.  Usually, some functionality will be missing until the
     condition is fixed.

`critical($str)'
     Log at the "crit" level, to signal a severe error that prevents
     fulfilling some activity.

`error($str)'
     Log at the "err" level, to signal a regular error.

`warn($str)'
     Log at the "warning" level, which is an indication that something
     unusual occurred.

`notice($str)'
     Log at the "notice" level, indicating something that is fully handled
     by the applicaiton, but which is not the norm.  A significant
     condition, as they say.

`info($str)'
     Log at the "info" level, for their amusement.

`debug($str)'
     Log at the "debug" level, to further confuse them.

Closing Channel
---------------

close
     This routine closes the channel.  Furhter logging to the logger is
     permitted, but will be simply discarded without notice.

Attribute Access
----------------

   The following access routines are defined:

channel
     The defined logging channel.  Cannot be changed.

`max_prio' and `max_prio_str'
     Returns the maximum priority recorded, either as a numeric value or
     as a string.  For the correspondance between the two, see
     Log/Agent/Priorities.

`min_prio' and `min_prio_str'
     Returns the minimum priority recorded, either as a numeric value or
     as a string.  For the correspondance between the two, see
     Log/Agent/Priorities.

`set_max_prio($prio)' and `set_min_prio($prio)'
     Used to modify the maximum/minimum priorities.  You can use either
     the string value or the numerical equivalent, as documented in
     Log/Agent/Priorities.

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   Log::Agent::Channel(3).

a log message
*************

NAME
====

   Log::Agent::Message - a log message

SYNOPSIS
========

     require Log::Agent::Message;

     my $msg = Log::Agent::Message->make("string");
     $msg->prepend("string");
     $msg->append("string");
     my $copy = $msg->clone;

     print "Message is $msg\n";     # overloaded stringification

DESCRIPTION
===========

   The Log::Agent::Message class represents an original log message (a
string) to which one may prepend or append other strings, but with the
special property that prepended strings aggregate themselves in FIFO
order, whilst appended strings aggregate themselves in LIFO order, which
is counter-intuitive at first sight.

   In plain words, this means that the last routine that prepends something
to the message will get its prepended string right next to the original
string, regardless of what could have been prepended already. The behaviour
is symetric for appending.

INTERFACE
=========

   The following routines are available:

append($str)
     Append suppled string $str to the original string (given at creation
     time), at the head of all existing appended strings.

append_last($str)
     Append suppled string $str to the original string (given at creation
     time), at the tail of all existing appended strings.

clone
     Clone the message. This is not a shallow clone, because the list of
     prepended and appended strings is recreated. However it is not a deep
     clone, because the items held in those lists are merely copied (this
     would matter only when other objects with overloaded stringification
     routines were supplied to prepend() and append(), which is not the
     case today in the basic Log::Agent framework).

make($string)
     This is the creation routine.

prepend($str)
     Prepend supplied string $str to the original string (given at creation
     time), at the tail of all existing prepended strings.

prepend_first($str)
     Prepend supplied string $str to the original string (given at creation
     time), at the head of all existing prepended strings.

stringify
     This is the overloaded "" operator, which returns the complete string
     composed of all the prepended strings, the original string, and all
     the appended strings.

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   Log::Agent(3).

conversion between syslog priorities and levels
***********************************************

NAME
====

   Log::Agent::Priorities - conversion between syslog priorities and levels

SYNOPSIS
========

     Not intended to be used directly

DESCRIPTION
===========

   This package contains routines to convert between syslog priorities and
logging levels: level_from_prio("crit") yields 2, and prio_from_level(4)
yields "warning", as does prio_from_level(5).

   Here are the known priorities (which may be abbreviated to the first 2
letters, in a case-insensitive manner) and their corresponding logging
level:

     Name    Level   Traditional    Export
         --------- -----  --------------  ------
         none       -1                    NONE    (special, see text)
         emergency   0    (emerg, panic)  EMERG
         alert       1                    ALERT
         critical    2    (crit)          CRIT
         error       3    (err)           ERROR
         warning     4                    WARN
         notice      6                    NOTICE
         info        8                    INFO
         debug       10                   DEBUG

   The values between parenthesis show the traditional syslog priority
tokens.  The missing levels (5, 7, 9) are there for possible extension.
They currently map to the level immediately below.

   The Export column lists the symbolic constants defined by this package.
They can be imported selectively, or alltogether via the `:LEVELS' tag, as
in:

     use Log::Agent::Priorities qw(:LEVELS);

   The special token "none" may be used (and spelled out fully) on special
occasions: it maps to -1, and is convenient when specifying a logging
level, for instance: specifying "none" ensures that *no logging* will take
place, even for emergency situations.

   Anywhere where a priority is expected, one may specify a number taken
as a logging level or a string taken as a priority. If the default mapping
outlined above is not satisfactory, it can be redefined by specifying, for
instance `"notice:9"'. It will be taken as being of level 9, but with a
notice priority nonetheless, not info as it would have been implicitely
determined otherwise.

   The routine priority_level() decompiles `"notice:9"' into ("notice", 9),
and otherwise uses prio_from_level() or level_from_prio() to compute the
missing informatin.  For instance, given "critical", priority_level()
routine will return the tuple ("critical", 2).

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   Log::Agent(3), Log::Agent::Logger(3).

parameters for logfile rotation
*******************************

NAME
====

   Log::Agent::Rotate - parameters for logfile rotation

SYNOPSIS
========

     require Log::Agent::Rotate;

     my $policy = Log::Agent::Rotate->make(
     	 -backlog     => 7,
     	 -unzipped    => 2,
     	 -is_alone    => 0,
     	 -max_size    => 100_000,
     	 -max_time    => "1w",
     );

DESCRIPTION
===========

   The `Log::Agent::Rotate' class holds the parameters describing the
logfile rotation policy, and is meant to be supplied to instances of
Log::Agent::Driver::File via arguments in the creation routine, such as
`-rotate', or by using array references as values in the `-channels'
hashref: See complementary information in Log/Agent/Driver/File.

   As rotation cycles are performed, the current logfile is renamed, and
possibly compressed, until the maximum backlog is reached, at which time
files are deleted.  Assuming a backlog of 5 and that the latest 2 files
are not compressed, the following files can be present on the filesystem:

     logfile           # the current logfile
     logfile.0         # most recently renamed logfile
     logfile.1
     logfile.2.gz
     logfile.3.gz
     logfile.4.gz      # oldest logfile, unlinked next cycle

   The following switches are available to the creation routine make(),
listed in alphabetical order, all taking a single integer value as
argument:

backlog
     The total amount of old logfiles to keep, besides the current logfile.

     Defaults to 7.

is_alone
     The argument is a boolean stating whether the program writing to the
     logfile will be the only one or not.  This is a hint that drives some
     optimizations, but it is up to the program to *guarantee* that noone
     else will be able to write to or unlink the current logfile when set
     to *true*.

     Defaults to false.

max_size
     The maximum logfile size.  This is a threshold, which will cause a
     logfile rotation cycle to be performed, when crossed after a write to
     the file.  If set to 0, this threshold is not checked.

     Defaults to 1 megabyte.

max_time
     The maximum time in seconds between the moment we opened the file and
     the next rotation cycle occurs.  This threshold is only checked after
     a write to the file.

     The value can also be given as a string, postfixed by one of the
     following letters to specify the period unit (e.g. "3w"):

          Letter   Unit
          ------   -------
             m     minutes
             h     hours
             d     days
             d     days
             w     weeks
             M     months (30 days of 24 hours)
             y     years

     Defaults to 0, meaning it is not checked.

max_write
     The maximum amount of data we can write to the logfile.  Like
     max_size, this is a threshold, which is only checked after a write to
     the logfile.  This is not the total logfile size: if several programs
     write to the same logfile and max_size is not used, then the logfiles
     may never be rotated at all if none of the programs write at least
     max_write bytes to the logfile before exiting.

     Defaults to 0, meaning it is not checked.

single_host
     The argument is a boolean stating whether the access to the logfiles
     will be made from one single host or not.  This is a hint that drives
     some optimizations, but it is up to the program to *guarantee* that
     it is accurately set.

     Defaults to false, which is always a safe value.

unzipped
     The amount of old logfiles, amongst the most recent ones, that should
     not be compressed but be kept as plain files.

     Defaults to 1.

   To test whether two configurations are strictly identical, use
is_same(), as in:

     print "identical\n" if $x->is_same($y);

   where both $x and $y are `Log::Agent::Rotate' objects.

   All the aforementionned switches also have a corresponding querying
routine that can be issued on instances of the class to get their value.
It is not possible to modify those attributes.

   For instance:

     my $x = Log::Agent::Rotate->make(...);
     my $mwrite = $x->max_write();

   would get the configured max_write threshold.

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   Log::Agent(3), Log::Agent::Driver::File(3), Log::Agent::Rotate::File(3).

time-stamping routines
**********************

NAME
====

   Log::Agent::Stamping - time-stamping routines

SYNOPSIS
========

     Not intended to be used directly

DESCRIPTION
===========

   This package contains routines to generate the leading time-stamping on
logged messages.  Formats are identified by a name, and the stamping_fn()
function converts that name into a CODE ref, defaulting to the "own"
format when given an unknown name.

   Here are the known formats:

     date      "[Fri Oct 22 16:23:10 1999]"
     none
     own       "99/10/22 16:23:10"
     syslog    "Oct 22 16:23:10"

   Channels or Drivers which take a `-stampfmt' switch expect either a
string giving the format name (e.g. "date"), or a CODE ref.  That
referenced routine will be called every time we need to compute a time
stamp.  It should not expect any parameter, and should return a stamping
string.

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   Log::Agent(3), Log::Agent::Channel(3), Log::Agent::Driver(3).

log messages in the httpd access and error log styles
*****************************************************

NAME
====

   Log::Common - log messages in the httpd access and error log styles

SYNOPSIS
========

     use Log::Common;

     $l = new Log::Common(access => "/var/log/search-hits",
                          error  => "/usr/local/log/error_log",
                          no_stderr => 1,
                          class => "debug");

     $l->error(message => "Uh-oh... :-(", fatal => 1);
     $l->access(user => "martin", message => "$query_string",
     	       code => 200);

DESCRIPTION
===========

   This class defines two methods which may be used to write messages to
*httpd* common log file style access and error log files, such as those
maintained by the Apache and NCSA WWW servers.  The log file is locked
whilst being written to avoid corruption when multiple processes attempt
to write to the same file at the same time.  For convenience both methods
support a parameter which, if specified, results in "exit" being called to
bomb out of the program.

   If the environmental variable GATEWAY_INTERFACE isn't set, error
messages are also sent to STDERR - though this behaviour can be overridden
if undesired.  This is so that Perl programs which use this class can
trivially dump out messages both to their end user and to a system log
file at the same time.

   Error log file entries are written with a leading UTC timestamp, in the
common HTTP server usage.

METHODS
=======

access( [ OPTIONS ] );
error( [ OPTIONS ] );
PARAMETERS
==========

   When creating a Log::Common object:

access => *access_log_filename*
     This is the filename to use when logging via the access method.

error => *error_log_filename*
     This is the filename to use when logging via the error method.

class => *class_name*
     The default class of error log messages.  You can use this to
     distinguish between debugging info, security related info, messages
     from WWW servers, messages from the mail system, and so on.  This
     default value can be overridden in an individual call to the error
     logging method.

no_stderr => 0 or 1
     Suppress the printing of the message to STDERR if set to 1, defaults
     to 0.  This can be overridden when the error method is invoked.

   Common to both methods:

fatal => *exit_code*
     This indicates that whatever happened was a fatal error, and causes
     the program to croak after the log file entry has been written.  The
     value given will be used as the program's exit code.

message => *message_string*
     The actual message to write to the log file.

   For the access method only:

count => number
     Normally the number of bytes transferred - 0 if not supplied.

code => *response_code*
     Normally the number of bytes transferred - 0 if not supplied.

host => host_name
     The domain name or IP address of the calling/client host.  If not
     supplied, the process environment will be checked for REMOTE_HOST and
     REMOTE_ADDR (as set by CGI) in turn.  If neither of these is present
     this field in the log file will be set to *0.0.0.0*.

ident => *value_of_ident_lookup*
     Normally the result of an IDENT (AUTH) lookup on the calling host and
     port.  If not supplied, the value of REMOTE_IDENT in the process
     environment will be used, or "-".

user => *authenticated_user_name*
     Normally the user name which has been authenticated, e.g. using basic
     HTTP authentication.  If not supplied, the value of REMOTE_USER in the
     process environment will be used instead, or "-".

   For the error method only:

class => *class_name*
     Overrides default setting for this invocation - see above.

info => *info_string*
     Additional info - this will be rendered enclosed in round brackets at
     the end of this line in the log file.

no_stderr => 0 or 1
     Overrides default setting for this invocation - see above.

FILE FORMATS
============

   Note that these are the common field usages - you don't have to put the
same things in the same fields, though it would probably make life easier
if you were planning to process these log files through existing HTTP
server log file analysis tools.

   The error log file is structured as follows :-

*the date*
     This is prettyprinted in GMT (UTC) using the gmtime function and
     enclosed in square brackets.  It's always generated for you.

*the class of message*
     This will be followed by a colon character ':'.  Taken from the class
     parameter.  This overrides any default value set for the object as a
     whole.

*any supplementary information*
     Taken from the info parameter.  This will be enclosed in round
     brackets.

   The access log file is structured as follows :-

*client host name/IP address*
     Taken from the host parameter.

*remote user name*
     Taken from the ident parameter.  This is normally found via the
     AUTH/IDENT protocol - RFC 1413, RFC 931.

*remote user name*
     Taken from the user parameter.  This is normally from HTTP
     authentication.

timestamp
     Generated using localtime, with a GMT (UTC) offset.  This will be
     enclosed in square brackets, and will always be generated
     automatically for you.

*the message itself*
     Taken from the message parameter.

*response status code*
     Taken from the code parameter.  This is normally numeric.

*bytes transferred count*
     Taken from the count parameter.  This is normally numeric.

BUGS
====

   None ? :-)

TODO
====

   Extended log file format (dump variable X as field Y in the log file
entry?) might be useful.

COPYRIGHT
=========

   Copyright (c) 1998 Martin Hamilton <martinh@gnu.org> and Jon Knight
<jon@net.lut.ac.uk>.  All rights reserved.  This program is free software;
you can redistribute it and/or modify it under the same terms as Perl
itself.

   It was developed by the Department of Computer Studies at Loughborough
University of Technology, as part of the ROADS project.  This work was
funded by the Joint Information Systems Committee (JISC) of the Higher
Education Funding Councils under the UK Electronic Libraries Programme
(eLib), the European Commission DESIRE project, and the TERENA development
programme.

AUTHORS
=======

     Jon Knight <jon@net.lut.ac.uk>
     Martin Hamilton <martinh@gnu.org>

Dispatches messages to multiple Log::Dispatch::* objects
********************************************************

NAME
====

   Log::Dispatch - Dispatches messages to multiple Log::Dispatch::* objects

SYNOPSIS
========

     use Log::Dispatch;

     my $dispatcher = Log::Dispatch->new;

     $dispatcher->add( Log::Dispatch::File->new( name => 'file1',
                                                 min_level => 'debug',
                                                 filename => 'logfile' ) );

     $dispatcher->log( level => 'info',
                       message => 'Blah, blah' );

     my $sub = sub { my %p = @_;  return reverse $p{message}; };
     my $reversing_dispatcher = Log::Dispatch->new( callbacks => $sub );

DESCRIPTION
===========

   This module manages a set of Log::Dispatch::* objects, allowing you to
add and remove output objects as desired.

METHODS
=======

   * new

     Returns a new Log::Dispatch object.  This method takes one optional
     parameter:

   * - callbacks( \& or [ \&, \&, ... ] ) This parameter may be a single
     subroutine reference or an array reference of subroutine references.
     These callbacks will be called in the order they are given and passed
     a hash containing the following keys:

          ( message => $log_message, level => $log_level )

     It's a hash in case I need to add parameters in the future.

     The callbacks are expected to modify the message and then return a
     single scalar containing that modified message.  These callbacks will
     be called when either the log or `log_to' methods are called and will
     only be applied to a given message once.  If they do not return the
     message then you will get no output.  Make sure to return the message!

   * add( Log::Dispatch::* OBJECT )

     Adds a new a Log::Dispatch::* object to the dispatcher.  If an object
     of the same name already exists, then that object is replaced.  A
     warning will be issued if the '-w' flag is set.

     NOTE: This method can really take any object that has methods called
     'name' and 'log'.

   * remove($)

     Removes the object that matches the name given to the remove method.
     The return value is the object being removed or undef if no object
     matched this.

   * log( level => $, message => $ )

     Sends the message (at the appropriate level) to all the
     Log::Dispatch::* objects that the dispatcher contains (by calling the
     `log_to' method repeatedly).

   * log_to( name => $, level => $, message => $ )

     Sends the message only to the named object.

   * level_is_valid( $string )

     Returns true or false to indicate whether or not the given string is a
     valid log level.  Can be called as either a class or object method.

CONVENIENCE METHODS
===================

   Version 1.6 of Log::Dispatch adds a number of convenience methods for
logging.  You may now call any valid log level (including valid
abbreviations) as a method on the Log::Dispatch object with a single
argument that is the message to be logged.  This is converted into a call
to the log method with the appropriate level.

   For example:

     $dispatcher->alert('Strange data in incoming request');

   translates to:

     $dispatcher->log( level => 'alert', message => 'Strange data in incoming request' );

   These methods act like Perl's print built-in when given a list of
arguments.  Thus, the following calls are equivalent:

     my @array = ('Something', 'bad', 'is', here');
     $dispatcher->alert(@array);

     my $scalar = join $,, @array; # That is not a typo.  See perldoc perlvar for info on $,
     $dispatcher->alert($scalar);

   One important caveat about these methods is that its not that forwards
compatible.  If I were to add more parameters to the log call, it is
unlikely that these could be integrated into these methods without
breaking existing uses.  This probably means that any future parameters to
the log method will never be integrated into these convenience methods.
OTOH, I don't see any immediate need to expand the parameters given to the
log method.

Log Levels
----------

   The log levels that Log::Dispatch uses are taken directly from the
syslog man pages (except that I expanded them to full words).  Valid
levels are:

     debug
     info
     notice
     warning
     error
     critical
     alert
     emergency

   Alternately, the numbers 0 through 7 may be used (debug is 0 and
emergency is 7).  The syslog standard of 'err', 'crit', and 'emerg' is
also acceptable.

USAGE
=====

   This logging system is designed to be used as a one-stop logging
system.  In particular, it was designed to be easy to subclass so that if
you want to handle messaging in a way other than one of the modules used
here, you should be able to implement this with minimal effort.

   The basic idea behind Log::Dispatch is that you create a Log::Dispatch
object and then add various logging objects to it (such as a file logger
or screen logger).  Then you call the log method of the dispatch object,
which passes the message to each of the objects, which in turn decide
whether or not to accept the message and what to do with it.

   This makes it possible to call single method and send a message to a
log file, via email, to the screen, and anywhere else all in one simple
command.

   The logging levels that Log::Dispatch uses are borrowed from the
standard UNIX syslog levels, except that where syslog uses partial words
('err') Log::Dispatch also allows the use of the full word as well
('error').

   Please note that because this code uses pseudo-hashes and compile-time
object typing that it will only run under Perl 5.005 or greater.

Making your own logging objects
-------------------------------

   Making your own logging object is generally as simple as subclassing
Log::Dispatch::Output and overriding the new and log methods.  See the
Log/Dispatch/Output, docs for more details.

   If you would like to create your own subclass for sending email then it
is even simpler.  Simply subclass Log/Dispatch/Email,
and override the `send_email' method.  See the
Log/Dispatch/Email, docs for more details.

Why doesn't Log::Dispatch add a newline to the message?
-------------------------------------------------------

   A few people have written email to me asking me to add something that
would tack a newline onto the end of all messages that don't have one.
This will never happen.  There are several reasons for this.  First of
all, Log::Dispatch was designed as a simple system to broadcast a message
to multiple outputs.  It does not attempt to understand the message in any
way at all.  Adding a newline implies an attempt to understand something
about the message and I don't want to go there.  Secondly, this is not
very cross-platform and I don't want to go down the road of testing Config
values to figure out what to tack onto messages based on OS.

   I think people's desire to do this is because they are too focused on
just the logging to files aspect of this module.  In this case newlines
make sense.  However, imagine someone is using this module to log to a
remote server and the interactions between the client and server use
newlines as part of the control flow.  Casually adding a newline could
cause serious problems.

   However, the 1.2 release adds the callbacks parameter for the
Log::Dispatch object which you can easily use to add newlines to messages
if you so desire.

RELATED MODULES
===============

Log::Dispatch::Tk
-----------------

   Dominique Dumont has written Log::Dispatch::Tk which allows log
messages to show up in a window.  This code is available from CPAN.

AUTHOR
======

   Dave Rolsky, <autarch@urth.org>

SEE ALSO
========

   Log::Dispatch::ApacheLog, Log::Dispatch::Email,
Log::Dispatch::Email::MailSend, Log::Dispatch::Email::MailSendmail,
Log::Dispatch::Email::MIMELite, Log::Dispatch::File,
Log::Dispatch::Handle, Log::Dispatch::Output, Log::Dispatch::Screen,
Log::Dispatch::Syslog

Object for logging to Apache::Log objects
*****************************************

NAME
====

   Log::Dispatch::ApacheLog - Object for logging to Apache::Log objects

SYNOPSIS
========

     use Log::Dispatch::ApacheLog;

     my $handle = Log::Dispatch::ApacheLog->new( name      => 'apache log',
                                                 min_level => 'emerg',
                                                 apache    => $r );

     $handle->log( level => 'emerg', message => 'Kaboom' );

DESCRIPTION
===========

   This module allows you to pass messages Apache's log object,
represented by the Apache::Log class.

METHODS
=======

   * new(%PARAMS)

     This method takes a hash of parameters.  The following options are
     valid:

   * - name ($) The name of the object (not the filename!).  Required.

   * - min_level ($) The minimum logging level this object will accept.
     See the Log::Dispatch documentation for more information.  Required.

   * - max_level ($) The maximum logging level this obejct will accept.
     See the Log::Dispatch documentation for more information.  This is not
     required.  By default the maximum is the highest possible level (which
     means functionally that the object has no maximum).

   * - apache ($) The apache object.

   * - callbacks( \& or [ \&, \&, ... ] ) This parameter may be a single
     subroutine reference or an array reference of subroutine references.
     These callbacks will be called in the order they are given and passed
     a hash containing the following keys:

          ( message => $log_message )

     It's a hash in case I need to add parameters in the future.

     The callbacks are expected to modify the message and then return a
     single scalar containing that modified message.  These callbacks will
     be called when either the log or `log_to' methods are called and will
     only be applied to a given message once.

   * log_message( message => $ )

     Sends a message to the appropriate output.  Generally this shouldn't
     be called directly but should be called through the `log()' method
     (in Log::Dispatch::Output).

AUTHOR
======

   Dave Rolsky, <autarch@urth.org>

SEE ALSO
========

   Log::Dispatch, Log::Dispatch::Email, Log::Dispatch::Email::MailSend,
Log::Dispatch::Email::MailSendmail, Log::Dispatch::Email::MIMELite,
Log::Dispatch::File, Log::Dispatch::Output, Log::Dispatch::Screen,
Log::Dispatch::Syslog, Apache::Log

Code shared by dispatch and output objects.
*******************************************

NAME
====

   Log::Dispatch::Base - Code shared by dispatch and output objects.

SYNOPSIS
========

     use Log::Dispatch::Base;

     ...

     @ISA = qw(Log::Dispatch::Base);

DESCRIPTION
===========

   Unless you are me, you probably don't need to know what this class does.

AUTHOR
======

   Dave Rolsky, <autarch@urth.org>

SEE ALSO
========

   Log::Dispatch, Log::Dispatch::ApacheLog, Log::Dispatch::Email,
Log::Dispatch::Email::MailSend, Log::Dispatch::Email::MailSendmail,
Log::Dispatch::Email::MIMELite, Log::Dispatch::Handle,
Log::Dispatch::Output, Log::Dispatch::Screen, Log::Dispatch::Syslog

Base class for objects that send log messages via email
*******************************************************

NAME
====

   Log::Dispatch::Email - Base class for objects that send log messages
via email

SYNOPSIS
========

     package Log::Dispatch::Email::MySender

     use Log::Dispatch::Email;
     use base qw( Log::Dispatch::Email );

     sub send_email
     {
         my Log::Dispatch::Email::MySender $self = shift;
         my %params = @_;

     # Send email somehow.  Message is in $params{message}
       }

DESCRIPTION
===========

   This module should be used as a base class to implement
Log::Dispatch::* objects that send their log messages via email.
Implementing a subclass simply requires the code shown in the `SYNOPSIS'
in this node with a real implementation of the `send_email()' method.

METHODS
=======

   * new(%PARAMS)

     This method takes a hash of parameters.  The following options are
     valid:

   * - name ($) The name of the object (not the filename!).  Required.

   * - min_level ($) The minimum logging level this object will accept.
     See the Log::Dispatch documentation for more information.  Required.

   * - max_level ($) The maximum logging level this obejct will accept.
     See the Log::Dispatch documentation for more information.  This is not
     required.  By default the maximum is the highest possible level (which
     means functionally that the object has no maximum).

   * - subject ($) The subject of the email messages which are sent.
     Defaults to "$0: log email"

   * - to ($ or \@) Either a string or a list reference of strings
     containing email addresses.  Required.

   * - from ($) A string containing an email address.  This is optional
     and may not work with all mail sending methods.

   * - buffered (0 or 1) This determines whether the object sends one
     email per message it is given or whether it stores them up and sends
     them all at once.  The default is to buffer messages.

   * - callbacks( \& or [ \&, \&, ... ] ) This parameter may be a single
     subroutine reference or an array reference of subroutine references.
     These callbacks will be called in the order they are given and passed
     a hash containing the following keys:

          ( message => $log_message )

     It's a hash in case I need to add parameters in the future.

     The callbacks are expected to modify the message and then return a
     single scalar containing that modified message.  These callbacks will
     be called when either the log or `log_to' methods are called and will
     only be applied to a given message once.

   * log_message( message => $ )

     Sends a message to the appropriate output.  Generally this shouldn't
     be called directly but should be called through the `log()' method
     (in Log::Dispatch::Output).

   * send_email(%PARAMS)

     This is the method that must be subclassed.  For now the only
     parameter in the hash is 'message'.

   * DESTROY

     If the object is buffered, then this method will call the
     `send_email()' method to send the contents of the buffer.

AUTHOR
======

   Dave Rolsky, <autarch@urth.org>

SEE ALSO
========

   Log::Dispatch, Log::Dispatch::ApacheLog,
Log::Dispatch::Email::MailSend, Log::Dispatch::Email::MailSendmail,
Log::Dispatch::Email::MIMELite, Log::Dispatch::File,
Log::Dispatch::Handle, Log::Dispatch::Output, Log::Dispatch::Screen,
Log::Dispatch::Syslog

Subclass of Log::Dispatch::Email that uses the Mail::Sendmail module
********************************************************************

NAME
====

   Log::Dispatch::Email::MIMELite - Subclass of Log::Dispatch::Email that
uses the Mail::Sendmail module

SYNOPSIS
========

     use Log::Dispatch::Email::MIMELite;

     my $email = Log::Dispatch::Email::MIMELite->new( name => 'email',
                                                      min_level => 'emerg',
                                                      to => [ qw( foo@bar.com bar@baz.org ) ],
                                                      subject => 'Oh no!!!!!!!!!!!', );

     $email->log( message => "Something bad is happening\n", level => 'emerg' );

DESCRIPTION
===========

   This is a subclass of Log::Dispatch::Email that implements the
send_email method using the MIME::Lite module.

METHODS
=======

   * new

     This method takes a hash of parameters.  The following options are
     valid:

   * - name ($) The name of the object (not the filename!).  Required.

   * - min_level ($) The minimum logging level this object will accept.
     See the Log::Dispatch documentation for more information.  Required.

   * - max_level ($) The maximum logging level this obejct will accept.
     See the Log::Dispatch documentation for more information.  This is not
     required.  By default the maximum is the highest possible level (which
     means functionally that the object has no maximum).

   * - subject ($) The subject of the email messages which are sent.
     Defaults to "$0: log email"

   * - to ($ or \@) Either a string or a list reference of strings
     containing email addresses.  Required.

   * - from ($) A string containing an email address.  This is optional
     and may not work with all mail sending methods.

   * - buffered (0 or 1) This determines whether the object sends one
     email per message it is given or whether it stores them up and sends
     them all at once.  The default is to buffer messages.

   * - callbacks( \& or [ \&, \&, ... ] ) This parameter may be a single
     subroutine reference or an array reference of subroutine references.
     These callbacks will be called in the order they are given and passed
     a hash containing the following keys:

          ( message => $log_message )

     It's a hash in case I need to add parameters in the future.

     The callbacks are expected to modify the message and then return a
     single scalar containing that modified message.  These callbacks will
     be called when either the log or `log_to' methods are called and will
     only be applied to a given message once.

   * log( level => $, message => $ )

     Sends a message if the level is greater than or equal to the object's
     minimum level.

AUTHOR
======

   Dave Rolsky, <autarch@urth.org>

SEE ALSO
========

   Log::Dispatch, Log::Dispatch::ApacheLog, Log::Dispatch::Email,
Log::Dispatch::Email::MailSend, Log::Dispatch::Email::MailSendmail,
Log::Dispatch::File, Log::Dispatch::Handle, Log::Dispatch::Output,
Log::Dispatch::Screen, Log::Dispatch::Syslog

Subclass of Log::Dispatch::Email that uses the Mail::Send module
****************************************************************

NAME
====

   Log::Dispatch::Email::MailSend - Subclass of Log::Dispatch::Email that
uses the Mail::Send module

SYNOPSIS
========

     use Log::Dispatch::Email::MailSend;

     my $email = Log::Dispatch::Email::MailSend->new( name => 'email',
                                                      min_level => 'emerg',
                                                      to => [ qw( foo@bar.com bar@baz.org ) ],
                                                      subject => 'Oh no!!!!!!!!!!!', );

     $email->log( message => 'Something bad is happening', level => 'emerg' );

DESCRIPTION
===========

   This is a subclass of Log::Dispatch::Email that implements the
send_email method using the Mail::Send module.

METHODS
=======

   * new

     This method takes a hash of parameters.  The following options are
     valid:

   * - name ($) The name of the object (not the filename!).  Required.

   * - min_level ($) The minimum logging level this object will accept.
     See the Log::Dispatch documentation for more information.  Required.

   * - max_level ($) The maximum logging level this obejct will accept.
     See the Log::Dispatch documentation for more information.  This is not
     required.  By default the maximum is the highest possible level (which
     means functionally that the object has no maximum).

   * - subject ($) The subject of the email messages which are sent.
     Defaults to "$0: log email"

   * - to ($ or \@) Either a string or a list reference of strings
     containing email addresses.  Required.

   * - from ($) A string containing an email address.  This is optional
     and may not work with all mail sending methods.

   * - buffered (0 or 1) This determines whether the object sends one
     email per message it is given or whether it stores them up and sends
     them all at once.  The default is to buffer messages.

   * - callbacks( \& or [ \&, \&, ... ] ) This parameter may be a single
     subroutine reference or an array reference of subroutine references.
     These callbacks will be called in the order they are given and passed
     a hash containing the following keys:

          ( message => $log_message )

     It's a hash in case I need to add parameters in the future.

     The callbacks are expected to modify the message and then return a
     single scalar containing that modified message.  These callbacks will
     be called when either the log or `log_to' methods are called and will
     only be applied to a given message once.

   * log( level => $, message => $ )

     Sends a message if the level is greater than or equal to the object's
     minimum level.

AUTHOR
======

   Dave Rolsky, <autarch@urth.org>

SEE ALSO
========

   Log::Dispatch, Log::Dispatch::ApacheLog, Log::Dispatch::Email,
Log::Dispatch::Email::MailSendmail, Log::Dispatch::Email::MIMELite,
Log::Dispatch::File, Log::Dispatch::Handle, Log::Dispatch::Output,
Log::Dispatch::Screen, Log::Dispatch::Syslog

Subclass of Log::Dispatch::Email that uses the Mail::Sendmail module
********************************************************************

NAME
====

   Log::Dispatch::Email::MailSendmail - Subclass of Log::Dispatch::Email
that uses the Mail::Sendmail module

SYNOPSIS
========

     use Log::Dispatch::Email::MailSendmail;

     my $email = Log::Dispatch::Email::MailSendmail->new( name => 'email',
                                                          min_level => 'emerg',
                                                          to => [ qw( foo@bar.com bar@baz.org ) ],
                                                          subject => 'Oh no!!!!!!!!!!!', );

     $email->log( message => 'Something bad is happening', level => 'emerg' );

DESCRIPTION
===========

   This is a subclass of Log::Dispatch::Email that implements the
send_email method using the Mail::Sendmail module.

METHODS
=======

   * new

     This method takes a hash of parameters.  The following options are
     valid:

   * - name ($) The name of the object (not the filename!).  Required.

   * - min_level ($) The minimum logging level this object will accept.
     See the Log::Dispatch documentation for more information.  Required.

   * - max_level ($) The maximum logging level this obejct will accept.
     See the Log::Dispatch documentation for more information.  This is not
     required.  By default the maximum is the highest possible level (which
     means functionally that the object has no maximum).

   * - subject ($) The subject of the email messages which are sent.
     Defaults to "$0: log email"

   * - to ($ or \@) Either a string or a list reference of strings
     containing email addresses.  Required.

   * - from ($) A string containing an email address.  This is optional
     and may not work with all mail sending methods.

     NOTE: The Mail::Sendmail module requires an address be passed to it to
     set this in the mail it sends.  We pass in 'LogDispatch@foo.bar' as
     the default.

   * - buffered (0 or 1) This determines whether the object sends one
     email per message it is given or whether it stores them up and sends
     them all at once.  The default is to buffer messages.

   * - callbacks( \& or [ \&, \&, ... ] ) This parameter may be a single
     subroutine reference or an array reference of subroutine references.
     These callbacks will be called in the order they are given and passed
     a hash containing the following keys:

          ( message => $log_message )

     It's a hash in case I need to add parameters in the future.

     The callbacks are expected to modify the message and then return a
     single scalar containing that modified message.  These callbacks will
     be called when either the log or `log_to' methods are called and will
     only be applied to a given message once.

   * log( level => $, message => $ )

     Sends a message if the level is greater than or equal to the object's
     minimum level.

AUTHOR
======

   Dave Rolsky, <autarch@urth.org>

SEE ALSO
========

   Log::Dispatch, Log::Dispatch::ApacheLog, Log::Dispatch::Email,
Log::Dispatch::Email::MailSend, Log::Dispatch::Email::MIMELite,
Log::Dispatch::File, Log::Dispatch::Handle, Log::Dispatch::Output,
Log::Dispatch::Screen, Log::Dispatch::Syslog

Object for logging to files
***************************

NAME
====

   Log::Dispatch::File - Object for logging to files

SYNOPSIS
========

     use Log::Dispatch::File;

     my $file = Log::Dispatch::File->new( name      => 'file1',
                                          min_level => 'info',
                                          filename  => 'Somefile.log',
                                          mode      => 'append' );

     $file->log( level => 'emerg', message => "I've fallen and I can't get up\n" );

DESCRIPTION
===========

   This module provides a simple object for logging to files under the
Log::Dispatch::* system.

METHODS
=======

   * new(%PARAMS)

     This method takes a hash of parameters.  The following options are
     valid:

   * - name ($) The name of the object (not the filename!).  Required.

   * - min_level ($) The minimum logging level this object will accept.
     See the Log::Dispatch documentation for more information.  Required.

   * - max_level ($) The maximum logging level this obejct will accept.
     See the Log::Dispatch documentation for more information.  This is not
     required.  By default the maximum is the highest possible level (which
     means functionally that the object has no maximum).

   * - filename ($) The filename to be opened for writing.

   * - mode ($) The mode the file should be opened with.  Valid options
     are 'write', '>', 'append', '>>', or the relevant constants from
     Fcntl.  The default is 'write'.

   * - callbacks( \& or [ \&, \&, ... ] ) This parameter may be a single
     subroutine reference or an array reference of subroutine references.
     These callbacks will be called in the order they are given and passed
     a hash containing the following keys:

          ( message => $log_message )

     It's a hash in case I need to add parameters in the future.

     The callbacks are expected to modify the message and then return a
     single scalar containing that modified message.  These callbacks will
     be called when either the log or `log_to' methods are called and will
     only be applied to a given message once.

   * log_message( message => $ )

     Sends a message to the appropriate output.  Generally this shouldn't
     be called directly but should be called through the `log()' method
     (in Log::Dispatch::Output).

AUTHOR
======

   Dave Rolsky, <autarch@urth.org>

SEE ALSO
========

   Log::Dispatch, Log::Dispatch::ApacheLog, Log::Dispatch::Email,
Log::Dispatch::Email::MailSend, Log::Dispatch::Email::MailSendmail,
Log::Dispatch::Email::MIMELite, Log::Dispatch::Handle,
Log::Dispatch::Output, Log::Dispatch::Screen, Log::Dispatch::Syslog

Object for logging to IO::Handle objects (and subclasses thereof)
*****************************************************************

NAME
====

   Log::Dispatch::Handle - Object for logging to IO::Handle objects (and
subclasses thereof)

SYNOPSIS
========

     use Log::Dispatch::Handle;

     my $handle = Log::Dispatch::Handle->new( name      => 'a handle',
                                              min_level => 'emerg',
                                              handle    => $io_socket_object );

     $handle->log( level => 'emerg', message => 'I am the Lizard King!' );

DESCRIPTION
===========

   This module supplies a very simple object for logging to some sort of
handle object.  Basically, anything that implements a print() method can
be passed the object constructor and it should work.

METHODS
=======

   * new(%PARAMS)

     This method takes a hash of parameters.  The following options are
     valid:

   * - name ($) The name of the object (not the filename!).  Required.

   * - min_level ($) The minimum logging level this object will accept.
     See the Log::Dispatch documentation for more information.  Required.

   * - max_level ($) The maximum logging level this obejct will accept.
     See the Log::Dispatch documentation for more information.  This is not
     required.  By default the maximum is the highest possible level (which
     means functionally that the object has no maximum).

   * - handle ($) The handle object.  This object must implement a print()
     method.

   * - callbacks( \& or [ \&, \&, ... ] ) This parameter may be a single
     subroutine reference or an array reference of subroutine references.
     These callbacks will be called in the order they are given and passed
     a hash containing the following keys:

          ( message => $log_message )

     It's a hash in case I need to add parameters in the future.

     The callbacks are expected to modify the message and then return a
     single scalar containing that modified message.  These callbacks will
     be called when either the log or `log_to' methods are called and will
     only be applied to a given message once.

   * log_message( message => $ )

     Sends a message to the appropriate output.  Generally this shouldn't
     be called directly but should be called through the `log()' method
     (in Log::Dispatch::Output).

AUTHOR
======

   Dave Rolsky, <autarch@urth.org>

SEE ALSO
========

   Log::Dispatch, Log::Dispatch::ApacheLog, Log::Dispatch::Email,
Log::Dispatch::Email::MailSend, Log::Dispatch::Email::MailSendmail,
Log::Dispatch::Email::MIMELite, Log::Dispatch::File,
Log::Dispatch::Output, Log::Dispatch::Screen, Log::Dispatch::Syslog

Base class for all Log::Dispatch::* object
******************************************

NAME
====

   Log::Dispatch::Output - Base class for all Log::Dispatch::* object

SYNOPSIS
========

     package Log::Dispatch::MySubclass;

     use Log::Dispatch::Output;
     use base qw( Log::Dispatch::Output );

     sub new
     {
         my $proto = shift;
         my $class = ref $proto || $proto;

     my %params = @_;

     my $self;
     {
     	  no strict 'refs';
     	  $self = bless [ \%{"${class}::FIELDS"} ], $class;
     }

     $self->_basic_init(%params);

     # Do more if you like
       }

     sub log_message
     {
         my Log::Dispatch::MySubclass $self = shift;
         my %params = @_;

     # Do something with message in $params{message}
       }

DESCRIPTION
===========

   This module is the base class from which all Log::Dispatch::* objects
should be derived.

METHODS
=======

   * new(%PARAMS)

     This must be overridden in a subclass.  Takes the following
     parameters:

   * - name ($) The name of the object (not the filename!).  Required.

   * - min_level ($) The minimum logging level this object will accept.
     See the Log::Dispatch documentation for more information.  Required.

   * - max_level ($) The maximum logging level this obejct will accept.
     See the Log::Dispatch documentation for more information.  This is not
     required.  By default the maximum is the highest possible level (which
     means functionally that the object has no maximum).

   * - callbacks( \& or [ \&, \&, ... ] ) This parameter may be a single
     subroutine reference or an array reference of subroutine references.
     These callbacks will be called in the order they are given and passed
     a hash containing the following keys:

          ( message => $log_message )

     It's a hash in case I need to add parameters in the future.

     The callbacks are expected to modify the message and then return a
     single scalar containing that modified message.  These callbacks will
     be called when either the log or `log_to' methods are called and will
     only be applied to a given message once.

   * _basic_init(%PARAMS)

     This should be called from a subclass's constructor.  Make sure to
     pass the arguments in @_ to it.  It sets the object's name and minimum
     level.  It also sets up two other attributes which are used by other
     Log::Dispatch::Output methods, level_names and level_numbers.

   * name

     Returns the object's name.

   * min_level

     Returns the object's minimum log level.

   * max_level

     Returns the object's maximum log level.

   * accepted_levels

     Returns a list of the object's accepted levels (by name) from minimum
     to maximum.

   * log( level => $, message => $ )

     Sends a message if the level is greater than or equal to the object's
     minimum level.  This method applies any message formatting callbacks
     that the object may have.

   * _should_log ($)

     This method is called from the `log()' method with the log level of
     the message to be logged as an argument.  It returns a boolean value
     indicating whether or not the message should be logged by this
     particular object.  The `log()' method will not process the message
     if the return value is false.

   * _level_as_number ($)

     This method will take a log level as a string (or a number) and return
     the number of that log level.  If not given an argument, it returns
     the calling object's log level instead.  If it cannot determine the
     level then it will issue a warning and return undef.

Subclassing
-----------

   This class should be used as the base class for all logging objects you
create that you would like to work under the Log::Dispatch architecture.
Subclassing is fairly trivial.  For most subclasses, if you simply copy
the code in the SYNOPSIS and then put some functionality into the
`log_message' method then you should be all set.  Please make sure to use
the `_basic_init' method as directed.

AUTHOR
======

   Dave Rolsky, <autarch@urth.org>

SEE ALSO
========

   Log::Dispatch, Log::Dispatch::ApacheLog, Log::Dispatch::Email,
Log::Dispatch::Email::MailSend, Log::Dispatch::Email::MailSendmail,
Log::Dispatch::Email::MIMELite, Log::Dispatch::File,
Log::Dispatch::Handle, Log::Dispatch::Screen, Log::Dispatch::Syslog

Object for logging to the screen
********************************

NAME
====

   Log::Dispatch::Screen - Object for logging to the screen

SYNOPSIS
========

     use Log::Dispatch::Screen;

     my $screen = Log::Dispatch::Screen->new( name      => 'screen',
                                              min_level => 'debug',
                                              stderr    => 1 );

     $screen->log( level => 'alert', message => "I'm searching the city for sci-fi wasabi\n" );

DESCRIPTION
===========

   This module provides an object for logging to the screen (really STDOUT
or STDERR).

METHODS
=======

   * new(%PARAMS)

     This method takes a hash of parameters.  The following options are
     valid:

   * - name ($) The name of the object (not the filename!).  Required.

   * - min_level ($) The minimum logging level this object will accept.
     See the Log::Dispatch documentation for more information.  Required.

   * - max_level ($) The maximum logging level this obejct will accept.
     See the Log::Dispatch documentation for more information.  This is not
     required.  By default the maximum is the highest possible level (which
     means functionally that the object has no maximum).

   * - stderr (0 or 1) Indicates whether or not logging information should
     go to STDERR.  If false, logging information is printed to STDOUT
     instead.  This defaults to true.

   * - callbacks( \& or [ \&, \&, ... ] ) This parameter may be a single
     subroutine reference or an array reference of subroutine references.
     These callbacks will be called in the order they are given and passed
     a hash containing the following keys:

          ( message => $log_message )

     It's a hash in case I need to add parameters in the future.

     The callbacks are expected to modify the message and then return a
     single scalar containing that modified message.  These callbacks will
     be called when either the log or `log_to' methods are called and will
     only be applied to a given message once.

   * log_message( message => $ )

     Sends a message to the appropriate output.  Generally this shouldn't
     be called directly but should be called through the `log()' method
     (in Log::Dispatch::Output).

AUTHOR
======

   Dave Rolsky, <autarch@urth.org>

SEE ALSO
========

   Log::Dispatch, Log::Dispatch::ApacheLog, Log::Dispatch::Email,
Log::Dispatch::Email::MailSend, Log::Dispatch::Email::MailSendmail,
Log::Dispatch::Email::MIMELite, Log::Dispatch::File,
Log::Dispatch::Handle, Log::Dispatch::Output, Log::Dispatch::Syslog

Object for logging to system log.
*********************************

NAME
====

   Log::Dispatch::Syslog - Object for logging to system log.

SYNOPSIS
========

     use Log::Dispatch::Syslog;

     my $file = Log::Dispatch::Syslog->new( name      => 'file1',
                                            min_level => 'info',
                                            ident     => 'Yadda yadda' );

     $file->log( level => 'emerg', message => "Time to die." );

DESCRIPTION
===========

   This module provides a simple object for sending messages to the system
log (via UNIX syslog calls).

METHODS
=======

   * new(%PARAMS)

     This method takes a hash of parameters.  The following options are
     valid:

   * - name ($) The name of the object.  Required.

   * - min_level ($) The minimum logging level this object will accept.
     See the Log::Dispatch documentation for more information.  Required.

   * - max_level ($) The maximum logging level this obejct will accept.
     See the Log::Dispatch documentation for more information.  This is not
     required.  By default the maximum is the highest possible level (which
     means functionally that the object has no maximum).

   * - ident ($) This string will be prepended to all messages in the
     system log.  Defaults to $0.

   * - logopt ($) A string containing the log options (separated by any
     separator you like).  Valid options are 'cons', 'pid', 'ndelay', and
     'nowait'.  See the openlog(3) and Sys::Syslog docs for more details.
     I would suggest not using 'cons' but instead using
     Log::Dispatch::Screen.  Defaults to ".

   * - facility ($) Specifies what type of program is doing the logging to
     the system log.  Valid options are 'auth', 'authpriv', 'cron',
     'daemon', 'kern', 'local0' through 'local7', 'mail, 'news', 'syslog',
     'user', 'uucp'.  Defaults to 'user'

   * - socket ($) Tells what type of socket to use for sending syslog
     messages.  Valid options are 'unix' or 'inet'.  Defaults to 'inet'.

   * - callbacks( \& or [ \&, \&, ... ] ) This parameter may be a single
     subroutine reference or an array reference of subroutine references.
     These callbacks will be called in the order they are given and passed
     a hash containing the following keys:

          ( message => $log_message )

     It's a hash in case I need to add parameters in the future.

     The callbacks are expected to modify the message and then return a
     single scalar containing that modified message.  These callbacks will
     be called when either the log or `log_to' methods are called and will
     only be applied to a given message once.

   * log_message( message => $ )

     Sends a message to the appropriate output.  Generally this shouldn't
     be called directly but should be called through the `log()' method
     (in Log::Dispatch::Output).

AUTHOR
======

   Dave Rolsky, <autarch@urth.org>

SEE ALSO
========

   Log::Dispatch, Log::Dispatch::ApacheLog, Log::Dispatch::Email,
Log::Dispatch::Email::MailSend, Log::Dispatch::Email::MailSendmail,
Log::Dispatch::Email::MIMELite, Log::Dispatch::File,
Log::Dispatch::Handle, Log::Dispatch::Output, Log::Dispatch::Screen

Text widget for Log::Dispatch
*****************************

NAME
====

   Log::Dispatch::TkText - Text widget for Log::Dispatch

SYNOPSIS
========

     use Tk ;
     use Log::Dispatch;
     use Log::Dispatch::TkText ;

     my $dispatch = Log::Dispatch->new;

     my $mw = MainWindow-> new ;

     my $tklog = $mw->Scrolled('LogText', name => 'tk',
                                min_level => 'debug');
     $tklog -> pack ;

     # add the logger object to $dispatch (not the widget !!)
     $dispatch->add($tklog->logger) ;

     $dispatch -> log
      (
       level => 'info',
       message => "Quaquacomekiki ? (so says Averell Dalton)"
      ) ;

DESCRIPTION
===========

   This widget provide a read-only text widget (based on Tk/ROText)
for logging through the Log/Dispatch,
module.

   Note that this widget works with a buddy Log/Dispatch/ToTk,
object which will be created by the widget's
constructor.  The reference to this buddy object must be added to the main
log dispatcher.

Filters
=======

   By clicking on <button-3> within the text widget, you get access to a
filter menu which can hide specific levels of logging.

   For instance if you text widget is cluttered with 'info' message and
you are looking for only 'error' messages, you can hide all 'info'
messages by disabling the 'info' level in the Filter menu so only the
'error' messages will be left on the screen.

   Note that the filter hides the text. They can be displaying again if
you switch back the 'info' level in the Filter menu.

METHODS
=======

   The following methods were added to the Tk/ROText,
widget:

logger()
--------

   Returns the buddy ToTk object.

log_message( level => $, message => $ )
---------------------------------------

   Sends a message if the level is greater than or equal to the object's
minimum level.

AUTHOR
======

   Dominique Dumont <Dominique_Dumont@hp.com> using Log/Dispatch,
from Dave Rolsky, <autarch@urth.org>

   Copyright (c) 2000-2001 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   See Log/Dispatch, Log/Dispatch/Email,
see Log/Dispatch/Email/MailSend,
see Log/Dispatch/Email/MailSendmail,
see Log/Dispatch/Email/MIMELite,
see Log/Dispatch/File,
Log/Dispatch/Handle,
Log/Dispatch/Screen, Log/Dispatch/Syslog,
see Log/Dispatch/ToTk,

Class to redirect Log::Dispatch to Tk widgets
*********************************************

NAME
====

   Log::Dispatch::ToTk - Class to redirect Log::Dispatch to Tk widgets

SYNOPSIS
========

     # Log::Dispatch::ToTk must be used in a composite widget

     Tk::Widget->Construct('LogText');

     sub InitObject
      {
        my ($dw,$args) = @_ ;

        # retrieve parameters specific to Log::Dispatch::*
        my %params ;
        foreach my $key (qw/name min_level max_level/)
          {
            $params{$key} = delete $args->{$key}
               if defined $args->{$key};
          }

        # create the TkTk buddy class
        $dw->{logger} = Log::Dispatch::ToTk->
          new(%params, widget => $dw) ;

     # initiaze the widget
     $dw->SUPER::InitObject($args) ;
       }

     # mandatory method in Tk widget using Log::Dispatch::ToTk
     sub logger
      {
        my $dw = shift;
        return $dw->{logger} ;
      }

   __END__

DESCRIPTION
===========

   This module is the interface class between Log/Dispatch,
and Tk widgets.  This class is derived from
Log/Dispatch/Output.

   This class must be used only by a composite widget dedicated to handle
Log::Dispatch logs.

   One ToTk object will be created for each Log::Dispatch::Tk* widget and
the user must register the ToTk object to the log dispatcher.

METHODS
=======

new(...)
--------

   Create a new ToTk object. Parameter are :

   * widget ($)

     The buddy widget object

   * name ($)

     The name of the object (not the filename!).  Required.

   * min_level ($)

     The minimum logging level this object will accept.  See the
     Log::Dispatch documentation for more information.  Required.

   * max_level ($)

     The maximum logging level this obejct will accept.  See the
     Log::Dispatch documentation for more information.  This is not
     required.  By default the maximum is the highest possible level (which
     means functionally that the object has no maximum).

log_message( level => $, message => $ )
---------------------------------------

   Sends a message if the level is greater than or equal to the object's
minimum level.

AUTHOR
======

   Dominique Dumont <Dominique_Dumont@hp.com> using Log/Dispatch,
and Log/Dispatch/Output, from
Dave Rolsky, autarch@urth.org

   Copyright (c) 2000 Dominique Dumont. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   See Log/Dispatch, Log/Dispatch/Email,
see Log/Dispatch/Email/MailSend,
see Log/Dispatch/Email/MailSendmail,
see Log/Dispatch/Email/MIMELite,
see Log/Dispatch/File,
Log/Dispatch/Handle,
Log/Dispatch/Screen, Log/Dispatch/Syslog,
see Log/Dispatch/TkText,

Log errors and error-like events
********************************

NAME
====

   Log::ErrLogger - Log errors and error-like events

SYNOPSIS
========

     use Log::ErrLogger;

     # Send e-mail for ERROR or worse
     my $mail_logger = new Log::ErrLogger::Mail(
       SENSITIVITY => Log::ErrLogger::ERROR,
       HEADERS     => { To      => "who@where.com",
     					 Subject => "Errors occurred while running $0" });

     # Log INFORMATIONAL or worse to a file
     my $file_logger = new Log::ErrLogger::File(
       FILE        => "/home/who/what.err",
       SENSITIVITY => Log::ErrLogger::INFORMATIONAL );

     # Print a nice HTML error message
     my $sub_logger  = new Log::ErrLogger::Sub (
       SENSITIVITY => FATAL,
       SUB         => sub { print STDOUT "<TITLE>Oops!</TITLE><HTML><HEAD1>Please try again later.</HEAD1></HTML>\n";
     						 exit(0); } );

     # Capture all output to STDERR as an UNEXPECTED error
     my $stderr_logger = Log::ErrLogger::tie( Log::ErrLogger::UNEXPECTED );

     # But don't actually print to STDERR
     $stderr_logger->close;

     # Log a warning
     log_error( WARNING, "Danger, %s!", "Will Robinson" );

DESCRIPTION
===========

   Log::ErrLogger provides a means of logging errors and error-like events
(such as warnings and unexpected situations) when printing to STDERR just
will not do.

   Error-like events are classified by a severity (see `ERROR SEVERITIES'
in this node below).  Programs instantiate error logging objects which can
respond differently to events.  The objects have a sensitivity - they will
respond to any event at least as severe as their sensitivity, and will
ignore any events that are less severe.

   This module instantiates new __DIE__ and __WARN__ handlers that call
log_error( FATAL, die-message) and log_error( WARNING, warn-message),
respectively.

HISTORY
=======

   $Id: ErrLogger.pm,v 1.6 1999/09/23 21:37:24 dcw Exp $

   $Log: ErrLogger.pm,v $ Revision 1.6  1999/09/23 21:37:24  dcw
Incorporated Tim Ayers <tayers@bridge.com> suggestions

   Revision 1.5  1999/09/13 17:59:48  dcw Copyright

   Revision 1.4  1999/09/13 16:37:17  dcw Documentation

   Revision 1.3  1999/09/01 14:28:28  dcw Backup file, export, autoflush

   Revision 1.2  1999/08/31 17:18:39  dcw Log::ErrLogger::Sub

   Revision 1.1  1999/08/30 21:28:43  dcw Initial

AUTHOR
======

   David C. Worenklein <dcw@gcm.com>

COPYRIGHT
=========

   Copyright 1999 Greenwich Capital Markets

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

ERROR SEVERITIES
================

   The predefined severities are

DEBUGGING
INFORMATIONAL
UNEXPECTED
WARNING
ERROR
FATAL
   They have numerical values from 1 to 6.

NON-METHOD SUBROUTINES
======================

log_error( SEVERITY, FORMAT [,LIST] )
     Log an error of the specified severity.  The text of the message is
     the output of sprintf FORMAT, ARGS.  A carriage-return (\n) will be
     appended if one is not supplied.

my $stderr_logger = tie( [SEVERITY] );
     Tie the STDERR handle to the Log::ErrLogger module, so that any
     output to STDERR will call log_error( $severity, output ).

     If $severity is not specified, it will default to INFORMATIONAL.

METHODS
=======

my $sensitivity = $logger->sensitivity;
     Returns the sensitivty of an error logger object.  Objects respond to
     events that are at least as severe as their sensitivity.  There are
     two special sensitivities.  Objects with a sensitivity of NONE do not
     respond to any events.  Objects with a sensitivity of ALL respond to
     all events.

my $old_sensitivity = $logger->sensitivity( SENSITIVITY );
     Sets the sensitivty of an error logger object.  Objects respond to
     events that are at least as severe as their sensitivity.

     Returns what the sensitivity of the object used to be.

my $fh = $logger->file_handle;
     Returns the IO::Handle associated with the error logger object.  Not
     all error loggers will have a file handle, but most will.

$logger->set_file_handle( HANDLE );
     Associates the error logger object with the given (opened)
     IO::Handle, and closes the old file handle that used to be associated
     with the object (if there was one.)

     The handle is set to autoflush, since buffering is usually a bad idea
     on error loggers.

$logger->close;
     Decommission the error logging object.  `log_error' in this node will
     no longer invoke this object.

     Note that this does NOT close the associated file handle.  However,
     if the error logging object has the only reference to the file
     handle, and the program does not have any references to the error
     logging object, the handle will have no references left and will be
     destroyed.

$logger->log( SEVERITY, MESSAGE );
     This is the method called by `log_error' in this node, above.  It
     prints

     <time>: <message>

     to the associated file handle, where <time> is the output of
     `localtime' in this node, evaluated in a scalar context.

     Additionally, if the object has a TRACE attribute that is at least as
     large as the error severity, this method will print a trace of where
     the error occurred:

     <spaces>: From <subroutine1>, at <filename1>:<line1> <spaces>: From
     <subroutine2>, at <filename2>:<line2>

     where <spaces> is the number of spaces needed to make all the colons
     line up.

CONSTRUCTORS
============

   The following erorr logging classes are provided by the module:

my $logger = new Log::ErrLogger( [parameter-hash] );
     Creates a new error logging object that uses the default `log' in
     this node given above.  The parameters that are understood are

    SENSITIVITY
          The sensitivity of the object.  Defaults to INFORMATIONAL or, in
          the perl debugger, DEBUGGING.

    TRACE
          Events that are at least as severe as the TRACE value will have
          their call stack printed.

my $logger = new Log::ErrLogger::File( [parameter-hash] );
     Creates an error logging object that logs events to a file.  In
     addition to the parameters that the Log::ErrLogger constructor takes,
     it also takes

    FILE
          Name of the file that in which to log events.  Defaults to
          /tmp/<program-base-name>.<pid>.err.  See the `set_file' in this
          node method, below, for details.

     Log::ErrLogger::File objects also provides the following methods:

    my $filename = $filelogger->filename();
          Returns the name of the file to which events are logger.

    my $old_filename = $filelogger->set_file( $new_filename [, mode [, perms]])
          Opens the given file for output and sets its FILEHANDLE to that
          file.  An ERROR event is generated if the file could not be
          opened.

          Note that the file is opened by putting a ">" at the beginning
          and creating a new IO::File object.  This means that if the
          filename given already begins with a ">", the file will be
          opened for appending.

          If the file already exists, it is renamed by appending ".bak" to
          it.  A WARNING event is generated if the file could not be
          backed up.

          Returns the old filename that errors used to be logged to.

my $logger = new Log::ErrLogger::Mail( [parameter-hash] );
     Log events by sending email to interested parties. In addition to the
     parameters that the Log::ErrLogger constructor takes, it also takes

    HEADERS
          A reference to a hash containing the headers of the e-mail, such
          as To and Subject.

     If no sufficiently severe events occur, no email is sent.  (In other
     words, you will not get a blank e-mail.)

my $logger = new Log::ErrLogger::Sub( [parameter-hash] );
     Calls a user specified subroutine every time a sufficiently severe
     events occurs.  In addition to the parameters that the Log::ErrLogger
     constructor takes, it also takes

    SUB
          A reference (regular or symbolic) to the subroutine to be
          called.  The subroutine will receive two parameters - the event
          message and the error severity.  This parameter MUST be supplied
          to the constructor.

          Note that, within this subroutine, STDERR is what you would want
          it to be, even if the program has used tie to capture STDERR.
          Thus, the subroutine does not have to worry that output to
          STDERR will cause infinite recursion.

The `Log::LogLite' class helps us create simple logs for our application.
*************************************************************************

NAME
====

   Log::LogLite - The `Log::LogLite' class helps us create simple logs for
our application.

SYNOPSIS
========

     use Log::LogLite;
     my $LOG_DIRECTORY = "/where/ever/our/log/file/should/be";
     my $ERROR_LOG_LEVEL = 6;

     # create new Log::LogLite object
     my $log = new Log::LogLite($LOG_DIRECTORY."/error.log", $ERROR_LOG_LEVEL);

     ...

     # we had an error
     $log->write("Could not open the file ".$file_name.": $!", 4);

DESCRIPTION
===========

   In order to have a log we have first to create a `Log::LogLite' object.
The c<Log::LogLite> object is created with a logging level. The default
logging level is 5. After the `Log::LogLite' object is created, each call
to the write method may write a new line in the log file. If the level of
the message is lower or equal to the logging level, the message will be
written to the log file. The format of the logging messages can be
controled by changing the template, and by defining a default message.
The log file uses the IO::LockedFile class and the Devel::DumpStack module.

CONSTRUCTOR
===========

new ( FILEPATH [,LEVEL [,DEFAULT_MESSAGE ]] )
     The constructor. FILEPATH is the path of the log file. LEVEL is the
     defined logging level - the LEVEL data member. DEFAULT_MESSAGE will
     define the DEFAULT_MESSAGE data member - a message that will be added
     to the message of each entry in the log (according to the TEMPLATE
     data member, see below).

     The levels can be any levels that the user chooses to use. There are,
     though, recommended levels:       0  the application is unusable
     1  the application is going to be unusable       2  critical
     conditions       3  error conditions       4  warning conditions
     5  normal but significant condition       6  informational       7+
     debug-level messages

     The default value of LEVEL is 5.  The default value of
     DEFAULT_MESSAGE is "".  Returns the new object.

METHODS
=======

write( MESSAGE [, LEVEL ] )
     If LEVEL is less or equal to the LEVEL data member, or if LEVEL is
     undefined, the string in MESSAGE will be written to the log file.
     Does not return anything.

level( [ LEVEL ] )
     Access method to the LEVEL data member. If LEVEL is defined, the
     LEVEL data member will get its value.  Returns the value of the LEVEL
     data member.

default_message( [ MESSAGE ] )
     Access method to the DEFAULT_MESSAGE data member. If MESSAGE is
     defined, the DEFAULT_MESSAGE data member will get its value.  Returns
     the value of the DEFAULT_MESSAGE data member.

log_line_numbers( [ BOOLEAN ] )
     If this flag is set to true, the <called_by> string will hold the file
     that calls the subroutine and the line where the call is issued. The
     default value is zero.

template( [ TEMPLATE ] )
     Access method to the TEMPLATE data member. The TEMPLATE data member
     is a string that defines how the log entries will look like. The
     default TEMPLATE is:

     '[<date>] <<level>> <called_by><default_message><message>'

     Where:

          <date>           will be replaced by a string that represent
                            the date. For example: 09/01/2000 17:00:13
          <level>          will be replaced by the level of the entry.
          <called_by>       will be replaced by a call trace string. For
                            example:
                            CGIDaemon::listen > MyCGIDaemon::accepted
          <default_message> will be replaced by the value of the
                            DEFAULT_MESSAGE data member.
          <message>         will be replaced by the message string that
                            is sent to the C<write> method.

     Returns the value of the TEMPLATE data member.

AUTHOR
======

   Rani Pinchuk, rani@cpan.org

COPYRIGHT
=========

   Copyright (c) 2001 EM-TECH (www.em-tech.net) & Rani Pinchuk.  All
rights reserved.  This package is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

SEE ALSO
========

   `Devel::DumpStack(3)' in this node, `IO::LockedFile(3)' in this node

OO interface to user defined logfile
************************************

NAME
====

   Log::Logger - OO interface to user defined logfile

SYNOPSIS
========

     use Log::Logger;

     $lh = new Log::Logger;
     $lh->open("/tmp/mylog");
     $lh->log("Log this string");
     $lh->close();

     $lh = new Log::Logger "/tmp/mylog";
     $lh->log_print("Log and print this string");
     $lh->close();

     $lh = new Log::Logger;
     $lh->open_append("/tmp/mylog");
     $lh->log("Append this string");
     $lh->fail("Append this string and die");
     # Can't close $lh, because fail exits...

DESCRIPTION
===========

   Whenever writing scripts for system management, I always find myself
wishing to keep a log of what I have done.  But typing

     print LOGHANDLE $progname . ": " . $stringToLog . "\n";

   every time gets really old.  Similarly, `die()' does not have the
facility to print to a logfile as it exits.

   A long time ago, I wrote two functions, `log()' and `fail()', to handle
this problem.  I cut and pasted them everywhere.  But now that Perl does
modules for object reuse, I have ported them to a module and added
features.

   `Log::Logger' is esentially a wrapper around an IO::File object.  The
open and open_append functions just call `IO::File->open()' with the
appropriate arguments.  The useful functionality is in the `log()',
`log_print()', and `fail()' methods.  These methods make logging what you
are doing - and printing to the user, if you like - one line of code.  eg:

     # Old way
     print STDOUT "$progName: Running /var/clean script...\n";
     print LOGHANDLE "$progName: Running /var/clean script...\n";

     # Log::Logger way
     $lh->log_print("Running /var/clean script...");

   And if you wish to log things, but also keep neat die() expressions,
you can.  eg:

     # Old way no logging
     system("foo") == 0 or die "Call to foo failed"

     # Old way, hackneyed logging
     system("foo") == 0 or do {
        print LOGHANDLE, "Call to foo failed";
        die "Call to foo failed";
     }

     # Log::Logger way
     system("foo") == 0 or $lh->fail("Call to foo failed");

   Obviously, this is not a huge difference, but in a utility where you
keep track of a lot of operations, it just is easier, and saves a little
bit of typing.  Remember, one of the fundamental qualities of a programmer
is Laziness (see the Camel book).

CONSTRUCTOR
===========

new ([ FILENAME [, APPEND ] ])
     Crates a new Log::Logger.  If it recieves an argument, that argument
     is assumed to be a filename and the Log::Logger object attempts to
     open the file for write.  If a second argument is passed and it
     evaluates to TRUE, the file is opened for append.

METHODS
=======

open ( FILENAME )
     Opens FILENAME for writing.  If this Log::Logger object already had a
     logfile open, that file will be closed before the new file is opened.

     Returns FALSE on failure.

open_append ( FILENAME )
     Opens FILENAME for append.  If this Log::Logger object already had a
     logfile open, that file will be closed before the new file is opened.

close ()
     Closes the logfile.

log ( STRING )
     Writes STRING to the logfile.  If there is no logfile open, does
     nothing, and does it quietly.

log_print ( STRING )
     Writes STRING to the logfile, printing it on STDOUT also.  If there is
     no logfile open, it just prints to STDOUT.

fail ( STRING [, RETCODE ] )
     Writes STRING to the logfile, printing it on STDOUT also.  It then
     calls exit() to exit the program.  If RETCODE is supplied, it exits
     with that return code.  Otherwise, it exits with a return code of 1.
     If no logfile is open, it prints to STDOUT only, and exits.

BUGS
====

   None that I know of, except maybe this documentation.  Probably should
have an error checking return for <new()> with arguments like there is on
open() and `open_append()'.

AUTHOR
======

   Joel Becker 	jlbec@ocala.cs.miami.edu

   Copyright (c) 1998 Joel Becker.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

VERSION
=======

   Version 1.01 (8 April 1998)

HISTORY
=======

Version 1.01
     Documentation fixes.  Man, I thought it was clean.  Oops.

Version 1.00
     Turned my `log()' and `fail()' subroutines into a proper Perl module
     (this one).  Much better than cut-and-paste.

SEE ALSO
========

   `IO::File(3)' in this node

The `Log::NullLogLite' class implements the Null Object  pattern for the `Log::LogLite' class.
**********************************************************************************************

NAME
====

   Log::NullLogLite - The `Log::NullLogLite' class implements the Null
Object pattern for the `Log::LogLite' class.

SYNOPSIS
========

     use Log::NullLogLite;

     # create new Log::NullLogLite object
     my $log = new Log::NullLogLite();

     ...

     # we had an error (this entry will not be written to the log
     # file because we use Log::NullLogLite object).
     $log->write("Could not open the file ".$file_name.": $!", 4);

DESCRIPTION
===========

   The `Log::NullLogLite' class is derived from the `Log::LogLite' class
and implement the Null Object Pattern to let us to use the `Log::LogLite'
class with null `Log::LogLite' objects.  We might want to do that if we
use a `Log::LogLite' object in our code, and we do not want always to
actually define a `Log::LogLite' object (i.e. not always we want to write
to a log file). In such a case we will create a `Log::NullLogLite' object
instead of the `Log::LogLite' object, and will use that object instead.
The object has all the methods that the `Log::LogLite' object has, but
those methods do nothing. Thus our code will continue to run without any
change, yet we will not have to define a log file path for the
`Log::LogLite' object, and no log will be created.

CONSTRUCTOR
===========

new ( FILEPATH [,LEVEL [,DEFAULT_MESSAGE ]] )
     The constructor. The parameters will not have any affect.  Returns
     the new Log::NullLogLite object.

METHODS
=======

write( MESSAGE [, LEVEL ] )
     Does nothing. The parameters will not have any affect.  Returns
     nothing.

level( [ LEVEL ] )
     Does nothing. The parameters will not have any affect.  Returns -1.

default_message( [ MESSAGE ] )
     Does nothing. The parameters will not have any affect.  Returns empty
     string ("").

AUTHOR
======

   Rani Pinchuk, rani@cpan.org

COPYRIGHT
=========

   Copyright (c) 2001 EM-TECH (www.em-tech.net) & Rani Pinchuk.  All
rights reserved.  This package is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

SEE ALSO
========

   `Log::LogLite(3)' in this node, The Null Object Pattern - Bobby Woolf -
PLoP96 - published in Pattern Languages of Program Design 3
(http://cseng.aw.com/book/0,,0201310112,00.html)

control flow of logging messages
********************************

NAME
====

   Log::Topics - control flow of logging messages

SYNOPSIS
========

     use Log::Topics qw(add_topic log_topic topics);
     add_topic $topic_name,$filehandle,$overload
     add_topic $topic_name,$filename,$overload
     log_topic $topic_name,@messages
     @topicslist=topics();

DESCRIPTION
===========

   This package provides services for controlling the output of logging
messages from an application. Log messages are identified by named topics,
and the messages for each topic can be directed or redirected to file
handles or files.

   The add_topic() function can be used to associate a named topic with a
particular file handle. If a value of 0 then logging of that particular
topic is switched off. If the file handle is not connected to a file then
it will be created and connected to a file of the same name. add_topic()
returns the name of the file handle. The third $overload parameter, if
specified and false will only set the file handle if the specified topic
is not already associated with a file handle.

   Log messages are written using the log_topic() function which takes the
topic name, and if that particular topic is enabled will print its
remaining arguments to the associated file handle. It is an error to use a
topic name that has not been declared using add_topic() first.

   The topics() function returns a list of all the current registered
topics.

   This package can usefully be used for controlling all the output of a
program, not just debugging and logging messages.

   If you have Getopt::Regex package then the following lines of code
allow the user to control the log messages from the command line using
either '-Lname=FILE' or '-Lname FILE' syntaxes.

     use Log::Topics qw(add_topic log_topic);
     use Getopt::Regex qw(GetOptions);
     GetOptions(\@ARGV,
      ['-L(.+)=(.+)',sub { add_topic $1,$2; }    ,0],
      ['-L(.+)',     sub { add_topic $1; $_[0]; },1]);

HISTORY
=======

     $Log: Topics.pm,v $
     Revision 1.5  1996/01/04 20:45:38  willijar
     Renamed module to Log::Topics, and renamed functions to more
     accurately reflect modules operation.
     Added topics() function to obtain list of available topics and removed
     internal hash variable from export list.
     Reduced to one the hash dereference in log_topic for slight efficiency
     gain.

     Revision 1.4  1995/12/17 17:16:31  willijar
     Fixed bug that crept in in non-overloading case of diagnose

     Revision 1.3  1995/12/16 11:59:19  willijar
     Removed function for reading arguments from commandline -
     use Getopt::Regex instead.
     Added ability to open files for undefined filehandles.
     Improvements to documentation
     Changed name to be closer to module guidlines.

     Revision 1.2  1995/09/20  19:11:44  willijar
     Added pod documentation and RCS control

TO DO
=====

   Could perhaps have the idea of groups of related topics which could be
set and changed together. Would this be useful?

BUGS
====

   Please let me know of any bugs.  Suggestions for improvements gladly
received.

AUTHOR
======

   John A.R. Williams, <J.A.R.Williams@aston.ac.uk>

   Thanks to Tim Bunce <Tim.Bunce@ig.co.uk> for helpful suggestions and
comments.

Perl extension for trace messages used in debugging
***************************************************

NAME
====

   Log::TraceMessages - Perl extension for trace messages used in debugging

SYNOPSIS
========

     use Log::TraceMessages qw(t d);
     $Log::TraceMessages::On = 1;
     t 'got to here';
     t 'value of $a is ' . d($a);
     {
         local $Log::TraceMessages::On = 0;
         t 'this message will not be printed';
     }

     # For a CGI program producing HTML
     $Log::TraceMessages::CGI = 1;

     # Or to turn on trace if there's a command-line argument '--trace'
     Log::TraceMessages::check_argv();

DESCRIPTION
===========

   This module is a slightly better way to put trace statements into your
code than just calling print().  It provides an easy way to turn trace on
and off for particular sections of code without having to comment out bits
of source.

USAGE
=====

$Log::TraceMessages::On
     Flag controlling whether tracing is on or off.  You can set it as you
     wish, and of course it can be local-ized.  The default is off.

$Log::TraceMessages::CGI
     Flag controlling whether the program printing trace messages is a CGI
     program (default is no).  This means that trace messages will be
     printed as HTML to stdout, so they appear in the output page.

t(messages)
     Print the given strings, if tracing is enabled.  Unless
     $Log::TraceMessages::CGI is true (see below), each message will be
     printed to standard error with a newline appended.

trace(messages)
     Synonym for t(messages).

d(scalar)
     Return a string representation of a scalar's value suitable for use in
     a trace statement.  This is just a wrapper for Data::Dumper.

     `d()' will exit with " if trace is not turned on.  This is to stop
     your program being slowed down by generating lots of strings for
     trace statements that are never printed.

dmp(scalar)
     Synonym for d(scalar).

check_argv()
     Looks at the global `@ARGV' of command-line parameters to find one
     called '-trace'.  If this is found, it will be removed from `@ARGV'
     and tracing will be turned on.  Since tracing is off by default,
     calling check_argv() is a way to make your program print trace only
     when you ask for it from the command line.

AUTHOR
======

   Ed Avis, epa98@doc.ic.ac.uk

SEE ALSO
========

   perl(1), Data::Dumper(3).

Perl extension for generating reports from logfiles
***************************************************

NAME
====

   Logfile - Perl extension for generating reports from logfiles

SYNOPSIS
========

     use Logfile::Cern;

     $l = new Logfile::Cern  File  => 'cache.log.gz',
                             Group => [Domain,File,Hour];
     $l->report(Group => File,   Sort => Records);
     $l->report(Group => Domain, Sort => Bytes);
     $l->report(Group => Hour, List => [Bytes, Records]);

     use Logfile::Wftp;

     [...]

DESCRIPTION
===========

   The Logfile extension will help you generate various reports from
different server logfiles. In general there is no restriction as to what
information you extract from the logfiles.

Reading the files
-----------------

   The package can be customized by subclassing Logfile.

   A subclass should provide a funtion next which reads the next record
from the file handle `$self->{Fh}' and returns an object of type
`Logfile::Record'. In addition a function norm may be specified to
normalize the various record fields.

   Here is a shortened version of the `Logfile::Cern' class:

     package Logfile::Cern;
     @ISA = qw ( Logfile::Base ) ;

     sub next {
         my $self = shift;
         my $fh = $self->{Fh};

     *S = $fh;
     my ($line,$host,$user,$pass,$rest,$date,$req,$code,$bytes);

     ($host,$user,$pass,$rest) = split ' ', $line, 4;
     ($rest =~ s!\[([^\]]+)\]\s*!!) && ($date = $1);
     ($rest =~ s!\"([^\"]+)\"\s*!!) && ($req = (split ' ', $1)[1]);
     ($code, $bytes) = split ' ', $rest;
     Logfile::Record->new(Host  => $host,
                          Date  => $date,
                          File  => $req,
                          Bytes => $bytes);
       }

   As stated above, in general you are free to choose the fields you enter
in the record. But:

Date
     should be a valid date string. For conversion to the seconds elapsed
     since the start of epoch the modules `GetDate' and `Date::DateParse'
     are tried. If both cannot be useed, a crude build-in module is used.

     The record constructor replaces Date by the date in `yymmdd' form to
     make it sortable. Also the field *Hour* is padded in.

Host
     Setting Host will also set field Domain by the verbose name of the
     country given by the the domain suffix of the fully qualified domain
     name (hostname.domain). `foo.bar.PG' will be mapped to `Papua New'.
     Hostnames containing no dot will be assigned to the domain *Local*.
     IP numbers will be assiged to the domain *Unresolved*. Mapping of
     short to long domain names is done in the *Net::Country* extension
     which might be usefull in other contexts:

          use Net::Country;
          $germany = Net::Country::Name('de');

Records
     is always set to 1 in the `Record' constructor. So this field gives
     the number of successful returns from the next function.

   Here is the shortened optional norm method:

     sub norm {
         my ($self, $key, $val) = @_;

     if ($key eq File) {
         $val =~ s/\?.*//;                             # remove query
         $val =~ s!%([\da-f][\da-f])!chr(hex($1))!eig; # decode escapes
     }
     $val;
       }

   The constructor reads in a logfile and builds one or more indices.

     $l = new Logfile::Cern  File => 'cache.log.gz',
                             Group => [Host,Domain,File,Hour,Date];

   There is little space but some time overhead in generating additional
indexes. If the File parameter is not given, STDIN is used. The Group
parameter may be a field name or a reference to a list of field names.
Only the field names given as constructor argument can be used for report
generation.

Report Generation
-----------------

   The Index to use for a report must be given as the Group parameter.
Output is sorted by the index field unless a Sort parameter is given. Also
the output can be truncated by a Top argument or Limit.

   The report generator lists the fields *Bytes* and Records for a given
index. The option List may be a single field name or a reference to an
array fo field names. It specifies which field should be listed in
addition to the Group field. List defaults to Records.

     $l->report(Group => Domain, List => [Bytes, Records])

   Output is sorted by the Group field unless overwritten by a Sort
option. Default sorting order is increasing for Date and *Hour* fields and
decreasing for all other Fields. The order can be reversed using the
Reverse option.

   This code

     $l->report(Group => File, Sort => Records, Top => 10);

   prints:

     File                          Records
     =====================================
     /htbin/SFgate               30 31.58%
     /freeWAIS-sf/*              22 23.16%
     /SFgate/SFgate               8  8.42%
     /SFgate/SFgate-small         7  7.37%
     /icons/*                     4  4.21%
     /~goevert                    3  3.16%
     /journals/SIGMOD             3  3.16%
     /SFgate/ciw                  2  2.11%
     /search                      1  1.05%
     /reports/96/                 1  1.05%

   Here are other examples. Also take a look at the `t/*' files.

     $l->report(Group => Domain, Sort => Bytes);

     Domain                  Records
     ===============================
     Germany               12 12.63%
     Unresolved             8  8.42%
     Israel                34 35.79%
     Denmark                4  4.21%
     Canada                 3  3.16%
     Network                6  6.32%
     US Commercial         14 14.74%
     US Educational         8  8.42%
     Hong Kong              2  2.11%
     Sweden                 2  2.11%
     Non-Profit             1  1.05%
     Local                  1  1.05%

     $l->report(Group => Hour, List => [Bytes, Records]);

     Hour            Bytes          Records
     ======================================
     07      245093 17.66%        34 35.79%
     08      438280 31.59%        19 20.00%
     09      156730 11.30%        11 11.58%
     10      255451 18.41%        16 16.84%
     11      274521 19.79%        10 10.53%
     12       17396  1.25%         5  5.26%

Report options
--------------

Group `=>' field
     Mandatory. field must be one of the fields passed to the constructor.

List `=>' field
List `=>' [field, field]
     List the subtotals for fields. Defaults to Records.

Sort `=>' field.
     Sort output by field. By default, Date and *Hour* are sorted in
     increasing order, whereas all   other fields are sorted in decreasing
     order.

Reverse `=> 1'
     Reverse sorting order.

Top `=>' number
     Print only the first number subtotals.

Limit `=>' number
     Print only the subtotals with Sort field greater than number (less
     than number if sorted in increasing order).

   Currently reports are simply printed to STDOUT.

AUTHOR
======

   Ulrich Pfeifer <`pfeifer@ls6.informatik.uni-dortmund.de'>

SEE ALSO
========

   perl(1).

Perl module for generating reports from Radius                    Accounting logfiles
*************************************************************************************

NAME
====

   Logfile::Radius - Perl module for generating reports from Radius
          Accounting logfiles

SYNOPSIS
========

     use Logfile::Radius;

DESCRIPTION
===========

   This module is a subclass of the `Logfile::Base' in this node package
by *Ulrich Pfeifer*.  A description on how to pass logfiles to this module
and generate reports is available in the Logfile package.

   This module has been written to parse *Radius Accounting* detail files.
I only have copies of those generated by the *Ascend* Radius server, so I
don't know if it is compatible with other Radius versions.

   In particular I only record Stop type records as they contain the
information that is relavent to my analysis.  This may change if enough
people want the Start records included.

DEPENDANCIES
============

   I overwrite the norm function, to avoid accepting duplicate session
ids.  This may or may not suit you.

COPYRIGHT
=========

   Copyright (c) 1997-98 Paul Gampe. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

   THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

SEE ALSO
========

   `Logfile::Base' in this node by *Ulrich Pfeifer*.

AUTHORS
=======

   Paul Gampe <paulg@twics.com>

Perl module to rotate logfiles.
*******************************

NAME
====

   Logfile::Rotate - Perl module to rotate logfiles.

SYNOPSIS
========

     use Logfile::Rotate;
     my $log = new Logfile::Rotate( File   => '/var/adm/syslog/syslog.log',
                                    Count  => 7,
                                    Gzip  => 'lib',
                                    Post   => sub{
                                      open(IN, "/var/run/syslog.pid");
                                      kill("HUP", chomp(<IN>)); }
                                    Dir    => '/var/log/old',
                                    Flock	 => 'yes',
                                    Persist => 'yes',
                                  );

     # process log file

     $log->rotate();

     or

     my $log = new Logfile::Rotate( File  => '/var/adm/syslog',
                                    Gzip   => '/usr/local/bin/gzip');

     # process log file

     $log->rotate();
     undef $log;

DESCRIPTION
===========

   I have used the name space of `Logfile::Base' in this node package by
*Ulrich Pfeifer*, as the use of this module closely relates to the
processing logfiles.

new
     new accepts the following arguments, File, Count, `Gzip', `Pre',
     `Post', `Flock' and Dir with only File being mandatory.  new will
     open and lock the file, so you may co-ordinate the processing of the
     file with rotating it.  The file is closed and unlocked when the
     object is destroyed, so you can do this explicitly by undef'ing the
     object.

     The `Pre'/`Post' arguments allow you to pass function references to
     this method, which you may use as a callback for any processing you
     want before or after the rotation. For example, you may notify the
     process writing to the file that it has been rotated.

     The `Pre' function is passed the current filename to be rotated as an
     argument and the `Post' function is passed the current filename that
     was rotated and that file's new filename including any extension added
     by compression previously.

     Both the `Pre' and `Post' function references you provide are executed
     within an eval statement inside the rotate method.  If the eval
     returns an error then the rotate method will croak at that point.

     The Signal argument is deprecated by the `Post' argument.

     The `Flock' argument allows you to specify whether the perl function
     flock is used to lock the file during the rotation operation.
     Apparently flock causes problems on some platforms and this option has
     been added to allow you to control the programs behaviour.  By default
     the file will be locked using flock.

     The `Persist' argument allows you to control whether the program will
     try and set the current log file ownership and permissions on any new
     files that may be created by the rotation.  In some circumstances the
     program doing the file rotation may not have sufficient permission to
     chown on the file.  By default the program will try and preserve
     ownership and permissions.

rotate()
     This method will copy the file passed in new to a file of the same
     name, with a numeric extension and truncate the original file to zero
     length.  The numeric extension will range from 1 up to the value
     specified by Count, or 7 if none is defined, with 1 being the most
     recent file.  When Count is reached, the older file is discarded in a
     FIFO (first in, first out) fashion. If the argument Dir was given,
     all old files will be placed in the specified directory.

     The `Post' function is the last step executed by the rotate method so
     the return code of rotate will be the return code of the function you
     proved, or 1 by default.

     The copy function is implemented by using the File/Copy,
     package, but I have had a few people suggest that they
     would prefer `File::Move' in this node.  I'm still not decided on
     this as you would loose data if the move should fail.

Optional Compression
--------------------

   If available rotate will also compress the file with the `gzip' in this
node program or the program passed as the `Gzip' argument.

   You may now also use lib as a value for the `Gzip' argument.  This
directs the program to load the `Compress::Zlib' module, if available and
use it do the compression within perl.  *This avoids the security issues
associated with spawning external programs and is the recommended value
for this option.*

   If no argument is defined it will first check to see if the
`Compress::Zlib' module can be loaded then check the perl Config,
to determine if gzip is available on your system. In this case the
`gzip' in this node must be in your current path to succeed, and accept
the -f option.

   See the `"WARNING"' in this node section below.

Optional Relocation Directory
-----------------------------

   If you specify an argument for Dir then the file being rotated will be
relocated to the directory specified.  Along with any other files that may
have been rotated previously.  If the directory name specified does not
exist then it will be created with `0750' permissions.  If you wish to
have other permissions on the directory then I would recommend you create
the directory before using this module.

   See the `"WARNING"' in this node section below.

WARNING
=======

   If a system call is made to `gzip' this makes this module vulnerable to
security problems if a rogue gzip is in your path or `gzip' has been
sabotaged.  For this reason a STRONGLY RECOMMEND you DO NOT use this
module while you are ROOT.

   For a more secure alternative install the `Compress::Zlib' module and
use the lib value for the `Gzip' argument.

   If you specify an argument for Dir and the directory name you pass does
not exist, this module *will create* the directory with permissions `0750'.

DEPENDANCIES
============

   See File/Copy.

   If `Gzip' is being used it must create files with an extension of `.gz'
for the file to be picked by the rotate cycle.

COPYRIGHT
=========

   Copyright (c) 1997-99 Paul Gampe. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

   IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

   THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS
PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO
OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.

SEE ALSO
========

   See File/Copy, `Logfile::Base' in this node, `flock' in
this node Changes file for change history and credits for contributions.

RETURN
======

   All functions return 1 on success, 0 on failure.

AUTHOR
======

   Paul Gampe <paulg@apnic.net>

Perl extension to manipulate MAchine Readable Cataloging records.
*****************************************************************

NAME
====

   MARC.pm - Perl extension to manipulate MAchine Readable Cataloging
records.

SYNOPSIS
========

     use MARC;

     # constructors
       $x=MARC->new();
       $x=MARC->new("filename","fileformat");
       $x->openmarc({file=>"makrbrkr.mrc",'format'=>"marcmaker",
     	increment=>"5", lineterm=>"\n",
     	charset=>\%char_hash});
       $record_num=$x->createrecord({leader=>"00000nmm  2200000 a 4500"});

     # input/output operations
       $y=$x->nextmarc(10);			# increment
       $x->closemarc();
       print $x->marc_count();
       $x->deletemarc({record=>'2',field=>'110'});
       $y=$x->selectmarc(['4','21-50','60']);

     # character translation
       my %inc = %{$x->usmarc_default()};	# MARCMaker input charset
       my %outc = %{$x->ustext_default()};	# MARCBreaker output charset

     # data queries
       @records = $x->searchmarc({field=>"245"});
       @records = $x->searchmarc({field=>"260",subfield=>"c",
     		     regex=>"/19../"});
       @records = $x->searchmarc({field=>"245",notregex=>"/huckleberry/i"});
       @results = $x->getvalue({record=>'12',field=>'856',subfield=>'u'});

     # header and control field operations
       $rldr = $x->unpack_ldr($record);
       print "Desc is $rldr->{Desc}";
       next if ($x->bib_format($record) eq 'SERIALS');
       $rff = $x->unpack_008($record);
       last if ($rff->{'Date1'}=~/00/ or $rff->{'Date2'}=~/00/);

     # data modifications
       $x->addfield({record=>"2", field=>"245",
     	i1=>"1", i2=>"4", ordered=>'y', value=>
     	[a=>"The adventures of Huckleberry Finn /",
                      c=>"Mark Twain ; illustrated by E.W. Kemble."]});

     my $update245 = {field=>'245',record=>2,ordered=>'y'};
     my @u245 = $x->getupdate($update245);
     $x->deletemarc($update245);
     $x->addfield($update245, @u245_modified);

     	# outputs
     $y = $x->output({'format'=>"marcmaker", charset=>\%outc});
     $x->output({file=>">>my_text.txt",'format'=>"ascii",record=>2});
     $x->output({file=>">my_marcmaker.mkr",'format'=>"marcmaker",
     	      nolinebreak=>'y',lineterm=>'\n'});
     $x->output({file=>">titles.html",'format'=>"html", 245=>"Title: "});

     # manipulation of individual marc records.
       @recs = $x[1..$#$x];
       grep {$_->unpack_ldr() && 0} @recs;
       @LCs = grep {$_->unp_ldr{Desc} eq 'a' &&
     	       $_->getvalue({field=>'040'}) =~/DLC\c_.DLC/} @recs;
       foreach my $rec (@LCs) {
     	  print $rec->output({format=>'usmarc'});
       }

     # manipulation as strings.
       foreach my $rec (@LCs) {
     	  my $stringvar = $rec->as_string();
     	  $stringvar=~s[^(
     			  100\s # main entries of this stripe..
     			  ..\s # (don't care about indicators)
     			  \c_.\s*
     			  )(\S) # take the first letter..
     			] [
     			${1}uc($2) # and upcase it. All authors have
     				   # upcase first letters in my library.
     			]xm; # x means 'ignore whitespace and allow
     			     # embedded comments'.
     	 $rec->from_string($stringvar);
     	 my ($i2,$article) = $stringvar =~/245 .(.) \c_.(.{0,9})/;
     	 $article = substr($article,0,$i2) if $i2=~/\d/;
     	 print "article $article is not common" unless $COMMON_ARTS{$article};
       }

DESCRIPTION
===========

   MARC.pm is a Perl 5 module for reading in, manipulating, and outputting
bibliographic records in the *USMARC* format. You will need to have Perl
5.004 or greater for MARC.pm to work properly. Since it is a Perl module
you use MARC.pm from one of your own Perl scripts. To see what sorts of
conversions are possible you can try out a web interface to MARC.pm which
will allow you to upload MARC files and retrieve the results (for details
see the section below entitled "Web Interface").

   However, to get the full functionality you will probably want to
install MARC.pm on your server or PC. MARC.pm can handle both single and
batches of MARC  records. The limit on the number of records in a batch is
determined by the memory capacity of the machine you are running. If
memory is an issue for you MARC.pm will allow you to read in records from
a batch gradually. MARC.pm also includes a variety of tools for searching,
removing, and even creating records from scratch.

Types of Conversions:
---------------------

   * MARC -> ASCII : separates the MARC fields out into separate lines

   * MARC <-> MARCMaker : The MARCMaker format is a format that was
     developed by the *Library of Congress* for use with their DOS based
     *MARCMaker* and *MARCBreaker* utilities. This format is particularly
     useful for making global changes (ie. with a text editor's search and
     replace) and then converting back to MARC (MARC.pm will read properly
     formatted MARCMaker records). For more information about the
     MARCMaker format see http://lcweb.loc.gov/marc/marcsoft.html

   * MARC -> HTML : The MARC to HTML conversion creates an HTML file from
     the fields and field labels that you supply. You could possibly use
     this to create HTML bibliographies from a batch of MARC records.

   * MARC <-> XML : XML support is handled by MARC::XML which is a
     subclass of MARC.pm and is also available for download from the CPAN.

   * MARC -> URLS : This conversion will extract URLs from a batch of MARC
     records. The URLs are found in the 856 field, subfield u. The HTML
     page that is generated can then be used with link-checking software
     to determine which URLs need to be repaired. Hopefully library system
     vendors will soon support this activity soon and make this conversion
     unecessary!

Downloading and Installing
--------------------------

Download
     The module is provided in standard CPAN distribution format. It will
     extract into a directory MARC-version with any necessary
     subdirectories.  Change into the MARC top directory. Download the
     latest version from http://www.cpan.org/modules/by-module/MARC/

Unix
          perl Makefile.PL
          make
          make test
          make install

Win9x/WinNT/Win2000
          perl Makefile.PL
          perl test.pl
          perl install.pl

Test
     Once you have installed, you can check if Perl can find it. Change to
     some other directory and execute from the command line:

          perl -e "use MARC"

     If you do not get any response that means everything is OK! If you
     get an error like *Can't locate method "use" via package MARC*.  then
     Perl is not able to find MARC.pm-double check that the file copied it
     into the right place during the install.

Todo
----

   * Support for other MARC formats (UKMARC, FINMARC, etc).

   * Create a map and instructions for using and extending the MARC.pm data
     structure.

   * Develop better error catching mechanisms.

   * Support for MARC <-> Unicode character conversions.

   * MARC <-> EAD (Encoded Archival Description) conversion?

   * MARC <-> DC/RDF (Dublin Core Metadata encoded in the Resource
     Description Framework)?

Web Interface
-------------

   A web interface to MARC.pm is available at
http://marcpm.sourceforge.net/cgi-bin/converter.cgi where you can upload
records and observe the results. If you'd like to check out the cgi script
take a look at
http://marcpm.sourceforge.net/documentation/marcpm/converter.txt However,
to get the full functionality you will want to install MARC.pm on your
server or PC.

Option Templates
----------------

   A MARC record is a complex structure. Hence, most of the methods have a
number of options. Since a series of operations frequently uses many the
same options for each method, you can create a single variable that forms
a "template" for the desired options. The variable points to a hash - and
the hash keys have been selected so the same hash works for all of the
related methods.

     my $loc852 = {record=>1, field=>'852', ordered=>'y'};
     my ($found) = $x->searchmarc($loc852);
     if (defined $found) {
         my @m852 = $x->getupdate($loc852);
         $x->deletemarc($loc852);
             # change @m852 as desired
         $x->updaterecord($loc852, @m852fix);
     }
     else {
         $x->addfield($loc852, @m852new);
     }

   The following methods are specifically designed to work together using
Option Templates. The required options are shown as bold. Any `(default)'
options are shown in parentheses. Although deletemarc() permits an array
for the record option, a single record should be used in a Template. The
*subfield* option must not be used in a Template that uses both
*deletemarc* and one of the methods that acts on a complete field like
addfield(). The value option must not be used with updaterecord().

   deletemarc()    - field (all), record (all), subfield [supplemental]

   searchmarc()    - field, regex, notregex, subfield [supplemental]

   getvalue()      - record, field, subfield, delimiter [supplemental]

   getfirstvalue() - record, field, subfield, delimiter [supplemental]

   getupdate()     - record, field

   getfields()     - record, field

   addfield()      - record, field, i1 (' '), i2 (' '), value, ordered
('y')

   updaterecord()  - record, field, i1 (' '), i2 (' '), ordered ('y')

   updatefields()  - record, field

   deletefirst()   - record, field, subfield

   updatefirst()   - record, field, subfield, i1,i2

   Methods that accept a *subfield* option also accept specifying it as a
supplemental parameter. (Deletefirst and updatefirst are the only
exceptions).  Supplemental parameters append/overwrite the hash values
specified in the template.

     $x->deletemarc($loc852, 'subfield','k');

     my $f260 = {field=>"260",regex=>"/19../"};
     my @records=$x->searchmarc($f260,'subfield','c');
     foreach $found (@records) {
         $value = $x->getvalue($f260,'record',"$found",'field',"245");
         print "TITLE: $value\n";
     }

METHODS
=======

   Here is a list of the methods in MARC.pm that are available to you for
reading in, manipulating and outputting MARC data.

new()
-----

   Creates a new MARC object.

     $x = MARC->new();

   You can also use the optional file and format parameters to create and
populate the object with data from a file. If a file is specified it will
read in the entire file. If you wish to read in only portions of the file
see openmarc(), nextmarc(), and closemarc() below. The format defaults to
`'usmarc'' if not specified. It is only used when a file is given.

     $x = MARC->new("mymarc.dat","usmarc");
     $x = MARC->new("mymarcmaker.mkr","marcmaker");

   Creates a new MARC::Rec object.

     $rec=MARC::Rec->new();
     $rec=MARC::Rec->new($filehandle,"usmarc");

   MARC::Rec objects are typically created by reading from a filehandle
using nextrec() and a proto MARC::Rec object or by directly stuffing the
@{$rec->{'array'}} array.

openmarc()
----------

   Opens a specified file for reading data into a MARC object. If no
format is specified openmarc() will default to USMARC. The *increment*
parameter defines how many records you would like to read from the file.
If no *increment* is defined then the file will just be opened, and no
records will be read in. If *increment* is set to -1 then the entire file
will be read in.

     $x = new MARC;
     $x->openmarc({file=>"mymarc.dat",'format'=>"usmarc",
     		  increment=>"1"});
     $x->openmarc({file=>"mymarcmaker.mkr",'format'=>"marcmaker",
     		  increment=>"5"});

   note: openmarc() will return the number of records read in. If the file
opens successfully, but no records are read, it returns `"0 but true"'.
For example:

     $y=$x->openmarc({file=>"mymarc.dat",'format'=>"usmarc",
     		     increment=>"5"});
     print "Read in $y records!";

   When the *MARCMaker* format is specified, the lineterm parameter can be
used to override the CRLF line-ending default (the format was originally
released for MS-DOS). A charset parameter accepts a hash-reference to a
user supplied character translation table. The "usmarc.txt" table supplied
with the LoC. MARCMaker utility is used internally as the default. You can
use the *usmarc_default* method to get a hash-reference to it if you only
want to modify a couple of characters. See example below.

     $x->openmarc({file=>"makrbrkr.mrc",'format'=>"marcmaker",
     		  increment=>"5",lineterm=>"\n",
     		  charset=>\%char_hash});

   openmarc inherits some error checking sanity checks from
MARC::Rec::nextrec.  These will lead it to return the negative of the
number of records read in if there is a header length error. This behavior
can be suppressed with an option:

     $x->openmarc({file=>"mymarc.dat", format=>"usmarc",
     		  increment=> 1, strict => 0});

nextmarc()
----------

   Once a file is open nextmarc() can be used to read in the next group of
records. The increment can be passed to change the number of records read
in if necessary. An increment of -1 will read in the rest of the file.
Specifying the increment will change the value set with openmarc().
Otherwise, that value is the default.

     $x->nextmarc();
     $x->nextmarc(10);
     $x->nextmarc(-1);

   note: Similar to openmarc(), nextmarc() will return the number of
records read in.

     $y=$x->nextmarc();
     print "$y more records read in!";

nextrec()
---------

   MARC:Rec instances can read from a filehandle and produce a new
MARC::Rec instance.  If nextrec is passed a string, it will read from that
instead. The string should be formatted according to the {format} field of
the instance.

   Cases where a new instance cannot be created are classified by a status
value:

     my ($newrec,$status) = $rec->nextrec();

   $status is undefined if we are at the end of the filehandle. If the
data read from the filehandle cannot be made into a marc record, $status
will be negative.  For example, $status is -1 if there is a distinction
between recsize and leader definition of recsize, and -2 if the leader is
not numeric.

   An idiom for reading records incrementally with MARC::Recs is:

     my $proto=MARC::Rec->new($filehandle,$format);
     while (1) {
     	  my ($rec,$status)=$proto->nextrec();
     	  last unless $status;
     	  die "Bad record, bad, bad record: error $status"
     	      if $status <0;
     	  print $rec->output({$format=>'ascii'});
     	  # or replace print and output with your own functions/methods.
     }
     close $filehandle or die "File $filehandle is not happy on close\n";

   If you are getting records from an external source as strings, the
idiom is:

     my $proto=MARC::Rec->new($filehandle,$format);
     while (1) {
           my $string = get_external_marc();
           last unless $string;
           my ($rec,$status)=$proto->nextrec($string);
           last unless $status;
           die "Bad record, bad, bad record: error $status"
               if $status <0;
           print $rec->output({$format=>'ascii'});
           # or replace print and output with your own functions/methods.
     }

closemarc()
-----------

   If you are finished reading in records from a file you should close it
immediately.

     $x->closemarc();

add_map()
---------

   add_map() takes a recnum and a ref to a field in ($tag,
$i1,$i2,a=>"bar",...) or ($tag, $field) formats and will append to the
various indices that we have hanging off that record.  It is intended for
use in creating records de novo and as a component for rebuild_map(). It
carefully does not copy subfield values or entire fields, maintaining some
reference relationships.  What this means for indices created with add_map
that you can directly edit subfield values in $marc->[recnum]{array} and
the index will adjust automatically. Vice-versa, if you edit subfield
values in $marc->{recnum}{tag}{subfield_code} the fields in
$marc->[recnum]{array} will adjust. If you change structural information
in the array with such an index, you must rebuild the part of the index
related to the current tag (and possibly the old tag if you change the
tag).

     use MARC 1.02;
     while (<>) {
          chomp;
          my ($author,$title) = split(/\t/);
          my $rnum = $x->createrecord({leader=>
     			    	       "00000nmm  2200000 a 4500"});

     my @auth = (100, ' ', ' ', a=>$author);
     my @title = (245, ' ', ' ', a=>$title);
     push @{$x->[$rnum]{array}}, \@auth;
     $x->add_map($rnum,\@auth);
     push @{$x->[$rnum]{array}}, \@title;
     $x->add_map($rnum,\@title);
        }

   MARC::Rec::add_map($rfield) does not need the record specification and
has the same effect as add_map.

rebuild_map
-----------

   rebuild_map takes a recnum and a tag and will synchronize the index with
the array elements of the marc record at the recnum with that tag.

     #Gonna change all 099's to 092's since this is a music collection.
     grep {$->[0] =~s/099/092} @{$x->[$recnum]{array}};

     #Oops, now the index is out of date on the 099's...
     $x->rebuild_map($recnum,099);
     #... and the 092's since we now have new ones.
     $x->rebuild_map($recnum,092);
     #All fixed.

   MARC::Rec::rebuild_map($tag) does not need the record number and has
the same effect as rebuild_map.

rebuild_map_all
---------------

   rebuild_map takes a recnum and will synchronize the index with the
array elements of the marc record at the recnum.

   MARC::Rec::rebuild_map_all() does not need the record number and has
the same effect as rebuild_map_all.

getfields
---------

   getfields takes a template and returns an array of fieldrefs from the
record number implied by that template. The fields referred are fields
from the $marc->[$recnum]{array} group. The fields are all fields from the
first one with the tag from the template to the last with that tag. Some
marc records (e.g. cjk) may have fields with other tags mixed in.
Consecutive calls to updatefields with a different tag and the same record
are probably a bad idea unless you have assurance that fields with the
same tag are always together.

   MARC::Rec::getfields is identical to getfields, but ignores any record
specification in the template.

marc_count()
------------

   Returns the total number of records in a MARC object. This method was
previously named length(), but that conflicts with the Perl built-in of
the same name. Use the new name, the old one is deprecated and will
disappear shortly.

     $length=$x->marc_count();

getfirstvalue()
---------------

   getfirstvalue will return the first value of a field or subfield or
indicator or i12 in a particular record found in the MARC object. It does
not depend on the index being up to date.

   MARC::Rec::getfirstvalue is identical to getfirstvalue, but ignores any
record specification in the template.

getvalue()
----------

   This method will retrieve MARC field data from a specific record in the
MARC object. getvalue() takes four parameters: record, field, *subfield*,
and delimiter. Since a single MARC record could contain several of the
fields or subfields the results are returned to you as an array. If you
only pass record and field you will be returned the entire field without
subfield delimiters. Optionally you can use delimiter to specify what
character to use for the delimiter, and you will also get the subfield
delimiters. If you also specify *subfield* your results will be limited to
just the contents of that subfield. Repeated subfield occurances will end
up in separate array elements in the order in which they were read in. The
*subfield* designations `'i1', 'i2' and 'i12'' can be used to get
indicator(s).

     #get the 650 field(s)
         @results = $x->getvalue({record=>'1',field=>'650'});

     #get the 650 field(s) with subfield delimiters (ie. |x |v etc)
         @results = $x->getvalue({record=>'1',field=>'650',delimiter=>'|'});

     #get all of the subfield u's from the 856 field
         @results = $x->getvalue({record=>'12',field=>'856',subfield=>'u'});

   MARC::Rec::getvalue($template) is identical to getvalue, but ignores
any record specification.

unpack_ldr($record)
-------------------

   Returns a ref to a hash version of the record'th LDR.  Installs the ref
in $marc as $marc->[$record]{unp_ldr}

     my $rldr = $x->unpack_ldr(1);
     print "Desc is $rldr{Desc}";
     my ($m040) = $x->getvalues({record=>'1',field=>'040'});
     print "First record is LC, let's leave it alone"
           if $rldr->{'Desc'} eq 'a' && $m040=~/DLC\s*\c_c\s*DLC/;

   The hash version contains the following information:

     Key		000-Pos	length	Function [standard value]
     ---     	-------	------	--------
     rec_len		00-04	   5	Logical Record Length
     RecStat		05	   1	Record Status
     Type		06	   1	Type of Record
     BLvl		07	   1	Bibliographic Level
     Ctrl		08	   1
     Undefldr	09-11	   3	[x22]
     base_addr	12-16	   5	Base Address of Data
     ELvl		17	   1	Encoding Level
     Desc		18	   1	Descriptive Cataloging Form
     ln_rec		19	   1	Linked-Record Code
     len_len_field	20	   1	Length "length of field" [4]
     len_start_char	21	   1	Length "start char pos" [5]
     len_impl	22	   1	Length "implementation dep" [0]
     Undef2ldr	23	   1	[0]

   MARC::Rec::unpack_ldr() is identical to unpack_ldr, but does not need
the record number.

get_hash_ldr($record)
---------------------

   Takes a record number. Returns a ref to the cached version of the hash
ldr if it exists.  Does this *without* overwriting the hash ldr. Allows
external code to safely manipulate hash versions of the ldr.

     my $rhldr = $marc->get_hash_ldr($record);
     return undef unless $rhldr;
     $rhldr->{'Desc'} =~ s/a/b/;
     $ldr = $x->pack_ldr($record);

   MARC::Rec::get_hash_ldr() is identical to get_hash_ldr, but does not
need the record number.

pack_ldr($record)
-----------------

   Takes a record number. Updates the appropriate ldr.

     $marc->[$record]{'unp_ldr'}{'Desc'} =~ s/a/b/;
     my $ldr = $x->pack_ldr($record);
     return undef unless $ldr;

   MARC::Rec::pack_ldr() is identical to pack_ldr, but does not need the
record number.

bib_format($record)
-------------------

   Takes a record number. Returns the "format" used in determining the
meanings of the fixed fields in 008. Will force update of the ldr based on
any existing hash version.

     foreach $record (1..$#$x) {
     	    next if $x->bib_format($record) eq 'SERIALS';
     		# serials are hard
     	    do_something($x->[record]);
     }

   MARC::Rec::bib_format() is identical to bib_format, but does not need
the record number.

unpack_008($record)
-------------------

   Returns a ref to hash version of the 008 field, based on the field's
value.  Installs the ref as $marc->[$record]{unp_008}

     foreach $record (1..$#$x) {
     	    my $rff = $x->unpack_008($record);
     	    print "Record $record: Y2K problem possible"
     		if ($rff->{'Date1'}=~/00/ or $rff->{'Date2'}=~/00/);
     }

   MARC::Rec::unpack_008() is identical to unpack_008, but does not need
the record number.

get_hash_008($record)
---------------------

   Takes a record number. Returns a ref to the cached version of the hash
008 if it exists.  Does this *without* overwriting the hash 008. Allows
external code to safely manipulate hash versions of the 008.

     my $rh008 = $marc->get_hash_008($record);
     return undef unless $rh008;
     $rh008->{'Date1'} =~ s/00/01/;
     my $m008 = $x->pack_008($record);
     return undef unless $m008;

   MARC::Rec::get_hash_008() is identical to get_hash_008, but does not
need the record number.

pack_008($record)
-----------------

   Takes a record number and updates the appropriate 008. Will force
update of the ldr based on any existing hash version. Updates the map for
008.

     foreach $record (1..$#$x) {
     	    my $rff = $x->unpack_008($record);
     	    $rff->{'Date1'}='2000';
     	    print "Record:$record Y2K problem created\n";
     	    $x->pack_008($record);
     	    # New value is in the 008 field of $record'th marc
     }

   MARC::Rec::pack_008() is identical to pack_008, but does not need the
record number.

deletefirst()
-------------

   deletefirst() takes a template. It deletes the field data for a first
match, using the template and leaves the rest alone.

   For example, assume that we have a marc file whose second record looks
like:

     =008  960221s1955\\\\dcuabcdjdbkoqu001\0dspa\d
     =020  \\$a0777000008 :$c{24}35.99
     =020  \\$a0777000008 :$c{curren}35.99
     =040  \\$aViArRB$cViArRB
     =100  2 $aDeer-Doe, Jane,$d1957-

   Assume we have placed this in a MARC object x. Then we can delete an
entire field of the second record thus:

     my $loc100 = {record=>2,field=>100,rebuild_map=>1};
     $x->deletefirst($loc100);

   The second record now looks like:

     =008  960221s1955\\\\dcuabcdjdbkoqu001\0dspa\d
     =020  \\$a0777000008 :$c{24}35.99
     =020  \\$a0777000008 :$c{curren}35.99
     =040  \\$aViArRB$cViArRB

   If the template has a subfield element it deletes based on the subfield
information in the template.

     $x->deletefirst({record=>2,field=>020,subfield=>'c',rebuild_map=>1};

     =008  960221s1955\\\\dcuabcdjdbkoqu001\0dspa\d
     =020  \\$a0777000008 :
     =020  \\$a0777000008 :$c{curren}35.99
     =040  \\$aViArRB$cViArRB

     If the last subfield of a field is deleted,
     deletefirst() also deletes the field.

     $x->deletefirst({record=>2,field=>020,subfield=>'a',rebuild_map=>1};

     =008  960221s1955\\\\dcuabcdjdbkoqu001\0dspa\d
     =020  \\$a0777000008 :$c{curren}35.99
     =040  \\$aViArRB$cViArRB

     It complains about attempts to
     delete indicators.

     $x->deletefirst({record=>2,field=>020,subfield=>'i1',rebuild_map=>1};
     OR
     $x->deletefirst({record=>2,field=>020,i1=>1,rebuild_map=>1};

   Produces a warning and leaves the record untouched.

     If there is no match, it does nothing.

     $x->deletefirst({record=>2,field=>020,subfield=>'x',rebuild_map=>1};

     =008  960221s1955\\\\dcuabcdjdbkoqu001\0dspa\d
     =020  \\$a0777000008 :$c{curren}35.99
     =040  \\$aViArRB$cViArRB

     Deletefirst also rebuilds the map if the template asks for that
     $do_rebuild_map. Deletefirst returns the number of matches deleted
     (that would be 0 or 1), or undef if it feels grumpy (i.e. carps).

   MARC::Rec::deletefirst($template) is identical to deletefirst, but
ignores any record number specified by $template.

   Most use of deletefirst is expected to be by Tie::MARC.

deletemarc()
------------

   This method will allow you to remove a specific record, fields or
subfields from a MARC object. Accepted parameters include: record, field
and *subfield*. Note: you can use the .. operator to delete a range of
records. deletemarc() will return the number of items deleted (be they
records, fields or subfields). The record parameter is optional. It
defaults to all user records [1..$#marc] if not specified.

     #delete all the records in the object
         $x->deletemarc();

     #delete records 1-5 and 7
         $x->deletemarc({record=>[1..5,7]});

     #delete all of the 650 fields from all of the records
         $x->deletemarc({field=>'650'});

     #delete the 110 field in record 2
         $x->deletemarc({record=>'2',field=>'110'});

     #delete all of the subfield h's in the 245 fields
         $x->deletemarc({field=>'245',subfield=>'h'});

updatefirst()
-------------

   updatefirst() takes a template, and an array from
$marc->[recnum]{array}. It replaces/creates the field data for a first
match, using the template and the array, and leaves the rest alone. If the
template has a subfield element, (this includes indicators) it ignores all
other information in the array and only updates/creates based on the
subfield information in the array. If the template has no subfield
information then indicators are left untouched unless a new field needs to
be created, in which case they are left blank.

   MARC::Rec::updatefirst($template) is identical to deletefirst, but
ignores any record number specified by $template.

   Most use of updatefirst() is expected to be from Tie::MARC.  It does
not currently provide a useful return value.

updatefields()
--------------

   updatefields() takes a template which specifies recnum, a
$do_rebuild_map and a field (needs the field in case $rafields->[0] is
empty). It also takes a ref to an array of fieldrefs formatted like the
output of getfields(), and replaces/creates the field data. It assumes
that it should replace the fields with the first tag in the fieldrefs. It
calls rebuild_map() if $do_rebuild_map.

     #Let's kill the *last* 500 field.
     my $loc500 = {record=>1,field=>500,rebuild_map=>1};
     my @rfields = $x->getfields($loc500);
     pop @rfields;
     $x->updatefields($loc500,\@rfields);

getmatch()
----------

   getmatch() takes a subfield code (can be an indicator) and a fieldref.
Returns 0 or a ref to the value to be updated.

   #Let's update the value of i2 for the *last* 500     my $loc500 =
{record=>1,field=>500,rebuild_map=>1};     my @rfields =
$x->getfields($loc500);     my $rvictim = pop @rfields;     my $rval =
getmatch('i2',$rvictim);     $$rval = "4" if $rval;

   MARC::Rec::getmatch($subf,$rfield) is identical to getmatch.

insertpos()
-----------

   insertpos() takes a subfield code (can not be an indicator), a value,
and a fieldref. Updates the fieldref with the first place that the
fieldref can match. Assumes there is no exact subfield match in $fieldref.

     #Let's update the value of subfield 'a' for the *last* 500
     my $value = "new info";
     my $loc500 = {record=>1,field=>500,rebuild_map=>1};
     my @rfields = $x->getfields($loc500);
     my $rvictim = pop @rfields;
     my $rval = getmatch('a',$rvictim);
     if ($rval) {
         $$rval = $value ;
     } else {
     	$x->insertpos('a',$value,$rvictim);
     }

   MARC::Rec::insertpos($subf,$value,$rfield) is identical to insertpos;

selectmarc()
------------

   This method will select specific records from a MARC object and delete
the rest. You can specify both individual records and ranges of records in
the same way as deletemarc(). selectmarc() will also return the number of
records deleted.

     $x->selectmarc(['3']);
     $y=$x->selectmarc(['4','21-50','60']);
     print "$y records selected!";

searchmarc()
------------

   This method will allow you to search through a MARC object, and
retrieve record numbers for records that matched your criteria. You can
search for: 1) records that contain a particular field, or field and
subfield ; 2) records that have fields or subfields that match a regular
expression ; 3) and records that have fields or subfields that *do not*
match a regular expression. The record numbers are returned to you in an
array which you can then use with deletemarc(), selectmarc() and output()
if you want.

   * 1) Field/Subfield Presence:

          @records=$x->searchmarc({field=>"245"});
          @records=$x->searchmarc({field=>"245",subfield=>"a"});

   * 2) Field/Subfield Match:

          @records=$x->searchmarc({field=>"245",
          			     regex=>"/huckleberry/i"});
          @records=$x->searchmarc({field=>"260",subfield=>"c",
          			     regex=>"/19../"});

   * 3) Field/Subfield NotMatch:

          @records=$x->searchmarc({field=>"245",
          			     notregex=>"/huckleberry/i"});
          @records=$x->searchmarc({field=>"260",
          			     subfield=>"c",notregex=>"/19../"});

createrecord()
--------------

   You can use this method to initialize a new record. It only takes one
optional parameter, *leader* which sets the 24 characters in the record
leader: see http://lcweb.loc.gov/marc/bibliographic/ecbdhome.html for more
details on the leader. Note: you do not need to pass character positions
00-04 or 12-16 since these are calculated by MARC.pm if outputting to MARC
you can assign 0 to each position. If no leader is passed a default USMARC
leader will be created of "00000nam  2200000 a 4500". createrecord() will
return the record number for the record that was created, which you will
need to use later when adding fields with addfield(). Createrecord now
makes the new record an instance of an appropriate MARC::Rec subclass.

     use MARC;
     my $x = new MARC;
     $record_number = $x->createrecord();
     $record_number = $x->createrecord({leader=>
     			    	       "00000nmm  2200000 a 4500"});

   MARC::Rec::createrecord($leader) returns an instance of a suitable
subclass of MARC::Rec.

getupdate()
-----------

   The getupdate() method returns an array that contains the contents of a
field in a defined order that permits restoring the field after deleting
it. This permits changing only individual subfields while keeping other
data intact. If a field is repeated in the record, the resulting array
separates the field information with an element containing "\036" - the
internal field separator which can never occur in real MARC data
parameters. A non-existing field returns undef. An example will make the
structure clearer. The next two MARC fields (shown in ASCII) will be
described in the following array:

     246  30  $aPhoto archive
     246  3   $aAssociated Press photo archive

     my $update246 = {field=>'246',record=>2,ordered=>'y'};
     	# next two statements are equivalent
     my @u246 = $x->getupdate($update246);
     	# or
     my @u246 = ('i1','3','i2','0',
     		'a','Photo archive',"\036",
                 'i1','3','i2',' ',
     		'a','Associated Press photo archive',"\036");

     After making any desired modifications to the data, the existing field can be replaced using the following sequence (for non-repeating fields):

     $x->deletemarc($update246));
     my @records = ();
     foreach my $y1 (@u246) {
         last if ($y1 eq "\036");
     	push @records, $y1;
     }
     $x->addfield($update246, @records);

updaterecord()
--------------

   The updaterecord() method is a more complete version of the preceding
sequence with error checking and the ability to split the update array
into multiple addfield() commands when given repeating fields. It takes an
array of key/value pairs, formatted like the output of getupdate(), and
replaces/creates the field data. For repeated tags, a "\036" element is
used to delimit data into separate addfield() commands. It returns the
number of successful addfield() commands or undef on failure.

     $repeats = $x->updaterecord($update246, @u246);	# same as above

addfield()
----------

   This method will allow you to addfields to a specified record. The
syntax may look confusing at first, but once you understand it you will be
able to add fields to records that you have read in, or to records that
you have created with createrecord(). addfield() takes six parameters:
record which indicates the record number to add the field to, field which
indicates the field you wish to create (ie. 245), *i1* which holds one
character for the first indicator, *i2* which holds one character for the
second indicator, and value which holds the subfield data that you wish to
add to the field. addfield() will automatically try to insert your new
field in tag order (ie. a 500 field before a 520 field), however you can
turn this off if you set ordered to "no" which will add the field to the
end. Here are some examples:

     $y = $x->createrecord(); # $y will store the record number created

     $x->addfield({record=>"$y", field=>"100", i1=>"1", i2=>"0",
     		  value=> [a=>"Twain, Mark, ", d=>"1835-1910."]});

     $x->addfield({record=>"$y", field=>"245",
     		  i1=>"1", i2=>"4", value=>
                  [a=>"The adventures of Huckleberry Finn /",
                   c=>"Mark Twain ; illustrated by E.W. Kemble."]});

   This example initialized a new record, and added a 100 field and a 245
field. For some more creative uses of the addfield() function take a look
at the EXAMPLES section. The value parameters, including *i1* and *i2*,
can be specified using a separate array. This permits restoring field(s)
from the array returned by the getupdate() method - either as-is or with
modifications. The *i1* and *i2* key/value pairs must be first and in that
order if included.

     # same as "100" example above
         my @v100 = 'i1','1','i2',"0",'a',"Twain, Mark, ",
            'd',"1835-1910.";
         $x->addfield({record=>"$y", field=>"100"}, @v100);

add_005s()
----------

   Add_005s takes a specification of records (defaults to everything) and
updates the indicated records with updated 005 fields (date of last
transaction).

output()
--------

   Output is a multi-functional method for creating formatted output from
a MARC object. There are three parameters file, format, records. If file
is specified the output will be directed to that file. It is important to
specify with > and >> whether you want to create or append the file! If no
file is specified then the results of the output will be returned to a
variable (both variations are listed below).

   The MARC standard includes a control field (005) that records the date
of last automatic processing. This is implemented as a side-effect of
output() to a file or if explicitly requested via a add_005s field of the
template. The current time is stamped on the records indicated by the
template.

   Valid format values currently include usmarc, marcmaker, ascii, html,
urls, and isbd. The optional records parameter allows you to pass an array
of record numbers which you wish to output. You must pass the array as a
reference, hence the forward-slash in \@records below. If you do not
include records the output will default to all the records in the object.

   The lineterm parameter can be used to override the line-ending default
for any of the formats. *MARCMaker* defaults to CRLF (the format was
originally released for MS-DOS). The others use '\n' as the default.

   With the *MARCMaker* format, a charset parameter accepts a
hash-reference to a user supplied character translation table. The
"ustext.txt" table supplied with the LoC. MARCBreaker utility is used
internally as the default. You can use the *ustext_default* method to get
a hash-reference to it if you only want to modify a couple of characters.
See example below.

   The *MARCMaker* Specification requires that long lines be split to less
than 80 columns. While that behavior is the default, the *nolinebreak*
parameter can override it and the resulting output will be much like the
ascii format.

   MARC::Rec::output($template) is the same as output except that ignores
record number(s) and only outputs its caller. (E.g., with $format eq
'urls' it does not output html header and footer information.)

   * MARC

          $x->output({file=>">mymarc.dat",'format'=>"usmarc"});
          $x->output({file=>">mymarc.dat",'format'=>"usmarc",
          		records=>\@records});
          $y=$x->output({'format'=>"usmarc"}); #put the output into $y

   * MARCMaker

          $x->output({file=>">mymarcmaker.mkr",'format'=>"marcmaker"});
          $x->output({file=>">mymarcmaker.mkr",'format'=>"marcmaker",
          		records=>\@records});
          $y=$x->output({'format'=>"marcmaker"}); #put the output into $y

          $x->output({file=>"brkrtest.mkr",'format'=>"marcmaker",
          		nolinebreak=>"1", lineterm=>"\n",
          		charset=>\%char_hash});

   * ASCII

          $x->output({file=>">myascii.txt",'format'=>"ascii"});
          $x->output({file=>">myascii.txt",'format'=>"ascii",
          		records=>\@records});
          $y=$x->output({'format'=>"ascii"}); #put the output into $y

   * HTML

     The HTML output method has some additional parameters. fields which
     if set to "all" will output all of the fields. Or you can pass the
     tag number and a label that you want to use for that tag. This will
     result in HTML output that only contains the specified tags, and will
     use the label in place of the MARC code.

          $x->output({file=>">myhtml.html",'format'=>"html",
          		fields=>"all"});

          #this will only output the 100 and 245 fields, with the
          	#labels "Title: " and "Author: "
              $x->output({file=>">myhtml.html",'format'=>"html",
                  245=>"Title: ",100=>"Author: "});

          $y=$x->output({'format'=>"html"});

     If you want to build the HTML file in stages, there are four other
     format values available to you: 1) "html_header", 2) "html_start", 3)
     "html_body", and 4) "html_footer". Be careful to use the >> append
     when adding to a file though!

          $x->output({file=>">myhtml.html",
          		'format'=>"html_header"}); # Content-type
          $x->output({file=>">>myhtml.html",
          		'format'=>"html_start"});  # <BODY>
          $x->output({file=>">>myhtml.html",
          		'format'=>"html_body",fields=>"all"});
          $x->output({file=>">>myhtml.html",
          		'format'=>"html_footer"});

   * URLS

          $x->output({file=>"urls.html",'format'=>"urls"});
          $y=$x->output({'format'=>"urls"});

   * ISBD

     An experimental output format that attempts to mimic the ISBD.

          $x->output({file=>"isbd.txt",'format'=>"isbd"});
          $y=$x->output({'format'=>"isbd"});

   * XML

     Round-trip conversion between MARC and XML is handled by the subclass
     MARC::XML. MARC::XML is available for download from the CPAN.

usmarc_default()
----------------

   This method returns a hash reference to a translation table between
mnemonics delimited by curly braces and single-byte character codes in the
MARC record.  Multi-byte characters are not currently supported. The hash
has keys of the form '{esc}' and values of the form chr(0x1b). It is used
during MARCMaker input.

     my %inc = %{$x->usmarc_default()};
     printf "dollar = %s\n", $inc{'dollar'};	# prints '$'
     $inc{'yen'} = 'Y';
     $x->openmarc({file=>"makrbrkr.mrc",'format'=>"marcmaker",
     		  charset=>\%inc});

   MARC::Rec::usmarc_default is identical to usmarc_default;

ustext_default()
----------------

   This method returns a hash reference to a translation table between
single-byte character codes and mnemonics delimited by curly braces.
Multi-byte characters are not currently supported. The hash has keys of
the form chr(0x1b) and values of the form '{esc}'. It is used during
MARCMaker output.

     my %outc = %{$x->ustext_default()};
     printf "dollar = %s\n", $outc{'$'};	# prints '{dollar}'
     $outc{'$'} = '{uscash}';
     printf "dollar = %s\n", $outc{'$'};	# prints '{uscash}'
     $y = $x->output({'format'=>"marcmaker", charset=>\%outc});

   MARC::Rec::ustext_default is identical to ustext_default;

as_string()
-----------

   As_string() takes no parameters and returns a (Unix) newline separated
version of the record.

     Format is: $tag<SPACE>$i1$i2<SPACE>$subfields
     where $subfields are separated by "\c_" binary subfield indicators.
     Tag 000 is ldr.

   Subclasses may need to override this format. If so, they should
override from_string.

from_string()
-------------

   From_string() takes a string parameter and updates the calling record's
{array} information.  It assumes the string is formatted like the output
of as_string().

EXAMPLES
========

   Here are a few examples to fire your imagination.

   * This example will read in the complete contents of a MARC file called
     "mymarc.dat" and then output it as a MARCMaker file called
     "mymkr.mkr".

          #!/usr/bin/perl
          use MARC;
          $x = MARC->new("mymarc.dat","marcmaker");
          $x->output({file=>"mymkr.mkr",'format'=>"marcmaker");

   * The MARC object occupies a fair number of working memory, and you may
     want to do conversions on very large files. In this case you will
     want to use the openmarc(), nextmarc(), deletemarc(), and closemarc()
     methods to read in portions of the MARC file, do something with the
     record(s), remove them from the object, and then read in the next
     record(s). This example will read in one record at a time from a MARC
     file called "mymarc.dat" and convert it to a MARC Maker file called
     "myfile.mkr".

          #!/usr/bin/perl
          use MARC;
          $x = new MARC;
          $x->openmarc({file=>"mymarc.dat",'format'=>"usmarc"});
          while ($x->nextmarc(1)) {
          	$x->output({file=>">>myfile.mkr",'format'=>"marcmaker"});
          	$x->deletemarc(); #empty the object for reading in another
          }

   * Perhaps you have a tab delimited text file of data for online
     journals you have access to from Dow Jones Interactive, and you would
     like to create a batch of MARC records to load into your catalog. In
     this case you can use createrecord(), addfield() and output() to
     create records as you read in your delimited file. When you are done,
     you then output to a file in USMARC.

          #!/usr/bin/perl
          use MARC;
          $x = new MARC;
          open (INPUT_FILE, "delimited_file");
          while ($line=<INPUT_FILE>) {
              ($journaltitle,$issn) = split /\t/,$line;
              $num=$x->createrecord();
              $x->addfield({record=>$num,
                            field=>"022",
                            i1=>" ", i2=>" ",
                            value=>$issn});
              $x->addfield({record=>$num,
                            field=>"245",
                            i1=>"0", i2=>" ",
                            value=>[a=>$journaltitle]});
              $x->addfield({record=>$num,
                            field=>"260",
                            i1=>" ", i2=>" ",
                            value=>[a=>"New York (N.Y.) :",
          			      b=>"Dow Jones & Company"]});
          	$x->addfield({record=>$num,
          		      field=>"710",
          		      i1=>"2", i2=>" ",
          		      value=>[a=>"Dow Jones Interactive."]});
          	$x->addfield({record=>$num,
          		      field=>"856",
          		      i1=>"4", i2=>" ",
          		      value=>[u=>"http://www.djnr.com",
          			      z=>"Connect"]});
          }
          close INPUT_FILE;
          $x->output({file=>">dowjones.mrc",'format'=>"usmarc"})

   * Perhaps you have periodicals coming in that you want to order by
     location and then title. MARC::Rec's get you out of some array
     indexing.

          #!/usr/bin//perl
          use MARC 1.03;

          my @newmarcs=@$marc[1..$#$marc]; # array slice.
          my @sortmarcs = sort by_loc_oclc @newmarcs;
          @marc[1..$#$marc] = @sortmarcs;

          sub by_loc_title {
          	my ($aloc,$atitle) = loc_title($a);
          	my ($bloc,$btitle) = loc_title($b);
          	return  $aloc cmp $bloc
          		      ||
          	      $atitle cmp $btitle;
          }

          sub loc_title {
          	my ($rec)=@_;
          	my $n049 = $rec->getfirstvalue({field=>040});
          	my ($loc) = $n049=~/(ND\S+)/; # Or the first two letters of your OCLC
          				      # location.

          my $title = $rec->getfirstvalue({field=>100,delimiter=>" "});

          return ($loc,$title);
              }

NOTES
=====

   Please let us know if you run into any difficulties using MARC.pm-we'd
be happy to try to help. Also, please contact us if you notice any bugs, or
if you would like to suggest an improvement/enhancement. Email addresses
are listed at the bottom of this page.

   Development of MARC.pm and other library oriented Perl utilities is
conducted on the Perl4Lib listserv. Perl4Lib is an open list and is an
ideal place to ask questions about MARC.pm. Subscription information is
available at http://www.vims.edu/perl4lib

   Two global boolean variables are reserved for test and debugging. Both
are "0" (off) by default. The `$TEST' variable disables internal error
messages generated using Carp. It also overrides the date_stamp in the
"005" field with a constant "19960221075055.7". It should only be used in
the automatic test suite. The `$DEBUG' variable adds verbose diagnostic
messages. Since both variables are used only in testing, *MARC::Rec* uses
`$MARC::TEST' and `$MARC::DEBUG' rather than define a second pair.

AUTHORS
=======

   Chuck Bearden cbearden@rice.edu

   Bill Birthisel wcbirthisel@alum.mit.edu

   Derek Lane dereklane@pobox.com

   Charles McFadden chuck@vims.edu

   Ed Summers ed@cheetahmail.com

SEE ALSO
========

   perl(1), http://lcweb.loc.gov/marc

COPYRIGHT
=========

   Copyright (C) 1999,2000, Bearden, Birthisel, Lane, McFadden, and
Summers.  All rights reserved. This module is free software; you can
redistribute it and/or modify it under the same terms as Perl itself. 23
April 2000.  Portions Copyright (C) 1999,2000, Duke University, Lane.

A subclass of MARC.pm to provide XML support.
*********************************************

NAME
====

   MARC::XML - A subclass of MARC.pm to provide XML support.

SYNOPSIS
========

     use MARC::XML;

     #read in some MARC and output some XML
     $myobject = MARC::XML->new("marc.mrc","usmarc");
     $myobject->output({file=>">marc.xml",format=>"xml"});

     #read in some XML and output some MARC
     $myobject = MARC::XML->new("marc.xml","xml");
     $myobject->output({file=>">marc.mrc","usmarc");

DESCRIPTION
===========

   MARC::XML is a subclass of MARC.pm which provides methods for round-trip
conversions between MARC and XML. MARC::XML requires that you have the
CPAN modules MARC.pm and XML::Parser installed in your Perl library.
Version 1.04 of MARC.pm and 2.27 of XML::Parser (or later) are required.
As a subclass of MARC.pm a MARC::XML object will by default have the full
functionality of a MARC.pm object. See the MARC.pm documentation for
details.

   The XML file that is read and generated by MARC::XML is not associated
with a Document Type Definition (DTD). This means that your files need to
be well-formed, but they will not be validated. When performing XML->MARC
conversion it is important that the XML file is structured in a particular
way. Fortunately, this is the same format that is generated by the
MARC->XML conversion, so you should be able to be able to move your data
easily between the two formats.

Downloading and Intalling
-------------------------

Download
     First make sure that you have *MARC.pm* and XML::Parser installed.
     Both Perl extensions are available from the CPAN
     http://www.cpan.org/modules/by-module, and they must be available in
     your Perl library for MARC::XML to work properly.

     MARC::XML is provided in standard CPAN distribution format. Download
     the latest version from
     http://www.cpan.org/modules/by-module/MARC/XML. It will extract into
     a directory MARC-XML-version with any necessary subdirectories.  Once
     you have extracted the archive Change into the MARC-XML top directory
     and execute the following command depending on your platform.

Unix
          perl Makefile.PL
          make
          make test
          make install

Win9x/WinNT/Win2000
          perl Makefile.PL
          perl test.pl
          perl install.pl

Test
     Once you have installed, you can check if Perl can find it. Change to
     some other directory and execute from the command line:

          perl -e "use MARC::XML"

     If you *do not* get any response that means everything is OK! If you
     get an error like *Can't locate method "use" via package MARC::XML*.
     then Perl is not able to find MARC::XML-double check that the file
     copied it into the right place during the install.

Todo
----

   * Checking for field and record lengths to make sure that data read in
     from an XML file does not exceed the limited space available in a
     MARC record.

   * Support for MARC <-> Unicode character conversions.

   * MARC <-> EAD (Encoded Archival Description) conversion?

   * Support for MARC <-> DC/RDF (Dublin Core Metadata encoded in the
     Resource Description Framework)?

   * Support for MARC <-> FGDC Metadata (Federal Geographic Data Committee)
     conversion?

Web Interface
-------------

   A web interface to MARC.pm and MARC::XML is available at
http://libstaff.lib.odu.edu/cgi-bin/marc.cgi where you can upload records
and observe the results. If you'd like to check out the cgi script take a
look at
http://libstaff.lib.odu.edu/depts/systems/iii/scripts/MARCpm/marc-cgi.txt
However, to get the full functionality you will want to install MARC.pm and
MARC::XML on your server or PC.

Sample XML file
---------------

   Below is an example of the flavor of XML that MARC::XML will generate
and read.  There are only four elements: the *<marc>* pair that serves as
the root for the file; the *<record>* pair that encloses each record; the
*<field>* pair which encloses each field; and the *<subfield>* pair which
encloses each subfield. In addition the *<field>* and *<subfield>* tags
have three possible attributes: type which defines the specific tag or
subfield ; as well as *i1* and *i2* which allow you to define the
indicators for a specific tag.

     <?xml version="1.0" encoding="UTF-8" standalone="yes"?>

     <marc>

     <record>
     <field type="000">00901cam  2200241Ia 45e0</field>
     <field type="001">ocm01047729 </field>
     <field type="003">OCoLC</field>
     <field type="005">19990808143752.0</field>
     <field type="008">741021s1884    enkaf         000 1 eng d</field>
     <field type="040" i1=" " i2=" ">
        <subfield type="a">KSU</subfield>
        <subfield type="c">KSU</subfield>
        <subfield type="d">GZM</subfield>
     </field>
     <field type="090" i1=" " i2=" ">
        <subfield type="a">PS1305</subfield>
        <subfield type="b">.A1 1884</subfield>
     </field>
     <field type="049" i1=" " i2=" ">
        <subfield type="a">VODN</subfield>
     </field>
     <field type="100" i1="1" i2=" ">
        <subfield type="a">Twain, Mark,</subfield>
        <subfield type="d">1835-1910.</subfield>
     </field>
     <field type="245" i1="1" i2="4">
        <subfield type="a">The adventures of Huckleberry Finn :</subfield>
        <subfield type="b">(Tom Sawyer's comrade) : scene, the Mississippi Valley : time, forty to fifty years ago /</subfield>
        <subfield type="c">by Mark Twain (Samuel Clemens) ; with 174 illustrations.</subfield>
     </field>
     <field type="260" i1=" " i2=" ">
        <subfield type="a">London :</subfield>
        <subfield type="b">Chatto &amp; Windus,</subfield>
        <subfield type="c">1884.</subfield>
     </field>
     <field type="300" i1=" " i2=" ">
        <subfield type="a">xvi, 438 p., [1] leaf of plates :</subfield>
        <subfield type="b">ill. ;</subfield>
        <subfield type="c">20 cm.</subfield>
     </field>
     <field type="500" i1=" " i2=" ">
        <subfield type="a">First English ed.</subfield>
     </field>
     <field type="500" i1=" " i2=" ">
        <subfield type="a">State B; gatherings saddle-stitched with wire staples.</subfield>
     </field>
     <field type="500" i1=" " i2=" ">
        <subfield type="a">Advertisements on p. [1]-32 at end.</subfield>
     </field>
     <field type="500" i1=" " i2=" ">
        <subfield type="a">Bound in red S cloth; stamped in black and gold.</subfield>
     </field>
     <field type="510" i1="4" i2=" ">
        <subfield type="a">BAL</subfield>
        <subfield type="c">3414.</subfield>
     </field>
     <field type="740" i1="0" i2="1">
        <subfield type="a">Huckleberry Finn.</subfield>
     </field>
     <field type="994" i1=" " i2=" ">
        <subfield type="a">E0</subfield>
        <subfield type="b">VOD</subfield>
     </field>
     </record>

     </marc>

METHODS
=======

   Here is a list of methods available to you in MARC::XML.

new()
-----

   MARC::XML overides MARC.pm's new() method to create a MARC::XML object.
Similar to MARC.pm's new() it can take two arguments: a file name, and the
format of the file to read in. However MARC::XML's new() gives you an
extra format choice "XML" (which is also the default). Internally, the XML
source is converted to a series of addfield() and createrecord() calls.
The order of MARC tags is preserved by default. But if an optional third
argument is passed to new(), it is used as the ordered option for the
addfield() calls. Like MARC.pm, it is not possible to read only part of an
XML input file using new(). Some examples:

     #read in an XML file called myxmlfile.xml
        use MARC::XML;
        $x = MARC::XML->new("myxmlfile.xml","xml");
        $x = MARC::XML->new("needsort.xml","xml","y");

   Since the full funtionality of MARC.pm is also available you can read in
other types of files as well. Although new() with no arguments will create
an object with no records, just like MARC.pm, XML format not supported by
openmarc() and nextmarc() for input. The openxml() and nextxml() methods
provide similar operation. And you can output from XML to a different
format source.

     #read in a MARC file called mymarcfile.mrc
        use MARC::XML;
        $x = MARC::XML->new("mymarcfile.mrc","usmarc");
        $x = MARC::XML->new();

output()
--------

   MARC::XML's output() method allows you to output the MARC object as an
XML file. It takes eight arguments: file, format, lineterm, and records
have the same function as in MARC.pm. If not specified, format defaults to
"xml" and lineterm defaults to "\n". A charset parameter accepts a
hash-reference to a user supplied character translation table.  The
internal default is based on the LoC "register.sgm" table supplied with
the LoC. SGML utilities. You can use the *ansel_default* method to get a
hash-reference to it if you only want to modify a couple of characters.
See example below. The encoding, *dtd_file*, and *standalone* arguments
correspond to the specified fields in an XML header. If not specified,
*standalone* defaults to "yes" and encoding to "US-ASCII". If an optional
*dtd_file* is specified, a *Document Type Declaration* is added to the
output to contain the data.

     use MARC::XML;
     $x = MARC::XML->new("mymarcfile.mrc","usmarc");
     $x->output({file=>">myxmlfile.xml",format=>"xml"});

   Or if you only want to output the first record:

     $x->output({file=>">myxmlfile.xml",format=>"xml",records=>[1]});

   If you like you can also output portions of the XML file using the
format options: *xml_header*, *xml_body*, and *xml_footer*. Remember to
prefix your file name with a >> to append though. This example will output
record 1 twice.

     use MARC::XML;
     $x = MARC::XML->new("mymarcfile.mrc","usmarc");
     $x->output({file=>">myxmlfile.xml",format=>"xml_header"});
     $x->output({file=>">>myxmlfile.xml",format=>"xml_body",records=>[1]});
     $x->output({file=>">>myxmlfile.xml",format=>"xml_body",records=>[1]});
     $x->output({file=>">>myxmlfile.xml",foramt=>"xml_footer"});

   Instead of outputting to a file, you can also capture the output in a
variable if you wish.

     use MARC::XML;
     $x = MARC::XML->new("mymarcfile.mrc","usmarc");
     $myxml = $x->output({format=>"xml"});

   As with new() the full functionality of MARC.pm's output() method are
available to you as well.  So you could read in an XML file and then
output it as ascii text:

     use MARC::XML;
     $x = MARC::XML->new("myxmlfile.xml","xml");
     $x->output({file=>">mytextfile.txt","ascii");

NOTES
=====

   Please let us know if you run into any difficulties using MARC.pm-we'd
be happy to try to help. Also, please contact us if you notice any bugs, or
if you would like to suggest an improvement/enhancement. Email addresses
are listed at the bottom of this page.

   Development of MARC.pm and other library oriented Perl utilities is
conducted on the Perl4Lib listserv. Perl4Lib is an open list and is an
ideal place to ask questions about MARC.pm. Subscription information is
available at http://www.vims.edu/perl4lib

   Two global boolean variables are reserved for test and debugging. Both
are "0" (off) by default. The `$XTEST' variable disables internal error
messages generated using Carp. It should only be used in the automatic
test suite.  The `$XDEBUG' variable adds verbose diagnostic messages.

EXAMPLES
========

   The *eg* subdirectory contains a few complete examples to get you
started.

AUTHORS
=======

   Chuck Bearden cbearden@rice.edu

   Bill Birthisel wcbirthisel@alum.mit.edu

   Derek Lane dereklane@pobox.com

   Charles McFadden chuck@vims.edu

   Ed Summers ed@cheetahmail.com

SEE ALSO
========

   perl(1), MARC.pm, MARC http://lcweb.loc.gov/marc , XML
http://www.w3.org/xml .

COPYRIGHT
=========

   Copyright (C) 1999,2000, Bearden, Birthisel, Lane, McFadden, and
Summers.  All rights reserved. This module is free software; you can
redistribute it and/or modify it under the same terms as Perl itself. 23
April 2000.  Portions Copyright (C) 1999,2000, Duke University, Lane.

Perl extension for MCrypt Crypto library
****************************************

NAME
====

   MCrypt - Perl extension for MCrypt Crypto library

DISCLAIMER
==========

THIS IS A FIRST RELEASE BETA VERSION.
-------------------------------------

     Yes, it does work.

   If you have use for this, please try and use it and report any bugs you
find.  Feedback from users of this module is important.

SYNOPSIS
========

     use MCrypt qw(:Functions :Modes :Types) ;
     my $key = "my secret key";
     my $data "this is my secret data";
     # optional IV that matches the blocksize of the cipher!
     my $iv = "12345678" ; # 8 bytes for MCRYPT_3DES
     $ciphertext = mcrypt_cbc( MCRYPT_3DES, $key, $data, MCRYPT_ENCRYPT, $iv ) ;

     **NOTE** Please read the section on EXPORT TAGS below for information on the MCRYPT_ constants and the how to conserve your namespace.

DEPENDENCIES
============

   This interface is dependent on the 2.2.x tree of the MCRYPT library.
Please download and install the latest libmcrypt-2.2.x.tar.gz at
ftp://argeas.cs-net.gr/pub/unix/mcrypt.  As of this writing, the latest is
libmcrypt-2.2.7.tar.gz.  Additional information about the mcrypt library
can be found at http://mcrypt.hellug.gr.

   Libmcrypt MUST be found in your library path when using this module.
In Linux, libmcrypt is defaultly installed in /usr/local/lib - in this
case, be sure that the /usr/local/lib path is in your /etc/ld.so.conf.

DESCRIPTION
===========

   This is an perl interface to the MCrypt crypto library, which supports
a wide variety of block algorithms such as DES, TripleDES, Blowfish
(default), 3-WAY, SAFER-SK64, SAFER-SK128, TWOFISH, TEA, RC2, GOST, LOKI,
SERPENT, CAST and RIJNDAEL in CBC, OFB, CFB and ECB cipher modes.

   Mcrypt can be used to encrypt and decrypt using the above mentioned
ciphers. The four important mcrypt commands (mcrypt_cfb(), mcrypt_cbc(),
mcrypt_ecb(), and mcrypt_ofb()) can operate in both modes which are named
MCRYPT_ENCRYPT and MCRYPT_DECRYPT, respectively.

   Mcrypt can operate in four block cipher modes (CBC, OFB, CFB, and ECB).
We will outline the normal use for each of these modes. For a more
complete reference and discussion see Applied Cryptography by Schneier
(ISBN 0-471-11709-9).

     ECB (electronic codebook) is suitable for random data, such as encrypting other keys. Since data there is short and random, the disadvantages of ECB have a favorable negative effect.

     CBC (cipher block chaining) is especially suitable for encrypting files where the security is increased over ECB significantly.

     CFB (cipher feedback) is the best mode for encrypting byte streams where single bytes must be encrypted.

     OFB (output feedback, in 8bit) is comparable to CFB, but can be used in applications where error propagation cannot be tolerated. It's insecure (because it operates in 8bit mode) so it is not recommended to use it.

   MCrypt does not support encrypting/decrypting bit streams currently. As
of now, MCrypt only supports handling of strings.

   Here is the list of cipher constants which are currently supported by
the MCrypt module:

     MCRYPT_DES

     MCRYPT_3DES

     MCRYPT_3WAY

     MCRYPT_GOST

     MCRYPT_SAFER64

     MCRYPT_SAFER128

     MCRYPT_CAST_128

     MCRYPT_CAST_256

     MCRYPT_XTEA

     MCRYPT_RC2_128

     MCRYPT_RC2_192

     MCRYPT_RC2_1024

     MCRYPT_TWOFISH128

     MCRYPT_TWOFISH192

     MCRYPT_TWOFISH256

     MCRYPT_BLOWFISH_128

     MCRYPT_BLOWFISH_192

     MCRYPT_BLOWFISH_256

     MCRYPT_BLOWFISH_448 (the default if a blank cipher is supplied)

     MCRYPT_CAST_256

     MCRYPT_SAFERPLUS

     MCRYPT_LOKI97

     MCRYPT_SERPENT_128

     MCRYPT_SERPENT_192

     MCRYPT_SERPENT_256

     MCRYPT_RIJNDAEL_128

     MCRYPT_RIJNDAEL_192

     MCRYPT_RIJNDAEL_256

     MCRYPT_CRYPT

     MCRYPT_RC6_128

     MCRYPT_RC6_192

     MCRYPT_RC6_256

     MCRYPT_IDEA (non-free)

     MCRYPT_ARCFOUR (also aliased as MCRYPT_RC_4)

   You must (in CFB and OFB mode) or can (in CBC mode) supply an
initialization vector (IV) to the respective cipher function. The IV must
be unique and must be the same when decrypting/encrypting. With data which
is stored encrypted, you can take the output of a function of the index
under which the data is stored (e.g. the MD5 key of the filename).
Alternatively, you can transmit the IV together with the encrypted data
(see chapter 9.3 of Applied Cryptography by Schneier (ISBN 0-471-11709-9)
for a discussion of this topic).

EXPORT TAGS     A more conservative usage of the above SYNOPSIS:
================================================================

     # no export tags supplied in the below line; import :Functions by default
     use MCrypt ;
     my $key = "my secret key";
     my $data "this is my secret data";
     # optional IV that matches the blocksize of the cipher!
     my $iv = "12345678" ; # 8 bytes for MCRYPT_3DES
     $ciphertext = mcrypt_cbc( MCrypt::MCRYPT_3DES, $key, $data, MCrypt::MCRYPT_ENCRYPT, $iv ) ;

   Functions   This tag exports all the functions related to MCrypt.  This
tag should always be imported unless you are going to be calling MCrypt
functions with the full package name.  This tag is automatically imported
if no export tags are supplied as in the above example.  (i.e.
MCrypt::mcrypt_cbc()).

   Modes   This tag exports the encryption mode constants MCRYPT_ENCRYPT
and MCRYPT_DECRYPT.  It is recommended that you import this tag as it only
imports two constants into your namespace.  If you are being conservative
with your namespace, you can leave this out providing you call these
constant with the package name.  (i.e. MCrypt::MCRYPT_ENCRYPT )

   Types   This tag exports the cipher constants defined by the list of
ciphers above in DESCRIPTION.  It is recommended you import this tag for
ease of use.  If you are concerned with polluting your namespace, do not
import this tag, and use the form MCrypt::MCRYPT_CIPHERNAME when supplying
the cipher to the MCrypt functions.  (i.e. MCrypt::MCRYPT_3DES )

PROGRAMMING FUNCTIONS AND METHODS
=================================

   The following methods are available:

   mcrypt_cbc()

   Mcrypt_cbc() encrypts or decrypts (depending on mode) the data with
cipher and key in CBC cipher mode and returns the resulting string.

     $ciphertext = mcrypt_cbc($cipher, $key, $data, $mode, [$IV]) ;

   Cipher is one of the MCRYPT_ciphername constants.

   Key is the key supplied to the algorithm. It must be kept secret.

   Data is the data which shall be encrypted/decrypted.

   Mode is MCRYPT_ENCRYPT or MCRYPT_DECRYPT.

   IV is the optional initialization vector.   (This must be the blocksize
of the cipher!)

   mcrypt_ecb()

     Mcrypt_ecb() encrypts or decrypts (depending on mode) the data with cipher and key in ECB cipher mode and returns the resulting string.

     $ciphertext = mcrypt_ecb($cipher, $key, $data, $mode) ;

   Cipher is one of the MCRYPT_ciphername constants.

   Key is the key supplied to the algorithm. It must be kept secret.

   Data is the data which shall be encrypted/decrypted.

   Mode is MCRYPT_ENCRYPT or MCRYPT_DECRYPT.

   mcrypt_ofb()

     Mcrypt_ofb() encrypts or decrypts (depending on mode) the data with cipher and key in OFB cipher mode and returns the resulting string.

     $ciphertext = mcrypt_ofb($cipher, $key, $data, $mode, $IV) ;

   Cipher is one of the MCRYPT_ciphername constants.

   Key is the key supplied to the algorithm. It must be kept secret.

   Data is the data which shall be encrypted/decrypted.

   Mode is MCRYPT_ENCRYPT or MCRYPT_DECRYPT.

   IV is the initialization vector.  (This must be the blocksize of the
cipher!)

   mcrypt_cfb()

     Mcrypt_cfb() encrypts or decrypts (depending on mode) the data with cipher and key in CFB cipher mode and returns the resulting string.

     $ciphertext = mcrypt_cfb($cipher, $key, $data, $mode, $IV) ;

   Cipher is one of the MCRYPT_ciphername constants.

   Key is the key supplied to the algorithm. It must be kept secret.

   Data is the data which shall be encrypted/decrypted.

   Mode is MCRYPT_ENCRYPT or MCRYPT_DECRYPT.

   IV is the initialization vector.  (This must be the blocksize of the
cipher!)

   mcrypt_get_cipher_name()

     Mcrypt_get_cipher_name() is used to get the name of the specified cipher.  This function takes the cipher number as an argument and returns the name of the cipher as a string or false, if the cipher does not exist.

     $ciphername = mcrypt_get_cipher_name( MCRYPT_3DES ) ;

   Cipher is one of the MCRYPT_ciphername constants.

   mcrypt_get_key_size()

     Mcrypt_get_key_size() is used to get the size of a key of the specified cipher.  This function takes one argument, the cipher and returns the size in bytes.  This function is useful to find the keysize for a specific cipher.  The key you use SHOULD match the keysize.

     $keysize = mcrypt_get_key_size( MCRYPT_3DES ) ;

   Cipher is one of the MCRYPT_ciphername constants.

   mcrypt_get_block_size()

     Mcrypt_get_block_size() is used to get the size of a block of the specified cipher.  This function takes one argument, the cipher and returns the size in bytes.   This function is useful for determining the correct size of the IV of a cipher.

     $keysize = mcrypt_get_block_size( MCRYPT_3DES ) ;

   Cipher is one of the MCRYPT_ciphername constants.

TODO
====

     - More bug testing.
     - implement mcrypt_create_iv() in a nice way
     - detection of libmcrypt installation

AUTHOR
======

   Kuo, Frey, kero@3SHEEP.COM.

CREDITS
-------

   Mavroyanopoulos, Nikos, <nmav@hellug.gr> - for the libmcrypt library.

   Schumann, Sasha, <sascha@schumann.2ns.de> - for PHP's implementation of
the libmcrypt interface.

SEE ALSO
========

   mcrypt(3).

Perl interface to the MD5 Message-Digest Algorithm
**************************************************

NAME
====

   MD5 - Perl interface to the MD5 Message-Digest Algorithm

SYNOPSIS
========

     use MD5;

     $context = new MD5;
     $context->reset();

     $context->add(LIST);
     $context->addfile(HANDLE);

     $digest = $context->digest();
     $string = $context->hexdigest();

     $digest = MD5->hash(SCALAR);
     $string = MD5->hexhash(SCALAR);

DESCRIPTION
===========

   The MD5 module is *depreciated*.  Use Digest::MD5 instead.

   The current MD5 module is just a wrapper around the Digest::MD5 module.
It is provided so that legacy code that rely on the old interface still
work and get the speed benefit of the new module.

   In addition to the methods provided for Digest::MD5 objects, this
module provide the class methods MD5->hash() and MD5->hexhash() that
basically do the same as the md5() and md5_hex() functions provided by
Digest::MD5.

SEE ALSO
========

   See Digest/MD5,

read, compose, modify, and write MIDI files.
********************************************

NAME
====

   MIDI - read, compose, modify, and write MIDI files.

SYNOPSIS
========

     use MIDI;
     $chimes_track = MIDI::Track->new({ 'events' => [
      ['text_event',0, 'www.ely.anglican.org/parishes/camgsm/chimes.html'],
      ['text_event',0, 'Lord through this hour/ be Thou our guide'],
      ['text_event',0, 'so, by Thy power/ no foot shall slide'],
      ['text_event',0, '(coded at ' . scalar(localtime) . ' )'],
      ['patch_change', 0, 1, 8], # Patch 8 = Celesta
      map( (['note_on',0,1,$_->[0],96], ['note_off',$_->[1],1,$_->[0],0]),
           [25,96],[29,96],[27,96],[20,192],[25,96],[27,96],[29,96],[25,192],
           [29,96],[25,96],[27,96],[20,192],[20,96],[27,96],[29,96],[25,192],
         )# [Note,Duration] ==> ['note_on',0,1, N ,96], ['note_off', D ,1, N ,0]
     ] });
     $chimes = MIDI::Opus->new(
      { 'format' => 0, 'ticks' => 96, 'tracks' => [ $chimes_track ] } );
     $chimes->write_to_file('chimes.mid');

DESCRIPTION
===========

   This suite of modules provides routines for reading, composing,
modifying, and writing MIDI files.

   From FOLDOC (`http://wombat.doc.ic.ac.uk/foldoc/'):

   *MIDI, Musical Instrument Digital Interface*

   <multimedia, file format> (MIDI /mi'-dee/, /mee'-dee/) A hardware
specification and protocol used to communicate note and effect information
between synthesisers, computers, music keyboards, controllers and other
electronic music devices. [...]

   The basic unit of information is a "note on/off" event which includes a
note number (pitch) and key velocity (loudness). There are many other
message types for events such as pitch bend, patch changes and
synthesizer-specific events for loading new patches etc.

   There is a file format for expressing MIDI data which is like a dump of
data sent over a MIDI port. [...]

COMPONENTS
==========

   The MIDI-Perl suite consists of these modules:

   MIDI, (which you're looking at), see MIDI/Opus,
see MIDI/Track, MIDI/Event,
MIDI/Score, and MIDI/Simple.  All
of these contain documentation in pod format.  You should read all of
these pods.

   The order you want to read them in will depend on what you want to do
with this suite of modules: if you are focused on manipulating the guts of
existing MIDI files, read the pods in the order given above.

   But if you aim to compose music with this suite, read this pod, then
MIDI/Score, and MIDI/Simple, and
then skim the rest.

   (For your reference, there is also a document in pod format which is
not itself an actual module: MIDI/Filespec.  It is
an old version of the MIDI file specification.)

INTRODUCTION
============

   This suite of modules is basically object-oriented, with the exception
of MIDI::Simple.  MIDI opuses ("songs") are represented as objects
belonging to the class MIDI::Opus.  An opus contains tracks, which are
objects belonging to the class MIDI::Track.  A track will generally
contain a list of events, where each event is a list consisting of a
command, a delta-time, and some number of parameters.  In other words,
opuses and tracks are objects, and the events in a track comprise a LoL
(and if you don't know what an LoL is, you must read Perllol (perl.info)).

   Furthermore, for some purposes it's useful to analyze the totality of a
track's events as a "score" - where a score consists of notes where each
event is a list consisting of a command, a time offset from the start of
the track, and some number of parameters.  This is the level of
abstraction that MIDI::Score and MIDI::Simple deal with.

   While this suite does provide some functionality accessible only if
you're comfortable with various kinds of references, and while there are
some options that deal with the guts of MIDI encoding, you can (I hope)
get along just fine with just a basic grasp of the MIDI "standard", and a
command of LoLs.  I have tried, at various points in this documentation,
to point out what things are not likely to be of use to the casual user.

TO DO
=====

   Maybe have a MIDI cookbook of commonly used short scripts?

   *A PLEA*: Currently this suite can only read/write MIDI data from/to
MIDI files.  However, it would be desirable to have realtime access to a
MIDI device - at least on systems where a MIDI device (whether thru a
hardware port or as a virtual sequencer in a sound card) is accessable as
a virtual file (`/dev/midi0', `/dev/midi', `/dev/sequencer', or whatever).
However, I have no such MIDI devices (much less ports) at hand for
development and testing.  But if *you* have such devices (I'm thinking a
Linuxer with a synth hooked to their MIDI port), and if you want to help
me experiment with directly accessing them from Perl, then please email
me.  I already have a pretty good idea of how it should work - but as
always, the proof is as much in the pudding as the devil is in the details.

GOODIES
=======

   The bare module MIDI.pm doesn't do much more than use the necessary
component submodules (i.e., all except MIDI::Simple).  But it does provide
some hashes you might find useful:

`%MIDI::note2number' and `%MIDI::number2note'
     `%MIDI::number2note' correponds MIDI note numbers to a more
     comprehensible representation (e.g., 68 to 'Gs4', for G-sharp, octave
     4); `%MIDI::note2number' is the reverse.  Have a look at the source
     to see the contents of the hash.

`%MIDI::patch2number' and `%MIDI::number2patch'
     `%MIDI::number2patch' correponds General MIDI patch numbers (0 to
     127) to English names (e.g., 79 to 'Ocarina'); `%MIDI::patch2number'
     is the reverse.  Have a look at the source to see the contents of the
     hash.

`%MIDI::notenum2percussion' and `%MIDI::percussion2notenum'
     `%MIDI::notenum2percussion' correponds General MIDI Percussion Keys
     to English names (e.g., 56 to 'Cowbell') - but note that only numbers
     35 to 81 (inclusive) are defined; `%MIDI::percussion2notenum' is the
     reverse.  Have a look at the source to see the contents of the hash.

BRIEF GLOSSARY
==============

   This glossary defines just a few terms, just enough so you can
(hopefully) make some sense of the documentation for this suite of
modules.  If you're going to do anything serious with these modules,
however, you *should really* invest in a good book about the MIDI standard
- see the References.

   channel: a logical channel to which control changes and patch changes
apply, and in which MIDI (note-related) events occur.

   control: one of the various numeric parameters associated with a given
channel.  Like S registers in Hayes-set modems, MIDI controls consist of a
few well-known registers, and beyond that, it's patch-specific and/or
sequencer-specific.

   *delta-time*: the time (in ticks) that a sequencer should wait between
playing the previous event and playing the current event.

   *meta-event*: any of a mixed bag of events whose common trait is merely
that they are similarly encoded.  Most meta-events apply to all channels,
unlike events, which mostly apply to just one channel.

   note: my oversimplistic term for items in a score structure.

   *opus*: the term I prefer for a piece of music, as represented in MIDI.
Most specs use the term "song", but I think that this falsely implies
that MIDI files represent vocal pieces.

   patch: an electronic model of the sound of a given notional instrument.

   *running status*: a form of modest compression where an event lacking
an event command byte (a "status" byte) is to be interpreted as having the
same event command as the preceding event - which may, in turn, lack a
status byte and may have to be interpreted as having the same event
command as *its* previous event, and so on back.

   score: a structure of notes like an event structure, but where notes
are represented as single items, and where timing of items is absolute
from the beginning of the track, instead of being represented in
delta-times.

   *song*: what some MIDI specs call a song, I call an opus.

   *sequencer*: a device or program that interprets and acts on MIDI data.
This prototypically refers to synthesizers or drum machines, but can also
refer to more limited devices, such as mixers or even lighting control
systems.

   status: a synonym for "event".

   *sysex*: a chunk of binary data encapsulated in the MIDI data stream,
for whatever purpose.

   *text event*: any of the several meta-events (one of which is actually
called 'text_event') that conveys text.  Most often used to just label
tracks, note the instruments used for a track, or to provide
metainformation about copyright, performer, and piece title and author.

   *tick*: the timing unit in a MIDI opus.

   *variable-length encoding*: an encoding method identical to what Perl
calls the 'w' (BER, Basic Encoding Rules) pack/unpack format for integers.

REFERENCES
==========

   Christian Braut.  *The Musician's Guide to Midi.*  ISBN 0782112854.
[This one is indispensible -SMB]

   Langston, Peter S.  1998. "Little Music Languages", p.587-656 in:
Salus, Peter H,. editor in chief, /Handbook of Programming Languages/,
vol.  3.  MacMillan Technical, 1998.  [The volume it's in is probably not
worth the money, but see if you can at least glance at this article
anyway.  It's not often you see 70 pages written on music languages. -SMB]

   I'll keep a list of other references and good stuff at the URL
`http://www.speech.cs.cmu.edu/~sburke/pub/perl_midi/'

AUTHOR
======

   Sean M. Burke `sburke@cpan.org'

MIDI events
***********

NAME
====

   MIDI::Event - MIDI events

SYNOPSIS
========

     # Dump a MIDI file's text events
     die "No filename" unless @ARGV;
     use MIDI;  # which "use"s MIDI::Event;
     MIDI::Opus->new( {
        "from_file" => $ARGV[0],
        "exclusive_event_callback" => sub{print "$_[2]\n"},
        "include" => \@MIDI::Event::Text_events
      } ); # These options percolate down to MIDI::Event::decode
     exit;

DESCRIPTION
===========

   Functions and lists to do with with MIDI events and MIDI event
structures.

   An event is a list, like:

     ( 'note_on', 141, 4, 50, 64 )

   where the first element is the event name, the second is the
delta-time, and the remainder are further parameters, per the event-format
specifications below.

   An *event structure* is a list of references to such events - a "LoL".
If you don't know how to deal with LoLs, you must read Perllol (perl.info).

GOODIES
=======

   For your use in code (as in the code in the Synopsis), this module
provides a few lists:

@MIDI_events
     a list of all "MIDI events" AKA voice events - e.g., 'note_on'

@Text_events
     a list of all text meta-events - e.g., 'track_name'

@Nontext_meta_events
     all other meta-events (plus 'raw_data' and F-series events like
     'tune_request').

@Meta_events
     the combination of Text_events and Nontext_meta_events.

@All_events
     the combination of all the above lists.

FUNCTIONS
=========

   This module provides three functions of interest, which all act upon
event structures.  As an end user, you probably don't need to use any of
these directly, but note that options you specify for MIDI::Opus->new with
a from_file or from_handle options will percolate down to these functions;
so you should understand the options for the first two of the below
functions.  (The casual user should merely skim this section.)

MIDI::Event::decode( \$data, { ...options... } )
     This takes a reference to binary MIDI data and decodes it into a new
     event structure (a LoL), a reference to which is returned.  Options
     are:

    'include' => LISTREF
          *If specified*, listref is interpreted as a reference to a list
          of event names (e.g., 'cue_point' or 'note_off') such that only
          these events will be parsed from the binary data provided.
          Events whose names are NOT in this list will be ignored - i.e.,
          they won't end up in the event structure, and they won't be each
          passed to any callbacks you may have specified.

    'exclude' => LISTREF
          *If specified*, listref is interpreted as a reference to a list
          of event names (e.g., 'cue_point' or 'note_off') that will NOT
          be parsed from the binary stream; they'll be ignored - i.e.,
          they won't end up in the event structure, and they won't be
          passed to any callbacks you may have specified.  Don't specify
          both an include and an exclude list.  And if you specify
          *neither*, all events will be decoded - this is what you
          probably want most of the time.  I've created this
          include/exclude functionality mainly so you can scan a file
          rather efficiently for just a few specific event types, e.g.,
          just text events, or just sysexes.

    'no_eot_magic' => 0 or 1
          See the description of `'end_track'', in "EVENTS", below.

    'event_callback' => CODEREF
          If defined, the code referred to (whether as `\&wanted' or as
          `sub { BLOCK }') is called on every event after it's been parsed
          into an event list (and any EOT magic performed), but before
          it's added to the event structure.  So if you want to alter the
          event stream on the way to the event structure (which counts as
          deep voodoo), define 'event_callback' and have it modify its
          `@_'.

    'exclusive_event_callback' => CODEREF
          Just like 'event_callback'; but if you specify this, the
          callback is called *instead* of adding the events to the event
          structure.  (So the event structure returned by decode() at the
          end will always be empty.)  Good for cases like the text dumper
          in the Synopsis, above.

MIDI::Event::encode( \@events, {...options...})
     This takes a reference to an event structure (a LoL) and encodes it
     as binary data, which it returns a reference to.  Options:

    'unknown_callback' => CODEREF
          If this is specified, it's interpreted as a reference to a
          subroutine to be called when an unknown event name (say,
          'macro_10' or something), is seen by encode().  The function is
          fed all of the event (its name, delta-time, and whatever
          parameters); the return value of this function is added to the
          encoded data stream - so if you don't want to add anything, be
          sure to return ".

          If no 'unknown_callback' is specified, encode() will warn (well,
          carp) of the unknown event.  To merely block that, just set
          'unknown_callback' to `sub{return('')}'

    'no_eot_magic' => 0 or 1
          Determines whether a track-final 0-length text event is encoded
          as a end-track event - since a track-final 0-length text event
          probably started life as an end-track event read in by decode(),
          above.

    'never_add_eot' => 0 or 1
          If 1, encode() never ever *adds* an end-track (EOT) event to the
          encoded data generated unless it's *explicitly* there as an
          'end_track' in the given event structure.  You probably don't
          ever need this unless you're encoding for *straight* writing to
          a MIDI port, instead of to a file.

    'no_running_status' => 0 or 1
          If 1, disables MIDI's "running status" compression.  Probably
          never necessary unless you need to feed your MIDI data to a
          strange old sequencer that doesn't understand running status.

     Note: If you're encoding just a single event at a time or less than a
     whole trackful in any case, then you probably want something like:

          $data_r = MIDI::Event::encode(
            [
              [ 'note_on', 141, 4, 50, 64 ]
            ],
            { 'never_add_eot' => 1} );

     which just encodes that one event *as* an event structure of one
     event - i.e., an LoL that's just a list of one list.

     But note that running status will not always apply when you're
     encoding less than a whole trackful at a time, since running status
     works only within a LoL encoded all at once.  This'll result in
     non-optimally compressed, but still effective, encoding.

MIDI::Event::copy_structure()
     This takes a reference to an event structure, and returns a reference
     to a copy of it.  If you're thinking about using this, you probably
     should want to use the more straightforward

          $track2 = $track->copy

     instead.  But it's here if you happen to need it.

EVENTS AND THEIR DATA TYPES
===========================

DATA TYPES
----------

   Events use these data types:

channel = a value 0 to 15
note = a value 0 to 127
dtime = a value 0 to 268,435,455 (0x0FFFFFFF)
velocity = a value 0 to 127
channel = a value 0 to 15
patch = a value 0 to 127
sequence = a value 0 to 65,535 (0xFFFF)
text = a string of 0 or more bytes of of ASCII text
raw = a string of 0 or more bytes of binary data
pitch_wheel = a value -8192 to 8191 (0x1FFF)
song_pos = a value 0 to 16,383 (0x3FFF)
song_number = a value 0 to 127
tempo = microseconds, a value 0 to 16,777,215 (0x00FFFFFF)
   For data types not defined above, (e.g., *sf* and *mi* for
`'key_signature''), consult MIDI/Filespec, and/or the
source for `MIDI::Event.pm'.  And if you don't see it documented, it's
probably because I don't understand it, so you'll have to consult a real
MIDI reference.

EVENTS
------

   And these are the events:

('note_off', dtime, channel, note, velocity)
('note_on', dtime, channel, note, velocity)
('key_after_touch', dtime, channel, note, velocity)
('control_change', dtime, channel, *controller(0-127)*, *value(0-127)*)
('patch_change', dtime, channel, patch)
('channel_after_touch', dtime, channel, velocity)
('pitch_wheel_change', dtime, channel, pitch_wheel)
('set_sequence_number', dtime, sequence)
('text_event', dtime, text)
('copyright_text_event', dtime, text)
('track_name', dtime, text)
('instrument_name', dtime, text)
('lyric', dtime, text)
('marker', dtime, text)
('cue_point', dtime, text)

('text_event_08', dtime, text)

('text_event_09', dtime, text)

('text_event_0a', dtime, text)

('text_event_0b', dtime, text)

('text_event_0c', dtime, text)

('text_event_0d', dtime, text)

('text_event_0e', dtime, text)

('text_event_0f', dtime, text)
('end_track', dtime)
('set_tempo', dtime, tempo)
('smpte_offset', dtime, *hr*, *mn*, *se*, *fr*, ff)
('time_signature', dtime, *nn*, dd, cc, *bb*)
('key_signature', dtime, *sf*, *mi*)
('sequencer_specific', dtime, raw)
('raw_meta_event', dtime, command(0-255), raw)

('sysex_f0', dtime, raw)

('sysex_f7', dtime, raw)
('song_position', dtime)
('song_select', dtime, song_number)
('tune_request', dtime)
('raw_data', dtime, raw)
   Three of the above events are represented a bit oddly from the point of
view of the file spec:

   The parameter pitch_wheel for `'pitch_wheel_change'' is a value -8192
to 8191, although the actual encoding of this is as a value 0 to 16,383,
as per the spec.

   Sysex events are represented as either `'sysex_f0'' or `'sysex_f7'',
depending on the status byte they are encoded with.

   `'end_track'' is a bit stranger, in that it is almost never actually
found, or needed.  When the MIDI decoder sees an EOT (i.e., an end-track
status: FF 2F 00) with a delta time of 0, it is *ignored*!  If in the
unlikely event that it has a nonzero delta-time, it's decoded as a
`'text_event'' with whatever that delta-time is, and a zero-length text
parameter.  (This happens before the 'event_callback' or
'exclusive_event_callback' callbacks are given a crack at it.)  On the
encoding side, an EOT is added to the end of the track as a normal part of
the encapsulation of track data.

   I chose to add this special behavior so that you could add events to
the end of a track without having to work around any track-final
`'end_track'' event.

   However, if you set `no_eot_magic' as a decoding parameter, none of
this magic happens on the decoding side - `'end_track'' is decoded just as
it is.

   And if you set `no_eot_magic' as an encoding parameter, then a
track-final 0-length `'text_event'' with non-0 delta-times is left as is.
Normally, such an event would be converted from a `'text_event'' to an
`'end_track'' event with thath delta-time.

   Normally, no user needs to use the `no_eot_magic' option either in
encoding or decoding.  But it is provided in case you need your event LoL
to be an absolutely literal representation of the binary data, and/or vice
versa.

MIDI BNF
========

   For your reference (if you can make any sense of it), here is a copy of
the MIDI BNF, as I found it in a text file that's been floating around the
Net since the late 1980s.

   Note that this seems to describe MIDI events as they can occur in
MIDI-on-the-wire.  I *think* that realtime data insertion (i.e., the
ability to have <realtime byte>s popping up in the *middle* of messages)
is something that can't happen in MIDI files.

   In fact, this library, as written, *can't* correctly parse MIDI data
that has such realtime bytes inserted in messages.  Nor does it support
representing such insertion in a MIDI event structure that's encodable for
writing to a file.  (Although you could theoretically represent events
with embedded <realtime byte>s as just raw_data events; but then, you can
always stow anything at all in a raw_data event.)

     1.  <MIDI Stream> ::=           <MIDI msg> < MIDI Stream>
     2.  <MIDI msg> ::=              <sys msg> | <chan msg>
     3.  <chan msg> ::=              <chan 1byte msg> |
                                     | <chan 2byte msg>
     4.  <chan 1byte msg> ::=        <chan stat1 byte> <data singlet>
                                       <running singlets>
     5.  <chan 2byte msg> ::=        <chan stat2 byte> <data pair>
                                       <running pairs>
     6.  <chan stat1 byte> ::=       <chan voice stat1 nibble>
                                       <hex nibble>
     7.  <chan stat2 byte> ::=       <chan voice stat2 nibble>
                                       <hex nibble>
     8.  <chan voice stat1 nyble>::= C | D
     9.  <chan voice stat2 nyble>::= 8 | 9 | A | B | E
     10. <hex nyble> ::=             0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
                                     | 8 | 9 | A | B | C | D | E | F
     11. <data pair> ::=             <data singlet> <data singlet>
     12. <data singlet> ::=          <realtime byte> <data singlet> |
                                     | <data byte>
     13. <running pairs> ::=         <empty> | <data pair> <running pairs>
     14. <running singlets> ::=      <empty> |
                                     | <data singlet> <running singlets>
     15. <data byte> ::=             <data MSD> <hex nyble>
     16. <data MSD> ::=              0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
     17. <realtime byte> ::=         F8 | FA | FB | FC | FE | FF
     18. <sys msg> ::=               <sys common msg> |
                                     | <sysex msg> |
                                     | <sys realtime msg>
     19. <sys realtime msg> ::=      <realtime byte>
     20. <sysex msg> ::=             <sysex data byte>
                                       <data singlet> <running singlets>
                                       <eox byte>
     21. <sysex stat byte> ::=       F0
     22. <eox byte> ::=              F7
     23. <sys common msg> ::=        <song position msg> |
                                     | <song select msg> |
                                     | <tune request>
     24. <tune request> ::=          F6
     25. <song position msg> ::=     <song position stat byte>
                                       <data pair>
     26. <song select msg> ::=       <song select stat byte>
                                       <data singlet>
     27. <song position stat byte>::=F2
     28. <song select stat byte> ::= F3

AUTHOR
======

   Sean M. Burke `sburke@cpan.org'  (Except the BNF - who knows who's
behind that.)

MIDI File Specification
***********************

NAME
====

   MIDI::Filespec - MIDI File Specification

DESCRIPTION
===========

   This is a POD version of a text file widely available on the Net.  The
copy I found came with this note:

   This document is Dave Oppenheim's current version of the MIDI file
specification, as sent to those who have participated in its development.
The consensus seems to be to submit this to the MIDI Manufacturers'
Association as version 1.0.  I apologize for any loss of clarity that
might have occurred in the conversion from a Microsoft Word document to
this pure text file.  I have removed some of the discussion about recent
changes to the specification in order to keep the file size reasonable.
-Doug Wyatt

   Moreover, these caveats are in order:

   * The file below is not everything you need to know about MIDI - not by
a long shot.  If you know MIDI-on-the-wire, this document tells you how to
encapsulate that data into files - and that's about all it tells you.  If
you need to know the semantics (or even syntax) of, for example,
key_after_touch, it's not in here.

   * In other words: the file below describes syntax, but is a bit thin on
semantics sometimes.

   * The file below is, in terms of computers and computer music, quite
vintage.  However, code built to this spec runs just fine on all of the
two-dozen or so MIDIs I pulled at random from various places on the Net
for testing.  The only thing I've found that's not in this spec is a
meta-event of the form "FF 21 01 00" that seems to occur often as the
first event in a track.  (I infer it means "start track", but I don't
know, so I've made no effort to deal with it other than to parse it as
`('raw_meta_event', 0, 33, "\x00")'.)  There may be other extensions
that've been made to the standard, and which are being used, but I've not
yet run into them.  Email me if you run across any.

   * The example C code in the section "4. Program Fragments and Example
MIDI Files" is not the optimal way to do "variable-length encoding" in
Perl; Perl supports this natively as the "w" format in packing and
unpacking.  See the source for `MIDI::Event' for examples.

Standard MIDI Files 0.06,  March 1, 1988
========================================

0: Introduction
===============

   This describes a proposed standard MIDI file format.  MIDI files
contain one or more MIDI streams, with time information for each event.
Song, sequence, and track structures, tempo and time signature
information, are all supported.  Track names and other descriptive
information may be stored with the MIDI data.  This format supports
multiple tracks and multiple sequences so that if the user of a program
which supports multiple tracks intends to move a file to another one, this
format can allow that to happen.

   This spec defines the 8-bit binary data stream used in the file.  The
data can be stored in a binary file, nibbleized, 7-bit-ized for efficient
MIDI transmission, converted to Hex ASCII, or translated symbolically to a
printable text file.  This spec addresses what's in the 8-bit stream.

1: Sequences, Tracks, Chunks:  File Block Structure
===================================================

   Sequence files are made up of chunks.  Each chunk has a 4-character
type and a 32-bit length, which is the number of bytes in the chunk.  On
the Macintosh, data is passed either in the data fork of a file, or on the
Clipboard.  (The file type on the Macintosh for a file in this format will
be "Midi".)  On any other computer, the data is simply the contents of the
file.  This structure allows future chunk types to be designed which may
easily be ignored if encountered by a program written before the chunk
type is introduced.  Your programs should expect alien chunks and treat
them as if they weren't there.

   This proposal defines two types of chunks:  a header chunk and a track
chunk.  A header chunk provides a minimal amount of information pertaining
to the entire MIDI file.  A track chunk contains a sequential stream of
MIDI data which may contain information for up to 16 MIDI channels.  The
concepts of multiple tracks, multiple MIDI outputs, patterns, sequences,
and songs may all be implemented using several track chunks.

   A MIDI file always starts with a header chunk, and is followed by one or
more track chunks.

     MThd  <length of header data>
     <header data>
     MTrk  <length of track data>
     <track data>
     MTrk  <length of track data>
     <track data>
     ...

Track Data Format (MTrk chunk type)
-----------------------------------

   The MTrk chunk type is where actual song data is stored.  It is simply a
stream of MIDI events (and non-MIDI events), preceded by delta-time values.

   Some numbers in MTrk chunks are represented in a form called a
variable-length quantity. These numbers are represented 7 bits per byte,
most significant bits first.  All bytes except the last have bit 7 set,
and the last byte has bit 7 clear.  If the number is between 0 and 127, it
is thus represented exactly as one byte.

   Here are some examples of numbers represented as variable-length
quantities:

     Number (hex)    Representation (hex)
     00000000        00
     00000040        40
     0000007F        7F
     00000080        81 00
     00002000        C0 00
     00003FFF        FF 7F
     00004000        81 80 00
     00100000        C0 80 00
     001FFFFF        FF FF 7F
     00200000        81 80 80 00
     08000000        C0 80 80 00
     0FFFFFFF        FF FF FF 7F

   The largest number which is allowed is 0FFFFFFF so that the
variable-length representation must fit in 32 bits in a routine to write
variable-length numbers.  Theoretically, larger numbers are possible, but
2 x 108 96ths of a beat at a fast tempo of 500 beats per minute is four
days, long enough for any delta-time!

   Here is the syntax of an MTrk chunk:

     <track data> = <MTrk event>+

     <MTrk event> = <delta-time> <event>

   <delta-time> is stored as a variable-length quantity.  It represents
the  amount of time before the following event.  If the first event in a
track occurs at the very beginning of a track, or if two events occur
simultaneously, a delta-time of zero is used.  Delta-times are always
present.  (Not storing delta-times of 0 requires at least two bytes for
any other value, and most delta-times aren't zero.)  Delta-time is in some
fraction of a beat (or a second, for recording a track with SMPTE times),
as specified in the header chunk.

     <event> = <MIDI event> | <sysex event> | <meta-event>

   <MIDI event> is any MIDI channel message.  Running status is used:
status bytes may be omitted after the first byte.  The first event in a
file must specify status.  Delta-time is not  considered an event itself:
it is an integral part of the specification.  Notice that running status
occurs across delta-times.

   <meta-event> specifies non-MIDI information useful to this format or to
sequencers, with this syntax:

     FF <type> <length> <bytes>

   All meta-events begin with FF, then have an event type byte (which is
always less than 128), and then have the length of the data stored as a
variable-length quantity, and then the data itself.  If there is no data,
the length is 0.  As with sysex events, running status is not allowed.  As
with chunks, future meta-events may be designed which may not be known to
existing programs, so programs must properly ignore meta-events which they
do not recognize, and indeed, should expect to see them.  New for 0.06:
programs must never ignore the length of a meta-event which they do
recognize, and they shouldn't be surprised if it's bigger than they
expected.  If so, they must ignore everything past what they know about.
However, they must not add anything of their own to the end of a
meta-event.

   <sysex event> is used to specify a MIDI system exclusive message, or as
an "escape" to specify any arbitrary bytes to be transmitted.
Unfortunately, some synthesizer manufacturers specify that their system
exclusive messages are to be transmitted as little packets.  Each packet
is only part of an entire syntactical system exclusive message, but the
times they are transmitted at are important.  Examples of this are the
bytes sent in a CZ patch dump, or the FB-01's "system exclusive mode" in
which microtonal data can be transmitted.  To be able to handle situations
like these, two forms of <sysex event> are provided:

     F0 <length> <bytes to be transmitted after F0>
     F7 <length> <all bytes to be transmitted>

   In both cases, <length> is stored as a variable-length quantity.  It is
equal to the number of bytes following it, not including itself or the
message type (F0 or F7), but all the bytes which follow, including any F7
at the end which is intended to be transmitted.  The first form, with the
F0 code, is used for syntactically complete system exclusive messages, or
the first packet an a series - that is, messages in which the F0 should be
transmitted.  The second form is used for the remainder of the packets
within a syntactic sysex message, which do not begin with F0.  Of course,
the F7 is not considered part of the system exclusive message.  Of course,
just as in MIDI, running status is not allowed, in this case because the
length is stored as a variable-length quantity which may or may not start
with bit 7 set.

   (New to 0.06)  A syntactic system exclusive message must always end with
an F7, even if the real-life device didn't send one, so that you know when
you've reached the end of an entire sysex message without looking ahead to
the next event in the MIDI file.  This principle is repeated and
illustrated in the paragraphs below.

   The vast majority of system exclusive messages will just use the F0
format.  For instance, the transmitted message F0 43 12 00 07 F7 would be
stored in a MIDI file as F0 05 43 12 00 07 F7.  As mentioned above, it is
required to include the F7 at the end so that the reader of the MIDI file
knows that it has read the entire message.

   For special situations when a single system exclusive message is split
up, with parts of it being transmitted at different times, such as in a
Casio CZ patch transfer, or the FB-01's "system exclusive mode", the F7
form of sysex event is used for each packet except the first.  None of the
packets would end with an F7 except the last one, which must end with an
F7.  There also must not be any transmittable MIDI events in- between the
packets of a multi-packet system exclusive message.  Here is an example:
suppose the bytes F0 43 12 00 were to be sent, followed by a 200-tick
delay, followed by the bytes  43 12 00 43 12 00, followed by a 100-tick
delay, followed by the bytes  43 12 00 F7, this would be in the MIDI File:

     F0 03 43 12 00
     81 48                                   200-tick delta-time
     F7 06 43 12 00 43 12 00
     64                                      100-tick delta-time
     F7 04 43 12 00 F7

   The F7 event may also be used as an "escape" to transmit any bytes
whatsoever, including real-time bytes, song pointer, or MIDI Time Code,
which are not permitted normally in this specification.  No effort should
be made to interpret the bytes used in this way.  Since a system exclusive
message is not being transmitted, it is not necessary or appropriate to
end the F7 event with an F7 in this case.

2. Header Chunk
===============

   The header chunk at the beginning of the file specifies some basic
information about the data in the file.  The data section contains three
16-bit words, stored high byte first (of course).  Here's the syntax of
the complete chunk:

     <chunk type> <length> <format> <ntrks> <division>

   As described above, <chunk type> is the four ASCII characters 'MThd';
<length> is a 32-bit representation of the number 6 (high byte first).
The first word, format, specifies the overall organization of the file.
Only three values of format are specified:

     0       the file contains a single multi-channel track
     1       the file contains one or more simultaneous tracks (or MIDI
              outputs) of a sequence
     2       the file contains one or more sequentially independent
              single-track patterns

   The next word, ntrks, is the number of track chunks in the file.  The
third word, division,  is the division of a quarter-note represented by
the delta-times in the file.  (If division is negative, it represents the
division of a second represented by the delta-times in the file, so that
the track can represent events occurring in actual time instead of
metrical time.  It is represented in the following way:  the upper byte is
one of the four values -24, -25, -29, or -30, corresponding to the four
standard SMPTE and MIDI time code formats, and represents the number of
frames per second.  The second byte (stored positive) is the resolution
within a frame:  typical values may be 4 (MIDI time code resolution), 8,
10, 80 (bit resolution), or 100.  This system allows exact specification
of time-code-based tracks, but also allows millisecond-based tracks by
specifying 25 frames/sec and a resolution of 40 units per frame.)

   Format 0, that is, one multi-channel track, is the most interchangeable
representation of data.  One application of MIDI files is a simple
single-track player in a program which needs to make synthesizers make
sounds, but which is primarily concerned with something else such as
mixers or sound effect boxes.  It is very desirable to be able to produce
such a format, even if your program is track-based, in order to work with
these simple programs.  On the other hand, perhaps someone will write a
format conversion from format 1 to format 0 which might be so easy to use
in some setting that it would save you the trouble of putting it into your
program.

   Programs which support several simultaneous tracks should be able to
save and read data in format 1, a vertically one-dimensional form, that
is, as a collection of tracks.  Programs which support several independent
patterns should be able to save and read data in format 2, a horizontally
one-dimensional form.  Providing these minimum capabilities will ensure
maximum interchangeability.

   MIDI files can express tempo and time signature, and they have been
chosen to do so for transferring tempo maps from one device to another.
For a format 0 file, the tempo will be scattered through the track and the
tempo map reader should ignore the intervening events; for a format 1
file, the tempo map must (starting in 0.04) be stored as the first track.
It is polite to a tempo map reader to offer your user the ability to make
a format 0 file with just the tempo, unless you can use format 1.

   All MIDI files should specify tempo and time signature.  If they don't,
the time signature is assumed to be 4/4, and the tempo 120 beats per
minute.  In format 0, these meta-events should occur at least at the
beginning of the single multi-channel track.  In format 1, these
meta-events should be contained in the first track.  In format 2, each of
the temporally independent patterns should contain at least initial time
signature and tempo information.

   We may decide to define other format IDs to support other structures.  A
program reading an unfamiliar format ID should return an error to the user
rather than trying to read further.

3. Meta-Events
==============

   A few meta-events are defined herein.  It is not required for every
program to support every meta-event.  Meta-events initially defined
include:

FF 00 02 ssss : Sequence Number
-------------------------------

   This optional event, which must occur at the beginning of a track,
before any nonzero delta-times, and before any transmittable MIDI events,
specifies the number of a sequence.  The number in this track corresponds
to the sequence number in the new Cue message discussed at the summer 1987
MMA meeting.  In a format 2 MIDI file, it is used to identify each
"pattern" so that a "song" sequence using the Cue message to refer to the
patterns.  If the ID numbers are omitted, the sequences' locations in
order in the file are used as defaults.  In a format 0 or 1 MIDI file,
which only contain one sequence, this number should be contained in the
first (or only) track.  If transfer of several multitrack sequences is
required, this must be done as a group of format 1 files, each with a
different sequence number.

FF 01 len text : Text Event
---------------------------

   Any amount of text describing anything.  It is a good idea to put a text
event right at the beginning of a track, with the name of the track, a
description of its intended orchestration, and any other information which
the user wants to put there.  Text events may also occur at other times in
a track, to be used as lyrics, or descriptions of cue points.  The text in
this event should be printable ASCII characters for maximum interchange.
However, other character codes using the high-order bit may be used for
interchange of files between different programs on the same computer which
supports an extended character set.  Programs on a computer which does not
support non-ASCII characters should ignore those characters.

   (New for 0.06 ).  Meta event types 01 through 0F are reserved for
various types of text events, each of which meets the specification of
text events(above) but is used for a different purpose:

FF 02 len text : Copyright Notice
---------------------------------

   Contains a copyright notice as printable ASCII text.  The notice should
contain the characters (C), the year of the copyright, and the owner of
the copyright.  If several pieces of music are in the same MIDI file, all
of the copyright notices should be placed together in this event so that
it will be at the beginning of the file.  This event should be the first
event in the first track chunk, at time 0.

FF 03 len text : Sequence/Track Name
------------------------------------

   If in a format 0 track, or the first track in a format 1 file, the name
of the sequence.  Otherwise, the name of the track.

FF 04 len text : Instrument Name
--------------------------------

   A description of the type of instrumentation to be used in that track.
May be used with the MIDI Prefix meta-event to specify which MIDI channel
the description applies to, or the channel may be specified as text in the
event itself.

FF 05 len text : Lyric
----------------------

   A lyric to be sung.  Generally, each syllable will be a separate lyric
event which begins at the event's time.

FF 06 len text : Marker
-----------------------

   Normally in a format 0 track, or the first track in a format 1 file.
The name of that point in the sequence, such as a rehearsal letter or
section name ("First Verse", etc.).

FF 07 len text : Cue Point
--------------------------

   A description of something happening on a film or video screen or stage
at that point in the musical score ("Car crashes into house", "curtain
opens", "she slaps his face", etc.)

FF 2F 00 : End of Track
-----------------------

   This event is not optional.  It is included so that an exact ending
point may be specified for the track, so that it has an exact length,
which is necessary for tracks which are looped or concatenated.

FF 51 03 tttttt : Set Tempo, in microseconds per MIDI quarter-note
------------------------------------------------------------------

   This event indicates a tempo change.  Another way of putting
"microseconds per quarter-note" is "24ths of a microsecond per MIDI
clock".  Representing tempos as time per beat instead of beat per time
allows absolutely exact long-term synchronization with a time-based sync
protocol such as SMPTE time code or MIDI time code.  This amount of
accuracy provided by this tempo resolution allows a four-minute piece at
120 beats per minute to be accurate within 500 usec at the end of the
piece.  Ideally, these events should only occur where MIDI clocks would be
located - this convention is intended to guarantee, or at least increase
the likelihood, of compatibility with other synchronization devices so
that a time signature/tempo map stored in this format may easily be
transferred to another device.

FF 54 05 hr mn se fr ff : SMPTE Offset
--------------------------------------

   (New in 0.06 - SMPTE Format specification) This event, if present,
designates the SMPTE time at which the track chunk is supposed to start.
It should be present at the beginning of the track, that is, before any
nonzero delta-times, and before any transmittable MIDI events.  The hour
must be encoded with the SMPTE format, just as it is in MIDI Time Code.
In a format 1 file, the SMPTE Offset must be stored with the tempo map,
and has no meaning in any of the other tracks.  The ff field contains
fractional frames, in 100ths of a frame, even in SMPTE-based tracks which
specify a different frame subdivision for delta-times.

FF 58 04 nn dd cc bb : Time Signature
-------------------------------------

   The time signature is expressed as four numbers.  nn and dd represent
the numerator and denominator of the time signature as it would be
notated.  The denominator is a negative power of two: 2 represents a
quarter-note, 3 represents an eighth-note, etc.  The cc parameter
expresses the number of MIDI clocks in a metronome click.  The bb
parameter expresses the number of notated 32nd-notes in a MIDI
quarter-note (24 MIDI Clocks).  This was added because there are already
multiple programs which allow the user to specify that what MIDI thinks of
as a quarter-note (24 clocks) is to be notated as, or related to in terms
of, something else.

   Therefore, the complete event for 6/8 time, where the metronome clicks
every three eighth-notes, but there are 24 clocks per quarter-note, 72 to
the bar, would be (in hex):

     FF 58 04 06 03 24 08

   That is, 6/8 time (8 is 2 to the 3rd power, so this is 06 03), 32 MIDI
clocks per dotted-quarter (24 hex!), and eight notated 32nd-notes per MIDI
quarter note.

     FF 59 02 sf mi  Key Signature
            sf = -7:  7 flats
            sf = -1:  1 flat
            sf = 0:  key of C
            sf = 1:  1 sharp
            sf = 7: 7 sharps

     mi = 0:  major key
     mi = 1:  minor key

FF 7F len data : Sequencer-Specific Meta-Event
----------------------------------------------

   Special requirements for particular sequencers may use this event type:
the first byte or bytes of data is a manufacturer ID.  However, as this
is an interchange format, growth of the spec proper is preferred to use of
this event type.  This type of event may be used by a sequencer which
elects to use this as its only file format; sequencers with their
established feature-specific formats should probably stick to the standard
features when using this format.

4. Program Fragments and Example MIDI Files
===========================================

   Here are some of the routines to read and write variable-length numbers
in MIDI Files.  These routines are in C, and use getc and putc, which read
and write single 8-bit characters from/to the files infile and outfile.

     WriteVarLen (value)
     register long value;
     {
             register long buffer;

     buffer = value & 0x7f;
     while ((value >>= 7) > 0)
     {
             buffer <<= 8;
             buffer |= 0x80;
             buffer += (value & 0x7f);
     }

     while (TRUE)
     {
             putc(buffer,outfile);
             if (buffer & 0x80)
                     buffer >>= 8;
             else
                     break;
     }
      }

     doubleword ReadVarLen ()
     {
             register doubleword value;
             register byte c;

     if ((value = getc(infile)) & 0x80)
     {
             value &= 0x7f;
             do
             {
                     value = (value << 7) + ((c = getc(infile)) & 0x7f);
             } while (c & 0x80);
     }
     return (value);
      }

   As an example, MIDI Files for the following excerpt are shown below.
First, a format 0 file is shown, with all information intermingled; then,
a format 1 file is shown with all data separated into four tracks: one for
tempo and time signature, and three for the notes.  A resolution of 96
"ticks" per quarter note is used.  A time signature of 4/4 and a tempo of
120, though implied, are explicitly stated.

   The contents of the MIDI stream represented by this example are broken
down here:

     Delta Time | Event Code | Other Bytes    |
     (decimal)  | (hex)      | (decimal)      | Comment
       0          FF 58        04 04 02 24 08   4 bytes: 4/4 time,
                                                   24 MIDI clocks/click,
                                                8 32nd notes/24 MIDI clocks
       0          FF 51        03 500000        3 bytes: 500,000 5sec per
                                                   quarter-note
       0          C0           5                Ch. 1, Program Change 5
       0          C0           5                Ch. 1, Program Change 5
       0          C1           46               Ch. 2, Program Change 46
       0          C2           70               Ch. 3, Program Change 70
       0          92           48  96           Ch. 3 Note On C2, forte
       0          92           60  96           Ch. 3 Note On C3, forte
      96          91           67  64           Ch. 2 Note On G3, mezzo-forte
      96          90           76  32           Ch. 1 Note On E4, piano
     192          82           48  64           Ch. 3 Note Off C2, standard
       0          82           60  64           Ch. 3 Note Off C3, standard
       0          81           67  64           Ch. 2 Note Off G3, standard
       0          80           76  64           Ch. 1 Note Off E4, standard
       0          FF 2F        00               Track End

   The entire format 0 MIDI file contents in hex follow.  First, the header
chunk:

     4D 54 68 64             MThd
     00 00 00 06             chunk length
     00 00                   format 0
     00 01                   one track
     00 60                   96 per quarter-note

   Then, the track chunk.  Its header, followed by the events (notice that
running status is used in places):

     4D 54 72 6B             MTrk
     00 00 00 3B             chunk length (59)

     Delta-time     Event                   Comments
            00      FF 58 04 04 02 18 08    time signature
            00      FF 51 03 07 A1 20       tempo
            00      C0 05
            00      C1 2E
            00      C2 46
            00      92 30 60
            00      3C 60                   running status
            60      91 43 40
            60      90 4C 20
            81 40   82 30 40                two-byte delta-time
            00      3C 40                   running status
            00      81 43 40
            00      80 4C 40
            00      FF 2F 00                end of track

   A format 1 representation of the file is slightly different.  Its header
chunk:

     4D 54 68 64             MThd
     00 00 00 06             chunk length
     00 01                   format 1
     00 04                   four tracks
     00 60                   96 per quarter-note

   First, the track chunk for the time signature/tempo track.  Its header,
followed by the events:

     4D 54 72 6B             MTrk
     00 00 00 14             chunk length (20)

     Delta-time     Event                   Comments
            00      FF 58 04 04 02 18 08    time signature
            00      FF 51 03 07 A1 20       tempo
            83 00   FF 2F 00                end of track

   Then, the track chunk for the first music track.  The MIDI convention
for note on/off running status is used in this example:

     4D 54 72 6B     MTrk
     00 00 00 10     chunk length (16)

     Delta-time     Event                   Comments
            00      C0 05
            81 40   90 4C 20
            81 40   4C 00                   Running status: note on, vel = 0
            00      FF 2F 00                end of track

   Then, the track chunk for the second music track:

     4D 54 72 6B             MTrk
     00 00 00 0F             chunk length (15)

     Delta-time     Event                   Comments
            00      C1 2E
            60      91 43 40
            82 20   43 00                   running status
            00      FF 2F 00                end of track

   Then, the track chunk for the third music track:

     4D 54 72 6B             MTrk
     00 00 00 15             chunk length (21)

     Delta-time     Event                   Comments
            00      C2 46
            00      92 30 60
            00      3C 60                   running status
            83 00   30 00                   two-byte delta-time, running status
            00      3C 00                   running status
            00      FF 2F 00                end of track

5. MIDI Transmission of MIDI Files
==================================

   Since it is inconvenient to exchange disks between different computers,
and since many computers which will use this format will have a MIDI
interface anyway, MIDI seems like a perfect way to send these files from
one computer to another.  And, while we're going through all the trouble
to make a way of sending MIDI Files, it would be nice if they could send
any files (like sampled sound files, text files, etc.)

Goals
-----

   The transmission protocol for MIDI files should be reasonably
efficient, should support fast transmission for computers which are
capable of it, and slower transmission for less powerful ones.  It should
not be impossible to convert a MIDI File to or from an arbitrary internal
representation on the fly as it is transmitted, but, as long as it is not
too difficult, it is very desirable to use a generic method so that any
file type could be accommodated.

   To make the protocol efficient, the MIDI transmission of these files
will take groups of seven 8-bit bytes and transmit them as eight 7-bit
MIDI data bytes.  This is certainly in the spirit of the rest of this
format (keep it small, because it's not that hard to do).  To accommodate
a wide range of transmission speeds, files will be transmitted in packets
with acknowledge - this allows data to be stored to disk as it is
received.  If the sender does not receive a response from a reader in a
certain amount of time, it can assume an open-loop situation, and then
just continue.

   The last edition of MIDI Files contained a specialized protocol for
sending just MIDI Files.  To meet a deadline, unfortunately I don't have
time right now to propose a new generalized protocol.  This will be done
within the next couple of months.  I would welcome any proposals anyone
else has, and would direct your attention to the proposal from Ralph Muha
of Kurzweil, available in a recent MMA bulletin, and also directly from
him.

functions and methods for MIDI opuses
*************************************

NAME
====

   MIDI::Opus - functions and methods for MIDI opuses

SYNOPSIS
========

     use MIDI; # uses MIDI::Opus et al
     foreach $one (@ARGV) {
       my $opus = MIDI::Opus->new({ 'from_file' => $one, 'no_parse' => 1 });
       print "$one has ", scalar( $opus->tracks ) " tracks\n";
     }
     exit;

DESCRIPTION
===========

   MIDI::Opus provides a constructor and methods for objects representing
a MIDI opus (AKA "song").  It is part of the MIDI suite.

   An opus object has three attributes: a format (0 for MIDI Format 0), a
tick parameter (parameter "division" in MIDI/Filespec),
and a list of tracks objects that are the real content of
that opus.

   Be aware that options specified for the encoding or decoding of an opus
may not be documented in *this* module's documentation, as they may be
(and, in fact, generally are) options just passed down to the
decoder/encoder in MIDI::Event - so see MIDI/Event, for
an explanation of most of them, actually.

CONSTRUCTOR AND METHODS
=======================

   MIDI::Opus provides...

the constructor MIDI::Opus->new({ ...options... })
     This returns a new opus object.  The options, which are optional, is
     an anonymous hash.  By default, you get a new format-0 opus with no
     tracks and a tick parameter of 96.  There are six recognized options:
     format, to set the MIDI format number (generally either 0 or 1) of
     the new object; `ticks', to set its ticks parameter; tracks, which
     sets the tracks of the new opus to the contents of the list-reference
     provided; `tracks_r', which is an exact synonym of tracks; from_file,
     which reads the opus from the given filespec; and `from_handle',
     which reads the opus from the the given filehandle reference (e.g.,
     `*STDIN{IO}'), after having called binmode() on that handle, if
     that's a problem.

     If you specify either from_file or `from_handle', you probably don't
     want to specify any of the other options - altho you may well want to
     specify options that'll get passed down to the decoder in
     MIDI::Events, such as 'include' => ['sysex_f0', 'sysex_f7'], just for
     example.

     Finally, the option `no_parse' can be used in conjuction with either
     from_file or `from_handle', and, if true, will block MTrk tracks'
     data from being parsed into MIDI events, and will leave them as track
     data (i.e., what you get from $track->data).  This is useful if you
     are just moving tracks around across files (or just counting them in
     files, as in the code in the Synopsis, above), without having to deal
     with any of the events in them.  (Actually, this option is implemented
     in code in MIDI::Track, but in a routine there that I've left
     undocumented, as you should access it only thru here.)

the method $new_opus = $opus->copy
     This duplicates the contents of the given opus, and returns the
     duplicate.  If you are unclear on why you may need this function,
     read the documentation for the copy method in MIDI/Track.

the method $opus->tracks( @tracks )
     Returns the list of tracks in the opus, possibly after having set it
     to @tracks, if specified and not empty.  (If you happen to want to set
     the list of tracks to an empty list, for whatever reason, you have to
     use "$opus->tracks_r([])".)

     In other words: $opus->tracks(@tracks) is how to set the list of
     tracks (assuming @tracks is not empty), and @tracks = $opus->tracks is
     how to read the list of tracks.

the method $opus->tracks_r( $tracks_r )
     Returns a reference to the list of tracks in the opus, possibly after
     having set it to $tracks_r, if specified.  "$tracks_r" can actually be
     any listref, whether it comes from a scalar as in `$some_tracks_r',
     or from something like `[@tracks]', or just plain old `\@tracks'

     Originally $opus->tracks was the only way to deal with tracks, but I
     added $opus->tracks_r to make possible 1) setting the list of tracks
     to (), for whatever that's worth, 2) parallel structure between
     MIDI::Opus::tracks[_r] and MIDI::Tracks::events[_r] and 3) so you can
     directly manipulate the opus's tracks, without having to copy the
     list of tracks back and forth.  This way, you can say:

          $tracks_r = $opus->tracks_r();
          @some_stuff = splice(@$tracks_r, 4, 6);

     But if you don't know how to deal with listrefs like that, that's OK,
     just use $opus->tracks.

the method $opus->ticks( $tick_parameter )
     Returns the tick parameter from $opus, after having set it to
     $tick_parameter, if provided.

the method $opus->format( $format )
     Returns the MIDI format for $opus, after having set it to $format, if
     provided.

the method $opus->dump( { ...options...} )
     Dumps the opus object as a bunch of text, for your perusal.  Options
     include: flat, if true, will have each event in the opus as a
     tab-delimited line - or as delimited with whatever you specify with
     option delimiter; otherwise, dump the data as Perl code that, if run,
     would/should reproduce the opus.  For concision's sake, the track data
     isn't dumped, unless you specify the option `dump_tracks' as true.

the method $opus->write_to_file('filespec', { ...options...} )
     Writes $opus as a MIDI file named by the given filespec.  The options
     hash is optional, and whatever you specify as options percolates down
     to the calls to MIDI::Event::encode - which see.  Currently this just
     opens the file, calls $opus->write_to_handle on the resulting
     filehandle, and closes the file.

the method $opus->write_to_handle(IOREF, { ...options...} )
     Writes $opus as a MIDI file to the IO handle you pass a reference to
     (example: `*STDOUT{IO}').  The options hash is optional, and whatever
     you specify as options percolates down to the calls to
     MIDI::Event::encode - which see.  Note that this is probably not what
     you'd want for sending music to `/dev/sequencer', since MIDI files
     are not MIDI-on-the-wire.

the method $opus->draw({ ...options...})
     This currently experimental method returns a new GD image object
     that's a graphic representation of the notes in the given opus.
     Options include: width - the width of the image in pixels (defaults
     to 600); bgcolor - a six-digit hex RGB representation of the
     background color for the image (defaults to $MIDI::Opus::BG_color,
     currently '000000'); `channel_colors' - a reference to a list of
     colors (in six-digit hex RGB) to use for representing notes on given
     channels.  Defaults to @MIDI::Opus::Channel_colors.  This list is a
     list of pairs of colors, such that: the first of a pair (color N*2)
     is the color for the first pixel in a note on channel N; and the
     second (color N*2 + 1) is the color for the remaining pixels of that
     note.  If you specify only enough colors for channels 0 to M, notes
     on a channels above M will use 'recycled' colors - they will be
     plotted with the color for channel "channel_number % M" (where % =
     the MOD operator).

     This means that if you specify

          channel_colors => ['00ffff','0000ff']

     then all the channels' notes will be plotted with an aqua pixel
     followed by blue ones; and if you specify

          channel_colors => ['00ffff','0000ff', 'ff00ff','ff0000']

     then all the *even* channels' notes will be plotted with an aqua
     pixel followed by blue ones, and all the *odd* channels' notes will
     be plotted with a purple pixel followed by red ones.

     As to what to do with the object you get back, you probably want
     something like:

          $im = $chachacha->draw;
          open(OUT, ">$gif_out"); binmode(OUT);
          print OUT $im->gif;
          close(OUT);

     Using this method will cause a die if it can't successfully `use GD'.

     I emphasise that draw is expermental, and, in any case, is only meant
     to be a crude hack.  Notably, it does not address well some basic
     problems: neither volume nor patch-selection (nor any notable aspects
     of the patch selected) are represented; pitch-wheel changes are not
     represented; percussion (whether on percussive patches or on channel
     10) is not specially represented, as it probably should be; notes
     overlapping are not represented at all well.

WHERE'S THE DESTRUCTOR?
=======================

   Because MIDI objects (whether opuses or tracks) do not contain any
circular data structures, you don't need to explicitly destroy them in
order to deallocate their memory.  Consider this code snippet:

     use MIDI;
     foreach $one (@ARGV) {
       my $opus = MIDI::Opus->new({ 'from_file' => $one, 'no_parse' => 1 });
       print "$one has ", scalar( $opus->tracks ) " tracks\n";
     }

   At the end of each iteration of the foreach loop, the variable $opus
goes away, along with its contents, a reference to the opus object.  Since
no other references to it exist (i.e., you didn't do anything like
push(@All_opuses,$opus) where @All_opuses is a global), the object is
automagically destroyed and its memory marked for recovery.

   If you wanted to explicitly free up the memory used by a given opus
object (and its tracks, if those tracks aren't used anywhere else) without
having to wait for it to pass out of scope, just replace it with a new
empty object:

     $opus = MIDI::Opus->new;

   or replace it with anything at all - or even just undef it:

     undef $opus;

   Of course, in the latter case, you can't then use $opus as an opus
object anymore, since it isn't one.

NOTE ON TICKS
=============

   If you want to use "negative" values for ticks (so says the spec: "If
division is negative, it represents the division of a second represented
by the delta-times in the file,[...]"), then it's up to you to figure out
how to represent that whole ball of wax so that when it gets pack()'d as
an "n", it comes out right.  I think it'll involve something like:

     $opus->ticks(  (unpack('C', pack('c', -25)) << 8) & 80  );

   for bit resolution (80) at 25 f/s.

   But I've never tested this.  Let me know if you get it working right,
OK?  If anyone *does* get it working right, and tells me how, I'll try to
support it natively.

NOTE ON WARN-ING AND DIE-ING
============================

   In the case of trying to parse a malformed MIDI file (which is not a
common thing, in my experience), this module (or MIDI::Track or
MIDI::Event) may warn() or die() (Actually, carp() or croak(), but it's
all the same in the end).  For this reason, you shouldn't use this suite
in a case where the script, well, can't warn or die - such as, for
example, in a CGI that scans for text events in a uploaded MIDI file that
may or may not be well-formed.  If this *is* the kind of task you or
someone you know may want to do, let me know and I'll consider some kind
of 'no_die' parameter in future releases.  (Or just trap the die in an
eval { } around your call to anything you think you could die.)

AUTHOR
======

   Sean M. Burke `sburke@cpan.org'

MIDI scores
***********

NAME
====

   MIDI::Score - MIDI scores

SYNOPSIS
========

     # it's a long story; see below

DESCRIPTION
===========

   This module provides functions to do with with MIDI scores.  It is used
as the basis for all the functions in MIDI::Simple.  (Incidentally,
MIDI::Opus's draw() method also uses some of the functions in here.)

   Whereas the events in a MIDI event structure are items whose timing is
expressed in delta-times, the timing of items in a score is expressed as
an absolute number of ticks from the track's start time.  Moreover, pairs
of 'note_on' and 'note_off' events in an event structure are abstracted
into a single 'note' item in a score structure.

   'note' takes the following form:

     ('note_on', I<start_time>, I<duration>, I<channel>, I<note>, I<velocity>)

   The problem that score structures are meant to solve is that 1) people
definitely don't think in delta-times - they think in absolute times or in
structures based on that (like 'time from start of measure'); 2) people
think in notes, not note_on and note_off events.

   So, given this event structure:

     ['text_event', 0, 'www.ely.anglican.org/parishes/camgsm/chimes.html'],
     ['text_event', 0, 'Lord through this hour/ be Thou our guide'],
     ['text_event', 0, 'so, by Thy power/ no foot shall slide'],
     ['patch_change', 0, 1, 8],
     ['note_on', 0, 1, 25, 96],
     ['note_off', 96, 0, 1, 0],
     ['note_on', 0, 1, 29, 96],
     ['note_off', 96, 0, 1, 0],
     ['note_on', 0, 1, 27, 96],
     ['note_off', 96, 0, 1, 0],
     ['note_on', 0, 1, 20, 96],
     ['note_off', 192, 0, 1, 0],
     ['note_on', 0, 1, 25, 96],
     ['note_off', 96, 0, 1, 0],
     ['note_on', 0, 1, 27, 96],
     ['note_off', 96, 0, 1, 0],
     ['note_on', 0, 1, 29, 96],
     ['note_off', 96, 0, 1, 0],
     ['note_on', 0, 1, 25, 96],
     ['note_off', 192, 0, 1, 0],
     ['note_on', 0, 1, 29, 96],
     ['note_off', 96, 0, 1, 0],
     ['note_on', 0, 1, 25, 96],
     ['note_off', 96, 0, 1, 0],
     ['note_on', 0, 1, 27, 96],
     ['note_off', 96, 0, 1, 0],
     ['note_on', 0, 1, 20, 96],
     ['note_off', 192, 0, 1, 0],
     ['note_on', 0, 1, 20, 96],
     ['note_off', 96, 0, 1, 0],
     ['note_on', 0, 1, 27, 96],
     ['note_off', 96, 0, 1, 0],
     ['note_on', 0, 1, 29, 96],
     ['note_off', 96, 0, 1, 0],
     ['note_on', 0, 1, 25, 96],
     ['note_off', 192, 0, 1, 0],

   here is the corresponding score sctructure:

     ['text_event', 0, 'www.ely.anglican.org/parishes/camgsm/chimes.html'],
     ['text_event', 0, 'Lord through this hour/ be Thou our guide'],
     ['text_event', 0, 'so, by Thy power/ no foot shall slide'],
     ['patch_change', 0, 1, 8],
     ['note', 0, 96, 1, 25, 96],
     ['note', 96, 96, 1, 29, 96],
     ['note', 192, 96, 1, 27, 96],
     ['note', 288, 192, 1, 20, 96],
     ['note', 480, 96, 1, 25, 96],
     ['note', 576, 96, 1, 27, 96],
     ['note', 672, 96, 1, 29, 96],
     ['note', 768, 192, 1, 25, 96],
     ['note', 960, 96, 1, 29, 96],
     ['note', 1056, 96, 1, 25, 96],
     ['note', 1152, 96, 1, 27, 96],
     ['note', 1248, 192, 1, 20, 96],
     ['note', 1440, 96, 1, 20, 96],
     ['note', 1536, 96, 1, 27, 96],
     ['note', 1632, 96, 1, 29, 96],
     ['note', 1728, 192, 1, 25, 96]

   Note also that scores aren't crucially ordered.  So this:

     ['note', 768, 192, 1, 25, 96],
     ['note', 960, 96, 1, 29, 96],
     ['note', 1056, 96, 1, 25, 96],

   means the same thing as:

     ['note', 960, 96, 1, 29, 96],
     ['note', 768, 192, 1, 25, 96],
     ['note', 1056, 96, 1, 25, 96],

   The only exception to this is in the case of things like:

     ['patch_change', 200,     2, 15],
     ['note',         200, 96, 2, 25, 96],

   where two (or more) score items happen *at the same time* and where one
affects the meaning of the other.

WHAT CAN BE IN A SCORE
======================

   Besides the new score structure item note (covered above), the possible
contents of a score structure can be summarized thus: Whatever can appear
in an event structure can appear in a score structure, save that its
second parameter denotes not a delta-time in ticks, but instead denotes
the absolute number of ticks from the start of the track.

   To avoid the long periphrase "items in a score structure", I will
occasionally refer to items in a score structure as "notes", whether or
not they are actually note commands.  This leaves "event" to unambiguously
denote items in an event structure.

   These, below, are all the items that can appear in a score.  This is
basically just a repetition of the table in MIDI/Event,
with starttime substituting for dtime - so refer to MIDI/Event,
for an explanation of what the data types (like "velocity" or
"pitch_wheel").  As far as order, the first items are generally the most
important:

('note', *starttime*, *duration*, channel, note, velocity)
('key_after_touch', *starttime*, channel, note, velocity)
('control_change', *starttime*, channel, *controller(0-127)*, *value(0-127)*)
('patch_change', *starttime*, channel, patch)
('channel_after_touch', *starttime*, channel, velocity)
('pitch_wheel_change', *starttime*, channel, pitch_wheel)
('set_sequence_number', *starttime*, sequence)
('text_event', *starttime*, text)
('copyright_text_event', *starttime*, text)
('track_name', *starttime*, text)
('instrument_name', *starttime*, text)
('lyric', *starttime*, text)
('marker', *starttime*, text)
('cue_point', *starttime*, text)

('text_event_08', *starttime*, text)

('text_event_09', *starttime*, text)

('text_event_0a', *starttime*, text)

('text_event_0b', *starttime*, text)

('text_event_0c', *starttime*, text)

('text_event_0d', *starttime*, text)

('text_event_0e', *starttime*, text)

('text_event_0f', *starttime*, text)
('end_track', *starttime*)
('set_tempo', *starttime*, tempo)
('smpte_offset', *starttime*, *hr*, *mn*, *se*, *fr*, ff)
('time_signature', *starttime*, *nn*, dd, cc, *bb*)
('key_signature', *starttime*, *sf*, *mi*)
('sequencer_specific', *starttime*, raw)
('raw_meta_event', *starttime*, command(0-255), raw)

('sysex_f0', *starttime*, raw)

('sysex_f7', *starttime*, raw)
('song_position', *starttime*)
('song_select', *starttime*, song_number)
('tune_request', *starttime*)
('raw_data', *starttime*, raw)
FUNCTIONS
=========

   This module provides these functions:

$score2_r = MIDI::Score::copy_structure($score_r)
     This takes a reference to a score structure, and returns a reference
     to a copy of it. Example usage:

          @new_score = @{ MIDI::Score::copy_structure( \@old_score ) };

$events_r = MIDI::Score::score_r_to_events_r( $score_r )
($events_r, $ticks) = MIDI::Score::score_r_to_events_r( $score_r )
     This takes a reference to a score structure, and converts it to an
     event structure, which it returns a reference to.  In list context,
     also returns a second value, a count of the number of ticks that
     structure takes to play (i.e., the end-time of the temporally last
     item).

$score2_r = MIDI::Score::sort_score_r( $score_r)
     This takes a reference to a score structure, and returns a reference
     to a sorted (by time) copy of it. Example usage:

          @sorted_score = @{ MIDI::Score::sort_score_r( \@old_score ) };

$score_r = MIDI::Score::events_r_to_score_r( $events_r )
($score_r, $ticks) = MIDI::Score::events_r_to_score_r( $events_r )
     This takes a reference to an event structure, converts it to a score
     structure, which it returns a reference to.  If called in list
     context, also returns a count of the number of ticks that structure
     takes to play (i.e., the end-time of the temporally last item).

$ticks = MIDI::Score::score_r_time( $score_r )
     This takes a reference to a score structure, and returns a count of
     the number of ticks that structure takes to play (i.e., the end-time
     of the temporally last item).

MIDI::Score::dump_score( $score_r )
     This dumps (via print) a text representation of the contents of the
     event structure you pass a reference to.

AUTHOR
======

   Sean M. Burke `sburke@cpan.org'

procedural/OOP interface for MIDI composition
*********************************************

NAME
====

   MIDI::Simple - procedural/OOP interface for MIDI composition

SYNOPSIS
========

     use MIDI::Simple;
     new_score;
     text_event 'http://www.ely.anglican.org/parishes/camgsm/chimes.html';
     text_event 'Lord through this hour/ be Thou our guide';
     text_event 'so, by Thy power/ no foot shall slide';
     set_tempo 500000;  # 1 qn => .5 seconds (500,000 microseconds)
     patch_change 1, 8;  # Patch 8 = Celesta

     noop c1, f, o2;  # Setup
     # Now play
     n qn, Cs2;   n F;   n Ds;  n hn, Gs_d1;
     n qn, Cs;    n Ds;  n F;   n hn, Cs;
     n qn, F;     n Cs;  n Ds;  n hn, Gs_d1;
     n qn, Gs_d1; n Ds;  n F;   n hn, Cs;

     write_score 'westmister_chimes.mid';

NOTE ON VERSION CHANGES
=======================

   I consider this module a late-stage beta.  Let me know if you run into
any problems, and feel free to suggest features.

   This module is somewhat incompatible with the MIDI::Simple versions
before .700.

   I think I've settled on (i.e., basically frozen) the basic interface
for this module, and will now hopefully only add functionality.

DESCRIPTION
===========

   This module sits on top of all the MIDI modules - notably MIDI::Score
(so you should skim MIDI/Score) - and is meant to serve
as a basic interface to them, for composition.  By composition, I mean
composing anew; you can use this module to add to or modify existing MIDI
files, but that functionality is to be considered expermental.

   This module provides two related but distinct bits of functionality: 1)
a mini-language (implemented as procedures that can double as methods) for
composing by adding notes to a score structure; and 2) simple functions
for reading and writing scores, specifically the scores you make with the
composition language.

   The fact that this module's interface is both procedural and
object-oriented makes it a definite two-headed beast.  The parts of the
guts of the source code are not for the faint of heart.

OBJECT STRUCTURE
----------------

   A MIDI::Simple object is a data structure with the following attributes:

Score
     This is a list of all the notes (each a listref) that constitute this
     one-track musical piece.  Scores are explained in MIDI/Score.
     You probably don't need to access the Score attribute
     directly, but be aware that this is where all the notes you make with
     n events go.

Time
     This is a non-negative integer expressing the start-time, in ticks
     from the start-time of the MIDI piece, that the next note pushed to
     the Score will have.

Channel
     This is a number in the range [0-15] that specifies the current
     default channel for note events.

Duration
     This is a non-negative (presumably nonzero) number expressing, in
     ticks, the current default length of note events, or rests.

Octave
     This is a number in the range [0-10], expressing what the current
     default octave number is.  This is used for figuring out exactly what
     note-pitch is meant by a relative note-pitch specification like "A".

Notes
     This is a list (presumably non-empty) of note-pitch specifications,
     *as note numbers* in the range [0-127].

Volume
     This is an integer in the range [0-127] expressing the current default
     volume for note events.

Tempo
     This is an integer expressing the number of ticks a quarter note
     occupies.  It's currently 96, and you shouldn't alter it unless you
     *really* know what you're doing.  If you want to control the tempo of
     a piece, use the set_tempo routine, instead.

Cookies
     This is a hash that can be used by user-defined object-methods for
     storing whatever they want.

   Each package that you call the procedure `new_score' from, has a
default MIDI::Simple object associated with it, and all the above
attributes are accessible as:

     @Score $Time $Channel $Duration $Octave
     @Notes $Volume $Tempo %Cookies

   (Although I doubt you'll use these from any package other than "main".)
If you don't know what a package is, don't worry about it.  Just consider
these attributes synonymous with the above-listed variables.  Just start
your programs with

     use MIDI::Simple;
     new_score;

   and you'll be fine.

Routine/Method/Procedure
------------------------

   MIDI::Simple provides some pure functions (i.e., things that take
input, and give a return value, and that's all they do), but what you're
mostly interested in its routines.  By "routine" I mean a subroutine that
you call, whether as a procedure or as a method, and that affects data
structures other than the return value.

   Here I'm using "procedure" to mean a routine you call like this:

     name(parameters...);
     # or, just maybe:
     name;

   (In technical terms, I mean a non-method subroutine that can have side
effects, and which may not even provide a useful return value.)  And I'm
using "method" to mean a routine you call like this:

     $object->name(parameters);

   So bear these terms in mind when you see routines below that act like
one, or the other, or both.

MAIN ROUTINES
-------------

   These are the most important routines:

new_score()  or  $obj = MIDI::Simple->new_score()
     As a procedure, this initializes the package's default object (Score,
     etc.).  As a method, this is a constructor, returning a new
     MIDI::Simple object.  Neither form takes any parameters.

n(...parameters...)  or  $obj->n(...parameters...)
     This uses the parameters given (and/or the state variables like
     Volume, Channel, Notes, etc) to add a new note to the Score - or
     several notes to the Score, if Notes has more than one element in it
     - or no notes at all, if Notes is empty list.

     Then it moves Time ahead as appropriate.  See the section "Parameters
     For n/r/noop", below.

r(...parameters...)  or  $obj->r(...parameters...)
     This is exactly like n, except it never pushes anything to Score, but
     moves ahead Time.  (In other words, there is no such thing as a
     rest-event; it's just a item during which there are no note-events
     playing.)

noop(...parameters...)  or  $obj->noop(...parameters...)
     This is exactly like n and r, except it never alters Score, and never
     changes Time.  It is meant to be used for setting the other state
     variables, i.e.: Channel, Duration, Octave, Volume, Notes.

Parameters for n/r/noop
-----------------------

   A parameter in an n, r, or noop call is meant to change an attribute
(AKA state variable), namely Channel, Duration, Octave, Volume, or Notes.

   Here are the kinds of parameters you can use in calls to n/r/noop:

   * A numeric volume parameter.  This has the form "v" followed by a
positive integer in the range 0 (completely inaudible?) to 127 (AS LOUD AS
POSSIBLE).  Example: "v90" sets Volume to 90.

   * An alphanumeric volume parameter.  This is a key from the hash
%MIDI::Simple::Volume.  Current legal values are "ppp", "pp", "p", "mp",
"mezzo" (or "m"), "mf", "f", "ff", and "fff".  Example: "ff" sets Volume
to 112.  (Note that "m" isn't a good bareword, so use "mezzo" instead, or
just always remember to use quotes around "m".)

   * A numeric channel parameter.  This has the form "c" followed by a
positive integer 0 to 15.  Example: "c2", to set Channel to 2.

   * A numeric *duration* parameter.  This has the form "d" followed by a
positive (presumably nonzero) integer.  Example: "d48", to set Duration to
48.

   * An alphabetic (or in theory, possibly alphanumeric) *duration*
parameter.  This is a key from the hash %MIDI::Simple::Length.  Current
legal values start with "wn", "hn", "qn", "en", "sn" for whole, half,
quarter, eighth, or sixteenth notes.  Add "d" to the beginning of any of
these to get "dotted..." (e.g., "dqn" for a dotted quarter note).  Add
"dd" to the beginning of any of that first list to get "double-dotted..."
(e.g., "ddqn" for a double-dotted quarter note).  Add "t" to the beginning
of any of that first list to get "triplet..."  (e.g., "tsn" for a triplet
sixteenth note - i.e. a note such that 3 of them add up to something as
long as one eighth note).  You may add to the contents of
%MIDI::Simple::Length to support whatever abbreviations you want, as long
as the parser can't mistake them for any other kind of n/r/noop parameter.

   * A numeric, absolute *octave* specification.  This has the form: an
"o" (lowercase oh), and then an integer in the range 0 to 10, representing
an octave 0 to 10.  The Octave attribute is used only in resolving
relative note specifications, as explained further below in this section.
(All absolute note specifications also set Octave to whatever octave they
occur in.)

   * A numeric, relative *octave* specification.  This has the form: "o_d"
("d" for down) or "o_u" ("u" for down), and then an integer.  This
increments, or decrements, Octave.  E.g., if Octave is 6, "o_d2" will
decrement Octave by 2, making it 4.  If this moves Octave below 0, it is
forced to 0.  Or if it moves Octave above 10, it is forced to 10.  (For
more information, see the section "Invalid or Out-of-Range Parameters to
n/r/noop", below.)

   * A numeric, absolute note specification.  This has the form: an
optional "n", and then an integer in the range 0 to 127, representing a
note ranging from C0 to G10.  The source to MIDI, has a useful
reference table showing the meanings of given note numbers.  Examples:
"n60", or "60", which each add a 60 to the list Notes.

   Since this is a kind of absolute note specification, it sets Octave to
whatever octave the given numeric note occurs in.  E.g., "n60" is "C5",
and therefore sets Octave to 5.

   The setting of the Notes list is a bit special, compared to how setting
the other attributes works.  If there are any note specifications in a
given parameter list for n, r, or noop, then all those specifications
together are assigned to Notes.

   If there are no note specifications in the parameter list for n, r, or
noop, then Notes isn't changed.  (But see the destription of "rest", at
the end of this section.)

   So this:

     n mf, n40, n47, n50;

   sets Volume to 80, and Notes to (40, 47, 50).  And it sets Octave,
first to 3 (since n40 is in octave 3), then to 3 again (since n47 = B3),
and then finally to 4 (since n50 = D4).

   Note that this is the same as:

     n n40, n47, n50, mf;

   The relative orders of parameters is *usually* irrelevant; but see the
section "Order of Parameters in a Call to n/r/noop", below.

   * An alphanumeric, absolute note specification.

   These have the form: a string denoting a note within the octave (as
determined by %MIDI::Simple::Note - see below, in the description of
alphanumeric, relative note specifications), and then a number denoting
the octave number (in the range 0-10).  Examples: "C3", "As4" or
"Asharp4", "Bf9" or "Bflat9".

   Since this is a kind of absolute note specification, it sets Octave to
whatever octave the given numeric note occurs in.  E.g., "C3" sets Octave
to 3, "As4" sets Octave to 4, and "Bflat9" sets Octave to 9.

   This:

     n E3, B3, D4, mf;

   does the same as this example of ours from before:

     n n40, n47, n50, mf;

   * An alphanumeric, relative note specification.

   These have the form: a string denoting a note within the octave (as
determined by %MIDI::Simple::Note), and then an optional parameter
"_u[number]" meaning "so many octaves up from the current octave" or
"_d[parameter]" meaning "so many octaves down from the current octave".

   Examples: "C", "As" or "Asharp", "Bflat" or "Bf", "C_d3", "As_d1" or
"Asharp_d1", "Bflat_u3" or "Bf_u3".

   In resolving what actual notes these kinds of specifications denote,
the current value of Octave is used.

   What's a legal for the first bit (before any optional octave up/down
specification) comes from the keys to the hash %MIDI::Simple::Note.  The
current acceptable values are:

     C                                 (maps to the value 0)
     Cs or Df or Csharp or Dflat       (maps to the value 1)
     D                                 (maps to the value 2)
     Ds or Ef or Dsharp or Eflat       (maps to the value 3)
     E                                 (maps to the value 4)
     F                                 (maps to the value 5)
     Fs or Gf or Fsharp or Gflat       (maps to the value 6)
     G                                 (maps to the value 7)
     Gs or Af or Gsharp or Aflat       (maps to the value 8)
     A                                 (maps to the value 9)
     As or Bf or Asharp or Bflat       (maps to the value 10)
     B                                 (maps to the value 11)

   (Note that these are based on the English names for these notes.  If
you prefer to add values to accomodate other strings denoting notes in the
octave, you may do so by adding to the hash %MIDI::Simple::Note like so:

     use MIDI::Simple;
     %MIDI::Simple::Note =
       (%MIDI::Simple::Note,  # keep all the old values
        'H' => 10,
        'Do' => 0,
        # ...etc...
       );

   But the values you add must not contain any characters outside the
range [A-Za-z\x80-\xFF]; and your new values must not look like anything
that could be any other kind of specification.  E.g., don't add "mf" or
"o3" to %MIDI::Simple::Note.)

   Consider that these bits of code all do the same thing:

     n E3, B3, D4, mf;       # way 1

     n E3, B,  D_u1, mf;     # way 2

     n o3, E, B,  D_u1, mf;  # way 3

     noop o3, mf;            # way 4
     n     E, B,  D_u1;

   or even

     n o3, E, B, o4, D, mf;       # way 5!

     n o6, E_d3, B_d3, D_d2, mf;  # way 6!

   If a "_d[number]" would refer to a note in an octave below 0, it is
forced into octave 0.  If a "_u[number]" would refer to a note in an
octave above 10, it is forced into octave 10.  E.g., if Octave is 8,
"G_u4" would resolve to the same as "G10" (not "G12" - as that's out of
range); if Octave is 2, "G_d4" would resolve to the same as "G0".  (For
more information, see the section "Invalid or Out-of-Range Parameters to
n/r/noop", below.)

   * The string "`rest'" acts as a sort of note specification - it sets
Notes to empty-list.  That way you can make a call to n actually make a
rest:

     n qn, G;    # makes a G quarter-note
     n hn, rest; # half-rest -- alters Notes, making it ()
     n C,G;      # half-note chord: simultaneous C and G
     r;          # half-rest -- DOESN'T alter Notes.
     n qn;       # quarter-note chord: simultaneous C and G
     n rest;     # quarter-rest
     n;          # another quarter-rest

   (If you can follow the above code, then you understand.)

   A "`rest'" that occurs in a parameter list with other note specs (e.g.,
"n qn, A, rest, G") has *no effect*, so don't do that.

Order of Parameters in a Call to n/r/noop
-----------------------------------------

   The order of parameters in calls to n/r/noop is not important except
insofar as the parameters change the Octave parameter, which may change
how some relative note specifications are resolved.  For example:

     noop o4, mf;
     n G, B, A3, C;

   is the same as "n mf, G4, B4, A3, C3".  But just move that "C" to the
start of the list:

     noop o4, mf;
     n C, G, B, A3;

   and you something different, equivalent to "n mf, C4, G4, B4, A3".

   But note that you can put the "mf" anywhere without changing anything.

   But *stylistically*, I strongly advise putting note parameters at the
end of the parameter list:

     n mf, c10, C, B;  # 1. good
     n C, B, mf, c10;  # 2. bad
     n C, mf, c10, B;  # 3. so bad!

   3 is particularly bad because an uninformed/inattentive reader may get
the impression that the C may be at a different volume and on a different
channel than the B.

   (Incidentally, "n C5,G5" and "n G5,C5" are the same for most purposes,
since the C and the G are played at the same time, and with the same
parameters (channel and volume); but actually they differ in which note
gets put in the Score first, and therefore which gets encoded first in the
MIDI file - but this makes no difference at all, unless you're
manipulating the note-items in Score or the MIDI events in a track.)

Invalid or Out-of-Range Parameters to n/r/noop
----------------------------------------------

   If a parameter in a call to n/r/noop is uninterpretable, Perl dies with
an error message to that effect.

   If a parameter in a call to n/r/noop has an out-of-range value (like
"o12" or "c19"), Perl dies with an error message to that effect.

   As somewhat of a merciful exception to this rule, if a parameter in a
call to n/r/noop is a relative specification (whether like "o_d3" or
"o_u3", or like "G_d3" or "G_u3") which happens to resolve to an
out-of-range value (like "G_d3" given an Octave value of 2), then Perl
will not die, but instead will silently try to bring that note back into
range, by forcing it up to octave 0 (if it would have been lower), or down
into 9 or 10 (if it would have been an octave higher than 10, or a note
higher than G10), as appropriate.

   (This becomes strange in that, given an Octave of 8, "G_u4" is forced
down to G10, but "A_u4" is forced down to an A9.  But that boundary has to
pop up someplace - it's just unfortunate that it's in the middle of octave
10.)

ATTRIBUTE METHODS
-----------------

   The object attributes discussed above are readable and writeable with
object methods.  For each attribute there is a read/write method, and a
read-only method that returns a reference to the attribute's value:

     Attribute ||  R/W-Method ||   RO-R-Method
     ----------++-------------++--------------------------------------
     Score     ||  Score      ||   Score_r      (returns a listref)
     Notes     ||  Notes      ||   Notes_r      (returns a listref)
     Time      ||  Time       ||   Time_r       (returns a scalar ref)
     Duration  ||  Duration   ||   Duration_r   (returns a scalar ref)
     Channel   ||  Channel    ||   Channel_r    (returns a scalar ref)
     Octave    ||  Octave     ||   Octave_r     (returns a scalar ref)
     Volume    ||  Volume     ||   Volume_r     (returns a scalar ref)
     Tempo     ||  Tempo      ||   Tempo_r      (returns a scalar ref)
     Cookies   ||  Cookies    ||   Cookies_r    (returns a hashref)

   To read any of the above via a R/W-method, call with no parameters,
e.g.:

     $notes = $obj->Notes;  # same as $obj->Notes()

   The above is the read-attribute ("get") form.

   To set the value, call with parameters:

     $obj->Notes(13,17,22);

   The above is the write-attribute ("put") form.  Incidentally, when used
in write-attribute form, the return value is the same as the parameters,
except for Score or Cookies.  (In those two cases, I've suppressed it for
efficiency's sake.)

   Alternately (and much more efficiently), you can use the read-only
reference methods to read or alter the above values;

     $notes_r = $obj->Notes_r;
     # to read:
     @old_notes = @$notes_r;
     # to write:
     @$notes_r = (13,17,22);

   And this is the only way to set Cookies, Notes, or Score to a (), like
so:

     $notes_r = $obj->Notes_r;
     @$notes_r = ();

   Since this:

     $obj->Notes;

   is just the read-format call, remember?

   Like all methods in this class, all the above-named attribute methods
double as procedures that act on the default object - in other words, you
can say:

     Volume 10;              # same as:  $Volume = 10;
     @score_copy = Score;    # same as:  @score_copy = @Score
     Score @new_score;       # same as:  @Score = @new_score;
     $score_ref = Score_r;   # same as:  $score_ref = \@Score
     Volume(Volume + 10)     # same as:  $Volume += 10

   But, stylistically, I suggest not using these procedures - just
directly access the variables instead.

MIDI EVENT ROUTINES
-------------------

   These routines, below, add a MIDI event to the Score, with a start-time
of Time.  Example:

     text_event "And now the bongos!";  # procedure use

     $obj->text_event "And now the bongos!";  # method use

   These are named after the MIDI events they add to the score, so see
MIDI/Event, for an explanation of what the data types
(like "velocity" or "pitch_wheel") mean.  I've reordered this list so that
what I guess are the most important ones are toward the top:

patch_change channel, patch;
key_after_touch channel, note, velocity;
channel_after_touch channel, velocity;
control_change channel, *controller(0-127)*, *value(0-127)*;
pitch_wheel_change channel, pitch_wheel;
set_tempo tempo;  (See the section on tempo, below.)
smpte_offset *hr*, *mn*, *se*, *fr*, ff;
time_signature *nn*, dd, cc, *bb*;
key_signature *sf*, *mi*;
text_event text;
copyright_text_event text;
track_name text;
instrument_name text;
lyric text;
set_sequence_number sequence;
marker text;
cue_point text;
sequencer_specific raw;

sysex_f0 raw;

sysex_f7 raw;
   And here's the ones I'll be surprised if anyone ever uses:

text_event_08 text;

text_event_09 text;

text_event_0a text;

text_event_0b text;

text_event_0c text;

text_event_0d text;

text_event_0e text;

text_event_0f text;
raw_meta_event command(0-255), raw;
song_position *starttime*;
song_select song_number;
tune_request *starttime*;
raw_data raw;
end_track *starttime*;
note *duration*, channel, note, velocity;
About Tempo
-----------

   The chart above shows that tempo is set with a method/procedure that
takes the form set_tempo(tempo), and MIDI/Event, says
that tempo is "microseconds, a value 0 to 16,777,215 (0x00FFFFFF)".  But
at the same time, you see that there's an attribute of the MIDI::Simple
object called "Tempo", which I've warned you to leave at the default value
of 96.  So you may wonder what the deal is.

   The "Tempo" attribute (AKA "Divisions") is an integer that specifies
the number of "ticks" per MIDI quarter note.  Ticks is just the notional
timing unit all MIDI events are expressed in terms of.  Calling it "Tempo"
is misleading, really; what you want to change to make your music go
faster or slower isn't that parameter, but instead the mapping of ticks to
actual time - and that is what set_tempo does.  Its one parameter is the
number of microseconds each quarter note should get.

   Suppose you wanted a tempo of 120 quarter notes per minute.  In terms
of microseconds per quarter note:

     set_tempo 500_000; # you can use _ like a thousands-separator comma

   In other words, this says to make each quarter note take up 500,000
microseconds, namely .5 seconds.  And there's 120 of those half-seconds to
the minute; so, 120 quarter notes to the minute.

   If you see a "[quarter note symbol] = 160" in a piece of sheet music,
and you want to figure out what number you need for the set_tempo, do:

     60_000_000 / 160  ... and you get:  375_000

   Therefore, you should call:

     set_tempo 375_000;

   So in other words, this general formula:

     set_tempo int(60_000_000 / $quarter_notes_per_minute);

   should do you fine.

   As to the Tempo/Duration parameter, leave it alone and just assume that
96 ticks-per-quarter-note is a universal constant, and you'll be happy.

   (You may wonder: Why 96?  As far as I've worked out, all purmutations
of the normal note lengths (whole, half, quarter, eighth, sixteenth, and
even thirty-second notes) and tripletting, dotting, or double-dotting,
times 96, all produce integers.  For example, if a quarter note is 96
ticks, then a double-dotted thirty-second note is 21 ticks (i.e., 1.75 *
1/8 * 96).  But that'd be a messy 10.5 if there were only 48 ticks to a
quarter note.  Now, if you wanted a quintuplet anywhere, you'd be out of
luck, since 96 isn't a factor of five.  It's actually 3 * (2 ** 5), i.e.,
three times two to the fifth.  If you really need quintuplets, then you
have my very special permission to mess with the Tempo attribute - I
suggest multiples of 96, e.g., 5 * 96.)

   (You may also have read in MIDI/Filespec, that
time_signature allows you to define an arbitrary mapping of your concept
of quarter note, to MIDI's concept of quarter note.  For your sanity and
mine, leave them the same, at a 1:1 mapping - i.e., with an '8' for
time_signature's last parameter, for "eight notated 32nd-notes per MIDI
quarter note".  And this is relevant only if you're calling time_signature
anyway, which is not necessarily a given.)

MORE ROUTINES
-------------

$opus = write_score *filespec*
$opus = $obj->write_score(*filespec*)
     Writes the score to the filespec (e.g, "../../samples/funk2.midi", or
     a variable containing that value), with the score's Ticks as its tick
     parameters (AKA "divisions").  Among other things, this function calls
     the function `make_opus', below, and if you capture the output of
     write_score, you'll get the opus created, if you want it for anything.
     (Also: you can also use a filehandle-reference instead of the
     filespec: `write_score *STDOUT{IO}'.)

read_score *filespec*
$obj = MIDI::Simple->read_score('foo.mid'))
     In the first case (a procedure call), does `new_score' to erase and
     initialize the object attributes (Score, Octave, etc), then reads from
     the file named.  The file named has to be a MIDI file with exactly one
     eventful track, or Perl dies.  And in the second case, read_score
     acts as a constructor method, returning a new object read from the
     file.

     Score, Ticks, and Time are all affected:

     Score is the event form of all the MIDI events in the MIDI file.
     (Note: *Seriously* deformed MIDI files may confuse the routine that
     turns MIDI events into a Score.)

     Ticks is set from the ticks setting (AKA "divisions") of the file.

     Time is set to the end time of the latest event in the file.

     (Also: you can also use a filehandle-reference instead of the
     filespec: `read_score *STDIN{IO}'.)

     If ever you have to make a Score out of a single track from a
     *multitrack* file, read the file into an $opus, and then consider
     something like:

          new_score;
          $opus = MIDI::Opus->new({ 'from_file' => "foo2.mid" });
          $track = ($opus->tracks)[2]; # get the third track

          ($score_r, $end_time) =
            MIDI::Score::events_r_to_score_r($track->events_r);

          $Ticks = $opus->ticks;
          @Score =  @$score_r;
          $Time = $end_time;

synch( LIST of coderefs )
$obj->synch( LIST of coderefs )
     LIST is a list of coderefs (whether as a series of anonymous subs, or
     as a list of items like `(\&foo, \&bar, \&baz)', or a mixture of
     both) that `synch' calls in order to add to the given object - which
     in the first form is the package's default object, and which in the
     second case is $obj.  What `synch' does is:

     * remember the initial value of Time, before calling any of the
     routines;

     * for each routine given, reset Time to what it was initially, call
     the routine, and then note what the value of Time is, after each call;

     * then, after having called all of the routines, set Time to whatever
     was the greatest (equals latest) value of Time that resulted from any
     of the calls to the routines.

     The coderefs are all called with one argument in `@_' - the object
     they are supposed to affect.  All these routines should/must therefore
     use method calls instead of procedure calls.  Here's an example usage
     of synch:

          my $measure = 0;
          my @phrases =(
            [ Cs, F,  Ds, Gs_d1 ], [Cs,    Ds, F, Cs],
            [ F,  Cs, Ds, Gs_d1 ], [Gs_d1, Ds, F, Cs]
          );

          for(1 .. 20) { synch(\&count, \&lalala); }

          sub count {
            my $it = $_[0];
            $it->r(wn); # whole rest
            # not just "r(wn)" -- we want a method, not a procedure!
            ++$measure;
          }

          sub lalala {
            my $it = $_[0];
            $it->noop(c1,mf,o3,qn); # setup
            my $phrase_number = ($measure + -1) % 4;
            my @phrase = @{$phrases[$phrase_number]};
            foreach my $note (@phrase) { $it->n($note); }
          }

$opus = make_opus  or  $opus = $obj->make_opus
     Makes an opus (a MIDI::Opus object) out of Score, setting the opus's
     tick parameter (AKA "divisions") to $ticks.  The opus is,
     incidentally, format 0, with one track.

dump_score  or  $obj->dump_score
     Dumps Score's contents, via print (so you can select() an output
     handle for it).  Currently this is in this somewhat uninspiring
     format:

          ['note', 0, 96, 1, 25, 96],
          ['note', 96, 96, 1, 29, 96],

     as it is (currently) just a call to &MIDI::Score::dump_score; but in
     the future I may (should?) make it output in n/r notation.  In the
     meantime I assume you'll use this, if at all, only for debugging
     purposes.

FUNCTIONS
---------

   These are subroutines that aren't methods and don't affect anything
(i.e., don't have "side effects") - they just take input and/or give
output.

interval LISTREF, LIST
     This takes a reference to a list of integers, and a list of note-pitch
     specifications (whether relative or absolute), and returns a list
     consisting of the given note specifications transposed by that many
     half-steps.  E.g.,

          @majors = interval [0,4,7], C, Bflat3;

     which returns the list `(C,E,G,Bf3,D4,F4)'.

     Items in LIST which aren't note specifications are passed thru
     unaltered.

note_map { BLOCK } LIST
     This is pretty much based on (or at least inspired by) the normal Perl
     map function, altho the syntax is a bit more restrictive (i.e., map
     can take the form `map {BLOCK} LIST' or `map(EXPR,LIST)' - the latter
     won't work with note_map).

     `note_map {BLOCK} (LIST)' evaluates the BLOCK for each element of
     LIST (locally setting $_ to each element's note-number value) and
     returns the list value composed of the results of each such
     evaluation.  Evaluates BLOCK in a list context, so each element of
     LIST may produce zero, one, or more elements in the returned value.
     Moreover, besides setting $_, note_map feeds BLOCK (which it sees as
     an anonymous subroutine) three parameters, which BLOCK can access in
     @_ :

          $_[0]  :  Same as $_.  I.e., The current note-specification,
                    as a note number.
                    This is the result of having fed the original note spec
                    (which you can see in $_[2]) to is_note_spec.

          $_[1]  :  The absoluteness flag for this note, from the
                    above-mentioned call to is_note_spec.
                    0 = it was relative (like 'C')
                    1 = it was absolute (whether as 'C4' or 'n41' or '41')

          $_[2] : the actual note specification from LIST, if you want
                    to access it for any reason.

     Incidentally, any items in LIST that aren't a note specification are
     passed thru unchanged - BLOCK isn't called on it.

     So, in other words, what note_map does, for each item in LIST, is:

     * It calls is_note_spec on it to test whether it's a note
     specification at all.  If it isn't, just passes it thru.  If it is,
     then note_map stores the note number and the absoluteness flag that
     is_note_spec returned, and...

     * It calls BLOCK, providing the note number in $_ and $_[0], the
     absoluteness flag in $_[1], and the original note specification in
     $_[2].  Stores the return value of calling BLOCK (in a list context of
     course) - this should be a list of note numbers.

     * For each element of the return value (which is actually free to be
     an empty list), converts it from a note number to whatever *kind* of
     specification the original note value was.  So, for each element, if
     the original was relative, note_map interprets the return value as a
     relative note number, and calls `number_to_relative' on it; if it was
     absolute, note_map will try to restore it to the correspondingly
     formatted absolute specification type.

     An example is, I hope, helpful:

     This:

          note_map { $_ - 3, $_ + 2 }  qw(Cs3 n42 50 Bf)

     returns this:

          ('Bf2', 'Ef3', 'n39', 'n44', '47', '52', 'G', 'C_u1')

     Or, to line things up:

          Cs3       n42       50      Bf
           |         |        |       |
                  /-----\   /-----\   /---\   /----\
                  Bf2 Ef3   n39 n44   47 52   G C_u1

     Now, of course, this is the same as what this:

          interval [-3, 2], qw(Cs3 n42 50 Bf)

     returns.  This is fitting, as interval, internally, is basically a
     simplified version of note_map.  But interval only lets you do
     unconditional transposition, whereas note_map lets you do anything at
     all.  For example:

          @note_specs = note_map { $funky_lookup_table{$_} }
                                 C, Gf;

     or

          @note_specs = note_map { $_ + int(rand(2)) }
                                 @stuff;

     note_map, like map, can seem confusing to beginning programmers (and
     many intermediate ones, too), but it is quite powerful.

number_to_absolute NUMBER
     This returns the absolute note specification (in the form "C5") that
     the MIDI note number in NUMBER represents.

     This is like looking up the note number in %MIDI::number2note - not
     exactly the same, but effectively the same.  See the source for more
     details.

the function number_to_relative NUMBER
     This returns the relative note specification that NUMBER represents.
     The idea of a numerical representation for relative note
     specifications was necessitated by interval and note_map - since
     without this, you couldn't meaningfully say, for example, interval
     [0,2] 'F'.  This should illustrate the concept:

          number_to_relative(-10)   =>   "D_d1"
          number_to_relative( -3)   =>   "A_d1"
          number_to_relative(  0)   =>   "C"
          number_to_relative(  5)   =>   "F"
          number_to_relative( 10)   =>   "Bf"
          number_to_relative( 19)   =>   "G_u1"
          number_to_relative( 40)   =>   "E_u3"

is_note_spec STRING
     If STRING is a note specification, `is_note_spec(STRING)' returns a
     list of two elements: first, a flag of whether the note specification
     is absolute (flag value 1) or relative (flag value 0); and second, a
     note number corresponding to that note specification.  If STRING is
     not a note specification, `is_note_spec(STRING)' returns an empty
     list (which in a boolean context is FALSE).

     Implementationally, is_note_spec just uses is_absolute_note_spec and
     is_relative_note_spec.

     Example usage:

          @note_details = is_note_spec($thing);
          if(@note_details) {
            ($absoluteness_flag, $note_num) = @note_details;
            ...stuff...
          } else {
            push @other_stuff, $thing;  # or whatever
          }

is_relative_note_spec STRING
     If STRING is an relative note specification, returns the note number
     for that specification as a one-element list (which in a boolean
     context is TRUE).  Returns empty-list (which in a boolean context is
     FALSE) if STRING is NOT a relative note specification.

     To just get the boolean value:

          print "Snorf!\n" unless is_relative_note_spec($note);

     But to actually get the note value:

          ($note_number) = is_relative_note_spec($note);

     Or consider this:

          @is_rel = is_relative_note_spec($note);
          if(@is_rel) {
            $note_number = $is_rel[0];
          } else {
            print "Snorf!\n";
          }

     (Author's note, two years later: all this business of returning lists
     of various sizes, with this and other functions in here, is basically
     a workaround for the fact that there's not really any such thing as a
     boolean context in Perl - at least, not as far as user-defined
     functions can see.  I now think I should have done this with just
     returning a single scalar value: a number (which could be 0!) if the
     input is a number, and undef/emptylist (`return;') if not - then, the
     user could test:

          # Hypothetical --
          # This fuction doesn't actually work this way:
          if(defined(my $note_val = is_relative_note_spec($string))) {
             ...do things with $note_val...
          } else {
             print "Hey, that's no note!\n";
          }

     However, I don't anticipate users actually using these messy functions
     often at all - I basically wrote these for internal use by
     MIDI::Simple, then I documented them on the off chance they *might*
     be of use to anyone else.)

is_absolute_note_spec STRING
     Just like is_relative_note_spec, but for absolute note specifications
     instead of relative ones.

Self() or $obj->Self();
     Presumably the second syntax is useless - it just returns $obj.  But
     the first syntax returns the current package's default object.

     Suppose you write a routine, `funkify', that does something-or-other
     to a given MIDI::Simple object.  You could write it so that acts on
     the current package's default object, which is fine - but, among
     other things, that means you can't call `funkify' from a sub you have
     `synch' call, since such routines should/must use only method calls.
     So let's say that, instead, you write `funkify' so that the first
     argument to it is the object to act on.  If the MIDI::Simple object
     you want it to act on is it `$sonata', you just say

          funkify($sonata)

     However, if you want it to act on the current package's default
     MIDI::Simple object, what to say?  Simply,

          $package_opus = Self;
          funkify($package_opus);

AUTHOR
======

   Sean M. Burke `sburke@cpan.org'

functions and methods for MIDI tracks
*************************************

NAME
====

   MIDI::Track - functions and methods for MIDI tracks

SYNOPSIS
========

     use MIDI; # ...which "use"s MIDI::Track et al
     $taco_track = MIDI::Track->new;
     $taco_track->events(
      ['text_event', 0, "I like tacos!"],
      ['note_on',    0, 4, 50, 96 ],
      ['note_off', 300, 4, 50, 96 ],
     );
     $opus = MIDI::Opus->new(
      {  'format' => 0,  'ticks' => 240,  'tracks' => [ $taco_track ] }
     );
       ...etc...

DESCRIPTION
===========

   MIDI::Track provides a constructor and methods for objects representing
a MIDI track.  It is part of the MIDI suite.

   MIDI tracks have, currently, three attributes: a type, events, and
data.  Almost all tracks you'll ever deal with are of type "MTrk", and so
this is the type by default.  Events are what make up an MTrk track.  If a
track is not of type MTrk, or is an unparsed MTrk, then it has (or better
have!) data.

   When an MTrk track is encoded, if there is data defined for it, that's
what's encoded (and "encoding data" means just passing it thru untouched).
Note that this happens even if the data defined is "" (but it won't
happen if the data is undef).  However, if there's no data defined for the
MTrk track (as is the general case), then the track's events are encoded,
via a call to `MIDI::Event::encode'.

   (If neither events not data are defined, it acts as a zero-length
track.)

   If a non-MTrk track is encoded, its data is encoded.  If there's no
data for it, it acts as a zero-length track.

   In other words, 1) events are meaningful only in an MTrk track, 2) you
probably don't want both data and events defined, and 3) 99.999% of the
time, just worry about events in MTrk tracks, because that's all you ever
want to deal with anyway.

CONSTRUCTOR AND METHODS
=======================

   MIDI::Track provides...

the constructor MIDI::Track->new({ ...options... })
     This returns a new track object.  By default, the track is of type
     MTrk, which is probably what you want.  The options, which are
     optional, is an anonymous hash.  There are four recognized options:
     data, which sets the data of the new track to the string provided;
     type, which sets the type of the new track to the string provided;
     events, which sets the events of the new track to the contents of the
     list-reference provided (i.e., a reference to a LoL - see
     Perllol (perl.info), for the skinny on LoLs); and `events_r',
     which is an exact synonym of events.

the method $new_track = $track->copy
     This duplicates the contents of the given track, and returns the
     duplicate.  If you are unclear on why you may need this function,
     consider:

          $funk  = MIDI::Opus->new({'from_file' => 'funk1.mid'});
          $samba = MIDI::Opus->new({'from_file' => 'samba1.mid'});

          $bass_track = ( $funk->tracks )[-1]; # last track
          push(@{ $samba->tracks_r }, $bass_track );
               # make it the last track

          &funk_it_up(  ( $funk->tracks )[-1]  );
               # modifies the last track of $funk
          &turn_it_out(  ( $samba->tracks )[-1]  );
               # modifies the last track of $samba

          $funk->write_to_file('funk2.mid');
          $samba->write_to_file('samba2.mid');
          exit;

     So you have your routines funk_it_up and turn_it_out, and they each
     modify the track they're applied to in some way.  But the problem is
     that the above code probably does not do what you want - because the
     last track-object of $funk and the last track-object of $samba are the
     *same object*.  An object, you may be surprised to learn, can be in
     different opuses at the same time - which is fine, except in cases
     like the above code.  That's where you need to do copy the object.
     Change the above code to read:

          push(@{ $samba->tracks_r }, $bass_track->copy );

     and what you want to happen, will.

     Incidentally, this potential need to copy also occurs with opuses (and
     in fact any reference-based data structure, altho opuses and tracks
     should cover almost all cases with MIDI stuff), which is why there's
     $opus->copy, for copying entire opuses.

     (If you happen to need to copy a single event, it's just $new =
     [@$old] ; and if you happen to need to copy an event structure (LoL)
     outside of a track for some reason, use MIDI::Event::copy_structure.)

the method $track->events( @events )
     Returns the list of events in the track, possibly after having set it
     to @events, if specified and not empty.  (If you happen to want to set
     the list of events to an empty list, for whatever reason, you have to
     use "$track->events_r([])".)

     In other words: $track->events(@events) is how to set the list of
     events (assuming @events is not empty), and @events = $track->events
     is how to read the list of events.

the method $track->events_r( $event_r )
     Returns a reference to the list of events in the track, possibly after
     having set it to $events_r, if specified.  Actually, "$events_r" can
     be any listref to a LoL, whether it comes from a scalar as in
     `$some_events_r', or from something like `[@events]', or just plain
     old `\@events'

     Originally $track->events was the only way to deal with events, but I
     added $track->events_r to make possible 1) setting the list of events
     to (), for whatever that's worth, and 2) so you can directly
     manipulate the track's events, without having to copy the list of
     events (which might be tens of thousands of elements long) back and
     forth.  This way, you can say:

          $events_r = $track->events_r();
          @some_stuff = splice(@$events_r, 4, 6);

     But if you don't know how to deal with listrefs outside of LoLs,
     that's OK, just use $track->events.

the method $track->type( 'MFoo' )
     Returns the type of $track, after having set it to 'MFoo', if
     provided.  You probably won't ever need to use this method, other
     than in a context like:

          if( $track->type eq 'MTrk' ) { # The usual case
            give_up_the_funk($track);
          } # Else just keep on walkin'!

     Track types must be 4 bytes long; see MIDI/Filespec,
     for details.

the method $track->data( $kooky_binary_data )
     Returns the data from $track, after having set it to
     $kooky_binary_data, if provided - even if it's zero-length!  You
     probably won't ever need to use this method.  For your information,
     $track->data(undef) is how to undefine the data for a track.

the method $track->new_event('event', ...parameters... )
     This adds the event ('event', ...parameters...) to the end of the
     event list for $track.  It's just sugar for:

          push( @{$this_track->events_r}, [ 'event', ...params... ] )

     If you want anything other than the equivalent of that, like some
     kinda splice(), then do it yourself with $track->events_r or
     $track->events.

the method $track->dump({ ...options... })
     This dumps the track's contents for your inspection.  The dump format
     is code that looks like Perlcode you'd use to recreate that track.
     This routine outputs with just print, so you can use select to change
     where that'll go.  I intended this to be just an internal routine for
     use only by the method MIDI::Opus::dump, but I figure it might be
     useful to you, if you need te dump the code for just a given track.
     Read the source if you really need to know how this works.

AUTHOR
======

   Sean M. Burke `sburke@cpan.org'

Encoding and decoding of base64 strings
***************************************

NAME
====

   MIME::Base64 - Encoding and decoding of base64 strings

SYNOPSIS
========

     use MIME::Base64;

     $encoded = encode_base64('Aladdin:open sesame');
     $decoded = decode_base64($encoded);

DESCRIPTION
===========

   This module provides functions to encode and decode strings into the
Base64 encoding specified in RFC 2045 - *MIME (Multipurpose Internet Mail
Extensions)*. The Base64 encoding is designed to represent arbitrary
sequences of octets in a form that need not be humanly readable. A
65-character subset ([A-Za-z0-9+/=]) of US-ASCII is used, enabling 6 bits
to be represented per printable character.

   The following functions are provided:

encode_base64($str, [$eol])
     Encode data by calling the encode_base64() function.  The first
     argument is the string to encode.  The second argument is the line
     ending sequence to use (it is optional and defaults to `"\n"').  The
     returned encoded string is broken into lines of no more than 76
     characters each and it will end with $eol unless it is empty.  Pass an
     empty string as second argument if you do not want the encoded string
     broken into lines.

decode_base64($str)
     Decode a base64 string by calling the decode_base64() function.  This
     function takes a single argument which is the string to decode and
     returns the decoded data.

     Any character not part of the 65-character base64 subset set is
     silently ignored.  Characters occuring after a '=' padding character
     are never decoded.

     If the length of the string to decode (after ignoring non-base64
     chars) is not a multiple of 4 or padding occurs too ealy, then a
     warning is generated if perl is running under -w.

   If you prefer not to import these routines into your namespace you can
call them as:

     use MIME::Base64 ();
     $encoded = MIME::Base64::encode($decoded);
     $decoded = MIME::Base64::decode($encoded);

DIAGNOSTICS
===========

   The following warnings might be generated if perl is invoked with the
-w switch:

Premature end of base64 data
     The number of characters to decode is not a multiple of 4.  Legal
     base64 data should be padded with one or two "=" characters to make
     its length a multiple of 4.  The decoded result will anyway be as if
     the padding was there.

Premature padding of base64 data
     The '=' padding character occurs as the first or second character in
     a base64 quartet.

EXAMPLES
========

   If you want to encode a large file, you should encode it in chunks that
are a multiple of 57 bytes.  This ensures that the base64 lines line up
and that you do not end up with padding in the middle. 57 bytes of data
fills one complete base64 line (76 == 57*4/3):

     use MIME::Base64 qw(encode_base64);

     open(FILE, "/var/log/wtmp") or die "$!";
     while (read(FILE, $buf, 60*57)) {
         print encode_base64($buf);
     }

   or if you know you have enough memory

     use MIME::Base64 qw(encode_base64);
     local($/) = undef;  # slurp
     print encode_base64(<STDIN>);

   The same approach as a command line:

     perl -MMIME::Base64 -0777 -ne 'print encode_base64($_)' <file

   Decoding does not need slurp mode if all the lines contains a multiple
of 4 base64 chars:

     perl -MMIME::Base64 -ne 'print decode_base64($_)' <file

COPYRIGHT
=========

   Copyright 1995-1999, 2001 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Distantly based on LWP::Base64 written by Martijn Koster
<m.koster@nexor.co.uk> and Joerg Reichelt <j.reichelt@nexor.co.uk> and
code posted to comp.lang.perl <3pd2lp$6gf@wsinti07.win.tue.nl> by Hans
Mulder <hansm@wsinti07.win.tue.nl>

   The XS implementation use code from metamail.  Copyright 1991 Bell
Communications Research, Inc. (Bellcore)

the body of a MIME message
**************************

NAME
====

   MIME::Body - the body of a MIME message

SYNOPSIS
========

   Before reading further, you should see MIME/Tools, to
make sure that you understand where this module fits into the grand scheme
of things.  Go on, do it now.  I'll wait.

   Ready?  Ok...

Obtaining bodies
----------------

     ### Get the bodyhandle of a MIME::Entity object:
     $body = $entity->bodyhandle;

     ### Create a body which stores data in a disk file:
     $body = new MIME::Body::File "/path/to/file";

     ### Create a body which stores data in an in-core array:
     $body = new MIME::Body::InCore \@strings;

Opening, closing, and using IO handles
--------------------------------------

     ### Write data to the body:
     $IO = $body->open("w")      || die "open body: $!";
     $IO->print($message);
     $IO->close                  || die "close I/O handle: $!";

     ### Read data from the body (in this case, line by line):
     $IO = $body->open("r")      || die "open body: $!";
     while (defined($_ = $IO->getline)) {
         ### do stuff
     }
     $IO->close                  || die "close I/O handle: $!";

Other I/O
---------

     ### Dump the ENCODED body data to a filehandle:
     $body->print(\*STDOUT);

     ### Slurp all the UNENCODED data in, and put it in a scalar:
     $string = $body->as_string;

     ### Slurp all the UNENCODED data in, and put it in an array of lines:
     @lines = $body->as_lines;

Working directly with paths to underlying files
-----------------------------------------------

     ### Where's the data?
     if (defined($body->path)) {   ### data is on disk:
         print "data is stored externally, in ", $body->path;
     }
     else {                        ### data is in core:
         print "data is already in core, and is...\n", $body->as_string;
     }

     ### Get rid of anything on disk:
     $body->purge;

DESCRIPTION
===========

   MIME messages can be very long (e.g., tar files, MPEGs, etc.) or very
short (short textual notes, as in ordinary mail).  Long messages are best
stored in files, while short ones are perhaps best stored in core.

   This class is an attempt to define a common interface for objects which
contain message data, regardless of how the data is physically stored.
The lifespan of a "body" object usually looks like this:

  1. *Body object is created by a MIME::Parser during parsing.* It's at
     this point that the actual MIME::Body subclass is chosen, and new()
     is invoked.  (For example: if the body data is going to a file, then
     it is at this point that the class MIME::Body::File, and the
     filename, is chosen).

  2. *Data is written to the body* (usually by the MIME parser) like this:
     The body is opened for writing, via `open("w")'.  This will trash any
     previous contents, and return an "I/O handle" opened for writing.
     Data is written to this I/O handle, via print().  Then the I/O handle
     is closed, via close().

  3. *Data is read from the body* (usually by the user application) like
     this: The body is opened for reading by a user application, via
     `open("r")'.  This will return an "I/O handle" opened for reading.
     Data is read from the I/O handle, via read(), getline(), or
     getlines().  Then the I/O handle is closed, via close().

  4. *Body object is destructed.*

        You can write your own subclasses, as long as they follow the
interface described below.  Implementers of subclasses should assume that
steps 2 and 3 may be repeated any number of times, and in different orders
(e.g., 1-2-2-3-2-3-3-3-3-3-2-4).

   In any case, once a MIME::Body has been created, you ask to open it for
reading or writing, which gets you an "i/o handle": you then use the same
mechanisms for reading from or writing to that handle, no matter what
class it is.

   Beware: unless you know for certain what kind of body you have, you
should not assume that the body has an underlying filehandle.

PUBLIC INTERFACE
================

new ARGS...
     *Class method, constructor.* Create a new body.  Any ARGS are sent to
     init().

init ARGS...
     *Instance method, abstract, initiallizer.* This is called
     automatically by new(), with the arguments given to new().  The
     arguments are optional, and entirely up to the subclass.  The default
     method does nothing,

as_lines
     *Instance method.* Return the contents of the body as an array of
     lines (each terminated by a newline, with the possible exception of
     the final one).  Returns empty on failure (NB: indistinguishable from
     an empty body!).

     Note: the default method gets the data via repeated getline() calls;
     your subclass might wish to override this.

as_string
     *Instance method.* Return the body data as a string (slurping it into
     core if necessary).  Best not to do this unless you're *sure* that
     the body is reasonably small!  Returns empty string for an empty
     body, and undef on failure.

     Note: the default method uses print(), which gets the data via
     repeated read() calls; your subclass might wish to override this.

binmode [ONOFF]
     *Instance method.* With argument, flags whether or not open() should
     return an I/O handle which has binmode() activated.  With no
     argument, just returns the current value.

dup
     *Instance method.* Duplicate the bodyhandle.

     *Beware:* external data in bodyhandles is not copied to new files!
     Changing the data in one body's data file, or purging that body,
     *will* affect its duplicate.  Bodies with in-core data probably need
     not worry.

open READWRITE
     *Instance method, abstract.* This should do whatever is necessary to
     open the body for either writing (if READWRITE is "w") or reading (if
     mode is "r").

     This method is expected to return an "I/O handle" object on success,
     and undef on error.  An I/O handle can be any object that supports a
     small set of standard methods for reading/writing data.  See the
     IO::Handle class for an example.

path [PATH]
     *Instance method.* If you're storing the body data externally (e.g.,
     in a disk file), you'll want to give applications the ability to get
     at that data, for cleanup.  This method should return the path to the
     data, or undef if there is none.

     Where appropriate, the path should be a simple string, like a
     filename.  With argument, sets the PATH, which should be undef if
     there is none.

print FILEHANDLE
     *Instance method.* Output the body data to the given filehandle, or
     to the currently-selected one if none is given.

purge
     *Instance method, abstract.* Remove any data which resides external
     to the program (e.g., in disk files).  Immediately after a purge(),
     the path() should return undef to indicate that the external data is
     no longer available.

SUBCLASSES
==========

   The following built-in classes are provided:

     Body                 Stores body     When open()ed,
     class:               data in:        returns:
     --------------------------------------------------------
     MIME::Body::File     disk file       IO::Handle
     MIME::Body::Scalar   scalar          IO::Scalar
     MIME::Body::InCore   scalar array    IO::ScalarArray

MIME::Body::File
----------------

   A body class that stores the data in a disk file.  The I/O handle is a
wrapped filehandle.  Invoke the constructor as:

     $body = new MIME::Body::File "/path/to/file";

   In this case, the path() method would return the given path, so you
*could* say:

     if (defined($body->path)) {
     	open BODY, $body->path or die "open: $!";
     	while (<BODY>) {
     	    ### do stuff
         }
     	close BODY;
     }

   But you're best off not doing this.

MIME::Body::Scalar
------------------

   A body class that stores the data in-core, in a simple scalar.  Invoke
the constructor as:

     $body = new MIME::Body::Scalar \$string;

   A single scalar argument sets the body to that value, exactly as though
you'd opened for the body for writing, written the value, and closed the
body again:

     $body = new MIME::Body::Scalar "Line 1\nLine 2\nLine 3";

   A single array reference sets the body to the result of joining all the
elements of that array together:

     $body = new MIME::Body::Scalar ["Line 1\n",
                                     "Line 2\n",
                                     "Line 3"];

   Uses *IO::Scalar* as the I/O handle.

MIME::Body::InCore
------------------

   A body class that stores the data in-core.  Invoke the constructor as:

     $body = new MIME::Body::InCore \$string;
     $body = new MIME::Body::InCore  $string;
     $body = new MIME::Body::InCore \@stringarray

   A simple scalar argument sets the body to that value, exactly as though
you'd opened for the body for writing, written the value, and closed the
body again:

   $body = new MIME::Body::InCore "Line 1\nLine 2\nLine 3";

   A single array reference sets the body to the concatenation of all
scalars that it holds:

     $body = new MIME::Body::InCore ["Line 1\n",
                                     "Line 2\n",
                                     "Line 3"];

   Uses *IO::ScalarArray* as the I/O handle.

Defining your own subclasses
----------------------------

   So you're not happy with files and scalar-arrays?  No problem: just
define your own MIME::Body subclass, and make a subclass of MIME::Parser
or MIME::ParserBase which returns an instance of your body class whenever
appropriate in the `new_body_for(head)' method.

   Your "body" class must inherit from MIME::Body (or some subclass of it),
and it must either provide (or inherit the default for) the following
methods...

   The default inherited method *should suffice* for all these:

     new
     binmode [ONOFF]
     path

   The default inherited method *may suffice* for these, but perhaps
there's a better implementation for your subclass.

     init ARGS...
     as_lines
     as_string
     dup
     print
     purge

   The default inherited method *will probably not suffice* for these:

     open

NOTES
=====

   One reason I didn't just use FileHandle or IO::Handle objects for
message bodies was that I wanted a "body" object to be a form of completely
encapsulated program-persistent storage; that is, I wanted users to be
able to write code like this...

     ### Get body handle from this MIME message, and read its data:
     $body = $entity->bodyhandle;
     $IO = $body->open("r");
     while (defined($_ = $IO->getline)) {
         print STDOUT $_;
     }
     $IO->close;

   ...without requiring that they know anything more about how the $body
object is actually storing its data (disk file, scalar variable, array
variable, or whatever).

   Storing the body of each MIME message in a persistently-open IO::Handle
was a possibility, but it seemed like a bad idea, considering that a
single multipart MIME message could easily suck up all the available file
descriptors on some systems.  This risk increases if the user application
is processing more than one MIME entity at a time.

AUTHOR
======

   Eryq (`eryq@zeegee.com'), ZeeGee Software Inc (`http://www.zeegee.com').

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

   Thanks to Achim Bohnet for suggesting that MIME::Parser not be
restricted to the use of FileHandles.

VERSION
=======

   $Revision: 5.403 $ $Date: 2000/11/04 19:54:46 $

an object for decoding the body part of a MIME stream
*****************************************************

NAME
====

   MIME::Decoder - an object for decoding the body part of a MIME stream

SYNOPSIS
========

   Before reading further, you should see MIME/Tools, to
make sure that you understand where this module fits into the grand scheme
of things.  Go on, do it now.  I'll wait.

   Ready?  Ok...

Decoding a data stream
----------------------

   Here's a simple filter program to read quoted-printable data from STDIN
(until EOF) and write the decoded data to STDOUT:

     use MIME::Decoder;

     $decoder = new MIME::Decoder 'quoted-printable' or die "unsupported";
     $decoder->decode(\*STDIN, \*STDOUT);

Encoding a data stream
----------------------

   Here's a simple filter program to read binary data from STDIN (until
EOF) and write base64-encoded data to STDOUT:

     use MIME::Decoder;

     $decoder = new MIME::Decoder 'base64' or die "unsupported";
     $decoder->encode(\*STDIN, \*STDOUT);

Non-standard encodings
----------------------

   You can *write and install* your own decoders so that MIME::Decoder
will know about them:

     use MyBase64Decoder;

     install MyBase64Decoder 'base64';

   You can also test if a given encoding is supported:

     if (supported MIME::Decoder 'x-uuencode') {
         ### we can uuencode!
     }

DESCRIPTION
===========

   This abstract class, and its private concrete subclasses (see below)
provide an OO front end to the actions of...

   * Decoding a MIME-encoded stream

   * Encoding a raw data stream into a MIME-encoded stream.

   The constructor for MIME::Decoder takes the name of an encoding
(base64, 7bit, etc.), and returns an instance of a *subclass* of
MIME::Decoder whose `decode()' method will perform the appropriate
decoding action, and whose encode() method will perform the appropriate
encoding action.

PUBLIC INTERFACE
================

Standard interface
------------------

   If all you are doing is using this class, here's all you'll need...

new ENCODING
     *Class method, constructor.* Create and return a new decoder object
     which can handle the given ENCODING.

          my $decoder = new MIME::Decoder "7bit";

     Returns the undefined value if no known decoders are appropriate.

best ENCODING
     *Class method, constructor.* Exactly like new(), except that this
     defaults any unsupported encoding to "binary", after raising a
     suitable warning (it's a fatal error if there's no binary decoder).

          my $decoder = best MIME::Decoder "x-gzip64";

     Will either return a decoder, or a raise a fatal exception.

decode INSTREAM,OUTSTREAM
     *Instance method.* Decode the document waiting in the input handle
     INSTREAM, writing the decoded information to the output handle
     OUTSTREAM.

     Read the section in this document on I/O handles for more information
     about the arguments.  Note that you can still supply old-style
     unblessed filehandles for INSTREAM and OUTSTREAM.

     Returns true on success, throws exception on failure.

encode INSTREAM,OUTSTREAM
     *Instance method.* Encode the document waiting in the input
     filehandle INSTREAM, writing the encoded information to the output
     stream OUTSTREAM.

     Read the section in this document on I/O handles for more information
     about the arguments.  Note that you can still supply old-style
     unblessed filehandles for INSTREAM and OUTSTREAM.

     Returns true on success, throws exception on failure.

encoding
     *Instance method.* Return the encoding that this object was created
     to handle, coerced to all lowercase (e.g., `"base64"').

head [HEAD]
     *Instance method.* Completely optional: some decoders need to know a
     little about the file they are encoding/decoding; e.g., x-uu likes to
     have the filename.  The HEAD is any object which responds to messages
     like:

          $head->mime_attr('content-disposition.filename');

supported [ENCODING]
     *Class method.* With one arg (an ENCODING name), returns truth if
     that encoding is currently handled, and falsity otherwise.  The
     ENCODING will be automatically coerced to lowercase:

          if (supported MIME::Decoder '7BIT') {
              ### yes, we can handle it...
          }
          else {
              ### drop back six and punt...
          }

     With no args, returns a reference to a hash of all available decoders,
     where the key is the encoding name (all lowercase, like '7bit'), and
     the value is true (it happens to be the name of the class that
     handles the decoding, but you probably shouldn't rely on that).  You
     may safely modify this hash; it will not change the way the module
     performs its lookups.  Only install can do that.

     *Thanks to Achim Bohnet for suggesting this method.*

Subclass interface
------------------

   If you are writing (or installing) a new decoder subclass, there are
some other methods you'll need to know about:

decode_it INSTREAM,OUTSTREAM
     *Abstract instance method.* The back-end of the decode method.  It
     takes an input handle opened for reading (INSTREAM), and an output
     handle opened for writing (OUTSTREAM).

     If you are writing your own decoder subclass, you must override this
     method in your class.  Your method should read from the input handle
     via `getline()' or read(), decode this input, and print the decoded
     data to the output handle via print().  You may do this however you
     see fit, so long as the end result is the same.

     Note that unblessed references and globrefs are automatically turned
     into I/O handles for you by `decode()', so you don't need to worry
     about it.

     Your method must return either undef (to indicate failure), or 1 (to
     indicate success).  It may also throw an exception to indicate
     failure.

encode_it INSTREAM,OUTSTREAM
     *Abstract instance method.* The back-end of the encode method.  It
     takes an input handle opened for reading (INSTREAM), and an output
     handle opened for writing (OUTSTREAM).

     If you are writing your own decoder subclass, you must override this
     method in your class.  Your method should read from the input handle
     via `getline()' or read(), encode this input, and print the encoded
     data to the output handle via print().  You may do this however you
     see fit, so long as the end result is the same.

     Note that unblessed references and globrefs are automatically turned
     into I/O handles for you by encode(), so you don't need to worry
     about it.

     Your method must return either undef (to indicate failure), or 1 (to
     indicate success).  It may also throw an exception to indicate
     failure.

filter IN, OUT, COMMAND...
     *Class method, utility.* If your decoder involves an external
     program, you can invoke them easily through this method.  The command
     must be a "filter": a command that reads input from its STDIN (which
     will come from the IN argument) and writes output to its STDOUT
     (which will go to the OUT argument).

     For example, here's a decoder that un-gzips its data:

          sub decode_it {
              my ($self, $in, $out) = @_;
              $self->filter($in, $out, "gzip -d -");
          }

     The usage is similar to IPC::Open2::open2 (which it uses internally),
     so you can specify COMMAND as a single argument or as an array.

init ARGS...
     *Instance method.* Do any necessary initialization of the new
     instance, taking whatever arguments were given to new().  Should
     return the self object on success, undef on failure.

install ENCODINGS...
     Class method.  Install this class so that each encoding in ENCODINGS
     is handled by it:

          install MyBase64Decoder 'base64', 'x-base64super';

     You should not override this method.

uninstall ENCODINGS...
     Class method.  Uninstall support for encodings.  This is a way to
     turn off the decoding of "experimental" encodings.  For safety,
     always use MIME::Decoder directly:

          uninstall MIME::Decoder 'x-uu', 'x-uuencode';

     You should not override this method.

DECODER SUBCLASSES
==================

   You don't need to "use" any other Perl modules; the following
"standard" subclasses are included as part of MIME::Decoder:

     Class:                         Handles encodings:
     ------------------------------------------------------------
     MIME::Decoder::Binary          binary
     MIME::Decoder::NBit            7bit, 8bit
     MIME::Decoder::Base64          base64
     MIME::Decoder::QuotedPrint     quoted-printable

   The following "non-standard" subclasses are also included:

     Class:                         Handles encodings:
     ------------------------------------------------------------
     MIME::Decoder::UU              x-uu, x-uuencode
     MIME::Decoder::Gzip64          x-gzip64            ** requires gzip!

NOTES
=====

Input/Output handles
--------------------

   As of MIME-tools 2.0, this class has to play nice with the new
MIME::Body class... which means that input and output routines cannot just
assume that they are dealing with filehandles.

   Therefore, all that MIME::Decoder and its subclasses require (and, thus,
all that they can assume) is that INSTREAMs and OUTSTREAMs are objects
which respond to a subset of the messages defined in the IO::Handle
interface; minimally:

     print
     getline
     read(BUF,NBYTES)

   For backwards compatibilty, if you supply a scalar filehandle name
(like `"STDOUT"') or an unblessed glob reference (like `\*STDOUT') where
an INSTREAM or OUTSTREAM is expected, this package will automatically wrap
it in an object that fits these criteria, via IO::Wrap.

   *Thanks to Achim Bohnet for suggesting this more-generic I/O model.*

Writing a decoder
-----------------

   If you're experimenting with your own encodings, you'll probably want
to write a decoder.  Here are the basics:

  1. Create a module, like "MyDecoder::", for your decoder.  Declare it to
     be a subclass of MIME::Decoder.

  2. Create the following instance methods in your class, as described
     above:

          decode_it
          encode_it
          init

  3. In your application program, activate your decoder for one or more
     encodings like this:

          require MyDecoder;

          install MyDecoder "7bit";   ### use MyDecoder to decode "7bit"
          install MyDecoder "x-foo";  ### also use MyDecoder to decode "x-foo"

        To illustrate, here's a custom decoder class for the
`quoted-printable' encoding:

     package MyQPDecoder;

     @ISA = qw(MIME::Decoder);
     use MIME::Decoder;
     use MIME::QuotedPrint;

     ### decode_it - the private decoding method
     sub decode_it {
         my ($self, $in, $out) = @_;

         while (defined($_ = $in->getline)) {
             my $decoded = decode_qp($_);
     	    $out->print($decoded);
         }
         1;
     }

     ### encode_it - the private encoding method
     sub encode_it {
         my ($self, $in, $out) = @_;

         my ($buf, $nread) = ('', 0);
         while ($in->read($buf, 60)) {
             my $encoded = encode_qp($buf);
     	    $out->print($encoded);
         }
         1;
     }

   That's it.  The task was pretty simple because the `"quoted-printable"'
encoding can easily be converted line-by-line... as can even `"7bit"' and
`"8bit"' (since all these encodings guarantee short lines, with a max of
1000 characters).  The good news is: it is very likely that it will be
similarly-easy to write a MIME::Decoder for any future standard encodings.

   The `"binary"' decoder, however, really required block reads and writes:
see `"MIME::Decoder::Binary"' in this node for details.

AUTHOR
======

   Eryq (`eryq@zeegee.com'), ZeeGee Software Inc (`http://www.zeegee.com').

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

VERSION
=======

   $Revision: 5.403 $ $Date: 2000/11/04 19:54:46 $

encode/decode a "base64" stream
*******************************

NAME
====

   MIME::Decoder::Base64 - encode/decode a "base64" stream

SYNOPSIS
========

   A generic decoder object; see MIME/Decoder, for
usage.

DESCRIPTION
===========

   A MIME/Decoder, subclass for the `"base64"'
encoding.  The name was chosen to jibe with the pre-existing MIME::Base64
utility package, which this class actually uses to translate each chunk.

   * When *decoding*, the input is read one line at a time.  The input
     accumulates in an internal buffer, which is decoded in
     multiple-of-4-sized chunks (plus a possible "leftover" input chunk,
     of course).

   * When encoding, the input is read 45 bytes at a time: this ensures
     that the output lines are not too long.   We chose 45 since it is a
     multiple of 3 and produces lines under 76 characters, as RFC-1521
     specifies.

AUTHOR
======

   Eryq (`eryq@zeegee.com'), ZeeGee Software Inc (`http://www.zeegee.com').

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

VERSION
=======

   $Revision: 5.403 $ $Date: 2000/11/04 19:54:48 $

perform no encoding/decoding
****************************

NAME
====

   MIME::Decoder::Binary - perform no encoding/decoding

SYNOPSIS
========

   A generic decoder object; see MIME/Decoder, for
usage.

DESCRIPTION
===========

   A MIME::Decoder subclass for the `"binary"' encoding (in other words,
no encoding).

   The `"binary"' decoder is a special case, since it's ill-advised to
read the input line-by-line: after all, an uncompressed image file might
conceivably have loooooooooong stretches of bytes without a `"\n"' among
them, and we don't want to risk blowing out our core.  So, we
read-and-write fixed-size chunks.

   Both the *encoder* and *decoder* do a simple pass-through of the data
from input to output.

AUTHOR
======

   Eryq (`eryq@zeegee.com'), ZeeGee Software Inc (`http://www.zeegee.com').

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

VERSION
=======

   $Revision: 5.403 $ $Date: 2000/11/04 19:54:48 $

decode a "base64" gzip stream
*****************************

NAME
====

   MIME::Decoder::Gzip64 - decode a "base64" gzip stream

SYNOPSIS
========

   A generic decoder object; see MIME/Decoder, for
usage.

DESCRIPTION
===========

   A MIME::Decoder::Base64 subclass for a nonstandard encoding whereby
data are gzipped, then the gzipped file is base64-encoded.  Common
non-standard MIME encodings for this:

     x-gzip64

   Since this class relies on external programs which may not exist on
your machine, MIME-tools does not "install" it by default.  To use it, you
need to say in your main program:

     install MIME::Decoder::Gzip64 'x-gzip64';

   Note: if this class isn't working for you, you may need to change the
commands it runs.  In your main program, you can do so by setting up the
two commands which

     use MIME::Decoder::Gzip64;

     $MIME::Decoder::Gzip64::GZIP   = 'gzip -c';
     $MIME::Decoder::Gzip64::GUNZIP = 'gzip -d -c';

AUTHOR
======

   Eryq (`eryq@zeegee.com'), ZeeGee Software Inc (`http://www.zeegee.com').

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

VERSION
=======

   $Revision: 5.403 $ $Date: 2000/11/04 19:54:48 $

encode/decode a "7bit" or "8bit" stream
***************************************

NAME
====

   MIME::Decoder::NBit - encode/decode a "7bit" or "8bit" stream

SYNOPSIS
========

   A generic decoder object; see MIME/Decoder, for
usage.

DESCRIPTION
===========

   This is a MIME::Decoder subclass for the 7bit and 8bit content transfer
encodings.  These are not "encodings" per se: rather, they are simply
assertions of the content of the message.  From RFC-2045 Section 6.2.:

     Three transformations are currently defined: identity, the "quoted-
     printable" encoding, and the "base64" encoding.  The domains are
     "binary", "8bit" and "7bit".

     The Content-Transfer-Encoding values "7bit", "8bit", and "binary" all
     mean that the identity (i.e. NO) encoding transformation has been
     performed.  As such, they serve simply as indicators of the domain of
     the body data, and provide useful information about the sort of
     encoding that might be needed for transmission in a given transport
     system.

   In keeping with this: as of MIME-tools 4.x, *this class does no
modification of its input when encoding;* all it does is attempt to
*detect violations* of the 7bit/8bit assertion, and issue a warning (one
per message) if any are found.

Legal 7bit data
---------------

   RFC-2045 Section 2.7 defines legal 7bit data:

     "7bit data" refers to data that is all represented as relatively
     short lines with 998 octets or less between CRLF line separation
     sequences [RFC-821].  No octets with decimal values greater than 127
     are allowed and neither are NULs (octets with decimal value 0).  CR
     (decimal value 13) and LF (decimal value 10) octets only occur as
     part of CRLF line separation sequences.

Legal 8bit data
---------------

   RFC-2045 Section 2.8 defines legal 8bit data:

     "8bit data" refers to data that is all represented as relatively
     short lines with 998 octets or less between CRLF line separation
     sequences [RFC-821]), but octets with decimal values greater than 127
     may be used.  As with "7bit data" CR and LF octets only occur as part
     of CRLF line separation sequences and no NULs are allowed.

How decoding is done
--------------------

   The *decoder* does a line-by-line pass-through from input to output,
leaving the data unchanged except that an end-of-line sequence of CRLF is
converted to a newline "\n".  Given the line-oriented nature of 7bit and
8bit, this seems relatively sensible.

How encoding is done
--------------------

   The *encoder* does a line-by-line pass-through from input to output,
and simply attempts to detect violations of the 7bit/8bit domain.  The
default action is to warn once per encoding if violations are detected;
the warnings may be silenced with the QUIET configuration of
MIME/Tools.

AUTHOR
======

   Eryq (`eryq@zeegee.com'), ZeeGee Software Inc (`http://www.zeegee.com').

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

VERSION
=======

   $Revision: 5.403 $ $Date: 2000/11/04 19:54:48 $

decode a "radix-64" PGP stream
******************************

NAME
====

   MIME::Decoder::PGP - decode a "radix-64" PGP stream

SYNOPSIS
========

   A generic decoder object; see MIME/Decoder, for
usage.

DESCRIPTION
===========

   A MIME::Decoder subclass for a nonstandard encoding using the PGP tool.
Common non-standard MIME encodings for this:

     x-pgp

AUTHOR
======

   Copyright (c) 1998 by Jochen Wiedmann / joe@ispsoft.de

   Based on MIME::Decoder::Gzip64, which is

   Copyright (c) 1996, 1997 by Eryq / eryq@zeegee.com

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

VERSION
=======

   $Revision: 1.1.1.1 $ $Date: 1999/09/12 13:05:51 $

encode/decode a "quoted-printable" stream
*****************************************

NAME
====

   MIME::Decoder::QuotedPrint - encode/decode a "quoted-printable" stream

SYNOPSIS
========

   A generic decoder object; see MIME/Decoder, for
usage.

DESCRIPTION
===========

   A MIME::Decoder subclass for the `"quoted-printable"' encoding.  The
name was chosen to jibe with the pre-existing MIME::QuotedPrint utility
package, which this class actually uses to translate each line.

   * The *decoder* does a line-by-line translation from input to output.

   * The *encoder* does a line-by-line translation, breaking lines so that
     they fall under the standard 76-character limit for this encoding.

   Note: just like MIME::QuotedPrint, we currently use the native `"\n"'
for line breaks, and not `CRLF'.  This may need to change in future
versions.

AUTHOR
======

   Eryq (`eryq@zeegee.com'), ZeeGee Software Inc (`http://www.zeegee.com').

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

VERSION
=======

   $Revision: 5.403 $ $Date: 2000/11/04 19:54:49 $

decode a "uuencoded" stream
***************************

NAME
====

   MIME::Decoder::UU - decode a "uuencoded" stream

SYNOPSIS
========

   A generic decoder object; see MIME/Decoder, for
usage.

   Also supports a preamble() method to recover text before the uuencoded
portion of the stream.

DESCRIPTION
===========

   A MIME::Decoder subclass for a nonstandard encoding whereby data are
uuencoded.  Common non-standard MIME encodings for this:

     x-uu
     x-uuencode

AUTHOR
======

   Eryq (`eryq@zeegee.com'), ZeeGee Software Inc (`http://www.zeegee.com').

   UU-decoding code lifted from "uuexplode", a Perl script by an unknown
author...

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

VERSION
=======

   $Revision: 5.403 $ $Date: 2000/11/04 19:54:49 $

class for parsed-and-decoded MIME message
*****************************************

NAME
====

   MIME::Entity - class for parsed-and-decoded MIME message

SYNOPSIS
========

   Before reading further, you should see MIME/Tools, to
make sure that you understand where this module fits into the grand scheme
of things.  Go on, do it now.  I'll wait.

   Ready?  Ok...

     ### Create an entity:
     $top = MIME::Entity->build(From    => 'me@myhost.com',
                                To      => 'you@yourhost.com',
                                Subject => "Hello, nurse!",
     			       Data    => \@my_message);

     ### Attach stuff to it:
     $top->attach(Path     => $gif_path,
     		 Type     => "image/gif",
     		 Encoding => "base64");

     ### Sign it:
     $top->sign;

     ### Output it:
     $top->print(\*STDOUT);

DESCRIPTION
===========

   A subclass of Mail::Internet.

   This package provides a class for representing MIME message entities,
as specified in RFC 1521, *Multipurpose Internet Mail Extensions*.

EXAMPLES
========

Construction examples
---------------------

   Create a document for an ordinary 7-bit ASCII text file (lots of stuff
is defaulted for us):

     $ent = MIME::Entity->build(Path=>"english-msg.txt");

   Create a document for a text file with 8-bit (Latin-1) characters:

     $ent = MIME::Entity->build(Path     =>"french-msg.txt",
                                Encoding =>"quoted-printable",
                                From     =>'jean.luc@inria.fr',
                                Subject  =>"C'est bon!");

   Create a document for a GIF file (the description is completely
optional; note that we have to specify content-type and encoding since
they're not the default values):

     $ent = MIME::Entity->build(Description => "A pretty picture",
                                Path        => "./docs/mime-sm.gif",
                                Type        => "image/gif",
                                Encoding    => "base64");

   Create a document that you already have the text for, using "Data":

     $ent = MIME::Entity->build(Type        => "text/plain",
                                Encoding    => "quoted-printable",
                                Data        => ["First line.\n",
                                               "Second line.\n",
                                               "Last line.\n"]);

   Create a multipart message, with the entire structure given explicitly:

     ### Create the top-level, and set up the mail headers:
     $top = MIME::Entity->build(Type     => "multipart/mixed",
                                From     => 'me@myhost.com',
                                To       => 'you@yourhost.com',
                                Subject  => "Hello, nurse!");

     ### Attachment #1: a simple text document:
     $top->attach(Path=>"./testin/short.txt");

     ### Attachment #2: a GIF file:
     $top->attach(Path        => "./docs/mime-sm.gif",
                  Type        => "image/gif",
                  Encoding    => "base64");

     ### Attachment #3: text we'll create with text we have on-hand:
     $top->attach(Data => $contents);

   Suppose you don't know ahead of time that you'll have attachments?  No
problem: you can "attach" to singleparts as well:

     $top = MIME::Entity->build(From    => 'me@myhost.com',
     			       To      => 'you@yourhost.com',
     			       Subject => "Hello, nurse!",
     			       Data    => \@my_message);
     if ($GIF_path) {
     	$top->attach(Path     => $GIF_path,
     	             Type     => 'image/gif');
     }

   Copy an entity (headers, parts... everything but external body data):

     my $deepcopy = $top->dup;

Access examples
---------------

     ### Get the head, a MIME::Head:
     $head = $ent->head;

     ### Get the body, as a MIME::Body;
     $bodyh = $ent->bodyhandle;

     ### Get the intended MIME type (as declared in the header):
     $type = $ent->mime_type;

     ### Get the effective MIME type (in case decoding failed):
     $eff_type = $ent->effective_type;

     ### Get preamble, parts, and epilogue:
     $preamble   = $ent->preamble;          ### ref to array of lines
     $num_parts  = $ent->parts;
     $first_part = $ent->parts(0);          ### an entity
     $epilogue   = $ent->epilogue;          ### ref to array of lines

Manipulation examples
---------------------

   Muck about with the body data:

     ### Read the (unencoded) body data:
     if ($io = $ent->open("r")) {
     	while (defined($_ = $io->getline)) { print $_ }
     	$io->close;
     }

     ### Write the (unencoded) body data:
     if ($io = $ent->open("w")) {
     	foreach (@lines) { $io->print($_) }
     	$io->close;
     }

     ### Delete the files for any external (on-disk) data:
     $ent->purge;

   Muck about with the signature:

     ### Sign it (automatically removes any existing signature):
     $top->sign(File=>"$ENV{HOME}/.signature");

     ### Remove any signature within 15 lines of the end:
     $top->remove_sig(15);

   Muck about with the headers:

     ### Compute content-lengths for singleparts based on bodies:
     ###   (Do this right before you print!)
     $entity->sync_headers(Length=>'COMPUTE');

   Muck about with the structure:

     ### If a 0- or 1-part multipart, collapse to a singlepart:
     $top->make_singlepart;

     ### If a singlepart, inflate to a multipart with 1 part:
     $top->make_multipart;

   Delete parts:

     ### Delete some parts of a multipart message:
     my @keep = grep { keep_part($_) } $msg->parts;
     $msg->parts(\@keep);

Output examples
---------------

   Print to filehandles:

     ### Print the entire message:
     $top->print(\*STDOUT);

     ### Print just the header:
     $top->print_header(\*STDOUT);

     ### Print just the (encoded) body... includes parts as well!
     $top->print_body(\*STDOUT);

   Stringify... note that `stringify_xx' can also be written
`xx_as_string'; the methods are synonymous, and neither form will be
deprecated:

     ### Stringify the entire message:
     print $top->stringify;              ### or $top->as_string

     ### Stringify just the header:
     print $top->stringify_header;       ### or $top->header_as_string

     ### Stringify just the (encoded) body... includes parts as well!
     print $top->stringify_body;         ### or $top->body_as_string

   Debug:

     ### Output debugging info:
     $entity->dump_skeleton(\*STDERR);

PUBLIC INTERFACE
================

Construction
------------

new [SOURCE]
     *Class method.* Create a new, empty MIME entity.  Basically, this
     uses the Mail::Internet constructor...

     If SOURCE is an ARRAYREF, it is assumed to be an array of lines that
     will be used to create both the header and an in-core body.

     Else, if SOURCE is defined, it is assumed to be a filehandle from
     which the header and in-core body is to be read.

     Note: in either case, the body will not be *parsed:* merely read!

add_part ENTITY, [OFFSET]
     *Instance method.* Assuming we are a multipart message, add a body
     part (a MIME::Entity) to the array of body parts.  Returns the part
     that was just added.

     If OFFSET is positive, the new part is added at that offset from the
     beginning of the array of parts.  If it is negative, it counts from
     the end of the array.  (An INDEX of -1 will place the new part at the
     very end of the array, -2 will place it as the penultimate item in the
     array, etc.)  If OFFSET is not given, the new part is added to the end
     of the array.  *Thanks to Jason L Tibbitts III for providing support
     for OFFSET.*

     Warning: in general, you only want to attach parts to entities with a
     content-type of `multipart/*').

attach PARAMHASH
     *Instance method.* The real quick-and-easy way to create multipart
     messages.  The PARAMHASH is used to build a new entity; this method is
     basically equivalent to:

          $entity->add_part(ref($entity)->build(PARAMHASH, Top=>0));

     Note: normally, you attach to multipart entities; however, if you
     attach something to a singlepart (like attaching a GIF to a text
     message), the singlepart will be coerced into a multipart
     automatically.

build PARAMHASH
     *Class/instance method.* A quick-and-easy catch-all way to create an
     entity.  Use it like this to build a "normal" single-part entity:

          $ent = MIME::Entity->build(Type     => "image/gif",
          		              Encoding => "base64",
                                     Path     => "/path/to/xyz12345.gif",
                                     Filename => "saveme.gif",
                                     Disposition => "attachment");

     And like this to build a "multipart" entity:

          $ent = MIME::Entity->build(Type     => "multipart/mixed",
                                     Boundary => "---1234567");

     A minimal MIME header will be created.  If you want to add or modify
     any header fields afterwards, you can of course do so via the
     underlying head object... but hey, there's now a prettier syntax!

          $ent = MIME::Entity->build(Type          =>"multipart/mixed",
                                     From          => $myaddr,
                                     Subject       => "Hi!",
                                     'X-Certified' => ['SINED',
                                                       'SEELED',
                                                       'DELIVERED']);

     Normally, an `X-Mailer' header field is output which contains this
     toolkit's name and version (plus this module's RCS version).  This
     will allow any bad MIME we generate to be traced back to us.  You can
     of course overwrite that header with your own:

          $ent = MIME::Entity->build(Type        => "multipart/mixed",
                                     'X-Mailer'  => "myprog 1.1");

     Or remove it entirely:

          $ent = MIME::Entity->build(Type       => "multipart/mixed",
                                     'X-Mailer' => undef);

     OK, enough hype.  The parameters are:

    (FIELDNAME)
          Any field you want placed in the message header, taken from the
          standard list of header fields (you don't need to worry about
          case):

               Bcc           Encrypted     Received      Sender
               Cc            From          References    Subject
               Comments	  Keywords      Reply-To      To
               Content-*	  Message-ID    Resent-*      X-*
               Date          MIME-Version  Return-Path
                             Organization

          To give experienced users some veto power, these fields will be
          set after the ones I set... so be careful: *don't set any MIME
          fields* (like `Content-type') unless you know what you're doing!

          To specify a fieldname that's not in the above list, even one
          that's identical to an option below, just give it with a
          trailing `":"', like `"My-field:"'.  When in doubt, that always
          signals a mail field (and it sort of looks like one too).

    Boundary
          *Multipart entities only. Optional.* The boundary string.  As
          per RFC-1521, it must consist only of the characters
          `[0-9a-zA-Z'()+_,-./:=?]' and space (you'll be warned, and your
          boundary will be ignored, if this is not the case).  If you omit
          this, a random string will be chosen... which is probably safer.

    Charset
          *Optional.* The character set.

    Data
          *Single-part entities only. Optional.* An alternative to Path
          (q.v.): the actual data, either as a scalar or an array
          reference (whose elements are joined together to make the actual
          scalar).  The body is opened on the data using
          MIME::Body::InCore.

    Description
          *Optional.* The text of the content-description.  If you don't
          specify it, the field is not put in the header.

    Disposition
          *Optional.* The basic content-disposition (`"attachment"' or
          `"inline"').  If you don't specify it, it defaults to "inline"
          for backwards compatibility.  *Thanks to Kurt Freytag for
          suggesting this feature.*

    Encoding
          *Optional.* The content-transfer-encoding.  If you don't specify
          it, a reasonable default is put in.  You can also give the
          special value '-SUGGEST', to have it chosen for you in a
          heavy-duty fashion which scans the data itself.

    Filename
          *Single-part entities only. Optional.* The recommended filename.
          Overrides any name extracted from Path.  The information is
          stored both the deprecated (content-type) and preferred
          (content-disposition) locations.  If you explicitly want to
          *avoid* a recommended filename (even when Path is used), supply
          this as empty or undef.

    Id
          *Optional.* Set the content-id.

    Path
          *Single-part entities only. Optional.* The path to the file to
          attach.  The body is opened on that file using MIME::Body::File.

    Top
          *Optional.* Is this a top-level entity?  If so, it must sport a
          MIME-Version.  The default is true.  (NB: look at how `attach()'
          uses it.)

    Type
          *Optional.* The basic content-type (`"text/plain"', etc.).  If
          you don't specify it, it defaults to `"text/plain"' as per
          RFC-1521.  *Do yourself a favor: put it in.*

dup
     *Instance method.* Duplicate the entity.  Does a deep, recursive
     copy, *but beware:* external data in bodyhandles is not copied to new
     files!  Changing the data in one entity's data file, or purging that
     entity, *will* affect its duplicate.  Entities with in-core data
     probably need not worry.

Access
------

body [VALUE]
     *Instance method.* Get the *encoded* (transport-ready) body, as an
     array of lines.  This is a read-only data structure: changing its
     contents will have no effect.  Its contents are identical to what is
     printed by `print_body()|' in this node.

     Provided for compatibility with Mail::Internet, so that methods like
     `smtpsend()' will work.  Note however that if VALUE is given, a fatal
     exception is thrown, since you cannot use this method to set the
     lines of the encoded message.

     If you want the raw (unencoded) body data, use the `bodyhandle()|' in
     this node method to get and use a MIME::Body.  The content-type of
     the entity will tell you whether that body is best read as text (via
     getline()) or raw data (via read()).

bodyhandle [VALUE]
     *Instance method.* Get or set an abstract object representing the
     body of the message.  The body holds the decoded message data.

     See that not all entities have bodies!* An entity will have either a body or parts.
     This method will *only* return an object
     if this entity can have a body; otherwise, it will return undefined.
     Whether-or-not a given entity can have a body is determined by (1)
     its content type, and (2) whether-or-not the parser was told to
     extract nested messages:

          Type:        | Extract nested? | bodyhandle() | parts()
          -----------------------------------------------------------------------
          multipart/*  | -               | undef        | 0 or more MIME::Entity
          message/*    | true            | undef        | 0 or 1 MIME::Entity
          message/*    | false           | MIME::Body   | empty list
          (other)      | -               | MIME::Body   | empty list

     If VALUE *is not* given, the current bodyhandle is returned, or undef
     if the entity cannot have a body.

     If VALUE *is* given, the bodyhandle is set to the new value, and the
     previous value is returned.

     See `' in this node for more info.

effective_type [MIMETYPE]
     *Instance method.* Set/get the *effective* MIME type of this entity.
     This is *usually* identical to the actual (or defaulted) MIME type,
     but in some cases it differs.  For example, from RFC-2045:

          Any entity with an unrecognized Content-Transfer-Encoding must be
          treated as if it has a Content-Type of "application/octet-stream",
          regardless of what the Content-Type header field actually says.

     Why? because if we can't decode the message, then we have to take the
     bytes as-is, in their (unrecognized) encoded form.  So the message
     ceases to be a "text/foobar" and becomes a bunch of undecipherable
     bytes - in other words, an "application/octet-stream".

     Such an entity, if parsed, would have its effective_type() set to
     `"application/octet_stream"', although the mime_type() and the
     contents of the header would remain the same.

     If there is no effective type, the method just returns what
     mime_type() would.

     Warning: the effective type is "sticky"; once set, that
     effective_type() will always be returned even if the conditions that
     necessitated setting the effective type become no longer true.

epilogue [LINES]
     *Instance method.* Get/set the text of the epilogue, as an array of
     newline-terminated LINES.  Returns a reference to the array of lines,
     or undef if no epilogue exists.

     If there is a epilogue, it is output when printing this entity;
     otherwise, a default epilogue is used.  Setting the epilogue to undef
     (not []!) causes it to fallback to the default.

head [VALUE]
     *Instance method.* Get/set the head.

     If there is no VALUE given, returns the current head.  If none
     exists, an empty instance of MIME::Head is created, set, and returned.

     Note: This is a patch over a problem in Mail::Internet, which doesn't
     provide a method for setting the head to some given object.

is_multipart
     *Instance method.* Does this entity's effective MIME type indicate
     that it's a multipart entity?  Returns undef (false) if the answer
     couldn't be determined, 0 (false) if it was determined to be false,
     and true otherwise.  Note that this says nothing about whether or not
     parts were extracted.

     NOTE: we switched to effective_type so that multiparts with bad or
     missing boundaries could be coerced to an effective type of
     `application/x-unparseable-multipart'.

mime_type
     *Instance method.* A purely-for-convenience method.  This simply
     relays the request to the associated MIME::Head object.  If there is
     no head, returns undef in a scalar context and the empty array in a
     list context.

     *Before you use this,* consider using effective_type() instead,
     especially if you obtained the entity from a MIME::Parser.

open READWRITE
     *Instance method.* A purely-for-convenience method.  This simply
     relays the request to the associated MIME::Body object (see
     MIME::Body::open()).  READWRITE is either 'r' (open for read) or 'w'
     (open for write).

     If there is no body, returns false.

parts
parts INDEX
parts ARRAYREF
     *Instance method.* Return the MIME::Entity objects which are the sub
     parts of this entity (if any).

     *If no argument is given,* returns the array of all sub parts,
     returning the empty array if there are none (e.g., if this is a single
     part message, or a degenerate multipart).  In a scalar context, this
     returns you the number of parts.

     *If an integer INDEX is given,* return the INDEXed part, or undef if
     it doesn't exist.

     *If an ARRAYREF to an array of parts is given,* then this method sets
     the parts to a copy of that array, and returns the parts.  This can
     be used to delete parts, as follows:

          ### Delete some parts of a multipart message:
          $msg->parts([ grep { keep_part($_) } $msg->parts ]);

     Note: for multipart messages, the preamble and epilogue are not
     considered parts.  If you need them, use the `preamble()' and
     `epilogue()' methods.

     Note: there are ways of parsing with a MIME::Parser which cause
     certain message parts (such as those of type `message/rfc822') to be
     "reparsed" into pseudo-multipart entities.  You should read the
     documentation for those options carefully: it *is* possible for a
     diddled entity to not be multipart, but still have parts attached to
     it!

     See `' in this node for a discussion of parts vs. bodies.

parts_DFS
     *Instance method.* Return the list of all MIME::Entity objects
     included in the entity, starting with the entity itself, in
     depth-first-search order.  If the entity has no parts, it alone will
     be returned.

     *Thanks to Xavier Armengou for suggesting this method.*

preamble [LINES]
     *Instance method.* Get/set the text of the preamble, as an array of
     newline-terminated LINES.  Returns a reference to the array of lines,
     or undef if no preamble exists (e.g., if this is a single-part
     entity).

     If there is a preamble, it is output when printing this entity;
     otherwise, a default preamble is used.  Setting the preamble to undef
     (not []!) causes it to fallback to the default.

Manipulation
------------

make_multipart [SUBTYPE], OPTSHASH...
     *Instance method.* Force the entity to be a multipart, if it isn't
     already.  We do this by replacing the original [singlepart] entity
     with a new multipart that has the same non-MIME headers ("From",
     "Subject", etc.), but all-new MIME headers ("Content-type", etc.).
     We then create a copy of the original singlepart, *strip out* the
     non-MIME headers from that, and make it a part of the new multipart.
     So this:

          From: me
          To: you
          Content-type: text/plain
          Content-length: 12

          Hello there!

     Becomes something like this:

          From: me
          To: you
          Content-type: multipart/mixed; boundary="----abc----"

          ------abc----
          Content-type: text/plain
          Content-length: 12

          Hello there!
          ------abc------

     The actual type of the new top-level multipart will be
     "multipart/SUBTYPE" (default SUBTYPE is "mixed").

     Returns 'DONE'    if we really did inflate a singlepart to a
     multipart.  Returns 'ALREADY' (and does nothing) if entity is
     *already* multipart and Force was not chosen.

     If OPTSHASH contains Force=>1, then we always bump the top-level's
     content and content-headers down to a subpart of this entity, even if
     this entity is already a multipart.  This is apparently of use to
     people who are tweaking messages after parsing them.

make_singlepart
     *Instance method.* If the entity is a multipart message with one
     part, this tries hard to rewrite it as a singlepart, by replacing the
     content (and content headers) of the top level with those of the
     part.  Also crunches 0-part multiparts into singleparts.

     Returns 'DONE'    if we really did collapse a multipart to a
     singlepart.  Returns 'ALREADY' (and does nothing) if entity is
     already a singlepart.  Returns '0'       (and does nothing) if it
     can't be made into a singlepart.

purge
     *Instance method.* Recursively purge (e.g., unlink) all external
     (e.g., on-disk) body parts in this message.  See MIME::Body::purge()
     for details.

     Note: this does not delete the directories that those body parts are
     contained in; only the actual message data files are deleted.  This
     is because some parsers may be customized to create intermediate
     directories while others are not, and it's impossible for this class
     to know what directories are safe to remove.  Only your application
     program truly knows that.

     *If you really want to "clean everything up",* one good way is to use
     `MIME::Parser::file_under()', and then do this before parsing your
     next message:

          $parser->filer->purge();

     I wouldn't attempt to read those body files after you do this, for
     obvious reasons.  As of MIME-tools 4.x, each body's path *is*
     undefined after this operation.  I warned you I might do this; truly
     I did.

     *Thanks to Jason L. Tibbitts III for suggesting this method.*

remove_sig [NLINES]
     *Instance method, override.* Attempts to remove a user's signature
     from the body of a message.

     It does this by looking for a line matching `/^-- $/' within the last
     `NLINES' of the message.  If found then that line and all lines after
     it will be removed. If `NLINES' is not given, a default value of 10
     will be used.  This would be of most use in auto-reply scripts.

     For MIME entity, this method is reasonably cautious: it will only
     attempt to un-sign a message with a content-type of `text/*'.

     If you send remove_sig() to a multipart entity, it will relay it to
     the first part (the others usually being the "attachments").

     Warning: currently slurps the whole message-part into core as an
     array of lines, so you probably don't want to use this on extremely
     long messages.

     Returns truth on success, false on error.

sign PARAMHASH
     *Instance method, override.* Append a signature to the message.  The
     params are:

    Attach
          Instead of appending the text, add it to the message as an
          attachment.  The disposition will be inline, and the description
          will indicate that it is a signature.  The default behavior is
          to append the signature to the text of the message (or the text
          of its first part if multipart).  *MIME-specific; new in this
          subclass.*

    File
          Use the contents of this file as the signature.  Fatal error if
          it can't be read.  *As per superclass method.*

    Force
          Sign it even if the content-type isn't `text/*'.  Useful for
          non-standard types like `x-foobar', but be careful!
          *MIME-specific; new in this subclass.*

    Remove
          Normally, we attempt to strip out any existing signature.  If
          true, this gives us the NLINES parameter of the remove_sig call.
          If zero but defined, tells us not to remove any existing
          signature.  If undefined, removal is done with the default of 10
          lines.  *New in this subclass.*

    Signature
          Use this text as the signature.  You can supply it as either a
          scalar, or as a ref to an array of newline-terminated scalars.
          *As per superclass method.*

     For MIME messages, this method is reasonably cautious: it will only
     attempt to sign a message with a content-type of `text/*', unless
     Force is specified.

     If you send this message to a multipart entity, it will relay it to
     the first part (the others usually being the "attachments").

     Warning: currently slurps the whole message-part into core as an
     array of lines, so you probably don't want to use this on extremely
     long messages.

     Returns true on success, false otherwise.

suggest_encoding
     *Instance method.* Based on the effective content type, return a good
     suggested encoding.

     text and message types have their bodies scanned line-by-line for
     8-bit characters and long lines; lack of either means that the
     message is 7bit-ok.  Other types are chosen independent of their body:

          Major type:      7bit ok?    Suggested encoding:
          -----------------------------------------------------------
          text             yes         7bit
          text             no          quoted-printable
          message          yes         7bit
          message          no          binary
          multipart        *           binary (in case some parts are bad)
          image, etc...    *           base64

sync_headers OPTIONS
     *Instance method.* This method does a variety of activities which
     ensure that the MIME headers of an entity "tree" are in-synch with
     the body parts they describe.  It can be as expensive an operation as
     printing if it involves pre-encoding the body parts; however, the aim
     is to produce fairly clean MIME.  *You will usually only need to
     invoke this if processing and re-sending MIME from an outside source.*

     The OPTIONS is a hash, which describes what is to be done.

    Length
          One of the "official unofficial" MIME fields is "Content-Length".
          Normally, one doesn't care a whit about this field; however, if
          you are preparing output destined for HTTP, you may.  The value
          of this option dictates what will be done:

          *COMPUTE* means to set a `Content-Length' field for every
          non-multipart part in the entity, and to blank that field out
          for every multipart part in the entity.

          *ERASE* means that `Content-Length' fields will all be blanked
          out.  This is fast, painless, and safe.

          *Any false value* (the default) means to take no action.

    Nonstandard
          Any header field beginning with "Content-" is, according to the
          RFC, a MIME field.  However, some are non-standard, and may
          cause problems with certain MIME readers which interpret them in
          different ways.

          *ERASE* means that all such fields will be blanked out.  This is
          done before the Length option (q.v.) is examined and acted upon.

          *Any false value* (the default) means to take no action.

     Returns a true value if everything went okay, a false value otherwise.

tidy_body
     *Instance method, override.* Currently unimplemented for MIME
     messages.  Does nothing, returns false.

Output
------

dump_skeleton [FILEHANDLE]
     *Instance method.* Dump the skeleton of the entity to the given
     FILEHANDLE, or to the currently-selected one if none given.

     Each entity is output with an appropriate indentation level, the
     following selection of attributes:

          Content-type: multipart/mixed
          Effective-type: multipart/mixed
          Body-file: NONE
          Subject: Hey there!
          Num-parts: 2

     This is really just useful for debugging purposes; I make no
     guarantees about the consistency of the output format over time.

print [OUTSTREAM]
     *Instance method, override.* Print the entity to the given OUTSTREAM,
     or to the currently-selected filehandle if none given.  OUTSTREAM can
     be a filehandle, or any object that reponds to a print() message.

     The entity is output as a valid MIME stream!  This means that the
     header is always output first, and the body data (if any) will be
     encoded if the header says that it should be.  For example, your
     output may look like this:

          Subject: Greetings
          Content-transfer-encoding: base64

          SGkgdGhlcmUhCkJ5ZSB0aGVyZSEK

     *If this entity has MIME type "multipart/*",* the preamble, parts,
     and epilogue are all output with appropriate boundaries separating
     each.  Any bodyhandle is ignored:

          Content-type: multipart/mixed; boundary="*----*"
          Content-transfer-encoding: 7bit

          [Preamble]
          --*----*
          [Entity: Part 0]
          --*----*
          [Entity: Part 1]
          --*----*--
          [Epilogue]

     *If this entity has a single-part MIME type with no attached parts,*
     then we're looking at a normal singlepart entity: the body is output
     according to the encoding specified by the header.  If no body
     exists, a warning is output and the body is treated as empty:

          Content-type: image/gif
          Content-transfer-encoding: base64

          [Encoded body]

     *If this entity has a single-part MIME type but it also has parts,*
     then we're probably looking at a "re-parsed" singlepart, usually one
     of type `message/*' (you can get entities like this if you set the
     `parse_nested_messages(NEST)' option on the parser to true).  In this
     case, the parts are output with single blank lines separating each,
     and any bodyhandle is ignored:

          Content-type: message/rfc822
          Content-transfer-encoding: 7bit

          [Entity: Part 0]

          [Entity: Part 1]

     In all cases, when outputting a "part" of the entity, this method is
     invoked recursively.

     Note: the output is very likely not going to be identical to any
     input you parsed to get this entity.  If you're building some sort of
     email handler, it's up to you to save this information.

print_body [OUTSTREAM]
     *Instance method, override.* Print the body of the entity to the
     given OUTSTREAM, or to the currently-selected filehandle if none
     given.  OUTSTREAM can be a filehandle, or any object that reponds to
     a print() message.

     The body is output for inclusion in a valid MIME stream; this means
     that the body data will be encoded if the header says that it should
     be.

     Note: by "body", we mean "the stuff following the header".  A printed
     multipart body includes the printed representations of its subparts.

     Note: The body is *stored* in an un-encoded form; however, the idea
     is that the transfer encoding is used to determine how it should be
     *output.* This means that the print() method is always guaranteed to
     get you a sendmail-ready stream whose body is consistent with its
     head.  If you want the *raw body data* to be output, you can either
     read it from the bodyhandle yourself, or use:

          $ent->bodyhandle->print($outstream);

     which uses read() calls to extract the information, and thus will
     work with both text and binary bodies.

     Warning: Please supply an OUTSTREAM.  This override method differs
     from Mail::Internet's behavior, which outputs to the STDOUT if no
     filehandle is given: this may lead to confusion.

print_header [OUTSTREAM]
     *Instance method, inherited.* Output the header to the given
     OUTSTREAM.  You really should supply the OUTSTREAM.

stringify
     *Instance method.* Return the entity as a string, exactly as print
     would print it.  The body will be encoded as necessary, and will
     contain any subparts.  You can also use as_string().

stringify_body
     *Instance method.* Return the *encoded* message body as a string,
     exactly as print_body would print it.  You can also use
     `body_as_string()'.

     If you want the *unencoded* body, and you are dealing with a
     singlepart message (like a "text/plain"), use `bodyhandle()' instead:

          if ($ent->bodyhandle) {
          	$unencoded_data = $ent->bodyhandle->as_string;
          }
          else {
          	### this message has no body data (but it might have parts!)
          }

stringify_header
     *Instance method.* Return the header as a string, exactly as
     print_header would print it.  You can also use `header_as_string()'.

NOTES
=====

Under the hood
--------------

   A *MIME::Entity* is composed of the following elements:

   * A head, which is a reference to a MIME::Head object containing the
     header information.

   * A bodyhandle, which is a reference to a MIME::Body object containing
     the decoded body data.  This is only defined if the message is a
     "singlepart" type:

          application/*
          audio/*
          image/*
          text/*
          video/*

   * An array of parts, where each part is a MIME::Entity object.  The
     number of parts will only be nonzero if the content-type is not one
     of the "singlepart" types:

          message/*        (should have exactly one part)
          multipart/*      (should have one or more parts)

The "two-body problem"
----------------------

   MIME::Entity and Mail::Internet see message bodies differently, and
this can cause confusion and some inconvenience.  Sadly, I can't change
the behavior of MIME::Entity without breaking lots of code already out
there.  But let's open up the floor for a few questions...

What is the difference between a "message" and an "entity"?
     A message is the actual data being sent or received; usually this
     means a stream of newline-terminated lines.  An entity is the
     representation of a message as an object.

     This means that you get a "message" when you print an "entity" to a
     filehandle, and you get an "entity" when you parse a message from a
     filehandle.

What is a message body?
     *Mail::Internet:* The portion of the printed message after the header.

     *MIME::Entity:* The portion of the printed message after the header.

How is a message body stored in an entity?
     *Mail::Internet:* As an array of lines.

     *MIME::Entity:* It depends on the content-type of the message.  For
     "container" types (`multipart/*', `message/*'), we store the
     contained entities as an array of "parts", accessed via the `parts()'
     method, where each part is a complete MIME::Entity.  For "singlepart"
     types (`text/*', `image/*', etc.), the unencoded body data is
     referenced via a MIME::Body object, accessed via the `bodyhandle()'
     method:

          bodyhandle()   parts()
              Content-type:     returns:       returns:
              ------------------------------------------------------------
              application/*     MIME::Body     empty
              audio/*           MIME::Body     empty
              image/*           MIME::Body     empty
              message/*         undef          MIME::Entity list (usually 1)
              multipart/*       undef          MIME::Entity list (usually >0)
              text/*            MIME::Body     empty
              video/*           MIME::Body     empty
              x-*/*             MIME::Body     empty

     As a special case, `message/*' is currently ambiguous: depending on
     the parser, a `message/*' might be treated as a singlepart, with a
     MIME::Body and no parts.  Use bodyhandle() as the final arbiter.

What does the body() method return?
     *Mail::Internet:* As an array of lines, ready for sending.

     *MIME::Entity:* As an array of lines, ready for sending.

If an entity has a body, does it have a soul as well?
     The soul does not exist in a corporeal sense, the way the body does;
     it is not a solid [Perl] object.  Rather, it is a virtual object
     which is only visible when you print() an entity to a file... in other
     words, the "soul" it is all that is left after the body is DESTROY'ed.

What's the best way to get at the body data?
     *Mail::Internet:* Use the body() method.

     *MIME::Entity:* Depends on what you want... the *encoded* data (as it
     is transported), or the *unencoded* data?  Keep reading...

How do I get the "encoded" body data?
     *Mail::Internet:* Use the body() method.

     *MIME::Entity:* Use the body() method.  You can also use:

          $entity->print_body()
          $entity->stringify_body()   ### a.k.a. $entity->body_as_string()

How do I get the "unencoded" body data?
     *Mail::Internet:* Use the body() method.

     *MIME::Entity:* Use the *bodyhandle()* method!  If bodyhandle()
     method returns true, then that value is a `MIME::Body|MIME::Body' in
     this node which can be used to access the data via its open() method.
     If bodyhandle() method returns an undefined value, then the entity
     is probably a "container" that has no real body data of its own
     (e.g., a "multipart" message): in this case, you should access the
     components via the parts() method.  Like this:

          if ($bh = $entity->bodyhandle) {
          	$io = $bh->open;
          	...access unencoded data via $io->getline or $io->read...
          	$io->close;
          }
          else {
          	foreach my $part (@parts) {
          	    ...do something with the part...
          	}
          }

     You can also use:

          if ($bh = $entity->bodyhandle) {
          	$unencoded_data = $bh->as_string;
          }
          else {
          	...do stuff with the parts...
          }

What does the body() method return?
     *Mail::Internet:* The transport-encoded message body, as an array of
     lines.

     *MIME::Entity:* The transport-encoded message body, as an array of
     lines.

What does print_body() print?
     *Mail::Internet:* Exactly what body() would return to you.

     *MIME::Entity:* Exactly what body() would return to you.

Say I have an entity which might be either singlepart or multipart.       How do I print out just "the stuff after the header"?
     *Mail::Internet:* Use print_body().

     *MIME::Entity:* Use print_body().

Why is MIME::Entity so different from Mail::Internet?
     Because MIME streams are expected to have non-textual data...
     possibly, quite a lot of it, such as a tar file.

     Because MIME messages can consist of multiple parts, which are
     most-easily manipulated as MIME::Entity objects themselves.

     Because in the simpler world of Mail::Internet, the data of a message
     and its printed representation are *identical*... and in the MIME
     world, they're not.

     Because parsing multipart bodies on-the-fly, or formatting multipart
     bodies for output, is a non-trivial task.

This is confusing.  Can the two classes be made more compatible?
     Not easily; their implementations are necessarily quite different.
     Mail::Internet is a simple, efficient way of dealing with a "black
     box" mail message... one whose internal data you don't care much
     about.  MIME::Entity, in contrast, cares *very much* about the
     message contents: that's its job!

Design issues
-------------

Some things just can't be ignored
     In multipart messages, the *"preamble"* is the portion that precedes
     the first encapsulation boundary, and the *"epilogue"* is the portion
     that follows the last encapsulation boundary.

     According to RFC-1521:

          There appears to be room for additional information prior
          to the first encapsulation boundary and following the final
          boundary.  These areas should generally be left blank, and
          implementations must ignore anything that appears before the
          first boundary or after the last one.

          NOTE: These "preamble" and "epilogue" areas are generally
          not used because of the lack of proper typing of these parts
          and the lack of clear semantics for handling these areas at
          gateways, particularly X.400 gateways.  However, rather than
          leaving the preamble area blank, many MIME implementations
          have found this to be a convenient place to insert an
          explanatory note for recipients who read the message with
          pre-MIME software, since such notes will be ignored by
          MIME-compliant software.

     In the world of standards-and-practices, that's the standard.  Now
     for the practice:

     *Some "MIME" mailers may incorrectly put a "part" in the preamble*.
     Since we have to parse over the stuff *anyway*, in the future I may
     allow the parser option of creating special MIME::Entity objects for
     the preamble and epilogue, with bogus MIME::Head objects.

     For now, though, we're MIME-compliant, so I probably won't change how
     we work.

AUTHOR
======

   Eryq (`eryq@zeegee.com'), ZeeGee Software Inc (`http://www.zeegee.com').

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

VERSION
=======

   $Revision: 5.404 $ $Date: 2000/11/06 11:58:53 $

a "Content-transfer-encoding" field
***********************************

NAME
====

   MIME::Field::ConTraEnc - a "Content-transfer-encoding" field

DESCRIPTION
===========

   A subclass of Mail::Field.

   *Don't use this class directly... its name may change in the future!*
Instead, ask Mail::Field for new instances based on the field name!

SYNOPSIS
========

     use Mail::Field;
     use MIME::Head;

     # Create an instance from some text:
     $field = Mail::Field->new('Content-transfer-encoding', '7bit');

     # Get the encoding.
     #    Possible values: 'binary', '7bit', '8bit', 'quoted-printable',
     #    'base64' and '' (unspecified).  Note that there can't be a
     #    single default for this, since it depends on the content type!
     $encoding = $field->encoding;

AUTHOR
======

   Eryq (`eryq@zeegee.com'), ZeeGee Software Inc (`http://www.zeegee.com').

a "Content-disposition" field
*****************************

NAME
====

   MIME::Field::ContDisp - a "Content-disposition" field

DESCRIPTION
===========

   A subclass of Mail::Field.

   *Don't use this class directly... its name may change in the future!*
Instead, ask Mail::Field for new instances based on the field name!

SYNOPSIS
========

     use Mail::Field;
     use MIME::Head;

     # Create an instance from some text:
     $field = Mail::Field->new('Content-disposition', $text);

     # Inline or attachment?
     $type = $field->type;

     # Recommended filename?
     $filename = $field->filename;

AUTHOR
======

   Eryq (`eryq@zeegee.com'), ZeeGee Software Inc (`http://www.zeegee.com').

a "Content-type" field
**********************

NAME
====

   MIME::Field::ContType - a "Content-type" field

DESCRIPTION
===========

   A subclass of Mail::Field.

   *Don't use this class directly... its name may change in the future!*
Instead, ask Mail::Field for new instances based on the field name!

SYNOPSIS
========

     use Mail::Field;
     use MIME::Head;

     # Create an instance from some text:
     $field = Mail::Field->new('Content-type',
                               'text/HTML; charset="US-ASCII"');

     # Get the MIME type, like 'text/plain' or 'x-foobar'.
     # Returns 'text/plain' as default, as per RFC-1521:
     my ($type, $subtype) = split('/', $field->type);

     # Get generic information:
     print $field->name;

     # Get information related to "message" type:
     if ($type eq 'message') {
     	print $field->id;
     	print $field->number;
     	print $field->total;
     }

     # Get information related to "multipart" type:
     if ($type eq 'multipart') {
     	print $field->boundary;            # the basic value, fixed up
     	print $field->multipart_boundary;  # empty if not a multipart message!
     }

     # Get information related to "text" type:
     if ($type eq 'text') {
     	print $field->charset;      # returns 'us-ascii' as default
     }

PUBLIC INTERFACE
================

boundary
     Return the boundary field.  The boundary is returned exactly as given
     in the `Content-type:' field; that is, the leading double-hyphen (-)
     is not prepended.

     (Well, *almost* exactly... from RFC-1521:

          (If a boundary appears to end with white space, the white space
          must be presumed to have been added by a gateway, and must be deleted.)

     so we oblige and remove any trailing spaces.)

     Returns the empty string if there is no boundary, or if the boundary
     is illegal (e.g., if it is empty after all trailing whitespace has
     been removed).

multipart_boundary
     Like `boundary()', except that this will also return the empty string
     if the message is not a multipart message.  In other words, there's
     an automatic sanity check.

type
     Try real hard to determine the content type (e.g., `"text/plain"',
     `"image/gif"', `"x-weird-type"', which is returned in all-lowercase.

     A happy thing: the following code will work just as you would want,
     even if there's no subtype (as in `"x-weird-type"')... in such a case,
     the $subtype would simply be the empty string:

          ($type, $subtype) = split('/', $head->mime_type);

     If the content-type information is missing, it defaults to
     `"text/plain"', as per RFC-1521:

          Default RFC-822 messages are typed by this protocol as plain text in
          the US-ASCII character set, which can be explicitly specified as
          "Content-type: text/plain; charset=us-ascii".  If no Content-Type is
          specified, this default is assumed.

     Note: under the "be liberal in what we accept" principle, this routine
     no longer syntax-checks the content type.  If it ain't empty, just
     downcase and return it.

NOTES
=====

   Since nearly all (if not all) parameters must have non-empty values to
be considered valid, we just return the empty string to signify missing
fields.  If you need to get the real underlying value, use the inherited
param() method (which returns undef if the parameter is missing).

AUTHOR
======

   Eryq (`eryq@zeegee.com'), ZeeGee Software Inc (`http://www.zeegee.com').

subclass of Mail::Field, for structured MIME fields
***************************************************

NAME
====

   MIME::Field::ParamVal - subclass of Mail::Field, for structured MIME
fields

SYNOPSIS
========

     # Create an object for a content-type field:
     $field = new Mail::Field 'Content-type';

     # Set some attributes:
     $field->param('_'        => 'text/html');
     $field->param('charset'  => 'us-ascii');
     $field->param('boundary' => '---ABC---');

     # Same:
     $field->set('_'        => 'text/html',
     		'charset'  => 'us-ascii',
     		'boundary' => '---ABC---');

     # Get an attribute, or undefined if not present:
     print "no id!"  if defined($field->param('id'));

     # Same, but use empty string for missing values:
     print "no id!"  if ($field->paramstr('id') eq '');

     # Output as string:
     print $field->stringify, "\n";

DESCRIPTION
===========

   This is an abstract superclass of most MIME fields.  It handles fields
with a general syntax like this:

     Content-Type: Message/Partial;
         number=2; total=3;
         id="oc=jpbe0M2Yt4s@thumper.bellcore.com"

   Comments are supported *between* items, like this:

     Content-Type: Message/Partial; (a comment)
         number=2  (another comment) ; (yet another comment) total=3;
         id="oc=jpbe0M2Yt4s@thumper.bellcore.com"

PUBLIC INTERFACE
================

set [\%PARAMHASH | KEY=>VAL,...,KEY=>VAL]
     *Instance method.*  Set this field.  The paramhash should contain
     parameter names in *all lowercase*, with the special `"_"' parameter
     name signifying the "default" (unnamed) parameter for the field:

          # Set up to be...
          #
          #     Content-type: Message/Partial; number=2; total=3; id="ocj=pbe0M2"
          #
          $conttype->set('_'       => 'Message/Partial',
          		  'number'  => 2,
          		  'total'   => 3,
          		  'id'      => "ocj=pbe0M2");

     Note that a single argument is taken to be a reference to a
     paramhash, while multiple args are taken to be the elements of the
     paramhash themselves.

     Supplying undef for a hashref, or an empty set of values, effectively
     clears the object.

     The self object is returned.

parse_params STRING
     *Class/instance utility method.* Extract parameter info from a
     structured field, and return it as a hash reference.  For example,
     here is a field with parameters:

          Content-Type: Message/Partial;
              number=2; total=3;
              id="oc=jpbe0M2Yt4s@thumper.bellcore.com"

     Here is how you'd extract them:

          $params = $class->parse_params('content-type');
          if ($$params{'_'} eq 'message/partial') {
              $number = $$params{'number'};
              $total  = $$params{'total'};
              $id     = $$params{'id'};
          }

     Like field names, parameter names are coerced to lowercase.  The
     special '_' parameter means the default parameter for the field.

     NOTE: This has been provided as a public method to support backwards
     compatibility, but you probably shouldn't use it.

parse STRING
     *Class/instance method.* Parse the string into the instance.  Any
     previous information is wiped.  The self object is returned.

     May also be used as a constructor.

param PARAMNAME,[VALUE]
     *Instance method.* Return the given parameter, or undef if it isn't
     there.  With argument, set the parameter to that VALUE.  The
     PARAMNAME is case-insensitive.  A "_" refers to the "default"
     parameter.

paramstr PARAMNAME,[VALUE]
     *Instance method.* Like param(): return the given parameter, or empty
     if it isn't there.  With argument, set the parameter to that VALUE.
     The PARAMNAME is case-insensitive.  A "_" refers to the "default"
     parameter.

stringify
     *Instance method.* Convert the field to a string, and return it.

tag
     *Instance method, abstract.* Return the tag for this field.

MIME message header (a subclass of Mail::Header)
************************************************

NAME
====

   MIME::Head - MIME message header (a subclass of Mail::Header)

SYNOPSIS
========

   Before reading further, you should see MIME/Tools, to
make sure that you understand where this module fits into the grand scheme
of things.  Go on, do it now.  I'll wait.

   Ready?  Ok...

Construction
------------

     ### Create a new, empty header, and populate it manually:
     $head = MIME::Head->new;
     $head->replace('content-type', 'text/plain; charset=US-ASCII');
     $head->replace('content-length', $len);

     ### Parse a new header from a filehandle:
     $head = MIME::Head->read(\*STDIN);

     ### Parse a new header from a file, or a readable pipe:
     $testhead = MIME::Head->from_file("/tmp/test.hdr");
     $a_b_head = MIME::Head->from_file("cat a.hdr b.hdr |");

Output
------

     ### Output to filehandle:
     $head->print(\*STDOUT);

     ### Output as string:
     print STDOUT $head->as_string;
     print STDOUT $head->stringify;

Getting field contents
----------------------

     ### Is this a reply?
     $is_reply = 1 if ($head->get('Subject') =~ /^Re: /);

     ### Get receipt information:
     print "Last received from: ", $head->get('Received', 0), "\n";
     @all_received = $head->get('Received');

     ### Print the subject, or the empty string if none:
     print "Subject: ", $head->get('Subject',0), "\n";

     ### Too many hops?  Count 'em and see!
     if ($head->count('Received') > 5) { ...

     ### Test whether a given field exists
     warn "missing subject!" if (! $head->count('subject'));

Setting field contents
----------------------

     ### Declare this to be an HTML header:
     $head->replace('Content-type', 'text/html');

Manipulating field contents
---------------------------

     ### Get rid of internal newlines in fields:
     $head->unfold;

     ### Decode any Q- or B-encoded-text in fields (DEPRECATED):
     $head->decode;

Getting high-level MIME information
-----------------------------------

     ### Get/set a given MIME attribute:
     unless ($charset = $head->mime_attr('content-type.charset')) {
         $head->mime_attr("content-type.charset" => "US-ASCII");
     }

     ### The content type (e.g., "text/html"):
     $mime_type     = $head->mime_type;

     ### The content transfer encoding (e.g., "quoted-printable"):
     $mime_encoding = $head->mime_encoding;

     ### The recommended name when extracted:
     $file_name     = $head->recommended_filename;

     ### The boundary text, for multipart messages:
     $boundary      = $head->multipart_boundary;

DESCRIPTION
===========

   A class for parsing in and manipulating RFC-822 message headers, with
some methods geared towards standard (and not so standard) MIME fields as
specified in RFC-1521, *Multipurpose Internet Mail Extensions*.

PUBLIC INTERFACE
================

Creation, input, and output
---------------------------

new [ARG],[OPTIONS]
     *Class method, inherited.* Creates a new header object.  Arguments
     are the same as those in the superclass.

from_file EXPR,OPTIONS
     *Class or instance method*.  For convenience, you can use this to
     parse a header object in from EXPR, which may actually be any
     expression that can be sent to open() so as to return a readable
     filehandle.  The "file" will be opened, read, and then closed:

          ### Create a new header by parsing in a file:
          my $head = MIME::Head->from_file("/tmp/test.hdr");

     Since this method can function as either a class constructor or an
     instance initializer, the above is exactly equivalent to:

          ### Create a new header by parsing in a file:
          my $head = MIME::Head->new->from_file("/tmp/test.hdr");

     On success, the object will be returned; on failure, the undefined
     value.

     The OPTIONS are the same as in new(), and are passed into new() if
     this is invoked as a class method.

     Note: This is really just a convenience front-end onto read(),
     provided mostly for backwards-compatibility with MIME-parser 1.0.

read FILEHANDLE
     *Instance (or class) method.* This initiallizes a header object by
     reading it in from a FILEHANDLE, until the terminating blank line is
     encountered.  A syntax error or end-of-stream will also halt
     processing.

     Supply this routine with a reference to a filehandle glob; e.g.,
     `\*STDIN':

          ### Create a new header by parsing in STDIN:
          $head->read(\*STDIN);

     On success, the self object will be returned; on failure, a false
     value.

     Note: in the MIME world, it is perfectly legal for a header to be
     empty, consisting of nothing but the terminating blank line.  Thus,
     we can't just use the formula that "no tags equals error".

     Warning: as of the time of this writing, Mail::Header::read did not
     flag either syntax errors or unexpected end-of-file conditions (an EOF
     before the terminating blank line).  MIME::ParserBase takes this into
     account.

Getting/setting fields
----------------------

   The following are methods related to retrieving and modifying the header
fields.  Some are inherited from Mail::Header, but I've kept the
documentation around for convenience.

add TAG,TEXT,[INDEX]
     *Instance method, inherited.* Add a new occurence of the field named
     TAG, given by TEXT:

          ### Add the trace information:
          $head->add('Received',
                     'from eryq.pr.mcs.net by gonzo.net with smtp');

     Normally, the new occurence will be *appended* to the existing
     occurences.  However, if the optional INDEX argument is 0, then the
     new occurence will be *prepended*.  If you want to be explicit about
     appending, specify an INDEX of -1.

     Warning: this method always adds new occurences; it doesn't overwrite
     any existing occurences... so if you just want to change the value of
     a field (creating it if necessary), then you probably *don't* want to
     use this method: consider using replace() instead.

count TAG
     *Instance method, inherited.* Returns the number of occurences of a
     field; in a boolean context, this tells you whether a given field
     exists:

          ### Was a "Subject:" field given?
          $subject_was_given = $head->count('subject');

     The TAG is treated in a case-insensitive manner.  This method returns
     some false value if the field doesn't exist, and some true value if
     it does.

decode [FORCE]
     *Instance method, DEPRECATED.* Go through all the header fields,
     looking for RFC-1522-style "Q" (quoted-printable, sort of) or "B"
     (base64) encoding, and decode them in-place.  Fellow Americans, you
     probably don't know what the hell I'm talking about.  Europeans,
     Russians, et al, you probably do.  `:-)'.

     *This method has been deprecated.* See `decode_headers', see
     MIME/Parser, for the full reasons.  If you absolutely
     must use it and don't like the warning, then provide a FORCE:

          "I_NEED_TO_FIX_THIS"
                 Just shut up and do it.  Not recommended.
                 Provided only for those who need to keep old scripts functioning.

          "I_KNOW_WHAT_I_AM_DOING"
                 Just shut up and do it.  Not recommended.
                 Provided for those who REALLY know what they are doing.

     *What this method does.* For an example, let's consider a valid email
     header you might get:

          From: =?US-ASCII?Q?Keith_Moore?= <moore@cs.utk.edu>
          To: =?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= <keld@dkuug.dk>
          CC: =?ISO-8859-1?Q?Andr=E9_?= Pirard <PIRARD@vm1.ulg.ac.be>
          Subject: =?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=
           =?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=
           =?US-ASCII?Q?.._cool!?=

     That basically decodes to (sorry, I can only approximate the Latin
     characters with 7 bit sequences /o and 'e):

          From: Keith Moore <moore@cs.utk.edu>
          To: Keld J/orn Simonsen <keld@dkuug.dk>
          CC: Andr'e  Pirard <PIRARD@vm1.ulg.ac.be>
          Subject: If you can read this you understand the example... cool!

     Note: currently, the decodings are done without regard to the
     character set: thus, the Q-encoding `=F8' is simply translated to the
     octet (hexadecimal `F8'), period.  For piece-by-piece decoding of a
     given field, you want the array context of
     `MIME::Word::decode_mimewords()'.

     Warning: the CRLF+SPACE separator that splits up long encoded words
     into shorter sequences (see the Subject: example above) gets lost
     when the field is unfolded, and so decoding after unfolding causes a
     spurious space to be left in the field.  *THEREFORE: if you're going
     to decode, do so BEFORE unfolding!*

     This method returns the self object.

     *Thanks to Kent Boortz for providing the idea, and the baseline
     RFC-1522-decoding code.*

delete TAG,[INDEX]
     *Instance method, inherited.* Delete all occurences of the field
     named TAG.

          ### Remove some MIME information:
          $head->delete('MIME-Version');
          $head->delete('Content-type');

get TAG,[INDEX]
     *Instance method, inherited.* Get the contents of field TAG.

     If a *numeric INDEX* is given, returns the occurence at that index,
     or undef if not present:

          ### Print the first and last 'Received:' entries (explicitly):
          print "First, or most recent: ", $head->get('received', 0), "\n";
          print "Last, or least recent: ", $head->get('received',-1), "\n";

     If *no INDEX* is given, but invoked in a scalar context, then INDEX
     simply defaults to 0:

          ### Get the first 'Received:' entry (implicitly):
          my $most_recent = $head->get('received');

     If *no INDEX* is given, and invoked in an array context, then all
     occurences of the field are returned:

          ### Get all 'Received:' entries:
          my @all_received = $head->get('received');

get_all FIELD
     *Instance method.* Returns the list of all occurences of the field,
     or the empty list if the field is not present:

          ### How did it get here?
          @history = $head->get_all('Received');

     Note: I had originally experimented with having get() return all
     occurences when invoked in an array context... but that causes a lot
     of accidents when you get careless and do stuff like this:

          print "\u$field: ", $head->get($field), "\n";

     It also made the intuitive behaviour unclear if the INDEX argument
     was given in an array context.  So I opted for an explicit approach
     to asking for all occurences.

print [OUTSTREAM]
     *Instance method, override.* Print the header out to the given
     OUTSTREAM, or the currently-selected filehandle if none.  The
     OUTSTREAM may be a filehandle, or any object that responds to a
     print() message.

     The override actually lets you print to any object that responds to a
     print() method.  This is vital for outputting MIME entities to
     scalars.

     Also, it defaults to the *currently-selected* filehandle if none is
     given (not STDOUT!), so *please* supply a filehandle to prevent
     confusion.

stringify
     *Instance method.* Return the header as a string.  You can also
     invoke it as as_string.

unfold [FIELD]
     *Instance method, inherited.* Unfold (remove newlines in) the text of
     all occurences of the given FIELD.  If the FIELD is omitted, all
     fields are unfolded.  Returns the "self" object.

MIME-specific methods
---------------------

   All of the following methods extract information from the following
fields:

     Content-type
     Content-transfer-encoding
     Content-disposition

   Be aware that they do not just return the raw contents of those fields,
and in some cases they will fill in sensible (I hope) default values.  Use
get() or `mime_attr()' if you need to grab and process the raw field text.

   Note: some of these methods are provided both as a convenience and for
backwards-compatibility only, while others (like recommended_filename())
*really do have to be in MIME::Head to work properly,* since they look for
their value in more than one field.  However, if you know that a value is
restricted to a single field, you should really use the Mail::Field
interface to get it.

mime_attr ATTR,[VALUE]
     A quick-and-easy interface to set/get the attributes in structured
     MIME fields:

          $head->mime_attr("content-type"         => "text/html");
          $head->mime_attr("content-type.charset" => "US-ASCII");
          $head->mime_attr("content-type.name"    => "homepage.html");

     This would cause the final output to look something like this:

          Content-type: text/html; charset=US-ASCII; name="homepage.html"

     Note that the special empty sub-field tag indicates the anonymous
     first sub-field.

     *Giving VALUE as undefined* will cause the contents of the named
     subfield to be deleted:

          $head->mime_attr("content-type.charset" => undef);

     *Supplying no VALUE argument* just returns the attribute's value, or
     undefined if it isn't there:

          $type = $head->mime_attr("content-type");      ### text/html
          $name = $head->mime_attr("content-type.name"); ### homepage.html

     In all cases, the new/current value is returned.

mime_encoding
     *Instance method.* Try *real hard* to determine the content transfer
     encoding (e.g., `"base64"', `"binary"'), which is returned in
     all-lowercase.

     If no encoding could be found, the default of `"7bit"' is returned.
     I quote from RFC-1521 section 5:

          This is the default value -- that is, "Content-Transfer-Encoding: 7BIT"
          is assumed if the Content-Transfer-Encoding header field is not present.

mime_type [DEFAULT]
     *Instance method.* Try `real hard' to determine the content type
     (e.g., `"text/plain"', `"image/gif"', `"x-weird-type"', which is
     returned in all-lowercase.  "Real hard" means that if no content type
     could be found, the default (usually `"text/plain"') is returned.
     From RFC-1521 section 7.1:

          The default Content-Type for Internet mail is
          "text/plain; charset=us-ascii".

     Unless this is a part of a "multipart/digest", in which case
     "message/rfc822" is the default.  Note that you can also set the
     default, but you shouldn't: normally only the MIME parser uses this
     feature.

multipart_boundary
     *Instance method.* If this is a header for a multipart message,
     return the "encapsulation boundary" used to separate the parts.  The
     boundary is returned exactly as given in the `Content-type:' field;
     that is, the leading double-hyphen (-) is not prepended.

     Well, *almost* exactly... this passage from RFC-1521 dictates that we
     remove any trailing spaces:

          If a boundary appears to end with white space, the white space
          must be presumed to have been added by a gateway, and must be deleted.

     Returns undef (not the empty string) if either the message is not
     multipart, if there is no specified boundary, or if the boundary is
     illegal (e.g., if it is empty after all trailing whitespace has been
     removed).

recommended_filename
     *Instance method.* Return the recommended external filename.  This is
     used when extracting the data from the MIME stream.

     Returns undef if no filename could be suggested.

NOTES
=====

Why have separate objects for the entity, head, and body?
     See the documentation for the MIME-tools distribution for the
     rationale behind this decision.

Why assume that MIME headers are email headers?
     I quote from Achim Bohnet, who gave feedback on v.1.9 (I think he's
     using the word "header" where I would use "field"; e.g., to refer to
     "Subject:", "Content-type:", etc.):

          There is also IMHO no requirement [for] MIME::Heads to look
          like [email] headers; so to speak, the MIME::Head [simply stores]
          the attributes of a complex object, e.g.:

          new MIME::Head type => "text/plain",
                         charset => ...,
                         disposition => ..., ... ;

     I agree in principle, but (alas and dammit) RFC-1521 says otherwise.
     RFC-1521 [MIME] headers are a syntactic subset of RFC-822 [email]
     headers.  Perhaps a better name for these modules would be RFC1521::
     instead of MIME::, but we're a little beyond that stage now.

     In my mind's eye, I see an abstract class, call it MIME::Attrs, which
     does what Achim suggests... so you could say:

          my $attrs = new MIME::Attrs type => "text/plain",
          				 charset => ...,
                                      disposition => ..., ... ;

     We could even make it a superclass of MIME::Head: that way, MIME::Head
     would have to implement its interface, and allow itself to be
     initiallized from a MIME::Attrs object.

     However, when you read RFC-1521, you begin to see how much MIME
     information is organized by its presence in particular fields.  I
     imagine that we'd begin to mirror the structure of RFC-1521 fields
     and subfields to such a degree that this might not give us a
     tremendous gain over just having MIME::Head.

Why all this "occurence" and "index" jazz?  Isn't every field unique?
     Aaaaaaaaaahh....no.

     Looking at a typical mail message header, it is sooooooo tempting to
     just store the fields as a hash of strings, one string per hash entry.
     Unfortunately, there's the little matter of the `Received:' field,
     which (unlike `From:', `To:', etc.) will often have multiple
     occurences; e.g.:

          Received: from gsfc.nasa.gov by eryq.pr.mcs.net  with smtp
              (Linux Smail3.1.28.1 #5) id m0tStZ7-0007X4C;
          	 Thu, 21 Dec 95 16:34 CST
          Received: from rhine.gsfc.nasa.gov by gsfc.nasa.gov
          	 (5.65/Ultrix3.0-C) id AA13596;
          	 Thu, 21 Dec 95 17:20:38 -0500
          Received: (from eryq@localhost) by rhine.gsfc.nasa.gov
          	 (8.6.12/8.6.12) id RAA28069;
          	 Thu, 21 Dec 1995 17:27:54 -0500
          Date: Thu, 21 Dec 1995 17:27:54 -0500
          From: Eryq <eryq@rhine.gsfc.nasa.gov>
          Message-Id: <199512212227.RAA28069@rhine.gsfc.nasa.gov>
          To: eryq@eryq.pr.mcs.net
          Subject: Stuff and things

     The `Received:' field is used for tracing message routes, and although
     it's not generally used for anything other than human debugging, I
     didn't want to inconvenience anyone who actually wanted to get at that
     information.

     I also didn't want to make this a special case; after all, who knows
     what other fields could have multiple occurences in the future?  So,
     clearly, multiple entries had to somehow be stored multiple times...
     and the different occurences had to be retrievable.

AUTHOR
======

   Eryq (`eryq@zeegee.com'), ZeeGee Software Inc (`http://www.zeegee.com').

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

   The more-comprehensive filename extraction is courtesy of Lee E.
Brotzman, Advanced Data Solutions.

VERSION
=======

   $Revision: 5.403 $ $Date: 2000/11/04 19:54:46 $

low-calorie MIME generator
**************************

NAME
====

   MIME::Lite - low-calorie MIME generator

SYNOPSIS
========

     use MIME::Lite;

     Create a single-part message:

     ### Create a new single-part message, to send a GIF file:
     $msg = MIME::Lite->new(
                  From     =>'me@myhost.com',
                  To       =>'you@yourhost.com',
                  Cc       =>'some@other.com, some@more.com',
                  Subject  =>'Helloooooo, nurse!',
                  Type     =>'image/gif',
                  Encoding =>'base64',
                  Path     =>'hellonurse.gif'
     		 );

   Create a multipart message (i.e., one with attachments):

     ### Create a new multipart message:
     $msg = MIME::Lite->new(
                  From    =>'me@myhost.com',
                  To      =>'you@yourhost.com',
                  Cc      =>'some@other.com, some@more.com',
                  Subject =>'A message with 2 parts...',
                  Type    =>'multipart/mixed'
     		 );

     ### Add parts (each "attach" has same arguments as "new"):
     $msg->attach(Type     =>'TEXT',
                  Data     =>"Here's the GIF file you wanted"
     		 );
     $msg->attach(Type     =>'image/gif',
                  Path     =>'aaa000123.gif',
                  Filename =>'logo.gif'
     		 );

   Output a message:

     ### Format as a string:
     $str = $msg->as_string;

     ### Print to a filehandle (say, a "sendmail" stream):
     $msg->print(\*SENDMAIL);

   Send a message:

     ### Send in the "best" way (the default is to use "sendmail"):
     $msg->send;

DESCRIPTION
===========

   In the never-ending quest for great taste with fewer calories, we
proudly present: *MIME::Lite*.

   MIME::Lite is intended as a simple, standalone module for generating
(not parsing!) MIME messages... specifically, it allows you to output a
simple, decent single- or multi-part message with text or binary
attachments.  It does not require that you have the Mail:: or MIME::
modules installed.

   You can specify each message part as either the literal data itself (in
a scalar or array), or as a string which can be given to open() to get a
readable filehandle (e.g., "<filename" or "somecommand|").

   You don't need to worry about encoding your message data: this module
will do that for you.  It handles the 5 standard MIME encodings.

   If you need more sophisticated behavior, please get the MIME-tools
package instead.  I will be more likely to add stuff to that toolkit over
this one.

MORE EXAMPLES
=============

Attach a GIF to a text message
------------------------------

   This will create a multipart message exactly as above, but using the
"attach to singlepart" hack:

     ### Create a new multipart message:
     $msg = MIME::Lite->new(
                  From    =>'me@myhost.com',
                  To      =>'you@yourhost.com',
                  Cc      =>'some@other.com, some@more.com',
                  Subject =>'A message with 2 parts...',
                  Type    =>'TEXT',
                  Data    =>"Here's the GIF file you wanted"
                  );

     ### Attach a part:
     $msg->attach(Type     =>'image/gif',
                  Path     =>'aaa000123.gif',
                  Filename =>'logo.gif'
                  );

Send an HTML document... with images included!
----------------------------------------------

     $msg = MIME::Lite->new(
                  To      =>'you@yourhost.com',
                  Subject =>'HTML with in-line images!',
                  Type    =>'multipart/related'
                  );
     $msg->attach(Type => 'text/html',
                  Data => qq{ <body>
                              Here's <i>my</i> image:
                              <img src="cid:myimage.gif">
                              </body> }
                  );
     $msg->attach(Type => 'image/gif',
                  Id   => 'myimage.gif',
                  Path => '/path/to/somefile.gif',
                  );
     $msg->send();

Output a message to a filehandle
--------------------------------

     ### Write it to a filehandle:
     $msg->print(\*STDOUT);

     ### Write just the header:
     $msg->print_header(\*STDOUT);

     ### Write just the encoded body:
     $msg->print_body(\*STDOUT);

Get a message as a string
-------------------------

     ### Get entire message as a string:
     $str = $msg->as_string;

     ### Get just the header:
     $str = $msg->header_as_string;

     ### Get just the encoded body:
     $str = $msg->body_as_string;

Change how messages are sent
----------------------------

     ### Do something like this in your 'main':
     if ($I_DONT_HAVE_SENDMAIL) {
        MIME::Lite->send('smtp', "smtp.myisp.net", Timeout=>60);
     }

     ### Now this will do the right thing:
     $msg->send;         ### will now use Net::SMTP as shown above

FAQ
===

How do I prevent "Content" headers from showing up in my mail reader?
---------------------------------------------------------------------

   Apparently, some people are using mail readers which display the MIME
headers like "Content-disposition", and they want MIME::Lite not to
generate them "because they look ugly".

   Sigh.

   Y'know, kids, those headers aren't just there for cosmetic purposes.
They help ensure that the message is *understood* correctly by mail
readers.  But okay, you asked for it, you got it...  here's how you can
suppress the standard MIME headers.  Before you send the message, do this:

     $msg->scrub;

   You can scrub() any part of a multipart message independently; just be
aware that it works recursively.  Before you scrub, note the rules that I
follow:

Content-type
     You can safely scrub the "content-type" attribute if, and only if,
     the part is of type "text/plain" with charset "us-ascii".

Content-transfer-encoding
     You can safely scrub the "content-transfer-encoding" attribute if,
     and only if, the part uses "7bit", "8bit", or "binary" encoding.  You
     are far better off doing this if your lines are under 1000
     characters.  Generally, that means you can scrub it for plain text,
     and you can not scrub this for images, etc.

Content-disposition
     You can safely scrub the "content-disposition" attribute if you trust
     the mail reader to do the right thing when it decides whether to show
     an attachment inline or as a link.  Be aware that scrubbing both the
     content-disposition and the content-type means that there is no way
     to "recommend" a filename for the attachment!

     Note: there are reports of brain-dead MUAs out there that do the
     wrong thing if you *provide* the content-disposition.  If your
     attachments keep showing up inline or vice-versa, try scrubbing this
     attribute.

Content-length
     You can always scrub "content-length" safely.

How do I give my attachment a [different] recommended filename?
---------------------------------------------------------------

   By using the Filename option (which is different from Path!):

     $msg->attach(Type => "image/gif",
                  Path => "/here/is/the/real/file.GIF",
                  Filename => "logo.gif");

   You should not put path information in the Filename.

PUBLIC INTERFACE
================

Global configuration
--------------------

   To alter the way the entire module behaves, you have the following
methods/options:

MIME::Lite->quiet()
     This `classmethod|' in this node can be used to suppress/unsuppress
     all warnings coming from this module.

MIME::Lite->send()
     When used as a `classmethod|' in this node, this can be used to
     specify a different default mechanism for sending message.  The
     initial default is:

          MIME::Lite->send("sendmail", "/usr/lib/sendmail -t -oi -oem");

     However, you should consider the similar but smarter and taint-safe
     variant:

          MIME::Lite->send("sendmail");

     Or, for non-Unix users:

          MIME::Lite->send("smtp");

$MIME::Lite::PARANOID
     If true, we won't attempt to use MIME::Base64/MIME::QuotedPrint, even
     if they're available.  Default is false.

$MIME::Lite::AUTO_ENCODE
     If true, automatically choose the encoding from the content type.
     Default is *true*.

$MIME::Lite::AUTO_CC
     If true, automatically send to the Cc/Bcc addresses for
     send_by_smtp().  Default is *true*.

$MIME::Lite::AUTO_VERIFY
     If true, check paths to attachments right before printing, raising an
     exception if any path is unreadable.  Default is *true*.

Construction
------------

new [PARAMHASH]
     *Class method, constructor.* Create a new message object.

     If any arguments are given, they are passed into `build()'; otherwise,
     just the empty object is created.

attach [OBJECT|PARAMHASH]
     *Instance method.* Add a new part to this message, and return the new
     part.

     You can attach a MIME::Lite OBJECT, or have it create one by
     specifying a PARAMHASH that will be automatically given to new().

     One of the possibly-quite-useful hacks thrown into this is the
     "attach-to-singlepart" hack: if you attempt to attach a part (let's
     call it "part 1") to a message that doesn't have a content-type of
     "multipart" or "message", the following happens:

        * A new part (call it "part 0") is made.

        * The MIME attributes and data (but not the other headers) are cut
          from the "self" message, and pasted into "part 0".

        * The "self" is turned into a "multipart/mixed" message.

        * The new "part 0" is added to the "self", and *then* "part 1" is
          added.

     One of the nice side-effects is that you can create a text message
     and then add zero or more attachments to it, much in the same way
     that a user agent like Netscape allows you to do.

build [PARAMHASH]
     *Class/instance method, initializer.* Create (or initialize) a MIME
     message object.  Normally, you'll use the following keys in PARAMHASH:

          * Data, FH, or Path      (either one of these, or none if multipart)
          * Type                   (e.g., "image/jpeg")
          * From, To, and Subject  (if this is the "top level" of a message)

     The PARAMHASH can contain the following keys:

    (fieldname)
          Any field you want placed in the message header, taken from the
          standard list of header fields (you don't need to worry about
          case):

               Bcc           Encrypted     Received      Sender
               Cc            From          References    Subject
               Comments	  Keywords      Reply-To      To
               Content-*	  Message-ID    Resent-*      X-*
               Date          MIME-Version  Return-Path
                             Organization

          To give experienced users some veto power, these fields will be
          set after the ones I set... so be careful: *don't set any MIME
          fields* (like `Content-type') unless you know what you're doing!

          To specify a fieldname that's not in the above list, even one
          that's identical to an option below, just give it with a
          trailing `":"', like `"My-field:"'.  When in doubt, that always
          signals a mail field (and it sort of looks like one too).

    Data
          *Alternative to "Path" or "FH".* The actual message data.  This
          may be a scalar or a ref to an array of strings; if the latter,
          the message consists of a simple concatenation of all the
          strings in the array.

    Datestamp
          *Optional.* If given true (or omitted), we force the creation of
          a `Date:' field stamped with the current date/time if this is a
          top-level message.  You may want this if using `send_by_smtp()|'
          in this node.  If you don't want this to be done, either provide
          your own Date or explicitly set this to false.

    Disposition
          *Optional.* The content disposition, `"inline"' or
          `"attachment"'.  The default is `"inline"'.

    Encoding
          *Optional.* The content transfer encoding that should be used to
          encode your data:

               Use encoding:     | If your message contains:
               ------------------------------------------------------------
               7bit              | Only 7-bit text, all lines <1000 characters
               8bit              | 8-bit text, all lines <1000 characters
               quoted-printable  | 8-bit text or long lines (more reliable than "8bit")
               base64            | Largely non-textual data: a GIF, a tar file, etc.

          The default is taken from the Type; generally it is "binary" (no
          encoding) for text/*, message/*, and multipart/*, and "base64"
          for everything else.  A value of `"binary"' is generally not
          suitable for sending anything but ASCII text files with lines
          under 1000 characters, so consider using one of the other values
          instead.

          In the case of "7bit"/"8bit", long lines are automatically
          chopped to legal length; in the case of "7bit", all 8-bit
          characters are automatically removed.  This may not be what you
          want, so pick your encoding well!  For more info, see `"A MIME
          PRIMER"' in this node.

    FH
          *Alternative to "Data" or "Path".* Filehandle containing the
          data, opened for reading.  See "ReadNow" also.

    Filename
          *Optional.* The name of the attachment.  You can use this to
          supply a recommended filename for the end-user who is saving the
          attachment to disk, if the one in the Path is inadequate, or if
          you're using the Data argument.  You should not put path
          information in here (e.g., no "/" or "\" or ":" characters).

    Id
          *Optional.* Same as setting "content-id".

    Length
          *Optional.* Set the content length explicitly.  Normally, this
          header is automatically computed, but only under certain
          circumstances (see `"Limitations"' in this node).

    Path
          *Alternative to "Data" or "FH".* Path to a file containing the
          data... actually, it can be any open()able expression.  If it
          looks like a path, the last element will automatically be
          treated as the filename.  See "ReadNow" also.

    ReadNow
          *Optional, for use with "Path".* If true, will open the path and
          slurp the contents into core now.  This is useful if the Path
          points to a command and you don't want to run the command over
          and over if outputting the message several times.  *Fatal
          exception* raised if the open fails.

    Top
          *Optional.* If defined, indicates whether or not this is a
          "top-level" MIME message.  The parts of a multipart message are
          not top-level.  Default is true.

    Type
          *Optional.* The MIME content type, or one of these special
          values (case-sensitive):

               "TEXT"   means "text/plain"
               "BINARY" means "application/octet-stream"

          The default is `"TEXT"'.

     A picture being worth 1000 words (which is of course 2000 bytes, so
     it's probably more of an "icon" than a "picture", but I digress...),
     here are some examples:

          $msg = MIME::Lite->build(
                     From     => 'yelling@inter.com',
                     To       => 'stocking@fish.net',
                     Subject  => "Hi there!",
                     Type     => 'TEXT',
                     Encoding => '7bit',
                     Data     => "Just a quick note to say hi!");

          $msg = MIME::Lite->build(
                     From     => 'dorothy@emerald-city.oz',
                     To       => 'gesundheit@edu.edu.edu',
                     Subject  => "A gif for U"
                     Type     => 'image/gif',
                     Path     => "/home/httpd/logo.gif");

          $msg = MIME::Lite->build(
                     From     => 'laughing@all.of.us',
                     To       => 'scarlett@fiddle.dee.de',
                     Subject  => "A gzipp'ed tar file",
                     Type     => 'x-gzip',
                     Path     => "gzip < /usr/inc/somefile.tar |",
                     ReadNow  => 1,
                     Filename => "somefile.tgz");

     To show you what's really going on, that last example could also have
     been written:

          $msg = new MIME::Lite;
          $msg->build(Type     => 'x-gzip',
                      Path     => "gzip < /usr/inc/somefile.tar |",
                      ReadNow  => 1,
                      Filename => "somefile.tgz");
          $msg->add(From    => "laughing@all.of.us");
          $msg->add(To      => "scarlett@fiddle.dee.de");
          $msg->add(Subject => "A gzipp'ed tar file");

Setting/getting headers and attributes
--------------------------------------

add TAG,VALUE
     Add field TAG with the given VALUE to the end of the header.  The TAG
     will be converted to all-lowercase, and the VALUE will be made "safe"
     (returns will be given a trailing space).

     *Beware:* any MIME fields you "add" will override any MIME attributes
     I have when it comes time to output those fields.  Normally, you will
     use this method to add *non-MIME* fields:

          $msg->add("Subject" => "Hi there!");

     Giving VALUE as an arrayref will cause all those values to be added.
     This is only useful for special multiple-valued fields like
     "Received":

          $msg->add("Received" => ["here", "there", "everywhere"]

     Giving VALUE as the empty string adds an invisible placeholder to the
     header, which can be used to suppress the output of the "Content-*"
     fields or the special  "MIME-Version" field.  When suppressing
     fields, you should use replace() instead of add():

          $msg->replace("Content-disposition" => "");

     Note: add() is probably going to be more efficient than replace(), so
     you're better off using it for most applications if you are certain
     that you don't need to delete() the field first.

     Note: the name comes from Mail::Header.

attr ATTR,[VALUE]
     Set MIME attribute ATTR to the string VALUE.  ATTR is converted to
     all-lowercase.  This method is normally used to set/get MIME
     attributes:

          $msg->attr("content-type"         => "text/html");
          $msg->attr("content-type.charset" => "US-ASCII");
          $msg->attr("content-type.name"    => "homepage.html");

     This would cause the final output to look something like this:

          Content-type: text/html; charset=US-ASCII; name="homepage.html"

     Note that the special empty sub-field tag indicates the anonymous
     first sub-field.

     Giving VALUE as undefined will cause the contents of the named
     subfield to be deleted.

     Supplying no VALUE argument just returns the attribute's value:

          $type = $msg->attr("content-type");        ### returns "text/html"
          $name = $msg->attr("content-type.name");   ### returns "homepage.html"

delete TAG
     Delete field TAG with the given VALUE to the end of the header.  The
     TAG will be converted to all-lowercase.

          $msg->delete("Subject");

     Note: the name comes from Mail::Header.

fields
     Return the full header for the object, as a ref to an array of `[TAG,
     VALUE]' pairs, where each TAG is all-lowercase.  Note that any fields
     the user has explicitly set will override the corresponding MIME
     fields that we would otherwise generate.  So, don't say...

          $msg->set("Content-type" => "text/html; charset=US-ASCII");

     unless you want the above value to override the "Content-type" MIME
     field that we would normally generate.

     Note: I called this "fields" because the header() method of
     Mail::Header returns something different, but similar enough to be
     confusing.

filename [FILENAME]
     Set the filename which this data will be reported as.  This actually
     sets both "standard" attributes.

     With no argument, returns the filename as dictated by the
     content-disposition.

get TAG,[INDEX]
     Get the contents of field TAG, which might have been set with set()
     or replace().  Returns the text of the field.

          $ml->get('Subject', 0);

     If the optional 0-based INDEX is given, then we return the INDEX'th
     occurence of field TAG.  Otherwise, we look at the context: In a
     scalar context, only the first (0th) occurence of the field is
     returned; in an array context, all occurences are returned.

     Warning: this should only be used with non-MIME fields.  Behavior
     with MIME fields is TBD, and will raise an exception for now.

get_length
     Recompute the content length for the message *if the process is
     trivial*, setting the "content-length" attribute as a side-effect:

          $msg->get_length;

     Returns the length, or undefined if not set.

     Note: the content length can be difficult to compute, since it
     involves assembling the entire encoded body and taking the length of
     it (which, in the case of multipart messages, means freezing all the
     sub-parts, etc.).

     This method only sets the content length to a defined value if the
     message is a singlepart with `"binary"' encoding, and the body is
     available either in-core or as a simple file.  Otherwise, the content
     length is set to the undefined value.

     Since content-length is not a standard MIME field anyway (that's
     right, kids: it's not in the MIME RFCs, it's an HTTP thing), this
     seems pretty fair.

replace TAG,VALUE
     Delete all occurences of fields named TAG, and add a new field with
     the given VALUE.  TAG is converted to all-lowercase.

     *Beware* the special MIME fields (MIME-version, Content-*): if you
     "replace" a MIME field, the replacement text will override the
     *actual* MIME attributes when it comes time to output that field.  So
     normally you use attr() to change MIME fields and add()/replace() to
     change *non-MIME* fields:

          $msg->replace("Subject" => "Hi there!");

     Giving VALUE as the *empty string* will effectively *prevent* that
     field from being output.  This is the correct way to suppress the
     special MIME fields:

          $msg->replace("Content-disposition" => "");

     Giving VALUE as *undefined* will just cause all explicit values for
     TAG to be deleted, without having any new values added.

     Note: the name of this method  comes from Mail::Header.

scrub
     *This is Alpha code.  If you use it, please let me know how it goes.*
     Recursively goes through the "parts" tree of this message and tries
     to find MIME attributes that can be removed.  With an array argument,
     removes exactly those attributes; e.g.:

          $msg->scrub(['content-disposition', 'content-length']);

     Is the same as recursively doing:

          $msg->replace('Content-disposition' => '');
          $msg->replace('Content-length'      => '');

Setting/getting message data
----------------------------

binmode [OVERRIDE]
     With no argument, returns whether or not it thinks that the data (as
     given by the "Path" argument of `build()') should be read using
     binmode() (for example, when `read_now()' is invoked).

     The default behavior is that any content type other than `text/*' or
     `message/*' is binmode'd; this should in general work fine.

     With a defined argument, this method sets an explicit "override"
     value.  An undefined argument unsets the override.  The new current
     value is returned.

data [DATA]
     Get/set the literal DATA of the message.  The DATA may be either a
     scalar, or a reference to an array of scalars (which will simply be
     joined).

     Warning: setting the data causes the "content-length" attribute to be
     recomputed (possibly to nothing).

path [PATH]
     Get/set the PATH to the message data.

     Warning: setting the path recomputes any existing "content-length"
     field, and re-sets the "filename" (to the last element of the path if
     it looks like a simple path, and to nothing if not).

fh [FILEHANDLE]
     Get/set the FILEHANDLE which contains the message data.

     Takes a filehandle as an input and stores it in the object.  This
     routine is similar to path(); one important difference is that no
     attempt is made to set the content length.

resetfh [FILEHANDLE]
     Set the current position of the filehandle back to the beginning.
     Only applies if you used "FH" in build() or attach() for this message.

     Returns false if unable to reset the filehandle (since not all
     filehandles are seekable).

read_now
     Forces data from the path/filehandle (as specified by `build()') to
     be read into core immediately, just as though you had given it
     literally with the Data keyword.

     Note that the in-core data will always be used if available.

     Be aware that everything is slurped into a giant scalar: you may not
     want to use this if sending tar files!  The benefit of not reading in
     the data is that very large files can be handled by this module if
     left on disk until the message is output via print() or
     `print_body()'.

sign PARAMHASH
     Sign the message.  This forces the message to be read into core,
     after which the signature is appended to it.

    Data
          As in `build()': the literal signature data.  Can be either a
          scalar or a ref to an array of scalars.

    Path
          As in `build()': the path to the file.

     If no arguments are given, the default is:

          Path => "$ENV{HOME}/.signature"

     The content-length is recomputed.

verify_data
     *Instance method.* Verify that all "paths" to attached data exist,
     recursively.  It might be a good idea for you to do this before a
     print(), to prevent accidental partial output if a file might be
     missing.  Raises exception if any path is not readable.

Output
------

print [OUTHANDLE]
     *Instance method.* Print the message to the given output handle, or
     to the currently-selected filehandle if none was given.

     All OUTHANDLE has to be is a filehandle (possibly a glob ref), or any
     object that responds to a print() message.

print_body [OUTHANDLE]
     *Instance method.* Print the body of a message to the given output
     handle, or to the currently-selected filehandle if none was given.

     All OUTHANDLE has to be is a filehandle (possibly a glob ref), or any
     object that responds to a print() message.

     *Fatal exception* raised if unable to open any of the input files, or
     if a part contains no data, or if an unsupported encoding is
     encountered.

print_header [OUTHANDLE]
     *Instance method.* Print the header of the message to the given
     output handle, or to the currently-selected filehandle if none was
     given.

     All OUTHANDLE has to be is a filehandle (possibly a glob ref), or any
     object that responds to a print() message.

as_string
     *Instance method.* Return the entire message as a string, with a
     header and an encoded body.

body_as_string
     *Instance method.* Return the encoded body as a string.  This is the
     portion after the header and the blank line.

     Note: actually prepares the body by "printing" to a scalar.  Proof
     that you can hand the `print*()' methods any blessed object that
     responds to a print() message.

header_as_string
     *Instance method.* Return the header as a string.

Sending
-------

send
send HOW, HOWARGS...
     *Class/instance method.* This is the principal method for sending
     mail, and for configuring how mail will be sent.

     *As an instance method* (with no arguments), sends the message by
     whatever means has been set up (the default is to use the Unix
     "sendmail" program).  Returns whatever the mail-handling routine
     returns: this should be true on success, false/exception on error:

          $msg = MIME::Lite->new(From=>...);
          $msg->send || die "you DON'T have mail!";

     *As a class method* (with a HOW argument and optional HOWARGS), sets
     up how the instance method will work for all objects until further
     notice It treats HOW as a facility name, with optional HOWARGS
     handled by the facility (and returns the previous HOW and HOWARGS as
     an array).  There are three facilities:

    "sendmail", ARGS...
          Send a message by piping it into the "sendmail" command.  Uses
          the `send_by_sendmail()|' in this node method, giving it the
          ARGS.  This usage implements (and deprecates) the sendmail()
          method.

    "smtp", [HOSTNAME]
          Send a message by SMTP, using optional HOSTNAME as SMTP-sending
          host.  Uses the `send_by_smtp()|' in this node method.

    "sub", \&SUBREF, ARGS...
          Sends a message MSG by invoking the subroutine SUBREF of your
          choosing, with MSG as the first argument, and ARGS following.

     *For example:* let's say you're on an OS which lacks the usual Unix
     "sendmail" facility, but you've installed something a lot like it, and
     you need to configure your Perl script to use this "sendmail.exe"
     program.  Do this following in your script's setup:

          MIME::Lite->send('sendmail', "d:\\programs\\sendmail.exe");

     Then, whenever you need to send a message $msg, just say:

          $msg->send;

     That's it.  Now, if you ever move your script to a Unix box, all you
     need to do is change that line in the setup and you're done.  All of
     your $msg->send invocations will work as expected.

send_by_sendmail SENDMAILCMD
send_by_sendmail PARAM=>VALUE, ...
     *Instance method.* Send message via an external "sendmail" program
     (this will probably only work out-of-the-box on Unix systems).

     Returns true on success, false or exception on error.

     You can specify the program and all its arguments by giving a single
     string, SENDMAILCMD.  Nothing fancy is done; the message is simply
     piped in.

     However, if your needs are a little more advanced, you can specify
     zero or more of the following PARAM/VALUE pairs; a Unix-style,
     taint-safe "sendmail" command will be constructed for you:

    Sendmail
          Full path to the program to use.  Default is "/usr/lib/sendmail".

    BaseArgs
          Ref to the basic array of arguments we start with.  Default is
          `["-t", "-oi", "-oem"]'.

    SetSender
          Unless this is *explicitly* given as false, we attempt to
          automatically set the -f argument to the first address that can
          be extracted from the "From:" field of the message (if there is
          one).

          *What is the -f, and why do we use it?* Suppose we did not use
          -f, and you gave an explicit "From:" field in your message: in
          this case, the sendmail "envelope" would indicate the real user
          your process was running under, as a way of preventing mail
          forgery.  Using the -f switch causes the sender to be set in the
          envelope as well.

          *So when would I NOT want to use it?* If sendmail doesn't regard
          you as a "trusted" user, it will permit the -f but also add an
          "X-Authentication-Warning" header to the message to indicate a
          forged envelope.  To avoid this, you can either (1) have
          SetSender be false, or (2) make yourself a trusted user by
          adding a T configuration     command to your *sendmail.cf* file
            (e.g.: `Teryq' if the script is running as user "eryq").

    FromSender
          If defined, this is identical to setting SetSender to true,
          except that instead of looking at the "From:" field we use the
          address given by this option.  Thus:

               FromSender => 'me@myhost.com'

send_by_smtp ARGS...
     *Instance method.* Send message via SMTP, using Net::SMTP.  The
     optional ARGS are sent into Net::SMTP::new(): usually, these are

          MAILHOST, OPTION=>VALUE, ...

     Note that the list of recipients is taken from the "To", "Cc" and
     "Bcc" fields.

     Returns true on success, false or exception on error.

sendmail COMMAND...
     *Class method, DEPRECATED.* Declare the sender to be "sendmail", and
     set up the "sendmail" command.  *You should use send() instead.*

Miscellaneous
-------------

quiet ONOFF
     *Class method.* Suppress/unsuppress all warnings coming from this
     module.

          MIME::Lite->quiet(1);       ### I know what I'm doing

     I recommend that you include that comment as well.  And while you
     type it, say it out loud: if it doesn't feel right, then maybe you
     should reconsider the whole line.  `;-)'

NOTES
=====

Benign limitations
------------------

   This is "lite", after all...

   * There's no parsing.  Get MIME-tools if you need to parse MIME
     messages.

   * MIME::Lite messages are currently not interchangeable with either
     Mail::Internet or MIME::Entity objects.  This is a completely
     separate module.

   * A content-length field is only inserted if the encoding is binary,
     the message is a singlepart, and all the document data is available
     at `build()' time by virtue of residing in a simple path, or in-core.
     Since content-length is not a standard MIME field anyway (that's
     right, kids: it's not in the MIME RFCs, it's an HTTP thing), this
     seems pretty fair.

   * MIME::Lite alone cannot help you lose weight.  You must supplement
     your use of MIME::Lite with a healthy diet and exercise.

Cheap and easy mailing
----------------------

   I thought putting in a default "sendmail" invocation wasn't too bad an
idea, since a lot of Perlers are on UNIX systems.  The out-of-the-box
configuration is:

     MIME::Lite->send('sendmail', "/usr/lib/sendmail -t -oi -oem");

   By the way, these arguments to sendmail are:

     -t      Scan message for To:, Cc:, Bcc:, etc.

     -oi     Do NOT treat a single "." on a line as a message terminator.
             As in, "-oi vey, it truncated my message... why?!"

     -oem    On error, mail back the message (I assume to the
             appropriate address, given in the header).
             When mail returns, circle is complete.  Jai Guru Deva -oem.

   Note that these are the same arguments you get if you configure to use
the smarter, taint-safe mailing:

     MIME::Lite->send('sendmail');

   If you get "X-Authentication-Warning" headers from this, you can forgo
diddling with the envelope by instead specifying:

     MIME::Lite->send('sendmail', SetSender=>0);

   And, if you're not on a Unix system, or if you'd just rather send mail
some other way, there's always:

     MIME::Lite->send('smtp', "smtp.myisp.net");

   Or you can set up your own subroutine to call.  In any case, check out
the `send()|' in this node method.

WARNINGS
========

Good-vs-bad email addresses with send_by_smtp()
-----------------------------------------------

   If using `send_by_smtp()|' in this node, be aware that you are forcing
MIME::Lite to extract email addresses out of a possible list provided in
the `To:', `Cc:', and `Bcc:' fields.  This is tricky stuff, and as such
only the following sorts of addresses will work reliably:

     username
     full.name@some.host.com
     "Name, Full" <full.name@some.host.com>

   This last form is discouraged because SMTP must be able to get at the
name or *name@domain* portion.

   *Disclaimer:* MIME::Lite was never intended to be a Mail User Agent, so
please don't expect a full implementation of RFC-822.  Restrict yourself to
the common forms of Internet addresses described herein, and you should be
fine.  If this is not feasible, then consider using MIME::Lite to prepare
your message only, and using Net::SMTP explicitly to send your message.

Formatting of headers delayed until print()
-------------------------------------------

   This class treats a MIME header in the most abstract sense, as being a
collection of high-level attributes.  The actual RFC-822-style header
fields are not constructed until it's time to actually print the darn
thing.

Encoding of data delayed until print()
--------------------------------------

   When you specify message bodies (in `build()|' in this node or
`attach()|' in this node) - whether by FH, Data, or Path - be warned that
we don't attempt to open files, read filehandles, or encode the data until
`print()|' in this node is invoked.

   In the past, this created some confusion for users of sendmail who gave
the wrong path to an attachment body, since enough of the print() would
succeed to get the initial part of the message out.  Nowadays,
$AUTO_VERIFY is used to spot-check the Paths given before the mail
facility is employed.  A whisker slower, but tons safer.

   Note that if you give a message body via FH, and try to print() a
message twice, the second print() will not do the right thing unless you
explicitly rewind the filehandle.

   You can get past these difficulties by using the ReadNow option,
provided that you have enough memory to handle your messages.

MIME attributes are separate from header fields!
------------------------------------------------

   *Important:* the MIME attributes are stored and manipulated separately
from the message header fields; when it comes time to print the header
out, *any explicitly-given header fields override the ones that would be
created from the MIME attributes.*  That means that this:

     ### DANGER ### DANGER ### DANGER ### DANGER ### DANGER ###
     $msg->add("Content-type", "text/html; charset=US-ASCII");

   will set the exact `"Content-type"' field in the header I write,
*regardless of what the actual MIME attributes are.*

   *This feature is for experienced users only,* as an escape hatch in case
the code that normally formats MIME header fields isn't doing what you
need.  And, like any escape hatch, it's got an alarm on it: MIME::Lite
will warn you if you attempt to set() or replace() any MIME header field.
Use attr() instead.

Beware of lines consisting of a single dot
------------------------------------------

   Julian Haight noted that MIME::Lite allows you to compose messages with
lines in the body consisting of a single ".".  This is true: it should be
completely harmless so long as "sendmail" is used with the -oi option (see
`"Cheap and easy mailing"' in this node).

   However, I don't know if using Net::SMTP to transfer such a message is
equally safe.  Feedback is welcomed.

   My perspective: I don't want to magically diddle with a user's message
unless absolutely positively necessary.  Some users may want to send files
with "." alone on a line; my well-meaning tinkering could seriously harm
them.

A MIME PRIMER
=============

Content types
-------------

   The "Type" parameter of `build()' is a *content type*.  This is the
actual type of data you are sending.  Generally this is a string of the
form `"majortype/minortype"'.

   Here are the major MIME types.  A more-comprehensive listing may be
found in RFC-2046.

application
     Data which does not fit in any of the other categories, particularly
     data to be processed by some type of application program.
     `application/octet-stream', `application/gzip',
     `application/postscript'...

audio
     Audio data.  `audio/basic'...

image
     Graphics data.  `image/gif', `image/jpeg'...

message
     A message, usually another mail or MIME message.  `message/rfc822'...

multipart
     A message containing other messages.  `multipart/mixed',
     `multipart/alternative'...

text
     Textual data, meant for humans to read.  `text/plain', `text/html'...

video
     Video or video+audio data.  `video/mpeg'...

Content transfer encodings
--------------------------

   The "Encoding" parameter of `build()'.  This is how the message body is
packaged up for safe transit.

   Here are the 5 major MIME encodings.  A more-comprehensive listing may
be found in RFC-2045.

  1. Basically, no real encoding is done.  However, this label guarantees
     that no 8-bit characters are present, and that lines do not exceed
     1000 characters in length.

  2. Basically, no real encoding is done.  The message might contain 8-bit
     characters, but this encoding guarantees that lines do not exceed 1000
     characters in length.

  3. binary No encoding is done at all.  Message might contain 8-bit
     characters, and lines might be longer than 1000 characters long.

     The most liberal, and the least likely to get through mail gateways.
     Use sparingly, or (better yet) not at all.

  4. base64 Like "uuencode", but very well-defined.  This is how you
     should send essentially binary information (tar files, GIFs, JPEGs,
     etc.).

  5. quoted-printable Useful for encoding messages which are textual in
     nature, yet which contain non-ASCII characters (e.g., Latin-1,
     Latin-2, or any other 8-bit alphabet).

VERSION
=======

   $Id: Lite.pm,v 2.106 2000/11/21 08:16:32 eryq Exp $

CHANGE LOG
==========

Version 2.106   (2000/11/21)
     Added Alpha version of scrub() to make it easy for people to suppress
     the printing of unwanted MIME attributes (like Content-length).
     *Thanks to the many people who asked for this.*

     Headers with empty-strings for their values are no longer printed.
     This seems sensible, and helps us implement scrub().

Version 2.105   (2000/10/14)
     The regression-test failure was identified, and it was my fault.
     Apparently some of the \-quoting in my "autoloaded" code was making
     Perl 5.6 unhappy.  For this nesting-related idiocy, a nesting kaiku.
     *Thanks to Scott Schwartz for identifying the problem.*

          In a pattern, my
             backslash-s dwells peacefully,
          unambiguous --

             but I embed it
                in a double-quoted string
             doubling the backslash --

                interpolating
                   that same double-quoted string
                in other patterns --

                   and, worlds within worlds,
                      I single-quote the function
                   to autoload it --

                changing the meaning
             of the backslash and the 's';
          and Five-Point-Six growls.

Version 2.104   (2000/09/28)
     Now attempts to load and use Mail::Address for parsing email
     addresses before falling back to our own method.  *Thanks to numerous
     people for suggesting this.*

          Parsing addresses
             is too damn hard. One last hope:
          Let Graham Barr do it!

     For the curious, the version of Mail::Address appears as the "A"
     number in the X-Mailer:

          X-Mailer: MIME::Lite 2.104  (A1.15; B2.09; Q2.03)

     Added FromSender option to send_by_sendmail().  *Thanks to Bill
     Moseley for suggesting this feature.*

Version 2.101   (2000/06/06)
     Major revision to print_body() and body_as_string() so that "body"
     really means "the part after the header", which is what most people
     would want in this context.  This is not how it was used 1.x, where
     "body" only meant "the body of a simple singlepart".  Hopefully, this
     change will solve many problems and create very few ones.

     Added support for attaching a part to a "message/rfc822", treating
     the "message" type as a multipart-like container.

     Now takes care not to include "Bcc:" in header when using
     send_by_smtp, as a safety precaution against qmail's behavior.
     *Thanks to Tatsuhiko Miyagawa for identifying this problem.*

     Improved efficiency of many stringifying operations by using
     string-arrays which are joined, instead of doing multiple appends to
     a scalar.

     Cleaned up the "examples" directory.

Version 1.147   (2000/06/02)
     Fixed buglet where lack of Cc:/Bcc: was causing extract_addrs to emit
     "undefined variable" warnings.  Also, lack of a "To:" field now
     causes a croak.  *Thanks to David Mitchell for the bug report and
     suggested patch.*

Version 1.146   (2000/05/18)
     Fixed bug in parsing of addresses; please read the WARNINGS section
     which describes recommended address formats for "To:", "Cc:", etc.
     Also added automatic inclusion of a UT "Date:" at top level unless
     explicitly told not to.  *Thanks to Andy Jacobs for the bug report
     and the suggestion.*

Version 1.145   (2000/05/06)
     Fixed bug in encode_7bit(): a lingering `/e' modifier was removed.
     *Thanks to Michael A. Chase for the patch.*

Version 1.142   (2000/05/02)
     Added new, taint-safe invocation of "sendmail", one which also sets
     up the -f option.  Unfortunately, I couldn't make this automatic: the
     change could have broken a lot of code out there which used
     send_by_sendmail() with unusual "sendmail" variants.  So you'll have
     to configure "send" to use the new mechanism:

          MIME::Lite->send('sendmail');       ### no args!

     *Thanks to Jeremy Howard for suggesting these features.*

Version 1.140   (2000/04/27)
     Fixed bug in support for "To", "Cc", and "Bcc" in send_by_smtp():
     multiple (comma-separated) addresses should now work fine.  We try
     real hard to extract addresses from the flat text strings.  *Thanks
     to John Mason for motivating this change.*

     Added automatic verification that attached data files exist, done
     immediately before the "send" action is invoked.  To turn this off,
     set $MIME::Lite::AUTO_VERIFY to false.

Version 1.137   (2000/03/22)
     Added support for "Cc" and "Bcc" in send_by_smtp().  To turn this
     off, set $MIME::Lite::AUTO_CC to false.  *Thanks to Lucas Maneos for
     the patch, and tons of others for the suggestion.*

     Chooses a better default content-transfer-encoding if the content-type
     is "image/*", "audio/*", etc.  To turn this off, set
     $MIME::Lite::AUTO_ENCODE to false.  *Thanks to many folks for the
     suggestion.*

     Fixed bug in QP-encoding where a non-local $_ was being modified.
     *Thanks to Jochen Stenzel for finding this very obscure bug!*

     Removed references to $`, $', and $& (bad variables which slow things
     down).

     Added an example of how to send HTML files with enclosed in-line
     images, per popular demand.

Version 1.133   (1999/04/17)
     Fixed bug in "Data" handling: arrayrefs were not being handled
     properly.

Version 1.130   (1998/12/14)
     Added much larger and more-flexible send() facility.  *Thanks to
     Andrew McRae (and Optimation New Zealand Ltd) for the Net::SMTP
     interface.  Additional thanks to the many folks who requested this
     feature.*

     Added get() method for extracting basic attributes.

     New... "t" tests!

Version 1.124   (1998/11/13)
     Folded in filehandle (FH) support in build/attach.  *Thanks to Miko
     O'Sullivan for the code.*

Version 1.122   (1998/01/19)
     MIME::Base64 and MIME::QuotedPrint are used if available.

     The 7bit encoding no longer does "escapes"; it merely strips 8-bit
     characters.

Version 1.121   (1997/04/08)
     Filename attribute is now no longer ignored by build().  *Thanks to
     Ian Smith for finding and patching this bug.*

Version 1.120   (1997/03/29)
     Efficiency hack to speed up MIME::Lite::IO_Scalar.  *Thanks to David
     Aspinwall for the patch.*

Version 1.116   (1997/03/19)
     Small bug in our private copy of encode_base64() was patched.
     *Thanks to Andreas Koenig for pointing this out.*

     New, prettier way of specifying mail message headers in `build()'.

     New quiet method to turn off warnings.

     Changed "stringify" methods to more-standard "as_string" methods.

Version 1.112   (1997/03/06)
     Added `read_now()', and binmode() method for our non-Unix-using
     brethren: file data is now read using binmode() if appropriate.
     *Thanks to Xiangzhou Wang for pointing out this bug.*

Version 1.110   (1997/03/06)
     Fixed bug in opening the data filehandle.

Version 1.102   (1997/03/01)
     Initial release.

Version 1.101   (1997/03/01)
     Baseline code.

TERMS AND CONDITIONS
====================

   Copyright (c) 1997 by Eryq.  Copyright (c) 1998 by ZeeGee Software Inc.
All rights reserved.  This program is free software; you can redistribute
it and/or modify it under the same terms as Perl itself.

   This software comes with NO WARRANTY of any kind.  See the COPYING file
in the distribution for details.

NUTRITIONAL INFORMATION
=======================

   For some reason, the US FDA says that this is now required by law on
any products that bear the name "Lite"...

     MIME::Lite                |
     ------------------------------------------------------------
     Serving size:             | 1 module
     Servings per container:   | 1
     Calories:                 | 0
     Fat:                      | 0g
       Saturated Fat:          | 0g

   Warning: for consumption by hardware only!  May produce indigestion in
humans if taken internally.

AUTHOR
======

   Eryq (`eryq@zeegee.com').  President, ZeeGee Software Inc.
(`http://www.zeegee.com').

   Created: 11 December 1996.  Ho ho ho.

Provide routine to transform a HTML page in a MIME-Lite mail
************************************************************

NAME
====

   MIME::Lite::HTML - Provide routine to transform a HTML page in a
MIME-Lite mail

SYNOPSIS
========

     use MIME::Lite;
     use MIME::Lite::HTML;

     my $mailHTML = new MIME::Lite::HTML
          From     => 'MIME-Lite@alianwebserver.com',
        To       => 'alian@jupiter',
        Subject => 'Mail in HTML with images';

     $MIMEmail = $mailHTML->parse('http://www.alianwebserver.com');
     $MIMEmail->send; # or for win user : $mail->send_by_smtp('smtp.fai.com');

DESCRIPTION
===========

   This module provide routine to transform a HTML page in MIME::Lite mail.
So you need this module to use MIME-Lite-HTML possibilities

What's happen ?
---------------

   The job done is:

   * Get the file (LWP) if needed

   * Parse page to find include images

   * Attach them to mail with adequat cid

   * Include external CSS,Javascript file

   * Replace relative url with absolute one

Usage
-----

   It can be used by example in a HTML newsletter. You make a classic HTML
page, and give just url to MIME::Lite::HTML.

Construction
------------

   MIME-Lite-HTML use a MIME-Lite object, build with

     --> multipart/alternative
     ------> text/plain if present
     ------> multipart/related
     -------------> text/html
     -------------> each images

Documentation
-------------

   Additionnal documentation can be found here:

   * MIME-lite module

   * RFC 822, RFC 1521, RFC 1522 and specially RFC 2257 (MIME Encapsulation
     of Aggregate Documents, such as HTML)

Clients tested
--------------

   HTML in mail is not a standart, so this module can't work with all mail
clients.

   Clients who has been tested:

   * Outlook Express : 100% ok

   * Netscape Messager : 100% ok

   * Eudora : Two problems : Two additional headers will be displayed in
     HTML part and Eudora didn't recognize multipart/alternative part as
     describe in RFC 2257 so text and HTML part will be displayed both,
     text part in first. Version 1.0 of this module correct major problem
     of headers with image include in HTML part.  May be a solution is not
     use mail text with MIME-Lite-HTML, and use MIME-Lite for text mail.
     Ask your users what they want ...

VERSION
=======

   $Revision: 1.1 $

METHODS
=======

new(%hash)
----------

   Create a new instance of MIME::Lite::HTML.

   %hash can have this key : [Proxy], [Debug], [HashTemplate] Others keys
are use with MIME::Lite constructor.

   This MIME-Lite keys are: Bcc, Encrypted, Received, Sender, Cc, From,
References, Subject, Comments, Keywords, Reply-To To, Content-*,
Message-ID,Resent-*, X-*,Date,MIME-Version,Return-Path, Organization

   $hash{'HashTemplate'} is a reference to a hash. If present,
MIME::Lite::HTML will substitute <? $name ?> with
$hash{'HashTemplate'}{'name'} when parse url to send.
$hash{'HashTemplate'} can be used too for include data for subelement. Ex:
$hash{'HashTemplate'}{'http://www.alianwebserver.com/images/sommaire.gif'}=\@data;
or
$hash{'HashTemplate'}{'http://www.alianwebserver.com/script.js'}="alert("Hello
world");";

   When module find the image
http://www.alianwebserver.com/images/sommaire.gif in buffer, it don't get
image with LWP but use data found in $hash{'HashTemplate'}.

parse($html, [$url_txt], [$url_base])
-------------------------------------

   Subroutine used for created HTML mail with MIME-Lite

   Parameters:

$html
     Url of HTML file to send, can be a local file. If $url is not an url
     (http or https or ftp or file or nntp), $url is used as a buffer.
     Example : http://www.alianwebserver.com, file://c|/tmp/index.html or
     '<img src=toto.gif>'.

$url_txt
     Url of text part to send for person who doesn't support HTML mail.
     As $html, $url_txt can be a simple buffer.

$url_base
     $url_base is used if $html is a buffer, for get element found in HTML
     buffer.

   Return the MIME::Lite part to send

Private methods
===============

include_css($gabarit,$root)
---------------------------

   (private)

   Search in HTML buffer ($gabarit) to remplace call to extern CSS file
with his content. $root is original absolute url where css file will be
found.

include_javascript($gabarit,$root)
----------------------------------

   (private)

   Search in HTML buffer ($gabarit) to remplace call to extern javascript
file with his content. $root is original absolute url where javascript
file will be found.

input_image($gabarit,$root)
---------------------------

   (private)

   Search in HTML buffer ($gabarit) to remplace input form image with his
cid

   Return final buffer and list of MIME::Lite part

link_form($gabarit,$root)
-------------------------

   (private)

   Replace link to formulaire with absolute link

fill_template($masque,$vars)
----------------------------

     $masque : Path of template
     $vars : hash ref with keys/val to substitue

   Give template with remplaced variables Ex: if $$vars{age}=12, and
$masque have

     J'ai <? $age ?> ans,

   this function give:

     J'ai 12 ans,

Error Handling
==============

   The set_err routine is used privately. You can ask for an array of all
the errors which occured inside the parse routine by calling:

   @errors = $mailHTML->errstr;

   If no errors where found, it'll return undef.

AUTHOR
======

   Alain BARBET alian@alianwebserver.com

experimental class for parsing MIME streams
*******************************************

NAME
====

   MIME::Parser - experimental class for parsing MIME streams

SYNOPSIS
========

   Before reading further, you should see MIME/Tools, to
make sure that you understand where this module fits into the grand scheme
of things.  Go on, do it now.  I'll wait.

   Ready?  Ok...

Basic usage examples
--------------------

     ### Create a new parser object:
     my $parser = new MIME::Parser;

     ### Tell it where to put things:
     $parser->output_under("/tmp");

     ### Parse an input filehandle:
     $entity = $parser->parse(\*STDIN);

     ### Congratulations: you now have a (possibly multipart) MIME entity!
     $entity->dump_skeleton;          # for debugging

Examples of input
-----------------

     ### Parse from filehandles:
     $entity = $parser->parse(\*STDIN);
     $entity = $parser->parse(IO::File->new("some command|");

     ### Parse from any object that supports getline() and read():
     $entity = $parser->parse($myHandle);

     ### Parse an in-core MIME message:
     $entity = $parser->parse_data($message);

     ### Parse an MIME message in a file:
     $entity = $parser->parse_open("/some/file.msg");

     ### Parse an MIME message out of a pipeline:
     $entity = $parser->parse_open("gunzip - < file.msg.gz |");

     ### Parse already-split input (as "deliver" would give it to you):
     $entity = $parser->parse_two("msg.head", "msg.body");

Examples of output control
--------------------------

     ### Keep parsed message bodies in core (default outputs to disk):
     $parser->output_to_core(1);

     ### Output each message body to a one-per-message directory:
     $parser->output_under("/tmp");

     ### Output each message body to the same directory:
     $parser->output_dir("/tmp");

     ### Change how nameless message-component files are named:
     $parser->output_prefix("msg");

Examples of error recovery
--------------------------

     ### Normal mechanism:
     eval { $entity = $parser->parse(\*STDIN) };
     if ($@) {
     	$results  = $parser->results;
     	$decapitated = $parser->last_head;  ### get last top-level head
     }

     ### Ultra-tolerant mechanism:
     $parser->ignore_errors(1);
     $entity = eval { $parser->parse(\*STDIN) };
     $error = ($@ || $parser->last_error);

     ### Cleanup all files created by the parse:
     eval { $entity = $parser->parse(\*STDIN) };
     ...
     $parser->filer->purge;

Examples of parser options
--------------------------

     ### Automatically attempt to RFC-1522-decode the MIME headers?
     $parser->decode_headers(1);             ### default is false

     ### Parse contained "message/rfc822" objects as nested MIME streams?
     $parser->extract_nested_messages(0);    ### default is true

     ### Look for uuencode in "text" messages, and extract it?
     $parser->extract_uuencode(1);           ### default is false

     ### Should we forgive normally-fatal errors?
     $parser->ignore_errors(0);              ### default is true

Miscellaneous examples
----------------------

     ### Convert a Mail::Internet object to a MIME::Entity:
     @lines = (@{$mail->header}, "\n", @{$mail->body});
     $entity = $parser->parse_data(\@lines);

DESCRIPTION
===========

   You can inherit from this class to create your own subclasses that
parse MIME streams into MIME::Entity objects.

PUBLIC INTERFACE
================

Construction
------------

new ARGS...
     *Class method.* Create a new parser object.  Once you do this, you
     can then set up various parameters before doing the actual parsing.
     For example:

          my $parser = new MIME::Parser;
          $parser->output_dir("/tmp");
          $parser->output_prefix("msg1");
          my $entity = $parser->parse(\*STDIN);

     Any arguments are passed into `init()'.  Don't override this in your
     subclasses; override init() instead.

init ARGS...
     *Instance method.* Initiallize a new MIME::Parser object.  This is
     automatically sent to a new object; you may want to override it.  If
     you override this, be sure to invoke the inherited method.

init_parse
     *Instance method.* Invoked automatically whenever one of the
     top-level parse() methods is called, to reset the parser to a "ready"
     state.

Altering how messages are parsed
--------------------------------

decode_headers [YESNO]
     *Instance method.* Controls whether the parser will attempt to decode
     all the MIME headers (as per RFC-1522) the moment it sees them.
     *This is not advisable for two very important reasons:*

        * *It screws up the extraction of information from MIME fields.*
          If you fully decode the headers into bytes, you can inadvertently
          transform a parseable MIME header like this:

               Content-type: text/plain; filename="=?ISO-8859-1?Q?Hi=22Ho?="

          into unparseable gobbledygook; in this case:

               Content-type: text/plain; filename="Hi"Ho"

        * *It is information-lossy.*  An encoded string which contains
          both Latin-1 and Cyrillic characters will be turned into a binary
          mishmosh which simply can't be rendered.

     *History.* This method was once the only out-of-the-box way to deal
     with attachments whose filenames had non-ASCII characters.  However,
     since MIME-tools 5.4xx this is no longer necessary.

     *Parameters.* If YESNO is true, decoding is done.  However, you will
     get a warning unless you use one of the special "true" values:

          "I_NEED_TO_FIX_THIS"
                 Just shut up and do it.  Not recommended.
                 Provided only for those who need to keep old scripts functioning.

          "I_KNOW_WHAT_I_AM_DOING"
                 Just shut up and do it.  Not recommended.
                 Provided for those who REALLY know what they are doing.

     If YESNO is false (the default), no attempt at decoding will be done.
     With no argument, just returns the current setting.  *Remember:* you
     can always decode the headers after the parsing has completed (see
     `MIME::Head::decode()|MIME::Head' in this node), or decode the words
     on demand (see MIME/Words).

extract_nested_messages OPTION
     *Instance method.* Some MIME messages will contain a part of type
     `message/rfc822': literally, the text of an embedded
     mail/news/whatever message.  This option controls whether (and how)
     we parse that embedded message.

     If the OPTION is false, we treat such a message just as if it were a
     `text/plain' document, without attempting to decode its contents.

     If the OPTION is true (the default), the body of the `message/rfc822'
     part is parsed by this parser, creating an entity object.  What
     happens then is determined by the actual OPTION:

    NEST or 1
          The default setting.  The contained message becomes the sole
          "part" of the `message/rfc822' entity (as if the containing
          message were a special kind of "multipart" message).  You can
          recover the sub-entity by invoking the `parts()|MIME::Entity' in
          this node method on the `message/rfc822' entity.

    REPLACE
          The contained message replaces the `message/rfc822' entity, as
          though the `message/rfc822' "container" never existed.

          Warning: notice that, with this option, all the header
          information in the `message/rfc822' header is lost.  This might
          seriously bother you if you're dealing with a top-level message,
          and you've just lost the sender's address and the subject line.
          `:-/'.

     *Thanks to Andreas Koenig for suggesting this method.*

extract_uuencode [YESNO]
     *Instance method.* If set true, then whenever we are confronted with
     a message whose effective content-type is "text/plain" and whose
     encoding is 7bit/8bit/binary, we scan the encoded body to see if it
     contains uuencoded data (generally given away by a "begin XXX" line).

     If it does, we explode the uuencoded message into a multipart, where
     the text before the first "begin XXX" becomes the first part, and all
     "begin...end" sections following become the subsequent parts.  The
     filename (if given) is accessible through the normal means.

ignore_errors [YESNO]
     *Instance method.* Controls whether the parser will attempt to ignore
     normally-fatal errors, treating them as warnings and continuing with
     the parse.

     If YESNO is true (the default), many syntax errors are tolerated.  If
     YESNO is false, fatal errors throw exceptions.  With no argument,
     just returns the current setting.

Parsing an input source
-----------------------

parse_data DATA
     *Instance method.* Parse a MIME message that's already in core.  You
     may supply the DATA in any of a number of ways...

        * *A scalar* which holds the message.

        * *A ref to a scalar* which holds the message.  This is an
          efficiency hack.

        * *A ref to an array of scalars.*  They are treated as a stream
          which (conceptually) consists of simply concatenating the
          scalars.

     Returns the parsed MIME::Entity on success.  Throws exception on
     failure.

parse INSTREAM
     *Instance method.* Takes a MIME-stream and splits it into its
     component entities.

     The INSTREAM can be given as a readable FileHandle, an IO::File, a
     globref filehandle (like `\*STDIN'), or as any blessed object
     conforming to the IO:: interface (which minimally implements
     getline() and read()).

     Returns the parsed MIME::Entity on success.  Throws exception on
     failure.

parse_open EXPR
     *Instance method.* Convenience front-end onto parse().  Simply give
     this method any expression that may be sent as the second argument to
     open() to open a filehandle for reading.

     Returns the parsed MIME::Entity on success.  Throws exception on
     failure.

parse_two HEADFILE, BODYFILE
     *Instance method.* Convenience front-end onto `parse_open()',
     intended for programs running under mail-handlers like *deliver*,
     which splits the incoming mail message into a header file and a body
     file.  Simply give this method the paths to the respective files.

     Warning: it is assumed that, once the files are cat'ed together,
     there will be a blank line separating the head part and the body part.

     Warning: new implementation slurps files into line array for
     portability, instead of using 'cat'.  May be an issue if your
     messages are large.

     Returns the parsed MIME::Entity on success.  Throws exception on
     failure.

Specifying output destination
-----------------------------

   Warning: in 5.212 and before, this was done by methods of MIME::Parser.
However, since many users have requested fine-tuned control over how this
is done, the logic has been split off from the parser into its own class,
MIME::Parser::Filer Every MIME::Parser maintains an instance of a
MIME::Parser::Filer subclass to manage disk output (see
MIME/Parser/Filer, for details.)

   The benefit to this is that the MIME::Parser code won't be confounded
with a lot of garbage related to disk output.  The drawback is that the
way you override the default behavior will change.

   For now, all the normal public-interface methods are still provided,
but many are only stubs which create or delegate to the underlying
MIME::Parser::Filer object.

filer [FILER]
     *Instance method.* Get/set the FILER object used to manage the output
     of files to disk.  This will be some subclass of
     `MIME::Parser::Filer|MIME::Parser::Filer' in this node.

output_dir DIRECTORY
     *Instance method.* Causes messages to be filed directly into the
     given DIRECTORY.  It does this by setting the underlying `filer()|'
     in this node to a new instance of MIME::Parser::FileInto, and passing
     the arguments into that class' new() method.

     Note: Since this method replaces the underlying filer, you must
     invoke it before doing changing any attributes of the filer, like the
     output prefix; otherwise those changes will be lost.

output_under BASEDIR, OPTS...
     *Instance method.* Causes messages to be filed directly into
     subdirectories of the given BASEDIR, one subdirectory per message.
     It does this by setting the underlying `filer()|' in this node to a
     new instance of MIME::Parser::FileUnder, and passing the arguments
     into that class' new() method.

     Note: Since this method replaces the underlying filer, you must
     invoke it before doing changing any attributes of the filer, like the
     output prefix; otherwise those changes will be lost.

output_path HEAD
     *Instance method, DEPRECATED.* Given a MIME head for a file to be
     extracted, come up with a good output pathname for the extracted file.
     Identical to the preferred form:

     $parser->filer->output_path(...args...);

     We just delegate this to the underlying `filer()|' in this node
     object.

output_prefix [PREFIX]
     *Instance method, DEPRECATED.* Get/set the short string that all
     filenames for extracted body-parts will begin with (assuming that
     there is no better "recommended filename").  Identical to the
     preferred form:

     $parser->filer->output_prefix(...args...);

     We just delegate this to the underlying `filer()|' in this node
     object.

evil_filename NAME
     *Instance method, DEPRECATED.* Identical to the preferred form:

     $parser->filer->evil_filename(...args...);

     We just delegate this to the underlying `filer()|' in this node
     object.

output_to_core YESNO
     *Instance method.* Normally, instances of this class output all their
     decoded body data to disk files (via MIME::Body::File).  However, you
     can change this behaviour by invoking this method before parsing:

     If YESNO is false (the default), then all body data goes to disk
     files.

     If YESNO is true, then all body data goes to in-core data structures
     This is a little risky (what if someone emails you an MPEG or a tar
     file, hmmm?) but people seem to want this bit of noose-shaped rope,
     so I'm providing it.  Note that setting this attribute true *does
     not* mean that parser-internal temporary files are avoided!  Use
     `tmp_to_core()|' in this node for that.

     With no argument, returns the current setting as a boolean.

tmp_recycling [YESNO]
     *Instance method.* Normally, tmpfiles are created when needed during
     parsing, and destroyed automatically when they go out of scope.  But
     for efficiency, you might prefer for your parser to attempt to rewind
     and reuse the same file until the parser itself is destroyed.

     If YESNO is true (the default), we allow recycling; tmpfiles persist
     until the parser itself is destroyed.  If YESNO is false, we do not
     allow recycling; tmpfiles persist only as long as they are needed
     during the parse.  With no argument, just returns the current setting.

tmp_to_core [YESNO]
     *Instance method.* Should `new_tmpfile()|' in this node create real
     temp files, or use fake in-core ones?  Normally we allow the creation
     of temporary disk files, since this allows us to handle huge
     attachments even when core is limited.

     If YESNO is true, we implement new_tmpfile() via in-core handles.  If
     YESNO is false (the default), we use real tmpfiles.  With no
     argument, just returns the current setting.

use_inner_files [YESNO]
     *Instance method.* If you are parsing from a handle which supports
     seek() and tell(), then we can avoid tmpfiles completely by using
     IO::InnerFile, if so desired: basically, we simulate a temporary file
     via pointers to virtual start- and end-positions in the input stream.

     If YESNO is false (the default), then we will not use IO::InnerFile.
     If YESNO is true, we use IO::InnerFile if we can.  With no argument,
     just returns the current setting.

     Note: inner files are slower than real tmpfiles, but possibly faster
     than *in-core* tmpfiles... so your choice for this option will
     probably depend on your choice for `tmp_to_core()|' in this node and
     the kind of input streams you are parsing.

Specifying classes to be instantiated
-------------------------------------

interface ROLE,[VALUE]
     *Instance method.* During parsing, the parser normally creates
     instances of certain classes, like MIME::Entity.  However, you may
     want to create a parser subclass that uses your own experimental
     head, entity, etc. classes (for example, your "head" class may
     provide some additional MIME-field-oriented methods).

     If so, then this is the method that your subclass should invoke during
     init.  Use it like this:

          package MyParser;
          @ISA = qw(MIME::Parser);
          ...
          sub init {
          	my $self = shift;
          	$self->SUPER::init(@_);        ### do my parent's init
              $self->interface(ENTITY_CLASS => 'MIME::MyEntity');
          	$self->interface(HEAD_CLASS   => 'MIME::MyHead');
          	$self;                         ### return
          }

     With no VALUE, returns the VALUE currently associated with that ROLE.

new_body_for HEAD
     *Instance method.* Based on the HEAD of a part we are parsing, return
     a new body object (any desirable subclass of MIME::Body) for
     receiving that part's data.

     If you set the output_to_core option to false before parsing (the
     default), then we call `output_path()' and create a new
     MIME::Body::File on that filename.

     If you set the output_to_core option to true before parsing, then you
     get a MIME::Body::InCore instead.

     If you want the parser to do something else entirely, you can
     override this method in a subclass.

new_tmpfile [RECYCLE]
     *Instance method.* Return an IO handle to be used to hold temporary
     data during a parse.  The default uses the standard
     IO::File->new_tmpfile() method unless `tmp_to_core()|' in this node
     dictates otherwise, but you can override this.  You shouldn't need to.

     If you do override this, make certain that the object you return is
     set for binmode(), and is able to handle the following methods:

          read(BUF, NBYTES)
          getline()
          getlines()
          print(@ARGS)
          flush()
          seek(0, 0)

     Fatal exception if the stream could not be established.

     If RECYCLE is given, it is an object returned by a previous invocation
     of this method; to recycle it, this method must effectively rewind and
     truncate it, and return the same object.  If you don't want to support
     recycling, just ignore it and always return a new object.

Parse results and error recovery
--------------------------------

last_error
     *Instance method.* Return the error (if any) that we ignored in the
     last parse.

last_head
     *Instance method.* Return the top-level MIME header of the last
     stream we attempted to parse.  This is useful for replying to people
     who sent us bad MIME messages.

          ### Parse an input stream:
          eval { $entity = $parser->parse(\*STDIN) };
          if (!$entity) {    ### parse failed!
          	my $decapitated = $parser->last_head;
          	...
          }

results
     *Instance method.* Return an object containing lots of info from the
     last entity parsed.  This will be an instance of class
     `MIME::Parser::Results|MIME::Parser::Results' in this node.

OPTIMIZING YOUR PARSER
======================

Maximizing speed
----------------

   Optimum input mechanisms:

     parse()                    YES (if you give it a globref or a
     				    subclass of IO::File)
     parse_open()               YES
     parse_data()               NO  (see below)
     parse_two()                NO  (see below)

   Optimum settings:

     decode_headers()           *** (no real difference; 0 is slightly faster)
     extract_nested_messages()  0   (may be slightly faster, but in
                                     general you want it set to 1)
     output_to_core()           0   (will be MUCH faster)
     tmp_recycling()            1?  (probably, but should be investigated)
     tmp_to_core()              0   (will be MUCH faster)
     use_inner_files()          0   (if tmp_to_core() is 0;
     				    use 1 otherwise)

   *File I/O is much faster than in-core I/O.* Although it *seems* like
slurping a message into core and processing it in-core should be faster...
it isn't.  Reason: Perl's filehandle-based I/O translates directly into
native operating-system calls, whereas the in-core I/O is implemented in
Perl.

   *Inner files are slower than real tmpfiles, but faster than in-core
ones.* If speed is your concern, that's why you should set
use_inner_files(true) if you set tmp_to_core(true): so that we can bypass
the slow in-core tmpfiles if the input stream permits.

   *Native I/O is much faster than object-oriented I/O.* It's much faster
to use <$foo> than $foo->getline.  For backwards compatibilty, this module
must continue to use object-oriented I/O in most places, but if you use
`parse()|' in this node with a "real" filehandle (string, globref, or
subclass of IO::File) then MIME::Parser is able to perform some crucial
optimizations.

   *The parse_two() call is very inefficient.* Currently this is just a
front-end onto parse_data().  If your OS supports it, you're *far* better
off doing something like:

     $parser->parse_open("/bin/cat msg.head msg.body |");

Minimizing memory
-----------------

   Optimum input mechanisms:

     parse()                    YES
     parse_open()               YES
     parse_data()               NO  (in-core I/O will burn core)
     parse_two()                NO  (in-core I/O will burn core)

   Optimum settings:

     decode_headers()           *** (no real difference)
     extract_nested_messages()  *** (no real difference)
     output_to_core()           0   (will use MUCH less memory)
     tmp_recycling()            0?  (promotes faster GC if
                                     tmp_to_core is 1)
     tmp_to_core()              0   (will use MUCH less memory)
     use_inner_files()          *** (no real difference, but set it to 1
     				    if you *must* have tmp_to_core set to 1,
     				    so that you avoid in-core tmpfiles)

Maximizing tolerance of bad MIME
--------------------------------

   Optimum input mechanisms:

     parse()                    *** (doesn't matter)
     parse_open()               *** (doesn't matter)
     parse_data()               *** (doesn't matter)
     parse_two()                *** (doesn't matter)

   Optimum settings:

     decode_headers()           0   (sidesteps problem of bad hdr encodings)
     extract_nested_messages()  0   (sidesteps problems of bad nested messages,
                                     but often you want it set to 1 anyway).
     output_to_core()           *** (doesn't matter)
     tmp_recycling()            *** (doesn't matter)
     tmp_to_core()              *** (doesn't matter)
     use_inner_files()          *** (doesn't matter)

Avoiding disk-based temporary files
-----------------------------------

   Optimum input mechanisms:

     parse()                    YES (if you give it a seekable handle)
     parse_open()               YES (becomes a seekable handle)
     parse_data()               NO  (unless you set tmp_to_core(1))
     parse_two()                NO  (unless you set tmp_to_core(1))

   Optimum settings:

     decode_headers()           *** (doesn't matter)
     extract_nested_messages()  *** (doesn't matter)
     output_to_core()           *** (doesn't matter)
     tmp_recycling              1   (restricts created files to 1 per parser)
     tmp_to_core()              1
     use_inner_files()          1

   *If we can use them, inner files avoid most tmpfiles.* If you parse
from a seekable-and-tellable filehandle, then the internal
process_to_bound() doesn't need to extract each part into a temporary
buffer; it can use IO::InnerFile (*warning:* this will slow down the
parsing of messages with large attachments).

   *You can veto tmpfiles entirely.* If you might not be parsing from a
seekable-and-tellable filehandle, you can set `tmp_to_core()|' in this
node true: this will always use in-core I/O for the buffering (*warning:*
this will slow down the parsing of messages with large attachments).

   *Final resort.* You can always override `new_tmpfile()|' in this node
in a subclass.

WARNINGS
========

Multipart messages are always read line-by-line
     Multipart document parts are read line-by-line, so that the
     encapsulation boundaries may easily be detected.  However, bad MIME
     composition agents (for example, naive CGI scripts) might return
     multipart documents where the parts are, say, unencoded bitmap
     files... and, consequently, where such "lines" might be veeeeeeeeery
     long indeed.

     A better solution for this case would be to set up some form of state
     machine for input processing.  This will be left for future versions.

Multipart parts read into temp files before decoding
     In my original implementation, the MIME::Decoder classes had to be
     aware of encapsulation boundaries in multipart MIME documents.  While
     this decode-while-parsing approach obviated the need for temporary
     files, it resulted in inflexible and complex decoder implementations.

     The revised implementation uses a temporary file (a la tmpfile())
     during parsing to hold the *encoded* portion of the current MIME
     document or part.  This file is deleted automatically after the
     current part is decoded and the data is written to the "body stream"
     object; you'll never see it, and should never need to worry about it.

     Some folks have asked for the ability to bypass this temp-file
     mechanism, I suppose because they assume it would slow down their
     application.  I considered accomodating this wish, but the temp-file
     approach solves a lot of thorny problems in parsing, and it also
     protects against hidden bugs in user applications (what if you've
     directed the encoded part into a scalar, and someone unexpectedly
     sends you a 6 MB tar file?).  Finally, I'm just not conviced that the
     temp-file use adds significant overhead.

Fuzzing of CRLF and newline on input
     RFC-1521 dictates that MIME streams have lines terminated by CRLF
     (`"\r\n"').  However, it is extremely likely that folks will want to
     parse MIME streams where each line ends in the local newline
     character `"\n"' instead.

     An attempt has been made to allow the parser to handle both CRLF and
     newline-terminated input.

Fuzzing of CRLF and newline on output
     The `"7bit"' and `"8bit"' decoders will decode both a `"\n"' and a
     `"\r\n"' end-of-line sequence into a `"\n"'.

     The `"binary"' decoder (default if no encoding specified) still
     outputs stuff verbatim... so a MIME message with CRLFs and no
     explicit encoding will be output as a text file that, on many
     systems, will have an annoying ^M at the end of each line... *but
     this is as it should be*.

Inability to handle multipart boundaries that contain newlines
     First, let's get something straight: *this is an evil, EVIL practice,*
     and is incompatible with RFC-1521... hence, it's not valid MIME.

     If your mailer creates multipart boundary strings that contain
     newlines *when they appear in the message body,* give it two weeks
     notice and find another one.  If your mail robot receives MIME mail
     like this, regard it as syntactically incorrect MIME, which it is.

     Why do I say that?  Well, in RFC-1521, the syntax of a boundary is
     given quite clearly:

          boundary := 0*69<bchars> bcharsnospace

          bchars := bcharsnospace / " "

          bcharsnospace :=    DIGIT / ALPHA / "'" / "(" / ")" / "+" /"_"
                       / "," / "-" / "." / "/" / ":" / "=" / "?"

     All of which means that a valid boundary string *cannot* have
     newlines in it, and any newlines in such a string in the message
     header are expected to be solely the result of *folding* the string
     (i.e., inserting to-be-removed newlines for readability and
     line-shortening *only*).

     Yet, there is at least one brain-damaged user agent out there that
     composes mail like this:

          MIME-Version: 1.0
          Content-type: multipart/mixed; boundary="----ABC-
           123----"
          Subject: Hi... I'm a dork!

          This is a multipart MIME message (yeah, right...)

          ----ABC-
           123----

          Hi there!

     We have *got* to discourage practices like this (and the recent file
     upload idiocy where binary files that are part of a multipart MIME
     message aren't base64-encoded) if we want MIME to stay relatively
     simple, and MIME parsers to be relatively robust.

     *Thanks to Andreas Koenig for bringing a baaaaaaaaad user agent to my
     attention.*

AUTHOR
======

   Eryq (`eryq@zeegee.com'), ZeeGee Software Inc (`http://www.zeegee.com').

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

VERSION
=======

   $Revision: 5.406 $ $Date: 2000/11/12 05:55:11 $

manage file-output of the parser
********************************

NAME
====

   MIME::Parser::Filer - manage file-output of the parser

SYNOPSIS
========

   Before reading further, you should see MIME/Parser,
to make sure that you understand where this module fits into the grand
scheme of things.  Go on, do it now.  I'll wait.

   Ready?  Ok... now read `"DESCRIPTION"' in this node below, and
everything else should make sense.

Public interface
----------------

     ### Create a "filer" of the desired class:
     my $filer = MIME::Parser::FileInto->new($dir);
     my $filer = MIME::Parser::FileUnder->new($basedir);
     ...

     ### Want added security?  Don't let outsiders name your files:
     $filer->ignore_filename(1);

     ### Prepare for the parsing of a new top-level message:
     $filer->init_parse;

     ### Return the path where this message's data should be placed:
     $path = $filer->output_path($head);

Semi-public interface
---------------------

   These methods might be overriden or ignored in some subclasses, so they
don't all make sense in all circumstances:

     ### Tweak the mapping from content-type to extension:
     $emap = $filer->output_extension_map;
     $emap->{"text/html"} = ".htm";

DESCRIPTION
===========

How this class is used when parsing
-----------------------------------

   When a MIME::Parser decides that it wants to output a file to disk, it
uses its "Filer" object - an instance of a MIME::Parser::Filer subclass -
to determine where to put the file.

   Every parser has a single Filer object, which it uses for all parsing.
You can get the Filer for a given $parser like this:

     $filer = $parser->filer;

   At the beginning of each parse(), the filer's internal state is reset
by the parser:

     $parser->filer->init_parse;

   The parser can then get a path for each entity in the message by
handing that entity's header (a MIME::Head) to the filer and having it do
the work, like this:

     $new_file = $parser->filer->output_path($head);

   Since it's nice to be able to clean up after a parse (especially a
failed parse), the parser tells the filer when it has actually used a path:

     $parser->filer->purgeable($new_file);

   Then, if you want to clean up the files which were created for a
particular parse (and also any directories that the Filer created), you
would do this:

     $parser->filer->purge;

Writing your own subclasses
---------------------------

   There are two standard "Filer" subclasses (see below):
MIME::Parser::FileInto, which throws all files from all parses into the
same directory, and MIME::Parser::FileUnder (preferred), which creates a
subdirectory for each message.  Hopefully, these will be sufficient for
most uses, but just in case...

   The only method you have to override is `output_path()|' in this node:

     $filer->output_path($head);

   This method is invoked by MIME::Parser when it wants to put a decoded
message body in an output file.  The method should return a path to the
file to create.  Failure is indicated by throwing an exception.

   The path returned by `output_path()' should be "ready for open()": any
necessary parent directories need to exist at that point.  These
directories can be created by the Filer, if course, and they should be
marked as *purgeable()* if a purge should delete them.

   Actually, if your issue is more where the files go than what they're
named, you can use the default `output_path()|' in this node method and
just override one of its components:

     $dir  = $filer->output_dir($head);
     $name = $filer->output_filename($head);
     ...

PUBLIC INTERFACE
================

MIME::Parser::Filer
-------------------

   This is the abstract superclass of all "filer" objects.

new INITARGS...
     *Class method, constructor.* Create a new outputter for the given
     parser.  Any subsequent arguments are given to init(), which
     subclasses should override for their own use (the default init does
     nothing).

results RESULTS
     *Instance method.* Link this filer to a MIME::Parser::Results object
     which will tally the messages.  Notice that we avoid linking it to the
     parser to avoid circular reference!

init_parse
     *Instance method.* Prepare to start parsing a new message.
     Subclasses should always be sure to invoke the inherited method.

evil_filename FILENAME
     *Instance method.* Is this an evil filename; i.e., one which should
     not be used in generating a disk file name?  It is if any of these
     are true:

          * it is empty
          * it is a string of dots: ".", "..", etc.
          * it contains a known "path" character: '/' '\' ':' '[' ']'
          * it is too long

     If you just want to change this behavior, you should override this
     method in the subclass of MIME::Parser::Filer that you use.

     Warning: at the time this method is invoked, the FILENAME has already
     been unmime'd into the local character set.  If you're using any
     character set other than ASCII, ISO-8859-*, or UTF-8, the
     interpretation of the "path" characters might be very different, and
     you will probably need to override this method.  See `unmime', see
     MIME/WordDecoder, for more details.

     Note: subclasses of MIME::Parser::Filer which override output_path()
     might not consult this method; note, however, that the built-in
     subclasses do consult it.

     *Thanks to Andrew Pimlott for finding a real dumb bug in the original
     version.  Thanks to Nickolay Saukh for noting that evil is in the eye
     of the beholder.*

exorcise_filename FILENAME
     *Instance method.* If a given filename is evil (see `' in this node)
     we try to rescue it by performing some basic operations: shortening
     it, removing bad characters, etc., and checking each against
     evil_filename().

     Returns the exorcised filename (which is guaranteed to not be evil),
     or undef if it could not be salvaged.

     Warning: at the time this method is invoked, the FILENAME has already
     been unmime'd into the local character set.  If you're using anything
     character set other than ASCII, ISO-8859-*, or UTF-8, the
     interpretation of the "path" characters might be very very different,
     and you will probably need to override this method.  See `unmime',
     see MIME/WordDecoder, for more details.

find_unused_path DIR, FILENAME
     *Instance method, subclasses only.* We have decided on an output
     directory and tentative filename, but there is a chance that it might
     already exist.  Keep adding a numeric suffix "-1", "-2", etc. to the
     filename until an unused path is found, and then return that path.

     The suffix is actually added before the first "." in the filename is
     there is one; for example:

          picture.gif       archive.tar.gz      readme
          picture-1.gif     archive-1.tar.gz    readme-1
          picture-2.gif     archive-2.tar.gz    readme-2
          ...               ...                 ...
          picture-10.gif
          ...

     This can be a costly operation, and risky if you don't want files
     renamed, so it is in your best interest to minimize situations where
     these kinds of collisions occur.  Unfortunately, if a multipart
     message gives all of its parts the same recommended filename, and you
     are placing them all in the same directory, this method might be
     unavoidable.

ignore_filename [YESNO]
     *Instance method.* Return true if we should always ignore recommended
     filenames in messages, choosing instead to always generate our own
     filenames.  With argument, sets this value.

     Note: subclasses of MIME::Parser::Filer which override output_path()
     might not honor this setting; note, however, that the built-in
     subclasses honor it.

output_dir HEAD
     *Instance method.* Return the output directory for the given header.
     The default method returns ".".

output_filename HEAD
     *Instance method, subclasses only.* A given recommended filename was
     either not given, or it was judged to be evil.  Return a fake name,
     possibly using information in the message HEADer.  Note that this is
     just the filename, not the full path.

     Used by `output_path()|' in this node.  If you're using the default
     `output_path()', you probably don't need to worry about avoiding
     collisions with existing files; we take care of that in
     `find_unused_path()|' in this node.

output_prefix [PREFIX]
     *Instance method.* Get the short string that all filenames for
     extracted body-parts will begin with (assuming that there is no
     better "recommended filename").  The default is `"msg"'.

     If PREFIX *is not* given, the current output prefix is returned.  If
     PREFIX *is* given, the output prefix is set to the new value, and the
     previous value is returned.

     Used by `output_filename()|' in this node.

     Note: subclasses of MIME::Parser::Filer which override output_path()
     or output_filename() might not honor this setting; note, however,
     that the built-in subclasses honor it.

output_type_ext
     *Instance method.* Return a reference to the hash used by the default
     `output_filename()|' in this node for mapping from content-types to
     extensions when there is no default extension to use.

          $emap = $filer->output_typemap;
          $emap->{'text/plain'} = '.txt';
          $emap->{'text/html'}  = '.html';
          $emap->{'text/*'}     = '.txt';
          $emap->{'*/*'}        = '.dat';

     Note: subclasses of MIME::Parser::Filer which override output_path()
     or output_filename() might not consult this hash; note, however, that
     the built-in subclasses consult it.

output_path HEAD
     *Instance method, subclasses only.* Given a MIME head for a file to
     be extracted, come up with a good output pathname for the extracted
     file.  This is the only method you need to worry about if you are
     building a custom filer.

     The default implementation does a lot of work; subclass implementers
     *really* should try to just override its components instead of the
     whole thing.  It works basically as follows:

          $directory = $self->output_dir($head);

          $filename = $head->recommended_filename();
          if (!$filename or
          	 $self->ignore_filename() or
          	 $self->evil_filename($filename)) {
           	$filename = $self->output_filename($head);
          }

          return $self->find_unused_path($directory, $filename);

     Note: There are many, many, many ways you might want to control the
     naming of files, based on your application.  If you don't like the
     behavior of this function, you can easily define your own subclass of
     MIME::Parser::Filer and override it there.

     Note: Nickolay Saukh pointed out that, given the subjective nature of
     what is "evil", this function really shouldn't warn about an evil
     filename, but maybe just issue a debug message.  I considered that,
     but then I thought: if debugging were off, people wouldn't know why
     (or even if) a given filename had been ignored.  In mail robots that
     depend on externally-provided filenames, this could cause
     hard-to-diagnose problems.  So, the message is still a warning.

     *Thanks to Laurent Amon for pointing out problems with the original
     implementation, and for making some good suggestions.  Thanks also to
     Achim Bohnet for pointing out that there should be a hookless, OO way
     of overriding the output path.*

purge
     *Instance method, final.* Purge all files/directories created by the
     last parse.  This method simply goes through the purgeable list in
     reverse order (see `' in this node) and removes all existing
     files/directories in it.  You should not need to override this method.

purgeable [FILE]
     *Instance method, final.* Add FILE to the list of "purgeable"
     files/directories (those which will be removed if you do a purge()).
     You should not need to override this method.

     If FILE is not given, the "purgeable" list is returned.  This may be
     used for more-sophisticated purging.

     As a special case, invoking this method with a FILE that is an
     arrayref will replace the purgeable list with a copy of the array's
     contents, so [] may be used to clear the list.

     Note that the "purgeable" list is cleared when a parser begins a new
     parse; therefore, if you want to use purge() to do cleanup, you must
     do so before starting a new parse!

MIME::Parser::FileInto
----------------------

   This concrete subclass of MIME::Parser::Filer supports filing into a
given directory.

init DIRECTORY
     *Instance method, initiallizer.* Set the directory where all files
     will go.

MIME::Parser::FileUnder
-----------------------

   This concrete subclass of MIME::Parser::Filer supports filing under a
given directory, using one subdirectory per message, but with all message
parts in the same directory.

init BASEDIR, OPTSHASH...
     *Instance method, initiallizer.* Set the base directory which will
     contain the message directories.  If used, then each parse of begins
     by creating a new subdirectory of BASEDIR where the actual parts of
     the message are placed.  OPTSHASH can contain the following:

    DirName
          Explicitly set the name of the subdirectory which is created.
          The default is to use the time, process id, and a sequence
          number, but you might want a predictable directory.

    Purge
          Automatically purge the contents of the directory (including all
          subdirectories) before each parse.  This is really only needed if
          using an explicit DirName, and is provided as a convenience only.
          Currently we use the 1-arg form of File::Path::rmtree; you should
          familiarize yourself with the caveats therein.

     The output_dir() will return the path to this message-specific
     directory until the next parse is begun, so you can do this:

          use File::Path;

          $parser->output_under("/tmp");
          $ent = eval { $parser->parse_open($msg); };   ### parse
          if (!$ent) {	 ### parse failed
          	rmtree($parser->output_dir);
          	die "parse failed: $@";
          }
          else {               ### parse succeeded
          	...do stuff...
          }

AUTHOR
======

   Eryq (`eryq@zeegee.com'), ZeeGee Software Inc (`http://www.zeegee.com').

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

VERSION
=======

   $Revision: 5.406 $

a line-oriented reader for a MIME::Parser
*****************************************

NAME
====

   MIME::Parser::Reader - a line-oriented reader for a MIME::Parser

SYNOPSIS
========

   This module is used internally by MIME::Parser; you probably don't need
to be looking at it at all.  But just in case...

     ### Create a top-level reader, where chunks end at EOF:
     $rdr = MIME::Parser::Reader->new();

     ### Spawn a child reader, where chunks also end at a boundary:
     $subrdr = $rdr->spawn->add_boundary($bound);

     ### Spawn a child reader, where chunks also end at a given string:
     $subrdr = $rdr->spawn->add_terminator($string);

     ### Read until boundary or terminator:
     $subrdr->read_chunk($in, $out);

DESCRIPTION
===========

   A line-oriented reader which can deal with virtual end-of-stream
defined by a collection of boundaries.

   Warning: this is a private class solely for use by MIME::Parser.  This
class has no official public interface

results of the last entity parsed
*********************************

NAME
====

   MIME::Parser::Results - results of the last entity parsed

SYNOPSIS
========

   Before reading further, you should see MIME/Parser,
to make sure that you understand where this module fits into the grand
scheme of things.  Go on, do it now.  I'll wait.

   Ready?  Ok...

     ### Do parse, get results:
     my $entity = eval { $parser->parse(\*STDIN); };
     my $results  = $parser->results;

     ### Get all messages logged:
     @msgs = $results->msgs;

     ### Get messages of specific types (also tests if there were problems):
     $had_errors   = $results->errors;
     $had_warnings = $results->warnings;

     ### Get outermost header:
     $top_head  = $results->top_head;

DESCRIPTION
===========

   Results from the last MIME::Parser parse.

PUBLIC INTERFACE
================

new
     *Constructor.*

msgs
     *Instance method.* Return all messages that we logged, in order.
     Every message is a string beginning with its type followed by `": "';
     the current types are debug, warning, and error.

errors
     *Instance method.* Return all error messages that we logged, in order.
     A convenience front-end onto msgs().

warnings
     *Instance method.* Return all warning messages that we logged, in
     order.  A convenience front-end onto msgs().

top_head
     *Instance method.* Return the topmost header, if we were able to read
     it.  This may be useful if the parse fails.

AUTHOR
======

   Eryq (`eryq@zeegee.com'), ZeeGee Software Inc (`http://www.zeegee.com').

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

VERSION
=======

   $Revision: 5.403 $

Encoding and decoding of quoted-printable strings
*************************************************

NAME
====

   MIME::QuotedPrint - Encoding and decoding of quoted-printable strings

SYNOPSIS
========

     use MIME::QuotedPrint;

     $encoded = encode_qp($decoded);
     $decoded = decode_qp($encoded);

DESCRIPTION
===========

   This module provides functions to encode and decode strings into the
Quoted-Printable encoding specified in RFC 2045 - *MIME (Multipurpose
Internet Mail Extensions)*.  The Quoted-Printable encoding is intended to
represent data that largely consists of bytes that correspond to printable
characters in the ASCII character set.  Non-printable characters (as
defined by english americans) are represented by a triplet consisting of
the character "=" followed by two hexadecimal digits.

   The following functions are provided:

encode_qp($str)
     This function will return an encoded version of the string given as
     argument.

     Note that encode_qp() does not change newlines `"\n"' to the CRLF
     sequence even though this might be considered the right thing to do
     (RFC 2045 (Q-P Rule #4)).

decode_qp($str);
     This function will return the plain text version of the string given
     as argument.

   If you prefer not to import these routines into your namespace you can
call them as:

     use MIME::QuotedPrint ();
     $encoded = MIME::QuotedPrint::encode($decoded);
     $decoded = MIME::QuotedPrint::decode($encoded);

COPYRIGHT
=========

   Copyright 1995-1997 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

tools - modules for parsing (and creating!) MIME entities
*********************************************************

NAME
====

   MIME-tools - modules for parsing (and creating!) MIME entities

SYNOPSIS
========

   Here's some pretty basic code for *parsing a MIME message,* and
outputting its decoded components to a given directory:

     use MIME::Parser;

     ### Create parser, and set some parsing options:
     my $parser = new MIME::Parser;
     $parser->output_under("$ENV{HOME}/mimemail");

     ### Parse input:
     $entity = $parser->parse(\*STDIN) or die "parse failed\n";

     ### Take a look at the top-level entity (and any parts it has):
     $entity->dump_skeleton;

   Here's some code which *composes and sends a MIME message* containing
three parts: a text file, an attached GIF, and some more text:

     use MIME::Entity;

     ### Create the top-level, and set up the mail headers:
     $top = MIME::Entity->build(Type    =>"multipart/mixed",
                                From    => "me\@myhost.com",
     	                       To      => "you\@yourhost.com",
                                Subject => "Hello, nurse!");

     ### Part #1: a simple text document:
     $top->attach(Path=>"./testin/short.txt");

     ### Part #2: a GIF file:
     $top->attach(Path        => "./docs/mime-sm.gif",
                  Type        => "image/gif",
                  Encoding    => "base64");

     ### Part #3: some literal text:
     $top->attach(Data=>$message);

     ### Send it:
     open MAIL, "| /usr/lib/sendmail -t -oi -oem" or die "open: $!";
     $top->print(\*MAIL);
     close MAIL;

   For more examples, look at the scripts in the examples directory of the
MIME-tools distribution.

DESCRIPTION
===========

   MIME-tools is a collection of Perl5 MIME:: modules for parsing,
decoding, *and generating* single- or multipart (even nested multipart)
MIME messages.  (Yes, kids, that means you can send messages with attached
GIF files).

REQUIREMENTS
============

   You will need the following installed on your system:

     File::Path
     File::Spec
     IPC::Open2              (optional)
     IO::Scalar, ...         from the IO-stringy distribution
     MIME::Base64
     MIME::QuotedPrint
     Net::SMTP
     Mail::Internet, ...     from the MailTools distribution.

   See the Makefile.PL in your distribution for the most-comprehensive
list of prerequisite modules and their version numbers.

A QUICK TOUR
============

Overview of the classes
-----------------------

   Here are the classes you'll generally be dealing with directly:

     (START HERE)            results() .-----------------.
           \                 .-------->| MIME::          |
            .-----------.   /          | Parser::Results |
            | MIME::    |--'           `-----------------'
            | Parser    |--.           .-----------------.
            `-----------'   \ filer()  | MIME::          |
               | parse()     `-------->| Parser::Filer   |
               | gives you             `-----------------'
               | a...                        	      | output_path()
               |                         	      | determines
               |					      | path() of...
               |    head()       .--------.	      |
               |    returns...   | MIME:: | get()      |
               V       .-------->| Head   | etc...     |
            .--------./          `--------'            |
      .---> | MIME:: | 				      |
      `-----| Entity |           .--------.            |
        parts() `--------'\          | MIME:: |           /
        returns            `-------->| Body   |<---------'
        sub-entities    bodyhandle() `--------'
        (if any)        returns...       | open()
                                     | returns...
                                     |
                                     V
                                 .--------. read()
                                 | IO::   | getline()
                                 | Handle | print()
                                 `--------' etc...

   To illustrate, parsing works this way:

   * *The "parser" parses the MIME stream.* A parser is an instance of
     `MIME::Parser'.  You hand it an input stream (like a filehandle) to
     parse a message from: if the parse is successful, the result is an
     "entity".

   * *A parsed message is represented by an "entity".* An entity is an
     instance of `MIME::Entity' (a subclass of Mail::Internet).  If the
     message had "parts" (e.g., attachments), then those parts are
     "entities" as well, contained inside the top-level entity.  Each
     entity has a "head" and a "body".

   * *The entity's "head" contains information about the message.* A
     "head" is an instance of `MIME::Head' (a subclass of `Mail::Header').
     It contains information from the message header: content type,
     sender, subject line, etc.

   * *The entity's "body" knows where the message data is.* You can ask to
     "open" this data source for *reading* or *writing*, and you will get
     back an "I/O handle".

   * *You can open() a "body" and get an "I/O handle" to read/write
     message data.* This handle is an object that is basically like an
     IO::Handle or a FileHandle... it can be any class, so long as it
     supports a small, standard set of methods for reading from or writing
     to the underlying data source.

   A typical multipart message containing two parts - a textual greeting
and an "attached" GIF file - would be a tree of MIME::Entity objects, each
of which would have its own MIME::Head.  Like this:

     .--------.
     | MIME:: | Content-type: multipart/mixed
     | Entity | Subject: Happy Samhaine!
     `--------'
          |
          `----.
         parts |
               |   .--------.
               |---| MIME:: | Content-type: text/plain; charset=us-ascii
               |   | Entity | Content-transfer-encoding: 7bit
               |   `--------'
               |   .--------.
               |---| MIME:: | Content-type: image/gif
                   | Entity | Content-transfer-encoding: base64
                   `--------' Content-disposition: inline;
                                filename="hs.gif"

Parsing messages
----------------

   You usually start by creating an instance of *MIME::Parser* and setting
up certain parsing parameters: what directory to save extracted files to,
how to name the files, etc.

   You then give that instance a readable filehandle on which waits a MIME
message.  If all goes well, you will get back a *MIME::Entity* object (a
subclass of Mail::Internet), which consists of...

   * A *MIME::Head* (a subclass of *Mail::Header*) which holds the MIME
     header data.

   * A *MIME::Body*, which is a object that knows where the body data is.
     You ask this object to "open" itself for reading, and it will hand
     you back an "I/O handle" for reading the data: this is a
     FileHandle-like object, and could be of any class, so long as it
     conforms to a subset of the IO::Handle interface.

   If the original message was a multipart document, the MIME::Entity
object will have a non-empty list of "parts", each of which is in turn a
MIME::Entity (which might also be a multipart entity, etc, etc...).

   Internally, the parser (in MIME::Parser) asks for instances of
*MIME::Decoder* whenever it needs to decode an encoded file.
MIME::Decoder has a mapping from supported encodings (e.g., 'base64') to
classes whose instances can decode them.  You can add to this mapping to
try out new/experiment encodings.  You can also use MIME::Decoder by
itself.

Composing messages
------------------

   All message composition is done via the *MIME::Entity* class.  For
single-part messages, you can use the *MIME::Entity/build* constructor to
create MIME entities very easily.

   For multipart messages, you can start by creating a top-level multipart
entity with *MIME::Entity::build()*, and then use the similar
*MIME::Entity::attach()* method to attach parts to that message.  *Please
note:* what most people think of as "a text message with an attached GIF
file" is *really* a multipart message with 2 parts: the first being the
text message, and the second being the GIF file.

   When building MIME a entity, you'll have to provide two very important
pieces of information: the *content type* and the *content transfer
encoding*.  The type is usually easy, as it is directly determined by the
file format; e.g., an HTML file is `text/html'.  The encoding, however, is
trickier... for example, some HTML files are 7bit-compliant, but others
might have very long lines and would need to be sent `quoted-printable'
for reliability.

   See the section on encoding/decoding for more details, as well as `"A
MIME PRIMER"' in this node.

Sending email
-------------

   Since MIME::Entity inherits directly from Mail::Internet, you can use
the normal Mail::Internet mechanisms to send email.  For example,

     $entity->smtpsend;

Encoding/decoding support
-------------------------

   The *MIME::Decoder* class can be used to encode as well; this is done
when printing MIME entities.  All the standard encodings are supported
(see `"A MIME PRIMER"' in this node for details):

     Encoding:        | Normally used when message contents are:
     -------------------------------------------------------------------
     7bit             | 7-bit data with under 1000 chars/line, or multipart.
     8bit             | 8-bit data with under 1000 chars/line.
     binary           | 8-bit data with some long lines (or no line breaks).
     quoted-printable | Text files with some 8-bit chars (e.g., Latin-1 text).
     base64           | Binary files.

   Which encoding you choose for a given document depends largely on (1)
what you know about the document's contents (text vs binary), and (2)
whether you need the resulting message to have a reliable encoding for
7-bit Internet email transport.

   In general, only `quoted-printable' and base64 guarantee reliable
transport of all data; the other three "no-encoding" encodings simply pass
the data through, and are only reliable if that data is 7bit ASCII with
under 1000 characters per line, and has no conflicts with the multipart
boundaries.

   I've considered making it so that the content-type and encoding can be
automatically inferred from the file's path, but that seems to be asking
for trouble... or at least, for Mail::Cap...

Message-logging
---------------

   MIME-tools is a large and complex toolkit which tries to deal with a
wide variety of external input.  It's sometimes helpful to see what's
really going on behind the scenes.  There are several kinds of messages
logged by the toolkit itself:

Debug messages
     These are printed directly to the STDERR, with a prefix of
     `"MIME-tools: debug"'.

     Debug message are only logged if you have turned `' in this node on
     in the MIME::Tools configuration.

Warning messages
     These are logged by the standard Perl warn() mechanism to indicate an
     unusual situation.  They all have a prefix of `"MIME-tools: warning"'.

     Warning messages are only logged if $^W is set true and MIME::Tools
     is not configured to be `' in this node.

Error messages
     These are logged by the standard Perl warn() mechanism to indicate
     that something actually failed.  They all have a prefix of
     `"MIME-tools: error"'.

     Error messages are only logged if $^W is set true and MIME::Tools is
     not configured to be `' in this node.

Usage messages
     Unlike "typical" warnings above, which warn about problems processing
     data, usage-warnings are for alerting developers of deprecated methods
     and suspicious invocations.

     Usage messages are currently only logged if $^W is set true and
     MIME::Tools is not configured to be `' in this node.

   When a MIME::Parser (or one of its internal helper classes) wants to
report a message, it generally does so by recording the message to the
*MIME::Parser::Results* object immediately before invoking the appropriate
function above.  That means each parsing run has its own trace-log which
can be examined for problems.

Configuring the toolkit
-----------------------

   If you want to tweak the way this toolkit works (for example, to turn
on debugging), use the routines in the *MIME::Tools* module.

debugging
     Turn debugging on or off.  Default is false (off).

          MIME::Tools->debugging(1);

quiet
     Turn the reporting of warning/error messages on or off.  Default is
     true, meaning that these message are silenced.

          MIME::Tools->quiet(1);

version
     Return the toolkit version.

          print MIME::Tools->version, "\n";

THINGS YOU SHOULD DO
====================

Take a look at the examples
---------------------------

   The MIME-Tools distribution comes with an "examples" directory.  The
scripts in there are basically just tossed-together, but they'll give you
some ideas of how to use the parser.

Run with warnings enabled
-------------------------

   Always run your Perl script with -w.  If you see a warning about a
deprecated method, change your code ASAP.  This will ease upgrades
tremendously.

Avoid non-standard encodings
----------------------------

   Don't try to MIME-encode using the non-standard MIME encodings.  It's
just not a good practice if you want people to be able to read your
messages.

Plan for thrown exceptions
--------------------------

   For example, if your mail-handling code absolutely must not die, then
perform mail parsing like this:

     $entity = eval { $parser->parse(\*INPUT) };

   Parsing is a complex process, and some components may throw exceptions
if seriously-bad things happen.  Since "seriously-bad" is in the eye of
the beholder, you're better off *catching* possible exceptions instead of
asking me to propagate undef up the stack.  Use of exceptions in reusable
modules is one of those religious issues we're never all going to agree
upon; thankfully, that's what `eval{}' is good for.

Check the parser results for warnings/errors
--------------------------------------------

   As of 5.3xx, the parser tries extremely hard to give you a
MIME::Entity.  If there were any problems, it logs warnings/errors to the
underlying "results" object (see MIME/Parser/Results).
Look at that object after each parse.  Print out
the warnings and errors, *especially* if messages don't parse the way you
thought they would.

Don't plan on printing exactly what you parsed!
-----------------------------------------------

   *Parsing is a (slightly) lossy operation.* Because of things like
ambiguities in base64-encoding, the following is not going to spit out its
input unchanged in all cases:

     $entity = $parser->parse(\*STDIN);
     $entity->print(\*STDOUT);

   If you're using MIME::Tools to process email, remember to save the data
you parse if you want to send it on unchanged.  This is vital for things
like PGP-signed email.

Understand how international characters are represented
-------------------------------------------------------

   The MIME standard allows for text strings in headers to contain
characters from any character set, by using special sequences which look
like this:

     =?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?=

   To be consistent with the existing Mail::Field classes, MIME::Tools
does not automatically unencode these strings, since doing so would lose
the character-set information and interfere with the parsing of fields
(see `decode_headers', see MIME/Parser, for a full
explanation).  That means you should be prepared to deal with these
encoded strings.

   The most common question then is, *how do I decode these encoded
strings?* The answer depends on what you want to decode them to: ASCII,
Latin1, UTF-8, etc.  Be aware that your "target" representation may not
support all possible character sets you might encounter; for example,
Latin1 (ISO-8859-1) has no way of representing Big5 (Chinese) characters.
A common practice is to represent "untranslateable" characters as "?"s, or
to ignore them completely.

   To unencode the strings into some of the more-popular Western byte
representations (e.g., Latin1, Latin2, etc.), you can use the decoders in
MIME::WordDecoder (see MIME/WordDecoder).  The
simplest way is by using `unmime()', a function wrapped around your
"default" decoder, as follows:

     use MIME::WordDecoder;
     ...
     $subject = unmime $entity->head->get('subject');

   One place this *is* done automatically is in extracting the recommended
filename for a part while parsing.  That's why you should start by setting
up the best "default" decoder if the default target of Latin1 isn't to
your liking.

THINGS I DO THAT YOU SHOULD KNOW ABOUT
======================================

Fuzzing of CRLF and newline on input
------------------------------------

   RFC-1521 dictates that MIME streams have lines terminated by CRLF
(`"\r\n"').  However, it is extremely likely that folks will want to parse
MIME streams where each line ends in the local newline character `"\n"'
instead.

   An attempt has been made to allow the parser to handle both CRLF and
newline-terminated input.

Fuzzing of CRLF and newline when decoding
-----------------------------------------

   The `"7bit"' and `"8bit"' decoders will decode both a `"\n"' and a
`"\r\n"' end-of-line sequence into a `"\n"'.

   The `"binary"' decoder (default if no encoding specified) still outputs
stuff verbatim... so a MIME message with CRLFs and no explicit encoding
will be output as a text file that, on many systems, will have an annoying
^M at the end of each line... *but this is as it should be*.

Fuzzing of CRLF and newline when encoding/composing
---------------------------------------------------

   All encoders currently output the end-of-line sequence as a `"\n"',
with the assumption that the local mail agent will perform the conversion
from newline to CRLF when sending the mail.  However, there probably
should be an option to output CRLF as per RFC-1521.

Inability to handle multipart boundaries with embedded newlines
---------------------------------------------------------------

   Let's get something straight: this is an evil, EVIL practice.  If your
mailer creates multipart boundary strings that contain newlines, give it
two weeks notice and find another one.  If your mail robot receives MIME
mail like this, regard it as syntactically incorrect, which it is.

Ignoring non-header headers
---------------------------

   People like to hand the parser raw messages straight from POP3 or from
a mailbox.  There is often predictable non-header information in front of
the real headers; e.g., the initial "From" line in the following message:

     From - Wed Mar 22 02:13:18 2000
     Return-Path: <eryq@zeegee.com>
     Subject: Hello

   The parser simply ignores such stuff quietly.  Perhaps it shouldn't,
but most people seem to want that behavior.

Fuzzing of empty multipart preambles
------------------------------------

   Please note that there is currently an ambiguity in the way preambles
are parsed in.  The following message fragments both are regarded as
having an empty preamble (where \n indicates a newline character):

     Content-type: multipart/mixed; boundary="xyz"\n
     Subject: This message (#1) has an empty preamble\n
     \n
     --xyz\n
     ...

     Content-type: multipart/mixed; boundary="xyz"\n
     Subject: This message (#2) also has an empty preamble\n
     \n
     \n
     --xyz\n
     ...

   In both cases, the first completely-empty line (after the "Subject")
marks the end of the header.

   But we should clearly ignore the *second* empty line in message #2,
since it fills the role of *"the newline which is only there to make sure
that the boundary is at the beginning of a line"*.  Such newlines are
never part of the content preceding the boundary; thus, there is no
preamble "content" in message #2.

   However, it seems clear that message #1 *also* has no preamble
"content", and is in fact merely a compact representation of an empty
preamble.

Use of a temp file during parsing
---------------------------------

   *Why not do everything in core?* Although the amount of core available
on even a modest home system continues to grow, the size of attachments
continues to grow with it.  I wanted to make sure that even users with
small systems could deal with decoding multi-megabyte sounds and movie
files.  That means not being core-bound.

   As of the released 5.3xx, MIME::Parser gets by with only one temp file
open per parser.  This temp file provides a sort of infinite scratch space
for dealing with the current message part.  It's fast and lightweight, but
you should know about it anyway.

Why do I assume that MIME objects are email objects?
----------------------------------------------------

   Achim Bohnet once pointed out that MIME headers do nothing more than
store a collection of attributes, and thus could be represented as objects
which don't inherit from Mail::Header.

   I agree in principle, but RFC-1521 says otherwise.  RFC-1521 [MIME]
headers are a syntactic subset of RFC-822 [email] headers.  Perhaps a
better name for these modules would have been RFC1521:: instead of MIME::,
but we're a little beyond that stage now.

   When I originally wrote these modules for the CPAN, I agonized for a
long time about whether or not they really should subclass from
Mail::Internet (then at version 1.17).  Thanks to Graham Barr, who
graciously evolved MailTools 1.06 to be more MIME-friendly, unification
was achieved at MIME-tools release 2.0.  The benefits in reuse alone have
been substantial.

A MIME PRIMER
=============

   So you need to parse (or create) MIME, but you're not quite up on the
specifics?  No problem...

Glossary
--------

   Here are some definitions adapted from RFC-1521 explaining the
terminology we use; each is accompanied by the equivalent in MIME:: module
terms...

attachment
     An "attachment" is common slang for any part of a multipart message -
     except, perhaps, for the first part, which normally carries a user
     message describing the attachments that follow (e.g.: "Hey dude,
     here's that GIF file I promised you.").

     In our system, an attachment is just a *MIME::Entity* under the
     top-level entity, probably one of its `parts|MIME::Entity' in this
     node.

body
     The "body" of an `entity|' in this node is that portion of the entity
     which follows the `header|' in this node and which contains the real
     message content.  For example, if your MIME message has a GIF file
     attachment, then the body of that attachment is the base64-encoded
     GIF file itself.

     A body is represented by an instance of *MIME::Body*.  You get the
     body of an entity by sending it a `bodyhandle()|MIME::Entity' in this
     node message.

body part
     One of the parts of the body of a multipart */entity*.  A body part
     has a */header* and a */body*, so it makes sense to speak about the
     body of a body part.

     Since a body part is just a kind of entity, it's represented by an
     instance of *MIME::Entity*.

entity
     An "entity" means either a */message* or a */body part*.  All
     entities have a */header* and a */body*.

     An entity is represented by an instance of *MIME::Entity*.  There are
     instance methods for recovering the `header|MIME::Entity' in this
     node (a *MIME::Head*) and the `body|MIME::Entity' in this node (a
     *MIME::Body*).

header
     This is the top portion of the MIME message, which contains the
     "Content-type", "Content-transfer-encoding", etc.  Every MIME entity
     has a header, represented by an instance of *MIME::Head*.  You get the
     header of an entity by sending it a head() message.

message
     A "message" generally means the complete (or "top-level") message
     being transferred on a network.

     There currently is no explicit package for "messages"; under MIME::,
     messages are streams of data which may be read in from files or
     filehandles.  You can think of the *MIME::Entity* returned by the
     *MIME::Parser* as representing the full message.

Content types
-------------

   This indicates what kind of data is in the MIME message, usually as
*majortype/minortype*.  The standard major types are shown below.  A
more-comprehensive listing may be found in RFC-2046.

application
     Data which does not fit in any of the other categories, particularly
     data to be processed by some type of application program.
     `application/octet-stream', `application/gzip',
     `application/postscript'...

audio
     Audio data.  `audio/basic'...

image
     Graphics data.  `image/gif', `image/jpeg'...

message
     A message, usually another mail or MIME message.  `message/rfc822'...

multipart
     A message containing other messages.  `multipart/mixed',
     `multipart/alternative'...

text
     Textual data, meant for humans to read.  `text/plain', `text/html'...

video
     Video or video+audio data.  `video/mpeg'...

Content transfer encodings
--------------------------

   This is how the message body is packaged up for safe transit.  There
are the 5 major MIME encodings.  A more-comprehensive listing may be found
in RFC-2045.

  1. No encoding is done at all.  This label simply asserts that no 8-bit
     characters are present, and that lines do not exceed 1000 characters
     in length (including the CRLF).

  2. No encoding is done at all.  This label simply asserts that the
     message might contain 8-bit characters, and that lines do not exceed
     1000 characters in length (including the CRLF).

  3. binary No encoding is done at all.  This label simply asserts that
     the message might contain 8-bit characters, and that lines may exceed
     1000 characters in length.  Such messages are the *least* likely to
     get through mail gateways.

  4. base64 A standard encoding, which maps arbitrary binary data to the
     7bit domain.  Like "uuencode", but very well-defined.  This is how
     you should send essentially binary information (tar files, GIFs,
     JPEGs, etc.).

  5. quoted-printable A standard encoding, which maps arbitrary
     line-oriented data to the 7bit domain.  Useful for encoding messages
     which are textual in nature, yet which contain non-ASCII characters
     (e.g., Latin-1, Latin-2, or any other 8-bit alphabet).

TERMS AND CONDITIONS
====================

   Eryq (`eryq@zeegee.com'), ZeeGee Software Inc (`http://www.zeegee.com').

   Copyright (c) 1998, 1999 by ZeeGee Software Inc (www.zeegee.com).

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.  See
the COPYING file in the distribution for details.

SUPPORT
=======

   Please email me directly with questions/problems (see AUTHOR below).

   If you want to be placed on an email distribution list (not a mailing
list!)  for MIME-tools, and receive bug reports, patches, and updates as
to when new MIME-tools releases are planned, just email me and say so.  If
your project is using MIME-tools, it might not be a bad idea to find out
about those bugs before they become problems...

VERSION
=======

   $Revision: 5.410 $

CHANGE LOG
==========

Version 5.410   (2000/11/23)
     *Better detection of evil filenames.* Now we check for filenames
     which are suspiciously long, and a new
     MIME::Filer::exorcise_filename() method is used to try and remove the
     evil.  *Thanks to Jason Haar for the suggestion.*

Version 5.409   (2000/11/12)
     *Added functionality to MIME::WordDecoder,* including support for
     plain US-ASCII.

     *MIME::Tools::tmpopen()* made more flexible.  You can now override
     the tmpfile-opening behavior.

Version 5.408   (2000/11/10)
     *Added new Beta unmime() mechanism.* See MIME/WordDecoder,
     for full details.  Also see `"Understand how
     international characters are represented"' in this node.

Version 5.405   (2000/11/05)
     *Added a purge() that does what people want it to.* Now, when a parse
     finishes and you want to delete everything that was created by it,
     you can invoke purge() on the parser's filer.  All files/directories
     created during the last parse should vanish.  *Thanks to everyone who
     complained about MIME::Entity::purge.*

Version 5.404   (2000/11/04)
     *Added new automatic MIME-decoding of attachment filenames with
     encoded (non-ASCII) characters.* Hopefully this will do more good
     than harm.  The use of MIME::Parser::decode_headers() and
     MIME::Head::decode() has been deprecated in favor of the new
     MIME::Words "unmime" mechanism.  Please see `unmime', see
     MIME/Words.

     *Added tolerance for unquoted =?...?= in param values.* This is in
     violation of the RFCs, but then, so are some MUAs.  *Thanks to desti
     for bringing this to my attention.*

     *Fixed supposedly-bad B-encoding.* *Thanks to Otto Frost for bringing
     this to my attention.*

Version 5.316   (2000/09/21)
     *Increased tolerance in MIME::Parser.* Now will ignore bogus POP3
     "+OK" line before header, as well as bogus mailbox "From " line (both
     with warnings).  *Thanks to Antony OSullivan (ajos1) for suggesting
     this feature.*

     *Fixed small epilogue-related bug in MIME::Entity::print_body().* Now
     it only outputs a final newline if the epilogue does not end in one
     already.  Support for checking the preamble/epilogue in regression
     tests was also added.  *Thanks to Lars Hecking for bringing this
     issue up.*

     *Updated documentation.* All module manual pages should now direct
     readers to the main MIME-tools manual page.

Version 5.314   (2000/09/06)
     Fixed Makefile.PL to have less-restrictive requirement for File::Spec
     (0.6).

Version 5.313   (2000/09/05)
     *Fixed nasty bug with evil filenames.* Certain evil filenames were
     getting replaced by internally-generated filenames which were just as
     evil... ouch!  If your parser occasionally throws a fatal exception
     with a "write-open" error message, then you have this bug.  *Thanks
     to Julian Field and Antony OSullivan (ajos1) for delivering the
     evidence!*

          Beware the doctor
             who cures seasonal head cold
          by killing patient

     *Improved naming of extracted files.* If a filename is regarded as
     evil, we guess that it might just be because of part information, and
     attempt to find and use the final path element.

     *Simplified message logging and made it more consistent.* For
     details, see `"Message-logging"' in this node.

Version 5.312   (2000/09/03)
     *Fixed a Perl 5.7 select() incompatibility* which caused "make test"
     to fail.  *Thanks to Nick Ing-Simmons for the patch.*

Version 5.311   (2000/08/16)
     *Blind fix for Win32 uudecoding bug.* A missing binmode seems to be
     the culprit here; let's see if this fixes it.  *Thanks to ajos1 for
     finding the culprit!*

          The carriage return
             thumbs its nose at me, laughing:
          DOS I/O *still* sucks

Version 5.310   (2000/08/15)
     *Fixed a bug in the back-compat output_prefix() method of
     MIME::Parser.* Basically, output prefixes were not being set through
     this mechanism.  *Thanks to ajos1 for the alert.*

          shift @_,                               ### "shift at-underscore"
             or @_ will have
          bogus "self" object

     *Added some backcompat methods,* like parse_FH().  *Thanks (and
     apologies) to Alain Kotoujansky.*

     *Added filenames-with-spaces support to MIME::Decoder::UU.* *Thanks
     to Richard Pun for the suggestion.*

Version 5.305   (2000/07/20)
     *Added MIME::Entity::parts_DFS* as convenient way to "get all parts".
     *Thanks to Xavier Armengou for suggesting this method.*

     Removed the Alpha notice.  Still a few features to tweak, but those
     will be minor.

Version 5.303   (2000/07/07)
     *Fixed output bugs in new Filers*.  Scads of them: bad handling of
     filename collisions, bad implementation of output_under(), bad
     linking to results, POD errors, you name it.  If this had gone to
     CPAN, I'd have issued a factory recall. `:-('

          Errors, like beetles,
             Multiply ferociously
          In the small hours

Version 5.301   (2000/07/06)
     *READ ME BEFORE UPGRADING PAST THIS POINT!* *New MIME::Parser::Filer
     class - not fully backwards-compatible.* In response to demand for
     more-comprehensive file-output strategies, I have decided that the
     best thing to do is to split all the file-output logic
     (output_path(), evil_filename(), etc.)  into its own separate class,
     inheriting from the new `MIME::Parser::Filer|MIME::Parser::Filer' in
     this node class.  If you override any of the following in a
     MIME::Parser subclass, you will need to change your code accordingly:

          evil_filename
          output_dir
          output_filename
          output_path
          output_prefix
          output_under

     My sincere apologies for any inconvenience this will cause, but it's
     ultimately for the best, and is quite likely the last structural
     change to 5.x.  *Thanks to Tyson Ackland for all the ideas.*
     Incidentally, the new code also fixes a bug where identically-named
     files in the same message could clobber each other.

          A message arrives:
              "Here are three files, all named 'Foo'"
          Only one survives.  :-(

     *Fixed bug in MIME::Words header decoding.* Underscores were not
     being handled properly.  *Thanks to Dominique Unruh and Doru
     Petrescu,* who independently submitted the same fix within 2 hours of
     each other, after this bug has lain dormant for months:

          Two users, same bug,
             same patch -- mere hours apart:
          Truly, life is odd.

     *Removed escaping of underscore in regexps.* Escaping the underscore
     (\_) in regexps was sloppy and wrong (escaped metacharacters may
     include anything in \w), and the newest Perls warn about it.  *Thanks
     to David Dyck for bringing this to my attention.*

          What, then, is a word?
          	  Some letters, digits, and, yes:
          Underscores as well

     *Added Force option to MIME::Entity's make_multipart*.  *Thanks to
     Bob Glickstein for suggesting this.*

     *Numerous fixlets to example code.* *Thanks to Doru Petrescu for
     these.*

     *Added REQUIREMENTS section in docs.* Long-overdue.  *Thanks to Ingo
     Schmiegel for motivating this.*

Version 5.211   (2000/06/24)
     *Fixed auto-uudecode bug.* Parser was failing with "part did not end
     with expected boundary" error when uuencoded entity was a
     *singlepart* message (ironically, uuencoded parts of multiparts
     worked fine).  *Thanks to Michael Mohlere for testing uudecode and
     finding this.*

          The hurrying bee
             Flies far for nectar, missing
          The nearest flowers

          Say ten thousand times:
             Complex cases may succeed
          Where simple ones fail

     *Parse errors now generate warnings.* Parser errors now cause warn()s
     to be generated if they are not turned into fatal exceptions.  This
     might be a little redundant, seeing as they are available in the
     "results", but parser-warnings already cause warn()s.  I can always
     put in a "quiet" switch if people complain.

     *Miscellaneous cleanup.* Documentation of MIME::Parser improved
     slightly, and a redundant warning was removed.

Version 5.210   (2000/06/20)
     *Change in "evil" filename.* Made MIME::Parser's evil_filename
     stricter by having it reject "path" characters: any of '/' '\' ':'
     '[' ']'.

          Just as with beauty
          	  The eye of the beholder
          Is where "evil" lives.

     *Documentation fixes.* Corrected a number of docs in MIME::Entity
     which were obsoleted in the transition from 4.x to 5.x.  *Thanks to
     Michael Fischer for pointing these out.* For this one, a special
     5-5-5-5 Haiku of anagrams:

          Documentation
          	  in mutant code, O!
          Edit -- no, CUT! [moan]
          	  I meant to un-doc...

     *IO::Lines usage bug fixed.* MIME::Entity was missing a "use
     IO::Lines", which caused an exception when you tried to use the
     body() method of MIME::Entity.  *Thanks to Hideyo Imazu and Michael
     Fischer for pointing this out.*

          Bareword looks fine, but
             Perl cries: "Whoa there... IO::Lines?
          Never heard of it."

Version 5.209   (2000/06/10)
     *Autodetection of uuencode.* You can now tell the parser to hunt for
     uuencode inside what should be text parts.  See
     `extract_uuencode()|MIME::Parser' in this node for full details.
     *Beware:* this is largely untested at the moment.  *Special thanks to
     Michael Mohlere at ADJE Webmail, who was the   first - and
     most-insistent - user to request this feature.*

     *Faster parsing.* Sped up the MIME::Decoder::NBit decoder quite a bit
     by using a variant of the chunking trick I used for
     MIME::Decoder::Base64.  I suspect that the same trick (reading a big
     chunk plus the next line to get a big block of lines) would work with
     MIME::Decoder::QuotedPrint, but I don't have the time or resources to
     check that right now (tested contributions would be welcome).  NBit
     encoding is more-conveniently done line-by-line for now, because
     individual line lengths must be checked.

     *Better use of core.* MIME::Body::InCore is now used when you build()
     an entity with the Data parameter, instead of MIME::Body::Scalar.

     *More documentation* on toolkit configuration.

Version 5.207   (2000/06/09)
     *Fixed whine() bug in MIME::Parser* where the "warning" method
     whine() was called as a static function instead of invoked as an
     instance method.  *Thanks to Todd A. Bradfute for reporting this.*

          A simple warning
             Invokes method as function:
          "Warning" makes us die

Version 5.206   (2000/06/08)
     Ahem.  Cough cough:

          Way too many bugs
             Thus, a self-imposed penance:
          Write haiku for each

     *Fixed bug in MIME::Parser:* the reader was not handling the odd (but
     legal) case where a multipart boundary is followed by linear
     whitespace.  *Thanks to Jon Agnew for reporting this with the RFC
     citation.*

          Legal message fails
             And 'round the globe, thousands cry:
          READ THE RFC

     Empty preambles are now handled properly by MIME::Entity when
     printing: there is now no space between the header-terminator and the
     initial boundary.  *Thanks to "sen_ml" for suggesting this.*

          Nature hates vacuum
             But please refrain from tossing
          Newlines in the void

     Started using Benchmark for benchmarking.

Version 5.205   (2000/06/06)
     Added terminating newline to all parser messages, and fixed small
     parser bug that was dropping parts when errors occurred in certain
     places.

Version 5.203   (2000/06/05)
     Brand new parser based on new (private) MIME::Parser::Reader and
     (public) MIME::Parser::Results.  Fast and yet simple and very tolerant
     of bad MIME when desired.  Message reporting needs some muzzling.

     MIME::Parser now has ignore_errors() set true by default.

Version 5.116   (2000/05/26)
     Removed Tmpfile.t test, which was causing a bogus failure in "make
     test".  Now we require 5.004 for MIME::Parser anyway, so we don't
     need it.  *Thanks to Jonathan Cohn for reporting this.*

Version 5.115   (2000/05/24)
     Fixed Ref.t bug, and documented how to remove parts from a
     MIME::Entity.

Version 5.114   (2000/05/23)
     Entity now uses MIME::Lite-style default suggested encoding.

     More regression test have been added, and the "Size" tests in Ref.t
     are skipped for text document (due to CRLF differences between
     platforms).

Version 5.113   (2000/05/21)
     *Major speed and structural improvements to the parser.*     *Major,
     MAJOR thanks to Noel Burton-Krahn, Jeremy Gilbert,       and Doru
     Petrescu for all the patches, benchmarking,       and Beta-testing!*

     *Convenient new one-directory-per-message parsing mechanism.*     Now
     through `MIME::Parser' method `output_under()',     you can tell the
     parser that you want it to create     a unique directory for each
     message parsed, to hold the     resulting parts.

     *Elimination of $', $` and $&.*     Wow... I still can't believe I
     missed this.  D'OH!      *Thanks to Noel Burton-Krahn for all his
     patches.*

     *Parser is more tolerant of weird EOL termination.*     Some
     mailagents are can terminate lines with "\r\r\n".      We're okay
     with that now when we extract the header.      *Thanks to Joao
     Fonseca for pointing this out.*

     *Parser is tolerant of "From " lines in headers.*     *Thanks to
     Joachim Wieland, Anthony Hinsinger, Marius Stan,       and numerous
     others.*

     *Parser catches syntax errors in headers.*     *Thanks to Russell P.
     Sutherland for catching this.*

     *Parser no longer warns when subtype is undefined.*     *Thanks to
     Eric-Olivier Le Bigot for his fix.*

     *Better integration with Mail::Internet.*     For example, smtpsend()
     should work fine.      *Thanks to Michael Fischer and others for the
     patch.*

     *Miscellaneous cleanup.*     *Thanks to Marcus Brinkmann for
     additional helpful input.*     *Thanks to Klaus Seidenfaden for good
     feedback on 5.x Alpha!*

Version 4.123   (1999/05/12)
     Cleaned up some of the tests for non-Unix OS'es.  Will require a few
     iterations, no doubt.

Version 4.122   (1999/02/09)
     *Resolved CORE::open warnings for 5.005.*         *Thanks to several
     folks for this bug report.*

Version 4.121   (1998/06/03)
     *Fixed MIME::Words infinite recursion.*         *Thanks to several
     folks for this bug report.*

Version 4.117   (1998/05/01)
     *Nicer MIME::Entity::build.*         No longer outputs warnings with
     undefined Filename, and now         accepts Charset as well.  	*Thanks
     to Jason Tibbits III for the inspirational patch.*

     *Documentation fixes.*         Hopefully we've seen the last of the
     pod2man warnings...

     *Better test logging.*         Now uses ExtUtils::TBone.

Version 4.116   (1998/02/14)
     *Bug fix:*         MIME::Head and MIME::Entity were not downcasing the
            content-type as they claimed.  This has now been fixed.
     *Thanks to Rodrigo de Almeida Siqueira for finding this.*

Version 4.114   (1998/02/12)
     *Gzip64-encoding has been improved, and turned off as a default,*
     since it depends on having gzip installed.          See
     MIME::Decoder::Gzip64 if you want to activate it in your app.  	You
     can	now set up the gzip/gunzip commands to use, as well.
     *Thanks to Paul J. Schinder for finding this bug.*

Version 4.113   (1998/01/20)
     *Bug fix:*         MIME::ParserBase was accidentally folding newlines
     in header fields.  	*Thanks to Jason L. Tibbitts III for
     spotting this.*

Version 4.112   (1998/01/17)
     *MIME::Entity::print_body now recurses* when printing multipart
     entities, and prints "everything following the header."  This is more
     likely what people expect to happen.  PLEASE read the         "two
     body problem" section of MIME::Entity's docs.

Version 4.111   (1998/01/14)
     Clean build/test on Win95 using 5.004.  Whew.

Version 4.110   (1998/01/11)
     Added make_multipart() and make_singlepart() in MIME::Entity.

     Improved handling/saving of preamble/epilogue.

Version 4.109   (1998/01/10)

    Overall
          *Major version shift to 4.x* 	accompanies numerous structural
          changes, and 	the deletion of some long-deprecated code.  Many
          apologies to those 	who are inconvenienced by the upgrade.

          *MIME::IO deprecated.* 	You'll see IO::Scalar, IO::ScalarArray,
          and IO::Wrap 	to make this toolkit work.

          *MIME::Entity deep code.* 	You can now deep-copy MIME entities
          (except for on-disk data files).

    Encoding/decoding
          *MIME::Latin1 deprecated, and 8-to-7 mapping removed.* 	Really,
          MIME::Latin1 was one of my more dumber ideas.  	It's
          still there, but if you want to map 8-bit characters to 	Latin1
          ASCII approximations when 7bit encoding, you'll have to 	request
          it explicitly.	*But use quoted-printable for your 8-bit
          documents; that's what it's there for!*

          *7bit and 8bit "encoders" no longer encode.* 	As per RFC-2045,
          these just do a pass-through of the data, 	but they'll warn you
          if you send bad data through.

          *MIME::Entity suggests encoding.* 	Now you can ask
          MIME::Entity's build() method to "suggest" 	a legal encoding
          based on the body and the content-type.  	No more guesswork!  See
          the "mimesend" example.

          *New module structure for MIME::Decoder classes.* 	It
          should be easier for you to see what's happening.

          *New MIME decoders!* 	Support added for decoding
          `x-uuencode', and for 	decoding/encoding `x-gzip64'.  You'll need
          "gzip" to make 	the latter work.

          *Quoted-printable back on track... and then some.* 	The
          'quoted-printable' decoder now uses the newest MIME::QuotedPrint,
          and amends its output with guideline #8 from RFC2049 (From/.).
          *Thanks to Denis N. Antonioli for suggesting this.*

    Parsing
          *Preamble and epilogue are now saved.* 	These are saved in the
          parsed entities as simple 	string-arrays, and are output by
          print() if there.  	*Thanks to Jason L. Tibbitts for
          suggesting this.*

          *The "multipart/digest" semantics are now preserved.* 	Parts of
          digest messages have their mime_type() defaulted 	to
          "message/rfc822" instead of "text/plain", as per the RFC.
          *Thanks to Carsten Heyl for suggesting this.*

    Output
          *Well-defined, more-complete print() output.* 	When
          printing an entity, the output is now well-defined if the 	entity
          came from a MIME::Parser, even if using parse_nested_messages.
          See MIME::Entity for details.

          *You can prevent recommended filenames from being output.* 	This
          possible security hole has been plugged; when building MIME
          entities, you can specify a body path but suppress the filename
          in the header.  	*Thanks to Jason L. Tibbitts for
          suggesting this.*

    Bug fixes
          *Win32 installations should work.* 	The binmode() calls
          should work fine on Win32 now.  	*Thanks to numerous
          folks for their patches.*

          *MIME::Head::add()* now no longer downcases its argument.
          *Thanks to Brandon Browning & Jason L. Tibbitts for finding this
          bug.*

Version 3.204
     *Bug in MIME::Head::original_text fixed.* 	Well, it took a
     while, but another bug surfaced from my transition 	from 1.x
     to 2.x.  This method was, quite idiotically, sorting the
     header fields.  	*Thanks, as usual, to Andreas Koenig for spotting
     this one.*

     *MIME::ParserBase no longer defaults to RFC-1522-decoding headers.*
     The documentation correctly stated that the default setting was 	to
     not RFC-1522-decode the headers.  The code, on the other hand, 	was
     init'ing this parser option in the "on" position.  	This has
     been fixed.

     *MIME::ParserBase::parse_nested_messages reexamined.* 	If you
     use this feature, please re-read the documentation.  	It
     explains a little more precisely what the ramifications are.

     *MIME::Entity tries harder to ensure MIME compliance.* 	It is
     now a fatal error to use certain bad combinations of content 	type and
     encoding when "building", or to attempt to "attach" to
     anything that is not a multipart document.  My apologies if this
     inconveniences anyone, but it was just too darn easy before for folks
     to create bad MIME, and gosh darn it, good libraries should at least
     try to protect you from mistakes.

     *The "make" now halts if you don't have the right stuff,*
     provided your MakeMaker supports PREREQ_PM.  See `"REQUIREMENTS"' in
     this node 	for what you need to install this package.  I still
     provide 	old courtesy copies of the MIME:: decoding modules.
     *Thanks to Hugo van der Sanden for suggesting this.*

     *The "make test" is far less chatty.* 	Okay, okay, STDERR is
     evil.  Now a `"make test"' will just give you 	the important stuff: do
     a `"make test TEST_VERBOSE=1"' if you want 	the gory details
     (advisable if sending me a bug report).  *Thanks to Andreas Koenig
     for suggesting this.*

Version 3.203
     *No, there haven't been any major changes between 2.x and 3.x.* 	The
     major-version increase was from a few more tweaks to get $VERSION 	to
     be calculated better and more efficiently (I had been using RCS
     version numbers in a way which created problems for users of CPAN::).
     After a couple of false starts, all modules have been upgraded to RCS
     3.201 or higher.

     *You can now parse a MIME message from a scalar,* 	an
     array-of-scalars, or any MIME::IO-compliant object (including IO::
     objects.)  Take a look at parse_data() in MIME::ParserBase.  The
     parser code has been modified to support the MIME::IO interface.
     *Thanks to fellow Chicagoan Tim Pierce (and countless others) 	for
     asking.*

     *More sensible toolkit configuration.* 	A new config() method
     in MIME::ToolUtils makes a lot of toolkit-wide 	configuration cleaner.
     Your old calls will still work, but with 	deprecation
     warnings.

     *You can now sign messages* just like in Mail::Internet.  	See
     MIME::Entity for the interface.

     *You can now remove signatures from messages* just like in
     Mail::Internet.  	See MIME::Entity for the interface.

     *You can now compute/strip content lengths* 	and other non-standard
     MIME fields.  	See sync_headers() in MIME::Entity.  	*Thanks to
     Tim Pierce for bringing the basic problem to my attention.*

     *Many warnings are now silent unless $^W is true.* 	That means
     unless you run your Perl with -w, you won't see         deprecation
     warnings, non-fatal-error messages, etc.          But of course you
     run with -w, so this doesn't affect you.  `:-)'

     *Completed the 7-bit encodings in MIME::Latin1.* 	We hadn't had
     complete coverage in the conversion from 8- to 7-bit; 	now we
     do. *Thanks to Rolf Nelson for bringing this to my attention.*

     *Fixed broken parse_two() in MIME::ParserBase.* 	BTW, if your code
     worked with the "broken" code, it should *still* 	work.
     *Thanks again to Tim Pierce for bringing this to my attention.*

Version 2.14
     Just a few bug fixes to improve compatibility with Mail-Tools 1.08,
     and with the upcoming Perl 5.004 release.  *Thanks to Jason L.
     Tibbitts III for reporting the problems so quickly.*

Version 2.13

    New features
          *Added RFC-1522-style decoding of encoded header fields.* 	Header
          decoding can now be done automatically during parsing via the
          new `decode()' method in MIME::Head... just tell your parser
          object that you want to `decode_headers()'.  	*Thanks to Kent
          Boortz for providing the idea, and the baseline
          RFC-1522-decoding code!*

          *Building MIME messages is even easier.* 	Now, when you use
          MIME::Entity's `build()' or `attach()', 	you can also supply
          individual 	mail headers to set (e.g., `-Subject', `-From',
          `-To').

          Added Disposition to MIME::Entity's `build()' method.  	*Thanks
          to Kurt Freytag for suggesting this feature.*

          An `X-Mailer' header is now output 	by default in all
          MIME-Entity-prepared messages, 	so any bad MIME we
          generate can be traced back to this toolkit.

          Added purge() method to MIME::Entity for deleteing leftover
          files.  	*Thanks to Jason L. Tibbitts III for suggesting this
          feature.*

          Added `seek()' and tell() methods to built-in MIME::IO classes.
          Only guaranteed to work when reading!  	*Thanks to Jason L.
          Tibbitts III for suggesting this feature.*

          When parsing a multipart message with apparently no boundaries,
          the error message you get has been improved.  	*Thanks to
          Andreas Koenig for suggesting this.*

    Bug fixes
          *Patched over a Perl 5.002 (and maybe earlier and later) bug
          involving FileHandle::new_tmpfile.*  It seems that the
          underlying filehandles were not being closed when the FileHandle
          objects went out of scope!  There is now an internal routine
          that creates true FileHandle objects for anonymous temp files.
          *Thanks to Dragomir R. Radev and Zyx for reporting the weird
          behavior that led to the discovery of this bug.*

          MIME::Entity's `build()' method now warns you if you give it an
          illegal boundary string, and substitutes one of its own.

          MIME::Entity's `build()' method now generates safer,
          fully-RFC-1521-compliant boundary strings.

          Bug in MIME::Decoder's `install()' method was fixed.  *Thanks to
          Rolf Nelson and Nickolay Saukh for finding this.*

          Changed FileHandle::new_tmpfile to FileHandle->new_tmpfile, so
          some Perl installations will be happier.  *Thanks to Larry W.
          Virden for finding this bug.*

          Gave =over an arg of 4 in all PODs.  *Thanks to Larry W. Virden
          for pointing out the problems of bare =over's*

Version 2.04
     *A bug in MIME::Entity's output method was corrected.*
     MIME::Entity::print now outputs everything to the desired filehandle
     explicitly.  *Thanks to Jake Morrison for pointing out the
     incompatibility with Mail::Header.*

Version 2.03
     *Fixed bug in autogenerated filenames* resulting from transposed "if"
     statement in MIME::Parser, removing spurious printing of header as
     well.  (Annoyingly, this bug is invisible if debugging is turned on!)
     *Thanks to Andreas Koenig for bringing this to my attention.*

     Fixed bug in MIME::Entity::body() where it was using the bodyhandle
     completely incorrectly.  *Thanks to Joel Noble for bringing this to
     my attention.*

     Fixed MIME::Head::VERSION so CPAN:: is happier.  *Thanks to Larry
     Virden for bringing this to my attention.*

     Fixed undefined-variable warnings when dumping skeleton (happened
     when there was no Subject: line) *Thanks to Joel Noble for bringing
     this to my attention.*

Version 2.02
     *Stupid, stupid bugs in both BASE64 encoding and decoding were fixed.*
     *Thanks to Phil Abercrombie for locating them.*

Version 2.01
     *Modules now inherit from the new Mail:: modules!* This means big
     changes in behavior.

     *MIME::Parser can now store message data in-core.* There were a *lot*
     of requests for this feature.

     *MIME::Entity can now compose messages.* There were a *lot* of
     requests for this feature.

     Added option to parse `"message/rfc822"' as a pseduo-multipart
     document.  *Thanks to Andreas Koenig for suggesting this.*

Version 1.13
     MIME::Head now no longer requires space after ":", although either a
     space or a tab after the ":" will be swallowed if there.  *Thanks to
     Igor Starovoitov for pointing out this shortcoming.*

Version 1.12
     Fixed bugs in parser where CRLF-terminated lines were blowing out the
     handling of preambles/epilogues.  *Thanks to Russell Sutherland for
     reporting this bug.*

     Fixed idiotic is_multipart() bug.  *Thanks to Andreas Koenig for
     noticing it.*

     Added untested binmode() calls to parser for DOS, etc.  systems.  No
     idea if this will work...

     Reorganized the output_path() methods to allow easy use of
     inheritance, as per Achim Bohnet's suggestion.

     Changed MIME::Head to report mime_type more accurately.

     POSIX module no longer loaded by Parser if perl >= 5.002.  Hey,
     5.001'ers: let me know if this breaks stuff, okay?

     Added unsupported ./examples directory.

Version 1.11
     Converted over to using Makefile.PL.  *Thanks to Andreas Koenig for
     the much-needed kick in the pants...*

     Added t/*.t files for testing.  Eeeeeeeeeeeh...it's a start.

     Fixed bug in default parsing routine for generating output paths; it
     was warning about evil filenames if there simply *were* no
     recommended filenames.  D'oh!

     Fixed redefined parts() method in Entity.

     Fixed bugs in Head where field name wasn't being case folded.

Version 1.10
     A typo was causing the epilogue of an inner multipart message to be
     swallowed to the end of the OUTER multipart message; this has now
     been fixed.  *Thanks to Igor Starovoitov for reporting this bug.*

     A bad regexp for parameter names was causing some parameters to be
     parsed incorrectly; this has also been fixed.  *Thanks again to Igor
     Starovoitov for reporting this bug.*

     It is now possible to get full control of the filenaming algorithm
     before output files are generated, and the default algorithm is safer.
     *Thanks to Laurent Amon for pointing out the problems, and suggesting
     some solutions.*

     Fixed illegal "simple" multipart test file.  D'OH!

Version 1.9
     No changes: 1.8 failed CPAN registration

Version 1.8
     Fixed incompatibility with 5.001 and FileHandle::new_tmpfile Added
     COPYING file, and improved README.

AUTHOR
======

   MIME-tools was created by:

     ___  _ _ _   _  ___ _
        / _ \| '_| | | |/ _ ' /    Eryq, (eryq@zeegee.com)
       |  __/| | | |_| | |_| |     President, ZeeGee Software Inc.
        \___||_|  \__, |\__, |__   http://www.zeegee.com/
              |___/    |___/

   Released as MIME-parser (1.0): 28 April 1996.  Released as MIME-tools
(2.0): Halloween 1996.  Released as MIME-tools (4.0): Christmas 1997.
Released as MIME-tools (5.0): Mother's Day 2000.

ACKNOWLEDGMENTS
===============

   *This kit would not have been possible* but for the direct
contributions of the following:

     Gisle Aas             The MIME encoding/decoding modules.
     Laurent Amon          Bug reports and suggestions.
     Graham Barr           The new MailTools.
     Achim Bohnet          Numerous good suggestions, including the I/O model.
     Kent Boortz           Initial code for RFC-1522-decoding of MIME headers.
     Andreas Koenig        Numerous good ideas, tons of beta testing,
                             and help with CPAN-friendly packaging.
     Igor Starovoitov      Bug reports and suggestions.
     Jason L Tibbitts III  Bug reports, suggestions, patches.

   Not to mention the Accidental Beta Test Team, whose bug reports (and
comments) have been invaluable in improving the whole:

     Phil Abercrombie
     Mike Blazer
     Brandon Browning
     Kurt Freytag
     Steve Kilbane
     Jake Morrison
     Rolf Nelson
     Joel Noble
     Michael W. Normandin
     Tim Pierce
     Andrew Pimlott
     Dragomir R. Radev
     Nickolay Saukh
     Russell Sutherland
     Larry Virden
     Zyx

   Please forgive me if I've accidentally left you out.  Better yet, email
me, and I'll put you in.

SEE ALSO
========

   At the time of this writing ($Date: 2000/11/23 05:04:01 $), the
MIME-tools homepage was `http://www.zeegee.com/code/perl/MIME-tools'.
Check there for updates and support.

   Users of this toolkit may wish to read the documentation of Mail::Header
and Mail::Internet.

   The MIME format is documented in RFCs 1521-1522, and more recently in
RFCs 2045-2049.

   The MIME header format is an outgrowth of the mail header format
documented in RFC 822.

Perl extension for determining MIME types and Transfer Encoding
***************************************************************

NAME
====

   MIME::Types - Perl extension for determining MIME types and Transfer
Encoding

SYNOPSIS
========

     use MIME::Types qw(by_suffix by_mediatype);

     my ($mime_type, $encoding) = by_suffix(FILENAME);
     my $aref = by_suffix(FILENAME);

     my @list = by_mediatype(MEDIATYPE);
     my $aref = by_mediatype(MEDIATYPE);

DESCRIPTION
===========

   NOTE: This is ALPHA code. There are no guarantees that any of the
subroutines described here will not have their names or return values
changed.

   This module is built to conform to the MIME types standard defined in
RFC 1341 and updated by RFC's 1521 and 1522. It follows the collection
kept at `http://www.ltsw.se/knbase/internet/mime.htp'.

INTERFACE
=========

   The following functions are avilable:

by_suffix
     This function takes either a file name suffix or a complete file name.
     It returns a two-element list or an anonymous array if the suffix can
     be found: the media type and a content encoding.  An empty list is
     returned if the suffix could not be found.

by_mediatype
     This function takes a media type and returns a list or anonymous
     array of anonymous three-element arrays whose values are the file
     name suffix used to identify it, the media type, and a content
     encoding.

     If the media type contains a slash (/), it is assumed to be a
     complete media type and must exactly match against the internal table.
     Otherwise the value is compared to all the values in the table via a
     regular expression.  All regular expression codes are supported
     (except, of course, any string with a slash in it).  Thus, calling
     *by_mediatype("application")* will return a large list.

AUTHOR
======

   Jeff Okamoto <`okamoto@corp.hp.com'>.

   Updated by David Wheeler <`david@wheeler.net'>.

   Inspired by the mail_attach.pl program by Dan Sugalski
<`dan@sidhe.org'>.

decode RFC-1522 encoded words to a local representation
*******************************************************

NAME
====

   MIME::WordDecoder - decode RFC-1522 encoded words to a local
representation

SYNOPSIS
========

   See MIME/Words, for the basics of encoded words.  See
`"DESCRIPTION"' in this node for how this class works.

     use MIME::WordDecoder;

     ### Get the default word-decoder (used by unmime()):
     $wd = default MIME::WordDecoder;

     ### Get a word-decoder which maps to ISO-8859-1 (Latin1):
     $wd = supported MIME::WordDecoder "ISO-8859-1";

     ### Decode a MIME string (e.g., into Latin1) via the default decoder:
     $str = $wd->decode('To: =?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= <keld>');

     ### Decode a string using the default decoder, non-OO style:
     $str = unmime('To: =?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= <keld>');

DESCRIPTION
===========

   A MIME::WordDecoder consists, fundamentally, of a hash which maps a
character set name (US-ASCII, ISO-8859-1, etc.) to a subroutine which
knows how to take bytes in that character set and turn them into the
target string representation.  Ideally, this target representation would
be Unicode, but we don't want to overspecify the translation that takes
place: if you want to convert MIME strings directly to Big5, that's your
own decision.

   The subroutine will be invoked with two arguments: DATA (the data in
the given character set), and CHARSET (the upcased character set name).

   For example:

     ### Keep 7-bit characters as-is, convert 8-bit characters to '#':
     sub keep7bit {
     	local $_ = shift;
     	tr/\x00-\x7F/#/c;
     	$_;
     }

   Here's a decoder which uses that:

     ### Construct a decoder:
     $wd = MIME::WordDecoder->new({'US-ASCII'   => "KEEP",   ### sub { $_[0] }
                                   'ISO-8859-1' => \&keep7bit,
                                   'ISO-8859-2' => \&keep7bit,
                                   'Big5'       => "WARN",
                                   '*'          => "DIE"});

     ### Convert some MIME text to a pure ASCII string...
     $ascii = $wd->decode('To: =?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= <keld>');

     ### ...which will now hold: "To: Keld J#rn Simonsen <keld>"

PUBLIC INTERFACE
================

default [DECODER]
     *Class method.* Get/set the default DECODER object.

supported CHARSET, [DECODER]
     *Class method.* If just CHARSET is given, returns a decoder object
     which maps data into that character set (the character set is forced
     to all-uppercase).

          $wd = supported MIME::WordDecoder "ISO-8859-1";

     If DECODER is given, installs such an object:

          MIME::WordDecoder->supported("ISO-8859-1" =>
          				 (new MIME::WordDecoder::ISO_8859 "1"));

     You should not override this method.

new [\@HANDLERS]
     *Class method, constructor.* If \@HANDLERS is given, then @HANDLERS
     is passed to handler() to initiallize the internal map.

handler CHARSET=>\&SUBREF, ...
     *Instance method.* Set the handler SUBREF for a given CHARSET, for as
     many pairs as you care to supply.

     When performing the translation of a MIME-encoded string, a given
     SUBREF will be invoked when translating a block of text in character
     set CHARSET.  The subroutine will be invoked with the following
     arguments:

          DATA    - the data in the given character set.
          CHARSET - the upcased character set name, which may prove useful
                    if you are using the same SUBREF for multiple CHARSETs.
          DECODER - the decoder itself, if it contains configuration information
                    that your handler function needs.

     For example:

          $wd = new MIME::WordDecoder;
          $wd->handler('US-ASCII'   => "KEEP");
          $wd->handler('ISO-8859-1' => \&handle_latin1,
          		 'ISO-8859-2' => \&handle_latin1,
          		 '*'          => "DIE");

     Notice that, much as with %SIG, the SUBREF can also be taken from a
     set of special keywords:

          KEEP     Pass data through unchanged.
          IGNORE   Ignore data in this character set, without warning.
          WARN     Ignore data in this character set, with warning.
          DIE      Fatal exception with "can't handle character set" message.

     The subroutine for the special CHARSET of 'raw' is used for raw
     (non-MIME-encoded) text, which is supposed to be US-ASCII.  The
     handler for 'raw' defaults to whatever was specified for 'US-ASCII'
     at the time of construction.

     The subroutine for the special CHARSET of '*' is used for any
     unrecognized character set.  The default action for '*' is WARN.

decode STRING
     *Instance method.* Decode a STRING which might contain MIME-encoded
     components into a local representation (e.g., UTF-8, etc.).

unmime STRING
     *Function, exported.* Decode the given STRING using the default()
     decoder.  See `default()|' in this node.

SUBCLASSES
==========

MIME::WordDecoder::ISO_8859
     A simple decoder which keeps US-ASCII and the 7-bit characters of
     ISO-8859 character sets and UTF8, and also keeps 8-bit characters
     from the indicated character set.

          ### Construct:
          $wd = new MIME::WordDecoder::ISO_8859 2;    ### ISO-8859-2

          ### What to translate unknown characters to (can also use empty):
          ### Default is "?".
          $wd->unknown("?");

          ### Collapse runs of unknown characters to a single unknown()?
          ### Default is false.
          $wd->collapse(1);

     According to *http://czyborra.com/charsets/iso8859.html* (ca.
     November 2000):

     ISO 8859 is a full series of 10 (and soon even more) standardized
     multilingual single-byte coded (8bit) graphic character sets for
     writing in alphabetic languages:

          1. Latin1 (West European)
          2. Latin2 (East European)
          3. Latin3 (South European)
          4. Latin4 (North European)
          5. Cyrillic
          6. Arabic
          7. Greek
          8. Hebrew
          9. Latin5 (Turkish)
             10. Latin6 (Nordic)

     The ISO 8859 charsets are not even remotely as complete as the truly
     great Unicode but they have been around and usable for quite a while
     (first registered Internet charsets for use with MIME) and have
     already offered a major improvement over the plain 7bit US-ASCII.

     Characters 0 to 127 are always identical with US-ASCII and the
     positions 128 to 159 hold some less used control characters: the
     so-called C1 set from ISO 6429.

MIME::WordDecoder::US_ASCII
     A subclass of the ISO-8859-1 decoder which discards 8-bit characters.
     You're probably better off using ISO-8859-1.

AUTHOR
======

   Eryq (`eryq@zeegee.com'), ZeeGee Software Inc (`http://www.zeegee.com').

VERSION
=======

   $Revision: 5.403 $ $Date: 2000/11/23 05:04:03 $

deal with RFC-1522 encoded words
********************************

NAME
====

   MIME::Words - deal with RFC-1522 encoded words

SYNOPSIS
========

   Before reading further, you should see MIME/Tools, to
make sure that you understand where this module fits into the grand scheme
of things.  Go on, do it now.  I'll wait.

   Ready?  Ok...

     use MIME::Words qw(:all);

     ### Decode the string into another string, forgetting the charsets:
     $decoded = decode_mimewords(
           'To: =?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= <keld@dkuug.dk>',
           );

     ### Split string into array of decoded [DATA,CHARSET] pairs:
     @decoded = decode_mimewords(
           'To: =?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= <keld@dkuug.dk>',
           );

     ### Encode a single unsafe word:
     $encoded = encode_mimeword("\xABFran\xE7ois\xBB");

     ### Encode a string, trying to find the unsafe words inside it:
     $encoded = encode_mimewords("Me and \xABFran\xE7ois\xBB in town");

DESCRIPTION
===========

   Fellow Americans, you probably won't know what the hell this module is
for.  Europeans, Russians, et al, you probably do.  `:-)'.

   For example, here's a valid MIME header you might get:

     From: =?US-ASCII?Q?Keith_Moore?= <moore@cs.utk.edu>
     To: =?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= <keld@dkuug.dk>
     CC: =?ISO-8859-1?Q?Andr=E9_?= Pirard <PIRARD@vm1.ulg.ac.be>
     Subject: =?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=
      =?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=
      =?US-ASCII?Q?.._cool!?=

   The fields basically decode to (sorry, I can only approximate the Latin
characters with 7 bit sequences /o and 'e):

     From: Keith Moore <moore@cs.utk.edu>
     To: Keld J/orn Simonsen <keld@dkuug.dk>
     CC: Andr'e  Pirard <PIRARD@vm1.ulg.ac.be>
     Subject: If you can read this you understand the example... cool!

PUBLIC INTERFACE
================

decode_mimewords ENCODED, [OPTS...]
     *Function.* Go through the string looking for RFC-1522-style "Q"
     (quoted-printable, sort of) or "B" (base64) encoding, and decode them.

     *In an array context,* splits the ENCODED string into a list of
     decoded `[DATA, CHARSET]' pairs, and returns that list.  Unencoded
     data are returned in a 1-element array `[DATA]', giving an effective
     CHARSET of undef.

          $enc = '=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= <keld@dkuug.dk>';
          foreach (decode_mimewords($enc)) {
              print "", ($_[1] || 'US-ASCII'), ": ", $_[0], "\n";
          }

     *In a scalar context,* joins the "data" elements of the above list
     together, and returns that.  *Warning: this is information-lossy,*
     and probably not what you want, but if you know that all charsets in
     the ENCODED string are identical, it might be useful to you.  (Before
     you use this, please see `unmime', see MIME/WordDecoder,
     which is probably what you want.)

     In the event of a syntax error, $@ will be set to a description of
     the error, but parsing will continue as best as possible (so as to
     get *something* back when decoding headers).  $@ will be false if no
     error was detected.

     Any arguments past the ENCODED string are taken to define a hash of
     options:

    Field
          Name of the mail field this string came from.  *Currently
          ignored.*

encode_mimeword RAW, [ENCODING], [CHARSET]
     *Function.* Encode a single RAW "word" that has unsafe characters.
     The "word" will be encoded in its entirety.

          ### Encode "<<Franc,ois>>":
          $encoded = encode_mimeword("\xABFran\xE7ois\xBB");

     You may specify the ENCODING (`"Q"' or `"B"'), which defaults to
     `"Q"'.  You may specify the CHARSET, which defaults to `iso-8859-1'.

encode_mimewords RAW, [OPTS]
     *Function.* Given a RAW string, try to find and encode all "unsafe"
     sequences of characters:

          ### Encode a string with some unsafe "words":
          $encoded = encode_mimewords("Me and \xABFran\xE7ois\xBB");

     Returns the encoded string.  Any arguments past the RAW string are
     taken to define a hash of options:

    Charset
          Encode all unsafe stuff with this charset.  Default is
          'ISO-8859-1', a.k.a. "Latin-1".

    Encoding
          The encoding to use, `"q"' or `"b"'.  The default is `"q"'.

    Field
          Name of the mail field this string will be used in.  *Currently
          ignored.*

     Warning: this is a quick-and-dirty solution, intended for character
     sets which overlap ASCII.  *It does not comply with the RFC-1522
     rules regarding the use of encoded words in message headers*.  You
     may want to roll your own variant, using `encoded_mimeword()', for
     your application.  *Thanks to Jan Kasprzak for reminding me about
     this problem.*

NOTES
=====

   Exports its principle functions by default, in keeping with
MIME::Base64 and MIME::QuotedPrint.

AUTHOR
======

   Eryq (`eryq@zeegee.com'), ZeeGee Software Inc (`http://www.zeegee.com').

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

   Thanks also to...

     Kent Boortz        For providing the idea, and the baseline
                        RFC-1522-decoding code!
     KJJ at PrimeNet    For requesting that this be split into
                        its own module.
     Stephane Barizien  For reporting a nasty bug.

VERSION
=======

   $Revision: 5.404 $ $Date: 2000/11/10 16:45:12 $

store multi-level hash structure in single level tied hash
**********************************************************

NAME
====

   MLDBM - store multi-level hash structure in single level tied hash

SYNOPSIS
========

     use MLDBM;				# this gets the default, SDBM
     #use MLDBM qw(DB_File FreezeThaw);	# use FreezeThaw for serializing
     #use MLDBM qw(DB_File Storable);	# use Storable for serializing

     $dbm = tie %o, 'MLDBM' [..other DBM args..] or die $!;

DESCRIPTION
===========

   This module can serve as a transparent interface to any TIEHASH package
that is required to store arbitrary perl data, including nested references.
Thus, this module can be used for storing references and other arbitrary
data within DBM databases.

   It works by serializing the references in the hash into a single
string. In the underlying TIEHASH package (usually a DBM database), it is
this string that gets stored.  When the value is fetched again, the string
is deserialized to reconstruct the data structure into memory.

   For historical and practical reasons, it requires the Data::Dumper
package, available at any CPAN site. Data::Dumper gives you really
nice-looking dumps of your data structures, in case you wish to look at
them on the screen, and it was the only serializing engine before version
2.00.  However, as of version 2.00, you can use any of Data::Dumper,
*FreezeThaw* or Storable to perform the underlying serialization, as
hinted at by the `SYNOPSIS' in this node overview above.  Using Storable
is usually much faster than the other methods.

   See the `BUGS' in this node section for important limitations.

Changing the Defaults
---------------------

   *MLDBM* relies on an underlying TIEHASH implementation (usually a DBM
package), and an underlying serialization package.  The respective
defaults are SDBM_File and D<Data::Dumper>.  Both of these defaults can be
changed.  Changing the SDBM_File default is strongly recommended.  See
`WARNINGS' in this node below.

   Three serialization wrappers are currently supported: Data::Dumper,
Storable, and *FreezeThaw*.  Additional serializers can be supported by
writing a wrapper that implements the interface required by
*MLDBM::Serializer*.  See the supported wrappers and the
*MLDBM::Serializer* source for details.

   In the following, *$OBJ* stands for the tied object, as in:

     $obj = tie %o, ....
     $obj = tied %o;

$MLDBM::UseDB	or	*$OBJ*->UseDB(*[TIEDOBJECT]*)
     The global $MLDBM::UseDB can be set to default to something other than
     SDBM_File, in case you have a more efficient DBM, or if you want to
     use this with some other TIEHASH implementation.  Alternatively, you
     can specify the name of the package at use time, as the first
     "parameter".  Nested module names can be specified as "Foo::Bar".

     The corresponding method call returns the underlying TIEHASH object
     when called without arguments.  It can be called with any object that
     implements Perl's TIEHASH interface, to set that value.

$MLDBM::Serializer	or	*$OBJ*->Serializer(*[SZROBJECT]*)
     The global $MLDBM::Serializer can be set to the name of the
     serializing package to be used. Currently can be set to one of
     Data::Dumper, Storable, or `FreezeThaw'. Defaults to Data::Dumper.
     Alternatively, you can specify the name of the serializer package at
     use time, as the second "parameter".

     The corresponding method call returns the underlying MLDBM serializer
     object when called without arguments.  It can be called with an
     object that implements the MLDBM serializer interface, to set that
     value.

Controlling Serializer Properties
---------------------------------

   These methods are meant to supply an interface to the properties of the
underlying serializer used.  Do not call or set them without understanding
the consequences in full.  The defaults are usually sensible.

   Not all of these necessarily apply to all the supplied serializers, so
we specify when to apply them.  Failure to respect this will usually lead
to an exception.

$MLDBM::DumpMeth	or  *$OBJ*->DumpMeth(*[METHNAME]*)
     If the serializer provides alternative serialization methods, this
     can be used to set them.

     With Data::Dumper (which offers a pure Perl and an XS verion of its
     serializing routine), this is set to `Dumpxs' by default if that is
     supported in your installation.  Otherwise, defaults to the slower
     `Dump' method.

     With Storable, a value of `portable' requests that serialization be
     architecture neutral, i.e. the deserialization can later occur on
     another platform. Of course, this only makes sense if your database
     files are themselves architecture neutral.  By default, native format
     is used for greater serializing speed in Storable.  Both Data::Dumper
     and *FreezeThaw* are always architecture neutral.

     *FreezeThaw* does not honor this attribute.

$MLDBM::Key  or  *$OBJ*->Key(*[KEYSTRING]*)
     If the serializer only deals with part of the data (perhaps because
     the TIEHASH object can natively store some types of data), it may need
     a unique key string to recognize the data it handles.  This can be
     used to set that string.  Best left alone.

     Defaults to the magic string used to recognize MLDBM data. It is a six
     character wide, unique string. This is best left alone, unless you
     know what you are doing.

     Storable and *FreezeThaw* do not honor this attribute.

$MLDBM::RemoveTaint  or  *$OBJ*->RemoveTaint(*[BOOL]*)
     If the serializer can optionally untaint any retrieved data subject to
     taint checks in Perl, this can be used to request that feature.  Data
     that comes from external sources (like disk-files) must always be
     viewed with caution, so use this only when you are sure that that is
     not an issue.

     Data::Dumper uses `eval()' to deserialize and is therefore subject to
     taint checks.  Can be set to a true value to make the Data::Dumper
     serializer untaint the data retrieved. It is not enabled by default.
     Use with care.

     Storable and *FreezeThaw* do not honor this attribute.

EXAMPLES
========

   Here is a simple example.  Note that does not depend upon the underlying
serializing package-most real life examples should not, usually.

     use MLDBM;				# this gets SDBM and Data::Dumper
     #use MLDBM qw(SDBM_File Storable);	# SDBM and Storable
     use Fcntl;				# to get 'em constants

     $dbm = tie %o, 'MLDBM', 'testmldbm', O_CREAT|O_RDWR, 0640 or die $!;

     $c = [\ 'c'];
     $b = {};
     $a = [1, $b, $c];
     $b->{a} = $a;
     $b->{b} = $a->[1];
     $b->{c} = $a->[2];
     @o{qw(a b c)} = ($a, $b, $c);

     #
     # to see what was stored
     #
     use Data::Dumper;
     print Data::Dumper->Dump([@o{qw(a b c)}], [qw(a b c)]);

     #
     # to modify data in a substructure
     #
     $tmp = $o{a};
     $tmp->[0] = 'foo';
     $o{a} = $tmp;

     #
     # can access the underlying DBM methods transparently
     #
     #print $dbm->fd, "\n";		# DB_File method

   Here is another small example using Storable, in a portable format:

     use MLDBM qw(DB_File Storable);	# DB_File and Storable

     tie %o, 'MLDBM', 'testmldbm', O_CREAT|O_RDWR, 0640 or die $!;

     (tied %o)->DumpMeth('portable');	# Ask for portable binary
     $o{'ENV'} = \%ENV;			# Stores the whole environment

BUGS
====

  1. Adding or altering substructures to a hash value is not entirely
     transparent in current perl.  If you want to store a reference or
     modify an existing reference value in the DBM, it must first be
     retrieved and stored in a temporary variable for further
     modifications.  In particular, something like this will NOT work
     properly:

          $mldb{key}{subkey}[3] = 'stuff';	# won't work

     Instead, that must be written as:

          $tmp = $mldb{key};			# retrieve value
          $tmp->{subkey}[3] = 'stuff';
          $mldb{key} = $tmp;			# store value

     This limitation exists because the perl TIEHASH interface currently
     has no support for multidimensional ties.

  2. The Data::Dumper serializer uses eval().  A lot.  Try the Storable
     serializer, which is generally the most efficient.

WARNINGS
========

  1. Many DBM implementations have arbitrary limits on the size of records
     that can be stored.  For example, SDBM and many ODBM or NDBM
     implementations have a default limit of 1024 bytes for the size of a
     record.  MLDBM can easily exceed these limits when storing large data
     structures, leading to mysterious failures.  Although SDBM_File is
     used by MLDBM by default, it is not a good choice if you're storing
     large data structures.  Berkeley DB and GDBM both do not have these
     limits, so I recommend using either of those instead.

  2. MLDBM does well with data structures that are not too deep and not
     too wide.  You also need to be careful about how many FETCHes your
     code actually ends up doing.  Meaning, you should get the most mileage
     out of a FETCH by holding on to the highest level value for as long
     as you need it.  Remember that every toplevel access of the tied hash,
     for example `$mldb{foo}', translates to a MLDBM FETCH() call.

     Too often, people end up writing something like this:

          tie %h, 'MLDBM', ...;
          for my $k (keys %{$h{something}}) {
              print $h{something}{$k}[0]{foo}{bar};  # FETCH _every_ time!
          }

     when it should be written this for efficiency:

          tie %h, 'MLDBM', ...;
          my $root = $h{something};                  # FETCH _once_
          for my $k (keys %$root) {
              print $k->[0]{foo}{bar};
          }

AUTHORS
=======

   Gurusamy Sarathy <`gsar@umich.edu'>.

   Support for multiple serializing packages by Raphael Manfredi
<`Raphael_Manfredi@grenoble.hp.com'>.

   Copyright (c) 1995-98 Gurusamy Sarathy.  All rights reserved.

   Copyright (c) 1998 Raphael Manfredi.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

VERSION
=======

   Version 2.00	10 May 1998

SEE ALSO
========

   perl(1), perltie(1), perlfunc(1), Data::Dumper(3), FreezeThaw(3),
Storable(3).

safe concurrent access to MLDBM databases
*****************************************

NAME
====

     MLDBM::Sync (BETA) - safe concurrent access to MLDBM databases

SYNOPSIS
========

     use MLDBM::Sync;                       # this gets the default, SDBM_File
     use MLDBM qw(DB_File Storable);        # use Storable for serializing
     use MLDBM qw(MLDBM::Sync::SDBM_File);  # use extended SDBM_File, handles values > 1024 bytes

     # NORMAL PROTECTED read/write with implicit locks per i/o request
     my $sync_dbm_obj = tie %cache, 'MLDBM::Sync' [..other DBM args..] or die $!;
     $cache{"AAAA"} = "BBBB";
     my $value = $cache{"AAAA"};

     # SERIALIZED PROTECTED read/write with explicit lock for both i/o requests
     my $sync_dbm_obj = tie %cache, 'MLDBM::Sync', '/tmp/syncdbm', O_CREAT|O_RDWR, 0640;
     $sync_dbm_obj->Lock;
     $cache{"AAAA"} = "BBBB";
     my $value = $cache{"AAAA"};
     $sync_dbm_obj->UnLock;

     # SERIALIZED PROTECTED read access with explicit read lock for both reads
     $sync_dbm_obj->ReadLock;
     my @keys = keys %cache;
     my $value = $cache{'AAAA'};
     $sync_dbm_obj->UnLock;

     # KEY CHECKSUMS, for lookups on MD5 checksums on large keys
     my $sync_dbm_obj = tie %cache, 'MLDBM::Sync', '/tmp/syncdbm', O_CREAT|O_RDWR, 0640;
     $sync_dbm_obj->SyncKeysChecksum(1);
     my $large_key = "KEY" x 10000;
     $sync{$large_key} = "LARGE";
     my $value = $sync{$large_key};

DESCRIPTION
===========

   This module wraps around the MLDBM interface, by handling concurrent
access to MLDBM databases with file locking, and flushes i/o explicity per
lock/unlock.  The new [Read]Lock()/UnLock() API can be used to serialize
requests logically and improve performance for bundled reads & writes.

     my $sync_dbm_obj = tie %cache, 'MLDBM::Sync', '/tmp/syncdbm', O_CREAT|O_RDWR, 0640;

     # Write locked critical section
     $sync_dbm_obj->Lock;
       ... all accesses to DBM LOCK_EX protected, and go to same tied file handles
       $cache{'KEY'} = 'VALUE';
     $sync_dbm_obj->UnLock;

     # Read locked critical section
     $sync_dbm_obj->ReadLock;
       ... all read accesses to DBM LOCK_SH protected, and go to same tied files
       ... WARNING, cannot write to DBM in ReadLock() section, will die()
       my $value = $cache{'KEY'};
     $sync_dbm_obj->UnLock;

     # Normal access OK too, without explicity locking
     $cache{'KEY'} = 'VALUE';
     my $value = $cache{'KEY'};

   MLDBM continues to serve as the underlying OO layer that serializes
complex data structures to be stored in the databases.  See the MLDBM
`BUGS' in this node section for important limitations.

INSTALL
=======

   Like any other CPAN module, either use CPAN.pm, or perl -MCPAN -e shell,
or get the file MLDBM-Sync-x.xx.tar.gz, unzip, untar and:

     perl Makefile.PL
     make
     make test
     make install

LOCKING
=======

   The MLDBM::Sync wrapper protects MLDBM databases by locking and
unlocking around read and write requests to the databases.  Also necessary
is for each new lock to tie() to the database internally, untie()'ing when
unlocking.  This flushes any i/o for the dbm to the operating system, and
allows for concurrent read/write access to the databases.

   Without any extra effort from the developer, an existing MLDBM database
will benefit from MLDBM::sync.

     my $dbm_obj = tie %dbm, ...;
     $dbm{"key"} = "value";

   As a write or STORE operation, the above will automatically cause the
following:

     $dbm_obj->Lock; # also ties
     $dbm{"key"} = "value";
     $dbm_obj->UnLock; # also unties

   Just so, a read or FETCH operation like:

     my $value = $dbm{"key"};

   will really trigger:

     $dbm_obj->ReadLock; # also ties
     my $value = $dbm{"key"};
     $dbm_obj->Lock; # also unties

   However, these lock operations are expensive because of the underlying
tie()/untie() that occurs for i/o flushing, so when bundling reads &
writes, a developer may explicitly use this API for greater performance:

     # tie once to database, write 100 times
     $dbm_obj->Lock;
     for (1..100) {
       $dbm{$_} = $_ * 100;
       ...
     }
     $dbm_obj->UnLock;

     # only tie once to database, and read 100 times
     $dbm_obj->ReadLock;
     for(1..100) {
       my $value = $dbm{$_};
       ...
     }
     $dbm_obj->UnLock;

KEYS CHECKSUM
=============

   A common operation on database lookups is checksumming the key, prior
to the lookup, because the key could be very large, and all one really
wants is the data it maps too.  To enable this functionality automatically
with MLDBM::Sync, just:

     my $sync_dbm_obj = tie %cache, 'MLDBM::Sync', '/tmp/syncdbm', O_CREAT|O_RDWR, 0640;
     $sync_dbm_obj->SyncKeysChecksum(1);

     !! WARNING: keys() & each() do not work on these databases
     !! as of v.03, so the developer will not be fooled into thinking
     !! the stored key values are meaningful to the calling application
     !! and will die() if called.
     !!
     !! This behavior could be relaxed in the future.

     An example of this might be to cache a XSLT conversion,
     which are typically very expensive.  You have the
     XML data and the XSLT data, so all you do is:

     # $xml_data, $xsl_data are strings
     my $xslt_output;
     unless ($xslt_output = $cache{$xml_data.'&&&&'.$xsl_data}) {
       ... do XSLT conversion here for $xslt_output ...
       $cache{$xml_data.'&&&&'.xsl_data} = $xslt_output;
     }

   What you save by doing this is having to create HUGE keys to lookup on,
which no DBM is likely to do efficiently.  This is the same method that
File::Cache uses internally to hash its file lookups in its directories.

New MLDBM::Sync::SDBM_File
==========================

   SDBM_File, the default used for MLDBM and therefore MLDBM::Sync has a
limit of 1024 bytes for the size of a record.

   SDBM_File is also an order of magnitude faster for small records to use
with MLDBM::Sync, than DB_File or GDBM_File, because the tie()/untie() to
the dbm is much faster.  Therefore, bundled with MLDBM::Sync release is a
MLDBM::Sync::SDBM_File layer which works around this 1024 byte limit.  To
use, just:

     use MLDBM qw(MLDBM::Sync::SDBM_File);

   It works by breaking up up the STORE() values into small 128 byte
segments, and spreading those segments across many records, creating a
virtual record layer.  It also uses Compress::Zlib to compress STORED
data, reducing the number of these 128 byte records. In benchmarks, 128
byte record segments seemed to be a sweet spot for space/time
effienciency, as SDBM_File created very bloated *.pag files for 128+ byte
records.

BENCHMARKS
==========

   In the distribution ./bench directory is a bench_sync.pl script that
can benchmark using the various DBMs with MLDBM::Sync.

   The MLDBM::Sync::SDBM_File DBM is special because is uses SDBM_File for
fast small inserts, but slows down linearly with the size of the data
being inserted and read, with the speed matching that of GDBM_File &
DB_File somewhere around 20,000 bytes.

   So for DBM key/value pairs up to 10000 bytes, you are likely better off
with MLDBM::Sync::SDBM_File if you can afford the extra space it uses.  At
20,000 bytes, time is a wash, and disk space is greater, so you might as
well use DB_File or GDBM_File.

   Note that MLDBM::Sync::SDBM_File is ALPHA as of 2/27/2001.

   The results for a dual 450 linux 2.2.14, with a ext2 file system
blocksize 4096 mounted async on a SCSI disk were as follows:

     === INSERT OF 50 BYTE RECORDS ===
      Time for 100 writes + 100 reads for  SDBM_File                  0.13 seconds     12288 bytes
      Time for 100 writes + 100 reads for  MLDBM::Sync::SDBM_File     0.15 seconds     12288 bytes
      Time for 100 writes + 100 reads for  GDBM_File                  3.33 seconds     18066 bytes
      Time for 100 writes + 100 reads for  DB_File                    4.26 seconds     20480 bytes

     === INSERT OF 500 BYTE RECORDS ===
      Time for 100 writes + 100 reads for  SDBM_File                  0.17 seconds   1033216 bytes
      Time for 100 writes + 100 reads for  MLDBM::Sync::SDBM_File     0.54 seconds    110592 bytes
      Time for 100 writes + 100 reads for  GDBM_File                  3.47 seconds     63472 bytes
      Time for 100 writes + 100 reads for  DB_File                    4.30 seconds     86016 bytes

     === INSERT OF 5000 BYTE RECORDS ===
     (skipping test for SDBM_File 1024 byte limit)
      Time for 100 writes + 100 reads for  MLDBM::Sync::SDBM_File     1.33 seconds   1915904 bytes
      Time for 100 writes + 100 reads for  GDBM_File                  4.32 seconds    832400 bytes
      Time for 100 writes + 100 reads for  DB_File                    6.16 seconds    839680 bytes

     === INSERT OF 20000 BYTE RECORDS ===
     (skipping test for SDBM_File 1024 byte limit)
      Time for 100 writes + 100 reads for  MLDBM::Sync::SDBM_File     4.40 seconds   8173568 bytes
      Time for 100 writes + 100 reads for  GDBM_File                  4.86 seconds   2063912 bytes
      Time for 100 writes + 100 reads for  DB_File                    6.71 seconds   2068480 bytes

     === INSERT OF 50000 BYTE RECORDS ===
     (skipping test for SDBM_File 1024 byte limit)
      Time for 100 writes + 100 reads for  MLDBM::Sync::SDBM_File    12.87 seconds  27446272 bytes
      Time for 100 writes + 100 reads for  GDBM_File                  5.39 seconds   5337944 bytes
      Time for 100 writes + 100 reads for  DB_File                    7.22 seconds   5345280 bytes

WARNINGS
========

   MLDBM::Sync is in BETA.  As of 2/27/2001 I have been using it in
development for months, and been using its techniques for years in
Apache::ASP $Session & $Application data storage.  Future releases of
Apache::ASP will use MLDBM::Sync for its Apache::ASP::State base
implementation instead of MLDBM

   MLDBM::Sync::SDBM_File is ALPHA quality.  Databases created while using
it may not be compatible with future releases if the segment manager code
or support for compression changes.

TODO
====

   Production testing.

AUTHORS
=======

   Copyright (c) 2001 Joshua Chamas, Chamas Enterprises Inc.  All rights
reserved.  Sponsored by development on NodeWorks http://www.nodeworks.com

SEE ALSO
========

     MLDBM(3), SDBM_File(3), DB_File(3), GDBM_File(3)

Perl module for indexing and searching text files and web objects
*****************************************************************

NAME
====

   MMM::Text::Search - Perl module for indexing and searching text files
and web objects

SYNOPSIS
========

     use MMM::Text::Search;

     my $srch = new MMM::Text::Search {	#for indexing...
     	#index main file location...
     		IndexPath => "/tmp/myindex.db",
     	#local files...
     		FileMask  => '(?i)(\.txt|\.htm.?)$',
     		Dirs	  => [ "/usr/doc", "/tmp" ] ,
     		FollowSymLinks => 0|1, (default = 0)
     	#web objects...
     		URLs	  => [ "http://localhost/", ... ],
     		Level	  => recursion-level (0=unlimited)
     	#common options...
     		IgnoreLimit =>	0.3,   (default = 2/3)
     		Verbose => 0|1
     	};

     $srch->makeindex;

     my $srch = new MMM::Text::Search (  #for searching....
     		  "/tmp/myindex.db", verbose_flag );

     my $hashref = $srch->query("pizza","ciao", "-pasta" );
     my $hashref = $srch->advanced_query("(pizza OR ciao) AND NOT pasta");

     $srch->errstr()	# returns last error
     			# (only query syntax-errors for the moment being)

     $srch->dump_word_stats(\*FH)

DESCRIPTION
===========

   * Indexing

     makeindex() does all the job of indexing. When it's finished the
     following files will have been created (assuming IndexPath =
     /path/myindex.db, see constructor):

          /path/myindex.db	 word index database
          /path/myindex-files.db	 filename/URL database
          /path/myindex-titles.db	 html title database
          /path/myindex.stopwords	 stop-words list
          /path/myindex.filelist	 readable list of indexed files/URLs
          /path/myindex.deadlinks	 broken http links

          [... lots of important things missing ... ]

     dump_word_stats(\*FH) dumps all words sorted by occurence frequency
     using FH file handle (or STDOUT if no parameter is specified).
     Stop-words get a frequency value of 1.

   * Searching

     Both query() and advanced_query() return a reference to a hash with
     the following structure:

          (
           ignored  => [ string, string, ... ], # ignored words
           searched => [ string, string, ... ], # words searched for
           files    => [  hashref, hashref, ... ] # list of files
          					# or URLs found
           )

          The 'files' element is a reference to an array of hashes, each having
          the following structure:

          (
           	 filename => string,  # file path or http URL
           score    => number,  # score
           title    => string   # HTML title
          )

NOTES
=====

   Note on implementation: The technique used for indexing is
substantially derived from that exposed by Tim Kientzle on Dr. Dobbs
magazine.

BUGS
====

   Many, I guess.

AUTHOR
======

   Max Muzi <maxim@comm2000.it>

SEE ALSO
========

   perl(1).

Perl extension providing a meta-object protocol for Perl modules.
*****************************************************************

NAME
====

   MOP::MOP - Perl extension providing a meta-object protocol for Perl
modules.

SYNOPSIS
========

     # A random package declaration
     package MyBaseModule;

     # Activate the meta-object protocol for a few methods
     use MOP::MOP qw(new method1 method3);
     # Our meta-module is 'MyMetaModule'
     MOP::MOP::register_meta('MyMetaModule','MyBaseModule');

     # Some functions
     sub new () {
     	return bless {};
     }
     sub method1 ($$) { ... }
     sub method2 ($) { ... }
     sub method3 () { ... }

DESCRIPTION
===========

   This module provides a simple and, in my opinion, powerful meta-object
protocol (MOP) for Perl5 modules.  In short, such MOP allows to *trap the
method calls* made on an object (represented by a reference) before they
reach the original module implementing them. These method calls are
redirected to another module, called the meta-module, before their
execution. The original (legitimate) destination of the method call is in
the (base) module. Of course, one day or another, the meta-module should
perform the actual normal method call at the base level, but it can do
some nice things before or after doing that. And this is the whole purpose
of its existence.

   MOP::MOP implements the base level part of the protocol. This module is
tightly linked with module MOP::MetaModule which implements the other
upper part of the behavior, i.e. the generic behavior of a meta-module.

   In the above example, MyBaseModule is the base module, and MyMetaModule
is the meta-module (not shown here). In this example, the 3 methods new(),
method1() and method3() are modified due to the MOP.  These methods become
*reflective* methods. When a user of MyBaseModule calls one of these
methods, they are not called directly, but the method meta_method_call()
of MyMetaModule is called instead. This method is passed the original
arguments of the method call, prepended by the (base level) method name and
(base level) object reference or package name used.

   Hence, if a programmer does:

     use MyBaseModule;
     my $obj = MyBaseModule->new($newarg);
     $obj->method1($foo, $bar);
     $obj->method2($bur);
     $obj->method3();

   In fact, the actual operations taking place correspond to the following
steps.

  1. `$obj = MyMetaModule->meta_method_call(new_Refl, 'MyBaseModule',
     $newarg)'

     This occurs in place of the first call, as MyMetaModule is registered
     as the meta-module of MyBaseModule.

        Then, supposing that at the end of this strange new() a meta-object
referenced by $metaobj is registered for the freshly created $obj, the
processing will continue as in the following.

  1. $metaobj->meta_method_call(*method1_Refl*, $obj, $foo, $bar)

     This is the call of a reflective method on $obj and such calls are
     processed by the meta-object, not by perl itself directly (even though
     Perl behavior remains valid somewhere else).

  2. $obj->method2($bur)

     This is a normal method call. As method2() is not reflective, the
     work is done by perl itself.

  3. $metaobj->meta_method_call(*method2_Refl*, $obj)

     Again, a reflective method call to finish.

        Note: Here, even if they are actually used, the *blabla_Refl*
names are only for illustration. They represent the name of the base level
method. The meta-object needs them if it ever wants the real work to be
done. But note that the structure of these names may not follow this
scheme indefinitely (and these thingies may become code references in the
future).  See  meta_handle_method_call() in MOP::MetaModule.

   A MOP is mainly useful for modules that provide a rather strict
object-oriented interface. It allows to extend transparently the
functionality provided by such a class module in order to provide
additional properties not directly related to the module functions. This
may sound rather obscure, but it can really be useful.  For example, this
is the case in the real world when you want to add transparent
distribution to your programs, when you want to enhance such distributed
execution with a CRC integrity check in messages, when you want to manage
multiple replicas of a server, etc.

Functions
---------

`MOP::MOP::register_meta($metaobj,$obj)'
     Registers the object $metaobj as the meta-object of the (base) object
     $obj. This allows the MOP to find which meta-object is associated to
     a given object (the meta-level often needs a state, stored in the
     meta-object).  You can also directly associate a meta-module to a
     module. This is even necessary to bootstrap the protocol somewhere.

`MOP::MOP::find_meta($obj)'
     Finds the meta-object associated to $obj. It is usually not needed to
     call this function directly as the MOP itself provides the base level
     object to the meta-object among the arguments to meta_method_call().

Is it possible to do something useful with this?
------------------------------------------------

   The test programs included with the distribution of this module
demonstrate such usage (and I hope that the number of really useful
meta-modules will increase as time goes and files migrate from `t/' to
their own subdirectory). Most simple examples deal with not very useful
meta-modules, such as counting the number of method calls, tracing some
method calls, etc.

   More serious examples include a full-featured client/server system that
should allow to execute any Perl object remotely without modifying the
source code of the original module. The MOP traps the creation and local
method calls on the object (which remains an empty proxy on the client
side). The meta-module takes care of redirecting all calls and calling the
real object on the server.  See module MOP::Remote.  Note that you need
the Data::Dumper module to run that test. Currently, it is blindly based
on the availability of the Unix rsh command. But I've been seriously using
this mechanism for distributed processing for more than one year up to now.

   A future demo program that will be added soon will show how to add some
(simple) encryption to that remote execution system. The idea is simply to
encrypt transparently the data exchanged by the client/server
meta-objects, using another meta-object. Thus introducing to the world a
*meta* meta-module.

Notes
-----

   The MOP::MOP module is implemented as a source filter and is dependent
on the Filter::Util::Call module.

   This module transparently *modifies the source code of your module*. It
really renames the method subroutines and replaces them by stubs. Be warned
that we are somehow redefining the world...

   Would it be possible to keep the module source code somewhere in memory
and track the uses of libraries thanks to this mechanism? It could be nice
to enable Perl to send all this to another host...

BUGS
====

   Functions stubs (e.g.: `sub truc;') probably do not work.

   This documentation is much bigger than the module code itself.  Do not
hesitate to read the source code!

AUTHOR
======

   Rodolphe Ortalo, ortalo@laas.fr

Acknowledgements
----------------

   This work has been performed with the support of LAAS-CNRS.

SEE ALSO
========

   perl(1), MOP::MetaModule(3), MOP::Remote(3), Filter::Util::Call(3).

Perl base class for all meta-modules.
*************************************

NAME
====

   MOP::MetaModule - Perl base class for all meta-modules.

SYNOPSIS
========

   Basic usage example. Absolutely useless.

     use MOP::MetaModule;
     use MOP::MOP;
     use MyBaseModule; # A reflective package

     my $obj = MyBaseModule->new();
     my $raw_meta_obj = MOP::MetaModule->new();

     # Provides (or replaces) the meta-object for the base object
     MOP::MOP::register_meta($raw_meta_obj, $obj);

     $obj->method1($foo,$bar);# With a raw meta-object, method calls are
     $obj->method2($bur);     # done normally.  But they are done by the
     $obj->method3();         # meta-object. (I told you it was useless.)

   Simple derived class that correspond to the normal context of a
meta-module.  It allows to perform additional operations before or after
the method call.

   use MOP::MetaModule;   use MOP::MOP; # We probably use some MOP
function somewhere

     use vars qw(@ISA);
     @ISA = qw(MOP::MetaModule);

     # Overload the meta-level management of a method call
     sub meta_method_call {
        # Get the meta-object (sometimes a meta-module)
         my $meta_that = shift;
         # Get the (base level) method name
         my $reflected_method = shift;
         # Normal method arguments (including base self)
         my @method_args = @_;
         # Placeholder for returned value(s)
         my @returned;
         ...
         # Here, you have full control over how the actual method call
         # will take place. So, do something nice that enhances the object
         # behavior, and somewhere, you can do the real method call with:
         @returned = $meta_that->meta_handle_method_call($reflected_method,
     						      @method_args);
         ...
         return wantarray ? @returned : $returned[0];
     }

DESCRIPTION
===========

Methods
-------

`MOP::MetaModule->new()' or $meta_thing->new()
     Creates a new raw meta-object from the MOP::MetaModule class. This
     one will do nothing except normal method calls. This method should be
     overloaded, but the default method will provide you an anonymous hash
     that you can use directly as a placeholder for some named attributes
     if you want.

$meta_thing->meta_method_call($method_name, $base_arguments)
     This method is called by the meta-object protocol (MOP) when a
     (reflective) method call is performed on a base level object
     controlled by a meta-object. Hence, it provides the entry point where
     you should customize the meta-object behavior if you want to do
     something nice for the object. This method should be overloaded in
     real meta-classes. For example, you can imagine saving some state
     before the call, and restoring that state in case the method fails
     the rough way.  The meta-object could also call a remote server (see
     MOP::Remote).  The MOP may call this method either via a blessed
     reference (a real meta-object) or on the module itself (that behaves
     then like a meta-class).

$meta_thing->meta_handle_method_call($method_name, $base_arguments)
     This method will perform the actual call to the base level class or
     object and return you the results from this call. Inside the
     meta-object methods, this one allows you to activate the real method
     call requested originally by the programmer (or by a lower
     meta-level). You should use this method that you will inherit from
     MOP::MetaModule to do so as it will be able to locate the original
     method thanks to the method name provided by the MOP.

Usage outline
-------------

   In the following example, the synopsis is detailed a little further to
show how you can write a meta-module. Most of the work is done inside the
meta_method_call() method which needs to study the base level methods
names and act accordingly. Base level constructors deserve special care as
the meta-module should usually create a meta-object and register it with
the freshly created base level object (see the `/new/' case below).  More
generally, pure class methods called on the base module should be treated
with care at the meta-level.

     # We are a meta-module: use MetaModule to inherit from it
     use MOP::MetaModule;
     # We probably use the MOP register function in object creation
     use MOP::MOP;

     use vars qw(@ISA);
     @ISA = qw(MOP::MetaModule);

     ###  META-METHODS  ###
     # Trap of method call
     sub meta_method_call {
         my $meta_that = shift; # meta-object (sometimes meta-module)
         my $reflected_method = shift; # Get the (base) method name
         my @method_args = @_; # Normal method arguments (w/ self)
         my @returned; # Placeholder
         # Switch on method name.
         foreach ($reflect) {
     	  # Specific behavior for 'new' method: meta-object creation
     	  /new/o and do {
     	      # We call the base-level creation method
     	      @returned =
     	       $meta_that->meta_handle_method_call($reflected_method,
     						   @method_args);
     	      # We create a meta object for this object
     	      my $meta_object = $meta_that->new();
     	      # ...we initialize it if we need some meta-state...
     	      # We register both the object and meta-object.
     	    MOP::MOP::register_meta($meta_object, $returned[0]);
     	      last;
     	  };
     	  # First, we manage only object methods... (Not mandatory)
     	  if (ref($m_that)) {
     	      # Behavior for working methods
     	      /method1|method3/o and do {
     		  ...do something nice before the method call...
     		  @returned =
     		   $meta_that->meta_handle_method_call($reflected_method,
     						       @method_args);
     		  ...do something nice after the method call...
     	      };
     	  } else { # Here, we deal we class methods...
     	      ...spit some warning...but call it anyway...
     	      @returned =
     	       $meta_that->meta_handle_method_call($reflected_method,
     						   @method_args);
     	  }
         }
         return wantarray ? @returned : $returned[0];
     }

   Useful work can be performed on normal method calls on base level
objects (see the `/method1|method3/' case above). At this point, you have
full control on the method parameters and behavior. Possible usages
involve: security management via authorization verification or arguments
encryption, fault tolerance via multiple replicas management or stable
storage of object state, transparent remote execution, and maybe a
combination of these.

BUGS
====

   It is not yet clear how *destruction* of base level objects can be
trapped and handled in the meta-module. Expect improvement on this point
(and an additional class method to manage carefully in the meta-object).

AUTHOR
======

   Rodolphe Ortalo, ortalo@laas.fr

Acknowledgements
----------------

   This work has been performed with the support of LAAS-CNRS.

SEE ALSO
========

   perl(1), MOP::MOP(3).

Perl meta-module for transparent distribution of object oriented modules.
*************************************************************************

NAME
====

   MOP::Remote - Perl meta-module for transparent distribution of object
oriented modules.

SYNOPSIS
========

     # A random package declaration
     package MyModule;

     # Activate the meta-object protocol for a few methods
     use MOP::MOP qw(new method1 method3);
     # Our meta-module is 'MOP::Remote'
     MOP::MOP::register_meta('MOP::Remote','MyModule');

     # Some functions
     sub new { return bless { ... }; } # Constructor
     sub method1 { ... }
     sub method2 { ... }
     sub method3 { ... }

     ##### NOW USING MyModule ####
     use MyModule;

     # Creates a remote server
     my $REMOTE = 'host.name.fr'; my $PORT = 1234;
     my $server = MOP::Remote::create_server('MyModule', $REMOTE, $PORT);

     # Creates an object - additional argument is grabbed by meta-module
     my $o = MyModule->new(..., $server);
     # Now, simply use it: all methods are done remotely on $REMOTE_HOST
     $o->method1();
     my $var = $o->method3('a_value');
     ...

DESCRIPTION
===========

   This module provides two things:

     An example of basic meta-module that demonstrates how it is possible
     to design a meta-module, and use it to provide useful functionality
     to third-party module writers.

     A transparent way of adding remote processing capabilities to any
     module with minimal modifications. This will probably work only on
     Unix systems.

   Using this module should be straightforward. In the definition of an
object-oriented Perl module that you want to enhance by remote processing
capabilities, you simply need to state that several methods should be
reflective, with: `use MOP::MOP qw(method_name1 method_name2 ...)'.  This
simply makes the MOP (Meta-Object Protocol) aware of the given methods.
Then, you should probably define a static link between your module and the
MOP::Remote meta-module with:
`MOP::MOP::register_meta('MOP::Remote','MyModule')', at the beginning of
`MyModule.pm'.  This magic formula indicates to the MOP that MOP::Remote
is the meta-module to be used for MyModule. It is this meta-module that
provides the magical remote processing capability.

   Then, the user of MyModule creates a new server via the create_server()
function of MOP::Remote, in order to create new objects on that server.
All method calls on such an object will be performed on the remote server.
If the user wants to create a local object (in-process), he simply passes
the constant LOCAL instead of a server reference, as in:
`MyModule->new(..., 'LOCAL')'. This creates an object normally.  But then,
there is nothing funny anymore.

Detailed operation
------------------

   At creation via `MyModule->new(...,$server)', the call will be trapped
and redirected to the host associated with the given server.  The $server
argument will be removed before calling the new() method on the server, of
course.  The remote server will create a new object, and the local machine
will simply return you an empty hashref that plays the role of a proxy.
In fact, two additional meta-objects will be created: one locally that
will hold some useful information (such as the remote object ID) and will
control the future method calls made on the proxy, and one meta-object on
the remote server that will perform the real base-level method call on the
real (remote) object.

   Afterwards, all method calls made on objects from MyModule will be
trapped by the MOP and redirected to MOP::Remote. The (local) meta-object
created after the call to new() will be used to find the remote processing
server, and the call with all its arguments will be redirected to that
server. On the remote host, the server will catch this request, perform
the operation on the real object (via its own meta-object) and communicate
the results back to your process. The returned value will be sent back to
you.  Data::Dumper is used (in deep mode) to pass the arguments back and
forth.  So, it is possible that some references be lost during the network
exchange, depending on the base module operation.

   The remote invocation is a blocking one. If you want to perform multiple
concurrent remote invocations, you should handle that yourself.

   Currently, you should consider MOP::Remote as a form of RPC.  It is
also preferred to create different remote servers for different modules
(ie: one for each class).  You can create several objects on one server,
and you may also create them from different client machines. However, note
that one remote server serializes the method calls (it does not do any
fork()) and that you will need to find a way to exchange the server
reference. This is not exactly the normal way of operation.

Functions
---------

`$server = MOP::Remote::create_server($module_name[,$host,$port,$remote_perl])'
     This function creates a new server on a remote machine. $module_name
     should contain the name of the module that is operated by the server.
     rsh is used to create a Perl process on the remote machine, so you
     need to have rsh and an account on the remote machine (that does not
     require a password).  The remaining arguments are optional. $host is
     the name of a remote host on which you want to create the server. It
     defaults to 'localhost', ie: the local host (in another Perl process
     in fact - this is a behavior of rsh). However, you will probably want
     to specify this one.  $port is the TCP port number used for the
     communication between the client and the server.  It default to 2345
     (an arbitrary value). You should adapt that to your application.
     Finally, $remote_perl may indicate the name of the Perl executable to
     use on the remote machine. MOP::Remote tries to be smart and to guess
     that name, so usually you need not specify it. But in cross-platform
     configurations, it may be useful to be able to specify it. (*Hint*:
     if you configured your shell initializations correcty so that the
     simple command *perl* works on the remote host, MOP::Remote will
     surely find the name of a good Perl executable.)

     This function will return you a hash reference that contains
     server-related information. You may use that hashref to create
     objects on the server via new().

`MOP::Remote::exit_server($server)'
     This function will send an exit message to the remote server that will
     handshake and exit.

Notes
-----

   MOP::Remote *closes* STDOUT and `STDERR' on the remote server by
default.  It may be difficult to debug your module (that executes
remotely).  You can set the debug flag `$MOP::Remote::DEBUG'. In that case,
MOP::Remote will not close ouputs and will arrange to maintain a link
between the standard outputs of remote processes and the local terminal.
You can also set `$MOP::Remote::DEBUG2' if you want to see the messages
exchanged between the client and the server.

   I have successfully tested remote invocations between Solaris and Linux
hosts.  However, cross-platform invocation, even though possible, still
involves careful setup of both platforms Perl5 modules library.  (The same
modules should be available on both hosts.  Versions should be similar.
Previous note is really applicable.)

   MOP::Remote depends on Data::Dumper.

LIMITATIONS AND FUTURE EVOLUTIONS
=================================

   The client-server functionality implemented inside MOP::Remote is
self-contained but rather basic. It would be desirable to use a more
sophisticated set of functionalities for client-server operation (like in
EventServer).  Only the true meta-level part of MOP::Remote should remain
in that case.

   As any magical device, MOP::Remote surely has a lot of shortcomings.
In fact, it is not sure at all that a MOP::Remote-enhanced module will
behave exactly like a normal module. For example, the inheritance
semantics of a reflective module is not (yet) clear. If something inherits
from MyModule, but overloads some methods, the remote processing
capability may be broken for these methods.

   Furthermore, if some public methods are not reflective, the MOP does
not know them, so they will not be trapped to be sent to the remote
server. Instead they will be executed locally by Perl itself: at once *on
a proxy object*. So the result will surely be some bad thing. Private
method calls need not be reflective, because the user should never call
them (or they would not be private), but well... nothing really prevents
them from doing so especially when inheritance is involved.

   Finally, there may be meta-meta-objects on any side of the client-server
communication, and at this point, my brain usually stops understanding the
real path of the method call. Maybe Perl will figure out what to do...
(Remember this is just an example.)

BUGS
====

   Due to a limitation of the meta-object protocol of MOP::MOP, the
destruction of objects is not handled. If you create a lot of objects on
the remote server and do not use them, it may be a (remote) problem.

   new() is the only class method name considered. If your module has
other constructors that should execute remotely, you should modify the
meta-module. Currently MOP::Remote will complain, but it will perform the
class method call locally anyway.

   The default TCP port number used for communication is arbitrary: it is
2345.

AUTHOR
======

   Rodolphe Ortalo, ortalo@laas.fr

Acknowledgements
----------------

   This work has been performed with the support of LAAS-CNRS.

SEE ALSO
========

   perl(1), MOP::MOP(3), MOP::MetaModule(3).

a daemon that possesses mpg123
******************************

NAME
====

   MP3::Daemon - a daemon that possesses mpg123

SYNOPSIS
========

   MP3::Daemon is meant to be subclassed - not used directly.

     package MP3::Daemon::Simple;

     use strict;
     use vars qw(@ISA);
     use MP3::Daemon;

     @ISA = qw(MP3::Daemon);

   Other perl scripts would use MP3::Daemon::Simple like this:

     my $socket_path = "/tmp/mp3d_socket";

     # start up a daemon
     MP3::Daemon::Simple->spawn($socket_path);

     # get a socket that's good for one request to the daemon
     my $client = MP3::Daemon::Simple->client($socket_path);

     print $client @command;

REQUIRES
========

Audio::Play::MPG123
     This is used to control mpg123 in remote-mode.

IO::Socket::UNIX
     This is for client/server communication.

IO::Select
     I like the OO interface.  I didn't feel like using normal select()
     and messing with vec().

MP3::Info
     This is for getting information from mp3 files.

Pod::Usage
     This is an optional module that bin/mp3 uses to generate help
     messages.

POSIX
     This is just for setsid.

DESCRIPTION
===========

   MP3::Daemon provides a framework for daemonizing mpg123 and
communicating with it using unix domain sockets.  It provides an event
loop that listens for client requests and also polls the mpg123 player to
monitor its state and change mp3s when one finishes.

   The types of client requests available are not defined in MP3::Daemon.
It is up to subclasses of MP3::Daemon to flesh out their own protocol for
communicating with the daemon.  This was done to allow people freedom in
defining their own mp3 player semantics.

   The following is a short description of the subclasses of MP3::Daemon
that are packaged with the MP3::Daemon distribution.

MP3::Daemon::Simple => mp3
--------------------------

   This subclass of MP3::Daemon provides a very straightforward mp3
player.  It comes with a client called *mp3* that you'll find in the bin/
directory.  It implements a very simple playlist.  It also implements
common commands one would expect from an player, and it feels very similar
to cdcd(1).  It is touted as an mpg123 front-end for UNIX::Philosophers,
because it does not have a Captive User Interface.

   For more information, `perldoc mp3`;

MP3::Daemon::PIMP => pimp
-------------------------

   This subclass of MP3::Daemon has yet to be written.  The significant
difference between M:D:Simple and M:D:PIMP will be the *Plaqueluster*.  A
Plaqueluster is a pseudorandom playlist that enforces a user-definable
level of non-repetitiveness.  It is also capable of maintaining a median
volume such that all mp3s are played at the same relative volume.  Never
again will you be startled by having an mp3 recorded at a low volume being
followed by an mp3 recorded *VERY LOUDLY*.

   For more information, `perldoc pimp`;

METHODS
=======

Server-related Methods
----------------------

   MP3::Daemon relies on unix domain sockets to communicate.  The socket
requires a place in the file system which is referred to as `$socket_path'
in the following descriptions.

new $socket_path
     This instantiates a new MP3::Daemon.

          my $mp3d = MP3::Daemon->new("$ENV{HOME}/.mp3/mp3_socket");

main
     This starts the event loop.  This will be listening to the socket for
     client requests while polling mpg123 in times of idleness.  This
     method will never return.

          $mp3d->main;

spawn $socket_path
     This combines new() and `main()' while also forking itself into the
     background.  The spawn method will return immediately to the parent
     process while the child process becomes an MP3::Daemon that is
     waiting for client requests.

          MP3::Daemon->spawn("$ENV{HOME}/.mp3/mp3_socket");

client $socket_path
     This is a factory method for use by clients who want a socket to
     communicate with a previously instantiated MP3::Daemon.

          my $client = MP3::Daemon->client("$ENV{HOME}/.mp3/mp3_socket");

Client API
----------

   These methods are usually not invoked directly.  They are invoked when
a client makes a request.  The protocol is very simple.  The first line is
the name of the method.  Each argument to the method is specified on
successive lines.  A final blank line signifies the end of the request.

     0   method name
     1   $arg[0]
     .   ...
     n-1 $arg[n-2]
     n   /^$/

   Example:

     print $client <<REQUEST;
     play
     5

     REQUEST

   This plays $self->{playlist}[5].

SUBCLASSES
==========

   When writing a subclass of MP3::Daemon keep the following in mind.

Writing the constructor
     The new() method provided by MP3::Daemon returns a blessed hash.
     Feel free to add more attributes to the blessed hash as long as you
     don't accidentally stomp on the following keys.

    player
          This is an instance of Audio::Play::MPG123.

    server
          This is an instance of IO::Socket::UNIX.

    client
          This is another instance of IO::Socket::UNIX that the daemon may
          write to in order to reply to a client.

    socket_path
          This is where in the filesystem the unix domain socket is
          sitting.

You must implement a next() method.
     The event loop in &MP3::Daemon::main relies on it.  When a song ends,
     it will execute $self->next.

Only methods prefixed with "_" will be available to clients.
     This was to prevent mischievous clients from trying to execute methods
     like new(), spawn() or main().  That would have been evil.  By only
     allowing methods with names matching /^_/ to be executed, this allows
     the author of a daemon to control what the client can and can't
     request the daemon to do.

     When a client makes a request, the following sequence happens in the
     event loop.

          my @args = $self->readCommand;
          my $do_this = "_" . shift(@args);
          if ($self->can($do_this)) { ... }

     If a client requested the daemon to "play", the event loop will ask
     itself `if ($self->can('_play'))' before taking any action.

Letting us know
     If you write a subclass of MP3::Daemon, we (pip and beppu) would be
     happy to hear from you.

DIAGNOSTICS
===========

   I need to be able to report errors in the daemon better.  They
currently go to /dev/null.  I need to learn how to use syslog.

COPYLEFT
========

   Copyleft (!c) 2001 John BEPPU.  All rights reversed.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

AUTHOR
======

   John BEPPU <beppu@binq.org>

SEE ALSO
========

   mpg123(1), Audio::Play::MPG123(3pm), pimp(1p), mpg123sh(1p), mp3(1p)

the daemon for Pip's Intergallactive Moosex Plaquluster
*******************************************************

NAME
====

   MP3::Daemon::PIMP - the daemon for Pip's Intergallactive Moosex
Plaquluster

SYNOPSIS
========

   Fork a daemon

     MP3::Daemon::PIMP->spawn($socket_path);

   Start a server, but don't fork into background

     my $mp3d = MP3::Daemon::PIMP->new($socket_path);
     $mp3d->main;

   You're a client wanting a socket to talk to the daemon

     my $client = MP3::Daemon::PIMP->client($socket_path);
     print $client @command;

REQUIRES
========

MP3::Daemon
     This is the base class.  It provides the daemonization and event loop.

DESCRIPTION
===========

   MP3::Daemon::PIMP provides a server that controls mpg123.  Clients such
as mp3(1p) may connect to it and request the server to manipulate its
internal playlists.

METHODS
=======

Server-related Methods
----------------------

   MP3::Daemon::PIMP relies on unix domain sockets to communicate.  The
socket requires a place in the file system which is referred to as
`$socket_path' in the following descriptions.

new $socket_path
     This instantiates a new MP3::Daemon::PIMP.

          my $mp3d = MP3::Daemon::PIMP->new("$ENV{HOME}/.mp3/mp3_socket");

main
     This starts the event loop.  This will be listening to the socket for
     client requests while polling mpg123 in times of idleness.  This
     method will never return.

          $mp3d->main;

spawn $socket_path
     This combines new() and `main()' while also forking itself into the
     background.  The spawn method will return immediately to the parent
     process while the child process becomes an MP3::Daemon::PIMP that is
     waiting for client requests.

          MP3::Daemon::PIMP->spawn("$ENV{HOME}/.mp3/mp3_socket");

client $socket_path
     This is a factory method for use by clients who want a socket to
     communicate with a previously instantiated MP3::Daemon::PIMP.

          my $client = MP3::Daemon::PIMP->client("$ENV{HOME}/.mp3/mp3_socket");

Client API
----------

   These methods are usually not invoked directly.  They are invoked when
a client makes a request.  The protocol is very simple.  The first line is
the name of the method.  Each argument to the method is specified on
successive lines.  A final blank line signifies the end of the request.

     0   method name
     1   $arg[0]
     .   ...
     n-1 $arg[n-2]
     n   /^$/

   Example:

     print $client <<REQUEST;
     play
     5

     REQUEST

   This plays $self->{playlist}[5].

command
command
COPYLEFT
========

   Copyleft (c) 2001 pip.  All rights reversed.  This program is free
software; you can redistribute it and/or modify it under the same terms as
Perl itself.

AUTHOR
======

   pip <pip@binq.org>

SEE ALSO
========

   mpg123(1), Audio::Play::MPG123(3pm), pimp(1p), mpg123sh(1p), mp3(1p)

the daemon for the mp3(1p) client
*********************************

NAME
====

   MP3::Daemon::Simple - the daemon for the mp3(1p) client

SYNOPSIS
========

   Fork a daemon

     MP3::Daemon::Simple->spawn($socket_path);

   Start a server, but don't fork into background

     my $mp3d = MP3::Daemon::Simple->new($socket_path);
     $mp3d->main;

   You're a client wanting a socket to talk to the daemon

     my $client = MP3::Daemon::Simple->client($socket_path);
     print $client @command;

REQUIRES
========

File::Basename
     This is used to give titles to songs when the mp3 leaves the title
     undefined.

Getopt::Std
     Some methods need to pretend they're command line utilities.

MP3::Daemon
     This is the base class.  It provides the daemonization and event loop.

MP3::Info
     This is for getting information out of mp3s.

DESCRIPTION
===========

   MP3::Daemon::Simple provides a server that controls mpg123.  Clients
such as mp3(1p) may connect to it and request the server to manipulate its
internal playlists.

METHODS
=======

Server-related Methods
----------------------

   MP3::Daemon::Simple relies on unix domain sockets to communicate.  The
socket requires a place in the file system which is referred to as
`$socket_path' in the following descriptions.

     $socket_path = "$ENV{HOME}/.mp3/mp3_socket";

new $socket_path
     This instantiates a new MP3::Daemon::Simple.

          my $mp3d = MP3::Daemon::Simple->new($socket_path);

main
     This starts the event loop.  This will be listening to the socket for
     client requests while polling mpg123 in times of idleness.  This
     method will never return.

          $mp3d->main;

spawn $socket_path
     This combines new() and `main()' while also forking itself into the
     background.  The spawn method will return immediately to the parent
     process while the child process becomes an MP3::Daemon::Simple that is
     waiting for client requests.

          MP3::Daemon::Simple->spawn($socket_path);

client $socket_path
     This is a factory method for use by clients who want a socket to
     communicate with a previously instantiated MP3::Daemon::Simple.

          my $client = MP3::Daemon::Simple->client($socket_path);

Client API
----------

   These methods are usually not invoked directly.  They are invoked when
a client makes a request.  The protocol is very simple.  The first line is
the name of the method.  Each argument to the method is specified on
successive lines.  A final blank line signifies the end of the request.

     0   method name
     1   $arg[0]
     .   ...
     n-1 $arg[n-2]
     n   /^$/

   Example:

     print $client <<REQUEST;
     play
     5

     REQUEST

   This plays $self->{playlist}[5].

add
     This adds mp3s to the playlist.  Multiple files may be specified.

del
     This deletes items from the playlist by index.  More than one index
     may be specified.  If no index is specified, the current mp3 in the
     playlist is removed.  Indices may also be negative in which case they
     count from the end of the playlist.

play
     This plays the current mp3 if no other parameters are given.  This
     command also takes an optional parameter where the index of an mp3 in
     the playlist may be given.

next
     This loads the next mp3 in the playlist.

prev
     This loads the previous mp3 in the playlist.

pause
     This pauses the currently playing mp3.  If the mp3 was already
     paused, this will unpause it.  Note that using the play command on a
     paused mp3 makes it start over from the beginning.

rw
     This rewinds an mp3 by the specified amount of seconds.

ff
     This fastforwards an mp3 by the specified amount of seconds.

jump
     This will go directly to a part of an mp3 specified by seconds from
     the beginning of the track.  If the number of seconds is prefixed
     with either a "-" or a "+", a relative jump will be made.  This is
     another way to rewind or fastforward.

stop
     This stops the player.

time
     This sends back the index of the current track, the amount of time
     that has elapsed, the amount of time that is left, and the total
     amount of time.  All times are reported in seconds.

info
     This sends back information about the current track.

ls [-fl] [REGEX]
     First, a warning - I'm beginning to realize how GNU/ls became so
     bloated.  The ls interface should not be considered stable.  I'm
     still playing with it.

     This sends back a list of the titles of all mp3s currently in the
     playlist.  The current track is denoted by a line matching the regexp
     /^>/.

    -f
          This makes ls return a listing with index and filename.

    -l
          This makes ls return a long listing that includes index, title,
          and filename.

    [REGEX]
          This allows one to filter the playlist for only titles matching
          this regex.  Of course, one may use grep, instead.

quit
     This unloads the MP3::Daemon::Simple that was automagically spawned
     when you first invoked mp3.

DIAGNOSTICS
===========

   I need to be able to report errors in the daemon better.  They
currently go to /dev/null.  I need to learn how to use syslog.

COPYLEFT
========

   Copyleft (c) 2001 John BEPPU.  All rights reversed.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

AUTHOR
======

   John BEPPU <beppu@binq.org>

SEE ALSO
========

   mpg123(1), Audio::Play::MPG123(3pm), pimp(1p), mpg123sh(1p), mp3(1p)

Edit ID3v1 Tags from an Audio MPEG Layer 3.
*******************************************

NAME
====

   MP3::ID3v1Tag - Edit ID3v1 Tags from an Audio MPEG Layer 3.

SYNOPSIS
========

     use MP3::ID3v1Tag;

     $mp3_file = new MP3::ID3v1Tag("filename.mp3");
     $mp3_file->print_tag();

     if($mp3_file->got_tag()) {
        $mp3_file->set_title($title);
        $save_status = $mp3_file->save();
     }

DESCRIPTION
===========

   The ID3v1Tag routines are useful for setting and reading ID3 MP3 Audio
Tags.  Just create an MP3::ID3v1Tag Object with the path to the file of
interest, and query any of the methods below.

Print Full ID3 Tag
------------------

   To get a print out of all the header information (Default FileHandler),
simply state the following

   $mp3_file->print_tag();

Print Genre Chart
-----------------

   With an optional number of columns argument (default is 3) this will
return a list of genre numbers with their appropriate genre.

   $mp3_file->print_genre_chart($COLUMNS);

Checking for the Existance of ID3 Tags
--------------------------------------

   There is a handy method named got_tag() that can be easily used to
determine if a particular MP3 file contains an ID3 Tag.

     if $mp3_file->got_tag() {
        $mp3_file->print_tag();
     }

Viewing Tag Compontents individually
------------------------------------

   There exist several methods that will return you the individual
components of the ID3 Tag.

     $title     = $mp3_file->get_title();
     $artist    = $mp3_file->get_artist();
     $album     = $mp3_file->get_album();
     $year      = $mp3_file->get_year();
     $genre     = $mp3_file->get_genre();
     $genre_num = $mp3_file->get_genre_num();
     $comment   = $mp3_file->get_comment();

Editing and Removing Tags
-------------------------

   Similar methods exist to allow you to change the components of the Tag,
but none of the changes will actually be changed in the file until you
call the save() routine.

     $mp3_file->set_title("New Title");
     $mp3_file->set_artist("New Artist");
     $mp3_file->set_album("New Album");
     $mp3_file->set_year(1999);
     $mp3_file->set_genre("Blues");
     # Or use the genre numbers ->
     $mp3_file->set_genre_num(0);

   To remove an tag in its entirely just calling the remove_tag() method
should work for you.

     $mp3_file->remove_tag() if $mp3_file->got_tag();

     You could access all the components directly for a read only loop such
     as the following

   foreach (sort $mp3_file->tag) {     print "$_: " . $mp3_file->tag($_) .
"\n"; }

AUTHOR
======

   Sander van Zoest <svanzoest@cpan.org>

THANKS
======

   Matt Plummer <matt@mp3.com>, Mike Oliphant <oliphant@gtk.org>, Matt
DiMeo <mattd@mp3.com>, Olaf Maetzner, Jason Bodnar and Peter Johansson

COPYRIGHT
=========

   Copyright 2000, Alexander van Zoest. All rights reserved.  Copyright
1999-2000, Alexander van Zoest, MP3.com, Inc. All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

REFERENCES
==========

   For general overview of MPEG 1.0, Layer 3 (MP3) Audio visit
<http://help.mp3.com/help/gettingstarted/guide.html> or get the book,
"MP3: The Definitive Guide" by O'Reilly and Associates
<http://www.oreilly.com/catalog/mp3/>.

   For technical details about MP3 Audio read the ISO/IEC 11172 and
ISO/IEC 13818 specifications, obtained via <http://www.ANSI.org/> in the
US or <http://www.ISO.ch/> elsewhere in the world. For more information
also check out <http://www.mp3-tech.org/> compiled by Gabriel Bouvigne.

   For more specific references to the MP3 Audio ID3 Tags visit
<http://www.id3.org/>

   For information about ID3v2 and a perl implementation see MPEG::ID3v2Tag
written by Matt DiMeo <mattd@mp3.com>.

Data - GetFrame() Data Format
*****************************

NAME
====

   MP3::Tag::ID3v2-Data - GetFrame() Data Format

DESCRIPTION
===========

   This document describes how to use the results of the GetFrame function
of MP3::Tag::ID3v2, thus the data format of frames retrieved with
MP3::Tag::ID3v2::GetFrame().

Calling GetFrame()
------------------

   You have to call GetFrame() like this:

   ($info, $long) = GetFrame($id);    # or

   ($info, $long) = GetFrame($id, 'raw');

   $id has to be a name of a frame like "APIC". The names of all frames
found in a tag can be retrieved with the `GetFrameIDs()|MP3::Tag::ID3v2'
in this node function.

Using the returned data
-----------------------

   In the ID3v2.3 specifications -1 frames are defined, which can contain
very different information. That means also that GetFrame returns the
information found in a frame in different ways.

Simple Frames
     A lot of the tags contain only a text string and encoding
     information. If you call ($info, $long) = GetFrame($id) for such a
     frame, $info will contain the text string and $long will contain the
     english name of the frame.

     Example:   getFrame("TIT2");     # returns

          ("Birdhouse In Your Soul", "Title/songname/content description")

Complex Frames
     For more complex frames the returned $info is a reference to a hash,
     where each entry of the hash decribes a part of the information found
     in the frame. The key of a hash entry contains the name of this part,
     the according value contains the information itself.

     Example:   getFrame("APIC");     # returns

     ( { "Description" => "Flood",       "MIME Type" => "/image/jpeg",
      "Picture Type" => "Cover (front)",       "_Data" => "..data of jpeg
     picture (binary).."       },    "Attached Picture");

Other Frames
     Some frames are not supported at the moment, ie the data found in the
     frame is not returned in a descriptive way. But you can read the data
     of this frames (and also of all other frames too) in raw mode. Then
     the complete data field of the frame is returned, without any
     modifications. This means that the returned data will be almost
     binary data.

     Example:   getFrame("TIT2", 'raw');    # returns

          ("\x00Birdhouse In Your Soul", "Title/songname/content description")

List of Simple Frames
---------------------

   Following Frames are supported and return a single string (text). In
the List you can find the frame IDs and the long names of the frames as
returned by GetFrame():

IPLS : Involved people list
MCDI : Music CD identifier
PCNT : Play counter
TALB : Album/Movie/Show title
TBPM : BPM (beats per minute)
TCOM : Composer
TCON : Content type
TCOP : Copyright message
TDAT : Date
TDLY : Playlist delay
TENC : Encoded by
TEXT : Lyricist/Text writer
TFLT : File type
TIME : Time

TIT1 : Content group description

TIT2 : Title/songname/content description

TIT3 : Subtitle/Description refinement
TKEY : Initial key
TLAN : Language(s)
TLEN : Length
TMED : Media type
TOAL : Original album/movie/show title
TOFN : Original filename
TOLY : Original lyricist(s)/text writer(s)
TOPE : Original artist(s)/performer(s)
TORY : Original release year
TOWN : File owner/licensee

TPE1 : Lead performer(s)/Soloist(s)

TPE2 : Band/orchestra/accompaniment

TPE3 : Conductor/performer refinement

TPE4 : Interpreted, remixed, or otherwise modified by
TPOS : Part of a set
TPUB : Publisher
TRCK : Track number/Position in set
TRDA : Recording dates
TRSN : Internet radio station name
TRSO : Internet radio station owner
TSIZ : Size
TSRC : ISRC (international standard recording code)
TSSE : Software/Hardware and settings used for encoding
TYER : Year
WCOM : Commercial information
WCOP : Copyright/Legal information
WOAF : Official audio file webpage
WOAR : Official artist/performer webpage
WOAS : Official audio source webpage
WORS : Official internet radio station homepage
WPAY : Payment
WPUB : Publishers official webpage
List of Complex Frames
----------------------

   Following frames are supported and return a reference to a hash. The
list shows which keys can be found in the returned hash:

AENC : Audio encryption
          Keys: URL, Preview start, Preview length

APIC : Attached picture
          Keys: MIME type, Picture Type, Description, _Data

COMM : Comments
          Keys: Language, short, Text

COMR : Commercial frame
          Keys: Price, Valid until, URL, Received as, Name of Seller, Description, MIME type, _Logo

ENCR : Encryption method registration
          Keys: Owner ID, Method symbol, _Data

GEOB : General encapsulated object
          Keys: MIME type, Filename, Description, _Data

GRID : Group identification registration
          Keys: Owner, Symbol, _Data

LINK : Linked information
          Keys: _ID, URL, Text

OWNE : Ownership frame
          Keys: Price payed, Date of purchase, Text

POPM : Popularimeter
          Keys: URL, Rating, _Data

PRIV : Private frame
          Keys: Text, _Data

RBUF : Recommended buffer size
          Keys: Buffer size, Embedded info flag, Offset to next tag

RVRB : Reverb
          Keys: Reverb left (ms), Reverb right (ms), Reverb bounces (left), Reverb bounces (right), Reverb feedback (left to left), Reverb feedback (left to right), Reverb feedback (right to right), Reverb feedback (right to left), Premix left to right, Premix right to left

SYTC : Synchronized tempo codes
          Keys: Time Stamp Format, _Data

TXXX : User defined text information frame
          Keys: Description, Text

UFID : Unique file identifier
          Keys: Text, _Data

USER : Terms of use
          Keys: Language, Text

USLT : Unsychronized lyric/text transcription
          Keys: Language, Description, Text

WXXX : User defined URL link frame
          Keys: Description, URL

List of Other Frames
--------------------

   Following frames are only supported in raw mode:

EQUA : Equalization
ETCO : Event timing codes
MLLT : MPEG location lookup table
POSS : Position synchronisation frame
RVAD : Relative volume adjustment
SYLT : Synchronized lyric/text
SEE ALSO
========

   See MP3/Tag, MP3/Tag/ID3v2,

Manipulate / fetch info from MP3 audio files
********************************************

NAME
====

   MP3::Info - Manipulate / fetch info from MP3 audio files

SYNOPSIS
========

     #!perl -w
     use MP3::Info;
     my $file = 'Pearls_Before_Swine.mp3';
     set_mp3tag($file, 'Pearls Before Swine', q"77's",
     	'Sticks and Stones', '1990',
     	q"(c) 1990 77's LTD.", 'rock & roll');

     my $tag = get_mp3tag($file) or die "No TAG info";
     $tag->{GENRE} = 'rock';
     set_mp3tag($file, $tag);

     my $info = get_mp3info($file);
     printf "$file length is %d:%d\n", $info->{MM}, $info->{SS};

     my $mp3 = new MP3::Info $file;
     printf "$file length is %s, title is %s\n",
     	$mp3->time, $mp3->title;

DESCRIPTION
===========

use_winamp_genres()
     Puts WinAmp genres into `@mp3_genres' and `%mp3_genres' (adds 68
     additional genres to the default list of 80).  This is a separate
     function because these are non-standard genres, but they are included
     because they are widely used.

     You can import the data structures with one of:

          use MP3::Info qw(:genres);
          use MP3::Info qw(:DEFAULT :genres);
          use MP3::Info qw(:all);

remove_mp3tag (FILE [, VERSION, BUFFER])
     Can remove ID3v1 or ID3v2 tags.  VERSION should be 1 for ID3v1, 2 for
     ID3v2, and ALL for both.

     For ID3v1, removes last 128 bytes from file if those last 128 bytes
     begin with the text 'TAG'.  File will be 128 bytes shorter.

     For ID3v2, removes ID3v2 tag.  Because an ID3v2 tag is at the
     beginning of the file, we rewrite the file after removing the tag
     data.  The buffer for rewriting the file is 4MB.  BUFFER (in bytes) ca
     change the buffer size.

     Returns the number of bytes removed, or -1 if no tag removed, or
     undef if there is an error.

set_mp3tag (FILE, TITLE, ARTIST, ALBUM, YEAR, COMMENT, GENRE [, TRACKNUM])

set_mp3tag (FILE, $HASHREF)
     Adds/changes tag information in an MP3 audio file.  Will clobber any
     existing information in file.

     Fields are TITLE, ARTIST, ALBUM, YEAR, COMMENT, GENRE.  All fields
     have a 30-byte limit, except for YEAR, which has a four-byte limit,
     and GENRE, which is one byte in the file.  The GENRE passed in the
     function is a case-insensitive text string representing a genre found
     in `@mp3_genres'.

     Will accept either a list of values, or a hashref of the type
     returned by get_mp3tag.

     If TRACKNUM is present (for ID3v1.1), then the COMMENT field can only
     be 28 bytes.

     ID3v2 support may come eventually.

get_mp3tag (FILE [, VERSION, RAW_V2])
     Returns hash reference containing tag information in MP3 file.  Same
     info as described in set_mp3tag.

     If VERSION is 1, the information is taken from the ID3v1 tag (if
     present).  If VERSION is 2, the information is taken from the ID3v2
     tag (if present).  If VERSION is not supplied, the ID3v1 tag is read
     if present, and then, if present, the ID3v2 tag information will
     override any existing ID3v1 tag info.

     If the ID3v2 version is older than ID3v2.2.0, it will not be read (and
     a warning will be issued if -w is on).

     If RAW_V2 is false or not supplied and VERSION is 2, only the tags
     corresponding to ID3v1 tags are returned, with the same keys in the
     returned hashref.

     If RAW_V2 is true and VERSION is 2, get_mp3tag will return a hash of
     tag four-character IDs and their data.  Tag IDs and their meanings
     are in the global hash (not exported) `%v2_tag_names'.

          my $tag = get_mp3tag('mysong.mp3', 2, 1);   # ID3v2, raw ID3v2 tags
          for (keys %$tag) {
          	printf "%s => %s\n", $MP3::Info::v2_tag_names{$_}, $tag->{$_};
          }

get_mp3info (FILE)
     Returns hash reference containing file information for MP3 file.
     This data cannot be changed.  Returned data:

          VERSION		MPEG audio version (1, 2, 2.5)
          LAYER		MPEG layer description (1, 2, 3)
          STEREO		boolean for audio is in stereo

          VBR		boolean for variable bitrate
          BITRATE		bitrate in kbps (average for VBR files)
          FREQUENCY	frequency in kHz
          SIZE		bytes in audio stream

          SECS		total seconds
          MM		minutes
          SS		leftover seconds
          MS		leftover milliseconds
          TIME		time in MM:SS

          COPYRIGHT	boolean for audio is copyrighted
          PADDING		boolean for MP3 frames are padded
          MODE		channel mode (0 = stereo, 1 = joint stereo,
          		2 = dual channel, 3 = single channel)
          FRAMES		approximate number of frames
          FRAME_LENGTH	approximate length of a frame
          VBR_SCALE	VBR scale from VBR header

TROUBLESHOOTING
===============

   If you find a bug, please send me a patch.  If you cannot figure out
why it does not work for you, please put the MP3 file in a place where I
can get it (preferably via FTP) and send me mail regarding where I can get
the file, with a detailed description of the problem.

   If I download the file, after debugging the problem I will not keep the
MP3 file if it is not legal for me to have it.  Just let me know if it is
legal for me ot keep it or not.

TODO
====

ID3v2 Support
     First go at adding support for reading ID3v2 tags.  Still need to do
     more, such as using Compress::Zlib to decompress compressed tags.
     But until I see this in use more, I won't bother.  I might not be able
     to support Unicode at all, until Perl supports 16-bit Unicode.  If
     something does not work properly with reading, follow the
     instructions above for troubleshooting.

     I think I might just use Matt DiMeo's MPEG::ID3v2Tag; the problem is
     that right now it requires 5.005, and MacPerl uses 5.004 (for now).

Get data from scalar
     Instead of passing a file spec or filehandle, pass the data itself.
     Would take some work, converting the seeks, etc.

Padding bit ?
     Do something with padding bit.

ID3v2.4.0
     It's the new standard.  There are no specific plans to update to
     2.4.0.  I'd like it to be done, but there is no pressing need, and I
     don't really have the time right now.  Patches welcome!  :-)

Test suite
     Test suite could use a bit of an overhaul and update.

HISTORY
=======

v0.91, Saturday, February 10, 2001
     Fix dumb bug with /o. (David Reuteler)

     Fix bug where get_mp3tag would return an empty hashref instead of
     undef if ID3v1 tag is asked for, and there is no ID3v1 tag, but there
     is an ID3v2 tag.  (Stuart)

v0.90, Sunday, January 14, 2001
     Added experimental OOP support for getting and setting data; doesn't
     work for removing tags.

     Made all functions optionally accept filehandle in place of filename.

     Remove all croaks/dies and replace with simple returns or carps/warns.
     (Jeffrey Sumler)

     Fix various input data problems, bad warnings, division by zero, etc.

     Undef $/ in set_mp3tag() so caller can't mess up the print.

     Fix bitrate if ID == 0 and VBR.  (Kyle Farrell, Per Bolmstedt)

     Split off _get_info() from get_mp3info(), so, eventually, programmers
     can access that functionality without passing in a file or filehandle.
     Not supported yet, but available for playing.

     Added total frames, leftover milliseconds, and formatted time.

     Fixed sample frequency for MPEG 2.5 files (perhaps not including VBR,
     though ... see bug above).

     Add in some additional genres.  (Peter Marschall)

     Added ID3v2 tag removal. (Ronan Waide)  NOTE: this is DANGEROUS.  It
     is tested, but needs more testing.  The file is rewritten entirely.
     Lots of data moving around.

     Added ID3v2.2.0 tag reading. (Ronan Waide, Kee Hinckley)

     Changed ID3v2 tag recognition to only match [A-Z0-9] instead of \w.
     (Christoph Oberauer)

v0.80, Monday, March 6, 2000
     Better stripping of bad data (after nulls) in ID3 tags (Dave O'Neill)

     Fixed VERSION in get_mp3info to properly return 2 when appropriate.
     (Bogdan Surdu)

     Added VBR support.  Average bitrate is returned as BITRATE, and
     minutes and seconds (MM and SS) should be accurate.  (Andy Waite for
     pointer to MP3Ext)

     Made time calculation better overall.

     Made MP3 header validation routines more comprehensive.  (Matthew
     Sachs for pointer to xmms source)

     Changed name to MP3::Info (with wrapper still named MP3::Info).

v0.71, Thursday, July 8, 1999
     Several fixes to ID3v2 support unpack unsigned instead of signed,
     don't bail out after 4096-byte offsets on long ID3v2 headers.  Thanks
     much to Matthew Sachs.

v0.70, Saturday, July 3, 1999
     Added preliminary ID3v2 reading support in get_mp3tag.  Thanks much
     to Tom Brown.

v0.64, Thursday, July 1, 1999
     Found bug in checking TRACKNUM parameter, used \d instead of \d+.
     Only gives spurious warnings, doesn't affect anything else.

     Cleaned up a bit, prepare for impending ID3v2 support.

     NOTE: truncate() broken in some builds of ActivePerl (517, maybe
     others).  No changes to module to fix problem.  (Brian Goodwin)

v0.63, Friday, April 30, 1999
     Added ID3v1.1 support. (Trond Michelsen, Pass F. B. Travis)

     Added 255 (\xFF) as default genre. (Andrew Phillips)

     I think I fixed bug relating to spaces in ID3v2 headers. (Tom Brown)

v0.62, Sunday, March 7, 1999
     Doc updates.

     Fix small unnoticable bug where ID3v2 offset is tag size plus 10, not
     just tag size.

     Not publickly released.

v0.61, Monday, March 1, 1999
     Fixed problem of not removing nulls on return from get_mp3tag (was
     using spaces for padding before ... now trailing whitespace and all
     nulls are removed before returning tag info).

     Made tests more extensive (more for my own sanity when making all
     these changes than to make sure it works on other platforms and
     machines :).

v0.60, Sunday, February 28, 1999
     Cleaned up a lot of stuff, added more comments, made get_mp3info much
     faster and much more reliable, and added recognition of ID3v2
     headers.  (Tom Brown)

v0.52, Sunday, February 21, 1999
     Fixed problem in get_mp3tag that changed value of $_ in caller (Todd
     Hanneken).

v0.51, Saturday, February 20, 1999
     Fixed problem with `%winamp_genres' having the wrong numbers (Matthew
     Sachs).

v0.50, Friday, February 19, 1999
     Added remove_mp3tag.  Addeed VERSION to the hash returned by
     get_mp3info, and fixed a bug where STEREO was not being set correctly.

     Export all genre data structures on request.  Added
     `use_winamp_genres' to use WinAmp genres. (Roland Steinbach)

     Added a `$MPEG::MP3Info::try_harder' (`$MP3::Info::try_harder')
     variable that will try harder to find the MP3 header in a file.
     False by default.  Can take a long time to fail, but should find most
     headers at any offsets if set to true.

     Thanks to Matthew Sachs for his input and fixes, and for mp3tools.

v0.20, Saturday, October 17, 1998
     Changed name from `MPEG::MP3Tag' to `MPEG::MP3Info', because it does
     more than just TAG stuff now.

     Made header stuff even more reliable.  Lots of help and testing from
     Meng Weng Wong again.  :-)

v0.13, Thursday, October 8, 1998
     Had some problems with header verification, got some code from
     Predrag Supurovic with his mpgtools.  Great stuff.  Also did some
     looping to find a header if it is not in the "right" place.  I did
     what I think it is a smart way to do it, since some files have the
     header as far down as 2 kbytes into the file.  First, I look at
     position 0, then at position 36 (a position where I have found many
     headers), then I start at 0 again and jump in 128-byte chunks.  Once
     I do that a bunch of times, I go back at the beginning and try at 0
     and go ahead in 1-byte chunks for a bunch more times.

     If you have an MP3 that has the header begin at an odd place like byte
     761, then I suggest you strip out the junk before the header begins.
     :-)

v0.12, Friday, October 2, 1998
     Added get_mp3info.  Thanks again to mp3tool source from Johann
     Lindvall, because I basically stole it straight (after converting it
     from C to Perl, of course).

     I did everything I could to find the header info, but if anyone has
     valid MP3 files that are not recognized, or has suggestions for
     improvement of the algorithms, let me know.

v0.04, Tuesday, September 29, 1998
     Changed a few things, replaced a regex with an unpack.  (Meng Weng
     Wong)

v0.03, Tuesday, September 8, 1998
     First public release.

THANKS
======

   Edward Allen <allenej@c51844-a.spokn1.wa.home.com>, Vittorio Bertola
<v.bertola@vitaminic.com>, Michael Blakeley <mike@blakeley.com>, Per
Bolmstedt <tomten@kol14.com>, Tony Bowden <tony@tmtm.com>, Tom Brown
<thecap@usa.net>, Sergio Camarena <scamarena@users.sourceforge.net>, Chris
Dawson <cdawson@webiphany.com>, Luke Drumm <lukedrumm@mypad.com>, Kyle
Farrell <kyle@cantametrix.com>, Brian Goodwin <brian@fuddmain.com>, Todd
Hanneken <thanneken@hds.harvard.edu>, Kee Hinckley <nazgul@somewhere.com>,
Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>, Peter Kovacs
<kovacsp@egr.uri.edu>, Johann Lindvall, Peter Marschall
<peter.marschall@mayn.de>, Trond Michelsen <mike@crusaders.no>, Dave
O'Neill <dave@nexus.carleton.ca>, Christoph Oberauer
<christoph.oberauer@sbg.ac.at>, Andrew Phillips <asp@wasteland.org>, David
Reuteler <reuteler@visi.com>, Matthew Sachs <matthewg@zevils.com>, Hermann
Schwaerzler <Hermann.Schwaerzler@uibk.ac.at>, Chris Sidi
<sidi@angband.org>, Roland Steinbach <roland@support-system.com>, Stuart
<schneis@users.sourceforge.net>, Jeffery Sumler <jsumler@mediaone.net>,
Predrag Supurovic <mpgtools@dv.co.yu>, Bogdan Surdu <tim@go.ro>, Pass F.
B. Travis <pftravis@bellsouth.net>, Tobias Wagener <tobias@wagener.nu>,
Ronan Waide <waider@stepstone.ie>, Andy Waite <andy@mailroute.com>, Ken
Williams <ken@forum.swarthmore.edu>, Meng Weng Wong <mengwong@pobox.com>.

AUTHOR AND COPYRIGHT
====================

   Chris Nandor <pudge@pobox.com>, http://pudge.net/

   Copyright (c) 1998-2001 Chris Nandor.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the terms of the Artistic License, distributed with Perl.

SEE ALSO
========

SourceForge Page
          http://sourceforge.net/projects/mp3-info/

mp3tools
          http://www.zevils.com/linux/mp3tools/

mpgtools
          http://www.dv.co.yu/mpgscript/mpgtools.htm
          http://www.dv.co.yu/mpgscript/mpeghdr.htm

mp3tool
          http://www.dtek.chalmers.se/~d2linjo/mp3/mp3tool.html

ID3v2
          http://www.id3.org/

Xing Variable Bitrate
          http://www.xingtech.com/support/partner_developer/mp3/vbr_sdk/

MP3Ext
          http://rupert.informatik.uni-stuttgart.de/~mutschml/MP3ext/

Xmms
          http://www.xmms.org/

VERSION
=======

   v0.91, Saturday, February 10, 2001

Perl interface to the Napster Server
************************************

NAME
====

   MP3::Napster - Perl interface to the Napster Server

SYNOPSIS
========

     use MP3::Napster;

     my $nap = MP3::Napster->new;

     # log in as "username" "password" using a T1 line
     $nap->login('username','password',LINK_T1) || die "Can't log in ",$nap->error;

     # listen for incoming transfer requests on port 6699
     $nap->port(6699) || die "can't listen: ",$nap->error;

     # set the download directory to "/tmp/songs"
     mkdir '/tmp/songs',0777;
     $nap->download_dir('/tmp/songs');

     # arrange for incomplete downloads to be unlinked
     $nap->callback(TRANSFER_DONE,
     	         sub { my ($nap,$code,$transf) = @_;
     		       return unless $transf->direction eq 'download';
     		       return if $transf->status eq 'transfer complete';
     		       warn "INCOMPLETE: ",$transf->song," (UNLINKING)\n";
     		       unlink $transf->local_path;
     		      } );

     # search for songs by the Beatles that are on a cable modem or better
     # and have a bitrate of at least 128 kbps
     my @songs = $nap->search(artist=>'beatles',linespeed=>LINK_CABLE,bitrate=>128);

     # initiate downloads on the first four songs
     my $count = 0;
     foreach my $s (@songs) {
       next if $seen_it{$s}++;
       next unless $s->owner->ping;
       next unless $s->download;  # try to initiate download
       print "Downloading $s, size = ",$s->size,"\n";
       last if ++$count >= 4;  # download no more than four
     }

     # disconnect after waiting for all pending transfers to finish
     $nap->wait_for_downloads;
     $nap->disconnect;

DESCRIPTION
===========

   MP3::Napster provides access to the Napster MP3 file search and
distribution protocol.  With it, you can connect to a Napster server,
exchange messages with users, search the database of MP3 sound files, and
either download selected MP3s to disk or pipe them to another program,
typically an MP3 player.

   The module can be used to write Napster robots to search and download
files automatically, or as the basis of an interactive client.

THEORY OF OPERATION
===================

   The Napster protocol is asynchronous, meaning that it is
event-oriented.  After connecting to a Napster server, your program will
begin receiving a stream of events which you are free to act on or ignore.
Examples of events include PUBLIC_MESSAGE, received when another user
sends a public message to a channel, and USER_JOINS, sent when a user
joins a channel.  You may install code subroutines called "callbacks" in
order to intercept and act on certain events.  Many events are also
handled internally by the module.  It is also possible to issue a command
to the Napster server and then wait up to a predetermined period of time
for a particular event or set of events to be returned.

   If you wish to build an interactive Napster client on top of this
module, you will need to install a series of callbacks to handle each of
the events that you wish to catch.  Once the callbacks are installed, you
will call the run() method in order to run MP3::Napster's event loop.
run() will not return until the connection between client and server is
finished.  To process line-oriented user commands during this time, you
can install a command-handling callback using the command_processor()
method.

   MP3::Napster has a Tk mode, for writing applications on top of the
graphical PerlTk module.  In this mode, Tk takes over MP3::Napster's
internal event loop, processing I/O from the server and peers, and
invoking your callbacks when appropriate.

   You don't need to worry about callbacks if you only intend to use the
module as a non-interactive robot.

   Because of its asynchronous operation MP3::Napster makes heavy use of
nonblocking I/O and Perl's IO::Select class.  IO::Select is standard in
Perl versions 5.00503 and higher.  Other prerequisites are Digest::MD5 and
MP3::Info (both needed to handle MP3 uploads).

   The Napster protocol has a peer-to-peer component.  During MP3 upload
and download operations between two users, one user's client will initiate
a connection to the other. In order for such a connection to succeed, at
least one of the clients must be listening for incoming connections on a
network port.  The MP3::Napster module can do this, either by listening on
a hard-coded port, or by selecting a free port automatically. If you are
behind a firewall and cannot make a port available for incoming
connections, MP3::Napster will be able to exchange files with
non-firewalled users, but not with those behind firewalls.

   For more information on the Napster protocol, see
opennap.sourceforge.net, or the file "napster.txt" which accompanies this
module.  This file contains a partial specification of the Napster
protocol, as reverse engineered by several Open Source developers.

BASIC OPERATION
===============

   This section describes the basic operation of the module.

Connecting, Disconnecting, and Retrieving Errors
------------------------------------------------

*$nap = MP3::Napster->new([$address])*
*$nap = MP3::Napster->new(@options)*
     The new() class method will attempt to establish a connection with a
     Napster server.  If you wish to establish a connection with a
     particular server, you may provide its address and port number in the
     following format: aa.bb.cc.dd:PPPP, where PPPP is the port number.
     You may use a hostnames rather than IP addresses if you prefer.

     If you do not provide an address, MP3::Napster will choose the "best"
     server by asking the "meta" Napster master server located at
     server.napster.com:8875.  Note that there are several Napster servers,
     and that a user logged into one server will not be visible to you if
     you are logged into a different one.

     If successful, new() return an MP3::Napster object.  Otherwise it will
     return undef and leave an error message in $@ and in
     MP3::Napster->error.

     The module also provides a long form of the new() method which takes a
     series of option/value pairs.  Options and their defaults are:

          Option    Description                   Default

          -server   Server in form addr:port      undef
          -meta     Metaserver in form addr:port  server.napster.com:8875
          -tkmain   TK main widget                undef

     The *-server* argument has the same meaning as in the single-argument
     form of new().  *-meta* allows you to specify an alternative address
     for the Napster meta server.  *-tkmain* provides a hook into the
     Perl-Tk event handling, as described below under `"Using MP3::Napster
     with PerlTk"' in this node.  For example, to connect to the BitchX
     server and use the Tk event handling system:

          use Tk;
          use MP3::Napster;
          $main = MainWindow->new;
          $nap  = MP3::Napster->new(-server => 'bitchx.dimension6.com:8888',
                                    -tkmain => $main);

*$nap->disconnect([$wait])*
     The disconnect() object method will sever its connection with the
     Napster server and tidy up by cancelling any pending upload or
     download operations.

     By default, disconnect() will immediately abort all pending downloads
     and uploads.  If you wish your script to wait until they are done,
     call wait_for_downloads() first.

*$nap->wait_for_downloads*
     This method will block until all pending uploads and downloads are
     complete.  It first unshares all shared files, and refuses to service
     new upload requests.

     In the case of a slow or hung peer, wait_for_downloads() will wait
     until the transfer has timed out, ordinarily five minutes of complete
     inactivity.  See `"Waiting for Downloads"' in this node for details
     on how to alter this.

*$nap->run*
     Run the event loop, receiving and responding to events.  This
     operation will block until the connection is disconnected.
     Ordinarily, you will disconnect the connection within a callback.

*$nap->error*
     The error() method will return a human-readable string containing the
     last error message to be emitted by the server or generated internally
     by MP3::Napster.  You may clear the error message by setting it to an
     empty string this way:

          $nap->error('');

     If multiple errors occur in quick succession, error() will return only
     the most recent one.

Login and Registration
----------------------

   After establishing a connection with a Napster server, you must either
login as an existing user, or register as a new one.  The methods in this
section provide access to the login facilities.

*$email = $nap->login($nickname,$password [,LINK_SPEED] [,$port])*
     The login() method will attempt to log you in as a registered user
     under the indicated nickname and password.  You may optionally provide
     a link speed and a value describing the port on which the client will
     accept incoming connections.

     The link speed should be selected from the following list of exported
     constants:

          LINK_14K   LINK_64K    LINK_T1
          LINK_28K   LINK_128K   LINK_T3
          LINK_33K   LINK_CABLE  LINK_UNKNOWN
          LINK_56K   LINK_DSL

     The link speed will default to LINK_UNKNOWN if absent.  The indicated
     speed will be displayed to other users when they browse your list of
     shared files and user profile.

     The port many be any valid internet port number, normally an integer
     between 1024 and 65535.  The standard napster port is 6699, but you
     are free to use any valid port. If a port of 0 is specified, the
     module will identify your client to the server as being firewalled.
     The module will still be able to perform file transfers by making
     outgoing connections to other peers, but will not be able to exchange
     files with other firewalled peers.  If a port of -1 is specified, the
     module will pick an unused port automatically.  This is recommended
     for multiuser systems.

     If successful, login() will either return the email address you
     provided at registration time or the anonymous email address
     "anon@napster.com" if the account is not formally registered.
     Otherwise an undefined value will be returned and the error message
     left in $nap->error.  Typical errors include "no such user" and
     "invalid password".

     The nickname you logged in under is available as $nap->nickname.

*$email = $nap->register($nickname,$password,\%attributes)*
     The register() method will attempt to register you as a new user under
     the indicated nickname and password.  You may optionally provide
     register() with a hash reference containing one or more of the
     following keys:

          key        description
          ---        -----------
          link       Link speed, selected from among the LINK_* constants
          port       Preferred port for incoming connections
          email      Your e-mail address
          name       Your full name
          address    Your street address
          city       Your city
          state      Your state (two-letter abbreviation)
          phone	     Your phone number
          age	     Your age
          income     Your income level
          education  Your educational level

     Of these attributes only the link speed is relevant, since the others
     can either be automatically determined by the module, or may be
     considered intrusive by some people.  In addition, I have been unable
     to confirm that the demographic attributes actually "take," since the
     uploaded information is not made available to clients.

     If successful, the registration email address will be returned.
     Otherwise undef will be returned and $self->error will show the exact
     error message.  Typical error messages are "user already registered"
     and "invalid nickname."

*$result = $nap->change_registration(email=>$mail,password=>$pass,link=>$link)*
     Change_registration() allows you to change some fields in your
     registration record.  Pass it one or more of the keys "email",
     "password" or "link" to change the indicated attribute.

     There is no acknowledgement from the server, and therefore no positive
     way to confirm that the changes occurred.  Indeed, there seem to be
     synchronization problems among the Napster servers, so that a password
     change on one server may not take effect on others!  Therefore, use
     this method with care.

Sharing Files
-------------

   Once you have logged in, you may begin sharing files with other users.
If you choose not to do this, you may still download files and use other
features of the Napster server.

*$share = $nap->share('path/to/a/file.mp3' [,$cache])*
     The share() method will mark an MP3 file as shared with the community.
     The file may be specified using an absolute or relative path.
     However, it must be a bona fide MP3 file.  MP3::Napster will use
     MP3::Info to determine the file's bitrate, play length and other
     information, and upload this information to the Napster server.

     Rather than providing the Napster server with the file's full file
     pathname, MP3::Napster constructs a "share name" based on the file's
     IDv3 tag.  For example, the song "A Hard Day's Night" by the Beatles
     will be shared under the name:

          [The Beatles] A Hard Day's Night.mp3

     If the IDv3 tag is missing, the file is shared under its physical
     filename after stripping off the path information.

     If successful, the method returns an MP3::Napster::Song object, which
     when used in a string context returns its share name (see
     MP3/Napster/Song, for more details).  Otherwise the
     method returns undef and leaves the error message in $self->error.

     If you provide an optional $cache flag of true, then the IDv3 tag
     information will be cached in a directory named ".mpeg-nap" parallel
     to the downloaded file.  This avoids having to collect statistics on
     the file every time you share it.  This is recommended if you
     frequently share large numbers of files.  However, it requires that
     the directory containing the indicated file be writable and
     executable.

*@shares = $nap->share_dir('path/to/a/directory/' [,$cache])*
     This is like share() but instead of sharing a single file it shares
     the contents of a directory, and returns the list of
     MP3::Napster::Song objects shared in this way.  Currently, the module
     does not automatically monitor the directory and add to the list of
     shares when it is updated.

*$port = $nap->port([$port])*
     The port() method will set or change the port on which the client
     listens for incoming connections.  This method is called internally by
     login() and register() immediately after the client successfully logs
     into the server.  You may call the method at any time thereafter in
     order to change the port, or to disable incoming connections.

     You may hard-code a port to listen to and provide it as an argument to
     listen().  If you provide a negative port number, port() will select
     an unused high-numbered port and register it with the Napster server.
     This is recommended if you are on a machine that is shared by multiple
     users and there are no firewall issues that will limit the range of
     open ports.  The standard port used by the PC clients is 6699.

     Called with no arguments, this method returns the current port.

     Note that it is possible for a Napster server to tell the module to
     change its data port number.  Install a callback for the
     CHANGE_DATA_PORT event if you want to be notified when this happens.
     Set allow_setport() to a false value to prevent this from happening.

     If you are behind a firewall and cannot accept incoming connections,
     set the port to 0, or just accept the defaults.  This will inform the
     Napster server that you are firewalled.  Although you will not be able
     to exchange files with other firewalled users, you will be able to do
     so with non-firewalled users.

     If successful, port() returns the port that it is listening on.
     Otherwise it returns undef and leaves the error message in
     $nap->error.  Uploads requested by remote users will proceed
     automatically without other intervention.  You can receive
     notification of these uploads by installing callbacks for the
     TRANSFER_STARTED, TRANSFER_IN_PROGRESS and TRANSFER_DONE events or by
     interrogating the $nap->uploads() method (described below).

*$flag = $nap->allow_setport([$flag])*
     The Napster protocol allows the server to send the client
     SET_DATA_PORT commands, causing the module to change the port that it
     is listening on.  This may be a security hole, because it allows
     unscrupulous individuals to open arbitrary listening ports on your
     machine, so by default, the module ignores such requests.  To turn
     automatic handling of setport messages on, call allow_setport() with a
     true flag.

     Without any arguments, the method returns the current state of the
     flag.

     item *$song->unshare()*

     Given a Song object returned from share() or share_file(), unshare()
     will unregister the song, removing it from the search list at the
     server and disallowing further downloads.

Searching and Downloading Song Files
------------------------------------

   You may search the Napster sound file directory by keyword search, or
by browsing all the files shared by a named user.  The search functions
return a list of matching MP3::Napster::Song objects, each of which
contains such information about the song as its bitrate, its length, and
its sample frequency.  You can download a desired song either by invoking
its download() method directly (see MP3/Napster/Song)
or by passing the song to the MPEG::Napster object's
download() method.  Also see MP3/Napster/User, for
information on how to determine whether the owner of a song is still
online and reachable.

*@songs = $nap->browse($nickname)*
     The browse() method returns a list of the song files shared by a user.
     You may provide the user's nickname or a MP3::Napster::User object as
     the argument.  The method will return a list of songs shared by the
     user, or an empty list.  The empty list will be returned when the user
     is online but sharing no files as well as in such exceptional
     conditions as the user being offline or nonexistent.  You can
     distinguish between the two cases by checking $nap->error.

*@songs = $nap->search('keywords')*
*@songs = $nap->search(%attributes)*
     The first form of the search() method allows you to search for songs
     by words located in the artist's name or the song title.  For example,
     this will search for Bob Dylan's *Blowing in the Wind*:

          @songs = $nap->search('bob dylan blowing in the wind');

     For unknown reasons, lowercase searches are more effective than
     uppercase ones.  The result value is an array of matching songs, or an
     empty list if none were found.

     A more structured search can be made by providing search() with a hash
     of attribute/value pairs.  The available attributes are as follows:

          Attribute	   Value
          ---------	   -----
          artist	   The artist's name
          title		   The song title
          limit		   Limit the responses to the indicated number
          linespeed	   The link speed of the owner
          bitrate	   The bitrate of the song, in kbps
          frequency	   The sampling frequency of the song, in Hz

     The linespeed, bitrate and frequency fields can be specified in any
     of the following forms:

          Form                     Example
          ----                     -------
          1. a bare value          bitrate => 128
          2. "at least $value"     bitrate => 'at least 128'
          3. "at best $value"      bitrate => 'at best 64'
          4. "equal to $value"     frequency => 'equal to 44100'

     Using a bare value is the same as specifying "at least".

     In this example, we search for songs by Bob Dylan that have a bitrate
     of at least 160 kbps and are sampled at exactly 44.1 kHz:

          @songs = $nap->search(artist => 'Bob Dylan',
                                title  => 'Blowing in the Wind,
          			bitrate => 160,
          			frequency => 'equal to 44100');

     Due to server limitations, "artist" and "title" are interchangeable,
     and "limit" doesn't seem to do anything.  Search results are limited
     to 100 songs at the server's end of the connection.  No facility is
     provided for searching on a song's size or play length.

*$path = $nap->download_dir( [$path] )*
     The download_dir() gets or sets the path to the directory used for
     automatic downloads.  If a song download is initiated without
     providing an explicit path or filehandle, the song data will be
     written into a file having the same name as the song located in the
     directory indicated by download_dir().

     Download_dir() starts out containing the empty string, which will
     cause the song data to be written to the current working directory.
     You may change the path by providing the method with an argument
     containing a relative or absolute directory.  For example:

          $nap->download_dir('/tmp/songs');  # write data to this path

     The download directory must already exist.  It will not be created for
     you.

*$download = $nap->download($song [, $file | $fh ])*
     Given an MP3::Napster::Song object returned from a previous search()
     or browse(), the download() method will attempt to initiate a download
     and perform the file transfer in the background.  If the download is
     successfully initiated, an MP3::Napster::Transfer object will be
     returned (see `MP3::Napster::Transfer' in this node).  You can use
     this object to monitor the progress of the transfer.  If the download
     attempt was unsuccessful, the method will return undef and leave an
     error message in $nap->error.

     You may also monitor the progress of the transfer by installing
     callbacks for TRANSFER_STARTED, TRANSFER_IN_PROGRESS, and
     TRANSFER_DONE, as described later.

     The download() method takes an optional second argument that can be
     either a file path or a filehandle.  In the case of a file path, the
     file is opened for writing.  If the file already exists, it is opened
     for appending and the download is coordinated in such a way that only
     the portion of the local file that is missing is downloaded from the
     peer.  This can be used to resume from previously cancelled download
     attempts.

     If you pass a filehandle to the download() method, the song data will
     be written directly to the filehandle.  This will work for pipes and
     other types of handles as well as with filehandles.  For example, you
     can play a song directly off the net by opening up a pipe to your
     favorite command-line MP3 decoder.

          open(PLAYER,"|mpg123 -");
          $nap->download($song,\*PLAYER);

     You must pass filehandles as GLOB refs (\*FH), GLOBS (*FH) or as
     IO::Handle objects.

     If no path or filehandle is passed to download(), then the module will
     write the song data into a file having same name as the song located
     within the directory specified by the download_dir() method.

*@downloads = $nap->downloads*
*@uploads   = $nap->uploads*
*@transfers = $nap->transfers*
     The downloads() method will return the list of active
     MP3::Napster::Transfer objects being used for downloading.  If the
     download has already completed, it will not be present on this list.

     The uploads() method returns all pending uploads, and transfers()
     returns the union of downloads() and uploads().

   See `MP3::Napster::Transfer' in this node for more information on
managing downloads, including how to abort them prematurely.

Chat Groups and Users
---------------------

   These methods provide access to Napster's chat groups, which are also
known as "channels".  To capture public and private messages, you must
install callbacks for the relevant events.  See `"Callbacks"' in this node.

*@channels = $nap->channels*
     The channels() method will return a list of available channels as an
     array of MP3::Napster::Channel objects.  When used in a string
     context, these objects interpolate as the name of the channel.  Object
     methods provide access to the topic channel, the number of users on
     the channel, and to the list of the users currently participating in
     the channel.  The channel object also provides a join() method that
     will allow you to join it and start receiving its events.

     See MP3/Napster/Channel.

*$result = $nap->join_channel($channel)*
     The join_channel() method will join the indicated channel. You may
     provide an MP3::Napster::Channel object from a previous channels()
     call, or a plain string containing the name of the channel.

     After joining a channel, the client will begin to send event messages
     relevant to the channel, such as notifications of when users join or
     leave the channel.  This method also sets the user's "current
     channel", which is used as the default destination for the
     public_message() method.

     More than one channel can be joined simultaneously, up to a limit set
     by the server.  If the channel is joined successfully, a true result
     will be returned.  Otherwise undef will be returned and $nap->error
     will contain the error message.  The list of channels currently joined
     can be retrieved with the member_channels() method.  If you attempt to
     join the same channel more than once, join_channel() will have the
     effect of making the selected channel the current one.

*$result = $nap->part_channel($channel)*
     The part_channel() method will disconnect you from the indicated
     channel so that you no longer receive messages from the channel.  You
     may pass the method an MP3::Napster::Channel object,or just a plain
     string containing the channel name.  The method always returns a true
     value, since the server provides no positive acknowledgement that the
     channel was successfully departed.

*$channel = $nap->channel([$channel])*
     The channel() method will return the current channel object, or undef
     if no channel is current.  It can also be used to set the current
     channel to the one indicated by the argument.  However it is better to
     use join_channel() for this purpose.

*@channels = $nap->enrolled_channels*
     This method returns the list of channels in which the user is
     currently enrolled, or an empty list if the user is not enrolled in
     any.

*@users = $nap->users([$channel])*
     The users() method returns the list of users currently attached to the
     channel as an array of MP3::Napster::User objects.  User object
     methods allow you to ping the indicated user, discover a limited
     amount of information about him or her, and list his or her files.

     If you provide a channel name or object, the user list will be
     retrieved from that channel.  Otherwise the method returns the list of
     users enrolled in the current channel.

     In case of error, the methods returns an empty list and stashes the
     error message in $nap->error.

*$result = $nap->public_message($message [,$channel])*
     This method sends a public message to the indicated channel, or the
     current channel if one is not designated.  On success, the method
     returns a true result.  On failure, it returns undef and sets
     $nap->error to a pithy error message.

     I do not know whether there is a limit on the size or content of
     public messages.  Most messages posted to the Napster service are
     short single lines containing cryptic abbreviations and
     poorly-disguised obscenities.

*$result = $nap->private_message($nickname,$message)*
     Private_message() sends a private message to the indicated user.  You
     may provide an MP3::Napster::User object, or just the user's nickname
     as a string.  On success, the method returns a true result.  On
     failure, it returns undef and sets $nap->error to an error message.

     I do not know whether there is a limit on the size or content of
     private messages.  Most messages posted to the Napster service are
     short single lines.

*$user = $nap->whois($nickname)*
     Given a string containing the nickname of a user, whois() returns an
     MP3::Napster::User object which you can query for further information
     on the user.  On an error, this method returns undef and sets
     $nap->error.  The most typical error is "no such user".  If the user
     is offline, you will receive an object whose fields are mostly blank.
     See MP3/Napster/User.

*$result = $nap->ping($nickname [,$timeout])*
     Given a string containing the nickname of a user or a
     MP3::Napster::User object and an optional timeout value in seconds,
     ping() sends a ping message to the user's client to determine if he or
     she is online.  If the user's client responds within the indicated
     period of time, then the method returns true.

     This method is also accessible directly from the MP3::Napster::User
     object.

     If timeout is explicitly set to zero, then the routine will return
     immediately without waiting for the reply.  You may intercept the PONG
     event with a callback in order to calculate the round-trip time to the
     remote user.

*($users,$files,$gigabytes) = $nap->stats*
     The stats() method returns a three element list containing server
     statistics.  The elements of the list are the number of users
     currently logged in, the number of song files being shared, and the
     total number of gigabytes of the shared files.

     Statistics messages (event SERVER_STATS) are issued by the Napster
     server at more-or-less random intervals. If no statistics event has
     arrived, this method will block until one does.  This is not usually a
     problem as the first statistics event arrives soon after login.

Low-Level Functions
-------------------

   Some low-level functions are documented.  Others are for internal use
and shouldn't be relied upon.  Caveat emptor!

*$result = $nap->send($event_code,$message)*
     This method will send the indicated event code and message to the
     server, and will return a result code indicating whether the message
     was sent successfully (but not whether it was in the correct format or
     correctly processed!)

     For a list of event codes, see `"Outgoing Events"' in this node
     below.  For the exact format of the message to send, see the
     napster.txt document that accompanies the MP3::Napster distribution.

     Example:

          $nap->send(PING,"Poppa_Bear");

*($event,$message) = $nap->wait_for(\@event_codes [,$timeout])*
     The wait_for() method will block until one of the indicated events
     occurs or the call times out, using the optional $timeout argument
     (expressed in seconds).  If one of the events occurs, wait_for() will
     return a two-element list containing the event code and the message.
     If the call times out, the method will return an empty list.

     wait_for() provides a number of shortcut variants.  To wait for just
     one event, you can pass the event code as a scalar rather than an
     array reference.  If you call the method in a scalar context, it will
     return just the event code, discarding the message, or undef in the
     case of a timeout.

     Example 1:

          $nap->send(PING,"Poppa_Bear");
          if ( ($ec,$msg) = $nap->wait_for(PONG,20) ) { # wait 20 seconds
             print "Got a PONG from $msg\n";
          } else {
             print "PING timed out\n";
          }

     Example 2:

          $nap->send(PING,"Poppa_Bear");
          $ec = $nap->wait_for([PONG,NO_SUCH_USER],20);
          if ($ec == PONG) {
             print "Got a PONG\n";
          } elsif ($ec == NO_SUCH_USER) {
             print "No such user!\n";
          } else {
             print "Timed out\n";
          }

*($event,$message) = $nap->send_and_wait($event_code,$message,\@event_codes [,$timeout])*
     This method combines send() with wait_for() in one operation.

     Example:

          ($ec,$msg) = $nap->send_and_wait(PING,"Poppa_Bear",[PONG,NO_SUCH_USER],20);
          if ($ec == PONG) {
             print "Got a PONG from $msg\n";
          } elsif ($ec == NO_SUCH_USER) {
             print "Invalid user: $msg\n";
          } else {
             print "Timed out\n";
          }

     If timeout is explicitly set to zero, then no wait will be performed
     and this call will be equivalent to send().

*$result = $nap->process_message($event_code,$message)*
     If you wish to insert an event of your own making into the event
     queue, process_message() allows you to do so.  This will block until
     all callbacks for the event have finished execution.

Waiting for Downloads
---------------------

   Because file transfers occur in the background, you have to be careful
that your script does not quit while they are still in progress.  The
easiest way to do this is to call wait_for_downloads().  This will unshare
all shared songs to prevent further transfers from being initiated and
then block until the last transfer is finished.  During this time, the
callbacks installed for TRANSFER_IN_PROGRESS and TRANSFER_DONE will be
executed as usual.

   If you prefer, you can manually check and wait on pending transfers.
You might want to do this, for instance, if you want to wait for
downloads, but don't care about interrupting pending uploads.  This code
fragment illustrates the idiom:

     # wait for the downloads to complete
     while (@d = $nap->downloads) {
       warn "waiting for ",scalar(@d)," downloads to finish...\n";
       my ($event,$download) = $nap->wait_for(TRANSFER_DONE);
       warn "$download is done...\n";
     }

   This is a loop that fetches the list of downloads currently in progress
by calling the downloads() method.  If it is non-empty, then there are
still downloads in progress.  The code prints out a warning message, and
then performs a wait_for() for a TRANSFER_DONE event.  When wait_for()
returns, the second item in the result list is the affected
MP3::Napster::Transfer object. The code prints out the Transfer object
(which interpolates the song name as a string), and goes back to looping.
When all the downloads are done, downloads() will return an empty list and
the loop will finish.

   You might want to modify this code to print out the status of finished
downloads and to unlink incomplete song files.  It is also possible to
abort a pending download by calling its abort() method (see
`MP3::Napster::Transfer' in this node).  See the napster.pl and
eg/simple_download.pl scripts for some ideas on doing this.

   Similar code will also work for pending uploads.

   To time out the process of waiting for transfers to complete, you can
use a standard eval{} block:

     eval {
        alarm(300);  # allow five minutes for completion
        local $SIG{ALARM} = sub { die "timeout" };
        $nap->wait_for_downloads();
     }
     alarm(0);

   You may also adjust an internal timeout used for idle transfers:

*$timeout = $nap->transfer_timeout([$timeout])*
     Internally the module checks transfers at regular intervals and
     cancels any that have been inactive for a period of time.  Inactivity
     means that no data has been transmitted in either direction.

     The default timeout is 300 seconds (five minutes).  You may examine
     and change this value with the transfer_timeout() method.

CALLBACKS
=========

   If you wish to write an interactive Napster client based on this
module, you will need to intercept and act on at least some of the server
events that are issued asynchronously after you login. You do this by
installing callbacks, which are simply Perl code references associated
with certain event codes. Once a callback is installed, the subroutine is
invoked whenever the corresponding event occurs.  An event can have
multiple callbacks installed, or no callbacks at all.

Callback Methods
----------------

   The callback() and replace_callback() methods allow you to attach and
remove callbacks from events.

*$coderef = $nap->callback(EVENT_CODE [,$coderef])*
     The callback() method assigns a callback subroutine to an event.  The
     event code is a small integer constant that is imported by default
     when you load MP3::Napster.  See `"Incoming Events"' in this node for
     the listing of event codes.  It is possible to have several callbacks
     assigned to a single event.  The subroutines will be called in the
     reverse order of which they were assigned.

     The two-argument form appends a callback to the event. With a single
     argument, callback() returns the list of callbacks currently assigned
     to the event.

*$nap->replace_callback(EVENT_CODE [,$coderef])*
     The replace_callback() method assigns a callback to the indicated
     event code, replacing whatever was there before.  When called with a
     single event code argument, any callbacks assigned to the event code
     are deleted.

*$nap->delete_callback(EVENT_CODE [,$coderef])*
     The delete_callback() method deletes a callback from the indicated
     event code.  If called without a code reference, all callbacks
     assigned to the event are cleared.  Use this with caution, as some
     callbacks are used internally to handle transfer requests.

*$event_code = $nap->event_code*
     The event_code() method returns the current event code.  It is most
     useful when called from within a callback subroutine to determine what
     event triggered the callback.

*$event_code = $nap->event_code*
     The event_code() method returns the current event code.  It is most
     useful when called from within a callback subroutine to determine what
     event triggered the callback.

*$event = $nap->event*
     The event() method returns the current event as the string
     corresponding to the event code constant.  For example, the USER_JOINS
     code, numeric 406, will be returned by $nap->event_code as numeric
     406, and as "USER_JOINS" by $nap->event.

*$message = $nap->message($code [,$msg])*
     The message() method returns the message associated with the specified
     event code.  It can also be used to change the message.  This method
     is most useful when used from within a callback.

   When a callback is invoked, it is passed three arguments consisting of
the MP3::Napster object, the event code, and a callback-specific message.
Usually the message is a string, but for some callbacks it is a more
specialized object, such as an MP3::Napster::Song.  Some events have no
message, in which case $msg will be undefined.

   Callbacks should have the following form:

     sub callback {
        my ($nap,$code,$msg) = @_;
        # do something
     }

   Here's an example of installing a callback for the USER_JOINS event, in
which the message is an MP3::Napster::User object corresponding to the
user who joined the channel:

     sub report_join {
       my ($nap,$code,$user) = @_;
       my $channel = $user->current_channel;
       print "* $user has entered $channel *\n";
     }

     $nap->callback(USER_JOINS,\&report_join);

   The same thing can also be accomplished more succinctly using anonymous
coderefs:

     $nap->callback(USER_JOINS,
                    sub {
                        my ($nap,$code,$user) = @_;
                        my $channel = $user->current_channel;
                        print "* $user has entered $channel *\n";
                    });

   Callbacks are invoked in an eval() context, which means that they can't
crash the system (hopefully).  Any error messages generated by die() or
compile-time errors in callbacks are printed to standard error.

Handling User Input
-------------------

   If you wish to write an interactive application that takes user input
and passes it on to the Napster server, MP3::Napster provides a way to
monitor a filehandle for available data and invoke a callback whenever
there is a complete line to read.

*$nap-*command_processor($coderef [,$filehandle])>
     The command_processor will install the code reference $coderef to be
     called whenever $filehandle has a complete line of data to be read.
     If no filehandle is provided, then STDIN is assumed.

   Here is an example of using this facility:

     $nap->command_processor(\&do_command,\*STDIN);
     $nap->run;

     sub do_command {
       my $nap  = shift;
       my $line = shift;
       if ($line =~ /^login/) {
          do_login($line);
       } elsif ($line =~ /^whisper/) {
          do_whisper($line);
       }
     }

   This example first installs do_command() as the handler for data coming
in on STDIN, and then calls $nap->run, starting the event loop.  Whenever
there is a complete line to read the callback will be called with two
arguments consisting a reference to the MP3::Napster object, and the input
line.  The line may end with a terminating newline.  On end of file, the
callback will be called a final time with undef as the second argument.

   The more traditional way of doing this will not necessarily work
satisfactorily:

     while (my $line = <>) {
      if ($line =~ /^login/) {
         do_login($line);
      } elsif ($line =~ /^whisper/) {
         do_whisper($line);
      }
     }

   The problem is that the program spends most of its time waiting on
STDIN.  During this time, background processing of file transfers and
other events will not be executed.

Using MP3::Napster with PerlTk
------------------------------

   If you wish to use MP3::Napster with PerlTk, call MP3::Napster->new()
with a *-tkmain* argument, providing it with the reference to the main
window returned by the Tk::MainWindow() function.  This will change
MP3::Napster's event processing in the following fundamental ways:

  1. Outgoing message methods will return immediately.  login(),
     register(), search() and all the other methods that send messages to
     the server will no longer wait for a result, but will return
     immediately.  The return value will indicate only whether the message
     was successfully queued for transmission.  You must detect the result
     of the command by intercepting and handling events returned by the
     server.

  2. The run(), wait_for(), and send_and_wait() methods return immediately
     Similarly, these methods no longer block until an event has occurred
     but return immediately.

  3. Tk's MainLoop handles I/O All I/O is handled through Tk's internal
     event handling, by using Tk::fileevent() to install a set of
     filehandles to be monitored for I/O.  You must call MainLoop() in
     order for anything to happen.

        A very very primitive PerlTk interface to MP3::Napster can be
found in the top level of the MP3::Napster directory in tknapster.pl.  It
is installed automatically in /usr/local/bin during "make install".

Incoming Events
---------------

   This is a list of the events that can be intercepted and handled by
callbacks.  Those that are marked as "used internally" may already have
default callbacks installed, but you are free to add your own using
callback().  However be careful before using replace_callback() or
delete_callback() to remove the default handler, and be sure you know what
you're doing!

   Not all of the known events are documented here (but will be in later
versions).  In addition, there are a number of events whose significance
is not yet understood by those reverse engineering the Napster protocol.

ERROR (code 0)
          Message: <error string>

     This is an error message from the server, ordinarily handled
     internally by remembering the error text for retrieval by the error()
     method.

LOGIN_ACK (code 3)
          Message: <email address>

     Acknowledgement of a successful login attempt.  Usually handled
     internally by the login() and register() methods.

REGISTRATION_ACK (code 8)
          Message: none

     Server acknowledges a successful registration attempt.  Ordinarily
     handled internally by register().

ALREADY_REGISTERED (code 9)
          Message: none

     Registration has failed because the nickname is taken.  Ordinarily
     handled internally by register().

INVALID_NICKNAME (code 10)
          Message: none

     Registration has failed because the nickname is invalid.  Ordinarily
     handled internally by register().

LOGIN_ERROR (code 13)
          Message: <error string>

     Some error occurred during login (such as invalid password).
     Ordinarily handled internally by login().

SEARCH_RESPONSE (code 201)
          Message: MP3::Napster::Song

     This event is returned in the course of a search to indicate a
     matching song.  The event is the MP3::Napster::Song corresponding to
     the search result.  There will be one such events for each song that
     is matched.  You might want to stuff the result into a global array in
     order to build up a list of such responses.  This is ordinarily
     handled internally by the search() method.

SEARCH_RESPONSE_END (code 202)
          Message: none

     This event is returned at the end of a search to indicate that it is
     done.  This is ordinarily handled internally by the search() method.

DOWNLOAD_ACK (code 204)
          Message: <nick> <ip> <port> "<filename>" <md5> <linespeed>

     This event is sent by the server to acknowledge your request for a
     download (event DOWNLOAD_REQ).  The message is a string containing
     multiple fields.  See napster.txt in the MP3::Napster distribution
     for details.  This event is ordinarily handled internally by the
     download() method.

PRIVATE_MESSAGE (code 205)
          Message: <nick> <msg>

     User has sent you a private message.  The message is a string
     containing the fields <nick> and <msg> separated by a single space.
     You can parse it out with the regular expression /^(\S+) (.*)/

     This event is ordinarily ignored.

GET_ERROR (code 206)
          Message: <nick> "<filename>"

     The file requested for download from user <nick> is unavailable.  The
     message is a string containing the user's nickname and the requested
     file path, enclosed in quotes.  For example:

          lefty "C:\stuff\mp3\John Phillips Sousa - Oh Canada!"

     This condition is usually handled internally by the download() method.

USER_SIGNON (code 209)
          Message: <nick> <link>

     A user on your hotlist has logged on to the server.  The message
     consists of the user's nickname and a small integer indicating the
     user's link speed, separated by a space.

     Hotlists are not currently implemented in the MP3::Napster API.  This
     message will probably be converted into an MP3::Napster::User object
     in the final version.

USER_SIGNOFF (code 210)
          Message: <nick>

     A user on your hotlist has logged off.

BROWSE_RESPONSE (code 212)
          Message: MP3::Napster::Song

     During a browse() of another user's shared files, a series of
     BROWSE_RESPONSE events will be returned, one for each song on the
     user's share list.  The message is converted internally into an
     MP3::Napster::Song object.  This is ordinarily handled internally by
     the browse() method, but an additional callback can be installed
     without interference.

BROWSE_RESPONSE_END (code 213)
          Message: none

     This event is sent to indicate that list of shared files returned in
     response to a browse request is done.  This is ordinarily handled
     internally by the browse() method, but an additional callback can be
     installed without interference.

SERVER_STATS (code 214)
          Message: <users> <files> <gigs>

     This event is sent intermittently by the server to give summary
     statistics.  The message consists of the number of users, number of
     shared files, and total size of shared data in gigabytes, separated by
     whitespace. For example:

          1021 8772 932

     This event is ordinarily ignored.

RESUME_RESPONSE (code 216)
          Message: MP3::Napster::Song

     The resume mechanism allows you to complete an interrupted download by
     searching for users who have songs that match the MD5 sum of the first
     300K of the interrupted transfer.

     After a RESUME_REQUEST, the server will return a list of all users who
     have a song that exactly matches the specified MD5 hash fingerprint.
     Each matching song generates a RESUME_RESPONSE event, similar to a
     SEARCH_RESPONSE event.  The message contains the matching song.

     The resume mechanism is not fully implemented in this version of
     MP3::Napster.

RESUME_RESPONSE_END (code 217)
          Message: none

     This event is sent at the end of a series of resume responses.

PUBLIC_MESSAGE (code 403)
          Message: <chan> <nick> <msg>

     This event is received when a user sends a public message to one of
     the channels in which you are enrolled.  The message consists of the
     channel, the user's nickname, and the message, separated by spaces:

          Alternative rastaman What do the colored dots mean?

     The fields can be parsed out with this regular expression:

          my ($chan,$nick,$msg) = $message =~ /^(\S+) (\S+) (.*)/;

     This event is ignored by default.

INVALID_ENTITY (code 404)
          Message: <error string>

     This error message is returned when the client has requested an
     operation on an invalid user or a channel.  This can be used to
     indicate that the user has gone offline, that the user doesn't exist,
     or that the channel doesn't exist.  Ordinarily this is handled by
     saving the message and making it available in $nap->error.

JOIN_ACK (code 405)
          Message: <channel>

     This event is sent when you have successfully joined a channel.  It is
     ordinarily handled internally by the join_channel() method.

USER_JOINS (code 406)
          Message: MP3::Napster::User

     This event is sent when a user joins a channel that you are registered
     for.  The message is an MP3::Napster::User object.  To determine
     which channel generated the event, interrogate the user object's
     current_channel() method.

USER_DEPARTS (code 407)
          Message:  MP3::Napster::User

     The user has departed one of the channels in which you are enrolled.
     To determine which channel generated the event, interrogate the
     object's current_channel() method.

CHANNEL_USER_ENTRY (code 408)
          Message: MP3::Napster::User

     Soon after joining a channel using join(), the server will return a
     list of users enrolled in the channel by sending a series of
     CHANNEL_USER_ENTRY events.  The message for each event contains a
     single MP3::Napster::User object.

     This event is ordinarily ignored.

CHANNEL_USER_END (code 409)
          Message: none

     This event is sent to indicate the end of a series of
     CHANNEL_USER_ENTRY events.

CHANNEL_TOPIC (code 410)
          Message: <topic>

     This event is sent soon after joining a channel and contains the
     welcome banner for the channel.  Usually ignored.

UPLOAD_REQUEST (code 501)
          Message: <nick> <ip> <port> "<sharename>" <md5> <link>

     User <nick> is requesting that you upload to his or her client the
     shared file named "sharename", using the indicated IP address and port
     to establish an outgoing connection to the remote user's machine.
     This event is issued when your client is behind a firewall and cannot
     accept incoming connections.  Ordinarily this event is handled
     internally and you will not want to replace it.  For details on the
     format of the message, see the napster.txt document.

     Unlike PASSIVE_UPLOAD_REQUEST, this event requires your client to make
     an outgoing connection with the indicated client.

     Also see PASSIVE_UPLOAD_REQUEST, TRANSFER_STARTED, TRANSFER_IN_PROCESS
     and TRANSFER_DONE.

LINK_SPEED_RESPONSE (601)
          Message: <nick> <link>

     This event is sent in response to a LINK_SPEED_REQUEST message and
     contains the indicated user's link speed as a small integer.
     Currently this event is neither triggered by MP3::Napster or handled.

WHOIS_RESPONSE (code 604)
          Message: MP3::Napster::User

     This event is returned in response to a whois() method, and contains
     information about the requested user.  Ordinarily it is handled
     internally by whois().

WHOWAS_RESPONSE (code 605)
          Message: MP3::Napster::User

     This event is returned in response to a whois() method when the user
     is currently offline.  It is ordinarily handled internally by whois().

PASSIVE_UPLOAD_REQUEST (code 607)
          Message: <nick> "<sharename>"

     User <nick> is notifying your client that it will soon establish an
     incoming connection to your machine in order to download the shared
     file named "filename".  The quotes are part of the message, as in:

          jenz22 "[Antonio Vivaldi] La Notte G minor.mp3"

     The "passive" part means that your client does not need to establish
     the connection.  It just waits for the remote client's incoming
     connect.

     Ordinarily this event is handled internally.  You definitely do not
     want to replace it.

     Also see UPLOAD_REQUEST, TRANSFER_STARTED, TRANSFER_IN_PROCESS and
     TRANSFER_DONE.

SET_DATA_PORT (code 613)
          Message: <port>

     The server sends this event when requesting that the client change its
     port for incoming connections. The default behavior is to change the
     port the client is listening on.  This may not be what you want if
     there is a firewall in the way.

CHANNEL_ENTRY (code 618)
          Message: MP3::Napster::Channel

     After requesting the channel list using channels() the server will
     return a series of CHANNEL_ENTRY events, each containing an
     MP3::Napster::Channel object.  You may interrogate the object to get
     more information about the channel, its users, and topic.

LIST_CHANNELS (code 617)
          Message: none

     This indicates that the CHANNEL_ENTRY list is finished.

USER_OFFLINE (code 620)
          Message: <nick>

     The user has gone offline.  This is returned as an error condition for
     a variety of user inquiries.

     This description may be mistaken, as newer versions of napster.txt
     describe this as an unknown event code.

MOTD (code 621)
          Message: <line of text>

     A series of message-of-the-day messages are returned soon after
     logging into the system.  Each message contains a line of text for
     display by the client.  This event is ordinarily ignored.

PING (code 751)
          Message: <nick>

     This event occurs when another user is attempting to ascertain if your
     client is still alive and connected to the network.  The message
     contains your nickname.  The client should respond to the PING event
     with a PONG message, and in fact the default callback for PING looks
     like this:

          $self->callback(PING,sub { my $self = shift;
          			     $self->send(PONG,$self->nickname) });

USER_LIST_ENTRY (code 825)
          Message: MP3::Napster::User

     A series of these events are sent in response to a users() request,
     each containing an MP3::Napster::User object corresponding to one of
     the users enrolled in the current channel.  This event is ordinarily
     handled internally by users().

LIST_USERS (code 830)
          Message: none

     This is sent at the end of a series of USER_LIST_ENTRY messages to
     indicate that the list is finished.

TRANSFER_STARTED (code 1024)
          Message: MP3::Napster::Transfer

     This event is sent when a download or upload begins.  You may examine
     the MP3::Napster::Transfer object to determine the direction of the
     transfer and the name of the remote user.

     This is actually a pseudo-event generated internally by MP3::Napster,
     and not part of the Napster protocol itself.

TRANSFER_IN_PROGRESS (code 1025)
          Message: MP3::Napster::Transfer

     This event is sent periodically during the course of a download or
     upload.  The precise interval can be adjusted with calls to the
     Transfer object's interval() method.  You may examine the object to
     determine the status of the transfer, and how many bytes have been
     transferred.

     This is actually a pseudo-event generated internally by MP3::Napster,
     and not part of the Napster protocol itself.

TRANSFER_DONE (code 1026)
          Message: MP3::Napster::Transfer

     This message is sent when a transfer is done.  Examine the object to
     determine whether the transfer was completed normally.

     This is actually a pseudo-event generated internally by MP3::Napster,
     and not part of the Napster protocol itself.

Outgoing Events
---------------

   This section is a brief summary of the outgoing commands that you can
send to the Napster server via the send() method.  Most of these commands
are easier to issue through API calls, such as $nap->search().  You may
need to use these outgoing commands to implement certain features that are
not yet part of the API, such as the various Napster administrative
functions.

   See the napster.txt document for a fuller description of these
commands.  As with the incoming events, not all of the known commands are
documented here, and there are commands issued by the PC client whose
significance is not yet understood.

LOGIN (code 2)
          Message: <nick> <password> <port> "<client-version>" <linkspeed>

     This requests a login for username <nick> with the specified password,
     port, client name and version and link type.  This message is issued
     automatically by login().

NEW_LOGIN (code 6)
          Message: <nick> <pass> <port> "<client-version>" <linkspeed> <email-address>

     This is an alternative login format that is used immediately after a
     successful registration request (see below).

REGISTRATION_REQUEST (code 7)
          Message: <nick>

     This message requests the registration of a new nickname.  It is
     issued automatically by the register() method.

LOGIN_OPTIONS (code 14)
          Message: NAME:%s ADDRESS:%s CITY:%s STATE:%s PHONE:%s AGE:%s INCOME:%s EDUCATION:%s

     This is sent at some point after a successful login or registration in
     order to upload the indicated information to the Napster server.  The
     description of the message in napster.txt is unclear on when and how
     the message should be used.  It is likely that the current module does
     not implement it correctly.

I_HAVE (code 100)
          Message: "<sharename>" <md5> <size> <bitrate> <frequency> <time>

     This message is sent to register a shared song file with the Napster
     server.  It is normally handled for you by the share() method.  See
     napster.txt for a fuller description.

REMOVE_FILE (code 102)
          Message: "<sharename>"

     This message removes the indicated shared song from the list
     maintained by the server.  It is not currently available in the
     MP3::Napster API.

SEARCH (code 200)
          Message: (see napster.txt)

     This message initiates a search for a shared song.  The message format
     is complex, but explained well in napster.txt.

DOWNLOAD_REQ (code 203)
          Message: <nick> "<sharename>"

     This message notifies the server of the client's intention to download
     file "sharename" from the indicated user.  The server will reply with
     a DOWNLOAD_ACK.  This is normally handled for you by the download()
     method.

PRIVATE_MESSAGE (code 205)
          Message: <nick> <message>

     This message code sends a private message to the indicated user. It is
     normally handled for you by the private_message()  method.

BROWSE_REQUEST (code 211)
          Message: <nick>

     This sends a request to the server to browse all the files shared by
     the indicated user.  This is ordinarily issued by the browse()
     method.  The response is returned as a series of BROWSE_RESPOND
     events.

RESUME_REQUEST (code 215)
          Message: <md5> <size>

     This issues a request to search for all songs that match the indicated
     MD5 hash and file size.  This is used to resume previously interrupted
     transfers.  The server replies with a series of RESUME_RESPONSE
     events.

     The resume facility is not yet implemented in MP3::Napster.

DOWNLOADING (code 218)
          Message: none

     The client sends this message to the server to indicate that it has
     begun downloading a song.  It does nothing except to bump up the
     "download" count in the user's profile, and is ordinarily handled
     automatically in the download() method.

DOWNLOAD_COMPLETE (code 219)
          Message: none

     This indicates that the client has completed a download, and reduces
     the download count by one.

UPLOADING (code 220)
          Message: none

     This indicates that the client has begun an upload, and is ordinarily
     issued automatically by the module when it has shared files.

UPLOAD_COMPLETE (code 221)
          Message: none

     This message indicates that the client has finished an upload.

JOIN_CHANNEL (code 400)
          Message: <channel>

     This is the message that is issued by join() to enroll in a channel.
     If succesful, the server will return with a JOIN_ACK.

PART_CHANNEL (code 401)
          Message: <channel>

     This message is sent when departing a channel, ordinarily issued by
     the part_channel() method.  Oddly, the server doesn't acknowledge this
     one.

SEND_PUBLIC_MESSAGE (code 402)
          Message: <channel> <message>

     This message sends a public message to the indicated channel.  It is
     issued by the public_message() method.

CHANNEL_TOPIC (code 410)
          Message: <channel> <topic>

     This message can be sent in order to change the topic assigned to a
     channel.  You probably need special privileges to do this.

PASSIVE_DOWNLOAD_REQ (code 500)
          Message: <nick> "<sharename>"

     This message requests that the user <nick> make an outgoing connection
     to the client's machine and send <sharename>.  It's used in the case
     that the owner of the file is behind a firewall and cannot accept
     incoming connections.  This message is ordinarily issued for you by
     the download() method.

LINK_SPEED_REQUEST (code 600)
          Message: <nick>

     This message requests a user's link speed.  The result will be a
     LINK_SPEED_RESPONSE event.

WHOIS_REQ (code 603)
          Message: <nick>

     This requests information about the specified user, ordinarily issued
     by the whois() method.

LIST_CHANNELS (code 617)
          Message: none

     This message is sent to get a list of channels and their topics from
     the server.  The response is a set of CHANNEL_ENTRY events, followed
     by a LIST_CHANNELS event to end the list (yes, the same event code is
     used for request and response).  This is ordinarily handled for you by
     the channels() method.

DATA_PORT_ERROR (code 626)
          Message: <nick>

     The client sends this message to the server when it has attempted and
     failed to make an outgoing connection to the indicated user.  This is
     issued when appropriate by MP3::Napster's file transfer routines.

CHANGE_LINK_SPEED (code 700)
          Message: <link>

     This message can be issued after login to change the listed link speed
     for the user.  It is sent (perhaps incorrectly?) by the
     change_registration() method.

CHANGE_PASSWORD (code 701)
          Message: <password>

     This message can be issued after login to change the user's password.
     It is issed by the change_registration() method.  Note that
     napster.txt does not document this code; I found it by accident when
     trying to change the e-mail address (see below).

CHANGE_EMAIL (code 702)
          Message: <email address>

     This message can be issued after login to change the user's e-mail
     address, or at least so it's documented.  In practice, I get a cryptic
     error message from the server

CHANGE_DATA_PORT  (code 703)
          Message: <port>

     This message is used to inform the server that the client is now
     listening on a different port for incoming connections. This message
     is issued automatically when processing the SET_DATA_PORT event.
     Ordinarily you will not want to manipulate it directly.

PING (code 751)
          Message: <nick>

     This message sends a PING event to the indicated user, ordinarily
     issued by the ping() method.  If the user's client is still online, it
     will respond with a PONG message.

PONG (code 752)
          Message: <nick>

     A client should respond to a PING event with a PONG message.  In fact,
     the default callback for the PING event does exactly that.

LIST_USERS (code 830)
          Message: <channel>

     This message requests a list of all the users in the indicated
     channel.  The server replies with a series of USER_LIST_ENTRY events.
     followed by a final LIST_USERS event (the same code is used both to
     initiate and terminate a user list).  This is ordinarily issued by the
     users() method.

MORE INFORMATION ON THE NAPSTER PROTOCOL
========================================

   More information on the Napster protocol can be found in the document
"napster.txt" that accompanies this module.  Other information can be
found in the documents and discussion groups available through
opennap.sourceforge.net.

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

COPYRIGHT
=========

   Copyright (c) 2000 Cold Spring Harbor Laboratory. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   See MP3/Napster/User, MP3/Napster/Song,
see MP3/Napster/Channel, and
`MPEG::Napster::Transfer' in this node

Autoload object accessors
*************************

NAME
====

   MP3::Napster::Base - Autoload object accessors

SYNOPSIS
========

   None

DESCRIPTION
===========

   This class is used internally by MP3::Napster as a base class for
MP3::Napster::Song, MP3::Napster::Channel, MP3::Napster::Transfer, and
MP3::Napster itself.  It provides autoloading facilities for accessors.

   Documentation will be added if and when it becomes useful to
application developers.

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

COPYRIGHT
=========

   Copyright (c) 2000 Cold Spring Harbor Laboratory. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   See MP3/Napster, MP3/Napster/Song,
see MP3/Napster/Channel, and
`MPEG::Napster::Transfer' in this node

Object-oriented access to Napster channels
******************************************

NAME
====

   MP3::Napster::Channel - Object-oriented access to Napster channels

SYNOPSIS
========

     @channels = $nap->channels;
     foreach $chan (@channels) {
        print $chan->name,"\n";
        print $chan->topic,"\n";
        print $chan->user_count,"\n";
        print $chan->server,"\n";
        @users = $chan->users,"\n";
     }

     $chan->join && print "Welcome to $chan!\n";
     $chan->part && print "Goodbye!\n";

DESCRIPTION
===========

   MP3::Napster::Channel provides object-oriented access to discussion
channels on the Napster service.

OBJECT CONSTRUCTION
-------------------

   Channel objects are normally not constructed from scratch but are
returned by the MPEG::Napster channels() method.

OBJECT METHODS
--------------

   Methods provide access to various attributes of the Channel object and
allow you to join and depart the channel.

Accessors
     The accessors provide read-only access to the following Channel
     attributes.

          Accessor                Description
          --------                -----------
          $channel->name          Channel name
          $channel->user_count    Number of users enrolled in channel
          $channel->topic         Channel's topic (welcome banner)
          $channel->server        MP3::Napster object from which channel was derived

*@users = $channel->users*
     This method returns the current list of users subscribed to the
     channel.  The return value is an array of MP3::Napster::User objects.

*$result = $channel->join*
     Attempt to join the channel, and return a true result if successful.

*$result = $channel->join*
     Attempt to join the channel, returning a true result if successful.

*$result = $channel->part*
     Attempt to depart from the channel, returning a true result if
     successful.

*String Overloading*
     If used in a string context, MPEG::Napster::Channel objects will
     invoke the name() method, allowing the objects to be directly
     interpolated into strings, printed, and pattern matched.

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

COPYRIGHT
=========

   Copyright (c) 2000 Cold Spring Harbor Laboratory. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   See MP3/Napster, MP3/Napster/Song,
see MP3/Napster/User, and
`MPEG::Napster::Transfer' in this node

MP3::Napster::IOEvent
*********************

NAME
====

   MP3::Napster::IOEvent

SYNOPSIS
========

DESCRIPTION
===========

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

COPYRIGHT
=========

   Copyright (c) 2000 Cold Spring Harbor Laboratory. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

Manage local songs shared by MP3::Napster
*****************************************

NAME
====

   MP3::Napster::Registry - Manage local songs shared by MP3::Napster

SYNOPSIS
========

   None

DESCRIPTION
===========

   This class is used internally by MP3::Napster to manage the list of
local MP3 files that are shared with other users.  Documentation will be
added if and when it becomes useful to application developers.

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

COPYRIGHT
=========

   Copyright (c) 2000 Cold Spring Harbor Laboratory. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   See MP3/Napster, MP3/Napster/Song,
and `MPEG::Napster::Transfer' in this node

MP3::Napster::Echo
******************

NAME
====

   MP3::Napster::Echo

SYNOPSIS
========

DESCRIPTION
===========

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

COPYRIGHT
=========

   Copyright (c) 2000 Cold Spring Harbor Laboratory. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

Object-oriented access to Napster shared songs
**********************************************

NAME
====

   MP3::Napster::Song - Object-oriented access to Napster shared songs

SYNOPSIS
========

     @songs = $nap->browse('sexybabe');
     foreach $song (@songs) {
       print $song->name,"\n";
       print $song->size,"\n";
       print $song->bitrate,"\n";
       print $song->freq,"\n";
       print $song->owner,"\n";
       print $song->length,"\n";
       print $song->hash,"\n";
       print $song->address,"\n";
       print $song->link,"\n";
     }

     $songs[0]->download;  # download to local disk

DESCRIPTION
===========

   MP3::Napster::Song provides object-oriented access to shared MP3 files
that can be retrieved via the Napster network protocol.

OBJECT CONSTRUCTION
-------------------

   Song objects are normally not constructed *de novo*, but are returned
by search() and browse() calls to MPEG::Napster objects.

OBJECT METHODS
--------------

   Object methods provide access to various attributes of the sound file,
and allow you to download the file to disk or pass its data to a pipe.

Accessors
     The accessors provide read-only access to the Song object's
     attributes.

          Accessor                Description
          --------                -----------
          $song->name             Title of the song, often including artist
          $song->title            Same as above
          $song->size             Physical size of file, in bytes
          $song->bitrate          Bit rate of MP3 data, in kilobits/sec
          $song->freq             Sampling frequency, in Hz
          $song->length           Duration of song, in seconds
          $song->owner            Owner of the song, as an MP3::Napster::User object
          $song->path             Physical path of the song, at the remote end
          $song->hash             MD5 hash of the first 300K of the song, for identification
          $song->address          IP address of the client that holds the song
          $song->link             The link speed of the owner, as a string (e.g. LINK_DSL)
          $song->link_code        The link speed of the owner, as a numeric code (e.g. 3)
          $song->server           The MP3::Napster object from which this song was retrieved

*$transfer = $song->download( [$path | $fh] )*
     The download() method will initiate a download on the song.  The
     method behaves like the MP3::Napster->download() method.  If no
     argument is provided, the method will open up a file in the location
     specified by the MP3::Napster object's download_dir() method.
     Otherwise the song data will be written to the indicated path or
     filehandle.

     If successful, the method will return a MP3::Napster::Transfer object,
     which can be used to monitor and control the download process.

*String Overloading*
     If used in a string context, MPEG::Napster::Song objects will invoke
     the name() method.  This allows the objects to be directly
     interpolated into strings, printed, and pattern matched.

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

COPYRIGHT
=========

   Copyright (c) 2000 Cold Spring Harbor Laboratory. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   See MP3/Napster, MP3/Napster/User,
see MP3/Napster/Channel, and
`MPEG::Napster::Transfer' in this node

Object-oriented access to Napster users
***************************************

NAME
====

   MP3::Napster::User - Object-oriented access to Napster users

SYNOPSIS
========

     $user = $nap->whois('glimitz');
     print $user->name,"\n";
     print $user->sharing,"\n";
     print $user->link,"\n";
     print $user->link_code,"\n";
     print $user->server,"\n";
     print $user->current_channel,"\n";
     print join ' ',$user->channels,"\n";
     print $user->login_time,"\n";
     print $user->time,"\n";
     print $user->channels,"\n";
     print $user->uploads,"\n";
     print $user->downloads,"\n";
     print $user->level,"\n";
     print $user->last_seen,"\n";
     print $user->profile,"\n";

     $user->ping || warn "$user is unreachable";
     $user->msg('Hello there!');

DESCRIPTION
===========

   MP3::Napster::User provides object-oriented access to other users on
the Napster service.

OBJECT CONSTRUCTION
-------------------

   User objects are normally not constructed *de novo*, but are returned
by the MPEG::Napster whois() and users() methods, as well as by several of
the callbacks involving the Napster chat channels, specifically USER_JOINS
and USER_DEPARTS.

OBJECT METHODS
--------------

   Object methods provide access to various attributes of the User object,
allow you to send private messages to users, to browse their files, and to
ping them to determine if they are online.

Accessors
     The accessors provide read-only access to the following User
     attributes.

          Accessor                Description
          --------                -----------
          $user->name             User's (nick)name
          $user->link             User's link speed as a string
          $user->link_code        User's link speed as a numeric code
          $user->sharing          Number of files user is sharing
          $user->current_channel  User's current channel
          $user->channels         List of channels that user is subscribed to
          $user->uploads          Number of uploads the user is currently performing
          $user->downloads        Number of downloads the user is currently performing
          $user->level            The user's "level", one of "User" or "Admin"
          $user->status           One of "Offline", "Active" or "Inactive"
          $user->last_seen        The time the user was last seen, in seconds since the epoch
          $user->time             The number of seconds that the user has been logged in
          $user->login_time       The same, in a nice human-readable form
          $user->client           The version of the user's Napster client
          $user->server           The MP3::Napster that this User is attached to

*$result = $user->ping([$timeout])*
     The ping() method returns true if the user is reachable by a PING
     command.  The default timeout for a positive response is defined by
     MP3::Napster, currently 5 seconds by default.

*@songs = $user->browse*
     Browse the user's shared files, returning an array of
     MP3::Napster::Song objects.

*$user->update*
     Update the user's attributes from the most current versions on the
     server.  Withoug calling update() the values are always those present
     when the object was first created.

*$user->msg("text")*
     Send a private message to the user.

*$profile = $user->profile*
     Return a human readable profile like this one:

          Name:      OddBall187
          Status:    Active
          Sharing:   62
          Link:      CABLE
          Level:     User
          Time:      53.5 min
          Channels:  Themes,Alternative,Rap,Rock
          Uploads:   5
          Downloads: 1
          Client:    v2.0

*String Overloading*
     If used in a string context, MPEG::Napster::User objects will invoke
     the name() method, allowing the objects to be directly interpolated
     into strings, printed, and pattern matched.

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

COPYRIGHT
=========

   Copyright (c) 2000 Cold Spring Harbor Laboratory. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   See MP3/Napster, MP3/Napster/Song,
see MP3/Napster/Channel, and
`MPEG::Napster::Transfer' in this node

MP3::Napster::Echo
******************

NAME
====

   MP3::Napster::Echo

SYNOPSIS
========

DESCRIPTION
===========

AUTHOR
======

   Lincoln Stein <lstein@cshl.org>.

COPYRIGHT
=========

   Copyright (c) 2000 Cold Spring Harbor Laboratory. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

Perl extension for reading / writing ID3v1 tags of mp3-files
************************************************************

NAME
====

   MP3::TAG::ID3v1 - Perl extension for reading / writing ID3v1 tags of
mp3-files

SYNOPSIS
========

   MP3::TAG::ID3v2 is designed to be called from the MP3::Tag module.  It
then returns a ID3v2-tag-object, which can be used in a users program.

     use MP3::TAG::ID3v1;
     $id3v1 = MP3::TAG::ID3v1->new($mp3obj);

   `$mp3obj' is a object from MP3::Tag. See according documentation.  $tag
is undef when no tag is found in the `$mp3obj'.

   * Reading the tag

     print "   Song: " .$id3v1->song . "\n";
     print " Artist: " .$id3v1->artist . "\n";
     print "  Album: " .$id3v1->album . "\n";
     print "Comment: " .$id3v1->comment . "\n";
     print "   Year: " .$id3v1->year . "\n";
     print "  Genre: " .$id3v1->genre . "\n";
     print "  Track: " .$id3v1->track . "\n";
     @tagdata = $mp3->all();
     foreach (@tagdata) {
       print $_;
     }

   * Changing / Writing the tag

     $id3v1->comment("This is only a Test Tag");
     $id3v1->song("testing");
     $id3v1->artist("Artest");
     $id3v1->album("Test it");
     $id3v1->year("1965");
     $id3v1->track("5");
     $id3v1->genre("Blues");
     # or at once
     $id3v1->all("song title","artist","album","1900","comment",10,"Ska");#
     $id3v1->writeTag;

AUTHOR
======

   Thomas Geffert, thg@users.sourceforge.net

DESCRIPTION
===========

new()
          $id3v1 = MP3::TAG::ID3v1->new($mp3obj[, $create]);

     Generally called from MP3::TAG, because a $mp3obj is needed.  If
     $create is true, a new tag is created. Otherwise undef is returned,
     if now ID3v1 tag is found in the $mp3obj.

song(), artist(), album(), year(), comment(), track(), genre()
          $artist  = $id3v1->artist;
          $artist  = $id3v1->artist($artist);
          $album   = $id3v1->album;
          $album   = $id3v1->album($album);
          $year    = $id3v1->year;
          $year    = $id3v1->year($year);
          $comment = $id3v1->comment;
          $comment = $id3v1->comment($comment);
          $track   = $id3v1->track;
          $track   = $id3v1->track($track);
          $genre   = $id3v1->genre;
          $genre   = $id3v1->genre($genre);

     Use these functions to retrieve the date of these fields, or to set
     the data.

     $genre can be a string with the name of the genre, or a number
     describing the genre.

all()
          @tagdata = $id3v1->all;
          @tagdata = $id3v1->all($song, $artist, $album, $year, $comment, $track, $genre);

     Returns all information of the tag in a list.  You can use this sub
     also to set the data of the complete tag.

     The order of the data is always song, artist, album, year, comment,
     track, and  genre.  genre has to be a string with the name of the
     genre, or a number identifying the genre.

writeTag()
          $id3v1->writeTag;

     Writes the ID3v1 tag to the file.

removeTag()
          $id3v1->removeTag;

     Removes the ID3v1 tag from the file.

genres()
          @allgenres = $id3v1->genres;
          $genreName = $id3v1->genres($genreID);
          $genreID   = $id3v1->genres($genreName);

     Returns a list of all genres, or the according name or id to a given
     id or name.

SEE ALSO
========

   MP3::Tag, MP3::TAG::ID3v2

   ID3v1 standard - http://www.id3.org

Read / Write ID3v2.3 tags from MP3 audio files
**********************************************

NAME
====

   MP3::TAG::ID3v2 - Read / Write ID3v2.3 tags from MP3 audio files

SYNOPSIS
========

   MP3::TAG::ID3v2 is designed to be called from the MP3::Tag module.  It
then returns a ID3v2-tag-object, which can be used in a users program.

     $id3v2 = MP3::TAG::ID3v2->new($mp3obj);

   `$mp3obj' is a object from MP3::Tag. See according documentation.  $tag
is undef when no tag is found in the `$mp3obj'.

   * Reading a tag

     @frameIDs = $id3v2->getFrameIDS;

     foreach my $frame (@frameIDs) {
       my ($info, $name) = $id3v2->getFrame($frame);
       if (ref $info) {
         print "$name ($frame):\n";
         while(my ($key,$val)=each %$info) {
     	print " * $key => $val\n";
         }
       } else {
         print "$name: $info\n";
       }
     }

   * Changing / Writing a tag

     $id3v2->add_frame("TIT2", "Title of the song");
     $id3v2->change_frame("TALB","Greatest Album");
     $id3v2->remove_frame("TLAN");

     $id3v2->write_tag();

   * Get information about supported frames

     %tags = $id3v2->supported_frames();
     while (($fname, $longname) = each %tags) {
         print "$fname $longname: ",
               join(", ", @{$id3v2->what_data($fname)}), "\n";
     }

AUTHOR
======

   Thomas Geffert, thg@users.sourceforge.net

DESCRIPTION
===========

new()
          $tag = new($mp3obj);

     new() needs as parameter a mp3obj, as created by `MP3::Tag' (see
     documentation of MP3::Tag).  new tries to find a ID3v2 tag in the
     mp3obj. If it does not find a tag it returns undef.  Otherwise it
     reads the tag header, as well an extended header, if available. It
     reads the rest of the tag in a buffer, does unsynchronizing if
     neccessary, and returns a ID3v2-object.  At this moment only ID3v2.3
     is supported. Any extended header with CRC data is ignored, so not
     CRC check is done at the moment.  The ID3v2-object can then be used
     to extract information from the tag.

getFrameIDs()
          @frameIDs = $tag->getFrameIDs;

     getFrameIDs loops through all frames, which exist in the tag. It
     returns a list of all available Frame IDs. These are
     4-character-codes (short names), the internal names of the frames.

     You can use this list to iterate over all frames to get their data,
     or to check if a specific frame is included in the tag.

     If there are multiple occurences of a frame in one tag, the first
     frame is returned with its normal short name, following frames of
     this type get a '00', '01', '02', ... appended to this name. These
     expanded names can then used with `getFrame' to get the information
     of these frames.

getFrame()
          ($info, $name) = getFrame($ID);
          ($info, $name) = getFrame($ID, 'raw');

     getFrame gets the contents of a specific frame, which must be
     specified by the 4-character-ID (aka short name). You can use
     `getFrameIDs' to get the IDs of the tag, or use IDs which you hope to
     find in the tag. If the ID is not found, getFrame returns (undef,
     undef).

     Otherwise it extracts the contents of the frame. Frames in ID3v2 tags
     can be very small, or complex and huge. That is the reason, that
     getFrame returns the frame data in two ways, depending on the tag.

     If it is a simple tag, with only one piece of data, this date is
     returned directly as ($info, $name), where $info is the text string,
     and $name is the long (english) name of the frame.

     If the frame consist of different pieces of data, $info is a hash
     reference, $name is again the long name of the frame.

     The hash, to which $info points, contains key/value pairs, where the
     key is always the name of the data, and the value is the data itself.

     If the name starts with a underscore (as eg '_code'), the data is
     probably binary data and not printable. If the name starts without an
     underscore, it should be a text string and printable.

     If there exists a second parameter like raw, the whole frame data is
     returned, but not the frame header. If the data was stored
     compressed, it is also in raw mode uncompressed before it is
     returned. Then $info contains a string with all data (which might be
     binary), and $name against the long frame name.

     ! Encrypted frames are not supported yet !

     ! Some frames are not supported yet, but the most common ones are
     supported !

write_tag()
          $id3v2->write_tag;

     Saves a frame to the file. It tries to update the file in place, when
     the space of the old tag is big enoug for the new tag.  Otherwise it
     creates a temp file (i.e. copies the whole mp3 file) and
     renames/moves it to the original file name.

     An extended header with CRC checksum is not supported yet.

     At the moment the tag is automatically unsynchronized.

remove_tag()
          $id3v2->remove_tag();

     Removes the whole tag from the file by copying the whole mp3-file to
     a temp-file and renaming/moving that to the original filename.

add_frame()
          $id3v2->add_frame($fname, @data);

     Add a new frame, identified by the short name $fname.  The $data must
     consist from so much elements, as described in the ID3v2.3 standard.
     If there is need to give an encoding parameter and you would like
     standard ascii encoding, you can omit the parameter or set it to 0.
     Any other encoding is not supported yet, and thus ignored.

     Examples:

          add_frame("TIT2", 0, "Abba");   # both the same, but
          add_frame("TIT2", "Abba");      # this one with implicit encoding
          add_frame("COMM", "ENG", "Short text", "This is a comment");

change_frame()
          $id3v2->change_frame($fname, @data);

     Change an existing frame, which is identified by its short name
     $fname. @data must be same as in add_frame;

remove_frame()
          $id3v2->remove_frame($fname);

     Remove an existing frame. $fname is the short name of a frame, eg as
     returned by `getFrameIDs'.

supported_frames()
          %frames = $id3v2->supported_frames();

     Returns a hash with all supported frames. The keys of the hash are
     the short names of the supported frames, the according values are the
     long (english) names of the frames.

what_data()
          @data = $id3v2->what_data($fname);

     Returns for a frame the needed data fields to write this tag.  At
     this moment only the internal field names are returned, without any
     additional information about the data format of this field. Names
     beginning with an underscore (normally '_data') can contain binary
     data.

     This will change hopefully later on...

SEE ALSO
========

   MP3::Tag, MP3::TAG::ID3v1

   ID3v2 standard - http://www.id3.org

Module for reading tags of MP3 audio files
******************************************

NAME
====

   Tag - Module for reading tags of MP3 audio files

SYNOPSIS
========

     use Tag;
     $mp3 = MP3::Tag->new($filename);
     $mp3->getTags;

     if (exists $mp3->{ID3v1}) {
       $id3v1 = $mp3->{ID3v1};
       print $id3v1->song;
       ...
     }

     if (exists $mp3->{ID3v2}) {
       ($name, $info) = $mp3->{ID3v2}->getFrame("TIT2");
       ...
     }

     $mp3->close();

AUTHOR
======

   Thomas Geffert, thg@users.sourceforge.net

DESCRIPTION
===========

   Tag is a wrapper module to read different tags of mp3 files.  It
provides an easy way to access the functions of seperate moduls which do
the handling of reading/writing the tags itself.

   At the moment MP3::Tag::ID3v1 and MP3::Tag::ID3v2 are supported.

   !! As this is only a beta version, it is very likely that the design !!
of this wrapper module will change soon !!

new()
          $mp3 = MP3::Tag->new($filename);

     Creates a mp3-object, which can be used to retrieve/set different
     tags.

getTags()
          @tags = $mp3->getTags;

     Checks which tags can be found in the mp3-object. It returns a list
     @tags which contains strings identifying the found tags.

     Each found tag can be accessed then with $mp3->{tagname} .

     Use the information found in MP3::Tag::ID3v1 and MP3::Tag::ID3v2 to
     see what you can do with the tags.

newTag()
          $tag = $mp3->newTag($tagname);

     Creates a new tag of the given type $tagname. You can access it then
     with $mp3->{$tagname}. At the moment ID3v1 and ID3v2 are supported as
     tagname.

     Returns an tag-object: $mp3->{$tagname}.

close()
          $mp3->close;

     You can use close() to explicitly close a file. Normally this is done
     automatically by the module, so that you don't need to do this.

genres()
          $allgenres = $mp3->genres;
          $genreName = $mp3->genres($genreID);
          $genreID   = $mp3->genres($genreName);

     Returns a list of all genres (reference to an array), or the according
     name or id to a given id or name.

     This function is only a shortcut to MP3::Tag::ID3v1->genres.

     This can be also called as MP3::Tag->genres; =cut

     sub genres {   # returns all genres, or if a parameter is given, the
     according genre   my $self=shift;   return
     MP3::Tag::ID3v1::genres(shift); }

autoinfo()
          ($song, $track, $artist, $album) = $mp3->autoinfo();
          $info_hashref = $mp3->autoinfo();

     autoinfo() returns information about the song name, song number,
     artist number and album name. It can get this information from an
     ID3v1-tag, an ID3v2-tag and from the filename itself.

     It will as default first try to find a ID3v2-tag to get this
     information. If this cannot be found it tries to find a ID3v1-tag and
     if this is not present either, it will use the filename to retrieve
     the information.

     You can change the order of this with the config() command.

     autoinfo() returns an array with the information or a hashref. The
     hash then has the keys song, track, artist, album where the
     information is stored.

config
          MP3::Tag->config("item", options, ...);

     Possible items are:

     * autoinfo

          Configure the order in which ID3v1-, ID3v2-tag and filename are used
          by autoinfo.  options can be "ID3v1","ID3v2","filename". The order
          in which they are given to config also sets the order how they are
          used by autoinfo. If an option is not present, it will not be used
          by auotinfo.

          $mp3->config("autoinfo","ID3v1","ID3v2","filename");

          sets the order to check first ID3v1, then ID3v2 and last the
          Filename

          $mp3->config("autoinfo","ID3v1","filename","ID3v2");

          sets the order to check first ID3v1, then the Filename and last
          ID3v2. As the filename will be always present ID3v2 will be
          checked never.

          $mp3->config("autoinfo","ID3v1","ID3v2");

          sets the order to check first ID3v1, then ID3v2. The filename will
          be never used.

     * Later this will be used probably to configure more things.

SEE ALSO
========

   See MP3/Tag/ID3v1, MP3/Tag/ID3v2,
see MP3/Tag/File,

Module for reading / writing files
**********************************

NAME
====

   MP3::Tag::File - Module for reading / writing files

SYNOPSIS
========

   MP3::Tag::File is designed to be called from the MP3::Tag module.

   It offers possibilities to read/write data from files.

read_filename($what, $filename)
     read_filename() tries to extract information about artist, song, song
     number and album from the filename.

     This is likely to fail for a lot of filenames, especially the album
     will be often wrongly guessed, as the name of the parent directory is
     taken as album name.

     $what and $filename are optional. $what maybe song, track, artist or
     album.  If $what is defined read_filename will return only this
     element.

     If $filename is defined this filename will be used and not the real
     filename.

     Following formats will be hopefully recognized:

     album name/artist name - song name.mp3
     album_name/artist_name-song_name.mp3
     album.name/artist.name_song.name.mp3 album name/(artist name) song
     name.mp3 album name/01. artist name - song name.mp3 album name/artist
     name - 01 - song.name.mp3

song($filename)
     Returns the song name, guessed from the filename. See also
     read_filename()

     $filename is optional and if defined will be used instead of the real
     filename.

artist($filename)
     Returns the artist name, guessed from the filename. See also
     read_filename()

     $filename is optional and if defined will be used instead of the real
     filename.

track($filename)
     Returns the track number, guessed from the filename. See also
     read_filename()

     $filename is optional and if defined will be used instead of the real
     filename.

album($filename)
     Returns the album name, guessed from the filename. See also
     read_filename() The album name is guessed from the parent directory
     so be careful with this!

     $filename is optional and if defined will be used instead of the real
     filename.

Module for reading / writing ID3v1 tags of MP3 audio files
**********************************************************

NAME
====

   MP3::Tag::ID3v1 - Module for reading / writing ID3v1 tags of MP3 audio
files

SYNOPSIS
========

   MP3::Tag::ID3v1 is designed to be called from the MP3::Tag module.  It
then returns a ID3v1-tag-object, which can be used in a users program.

     use MP3::Tag::ID3v1;
     $id3v1 = MP3::Tag::ID3v1->new($mp3obj);

   `$mp3obj' is a object from MP3::Tag. See `MP3::Tag|according
documentation' in this node.  $tag is undef when no tag is found in the
`$mp3obj'.

   * Reading the tag

     print "   Song: " .$id3v1->song . "\n";
     print " Artist: " .$id3v1->artist . "\n";
     print "  Album: " .$id3v1->album . "\n";
     print "Comment: " .$id3v1->comment . "\n";
     print "   Year: " .$id3v1->year . "\n";
     print "  Genre: " .$id3v1->genre . "\n";
     print "  Track: " .$id3v1->track . "\n";
     @tagdata = $mp3->all();
     foreach (@tagdata) {
       print $_;
     }

   * Changing / Writing the tag

     $id3v1->comment("This is only a Test Tag");
     $id3v1->song("testing");
     $id3v1->artist("Artest");
     $id3v1->album("Test it");
     $id3v1->year("1965");
     $id3v1->track("5");
     $id3v1->genre("Blues");
     # or at once
     $id3v1->all("song title","artist","album","1900","comment",10,"Ska");#
     $id3v1->writeTag;

AUTHOR
======

   Thomas Geffert, thg@users.sourceforge.net

DESCRIPTION
===========

new()
          $id3v1 = MP3::Tag::ID3v1->new($mp3obj[, $create]);

     Generally called from MP3::Tag, because a $mp3obj is needed.  If
     $create is true, a new tag is created. Otherwise undef is returned,
     if now ID3v1 tag is found in the $mp3obj.

song(), artist(), album(), year(), comment(), track(), genre()
          $artist  = $id3v1->artist;
          $artist  = $id3v1->artist($artist);
          $album   = $id3v1->album;
          $album   = $id3v1->album($album);
          $year    = $id3v1->year;
          $year    = $id3v1->year($year);
          $comment = $id3v1->comment;
          $comment = $id3v1->comment($comment);
          $track   = $id3v1->track;
          $track   = $id3v1->track($track);
          $genre   = $id3v1->genre;
          $genre   = $id3v1->genre($genre);

     Use these functions to retrieve the date of these fields, or to set
     the data.

     $genre can be a string with the name of the genre, or a number
     describing the genre.

all()
          @tagdata = $id3v1->all;
          @tagdata = $id3v1->all($song, $artist, $album, $year, $comment, $track, $genre);

     Returns all information of the tag in a list.  You can use this sub
     also to set the data of the complete tag.

     The order of the data is always song, artist, album, year, comment,
     track, and  genre.  genre has to be a string with the name of the
     genre, or a number identifying the genre.

writeTag()
          $id3v1->writeTag;

     Writes the ID3v1 tag to the file.

removeTag()
          $id3v1->removeTag;

     Removes the ID3v1 tag from the file.

genres()
          @allgenres = $id3v1->genres;
          $genreName = $id3v1->genres($genreID);
          $genreID   = $id3v1->genres($genreName);

     Returns a list of all genres, or the according name or id to a given
     id or name.

SEE ALSO
========

   See MP3/Tag, MP3/Tag/ID3v2,

   ID3v1 standard - http://www.id3.org

Read / Write ID3v2.3 tags from mp3 audio files
**********************************************

NAME
====

   MP3::Tag::ID3v2 - Read / Write ID3v2.3 tags from mp3 audio files

SYNOPSIS
========

   MP3::Tag::ID3v2 is designed to be called from the MP3::Tag module.  It
then returns a ID3v2-tag-object, which can be used in a users program.

     $id3v2 = MP3::Tag::ID3v2->new($mp3obj);

   `$mp3obj' is a object from MP3::Tag. See according documentation.  $tag
is undef when no tag is found in the `$mp3obj'.

   * Reading a tag

     $frameIDs_hash = $id3v2->getFrameIDS;

     foreach my $frame (keys %$frameIDs_hash) {
       my ($info, $name) = $id3v2->getFrame($frame);
       if (ref $info) {
         print "$name ($frame):\n";
         while(my ($key,$val)=each %$info) {
     	print " * $key => $val\n";
         }
       } else {
         print "$name: $info\n";
       }
     }

   * Changing / Writing a tag

     $id3v2->add_frame("TIT2", "Title of the song");
     $id3v2->change_frame("TALB","Greatest Album");
     $id3v2->remove_frame("TLAN");

     $id3v2->write_tag();

   * Get information about supported frames

     %tags = $id3v2->supported_frames();
     while (($fname, $longname) = each %tags) {
         print "$fname $longname: ",
               join(", ", @{$id3v2->what_data($fname)}), "\n";
     }

AUTHOR
======

   Thomas Geffert, thg@users.sourceforge.net

DESCRIPTION
===========

new()
          $tag = new($mp3obj);

     new() needs as parameter a mp3obj, as created by `MP3::Tag' (see
     documentation of MP3::Tag).  new tries to find a ID3v2 tag in the
     mp3obj. If it does not find a tag it returns undef.  Otherwise it
     reads the tag header, as well an extended header, if available. It
     reads the rest of the tag in a buffer, does unsynchronizing if
     neccessary, and returns a ID3v2-object.  At this moment only ID3v2.3
     is supported. Any extended header with CRC data is ignored, so not
     CRC check is done at the moment.  The ID3v2-object can then be used
     to extract information from the tag.

getFrameIDs()
          $frameIDs = $tag->getFrameIDs;

     getFrameIDs loops through all frames, which exist in the tag. It
     returns a hash reference with a list of all available Frame IDs. The
     keys of the returned hash are 4-character-codes (short names), the
     internal names of the frames, the according value is the english
     (long) name of the frame.

     You can use this list to iterate over all frames to get their data,
     or to check if a specific frame is included in the tag.

     If there are multiple occurences of a frame in one tag, the first
     frame is returned with its normal short name, following frames of
     this type get a '00', '01', '02', ... appended to this name. These
     names can then used with `getFrame' to get the information of these
     frames.

getFrame()
          ($info, $name) = getFrame($ID);
          ($info, $name) = getFrame($ID, 'raw');

     getFrame gets the contents of a specific frame, which must be
     specified by the 4-character-ID (aka short name). You can use
     `getFrameIDs' to get the IDs of the tag, or use IDs which you hope to
     find in the tag. If the ID is not found, getFrame returns (undef,
     undef).

     Otherwise it extracts the contents of the frame. Frames in ID3v2 tags
     can be very small, or complex and huge. That is the reason, that
     getFrame returns the frame data in two ways, depending on the tag.

     If it is a simple tag, with only one piece of data, this date is
     returned directly as ($info, $name), where $info is the text string,
     and $name is the long (english) name of the frame.

     If the frame consist of different pieces of data, $info is a hash
     reference, $name is again the long name of the frame.

     The hash, to which $info points, contains key/value pairs, where the
     key is always the name of the data, and the value is the data itself.

     If the name starts with a underscore (as eg '_code'), the data is
     probably binary data and not printable. If the name starts without an
     underscore, it should be a text string and printable.

     If there exists a second parameter like raw, the whole frame data is
     returned, but not the frame header. If the data was stored
     compressed, it is also in raw mode uncompressed before it is
     returned. Then $info contains a string with all data (which might be
     binary), and $name against the long frame name.

     See also `MP3::Tag::ID3v2-Data' in this node for a list of all
     supported frames, and some other explanations of the returned data
     structure.

     ! Encrypted frames are not supported yet !

     ! Some frames are not supported yet, but the most common ones are
     supported !

write_tag()
          $id3v2->write_tag;

     Saves a frame to the file. It tries to update the file in place, when
     the space of the old tag is big enoug for the new tag.  Otherwise it
     creates a temp file (i.e. copies the whole mp3 file) and
     renames/moves it to the original file name.

     An extended header with CRC checksum is not supported yet.

     At the moment the tag is automatically unsynchronized.

remove_tag()
          $id3v2->remove_tag();

     Removes the whole tag from the file by copying the whole mp3-file to
     a temp-file and renaming/moving that to the original filename.

add_frame()
          $fn = $id3v2->add_frame($fname, @data);

     Add a new frame, identified by the short name $fname.  The $data must
     consist from so much elements, as described in the ID3v2.3 standard.
     If there is need to give an encoding parameter and you would like
     standard ascii encoding, you can omit the parameter or set it to 0.
     Any other encoding is not supported yet, and thus ignored.

     It returns the the short name $fn, which can differ from $fname, when
     there existed already such a frame. If no other frame of this kind is
     allowed, an empty string is returned. Otherwise the name of the newly
     created frame is returned (which can have a 01 or 02 or ... appended).

     Data must be undef or equal to the number of fields of the tag.

     Examples:

          $f = add_frame("TIT2", 0, "Abba");   # $f="TIT2"
          $f = add_frame("TIT2", "Abba");      # $f="TIT201", encoding=0 implicit

          add_frame("COMM", "ENG", "Short text", "This is a comment");
          add_frame("COMM");                   # creates an empty frame
          $f = add_frame("COMM", "ENG");       # ! wrong ! $f=undef, becaues number
                                               # of arguments is wrong

change_frame()
          $id3v2->change_frame($fname, @data);

     Change an existing frame, which is identified by its short name
     $fname. @data must be same as in add_frame;

remove_frame()
          $id3v2->remove_frame($fname);

     Remove an existing frame. $fname is the short name of a frame, eg as
     returned by `getFrameIDs'.

supported_frames()
          $frames = $id3v2->supported_frames();

     Returns a hash reference with all supported frames. The keys of the
     hash are the short names of the supported frames, the according
     values are the long (english) names of the frames.

what_data()
          ($data, $res_inp) = $id3v2->what_data($fname);

     Returns an array reference with the needed data fields for a given
     frame.  At this moment only the internal field names are returned,
     without any additional information about the data format of this
     field. Names beginning with an underscore (normally '_data') can
     contain binary data.

     $resp_inp is a reference to an array, which contains information about
     a restriction for the content of the data field ( coresspodending to
     the same array field in the @$data array).  If the entry is undef, no
     restriction exists. Otherwise it is a hash.  The keys of the hash are
     the allowed input, the correspodending value is the value which
     should stored later in that field. If the value is undef then the key
     itself is valid for saving.  If the hash contains an entry with
     "_FREE", the hash contains only suggestions for the input, but other
     input is also allowed.

     Example for picture types of the APIC frame:

     `  {"Other" =' "\x00",    "32x32 pixels 'file icon' (PNG only)" =>
     "\x01",    "Other file icon" => "\x02",    ...}>

song()
     Returns the song title (TIT2) from the tag.

track()
     Returns the track number (TRCK) from the tag.

artist()
     Returns the artist name (TPE1 (or TPE2 if TPE1 doesn't exist)) from
     the tag.

album()
     Returns the album name (TALB) form the tag.

SEE ALSO
========

   See MP3/Tag, MP3/Tag/ID3v1,
`MP3::Tag::ID3v2-Data' in this node

   ID3v2 standard - http://www.id3.org

Edit ID3v1 Tags from an Audio MPEG Layer 3.
*******************************************

NAME
====

   MPEG::ID3v1Tag - Edit ID3v1 Tags from an Audio MPEG Layer 3.

SYNOPSIS
========

   use MP3::ID3v1Tag;

DESCRIPTION
===========

   This module is provided for backwards compatibility. Please migrate to
use MP3::ID3v1Tag

AUTHOR
======

   Sander van Zoest <svanzoest@cpan.org>

THANKS
======

   Matt Plummer <matt@mp3.com>, Mike Oliphant <oliphant@gtk.org>, Matt
DiMeo <mattd@mp3.com>, Olaf Maetzner, Jason Bodnar and Peter Johansson

COPYRIGHT
=========

   Copyright 1999-2000, Sander van Zoest, MP3.com, Inc. All rights
reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

REFERENCES
==========

   For general overview of MPEG 1, Layer 3 (MP3) Audio visit
http://www.mp3.com/

   For more specific references to the MP3 Audio ID3 Tags visit
http://www.id3.org/

   For information about ID3v2 and a perl implementation see MPEG::ID3v2Tag
written by Matt DiMeo <mattd@mp3.com>.

Parses and creates ID3v2 Tags for MPEG audio files.
***************************************************

NAME
====

   *MPEG::ID3v2Tag* - Parses and creates ID3v2 Tags for MPEG audio files.

SYNOPSIS
========

     use MPEG::ID3v2Tag ;
     use IO::File ;

     # create a tag
     $tag = MPEG::ID3v2Tag->new() ;
     $tag->add_frame("TIT2", "Happy Little Song") ;  # one step
     $frame = MPEG::ID3Frame::TALB->new("Happy little album") ;
     $tag->add_frame($frame) ;                       # two steps
     $tag->add_frame("WCOM", "http://www.mp3.com") ;
     $tag->add_frame("APIC", -picture_type => 0, -file => "happy_little_song.gif");
     .....
     $tag->set_padding_size(256) ;
     print OUTFILE $tag->as_string() ;

     # read a tag from a file and dump out some data.
     $fh = IO::File->new("<happysong.mp3") ;
     $tag = MPEG::ID3v2Tag->parse($fh) ;
     foreach $frame ($tag->frames()) {
       print $frame->frameid(), "\n" ;   # prints TALB, TIT2, WCOM, etc.
       if ($frame->flag_read_only()) {
         print "  read only\n" ;
       }
       if ($frame->fully_parsed() && $frame->frame_id =~ /^T.../) {
         print "  frame text is ", $frame->text(), "\n" ;
       }
       if ($frame->fully_parsed() && $frame->frame_id =~ /^W.../) {
         print "  url is ", $frame->url(), "\n" ;
       }
     }

DESCRIPTION
===========

   MPEG::ID3v2Tag is a class capable of parsing and creating ID3v2 revision
3 tags.  While not all frames are fully supported, it's easy to add
support for more.

   The object doesn't (currently) support modification of .mp3 files; the
caller has to handle the mechanics of prepending the tag to the file.

METHODS
=======

$tag = MPEG::ID3v2Tag->new()
     Creates a `MPEG::ID3v2Tag'.  Takes no parameters.

$arrayref = $tag->frames()
@array    = $tag->frames()
     Returns an array or arrayref containing all the MPEG::ID3Frame-derived
     objects from the tag.  See FRAME SUPPORT for details on what frames
     can do.

$tagdata = $tag->as_string
     Returns the complete tag, formatted as a binary string, ready to be
     slapped on the front of an .mp3 file.

$tag->set_padding_size($bytes)
     Sets the number of bytes of padding to add at the end of the tag.
     This will be added as zero bytes.  Also sets the extended_header flag
     if $bytes > 0.

$tag->add_frame($frame)
$tag->add_frame($frameid, [arguments])
     Adds a new frame to the end of the tag.  The first form takes an
     object derived from the class MPEG::ID3Frame and simply appends it to
     the list of frames.  The second will take a four-letter frame id code
     (TALB, RBUF, SYLT, etc.) and attempt to call the new() method of the
     class MPEG::ID3Frame::<frame_id> to create the frame to be added.
     The arguments to the constructor will be those passed to
     ->add_frame(), minus the frame id.  If there is no new method, it
     will die.

     For details on the arguments for supported frames, see the FRAME
     SUPPORT section.

@frames = $tag->get_frame(frame_id)
     Given a four-letter frame id, this method will search the tag's frames
     for all that match and return them.  If called in scalar context, it
     will return just the first one found, if any.

$tag->flag_unsynchronization([1|0])

$tag->flag_extended_header([1|0])

$tag->flag_experimental([1|0])
     These get and set the flags for the ID3v2 header.  If an argument is
     passed, the flag will be set to that value.  The current flag value
     is returned.

     If flag_unsynchronization is set when as_string() is called, the
     unsynchronization scheme will be applied to the data portion of the
     tag.

     If flag_extended_header is set when as_string() is called, an ID3v2
     Extended Header will be added.  This flag is set automatically when
     set_padding_size() is set to a non-zero value.

MPEG::ID3v2Tag->parse($filehandle)
     This method will construct a new tag by reading from a file containing
     an ID3v2 tag.  If there is no revision 3 tag in the file, undef is
     returned.

     Frame types for which a parse_data method has been written will be
     parsed individually, and (should) provide appropriate access methods
     to retrieve the data contained in the frame.

     All frame types, whether supported by a MPEG::ID3Frame subclass or
     not, will be read in and will be formatted appropriately when output
     with $tag->as_string().  You just won't be able to do anything with
     the data inside the tag unless a parser has been written.

     This method will read the tag and leave the filehandle's file pointer
     at the byte immediately following the tag.

     See FRAME SUPPORT for details about frames and their parsers.

$tag->dump()
     Dumps out the tag to the currently selected filehandle, for debugging
     purposes.

FRAME SUPPORT
=============

   Each ID3v2 frame type is implemented by its own class.  TALB is
implemented by MPEG::ID3Frame::TALB, OWNE is implemented by
MPEG::ID3Frame::OWNE, etc.

   Not all frames are currently implemented for writing, and not all
frames that are implemented for writing have parsers for reading.

   All frames support the following public methods, which they get from a
base class called MPEG::ID3Frame.

$id = $frame->frameid()
     Returns the four-letter frame id code for the frame.

$frame->fully_parsed()
     When a frame is read from an ID3v2 tag which has been parsed by
     MPEG::ID3v2Tag->parse(), actually parsing the data into a useful form
     may turn out to be impossible.  For example, the appropriate parser
     routine may not be implemented, or the tag may contain a flag
     demanding unimplemented functionality like encryption.

     This method can be used to determine whether the tag was parsed into
     its component bits.

     If this routine returns a false value, the reason the tag could not
     be parsed may be found in the $frame->{UNSUPPORTED_REASON} private
     variable.

     Note that even if a frame can't be parsed, it can still be retained
     in the tag when it is output with the $tag->as_string() method.  It
     will be output exactly as it appeared in the data stream when it was
     read in.

$frame->flag_tag_alter([1|0])

$frame->flag_file_alter([1|0])

$frame->flag_read_only([1|0])

$frame->flag_compression([1|0])

$frame->flag_encryption([1|0])

$frame->flag_grouping_identity([1|0])
     These functions get and/or set the flag bits from the frame header.
     See the ID3v2.3.0 informal standard for semantics.

     Note that encryption is not currently supported, and that attempting
     to create frames with these bits turned on may create bad headers.

     If you set the compression flag on a frame, this module will attempt
     to load the Compress::Zlib module to compress the frame, dying if the
     module can't be found.  When parsing a compressed frame,
     Compress::Zlib will be used if available.  If not, the frame will not
     be parsed (the fully_parsed method will tell you if a frame was
     successfully parsed, and $frame->{UNSUPPORTED_REASON} will give you a
     string telling you why), but no fatal errors will be generated.

$frame->dump()
     Dumps out some data from this frame.  This is generally overridden in
     subclasses to dump frame-specific data.

Support for specific frame types
--------------------------------

   In addition to the above methods, each individual supported frame will
have a new() constructor (which can be called directly, or implicitly by
$tag->add_frame()) and possibly access methods for the data contained in
the frame.  In the list below, the constructor is shown as a call to
$tag->add_frame(<tagname>, <arguments>), but remember you can call
MPEG::ID3Frame::TALB->new(<arguments>) and pass the return value to
add_frame.

TALB
TBPM
TCOM
.... and so on T???
     All these text information frames are supported:

     TALB TBPM TCOM TCON TCOP TDAT TDLY TENC TEXT TFLT TIME TIT1 TIT2 TIT3
     TKEY TLAN TLEN TMED TOAL TOFN TOLY TOPE TORY TOWN TPE1 TPE2 TPE3 TPE4
     TPOS TPUB TRCK TRDA TRSN TRSO TSIZ TSRC TSSE TYER

     The constructor is generally called like this:

     [$frame = ]$tag->add_frame(TALB, "text string", [optional_encoding]) ;

     You can get the encoding value with $frame->encoding() and the text
     string value with $frame->text().

     Parsing is implemented for these frames.

WCOM
WCOP
.... and so on  (W???)
     All url link frames are supported: WCOM WCOP WOAF WOAR WOAS WORS WPAY
     WPUB

     The constructor is generally called like this:

     [$frame = ]$tag->add_frame(WCOM, "text string", [optional_encoding]) ;

     You can read back the url with $frame->url().

UFID
     Call the constructor like this:

     [$frame = ]$tag->add_frame(UFID, $owner_idstring, $id) ;

     There is currently no parsing support.

USLT
     Call the constructor like this:

     $tag->add_frame(USLT, $encoding, $language, $content_descriptor,
     $lyrics) ;

     also supports parsing, and these access methods: encoding(),
     language(), content_descriptor(), and lyrics() ;

APIC
     This is one of the more complicated frames.

     The constructor is called as

     $tag->add_frame(APIC, [switches])

     where switches can be:

     -encoding => $encoding

     -mime[type] => $mime_type

     -picture_type => $picture_type

     -desc[ription] => $description

     -fh => $filehandle

     -fn[ame] => $filename

     -data => $data

     At least one of -fh, -fn, or -data must be provided.  -data takes the
     images as a binary string.  -fh provides an open filehandle on the
     image file, and -fn provides a file for reading.

     -mimetype must be provided also.  However, if -fname is used, and the
     filename ends in '.gif' or '.jpg', the mime type will be assumed
     'image/gif' or 'image/jpg'.

     There is currently no parsing support.

USER
     The constructor for the Terms of Use frame is called as

     $tag->add_frame("USER", $encoding, $language, $text) ;

     There is no parsing support.

COMM
     The constructor for the Comments frame is called as

     $tag->add_frame("COMM", $encoding, $language, $description, $text) ;

     There is no parsing support.

SUPPORTING NEW FRAMES
=====================

   Adding support for more frames is very simple.  In general, all you
need to do is copy and tweak one of the supported frames (USER is a nice
simple one to start from).

   Suppose we're adding support for frame XXXX.  Read the section about
XXXX in the ID3v2.3.0 spec, then...

   Create a new package MPEG::ID3Frame::XXXX.

   Derive it from MPEG::ID3Frame (put "MPEG::ID3Frame" in its @ISA array).

   create a subroutine/method called frameid() that just returns "XXXX".

   create a constructor called new(), which takes whatever arguments you
will need.

   create a data_as_string method to construct the frame based on the
ID3v2.3.0 spec.  pack() is helpful, here.

   Optionally, create access methods for the data you passed in in your
constructor.

   Optionally, create a parse_data method which takes the data portion of
the frame and parses out the data so your access methods can access them.
If your parser finds it can't parse the body data, it should set
$self->{UNSUPPORTED_BODY} to the string passed in, and
$self->{UNSUPPORTED_REASON} to a short string giving the reason it failed.

   Optionally, create a dump() method.

   Make sure that you get the same answer if you write out the frame, read
it in, and write it out again.

BUGS
====

   Creating tags with encryption will probably explode.

   Encrypted tags can't be parsed.  They can be read in and written back
out, however.

   UNICODE character encodings will currently fail on input or output.

   No support for modifying .mp3 files.

   Many frame types unimplemented.

   Most frame types don't have parsers.

Manipulate / fetch info from MP3 audio files
********************************************

NAME
====

   MPEG::MP3Info - Manipulate / fetch info from MP3 audio files

SYNOPSIS
========

     use MP3::Info;

DESCRIPTION
===========

   This is just a wrapper around MP3::Info now.

AUTHOR AND COPYRIGHT
====================

   Chris Nandor <pudge@pobox.com>, http://pudge.net/

   Copyright (c) 1998-2001 Chris Nandor.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the terms of the Artistic License, distributed with Perl.

SEE ALSO
========

   MP3::Info

VERSION
=======

   v0.90, Sunday, January 14, 2001

Perl extension for MQSeries support
***********************************

NAME
====

   MQSeries - Perl extension for MQSeries support

SYNOPSIS
========

   There are two interfaces provided by the MQSeries modules.  The first
is a straight forward mapping to all of the individual MQI calls, and the
second is a value-added, OO interface, which provides a simpler interface
to a subset of the full MQI functionality.

   The straight MQI mapping is:

     use MQSeries;

     $Hconn = MQCONN($Name,$CompCode,$Reason);
     MQDISC($Hconn,$CompCode,$Reason);

     $Hobj = MQOPEN($Hconn,$ObjDesc,$Options,$CompCode,$Reason);
     MQCLOSE($Hconn,$Hobj,$Options,$CompCode,$Reason);

     MQBACK($Hconn,$CompCode,$Reason);
     MQCMIT($Hconn,$CompCode,$Reason);

     $Buffer = MQGET($Hconn,$Hobj,$MsgDesc,$GetMsgOpts,$BufferLength,$CompCode,$Reason);
     MQPUT($Hconn,$Hobj,$MsgDesc,%PutMsgOpts,$Msg,$CompCode,$Reason);
     MQPUT1($Hconn,$ObjDesc,$MsgDesc,$PutMsgOpts,$Msg,$CompCode,$Reason);

     ($Attr1,...) = MQINQ($Hconn,$Hobj,$CompCode,$Reason,$Selector1,...);
     MQSET($Hconn,$Hobj,$CompCode,$Reason,$Selector1,$Attr1,...);

   If the perl5 API is compiled with the version 5 headers and libraries,
then the following MQI calls are also available:

     MQBEGIN($Hconn,$BeginOpts,$CompCode,$Reason);
     $Hconn = MQCONNX($Name,$ConnectOpts,$CompCode,$Reason);

   There are also some additional utility routines provided which are not
part of the MQI, but specific to the perl5 API:

     ($ReasonText,$ReasonMacro) = MQReasonToStrings($Reason);
     ($ReasonText) = MQReasonToText($Reason);
     ($ReasonMacro) = MQReasonToMacro($Reason);

   The OO interface is provided in several optional modules.  Three of
these make up the core OO interface:

     MQSeries::QueueManager
     MQSeries::Queue
     MQSeries::Message

   There are several subclasses of MQSeries::Message which handle special
message formats:

     MQSeries::Message::Storable
     MQSeries::Message::Event
     MQSeries::Message::PCF
     MQSeries::Message::RulesFormat
     MQSeries::Message::XML-Dumper
     MQSeries::Message::DeadLetter

   There is also a set of modules which provide an interface to the
optional Publish/Subscribe system, which is available as a support pack
for the distributed platforms using Version 5 of MQSeries.

     MQSeries::PubSub::Broker
     MQSeries::PubSub::Stream
     MQSeries::PubSub::Command (docs only, not used directly)
     MQSeries::PubSub::Message
     MQSeries::PubSub::AdminMessage

   There is also a module which provides an interface to the command
server PCF messages for MQSeries administration:

     MQSeries::Command

   There are two sets of classes that help you follow (tail -f style) and
parse the two kinds of log-files written by MQSeries: the FDC files and
the error-logs.  These classes allow you to write a log monitoring daemon
that feeds into syslog or your system management tools.

     MQSeries::ErrorLog::Tail
     MQSeries::ErrorLog::Parser
     MQSeries::ErrorLog::Entry
     MQSeries::FDC::Tail
     MQSeries::FDC::Parser
     MQSeries::FDC::Entry

   There is a set of classes that parses configuration and authority files
(/var/mqm/mqs.ini, /var/mqm/qmgrs/*/qm.ini, /var/mqm/qmgrs/*/auth/*/*).

     MQSeries::Config::Authority
     MQSeries::Config::Machine
     MQSeries::Config::QMgr

   Some internal helper functions are stored in the module:

     MQSeries::Utils

   See the documentation for each of these individual modules for more
information.

DESCRIPTION
===========

   This module provides a perl language interface to MQSeries functions.
It uses the standard MQSeries interface except where a perl convention is
required or just more useful.

   Where data structures are required, this interface uses a hash
reference. The keys in the hash are structure element names. If an element
is not specified in the hash, a default value will be used. Output
elements are updated in the hash as necessary.

SUBROUTINES
===========

   For complete details on each of the following subroutines, please
consult the "MQSeries Application Programming Guide" and "MQSeries
Application Programming Reference".  This documentation will merely
document how the perl API and the underlying C API calling and return code
conventions vary.

   One way in which all of these calls are identical to the C API is in
the use of the '$CompCode' and '$Reason' conventions.  All of the API
calls take these as positional arguments, and the completion code and
reason code are written to those variables, respecitively.

   In general, all of the C data structures used to pass or return values
to each API call are passed or returned as a perl hash reference,
specified as a positional argument in the relavent API call.

MQCONN
------

     $Hconn = MQCONN($Name,$CompCode,$Reason);

   This call returns the Hconn value, to be used in subsequent MQI calls.
The C API took the $Hconn as a positional parameter, whereas the perl API
returns it.

MQCONNX
-------

     $Hconn = MQCONNX($Name,$ConnectOpts,$CompCode,$Reason);

   NOTE: This MQI call is only available if the perl5 API is compiled
against MQSeries version 5 headers and libraries.

   This call returns the Hconn value, to be used in subsequent MQI calls.
The C API took the $Hconn as a positional parameter, whereas the perl API
returns it.

   The $ConnectOpts value is a hash reference, with keys corresponding to
the fields of the MQCO structure.  This is an input value only.

MQDISC
------

     MQDISC($Hconn,$CompCode,$Reason);

   The calling convention of this subroutine is identical to the C API.

MQOPEN
------

     $Hobj = MQOPEN($Hconn,$ObjDesc,$Options,$CompCode,$Reason);

   In the same way that MQCONN loses one positional parameter, and returns
it to the caller, so does MQOPEN remove the $Hobj parameter from the
argument list and returns the value.

   The $ObjDesc parameter should be a hash reference, for example:

     $ObjDesc = {
                 ObjectName 	=> 'SOME.MODEL.QUEUE',
                 DynamicQName 	=> 'FOOBAR*',
                };

   The $Options parameter should be a set of ORed options, for example:

     $Options = MQOO_INPUT_AS_Q_DEF | MQOO_FAIL_IF_QUIESCING;

   If a distribution list is being opened, then the list of queues can be
specified in one of three ways.  The list is given via a new key
"ObjectRecs", used to identify the list.  This is different from the
C-centric approach in the C API, namely to specify the list using the
RecsPresent, ObjectRecPtr, etc.

   The first method is to specify an array of plain queue names:

     $ObjDesc = {
                 ObjectRecs	=> [qw( QUEUE1 QUEUE2 QUEUE3 )],
                };

   The second method is to specify an array or array references, each
giving the QName and QMgrName:

     $ObjDesc = {
                 ObjectRecs	=> [
                                       [qw( QUEUE1 QM1 )],
                                       [qw( QUEUE2 QM2 )],
                                       [qw( QUEUE3 QM3 )],
                                      ],
                };

   Finally, an array of hash references can be specified, each giving the
QName and QMgrName via specific keys:

     $ObjDesc = {
                 ObjectRecs	=> [
                                       {
                                        ObjectName		=> 'QUEUE1',
                                        ObjectQMgrName	=> 'QM1',
                                       },
                                       {
                                        ObjectName		=> 'QUEUE2',
                                        ObjectQMgrName	=> 'QM2',
                                       },
                                       {
                                        ObjectName		=> 'QUEUE3',
                                        ObjectQMgrName	=> 'QM3',
                                       },
                                      ],
                };

   In the second and third cases, the queue manager names are always
optional.  Which method to use is largely a matter of style.

   When the Reason Code returned by the API is MQRC_MULTIPLE_REASONS, then
these are encoded into an array of hash references, and that array is
returned as a new key in the ObjDesc hash, "ResponseRecs".  The order of
the CompCode/Reason pair in the array corresponds to the order of the
queues listed in the ObjectRecs array.

   This is best explained in an example.  In this case, we used the first,
simple list of queue names for our distribution list.

     if ( $Reason == MQRC_MULTIPLE_REASONS ) {
         for ( $index = 0 ; $index <= scalar @{$ObjDesc->{ObjectRecs}} ; $index++ ) {
             next if $ObjDesc->{ResponseRecs}->[$index]->{Reason} == MQRC_NONE;
             print "QName: " . $ObjDesc->{ObjectRecs}->[$index] . "\n";
             print "Reason: " . $ObjDesc->{ResponseRecs}->[$index]->{Reason} . "\n";
             print "CompCode: " . $ObjDesc->{ResponseRecs}->[$index]->{CompCode} . "\n";
         }
     }

MQCLOSE
-------

     MQCLOSE($Hconn,$Hobj,$Options,$CompCode,$Reason);

   The calling convention of this subroutine is identical to the C API.

   The $Options value is a set of ORed options, for example:

     $Options = MQCO_DELETE_PURGE;

MQBEGIN
-------

     MQBEGIN($Hconn,$BeginOpts,$CompCode,$Reason)

   NOTE: This MQI call is only available if the perl5 API is compiled
against MQSeries version 5 headers and libraries.

   The calling convention of this subroutine is identical to the C API.

   The $BeginOpts value is a hash reference, with keys corresponding to
the fields of the MQBO structure.  This is both an input and output value.

MQBACK
------

     MQBACK($Hconn,$CompCode,$Reason);

   The calling convention of this subroutine is identical to the C API.

MQCMIT
------

     MQCMIT($Hconn,$CompCode,$Reason);

   The calling convention of this subroutine is identical to the C API.

MQGET
-----

     $Buffer = MQGET($Hconn,$Hobj,$MsgDesc,$GetMsgOpts,$BufferLength,$CompCode,$Reason);

   One positional parameter, the $Buffer, is removed from the argument
list.  This is the return value of this subroutine.  The $MsgDesc and
$GetMsgOpts values are hash references.  The $MsgDesc will be populated
with the MQMD structure returned by the MQGET call.  This is also an input
value, and the $MsgDesc data can be populated, for example, with a
specific 'CorrelId'.

     $MsgDesc = {
                 CorrelId => $correlid,
                };

   The $GetMsgOpts hash reference contains the MQGMO data structure
fields, for example:

     $GetMsgOpts = {
                    Options => MQGMO_FAIL_IF_QUIESCING | MQGMO_SYNCPOINT | MQGMO_WAIT,
                    WaitInterval => MQWI_UNLIMITED,
                   };

MQPUT, MQPUT1
-------------

     MQPUT($Hconn,$Hobj,$MsgDesc,$PutMsgOpts,$Msg,$CompCode,$Reason);
     MQPUT1($Hconn,$ObjDesc,$MsgDesc,$PutMsgOpts,$Msg,$CompCode,$Reason);

   Both of these calls differ from the C API in the same way as MQGET.
Likewise, the $MsgDesc and $PutMsgOpts values are hash references for the
appropriate data structures.

   If MQPUT1() is being used to put a message to a distribution list, then
the $ObjDesc is used in the same way as documented above for MQOPEN().  In
addition, there is a special key to the $PutMsgOpts hash which can be
specified, and the rest of this discussion applies equally to both MQPUT()
and MQPUT1().

   The $PutMsgOpts->{PutMsgRecs} value must be an array of hash
references, one for each queue opened in the distribution list,
interpreted in the same order.  Each individual hash reference is
interpreted as a single put message record.  The keys of each record can
be any of:

     MsgId
     CorrelId
     GroupId
     Feedback
     AccountingToken

   For example, the following sets the CorrelId the same across all of the
messages in a distribution list of three queues.

     $PutMsgOpts = {
                    PutMsgRecs => [
                                   {
                                    MsgId		=> MQPMO_NEW_MSG_ID,
                                    CorrelId       => $SomeCorrelId,
                                   },
                                   {
                                    MsgId		=> MQPMO_NEW_MSG_ID,
                                    CorrelId       => $SomeCorrelId,
                                   },
                                   {
                                    MsgId		=> MQPMO_NEW_MSG_ID,
                                    CorrelId       => $SomeCorrelId,
                                   },
                                  ],
                   };

   Note that the following fields of the $PutMsgOpts hash do not need to
be specified:

     PutMsgRecFields (calculated automatically)
     PutMsgRecOffset
     PutMsgRecPtr
     ResponseRecPtr
     ResponseRecOffset

   For the MQPUT() call, if the Reason code returned is
MQRC_MULTIPLE_REASONS, then these are returned as part of the $PutMsgOpts
hash, in the key ResponseRecs.  For the MQPUT1() call, these are returned
as part of the $ObjDesc hash.

   See the MQOPEN() documentation above for the format of this value.

MQINQ
-----

     ($Attr1,...) = MQINQ($Hconn,$Hobj,$CompCode,$Reason,$Selector1,...);

   This call differs from the C API significantly.  Rather than passing a
list of pairs of selectors and attributes, only a list of selectors is
passed.  The return value is a list of attributed.  The C API convention
was simply to pass the address for each answer in the arguments, but in
perl, it makes more sense to return this as a list.

MQSET
-----

     MQSET($Hconn,$Hobj,$CompCode,$Reason,$Selector1,$Attr1,...);

   This call also differs from the C API significantly.  The C API took a
pointer to an array of selectors, with an argument indicating the length
of the array, and a similar pair of values for the attribute values
themselves.  The perl convention is to list the selectors and attributes
in pairs, rather than by passing in an array reference.

MQParseEvent (deprecated in 1.06)
---------------------------------

   This routine has been deprecated, and is no longer supported.  The next
release will remove it from the documentation altogether.

   Equivalent functionality is available via the MQDecodePCF subroutine,
which is optionally exported from the MQSeries::Message::PCF module.

   The author highly recommends using the OO abstraction via
MQSeries::Message::Event, and interface which is supported and will remain
part of this API permanently.

MQReasonToStrings
-----------------

     ($ReasonText,$ReasonMacro) = MQReasonToStrings($Reason);

   This subroutine is specific to the perl API, although similar
functionality is desperately needed in the other programming languages as
well.  This takes an MQSeries Reason code, and returns the English
language text explaining the reason code, and the macro name.  These
strings are compiled into the perl module, encoded in the XS routines,
after having been extracted from the IBM HTML documentation.

   For example, a reason code of 2009 (MQRC_CONNECTION_BROKEN) will return:

     "Connection to queue manager lost."

   which looks a lot better in error logs and alerts than 2009.

   The macro name itself is also returned as a string, so one could use
"MQRC_CONNECTION_BROKEN" in logs, error messages, etc.

   In this release, only English language text is returned, but in a
future release, these messages will be locale specific.  This will almost
certainly be implemented with locale-specific DBM files, but you probably
do not need to know this just yet....

MQReasonToText
--------------

     ($ReasonText) = MQReasonToText($Reason);

   This is nothing more than a trivial interface to MQReasonToStrings,
returning just the one value (the reason text).

MQReasonToMacro
---------------

     ($ReasonMacro) = MQReasonToMacro($Reason);

   This is nothing more than a trivial interface to MQReasonToStrings,
returning just the one value (the MQRC_* macro as a string).

OO interface to the Programmable Commands
*****************************************

NAME
====

   MQSeries::Command - OO interface to the Programmable Commands

SYNOPSIS
========

     use MQSeries;
     use MQSeries::Command;

     #
     # Simplest usage
     #
     my $command = MQSeries::Command->new
       (
        QueueManager => 'some.queue.manager',
       )
       or die("Unable to instantiate command object\n");

     @qnames = $command->InquireQueueNames()
       or die "Unable to list queue names\n";

     foreach my $qname ( @qnames ) {

     $attr = $command->InquireQueue
     	(
     	 QName		=> $qname,
     	 QAttrs		=> [qw(
     			       OpenInputCount
     			       OpenOutputCount
     			       CurrentQDepth
     			      )],
     	) or die "InquireQueue: " . MQReasonToText($command->Reason()) . "\n";

     print "QName = $qname\n";

     foreach my $key ( sort keys %$attr ) {
     	  print "\t$key => $attr->{$key}\n";
     }

     }

     #
     # High-level wrapper method: CreateObject
     #
     $command->CreateObject
       (
        Attrs		=>
        {
         QName		=> 'FOO.BAR.REQUEST',
         QType		=> 'Local',
         MaxQDepth		=> '50000',
         MaxMsgLength	=> '20000',
        }
       ) || die "CreateObject: " . MQReasonToText($command->Reason()) . "\n";

     $command->CreateObject
       (
        Clear		=> 1,
        Attrs		=>
        {
         QName		=> 'FOO.BAR.REPLY',
         QType		=> 'Remote',
         RemoteQName	=> 'FOO.BAR.REPLY',
         RemoteQMgrName	=> 'SAT1',
        }
       ) || die "CreateObject: " . MQReasonToText($command->Reason()) . "\n";

DESCRIPTION
===========

   The MQSeries::Command class implements an interface to the Programmable
Command Format messages documented in the:

     "MQSeries Programmable System Management"

   section of the MQSeries documentation.  In particular, this document
will primarily explain how to interpret the above documentation, and thus
use this particular implementation in perl.  Please read and understand
the following sections of the above document:

     Part 2. Programmable Command Formats
       Chapter 8. Definitions of the Programmable Command Formats
       Chapter 9. Structures used for commands and responses

   This interface also supports the text-based MQSC format messages used
by the queue manager of some platforms, particularly MVS.  Using the same
interface, either PCF or MQSC command server can be queried, with the
results translated into the same format for responses as well.  Note that
there are limits to how transparent this is (see MQSC NOTES), but the code
tries quite hard to hide as many of the differences as possible.

COMMAND ARGUMENTS
-----------------

   Before we discuss the specific arguments and return values of each of
the methods supported by the MQSeries::Command module, we must explain how
the keys and values used by the interface were chosen, as this will allow
the developer to understand how to take advantage of the very complete
documentation provided by IBM (which will not be reproduced here).

   For each command documented in 'Definitions of the Programmable Command
Formats' (there is a specific page listing all of the commands, grouped by
type), there is a corresponding method in this class.  For example, there
is a method named 'InquireQueueManager', for the obvious (I hope) PCF
command.

   All of these methods take a hash of key/value pairs as an argument,
with the keys being those defined in the documentation for each command.
When writing C code to produce PCF messages, the parameter names are
macros, such as:

     MQIACF_Q_MGR_ATTRS

   to specify a list of queue manager attributes.  Rather than use these
names directly, the key strings are taken from the IBM documentation.  In
this example, the string used for this key is:

     QMgrAttrs

   The values depend on the structure type of the parameter.  If the
structure is a string (MQCFST) or an integer (MQCFIN) then the value of
the key is simply a scalar string or integer in perl.  If it either a
string list (MQCFSL) or an integer list (MQCFIL), then the value of the
key is an array reference (see the InquireQueueManager example in the
SYNOPSIS) of scalar strings or integers.

RETURN VALUES
-------------

   Most of the individual methods map to underlying commands which do not
return any data.  For all of these, the return value is simply Boolean;
true or false.  That is, the command either worked or failed.

   Only the methods associated with those commands documented as producing
data responses:

     Escape
     Inquire Channel
     Inquire Channel Names
     Inquire Channel Status
     Inquire Cluster Queue Manager
     Inquire Namelist
     Inquire Namelist Names
     Inquire Process
     Inquire Process Names
     Inquire Queue
     Inquire Queue Manager
     Inquire Queue Names
     Reset Queue Statistics

   return interesting information.  Most of these will return an array of
hash references, one for each object matching the query criteria.  For
example.  The specific keys are documented in the section of the IBM
documentation which discusses the "Data responses to commands", on the
summary page "PCF commands and responses in groups".  If you have read the
IBM documentation as requested above, you should have found this page.

   Note that in an array context, the entire list is returned, but in a
scalar context, only the first item in the list is returned.

   Four of these commands, however, have a simplified return value.  All
four of:

     Inquire Channel Names
     Inquire Namelist Names
     Inquire Process Names
     Inquire Queue Names

   simply return an array of strings, containing the names which matched
the query criteria.

METHODS
=======

new
---

   The arguments to the constructor are a hash, with the following
key/value pairs:

     Key                Value
     ===                =====
     QueueManager       String or MQSeries::QueueManager object
     ProxyQueueManager  String or MQSeries::QueueManager object
     ReplyToQ           String or MQSeries::Queue object
     CommandQueueName   String
     DynamicQName       String
     ModelQName	     String
     Type               String ("PCF" or "MQCS")
     Expiry	     Numeric
     Wait               Numeric
     ReplyToQMgr        String
     Carp               CODE Reference
     StrictMapping      Boolean
     CompCode           Reference to Scalar Variable
     Reason             Reference to Scalar Variable

QueueManager
     The name of the QueueManager (or alternatively, a previously
     instantiated MQSeries::QueueManager object) to which commands are to
     be sent.

     This can be omitted, in which case the "default queue manager" is
     therefore assumed.

ProxyQueueManager
     The name of the queue manager to which to MQCONN(), and submit
     messages on the QueueManagers behalf.  This is to be used if a direct
     connection to the QueueManager is not possible, for example MVS queue
     managers with support for direct client access.

     The messages will be put to what is assumed to be a remote queue
     definition which routes to the command queue on the desired
     QueueManager.

     In order to specify the "default" queue manager as the
     ProxyQueueManager, an empty string must be explicitly given.

ReplyToQ
     The ReplyToQ can be opened by the application, and the MQSeries::Queue
     object passed in to the MQSeries::Command constructor, if so desired,
     os, a fixed queue name can be given.  This is a somewhat advanced
     usage of the API, since the default behavior of opening a temporary
     dynamic queue under the covers is usually prefered, and much simpler.

     The responses are retreived from the reply queue using gets by
     CorrelId, so there should be no issue with using a pre-defined, shared
     queue for this, if so desired.

CommandQueueName
     This specifies the queue to which the command messages will be put.
     The defaults are usually reasonable, and depend on the command message
     Type (PCF or MQSC).

          PCF   => SYSTEM.ADMIN.COMMAND.QUEUE
          MQSC  => SYSTEM.COMMAND.INPUT

     If the ProxyQueueManager has been specified, then we assume the
     messages are being written to a remote queue definition, and the
     defaults are then:

          PCF   => SYSTEM.ADMIN.COMMAND.QUEUE."QueueManager"
          MQSC  => SYSTEM.COMMAND.INPUT."QueueManager"

     See "MQSC NOTES" for some examples of how to use this in practice.

Type
     This argument indicates whether the command server on the QueueManager
     supports either PCF or MQSC messages.  The default is PCF.  See the
     section "MQSC NOTES" for the Ugly Truth about the MQSC support.

Expiry
     This value is used as the MQMD.Expiry field on all requests sent to
     the command server.  The value is passed to the MQSeries::Message
     constructor, and should specify the time in *tenths of a second*.
     The default is 600, or 60 seconds.

     A symbolic value ending on 's' for seconds or 'm' for minutes may
     also be specified, e.g. the symbolic value '45s' will have the same
     meaning as the number 450.

Wait
     This value is used as the Wait argument to the MQSeries::Queue->Get()
     method call made against the ReplyToQ (a dynamic reply queue). and
     should be a time specified in *milliseconds*.  The default is 60000,
     or 60 seconds.

     A symbolic value ending on 's' for seconds or 'm' for minutes may
     also be specified, e.g. the symbolic value '45s' will have the same
     meaning as the number 45000.

     NOTE: Both the Expiry and Wait defaults may be too slow for heavily
     loaded queue managers.  Tune them appropriately.

ReplyToQMgr
     The ReplyToQMgr normally defaults to the QueueManager, but it can be
     overridden, perhaps as a means of specifying an alternate return path
     over a specific channel.  For example, the author uses special
     channels for SYSTEM related traffic, over which we forward MQSeries
     events from one queue manager to another, and also over which we wish
     the command server queries to flow.

     The "default" path between QMA and QMB flows over a channel called
     QMA.QMB, but this traffic is application data, not administrative
     system data.  The system queries flow over QMA.QMB.SYSTEM, and we need
     to ensure that replies to queries follow a similar reverse path.
     Specifying the ReplyToQMgr as "QMB.SYSTEM" accomplishes this.

Carp
     This key specifies a code reference to a routine to replace all of the
     carp() calls in the API, allowing the user of the API to trap and
     handle all of the error message generated internally, or simply
     redirect how they get logged.

     For example, one might want everything to be logged via syslog:

          sub MyLogger {
              my $message = @_;
              foreach my $line ( split(/\n+/,$message) ) {
                  syslog("err",$message);
              }
          }

     Then, one tells the object to use this routine:

          my $command = MQSeries::Command->new(
          				       QueueManager => 'some.queue.manager',
          				       Carp => \&MyLogger,
          				      )
              or die("Unable to connect to queue manager.\n");

     The default, as one might guess, is Carp::carp();

StrictMapping
     If this argument has a true value, then strict mapping of PCF
     parameters and values will be enforced.  Normally, if you feed a bogus
     string into the API, it will attempt to map it to the underlying PCF
     macro value, and if the mapping fails, it will quietly forgive you,
     and ignore the parameter.  Enabling this feature will cause the
     translation of an encoded PCF message into the data structure for a
     Response, or the translation of a Request into an encoded PCF message,
     to fail if any of the mappings fail.

     Usually, the command server will generate errors if you feed bogus
     data into the API. but that will only occur after the data has been
     encoded and sent to the command server.  This feature will allow you
     to detect this error before the data is ever sent.

CompCode
     Normally the CompCode and Reason are access via the methods of the
     same name.  However, that obviously is not possible if the constructor
     fails.  If you want to perform special handling of the error codes in
     this case, you will have tell the constructor where to write the
     CompCode and Reason, by providing a SCALAR reference.

     For example:

          my $CompCode = MQCC_FAILED;
          my $Reason   = MQRC_NONE;

          my $command = MQSeries::Command->new
            (
             QueueManager => 'some.queue.manager',
             CompCode     => \$CompCode,
             Reason       => \$Reason,
            );

     Now, the CompCode and Reason are available, even if the constructor
     fails, in which case it would normally return nothing.

Reason
     See CompCode above.

CompCode
--------

   This method will return the MQI CompCode for the most recent MQI call
made by the API.

Reason
------

   This method will return the MQI Reason for the most recent MQI call
made by the API.

Responses
---------

   Normally, the data of interest is returned from the method in question,
but the individual responses are available via this method.  This returns
a list of MQSeries::Command::Response objects, one for each individual
message recieved.

   NOTE: In previous releases, this method was named "Response", but due
to a namespace conflict between the class "MQSeries::Command::Response",
and the method "MQSeries::Command->Response", and the headaches this
causes, it has been renamed.

DataParameters
--------------

   This method will return a list of parameters structures from all of the
responses messages sent back which were not error responses.  Some errors
will send back responses with parameters, and these could easily be
confused with real data (until you start looking at the actual data, of
course).

ErrorParameters
---------------

   This method will return a list of parameters structures from all of the
responses messages sent back which *were* error responses.  If a command
fails, the Reason() will usually tell you enough about the cause of the
failure, but if the reason is MQRCCF_CFIN_PARM_ID_ERROR, then the
parameters in the error message will indicate which Parameter key was
invalid.

CreateObject
------------

   This is a generic "wrapper" method for creating any generic MQSeries
object.  The arguments to this method are a hash, with the following
key/value pairs:

     Key                Value
     ===                =====
     Attrs		     HASH reference
     Verify	     Boolean
     Clear              Boolean
     Quiet              Boolean

   The key/value pairs in the Attrs argument are passed directly to the
corresponding CreateQueue(), CreateChannel(), or CreateProcess() method.
However, there is more to this than just creating the object.  For
clarity, this discussion will use creation of a queue as an example.

   First, InquireQueue is called to see if the object already exists.  If
it does not exist, then the object is simply created, with the specified
attributes.

   If it does exist, and the QType matches, then the actual object
attributes are compared against those passed to the CreateObject method,
and if they match, then no action is taken, and the object is not modified.

   If it does exist, but of a different QType, then the existing object is
deleted, and the new object created as requested.

   The idea here is to match the modification of the object conditional on
the need for modifying the object.  If the same CreateObject method call,
with the same arguments, is called twice, then the second method
invocation should be a noop, as far as the actual MQSeries object is
concerned.

Attrs
     As discussed above, this is a HASH reference, whose key/value pairs
     are used to determine what type of object is being created or updated,
     and those key/value pairs are passed as-is to the appropriate Create*
     method call for the specified MQSeries object type.

Verify
     If this key has a true value, then no changes will actually be
     implemented.  They will merely be reported via test messages on
     stdout.

Quiet
     CreateObject is by default rather chatty about what it is doing, but
     all of the messages, other than errors, can be suppressed if this key
     has a true value.

Clear
     Normally, when a Local queue is being replaced with another QType
     (eg. Remote or Alias), then the Local queue is not cleared before
     being deleted.  If there are messages on the queue, this will cause an
     error.  If the queue needs to be cleared, then this key must be passed
     with a true value.

     This is a seperate option due to the inherit danger of destroying data
     accidentally.  If you really want to clear the queues before
     recreating them as another QType, you will have to be explicitl about
     it.

COMMAND REQUESTS
================

   This section is *NOT* intended to replace the IBM "MQSeries
Programmable System Management" documentation, and it merely serves to
document the specific keys and values used by the perl implementation of
the API.

   In all cases, the keys which can be passed to the command are identical
to the strings found in the documentation.  However, some of the values
also have more convenient string mapping as well, as these are not easily
intuited by reading IBMs docs, thus these are clarified here.

   The IBM docs list the possible values for each key as a list of
MQSeries C macros (eg. MQCHT_SENDER), and if given, these will be
respected.  It will be faster to use the strings given, since these map
directly to the actual macro values via a hash lookup, rather than a
function call (all of the various C macros are implemented as function
calls via an AUTOLOAD).  Also, the author finds the replacement strings
far more readable.  YMMV.

   For each key shown, the format of value is one of the following:

(string)
     The value given must be a scalar value, interpretable as a text
     string.

(string list)
     The value must be an ARRAY reference of scalar values, all of which
     must be interpretable as strings.

     NOTE: Some of the parameters (for example, the MsgExit parameter for
     the various Channel commands) can take either a string or string list.
     In this case, the API will be forgiving, and try to determine what you
     meant automatically.  If you pass a reference, it will create a string
     list parameter, and if you pass a plain scalar, it will create a
     string.

     ANOTHER NOTE: if you pass a simple scalar string where a string list
     is explicitly required (as opposed to optional), then the API will
     create a list of one string for you.

(integer)
     The value given must be a scalar value, interpretable as an integer.
     In some cases, a table will show a mapping from more readable text
     strings to the macros documented in the IBM manuals.

(integer list)
     The value must be an ARRAY reference of scalar values, all of which
     must be interpretable as integers.  As with the integer format, in
     some cases, a table will show a mapping from more readable text
     strings to the macros documented in the IBM manuals.

(Boolean)
     The value given need only be 0 or 1.  This was done for some of the
     integer types which are documented to take a pair of macros, whose
     values were simply zero or one, and when the true/false nature of the
     key was considered to be intiuitive.  For example, "DataConversion" is
     either on (true) or off (false).

   In order to reduce needless redundancy, only the keys which have
special value mappings, or which have Boolean values will be listed here.
For all others, the IBM documentation is sufficient.

Channel Commands
----------------

   Subsets of the these keys are applicable to the following commands.
See the documentation for each of the for the specific list.

     Change Channel
     Copy Channel
     Create Channel
     Delete Channel
     Inquire Channel
     Inquire Channel Names
     Inquire Channel Status
     Ping Channel
     Reset Channel
     Resolve Channel
     Start Channel
     Start Channel Initiator
     Start Channel Listener
     Stop Channel

   The following keys have special value mappings:

ChannelType 		(integer)
          Key				Macro
          ===				=====
          Clntconn                    MQCHT_CLNTCONN
          ClusterReceiver             MQCHT_CLUSRCVR
          ClusterSender               MQCHT_CLUSSDR
          Receiver                    MQCHT_RECEIVER
          Requester                   MQCHT_REQUESTER
          Sender                      MQCHT_SENDER
          Server                      MQCHT_SERVER
          Svrconn                     MQCHT_SVRCONN

TransportType		(integer)
          Key				Macro
          ===				=====
          DECnet                      MQXPT_DECNET
          LU62                        MQXPT_LU62
          NetBIOS                     MQXPT_NETBIOS
          SPX                         MQXPT_SPX
          TCP                         MQXPT_TCP
          UDP                         MQXPT_UDP

PutAuthority 		(integer)
          Key				Macro
          ===				=====
          Context                     MQPA_CONTEXT
          Default                     MQPA_DEFAULT

MCAType 			(integer)
          Key				Macro
          ===				=====
          Process                     MQMCAT_PROCESS
          Thread                      MQMCAT_THREAD

NonPersistentMsgSpeed	(integer)
          Key				Macro
          ===				=====
          Normal                      MQNPMS_NORMAL
          Fast                        MQNPMS_FAST

ChannelTable		(integer)
          Key				Macro
          ===				=====
          Clntconn                    MQCHTAB_CLNTCONN
          QMgr                        MQCHTAB_Q_MGR

ChannelInstanceAttrs	(integer list)
     Same as ChannelAttrs:

ChannelAttrs		(integer list)
          Key				Macro
          ===				=====
          All                         MQIACF_ALL
          AlterationDate              MQCA_ALTERATION_DATE
          AlterationTime              MQCA_ALTERATION_TIME
          BatchInterval               MQIACH_BATCH_INTERVAL
          BatchSize                   MQIACH_BATCH_SIZE
          Batches                     MQIACH_BATCHES
          BuffersReceived             MQIACH_BUFFERS_RCVD
          BuffersSent                 MQIACH_BUFFERS_SENT
          BytesReceived               MQIACH_BYTES_RCVD
          BytesSent                   MQIACH_BYTES_SENT
          ChannelDesc                 MQCACH_DESC
          ChannelInstanceType         MQIACH_CHANNEL_INSTANCE_TYPE
          ChannelName                 MQCACH_CHANNEL_NAME
          ChannelNames                MQCACH_CHANNEL_NAMES
          ChannelStartDate            MQCACH_CHANNEL_START_DATE
          ChannelStartTime            MQCACH_CHANNEL_START_TIME
          ChannelStatus               MQIACH_CHANNEL_STATUS
          ChannelType                 MQIACH_CHANNEL_TYPE
          ClusterName                 MQCA_CLUSTER_NAME
          ClusterNamelist             MQCA_CLUSTER_NAMELIST
          ConnectionName              MQCACH_CONNECTION_NAME
          CurrentLUWID                MQCACH_CURRENT_LUWID
          CurrentMsgs                 MQIACH_CURRENT_MSGS
          CurrentSequenceNumber       MQIACH_CURRENT_SEQ_NUMBER
          DataConversion              MQIACH_DATA_CONVERSION
          DiscInterval                MQIACH_DISC_INTERVAL
          HeartbeatInterval           MQIACH_HB_INTERVAL
          InDoubtStatus               MQIACH_INDOUBT_STATUS
          LastLUWID                   MQCACH_LAST_LUWID
          LastMsgDate                 MQCACH_LAST_MSG_DATE
          LastMsgTime                 MQCACH_LAST_MSG_TIME
          LastSequenceNumber          MQIACH_LAST_SEQ_NUMBER
          LongRetriesLeft             MQIACH_LONG_RETRIES_LEFT
          LongRetryCount              MQIACH_LONG_RETRY
          LongRetryInterval           MQIACH_LONG_TIMER
          MCAJobName                  MQCACH_MCA_JOB_NAME
          MCAName                     MQCACH_MCA_NAME
          MCAStatus                   MQIACH_MCA_STATUS
          MCAType                     MQIACH_MCA_TYPE
          MCAUserIdentifier           MQCACH_MCA_USER_ID
          MaxMsgLength                MQIACH_MAX_MSG_LENGTH
          ModeName                    MQCACH_MODE_NAME
          MsgExit                     MQCACH_MSG_EXIT_NAME
          MsgRetryCount               MQIACH_MR_COUNT
          MsgRetryExit                MQCACH_MR_EXIT_NAME
          MsgRetryInterval            MQIACH_MR_INTERVAL
          MsgRetryUserData            MQCACH_MR_EXIT_USER_DATA
          MsgUserData                 MQCACH_MSG_EXIT_USER_DATA
          Msgs                        MQIACH_MSGS
          NetworkPriority             MQIACH_NETWORK_PRIORITY
          NonPersistentMsgSpeed       MQIACH_NPM_SPEED
          Password                    MQCACH_PASSWORD
          PutAuthority                MQIACH_PUT_AUTHORITY
          QMgrName                    MQCA_Q_MGR_NAME
          ReceiveExit                 MQCACH_RCV_EXIT_NAME
          ReceiveUserData             MQCACH_RCV_EXIT_USER_DATA
          SecurityExit                MQCACH_SEC_EXIT_NAME
          SecurityUserData            MQCACH_SEC_EXIT_USER_DATA
          SendExit                    MQCACH_SEND_EXIT_NAME
          SendUserData                MQCACH_SEND_EXIT_USER_DATA
          SeqNumberWrap               MQIACH_SEQUENCE_NUMBER_WRAP
          ShortRetriesLeft            MQIACH_SHORT_RETRIES_LEFT
          ShortRetryCount             MQIACH_SHORT_RETRY
          ShortRetryInterval          MQIACH_SHORT_TIMER
          StopRequested               MQIACH_STOP_REQUESTED
          TpName                      MQCACH_TP_NAME
          TransportType               MQIACH_XMIT_PROTOCOL_TYPE
          UserIdentifier              MQCACH_USER_ID
          XmitQName                   MQCACH_XMIT_Q_NAME

ChannelInstanceType  	(integer)
          Key				Macro
          ===				=====
          Current                     MQOT_CURRENT_CHANNEL
          Saved                       MQOT_SAVED_CHANNEL

InDoubt			(integer)
          Key				Macro
          ===				=====
          Backout                     MQIDO_BACKOUT
          Commit                      MQIDO_COMMIT

   The following keys have Boolean values:

Replace
DataConversion
Quiesce
Namelist Commands
-----------------

   Subsets of the these keys are applicable to the following commands.
See the documentation for each of the for the specific list.

     Change Namelist
     Copy Namelist
     Create Namelist
     Delete Namelist
     Inquire Namelist
     Inquire Namelist Names

   The following keys have special value mappings:

NamelistAttrs		(integer list)
          Key				Macro
          ===				=====
          AlterationDate              MQCA_ALTERATION_DATE
          AlterationTime              MQCA_ALTERATION_TIME
          NamelistDesc                MQCA_NAMELIST_DESC
          NamelistName                MQCA_NAMELIST_NAME
          Names                       MQCA_NAMES

   The following keys have Boolean values:

Replace
Process Commands
----------------

   Subsets of the these keys are applicable to the following commands.
See the documentation for each of the for the specific list.

     Change Process
     Copy Process
     Create Process
     Delete Process
     Inquire Process
     Inquire ProcessNames

   The following keys have special value mappings:

ApplType    		(integer)
          Key				Macro
          ===				=====
          AIX                         MQAT_AIX
          CICS                        MQAT_CICS
          DOS                         MQAT_DOS
          Default                     MQAT_UNIX
          IMS                         MQAT_IMS
          MVS                         MQAT_MVS
          NSK                         MQAT_NSK
          OS2                         MQAT_OS2
          OS400                       MQAT_OS400
          UNIX                        MQAT_UNIX
          VMS                         MQAT_VMS
          Win16                       MQAT_WINDOWS
          Win32                       MQAT_WINDOWS_NT

ProcessAttrs		(interger list)
          Key				Macro
          ===				=====
          All                         MQIACF_ALL
          AlterationDate              MQCA_ALTERATION_DATE
          AlterationTime              MQCA_ALTERATION_TIME
          ApplId                      MQCA_APPL_ID
          ApplType                    MQIA_APPL_TYPE
          EnvData                     MQCA_ENV_DATA
          ProcessDesc                 MQCA_PROCESS_DESC
          ProcessName                 MQCA_PROCESS_NAME
          ProcessNames                MQCACF_PROCESS_NAMES
          UserData                    MQCA_USER_DATA

   The following keys have Boolean values:

Replace
Queue Commands
--------------

   Subsets of the these keys are applicable to the following commands.
See the documentation for each of the for the specific list.

     Change Queue
     Clear Queue
     Copy Queue
     Create Queue
     Delete Queue
     Inquire Queue
     Inquire Queue Names
     Reset Queue Statistics

   The following keys have special value mappings:

DefBind  			(integer)
          Key				Macro
          ===				=====
          OnOpen                      MQBND_BIND_ON_OPEN
          NotFixed                    MQBND_BIND_NOT_FIXED

DefinitionType		(integer)
          Key				Macro
          ===				=====
          Permanent                   MQQDT_PERMANENT_DYNAMIC
          Temporary                   MQQDT_TEMPORARY_DYNAMIC

DefInputOpenOption    	(integer)
          Key				Macro
          ===				=====
          Exclusive                   MQOO_INPUT_EXCLUSIVE
          Shared                      MQOO_INPUT_SHARED

MsgDeliverySequence    	(integer)
          Key				Macro
          ===				=====
          FIFO                        MQMDS_FIFO
          Priority                    MQMDS_PRIORITY

QAttrs			(integer list)
          Key				Macro
          ===				=====
          All                         MQIACF_ALL
          AlterationDate              MQCA_ALTERATION_DATE
          AlterationTime              MQCA_ALTERATION_TIME
          BackoutRequeueName          MQCA_BACKOUT_REQ_Q_NAME
          BackoutThreshold            MQIA_BACKOUT_THRESHOLD
          BaseQName                   MQCA_BASE_Q_NAME
          ClusterDate                 MQCA_CLUSTER_DATE
          ClusterName                 MQCA_CLUSTER_NAME
          ClusterNamelist             MQCA_CLUSTER_NAMELIST
          ClusterQType                MQIA_CLUSTER_Q_TYPE
          ClusterTime                 MQCA_CLUSTER_TIME
          CreationDate                MQCA_CREATION_DATE
          CreationTime                MQCA_CREATION_TIME
          CurrentQDepth               MQIA_CURRENT_Q_DEPTH
          DefBind                     MQIA_DEF_BIND
          DefInputOpenOption          MQIA_DEF_INPUT_OPEN_OPTION
          DefPersistence              MQIA_DEF_PERSISTENCE
          DefPriority                 MQIA_DEF_PRIORITY
          DefinitionType              MQIA_DEFINITION_TYPE
          DistLists                   MQIA_DIST_LISTS
          HardenGetBackout            MQIA_HARDEN_GET_BACKOUT
          HighQDepth                  MQIA_HIGH_Q_DEPTH
          InhibitGet                  MQIA_INHIBIT_GET
          InhibitPut                  MQIA_INHIBIT_PUT
          InitiationQName             MQCA_INITIATION_Q_NAME
          MaxMsgLength                MQIA_MAX_MSG_LENGTH
          MaxQDepth                   MQIA_MAX_Q_DEPTH
          MsgDeliverySequence         MQIA_MSG_DELIVERY_SEQUENCE
          MsgDeqCount                 MQIA_MSG_DEQ_COUNT
          MsgEnqCount                 MQIA_MSG_ENQ_COUNT
          OpenInputCount              MQIA_OPEN_INPUT_COUNT
          OpenOutputCount             MQIA_OPEN_OUTPUT_COUNT
          ProcessName                 MQCA_PROCESS_NAME
          QDepthHighEvent             MQIA_Q_DEPTH_HIGH_EVENT
          QDepthHighLimit             MQIA_Q_DEPTH_HIGH_LIMIT
          QDepthLowEvent              MQIA_Q_DEPTH_LOW_EVENT
          QDepthLowLimit              MQIA_Q_DEPTH_LOW_LIMIT
          QDepthMaxEvent              MQIA_Q_DEPTH_MAX_EVENT
          QDesc                       MQCA_Q_DESC
          QMgrIdentifier              MQCA_Q_MGR_IDENTIFIER
          QMgrName                    MQCA_CLUSTER_Q_MGR_NAME
          QName                       MQCA_Q_NAME
          QNames                      MQCACF_Q_NAMES
          QServiceInterval            MQIA_Q_SERVICE_INTERVAL
          QServiceIntervalEvent       MQIA_Q_SERVICE_INTERVAL_EVENT
          QType                       MQIA_Q_TYPE
          RemoteQMgrName              MQCA_REMOTE_Q_MGR_NAME
          RemoteQName                 MQCA_REMOTE_Q_NAME
          RetentionInterval           MQIA_RETENTION_INTERVAL
          Scope                       MQIA_SCOPE
          Shareability                MQIA_SHAREABILITY
          TimeSinceReset              MQIA_TIME_SINCE_RESET
          TriggerControl              MQIA_TRIGGER_CONTROL
          TriggerData                 MQCA_TRIGGER_DATA
          TriggerDepth                MQIA_TRIGGER_DEPTH
          TriggerMsgPriority          MQIA_TRIGGER_MSG_PRIORITY
          TriggerType                 MQIA_TRIGGER_TYPE
          Usage                       MQIA_USAGE
          XmitQName                   MQCA_XMIT_Q_NAME

QServiceIntervalEvent    	(integer)
          Key				Macro
          ===				=====
          High                        MQQSIE_HIGH
          None                        MQQSIE_NONE
          OK                          MQQSIE_OK

QType    			(integer)
          Key				Macro
          ===				=====
          Alias                       MQQT_ALIAS
          All                         MQQT_ALL
          Cluster                     MQQT_CLUSTER
          Local                       MQQT_LOCAL
          Model                       MQQT_MODEL
          Remote                      MQQT_REMOTE

Scope    			(integer)
          Key				Macro
          ===				=====
          Cell                        MQSCO_CELL
          QMgr                        MQSCO_Q_MGR

TriggerType    		(integer)
          Key				Macro
          ===				=====
          Depth                       MQTT_DEPTH
          Every                       MQTT_EVERY
          First                       MQTT_FIRST
          None                        MQTT_NONE

Usage    			(integer)
          Key				Macro
          ===				=====
          Normal                      MQUS_NORMAL
          XMITQ                       MQUS_TRANSMISSION

   The following keys have Boolean values:

Replace
Force
InhibitPut
DefPersistence
InhibitGet
Shareability
HardenGetBackout
DistLists
TriggerControl
QDepthMaxEvent
QDepthHighEvent
QDepthLowEvent
Purge
Queue Manager Commands
----------------------

   Subsets of the these keys are applicable to the following commands.
See the documentation for each of the for the specific list.

     Change Queue Manager
     Inquire Queue Manager
     Ping Queue Manager

   The following keys have special value mappings:

QMgrAttrs			(integer list)
          Key				Macro
          ===				=====
          All                         MQIACF_ALL
          AlterationDate              MQCA_ALTERATION_DATE
          AlterationTime              MQCA_ALTERATION_TIME
          AuthorityEvent              MQIA_AUTHORITY_EVENT
          ChannelAutoDef              MQIA_CHANNEL_AUTO_DEF
          ChannelAutoDefEvent         MQIA_CHANNEL_AUTO_DEF_EVENT
          ChannelAutoDefExit          MQCA_CHANNEL_AUTO_DEF_EXIT
          ClusterWorkLoadData         MQCA_CLUSTER_WORKLOAD_DATA
          ClusterWorkLoadExit         MQCA_CLUSTER_WORKLOAD_EXIT
          ClusterWorkLoadLength       MQIA_CLUSTER_WORKLOAD_LENGTH
          CodedCharSetId              MQIA_CODED_CHAR_SET_ID
          CommandInputQName           MQCA_COMMAND_INPUT_Q_NAME
          CommandLevel                MQIA_COMMAND_LEVEL
          DeadLetterQName             MQCA_DEAD_LETTER_Q_NAME
          DefXmitQName                MQCA_DEF_XMIT_Q_NAME
          DistLists                   MQIA_DIST_LISTS
          InhibitEvent                MQIA_INHIBIT_EVENT
          LocalEvent                  MQIA_LOCAL_EVENT
          MaxHandles                  MQIA_MAX_HANDLES
          MaxMsgLength                MQIA_MAX_MSG_LENGTH
          MaxPriority                 MQIA_MAX_PRIORITY
          MaxUncommittedMsgs          MQIA_MAX_UNCOMMITTED_MSGS
          PerformanceEvent            MQIA_PERFORMANCE_EVENT
          Platform                    MQIA_PLATFORM
          QMgrDesc                    MQCA_Q_MGR_DESC
          QMgrIdentifier              MQCA_Q_MGR_IDENTIFIER
          QMgrName                    MQCA_Q_MGR_NAME
          RemoteEvent                 MQIA_REMOTE_EVENT
          RepositoryName              MQCA_REPOSITORY_NAME
          RepositoryNamelist          MQCA_REPOSITORY_NAMELIST
          StartStopEvent              MQIA_START_STOP_EVENT
          SyncPoint                   MQIA_SYNCPOINT
          TriggerInterval             MQIA_TRIGGER_INTERVAL

   The following keys have Boolean values:

Force
AuthorityEvent
InhibitEvent
LocalEvent
RemoteEvent
StartStopEvent
PerformanceEvent
ChannelAutoDef
ChannelAutoDefEvent
Cluster Commands
----------------

   Subsets of the these keys are applicable to the following commands.
See the documentation for each of the for the specific list.

     Inquire Cluster Queue Manager
     Refresh Cluster
     Reset Cluster
     Resume Queue Manager Cluster
     Suspend Queue Manager Cluster

   The following keys have special value mappings:

ClusterQMgrAttrs		(integer list)
          Key				Macro
          ===				=====
          AlterationDate              MQCA_ALTERATION_DATE
          AlterationTime              MQCA_ALTERATION_TIME
          BatchInterval               MQIACH_BATCH_INTERVAL
          BatchSize                   MQIACH_BATCH_SIZE
          ChannelStatus               MQIACH_CHANNEL_STATUS
          ClusterDate                 MQCA_CLUSTER_DATE
          ClusterName                 MQCA_CLUSTER_NAME
          ClusterTime                 MQCA_CLUSTER_TIME
          ConnectionName              MQCACH_CONNECTION_NAME
          DataConversion              MQIACH_DATA_CONVERSION
          Description                 MQCACH_DESC
          DiscInterval                MQIACH_DISC_INTERVAL
          HeartbeatInterval           MQIACH_HB_INTERVAL
          LongRetryCount              MQIACH_LONG_RETRY
          LongRetryInterval           MQIACH_LONG_TIMER
          MCAName                     MQCACH_MCA_NAME
          MCAType                     MQIACH_MCA_TYPE
          MCAUserIdentifier           MQCACH_MCA_USER_ID
          MaxMsgLength                MQIACH_MAX_MSG_LENGTH
          ModeName                    MQCACH_MODE_NAME
          MsgExit                     MQCACH_MSG_EXIT_NAME
          MsgRetryCount               MQIACH_MR_COUNT
          MsgRetryExit                MQCACH_MR_EXIT_NAME
          MsgRetryInterval            MQIACH_MR_INTERVAL
          MsgRetryUserData            MQCACH_MR_EXIT_USER_DATA
          MsgUserData                 MQCACH_MSG_EXIT_USER_DATA
          NetworkPriority             MQIACH_NETWORK_PRIORITY
          NonPersistentMsgSpeed       MQIACH_NPM_SPEED
          Password                    MQCACH_PASSWORD
          PutAuthority                MQIACH_PUT_AUTHORITY
          QMgrDefinitionType          MQIACF_Q_MGR_DEFINITION_TYPE
          QMgrIdentifier              MQCA_Q_MGR_IDENTIFIER
          QMgrType                    MQIACF_Q_MGR_TYPE
          ReceiveExit                 MQCACH_RCV_EXIT_NAME
          ReceiveUserData             MQCACH_RCV_EXIT_USER_DATA
          SecurityExit                MQCACH_SEC_EXIT_NAME
          SecurityUserData            MQCACH_SEC_EXIT_USER_DATA
          SendExit                    MQCACH_SEND_EXIT_NAME
          SendUserData                MQCACH_SEND_EXIT_USER_DATA
          SeqNumberWrap               MQIACH_SEQUENCE_NUMBER_WRAP
          ShortRetryCount             MQIACH_SHORT_RETRY
          ShortRetryInterval          MQIACH_SHORT_TIMER
          Suspend                     MQIACF_SUSPEND
          TpName                      MQCACH_TP_NAME
          TransportType               MQIACH_XMIT_PROTOCOL_TYPE
          UserIdentifier              MQCACH_USER_ID
          XmitQName                   MQCACH_XMIT_Q_NAME

Action			(integer)
          Key				Macro
          ===				=====
          ForceRemove                 MQACT_FORCE_REMOVE

   The following keys have Boolean values:

Quiesce
Escape Command
--------------

   This command is not really part of a grouping, so its all by itself
here.

   The following keys have special value mappings:

EscapeType 		(integer)
          Key				Macro
          ===				=====
          MQSC                        MQET_MQSC

COMMAND RESPONSES
=================

   There are several commands which return data.  The return value of the
actual command methods depends on the specific command.  All of the
"Inquire*Names" commands return a list of the actual names returned, which
greatly simplifies the parsing of the return value.

   The commands which return a list of names are:

     Inquire Channel Names
     Inquire Namelist Names
     Inquire Process Names
     Inquire Queue Names

   For example:

     @qnames = $command->InquireQueueNames( QName => 'FOO.*' );

   will result in @qnames containing a list of strings of all of the queue
names starting with FOO.

   The rest of the commands return a list of Parameters HASH references,
extracted from each of the messages sent back from the command server.  In
a scalar context, only the first Parameters HASH reference is returned.
This applies to all of the following commands:

     Escape
     Inquire Channel
     Inquire Channel Status
     Inquire Cluster Queue Manager
     Inquire Namelist
     Inquire Process
     Inquire Queue
     Inquire Queue Manager
     Reset Queue Statistics

   For example:

     @queues = $command->InquireQueue( QName => 'FOO.*', QAttrs => 'All' );

   will result in @queues containing a list of HASH references, each of
which has key/value pairs for the attributes of one of the queues starting
with FOO.

   The keys in the Parameters HASH references are mapped from the numeric
macro values back into the same strings described above for simplifying
the input Parameters.

   However, there are a few keys in the responses which are not supported
as keys in the inquiry.  In general, the return values are left
unmolested, with the exception of the keys documented above for each
command type, as well as the following:

Inquire Channel Status Response
-------------------------------

   The following keys have special value mappings:

ChannelStatus			(integer)
          Macro				Key
          =====				===
          MQCHS_BINDING                       Binding
          MQCHS_INACTIVE                      Inactive
          MQCHS_INITIALIZING                  Initializing
          MQCHS_PAUSED                        Paused
          MQCHS_REQUESTING                    Requesting
          MQCHS_RETRYING                      Retrying
          MQCHS_RUNNING                       Running
          MQCHS_STARTING                      Starting
          MQCHS_STOPPED                       Stopped
          MQCHS_STOPPING                      Stopping

MCAStatus				(integer)
          Macro				Key
          =====				===
          MQMCAS_RUNNING                      Running
          MQMCAS_STOPPED                      Stopped

   The following keys can be interpreted in a Boolean context:

InDoubtStatus
StopRequested
Inquire Cluster Queue Manager Response
--------------------------------------

   The following keys have special value mappings:

QMgrDefinitionType 		(integer)
          Macro				Key
          =====				===
          MQQMDT_AUTO_CLUSTER_SENDER          AutoClusterSender
          MQQMDT_AUTO_EXP_CLUSTER_SENDER      AutoExplicitClusterSender
          MQQMDT_CLUSTER_RECEIVER             ClusterReceiver
          MQQMDT_EXPLICIT_CLUSTER_SENDER      ExplicitClusterSender

QMgrType				(integer)
          Macro				Key
          =====				===
          MQQMT_NORMAL                        Normal
          MQQMT_REPOSITORY                    Repository

ChannelStatus			(integer)
          Macro				Key
          =====				===
          MQCHS_BINDING                       Binding
          MQCHS_INACTIVE                      Inactive
          MQCHS_INITIALIZING                  Initializing
          MQCHS_PAUSED                        Paused
          MQCHS_REQUESTING                    Requesting
          MQCHS_RETRYING                      Retrying
          MQCHS_RUNNING                       Running
          MQCHS_STARTING                      Starting
          MQCHS_STOPPED                       Stopped
          MQCHS_STOPPING                      Stopping

   The following keys can be interpreted in a Boolean context:

Suspend
Inquire Queue Response
----------------------

   The following keys have special value mappings:

ClusterQType			(integer)
          Macro				Key
          =====				===
          MQCQT_ALIAS_Q                       Alias
          MQCQT_LOCAL_Q                       Local
          MQCQT_Q_MGR_ALIAS                   QMgrAlias
          MQCQT_REMOTE_Q                      Remote

Inquire Queue Manager Response
------------------------------

   The following keys have special value mappings:

Platform				(integer)
          Macro				Key
          =====				===
          MQPL_MVS                            MVS
          MQPL_NSK                            NSK
          MQPL_OS2                            OS2
          MQPL_OS400                          OS400
          MQPL_UNIX                           UNIX
          MQPL_WINDOWS                        Win16
          MQPL_WINDOWS_NT                     Win32

   The following keys can be interpreted in a Boolean context:

DistLists
SyncPoint
SEE ALSO
========

   MQSeries(3), MQSeries::Queue(3), MQSeries::Message(3),
MQSeries::Command::Request(3), MQSeries::Command::Response(3)

   In addition, the MQSeries documentation is the primary source of
documentation for the commands and their arguments, especially the
following sections.

     "MQSeries Programmable System Management"
     Part 2. Programmable Command Formats
       Chapter 8. Definitions of the Programmable Command Formats
       Chapter 9. Structures used for commands and responses

Interface to parse authority files
**********************************

NAME
====

   MQSeries::Config::Authority - Interface to parse authority files

SYNOPSIS
========

     use MQSeries::Config::Authority;

     my $authobj = new MQSeries::Config::Authority('QMgrName'   => 'TEST',
                                                   'ObjectType' => 'queue',
                                                   'ObjectName' => 'FOO.BAR');
     print "All entities for queue: ", join(', ', $authobj->entities()), "\n";
     print "Entity 'mqm' has authorities: ",
         join(', ', $authobj->authorities('mqm')), "\n";

     if ($authobj->has_authority('allcmd', 'mqops')) {
         print "Entity 'mqops' has 'allcmd' authority\n";
     }

     print "The command to recreate authority for user 'nobody' is:\n\t",
         "setmqaut -m TEST -t queue -n FOO.BAR -g nobody ",
         $authobj->authority_command(), "\n";

DESCRIPTION
===========

   The MQSeries::Config::Authority class is an interface to the authority
files in /var/mqm/qmgrs/XYZ/auth/.  This class will parse authority files
for specific objects and take into account the @aclass and  @class files.
Objects created then provide access to the entities (Unix groups or
principals) that have access to the object, allow you to query whether an
entity has specific access levels, or to create command input that will
allow you to recreate the access settings at a later date.

   The MQSeries::Config::Authority class will cache the parsed @aclass and
@class authority files across multiple authority files for efficiency, but
will check the timestamp of these files at every lookup.  Should the files
change, they will be re-parsed, so that up-to-date information is always
returned.

METHODS
=======

new
---

   Create a new MQSeries::Config::Authority object.  The constructor takes
named parameters, of which two are required and three are optional,
depending on the type and your environment:

QMgrName
     The name of the queue manager containing the object.  The Authority
     class will query the mqs.ini file for the queue-manager directory
     name, using the MQseries::Config::Machine class.

ObjectType
     This must be either 'qmgr', 'queue', 'process' or 'namelist'.  The
     aliases 'QMgr', 'QueueManager', 'Queue', 'Process' and 'Namelist' or
     also supported.

ObjectName
     The name of the object to be read, if the object type is not 'qmgr'.

BaseDir
     An optional parameter specifying the base directory, if not /var/mqm.

Carp
     A reference to a routine used to issue warnings.  Will default to
     carp.

entities
--------

   Returns an array with all entities (Unix groups or principals).  These
can then be used in further method calls.  As the authority file has a
flat namespace, it is not indicated whether an entity name is that of a
Unix group of that of a principal.

numeric_authority
-----------------

   This method requires one parameter, an entity name, and will return the
numeric authority value for that entity.  The numeric authority is
normally not of interest, but can be used when generating authority files
directly.

authorities
-----------

   This method has one parameter, an entity name, and one optional
parameter, the format ('setmqaut' or 'PCF').  It returns a list of all
authority names for this entity.

   If the format parameter is 'setmquat' or is not specified, the
authority names returned correspond to the values as specified in
`setmqaut', e.g. 'connect', 'inq', 'get', etc.  If a user has all
authorities, the full list of names is returned, not 'all'.

   If the format parameter is 'PCF', the PCF macros as defined by the
MQSeries::Command module are returned.

has_authority
-------------

   This method requires two parameters: an entity name and an authority
name.  It returns a boolean value indicating whether the user has the
indicated authority or not.  Apart from the indidivual authority names,
this method also supports the combined authority names 'all', 'allcmd' and
'allmqi'.

authority_command
-----------------

   This method requires one parameter, an entity name, and returns a
string with authorities suitable for use in a `setmqaut' command.  If the
entity holds 'connect' authority, the string includes '+connect',
otherwise it will include '-connect'.  In order to keep the string short,
the combined authority values 'all', 'allcmd' and 'allmqi' will be used
when appropriate.

SEE ALSO
========

   MQSeries(3), MQSeries::Config::Authority(3)

Interface to read the machine configuration file
************************************************

NAME
====

   MQSeries::Config::Machine - Interface to read the machine configuration
file

SYNOPSIS
========

     use MQSeries::Config::Machine;

     my $conf = new MQSeries::Config::Machine;

     print "All configuration sections: ", join(', ', $conf->stanzas()), "\n";

     my $default = $conf->lookup('DefaultQueueManager');
     if (defined $default) {
         print "Default queue manager: $default->{'Name'}\n";
     }

     my $local = $conf->localqmgrs();
     print "All local queue managers:\n";
     while (my ($name, $data) = each %$local) {
         print "  $name - $data->{'Directory'}\n";
     }

DESCRIPTION
===========

   The MQSeries::Config::Machine class is an interface to the machine
configuration file, typically /var/mqm/mqs.ini.  This class will parse the
file and allow you to lookup any group of settings in the class.  A
utility function based on this will return a full list of all local queue
managers and their base directory name.

   An MQSeries::Config::Machine object will cache the parsed configuration
file for efficiency, but will check the timestamp of the file at every
lookup.  Should the file change, it will be re-parsed, so that up-to-date
information is always returned.

METHODS
=======

new
---

   Create a new MQSeries::Config::Machine object.  The constructor takes
an optional filename parameter, used when your configuration file is not
at the default location of /var/mqm/mqs.ini.

stanzas
-------

   Return an array with all stanza names.  These can then be used as a
parameter to lookup.

lookup
------

   Lookup a stanza in the configuration file.  Depending on the context,
this returns either an array with one entry for each instance of the
stanza found, or the latest stanza with that name. Each entry is a
hash-reference with key-value pairs.  For example, using
`$conf-'lookup('QueueManager')> returns an array with one hash-reference
for each locally-defined queue manager; each hash-reference will contain a
'Name' and 'Directory' field and whatever other fields the configuration
file will contain.

localqmgrs
----------

   A convenience function written on top of lookup.  This function returns
a hash-reference mapping local queue manager names to configuration
settings.

FILES
=====

   /var/mqm/mqs.ini

SEE ALSO
========

   MQSeries(3), MQSeries::Config::QMgr

Interface to read the queue manager configuration file
******************************************************

NAME
====

   MQSeries::Config::QMgr - Interface to read the queue manager
configuration file

SYNOPSIS
========

     use MQSeries::Config::QMgr;

     my $conf = new MQSeries::Config::QMgr('your.queue.manager');

     print "All configuration sections: ", join(', ', $conf->stanzas()), "\n";

     my $tuning = $conf->lookup('TuningParameters');
     if (defined $tuning) {
         print "Tuning parameters:\n";
         foreach my $param (sort keys %$tuning) {
             print "\t$param: $tuning->{$param}\n";
         }
     }

DESCRIPTION
===========

   The MQSeries::Config::QMgr class is an interface to a queue manager
configuration file, typically /var/mqm/qmgrs/XXX/qm.ini for queue manager
'XXX'.  This class will parse the file and allow you to lookup any group
of settings in the class.

   An MQSeries::Config::QMgr object will cache the parsed configuration
file for efficiency, but will check the timestamp of the file at every
lookup.  Should the file change, it will be re-parsed, so that up-to-date
information is always returned.

METHODS
=======

new
---

   Create a new MQSeries::Config::QMgr object. The constructor takes one
required and one optional parameter:

The name of the queue manager
The name of the base directory, if not /var/mqm
   The constructor will use the machine configuration file (by default
/var/mqm/mqs.ini) to map the queue manager name to the appropriate
directory name.

stanzas
-------

   Return an array with all stanza names.  These can then be used as a
parameter to lookup.

lookup
------

   Lookup a stanza in the configuration file.  Depending on the context,
this returns either an array with one entry for each instance of the
stanza found, or the latest stanza with that name. Each entry is a
hash-reference with key-value pairs.  For example, using
`$conf-'lookup('QueueManager')> returns an array with one hash-reference
for each locally-defined queue manager; each hash-reference will contain a
'Name' and 'Directory' field and whatever other fields the configuration
file will contain.

FILES
=====

   /var/mqm/mqs.ini /var/mqm/qmgrs/*/qm.ini

SEE ALSO
========

   MQSeries(3), MQSeries::Config::Machine

One entry in an MQSeries error-log file
***************************************

NAME
====

   MQSeries::ErrorLog::Entry - One entry in an MQSeries error-log file

SYNOPIS
=======

     #
     # Assuming we get an array of parsed MQSeries::ErrorLog::Entry
     # objects from somewhere, here's how we dump them to syslog.
     #
     use Sys::Syslog;
     openlog($0, 'pid', 'daemon');

     sub process_errorlog_entries {
         foreach my $entry (@_) {
             syslog('info', "$entry"); # Overloaded operator-""
         }
     }

DESCRIPTION
===========

   The MQSeries::ErrorLog::Entry class is not used directly, but invoked
through the MQSeries::ErrorLog::Parser class.

   When the MQSeries::ErrorLog::Tail or MQSeries::ErrorLog::Parser classes
return an array of entries, these can be queried for their error-codes,
summary, parsed fields, etc.

   This class has overloaded the '""' (to-string) operator, which means
that printing an object results in reasonable results.

METHODS
=======

new
---

   Create a new MQSeries::ErrorLog::Entry object.  The parameters are not
documented; use the MQSeries::ErrorLog::Parser class to create these.

error_code
----------

   Return the error code (e.g., AMQ9001)

timestamp
---------

   Return the original time-stamp from the entry, in Unix time() format

summary
-------

   Return the original summary

field
-----

   Get (one parameter) or set (two parameters) detailed parsed fields,
such as 'QMgr', 'Channel', 'Host', etc.  See the 'descriptions.pl' files
used by the MQSeries::ErrorLog::Parser class for a list of supported
messages and the fields parsed.

fields
------

   Get a list of all field names supported by this entry.

as_string
---------

   Return a string with the details of this entry; also invoked by the
overloaded operator-"".

FILES
=====

   The file 'descriptions.pl' contains a list of all error messages
supported, in the form of regular expressions and a set of field names
extracted from these expressions.  Additions and corrections are welcome.

SEE ALSO
========

   MQSeries(3), MQSeries::ErrorLog::Tail(3), MQSeries::ErrorLog::Parser(3)

Parse a portion of an MQSeries error log and return parsed Entry objects.
*************************************************************************

NAME
====

   MQSeries::ErrorLog::Parser - Parse a portion of an MQSeries error log
and return parsed Entry objects.

SYNOPSIS
========

     use MQSeries::ErrorLog::Parser;

     my $qmgr = 'foo';   # Queue Manager we are processing
     my $parser =
       new MQSeries::ErrorLog::Parser('defaults' => { 'QMgr' => $qmgr });
     open (ERRORS, "/var/mqm/qmgrs/$qmgr/errors/AMQERR01.LOG");
     local $/;
     my @entries = $parser->parse_data(<ERRORS>);
     close ERRORS;

DESCRIPTION
===========

   The MQSeries::ErrorLog::Parser class is typically not used directly,
but invoked through the MQSeries::ErrorLog::Tail class.  When used
directly, it can be used to parse a (possibly archived) error-log file and
return an array of neatly-parsed MQSeries::ErrorLog::Entry objects.

   This class will try and deal with the vagaries of error-log processing,
chief of which is that the MQSeries error-log is not written to in an
atomic fashion, meaning that some error-log entries may be interleaved and
hence un-parseable.

   All error-log entries can be parsed to some extent (summary, action,
timestamp); however, most common error messages are also parsed in detail
to give access to embedded fields such as 'QMgr', 'Channel', 'Queue', etc.

METHODS
=======

new
---

   Create a new MQSeries::ErrorLog::Parser object.  The constructor take
the following optional parameters:

Carp
     A reference to an error-handling routine.  This defaults to 'carp',
     but can be changed to your own error-handling routine.

     In order to avoid overloading the system with error messages, message
     format errors are not logged and errors for specific error-log
     messages are generated only once for each message code.

defaults
     A reference to a hash with default parameters that will be used to
     initialize the MQSeries::ErrorLog::Entry object created.  A typical
     default parameter is 'QMgr', which should be specified whenever you
     are parsing error-log messages for a specific queue manager.

parse_data
----------

   Parse a chunk of text with one or more error messages and return
individual parsed entries.

FILES
=====

   The file 'descriptions.pl' contains a list of all error messages
supported, in the form of regular expressions and a set of field names
extracted from these expressions.  Additions and corrections are welcome.

SEE ALSO
========

   MQSeries(3), MQSeries::ErrorLog::Tail(3), MQSeries::ErrorLog::Entry(3)

Watch MQSeries error-log files
******************************

NAME
====

   MQSeries::ErrorLog::Tail - Watch MQSeries error-log files

SYNOPSIS
========

     use MQSeries::ErrorLog::Tail;

     my $err_log = new MQSeries::ErrorLog::Tail("/var/mqm/errors");
     while (1) {
         my @entries = $err_log->process();
         process_errorlog_entries(@entries) if (@entries);
         sleep(10) unless (@entries);
     }

     sub process_errorlog_entries {
         my (@errlog_entries) = @_;

     foreach my $entry (@errlog_entries) {
         # Send off to syslog or whatever
     }
       }

DESCRIPTION
===========

   The MQSeries::ErrorLog::Tail class provides a mechanism to watch the
MQSeries errorlog (AMQERR01.LOG), which is generally written to whenever
an MQSeries error occurs, or when certain events happen.

   Every time the process() method is invoked, it will return a (possibly
empty) array of MQSeries::ErrorLog::Entry objects, which can in turn be
analyzed and shipped off to syslog or other monitoring tools.

   The MQSeries::ErrorLog::Tail class will notice file roll-overs (where
the old AMQERR01.LOG is renamed AMQERR02.LOG and a new file AMQERR01.LOG
is created).  In such cases, it will first process the tail-end of the old
file, then switch over to the new file.

METHODS
=======

new
---

   Create a new MQSeries::ErrorLog::Tail object. The argument is the
directory to watch (/var/mqm/errors for a typical installation's
system-wide global error log, /var/mqm/qmgrs/XYZ/errors for a typical
installation's queue-manager specific error log).

process
-------

   Process any changes since the previous invocation (or the constructor).
Read any data found, parse it and return the MQSeries::ErrorLog::Entry
objects that were read.

SEE ALSO
========

   MQSeries(3), MQSeries::ErrorLog::Parser(3),
MQSeries::ErrorLog::Entry(3), MQSeries::FDC::Tail(3)

One entry in an MQSeries FDC file
*********************************

NAME
====

   MQSeries::FDC::Entry - One entry in an MQSeries FDC file

SYNOPIS
=======

     #
     # Assuming we get an array of parsed MQSeries::FDC::Entry
     # objects from somewhere, here's how we dump them to syslog.
     #
     use Sys::Syslog;
     openlog($0, 'pid', 'daemon');

     sub process_fdc_entries {
         foreach my $entry (@_) {
             syslog('info', "$entry"); # Overloaded operator-""
         }
     }

DESCRIPTION
===========

   The MQSeries::FDC::Entry class is not used directly, but invoked
through the MQSeries::FDC::Parser class.

   When the MQSeries::FDC::Tail or MQSeries::FDC::Parser classes return an
array of entries, these can be queried for their parsed fields.

   This class has overloaded the '""' (to-string) operator, which means
that printing an object results in reasonable results.

METHODS
=======

new
---

   Create a new MQSeries::FDC::Entry object.  The parameters are not
documented; use the MQSeries::FDC::Parser class to create these.

get_header
----------

   Return a field parsed from the header.  Any field from the header is
available directly; in addition, a number of parsed fields are derived.
Most FDC entries have following standard fields:

     Date/Time
     Host Name
     QueueManager (sometimes missing)
     PIDS
     LVLS
     Product Long Name
     Vendor
     Probe Id
     Application Name
     Component
     Build Date
     UserID
     Program Name
     Process
     Thread
     Major Errorcode
     Minor Errorcode
     Probe Type
     Probe Severity
     Probe Description
     Comment1

   In addition, the following parsed fields are available (these have all
lower-case names):

     uid        (numerical userid from UserID field, if available)
     userid     (text userid from UserID field, if available)
     event_code (event code from Probe Description, if available)

get_body
--------

   Return the body with all details from the FDC entry

as_string
---------

   Return a string with the details of this entry; also invoked by the
overloaded operator-"".

SEE ALSO
========

   MQSeries(3), MQSeries::FDC::Tail(3), MQSeries::FDC::Parser(3)

Parse a portion of an MQSeries FDC file and return parsed Entry objects.
************************************************************************

NAME
====

   MQSeries::FDC::Parser - Parse a portion of an MQSeries FDC file and
return parsed Entry objects.

SYNOPSIS
========

     use MQSeries::FDC::Parser;

     my $parser = new MQSeries::FDC::Parser("AMQ09151.0.FDC");
     open (FDC, "/var/mqm/errors/AMQ09151.0.FDC");
     local $/;
     my @entries = $parser->parse_data(<FDC>);
     close FDC;

DESCRIPTION
===========

   The MQSeries::FDC::Parser class is typically not used directly, but
invoked through the MQSeries::FDC::Tail class.  When used directly, it can
be used to parse a (possibly archived) FDC file and return an array of
neatly-parsed MQSeries::FDC::Entry objects.

   This class will try and deal with the vagaries of error-log processing,
chief of which is that the MQSeries FDC is not written to in an atomic
fashion, meaning that some error-log entries may be incomplete.  In this
case, the incomplete part is saved and prefixed to the data supplied in
the next call.  For this reason, you must create an individual Parser
object for each file that is processed.

METHODS
=======

new
---

   Create a new MQSeries::ErrorLog::Parser object.  The constructor takes
the filename as its argument; this filename is only used for error
messages.

parse_data
----------

   Parse a chunk of text with one or more FDC entries and return
individual parsed entries.

SEE ALSO
========

   MQSeries(3), MQSeries::FDC::Tail(3), MQSeries::FDC::Entry(3)

Watch MQSeries FDC error files
******************************

NAME
====

   MQSeries::FDC::Tail - Watch MQSeries FDC error files

SYNOPSIS
========

     use MQSeries::FDC::Tail;

     my $fdc_log = new MQSeries::FDC::Tail("/var/mqm/errors");
     while (1) {
         my @entries = $fdc_log->process();
         process_fdc_entries(@entries) if (@entries);
         sleep(10) unless (@entries);
     }

     sub process_fdc_entries {
         my (@fdc_entries) = @_;

     foreach my $entry (@fdc_entries) {
         # Send off to syslog or whatever
     }
       }

DESCRIPTION
===========

   The MQSeries::FDC::Tail class provides a mechanism to watch the FDC
logs, which are generally written to if a fatal MQSeries error, or
internal MQSeries error, occurs.

   Every time the process() method is invoked, it will return a (possibly
empty) array of MQSeries::FDC::Entry objects, which can in turn be
analyzed and shipped off to syslog or other monitoring tools.

   The MQSeries::FDC::Tail class will notice new FDC files appearing;
files being truncated (e.g. by housekeeping jobs) or files being removed.

METHODS
=======

new
---

   Create a new MQSeries::FDC::Tail object. The argument is the directory
to watch (/var/mqm/errors for a typical installation).  An optional second
argument specifies the maximum number of files that may be open at the
same time; the default is 200, well under the default limit of 255 open
files imposed by the stdio libraries of many vendors.

process
-------

   Process any changes since the previous invocation (or the constructor).
Read any data found, parse it and return the MQSeries::FDC::Entry objects
that were read.

SEE ALSO
========

   MQSeries(3), MQSeries::FDC::Parser(3), MQSeries::FDC::Entry(3),
MQSeries::ErrorLog::Tail(3)

OO interface to MQSeries messages
*********************************

NAME
====

   MQSeries::Message - OO interface to MQSeries messages

SYNOPSIS
========

     use MQSeries;
     use MQSeries::Message;

     #
     # Create a vanilla MQSeries::Message object for getting messages
     #
     my $getmsg = MQSeries::Message->new();

     #
     # Create a message for putting strings, which requires the
     # MQMD.Format field to be specified.  This is essential for
     # character codeset conversion.
     #
     my $putmsg = MQSeries::Message->new
       (
        MsgDesc 		=>
        {
         Format		=> MQFMT_STRING,
        },
       );

     #
     # Create a reply message, copying the CorrelId from the MsgId of a
     # request.  This reply is also a string.
     #
     my $request = MQSeries::Message->new();

     # Assume we get the message via an MQSeries::Queue object...

     my $reply = MQSeries::Message->new
       (
        MsgDesc 		=>
        {
         Format		=> MQFMT_STRING,
         CorrelId 		=> $request->MsgDesc("MsgId"),
        },
       );

   See MQSeries::Queue SYNOPSIS section as well.

DESCRIPTION
===========

   The MQSeries::Message object is an OO mechanism for creating MQSeries
messages, and putting and getting them onto MQSeries queues, with an
interface which is much simpler than the full MQI.

   This module is used together with MQSeries::QueueManager and
MQSeries::Queue.  These objects provide a subset of the MQI, with a
simpler interface.

METHODS
=======

new
---

   The arguments to the constructor are a hash, with the following
key/value pairs (there are no required keys):

     Key            Value
     ===            =====
     Data           Scalar
     BufferLength   Positive Integer
     MsgDesc        MQI MsgDesc hash (MQMD structure)
     Carp           CODE reference

Data
     When creating a message to be put into a queue, the Data should be
     specified.  This must be a simple scalar value.  Other subclasses of
     MQSeries::Message support the direct encoding of complex data
     structure, for example perl references can be sent and retreived as
     MQSeries messages using the MQSeries::Message::Storable module.

     The Data method will set the Data portion of the message if it is
     passed any defined value, and will simply return the data otherwise.
     Thus, to clear any existing Data from a message, one would pass the
     empty string:

          $message = MQSeries::Message->new( Data => "foo" );
          $message->Data(""); # Clears Data value entirely

     In order to query the Data value, the method must be called with no
     further arguments;

          $data = $message->Data(); # Returns Data unmolested

Buffer
     This method will return the raw, converted buffer when one exists.
     This is really only relevant for a message type which uses a
     PutConvert and/or GetConvert method to translate the raw buffer
     returned from MQGET().

BufferLength
     This sets the BufferLength of the messages to be extracted using
     MQGET.  The default is 32K, and if the messages to be received from
     the queue are expected to be larger, this must be set appropriately.

MsgDesc
     The value of this key is a hash refernece which sets the key/values of
     the MsgDesc structure.  See the "MQSeries Application Programming
     Reference" documentation for the possible keys and values of the MQMD
     structure.

     Also, see the examples section for specific usage of this feature.
     This is one area of the API which is not easily hidden; you have to
     know what you are doing.

Carp
     This key specifies a code reference to a routine to replace all of the
     carp() calls in the API, allowing the user of the API to trap and
     handle all of the error message generated internally, or simply
     redirect how they get logged.

     For example, one might want everything to be logged via syslog:

          sub MyLogger {
              my $message = @_;
              foreach my $line ( split(/\n+/,$message) ) {
                  syslog("err",$message);
              }
          }

     Then, one tells the object to use this routine:

          my $message = MQSeries::Message->new( Carp => \&MyLogger )
            || die "Unable to create message.\n";

     The default, as one might guess, is Carp::carp();

Data
----

   This method is used to set or query the value of the Data structure.
If an argument is specified, then the given data is assigned as the Data
value for this object.  If no argument is given, then the current Data
value is returned.

   The Data can be any arbitrary perl data structure, however, it must be
convertible to a scalar by means of the PutConvert and GetConvert hooks in
MQSeries::QueueManager and MQSeries::Queue objects.  See the documentation
for those classes for more details.

   If the GetConvert and PutConvert hooks are not used, then the data must
be a simple scalar value.

BufferLength
------------

   This method is used to set or query the current BufferLength used when
extracting messages.  If given an argument, the BufferLength is set to the
given value.  If the given value is not a positive integer, then an error
is generated, and a false value returned.

   With no argument, the current BufferLength is returned.

MsgDesc
-------

   This method can be used to query the MsgDesc data structure.  If no
argument is given, then the entire MsgDesc hash is returned.  If a single
argument is given, then this is interpreted as a specific key, and the
value of that key in the MsgDesc hash is returned.

ERROR HANDLING
==============

   Most methods return a true or false value indicating success of
failure, and internally, they will call the carp subroutine (either
Carp::carp, or something user-defined) with a text message indicating the
cause of the failure.

SUBCLASSES
==========

   This class is designed to be subclassed, and follows all the usual
rules (see the "perltoot" documentation provided with the core perl
distribution).  In particular, the PutConvert and GetConvert arguments
usually supplied to either the MQSeries::QueueManager or MQSeries::Queue
constructors are not necessary if you implement a subclass of
MQSeries::Message with methods of the same name.

   See the MQSeries::Message::Storable documentation for an example of one
such class.

   See also the section "CONVERSION PRECEDENCE" in the
MQSeries::QueueManager documentation.

SEE ALSO
========

   MQSeries(3), MQSeries::QueueManager(3), MQSeries::Queue(3),
MQSeries::Message::Storable(3), MQSeries::Message::Event(3)

OO Class for decoding MQSeries event messages
*********************************************

NAME
====

   MQSeries::Message::Event - OO Class for decoding MQSeries event messages

SYNOPSIS
========

     use MQSeries::Message::Event;
     my $message = MQSeries::Message::Event->new;

DESCRIPTION
===========

   This class is a subclass of MQSeries::Message which provides a
GetConvert() method to decode standard MQSeries Event messages.

METHODS
=======

   Since this is a subclass of MQSeries::Message, all of that classes
methods are available, as well as the following.

PutConvert, GetConvert
----------------------

   Neither of these methods are called by the users application, but are
used internally by MQSeries::Queue::Put() and MQSeries::Queue::Get(), as
well as MQSeries::QueueManager::Put1().

   The PutConvert method will cause a failure, since this class is only to
be used for decoding MQSeries events, not generating them.  Perhaps a
futute release will support the creation of such events.

   The GetConvert method decodes the message contents into the EventHeader
and EventData hashes, which are available via the methods of the same name.

Buffer
------

   Actually, this is one of the MQSeries::Message methods, and not
specific to MQSeries::Message::Event.  However, it is important to note
that this class is one of those that saves the raw buffer returned by
MQGET in the object.

   The Buffer method will return the raw, unconverted PCF data in the
original message.  The autor uses this to echo the original event message
to other systems management software that wants to parse the PCF.

EventHeader
-----------

   This method can be used to query the EventHeader data structure.  If no
argument is given, then the entire EventHeader hash is returned.  If a
single argument is given, then this is interpreted as a specific key, and
the value of that key in the EventHeader hash is returned.

   The keys in the EventHeader hash are the fields from the MQCFH
structure.  See the "MQSeries Programmable System Management"
documentation.

EventData
---------

   This method can be used to query the EventData data structure.  If no
argument is given, then the entire EventData hash is returned.  If a
single argument is given, then this is interpreted as a specific key, and
the value of that key in the EventData hash is returned.

   The keys in the EventData hash vary, depending on the specific event.
In general, these are the strings shown in the documentation for each
individual event described in the "MQSeries Programmable System
Management" documentation.  The data structures in the eventdata in the
original event are identified with macros, such as "MQCA_Q_MGR_NAME".
Rather than use these (in some cases very cryptic) macros, the strings
shown in the IBM MQSeries documentation are used instead.  In this case,
"QMgrName".

   The macros are mapped to strings as follows:

     Macro				Key
     =====				===
     MQCACF_APPL_NAME                     ApplName
     MQCACF_AUX_ERROR_DATA_STR_1          AuxErrorDataStr1
     MQCACF_AUX_ERROR_DATA_STR_2          AuxErrorDataStr2
     MQCACF_AUX_ERROR_DATA_STR_3          AuxErrorDataStr3
     MQCACF_BRIDGE_NAME                   BridgeName
     MQCACF_OBJECT_Q_MGR_NAME             ObjectQMgrName
     MQCACF_USER_IDENTIFIER               UserIdentifier
     MQCACH_CHANNEL_NAME                  ChannelName
     MQCACH_CONNECTION_NAME               ConnectionName
     MQCACH_FORMAT_NAME                   Format
     MQCACH_XMIT_Q_NAME                   XmitQName
     MQCA_BASE_Q_NAME                     BaseQName
     MQCA_PROCESS_NAME                    ProcessName
     MQCA_Q_MGR_NAME                      QMgrName
     MQCA_Q_NAME                          QName
     MQCA_XMIT_Q_NAME                     XmitQName
     MQIACF_AUX_ERROR_DATA_INT_1          AuxErrorDataInt1
     MQIACF_AUX_ERROR_DATA_INT_2          AuxErrorDataInt2
     MQIACF_BRIDGE_TYPE                   BridgeType
     MQIACF_COMMAND                       Command
     MQIACF_CONV_REASON_CODE              ConversionReasonCode
     MQIACF_ERROR_IDENTIFIER              ErrorIdentifier
     MQIACF_OPEN_OPTIONS                  Options
     MQIACF_REASON_QUALIFIER              ReasonQualifier
     MQIACH_CHANNEL_TYPE                  ChannelType
     MQIA_APPL_TYPE                       ApplType
     MQIA_HIGH_Q_DEPTH                    HighQDepth
     MQIA_MSG_DEQ_COUNT                   MsgDeqCount
     MQIA_MSG_ENQ_COUNT                   MsgEnqCount
     MQIA_Q_TYPE                          QType
     MQIA_TIME_SINCE_RESET                TimeSinceReset

SEE ALSO
========

   MQSeries(3), MQSeries::QueueManager(3), MQSeries::Queue(3),
MQSeries::Message(3)

Generic OO and procedurel interface to PCF (Programmable Command Format) messages.
**********************************************************************************

NAME
====

   MQSeries::Message::PCF - Generic OO and procedurel interface to PCF
(Programmable Command Format) messages.

SYNOPSIS
========

     #
     # Here's an example of creating a PCF Command (InquireQueue) to send
     # to the command server.  Note that this example is a bit contrived,
     # since you would normally use the higher level MQSeries::Command
     # object for this.
     #
     use MQSeries;
     use MQSeries::Message::PCF;

     #
     # The $header hash represents the MQCFH PCF Header.
     #
     $header =
     {
      Type		=> MQCFT_COMMAND,
      Command      => MQCMD_INQUIRE_Q,
     };

     #
     # The $parameters array is an array of hash references, each of
     # which individually represents one of the PCF parameter structures
     # (MQCFIN, MQCFST, MQCFIL, or MQCFSL).
     #
     $parameters =
     [

     # QName is a string (MQCFST)
     {
      Parameter	=> MQCA_Q_NAME,
      String	=> "FOO.*",
     },

     # QType is an integer (MQCFIN)
     {
      Parameter	=> MQIA_Q_TYPE,
      Value	=> MQQT_LOCAL,
     },

     # QAttrs in an integer list (MQCFIL)
     {
      Parameter	=> MQIACF_Q_ATTRS,
      Values	=>
      [
       MQCA_Q_NAME,
       MQIA_Q_TYPE,
       MQCA_Q_DESC,
       MQIA_MAX_Q_DEPTH,
       MQIA_MAX_MSG_LENGTH,
      ],
     },

     # Although not shown in this example, string lists (MQCFSL) have a
     # structure similar to the integer lists.

     ];

     my $message = MQSeries::Message::PCF->new
       (
        Header			=> $header,
        Parameters			=> $parameters,
       ) || die;

     #
     # The rest of the SYNOPSIS shows the procedural interface, which you
     # can use directly if you really want to, but the intent was for
     # MQEncodePCF and MQDecodePCF to be used as building blocks for OO
     # classes which further abstract the PCF data.  See the SEE ALSO
     # section for a list of modules which do exactly that.
     #
     use MQSeries;
     use MQSeries::Message::PCF qw(MQDecodePCF MQEncodePCF);

     my $msgdata = MQEncodePCF($header,$parameters);

     #
     # The reverse operation would be:
     #
     my ($header, $parameters) = MQDecodePCF($msgdata);

DESCRIPTION
===========

   This module is both an OO API to PCF messages, and a pair of exportable
procedures for encoding and decoding PCF messages.  The two functions are
imported by other classes which further parse and abstract specific PCF
formats.

   Note that it the intention of the author to provide specific
implementations of each of the standard PCF formats used in the MQSeries
product, and the current release already includes support for:

     PCF Command Server messages 		(MQSeries::Command)
     PubSub Administrative Messages 	(MQSeries::PubSub::AdminMessage)
     Performance Events 			(MQSeries::Message::Event)

   If you are reading this documentation with the intention of using it
for any of the above standard MQSeries messages, please see the docs for
those modules instead.

   This module optionally exports the core PCF parsing procedures used by
all of the above (MQEncodePCF and MQDecodePCF), and the OO API is provided
for completeness (and because, well, it was trivial).

METHODS
=======

   The MQSeries::Message::PCF class is a subclass of MQSeries::Message, so
all of the methods of the latter class are also available.

new
---

   The arguments to the MQSeries::Message::PCF constructor are passed
directly to the MQSeries::Message constructor, upon which this object is
based.  There are two additional keys supported by this class as well:
"Header" and "Parameters"

Header
     The value of this key is a HASH reference, representing the MQCFH PCF
     header structure.  See below for specific details.

Parameters
     The value of this key is an ARRAY reference of HASH references.  Each
     HASH reference represents one of the PCF parameters structures MQCFIN,
     MQCFST, MQCFIL, or MQCFSL.  See below for details.

PROCEDURES
==========

   Both of these procedures must be explicitly imported by the caller, and
they are provided as building blocks for higher level abstractions of the
PCF message format.  All of the previously mentioned OO classes in the
MQSeries heirarchy which implement PCF formats use these procedures in
this way.

MQEncodePCF
-----------

   This takes a pair of HASH references, for the PCF Header and Parameters
(format discussed below) and returns a string which is the binary encoding
of data into a set of C structures, suitable for use as the message body
for an MQSeries message of the appropriate PCF format type.

     my $msgdata = MQEncodePCF($header,$parameters);

   This routine returns the undefined value if an error is encountered
while encoding the data.

MQDecodePCF
-----------

   This takes a string, which is assumed to be the body of a PCF message,
and returns a pair of HASH references, each representing the PCF Header
and Parameters data structures (formats discussed below).

     my ($header,$parameters) = MQDecodePCF($msgdata);

   This routine returns an empty array if an error is encountered while
decoding the data.

Header and Parameter Data Structures
====================================

PCF Header (MQCFH)
------------------

   This is a HASH reference which represents the MQCFH PCF header
structure.  See the MQCFH documentation for the details of the keys which
can be given in this hash, and the specific PCF implementation
documentation for the possible values which can be given, since they vary
from one usage to another.

   Note that the "ParameterCount" key need not be specified, as the
MQEncodePCF() subroutine will calculate this automatically, by simply
counting the entries in the Parameters ARRAY.

   Also, the "StrucLength", and "Version" keys are handled automatically,
and need not be given.

   When this HASH is returned, all of the structures fields are returned
as keys in the HASH, although in most cases, you can ignore most of them.

PCF Parameters (MQCFIN, MQCFST, MQCFIL, or MQCFSL)
--------------------------------------------------

   This is an ARRAY reference or HASH references.  Each individual HASH
reference represents one of the PCF parameters structures, and each is
discussed individually.

   In all cases, the "Type" and "StrucLength" keys can be omitted, since
the "Type" is derived from the other keys present (if there is a "Value"
key, its a MQCFIN, a "String" key, its a MQCFST, etc).  In fact, both of
these keys will be entirely ignored.

   The "Parameter" values depend entirely on the specific usage of the PCF
format, with one set of possible values used for PCF command server
messages, and another for PubSub administrative messages, and yet another
for performance events.  See the respective documentation for each of
these formats for more information.

Integer Parameter (MQCFIN)
     This is a HASH reference with the following input keys:

          Parameter
          Value

     The "Value" must be a numeric value, or an error will be raised.

     When returned, it has the following output keys:

          Parameter
          Value
          Type (always == MQCFT_INTEGER)

String Parameter (MQCFST)
     This is a HASH reference with the following input keys (optional keys
     denoted by *):

          Parameter
          String
          CodedCharSetId*

     The "String" must have a string value, or an error will be raised.

     When returned, is has the following output keys:

          Parameter
          String
          CodedCharSetId
          Type (always == MQCFT_STRING)

Integer List Parameter (MQCFIL)
     This is a HASH reference with the following input keys:

          Parameter
          Values

     The "Values" must be an ARRAY reference of numeric values, or an error
     will be raised.  Note that the documented "Count" MQCFIL key may be
     omitted, since it is automatically calculated as the length of the
     ARRAY.

     When returned, it has the following output keys:

          Parameter
          Values
          Type (always == MQCFT_INTEGER_LIST)

String List Parameter (MQCFSL)
     This is a HASH reference with the following input keys (optional keys
     denoted by *):

          Parameter
          Strings
          CodedCharSetId*

     The "Strings" must be an ARRAY reference of string values, or an error
     will be raised.Note that the documented "Count" MQCFSL key may be
     omitted, since it is automatically calculated as the length of the
     ARRAY.

     When returned, it has the following output keys:

          Parameter
          Strings
          CodedCharSetId
          Type (always == MQCFT_STRING_LIST)

SEE ALSO
========

     MQSeries::Message::Event(3),
     MQSeries::Command::Request(3),
     MQSeries::Command::Response(3),
     MQSeries::PubSub::AdminMessage(3)

OO Class for sending and receiving perl references as MQSeries message application data
***************************************************************************************

NAME
====

   MQSeries::Message::Storable - OO Class for sending and receiving perl
references as MQSeries message application data

SYNOPSIS
========

     use MQSeries::Message::Storable;
     my $message = MQSeries::Message::Storable->new
       (
        Data => {
     	      some => "big ugly",
     	      complicated =>
     	      {
     	       data => [0..5],
     	       structure => [6..10],
     	      },
     	     },
       );

DESCRIPTION
===========

   This is a simple subclass of MQSeries::Message which support the use of
perl references as data structures in the message.  These references have
to be converted to a string of data which can be written to an MQSeries
message as application data, and for this the Storable module is used.

   The Storable::nfreeze and Storable::thaw subroutines are not very
forgiving.  If the input to nfreeze is not a perl reference, then the code
raises a fatal exception.  Similarly, if the input to thaw is not a frozen
perl reference (i.e. the output from a nfreeze() call), is also raises a
fatal exception.  Both of these are trapped with eval, but the data
conversion is considered to fail, and thus the Put(), Get(), or Put1()
method calls will subsequently fail.

   An object of this class will require that all of the messages put to or
gotten from any given queue use perl references as the underlying data
structure.  This also requires that both the putting and getting
application use this class to create the MQSeries messages.

METHODS
=======

PutConvert, GetConvert
----------------------

   Neither of these methods are called by the users application, but are
used internally by MQSeries::Queue::Put() and MQSeries::Queue::Get(), as
well as MQSeries::QueueManager::Put1().

   PutConvert() calls Storable::nfreeze to convert the perl reference
(which can be arbitrarily deep) to a scalar buffer which is then passed to
MQPUT() or MQPUT1().

   GetConvert() calls Storable::thaw to convert the contents of a message
retreived from a queue via MQGET() to a perl reference, which is then
inserted into the Data structure of the message object.

SEE ALSO
========

   MQSeries(3), MQSeries::QueueManager(3), MQSeries::Queue(3),
MQSeries::Message(3), Storable(3)

Dumper - OO Class for sending and receiving perl references as MQSeries message application data in XML format, using the XML::Dumper module
********************************************************************************************************************************************

NAME
====

   MQSeries::Message::XML-Dumper - OO Class for sending and receiving perl
references as MQSeries message application data in XML format, using the
XML::Dumper module

SYNOPSIS
========

     use MQSeries::Message::XML-Dumper;
     my $message = MQSeries::Message::XML-Dumper->new
       (
        Data 		=>
        {
         some 		=> "big ugly",
         complicated 	=>
         {
          data 		=> [0..5],
          structure 	=> [6..10],
         },
        },
       );

DESCRIPTION
===========

   This is a simple subclass of MQSeries::Message which support the use of
perl references as data structures in the message.  These references have
to be converted to a string of data which can be written to an MQSeries
message as application data, and for this the XML::Dumper module is used.

METHODS
=======

PutConvert, GetConvert
----------------------

   Neither of these methods are called by the users application, but are
used internally by MQSeries::Queue::Put() and MQSeries::Queue::Get(), as
well as MQSeries::QueueManager::Put1().

   PutConvert() calls XML::Dumper::pl2xml to convert the perl reference
(which can be arbitrarily deep) to a scalar buffer which is then passed to
MQPUT() or MQPUT1().

   GetConvert() calls XML::Dumper::xml2pl to convert the contents of a
message retreived from a queue via MQGET() to a perl reference, which is
then inserted into the Data structure of the message object.

SEE ALSO
========

   MQSeries(3), MQSeries::QueueManager(3), MQSeries::Queue(3),
MQSeries::Message(3), XML::Dumper(3)

OO interface to the MQSeries Queue objects
******************************************

NAME
====

   MQSeries::Queue - OO interface to the MQSeries Queue objects

SYNOPSIS
========

     use MQSeries;
     use MQSeries::Queue;
     use MQSeries::Message;

     #
     # Open a queue for output, loop getting messages, updating some
     # database with the data.
     #
     my $queue = MQSeries::Queue->new
       (
        QueueManager 	=> 'some.queue.manager',
        Queue 		=> 'SOME.QUEUE',
        Mode 		=> 'input_exclusive',
       )
       or die("Unable to open queue.\n");

     while ( 1 ) {

     my $getmessage = MQSeries::Message->new;

     $queue->Get
       (
        Message => $getmessage,
        Sync => 1,
       ) or die("Unable to get message\n" .
     	       "CompCode = " . $queue->CompCode() . "\n" .
     	       "Reason = " . $queue->Reason() . "\n");

     if ( UpdateSomeDatabase($getmessage->Data()) ) {
         $queue->Commit()
     	  or die("Unable to commit changes to queue.\n" .
     		 "CompCode = " . $queue->CompCode() . "\n" .
     		 "Reason = " . $queue->Reason() . "\n");
     } else {
         $queue->Backout()
     	  or die("Unable to backout changes to queue.\n" .
     		 "CompCode = " . $queue->CompCode() . "\n" .
     		 "Reason = " . $queue->Reason() . "\n");
     }

     }

     #
     # Put a message into the queue, using Storable to allow use of
     # references as message data. (NOTE: this is done for you if use the
     # MQSeries::Message::Storable class.)
     #
     use Storable;
     my $queue = MQSeries::Queue->new
       (
        QueueManager 	=> 'some.queue.manager',
        Queue 		=> 'SOME.QUEUE',
        Mode 		=> 'output',
        PutConvert        	=> \&Storable::nfreeze,
        GetConvert 	=> \&Storable::thaw,
       )
       or die("Unable to open queue.\n");

     my $putmessage = MQSeries::Message->new
       (
        Data => {
     	      a => [qw( b c d )],
     	      e => {
     		    f => "Huh?",
     		    g => "Wow!",
     		   },
     	      h => 42,
     	     },
       );

     $queue->Put( Message => $putmessage )
       or die("Unable to put message onto queue.\n" .
     	   "CompCode = " . $queue->CompCode() . "\n" .
     	   "Reason = " . $queue->Reason() . "\n");

     #
     # Alternate mechanism for specifying the conversion routines.
     #
     my $queue = MQSeries::Queue->new
       (
        QueueManager 	=> 'some.queue.manager',
        Queue 		=> 'SOME.QUEUE',
        Mode 		=> 'output',
       )
       or die("Unable to open queue.\n");

     my $putmessage = MQSeries::Message->new
       (
        Data => {
     	      a => [qw( b c d )],
     	      e => {
     		    f => "Huh?",
     		    g => "Wow!",
     		   },
     	      h => 42,
     	     },
       );

     $queue->Put(
     	      Message => $putmessage
     	      PutConvert => \&Storable::freeze,
     	     )
       or die("Unable to put message onto queue.\n" .
     	   "CompCode = " . $queue->CompCode() . "\n" .
     	   "Reason = " . $queue->Reason() . "\n");

DESCRIPTION
===========

   The MQSeries::Queue object is an OO mechanism for opening MQSeries
Queues, and putting and getting messages from those queues, with an
interface which is much simpler than the full MQI.

   This module is used together with MQSeries::QueueManager and
MQSeries::Message.  These objects provide a subset of the MQI, with a
simpler interface.

   The primary value added by this interface is logic to retry the
connection under certain failure conditions.  Basically, any Reason Code
which represents a transient condition, such as a Queue Manager shutting
down, or a connection lost (possible due to a network glitch?), will
result in the MQCONN call being retried, after a short sleep.  See below
for how to tune this behavior.

   This is intended to allow developers to write MQSeries applications
which recover from short term outages without intervention.  This behavior
is critically important to the authors applications, but may not be right
for yours.

METHODS
=======

new
---

   The arguments to the constructor are a hash, with the following
key/value pairs (required keys are marked with a '*'):

     Key                		Value
     ===                		=====
     QueueManager      		String, or MQSeries::QueueManager object
     Queue*             		String, or ARRAY reference (distribution list)
     Mode*              		String
     Options*           		MQOPEN 'Options' values
     CloseOptions	     		MQCLOSE 'Options' values
     DynamicQName			String
     DisableAutoResize  		Boolean
     NoAutoOpen    		Boolean
     ObjDesc            		HASH Reference
     Carp               		CODE Reference
     PutConvert         		CODE Reference
     GetConvert         		CODE Reference
     CompCode           		Reference to Scalar Variable
     Reason             		Reference to Scalar Variable
     RetrySleep			Numeric
     RetryCount			Numeric
     RetryReasons			HASH Reference

   NOTE: Only one or the 'Options' or 'Mode' keys can be specified.  They
are mutually exclusive.  If 'NoAutoOpen' is given, then both 'Options' and
'Mode' are optional, as they canbe passed directly to the Open() method.

QueueManager
     The Queue Manager to connect to must be specified, unless you want to
     connect to the "default" queue manager, and your site supports such a
     configuration.

     This can either be an MQSeries::QueueManager object, or the name of
     the Queue Manager.  Since the MQSeries::Queue object will internally
     create the MQSeries::QueueManager object, if given a name, this is the
     simpler mechanism.

     Code which opens multiple Queues on a single Queue Manager can be
     slightly optimized by creating the QueueManager object explicitly, and
     then reusing it for the multiple MQSeries::Queue objects which must be
     instantiated.  This will avoid a few unnecesary MQCONN calls, but this
     overhead should prove to be minimal in most cases.

     If the "default" queue manager is to be used, then the QueueManager
     argument can either be specified as the empty string "", or just
     omitted entirely.

Queue
     The name of the Queue obviously must be specified.  This can be either
     a plain ASCII string, indicating a single queue, or an ARRAY
     reference, indicating a distribution list.  There are three ways to
     specify the list.

     The list may be a simple array of strings:

          $queue = MQSeries::Queue->new
            (
             QueueManager 	=> "FOO",
             Queue 		=> [qw( QUEUE1 QUEUE2 QUEUE3 )],
            )

     or, it can be an array of arrays, each one specifying the queue and
     queue manager name of the target queue:

          $queue = MQSeries::Queue->new
            (
             QueueManager 	=> "FOO",
             Queue 		=> [
          			    [qw( QUEUE1 QM1 )],
          			    [qw( QUEUE2 QM2 )],
          			    [qw( QUEUE3 QM3 )],
          			   ],
            )

     or finally, it can be an array of hash references, each naming the
     queue and queue manager:

          $queue = MQSeries::Queue->new
            (
             QueueManager 	=> "FOO",
             Queue 		=>
             [
              {
               ObjectName	=> 'QUEUE1',
               ObjectQMgrName	=> 'QM1',
              },
              {
               ObjectName	=> 'QUEUE2',
               ObjectQMgrName	=> 'QM2',
              },
              {
               ObjectName	=> 'QUEUE3',
               ObjectQMgrName	=> 'QM3',
              },
             ],
            )

     In the latter two cases, the queue manager names are optional.  Which
     method to use is largely a choice of style.

Mode
     If the Mode key is specified, then the Options key may *NOT* be
     specified.  These are mutually exclusive.

     The Mode is a shorthand for opening the Queue for output or input,
     without requiring the developer to work with the Options flags
     directly.  The mode may have one of the following values, which
     implies the Options shown.

          Mode Value       Equivalent MQOPEN Options
          ==========       =========================
          input            MQOO_INPUT_AS_Q_DEF | MQOO_FAIL_IF_QUIESCING
          input_shared     MQOO_INPUT_SHARED | MQOO_FAIL_IF_QUIESCING
          input_exclusive  MQOO_INPUT_EXCLUSIVE | MQOO_FAIL_IF_QUIESCING
          output           MQOO_OUTPUT | MQOO_FAIL_IF_QUIESCING

Options
     If the Options key is specified, then the Mode key may *NOT* be
     specified.  These are mutually exclusive.  This is a used as-is as the
     Options field in the MQOPEN call.  Refer to the MQI documentation on
     MQOPEN() for more details.

CloseOptions
     This option allows you to specify the MQCLOSE() Options to be used
     when the perl object destructor closes the queue for you.  Since there
     are many close options to begin with, this is primarily useful for
     creating Permanent Dynamic queues that you want to automatically
     destroy when you are finished with them.

     The value specified here will be passed directly to the MQCLOSE()
     call, so it should be specified as:

          CloseOptions	=> MQCO_DELETE_PURGE,

     for example.

DynamicQName
     This is the template string to use when opening a dynamic queue.  This
     is only relevant is the Queue specified is a model queue.  Normally,
     this would be some kind of string ending in a '*', resulting in a
     unique queue name for the application.

DisableAutoResize
     This is a Boolean value, which if true, will disable the automatic
     resizing of the message buffer when it is either truncated, or the
     converted message will not fit.

     See the Get() method documentation for more information.

NoAutoOpen
     This will disable the implicit call to the Open() method by the
     constructor, thus requiring the application to call it itself.  This
     allows for more fine-grained error checking, since the constructur
     will then fail only if there is a problem parsing the constructor
     arguments.  The subsequent call to Open() can be error checked
     independently of the new() constructor.

ObjDesc
     The value of this key is a hash refernece which sets the key/values of
     the MsgDesc structure.  See the "MQSeries Application Programming
     Reference" documentation for the possible keys and values of the MQOD
     structure.

     Also, see the examples section for specific usage of this feature.
     This is one area of the API which is not easily hidden; you have to
     know what you are doing.

Carp
     This key specifies a code reference to a routine to replace all of the
     carp() calls in the API, allowing the user of the API to trap and
     handle all of the error message generated internally, or simply
     redirect how they get logged.

     For example, one might want everything to be logged via syslog:

          sub MyLogger {
              my $message = @_;
              foreach my $line ( split(/\n+/,$message) ) {
                  syslog("err",$message);
              }
          }

     Then, one tells the object to use this routine:

          my $queue = MQSeries::Queue->new
            (
             QueueManager 	=> 'some.queue.manager',
             Queue 		=> 'SOME.QUEUE',
             Carp 		=> \&MyLogger,
            ) or die("Unable to connect to queue manager.\n");

     The default, as one might guess, is Carp::carp();

PutConvert, GetConvert
     These are CODE references to subroutines which are used to convert the
     data in a MQSeries::Message object prior to passing it to the MQPUT
     MQI call, or convert the data retreived from the queue by the MQGET
     MQI call before inserting it into a MQSeries::Message object.

     See the MQSeries::QueueManager documentation for details on the
     calling and error handling syntax of these subroutines, as well as an
     example using Storable.pm to pass perl references around in MQSeries
     messages.

     If this key is not specified, then the MQSeries::Queue objects will
     inherit these CODE references from the MQSeries::QueueManager object.
     If the QueueManager key was given as a name, and not an object, then
     no conversion is performed.

     Note that these can be overridden for individual Put() or Get() calls,
     if necessary for a single message, just as PutConvert can be
     overridden for a single Put1() call (see MQSeries::QueueManager docs).

     Also, note that to disable these for a single message, or a single
     queue, one would simply pass a function that returns its first
     argument.

          PutConvert => sub { return $_[0]; },
          GetConvert => sub { return $_[0]; },

     See also the section "CONVERSION PRECEDENCE" in the
     MQSeries::QueueManager documentation.

CompCode, Reason
     WARNING: These keys are deprecated, and their use no longer
     encouraged.  They are left in place only for backwards compabitility.

     See the docs for the NoAutoOpen argument, and the Open() method.

     When the constructor encounters an error, it returns nothing, and you
     can not make method calls off of a non-existent object.  Thus, you do
     not have access to the CompCode() and Reason() method calls.  If you
     want to extract these values, you will have to pass a scalar reference
     value to the constructor, for example:

          my $CompCode = MQCC_FAILED;
          my $Reason = MQRC_UNEXPECTED_ERROR;

          my $queue = MQSeries::Queue->new
            (
             QueueManager		=> 'some.queue.manager',
             Queue			=> 'SOME,QUEUE',
             CompCode			=> \$CompCode,
             Reason			=> \$Reason,
            ) || die "Unable to open queue: CompCode => $CompCode, Reason => $Reason\n";

     But, this is ugly (authors opinion, but then, he gets to write the
     docs, too).

     NOTE: If you let the MQSeries::Queue object implicitly create the
     MQSeries::QueueManager object, and that fails, you will *NOT* get the
     CompCode/Reason values which resulted.  This is intentional.  If you
     want this level of granularity, then instantiante the
     MQSeries::QueueManager object yourself, and pass it to the
     MQSeries::Queue constructor.

     See the ERROR HANDLING section as well.

RetryCount
     The call to MQOPEN() (implemented via the Open() method), can be told
     to retry the failure for a specific list of reason codes.  This
     functionality is only enabled if the RetryCount is non-zero. By
     default, this value is zero, and thus retries are disabled.

RetrySleep
     This argument is the amount of time, in seconds, to sleep between
     subsequent retry attempts.

RetryReasons
     This argument is either an ARRAY or HASH reference indicating the
     specific reason code for which retries will be attempted.  If given as
     an ARRAY, the elements are simply the reason codes, and if given as a
     HASH, then the keys are the reason codes (and the values ignored).

Open
----

   This method will accept the following arguments which can be passed to
the constructor (new()), and it merely calls Open() to open the actual
queue object.

     Key                		Value
     ===                		=====
     Mode              		String
     Options           		MQOPEN 'Options' values
     RetrySleep			Numeric
     RetryCount			Numeric
     RetryReasons			HASH Reference

   This method is called automatically by the constructor, unless the
NoAutoOpen argument is given.

   Note that this is a new method as of the 1.06 release, and is provided
to enable more fine grained error checking.  See the ERROR HANDLING
section.

Close
-----

   The arguments to this method are a hash of key/value pairs, and
currently only one key is supported: "Options".  The value is the Options
argument to MQCLOSE().  This will override the "CloseOptions" passed to
the constructor.  This method merely calls MQCLOSE() to close the actual
queue object.

   It is important to note that normally, this method need not be called,
since it is implicitly called via the object destructor.  If the Close()
call errors need to be handled, then it can be done explicitly.  See the
ERROR HANDLING section.

Put
---

   This method wraps the MQPUT call.  The arguments are a hash, with the
following key/value pairs (required keys are marked with a '*'):

     Key         Value
     ===         =====
     Message*    MQSeries::Message object
     PutMsgOpts  HASH Reference
     PutMsgRecs  ARRAY Reference
     Sync        Boolean
     PutConvert  CODE Reference

   The return value is true or false, depending on the success of the
underlying MQPUT() call.  If the operation fails, then the Reason() and
CompCode() methods will return the appropriate error codes, if the error
was an MQSeries error.

   If a PutConvert() method failed before the actual MQPUT() function was
called, then the Reason() code will be MQRC_UNEXPECTED_ERROR, and the
PutConvertReason() will be true.  All of the PutConvert() methods supplied
with the various MQSeries::Message subclasses in this distribution will
generate some form of error via carp (or the Carp attribute of the
objects, if overridden).

Message
     This argument is the message to be placed onto the queue.  The value
     must be an MQSeries::Message object.

PutMsgOpts
     This option allows the programmer complete control over the PutMsgOpts
     structure passed to the MQPUT() call.  If this option is specified,
     then the Sync option is simply ignored.

     The default options specified by the OO API are

          MQGMO_FAIL_IF_QUIESCING

     See the MQPUT() documentation for the use of PutMsgOpts.

PutMsgRecs
     This argument is relevant only when using distribution lists.

     The value is an ARRAY reference, specifying the put message records
     for the individual queues in the distribution list.  Normally, these
     are specified as part of the PutMsgOpts, but this API attempts to hide
     the complexity of the PutMsgOpts structure from the user.

     When using distribution lists, PutMsgRecs are often necessary to
     control how the MsgId, CorrelId, and three other specific fields in
     the MsgDesc are handled.

     For details, see the MQPUT() and MQPUT1() documentation in
     MQSeries(3).

Sync
     This is a flag to indicate that the Syncpoint option is to be used,
     and the message(s) not committed to the queue until an MQBACK or
     MQCOMM call is made.  These are both wrapped with the Backout() and
     Commit() methods respectively.

     The value is simply interpreted as true or false.

PutConvert
     This is a means of overriding the PutConvert routine specified for the
     MQSeries::Queue object, for a single Put.  See the new() documentation
     for more details.

Get
---

   This method wraps the MQGET call.  The arguments are a hash, with the
following key/value pairs (required keys are marked with a '*'):

     Key                Value
     ===                =====
     Message*           MQSeries::Message object
     GetMsgOpts         HASH Reference
     Wait               Numeric Value
     Sync               Boolean
     DisableAutoResize  Boolean
     GetConvert         CODE Reference

   The return value of Get() is either 1, 0 or -1.  Success or failure can
still be interpreted in a Boolean context, with the following caveat.  A
value of 1 is returned when a message was successfully retreives from the
queue.  A value of 0 is returned if some form of error was encountered.  A
value of -1 is returned when no message was retreived, but the MQGET call
failed with a Reason Code of "MQRC_NO_MSG_AVAILABLE".

   The last condition (-1) may or may not be an error, depending on your
application.  This merely indicates that a message matching the specified
MsgDesc criteria was not found, or perhaps the queue was just empty.  You
have to decide how to handle this.

   The return value of 0 may indicate an error in either the MQSeries call
itself, or if applicable, the failure of any GetConvert() method called
after a successful MQGET() call.  In this case, the GetConvertReason()
should be checked, as this error may indicate an invalid or improperly
formatted message.  This is akin to an error encountered while parsing the
body of the message.

   By default, the Get() method will also handle the message buffer size
being too small for two very specific cases.

   Case 1:  Reason == MQRC_TRUNCATED_MSG_FAILED

   In this case, the BufferLength of the Message object is reset to the
DataLength value returned by the MQGET() call, and the MQGET() call is
redone.

   Case 2:  Reason == MQRC_CONVERTED_MSG_TOO_BIG

   In this case, the BufferLength of the Message object is reset to
*twice* the DataLength value returned by the MQGET() call, and the MQGET()
call is redone.  Doubling the size is probably overkill, but there is no
deterministic way of finding the actual size required.  Since most of the
conversions are character set mappings, we are assuming that double will
always be sufficient.

   Note that this functionality can be disabled, if not desired, by
specifying DisableAutoResize as an argument to either the
MQSeries::Queue->new() constructor or the Get() method.

Message
     This argument is the MQSeries::Message object into which the message
     extracted from the queue is placed.  This can be a 'raw'
     MQSeries::Message, or it can be one with the MsgId, or some other key
     in the MsgDesc explicitly specified, in order to retreive a specific
     message.  See MQSeries::Message documentation for more details.

GetMsgOpts
     This option allows the programmer complete control over the GetMsgOpts
     structure passed to the MQGET() call.  If this option is specified,
     then the Sync, and Wait options are simply ignored.

     The default options specified by the OO API are

          MQGMO_FAIL_IF_QUIESCING
          MQGMO_CONVERT

     See the MQGET() documentation for the use of GetMsgOpts.

Wait
     This is a numeric or symbolic value, interpreted as follows.  A
     symbolic value is a number ending on 's' for seconds or 'm' for
     minutes, which will be converted to the appropriate numeric value.
     If the value is greater than zero, then the MQGMO_WAIT option is used,
     and the value is set as the WaitInterval in the GetMsgOpts structure.

     Remember, if a numeric value is specified, it is interpreted by the
     API as a number of milliseconds, not seconds (the rest of the OO-API
     uses seconds).

     If the value is 0, then the MQGMO_NO_WAIT option is used.

     If the value is -1, then the MQGMO_WAIT option is used, and the
     WaitInterval is set to MQWI_UNLIMITED, meaning the MQGET call will
     block until a message appears on the queue.

     The default is 0, the same as the MQGET() call itself.

     NOTE: MQWI_UNLIMITED should be used with caution, as applications
     which block forever can prevent queue managers from shutting down
     elegantly, in some cases.

Sync
     This is a flag to indicate that the Syncpoint option is to be used,
     and the message(s) not committed to the queue until an MQBACK or
     MQCMIT call is made.  These are both wrapped with the Backout() and
     Commit() methods respectively.

     The value is simply interpreted as true or false.

DisableAutoResize
     This is a Boolean value, which if true, will disable the automatic
     resizing of the message buffer when it is either truncated, or the
     converted message will not fit.

GetConvert
     This is a means of overriding the GetConvert routine specified for the
     MQSeries::Queue object, for a single Get.  See the new() documentation
     for more details.

Inquire
-------

   This method is an interface to the MQINQ() API call, however, it takes
more convenient, human-readable strings in place of the C macros for the
selectors, as well as supports more readable strings for some of the data
values as well.

   For example, to query the MaxMsgLength and MaxQDepth of a queue:

     my %qattr = $queue->Inquire( qw(MaxMsgLength MaxQDepth) );

   The argument to this method is a list of "selectors", or Queue
attributes, to be queried.  The following table shows the complete set of
possible keys, and their underlying C macro.

   Note that this list is all-inclusive, and that many of these are not
supported on some of the MQSeries platforms.  Consult the IBM
documentation for such details.

     Key				Macro
     ===				=====
     AlterationDate              MQCA_ALTERATION_DATE
     AlterationTime              MQCA_ALTERATION_TIME
     BackoutRequeueName          MQCA_BACKOUT_REQ_Q_NAME
     BackoutThreshold            MQIA_BACKOUT_THRESHOLD
     BaseQName                   MQCA_BASE_Q_NAME
     ClusterDate                 MQCA_CLUSTER_DATE
     ClusterName                 MQCA_CLUSTER_NAME
     ClusterNamelist             MQCA_CLUSTER_NAMELIST
     ClusterQType                MQIA_CLUSTER_Q_TYPE
     ClusterTime                 MQCA_CLUSTER_TIME
     CreationDate                MQCA_CREATION_DATE
     CreationTime                MQCA_CREATION_TIME
     CurrentQDepth               MQIA_CURRENT_Q_DEPTH
     DefBind                     MQIA_DEF_BIND
     DefInputOpenOption          MQIA_DEF_INPUT_OPEN_OPTION
     DefPersistence              MQIA_DEF_PERSISTENCE
     DefPriority                 MQIA_DEF_PRIORITY
     DefinitionType              MQIA_DEFINITION_TYPE
     DistLists                   MQIA_DIST_LISTS
     HardenGetBackout            MQIA_HARDEN_GET_BACKOUT
     HighQDepth                  MQIA_HIGH_Q_DEPTH
     InhibitGet                  MQIA_INHIBIT_GET
     InhibitPut                  MQIA_INHIBIT_PUT
     InitiationQName             MQCA_INITIATION_Q_NAME
     MaxMsgLength                MQIA_MAX_MSG_LENGTH
     MaxQDepth                   MQIA_MAX_Q_DEPTH
     MsgDeliverySequence         MQIA_MSG_DELIVERY_SEQUENCE
     MsgDeqCount                 MQIA_MSG_DEQ_COUNT
     MsgEnqCount                 MQIA_MSG_ENQ_COUNT
     OpenInputCount              MQIA_OPEN_INPUT_COUNT
     OpenOutputCount             MQIA_OPEN_OUTPUT_COUNT
     ProcessName                 MQCA_PROCESS_NAME
     QDepthHighEvent             MQIA_Q_DEPTH_HIGH_EVENT
     QDepthHighLimit             MQIA_Q_DEPTH_HIGH_LIMIT
     QDepthLowEvent              MQIA_Q_DEPTH_LOW_EVENT
     QDepthLowLimit              MQIA_Q_DEPTH_LOW_LIMIT
     QDepthMaxEvent              MQIA_Q_DEPTH_MAX_EVENT
     QDesc                       MQCA_Q_DESC
     QMgrIdentifier              MQCA_Q_MGR_IDENTIFIER
     QMgrName                    MQCA_CLUSTER_Q_MGR_NAME
     QName                       MQCA_Q_NAME
     QNames                      MQCACF_Q_NAMES
     QServiceInterval            MQIA_Q_SERVICE_INTERVAL
     QServiceIntervalEvent       MQIA_Q_SERVICE_INTERVAL_EVENT
     QType                       MQIA_Q_TYPE
     RemoteQMgrName              MQCA_REMOTE_Q_MGR_NAME
     RemoteQName                 MQCA_REMOTE_Q_NAME
     RetentionInterval           MQIA_RETENTION_INTERVAL
     Scope                       MQIA_SCOPE
     Shareability                MQIA_SHAREABILITY
     TimeSinceReset              MQIA_TIME_SINCE_RESET
     TriggerControl              MQIA_TRIGGER_CONTROL
     TriggerData                 MQCA_TRIGGER_DATA
     TriggerDepth                MQIA_TRIGGER_DEPTH
     TriggerMsgPriority          MQIA_TRIGGER_MSG_PRIORITY
     TriggerType                 MQIA_TRIGGER_TYPE
     Usage                       MQIA_USAGE
     XmitQName                   MQCA_XMIT_Q_NAME

   The return value of this method is a hash, whose keys are those given
as arguments, and whose values are the queried queue attributes.  In most
cases, the values are left unmolested, but in the following cases, the
values are mapped to more readable strings.

DefBind  			(integer)
          Key				Macro
          ===				=====
          OnOpen                      MQBND_BIND_ON_OPEN
          NotFixed                    MQBND_BIND_NOT_FIXED

DefinitionType		(integer)
          Key				Macro
          ===				=====
          Permanent                   MQQDT_PERMANENT_DYNAMIC
          Temporary                   MQQDT_TEMPORARY_DYNAMIC

DefInputOpenOption    	(integer)
          Key				Macro
          ===				=====
          Exclusive                   MQOO_INPUT_EXCLUSIVE
          Shared                      MQOO_INPUT_SHARED

MsgDeliverySequence    	(integer)
          Key				Macro
          ===				=====
          FIFO                        MQMDS_FIFO
          Priority                    MQMDS_PRIORITY

QServiceIntervalEvent    	(integer)
          Key				Macro
          ===				=====
          High                        MQQSIE_HIGH
          None                        MQQSIE_NONE
          OK                          MQQSIE_OK

QType    			(integer)
          Key				Macro
          ===				=====
          Alias                       MQQT_ALIAS
          All                         MQQT_ALL
          Cluster                     MQQT_CLUSTER
          Local                       MQQT_LOCAL
          Model                       MQQT_MODEL
          Remote                      MQQT_REMOTE

Scope    			(integer)
          Key				Macro
          ===				=====
          Cell                        MQSCO_CELL
          QMgr                        MQSCO_Q_MGR

TriggerType    		(integer)
          Key				Macro
          ===				=====
          Depth                       MQTT_DEPTH
          Every                       MQTT_EVERY
          First                       MQTT_FIRST
          None                        MQTT_NONE

Usage    			(integer)
          Key				Macro
          ===				=====
          Normal                      MQUS_NORMAL
          XMITQ                       MQUS_TRANSMISSION

Set
---

   This method is an interface to the MQSET() API call, and like
Inquire(), it takes more convenient, human-readable strings in place of
the C macros.

   For example, to put inhibit a queue:

     $queue->Set( InhibitPut => 1 );

   The argument to this method is a hash of key/value pairs representing
queue attributes to be set.  The MQSET() API supports setting a very
limited subset of specific queue attributes.  The following table shows
the complete set of possible keys, and their underlying C macros.

     Key				Macro
     ===				=====
     InhibitGet                  MQIA_INHIBIT_GET
     InhibitPut                  MQIA_INHIBIT_PUT
     DistLists                   MQIA_DIST_LISTS
     TriggerControl              MQIA_TRIGGER_CONTROL
     TriggerData                 MQCA_TRIGGER_DATA
     TriggerDepth                MQIA_TRIGGER_DEPTH
     TriggerMsgPriority          MQIA_TRIGGER_MSG_PRIORITY
     TriggerType                 MQIA_TRIGGER_TYPE

   In addition, the data value for the "TriggerType" key can have one of
the following values:

     Key				Macro
     ===				=====
     Depth                       MQTT_DEPTH
     Every                       MQTT_EVERY
     First                       MQTT_FIRST
     None                        MQTT_NONE

   All of the other values are simply Boolean (0 or 1), with the exception
of "TriggerData", which is a string.

   This method call returns true upon success, and false upon failure.
CompCode() and Reason() will be set appropriately.

ObjDesc
-------

   This method can be used to query the ObjDesc data structure.  If no
argument is given, then the ObjDesc hash reference is returned.  If a
single argument is given, then this is interpreted as a specific key, and
the value of that key in the ObjDesc hash is returned.

Backout
-------

   This method takes no arguments, and merely calls MQBACK.  It returns
true on success, and false on failure.

   NOTE: This operation is in reality not specific to the Queue, but
rather to the Queue Manager connection.  Because the API does not require
the developer to specifically open a Queue Manager connection (via an
MQSeries::QueueManager object), but will do so implicitly (see the new()
documentation above), these methods are provided as part of the
MQSeries::Queue API.  Note, however, that this does *NOT* imply that
syncpoint operations can be performed at the individual Queue level.
Transactions are still per-queue manager connection.

Commit
------

   This method takes no arguments, and merely calls MQCMIT.  It returns
true on success, and false on failure.

   NOTE: The same comments for Backout() apply here.  This is really a
Queue Manager connection operation.

CompCode
--------

   This method returns the MQI Completion Code for the most recent MQI
call attempted.

Reason
------

   This method returns the MQI Reason Code for the most recent MQI call
attempted.

PutConvertReason
----------------

   This method returns a true of false value, indicating if a PutConvert
method failed or not.  Similar to the MQRC reason codes, false indicates
success, and true indicates some form of error.  If there was no
PutConvert method called, this will always return false.

GetConvertReason
----------------

   This method returns a true of false value, indicating if a GetConvert
method failed or not.  Similar to the MQRC reason codes, false indicates
success, and true indicates some form of error.  If there was no
GetConvert method called, this will always return false.

Reasons
-------

   This method call returns an array reference, and each member of the
array is a Response Record returned as a possible side effect of calling a
Put() method to put a message to a distribution list.

   The individual records are hash references, with two keys: CompCode and
Reason.  Each provides the specific CompCode and Reason associated with
the put of the message to each individual queue in the distribution list,
respectively.

Pending
-------

   This method indicated whether or not there are currently actively
pending transactions (puts or gets under syncpoint).

MQOPEN RETRY SUPPORT
====================

   Normally, when MQOPEN() fails, the method that called it (Open() or
new()) also fails.  It is possible to have the Open() method retry the
MQOPEN() call for a specific set of reason codes.

   By default,  the retry logic  is  disabled, but it  can  be enabled by
setting the RetryCount to a non-zero value.  The  list of reason codes
defaults to just MQRC_OBJECT_IN_USE, but a list of retryable codes can be
specified via the RetryReasons argument.

   You are probably wondering why this logic is useful for MQOPEN().  The
choice of the default RetryReasons is not without its own reason.

   Consider an application that opens a queue for exclusive input.  If
that application crashes and restarts, there will typically be a window of
time when the queue manager has not yet noticed that the crashed
application instance has died.  The application which has been restarted
will not fail to open the queue, and MQOPEN() will set the reason to
MQRC_OBJECT_IN_USE.

   By retrying this particular reason code, and tuning the RetryCount and
RetrySleep to be consistent with the timeout on the queue manager,
applications can restart, reconnect and reopen these queues transparently.

   There are almost certainly other scenarios where the RetryReasons may
need to be customized, and thus the code supports this flexibility.

ERROR HANDLING
==============

   Most methods return a true or false value indicating success of
failure, and internally, they will call the Carp subroutine (either
Carp::carp(), or something user-defined) with a text message indicating
the cause of the failure.

   In addition, the most recent MQI Completion and Reason codes will be
available via the CompCode() and Reason() methods:

     $queue->CompCode()
     $queue->Reason()

   When distribution lists are used, then it is possible for a list of
reason codes to be returned by the API.  Normally, these are buried inside
the ObjDesc strucure, but they are also available via the

     $queue->Reasons()

   method.  In this case, the $queue->Reason() will always return
MQRC_MULTIPLE_REASONS.  The return value of the Reasons() method is an
array reference, and each array item is a hash reference with two keys:
CompCode and Reason.  These correspond, respectively, with the CompCode
and Reason associated with the individual queues in the distribution list.

   For example, the Reason code associated with the 3rd queue in the list
would be:

     $queue->Reasons()->[2]->{Reason}

   In the case of the constructor new(), which returns nothing when it
fails, these methods are not available.  Most applications will not need
to handle the specific CompCode and Reason when the instantiation fails,
but if necessary, these can be obtained in one of two ways.

   The older method, which is supported for backwards compabitility but
strongly discouarged, is to pass references to scalar variables to new().
See the new() documentation above for more details.

   The newer method would be to explicitly call the Open() method, and
error check it yourself.  This will mean that the constructor will now
fail only if there is an error processing the constructor arguments, as
opposed to an error in the MQSeries infrastructure.

   Some examples should make this clear.

   The simplest way to create an MQSeries::Queue object is:

     my $queue = MQSeries::Queue->new
       (
        QueueManager		=> 'some.queue.manager',
        Queue			=> 'SOME.QUEUE',
        Mode			=> 'input',
       ) || die;

   But in this case, either the connection to the queue manager or the
open of the queue could fail, and your application will not be able to
determine why.

   In order to explicitly have access to the CompCode and Reason one would
do the following:

     # Explicitly create your own MQSeries::QueueManager object
     my $qmgr = MQSeries::QueueManager->new
       (
        QueueManager		=> 'some.queue.manager',
        DisableAutoConnect		=> 1,
       ) || die "Unable to instantiate MQSeries::QueueManager object\n";

     # Call the Connect method explicitly
     unless ( $qmgr->Connect() ) {
       die("Connection to queue manager failed\n" .
           "CompCode => " . $qmgr->CompCode() . "\n" .
           "Reason   => " . $qmgr->Reason() . "\n");
     }

     my $queue = MQSeries::Queue->new
       (
        QueueManager		=> $qmgr,
        Queue			=> 'SOME.QUEUE',
        Mode			=> 'input',
        NoAutoOpen			=> 1,
       ) || die "Unable to instantiate MQSeries::Queue object\n";

     # Call the Open method explicitly
     unless ( $queue->Open() ) {
       die("Open of queue failed\n" .
           "CompCode => " . $queue->CompCode() . "\n" .
           "Reason   => " . $queue->Reason() . "\n");
     }

SEE ALSO
========

   MQSeries(3), MQSeries::QueueManager(3), MQSeries::Message(3),
MQSeries::Message::Storable(3)

OO interface to the MQSeries Queue Manager
******************************************

NAME
====

   MQSeries::QueueManager - OO interface to the MQSeries Queue Manager

SYNOPSIS
========

     use MQSeries;
     use MQSeries::QueueManager;

     #
     # Simplest, trivial usage
     #
     my $qmgr = MQSeries::QueueManager->new( QueueManager => 'some.queue.manager' ) ||
       die("Unable to connect to queue manager\n");

     #
     # The best way to do error checking.  Handle the object
     # instantiation and connection to the queue manager independently.
     #
     my $qmgr = MQSeries::QueueMananer->new
       (
        QueueManager	=> 'some.queue.manager',
        NoAutoConnect	=> 1,
       ) || die "Unable to instantiate MQSeries::QueueManager object\n";

     $qmgr->Connect() ||
       die("Unable to connect to queue manager\n" .
     	"CompCode => " . $qmgr->CompCode() . "\n" .
     	"Reason => " . $qmgr->Reason() . "\n");

     #
     # Advanced usage.  Enable the connection timeout, and connection
     # retry logic.
     #
     my $qmgr = MQSeries::QueueManager->new
       (
        QueueManager 	=> 'some.queue.manager',
        NoAutoConnect	=> 1,
        ConnectTimeout	=> 120,
        RetryCount 	=> 60,
        RetrySleep 	=> 10,
       ) || die "Unable to instantiate MQSeries::QueueManager object\n";

     $qmgr->Connect() ||
       die("Unable to connect to queue manager\n" .
     	"CompCode => " . $qmgr->CompCode() . "\n" .
     	"Reason => " . $qmgr->Reason() . "\n");

DESCRIPTION
===========

   The MQSeries::QueueManager object is an OO mechanism for connecting to
an MQSeries queue manager, and/or opening and inquiring a queue manager
object.

   This module is used together with MQSeries::Queue and
MQSeries::Message, and the other MQSeries::* modules.  These objects
provide a simpler, higher level interface to the MQI.

   This module also provides special support for connect timeouts (for
interrupting MQCONN() calls that may hang forever), as well as connect
retry logic, which will retry failed MQCONN() calls for a specific list of
reason codes.

   See the "Special Considerations" section for a discussion of these
advanced, but powerful, features.

METHODS
=======

new
---

   The constructor takes a hash as an argument, with the following keys:

     Key            		Value
     ===            		=====
     QueueManager  		String
     Carp           		CODE reference
     NoAutoConnect			Boolean
     AutoCommit			Boolean
     ConnectTimeout		Numeric
     ConnectTimeoutSignal		String
     GetConvert     		CODE reference
     PutConvert     		CODE reference
     RetrySleep			Numeric
     RetryCount			Numeric
     RetryReasons			HASH Reference
     CompCode       		Reference to Scalar Variable
     Reason         		Reference to Scalar Variable

QueueManager
     This is simply the name of the Queue Manager to which to connect.
     This is passed directly to the MQCONN() call as-is.

     Normally, this is simply the name of the queue manager to which you
     wish to connect, but if the "default" queue manager is to be used,
     then this can either be the empty string "", or simply omitted
     entirely.

Carp
     This key specifies a code reference to a routine to replace all of the
     carp() calls in the API, allowing the user of the API to trap and
     handle all of the error message generated internally, or simply
     redirect how they get logged.

     For example, one might want everything to be logged via syslog:

          sub MyLogger {
              my $message = @_;
              foreach my $line ( split(/\n+/,$message) ) {
                  syslog("err",$message);
              }
          }

     Then, one tells the object to use this routine:

          my $qmgr = MQSeries::QueueManager->new
            (
             QueueManager 	=> 'some.queue.manager',
             Carp 		=> \&MyLogger,
            ) || die("Unable to connect to queue manager.\n");

     The default, as one might guess, is Carp::carp();

NoAutoConnect
     If the value of this argument is true, then the constructor will not
     automatically call the Connect() method, allowing the developer to
     call it explicitly, and thus independently error check object
     instantiation and the connection to the queue manager.  See the
     section on Error Handling in Special Considerations.

AutoCommit
     If the value of this argument is true, then pending transactions will
     be committed during object destruction.  If it is false, then pending
     transactions will be backed out before disconnecting from the queue
     manager during object destruction.

     See the section on "AutoCommit" in "Special Considerations".

ConnectTimeout
     If this value is given, it must be a positive integer.  This is the
     time, in seconds, in which an MQCONN() must complete before the MQI
     call will be interrupted.  The default value is zero, which means the
     MQCONN() call will not be interrupted.

     There are outage scenarios, in the experience of the author, where the
     MQCONN() call will block indefinetely and never return.  This happens
     when a queue manager is "hung", and completely unresponsive, in some
     cases.

     This feature should be used with caution, since it is implemented
     using a SIGALRM handler, and the alarm() system call.  See the section
     on "Connection Timeouts" in "Special Considerations".

     Attempts to use this feature on unsupported platforms that do not
     support signals will generate a warning, and be silently ignored.

ConnectTimeoutSignal
     By default, the ConnectTimeout mechanism is implemented using a signal
     handler for SIGUSR1, but the signal used to interrupt the MQCONN()
     call can be customized using this attribute.

     The signal handler installed by this API is done using local(), so the
     effects of the handler will only override the applications handler
     during the call to MQCONN().

     The string used for this attribute should be the short hand name of
     the signal, for example, to set the signal to SIGUSR2:

          my $qmgr = MQSeries::QueueManager->new
            (
             QueueManager		=> 'FOO',
             ConnectTimeout		=> 300,
             ConnectTimeoutSignal	=> 'USR2',
            ) || die;

RetryCount
     This is an integer value, and specifies the maximum number of times to
     retry the connection, before failing.  The default is 0.

RetrySleep
     This is an integer value, and specified the number of seconds to sleep
     between retries.  The maximum timeout for an outage is the product of
     the RetrySleep and RetryCount parameters.  The default is 0.

PutConvert, GetConvert
     These are CODE references to subroutines which are used to convert the
     data in a MQSeries::Message object prior to passing it to the MQPUT
     MQI call, or convert the data retreived from the queue by the MQGET
     MQI call before inserting it into a MQSeries::Message object.

     These must be CODE references, or the new() constructor will fail.  A
     properly written conversion routine will be passed a single scalar
     value and return a single scalar value.  In the event of an error, the
     conversion routine should return 'undef'.

     The example shown in the synopsis shows how one might use a pair of
     home grown encryption and decryption subroutines to keep data in clear
     text in core, but encrypted in the contents of the message on the
     queue.  This is probably not the most hi-tech way to encrypt MQSeries
     data, of course.

     The MQSeries::Message::Storable class provides an example of how to
     subclass MQSeries::Message to have this type of conversion handled
     transparently, in the class definition.

CompCode, Reason
     WARNING: These keys are deprecated, and their use no longer
     encouraged.  They are left in place only for backwards compabitility.

     See the docs for the NoAutoConnect argument, and the Connect() method.

     When the constructor encounters an error, it returns nothing, and you
     can not make method calls off of a non-existent object.  Thus, you do
     not have access to the CompCode() and Reason() method calls.  If you
     want to extract these values, you will have to pass a scalar reference
     value to the constructor, for example:

          my $CompCode = MQCC_FAILED;
          my $Reason = MQRC_UNEXPECTED_ERROR;

          my $qmgr = MQSeries::QueueManager->new
            (
             QueueManager		=> 'some.queue.manager',
             CompCode			=> \$CompCode,
             Reason			=> \$Reason,
            ) || die "Unable to open queue: CompCode => $CompCode, Reason => $Reason\n";

     But, this is ugly (authors opinion, but then, he gets to write the
     docs, too).

RetryCount
     The call to MQCONN() (implemented via the Connect() method), can be
     old to retry the failure for a specific list of reason codes.  This
     functionality is only enabled if the RetryCount is non-zero. By
     default, this value is zero, and thus retries are disabled.

RetrySleep
     This argument is the amount of time, in seconds, to sleep between
     subsequent retry attempts.

RetryReasons
     This argument is either an ARRAY or HASH reference indicating the
     specific reason code for which retries will be attempted.  If given as
     an ARRAY, the elements are simply the reason codes, and if given as a
     HASH, then the keys are the reason codes (and the values ignored).

Connect
-------

   This method takes no arguments, and merely calls MQCONN() to connect to
the queue manager.  The various options are all set via the
MQSeries::Queue constructor (see above).

   This method is called automatically by the constructor, unless the
NoAutoConnect argument is given.

   Note that this is a new method as of the 1.06 release, and is provided
to enable more fine grained error checking.  See the ERROR HANDLING
section.

Disconnect
----------

   This methodtakes no arguments, and merely calls MQDISC() to disconnect
from the queue manager.

   It is important to note that normally, this method need not be called,
since it is implicitly called via the object destructor.  If the
Disconnect() call errors need to be handled, then it can be done
explicitly.  See the ERROR HANDLING section.

Backout
-------

   This method takes no arguments, and merely calls MQBACK.  It returns
true on success, and false on failure.

Commit
------

   This method takes no arguments, and merely calls MQCMIT.  It returns
true on success, and false on failure.

Put1
----

   This method wraps the MQPUT1 call.  The arguments are a hash, with the
following key/value pairs (required keys are marked with a '*'):

     Key           Value
     ===           =====
     Message*      MQSeries::Message object
     Queue         String, or ARRAY reference (distribution list)
     QueueManager  String
     ObjDesc       HASH reference
     PutMsgOpts    HASH Reference
     PutMsgRecs    ARRAY Reference
     Sync          Boolean
     PutConvert    CODE reference

   The return value is true or false, depending on the success of the
underlying MQPUT1() call.  If the operation fails, then the Reason() and
CompCode() methods will return the appropriate error codes, if the error
was an MQSeries error.

   If a PutConvert() method failed before the actual MQPUT1() function was
called, then the Reason() code will be MQRC_UNEXPECTED_ERROR, and the
PutConvertReason() will be true.  All of the PutConvert() methods supplied
with the various MQSeries::Message subclasses in this distribution will
generate some form of error via carp (or the Carp attribute of the
objects, if overridden).

Message
     This argument is the message to be placed onto the queue.  The value
     must be an MQSeries::Message object.

Queue
     This is the queue, or list of queue if using a distribution list, to
     which to put the message.  If it is a single queue, then this value is
     a string, naming the queue.  If it is a distribution list, then this
     value is an ARRAY reference, listing the target queues.  There are
     three ways to specify the list.

     The list may be a simple array of strings:

          $qmgr->Put1(
                      Message => $message,
                      Queue => [qw( QUEUE1 QUEUE2 QUEUE3 )],
                     )

     or, it can be an array of arrays, each one specifying the queue and
     queue manager name of the target queue:

          $qmgr->Put1(
                      Message => $message,
                      Queue => [
                                [qw( QUEUE1 QM1 )],
                                [qw( QUEUE2 QM2 )],
                                [qw( QUEUE3 QM3 )],
                               ],
                     )

     or finally, it can be an array of hash references, each naming the
     queue and queue manager:

          $qmgr->Put1(
                      Message => $message,
                      Queue => [
          	                {
          			 ObjectName		=> 'QUEUE1',
          			 ObjectQMgrName		=> 'QM1',
          			},
          		        {
          			 ObjectName		=> 'QUEUE2',
          			 ObjectQMgrName		=> 'QM2',
          			},
          			{
          			 ObjectName		=> 'QUEUE3',
          			 ObjectQMgrName		=> 'QM3',
          			},
                               ],
                      )

     In the latter two cases, the queue manager names are optional.  Which
     method to use is largely a choice of style.

QueueManager
     Note that this key is *only* relevant when not using distribution
     lists.  This identifies the queue manager of the target queue, to
     which the message is being written.  This is an optional key.

ObjDesc
     The entire ObjDesc structure passed to the underlying MQPUT1() call
     can be specified via this key.  In this case, the Queue and/or
     QueueManager are simply ignored.  Use of this key would be considered
     somewhat non-conventional, as the OO API is attempting to hide the
     complexity of these underlying data structures.

     However, this allows the developer access to the entire ObjDesc, if
     necessary.

PutMsgOpts
     This argument forces the developer to specify the complete PutMsgOpts
     structure, and will override the use of convenience flags, such as
     Sync.  Similar to the use of ObjDesc, this is non-conventional, but
     provided to allow access to the complete API, if necessary.

PutMsgRecs
     This argument is relevant only when using distribution lists.

     The value is an ARRAY reference, specifying the put message records
     for the individual queues in the distribution list.  Normally, these
     are specified as part of the PutMsgOpts, but this API attempts to hide
     the complexity of the PutMsgOpts structure from the user.

     When using distribution lists, PutMsgRecs are often necessary to
     control how the MsgId, CorrelId, and three other specific fields in
     the MsgDesc are handled.

     For details, see the MQPUT() and MQPUT1() documentation in
     MQSeries(3).

Sync
     This is a flag to indicate that the Syncpoint option is to be used,
     and the message(s) not committed to the queue until an MQBACK or
     MQCOMM call is made.  These are both wrapped with the Backout() and
     Commit() methods respectively.

     The value is simply interpreted as true or false.

PutConvert
     See the new() constuctor documentation for the verbose details.  This
     can be specified for just the Put1() method in the event that a
     converted message format needs to be put to a queue on a
     MQSeries::QueueManager object for which default conversion routines
     have not been installed.

     If you have a QueueManager for which all of the Queue use the same
     message formats, then you can simply specify the PutConvert and
     GetConvert CODE references once, when the MQSeries::QueueManager
     object is instantiated.  Alternately, you may be specifying the
     conversion routined for only a few specific queues.  In the latter
     case, it is entirely possible that you will need to specify PutConvert
     when performing an MQPUT1 MQI call via the Put1() method.

CompCode
--------

   This method returns the MQI Completion Code for the most recent MQI
call attempted.

Reason
------

   This method returns the MQI Reason Code for the most recent MQI call
attempted.

PutConvertReason
----------------

   This method returns a true of false value, indicating if a PutConvert
method failed or not.  Similar to the MQRC reason codes, false indicates
success, and true indicates some form of error.  If there was no
PutConvert method called, this will always return false.

Reasons
-------

   This method call returns an array reference, and each member of the
array is a Response Record returned as a possible side effect of calling a
Put1() method to put a message to a distribution list.

   The individual records are hash references, with two keys: CompCode and
Reason.  Each provides the specific CompCode and Reason associated with
the put of the message to each individual queue in the distribution list,
respectively.

Open
----

   This method takes two optional (but typically not necessary) arguments,
and calls MQOPEN() on the Queue Manager, in order to enable the Inquire
method.  The arguments are a has, with the following keys:

     Key            		Value
     ===            		=====
     Options			MQOPEN 'Options' Values
     ObjDesc			HASH reference (MQOD structure)

   The Options default to MQOO_INQUIRE|MQOO_FAIL_IS_QUIESCING, which is
usually correct.  Note that you can not call MQSET() on a queue manager,
so MQOO_SET is meaningless, as are most of the other options.  Advanced
users can set this as they see fit.

   The ObjDesc argument is also not terribly interesting, as you most of
the values have reasonable defaults for a queue manager.  Again, the API
supports advanced users, so you can set this as you see fit.  The keys of
the ObjDesc hash are the fields in the MQOD structure.

   This method returns a true of false values depending on its success or
failure.  Investigate the CompCode() and Reason() for MQSeries-specific
error codes.

Close
-----

   This method takes no arguments, and merely calls MQCLOSE() to close the
actual queue manager object.  This is meaningful only if the queue manager
has been Open()ed for use by Inquire().

   It is important to note that normally, this method need not be called,
since it is implicitly called via the object destructor, if necessary.  If
the Close() call errors need to be handled, then it can be done
explicitly.  See the ERROR HANDLING section.

Inquire
-------

   This method is an interface to the MQINQ() API call, however, it takes
more convenient, human-readable strings in place of the C macros for the
selectors, as well as supports more readable strings for some of the data
values as well.

   For example, to query the Platform and DeadLetterQName of a queue
manager:

     my %qmgrattr = $qmgr->Inquire( qw(Platform DeadLetterQName) );

   The argument to this method is a list of "selectors", or QueueManager
attributes, to be queried.  The following table shows the complete set of
possible keys, and their underlying C macro.

   Note that this list is all-inclusive, and that many of these are not
supported on some of the MQSeries platforms.  Consult the IBM
documentation for such details.

     Key				Macro
     ===				=====
     AlterationDate              MQCA_ALTERATION_DATE
     AlterationTime              MQCA_ALTERATION_TIME
     AuthorityEvent              MQIA_AUTHORITY_EVENT
     ChannelAutoDef              MQIA_CHANNEL_AUTO_DEF
     ChannelAutoDefEvent         MQIA_CHANNEL_AUTO_DEF_EVENT
     ChannelAutoDefExit          MQCA_CHANNEL_AUTO_DEF_EXIT
     ClusterWorkLoadData         MQCA_CLUSTER_WORKLOAD_DATA
     ClusterWorkLoadExit         MQCA_CLUSTER_WORKLOAD_EXIT
     ClusterWorkLoadLength       MQIA_CLUSTER_WORKLOAD_LENGTH
     CodedCharSetId              MQIA_CODED_CHAR_SET_ID
     CommandInputQName           MQCA_COMMAND_INPUT_Q_NAME
     CommandLevel                MQIA_COMMAND_LEVEL
     DeadLetterQName             MQCA_DEAD_LETTER_Q_NAME
     DefXmitQName                MQCA_DEF_XMIT_Q_NAME
     DistLists                   MQIA_DIST_LISTS
     InhibitEvent                MQIA_INHIBIT_EVENT
     LocalEvent                  MQIA_LOCAL_EVENT
     MaxHandles                  MQIA_MAX_HANDLES
     MaxMsgLength                MQIA_MAX_MSG_LENGTH
     MaxPriority                 MQIA_MAX_PRIORITY
     MaxUncommittedMsgs          MQIA_MAX_UNCOMMITTED_MSGS
     PerformanceEvent            MQIA_PERFORMANCE_EVENT
     Platform                    MQIA_PLATFORM
     QMgrDesc                    MQCA_Q_MGR_DESC
     QMgrIdentifier              MQCA_Q_MGR_IDENTIFIER
     QMgrName                    MQCA_Q_MGR_NAME
     RemoteEvent                 MQIA_REMOTE_EVENT
     RepositoryName              MQCA_REPOSITORY_NAME
     RepositoryNamelist          MQCA_REPOSITORY_NAMELIST
     StartStopEvent              MQIA_START_STOP_EVENT
     SyncPoint                   MQIA_SYNCPOINT
     TriggerInterval             MQIA_TRIGGER_INTERVAL

   The return value of this method is a hash, whose keys are those given
as arguments, and whose values are the queried queue manager attributes.
In almost all cases, the values are left unmolested, but in the following
case, the values are mapped to more readable strings.

Platform			(integer)
          Key				Macro
          ===				=====
          MVS                         MQPL_MVS
          NSK                         MQPL_NSK
          OS2                         MQPL_OS2
          OS400                       MQPL_OS400
          UNIX                        MQPL_UNIX
          Win16                     	MQPL_WINDOWS
          Win32                  	MQPL_WINDOWS_NT

ObjDesc
-------

   This method can be used to query the ObjDesc data structure.  If no
argument is given, then the ObjDesc hash reference is returned.  If a
single argument is given, then this is interpreted as a specific key, and
the value of that key in the ObjDesc hash is returned.

   NOTE: This method is meaningless unless the queue manager has been
MQOPEN()ed via the Open() method.

Special Considerations
======================

AutoCommit
----------

   Normally, when you have pending transactions (i.e. MQPUT() and/or
MQGET() calls with syncpoint), they will be automatically committed when
MQDISC() is called.  The MQSeries::QueueManager object destructor, in an
attempt to make things easy for the programmer, automatically calls
MQDISC() for you.  The result is that transactions will be automatically
committed when the application exits in any way that allows the object
destruction to occur.

   This behavior is somewhat counter intuitive, as you would expect
transactions to be backed out unless you explicitly say otherwise (i.e.
call MQCMIT(), or in this context, the Commit() method call).

   As of the 1.12 release of the MQSeries Perl API, this behavior is under
the control of the developer.  The AutoCommit argument to the object
constructor is a Boolean value that specifies whether AutoCommit is on or
off.  If enabled, then a pending transaction will be committed before
disconnecting.  If disabled, then the transaction will be backed out, and
only if the backout succeeds will we cleanly disconnect.

   NOTE: The default behavior is backwards compatible in the 1.12 release,
meaning that AutoCommit is enabled by default.  However, if you do not
specify the AutoCommit behavior explicitly, then the automatic commit of a
pending tranaction will generate a warning when the object is destroyed.
This is because we (the MQSeries Perl API authors) feel that depending on
this functionality is dangerous.

   ANOTHER NOTE: The default behavior will change with the 1.13 release,
as AutoCommit will default to 0, not 1, making the intuitive behavior the
default.

Connection Timeout Support
--------------------------

   There are known outage scenarios wherein the queue manager will be in a
"hung" state, where it is entirely unresponsive, but still up and running.
Attempts to connect to such a queue manager can block indefinetely, with
the MQCONN() call never returning, until the queue manager is shutdown and
restarted.  Normally, applications can not trap this error, since they
will be stuck in the MQCONN() call, forever.

   By setting the ConnectTimeout argument to the MQSeries::QueueManager
constructor, a time limit on MQCONN() can be imposed, and applications
will be able to detect this situation, and take action, if so desired.

   This functionality is implemented by forking a child process, which
sleeps for the duration of the ConnectTimeout, and then sends a signal to
the parent to interrupt the MQCONN() call.  If the MQCONN() call succeeds
before the timeout is reached, then the parent kill the child with the
same signal.

   By default, SIGUSR1 is used, and the handlers are installed locally, so
there should be no conflict with any signal handlers installed by the
application, unless you really need your own SIGUSR1 to be enabled during
the MQCONN() call.  You can customize the signal used via the
ConnectTimeoutSignal argument.

   If the timeout occurs, it will be considered a retryable error. (See
the next section).

   NOTE: This functionality is only supported on platforms that support
fork(), and signals, of course.  Win32 is not supported, since it does not
support sending signals to other processes.

Connection Retry Support
------------------------

   Normally, when MQCONN() fails, the method that called it (Connect() or
new()) also fails.  It is possible to have the Connect() method retry the
MQCONN() call for a specific set of reason codes.

   By default, the retry logic is disabled, but it can be enabled by
setting the RetryCount to a non-zero value.  The list of reason codes
defaults to a few reasonable values, but a list of retryable codes can be
specified via the RetryReasons argument.

   You are probably wondering why this logic is useful for MQCONN().  The
choice of the default RetryReasons is not without its own reason.

   Consider an application that loses its connection to its queue manager,
and thus crashes and restarts.  It may very well attempt to reconnect
before the queue manager has recovered, and this support allows the
application to retry the connection for a while, until it succeeds.

   Alternately, consider an application that is started at boot time,
possible in parallel with the queue manager.  If the application comes up
before the queue manager, the MQCONN() call will fail.  Retrying this
initial connection will make the application startup more robust.

   This makes it easier to have applications recover from queue manager
failures, or that have more robust startup logic, but note that this retry
logic only applies to the initial connection.  Reconnecting at arbitrary
points in the code is far more complex, and it left as a (painful)
exercise to the reader.

Error Handling
--------------

   Most methods return a true or false value indicating success of
failure, and internally, they will call the Carp subroutine (either
Carp::Carp, or something user-defined) with a text message indicating the
cause of the failure.

   In addition, the most recent MQI Completion and Reason codes will be
available via the CompCode() and Reason() methods:

     $qmgr->CompCode()
     $qmgr->Reason()

   When distribution lists are used, then it is possible for a list of
reason codes to be returned by the API.  Normally, these are buried inside
the ObjDesc strucure, but they are also available via the

     $qmgr->Reasons()

   method.  In this case, the $queue->Reason() will always return
MQRC_MULTIPLE_REASONS.  The return value of the Reasons() method is an
array reference, and each array item is a hash reference with two keys:
CompCode and Reason.  These correspond, respectively, with the CompCode
and Reason associated with the individual queues in the distribution list.

   For example, the Reason code associated with the 3rd queue in the list
would be:

     $qmgr->Reasons()->[2]->{Reason}

   In the case of the constructor new(), which returns nothing when it
fails, these methods are not available.  Most applications will not need
to handle the specific CompCode and Reason when the instantiation fails,
but if necessary, these can be obtained in one of two ways.

   The older method, which is supported for backwards compabitility but
strongly discouarged, is to pass references to scalar variables to new().
See the new() documentation above for more details.

   The newer method would be to explicitly call the Open() method, and
error check it yourself.  This will mean that the constructor will now
fail only if there is an error processing the constructor arguments, as
opposed to an error in the MQSeries infrastructure.

   Some examples should make this clear.

   The simplest way to create an MQSeries::QueueManager object is:

     my $qmgr = MQSeries::QueueManager->new
       (
        QueueManager		=> 'some.queue.manager',
       ) || die;

   But in this case, the connection to the queue manager could fail, and
your application will not be able to determine why.

   In order to explicitly have access to the CompCode and Reason one would
do the following:

     my $qmgr = MQSeries::QueueManager->new
       (
        QueueManager		=> 'some.queue.manager',
        NoAutoConnect		=> 1,
       ) || die "Unable to instantiate MQSeries::QueueManager object\n";

     # Call the Connect method explicitly
     unless ( $qmgr->Connect() ) {
       die("Connection to queue manager failed\n" .
           "CompCode => " . $qmgr->CompCode() . "\n" .
           "Reason   => " . $qmgr->Reason() . "\n");
     }

Conversion Precedence
---------------------

   Once you have read all the MQSeries::* documentation, you might be
confused as to how the various PutConvert/GetConvert method arguments and
constructor arguments interact with the MQSeries::Message PutConvert() and
GetConvert() methods.

   The following is the precedence of the various places you can specify a
PutConvert or GetConvert subroutine, from highest to lowest:

     [A] Put(), Get(), and Put1() method arguments
     [B] MQSeries::Message PutConvert() and GetConvert() methods
     [C] MQSeries::Queue object defaults (set as arguments to new())
     [C] MQSeries::QueueManager object defaults (set as arguments to new())

   The cleanest way to code these is probably (and here your mileage will
vary wildly with your tastes) to implement a subclass of MQSeries::Message
which provides the appropriate GetConvert() and PutConvert() methods, one
seperate class for each type of data conversion which is necessary.

   Then the conversion happens "under the covers" when message objects of
that class are put to or gotten from a queue.

SEE ALSO
========

   MQSeries(3), MQSeries::Queue(3), MQSeries::Message(3)

Internal utility functions
**************************

NAME
====

   MQSeries::Utils - Internal utility functions

SYNOPSIS
========

     use MQSeries::Utils qw(ConvertUnit);

     my $wait_value = ConvertUnit('Wait', '45s');
     my $exp_value = ConvertUnit('Expiry', '1.5m');

DESCRIPTION
===========

   The MQSeries::Utils module contains internal helper functions that are
generally not of interest to users of the MQSeries module.

FUNCTIONS
=========

ConvertUnit
-----------

   This function can convert values for the 'Wait' and 'Expiry' options
from symbolic values into the numeric values required. Symbolic values are
numeric values ending in an 's' for seconds or an 'm' for minutes.

   As 'Wait' values are in 1/1000 of a second and 'Expiry' is in 1/10 of a
second, using symbolic values can help avoid mistakes such as getting the
magnitude of these numbers wrong by one or more orders of magnitude.

SEE ALSO
========

   MQSeries(3)

My base class object
********************

NAME
====

   MRP::BaseClass - My base class object

DESCRIPTION
===========

   Base class for my perl objects that generates the class interface from
a definition.

SYNOPSIS
========

   The aim of this package is to allow you to define a classes interface,
and have perl generate all of the standard functions for you. Currently,
you can define:

fields
     Member access functions are auto-generated so that nowhere in your
     code do you ever directly access member variables.

package variables
     Class functions are auto-generated to make package variables work like
     static class members.

default variables
     The package variable an be made to act as the default value for a
     field of the same name.

delegation support
     Simply specify which field is a delegate and which funcitons to
     delegate to it, and the glue code is auto-generated.

   The other realy usefull thing it does is provide dramaticaly better
error messages when methods or static functions canot be found. Try
invoking the <C -w> flag. It even lists possible correct spellings of
misspelled function names!

   As a matter of course, I include the class definition in a BEGIN block
at the end of the package. This allows the interface to be checked, and
the code to be generated at compile time. This has the additional benefit
that these checks are performed during a <C -c> compilation.

SEE ALSO
========

   This module relies upon these modules:

MRP::Interface
MRP::Text
MRP::Introspection
A skeletal derived class
========================

     package myDerived;

     use strict;                   # I'm paranoid about this...
     use vars qw ( @ISA %fields );

     use MRP::BaseClass;

     BEGIN {                       # Putting this code in BEGIN makes
                                   # errors show up at compile time.
        # our parent class - in this case only MRP::BaseClass.
        @ISA = ('MRP::BaseClass');
        # the object model - member names and initial values
        %fields = (
     	       'number' => 1,
     	       'hash' => undef,
                   'array' => undef,
     	       );
        # check4Clashes ensures that you are not overriding base class
        # member variables and creates the member access functions.
        myDerived->check4Clashes();
     }

     # Our constructor - this one is very simple.
     sub new {
        my $class = shift;              # we need to know what type we are.
        my $self = new MRP::BaseClass;  # get an object from the emediate parent

        $self->rebless ($class);        # re-bless the object into this package
                                        # this is when MRP::BaseClass sets up
                                        # member variables
        return $self;                   # return the object.
     }

     # This function is called during re-blessing. Here we are just going
     # to set the member 'hash' to a new hash reference.
     # At this point $self is blessed into this package, and contains
     # all of its members. You could call member funcitons from here if
     # you realy wanted to.
     sub initialize {
        my $self = shift;
        $self->hash({});
        $self->array([]);
     }

   You can now use this class as follows:

     $thing = new myDerived();          # get a new myDerived object
     $thing->hash->{'red'} = 1;         # set the key red in hash to 1
     $thing->number(5);                 # set the value of number to 5
     $thing->array->[0] = "goo";        # set the first element of array to 'goo'
     $thing->array->('a','b');          # this is not what you meant. The
                                        # array ref will be replaced with 'a' and
                                        # the rest of the parameters will be lost.
     @{$thing->array} = ('a','b');      # this is better.
     $thing->array([('a','b')]);        # replace the refrerence with a new one
                                        # containing the array ('a','b')

     print "I have the number ", $thing->number, " in me\n";

   A class derived from myDerived would just substitute the name myDerived
for MRP::BaseClass.  Hey presto - all sorted!

   The return value of the member access functons is the value of the
member. If a value is given to the member access function then the member
is set to that value, and it's new value is returned. Thus:

     $val = $thing->hash;     # puts the same reference in $val that was in hash
     $thing->hash(\%myHash);  # sets the hash reference used to\%myHash

Using clever fields
===================

   MRP::BaseClass is clever enough to create hash and array members and
specialised access functions, as well as methods that check the interface
of methods. Include a fields like this...

     %fields = (
     	       myHashMember => {},
     	       myArrayMember => [],
                myDelegate => MRP::Interface->ActionDelegate,
     	       );

   and MRP::BaseClass will do the following:

   * During rebless, a new hash or array ref will be put into these
     members.  You do not need to add these parts in initialize()

   * During member access generation, member access functions will be
     generated that understand that these members are hashes or arrays.

   * A member access function named *field_ref* gives you access to the
     actual member variable.

   * When you set $obj->myDelegate, it checks that the new object
     implements the interface ActionDelegate.

   So, reworking the original example,

     %fields = (
     	       'number' => 1,
     	       'hash' => {},   # put an empty hash here
                'array' => [],  # and an empty array here
     	       );

   The initialize subroutine can be discarded - you don't need to set
anything up now. The rest of the code is unchanged. You can access the
members as follows:

     $thing = new myDerived;          # get an object as before
     $thing->number(50);              # access to scalars doesn't change
     $thing->hash('foo'=>1,'bar'=>2); # sets hash to the value passed.
     $ref = $thing->hash;             # returns the reference used
     $val = $thing->hash->{'foo'};    # return 1
     %hash = $thing->hash;            # sets the contence of %hash equal to hash
     $thing->array(@list);            # sets the value of array to @list
     @list = $thing->array();         # sets the value of @list to array
     $array = $thing->array;          # sets $array to the same reference as array
     $val = $thing->array->[3];       # sets $val equal to the 3rd element of array
     $thing->array(\@array);          # sets array to a one member list containing
                                      # \@array. array and @array still point to
                                      # different objects
     $thing->array_ref(\@anarray);    # set array to the reference of @anarray. They
                                      # now refer to the same object.
     $thing->hash_ref(\%ahash);       # likewise, hash now refers to ahash.

Package variables
=================

   MRP::BaseClass will also generate access functions for package
variables. You must list the ones that you want to expose in the
@public_vars array. When check4Clashes is invoked, it will generate access
functions for each of the values in this array. For example,

     package myDerived;
     use strict;
     use vars qw(@ISA @public_vars $scalar %hash @array);
     use MRP::BaseClass;

     @ISA = qw(MRP::BaseClass);
     @public_vars = qw($scalar %hash @array);
     myDerived->check4Clashes();

     ...

     $s = myDerived->scalar;      # set $s to $myDerived::scalar
     myDerived->hash(%newValue);  # set %myDerived::hash to %newValue
     @list = myDerived->array;    # set @list to @myDerived::array

   The benefit of this is that in any package derived from myDerived, you
can still access these variables. This makes package variable access
follow all the same rules as member variables do for inheritance. One
freebie is that you can access these package variables via an object. So,
if $error is a global scalar then $obj->error would access the global
value of error for you. In this way, global variables are made to work
like static class members.

Package variables and fields with the same name
===============================================

   There will be cases when the same variable is used for a package
variable and field name. If you include the variable both in fields and in
public_vars, then the access function will decide which value to return
based upon whether it was invoked as a class or objet method.

     package myDerived;
     use strict;
     use vars qw(@ISA @public_vars %fields $error $linewidth);
     use MRP::BaseClass;

     @ISA = qw(MRP::BaseClass);
     %fields = { $error=>undef, };
     @public_vars = qw($error);
     myDerived->check4Clashes();

     ...

     $t = new myDerived;   # get a new object
     $t->error;            # returns the error field of object $t
     myDerived->error;     # returns the error associated with the package

Default variables
=================

   These are specified in the @defaults array. They do not need to be
listed in either fields or public_vars. A field and a package variable
will be generate, with the field providing the object-specific value and
the package variable provides the default value. This is returned when you
query an object for it, and the object value is undef. So - to illustrate
with the linewidth field:

     package myDerived;
     use strict;
     use vars qw(@ISA @defaults $linewidth);
     use MRP::BaseClass;

     @ISA = qw(MRP::BaseClass);
     @defaults = qw($linewidth);
     myDerived->check4Clashes();

     ...

     $t = new myDerived;        # make a new myDerived object
     $t->linewidth(72);         # set linewidth to 72 for this object
     myDerived->linewidth(70);  # set the defuault value to 70
     print $t->linewidth, "\n"; # will print '72'
     $t->linewidth(undef);      # make sure that linewidth is undef
     print $t->linewidth, "\n"; # will now print '70' - the default value

Delegation support
==================

   Very often, an object will contain a reference to another object that
it uses to implement part of its public interface. Usualy this is achieved
by just forwarding the function calls directly. MRP::BaseClass will
generate these functions automaticaly from the %delegates hash.

     package myComposite;
     use strict;
     use MRP::BaseClass;

     use vars qw(%fields %delegates @ISA);

     BEGIN {
       @ISA = qw(MRP::BaseClass);
       %delegates = (
                     stringMaker => [qw(toString toText)],
                    );
       myComopsite->check4Clashes();
     }

   ... insert new function and the rest of the functionality here...

   The delegates hash contains field names as keys followed by an arrray
reference containing function names. Thus, code will be generated to wire
myComoposite->toString to myComposite>stringMaker->toString. The arguments
are forwarded, so that myComposite objects share a subset of the interface
of the stringMaker delegate.

   I have invented a hypothetical class called StringMaker that can write
out text in different languages. I wish that I had one during school!  It
can expand messages into a string with `toText' and to formatted text with
toString. It can also have its target set with language. I do not wish
myComposite to have a language method, but I do wish it to be able to
write out text.

     $mc1 = new myComposite(); # get a composite object
     $mc2 = new myComposite(); # and another
     $mc1->stringMaker($sm1); # set stringMaker to $sm1
     $sm1->language('English UK'); # and set the stringMaker language to british.
     $mc2->stringMaker($sm2); # set this stringmaker as well
     $sm2->language(french); # and set the language to french

     print $mc1->toText('Apologise'); # an eloquant british apology
     print $mc2->toText('Apologise'); # a beautifull french apology

   If you try to use a field as a delegate that appears in the fields
hash, then a fatal error message will be printed.

Delegation support with type checking
=====================================

   It is not possible to check that the methods are legal for the
delegate, as the type of the delegate is not known at compile time.
However, by giving an interface object rather than a function name, the
object can be validated when the delegate is set.

     %delegates = (stringMaker => [MRP::Interface->StringMaker];);

   Now, any object put into the stringMaker field of this class must
implement the interfave StringMaker, or an exception will be thrown.

Enhanced <C -w> diagnostics
===========================

   If you run your script with <C -w> invoked, then MRP::BaseClass gives
you some extra diagnostics that I have found to be very usefull. The first
line is of the form:

   Can't access 'funcName' in [object/package] [objectName/packageName]:

   This clearly describes which function could not be located, whether it
was invoked as an object or package function, and the object or package.

   There may follow a section where the program lists potential
corrections. Thus, a common mistake I make is to type check4clashes -
incorrect case. In response to this, it would sudgest that I use the
function MRP::BaseClass::check4Clashes. It lists both similar filed and
function names.

   The next line says where the error occured, in the form `in
temp/testMutipleInheritance.pl at line 40'.

   It then dumps the model for the object. This consists of its fields and
their values, all methods that can be directly accessed via inheritance,
and all package variables. The function list does not include functions in
baseclasses that are overridden in derived classes, and it doesn't include
functions starting with a leading underscore.

   Following this, a complete stack trace is displayed.

Functions
=========

new
     Returns a new MRP::BaseClass object. This can then be reblessed into
     your package.

rebless
     Converts a base class into your class!  Call as $self->rebless($class)
     where $self is a base class object.  It returns $self, blessed, with
     the correct member variables. It is at this time that initialize, if
     present, is invoked. This functon should be used in every constructor
     that has to bless an object from a base class that is derived from
     MRP::BaseClass into the current package. If you employ multiple
     inheritance of field members, then use $class->rebless($parent1,
     $parent2...). This is clever enough to combine the data members from
     multiple parents. Therefore, it implements multiple inheritance by
     combining all fields within a single namespace, rather than the c++
     approach of each class having its own namespace within the object.
     This should work fine for most things.

initialize
     Override this in each derived class to provide class specific
     initialization. For example, initialize may put arrays into member
     variables that need them. MRP::BaseClass will not complain if you do
     not provied an initialize function. It will assume that it is not
     needed.

clone
     Returns a new object that is a clone of this one. Currently it copies
     scalars and references and then blesses the new object into the same
     class as the cloned object.  This is a shallow copy by default. Invoke
     it will a true argument and it will do a deep copy, calling clone for
     all objects it can. If you invoke clone with `shallow' then you force
     a shallow copy. Override this in a base class if this is not the
     behavure you want. For example, my MRP::Document objects return
     themselves when you call clone, so that only one object exists for
     each directory being documented.

_PrintMembers
     This function is provided for debugging.  It returns a string
     representaion of your object model, including members, methods and
     package variables.

check4Clashes
     Call this function after you have defined your classes interface. It
     does the following:

        * Checks the `%fields' of all classes in @ISA to ensure that you
          are not redefining members

        * Checks the interface of all classes in @ISA to ensure that you
          have no ambiguously inherited function calls that are not
          disambiguated in the current class.

        * Generates code to support member variables and static variables
          via access functions.

        * Generates code to support simple delegation models where function
          arguments are forwarded unchanged.

     The template for the automaticaly generated code can be over-ridden in
     any subclass to give more precise functionality. For example, in
     MRP::Matrix, the delegation funciton is replaced with one that
     systematicaly modifies the argumet list. This is a painless operation
     under this system.

package::memberAccess
=====================

   When the class is created, MRP::BaseClass creates a package called
class::memberAccess. This package contains the member access functions.
MRP::BaseClass then makes class::memberAccess the first parent in
@class::ISA. Thus, you can do things like this:

     package myPath;
     ...
     %fields = (path => []);
     myPath->check4Clashes();
     ...
     sub path {
     	my $self = shift;
     	my @path = $self->SUPER::path;
     	return join "/", @path;
     }

   Because the member access functions are in a seperate package, you can
still create functions of the same name in your package without 'loosing'
the member access. Cool!

Other usefull functions
=======================

   These functons are very usefull, but are more aprpreate to packages
than members. They all work regardless of whether invoked as a class or
object method.

Class variables

    _ISA
          In a scalar context, this function returns a reference to the ISA
          array for the package. In an array context it returns the
          contence of ISA for the package.

    _fields
          In a scalar context, this function returns a reference to the
          fields hash for the package. In an array context it returns the
          contence of fields for the package as a list of key/value pairs.

Text Formatting

    _pretyArray
          This function takes either an array or a reference to an array.
          It returns a string representation of the array.

    _pretyHash
          This function takes a leader string followed by either a hash or
          a reference to a hash. The leader sequene is prepended to each
          line of text. The function returns a single string representing
          the hash contence.

Inheriting from an MRP::BaseClass-derived object
================================================

   This is as simple as extending MRP::BaseClass. Optionaly define
%fields, @public_vars and @defaults, write an initialize function, and
then call check4Clashes. Then in the new function, get an object for the
imediate base class and call rebless for it.

     package myBox;

     use strict;
     use vars qw(@INC, %fields, @defaults);
     use myGraphable;

     BEGIN {
       @ISA = qw(myGraphable);
       %fields = (
         'x'=>undef, 'y'=>undef, 'w'=>undef, 'h'=>undef
       );
       @defaults = qw($color);
       myBox->check4clashes();
     }

     sub new {
       my $class = shift;
       my $self = new myGraphable;
       $self->rebless($class);
       return $self;
     }

     ... everything else goes here ...

Multiple inheritance
====================

   Much of the strife of multiple inheritance is taken care of for you.
Simply use the multi-argument form of rebless to create the new object.

     package multiple;
     use myGlyph;
     use myPersistant;

     @ISA = qw(myGlyph myPersistant);

     sub new {
       my $class = shift;
       my $glyph = new myGlyph;
       my $persistant = new myPersistant;
       my $self = multiple->rebless($glyph,$persistant);
       return $self;
     }

   ... everything else here ...

   Of course, you could include %fields, @public_vars and @defaults to
give this package extra behaviour, and you may wish to define initialize.

Multiple inheritance involving non-MRP::BaseClass parents
=========================================================

   check4Clashes stops searching a root of an inheritance hierachy when it
can find no baseclasses that support _containsFields. This section
describes how to implement _containsFields so that you can add your
classes into this framework if you wish to. The premice is that you will
only allow people to access member variables outside of the package
through access functions, and that your stoorage method doesn't clash with
mine.

   _containsFields is responsible for comparing a classes fields with the
set in the calling package. The MRP::BaseClass implimentation will work
for cases where all of the classes that contribute fields are derived from
MRP::BaseClass, and relies on my use of the %fields hash.

   _containsFields assumes that the first argument is the package that it
is being called in.  The following arguments are taken to be a list of
fields which to check are not found in members of the current package.

   It should return either undef or a reference to an array of name
clashes in the format `package::variable'. These clashes should be the
combination of classes with this package and with all of the base classes.

   So it would look something like   _containsFields {     my $class =
shift;     my @toCheck = @_;

     foreach @toCheck {
     	check that they are not in me.
     	  If they are, add them to the list of clashes to return.
     }

     add all base class clashes to your list of clashes

     if there were name clashes return a reference to them

     otherwise return undef
       }

   It is as simple as that. Currently, member variables are contained as
keys within the $self hash reference. I provide access functions for all
of the keys mentioned by name in %package::fields when check4Clashes is
called. If anybody adds keys afterwards, member access functions are not
generated for them. I can not be bothered to create a
public:protected:private system. In the pod I just don't document private
stuff.

Modifying the code generated for variable access and delegation support
=======================================================================

   Here are the parameters that are passed into the code-generating
functions.

thingy
     The class (possibly an object?) that the function is being generated
     for. You can use this to access other functions.

memberPackage
     The package that the function must be compiled into. Normaly you would
     include `package $memberPacage' as the first line of the text.

delegate
     The name of the field that is acting as a delegate

interface
     An MRP::Interface object - the generated code must ensure that objects
     implement the correct interface before setting the field.

functions
     The name of the function that the delegate is providing

    name
          The name that you must give the function

    item
          The name of the field that this function must provide access to.

     Here are the funcitons themselves.

    _delegateFunc($thingy, $memberPackage, $delegate, $function)
    _delegateAccess($thingy, $memberPackage, $item, $interface, $interface.....)
    _fieldScalarFunc($thingy, $memberPackage, $name, $interface, $item)
    _packageScalarFunc($thingy, $memberPackage, $name, $item)
    _fieldArrayFunc($thingy, $memberPackage, $name, $item)
    _packageArrayFunc($thingy, $memberPackage, $name, $item)
    _fieldHashFunc($thingy, $memberPackage, $name, $item)
    _packageHashFunc($thingy, $memberPackage, $name, $item)
    _packageAndField($thingy,$memberPackage,$item,$fieldFunc,$packageFunc)
          Handles the case when you have a static variable and a field of
          the same name

    _defaultField($thingy,$memberPackage,$item,$fieldFunc,$packageFunc)
          Handles the case when you have a static variable that provides
          the default value for a field

AUTHOR
======

   Matthew Pocock mrp@sanger.ac.uk

defines object interfaces
*************************

NAME
====

   MRP::Interface - defines object interfaces

DESCRIPTION
===========

   Allows you to specify the interface that an object is expected to
implement without implying an inheritance hierachy.

SYNOPSIS
========

     MRP::Interface->create(Foo => {''=>'My realy usefull interface',  # interface description
     				 action=>'performs an action',      # functions and their descriptions
     				 reaction=>'responds to an action', # ...
     				});

     MRP::Interface->Foo->implementedBy('Bar'); # register package Bar as implementing interface Foo
                                                # Package Bar must have functions 'action' and 'reaction'
                                                # or a fatal error is generated.
     $bar = new Bar;
     $hoot = new Hoot;

     MRP::Interface->Foo->implementedBy($bar);  # returns true as $bar does implement Foo
     MRP::Interface->Foo->implementedBy($hoot); # returns false as $hoot doen't implement Foo
     MRP::Interface->Gee->implementedBy($bar);  # fatal error if interface Gee is not defined

     $int = MRP::Interface->Foo;                # gets the interface object for 'Foo'
     print $int->name();                        # prints out 'Foo'
     %functions = %{$int->functions()};         # %functions now contains Foo's functions and descriptions

FUNCTIONS
=========

create
     Creates a new interface. You can create any number of interfaces with
     a single call. Treats the parameters as a hash, where each key is an
     interface name, and each value is a hashref. The hasref key/value
     pairs specify function names and descriptions for those functions. If
     the function name is " then this is used as the interface description.

          MRP::Interface->create( interfaceName => { '' => $description_for_interfaceName,
                                                     func1 => $description_for_func1,
                                                     func2 => $description_for_func2,
                                                     ...
                                                     funcn => $description_for_funcn },
                                  otherInterface => { ..... }
          );

functions
     Returns the hash of function names and descriptions used to create the
     interface.

name
     Returns the name of the interface.

implementedBy
     If the argument is a reference (presumably an object) then return true
     or false depending on whether the object is of a class that implements
     the interface.

     If the argument is a package name (not a reference) then the package
     is registered as implementing the interface. If the package does not
     provide all of the required functions then an error is thrown.

anything else
     Any other method is treated as if it where the name of an interface to
     retrieve. Thus, MRP::Interface->Holly will retrieve the interface
     named Holly. If Holly does not exist then a fatal error is thrown. So,
     you can have code like:

          MRP::Interface->Holly->implementedBy($obj)
           || die "$obj does not implement interface Holly";

AUTHOR
======

   Matthew Pocock mrp@sanger.ac.uk

powerful introspection
**********************

NAME
====

   MRP::Introspection - powerful introspection

DESCRIPTION
===========

   Provides introspection support without you breaking strict.

SYNOPSIS
========

   These functions perform introspection into a package to avoid you
having to tamper with the symbol table directly. They use MAJOR wizardry
to make sure that things behave just as you would expect. Use with
caution, particularly if you use them to alter variables.

Package symbols
     In a scalar context, these functions return a reference to a hash. In
     a list context, they return a list of key/value pairs. The keys are
     all of the items found in the symbol table of a given type. The values
     are references to these items. Call using something like:

          $arrayHash = MRP::Interface->_arrays($obj);
          print "Got ISA ", $arrayHash->{ISA}, "\n";
          %arrayHash = MRP::Interface->_functions(MyPackage);
          print "Found ISA" if exists $arrayHash{'ISA'}

    _functions
    _scalars
    _arrays
    _hashes
Accessing individual symbol table elements
     These functions all return either a reference to to the item within
     the package or undef if it doesn't exist. For example,

          $func = MRP::Interface->_function($thingy, 'printme');

     will put a reference to the function 'printme' in $func. If there is
     no such function within the package that $thingy is blessed into (or
     the package named by $thingy), then $func will be undef. These
     functions do not deal with inheritance. They only look in a single
     package.

    _function
    _scalar
    _array
    _hash
Other functions

    symTable
          Returns a hash ref to the symbol table of a package (or the
          package that an object is blessed into).

               $symTable = MRP::Introspection->symTable($obj);

    ISA
          Returns the @ISA array for a package or object. Returned as an
          array or a reference to the actual ISA array depending on
          wantarray.

               $isaRef = MRP::Introspection->ISA($package);
               push @$isaRef, $newBaseClass;

    functionsMatching
          Returns all of the functions that match a given regex.

               $sets = MRP::Introspection($package, '^set.*$'); # all the functions in
                                                   # package $package matching ^set.*$

    recursiveFunction
          MRP::Introspection->recursiveFunction($package, $funcRef);

          Recursively applies a function throughout an objects inheritance
          hierachy.  Returns a hash or hashref of all of the function
          return values pre-catonated with the package name. You will have
          to just try this one out.

    recursiveInheritance
          Same as recursiveFunction, but throws away results that could
          not be reached because they are masked by inheritance. Again,
          just try it.

    superAUTOLOAD
          use:

               $autref = MRP::Interface->superAutoload($thisPackage, $AUTOLOAD);
               $autref->(@paramlist);

          For those stickey moments when you have entered an AUTOLOAD
          method, but it needs to allow some superclasses AUTOLOAD to do
          some processing. The method sets $AUTOLOAD in the package that
          is first reached by inheritance that has an AUTOLOAD method, and
          returns a reference to that function. You just have to use the
          reference and pass it the relevant arguments.

AUTHOR
======

   Matthew Pocock mrp@sanger.ac.uk

some text utilities
*******************

NAME
====

   MRP::Text - some text utilities

DESCRIPTION
===========

   Provides a small number of text manipulating methods that I use all the
time. They are invoked as MRP::Text->func.

SYNOPSIS
========

   print "got ", MRP::Text->pretyArray(@someList), "\n";

Functions
=========

pretyArray
     use:

          print MRP::Text->pretyArray(qw(pig dog cat)); # prints out (pig, dog, cat)
          print MRP::Text->pretyArray($arrayRef); # prety-prints the contence of the array ref

pretyHash
     use:

          print MRP::Text->pretyHash($leader, $hashRef);
          print MRP::Text->pretyHash($leader, %hash);

     leader is printed before each key/value pair.

AUTHOR
======

   Matthew Pocock mrp@sanger.ac.uk

Get or set MS-DOS file attributes
*********************************

NAME
====

   MSDOS::Attrib - Get or set MS-DOS file attributes

SYNOPSIS
========

     use MSDOS::Attrib qw(get_attribs set_attribs);
     $attribs = get_attribs($path);
     set_attribs($attribs, $path1, $path2, ...);

DESCRIPTION
===========

   MSDOS::Attrib provides access to MS-DOS file attributes.  While the
read-only attribute can be handled by chmod and stat, the hidden, system,
and archive attributes cannot.

$attribs = get_attribs($path)
     Returns the attributes of $path, or the empty string if $path does
     not exist.  Attributes are returned as a five-character string in
     this format: "RHSAD".  Each letter is replaced by an underscore (_)
     if the file does not have the corresponding attribute.  (This is the
     same format as a 4DOS directory listing.)  The attributes are:

          R  The file is read-only (not writable)
          H  The file is hidden (does not appear in directory listings)
          S  The file is a system file (does not appear in directory listings)
          A  The file needs to be archived (it has changed since last backup)
          D  The file is a directory

$count = set_attribs($attribs, $path1, [$path2, ...])
     Sets the attributes of `$path1', `$path2', etc.  You can either
     specify the complete set of attributes, or add and subtract attributes
     by using + and -.  The case and order of the attributes is not
     important.  For example, '-s+ra' will remove the system attribute and
     add the read-only and archive attributes.  You should not use
     whitespace between attributes, although underscores are OK.  See
     `get_attribs' for an explanation of the attribute values.  You cannot
     change the directory attribute; if you specify it, it is ignored.
     Returns the number of files successfully changed.

LICENSE
=======

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   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 either the GNU General Public
License or the Artistic License for more details.

AUTHOR
======

   Christopher J. Madsen <`chris_madsen@geocities.com'>

SEE ALSO
========

   The `OS2::ExtAttr' in this node module provides access to extended
attributes under OS/2.

   The Win32/FileSecurity, module provides
access to Discretionary Access Control Lists under Windows NT.

Manage 4DOS style DESCRIPT.ION files
************************************

NAME
====

   MSDOS::Descript - Manage 4DOS style DESCRIPT.ION files

SYNOPSIS
========

     use MSDOS::Descript;
     $d = new MSDOS::Descript;
     print $d->description('foo.txt');
     $d->rename('foo.txt', 'bar.txt');
     $d->description('baz.txt','This is Baz.txt');
     $d->description('frotz.txt', ''); # Remove description for frotz.txt
     $d->update;

DESCRIPTION
===========

   *MSDOS::Descript* provides access to 4DOS style DESCRIPT.ION files.

   Remember that changes to the descriptions are not saved unless you call
the update or write methods.

   By default, *MSDOS::Descript* uses relative paths, so if you change the
current directory between new and update, you'll be writing to a different
file.  To avoid this, you can pass an absolute path to new.

Methods
-------

$d = MSDOS::Descript->new([$filename])
     Constructs a new `MSDOS::Descript' object.  $filename may be a
     directory or a 4DOS DESCRIPT.ION format file.  If it's a directory,
     looks for a DESCRIPT.ION file in that directory.  If $filename is
     omitted, it defaults to the current directory.

$d->description($file, [$desc])
     Gets or sets the description of $file.  If `$desc' is omitted,
     returns the description of $file or undef if it doesn't have one.
     Otherwise, sets the description of $file to `$desc' and returns the
     old description.  (If `$desc' is the null string or undef, the
     description is deleted.)

$d->rename($old, $new)
     Transfers the description of `$old' (if any) to `$new'.  This does
     not actually rename the file on disk.

$d->read([$file])
     Load the descriptions from $file.  If $file is omitted, then re-read
     the original description file.  Since new does this automatically,
     you shouldn't have to call read yourself.

$d->read_add($file)
     Add the descriptions from $file to the current descriptions.

$d->write([$file])
     Writes the descriptions to $file, or the original description file if
     $file is omitted.  Marks the descriptions as unchanged if writing to
     the original description file.  If the current directory has changed
     since the descriptions were loaded, and the description file was
     specified by a relative path (which is the default), you will be
     writing to a different file.

$d->update
     Saves the descriptions to the original file if any changes have been
     made.  The same warning about the current directory applies (see
     write).

$d->autoupdate([$auto])
     Turns on automatic updates for $d if `$auto' is true or omitted.
     Otherwise, turns automatic updates off.

     When automatic updates are on, the descriptions are automatically
     saved when the object is destroyed.  *Beware of relative paths!*  If
     the current directory changes before the object is destroyed, you're
     going to be writing to a different file!  I strongly suggest that you
     use absolute paths if you're going to use `autoupdate'.

REQUIREMENTS
============

   *MSDOS::Descript* requires the *Tie::CPHash* module (a case-insensitive
hash).

   It also uses *MSDOS::Attrib* to hide DESCRIPT.ION files after it
changes them.  If you don't have *MSDOS::Attrib*, it will still work, but
any DESCRIPT.ION files changed by *MSDOS::Descript* will become visible.

   Both *Tie::CPHash* and *MSDOS::Attrib* are available from CPAN.

BUGS
====

   Uses relative paths, so changing the current directory after loading a
description file can cause problems.

AUTHOR
======

   Christopher J. Madsen <`chris_madsen@geocities.com'>

Perl extension for submitting JCL to MVS systems through FTP.
*************************************************************

NAME
====

   MVS::JESFTP - Perl extension for submitting JCL to MVS systems through
FTP.

SYNOPSIS
========

   use MVS::JESFTP;

   $jes = MVS::JESFTP->open($host, $logonid, $password) or die;

   $jes->submit($job);

   $aref = $jes->wait_for_results($jobname, $timeout);

   $jes->get_results($aref);

   $jes->delete_results($aref);

   $jes->quit;

DESCRIPTION
===========

   IBM mainframe MVS systems accept job input through the Job Entry
Subsystem (JES). This input is in the form of 80-byte *card images* that
correspond to the punch cards of ancient times. The new releases of MVS
can accept this input via FTP to the MVS *internal reader* (equivalent to
the physical card readers of older systems).

   This module uses the Net::FTP module under the hood to handle the FTP
chores.

METHODS
=======

$jes = MVS::JESFTP->open($host, $logonid, $password);
-----------------------------------------------------

   This method creates a connection to the MVS system JES. If the
connection is made, open returns a reference `$jes' to the JES connection;
otherwise open returns `undefined'.

   open takes three arguments:

$host
     The IP address or DNS name of the MVS system.

`$logonid'
     A valid FTP logon ID for the host.

$password
     A valid FTP password for the host.

$jes->submit($job);
-------------------

   This method submits the jobstream contained in the file `$job'. If the
submission is successful, `submit' returns true; otherwise `submit'
returns `undefined'.

$aref = $jes->wait_for_results($jobname, $timeout);
---------------------------------------------------

   This method waits for the output of the submitted job to arrive in the
JES *hold queue*. `wait_for_results' returns an array reference `$aref' to
the a list of output files for the job suitable for input to
get_results.(1)

   `wait_for_results' takes two arguments:

`$jobname'
     The name of the job you presumedly submitted with the `submit' method.

$timeout
     How many seconds to wait for the job output to arrive; defaults to 60.

$result = $jes->get_results($aref);
-----------------------------------

   This method retrieves the output of the submitted job from the JES
*hold queue*. get_results returns `undefined' if successful; otherwise it
returns a reference to an array of names of the files it could not
retrieve. (1)

   get_results takes one argument:

`$aref'
     An array reference to the a list of output files from the job, such as
     `wait_for_results' generates. get_results will retreive (via FTP)
     each output file in turn and store them in the current subdirectory;
     file names will be preserved.

$result = $jes->delete_results($aref);
--------------------------------------

   This method deletes the output of the submitted job from the JES *hold
queue*. `delete_results' returns `true' if successful; otherwise it
returns a reference to an array of names of the jobs it could not delete.

   `delete_results' takes one argument:

`$aref'
     An array reference to the a list of output files from the job, such as
     `wait_for_results' generates. `delete_results' will delete each job
     in turn.

$jes->quit;
-----------

   This method closes the connection to JES. It is just the Net::FTP quit
method.

   (1) To use this method, your JCL *JOB* card must specify a *MSGCLASS*
that directs its output to the JES *hold queue*. If you don't understand
what this means, *don't use this method*, or you will hang your calling
program.

PREREQUISITES
=============

   You have to have Net::FTP installed.

INSTALLATION
============

     tar -xzf MVS-JESFTP-0.01.tar.gz
     perl Makefile.PL
     make
     #
     # Edit TEST.SEQ to contain your site-specific logonid,
     # password, account, & node in the appropriate places.
     #
     make test
     make install

   For Win32 systems, after unarchiving the the package, copy JESFTP.pm to
C:\Perl\site\lib\MVS (modifying this path for your installation of Perl).

AUTHOR
======

   Mike Owens

   mike.owens@state.nm.us

   Copyright (c) 2000 Mike Owens. All rights reserved. This program is free
software; you can redistribute it and/or modify it under the same terms as
Perl itself.

   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 either the GNU General Public
License or the Artistic License for more details.

SEE ALSO
========

   `perl(1)'

   `Net::FTP'

Perl extension to read and write variable-length MVS files
**********************************************************

NAME
====

   MVS::VBFile - Perl extension to read and write variable-length MVS files

SYNOPSIS
========

     use MVS::VBFile qw(:all);  # only vbget is exported by default
     $next_record = vbget(*FILEHANDLE);
     @whole_enchilada = vbget(*FILEHANDLE);

     vbopen(*FILEHANDLE, ">output_file", $blksize);
     vbput(*FILEHANDLE, $record);
     vbclose(*FILEHANDLE);
     $b = vb_blocks_written(*FILEHANDLE);

DESCRIPTION
===========

   This module provides functions to get records from mainframe MVS files
in variable blocked (VB) format and to write records in a similar format.

FUNCTIONS
=========

   vbget is exported by default; if you want any other functions, you must
ask for them by name.  `qw(:all)' exports all functions.

vbget *FILEHANDLE
     The input function, vbget(), works like the angle operator: when
     called in scalar context, it returns the next record; when in array
     context, it returns the entire file in a single array.  The file must
     be in "binary" format (no translation of bytes) and include record
     descriptor words.  The file may include block descriptor words but
     need not.

     The rationale behind this is as follows.  Most files from MVS systems
     are either fixed-length (record format FB) or variable-length (recfm
     VB).  Perl can read fixed-length mainframe files just as it reads
     other fixed-length files - open, read a certain number of bytes,
     close - but variable-length files require some special handling.
     Since Perl provides open and close, the only function needed is one to
     get the next record.

     Read the file as follows:

          open FILEHANDLE, "..name..";
          while (vbget(*FILEHANDLE)) {  # Be sure to use '*'!!
             # process and reality...
          }
          # OR do this:
          @much_in_little = vbget(*FILEHANDLE);
          # and then process the array (only on small files, of course).
          close FILEHANDLE;

vbopen *FILEHANDLE EXPR [BLKSIZE]
     Three output functions are provided: vbopen(), vbput(), and vbclose().
     These functions allow you to write out records (to tape, most likely)
     that can later be read by an MVS system.  Like vbget(), these
     functions do not translate any of the data given to them; any
     translation to EBCDIC (or anything else) must be done before the
     record is written.

     vbopen() is similar to Perl's open, but you must pass a typeglob as
     the first argument (in other words, put a * on the front of it).  The
     third argument is the blksize of the file.  The minimum blksize is 9
     bytes; the maximum, 256KB (262_144 bytes); the default, 32760.  If
     you wish to use a blksize larger than 32760, make sure that your MVS
     system will support it.  Your output must be blocked; in other words,
     you cannot write out files with RDW's but no BDW's.

     You may have more than one filehandle open at a time.

vbput *FILEHANDLE RECORD
     Puts a single logical record to the file.

vbclose *FILEHANDLE
     Closes the file.  Be sure to use this function, since it will write a
     final block that contains any remaining logical records.

vb_blocks_written *FILEHANDLE
     Can be called at any time to find the number of blocks written to the
     file.  This would be most useful after closing the file; the count
     could, for instance, be used to build an MVS-style tape header.

     Here's a full example of writing output:

          vbopen(*VBO, ">$outfile", 32760);
          foreach $record (@my_array) {
             vbput(*VBO, $record);
          }
          vbclose(*VBO);
          $b = vb_blocks_written(*VBO);

VARIABLE
========

   The variable *MVS::VBFile::bdws* applies only to input.  It tells the
module whether the file to be read contains block descriptor words.  The
default is 0 (false); set it to 1 or any other true value if the file
contains BDW's.

RESTRICTIONS
============

   For input, both VB (blocked) and V (unblocked) formats are supported.
vbget() will not work properly on format VBS (spanned).  Since VB is by
far the most commonly used format, this should not be a major snag.

   Output must be blocked (VB); in other words, you cannot write out files
with RDW's but no BDW's.

MORE ABOUT DESCRIPTOR WORDS
===========================

   Record descriptor words are 4 bytes that appear at the beginning of
each record in a VB file.  The first two bytes contain the record length
in binary (16 bits, signed, big-endian); the last two are used only by
spanned records and are ignored by this module.  Block descriptor words,
likewise, are 4 bytes that appear at the beginning of each block, having
the same format.

   My experience with FTP from MVS is limited, but it seems that if you
transfer a file from an MVS host via FTP including the RDW's, the RDW's
will be transferred but the BDW's will not.  Most applications do not
require BDW's, but if you want them, they can be transferred by converting
the VB file to undefined records (recfm=U) under MVS and then transferring
the converted file.

AUTHOR
======

   W. Geoffrey Rommel, GROMMEL@cpan.org, March 1999.

   Thanks to Bob Shair (bshair@amdocs.com) for suggesting vbput and
providing preliminary code.

reads the Macintosh Apple event dictionary from an application.
***************************************************************

NAME
====

   Mac::AETE::App - reads the Macintosh Apple event dictionary from an
application.

SYNOPSIS
========

     use Mac::AETE::App;
     use Mac::AETE::Format::Dictionary;

     $app = App->new("My Application");
     $formatter = Dictionary->new;
     $app->set_format($formatter);
     $app->read;
     $app->write;

DESCRIPTION
===========

   The App module simplifies reading the Apple event dictionary from an
application.  It will launch the application if necessary to obtain the
dictionary.

Methods
-------

new
     Example: ($name is the name of the application.)

          use Mac::AETE::App;
          use Mac::AETE::Format::Dictionary;

          $app = App->new($aete_handle, $name);

read
     (Inherited from Mac::AETE::Parser.)

     Reads the data contained in the AETE resource or handle. Example:

     $app->read;

set_format
     (Inherited from Mac::AETE::Parser.)

     Sets the output formatter used during by the 'write' subroutine.
     Example:

          $formatter = Dictionary->new;
          $app->set_format($formatter);

copy
     (Inherited from Mac::AETE::Parser.)

     Copies all suites from one Parser object into another. Example:

     $aete2 = Parser->new($aete_handle2, $another_name);
     $app->copy($aete2);

     copies the suites from $aete2 into $aete.

merge
     (Inherited from Mac::AETE::Parser.)

     Merges suites from one Parser object into another. Only the suites
     that exist in both objects will be replaced. Example:

          $aete3 = Parser->new($aete_handle2, $another_name);
          $app->merge($aete3);

write
     (Inherited from Mac::AETE::Parser.)

     Prints the contents of the AETE or AEUT resource using the current
     formatter.

          $app->write;

INHERITANCE
===========

   Inherits from Mac::AETE::Parser.

AUTHOR
======

   David Schooley <`dcschooley@mediaone.net'>

reads the Macintosh Apple event dictionary from an  Applescript dialect file.
*****************************************************************************

NAME
====

   Mac::AETE::Dialect - reads the Macintosh Apple event dictionary from an
Applescript dialect file.

SYNOPSIS
========

     use Mac::AETE::App;
     use Mac::AETE::Dialect;
     use Mac::AETE::Format::Dictionary;

     $aeut = Dialect->new();
     $aeut->read();

     $app = App->new("My Application");
     $formatter = Dictionary->new;
     $app->set_format($formatter);
     $app->read;
     $app->merge($aeut);
     $app->write;

DESCRIPTION
===========

   The data in Dialect objects can be merged into a Parser or App object
to make a complete Apple event dictionary. The module will locate the
proper AppleScript dialect file in the system folder.

   See Mac::AETE::Parser and Mac::AETE::App for more details.

Methods
-------

new
     Example:

          use Mac::AETE::Dialect;

          $app = Dialect->new;

read
     (Inherited from Mac::AETE::Parser.)

     Reads the data contained in the AETE resource or handle. Example:

     $app->read;

INHERITANCE
===========

   Inherits from Mac::AETE::Parser.

AUTHOR
======

   David Schooley <`dcschooley@mediaone.net'>

SYNOPSIS
========

     use Mac::Glue;
     my $obj = new Mac::Glue '__APPNAME__';

DESCRIPTION
===========

   See `Mac::Glue' for complete documentation on base usage and framework.

   EOT

     $self{FINISH} = <<EOT;
     =head1 AUTHOR

   Glue created by ${\($ENV{'USER'} || '????')} using `gluemac' by Chris
Nandor and the Mac::AETE modules by David C. Schooley.

   Copyright (c) ${\((localtime)[5] + 1900)}.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the terms of the Artistic License, distributed with Perl.

SEE ALSO
========

   Mac::AppleEvents, Mac::AppleEvents::Simple, macperlcat, Inside
Macintosh: Interapplication Communication, Mac::Glue, Mac::AETE.

parses Macintosh AETE and AEUT resources.
*****************************************

NAME
====

   Mac::AETE::Parser - parses Macintosh AETE and AEUT resources.

SYNOPSIS
========

     use Mac::AETE::Parser;
     use Mac::AETE::Format::Dictionary;

     $aete = Parser->new($aete_handle, $name);
     $formatter = Dictionary->new;
     $aete->set_format($formatter);
     $aete->read;
     $aete->write;

DESCRIPTION
===========

   The Parser module serves as a base class for the Mac::AETE::App and
Mac::AETE::Dialect modules.

Methods
-------

new
     Example: ($aete_handle is a handle containing a valid AETE resource.
     $name is the name of the application.)

          use Mac::AETE::Parser;
          use Mac::AETE::Format::Dictionary;

          $aete = Parser->new($aete_handle, $name);

read
     Reads the data contained in the AETE resource or handle. Example:

     $aete->read;

     =item set_format

     Sets the output formatter used during by the 'write' subroutine.
     Example:

          $formatter = Dictionary->new;
          $aete->set_format($formatter);

copy
     Copies all suites from one Parser object into another. Example:

     $aete2 = Parser->new($aete_handle2, $another_name);
     $aete->copy($aete2);

     copies the suites from $aete2 into $aete.

merge
     Merges suites from one Parser object into another. Only the suites
     that exist in both objects will be replaced. Example:

          $aete3 = Parser->new($aete_handle2, $another_name);
          $aete->merge($aete3);

write
     Prints the contents of the AETE or AEUT resource using the current
     formatter.

          $aete->write;

INHERITANCE
===========

   Parser does not inherit from any other modules.

AUTHOR
======

   David Schooley <`dcschooley@mediaone.net'>

   The data structures are adapted from modifications made to the original
aeteconvert script by Chris Nandor.

GUI-Class to create the dialogs for AssistantFrame
**************************************************

NAME
====

   AFDialogs - GUI-Class to create the dialogs for AssistantFrame

SYNOPSIS
========

DESCRIPTION
===========

   This module implements the dialogs for AssistantFrame. You shouldn't
need to access the methods directly without AssistantFrame.

HISTORY
=======

   Starting with version 0.1a this module needs MacPerl 5.1.8r4 minimum.

COPYRIGHT
=========

     Copyright 1998, Georg Bauer

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AVAILABILITY
============

   The latest version of this library is likely to be available from:

     http://www.westfalen.de/hugo/mac/

     If there are problems with this library, just drop a note to:

     Georg_Bauer@muensterland.org

     =cut

Interface to Anarchie 2.01+
***************************

NAME
====

   Mac::Apps::Anarchie - Interface to Anarchie 2.01+

SYNOPSIS
========

     use Mac::Apps::Anarchie;
     $ftp = new Mac::Apps::Anarchie;
     #see description for the rest

DESCRIPTION
===========

   This is a MacPerl interface to the popular MacOS shareware FTP/archie
client, Anarchie.  For more info, see the Anarchie documentation.

   Also required is the Mac::Apps::Launch module, which requires MacPerl
5.1.4r4.

   NOTE: for some explanations of methods, drop Anarchie on Script Editor,
and check the Anarchie docs.

   Before using, you must autosplit the module.  See version notes for 1.4
below.

Standard Suite
--------------

     $ftp->open(ALIAS);
     $ftp->quit;
     $ftp->showabout;
     $ftp->close;
     $ftp->closeall;
     $ftp->undo;
     $ftp->cut;
     $ftp->copyclip;
     $ftp->paste;
     $ftp->clear;
     $ftp->selectall;

Anarchie Suite
--------------

   NOTE: * denotes compatability with Fetch.  Fetch does not use the
variables SOCKS, FIRE, BINARY, or TYPE.  Fetch implements some of these
methods differently than Anarchie.  To use Fetch instead of Anarchie for
these methods, call the method:

     $ftp->useagent('FTCh');

   There are two forms of each of the following methods: "method" and
"methodURL".  The methodURL version takes the user name, password, host
and path in the URL instead of separately.  URLs are usually in the form:

     ftp://user:password@host.com/path/to/file
     ftp://user:password@host.com//absolute/path/to/file

   See Anarchie docs for more info on URLs.

   Also, the host, username, password, proxy firewall and socks firewall
can be preset and then omitted during the method call.  This saves a lot
of code writing if you are going to make multiple calls to the same host.
If a method explicitly names any of those strings, it overrides presets.
If username and password are not specified anywhere, FTP is done
anonymously.

     $ftp->host(HOST);
     $ftp->user(USER);
     $ftp->pass(PASS);
     $ftp->fire(FIRE);
     $ftp->socks(SOCKS);

waitreply
          $ftp->waitreply(BOOLEAN);

     If you don't want MacPerl to wait for Anarchie to finish what it is
     doing, then call this with the value 0.  You can change it back to 1
     if you do want it to wait.  The initial setting is 1.

fetch *
          $ftp->fetch(FILENAME [, PATH, BINARY, TYPE, HOST, USER, PASS, FIRE, SOCKS]);
          $ftp->fetchURL(FILENAME [, URL, BINARY, TYPE, FIRE, SOCKS]);

     Fetches file and saves to FILENAME on local drive.  BINARY is boolean
     for whether file is binary or ascii.  TYPE is the creator code to
     link file to.  NOTE: for Fetch, FILENAME must be an existing
     directory name, NOT a filename.  For Anarchie, FILENAME must be a
     file if the fetched item is a file or a directory if the fetched item
     is a directory.  Anarchie will create FILENAME on the local drive if
     it does not exist.

store *
          $ftp->store(FILENAME [, PATH, BINARY, HOST, USER, PASS, FIRE, SOCKS]);
          $ftp->storeURL(FILENAME [, URL, BINARY, FIRE, SOCKS]);

     Stores file FIELNAME from local drive to remote location specified.

rename *
          $ftp->rename(NEWNAME [, PATH, HOST, USER, PASS, FIRE, SOCKS]);
          $ftp->renameURL(NEWNAME [, URL, FIRE, SOCKS]);

     Renames file NEWNAME to value in PATH or URL.

remove *
     $ftp->remove([PATH, HOST, USER, PASS, FIRE, SOCKS]);
     $ftp->removeURL([URL, FIRE, SOCKS]);

     Removes file/directory specified in PATH or URL.

mkdir *
          $ftp->mkdir([PATH, HOST, USER, PASS, FIRE, SOCKS]);
          $ftp->mkdirURL([URL, FIRE, SOCKS]);

     Make directory specified in PATH or URL.

sendcommand *
          $ftp->sendcommand([PATH, HOST, USER, PASS, FIRE, SOCKS]);
          $ftp->sendcommandURL([URL, FIRE, SOCKS]);

     Send raw FTP command.

index *
          $ftp->index([PATH, HOST, USER, PASS, FIRE, SOCKS]);
          $ftp->indexURL([URL, FIRE, SOCKS]);

     Display index listing.  SITE INDEX command must be implemented on
     host.

list *
          $ftp->list(FILENAME, [PATH, HOST, USER, PASS, FIRE, SOCKS]);
          $ftp->listURL(FILENAME, [URL, FIRE, SOCKS]);

     List files in a directory, put into file FILENAME.  Fetch apparently
     only lists to the screen, while Anarchie lists to a file.  For Fetch,
     just put any old text in place of FILENAME and it should work just
     fine.

nlist
          $ftp->nlist(FILENAME, [PATH, HOST, USER, PASS, FIRE, SOCKS]);
          $ftp->nlistURL(FILENAME, [URL, FIRE, SOCKS]);

     List names of files in a directory, put into file FILENAME.

Anarchie Suite, Part Deux
-------------------------

   NOTE: These methods are NOT supported at all by Fetch.

find
          $ftp->find(FILENAME [, SERVER, MAX, CASE, REGEX, URL]);

     Find file containing text FILENAME in Archie SERVER with maximum
     matches MAX.  CASE is boolean (0 or 1) for case sensitive.  REGEX is
     0, 1 or 2 for denoting that FILENAME is a substring, pattern, or
     regular expression.

macsearch
          $ftp->macsearch(FILENAME);

     Find Mac file containing text FILENAME on Ambrosia's Mac server.

others
          $ftp->showtranscript;
          $ftp->showarchie;
          $ftp->showget;
          $ftp->updateserverlist;
          $ftp->showlog;
          $ftp->showmacsearch;
          $ftp->showtips;

geturl
     $ftp->geturl(URL [, FILENAME]);

HISTORY
=======

v.1.4, January 3, 1998
     Basic cleanup.  Requires MacPerl 5.1.4r4 or better now.

v.1.4, November 3, 1997
     Pulled out main functions as autosplit/autoload files.  Before using,
     you must run a script such as the following, in order to AutoSplit
     the routines:

          #!perl -w
          use AutoSplit;
          $dir = 'HD:MacPerl:site_perl';
          autosplit("$dir:Mac:Apps:Anarchie.pm","$dir:auto",0,1,1);

     This also means that the `Mac::Apps::Anarchie' class is no longer
     aliased to simply Anarchie.

v.1.3, October 15, 1997
     Added waitreply method.  Fixed error catching.  Erorrs still are not
     descriptive, but now they are reported.  :-)

v.1.2, October 13, 1997
     Get app launching from Mac::Apps::Launch, fixed descriptor disposing.

v.1.1 May 4, 1997
     Whoops, fixed something I broke in the AEPutParamDesc stuff.

v.1.0 May 4, 1997
     Finally got around to cleaning it up.  Only minor changes.

v.0.2 March 20, 1997
     First 'public' beta.

BUGS
====

regex find
     Still having problems with the substring/pattern/regex option on
     `"find"' in this node.  I am not sure what the problem is.

SEE ALSO
========

Anarchie Home Page
     http://www.stairways.com/anarchie/index.html

AUTHOR
======

   Chris Nandor `<pudge@pobox.com>' http://pudge.net/

   Copyright (c) 1998 Chris Nandor.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.  Please see the Perl Artistic License.

VERSION
=======

   Version 1.50 (03 January 1998)

MacPerl module to launch applications
*************************************

NAME
====

   Mac::Apps::Launch - MacPerl module to launch applications

SYNOPSIS
========

     use Mac::Apps::Launch;
     my @apps = qw(R*ch Arch MPGP);
     my $path = "HD:System Folder:Finder";
     LaunchApps([@apps], 1) or warn $^E; # launch and switch to front
     LaunchApps([@apps])    or warn $^E; # launch and don't switch
     LaunchApps($app, 1)    or warn $^E; # launch and switch to front
     LaunchSpecs($path, 1)  or warn $^E; # use path instead of app ID
     QuitApps(@apps)        or warn $^E; # quit all @apps
     QuitAllApps(@apps)     or warn $^E; # quit all except @apps
     IsRunning('MACS');                  # returns boolean for whether
                                         # given app ID is running
     SetFront('MACS')       or warn $^E; # set Finder to front
     Hide('MACS')           or warn $^E; # hide Finder
     Show('Finder', 1)      or warn $^E; # show Finder (1 == use name)

DESCRIPTION
===========

   Simply launch or quit applications by their creator ID.  The Finder can
be quit in this way, though it cannot be launched in this way.

   This module is used by many other modules.

   This module as written does not work with MacPerls prior to 5.1.4r4.

EXPORT
======

   Exports functions `QuitApps', `QuitAllApps', and `LaunchApps',
`IsRunning', `LaunchSpecs', `SetFront', Hide, Show.

HISTORY
=======

v.1.70, June 4, 1999
     Cleaned up stuff.  Added `SetFront', Show, Hide.  Fixed setting of
     $^E.  Improved QuitAllApps to not quit only normal apps by checking
     `processType' for "APPL".

v.1.60, September 28, 1998
     Added `LaunchSpecs'.  Use this when the app does not have a unique
     app ID, the app is not really an app (like the Finder), or you have
     more than one instance of the app, and want to launch a particular
     one.

v.1.50, September 16, 1998
     Added `IsRunning'.

v.1.40, August 3, 1998
     Only launches application if not already open; e.g., won't launch
     newer version it finds if older version is open.

v.1.31, May 18, 1998
     Added `AEDisposeDesc' call (D'oh!).  Dunno why I forgot this.

v.1.3, January 3, 1998
     General cleanup, rewrite of method implementation, no longer support
     versions prior to 5.1.4r4, addition of Quit methods, methods return
     undef on failure (most recent error in $^E, but could be multiple
     errors; oh well).

AUTHOR
======

   Chris Nandor <pudge@pobox.com>, http://pudge.net/

   Copyright (c) 1999 Chris Nandor.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the terms of
the Artistic License, distributed with Perl.

VERSION
=======

   Version 1.70 (June 4, 1999)

Interface to MacPGP 2.6.3
*************************

NAME
====

   Mac::Apps::MacPGP - Interface to MacPGP 2.6.3

SYNOPSIS
========

     use Mac::Apps::MacPGP;
     $object = new Mac::Apps::MacPGP;
     #see description for the rest

DESCRIPTION
===========

   MacPerl interface to MacPGP 2.6.3.  Older versions WILL NOT WORK.  The
MIT version, MacPGP 2.6.2, does not support nearly the number of
AppleEvents as does 2.6.3.  For those outside the U.S., you will not be
able to download the program; but there are International versions.
Perhaps in the future I will add support for those.  Many of the functions
should work fine for those, actually, but I imagine some will not.

   MacPerl 5.1.1 (released January 1997) or higher is also required
because of bugs in the AppleEvents library in previous versions.

   Also required is the Mac::Apps::Launch module, however, which requires
MacPerl 5.1.4r4 or higher.  :)

   For optional parameters, MacPGP will either use the default or prompt
the user.  Parameters are required unless noted as optional.  Exception:
For the `$OUTP' parameter, the MacPGP default is binary but I set it to
ASCII in the module, because I rarely use binary PGP files.

   Boolean parameters take a value of 1 (true) or 0 (false).  Filenames
should be given the full pathname.  To leave an optional parameter empty,
give it a value of undef.  Optional parameters will either be given the
default by MacPGP or MacPGP will prompt the user for a value if necessary.

   For further explanation of methods and parameters, see your MacPGP
2.6.3 user guide.

   If something seems seems to not work properly, try doing it directly
from MacPGP before assuming it is the fault of MacPGP.pm.  :-)

USAGE
=====

encrypt
-------

   Encrypt.  Returns encrypted text for `$TYPE="ncrd"'.

   $object->encrypt(TYPE, DOBJ, [RECV|CPAS], PASS, USID, SIGN, READ, OUTP,
LATI, WRAP, ALNS, TABX, MDAL, WSRC, COPT);

TYPE
     One of "encr" (encrypt files), "ncrd" (encrypt data), or "cncr"
     (conventional encryption).

DOBJ
     For `$TYPE="encr"' or `"cncr"', `$DOBJ' is either a filename or a
     reference to an array of filenames.  For `$TYPE="ncrd"', `$DOBJ' is
     the data to be encrypted.  If `$DOBJ' is empty, MacPGP will attempt
     to encrypt the clipboard instead.

RECV
     Either the name of a recipient or a reference to an array of
     recipients.  (encr and ncrd only)

CPAS
     Password used for conventional encryption.  Optional.  (cncr only)

PASS
     The password.  Optional.

USID
     Name of secret key.  Optional.

SIGN
     Sign?  One of "sepa" (signature in separate file), "incl", (signature
     included), "omit" (omitted, don't sign).  Optional.

READ
     Input format.  One of "macb" (MacBinarize first), "text", (convert
     text to CRLF), "norm" (do nothing).  Optional.

OUTP
     Output format.  One of "bina" (8-bit binary), "asci",
     (ASCII-armored).  Optional.

LATI
     Convert text to ISO-Latin1?  Boolean.  Optional.

WRAP
     Wrap text to this many lines, between 30 and 100.  0=no wrap.
     Optional.

ALNS
     For armored files, split output into files of this line length.  0=no
     split.  Optional.

TABX
     For wrapped files, expand tabs to this many spaces, from 0 to 9.
     Optional.

MDAL
     Use "MD5 " or "SHA1" to compute message digest for file.  Optional.

WSRC
     Wipe out source file?  Boolean.  Optional.  (encr and cncr only)

COPT
     Self-decrypting?  One of "sdf" (self-decrypting) or "sdfb",
     (self-decrypting and binhexed).  Default is neither.  Optional. (cncr
     only)

decrypt
-------

   Decrypt.  Returns decrypted text for `$TYPE="dcrd"' and `$DOBJ ne
undef'.  Returns signatures for `$TYPE="decr"'.

   $object->decrypt(TYPE, DOBJ, PASS, SCRE, NSIG, APL2, RECV);

TYPE
     One of "decr" (decrypt files), "dcrd" (decrypt data).

DOBJ
     For `$TYPE="decr"', `$DOBJ' is either a filename or a reference to an
     array of filenames.  For `$TYPE="dcrd"', `$DOBJ' is the data to be
     decrypted.  If `$DOBJ' is empty, MacPGP will attempt to decrypt the
     clipboard instead.  To get signatures from "dcrd" event, see
     `"checksignresult"' in this node.

PASS
     The password.  Optional.

SCRE
     Decrypt to screen instead of file?  Boolean.  Optional.

NSIG
     Do not put up bad signature alerts?  Boolean.  Optional.

APL2
     If direct object is a separate sig file, the file the sig applies to.
     Optional.

RECV
     File to decrypt to.  Optional. (decr only)

sign
----

   Sign.  Returns encrypted signed text for `$TYPE="sigd"', returns
signature results for `$TYPE="sign"'.

   $object->sign(TYPE, DOBJ, PASS, USID, SIGN, READ, OUTP, LATI, WRAP,
ALNS, TABX, MDAL, STFX);

TYPE
     One of "sign" (sign files), "sigd" (sign data).

DOBJ
     For `$TYPE="sign"', `$DOBJ' is either a filename or a reference to an
     array of filenames.  For `$TYPE="sigd"', `$DOBJ' is the data to be
     signed.  If `$DOBJ' is empty, MacPGP will attempt to sign the
     clipboard instead.

PASS
     The password.  Optional.

USID
     Name of secret key.  Optional.

SIGN
     Sign?  One of "sepa" (signature in separate file), "incl", (signature
     included), "omit" (omitted, don't sign).  Optional.

READ
     See READ in `"encrypt"' in this node.  Optional.

OUTP
     See OUTP in `"encrypt"' in this node.  Optional.

LATI
     See LATI in `"encrypt"' in this node.  Optional.

WRAP
     See WRAP in `"encrypt"' in this node.  Optional.

ALNS
     See ALNS in `"encrypt"' in this node.  Optional.

TABX
     See TABX in `"encrypt"' in this node.  Optional.

MDAL
     See MDAL in `"encrypt"' in this node.  Optional.

STFX
     Set text flag? (Esoteric option for some PGP/MIME implementations.)
     Boolean.  Optional.

asciify
-------

   Asciify a file.

   $object->asciify(DOBJ, READ, LATI, WRAP, ALNS, TABX);

DOBJ
     Filename or reference to an array of filenames to be asciified.

READ
     See READ in `"encrypt"' in this node.  Optional.

LATI
     See LATI in `"encrypt"' in this node.  Optional.

WRAP
     See WRAP in `"encrypt"' in this node.  Optional.

ALNS
     See ALNS in `"encrypt"' in this node.  Optional.

TABX
     See TABX in `"encrypt"' in this node.  Optional.

execute
-------

   Execute MacPGP command-line command.

   $object->execute(DOBJ, PASS, LATI, WRAP, ALNS, TABX, MDAL);

DOBJ
     Command to be executed (i.e., `pgp -kv pudge').

PASS
     The password.  Optional.

LATI
     See LATI in `"encrypt"' in this node.  Optional.

WRAP
     See WRAP in `"encrypt"' in this node.  Optional.

ALNS
     See ALNS in `"encrypt"' in this node.  Optional.

TABX
     See TABX in `"encrypt"' in this node.  Optional.

MDAL
     See MDAL in `"encrypt"' in this node.  Optional.

generate
--------

   Generate new public/secret key pair.

   $object->generate(DOBJ, LENG, EBIT);

DOBJ
     User id of new key.

LENG
     Bit length of key.  Higher is stronger and slower.  Lower is faster
     and less secure.  Can be either a number from 384 to 2048, or one of
     the following: "casu" (casual, 512), "comm" (commercial, 768), "mili"
     (military, 1024).  Default is casual.  Optional.

EBIT
     Number of bits in encryption exponent.  Default is 17.  Optional.

extract
-------

   Extract (export) a key.

   $object->extract(DOBJ, RECV, KEYR, OUTP);

DOBJ
     Key id to extract.

RECV
     File to extract key to.  File must already exist (for now).  See
     `"create"' in this node.

KEYR
     Filename of keyring to perform operation on.  Optional.

OUTP
     Output format.  One of "bina" (8-bit binary), "asci",
     (ASCII-armored).  Optional.

keyring
-------

   Miscellaneous keyring functions.

   $object->keyring(TYPE, DOBJ, KEYR, USID);

TYPE

    addk
          Add key in file `$DOBJ'.

    ckey
          Count keys matching `$DOBJ'.

    crfy
          Certify key matching `$DOBJ'.

    fing
          Return fingerprint of key matching `$DOBJ'.

    remv
          Remove key matching `$DOBJ'.

    selk
          Show dialog box, with text `$DOBJ', of keys available in
          keyring.  Returns user id of selected key.

DOBJ
     Varies; see above.

KEYR
     Filename of keyring to perform operation on.  Optional.

USID
     Name of secret key to certify with.  Optional. (crfy only)

create
------

   Create temporary scratch file.  File with same name, if existing, is
erased.

   $object->create(DOBJ);

DOBJ
     New filename.

clip2file
---------

   Copy Clipboard to file.

   $object->clip2file(DOBJ);

DOBJ
     Filename of destination file.

file2clip
---------

   Copy file to Clipboard.  NOTE:  This only works if MacPGP is the front
application (see `"switchapp"' in this node).

   $object->file2clip(DOBJ);

DOBJ
     Filename of source file.

checksignresult
---------------

   Check signature result from previous decrypt data event.  See
`"decrypt"' in this node.

   $object->checksignresult;

getlasterror
------------

   Returns error message from previous MacPGP Apple Event.

   $object->getlasterror;

getversion
----------

   Returns MacPGP version.

   $object->getversion;

window
------

   Show/hide window.

   $object->window(DOBJ);

DOBJ
     Either "show" or "hide".

logfile
-------

   Echo PGP messages to a logfile.  If logging was active when true sent
or no filename is given, returns error. If logging was active.  Returns
full pathname if successful.

   $object->logfile(DOBJ, RECV);

DOBJ
     Logging?  Boolean.

RECV
     Full pathname of logfile.  Existing file of same name erased.
     Optional.

switchapp
---------

   Set up window handling.  Whenever another method is called, MacPGP.pm
will use these two variables to determine what app should be in front.
Note:  when muliple methods are called, this doesn't seem to work great.
Oh well.  Maybe someone else will fix this for me or have some ideas.
Until then, I suggest that if you DO want MacPGP to come to the front and
you have sveral methods being called one after the other, that you just
set `$object-'switchapp(1)> and don't have it switch back.

   $object->switchapp(SWITCH, APP);

SWITCH
     Switch to MacPGP when method is called?  Boolean.

APP
     Switch to `$APP' after $object is destroyed (i.e., when last
     reference to $object is made).  If left blank and `$SWITCH=1', MacPGP
     will go to front and stay there.

getresults
----------

   Returns result of parameter `$DOBJ' from last method call.

   $object->getresults(DOBJ);

DOBJ
     Name of parameter keyword, one of "---", "result" (synonym for "---",
     the direct object parameter), "errs" (error string), "errn" (error
     number), "outp".  Optional, defaults to "result".

getresultsall
-------------

   Returns hash of all result parameters from last method call.

   %results = $object->getresultsall;

quitpgp
-------

   Quit MacPGP app.

   $object->quitpgp;

HISTORY
=======

v.1.2, January 3, 1998
     Basic cleanup.  Requires MacPerl 5.1.4r4 or better now.

v.1.1, October 13, 1997
     Get app launching from Mac::Apps::Launch, fixed descriptor disposing.

v.1.0, February 9, 1997
     First full release.

        * Added a whole slew of scripts and extensions for BBEdit,
          YA-NewsWatcher, Clipboard, Drag-n-Drop.  See
          MacPGP-scripts.readme for details.

        * Changed the behavior of switchapp method.  Switching to MacPGP
          only occurs when switchapp method is invoked, and switching back
          only occurs when object is destroyed.  Previously, switching
          took place before and after each method call.

        * Fixed bug which required decrypt, encrypt and sign to have a
          DOBJ value.  When one of those methods is performing a function
          on data (dcrd, ncrd, sigd), MacPGP will use Clipboard if no data
          is given.

        * Fixed bug in `_MpgpBBool' routine which would not catch
          unacceptable input.

v.1.0b3, January 15, 1997
     Simply switching to .tar.gz for CPAN instead of .sit.hqx.

v.1.0b2 January 8, 1997
     Fixes problems in earlier release, optimizes, module-izes.

        * Change name from MacPGP to Mac::Apps::MacPGP.

        * Rewrote AppleEvent calls using individual `AEPutParamDesc' and
          `AEBuild' calls.  Should be more efficient.  Fixes other bugs
          (like problems with lists and certain characters in TEXT values).

        * Improved error handling and descriptions.  Uses carp for MacPGP
          errors.

        * Made file and recipients variables capable of handling either a
          scalar or a reference to an array.

        * Added switchapp, getresults, getresultsall, quitpgp methods.
          See docs above.

v.1.0b1, January 3, 1997
     First public beta.  Nearly fully-functional.

BUGS
====

app switching
     I want to benchmark different ways to switch between applications and
     use the best one.  Stay tuned.  If you have ideas, let me know.

other versions
     I am investigating the idea of making this useful with other versions
     of MacPGP (international versions, and limited capabilities of MacPGP
     2.6.2) and the future version of PGP 5.0.

stealthify
     I have one more method group to add, and that is for
     stealtifying/destealthifying files.  This will come along eventually,
     but it is not a high priority.  First I have to figure out how to use
     it and what it does ... :-)  If you have a need/want for it, let me
     know.

SEE ALSO
========

MacPGP 2.6.3 Home Page
     http://www.math.ohio-state.edu/~fiedorow/PGP/

MacPGP 2.6.3 Documentation
     Included with the above package, take special note of the PGP User's
     Guide, MacPGP263_Manual, and MacPGP263_AppleEvents.

AUTHOR
======

   Chris Nandor `<pudge@pobox.com>' http://pudge.net/

   Copyright (c) 1998 Chris Nandor.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.  Please see the Perl Artistic License.

VERSION
=======

   Version 1.20 (03 January 1998)

An AppleEvent Module for Progress Bar 1.0.1
*******************************************

NAME
====

   Mac::Apps::PBar - An AppleEvent Module for Progress Bar 1.0.1

SYNOPSIS
========

     use Mac::Apps::PBar;
     $bar = Mac::Apps::PBar->new('FTP DOWNLOAD', '100, 50');
     $bar->data({
     	Cap1=>'file: BigFile.tar.gz',
     	Cap2=>'size: 1,230K',
     	MinV=>'0',
     	MaxV=>'1230',
     });
     for(0..10) {
     	$n = $_*123;
     	$bar->data(Valu, $n);
     	sleep(1);
     }
     sleep(5);
     $bar->close_window;

DESCRIPTION
===========

   Progress Bar is a small AppleScriptable utility written by Gregory H.
Dow. This module, `PBar.pm', generates Apple Event calls using AEBuild in
place of AppleScript.  Because the Apple Event Manager is not involved,
Progress Bar updates more quickly.

   In most applications the time taken to up date the Progress Bar must be
kept to a minimum. On this machine (68030 CPU) An `AppleScript' update to
the progress bar takes about 0.72 seconds. Using `PBar.pm' the time is
reduced to 0.10 seconds; a seven-fold improvement.

   Progress Bar 1.0.1 is found by a search for the creator type `PBar' and
launched automatically. To minimise the time taken for the search,
`Progress Bar 1.0.1' should be kept in the same volume as `PBar.pm'.

CREATING A NEW PROGRESS BAR
---------------------------

   Progress Bar 1.0.1 is launced and a new Progress bar created by:

     $bar = Mac::Apps::PBar->new('NAME', 'xpos, ypos');

   where the arguments to the new constructor have the following meanings:

First argument
     is a string for the title bar of the Progress Bar window.

Second argument
     is a string `'xpos, ypos'' defining the position of the top left-hand
     corner of the window in pixels. The pair of numbers and the comma
     should be enclosed in single quotes as shown.

SENDING DATA
------------

   Values are sent to the `Progress Bar' by the data sub-routine using the
variable names in the `aete resource' for each of the `Progress Bar'
properties.  There are five property values for the `PBar' class. The
syntax is:

     $bar->data('property', 'value')

   or

     $bar->data({'property', 'value', 'property', 'value'})

   The second method is suggested.

*Minimum value*  `'MinV''
     This is the value of the displayed parameter corresponding to the
     origin of the bar. Often it is zero, but may take other values (for
     instance a temperature bar in degrees Fahrenheit might start at 32).

*Maximum value*  `'MaxV''
     This is the value corresponding to the full extent of the bar. It can
     take any value, such as the size of a file in KB, or 100 for a
     percentage variable. Bar increments are integers, hence
     discrimination is finer the larger the value of `MaxV'.

*Current value*  `'Valu''
     This is the value which sets the progress bar to the position
     corresponding to the current value of the parameter displayed. The
     value must obviously lie somewhere between `MinV' and `MaxV'.

*Upper caption*  `'Cap1''
     This string, immediately under the title bar, can be set to anything
     appropriate for the application.

*Lower caption*  `'Cap2''
     The lower caption string can either be set to a constant value (e.g.
     `File size = 1234K') or up-dated with the bar. For instance it might
     be appropriate to set `'Cap2'' as follows:

          $n = $max_value - $current_value;
          $bar->data({Cap2=>"remaining $n"});

     Note the double quotes so that the value of $n is interpolated.

     It should be remembered however that it will take twice as long to
     update both `Cap2' and `Valu' as just to update the bar `Valu' by
     itself. In applications where speed is of the essence, just the bar
     value `Valu' should be changed.

SEE ALSO
--------

   The following documents, which are relevant to AEBuild, may be of
interest:

AEGizmos_1.4.1
     Written by Jens Peter Alfke this gives a description of AEBuild on
     which the MacPerl AEBuildAppleEvent is based. Available from:

          ftp://dev.apple.com/
          devworld/Tool_Chest/Interapplication_Communication/
          AE_Tools_/AEGizmos_1.4.1

aete.convert
     A fascinating MacPerl script by David C. Schooley which extracts the
     aete resources from scriptable applications. It is an invaluable aid
     for the construction ofAEBuild events. Available from:

          ftp://ftp.ee.gatech.edu/
          pub/mac/Widgets/
          aete.converter_1.1.sea.hqx

AE_Tracker
     This a small control panel which allows some or all AE Events to be
     tracked at various selectable levels of information. It is relatively
     difficult to decipher the output but AE_Tracker can be helpful.
     Available from:

          ftp://ftp.amug.org/
          pub/amug/bbs-in-a-box/files/system7/a/
          aetracker2.0.sit.hqx

Inside Macintosh
     Chapter 6 "Resolving and Creating Object Specifier Records" . The
     summary can be obtained from:

          http://gemma.apple.com/
          dev/techsupport/insidemac/IAC/
          IAC-287.html

Progress Bar 1.0.1
     Obtainable from Info-Mac archives as:

          info-mac/dev/osa/progress-bar-1.0.1.hqx

   References are valid as of May 1997.

AUTHORS
=======

   Chris Nandor `<pudge@pobox.com>' http://pudge.net/

   Alan Fry `<ajf@afco.demon.co.uk>'

   Copyright (c) 1998 Chris Nandor and Alan Fry.  All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  Please see the Perl Artistic License.

HISTORY
=======

Version 1.3, 3 January 1998
     General cleanup.  Now requires MacPerl 5.1.4r4.

Version 1.2, 13 October 1997
     Switched to Mac::Apps::Launch package.

Version 1.1, 16 September 1997
     Put in the hashref methods to change multiple data in one call.

GUI-Class to build an assistant-like line of frames resembles the standard OS assistants/wizards.
*************************************************************************************************

NAME
====

   Mac::AssistantFrames - GUI-Class to build an assistant-like line of
frames resembles the standard OS assistants/wizards.

SYNOPSIS
========

   This uses a static predefined sequence. This is easy to set up and easy
to process.

     use Mac::AssistantFrames;

     my $assist = Mac::AssistantFrames->new();

     $assist->addToSequence(sub { $assist->startFrame("title", "description"); });
     $assist->addToSequence(sub { $assist->yesnoFrame("title", "description"); });
     $assist->addToSequence(sub { $assist->finishFrame("title", "description"); });

     my $res = $assist->processSequence();
     if (defined($res)) {
        print join(":", @$res);
     }

   This is for handcoded sequencing through dialogs - this allows a
flexible sequence and shows some more of the methods.

     use Mac::AssistantFrames;

     my $assist = Mac::AssistantFrames->new();

     while ($assist->running()) {
        my $last = $assist->getLastFrame();
        if ($last eq "<empty>") {
           $assist->startFrame("title", "description");
        } elsif ($last eq "<start>") {
           $assist->constantFrame("dlg1", "title",
                                  "description", "value");
        } elsif ($last eq "dlg1") {
           $assist->singleSelectionFrame("dlg2", "title",
                                         "description",
                                         ["v1", "v2", "v3"]);
        } elsif ($last eq "dlg2") {
           $assist->constantHiddenFrame("dlg3", "value");
        } elsif ($last eq "dlg3") {
           $assist->finishFrame("title", "description");
        }
     }
     if ($assist->getLastFrame eq "<finish>") {
        print $assist->joinedAnswersr(":"), "\n";
     } else {
        print "aborted\n";
     }

DESCRIPTION
===========

   This Module implements simple assistant style frames for MacPerl. You
can use it if you need to ask the user some questions in sequence to
accomplish a task. This could be done with one dialogbox, too. But the
assistant approach is often easier to understand, especially if the user
doesn't know much about the subject at hand.  This is the case most often
with configuration of new software packages, where the user has to be
given much more detailed descriptions of what to do as would fit on a
simple dialog.

   The AssistantFrame allows backward navigation in case the user erred on
some of his answers. It allows complete backwind of the frames (abortion
of the process) and it has a uniform userinterface that resembles a lot
the Mac-style assistants.

CLASS METHODS
=============

new()
     This constructor creates a new frame sequence object.

Version()
     This method returns the version of the module.

METHODS
=======

running()
     This checks if the assistant object is in running state. If the
     "<start>" frame is aborted, this is reset to 0. If the "<finish>"
     frame is accepted, this is reset to 0.

backupOne()
     This method backs up one frame. This is internally used, you seldom
     have to invoke it yourself.

continueOne(name, value)
     This method adds a successfull frame to the sequence. This is used
     internally, so you shouldn't need to call this yourself.

abort([text])
     This method stops the assistant. If "text" is given, it creates an
     alert dialog.  If it is not given, the assistant is just canceled.
     This can be used to react on errors in a assistant processing.

standardAction(name, dlg)
     This method is internally used to process the events from the dialog.
     Just ignore it.

getLastFrame()
     This method returns the last frame the user completed. This is needed
     to allow backing up and sequencing correctly. If the sequence of
     frames is empty, it returns "<empty>".

getLastFrameRaw()
     This method is used to get the last frame, as is getLastFrame. Only
     difference: getLastFrameRaw delivers the frame-name in "raw" format -
     names of hidden constant elements is bracketed in []. This function
     is used internally to distinguish frames from constants.

getLastAnswer()
     This returns the last answer given. It is usefull to make frames
     dependend on older frames.

getAnswers()
     This returns a reference to the array of the answer-strings.

joinedAnswers(sep)
     This returns a string created by joining all answers together,
     separated by sep.

getNumAnswers()
     This returns the number of accumulated answers.

addToSequence(closure)
     This adds the closure to the sequence array of the assistant. The
     sequence array allows a simple processing of a static sequence of
     frames.

processSequence()
     This processes the sequence array and returns a reference to the
     array of answers.

FRAMES
======

startFrame(title, description)
     This frame has the special name "<start>". It must be the first frame
     in the sequence and should give the user a short introduction into
     the task at hand. The user can only abort the sequence if he is at
     this frame and backs up, or by closing the window of the current
     frame (this can be done in any frame). The startframe produces the
     empty string as value. Any other frame can take over the rule of the
     startframe by giving it the name "<start>".

finishFrame(title, description)
     This frame has the special name "<finish>". It must be the last frame
     in the sequence and should give the user a description of the effect
     this whole sequence would have if completed. It produces the empty
     string as value. Any frame can take over the rule of the finish-frame
     by giving it the name "<finish>".

constantFrame(dlg, title, description, value)
     This frame is just an informational Message that is associated with a
     constant value. It is often needed if you have to give more detailed
     descriptions.

constantHiddenFrame(value)
     This frame is no frame - it is just a constant value that is spliced
     into the answer list. This might be needed by your application, if
     you want to construct a string out of the answer-list with join. If
     backed-up, this frame is ignored.

textEntryFrame(dlg, title, description, value)
     This frame allows the entry of free text into a frame. This text is
     then delivered as answer.

extendedTextEntryFrame(dlg, title, description, value, format, [pattern])
     This is identical to textEntryFrame, except that it shows some
     additional description on the format of the text to be entered. An
     optional additional parameter gives you the possibility to give a
     regexp that must match with the entered string.

numberEntryFrame(dlg, title, description, value)
     This is identical to textEntryFrame, but it expects you to enter a
     number and does check the syntax of your entry. Numbers are always
     delivered with a sign, even if that is "+".

extendedNumberEntryFrame(dlg, title, description, value, format, from, to)
     This is identical to numberEntryFrame, except that you can give an
     additional parameter that gives a description about the number to be
     entered. Two more additional parameters make a range of numbers you
     are allowed to enter.

yesnoFrame(dlg, title, description)
     This frame asks a simple yes-no question. This may be used for asking
     for optional parts of the assistant. It delivers a Y or a N as answer.

radioFrame(dlg, title, description, values, labels [, offset])
     This frame presents a selection using radio buttons. Only one value
     can be selected. This is usefull for small selections. The strings
     from labels are used for the frame, the strings from values are
     delivered in the answer. The offset is used for the positioning of
     the elements.

singleSelectFrame(dlg, title, description, [val1, val2, val3])
     This frame allows a single selection out of a list of values. This
     should be used if there are more than 5 values to choose from, or if
     the number of values is not known at compiletime.

COPYRIGHT
=========

     Copyright 1998, Georg Bauer

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AVAILABILITY
============

   The latest version of this library is likely to be available from:

     http://www.westfalen.de/hugo/mac/

     If there are problems with this library, just drop a note to:

     Georg_Bauer@muensterland.org

     =cut

Interface to Open Transport PPP
*******************************

NAME
====

   Mac::Comm::OT_PPP - Interface to Open Transport PPP

SYNOPSIS
========

     use Mac::Comm::OT_PPP;
     $ppp = new Mac::Comm::OT_PPP;

DESCRIPTION
===========

   This module allows you to do basic operations with OT/PPP, the PPP
connection software from Apple Computer designed for use with their Open
Transport networking architecture.  For more information on Open Transport
or OT/PPP, see the Open Transport web site.

PPPconnect
          $ppp->PPPconnect(USER,PASS,ADRS);

     Connect to phone number ADRS as user USER with password PASS.

PPPdisconnect
          $ppp->PPPdisconnect();

     Disconnect.

PPPstatus
          $hash = $ppp->PPPstatus();
          foreach $key (keys %{$hash}) {
          	print "$key: $$hash{$key}\n";
          }

     Return status:

    RAsb
          State of connection

    RAsc
          Seconds connected

    RAsr
          Seconds remaining

    RAun
          User name

    RAsn
          Server name

    RAms
          Most recent message for connection

    RAbm
          Baud rate of connection

    RAbi
          Bytes in/received

    RAbo
          Bytes out/sent

    RAsp
          Connection type (?)

PPPsavelog
          $ppp->PPPsavelog(FILE);

     Save log to file of filepath FILE.  Operation can take a minute or
     two if the log is big, and might freeze up your computer while
     working.  Be patient.

VERSION NOTES
=============

v.1.2 January 3, 1998
     General cleanup.

v.1.1 October 13, 1997
     Took some code and threw it in a module.

v.1.0 May 4, 1997
     Took some code and threw it in a module.

SEE ALSO
========

Open Transport Home Page
     http://tuvix.apple.com/dev/opentransport

AUTHOR
======

   Chris Nandor `<pudge@pobox.com>' http://pudge.net/

   Copyright (c) 1998 Chris Nandor.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.  Please see the Perl Artistic License.

VERSION
=======

   Version 1.20 (03 January 1998)

Unixish-compatability in file specifications
********************************************

NAME
====

   Mac::FileSpec::Unixish - Unixish-compatability in file specifications

SYNOPSIS
========

     use Mac::FileSpec::Unixish; # exports 'unixify' and 'nativize'

     @input = map( unixify($_), @ARGV);
     foreach $item (@input) {
       my $_native_item = nativize($item);
       next unless
                $item =~ m<([^/]+)$>s # assumes / is the path separator
                and -f $_native_item;
       printf("File %s is %d bytes long...\n", $1, -s _ );
       open(IN, "<$_native_item")
         || die "Can't open $_native_item : $!\n";
       print "First line: ", scalar(<IN>);
       close(IN);
     }

DESCRIPTION
===========

   Mac::FileSpec::Unixish provides two functions, `nativize' and `unixify'
(both of which are exported by default), that will allow you to denote and
manipulate pathspecs in Unixish style, and let you convert these pathspecs
to and from the native OS's format for conveying such things.  It
currently assumes that if you are not running under MacOS (as reported in
$^O), you must be on a Unix box.  If you want better, I suggest using
File::Spec.  (In essence, I wrote Mac::FileSpec::Unixish as a cheap hack
to get around using File::Spec.)

   Using this library, you can, in your code, refer to files using a
Unixish notation, a la:

     $foo = "../analyses/ziz.txt";
     open(OUT, '>' . nativize($foo) ) || die "Couldn't open $foo \: $!";

   Under Unix, `nativize($foo)' will be simply "../analyses/ziz.txt"
(`nativize' and `unixify' are nearly no-ops under Unixes); but under MacOS
it will be "::analyses:ziz.txt".

   Incidentally, `nativize(unixify($item))' is always eq $item, for all
(defined, non-undef) values of $item, regardless of whether or not this is
performed under MacOS.  In other words, this:

     @items = map(unixify($_), @ARGV);
     foreach $one (@items) {
       print "$one => ", -s nativize($one), " bytes\n";
       my $one_copy = $one;
       $one_copy =~ s/[^/]+$//s;
       print " in the directory $one_copy";
     }

   will work equally well under MacOS as under Unix, regardless of the
fact that items in @ARGV will be in "foo:bar:baz" format if run under
MacOS, and "/foo/bar/baz" format if run under Unix.

   This portability is the entire point of this library.

   (This code will work even if run under MacOS and if @ARGV contains a
pathspec like "Sean:reports:by week:5/5/98".  `unixify' encodes those
slashes (as "\e2f", if you're curious) so that they won't be misunderstood
as path separators in the Unixish representation - see "GUTS", below, for
the gory details.)

   This library also provides (but does not by default export) a function
Mac::FileSpec::Unixish::under_macos(), which returns true if you're
running under MacOS, and false otherwise.  You can use that in cases like:

     my $home =
       Mac::FileSpec::Unixish::under_macos() ?  '/Sean/' : '~/' ;

PURPOSE
-------

   This library exists so that a careful programmer who knows what
filespecs are legal and meaningful both under Mac and under Unix, can
write code that manipulates files and filenawes, and have this code work
equally well under MacOS and under Unix.

   That's all this library is for, and that's all it does.

   This library doesn't overload anything, so *don't* go thinking that you
can go

     open(OUT, '>../foo/bar.txt");

   under MacOS.

   Proper use of this library means that every time you pass a file
specification to any file operation (from chdir to -s to opendir), you
should pass the Unixish designation thru `nativize' - and every time you
get a file spec from the OS (thru `@ARGV' or
`StandardFile::GetFolder("Select a folder")' or whatever), that you pass
it thru `unixify' to get the Unixish representation.

   `nativize' and `unixify' are the only two functions this module exports.

   This library doesn't try to interpret Unixish pathspecs with any
semantics other than the above-described - to wit, "~"s in filespecs (as
in `~/.plan' or `~luser/.plan') aren't expanded, since there is no
equivalent meaning under MacOS.

   And if you say "/tmp/", you *will* get "tmp:" under MacOS - and this is
probably not what you want.

   This (coupled with the fact that MacOS has nothing like "/", save as a
notational (or notional) base for the mounted volumes) almost definitely
means that *you don't want to use any absolute pathspecs like "/tmp/" or
"/usr/home/luser" or "/Sean/System Folder", or pathspecs based on ~ or
~luser*.  In other words, your pathspecs should either come from outside
the program (as from %ENV, @ARGV, or things you devise based on them), or
should be relative.

   You have been warned!

GUTS
----

   Here are some of the icky details of how this module works.

   "Unixish" path specification means pathspecs expressed with the
meanings that Unix assigns to '/', '.', and '..' - with the additional bit
of semantics that the escape character (ASCII 0x1B, a.k.a. `"\e"') and two
hex ([a-fA-F0-9]) characters after it denote the one character with that
hex code.

   In other words, it's just like URL-encoding, but with `ESC' instead of
%. I included this quoting mechanism so it would be possible to denote, in
Unixish notation, Mac filenames with "/"s in them.  Example:

     "Foovol:stuff:05/98" -> "/Foovol/stuff/05\e2f98"

   But actual hardcoding of "\e2f" is unwise, since if you have:

     open(OUT, '>' . nativize("/Foovol/stuff/05\e2f98"));

   This will Do What You Want only if you're under MacOS, but under Unix
it will instead try to write to `/Foovol/stuff/05/98'.

   As mentioned above, `nativize(unixify($item))' is always $item, for all
values of $item, and regardless of whether or not this is performed under
MacOS.

   But the inverse (i.e., whether `unixify(nativize($item))') is not
necessarily true!  In a rather dramatic case, `nativize("/")' happens to
yield "" under MacOS, for many, many reasons.  Other, more mundane cases
include the fact that "../foo" and "./../foo" and, for that matter,
".././foo" are all synonyms for the same thing, and the (notational if not
meaningful) distinction between them may be smashed - under MacOS, they'd
all end up "::foo".

A Note on Trailers
------------------

   Note that when a trailing MacOS ":" means 'directory' (e.g.,
"Sean:reports:", it is represented as a trailing '/' in the Unixish
representation, and vice versa.  When I'm writing code, I always use a
trailer (a trailing ":" or "/") when accessing a directory (as is
`opendir(FOODIR, ":foo:bar:")' or `opendir(FOODIR, "./foo/bar/")' ).  Now,
this is generally unnecessary; `opendir(FOODIR, ":foo:bar:")' and
`opendir(FOODIR, ":foo:bar:")' do the same thing, just as `opendir(FOODIR,
"foo/bar/")' and `opendir(FOODIR, "foo/bar")' do the same thing on
(absolutely all?) Unix boxes.

   However, when accessing the root drive of a MacOS volume, the "root"
directory of a volume, like "foo", you should use the trailer -
`opendir(FOODIR, "foo:")', not `opendir(FOODIR, "foo")'.

   It's odd to note that MacOS seems inconsistent about using the trailer.
If you drop the Finder icon for the volume "foo" onto a droplet, it'll
see "foo:" in @ARGV - with the trailer.  But if you drop the Finder icon
for the directory "foo:bar" (or any other non-volume-root directory I've
tested this on) onto a droplet, it'll see "foo:bar" in @ARGV - no trailer.

COPYRIGHT
=========

   Copyright 1998-2000, Sean M. Burke `sburke@cpan.org', all rights
reserved.

   You may use and redistribute this library under the same terms as Perl
itself.

AUTHOR
======

   Sean M. Burke `sburke@cpan.org'

Control Mac apps with Apple event terminology
*********************************************

NAME
====

   Mac::Glue - Control Mac apps with Apple event terminology

SYNOPSIS
========

     use Mac::Glue;
     my $glue = Mac::Glue->new('Finder');
     $glue->open( $glue->prop('System Folder') );
     # see rest of docs for lots more info

DESCRIPTION
===========

   You should have the latest cpan-mac distribution:

     http://sourceforge.net/projects/cpan-mac/

   For more information, support, CVS, etc.:

     http://sourceforge.net/projects/mac-glue/

   Mac OS apps speak to each other with a *lingua franca* called *Apple
events*.  The most common way to do Apple events (aside from doaing them
in a precompiled application with C, Pascal, etc.) is with AppleScript.
Other languages can do Apple events too, like Frontier and even Python.
But we like Perl.

   MacPerl has for a few years had an interface to Apple events, with the
Mac::AppleEvents module, which is the basis for everything we'll do here.
Mac::AppleEvents::Simple was made to simplify the process of doing Apple
events in MacPerl, but even that can be too much trouble to use.  One has
to find out the class and event IDs, find out the keywords and data types
for each parameter, etc.

   So the vision was born for a framework that wouldn't take much
significant work.  An application's AETE resource would provide the names
to match to the cryptic four-character codes we had been using.  Compare.

Raw Mac::AppleEvents method
          use Mac::AppleEvents;
          $evt = AEBuildAppleEvent('aevt', 'odoc', typeApplSignature, 'MACS',
          	kAutoGenerateReturnID, kAnyTransactionID,
          	"'----': obj{want:type(prop), from:'null'()," .
          	"form:prop, seld:type(macs)}"
          ) or die $^E;
          $rep = AESend($evt, kAEWaitReply) or die $^E;
          AEDisposeDesc($evt);
          AEDisposeDesc($rep);

Easier Mac::AppleEvents::Simple method
          use Mac::AppleEvents::Simple;
          do_event(qw(aevt odoc MACS),
          	"'----': obj{want:type(prop), from:'null'()," .
          	"form:prop, seld:type(macs)}"
          );

Cool Mac::Glue method
          use Mac::Glue;
          my $glue = Mac::Glue->new('Finder');
          $glue->open( $glue->prop('System Folder') );

   The latter is much simpler to understand, to read, to write.  It
leverages the user's understanding of AppleScript.  And it is just more
natural.

   There are downsides.  Mac::Glue is less powerful than the
Mac::AppleEvents raw interfaces, because it offers less flexibility in how
events are called.  It is also slower to start a script, because the glue
structures need to be loaded in.  However, once a script has started, a
difference in speed from the raw interfaces should be minimal (though not
a lot of testing has been done on that).  With the code above, on a
PowerBook G3/292, running Mac OS 8.6:

     Benchmark: timing 100 iterations of glue, glue2, raw, simple...
           glue: 10 secs ( 9.98 usr  0.00 sys =  9.98 cpu)
          glue2:  8 secs ( 8.35 usr  0.00 sys =  8.35 cpu)
            raw:  8 secs ( 7.88 usr  0.00 sys =  7.88 cpu)
         simple:  7 secs ( 7.50 usr  0.00 sys =  7.50 cpu)

   The "glue2" entry is the same as "glue" entry, but it creates a glue
object only once instead of each time through, cutting down on the
overhead.  It appears that Mac::Glue is a bit slower than the other
methods, but not substantially, and it is cooler and easier.  The one
place where performance is the biggest problem is on initial execution of
the program, but once it starts it is plenty fast.  We'll work to cut down
that start time, too.

   So, now that you are convinced this is cool, let's continue.

Creating a Glue
---------------

   In order to script an application with Mac::Glue, a glue must be created
first.  For that, the application is dropped on the `gluemac' droplet.  A
distribution called Mac::AETE, created by David Schooley, is used to parse
an application's AETE resource, and the glue is written out to a file
using Storable, DB_File, and MLDBM.  Glues are saved in $ENV{MACGLUEDIR}
(which is defined when Mac::Glue is used if it is not defined already).
By default, glues are stored in `:site_perl:Mac:Glue:glues:'.

   All glues have access to the global scripting additions and dialect
information.  Glues for these must be created as well, and are created
with the `gluescriptadds' and `gluedialect' programs, which are similar to
the `gluemac' program.  They are saved in "$ENV{MACGLUEDIR}additions:" and
"$ENV{MACGLUEDIR}dialects:".

   Along with the glue file is a POD file containing documentation for the
glue, listing all the events (with parameters), classes (with properties),
and enumerators, and descriptions of each.

Using a Glue
------------

   The first thing you do is call the module.

     use Mac::Glue;

   Then you create an object for your app by passing the new function the
name of the glue (you may include or omit underscores in the name if you
like).

     my $glue = Mac::Glue->new('My App');  # or My_App

   You can also pass in additional parameters for the type of target to
use.  For PPC ports, you can do this:

     my $glue = Mac::Glue->new('My App', ppc => 'My App Name',
     	'Server Name', 'Zone');

   You may also specify a process serial number:

     my $glue = Mac::Glue->new('My App', psn => $psn);

   Note that `$psn' should be a regular long integer, and will be packed
into a double long behind the scenes.  If this confuses you, don't worry
about it; the values returned from the Mac::Processes module are good to
pass back in as `$psn'.

   You can also pass a path to an application:

     my $glue = Mac::Glue->new('My App', path => $path_to_file);

   New for Mac OS 9, you can send events over TCP/IP:

     my $glue = Mac::Glue->new('My App', eppc => 'My App Name',
     	'some.machine.com');

   Once you have your glue set up, you start calling events, as they are
documented in the POD file for the glue.  The events can be called
case-insensitively, with the exception of those that match the names of
the special methods (see `"Special parameters and methods"' in this node).
In that case, since the special methods are in all caps, the event
methods can be called case-insensitively except for all caps.  e.g., for
an event named reply, it could be called with:

     $glue->Reply;
     $glue->reply;
     $glue->RePLY;

   However, it could not be called with `$glue->REPLY', since that is
reserved.

   All applications respond to events differently.  Something that works
for one application might not work for another, so don't use any of these
examples as a way you should script a specific application.  They are just
hyopthetical examples, for the most part.

   Events sometimes accept parameters, sometimes they don't.  The primary
parameter of most events is a special parameter called the *direct object*
parameter.  In your event call, pass the data for that parameter first:

     $glue->open($file);

   Other parameters must be named and must be provided as key-value pairs,
with the key as the name of the parameter, and the value as the
parameter's data:

     $glue->open($file, using => $myapp);

   Note that the direct object parameter is the only parameter that doesn't
need a name in front of it, and must come first in the list if it is
supplied at all.

   Mac::Glue will attempt to coerce passed data into the expected type.
For example, if open expects an alias, the file specification in $file
will be turned into an alias before being added to the event.

   You can override this behavior with the `param_type' function.  If open
expects an alias (`typeAlias'), but you want to pass text, you can do:

     $glue->open( param_type($path, typeChar) );

   Each datum can be a simple scalar as above, an AEDesc object, an
Mac::AEObjDesc object (returned by `obj', `prop', and event methods), an
Mac::AEEnum object (returned by the enum function), or an array or hash
reference, corresponding to AE lists and records.  In this example, we
nest them, with an arrayref as one of the values in the hashref, so the AE
list is a datum for one of the keys in the AE record:

     $glue->make(new => 'window', with_properties =>
     	{name => "New Window", position => [100, 200]});

   The words "name" and "position" will be changed into the proper
corresponding AE IDs.  And on return, record keys will be changed back
from the AE IDs into the English words.

   Events return direct object parameters, turned into suitable data for
use in the program.  Aliases are resolved into file specifications, AE
records and lists are turned into Perl hashes and arrays (recursively, for
nested lists), etc.

     my @urls = $sherlock->search_internet('AltaVista',
     	'for' => 'Mac::Glue');

   AE objects (which will be discussed later) are returned as
`Mac::AEObjDesc' objects, so they may be used again by being passed back
to another event.

     my $window_object = $glue->get( window => 1 );
     $glue->save($window_object);

   This allows AppleScript-like loops:

     my @selection = $glue->get( $glue->prop(selection => of => window) );
     my @owners;
     for my $item (@selection) {
     	push @owners, $glue->get( $glue->obj(cell => 'Owners' => $item) );
     }

   Some objects may allow an easy way to get a human-readable form, with
the `as' parameter:

     my $item = $glue->get( file => 1, as => 'string' );

   Errors are returned in the special variable $^E, which should be
checked immediately after an event call.

     $glue->close(window => 1);
     if ($^E) {
     	warn "Couldn't close window: $^E\n";
     }

   Or, if a value is expected and none is returned:

     my $file = $glue->choose_file('Select a file, please.')
     	or die "No file chosen: $^E";

   Checking $^E only works if the error returned is an error number.  If
it isn't, the actual error is available from the reply event, which can be
accessed by using the RETOBJ parameter (described below in `"Special
parameters and methods"' in this node).

   You can also handle errors with the ERRORS handlers (also described
below in `"Special parameters and methods"' in this node).

Creating object specifier records
---------------------------------

   This is one of the more complex parts of Apple events, and it is only
partially implemented (though full implementation is expected eventually,
and most of it is implemented now).

   Object specifier records are created by the `obj' method, and have four
components to them.

class
container
form
data
   The class and data are passed as key-value pairs, like in AE records or
parameter lists.  The form and the type of the data are determined by the
glue data or a good guess.  The container is determined by the order of
the key-value pairs: each pair is contained by the pair or object that
follows it.

     my $obj = $glue->obj(file => 'foo', folder => 'bar', disk => 'buz');

   So you have three pairs.  The key of each pair ("file", "folder",
"disk") is the class.  The value of each pair ("foo", "bar", "baz") is the
data.  Because the data are each text, the form defaults to formName, and
the data type defaults to typeChar (TEXT).  If the data is a number, then
the form would be formAbsolutePosition, and the data type would be
typeLongInteger.

   So that leaves only the container.  Each pair is contained by the pair
following it.  The disk contains the folder, the folder contains the file.
The disk has no container (its container is null).

   Easy, right?  I hope so.  That's the idea.  But let's go back to the
forms, since that is the only tough part left.

   The primary forms are types, names, unique IDs, absolute positions,
relative positions, tests, and ranges.  Normally, text data has form name
and type TEXT.  Integer data has absolute position form, and integer type.
The `obj_form' function accepts three parameters, which allows you to set
the form and data, or form, type, and data, in case you want to send data
different from how Mac::Glue would guess.

   These two are the same, since in the second case, the other is assumed:

     use Mac::Glue ':glue';

     $obj1 = $glue->obj(window =>
     	obj_form(formAbsolutePostion, typeLongInteger, 1));

     $obj2 = $glue->obj(window => 1);

   Special constants are exported that specify relative positions and
absolute positions.

     $first  = $glue->obj(file => gFirst, property => 'Desktop');
     $second = $glue->obj(file => gNext, $first);

     for ($first, $second) {
     	print $glue->get($_, as => 'string');
     }

   `of' and in are synonyms of property:

     $glue->obj(file => gFirst, property => 'Desktop');
     $glue->obj(file => gFirst, of => 'Desktop');
     $glue->obj(file => gFirst, in => 'Desktop');

   The "as" parameter above has a form of type, such as:

     obj_form(formPropertyID, typeType, 'string');

   Then "string" is turned into a four-character ID behind the scenes (in
this case, it is "TEXT").

   A special method called `prop' is for specifying properties.  These are
equivalent:

     $glue->obj(property => 'Desktop');
     $glue->prop('Desktop');

Descriptor types for object specifier records
---------------------------------------------

Property IDs
     Normally, the glue will know a property is expected and coerce
     whatever string you provide into its four-character ID.  Sometimes
     `obj_form(formPropertyID, typeType, 'property_name')' may be
     appropriate.

Name
     Just pass the data as text.  If there is some ambiguity, you may
     explicitly use `obj_form(formName, typeChar, 'string')'.

Unique IDs
     Could be anything.

Absolute position
     As discussed above, if it is an index number, you can just pass the
     number, as in `window => 1', or you can explicitly mark it with
     `window => obj_form(formAbsolutePosition, typeLongInteger, 1)'.

     For other absolutes, you may use constants, such as `window =>
     gLast'.  Choices are `gFirst', `gMiddle', `gLast', `gAny', `gAll'.

     These are just shortcuts for explicit forms like
     `obj_form(formAbsolutePosition, typeAbsoluteOrdinal, kAEAll)'.

     Note that if there is a plural form of the class name, you may use it
     to mean the same thing as "class => gAll".  These are all the same:

          $f->obj(files => of => 'System Folder');
          $f->obj(files => gAll, of => 'System Folder');
          $f->obj(file => gAll, of => 'System Folder');

Relative position
     Similar to absolute position, but an additional object must be
     specified, such as `file =' gNext, file => gMiddle>, which would
     return the file after the middle file.  Available constants are
     `gNext' and `gPrevious'.

     The explicit form is `obj_form(formRelativePosition, typeEnumerated,
     kAENext)'.

Ranges
     The range function accepts two arguments, the start and stop ranges.

          range(START, STOP)

     Each can be a number index, an absolute position constant, a string,
     or another data type passed with `obj_form'.  Here are a few ways to
     specify files in the System Folder:

          $f->obj(files => range(1, 5), of => 'System Folder');
          $f->obj(files => range(1, "System"), of => 'System Folder');
          $f->obj(files => range("Finder", "System"), of => 'System Folder');
          $f->obj(files => range(gFirst, "System"), of => 'System Folder');

Whose tests
     The `whose' function accepts either logical records or comparison
     records.

          # comparison record
          $f->obj(CLASS => whose(CLASS => VALUE, OPERATOR, VALUE));
          $f->obj(CLASS => whose(PROPERTY, OPERATOR, VALUE));

     PROPERTY and CLASS => VALUE work like prop() and obj().  The PROPERTY
     form is the same as `property => VALUE'.

     OPERATOR is contains, equals, `begins_with', `ends_with', `l_t',
     `l_e', `g_t', or `g_e'.  VALUE is the value to compare to.

          # files whose name begins with "foo"
          $f->obj(files => whose(name => begins_with => 'foo'));

          # rows whose first cell equals "bar"
          $f->obj(rows => whose(cell => 1 => equals => 'bar'));

     Then there is the logical record type, for use when more than one
     comparison record is needed.

          # logical record
          $f->obj(CLASS => whose(OPERATOR, LIST));

     OPERATOR is AND, `OR', or `NOT'.  LIST is any number of other logical
     records or comparison records, contained in anonymous arrays.  So you
     can join any number of records together:

          # words where it contains "e" and it begins with "p" and it does not end with "s"
          $aw->obj(
          	words => whose(AND =>
          		[it => contains => 'e'], [it => begins_with => 'p'],
          		[NOT => [it => ends_with => 's']]
          	), $text)

     Note how each logical record and comparison record following each
     logical operator is in an anonymous array.  Also not how the special
     word "it" refers to the object being examined.

   There's one more record type that works similarly to the above object
specifier records, but is not exactly the same thing.  It's called an
*insertion location record*, and is created like this:

     location(POSITION[, OBJECT])

   POSITION is a string, and can be one of before, after, `beginning', or
end.  `front' is a synonym for `beginning', and back and `behind' are
synonyms for after.

   OBJECT is the object to be positioned against, and will be the null
object if not supplied.

     my $aw = new Mac::Glue 'AppleWorks';
     my $text = $aw->prop(text_body => document => 1);
     $aw->activate;

     # note null object in location()
     $aw->make(new => 'document', at => location('front'));
     $aw->set($text, to => "foo bar buz baz.");

     $aw->move(
     	$aw->obj(word => 4 => $text),
     	to => location(after => $aw->obj(word => 2 => $text))
     );

Special parameters and methods
------------------------------

   Special parameters can be passed in the event which control certain
aspects of the event call's behavior.  They can be passed as parameters
(affecting only the one event), or called as methods (which affect every
call made from that object).  They are all upper case.

     $glue->REPLY(1);		# wait for reply on all events
     $glue->close(REPLY => 0);	# don't wait for this one event

REPLY
     Boolean, for whether or not to wait for a reply.  Default is to wait.

MODE
     Set other modes, such as `kAENeverInteract'.  This value is OR'd
     together with the REPLY value.  Default is `kAECanInteract |
     kAECanSwitchLayer'.

SWITCH
     Switch to the application being called.  Usually more efficient to use
     the activate event:

          $glue->activate;

PRIORITY
     Set the event priority.  Default is `kAENormalPriority'.

TIMEOUT
     Number of seconds to wait before timing out.  Default is a couple
     hundred thousand seconds or so.

RETOBJ
     Boolean, for whether or not the event call will return the direct
     object data (the default), or a Mac::AppleEvents::Simple object,
     containing references to the actual event and reply, so you can do
     more advanced things with the data if you want to.

ERRORS
     A subroutine reference that will handle any errors (that is, will be
     executed only if $^E is true) after the event is executed.  Your
     handler will be passed 6 or more arguments:

          0	The glue object
          1	The event object (same object returned by RETOBJ)
          2	The Glue's name
          3	The event's name
          4	The error message
          5	The error number
          6..n	Any arguments passed to the event in the first place

     Example:

          sub error_handler {
          	my($glue, $event, $gluename, $eventname,
          		$errs, $errn, @args) = @_;
          	my $args = join ', ', @args;
          	die "$gluename->$eventname($args) event failed:\n$errs\n";
          }

          $finder->open(
          	$finder->obj( item => 'HD' ), # nothing named HD in Finder
          	ERRORS => \&error_handler
          );

     Result:

          # Finder->open(DOBJ, Mac::AEObjDesc=HASH(0xc4c0814)) event failed:
          No such object (OS error -1728)

Editing a Glue
--------------

   There is an included droplet, `glueedit', for editing glues.  Drop a
created glue on the droplet, and it will make a text file on the Desktop.
Edit it, and then drop the text file back on the droplet.  Be careful;
this obviously can be dangerous.  If you break something, you can use
`gluemac' to recreate the original glue, of course.

   Why would you edit a glue?  Well, sometimes AETE resources are wrong.
:)

EXPORT
======

   Mac::Glue has two export sets.  `glue' exports the constants and
functions beginning with "glue" listed in `"Creating Object Specifier
Records"' in this node, as well as the functions `obj_form', enum,
location, range, and `whose'.  all exports everything from
Mac::AppleEvents and Mac::AppleEvents::Simple, including all functions and
constants.  Nothing is exported by default.

     use Mac::Glue ':glue';  # good for most things
     use Mac::Glue ':all';   # for more advanced things

TIPS
====

Hide background apps
--------------------

     use Mac::Glue;
     use Mac::Apps::Launch;
     $a = new Mac::Glue 'Acrobat Exchange';
     $a->launch;
     Hide($a->{ID});

     # now do your thing ...

Scripting Addition Maintenance
------------------------------

   If you have a lot of scripting additions, it can slow down Mac::Glue
(on startup) and take up more RAM.  Same thing goes for Mac OS in general;
each installed additions takes up more RAM and has to be loaded into the
system, taking up extra time.  So only keep installed the ones you want
installed.

   If you have a huge scripting addition and you only want to use a small
part of its functionality, you could also edit the glue and strip out
portions you don't want.  This is not recommended for those who don't know
precisely what they are doing, and the gains may be unnoticable anyway.

GOTCHAS
=======

   * MAKE SURE `site_perl' COMES FIRST IN YOUR LIBRARY PREFERENCES.  Thank
     you.  :-)

   * Do NOT send an event to the MacPerl application itself and expect a
     reply.  Instead, try `$macperlglue->REPLY(0)'.  Similarly, do not drop
     MacPerl onto `gluemac'.  Instead, you can make a copy of the MacPerl
     application, and drop that on `gluemac'.

   * You should have the latest cpan-mac distribution is installed.

   * You should delete old dialect glue files manually if running Mac OS 9.

TODO / BUGS
===========

   * Specifying other attributes (transactions, etc.)

   * Add more coercions etc. to Mac::AppleEvents::Simple (feedback wanted
     on this, let me know what I missed)

   * Add comparison operators from glues

   * "tell" objects to do events

   * New AETE flags in Mac OS 8.5, Mac OS 9?  Anything else new?  Anything
     missing in backward compatibility to 7.5?

   * System of versioning (for glues and target apps) for distribution of
     modified glues

   * MacPerl (I think) needs a new idle function for waiting for replies

   * MacPerl hangs if it waits for a reply after sending an event to itself

   * Handlers?

   * Add dynamic fetching of glues?

HISTORY
=======

v1.00, Tuesday, September 12, 2000
     Added error handling via ERRORS parameter / method.

     General cleanup, additional examples.

v0.58, Tuesday, November 16, 1999
     Change all of the classes to have `Mac::' at the beginning of them
     (except for ones that originate elsewhere, like `AEDesc', et al).

     Added `Mac::AEParamType' and `param_type'.

     If a parameter expects an AE object specifier record, and is not
     passed one, then it guesses the type and sets it to either `typeChar'
     or `typeInteger'.

     Made the conversion of keys into English names recursive with lists,
     in addition to records (i.e., lists can contain multiple records).

v0.57, Tuesday, November 2, 1999
     Added conversion of keys in returned records back into the "English"
     names.

     Records containing class parameter are coerced into descriptors of
     that class (i.e., `{name => 'foo', class => 'disk'}').

     Added support for events over TCP/IP (Mac OS 9 required).

     Note: if Keychain Access is used in Mac OS 9, the login method may no
     longer be required for accessing of remote machines.

     Fixed bug in can method; also changed how can calls AUTOLOAD.

     Added code for experimental callback stuff, undocumented, subject to
     change, and probably does not even work.

     Changed `_get_name' to `_get_id', created new `_get_name'.

     Updated dialect creation code for Mac OS 9 (aeut is now stored in the
     `AppleScript' extension instead of a dialect file, but for Mac::Glue
     is still stored in the `dialects' folder.  Instead of being called
     English, it will likely be called `AppleScript'.  You should delete
     (or archive) old dialect glues manually.

v0.56, Friday, September 10, 1999
     If plural class is used (i.e., files for file), and the following
     value is not an `AE*' object, then it will become "every class".
     (Jeff Lowrey)

     Added more documentation about using `AEObjDesc' objects.  (Jeff
     Lowrey)

v0.55, Thursday, September 2, 1999
     Added extra arguments to new to accept alternate targets.  PPC ports,
     PSNs, and paths are explicitly accepted now.  (Paths are first
     launched, then the PSN is found ... aliases won't work properly as
     paths.)

     Added login class method to tell MacPerl to try logging in with
     specified username and password.  Requires `Login As' OSAX from the
     `GTQ Scripting Library'.

v0.51, Wednesday, September 1, 1999
     Changed ordering of search in `_find_event'.

     Fixed doc problems in Mac::AETE::Format::Glue: inheritance classes
     are named, and optional parameters are properly denoted.

v0.50, 12 July 1999
     Added g* constants in addition to glue* constants.  Use whichever you
     like, but I will use g* for everything.  If you don't want the g*
     constants, because they conflict with something, use the `:long' and
     `:longall' import tags instead of `:glue' and :all.

     Gone to beta!  Woo!

v0.31, 22 June 1999
     Fixed bug that only found class names instead of class and property
     names in creation of object specifier records.

     Fixed bug which changed directories on initialization, and didn't
     change it back.

     Allow case-insensitive parameter names.

v0.30, 16 June 1999
     Changed function names: `glueInsertion' is now location, `glueRange'
     is now range.

     Added `whose' function.

     Added can method which correctly finds available events.

     Made special parameters, formerly with leading underscore and
     lowercase, to all uppercase with no underscore (i.e., `_retobj' is
     now RETOBJ).

     Added `of' and in as synonyms for property in `obj' method calls.

     Put `AEObjDesc' back in!  Will use in the future, maybe, to use
     objects as targets for events.

     Return all descriptors from `obj' and `prop', and all objects
     returned from events, as `AEObjDesc' objects.

     Added `glueTrue' and `glueFalse' constants.

     Tried again to suppress warnings during initial scripting additions
     and dialect creation.

     Tons of internal cleaning up.

v0.26, 07 June 1999
     Made choice of serializer for glue more intelligent: FreezeThaw
     automatically picked for CFM68K, Storable for PPC.

     Updated Mac::AppleEvents and Mac::Memory, fixed more bugs and added
     constants.  Fixed bug in AutoSplit.

     Added `glueInsertion', `glueRange', and `glueNull'.

     Completely removed `AEObjDesc' package, which existed to support
     destruction of descriptors.  Use global hash now to keep track of
     descriptors to destroy (`Mac::AppleEvents::Simple' in this node).  So
     all descriptors returned from `obj' and `prop' and others are
     `AEDesc' objects.

     Changed ordering of items in creating object specifiers in `_do_obj'
     to match AppleScript, so comparing to Capture AE output would be
     easier.

     Put `%AE_PUT' back in Mac::Glue and left `%AE_GET' in
     Mac::AppleEvents::Simple.

     Switched `DOBJ, {PARAM1 => DATA1}' to `DOBJ, PARAM1 => DATA1' in
     event calls.

     Always default to wait for reply and no timeout if unspecified by
     user.

     Return useful errors in $^E.

     Accept and return nested arrays/lists and hashes/records.

     Call events and pass classes / properties case-insensitively.

     Other miscellaneous changes.  Some cleaning up.

v0.25, 30 May 1999
     Add serializer option.

     Updates to Mac::Memory and Mac::AppleEvents and
     Mac::AppleEvents::Simple.

     Added constants for absolute and relative positions.

     Added enum.

     Put o and p back as `obj' and `prop'.

     Other miscellaneous changes.  Lots of cleaning up.

v0.20, 22 May 1999
     Complete rewrite.  Too many changes to bother mentioning, because I
     am lazy.

v0.09, 13 October 1998
     Added ability to use properties.  These are called with the p method:

          $obj->get($obj->p('label_index', item=>'HD'));

     which is equivalent to:

          $obj->get($obj->o(property=>'label_index', item=>'HD'));

v0.08, 10 October 1998
     Unreleased.

     Significant cleanup of module, in large part unfinished changes from
     last version.

     No longer doing error checking for whether lists are allowed or
     objects are allowed, because these are sometimes wrong or
     undetectable.  Also, will not raise exception on a missing required
     parameter, but will warn if -w is on.

     `obj_form' is exported from the glue modules, and all of the functions
     and constant from `Mac::AppleEvents' can be imported from a glue
     module with the :all tag:

          use Mac::Glue::SomeApp qw(:all);

v0.07, 30 September 1998
     More documentation and bugfixes.  Having serious problems with
     `AEObjDesc::DESTROY'.

v0.06, 29 September 1998
     Whole bunches of changes.  Note that glues made under 0.05 no longer
     work.

AUTHOR
======

   Chris Nandor <pudge@pobox.com>, http://pudge.net/

   Copyright (c) 1998-2000 Chris Nandor.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the terms of the Artistic License, distributed with Perl.

THANKS
======

   Matthias Neeracher <neeri@iis.ee.ethz.ch>, David Schooley
<dcschooley@mediaone.net>, Graham Barr <gbarr@pobox.com>, John W Baxter
<jwblist@olympus.net>, Marion Delgado <dhp@efn.org>, Eric Dobbs
<dobbs@visionlink.org>, Josh Gemmell <joshg@ola.bc.ca>, Nathaniel Irons
<irons@espresso.hampshire.edu>, Dave Johnson <dave_johnson@ieee.org>, Bart
Lateur <bart.mediamind@ping.be>, Jefferson R. Lowrey <lowrey@mailbag.com>,
Mat Marcus <mmarcus@adobe.com>, Larry Moore <ljmoore@freespace.net>,
Ricardo Muggli <rtmuggli@carlsoncraft.com>, Vincent Nonnenmacher
<dpi@pobox.oleane.com>, Henry Penninkilampi <htp@metropolis.net.au>, Peter
Prymmer <pvhp@best.com>, Ramesh R. <sram0mp@radon.comm.mot.com>, Axel Rose
<rose@sj.com>, Stephan Somogyi <somogyi@gyroscope.net>, Kevin Walker
<kwalker@xmission.com>, Matthew Wickline <mattheww@wickline.org>.

   (If I left your name out, please remind me.)

SEE ALSO
========

   Mac::AppleEvents, Mac::AppleEvents::Simple, macperlcat, Inside
Macintosh: Interapplication Communication.

     http://sourceforge.net/projects/mac-glue/

VERSION
=======

   v1.00, Tuesday, September 12, 2000

Decodes Macbinary files
***********************

NAME
====

   Mac::Macbinary - Decodes Macbinary files

SYNOPSIS
========

     use Mac::Macbinary;

     $mb = Mac::Macbinary->new(\*FH);	# filehandle
     $mb = Mac::Macbinary->new($fh);	# IO::* instance
     $mb = Mac::Macbinary->new("/path/to/file");

     # do validation
     eval {
         $mb = Mac::Macbinary->new("/path/to/file", { validate => 1 });
     };

     $header = $mb->header;		# Mac::Macbinary::Header instance
     $name = $header->name;

DESCRIPTION
===========

   This module provides an object-oriented way to extract various kinds of
information from Macintosh Macbinary files.

METHODS
=======

   Following methods are available.

Class method
------------

new( THINGY, [ \%attr ] )
     Constructor of Mac::Macbinary. Accepts filhandle GLOB reference,
     FileHandle instance, IO::* instance, or whatever objects that can do
     read methods.

     If the argument belongs none of those above, new() treats it as a
     path to file. Any of following examples are valid constructors.

          open FH, "path/to/file";
          $mb = Mac::Macbinary->new(\*FH);

          $fh = FileHandle->new("path/to/file");
          $mb = Mac::Macbinary->new($fh);

          $io = IO::File->new("path/to/file");
          $mb = Mac::Macbinary->new($io);

          $mb = Mac::Macbinary->new("path/to/file");

     new() throws an exception "Can't read blahblah" if the given argument
     to the constructor is neither a valid filehandle nor an existing file.

     The optional "\%attr" parameter can be used for validation of file
     format.  You can check and see if a file is really a Macbinary or not
     by setting "validate" attribute to 1.

          $fh = FileHandle->new("path/to/file");
          eval {
              $mb = Mac::Macbinary->new(FileHandle->new($fh), {
                   validate => 1,
              });
          };
          if ($@) {
              warn "file is not a Macbinary.";
          }

Instance Method
---------------

data
     returns the data range of original file.

header
     returns the header object (instance of Mac::Macbinary::Header).

   Following accessors are available via Mac::Macbinary::Header instance.

name, type, creator, flags, location, dflen, rflen, cdate, mdate
     returns the original entry in the header of Macbinary file.  Below is
     a structure of the info file, taken from MacBin.C

          char zero1;
          char nlen;
          char name[63];
          char type[4];           65      0101
          char creator[4];        69
          char flags;             73
          char zero2;             74      0112
          char location[6];       80
          char protected;         81      0121
          char zero3;             82      0122
          char dflen[4];
          char rflen[4];
          char cdate[4];
          char mdate[4];

EXAMPLE
=======

   Some versions of MSIE for Macintosh sends their local files as
Macbinary format via forms. You can decode them in a following way:

     use CGI;
     use Mac::Macbinary;

     $q = new CGI;
     $filename = $q->param('uploaded_file');
     $type = $q->uploadInfo($filename)->{'Content-Type'};

     if ($type eq 'application/x-macbinary') {
         $mb = Mac::Macbinary->new($q->upload('uploaded_file'));
         # now, you can get data via $mb->data;
     }

COPYRIGHT
=========

   Copyright 2000 Tatsuhiko Miyagawa <miyagawa@bulknews.net>

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

ACKNOWLEDGEMENT
===============

   Macbinary.pm is originally written by Dan Kogai <dankogai@dan.co.jp>.

   There are also `Mac::Conversions' and `Convert::BinHex', working kind
similar to this module. (However, `Mac::Conversions' works only on
MacPerl, and `Convert::BinHex' is now deprecated.) Many thanks to Paul J.
Schinder and Eryq, authors of those ones.

   Macbinary validation is almost a replication of *is_macbinary* in
Mac::Conversions.

SEE ALSO
========

   perl(1), `Mac::Conversions' in this node, see Convert/BinHex.

Simple access to Mac::OSA
*************************

NAME
====

   Mac::OSA::Simple - Simple access to Mac::OSA

SYNOPSIS
========

     #!perl -wl
     use Mac::OSA::Simple;
     osa_script('LAND', <<'EOS');
       dialog.getInt ("Duration?",@examples.duration);
       dialog.getInt ("Amplitude?",@examples.amplitude);
       dialog.getInt ("Frequency?",@examples.frequency);
       speaker.sound (examples.duration, examples.amplitude,
           examples.frequency)
     EOS

     print frontier('clock.now()');

     applescript('beep 3');

DESCRIPTION
===========

     **MAJOR CHANGE**
     Scripting component in osa_script and compile_osa_script
     is now the first parameter, not the second.
     Now the script text is second.

   You can access scripting components via the tied hash
`%ScriptComponents' which is automatically exported.  Components are only
opened if they have not been already, and are closed when the program
exits.  It is normally not necessary to use this hash, as it is accessed
internally when needed.

   Also usually not necessary, but possibly useful, are all the functions
and constants from Mac::OSA, available with the EXPORT_TAG "all".

Functions
---------

   The following functions are automatically exported.

osa_script(SCRIPTCOMPONENT, SCRIPTTEXT)
     Compiles and executes SCRIPTTEXT, using four-char SCRIPTCOMPONENT.
     Component is opened and closed behind the scenes, and SCRIPTTEXT is
     compiled, executed, and disposed of behind the scenes.  If the script
     returns data, the function returns the data, else it returns 1 or
     undef on failure.

applescript(SCRIPTTEXT)
frontier(SCRIPTTEXT)
     Same thing as `osa_script' with SCRIPTCOMPONENT already set ('ascr'
     for AppleScript, 'LAND' for Frontier).

compile_osa_script(SCRIPTCOMPONENT, SCRIPTTEXT)
     Compiles script as `osa_script' above, but does not execute it.
     Returns Mac::OSA::Simple object.  See `"Methods"' in this node for
     more information.

compile_applescript(SCRIPTTEXT)
compile_frontier(SCRIPTTEXT)
     Same thing as `compile_osa_script' with SCRIPTCOMPONENT already set.

load_osa_script(HANDLE)
load_osa_script(FILE, FROMFILE [, RESOURCEID])
     In the first form, load compiled OSA script using data in HANDLE
     (same data as returned by compiled method; see `Mac::Memory' in this
     node).  In the second form, with FROMFILE true, gets script from FILE
     using RESOURCEID (which is 128 by default).  Returns Mac::OSA::Simple
     object.

          **NOTE**
          This function uses FSpOpenResFile, which has a bug in it
          that causes it to treat $ENV{MACPERL} as the current
          directory.  For safety, always pass FILE as an absolute
          path, for now.

     Example:

          use Mac::OSA::Simple qw(:all);
          use Mac::Resources;
          $res = FSpOpenResFile($file, 0) or die $^E;
          $scpt = Get1Resource(kOSAScriptResourceType, 128)
              or die $^E;
          $osa = load_osa_script($scpt);
          $osa->execute;
          CloseResFile($res);

     Same thing:

          use Mac::OSA::Simple;
          $osa = load_osa_script($file, 1);
          $osa->execute;

     Another example:

          use Mac::OSA::Simple;
          $osa1 = compile_applescript('return "foo"');
          print $osa1->execute;

          # make copy of script in $osa1 and execute it
          $osa2 = load_osa_script($osa1->compiled);
          print $osa2->execute;

     See `"Methods"' in this node for more information.

Methods
-------

   This section describes methods for use on objects returned by
`compile_osa_script' and its related functions and `load_osa_script'.

compiled
     Returns a HANDLE containing the raw compiled form of the script (see
     `Mac::Memory' in this node).

dispose
     Disposes of OSA script.  Done automatically if not called explicitly.

execute
     Executes script.  Can be executed more than once.

save(FILE [, ID [, NAME]])
     Saves script in FILE with ID and NAME.  ID defaults to 128, NAME
     defaults to "MacPerl Script".  DANGEROUS!  Will overwrite existing
     resource!

          **NOTE**
          This function uses FSpOpenResFile, which has a bug in it
          that causes it to treat $ENV{MACPERL} as the current
          directory.  For safety, always pass FILE as an absolute
          path, for now.

BUGS
====

   `load_osa_script' function and save method require absolute paths.
Problem in Mac::Resources itself.

TODO
====

   Work on error handling.  We don't want to die when a toolbox function
fails.  We'd rather return undef and have the user check $^E.

   Should `frontier' and/or `osa_script('LAND', $script)' launch Frontier
if it is not running?

   Add `run_osa_script', which could take script data in a Handle or a
path to a script (as with `load_osa_script'.

   Should save have optional parameter for overwriting resource?

   Should `run_osa_script' and execute take arguments?  If so, how?

HISTORY
=======

v0.51, Saturday, March 20, 1999
     Fixed silly bug in return from execute, where multiline return values
     would not return (added /s so . would match \n) (John Moreno
     <phenix@interpath.com>).

v0.50, Friday, March 12, 1999
     Changed around the argument order for `osa_script' and
     `compile_osa_script'.

     Added `load_osa_script' function.

     Added save method.

     Added lots of tests.

v0.10, Tuesday, March 9, 1999
     Added lots of stuff to get compiled script data.

v0.02, May 19, 1998
     Here goes ...

AUTHOR
======

   Chris Nandor `<pudge@pobox.com>' http://pudge.net/

   Copyright (c) 1999 Chris Nandor.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.  Please see the Perl Artistic License.

SEE ALSO
========

   Mac::OSA, Mac::AppleEvents, Mac::AppleEvents::Simple, macperlcat.

VERSION
=======

   Version 0.51 (Saturday, March 20, 1999)

add items to the MacOS Recent Documents menu
********************************************

NAME
====

   Mac::RecentDocuments - add items to the MacOS Recent Documents menu

SYNOPSIS
========

     use Mac::RecentDocuments qw(:ARGV);
      # Adds all files in @ARGV to Recent Documents folder,
      #  and imports recent_documents and recent_document

     foreach my $in (@ARGV) {
       open(IN, "<$in") or die "Can't read-open $in: $!";
       my $out = $in . '2';
       die "But $out already exists!" if -e $out;
       open(OUT, ">$out") or die "Can't write-open $out: $!";

       ...do whatever to $out...

       recent_documents($out); # add to Recent Documents folder
     }

DESCRIPTION
===========

   This module provides a function that adds specified files to the MacOS
Apple Menu "Recent Documents" folder.  You can use this module under
non-MacOS environments, and it will compile, but it will do nothing.

FUNCTIONS
=========

recent_documents( ...files... )
     This adds the given items to the Recent Documents folder, for each
     item that is a pathspec to an existing file. Relative (`":bar.txt"')
     as well as absolute filespecs (`"Lame Drive:stuff:bar.txt"') should
     work equally well.

     The number of aliases that this creates in the Recent Documents folder
     is returned.

     Under non-MacOS environments, this function does nothing at all, and
     always returns 0.

recent_document( file )
     This is just an alias to `recent_documents'

Mac::RecentDocuments::OK()
     This function returns true iff you are running under MacOS, and if, at
     compile-time, Mac::RecentDocuments was able to find your Recent
     Documents folder, and verified that it was a writeable directory.  In
     all other cases, this returns false.

IMPORTING, AND :ARGV
====================

   If you say

     use Mac::RecentDocuments;

   then this will by default import the functions `recent_documents' and
`recent_document'.

   This is equivalent to:

     use Mac::RecentDocuments qw(:all);

   If you want to use the module but import no functions, you can say:

     use Mac::RecentDocuments ();

   or

     use Mac::RecentDocuments qw(:none);

   This module also defines a use-option `":ARGV"' that causes
Mac::RecentDocuments to also call `recent_documents(@ARGV)', at compile
time.  This should be rather useful with MacPerl droplets.

   That is, this:

     use Mac::RecentDocuments qw(:ARGV);

   is basically equivalent to:

     BEGIN {
       use Mac::RecentDocuments;
       Mac::RecentDocuments(@ARGV);
     }

   (The only difference is that if several instances of `use
Mac::RecentDocuments qw(:ARGV)' are seen in a given session,
`Mac::RecentDocuments(@ARGV)' is called only the first time.)

   When "qw(:ARGV)" is the whole option list, it is interpreted as
equivalent to "qw(:ARGV :all)".  If you want the `:ARGV' option without
importing anything, explicitly specify the `":none"' option:

     use Mac::RecentDocuments qw(:ARGV :none);

CAVEATS
=======

   The module is called Mac::RecentDocuments (no underscore), but the
function is called `recent_documents' (with underscore).

   The module is called Mac::RecentDocuments, not Mac::RecentFiles.

THANKS
======

   Thanks to Chris Nandor for the `kRecentDocumentsFolderType' tips.

COPYRIGHT
=========

   Copyright (c) 2000 Sean M. Burke. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Sean M. Burke `sburke@cpan.org'

Parse mail addresses
********************

NAME
====

   Mail::Address - Parse mail addresses

SYNOPSIS
========

     use Mail::Address;

     my @addrs = Mail::Address->parse($line);

     foreach $addr (@addrs) {
     	print $addr->format,"\n";
     }

DESCRIPTION
===========

   `Mail::Address' extracts and manipulates RFC822 compilant email
addresses. As well as being able to create `Mail::Address' objects in the
normal manner, `Mail::Address' can extract addresses from the To and Cc
lines found in an email message.

CONSTRUCTORS
============

new( PHRASE,  ADDRESS, [ COMMENT ])
          Mail::Address->new("Perl5 Porters", "perl5-porters@africa.nicoh.com");

     Create a new `Mail::Address' object which represents an address with
     the elements given. In a message these 3 elements would be seen like:

          PHRASE <ADDRESS> (COMMENT)
          ADDRESS (COMMENT)

parse( LINE )
          Mail::Address->parse($line);

     Parse the given line a return a list of extracted `Mail::Address'
     objects.  The line would normally be one taken from a To,Cc or Bcc
     line in a message

METHODS
=======

phrase ()
     Return the phrase part of the object.

address ()
     Return the address part of the object.

comment ()
     Return the comment part of the object

format ()
     Return a string representing the address in a suitable form to be
     placed on a To,Cc or Bcc line of a message

name ()
     Using the information contained within the object attempt to identify
     what the person or groups name is

host ()
     Return the address excluding the user id and '@'

user ()
     Return the address excluding the '@' and the mail domain

path ()
     Unimplemented yet but should return the UUCP path for the message

canon ()
     Unimplemented yet but should return the UUCP canon for the message

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

COPYRIGHT
=========

   Copyright (c) 1995-8 Graham Barr. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Maniulates mail alias files of various formats. Works on files directly or loads files into memory and works on the buffer.
***************************************************************************************************************************

NAME
====

   Mail::Alias - Maniulates mail alias files of various formats. Works on
files directly or loads files into memory and works on the buffer.

SYNOPSIS
========

     use Mail::Alias;

DESCRIPTION
===========

   `Mail::Alias' can read various formats of mail alias. Once an object
has been created it can be used to expand aliases and output in another
format.

CONSTRUCTOR
===========

new () Alias objects can be created in two ways;  With a format specified- Mail::Alias::Sendmail->new([filename])  Without a format specified- Mail::Alias->new([filename]}. Format defaults to   SENDMAIL In either case, the filename is optional and, if supplied, it will be read in  when the object is created. Available formats are Sendmail, Ucbmail, and   Binmail.
METHODS
=======

*read ()* Reads an alias file of the specified format into memory. Comments or blank  lines are lost upon reading. Due to storage in a hash, ordering of the alias  lines is also lost.
*write ()* The current set of aliases contained in the object memory are written to a  file using the current format. If a filehandle is passed, data is written to the already opened file. If a  filename is passed, it is opened and the memory is written to the file.  Note: if passing a filename, include the mode (i.e. to write to a file named  aliases pass >aliases). Before writing, the alias lines are sorted  alphabetically.
*format ()* Set the current alias file format.
*exists ()* Indicates the presence of the passed alias within the object (if using memory  access), or the current aliases file (if using direct file access). For  direct file access, the return value is the address string for the alias.   =item *expand ()* Expands the passed alias into a list of addresses. Expansion properly handles  :include: files, recursion, and continuation lines.Only works when memory   access is being used. If the alias is not found in the object, you get back   what you sent.
*alias_file ()* Sets or gets the name of the current alias filename for direct access.
*append () *-Sendmail only-** Adds an alias to an existing Sendmail alias file. The alias and addresses can  be passed as two separate arguments (alias, addresses) or as a single line of  text (alias: addresses)
*delete () *-Sendmail only-** Deletes the entry for an alias from the current alias file.
*update () *-Sendmail only-** Replaces the address string entry for an alias in the current alias file.
*usemem ()* Sets the working mode to use memory (indirect access). Use read(), write() and  format() methods.
*usefile ()* Sets the working mode to use files (direct access). Use append() and delete()  methods.
AUTHOR
======

   Tom Zeltwanger <perl@ename.com> (CPAN author ID: ZELT)

COPYRIGHT
=========

   Copyright (c) 2000 Tom Zeltwanger. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

   Versions up to 1.06, Copyright (c) 1995-1997 Graham Barr. All rights
reserved.  This program is free software; you can distribute it and/or
modify it under the same terms as Perl itself.

Library for creating easy mail filters
**************************************

NAME
====

   Mail::Audit - Library for creating easy mail filters

SYNOPSIS
========

     use Mail::Audit; # use Mail::Audit qw(...plugins...);
     my $mail = Mail::Audit->new;
     $mail->pipe("listgate p5p") if ($mail->from =~ /perl5-porters/);
     $mail->accept("perl) if ($mail->from =~ /perl/);
     $mail->reject("We do not accept spam") if looks_like_spam($mail);
     $mail->ignore if $mail->subject =~ /boring/i;
     ...

DESCRIPTION
===========

   `procmail' is nasty. It has a tortuous and complicated recipe format,
and I don't like it. I wanted something flexible whereby I could filter my
mail using Perl tests.

   `Mail::Audit' was inspired by Tom Christiansen's `audit_mail' and
`deliverlib' programs. It allows a piece of email to be logged, examined,
accepted into a mailbox, filtered, resent elsewhere, rejected, and so on.
It's designed to allow you to easily create filter programs to stick in a
`.forward' file or similar.

CONSTRUCTOR
-----------

`new(%options)'
     The constructor reads a mail message from STDIN (or, if the data
     option is set, from an array reference) and creates a `Mail::Audit'
     object from it, to be manipulated by the following methods.

     Other options include the accept, `reject' or pipe keys, which
     specify subroutine references to override the methods with those
     names.

     You may also specify `< log =' $logfile >> to write a debugging log;
     you can set the verbosity of the log with the `loglevel' key, on a
     scale of 1 to 4. If you specify a log level without a log file,
     logging will be written to `/tmp/you-audit.log' where `you' is
     replaced by your user name. If you specify `< noexit =' 1 >>,
     `Mail::Audit' will not exit after delivering the mail, but continue
     running your filter.

METHODS
-------

`accept($where)'
     You can choose to accept the mail into a mailbox by calling the
     accept method; with no argument, this accepts to
     `/var/spool/mail/you'. The mailbox is opened append-write, then locked
     `LOCK_EX', the mail written and then the mailbox unlocked and closed.
     If Mail::Audit sees that you have a maildir style system, where
     `/var/spool/mail/you' is a directory, it'll deliver in maildir style.

     If this isn't how you want local delivery to happen, you'll need to
     override this method.

`reject($reason)'
     This rejects the email; it will be bounced back to the sender as
     undeliverable. If a reason is given, this will be included in the
     bounce.

`ignore'
     This merely ignores the email, dropping it into the bit bucket for
     eternity.

`rblcheck([$timeout])'
     Attempts to check the mail headers with the Relay Blackhole List.
     Returns false if the headers check out fine or the query times out,
     returns a reason if the mail is considered spam.

`pipe($program)'
     This opens a pipe to an external program and feeds the mail to it.

`tidy'
     Tidies up the email as per Mail/Internet,

`get($header)'
     Retrieves the named header from the mail message.

`put($header, $value')
     Inserts a new header into the mail message with the given value.

body
     Returns an array of lines in the body of the email.

header
     Returns the header as a single string.

`resend($address)'
     Bounces the email in its entirety to another address.

ATTRIBUTES
----------

   The following attributes correspond to fields in the mail:

   * from

   * to

   * subject

   * cc

   * bcc

BUGS
====

   Fewer than before.

AUTHOR
======

   Simon Cozens <simon@cpan.org>

SEE ALSO
========

   See Mail/Internet, `Mail::SMTP' in this node

Mail::Audit plugin for duplicate suppression
********************************************

NAME
====

   Mail::Audit::KillDups - Mail::Audit plugin for duplicate suppression

SYNOPSIS
========

     use Mail::Audit qw(KillDups);
     $Mail::Audit::KillDups::dupfile = "/home/simon/.msgid-cache";
     	my $mail = Mail::Audit->new;
     $mail->killdups;

DESCRIPTION
===========

   This is a Mail::Audit plugin which provides a method for checking and
supressing duplicate messages; that is, mails with message-ids which have
been previously seen.

METHODS
-------

`killdups'
     Checks the incoming message against a file of previously seen message
     ids, ignores it if it's already seen, and adds it if it hasn't been.
     `$Mail::Audit::KillDups::dupfile' contains the name of the file used;
     if you don't set this, it will be `.msgid-cache' in the current
     directory. (Probably your home directory.)

AUTHOR
======

   Simon Cozens <simon@cpan.org>

SEE ALSO
========

   See Mail/Audit,

Mail::Audit plugin for RBL checking
***********************************

NAME
====

   Mail::Audit::MAPS - Mail::Audit plugin for RBL checking

SYNOPSIS
========

     use Mail::Audit qw(MAPS);
     	my $mail = Mail::Audit->new;
     ...
     	if ($mail->rblcheck) {
         ...
     }

DESCRIPTION
===========

   This is a Mail::Audit plugin which provides a method for checking
messages against the Relay Black List.

METHODS
-------

`rblcheck([$timeout])'
     Attempts to check the mail headers with the Relay Blackhole List.
     Returns false if the headers check out fine or the query times out,
     returns a reason if the mail is considered spam.

AUTHOR
======

   Simon Cozens <simon@cpan.org>

SEE ALSO
========

   See Mail/Audit,

Mail::Audit plugin for PGP header fixing
****************************************

NAME
====

   Mail::Audit::PGP - Mail::Audit plugin for PGP header fixing

SYNOPSIS
========

     use Mail::Audit qw(PGP);
     	my $mail = Mail::Audit->new;
     ...
     $mail->fix_pgp_headers;

DESCRIPTION
===========

   This is a Mail::Audit plugin which provides a method for checking
whether a given email contains a PGP-signed or -encrypted message, and if
so, adds the relevant headers to tell the mailer to check the signature or
decrypt it.

AUTHOR
======

   Simon Cozens <simon@cpan.org>

SEE ALSO
========

   See Mail/Audit,

Manage a message-folder.
************************

NAME
====

   Mail::Box - Manage a message-folder.

SYNOPSIS
========

     use Mail::Box;
     my $folder = new Mail::Box::Mbox file => $ENV{MAIL}, ...;
     print $folder->message(0)->subject;      # See Mail::Box::Message
     $folder->message(3)->deleted(1);
     my $emails = $folder->messages;          # amount

     $folder->addMessage(new Mail::Box::Message(...));

     foreach (@{$folder->messages}) {...}     # the messages
     foreach (@$folder) {...}                 # same

   Tied-interface:

     use Mail::Box;
     tie my @inbox, 'Mail::Box', file => $ENV{MAIL};
     # See Mail::Box::Tied

DESCRIPTION
===========

   Read Mail::Box::Manager first.  Mail::Box is the base-class for
accessing various types of mail-folder organizational structures in a
uniformal way.

   This class extends:

   * Mail::Box::Threads

     implements thread detection and simplified access to the threads
     found.

   * Mail::Box::Locker

     implements various locking algorithms

   * Mail::Box::Tie

     provides simple array-based access to the folder.

   You need to read their manual-pages too, to find-out what a folder is
capable of.

   The various folder-types do vary on how they store their messages (a
folder with many messages in a single file or a folder as a directory with
each message in a single file)  Furthermore, different types of folders
have different ways to be locked.

   Applications usually add information to the messages in the folders, for
instance whether you have replied to a message or not.  The base-class for
messages in a folder is Mail::Box::Message (an extention of MIME::Entity).
It presents message-facts in an application-independent way.  Each
application needs to extend Mail::Box::Message with their own practices.

METHODS
=======

new ARGS
     (Class method) Open a new folder.  The ARGS is a list of labeled
     parameters defining what to do.  Each sub-class of Mail::Box will add
     different options to this method.  See their manual-pages.

     All possible options are:  (for detail description of the Mail::Box
     specific options see below, for the other options their respective
     manual-pages)

          access            Mail::Box          'r'
          create            Mail::Box          0
          dummy_type        Mail::Box::Threads 'Mail::Box::Message::Dummy'
          folder            Mail::Box          $ENV{MAIL}
          folderdir         Mail::Box          <no default>
          lazy_extract      Mail::Box          10kb
          lockfile          Mail::Box::Locker  foldername.'.lock'
          lock_method       Mail::Box::Locker  'dotlock'
          lock_timeout      Mail::Box::Locker  1 hour
          lock_wait         Mail::Box::Locker  10 seconds
          manager           Mail::Box          undef
          message_type      Mail::Box          'Mail::Box::Message::Parsed'
          notreadhead_type  Mail::Box          'Mail::Box::Message::NotReadHead'
          notread_type      Mail::Box          'Mail::Box::Message::NotParsed'
          realhead_type     Mail::Box          'MIME::Head'
          remove_when_empty Mail::Box          1
          save_on_exit      Mail::Box          1
          take_headers      Mail::Box          <specify everything you need>
          thread_body       Mail::Box::Threads 0
          thread_timespan   Mail::Box::Threads '3 days'
          thread_window     Mail::Box::Threads 10
          <none>            Mail::Box::Tie

     The options added by Mail::Box

        * folder => FOLDERNAME

          Which folder to open (for read or write).  When used for reading
          (the access option set to `"r"') the mailbox should already
          exist.  When opened for `"rw"', we do not care, although
          write-permission is checked on opening.

        * access => MODE

          Access-rights to the folder. MODE can be read-only (`"r"'),
          append (`"a"'), and read-write (`"rw"').  These modes have
          nothing in common with the modes actually used to open the
          folder-files within this module.

          Folders are opened for read-only (`"r"') by default.

        * folderdir => DIRECTORY

          Where are folders written by default?  You can specify a
          folder-name preceeded by = to explicitly state that the folder
          is located below this directory.

        * message_type => CLASS

          What kind of message-objects are stored in this type of folder.
          The default is Mail::Box::Message (which is a sub-class of
          MIME::Entity).  The class you offer must be an extention of
          Mail::Box::Message.

        * save_on_exit => BOOL

          Sets the default on what to do when the folder is closed (see the
          close() method.  When the program is terminated, or any other
          reason when the folder is automatically close, this flag
          determines what to do.  By default, this is TRUE;

        * remove_when_empty => BOOL

          Remove the folder-file or directory (dependent on the type of
          folder) automatically when the write would result in a folder
          without sub-folders and messages.  This is true by default.

        * manager => MANAGER

          The object which manages this folder.  Typically a (sub-class of)
          Mail::Box::Manager.

     Some folder-types have the following options.  You can find this in
     their specific manual-pages.  Folders which do not support these
     fields will not complain.

        * notread_type => CLASS

        * notreadhead_type => CLASS

        * realhead_type => CLASS

          Three classes of objects which are usually hidden for users of
          this module, but especially useful if you plan to extent
          modules.  These classes all contain parts of an incompletely
          read message.

        * lazy_extract => INTEGER

        * lazy_extract => CODE

        * lazy_extract => METHOD

        * lazy_extract => 'NEVER'|'ALWAYS'

          If you supply a number to this option, bodies of those messages
          with a total size less than that number will be extracted from
          the folder only when nessesary.  Headers will always be
          extracted, even from the larger messages.  This reduces the
          memory-footprint of the program, with only little cost.

          When you supply a code-reference, that subroutine is called
          every time that the extraction mechanism wants to determine
          whether to parse the body or not. The subroutine is called:

               $code->(FOLDER, HEADER, BODY, BYTES)

          where FOLDER is a reference to the folder we are reading.
          HEADER refers an array of header-lines, or a MIME::Header, but
          may also be undef.  You have to handle all three situations.
          BODY refers to the array lines which form the body of the
          message (including message-parts), but may also be undef,
          dependent on the folder-type.  BYTES is the size of the message
          in bytes including the header-lines, and always defined.  This
          may be the best way to make a selection.

          The routine must return true (be lazy: delay extract) or false
          (extract now).

          The third possibility is to specify the NAME of a method.  In
          that case, for each message is called:

               FOLDER->NAME(HEADER, BODY, BYTES)

          Where each field has the same meaning as described above.

          The fourth way to use this parameter involves constants: with
          `'NEVER'' you can disable delayed loading.    With `'ALWAYS''
          you force unconditional delayed-loading.

          Examples:

               $folder->new(lazy_extract => 'NEVER');
               $folder->new(lazy_extract => 10000);
               $folder->new(lazy_extract => sub {$_[3] >= 10000 }); #same

               $folder->new(lazy_extract => 'sent_by_me');
               sub Mail::Box::send_by_me($$$)
               {   my ($self, $header, $lines, $bytes) = @_;
                   $header->get('from') =~ m/\bmy\@example.com\b/i;
               }

          The Mail::Box::Message manual-page has more on this subject.

        * take_headers => ARRAY-REGEXPS|REGEXP|'ALL'|'REAL'|'DELAY'

          When messages are not parsed (as controlled by the
          `lazy_extract' parameter), and hence stay in their respective
          folders, some header-lines are still to be taken: for instance
          you still want access to the subject-field to be able to print
          an index.

          See `registerHeaders()' below, for a detailed explanation.
          Please try to avoid calling that method when you can do with
          using this option.

          Examples:

               $folder->new( take_headers  => 'ALL');
               $folder->new( take_headers  => 'Subject');
               $folder->new( take_headers  =>
                     [ 'X-Mutt-.*', 'X-Folder-.*' ]);
               $folder->new( take_headers  => 'REAL'
                           , realhead_type => 'MIME::Head'
                           );

clone [OPTIONS]
     Create a new folder, with the same settings as this folder.  One of
     the specified options must be new folder to be opened.  Other options
     overrule those of the folder where this is a clone from.

     Example:

          my $folder2 = $folder->clone(folder => '=jan');

registerHeaders REGEXP [,REGEXP, ...]
registeredHeaders
     See the `take_header' option of new(), which is the prefered way to
     specify which way the header should be treated.  Try to avoiding
     registerHeaders directly.

     The registerHeaders method can be used to specify more header-lines
     to be taken when scanning through a folder.  Its counterpart
     registeredHeaders returns the current setting.

     If you know your application needs some header-fields frequently, you
     add them to the default list of fields which are already taken by the
     folder-implementation.  No problem if you specify the same name twice.

     If you specify too few field-names, then all messages will get parsed
     (read from file into memory) to get the field-data you missed.  When
     you specify too many fields, your program will consume considerable
     more memory.

     You can specify a regular expression, although you cannot use
     parentheses in them which do count.  The expressions will be matched
     always on the whole field.  So `X-.*' will only match lines starting
     with `X-'.  You can not used `X-(ab|cd).*', but may say
     `X-(?:ab|cd).*'.

     There are three special constants.  With ALL you get all header-lines
     from the message (same as pattern `.*')  and REAL will cause headers
     to be read into a real MIME::Header structure (to be more precise: the
     type you specify with `realhead_type'.)

     Some folder-types (like MH) support DELAY, where headers are to taken
     at all, until a line from the header is required.  This is useful for
     folders where each message has to be read from a seperate source.  In
     this case, we would like to delay even that contact as long as
     possible.

        * 'ALL' to indicate that all headers should be taken.

        * 'REAL'

          indicates that all headers should be taken and translated into a
          real MIME::Header.

        * 'DELAY'

          requests for no header at all, unless we accidentally stumble on
          them.  This is default (and only usefull) for all folder-types
          which store their messages in seperate files.  Mail::Box will
          try to avoid opening those files with maximum effort.

          In case you need header-lines, and at the same time want to
          avoid access to each file when a folder is opened (for instance,
          if you want to read e-mail in threads), consider using
          index-files.  Read the manual-page of the folder-type you need
          on whether those is supported for that specific type.

        * a list of regular expressions

          which specify the header-lines to be taken.

     Examples:

          $folder->registerHeaders('ALL');
          $folder->registerHeaders('Subject', 'X-Folder-.*');

unfoldHeaders REF-ARRAY
     E-mail headers may span a few lines (folded fields).  The first line
     has the name of the field, and is followed by one or more lines which
     start with some blanks.

     This method receives an array, and modifies it such that folder lines
     are rejoined with their field-name.  Don't forget to fold back again
     when printing to file.

read OPTIONS
     Read messages from the folder into the folder-structure.  If there
     are already messages in this structure, the new ones are added.

     When to want to add messages from a different foldertype to this
     folder, you need to join folders, as shown in the following example.

     Example read folder into folder:

          my $folder = Mail::Box::File->new(folder => 'InBox');
          my $old    = Mail::Box::MH->new(folder => 'Received');
          $folder->addMessages(@$old);
          $folder->write;
          $old->delete;

write [OPTIONS]
     Write the data to disk.  It returns the folder when this succeeded.
     If you want to write to a different file, you first create a new
     folder, then move the messages, and then write that file.

     As options you may specify

        * force => BOOL

          Overrule write-protection (if possible, it may still be blocked
          by the operating-system).

        * keep_deleted => BOOL

          Do not remove messages which were flaged to be deleted from the
          folder, but do remove them from disk.

        * save_deleted => BOOL

          Save messages which where flagged to be deleted.  The flag is
          conserved (when possible)

close OPTIONS
     Close the folder.  It depends on the OPTIONS whether the folder is to
     be written or not.  Futhermore, you may specify options which are
     passed to write, as descibed above.

     Options specific to close are:

        * write => 'ALWAYS'|'NEVER'|'MODIFIED'

          When must the folder be written.  As could be expected,
          `'ALWAYS'' means always (even if there are no changes),
          `'NEVER'' means that changes to the folder will be lost, and
          `'MODIFIED'' (which is the default) only saves the folder if
          there are any changes.

        * force => BOOL

          Overrule the setting of access when the folder was opened.  This
          only contributes to your program when you give it a TRUE value.
          However: writing to the folder not be permitted by the
          file-system, in which case even force will not help.

delete
     Remove the specified folder-file or folder-directory (dependent on
     the type of folder) from disk.  Of course, THIS IS DANGEROUS: you
     "may" lose data.

     When you first copied this folder's information into an other folder,
     then be sure that that folder is written to disk first!  Otherwise
     you may loose data in case of a system-crash or software problems.

     Examples of instance call:

          my $folder = Mail::Box::File->new(folder => 'InBox');
          $folder->delete;

name
     Returns the name of this folder.  What the name represents depends on
     the actual type of mailboxes used.

     Example:

          print $folder->name;

writeable
readable
     Checks whether the current folder is writeable respectively readable.

     Example:

          $folder->addMessage($msg) if $folder->writeable;

modified
modifications INCR
     modified checks if the folder is modified, where modifications is
     used to tell the folder how many changes are made in messages.  The
     INCR value can be negative to undo effects.

lazyExtract HEADER, BODY, BYTES
     Calls the subroutine which will perform the chech whether a message's
     body should be extracted or stay in the folder until used.  This
     method calls the routine defined by the `lazy_extract' option at
     creation of the folder.

message INDEX
     Get or set a message with on a certain index.

     Examples:

          my $msg = $folder->message(3);
          $folder->message(3)->delete;   # status changes to `deleted'
          $folder->message(3) = $msg;

messageID MESSAGE-ID [,MESSAGE]
     Returns the message in this folder with the specified MESSAGE-ID.
     This method returns a not-parsed, parsed, or dummy message.  With the
     second MESSAGE argument, the value is first set.

messages
     Returns all messages which are not scheduled to be deleted.  In
     scalar context, it provides you with the number of undeleted messages
     in this folder.  Dereferencing a folder to an array is overloaded to
     call this method.

     Examples:

          foreach ($folder->messages) {...}
          foreach (@$folder)
          my $remaining_size = $folder->messages;

activeMessage INDEX [,MESSAGE]
     Returns the message indicated by INDEX from the list of non-deleted
     messages.  This is useful for the tied-folder interface, where we only
     see the non-deleted messages, but not for other purposes.

allMessages
     Returns a list of all messages in the folder, including those which
     are to be deleted.

     Examples:

          foreach my $msg ($folder->allMessages)
          {   $msg->print;
          }
          my $total_size = $folder->allMessages;

allMessageIDs
     Returns a list of all message-ids in the folder, including those
     which are to be deleted.

     For some folder-types (like MH), this method may cause all
     message-files to be read.  See their respective manual-pages.

     Examples:

          foreach my $id ($folder->allMessageIDs)
          {   $folder->messageID($id)->print;
          }

addMessage  MESSAGE
addMessages MESSAGE [, MESSAGE, ...]
     Add a message to the folder.  A message is usually a
     Mail::Box::Message object or a sub-class of that.

     Messages with id's which allready exist in this folder are neglected.

     Examples:

          $folder->addMessage($msg);
          $folder->addMessages($msg1, $msg2, ...);

appendMessages OPTIONS
     (Class method) Append one or more messages to an unopened folder.
     Usually, this method is called by the Mail::Box::Manager (its method
     `appendMessage()'), in which case the correctness of the foldertype
     is checked.

     This method gets a list of labeled parameters, which may contain any
     flag which can be used when a folder is opened (most importantly
     folderdir).  Next to these, two parameters shall be specified:

        * folder => FOLDERNAME

          The name of the folder where the messages are to be appended.
          When possible, the folder-implementation will avoid to open the
          folder for real, because that is resource consuming.

        * message => MESSAGE

        * messages => ARRAY-OF-MESSAGES

          One reference to a MESSAGE or a reference to an ARRAY of
          MESSAGEs, which may be of any type.  The messages will first be
          coerced into the correct message-type to fit in the folder, and
          then be added to it.

coerce MESSAGE
     Coerce the message to be of the correct type to be placed in the
     folder.

messageDeleted MESSAGE|MESSAGE-ID, BOOL
     Signals to the folder that a message has been deleted.  This method is
     called automatically when you call the delete method on a MESSAGE.  If
     the BOOL is true, the message got deleted, otherwise it got undeleted.

folderdir [DIR]
     Get or set the directory which is used to store mail-folders by
     default.

     Examples:

          print $folder->folderdir;
          $folder->folderdir("$ENV{HOME}/nsmail");

current [NR|MESSAGE|MESSAGE-ID]
     Returns the current message (when specified, after setting it to a new
     values.  You may specify a NUMBER, to specify that that message-number
     is to be selected as current, or a MESSAGE/MESSAGE-ID (as long as you
     are sure that the header is already loaded, otherwise they are not
     recognized).

     Examples:

          $folder->current(0);
          $folder->current($message);

DESTROY
     This method is called by Perl when an folder-object is not accessible
     anymore by the rest of the program.  However... This is not
     accomplished automatically because (unparsed) messages reference back
     to their folder: there is a two-way reference which is not resolved
     by the perl-memory cleanup.

     The two ways to clean-up the folder information is

        * by explicitly call for a close on a folder,

          in which case the data may be preserved (when the `save_on_exit'
          flag was selected), or

        * by terminating the program

          which will cause changes to be lost.  In this condition, the
          two-way reference will cause Perl to call the DESTROY of the
          folder and its messages in undefined order.  It is not possible
          to write messages which are already removed...

folder management methods
-------------------------

   The following class methods are used to test and list folders.  The do
share the folderdir option, where you can specify which is the default
location for the folder-files.

foundIn FOLDERNAME [,OPTIONS]
     (class method) Autodetect if there is a folder of a certain type
     specified here.  This method is extended for each type of folder.

     The FOLDERNAME specifies the name of the folder, as is specified by
     the application.  OPTIONS is a list of extra information on the
     request.  Read the manual-page for each type of folder for more
     options, but at least each type will support

        * folderdir => DIRECTORY

          The location where the folders of this class are stored by
          default.  If the user specifies a name starting with a =, that
          symbolizes that the name is to be found is this default
          DIRECTORY.

create FOLDERNAME [, OPTIONS]
     (Class method) Create a folder.  If the folder already exists, it will
     be left untouched.  As options, you may specify:

        * folderdir => DIRECTORY

          When the foldername is preceeded by a =, the folderdir directory
          will be searched for the named folder.

listFolders [OPTIONS]
     (Class and Instance method) List all folders which belong to a
     certain class of folders.  Each class shall extent this method.  As
     class method, the folder option is usually used (defaults to the top
     folderdir).  This method will return the sub-folders of the opened
     folder when called as instance method.

     At least the following options are supported, but refer to the manpage
     of the various folder-classes to see more options.

        * folder => FOLDERNAME

          The folder of which the sub-folders should be listed.

        * folderdir => DIRECTORY

        * check => BOOL

          Specifies whether to do a very thorrow job on selecting folders.
          Performing a check on each file or directory (depends on the
          type of folder) to see if it really contains a folder can be
          time-consuming, so the default is off.

        * skip_empty => BOOL

          Shall empty folders (folders which currently do not contain any
          messages) be included?  Empty folders are not useful to open,
          but may be useful to save to.

     Examples:

          my $folder = $mgr->open('=in/new');
          my @subs = $folder->listFolders;

          my @subs = Mail::Box::Mbox->listFolders(folder => '=in/new');
          my @subs = Mail::Box::Mbox->listFolders; # toplevel folders.

AUTHOR
======

   Mark Overmeer (`Mark@Overmeer.net').  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

VERSION
=======

   This code is beta, version 1.100

Keep indexfiles on messages.
****************************

NAME
====

   Mail::Box::Index - Keep indexfiles on messages.

SYNOPSIS
========

     $folder->readIndex(...)
     $folder->writeIndex(...)

DESCRIPTION
===========

   Message-folders which store their data in one single file per message
are very inefficient for producing subject overviews and detecting
message-threads.  The Mail::Box::Index is able to store and read a the
headers of all messages in one file.

   When Mail::Box::Index functionality is switched on (specify `keep_index'
when creating a folder), the index-file is automatically read.  When the
folder is closed, a new index-file is created.

   Special care is taken to avoid a problems when the user changed or
removed message-files without updating the index.  If the index is not
trusted, it will not be used (and so cost performance to the reader of the
folder).

METHODS
=======

new ARGS
     You will not call this method yourself, unless you implement a folder
     yourself.  The following options can be specified when you create a
     folder.

        * keep_index => BOOL

          Keep an index-file in the specified file, one file per
          directory.  Using an index-file will speed-up things
          considerably, because it avoids that all message-files have to
          be read on the moment that you open the folder.  When you open a
          folder, you need information like the the subject of each
          message, and it is not pleasant to open all thousands of
          messages to read them.

        * index_filename => FILENAME

          The FILENAME which is used in each directory to store the
          headers of all mails.  The filename shall not contain a
          directory path (so: do not use `/usr/people/jan/.index', nor
          `subdir/.index', but say `.index')

indexFilename
     Returns the index-file for a folder.  If the `keep_index' option was
     not used when the folder was read, this returns undef.

writeIndex MESSAGE [,MESSAGE]
     Write an index-file containing the specified messages, but only if the
     user requested it: the `keep_index' option of new() must have been
     specified.

readIndex [HEADERCLASS]
     Read the index-file if it exists and the user has specified
     `keep_index' with the constructor (new) of this folder.  If that
     option is not specified, the readIndex does not know under what name
     the index is stored, and therefore not work.

     The headers which are read are created into the specified HEADERCLASS,
     which may be different for each folder-type, but by default a
     `MIME::Head'.

AUTHOR
======

   Mark Overmeer (`Mark@Overmeer.net').  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

VERSION
=======

   This code is beta, version 1.100

Manage the locking of mail-folders
**********************************

NAME
====

   Mail::Box::Locker - Manage the locking of mail-folders

SYNOPSIS
========

     use Mail::Box::Locker;
     my $locker = new Mail::Box::Locker;

     $locker->lock($folder);
     $locker->isLocked($folder);
     $locker->hasLock($folder);
     $locker->unlock($folder);

     Mail::Box::Locker->addLockingMethod(...);

     # Because Mail::Box inherits from this class:
     my $folder = new Mail::Box(lock_method => 'dotlock');
     $folder->lock;
     $folder->isLocked;
     $folder->hasLock;
     $folder->unlock;

DESCRIPTION
===========

   Read Mail/Box/Manager, first.  The locker
module contains the various locking functionalities as needed when
handling folders.

   Because `Mail::Box' inherits from Mail::Box::Locker, this example works:

     my $folder
     $folder->lock;

METHOD
======

new ARGS
     Create a new lock.  You may do this, however, in most cases the lock
     will not be seperately instantiated but be the second class in a
     multiple inheritance construction with a Mail/Box.

     ARGS is a reference to a hash, where the following fields are used
     for the locker information:

        * lock_method => METHOD

          Which METHOD has to be used for locking.  Supported are

         'dotlock'
               The folder handler creates a file which signals that it is
               in use.  This is a bit problematic, because all
               mail-handling software should agree on the name of the file
               to be created.

               On various folder-types, the lockfile differs.  See each
               manual-page and special options to change their default
               behavior.

         'file'
               For some folder handlers, locking is based on simply
               file-locking mechanism.  However, this does not work on
               network filesystems, and such.  This also doesn't work on
               directory-type of folders (Mail::Box::Dir and derived).

         'nfs'
               A kind of `dotlock' file-locking mechanism, but adapted to
               work over NFS.  Extra precaution is needed because an `open
               O_EXCL' on NFS is not an atomic action.

         'NONE'
               Disable locking.

        * lock_timeout => SECONDS

          How long can a lock stand?  When an different e-mail program
          left a lock, then this will be removed automatically after the
          specified seconds.  The default is one hour.

        * lock_wait => SECONDS|'NOTIMEOUT'

          How long to wait for receiving the lock.  The lock-request may
          fail, when the specified number of seconds is reached.  If
          'NOTIMEOUT' is specified, we wait till the lock can be taken.

          It is platform and locking method specific whether it is
          possible at all to limit the trials to the specified number of
          seconds.  For instance, the `dotlock' method on Windows will
          always wait until the lock has been received.

        * lockfile => FILENAME

          Name of the file to take the lock on or to represent a lock
          (depends on the kind of lock used).

lockingMethod NAME, CODE, CODE, CODE
     (class method)  Add locking methods to the set of know methods.  You
     need to specify a method-name and three code references, respectively
     for the get, test, and un method.  You may also specify method-names
     instead of code-references.

Basic functions
---------------

   The lock, `test_lock', and unlock methods are to be used.  They call
specific methods which implement the right locking mechanism.   *Do not
call* the various locking methods directly.

lock [FOLDER] [METHOD]
     Get a lock on a folder, by using the predefined method, or a specific
     METHOD.  If you do not specify a FOLDER, it is assumed the locking
     functionality is inherited.

     Examples:

          $locker->lock($folder);
          $folder->lock;

isLocked [FOLDER] [METHOD]
     Test if the folder is locked.

     Examples:

          $locker->isLocked($folder);
          $folder->isLocked;

hasLock [FOLDER]
     Check wheter the folder has the lock.

     Examples:

          $locker->hasLock($folder);
          $folder->hasLock;

unlock [FOLDER] [METHOD]
     un the lock on a folder.

     Examples:

          $locker->unlock($folder);
          $folder->unlock;

lockFilename [FILENAME]
     Returns the filename which is used to lock the folder.  It depends on
     the locking method how this file is used.

AUTHOR
======

   Mark Overmeer (`Mark@Overmeer.net').  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

VERSION
=======

   This code is beta, version 1.100

Handle folders with a file per message.
***************************************

NAME
====

   Mail::Box::MH - Handle folders with a file per message.

SYNOPSIS
========

     use Mail::Box::MH;
     my $folder = new Mail::Box::MH folder => $ENV{MAIL}, ...;

DESCRIPTION
===========

   `Mail::Box::MH' extends Mail/Box, and
Mail/Box/Index, to implement MH-type folders.  Read
Mail/Box/Manager, for the general overview, see
Mail/Box, for understanding mailboxes, and
Mail/Box/Message, about how messages are used, first.

   `The internal organization and details|' in this node are found at the
bottom of this manual-page.  The working of MH-messages are described in
Mail/Box/MH/Message.

METHODS
=======

new ARGS
     Create a new folder.  The are many options which are taken from other
     objects.  For some, different options are set.  For MH-specific
     options see below, but first the full list.

          access            Mail::Box          'r'
          create            Mail::Box          0
          dummy_type        Mail::Box::Threads 'Mail::Box::Thread::Dummy'
          folder            Mail::Box          $ENV{MAIL}
          folderdir         Mail::Box          <no default>
          index_filename    Mail::Box::Index   foldername.'/.index'
          keep_index        Mail::Box::Index   0
          labels_filename   Mail::Box::MH      foldername.'/.mh_sequence'
          lazy_extract      Mail::Box          10000   (10kB)
          lockfile          Mail::Box::Locker  foldername.'/.lock'
          lock_method       Mail::Box::Locker  'dotlock'
          lock_timeout      Mail::Box::Locker  3600    (1 hour)
          lock_wait         Mail::Box::Locker  10      (seconds)
          manager           Mail::Box          undef
          message_type      Mail::Box          'Mail::Box::MH::Message'
          notreadhead_type  Mail::Box          'Mail::Box::MH::NotReadHead'
          notread_type      Mail::Box          'Mail::Box::MH::NotParsed'
          realhead_type     Mail::Box          'MIME::Head'
          remove_when_empty Mail::Box          1
          save_on_exit      Mail::Box          1
          take_headers      Mail::Box          'DELAY'
          thread_body       Mail::Box::Threads 0
          thread_timespan   Mail::Box::Threads '3 days'
          thread_window     Mail::Box::Threads 10
          <none>            Mail::Box::Tie

     MH specific options:

        * labels_filename => FILENAME

          In MH-folders, messages can be labeled, for instance based on the
          sender or whether it is read or not.  This status is kept in a
          file which is usually called `.mh_sequences', but that name can
          be overruled with this flag.

readMessages
     Read all messages from the folder.  This method is called at
     instantiation of the folder, so do not call it yourself unless you
     have a very good reason.

readMessage MESSAGE-NR [, BOOL]
     Read one message from its file.  This method is automatically
     triggered by the AUTOLOAD mechanism, so will usually not be called
     explicitly.

     Although the name of the method seems to imply that also the message
     body is read, this might not be true.  If BOOL is true (default
     false), the body is certainly read.  Otherwise, it depends on the
     content of the folder's `take_headers' and `lazy_extract' flags.

     =cut

     sub readMessage($;$) {   my ($self, $msgnr, $force_read_all) = @_;
     my $message = $self->{MB_messages}[$msgnr];     my $mode    =
     $self->{MB_header_mode};     my $head    = $message->{MB_head};
     local $_;                       # protect global $_

          unless(open MESSAGE, $message->filename)
          {   warn "Unable to open ", $message->filename, ": $!\n";
              return;
          }

          # Read the header.
          my @header;
          while(<MESSAGE>)
          {   last if /^\r?\n$/;
              push @header, $_;
          }
          $self->unfoldHeaders(\@header);

          if($force_read_all || !$self->lazyExtract(\@header, undef, $message->size))
          {   # Take the message immediately.
              push @header, "\r\n", <MESSAGE>;
              $message->load($self->{MB_message_type}, \@header);
          }
          elsif($mode eq 'SOME' || $mode eq 'ALL')
          {   # Keep a delay-loaded message with some fields.
              my $header = $self->{MB_notreadhead_type}
                                ->new(expect => $self->{MB_expect});
              my $take_headers = $self->{MB_header_scan};

          if($mode eq 'SOME')
          {   foreach (@header)
              {   $header->setField($1, $2) if $_ =~ $take_headers;
              }
          }
          else {  $header->setField(split ':', $_, 2) foreach @header }

          $message->{MBM_head} = $header;
              }
              else
              {   # Create a real header structure, but not yet the body.
          $message->{MBM_head} = MIME::Head->new(\@header)->unfold;
              }

          close MESSAGE;

          --$self->{MB_last_untouched}
              if $message->seqnr == $self->{MB_last_untouched};

          $message->head_init;

          $self->messageID($message->messageID, $message);
          $self->toBeThreaded($message);
          $message->statusToLabels->XstatusToLabels;
          $message;
          }

     #------------------------------------------

addMessage MESSAGE
     Add a message to the MH-folder.

write [OPTIONS]
     Write all messages to the folder-file.  Returns the folder when this
     was successful.  As options you may specify (see `Mail::Box' for
     explanation)

        * keep_deleted => BOOL

        * save_deleted => BOOL

        * renumber => BOOL

          Permit renumbering of message.  Bij default this is true, but
          for some unknown reason, you may be thinking that messages
          should not be renumbered.

readAllHeaders
     Force all messages to be read at least till their header information
     is known.  The exact status reached depends on the `take_headers' of
     new(), as described above.

appendMessages OPTIONS
     (Class method) Append one or more messages to this folder.  The folder
     will not be opened.

     If the folder does not exist, undef (or FALSE) is returned.

        * folder => FOLDERNAME

        * message => MESSAGE

        * messages => ARRAY-OF-MESSAGES

     Example:

          my $message = Mail::Internet->new(...);
          Mail::Box::Mbox->appendMessages
            ( folder    => '=xyz'
            , message   => $message
            , folderdir => $ENV{FOLDERS}
            );

directory
     Returns the directory related to this folder.

     Example:

          print $folder->directory;

folderToDirectory FOLDERNAME, FOLDERDIR
     (class method)  Translate a foldername into a filename, with use of
     the FOLDERDIR to replace a leading =.

highestMessageNumber
     Returns the highest number which is used in the folder to store a
     file.  This method may be called when the folder is read (then this
     number can be derived without file-system access), but also when the
     folder is not read (yet).

messageID MESSAGE-ID [,MESSAGE]
     Returns the message with the specified MESSAGE-ID.  If also a MESSAGE
     is specified, the relationship between ID and MESSAGE will be stored
     first.

     Be warned, that if the message is not read at all (`take_headers' set
     to DELAY), each message of the folder will be parsed, at least to get
     its header.  The headers are read from back to front in the folder.

allMessageIDs
     Returns a list of all message-ids in the folder, including those
     which are to be deleted.

     Be warned that this will cause all message-headers to be read from
     their files, if that was not done before.  This penalty can be
     avoided keeping an index-file.  See the `keep_index' option of new().

Manage message labels
---------------------

   MH-folder use one dedicated file per folder-directory to list special
tags to messages in the folder.  Typically, this file is called
`.mh_sequences'.  The messages are numbered from 1.

   Example content of `.mh_sequences':

     cur: 93
     unseen: 32 35-56 67-80

   To generalize labels on messages, two are treated specially:

   * cur

     The `cur' specifies the number of the message where the user stopped
     reading mail from this folder at last access.  Internally in these
     modules refered to as label current.

   * unseen

     With `unseen' is listed which message was never read.  This must be a
     mistake in the design of MH: it must be a source of confusion.
     People should never use labels with a negation in the name:

          if($seen)           if(!$unseen)    #yuk!
          if(!$seen)          if($unseen)
          unless($seen)       unless($unseen) #yuk!

     So: label `unseen' is translated into seen for internal use.

labelsFilename [FILENAME]
     Returns the filename of the dedicated file which contains the label
     related to the messages in this folder-directory.

readLabels
     In MH-folders, messages can be labeled to easily select sets which
     are, for instance, posted by who.  The file is usually called
     `.mh_sequences' but that name can be overruled using the
     `labels_filename' option of new().

writeLabels HASH
     Write the file which contains the relation between messages (actually
     the messages' sequence-numbers) and the labels those messages have.
     The parameter is a reference to an hash which contains for each label
     a reference to a list of message-numbers which have to be written.

folder management methods
-------------------------

   Read the Mail::Box manual for more details and more options on each
method.

foundIn FOLDERNAME [,OPTIONS]
     Autodetect if there is a Mail::Box::MH folder specified here.  The
     FOLDERNAME specifies the name of the folder, as is specified by the
     application.  The OPTIONS is a list of extra parameters to the
     request.

     For this class, we use (if defined):

        * folderdir => DIRECTORY

     Example:

          Mail::Box::MH->foundIn
             ( '=markov'
             , folderdir => "$ENV{HOME}/.mh"
             );

create FOLDERNAME [, OPTIONS]
     (Class method) Create a folder.  If the folder already exists, it will
     be left untouched.  As options, you may specify:

        * folderdir => DIRECTORY

listFolders [OPTIONS]
     (Class and Instance method) List the folders in a certain directory.
     As class method, you will use the folder option to indicate which
     folder to list.  As instance method, the sub-folders of that folder
     are returned.

        * folder => FOLDERNAME

        * folderdir => DIRECTORY

        * check => BOOL

        * skip_empty => BOOL

openSubFolder NAME [,OPTIONS]
     Open (or create, if it does not exist yet) a new subfolder to an
     existing folder.

     Example:

          my $folder = Mail::Box::MH->new(folder => '=Inbox');
          my $sub    = $folder->openSubFolder('read');

          =cut

     sub openSubFolder($@) {   my ($self, $name) = (shift, shift);     my
     $dir = $self->directory . '/' . $name;

          unless(-d $dir || mkdir $dir, 0755)
          {   warn "Cannot create subfolder $name for $self: $!\n";
              return;
          }

          $self->clone( folder => File::Spec->catfile("$self",$name), @_ );
          }

IMPLEMENTATION
==============

   The explanation is complicated, but for normal use you should bother
yourself with all details.

How MH-folders work
-------------------

   MH-type folders use a directory to store the messages of one folder.
Each message is stored in a seperate file.  This seems useful, because
changes in a folder change only a few of these small files, in contrast
with file-based folders where changes in a folder cause rewrites of huge
folder-files.

   However, MH-based folders perform very bad if you need
header-information of all messages.  For instance, if you want to have
full knowledge about all message-threads (see Mail::Box::Threads) in the
folder, it requires to read all header-lines in all message-files.  And
usually, reading in threads is desired.

   So, each message is written in a seperate file.  The file-names are
numbers, which count from 1.  Next to these message-files, a directory may
contain a file named `.mh_sequences', storing labels which relate to the
messages.  Furthermore, a folder-directory may contain sub-directories,
which are seen as sub-folders.

This implementation
-------------------

   This implementation supports the `.mh-sequences' file and sub-folders.
Next to this, considerable effort it made to avoid reading each
message-file.  This should boost performance of the Mail::Box module over
other Perl-modules which are able to read folders.

   Folder-types which store their messages each in one file, together in
one directory, are bad for performance.  Consider that you want to know
the subjects of all messages, while browser through a folder with your
mail-reading client.  This would cause all message-files to be read.

   Mail::Box::MH has two ways to try improve performance.  You can use an
index-file, and use on delay-loading.  The combination performs even
better.  Both are explained in the next sections.

An index-file
-------------

   If you specify `keep_index' as option to the folder creation method
new(), then all header-lines of all messages from the folder which have
been read once, will also be written into one dedicated index-file (one
file per folder).  The default filename is `.index'

   However, index-files are not supported by any other reader which
supports MH (as far as I know).  If you read the folders with such I
client, it will not cause unrecoverable conflicts with this index-file,
but at most be bad for performance.

   If you do not (want to) use an index-file, then delay-loading may save
your day.

Delayed loading
---------------

   The delay-loading mechanism of messages tries to be as lazy as possible.
When the folder is opened, none of the message-files will be read.  If
there is an index-file, those headers will be taken.  The labels will be
read from the `.mh-sequences'.  But from the messages, only the filenames
are scanned.

   Not before any header-line (or any other action on a message) is used,
the message is read.  This is done using Perl's AUTOLOADing, and is
transparent to users.  If the first thing you ask for is a header-line,
then `lazy_extract' and `take_headers' determine what how far this message
is parsed: into a `Mail::Box::MH::NotParsed' or a `Mail::Box::MH::Message'.

   The index-file is farmost best performing, but also in the second case,
performance can be ok.  When a mail-client opens a huge folder, only a few
of the messages will be displayed on the screen as folder-list.  Only from
the visible messages, header-lines like `Subject' are needed, so the
AUTOLOAD automatically reads those message-files.  Other messages will
only be read from file when they appear in the viewport.

AUTHOR
======

   Mark Overmeer (`Mark@Overmeer.net').  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

VERSION
=======

   This code is beta, version 1.100

a message in a MH-folder
************************

NAME
====

   Mail::Box::MH::Message - a message in a MH-folder

SYNOPSIS
========

     my $folder = new Mail::Box::MH ...
     my $message = $folder->message(10);

DESCRIPTION
===========

   This manual-page describes the classes `Mail::Box::MH::Message',
`Mail::Box::MH::Parsed', and `Mail::Box::MH::NotParsed'.  These objects are
used to store messages which are not totally read, fully read, or to be
written to a Mail/Box/MH, type of folder.

   During its life, a message will pass through certain stages.  These
stages were introduced to reduce the access-time to the folder.  Changing
from stage, the message changes from object-class (try to do this in any
other language than Perl!).

   All information which is required during the full life-span of the
message is stored in a `Mail::Box::MH::Message', which is extended by the
`Mail::Box::MH::NotParsed' and the `Mail::Box::MH::Parsed'.  The last
object (`Mail::Box::MH::NotReadHead') maintains some header-lines of the
message.

   The bottom of this page provides more details about `details about the
implementation|' in this node, but first the use.

CLASS Mail::Box::MH::Message
============================

   This object contains methods which are part of as well delay-loaded
(not-parsed) as loaded messages, but not general for all folders.

METHODS
-------

new ARGS
     Messages in directory-based folders use the following extra options
     for creation:

        * filename => FILENAME

          The file where the message is stored in.

print TO
     Write one message to a file-handle.  Unmodified messages are taken
     from the folder-file where they were stored in.  Modified messages
     are written as in memory.  Specify a file-handle to write TO
     (defaults to STDOUT).

printIndex [FILEHANDLE]
     Print the information of this message which is required to maintain
     an index-file.  By default, this prints to STDOUT.

readIndex CLASS [,FILEHANDLE]
     Read the headers of one message from the index into a CLASS
     structure.  CLASS is (a sub-class of) a MIME::Head.  If no FILEHANDLE
     is specified, the data is read from STDIN.

filename [FILENAME]
     Returns the name of the file in which this message is actually
     stored.  This will return undef when the message is not stored in a
     file.

CLASS Mail::Box::MH::Parsed
===========================

   This object extends a Mail::Box::Message with extra tools and facts on
what is special to messages in file-based folders, with respect to
messages in other types of folders.

METHODS
-------

coerce FOLDER, MESSAGE [,OPTIONS]
     (Class method) Coerce a MESSAGE into a Mail::Box::MH::Parsed, ready
     to be stored in FOLDER.  When any message is offered to be stored in
     the mailbox, it first should have all fields which are specific for
     MH-folders.

     The coerced message is returned on success, else undef.

     Example:

          my $mh = Mail::Box::MH->new(...);
          my $message = Mail::Box::Mbox::Message->new(...);
          Mail::Box::MH::Parsed->coerce($mh, $message);
          # Now $message is ready to be stored in $mh.

     However, you can better use

          $mh->coerce($message);

     which will call coerce on the right message type for sure.

CLASS Mail::Box::MH::NotParsed
==============================

   Not parsed messages stay in the file until the message is used.  Because
this folder structure uses many messages in the same file, the
byte-locations are remembered.

METHODS
-------

load CLASS [, ARRAY-OF-LINES]
     This method is called by the autoloader then the data of the message
     is required.  If you specified REAL for the `take_headers' option for
     new(), you did have a MIME::Head in your hands, however this will be
     destroyed when the whole message is loaded.

     If an array of lines is provided, that is parsed as message.
     Otherwise, the file of the message is opened and parsed.

head
     Get the head of the message.  This may return immediately, because the
     head is already read.  However, when we do not have a header yet, we
     read the message.  At this moment, the `lazy_extract' option of new
     comes into action: will we read the whole message now, or only the
     header?

headIsRead
     Checks if the head of the message is read.  This is true for fully
     parsed messages and messages where the header was accessed once.

messageID
     Retreive the message's id.  Every message has a unique message-id.
     This id is used mainly for recognizing discussion threads.

IMPLEMENTATION
==============

   The user of a folder gets his hand on a message-object, and is not
bothered with the actual data which is stored in the object at that
moment.  As implementor of a mail-package, you might be.

   A message is simple to use, but has a quite complex class structure.  A
message is not a real message from the start, but only if you access the
body from it.  Till then, you only have a hollow placeholder.  Below is
depicted how the internal status of a message-object changes based on
actions on the object and parameters.

   The inheritance relation is like this:

     read()
     =====#
          V              load()
       ::MH::NotParsed ========> ::MH::Parsed
           |       \               /    |
           ^        \             /     ^
           |          ::MH::Message     |
           |                            |
         ::Message                ::Message
        ::NotParsed                ::Parsed
                \                  /    |
                 `--- ::Message --'     ^
                           |            |
                           ^        MIME::Entity
                           |            |
                       ::Thread         ^
                                        |
                                    Mail::Internet

   The `Mail::Box::MH::Parsed' stage, means that the whole message is in
memory.  It then is a full decendent of a `MIME::Entity'.  But at the same
time, it consumes a considerable amount of memory, and spent quite some
processor time.  All the intermediate stati are created to avoid full
loading, so to be cheap in memory and time.  Random folder access will be
much faster by this strategy, under normal circumstances.

   For trained eyes only the transition diagram:

     read()     !lazy && !DELAY
     -------> +----------------------------------> Mail::Box::
              |                                    MH::Parsed
              | lazy && !DELAY && !index                ^
              +--------------.                          |
              |           \   \    NotParsed    load    |
              |            \   `-> NotReadHead ------>-'|
              |        REAL \                           |
              |              \                          |
              | index         v    NotParsed    load    |
              +------------------> MIME::Head ------->-'|
              |                       ^                 |
              |                       |                 |
              |                       |load_head        |
              |                       |                 |
              | DELAY && !index    NotParsed    load    |
              +------------------> <no head> -------->--'

     ,-------------------------+---.
             |                      ALL |   | regexps && taken
             v                          |   |
        NotParsed    head()    get()   /   /
        NotReadHead --------> ------->+---'
         \          \         \
          \ other()  \ other() \regexps && !taken
           \          \         \
            \          \         \    load    Mail::Box::
             `----->----+---------+---------> MH::Parsed

     ,---------------.
             |                |
             v                |
        NotParsed     head()  |
        MIME::Head -------->--'
        \                           Mail::Box::
         `------------------------> MH::Parsed

     load_head   NotParsed
                                ,----------> MIME::Head
                               /
        NotParsed    head()   / lazy
        <no head>  --------->+
                              \ !lazy
                               \
                                `-----------> Mail::Box::
      load        MH::Parsed

   Terms: lazy refers to the evaluation of the `lazy_extract()' option. The
load and `load_head' are triggers to the AUTOLOAD mothods.  All terms like
`head()' refer to method-calls.  The index is true if there is an
index-file kept, and the message-header found in there seems still valid
(see the `keep_index' option of new()).

   Finally, ALL, REAL, DELAY (default), and `regexps' refer to values of
the `take_headers' option of new().  Notice that `take_headers' on DELAY
is more important than `lazy_extract'.

   Hm... not that easy...  Happily, the implementation takes fewer lines
than the documentation.

AUTHOR
======

   Mark Overmeer (`Mark@Overmeer.net').  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

VERSION
=======

   This code is beta, version 1.100

Manage a set of folders
***********************

NAME
====

   Mail::Box::Manager - Manage a set of folders

SYNOPSIS
========

     use Mail::Box::Manager;
     my $manager = new Mail::Box::Manager;
     my $folder  = $manager->open(folder => $ENV{MAIL});
     $manager->registerType(mbox => 'Mail::Box::Mbox');
     $manager->close($folder);

DESCRIPTION
===========

   This code is beta, which means that there are no serious applications
written with it yet.  Please inform the author when you have, so this
module can go to stable.  Read the STATUS file inclosed in the package for
more details.

   The Mail::Box package can be used as back-end to Mail User-Agents
(MUA's), and has special features to help those agents to have fast access
to folder-data.  These features may delay access to folders for other
kinds of applications.  Maybe Mail::Procmail has more for you in such
cases.

The folder manager
------------------

   The folder manager maintains a set of folders (mail-boxes).  Those
folders may be of different types.  Most folder-types can be detected
automatically.  This class is the only one you create in your program: all
other classes will come when needed.

   Overview:

     Mail::Box::Manager
           |
           | open()
           |              message()
           v             ,--------->  Mail::Box::Message
        Mail::Box      /                    isa
     (Mail::Box::Mbox)                  MIME::Entity
      (Mail::Box::MH)                   : :
       : : :                            : :
       : : :                            : Mail::Box::Message::Dummy
       : : :                            Mail::Box::Message::NotParsed
       : : Mail::Box::Tie
       : Mail::Box::Threads
       Mail::Box::Locker

   All classes are written to be extendible.  The most complicated work is
done in MIME::Entity, which is written and maintained by Eryq
(eryq@zeegee.com).

METHODS
=======

new ARGS
     (class method) Create a new folder folder-manager.  This constructor
     may carry the following options:

        * folder_types => [ NAME => CLASS [,OPTIONS] ]

        * folder_types => [ [ NAME => CLASS [,OPTIONS] ], [...] ]

          Add one or more folder_types to the list of known types.  The
          order is important: when you open a file without specifying its
          type, the manager will start trying the last added set of types,
          with precedence for the first of that list.

          You may specify folder-specific defaults as OPTIONS.  They
          overrule the settings of the manager.

        * default_folder_type => NAME|CLASS

          When a new folder is created, it is of this type.  If this
          option is not specified, the most recently registered type is
          used (see registerType and the `folder_types'-option.

        * folderdir => DIRECTORY

        * folderdirs => [ DIRECTORY, ... ]

          The default directory, respectively directories, where folders
          are located.  Mail::Box::Manager can autodetect the existing
          folder-types.  There may be different kinds of folders opened at
          the same time, and messages can be moved between those types,
          although that may result in a loss of information.

registerType TYPE => CLASS [,OPTIONS]
     With registerType you can register one TYPE of folders.  The CLASS is
     compiled immediately, so you do not need to use them in your own
     modules.  The TYPE is just an arbitrary name.

     The added types are put in front of the known types, so are checked
     first when a folder is opened in autodetect mode.

     Example:

          $manager->registerType(mbox => 'Mail::Box::Mbox',
             save_on_exit => 0, folderdir => '/tmp');

folderTypes
     The folderTypes returns the list of currently defined types.

     Example:

          print join("\n", $manager->folderTypes), "\n";

open ARGS
     Open a folder.  The folder-type is autodetected unless the type is
     specified.  open carries options for the manager, which are described
     here, but may have additional options for each type of folders.  See
     the options to the constructor (the new method) for each type of
     mail-box, but first the new of `Mail::Box' for the general options.

     The options which are most common to open():

        * folder => FOLDERNAME

          Which folder to open.  The default folder is $ENV{MAIL}.

        * folderdir => DIRECTORY

          The directory where the folders are usually stored.

        * type => FOLDERTYPENAME|FOLDERTYPE

          Specify that the folder is of a specific type.  When you do not
          specify this and you open the folder for ready, it checks all
          registered folder-types for the ability to open the folder.  If
          you open a new folder to write, then the default will be the
          most recently registered type (if you add more than one type at
          once, the first of the list is taken).

          Examples:

               $manager->open(folder => '=jack', type => 'mbox');
               $manager->open(type => 'Mail::Box::Mbox');

        * create => BOOL

          Create the folder when it does not exist.  By default, this is
          not done.  The type-option specifies which type of folder is
          created.

addOpenFolder FOLDER
openFolders
     As could be expected from the name, addOpenFolder adds a new folder to
     set of open folders.  Ignores undefined value for FOLDER.
     openFolders returns a list of all open folders.

close FOLDER
closeAllFolders
     close removes the specified folder from the list of open folders.
     Indirectly it will update the files on disk if needed (depends on the
     `save_on_exit' flag to each seperate folder).

     You may also close the folder directly.  The manager will be informed
     about this event.

     Examples:

          my $inbox = $mgr->open('inbox');
          $mgr->close($inbox);
          $inbox->close;        # alternative

     closeAllFolders calls close for each folder managed by this object.

appendMessage FOLDER|FOLDERNAME, MESSAGES, OPTIONS
     Append one or more messages to a folder.  As first argument, you may
     specify a FOLDERNAME or an opened folder.  When the name is that of
     an opened folder, is it treated as if the folder-structure was
     specified.

     When a message is added to an opened folder, it is only added to the
     structure internally in the program.  The data will not be written to
     disk until a write of that folder takes place.  When the name of an
     unopened folder is given, data message data is immediately stored on
     disk.

     A message must be an instance of an MIME::Entity.  The actual type
     may be in conflict with the requirements for the folder-type where
     the data is added.  However, this is not a concern of the caller: the
     folders will try to resolve the differences with minimal loss of
     information.

     The OPTIONS is a list of key-values, which are added to (overruling)
     the default options for the detected folder-type.

     Examples:

          $mgr->appendMessage('=send', $message, folderdir => '/');
          $mgr->appendMessage('=received', $inbox->messages);

delete FOLDERNAME [,OPTIONS]
     Remove the named folder, including all its sub-folders.  The OPTIONS
     are those of open().

     To accomplish a full removal, all folders have to be opened first,
     while Mail::Box messages may have parts of them stored in external
     files, which must be removed too.

AUTHOR
======

   Mark Overmeer (`Mark@Overmeer.net').  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

VERSION
=======

   This code is beta, version 1.100

Handle folders with many messages per file.
*******************************************

NAME
====

   Mail::Box::Mbox - Handle folders with many messages per file.

SYNOPSIS
========

     use Mail::Box::Mbox;
     my $folder = new Mail::Box::Mbox folder => $ENV{MAIL}, ...;

DESCRIPTION
===========

   This manual-page describes Mail::Box::Mbox and Mail::Box::Mbox::*
packages.  Read Mail::Box::Manager and Mail::Box first.

How Mbox-folders work
---------------------

   Mbox folders store many messages in one file (let's call this a
`file-based' folder, in contrary to a `directory-based' foldertype like
MH).

   In file-based folders, each message is preceeded by a line which starts
with the word `From '.  Lines inside a message which do accedentally start
with From are, in the file, preceeded by `>'.  This character is stripped
when the message is read.

   The name of a folder may be an absolute or relative path.  You can also
preceed the foldername by =, which means that it is relative to the
folderdir as specified at new.

Simulation of sub-folders
-------------------------

   File-based folders do not really have a sub-folder idea, as
directory-based folders have, but this module tries to simulate them.  In
this implementation a directory like

     Mail/subject1/

   is taken as an empty folder `Mail/subject1', with the folders in that
directory as sub-folders for it.  You may also use

     Mail/subject1
     Mail/subject1.d/

   where `Mail/subject1' is the folder, and the folders in the
`Mail/subject1.d' directory are used as sub-folders.  If your situation is
as in the first example and you want to put messages in that empty folder,
the directory is automatically renamed, such that the second situation is
reached.

   Because of these simulated sub-folders, the folder-manager does not
need to distiguish between file- and directory-based folders in this
respect.

METHODS
=======

new ARGS
     Create a new folder.  Many options are taken from object-classes which
     Mail::Box::Mbox is an extention of.  Read below for a detailed
     description of Mbox specific options.

          access            Mail::Box          'r'
          create            Mail::Box          0
          dummy_type        Mail::Box::Threads 'Mail::Box::Thread::Dummy'
          folder            Mail::Box          $ENV{MAIL}
          folderdir         Mail::Box          $ENV{HOME}.'/Mail'
          lazy_extract      Mail::Box          10kb
          lockfile          Mail::Box::Locker  foldername.lock-extention
          lock_extention    Mail::Box::Mbox    '.lock'
          lock_method       Mail::Box::Locker  'dotlock'
          lock_timeout      Mail::Box::Locker  1 hour
          lock_wait         Mail::Box::Locker  10 seconds
          manager           Mail::Box          undef
          message_type      Mail::Box          'Mail::Box::Mbox::Message'
          notreadhead_type  Mail::Box          'Mail::Box::Message::NotReadHead'
          notread_type      Mail::Box          'Mail::Box::Mbox::NotParsed'
          realhead_type     Mail::Box          'MIME::Head'
          remove_when_empty Mail::Box          1
          save_on_exit      Mail::Box          1
          subfolder_extention Mail::Box::Mbox  '.d'
          take_headers      Mail::Box          <quite some>
          thread_body       Mail::Box::Threads 0
          thread_timespan   Mail::Box::Threads <not used>
          thread_window     Mail::Box::Threads <not used>
          <none>            Mail::Box::Tie

     Mbox specific options:

        * lock_extention => FILENAME|STRING

          When the dotlock locking mechanism is used, the lock is created
          by the creation of a file.  For Mail::Box::Mbox type of folders,
          this file is by default named as the folder-file itself,
          followed by `.lock'.

          You may specify an absolute filename, a relative (to the folder's
          directory) name, or an extention (preceeded by a dot).  So valid
          examples are:

               .lock                  # append to filename
               my_own_lockfile.test   # full filename, same dir
               /etc/passwd            # somewhere else

        * subfolder_extention => STRING

          Mail folders which store their messages in files do usually not
          support sub-folders, as known by mail folders which store
          messages in a directory.

          However, we simulate sub-directories if the user wants us to.
          When a subfolder of folder `xyz' is created, we create a
          directory which is called `xyz.d' to contain them.  This
          extention `.d' can be changed using this option.

fileOpen
fileIsOpen
fileClose
     Open/close the file which keeps the folder.  If the folder is already
     open, it will not be opened again.  This method will maintain
     exclusive locking.  Of course, fileIsOpen only checks if the file is
     opened or not.

     Example:

          my $file = $folder->fileOpen or die;
          $folder->fileClose;

readMessages
     Read all messages from the folder.  This method is called at
     instantiation of the folder, so do not call it yourself unless you
     have a very good reason.

write
     Write all messages to the folder-file.  Returns the folder when this
     was successful.  If you want to write to a different file, you first
     create a new folder, then move the messages, and then write that
     file. As options you may specify (see `Mail::Box' for explanation)

        * keep_deleted => BOOL

        * save_deleted => BOOL

        * remove_when_empty => BOOL

addMessage MESSAGE
     Add a message to the Mbox-folder.  If you specify a message with an
     id which is already in the folder, the message will be ignored.

appendMessages OPTIONS
     (Class method) Append one or more messages to a folder.  The folder
     will not be read, but messages are just appended to the folder-file.
     This also means that double messages can exist in a folder.

     If the folder does not exist, undef (or FALSE) is returned.

        * folder => FOLDERNAME

        * message => MESSAGE

        * messages => ARRAY-OF-MESSAGES

     Example:

          my $message = Mail::Internet->new(...);
          Mail::Box::Mbox->appendMessages
            ( folder    => '=xyz'
            , message   => $message
            , folderdir => $ENV{FOLDERS}
            );

filename
     Returns the filename related to this folder.

     Example:

          print $folder->filename;

folderToFilename FOLDERNAME, FOLDERDIR, EXTENTION
     (class method)  Translate a foldername into a filename, with use of
     the FOLDERDIR to replace a leading =.

folder management methods
-------------------------

   Read the Mail::Box manual for more details and more options on each
method.

foundIn FOLDERNAME [,OPTIONS]
     Autodetect if there is a Mail::Box::Mbox folder specified here.  The
     FOLDERNAME specifies the name of the folder, as is specified by the
     application.  ARGS is a reference to a hash with extra information on
     the request.  For this class, we use (if defined):

        * folderdir => DIRECTORY

        * subfolder_extention => STRING

     Example:

          Mail::Box::Mbox->foundIn
             ( '=markov'
             , folderdir => "$ENV{HOME}/Mail"
             );

create FOLDERNAME [, OPTIONS]
     (Class method) Create a folder.  If the folder already exists, it will
     be left untouched.  As options, you may specify:

        * folderdir => DIRECTORY

listFolders [OPTIONS]
     (Class OR Instance method) List the folders in a certain directory.
     This method can be called on the class, in which case you specify the
     base folder where the sub-folders must be retreived from as name.
     When used on an instance, the sub-folders of the instance are
     returned.

     Folders will not start with a dot.  When a directory without the
     sub-folder extention is found, then an empty folder is presumed.

        * folder => FOLDERNAME

        * folderdir => DIRECTORY

        * check => BOOL

        * skip_empty => BOOL

        * subfolder_extention => STRING

openSubFolder NAME [,OPTIONS]
     Open (or create, if it does not exist yet) a new subfolder to an
     existing folder.

     Example:

          my $folder = Mail::Box::Mbox->new(folder => '=Inbox');
          my $sub    = $folder->openSubFolder('read');

          =cut

     sub openSubFolder($@) {   my ($self, $name) = (shift, shift);
     $self->clone(folder => $self->name . '/' .$name, @_); }

AUTHOR
======

   Mark Overmeer (`Mark@Overmeer.net').  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

VERSION
=======

   This code is beta, version 1.100

a message in a Mbox folder
**************************

NAME
====

   Mail::Box::Mbox::Message - a message in a Mbox folder

SYNOPSIS
========

     my $folder  = new Mail::Box::Mbox folder => $ENV{MAIL}, ...;
     my $message = $folder->message(0);

DESCRIPTION
===========

   This manual-page describes the classes `Mail::Box::Mbox::Message',
`Mail::Box::Mbox::Parsed', and `Mail::Box::Mbox::NotParsed'.  These
objects are used to store messages which are not totally read, fully read,
or to be written to a Mail/Box/Mbox, type of folder.

   During its life, a message will pass through certain stages.  These
stages were introduced to reduce the access-time to the folder.  Changing
from stage, the message changes from object-class (try to do this in any
other language than Perl!).

   All information which is required during the full life-span of the
message is stored in a `Mail::Box::Mbox::Message', which is extended by the
`Mail::Box::Mbox::NotParsed' and the `Mail::Box::Mbox::Message::Parsed'.
The last object (`Mail::Box::Mbox::NotReadHead') maintains some
header-lines of the message.

   The bottom of this page provides more `details about the
implementation|' in this node, but first the use.

CLASS Mail::Box::Mbox::Message
==============================

   This object contains methods which are part of as well delay-loaded
(not-parsed) as loaded messages, but not general for all folders.

METHODS
-------

new ARGS
     Messages in file-based folders use the following extra options for
     creation:

        * from LINE

          The line which precedes each message in the file.  Some people
          detest this line, but this is just how things were invented...

fromLine [LINE]
     Many people detest file-style folders because they store messages all
     in one file, where a line starting with `From ' leads the header.  If
     we receive a message from a file-based folder, we store that line.
     If we write to such a file, but there is no such line stored, then we
     try to produce one.

     When you pass a LINE, that this is stored.

print FILEHANDLE
     Write one message to a file-handle.  Unmodified messages are taken
     from the folder-file where they were stored in.  Modified messages
     are written as in memory.  Specify a FILEHANDLE to write to (defaults
     to STDOUT).

migrate FILEHANDLE
     Move the message from the current folder, to a new folder-file.  The
     old location should be not used after this.

CLASS Mail::Box::Mbox::Parsed
=============================

   This object extends a `Mail::Box::Message::Parsed' with extra tools and
facts on what is special to messages in file-based folders, with respect
to messages in other types of folders.

METHODS
-------

coerce FOLDER, MESSAGE [,OPTIONS]
     (Class method) Coerce a MESSAGE into a `Mail::Box::Mbox::Parsed'.
     When any message is offered to be stored in a mbox FOLDER, it first
     should have all fields which are specific for Mbox-folders.

     The coerced message is returned on success, else undef.

     Example:

          my $inbox = Mail::Box::Mbox->new(...);
          my $mh    = Mail::Box::MH::Message->new(...);
          Mail::Box::Mbox::Parsed->coerce($inbox, $mh);
          # Now, the $mh is ready to be included in $inbox.

     However, you can better use

          $inbox->coerce($mh);

     which will call the right coerce() for sure.

CLASS Mail::Box::Mbox::NotParsed
================================

   Not parsed messages stay in the file until the message is used.  Because
this folder structure uses many messages in the same file, the
byte-locations are remembered.

METHODS
-------

load
     This method is called by the autoloader then the data of the message
     is required.  If you specified REAL for the `take_headers' option for
     new(), you did have a MIME::Head in your hands, however this will be
     destroyed when the whole message is loaded.

IMPLEMENTATION
==============

   The user of a folder gets his hand on a message-object, and is not
bothered with the actual data which is stored in the object at that
moment.  As implementor of a mail-package, you might be.

   A message is simple to use, but has a quite complex class structure.  A
message is not a real message from the start, but only when you access the
body of it.  Before that, a hollow placeholder is used.  Below is depicted
how the internal structure of a message-object changes based on actions on
the object and parameters.

   The inheritance relation is like this:

     read()
     =====#
          V              load()
     ::Mbox::NotParsed ========> ::Mbox::Parsed
           |       \               /    |
           ^        \             /     ^
           |        ::Mbox::Message     |
           |                            |
        ::Message::NotParsed        ::Message::Parsed
                 \                  /   |
                  ::Message::Message    ^
                           |            |
                           ^       MIME::Entity
                           |            |
                       ::Thread         ^
                                        |
                                    Mail::Internet

   The `Mail::Box::Mbox::Parsed' stage, means that the whole message is in
memory.  It then is a full decendent of a `MIME::Entity'.  But at the same
time, it consumes a considerable amount of memory, and the program has
spent quite some processor time on.  All the intermediate stati are
created to avoid full loading, so to be cheap in memory and time.  Folder
access will be much faster under normal circumstances.

   For trained eyes only the status-transition diagram:

     read()     !lazy
     -------> +----------------------------------> Mail::Box::
              |                                  Mbox::Parsed
              |                                         ^
              |                                         |
              |                    NotParsed    load    |
              |        ALL ,-----> NotReadHead ------>-'|
              | lazy      /                             |
              `--------->+                              |
                          \        NotParsed    load    |
                      REAL `-----> MIME::Head ------->-'

     ,-------------------------+---.
             |                      ALL |   | regexps && taken
             v                          |   |
        NotParsed    head()    get()   /   /
        NotReadHead --------> ------->+---'
         \          \         \
          \ other()  \ other() \regexps && !taken
           \          \         \
            \          \         \    load    Mail::Box::
             `----->----+---------+---------> MBox::Parsed

     ,---------------.
             |                |
             v                |
        NotParsed     head()  |
        MIME::Head -------->--'
        \                           Mail::Box::
         `------------------------> MBox::Parsed

   Terms: lazy refers to the evaluation of the `lazy_extract()' option. The
load and `load_head' are triggers to the AUTOLOAD mothods.  All terms like
`head()' refer to method-calls.  Finally, ALL, REAL, and `regexps'
(default) refer to values of the `take_headers' option of new().

   Hm... not that easy...  but relatively simple compared to MH-folder
messages.

AUTHOR
======

   Mark Overmeer (`Mark@Overmeer.net').  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

VERSION
=======

   This code is beta, version 1.100

Manage one message within a mail-folder
***************************************

NAME
====

   Mail::Box::Message - Manage one message within a mail-folder

SYNOPSIS
========

     # Usually these message objects are created indirectly
     use Mail::Box::Message;
     my $folder = new Mail::Box::Mbox folder => ...;
     my $msg    = $folder->message(1);
     $msg->delete;
     $msg->size;   # and much more

DESCRIPTION
===========

   These pages do only describe methods which relate to folders.  If you
access the knowledge of a message, then read `MIME::Entity'.

   Read Mail/Box/Manager, first.  This page also
describes `Mail::Box::Message::Parsed', Mail::Box::Message::NotParsed,
`Mail::Box::Message::NotReadHead', and `Mail::Box:Message::Dummy'.  These
objects are used as base-classes for messages which are not totally read,
are fully read, or to be written to some kind of folder.

   During its life, a message will pass through certain stages.  These
stages were introduced to reduce the access-time to the folder.  Changing
from stage, the message changes from object-class (try to do this in any
other language than Perl!).

Classes described in this manual-page
-------------------------------------

   This page handles three types of messages:

   * Mail::Box::Message::Parsed

     A read message.  This is a full decendent of MIME::Entity, with all
     information on the message and its parts stored in easily and fast
     accessible memory-structures.

   * Mail::Box::Message::NotParsed

     This is a nearly ready-to-go message.  When scanning a folder, the
     `lazy_extract' parameter of `Mail::Box::new' determines which
     messages are directly parsed into a Mail::Box::Message, and which are
     not yet parsed.

     Messages which are not directly parsed into a real message object are
     stored as an Mail::Box::Message::NotParsed object.  This object only
     contains a few important header-lines, and triggers to load the
     message for real on the moment other information on this message is
     needed.

     Which header-lines are taken is determined by the `take_headers'
     parameter of `Mail::Box::new'.  Taking too few headers for your task
     will result in bad performance: all message will be read.  When you
     take too many headers, this is bad for the memory usage of your
     program.

   * Mail::Box::Message::Dummy

     A message which is a place-holder in a thread description.  This
     object-type is used to fill holes in the linked list of thread
     messages.  See Mail/Box/Threads.

   Two more classes are defined, to help the message-types to function
properly:

   * Mail::Box::Message

     Data and functionality which is not stored in the folder, but is
     shared by various message-types (a real-message, a dummy, and a
     not-parsed)

   * Mail::Box::Message::NotReadHead

     A header which is part of a Mail::Box::Message::NotParsed.  It
     contains some header-lines, but far from all.  It can trigger the
     not-parsed to load itself from the folder.

   The bottom of this page provides more `details about the
implementation|' in this node, but first the use.

CLASS Mail::Box::Message
========================

   This class is a base for all kinds of messages.  It defines the
simularities between messages in various stages: dummy, not-parsed, or
parsed.

new ARGS
     Initialize the runtime variables of a message.  The following options
     are supported:

        * folder => FOLDER

          (obligatory) The folder where this message appeared in.  The
          argument is an instance of (a sub-class of) a Mail::Box.

        * size => INTEGER

          The size of the message inclusive headers and accompanying lines
          (such as the `From' line in mboxes) in bytes.

        * messageID => STRING

          The id on which this message can be recognized.  If none
          specified, there will be one assigned to the message to be able
          to pass unique message-ids between objects.

        * modified => BOOL

          Whether there are some modifications to the message from the
          start-on.  For instance, new message will be flagged modified
          immediately.

        * deleted => BOOL

          Is the file deleted from the start?

        * labels => [ STRING => VALUE, ... ]

          Set the specified labels to their accompanying value.  In most
          cases, this value will only be used as boolean, but it might be
          more complex.

messageID
     Retreive the message's id.  Every message has a unique message-id.
     This id is used mainly for recognizing discussion threads.

folder [FOLDER]
     In with folder did we detect this message/dummy?  This is a reference
     to the folder-object.

size
     Returns the size of the message, including headers.

     Example:

          print $folder->message(8)->size;

isParsed
     isParsed checks whether the message is parsed (read from file).
     Returns true or false.  Only a Mail::Box::Message::Parsed will return
     true.

isDummy
     isDummy Checks whether the message is only found in a thread, but not
     (yet) in the folder.  Only a `Mail::Box::Message::Dummy' will return
     true.

headIsRead
     Checks if the head of the message is read.  This is true for fully
     parsed messages and messages where the header was accessed once.

modified [BOOL]
     Check (or set, when an argument is supplied) that the
     message-contents has been changed by the program.  This is used
     later, when the messages are written back to file.

     Examples:

          if($message->modified) {...}
          $message->modified(1);

delete
     Flag the message to be deleted.  The real deletion only takes place on
     a synchronization of the folder.

     Examples:

          $message->delete;
          delete $message;

deleted [BOOL]
     Check or set the deleted flag for this message.  This method returns
     undef (not deleted, false) or the time of deletion (true).  With a
     BOOL argument, the status is changed first.

     Examples:

          if($message->deleted) {...}
          $message->deleted(0);        # undelete

seqnr [INTEGER]
     Get (add set) the number of this message is the current folder.

timestamp
     Returns an indication on the moment that the message was originally
     sent.  The exact value which is returned is operating-system
     dependent, but on UNIX systems will be in seconds since 1 January
     1970.

Label management
----------------

   Labels are used to store knowledge about handling of the message within
the folder.  Flags about whether a message was read, replied to, or (in
some cases) scheduled for deletion.

setLabel LIST
label STRING [ ,STRING ,...]
     Get the value related to the label(s).  This returns a list of
     values, which may be empty, undefined, or a value which evaluates to
     TRUE.

     Example:

          if($message->label('seen')) {...}
          my ($seen, $current) = $msg->label('seen', 'current');

labels
     Returns all known labels.  In SCALAR context, it returns the knowledge
     as reference to a hash.  This is a reference to the original data, but
     you shall *not* change that data directly: call `setLabel()' for
     changes!

     In LIST context, you get a list of names which are defined.  Be warned
     that they will not all evaluate to true, although most of them will.

shortString
     Convert the message header to a short string, representing the most
     important facts (for debugging purposes only).

diskDelete
     Remove a message from disk.  This is not from the folder, but
     everything else, like parts of the message which are stored
     externally from the folder.

CLASS Mail::Box::Message::Parsed
================================

   This object extends a MIME::Entity.  This is the only object type
defined in this set of packages which represents a real message (which
parsed into memory, with access to all headers, and writeable)

METHODS
-------

new [OPTIONS]
     Create a new message.  The options available are taken from
     `Mail::Box::Message::new()', as described above.

     If you want to add a message to a folder, which is derived from some
     strange source, then you do:

          use MIME::Parser;
          my $parser = MIME::Parser->new;
          my $entity = $parser->parse(@lines);
          $folder->addMessage($entity);

     The `addMessage()' accepts anything what is based on Mail::Internet.

coerce FOLDER, MESSAGE [,OPTIONS]
     (Class method) Coerce a MESSAGE into a Mail::Box::Message::Parsed.
     This method is automatically called if you add a strange message-type
     to a FOLDER.  You usually do not need to call this yourself.

     The coerced message is returned on success, else undef.

     Example:

          my $folder = Mail::Box::Mbox->new;
          my $entity = MIME::Entity->new(...);
          Mail::Box::MBox::Message::Parsed->coerce($inbox, $entity);
          # now $entity is a Mail::Box::Mbox::Message::Parsed

     It better to use

          $folder->coerce($entity);

     which does exacty the same, by calling coerce in the right package.

forceLoad
     This method is called to signal that the message must be loaded,
     although the method only returns the folder.

body
     Call body to get the whole message-body in storable message format
     (multiparts are folded back into one message).  This may be useful to
     print the whole message.  If you want to access the message content,
     you should used `' in this node or `' in this node which are
     described below.

bodyhandle
     Some messages are multi-parts, other are plain.  Check which type of
     message you have (with is_multipart as described in MIME::Entity)
     before accessing its content.

     If the parsing of the folder was delayed (controlled by the
     `lazy_extract' option at folder-creation) this implies that the
     message-body is read from folder and parsed.  This is performed
     automatically.

     If you do not have a multipart message, you call bodyhandle, which
     returns a handle to a handle-type object which can be opened to read
     the body of the message.

     Example:

          sub print_body($)
          {   my ($self,$message) = @_;
              if($message->is_multipart)
                   { $self->print_body($_)
                         foreach $message->parts }
              else { $message->bodyhandle->print }
          }

parts [ARRAY]
     Some messages are multi-parts, other are plain.  Check which type of
     message you have (with is_multipart as described in MIME::Entity)
     before accessing its content.

     If the parsing of the folder was delayed (controlled by the
     `lazy_extract' option at folder-creation) this implies that the
     message-body is read from folder and parsed.  This is performed
     automatically.

     When you do have a multipart message, you have to call parts to get a
     list of Mail::Box::Message::Parsed objects, each representing one
     part of the message.  Be warned that even such part can be split in
     nested parts.  You can pass an array-reference with messages to set a
     new list of parts.

     See `' in this node and `' in this node above.

removePart PART|INDEX
     Remove one part of the list of parts from this message.  Specify a
     PART (Mail::Box::Message::Parsed instance) or an index
     (sequence-number is list of parts)

isPart
     A part of a message is of the same type as the message itself.  This
     call can distinguish between the two.

Mail::Box::Message::NotParsed
=============================

   A message where most of the data still resides in the folder-file, is a
'message which is not read' (yet).  This status is signalled by the type
of the object.

METHODS
-------

new ARGS
     Create a not-parsed message.  The message can have a `not-read-head',
     which means that only a few of the header-lines are kept, or a real
     MIME::Head to start with.

AUTOLOAD
     When any method is called which can not be performed without parsing
     the whole folder message, Perl calls the autoloader.  A check is
     performed to see if not anyone has accidentally an old
     message-handle: we may otherwise read the message twice.

head
     This function returns a Mail::Box::Message::NotReadHead object on
     which you may perform any actions as expected from MIME::Header
     object.  Performing actions on a header which is part of a non-parsed
     message is complicated by the fact that we have some header-lines,
     but not all.

     See `' in this node below.

CLASS Mail::Box::Message::Dummy
===============================

   A dummy message is a placeholder, for instance for messages in threads
which are found in a reference-list, but not (yet) in the folder.

new
     (Class method) Create a new dummy message.

     Examples:

          my $message = Mail::Box::Message::Dummy->new($msgid);
          if($message->isDummy) {...}

CLASS Mail::Box::Message::NotReadHead
=====================================

   This object contains a few header-lines which were captured during the
initial reading of the folder.  It will also automagically load the
messages on any other call to head.

METHODS
-------

   See `MIME::Header' in this node for all methods you can perform on this
object.  The following methods need extra consideration.

new ARGS
     (Class method)  Called by the Mail::Box::Message::NotParsed method
     new to store some header-lines which were capurtured during the
     initial reading through the folder file.  See the `take_headers'
     option on how to add header-lines to this structure.

     The following parameters can be passed to new:

        * expect FIELDNAMES

          (obligatory) Which fields will be taken from the folder-file.
          Even when we do not actually find all these fields, we still
          have to know when the message lacks the field, to avoid that the
          message is read from the folder to find-out that the line isn't
          there either.

get TAG [, INDEX]
get_all TAG
count TAG
     Overruled methods, which first check if we know about the header.  In
     case we do, the values can be returned immediately.  Otherwise we
     trigger the message to be read from the folder-file and then retry on
     the real Mail::Box::Message::Parsed object.

setField NAME, CONTENT
     Store a content into a field.  Do only specify fields which are
     defined with expect when this object was instantiated.

     You may add the same name more than once.  In that case, the get
     method in list context (and the get_all method) will return all
     definition in the order that they were added.  For the `Received:'
     field in messages, that means that the most recently added line to
     the message is put first in the list (they are in reverse order in
     the mime-header.

message [MESSAGE]
     Get (or check) the message to which this header belongs.

AUTOLOAD
     Load the message, then capture the real header, and finally calls the
     method on the what should have been called in the first place.

     Example:

          $message->head->get('some-field')

     where $message is a Mail::Box::Message::NotParsed, will return a
     `Mail::Box::Message::NotReadHead' from its head call.  A get of a
     previously captured header returns the right value, however in case
     not, the following steps are taken:

        * get calls AUTOLOAD to get a new header.

        * `NotReadHead::AUTOLOAD' will call `NotParsed::AUTOLOAD' to read
          the message.

        * `NotParsed::AUTOLOAD' reads the message from the folder and
          returns it to the header autoloader.

        * The header autoloader calls the real get method of the
          `Mail::Box::Message::Parsed', as autoloaders should do.

IMPLEMENTATION
==============

Extending MIME::Entity
----------------------

   Because reading MIME::Entity objects from file is quite time-consuming
and memory flooding, this module actively tries to keep most messages in
the folder-files where they are stored in un-parsed form.  When a folder
is opened, only some of the header-lines of the messages are taken and
stored in objects.  Not before the message is seriously used, the message
is translated into a real MIME::Entity.

Delayed loading of messages
---------------------------

   When a folder is read, the `lazy_extract' option to `Mail::Box::new'
determines if the content of the message is to be parsed immediately into
a Mail::Box::Message::Parsed or should be left unparsed in the folder-file.
In the latter case, a Mail::Box::Message::NotParsed is created.

   Not-parsing messages improves the speed of folder reading, and reduce
the memory footprint of your program considerably.  However, it keeps the
folder-file locked, so should not be used on the incoming messages
mail-box.

   The parsing of a message (reading the non-parsed messages from the
folder file and translating it into Mail::Box::Message::Parsed type
objects) is automatically triggered when you access head-lines which were
not specified in `take_headers' when the folder was read, and when you
call methods which are not defined on a non-parsed message.

State transition
----------------

   Messages are detected when reading a folder, or composed by the user
when it is sent by a used.  The relationships shown below are only about
reading existing folders.

     unknown references
        Mail::Box      and reply-to's        Mail::Box
        finds message -----------------> ::Message::Dummy
              |                                    |
              v messages                           |
              |                                    |
              |                                    |
             / \was dummy                          |
             |  '--------------> merge <-----------'
             |                     |
             |                     |
             \new                  |
              `-->-----,  ,-----<--'
     lazy
                     extract?
                  yes/       \no
                    /         `--->-------,
                   v                       |
             Mail::Box                     |
         ::Message::NotParsed              |
                   |                       v
                   |serious use         Mail::Box
                    `---------->-- ::Message::Parsed

Class structure for messages
----------------------------

   As example, the next scheme uses the fake folder-type `XYZ', which may
be for instance mbox or `MH'.

     ::XYZ::Parsed              ::XYZ::NotParsed
        |      \                /         |
        |       \              /          |
        ^        ::XYZ::Message           ^
        |                                 |
        |                                 |
          ::Message    ::Message::Dummy    ::Message
           ::Parsed            |          ::NotParsed
        |    ^          ^           ^
        ^     \         |          /
        |      `--- ::Message ----'
        |               |
          MIME::Entity         ^
        |               |
        ^           ::Thread
        |
          Mail::Internet

AUTHOR
======

   Mark Overmeer (`Mark@Overmeer.net').  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

VERSION
=======

   This code is beta, version 1.100

one discussion thread in a folder
*********************************

NAME
====

   Mail::Box::Thread - one discussion thread in a folder

SYNOPSIS
========

     my $thread = $message->thread;
     $thread->printThread;

DESCRIPTION
===========

   Read Mail/Box/Manager, and
Mail/Box/Threads, first.

   A (message-)thread is a message, with the messages which followed in
reply on that message.  And the messages with replied the messages which
replied the original message.  And so on.  Some threads are only one
message (never replied to), some threads are very long.

Mail::Box::Thread
=================

new ARGS
     The instatiation of a thread is done by its subclasses.  You will not
     call this method by yourself (it is even not implemented).

     In the current implementation, there are no options added to the
     `Mail::Box::Message''s object creation.

thread
     Returns the first message in the thread where this message is part
     of.  This may be this message itself.  This also may return any other
     message in the folder.  Even a dummy message can be returned, when the
     first message in the thread was not stored in the folder.

     Example:

          my $start = $folder->message(42)->thread;

inThread
     Include the message in a thread.  If the message was not known to the
     thread-administration yet, it will be added to those structures.

repliedTo
     Returns the message where this one is a reply to.  In SCALAR context,
     this will return the MESSAGE which was replied to by this one.  This
     message object may be a dummy message. In case the message seems to
     be the first message of a thread, the value undef is returned.

     In LIST context, this method also returns how sure these are messages
     are related.  When extended thread discovery in enabled, then some
     magic is applied to relate messages.  In LIST context, the first
     returned argment is a MESSAGE, and the second a STRING constant.
     Values for the STRING may be:

        * 'REPLY'

          This relation was directly derived from an `in-reply-to' message
          header field.  The relation is very sure.

        * 'REFERENCE'

          This relation is based on information found in a `Reference'
          message header field.  One message may reference a list of
          messages which precede it in the thread.  Let's hope they are
          stored in the right order.

        * 'GUESS'

          The relation is a big guess, of undetermined type.

     More constants may be added later.

     Examples:

          my $question = $answer->repliedTo;
          my ($question, $quality) = $answer->repliedTo;
          if($question && $quality eq 'REPLY') { ... };

follows MESSAGE|MESSAGE-ID, STRING
     Register that the specified MESSAGE (or MESSAGE-ID) is a reply on this
     message, where the quality of the relation is specified by the
     constant STRING.

     The relation may be specified more than once, but there can be only
     one.  Once a reply (STRING equals REPLY) is detected, that value will
     be kept.

followedBy [MESSAGE-ID|MESSAGE, ...]
     Register that the MESSAGEs (or MESSAGE-IDs) are follow-ups to this
     message.  There may be more than one of these follow-ups which are
     not related to each-other in any other way than sharing the same
     parent.

     If the same relation is defined more than ones, this will not cause
     duplication of information.

followUps
     Returns the list of follow-ups to this message.  This list contains
     parsed, not-parsed, and dummy messages.  followUps returns
     MESSAGE-objects, while `followUpIDs' returns the IDs only.

threadFilled [BOOL]
     Returns (after setting) a flag whether the thread (where this message
     is the start of) is fully processed in finding holes.  If this is set
     on TRUE, than any dummies still in this thread could not be found
     within the limits of `thread_window' and `thread_timespan'.

Actions on whole threads
------------------------

   Some conveniance methods are added to threads, to simplify retreiving
knowledge from it.

recurseThread CODE-REF
     Execute a function for all sub-threads.  If the subroutine returns
     true, sub-threads are visited, too.  Otherwise, this branch is
     aborted.

totalSize
     Sum the size of all the messages in the thread.

nrMessages
     Number of messages in this thread.

ids
     Collect all the ids in this thread.

     Examples:

          $newfolder->addMessages($folder->ids($thread->ids));
          $folder->delete($thread->ids);

folded [BOOL]
     Returns whether this (part of the) folder has to be shown folded or
     not.  This is simply done by a label, which means that most
     folder-types can store this.

threadToString
     Translate a thread into a string.  The string will contain at least
     one line for each message which was found, but tries to fold dummies.
     This is useful for debugging, but most message-readers will prefer to
     implement their own thread printer.

     Example:

          print $message->threadToString;

     may result in

          Subject of this message
          |- Re: Subject of this message
          |-*- Re: Re: Subject of this message
          | |- Re(2) Subject of this message
          | |- [3] Re(2) Subject of this message
          | `- Re: Subject of this message (reply)
          `- Re: Subject of this message

     The `*' represents a lacking message.  The `[3]' presents a folded
     thread with three messages.

AUTHOR
======

   Mark Overmeer (`Mark@Overmeer.net').  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

VERSION
=======

   This code is beta, version 1.100

maintain threads within a folder
********************************

NAME
====

   Mail::Box::Threads - maintain threads within a folder

SYNOPSIS
========

     my Mail::Box $folder = ...;
     foreach my $thread ($folder->threads)
     {   $thread->printThread;
     }

DESCRIPTION
===========

   Read Mail/Box/Manager, and Mail/Box,
first.  It might be helpfull to study Mail/Box/Thread,
too.

   A (message-)thread is a message, with the messages which followed in
reply on that message.  And the messages with replied the messages which
replied the original message.  And so on.  Some threads are only one
message (never replied to), some threads are very long.

METHODS
=======

new ARGS
     `Mail::Box::Threads' is sub-classed always by `Mail::Box'.  This
     object is not meant to be instantiated itself: do not call new on it
     (you'll see it even fails because there is no new()!).

     The construction of thread administration accepts the following
     options:

        * dummy_type => CLASS

          Of which class are dummy messages?  Usually, this is the basic
          dummy type, `Mail::Box::Message::Dummy' in this node, unless you
          intend to extend the object.

        * thread_window => INTEGER|'ALL'

          The thread-window describes how many messages should be checked
          at maximum to fill `holes' in threads for folder which use
          delay-loading of message headers.  The default value is 10.

          The constant 'ALL' will cause thread-detection not to stop trying
          to fill holes, but continue looking until the first message of
          the folder is reached.  Gives the best quality results, but may
          perform bad.

        * thread_timespan => TIME|'EVER'

          Specify how fast threads usually work: the amount of time
          between an answer and a reply.  This is used in combination with
          the `thread_window' option to determine when to give-up filling
          the holes in threads.

          TIME is a string, which starts with a float, and then one of the
          words 'hour', 'hours', 'day', 'days', 'week', or 'weeks'.  For
          instance:

               thread_timespan => '1 hour'
               thread_timespan => '4 weeks'

          The default is '3 days'.  TIME may also be the string 'EVER',
          which will effectively remove this limit.

        * thread_body => BOOL

          May thread-detection be based on the content of a message?  This
          has a serious performance implication when there are many
          messages without `In-Reply-To' and References headers in the
          folder, because it will cause many messages to be parsed.

          NOT USED YET.  Defaults to FALSE.

toBeThreaded MESSAGE [, ...]
toBeUnthreaded MESSAGE-ID [, ...]
     Register a message to be put in (withdrawn from) a thread when the
     user is asking for threads.  If no-one ever asks for threads, then no
     work is done on them.

createDummy MESSAGE-ID
     Create a dummy message for this folder.  The dummy is a place-holder
     in a thread description to represent a message which is not found in
     the folder (yet).

processDelayedThreading
     Parse all messages which where detected in the folder, but were not
     processed into a thread yet.

thread MESSAGE
     Based on a message, and facts from previously detected threads, try
     to build solid knowledge about the thread where this message is in.

inThread MESSAGE
     Collect the thread-information of one message.  The `In-Reply-To' and
     `Reference' header-fields are processed.  If this method is called on
     a message whose header was not read yet (as usual for MH-folders, for
     instance) the reading of that header will be triggered here.

     Examples:

          $folder->inThread($message);
          $message->inThread;    #same

outThread MESSAGE-ID
     Remove the message, which is represented by its message-id, from the
     thread-infrastructure.  A message is replaced by a dummy, if it has
     follow-ups.

registerThread MESSAGE|MESSAGE-ID
     Register the message as start of a thread.

threads
     Returns all messages which start a thread.  The list may contain dummy
     messages, and messages which are scheduled for deletion.

     To be able to return all threads, thread construction on each message
     is performed first, which may be slow for some folder-types because
     is will enforce parsing of message-bodies.

knownThreads
     Returns the list of all messages which are known to be the start of a
     thread.  Threads containing messages which where not read from their
     folder (like often happends MH-folder messages) are not yet known, and
     hence will not be returned.

     The list may contain dummy messages, and messages which are scheduled
     for deletion.  Threads are detected based on explicitly calling
     `inThread()' and `thread()' with a messages from the folder.

     Be warned that, each time a message's header is read from the folder,
     the return of the method can change.

IMPLEMENTATION
==============

   This module implements thread-detection on a folder.  Messages created
by the better mailers will include `In-Reply-To' and References lines,
which are used to figure out how messages are related.  If you prefer a
better thread detection, then you can ask for it, but there may be a
serious performance hit (depends on the type of folder used).

Delayed thread detection
------------------------

   With threads you get the start-messages of each thread of this folder.
When that message was not found in the folder (not saved or already
removed), you get a message of the dummy-type.  These thread descriptions
are in perfect state: all messages of the folder are included somewhere,
and each missing message of the threads (`holes') are filled by dummies.

   However, to be able to detect all threads it is required to have the
headers of all messages, which is very slow for some types of folders,
especially MH and IMAP folders.

   For interactive mail-readers, it is prefered to detect threads only on
messages which are in the viewport of the user.  This may be sloppy in
some situations, but everything is preferable over reading an MH mailbox
with 10k e-mails to read only the see most recent messages.

   In this object, we take special care not to cause unnecessary parsing
(loading) of messages.  Threads will only be detected on command, and by
default only the message headers are used.

   The user of the folder signals that a message has to be included in a
thread within the thread-list, by calling

     $folder->inThread($message);   #or
     $message->inThread;

   This only takes the information from this message, and stores this in a
thread-structure.  You can also directly ask for the thread where the
message is in:

     my $thread = $message->thread;

   When the message was not put in a thread, it is done now.  But, more
work is done to return the best thread.  Based on various parameters,
which where specified when the folder was created, the method walks
through the folder to fill the holes which are in this thread.

   Walking from back to front (latest messages are usually in the back of
the folder), message after message are triggered to be indexed in their
thread.  At a certain moment, the whole thread of the requested method is
found, a certain maximum number of messages was tried, but that didn't
help (search window bound reached), or the messages within the folder are
getting too old.  Then the search to complete the thread will end,
although more messages of the could be in the folder.

   Finally, for each message where the head is known, for instance for all
messages in mbox-folders, the correct thread is determined immediately.
Also, all messages where the head get loaded later, are automatically
included.

AUTHOR
======

   Mark Overmeer (`Mark@Overmeer.net').  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

VERSION
=======

   This code is beta, version 1.100

Acces an existing message-folder as array
*****************************************

NAME
====

   Mail::Box::Tie - Acces an existing message-folder as array

SYNOPSIS
========

     tie my @inbox, 'Mail::Box::File', file => $ENV{MAIL};
     tie my @inbox, $folder;

     foreach (@inbox) {print $_->short}
     print $inbox[3];
     push @inbox, Mail::Box::Message->new(...);
     my $folder = tied @inbox;

DESCRIPTION
===========

   Read Mail/Box/Manager, first.  Folders
certainly look as arrays, so why not just access them as one?  Each folder
is a sub-class of this class.

METHODS
=======

   Not all operations on arrays are supported.  Actually, most functions
which would reduce the size of the array are modified to signal messages as
ready for removal.

   Examples of what you can do:

     tie my @inbox, 'Mail::Box::File', ...;
     my $message = new Mail::Box::Message(...);

     push @inbox, $message;
     delete $inbox[2];         # becomes undef
     $inbox[3]   = $message;
     print $inbox[0]->status;
     my $emails  = @inbox;
     untie @inbox;             # calls write()

     # Direct access to the Mail::Box object.
     my $folder = tied @inbox;
     $folder->synchonize;

   Examples what you *cannot* do:

     shift/unshift/pop/splice @inbox;

tie ARRAY, FOLDERTYPE, PARAMS
tie ARRAY, FOLDERTYPE, FOLDER
     There are to ways to construct a tie.  In the first case, you start
     with a tie, and may later ask for the tied folder structure.  In the
     second version, you have first created a folder, and then put a tie
     around it.

     The first version: tie an ARRAY to a folder of type FOLDERTYPE, where
     the constructor of the folder requires some parameters.  Possible
     PARAMS are the parameters of the new constructor of the specified
     folder-type.

     Example:

          tie my(@inbox), 'Mail::Box::File', folder => $ENV{MAIL};
          my $inbox = tied @inbox;

     The second version: tie an ARRAY interface around an existing FOLDER.
     The type as specified with FOLDERTYPE is only used to find the
     correct TIEARRAY method, usually the result of `ref FOLDER'.

     Example:

          my $inbox = Mail::Box::File->new(folder => $ENV{MAIL});
          tie my(@inbox), ref $inbox, $inbox;

IMPLEMENTED METHODS
===================

   This module implements TIEARRAY, FETCH, STORE, FETCHSIZE, DELETE, PUSH,
and DESTROY.

   This module does not implement all other methods as described in the
Tie/Array, manual-page.

AUTHOR
======

   Mark Overmeer (`Mark@Overmeer.net').  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

VERSION
=======

   This code is beta, version 1.100

Platform independent mailing list module
****************************************

NAME
====

   Mail::Bulkmail 2.05 - Platform independent mailing list module

AUTHOR
======

   Jim Thomason thomasoniii@yahoo.com

SYNOPSIS
========

     $bulk = Mail::Bulkmail->new(
               "LIST" => "/home/jim3.list",
               "From" => 'thomasoniii@yahoo.com',
            "Subject" => 'This is a test message!',
            "Message" => "Here is the text of my message!"
     );

     $bulk->bulkmail;

   Be sure to set your default variables in the module, or set them in
each bulk mail object.  Otherwise, you'll be using the defaults.

DESCRIPTION
===========

   Mail::Bulkmail gives a fairly complete set of tools for managing
mass-mailing lists.  I wrote it because our existing tools were just too
damn slow for mailing out to thousands of recipients.

   2.00 is a major major *major* upgrade to the previous version (1.11).
I literally threw out all of the code from 1.00 and started over.  Well,
almost all of it, I'm really content with the email validation, so I kept
that.  :)

   Everything else is brand spanking new.  All of the bugs from the 1.x
releases should be gone (ever try allowing duplicates?  Good.).  And, of
course, a bunch of new toys have been added in.

   The two major additions to v2 are the ability to send via envelope and
support for dynamic messaging.  Sending via the envelope allows you to
potentially transfer your email *much* faster (I've been estimating a 900%
speed increase vs. non-envelope sending in 1.11).  Dynamic messaging
allows you to actually construct the message that you're sending out on
the fly.  Specify which components of a message you want to include, and
Bulkmail will generate the message for you.  So every person on your list
could potentially receive a different message, if you wanted.

   Dynamic messaging is a few steps above a simple mail merge.  While you
could accomplish the same effect using a simple mail merge it wouldn't be
pretty.  You'd have to duplicate each component of the message for each
person on the list.

   Further changes are listed in the version history and FAQ sections
below, I just wanted to mention the big guns up front.

REQUIRES
========

   Perl5.004, Socket

OBJECT METHODS
==============

CREATION
--------

   New Mail::Bulkmail objects are created with the new() constructor.  For
a minimalist creation, do this:

   $bulk = Mail::Bulkmail->new();

   You can also initialize values at creation time, such as:

     $bulk = Mail::Bulkmail->new(
                From => 'thomasoniii@yahoo.com',
                Smtp => 'some.smtp.com'
     );

   When Bulkmail objects are destroyed, they automatically disconnect from
the server they're connected to if they're still connected.

add_attr
     Mail::Bulkmail is much easier to subclass now (I hope).  I like using
     arrays for my objects instead of hashes.  Perhaps one day I'll switch
     to pseudo-hashes, but not yet.

     Until that time, you need to allocate new space in the array for your
     new attributes if you want to subclass the thing.  But how do you do
     that nicely?  Push onto the blessed arrayref?  Too messy, and you
     can't do the nice trick of setting up a variable with the value of
     the place in the array.  Besides, if I do switch away from arrays
     this'll break.  So use add_attr to tack it onto the end of the object.

     package Mail::Bulkmail::My_version;

     @ISA = qw(Mail::Bulkmail);

          my $new_attribute = Mail::Bulkmail->add_attr();

          $my_bulk_object->[$new_attribute] = "my value";

BUILT IN ACCESSORS
------------------

   Okay, here's where the fun stuff beings.  Since these are objects, the
important stuff is how you access your data.

   Object methods work as you probably expect.

   $bulk->property

     Will return the value of "property" in $bulk

   $bulk->property("new value")

   Will set the value of "property" in $bulk to "new value" and return
"new value".  The property may not be set if $bulk->Trusting has a false
value and the property has a validation check on it.  See Validated
Accessors, below.

   All accessor methods are case sensitive.  Be careful!

   Here are all of the accessors that come built in to your Mail::Bulkmail
objects.

From
     The e-mail address this list is coming from.  This can be either a
     simple e-mail address (thomasoniii@yahoo.com), or a name + e-mail
     address ("Jim Thomason"<thomasoniii@yahoo.com>).  This is checked to
     make sure it's a valid email address unless you have Trusting turned
     on (see below).

     *v1.x equivalent*:  From

Subject
     The subject of the e-mail message.  If it's not set, you'll use the
     default.

     *v1.x equivalent*:  Subject

Message
     This is the actual text that will appear in the message body.  You
     can also specify control fields to allow your message to be
     dynamically individually built on the fly, as well as do a mail merge
     to personalize your email to each recipient

     *v1.x equivalent*:  Message

merge
     This is where you define a mail merge for your message.  See the
     section MERGING below.

     A merge is defined with a hashref as follows:

          $bulk->merge(
             "Date"    => "June 22nd",
             "Company" => "Foofram Industries"
          );

     *v1.x equivalent*:  Map

Smtp
     This sets the SMTP server that you're going to connect to.  You'll
     probably just want to use whatever you've set as your default SMTP
     server in the module.  You did set your default SMTP server when you
     double-checked all the other defaults, right?

     *v1.x equivalent*:  Smtp

Port
     This sets the port on which to connect to your SMTP server.  You'll
     probably just want to use 25 (the default).

     *v1.x equivalent*:  Port

Tries
     This sets the number of times that you will attempt to connect to a
     server.  You'll probably just want to use the default.

     *v1.x equivalent*:  Tries

Precedence
     This sets the precedence of the e-mail message.  This is validated
     unless you turn off validation by making your object Trusting.
     Default precedence is "list", although you can set a precedence of
     either "bulk" (bulk, usually unsolicited mail) or "junk" (totally
     worthless message)

     *v1.x equivalent*:  Precedence

Domain
     You're going to be saying HELO to an SMTP server, you'd better be
     willing to give it a domain as well.  You can explicitly set the
     Domain here, or choose not to.  If no Domain is set, the domain of
     the From e-mail address will be used instead.  It doesn't do you any
     good to set Domain after you've connected to a server.

     *v1.x equivalent*:  Domain

HTML
     People can be dopes.  It's very very easy to send out mass HTML email
     with Mail::Bulkmail, just set a content-type:

          $bulk->header("Content-type", "text/html");

     But most people don't seem to know that, so I've added the HTML
     accessor.  Give it true value to send out HTML mail, a false value to
     send out plaintext.  It's false by default.

use_envelope
     use_envelope is like lasing a stick of dynamite.  Mail::Bulkmail is
     fast.  Mail::Bulkmail with use_envelope is ungodly incredibly
     unbelievably fast.

     For the uninformed, an email message contains two parts, the message
     itself and the envelope.   Mail servers only care about the envelope
     (for the most part), since that's where they find out who the message
     is to and from, and they don't really need to know anything else.

     A nifty feature of the envelope is that you can submit multiple
     addresses within the envelope, and then your mail server will
     automagically send along the message to everyone contained within the
     envelope.  You end up sending a hell of a lot less data across your
     connection, your SMTP server has less work to do, and everything ends
     up working out wonderfully.

     There are two catches.  First of all, with envelope sending turned
     off, the recipient will have their own email address in the "To"
     field (To: thomasoniii@yahoo.com, fer instance).  With the envelope
     on, the recipient will only receive a generic email address ("To:
     list@myserver.com", fer instance)  Most people don't care since that's
     how most email lists work, but you should be aware of it.

     Secondly, you *MUST* and I mean *MUST* sort your list by domain.
     Envelopes can only be bundled up by domain, so that we send all email
     to a domain in one burst, all of the email to another domain in the
     next burst, and so on.  So you need to have all of your domains
     clustered together in your list.  If you don't, your list will still
     go out, but it will be a *lot* slower, since Mail::Bulkmail has a
     fair amount more processing to do when you send with then envelope.
     This is normally more than offset by the gains received from sending
     fewer messages.  But with an unsorted list, you never see the big
     gains and you see a major slow down.  Sort your lists.

envelope_limit
     It's entirely likely that with a very large list you'll have a very
     large number of people in the same domain.  For instance, there are
     an awful lot of people that have yahoo addresses.  So, for example,
     say that you have a list of 100,000 people and 20,000 of them are in
     the foobar.com domain and you're sending using the envelope.  That
     means that the server at foobar.com is going to receive one message
     with 20,000 people in the envelope!

     Now, this might be a bad thing.  We don't know if the foobar.com mail
     server will actually process a message with 20,000 envelope
     recipients.  It may or may not and the only way to find out is to try
     it.  If it does work, then great no worries, but if it doesn't, then
     you're stuck.  If you stop using envelope sending, you sacrifice its
     major speed gains, but if you keep using it you can't send to
     foobar.com.

     envelope_limit fixes that.

     envelope_limit is precisely what it sounds like, it allows you to
     specify a limit on the number of recipients that will be specified in
     your envelope.  That way, with our previous example, you can specify
     an envelope limit of 1000, for example.

          $bulk->envelope_limit(1000);

     This means that foobar.com will get 20 messages, each with 1000
     recipients in the envelope.  Of course, this still may not be small
     enough, so you can tweak it as much as necessary.

     Setting an envelope limit does trade off some of the gains from using
     the envelope, but it's still over all a vast speed boost over not
     using it.

     envelope_limit is set to 0 (zero) by default, meaning that there is
     no limit specified.

LIST
     IO is a lot smarter in v2.0.  In Bulkmail 1.x, the various IO methods
     (LIST, BAD, etc.) had to be globs to file handles, which was rather
     restrictive.

     In 2.0, you have four options for how you want to import your list, a
     string, or a reference to either an array, a glob, or a function.

     If you have a flat text file, you can use it by simply passing a
     string containing the path to the file:

          $bulk->LIST("/home/jim3/list.txt");

     And Bulkmail will open the file and manage it internally, so you
     don't need to worry about polluting your namespace with filehandles
     the way you did with 1.x.

     Of course, if you *want* to pollute your namespace, then feel free to.

          open (LIST, "/home/jim3/list.txt");
          $bulk->LIST(\*LIST);

     Just note that you now have to pass a reference to the glob, not the
     glob itself as you did in 1.x.

     Flat file lists will read in one entry per line, where a line is
     determined by whatever value you've set with lineterm().

     Alternatively, you can pass a ref to an array for your list.

     my @list = ('thomasoniii@yahoo.com', 'someguy@somewhere.com',
     'invalid_@address');

     $bulk->LIST(\@list);

     #or, with an anonymous array

     $bulk->LIST(['thomasoniii@yahoo.com', 'someguy@somewhere.com',
     'invalid_@address']);

     You probably don't want to use arrays for your lists unless you're
     doing small tests.  Otherwise, you'll read your whole list into
     memory in advance, which is probably not what you wanted to do.

     Arrays as lists will return the values in order from the front to the
     end of the array.

     Probably the most powerful method to build your list is to pass a ref
     to a function.

          {
           my @list = ('thomasoniii@yahoo.com', 'someguy@somewhere.com', 'invalid_@address');

          sub some_function {return shift @list};
           };

          $bulk->LIST(\&some_function);

     Of course, in this case it's wasteful to actually pass a function
     reference instead of just an array ref to @list, but it serves as a
     good example.

     By passing function refs around, you can extract your list directly
     from a database if you want.

          my $dbh = DBI->connect();
          my $sth = $dbh->prepare("SELECT name, email FROM MAIL_LIST");
          $sth->execute;

          sub mail_list {return $sth->fetch_row_array};

          $bulk->LIST(\&mail_list);

     No more having to export your list to a flat file first.

     You can't just pass a ref to $sth->fetch_row_array because it doesn't
     work that way.  \&{$sth->fetchrow_array} returns a coderef to a hash
     containing the return value, which ain't what you want.
     &$sth...doesn't work and so on.  If anyone *does* know a way to do it
     directly, please do let me know.  :)

     The values are returned in whatever order your function returns them
     in.  Be sure to return undef when you're done, otherwise Bulkmail
     won't know when you've finished.

     Each of these methods returns "lines" of entries in your mailing
     list.  So what the hell's a line?  An email address?  A delimited
     string?  A code ref?  Actually, it's anything you want.  :)  See the
     section on MERGING below.

     *v1.x equivalent*:  LIST

BAD
     This is an optional item which specifies a place to log bad addresses
     (invalid, banned, etc.).  Just like LIST above, in v1.x it had to be
     a glob to a file handle, but not so any more!

     You have the same four options that you did for list, a string, a ref
     to a glob, a ref to a function, and a ref to an array.

     The string will cause a file to be opened for appending (">>").  The
     ref to a glob is a file that you already have open for appending (or
     simply for writing).

     If you pass a ref to an array, any items will be pushed onto the
     array as they're encountered.

     If you pass a ref to a function, then the function will be called
     with a single argument of whatever it is that was going to be logged.

     For example, if ".thomasoniii@yahoo.com" is encountered (a bad
     address!), any of the following would end up happening, depending
     upon what "BAD" is:

          print BAD ".jim3@ psynet.net", $bulk->lineterm(); #BAD is a file
          push @BAD, ".jim3@ psynet.net";                   #BAD is an array
          &BAD(".jim3@ psynet.net");                        #BAD is a function

     *v1.x equivalent*:  BAD

GOOD
     This is an optional item which specifies a place to log good
     addresses (anything not invalid or banned).  That way, you'll have a
     list at the end of all of your good addresses with the bad ones
     weeded out.

     There is one issue with the GOOD list, when using the envelope.
     You're not guaranteed that everything in the good list actually went
     through, unlike when not using the envelope.  When not using the
     envelope, a message is logged as being good as soon as it's
     completely transmitted to the server.  When using the envelope,
     however, a message is logged as being good as soon as the attempt is
     made to transmit it to the server.  As long as the message is
     accepted and delivered, everything is fine.  But if the message isn't
     accepted (if you specified too many people in the envelope, for
     instance), you'll log everyone else in the envelope as being good
     even though they weren't actually sent to.

     This is a terribly irritating bug to me, but I haven't thought of a
     clever way to handle it perfectly without caching those recipients
     elsewhere, which I'd rather not do since it's messy.  Ho hum.  Let me
     know if you have a clever solution.

     You have the same options as with BAD, above.

     *v1.x equivalent*:  GOOD

ERRFILE
     This is an optional item which specifies a place to log any and all
     errors that occur while running.  It is recommended that you run with
     this option on, so it's easier to see if anything bad is happening.

     *v1.x equivalent*:  ERROR

log_full_line
     It occurred to me that log_it was only logging the email address of a
     person.  So if you encounter a bad address of, say
     'thomasoniii@yahoo', it will log 'thomasoniii@yahoo'.  No problems,
     right?  But what if you're using a mailmerge?  Then things can get
     tricky.  If your line is, for example,

          #BULK_MAILMERGE is BULK_EMAIL::NAME::TITLE
          thomasoniii@yahoo::Jim::Perl Bulkmail Guru

     you would only log (in the bad file):

          thomasoniii@yahoo

     This may or may not be what you want.  As of v2.04, you have the
     option of choosing to log the full "line" of information.  With
     log_full_line set to true, this would be in the BAD file:

          thomasoniii@yahoo.com::Jim::Perl Bulkmail Guru

     Which may come in handy for you, or it may not.  But you at least
     have the option of doing it.  Why did I add this feature?  I was
     running a list that was extracting information via a SQL query and
     pulling out several pieces of information.  After the message was
     sent, I neede to perform another query to update that information in
     the table.  Easily done by setting GOOD to a function reference, but
     that GOOD was only receiving the email address back from bulkmail,
     not the full line of info.  That meant that I had to cache the other
     data in a seperate hash table and then come back to it later.  Most
     inelegent. This is much better.  :)

     There are a couple of "gotchas" when it comes to log_full_line that I
     haven't quite ironed out to my satisfaction yet.  If you have ideas
     about better ways to handle them, please let me know.

     First of all, remember that when logging a full line, you get back
     exactly what you put in as your "line" (recalling that "lines" can be
     strings, hashes, arrays, codes, etc.)  So if your "line" of
     information is an array (ref), then you'll log that array ref.
     Mail::Bulkmail tries to guess about a smart way to log the item if
     it's logging to a text file.  Arrays will be de-referenced and
     delimited by whatever ->BMD is.  Hashes will be squashed into their
     values and delimited by ->BMD.  The keys won't be stored.  Any other
     reference will give you an error, and then happily log the reference
     which is probably useless.  Delimited strings are logged unchanged.

     But this guessing at de-referencing is only done for files.  If
     you're logging to a function or an array, you're expected to know how
     to de-reference it yourself.  It'll just be a minor code tweak, don't
     worry.  Just be sure to remember it.

     log_full_line is set to false by default, but I may set it to true by
     default in a long-in-the-future release (think v2.5 or higher).

     *No v1.x equivalent*

banned
     banned will allows you to provide a list of banned email addresses or
     domains.  These are people that you never *ever* want to send email
     to under any circumstances.  People that email you and say "Remove me
     from your mailing list and never email me again!" will go in this
     category.

     A banned list can be built the same way as GOOD, BAD, LIST, etc.,
     with an array, a filehandle, a function, or a string containing a
     filename.  Banned entries are one per line.

          thomasoniii@yahoo.com
          yahoo.com

     would ban email from thomasoniii@yahoo.com, and anyone within the
     yahoo.com domain.  Please note that domains will only be banned
     upwards, not downwards.  So with an entry like this:

          yahoo.com
          mail.msn.com

     your list will be blocked from going to yahoo.com, and mail.msn.com.
     It will also be blocked from mail.yahoo.com (contains yahoo.com), but
     not from webserver.msn.com (webserver.msn.com does not contain
     mail.msn.com).

     You can also construct a banned list using a hashref, though it must
     be precisely constructed or you'll shoot yourself in the foot
     bigtime.  Fortunately, the format is simple.

          $banned{lowercase email address} = email address.

     Mail::Bulkmail needs its banned information in this format to
     function correctly.  Consequently, if you give it a non-hashref value
     (array, glob, etc.) it will construct this hash internally.  So if
     you have a large number of banned addresses, you'll probably want to
     put them in a dbm file and hand in a ref to it, so as not to store
     everything in memory.

     Why the funky hash format?  One of the screwball, IMHO, things about
     the email specification is that the domain part of an email address
     is case insensitive, but the local part is case sensitive.  This
     means that

          thomasoniii@yahoo.com
          ThomasonIII@yahoo.com
          tHOMaSoNIii@yahoo.com

     all could be different addresses.  So, in theory, you could have
     those three addresses in your mailing list and they're three
     different people!  Consequently, we need to keep track of exactly how
     the email address was typed or we may lose some information.

     Yeah, I know it's arguably being silly to do this, since I've never
     (*ever*) encountered an email server that allowed multiple
     differently-cased email addresses like this, but dammit I want to
     have the option in here to deal with it!  :-)

     'course, people could very well subscribe to your list using
     "thomasonIII@yahoo.com" and then try to unsubscribe using
     "thomasoniii@yahoo.com" and mess things up royally.  That's why we
     have the safe_banned method.  *See safe_banned, below*

     *v1.x equivalent*:  BANNED

safe_banned
     safe_banned is set to true by default.  safe_banned makes your
     matches on addresses case insensitive.  So that a request to ban
     "thomasoniii@yahoo.com" will also ban "ThomasonIII@yahoo.com", and
     "thomASONIii@yahoo.com".  You almost definitely want to leave this
     on, for safety's sake, but you can turn it off if you'd like.

     *See banned above*

allow_duplicates
     allow_duplicates is off by default.  Setting allow_duplicates to 1
     will allow people with multiple entries in your mailing list to
     receive multiple copies of the message.  Otherwise, they will only
     receive one copy of the message.  Duplicate addresses are printed out
     to ERRFILE, if you specified ERRFILE and you didn't turn
     allow_duplicates on.

     allow_duplicates respects safe_banned.  So if safe_banned is false,
     it will do local-part case-insensitive matching for duplicates,
     otherwise it will do local-part case-sensitive matching.

Tz
     This returns the current timezone.

     *v1.x equivalent*:  _def_Tz

Date
     This returns the current date in RFC 1123 format.

     *v1.x equivalent*:  _def_Date

header
     header() is actually a method that pretends to be an accessor.  See
     ADDTIONAL ACCESSORS, below.

     *v1.x equivalent*:  headset

HFM
     HFM (Headers From Message) will extract any valid headers from the
     message body.  A valid header is of the form "Name:value", one per
     line with an empty line seperating the headers from the message.

     It is *much* better to explicitly set the headers using the header
     method because it's a tougher to make mistakes using header.
     Nonetheless, setting HFM to any true value will cause the module to
     look in the message for headers.  Any valid headers extracted from
     the message will override existing headers.  Dynamically generated
     headers will override extracted headers, however.  Headers extracted
     from the message will be removed from the message body.

     But be perfectly sure you know what you're doing.

          $bulk->HFM(1);

          $bulk->Message(
              "This is my message.  I'm going to try sending it out to everyone that I know.
              Messages are cool, e-mailing software is neat, and everyone will love me for it.
              Oh happy day, happy happy day.
              Love,

          Jim";

     Before v2.03, since HFM is set to true, the first four lines are
     extracted from the message and sent as headers.  The extent of the
     message that goes through is "Jim" (everything after the first blank
     line which separates headers from message body).

     After v2.03, this will generate an error since HFM now makes sure
     that the headers are formed properly.  It still doesn't verify its
     headers, though, so you still need to be careful.  Maybe in the next
     release...

     Prior to v2.03, HFM would unwrap wrapped headers.  Since 2.04, HFM
     passes any wrapped headers through unchanged.

     HFM is off by default.

     *v1.x equivalent*:  HFM

BMD
     BMD (bulkmail delimiter) tells the module what delimiter to use in
     the file when using BULK_MAILMERGEs (see below)

     *Important: BMD must be different than DMD and DHD*

     BMD is "::" by default.

     *v1.x equivalent*:  BMD

DMD
     DMD (dynamic mail delimiter) tells the module what delimiter to use
     in the file when using dynamic messages (see below)

     DMD is "," by default.

DMDE
     DMDE (Dynamic Mail delimeter for Equal) tells the module what
     delimiter to use in the file when using for equalities in dynamic
     messages (see below)

     DMDE is "=" by default.

DHD
     DHD (dynamic header delimiter) tells the module what delimiter to use
     in the file when using dynamic headers (see below)

     DHD is "," by default.

DHDE
     DHDE (Dynamic Header delimeter for Equal) tells the module what
     delimiter to use in the file when using for equalities in dynamic
     headers (see below)

     DHDE is "=" by default.

lineterm
     lineterm is nifty.  It allows you to set the ending line character in
     your files.  So if you have a file with email addresses that is
     inexplicably delimited with "<!X!>", then simply set lineterm to
     "<!X!>" and off you go.  No need to convert your files before hand.

     lineterm is "\n" by default.

Trusting
     Trusting() lets you decide to turn off error checking.  By default,
     Mail::Bulkmail will only allow you to use valid e-mail addresses
     (well, kinda see the valid_email method for comments), valid dates,
     valid timezones, and valid precedences.  Trusting is off by default.
     Turn it on by setting it to some non-zero value.  This will bypass
     all error checking.  You should probabaly just leave it off so you
     can check for valid e-mails, dates, etc.  But you have the option, at
     least.

     *v1.x equivalent*:  No_errors

ADDITIONAL ACCESSORS
--------------------

   You're perfectly welcome to access any additional data that you'd like.
We're gonna assume that you're accessing or setting a header other than
the standard ones that are provided.  You even get a special method to
access them: header().  Using it is a piece of cake:

   $bulk->header('Reply-to', 'thomasoniii@yahoo.com');

   Will set a "Reply-to" header to the value of "thomasoniii@yahoo.com".
Want to access it?

   $bulk->header('Reply-to');

   What's that you ask?  Why don't we set *all* headers this way?  Well,
truth be told you can set them using header.

   $bulk->header('From', 'thomasoniii@yahoo.com');

   Is the same as:

   $bulk->From('thomasoniii@yahoo.com');

   Note that you can only set other _headers_ this way.  The headers that
have their own methods are From, Subject, and Precedence.  Calling header
on something else, though (like "Smtp") will set a header with that value,
which is probably not what you want to do (a "Smtp: your.server.com"
header is reeeeeal useful).  I'd recommend just using the provided From,
Subject, and Precedence headers.  That's what they're there for.

   What's that?  Why the hell can't you just say $bulk->my_header('some
value')?  It's because you may want to have a header with a non-word
character in it (like "Reply-to"), and methods with non-word characters
are a Perl no-no.  So since it's not possible for me to check every damn
header to see if it has a non-word character in it (things get stripped
and messed up and the original value is lost), you'll just have to use
header to set or access additional headers.

   OR-You can just set your headers at object construction.
Realistically, you're going to be setting all of your headers at
construction time, so this is not a problem.  Just remember to quote those
things with non-word characters in them.

     $bulk->Mail::Bulkmail->new(
            From        => 'thomasoniii@yahoo.com',
            Subject     => 'Some mass message',
            'Reply-to'  => 'thomasoniii@yahoo.com'
        );

   If you don't quote headers with non-word characters, all sorts of nasty
errors may pop up.  And they're tough to track down.  So don't do it.
You've been warned.

   As of v2.03, ->header() without a specific header name will return a
hashref containing all additional headers that have been set.

   *Also see dynamic headers below*

VALIDATED ACCESSORS
-------------------

   The properties that have validation checks are "From", "To", "Domain",
and "Precedence" to try to keep you from making mistakes.  The only one
that should really ever concern you is perhaps "From"

From
     This checks the return e-mail address against RFC 822 standards.  The
     validation routine is not perfect as it's really really hard to be
     perfect, but it should accept any valid non-group e-mail address.
     There is one bug in the routine that will allow
     "Jim<thomasoniii@yahoo.com" to pass as valid, but it's a nuisance to
     fix so I'm not going to.  :-)

     *v1.x equivalent*:  From

To
     This checks the to e-mail address against RFC 822 standards.  The
     validation routine is not perfect as it's really really hard to be
     perfect, but it should accept any valid non-group e-mail address.
     There is one bug in the routine that will allow
     "Jim<thomasoniii@yahoo.com" to pass as valid, but it's a nuisance to
     fix so I'm not going to.  :-)

     The ->To address is used when you are sending to a list using the
     envelope.  *See use_envelope, above*

Domain
     Domain sets which domain you'll use to say HELO to your SMTP server.
     If no domain is specified, you'll just use the domain part of your
     From address.  You probably won't need to set this ever.

Precedence
     We are doing bulkmail here, so the precedence should always be
     "list", "bulk", or "junk" and nothing else.  We might as well be
     polite and not make our servers think that we're sending out 60,000
     first-class or special-delivery messages.  You probably don't want to
     fiddle with this.

     *v1.x equivalent*:  Precedence

     If you don't want to do any validation checks, then set Trusting
     equal to 1 (see Trusting, below).  That will bypass all validation
     checks and allow you to insert "Garbonzo" as your date if you desire.
     It's recommended that you leave error checking on.  It's pretty good.
     And you have more important things to worry about.

Methods
-------

   There are several methods you are allowed to invoke upon your bulkmail
object.

bulkmail (?local merge?)
     This method is where the magic is.  This method starts up your
     mailing, sending your message to every person specified in LIST.
     bulkmail returns nothing.  bulkmail merely loops through everything
     in your LIST file and calls mail on each entry.

     bulkmail is a hell of a lot more complex then it used to be.  It used
     to just pass each address off to the mail method, so it was
     essentially just a big for loop.

     Now it's gotta do condition checking, verifications, and 4 or 5
     method calls instead of one.  Obviously, those 4-5 method calls are
     going to slow down your list processing, so that's bad.  How much
     it'll slow down I'm not really sure.  I shouldn't be much...10% I'm
     guessing.  Maybe.

     So why the hell did I complicate this up and make it slower, you ask?
     It needs the extra tricks to enable envelope sending.  Envelope
     sending will typically provide you with a performance increase of
     somewhere around 400%, I'm estimating.  The little slowdown from the
     method calls seemed unimportant.

     bulkmail can be handed a local merge hash.  *See merging, below*

     Returns 1 on success, undef on failure.

mail (line ?local merge?)
     mail is much much dumber than it used to be.  Give it a line (as in
     whatever a line would look like if extracted from your list) and an
     optional local merge, and it will email that one person.  You can now
     very easily accomplish the exact same thing by setting LIST to an
     array with one item and using bulkmail, but I figured I'd keep mail
     around for the heck of it so everyone easily knows that you can email
     just one person.

     There may be better modules for emailing to just one person, though.

     Returns 1 on success, undef on failure.

connect (no arguments)
     This method connects to your SMTP server.  It is called by the
     internal build_envelope method.  You can explicitly call it yourself,
     if you'd like.  That way you can verify that you can connect to your
     server in advance, and do something if you can't, I suppose.

     Returns 1 on success, undef on failure.

disconnect (no arguments)
     This method disconnects from your SMTP server.  It is called at
     object destruction, or explicitly if you wish to disconnect earlier.
     You should never need to call this method.  Returns nothing.

error (no arguments)
     error is where the last error message is kept.  Can be used as
     follows:

     $bulk->connect || die $bulk->error;

     All object error messages will be logged if you specifed an ERRFILE
     file.  Class errors will not be logged internally, you'll have to do
     that yourself.

     error is also usable as a class method:

     Mail::Bulkmail->error();

     will return whatever the last global class-wide error is, such as an
     object construction failure.  In fact, currently that's the only
     error it catches.  But you can now easily do:

          my $bulk = Mail::Bulkmail->new(
             "From" => 'thomasoniiI@yaho'     #invalid address!
          ) or die Mail::Bulkmail->error();

     to find out why construction failed.

MERGING
=======

   Finally, the mysterious merging section so often alluded to.

   Mail merging is exactly the same as "file mapping" was in v1.x.  I just
didn't realize until long after I released it that "file map" was stupid
and that "mail merge" is the correct term.  I'm finally correcting that
error.  If you understood mapping in v1.x, you'll understand merging now.
:-)

   You are sending out bulk e-mail to any number of people, but perhaps
you would like to personalize the message to some degree.  That's where
merging comes in handy.  You are able to define a merge to replace certain
characters (control strings) in an e-mail message with certain other
characters (values).

   Now in v2.0 you can go one step further and use dynamic messages, which
actually allows you to construct your message on the fly, instead of just
inserting values.  *See dynamic messages, below*

   Merges can be global so that all control strings in all messages will
be replaced with the same value or local so that control strings are
replaced with different values depending upon the recipient.

   Merges are declared at object constrution or by using the merge
accessor.  merge values are either anonymous hashes or references to
hashes.  For example:

   At constrution:

     $bulk = Mail::Bulkmail->new(
                 "From"    => "thomasoniii@yahoo.com",
                 "merge"   => {
                                 'DATE'    => 'today',
                                 'company' => 'Thomason Industries'
                              }
             );

   Or using the accessor:

     $bulk->merge({'DATE' => 'yesterday'});

   Global merges are not terribly useful beyond setting generic values,
such as today's date within a message template or the name of your
company.  Local merges are much more helpful since they allow values to be
set individually in each message.  Local merges can be declared either in
a call to the mail method or by using the BULK_MAILMERGE key.  Local
merges are declared with the same keyword (merge) as global merges.

   As a call to mail:

     $bulk->mail(
             'thomasoniii@yahoo.com',
             {
               'ID'   => '36373',
               'NAME' => 'Jim Thomason',
             }
     );

   Using BULK_MAILMERGE

     $bulk->merge({'BULK_MAILMERGE'=>'BULK_EMAIL::ID::NAME'});

   Be careful with your control strings to make sure that you don't
accidentally replace text in the message that you didn't mean to.  Control
strings are case sensitive, so that "name" in a message from the above
example would not be replaced by "Jim Thomason" but "NAME" would be.

   NOTE: I would *highly* recommend against having "BULK_" or "DYNAMIC_"
in any of your keys (except BULK_EMAIL, of course).  BULK_* keys are used
internally by Mail::Bulkmail for keeping track of things that it needs to
keep track of.  BULK_MAILMERGE, BULK_EMAIL, DYNAMIC_MESSAGE, and
DYNAMIC_HEADERS are examples of internal keys.  BULK_LINE is also hanging
around inside, but you never see it, now do you?  But you never know what
keys I may need to add internally at a later date.  I will always prepend
those keys with 'BULK_' or 'DYNAMIC_', so you be sure to never prepend
your keys with 'BULK_' or 'DYNAMIC_' and we'll all get along just fine.

   BULK_MAILMERGE will be explained more below.

BULK_MAILMERGE
--------------

   First of all, BULK_MAILMERGE is not compatible with use_envelope.  Use
one or the other, but not both.  It'll yell at you if you do.

   Earlier we learned that LIST files may be in two main formats, either a
single e-mail address per line, or an email address and several values per
"line", either delimited in a line of a file, or stored in an array or a
hash or a function or whatever.

   Delimited lists _must_ be used in conjunction with a BULK_MAILMERGE
parameter to merge.  BULK_MAILMERGE allows you to specify that each e-mail
message will have unique values inserted for control strings without
having to loop through the address list yourself and specify a new local
merge for every message.  BULK_MAILMERGE may only be set in a global map,
its presence is ignored in local merges.

     If your list file is this:
       thomasoniii@yahoo.com::36373::Jim Thomason
       or
       ["thomasoniii@yahoo.com", "36373", "Jim Thomason"]
       or
       {
           "BULK_EMAIL" => "thomasoniii@yahoo.com,
           "ID"         => "36373",
           "NAME"         => "Jim Thomason"
       }

   You can have a corresponding merge as any one of the following:

     $bulk->merge({
             'BULK_MAILMERGE'=>'BULK_EMAIL::ID::NAME'
             });

     $bulk->merge({
             'BULK_MAILMERGE'=>["BULK_EMAIL", "ID", "NAME"]
             });

     $bulk->merge({
             'BULK_MAILMERGE'=>
                 {"BULK_EMAIL" => undef,
                  "ID" => undef,
                  "NAME" => undef
                 }
             });

   This BULK_MAILMERGE will operate the same way that the local merge
above operated.  "BULK_EMAIL" is the only required item, it is case
sensitive.  This is where in your delimited line the e-mail address of the
recipient is.  "BULK_EMAIL" _is_ used as a control string in your message.
Be careful.  So if you want to include someone's e-mail address within
the text of your message, put the string "BULK_EMAIL" in your message body
wherever you'd like to insert it.

   Everything else may be anything you'd like, these are the control
strings that will be substituted for the values at that location in the
line in the file.  You may use global merges, BULK_MAILMERGEs and local
merges simultaneously.

   BULK_MAILMERGEs are declared as delimited by the BMD method (or "::" by
default), the data in the actual file is also delimited by the BMD method.
The default delimiter is "::", but as of version 1.10, you may use BMD to
choose any arbitrary delimiter in the file.

   For example:

     $bulk->BMD("-+-");

     $bulk->merge({'BULK_MAILMERGE'=>'BULK_EMAIL-+-ID-+-NAME'});

     (in your list file)
     thomasoniii@yahoo.com-+-ID #1-+-Jim Thomason
     thomasoniii@yahoo.com-+-ID #2-+-Jim Thomason

   If you have set LIST to a function, or array, you can have each line
return in an array or a hash.  Obviously, if LIST is a file, then every
line has to be a delimited string as listed above.

   But with arrays or functions, you don't have to return a delimited
string.  You can return your entry in an array or in a hash.  An array is
listed in the same order as the BULK_MAILMERGE, and operates the same way.
It's just a little cleaner and quicker since we skip the split step.

   The hash method is a little slower since it's a hash, and it also takes
up a little more memory since you're returning more values.

   You'll almost never want to use the hash method, since the array one is
preferrable.  I'm debating whether or not to expand that hash returning
approach to allow you to dynamically construct mail merges on the fly for
each individual item.  What do you think about that idea?

merge precedence
----------------

   local merge values will override global merge values.  BULK_MAILMERGE
merge values will override anything else.  Evaluation of merge control
strings is

     BULK_MAILMERGE value -> local value -> global value

   where the first value found is the one that is used.

DYNAMIC MESSAGES
================

   Dynamic messages rock.  :)

   We had a dotcom company come in one day to try to sell us on their
email solution for our mailing lists.  I calmly sat there, listened to
their presentation, and jotted down notes about anything they said that I
thought would be good to incorporate into Mail::Bulkmail.  The best thing
that they had was dynamic messages.

   Dynamic messages are mail merges taken to the next level. A mail merge
allows you to insert simple piece of information into your message, the
person's name or phone number or something for personalization purposes.
But it's not a good idea to do much beyond that because it gets messy to
try to maintain it across your list and keep consistency across everything.
A global mail merge is better, but not great.

   Enter dynamic messages.

   Dynamic messages allow you to actually construct your message on the
fly based upon preferences specified by the user.

   Say you've got a mailing list on animals, and you want to maintain one
list to send out to the people who like bears, rabbits, and iguanas.  One
list is easier to maintain than three, and conceptually they all like
animals, so it makes sense.  Besides, some people may want info on bears
and rabbits and wouldn't it be nice to send them one email instead of two?

   Dynamic messages must be used in conjunction with BULK_MAILMERGE, since
we're building them based upon the preferences of the individual
recipient.  Use the DYNAMIC_MESSAGE keyword in your BULK_MAILMERGE:

     "BULK_MAILMERGE" => "BULK_EMAIL::Name::ID::DYNAMIC_MESSAGE"

   and then your email entry would be:

     thomasoniii@yahoo.com::Jim Thomason::36373::Bears=yes,Rabbits=no,Iguanas=headlines

   To specify that I want info on bears, no info on rabbits, and just
headlines on iguanas.

   Then you use the ->dynamic method to declare your hash of hashes.

     $bulk->dynamic(
        "Bears" => {
            "yes" => "I see you like bears.  Bears are cuddly and we like them too!",
            "black" => "Here is your update on the black bear...",
            "polar" => "here is your update on the polar bear...",
            "no" => ""
        },
        "Rabbits" => {
            "yes" => "I see that you like rabbits.  Rabbits are cool."
            "cottontail" => "Here is information on the cotton tail rabbit..."
            "no" => ""
        },
        "Iguanas" => {
            "yes" =" Here is info on iguanas",
            "no" => ""
            "headlines" => "Here are important iguana stories"
        }
     );

   or at object creation:

     my $bulk = Mail::Bulkmail->new(
         "message" => "
         Bears
         Rabbits
         Iguanas",
         "dynamic" =>
         {
             "Bears" => {
                "yes" => "I see you like bears.  Bears are cuddly and we like them too!",
                "black" => "Here is your update on the black bear...",
                "polar" => "here is your update on the polar bear...",
                "no" => ""
            },
            "Rabbits" => {
                "yes" => "I see that you like rabbits.  Rabbits are cool."
                "cottontail" => "Here is information on the cotton tail rabbit..."
                "no" => ""
            },
            "Iguanas" => {
                "yes" =" Here is info on iguanas",
                "no" => ""
                "headlines" => "Here are important iguana stories"
            }
        }
     );

   Which will create this message:

     I see you like bears.  Bears are cuddly and we like them too!
     Here are important iguana stories

   It operates the same way as a mail merge, substituting the key word for
whatever keyword value is listed in the DYNAMIC_MESSAGE item.

   Dynamic messages execute before mail merges, so you can mail merge a
dynamic message as well!

   BULK_MAILMERGE = "BULK_EMAIL::NAME::DYNAMIC_MESSAGE";

     $bulk->dynamic(
        "Bears" => {
            "personal" => "I see you like bears, NAME",
            "impersonal" => "I see you like bears, whoever you are"
        }
     );

     thomasoniii@yahoo.com::Jim Thomason::Bears=personal

   would send:

   I see you like bears, Jim Thomason.

   So you can send truly dynamic, personalized messages.

DYNAMIC HEADERS
===============

   Well, I'm kinda spent after the huge lecture on dynamic messages above,
so I'll be briefer.

   Dynamic headers operate exactly the same way, except with headers
instead of message components.  So you can send individual people
individual subjects, for instance.

   use DYNAMIC_HEADERS in a BULK_MAILMERGE:

   BULK_MAILMERGE = "BULK_EMAIL::DYNAMIC_HEADERS";

   Use the dynamic_headers method:

     $bulk->dynamic_headers(
        "Subject" => {
            "Special offer" => "A special offer for valued customers",
            "First time" => "Thanks for your first order!",
            "No order" => "We miss your business!"
        }
     );

   or at object construction:

     my $bulk = Mail::Bulkmail->new(
        "dynamic_headers" =>{
            "Subject" => {
                "Special offer" => "A special offer for valued customers",
                "First time" => "Thanks for your first order!",
                "No order" => "We miss your business!"
            }
        }
     );

   So that

   thomasoniii@yahoo.com::Subject=Special offer

   Will send out your email message to thomasoniii@yahoo.com with "A
special offer for valued customers" as the subject.

   Again, you can use a mail merge into a dynamic header, if you'd like.
So you can insert a personalized header ID, for instance.

CLASS VARIABLES
===============

   (well, *technically* they aren't class variables, since they're
lexically scoped, but the gist is the same)

     my $def_From              = 'Postmaster';
     my $def_To                = 'postmaster@your.smtp.com';
     my $def_Smtp              = 'your.smtp.com';       #<--Set this variable.  Important!
     my $def_Domain            = "smtp.com";
     my $def_Port              = '25';
     my $def_Tries             = '5';
     my $def_Subject           = "(no subject)";
     my $def_Precedence        = "list";                #list, bulk, or junk
     my $def_Trusting          = 0;
     my $def_log_line          = 0;
     my $def_envelope_limit    = 0;
     my $def_allow_duplicates  = 0;

     my $def_BMD               = "::";
     my $def_DHD               = ",";
     my $def_DMD               = ",";
     my $def_DMDE              = "=";
     my $def_DHDE              = "=";

     my $def_lineterm          = "\n";

     my $def_HFM               = 0;

   The default values. for various items.  All of which may be overridden
in individual objects.

   These all should be obvious based upon what you've read so far.

DIAGNOSTICS
===========

   Bulkmail doesn't directly generate any errors.  If something fails, it
will return undef and set the ->error property of the bulkmail object.  If
you've provided an error log file, the error will be printed out to the
log file.

   Check the return of your functions, if it's false, check ->error to
find out what happened.

   isDuplicate and isBanned will return 0 if an address is not a duplicate
or banned, respectively, but this is (probably) not an error condition.

HISTORY
=======

- 2.05 10/3/00
     Added envelope_limit method.  See 'envelope_limit', above.

     Cleaned up the documentation a lot.

     Re-wrote the date generation methods.  They're now 5-10% faster and I
     fixed an *old* bug causing mail to sometimes appear to have been sent
     yesterday, or tomorrow.

     Altered logging when using the envelope, see item GOOD, above.

     Fixed a bug with undefined values in mailmerges

- 2.04 8/29/00
     Added log_full_line flag.  See 'log_full_line', above.

     Trusting is now more trusting.

     Domains can once again be banned.

     Error checking is done less often and in a slightly different order
     now

     ->bulkmail now returns 1 on success.  Doh.

     Fixed an annoyingly subtle bug with construction of dynamic messages

     Repaired a long-standing bug in the docs.

- 2.03 8/22/00
     Tweaked the constructor.

     Enhanced 'error'.  See 'error', above.

     Enhanced HFM.

     Various bug fixes.

     Enhanced the test suite.

- 2.01 8/16/00
     Fixed a *really* stupid error.  Merge hashes and dynamic hashes
     weren't properly initialized. Damn.

- 2.00 8/11/00
     Re-wrote everything.  Literally *everything*.  Total re-write.
     Should be a much better module now.  :)

- 1.11 11/09/99
     Banned addresses now checks entire address case insensitively instead
     of leaving the local part alone.  Better safe than sorry.

     $self->fmdl is now used to split BULK_FILEMAP

     Various fixes suggested by Chris Nandor to make -w shut up.

     Changed the way to provide local merges to mail and bulkmail so it's
     more intuitive.

- 1.10 09/08/99
     Several little fixes.

     The module will now re-connect if it receives a 221 (connection
     terminated) message from the server.

     Fixed a potential near-infinite loop in the _valid_email routine.

     _valid_email now merrily strips away comments (even nested ones).  :)

     hfm (headers from message) method added.

     fmdl (filemap delimiter) method added.

- 1.01 09/01/99
     E-mail validation and date generation bug fixes

- 1.00 08/18/99
     First public release onto CPAN

- 0.93 08/12/99
     Re-vamped the documentation substantially.

- 0.92 08/12/99
     Started adding a zero in front of the version name, just like I
     always should have

     Changed accessing of non-standard headers so that they have to be
     accessed and retrieved via the "header" method.  This is because
     methods cannot have non-word characters in them.

     From, Subject, and Precedence headers may also be accessed via
     header, if you so choose.

     AUTOLOAD now complains loudly (setting ->error and printing to
     STDERR) if it's called.

- 0.91 08/11/99
     Fixed bugs in setting values which require validation checks.  Fixed
     accessing of non-standard headers so that the returns are identical
     to every other accesor method.

- 0.90
     08/10/99 Initial "completed" release.  First release available to
     general public.

EXAMPLES
========

bulkmailing
-----------

   Here's how we use Bulkmail in one of our programs:

     use Mail::Bulkmail;

     $bulk = Mail::Bulkmail->new(
        'From'       => $from,
        'Subject'    => $subject,
        'Message'    => $message,
        'X-Header'   => "Rockin' e-mail!",
        'merge'      => {
                         '<DATE>'            => $today,
                         'BULK_MAILMERGE'    => "email::<ID>::<NAME>::<ADDRESS>"
                        },
        'LIST'       => './list.txt',
        'GOOD'       => './good_list.txt',
        'BAD'        => './baddata.txt',
        'ERROR'      => './error.txt',
        'BANNED'     => './banned.txt',
     );

   That example will set up a new bulkmail object, fill in who it's from,
the subject, and the message, as well as a "X-header" header which is set
to "Rockin' e-mail!".  It will also define a merge to turn "<DATE>"
control strings into the $today string, a BULK_MAILMERGE to merge in the
name, id number, and address of the user.  It opens a LIST file, and sets
up GOOD, BAD, and ERROR files for logging.  It also uses a BANNED list.

   This list is then mailed to by simply calling

   $bulk->bulkmail() or die $bulk->error();

   Easy as pie.  Especially considering that when we had to write all of
this code out in our original implementation, it took up well over 100
lines (and was 400x slower).

Single mailing
--------------

     use Mail::Bulkmail;

     $bulk = Mail::Bulkmail->new(
         'From'     => $from,
         'Subject'  => $Subject,
         'Message'  => $message,
         'X-Header' => "Rockin' e-mail!"
     );

     $bulk->mail(
          'thomasoniii@yahoo.com',
          {
             '<DATE>'    => $today,
             '<ID>'      => '36373',
             '<NAME>'    => 'Jim Thomason',
             '<ADDRESS>' => 'Chicago, IL'
           }
     );

   This will e-mail out a message identical to the one we bulkmailed up
above, but it'll only go to thomasoniii@yahoo.com

HUGE example with dynamic messaging
-----------------------------------

     {
        my @stuff = (
            \&solitary_address,
            ['some_address@somewhere.com', "HOOSIER", "BETDA", "GAMMA",
                "hoosier=alpha,pickle=something",
                "To=test,From=mike,Subject=special,Marvelous=Charlie"
            ],
            'some_other_address@somewhere.com::able::baker::charlie::::Subject=special',
            'some_address@somewhere_else.com::alpha::bravo::niner::::Subject=special'
        );

     sub email_list {
         return shift @stuff;
     };

     sub solitary_address {
         return ['another_address@some_server_somewhere.com', "hoosier", "betda", "gamma",
         "hoosier=alpha,pickle=something",
         "To=admin,From=herbert,Subject=yodel,Marvelous=Charlie"
         ]
     };

     };

     my %hash = ("this" => "That");
     my $bulk = Mail::Bulkmail->new(
        "From"             => "thomasoniii\@yahoo.com",
        "Subject"          => "Test with envelope",
        "Smtp"             => "email.emailserv.com",
        "LIST"             => \&email_list,
        "ERRFILE"          => \*STDERR,
        "use_envelope"     => 0,
        "Trusting"         => 0,
        "To"               => "My_list@my_server.com",
        "allow_duplicates" => 1,
        "Message"          => "azz--hello there who are you? (hoosier) (pickle) I see that you're at BULK_EMAIL",
        "merge" => {
            "this is a test" => "something",
            "who" => "what",
            "where" => "there",
            "ttt" => "things",
            "BULK_MAILMERGE" => "BULK_EMAIL::azz::bzz::czz::DYNAMIC_MESSAGE::DYNAMIC_HEADERS"
        },
        "dynamic" => {
            "hoosier" => {
                "alpha" => "This is an alpha email component",
                "beta" => "This is a beta email component",
                "agent" => "This is an agent email component"
            },
            "pickle" => {
                "something" => "You've requested the pickle agent!"
            }
        },
        "dynamic_headers" => {
            "Subject" => {
                "Hello!" => "Why HELLO there.",
                "yodel" => "I'm yodelling!",
                "special" => "Get this special offer!"
            },
            "From" => {
                "herbert" => 'herber@hoover.com',
                "mike" => 'mike@wallace.com'
            },
            "To" => {
                "admin" => "admin\@somewhere.com",
                "test" => "test\@elsewhere.com"
            },
            "Marvelous" => {
                "Max" => "Max is marvelous!",
                "Charlie" => "Charlie is marvelous!"
            }

     }
      ) or die Mail::Bulkmail->error();

   *Study this example*.  Change the email addresses.  Run it.  Understand
it.  Be happy.

FAQ
===

   *So just how fast is this thing, anyway?*

   I don't know any more, I don't have access to the same gigantic lists I
used to anymore.  :~(

   Anyway, I'm guesstimating that normal emailing will be about 5-10%
slower than before, at most.  But envelope mailing will be 400+ percent
faster.

   Well, there's a caveat to that.  I'm estimating that normal emailing
the same way you'd use v1.11 will be 5-10% slower than before.  "normal"
means using flat files as your lists.  If you start using functions or SQL
queries to build your list, then all bets are off.  For instance, one list
I'm using now sends to about 50 people in about 50 seconds (terribly
slow).  But it's repeatedly performing a SQL query 'til it gets the result
it likes, comparing that result against several conditions, deciding to
continue, and then completely building the message on the fly so every
single one is unique.  That's a lot of overhead which slows it down quite
a bit.  So YMMV, as usual.

   Here's the 1.x answer, with 2.00 comments

   Really fast.  Really stupendously incredibly fast.

   The largest list that I have data on has 91,140 people on it.  This
list runs through to *completion* in about an hour and 43 minutes, which
means that Mail::Bulkmail can process (at least) 884 messages per minute
or about 53,100 per hour. (*the guess is that with 2.00 and envelope
sending, you could email to these people in roughly 17 minutes*)

   *So? How big were the individual messages sent out?  Total data
transferred is what counts, not total recipients!*

   How right you are.  The last message sent out was 4,979 bytes.  4979 x
91,140 people is 453,786,060 bytes of data transferred, or about 453.786
megabytes in 1 hour and 43 minutes.  This is a sustained transfer rate of
about 4.4 megabytes per minute, or 264.34 megabytes per hour. (*This
hasn't changed in 2.00, we're just smart enough to send less data*)

   *Am I going to see transfer speeds that fast?*

   Maybe, maybe not.  It depends on how busy your SMTP server is.  If you
have a relatively unused SMTP server with a fair amount of horsepower, you
can easily get these speeds or beyond.  If you have a relatively busy
and/or low powered SMTP server, you're not going to reach speeds that fast.

   *How much faster will Mail::Bulkmail be than my current system?*

   This is a very tough question to answer, since it depends highly upon
what your current system is.  For the sake of argument, let's assume that
for your current system, you open an SMTP connection to your server, send
a message, and close the connection.  And then repeat.  Open, send, close,
etc.

   Mail::Bulkmail will always be faster than this approach since it opens
one SMTP connection and sends every single message across on that one
connection.  How much faster depends on how busy your server is as well as
the size of your list.

   Lets assume (for simplicity's sake) that you have a list of 100,000
people.  We'll also assume that you have a pretty busy SMTP server and it
takes (on average) 25 seconds for the server to respond to a connection
request.  We're making 100,000 connection requests (with your old system).
That means 100,000 x 25 seconds = almost 29 days waiting just to make
connections to the server!  Mail::Bulkmail makes one connection, takes 25
seconds for it, and ends up being 100,000x faster!

   But, now lets assume that you have a very unbusy SMTP server and it
responds to connection requests in .003 seconds.  We're making 100,000
connection requests.  That means 100,000 x .0003 seconds = about 5 minutes
waiting to make connections to the server.  Mail::Bulkmail makes on
connection, takes .0003 seconds for it, and ends up only being 1666x
faster.  But, even though being 1,666 times faster sounds impressive, the
world won't stop spinning on its axis if you use your old system and take
up an extra 5 minutes.

   And this doesn't even begin to take into account systems that don't
open and close SMTP connections for each message.

   *2.00 will probably be a little slower than 1.x without envelope
sending.  It'll be *much* faster with it*

   In short, there's no way to tell how much of a speed increase you'll
see.

   *Have you benchmarked it against anything else?*

   Not scientifically.  I've heard that Mail::Bulkmail is about 4-5x
faster than Listcaster from Mustang Software, but I don't have any hard
numbers.

   If you want to benchmark it against some other system and let me know
the results, it'll be much appreciated.  :-)

   *Wait a minute!  You said up there that Mail::Bulkmail opens one
connection and sends all the messages through.  What happens if the
connection is dropped midway through?*

   Well, either something good or something bad depending on what happens.
If it's something good, the server will send a 221 message (server
closing) which Mail::Bulkmail should pick up and some point, realize its
disconnected and then reconnect for the next message.  If it's something
bad, the server will just stop replying and Mail::Bulkmail will sit there
forever wondering why the server won't talk to it anymore.

   Realistically, if your server bellyflopped and is not responding at all
and won't even alert that it's disconnected, you probably have something
serious to worry about.

   A future release will probably have a time-out option so Mail::Bulkmail
will bow out and assume its disconnected after a certain period of time.

   *What about multipart messages? (MIME attachments)*

   *grumble grumble*  This is forthcoming, but it won't be in before
version 2.5.  Maybe 3.0...

   My current employer absolutely needs a mailing system that can handle
attachments, so I figure I might as well finally get around to building it
into the module.

   In the mean time, you can set your own headers, boundaries, etc. and
just do the MIME encoding yourself.  It will work, I just won't do it for
you.

   Note that if you just want to sent out a regular HTML message instead
of text that you can just use the ->HTML flag to tell the module that it's
HTML.

   *I'd like to send out a mass-mailing that has different From and To
fields in the message and the envelope.  Can I do this?*

   Oh all right, go ahead.   I've decided not to punish the legitimate
mass emailers because of the spammers.  So go to town.  I figure it
couldn't hurt once people start realizing that a Perl module is one of the
fastest freakin' mass mailers around.  Power to the cause!

   *Can I send spam with this thing?*

   No.  Don't be a jerk.

   *So what is it with these version numbers anyway?*

   I'm going to try to be consistent in how I number the releases.

   The *hundredths* digit will indicate bug fixes, minor behind-the-scenes
changes, etc.

   The *tenths* digit will indicate new and/or better functionality, as
well as some minor new features.

   The ones digit will indicate a major new feature or re-write.

   Basically, if you have x.ab and x.ac comes out, you want to get it
guaranteed.  Same for x.ad, x.ae, etc.

   If you have x.ac and x.ba comes out, you'll probably want to get it.
Invariably there will be bug fixes from the last "hundredths" release, but
it'll also have additional features.  These will be the releases to be
sure to read up on to make sure that nothing drastic has changes.

   If you have x.ac and y.ac comes out, it will be the same as x.ac->x.ba
but on a much larger scale.  Judging by the amount of revision and
improvement between 1.11 and 2.00, there's a very good chance you'll want
to look at this release.  But, also judging by 1.11->2.00, you'll want to
really pour over the docs, since it probably won't be backwards compatable
and you'll have to fiddle with your script to use it.

   *So what can I expect to see in the future?*

   Neat things.  Really *really* neat things.  I've got a few tricks up my
sleeve that will send the performance through the roof.  In theory.  If I
can get them to work.  Be patient.

   But good things are in the works.  I just have too much fun developing
this module.  :)

   *Wow, this module is really cool.  Have you contributed anything else
to CPAN?*

   Yes, Carp::Notify and Text::Flowchart

   *Was that a shameless plug?*

   Why, yes.  Yes it was.

   *Anything else you want to tell me?*

   Sure, anything you need to know.  Just drop me a message.

MISCELLANEA
===========

   Mail::Bulkmail will automatically set three headers for you (well,
maybe four).

  1. Who the message is from (From:....)

  2. The subject of the message (Subject:...)

  3. The precedence of the message (Precedence:...)

  4.      Who the message is to (To:....) I<only if using the envelope>
          (To: will actually always be set, but if not using the envelope it will
          be set to the individual receiving it)

        The defaults will be set unless you give them new values, but
regardless these headers *will* be set.  No way around it.  Additional
headers are set solely at the descretion of the user.

   Also, this module was originally written to make my life easier by
including in one place all the goodies that I used constantly.  That's not
to say that there aren't goodies that I haven't included that would be
beneficial to add.  If there's something that you feel would be worthwhile
to include, please let me know and I'll consider adding it.

   How do you know what's a worthwhile addition?  Basically, if you need
to do some sort of pre-processing to your e-mail addresses so that you
have to use your own loop and calls to mail() instead of using bulkmail(),
and you're using said loop and processing in several routines, it may be a
useful addition.  Definitely let me know about those.

   That's not to say that random suggestions wouldn't be good, those I'll
listen to as well.  But something big like that is probably a useful thing
to have so I'd be most interested in hearing about them.

COPYRIGHT (again)
=================

   Copyright (c) 1999, 2000 James A Thomason III (thomasoniii@yahoo.com).
All rights reserved.  This program is free software; you can redistribute
it and/or modify it under the same terms as Perl itself.

CONTACT INFO
============

   So you don't have to scroll all the way back to the top, I'm Jim
Thomason (thomasoniii@yahoo.com) and feedback is appreciated.  Bug
reports/suggestions/questions/etc.  Hell, drop me a line to let me know
that you're using the module and that it's made your life easier.  :-)

Parse mailcap files
*******************

NAME
====

   Mail::Cap - Parse mailcap files

SYNOPSIS
========

     my $mc = new Mail::Cap;

     $desc = $mc->description('image/gif');

     print "GIF desc: $desc\n";

     $cmd = $mc->viewCmd('text/plain; charset=iso-8859-1', 'file.txt');

DESCRIPTION
===========

   Parse mailcap files as specified in RFC 1524 - *A User Agent
Configuration Mechanism For Multimedia Mail Format Information*.  In the
description below $type refers to the MIME type as specified in the
*Content-Type* header of mail or HTTP messages.  Examples of types are:

     image/gif
     text/html
     text/plain; charset=iso-8859-1

METHODS
=======

new()
-----

     $mcap = new Mail::Cap;
     $mcap = new Mail::Cap "/mydir/mailcap";

   Create and initialize a new Mail::Cap object.  If you give it an
argument it will try to parse the specified file.  Without any arguments
it will search for the mailcap file using the standard mailcap path, or
the MAILCAPS environment variable if it is defined.

view($type, $file)
------------------

compose($type, $file)
---------------------

edit($type, $file)
------------------

print($type, $file)
-------------------

   These methods invoke a suitable progam presenting or manipulating the
media object in the specified file.  They all return 1 if a command was
found, and 0 otherwise.  You might test $? for the outcome of the command.

viewCmd($type, $file)
---------------------

composeCmd($type, $file)
------------------------

editCmd($type, $file)
---------------------

printCmd($type, $file)
----------------------

   These methods return a string that is suitable for feeding to system()
in order to invoke a suitable progam presenting or manipulating the media
object in the specified file.  It will return undef if no suitable
specification exists.

field($type, $field)
--------------------

   Returns the specified field for the type.  Returns undef if no
specification exsists.

description($type)
------------------

textualnewlines($type)
----------------------

x11_bitmap($type)
-----------------

nametemplate($type)
-------------------

   These methods return the corresponding mailcap field for the type.
These methods should be more convenient to use than the field() method for
the same fields.

COPYRIGHT
=========

   Copyright (c) 1995 Gisle Aas. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Gisle Aas <aas@oslonett.no>

   Maintained by Graham Barr <gbarr@pobox.com>

checking email addresses for validness
**************************************

NAME
====

   Mail::CheckUser - checking email addresses for validness

SYNOPSIS
========

     use Mail::CheckUser qw(check_email);
     my $res = check_email($email_addr);

     use Mail::CheckUser;
     my $res = Mail::CheckUser::check_email($email_addr);

DESCRIPTION
===========

   This Perl module provides routines for checking validness of email
address.

   It makes several checks:

  1. it checks syntax of email address;

  2. it checks if there any MX record or at least A record for domain in
     email address;

  3. it tries to connect to email server directly via SMTP to check if
     mailbox is valid. Old versions of this module have performed this
     check via VRFY command. Now module uses another check: it uses
     combination of commands MAIL and RCPT which simulates fake sending of
     email. It can detect bas mailboxes in many cases. For example
     hotmail.com mailboxes can be verified with MAIL/RCPT check.

        If is possible to turn of all networking checks (second and third
checks). See `"GLOBAL VARIABLES"' in this node.

   This module was designed with CGIs (or any other dynamic Web content
programmed with Perl) in mind. Usually it is required to check fast e-mail
address in form. If check can't be finished in reasonable time e-mail
address should be treated as valid. This is default policy. By default if
timeout happens result of check is treated as positive (it can be
overridden - see `"GLOBAL VARIABLES"' in this node).

IMPORTANT WARNING
=================

   In many cases there is no way to detect validness of email address with
network checks. For example Postfix SMTP mail server (at least with
default settings) always tells that user exists even if it is not so. Such
behavior is common to many SMTP servers designed with security in mind
since it is believed that lying about users existence helps to fight
against spam. Does it mean that network checks in this module are useless?
I think no since majority of SMTP servers do tell truth. Use this to
filter email addresses. It was designed in such way that if there is
exists possibility (even small) that email address is valid it will be
treated as valid by this module.

   Another warning is about *$Mail::CheckUser::Treat_Timeout_As_Fail*
global variable. Use it carefully - if it set in true than some valid
email addresses can be treated as bad simply SMTP server responds slowly.

EXAMPLE
=======

   This simple script checks if email address *blabla@foo.bar* is valid.

     use Mail::CheckUser qw(check_email);

     my $email = "blabla@foo.bar";

     if(check_email($email)) {
     	print "E-mail address <$email> is OK\n";
     } else {
     	print "E-mail address <$email> isn't valid\n";
     }

GLOBAL VARIABLES
================

   It is possible to configure *check_email()* using global variables
listed below.

   * *$Mail::CheckUser::Skip_Network_Checks* - if it is true then do only
     syntax checks. By default it is false.

   * *$Mail::CheckUser::Skip_SMTP_Checks* - if it is true then do not try
     to connect to mail server to check if user exist on it. By default it
     is false.

   * *$Mail::CheckUser::Sender_Addr* - MAIL/RCPT check needs some mailbox
     name to perform its check. Default value is "check\@user.com"

   * *$Mail::CheckUser::Helo_Domain* - sender domain used in HELO SMTP
     command - if undef lets Net::SMTP use its default value. By default is
     is undef.

   * *$Mail::CheckUser::Timeout* - timeout in seconds for network checks.
     By default it is 60.

   * *$Mail::CheckUser::Treat_Timeout_As_Fail* - if it is true
     Mail::CheckUser treats timeouted checks as failed checks. By default
     it is false.

   * *$Mail::CheckUser::Debug* - if it is true then enable debug output on
     STDERR. By default it is false.

AUTHOR
======

   Ilya Martynov *m_ilya@agava.com*

SEE ALSO
========

   perl(1).

Base class for manipulation of mail header fields
*************************************************

NAME
====

   Mail::Field - Base class for manipulation of mail header fields

SYNOPSIS
========

     use Mail::Field;

     $field = Mail::Field->new('Subject', 'some subject text');
     print $field->tag,": ",$field->stringify,"\n";

     $field = Mail::Field->subject('some subject text');

DESCRIPTION
===========

   `Mail::Field' is a base class for packages that create and manipulate
fields from Email (and MIME) headers. Each different field will have its
own sub-class, defining its own interface.

   This document describes the minimum interface that each sub-class should
provide, and also guidlines on how the field specific interface should be
defined.

CONSTRUCTOR
===========

   Mail::Field, and it's sub-classes define several methods which return
new objects. These can all be termed to be constructors.

new ( TAG [, STRING | OPTIONS ] )
     The new constructor will create an object in the class which defines
     the field specified by the tag argument.

     After creation of the object :-

     If the tag argument is followed by a single string then the parse
     method will be called with this string.

     If the tag argument is followed by more than one arguments then the
     create method will be called with these arguments.

extract ( TAG, HEAD [, INDEX ] )
     This constuctor takes as arguments the tag name, a `Mail::Head' object
     and optionally an index.

     If the index argument is given then extract will retrieve the given
     tag from the `Mail::Head' object and create a new `Mail::Field' based
     object.  undef will be returned in the field does not exist.

     If the index argument is not given the the result depends on the
     context in which extract is called. If called in a scalar context the
     result will be as if extract was called with an index value of zero.
     If called in an array context then all tags will be retrieved and a
     list of `Mail::Field' objects will be returned.

combine ( FIELD_LIST )
     This constructor takes as arguments a list of `Mail::Field' objects,
     which should all be of the same sub-class, and creates a new object
     in that same class.

     This constructor is nor defined in `Mail::Field' as there is no
     generic way to combine the various field types. Each sub-class should
     define its own combine constructor, if combining is possible/allowed.

METHODS
=======

parse
set
tag
stringify
SUB-CLASS PACKAGE NAMES
=======================

   All sub-classes should be called Mail::Field::name where name is
derived from the tag using these rules.

   * Consider a tag as being made up of elements separated by '-'

   * Convert all characters to lowercase except the first in each element,
     which should be uppercase.

   * name is then created from these elements by using the first N
     characters from each element.

   * N is calculated by using the formula :-

          int((7 + #elements) / #elements)

   * name is then limited to a maximum of 8 characters, keeping the first 8
     characters

   For an example of this take a look at the definition of the
`_header_pkg_name' subroutine in `Mail::Field'

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

SEE ALSO
========

   `MIME::*' in this nodes

CREDITS
=======

   Eryq <eryq@rhine.gsfc.nasa.gov> - for all the help in defining this
package so that Mail::* and MIME::* can be integrated together.

COPYRIGHT
=========

   Copyright (c) 1995-2000 Graham Barr. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

object representation of e-mail address lists
*********************************************

NAME
====

   Mail::Field::AddrList - object representation of e-mail address lists

DESCRIPTION
===========

   *Don't use this class directly!* Instead ask Mail::Field for new
instances based on the field name!

SYNOPSIS
========

     use Mail::Field::AddrList;

     $to = Mail::Field->new('To');
     $from = Mail::Field->new('From', 'poe@daimi.aau.dk (Peter Orbaek)');

     $from->create('foo@bar.com' => 'Mr. Foo', poe => 'Peter');
     $from->parse('foo@bar.com (Mr Foo), Peter Orbaek <poe>');

     # make a RFC822 header string
     print $from->stringify(),"\n";

     # extract e-mail addresses and names
     @addresses = $from->addresses();
     @names = $from->names();

     # adjoin a new address to the list
     $from->set_address('foo@bar.com', 'Mr. Foo');

NOTES
=====

   Defines parsing and formatting according to RFC822, of the following
fields: To, From, Cc, Reply-To and Sender.

AUTHOR
======

   Peter Orbaek <poe@cit.dk> 26-Feb-97 Modified by Graham Barr
<gbarr@pobox.com>

mostly RFC822-compliant parser of Received headers
**************************************************

NAME
====

   Mail::Field::Received - mostly RFC822-compliant parser of Received
headers

DESCRIPTION
===========

   *Don't use this class directly!*  Instead ask Mail::Field for new
instances based on the field name!

   Mail::Field::Received provides subroutines for parsing Received headers
from e-mails.  It mostly complies with RFC822, but deviates to accomodate
a number of broken MTAs which are in common use.

   It is a subclass derived from the Mail::Field and Mail::Field::Generic
classes.

SYNOPSIS
========

     use Mail::Field::Received;

     my $received = Mail::Field->new('Received', $header);
     my $results = $received->parse_tree();
     my $parsed_ok = $received->parsed_ok();
     my $diagnostics = $received->diagnostics();

ROUTINES
========

   * debug

     Returns current debugging level obtained via the diagnostics method.
     If a parameter is given, the debugging level is changed.  The default
     level is 3.

   * *diagnose*
          $received->diagnose("foo", "\n");

     Appends stuff to the parser's diagnostics buffer.

   * diagnostics
          my $diagnostics = $received->diagnostics();

     Returns the contents of the parser's diagnostics buffer.

   * parse

     The actual parser.  Returns the object (Mail::Field barfs otherwise).

   * *parsed_ok*
          if ($received->parsed_ok()) {
            ...
          }

     Returns true if the parse succeed, or if it failed, but was permitted
     to fail for some reason, such as encountering evidence of a known
     broken (non-RFC822-compliant) format mid-parse.

   * *parse_tree*
          my $parse_tree = $received->parse_tree();

     Returns the actual parse tree, which is where you get all the useful
     information.  It is returned as a hashref whose keys are strings like
     `from', `by', `with', `id', `via' etc., corresponding to the
     components of Received headers as defined by RFC822:

          received    =  "Received"    ":"            ; one per relay
                            ["from" domain]           ; sending host
                            ["by"   domain]           ; receiving host
                            ["via"  atom]             ; physical path
                           *("with" atom)             ; link/mail protocol
                            ["id"   msg-id]           ; receiver msg id
                            ["for"  addr-spec]        ; initial form
                             ";"    date-time         ; time received

     The corresponding values are more hashrefs which are mini-parse-trees
     for these individual components.  A typical parse tree looks something
     like:

          {
           'by' => {
                    'domain' => 'host5.hostingcheck.com',
                    'whole' => 'by host5.hostingcheck.com'
                   },
           'date_time' => {
                           'year' => 2000,
                           'week_day' => 'Tue',
                           'minute' => 57,
                           'day_of_year' => '1 Feb',
                           'month_day' => ' 1',
                           'zone' => '-0500',
                           'second' => 18,
                           'hms' => '21:57:18',
                           'date_time' => 'Tue, 1 Feb 2000 21:57:18 -0500',
                           'hour' => 21,
                           'month' => 'Feb',
                           'rest' => '2000 21:57:18 -0500',
                           'whole' => 'Tue, 1 Feb 2000 21:57:18 -0500'
                          },
           'with' => {
                      'with' => 'ESMTP',
                      'whole' => 'with ESMTP'
                     },
           'from' => {
                      'domain' => 'mediacons.tecc.co.uk',
                      'HELO' => undef,
                      'address' => '193.128.6.132',
                      'comments' => [
                                     '(mediacons.tecc.co.uk [193.128.6.132])',
                                     '(8.9.3/8.9.3)',
                                    ],
                      'whole' => 'from tr909.mediaconsult.com (mediacons.tecc.co.uk [193.128.6.132])
           (8
          '
                     },
           'id' => {
                    'id' => 'VAA24164',
                    'whole' => 'id VAA24164'
                   },
           'comments' => [
                          '(mediacons.tecc.co.uk [193.128.6.132])',
                          '(8.9.3/8.9.3)'
                         ],
           'for' => {
                     'for' => '<adam@spiers.net>',
                     'whole' => 'for <adam@spiers.net>'
                    },
           'whole' => 'from tr909.mediaconsult.com (mediacons.tecc.co.uk [193.128.6.132]) by host5.hostingcheck.com (8.9.3/8.9.3) with ESMTP id VAA24164 for <adam@spiers.net>; Tue, 1 Feb 2000 21:57:18 -0500'
          }

BUGS
====

   Doesn't use Parse::RecDescent, which it maybe should.

   Doesn't offer a `strict RFC822' parsing mode.  To implement that would
be a royal pain in the arse, unless we move to Parse::RecDescent.

SEE ALSO
========

   See Mail/Field, Mail/Header,

AUTHOR
======

   Adam Spiers <adam@spiers.net>

LICENSE
=======

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

Filter mail through multiple subroutines
****************************************

NAME
====

   Mail::Filter - Filter mail through multiple subroutines

SYNOPSIS
========

     use Mail::Filter;

     $filter = new Mail::Filter( \&filter1, \&filter2 );

     $mail = new Mail::Internet( [<>] );
     $mail = $filter->filter($mail);

     $folder = new Mail::Folder( .... );
     $filter->filter($folder);

DESCRIPTION
===========

   `Mail::Filter' provides an interface to filtering Email through multiple
subroutines.

   `Mail::Filter' filters mail by calling each filter subroutine in turn.
Each filter subroutine is called with two arguments, the first is the
filter object and the second is the mail or folder object being filtered.

   The result from each filter sub is passed to the next filter as the mail
object. If a filter subroutine returns undef, then `Mail::Filter' will
abort and return immediately.

   The function returns the result from the last subroutine to operate on
the mail object.

CONSTRUCTOR
===========

new ( [ FILTER [, ... ]])
     Create a new `Mail::Filter' object with the given filter subroutines.
     Each filter may be either a code reference or the name of a method to
     call on the <Mail::Filter> object.

METHODS
=======

add ( FILTER [, FILTER ...] )
     Add the given filters to the end of the fliter list.

filter ( MAIL-OBJECT | MAIL-FOLDER )
     If the first argument is a Mail::Internet object, then this object
     will be passed through the filter list. If the first argument is a
     `Mail::Folder' object, then each message in turn will be passed
     through the filter list.

folder
     If the filter method is called with a `Mail::Folder' object, then the
     filter subroutines may call this method to obtain the folder object
     that is being processed.

msgnum
     If the filter method is called with a `Mail::Folder' object, then the
     filter subroutines may call this method to obtain the message number
     of the message that is being processed.

SEE ALSO
========

   See Mail/Internet, Mail/Folder,

AUTHOR
======

   Graham Barr <`gbarr@pobox.com'>

COPYRIGHT
=========

   Copyright (c) 1997 Graham Barr. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SYNOPSIS
========

     use Mail::FilterXML;
     my $filter = new MailFilter(rules => "/home/matt/mail_rules.xml");
     $filter->process();

DESCRIPTION
===========

   This module builds upon Mail::Audit by Simon Cozens.  Mail::Audit is a
module for constructing filters, Mail::FilterXML is a filter of sorts.
FilterXML is just made up of some logic for processing an email message,
and is controlled by the contents of a rules file, so if I wanted to block
a particular sender, I could just add an element to my rules file, like:

   <Rule type="from" content="microsoft.com" folder="Trash" />

   The content attribute can contain perl regexps, such as
*\.microsoft\.*$, etceteras.

FUTURE
======

   I will be adding new "types" of rules, and the ability to reject or
altogether ignore messages, as possible in Mail::Audit.  Any feedback or
patches are welcome.

AUTHOR
======

   Matthew MacKenzie <mattmk@cpan.org>

COPYRIGHT
=========

   (c)2000 Matthew MacKenzie.  You may use/copy this under the same terms
as Perl.

SEE ALSO
========

   perl(1), Mail::Audit

A folder-independant interface to email folders.
************************************************

NAME
====

   Mail::Folder - A folder-independant interface to email folders.

SYNOPSIS
========

   `use Mail::Folder;'

DESCRIPTION
===========

   This base class, and companion subclasses provide an object-oriented
interface to email folders independant of the underlying folder
implementation.

   *WARNING: This code is in alpha release. Expect the interface to
change.*

   The following folder interfaces are provided with this package:

Mail::Folder::Mbox
     Ye olde standard mailbox format.

Mail::Folder::Maildir
     An interface to maildir (a la qmail) folders.  This is a very
     interesting folder format.  It is 'missing' some of the nicer features
     that some other folder interfaces have (like the message sequences in
     MH), but is probably one of the more resilient folder formats around.

Mail::Folder::Emaul
     Emaul is a folder interfaces of my own design (in the loosest sense of
     the word `:-\)').  It is vaguely similar to MH.  I wrote it to flesh
     out earlier versions of the `Mail::Folder' package.

Mail::Folder::NNTP
     This is the beginnings of an interface to NNTP.  Some of the
     `Mail::Folder' methods are not implemented yet, and no regression
     tests have been written.

   Here is a snippet of code that retrieves the third message from a
mythical emaul folder and outputs it to stdout:

     use Mail::Folder::Emaul;

     $folder = new Mail::Folder('emaul', "mythicalfolder");
     $message = $folder->get_message(3);
     $message->print(\*STDOUT);
     $folder->close;

METHODS
=======

new($foldertype [, %options])
-----------------------------

new($foldertype, $folder_name [, %options])
-------------------------------------------

   Create a new, empty `Mail::Folder' object of the specified folder type.
If `$folder_name' is specified, then the open method is automatically
called with that argument.

   If `$foldertype' is `'AUTODETECT'' then the foldertype is deduced by
querying each registered foldertype for a match.

   Options are specified as hash items using key and value pairs.

   The following options are currently built-in:

   * Create

     If set, open creates the folder if it does not already exist.

   * Content-Length

     If set, the Content-Length header field is automatically created or
     updated by the `append_message' and `update_message' methods.

   * DotLock

     If set and appropriate for the folder interface, the folder interface
     uses the '`.lock'' style of folder locking.  Currently, this is only
     used by the mbox interface - please refer to the documentation for the
     mbox interface for more information.  This mechanism will probably be
     replaced with something more generalized in the future.

   * Flock

     If set and appropriate for the folder interface, the folder interface
     uses the flock style of folder locking.  Currently this is only used
     by the mbox interface - please refer to the documentation for the
     mbox interface for more information.  This mechanism will probably be
     replaced with something more generalized in the future.

   * NFSLock

     If set and appropriate for the folder interface, the folder interface
     takes extra measures necessary to deal with folder locking across NFS.
     These special measure typically consist of constructing lock files in
     a special manner that is more immune to the atomicity problems that
     NFS has when creating a lock file.  Use of this option generally
     requires the ability to use long filenames on the NFS server in
     question.

   * NotMUA

     If the option is set, the folder interface still makes updates like
     deletes and appends, and the like, but does not save the message
     labels or the current message indicator.

     If the option is not set (the default), the folder interface saves the
     persistant labels and the current message indicator as appropriate for
     the folder interface.

     The default setting is designed for the types of updates to the state
     of mail mssages that a mail user agent typically makes.  Programmatic
     updates to folders might be better served to turn the option off so
     labels like 'seen' aren't inadvertantly set and saved when they really
     shouldn't be.

   * Timeout

     If this options is set, the folder interface uses it to override any
     default value for Timeout.  For folder interfaces doing network
     communications it is used to specify the maximum amount of time, in
     seconds, to wait for a response from the server.  For folder
     interfaces doing local file locking it is used to specify the maximum
     amount of time, in seconds, to wait for a lock to be acquired.  For
     the `maildir' interface it is, of course, meaningless `:-)'.

   * DefaultFolderType

     If the Create option is set and `AUTODETECT' is being used to
     determine the folder type, this option is used to determine what type
     of folder to create.

open($folder_name)
------------------

   Open the given folder and populate internal data structures with
information about the messages in the folder.  If the Create option is
set, then the folder will be created if it does not already exist.

   The read-only attribute is set if the underlying folder interface
determines that the folder is read-only.

   Please note that I have not done any testing for using this module
against system folders.  I am a strong advocate of using a filter package
or mail delivery agent that migrates the incoming email to the home
directory of the user.  If you try to use `MailFolder' against a system
folder, you deserve what you get.  Consider yourself warned.  I have no
intention, at this point in time, to deal with system folders and the
related issues.  If you work on it, and get it working in a portable
manner, let me know.

   Folder interfaces are expected to perform the following tasks:

   * Call the superclass new method.

   * Call set_readonly if folder is not writable.

   * Call `remember_message' for each message in the folder.

   * Initialize current_message.

   * Initialize any message labels from the persistant storage that the
     folder has.

close
-----

   Performs any housecleaning to affect a 'closing' of the folder.  It
does not perform an implicit sync.  Make sure you do a sync before the
close if you want the pending deletes, appends, updates, and the like to
be performed on the folder.

   Folder interfaces are expected to perform the following tasks:

   * Appropriate cleanup specific to the folder interface.

   * Return the result of calling the superclass close method.

sync
----

   Synchronize the folder with the internal data structures.  The folder
interface processes deletes, updates, appends, refiles, and dups.  It also
reads in any new messages that have arrived in the folder since the last
time it was either opened or synced.

   Folder interface are expected to perform the following tasks:

   * Call the superclass sync method.

   * Lock the folder.

   * Absorb any new messages

   * Perform any pending deletes and updates.

   * Update the folder persistant storage of current message.

   * Update the folder persistant storage of message labels.

   * Unlock the folder.

pack
----

   For folder formats that can have holes in the message number sequence
(like mh) this will rename the files in the folder so that there are no
gaps in the message number sequence.

   Please remember that because this method might renumber the messages in
a folder.  Any code that remembers message numbers outside of the object
could get out of sync after a pack.

   Folder interfaces are expected to perform the following tasks:

   * Call the superclass pack method.

   * Perform the guts of the pack

   * Renumber the `Messages' member of `$self'.

   * Do not forget to update current_message based on the renumbering.

get_message($msg_number)
------------------------

   Retrieve a Mail::Internet reference to the specified `$msg_number'.  A
fatal error is generated if no folder is currently open or if
`$msg_number' isn\'t in the folder.

   If present, it removes the `Content-Length' field from the message
reference that it returns.

   It also caches the header just as get_header does.

   Folder interfaces are expected to perform the following tasks:

   * Call the superclass get_message method.

   * Extract the message into a Mail::Internet object.

get_mime_message($msg_number [, parserobject] [, %options])
-----------------------------------------------------------

   Retrieves a `MIME::Entity' reference for the specified `$msg_number'.
Returns undef on failure.

   It essentially calls get_message_file to get a file to parse, creates a
`MIME::Parser' object, configures it a little, and then calls the read
method of `MIME::Parser' to create the `MIME::Entity' object.

   If `parserobject' is specified it will be used instead of an internally
created parser object.  The parser object is expected to a class instance
and a subcless (however far removed) of `MIME::ParserBase'.

   Options are specified as hash items using key and value pairs.

   Here is the list of known options.  They essentially map into the
`MIME::Parser' methods of the same name.  For documentation regarding
these options, refer to the documentation for `MIME::Parser'.

   * output_dir

   * output_prefix

   * output_to_core

get_message_file($msg_number)
-----------------------------

   Acts like `get_message()' except that a filename is returned instead of
a Mail::Internet object reference.

   A fatal error is generated if no folder is currently open or if
`$msg_number' isn\'t in the folder.

   Please note that get_message_file does not perform any 'From' escaping
or unescaping regardless of the underlying folder architecture.  I am
working on a mechanism that will resolve any resulting issues with this
malfeature.

   Folder interfaces are expected to perform the following tasks:

   * Call the superclass get_message_file method.

   * Extract the message into a temp file (if not already in one) and
     return the name of the file.

get_header($msg_number)
-----------------------

   Retrieves a message header.  Returns a reference to a `Mail::Header'
object.  It caches the result for later use.

   A fatal error is generated if no folder is currently open or if
`$msg_number' isn\'t in the folder.

   Folder interfaces are expected to perform the following tasks:

   * Call the superclass get_header method.

   * Return the cached entry if it exists.

   * Extract the header into a Mail::Internet object.

   * Cache it.

get_mime_header($msg_number)
----------------------------

   Retrieves the message header for the given message and returns a
reference to `MIME::Head' object.  It actually calls get_header, creates a
`MIME::Head' object, then stuffs the contents of the `Mail::Header' object
into the `MIME::Head' object.

   A fatal error is generated if no folder is currently open or if
`$msg_number' isn\'t in the folder.

get_fields($msg_number, @fieldnames)
------------------------------------

   Retrieves the fields, named in `@fieldnames', from message
`$msg_number'.

   At first glance, this method might seem redundant.  After all,
`Mail::Header' provides the equivalent functionality. This method is
provided to allow `Mail::Folder' interfaces for caching folder formats to
take advantage of the caching.  Those interfaces can override this method
as they see fit.

   The result is a list of field values in the same order as specified by
the method arguments.  If called in a list content, the resulting list is
returned.  If called in a scalar context, a reference to the list is
returned.

append_message($mref)
---------------------

   Add a message to a folder.  Given a reference to a Mail::Internet
object, it appends it to the end of the folder.  The result is not
committed to the original folder until a sync is performed.

   The `Content-Length' field is added to the written file if the
`Content-Length' option is enabled.

   This method will, under certain circumstances, alter the message
reference that was passed to it.  If you are writing a folder interface,
make sure you pass a dup of the message reference when calling the SUPER
of the method.  For examples, see the code for the stock folder interfaces
provided with Mail::Folder.

update_message($msg_number, $mref)
----------------------------------

   Replaces the message identified by `$msg_number' with the contents of
the message in reference to a Mail::Internet object `$mref'.  The result
is not committed to the original folder until a sync is performed.

   This method will, under certain circumstances, alter the message
reference that was passed to it.  If you are writing a folder interface,
make sure you pass a dup of the message reference when calling the SUPER
of the method.  For examples, see the code for the stock folder interfaces
provided with Mail::Folder.

   Folder interfaces are expected to perform the following tasks:

   * Call the superclass `update_message' method.

   * Replace the specified message in the working copy of the folder.

refile($msg_number, $folder_ref)
--------------------------------

   Moves a message from one folder to another.  Note that this method uses
`delete_message' and `append_message' so the changes will show up in the
folder objects, but will need a syncs performed in order for the changes
to show up in the actual folders.

dup($msg_number, $folder_ref)
-----------------------------

   Copies a message to a folder.  Works like `refile', but does not delete
the original message.  Note that this method uses `append_message' so the
change will show up in the folder object, but will need a sync performed
in order for the change to show up in the actual folder.

   A fatal error is generated if no folder is currently open or if
`$msg_number' isn\'t in the folder.

delete_message(@msg_numbers)
----------------------------

   Mark a list of messages for deletion.  The actual delete in the
original folder is not performed until a sync is performed.  This is
merely a convenience wrapper around add_label.  It returns 1.

   If any of the items in `@msg_numbers' are array references,
`delete_message' will expand out the array reference(s) and call add_label
for each of the items in the reference(s).

undelete_message(@msg_numbers)
------------------------------

   Unmarks a list of messages marked for deletion.  This is merely a
convenience wrapper around `delete_label'.  It returns 1.

   If any of the items in `@msg_numbers' are array references,
`undelete_message' will expand out the array reference(s) and call
`delete_label' for each of the items in the reference(s).

message_list
------------

   Returns a list of the message numbers in the folder.  The list is not
guaranteed to be in any specific order.

qty
---

   Returns the quantity of messages in the folder.

first_message
-------------

   Returns the message number of the first message in the folder.

last_message
------------

   Returns the message number of the last message in the folder.

next_message
------------

next_message($msg_number)
-------------------------

   Returns the message number of the next message in the folder relative
to `$msg_number'.  If `$msg_number' is not specified then the message
number of the next message relative to the current message is returned.
It returns 0 if there is no next message (ie. at the end of the folder).

prev_message
------------

prev_message($msg_number)
-------------------------

   Returns the message number of the previous message in the folder
relative to `$msg_number'.  If `$msg_number' is not specified then the
message number of the next message relative to the current message is
returned.  It returns 0 is there is no previous message (ie. at the
beginning of the folder).

first_labeled_message($label)
-----------------------------

   Returns the message number of the first message in the folder that has
the label $label associated with it.  Returns 0 is there are no messages
with the given label.

last_labeled_message($label)
----------------------------

   Returns the message number of the last message in the folder that has
the label $label associated with it.  Returns 0 if there are no messages
with the given label.

next_labeled_message($msg_number, $label)
-----------------------------------------

   Returns the message number of the next message (relative to
`$msg_number') in the folder that has the label $label associated with it.
It returns 0 is there is no next message with the given label.

prev_labeled_message($msg_number, $label)
-----------------------------------------

   Returns the message number of the previous message (relative to
`$msg_number') in the folder that has the label $label associated with it.
It returns 0 is there is no previous message with the given label.

current_message
---------------

current_message($msg_number)
----------------------------

   When called with no arguments returns the message number of the current
message in the folder.  When called with an argument set the current
message number for the folder to the value of the argument.

   For folder mechanisms that provide persistant storage of the current
message, the underlying folder interface will update that storage.  For
those that do not, changes to current_message will be affect while the
folder is open.

sort($func_ref)
---------------

   Returns a sorted list of messages.  It works conceptually similar to
the regular perl sort.  The `$func_ref' that is passed to sort must be a
reference to a function.  The function will be passed two *Mail::Header*
message references and it must return an integer less than, equal to, or
greater than 0, depending on how the list is to be ordered.

select($func_ref)
-----------------

   Returns a list of message numbers that match a set of criteria.  The
method is passed a reference to a function that is used to determine the
match criteria.  The function will be passed a reference to a
Mail::Internet message object containing only a header.

   The list of message numbers returned is not guaranteed to be in any
specific order.

inverse_select($func_ref)
-------------------------

   Returns a list of message numbers that do not match a set of criteria.
The method is passed a reference to a function that is used to determine
the match criteria.  The function will be passed a reference to a
Mail::Internet message object containing only a header.

   The list of message numbers returned is not guarenteed to be in any
specific order.

add_label($msg_number, $label)
------------------------------

   Associates $label with `$msg_number'.  The label must have a length > 0
and should be a printable string, although there are currently no
requirements for this.

   add_label will return 0 if $label is of zero length, otherwise it
returns 1.

   The persistant storage of labels is dependant on the underlying folder
interface.  Some folder interfaces may not support arbitrary labels.  In
this case, the labels will not exist when the folder is reopened.

   There are a few standard labels that have implied meaning.  Unless
stated, these labels are not actually acted on my the module interface,
rather they represent a standard set of labels for MUAs to use.

   * deleted

     This is used by the `delete_message' and sync to process the deletion
     of messages.  These will not be reflected in any persistant storage
     of message labels.

   * edited

     This tag is added by `update_message' to reflect that the message has
     been altered.  This behaviour may go away.

   * seen

     This means that the message has been viewed by the user.  The concept
     of seen is nebulous at best.  The get_message method sets this label
     for any message it is asked to retrieve.

   * filed

   * replied

   * forwarded

   * printed

delete_label($msg_number, $label)
---------------------------------

   Deletes the association of $label with `$msg_number'.

   Returns 0 if the label $label was not associated with `$msg_number',
otherwise returns a 1.

clear_label($label)
-------------------

   Deletes the association of $label for all of the messages in the folder.

   Returns the quantity of messages that were associated with the label
before they were cleared.

label_exists($msg_number, $label)
---------------------------------

   Returns 1 if the label $label is associated with `$msg_number'
otherwise returns 0.

list_labels($msg_number)
------------------------

   Returns a list of the labels that are associated with `$msg_number'.

   If `list_labels' is called in a scalar context, it returns the quantity
of labels that are associated with `$msg_number'.

   The returned list is not guaranteed to be in any specific order.

list_all_labels
---------------

   Returns a list of all the labels that are associated with the messages
in the folder.  The items in the returned list are not guaranteed to be in
any particular order.

   If list_all_labels is called in a scalar context, it returns the
quantity of labels that are associated with the messages.

select_label($label)
--------------------

   Returns a list of message numbers that have the given label $label
associated with them.

   If `select_label' is called in a scalar context, it will return the
quantity of messages that have the given label.

foldername
----------

   Returns the name of the folder that the object has open.

message_exists($msg_number)
---------------------------

   Returns 1 if the folder object contains a reference for `$msg_number',
otherwise returns 0.

set_readonly
------------

   Sets the readonly attribute for the folder.  This will cause the sync
command to not perform any updates to the actual folder.

is_readonly
-----------

   Returns 1 if the readonly attribute for the folder is set, otherwise
returns 0.

get_option($option)
-------------------

   Returns the setting for the given option.  Returns undef if the option
does not exist.

set_option($option, $value)
---------------------------

   Set $option to $value.

debug($value)
-------------

   Set the level of debug information for the object.  If $value is not
given then the current debug level is returned.

debug_print($text)
------------------

   Outputs $text, along with some other information to STDERR.  The format
of the outputted line is as follows:

   `-<gt' $subroutine $self $text>

WRITING A FOLDER INTERFACE
==========================

General Concepts
----------------

   In general, writing a folder interface consists of writing a set of
methods that overload some of the native ones in `Mail::Folder'.  Below is
a list of the methods that will typically need to overridden.  See the
code of the folder interfaces provided with the package for specific
examples.

   Basically, the goal of an interface writer is to map the mechanics of
interfacing to the folder format into the methods provided by the base
class.  If there are any obvious additions to be made, let me know.  If it
looks like I can fit them in and they make sense in the larger picture, I
will add them.

   If you set about writing a folder interface and find that something is
missing from this documentation, please let me know.

Initialization
--------------

   The beginning of a new folder interface module should start with
something like the following chunk of code:

     package Mail::Folder::YOUR_FOLDER_TYPE;
     @ISA = qw(Mail::Folder);
     use Mail::Folder;

     Mail::Folder::register_folder_type('Mail::Folder::YOUR_FOLDER_TYPE',
     				       'your_folder_type_name');

Envelopes
---------

   Please take note that inter-folder envelope issues are not complete
ironed out yet.  Some folder types (maildir via qmail) actually store all
of the envelope information, some (mbox) only store a portion of it, and
others do not store any.  Electronic has a rich history of various issues
related this issue (anyone out there remember the days when many elm
programs were compiled to use the '`From_'' field for replies instead of
the fields in the actual header - and then everyone started do non-uucp
email? :-).

   Depending on the expectations, the scale of the problem is relative.
Here is what I have done so far to deal with the problem.

   In the stock folder interfaces, the underlying Mail::Internet object is
created with the 'MailFrom' option set to '`COERCE''.  This will cause it
to rename a '`From_'' field to a '`Mail-From'' field.  All interface
writers should do the same.  This will prevent the interface writer from
needing to deal with it themselves.

   For folder interfaces that require part or all of the envelope to be
present as part of the stored message, then coercion is sometimes
necessary.  As an example, the `maildir' folder format uses a
'`Return-Path'' field as the first line in the file to signify the sender
portion of the envelope.  If that field is not present, then the
interfaces tries to synthesize it by way of the '`Reply-To'', 'From', and
'`Sender'' fields (in that order).  Currently, it croaks if it fails that
sequence of fields (this will probably change in the future - feedback
please).  At some time in the future, I am going to try to provide some
generalized routines to perform these processes in a consistant manner
across all of the interfaces; in the mean time, keep an eye out for issues
related to this whole mess.

   Every folder interface should take to prevent some of the more common
problems like being passed in a message with a '`From_'' field.  If all
other fields that carry similar information are present, then delete the
field.  If the interface can benefit from coercing it into another field
that would otherwise be missing, go for it.  Even if all of the other
interfaces do the right thing, a user might hand it a mail message that
contains a '`From_'' field, so one cannot be to careful.

   The recipient portion of the envelope is pretty much not dealt with at
all.  If it presents any major issues, describe them to me and I will try
to work something out.

Methods to override
-------------------

   The following methods will typically need to be overridden in the
folder interface.

   * open

   * close

   * sync

   * pack

   * get_header

   * get_message

   * get_message_file

   * update_message

FOLDER INTERFACE METHODS
========================

   This section describes the methods that for use by interface writers.
Refer to the stock folder interfaces for examples of their use.

register_type($type)
--------------------

   Registers a folder interface with Mail::Folder.

is_valid_folder_format($foldername)
-----------------------------------

   In a folder interface, this method should return 1 if it thinks the
folder is valid format and return 0 otherwise.  It is used by the
Mail::Folder open method when `AUTODETECT' is used as the folder type.
The open method iterates through the list of known folder interfaces until
it finds one that answer yes to the question.

   This method is always overrided by the folder interface.  A fatal
occurs if it isn\'t.

init
----

   This is a stub entry called by new.  The primary purpose is to provide
a method for subclasses to override for initialization to be performed at
constructor time.  It is called after the object members variables have
been initialized and before the optional call to open.  The new method
will return undef if the init method returns 0.  Only interface writers
need to worry about this one.

create($foldername)
-------------------

   In a folder interface, this method should return 1 after it
successfully creates a folder with the given name and return 0 otherwise.

   This method is always overrided by the folder interface.  The base
class method returns a 0 so that if create is not defined in the folder
interface, the call to create will return failure.

cache_header($msg_number, $header_ref)
--------------------------------------

   Associates `$header_ref' with `$msg_number' in the internal header
cache of the object.

invalidate_header($msg_number)
------------------------------

   Clobbers the header cache entry for `$msg_number'.

remember_message($msg_number)
-----------------------------

   Add an entry for `$msg_number' to the internal data structure of the
folder object.

forget_message($msg_number)
---------------------------

   Removes the entry for `$msg_number' from the internal data structure of
the folder object.

MISC
====

detect_folder_type($foldername)
-------------------------------

   Returns the folder type of the given `$foldername'.  Returns undef if
it cannot deduce the folder type.

CAVEATS
=======

Forking children
----------------

   If a script forks while having any folders open, only the parent should
make any changes to the folder.  In addition, when the parent closes the
folder, related temporary files will be reaped.  This temporary file
cleanup will not occur for the child.  I am contemplating a more general
solution to this problem, but until then *ONLY PARENTS SHOULD MANIPULATE
MAIL*.

Folder locking
--------------

   Ugh... Folder locking...

   Please note that I am not pleased with the folder locking as it is
currently implemented in `Mail::Folder' for some of the folder interfaces.
It will improve.

   Folder locking is problematic in certain circumstances.  For those not
familier with some of these issues, I will elaborate.

   An interface like `maildir' has no locking issues.  This is because the
design of the folder format inherently eliminates the need for locking
(cheers from the crowd).

   An interface like `nntp' has no locking issues, because it merely
implements an interface to a network protocol.  Locking issues are left as
an exercise to the server on the other end of a socket.

   Interfaces like mbox, on the other hand, are another story.

   Taken as a whole, the locking mechanism(s) used for mbox folders are
not inherently *rock-solid* in all circumstances.  To further complicate
things, there are a several variations that have been implemented as
attempts to work around the fundemental issues of the design of mbox
folder locking.

   In the simplest implementation, an mbox folder merely uses a `dotlock'
file as a semaphore to prevent simultaneous updates to the folder.  All
processes are supposed to cooperate and honor the lock file.

   In a non-NFS environment, the only typical issue with a dotlock is that
the code implementing the lock file needs to be written in such a way as
to prevent race conditions be testing for the locking and creating the
lockfile.  This is typically done with a `O_EXCL' flag passed to the call
to `open(2)'.  This allows for an atomic creation of the lock file if and
only if the file does not already exist, assuming the operating system
implements the `O_EXCL' feature.  Some operating systems implementations
have also resorted to using `lockf', fcntl, or flock as way to atomically
test and set the folder lock.  The major issue for `Mail::Folder' in this
type of environment is to merely detect what flavor(s) is necessary and
implement it.

   In an NFS environment, the story is somewhat different and a lot more
complicated.  The `O_EXCL' is not atomic across NFS and some
implementations of flock do not work across NFS, and not all operating
systems use flock to lock mbox folders.  To further complicate matters,
all processes that lock mbox folder need to do it un such a way that all
clients mounting the data can also cooperate in the locking mechanism.

   Here are a few of the outstanding folder locking issues in
`Mail::Folder' for folder interfaces that do not provide a native way to
solve locking issues.

   * only DotLock is supported

     There are snippets of code related to flock, but I have disabled it
     for a time.

   * not NFS safe

     Sorry...

   We now return you to your regularly scheduled program...

AUTHOR
======

   Kevin Johnson <`kjj@pobox.com'>

COPYRIGHT
=========

   Copyright (c) 1996-1998 Kevin Johnson <kjj@pobox.com>.

   All rights reserved. This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

An Emaul folder interface for Mail::Folder.
*******************************************

NAME
====

   Mail::Folder::Emaul - An Emaul folder interface for Mail::Folder.

   *WARNING: This code is in alpha release. Expect the interface to
change.*

SYNOPSIS
========

   `use Mail::Folder::Emaul;'

DESCRIPTION
===========

   This module provides an interface to the *emaul* folder mechanism.  It
is currently intended to be used as an example of hooking a folder
interface into Mail::Folder.

   The folder structure of *Emaul* is styled after *mh*.  It uses
directories for folders and numerically-named files for the individual
mail messages.  The current message for a particular folder is stored in a
file `.current_msg' in the folder directory.

   Folder locking is accomplished through the use of a .lock file in the
folder directory.

   If a Timeout option is specified when the object is created, that value
will be used to determine the timeout for attempting to aquire a folder
lock.  The default is 10 seconds.

METHODS
=======

open($folder_name)
------------------

   Populates the `Mail::Folder' object with information about the folder.

   * Call the superclass open method.

   * Make sure it is a valid mbox folder.

   * Check to see it it is readonly

   * Lock the folder if it is not readonly.  (This is dubious)

   * For every message file in the `$folder_name' directory, add the
     message_number to the list of messages in the object.

   * Load the contents of `$folder_dir/.current_msg' into
     `$self->{Current}'.

   * Set current_message.

   * Load message labels.

   * Unlock the folder if it is not readonly.

sync
----

   Flushes any pending changes out to the original folder.

   * Call the superclass sync method.

   * Return `-1' if the folder is readonly.

   * Return `-1' if the folder cannot be locked.

   * Scan the folder directory for message files that were not present the
     last time the folder was either opened or synced and absorb them.

   * For every pending delete, unlink that file in the folder directory

   * Clear out the 'pending delete' list.

   * Update the `.current_msg' file and the `.msg_labels' file if the
     `NotMUA' option is not set.

   * Return the number of new messages found.

pack
----

   Calls the superclass pack method.

   Return 0 if the folder is readonly.

   Return 0 if the folder cannot be locked.

   Renames the message files in the folder so that there are no gaps in
the numbering sequence.  It will tweak current_message accordingly.

   Old deleted message files (ones that start with `,') are also renamed
as necessary.

   It will abandon the operation and return 0 if a rename fails, otherwise
it returns 1.

   Please note that pack acts on the real folder.

get_message($msg_number)
------------------------

   Calls the superclass get_message method.

   Retrieves the given mail message file into a Mail::Internet object
reference and returns the reference.

   It will coerce the `From_' field into a `Mail-From' field, add the
'seen' label to the message, remove the `Content-Length' field if present,
and cache the header.

   Returns undef on failure.

get_message_file($msg_number)
-----------------------------

   Calls the superclass get_message_file method.

   Retrieves the given mail message file and returns the name of the file.

   Returns undef on failure.

get_header($msg_number)
-----------------------

   Calls the superclass get_header method.

   If the particular header has never been retrieved then get_header loads
the header of the given mail message into a member of
`$self->{Messages}{$msg_number}' and returns the object reference

   If the header for the given mail message has already been retrieved in
a prior call to get_header, then the cached entry is returned.

   The `Content-Length' field is deleted from the header object it returns.

append_message($mref)
---------------------

   Calls the superclass `append_message' method.

   Returns 0 if it cannot lock the folder.

   Appends the contents of the mail message contained `$mref' to the the
folder.

   It also caches the header.

   Please note that, contrary to other documentation for *Mail::Folder*,
the Emaul `append_message' method actually updates the real folder, rather
than queueing it up for a subsequent sync.  The dup and `refile' methods
are also affected. This will be fixed soon.

update_message($msg_number, $mref)
----------------------------------

   Calls the superclass `update_message' method.

   It returns 0 if it cannot lock the folder.

   Replaces the message pointed to by `$msg_number' with the contents of
the Mail::Internet object reference `$mref'.

   Please note that, contrary to other documentation for *Mail::Folder*,
the Emaul `update_message' method actually updates the real folder, rather
than queueing it up for a subsequent sync.  This will be fixed soon.

is_valid_folder_format($foldername)
-----------------------------------

   Returns 0 if the folder is not a directory or looks like a maildir
folder.  The current logic allows it to handle MH directories, but watch
out; you should probably set the `NotMUA' option so the interface doesn't
create it's own little folder droppings like `.msg_labels' and such.

create($foldername)
-------------------

   Returns 0 if the folder already exists.

   Creates a new folder named `$foldername' with mode `0700' and then
returns 1.

AUTHOR
======

   Kevin Johnson <`kjj@pobox.com'>

COPYRIGHT
=========

   Copyright (c) 1996-1998 Kevin Johnson <kjj@pobox.com>.

   All rights reserved. This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

A fast mailbox reader
*********************

NAME
====

   Mail::Folder::FastReader - A fast mailbox reader

SYNOPSIS
========

     use Mail::Folder::FastReader qw( read_email reset_file );

     open MAILBOX,"saved-mail";
     reset_file(MAILBOX);
     while (1)
     {
       my ($status, $email, $line_number) = read_email();
       last unless $status

     print <<EOF;
     EMAIL STARTING ON LINE $line_number:
     $email
     -------------------------------------
     EOF
       }
       close MAILBOX;

DESCRIPTION
===========

   This module provides a simple and fast way to read unix-style
mailboxes. It basically searches for the next line that begins with "From
", but which doesn't follow a "---- Begin Included Message ----".

FUNCTIONS
---------

($status,$email,$line) = read_email()
     Read the next email from the filehandle, storing the email in $email
     and the line number in $line. The status is 1 if successful, and 0 if
     not.

reset_file(FILEHANDLE)
     Reset the internal line counter and the reference to the filehandle.
     Call this before calling read_email().

AUTHOR
======

   David Coppit <david@coppit.org>

SEE ALSO
========

   grepmail, mail(1), printmail(1), Mail::Internet(3) Crocker,  D.  H.,
Standard for the Format of Arpa Internet Text Messages, RFC822.

A maildir folder interface for Mail::Folder.
********************************************

NAME
====

   Mail::Folder::Maildir - A maildir folder interface for Mail::Folder.

   *WARNING: This code is in alpha release. Expect the interface to
change.*

SYNOPSIS
========

   `use Mail::Folder::Maildir;'

DESCRIPTION
===========

   This module provides an interface to the *maildir* folder mechanism.

   The *maildir* folder format is the preferred folder mechanism for the
*qmail* mail transport agent.  It uses directories as folders and files as
messages.  It also provides separate directories for new and current
messages.  One of the most distinguishing features of the `maildir' format
is that it accomplishes it's job without the need for file locking, so
it's better equipped to deal with things like nfs mounts and the like.

   More information about qmail is available from
`http://pobox.com/~djb/qmail.html'.

METHODS
=======

open($folder_name)
------------------

   Populates the `Mail::Folder' object with information about the folder.

   * Call the superclass open method.

   * Make sure it is a valid maildir folder.

   * Detect whether the folder is readonly.

   * Clean the folder `tmp' directory.

   * Move message in folder new directory into the `cur' directory.

   * Clean up the folder `tmp' directory.

   * Moves message file in new directory to the `cur' directory.

   * For every message in the folder, add a new message number to the list
     of messages in the object, and remember the association between the
     message number and the message filename.

   * Set current_message to 1 (ugh).

close
-----

   Deletes the working copy of the folder and calls the superclass close
method.

sync
----

   * Call the superclass sync method.

   * Scan for new messages and absorb them.

   * If the folder is not readonly, expunge messages marked for deletion.

   * Update the `:info' portion of each file in the folder.

   * Return the quantity of new messages found.

pack
----

   Calls the superclass pack method.  Reassociates the filenames in the
folders to message numbers, deleting holes in the sequence of message
numbers.

get_message($msg_number)
------------------------

   Call the superclass get_message method.

   Retrieves the contents of the file pointed to by `$msg_number' into a
Mail::Internet object reference, caches the header, marks the message as
'seen' and returns the reference.

get_message_file($msg_number)
-----------------------------

   Call the superclass get_message_file method.

   Retrieves the given mail message file pointed to by $msg_number and
returns the name of the file.

get_header($msg_number)
-----------------------

   If the particular header has never been retrieved then get_header loads
the header of the given mail message into a member of
`$self->{Messages}{$msg_number}' and returns the object reference

   If the header for the given mail message has already been retrieved in
a prior call to get_header, then the cached entry is returned.

append_message($mref)
---------------------

   Calls the superclass `append_message' method.

   Writes a temporary copy of the message in `$mref' to the folder `tmp'
directory, then moves that temporary copy into the folder `cur' directory.

   It will delete the `From_' line in the header if one is present.

update_message($msg_number, $mref)
----------------------------------

   Calls the superclass `update_message' method.

   Writes a temporary copy of the message in `$mref' to the folder `tmp'
directory, then moves that temporary copy into the folder `cur' directory,
replacing the message pointed to by `$msg_number'.

   It will delete the `From_' line in the header if one is present.

is_valid_folder_format($foldername)
-----------------------------------

   Returns 1 if the folder is a directory and contains `tmp', `cur', and
new subdirectories otherwise returns 0.

create($foldername)
-------------------

   Creates a new folder named `$foldername'.  Returns 0 if the folder
already exists, otherwise returns 1.

AUTHOR
======

   Kevin Johnson <`kjj@pobox.com'>

COPYRIGHT
=========

   Copyright (c) 1996-1998 Kevin Johnson <kjj@pobox.com>.

   All rights reserved. This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

A Unix mbox interface for Mail::Folder.
***************************************

NAME
====

   Mail::Folder::Mbox - A Unix mbox interface for Mail::Folder.

   *WARNING: This code is in alpha release. Expect the interface to
change.*

SYNOPSIS
========

   `use Mail::Folder::Mbox;'

DESCRIPTION
===========

   This module provides an interface to unix mbox folders.

   The mbox folder format is the standard monolithic folder structure
prevalent on Unix.  A single folder is contained within a single file.
Each message starts with a line matching `/^From /' and ends with a blank
line.

   The folder architecture does not provide any persistantly stored
current message variable, so the current message in this folder interface
defaults to 1 and is not retained between opens of a folder.

   If the Timeout option is specified when the object is created, that
value will be used to determine the timeout for attempting to aquire a
folder lock.  The default is 10 seconds.

   If the `DotLock' option is specified when the object is created, that
value will be used to determine whether or not to use '`.lock'' style
folder locking.  The default value is 1.

   If the `Flock' option is specified when the object is created, that
value will be used to determined whether or not to use flock style folder
locking.  By default, the option is not set.

   If the `NFSLock' option is specified when the object is created, that
value will be used to determine whether or not special measures are taken
when doing `DotLock'ing.  These special measures consist of constructing
the lock file in a special manner that is more immune to atomicity
problems with NFS when creating a folder lock file.  By default, the
option is not set.  This option necessitates the ability to use long
filenames.

   It is currently a fatal error to have both `DotLock' and `Flock'
disabled.

   **NOTE** flock locking is currently disabled until I can sift out the
'right way'. **NOTE**

METHODS
=======

open($folder_name)
------------------

   * Call the superclass open method.

   * Check to see if it is a valid mbox folder.

   * Mark it as readonly if the folder is not writable.

   * Lock the folder.

   * Split the folder into individual messages in a temporary working
     directory.

   * Unlock the folder.

   * Cache all the headers.

   * Update the appropriate labels with information in the Status fields.

   * Set current_message to 1.

close
-----

   Deletes the internal working copy of the folder and calls the
superclass close method.

sync
----

   * Call the superclass sync method.

   * Lock the folder.

   * Extract into the temporary working directory any new messages that
     have been appended to the folder since the last time the folder was
     either opened or synced.

   * Create a new copy of the folder and populate it with the messages in
     the working copy that are not flagged for deletion and update the
     Status fields appropriately.

   * Move the original folder to a temp location

   * Move the new folder into place

   * Delete the old original folder

   * Unlock the folder

pack
----

   Calls the superclass pack method.

   Renames the message list to that there are no gaps in the numbering
sequence.

   It also tweaks the current_message accordingly.

get_message ($msg_number)
     Calls the superclass get_message method.

     Retrieves the given mail message file into a Mail::Internet object
     reference, sets the 'seen' label, and returns the reference.

     If the 'Content-Length' option is not set, then get_message will
     unescape 'From ' lines in the body of the message.

get_message_file ($msg_number)
     Calls the superclass get_message_file method.

     Retrieves the given mail message file and returns the name of the
     file.

     Returns undef on failure.

     This method does NOT currently do any 'From ' unescaping.

get_header($msg_number)
-----------------------

   If the particular header has never been retrieved then get_header loads
(in a manner similar to get_message) the header of the given mail message
into `$self->{Messages}{$msg_number}{Header}' and returns the object
reference.

   If the header for the given mail message has already been retrieved in
a prior call to get_header, then the cached entry is returned.

   It also calls the superclass get_header method.

append_message($mref)
---------------------

   Calls the superclass `append_message' method.

   Creates a new mail message file, in the temporary working directory,
with the contents of the mail message contained in `$mref'.  It will
synthesize a 'From ' line if one is not present in `$mref'.

   If the 'Content-Length' option is not set, then get_message will escape
'From ' lines in the body of the message.

update_message($msg_number, $mref)
----------------------------------

   Calls the superclass `update_message' method.

   Replaces the message pointed to by `$msg_number' with the contents of
the Mail::Internet object reference `$mref'.

   It will synthesize a 'From ' line if one is not present in $mref.

   If the 'Content-Length' option is not set, then get_message will escape
'From ' lines in the body of the message.

init
----

   Initializes various items specific to *Mbox*.

   * Determines an appropriate temporary directory.  If the TMPDIR
     environment variable is set, it uses that, otherwise it uses `/tmp'.
     The working directory will be a subdirectory in that directory.

   * Bumps a sequence number used for unique temporary filenames.

   * Initializes `$self->{WorkingDir}' to the name of a directory that
     will be used to hold the working copies of the messages in the folder.

is_valid_folder_format($foldername)
-----------------------------------

   Returns 1 if the folder is a plain file and starts with the string
'`From '', otherwise it returns 0.

   Returns 1 if the folder is a zero-length file and the
`$Mail::Format::DefaultEmptyFileFormat' class variable is set to 'mbox'.

   Otherwise it returns 0.

create($foldername)
-------------------

   Creates a new folder named `$foldername'.  Returns 0 if the folder
already exists, otherwise returns 1.

AUTHOR
======

   Kevin Johnson <`kjj@pobox.com'>

COPYRIGHT
=========

   Copyright (c) 1996-1998 Kevin Johnson <kjj@pobox.com>.

   All rights reserved. This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

An NNTP folder interface for Mail::Folder.
******************************************

NAME
====

   Mail::Folder::NNTP - An NNTP folder interface for Mail::Folder.

   *WARNING: This code is in alpha release.  Expect the interface to
change.*

SYNOPSIS
========

   `use Mail::Folder::NNTP;'

DESCRIPTION
===========

   This module provides an interface to newsgroups accessible via the NNTP
protocol.

METHODS
=======

open($foldername)
-----------------

   Populates the `Mail::Folder' object with information about the folder.

   The given foldername can be given one of two formats.  Either
`news://NEWSHOST/NEWSGROUP' where `NEWSHOST' is the nntp host and
`NEWSGROUP' is the news group of interest, or `#news:NEWSGROUP' in which
case the `NNTPSERVER' environment variable is referenced to determine the
news host to connect to.

   Please note that it opens an NNTP connection for each open NNTP folder.

   If no Timeout option is specified, it defaults to a timeout of 120
seconds.

   * Call the superclass open method.

   * Make sure it is a valid NNTP foldername.

   * Connect to the NNTP server referenced in $foldername.

   * Perform an NNTP group command to determine quantity and range of
     articles available.

   * Loop through available article numbers, retrieve and cache the
     headers.

   * Set current_message to first_message.

close
-----

   Calls the superclass get_message method and shuts down the connection
to the NNTP server.

sync
----

   Currently a no-op and returns 0.

   Eventually will expunge articles marked as seen, look for new articles,
update the `.newsrc' (or equivalent) file, and return the number of new
articles found.

pack
----

   Since the association between article and article number is determined
by the server, this method is a no-op.

   It return 1.

get_message($msg_number)
------------------------

   Calls the superclass get_message method.

   Retrieves the contents of the news article pointed to by the given
`$msg_number' into a Mail::Internet object reference, caches the header,
marks the message as 'seen', and returns the reference.

   It returns undef on failure.

get_message_file($msg_number)
-----------------------------

   Not currently implemented.  Returns undef.

get_header($msg_number)
-----------------------

   If the particular header has never been retrieved then get_header
retrieves the header for the given news article from the news server,
converts it into a `Mail::Header' object and returns a reference to the
object.

   If the header has already been retrieved in a prior call to get_header,
then the cached entry is returned.

   It returns undef on failure.

append_message($mref)
---------------------

   Not currently implemented.  Returns 0.

update_message($msg_number, $mref)
----------------------------------

   Not currently implemented.  Returns 0.

is_valid_folder_format($foldername)
-----------------------------------

   Returns 1 if the foldername either starts with the string '`news://''
or starts with the string '`#news:'' and the `NNTPSERVER' environment
variable is set, otherwise return 0;

create($foldername)
-------------------

   Not currently implemented.  Returns 0.

AUTHOR
======

   Kevin Johnson <`kjj@pobox.com'>

COPYRIGHT
=========

   Copyright (c) 1997-1998 Kevin Johnson <kjj@pobox.com>.

   All rights reserved. This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

class for parsing e-mail newsletters from freshmeat.net
*******************************************************

NAME
====

   Mail::Freshmeat - class for parsing e-mail newsletters from
freshmeat.net

SYNOPSIS
========

     $newsletter = new Mail::Freshmeat( \*STDIN );
     $newsletter->parse;

     foreach my $entry (@{$newsletter->entries}) {

     print "Name: $entry->{name}";
     print "Version: $entry->{version};
     ...

     # Get an entry line as if it was from the first list
     # in the newsletter
     print $newsletter->short_entry($entry), "\n";

     }

DESCRIPTION
===========

   A subclass of Mail::Internet.

   This package provides parsing of the daily e-mail newsletters which are
sent out from `http://freshmeat.net/' to any individual who requests them.

METHODS
=======

   * parse
          $newsletter->parse;

     This method must be called before any accessors can be used.

ACCESSORS
=========

   * *entry_keys*
          my @entry_keys = $newsletter->entry_keys;

     Returns the keys which each entry may have set, in the order in which
     they are encountered in the newsletter:

          - position
          - name_and_version
          - name
          - version
          - posted_on
          - license
          - category
          - homepage
          - download
          - changelog
          - body_type
          - body
          - changes
          - urgency
          - url

   * summary
          $summary = $self->summary;

     Returns the paragraph starting 'This is the official freshmeat
     newsletter ...'.

   * date
          $date = $self->date;

     Returns the date on which this newsletter was released.

   * total
          $total = $self->total;

     Returns the total number of entries in the newsletter.

   * entries

     Returns a reference to an array of hashes, each containing fully
     parsed information about an entry of the newsletter.  The entries are
     in the original newsletter order.

     The keys of each hash will be a subset of the list returned by the
     entry_keys method.

   * *advertisement*
          $ad = $self->advertisement;

     Returns the '[ advertisement ]' section of the newsletter, which has
     one entry per line.

   * list
          $list = $self->list;

     Returns the '[ article list ]' section of the newsletter, which has
     one entry per line.

   * footer

     Returns the remainder of the newsletter following the '[ article
     details ]' section.

   * details

     Returns the '[ article details ]' sections of the newsletter, which
     has each entry in full.

   * *short_entry*
          $list1 = $newsletter->list;
          $list2 = join '', map { 'o ' . $newsletter->short_entry($_) . "\n" }
                                @{$newsletter->entries};
          if ($list1 ne $list2) {
            die "Oh no!  Mail::Freshmeat doesn't do what it claims!";
          }

     :-)

     What, that's not real documentation?  Bah.  Alright then.  This method
     returns the entry in exactly the same format as when it was one of the
     lines beginning with 'o ' in the original newsletter, minus the actual
     'o ' bit.  So, you can regenerate the entire '[ article list ]'
     section (in a new order, if you want) using something similar to the
     example above.

   * *entry_header*

     This method returns the entry's "header" (from the line starting
     'name:' to the line starting 'changelog:' (or to the line where
     'changelog:' would have been if it was there)) in exactly the same
     format (modulo whitespace) as when it was one of the entries in the
     '[ article details ]' section of the original newsletter.

   * *entry_body*

     This method returns the entry's "body" - everything following the
     entry's "header" as returned by `entry_header'.

   * *long_entry*
          $list1 = $newsletter->details;
          $list2 = join $newsletter->divider,
                        map { $newsletter->long_entry($_) }
                            @{$newsletter->entries};

          # $list1 and $list2 should now be identical(ish) modulo whitespace

     This method returns the entry in exactly the same format (modulo
     whitespace differences) as when it was one of the entries in the '[
     article details ]' section of the original newsletter.  So, you can
     regenerate that entire section (in a new order, if you want) using
     something similar to the example above.

     All this method actually does is concatenate the results of the
     `entry_header' and `entry_body' methods.

   * *divider*
          print $newsletter->divider;

     Returns one of those fancy

          '--- - --- ------ - --- -- - - - -- -'

     dividers.

   * *ad_header*
          print $newsletter->ad_header;

     Returns the text for starting the advertisement section.

   * *list_header*
          print $newsletter->list_header;

     Returns the text for starting the article list section.

   * *details_header*
          print $newsletter->details_header;

     Returns the text for starting the article details section.

AUTHOR
======

   Adam Spiers <adam@spiers.net>

LICENSE
=======

   All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

VERSION
=======

   This is release 0.91.

SEE ALSO
========

   perl(1).

manipulate mail RFC822 compliant headers
****************************************

NAME
====

   Mail::Header - manipulate mail RFC822 compliant headers

SYNOPSIS
========

     use Mail::Header;

     $head = new Mail::Header;
     $head = new Mail::Header \*STDIN;
     $head = new Mail::Header [<>], Modify => 0;

DESCRIPTION
===========

   This package provides a class object which can be used for reading,
creating, manipulating and writing RFC822 compliant headers.

CONSTRUCTOR
===========

new ( [ ARG ], [ OPTIONS ] )
     ARG may be either a file descriptor (reference to a GLOB) or a
     reference to an array. If given the new object will be initialized
     with headers either from the array of read from the file descriptor.

     OPTIONS is a list of options given in the form of key-value pairs,
     just like a hash table. Valid options are

    Modify
          If this value is *true* then the headers will be re-formatted,
          otherwise the format of the header lines will remain unchanged.

    MailFrom
          This option specifies what to do when a header in the form `From
          ' is encountered. Valid values are `IGNORE' - ignore and discard
          the header, ERROR - invoke an error (call die), `COERCE' -
          rename them as Mail-From and `KEEP' - keep them.

    FoldLength
          The default length of line to be used when folding header lines

METHODS
=======

modify ( [ VALUE ] )
     If VALUE is false then `Mail::Header' will not do any automatic
     reformatting of the headers, other than to ensure that the line
     starts with the tags given.

mail_from ( OPTION )
     OPTION specifies what to do when a ``From '' line is encountered.
     Valid values are `IGNORE' - ignore and discard the header, ERROR -
     invoke an error (call die), `COERCE' - rename them as Mail-From and
     `KEEP' - keep them.

fold ( [ LENGTH ] )
     Fold the header. If LENGTH is not given then `Mail::Header' uses the
     following rules to determine what length to fold a line.

     The fold length for the tag that is begin processed

     The default fold length for the tag that is being processed

     The default fold length for the object

extract ( ARRAY_REF )
     Extract a header from the given array. extract *will modify* this
     array.  Returns the object that the method was called on.

read ( FD )
     Read a header from the given file descriptor.

empty ()
     Empty the `Mail::Header' object of all lines.

header ( [ ARRAY_REF ] )
     header does multiple operations. First it will extract a header from
     the array, if given. It will the reformat the header, if reformatting
     is permitted, and finally return a reference to an array which
     contains the header in a printable form.

header_hashref ( [ HASH_REF ] )
     As header, but it will eventually set headers from a hash reference,
     and it will return the headers as a hash reference.

     The values in the hash might either be a scalar or an array reference,
     as an example:

          $hashref->{From}='Tobias Brox <tobix@cpan.org>';
          $hashref->{To}=['you@somewhere', 'me@localhost'];

add ( TAG, LINE [, INDEX ] )
     Add a new line to the header. If TAG is undef the the tag will be
     extracted from the beginning of the given line. If INDEX is given the
     new line will be inserted into the header at the given point,
     otherwise the new line will be appended to the end of the header.

replace ( TAG, LINE [, INDEX ] )
     Replace a line in the header.  If TAG is undef the the tag will be
     extracted from the beginning of the given line. If INDEX is given the
     new line will replace the Nth instance of that tag, otherwise the
     first instance of the tag is replaced. If the tag does not appear in
     the header then a new line will be appended to the header.

combine ( TAG [, WITH ] )
     Combine all instances of TAG into one. The lines will be joined
     togther with WITH, or a single space if not given. The new item will
     be positioned in the header where the first instance was, all other
     instances of <TAG> will be removed.

get ( TAG [, INDEX ] )
     Get the text form a line. If INDEX is given then the text of the Nth
     instance will be returned. If it is not given the return value
     depends on the context in which get was called. In an array context a
     list of all the text from all the instances of TAG will be returned.
     In a scalar context the text for the first instance will be returned.

delete ( TAG [, INDEX ] )
     Delete a tag from the header. If INDEX id given then the Nth instance
     of the tag will be removed. If INDEX is not given all instances of
     tag will be removed.

count ( TAG )
     Returns the number of times the given atg appears in the header

print ( [ FD ] )
     Print the header to the given file descriptor, or STDOUT if no file
     descriptor is given.

as_string ()
     Returns the header as a single string.

fold_length ( [ TAG ], [ LENGTH ] )
     Set the default fold length for all tags or just one. With no
     arguments the default fold length is returned. With two arguments it
     sets the fold length for the given tag and returns the previous
     value. If only LENGTH is given it sets the default fold length for
     the current object.

     In the two argument form fold_length may be called as a static method,
     setting default fold lengths for tags that will be used by all
     `Mail::Header' objects. See the fold method for a description on how
     `Mail::Header' uses these values.

tags ()
     Retruns an array of all the tags that exist in the header. Each tag
     will only appear in the list once. The order of the tags is not
     specified.

dup ()
     Create a duplicate of the current object.

cleanup ()
     Remove any header line that, other than the tag, only contains
     whitespace

unfold ( [ TAG ] )
     Unfold all instances of the given tag so that they do not spread
     across multiple lines. IF TAG is not given then all lines are
     unfolded.

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

COPYRIGHT
=========

   Copyright (c) 1995-7 Graham Barr. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

An IMAP Client API
******************

NAME
====

   Mail::IMAPClient - An IMAP Client API

SYNOPSIS
========

     use Mail::IMAPClient;
     my $imap = Mail::IMAPClient->new( Server => 'imaphost',
     			  User   => 'memememe',
     			  Password => 'secret',
     );

     $imap->Debug($opt_d);

     my @folders = $imap->folders;

     foreach my $f (@folders) {

     print 	"$f is a folder with ",
     	$imap->message_count($f),
     	" messages.\n";
        }

DESCRIPTION
===========

   This module provides methods implementing the IMAP protocol. It allows
perl scripts to interact with IMAP message stores.

   The module is used by constructing or instantiating a new IMAPClient
object via the new constructor method. Once the object has been
instantiated, the connect method is either implicitly or explicitly
called. At that point methods are available that implement the IMAP client
commands as specified in *RFC2060*. When processing is complete, the
*logoff* object method is called, either explicitly by the program or
implicitly when the object goes out of scope (or at program termination).

   This documentation is not meant to be a replacement for RFC2060, and
the wily programmer will have a copy of that document handy when coding
IMAP clients.

   Note that this documentation uses the term folder in place of RFC2060's
use of mailbox.  This documentation reserves the use of the term mailbox
to refer to the set of folders owned by a specific IMAP id.

   RFC2060 defines four possible states for an IMAP connection: not
authenticated, authenticated, selected, and logged out. These correspond
to the *IMAPClient* constants *Connected*, Authenticated, Selected, and
*Unconnected*, respectively. These constants are implemented as class
methods, and can be used in conjunction with the Status method to
determine the status of an *IMAPClient* object and its underlying IMAP
session. Note that an *IMAPClient* object can be in the *Unconnected*
state both before a server connection is made and after it has ended. This
differs slightly from RFC2060, which does not define a pre-connection
status. For a discussion of the methods available for examining the
*IMAPClient* object's status, see the section labeled "Status Methods",
below.

Errors
------

   If you attempt an operation that results in an error, then you can
retrieve the text of the error message by using the *LastError* method.
However, since the *LastError* method is an object method (and not a class
method) you will only be able to use this method if you've successfully
created your object. Errors in the new method can prevent your object from
ever being created. Additionally, if you supply the Server, User, and
Password parameters to new, it will attempt to call connect and login,
either of which could fail and cause your new method call to return undef
(in which case your object will have been created but its reference will
have been discarded before ever being returned to you).

   If this happens to you, you can always check `$@'. *Mail::IMAPClient*
will populate that variable with something useful if either of the new,
connect, or login methods fail. In fact, as of version 2, the `$@'
variable will always contain error info from the last error, so you can
print that instead of calling *LastError* if you wish.

   If you run your script with warnings turned on (which I'm sure you'll
do at some point because it's such a good idea) then any error message
that gets placed into the *LastError* slot (and/or in `$@') will
automatically generate a warning.

Transactions
------------

   RFC2060 requires that each line in an IMAP conversation be prefixed
with a tag. A typical conversation consists of the client issuing a
tag-prefixed command string, and the server replying with one of more
lines of output. Those lines of output will include a command completion
status code prefixed by the same tag as the original command string.

   The *IMAPClient* module uses a simple counter to ensure that each
client command is issued with a unique tag value. This tag value is
referred to by the *IMAPClient* module as the transaction number. A
history is maintained by the *IMAPClient* object documenting each
transaction.  The Transaction method returns the number of the last
transaction, and can be used to retrieve lines of text from the object's
history.

   The Clear parameter is used to control the size of the session history
so that long-running sessions do not eat up unreasonable amounts of
memory. See the discussion of Clear under `"parameters"' in this node for
more information.

   The *Report* transaction returns the history of the entire IMAP session
since the initial connection or for the last Clear transactions.  This
provides a record of the entire conversation, including client command
strings and server responses, and is a wonderful debugging tool as well as
a useful source of raw data for custom parsing.

Class Methods
-------------

   There are a couple of methods that can be invoked as class methods.
Generally they can be invoked as an object method as well, as a
convenience to the programmer. (That is, as a convenience to the
programmer who wrote this module, as well as the programmers using it.
It's easier not to enforce a class method's classiness.) Note that if the
new method is called as an object method, the object returned is identical
to what have would been returned if new had been called as a class method.
It doesn't give you a copy of the original object or anything like that.

new()
     The new method creates a new instance of an *IMAPClient* object. If
     the Server parameter is passed as an argument to new, then new will
     implicitly call the connect method, placing the new object in the
     *Connected* state. If User and Password values are also provided, then
     connect will in turn call login, and the resulting object will be
     returned from new in the Authenticated state.

     If the Server parameter is not supplied then the *IMAPClient* object
     is created in the *Unconnected* state.

     If the new method is passed arguments then those arguments will be
     treated as a list of key=>value pairs. The key should be one of the
     parameters as documented under `"parameters"' in this node, below.

     Here are some examples:

          use Mail::IMAPClient;

          my $imap = Mail::IMAPClient->new;	# returns an unconnected Mail::IMAPClient object
          #	...				# intervening code using the 1st object, then:
          $imap = Mail::IMAPClient->new(		# returns a new, authenticated Mail::IMAPClient object
          		Server => $host,
          		User 	=> $id,
          		Password=> $pass,
          		Clear	=> 5,		# Unnecessary since '5' is the default
          #		...			# Other key=>value pairs go here
          )	or die "Cannot connect to $host as $id: $@";

     See also `"parameters"' in this node, below, and `"connect"' in this
     node and `"login"' in this node for information on how to manually
     connect and login after new.

Unconnected()
     returns a value equal to the numerical value associated with an
     object in the *Unconnected* state.

Connected()
     returns a value equal to the numerical value associated with an
     object in the *Connected* state.

Authenticated()
     returns a value equal to the numerical value associated with an
     object in the Authenticated state.

Selected()
     returns a value equal to the numerical value associated with an
     object in the Selected state.

Strip_cr()
     The *Strip_cr* method strips carriage returns from IMAP client
     command output. Although RFC2060 specifies that lines in an IMAP
     conversation end with <CR><LF>, it is often cumbersome to have the
     carriage returns in the returned data. This method accepts one or
     more lines of text as arguments, and returns those lines with all
     <CR><LF> sequences changed to <LF>. Any input argument with no
     carriage returns is returned unchanged. If the first argument (not
     counting the class name or object reference) is an array reference,
     then members of that array are processed as above and subsequent
     arguments are ignored. If the method is called in scalar context then
     an array reference is returned instead of an array of results.

     Taken together, these last two lines mean that you can do something
     like:

     	my @list = $imap->some_imap_method ;         @list =
     $imap->Strip_cr(@list) ; 	# or: 	my $list = [
     $imap->some_imap_method ] ; # returns an array ref 	$list =
     $imap->Strip_cr($list);

     *NOTE: Strip_cr* does not remove new line characters.

Rfc2060_date()
     The *Rfc2060_date* method accepts one input argument, a number of
     seconds since the epoch date. It returns an RFC2060 compliant date
     string for that date (as required in date-related arguments to
     SEARCH, such as "since", "before", etc.).

Rfc822_date()
     The *Rfc822_date* method accepts one input argument, a number of
     seconds since the epoch date. It returns an RFC822 compliant date
     string for that date (without the 'Date:' prefix). Useful for putting
     dates in message strings before calling append.

Parameters
----------

   There are several parameters that influence the behavior of an
*IMAPClient* object. Each is set by specifying a named value pair during
new method invocation as follows:

     my $imap = Mail::IMAPClient->new ( parameter  => "value",
     		       parameter2 => "value",
     			...
     	);

   Parameters can also be set after an object has been instantiated by
using the parameter's eponymous accessor method like this:

     my $imap = Mail::IMAPClient->new;
        $imap->parameter( "value");
        $imap->parameter2("value");

   The eponymous accessor methods can also be used without arguments to
obtain the current value of the parameter as follows:

     my $imap = Mail::IMAPClient->new;
                $imap->parameter( "value");
                $imap->parameter2("value");

     ... 	# A whole bunch of awesome perl code,
     	# omitted for brevity

     my $forgot  = $imap->parameter;
     my $forgot2 = $imap->parameter2;

   Note that in these examples I'm using 'parameter' and 'parameter2' as
generic parameter names.  The *IMAPClient* object doesn't actually have
parameters named 'parameter' and 'parameter2'.  On the contrary, the
available parameters are:

Clear()
     The name of this parameter, for historical reasons, is somewhat
     misleading. It should be named *Wrap*, because it specifies how many
     transactions are stored in the wrapped history buffer. But it didn't
     always work that way; the buffer used to actually get cleared. The
     name though remains the same in the interests of backwards
     compatibility.

     Clear specifies that the object's history buffer should be wrapped
     after every n transactions, where n is the value specified for the
     Clear parameter.  Calling the eponymous Clear method without an
     argument will return the current value of the Clear parameter but
     will not cause clear the history buffer to wrap.

     Setting Clear to 0 turns off automatic history buffer wrapping, and
     setting it to 1 turns off the history buffer facility (except for the
     last transaction, which cannot be disabled without breaking the
     *IMAPClient* module). Setting Clear to 0 will not cause an immediate
     clearing of the history buffer; setting it to 1 (or any other number)
     will (except of course for that inevitable last transaction).

     The default Clear value is set to five in order to conserve memory.

Debug()
     Sets the debugging flag to either a true or false value. Can be
     supplied with the new method call or separately by calling the Debug
     object method. Use of this parameter is strongly recommended when
     debugging scripts and required when reporting bugs.

Debug_fh()
     Specifies the filehandle to which debugging information should be
     printed. It can either a filehandle object reference or a filehandle
     glob. The default is to print debugging info to STDERR.

     For example, you can:

          use Mail::IMAPClient;
          use IO::File;
          # set $user, $pass, and $server here
          my $dh = IO::File->new(">debugging.output")
          	or die "Can't open debugging.output: $!\n";
          my $imap = Mail::IMAPClient->new(	User=>$user, Password=>$pass,
          					Server=>$server, Debug=> "yes, please",
          					Debug_fh => $dh
          );

          Or you can:

          use Mail::IMAPClient;
          # set $user, $pass, and $server here
          open(DBG,">debugging.output")
          	or die "Can't open debugging.output: $!\n";
          my $imap = Mail::IMAPClient->new(	User=>$user, Password=>$pass,
          					Server=>$server, Debug=> 1,
          					Debug_fh => *DBG
          );

Folder()
     The *Folder* parameter returns the name of the currently-selected
     folder (in case you forgot).  It can also be used to set the name of
     the currently selected folder, which is completely unnecessary if you
     used the select method (or select's read-only equivalent, the
     *examine* method) to select it.  Note that setting the *Folder*
     parameter does not automatically select a new folder; you use the
     select or *examine* object methods for that. Generally, the *Folder*
     parameter should only be queried (by using the no-argument form of
     the *Folder* method). You will only need to set the *Folder*
     parameter if you use some mysterious technique of your own for
     selecting a folder, which you probably won't do.

Password()
     Specifies the password to use when logging into the IMAP service on
     the host specified in the Server parameter as the user specified in
     the User parameter. Can be supplied with the new method call or
     separately by calling the Password object method.

     If Server, User, and Password are all provided to the new method,
     then the newly instantiated object will be connected to the host
     specified in Server (at either the port specified in Port or the
     default port 143) and then logged on as the user specified in the
     User parameter (using the password provided in the Password
     parameter). See the discussion of the new method, below.

Peek()
     Setting *Peek* to a true value will prevent the *body_string*,
     *message_string* and *message_to_file* methods from automatically
     setting the *\Seen* flag. Setting *Peek* to 0 (zero) will force
     *body_string*, *message_string*, *message_to_file*, and
     *parse_headers* to always set the *\Seen* flag.

     The default is to set the seen flag whenever you fetch the body of a
     message but not when you just fetch the headers. Passing undef to the
     eponymous *Peek* method will reset the *Peek* parameter to its
     pristine, default state.

Port()
     Specifies the port on which the IMAP server is listening. The default
     is 143, which is the standard IMAP port. Can be supplied with the new
     method call or separately by calling the Port object method.

Server()
     Specifies the hostname or IP address of the host running the IMAP
     server. If provided as part of the new method call, then the new IMAP
     object will automatically be connected at the time of instantiation.
     (See the new method, below.) Can be supplied with the new method call
     or separately by calling the Server object method.

Socket()
     The Socket method can be used to obtain the socket handle of the
     current connection (say, to do I/O on the connection that is not
     otherwise supported by *Mail::IMAPClient*) or to replace the current
     socket with a new handle (perhaps an SSL handle, for example).

     If you supply a socket handle yourself, either by doing something
     like:

          $imap=Mail::IMAPClient->new(Socket=>$sock, User => ... );

     or by doing something like:

          $imap=Mail::IMAPClient->new(User => $user, Password => $pass, Server => $host);
          # blah blah blah
          $imap->Socket($ssl);

     then it will be up to you to establish the connection AND to
     authenticate, either via the login method, or the fancier
     authenticate, or, since you know so much anyway, by just doing raw I/O
     against the socket until you're logged in. If you do any of this then
     you should also set the State parameter yourself to reflect the
     current state of the object (i.e. Connected, Authenticated, etc).

Timeout()
     Specifies the timeout value in seconds for reads. Specifying a true
     value for Timeout will prevent *Mail::IMAPClient* from blocking in a
     read.

     Since timeouts are implemented via the perl select operator, the
     Timeout parameter may be set to a fractional number of seconds. Not
     supplying a Timeout, or (re)setting it to zero, disables the timeout
     feature.

Uid()
     If *Uid* is set to a true value (i.e. 1) then the behavior of the
     fetch, search, copy, and store methods (and their derivatives) is
     changed so that arguments that would otherwise be message sequence
     numbers are treated as message UID's and so that return values (in
     the case of the search method and its derivatives) that would
     normally be message sequence numbers are instead message UID's.

     Internally this is implemented as a switch that, if turned on, causes
     methods that would otherwise issue an IMAP FETCH, STORE, SEARCH, or
     COPY client command to instead issue UID FETCH, UID STORE, UID
     SEARCH, or UID COPY, respectively. The main difference between
     message sequence numbers and message UID's is that, according to
     RFC2060, UID's must not change during a session and should not change
     between sessions, and must never be reused. Sequence numbers do not
     have that same guarantee and in fact may be reused right away.

     Since foldernames also have a unique identifier (UIDVALIDITY), which
     is provided when the folder is selected or *examine*d or by doing
     something like "$imap->status($folder,"UIDVALIDITY"), it is possible
     to uniquely identify every message on the server, although normally
     you won't need to bother.

     The methods currently affected by turning on the *Uid* flag are:

          copy 		fetch
          search 		store
          message_string 	message_uid
          body_string 	flags
          move 		size
          parse_headers

     Note that if for some reason you only want the *Uid* parameter turned
     on for one command, then you can choose between the following two
     snippets, which are equivalent:

     Example 1:

          $imap->Uid(1);
          my @uids = $imap->search('SUBJECT',"Just a silly test"); #
          $imap->Uid(0);

     Example 2:

          my @uids;
                 	foreach $r ($imap->UID("SEARCH","SUBJECT","Just a silly test") {
                 chomp $r;
                 $r =~ s/\r$//;
                 $r =~ s/^\*\s+SEARCH\s+// or next;
                 push @uids, grep(/\d/,(split(/\s+/,$r)));
          }

     In the second example, we used the default method to issue the UID
     IMAP Client command, being careful to use an all-uppercase method
     name so as not to inadvertently call the *Uid* accessor method.  Then
     we parsed out the message UIDs manually, since we don't have the
     benefit of the built-in search method doing it for us.

     Please be very careful when turning the *Uid* parameter on and off
     throughout a script. If you loose track of whether you've got the
     *Uid* parameter turned on you might do something sad, like deleting
     the wrong message. Remember, like all eponymous accessor methods, the
     *Uid* method without arguments will return the current value for the
     *Uid* parameter, so do yourself a favor and check. The safest
     approach is probably to turn it on at the beginning and then leave it
     on. (Remember that leaving it turned off can lead to problems if
     changes to a folder's contents cause resequencing.)

     By default, the *Uid* parameter is turned on.

User()
     Specifies the userid to use when logging into the IMAP service. Can
     be supplied with the new method call or separately by calling the
     User object method.

     Parameters can be set during new method invocation by passing named
     parameter/value pairs to the method, or later by calling the
     parameter's eponymous object method.

Object Methods
--------------

   Object methods must be invoked against objects created via the new
method. They cannot be invoked as class methods, which is why they are
"object methods" and not "class methods".

   There are basically two types of object methods-those that participate
in the IMAP session's conversation (i.e. they issue IMAP client commands)
and those that do not. Methods that do not result in new IMAP client
commands being issued (such as the *Transaction, Status*, and History
methods) all begin with an uppercase letter, to distinguish themselves
from methods that do correspond to IMAP client commands. (Class methods
and eponymous parameter methods likewise begin with an uppercase letter
because they also do not correspond to an IMAP client command.)

   The *IMAPClient* object methods are:

append()
     The append method adds a message to the specified folder. It takes
     two arguments, the name of the folder to append the message to, and
     the text of the message (including headers).  Additional arguments
     are added to the message text, separated with <CR><LF>.

     The append method returns the UID of the new message (a true value)
     if successful, or undef if not, if the IMAP server has the UIDPLUS
     capability.  If it doesn't then you just get true on success and
     undef on failure.

     Note that many servers will get really ticked off if you try to
     append a message that contains "bare newlines", which is the
     titillating term given to newlines that are not preceded by a carrage
     return. To protect against this, append will insert a carrage return
     before any newline that is "bare". If you don't like this behavior
     then you can avoid it by not passing naked newlines to append.

append_file()
     The *append_file* method adds a message to the specified folder. It
     takes two arguments, the name of the folder to append the message to,
     and the file name of an RFC822-formatted message.

     An optional third argument is the value to use for
     input_record_separator. The default is to use "" for the first read
     (to get the headers) and "\n" for the rest. Any valid value for $/ is
     acceptable, even the funky stuff, like `\1024'. (See Perlvar (perl.info),
     for more information on $/).

     The *append_file* method returns the UID of the new message (a true
     value) if successful, or undef if not, if the IMAP server has the
     UIDPLUS capability. If it doesn't then you just get true on success
     and undef on failure. If you supply a filename that doesn't exist
     then you get an automatic undef. The *LastError* method will remind
     you of this if you forget that your file doesn't exist but somehow
     manage to remember to check *LastError*.

     In case you're wondering, *append_file* is provided mostly as a way
     to allow large messages to be appended without having to have the
     whole file in memory. It uses the -s operator to obtain the size of
     the file and then reads and sends the contents line by line (or not,
     depending on whether you supplied that optional third argument).

authenticate()
     The authenticate method accepts two arguments, an authentication type
     to be used (ie CRAM-MD5) and a code or subroutine reference to
     execute to obtain a response. The authenticate assumes that the
     authentication type specified in the first argument follows a
     challenge-response flow. The authenticate method issues the IMAP
     Client AUTHENTICATE command and receives a challenge from the server.
     That challenge (minus any tag prefix or enclosing '+' characters but
     still in the original base64 encoding) is passed as the only argument
     to the code or subroutine referenced in the second argument. The
     return value from the 2nd argument's code is written to the server as
     is, except that a <CR><NL> sequence is appended if neccessary.

before()
     The before method works just like the `"since"' in this node method,
     below, except it returns a list of messages whose internal system
     dates are before the date supplied as the argument to the before
     method.

body_string()
     The *body_string* method accepts a message sequence number (or a
     message UID, if the *Uid* parameter is set to true) as an argument
     and returns the message body as a string. The returned value contains
     the entire message in one scalar variable, without the message
     headers.

capability()
     The capability method returns an array of capabilities as returned by
     the CAPABILITY IMAP Client command, or a reference to an array of
     capabilities if called in scalar context.  If the CAPABILITY IMAP
     Client command fails for any reason then the capability method will
     return undef.

close()
     The close method is implemented via the default method and is used to
     close the currently selected folder via the CLOSE IMAP client
     command.  According to RFC2060, the CLOSE command performs an
     implicit EXPUNGE, which means that any messages that you've flagged
     as *\Deleted* (say, with the *delete_message* method) will now be
     deleted. If you haven't deleted any messages then close can be
     thought of as an "unselect".

     See also *delete_message*, expunge, and your tattered copy of RFC2060.

connect()
     The connect method connects an imap object to the server. It returns
     undef if it fails to connect for any reason. If values are available
     for the User and Password parameters at the time that connect is
     invoked, then connect will call the login method after connecting and
     return the result of the login method to connect's caller.  If either
     or both of the User and Password parameters are unavailable but the
     connection to the server succeeds then connect returns a pointer to
     the *IMAPClient* object.

     The Server parameter must be set (either during new method invocation
     or via the Server object method) before invoking connect. If the
     Server parameter is supplied to the new method then connect is
     implicitly called during object construction.

     The connect method sets the state of the object to connected if it
     successfully connects to the server.

copy()
     The copy method requires a folder name as the first argument, and a
     list of one or more messages sequence numbers (or messages UID's, if
     the UID parameter is set to a true value). The message sequence
     numbers or UID's should refer to messages in the currenly selected
     folder. Those messages will be copied into the folder named in the
     first argument.

     The copy method returns undef on failure and a true value if
     successful. If the server to which the current Mail::IMAPClient
     object is connected supports the UIDPLUS capability then the true
     value returned by copy will be a comma separated list of UID's, which
     are the UID's of the newly copied messages in the target folder.

delete_message()
     The *delete_message* method accepts a list of arguments. If the *Uid*
     parameter is not set to a true value, then each item in the list
     should be either:

    > a message sequence number,
    > a comma-separated list of message sequence numbers,
    > a reference to an array of message sequence numbers, or
     If the *Uid* parameter is set to a true value, then each item in the
     list should be either:

    > a message UID,
    > a comma-separated list of UID's, or
    > a reference to an array of message UID's.
     The messages identified by the sequence numbers or UID's will be
     deleted. *delete_message* returns the number of messages it was told
     to delete. However, since the delete is done by issuing the
     *+FLAGS.SILENT* option of the STORE IMAP client command, there is no
     guarantee that the delete was successful for every message. In this
     manner the *delete_message* method sacrifices accuracy for speed.

     If you must have guaranteed results then use the IMAP STORE client
     command (via the default method) and use the +FLAGS (\Deleted)
     option, and then parse your results manually. Eg:

          $imap->store($msg_id,'+FLAGS (\Deleted)');
          	my @results = $imap->History($imap->Transaction);
          	...			# code to parse output goes here

     The *IMAPClient* object must be in Selected status to use the
     *delete_message* method.

     NOTE: All the messages identified in the input argument(s) must be in
     the currently selected folder. Failure to comply to this requirement
     will almost certainly result in the wrong message(s) being deleted.
     This would be a crying shame.

     *NOTE SOME MORE:* In the grand tradition of the IMAP protocol,
     deleting a message doesn't actually delete the message. Really. If
     you want to make sure the message has been deleted, you need to
     expunge the folder (via the expunge method, which is implemented via
     the default method). Or at least close it.  This is generally
     considered a feature, since after deleting a message, you can change
     your mind and undelete it at any time before your expunge or close.

     *See also:* The delete method, to delete a folder, the expunge
     method, to expunge a folder, the *restore_message* method to undelete
     a message, and the close method (implemented here via the default
     method) to close a folder.  Oh, and don't forget about RFC2060.

deny_seeing()
     The *deny_seeing* method accepts a list of one or more message
     sequence numbers, or a single reference to an array of one or more
     message sequence numbers, as its argument(s). It then unsets the
     "\Seen" flag for those messages. Of course, if the *Uid* parameter is
     set to a true value then those message sequence numbers had better be
     unique message id's, but then you already knew that, didn't you?

     Note that specifying `$imap-'deny_seeing(@msgs)> is just a shortcut
     for specifying `$imap-'unset_flag("Seen",@msgs)>.

disconnect()
     Disconnects the *IMAPClient* object from the server. Functionally
     equivalent to the logout method.

examine()
     The *examine* method selects a folder in read-only mode and changes
     the object's state to "Selected".  The folder selected via the
     *examine* method can be examined but no changes can be made unless it
     is first selected via the select method.

     The *examine* method accepts one argument, which is the name of the
     folder to select.

exists()
     Accepts one argument, a folder name. Returns true if the folder
     exists or false if it does not exist.

expunge()
     The expunge method accepts one optional argument, a folder name. It
     expunges the folder specified as the argument, or the currently
     selected folder if no argument is supplied.

     Although RFC2060 does not permit optional arguments (like a folder
     name) to the EXPUNGE client command, the expunge method does, which
     is especially interesting given that the expunge method doesn't
     technically exist.  In case you're curious, expunging a folder
     deletes the messages that you thought were already deleted via
     *delete_message* but really weren't, which means you have to use a
     method that doesn't exist to delete messages that you thought didn't
     exist. (Seriously, I'm not making any of this stuff up.)

     Or you could use the close method, which de-selects as well as
     expunges and which likewise doesn't technically exist. As with any
     IMAP client command, that fact that these methods don't exist will
     not stop them from working anyway. This is a feature of the
     *Mail::IMAPClient* module.  (See `"Other IMAP Client Commands and the
     Default Method"' in this node if you still don't believe me.)

fetch()
     The fetch method implements the FETCH IMAP client command. It accepts
     a list of arguments, which will be converted into a space-delimited
     list of arguments to the FETCH IMAP client command. If no arguments
     are supplied then fetch does a FETCH ALL.  If the *Uid* parameter is
     set to a true value then the first argument will be treated as a UID
     or list of UID's, which means that the UID FETCH IMAP client command
     will be run instead of FETCH. (It would really be a good idea at this
     point to review RFC2060.)

     If called in array context, fetch will return an array of output
     lines. The output lines will be returned just as they were received
     from the server, so your script will have to be prepared to parse out
     the bits you want. The only exception to this is literal strings,
     which will be inserted into the output line at the point at which
     they were encountered (without the {nnn} literal field indicator).
     See RFC2060 for a description of literal fields, and don't blame me
     if you're still confused by them. (I read that rfc just about every
     day and didn't really understand those literal fields for about a
     year.)

     If fetch is called in a scalar context, then a reference to an array
     (as described above) is returned instead of the entire array.

flags()
     The flags method implements the FETCH IMAP client command to list a
     single message's flags.  It accepts one argument, a message sequence
     number (or a message UID, if the *Uid* parameter is true), and
     returns an array (or a reference to an array, if called in scalar
     context) listing the flags that have been set. Flag names are
     provided with leading backslashes.

     As of version 1.11, you can supply either a list of message id's or a
     reference to an array of of message id's (which means either sequence
     number, if the Uid parameter is false, or message UID's, if the Uid
     parameter is true) instead of supplying a single message sequence
     number or UID.  If you do, then the return value will not be an array
     or array reference; instead, it will be a hash reference, with each
     key being a message sequence number (or UID) and each value being a
     reference to an array of flags set for that message.

     For example, if you want to display the flags for every message in
     the folder where you store e-mail related to your plans for world
     domination, you could do something like this:

          use Mail::IMAPClient;
          my $imap = Mail::IMAPClient->new( Server => $imaphost,
          				  User   => $login,
          				  Password=> $pass,
          				  Uid => 1,		# optional
          );

          $imap->select("World Domination");
          # get the flags for every message in my 'World Domination' folder
          $flaghash = $imap->flags( scalar($imap->search("ALL"))) ;

          # pump through sorted hash keys to print results:
          for my $k (sort { $flaghash->{$a} <=> $flaghash->{$b} } keys %$flaghash) {
          	# print: Message 1: \Flag1, \Flag2, \Flag3
          	print "Message $k:\t",join(", ",@{$flaghash->{$k}}),"\n";
          }

folders()
     The *folders* method returns an array listing the available folders.
     It will only be successful if the object is in the Authenticated or
     Selected states.

has_capability()
     Returns true if the IMAP server to which the *IMAPClient* object is
     connected has the capability specified as an argument to
     *has_capability*.

internaldate()
     *internaldate* accepts one argument, a message id (or UID if the Uid
     parameter is true), and returns that message's internal date.

is_parent()
     The *is_parent* method accepts one argument, the name of a folder. It
     returns a value that indicates whether or not the folder has
     children. The value it returns is either 1) a true value (indicating
     that the folder has children), 2) 0 if the folder has no children at
     this time, or 3) undef if the folder is not permitted to have
     children.

     Eg:

          my $parenthood = $imap->is_parent($folder);
          if (defined($parenthood)) {
          	if ($parenthood) {
          		print "$folder has children.\n" ;
          	} else {
          		print "$folder is permitted children, but has none.\n";
          	}
          } else {
          	print "$folder is not permitted to have children.\n";
          }

list()
     The list method implements the IMAP LIST client command. Arguments
     are passed to the IMAP server as received, separated from each other
     by spaces. If no arguments are supplied then the default list command
     `tag LIST "" '*'' is issued.

     The list method returns an array (or an array reference, if called in
     a scalar context).  The array is the unaltered output of the LIST
     command. (If you want your output altered then see the *folders*
     method, above.)

login()
     The login method uses the IMAP LOGIN client command (as defined in
     RFC2060) to log into the server.  The User and Password parameters
     must be set before the login method can be invoked. If successful,
     the login method returns a pointer to the *IMAPClient* object and
     sets the object status to Authenticated. If unsuccessful, it returns
     undef.

logout()
     The logout method issues the LOGOUT IMAP client commmand. Since the
     LOGOUT IMAP client command causes the server to end the connection,
     this also results in the *IMAPClient* client entering the
     *Unconnected* state. This method does not, however, destroy the
     *IMAPClient* object, so a program can re-invoke the connect and login
     methods if it wishes to reestablish a session later in the program.

lsub()
     The *lsub* method implements the IMAP LSUB client command. Arguments
     are passed to the IMAP server as received, separated from each other
     by spaces. If no arguments are supplied then the default lsub command
     `tag LSUB "" '*'' is issued.

     The *lsub* method returns an array (or an array reference, if called
     in a scalar context).  The array is the unaltered output of the LSUB
     command. If you want an array of subscribed folders then see the
     *subscribed* method, below.

message_count()
     The *message_count* method accepts the name of a folder as an
     argument and returns the number of messages in that folder.
     Internally, it invokes the status method (see above) and parses out
     the results to obtain the number of messages. If you don't supply an
     argument to *message_count* then it will return the number of
     messages in the currently selected folder (assuming of course that
     you've used the select or *examine* method to select it instead of
     trying something funky).

message_string()
     The *message_string* method accepts a message sequence number (or
     message UID if *Uid* is true) as an argument and returns the message
     as a string. The returned value contains the entire message in one
     scalar variable, including the message headers. Note that using this
     method will set the message's "\Seen" flag as a side effect, unless
     *Peek* is set to a true value.

message_to_file()
     The *message_to_file* method accepts a filename or file handle and
     one or more message sequence numbers (or message UIDs if *Uid* is
     true) as arguments and places the message string(s) (including RFC822
     headers) into the file named in the first argument (or prints them to
     the filehandle, if a filehandle is passed).  The returned value is
     true on succes and undef on failure.

     If the first argument is a reference, it is assumed to be an open
     filehandle and will not be closed when the method completes, If it is
     a file, it is opened in append mode, written to, then closed.

     Note that using this method will set the message's "\Seen" flag as a
     side effect. But you can use the *deny_seeing* method to set it back,
     or set the *Peek* parameter to a true value to prevent setting the
     "\Seen" flag at all.

     This method currently works by making some basic assumptions about
     the server's behavior, notably that the message text will be returned
     as a literal string but that nothing else will be. If you have a
     better idea then I'd like to hear it.

message_uid()
     The *message_uid* method accepts a message sequence number (or
     message UID if *Uid* is true) as an argument and returns the
     message's UID. Yes, if *Uid* is true then it will use the IMAP UID
     FETCH UID client command to obtain and return the very same argument
     you supplied.  This is an IMAP feature so don't complain to me about
     it.

move()
     The move method moves messages from the currently selected folder to
     the folder specified in the first argument to move.  If the *Uid*
     parameter is not true, then the rest of the arguments should be
     either:

    > a message sequence number,
    > a comma-separated list of message sequence numbers, or
    > a reference to an array of message sequence numbers.
     If the *Uid* parameter is true, then the arguments should be:

    > a message UID,
    > a comma-separated list of message UID's, or
    > a reference to an array of message UID's.
     If the target folder does not exist then it will be created.

     If move is sucessful, then it returns a true value. Furthermore, if
     the *Mail::IMAPClient* object is connected to a server that has the
     UIDPLUS capability, then the true value will be the comma-separated
     list of UID's for the newly copied messages. The list will be in the
     order in which the messages were moved. (Since move uses the copy
     method, the messages will be moved in numerical order.)

     If the move is not successful then move returns undef.

     Note that a move really just involves copying the message to the new
     folder and then setting the *\Deleted* flag. To actually delete the
     original message you will need to run expunge (or close).

namespace()
     The namespace method runs the NAMESPACE IMAP command (as defined in
     RFC 2342). When called in a list context, it returns a list of three
     references. Each reference looks like this:

          [ [ $prefix_1, $separator_1 ] , [ $prefix_2, $separator_2], [ $prefix_n , $separator_n] ]

     The first reference provides a list of prefices and separator
     charactors for the available personal namespaces.  The second
     reference provides a list of prefices and separator charactors for
     the available shared namespaces.  The third reference provides a list
     of prefices and separator charactors for the available public
     namespaces.

     If any of the three namespaces are unavailable on the current server
     then an 'undef' is returned instead of a reference. So for example if
     shared folders were not supported on the server but personal and
     public namespaces were both available (with one namespace each), the
     returned value might resemble this:

          ( [ "", "/" ] , undef, [ "#news", "." ] ) ;

     If the namespace method is called in scalar context, it returns a
     reference to the above-mentioned list of three references, thus
     creating a single structure that would pretty-print something like
     this:

          $VAR1 = [
          		[
          			[ $user_prefix_1, $user_separator_1 ] ,
          			[ $user_prefix_2, $user_separator_2],
          			[ $user_prefix_n , $user_separator_n]
          		] 	,					# or undef
          		[
          			[ $shared_prefix_1, $shared_separator_1 ] ,
          			[ $shared_prefix_2, $shared_separator_2],
          			[ $shared_prefix_n , $shared_separator_n]
          		] 	,					# or undef
          		[
          			[ $public_prefix_1, $public_separator_1 ] ,
          			[ $public_prefix_2, $public_separator_2],
          			[ $public_prefix_n , $public_separator_n]
          		] 	,					# or undef
          ];

     Or, to look at our previous example (where shared folders are
     unsupported) called in scalar context:

          $VAR1 = [
          		[
          			[
          				"" ,
          				"/",
          			],
          		],

          undef,

          [
          	[
          		"#news",
          		"."
          	],
          ],
          	];

on()
     The *on* method works just like the *since* method, below, except it
     returns a list of messages whose internal system dates are the same
     as the date supplied as the argument.

     =item parse_headers ()

     The *parse_headers* method accepts as arguments a message sequence
     number and a list of header fields. It returns a hash reference in
     which the keys are the header field names (without the colon) and the
     values are references to arrays of values. A picture would look
     something like this:

          $hashref = $imap->parse_headers(1,"Date","Received","Subject","To");
          $hashref = {
          	"Date" 	 	=> [ "Thu, 09 Sep 1999 09:49:04 -0400" ]  ,
               "Received"	=> [ q/
          	   	from mailhub ([111.11.111.111]) by mailhost.bigco.com
          	   	(Netscape Messaging Server 3.6)  with ESMTP id AAA527D for
          	   	<bigshot@bigco.com>; Fri, 18 Jun 1999 16:29:07 +0000
          	   	/, q/
          	   	from directory-daemon by mailhub.bigco.com (PMDF V5.2-31 #38473)
           	   	id <0FDJ0010174HF7@mailhub.bigco.com> for bigshot@bigco.com
           	   	(ORCPT rfc822;big.shot@bigco.com); Fri, 18 Jun 1999 16:29:05 +0000 (GMT)
          	   	/, q/
          	   	from someplace ([999.9.99.99]) by smtp-relay.bigco.com (PMDF V5.2-31 #38473)
          	        with ESMTP id <0FDJ0000P74H0W@smtp-relay.bigco.com> for big.shot@bigco.com; Fri,
          	   	18 Jun 1999 16:29:05 +0000 (GMT)
          	   	/] ,
          	"Subject" 	=> [ qw/ Help! I've fallen and I can't get up!/ ] ,
          	"To"		=> [ "Big Shot <big.shot@bigco.com> ] ,
          	} ;

     The text in the example for the "Received" array has been formated to
     make reading the example easier. The actual values returned are just
     strings of words separated by spaces and with newlines and carriage
     returns stripped off. The *Received* header is probably the main
     reason that the *parse_headers* method creates a hash of lists rather
     than a hash of values.

     If the second argument to *parse_headers* is 'ALL' or if it is
     unspecified then all available headers are included in the returned
     hash of lists.

     If you're not emotionally prepared to deal with a hash of lists then
     you can always call the fetch method yourself with the appropriate
     parameters and parse the data out any way you want to.

     If the *Uid* parameter is true then the first argument will be
     treated as a message UID. If the first argument is a reference to an
     array of message sequence numbers (or UID's if Uid is true), then
     *parse_headers* will be run against each message in the array. In
     this case the return value is a hash, in which the key is the message
     sequence number (or UID) and the value is a reference to a hash as
     described above.

     An example of using *parse_headers* to print the date and subject of
     every message in your smut folder could look like this:

          use Mail::IMAPClient;
          my $imap = Mail::IMAPClient->new( Server => $imaphost,
          				  User   => $login,
          				  Password=> $pass,
          				  Uid => 1,		# optional
          );

          $imap->select("smut");

          for my $h (

          # grab the Subject and Date from every message in my (fictional!) smut folder;
          # the first argument is a reference to an array listing all messages in the folder
          # (which is what gets returned by the $imap->search("ALL") method when called in
          # scalar context) and the remaining arguments are the fields to parse out

          # The key is the message number, which in this case we don't care about:
          values %{$imap->parse_headers( scalar($imap->search("ALL")) , "Subject", "Date")}
          	) {
          		# $h is the value of each element in the hash ref returned from parse_headers,
          		# and $h is also a reference to a hash.
          		# We'll only print the first occurance of each field because we don't expect more
          		# than one Date: or Subject: line per message.
          		 print map { "$_:\t$h->{$_}[0]\n"} keys %$h ;
          	}

recent()
     The recent method performs an IMAP SEARCH RECENT search against the
     selected folder and returns an array of sequence numbers (or UID's,
     if the *Uid* parameter is true) of messages that are recent.

recent_count()
     The *recent_count* method accepts as an argument a folder name. It
     returns the number of recent messages in the folder (as returned by
     the IMAP client command "STATUS folder RECENT"), or undef in the case
     of an error. The *recent_count* method was contributed by Rob Deker
     (deker@ikimbo.com).

rename()
     The rename method accepts two arguments: the name of an existing
     folder, and a new name for the folder. The existing folder will be
     renamed to the new name using the RENAME IMAP client command. rename
     will return a true value if successful, or undef if unsuccessful.

restore_message()
     The *restore_message* method is used to undo a previous
     *delete_message* operation (but not if there has been an intervening
     expunge or close).  The *IMAPClient* object must be in Selected status
     to use the *restore_message* method.

     The *restore_message* method accepts a list of arguments. If the
     *Uid* parameter is not set to a true value, then each item in the
     list should be either:

    > a message sequence number,
    > a comma-separated list of message sequence numbers,
    > a reference to an array of message sequence numbers, or
     If the *Uid* parameter is set to a true value, then each item in the
     list should be either:

    > a message UID,
    > a comma-separated list of UID's, or
    > a reference to an array of message UID's.
     The messages identified by the sequence numbers or UID's will have
     their *\Deleted* flags cleared, effectively "undeleting" the
     messages.  *restore_message* returns the number of messages it was
     able to restore.

     Note that *restore_messages* is similar to calling
     *unset_flag("\Deleted",@msgs)*, except that *restore_messages*
     returns a more meaningful value.

run()
     Like Perl itself, the *Mail::IMAPClient* module is designed to make
     common things easy and uncommon things possible. The run method is
     provided to make those uncommon things possible.

     The run method excepts one or two arguments. The first argument is a
     string containing an IMAP Client command, including a tag and all
     required arguments. The optional second argument is a string to look
     for that will indicate success. (The default is `/OK.*/').  The run
     method returns an array of output lines from the command, which you
     are free to parse as you see fit.

     The run method does not do any syntax checking, other than
     rudimentary checking for a tag.

     When run processes the command, it increments the transaction count
     and saves the command and responses in the History buffer in the same
     way other commands do. However, it also creates a special entry in
     the History buffer named after the tag supplied in the string passed
     as the first argument. If you supply a numeric value as the tag then
     you may risk overwriting a previous transaction's entry in the
     History buffer.

     If you want the control of run but you don't want to worry about the
     damn tags then see `"tag_and_run"' in this node, below.

search()
     The search method implements the SEARCH IMAP client command. Any
     argument supplied to search is prefixed with a space and appended  to
     the SEARCH IMAP client command. This method is another one of those
     situations where it will really help to have your copy of RFC2060
     handy, since the SEARCH IMAP client command contains a plethora of
     options and possible arguments.

     Remember that if your argument needs quotes around it then you must
     make sure that the quotes will be preserved when passing the
     argument. I.e. use `qq/"$arg"/' instead of `"$arg"'.

     The search method returns an array containing sequence numbers of
     messages that passed the SEARCH IMAP client command's search
     criteria. If the *Uid* parameter is true then the array will contain
     message UID's. If search is called in scalar context then a pointer
     to the array will be passed, instead of the array itself.

see()
     The see method accepts a list of one or more messages sequence
     numbers, or a single reference to an array of one or more message
     sequence numbers, as its argument(s). It then sets the "\Seen" flag
     for those message(s). Of course, if the *Uid* parameter is set to a
     true value then those message sequence numbers had better be unique
     message id's, but then you already knew that, didn't you?

     Note that specifying `$imap-'see(@msgs)> is just a shortcut for
     specifying `$imap-'set_flag("Seen",@msgs)>.

seen()
     The seen method performs an IMAP SEARCH SEEN search against the
     selected folder and returns an array of sequence numbers of messages
     that have already been seen (ie their SEEN flag is set).  If the
     *Uid* parameter is true then an array of message UID's will be
     returned instead. If called in scalar context than a pointer to the
     array (rather than the array itself) will be returned.

select()
     The select method selects a folder and changes the object's state to
     "Selected".  It accepts one argument, which is the name of the folder
     to select.

sentbefore()
     The *sentbefore* works just like `"sentsince"' in this node, below,
     except it searches for messages that were sent before the date
     supplied as an argument to the method.

senton()
     The *senton* works just like `"sentsince"' in this node, below,
     except it searches for messages that were sent on the exact date
     supplied as an argument to the method.

sentsince()
     The *sentsince* method accepts one argument, a date in either
     standard perl format (seconds since 1/1/1970, or as output by
     `time|perlfunc' in this node and as accepted by `localtime|perlfunc'
     in this node) or in the *date_text* format as defined in RFC2060
     (dd-Mon-yyyy, where Mon is the English-language three-letter
     abbreviation for the month).

     It searches for items in the currently selected folder for messages
     sent since the day whose date is provided as the argument. It uses
     the RFC822 *Date:* header to determine the *sentsince* date.

     In the case of arguments supplied as a number of seconds, the
     returned result list will include items sent on or after that day,
     regardless of whether they arrived before the specified time on that
     day. The IMAP protocol does not support searches at a granularity
     finer than a day, so neither do I. On the other hand, the only thing
     I check for in a *date_text* argument is that it matches the pattern
     `/\d\d-\D\D\D-\d\d\d\d/' (notice the lack of anchors),  so if your
     server lets you add something extra to a *date_text* string then so
     will *Mail::IMAPClient*.

separator()
     The separator method returns the character used as a separator
     character in folder hierarchies. On unix-based servers, this is often
     a forward slash (/). It accepts one argument, the name of a folder
     whose hierarchy's separator should be returned. If no folder name is
     supplied then the separator for the INBOX is returned, which probably
     is good enough.

set_flag()
     The *set_flag* method accepts the name of a flag as its first
     argument and a list of one or more messages  sequence numbers, or a
     single reference to an array of one or more message sequence numbers,
     as its next argument(s). It then sets the flag specified for those
     message(s). Of course, if the *Uid* parameter is set to a true value
     then those message sequence numbers had better be unique message id's,
     just as you'd expect.

     Note that when specifying the flag in question, the preceding
     backslash (\) is entirely optional. (For you, that is.
     *Mail::IMAPClient* still has remember to stick it in there before
     passing the command to the server. This is in fact so important that
     the method checks its argument and adds the backslash when necessary,
     which is why you don't have to worry about it overly much.)

setacl()
     The *setacl* method accepts three input arguments, a folder name, a
     user id (or authentication identifier, to use the terminology of
     RFC2086), and an access rights modification string. See RFC2086 for
     more information. (This is somewhat experimental and its
     implementation may change.)

since()
     The *since* method accepts a date in either standard perl format
     (seconds since 1/1/1970, or as output by `time', see Perlfunc (perl.info),
     and as accepted by `localtime', see Perlfunc (perl.info))
     or in the *date_text* format as defined in
     RFC2060 (dd-Mon-yyyy, where Mon is the English-language three-letter
     abbreviation for the month).  It searches for items in the currently
     selected folder for messages whose internal dates are on or after the
     day whose date is provided as the argument. It uses the internal
     system date for a message to determine if that message was sent since
     the given date.

     In the case of arguments supplied as a number of seconds, the
     returned result list will include items whose internal date is on or
     after that day, regardless of whether they arrived before the
     specified time on that day.

size()
     The size method accepts one input argument, a sequence number (or
     message UID if the *Uid* parameter is true). It returns the size of
     the message in the currently selected folder with the supplied
     sequence number (or UID).  The *IMAPClient* object must be in a
     Selected state in order to use this method.

status()
     The status method accepts one argument, the name of a folder (or
     mailbox, to use RFC2060's terminology), and returns an array
     containing the results of running the  IMAP STATUS client command
     against that folder. If additional arguments are supplied then they
     are appended to the IMAP STATUS client command string, separated from
     the rest of the string and each other with spaces.

     If status is not called in an array context then it returns a
     reference to an array rather than the array itself.

     The status method should not be confused with the Status method (with
     an uppercase 'S'), which returns information about the *IMAPClient*
     object. (See the section labeled `"Status Methods"' in this node,
     below).

subscribed()
     The *subscribed* method works like the *folders* method, above,
     except that the returned list (or array reference, if called in
     scalar context) contains only the subscribed folders.

tag_and_run()
     The *tag_and_run* method accepts one or two arguments. The first
     argument is a string containing an IMAP Client command, without a tag
     but with all required arguments. The optional second argument is a
     string to look for that will indicate success (without pattern
     delimiters).  The default is `OK.*'.

     The *tag_and_run* method will prefix your string (from the first
     argument) with the next transaction number and run the command. It
     returns an array of output lines from the command, which you are free
     to parse as you see fit. Using this method instead of run (above) will
     free you from having to worry about handling the tags (and from
     worrying about the side affects of naming your own tags).

uidnext()
     The uidnext method accepts one argument, the name of a folder, and
     returns the numeric string that is the next available message UID for
     that folder.

uidvalidity()
     The uidvalidity method accepts one argument, the name of a folder,
     and returns the numeric string that is the unique identifier validity
     value for the folder.

unseen()
     The *unseen* method performs an IMAP SEARCH UNSEEN search against the
     selected folder and returns an array of sequence numbers of messages
     that have not yet been seen (ie their SEEN flag is not set).  If the
     *Uid* parameter is true then an array of message UID's will be
     returned instead. If called in scalar context than a pointer to the
     array (rather than the array itself) will be returned.

     Note that when specifying the flag in question, the preceding
     backslash (\) is entirely optional.

unseen_count()
     The *unseen_count* method accepts the name of a folder as an argument
     and returns the number of unseen messages in that folder. If no
     folder argument is provided then it returns the number of unseen
     messages in the currently selected Folder.

unset_flag()
     The *unset_flag* method accepts the name of a flag as its first
     argument and a list of one or more messages sequence numbers, or a
     single reference to an array of one or more message sequence numbers,
     as its next argument(s). It then unsets the flag specified for those
     message(s). Of course, if the *Uid* parameter is set to a true value
     then those message sequence numbers had better be unique message id's,
     just as you'd expect.

Other IMAP Client Commands and the Default Method()
     IMAP Client Commands not otherwise documented have been implemented
     via an AUTOLOAD hack and use a default method.

     If a program calls a method that is not defined (or inherited) by the
     *IMAPClient* module then the *IMAPClient* module will assume that it
     is an IMAP client command. It will prefix the command with the next
     available transaction number (or tag value), and append to it the
     space-delimited list of arguments supplied to the unimplemented
     method (if any). It will then read lines of output from the imap
     session until it finds a line containing  the strings "OK" and
     "Completed", and return an array containing all of the lines of
     output (or, if called in scalar context, an array reference). If it
     finds "BAD" or "NO" instead of "OK" it returns undef.

     Eg:

          $imap->FOO("bar","an example","of the default");

     results in:

          "99 FOO bar an example of the default\r\n"

     being sent to the IMAP server (assuming that 99 is the current
     transaction number).

     Notice that we used an uppercase method name "FOO" so as not to
     conflict with future implementations of that IMAP command. If you run
     your script with warnings turned on (always a good idea, at least
     during testing), then you will receive warnings whenever you use a
     lowercase method name that has not been implemented. An exception to
     this is when you use certain common (yet unimplemented) methods that,
     if ever explicitly implemented, are guaranteed to behave just like
     the default method. To date, these are:

    store("$msg[,$msg2,$msg_n]", $flags)
          Invoke the STORE IMAP Client command to update a message's
          status on the server.

    copy($msg,$folder)
          Copy a message into a folder.

    subscribe($folder)
          Subscribe to a folder

    create($folder)
          Create a new folder.

    delete($folder)
          Delete a folder (and its contents).

    expunge
          Remove messages previously marked as deleted. (This is also
          documented under `"object methods"' in this node, above.)

     *CAUTION:* Once again, remember to quote your quotes if you want
     quotes to be part of the IMAP command string.

     You can also use the default method to override the behavior of
     implemented IMAP methods by changing the case of the method name,
     preferably to all-uppercase so as not to conflict with the Class
     method and accessor method namespace. For example, if you don't want
     the search method's behavior (which returns a list of message
     numbers) but would rather have an array of raw data returned from
     your search operation, you can issue the following snippet:

     	@raw = $imap->SEARCH("SUBJECT","Whatever...");

     which is slightly more efficient than the equivalent:

          my @msgs = $imap->search("SUBJECT","Whatever...");

          my @raw = $imap->Results;

Status Methods
     There are several object methods that return the status of the
     object. They can be used at any time to check the status of an
     *IMAPClient* object, but are particularly useful for determining the
     cause of failure when a connection and login are attempted as part of
     a single new method invocation. The status methods are:

       1. History The History method is almost identical to the *Results*
          method. Unlike the *Results* method, however, the IMAP command
          that was issued to create the results being returned is not
          included in the returned results.  If called in a scalar
          context, History returns an array reference rather than an array.

       2. IsUnconnected returns a true value if the object is currently in
          an *Unconnected* state.

       3. IsConnected returns a true value if the object is currently in
          either a *Connected, Authenticated*, or Selected state.

       4. IsAuthenticated returns a true value if the object is currently
          in either an Authenticated or Selected state.

       5. IsSelected returns a true value if the object is currently in a
          Selected state.

       6. LastError Internally *LastError* is implemented just like a
          parameter (as described in `"Parameters"' in this node, above).
          There is a *LastError* attribute and an eponymous accessor
          method which returns the *LastError* text string describing the
          last error condition encountered by the server.

          Note that some errors are more serious than others, so
          *LastError*'s value is only meaningful if you encounter an error
          condition that you don't like. For example, if you use the exists
          method to see if a folder exists and the folder does not exist,
          then an error message will be recorded in LastError even though
          this is not a particularly serious error. On the other hand, if
          you didn't use exists and just tried to select a non-existing
          folder, then select would return undef after setting *LastError*
          to something like "NO SELECT failed: Can't open mailbox
          <mailbox>: no such mailbox".  At this point it would be useful
          to print out the contents of *LastError* as you die.

       7. LastIMAPCommand New in version 2.0.4, *LastIMAPCommand* returns
          the exact IMAP command string to be sent to the server. Useful
          mainly in constructing error messages when *LastError* just
          isn't enough.

       8. Report The *Report* method returns an array containing a history
          of the IMAP session up to the point that *Report* was called. It
          is primarily meant to assist in debugging but can also be used
          to retrieve raw output for manual parsing. The value of the
          Clear parameter controls how many transactions are in the
          report. (See the discussion of Clear in `"parameters"' in this
          node, above.)

       9. Results The *Results* method returns an array containing the
          results of one IMAP client command.  It accepts one argument,
          the transaction number of the command whose results are to be
          returned. If transaction number is unspecified then *Results*
          returns the results of the last IMAP client command issued. If
          called in a scalar context, *Results* returns an array reference
          rather than an array.

      10. State The State method returns a numerical value that indicates
          the current status of the *IMAPClient* object. If invoked with
          an argument, it will set the object's state to that value. If
          invoked without an argument, it behaves just like Status, below.

          Normally you will not have to invoke this function. An exception
          is if you are bypassing the *Mail::IMAPClient* module's connect
          and/or login modules to set up your own connection (say, for
          example, over a secure socket), in which case you must manually
          do what the connect and login methods would otherwise do for you.

      11. Status The Status method returns a numerical value that
          indicates the current status of the *IMAPClient* object. (Not to
          be confused with the status method, all lower-case, which is the
          implementation of the STATUS IMAP client command.)

      12. Transaction The Transaction method returns the tag value (or
          transaction number) of the last IMAP client command.

REPORTING BUGS
==============

   Please feel free to e-mail the author at the below address if you
encounter any strange behaviors.  When reporting a bug, please be sure to
include the following:

   - As much information about your environment as possible. I especially
need to know which version of Mail::IMAPClient you are running and the
type/version of IMAP server to which you are connecting.

   - As detailed a description of the problem as possible. (What are you
doing? What happens?)

   - An example script that demonstrates the problem (preferably with as
few lines of code as possible!)  and which calls the Mail::IMAPClient's
new method with the Debug parameter set to "1".

   - Output from the example script when it's running with the Debug
parameter turned on. You can edit the output to remove (or preferably to
"X" out) sensitive data, such as hostnames, user names, and passwords, but
PLEASE do not remove the text that identifies the TYPE of IMAP server to
which you are connecting. Note that in the latest versions of
Mail::IMAPClient, debugging does not print out the user or password from
the login command line. However, if you use some other means of
authenticating then you may need to edit the debugging output with an eye
to security.

   - Don't be surprised if I come back asking for a trace of the problem.
To provide this, you should create a file called *.perldb* in your current
working directory and include the following line of text in that file:

   `&parse_options("NonStop=1 LineInfo=mail_imapclient_db.out");'

   For your debugging convenience, a sample .perldb file, which was
randomly assigned the name `sample.perldb', is provided in the
distribution.

   Next, without changing your working directory, debug the example script
like this: `perl -d example_script.pl [ args ]'

   Note that in these examples, the script that demonstrates your problem
is named "example_script.pl" and the trace output will be saved in
"mail_imapclient_db.out". You should change these to suite your needs.

AUTHOR
======

     David J. Kernen
     The Kernen Consulting Group, Inc
     david.kernen@erols.com

COPYRIGHT
=========

     Copyright 1999, 2000 The Kernen Group, Inc.
          All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the terms of either:

a) the "Artistic License" which comes with this Kit, or
b) the GNU General Public License as published by the Free Software Foundation; either  version 1, 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 either the GNU General Public
License or the Artistic License for more details.

manipulate Internet format (RFC 822) mail messages
**************************************************

NAME
====

   Mail::Internet - manipulate Internet format (RFC 822) mail messages

SYNOPSIS
========

     use Mail::Internet;

DESCRIPTION
===========

   This package provides a class object which can be used for reading,
creating, manipulating and writing a message with RFC822 compliant headers.

CONSTRUCTOR
===========

new ( [ ARG ], [ OPTIONS ] )
     ARG is optiona and may be either a file descriptor (reference to a
     GLOB) or a reference to an array. If given the new object will be
     initialized with headers and body either from the array of read from
     the file descriptor.

     OPTIONS is a list of options given in the form of key-value pairs,
     just like a hash table. Valid options are

    Header
          The value of this option should be a `Mail::Header' object. If
          given then Mail::Internet will not attempt to read a mail header
          from ARG, if it was specified.

    Body
          The value of this option should be a reference to an array which
          contains the lines for the body of the message. Each line should
          be terminated with \n (LF). If Body is given then Mail::Internet
          will not attempt to read the body from ARG (even if it is
          specified).

     The Mail::Header options Modify, MailFrom and FoldLength may also be
     given.

METHODS
=======

body ()
     Returns the body of the message. This is a reference to an array.
     Each entry in the array represents a single line in the message.

print_header ( [ FILEHANDLE ] )
print_body ( [ FILEHANDLE ] )
print ( [ FILEHANDLE ] )
     Print the header, body or whole message to file descriptor
     *FILEHANDLE*.  *$fd* should be a reference to a GLOB. If *FILEHANDLE*
     is not given the output will be sent to STDOUT.

          $mail->print( \*STDOUT );  # Print message to STDOUT

as_string ()
     Returns the message as a single string.

as_mbox_string ( [ ALREADY_ESCAPED ] )
     Returns the message as a string in mbox format.  `ALREADY_ESCAPED', if
     given and true, indicates that ->escape_from has already been called
     on this object.

head ()
     Returns the `Mail::Header' object which holds the headers for the
     current message

UTILITY METHODS
===============

   The following methods are more a utility type than a manipulation type
of method.

remove_sig ( [ NLINES ] )
     Attempts to remove a users signature from the body of a message. It
     does this by looking for a line equal to `'-- '' within the last
     `NLINES' of the message. If found then that line and all lines after
     it will be removed. If `NLINES' is not given a default value of 10
     will be used. This would be of most use in auto-reply scripts.

tidy_body ()
     Removes all leading and trailing lines from the body that only contain
     white spaces.

reply ()
     Create a new object with header initialised for a reply to the current
     object. And the body will be a copy of the current message indented.

add_signature ( [ FILE ] )
     Append a signature to the message. FILE is a file which contains the
     signature, if not given then the file "$ENV{HOME}/.signature" will be
     checked for.

send ( [ type [ args.. ]] )
     Send a Mail::Internet message using Mail::Mailer.  Type and args are
     passed on to `Mail::Mailer'

smtpsend ( [ OPTIONS ] )
     Send a Mail::Internet message via SMTP, requires Net::SMTP

     The return value will be a list of email addresses that the message
     was sent to. If the message was not sent the list will be empty.

     Options are passed as key-value pairs. Current options are

    Host
          Name of the SMTP server to connect to, or a Net::SMTP object to
          use

          If Host is not given then the SMTP host is found by attempting
          connections first to hosts specified in `$ENV{SMTPHOSTS}', a
          colon separated list, then mailhost and `localhost'.

    To
    Cc
    Bcc
          Send the email to the given addresses, each can be either a
          string or a reference to a list of email addresses. If none of
          To, <Cc> or Bcc are given then the addresses are extracted from
          the message being sent.

    Hello
          Send a HELO (or EHLO) command to the server with the given name.

    Port
          Port number to connect to on remote host

    Debug
          Debug value to pass to Net::SMPT, see <Net::SMTP>

nntppost ( [ OPTIONS ] )
     Post an article via NNTP, requires Net::NNTP.

     Options are passed as key-value pairs. Current options are

    Host
          Name of NNTP server to connect to, or a Net::NNTP object to use.

    Port
          Port number to connect to on remote host

    Debug
          Debug value to pass to Net::NNTP, see <Net::NNTP>

escape_from ()
     It can cause problems with some applications if a message contains a
     line starting with ``From '', in particular when attempting to split
     a folder.  This method inserts a leading ``''> on anyline that
     matches the regular expression `/^'*From/>

unescape_from ()
     This method will remove the escaping added by escape_from

SEE ALSO
========

   See Mail/Header, Mail/Address,

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

COPYRIGHT
=========

   Copyright (c) 1995-7 Graham Barr. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

An abstract base class of mail filters
**************************************

NAME
====

   Mail::IspMailGate::Filter - An abstract base class of mail filters

SYNOPSIS
========

     # Create a filter
     my($filter) = Mail::IspMailGate::Filter->new({});

     # Call him for filtering a given mail (aka MIME::Entity)
     my ($attr) = {
         'entity' => $entity,    # a MIME::Entity object
         'parser' => $parser     # a MIME::Parser object
     };
     my($res) = $filter->doFilter($attr);

VERSION AND VOLATILITY
======================

     $Revision 1.0 $
     $Date 1998/04/05 18:19:45 $

DESCRIPTION
===========

   This class is the abstract base class of email filters. It implements
the main functionality every email filter should have, such as recursive
filtering on multipart MIME-message. You create a new filter by deriving a
subclass from Mail::IspMailGate::Filter. Usually you only need to
implement your own versions of the getSign, filterFile and IsEq methods.

   Most filters are in/out filters. For example the packer module can do
compression or decompression and the PGP module can do encryption and
decryption. These filters are derived from
Mail::IspMailGate::Filter::InOut, which is itself derived from
Mail::IspMailGate::Filter. The main idea of these filters is that they
have two directions, a 'positive' direction (or 'in' mode) and a negative
direction (or 'out' mode).

PUBLIC INTERFACE
================

*new $ATTR*
     *Class method.* Create a new filter instance; by passing the hash ref
     ATTR you configure the filters behaviour. For example, the PGP filter
     typically needs a user ID, the virus scanner needs a path to the
     external virus scanning binary and so on.

     The method returns an object for success or an error message
     otherwise.

getSign
     *Instance method.* Returns a header name, that will be inserted into
     the MIME entities head. For example, the base class inserts a header
     field "X-ispMailGateFilter". Note that more than one header line will
     be inserted if you apply multiple filters.

     You should override this method.

*filterFile $ATTR*
     *Instance method.* This method is called for modifying a given, single
     part of the MIME entity. You can rely on the following attributes
     being set in the hash ref ATTR:

    body
          The MIME::Body object representing the part. The true data is
          stored as a file on disk. (It's a MIME::Body::File object, to be
          precise.) In particular this means that you can create a handle
          referring to the object with

               $fh = $ATTR->{'body'}->open("r") or die $!;

          If you need to work with external binaries you might use

               $path = $ATTR->{'body'}->path();

          If the external binaries create a new file and you want to
          replace the old file, use

               $ATTR->{'body'}->path($newPath);

          See `MIME::Body(3)' in this node for detailed information.

    head
          The MIME::Head object representing this parts head. See
          `MIME::Head(3)' in this node for detailed information.

    globHead
          The MIME::Head object of the top level MIME entity. If you are
          working on a single part entity, this is just the same as the
          'head' attribute.

    parser
          The Mail::IspMailGate::Parser object used for parsing the entity.
          This is mostly usefull for using the logging methods

               $ATTR->{'parser'}->Debug("A debugging message");
               $ATTR->{'parser'}->Error("An error message");
               $ATTR->{'parser'}->Fatal("A fatal error message");

          Note that the latter will abort the currently running thread,
          use is discouraged. Instead you should throw a Perl exception by
          calling die.

     The filterFile method returns an empty string for success or an error
     message otherwise. You should override this function, but calling

          $self->SUPER::filterFile($ATTR)

     at the beginning is strongly encouraged.

*mustFilter $ENTITY*
     *Instance method.* This method determines, whether the doFilter method
     ought to be executed. Usually it looks at the headers of the MIME
     entity $ENTITY, for example the InOut class supresses filtering
     twice. The method returns FALSE to supress filtering, TRUE otherwise.

*hookFilter $ENTITY*
     *Instance method.* If filtering was needed (see doFilter) and done,
     this method is called, mainly for modifying the headers of the MIME
     entity $ENTITY. When overriding this method, you should usually start
     with calling

          $self->SUPER::hookFilter($ENTITY);

*doFilter $ATTR*
     *Instance method.* This method builds the frame of the filtering
     process.  It calls mustFilter. If this method returns TRUE, the
     recdoFilter and hookFilter methods are executed.

     The hash ref $ATTR contains attributes 'entity', 'parser' correspond
     to the same attributes of the filterFile method.

*recdoFilter $ATTR*
     *Instance method.* Called by doFilter for filtering a MIME entity.
     It calls the filterFile method for singlepart entities. For multipart
     entities, it calls itself recursively for any part.

     The hash ref $ATTR corresponds to the arguments of doFilter.

*IsEq $CMP*
     *Instance method.* The IspMailGate program can handle multiple
     recipients at the same time, which is obviously important for
     performance reasons.  For any recipient, a list of filters is built
     that the mail is fed into.  In most cases these filter lists or at
     least parts of them are equivalent, so there's no need to pass the
     mail into both filter lists.

     This method is called for determining whether two filter objects
     ($self and $CMP) are equivalent. In other words: If I feed a mail
     into both objects, the method tells me whether I can expect the same
     result. For example, a simple implementation of IsEq would just look
     at the filter object classes and return TRUE, if both objects are of
     the same classes, but FALSE otherwise:

          sub IsEq ($$) {
              my($self, $CMP) = @_;
              ref($self) eq ref($CMP);
          }

     The above is the default implementation, so it's quite likely that
     you need to override this method.

Add a banner message to outgoing mails
**************************************

NAME
====

   Mail::IspMailGate::Filter::Banner - Add a banner message to outgoing
mails

SYNOPSIS
========

     # Create a filter
     my($filter) = Mail::IspMailGate::Filter::Banner->new({
         'plain' => '/etc/mail/banner.plain',
         'html' => '/etc/mail/banner.html'
     });

     # Call him for filtering a given mail (aka MIME::Entity)
     my ($attr) = {
         'entity' => $entity,    # a MIME::Entity object
         'parser' => $parser     # a MIME::Parser object
     };
     my($res) = $filter->doFilter($attr);

DESCRIPTION
===========

   This class can be used for adding a banner message to the top of
outgoing E-Mails. It knows about MIME types and can deal with plain text
or HTML messages.

PUBLIC INTERFACE
================

*new $ATTR*
     *Class method.* Create a new filter instance; you may supply two
     attributes: `plain' is the name of a banner file to attach to plain
     text mails and html is similar for HTML mails. The difference is,
     that the latter may contain HTML tags.

Encrypt and decrypt mails with PGP
**********************************

NAME
====

   Mail::IspMailGate::Filter::PGP - Encrypt and decrypt mails with PGP

SYNOPSIS
========

     # Create a filter object
     my($scanner) = Mail::IspMailGate::Filter::VirScan->new({
         'uid' => 'Jochen Wiedmann <joe@ispsoft.de>'
     });

     # Call it for filtering the MIME entity $entity and pass it a
     # Mail::IspMailGate::Parser object $parser
     my($result) = $scanner->doFilter({
         'entity' => $entity,
         'parser' => $parser
         });
     if ($result) { die "Error: $result"; }

VERSION AND VOLATILITY
======================

     $Revision 1.0 $
     $Date 1998/04/05 18:46:12 $

DESCRIPTION
===========

   This class implements an encrypting and decrypting filter based on PGP.
It is derived from the abstract base class Mail::IspMailGate::Filter.  For
details of an abstract filter see Mail/IspMailGate/Filter.

   The PGP module is based on the MIME::Decoder::PGP module which is using
an external PGP binary. The filter module is designed for installation on
two servers: When sending mail from one server to the other mails get
automatically encrypted on the sending server and decrypted on the
receiving server. Of course both servers need the IspMailGate package and
PGP installed. Installation typically includes creating an own secret and
public key ring which is specifically dedicated to IspMailGate.

INSTALLATION AND CUSTOMIZATION
==============================

Patching the MIME-tools
-----------------------

   Unfortunately the current version of the MIME-tools (4.116, as of this
writing) has a minor bug that make the MIME::Decoder::PGP module unusable.
This bug was reported to Eryq, the MIME-tools author and will be fixed in
the next release. The patch is quite easy:

     *** /usr/lib/perl5/site_perl/MIME/ParserBase.pm Thu Feb 12 04:11:27 1998
     --- lib/MIME/ParserBase.pm      Thu Apr  9 12:22:44 1998
     ***************
     *** 518,523 ****
     --- 518,524 ----
                 $ent->effective_type('application/octet-stream');
                 $decoder = new MIME::Decoder 'binary';
             }
     +       $decoder->head($head);

             # Obtain a filehandle for reading the encoded information:
             #    We have two different approaches, based on whether or not we

   In other words, just use your favourite text editor to edit the file
lib/MIME/ParserBase.pm of the MIME-tools distribution and add the line
marked with a plus sign as line 521. Then reinstall the MIME modules.

Creating a key ring
-------------------

   Before starting to use the PGP module, you have to create a public and
private keyring of the ispmailgate user. If you already have an appropriate
keyring, this is done by copying the files `pubring.pgp', `secring.pgp'
and `randseed.bin' to the `.pgp' subdirectory of the ispmailgate users
home directory. Note that your personal keyring is not appropriate.  An
anonymous user representing your information (an "info" user, for example)
might be more appropriate.

   Do not forget to set the file permissions the right way. For example you
might do the following:

     su
     mkdir ~ispmailgate/.pgp
     cp ~info/.pgp/pubring.pgp ~ispmailgate/.pgp
     cp ~info/.pgp/secring.pgp ~ispmailgate/.pgp
     cp ~info/.pgp/randseed.bin ~ispmailgate/.pgp
     chown -R ispmailgate ~ispmailgate/.pgp
     chgrp -R ispmailgate ~ispmailgate/.pgp
     chmod 755 ~ispmailgate/.pgp
     chmod 600 ~ispmailgate/.pgp/*

   If you don't have an appropriate keyring, you can instead create a new
one. This is done with the following command:

     su - ispmailgate -c "pgp -kg"

   PGP will ask you some questions, for example:

RSA key size
     I recommend using a value of 1024 bit; IspMailGate is not an
     interactive application and it doesn't hurt, if encryption and
     decryption take a little bit longer.

user ID
     Choose an appropriate user ID for representing your organization, for
     example

          FooBar Inc. <info@foobar.com>

     Do not choose the same user ID's and or keyrings on both ends. For
     example another user ID might be

          FooBar Inc., Department Stuttgart <info@stuttgart.foobar.com>

pass phrase
     Enter a random word (you'll be asked to repeat it), note that what you
     enter is usually not visible on the terminal. Remember this pass
     phrase for later use!

Configuring the PGP module
--------------------------

   Next step is editing the Mail::IspMailGate::Config module. In particular
you have to enter values for the following variables:

$cfg->{'pgp'}->{'uid'}
     This is the default user ID for encrypting emails. (You might override
     it with the uid attribute of the Mail::IspMailGate::Filter::PGP
     objects, see below.) Example:

          $PGP_UID = 'FooBar Inc. <info@foobar.com>';

$cfg->{'pgp'}->{'uids'}
     This is a hash ref of user ID's that you want to encrypt
     automatically.  The hash keys are the user ID's, the hash values are
     the respective pass phrases. Example:

          $PGP_UIDS = {
              'FooBar Inc. <info@foobar.com>' => 'foobar'
          };

$cfg->{'pgp'}->{'encrypt_command'}
     A command template for encrypting messages. Example:

          $cfg->{'pgp'}->{'encrypt_command'} =
              '/usr/bin/pgp -fea $uid +verbose=0';

     Note the use of single quotes to prevent expansion of the variable
     $uid. This variable will be expanded my the MIME::Decoder module.

$cfg->{'pgp'}->{'decrypt_command'}
     Likewise for decryption. Example:

          $cfg->{'pgp'}->{'decrypt_command'} =
              '/usr/bin/pgp -f +verbose=0';

     You might miss a variable $pass or something sililar here, as
     decryption requires a pass phrase. Pgp has no command line option for
     setting the pass phrase (Security reasons, might be visible in ps
     output), but it accepts an environment variable PGPPASS.  This
     variable gets set automatically.

Creating filter rules
---------------------

   Recall the situation from above. We have the FooBar headquarters and
the department in Stuttgart. The headquarter might use the following rule
for encrypting mails to the department:

     { 'recipients' => '\\@stuttgart.foobar.com^',
       'filters' => [ Mail::IspMailGate::Filter::PGP->new({
     	'uid' => 'FooBar Inc., Department Stuttgart'
     	    . ' <info@stuttgart.foobar.com>',
           'direction' => 'pos'
     	}) ]
     },
     { 'recipients' => '\\@stuttgart.foobar.com^',
       'filters' => [ Mail::IspMailGate::Filter::PGP->new({
           'direction' => 'neg'
     	}) ]
     }

   Likewise the following might be used at the department of Stuttgart:

     { 'recipients' => '\\@hq.foobar.com^',
       'filters' => [ Mail::IspMailGate::Filter::PGP->new({
     	'uid' => 'FooBar Inc. <info@foobar.com>',
           'direction' => 'pos'
     	}) ]
     },
     { 'recipients' => '\\@hq.foobar.com^',
       'filters' => [ Mail::IspMailGate::Filter::PGP->new({
           'direction' => 'neg'
     	}) ]
     }

   If you use multiple filters (for example the PGP filter might well be
used together with a compressing filter), note the following:

   When encrypting a mail, the PGP filter *must* always be the last
filter, because what the filter does is mainly choosing a certain type for
the content-transfer-encoding. On the other hand, the PGP filter must be
the first one, when decrypting a mail. Thus the headquarters setup for
both compressing and decrypting mails from the headquarter to the
department in Stuttgart and vice versa might look like this:

     { 'recipients' => '\\@stuttgart.foobar.com^',
       'filters' => [
           Mail::IspMailGate::Filter::Packer->new({
     	    'packer' => 'gzip',
     	    'direction' => 'pos'
               }),
           Mail::IspMailGate::Filter::PGP->new({
     	    'uid' => 'FooBar Inc., Department Stuttgart'
     	         . ' <info@stuttgart.foobar.com>',
               'direction' => 'pos'
     	    })
           ]
     },
     { 'recipients' => '\\@stuttgart.foobar.com^',
       'filters' => [
           Mail::IspMailGate::Filter::PGP->new({
     	    'uid' => 'FooBar Inc., Department Stuttgart'
     	         . ' <info@stuttgart.foobar.com>',
               'direction' => 'neg'
     	    })
           Mail::IspMailGate::Filter::Packer->new({
     	    'packer' => 'gzip',
     	    'direction' => 'neg'
               })
           ]
     }

SEE ALSO
========

   `ispMailGate' in this node, see Mail/IspMailGate/Filter,

Compressing emails
******************

NAME
====

   Mail::IspMailGate::Filter::Packer  - Compressing emails

SYNOPSIS
========

     # Create a Packer object for compression
     my($packer) = Mail::IspMailGate::Filter::Packer->new({
         'packer' => 'gzip',
         'direction' => 'pos'
     });

     # Create a Packer object for decompression
     my($packer) = Mail::IspMailGate::Filter::Packer->new({
         'packer' => 'gzip',
         'direction' => 'neg'
     });

     # Create a Packer object for automatic compression/decompression
     my($packer) = Mail::IspMailGate::Filter::Packer->new({
         'packer' => 'gzip'
     });

     # Call the filter
     my($res) = $packer->doFilter({
         'entity' => $entity,  # the MIME::Entity which is to be filtered
         'parser' => $parser
     });

VERSION AND VOLATILITY
======================

     $Revision 1.0 $
     $Date 1998/04/05 18:46:12 $

DESCRIPTION
===========

   This class is the Packer (compressing emails) derived from
Mail/IspMailGate/Filter, (refer to the manpage).
You can specify the attribute 'direction' with the constructor, so you can
force to act only in one direction: 'pos' only compressing and 'neg' only
for decompressing. If you specify no direction it will be guessed in the
function mustFilter. If the message has never been Filter by Packer it
chooses 'pos', else it checks in which direction this has happened and
chooses the opposite. You can also specify the attribute 'packer' in the
constructor to set the comressor type for direction 'pos'.  The supported
packer are configured in *$cfg-*{'packer'}> in each direction with a
template for the *system()* command.  It overrides the function
filterFile, mustFilter, *hookFile* and getSign.

PUBLIC INTERFACE
================

*mustFilter ENTITY*
     It determines the direction as described in DESCRIPTION and stores it
     in $self->{'recDirection'}. If the direction is 'neg' it also tries to
     determine the packer which was used for the compressing to guarantee
     a correct decompressing. If this failes it returns 0 and the email
     will not be decompressed.  The same happens if this obejct has the
     attribute 'direction' and this attribute equals the sign in the
     MIME-header which is set in hookFilter. The packer which is to use
     (if possible) is stored in $self->{'recPacker'}.

*filterFile FILENAME*
     Does the (de)compressing of a part of the MIME-message depending on
     $self->{'recDirection'} and $self->{'recPacker'}.

*hookFilter ENTITY*
     This function sets the direction in the header of the message as well
     which packer was used.

   Additionaly we have the function:

*sub setEncoding ATTR*
     Where the attribute 'direction' specifies in which direction Packer
     acts at the moment and 'head' is the head of a subpart of the whole
     entity. This function sets in 'head' the
     'Content-Transfer-Encoding'. It is set to base64 if the direction is
     'pos' else it restores the old one which is stored in
     'X-ispMailGate-Packer-PEncoding'. If this cannot be determined we
     assume base64.  It is called by the overriden filterFile to guarantee
     a correct encoding of the email.

Scanning emails for Viruses
***************************

NAME
====

   Mail::IspMailGate::Filter::VirScan  - Scanning emails for Viruses

SYNOPSIS
========

     # Create a filter object
     my($scanner) = Mail::IspMailGate::Filter::VirScan->new({});

     # Call it for filtering the MIME entity $entity and pass it a
     # Mail::IspMailGate::Parser object $parser
     my($result) = $scanner->doFilter({
         'entity' => $entity,
         'parser' => $parser
         });
     if ($result) { die "Error: $result"; }

DESCRIPTION
===========

   This class implements a Virus scanning email filter. It is derived from
the abstract base class Mail::IspMailGate::Filter. For details of an
abstract filter see Mail/IspMailGate/Filter.

   The virus scanner class needs an external binary which has the ability
to detect viruses in given files, like VirusX from http://www.antivir.com.
What the module does is extracting files from the email and passing them
to the scanner. Extracting includes dearchiving .zip files, .tar.gz files
and other known archive types by using external dearchiving utilities like
unzip, *tar* and *gzip*. Known extensions and dearchivers are
configurable, so you can customize them for your own needs.

CUSTOMIZATION
=============

   The virus scanner module depends on some items in the
Mail::IspMailGate::Config module:

$cfg->{'antivir_path'}
     Path of the AntiVir binary, for example

          $cfg->{'antivir_path'} = '/usr/bin/antivir';

$cfg->{virscan}->{scanner}
     A template for calling the external virus scanner; example:

          $cfg->{'virscan'}->{'scanner'} =
          	'$antivir_path -rs -nolnk -noboot $ipaths';

     The template must include either of the variable names $ipath or
     $ipaths; the former must be used, if the virus scanner cannot accept
     more than one file name with one call. Note the use of single quotes
     which prevent expanding the variable name!

     Additionally the pattern $antivir_path may be used for the path to
     the antivir binary.

$cfg->{virscan}->{deflater}
     This is an array ref of known archive deflaters. Each element of the
     array is a hash ref with the attributes cmd, a template for calling
     the dearchiver and pattern, a Perl regular expression for detecting
     file names which refer to archives that this program might extract.
     An example which configures the use of unzip, `tar' and `gzip':

          $cfg->{'virscan'}->{'deflater'} =
              [ { pattern => '\\.(tgz|tar\\.gz|tar\\.[zZ])$',
                  cmd => '$gzip_path -cd $ipath | /bin/tar -xf -C $odir'
                },
                { pattern => '\\.tar$',
                  cmd => '$tar_path -xf -C $odir'
          	  },
          	  { pattern => '\\.(gz|[zZ])$',
                  cmd => '$gzip_path -cd $ipath >$opath'
                },
                { pattern => '\\.zip$',
                  cmd => '$unzip_path $ifile -d $odir'
                }
              ];

     Again, note the use of single quotes to prevent variable expansion and
     double backslashes for passing a single backslash in the Perl regular
     expressions. See Perlre (perl.info), for details of
     regular expressions.

     The command template can use the following variables:

    $ipath
          Full filename of the archive being deflated

    $idir
    $ifile
          Directory and file name portion of the archive

    $odir
          Directory where the archive must be extracted to; if your
          dearchiver doesn't support an option -directory or something
          similar, you need to create a subshell. For example the
          following might be used for an LhA deflater:

               { 'pattern' => '\\.(lha|lzx)',
                  'cmd' => '(cd $odir; lha x $ipath)'
               }

    $ofile
    $opath
          Same as $ifile and $odir/$ofile; for example gzip needs this,
          when it runs as a standalone deflater and not as a backend of
          tar.

    $gzip_path
    $tar_path
    $unzip_path
    $lha_path
    $unarj_path
          These are the paths of the corresponding binaries and read from
          $cfg->{'gzip_path'}, $cfg->{'tar_path'} and so on.

PUBLIC INTERFACE
================

*checkFile $ATTR, $FILE*
     This function is called for every part of a MIME-message from within
     the filterFile method. It receives the arguments $ATTR (same as the
     $ATTR argument of filterFile) and $FILE, the filename where the MIME
     part is stored. If it detects $FILE to be an archive, it calls
     checkArchive for deflating it and building a list of files contained
     in the archive. If another archive is found, it calls checkArchive
     again.

     Finally, after building a list of files, it calls the virus scanner.
     If the scanner can handle multiple files, a single call occurs,
     otherwise the scanner will be called for any file. See
     `CONFIGURATION' in this node above.

*checkArchive $ATTR, $IPATH, $DEFLATER*
     This function is called from within checkFile to extract the archive
     $IPATH by using the $DEFLATER->{'cmd'} ($DEFLATER is an element from
     the deflater list). The $ATTR argument is the same as in checkFile.

     The function creates a new temporary directory and extracts the
     archive contents into that directory. Finally it returns a list of
     files that have been extracted.

HasVirus
          $hasVirus = $self->HasVirus($OUTPUT)

     (Instance method) This method takes the string $OUTPUT, which is a
     message emitted by the virus scanner and parses it for possible virus
     warnings.  The method returns TRUE, if such warnings are detected or
     FALSE otherwise.

     The default implementation knows about the output of the *AntiVir*
     virus scanner. To use the filter with other virus scanners, you
     typically dervice a subclass from it which overrides this method.

SEE ALSO
========

   `ispMailGate' in this node, see Mail/IspMailGate/Filter,

Perl extension for detecting mailing list messages
**************************************************

NAME
====

   Mail::ListDetector - Perl extension for detecting mailing list messages

SYNOPSIS
========

     use Mail::ListDetector;

DESCRIPTION
===========

   This module analyzses `Mail:;Internet' in this node objects. It returns
a Mail/ListDetector/List, object
representing the mailing list.

   The RFC2369 mailing list detector is also capable of matching some
Mailman and Ezmlm messages. It is deliberately checked last to allow the
more specific Mailman and Ezmlm parsing to happen first, and more
accurately identify the type of mailing list involved.

METHODS
=======

new()
=====

   This method is the core of the module. Pass it a Mail/Internet,
object, it will either return a
Mail/ListDetector/List, object that describes the
mailing list that the message was posted to, or undef if it appears not to
have been a mailing list post.

EMAILS USED
===========

   This module includes a number of sample emails from various mailing
lists. In all cases, mails are used with permission of the author, and
must not be distributed separately from this archive. If you believe I may
have accidentally used your email or content without permission, contact
me, and if this turns out to be the case I will immediately remove it from
the latest version of the archive.

BUGS
====

   * A lot of the code applies fairly simple regular expressions to email
     address to extract information. This may fall over for really weird
     email addresses, but I'm hoping no-one will use those for names of
     mailing lists.

   * The majordomo and smartlist recognisers don't have much to go on, and
     therefore are probably not as reliable as the other detectors.  This
     is liable to be hard to fix.

AUTHOR
======

   Michael Stevens - michael@etla.org.

SEE ALSO
========

   perl(1).

base class for mailing list detectors
*************************************

NAME
====

     Mail::ListDetector::Detector::Base - base class for mailing list detectors

SYNOPSIS
========

     use Mail::ListDetector::Detector::Base;

DESCRIPTION
===========

   Abstract base class for mailing list detectors, should not be
instantiated directly.

METHODS
=======

new()
-----

   Provides a simple constructor for the class. Accepts an optional data
argument and stores that argument in the object if it is supplied.

match()
-------

   This just dies, and should be implemented in any subclass.

BUGS
====

   No known bugs.

AUTHOR
======

   Michael Stevens - michael@etla.org.

Ezmlm message detector
**********************

NAME
====

   Mail::ListDetector::Detector::Ezmlm - Ezmlm message detector

SYNOPSIS
========

     use Mail::ListDetector::Detector::Ezmlm;

DESCRIPTION
===========

   An implementation of a mailing list detector, for ezmlm.

METHODS
=======

new()
-----

   Inherited from Mail/ListDetector/Detector/Base.

match()
-------

   Accepts a Mail/Internet, object and returns either
a Mail/ListDetector/List, object if it is a
post to an ezmlm mailing list, or undef.

BUGS
====

   No known bugs.

AUTHOR
======

   Michael Stevens - michael@etla.org.

Listar message detector
***********************

NAME
====

   Mail::ListDetector::Detector::Listar - Listar message detector

SYNOPSIS
========

     use Mail::ListDetector::Detector::Listar;

DESCRIPTION
===========

   An implementation of a mailing list detector, for Listar.

   This seems to only match older Listar list versions - newer ones appear
to be rfc2369 compliant, and are recognised as that instead.

METHODS
=======

new()
-----

   Inherited from Mail/ListDetector/Detector/Base.

match()
-------

   Accepts a Mail/Internet, object and returns either
a Mail/ListDetector/List, object if it is a
post to a listar mailing list, or undef.

BUGS
====

   None known.

AUTHOR
======

   Michael Stevens - michael@etla.org.

Mailman message detector
************************

NAME
====

   Mail::ListDetector::Detector::Mailman - Mailman message detector

SYNOPSIS
========

     use Mail::ListDetector::Detector::Mailman;

DESCRIPTION
===========

   An implementation of a mailing list detector, for GNU Mailman.

METHODS
=======

new()
-----

   Inherited from Mail/ListDetector/Detector/Base.

match()
-------

   Accepts a Mail/Internet, object and returns either
a Mail/ListDetector/List, object if it is a
post to a Mailman mailing list, or undef.

BUGS
====

   No known bugs.

AUTHOR
======

   Michael Stevens - michael@etla.org.

Majordomo message detector
**************************

NAME
====

   Mail::ListDetector::Detector::Majordomo - Majordomo message detector

SYNOPSIS
========

     use Mail::ListDetector::Detector::Majordomo;

DESCRIPTION
===========

   An implementation of a mailing list detector, for majordomo.

METHODS
=======

new()
-----

   Inherited from Mail/ListDetector/Detector/Base.

match()
-------

   Accepts a Mail/Internet, object and returns either
a Mail/ListDetector/List, object if it is a
post to a majordomo mailing list, or undef.

BUGS
====

   * This module needs to guess a little about whether a message is a post
     to a majordomo mailing list, as majordomo puts so little information
     in the message headers.

AUTHOR
======

   Michael Stevens - michael@etla.org.

RFC2369 message detector
************************

NAME
====

   Mail::ListDetector::Detector::RFC2369 - RFC2369 message detector

SYNOPSIS
========

     use Mail::ListDetector::Detector::RFC2369;

DESCRIPTION
===========

   An implementation of a mailing list detector, for RFC2369 compliant
mailing lists.

METHODS
=======

new()
-----

   Inherited from Mail/ListDetector/Detector/Base.

match()
-------

   Accepts a Mail/Internet, object and returns either
a Mail/ListDetector/List, object if it is a
post to a RFC2369 compliant mailing list, or undef.

   The RFC2369 standard does not REQUIRE all the information we wish to
extract to be present - therefore this module may not be able to return
full information for all RFC2369 compliant lists.

BUGS
====

   No known bugs.

AUTHOR
======

   Michael Stevens - michael@etla.org.

Smartlist message detector
**************************

NAME
====

   Mail::ListDetector::Detector::Smartlist - Smartlist message detector

SYNOPSIS
========

     use Mail::ListDetector::Detector::Smartlist;

DESCRIPTION
===========

   An implementation of a mailing list detector, for smartlist.

METHODS
=======

new()
-----

   Inherited from Mail/ListDetector/Detector/Base.

match()
-------

   Accepts a Mail/Internet, object and returns either
a Mail/ListDetector/List, object if it is a
post to a smartlist mailing list, or undef.

BUGS
====

   No known bugs.

AUTHOR
======

   Michael Stevens - michael@etla.org.

an object representing a mailing list
*************************************

NAME
====

   Mail::ListDetector::List - an object representing a mailing list

SYNOPSIS
========

     use Mail::ListDetector::List;

DESCRIPTION
===========

   This object provides a representation of the information extracted
about a mailing list. It should not be instantiated directly by anything
outside the Mail/ListDetector, package.

METHODS
=======

new()
=====

listname()
==========

   This method gets or sets the name of the mailing list. The name to set
is an optional argument.

posting_address()
=================

   This method gets or sets the posting address of the mailing list.  The
posting address to set is an optional argument.

listsoftware()
==============

   This method gets or sets the mailing list software name. The name to
set is an optional argument.

BUGS
====

   No known bugs.

AUTHOR
======

   Michael Stevens - michael@etla.org.

Simple interface to electronic mailing mechanisms
*************************************************

NAME
====

   Mail::Mailer - Simple interface to electronic mailing mechanisms

SYNOPSIS
========

     use Mail::Mailer;
     use Mail::Mailer qw(mail);

     $mailer = new Mail::Mailer;

     $mailer = new Mail::Mailer $type, @args;

     $mailer->open(\%headers);

     print $mailer $body;

     $mailer->close;

DESCRIPTION
===========

   Sends mail using any of the built-in methods.  You can alter the
behaviour of a method by passing $command to the new method.

mail
     Use the Unix system mail program to deliver the mail.  $command is
     the path to mail.  Mail::Mailer will search for `mailx', Mail and
     mail (in this order).

sendmail
     Use the sendmail program to deliver the mail.  $command is the path
     to sendmail.

smtp
     Use the smtp protocol via Net::SMTP to deliver the mail. The server
     to use can be specified in `@args' with

          $mailer = new Mail::Mailer 'smtp', Server => $server;

test
     Used for debugging, this calls `/bin/echo' to display the data.  No
     mail is ever sent.  $command is ignored.

   `Mail::Mailer' will search for executables in the above order. The
default mailer will be the first one found.

ARGUMENTS
---------

   new can optionally be given a $command and $type.  $type is one
sendmail, mail, ... given above.  The meaning of $command depends on $type.

   open is given a reference to a hash.  The hash consists of key and
value pairs, the key being the name of the header field (eg, To), and the
value being the corresponding contents of the header field.  The value can
either be a scalar (eg, `gnat@frii.com') or a reference to an array of
scalars (`eg, ['gnat@frii.com', 'Tim.Bunce@ig.co.uk']').

TO DO
=====

   Assist formatting of fields in ...::rfc822:send_headers to ensure valid
in the face of newlines and longlines etc.

   Secure all forms of send_headers() against hacker attack and invalid
contents. Especially "\n~..." in ...::mail::send_headers.

ENVIRONMENT VARIABLES
=====================

PERL_MAILERS
     Augments/override the build in choice for binary used to send out our
     mail messages.

     Format:

          "type1:mailbinary1;mailbinary2;...:type2:mailbinaryX;...:..."

     Example: assume you want you use private sendmail binary instead of
     mailx, one could set PERL_MAILERS to:

          "mail:/does/not/exists:sendmail:$HOME/test/bin/sendmail"

SEE ALSO
========

   Mail::Send

AUTHORS
=======

   Maintained by Graham Barr <`gbarr@pobox.com'>

   Original code written by Tim Bunce <`Tim.Bunce@ig.co.uk'>, with a kick
start from Graham Barr <`gbarr@pobox.com'>. With contributions by Gerard
Hickey <`hickey@ctron.com'> Small fix and documentation by Nathan
Torkington <`gnat@frii.com'>.

   For support please contact comp.lang.perl.misc or Graham Barr
<`gbarr@pobox.com'>

Complete mail client back end.
******************************

NAME
====

   Mail::MsgStore - Complete mail client back end.

SYNOPSIS
========

     use Mail::MsgStore;

     # set mailroot
     Mail::MsgStore::mailroot($ENV{MAILROOT});
     # get new messages from server
     $count= Mail::MsgStore::getmail(\&prompt);
     # send a Mail::Internet message
     Mail::MsgStore::send($msg);

     # add an account
     Mail::MsgStore::acct_set('Joe User <user@server.com> (work)',$password);
     # delete an account
     Mail::MsgStore::acct_del('Joe User <user@server.com> (work)');
     # change mailroot
     Mail::MsgStore::mailroot('c:/mail');
     # change from address
     Mail::MsgStore::from('Brian Lalonde <brianl@sd81.k12.wa.us>');
     # get SMTP server address
     $smtp= Mail::MsgStore::smtp;

     # add message
     $MsgStore{'/'}= $msg;                # auto-filter
     $MsgStore{'path/to/folder/'}= $msg;  # add to specific folder
     # delete message
     delete $MsgStore{'path/to/folder/msgid'};
     # delete folder
     delete $MsgStore{'path/to/folder/'};

     # get message
     $msg= $MsgStore{'path/to/folder/msgid'};
     # mark message as read, unmark 'general' flag
     $MsgStore{'path/to/folder/msgid'}= 'read, -general';
     # get folder's message id list
     @msgids= $MsgStore{'path/to/folder/'};
     # get list of folders
     @folders= keys %MsgStore;

     # move message
     $MsgStore{'newfolder/'}= delete $MsgStore{'path/to/folder/msgid'};
     # copy message
     $MsgStore{'path/to/newfolder/'}= $MsgStore{'path/to/folder/msgid'};

DESCRIPTION
===========

   The primary goal of this module is ease of use.  The Mail::Folder
module, on top of not quite being complete yet, is a pretty low-level API.
I was very impressed with how Win32::TieRegistry simplified an otherwise
complex task, and decided to adopt a similar interface for handling a mail
store.

   Another, equally important, reason for creating this module was
user-configurability.  I was unhappy with existing mail clients' filtering
capabilities- I wanted to pass every new message through some arbitrary
Perl code that was smart enough to forward, reply, send pages, activate
emergency-type alerts, etc. based on properties of the message.  What I
didn't want was more bloatware-Exchange, Outlook and Groupwise have
already been written, and despite being huge, still don't do enough.

Storage Format
--------------

   MsgStore uses a modified form of qmail's maildir format.  Here's how it
works: new messages are downloaded into a file guaranteed to have a
unique, but incomplete, name.  The filename is completed once the entire
message has been successfully downloaded (the finishing of the filename
replaces maildir's state subdirectories).

   The unique filename is generated as a dot-separated list of (uppercase)
hexadecimal numbers:  seconds past epoch (12 digits), IP address (8
digits), process id (4 digits), and download number (2 digits).  The IP
should guarantee uniqueness to a machine, the time and pid narrows it down
to a specific process, and a simple incremental number ensures that 256
messages can be downloaded per second and still retain uniqueness.  The
filename also begins and ends with 'mail', also separated by dots.

   Message flags are part of the message id (although requesting a message
by an id with the wrong flags still works).  The flags are five characters
delimited by parens.  Each position is either a dash (off) or a letter
(on).  Order is significant, but since the letters spell the word FLAGS,
that shouldn't be a problem.  Here are what the letters stand for:

     F  flame
     L  list/group
     A  answered/replied
     G  general/flag
     S  seen/opened/read

Warning
-------

   The storage format used for this module quickly becomes unusable for
large message stores; hundreds or thousands of tiny files are rarely
stored efficiently on the disk.

   Although the module is completely usable, I hope it will inspire better
storage formats to use the same simple tied-hash interface.

EVENTS
======

   The message store allows definition of the following subroutines in the
`events.pl' file located in the *mailroot* directory:

`filter($msg)'
     Accepts the Mail::Internet message object.  The message's recipient
     account is available as `X-Recipient-Account' in the message header.

     Returns the name of the folder that the Mail::Internet $msg belongs
     in.  Returning undef implies the `Inbox'.  Also, all message flags
     should be stored in the `X-Msg-Info' header, either as the native
     `(FLOR!)' format of the message ID, or the english equivalents:
     `flame, mailing-list, opened, replied, flagged'.

`keep($msg)'
     Accepts the Mail::Internet message object.  The message's recipient
     account is available as `X-Recipient-Account' in the message header.

     Returns a boolean value that determines whether the message should be
     kept on the server.

`sign($msg)'
     Signs a message before it is sent.

FUNCTIONS
=========

Sending and Receiving
---------------------

`getmail(\&prompt[,\&status])'
     Logs on to each mail account, checking for new messages, which are
     downloaded, passed to `filter()' and added.

     Returns number of messages downloaded.  Requires a callback that will
     be used if there is a problem logging in:

    `prompt($acct)'
          Parameters: `$acct' ISA Mail::Address: user is the POP3 username,
          host is the POP3 server.

          The function must return a password, or undef to cancel.  The
          password will be updated if it was initially set, or left blank
          otherwise.

    `status($status_message[,$percent_done])'
          Parameters: `$status_message' is a string describing what is
          going on suitable for GUI statusbars, etc.  `$percent_done' is
          an integer between 0 and 100 (when included, else undef)
          suitable for feeding to progress bars, etc.

`signmsg($msg)'
     Signs a Mail::Internet message, using the sign() function from the
     user-defined `events.pl'.

`sendmsg($msg)'
     Sends a Mail::Internet message, and stores a copy in `Sent/'.

Settings
--------

`mailroot([$mailroot])'
     Gets/sets the root directory of the mailstore.  The user's login is
     appended to this directory.  If the directory doesn't exist, it is
     created.  If the directory doesn't contain an `events.pl' file, one
     (fully commented) is created.

     Defaults to `$ENV{MAILROOT}' or current dir unless set.

`load_events()'
     Reloads the `events.pl' file.  Useful if you provide an editing
     facility for that file, or otherwise know that it has changed.

`smtp([$smtp])'
     Gets/sets the address of the outgoing mail server.

`from([$from])'
     Gets/sets the email `From:' address.

`accounts()'
     Returns a list of account strings.

`acct_set($acct,$pwd)'
     Adds/sets an POP3 account to the list handled by `getmail()'.
     Parameters: account and optional password.

     Accounts strings are parsed by Mail::Address; the server portion is
     used to connect, and the user portion is used to log in.  Everything
     else is mnemonic.

`acct_del($acct)'
     Deletes an account.

The Address Book
----------------

`addresses()'
     Returns a list of (references to) hashes for the entire address book.

`address( field => $value, ... )'
     Add an entry to the address book.  The key for the new entry is
     returned.  The full list of fields is available in `@addr_field',
     pretty names for the fields are in `%addr_field' (neither exported by
     default).

     Some fields of note:

    key
          A guaranteed unique identifier for the address entry.
          Auto-generated on insert.

    notes
          The *only* field allowed to contain tabs and newlines.

    firstname, lastname, nickname, email
          Standard mail-client stuff.

    tons more...
          (and in no guaranteed order)

`address($key)'
     Retrive the hash for an address.

`address($key, field => $value, ...)'
     Update fields on an existing address.  Boolean success is returned.

`address($key, DELETE => 1 )'
     Delete an entry from the address book.

`ldaps([$ldaps])'
     Gets/sets a comma or space-delimited list of LDAP servers.

`whosearch(qr/regex/, [ @fields ] )'
     Searches the address book fields specified by fields, looking for
     records that match the regex, the `firstname' and `lastname' fields
     by default.  (Actually, matches with `"@addr{@fields}"=~ /regex/'.)
     The special field nickname is also checked to match.  A list of
     (references to) hashes of matching records are returned, plus a
     `MATCHED' field in each hash that contains the value of either
     `$field[0]' or nickname, depending on which field matched.

     The result set is sorted by matching field.

     This function is probably unneccessarily complex for most mail
     clients.

`addrsearch( -starts => $namestart,  [ -number => $hitnum, ] [ -fields => \@fields, ] )'
     This is a simpler version of `"whosearch"' in this node that just
     returns address strings (rather than entire hashrefs for each record).
     (Actually, matches with `"@addr{@fields}"=~ /regex/'.)  By default,
     the `firstname' and `lastname' fields are used, just as in
     `"whosearch"' in this node.  The special field nickname is also
     checked to match.  In list context, the list of matching address
     strings is returned, but in a scalar context, the `$hitnum'-th
     element is returned (this allows passing of a kind of "Nope, next
     one." request).

     Each address is formatted this way:   `firstname' `lastname' <email>
     unless the match was via nickname, in which case the nickname and a
     tab character are prepended to the address string.

`ldapsearch($startswith)'
     Searches the server(s) specified by `ldaps()' for an entry that
     starts with `$startswith', and returns a list similar to
     `"addrsearch"' in this node.  Ignores queries shorter than 3 letters.

     This function is called by `"addrsearch"' in this node, and probably
     needn't be called directly.

Utility
-------

`msgsearch($folder,\&match)'
     Searches messages in `$folder' (and all subfolders) for messages that
     produce a true value when passed to `&match'.  Returns a list of
     fully-qualified message IDs.

`simplifymsg($msg)'
     Returns a text-only body of $msg.  If the actual $msg is a
     `multipart/mixed' or `multipart/alternative', for example, this just
     gives you the text portion of the message for display purposes.

`msgpath($fullqid)'
     Given a fully-qualified messsage ID (one that begins with the folder
     path), breaks the string into folder path and message ID.  (Similar
     in spirit to the File/Basename, module.)

`msgid($msgid)'
     Given a message ID whose flags may have changed (the message ID
     contains the message flags), returns the new message ID.

`flags($string)'
     Returns a valid flagstring for the Mail::MsgStore message ID, given
     either a msgid or english string (`'+read -list !flame'') to parse.
     Mostly for internal use.

AUTHOR
======

   v, <v@rant.scriptmania.com>

SEE ALSO
========

   perl(1), Sys::UniqueId, Mail::Internet, Mail::Folder,
Win32::TieRegistry, Net::LDAP, Net::POP3, Time::ParseDate

Perl 5 module to talk to a POP3 (RFC1939) server
************************************************

NAME
====

   Mail::POP3Client - Perl 5 module to talk to a POP3 (RFC1939) server

SYNOPSIS
========

     use Mail::POP3Client;
     $pop = new Mail::POP3Client( USER     => "me",
     			       PASSWORD => "mypassword",
     			       HOST     => "pop3.do.main" );
     for( $i = 1; $i <= $pop->Count(); $i++ ) {
       foreach( $pop->Head( $i ) ) {
         /^(From|Subject):\s+/i && print $_, "\n";
       }
     }
     $pop->Close();
     # OR
     $pop2 = new Mail::POP3Client( HOST  => "pop3.otherdo.main" );
     $pop2->User( "somebody" );
     $pop2->Pass( "doublesecret" );
     $pop2->Connect() || die $pop2->Message();
     $pop2->Close();

DESCRIPTION
===========

   This module implements an Object-Oriented interface to a POP3 server.
It implements RFC1939 (http://www.faqs.org/rfcs/rfc1939.html)

EXAMPLES
========

   Here is a simple example to list out the From: and Subject: headers in
your remote mailbox:

     #!/usr/local/bin/perl

     use Mail::POP3Client;

     $pop = new Mail::POP3Client( USER     => "me",
     			       PASSWORD => "mypassword",
     			       HOST     => "pop3.do.main" );
     for ($i = 1; $i <= $pop->Count(); $i++) {
       foreach ( $pop->Head( $i ) ) {
         /^(From|Subject):\s+/i and print $_, "\n";
       }
       print "\n";
     }

CONSTRUCTORS
============

   Old style (deprecated):    new Mail::POP3Client( USER, PASSWORD [,
HOST, PORT, DEBUG, AUTH_MODE] );

   New style (shown with defaults):    new Mail::POP3Client( USER      =>
"",                          PASSWORD  => "",
HOST      => "pop3",                          PORT      => 110,
             AUTH_MODE => 'BEST',                          DEBUG     => 0,
                        TIMEOUT   => 60,                        );

   * USER is the userID of the account on the POP server

   * PASSWORD is the cleartext password for the userID

   * HOST is the POP server name or IP address (default = 'pop3')

   * PORT is the POP server port (default = 110)

   * DEBUG - any non-null, non-zero value turns on debugging (default = 0)

   * AUTH_MODE - pass 'APOP' to force APOP (MD5) authorization. (default
     is 'BEST')

   * TIMEOUT - set a timeout value for socket operations (default = 60)

METHODS
=======

   These commands are intended to make writing a POP3 client easier.  They
do not necessarily map directly to POP3 commands defined in RFC1081 or
RFC1939, although all commands should be supported.  Some commands return
multiple lines as an array in an array context.

new( USER => 'user', PASSWORD => 'password', HOST => 'host',               PORT => 110, DEBUG => 0, AUTH_MODE => 'BEST', TIMEOUT => 60 )
     Construct a new POP3 connection with this.  You should use the
     hash-style constructor.  *The old positional constructor is
     deprecated and will be removed in a future release.  It is strongly
     recommended that you convert your code to the new version.*

     You should give it at least 2 arguments: USER and PASSWORD.  The
     default HOST is 'pop3' which may or may not work for you.  You can
     specify a different PORT (be careful here).

     new will attempt to Connect to and Login to the POP3 server if you
     supply a USER and PASSWORD.  If you do not supply them in the
     constructor, you will need to call Connect yourself.

     The valid values for AUTH_MODE are 'BEST', 'PASS' and 'APOP'.  BEST
     says to try APOP if the server appears to support it and it can be
     used to successfully log on, otherwise revert to PASS.  APOP implies
     that an MD5 checksum will be used instead of sending your password in
     cleartext.  However, *if the server does not claim to support APOP,
     the cleartext method will be used.  Be careful.* There are a few
     servers that will send a timestamp in the banner greeting, but APOP
     will not work with them (for instance if the server does not know your
     password in cleartext).  If you think your authentication information
     is correct, run in DEBUG mode and look for errors regarding
     authorization.  If so, then you may have to use 'PASS' for that
     server.

     If you enable debugging with DEBUG => 1, socket traffic will be echoed
     to STDERR.

     Another warning, it's impossible to differentiate between a timeout
     and a failure.

*Head*( MESSAGE_NUMBER )
     Get the headers of the specified message, either as an array or as a
     string, depending on context.

     You can also specify a number of preview lines which will be returned
     with the headers.  This may not be supported by all POP3 server
     implementations as it is marked as optional in the RFC.  Submitted by
     Dennis Moroney <dennis@hub.iwl.net>.

Body( MESSAGE_NUMBER )
     Get the body of the specified message, either as an array of lines or
     as a string, depending on context.

*BodyToFile*( FILE_HANDLE, MESSAGE_NUMBER )
     Get the body of the specified message and write it to the given file
     handle.  my $fh = new IO::Handle(); $fh->fdopen( fileno( STDOUT ),
     "w" ); $pop->BodyToFile( $fh, 1 );

     Does no stripping of NL or CR.

*HeadAndBody*( MESSAGE_NUMBER [, PREVIEW_LINES ] )
     Get the head and body of the specified message, either as an array of
     lines or as a string, depending on context.

    Example
          foreach ( $pop->HeadAndBody( 1, 10 ) )    print $_, "\n";

          prints out a preview of each message, with the full header and
          the first 10 lines of the message (if supported by the POP3
          server).

*HeadAndBodyToFile*( FILE_HANDLE, MESSAGE_NUMBER )
     Get the head and body of the specified message and write it to the
     given file handle.  my $fh = new IO::Handle(); $fh->fdopen( fileno(
     STDOUT ), "w" ); $pop->HeadAndBodyToFile( $fh, 1 );

     Does no stripping of NL or CR.  Since you have to create the file
     handle yourself, there is no HeadAndBodyToFile or HeadToFile.

*Retrieve*( MESSAGE_NUMBER )
     Same as HeadAndBody.

*RetrieveToFile*( FILE_HANDLE, MESSAGE_NUMBER )
     Same as HeadAndBodyToFile.

Delete( MESSAGE_NUMBER )
     Mark the specified message number as DELETED.  Becomes effective upon
     QUIT.  Can be reset with a Reset message.

Connect
     Start the connection to the POP3 server.  You can pass in the host and
     port.

Close
     Close the connection gracefully.  POP3 says this will perform any
     pending deletes on the server.

Alive
     Return true or false on whether the connection is active.

Socket
     Return the file descriptor for the socket.

Size
     Set/Return the size of the remote mailbox.  Set by POPStat.

Count
     Set/Return the number of remote messages.  Set during Login.

Message
     The last status message received from the server.

State
     The internal state of the connection: DEAD, AUTHORIZATION,
     TRANSACTION.

POPStat
     Return the results of a POP3 STAT command.  Sets the size of the
     mailbox.

List([message_number])
     Returns the size of the given message number when called with an
     argument using the following format:

          <message_number> <size_in_bytes>

     If message_number is omitted, List behaves the same as ListArray,
     returning an indexed array of the sizes of each message in the same
     format.

     You can parse the size in bytes using split:  ($msgnum, $size) =
     split ' ', $pop -> List( n )

ListArray
     Return a list of sizes of each message.  This returns an indexed
     array, with each message number as an index (starting from 1) and the
     value as the next entry on the line.  Beware that some servers send
     additional info for each message for the list command.  That info may
     be lost.

*Uidl*( [MESSAGE_NUMBER] )
     Return the unique ID for the given message (or all of them).  Returns
     an indexed array with an entry for each valid message number.
     Indexing begins at 1 to coincide with the server's indexing.

Last
     Return the number of the last message, retrieved from the server.

Reset
     Tell the server to unmark any message marked for deletion.

User( [USER_NAME] )
     Set/Return the current user name.

Pass( [PASSWORD] )
     Set/Return the current user name.

Login
     Attempt to login to the server connection.

Host( [HOSTNAME] )
     Set/Return the current host.

Port( [PORT_NUMBER] )
     Set/Return the current port number.

AUTHOR
======

   Sean Dowd <pop3client@dowds.net>

CREDITS
=======

   Based loosely on News::NNTPClient by Rodger Anderson
<rodger@boi.hp.com>.

SEE ALSO
========

   perl(1).

Procmail-like facility for creating easy mail filters.
******************************************************

NAME
====

   Mail::Procmail - Procmail-like facility for creating easy mail filters.

SYNOPSIS
========

     use Mail::Procmail;

     # Set up. Log everything up to log level 3.
     my $m_obj = pm_init ( loglevel  => 3 );

     # Pre-fetch some interesting headers.
     my $m_from		    = pm_gethdr("from");
     my $m_to		    = pm_gethdr("to");
     my $m_subject	    = pm_gethdr("subject");

     # Default mailbox.
     my $default = "/var/spool/mail/".getpwuid($>);

     pm_log(1, "Mail from $m_from");

     pm_ignore("Non-ASCII in subject")
       if $m_subject =~ /[\232-\355]{3}/;

     pm_resend("jojan")
       if $m_to =~ /jjk@/i;

     # Make sure I see these.
     pm_deliver($default, continue => 1)
       if $m_subject =~ /getopt(ions|(-|::)?long)/i;

     # And so on ...

     # Final delivery.
     pm_deliver($default);

DESCRIPTION
===========

   `procmail' is a great mail filter program, but it has weird recipe
format. It's pattern matching capabilities are basic and often
insufficient. I wanted something flexible whereby I could filter my mail
using the power of Perl.

   I've been considering to write a procmail replacement in Perl for a
while, but it was Simon Cozen's `Mail::Audit' module, and his article in
The Perl Journal #18, that set it off.

   I first started using Simon's great module, and then decided to write
my own since I liked certain things to be done differently. And I couldn't
wait for his updates. Currently, Simon and I are in the process of
considering to port my enhancements to his code as well.

   `Mail::Procmail' allows a piece of email to be logged, examined,
delivered into a mailbox, filtered, resent elsewhere, rejected, and so on.
It is designed to allow you to easily create filter programs to stick in a
`.forward' or `.procmailrc' file, or similar.

DIFFERENCES WITH MAIL::AUDIT
============================

   Note that several changes are due to personal preferences and do not
necessarily imply deficiencies in `Mail::Audit'.

General
     Not object oriented. Procmail functionality typically involves one
     single message. All (relevant) functions are exported.

Delivery
     Each of the delivery methods is able to continue (except pm_reject
     and pm_ignore).

     Each of the delivery methods is able to pretend they did it (for
     testing a new filter).

     No default file argument for mailbox delivery, since this is system
     dependent.

     Each of the delivery methods logs the line number in the calling
     program so one can deduce which 'rule' caused the delivery.

     Message IDs can be checked to suppress duplicate messages.

     System commands can be executed for their side-effects.

     pm_ignore logs a reason as well.

     pm_reject will fake a "No such user" status to the mail transfer
     agent.

Logging
     The logger function is exported as well. Logging is possible to a
     named file, STDOUT or STDERR.

     Since several deliveries can take place in parallel, logging is
     protected against concurrent access, and a timestamp/pid is included
     in log messages.

     A log reporting tool is included.

Robustness
     Exit with TEMPFAIL instead of die in case of problems.

     pm_pipe_to ignores  SIGPIPE.

     pm_pipe_to returns the command exit status if continuation is
     selected.

     Commands and pipes can be protected  against concurrent access using
     lockfiles.

EXPORTED ROUTINES
=================

   Note that most delivery routines exit the program unless the attribute
"continue=>1" is passed.

   Also, the delivery routines log the line number in the calling program
so it is easy to find out which 'rule' caused a specific delivery to take
place.

pm_init
-------

   This routine performs the basic initialisation. It must be called once.

   Example:

     pm_init (logfile => "my.log", loglevel => 3, test => 1);

   Attributes:

   * logfile

     The name of a file to log messages to. Each message will have a
     timestamp attached.

     The attribute may be 'STDOUT' or 'STDERR' to achieve logging to
     standard output or error respectively.

   * loglevel

     The amount of information that will be logged.

   * test

     If true, no actual delivery will be done. Suitable to test a new
     setup.  Note that file locks are done, so lockfiles may be created
     and deleted.

   * debug

     Provide some debugging info.

   * trace

     Provide some tracing info, eventually.

   * verbose

     Produce verbose information, eventually.

pm_gethdr
---------

   This routine fetches the contents of a header. The result will have
excess whitepace tidied up.

   The header is reported using warn() if the debug attribute was passed
(with a true value) to pm_init();

   Example:

     $m_rcvd = pm_gethdr("received");	# get first (or only) Received: header
     $m_rcvd = pm_gethdr("received",2);	# get 3rd Received: header
     @m_rcvd = pm_gethdr("received");	# get all Received: headers

pm_deliver
----------

   This routine performs delivery to a Unix style mbox file, or maildir.

   In case of an mbox file, the file is locked first by acquiring
exclusive access. Note that older style locking, with a lockfile with
`.lock' extension, is not supported.

   Example:

     pm_deliver("/var/spool/mail/".getpwuid($>));

   Attributes:

   * continue

     If true, processing will continue after delivery. Otherwise the
     program will exit with a DELIVERED status.

pm_pipe_to
----------

   This routine performs delivery to a command via a pipe.

   Return the command exit status if the continue attribute is supplied.
If execution is skipped due to test mode, the return value will be 0.  See
also attribute `testalso' below.

   If the name of a lockfile is supplied, multiple deliveries are
throttled.

   Example:

     pm_pipe_to("my_filter", lockfile => "/tmp/pm.lock");

   Attributes:

   * lockfile

     The name of a file that is used to guard against multiple deliveries.
     The program will try to exclusively create this file before proceding.
     Upon completion, the lock file will be removed.

   * continue

     If true, processing will continue after delivery. Otherwise the
     program will exit with a DELIVERED status, *even when the command
     failed*.

   * testalso

     Do this, even in test mode.

pm_command
----------

   Executes a system command for its side effects.

   If the name of a lockfile is supplied, multiple executes are throttled.
This would be required if the command manipulates external data in an
otherwise unprotected manner.

   Example:

     pm_command("grep foo some.dat > /tmp/pm.dat",
                lockfile => "/tmp/pm.dat.lock");

   Attributes:

   * lockfile

     The name of a file that is used to guard against multiple executions.
     The program will try to exclusively create this file before proceding.
     Upon completion, the lock file will be removed.

     testalso

     Do this, even in test mode.

pm_resend
---------

   Send this message through to some other user.

   Example:

     pm_resend("root");

   Attributes:

   * continue

     If true, processing will continue after delivery. Otherwise the
     program will exit with a DELIVERED status.

pm_reject
---------

   Reject a message. The sender will get a mail back with the reason for
the rejection (unless stderr has been redirected).

   Example:

     pm_reject("Non-existent address");

pm_ignore
---------

   Ignore a message. The program will do nothing and just exit with a
DELIVERED status. A descriptive text may be passed to log the reason for
ignoring.

   Example:

     pm_ignore("Another make money fast message");

pm_dupcheck
-----------

   Check for duplicate messages. Reject the message if its message ID has
already been received.

   Example:

     pm_dupcheck(pm_gethdr("msg-id"));

   Attributes:

   * dbm

     The name of a DBM file (created if necessary) to store the message
     IDs.  The default name is `.msgids' in the HOME directory.

   * retain

     The amount of time, in days, that subsequent identical message IDs are
     considered duplicates. Each new occurrence will refresh the time
     stamp.  The default value is 14 days.

   * continue

     If true, the routine will return true or false depending on the
     message ID being duplicate. Otherwise, if it was duplicate, the
     program will exit with a DELIVERED status.

   *Warning: In the current implementation, the DBM file will grow
unlimited. A separate tool will be supplied to expire old message IDs.*

pm_lockfile
-----------

   The program will try to get an exclusive lock using this file.

   Example:

     $lock_id = pm_lockfile("my.mailbox.lock");

   The lock id is returned, or undef on failure.

pm_unlockfile
-------------

   Unlocks a lock acquired earlier using pm_lockfile().

   Example:

     pm_unlockfile($lock_id);

   If unlocking succeeds, the lock file is removed.

pm_log
------

   Logging facility. If pm_init() was supplied the name of a log file,
this file will be opened, created if necessary. Every log message written
will get a timestamp attached. The log level (first argument) must be less
than or equal to the loglevel attribute used with pm_init(). If not, this
message will be skipped.

   Example:

     pm_log(2,"Retrying");

pm_report
---------

   pm_report() produces a summary report from log files from
Mail::Procmail applications.

   Example:

     pm_report(logfile => "pmlog");

   The report shows the deliveries, and the rules that caused the
deliveries. For example:

     393  393  deliver[203]  /home/jv/Mail/perl5-porters.spool
     370  370  deliver[203]  /home/jv/Mail/perl6-language.spool
     174  174  deliver[203]  /home/jv/Mail/perl6-internals.spool
     160   81  deliver[311]  /var/spool/mail/jv
     	46  deliver[337]
     	23  deliver[363]
     	10  deliver[165]

   The first column is the total number of deliveries for this target.
The second column is the number of deliveries triggered by the indicated
rule. If more rules apply to a target, this line is followed by additional
lines with an empty first and last column.

   Attributes:

   * logfile

     The name of the logfile to process.

   If no logfile attribute is passed, pm_report() reads all files supplied
on the command line. This makes it straighforward to run from the command
line:

     $ perl -MMail::Procmail -e 'pm_report()' syslog/pm_logs/*

USING WITH PROCMAIL
===================

   The following lines at the start of .procmailrc will cause a copy of
each incoming message to be saved in $HOME/syslog/mail, after which the
procmail-pl is run as a TRAP program (see the procmailrc documentation).
As a result, procmail will transfer the exit status of procmail-pl to the
mail transfer agent that invoked procmail (e.g., sendmail, or postfix).

     LOGFILE=$HOME/syslog/procmail
     VERBOSE=off
     LOGABSTRACT=off
     EXITCODE=
     TRAP=$HOME/bin/procmail-pl

     :0:
     $HOME/syslog/mail

   The original contents of the .procmailrc can be safely left in place
after these lines.

EXAMPLE
=======

   An extensive example can be found in the examples directory of the
`Mail::Procmail' kit.

SEE ALSO
========

   See Mail/Internet,

   See LockFile/Simple,

   procmail documentation.

AUTHOR
======

   Johan Vromans, Squirrel Consultancy <jvromans@squirrel.nl>

   Some parts are shamelessly stolen from Mail::Audit by Simon Cozens
<simon@cpan.org>, who admitted that he stole most of it from programs by
Tom Christiansen.

COPYRIGHT and DISCLAIMER
========================

   This program is Copyright 2000 by Squirrel Consultancy. All rights
reserved.

   This program is free software; you can redistribute it and/or modify it
under the terms of either: a) the GNU General Public License as published
by the Free Software Foundation; either version 1, or (at your option) any
later version, or b) the "Artistic License" which comes with Perl.

   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 either the GNU General Public
License or the Artistic License for more details.

Provides quotification functionality for Usenet articles and mail.
******************************************************************

NAME
====

   *Mail::QuoteWrap* - Provides quotification functionality for Usenet
articles and mail.

SYNOPSIS
========

     use Mail::QuoteWrap;

     ...

     my $columns = 72;                     # maximum column width of the post
     my $output_quotechar = ">";           # character to prepend to
                                           # quoted lines -- see quotify()
     my $input_quotechars = "<>:";         # characters to be recognized as
                                           # quotifiers when judging the
                                           # generation of a quote

     my $text = $news_article->body();     # get some body text somehow

     my $body = create Mail::QuoteWrap ($text, $columns, $output_quotechar,
                                      $input_quotechars, {});

     $body->quotify();
     $body->append("Me too!");

     my $newtext = $body->format();

DESCRIPTION
===========

   A *Mail::QuoteWrap* object expects its text member to contain a
reference to a list of lines of text, such as the output of methods like
`body News::Article()'.  It can then produce quotified output, optionally
prepended with the quote mark designated by output_quotechar, within the
width specified by columns.

   *Mail::QuoteWrap* specificially does not solve the following problems:

     It does not handle munged quote characters, such as those produced by
     the AOHell newsreader or similar gunge:

          >> This >is a second-generation quote, but it
          > looks >>like a nasty mix of first- and second->
          > generation >>material.

     It does not automatically detect and bypass news or mail headers.
     That is not the role of this object.

     It assumes a paragraph structure to the quoted text and doesn't try
     to enforce any other.  If you want a module that detects document
     structure and deals well with it, look at *Text::Autoformat*.

REQUIRES
========

   This module uses *Text::Format*.

BUGS
====

     If input_quotechars or output_quotechar contain suckful characters
     that regexp thinks it understands, all hell can break loose.

     *Mail::QuoteWrap* may not deal well with Supercite-style
     quotification:

          Chuck> I believe everything I see written on toilet paper

     is thought to be zeroth-generation (unquoted) material.

AUTHOR
======

   Chuck Hardin <chardin@savageoasis.fc.net>

COPYRIGHT
=========

   This module is copyright 2000, Chuck Hardin.

LICENSE
=======

   This module is distributed under version 2 of the GNU Public License.

Public class method
===================

create
------

     public class
     (Mail::QuoteWrap) create(string[] text [,integer columns]
                              [,string output_quotechar] [,string input_quotechars]
                              [,hashref format_params])

   This method creates a *Mail::QuoteWrap* object populated with the
parameters passed in.  It returns a NULL object if any of the provided
parameters are invalid.

   The meanings of the members are as follows:

text
     The body text of the message.

columns
     The width to which the message should be justified.  NOTE:  If any
     line consisting of the quotification string and the first word is
     wider than this, then the line will be generated with that
     quotification string and that word, and it will overflow.  Life is
     hard.

output_quotechar
     The quotification character to prepend to the text when quoting.  See
     `quotify()'.

input_quotechars
     The set of characters to be recognized as quotification marks when
     determining how to group quoted material.

format_params
     Miscellaneous parameters to pass for formatting.  See the
     documentation for the *Text::Format* module.

Private class method
====================

new
---

     private class
     (Mail::QuoteWrap) new(hashref params)

   Creates a *Mail::QuoteWrap* object populated by the data in params.

Public instance methods
=======================

text
----

     public instance
     (string []) text()

   Returns the text member of the current *Mail::QuoteWrap* object.

set_text
--------

     public instance
     (string) set_text(string[] text)

   Sets the text member of the current *Mail::QuoteWrap* object.  Returns
a NULL string if it succeeds, or a descriptive error message otherwise.

columns
-------

     public instance
     (integer) columns()

   Returns the columns member of the current *Mail::QuoteWrap* object.

set_columns
-----------

     public instance
     (string) set_columns(integer columns)

   Sets the columns member of the current *Mail::QuoteWrap* object.
Returns a NULL string if it succeeds, or a descriptive error message
otherwise.

input_quotechars
----------------

     public instance
     (string) input_quotechars()

   Returns the input_quotechars member of the current *Mail::QuoteWrap*
object.

set_input_quotechars
--------------------

     public instance
     (string) set_input_quotechars(string input_quotechars)

   Sets the input_quotechars member of the current *Mail::QuoteWrap*
object.  Returns a NULL string if it succeeds, or a descriptive error
message otherwise.

output_quotechar
----------------

     public instance
     (string) output_quotechar()

   Returns the output_quotechar member of the current *Mail::QuoteWrap*
object.

set_output_quotechar
--------------------

     public instance
     (string) set_output_quotechar(string output_quotechar)

   Sets the output_quotechar member of the current *Mail::QuoteWrap*
object.  Returns a NULL string if it succeeds, or a descriptive error
message otherwise.

format_params
-------------

     public instance
     (hashref) format_params()

   Returns the format_params member of the current *Mail::QuoteWrap*
object.

set_format_params
-----------------

     public instance
     (string) set_format_params(hashref format_params)

   Sets the format_params member of the current *Mail::QuoteWrap* object.
Returns a NULL string if it succeeds, or a descriptive error message
otherwise.

quotify
-------

     public instance
     (string) quotify()

   Quotifies all current text with the string in `output_quotechar()'.
Modifies the input_quotechars member to reflect that the text is now
quotified.  Returns a NULL string if it succeeds, or a descriptive error
message otherwise.

format
------

     public instance
     (string) format()

   This method alters the text member of the current *Mail::QuoteWrap*
object to conform to the constraints implied in the columns and
format_params members.  It recognizes the quotification characters in
input_quotechars and uses them to lump related quoted material together.
`format()' will use the same quotification character at the beginning of
each line within a block of quoted material which it believes to be
related.  Returns a NULL string if it succeeds, or a descriptive error
message otherwise.

Private utility methods
=======================

parse_quotification
-------------------

     private
     (string, string) parse_quotification (string text, string quotechars)

   Returns two strings:  the quotification part of the line of text
(consisting of all characters at the beginning of the line which are tabs,
spaces, or characters in *quotechars*), and the remainder of the line.
Returns two NULL strings if this matching does not work out.

break_text_into_blocks
----------------------

     private
     (hashref []) break_text_into_blocks (string[] text, string quotechars)

   Breaks text into a list of elements, each of which is a hash with the
following elements:

quotification
     Quotification string to use for this block.

message
     Array ref containing the message text; undef if the message portion
     is blank.

   Each message element is guaranteed to consist of lines of
same-generation quotage - i.e., a block will contain only first-generation
quotes, second-generation, zeroth-generation, or what have you.  Each line
with blank message text gets its own block, to preserve vertical
whitespace.

copy_and_push
-------------

     private
     (string) copy_and_push(hashref current_block, arrayref outlist)

   Pushes a copy of the contents of *current_block* onto outlist.
*current_block* is assumed to have two members as described in the
documentation for `break_text_into_blocks()' above.  Returns a NULL string
if it succeeds, or a descriptive error message otherwise.

break_block_into_paragraphs
---------------------------

     private
     (string[]) break_block_into_paragraphs(string[] block)

   Breaks the block into paragraphs according to the following rule:

   If the previous line ended with a period and the current line begins
with a tab or at least three spaces, the current line begins a new
paragraph.

Perl extension to access RBL-style host verification services
*************************************************************

NAME
====

   Mail::RBL - Perl extension to access RBL-style host verification
services

SYNOPSIS
========

     use Mail::RBL;

     my $list = new Mail::RBL('list.org');

     if ($list->check($host)) {
         print "$host is in the list";
     }

DESCRIPTION
===========

   This module eases the task of checking if a given host is in the list.
The methods available are described below:

`->new(suffix)'
     Creates a list handle. The suffix parameter is mandatory and
     specifies which suffix to append to the queries.

`->check($host)'
     $host can be either a hostname or an IP address. In the case of an IP
     Address, any trailing netmask (anything after a '/' character) will
     be ignored. In the case of a hostname, all the IP addresses will be
     looked up and checked against the list. If any of the addresses is in
     the list, the host will be considered in the list as a whole.

AUTHOR
======

   Luis E. Munoz <lem@cantv.net>

SEE ALSO
========

   perl(1).

Simple electronic mail interface
********************************

NAME
====

   Mail::Send - Simple electronic mail interface

SYNOPSIS
========

     require Mail::Send;

     $msg = new Mail::Send;

     $msg = new Mail::Send Subject=>'example subject', To=>'timbo';

     $msg->to('user@host');
     $msg->subject('example subject');
     $msg->cc('user@host');
     $msg->bcc('someone@else');

     $msg->set($header, @values);
     $msg->add($header, @values);
     $msg->delete($header);

     # Launch mailer and set headers. The filehandle returned
     # by open() is an instance of the Mail::Mailer class.

     $fh = $msg->open;

     print $fh "Body of message";

     $fh->close;         # complete the message and send it

     $fh->cancel;        # not yet implemented

DESCRIPTION
===========

SEE ALSO
========

   Mail::Mailer

AUTHORS
=======

   Maintained by Graham Barr <`gbarr@pobox.com'>

   Original code written by Tim Bunce <`Tim.Bunce@ig.co.uk'>, with a kick
start from Graham Barr <`gbarr@pobox.com'>. With contributions by Gerard
Hickey <`hickey@ctron.com'>

   For support please contact comp.lang.perl.misc or Graham Barr
<`gbarr@pobox.com'>

module for sending mails with attachments through an SMTP server
****************************************************************

NAME
====

   Mail::Sender - module for sending mails with attachments through an
SMTP server

   Version 0.7.06

SYNOPSIS
========

     use Mail::Sender;
     $sender = new Mail::Sender
      {smtp => 'mail.yourdomain.com', from => 'your@address.com'};
     $sender->MailFile({to => 'some@address.com',
      subject => 'Here is the file',
      msg => "I'm sending you the list you wanted.",
      file => 'filename.txt'});

DESCRIPTION
===========

   `Mail::Sender' provides an object oriented interface to sending mails.
It doesn't need any outer program. It connects to a mail server directly
from Perl, using Socket.

   Sends mails directly from Perl through a socket connection.

CONSTRUCTORS
============

`new Mail::Sender'
          new Mail::Sender ([from [,replyto [,to [,smtp [,subject [,headers [,boundary]]]]]]])
          new Mail::Sender {[from => 'somebody@somewhere.com'] , [to => 'else@nowhere.com'] [...]}

     Prepares a sender. This doesn't start any connection to the server.
     You have to use `$Sender-'Open> or `$Sender-'OpenMultipart> to start
     talking to the server.

     The parameters are used in subsequent calls to `$Sender-'Open> and
     `$Sender-'OpenMultipart>. Each such call changes the saved variables.
     You can set smtp,from and other options here and then use the info in
     all messages.

          from      = the senders e-mail address

          fake_from = the address that will be shown in headers
                      If not specified we use the value of "from"

          replyto   = the reply-to address

          to        = the recipient's address(es)

          fake_to   = the address that will be shown in headers
                      If not specified we use the value of "to"

          cc        = address(es) to send a copy (carbon copy)

          fake_cc   = the address that will be shown in headers
                      If not specified we use the value of "cc"

          bcc       = address(es) to send a copy (blind carbon copy)
                      these addresses will not be visible in the mail!

          smtp      = the IP or domain address of your SMTP (mail) server
                      This is the name of your LOCAL mail server, do not try to guess
                      and contact directly the adressee's mailserver!

          subject   = the subject of the message

          headers   = the additional headers

          boundary  = the message boundary

          multipart = the MIME subtype for the whole message (Mixed/Related/Alternative)
           you may need to change this setting if you want to send a HTML body with some
           inline images, or if you want to post the message in plain text as well as
           HTML (alternative). See the examples at the end of the docs.
           You may also use the nickname "subtype".

          type      = the content type of a multipart message, may be usefull for
                      multipart/related

          ctype     = the content type of a single part message

          Please do not confuse these two. The 'type' parameter is used to specify
          the overall content type of a multipart message (for example a HTML document
          with inlined images) while ctype is an ordinary content type for a single
          part message. For example a HTML mail message.

          encoding  = encoding of a single part message or the body of a multipart
           message. If the text of the message contains some extended characters or
           very long lines you should use 'encoding => "Quoted-printable"' in the
           call to Open(), OpenMultipart(), MailMsg() or MailFile().
           Keep in mind that if you use some encoding you should either use SendEnc()
           or encode the data yourself !

          charset   = the charset of the message

          client     = the name of the client computer. During the connection you send
           the mailserver your name. Usualy a "localhost" is sufficient, but sometimes
           you need to specify some real name. Usualy something like
           `hostname`.'.mycompany.com'. But I leave this for you.
           Mail::Sender doesn't try to guess the name, it sends "localhost" if you do
           not specify otherwise.

          priority   = 1 = highest, 2 = high, 3 = normal
           "X-Priority: 1 (Highest)";

          return codes:
           ref to a Mail::Sender object =  success
           -1 = $smtphost unknown
           -2 = socket() failed
           -3 = connect() failed
           -4 = service not available
           -5 = unspecified communication error
           -6 = local user $to unknown on host $smtp
           -7 = transmission of message failed
           -8 = argument $to empty
           -9 = no message specified in call to MailMsg or MailFile
           -10 = no file name specified in call to SendFile or MailFile
           -11 = file not found
           -12 = not available in singlepart mode
            $Mail::Sender::Error contains a textual description of last error.

METHODS
=======

Open
          Open([from [, replyto [, to [, smtp [, subject [, headers]]]]]])
          Open({[from => "somebody@somewhere.com"] , [to => "else@nowhere.com"] [...]})

     Opens a new message. If some parameters are unspecified or empty, it
     uses the parameters passed to the "`$Sender=new Mail::Sender(...)'";

     see `new Mail::Sender' for info about the parameters.

OpenMultipart
          OpenMultipart([from [, replyto [, to [, smtp [, subject [, headers [, boundary]]]]]]])
          OpenMultipart({[from => "somebody@somewhere.com"] , [to => "else@nowhere.com"] [...]})

     Opens a multipart message. If some parameters are unspecified or
     empty, it uses the parameters passed to the `$Sender=new
     Mail::Sender(...)'.

     see `new Mail::Sender' for info about the parameters.

MailMsg
          MailMsg([from [, replyto [, to [, smtp [, subject [, headers]]]]]], message)
          MailMsg({[from => "somebody@somewhere.com"]
                   [, to => "else@nowhere.com"] [...], msg => "Message"})

     Sends a message. If a mail in $sender is opened it gets closed and a
     new mail is created and sent. $sender is then closed.  If some
     parameters are unspecified or empty, it uses the parameters passed to
     the "`$Sender=new Mail::Sender(...)'";

     see `new Mail::Sender' for info about the parameters.

     The module was made so that you could create an object initialized
     with all the necesary options and then send several messages without
     need to specify the SMTP server and others each time. If you need to
     send only one mail using MailMsg() or MailFile() you do not have to
     create a named object and then call the method. You may do it like
     this :

          (new Mail::Sender)->MailMsg({smtp => 'mail.company.com', ...});

MailFile
          MailFile([from [, replyto [, to [, smtp [, subject [, headers]]]]]], message, file(s))
          MailFile({[from => "somebody@somewhere.com"]
                    [, to => "else@nowhere.com"] [...],
                    msg => "Message", file => "File"})

     Sends one or more files by mail. If a mail in $sender is opened it
     gets closed and a new mail is created and sent. $sender is then
     closed.  If some parameters are unspecified or empty, it uses the
     parameters passed to the "`$Sender=new Mail::Sender(...)'";

     The file parameter may be a "filename", a "list, of, file, names" or
     a \@list of file names.

     see `new Mail::Sender' for info about the parameters.

     Just keep in mind that parameters like ctype, charset and encoding
     will be used for the attached file, not the body of the message.  If
     you want to specify those parameters for the body you have to use
     b_ctype, b_charset and b_encoding. Sorry.

Send
          Send(@strings)

     Prints the strings to the socket. Doesn't add any end-of-line
     characters.  You should use `\r\n' as the end-of-line. IF YOU ARE NOT
     SURE ABOUT THIS USE SendEx() INSTEAD!

SendLine
          SendLine(@strings)

     Prints the strings to the socket. Adds the end-of-line character at
     the end.

SendEnc
          SendEnc(@strings)

     Prints the strings to the socket. Doesn't add any end-of-line
     characters.  You should use `\r\n' as the end-of-line.  Encodes the
     text using the selected encoding (Base64/Quoted-printable)

SendLineEnc
          SendLineEnc(@strings)

     Prints the strings to the socket. Add the end-of-line character at
     the end.  Encodes the text using the selected encoding
     (Base64/Quoted-printable)

     Do NOT mix up Send[Line][Ex] and Send[Line]Enc! SendEnc does some
     buffering necessary for correct Base64 encoding, and Send is not
     aware of that!

     Usage of Send[Line][Ex] in non 7BIT parts not recommended.  Using
     `Send(encode_base64($string))' may, but may NOT work!  In particular
     if you use several such to create one part, the data is very likely
     to get crippled.

SendEx
          SendEx(@strings)

     Prints the strings to the socket. Doesn't add any end-of-line
     characters.  Changes all end-of-lines to `\r\n'. YOU'D BETTER USE
     THIS METHOD THAN JUST Send(), SOME E-MAIL SERVERS ARE PICKY AND WOUNT
     ACCEPT THE MESSAGE IF YOU DO NOT USE CRLF (\r\n) AS THE END-OF-LINE !

SendLineEx
          SendLineEx(@strings)

     Prints the strings to the socket. Doesn't add any end-of-line
     characters.  Changes all end-of-lines to `\r\n'.

Part
          Part( I<description>, I<ctype>, I<encoding>, I<disposition> [, I<content_id>]);
          Part( [description => "desc"], [ctype], [encoding], [disposition], [content_id]});

          Prints a part header for the multipart message.
          The undef or empty variables are ignored.

    description
          The title for this part.

    ctype
          the content type (MIME type) of this part. May contain some other
          parameters, such as charset or name.

          Defaults to "application/octet-stream".

    encoding
          the encoding used for this part of message. Eg. Base64,
          Uuencode, 7BIT ...

          Defaults to "7BIT".

    disposition
          This parts disposition. Eg: 'attachment; filename="send.pl"'.

          Defaults to "attachment". If you specify "none" or "", the
          Content-disposition: line will not be included in the headers.

    content_id
          The content id of the part, used in multipart/related.  If not
          specified, the header is not included.

Body
          Body([charset [, encoding [, content-type]]]);

     Sends the head of the multipart message body. You can specify the
     charset and the encoding. Default is "US-ASCII","7BIT",'text/plain'.

     If you pass undef or zero as the parameter, this function uses the
     default value:

          Body(0,0,'text/html');

SendFile
          SendFile( I<description>, I<ctype>, I<encoding>, I<disposition>, I<file>);
          SendFile( { [description => "desc"] , [ctype => "ctype"], [encoding => "encoding"],
                      [disposition => "disposition"], file => "file"});

          Sends a file as a separate part of the mail message. Only in multipart mode.

    description
          The title for this part.

    ctype
          the content type (MIME type) of this part. May contain some other
          parameters, such as charset or name.

          Defaults to "application/octet-stream".

    encoding
          the encoding used for this part of message. Eg. Base64,
          Uuencode, 7BIT ...

          Defaults to "Base64".

    disposition
          This parts disposition. Eg: 'attachment; filename="send.pl"'. If
          you use 'attachment; filename=*' the * will be replaced by the
          respective names of the sent files.

          Defaults to "attachment; filename=*". If you do not want to
          include this header use "" as the value.

    file
          The name of the file to send or a 'list, of, names' or a
          ['reference','to','a','list','of','filenames']. Each file will
          be sent as a separate part.

    content_id
          The content id of the message part. Used in multipart/related.

               Special values:
                "*" => the name of the file
                "#" => autoincremented number (starting from 0)

Close
          $sender->Close;

     Close and send the mail. This method should be called automatically
     when destructing the object, but you should call it yourself just to
     be sure it gets called.  And you should do it as soon as possible to
     close the connection and free the socket.

     The mail is being sent to server, but is not processed by the server
     till the sender object is closed!

Cancel
          $sender->Cancel;

     Cancel an opened message.

     SendFile and other methods may set $sender->{'error'}.  In that case
     "undef $sender" calls `$sender-'>Cancel not `$sender-'>Close!!!

@Mail::Sender::Errors
     Contains the description of errors returned by functions in
     Mail::Sender.

     Usage: @Mail::Sender::Errors[$sender->{error}]

CONFIG
======

   If you create a file named Sender.config in the same directory where
Sender.pm resides, this file will be "require"d as soon as you "use
Mail::Sender" in your script. Of course the Sender.config MUST "return a
true value", that is it has to be succesfully compiled and the last
statement must return a true value. You may use this to forbide the use of
Mail::Sender to some users.

   You may define the default settings for new Mail::Sender objects and do
a few more things.

   The default options are stored in hash %Mail::Sender::default. You may
use all the examples you'd use in new, Open, OpenMultipart, MailMsg or
MailFile.

     Eg.
      %default = (
        smtp => 'mail.mccann.cz',
        from => Win32::LoginName.'@mccann.cz',
        client => Win32::NodeName.'mccann.cz'
      );
      # of course you will use your own mail server here !

   The other options you may set here (or later of course) are
$Mail::Sender::SITE_HEADERS and $Mail::Sender::NO_X_MAILER.

   The $Mail::Sender::SITE_HEADERS may contain headers that will be added
to each mail message sent by this script, the $Mail::Sender::NO_X_MAILER
disables the header item specifying that the message was sent by
Mail::Sender.

   !!! $Mail::Sender::SITE_HEADERS may NEVER end with \r\n !!!

   If you want to set the $Mail::Sender::SITE_HEADERS for every script sent
from your server without your users being able to change it you may use
this hack:

     $loginname = something_that_identifies_the_user();
     eval qq{*Mail::Sender::SITE_HEADERS = 'X-Sender: $loginname via $0'};

   You may even "install" your custom function that will be evaluated for
each message just before contacting the server. You may change all the
options from within as well as stop sending the message.

   All you have to do is to create a function named SiteHook in
Mail::Sender package. This function will get the Mail::Sender object as
its first argument. If it returns a TRUE value the message is sent, if it
returns FALSE the sending is canceled and the user gets "Site specific
error" error message.

   If you want to give some better error message you may do it like this :

     sub SiteHook {
      my $self = shift;
      if (whatever($self)) {
        $self->{'error'} = SITEERROR;
        $Mail::Sender::Error = "I don't like this mail";
        return 0
      } else {
        return 1;
      }
     }

   This example will ensure the from address is the users real address :

     sub SiteHook {
      my $self = shift;
      $self->{fromaddr} = getlogin.'@yoursite.com';
      $self->{from} = getlogin.'@yoursite.com';
      1;
     }

   Please note that at this stage the from address is in two different
object properties.

   $self->{from} is the address as it will appear in the mail, that is it
may include the full name of the user or any other comment ( "Jan Krynicky
<jenda@krynicky.cz>" for example), while the $self->{fromaddr} is realy
just the email address per se and it will be used in conversation with the
SMTP server. It must be without comments ("jenda@krynicky.cz" for example)!

   Without write access to .../lib/Mail/Sender.pm or
.../lib/Mail/Sender.config your users will then be unable to get rid of
this header. Well ... everything is doable, if he's cheeky enough ... :-(

   So if you take care of some site with virtual servers for several
clients and implement some policy via SiteHook() or
$Mail::Sender::SITE_HEADERS search the clients' scripts for "SiteHook" and
"SITE_HEADERS" from time to time. To see who's cheating.

EXAMPLES
========

     use Mail::Sender;

     #$sender = new Mail::Sender { from => 'somebody@somewhere.com',
        smtp => 'ms.chipnet.cz', boundary => 'This-is-a-mail-boundary-435427'};
     # # if you do not care about errors.
     # # otherwise use
     #
     ref ($sender = new Mail::Sender { from => 'somebody@somewhere.com',
           smtp => 'ms.chipnet.cz', boundary => 'This-is-a-mail-boundary-435427'})
     or die "Error($sender) : $Mail::Sender::Error\n";

     $sender->Open({to => 'friend@other.com', subject => 'Hello dear friend'});
     $sender->SendLine("How are you?");
     $sender->SendLine;
     $sender->Send(<<'*END*');
     I've found these jokes.

     Doctor, I feel like a pack of cards.
     Sit down and I'll deal with you later.

     Doctor, I keep thinking I'm a dustbin.
     Don't talk rubbish.

     Hope you like'em. Jenda
     *END*

     $sender->Close;

     $sender->Open({to => 'mama@home.org, papa@work.com',
                    cc => 'somebody@somewhere.com',
                    subject => 'Sorry, I'll come later.'});
     $sender->SendLine("I'm sorry, but due to a big load of work,
        I'll come at 10pm at best.");
     $sender->SendLine("\nHi, Jenda");

     $sender->Close;

     $sender->OpenMultipart({to => 'Perl-Win32-Users@activeware.foo',
                             subject => 'Mail::Sender.pm - new module'});
     $sender->Body;
     $sender->Send(<<'*END*');
     Here is a new module Mail::Sender.
     It provides an object based interface to sending SMTP mails.
     It uses a direct socket connection, so it doesn't need any
     additional program.

     Enjoy, Jenda
     *END*
     $sender->SendFile(
      {description => 'Perl module Mail::Sender.pm',
       ctype => 'application/x-zip-encoded',
       encoding => 'Base64',
       disposition => 'attachment; filename="Sender.zip"; type="ZIP archive"',
       file => 'sender.zip'
      });
     $sender->Close;

     _END_

   If everything you need is to send a simple message you may use:

     use Mail::Sender;

     ref ($sender = new Mail::Sender({from => 'somebody@somewhere.com',smtp
     => 'ms.chipnet.cz'})) or die "$Mail::Sender::Error\n";

     (ref ($sender->MailMsg({to =>'Jenda@Krynicky.cz', subject => 'this is a test',
                             msg => "Hi Johnie.\nHow are you?"}))
      and print "Mail sent OK."
     )
     or die "$Mail::Sender::Error\n";
     __END__

   If you want to attach some files:

     use Mail::Sender;

     ref ($sender = new Mail::Sender({from => 'somebody@somewhere.com',smtp
     => 'mail.yourdomain.com'})) or die "$Mail::Sender::Error\n";

     (ref ($sender->MailFile(
      {to =>'you@address.com', subject => 'this is a test',
       msg => "Hi Johnie.\nI'm sending you the pictures you wanted.",
       file => 'image1.jpg,image2.jpg'
      }))
      and print "Mail sent OK."
     )
     or die "$Mail::Sender::Error\n";
     __END__

   If you want to send a HTML mail:

     use Mail::Sender;
     open IN, $htmlfile or die "Cannot open $htmlfile : $!\n";
     $sender = new Mail::Sender {smtp => 'mail.yourdomain.com'};
     $sender->Open({ from => 'your@address.com', to => 'other@address.com', subject => 'HTML test',
            headers => "MIME-Version: 1.0\r\nContent-type: text/html\r\nContent-Transfer-Encoding: 7bit"
     }) or die $Mail::Sender::Error,"\n";

     while (<IN>) { $sender->Send($_) };
     close IN;
     $sender->Close();
     __END__

   If you want to send a HTML with some inline images :

     use strict;
     use Mail::Sender;
     my $recipients = 'somebody@somewhere.com';
     my $sender = new Mail::Sender {smtp => 'your.mailhost.com'};
     if ($sender->OpenMultipart({from => 'itstech2@gate.net', to => $recipients,
                           subject => 'Embedded Image Test', subtype => 'related',
                           boundary => 'boundary-test-1',
                           type => 'multipart/related'}) > 0) {
      $sender->SendFile(
             {description => 'html body',
             ctype => 'text/html; charset=us-ascii',
             encoding => '7bit',
             disposition => 'NONE',
             file => 'test.html'
       });
      $sender->SendFile(
       {description => 'ed\'s gif',
        ctype => 'image/gif',
        encoding => 'base64',
        disposition => "inline; filename=\"apache_pb.gif\";\r\nContent-ID: <ed1>",
        file => 'apache_pb.gif'
       });
      $sender->Close() or die "Close failed! $Mail::Sender::Error\n";
     } else {
      die "Cannot send mail: $Mail::Sender::Error\n";
     }
     __END__

   In the HTML you'll have this :  ... <IMG src="cid:ed1"> ...

   Please keep in mind that the image name is unimportant, the Content-ID
is what counts!

   If you want to send a mail with an attached file you just got from a
HTML form:

     #!perl

     use CGI;
     use Mail::Sender;

     $query = new CGI;

     # uploading the file...
     $filename = $query->param('mailformFile');
     if ($filename ne ""){
      $tmp_file = $query->tmpFileName($filename);
     }

     $sender = new Mail::Sender {from => 'script@mccann.cz',smtp => 'mail.mccann.cz'};
     $sender->OpenMultipart({to=> 'jenda@mccann.cz',subject=> 'test CGI attach'});
     $sender->Body();
     $sender->Send(<<"*END*");
     This is just a test of mail with an uploaded file.

     Jenda
     *END*
     $sender->SendFile(
              {encoding => 'Base64',
        description => $filename,
        ctype => $query->uploadInfo($filename)->{'Content-Type'},
        disposition => "attachment; filename = $filename",
               file => $tmp_file
              });
     $sender->Close();

     print "Content-type: text/plain\n\nYes, it's sent\n\n";

WARNING
-------

   DO NOT mix Open(Multipart)|Send(Line)(Ex)|Close with MailMsg or
MailFile.  Both Mail(Msg/File) close any Open-ed mail.  Do not try this:

     $sender = new Mail::Sender ...;
     $sender->OpenMultipart...;
     $sender->Body;
     $sender->Send("...");
     $sender->MailFile({file => 'something.ext');
     $sender->Close;

   This WON'T work!!!

BUGS
====

   This module (as well as those I used as an example when I wrote it)
doesn't work with qmail.  To make this clear, the local SMTP server you
contact directly from the script (Open({smtp => ...})) may not be qmail.
The problem is that the module expects a one-line response from the server
and gets confused if it gets a longer response.  If you set up qmail to
send only one-line responses you shell be OK.  Otherwise you need to use a
different SMTP server. Sorry, I'll fix this as soon as I have some spare
time.

DISCLAIMER
==========

   This module is based on SendMail.pm Version : 1.21 that appeared in
Perl-Win32-Users@activeware.com mailing list. I don't remember the name of
the poster and it's not mentioned in the script. Thank you mr. undef.

AUTHOR
======

   Jan Krynicky <Jenda@Krynicky.cz>

   With help of Rodrigo Siqueira <rodrigo@insite.com.br>, Ed McGuigan
<itstech1@gate.net>, and others.

COPYRIGHT
=========

   Copyright (c) 1997-1999 Jan Krynicky <Jenda@Krynicky.cz>. All rights
reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Simple platform independent mailer
**********************************

NAME
====

   Mail::Sendmail v. 0.78 - Simple platform independent mailer

SYNOPSIS
========

     use Mail::Sendmail;

     %mail = ( To      => 'you@there.com',
               From    => 'me@here.com',
               Message => "This is a very short message"
              );

     sendmail(%mail) or die $Mail::Sendmail::error;

     print "OK. Log says:\n", $Mail::Sendmail::log;

DESCRIPTION
===========

   Simple platform independent e-mail from your perl script. Only requires
Perl 5 and a network connection.

   After struggling for some time with various command-line mailing
programs which never did exactly what I wanted, I put together this Perl
only solution.

   Mail::Sendmail contains mainly &sendmail, which takes a hash with the
message to send and sends it. It is intended to be very easy to setup and
use.

INSTALLATION
============

Best
     perl -MCPAN -e "install Mail::Sendmail"

Traditional
          perl Makefile.PL
          make
          make test
          make install

Manual
     Copy Sendmail.pm to Mail/ in your Perl lib directory.

          (eg. c:\Perl\lib\Mail\, c:\Perl\site\lib\Mail\,
           /usr/lib/perl5/site_perl/Mail/, ... or whatever it
           is on your system)

ActivePerl's PPM
     ppm install -location=http://alma.ch/perl/ppm Mail-Sendmail

     But this way you don't get a chance to have a look at other files
     (Changes, Todo, test.pl, ...) and PPM doesn't run the test script
     (test.pl).

   At the top of Sendmail.pm, set your default SMTP server, unless you
specify it with each message, or want to use the default.

   Install MIME::QuotedPrint. This is not required but strongly
recommended.

FEATURES
========

   Automatic time zone detection, Date: header, MIME quoted-printable
encoding (if MIME::QuotedPrint installed), all of which can be overridden.

   Internal Bcc: and Cc: support (even on broken servers)

   Allows real names in From: and To: fields

   Doesn't send unwanted headers, and allows you to send any header(s) you
want

   Configurable retries and use of alternate servers if your mail server is
down

   Good plain text error reporting

LIMITATIONS
===========

   Doesn't work on OpenVMS.

   Headers are not encoded, even if they have accented characters.

   Since the whole message is in memory (twice!), it's not suitable for
sending very big attached files.

   The SMTP server has to be set manually in Sendmail.pm or in your script,
unless you have a mail server on localhost.

CONFIGURATION
=============

Default SMTP server(s)
     This is probably all you want to configure. It is usually done through
     *$mailcfg{smtp}*, which you can edit at the top of the Sendmail.pm
     file.  This is a reference to a list of SMTP servers. You can also
     set it from your script:

     `unshift @{$Mail::Sendmail::mailcfg{'smtp'}} , 'my.mail.server';'

     Alternatively, you can specify the server in the *%mail* hash you send
     from your script, which will do the same thing:

     `$mail{smtp} = 'my.mail.server';'

     A future version will try to set useful defaults for you during the
     Makefile.PL.

Other configuration settings
     See *%mailcfg* under `"DETAILS"' in this node below for other
     configuration options.

DETAILS
=======

sendmail()
----------

   sendmail is the only thing exported to your namespace by default

   `sendmail(%mail) || print "Error sending mail:
$Mail::Sendmail::error\n";'

   It takes a hash containing the full message, with keys for all headers,
body, and optionally for another non-default SMTP server and/or port.

   It returns 1 on success or 0 on error, and rewrites
$Mail::Sendmail::error and $Mail::Sendmail::log.

   Keys are NOT case-sensitive.

   The colon after headers is not necessary.

   The Body part key can be called 'Body', 'Message' or 'Text'. The SMTP
server key can be called 'Smtp' or 'Server'.

   The following headers are added unless you specify them yourself:

     Mime-version: 1.0
     Content-type: 'text/plain; charset="iso-8859-1"'

     Content-transfer-encoding: quoted-printable
     or (if MIME::QuotedPrint not installed)
     Content-transfer-encoding: 8bit

     Date: [string returned by time_to_date()]

   The following are not exported by default, but you can still access them
with their full name, or request their export on the use line like in:
`use Mail::Sendmail qw($address_rx time_to_date);'

Mail::Sendmail::time_to_date()
------------------------------

   convert time ( as from `time()' ) to an RFC 822 compliant string for the
Date header. See also `"%Mail::Sendmail::mailcfg"' in this node.

$Mail::Sendmail::error
----------------------

   When you don't run with the -w flag, the module sends no errors to
STDERR, but puts anything it has to complain about in here. You should
probably always check if it says something.

$Mail::Sendmail::log
--------------------

   A summary that you could write to a log file after each send

$Mail::Sendmail::address_rx
---------------------------

   A handy regex to recognize e-mail addresses.

   A correct regex for valid e-mail addresses was written by one of the
judges in the obfuscated Perl contest... :-) It is quite big. This one is
an attempt to a reasonable compromise, and should accept all real-world
internet style addresses. The domain part is required and comments or
characters that would need to be quoted are not supported.

     Example:
       $rx = $Mail::Sendmail::address_rx;
       if (/$rx/) {
         $address=$1;
         $user=$2;
         $domain=$3;
       }

%Mail::Sendmail::mailcfg
------------------------

   This hash contains all configuration options. You normally edit it once
(if ever) in Sendmail.pm and forget about it, but you could also access it
from your scripts. For readability, I'll assume you have imported it.

   The keys are not case-sensitive: they are all converted to lowercase
before use. Writing `$mailcfg{Port} = 2525;' is OK: the default
$mailcfg{port} (25) will be deleted and replaced with your new value of
2525.

$mailcfg{smtp}
     `$mailcfg{smtp} = [qw(localhost my.other.mail.server)];'

     This is a reference to a list of smtp servers, so if your main server
     is down, the module tries the next one. If one of your servers uses a
     special port, add it to the server name with a colon in front, to
     override the default port (like in my.special.server:2525).

     Default: localhost. (the previous version also had smtp.site1.csi.com
     which was an open relay, but it isn't anymore)

$mailcfg{from}
     `$mailcfg{from} = 'Mailing script me@mydomain.com';'

     From address used if you don't supply one in your script. Should not
     be of type 'user@localhost' since that may not be valid on the
     recipient's host.

     Default: undefined.

$mailcfg{mime}
     `$mailcfg{mime} = 1;'

     Set this to 0 if you don't want any automatic MIME encoding. You
     normally don't need this, the module should 'Do the right thing'
     anyway.

     Default: 1;

$mailcfg{retries}
     `$mailcfg{retries} = 1;'

     How many times should the connection to the same SMTP server be
     retried in case of a failure.

     Default: 1;

$mailcfg{delay}
     `$mailcfg{delay} = 1;'

     Number of seconds to wait between retries. This delay also happens
     before trying the next server in the list, if the retries for the
     current server have been exhausted. For CGI scripts, you want few
     retries and short delays to return with a results page before the
     http connection times out. For unattended scripts, you may want to
     use many retries and long delays to have a good chance of your mail
     being sent even with temporary failures on your network.

     Default: 1 (second);

$mailcfg{tz}
     `$mailcfg{tz} = '+0800';'

     Normally, your time zone is set automatically, from the difference
     between `time()' and `gmtime()'. This allows you to override
     automatic detection in cases where your system is confused (such as
     some Win32 systems in zones which do not use daylight savings time:
     see Microsoft KB article Q148681)

     Default: undefined (automatic detection at run-time).

$mailcfg{port}
     `$mailcfg{port} = 25;'

     Port used when none is specified in the server name.

     Default: 25.

$mailcfg{debug}
     `$mailcfg{debug} =' 0;>

     Prints stuff to STDERR. Not used much, and what is printed may change
     without notice. Don't count on it.

     Default: 0;

$Mail::Sendmail::VERSION
------------------------

   The package version number (you can not import this one)

Configuration variables from previous versions
----------------------------------------------

   The following global variables were used in version 0.74 for
configuration.  They should still work, but will not in a future version
(unless you complain loudly). Please use *%mailcfg* if you need to access
the configuration from your scripts.

$Mail::Sendmail::default_smtp_server
$Mail::Sendmail::default_smtp_port
$Mail::Sendmail::default_sender
$Mail::Sendmail::TZ
$Mail::Sendmail::connect_retries
$Mail::Sendmail::retry_delay
$Mail::Sendmail::use_MIME
     This one couldn't really be used in the previous version, so I just
     dropped it.  It is replaced by *$mailcfg{mime}* which works.

ANOTHER EXAMPLE
===============

     use Mail::Sendmail;

     print "Testing Mail::Sendmail version $Mail::Sendmail::VERSION\n";
     print "Default server: $Mail::Sendmail::mailcfg{smtp}->[0]\n";
     print "Default sender: $Mail::Sendmail::mailcfg{from}\n";

     %mail = (
         #To      => 'No to field this time, only Bcc and Cc',
         #From    => 'not needed, use default',
         Bcc     => 'Someone <him@there.com>, Someone else her@there.com',
         # only addresses are extracted from Bcc, real names disregarded
         Cc      => 'Yet someone else <xz@whatever.com>',
         # Cc will appear in the header. (Bcc will not)
         Subject => 'Test message',
         'X-Mailer' => "Mail::Sendmail version $Mail::Sendmail::VERSION",
     );

     $mail{Smtp} = 'special_server.for-this-message-only.domain.com';
     $mail{'X-custom'} = 'My custom additionnal header';
     $mail{'mESSaGE : '} = "The message key looks terrible, but works.";
     # cheat on the date:
     $mail{Date} = Mail::Sendmail::time_to_date( time() - 86400 ),

     if (sendmail %mail) { print "Mail sent OK.\n" }
     else { print "Error sending mail: $Mail::Sendmail::error \n" }

     print "\n\$Mail::Sendmail::log says:\n", $Mail::Sendmail::log;

CHANGES
=======

   Single-letter host names bug fixed since version 0.77. See the Changes
file for the full history.

AUTHOR
======

   Milivoj Ivkovic mi@alma.ch or ivkovic@bluewin.ch

NOTES
=====

   MIME::QuotedPrint is used by default on every message if available. It
allows reliable sending of accented characters, and also takes care of too
long lines (which can happen in HTML mails). It is available in the
MIME-Base64 package at http://www.perl.com/CPAN/modules/by-module/MIME/ or
through PPM.

   Look at http://alma.ch/perl/Mail-Sendmail-FAQ.htm for additional info
(CGI, examples of sending attachments, HTML mail etc...)

   You can use it freely. (Someone complained this is too vague. So, more
precisely: do whatever you want with it, but be warned that terrible things
will happen to you if you use it badly, like for sending spam, claiming you
wrote it alone, or ...?)

   I would appreciate a short (or long) e-mail note if you use this (and
even if you don't, especially if you care to say why). And of course,
bug-reports and/or suggestions are welcome.

   Last revision: 25.09.2000. Latest version should be available at
http://alma.ch/perl/mail.htm , and a few days later on CPAN.

Perl module for getting quick statistics on procmail generated mailbox files.
*****************************************************************************

NAME
====

   Mail::Stats - Perl module for getting quick statistics on procmail
generated mailbox files.

SYNOPSIS
========

     use Mail::Stats;

DESCRIPTION
===========

   This is the beginning of a quick and dirty mbox statistics program.  It
will be very reworked over the next many moons.  Hopefully it is mildly
useful in its current format.

   More documentation would be here, but I am getting on a plane to another
country, and would like to get something out in an alpha state before I
leave.

AUTHOR     Sean Dague   sean@dague.net   http://dague.net/sean
==============================================================

SEE ALSO
========

   perl(1).

Perl module for holding stats about a mailbox
*********************************************

NAME
====

   Mail::Stats::Record - Perl module for holding stats about a mailbox

SYNOPSIS
========

     use Mail::Stats::Record;

DESCRIPTION
===========

AUTHOR     Sean Dague   sean@dague.net   http://dague.net/sean
==============================================================

SEE ALSO
========

   perl(1), Mail::Stats

Tied hash interface for mail folders
************************************

NAME
====

   Mail::TieFolder - Tied hash interface for mail folders

SYNOPSIS
========

     use Mail::TieFolder;

     # assuming inbox is an MH folder, and the
     # Mail::TieFolder::mh module is installed:
     tie (%inbox, 'Mail::TieFolder', 'mh', 'inbox');

     # get list of all message IDs in folder
     @messageIDs = keys (%inbox);

     # fetch message (as Mail::Internet object) by ID
     $msg = $inbox{'9287342.2138749@foo.com'};

DESCRIPTION
===========

   Mail::TieFolder implements a tied hash interface for manipulating
folder contents.  Messages in the hash are accessed by Message-Id.

   See the Mail::TieFolder::* modules on CPAN for supported folder
formats.  If the format you're looking for isn't supported, please feel
free to implement your own module and upload it to CPAN as
Mail::TieFolder::yourformat.  New formats are by design relatively easy to
implement - see `"IMPLEMENTING A NEW MAILBOX FORMAT"' in this node for
guidelines.

COMPARISON WITH OTHER MODULES
=============================

   As with all things in Perl, There Is More Than One Way To Do It.

   Mail::TieFolder and the Mail::TieFolder::* modules provide a
lightweight API for manipulating the contents of mail folders in various
formats.  These modules only put, fetch, create, delete, or refile
messages in folders, using Message-ID as the message handle.  They don't
pretend to know anything about the internal formatting of the messages
themselves (leaving that to Mail::Internet), they don't do indexing,
searches, address books, or other MUA stuff, nor do they pretend to
provide any overall management of your folders.  They can, however, be
used to move or copy messages between folders, and will create a new
folder if you name a non-existent folder in the tie().

   The Mail::Folder, Mail::Box, and Mail::MsgStore modules also provide
for managing folders and their contents.  Those modules generally have
more of a concept of managing your whole mail world of multiple folders,
including address books, folder searches, indexes, and other MUA tools.  I
didn't need this, and the additional overhead was prohibitive.  The
additional capabilities of those modules also mean that implementing
modules to support new folder formats is a more complex undertaking.

   I went with a tie() interface for Mail::TieFolder because it
constrained the API to a reasonably small and well-defined set of
functions.  This lowers the bar of entry for other authors who want to add
Mail::TieFolder::* modules to support additional folder formats.

   Both Mail::Folder and the Mail::Box::Tie modules use message sequence
numbers as the primary key into a folder.  Message sequence numbers are
not fixed attributes uniquely attached to one and only one message, and
can change as a folder is resorted and packed, and as messages are moved
between folders.

   For Mail::TieFolder, I instead used Message-ID as the key into a mail
folder, since it's theoretically a globally unique identifier.  This way
you can sort, renumber, pack, and so on, and still have safe, immutable,
persistent handles on individual messages.

   (Note that Mail::Box does support a messageID() method, and if you were
so inclined, you could use Mail::Box as the backend for a
Mail::TieFolder::* module, provided that the correct Mail::Box::* module
exists to support your desired folder format.  This would be putting a
lightweight and constrained interface on the front of a much more capable
and heavyweight engine, but might meet your needs.)

IMPLEMENTING A NEW MAILBOX FORMAT
=================================

   Mail::TieFolder::* modules to support additional mailbox formats are
easy to implement; you only need to support the API functions for a tied
hash (TIEHASH, FETCH, FIRSTKEY, NEXTKEY, EXISTS, STORE, and DELETE).  See
the Perl Cookbook, see Perltie (perl.info), or the
Mail::TieFolder::mh module code for examples.  I'd suggest using 'h2xs
-Xn` to create a template for your module.

   To ensure compatibility with other Mail::TieFolder::* modules, make a
./t directory under the distribution tree for your new module, then copy
the test scripts and other data files from the ./t directory of the
Mail::TieFolder::mh distribution into the ./t directory of your own
module's tree, and edit them accordingly to get rid of the mh-specific
stuff and add any setup which your mailbox format needs.

   These test scripts will exercise your new module via the
Mail::TieFolder module to make sure they are talking to each other
correctly.

   Make sure when you edit the test scripts that you change the folder
format in the tie() calls.  You'll also want to delete the dummy ./test.pl
script which h2xs generated and then re-run 'perl Makefile.PL' to generate
a Makefile which recognizes the ./t subdirectory.

   If you run into "can't find subroutine" problems, you may not be doing
the inheritance right - careful, Mail::TieFolder ISA
Mail::TieFolder::yourformat, not the other way around.  See the TIEHASH
functions in Mail::TieFolder and Mail::TieFolder::mh - note in particular
the @ISA stuff in Mail::TieFolder and the ref() calls in the
Mail::TieFolder::mh bless().  Also make sure you've removed the 'our @ISA'
line in your new h2xs generated code - it masks the @ISA in
Mail::TieFolder.

   When you're happy with your module, you'll want to upload it to CPAN -
see ftp://cpan.org/pub/CPAN/modules/04pause.html.

AUTHOR
======

   Steve Traugott, stevegt@TerraLuna.Org

SEE ALSO
========

   See Perltie (perl.info), `Mail::TieFolder::mh' in this node,
see Mail/Folder, Mail/MsgStore,
Mail/Box,

mail utility functions
**********************

NAME
====

   Mail::Util - mail utility functions

SYNOPSIS
========

   use Mail::Util qw( ... );

DESCRIPTION
===========

   This package provides several mail related utility functions. Any
function required must by explicitly listed on the use line to be exported
into the calling package.

read_mbox( $file )
------------------

   Read $file, a binmail mailbox file, and return a list of  references.
Each reference is a reference to an array containg one message.

maildomain()
------------

   Attempt to determine the current uers mail domain string via the
following methods

     Look for a sendmail.cf file and extract DH parameter
     Look for a smail config file and usr the first host defined in hostname(s)
     Try an SMTP connect (if Net::SMTP exists) first to mailhost then localhost
     Use value from Net::Domain::domainname (if Net::Domain exists)

mailaddress()
-------------

   Return a guess at the current users mail address. The user can force
the return value by setting `$ENV{MAILADDRESS}'

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

COPYRIGHT
=========

   Copyright (c) 1995-8 Graham Barr. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

A Perl module to use Vmailmgr daemon.
*************************************

NAME
====

   Mail::Vmailmgr - A Perl module to use Vmailmgr daemon.

SYNOPSIS
========

   use Mail::Vmailmgr;

   #create a user account martin@mydomain.com vadduser("mydomain.com",
"my_domain_passwd", "martin");

DESCRIPTION
===========

   This module allows easy interaction with the vmailmgrd, a daemon
designed to allow access to all of vmailmgr functions from unprivileged
accounts, such as CGI scripts usually have.

   It was designed and tested against vmailmgrd version 0.96.9. A major
rewrite of vmailmgrd is expected, so this module may not work properly
with newer versions of vmailmgrd.

AUTHOR
======

   The author and mantainer of this module is Martin Langhoff
<martin@scim.net>.

   Most of this initial release is based on the PHP version written by
Mike Bell <mike@mikebell.org>. This module would not be here without
Mike's help.

Passwords
=========

   Commands that operate on an existing virtual user account can be
authorized with either the virtual user account password, or with the
domain-user password.

   Commands that operate on the virtual domain, such as vadduser, can only
be authorized with the domain-user password.

Return codes
============

   In a very un-perlish fashion, all of these functions (with a few
exceptions) will return an array where the first positions indicates if
the command succeded or not.

   If the command did not succeed, the error code will be >0. And probably
you'll find string in the second position of the array, indicating what
went wrong.

   The success code is "0". This is consistent with the design of the
vmailmgrd interface, and very inconsistent with the general Perl fashion.

vlistdomain($domain, $password){
================================

   Returns the user accounts available in the virtual domain.

   Similar to the listvdomain binary, supplied with Vmailmgr.

vlookup($domain, $user, $password)
==================================

   Returns for a single virtual user what vlistdomain does for an entire
domain.

vadduser($domain, $password, $username, $userpass, @forwards)
=============================================================

   Similar to the vadduser binary, supplied with Vmailmgr.

vaddalias($domain, $password, $username, $userpass, @forwards)
==============================================================

   Similar to the vaddalias binary, supplied with Vmailmgr.

vdeluser($domain, $password, $username)
=======================================

   Similar to the vdeluser binary, supplied with Vmailmgr.

vchpass($domain, $password, $username, $newpass)
================================================

   Similar to the vchpassd binary, supplied with Vmailmgr.

vchforward($domain, $password, $username, @forwards)
====================================================

   Similar to the vchpassd binary, supplied with Vmailmgr.

vchattr($domain, $password, $username, $attr, $value)
=====================================================

   Change Attribute. Chech attribute list and the possible values with the
vmailmgr documentation.

vwriteautoresponse($domain, $password, $username, $message)
===========================================================

   missing explanation

vreadautoresponse($domain, $password, $username, $message)
==========================================================

   missing explanation

vdisableautoresponse($domain, $password, $username, $message)
=============================================================

   missing explanation

venableautoresponse($domain, $password, $username, $message)
============================================================

   missing explanation

vautoresponsestatus($domain, $password, $username, $message)
============================================================

   missing explanation

SEE ALSO
========

   vmailmgr(7).

Adds a toXML() method to Mail::Internet.
****************************************

NAME
====

   Mail::XML - Adds a toXML() method to Mail::Internet.

SYNOPSIS
========

     use Mail::XML;
     my $mi = new Mail::XML(\@message);
     print $mi->toXML();

DESCRIPTION
===========

   All that this module does is provide a toXML() method to
Mail::Internet.  For all intents and purposes, Mail::XML is Mail::Internet
plus toXML(), so you are best off reading the Mail::Internet manpage :)

WHY??
=====

   I had some messy scripts which took messages from a mailing list and
archived them in XML.  When it came time to maintain my messy scripts, I
was lost, so I started using Mail::Internet and just supplying my own
toXML() method.  This module is an evolution of all of that :)

FUTURE PLANS
============

   I plan on doing something useful with MIME attachments, supplying a
toMIME() function.  Ideas and contributions are welcome.

   =head1 AUTHOR

   Matthew MacKenzie <matt@xmlglobal.com>

SEE ALSO
========

   Mail::Internet

module for processing makefiles
*******************************

NAME
====

   Make - module for processing makefiles

SYNOPSIS
========

     require Make;
     my $make = Make->new(...);
     $make->parse($file);
     $make->Script(@ARGV)
     $make->Make(@ARGV)
     $make->Print(@ARGV)

     my $targ = $make->Target($name);
     $targ->colon([dependancy...],[command...]);
     $targ->dolon([dependancy...],[command...]);
     my @depends  = $targ->colon->depend;
     my @commands = $targ->colon->command;

DESCRIPTION
===========

   Make->new creates an object if `new(Makefile => $file)' is specified
then it is parsed. If not the usual makefile Makefile sequence is used.
(If GNU => 1 is passed to new then GNUmakefile is looked for first.)

   `$make->Make(target...)' 'makes' the target(s) specified (or the first
'real' target in the makefile).

   `$make->Print' can be used to 'print' to current select'ed stream a
form of the makefile with all variables expanded.

   `$make->Script(target...)' can be used to 'print' to current select'ed
stream the equivalent bourne shell script that a make would perform i.e.
the output of `make -n'.

   There are other methods (used by parse) which can be used to add and
manipulate targets and their dependants. There is a hierarchy of classes
which is still evolving. These classes and their methods will be
documented when they are a little more stable.

   The syntax of makefile accepted is reasonably generic, but I have not
re-read any documentation yet, rather I have implemented my own mental
model of how make works (then fixed it...).

   In addition to traditional

     .c.o :
     	$(CC) -c ...

   GNU make's 'pattern' rules e.g.

     %.o : %.c
     	$(CC) -c ...

   Likewise a subset of GNU makes $(function arg...) syntax is supported.

   Via pmake Make has built perl/Tk from the MakeMaker generated
Makefiles...

BUGS
====

   At present new must always find a makefile, and `$make->parse($file)'
can only be used to augment that file.

   More attention needs to be given to using the package to write
makefiles.

   The rules for matching 'dot rules' e.g. .c.o   and/or pattern rules
e.g. %.o : %.c are suspect. For example give a choice of .xs.o vs .xs.c +
.c.o behaviour seems a little odd.

   Variables are probably substituted in different 'phases' of the process
than in make(1) (or even GNU make), so 'clever' uses will probably not
work.

   UNIXisms abound.

SEE ALSO
========

   `pmake' in this node

AUTHOR
======

   Nick Ing-Simmons

SYNOPSIS
========

     use Math::Amoeba qw(ConstructVertices EvaluateVertices Amoeba MinimiseND);
     my ($vertice,$y)=MinimiseND(\@guess,\@scales,\&func,$tol,$itmax);
     my @vertices=ConstructVertices(\@vector,\@offsets);
     my @y=EvaluateVertices(\@vertices,\&func);
     my ($vertice,$y)=Amoeba(\@vertices,\@y,\&func,$tol,$itmax);

DESCRIPTION
===========

   This is an implimenation of the Downhill Simpex Method in
Multidimensions (Nelder and Mead) for finding the (local) minimum of a
function. Doing this in Perl makes it easy for that function to actually
be the output of another program such as a simulator.

   Arrays and the function are passed by reference to the routines.

   The simplest use is the *MinimiseND* function. This takes a reference
to an array of guess values for the parameters at the function minimum, a
reference to an array of scales for these parameters (sensible ranges
around the guess in which to look), a reference to the function, a
convergence tolerence for the minimum and the maximum number of iterations
to be taken. It returns an array consisting of a reference to the function
parameters at the minimum and the value there.

   The *Amoeba* function is the actual implimentation of the Downhill
Simpex Method in Multidimensions. It takes a reference to an array of
references to arrays which are the initial n+1 vertices (where n is the
number of function parameters), a reference to the function valuation at
these vertices, a reference to the function, a convergence tolerence for
the minimum and the maximum number of iterations to be taken. It returns
an array consisting of a reference to the function parameters at the
minimum and the value there.

   The *ConstructVertices* is used by *MinimiseND* to construct the
initial vertices for *Amoeba* as the initial guess plus the parameter
scale parameters as vectors along the parameter axis.

   The *EvaluateVertices* takes these set of vertices, calling the
function for each one and returning the vector of results.

EXAMPLE
=======

     use Math::Amoeba qw(MinimiseND);
     sub afunc {
       my ($a,$b)=@_;
       print "$a\t$b\n";
       return ($a-7)**2+($b+3)**2;
     }
     my @guess=(1,1);
     my @scale=(1,1);
     ($p,$y)=MinimiseND(\@guess,\@scale,\&afunc,1e-7,100);
     print "(",join(',',@{$p}),")=$y\n";

   produces the output

   (6.99978191653352,-2.99981241563247)=1.00000008274829

HISTORY
=======

   $Log: Amoeba.pm,v $ Revision 1.2  1995/12/24 12:37:46  willijar General
fixup. Added documentation.

BUGS
====

   If the function value converges to exactly zero then the condition for
convergence fails and maximum iterations will be exceeded or there will be
a divide by zero error. There is no obvious way to test for convergence in
this case however adding 1 onto the function value gives expected
behaviour. i.e. replace '\&afunc' with 'sub { 1+afunc(@_); }' when calling
the routines.

   Let me know.

AUTHOR
======

   John A.R. Williams <J.A.R.Williams@aston.ac.uk>

SEE ALSO
========

   "Numerical Recipies: The Art of Scientific Computing" W.H. Press, B.P.
Flannery, S.A. Teukolsky, W.T. Vetterling.  Cambridge University Press.
ISBN 0 521 30811 9.

Math::Approx
************

NAME
====

   Math::Approx

METHODS
=======

new (constructor)
-----------------

     Math::Approx->new(\&poly, $degree, %data);

   If the first argument to the constructor is a CODE reference, this is
used as the function to iterate over the data. Such a function must take
two arguments: The *degree* and the x value.

   For interpolation with plain polynomials poly can be defined as:

     sub poly {
         my($n,$x) = @_;
         return $x ** $n;
     }

   If the first argument in the constructor is a FALSE value instead of a
CODE reference, then the above plain polynomial poly is used as the
iterator function.

   The second argument is the maximum degree which should be used for
interpolation. Degrees start with 0.

   The rest of the arguments are treated as pairs of x and y samples which
should be approximated.

   The constructor returns a Math::Approx reference.

approx
------

     $approximation->approx(17);

   The method returns the approximated  y value for the x value given as
argument.

fit
---

     $approximation->fit;

   Returns the medim square error for the data points.

plot
----

     $approximation->plot("tmp/app");

   Prints all data pairs and the corresponding approximation pairs into
the filename given as argument. The output is suitable for usage with
gnuplot(1).

print
-----

     $approximation->print;

   Prints information about the approximation on STDOUT

EXAMPLE
=======

     use Math::Approx;

     sub poly {
         my($n,$x) = @_;
         return $x ** $n;
     }

     for (1..20) {
         $x{$_} = sin($_/10)*cos($_/30)+0.3*rand;
     }

     $a = new Math::Approx (\&poly, 5, %x);
     $a->print;
     $a->plot("math-approx-demo.out");
     print "Fit: ", $a->fit, "\n";

SEE ALSO
========

   gnuplot(1).

AUTHOR
======

   Ulrich Pfeifer <`pfeifer@wait.de'>

Convert numbers between various bases
*************************************

NAME
====

   Math::BaseCalc - Convert numbers between various bases

SYNOPSIS
========

     use Math::BaseCalc;

     my $calc = new Math::BaseCalc(digits => [0,1]); #Binary
     my $bin_string = $calc->to_base(65); # Convert 465 to binary

     $calc->digits('oct'); # Octal
     my $number = $calc->from_base('1574'); # Convert octal 1574 to decimal

DESCRIPTION
===========

   This module facilitates the conversion of numbers between various
number bases.  You may define your own digit sets, or use any of several
predefined digit sets.

   The to_base() and from_base() methods convert between Perl numbers and
strings which represent these numbers in other bases.  For instance, if
you're using the binary digit set [0,1], $calc->to_base(5) will return the
string "101".  $calc->from_base("101") will return the number 5.

   To convert between, say, base 7 and base 36, use the 2-step process of
first converting to a Perl number, then to the desired base for the result:

     $calc7  = new Math::BaseCalc(digits=>[0..7]);
     $calc36 = new Math::BaseCalc(digits=>[0..9,'a'..'z'];

     $in_base_36 = $calc36->to_base( $calc7->from_base('3506') );

   If you just need to handle regular octal & hexdecimal strings, you
probably don't need this module.  See the sprintf(), oct(), and hex() Perl
functions.

METHODS
=======

   * new Math::BaseCalc

   * new Math::BaseCalc(digits=>...)

     Create a new base calculator.  You may specify the digit set to use,
     by either giving the digits in a list reference (in increasing order,
     with the 'zero' character first in the list) or by specifying the name
     of one of the predefined digit sets (see the digit() method below).

   * $calc->to_base(NUMBER)

     Converts a number to a string representing that number in the
     associated base.  Currently only handles integers.

   * $calc->from_base(STRING)

     Converts a string representing a number in the associated base to a
     Perl integer.  Currently only handles integers.  The behavior when fed
     strings with characters not in $calc's digit set is currently
     undefined.

   * $calc->digits

   * $calc->digits(...)

     Get/set the current digit set of the calculator.  With no arguments,
     simply returns a list of the characters that make up the current digit
     set.  To change the current digit set, pass a list reference
     containing the new digits, or the name of a predefined digit set.
     Currently the predefined digit sets are:

          bin => [0,1],
          hex => [0..9,'a'..'f'],
          HEX => [0..9,'A'..'F'],
          oct => [0..7],
          64  => ['A'..'Z','a'..'z',0..9,'+','/'],
          62  => [0..9,'a'..'z','A'..'Z'],

           Examples:
            $calc->digits('bin');
            $calc->digits([0..7]);
            $calc->digits([qw(w a l d o)]);

     If any of your "digits" has more than one character, the behavior is
     currently undefined.

QUESTIONS
=========

   The '64' digit set is meant to be useful for Base64 encoding.  I took
it from the MIME::Base64.pm module.  Does it look right?  It's sure in a
strange order.

AUTHOR
======

   Ken Williams, ken@forum.swarthmore.edu

COPYRIGHT
=========

   This is free software in the colloquial nice-guy sense of the word.
Copyright (c) 1999, Ken Williams.  You may redistribute and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1).

solution of Bezier Curves
*************************

NAME
====

   Math::Bezier - solution of Bezier Curves

SYNOPSIS
========

     use Math::Bezier;

     # create curve passing list of (x, y) control points
     my $bezier = Math::Bezier->new($x1, $y1, $x2, $y2, ..., $xn, $yn);

     # or pass reference to list of control points
     my $bezier = Math::Bezier->new([ $x1, $y1, $x2, $y2, ..., $xn, $yn]);

     # determine (x, y) at point along curve, range 0 -> 1
     my ($x, $y) = $bezier->point(0.5);

     # returns list ref in scalar context
     my $xy = $bezier->point(0.5);

     # return list of 20 (x, y) points along curve
     my @curve = $bezier->curve(20);

     # returns list ref in scalar context
     my $curve = $bezier->curve(20);

DESCRIPTION
===========

   This module implements the algorithm for the solution of Bezier curves
as presented by Robert D. Miller in Graphics Gems V, "Quick and Simple
Bezier Curve Drawing".

   A new Bezier curve is created using the new() constructor, passing a
list of (x, y) control points.

     use Math::Bezier;

     my @control = ( 0, 0, 10, 20, 30, -20, 40, 0 );
     my $bezier  = Math::Bezier->new(@control);

   Alternately, a reference to a list of control points may be passed.

     my $bezier  = Math::Bezier->new(\@control);

   The point($theta) method can then be called on the object, passing a
value in the range 0 to 1 which represents the distance along the curve.
When called in list context, the method returns the x and y coordinates of
that point on the Bezier curve.

     my ($x, $y) = $bezier->point(0.5);
     print "x: $x  y: $y\n

   When called in scalar context, it returns a reference to a list
containing the x and y coordinates.

     my $point = $bezier->point(0.5);
     print "x: $point->[0]  y: $point->[1]\n";

   The curve($n) method can be used to return a set of points sampled
along the length of the curve (i.e. in the range 0 <= $theta <= 1).  The
parameter indicates the number of sample points required, defaulting to 20
if undefined.  The method returns a list of ($x1, $y1, $x2, $y2, ..., $xn,
$yn) points when called in list context, or a reference to such an array
when called in scalar context.

     my @points = $bezier->curve(10);

     while (@points) {
     	my ($x, $y) = splice(@points, 0, 2);
     	print "x: $x  y: $y\n";
     }

     my $points = $bezier->curve(10);

     while (@$points) {
     	my ($x, $y) = splice(@$points, 0, 2);
     	print "x: $x  y: $y\n";
     }

AUTHOR
======

   Andy Wardley <abw@kfs.org>

SEE ALSO
========

   Graphics Gems 5, edited by Alan W. Paeth, Academic Press, 1995, ISBN
0-12-543455-3.  Section IV.8, 'Quick and Simple Bezier Curve Drawing' by
Robert D. Miller, pages 206-209.

Arbitrary length float math package
***********************************

NAME
====

   Math::BigFloat - Arbitrary length float math package

SYNOPSIS
========

     use Math::BigFloat;
     $f = Math::BigFloat->new($string);

     $f->fadd(NSTR) return NSTR            addition
     $f->fsub(NSTR) return NSTR            subtraction
     $f->fmul(NSTR) return NSTR            multiplication
     $f->fdiv(NSTR[,SCALE]) returns NSTR   division to SCALE places
     $f->fneg() return NSTR                negation
     $f->fabs() return NSTR                absolute value
     $f->fcmp(NSTR) return CODE            compare undef,<0,=0,>0
     $f->fround(SCALE) return NSTR         round to SCALE digits
     $f->ffround(SCALE) return NSTR        round at SCALEth place
     $f->fnorm() return (NSTR)             normalize
     $f->fsqrt([SCALE]) return NSTR        sqrt to SCALE places

DESCRIPTION
===========

   All basic math operations are overloaded if you declare your big floats
as

     $float = new Math::BigFloat "2.123123123123123123123123123123123";

number format
     canonical strings have the form /[+-]\d+E[+-]\d+/ .  Input values can
     have embedded whitespace.

Error returns 'NaN'
     An input parameter was "Not a Number" or divide by zero or sqrt of
     negative number.

Division is computed to
     `max($Math::BigFloat::div_scale,length(dividend)+length(divisor))'
     digits by default.  Also used for default sqrt scale.

Rounding is performed
     according to the value of `$Math::BigFloat::rnd_mode':

          trunc     truncate the value
          zero      round towards 0
          +inf      round towards +infinity (round up)
          -inf      round towards -infinity (round down)
          even      round to the nearest, .5 to the even digit
          odd       round to the nearest, .5 to the odd digit

     The default is `even' rounding.

BUGS
====

   The current version of this module is a preliminary version of the real
thing that is currently (as of perl5.002) under development.

   The printf subroutine does not use the value of
`$Math::BigFloat::rnd_mode' when rounding values for printing.
Consequently, the way to print rounded values is to specify the number of
digits both as an argument to `ffround' and in the `%f' printf string, as
follows:

     printf "%.3f\n", $bigfloat->ffround(-3);

AUTHOR
======

   Mark Biggar

Arbitrary size integer math package
***********************************

NAME
====

   Math::BigInt - Arbitrary size integer math package

SYNOPSIS
========

     use Math::BigInt;
     $i = Math::BigInt->new($string);

     $i->bneg return BINT               negation
     $i->babs return BINT               absolute value
     $i->bcmp(BINT) return CODE         compare numbers (undef,<0,=0,>0)
     $i->badd(BINT) return BINT         addition
     $i->bsub(BINT) return BINT         subtraction
     $i->bmul(BINT) return BINT         multiplication
     $i->bdiv(BINT) return (BINT,BINT)  division (quo,rem) just quo if scalar
     $i->bmod(BINT) return BINT         modulus
     $i->bgcd(BINT) return BINT         greatest common divisor
     $i->bnorm return BINT              normalization
     $i->blsft(BINT) return BINT        left shift
     $i->brsft(BINT) return (BINT,BINT) right shift (quo,rem) just quo if scalar
     $i->band(BINT) return BINT         bit-wise and
     $i->bior(BINT) return BINT         bit-wise inclusive or
     $i->bxor(BINT) return BINT         bit-wise exclusive or
     $i->bnot return BINT               bit-wise not

DESCRIPTION
===========

   All basic math operations are overloaded if you declare your big
integers as

     $i = new Math::BigInt '123 456 789 123 456 789';

Canonical notation
     Big integer value are strings of the form `/^[+-]\d+$/' with leading
     zeros suppressed.

Input
     Input values to these routines may be strings of the form
     `/^\s*[+-]?[\d\s]+$/'.

Output
     Output values always always in canonical form

   Actual math is done in an internal format consisting of an array whose
first element is the sign (/^[+-]$/) and whose remaining elements are base
100000 digits with the least significant digit first.  The string 'NaN' is
used to represent the result when input arguments are not numbers, as well
as the result of dividing by zero.

EXAMPLES
========

     '+0'                            canonical zero value
     '   -123 123 123'               canonical value '-123123123'
     '1 23 456 7890'                 canonical value '+1234567890'

Autocreating constants
======================

   After `use Math::BigInt ':constant'' all the integer decimal constants
in the given scope are converted to Math::BigInt.  This conversion happens
at compile time.

   In particular

     perl -MMath::BigInt=:constant -e 'print 2**100'

   print the integer value of `2**100'.  Note that without conversion of
constants the expression 2**100 will be calculated as floating point
number.

BUGS
====

   The current version of this module is a preliminary version of the real
thing that is currently (as of perl5.002) under development.

AUTHOR
======

   Mark Biggar, overloaded interface by Ilya Zakharevich.

Efficient big integer arithmetic (in C)
***************************************

NAME
====

   Math::BigIntFast - Efficient big integer arithmetic (in C)

SYNOPSIS
========

   See `Bit::Vector(3)' in this node and `Bit::Vector::Overload(3)' in
this node.

DESCRIPTION
===========

   See `Bit::Vector(3)' in this node and `Bit::Vector::Overload(3)' in
this node.

SEE ALSO
========

   Bit::Vector(3), Bit::Vector::Overload(3), Set::IntRange(3),
Math::MatrixBool(3), Math::MatrixReal(3), DFA::Kleene(3), Math::Kleene(3),
Graph::Kruskal(3), Math::Pari(3), PDL(3).

VERSION
=======

   This man page documents "Math::BigIntFast" version 6.0.

AUTHOR
======

     Steffen Beyer
     mailto:sb@engelschall.com
     http://www.engelschall.com/u/sb/download/

COPYRIGHT
=========

   Copyright (c) 2000 by Steffen Beyer. All rights reserved.

LICENSE
=======

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself, i.e., under the terms of the
"Artistic License" or the "GNU General Public License".

   The C library at the core of this Perl module can additionally be
redistributed and/or modified under the terms of the "GNU Library General
Public License".

   Please refer to the files "Artistic.txt", "GNU_GPL.txt" and
"GNU_LGPL.txt" in this distribution for details!

DISCLAIMER
==========

   This package 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.

Arbitrary length integer extension module for Perl
**************************************************

NAME
====

   BigInteger - Arbitrary length integer extension module for Perl

SYNOPSIS
========

     use Math::BigInteger;

DESCRIPTION
===========

   The BigInteger extension module gives access to Eric Young's bignum
library.  This provides a faster alternative to the Math::BigInt library.

   The basic object in this library is a BigInteger.  It is used to hold a
single large integer.

   It is not intended that this package be used directly, but instead be
used by a wrapper package, such as the Math::BigInteger class.

FUNCTIONS
=========

   Many of the following functions can be used in two styles, by calling
the function on an object, or by calling the function explicitly; for
example, here are two ways of assigning to $a the sum of $b and $c:

     $a->add($b, $c);
     or

     BigInteger::add($a, $b, $c);

Creation/Destruction routines.
------------------------------

new
          my $bi = new BigInteger;	# Create a new BigInteger object.

clone
          my $b = $a->clone();

     Create a new BigInteger object from another BigInteger object.

copy
          copy($a, $b);

     Copy one BigInteger object to another.

save
          my $data = $bi->save();

     Save a BigInteger object as a MSB-first string.

restore
          my $bi = restore BigInteger $data;

     Create a new BigInteger object from a MSB-first string.

Comparison functions
--------------------

ucmp
          ucmp($a, $b);

     Return -1 if $a is less than $b, 0 if $a and $b are the same and 1 is
     $a is greater than $b.  This is an *unsigned* comparison.

cmp
          cmp($a, $b);

     Return -1 if $a is less than $b, 0 if $a and $b are the same and 1 is
     $a is greater than $b.  This is a *signed* comparison.

Arithmetic Functions
--------------------

inc 	$bi->inc();
     Increment $bi by one:

dec 	$bi->dec();
     Decrement $bi by one:

add
          $r->add($a, $b);

     Add $a and $b and return the result in $r.

mul
          $r->mul($a, $b);

     Multiply $a by $b and return the result in $r.  Note that $r must not
     be the same object as $a or $b.

div
          div($dv, $rem, $m, $d);

     Divide $m by $d and return the result in $dv and the remainder in
     $rem.  Either of $dv or $rem can be undef, in which case that value
     is not returned.

mod
          $rem->mod($m, $d);

     Find the remainder of $m divided by $d and return it in $rem.  This
     function is more efficient than div.

lshift
          $r->lshift($a, $n);

     Shift $a left by $n bits.

lshift1
          $r->lshift1($a);

     Shift $a left by 1 bit.  This form is more efficient than `lshift($r,
     $a, 1)'.

rshift
          $r->rshift($a, $n);

     Shift $a right by $n bits.

rshift1
          $r->rshift1($a);

     Shift $a right by 1 bit.  This form is more efficient than
     `rshift($r, $a, 1)'.

mod_exp
          $r->mod_exp($a, $p, $mod);

     Raise $a to the $p power and return the remainder into $r when
     divided by $m.

modmul_recip
          modmul_recip($r, $x, $y, $m, $i, $nb);

     This function is used to perform an efficient `mod_mul' operation.
     If one is going to repeatedly perform `mod_mul' with the same modulus
     is worth calculating the reciprocal of the modulus and then using this
     function.  This operation uses the fact that a/b == a*r where r is the
     reciprocal of b.  On modern computers multiplication is very fast and
     big number division is very slow.  $x is multiplied by $y and then
     divided by $m and the remainder is returned in $r.  $i is the
     reciprocal of $m and $nb is the number of bits as returned from
     `reciprocal'.  This function is used in mod_exp.

mul_mod
          $r->mul_mod($a, $b, $m);

     Multiply $a by $b and return the remainder into $r when divided by $m.

reciprical
          $r->reciprical($m);

     Return the reciprocal of $m into $r.

Miscellaneous Routines
----------------------

num_bits
          my $size = $bi->numbits();

     Return the size (in bits) of the BigInteger.

gcd
          $r->gcd($a, $b);

     $r has the greatest common divisor of $a and $b.

inverse_modn
          $r->inverse_modn($a, $n);

     This function creates a new BigInteger and returns it in $r.  This
     number is the inverse mod $n of $a.  By this it is meant that the
     returned value $r satisfies (a*r)%n == 1.  This function is used in
     the generation of RSA keys.

BUGS
====

   Negative numbers cannot be saved or restored.  To fix this requires
modification of Eric Young's library.

   The documentation.

COPYRIGHT
=========

   Systemics Ltd ( http://www.systemics.com/ ).

   Portions copyright Eric Young (eay@mincom.oz.au).

SYNOPSIS
========

     use Math::Brent qw(FindMinima BracketMinimum Brent Minimise1D);
     my ($x,$y)=Minimise1D($guess,$scale,\&func,$tol,$itmax);
     my ($ax,$bx,$cx,$fa,$fb,$fc)=BracketMinimum($ax,$bx,$cx,\&func);
     my ($x,$y)=Brent($ax,$bx,$cx,\&func,$tol,$itmax);

DESCRIPTION
===========

   This is an implementation of Brents method for One-Dimensional
minimisation of a function without using derivatives. This algorithm
cleverly uses both the Golden Section Search and parabolic interpolation.

   The main function *Brent*, given a function reference *\&func* and a
bracketing triplet of abcissas *$ax*, *$bx*, *$cx* (such that *$bx* is
between *$ax* and *$cx* and *func($bx)* is less than both *func($ax)* and
*func($cx)*), isolates the minimum to a fractional precision of about
*$tol* using Brents method. A maximum number of iterations *$itmax* may be
specified for this search - it defaults to 100. Returned is an array
consisting of the abcissa of the minum and the function value there.

   The function *BracketMinimum*, given a function *\&func* and distinct
initial points *$ax* and *$bx* searches in the downhill direction (defined
by the function as evaluated at the initial points) and returns an array
of the three points *$ax*, *$bx*, *$cx* which bracket the minimum of the
function and the function values at those points.

   The function *Minimise1D* provides a simple interface to the above two
routines. Given a function *\&func*, an initial guess for its minimum, and
its scaling (*$guess*,$scale) this routine isolates the minimum to a
fractional precision of about *$tol* using Brents method. A maximum number
of iterations *$itmax* may be specified for this search - it defaults to
100. It returns an array consisting of the abcissa of the minum and the
function value there.

EXAMPLE
=======

     use Math::Brent qw(Minimise1D);
     sub func {
       my $x=shift ;
       return $x ? sin($x)/$x: 1;
     }
        my ($x,$y)=Minimise1D(1,1,\&func,1e-7);
        print "Minimum is func($x)=$y\n";

   produces the output

     Minimum is func(5.236068)=-.165388470697432

     =head1 HISTORY

   $Log: Brent.pm,v $ Revision 1.1  1995/12/26 10:06:36  willijar Initial
revision

BUGS
====

   Let me know of any problems.

AUTHOR
======

   John A.R. Williams <J.A.R.Williams@aston.ac.uk>

SEE ALSO
========

   "Numerical Recipies: The Art of Scientific Computing" W.H. Press, B.P.
Flannery, S.A. Teukolsky, W.T. Vetterling.  Cambridge University Press.
ISBN 0 521 30811 9.

Perl extension for calculating EMAs
***********************************

NAME
====

   Math::Business::EMA - Perl extension for calculating EMAs

SYNOPSIS
========

     use Math::Business::EMA;

     my $ema = new Math::Business::EMA;

     set_days $ema 3;

     insert $ema 10;
     insert $ema 13;
     insert $ema 14;

     print "The average so far is: ", $ema->query, ".\n";

AUTHOR
======

   Jettero Heller jettero@cpan.org

   http://www.voltar.org

SEE ALSO
========

   perl(1), Math::Business::EMA(3).

Generate probabilities and quantiles from several  statistical probability functions
************************************************************************************

NAME
====

   Math::CDF - Generate probabilities and quantiles from several
statistical probability functions

SYNOPSIS
========

   use Math::CDF;

   $prob = `&Math::CDF::pnorm(1.96)';

   `if( not defined($z = &Math::CDF::qnorm(0.975)) )' {     die "`qnorm()'
failed"; }

   or

   use Math::CDF `qw(:all)';

   $prob = `pnorm(1.96)';

DESCRIPTION
===========

   This module provides a perl interface to the DCDFLIB. See the section on
`DCDFLIB' in this node for more information.

   Functions are available for 7 continuous distributions (Beta,
Chi-square, F, Gamma, Normal, Poisson and T-distribution) and for two
discrete distributions (Binomial and Negative Binomial). Optional
non-centrality parameters are available for the Chi-square, F and
T-distributions. Cumulative probabilities are available for all 9
distributions and quantile functions are available for the 7 continuous
distributions.

   All cumulative probability function names begin with the character "p".
They give the probability of being less than or equal to the given value
[ `P(X <= x)' ]

   All quantile function names begin with the character q. They give a
value of x such that `P(X <= x)' = p where the value of p is provided to
the function.

   Non-centrality parameters are always the last function argument when
available. You do not need to supply the non-centrality parameter in which
case it will be assumed to be 0.

   All functions will return an undefined value if the function fails
(probably due to parameters being out of allowed range) but will not
otherwise generate an error message. The user should check for valid
output from the Math::CDF functions with the `defined()' function as
demonstrated in the `SYNOPSIS' in this node section.

FUNCTION DESCRIPTIONS
=====================

   In all, 16 functions are available via Math::CDF:

     pbeta(), qbeta()          [Beta Distribution]
     pchisq(), qchisq()        [Chi-square Distribution]
     pf(), qf()                [F Distribution]
     pgamma(), qgamma()        [Gamma Distribution]
     pnorm(), qnorm()          [Standard Normal Dist]
     ppois(), qpois()          [Poisson Distribution]
     pt(), qt()                [T-distribution]
     pbinom()                  [Binomial Distribution]
     pnbinom()                 [Negative Binomial Distribution]

`pbeta($x, $a, $b), qbeta($p, $a, $b)'
     Generates cumulative probabilities and quantiles from the Beta
     distribution.  $x should be in the range of [0,1] and $p should be in
     [0,1].  $a and $b are parameters of the beta distribution.  Both $a
     and $b must be in the range [0,Inf).

`pchisq($x, $df, $ncp), qbeta($p, $df, $ncp)'
     Generates cumulative probabilities and quantiles from the Chi-square
     distribution.  $x should be in the range of [0,Inf) and $p should be
     in [0,1].  $df is the degrees of freedom of the distribution and must
     be in the range (0,Inf).  $ncp is the optional non-centrality
     parameter and must be in the range [0,Inf).  The non-centrality
     parameter need not be specified and the calls `pchisq(5, 5, 0.0)' and
     `pchisq(5, 5)' will return identical values.

`pf($x, $dfn, $dfd, $ncp), qf($p, $dfn, $dfd, $ncp)'
     Generates cumulative probabilities and quantiles from the F
     distribution.  $x should be in the range of [0,Inf) and $p should be
     in [0,1].  $dfn and $dfd are the numerator and denominator degrees of
     freedom, respectively. Both must be in the range (0,Inf).  $ncp is
     the optional non-centrality parameter and must be in the range
     [0,Inf).  The non-centrality parameter need not be specified and the
     calls [CS]<pf(5, 2, 3, 0.0)> and [CS]<pf(5, 2, 3)> will return
     identical values.

`pgamma($x, $shape, $scale), qgamma($p, $shape, $scale)'
     Generates cumulative probabilities and quantiles from the Gamma
     distribution. The gamma density is proportional to [CS]<$x**($shape -
     1) * EXP(- $scale * $x)> $x should be in the range of [0,Inf) and $p
     should be in [0,1].  $shape and $scale are parameters of the Gamma
     distribution and both must be in the range (0,Inf).

`pnorm($x), qnorm($p)'
     Generates cumulative probabilities and quantiles from the standard
     Normal distribution.  $x should be in the range of (-Inf,Inf) and $p
     should be in [0,1].

`ppois($x, $lambda), qpois($p, $lambda)'
     Generates cumulative probabilities and quantiles from the Poisson
     distribution.  $x should be in the range of [0,Inf) and $p should be
     in [0,1].  $lambda is the parameter of the Poisson distribution and
     must be in the range [0,Inf).

`pt($x, $df, $ncp), qt($p, $df, $ncp)'
     Generates cumulative probabilities and quantiles from the T
     distribution.  $x should be in the range of (-Inf,Inf) and $p should
     be in [0,1].  $df is the degree of freedom of the distribution and
     must be in the range (0,Inf).  $ncp is the optional non-centrality
     parameter and must be in the range (-Inf,Inf).  The non-centrality
     parameter need not be specified and the calls [CS]<pt(0, 3, 0.0)> and
     [CS]<pt(0, 3)> will return identical values.

`pbinom($x, $n, $p)'
     Generates cumulative probabilities from the Binomial distribution.
     This is the probability of having $x or fewer successes in $n trials
     when each trial has a $p probability of success.  $x should be in the
     range of [0,$n], $n should be in the range (0,Inf) and $p should be
     in [0,1].

`pnbinom($x, $n, $p)'
     Generates cumulative probabilities from the Negative Binomial
     distribution.  The is the probability of having $x or fewer failures
     before the $n'th success when each trial has a $p probability of
     success.  $x should be in the range of [0,Inf), $n should be in the
     range (0,Inf) and $p should be in [0,1].

DCDFLIB
=======

   DCDFLIB is a library of C routines for cumulative distribution
functions, inverses, and other parameters written by Barry W. Brown, James
Lovato and Kathy Russell of the Department of Biomathematics at The
University of Texas M.D. Anderson Cancer Center in Houston Texas.

   Version 1.1 of DCDFLIB is included with this distribution and can be
downloaded via ftp from odin.mda.uth.tmc.edu as
/pub/src/dcdflib.c-1.1.tar.gz.  The library is also available in Fortran
source.

   Documentation for DCDFLIB is found in the cdflib/doc/ directory of the
source distribution of Math::CDF

   DCDFLIB has been put in the public domain. However, some of the
Algorithms are from the ACM publication and is under their copyright.
Generally this means that those algorithms can be distributed and used
freely for non-commercial purposes. See the file cdflib/doc/README in the
source distribution of Math::CDF for more information.

AUTHOR
======

   * Math::CDF was put together by Ed Callahan, callahan@envstat.com

     Environmental Statistics PO Box 563 Fountain City, WI  54629

   * DCDFLIB was written by Barry W. Brown (bwb@odin.mdacc.tmc.edu), James
     Lovato and Kathy Russell

     Department of Biomathematics, Box 237 The University of Texas, M.D.
     Anderson Cancer Center 1515 Holcombe Boulevard Houston, TX  77030

SEE ALSO
========

   See Math/Random, `Statistics::ChiSquare' in this node,
see Statistics/OLS,

perl interface to the cephes math library
*****************************************

NAME
====

   Math::Cephes - perl interface to the cephes math library

SYNOPSIS
========

     use Math::Cephes qw(:all);

DESCRIPTION
===========

     This module provides an interface to over 150 functions of the
     cephes math library of Stephen Moshier. No functions are exported
     by default, but rather must be imported explicitly, as in

     use Math::Cephes qw(sin cos);

     There are a number of export tags defined which allow
     importing groups of functions:

use Math::Cephes qw(:constants);
          imports the variables

          $PI      :   3.14159265358979323846      #  pi
          $PIO2    :   1.57079632679489661923      #  pi/2
          $PIO4    :   0.785398163397448309616     #  pi/4
          $SQRT2   :   1.41421356237309504880      #  sqrt(2)
          $SQRTH   :   0.707106781186547524401     #  sqrt(2)/2
          $LOG2E   :   1.4426950408889634073599    #  1/log(2)
          $SQ2OPI  :   0.79788456080286535587989   #  sqrt( 2/pi )
          $LOGE2   :   0.693147180559945309417     #  log(2)
          $LOGSQ2  :   0.346573590279972654709     #  log(2)/2
          $THPIO4  :   2.35619449019234492885      #  3*pi/4
          $TWOOPI  :   0.636619772367581343075535  #  2/pi

          As well, there are 4 machine-specific numbers available:

          $MACHEP : machine roundoff error
          $MAXLOG : maximum log on the machine
          $MINLOG : minimum log on the machine
          $MAXNUM : largest number represented

use Math::Cephes qw(:trigs);
          imports

          acos:  Inverse circular cosine
          asin:  Inverse circular sine
          atan:  Inverse circular tangent (arctangent)
          atan2:  Quadrant correct inverse circular tangent
          cos:  Circular cosine
          cosdg:  Circular cosine of angle in degrees
          cot:  Circular cotangent
          cotdg:  Circular cotangent of argument in degrees
          hypot: hypotenuse associated with the sides of a right triangle
          radian: Degrees, minutes, seconds to radians
          sin:  Circular sine
          sindg:  Circular sine of angle in degrees
          tan:  Circular tangent
          tandg:  Circular tangent of argument in degrees
          cosm1:  Relative error approximations for function arguments near unity

use Math::Cephes qw(:hypers);
          imports

          acosh:  Inverse hyperbolic cosine
          asinh:  Inverse hyperbolic sine
          atanh:  Inverse hyperbolic tangent
          cosh:  Hyperbolic cosine
          sinh:  Hyperbolic sine
          tanh:  Hyperbolic tangent

use Math::Cephes qw(:explog);
          imports

          exp:  Exponential function
          exp10:  Base 10 exponential function (Common antilogarithm)
          exp2:  Base 2 exponential function
          log:  Natural logarithm
          log10:  Common logarithm
          log2:  Base 2 logarithm
          log1p,expm1:  Relative error approximations for function arguments near unity.

use Math::Cephes qw(:cmplx);
          imports

          new_cmplx: create a new complex number object
          cabs:  Complex absolute value
          cacos:  Complex circular arc cosine
          cacosh: Complex inverse hyperbolic cosine
          casin:  Complex circular arc sine
          casinh: Complex inverse hyperbolic sine
          catan:  Complex circular arc tangent
          catanh: Complex inverse hyperbolic tangent
          ccos:  Complex circular cosine
          ccosh: Complex hyperbolic cosine
          ccot:  Complex circular cotangent
          cexp:  Complex exponential function
          clog:  Complex natural logarithm
          cadd: add two complex numbers
          csub: subtract two complex numbers
          cmul: multiply two complex numbers
          cdiv: divide two complex numbers
          cmov: copy one complex number to another
          cneg: negate a complex number
          cpow: Complex power function
          csin:  Complex circular sine
          csinh: Complex hyperbolic sine
          csqrt:  Complex square root
          ctan:  Complex circular tangent
          ctanh: Complex hyperbolic tangent

use Math::Cephes qw(:utils);
          imports

          cbrt:  Cube root
          ceil:  ceil
          drand:  Pseudorandom number generator
          fabs:  Absolute value
          fac:  Factorial function
          floor:  floor
          frexp:  frexp
          ldexp:  multiplies x by 2**n.
          lrand:  Pseudorandom number generator
          lsqrt:  Integer square root
          pow:  Power function
          powi:  Real raised to integer power
          round:  Round double to nearest or even integer valued double
          sqrt:  Square root

use Math::Cephes qw(:bessels);
          imports

          i0:  Modified Bessel function of order zero
          i0e:  Modified Bessel function of order zero, exponentially scaled
          i1:  Modified Bessel function of order one
          i1e:  Modified Bessel function of order one, exponentially scaled
          iv:  Modified Bessel function of noninteger order
          j0:  Bessel function of order zero
          j1:  Bessel function of order one
          jn:  Bessel function of integer order
          jv:  Bessel function of noninteger order
          k0:  Modified Bessel function, third kind, order zero
          k0e:  Modified Bessel function, third kind, order zero, exponentially scaled
          k1:  Modified Bessel function, third kind, order one
          k1e:  Modified Bessel function, third kind, order one, exponentially scaled
          kn:  Modified Bessel function, third kind, integer order
          y0:  Bessel function of the second kind, order zero
          y1:  Bessel function of second kind of order one
          yn:  Bessel function of second kind of integer order
          yv:  Bessel function Yv with noninteger v

use Math::Cephes qw(:dists);
          imports

          bdtr:  Binomial distribution
          bdtrc:  Complemented binomial distribution
          bdtri:  Inverse binomial distribution
          btdtr:  Beta distribution
          chdtr:  Chi-square distribution
          chdtrc:  Complemented Chi-square distribution
          chdtri:  Inverse of complemented Chi-square distribution
          fdtr:  F distribution
          fdtrc:  Complemented F distribution
          fdtri:  Inverse of complemented F distribution
          gdtr:  Gamma distribution function
          gdtrc:  Complemented gamma distribution function
          nbdtr:  Negative binomial distribution
          nbdtrc:  Complemented negative binomial distribution
          nbdtri:  Functional inverse of negative binomial distribution
          ndtr:  Normal distribution function
          ndtri:  Inverse of Normal distribution function
          pdtr:  Poisson distribution
          pdtrc:  Complemented poisson distribution
          pdtri:  Inverse Poisson distribution
          stdtr:  Student's t distribution
          stdtri:  Functional inverse of Student's t distribution

use Math::Cephes qw(:gammas);
          imports

          fac:  Factorial function
          gamma:  Gamma function
          igam:  Incomplete gamma integral
          igamc:  Complemented incomplete gamma integral
          igami:  Inverse of complemented imcomplete gamma integral
          psi:  Psi (digamma) function
          rgamma:  Reciprocal gamma function

use Math::Cephes qw(:betas);
          imports

          beta:  Beta function
          incbet:  Incomplete beta integral
          incbi:  Inverse of imcomplete beta integral
          lbeta:  Natural logarithm of |beta|

use Math::Cephes qw(:elliptics);
          imports

          ellie:  Incomplete elliptic integral of the second kind
          ellik:  Incomplete elliptic integral of the first kind
          ellpe:  Complete elliptic integral of the second kind
          ellpj:  Jacobian Elliptic Functions
          ellpk:  Complete elliptic integral of the first kind

use Math::Cephes qw(:hypergeometrics);
          imports

          hyp2f0:  Gauss hypergeometric function   F
          hyp2f1:  Gauss hypergeometric function   F
          hyperg:  Confluent hypergeometric function
          onef2:  Hypergeometric function 1F2
          threef0:  Hypergeometric function 3F0

use Math::Cephes qw(:misc);
          imports

          airy:  Airy function
          dawsn:  Dawson's Integral
          ei: Exponential integral
          erf:  Error function
          erfc:  Complementary error function
          expn:  Exponential integral En
          fresnl:  Fresnel integral
          shichi:  Hyperbolic sine and cosine integrals
          sici:  Sine and cosine integrals
          spence:  Dilogarithm
          struve:  Struve function
          zeta:  Riemann zeta function of two arguments
          zetac:  Riemann zeta function

use Math::Cephes qw(:fract);
          imports

          new_fract: create a new fraction object
          radd: add two fractions
          rmul: multiply two fractions
          rsub: subtracttwo fractions
          rdiv: divide two fractions
          euclid: finds the greatest common divisor

FUNCTIONS
=========

     A description of the various functions available follows.

acosh: Inverse hyperbolic cosine
          SYNOPSIS:

          # double x, y, acosh();

          $y = acosh( $x );

          DESCRIPTION:

          Returns inverse hyperbolic cosine of argument.

          If 1 <= x < 1.5, a rational approximation

          sqrt(z) * P(z)/Q(z)

          where z = x-1, is used.  Otherwise,

          acosh(x)  =  log( x + sqrt( (x-1)(x+1) ).

          ACCURACY:
                               Relative error:
          arithmetic   domain     # trials      peak         rms
             DEC       1,3         30000       4.2e-17     1.1e-17
             IEEE      1,3         30000       4.6e-16     8.7e-17

          ERROR MESSAGES:

          message         condition      value returned
           acosh domain       |x| < 1            NAN

*airy*: Airy function
          SYNOPSIS:

          # double x, ai, aiprime, bi, biprime;
          # int airy();

          ($flag, $ai, $aiprime, $bi, $biprime) = airy( $x );

          DESCRIPTION:

          Solution of the differential equation

          y"(x) = xy.

          The function returns the two independent solutions Ai, Bi
          and their first derivatives Ai'(x), Bi'(x).

          Evaluation is by power series summation for small x,
          by rational minimax approximations for large x.

          ACCURACY:
          Error criterion is absolute when function <= 1, relative
          when function > 1, except * denotes relative error criterion.
          For large negative x, the absolute error increases as x^1.5.
          For large positive x, the relative error increases as x^1.5.

          Arithmetic  domain   function  # trials      peak         rms
          IEEE        -10, 0     Ai        10000       1.6e-15     2.7e-16
          IEEE          0, 10    Ai        10000       2.3e-14*    1.8e-15*
          IEEE        -10, 0     Ai'       10000       4.6e-15     7.6e-16
          IEEE          0, 10    Ai'       10000       1.8e-14*    1.5e-15*
          IEEE        -10, 10    Bi        30000       4.2e-15     5.3e-16
          IEEE        -10, 10    Bi'       30000       4.9e-15     7.3e-16
          DEC         -10, 0     Ai         5000       1.7e-16     2.8e-17
          DEC           0, 10    Ai         5000       2.1e-15*    1.7e-16*
          DEC         -10, 0     Ai'        5000       4.7e-16     7.8e-17
          DEC           0, 10    Ai'       12000       1.8e-15*    1.5e-16*
          DEC         -10, 10    Bi        10000       5.5e-16     6.8e-17
          DEC         -10, 10    Bi'        7000       5.3e-16     8.7e-17

*radian*: Degrees, minutes, seconds to radians
          SYNOPSIS:

          # double d, m, s, radian();

          $r = radian( $d, $m, $s );

          DESCRIPTION:

          Converts an angle of degrees, minutes, seconds to radians.

*hypot*: returns the hypotenuse associated with the sides of a right triangle
          SYNOPSIS:

          # double a, b, c, hypot();

          $c = hypot( $a, $b );

          DESCRIPTION:

          Calculates the hypotenuse associated with the sides of a
          right triangle, according to

          c = sqrt( a**2 + b**2)

asin: Inverse circular sine
          SYNOPSIS:

          # double x, y, asin();

          $y = asin( $x );

          DESCRIPTION:

          Returns radian angle between -pi/2 and +pi/2 whose sine is x.

          A rational function of the form x + x**3 P(x**2)/Q(x**2)
          is used for |x| in the interval [0, 0.5].  If |x| > 0.5 it is
          transformed by the identity

          asin(x) = pi/2 - 2 asin( sqrt( (1-x)/2 ) ).

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC      -1, 1        40000       2.6e-17     7.1e-18
              IEEE     -1, 1        10^6        1.9e-16     5.4e-17

          ERROR MESSAGES:

          message         condition      value returned
           asin domain        |x| > 1           NAN

acos: Inverse circular cosine
          SYNOPSIS:

          # double x, y, acos();

          $y = acos( $x );

          DESCRIPTION:

          Returns radian angle between 0 and pi whose cosine
          is x.

          Analytically, acos(x) = pi/2 - asin(x).  However if |x| is
          near 1, there is cancellation error in subtracting asin(x)
          from pi/2.  Hence if x < -0.5,

          acos(x) =	 pi - 2.0 * asin( sqrt((1+x)/2) );

          or if x > +0.5,

          acos(x) =	 2.0 * asin(  sqrt((1-x)/2) ).

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       -1, 1       50000       3.3e-17     8.2e-18
              IEEE      -1, 1       10^6        2.2e-16     6.5e-17

          ERROR MESSAGES:

          message         condition      value returned
           asin domain        |x| > 1           NAN

asinh: Inverse hyperbolic sine
          SYNOPSIS:

          # double x, y, asinh();

          $y = asinh( $x );

          DESCRIPTION:

          Returns inverse hyperbolic sine of argument.

          If |x| < 0.5, the function is approximated by a rational
          form  x + x**3 P(x)/Q(x).  Otherwise,

          asinh(x) = log( x + sqrt(1 + x*x) ).

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC      -3,3         75000       4.6e-17     1.1e-17
              IEEE     -1,1         30000       3.7e-16     7.8e-17
              IEEE      1,3         30000       2.5e-16     6.7e-17

atan: Inverse circular tangent (arctangent)
          SYNOPSIS:

          # double x, y, atan();

          $y = atan( $x );

          DESCRIPTION:

          Returns radian angle between -pi/2 and +pi/2 whose tangent
          is x.

          Range reduction is from three intervals into the interval
          from zero to 0.66.  The approximant uses a rational
          function of degree 4/5 of the form x + x**3 P(x)/Q(x).

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       -10, 10     50000       2.4e-17     8.3e-18
              IEEE      -10, 10      10^6       1.8e-16     5.0e-17

atan2: Quadrant correct inverse circular tangent
          SYNOPSIS:

          # double x, y, z, atan2();

          $z = atan2( $y, $x );

          DESCRIPTION:

          Returns radian angle whose tangent is y/x.
          Define compile time symbol ANSIC = 1 for ANSI standard,
          range -PI < z <= +PI, args (y,x); else ANSIC = 0 for range
          0 to 2PI, args (x,y).

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              IEEE      -10, 10      10^6       2.5e-16     6.9e-17
           See atan.c.

atanh: Inverse hyperbolic tangent
          SYNOPSIS:

          # double x, y, atanh();

          $y = atanh( $x );

          DESCRIPTION:

          Returns inverse hyperbolic tangent of argument in the range
          MINLOG to MAXLOG.

          If |x| < 0.5, the rational form x + x**3 P(x)/Q(x) is
          employed.  Otherwise,
                 atanh(x) = 0.5 * log( (1+x)/(1-x) ).

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       -1,1        50000       2.4e-17     6.4e-18
              IEEE      -1,1        30000       1.9e-16     5.2e-17

*bdtr*: Binomial distribution
          SYNOPSIS:

          # int k, n;
          # double p, y, bdtr();

          $y = bdtr( $k, $n, $p );

          DESCRIPTION:

          Returns the sum of the terms 0 through k of the Binomial
          probability density:

          k
          --  ( n )   j      n-j
          >   (   )  p  (1-p)
          --  ( j )
            j=0

          The terms are not summed directly; instead the incomplete
          beta integral is employed, according to the formula

          y = bdtr( k, n, p ) = incbet( n-k, k+1, 1-p ).

          The arguments must be positive, with p ranging from 0 to 1.

          ACCURACY:

          Tested at random points (a,b,p), with p between 0 and 1.

          a,b                     Relative error:
           arithmetic  domain     # trials      peak         rms
            For p between 0.001 and 1:
              IEEE     0,100       100000      4.3e-15     2.6e-16
           See also incbet.c.

          ERROR MESSAGES:

          message         condition      value returned
           bdtr domain         k < 0            0.0
                            n < k
                            x < 0, x > 1

*bdtrc*: Complemented binomial distribution
          SYNOPSIS:

          # int k, n;
          # double p, y, bdtrc();

          $y = bdtrc( $k, $n, $p );

          DESCRIPTION:

          Returns the sum of the terms k+1 through n of the Binomial
          probability density:

          n
          --  ( n )   j      n-j
          >   (   )  p  (1-p)
          --  ( j )
            j=k+1

          The terms are not summed directly; instead the incomplete
          beta integral is employed, according to the formula

          y = bdtrc( k, n, p ) = incbet( k+1, n-k, p ).

          The arguments must be positive, with p ranging from 0 to 1.

          ACCURACY:

          Tested at random points (a,b,p).

          a,b                     Relative error:
           arithmetic  domain     # trials      peak         rms
            For p between 0.001 and 1:
              IEEE     0,100       100000      6.7e-15     8.2e-16
            For p between 0 and .001:
              IEEE     0,100       100000      1.5e-13     2.7e-15

          ERROR MESSAGES:

          message         condition      value returned
           bdtrc domain      x<0, x>1, n<k       0.0

*bdtri*: Inverse binomial distribution
          SYNOPSIS:

          # int k, n;
          # double p, y, bdtri();

          $p = bdtr( $k, $n, $y );

          DESCRIPTION:

          Finds the event probability p such that the sum of the
          terms 0 through k of the Binomial probability density
          is equal to the given cumulative probability y.

          This is accomplished using the inverse beta integral
          function and the relation

          1 - p = incbi( n-k, k+1, y ).

          ACCURACY:

          Tested at random points (a,b,p).

          a,b                     Relative error:
           arithmetic  domain     # trials      peak         rms
            For p between 0.001 and 1:
              IEEE     0,100       100000      2.3e-14     6.4e-16
              IEEE     0,10000     100000      6.6e-12     1.2e-13
            For p between 10^-6 and 0.001:
              IEEE     0,100       100000      2.0e-12     1.3e-14
              IEEE     0,10000     100000      1.5e-12     3.2e-14
           See also incbi.c.

          ERROR MESSAGES:

          message         condition      value returned
           bdtri domain     k < 0, n <= k         0.0
                         x < 0, x > 1

*beta*: Beta function
          SYNOPSIS:

          # double a, b, y, beta();

          $y = beta( $a, $b );

          DESCRIPTION:

          -     -
                            | (a) | (b)
           beta( a, b )  =  -----------.
            -
           | (a+b)

          For large arguments the logarithm of the function is
          evaluated using lgam(), then exponentiated.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC        0,30        1700       7.7e-15     1.5e-15
              IEEE       0,30       30000       8.1e-14     1.1e-14

          ERROR MESSAGES:

          message         condition          value returned
           beta overflow    log(beta) > MAXLOG       0.0
                         a or b <0 integer        0.0

*lbeta*: Natural logarithm of |beta|
          SYNOPSIS:

          # double a, b;

          # double lbeta( a, b );

          $y = lbeta( $a, $b);

*btdtr*: Beta distribution
          SYNOPSIS:

          # double a, b, x, y, btdtr();

          $y = btdtr( $a, $b, $x );

          DESCRIPTION:

          Returns the area from zero to x under the beta density
          function:

          x
                      -             -
                     | (a+b)       | |  a-1      b-1
           P(x)  =  ----------     |   t    (1-t)    dt
                     -     -     | |
                    | (a) | (b)   -
                                   0

          This function is identical to the incomplete beta
          integral function incbet(a, b, x).

          The complemented function is

          1 - P(1-x)  =  incbet( b, a, x );

          ACCURACY:

          See incbet.c.

*cbrt*: Cube root
          SYNOPSIS:

          # double x, y, cbrt();

          $y = cbrt( $x );

          DESCRIPTION:

          Returns the cube root of the argument, which may be negative.

          Range reduction involves determining the power of 2 of
          the argument.  A polynomial of degree 2 applied to the
          mantissa, and multiplication by the cube root of 1, 2, or 4
          approximates the root to within about 0.1%.  Then Newton's
          iteration is used three times to converge to an accurate
          result.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC        -10,10     200000      1.8e-17     6.2e-18
              IEEE       0,1e308     30000      1.5e-16     5.0e-17

*chdtr*: Chi-square distribution
          SYNOPSIS:

          # double v, x, y, chdtr();

          $y = chdtr( $v, $x );

          DESCRIPTION:

          Returns the area under the left hand tail (from 0 to x)
          of the Chi square probability density function with
          v degrees of freedom.

          inf.
            -
                                  1          | |  v/2-1  -t/2
            P( x | v )   =   -----------     |   t      e     dt
                              v/2  -       | |
                             2    | (v/2)   -
           x

          where x is the Chi-square variable.

          The incomplete gamma integral is used, according to the
          formula

          y = chdtr( v, x ) = igam( v/2.0, x/2.0 ).

          The arguments must both be positive.

          ACCURACY:

          See igam().

          ERROR MESSAGES:

          message         condition      value returned
           chdtr domain   x < 0 or v < 1        0.0

*chdtrc*: Complemented Chi-square distribution
          SYNOPSIS:

          # double v, x, y, chdtrc();

          $y = chdtrc( $v, $x );

          DESCRIPTION:

          Returns the area under the right hand tail (from x to
          infinity) of the Chi square probability density function
          with v degrees of freedom:

          inf.
            -
                                  1          | |  v/2-1  -t/2
            P( x | v )   =   -----------     |   t      e     dt
                              v/2  -       | |
                             2    | (v/2)   -
           x

          where x is the Chi-square variable.

          The incomplete gamma integral is used, according to the
          formula

          y = chdtrc( v, x ) = igamc( v/2.0, x/2.0 ).

          The arguments must both be positive.

          ACCURACY:

          See igamc().

          ERROR MESSAGES:

          message         condition      value returned
           chdtrc domain  x < 0 or v < 1        0.0

*chdtri*: Inverse of complemented Chi-square distribution
          SYNOPSIS:

          # double df, x, y, chdtri();

          $x = chdtri( $df, $y );

          DESCRIPTION:

          Finds the Chi-square argument x such that the integral
          from x to infinity of the Chi-square density is equal
          to the given cumulative probability y.

          This is accomplished using the inverse gamma integral
          function and the relation

          x/2 = igami( df/2, y );

          ACCURACY:

          See igami.c.

          ERROR MESSAGES:

          message         condition      value returned
           chdtri domain   y < 0 or y > 1        0.0
                            v < 1

*clog*: Complex natural logarithm
          SYNOPSIS:

          # void clog();
          # cmplx z, w;

          $z = new_cmplx(2, 3);    # $z = 2 + 3 i
          $w = new_cmplx();
          clog($z, $w );
          print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w

          DESCRIPTION:

          Returns complex logarithm to the base e (2.718...) of
          the complex argument x.

          If z = x + iy, r = sqrt( x**2 + y**2 ),
          then
                w = log(r) + i arctan(y/x).

          The arctangent ranges from -PI to +PI.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       -10,+10      7000       8.5e-17     1.9e-17
              IEEE      -10,+10     30000       5.0e-15     1.1e-16

          Larger relative error can be observed for z near 1 +i0.
          In IEEE arithmetic the peak absolute error is 5.2e-16, rms
          absolute error 1.0e-16.

*cexp*: Complex exponential function
          SYNOPSIS:

          # void cexp();
          # cmplx z, w;

          $z = new_cmplx(2, 3);    # $z = 2 + 3 i
          $w = new_cmplx();
          cexp($z, $w );
          print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w

          DESCRIPTION:

          Returns the exponential of the complex argument z
          into the complex result w.

          If
              z = x + iy,
              r = exp(x),

          then

          w = r cos y + i r sin y.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       -10,+10      8700       3.7e-17     1.1e-17
              IEEE      -10,+10     30000       3.0e-16     8.7e-17

*csin*: Complex circular sine
          SYNOPSIS:

          # void csin();
          # cmplx z, w;

          $z = new_cmplx(2, 3);    # $z = 2 + 3 i
          $w = new_cmplx();
          csin($z, $w );
          print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w

          DESCRIPTION:

          If
              z = x + iy,

          then

          w = sin x  cosh y  +  i cos x sinh y.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       -10,+10      8400       5.3e-17     1.3e-17
              IEEE      -10,+10     30000       3.8e-16     1.0e-16
           Also tested by csin(casin(z)) = z.

*ccos*: Complex circular cosine
          SYNOPSIS:

          # void ccos();
          # cmplx z, w;

          $z = new_cmplx(2, 3);    # $z = 2 + 3 i
          $w = new_cmplx();
          ccos($z, $w );
          print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w

          DESCRIPTION:

          If
              z = x + iy,

          then

          w = cos x  cosh y  -  i sin x sinh y.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       -10,+10      8400       4.5e-17     1.3e-17
              IEEE      -10,+10     30000       3.8e-16     1.0e-16

*ctan*: Complex circular tangent
          SYNOPSIS:

          # void ctan();
          # cmplx z, w;

          $z = new_cmplx(2, 3);    # $z = 2 + 3 i
          $w = new_cmplx();
          ctan($z, $w );
          print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w

          DESCRIPTION:

          If
              z = x + iy,

          then

          sin 2x  +  i sinh 2y
               w  =  --------------------.
           cos 2x  +  cosh 2y

          On the real axis the denominator is zero at odd multiples
          of PI/2.  The denominator is evaluated by its Taylor
          series near these points.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       -10,+10      5200       7.1e-17     1.6e-17
              IEEE      -10,+10     30000       7.2e-16     1.2e-16
           Also tested by ctan * ccot = 1 and catan(ctan(z))  =  z.

*ccot*: Complex circular cotangent
          SYNOPSIS:

          # void ccot();
          # cmplx z, w;

          $z = new_cmplx(2, 3);    # $z = 2 + 3 i
          $w = new_cmplx();
          ccot($z, $w );
          print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w

          DESCRIPTION:

          If
              z = x + iy,

          then

          sin 2x  -  i sinh 2y
               w  =  --------------------.
           cosh 2y  -  cos 2x

          On the real axis, the denominator has zeros at even
          multiples of PI/2.  Near these points it is evaluated
          by a Taylor series.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       -10,+10      3000       6.5e-17     1.6e-17
              IEEE      -10,+10     30000       9.2e-16     1.2e-16
           Also tested by ctan * ccot = 1 + i0.

*casin*: Complex circular arc sine
          SYNOPSIS:

          # void casin();
          # cmplx z, w;

          $z = new_cmplx(2, 3);    # $z = 2 + 3 i
          $w = new_cmplx();
          casin($z, $w );
          print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w

          DESCRIPTION:

          Inverse complex sine:

          2
           w = -i clog( iz + csqrt( 1 - z ) ).

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       -10,+10     10100       2.1e-15     3.4e-16
              IEEE      -10,+10     30000       2.2e-14     2.7e-15
           Larger relative error can be observed for z near zero.
           Also tested by csin(casin(z)) = z.

*cacos*: Complex circular arc cosine
          SYNOPSIS:

          # void cacos();
          # cmplx z, w;

          $z = new_cmplx(2, 3);    # $z = 2 + 3 i
          $w = new_cmplx();
          cacos($z, $w );
          print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w

          DESCRIPTION:

          w = arccos z  =  PI/2 - arcsin z.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       -10,+10      5200      1.6e-15      2.8e-16
              IEEE      -10,+10     30000      1.8e-14      2.2e-15

*catan*: Complex circular arc tangent
          SYNOPSIS:

          # void catan();
          # cmplx z, w;

          $z = new_cmplx(2, 3);    # $z = 2 + 3 i
          $w = new_cmplx();
          catan($z, $w );
          print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w

          DESCRIPTION:

          If
              z = x + iy,

          then
                   1       (    2x     )
          Re w  =  - arctan(-----------)  +  k PI
                   2       (     2    2)
                           (1 - x  - y )

          ( 2         2)
                    1    (x  +  (y+1) )
           Im w  =  - log(------------)
                    4    ( 2         2)
          (x  +  (y-1) )

          Where k is an arbitrary integer.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       -10,+10      5900       1.3e-16     7.8e-18
              IEEE      -10,+10     30000       2.3e-15     8.5e-17
           The check catan( ctan(z) )  =  z, with |x| and |y| < PI/2,
           had peak relative error 1.5e-16, rms relative error
           2.9e-17.  See also clog().

*csinh*: Complex hyperbolic sine
          SYNOPSIS:

          # void csinh();
          # cmplx z, w;

           $z = new_cmplx(2, 3);    # $z = 2 + 3 i
           $w = new_cmplx();
           csinh($z, $w );
           print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w

          DESCRIPTION:

          csinh z = (cexp(z) - cexp(-z))/2
                  = sinh x * cos y  +  i cosh x * sin y .

          ACCURACY:

                               Relative error:
          arithmetic   domain     # trials      peak         rms
             IEEE      -10,+10     30000       3.1e-16     8.2e-17

*casinh*: Complex inverse hyperbolic sine
          SYNOPSIS:

          # void casinh();
          # cmplx z, w;

           $z = new_cmplx(2, 3);    # $z = 2 + 3 i
           $w = new_cmplx();
           casinh($z, $w );
           print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w
           print_new_cmplx($w);                 # prints $w as Re($w) + i Im($w)

          DESCRIPTION:

          casinh z = -i casin iz .

          ACCURACY:

                               Relative error:
          arithmetic   domain     # trials      peak         rms
             IEEE      -10,+10     30000       1.8e-14     2.6e-15

*ccosh*: Complex hyperbolic cosine
          SYNOPSIS:

          # void ccosh();
          # cmplx z, w;

           $z = new_cmplx(2, 3);    # $z = 2 + 3 i
           $w = new_cmplx();
           ccosh($z, $w );
           print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w

          DESCRIPTION:

          ccosh(z) = cosh x  cos y + i sinh x sin y .

          ACCURACY:

                               Relative error:
          arithmetic   domain     # trials      peak         rms
             IEEE      -10,+10     30000       2.9e-16     8.1e-17

*cacosh*: Complex inverse hyperbolic cosine
          SYNOPSIS:

          # void cacosh();
          # cmplx z, w;

           $z = new_cmplx(2, 3);    # $z = 2 + 3 i
           $w = new_cmplx();
           cacosh($z, $w );
           print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w

          DESCRIPTION:

          acosh z = i acos z .

          ACCURACY:

                               Relative error:
          arithmetic   domain     # trials      peak         rms
             IEEE      -10,+10     30000       1.6e-14     2.1e-15

*ctanh*: Complex hyperbolic tangent
          SYNOPSIS:

          # void ctanh();
          # cmplx z, w;

          $z = new_cmplx(2, 3);    # $z = 2 + 3 i
          $w = new_cmplx();
          ctanh($z, $w );
          print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w

          DESCRIPTION:

          tanh z = (sinh 2x  +  i sin 2y) / (cosh 2x + cos 2y) .

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              IEEE      -10,+10     30000       1.7e-14     2.4e-16

*catanh*: Complex inverse hyperbolic tangent     SYNOPSIS:     # void catanh();   # cmplx z, w;    $z = new_cmplx(2, 3);    # $z = 2 + 3 i  $w = new_cmplx();  catanh($z, $w );  print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w       DESCRIPTION:     Inverse tanh, equal to  -i catan (iz);     ACCURACY:                          Relative error:   arithmetic   domain     # trials      peak         rms      IEEE      -10,+10     30000       2.3e-16     6.2e-17
*cpow*: Complex power function
          SYNOPSIS:

          # void cpow();
          # cmplx a, z, w;

           $a = new_cmplx(5, 6);    # $z = 5 + 6 i
           $z = new_cmplx(2, 3);    # $z = 2 + 3 i
           $w = new_cmplx();
           cpow($a, $z, $w );
           print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w

          DESCRIPTION:

          Raises complex A to the complex Zth power.
          Definition is per AMS55 # 4.2.8,
          analytically equivalent to cpow(a,z) = cexp(z clog(a)).

          ACCURACY:

                               Relative error:
          arithmetic   domain     # trials      peak         rms
             IEEE      -10,+10     30000       9.4e-15     1.5e-15

*cmplx*: Complex number arithmetic
          SYNOPSIS:

          # typedef struct {
          #     double r;     real part
          #     double i;     imaginary part
          #    }cmplx;

          # cmplx *a, *b, *c;

          $a = new_cmplx(3, 5);   # $a = 3 + 5 i
          $b = new_cmplx(2, 3);   # $b = 2 + 3 i
          $c = new_cmplx();

          cadd( $a, $b, $c );  #   c = b + a
          csub( $a, $b, $c );  #   c = b - a
          cmul( $a, $b, $c );  #   c = b * a
          cdiv( $a, $b, $c );  #   c = b / a
          cneg( $c );          #   c = -c
          cmov( $b, $c );      #   c = b

          print $c->{r}, '  ', $c->{i};   # prints real and imaginary parts of $c

          DESCRIPTION:

          Addition:
             c.r  =  b.r + a.r
             c.i  =  b.i + a.i

          Subtraction:
             c.r  =  b.r - a.r
             c.i  =  b.i - a.i

          Multiplication:
             c.r  =  b.r * a.r  -  b.i * a.i
             c.i  =  b.r * a.i  +  b.i * a.r

          Division:
             d    =  a.r * a.r  +  a.i * a.i
             c.r  = (b.r * a.r  + b.i * a.i)/d
             c.i  = (b.i * a.r  -  b.r * a.i)/d
          ACCURACY:

          In DEC arithmetic, the test (1/z) * z = 1 had peak relative
          error 3.1e-17, rms 1.2e-17.  The test (y/z) * (z/y) = 1 had
          peak relative error 8.3e-17, rms 2.1e-17.

          Tests in the rectangle {-10,+10}:
                               Relative error:
          arithmetic   function  # trials      peak         rms
             DEC        cadd       10000       1.4e-17     3.4e-18
             IEEE       cadd      100000       1.1e-16     2.7e-17
             DEC        csub       10000       1.4e-17     4.5e-18
             IEEE       csub      100000       1.1e-16     3.4e-17
             DEC        cmul        3000       2.3e-17     8.7e-18
             IEEE       cmul      100000       2.1e-16     6.9e-17
             DEC        cdiv       18000       4.9e-17     1.3e-17
             IEEE       cdiv      100000       3.7e-16     1.1e-16

*cabs*: Complex absolute value
          SYNOPSIS:

          # double a, cabs();
          # cmplx z;

          $z = new_cmplx(2, 3);    # $z = 2 + 3 i
          $a = cabs( $z );

          DESCRIPTION:

          If z = x + iy

          then

          a = sqrt( x**2 + y**2 ).

           Overflow and underflow are avoided by testing the magnitudes
           of x and y before squaring.  If either is outside half of
           the floating point full scale range, both are rescaled.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       -30,+30     30000       3.2e-17     9.2e-18
              IEEE      -10,+10    100000       2.7e-16     6.9e-17

*csqrt*: Complex square root
          SYNOPSIS:

          # void csqrt();
          # cmplx z, w;

          $z = new_cmplx(2, 3);    # $z = 2 + 3 i
          $w = new_cmplx();
          csqrt($z, $w );
          print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w

          DESCRIPTION:

          If z = x + iy,  r = |z|, then

          1/2
           Im w  =  [ (r - x)/2 ]   ,

          Re w  =  y / 2 Im w.

          Note that -w is also a square root of z.  The root chosen
          is always in the upper half plane.

          Because of the potential for cancellation error in r - x,
          the result is sharpened by doing a Heron iteration
          (see sqrt.c) in complex arithmetic.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       -10,+10     25000       3.2e-17     9.6e-18
              IEEE      -10,+10    100000       3.2e-16     7.7e-17

          2
           Also tested by csqrt( z ) = z, and tested by arguments
           close to the real axis.

*machconst*: Globally declared constants
          SYNOPSIS:

          extern double nameofconstant;

          DESCRIPTION:

          This file contains a number of mathematical constants and
          also some needed size parameters of the computer arithmetic.
          The values are supplied as arrays of hexadecimal integers
          for IEEE arithmetic; arrays of octal constants for DEC
          arithmetic; and in a normal decimal scientific notation for
          other machines.  The particular notation used is determined
          by a symbol (DEC, IBMPC, or UNK) defined in the include file
          mconf.h.

          The default size parameters are as follows.

          For DEC and UNK modes:
          MACHEP =  1.38777878078144567553E-17       2**-56
          MAXLOG =  8.8029691931113054295988E1       log(2**127)
          MINLOG = -8.872283911167299960540E1        log(2**-128)
          MAXNUM =  1.701411834604692317316873e38    2**127

          For IEEE arithmetic (IBMPC):
          MACHEP =  1.11022302462515654042E-16       2**-53
          MAXLOG =  7.09782712893383996843E2         log(2**1024)
          MINLOG = -7.08396418532264106224E2         log(2**-1022)
          MAXNUM =  1.7976931348623158E308           2**1024

          These lists are subject to change.

cosh: Hyperbolic cosine
          SYNOPSIS:

          # double x, y, cosh();

          $y = cosh( $x );

          DESCRIPTION:

          Returns hyperbolic cosine of argument in the range MINLOG to
          MAXLOG.

          cosh(x)  =  ( exp(x) + exp(-x) )/2.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       +- 88       50000       4.0e-17     7.7e-18
              IEEE     +-MAXLOG     30000       2.6e-16     5.7e-17

          ERROR MESSAGES:

          message         condition      value returned
           cosh overflow    |x| > MAXLOG       MAXNUM

*dawsn*: Dawson's Integral
          SYNOPSIS:

          # double x, y, dawsn();

          $y = dawsn( $x );

          DESCRIPTION:

          Approximates the integral

          x
          -
                                2     | |        2
            dawsn(x)  =  exp( -x  )   |    exp( t  ) dt
                                    | |
                                     -
                                     0

          Three different rational approximations are employed, for
          the intervals 0 to 3.25; 3.25 to 6.25; and 6.25 up.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              IEEE      0,10        10000       6.9e-16     1.0e-16
              DEC       0,10         6000       7.4e-17     1.4e-17

*drand*: Pseudorandom number generator
          SYNOPSIS:

          # double y, drand();

          ($flag, $y) = drand( );

          DESCRIPTION:

          Yields a random number 1.0 <= y < 2.0.

          The three-generator congruential algorithm by Brian
          Wichmann and David Hill (BYTE magazine, March, 1987,
          pp 127-8) is used. The period, given by them, is
          6953607871644.

          Versions invoked by the different arithmetic compile
          time options DEC, IBMPC, and MIEEE, produce
          approximately the same sequences, differing only in the
          least significant bits of the numbers. The UNK option
          implements the algorithm as recommended in the BYTE
          article.  It may be used on all computers. However,
          the low order bits of a double precision number may
          not be adequately random, and may vary due to arithmetic
          implementation details on different computers.

          The other compile options generate an additional random
          integer that overwrites the low order bits of the double
          precision number.  This reduces the period by a factor of
          two but tends to overcome the problems mentioned.

*ellie*: Incomplete elliptic integral of the second kind
          SYNOPSIS:

          # double phi, m, y, ellie();

          $y = ellie( $phi, $m );

          DESCRIPTION:

          Approximates the integral

          phi
           -
          | |
          |                   2
           E(phi_\m)  =    |    sqrt( 1 - m sin t ) dt
          |
                        | |
                         -
          0

          of amplitude phi and modulus m, using the arithmetic -
          geometric mean algorithm.

          ACCURACY:

          Tested at random arguments with phi in [-10, 10] and m in
          [0, 1].
                               Relative error:
          arithmetic   domain     # trials      peak         rms
             DEC        0,2         2000       1.9e-16     3.4e-17
             IEEE     -10,10      150000       3.3e-15     1.4e-16

*ellik*: Incomplete elliptic integral of the first kind
          SYNOPSIS:

          # double phi, m, y, ellik();

          $y = ellik( $phi, $m );

          DESCRIPTION:

          Approximates the integral

          phi
           -
          | |
          |           dt
           F(phi_\m)  =    |    ------------------
          |                   2
                        | |    sqrt( 1 - m sin t )
                         -
          0

          of amplitude phi and modulus m, using the arithmetic -
          geometric mean algorithm.

          ACCURACY:

          Tested at random points with m in [0, 1] and phi as indicated.

          Relative error:
           arithmetic   domain     # trials      peak         rms
              IEEE     -10,10       200000      7.4e-16     1.0e-16

*ellpe*: Complete elliptic integral of the second kind
          SYNOPSIS:

          # double m1, y, ellpe();

          $y = ellpe( $m1 );

          DESCRIPTION:

          Approximates the integral

          pi/2
           -
          | |                 2
           E(m)  =    |    sqrt( 1 - m sin t ) dt
                    | |
                     -
          0

          Where m = 1 - m1, using the approximation

          P(x)  -  x log x Q(x).

          Though there are no singularities, the argument m1 is used
          rather than m for compatibility with ellpk().

          E(1) = 1; E(0) = pi/2.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC        0, 1       13000       3.1e-17     9.4e-18
              IEEE       0, 1       10000       2.1e-16     7.3e-17

          ERROR MESSAGES:

          message         condition      value returned
           ellpe domain      x<0, x>1            0.0

*ellpj*: Jacobian Elliptic Functions
          SYNOPSIS:

          # double u, m, sn, cn, dn, phi;
          # int ellpj();

          ($flag, $sn, $cn, $dn, $phi) = ellpj( $u, $m );

          DESCRIPTION:

          Evaluates the Jacobian elliptic functions sn(u|m), cn(u|m),
          and dn(u|m) of parameter m between 0 and 1, and real
          argument u.

          These functions are periodic, with quarter-period on the
          real axis equal to the complete elliptic integral
          ellpk(1.0-m).

          Relation to incomplete elliptic integral:
          If u = ellik(phi,m), then sn(u|m) = sin(phi),
          and cn(u|m) = cos(phi).  Phi is called the amplitude of u.

          Computation is by means of the arithmetic-geometric mean
          algorithm, except when m is within 1e-9 of 0 or 1.  In the
          latter case with m close to 1, the approximation applies
          only for phi < pi/2.

          ACCURACY:

          Tested at random points with u between 0 and 10, m between
          0 and 1.

          Absolute error (* = relative error):
           arithmetic   function   # trials      peak         rms
              DEC       sn           1800       4.5e-16     8.7e-17
              IEEE      phi         10000       9.2e-16*    1.4e-16*
              IEEE      sn          50000       4.1e-15     4.6e-16
              IEEE      cn          40000       3.6e-15     4.4e-16
              IEEE      dn          10000       1.3e-12     1.8e-14

          Peak error observed in consistency check using addition
           theorem for sn(u+v) was 4e-16 (absolute).  Also tested by
           the above relation to the incomplete elliptic integral.
           Accuracy deteriorates when u is large.

*ellpk*: Complete elliptic integral of the first kind
          SYNOPSIS:

          # double m1, y, ellpk();

          $y = ellpk( $m1 );

          DESCRIPTION:

          Approximates the integral

          pi/2
           -
          | |
          |           dt
           K(m)  =    |    ------------------
          |                   2
                    | |    sqrt( 1 - m sin t )
                     -
          0

          where m = 1 - m1, using the approximation

          P(x)  -  log x Q(x).

          The argument m1 is used rather than m so that the logarithmic
          singularity at m = 1 will be shifted to the origin; this
          preserves maximum accuracy.

          K(0) = pi/2.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC        0,1        16000       3.5e-17     1.1e-17
              IEEE       0,1        30000       2.5e-16     6.8e-17

          ERROR MESSAGES:

          message         condition      value returned
           ellpk domain       x<0, x>1           0.0

*euclid*: Rational arithmetic routines
          SYNOPSIS:

          # typedef struct
           #     {
           #     double n;  numerator
           #     double d;  denominator
           #     }fract;

          $a = new_fract(3, 4);	# a = 3 / 4
          $b = new_fract(2, 3);  # b = 2 / 3
          $c = new_fract();
          radd( $a, $b, $c ); #     c = b + a
          rsub( $a, $b, $c ); #     c = b - a
          rmul( $a, $b, $c ); #     c = b * a
          rdiv( $a, $b, $c ); #     c = b / a
          print $c->{n}, ' ', $c->{d};  # prints numerator and denominator of $c

          ($gcd, $m_reduced, $n_reduced) = euclid($m, $n);
          # returns the greatest common divisor of $m and $n, as well as
          # the result of reducing $m and $n by $gcd

          Arguments of the routines are pointers to the structures.
          The double precision numbers are assumed, without checking,
          to be integer valued.  Overflow conditions are reported.

exp: Exponential function
          SYNOPSIS:

          # double x, y, exp();

          $y = exp( $x );

          DESCRIPTION:

          Returns e (2.71828...) raised to the x power.

          Range reduction is accomplished by separating the argument
          into an integer k and fraction f such that

          x    k  f
              e  = 2  e.

          A Pade' form  1 + 2x P(x**2)/( Q(x**2) - P(x**2) )
          of degree 2/3 is used to approximate exp(f) in the basic
          interval [-0.5, 0.5].

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       +- 88       50000       2.8e-17     7.0e-18
              IEEE      +- 708      40000       2.0e-16     5.6e-17

          Error amplification in the exponential function can be
          a serious matter.  The error propagation involves
          exp( X(1+delta) ) = exp(X) ( 1 + X*delta + ... ),
          which shows that a 1 lsb error in representing X produces
          a relative error of X times 1 lsb in the function.
          While the routine gives an accurate result for arguments
          that are exactly represented by a double precision
          computer number, the result contains amplified roundoff
          error for large arguments not exactly represented.

          ERROR MESSAGES:

          message         condition      value returned
           exp underflow    x < MINLOG         0.0
           exp overflow     x > MAXLOG         INFINITY

*exp10*: Base 10 exponential function (Common antilogarithm)
          SYNOPSIS:

          # double x, y, exp10();

          $y = exp10( $x );

          DESCRIPTION:

          Returns 10 raised to the x power.

          Range reduction is accomplished by expressing the argument
          as 10**x = 2**n 10**f, with |f| < 0.5 log10(2).
          The Pade' form

          1 + 2x P(x**2)/( Q(x**2) - P(x**2) )

          is used to approximate 10**f.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              IEEE     -307,+307    30000       2.2e-16     5.5e-17
           Test result from an earlier version (2.1):
              DEC       -38,+38     70000       3.1e-17     7.0e-18

          ERROR MESSAGES:

          message         condition      value returned
           exp10 underflow    x < -MAXL10        0.0
           exp10 overflow     x > MAXL10       MAXNUM

          DEC arithmetic: MAXL10 = 38.230809449325611792.
          IEEE arithmetic: MAXL10 = 308.2547155599167.

*exp2*: Base 2 exponential function
          SYNOPSIS:

          # double x, y, exp2();

          $y = exp2( $x );

          DESCRIPTION:

          Returns 2 raised to the x power.

          Range reduction is accomplished by separating the argument
          into an integer k and fraction f such that
              x    k  f
             2  = 2  2.

          A Pade' form

          1 + 2x P(x**2) / (Q(x**2) - x P(x**2) )

          approximates 2**x in the basic range [-0.5, 0.5].

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              IEEE    -1022,+1024   30000       1.8e-16     5.4e-17

          See exp.c for comments on error amplification.

          ERROR MESSAGES:

          message         condition      value returned
           exp underflow    x < -MAXL2        0.0
           exp overflow     x > MAXL2         MAXNUM

          For DEC arithmetic, MAXL2 = 127.
          For IEEE arithmetic, MAXL2 = 1024.

*ei*: 	Exponential integral
          SYNOPSIS:

          #double x, y, ei();

          $y = ei( $x );

          DESCRIPTION:

          x
           -     t
          | |   e
              Ei(x) =   -|-   ---  dt .
                       | |     t
                        -
                       -inf

           Not defined for x <= 0.
           See also expn.c.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              IEEE       0,100       50000      8.6e-16     1.3e-16

*expn*: 	Exponential integral En
          SYNOPSIS:

          # int n;
          # double x, y, expn();

          $y = expn( $n, $x );

          DESCRIPTION:

          Evaluates the exponential integral

          inf.
            -
           | |   -xt
           |    e
                E (x)  =    |    ----  dt.
                 n          |      n
                          | |     t
          -
           1

          Both n and x must be nonnegative.

          The routine employs either a power series, a continued
          fraction, or an asymptotic formula depending on the
          relative values of n and x.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       0, 30        5000       2.0e-16     4.6e-17
              IEEE      0, 30       10000       1.7e-15     3.6e-16

fabs: 	Absolute value
          SYNOPSIS:

          # double x, y;

          $y = fabs( $x );

          DESCRIPTION:

          Returns the absolute value of the argument.

*fac*: Factorial function
          SYNOPSIS:

          # double y, fac();
          # int i;

          $y = fac( $i );

          DESCRIPTION:

          Returns factorial of i  =  1 * 2 * 3 * ... * i.
          fac(0) = 1.0.

          Due to machine arithmetic bounds the largest value of
          i accepted is 33 in DEC arithmetic or 170 in IEEE
          arithmetic.  Greater values, or negative ones,
          produce an error message and return MAXNUM.

          ACCURACY:

          For i < 34 the values are simply tabulated, and have
          full machine accuracy.  If i > 55, fac(i) = gamma(i+1);
          see gamma.c.

          Relative error:
           arithmetic   domain      peak
              IEEE      0, 170    1.4e-15
              DEC       0, 33      1.4e-17

*fdtr*: F distribution
          SYNOPSIS:

          # int df1, df2;
          # double x, y, fdtr();

          $y = fdtr( $df1, $df2, $x );

          DESCRIPTION:

          Returns the area from zero to x under the F density
          function (also known as Snedcor's density or the
          variance ratio density).  This is the density
          of x = (u1/df1)/(u2/df2), where u1 and u2 are random
          variables having Chi square distributions with df1
          and df2 degrees of freedom, respectively.

          The incomplete beta integral is used, according to the
          formula

          P(x) = incbet( df1/2, df2/2, df1*x/(df2 + df1*x) ).

          The arguments a and b are greater than zero, and x is
          nonnegative.

          ACCURACY:

          Tested at random points (a,b,x).

          x     a,b                     Relative error:
           arithmetic  domain  domain     # trials      peak         rms
              IEEE      0,1    0,100       100000      9.8e-15     1.7e-15
              IEEE      1,5    0,100       100000      6.5e-15     3.5e-16
              IEEE      0,1    1,10000     100000      2.2e-11     3.3e-12
              IEEE      1,5    1,10000     100000      1.1e-11     1.7e-13
           See also incbet.c.

          ERROR MESSAGES:

          message         condition      value returned
           fdtr domain     a<0, b<0, x<0         0.0

*fdtrc*: Complemented F distribution
          SYNOPSIS:

          # int df1, df2;
          # double x, y, fdtrc();

          $y = fdtrc( $df1, $df2, $x );

          DESCRIPTION:

          Returns the area from x to infinity under the F density
          function (also known as Snedcor's density or the
          variance ratio density).

          inf.
           -
                        1       | |  a-1      b-1
           1-P(x)  =  ------    |   t    (1-t)    dt
                      B(a,b)  | |
                               -
          x

          The incomplete beta integral is used, according to the
          formula

          P(x) = incbet( df2/2, df1/2, df2/(df2 + df1*x) ).

          ACCURACY:

          Tested at random points (a,b,x) in the indicated intervals.
                         x     a,b                     Relative error:
          arithmetic  domain  domain     # trials      peak         rms
             IEEE      0,1    1,100       100000      3.7e-14     5.9e-16
             IEEE      1,5    1,100       100000      8.0e-15     1.6e-15
             IEEE      0,1    1,10000     100000      1.8e-11     3.5e-13
             IEEE      1,5    1,10000     100000      2.0e-11     3.0e-12
          See also incbet.c.

          ERROR MESSAGES:

          message         condition      value returned
           fdtrc domain    a<0, b<0, x<0         0.0

*fdtri*: Inverse of complemented F distribution
          SYNOPSIS:

          # int df1, df2;
          # double x, p, fdtri();

          $x = fdtri( $df1, $df2, $p );

          DESCRIPTION:

          Finds the F density argument x such that the integral
          from x to infinity of the F density is equal to the
          given probability p.

          This is accomplished using the inverse beta integral
          function and the relations

          z = incbi( df2/2, df1/2, p )
          x = df2 (1-z) / (df1 z).

          Note: the following relations hold for the inverse of
          the uncomplemented F distribution:

          z = incbi( df1/2, df2/2, p )
          x = df2 z / (df1 (1-z)).

          ACCURACY:

          Tested at random points (a,b,p).

          a,b                     Relative error:
           arithmetic  domain     # trials      peak         rms
            For p between .001 and 1:
              IEEE     1,100       100000      8.3e-15     4.7e-16
              IEEE     1,10000     100000      2.1e-11     1.4e-13
            For p between 10^-6 and 10^-3:
              IEEE     1,100        50000      1.3e-12     8.4e-15
              IEEE     1,10000      50000      3.0e-12     4.8e-14
           See also fdtrc.c.

          ERROR MESSAGES:

          message         condition      value returned
           fdtri domain   p <= 0 or p > 1       0.0
                            v < 1

ceil: ceil
          ceil() returns the smallest integer greater than or equal
          to x.  It truncates toward plus infinity.

          SYNOPSIS:

          # double x, y, ceil();

          $y = ceil( $x );

floor: floor
          floor() returns the largest integer less than or equal to x.
          It truncates toward minus infinity.

          SYNOPSIS:

          # double x, y, floor();

          $y = floor( $x );

frexp: frexp
          frexp() extracts the exponent from x.  It returns an integer
          power of two to expnt and the significand between 0.5 and 1
          to y.  Thus  x = y * 2**expn.

          SYNOPSIS:

          # double x, y, frexp();
          # int expnt;

          ($y, $expnt)  = frexp( $x );

ldexp: multiplies x by 2**n.
          SYNOPSIS:

          # double x, y, ldexp();
          # int n;

          $y = ldexp( $x, $n );

*fresnl*: Fresnel integral
          SYNOPSIS:

          # double x, S, C;
          # void fresnl();

          ($flag, $S, $C) = fresnl( $x );

          DESCRIPTION:

          Evaluates the Fresnel integrals

          x
          -
                    | |
           C(x) =   |   cos(pi/2 t**2) dt,
                  | |
                   -
                    0

          x
          -
                    | |
           S(x) =   |   sin(pi/2 t**2) dt.
                  | |
                   -
                    0

          The integrals are evaluated by a power series for x < 1.
          For x >= 1 auxiliary functions f(x) and g(x) are employed
          such that

          C(x) = 0.5 + f(x) sin( pi/2 x**2 ) - g(x) cos( pi/2 x**2 )
          S(x) = 0.5 - f(x) cos( pi/2 x**2 ) - g(x) sin( pi/2 x**2 )

          ACCURACY:

          Relative error.

          Arithmetic  function   domain     # trials      peak         rms
            IEEE       S(x)      0, 10       10000       2.0e-15     3.2e-16
            IEEE       C(x)      0, 10       10000       1.8e-15     3.3e-16
            DEC        S(x)      0, 10        6000       2.2e-16     3.9e-17
            DEC        C(x)      0, 10        5000       2.3e-16     3.9e-17

*gamma*: Gamma function
          SYNOPSIS:

          # double x, y, gamma();
          # extern int sgngam;

          $y = gamma( $x );

          DESCRIPTION:

          Returns gamma function of the argument.  The result is
          correctly signed, and the sign (+1 or -1) is also
          returned in a global (extern) variable named sgngam.
          This variable is also filled in by the logarithmic gamma
          function lgam().

          Arguments |x| <= 34 are reduced by recurrence and the function
          approximated by a rational function of degree 6/7 in the
          interval (2,3).  Large arguments are handled by Stirling's
          formula. Large negative arguments are made positive using
          a reflection formula.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC      -34, 34      10000       1.3e-16     2.5e-17
              IEEE    -170,-33      20000       2.3e-15     3.3e-16
              IEEE     -33,  33     20000       9.4e-16     2.2e-16
              IEEE      33, 171.6   20000       2.3e-15     3.2e-16

          Error for arguments outside the test range will be larger
          owing to error amplification by the exponential function.

*lgam*: Natural logarithm of gamma function
          SYNOPSIS:

          # double x, y, lgam();
          # extern int sgngam;

          $y = lgam( $x );

          DESCRIPTION:

          Returns the base e (2.718...) logarithm of the absolute
          value of the gamma function of the argument.
          The sign (+1 or -1) of the gamma function is returned in a
          global (extern) variable named sgngam.

          For arguments greater than 13, the logarithm of the gamma
          function is approximated by the logarithmic version of
          Stirling's formula using a polynomial approximation of
          degree 4. Arguments between -33 and +33 are reduced by
          recurrence to the interval [2,3] of a rational approximation.
          The cosecant reflection formula is employed for arguments
          less than -33.

          Arguments greater than MAXLGM return MAXNUM and an error
          message.  MAXLGM = 2.035093e36 for DEC
          arithmetic or 2.556348e305 for IEEE arithmetic.

          ACCURACY:

          arithmetic      domain        # trials     peak         rms
             DEC     0, 3                  7000     5.2e-17     1.3e-17
             DEC     2.718, 2.035e36       5000     3.9e-17     9.9e-18
             IEEE    0, 3                 28000     5.4e-16     1.1e-16
             IEEE    2.718, 2.556e305     40000     3.5e-16     8.3e-17
          The error criterion was relative when the function magnitude
          was greater than one but absolute when it was less than one.

          The following test used the relative error criterion, though
          at certain points the relative error could be much higher than
          indicated.
             IEEE    -200, -4             10000     4.8e-16     1.3e-16

*gdtr*: Gamma distribution function
          SYNOPSIS:

          # double a, b, x, y, gdtr();

          $y = gdtr( $a, $b, $x );

          DESCRIPTION:

          Returns the integral from zero to x of the gamma probability
          density function:

          x
                  b       -
                 a       | |   b-1  -at
           y =  -----    |    t    e    dt
                 -     | |
                | (b)   -
                         0

          The incomplete gamma integral is used, according to the
           relation

          y = igam( b, ax ).

          ACCURACY:

          See igam().

          ERROR MESSAGES:

          message         condition      value returned
           gdtr domain         x < 0            0.0

*gdtrc*: Complemented gamma distribution function
          SYNOPSIS:

          # double a, b, x, y, gdtrc();

          $y = gdtrc( $a, $b, $x );

          DESCRIPTION:

          Returns the integral from x to infinity of the gamma
          probability density function:

          inf.
                  b       -
                 a       | |   b-1  -at
           y =  -----    |    t    e    dt
                 -     | |
                | (b)   -
          x

          The incomplete gamma integral is used, according to the
           relation

          y = igamc( b, ax ).

          ACCURACY:

          See igamc().

          ERROR MESSAGES:

          message         condition      value returned
           gdtrc domain         x < 0            0.0

*hyp2f0*: Gauss hypergeometric function  2F0
          SYNOPSIS:

          # double a, b, x, value, *err;
          # int type;	/* determines what converging factor to use */

          ($value, $err) =  hyp2f0( $a, $b, $x, $type )

*hyp2f1*: Gauss hypergeometric function  2F1
          SYNOPSIS:

          # double a, b, c, x, y, hyp2f1();

          $y = hyp2f1( $a, $b, $c, $x );

          DESCRIPTION:

          hyp2f1( a, b, c, x )  =   F ( a, b; c; x )
                                   2 1

          inf.
           -   a(a+1)...(a+k) b(b+1)...(b+k)   k+1
             =  1 +   >   -----------------------------  x   .
           -         c(c+1)...(c+k) (k+1)!
                    k = 0

          Cases addressed are
          	Tests and escapes for negative integer a, b, or c
          	Linear transformation if c - a or c - b negative integer
          	Special case c = a or c = b
          	Linear transformation for  x near +1
          	Transformation for x < -0.5
          	Psi function expansion if x > 0.5 and c - a - b integer
              Conditionally, a recurrence on c to make c-a-b > 0

          |x| > 1 is rejected.

          The parameters a, b, c are considered to be integer
          valued if they are within 1.0e-14 of the nearest integer
          (1.0e-13 for IEEE arithmetic).

          ACCURACY:

          Relative error (-1 < x < 1):
           arithmetic   domain     # trials      peak         rms
              IEEE      -1,7        230000      1.2e-11     5.2e-14

          Several special cases also tested with a, b, c in
          the range -7 to 7.

          ERROR MESSAGES:

          A "partial loss of precision" message is printed if
          the internally estimated relative error exceeds 1^-12.
          A "singularity" message is printed on overflow or
          in cases not addressed (such as x < -1).

*hyperg*: Confluent hypergeometric function
          SYNOPSIS:

          # double a, b, x, y, hyperg();

          $y = hyperg( $a, $b, $x );

          DESCRIPTION:

          Computes the confluent hypergeometric function

          1           2
                                 a x    a(a+1) x
             F ( a,b;x )  =  1 + ---- + --------- + ...
            1 1                  b 1!   b(b+1) 2!

          Many higher transcendental functions are special cases of
          this power series.

          As is evident from the formula, b must not be a negative
          integer or zero unless a is an integer with 0 >= a > b.

          The routine attempts both a direct summation of the series
          and an asymptotic expansion.  In each case error due to
          roundoff, cancellation, and nonconvergence is estimated.
          The result with smaller estimated error is returned.

          ACCURACY:

          Tested at random points (a, b, x), all three variables
          ranging from 0 to 30.
                               Relative error:
          arithmetic   domain     # trials      peak         rms
             DEC       0,30         2000       1.2e-15     1.3e-16
             IEEE      0,30        30000       1.8e-14     1.1e-15

          Larger errors can be observed when b is near a negative
          integer or zero.  Certain combinations of arguments yield
          serious cancellation error in the power series summation
          and also are not in the region of near convergence of the
          asymptotic series.  An error message is printed if the
          self-estimated relative error is greater than 1.0e-12.

*i0*: Modified Bessel function of order zero
          SYNOPSIS:

          # double x, y, i0();

          $y = i0( $x );

          DESCRIPTION:

          Returns modified Bessel function of order zero of the
          argument.

          The function is defined as i0(x) = j0( ix ).

          The range is partitioned into the two intervals [0,8] and
          (8, infinity).  Chebyshev polynomial expansions are employed
          in each interval.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       0,30         6000       8.2e-17     1.9e-17
              IEEE      0,30        30000       5.8e-16     1.4e-16

*i0e*: Modified Bessel function of order zero, exponentially scaled
          SYNOPSIS:

          # double x, y, i0e();

          $y = i0e( $x );

          DESCRIPTION:

          Returns exponentially scaled modified Bessel function
          of order zero of the argument.

          The function is defined as i0e(x) = exp(-|x|) j0( ix ).

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              IEEE      0,30        30000       5.4e-16     1.2e-16
           See i0().

*i1*: Modified Bessel function of order one
          SYNOPSIS:

          # double x, y, i1();

          $y = i1( $x );

          DESCRIPTION:

          Returns modified Bessel function of order one of the
          argument.

          The function is defined as i1(x) = -i j1( ix ).

          The range is partitioned into the two intervals [0,8] and
          (8, infinity).  Chebyshev polynomial expansions are employed
          in each interval.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       0, 30        3400       1.2e-16     2.3e-17
              IEEE      0, 30       30000       1.9e-15     2.1e-16

*i1e*: Modified Bessel function of order one, exponentially scaled
          SYNOPSIS:

          # double x, y, i1e();

          $y = i1e( $x );

          DESCRIPTION:

          Returns exponentially scaled modified Bessel function
          of order one of the argument.

          The function is defined as i1(x) = -i exp(-|x|) j1( ix ).

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              IEEE      0, 30       30000       2.0e-15     2.0e-16
           See i1().

*igam*: Incomplete gamma integral
          SYNOPSIS:

          # double a, x, y, igam();

          $y = igam( $a, $x );

          DESCRIPTION:

          The function is defined by

          x
           -
                             1       | |  -t  a-1
            igam(a,x)  =   -----     |   e   t   dt.
                            -      | |
                           | (a)    -
          0

          In this implementation both arguments must be positive.
          The integral is evaluated by either a power series or
          continued fraction expansion, depending on the relative
          values of a and x.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              IEEE      0,30       200000       3.6e-14     2.9e-15
              IEEE      0,100      300000       9.9e-14     1.5e-14

*igamc*: Complemented incomplete gamma integral
          SYNOPSIS:

          # double a, x, y, igamc();

          $y = igamc( $a, $x );

          DESCRIPTION:

          The function is defined by

          igamc(a,x)   =   1 - igam(a,x)

          inf.
            -
                               1       | |  -t  a-1
                         =   -----     |   e   t   dt.
                              -      | |
                             | (a)    -
           x

          In this implementation both arguments must be positive.
          The integral is evaluated by either a power series or
          continued fraction expansion, depending on the relative
          values of a and x.

          ACCURACY:

          Tested at random a, x.
                         a         x                      Relative error:
          arithmetic   domain   domain     # trials      peak         rms
             IEEE     0.5,100   0,100      200000       1.9e-14     1.7e-15
             IEEE     0.01,0.5  0,100      200000       1.4e-13     1.6e-15

*igami*: Inverse of complemented imcomplete gamma integral
          SYNOPSIS:

          # double a, x, p, igami();

          $x = igami( $a, $p );

          DESCRIPTION:

          Given p, the function finds x such that

          igamc( a, x ) = p.

          Starting with the approximate value

          3
            x = a t

          where

          t = 1 - d - ndtri(p) sqrt(d)

           and

          d = 1/9a,

          the routine performs up to 10 Newton iterations to find the
          root of igamc(a,x) - p = 0.

          ACCURACY:

          Tested at random a, p in the intervals indicated.

          a        p                      Relative error:
           arithmetic   domain   domain     # trials      peak         rms
              IEEE     0.5,100   0,0.5       100000       1.0e-14     1.7e-15
              IEEE     0.01,0.5  0,0.5       100000       9.0e-14     3.4e-15
              IEEE    0.5,10000  0,0.5        20000       2.3e-13     3.8e-14

*incbet*: Incomplete beta integral
          SYNOPSIS:

          # double a, b, x, y, incbet();

          $y = incbet( $a, $b, $x );

          DESCRIPTION:

          Returns incomplete beta integral of the arguments, evaluated
          from zero to x.  The function is defined as

          x
               -            -
              | (a+b)      | |  a-1     b-1
            -----------    |   t   (1-t)   dt.
             -     -     | |
            | (a) | (b)   -
                           0

          The domain of definition is 0 <= x <= 1.  In this
          implementation a and b are restricted to positive values.
          The integral from x to 1 may be obtained by the symmetry
          relation

          1 - incbet( a, b, x )  =  incbet( b, a, 1-x ).

          The integral is evaluated by a continued fraction expansion
          or, when b*x is small, by a power series.

          ACCURACY:

          Tested at uniformly distributed random points (a,b,x) with a and b
          in "domain" and x between 0 and 1.
                                                 Relative error
          arithmetic   domain     # trials      peak         rms
             IEEE      0,5         10000       6.9e-15     4.5e-16
             IEEE      0,85       250000       2.2e-13     1.7e-14
             IEEE      0,1000      30000       5.3e-12     6.3e-13
             IEEE      0,10000    250000       9.3e-11     7.1e-12
             IEEE      0,100000    10000       8.7e-10     4.8e-11
          Outputs smaller than the IEEE gradual underflow threshold
          were excluded from these statistics.

          ERROR MESSAGES:
            message         condition      value returned
          incbet domain      x<0, x>1          0.0
          incbet underflow                     0.0

*incbi*: Inverse of imcomplete beta integral
          SYNOPSIS:

          # double a, b, x, y, incbi();

          $x = incbi( $a, $b, $y );

          DESCRIPTION:

          Given y, the function finds x such that

          incbet( a, b, x ) = y .

          The routine performs interval halving or Newton iterations to find the
          root of incbet(a,b,x) - y = 0.

          ACCURACY:

          Relative error:
                          x     a,b
           arithmetic   domain  domain  # trials    peak       rms
              IEEE      0,1    .5,10000   50000    5.8e-12   1.3e-13
              IEEE      0,1   .25,100    100000    1.8e-13   3.9e-15
              IEEE      0,1     0,5       50000    1.1e-12   5.5e-15
              VAX       0,1    .5,100     25000    3.5e-14   1.1e-15
           With a and b constrained to half-integer or integer values:
              IEEE      0,1    .5,10000   50000    5.8e-12   1.1e-13
              IEEE      0,1    .5,100    100000    1.7e-14   7.9e-16
           With a = .5, b constrained to half-integer or integer values:
              IEEE      0,1    .5,10000   10000    8.3e-11   1.0e-11

iv: Modified Bessel function of noninteger order
          SYNOPSIS:

          # double v, x, y, iv();

          $y = iv( $v, $x );

          DESCRIPTION:

          Returns modified Bessel function of order v of the
          argument.  If x is negative, v must be integer valued.

          The function is defined as Iv(x) = Jv( ix ).  It is
          here computed in terms of the confluent hypergeometric
          function, according to the formula

          v  -x
           Iv(x) = (x/2)  e   hyperg( v+0.5, 2v+1, 2x ) / gamma(v+1)

          If v is a negative integer, then v is replaced by -v.

          ACCURACY:

          Tested at random points (v, x), with v between 0 and
          30, x between 0 and 28.
                               Relative error:
          arithmetic   domain     # trials      peak         rms
             DEC       0,30          2000      3.1e-15     5.4e-16
             IEEE      0,30         10000      1.7e-14     2.7e-15

          Accuracy is diminished if v is near a negative integer.

          See also hyperg.c.

*j0*: Bessel function of order zero
          SYNOPSIS:

          # double x, y, j0();

          $y = j0( $x );

          DESCRIPTION:

          Returns Bessel function of order zero of the argument.

          The domain is divided into the intervals [0, 5] and
          (5, infinity). In the first interval the following rational
          approximation is used:

          2         2
           (w - r  ) (w - r  ) P (w) / Q (w)
                 1         2    3       8

          2
           where w = x  and the two r's are zeros of the function.

          In the second interval, the Hankel asymptotic expansion
          is employed with two rational functions of degree 6/6
          and 7/7.

          ACCURACY:

          Absolute error:
           arithmetic   domain     # trials      peak         rms
              DEC       0, 30       10000       4.4e-17     6.3e-18
              IEEE      0, 30       60000       4.2e-16     1.1e-16

*y0*: Bessel function of the second kind, order zero
          SYNOPSIS:

          # double x, y, y0();

          $y = y0( $x );

          DESCRIPTION:

          Returns Bessel function of the second kind, of order
          zero, of the argument.

          The domain is divided into the intervals [0, 5] and
          (5, infinity). In the first interval a rational approximation
          R(x) is employed to compute
            y0(x)  = R(x)  +   2 * log(x) * j0(x) / PI.
          Thus a call to j0() is required.

          In the second interval, the Hankel asymptotic expansion
          is employed with two rational functions of degree 6/6
          and 7/7.

          ACCURACY:

          Absolute error, when y0(x) < 1; else relative error:

          arithmetic   domain     # trials      peak         rms
             DEC       0, 30        9400       7.0e-17     7.9e-18
             IEEE      0, 30       30000       1.3e-15     1.6e-16

*j1*: Bessel function of order one
          SYNOPSIS:

          # double x, y, j1();

          $y = j1( $x );

          DESCRIPTION:

          Returns Bessel function of order one of the argument.

          The domain is divided into the intervals [0, 8] and
          (8, infinity). In the first interval a 24 term Chebyshev
          expansion is used. In the second, the asymptotic
          trigonometric representation is employed using two
          rational functions of degree 5/5.

          ACCURACY:

          Absolute error:
           arithmetic   domain      # trials      peak         rms
              DEC       0, 30       10000       4.0e-17     1.1e-17
              IEEE      0, 30       30000       2.6e-16     1.1e-16

*y1*: Bessel function of second kind of order one
          SYNOPSIS:

          # double x, y, y1();

          $y = y1( $x );

          DESCRIPTION:

          Returns Bessel function of the second kind of order one
          of the argument.

          The domain is divided into the intervals [0, 8] and
          (8, infinity). In the first interval a 25 term Chebyshev
          expansion is used, and a call to j1() is required.
          In the second, the asymptotic trigonometric representation
          is employed using two rational functions of degree 5/5.

          ACCURACY:

          Absolute error:
           arithmetic   domain      # trials      peak         rms
              DEC       0, 30       10000       8.6e-17     1.3e-17
              IEEE      0, 30       30000       1.0e-15     1.3e-16

          (error criterion relative when |y1| > 1).

*jn*: Bessel function of integer order
          SYNOPSIS:

          # int n;
          # double x, y, jn();

          $y = jn( $n, $x );

          DESCRIPTION:

          Returns Bessel function of order n, where n is a
          (possibly negative) integer.

          The ratio of jn(x) to j0(x) is computed by backward
          recurrence.  First the ratio jn/jn-1 is found by a
          continued fraction expansion.  Then the recurrence
          relating successive orders is applied until j0 or j1 is
          reached.

          If n = 0 or 1 the routine for j0 or j1 is called
          directly.

          ACCURACY:

          Absolute error:
           arithmetic   range      # trials      peak         rms
              DEC       0, 30        5500       6.9e-17     9.3e-18
              IEEE      0, 30        5000       4.4e-16     7.9e-17

          Not suitable for large n or x. Use jv() instead.

*jv*: Bessel function of noninteger order
          SYNOPSIS:

          # double v, x, y, jv();

          $y = jv( $v, $x );

          DESCRIPTION:

          Returns Bessel function of order v of the argument,
          where v is real.  Negative x is allowed if v is an integer.

          Several expansions are included: the ascending power
          series, the Hankel expansion, and two transitional
          expansions for large v.  If v is not too large, it
          is reduced by recurrence to a region of best accuracy.
          The transitional expansions give 12D accuracy for v > 500.

          ACCURACY:

          Results for integer v are indicated by *, where x and v
          both vary from -125 to +125.  Otherwise,
          x ranges from 0 to 125, v ranges as indicated by "domain."
          Error criterion is absolute, except relative when |jv()| > 1.

          arithmetic  v domain  x domain    # trials      peak       rms
             IEEE      0,125     0,125      100000      4.6e-15    2.2e-16
             IEEE   -125,0       0,125       40000      5.4e-11    3.7e-13
             IEEE      0,500     0,500       20000      4.4e-15    4.0e-16
          Integer v:
             IEEE   -125,125   -125,125      50000      3.5e-15*   1.9e-16*

*k0*: Modified Bessel function, third kind, order zero
          SYNOPSIS:

          # double x, y, k0();

          $y = k0( $x );

          DESCRIPTION:

          Returns modified Bessel function of the third kind
          of order zero of the argument.

          The range is partitioned into the two intervals [0,8] and
          (8, infinity).  Chebyshev polynomial expansions are employed
          in each interval.

          ACCURACY:

          Tested at 2000 random points between 0 and 8.  Peak absolute
          error (relative when K0 > 1) was 1.46e-14; rms, 4.26e-15.
                               Relative error:
          arithmetic   domain     # trials      peak         rms
             DEC       0, 30        3100       1.3e-16     2.1e-17
             IEEE      0, 30       30000       1.2e-15     1.6e-16

          ERROR MESSAGES:

          message         condition      value returned
            K0 domain          x <= 0          MAXNUM

*k0e*: Modified Bessel function, third kind, order zero, exponentially scaled
          SYNOPSIS:

          # double x, y, k0e();

          $y = k0e( $x );

          DESCRIPTION:

          Returns exponentially scaled modified Bessel function
          of the third kind of order zero of the argument.

          k0e(x) = exp(x) * k0(x).

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              IEEE      0, 30       30000       1.4e-15     1.4e-16
           See k0().

*k1*: Modified Bessel function, third kind, order one
          SYNOPSIS:

          # double x, y, k1();

          $y = k1( $x );

          DESCRIPTION:

          Computes the modified Bessel function of the third kind
          of order one of the argument.

          The range is partitioned into the two intervals [0,2] and
          (2, infinity).  Chebyshev polynomial expansions are employed
          in each interval.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       0, 30        3300       8.9e-17     2.2e-17
              IEEE      0, 30       30000       1.2e-15     1.6e-16

          ERROR MESSAGES:

          message         condition      value returned
           k1 domain          x <= 0          MAXNUM

*k1e*: Modified Bessel function, third kind, order one, exponentially scaled
          SYNOPSIS:

          # double x, y, k1e();

          $y = k1e( $x );

          DESCRIPTION:

          Returns exponentially scaled modified Bessel function
          of the third kind of order one of the argument:

          k1e(x) = exp(x) * k1(x).

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              IEEE      0, 30       30000       7.8e-16     1.2e-16
           See k1().

*kn*: Modified Bessel function, third kind, integer order
          SYNOPSIS:

          # double x, y, kn();
          # int n;

          $y = kn( $n, $x );

          DESCRIPTION:

          Returns modified Bessel function of the third kind
          of order n of the argument.

          The range is partitioned into the two intervals [0,9.55] and
          (9.55, infinity).  An ascending power series is used in the
          low range, and an asymptotic expansion in the high range.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       0,30         3000       1.3e-9      5.8e-11
              IEEE      0,30        90000       1.8e-8      3.0e-10

          Error is high only near the crossover point x = 9.55
           between the two expansions used.

log: Natural logarithm
          SYNOPSIS:

          # double x, y, log();

          $y = log( $x );

          DESCRIPTION:

          Returns the base e (2.718...) logarithm of x.

          The argument is separated into its exponent and fractional
          parts.  If the exponent is between -1 and +1, the logarithm
          of the fraction is approximated by

          log(1+x) = x - 0.5 x**2 + x**3 P(x)/Q(x).

          Otherwise, setting  z = 2(x-1)/x+1),

              log(x) = z + z**3 P(z)/Q(z).

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              IEEE      0.5, 2.0    150000      1.44e-16    5.06e-17
              IEEE      +-MAXNUM    30000       1.20e-16    4.78e-17
              DEC       0, 10       170000      1.8e-17     6.3e-18

          In the tests over the interval [+-MAXNUM], the logarithms
          of the random arguments were uniformly distributed over
          [0, MAXLOG].

          ERROR MESSAGES:

          log singularity:  x = 0; returns -INFINITY
          log domain:       x < 0; returns NAN

log10: Common logarithm
          SYNOPSIS:

          # double x, y, log10();

          $y = log10( $x );

          DESCRIPTION:

          Returns logarithm to the base 10 of x.

          The argument is separated into its exponent and fractional
          parts.  The logarithm of the fraction is approximated by

          log(1+x) = x - 0.5 x**2 + x**3 P(x)/Q(x).

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              IEEE      0.5, 2.0     30000      1.5e-16     5.0e-17
              IEEE      0, MAXNUM    30000      1.4e-16     4.8e-17
              DEC       1, MAXNUM    50000      2.5e-17     6.0e-18

          In the tests over the interval [1, MAXNUM], the logarithms
          of the random arguments were uniformly distributed over
          [0, MAXLOG].

          ERROR MESSAGES:

          log10 singularity:  x = 0; returns -INFINITY
          log10 domain:       x < 0; returns NAN

*log2*: Base 2 logarithm
          SYNOPSIS:

          # double x, y, log2();

          $y = log2( $x );

          DESCRIPTION:

          Returns the base 2 logarithm of x.

          The argument is separated into its exponent and fractional
          parts.  If the exponent is between -1 and +1, the base e
          logarithm of the fraction is approximated by

          log(1+x) = x - 0.5 x**2 + x**3 P(x)/Q(x).

          Otherwise, setting  z = 2(x-1)/x+1),

              log(x) = z + z**3 P(z)/Q(z).

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              IEEE      0.5, 2.0    30000       2.0e-16     5.5e-17
              IEEE      exp(+-700)  40000       1.3e-16     4.6e-17

          In the tests over the interval [exp(+-700)], the logarithms
          of the random arguments were uniformly distributed.

          ERROR MESSAGES:

          log2 singularity:  x = 0; returns -INFINITY
          log2 domain:       x < 0; returns NAN

*lrand*: Pseudorandom number generator
          SYNOPSIS:

          long y, lrand();

          $y = lrand( );

          DESCRIPTION:

          Yields a long integer random number.

          The three-generator congruential algorithm by Brian
          Wichmann and David Hill (BYTE magazine, March, 1987,
          pp 127-8) is used. The period, given by them, is
          6953607871644.

*lsqrt*: Integer square root
          SYNOPSIS:

          long x, y;
          long lsqrt();

          $y = lsqrt( $x );

          DESCRIPTION:

          Returns a long integer square root of the long integer
          argument.  The computation is by binary long division.

          The largest possible result is lsqrt(2,147,483,647)
          = 46341.

          If x < 0, the square root of |x| is returned, and an
          error message is printed.

          ACCURACY:

          An extra, roundoff, bit is computed; hence the result
          is the nearest integer to the actual square root.
          NOTE: only DEC arithmetic is currently supported.

*mtherr*: Library common error handling routine
          SYNOPSIS:

          char *fctnam;
          # int code;
          # int mtherr();

          mtherr( $fctnam, $code );

          DESCRIPTION:

          This routine may be called to report one of the following
          error conditions (in the include file mconf.h).

            Mnemonic        Value          Significance

          DOMAIN            1       argument domain error
          SING              2       function singularity
          OVERFLOW          3       overflow range error
          UNDERFLOW         4       underflow range error
          TLOSS             5       total loss of precision
          PLOSS             6       partial loss of precision
          EDOM             33       Unix domain error code
          ERANGE           34       Unix range error code

          The default version of the file prints the function name,
          passed to it by the pointer fctnam, followed by the
          error condition.  The display is directed to the standard
          output device.  The routine then returns to the calling
          program.  Users may wish to modify the program to abort by
          calling exit() under severe error conditions such as domain
          errors.

          Since all error conditions pass control to this function,
          the display may be easily changed, eliminated, or directed
          to an error logging device.

          SEE ALSO: mconf.h

*nbdtr*: Negative binomial distribution
          SYNOPSIS:

          # int k, n;
          # double p, y, nbdtr();

          $y = nbdtr( $k, $n, $p );

          DESCRIPTION:

          Returns the sum of the terms 0 through k of the negative
          binomial distribution:

          k
          --  ( n+j-1 )   n      j
          >   (       )  p  (1-p)
          --  (   j   )
            j=0

          In a sequence of Bernoulli trials, this is the probability
          that k or fewer failures precede the nth success.

          The terms are not computed individually; instead the incomplete
          beta integral is employed, according to the formula

          y = nbdtr( k, n, p ) = incbet( n, k+1, p ).

          The arguments must be positive, with p ranging from 0 to 1.

          ACCURACY:

          Tested at random points (a,b,p), with p between 0 and 1.

          a,b                     Relative error:
           arithmetic  domain     # trials      peak         rms
              IEEE     0,100       100000      1.7e-13     8.8e-15
           See also incbet.c.

*nbdtrc*: Complemented negative binomial distribution
          SYNOPSIS:

          # int k, n;
          # double p, y, nbdtrc();

          $y = nbdtrc( $k, $n, $p );

          DESCRIPTION:

          Returns the sum of the terms k+1 to infinity of the negative
          binomial distribution:

          inf
          --  ( n+j-1 )   n      j
          >   (       )  p  (1-p)
          --  (   j   )
            j=k+1

          The terms are not computed individually; instead the incomplete
          beta integral is employed, according to the formula

          y = nbdtrc( k, n, p ) = incbet( k+1, n, 1-p ).

          The arguments must be positive, with p ranging from 0 to 1.

          ACCURACY:

          Tested at random points (a,b,p), with p between 0 and 1.

          a,b                     Relative error:
           arithmetic  domain     # trials      peak         rms
              IEEE     0,100       100000      1.7e-13     8.8e-15
           See also incbet.c.

*nbdtrc*: Complemented negative binomial distribution
          SYNOPSIS:

          # int k, n;
          # double p, y, nbdtrc();

          $y = nbdtrc( $k, $n, $p );

          DESCRIPTION:

          Returns the sum of the terms k+1 to infinity of the negative
          binomial distribution:

          inf
          --  ( n+j-1 )   n      j
          >   (       )  p  (1-p)
          --  (   j   )
            j=k+1

          The terms are not computed individually; instead the incomplete
          beta integral is employed, according to the formula

          y = nbdtrc( k, n, p ) = incbet( k+1, n, 1-p ).

          The arguments must be positive, with p ranging from 0 to 1.

          ACCURACY:

          See incbet.c.

*nbdtri*: Functional inverse of negative binomial distribution
          SYNOPSIS:

          # int k, n;
          # double p, y, nbdtri();

          $p = nbdtri( $k, $n, $y );

          DESCRIPTION:

          Finds the argument p such that nbdtr(k,n,p) is equal to y.

          ACCURACY:

          Tested at random points (a,b,y), with y between 0 and 1.

          a,b                     Relative error:
           arithmetic  domain     # trials      peak         rms
              IEEE     0,100       100000      1.5e-14     8.5e-16
           See also incbi.c.

*ndtr*: Normal distribution function
          SYNOPSIS:

          # double x, y, ndtr();

          $y = ndtr( $x );

          DESCRIPTION:

          Returns the area under the Gaussian probability density
          function, integrated from minus infinity to x:

          x
           -
                             1        | |          2
              ndtr(x)  = ---------    |    exp( - t /2 ) dt
                         sqrt(2pi)  | |
                                     -
                                    -inf.

          =  ( 1 + erf(z) ) / 2

          where z = x/sqrt(2). Computation is via the functions
          erf and erfc.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC      -13,0         8000       2.1e-15     4.8e-16
              IEEE     -13,0        30000       3.4e-14     6.7e-15

          ERROR MESSAGES:

          message         condition         value returned
           erfc underflow    x > 37.519379347       0.0

erf: Error function
          SYNOPSIS:

          # double x, y, erf();

          $y = erf( $x );

          DESCRIPTION:

          The integral is

          x
           -
                           2         | |          2
             erf(x)  =  --------     |    exp( - t  ) dt.
                        sqrt(pi)   | |
                                    -
          0

          The magnitude of x is limited to 9.231948545 for DEC
          arithmetic; 1 or -1 is returned outside this range.

          For 0 <= |x| < 1, erf(x) = x * P4(x**2)/Q5(x**2); otherwise
          erf(x) = 1 - erfc(x).

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       0,1         14000       4.7e-17     1.5e-17
              IEEE      0,1         30000       3.7e-16     1.0e-16

erfc: Complementary error function
          SYNOPSIS:

          # double x, y, erfc();

          $y = erfc( $x );

          DESCRIPTION:

          1 - erf(x) =

          inf.
            -
                            2         | |          2
             erfc(x)  =  --------     |    exp( - t  ) dt
                         sqrt(pi)   | |
          -
           x

          For small x, erfc(x) = 1 - erf(x); otherwise rational
          approximations are computed.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       0, 9.2319   12000       5.1e-16     1.2e-16
              IEEE      0,26.6417   30000       5.7e-14     1.5e-14

          ERROR MESSAGES:

          message         condition              value returned
           erfc underflow    x > 9.231948545 (DEC)       0.0

ndtri: Inverse of Normal distribution function
          SYNOPSIS:

          # double x, y, ndtri();

          $x = ndtri( $y );

          DESCRIPTION:

          Returns the argument, x, for which the area under the
          Gaussian probability density function (integrated from
          minus infinity to x) is equal to y.

          For small arguments 0 < y < exp(-2), the program computes
          z = sqrt( -2.0 * log(y) );  then the approximation is
          x = z - log(z)/z  - (1/z) P(1/z) / Q(1/z).
          There are two rational functions P/Q, one for 0 < y < exp(-32)
          and the other for y up to exp(-2).  For larger arguments,
          w = y - 0.5, and  x/sqrt(2pi) = w + w**3 R(w**2)/S(w**2)).

          ACCURACY:

          Relative error:
           arithmetic   domain        # trials      peak         rms
              DEC      0.125, 1         5500       9.5e-17     2.1e-17
              DEC      6e-39, 0.135     3500       5.7e-17     1.3e-17
              IEEE     0.125, 1        20000       7.2e-16     1.3e-16
              IEEE     3e-308, 0.135   50000       4.6e-16     9.8e-17

          ERROR MESSAGES:

          message         condition    value returned
           ndtri domain       x <= 0        -MAXNUM
           ndtri domain       x >= 1         MAXNUM

*pdtr*: Poisson distribution
          SYNOPSIS:

          # int k;
          # double m, y, pdtr();

          $y = pdtr( $k, $m );

          DESCRIPTION:

          Returns the sum of the first k terms of the Poisson
          distribution:

          k         j
          --   -m  m
          >   e    --
          --       j!
            j=0

          The terms are not summed directly; instead the incomplete
          gamma integral is employed, according to the relation

          y = pdtr( k, m ) = igamc( k+1, m ).

          The arguments must both be positive.

          ACCURACY:

          See igamc().

*pdtrc*: Complemented poisson distribution
          SYNOPSIS:

          # int k;
          # double m, y, pdtrc();

          $y = pdtrc( $k, $m );

          DESCRIPTION:

          Returns the sum of the terms k+1 to infinity of the Poisson
          distribution:

          inf.       j
           --   -m  m
           >   e    --
           --       j!
          j=k+1

          The terms are not summed directly; instead the incomplete
          gamma integral is employed, according to the formula

          y = pdtrc( k, m ) = igam( k+1, m ).

          The arguments must both be positive.

          ACCURACY:

          See igam.c.

*pdtri*: Inverse Poisson distribution
          SYNOPSIS:

          # int k;
          # double m, y, pdtr();

          $m = pdtri( $k, $y );

          DESCRIPTION:

          Finds the Poisson variable x such that the integral
          from 0 to x of the Poisson density is equal to the
          given probability y.

          This is accomplished using the inverse gamma integral
          function and the relation

          m = igami( k+1, y ).

          ACCURACY:

          See igami.c.

          ERROR MESSAGES:

          message         condition      value returned
           pdtri domain    y < 0 or y >= 1       0.0
                            k < 0

pow: Power function
          SYNOPSIS:

          # double x, y, z, pow();

          $z = pow( $x, $y );

          DESCRIPTION:

          Computes x raised to the yth power.  Analytically,

          x**y  =  exp( y log(x) ).

          Following Cody and Waite, this program uses a lookup table
          of 2**-i/16 and pseudo extended precision arithmetic to
          obtain an extra three bits of accuracy in both the logarithm
          and the exponential.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              IEEE     -26,26       30000      4.2e-16      7.7e-17
              DEC      -26,26       60000      4.8e-17      9.1e-18
           1/26 < x < 26, with log(x) uniformly distributed.
           -26 < y < 26, y uniformly distributed.
              IEEE     0,8700       30000      1.5e-14      2.1e-15
           0.99 < x < 1.01, 0 < y < 8700, uniformly distributed.

          ERROR MESSAGES:

          message         condition      value returned
           pow overflow     x**y > MAXNUM      INFINITY
           pow underflow   x**y < 1/MAXNUM       0.0
           pow domain      x<0 and y noninteger  0.0

*powi*: Real raised to integer power
          SYNOPSIS:

          # double x, y, powi();
          # int n;

          $y = powi( $x, $n );

          DESCRIPTION:

          Returns argument x raised to the nth power.
          The routine efficiently decomposes n as a sum of powers of
          two. The desired power is a product of two-to-the-kth
          powers of x.  Thus to compute the 32767 power of x requires
          28 multiplications instead of 32767 multiplications.

          ACCURACY:

          Relative error:
           arithmetic   x domain   n domain  # trials      peak         rms
              DEC       .04,26     -26,26    100000       2.7e-16     4.3e-17
              IEEE      .04,26     -26,26     50000       2.0e-15     3.8e-16
              IEEE        1,2    -1022,1023   50000       8.6e-14     1.6e-14

          Returns MAXNUM on overflow, zero on underflow.

*psi*: Psi (digamma) function
          SYNOPSIS:

          # double x, y, psi();

          $y = psi( $x );

          DESCRIPTION:

          d      -
             psi(x)  =  -- ln | (x)
          dx

          is the logarithmic derivative of the gamma function.
          For integer x,
                            n-1
                             -
          psi(n) = -EUL  +   >  1/k.
                             -
                            k=1

          This formula is used for 0 < n <= 10.  If x is negative, it
          is transformed to a positive argument by the reflection
          formula  psi(1-x) = psi(x) + pi cot(pi x).
          For general positive x, the argument is made greater than 10
          using the recurrence  psi(x+1) = psi(x) + 1/x.
          Then the following asymptotic expansion is applied:

          inf.   B
           -      2k
           psi(x) = log(x) - 1/2x -   >   -------
           -        2k
          k=1   2k x

          where the B2k are Bernoulli numbers.

          ACCURACY:
             Relative error (except absolute when |psi| < 1):
          arithmetic   domain     # trials      peak         rms
             DEC       0,30         2500       1.7e-16     2.0e-17
             IEEE      0,30        30000       1.3e-15     1.4e-16
             IEEE      -30,0       40000       1.5e-15     2.2e-16

          ERROR MESSAGES:
              message         condition      value returned
          psi singularity    x integer <=0      MAXNUM

*rgamma*: Reciprocal gamma function
          SYNOPSIS:

          # double x, y, rgamma();

          $y = rgamma( $x );

          DESCRIPTION:

          Returns one divided by the gamma function of the argument.

          The function is approximated by a Chebyshev expansion in
          the interval [0,1].  Range reduction is by recurrence
          for arguments between -34.034 and +34.84425627277176174.
          1/MAXNUM is returned for positive arguments outside this
          range.  For arguments less than -34.034 the cosecant
          reflection formula is applied; lograrithms are employed
          to avoid unnecessary overflow.

          The reciprocal gamma function has no singularities,
          but overflow and underflow may occur for large arguments.
          These conditions return either MAXNUM or 1/MAXNUM with
          appropriate sign.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC      -30,+30       4000       1.2e-16     1.8e-17
              IEEE     -30,+30      30000       1.1e-15     2.0e-16
           For arguments less than -34.034 the peak error is on the
           order of 5e-15 (DEC), excepting overflow or underflow.

round: Round double to nearest or even integer valued double
          SYNOPSIS:

          # double x, y, round();

          $y = round( $x );

          DESCRIPTION:

          Returns the nearest integer to x as a double precision
          floating point result.  If x ends in 0.5 exactly, the
          nearest even integer is chosen.

          ACCURACY:

          If x is greater than 1/(2*MACHEP), its closest machine
          representation is already an integer, so rounding does
          not change it.

*shichi*: Hyperbolic sine and cosine integrals
          SYNOPSIS:

          # double x, Chi, Shi, shichi();

          ($flag, $Shi, $Chi) = shichi( $x );

          DESCRIPTION:

          Approximates the integrals

          x
          -
                                     | |   cosh t - 1
             Chi(x) = eul + ln x +   |    -----------  dt,
                                   | |          t
                                    -
                                    0

          x
          -
                        | |  sinh t
             Shi(x) =   |    ------  dt
                      | |       t
                       -
                       0

          where eul = 0.57721566490153286061 is Euler's constant.
          The integrals are evaluated by power series for x < 8
          and by Chebyshev expansions for x between 8 and 88.
          For large x, both functions approach exp(x)/2x.
          Arguments greater than 88 in magnitude return MAXNUM.

          ACCURACY:

          Test interval 0 to 88.
                               Relative error:
          arithmetic   function  # trials      peak         rms
             DEC          Shi       3000       9.1e-17
             IEEE         Shi      30000       6.9e-16     1.6e-16
                 Absolute error, except relative when |Chi| > 1:
             DEC          Chi       2500       9.3e-17
             IEEE         Chi      30000       8.4e-16     1.4e-16

*sici*: Sine and cosine integrals
          SYNOPSIS:

          # double x, Ci, Si, sici();

          ($flag, $Si, $Ci) = sici( $x );

          DESCRIPTION:

          Evaluates the integrals

          x
          -
                                   |  cos t - 1
             Ci(x) = eul + ln x +  |  --------- dt,
                                   |      t
                                  -
                                   0
                       x
                       -
                      |  sin t
             Si(x) =  |  ----- dt
                      |    t
                     -
                      0

          where eul = 0.57721566490153286061 is Euler's constant.
          The integrals are approximated by rational functions.
          For x > 8 auxiliary functions f(x) and g(x) are employed
          such that

          Ci(x) = f(x) sin(x) - g(x) cos(x)
          Si(x) = pi/2 - f(x) cos(x) - g(x) sin(x)

          ACCURACY:
             Test interval = [0,50].
          Absolute error, except relative when > 1:
          arithmetic   function   # trials      peak         rms
             IEEE        Si        30000       4.4e-16     7.3e-17
             IEEE        Ci        30000       6.9e-16     5.1e-17
             DEC         Si         5000       4.4e-17     9.0e-18
             DEC         Ci         5300       7.9e-17     5.2e-18

sin: Circular sine
          SYNOPSIS:

          # double x, y, sin();

          $y = sin( $x );

          DESCRIPTION:

          Range reduction is into intervals of pi/4.  The reduction
          error is nearly eliminated by contriving an extended precision
          modular arithmetic.

          Two polynomial approximating functions are employed.
          Between 0 and pi/4 the sine is approximated by
               x  +  x**3 P(x**2).
          Between pi/4 and pi/2 the cosine is represented as
               1  -  x**2 Q(x**2).

          ACCURACY:

          Relative error:
           arithmetic   domain      # trials      peak         rms
              DEC       0, 10       150000       3.0e-17     7.8e-18
              IEEE -1.07e9,+1.07e9  130000       2.1e-16     5.4e-17

           ERROR MESSAGES:

          message           condition        value returned
           sin total loss   x > 1.073741824e9      0.0

          Partial loss of accuracy begins to occur at x = 2**30
          = 1.074e9.  The loss is not gradual, but jumps suddenly to
          about 1 part in 10e7.  Results may be meaningless for
          x > 2**49 = 5.6e14.  The routine as implemented flags a
          TLOSS error for x > 2**30 and returns 0.0.

cos: Circular cosine
          SYNOPSIS:

          # double x, y, cos();

          $y = cos( $x );

          DESCRIPTION:

          Range reduction is into intervals of pi/4.  The reduction
          error is nearly eliminated by contriving an extended precision
          modular arithmetic.

          Two polynomial approximating functions are employed.
          Between 0 and pi/4 the cosine is approximated by
               1  -  x**2 Q(x**2).
          Between pi/4 and pi/2 the sine is represented as
               x  +  x**3 P(x**2).

          ACCURACY:

          Relative error:
           arithmetic   domain      # trials      peak         rms
              IEEE -1.07e9,+1.07e9  130000       2.1e-16     5.4e-17
              DEC        0,+1.07e9   17000       3.0e-17     7.2e-18

*sindg*: Circular sine of angle in degrees
          SYNOPSIS:

          # double x, y, sindg();

          $y = sindg( $x );

          DESCRIPTION:

          Range reduction is into intervals of 45 degrees.

          Two polynomial approximating functions are employed.
          Between 0 and pi/4 the sine is approximated by
               x  +  x**3 P(x**2).
          Between pi/4 and pi/2 the cosine is represented as
               1  -  x**2 P(x**2).

          ACCURACY:

          Relative error:
           arithmetic   domain      # trials      peak         rms
              DEC       +-1000        3100      3.3e-17      9.0e-18
              IEEE      +-1000       30000      2.3e-16      5.6e-17

           ERROR MESSAGES:

          message           condition        value returned
           sindg total loss   x > 8.0e14 (DEC)      0.0
                           x > 1.0e14 (IEEE)

*cosdg*: Circular cosine of angle in degrees
          SYNOPSIS:

          # double x, y, cosdg();

          $y = cosdg( $x );

          DESCRIPTION:

          Range reduction is into intervals of 45 degrees.

          Two polynomial approximating functions are employed.
          Between 0 and pi/4 the cosine is approximated by
               1  -  x**2 P(x**2).
          Between pi/4 and pi/2 the sine is represented as
               x  +  x**3 P(x**2).

          ACCURACY:

          Relative error:
           arithmetic   domain      # trials      peak         rms
              DEC      +-1000         3400       3.5e-17     9.1e-18
              IEEE     +-1000        30000       2.1e-16     5.7e-17
            See also sin().

sinh: Hyperbolic sine
          SYNOPSIS:

          # double x, y, sinh();

          $y = sinh( $x );

          DESCRIPTION:

          Returns hyperbolic sine of argument in the range MINLOG to
          MAXLOG.

          The range is partitioned into two segments.  If |x| <= 1, a
          rational function of the form x + x**3 P(x)/Q(x) is employed.
          Otherwise the calculation is sinh(x) = ( exp(x) - exp(-x) )/2.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC      +- 88        50000       4.0e-17     7.7e-18
              IEEE     +-MAXLOG     30000       2.6e-16     5.7e-17

*spence*: Dilogarithm
          SYNOPSIS:

          # double x, y, spence();

          $y = spence( $x );

          DESCRIPTION:

          Computes the integral

          x
          -
                             | | log t
           spence(x)  =  -   |   ----- dt
                           | |   t - 1
                            -
                            1

          for x >= 0.  A rational approximation gives the integral in
          the interval (0.5, 1.5).  Transformation formulas for 1/x
          and 1-x are employed outside the basic expansion range.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              IEEE      0,4         30000       3.9e-15     5.4e-16
              DEC       0,4          3000       2.5e-16     4.5e-17

sqrt: Square root
          SYNOPSIS:

          # double x, y, sqrt();

          $y = sqrt( $x );

          DESCRIPTION:

          Returns the square root of x.

          Range reduction involves isolating the power of two of the
          argument and using a polynomial approximation to obtain
          a rough value for the square root.  Then Heron's iteration
          is used three times to converge to an accurate value.

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       0, 10       60000       2.1e-17     7.9e-18
              IEEE      0,1.7e308   30000       1.7e-16     6.3e-17

          ERROR MESSAGES:

          message         condition      value returned
           sqrt domain        x < 0            0.0

*stdtr*: Student's t distribution
          SYNOPSIS:

          # double t, stdtr();
          short k;

          $y = stdtr( $k, $t );

          DESCRIPTION:

          Computes the integral from minus infinity to t of the Student
          t distribution with integer k > 0 degrees of freedom:

          t
          -
                                               | |
                        -                      |         2   -(k+1)/2
                       | ( (k+1)/2 )           |  (     x   )
                 ----------------------        |  ( 1 + --- )        dx
                               -               |  (      k  )
                 sqrt( k pi ) | ( k/2 )        |
                                             | |
                                              -
                                             -inf.

           Relation to incomplete beta integral:

          1 - stdtr(k,t) = 0.5 * incbet( k/2, 1/2, z )
           where
          z = k/(k + t**2).

          For t < -2, this is the method of computation.  For higher t,
          a direct method is derived from integration by parts.
          Since the function is symmetric about t=0, the area under the
          right tail of the density is found by calling the function
          with -t instead of t.

          ACCURACY:

          Tested at random 1 <= k <= 25.  The "domain" refers to t.
                               Relative error:
          arithmetic   domain     # trials      peak         rms
             IEEE     -100,-2      50000       5.9e-15     1.4e-15
             IEEE     -2,100      500000       2.7e-15     4.9e-17

*stdtri*: Functional inverse of Student's t distribution
          SYNOPSIS:

          # double p, t, stdtri();
          # int k;

          $t = stdtri( $k, $p );

          DESCRIPTION:

          Given probability p, finds the argument t such that stdtr(k,t)
          is equal to p.

          ACCURACY:

          Tested at random 1 <= k <= 100.  The "domain" refers to p:
                               Relative error:
          arithmetic   domain     # trials      peak         rms
             IEEE    .001,.999     25000       5.7e-15     8.0e-16
             IEEE    10^-6,.001    25000       2.0e-12     2.9e-14

*struve*: Struve function
          SYNOPSIS:

          # double v, x, y, struve();

          $y = struve( $v, $x );

          DESCRIPTION:

          Computes the Struve function Hv(x) of order v, argument x.
          Negative x is rejected unless v is an integer.

          ACCURACY:

          Not accurately characterized, but spot checked against tables.

*onef2*: Hypergeometric function 1F2
          SYNOPSIS:

          # double a, b, c, x, value;

          # double *err;

          ($value, $err) = onef2( $a, $b, $c, $x)

          ACCURACY:

          Not accurately characterized, but spot checked against tables.

*threef0*: Hypergeometric function 3F0
          SYNOPSIS:

          # double a, b, c, x, value;

          # double *err;

          ($value, $err) = threef0( $a, $b, $c, $x )

          ACCURACY:

          Not accurately characterized, but spot checked against tables.

*yv*: Bessel function Yv with noninteger v
          SYNOPSIS:

          # double v, x;

          # double yv( v, x );

          $y = yv( $v, $x );

          ACCURACY:

          Not accurately characterized, but spot checked against tables.

tan: Circular tangent
          SYNOPSIS:

          # double x, y, tan();

          $y = tan( $x );

          DESCRIPTION:

          Returns the circular tangent of the radian argument x.

          Range reduction is modulo pi/4.  A rational function
                x + x**3 P(x**2)/Q(x**2)
          is employed in the basic interval [0, pi/4].

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC      +-1.07e9      44000      4.1e-17     1.0e-17
              IEEE     +-1.07e9      30000      2.9e-16     8.1e-17

          ERROR MESSAGES:

          message         condition          value returned
           tan total loss   x > 1.073741824e9     0.0

*cot*: Circular cotangent
          SYNOPSIS:

          # double x, y, cot();

          $y = cot( $x );

          DESCRIPTION:

          Returns the circular cotangent of the radian argument x.

          Range reduction is modulo pi/4.  A rational function
                x + x**3 P(x**2)/Q(x**2)
          is employed in the basic interval [0, pi/4].

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              IEEE     +-1.07e9      30000      2.9e-16     8.2e-17

          ERROR MESSAGES:

          message         condition          value returned
           cot total loss   x > 1.073741824e9       0.0
           cot singularity  x = 0                  INFINITY

*tandg*: Circular tangent of argument in degrees
          SYNOPSIS:

          # double x, y, tandg();

          $y = tandg( $x );

          DESCRIPTION:

          Returns the circular tangent of the argument x in degrees.

          Range reduction is modulo pi/4.  A rational function
                x + x**3 P(x**2)/Q(x**2)
          is employed in the basic interval [0, pi/4].

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC      0,10          8000      3.4e-17      1.2e-17
              IEEE     0,10         30000      3.2e-16      8.4e-17

          ERROR MESSAGES:

          message         condition          value returned
           tandg total loss   x > 8.0e14 (DEC)      0.0
                           x > 1.0e14 (IEEE)
           tandg singularity  x = 180 k  +  90     MAXNUM

*cotdg*: Circular cotangent of argument in degrees
          SYNOPSIS:

          # double x, y, cotdg();

          $y = cotdg( $x );

          DESCRIPTION:

          Returns the circular cotangent of the argument x in degrees.

          Range reduction is modulo pi/4.  A rational function
                x + x**3 P(x**2)/Q(x**2)
          is employed in the basic interval [0, pi/4].

          ERROR MESSAGES:

          message         condition          value returned
           cotdg total loss   x > 8.0e14 (DEC)      0.0
                           x > 1.0e14 (IEEE)
           cotdg singularity  x = 180 k            MAXNUM

tanh: Hyperbolic tangent
          SYNOPSIS:

          # double x, y, tanh();

          $y = tanh( $x );

          DESCRIPTION:

          Returns hyperbolic tangent of argument in the range MINLOG to
          MAXLOG.

          A rational function is used for |x| < 0.625.  The form
          x + x**3 P(x)/Q(x) of Cody _& Waite is employed.
          Otherwise,
             tanh(x) = sinh(x)/cosh(x) = 1  -  2/(exp(2x) + 1).

          ACCURACY:

          Relative error:
           arithmetic   domain     # trials      peak         rms
              DEC       -2,2        50000       3.3e-17     6.4e-18
              IEEE      -2,2        30000       2.5e-16     5.8e-17

*unity*: Relative error approximations for function arguments near unity.
          SYNOPSIS:

     #    log1p(x) = log(1+x)

     $y = log1p( $x );

     #    expm1(x) = exp(x) - 1

          $y = expm1( $x );

     #    cosm1(x) = cos(x) - 1

          $y = cosm1( $x );

*yn*: Bessel function of second kind of integer order
          SYNOPSIS:

          # double x, y, yn();
          # int n;

          $y = yn( $n, $x );

          DESCRIPTION:

          Returns Bessel function of order n, where n is a
          (possibly negative) integer.

          The function is evaluated by forward recurrence on
          n, starting with values computed by the routines
          y0() and y1().

          If n = 0 or 1 the routine for y0 or y1 is called
          directly.

          ACCURACY:

          Absolute error, except relative
          when y > 1:
           arithmetic   domain     # trials      peak         rms
              DEC       0, 30        2200       2.9e-16     5.3e-17
              IEEE      0, 30       30000       3.4e-15     4.3e-16

          ERROR MESSAGES:

          message         condition      value returned
           yn singularity   x = 0              MAXNUM
           yn overflow                         MAXNUM

          Spot checked against tables for x, n between 0 and 100.

*zeta*: Riemann zeta function of two arguments
          SYNOPSIS:

          # double x, q, y, zeta();

          $y = zeta( $x, $q );

          DESCRIPTION:

          inf.
           -        -x
             zeta(x,q)  =   >   (k+q)
           -
          k=0

          where x > 1 and q is not a negative integer or zero.
          The Euler-Maclaurin summation formula is used to obtain
          the expansion

          n
          -       -x
           zeta(x,q)  =   >  (k+q)
          -
                         k=1

          1-x                 inf.  B   x(x+1)...(x+2j)
                (n+q)           1         -     2j
            +  ---------  -  -------  +   >    --------------------
                  x-1              x      -                   x+2j+1
                  2(n+q)      j=1       (2j)! (n+q)

          where the B2j are Bernoulli numbers.  Note that (see zetac.c)
          zeta(x,1) = zetac(x) + 1.

          ACCURACY:

          REFERENCE:

          Gradshteyn, I. S., and I. M. Ryzhik, Tables of Integrals,
          Series, and Products, p. 1073; Academic Press, 1980.

*zetac*: Riemann zeta function
          SYNOPSIS:

          # double x, y, zetac();

          $y = zetac( $x );

          DESCRIPTION:

          inf.
           -    -x
             zetac(x)  =   >   k   ,   x > 1,
           -
          k=2

          is related to the Riemann zeta function by

          Riemann zeta(x) = zetac(x) + 1.

          Extension of the function definition for x < 1 is implemented.
          Zero is returned for x > log2(MAXNUM).

          An overflow error may occur for large negative x, due to the
          gamma function in the reflection formula.

          ACCURACY:

          Tabulated values have full machine accuracy.

          Relative error:
           arithmetic   domain     # trials      peak         rms
              IEEE      1,50        10000       9.8e-16	    1.3e-16
              DEC       1,50         2000       1.1e-16     1.9e-17

TODO
====

   * Make the configuration of mconf.h automatic.

   * Include the rest of the routines in the cephes library, such as
     polynomial and matrix manipulation functions; this will involve
     writing typemaps for arrays.

BUGS
====

     Please report any to Randy Kobes <randy@theoryx5.uwinnipeg.ca>

SEE ALSO
========

   For interfaces to programs which can do symbolic manipulation, see
PDL, `Math::Pari' in this node, and `Math::ematica' in this
node.  For a command line interface to the routines of *Math::Cephes*, see
the included `pmath' script. For a different interface to the fraction and
complex number routines, see Math/Cephes/Fraction,
and Math/Cephes/Complex.

COPYRIGHT
=========

   The C code for the Cephes Math Library is Copyright 1984, 1987, 1989 by
Stephen L. Moshier, and is available at http://www.netlib.org/cephes/.
Direct inquiries to 30 Frost Street, Cambridge, MA 02140.

   The perl interface is copyright 2000 by Randy Kobes.  This library is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Perl interface to the cephes complex number routines
****************************************************

NAME
====

     Math::Cephes::Complex - Perl interface to the cephes complex number routines

SYNOPSIS
========

     use Math::Cephes::Complex qw(cmplx);
     my $z1 = cmplx(2,3);          # $z1 = 2 + 3 i
     my $z2 = cmplx(3,4);          # $z2 = 3 + 4 i
     my $z3 = $z1->radd($z2);      # $z3 = $z1 + $z2

DESCRIPTION
===========

     This module is a layer on top of the basic routines in the
     cephes math library to handle complex numbers. A complex
     number is created via any of the following syntaxes:

     my $f = Math::Cephes::Complex->new(3, 2);   # $f = 3 + 2 i
     my $g = new Math::Cephes::Complex(5, 3);    # $g = 5 + 3 i
     my $h = cmplx(7, 5);                        # $h = 7 + 5 i

     the last one being available by importing I<cmplx>. If no arguments
     are specified, as in

     my $h = cmplx();

     then the defaults $z = 0 + 0 i are assumed. The real and imaginary
     part of a complex number are represented respectively by

     $f->{r}; $f->{i}

     and can be set according to

     $f->{i} = 4; $f->{i} = 9;

     The complex number can be printed out as

     print $f->as_string;

     A summary of the usage is as follows.

*csin*: Complex circular sine
          SYNOPSIS:

          # void csin();
          # cmplx z, w;

          $z = cmplx(2, 3);    # $z = 2 + 3 i
          $w = $z->csin;
          print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w
          print $w->as_string;           # prints $w as Re($w) + i Im($w)

          DESCRIPTION:

          If
              z = x + iy,

          then

          w = sin x  cosh y  +  i cos x sinh y.

*ccos*: Complex circular cosine
          SYNOPSIS:

          # void ccos();
          # cmplx z, w;

          $z = cmplx(2, 3);    # $z = 2 + 3 i
          $w = $z->ccos;
          print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w
          print $w->as_string;           # prints $w as Re($w) + i Im($w)

          DESCRIPTION:

          If
              z = x + iy,

          then

          w = cos x  cosh y  -  i sin x sinh y.

*ctan*: Complex circular tangent
          SYNOPSIS:

          # void ctan();
          # cmplx z, w;

          $z = cmplx(2, 3);    # $z = 2 + 3 i
          $w = $z->ctan;
          print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w
          print $w->as_string;           # prints $w as Re($w) + i Im($w)

          DESCRIPTION:

          If
              z = x + iy,

          then

          sin 2x  +  i sinh 2y
               w  =  --------------------.
           cos 2x  +  cosh 2y

          On the real axis the denominator is zero at odd multiples
          of PI/2.  The denominator is evaluated by its Taylor
          series near these points.

*ccot*: Complex circular cotangent
          SYNOPSIS:

          # void ccot();
          # cmplx z, w;

          $z = cmplx(2, 3);    # $z = 2 + 3 i
          $w = $z->ccot;
          print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w
          print $w->as_string;           # prints $w as Re($w) + i Im($w)

          DESCRIPTION:

          If
              z = x + iy,

          then

          sin 2x  -  i sinh 2y
               w  =  --------------------.
           cosh 2y  -  cos 2x

          On the real axis, the denominator has zeros at even
          multiples of PI/2.  Near these points it is evaluated
          by a Taylor series.

*casin*: Complex circular arc sine
          SYNOPSIS:

          # void casin();
          # cmplx z, w;

          $z = cmplx(2, 3);    # $z = 2 + 3 i
          $w = $z->casin;
          print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w
          print $w->as_string;           # prints $w as Re($w) + i Im($w)

          DESCRIPTION:

          Inverse complex sine:

          2
           w = -i clog( iz + csqrt( 1 - z ) ).

*cacos*: Complex circular arc cosine
          SYNOPSIS:

          # void cacos();
          # cmplx z, w;

          $z = cmplx(2, 3);    # $z = 2 + 3 i
          $w = $z->cacos;
          print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w
          print $w->as_string;           # prints $w as Re($w) + i Im($w)

          DESCRIPTION:

          w = arccos z  =  PI/2 - arcsin z.

*catan*: Complex circular arc tangent
          SYNOPSIS:

          # void catan();
          # cmplx z, w;

          $z = cmplx(2, 3);    # $z = 2 + 3 i
          $w = $z->catan;
          print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w
          print $w->as_string;           # prints $w as Re($w) + i Im($w)

          DESCRIPTION:

          If
              z = x + iy,

          then
                   1       (    2x     )
          Re w  =  - arctan(-----------)  +  k PI
                   2       (     2    2)
                           (1 - x  - y )

          ( 2         2)
                    1    (x  +  (y+1) )
           Im w  =  - log(------------)
                    4    ( 2         2)
          (x  +  (y-1) )

          Where k is an arbitrary integer.

*csinh*: Complex hyperbolic sine
          SYNOPSIS:

          # void csinh();
          # cmplx z, w;

           $z = cmplx(2, 3);    # $z = 2 + 3 i
           $w = $z->csinh;
           print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w
           print $w->as_string;           # prints $w as Re($w) + i Im($w)

          DESCRIPTION:
          csinh z = (cexp(z) - cexp(-z))/2
                    = sinh x * cos y  +  i cosh x * sin y .

*casinh*: Complex inverse hyperbolic sine
          SYNOPSIS:

          # void casinh();
          # cmplx z, w;

           $z = cmplx(2, 3);    # $z = 2 + 3 i
           $w = $z->casinh;
           print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w
           print $w->as_string;           # prints $w as Re($w) + i Im($w)

          DESCRIPTION:

          casinh z = -i casin iz .

*ccosh*: Complex hyperbolic cosine
          SYNOPSIS:

          # void ccosh();
          # cmplx z, w;

           $z = cmplx(2, 3);    # $z = 2 + 3 i
           $w = $z->ccosh;
           print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w
           print $w->as_string;           # prints $w as Re($w) + i Im($w)

          DESCRIPTION:

          ccosh(z) = cosh x  cos y + i sinh x sin y .

*cacosh*: Complex inverse hyperbolic cosine
          SYNOPSIS:
          # void cacosh();
            # cmplx z, w;

           $z = cmplx(2, 3);    # $z = 2 + 3 i
           $w = $z->cacosh;
           print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w
           print $w->as_string;           # prints $w as Re($w) + i Im($w)
          DESCRIPTION:
          acosh z = i acos z .

*ctanh*: Complex hyperbolic tangent
          SYNOPSIS:

          # void ctanh();
          # cmplx z, w;

          $z = cmplx(2, 3);    # $z = 2 + 3 i
          $w = $z->ctanh;
          print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w
          print $w->as_string;           # prints $w as Re($w) + i Im($w)

          DESCRIPTION:

          tanh z = (sinh 2x  +  i sin 2y) / (cosh 2x + cos 2y) .

*catanh*: Complex inverse hyperbolic tangent
          SYNOPSIS:

          # void catanh();
          # cmplx z, w;

           $z = cmplx(2, 3);    # $z = 2 + 3 i
           $w = $z->catanh;
           print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w
           print $w->as_string;           # prints $w as Re($w) + i Im($w)

          DESCRIPTION:

          Inverse tanh, equal to  -i catan (iz);

*cpow*: Complex power function
          SYNOPSIS:

          # void cpow();
          # cmplx a, z, w;

           $a = cmplx(5, 6);    # $z = 5 + 6 i
           $z = cmplx(2, 3);    # $z = 2 + 3 i
           $w = $a->cpow($z);
           print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w
           print $w->as_string;           # prints $w as Re($w) + i Im($w)

          DESCRIPTION:

          Raises complex A to the complex Zth power.
          Definition is per AMS55 # 4.2.8,
          analytically equivalent to cpow(a,z) = cexp(z clog(a)).

*cmplx*: Complex number arithmetic
          SYNOPSIS:

          # typedef struct {
          #     double r;     real part
          #     double i;     imaginary part
          #    }cmplx;

          # cmplx *a, *b, *c;

          $a = cmplx(3, 5);   # $a = 3 + 5 i
          $b = cmplx(2, 3);   # $b = 2 + 3 i

          $c = $a->cadd( $b );  #   c = a + b
          $c = $a->csub( $b );  #   c = a - b
          $c = $a->cmul( $b );  #   c = a * b
          $c = $a->cdiv( $b );  #   c = a / b
          $c = $a->cneg;        #   c = -a
          $c = $a->cmov;        #   c = a

          print $c->{r}, '  ', $c->{i};   # prints real and imaginary parts of $c
          print $c->as_string;           # prints $c as Re($c) + i Im($c)

          DESCRIPTION:

          Addition:
             c.r  =  b.r + a.r
             c.i  =  b.i + a.i

          Subtraction:
             c.r  =  b.r - a.r
             c.i  =  b.i - a.i

          Multiplication:
             c.r  =  b.r * a.r  -  b.i * a.i
             c.i  =  b.r * a.i  +  b.i * a.r

          Division:
             d    =  a.r * a.r  +  a.i * a.i
             c.r  = (b.r * a.r  + b.i * a.i)/d
             c.i  = (b.i * a.r  -  b.r * a.i)/d

*cabs*: Complex absolute value
          SYNOPSIS:

          # double a, cabs();
          # cmplx z;

          $z = cmplx(2, 3);    # $z = 2 + 3 i
          $a = cabs( $z );

          DESCRIPTION:

          If z = x + iy

          then

          a = sqrt( x**2 + y**2 ).

           Overflow and underflow are avoided by testing the magnitudes
           of x and y before squaring.  If either is outside half of
           the floating point full scale range, both are rescaled.

*csqrt*: Complex square root
          SYNOPSIS:

          # void csqrt();
          # cmplx z, w;

          $z = cmplx(2, 3);    # $z = 2 + 3 i
          $w = $z->csqrt;
          print $w->{r}, '  ', $w->{i};  # prints real and imaginary parts of $w
          print $w->as_string;           # prints $w as Re($w) + i Im($w)

          DESCRIPTION:

          If z = x + iy,  r = |z|, then

          1/2
           Im w  =  [ (r - x)/2 ]   ,

          Re w  =  y / 2 Im w.

          Note that -w is also a square root of z.  The root chosen
          is always in the upper half plane.

          Because of the potential for cancellation error in r - x,
          the result is sharpened by doing a Heron iteration
          (see sqrt.c) in complex arithmetic.

TODO
====

   * Integrate the C routines with Math::Complex.

BUGS
====

     Please report any to Randy Kobes <randy@theoryx5.uwinnipeg.ca>

SEE ALSO
========

   For the basic interface to the cephes complex number routines, see
Math/Cephes. See also Math/Complex,
for a more extensive interface to complex number routines.

COPYRIGHT
=========

   The C code for the Cephes Math Library is Copyright 1984, 1987, 1989 by
Stephen L. Moshier, and is available at http://www.netlib.org/cephes/.
Direct inquiries to 30 Frost Street, Cambridge, MA 02140.

   The perl interface is copyright 2000 by Randy Kobes.  This library is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Perl interface to the cephes math fraction routines
***************************************************

NAME
====

     Math::Cephes::Fraction - Perl interface to the cephes math fraction routines

SYNOPSIS
========

     use Math::Cephes::Fraction qw(fract);
     my $f1 = fract(2,3);          # $f1 = 2/3
     my $f2 = fract(3,4);          # $f2 = 3/4
     my $f3 = $f1->radd($f2);      # $f3 = $f1 + $f2

DESCRIPTION
===========

     This module is a layer on top of the basic routines in the
     cephes math library to handle fractions. A fraction object
     is created via any of the following syntaxes:

     my $f = Math::Cephes::Fraction->new(3, 2);  # $f = 3/2
     my $g = new Math::Cephes::Fraction(5, 3);   # $g = 5/3
     my $h = fract(7, 5);                        # $h = 7/5

     the last one being available by importing I<:fract>. If no arguments
     are specified, as in

     my $h = fract();

     then the defaults $z = 0/1 are assumed. The numerator and
     denominator of a fraction are represented respectively by

     $f->{n}; $f->{d}

     and can be set according to

     $f->{n} = 4; $f->{d} = 9;

     The fraction can be printed out as

     print $f->as_string;

     or as a mixed fraction as

     print $f->as_mixed_string;

     These routines reduce the fraction to its basic form before printing.
     This uses the I<euclid> routine which finds the greatest common
     divisor of two numbers, as follows:

     ($gcd, $m_reduced, $n_reduced) = euclid($m, $n);

     which returns the greatest common divisor of $m and $n, as well as
     the result of reducing $m and $n by $gcd

     A summary of the basic routines is as follows.

     $x = fract(3, 4);	 #  x = 3 / 4
     $y = fract(2, 3);       #  y = 2 / 3
     $z = $x->radd( $y );    #  z = x + y
     $z = $x->rsub( $y );    #  z = x - y
     $z = $x->rmul( $y );    #  z = x * y
     $z = $x->rdiv( $y );    #  z = x / y
     print $z->{n}, ' ', $z->{d};  # prints numerator and denominator of $z
     print $z->as_string;         # prints the fraction $z
     print $z->as_mixed_string;   # converts $z to a mixed fraction, then prints it

     $m = 60;
     $n = 144;
     ($gcd, $m_reduced, $n_reduced) = euclid($m, $n);

TODO
====

   * Integrate the C routines with the `Math::Fraction' module.

BUGS
====

     Please report any to Randy Kobes <randy@theoryx5.uwinnipeg.ca>

SEE ALSO
========

   For the basic interface to the cephes fraction routines, see
Math/Cephes. See also Math/Fraction,
for a more extensive interface to fraction routines.

COPYRIGHT
=========

   The C code for the Cephes Math Library is Copyright 1984, 1987, 1989 by
Stephen L. Moshier, and is available at http://www.netlib.org/cephes/.
Direct inquiries to 30 Frost Street, Cambridge, MA 02140.

   The perl interface is copyright 2000 by Randy Kobes.  This library is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

   Math::Complex - complex numbers and associated mathematical functions

SYNOPSIS
========

     use Math::Complex;

     $z = Math::Complex->make(5, 6);
     $t = 4 - 3*i + $z;
     $j = cplxe(1, 2*pi/3);

DESCRIPTION
===========

   This package lets you create and manipulate complex numbers. By default,
Perl limits itself to real numbers, but an extra use statement brings full
complex support, along with a full set of mathematical functions typically
associated with and/or extended to complex numbers.

   If you wonder what complex numbers are, they were invented to be able
to solve the following equation:

     x*x = -1

   and by definition, the solution is noted i (engineers use *j* instead
since i usually denotes an intensity, but the name does not matter). The
number i is a pure *imaginary* number.

   The arithmetics with pure imaginary numbers works just like you would
expect it with real numbers... you just have to remember that

     i*i = -1

   so you have:

     5i + 7i = i * (5 + 7) = 12i
     4i - 3i = i * (4 - 3) = i
     4i * 2i = -8
     6i / 2i = 3
     1 / i = -i

   Complex numbers are numbers that have both a real part and an imaginary
part, and are usually noted:

     a + bi

   where a is the real part and b is the *imaginary* part. The arithmetic
with complex numbers is straightforward. You have to keep track of the
real and the imaginary parts, but otherwise the rules used for real
numbers just apply:

     (4 + 3i) + (5 - 2i) = (4 + 5) + i(3 - 2) = 9 + i
     (2 + i) * (4 - i) = 2*4 + 4i -2i -i*i = 8 + 2i + 1 = 9 + 2i

   A graphical representation of complex numbers is possible in a plane
(also called the *complex plane*, but it's really a 2D plane).  The number

     z = a + bi

   is the point whose coordinates are (a, b). Actually, it would be the
vector originating from (0, 0) to (a, b). It follows that the addition of
two complex numbers is a vectorial addition.

   Since there is a bijection between a point in the 2D plane and a complex
number (i.e. the mapping is unique and reciprocal), a complex number can
also be uniquely identified with polar coordinates:

     [rho, theta]

   where `rho' is the distance to the origin, and `theta' the angle between
the vector and the x axis. There is a notation for this using the
exponential form, which is:

     rho * exp(i * theta)

   where i is the famous imaginary number introduced above. Conversion
between this form and the cartesian form `a + bi' is immediate:

     a = rho * cos(theta)
     b = rho * sin(theta)

   which is also expressed by this formula:

     z = rho * exp(i * theta) = rho * (cos theta + i * sin theta)

   In other words, it's the projection of the vector onto the x and y
axes. Mathematicians call *rho* the norm or *modulus* and *theta* the
argument of the complex number. The norm of z will be noted `abs(z)'.

   The polar notation (also known as the trigonometric representation) is
much more handy for performing multiplications and divisions of complex
numbers, whilst the cartesian notation is better suited for additions and
subtractions. Real numbers are on the x axis, and therefore *theta* is
zero or pi.

   All the common operations that can be performed on a real number have
been defined to work on complex numbers as well, and are merely
*extensions* of the operations defined on real numbers. This means they
keep their natural meaning when there is no imaginary part, provided the
number is within their definition set.

   For instance, the sqrt routine which computes the square root of its
argument is only defined for non-negative real numbers and yields a
non-negative real number (it is an application from *R+* to *R+*).  If we
allow it to return a complex number, then it can be extended to negative
real numbers to become an application from R to C (the set of complex
numbers):

     sqrt(x) = x >= 0 ? sqrt(x) : sqrt(-x)*i

   It can also be extended to be an application from C to C, whilst its
restriction to R behaves as defined above by using the following
definition:

     sqrt(z = [r,t]) = sqrt(r) * exp(i * t/2)

   Indeed, a negative real number can be noted `[x,pi]' (the modulus x is
always non-negative, so `[x,pi]' is really -x, a negative number) and the
above definition states that

     sqrt([x,pi]) = sqrt(x) * exp(i*pi/2) = [sqrt(x),pi/2] = sqrt(x)*i

   which is exactly what we had defined for negative real numbers above.
The sqrt returns only one of the solutions: if you want the both, use the
root function.

   All the common mathematical functions defined on real numbers that are
extended to complex numbers share that same property of working *as usual*
when the imaginary part is zero (otherwise, it would not be called an
extension, would it?).

   A new operation possible on a complex number that is the identity for
real numbers is called the *conjugate*, and is noted with an horizontal
bar above the number, or `~z' here.

     z = a + bi
     	~z = a - bi

   Simple... Now look:

     z * ~z = (a + bi) * (a - bi) = a*a + b*b

   We saw that the norm of z was noted `abs(z)' and was defined as the
distance to the origin, also known as:

     rho = abs(z) = sqrt(a*a + b*b)

   so

     z * ~z = abs(z) ** 2

   If z is a pure real number (i.e. `b == 0'), then the above yields:

     a * a = abs(a) ** 2

   which is true (abs has the regular meaning for real number, i.e. stands
for the absolute value). This example explains why the norm of z is noted
`abs(z)': it extends the abs function to complex numbers, yet is the
regular abs we know when the complex number actually has no imaginary
part... This justifies *a posteriori* our use of the abs notation for the
norm.

OPERATIONS
==========

   Given the following notations:

     z1 = a + bi = r1 * exp(i * t1)
     z2 = c + di = r2 * exp(i * t2)
     z = <any complex or real number>

   the following (overloaded) operations are supported on complex numbers:

     z1 + z2 = (a + c) + i(b + d)
     z1 - z2 = (a - c) + i(b - d)
     z1 * z2 = (r1 * r2) * exp(i * (t1 + t2))
     z1 / z2 = (r1 / r2) * exp(i * (t1 - t2))
     z1 ** z2 = exp(z2 * log z1)
     ~z = a - bi
     abs(z) = r1 = sqrt(a*a + b*b)
     sqrt(z) = sqrt(r1) * exp(i * t/2)
     exp(z) = exp(a) * exp(i * b)
     log(z) = log(r1) + i*t
     sin(z) = 1/2i (exp(i * z1) - exp(-i * z))
     cos(z) = 1/2 (exp(i * z1) + exp(-i * z))
     atan2(z1, z2) = atan(z1/z2)

   The following extra operations are supported on both real and complex
numbers:

     Re(z) = a
     Im(z) = b
     arg(z) = t
     abs(z) = r

     cbrt(z) = z ** (1/3)
     log10(z) = log(z) / log(10)
     logn(z, n) = log(z) / log(n)

     tan(z) = sin(z) / cos(z)

     csc(z) = 1 / sin(z)
     sec(z) = 1 / cos(z)
     cot(z) = 1 / tan(z)

     asin(z) = -i * log(i*z + sqrt(1-z*z))
     acos(z) = -i * log(z + i*sqrt(1-z*z))
     atan(z) = i/2 * log((i+z) / (i-z))

     acsc(z) = asin(1 / z)
     asec(z) = acos(1 / z)
     acot(z) = atan(1 / z) = -i/2 * log((i+z) / (z-i))

     sinh(z) = 1/2 (exp(z) - exp(-z))
     cosh(z) = 1/2 (exp(z) + exp(-z))
     tanh(z) = sinh(z) / cosh(z) = (exp(z) - exp(-z)) / (exp(z) + exp(-z))

     csch(z) = 1 / sinh(z)
     sech(z) = 1 / cosh(z)
     coth(z) = 1 / tanh(z)

     asinh(z) = log(z + sqrt(z*z+1))
     acosh(z) = log(z + sqrt(z*z-1))
     atanh(z) = 1/2 * log((1+z) / (1-z))

     acsch(z) = asinh(1 / z)
     asech(z) = acosh(1 / z)
     acoth(z) = atanh(1 / z) = 1/2 * log((1+z) / (z-1))

   *arg*, abs, log, *csc*, *cot*, *acsc*, *acot*, *csch*, *coth*,
*acosech*, *acotanh*, have aliases *rho*, *theta*, *ln*, *cosec*, *cotan*,
*acosec*, *acotan*, *cosech*, *cotanh*, *acosech*, *acotanh*,
respectively.  `Re', `Im', `arg', abs, `rho', and `theta' can be used also
also mutators.  The `cbrt' returns only one of the solutions: if you want
all three, use the root function.

   The root function is available to compute all the n roots of some
complex, where n is a strictly positive integer.  There are exactly n such
roots, returned as a list. Getting the number mathematicians call `j' such
that:

     1 + j + j*j = 0;

   is a simple matter of writing:

     $j = ((root(1, 3))[1];

   The kth root for `z = [r,t]' is given by:

     (root(z, n))[k] = r**(1/n) * exp(i * (t + 2*k*pi)/n)

   The spaceship comparison operator, <=>, is also defined. In order to
ensure its restriction to real numbers is conform to what you would
expect, the comparison is run on the real part of the complex number
first, and imaginary parts are compared only when the real parts match.

CREATION
========

   To create a complex number, use either:

     $z = Math::Complex->make(3, 4);
     $z = cplx(3, 4);

   if you know the cartesian form of the number, or

     $z = 3 + 4*i;

   if you like. To create a number using the polar form, use either:

     $z = Math::Complex->emake(5, pi/3);
     $x = cplxe(5, pi/3);

   instead. The first argument is the modulus, the second is the angle (in
radians, the full circle is 2*pi).  (Mnemonic: e is used as a notation for
complex numbers in the polar form).

   It is possible to write:

     $x = cplxe(-3, pi/4);

   but that will be silently converted into `[3,-3pi/4]', since the
modulus must be non-negative (it represents the distance to the origin in
the complex plane).

   It is also possible to have a complex number as either argument of
either the make or `emake': the appropriate component of the argument will
be used.

     $z1 = cplx(-2,  1);
     $z2 = cplx($z1, 4);

STRINGIFICATION
===============

   When printed, a complex number is usually shown under its cartesian
style *a+bi*, but there are legitimate cases where the polar style *[r,t]*
is more appropriate.

   By calling the class method `Math::Complex::display_format' and
supplying either `"polar"' or `"cartesian"' as an argument, you override
the default display style, which is `"cartesian"'. Not supplying any
argument returns the current settings.

   This default can be overridden on a per-number basis by calling the
`display_format' method instead. As before, not supplying any argument
returns the current display style for this number. Otherwise whatever you
specify will be the new display style for *this* particular number.

   For instance:

     use Math::Complex;

     Math::Complex::display_format('polar');
     $j = (root(1, 3))[1];
     print "j = $j\n";		# Prints "j = [1,2pi/3]"
     $j->display_format('cartesian');
     print "j = $j\n";		# Prints "j = -0.5+0.866025403784439i"

   The polar style attempts to emphasize arguments like *k*pi/n* (where n
is a positive integer and k an integer within [-9,+9]), this is called
*polar pretty-printing*.

CHANGED IN PERL 5.6
-------------------

   The `display_format' class method and the corresponding
`display_format' object method can now be called using a parameter hash
instead of just a one parameter.

   The old display format style, which can have values `"cartesian"' or
`"polar"', can be changed using the `"style"' parameter.  (The one
parameter calling convention also still works.)

   There are two new display parameters.

   The first one is `"format"', which is a sprintf()-style format string
to be used for both parts of the complex number(s).  The default is undef,
which corresponds usually (this is somewhat system-dependent) to
`"%.15g"'.  You can revert to the default by setting the format string to
undef.

     # the $j from the above example

     $j->display_format('format' => '%.5f');
     print "j = $j\n";		# Prints "j = -0.50000+0.86603i"
     $j->display_format('format' => '%.6f');
     print "j = $j\n";		# Prints "j = -0.5+0.86603i"

   Notice that this affects also the return values of the `display_format'
methods: in list context the whole parameter hash will be returned, as
opposed to only the style parameter value.  If you want to know the whole
truth for a complex number, you must call both the class method and the
object method:

   The second new display parameter is `"polar_pretty_print"', which can
be set to true or false, the default being true.  See the previous section
for what this means.

USAGE
=====

   Thanks to overloading, the handling of arithmetics with complex numbers
is simple and almost transparent.

   Here are some examples:

     use Math::Complex;

     $j = cplxe(1, 2*pi/3);	# $j ** 3 == 1
     print "j = $j, j**3 = ", $j ** 3, "\n";
     print "1 + j + j**2 = ", 1 + $j + $j**2, "\n";

     $z = -16 + 0*i;			# Force it to be a complex
     print "sqrt($z) = ", sqrt($z), "\n";

     $k = exp(i * 2*pi/3);
     print "$j - $k = ", $j - $k, "\n";

     $z->Re(3);			# Re, Im, arg, abs,
     $j->arg(2);			# (the last two aka rho, theta)
     				# can be used also as mutators.

ERRORS DUE TO DIVISION BY ZERO OR LOGARITHM OF ZERO
===================================================

   The division (/) and the following functions

     log	ln	log10	logn
     tan	sec	csc	cot
     atan	asec	acsc	acot
     tanh	sech	csch	coth
     atanh	asech	acsch	acoth

   cannot be computed for all arguments because that would mean dividing
by zero or taking logarithm of zero. These situations cause fatal runtime
errors looking like this

     cot(0): Division by zero.
     (Because in the definition of cot(0), the divisor sin(0) is 0)
     Died at ...

   or

     atanh(-1): Logarithm of zero.
     Died at...

   For the `csc', `cot', `asec', `acsc', `acot', `csch', `coth', `asech',
`acsch', the argument cannot be 0 (zero).  For the the logarithmic
functions and the atanh, `acoth', the argument cannot be 1 (one).  For the
atanh, `acoth', the argument cannot be `-1' (minus one).  For the atan,
`acot', the argument cannot be i (the imaginary unit).  For the atan,
`acoth', the argument cannot be -i (the negative imaginary unit).  For the
tan, sec, tanh, the argument cannot be *pi/2 + k * pi*, where k is any
integer.

   Note that because we are operating on approximations of real numbers,
these errors can happen when merely `too close' to the singularities
listed above.  For example `tan(2*atan2(1,1)+1e-15)' will die of division
by zero.

ERRORS DUE TO INDIGESTIBLE ARGUMENTS
====================================

   The make and `emake' accept both real and complex arguments.  When they
cannot recognize the arguments they will die with error messages like the
following

     Math::Complex::make: Cannot take real part of ...
     Math::Complex::make: Cannot take real part of ...
     Math::Complex::emake: Cannot take rho of ...
     Math::Complex::emake: Cannot take theta of ...

BUGS
====

   Saying `use Math::Complex;' exports many mathematical routines in the
caller environment and even overrides some (sqrt, log).  This is construed
as a feature by the Authors, actually... ;-)

   All routines expect to be given real or complex numbers. Don't attempt
to use BigFloat, since Perl has currently no rule to disambiguate a '+'
operation (for instance) between two overloaded entities.

   In Cray UNICOS there is some strange numerical instability that results
in root(), cos(), sin(), cosh(), sinh(), losing accuracy fast.  Beware.
The bug may be in UNICOS math libs, in UNICOS C compiler, in Math::Complex.
Whatever it is, it does not manifest itself anywhere else where Perl runs.

AUTHORS
=======

   Raphael Manfredi <`Raphael_Manfredi@pobox.com'> and Jarkko Hietaniemi
<`jhi@iki.fi'>.

   Extensive patches by Daniel S. Lewart <`d-lewart@uiuc.edu'>.

Exact Currency Math with Formatting and Rounding
************************************************

NAME
====

   Math::Currency - Exact Currency Math with Formatting and Rounding

SYNOPSIS
========

     use Math::Currency qw(Money);
     $dollar = Math::Currency->new("$12,345.67");
     $taxamt = $dollar * 0.28;
     Math::Currency->format(
     	{
     		PREFIX      =>     '',
     		SEPARATOR   =>    ' ',
     		DECIMAL     =>    ',',
     		POSTFIX     =>  ' DM',
     		FRAC_DIGITS =>      2,
     		GROUPING    =>      3,
     	});
     $deutschmark = Money(12345.67);
     $deutschmark_string = Money(12345.67)->stringify();
     # or if you already have a Math::Currency object
     $deutschmark_string = "$deutschmark";

DESCRIPTION
===========

   Currency math is actually more closely related to integer math than it
is to floating point math.  Rounding errors on addition and subtraction
are not allowed and division/multiplication should never create more
accuracy than the original values.  All currency values should round to
the closest cent or whatever the local equivalent should happen to be.

   Each currency value can have an individual format or the global currency
format can be changed to reflect local usage.  I used the suggestions in
Tom Christiansen's `PerlTootC|http:' in this node to implement translucent
attributes.  If you have set your locale values correctly, this module
will pick up your local settings or US standards if you haven't.

   All common mathematical operations are overloaded, so once you
initialize a currency variable, you can treat it like any number and the
module will do the right thing.  This module is a thin layer over
Math::FixedPrecision which is itself a layer over Math::BigFloat which is
itself a layer over Math::BigInt.  The module optionally exports a single
function Money() which can be used instead of Math::Currency->new().

AUTHOR
======

   John Peacock <jpeacock@rowman.com>

SEE ALSO
========

   perl(1).  perllocale Math::FixedPrecision

SYNOPSIS
========

     use Math::Derivative qw(Derivative1 Derivative2);
     @dydx=Derivative1(\@x,\@y);
     @d2ydx2=Derivative2(\@x,\@y);
     @d2ydx2=Derivative2(\@x,\@y,$yp0,$ypn);

DESCRIPTION
===========

   This Perl package exports functions for performing numerical first
(*Derivative1*) and second *Derivative2*) order differentiation on vectors
of data. They both take references to two arrays containing the x and y
ordinates of the data and return an array of the 1st or 2nd derivative at
the given x ordinates. *Derivative2* may optionally be given values to use
for the first dervivative at the start and end points of the data -
otherwiswe 'natural' values are used.

HISTORY
=======

   $Log: Derivative.pm,v $ Revision 1.1  1995/12/26 16:26:59  willijar
Initial revision

BUGS
====

   Let me know.

AUTHOR
======

   John A.R. Williams <J.A.R.Williams@aston.ac.uk>

Parses mathematical expressions
*******************************

NAME
====

     Math::Expr - Parses mathematical expressions

SYNOPSIS
========

     use Math::Expr;

     SetOppDB(new Math::Expr::OpperationDB('<DBFileName>'));
     $e=Parse("a+4*b-d/log(s)+f(d,e)");

DESCRIPTION
===========

     Parses mathematical expressions into a tree structure. The expressions
     may contain integers, real numbers, alphanumeric variable names,
     alphanumeric function names and most other characters might be used
     as operators. The operators can even be longer than one character!
     The only limitation is that a variable or function name may not start
     on a digit, and not all chars are accepted as operations. To be exact,
     here is the grammatic (in perl regexp notation):

     <Expr>     = -?<Elem>(<OpChr><Elem>)*
     <Elem>     = <Number>|<Var>|<Function>|\(<Expr>\)
     <Number>   = <Integer>|<Float>
     <Integer>  = \d+
     <Float>    = \d*\.\d+
     <Var>      = [a-zA-Z][a-zA-Z0-9]*(:[a-zA-Z][a-zA-Z0-9]*)?
     <Function> = [a-zA-Z][a-zA-Z0-9]*\(<Expr>(,<Expr>)*\)
     <OpChr>    = [^a-zA-Z0-9\(\)\,\.\:]+

     If the - sign is present at the beginning of an <Expr> Then a neg()
     	function is placed around it. That is to allow constructions like
     "-a*b" or "b+3*(-7)".

     A variable consists of two parts separated by a ':'-char. The first
     part is the variable name, and the second optional part is its type.
     Default type is Real.

METHODS
=======

$e=Parse($str)
--------------

   This will parse the string $str and return an expression tree, in the
form of a Math::Expr::Opp object (or in simple cases only a
Math::Expr::Var or Math::Expr::Num object).

$p = new  Math::Expr
--------------------

   This is the constructor, it creates an object which later can be used
to parse the strings.

Priority({'^'=>50, '/'=>40, '*'=>30, '-'=>20, '+'=>10})
-------------------------------------------------------

   This will set the priority of ALL the operands (there is currently no
way to change only one of them). The priority decides what should be
constructed if several operands is listed without delimiters. Eg if a+b*c
should be treated as (a+b)*c or a+(b*c). (Default is listed in header).

   The priority is global for all parsers and all expretions, so changing
it here will change it for all parsers and parsed objects.  The idea is to
use this method to initiate the system before using it.

SetOppDB($db)
-------------

   Sets the OpperationDB to be used to $db. See
Math/Expr/OpperationDB, for more info.

   This is a global variable afecting all parsers and all parsed
structures.

BUGS
====

     The parses does not handle bad strings in a decent way. If you try
     to parse a string that does not follow the specification above, all
     strange things might happen...

AUTHOR
======

     Hakan Ardo <hakan@debian.org>

SEE ALSO
========

   See Math/Expr/Opp,

A db of formulas and there properties
*************************************

NAME
====

     Math::Expr::FormulaDB - A db of formulas and there properties

SYNOPSIS
========

     require Math::Expr::FormulaDB;
     $db=new Math::Expr::FormulaDB($file);

Represents matches in algebraic expretions
******************************************

NAME
====

     Math::Expr::MatchSet - Represents matches in algebraic expretions

SYNOPSIS
========

     require Math::Expr::MatchSet;
     $s=new Math::Expr::MatchSet;
     $s->Set($pos,$match);
     $s->Get($pos);

DESCRIPTION
===========

     Two expretion can be matched in several ways, therefor we need to be
     able to represent a set of matches keyed by the matchposition (the
     subexpretion, where the match where found).

METHODS
=======

$s=new Math::Expr::MatchSet
---------------------------

     Create a new MatchSet object.

$s->Set($pos, $match)
---------------------

     Sets the match at $pos to $match.

$s->Add($pos, $match)
---------------------

     Synonyme to Set.

$s->Insert($mset)
-----------------

     Inserts all mathes in the MatchSet £mset intho $s.

$s->SetAll($var, $obj)
----------------------

     Sets the variable $var to $obj in all mathces in this set, and removes
     all matches that already had a diffrent value for the variable $var.

$s->tostr
---------

     Generates a string representation of the MatchSet, used for debugging.

$s->Get($pos)
-------------

     Returns the Match at possition $pos.

$s->Keys
--------

     Returns the positions at which there excists a match.

A node in the expretion tree, used as superclass only
*****************************************************

NAME
====

     Math::Expr::Num - A node in the expretion tree, used as superclass only

SYNOPSIS
========

     package Math::Expr::Num;
     require Math::Expr::Node;

     use Math::Expr::Node;
     use vars qw(@ISA);
     @ISA = qw(Math::Expr::Node);

DESCRIPTION
===========

     Each expretion is represented by a tree where each opperation and variable
     is a separate node. This class contain the common code for all those noeds.

     It also defines all the common methods used in those node classes and does
     some typecheckinig for them. Therefor the methodname in the subclasses
     should start with a '_'-char followed by the actually method name. This
     method will be called by the acutall method in this class after the
     typecheking is done.

Represents one number in a parsed expression tree
*************************************************

NAME
====

     Math::Expr::Num - Represents one number in a parsed expression tree

SYNOPSIS
========

     require Math::Expr::Opp;
     require Math::Expr::Var;
     require Math::Expr::Num;

     # To represent the expression "x+7":
     $n=new Math::Expr::Opp("+");
     $n->SetOpp(0,new Math::Expr::Var("x"));
     $n->SetOpp(1,new Math::Expr::Num(7));
     print $n->tostr . "\n";

DESCRIPTION
===========

     Used by the Math::Expr to represent numbers.

METHODS
=======

$n=new Math::Expr::Num($num)
----------------------------

     Creates a new representation of the number $num.

$n->tostr
---------

     Returns the string representation of the number which in perl is
     the same as the number itsefle

$n->Copy
--------

   Returns a new copy of itself.

AUTHOR
======

     Hakan Ardo <hakan@debian.org>

SEE ALSO
========

     L<Math::Expr::Opp>

Represents one operation in the parsed expression                      tree
***************************************************************************

NAME
====

     Math::Expr::Opp - Represents one operation in the parsed expression
                       tree

SYNOPSIS
========

     require Math::Expr::Opp;
     require Math::Expr::Var;
     require Math::Expr::Num;

     # To represent the expression "x+7":
     $n=new Math::Expr::Opp("+");
     $n->SetOpp(0,new Math::Expr::Var("x"));
     $n->SetOpp(1,new Math::Expr::Num(7));
     print $n->tostr . "\n";

DESCRIPTION
===========

     Used by the Math::Expr to represent algebraic expressions. This class
     represents one operation or function with a set of operands, which
     in turn can be other Math::Expr::Opp objects. And in that way we are
     able to represent entire expression.

     Operations like a+b and functions like sin(a) or f(a,b) are all
     represented by this kind of objects with "+", "sin" and "f" as the
     operation- or function names and Math::Expr::Var(a) and
     Math::Expr::Var(b) as operands (only a in the sin example).

METHODS
=======

$e=new  Math::Expr::Opp($name,$db)
----------------------------------

     Creates a new operation object with the operation- or function-name
     $name. Using the operations defined in $db. See
     L<Math::Expr::OpperationDB> for more info.

$e->SetOpp($i, $v)
------------------

     Sets operand number $i to $v.

$e->Opp($i)
-----------

     Returns operand to number $i.

$e->tostr
---------

     Returns a string representation of the entire expression to be
     used for debugging.

$e->strtype
-----------

     Returns a string representation of this expressions entire type,
     without simplifying it. In the same notation as the tostr method.

$n->Simplify
------------

     Simplifys the expression to some normal from.

$n->BaseType
------------

     Returns a string type of this expression simplifyed as much as
     possible.

$n->SubMatch($rules,$match)
---------------------------

     Tries to match $rules to this expretions and adds the substitutions
     needed to $match.Returns 1 if the match excists and the substitutions
     needed can coexcist with those already in $match otherwise 0.

$n->Match($rules)
-----------------

     Tries to match $rules to this expretions and to all its subexpretions.
     Returns a MatchSet object specifying where the matches ocored and what
     substitutions they represent.

$n->Subs($vars)
---------------

     Substitues all variables in the expretion with there vaules in $vars.

$n->Copy
--------

   Returns a copy of this object.

$n->Breakable
-------------

     Used by the parser to indikate if this object was created using
     parantesis or if he should break it up to preserve the rules of order
     between the diffrent opperations.

$n->Find($pos)
--------------

     Returns an object pointer to the subexpression represented by the
     string $pos.

$n->Set($pos, $val)
-------------------

     Replaces the subexpression at position $pos with $val.

AUTHOR
======

     Hakan Ardo <hakan@debian.org>

SEE ALSO
========

     L<Math::Expr>

A db of basic opperands properties
**********************************

NAME
====

     Math::Expr::OpperationDB - A db of basic opperands properties

SYNOPSIS
========

     require Math::Expr::OpperationDB;
     $db=new Math::Expr::OpperationDB($file);

DESCRIPTION
===========

     This is a database containing info about the different opperations
     (eg +,  -, *, ...). Each opperation is represented by a regexp
     mathing a type specifikation. That way Real*Real wont be the same
     opperation as Matrix*Matrix even though the same operation character
     is used.

     The data stored for each operation is the return type of the
     operation and whatever this operation is kommutativ or assosiative.

     Currently the data is hardcoded into the code, but that is about to
     chnage.

METHODS
=======

$db=new Math::Expr::OpperationDB;
---------------------------------

     Creates a new db.

$db->Find($t)
-------------

     Tries all the type regexps in the db on $t and if one matches that
     post is returned.

Represents a agebraic rule
**************************

NAME
====

     Math::Expr::Var - Represents a agebraic rule

SYNOPSIS
========

     reuire Math::Expr::Var;
     reuire Math::Expr;

     	$r=new Math::Expr::Var($from, $to);
     @res=$r->Apply($expr)

DESCRIPTION
===========

     This will create a rule that converts the expression $from to $to,
     and then apply that rule to $expr. $from, $to, $expr are all
     Math::Expr::Opp structures that should be Simplified to work ok.

     The result is a array @res of Math::Expr::Opp objects which should
     contain the results of applying the rule once on $expr in all
     possible ways. They are all simplified, and duplicaions are removed.

METHODS
=======

$r=new Math::Expr::Var($from, $to);
-----------------------------------

     Makes a rule converting the Math::Expr::Opp structur $from into $to.

A db of basic type and there properties
***************************************

NAME
====

     Math::Expr::TypeDB - A db of basic type and there properties

SYNOPSIS
========

     require Math::Expr::TypeDB;
     $db=new Math::Expr::TypeDB($file);

Represents one variable in a parsed expression tree
***************************************************

NAME
====

     Math::Expr::Var - Represents one variable in a parsed expression tree

SYNOPSIS
========

     require Math::Expr::Opp;
     require Math::Expr::Var;
     require Math::Expr::Num;

     # To represent the expression "x+7":
     $n=new Math::Expr::Opp("+");
     $n->SetOpp(0,new Math::Expr::Var("x"));
     $n->SetOpp(1,new Math::Expr::Num(7));
     print $n->tostr . "\n";

DESCRIPTION
===========

     Used by the Math::Expr to represent variables.

METHODS
=======

$n=new Math::Expr::Var($name)
-----------------------------

     Creates a new representation of the variable named $name.

$n->tostr
---------

     Returns the string representation of the variable, that is the
     variable name.

$n->strtype
-----------

     Returns the type of the variable.

$n->BaseType
------------

     Simply cals strtype, its needed to be compatible with the other
     elements in the structure.

$n->Match
---------

     Mathces a rule expression with the variable, and returns an array of
     VarSet objects with this variable name set to the expression if there
     types match.

$n->SubMatch
------------

     Used by upper level Match procedure to match an entire expression.

$n->Subs($vars)
---------------

     Returns this variables vaule taken from $vars or a new copy of itselfe
     if it does not excist.

$n->Copy
--------

   Returns a new copy of itself.

AUTHOR
======

     Hakan Ardo <hakan@debian.org>

SEE ALSO
========

     L<Math::Expr::Opp>

Represents a set of variables and there values
**********************************************

NAME
====

     Math::Expr::VarSet - Represents a set of variables and there values

SYNOPSIS
========

     require Math::Expr::VarSet;
     $s=new Math::Expr::VarSet;
     $s->Set('a', 7);
     $s->Get('a');

DESCRIPTION
===========

     Used to represent variables with values and substitutions.

METHODS
=======

$s=new Math::Expr::VarSet
-------------------------

     Create a new VarSet object.

$s->Set($var, $val)
-------------------

     Sets $var to $val. Returns 1 if the $var was already set to $val ore did
     not have a value previously, otherwise 0.

$s->Insert($set)
----------------

     Inserts all variables from $set into this object

$s->tostr
---------

     Returns a stringrepresentation of the set, usefull for debugging.

$s->Get($var)
-------------

     Returns the value of $var.

Perl module to calculate Fast Fourier Transforms
************************************************

NAME
====

   Math::FFT - Perl module to calculate Fast Fourier Transforms

SYNOPSIS
========

     use Math::FFT;
     my $PI = 3.1415926539;
     my $N = 64;
     my ($series, $other_series);
     for (my $k=0; $k<$N; $k++) {
         $series->[$k] = sin(4*$k*$PI/$N) + cos(6*$k*$PI/$N);
     }
     my $fft = new Math::FFT($series);
     my $coeff = $fft->rdft();
     my $spectrum = $fft->spctrm;
     my $original_data = $fft->invrdft($coeff);

     for (my $k=0; $k<$N; $k++) {
         $other_series->[$k] = sin(16*$k*$PI/$N) + cos(8*$k*$PI/$N);
     }
     my $other_fft = $fft->clone($other_series);
     my $other_coeff = $other_fft->rdft();
     my $correlation = $fft->correl($other_fft);

DESCRIPTION
===========

   This module implements some algorithms for calculating Fast Fourier
Transforms for one-dimensional data sets of size 2^n.  The data, assumed
to arise from a constant sampling rate, is represented by an array
reference $data (as described in the methods below), which is then used to
create a `Math::FFT' object as

     my $fft = new Math::FFT($data);

   The methods available include the following.

FFT METHODS
-----------

`$coeff = $fft->cdft();'
     This calculates the complex discrete Fourier transform for a data set
     `x[j]'. Here, $data is a reference to an array `data[0...2*n-1]'
     holding the data

          data[2*j] = Re(x[j]),
          data[2*j+1] = Im(x[j]), 0<=j<n

     An array reference `$coeff' is returned consisting of

          coeff[2*k] = Re(X[k]),
          coeff[2*k+1] = Im(X[k]), 0<=k<n

     where

          X[k] = sum_j=0^n-1 x[j]*exp(2*pi*i*j*k/n), 0<=k<n

`$orig_data = $fft->invcdft([$coeff]);'
     Calculates the inverse complex discrete Fourier transform on a data
     set `x[j]'. If `$coeff' is not given, it will be set equal to an
     earlier call to `$fft->cdft()'. `$coeff' is a reference to an array
     `coeff[0...2*n-1]' holding the data

          coeff[2*j] = Re(x[j]),
          coeff[2*j+1] = Im(x[j]), 0<=j<n

     An array reference `$orig_data' is returned consisting of

          orig_data[2*k] = Re(X[k]),
          orig_data[2*k+1] = Im(X[k]), 0<=k<n

     where, excluding the scale,

          X[k] = sum_j=0^n-1 x[j]*exp(-2*pi*i*j*k/n), 0<=k<n

     A scaling `$orig_data->[$i] *= 2.0/$n' is then done so that
     `$orig_data' coincides with the original $data.

`$coeff = $fft->rdft();'
     This calculates the real discrete Fourier transform for a data set
     `x[j]'. On input, $data is a reference to an array `data[0...n-1]'
     holding the data. An array reference `$coeff' is returned consisting
     of

          coeff[2*k] = R[k], 0<=k<n/2
          coeff[2*k+1] = I[k], 0<k<n/2
          coeff[1] = R[n/2]

     where

          R[k] = sum_j=0^n-1 data[j]*cos(2*pi*j*k/n), 0<=k<=n/2
          I[k] = sum_j=0^n-1 data[j]*sin(2*pi*j*k/n), 0<k<n/2

`$orig_data = $fft->invrdft([$coeff]);'
     Calculates the inverse real discrete Fourier transform on a data set
     `coeff[j]'. If `$coeff' is not given, it will be set equal to an
     earlier call to `$fft->rdft()'. `$coeff' is a reference to an array
     `coeff[0...n-1]' holding the data

          coeff[2*j] = R[j], 0<=j<n/2
          coeff[2*j+1] = I[j], 0<j<n/2
          coeff[1] = R[n/2]

     An array reference `$orig_data' is returned where, excluding the
     scale,

          orig_data[k] = (R[0] + R[n/2]*cos(pi*k))/2 +
            sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) +
              sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k<n

     A scaling `$orig_data->[$i] *= 2.0/$n' is then done so that
     `$orig_data' coincides with the original $data.

`$coeff = $fft->ddct();'
     Computes the discrete cosine tranform on a data set `data[0...n-1]'
     contained in an array reference $data. An array reference `$coeff' is
     returned consisting of

          coeff[k] = C[k], 0<=k<n

     where

          C[k] = sum_j=0^n-1 data[j]*cos(pi*(j+1/2)*k/n), 0<=k<n

`$orig_data = $fft->invddct([$coeff]);'
     Computes the inverse discrete cosine tranform on a data set
     `coeff[0...n-1]' contained in an array reference `$coeff'.  If
     `$coeff' is not given, it will be set equal to an earlier call to
     `$fft->ddct()'. An array reference `$orig_data' is returned
     consisting of

          orig_data[k] = C[k], 0<=k<n

     where, excluding the scale,

          C[k] = sum_j=0^n-1 coeff[j]*cos(pi*j*(k+1/2)/n), 0<=k<n

     A scaling `$orig_data->[$i] *= 2.0/$n' is then done so that
     `$orig_data' coincides with the original $data.

`$coeff = $fft->ddst();'
     Computes the discrete sine transform of a data set `data[0...n-1]'
     contained in an array reference $data. An array reference `$coeff' is
     returned consisting of

          coeff[k] = S[k], 0<k<n
          coeff[0] = S[n]

     where

          S[k] = sum_j=0^n-1 data[j]*sin(pi*(j+1/2)*k/n), 0<k<=n

`$orig_data = $fft->invddst($coeff);'
     Computes the inverse discrete sine transform of a data set
     `coeff[0...n-1]' contained in an array reference `$coeff', arranged as

          coeff[j] = A[j], 0<j<n
          coeff[0] = A[n]

     If `$coeff' is not given, it will be set equal to an earlier call to
     `$fft->ddst()'. An array reference `$orig_data' is returned
     consisting of

          orig_data[k] = S[k], 0<=k<n

     where, excluding a scale,

          S[k] =  sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k<n

     The scaling `$a->[$i] *= 2.0/$n' is then done so that `$orig_data'
     coincides with the original $data.

`$coeff = $fft->dfct();'
     Computes the real symmetric discrete Fourier transform of a data set
     `data[0...n]' contained in the array reference $data. An array
     reference `$coeff' is returned consisting of

          coeff[k] = C[k], 0<=k<=n

     where

          C[k] = sum_j=0^n data[j]*cos(pi*j*k/n), 0<=k<=n

`$orig_data = $fft->invdfct($coeff);'
     Computes the inverse real symmetric discrete Fourier transform of a
     data set `coeff[0...n]' contained in the array reference `$coeff'.
     If `$coeff' is not given, it will be set equal to an earlier call to
     `$fft->dfct()'. An array reference `$orig_data' is returned
     consisting of

          orig_data[k] = C[k], 0<=k<=n

     where, excluding the scale,

          C[k] = sum_j=0^n coeff[j]*cos(pi*j*k/n), 0<=k<=n

     A scaling `$coeff->[0] *= 0.5', `$coeff->[$n] *= 0.5', and
     `$orig_data->[$i] *= 2.0/$n' is then done so that `$orig_data'
     coincides with the original $data.

`$coeff = $fft->dfst();'
     Computes the real anti-symmetric discrete Fourier transform of a data
     set `data[0...n-1]' contained in the array reference $data. An array
     reference `$coeff' is returned consisting of

          coeff[k] = C[k], 0<k<n

     where

          C[k] = sum_j=0^n data[j]*sin(pi*j*k/n), 0<k<n

     (`coeff[0]' is used for a work area)

`$orig_data = $fft->invdfst($coeff);'
     Computes the inverse real anti-symmetric discrete Fourier transform
     of a data set `coeff[0...n-1]' contained in the array reference
     `$coeff'.  If `$coeff' is not given, it will be set equal to an
     earlier call to `$fft->dfst()'. An array reference `$orig_data' is
     returned consisting of

          orig_data[k] = C[k], 0<k<n

     where, excluding the scale,

          C[k] = sum_j=0^n coeff[j]*sin(pi*j*k/n), 0<k<n

     A scaling `$orig_data->[$i] *= 2.0/$n' is then done so that
     `$orig_data' coincides with the original $data.

CLONING
-------

   The algorithm used in the transforms makes use of arrays for a work
area and for a cos/sin lookup table dependent only on the size of the data
set. These arrays are initialized when the `Math::FFT' object is created
and then are populated when a transform method is first invoked. After
this, they persist for the lifetime of the object.

   This aspect is exploited in a cloning method; if a `Math::FFT' object
is created for a data set `$data1' of size N:

     $fft1 = new Math::FFT($data1);

   then a new `Math::FFT' object can be created for a second data set
`$data2' of the *same* size N by

     $fft2 = $fft1->clone($data2);

   The `$fft2' object will copy the reuseable work area and lookup table
calculated from `$fft1'.

APPLICATIONS
------------

   This module includes some common applications - correlation,
convolution and deconvolution, and power spectrum - that arise with real
data sets. The conventions used here follow that of *Numerical Recipes in
C*, by Press, Teukolsky, Vetterling, and Flannery, in which further
details of the algorithms are given. Note in particular the treatment of
end effects by zero padding, which is assumed to be done by the user, if
required.

Correlation
     The correlation between two functions is defined as

          /
             Corr(t) = | ds g(s+t) h(s)
          /

     This may be calculated, for two array references `$data1' and
     `$data2' of the same size $n, as either

          $fft1 = new Math::FFT($data1);
          $fft2 = new Math::FFT($data2);
          $corr = $fft1->correl($fft2);

     or as

          $fft1 = new Math::FFT($data1);
          $corr = $fft1->correl($data2);

     The array reference `$corr' is returned in wrap-around order -
     correlations at increasingly positive lags are in `$corr->[0]' (zero
     lag) on up to `$corr->[$n/2-1]', while correlations at increasingly
     negative lags are in `$corr->[$n-1]' on down to `$corr->[$n/2]'. The
     sign convention used is such that if `$data1' lags `$data2' (that is,
     is shifted to the right), then `$corr' will show a peak at positive
     lags.

Convolution
     The convolution of two functions is defined as

          /
             Convlv(t) = | ds g(s) h(t-s)
          /

     This is similar to calculating the correlation between the two
     functions, but typically the functions here have a quite different
     physical interpretation - one is a signal which persists indefinitely
     in time, and the other is a response function of limited duration.
     The convolution may be calculated, for two array references $data and
     `$respn', as

          $fft = new Math::FFT($data);
          $convlv = $fft->convlv($respn);

     with the returned `$convlv' being an array reference. The method
     assumes that the response function `$respn' has an *odd* number of
     elements $m less than or equal to the number of elements $n of $data.
     `$respn' is assumed to be stored in wrap-around order - the first
     half contains the response at positive times, while the second half,
     counting down from `$respn->[$m-1]', contains the response at
     negative times.

Deconvolution
     Deconvolution undoes the effects of convoluting a signal with a known
     response function. In other words, in the relation

          /
             Convlv(t) = | ds g(s) h(t-s)
          /

     deconvolution reconstructs the original signal, given the convolution
     and the response function. The method is implemented, for two array
     references $data and `$respn', as

          $fft = new Math::FFT($data);
          $deconvlv = $fft->deconvlv($respn);

     As a result, if the convolution of a data set $data with a response
     function `$respn' is calculated as

          $fft1 = new Math::FFT($data);
          $convlv = $fft1->convlv($respn);

     then the deconvolution

          $fft2 = new Math::FFT($convlv);
          $deconvlv = $fft2->deconvlv($respn);

     will give an array reference `$deconvlv' containing the same elements
     as the original data $data.

Power Spectrum
     If the FFT of a real function of N elements is calculated, the
     `N/2+1' elements of the power spectrum are defined, in terms of the
     (complex) Fourier coefficients `C[k]', as

          P[0] = |C[0]|^2 / N^2
          P[k] = 2 |C[k]|^2 / N^2   (k = 1, 2 ,..., N/2-1)
          P[N/2] = |C[N/2]|^2 / N^2

     Often for these purposes the data is partitioned into K segments,
     each containing `2M' elements. The power spectrum for each segment is
     calculated, and the net power spectrum is the average of all of these
     segmented spectra.

     Partitioning may be done in one of two ways: *non-overlapping* and
     overlapping. Non-overlapping is useful when the data set is gathered
     in real time, where the number of data points can be varied at will.
     Overlapping is useful where there is a fixed number of data points.
     In non-overlapping, the first <2M> elements constitute segment 1, the
     next `2M' elements are segment 2, and so on up to segment K, for a
     total of `2KM' sampled points. In overlapping, the first and second M
     elements are segment 1, the second and third M elements are segment
     2, and so on, for a total of `(K+1)M' sampled points.

     A problem that may arise in this procedure is *leakage*: the power
     spectrum calculated for one bin contains contributions from nearby
     bins. To lessen this effect *data windowing* is often used: multiply
     the original data `d[j]' by a window function `w[j]', where j = 0, 1,
     ..., N-1. Some popular choices of such functions are

          | j - N/2 |
            w[j] = 1 -  | ------- |     ... Bartlett
          |   N/2   |

          / j - N/2 \ 2
            w[j] = 1 -  | ------- |     ... Welch
          \   N/2   /

          1   /                    \
            w[j] =  ---  |1 - cos(2 pi j / N) |     ... Hamm
          2   \                    /

     The `spctrm' method, used as

          $fft = Math::FFT->new($data);
          $spectrum = $fft->spctrm([$key => $value, ...]);

     returns an array reference `$spectrum' representing the power
     spectrum for a data set represented by an array reference $data.  The
     options available are

    `window => window_name'
          This specifies the window function; if not given, no such
          function is used. Accepted values (see above) are `"bartlett"',
          `"welch"', `"hamm"', and `\&my_window', where `my_window' is a
          user specified subroutine which must be of the form, for example,

               sub my_window {
                  my ($j, $n) = @_;
                  return 1 - abs(2*($j-$n/2)/$n);
               }

          which implements the Bartlett window.

    `overlap => 1'
          This specifies whether overlapping should be done; if true (1),
          overlapping will be used, whereas if false (0), or not
          specified, no overlapping is used.

    `segments => n'
          This specifies that the data will be partitioned into n
          segments. If not specified, no segmentation will be done.

    `number => m'
          This specifies that `2m' data points will be used for each
          segment, and must be a power of 2. The power spectrum returned
          will consist of `m+1' elements.

STATISTICAL FUNCTIONS
---------------------

   For convenience, a number of common statistical functions are included
for analyzing real data. After creating the object as

     my $fft = new Math::FFT($data);

   for a data set represented by the array reference $data of size N,
these methods may be called as follows.

`$mean = $fft->mean([$data]);'
     This returns the mean

          1/N * sum_j=0^N-1 data[j]

     If an array reference $data is not given, the data set used in
     creating `$fft' will be used.

`$stdev = $fft->stdev([$data]);'
     This returns the standard deviation

          sqrt{ 1/(N-1) * sum_j=0^N-1 (data[j] - mean)**2 }

     If an array reference $data is not given, the data set used in
     creating `$fft' will be used.

`($min, $max) = $fft->range([$data]);'
     This returns the minimum and maximum values of the data set.  If an
     array reference $data is not given, the data set used in creating
     `$fft' will be used.

`$median = $fft->median([$data]);'
     This returns the median of a data set. The median is defined, for the
     sorted data set, as either the middle element, if the number of
     elements is odd, or as the interpolated value of the the two values
     on either side of the middle, if the number of elements is even. If
     an array reference $data is not given, the data set used in creating
     `$fft' will be used.

BUGS
====

   Please report any to Randy Kobes <randy@theoryx5.uwinnipeg.ca>

SEE ALSO
========

   `Math::Pari' in this node and PDL,

COPYRIGHT
=========

   The algorithm used in this module to calculate the Fourier transforms
is based on the C routine of fft4g.c available at
http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html, which is copyrighted
1996-99 by Takuya OOURA. The file arrays.c included here to handle passing
arrays to and from C comes from the PGPLOT module of Karl Glazebrook
<kgb@aaoepp.aao.gov.au>. The perl code of Math::FFT is copyright 2000 by
Randy Kobes, and is distributed under the same terms as Perl itself.

Calculates figures relating to loans and annuities.
***************************************************

NAME
====

   Math::Financial - Calculates figures relating to loans and annuities.

SYNOPSIS
========

   $calc = new Math::Financial(fv => 100000, pv => 1000); $calc->set->(pmt
=> 500, ir => 8);

   $calc->compound_interest(find => 'fv');

DESCRIPTION
===========

   This package contains solves mathematical problems relating to loans
and annuities.

   The attributes that are used in the equations may be set on a
per-object basis, allowing you to run a set of different calculations
using the same numbers, or they may be fed directly to the methods.

   The attribute types, accessed through the get and set methods are

pv	=> 	Present Value
fv	=> 	Future Value
ir	=>  Yearly Interest Rate (in percent)
pmt	=>	Payment Amount
np	=>	Number of Payments/Loan Term
tpy	=>	Terms Per Year (defaults to 12)
pd	=>	Payments made so far (used only for loan/annuity balances)
   Attributes are case-insensitive.  The documentation for the individual
methods indicates which attributes must be set for those methods.

   Calculations are based *either* on the attributes set with the new or
set methods, or with arguments fed directly to the methods.  This seemed
like the least confusing way to make the interface flexible for people who
are using the module in different ways.

   Also, performing a calculation does not update the attribute of the
solution.  In other words, if you solve an equation that returns fv, the
solution is returned but the internal fv field is unaffected.

   Any attempted calculation which cannot be completed - due to either
missing or invalid attributes - will return undef.

   I am interested to hear from people using this module - let me know what
you think about the interface and how it can be improved.

METHODS
=======

new
---

   C<$calc = new Math::Financial();

   `$calc = new Math::Financial(pv => 10000, ir => 5, np =' 12)>

   Object constructor.  See above for a description of the available
attributes.  You do not *have* to set attributes here, you can also do so
using set, or feed attributes directly to the methods.

   There are no default values for any of the attributes except `TPY'
(Terms Per Year), which is 12 by default, and `PD' which defaults to zero.

   If you don't want to use the object-oriented interface, see the
`EXPORTS' in this node section below.

set
---

   `$calc->set(fv => 100000, pmt => 500)'

   You can set any of the stored attributes using this method, which is is
also called by <new>.  Returns the number of attributes set.

get
---

   `$calc->get(field =' 'ir')>

   `$calc->get('ir','pmt','pv')'

   `$calc->get([qw(ir pmt pv)])'

   You can get one or several attributes using this method.  In the
multiple attribute formats, it accepts either a list or a list reference
as input.

   In single attribute context, returns a scalar.  In multiple attribute
context, it returns a list or a reference to a list, depending on the
calling context.

compound_interest
-----------------

   `$calc->compound_interest'

   `$calc->compound_interest->('fv')'

   `$calc->compound_interest->(find => 'fv')'

   Calculates compund interest for an annuity.  With any 3 of pv, fv, np,
and ir, you can always solve the fourth.

   Without arguments, the method will attempt to figure out what you'd
like to solve based on what attributes of the object are defined.
Usually, you'll probably want to explicitly request what attribute you'd
like returned, which you can do using the second or third method.

funding_annuity
---------------

   `$calc->funding_annuity'

   `$calc->funding_annuity->(pmt => 2000, ir => 6.50, np => 40, tpy =' 4)>

   funding_annuity calculates how much money ( fv ) you will have at the
end of np periods if you deposit pmt into the account each period and the
account earns ir interest per year.

   You may want to set the tpy attribute here to something other than 12,
since, while loans usually compound monthly, annuities rarely do.

loan_balance
------------

   `$calc->loan_balance'

   `$calc->loan_balance->(pmt => 2000, ir => 6.50, np => 360, pd => 12)'

   loan_balance calculates the balance on a loan that is being made in np
equal payments, given that pd payments have already been made. You can
also use this method to determine the amount of money left in an annuity
that you are drawing down.

loan_payment
------------

   `$calc->loan_payment'

   Return the payment amount, per period, of a loan.  This is also known
as amortizing.  The ir, np, and pv fields must be set.

loan_size
---------

   `$calc->loan_term'

   `$calc->loan_size->(pmt => 2000, ir => 6.50, np => 360)'

   loan_size calculates the size of loan you can get based on the monthly
payment you can afford.

loan_term
---------

   `$calc->loan_term'

   Return the number of payments (term) of a loan given the interest rate
ir, payment amount pmt and loan amount pv.   The ir, pmt, and pv fields
must be set.

simple_interest
---------------

   `$calc->simple_interest'

   `$calc->simple_interest->('ir')'

   `$calc->simple_interest->(find => 'ir')'

   This works just like compound interest, but there is no consideration
of np.  With any 2 of pv, fv, and ir, you can always solve for the third.

   Without arguments, the method will attempt to figure out what you'd
like to solve based on what attributes of the object have been defined.
Usually, you'll probably want to explicitly request what attribute you'd
like returned, which you can do using the second or third method.

REQUIRES
========

   POSIX - c_type functions

   (c_types might work under Windows.  I really don't know.  I'd
appreciate it if someome would let me know.  If they don't, in a future
release, I'll provide a runtime replacement for the POSIX functions so
it'll work on Win releases.  )

EXPORTS
=======

   By default, nothing.

   If you'd like to use a procedural interface, you can `use
Math::Financial qw(:standard)'.

   Then you can call the methods as function, without an object reference,
like

   `$term = loan_term(ir => 6.5, pmt => 1000, pv => 200000);'

   All of the methods are exported in this fashion, except for set and
get; this just seemed too confusing.

   You can still use the facility of set and get with the procedural
interface (i.e., you can set the attributes and them use them for many
different calculations), but you must call them as `Math::Financial::set'
and `Math::Financial::get'.

AUTHOR
======

   Eric Fixler <fix@fixler.com>, 1999

TODO
====

   Add more equations!  Send me equations and I'll put them in.

ACKNOWLEDGEMENTS
================

   Larry Freeman, whose Financial Formulas Page
`http://ourworld.compuserve.com/homepages/Larry_Freeman/finance.htm' was
essential for this project.

Decimal Math without Floating Point Errors
******************************************

NAME
====

   Math::FixedPrecision - Decimal Math without Floating Point Errors

SYNOPSIS
========

   use Math::FixedPrecision; $height  = Math::FixedPrecision->new(12.362);
 # 3 decimal places $width   = Math::FixedPrecision->new(9.65);     # 2
decimal places $area    = $height * $width; # area is now 119.29 not
119.2933 $length  = Math::FixedPrecision->new("100.00"); # 2 decimal places
$section = $length / 9; # section is now 11.11 not 11.1111111...

DESCRIPTION
===========

   There are numerous instances where floating point math is unsuitable,
yet the data does not consist solely of integers.  This module is designed
to completely overload all standard math functions.  The module takes care
of all conversion and rounding automatically.  Rounding is handled using
the IEEE 754 standard even mode.  This is a complete rewrite to use
Math::BigFloat, rather than Math::BigInt to handle the underlying math
operations.

   This module is not a replacement for Math::BigFloat; rather it serves a
similar but slightly different purpose.  By strictly limiting precision
automatically, this module operates slightly more natually than
Math::BigFloat when dealing with floating point numbers of limited
accuracy.  Math::BigFloat can unintentially inflate the apparent accuracy
of a calculation.

   Please examine assumptions you are operating under before deciding
between this module and Math::BigFloat.  With this module the assumption
is that your data is not very accurate and you do not want to overstate
any resulting values; with Math::BigFloat, you can completely avoid the
rounding problems associated with floating point notation.

new(number[,precision])
-----------------------

   The constructor accepts either a number or a string that looks like a
number.  But if you want to enforce a specific precision, you either need
to pass an exact string or include the second term.  In other words, all
of the following variables have different precisions:

   $var1 = Math::FixedPrecision->new(10);           # 10 to infinite
decimals   $var2 = Math::FixedPrecision->new(10,2);           # 10.00 to 2
decimals   $var3 = Math::FixedPrecision->new("10.000");           # 10.000
to 3 decimals

   All calculations will return a value rounded to the level of precision
of the least precise datum.  A number which looks like an integer (like
$var1 above) has infinite precision (no decimal places).  This is
important to note since Perl will happily truncate all trailing zeros from
a number like 10.000 and the code will get 10 no matter how many zeros you
typed.  If you need to assert a specific precision, you need to either
explicitly state that like $var2 above, or quote the number like $var3.
For example:

     $var4 = $var3 * 2; # 20.000 to 3 decimals
     $var5 = Math::FixedPrecision->new("2.00");
             # 2.00 to 2 decimals
     $var6 = $var3 * $var 5;
             # 20.00 to 2 decimals, not 3

EXPORT None by default.
-----------------------

AUTHOR
======

   John Peacock <jpeacock@rowman.com>

SEE ALSO
========

   Math::BigFloat

SYNOPSIS
========

     use Math::Fortran qw(log10 sign);
     $v=log10($x);
     $v=sign($y);
     $v=sign($x,$y);

DESCRIPTION
===========

   This module provides and exports some mathematical functions which are
built in in Fortran but not in Perl. Currently there are only 2 included.

log10 log to the base of 10 =item sign with 1 parameter, +1 if $y>=0, -1 otherwise, with 2 parameters +abs($x) if $y>=0, -abs($x) otherwise.
HISTORY
=======

   $Log: Fortran.pm,v $ Revision 1.1  1995/12/26 09:43:01  willijar
Initial revision

BUGS
====

   I welcome other entries for this module and bug reports.

AUTHOR
======

   John A.R. Williams <J.A.R.Williams@aston.ac.uk>

To Manipulate Exact Fractions (v.53b, Beta Release)
***************************************************

NAME
====

   Math::Fraction - To Manipulate Exact Fractions (v.53b, Beta Release)

SYNOPSIS
========

     use Math::Fraction;

     $a = frac(1,2); $b = frac(6,7);

     print "$a + $b = ", $a + $b, "$a * $b = ", $a * $b;
     print $a->num;

DESCRIPTION
===========

   This program is meant to replace the old bigrat perl library.  It can do
everything it can do and a lot more.

   Some of its features include:

   * Being able to add, subtract, multiply, and divide, among other things
     just like you would normal numbers that's to the overload module.

   * Being able to convert a decimal, including repeating ones, into a
     fraction.  For example, 1.142857142857 would become 8/7.

   * Being able to control how the fraction is displayed.  For example 8/7
     verses 1 1/7

   * Being able to use arbitrary size numbers in the numerator and the
     denominator.

   * Being able to covert between SMALL (using normal floats/integers) and
     BIG (using arbitrary size floats/integers) as needed so you do not
     have to worry about it. (New as of ver .4a)

   * Being able to have multiple default sets so that a function can modify
     the defaults with out effecting other functions (New as of ver .4a)

Usage
-----

     frac(FRACTION, TAGS) || Math::Fraction->new(FRACTION, TAGS)
     ex $f1=frac(2,3); $f2=frac(7,3,MIXED); $f3=frac("-10 3/4");

   FRACTION can equal any of the following:

(Numerator, Denominator)
(Number, Numerator, Denominator)
Decimal
"Numerator/Denominator"
"Number Numerator/Denominator"
   Any of these numbers can be any real number however if you enter in
negative numbers in anything but the First Number for the Mixed (3
numbers) the negative will be ignored.

   TAGS can equal 0, one or more of the following

NORMAL|MIXED|MIXED_RAW|RAW|DEF_MIXED
     Controls How the fraction is displayed:

    NORMAL
          display it in the #/# form

    MIXED_RAW
          display it in the # #/# form

    MIXED
          the same as MIXED_RAW but if one part is equal to 0 it will
          leave it off

    RAW
          the same as NORAML but always includes the sign

    DEF_MIXED
          will let it be what ever the default value is at the time

REDUCE|NO_REDUCE|DEF_REDUCE
     Controls the automatic reduction of fraction after operations are
     performed on it.

AUTO|NO_AUTO|DEF_AUTO
     Set rether to automatically convert between BIG and SMALL as needed
     see `Notes on the AUTO tag' in this node.

SMALL|BIG|DEF_BIG
     When the AUTO tag is NOT set it will set whether to use
     Arbitrary-Length numbers using the Math::BigInt and Math::BigFloat
     package. (Not the ** operator will not work however due to
     limitations of the packages.)  When the AUTO tag is set these tags
     will have NO effect.  (Note the default tags are NORMAL REDUCE AUTO
     and SMALL)

Methods
-------

reduce
     returns a reduced fraction but leaves the original object untouched.

string(NORMAL|MIXED|MIXED_RAW|RAW)
     returns the fraction as a string.  if no parameters are given the
     objects default display method will be used.

decimal|num
     returned the decimal value of the fraction

list|list(MIXED)
     returns a list containing the fraction if MIXED is used than a 3 item
     list is returned.

is_tag
     returns 1 is that tag exists in the fraction undef if is set to the
     default -1 otherwise

is_tag(INC_DEF)
     returns 1 is that tag exists in the fraction -1 if is tag does not
     exist but the default is set to that, 0 otherwise.

tags
     returns a list of the objects tags

tags(INC_DEF)
     returns a list of the objects tags if a particular tag is set to read
     a default the default tag is returned instead.

   All of the above methods may all be exported so that they can be used
as functions with a fraction as their first parameter. The string,
decimal|num functions can be imported with the tag STR_NUM instead of
having to list each one.

modify
     modifies the object.  Works almost the same as the new method but it
     doesn't return anything and preserves the objects tags unless
     overridden by new entries

modify_reduce
     same as reduce but it modifies the object instead of returning a
     fraction.

modify_num(Numerator)
     modifies the fraction's numerator.

modify_den(Denominator)
     modified the fraction's denominator.

modify_tag(TAGS)
     modifies the fraction tags.

   The is_tag, tags, and modify_tags methods can be used on the class its
self to get at or modify the default tags.

   The following methods will always modify or read the Class defaults

digits
     returns the default number of digests to return when doing floating
     point operations with BIG numbers, if set to undef Math::BigFloat
     will decide.

          modify_digits(NUM)

Dafault Sets
------------

   Default sets are way of modifying the defaults with out effecting other
functions.  Functions that relay on the default values or modify the
default should start with a `$set_id = temp_set' and end with a
`temp_set($set_id)'.

   See `"EXAMPLES"' in this node for examples of how default sets work.

   The following methods are met to manage default sets and will always
work on the Class defaults.

sets
     returns a list of all the sets;

name_set
     return the name of the current set.

name_set(NAME)
     name the current set

save_set
     saves the current sent based on its name as given above

save_set(NAME)
     save the current set as NAME

save_set(RAND)
     save the current set using a unique name

load_set(NAME)
     loads a set.

copy_set(NAME_ORG, NAME_NEW)
     copies a set. Returns true if successful.

del_set(NAME)
     deletes a set.

exists_set(NAME)
     returns true if the set exists.

use_set(NAME)
     uses a set, that is any changes you make to the used set will also
     change the original set, like a link.

temp_set
     loads a temp set using the default default values and returns a
     unique id you need to keep.

temp_set(ID)
     restores the original set based on the id you should of kept.

   Unless otherwise specified all the set methods will return the name of
the set being worked on if it was successful, false otherwise

tags(SET)
     lists all the tags in SET.

is_tag(TAG, SET)
     returns true if TAG exists in SET

digits(SET)
     returns what digits is set to in SET;

Overloaded Operators
--------------------

   The following operations have been overridden and will return a
fraction:

     +  -  /  *  +  +=  -=  *=  /=  ++  -- abs

   The following operations have also been overridden:

     <=> == != < <= > >=

   The following operations have also been overridden however they may spit
out nasty fractions.

     ** sqrt

   Whenever you try to access a fraction as a string the string method
will be called and when try to access it as a number the decimal method
will be called.

   This means that almost all other operations will work however some might
return decimals like the sin and cos;

Notes on the AUTO tag
---------------------

   With the AUTO tag set Fractions will be converted between SMALL and BIG
as needed.  The BIG and SMALL tag will be **ignorded** unless you
explicitly specify NO_AUTO in auto to control how the fraction is stored.

   When you give it a number it will decide if it is small enough to be
stored as a SMALL or if the fraction needs to converted to BIG.  However,
in order for it to recognize a big fraction the number needs to be in
quotes, thus `frac(7823495784957895478,781344567825678454)' will still be
stored as a small with some of the digits lost.

   When calculating to SMALL numbers that results in a number that is to
big for SMALL the calculation is done AGAIN but this time with BIG numbers
(so that it will calculate all the digits correctly) and the new fraction
will become a BIG.

   When calculating to BIG numbers that results in a number that is small
enough to be a SMALL the new fraction will become a SMALL.

   Normally, the AUTO tag will save time as calculating with BIG numbers
can be quite time consuming however it might slow thinks down if it
constantly converts between the two thus in some cases it may be wise to
turn it off.

EXAMPLES
========

   This is a small demonstration of what the fraction module can do.

   It is run for the most part with these two functions.

     sub pevel {print ">$_[0]\n"; $ans = eval $_[0]; print " $ans\n"; }
     sub evelp {print ">$_[0]\n"; eval $_[0]; }

   You can see it for yourself my typing in `perl -e "use
Math::FractionDemo; frac_calc;"' then frac_demo.

     >frac(1, 3)
      1/3
     >frac(4, 3, MIXED)
      1 1/3
     >frac(1, 1, 3)
      4/3
     >frac(1, 1, 3, MIXED)
      1 1/3
     >frac(10)
      10/1
     >frac(10, MIXED)
      10
     >frac(.66667)
      2/3
     >frac(1.33333, MIXED)
      1 1/3
     >frac("5/6")
      5/6
     >frac("1 2/3")
      5/3
     >frac(10, 20, NO_REDUCE)
      10/20

     >$f1=frac(2,3); $f2=frac(4,5);
     >$f1 + $f2
      22/15
     >$f1 * $f2
      8/15
     >$f1 + 1.6667
      7/3
     >$f2->modify_tag(MIXED)
     >$f2 + 10
      10 4/5
     >frac($ans, NORMAL) # trick to create new fraction with different tags
      54/5
     >$f1 + $f2          # Add two unlikes it goes to default mode
      22/15
     >$f1**1.2
      229739670999407/373719281884655
     >$f1->num**1.2
      0.614738607654485
     >frac(1,2)+frac(2,5)
      9/10

     >$f1=frac(5,3,NORMAL); $f2=frac(7,5);
     >"$f1  $f2"
      5/3  7/5
     >Math::Fraction->modify_tag(MIXED)
     >"$f1  $f2"
      5/3  1 2/5
     >$f1 = frac("3267893629762/32678632179820")
      3267893629762/32678632179820
     >$f2 = frac("5326875886785/76893467996910")
      5326875886785/76893467996910
     >$f1->is_tag(BIG).",".$f2->is_tag(BIG) # Notice how neither is BIG
      0,0
     >$f1+$f2
      21267734600460495169085706/125638667885089122116217810
     >$ans->is_tag(BIG)                     # But this answer is.
      1
     >$f1*$f2
      1740766377695750621849517/251277335770178244232435620
     >$ans->is_tag(BIG)                     # And so is this one.
      1

     >$f1 = frac("3267893629762/32678632179820", BIG)
      3267893629762/32678632179820
     >$f1->is_tag(BIG)   # Notice how the big tag had no effect.
      0
     >$f1->modify_tag(NO_AUTO, BIG)
     >$f1->is_tag(BIG)   # But now it does.  You have to turn off AUTO.
      1
     >$f1->num
      .10000093063197482237806917498797382196606
     >Math::Fraction->modify_digits(15)
     >$f1->num
      .1000009306319748
     >$f1 = frac("0.1231231234564564564564564564561234567891234567891234")
      13680347037037036999999999999963000037/
                                 111111111000000000000000000000000000000
     >Math::Fraction->modify_digits(65)
     >$f1->num
      .123123123456456456456456456456123456789123456789123456789123456789

     >$f1 = frac(7,5);
     >$f2 = frac("3267893629762/32678632179820", NO_AUTO, BIG)
     >Math::Fraction->modify_tag(MIXED); Math::Fraction->modify_digits(60)
     >"$f1 ".$f2->num
      1 2/5 .1000009306319748223780691749879738219660647769485035912494771
     >Math::Fraction->load_set(DEFAULT)
     >"$f1 ".$f2->num
      7/5 .10000093063197482237806917498797382196606
     >Math::Fraction->modify_digits(25)
     >"$f1 ".$f2->num
      7/5 .10000093063197482237806917
     >$s = Math::Fraction->temp_set
     >Math::Fraction->modify_tag(MIXED); Math::Fraction->modify_digits(15)
     >"$f1 ".$f2->num
      1 2/5 .1000009306319748
     >Math::Fraction->temp_set($s)
     >Math::Fraction->exists_set($s)

     >"$f1 ".$f2->num  # Notice how it goes back to the previous settings.
      7/5 .10000093063197482237806917

     >Math::Fraction->name_set('temp1')
     >Math::Fraction->modify_tag(MIXED, NO_AUTO)
     >Math::Fraction->modify_digits(60)
     >&s(Math::Fraction->tags, Math::Fraction->digits)
      MIXED REDUCE SMALL NO_AUTO 60
     >Math::Fraction->save_set  # If no name is given it will be saved via
     >                          # its given name
     >Math::Fraction->load_set(DEFAULT)
     >&s(Math::Fraction->tags, Math::Fraction->digits)
      NORMAL REDUCE SMALL AUTO undef
     >&s(Math::Fraction->tags('temp1'), Math::Fraction->digits('temp1'))
      MIXED REDUCE SMALL NO_AUTO 60
     >  # ^^ Notice how this lets you preview other sets w/out loading them.
     >Math::Fraction->load_set(DEFAULT)
     >Math::Fraction->use_set('temp1')
     >Math::Fraction->modify_tag(NO_REDUCE)
     >&s(Math::Fraction->tags, Math::Fraction->digits)
      MIXED NO_REDUCE SMALL NO_AUTO 60
     >&s(Math::Fraction->tags('temp1'), Math::Fraction->digits('temp1'))
      MIXED NO_REDUCE SMALL NO_AUTO 60
     >  # ^^ Notice how this also modifies the temp1 tag becuase it is
     >  #    being used if it was just loaded it would not do this
     >  #    becuase there is no link.

NOTES
=====

   Beta Release

   Originally Developed with Perl v 5.003_37 for Win32.

   Has been testing on Perl Ver 5.003 on a solaris machine and perl 5.004
on Windows 95.

   Built on a Linux 2 machine with perl v5.003.

   Please send me feedback at kevina@clark.net

   This is my first real attempt at writing a Perl Module and at
Object-Oriented Programming. (Although I know this is not a true-true
Object-Oriented Module as I cheated a little). I mainly wrote it to teach
my self how to program Object-Oriently in Perl and for the challenge.

   If you know of any faster or simpler way of doing any this please let me
know.

SEE ALSO
========

   See Math/FractionDemo, `perl(1b)' in this node

AUTHOR and COPYRIGHT
====================

   Kevin Atkinson, kevina@clark.net

   Copyright (c) 1997 Kevin Atkinson.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Math::Fraction demo script (v.51b, Beta Release)
************************************************

NAME
====

   Math::FractionDemo - Math::Fraction demo script (v.51b, Beta Release)

SYNOPSIS
========

   `perl -e "use Math::FractionDemo; frac_calc;"'

DESCRIPTION
===========

   This is nothing but a simple perl "calculator" and demo script.

Functions
---------

frac_calc
     A simple perl "calculator" for trying out the Math::Fraction package.

frac_demo [OUTPUT] [,INDENT]
     A simple demo script.  OUTPUT will default to STDOUT unless otherwise
     specified.  If OUTPUT is STDOUT it will run interactivly otehrwsise
     it will dump the results to the OUTPUT file stream.

     INDENT controles how many spaces each line is indented.  INDENT
     defaults to 0 unless otherwise specified.

     This script can also be run from frac_calc.

SEE ALSO
========

   See Math/Fraction, `perl(1p)' in this node

AUTHOR and COPYRIGHT
====================

   Kevin Atkinson, kevina@clark.net

   Copyright (c) 1997 Kevin Atkinson.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

High speed arbitrary size integer math
**************************************

NAME
====

   Math::GMP - High speed arbitrary size integer math

SYNOPSIS
========

     use Math::GMP;
     my $n = new Math::GMP 2;

     $n = $n ** (256*1024);
     $n = $n - 1;
     print "n is now $n\n";

DESCRIPTION
===========

   Math::GMP is designed to be a drop-in replacement both for Math::BigInt
and for regular integer arithmetic.  Unlike BigInt, though, Math::GMP uses
the GNU gmp library for all of its calculations, as opposed to straight
Perl functions.  This results in a speed increase of anywhere from 5 to 30
times.  The downside is that this module requires a C compiler to install
- a small tradeoff in most cases.

   A Math::GMP object can be used just as a normal numeric scalar would be
- the module overloads the normal arithmetic operators to provide as
seamless an interface as possible.  However, if you need a perfect
interface, you can do the following:

     use Math::GMP qw(:constant);

     $n = 2 ** (256 * 1024);
     print "n is $n\n";

   This would fail without the ':constant' since Perl would use normal
doubles to compute the 250,000 bit number, and thereby overflow it into
meaninglessness (smaller exponents yield less accurate data due to
floating point rounding).

BUGS
====

   As of version 1.0, Math::GMP is mostly compatible with Math::BigInt.
There are some slight incompatibilities, such as output of positive
numbers not being prefixed by a '+' sign.  This is intentional.

   The install process of the gmp library is rather contrived.  This needs
fixing and testing on various platforms.

AUTHOR
======

   Chip Turner <chip@zfx.com>, based on Math::BigInt by Mark Biggar and
Ilya Zakharevich.

Geometry related functions
**************************

NAME
====

   Math::Geometry - Geometry related functions

SYNOPSIS
========

     use Math::Geometry;

     @P2=rotx(@P1,$angle);
     @P3=rotx(@P1,$angle);
     @N =triangle_normal(@P1,@P2,@P3);
     @ZP=zplane_project(@P1,$d);

NOTES
=====

   Currently for zplane_project onto a plane with normal of the z axis and
z=0, the function returns the orthographic projections as opposed to a
perspective projection. I'm currently looking into how to properly handle
z=0 and will update it shortly.

DESCRIPTION
===========

   This package implements classic geometry methods. It should be
considered alpha software and any feedback at all is greatly appreciated.
The following methods are available:

vector_product.
---------------

   Also known as the cross product, given two vectors in Geometry space,
the vector_product of the two vectors, is a vector which is perpendicular
to the plane of AB with length equal to the length of A multiplied by the
length of B, multiplied by the sin of @, where @ is the angle between the
two vectors.

triangle_normal
---------------

   Given a triangle ABC that defines a plane P. This function will return
a vector N, which is a normal to the plane P.

     ($Nx,$Ny,$Nz) =
        triangle_normal(($Ax,$Ay,$Az),($Bx,$By,$Bz),($Cx,$Cy,$Cz));

zplane_project
--------------

   Project a point in Geometry space onto a plane with the z-axis as the
normal, at a distance d from z=0.

     ($x2,$y2,$z2) = zplane_project ($x1,$y1,$z1,$d);

rotx
----

   Rotate about the x axis r radians.

   ($x2,$y2,$z2) = rotx ($x1,$y1,$z1,$r);

roty
----

   Rotate about the y axis r radians.

   ($x2,$y2,$z2) = roty ($x1,$y1,$z1,$r);

rotz
----

   Rotate about the z axis r radians.

   ($x2,$y2,$z2) = rotz ($x1,$y1,$z1,$r);

deg2rad
-------

   Convert degree's to radians.

rad2deg
-------

   Convert radians to degree's.

pi
--

   Returns an approximate value of Pi, the code has been cribed from
Pg146, Programming Perl 2nd Ed.

EXAMPLE
=======

     use Math::Geometry;

AUTHOR
======

     Greg McCarroll <greg@mccarroll.demon.co.uk>

scalar numerical integration
****************************

NAME
====

     Math::Integral::Romberg - scalar numerical integration

SYNOPSIS
========

     use Math::Integral::Romberg 'integral';
     $area = integral(\&f, $x1, $x2);    # Short form
     $area = integral                    # Long form
      (\&f, $x1, $x2, $rel_err, $abs_err, $max_split, $min_split);

     # an alternative way of doing the long form
     $Math::Integral::Romberg::rel_err = $rel_err;
     $Math::Integral::Romberg::abs_err = $abs_err;
     $Math::Integral::Romberg::max_split = $max_split;
     $Math::Integral::Romberg::min_split = $min_split;
     $area = integral(\&f, $x1, $x2);

DESCRIPTION
===========

   integral() numerically estimates the integral of f() using Romberg
integration, a faster relative of Simpson's method.

Parameters
----------

$f
     A reference to the function to be integrated.

$x1, $x2
     The two extreme values of the range to be integrated.  `&$f(x)' must
     be finite at $x1 and $x2.

$rel_err
     Maximum acceptable relative error . Estimates of relative and
     absolute error are based on a comparison of the estimate computed
     using `2**n + 1' points with the estimate computed using `2**(n-1) +
     1' points.

     Once $min_split has been reached (see below), computation stops as
     soon as relative error drops below $rel_err, absolute error drops
     below $abs_err, or $max_split is reached.

     If not supplied, uses the value *$Math::Integral::Romberg::rel_err*
     whose default is 10**-10. A value of 10**-15 is close to the accuracy
     limits of double-precision floating point.

$abs_err
     Maximum acceptable absolute error. If not supplied uses
     *$Math::Integral::Romberg::abs_err*, which defaults to 10**-20.

$max_split
     At most `2 ** $max_split + 1' different sample x values are used to
     estimate the integral of `f()'. If not supplied, uses the value of
     *$Math::Integral::Romberg::max_split*, which defaults to 16,
     corresponding to 65537 sample points.

$min_split
     At least `2 ** $min_split + 1' different sample x values are used to
     estimate the integral of `f()'. If not supplied, uses the value of
     *$Math::Integral::Romberg::max_split*, which defaults to 5,
     corresponding to 33 sample points.

$Math::Integral::Romberg::return_point_count
     This value defaults to 0.  If you set it to 1, then when invoked in a
     list context, integral() will return a two-element list, containing
     the estimate followed by the number of sample points used to compute
     the estimate.

$Math::Integral::Romberg::abort
     This value is set to 1 if neither the $rel_err nor the $abs_err
     thresholds are reached before computation stops.  Once set, this
     variable remains set until you reset it to 0.

Default values
--------------

   Using the long form of integral() sets the convergence parameters for
that call only - you must use the package-qualified variable names (e.g.
$Math::Integral::Romberg::abs_tol) to change the values for all calls.

About the Algorithm
-------------------

   Romberg integration uses progressively higher-degree polynomial
approximations each time you double the number of sample points.  For
example, it uses a 2nd-degree polynomial approximation (as Simpson's
method does) after one split (2**1 + 1 sample points), and it uses a
10th-degree polynomial approximation after five splits (2**5 + 1 sample
points).  Typically, this will greatly improve accuracy (compared to
simpler methods) for smooth functions, while not making much difference
for badly behaved ones.

AUTHOR
======

   Eric Boesch (ebo@notes.dannet.dk)

Interpolate the value Y from X using a list of (X, Y) pairs
***********************************************************

NAME
====

   Math::Interpolate - Interpolate the value Y from X using a list of (X,
Y) pairs

SYNOPSIS
========

     use Math::Interpolate qw(derivatives constant_interpolate
                              linear_interpolate robust_interpolate);
     my @x = (1..5);
     my @y = (5, 10, 13, -4.5, 3);
     my @dy = derivatives(\@x, \@y);
     my ($l_y, $l_dy) = linear_interpolate(3.4, \@x, \@y);
     my ($r_y, $r_dy) = robust_interpolate(3.4, \@x, \@y);
     ($r_y, $r_dy) = robust_interpolate(3.4, \@x, \@y, [-2, 3, 4, -1, 4]);

DESCRIPTION
===========

SUBROUTINES
===========

derivatives *x_sequence* *y_sequence*
     Given a reference to an array of x values in *x_sequence* and a
     reference to an array of y values in *y_sequence*, return an array of
     reasonable derivatives.  The *x_sequence* values are presumed to be
     sorted in increasing numerical order.

     If there is an error in the input, such as *x_sequence* and
     *y_sequence* containing a different number of elements, then the
     subroutine returns an empty list in list context, an undefined value
     in scalar context, or nothing in a void context.

constant_interpolate x *x_sequence* *y_sequence*
     Given a reference to an array of x values in *x_sequence* and a
     reference to an array of y values in *y_sequence*, return the y value
     associated with the first x value less than or equal to x.  In other
     words, if    *x_sequence*->[i] <= x < *x_sequence*->[i+1]

     then return    *y_sequence*->[i]

     If x is less than *x_sequence*->[0], then return *y_sequence*->[0].
     If x is greater than *x_sequence-*[-1], then return
     *y_sequence*->[-1].

     If there is an error in the input, such as *x_sequence* and
     *y_sequence* containing a different number of elements, then the
     subroutine returns an empty list in list context, an undefined value
     in scalar context, or nothing in a void context.

linear_interpolate x *x_sequence* *y_sequence*
     Given a reference to an array of x values in *x_sequence* and a
     reference to an array of y values in *y_sequence*, calculate the
     interpolated value y that corresponds to the value x.  The returned
     value y lies on the straight line between the two points surrounding
     x.  If <x> lies outside of the range of values spanned by
     *x_sequence* then a linear extrapolation will be done.

     In an array context, linear_interpolate will return an array
     containing the y value and and slope between the two nearest
     surrounding points.

     If there is an error in the input, such as *x_sequence* and
     *y_sequence* containing a different number of elements, then the
     subroutine returns an empty list in list context, an undefined value
     in scalar context, or nothing in a void context.

robust_interpolate value *x_sequence* *y_sequence* [*dy_sequence*]
     Given a reference to an array of x values in *x_sequence* and a
     reference to an array of y values in *y_sequence*, calculate the
     interpolated value y that corresponds to the value x.  The
     interpolated curve generated by robust_interpolate is smooth and even
     the derivatives of the curve are smooth with only a few exceptions.

     The returned value y lies on the curve between the two points
     surrounding x.  If <x> lies outside of the range of values spanned by
     *x_sequence* then a linear extrapolation will be done.

     In an array context, linear_interpolate will return an array
     containing the y value and and slope between the two nearest
     surrounding points.

     If there is an error in the input, such as *x_sequence* and
     *y_sequence* containing a different number of elements, then the
     subroutine returns an empty list in list context, an undefined value
     in scalar context, or nothing in a void context.

AUTHOR
======

   Blair Zajac <bzajac@geostaff.com>.

COPYRIGHT
=========

   Copyright (c) 1998 by Blair Zajac.

Search where an element lies in a list of sorted elements
*********************************************************

NAME
====

   Math::IntervalSearch - Search where an element lies in a list of sorted
elements

SYNOPSIS
========

     use Math::IntervalSearch qw(interval_search);
     my @array = (1..5);
     my $location = interval_search(2.4, \@array);

     # Use your own comparison operators.
     sub ReverseLessThan {
       $_[0] < $_[1];
     }

     sub ReverseLessThanEqualTo {
       $_[0] <= $_[1];
     }

     $location = interval_search(2.4,
                                 \@array,
                                 \&ReverseLessThan,
                                 \&ReverseLessThanEqualTo);

DESCRIPTION
===========

   This subroutine is used to locate a position in an array of values where
a given value would fit.  It has been designed to be efficient in the
common situation that it is called repeatedly.  The user can supply a
different set of comparison operators to replace the standard < and <=.

SUBROUTINES
===========

interval_search value sequence [*less_than* [*less_than_equal_to*]]
     Given a value interval_search returns the location in the reference
     to an array sequence where the value would fit.  The default <
     operator to compare the elements in sequence can be replaced by the
     subroutine *less_than* which should return 1 if the first element
     passed to *less_than* is less than the second.  The default <=
     operator to compare the elements in sequence can be replaced by the
     subroutine *less_than* which should return 1 if the first element
     passed to *less_than* is less than the second.

     The values in sequence should already be sorted in numerically
     increasing order or in the order that would be produced by using the
     *less_than* subroutine.

     Let N be the number of elements in referenced array sequence, then
     interval_search returns these values:     -1  if
     value < sequence->[0]     i   if sequence->[i]   <= value <
     sequence->[i+1]     N-1 if sequence->[N-1] <= value

     If a reference is made to an empty array, then -1 is always returned.

     If there is illegal input to interval_search, such as an improper
     number of arguments, then an empty list in list context, an undefined
     value in scalar context, or nothing in a void context is returned.

     This subroutine is designed to be efficient in the common situation
     that it is called repeatedly, with value taken from an increasing or
     decreasing list of values.  This will happen, e.g., when an irregular
     waveform is interpolated to create a sequence with constant
     separation.  The first guess for the output is therefore taken to be
     the value returned at the previous call and stored in the variable
     ilo.  A first check ascertains that ilo is less than the number of
     data points in sequence.  This is necessary since the present call
     may have nothing to do with the previous call.  Then, if
     sequence->[ilo] <= value < sequence->[ilo+1],

     we set left = ilo and are done after just three comparisons.
     Otherwise, we repeatedly double the difference     istep = ihi - ilo

     while also moving ilo and ihi in the direction of x, until
     sequence->[ilo] <= x < sequence->[ihi],

     after which bisection is used to get, in addition,     ilo+1 = ihi.

     Then left = ilo is returned.

AUTHOR
======

   Blair Zajac <bzajac@geostaff.com>.

COPYRIGHT
=========

   Copyright (c) 1998 by Blair Zajac.

the theory behind it
********************

NAME
====

   Kleene's Algorithm - the theory behind it

   brief introduction

DESCRIPTION
===========

Semi-Rings
----------

   A Semi-Ring (S, +, ., 0, 1) is characterized by the following
properties:

  1. a)  `(S, +, 0) is a Semi-Group with neutral element 0'

     b)  `(S, ., 1) is a Semi-Group with neutral element 1'

     c)  `0 . a = a . 0 = 0  for all a in S'

  2. `"+"' is commutative and *idempotent*, i.e., `a + a = a'

  3. Distributivity holds, i.e.,

     a)  `a . ( b + c ) = a . b + a . c  for all a,b,c in S'

     b)  `( a + b ) . c = a . c + b . c  for all a,b,c in S'

  4. `SUM_{i=0}^{+infinity} ( a[i] )'

     exists, is well-defined and unique

     `for all a[i] in S'

     and associativity, commutativity and idempotency hold

  5. Distributivity for infinite series also holds, i.e.,

          ( SUM_{i=0}^{+infty} a[i] ) . ( SUM_{j=0}^{+infty} b[j] )
          = SUM_{i=0}^{+infty} ( SUM_{j=0}^{+infty} ( a[i] . b[j] ) )

        EXAMPLES:

   * `S1 = ({0,1}, |, &, 0, 1)'

     Boolean Algebra

     See also `Math::MatrixBool(3)' in this node

   * `S2 = (pos. reals with 0 and +infty, min, +, +infty, 0)'

     Positive real numbers including zero and plus infinity

     See also `Math::MatrixReal(3)' in this node

   * `S3 = (Pot(Sigma*), union, concat, {}, {''})'

     Formal languages over Sigma (= alphabet)

     See also `DFA::Kleene(3)' in this node

Operator '*'
------------

   (reflexive and transitive closure)

   Define an operator called "*" as follows:

     a in S   ==>   a*  :=  SUM_{i=0}^{+infty} a^i

   where

     a^0  =  1,   a^(i+1)  =  a . a^i

   Then, also

     a*  =  1 + a . a*,   0*  =  1*  =  1

   hold.

Kleene's Algorithm
------------------

   In its general form, Kleene's algorithm goes as follows:

     for i := 1 to n do
         for j := 1 to n do
         begin
             C^0[i,j] := m(v[i],v[j]);
             if (i = j) then C^0[i,j] := C^0[i,j] + 1
         end
     for k := 1 to n do
         for i := 1 to n do
             for j := 1 to n do
                 C^k[i,j] := C^k-1[i,j] +
                             C^k-1[i,k] . ( C^k-1[k,k] )* . C^k-1[k,j]
     for i := 1 to n do
         for j := 1 to n do
             c(v[i],v[j]) := C^n[i,j]

Kleene's Algorithm and Semi-Rings
---------------------------------

   Kleene's algorithm can be applied to any Semi-Ring having the properties
listed previously (above). (!)

   EXAMPLES:

   * `S1 = ({0,1}, |, &, 0, 1)'

     `G(V,E)' be a graph with set of vortices V and set of edges E:

     `m(v[i],v[j])  :=  ( (v[i],v[j]) in E ) ? 1 : 0'

     Kleene's algorithm then calculates

     `c^{n}_{i,j} = ( path from v[i] to v[j] exists ) ? 1 : 0'

     using

     `C^k[i,j]  =  C^k-1[i,j]  |  C^k-1[i,k]  &  C^k-1[k,j]'

     (remember ` 0*  =  1*  =  1 ')

   * `S2 = (pos. reals with 0 and +infty, min, +, +infty, 0)'

     `G(V,E)' be a graph with set of vortices V and set of edges E, with
     costs `m(v[i],v[j])' associated with each edge `(v[i],v[j])' in E:

     `m(v[i],v[j])  :=  costs of (v[i],v[j])'

     `for all (v[i],v[j]) in E'

     Set `m(v[i],v[j]) := +infinity' if an edge (v[i],v[j]) is not in E.

     `  ==>  a* = 0  for all a in S2'

     `  ==>  C^k[i,j]  =  min( C^k-1[i,j] ,'

     `           C^k-1[i,k]  +  C^k-1[k,j] )'

     Kleene's algorithm then calculates the costs of the "shortest" path
     from any `v[i]' to any other `v[j]':

     `C^n[i,j] = costs of "shortest" path from v[i] to v[j]'

   * `S3 = (Pot(Sigma*), union, concat, {}, {''})'

     `M in DFA(Sigma)' be a Deterministic Finite Automaton with a set of
     states Q, a subset F of Q of accepting states and a transition
     function `delta : Q x Sigma --> Q'.

     Define

     `m(v[i],v[j])  :='

     `    { a in Sigma | delta( q[i] , a ) = q[j] }'

     and

     `C^0[i,j] := m(v[i],v[j]);'

     `if (i = j) then C^0[i,j] := C^0[i,j] union {''}'

     (`{''}' is the set containing the empty string, whereas `{}' is the
     empty set!)

     Then Kleene's algorithm calculates the language accepted by
     Deterministic Finite Automaton M using

     `C^k[i,j] = C^k-1[i,j] union'

     `    C^k-1[i,k] concat ( C^k-1[k,k] )* concat C^k-1[k,j]'

     and

     `L(M)  =  UNION_{ q[j] in F }  C^n[1,j]'

     (state `q[1]' is assumed to be the "start" state)

     finally being the language recognized by Deterministic Finite
     Automaton M.

   Note that instead of using Kleene's algorithm, you can also use the "*"
operator on the associated matrix:

   Define  `A[i,j]  :=  m(v[i],v[j])'

   `  ==>   A*[i,j]  =  c(v[i],v[j])'

   Proof:

   `A*  =  SUM_{i=0}^{+infty} A^i'

   where  `A^0  =  E_{n}'

   (matrix with one's in its main diagonal and zero's elsewhere)

   and  `A^(i+1)  =   A . A^i'

   Induction over k yields:

   `A^k[i,j]  =  c_{k}(v[i],v[j])'

`k = 0:'
     `c_{0}(v[i],v[j])  =  d_{i,j}'

     with  `d_{i,j}  :=  (i = j) ? 1 : 0'

     and  `A^0  =  E_{n}  =  [d_{i,j}]'

`k-1 -> k:'
     `c_{k}(v[i],v[j])'

     `= SUM_{l=1}^{n} m(v[i],v[l]) . c_{k-1}(v[l],v[j])'

     `= SUM_{l=1}^{n} ( a[i,l] . a[l,j] )'

     `= [a^{k}_{i,j}]  =  A^1 . A^(k-1)  =  A^k'

   qed

   In other words, the complexity of calculating the closure and doing
matrix multiplications is of the same order `O( n^3 )' in Semi-Rings!

SEE ALSO
========

   Math::MatrixBool(3), Math::MatrixReal(3), DFA::Kleene(3).

   (All contained in the distribution of the "Set::IntegerFast" module)

   Dijkstra's algorithm for shortest paths.

AUTHOR
======

   This document is based on lecture notes and has been put into POD
format by Steffen Beyer <sb@sdm.de>.

COPYRIGHT
=========

   Copyright (c) 1997 by Steffen Beyer. All rights reserved.

Object oriented interface to solving of linear programs using the lp_solve library
**********************************************************************************

NAME
====

   Math::LP - Object oriented interface to solving of linear programs
using the lp_solve library

SYNOPSIS
========

     use Math::LP qw(:types);             # imports optimization types
     use Math::LP::Constraint qw(:types); # imports constraint types

     # make a new LP
     $lp = new Math::LP;

     # make the variables for the LP
     $x1 = new Math::LP::Variable(name => 'x1');
     $x2 = new Math::LP::Variable(name => 'x2');

     # maximize the objective function to x1 + 2 x2
     $obj_fn = make Math::LP::LinearCombination($x1,1.0,$x2,2.0);
     $lp->maximize_for($obj_fn);

     # add the constraint x1 + x2 <= 2
     $constr = new Math::LP::Constraint(
         lhs  => make Math::LP::LinearCombination($x1,1.0,$x2,1.0),
         rhs  => 2.0,
         type => $LE,
     );
     $lp->add_constraint($constr);

     # solve the LP and print the results
     $lp->solve() or die "Could not solve the LP";
     print "Optimum = ", $obj_fn->{value}, "\n";
     print "x1 = ", $x1->{value}, "\n";
     print "x2 = ", $x1->{value}, "\n";
     print "slack = ", $constr->{slack}, "\n";

DESCRIPTION
===========

   The Math::LP package provides an object oriented interface to defining
and solving mixed linear/integer programs. It uses the lp_solve library as
the underlying solver. Please note that this is not a two way relation. An
LP is defined using Math::LP, converted to an lp_solve data structure, and
solved with lp_solve functions. It is not possible to grab an lp_solve
structure somehow and convert it to a Math::LP object for manipulation and
inspection. If you want to do that kind of stuff in Perl, use the
Math::LP::Solve package instead.

   That being said, the logical way of constructing an LP consists of

  1. Construct Math::LP::Variable objects, in the meanwhile marking
     integer variables

  2. Construct Math::LP::LinearCombination objects with the variables and
     use them as the objective function and constraints

  3. Solve the LP

  4. Fetch the variable values from the Math::LP::Variable objects, the
     slacks and dual values from the Math::LP::Constraint objects.  and
     the row values (including the optimum) from the corresponding
     Math::LP::LinearCombination.

DATA FIELDS
===========

solver_status
     Holds the status of the last solve() call.  Can be either $OPTIMAL,
     $MILP_FAIL, $INFEASIBLE, $UNBOUNDED, $FAILURE, $RUNNING, $FEAS_FOUND,
     $NO_FEAS_FOUND or $BREAK_BB.

variables
     A ref to a hash with all the Math::LP::Variable objects used in the
     LP indexed on their name.

constraints
     A ref to an array with all Math::LP::Constraint objects used in the
     LP.

objective_function
     A Math::LP::LinearCombination object representing the objective
     function

type
     The optimization type. Can be either $MAX or $MIN.

METHODS
=======

new()
     returns a new, empty LP

nr_rows()
     returns the number of rows, i.e. the number of constraints in the LP

nr_cols()
     returns the number of columns, i.e. the number of variables in the LP

add_variable($var)
     registers the variable as belonging to the LP. The index field of the
     variable is set as a side effect. For this reason it is not allowed
     to use 1 variable in 2 LP objects.

add_constraint($constr)
     adds a Math::LP::Constraint to the LP. The index field of the
     constraint is likewise set. It is thus also not allowed to use a
     single constraint in more than 1 LP. All variables present in the
     constraint are automatically registered.

set_objective_function($lincomb,$type)
     sets the objective function of the LP, specified by the following
     parameters:

    $lincomb
          a Math::LP::LinearCombination forming the objective function.
          New variables in the linear combination are automatically added
          to the LP.

    $type
          the optimization type, either $MAX or $MIN

maximize_for($lincomb)
     shortcut for set_objective_function($lincomb,$MAX)

minimize_for($lincomb)
     shortcut for set_objective_function($lincomb,$MIN)

solve([$lag_solve])
     Solves the LP, returns true if succeeded (i.e. the status value is
     $OPTIMAL), false otherwise. The status of the solver is available in
     the status field afterwards. The default is to solve using solve().
     If however $lag_solve is specified and true, lag_solve() will be used.

optimum()
     Returns the value of the objective function obtained by the solver.

SEE ALSO
========

   More info on the packages used in Math::LP is found in
Math/LP/Object, Math/LP/Variable,
and Math/LP/LinearCombination.

   The underlying wrapper to the lp_solve library is documented in
`Math::LP::Solve' in this node. More info on using the lp_solve library
written by Michel Berkelaar and adapted by Jeroen Dirks is found in its
source code available from ftp://ftp.ics.ele.tue.nl/pub/lp_solve/

AUTHOR
======

   Wim Verhaegen <wim.verhaegen@ieee.org>

COPYRIGHT
=========

   Copyright(c) 2000 Wim Verhaegen. All rights reserved.  This program is
free software; you can redistribute and/or modify it under the same terms
as Perl itself.

representation of constraints in Math::LP objects
*************************************************

NAME
====

   Math::LP::Constraint - representation of constraints in Math::LP objects

SYNOPSIS
========

     use Math::LP::Constraints qw(:types); # imports constraint types

     # make the constraint x1 + 2 x2 <= 3
     $x1 = new Math::LP::Variable(name => 'x1');
     $x2 = new Math::LP::Variable(name => 'x2');
     $constraint = new Math::LP::Constraint(
     	lhs  => make Math::LP::LinearCombination($x1,1.0,$x2,2.0),
         rhs  => 3.0,
         type => $LE,
     );

DESCRIPTION
===========

   A Math::LP::Constraint object has the following fields:

lhs
     a Math::LP::LinearCombination object forming the left hand side of the
     (in)equality (Required)

rhs
     a constant number for the right hand side of the (in)equality
     (Defaults to 0)

type
     the (in)equality type, either $LE (<=), $GE (>=) or $EQ (=) (Required)

name
     a string with a name for the constraint (Optional, set by
     Math::LP::add_constraint if not specified)

index
     the index of the constraint in the LP (Set by
     Math::LP::add_constraint)

slack
     the slack of the row in the LP (Set after solving the LP)

dual_value
     the dual value of the row in the LP (Set after solving the LP)

SEE ALSO
========

   See Math/LP, Math/LP/Variable,
Math/LP/LinearCombination, and
Math/LP/Object,

AUTHOR
======

   Wim Verhaegen <wim.verhaegen@ieee.org>

COPYRIGHT
=========

   Copyright(c) 2000 Wim Verhaegen. All rights reserved.  This program is
free software; you can redistribute and/or modify it under the same terms
as Perl itself.

linear combination of Math::LP::Variable objects
************************************************

NAME
====

   Math::LP::LinearCombination - linear combination of Math::LP::Variable
objects

SYNOPSIS
========

     use Math::LP::LinearCombination;

     # first construct some variables
     $x1 = new Math::LP::Variable(name => 'x1');
     $x2 = new Math::LP::Variable(name => 'x2');

     # build x1 + 2 x2 from an empty linear combination
     $lc1 = new Math::LP::LinearCombination;
     $lc1->add_var_with_coeff($x1,1.0);
     $lc1->add_var_with_coeff($x2,2.0);

     # alternatively, make x1 + 2 x2 in one go
     $lc2 = make Math::LP::LinearCombination($x1, 1.0,
                                             $x2, 2.0 );

DESCRIPTION
===========

   Any client should not access any other field than the value field.
This field contains the value of the linear combination, typically
obtained in calculate_value(), but it may be set elsewhere (e.g. by the
solve() function in Math::LP).

   The following methods are available:

new()
     returns a new, empty linear combination

make($var1,$coeff1,$var2,$coeff2,...)
     returns a new linear combination initialized with the given variables
     and coefficients. A ref to an array of variables and coefficients is
     also accepted as a legal argument.

add_var_with_coeff($var,$coeff)
     adds a variable to the linear combination with the given coefficient

calculate_value()
     calculates the value of the linear combination. The value is also
     stored in the value field. Requires that the values of all variables
     are defined.

SEE ALSO
========

   See Math/LP/Object, and Math/LP/Variable,

AUTHOR
======

   Wim Verhaegen <wim.verhaegen@ieee.org>

COPYRIGHT
=========

   Copyright(c) 2000 Wim Verhaegen. All rights reserved.  This program is
free software; you can redistribute and/or modify it under the same terms
as Perl itself.

base class for objects in the Math::LP family
*********************************************

NAME
====

   Math::LP::Object - base class for objects in the Math::LP family

SYNOPSIS
========

     package Math::LP::XXX; # a new member XXX in the family

     # derive XXX from Object
     use Math::LP::Object;
     use base qw(Math::LP::Object);
     use fields qw(foo bar);

     sub initialize {
         my Math::LP::XXX $this = shift;
         # put XXX specific initialization code here
     }

DESCRIPTION
===========

   Math::LP::Object provides the following methods to classes derived from
it:

new()
     Returns a new object, blessed in the package which it was called for.
     The returned object is a pseudo-hash, with fields specified using the
     fields pragma.

     new() optionally accepts a hash of initial values of the data fields.
     After these values have been set, initialize() is called on the
     object.  Specific initialization code for the derived class is thus
     to be put in the initialize() function of the derived class.

croak($msg)
     Dies with an error message, adding info on the last caller outside
     the Math::LP family.

     croak() can be invoked both as a method and a package function.

SEE ALSO
========

   See Base, Fields,

AUTHOR
======

   Wim Verhaegen <wim.verhaegen@ieee.org>

COPYRIGHT
=========

   Copyright(c) 2000 Wim Verhaegen. All rights reserved.  This program is
free software; you can redistribute and/or modify it under the same terms
as Perl itself.

variables used in linear programs
*********************************

NAME
====

   Math::LP::Variable - variables used in linear programs

SYNOPSIS
========

     use Math::LP::Variable;

     # make a variable named x1
     my $x1 = new Math::LP::Variable(name => 'x1');

     # make an integer variable named x2
     my $x2 = new Math::LP::Variable(name => 'x2', is_int => 1);

     # make a variable named x3 initialized to 3.1415
     my $x3 = new Math::LP::Variable(name => 'x3', value => '3.1415');

DESCRIPTION
===========

DATA FIELDS
-----------

name
     a string with the name of the variable (required)

is_int
     a flag indicating whether the variable can only have integer values
     (optional, defaults to false)

value
     a number representing the value of the variable (optional)

index
     an integer number holding the index of the variable in the matrix of
     the LP the variable is used in (optional)

METHODS
-------

   No methods available.

SEE ALSO
========

   See Math/LP, and Math/LP/Object,

AUTHOR
======

   Wim Verhaegen <wim.verhaegen@ieee.org>

COPYRIGHT
=========

   Copyright(c) 2000 Wim Verhaegen. All rights reserved.  This program is
free software; you can redistribute and/or modify it under the same terms
as Perl itself.

Perl extension for the C math library, libm
*******************************************

NAME
====

   Math::Libm - Perl extension for the C math library, libm

SYNOPSIS
========

     use Math::Libm ':all';

     print "e = ", M_E, "\n";
     print "pi/2 = ", M_PI_2, "\n";
     print "erf(1) = ", erf(1), "\n";
     print "hypot(3,4) = ", hypot(3,4), "\n";

     my $signgam = 0;
     my $y = lgamma_r(-0.5, $signgam);
     print "signgam=$signgam lgamma=$y\n";

DESCRIPTION
===========

   This module is a translation of the C `math.h' file.  It exports the
following selected constants and functions.

EXPORT
------

   None by default.

Exportable constants
--------------------

     M_1_PI
     M_2_PI
     M_2_SQRTPI
     M_E
     M_LN10
     M_LN2
     M_LOG10E
     M_LOG2E
     M_PI
     M_PI_2
     M_PI_4
     M_SQRT1_2
     M_SQRT2

Exportable functions
--------------------

     double acos(double x)
     double acosh(double x)
     double asin(double x)
     double asinh(double x)
     double atan(double x)
     double atanh(double x)
     double cbrt(double x)
     double ceil(double x)
     double cosh(double x)
     double erf(double x)
     double erfc(double x)
     double expm1(double x)
     double floor(double x)
     double hypot(double x, double y)
     double j0(double x)
     double j1(double x)
     double jn(int n, double x)
     double lgamma_r(double x, int signgam)
     double log10(double x)
     double log1p(double x)
     double pow(double x, double y)
     double rint(double x)
     double sinh(double x)
     double tan(double x)
     double tanh(double x)
     double y0(double x)
     double y1(double x)
     double yn(int n, double x)

AUTHOR
======

   Daniel S. Lewart, <d-lewart@uiuc.edu>

SEE ALSO
========

   See Perlfunc (perl.info), Math/Complex,
see POSIX.

BUGS
====

   Only tested on AIX 4.2, FreeBSD 4.0, Linux 2.2.16, and Solaris 2.5.1.
May need some more functions.

Provides pure 2, 3 or multi-value logic.
****************************************

NAME
====

   Math::Logic - Provides pure 2, 3 or multi-value logic.

SYNOPSIS
========

     use Math::Logic qw( $TRUE $FALSE $UNDEF $STR_TRUE $STR_FALSE $STR_UNDEF ) ;
                     #       1      0     -1     'TRUE'    'FALSE'    'UNDEF'

     use Math::Logic ':NUM' ; # $TRUE $FALSE $UNDEF -- what you normally want

     use Math::Logic ':ALL' ; # All the constants

     use Math::Logic ':STR' ; # $STR_TRUE $STR_FALSE $STR_UNDEF

     # 2-degree logic
     my $true  = Math::Logic->new( -value => $TRUE,  -degree => 2 ) ;
     my $false = Math::Logic->new( -value => $FALSE, -degree => 2 ) ;
     my $x     = Math::Logic->new_from_string( 'TRUE,2' ) ;

     print "true" if $true ;

     # 3-degree logic (non-propagating)
     my $true  = Math::Logic->new( -value => $TRUE,  -degree => 3 ) ;
     my $false = Math::Logic->new( -value => $FALSE, -degree => 3 ) ;
     my $undef = Math::Logic->new( -value => $UNDEF, -degree => 3 ) ;
     my $x     = Math::Logic->new_from_string( 'FALSE,3' ) ;

     print "true" if ( $true | $undef ) == $TRUE ;

     # 3-degree logic (propagating)
     my $true  = Math::Logic->new( -value => $TRUE,  -degree => 3, -propagate => 1 ) ;
     my $false = Math::Logic->new( -value => $FALSE, -degree => 3, -propagate => 1 ) ;
     my $undef = Math::Logic->new( -value => $UNDEF, -degree => 3, -propagate => 1 ) ;
     my $x     = Math::Logic->new_from_string( '( UNDEF, 3, -propagate )' ) ;

     print "undef" if ( $true | $undef ) == $UNDEF ;

     # multi-degree logic
     my $True   = 100 ; # Define our own true
     my $False  = $FALSE ;
     my $true   = Math::Logic->new( -value => $True,  -degree => $True ) ;
     my $very   = Math::Logic->new( -value => 67,     -degree => $True ) ;
     my $fairly = Math::Logic->new( -value => 33,     -degree => $True ) ;
     my $false  = Math::Logic->new( -value => $False, -degree => $True ) ;
     my $x      = Math::Logic->new_from_string( "25,$True" ) ;

     print "maybe" if ( $very | $fairly ) > 50 ;

     # We can have arbitrarily complex expressions; the result is a Math::Logic
     # object; all arguments must be Math::Logic objects or things which can be
     # promoted into such and must all be compatible. The outcome depends on
     # which kind of logic is being used.
     my $xor = ( $x | $y ) & ( ! ( $x & $y ) ) ;
     # This is identical to:
     my $xor = $x ^ $y ;

DESCRIPTION
===========

   Perl's built-in logical operators, and, or, xor and not support 2-value
logic. This means that they always produce a result which is either true
or false. In fact perl sometimes returns 0 and sometimes returns undef for
false depending on the operator and the order of the arguments. For "true"
Perl generally returns the first value that evaluated to true which turns
out to be extremely useful in practice. Given the choice Perl's built-in
logical operators are to be preferred - but when you really want pure
2-degree logic or 3-degree logic or multi-degree logic they are available
through this module.

   The only 2-degree logic values are 1 (TRUE) and 0 (FALSE).

   The only 3-degree logic values are 1 (TRUE), 0 (FALSE) and -1 (UNDEF).
Note that UNDEF is -1 not undef!

   The only multi-degree logic values are 0 (FALSE)..`-degree' - the value
of TRUE is equal to the degree, usually 100.

   The `-degree' is the maximum value (except for 2 and 3-degree logic);
i.e.  logic of n-degree is *n+1*-value logic, e.g. 100-degree logic has 101
values, 0..100.

   Although some useful constants may be exported, this is an object
module and the results of logical comparisons are Math::Logic objects.

2-degree logic
--------------

   2-degree logic has one simple truth table for each logical operator.

     Perl Logic      Perl Logic     Perl Logic
         A B and  and    A B or   or    A B xor  xor
         - - ---  ---    - - --   --    - - ---  ---
         F F  F    F     F F  F    F    F F  F    F
         T T  T    T     T T  T    T    T T  F    F
         T F  F    F     T F  T    T    T F  T    T
         F T  F    F     F T  T    T    F T  T    T

     Perl Logic
         A not  not
         - ---  ---
         F  T    T
         T  F    F

   In the above tables when dealing with Perl's built-in logic T and F are
any true and any false value respectively; with Math::Logic they are
objects whose values are 1 and 0 respectively. Note that whilst Perl may
return 0 or undef for false and any other value for true, Math::Logic
returns an object whose value is either 0 (FALSE) or 1 (TRUE) only.

     my $true   = Math::Logic->new( -value => $TRUE,  -degree => 2 ) ;
     my $false  = Math::Logic->new( -value => $FALSE, -degree => 2 ) ;

     my $result = $true & $false ; # my $result = $true->and( $false ) ;

     print $result if $result == $FALSE ;

3-degree logic
--------------

   3-degree logic has two different truth tables for "and" and "or"; this
module supports both. In the Perl column F means false or undefined; and
T, F and U under Math::Logic are objects with values 1 (TRUE), 0 (FALSE)
and -1 (UNDEF) respectively. The + signifies propagating nulls (UNDEFs).

     Perl  Logic        Perl  Logic         Perl  Logic
         A B and  and+ and    A B or or+  or    A B xor  xor+ xor(same)
         - - ---  ---  ---    - - -- --   --    - - ---  ---  ---
         U U  F    U    U     U U  F  U    U    U U  F    U    U
         U F  F    U    F     U F  F  U    U    U F  F    U    U
         F U  F    U    F     F U  F  U    U    F U  F    U    U
         F F  F    F    F     F F  F  F    F    F F  F    F    F
         U T  F    U    U     U T  T  U    T    U T  T    U    U
         T U  F    U    U     T U  T  U    T    T U  T    U    U
         T T  T    T    T     T T  T  T    T    T T  F    F    F
         T F  F    F    F     T F  T  T    T    T F  T    T    T
         F T  F    F    F     F T  T  T    T    F T  T    T    T

     Perl  Logic
         A not  not+ not(same)
         - ---  ---  ---
         U  T    U    U
         U  T    U    U
         F  T    T    T
         T  F    F    F

     # 3-degree logic (non-propagating)
     my $true   = Math::Logic->new( -value => $TRUE,  -degree => 3 ) ;
     my $false  = Math::Logic->new( -value => $FALSE, -degree => 3 ) ;
     my $undef  = Math::Logic->new( -value => $UNDEF, -degree => 3 ) ;

     my $result = $undef & $false ; # my $result = $undef->and( $false ) ;

     print $result if $result == $FALSE ;

     # 3-degree logic (propagating)
     my $true   = Math::Logic->new( -value => $TRUE,  -degree => 3, -propagate => 1 ) ;
     my $false  = Math::Logic->new( -value => $FALSE, -degree => 3, -propagate => 1 ) ;
     my $undef  = Math::Logic->new( -value => $UNDEF, -degree => 3, -propagate => 1 ) ;

     my $result = $undef & $false ; # my $result = $undef->and( $false ) ;

     print $result if $result == $UNDEF ;

multi-degree logic
------------------

   This is used in `fuzzy' logic. Typically we set the `-degree' to 100
representing 100% likely, i.e. true; 0 represents 0% likely, i.e. false,
and any integer in-between is a probability.

   The truth tables for multi-degree logic work like this:

     and     lowest  value is the result;
     or      highest value is the result;
     xor     by truth table xor(a,b) == and(or(a,b),not(and(a,b)))
     not     degree minus the value is the result.

     Logic
          A   B  and  or xor
         --- --- --- --- ---
           0   0   0   0   0
           0 100   0 100 100
         100   0   0 100 100
         100 100 100 100   0
           0  33   0  33  33
          33   0   0  33  33
          33 100  33 100  67
          33  33  33  33  33
         100  33  33 100  67
           0  67   0  67  67
          67   0   0  67  67
          67 100  67 100  33
          67  67  67  67  33
         100  67  67 100  33
          33  67  33  67  67
          67  33  33  67  67

     A  not
         --- ---
      0 100
     33  67
     67  33
         100   0

         # multi-degree logic
         my $True   = 100 ; # Define our own TRUE and FALSE
         my $False  = $FALSE ;
         $true      = Math::Logic->new( -value => $True,  -degree => $True ) ;
         $very      = Math::Logic->new( -value => 67,     -degree => $True ) ;
         $fairly    = Math::Logic->new( -value => 33,     -degree => $True ) ;
         $false     = Math::Logic->new( -value => $False, -degree => $True ) ;

     my $result = $fairly & $very ; # my $result = $fairly->and( $very ) ;

     print $result if $result == $fairly ;

Public methods
--------------

     new             class   object (also used for assignment)
     new_from_string class   object
     value                   object
     degree                  object
     propagate               object
     incompatible            object
     compatible              object (deprecated)
     as_string               object
     and                     object (same as &)
     or                      object (same as |)
     xor                     object (same as ^)
     not                     object (same as !)
     ""                      object (see as_string)
     0+                      object (automatically handled)
     <=>                     object (comparisons)
     &                       object (logical and)
     |                       object (logical or)
     ^                       object (logical xor)
     !                       object (logical not)

new (class and object method)
-----------------------------

     my $x = Math::Logic->new ;

     my $y = Math::Logic->new( -value => $FALSE, -degree => 3, -propagate => 0 );

     my $a = $x->new ;

     my $b = $y->new( -value => $TRUE ) ;

   This creates new Math::Logic objects. new should never fail because it
will munge any arguments into something `sensible'; in particular if the
value is set to -1 (UNDEF) for 2 or multi-degree logic it is silently
converted to 0 (FALSE). In all other cases anything that is true in Perl
is converted to 1 (TRUE) and everything else to 0 (FALSE).

   If used as an object method, e.g. for assignment then the settings are
those of the original object unless overridden. If used as a class method
with no arguments then default values are used.

   `-degree' an integer indicating the number of possible truth values;
typically set to 2, 3 or 100 (to represent percentages). Minimum value is
2.

   `-propagate' a true/false integer indicating whether NULLs (UNDEF)
should propagate; only applicable for 3-degree logic where it influences
which truth table is used.

   `-value' an integer representing the truth value. For 2-degree logic
only 1 and 0 are valid (TRUE and FALSE); for 3-degree logic 1, 0, and -1
are valid (TRUE, FALSE and UNDEF); for multi-degree logic any positive
integer less than or equal to the `-degree' is valid.

new_from_string (class and object method)
-----------------------------------------

     my $x = Math::Logic->new_from_string( '1,2' ) ;
     my $y = Math::Logic->new_from_string( 'TRUE,3,-propagate' ) ;
     my $z = Math::Logic->new_from_string( '( FALSE, 3, -propagate )' ) ;
     my $m = Math::Logic->new_from_string( '33,100' ) ;
     my $n = Math::Logic->new_from_string( '67%,100' ) ;

   This creates new Math::Logic objects. The string must include the first
two values, which are `-value' and `-degree' respectively.

   True  values can be expressed as  1, T or any word beginning with T,
e.g.  TRUE or -true; the pattern is /^-?[tT]/.  False values can be
expressed as  0, F or any word beginning with F, e.g.  FALSE or -false;
the pattern is /^-?[fF]/.  Undef values can be expressed as -1, U or any
word beginning with U, e.g.  UNDEF or -undef; the pattern is /^-?[uU]/.
Propagate is set to true by adding a third parameter matching /^-?[tTpP1]/,
e.g. -propagate. To set propagate to false either don't include a third
parameter or include it as 0 (zero).

value (object method)
---------------------

     print $x->value ;
     print $x ;

   This returns the numeric value of the object. For 2-degree logic this
will always be 1 or 0; for 3-degree logic the value will be 1, 0 or -1; for
multi-degree logic the value will be a positive integer <= `-degree'.

degree (object method)
----------------------

     print $x->degree ;

   This returns the degree of the object, i.e. the number of possible truth
values the object may hold; it is always 2 or more.

propagate (object method)
-------------------------

     print $x->propagate ;

   This returns whether or not the object propagates NULLs (UNDEF).
Objects using 2 or multi-degree logic always return FALSE; 3-degree logic
objects may return TRUE or FALSE.

incompatible (object method)
----------------------------

     print $x & $y unless $x->incompatible( $y ) ;

   Returns FALSE if the objects are compatible; returns an error string if
incompatible (which Perl treats as TRUE), e.g.:

     $x = Math::Logic->new_from_string('1,2') ;
     $y = Math::Logic->new_from_string('0,3') ;
     # The above are incompatible because the first uses 2-degree logic and the
     # second uses 3-degree logic.
     print $x->incompatible( $y ) if $x->incompatible( $y ) ;
     # This will print something like:
     Math::Logic(2,0) and Math::Logic(3,0) are incompatible at ./logic.t line 2102
     # The first number given is the degree and the second the propagate setting

   Objects are compatible if they have the same `-degree' and in the case
of 3-degree logic the same `-propagate'. Logical operators will only work
on compatible objects, there is no type-coersion (but see typecasting
later).

compatible DEPRECATED (object method)
-------------------------------------

     print $x->compatible( $y ) ;

   Returns TRUE or FALSE depending on whether the two objects are
compatible.  Objects are compatible if they have the same `-degree' and in
the case of 3-degree logic the same `-propagate'. Logical operators will
only work on compatible objects, there is no type-coersion (but see
typecasting later).

as_string and "" (object method)                                     # output:     print $x->as_string ;           # TRUE     print $x->as_string( 1 ) ;      # (TRUE,2)     print $x->as_string( -full ) ;  # (TRUE,2)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

     print $x ;                      # TRUE
     print $x->value ;               # 1

     print $m ;                      # 33
     print $m->value ;               # 33
     print $m->as_string( 1 ) ;      # (33%,100)

   Usually you won't have to bother using as_string since Perl will invoke
it for you as necessary; however if you want a string that can be saved,
(perhaps to be read in using `new_from_string' later), you can pass an
argument to as_string.

and and & (object method)
-------------------------

     print "true" if ( $y & $z ) == $TRUE ;
     print "yes"  if $y & 1 ;
     print "yes"  if $TRUE & $y ;

     $r = $y & $z ; # Creates a new Math::Logic object with the resultant truth value

     print "true" if $y->and( $z ) == $TRUE ;

   Applies logical and to two objects. The truth table used depends on the
object's `-degree' (and in the case of 3-degree logic on the `-propagate').
(See the truth tables above.)

or and | (object method)
------------------------

     print "true" if ( $y | $z ) == $TRUE ;
     print "yes"  if $y | 1 ;
     print "yes"  if $TRUE | $y ;

     $r = $y | $z ; # Creates a new Math::Logic object with the resultant truth value

     print "true" if $y->or( $z ) == $TRUE ;

   Applies logical or to two objects. The truth table used depends on the
object's `-degree' (and in the case of 3-degree logic on the `-propagate').
(See the truth tables above.)

xor and ^ (object method)
-------------------------

     print "true" if ( $y ^ $z ) == $TRUE ;
     print "yes"  if $y ^ 0 ;
     print "yes"  if $TRUE ^ $y ;

     $r = $y ^ $z ; # Creates a new Math::Logic object with the resultant truth value

     print "true" if $y->xor( $z ) == $TRUE ;

   Applies logical xor to two objects. The truth table used depends on the
object's `-degree'. (See the truth tables above.)

not and ! (object method)
-------------------------

     print "true" if ! $y == $TRUE ;

     $r = ! $y ; # Creates a new Math::Logic object with the resultant truth value

     print "true" if $y->not == $TRUE ;

   Applies logical not to the object. The truth table used depends on the
object's `-degree'. (See the truth tables above.)

comparisons and <=> (object method)
-----------------------------------

   All the standard (numeric) comparison operators may be applied to
Math::Logic objects, i.e. <, <=, >, =>, ==, != and <=>.

typecasting
-----------

   The only typecasting that appears to make sense is between 2 and
3-degree logic. There is no direct support for it but it can be achieved
thus:

     my $x = Math::Logic->new_from_string( '1,2' ) ;  # TRUE  2-degree
     my $y = Math::Logic->new_from_string( '0,3' ) ;  # FALSE 3-degree
     my $z = Math::Logic->new_from_string( '-1,3' ) ; # UNDEF 3-degree

     $x3 = $x->new( -degree => 3 ) ;
     $y2 = $y->new( -degree => 2 ) ;
     $z2 = $y->new( -degree => 2 ) ; # UNDEF converted silently to FALSE

BUGS
====

   Multi-degree logic has a minimum degree of 4, i.e. 5-value, 0..4.

   If you use & on two incompatible Math::Logic objects perl dies; I
believe that this is due to a problem with overload: it does not occur
with perl 5.6.0.

CHANGES
=======

   2000/05/25

   No changes; just corrected an error in the tarball that meant the test
would fail in some cases due to permissions problem.

   2000/05/22

   Dropped use of readonly pragma.

   2000/04/26

   Deleted quite a lot of internal error checks to improve speed.

   Class is now inheritable.

   2000/04/15

   Have switched constants to readonly scalars, i.e. $TRUE instead of TRUE
etc.  This makes them easier to use for certain things, e.g. string
interpolation and as array indexes or hash keys. The (now deprecated)
constants still work but you are recommended to use the constant scalars
instead. You will need to install `readonly.pm' which should be available
from wherever you got Math::Logic.

   The bugs with overload do not occur with perl 5.6.0. Added two tests
which are run if perl's version is > 5.005.

   2000/02/27

   Numerous minor documentation changes to clarify terminology.

   Two bugs noted.

   More tests added.

   2000/02/23

   Corrected multi-degree xor to match the truth table equivalence, i.e.

     xor(a,b) == and(or(a,b),not(and(a,b)))

   which can be expressed in Math::Logic as

     $a->xor( $b ) == $a->or( $b )->and( $a->and( $b )->not )

   or as

     $a ^ $b == ( $a | $b ) & ( ! ( $a & $b ) )

   2000/02/22

   Minor correction to _croak so that error messages don't list filename
and line twice; plus other minor cleanups to improve error output.

   Changed the way new_from_string handles string truth values; numeric
truth values operate as before.

   2000/02/21

   Added incompatible method and now deprecate compatible method; this
provides better error messages; updated test script.

   2000/02/20

   Minor documentation fixes. Also eliminated a warning that occurred under
5.005.

   2000/02/19

   First version. Ideas taken from my Math::Logic3 and (unpublished)
Math::Fuzzy; this module is intended to supercede both.

AUTHOR
======

   Mark Summerfield. I can be contacted as <summer@perlpress.com> - please
include the word 'logic' in the subject line.

COPYRIGHT
=========

   Copyright (c) Mark Summerfield 2000. All Rights Reserved.

   This module may be used/distributed/modified under the LGPL.

Magic Square Checker
********************

NAME
====

   Math::MagicSquare - Magic Square Checker

SYNOPSIS
========

     use Math::MagicSquare;

     $a= Math::MagicSquare -> new ([num,...,num],
                                    ...,
                                   [num,...,num]);
     $a->print("string");
     $a->printhtml();
     $a->check();
     $a->rotation();
     $a->reflection();

DESCRIPTION
===========

   The following methods are available:

new
---

   Constructor arguments are a list of references to arrays of the same
length.

     $a = Math::MagicSquare -> new ([num,...,num],
                                     ...,
                                    [num,...,num]);

check
-----

   This function can return 4 value

   * *0:* the Square is not Magic

   * *1:* the Square is a *Semimagic Square* (the sum of the rows and the
     columns is equal)

   * *2:* the Square is a *Magic Square* (the sum of the rows, the columns
     and the diagonals is equal)

   * *3:* the Square ia *Panmagic Square* (the sum of the rows, the
     columns, the diagonals and the broken diagonals is equal)

print
-----

   Prints the Square on STDOUT. If the method has additional parameters,
these are printed before the Magic Square is printed.

printhtml
---------

   Prints the Square on STDOUT in an HTML format (exactly a inside a TABLE)

rotation
--------

   Rotates the Magic Square of 90 degree clockwise

reflection
----------

   Reflect the Magic Square

EXAMPLE
=======

     use Math::MagicSquare;

     $A = Math::MagicSquare -> new ([8,1,6],
                                    [3,5,7],
                                    [4,9,2]);
     $A->print("Magic Square A:\n");
     $A->printhtml;
     $i=$A->check;
     if($i == 2) {print "This is a Magic Square.\n";}
     $A->rotation();
     $A->print("Rotation:\n");
     $A->reflection();
     $A->print("Reflection:\n");

     This is the output:
        Magic Square A:
            8     1     6
            3     5     7
            4     9     2
        <TABLE border=3 width="2" height="2" cellpadding=1 cellspacing=1>
        <TR>
        <TD align=right><FONT size=+2><B>8</B></font></TD>
        <TD align=right><FONT size=+2><B>1</B></font></TD>
        <TD align=right><FONT size=+2><B>6</B></font></TD>
        </TR>
        <TR>
        <TD align=right><FONT size=+2><B>3</B></font></TD>
        <TD align=right><FONT size=+2><B>5</B></font></TD>
        <TD align=right><FONT size=+2><B>7</B></font></TD>
        </TR>
        <TR>
        <TD align=right><FONT size=+2><B>4</B></font></TD>
        <TD align=right><FONT size=+2><B>9</B></font></TD>
        <TD align=right><FONT size=+2><B>2</B></font></TD>
        </TR>
        </TABLE>
        This is a Magic Square.
        Rotation:
            4     3     8
            9     5     1
            2     7     6
        Reflection:
            8     3     4
            1     5     9
            6     7     2

AUTHOR
======

     Fabrizio Pivari pivari@geocities.com
     member of ANFACE Software http://www.geocities.com/CapeCanaveral/Hangar/4794/

Copyright
=========

     Copyright 1998, Fabrizio Pivari pivari@geocities.com
     This library is free software; you can redistribute it and/or modify it under
     the same terms as Perl itself.

Availability
============

     The latest version of this library is likely to be available from:
     http://www.geocities.com/CapeCanaveral/Lab/3469/
     and at any CPAN mirror

Information about Magic Square
==============================

     Do you like Magic Square?
     Do you want to know more information about Magic Square?
     Try to visit

A very good introduction on Magic Square
     http://www.astro.virginia.edu/~eww6n/math/MagicSquare.html

A whole collection of links and documents in Internet
     http://www.pse.che.tohoku.ac.jp/~msuzuki/MagicSquare.html

A good collection of strange Magic Square
     http://www.geocities.com/CapeCanaveral/Lab/3469/examples.html

The only Magic Square checker and gif maker in Internet (I think)
     http://www.geocities.com/CapeCanaveral/Lab/3469/squaremaker.html

Multiply and invert Matrices
****************************

NAME
====

   Math::Matrix - Multiply and invert Matrices

DESCRIPTION
===========

   The following methods are available:

new
---

   Constructor arguments are a list of references to arrays of the same
length.  The arrays are copied. The method returns undef in case of error.

     $a = new Math::Matrix ([rand,rand,rand],
                            [rand,rand,rand],
                            [rand,rand,rand]);

concat
------

   Concatenates two matrices of same row count. The result is a new matrix
or undef in case of error.

     $b = new Math::Matrix ([rand],[rand],[rand]);
     $c = $a->concat($b);

transpose
---------

   Returns the transposed matrix. This is the matrix where colums and rows
of the argument matrix are swaped.

multiply
--------

   Multiplies two matrices where the length of the rows in the first
matrix is the same as the length of the columns in the second matrix.
Returns the product or undef in case of error.

solve
-----

   Solves a equation system given by the matrix. The number of colums must
be greater than the number of rows. If variables are dependent from each
other, the second and all further of the dependent coefficients are 0.
This means the method can handle such systems. The method returns a matrix
containing the solutions in its columns or undef in case of error.

print
-----

   Prints the matrix on STDOUT. If the method has additional parameters,
these are printed before the matrix is printed.

EXAMPLE
=======

     use Math::Matrix;

     srand(time);
     $a = new Math::Matrix ([rand,rand,rand],
                      [rand,rand,rand],
                      [rand,rand,rand]);
     $x = new Math::Matrix ([rand,rand,rand]);
     $a->print("A\n");
     $E = $a->concat($x->transpose);
     $E->print("Equation system\n");
     $s = $E->solve;
     $s->print("Solutions s\n");
     $a->multiply($s)->print("A*s\n");

AUTHOR
======

   Ulrich Pfeifer <pfeifer@ls6.informatik.uni-dortmund.de>

Matrix of Booleans
******************

NAME
====

   Math::MatrixBool - Matrix of Booleans

   Easy manipulation of matrices of booleans (Boolean Algebra)

SYNOPSIS
========

   * `use Math::MatrixBool;'

   * `$new_matrix = new Math::MatrixBool($rows,$columns);'

     the matrix object constructor method

     An exception is raised if the necessary memory cannot be allocated.

   * `$new_matrix = Math::MatrixBool->new($rows,$columns);'

     alternate way of calling the matrix object constructor method

   * `$new_matrix = $some_matrix->'`new($rows,$columns);'

     still another way of calling the matrix object constructor method
     ($some_matrix is not affected by this)

   * `$new_matrix = Math::MatrixBool->'`new_from_string($string);'

     This method allows you to read in a matrix from a string (for
     instance, from the keyboard, from a file or from your code).

     The syntax is simple: each row must start with "`[ '" and end with "`
     ]\n'" ("\n" being the newline character and "` '" a space or tab) and
     contain one or more numbers, all separated from each other by spaces
     or tabs.

     Additional spaces or tabs can be added at will, but no comments.

     Numbers are either "0" or "1".

     Examples:

          $string = "[ 1 0 0 ]\n[ 1 1 0 ]\n[ 1 1 1 ]\n";
          $matrix = Math::MatrixBool->new_from_string($string);
          print "$matrix";

     By the way, this prints

          [ 1 0 0 ]
          [ 1 1 0 ]
          [ 1 1 1 ]

     But you can also do this in a much more comfortable way using the
     shell-like "here-document" syntax:

          $matrix = Math::MatrixBool->new_from_string(<<'MATRIX');
          [  1  0  0  0  0  0  1  ]
          [  0  1  0  0  0  0  0  ]
          [  0  0  1  0  0  0  0  ]
          [  0  0  0  1  0  0  0  ]
          [  0  0  0  0  1  0  0  ]
          [  0  0  0  0  0  1  0  ]
          [  1  0  0  0  0  0  1  ]
          MATRIX

     You can even use variables in the matrix:

          $c1  =  $A1 * $x1 - $b1 >= 0  ?"1":"0";
          $c1  =  $A2 * $x2 - $b2 >= 0  ?"1":"0";
          $c1  =  $A3 * $x3 - $b3 >= 0  ?"1":"0";

          $matrix = Math::MatrixBool->new_from_string(<<"MATRIX");

          [   1    0    0   ]
          [   0    1    0   ]
          [  $c1  $c2  $c3  ]

          MATRIX

     (Remember that you may use spaces and tabs to format the matrix to
     your taste)

     Note that this method uses exactly the same representation for a
     matrix as the "stringify" operator "": this means that you can convert
     any matrix into a string with `$string = "$matrix";' and read it back
     in later (for instance from a file!).

     If the string you supply (or someone else supplies) does not obey the
     syntax mentioned above, an exception is raised, which can be caught
     by "eval" as follows:

          print "Please enter your matrix (in one line): ";
          $string = <STDIN>;
          $string =~ s/\\n/\n/g;
          eval { $matrix = Math::MatrixBool->new_from_string($string); };
          if ($@)
          {
              print "$@";
              # ...
              # (error handling)
          }
          else
          {
              # continue...
          }

     or as follows:

          eval { $matrix = Math::MatrixBool->new_from_string(<<"MATRIX"); };
          [   1    0    0   ]
          [   0    1    0   ]
          [  $c1  $c2  $c3  ]
          MATRIX
          if ($@)
          # ...

     Actually, the method shown above for reading a matrix from the
     keyboard is a little awkward, since you have to enter a lot of "\n"'s
     for the newlines.

     A better way is shown in this piece of code:

          while (1)
          {
              print "\nPlease enter your matrix ";
              print "(multiple lines, <ctrl-D> = done):\n";
              eval { $new_matrix =
                  Math::MatrixBool->new_from_string(join('',<STDIN>)); };
              if ($@)
              {
                  $@ =~ s/\s+at\b.*?$//;
                  print "${@}Please try again.\n";
              }
              else { last; }
          }

     Possible error messages of the "new_from_string()" method are:

          Math::MatrixBool::new_from_string(): syntax error in input string
          Math::MatrixBool::new_from_string(): empty input string

     If the input string has rows with varying numbers of columns, the
     following warning will be printed to STDERR:

          Math::MatrixBool::new_from_string(): missing elements will be set to zero!

     If everything is okay, the method returns an object reference to the
     (newly allocated) matrix containing the elements you specified.

   * `($rows,$columns) = $matrix->Dim();'

     returns the dimensions (= number of rows and columns) of the given
     matrix

   * `$matrix->Empty();'

     sets all elements in the matrix to "0"

   * `$matrix->Fill();'

     sets all elements in the matrix to "1"

   * `$matrix->Flip();'

     flips (i.e., complements) all elements in the given matrix

   * `$matrix->Zero();'

     sets all elements in the matrix to "0"

   * `$matrix->One();'

     fills the matrix with one's in the main diagonal and zero's elsewhere

     Note that multiplying this matrix with itself yields the same matrix
     again (provided it is a square matrix)!

   * `$matrix->Bit_On($row,$column);'

     sets a given element to "1"

   * `$matrix->Insert($row,$column);'

     alias for "Bit_On()", deprecated

   * `$matrix->Bit_Off($row,$column);'

     sets a given element to "0"

   * `$matrix->Delete($row,$column);'

     alias for "Bit_Off()", deprecated

   * `$boolean = $matrix->'`bit_flip($row,$column);'

     flips (i.e., complements) a given element and returns its new value

   * `$boolean = $matrix->'`flip($row,$column);'

     alias for "bit_flip()", deprecated

   * `$boolean = $matrix->'`bit_test($row,$column);'

     tests wether a given element is set

   * `$boolean = $matrix->'`contains($row,$column);'

     tests wether a given element is set (alias for "bit_test()")

   * `$boolean = $matrix->'`in($row,$column);'

     alias for "bit_test()", deprecated

   * `$elements = $matrix->Number_of_elements();'

     calculates the number of elements contained in the given matrix

   * `$norm_max = $matrix->Norm_max();'

     calculates the "maximum"-norm of the given matrix

   * `$norm_one = $matrix->Norm_one();'

     calculates the "1"-norm of the given matrix

   * `$matrix1->Addition($matrix2,$matrix3);'

     calculates the sum of matrix2 and matrix3 and stores the result in
     matrix1 (in-place is also possible)

   * `$product_matrix = $matrix1->Multiplication($matrix2);'

     calculates the product of matrix1 and matrix2 and returns an object
     reference to a new matrix where the result is stored; uses "^" as
     boolean addition operator internally

   * `$product_matrix = $matrix1->Product($matrix2);'

     calculates the product of matrix1 and matrix2 and returns an object
     reference to a new matrix where the result is stored; uses "|" as
     boolean addition operator internally

   * `$closure = $matrix->Kleene();'

     computes the reflexive transitive closure of the given matrix and
     returns a new matrix containing the result. (The original matrix is
     not changed by this in any way!)

     Uses a variant of Kleene's algorithm. See `Math::Kleene(3)' in this
     node for more details about this algorithm!

     This algorithm is mainly used in graph theory: Each position in the
     matrix corresponds to a (directed!) possible connection ("edge")
     between two points ("vortices") of a graph. Each position in the
     matrix contains a "1" if the corresponding edge is part of the graph
     and a "0" if not.

     Computing the closure of this matrix means to find out if there is a
     path from any vortice of the graph to any other (a path consisting of
     one or more edges).

     Note that there are more applications of Kleene's algorithm in other
     fields as well (see also Math::MatrixReal(3), DFA::Kleene(3),
     Math::Kleene(3)).

   * `$matrix1->Union($matrix2,$matrix3);'

     calculates the union of matrix2 and matrix3 and stores the result in
     matrix1 (in-place is also possible)

   * `$matrix1->Intersection($matrix2,$matrix3);'

     calculates the intersection of matrix2 and matrix3 and stores the
     result in matrix1 (in-place is also possible)

   * `$matrix1->Difference($matrix2,$matrix3);'

     calculates matrix2 "minus" matrix3 ( = matrix2 \ matrix3 ) and stores
     the result in matrix1 (in-place is also possible)

     Note that this is set difference, not matrix difference! Matrix
     difference degenerates to (= is the same as) matrix addition in a
     Boolean Algebra!!

   * `$matrix1->ExclusiveOr($matrix2,$matrix3);'

     calculates the exclusive-or (which in the case of a Boolean Algebra
     happens to be the same as the addition) of matrix2 and matrix3 and
     stores the result in matrix1 (in-place is also possible)

   * `$matrix1->Complement($matrix2);'

     calculates the complement of matrix2 and stores the result in matrix1
     (in-place is also possible)

   * `$matrix1->Transpose($matrix2);'

     calculates the transpose of matrix2 and stores the result in matrix1
     (in-place is also possible if and only if the matrix is a square
     matrix!); in general, matrix1 must have reversed numbers of rows and
     columns in relation to matrix2

   * `$boolean = $matrix1->equal($matrix2);'

     tests if matrix1 is the same as matrix2

   * `$boolean = $matrix1->subset($matrix2);'

     tests if matrix1 is a subset of matrix2

   * `$boolean = $matrix1->inclusion($matrix2);'

     alias for "subset()", deprecated

   * `$boolean = $matrix1->lexorder($matrix2);'

     tests if matrix1 comes lexically before matrix2, i.e., if (matrix1 <=
     matrix2) holds, as though the two bit vectors used to represent the
     two matrices were two large numbers in binary representation

     (Note that this is an *arbitrary* order relationship!)

   * `$result = $matrix1->Compare($matrix2);'

     lexically compares matrix1 and matrix2 and returns -1, 0 or 1 if
     (matrix1 < matrix2), (matrix1 == matrix2) or (matrix1 > matrix2)
     holds, respectively

     (Again, the two bit vectors representing the two matrices are
     compared as though they were two large numbers in binary
     representation)

   * `$matrix1->Copy($matrix2);'

     copies the contents of matrix2 to an *ALREADY EXISTING* matrix1

   * `$new_matrix = $some_matrix->Shadow();'

     returns an object reference to a NEW but EMPTY matrix of the *SAME
     SIZE* as some_matrix

   * `$twin_matrix = $some_matrix->Clone();'

     returns an object reference to a NEW matrix of the *SAME SIZE* as
     some_matrix; the contents of some_matrix have *ALREADY BEEN COPIED*
     to the new matrix

   * *Hint: method names all in lower case indicate a boolean return
     value!*

     (Except for "new()" and "new_from_string()", of course!)

   Please refer to `"OVERLOADED OPERATORS"' in this node below for ways of
using overloaded operators instead of explicit method calls in order to
facilitate calculations with matrices!

DESCRIPTION
===========

   This class lets you dynamically create boolean matrices of arbitrary
size and perform all the basic operations for matrices on them, like

-
     setting or deleting elements,

-
     testing wether a certain element is set,

-
     computing the sum, difference, product, closure and complement of
     matrices,

     (you can also compute the union, intersection, difference and
     exclusive-or of the underlying bit vector)

-
     copying matrices,

-
     testing two matrices for equality or inclusion (subset relationship),
     and

-
     computing the number of elements and the norm of a matrix.

   Please refer to `"OVERLOADED OPERATORS"' in this node below for ways of
using overloaded operators instead of explicit method calls in order to
facilitate calculations with matrices!

OVERLOADED OPERATORS
====================

   Calculations with matrices can not only be performed with explicit
method calls using this module, but also through "magical" overloaded
arithmetic and relational operators.

   For instance, instead of writing

     $matrix1 = Math::MatrixBool->new($rows,$columns);
     $matrix2 = Math::MatrixBool->new($rows,$columns);
     $matrix3 = Math::MatrixBool->new($rows,$columns);

     [...]

     $matrix3->Multiplication($matrix1,$matrix2);

   you can just say

     $matrix1 = Math::MatrixBool->new($rows,$columns);
     $matrix2 = Math::MatrixBool->new($rows,$columns);

     [...]

     $matrix3 = $matrix1 * $matrix2;

   That's all!

   Here is the list of all "magical" overloaded operators and their
semantics (meaning):

   Unary operators: '-', '~', 'abs', testing, '!', '""'

   Binary (arithmetic) operators: '+', '*', '|', '-', '&', '^'

   Binary (relational) operators: '==', '!=', '<', '<=', '>', '>='

   Binary (relational) operators: 'cmp', 'eq', 'ne', 'lt', 'le', 'gt', 'ge'

   Note that both arguments to a binary operator from the list above must
be matrices; numbers or other types of data are not permitted as arguments
and will produce an error message.

'-'
     Unary Minus / Complement ( `$matrix2 = -$matrix1;' )

     The unary operator '-' computes the complement of the given matrix.

'~'
     Transpose ( `$matrix2 = ~$matrix1;' )

     The operator '~' computes the transpose of the given matrix.

abs
     Absolute Value ( `$no_of_elem = abs($matrix);' )

     Here, the absolute value of a matrix has been defined as the number
     of elements the given matrix contains. This is *NOT* the same as the
     "norm" of a matrix!

test
     Boolean Test ( `if ($matrix) { ... }' )

     You can actually test a matrix as though it were a boolean value.

     No special operator is needed for this; Perl automatically calls the
     appropriate method in this package if "$matrix" is a blessed reference
     to an object of the "Math::MatrixBool" class or one of its derived
     classes.

     This operation returns "true" (1) if the given matrix is not empty and
     "false" (") otherwise.

'!'
     Negated Boolean Test ( `if (! $matrix) { ... }' )

     You can also perform a negated test on a matrix as though it were a
     boolean value. For example:

          if (! $matrix) { ... }

          unless ($matrix) { ... }     #  internally, same as above!

     This operation returns "true" (1) if the given matrix is empty and
     "false" (") otherwise.

'""""'
     "Stringification" ( `print "$matrix";' )

     It is possible to get a string representation of a given matrix by
     just putting the matrix object reference between double quotes.

     Note that in general the string representation of a matrix will span
     over multiple lines (i.e., the string which is generated contains
     "\n" characters, one at the end of each row of the matrix).

     Example:

          $matrix = new Math::MatrixBool(5,6);
          $matrix->One();
          print "$matrix";

     This will print:

          [ 1 0 0 0 0 0 ]
          [ 0 1 0 0 0 0 ]
          [ 0 0 1 0 0 0 ]
          [ 0 0 0 1 0 0 ]
          [ 0 0 0 0 1 0 ]

'+'
     Addition ( `$matrix3 = $matrix1 + $matrix2;' )

     The '+' operator calculates the sum of two matrices.

     Examples:

          $all   =  $odd + $even;

          $all  +=  $odd;
          $all  +=  $even;

     Note that the '++' operator will produce an error message if applied
     to an object of this class because adding a number to a matrix makes
     no sense.

     Multiplication ( `$matrix3 = $matrix1 * $matrix2;' )

     The '*' operator calculates the matrix product of two matrices.

     Examples:

          $test   =  $one * $one;

          $test  *=  $one;
          $test  *=  $test;

     Note that you can use matrices of any size as long as their numbers of
     rows and columns correspond in the following way (example):

          $matrix_3 = $matrix_1 * $matrix_2;

          [ 2 2 ]
          [ 2 2 ]
          [ 2 2 ]

          [ 1 1 1 ]   [ 3 3 ]
          [ 1 1 1 ]   [ 3 3 ]
          [ 1 1 1 ]   [ 3 3 ]
          [ 1 1 1 ]   [ 3 3 ]

     I.e., the number of columns of matrix #1 is the same as the number of
     rows of matrix #2, and the number of rows and columns of the resulting
     matrix #3 is determined by the number of rows of matrix #1 and the
     number of columns of matrix #2, respectively.

     This way you can also perform the multiplication of a matrix with a
     vector, since a vector is just a degenerated matrix with several rows
     but only one column, or just one row and several columns.

'|'
     Union ( `$matrix3 = $matrix1 | $matrix2;' )

     The '|' operator is used to calculate the union of two matrices (of
     corresponding elements).

     Examples:

          $all   =  $odd | $even;

          $all  |=  $odd;
          $all  |=  $even;

'-'
     Difference ( `$matrix3 = $matrix1 - $matrix2;' )

     The operator '-' calculates the (dotted) difference of two matrices,
     i.e.,

          0 - 0 == 0
          0 - 1 == 0
          1 - 0 == 1
          1 - 1 == 0

     for each corresponding element.

     Examples:

          $odd   =  $all  - $even;

          $all  -=  $even;

     Note that the '-' operator will produce an error message if applied
     to an object of this class because subtracting a number from a matrix
     makes no sense.

'&'
     Intersection ( `$matrix3 = $matrix1 & $matrix2;' )

     The '&' operator is used to calculate the intersection of two matrices
     (of the corresponding elements).

     Examples:

          $rest  =  $all & $even;

          $all  &=  $even;

'^'
     ExclusiveOr ( `$matrix3 = $matrix1 ^ $matrix2;' )

     The '^' operator is used to calculate the exclusive-or of two matrices
     (of their corresponding elements).

     In fact this operation is identical with the addition of two matrices
     in this case of a Boolean Algebra.

     Examples:

          $odd   =  $all  ^ $even;

          $all  ^=  $even;

'=='
     Test For Equality ( `if ($matrix1 == $matrix2) { ... }' )

     This operator tests two matrices for equality.

     Note that *without* operator overloading, `( $matrix1 == $matrix2 )'
     would test wether the two references *pointed to* the *same object*!
     (!)

     With operator overloading in effect, `( $matrix1 == $matrix2 )' tests
     wether the two matrix objects *contain* exactly the *same elements*!

'!='
     Test For Non-Equality ( `if ($matrix1 != $matrix2) { ... }' )

     This operator tests wether two matrices are different.

     Note again that this tests wether the *contents* of the two matrices
     are not the same, and not wether the two references are different!

'<'
     Test For True Subset ( `if ($matrix1 < $matrix2) { ... }' )

     This operator tests wether $matrix1 is a true subset of $matrix2, i.e.
     wether the elements contained in $matrix1 are also contained in
     $matrix2, but not all elements contained in $matrix2 are contained in
     $matrix1.

     Example:

          [ 1 0 0 0 0 ]                       [ 1 0 0 0 1 ]
          [ 0 1 0 0 0 ]                       [ 0 1 0 0 0 ]
          [ 0 0 1 0 0 ]  is a true subset of  [ 0 0 1 0 0 ]
          [ 0 0 0 1 0 ]                       [ 0 0 0 1 0 ]
          [ 1 0 0 0 1 ]                       [ 1 0 0 0 1 ]

          [ 1 0 0 0 0 ]                       [ 1 0 0 0 1 ]
          [ 0 1 0 0 0 ]                       [ 0 1 0 0 0 ]
             but  [ 0 0 1 0 0 ]   is not a subset of  [ 0 0 1 0 0 ]
          [ 0 0 0 1 0 ]                       [ 0 0 0 1 0 ]
          [ 1 0 0 0 1 ]                       [ 0 0 0 0 1 ]

     (nor vice-versa!)

          [ 1 0 0 0 1 ]                       [ 1 0 0 0 1 ]
          [ 0 1 0 0 0 ]                       [ 0 1 0 0 0 ]
             and  [ 0 0 1 0 0 ]     is a subset of    [ 0 0 1 0 0 ]
          [ 0 0 0 1 0 ]                       [ 0 0 0 1 0 ]
          [ 1 0 0 0 1 ]                       [ 1 0 0 0 1 ]

     but not a true subset because the two matrices are identical.

'<='
     Test For Subset ( `if ($matrix1 <= $matrix2) { ... }' )

     This operator tests wether $matrix1 is a subset of $matrix2, i.e.
     wether all elements contained in $matrix1 are also contained in
     $matrix2.

     This also evaluates to "true" when the two matrices are the same.

'>'
     Test For True Superset ( `if ($matrix1 > $matrix2) { ... }' )

     This operator tests wether $matrix1 is a true superset of $matrix2,
     i.e.  wether all elements contained in $matrix2 are also contained in
     $matrix1, but not all elements contained in $matrix1 are contained in
     $matrix2.

     Note that `($matrix1 > $matrix2)' is exactly the same as `($matrix2 <
     $matrix1)'.

'>='
     Test For Superset ( `if ($matrix1 >= $matrix2) { ... }' )

     This operator tests wether $matrix1 is a superset of $matrix2, i.e.
     wether all elements contained in $matrix2 are also contained in
     $matrix1.

     This also evaluates to "true" when the two matrices are equal.

     Note that `($matrix1 >= $matrix2)' is exactly the same as `($matrix2
     <= $matrix1)'.

cmp
     Compare ( `$result = $matrix1 cmp $matrix2;' )

     This operator compares the two matrices lexically, i.e. it regards the
     two bit vectors representing the two matrices as two large (unsigned)
     numbers in binary representation and returns "-1" if the number for
     $matrix1 is smaller than that for $matrix2, "0" if the two numbers are
     the same (i.e., when the two matrices are equal!) or "1" if the number
     representing $matrix1 is larger than the number representing $matrix2.

     Note that this comparison has nothing to do whatsoever with algebra,
     it is just an *arbitrary* order relationship!

     It is only intended to provide an (arbitrary) order by which (for
     example) an array of matrices can be sorted, for instance to find out
     quickly (using binary search) if a specific matrix has already been
     produced before in some matrix-producing process or not.

eq
     "equal"

ne
     "not equal"

lt
     "less than"

le
     "less than or equal"

gt
     "greater than"

ge
     "greater than or equal"

     These are all operators derived from the "cmp" operator (see above).

     They can be used instead of the "cmp" operator to make the intended
     type of comparison more obvious in your code.

     For instance, `($matrix1 le $matrix2)' is much more readable and
     clearer than `(($matrix1 cmp $matrix2) <= 0)'!

SEE ALSO
========

   Bit::Vector(3), Math::MatrixReal(3), DFA::Kleene(3), Math::Kleene(3),
Set::IntegerFast(3), Set::IntegerRange(3).

VERSION
=======

   This man page documents "Math::MatrixBool" version 5.7.

AUTHOR
======

   Steffen Beyer <sb@sdm.de>.

COPYRIGHT
=========

   Copyright (c) 1995, 1996, 1997, 1998, 1999 by Steffen Beyer.  All
rights reserved.

LICENSE AGREEMENT
=================

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Matrix of Reals
***************

NAME
====

   Math::MatrixReal - Matrix of Reals

   Implements the data type "matrix of reals" (and consequently also
"vector of reals")

DESCRIPTION
===========

   Implements the data type "matrix of reals", which can be used almost
like any other basic Perl type thanks to *OPERATOR OVERLOADING*, i.e.,

     $product = $matrix1 * $matrix2;

   does what you would like it to do (a matrix multiplication).

   Also features many important operations and methods: matrix norm,
matrix transposition, matrix inverse, determinant of a matrix, order and
numerical condition of a matrix, scalar product of vectors, vector product
of vectors, vector length, projection of row and column vectors, a
comfortable way for reading in a matrix from a file, the keyboard or your
code, and many more.

   Allows to solve linear equation systems using an efficient algorithm
known as "L-R-decomposition" and several approximative (iterative) methods.

   Features an implementation of Kleene's algorithm to compute the minimal
costs for all paths in a graph with weighted edges (the "weights" being
the costs associated with each edge).

SYNOPSIS
========

   * `use Math::MatrixReal;'

     Makes the methods and overloaded operators of this module available
     to your program.

   * `use Math::MatrixReal qw(min max);'

   * `use Math::MatrixReal qw(:all);'

     Use one of these two variants to import (all) the functions which the
     module offers for export; currently these are "min()" and "max()".

   * `$new_matrix = new Math::MatrixReal($rows,$columns);'

     The matrix object constructor method.

     Note that this method is implicitly called by many of the other
     methods in this module!

   * `$new_matrix = Math::MatrixReal->'`new($rows,$columns);'

     An alternate way of calling the matrix object constructor method.

   * `$new_matrix = $some_matrix->'`new($rows,$columns);'

     Still another way of calling the matrix object constructor method.

     Matrix "`$some_matrix'" is not changed by this in any way.

   * `$new_matrix = Math::MatrixReal->'`new_from_string($string);'

     This method allows you to read in a matrix from a string (for
     instance, from the keyboard, from a file or from your code).

     The syntax is simple: each row must start with "`[ '" and end with "`
     ]\n'" ("\n" being the newline character and "` '" a space or tab) and
     contain one or more numbers, all separated from each other by spaces
     or tabs.

     Additional spaces or tabs can be added at will, but no comments.

     Examples:

          $string = "[ 1 2 3 ]\n[ 2 2 -1 ]\n[ 1 1 1 ]\n";
          $matrix = Math::MatrixReal->new_from_string($string);
          print "$matrix";

     By the way, this prints

          [  1.000000000000E+00  2.000000000000E+00  3.000000000000E+00 ]
          [  2.000000000000E+00  2.000000000000E+00 -1.000000000000E+00 ]
          [  1.000000000000E+00  1.000000000000E+00  1.000000000000E+00 ]

     But you can also do this in a much more comfortable way using the
     shell-like "here-document" syntax:

          $matrix = Math::MatrixReal->new_from_string(<<'MATRIX');
          [  1  0  0  0  0  0  1  ]
          [  0  1  0  0  0  0  0  ]
          [  0  0  1  0  0  0  0  ]
          [  0  0  0  1  0  0  0  ]
          [  0  0  0  0  1  0  0  ]
          [  0  0  0  0  0  1  0  ]
          [  1  0  0  0  0  0 -1  ]
          MATRIX

     You can even use variables in the matrix:

          $c1 =   2  /  3;
          $c2 =  -2  /  5;
          $c3 =  26  /  9;

          $matrix = Math::MatrixReal->new_from_string(<<"MATRIX");

          [   3    2    0   ]
          [   0    3    2   ]
          [  $c1  $c2  $c3  ]

          MATRIX

     (Remember that you may use spaces and tabs to format the matrix to
     your taste)

     Note that this method uses exactly the same representation for a
     matrix as the "stringify" operator "": this means that you can convert
     any matrix into a string with `$string = "$matrix";' and read it back
     in later (for instance from a file!).

     Note however that you may suffer a precision loss in this process
     because only 13 digits are supported in the mantissa when printed!!

     If the string you supply (or someone else supplies) does not obey the
     syntax mentioned above, an exception is raised, which can be caught
     by "eval" as follows:

          print "Please enter your matrix (in one line): ";
          $string = <STDIN>;
          $string =~ s/\\n/\n/g;
          eval { $matrix = Math::MatrixReal->new_from_string($string); };
          if ($@)
          {
              print "$@";
              # ...
              # (error handling)
          }
          else
          {
              # continue...
          }

     or as follows:

          eval { $matrix = Math::MatrixReal->new_from_string(<<"MATRIX"); };
          [   3    2    0   ]
          [   0    3    2   ]
          [  $c1  $c2  $c3  ]
          MATRIX
          if ($@)
          # ...

     Actually, the method shown above for reading a matrix from the
     keyboard is a little awkward, since you have to enter a lot of "\n"'s
     for the newlines.

     A better way is shown in this piece of code:

          while (1)
          {
              print "\nPlease enter your matrix ";
              print "(multiple lines, <ctrl-D> = done):\n";
              eval { $new_matrix =
                  Math::MatrixReal->new_from_string(join('',<STDIN>)); };
              if ($@)
              {
                  $@ =~ s/\s+at\b.*?$//;
                  print "${@}Please try again.\n";
              }
              else { last; }
          }

     Possible error messages of the "new_from_string()" method are:

          Math::MatrixReal::new_from_string(): syntax error in input string
          Math::MatrixReal::new_from_string(): empty input string

     If the input string has rows with varying numbers of columns, the
     following warning will be printed to STDERR:

          Math::MatrixReal::new_from_string(): missing elements will be set to zero!

     If everything is okay, the method returns an object reference to the
     (newly allocated) matrix containing the elements you specified.

   * `$new_matrix = $some_matrix->shadow();'

     Returns an object reference to a NEW but EMPTY matrix (filled with
     zero's) of the *SAME SIZE* as matrix "`$some_matrix'".

     Matrix "`$some_matrix'" is not changed by this in any way.

   * `$matrix1->copy($matrix2);'

     Copies the contents of matrix "`$matrix2'" to an *ALREADY EXISTING*
     matrix "`$matrix1'" (which must have the same size as matrix
     "`$matrix2'"!).

     Matrix "`$matrix2'" is not changed by this in any way.

   * `$twin_matrix = $some_matrix->clone();'

     Returns an object reference to a NEW matrix of the *SAME SIZE* as
     matrix "`$some_matrix'". The contents of matrix "`$some_matrix'" have
     *ALREADY BEEN COPIED* to the new matrix "`$twin_matrix'".

     Matrix "`$some_matrix'" is not changed by this in any way.

   * `$row_vector = $matrix->row($row);'

     This is a projection method which returns an object reference to a
     NEW matrix (which in fact is a (row) vector since it has only one
     row) to which row number "`$row'" of matrix "`$matrix'" has already
     been copied.

     Matrix "`$matrix'" is not changed by this in any way.

   * `$column_vector = $matrix->column($column);'

     This is a projection method which returns an object reference to a
     NEW matrix (which in fact is a (column) vector since it has only one
     column) to which column number "`$column'" of matrix "`$matrix'" has
     already been copied.

     Matrix "`$matrix'" is not changed by this in any way.

   * `$matrix->zero();'

     Assigns a zero to every element of the matrix "`$matrix'", i.e.,
     erases all values previously stored there, thereby effectively
     transforming the matrix into a "zero"-matrix or "null"-matrix, the
     neutral element of the addition operation in a Ring.

     (For instance the (quadratic) matrices with "n" rows and columns and
     matrix addition and multiplication form a Ring. Most prominent
     characteristic of a Ring is that multiplication is not commutative,
     i.e., in general, "`matrix1 * matrix2'" is not the same as "`matrix2
     * matrix1'"!)

   * `$matrix->one();'

     Assigns one's to the elements on the main diagonal (elements (1,1),
     (2,2), (3,3) and so on) of matrix "`$matrix'" and zero's to all
     others, thereby erasing all values previously stored there and
     transforming the matrix into a "one"-matrix, the neutral element of
     the multiplication operation in a Ring.

     (If the matrix is quadratic (which this method doesn't require,
     though), then multiplying this matrix with itself yields this same
     matrix again, and multiplying it with some other matrix leaves that
     other matrix unchanged!)

   * `$matrix->assign($row,$column,$value);'

     Explicitly assigns a value "$value" to a single element of the matrix
     "`$matrix'", located in row "`$row'" and column "`$column'", thereby
     replacing the value previously stored there.

   * `$value = $matrix->'`element($row,$column);'

     Returns the value of a specific element of the matrix "`$matrix'",
     located in row "`$row'" and column "`$column'".

   * `($rows,$columns) = $matrix->dim();'

     Returns a list of two items, representing the number of rows and
     columns the given matrix "`$matrix'" contains.

   * `$norm_one = $matrix->norm_one();'

     Returns the "one"-norm of the given matrix "`$matrix'".

     The "one"-norm is defined as follows:

     For each column, the sum of the absolute values of the elements in the
     different rows of that column is calculated. Finally, the maximum of
     these sums is returned.

     Note that the "one"-norm and the "maximum"-norm are mathematically
     equivalent, although for the same matrix they usually yield a
     different value.

     Therefore, you should only compare values that have been calculated
     using the same norm!

     Throughout this package, the "one"-norm is (arbitrarily) used for all
     comparisons, for the sake of uniformity and comparability, except for
     the iterative methods "solve_GSM()", "solve_SSM()" and "solve_RM()"
     which use either norm depending on the matrix itself.

   * `$norm_max = $matrix->norm_max();'

     Returns the "maximum"-norm of the given matrix "`$matrix'".

     The "maximum"-norm is defined as follows:

     For each row, the sum of the absolute values of the elements in the
     different columns of that row is calculated. Finally, the maximum of
     these sums is returned.

     Note that the "maximum"-norm and the "one"-norm are mathematically
     equivalent, although for the same matrix they usually yield a
     different value.

     Therefore, you should only compare values that have been calculated
     using the same norm!

     Throughout this package, the "one"-norm is (arbitrarily) used for all
     comparisons, for the sake of uniformity and comparability, except for
     the iterative methods "solve_GSM()", "solve_SSM()" and "solve_RM()"
     which use either norm depending on the matrix itself.

   * `$matrix1->negate($matrix2);'

     Calculates the negative of matrix "`$matrix2'" (i.e., multiplies all
     elements with "-1") and stores the result in matrix "`$matrix1'"
     (which must already exist and have the same size as matrix
     "`$matrix2'"!).

     This operation can also be carried out "in-place", i.e., input and
     output matrix may be identical.

   * `$matrix1->transpose($matrix2);'

     Calculates the transposed matrix of matrix "`$matrix2'" and stores
     the result in matrix "`$matrix1'" (which must already exist and have
     the same size as matrix "`$matrix2'"!).

     This operation can also be carried out "in-place", i.e., input and
     output matrix may be identical.

     Transposition is a symmetry operation: imagine you rotate the matrix
     along the axis of its main diagonal (going through elements (1,1),
     (2,2), (3,3) and so on) by 180 degrees.

     Another way of looking at it is to say that rows and columns are
     swapped. In fact the contents of element `(i,j)' are swapped with
     those of element `(j,i)'.

     Note that (especially for vectors) it makes a big difference if you
     have a row vector, like this:

          [ -1 0 1 ]

     or a column vector, like this:

          [ -1 ]
          [  0 ]
          [  1 ]

     the one vector being the transposed of the other!

     This is especially true for the matrix product of two vectors:

          [ -1 ]
            [ -1 0 1 ] * [  0 ]  =  [ 2 ] ,  whereas
          [  1 ]

          *     [ -1  0  1 ]
            [ -1 ]                                            [  1  0 -1 ]
            [  0 ] * [ -1 0 1 ]  =  [ -1 ]   [  1  0 -1 ]  =  [  0  0  0 ]
            [  1 ]                  [  0 ]   [  0  0  0 ]     [ -1  0  1 ]
                                    [  1 ]   [ -1  0  1 ]

     So be careful about what you really mean!

     Hint: throughout this module, whenever a vector is explicitly required
     for input, a COLUMN vector is expected!

   * `$matrix1->add($matrix2,$matrix3);'

     Calculates the sum of matrix "`$matrix2'" and matrix "`$matrix3'" and
     stores the result in matrix "`$matrix1'" (which must already exist
     and have the same size as matrix "`$matrix2'" and matrix
     "`$matrix3'"!).

     This operation can also be carried out "in-place", i.e., the output
     and one (or both) of the input matrices may be identical.

   * `$matrix1->subtract($matrix2,$matrix3);'

     Calculates the difference of matrix "`$matrix2'" minus matrix
     "`$matrix3'" and stores the result in matrix "`$matrix1'" (which must
     already exist and have the same size as matrix "`$matrix2'" and
     matrix "`$matrix3'"!).

     This operation can also be carried out "in-place", i.e., the output
     and one (or both) of the input matrices may be identical.

     Note that this operation is the same as
     `$matrix1->add($matrix2,-$matrix3);', although the latter is a little
     less efficient.

   * `$matrix1->multiply_scalar($matrix2,$scalar);'

     Calculates the product of matrix "`$matrix2'" and the number "$scalar"
     (i.e., multiplies each element of matrix "`$matrix2'" with the factor
     "$scalar") and stores the result in matrix "`$matrix1'" (which must
     already exist and have the same size as matrix "`$matrix2'"!).

     This operation can also be carried out "in-place", i.e., input and
     output matrix may be identical.

   * `$product_matrix = $matrix1->multiply($matrix2);'

     Calculates the product of matrix "`$matrix1'" and matrix "`$matrix2'"
     and returns an object reference to a new matrix "`$product_matrix'" in
     which the result of this operation has been stored.

     Note that the dimensions of the two matrices "`$matrix1'" and
     "`$matrix2'" (i.e., their numbers of rows and columns) must harmonize
     in the following way (example):

          [ 2 2 ]
          [ 2 2 ]
          [ 2 2 ]

          [ 1 1 1 ]   [ * * ]
          [ 1 1 1 ]   [ * * ]
          [ 1 1 1 ]   [ * * ]
          [ 1 1 1 ]   [ * * ]

     I.e., the number of columns of matrix "`$matrix1'" has to be the same
     as the number of rows of matrix "`$matrix2'".

     The number of rows and columns of the resulting matrix
     "`$product_matrix'" is determined by the number of rows of matrix
     "`$matrix1'" and the number of columns of matrix "`$matrix2'",
     respectively.

   * `$minimum = Math::MatrixReal::min($number1,$number2);'

     Returns the minimum of the two numbers "`number1'" and "`number2'".

   * `$minimum = Math::MatrixReal::max($number1,$number2);'

     Returns the maximum of the two numbers "`number1'" and "`number2'".

   * `$minimal_cost_matrix = $cost_matrix->kleene();'

     Copies the matrix "`$cost_matrix'" (which has to be quadratic!) to a
     new matrix of the same size (i.e., "clones" the input matrix) and
     applies Kleene's algorithm to it.

     See `Math::Kleene(3)' in this node for more details about this
     algorithm!

     The method returns an object reference to the new matrix.

     Matrix "`$cost_matrix'" is not changed by this method in any way.

   * `($norm_matrix,$norm_vector) = $matrix->normalize($vector);'

     This method is used to improve the numerical stability when solving
     linear equation systems.

     Suppose you have a matrix "A" and a vector "b" and you want to find
     out a vector "x" so that `A * x = b', i.e., the vector "x" which
     solves the equation system represented by the matrix "A" and the
     vector "b".

     Applying this method to the pair (A,b) yields a pair (A',b') where
     each row has been divided by (the absolute value of) the greatest
     coefficient appearing in that row. So this coefficient becomes equal
     to "1" (or "-1") in the new pair (A',b') (all others become smaller
     than one and greater than minus one).

     Note that this operation does not change the equation system itself
     because the same division is carried out on either side of the
     equation sign!

     The method requires a quadratic (!) matrix "`$matrix'" and a vector
     "`$vector'" for input (the vector must be a column vector with the
     same number of rows as the input matrix) and returns a list of two
     items which are object references to a new matrix and a new vector,
     in this order.

     The output matrix and vector are clones of the input matrix and vector
     to which the operation explained above has been applied.

     The input matrix and vector are not changed by this in any way.

     Example of how this method can affect the result of the methods to
     solve equation systems (explained immediately below following this
     method):

     Consider the following little program:

          #!perl -w

          use Math::MatrixReal qw(new_from_string);

          $A = Math::MatrixReal->new_from_string(<<"MATRIX");
          [  1   2   3  ]
          [  5   7  11  ]
          [ 23  19  13  ]
          MATRIX

          $b = Math::MatrixReal->new_from_string(<<"MATRIX");
          [   0   ]
          [   1   ]
          [  29   ]
          MATRIX

          $LR = $A->decompose_LR();
          if (($dim,$x,$B) = $LR->solve_LR($b))
          {
              $test = $A * $x;
              print "x = \n$x";
              print "A * x = \n$test";
          }

          ($A_,$b_) = $A->normalize($b);

          $LR = $A_->decompose_LR();
          if (($dim,$x,$B) = $LR->solve_LR($b_))
          {
              $test = $A * $x;
              print "x = \n$x";
              print "A * x = \n$test";
          }

     This will print:

          x =
          [  1.000000000000E+00 ]
          [  1.000000000000E+00 ]
          [ -1.000000000000E+00 ]
          A * x =
          [  4.440892098501E-16 ]
          [  1.000000000000E+00 ]
          [  2.900000000000E+01 ]
          x =
          [  1.000000000000E+00 ]
          [  1.000000000000E+00 ]
          [ -1.000000000000E+00 ]
          A * x =
          [  0.000000000000E+00 ]
          [  1.000000000000E+00 ]
          [  2.900000000000E+01 ]

     You can see that in the second example (where "normalize()" has been
     used), the result is "better", i.e., more accurate!

   * `$LR_matrix = $matrix->decompose_LR();'

     This method is needed to solve linear equation systems.

     Suppose you have a matrix "A" and a vector "b" and you want to find
     out a vector "x" so that `A * x = b', i.e., the vector "x" which
     solves the equation system represented by the matrix "A" and the
     vector "b".

     You might also have a matrix "A" and a whole bunch of different
     vectors "b1".."bk" for which you need to find vectors "x1".."xk" so
     that `A * xi = bi', for `i=1..k'.

     Using Gaussian transformations (multiplying a row or column with a
     factor, swapping two rows or two columns and adding a multiple of one
     row or column to another), it is possible to decompose any matrix "A"
     into two triangular matrices, called "L" and "R" (for "Left" and
     "Right").

     "L" has one's on the main diagonal (the elements (1,1), (2,2), (3,3)
     and so so), non-zero values to the left and below of the main diagonal
     and all zero's in the upper right half of the matrix.

     "R" has non-zero values on the main diagonal as well as to the right
     and above of the main diagonal and all zero's in the lower left half
     of the matrix, as follows:

          [ 1 0 0 0 0 ]      [ x x x x x ]
          [ x 1 0 0 0 ]      [ 0 x x x x ]
                L = [ x x 1 0 0 ]  R = [ 0 0 x x x ]
          [ x x x 1 0 ]      [ 0 0 0 x x ]
          [ x x x x 1 ]      [ 0 0 0 0 x ]

     Note that "`L * R'" is equivalent to matrix "A" in the sense that `L
     * R * x = b  <==>  A * x = b' for all vectors "x", leaving out of
     account permutations of the rows and columns (these are taken care of
     "magically" by this module!) and numerical errors.

     Trick:

     Because we know that "L" has one's on its main diagonal, we can store
     both matrices together in the same array without information loss!
     I.e.,

          [ R R R R R ]
          [ L R R R R ]
                      LR = [ L L R R R ]
          [ L L L R R ]
          [ L L L L R ]

     Beware, though, that "LR" and "`L * R'" are not the same!!!

     Note also that for the same reason, you cannot apply the method
     "normalize()" to an "LR" decomposition matrix. Trying to do so will
     yield meaningless rubbish!

     (You need to apply "normalize()" to each pair (Ai,bi) *BEFORE*
     decomposing the matrix "Ai'"!)

     Now what does all this help us in solving linear equation systems?

     It helps us because a triangular matrix is the next best thing that
     can happen to us besides a diagonal matrix (a matrix that has
     non-zero values only on its main diagonal - in which case the
     solution is trivial, simply divide "`b[i]'" by "`A[i,i]'" to get
     "`x[i]'"!).

     To find the solution to our problem "`A * x = b'", we divide this
     problem in parts: instead of solving `A * x = b' directly, we first
     decompose "A" into "L" and "R" and then solve "`L * y = b'" and
     finally "`R * x = y'" (motto: divide and rule!).

     From the illustration above it is clear that solving "`L * y = b'"
     and "`R * x = y'" is straightforward: we immediately know that `y[1]
     = b[1]'. We then deduce swiftly that

          y[2] = b[2] - L[2,1] * y[1]

     (and we know "`y[1]'" by now!), that

          y[3] = b[3] - L[3,1] * y[1] - L[3,2] * y[2]

     and so on.

     Having effortlessly calculated the vector "y", we now proceed to
     calculate the vector "x" in a similar fashion: we see immediately
     that `x[n] = y[n] / R[n,n]'. It follows that

          x[n-1] = ( y[n-1] - R[n-1,n] * x[n] ) / R[n-1,n-1]

     and

          x[n-2] = ( y[n-2] - R[n-2,n-1] * x[n-1] - R[n-2,n] * x[n] )
                   / R[n-2,n-2]

     and so on.

     You can see that - especially when you have many vectors "b1".."bk"
     for which you are searching solutions to `A * xi = bi' - this scheme
     is much more efficient than a straightforward, "brute force" approach.

     This method requires a quadratic matrix as its input matrix.

     If you don't have that many equations, fill up with zero's (i.e., do
     nothing to fill the superfluous rows if it's a "fresh" matrix, i.e.,
     a matrix that has been created with "new()" or "shadow()").

     The method returns an object reference to a new matrix containing the
     matrices "L" and "R".

     The input matrix is not changed by this method in any way.

     Note that you can "copy()" or "clone()" the result of this method
     without losing its "magical" properties (for instance concerning the
     hidden permutations of its rows and columns).

     However, as soon as you are applying any method that alters the
     contents of the matrix, its "magical" properties are stripped off,
     and the matrix immediately reverts to an "ordinary" matrix (with the
     values it just happens to contain at that moment, be they meaningful
     as an ordinary matrix or not!).

   * `($dimension,$x_vector,$base_matrix) =
     $LR_matrix'`->'`solve_LR($b_vector);'

     Use this method to actually solve an equation system.

     Matrix "`$LR_matrix'" must be a (quadratic) matrix returned by the
     method "decompose_LR()", the LR decomposition matrix of the matrix
     "A" of your equation system `A * x = b'.

     The input vector "`$b_vector'" is the vector "b" in your equation
     system `A * x = b', which must be a column vector and have the same
     number of rows as the input matrix "`$LR_matrix'".

     The method returns a list of three items if a solution exists or an
     empty list otherwise (!).

     Therefore, you should always use this method like this:

          if ( ($dim,$x_vec,$base) = $LR->solve_LR($b_vec) )
          {
              # do something with the solution...
          }
          else
          {
              # do something with the fact that there is no solution...
          }

     The three items returned are: the dimension "`$dimension'" of the
     solution space (which is zero if only one solution exists, one if the
     solution is a straight line, two if the solution is a plane, and so
     on), the solution vector "`$x_vector'" (which is the vector "x" of
     your equation system `A * x = b') and a matrix "`$base_matrix'"
     representing a base of the solution space (a set of vectors which put
     up the solution space like the spokes of an umbrella).

     Only the first "`$dimension'" columns of this base matrix actually
     contain entries, the remaining columns are all zero.

     Now what is all this stuff with that "base" good for?

     The output vector "x" is *ALWAYS* a solution of your equation system
     `A * x = b'.

     But also any vector "`$vector'"

          $vector = $x_vector->clone();

          $machine_infinity = 1E+99; # or something like that

          for ( $i = 1; $i <= $dimension; $i++ )
          {
              $vector += rand($machine_infinity) * $base_matrix->column($i);
          }

     is a solution to your problem `A * x = b', i.e., if "`$A_matrix'"
     contains your matrix "A", then

          print abs( $A_matrix * $vector - $b_vector ), "\n";

     should print a number around 1E-16 or so!

     By the way, note that you can actually calculate those vectors
     "`$vector'" a little more efficient as follows:

          $rand_vector = $x_vector->shadow();

          $machine_infinity = 1E+99; # or something like that

          for ( $i = 1; $i <= $dimension; $i++ )
          {
              $rand_vector->assign($i,1, rand($machine_infinity) );
          }

          $vector = $x_vector + ( $base_matrix * $rand_vector );

     Note that the input matrix and vector are not changed by this method
     in any way.

   * `$inverse_matrix = $LR_matrix->invert_LR();'

     Use this method to calculate the inverse of a given matrix
     "`$LR_matrix'", which must be a (quadratic) matrix returned by the
     method "decompose_LR()".

     The method returns an object reference to a new matrix of the same
     size as the input matrix containing the inverse of the matrix that
     you initially fed into "decompose_LR()" *IF THE INVERSE EXISTS*, or
     an empty list otherwise.

     Therefore, you should always use this method in the following way:

          if ( $inverse_matrix = $LR->invert_LR() )
          {
              # do something with the inverse matrix...
          }
          else
          {
              # do something with the fact that there is no inverse matrix...
          }

     Note that by definition (disregarding numerical errors), the product
     of the initial matrix and its inverse (or vice-versa) is always a
     matrix containing one's on the main diagonal (elements (1,1), (2,2),
     (3,3) and so on) and zero's elsewhere.

     The input matrix is not changed by this method in any way.

   * `$condition = $matrix->condition($inverse_matrix);'

     In fact this method is just a shortcut for

          abs($matrix) * abs($inverse_matrix)

     Both input matrices must be quadratic and have the same size, and the
     result is meaningful only if one of them is the inverse of the other
     (for instance, as returned by the method "invert_LR()").

     The number returned is a measure of the "condition" of the given
     matrix "`$matrix'", i.e., a measure of the numerical stability of the
     matrix.

     This number is always positive, and the smaller its value, the better
     the condition of the matrix (the better the stability of all
     subsequent computations carried out using this matrix).

     Numerical stability means for example that if

          abs( $vec_correct - $vec_with_error ) < $epsilon

     holds, there must be a "`$delta'" which doesn't depend on the vector
     "`$vec_correct'" (nor "`$vec_with_error'", by the way) so that

          abs( $matrix * $vec_correct - $matrix * $vec_with_error ) < $delta

     also holds.

   * `$determinant = $LR_matrix->det_LR();'

     Calculates the determinant of a matrix, whose LR decomposition matrix
     "`$LR_matrix'" must be given (which must be a (quadratic) matrix
     returned by the method "decompose_LR()").

     In fact the determinant is a by-product of the LR decomposition: It is
     (in principle, that is, except for the sign) simply the product of the
     elements on the main diagonal (elements (1,1), (2,2), (3,3) and so on)
     of the LR decomposition matrix.

     (The sign is taken care of "magically" by this module)

   * `$order = $LR_matrix->order_LR();'

     Calculates the order (called "Rang" in German) of a matrix, whose LR
     decomposition matrix "`$LR_matrix'" must be given (which must be a
     (quadratic) matrix returned by the method "decompose_LR()").

     This number is a measure of the number of linear independent row and
     column vectors (= number of linear independent equations in the case
     of a matrix representing an equation system) of the matrix that was
     initially fed into "decompose_LR()".

     If "n" is the number of rows and columns of the (quadratic!) matrix,
     then "n - order" is the dimension of the solution space of the
     associated equation system.

   * `$scalar_product = $vector1->scalar_product($vector2);'

     Returns the scalar product of vector "`$vector1'" and vector
     "`$vector2'".

     Both vectors must be column vectors (i.e., a matrix having several
     rows but only one column).

     This is a (more efficient!) shortcut for

          $temp           = ~$vector1 * $vector2;
          $scalar_product =  $temp->element(1,1);

     or the sum `i=1..n' of the products `vector1[i] * vector2[i]'.

     Provided none of the two input vectors is the null vector, then the
     two vectors are orthogonal, i.e., have an angle of 90 degrees between
     them, exactly when their scalar product is zero, and vice-versa.

   * `$vector_product = $vector1->vector_product($vector2);'

     Returns the vector product of vector "`$vector1'" and vector
     "`$vector2'".

     Both vectors must be column vectors (i.e., a matrix having several
     rows but only one column).

     Currently, the vector product is only defined for 3 dimensions (i.e.,
     vectors with 3 rows); all other vectors trigger an error message.

     In 3 dimensions, the vector product of two vectors "x" and "y" is
     defined as

          |  x[1]  y[1]  e[1]  |
            determinant |  x[2]  y[2]  e[2]  |
          |  x[3]  y[3]  e[3]  |

     where the "`x[i]'" and "`y[i]'" are the components of the two vectors
     "x" and "y", respectively, and the "`e[i]'" are unity vectors (i.e.,
     vectors with a length equal to one) with a one in row "i" and zero's
     elsewhere (this means that you have numbers and vectors as elements
     in this matrix!).

     This determinant evaluates to the rather simple formula

          z[1] = x[2] * y[3] - x[3] * y[2]
          z[2] = x[3] * y[1] - x[1] * y[3]
          z[3] = x[1] * y[2] - x[2] * y[1]

     A characteristic property of the vector product is that the resulting
     vector is orthogonal to both of the input vectors (if neither of both
     is the null vector, otherwise this is trivial), i.e., the scalar
     product of each of the input vectors with the resulting vector is
     always zero.

   * `$length = $vector->length();'

     This is actually a shortcut for

          $length = sqrt( $vector->scalar_product($vector) );

     and returns the length of a given (column!) vector "`$vector'".

     Note that the "length" calculated by this method is in fact the
     "two"-norm of a vector "`$vector'"!

     The general definition for norms of vectors is the following:

          sub vector_norm
          {
              croak "Usage: \$norm = \$vector->vector_norm(\$n);"
                if (@_ != 2);

          my($vector,$n) = @_;
          my($rows,$cols) = ($vector->[1],$vector->[2]);
          my($k,$comp,$sum);

          croak "Math::MatrixReal::vector_norm(): vector is not a column vector"
            unless ($cols == 1);

          croak "Math::MatrixReal::vector_norm(): norm index must be > 0"
            unless ($n > 0);

          croak "Math::MatrixReal::vector_norm(): norm index must be integer"
            unless ($n == int($n));

          $sum = 0;
          for ( $k = 0; $k < $rows; $k++ )
          {
              $comp = abs( $vector->[0][$k][0] );
              $sum += $comp ** $n;
          }
          return( $sum ** (1 / $n) );
            }

     Note that the case "n = 1" is the "one"-norm for matrices applied to a
     vector, the case "n = 2" is the euclidian norm or length of a vector,
     and if "n" goes to infinity, you have the "infinity"- or
     "maximum"-norm for matrices applied to a vector!

   * `$xn_vector = $matrix->'`solve_GSM($x0_vector,$b_vector,$epsilon);'

   * `$xn_vector = $matrix->'`solve_SSM($x0_vector,$b_vector,$epsilon);'

   * `$xn_vector =
     $matrix->'`solve_RM($x0_vector,$b_vector,$weight,$epsilon);'

     In some cases it might not be practical or desirable to solve an
     equation system "`A * x = b'" using an analytical algorithm like the
     "decompose_LR()" and "solve_LR()" method pair.

     In fact in some cases, due to the numerical properties (the
     "condition") of the matrix "A", the numerical error of the obtained
     result can be greater than by using an approximative (iterative)
     algorithm like one of the three implemented here.

     All three methods, GSM ("Global Step Method" or
     "Gesamtschrittverfahren"), SSM ("Single Step Method" or
     "Einzelschrittverfahren") and RM ("Relaxation Method" or
     "Relaxationsverfahren"), are fix-point iterations, that is, can be
     described by an iteration function "`x(t+1) = Phi( x(t) )'" which has
     the property:

          Phi(x)  =  x    <==>    A * x  =  b

     We can define "`Phi(x)'" as follows:

          Phi(x)  :=  ( En - A ) * x  +  b

     where "En" is a matrix of the same size as "A" ("n" rows and columns)
     with one's on its main diagonal and zero's elsewhere.

     This function has the required property.

     Proof:

          A * x        =   b

          <==>  -( A * x )      =  -b

          <==>  -( A * x ) + x  =  -b + x

          <==>  -( A * x ) + x + b  =  x

          <==>  x - ( A * x ) + b  =  x

          <==>  ( En - A ) * x + b  =  x

     This last step is true because

          x[i] - ( a[i,1] x[1] + ... + a[i,i] x[i] + ... + a[i,n] x[n] ) + b[i]

     is the same as

          ( -a[i,1] x[1] + ... + (1 - a[i,i]) x[i] + ... + -a[i,n] x[n] ) + b[i]

     qed

     Note that actually solving the equation system "`A * x = b'" means to
     calculate

          a[i,1] x[1] + ... + a[i,i] x[i] + ... + a[i,n] x[n]  =  b[i]

          <==>  a[i,i] x[i]  =
                b[i]
                - ( a[i,1] x[1] + ... + a[i,i] x[i] + ... + a[i,n] x[n] )
                + a[i,i] x[i]

          <==>  x[i]  =
                ( b[i]
                    - ( a[i,1] x[1] + ... + a[i,i] x[i] + ... + a[i,n] x[n] )
                    + a[i,i] x[i]
                ) / a[i,i]

          <==>  x[i]  =
                ( b[i] -
                    ( a[i,1] x[1] + ... + a[i,i-1] x[i-1] +
                      a[i,i+1] x[i+1] + ... + a[i,n] x[n] )
                ) / a[i,i]

     There is one major restriction, though: a fix-point iteration is
     guaranteed to converge only if the first derivative of the iteration
     function has an absolute value less than one in an area around the
     point "`x(*)'" for which "`Phi( x(*) ) = x(*)'" is to be true, and if
     the start vector "`x(0)'" lies within that area!

     This is best verified grafically, which unfortunately is impossible
     to do in this textual documentation!

     See literature on Numerical Analysis for details!

     In our case, this restriction translates to the following three
     conditions:

     There must exist a norm so that the norm of the matrix of the
     iteration function, `( En - A )', has a value less than one, the
     matrix "A" may not have any zero value on its main diagonal and the
     initial vector "`x(0)'" must be "good enough", i.e., "close enough"
     to the solution "`x(*)'".

     (Remember school math: the first derivative of a straight line given
     by "`y = a * x + b'" is "a"!)

     The three methods expect a (quadratic!) matrix "`$matrix'" as their
     first argument, a start vector "`$x0_vector'", a vector "`$b_vector'"
     (which is the vector "b" in your equation system "`A * x = b'"), in
     the case of the "Relaxation Method" ("RM"), a real number "`$weight'"
     best between zero and two, and finally an error limit (real number)
     "`$epsilon'".

     (Note that the weight "`$weight'" used by the "Relaxation Method"
     ("RM") is *NOT* checked to lie within any reasonable range!)

     The three methods first test the first two conditions of the three
     conditions listed above and return an empty list if these conditions
     are not fulfilled.

     Therefore, you should always test their return value using some code
     like:

          if ( $xn_vector = $A_matrix->solve_GSM($x0_vector,$b_vector,1E-12) )
          {
              # do something with the solution...
          }
          else
          {
              # do something with the fact that there is no solution...
          }

     Otherwise, they iterate until `abs( Phi(x) - x ) < epsilon'.

     (Beware that theoretically, infinite loops might result if the
     starting vector is too far "off" the solution! In practice, this
     shouldn't be a problem. Anyway, you can always press <ctrl-C> if you
     think that the iteration takes too long!)

     The difference between the three methods is the following:

     In the "Global Step Method" ("GSM"), the new vector "`x(t+1)'"
     (called "y" here) is calculated from the vector "`x(t)'" (called "x"
     here) according to the formula:

          y[i] =
          ( b[i]
              - ( a[i,1] x[1] + ... + a[i,i-1] x[i-1] +
                  a[i,i+1] x[i+1] + ... + a[i,n] x[n] )
          ) / a[i,i]

     In the "Single Step Method" ("SSM"), the components of the vector
     "`x(t+1)'" which have already been calculated are used to calculate
     the remaining components, i.e.

          y[i] =
          ( b[i]
              - ( a[i,1] y[1] + ... + a[i,i-1] y[i-1] +  # note the "y[]"!
                  a[i,i+1] x[i+1] + ... + a[i,n] x[n] )  # note the "x[]"!
          ) / a[i,i]

     In the "Relaxation method" ("RM"), the components of the vector
     "`x(t+1)'" are calculated by "mixing" old and new value (like cold
     and hot water), and the weight "`$weight'" determines the "aperture"
     of both the "hot water tap" as well as of the "cold water tap",
     according to the formula:

          y[i] =
          ( b[i]
              - ( a[i,1] y[1] + ... + a[i,i-1] y[i-1] +  # note the "y[]"!
                  a[i,i+1] x[i+1] + ... + a[i,n] x[n] )  # note the "x[]"!
          ) / a[i,i]
          y[i] = weight * y[i] + (1 - weight) * x[i]

     Note that the weight "`$weight'" should be greater than zero and less
     than two (!).

     The three methods are supposed to be of different efficiency.
     Experiment!

     Remember that in most cases, it is probably advantageous to first
     "normalize()" your equation system prior to solving it!

Eigensystems
------------

   * `$matrix->is_symmetric();'

     Returns a boolean value indicating if the given matrix is symmetric
     (M[i,*j*]=M[*j*,i]). This is equivalent to `($matrix == ~$matrix)'
     but without memory allocation.

   * `($l, $V) = $matrix->sym_diagonalize();'

     This method performs the diagonalization of the quadratic symmetric
     matrix M stored in $matrix.  On output, l is a column vector
     containing all the eigenvalues of M and V is an orthogonal matrix
     which columns are the corresponding normalized eigenvectors.  The
     primary property of an eigenvalue l and an eigenvector x is of course
     that: M * x = l * x.

     The method uses a Householder reduction to tridiagonal form followed
     by a QL algoritm with implicit shifts on this tridiagonal. (The
     tridiagonal matrix is kept internally in a compact form in this
     routine to save memory.)  In fact, this routine wraps the
     householder() and tri_diagonalize() methods described below when their
     intermediate results are not desired.  The overall algorithmic
     complexity of this technique is O(N^3). According to several books,
     the coefficient hidden by the 'O' is one of the best possible for
     general (symmetric) matrixes.

   * `($T, $Q) = $matrix->householder();'

     This method performs the Householder algorithm which reduces the n by
     n real symmetric matrix M contained in $matrix to tridiagonal form.
     On output, T is a symmetric tridiagonal matrix (only diagonal and
     off-diagonal elements are non-zero) and Q is an *orthogonal* matrix
     performing the tranformation between M and T (`$M == $Q * $T * ~$Q').

   * `($l, $V) = $T->tri_diagonalize([$Q]);'

     This method diagonalizes the symmetric tridiagonal matrix T. On
     output, $l and $V are similar to the output values described for
     sym_diagonalize().

     The optional argument $Q corresponds to an orthogonal transformation
     matrix Q that should be used additionally during V (eigenvectors)
     computation. It should be supplied if the desired eigenvectors
     correspond to a more general symmetric matrix M previously reduced by
     the householder() method, not a mere tridiagonal. If T is really a
     tridiagonal matrix, Q can be omitted (it will be internally created
     in fact as an identity matrix).  The method uses a QL algorithm (with
     implicit shifts).

   * `$l = $matrix->sym_eigenvalues();'

     This method computes the eigenvalues of the quadratic symmetric
     matrix M stored in $matrix.  On output, l is a column vector
     containing all the eigenvalues of M. Eigenvectors are not computed
     (on the contrary of `sym_diagonalize()') and this method is more
     efficient (even though it uses a similar algorithm with two phases).
     However, understand that the algorithmic complexity of this technique
     is still also O(N^3). But the coefficient hidden by the 'O' is better
     by a factor of..., well, see your benchmark, it's wiser.

     This routine wraps the householder_tridiagonal() and
     tri_eigenvalues() methods described below when the intermediate
     tridiagonal matrix is not needed.

   * `$T = $matrix->householder_tridiagonal();'

     This method performs the Householder algorithm which reduces the n by
     n real symmetric matrix M contained in $matrix to tridiagonal form.
     On output, T is the obtained symmetric tridiagonal matrix (only
     diagonal and off-diagonal elements are non-zero). The operation is
     similar to the householder() method, but potentially a little more
     efficient as the transformation matrix is not computed.

   * `$l = $T->tri_eigenvalues();'

     This method compute the eigenvalues of the symmetric tridiagonal
     matrix T. On output, $l is a vector containing the eigenvalues
     (similar to `sym_eigenvalues()').  This method is much more efficient
     than tri_diagonalize() when eigenvectors are not needed.

OVERLOADED OPERATORS
====================

SYNOPSIS
--------

   * Unary operators:

     "-", "`~'", "abs", test, "!", '""'

   * Binary (arithmetic) operators:

     "+", "-", "*"

   * Binary (relational) operators:

     "`=='", "`!='", "`<'", "`<='", "`>'", "`>='"

     "eq", "ne", "lt", "le", "gt", "ge"

     Note that the latter ("eq", "ne", ... ) are just synonyms of the
     former ("`=='", "`!='", ... ), defined for convenience only.

DESCRIPTION
-----------

'-'
     Unary minus

     Returns the negative of the given matrix, i.e., the matrix with all
     elements multiplied with the factor "-1".

     Example:

          $matrix = -$matrix;

'~'
     Transposition

     Returns the transposed of the given matrix.

     Examples:

          $temp = ~$vector * $vector;
          $length = sqrt( $temp->element(1,1) );

          if (~$matrix == $matrix) { # matrix is symmetric ... }

abs
     Norm

     Returns the "one"-Norm of the given matrix.

     Example:

          $error = abs( $A * $x - $b );

test
     Boolean test

     Tests wether there is at least one non-zero element in the matrix.

     Example:

          if ($xn_vector) { # result of iteration is not zero ... }

'!'
     Negated boolean test

     Tests wether the matrix contains only zero's.

     Examples:

          if (! $b_vector) { # heterogenous equation system ... }
          else             { # homogenous equation system ... }

          unless ($x_vector) { # not the null-vector! }

'""""'
     "Stringify" operator

     Converts the given matrix into a string.

     Uses scientific representation to keep precision loss to a minimum in
     case you want to read this string back in again later with
     "new_from_string()".

     Uses a 13-digit mantissa and a 20-character field for each element so
     that lines will wrap nicely on an 80-column screen.

     Examples:

          $matrix = Math::MatrixReal->new_from_string(<<"MATRIX");
          [ 1  0 ]
          [ 0 -1 ]
          MATRIX
          print "$matrix";

          [  1.000000000000E+00  0.000000000000E+00 ]
          [  0.000000000000E+00 -1.000000000000E+00 ]

          $string = "$matrix";
          $test = Math::MatrixReal->new_from_string($string);
          if ($test == $matrix) { print ":-)\n"; } else { print ":-(\n"; }

'+'
     Addition

     Returns the sum of the two given matrices.

     Examples:

          $matrix_S = $matrix_A + $matrix_B;

          $matrix_A += $matrix_B;

'-'
     Subtraction

     Returns the difference of the two given matrices.

     Examples:

          $matrix_D = $matrix_A - $matrix_B;

          $matrix_A -= $matrix_B;

     Note that this is the same as:

          $matrix_S = $matrix_A + -$matrix_B;

          $matrix_A += -$matrix_B;

     (The latter are less efficient, though)

     Multiplication

     Returns the matrix product of the two given matrices or the product
     of the given matrix and scalar factor.

     Examples:

          $matrix_P = $matrix_A * $matrix_B;

          $matrix_A *= $matrix_B;

          $vector_b = $matrix_A * $vector_x;

          $matrix_B = -1 * $matrix_A;

          $matrix_B = $matrix_A * -1;

          $matrix_A *= -1;

'=='
     Equality

     Tests two matrices for equality.

     Example:

          if ( $A * $x == $b ) { print "EUREKA!\n"; }

     Note that in most cases, due to numerical errors (due to the finite
     precision of computer arithmetics), it is a bad idea to compare two
     matrices or vectors this way.

     Better use the norm of the difference of the two matrices you want to
     compare and compare that norm with a small number, like this:

          if ( abs( $A * $x - $b ) < 1E-12 ) { print "BINGO!\n"; }

'!='
     Inequality

     Tests two matrices for inequality.

     Example:

          while ($x0_vector != $xn_vector) { # proceed with iteration ... }

     (Stops when the iteration becomes stationary)

     Note that (just like with the '==' operator), it is usually a bad idea
     to compare matrices or vectors this way. Compare the norm of the
     difference of the two matrices with a small number instead.

'<'
     Less than

     Examples:

          if ( $matrix1 < $matrix2 ) { # ... }

          if ( $vector < $epsilon ) { # ... }

          if ( 1E-12 < $vector ) { # ... }

          if ( $A * $x - $b < 1E-12 ) { # ... }

     These are just shortcuts for saying:

          if ( abs($matrix1) < abs($matrix2) ) { # ... }

          if ( abs($vector) < abs($epsilon) ) { # ... }

          if ( abs(1E-12) < abs($vector) ) { # ... }

          if ( abs( $A * $x - $b ) < abs(1E-12) ) { # ... }

     Uses the "one"-norm for matrices and Perl's built-in "abs()" for
     scalars.

'<='
     Less than or equal

     As with the '<' operator, this is just a shortcut for the same
     expression with "abs()" around all arguments.

     Example:

          if ( $A * $x - $b <= 1E-12 ) { # ... }

     which in fact is the same as:

          if ( abs( $A * $x - $b ) <= abs(1E-12) ) { # ... }

     Uses the "one"-norm for matrices and Perl's built-in "abs()" for
     scalars.

'>'
     Greater than

     As with the '<' and '<=' operator, this

          if ( $xn - $x0 > 1E-12 ) { # ... }

     is just a shortcut for:

          if ( abs( $xn - $x0 ) > abs(1E-12) ) { # ... }

     Uses the "one"-norm for matrices and Perl's built-in "abs()" for
     scalars.

'>='
     Greater than or equal

     As with the '<', '<=' and '>' operator, the following

          if ( $LR >= $A ) { # ... }

     is simply a shortcut for:

          if ( abs($LR) >= abs($A) ) { # ... }

     Uses the "one"-norm for matrices and Perl's built-in "abs()" for
     scalars.

SEE ALSO
========

   Math::MatrixBool(3), DFA::Kleene(3), Math::Kleene(3),
Set::IntegerRange(3), Set::IntegerFast(3).

VERSION
=======

   This man page documents Math::MatrixReal version 1.3.

AUTHORS
=======

   Steffen Beyer <sb@sdm.de>, Rodolphe Ortalo <ortalo@laas.fr>.

CREDITS
=======

   Many thanks to Prof. Pahlings for stoking the fire of my enthusiasm for
Algebra and Linear Algebra at the university (RWTH Aachen, Germany), and
to Prof. Esser and his assistant, Mr. Jarausch, for their fascinating
lectures in Numerical Analysis!

COPYRIGHT
=========

   Copyright (c) 1996, 1997, 1999 by Steffen Beyer and Rodolphe Ortalo.
All rights reserved.

LICENSE AGREEMENT
=================

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Very useful, commonly needed math/statistics/geometric functions.
*****************************************************************

NAME
====

   Math::NumberCruncher - Very useful, commonly needed
math/statistics/geometric functions.

SYNOPSIS
========

   use Math::NumberCruncher;

   ($high, $low) = Math::NumberCruncher::Range(\@array);

   $mean = Math::NumberCruncher::Mean(\@array);

   $median = Math::NumberCruncher::Median(\@array);

   $odd_median = Math::NumberCruncher::OddMedian(\@array);

   $mode = Math::NumberCruncher::Mode(\@array);

   $covariance = Math::NumberCruncher::Covariance(\@array1, \@array2);

   $correlation = Math::NumberCruncher::Correlation(\@array1, \@array2);

   ($slope, $y_intercept) = Math::NumberCruncher::BestFit(\@array1,
\@array2);

   $distance = Math::NumberCruncher::Distance($x1,$y1,$z1,$x2,$y2,$z2);

   $distance = Math::NumberCruncher::Distance($x1,$y1,$x1,$x2);

   $distance = Math::NumberCruncher::ManhattanDistance($x1,$y1,$x2,$y2);

   $probAll = Math::NumberCruncher::AllOf('0.3','0.25','0.91','0.002');

   $probNone = Math::NumberCruncher::NoneOf('0.4','0.5772','0.212');

   $probSome = Math::NumberCruncher::SomeOf('0.11','0.56','0.3275');

   $factorial = Math::NumberCruncher::Factorial($some_number);

   $permutations = Math::NumberCruncher::Permutation($n);

   $permutations = Math::NumberCruncher::Permutation($n,$k);

   $roll = Math::NumberCruncher::Dice(3,12,4);

   $randInt = Math::NumberCruncher::RandInt(10,50);

   $randomElement = Math::NumberCruncher::RandomElement(\@array);

   @shuffled = Math::NumberCruncher::ShuffleArray(\@array);

   @unique = Math::NumberCruncher::Unique(\@array);

   @a_only = Math::NumberCruncher::Compare(\@a,\@b);

   @union = Math::NumberCruncher::Union(\@a,\@b);

   @intersection = Math::NumberCruncher::Intersection(\@a,\@b);

   @difference = Math::NumberCruncher::Difference(\@a,\@b);

   $gaussianRand = Math::NumberCruncher::GaussianRand();

   $prob = Math::NumberCruncher::Choose($n,$k);

   $binomial =
Math::NumberCruncher::Binomial($attempts,$successes,$probability);

   $gaussianDist = Math::NumberCruncher::GaussianDist($x,$mean,$variance);

   $StdDev = Math::NumberCruncher::StandardDeviation(\@array);

   $variance = Math::NumberCruncher::Variance(\@array);

   @scores = Math::NumberCruncher::StandardScores(\@array);

   $confidence =
Math::NumberCruncher::SignSignificance($trials,$hits,$probability);

   $e = Math::Numbercruncher::EMC2( "m512" [, 1] );

   $m = Math::NumberCruncher::EMC2( "e987432" [, 1] );

   $force = Math::NumberCruncher::FMA( "m12", "a73.5" );

   $mass = Math::NumberCruncher::FMA( "a43", "f1324" );

   $acceleration = Math::NumberCruncher::FMA( "f53512", "m356" );

   $predicted_value = Math::NubmerCruncher::Predict( $slope, $y_intercept,
$proposed_x );

   $area = Math::NumberCruncher::TriangleHeron( $a, $b, $c );

   $area = Math::NumberCruncher::TriangleHeron( 1,3, 5,7, 8,2 );

   $perimeter = Math::NumberCruncher::PolygonPerimeter( $x0,$y0, $x1,$y1,
$x2,$y2, ...);

   $direction = Math::NumberCruncher::Clockwise( $x0,$y0, $x1,$y1, $x2,$y2
);

   $collision = Math::NumberCruncher::InPolygon( $x, $y, @xy );

   @points = Math::NumberCruncher::BoundingBox_Points( $d, @p );

   $in_triangle = Math::NumberCruncher::InTriangle( $x,$y, $x0,$y0,
$x1,$y1, $x2,$y2 );

   $area = Math::NumberCruncher::PolygonArea( 0, 1, 1, 0, 2, 0, 3, 2, 2, 3
);

   $area = Math::NumberCruncher::CircleArea( $diameter );

   $circumference = Math::NumberCruncher::Circumference( $diameter );

   $volume = Math::NumberCruncher::SphereVolume( $radius );

   $surface_area = Math::NumberCruncher::SphereSurface( $radius );

DESCRIPTION
===========

   This module is a collection of commonly needed number-related
functions, including numerous standard statistical, geometric, and
probability functions.  Some of these functions are taken directly from
_Mastering Algorithms with Perl_, by Jon Orwant, Jarkko Hietaniemi, and
John Macdonald, and others are adapted heavily from same.  The remainder
are either original functions written by the author, or original
adaptations of standard algorithms.  Some of the functions are fairly
obvious, others are explained in greater detail below.  For all
calculations involving pi, the value of pi is taken out to 100 places.
Overkill? Probably, but it is better, in my opinion, to have too much
accuracy as opposed to not enough.

EXAMPLES
========

($high,$low) = *Math::NumberCruncher::Range*(\@array);
     Returns the largest and smallest elements in an array.

$mean = *Math::NumberCruncher::Mean*(\@array);
     Returns the mean, or average, of an array.

$median = *Math::NumberCruncher::Median*(\@array);
     Returns the median, or the middle, of an array.  The median may or
     may not be an element of the array itself.

$odd_median = *Math::NumberCruncher::OddMedian*(\@array);
     Returns the odd median, which, unlike the median, *is* an element of
     the array.  In all other respects it is similar to the median.

$mode = *Math::NumberCruncher::Mode*(\@array);
     Returns the mode, or most frequently occurring item, of @array.

$covariance = *Math::NumberCruncher::Covariance*(\@array1,\@array2);
     Returns the covariance, which is a measurement of the correlation of
     two variables.

$correlation = *Math::NumberCruncher::Correlation*(\@array1,\@array2);
     Returns the correlation of two variables. Correlation ranges from 1
     to -1, with a correlation of zero meaning no correlation exists
     between the two variables.

($slope,$y_intercept ) = *Math::NumberCruncher::BestFit*(\@array1,\@array2);
     Returns the slope and y-intercept of the line of best fit for the
     data in question.

$distance = *Math::NumberCruncher::Distance*($x1,$y1,$x1,$x2);
     Returns the Euclidian distance between two points.  The above example
     demonstrates the use in two dimensions. For three dimensions, use
     would be *$distance =
     *Math::NumberCruncher::Distance*($x1,$y1,$z1,$x2,$y2,$z2);*

$distance = *Math::NumberCruncher::ManhattanDistance*($x1,$y1,$x2,$y2);
     Modified two-dimensional distance between two points. As stated in
     _Mastering Algorithms with Perl_, "Helicopter pilots tend to think in
     Euclidian distance, good New York cabbies tend to think in Manhattan
     distance." Rather than distance "as the crow flies," this is distance
     based on a rigid grid, or network of streets, like those found in
     Manhattan.

$probAll = *Math::NumberCruncher::AllOf*('0.3','0.25','0.91','0.002');
     The probability that all of the probabilities in question will be
     satisfied. (i.e., the probability that the Steelers will win the
     SuperBowl and that David Tua will win the World Heavyweight Title in
     boxing.)

$probNone = *Math::NumberCruncher::NoneOf*('0.4','0.5772','0.212');
     The probability that none of the probabilities in question will be
     satisfied. (i.e., the probability that the Steelers will not win the
     SuperBowl and that David Tua will not win the World Heavyweight Title
     in boxing.)

$probSome = *Math::NumberCruncher::SomeOf*('0.11','0.56','0.3275');
     The probability that at least one of the probabilities in question
     will be satisfied. (i.e., the probability that either the Steelers
     will win the SuperBowl or David Tua will win the World Heavyweight
     Title in boxing.)

$factorial = *Math::NumberCruncher::Factorial*($some_number);
     The number of possible orderings of $factorial items. The factorial
     n! gives the number of ways in which n objects can be permuted.

$permutations = *Math::NumberCruncher::Permutation*($n);
     The number of permutations of $n elements.

$permutations = *Math::NumberCruncher::Permutation*($n,$k);
     The number of permutations of $k elements drawn from a set of $n
     elements.

$roll = *Math::NumberCruncher::Dice*($number,$sides,$plus);
     The obligatory dice rolling routine. Returns the result after passing
     the number of rolls of the die, the number of sides of the die, and
     any additional points to be added to the roll.  As commonly seen in
     role playing games, 4d12+5 would be expressed as *Dice(4,12,5)*.  The
     function defaults to a single 6-sided die rolled once without any
     points added.

$randInt = *Math::NumberCruncher::RandInt*(10,50);
     Returns a random integer between the two number passed to the
     function, inclusive. With no parameters passed, the function returns
     either 0 or 1.

$randomElement = *Math::NumberCruncher::RandomElement*(\@array);
     Returns a randome element from @array.

@shuffled = *Math::NumberCruncher::ShuffleArray*(\@array);
     Shuffles the elements of @array and returns them.

@unique = *Math::NumberCruncher::Unique*(\@array);
     Returns an array of the unique items in an array.

@a_only = *Math::NumberCruncher::Compare*(\@a,\@b);
     Returns an array of elements that appear only in the first array
     passed. Any elements that appear in both arrays, or appear only in
     the second array, are discarded.

@union = *Math::NumberCruncher::Union*(\@a,\@b);
     Returns an array of the unique elements produced from the joining of
     the two arrays.

@intersection = *Math::NumberCruncher::Intersection*(\@a,\@b);
     Returns an array of the elements that appear in both arrays.

@difference = *Math::NumberCruncher::Difference*(\@a,\@b);
     Returns an array of the symmetric difference of the two arrays. For
     example, in the words of _Mastering Algorithms in Perl_, "show me the
     web documents that talk about Perl or about sets *but not* those that
     talk about both.

$gaussianRand = *Math::NumberCruncher::GaussianRand*();
     Returns one or two floating point numbers based on the Gaussian
     Distribution, based upon the call wants an array or a scalar value.

$probability = *Math::NumberCruncher::Choose*($n,$k);
     Returns the probability of $k successes in $n tries.

$binomial = *Math::NumberCruncher::Binomial*($n,$k,$p);
     Returns the probability of $k successes in $n tries, given a
     probability of $p. (i.e., if the probability of being struck by
     lightning is 1 in 75,000, in 100 days, the probability of being
     struck by lightning exactly twice would be expressed as
     *Binomial('100','2','0.0000133')*)

$probability = *Math::NumberCruncher::GaussianDist*($x,$mean,$variance);
     Returns the probability, based on Gaussian Distribution, of our
     random variable, $x, given the $mean and $variance.

$StdDev = *Math::NumberCruncher::StandardDeviation*(\@array);
     Returns the Standard Deviation of @array, which is a measurement of
     how diverse your data is.

$variance = *Math::NumberCruncher::Variance*(\@array);
     Returns the variance for @array, which is the square of the standard
     deviation.  Or think of standard deviation as the square root of the
     variance.  Variance is another indicator of the diversity of your
     data.

@scores = *Math::NumberCruncher::StandardScores*(\@array);
     Returns an array of the number of standard deviations above the mean
     for @array.

$confidence = *Math::NumberCruncher::SignSignificance*($trials,$hits,$probability);
     Returns the probability of how likely it is that your data is due to
     chance.  The lower the confidence, the less likely your data is due
     to chance.

$e = *Math::NumberCruncher::EMC2*( "m36" [, 1] );
     Implementation of Einstein's E=MC**2.  Given either energy or mass,
     the function returns the other. When passing mass, the value must be
     preceeded by a "m," which may be either upper or lower case.  When
     passing energy, the value must be preceeded by a "e," which may be
     either upper or lower case. The function defaults to using kilometers
     per second for the speed of light.  To make the function use miles
     per second for the speed of light, simply pass any non-zero value as
     the second value.

$force = *Math::NumberCruncher::FMA*( "m97", "a53" );
     Implementation of the stadard force = mass * acceleration formula.
     Given two of the three variables (i.e., mass and force, mass and
     acceleration, or acceleration and force), the function returns the
     third.  When passing the values, mass must be preceeded by a "m,"
     force must be preceeded by a "f," and acceleration must be preceeded
     by an "a."  Case is irrelevant.

$predicted = *Math::NumberCruncher::Predict*( $slope, $y_intercept, $proposed_x );
     Useful for predicting values based on data trends, as calculated by
     BestFit(). Given the slope and y-intercept, and a proposed value of
     x, returns corresponding y.

$area = *Math::NumberCruncher::TriangleHeron*( $a, $b, $c );
     Calculates the area of a triangle, using Heron's formula.
     TriangleHeron() can be passed either the lengths of the three sides
     of the triangle, or the (x,y) coordinates of the three verticies.

$perimeter = *Math::NumberCruncher::PolygonPerimeter*( $x0,$y0, $x1,$y1, $x2,$y2, ...);
     Calculates the length of the perimeter of a given polygon.

$direction = *Math::NumberCruncher::Clockwise*( $x0,$y0, $x1,$y1, $x2,$y2 );
     Given three pairs of points, returns a positive number if you must
     turn clockwise when moving from p1 to p2 to p3, returns a negative
     number if you must turn counter-clockwise when moving from p1 to p2
     to p3, and a zero if the three points lie on the same line.

$collision = *Math::NumberCruncher::InPolygon*( $x, $y, @xy );
     Given a set of xy pairs (@xy) that define the perimeter of a polygon,
     returns a 1 if point ($x,$y) is inside the polygon and returns 0 if
     the point ($x,$y) is outside the polygon.

@points = *Math::NumberCruncher::BoundingBox_Points*( $d, @p );
     Given a set of @p points and $d dimensions, returns two points that
     define the upper left and lower right corners of the bounding box for
     set of points @p.

$in_triangle = *Math::NumberCruncher::InTriangle*( $x,$y, $x0,$y0, $x1,$y1, $x2,$y2 );
     Returns true if point $x,$y is inside the triangle defined by points
     ($x0,$y0), ($x1,$y1), and ($x2,$y2)

$area = *Math::NumberCruncher::PolygonArea*( 0, 1, 1, 0, 3, 2, 2, 3, 0, 2 );
     Calculates the area of a polygon using determinants.

$area = *Math::NumberCruncher::CircleArea*( $diameter );
     Calculates the area of a circle, given the diameter.

$circumference = *Math::NumberCruncher::Circumference*( $diameter );
     Calculates the circumference of a circle, given the diameter.

$volume = *Math::NumberCruncher::SphereVolume*( $radius );
     Calculates the volume of a sphere, given the radius.

$surface_area = *Math::NumberCruncher::SphereSurface*( $radius );
     Calculates the surface area of a sphere, given the radius.

AUTHOR
======

   Kurt Kincaid, sifukurt@yahoo.com Jon Orwant Jarkko Hietaniemi John
Macdonald

SEE ALSO
========

   perl(1).

Perl interface to pseudo random sequence generator function.
************************************************************

NAME
====

   PRSG - Perl interface to pseudo random sequence generator function.

SYNOPSIS
========

     use Math::PRSG;

DESCRIPTION
===========

   This perl extension implements a (159, 31, 0) LFSR, giving a period of
160 bits.  This can then be used as a RNG if seeded well (ie. with 160
bits of entropy) and if the output is fed through a message digest
function (in order to prevent any prediction).

FUNCTIONS
=========

new
          my $prsg = new PRSG $seed;

     Create a new PRSG object.  A 160 bit (20-byte) $seed must be provided,
     which is used to seed the LFSR.

seed
          $prsg->seed($rnd);

     Seed the LFSR with $rnd.

clock
          $value = $prsg->clock();

     Clock the LFSR, returning the new register value as a 20-byte string.

COPYRIGHT
=========

   Systemics Ltd ( http://www.systemics.com/ )

Perl class for working with polynomials.
****************************************

NAME
====

   Math::Polynomial - Perl class for working with polynomials.

SYNOPSIS
========

     use Math::Polynomial;

     # The polynomial 2x^2 + 3x - 2
         my $P = Math::Polynomial->new(2,3,-2);

     # Evaluate the polynomial for x = 10
     my $result = $P->eval(10);

     # The polynomial 3x + 4
     my $Q = Math::Polynomial->new(3,4);

     print "$P / $Q = ", $P / $Q, "\n";

     my $polynomial = Math::Polynomial::interpolate(1 => 5, 2 => 12, 3 => 6);

DESCRIPTION
===========

   This module implements single variable polynomials using arrays. It also
implements some useful functionality when working with polynomials, such
as adding, multiplication, etc.

CONSTRUCTOR
===========

   The following constructors exist to create new polynomials.

new(*coefficient*, ...)
     A new polynomial is constructed. The coefficient for the highest
     degree term is first in the list, while the constant (the coefficient
     for X**0) is the last one in the list.

CLASS METHODS
=============

   Here is a list of class methods available. The methods can be applied
to individual polynomials or `Math::Polynomial'. If it is applied to an
object it will affect the entire class.

configure(variable => value, ...)
     Configure various things regarding the class. Following is a list of
     variables used by the class.

    PLUS
          The string inserted as a plus sign between terms.  Default is `'
          + ''.

    MINUS
          The string inserted as a minus sign between terms. If the first
          coefficient is negative, this string without spaces is used as
          prefix.  Default is `' - ''.

    TIMES
          The string inserted as multiplication between the coefficients
          and the variables. Default is '*'.

    POWER
          The string inserted as power between the variable and the power.
          Default is `'**''.

    VARIABLE
          The string used as variable in the polynom. Default is `'$X''.

quotrem(*numerator*,*denominator*)
     This method computes the quotient and the remainder when dividing
     *numerator* by *denominator* and returns a list
     (*quotient*,*remainder*). It is used by the operators / and %.

     It uses the *Euclidian algorithm* for division, hence we have a
     complexity of *O(n*m)* where n and m are the degrees of the
     polynomials.

verbose(*bool*)
     If verbose is turned on, string conversion will return a string for
     the polynomial, otherwise a list of coefficients will be returned.

OBJECT METHODS
==============

   Here is a list of object methods available. Object methods are applied
to the object in question, in contrast with class methods which are
applied to a class.

clone()
     This method will clone the polynomial and return a copy of it.

coeff(*degree*)
     This method returns the coefficient for degree *degree*.

degree()
     This method returns the degree of the polynomial. The degree of a
     polynomial is the maximum of the degree of terms with non-zero
     coefficients.

eval(value)
     The polynomial is evaluated for value. The evaluation is done using
     *Horners rule*, hence evaluation is done in *O(n)* time, where n is
     the degree of the polynomial.

size()
     This method returns the internal size of the polynomial, i.e. the
     length of the array where the coefficients are stored. After a
     tidy(), *degree* is equal to size-1.

tidy()
     This method removes all terms which are redundant, i.e. the
     coefficients where all higher degree coefficients are zero.

     This method is never called automatically, since it is assumed that
     the programmer knows best when to tidy the polynomial.

OPERATORS
=========

   There is a set of operators defined for polynomials.

polynomial + polynomial
     Adds two polynomials together, returning the sum. The operation is
     *O(n)*, where n is the maximum of the degrees of the polynomials.

polynomial - polynomial
     Substracts the right polynomial from the left polynomial, returning
     the difference. The operation is *O(n)*, where n is the maximum of
     the degrees of the polynomials.

polynomial * polynomial
     Multiplies two polynomials together, returning the product. The
     operation is *O(n*m)*, where n and m are the degrees of the
     polynomials respectively.

polynomial / polynomial
     Divides the polynomial on the left (called the numerator) with the
     polynomial on the right (called the denominator) and returns the
     quotient. If the degree of the denominator is greater than the degree
     of the numerator, the zero polynomial will be returned.

polynomial % polynomial
     Divides the polynomial on the left (called the numerator) with the
     polynomial on the right (called the denominator) and returns the
     remainder of the division. If the degree of the denominator is greater
     than the degree of numerator, the numerator will be returned.

String conversion.
     If verbose is turned on, the polynomial will be converted to a string
     where '$X' is used as the variable. If a coefficient is zero, that
     term will not be printed.

     To change the string used as variable, use the configure class method
     described above.

     If verbose is turned off, a parenthesised, $"-separated list will be
     returned.

SUBROUTINES
===========

interpolate(x => y, ...)
     Given a set of pairs of x and y values, interpolate will return a
     polynomial which interpolates those values. The data points are
     supplied as a list of alternating x and y values.

     The degree of the resulting polynomial will be one less than the
     number of pairs, e.g. the polynomial in the synopsis will be of
     degree 2.

     The interpolation is done using *Lagrange's formula* and the
     implementation runs in *O(n^2)*, where n is the number of pairs
     supplied to interpolate.

     Please note that it is a *bad idea* to use interpolation for
     extrapolation, i.e. if you are interpolating a polynomial for
     x-values in the range 0 to 10, then you may get terrible results if
     you try to predict y-values outside this range. This is true
     especially if the true function is not a polynomial.

INTERNAL METHODS
================

   The methods in this section are internal and should not acually be used
for anything but internal stuff. They are documented here anyway, but
beware that these methods may change or dissapear without notice!

dump()
     Returns a compact, but human readable, string representing the object.

mul1c(c)
     Multiply the polynomial by *(x - c)*. Used internally by the
     interpolation package.

div1c(c)
     Divide the polynomial by *(x - c)*. Used internally by the
     interpolation package.

SEE ALSO
========

   *A Perl Module for Polynomial Interpolation*

COPYRIGHT
=========

   Copyright 1997 Matz Kindahl. All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Find the roots of polynomial equations.
***************************************

NAME
====

   Math::Polynomial::Solve - Find the roots of polynomial equations.

SYNOPSIS
========

     use Math::Complex;  # The roots may be complex numbers.
     use Math::Polynomial::Solve qw(poly_roots);

     my @x = poly_roots(@coefficients);

   or

     use Math::Complex;  # The roots may be complex numbers.
     use Math::Polynomial::Solve
     	qw(linear_roots quadratic_roots cubic_roots quartic_roots);

     # Find the roots of ax + b
     my @x1 = linear_roots($a, $b);

     # Find the roots of ax**2 + bx +c
     my @x2 = quadratic_roots($a, $b, $c);

     # Find the roots of ax**3 + bx**2 +cx + d
     my @x3 = cubic_roots($a, $b, $c, $d);

     # Find the roots of ax**4 + bx**3 +cx**2 + dx + e
     my @x4 = quartic_roots($a, $b, $c, $d, $e);

DESCRIPTION
===========

   This package supplies a set of functions that find the roots of
polynomials up to the quartic. There are no solutions for powers higher
than that at this time (partly because there are no general solutions for
fifth and higher powers).

   The linear, quadratic, cubic, and quartic *_roots() functions all expect
to have a non-zero value for the $a term.

   Passing a zero constant term means that the first value returned from
the function will always be zero, for all functions.

poly_roots()
------------

   A generic function that calls one of the other root-finding functions,
depending on the degree of the polynomial. Returns the solution for
polynomials of degree 1 to degree 4.

   Unlike the other root-finding functions, it will check for coefficients
of zero for the highest power, and 'step down' the degree of the
polynomial to the appropriate case. Additionally, it will check for
coefficients of zero for the lowest power terms, and add zeros to its root
list before calling one of the root-finding functions. Therefore, it is
possible to solve a polynomial of degree higher than 4, as long as it
meets these rather specialized conditions.

linear_roots()
--------------

   Here for completeness's sake more than anything else. Returns the
solution for

     ax + b = 0

   by returning `-b/a'. This may be in either a scalar or an array context.

quadratic_roots()
-----------------

   Gives the roots of the quadratic equation

     ax**2 + bx + c = 0

   using the well-known quadratic formula. A two-element list is returned.

cubic_roots()
-------------

   Gives the roots of the cubic equation

     ax**3 + bx**2 + cx + d = 0

   by the method described by R. W. D. Nickalls (see the Acknowledgments
section below). A three-element list is returned. The first element will
always be real. The next two values will either be both real or both
complex numbers.

quartic_roots()
---------------

   Gives the roots of the quartic equation

     ax**4 + bx**3 + cx**2 + dx + e = 0

   using Ferrari's method (see the Acknowledgments section below). A
four-element list is returned. The first two elements will be either both
real or both complex. The next two elements will also be alike in type.

EXPORT
------

   There are no default exports. The functions may be named in an export
list.

Acknowledgments
===============

The cubic
---------

   The cubic is solved by the method described by R. W. D. Nickalls, "A New
Approach to solving the cubic: Cardan's solution revealed," The
Mathematical Gazette, 77, 354-359, 1993. This article is available on the
web at http://www.m-a.org.uk/eb/mg/mg077ch.pdf.

   Dr. Nickalls was kind enough to send me his article, with notes and
revisions, and directed me to a Matlab script that was based on that
article, written by Herman Bruyninckx, of the Dept. Mechanical Eng., Div.
PMA, Katholieke Universiteit Leuven, Belgium. This function is an almost
direct translation of that script, and I owe Herman Bruyninckx for
creating it in the first place. It may be found on the web at
http://www.mech.kuleuven.ac.be/~bruyninc/matlab/cubic.ml

   Dick Nickalls, dicknickalls@compuserve.com

   Herman Bruyninckx, Herman.Bruyninckx@mech.kuleuven.ac.be,
http://www.mech.kuleuven.ac.be/~bruyninc

The quartic
-----------

   The method for quartic solution is Ferrari's, as described in the web
page Karl's Calculus Tutor, http://www.netsrq.com/~hahn/quartic.html.  I
also made use of some short cuts mentioned in web page Ask Dr. Math FAQ,
http://forum.swarthmore.edu/dr.math/faq/faq.cubic.equations.html.

Other functionality
-------------------

   Matz Kindahl, the author of Math::Polynomial, suggested the poly_roots()
function.

SEE ALSO
========

   Forsyth, George E., Michael A. Malcolm, and Cleve B. Moler (1977),
Computer Methods for Mathematical Computations, Prentice-Hall.

AUTHOR
======

   John M. Gamble, jgamble@ripco.com

perl bindings for drand48() family of random functions
******************************************************

NAME
====

   Math::Rand48 - perl bindings for drand48() family of random functions

SYNOPSIS
========

     use Math::Rand48;

     my $n = drand48();        # Float value [0.0,1.0)
     my $seed = seed48();      # Get seed for drand48, lrand48, mrand48
     my $m = erand48($seed);   # Float value [0.0,1.0) - modifies $seed

     seed48($seed);            # Set seed for drand48, lrand48, mrand48

     use Math::Rand48 qw(lrand48);
     my $un = lrand48();
     my $um = nrand48($seed);

DESCRIPTION
===========

   This package provides an interface to the 48-bit family of random number
functions, commonly provided on UNIX systems.

`seed48'
     Returns the current seed used by `drand48', `lrand48', `mrand48'.  If
     given an argument sets the seed to that value.

`drand48'

`erand48'($seed)
     Return float value in range [0.0,1.0).  Multiple independent streams
     of numbers can be obtained using `erand48'.

`lrand48'

`nrand48'($seed)
     Return integer in range [0,2**31).  Multiple independent streams of
     numbers can be obtained using `nrand48'.

`mrand48'

`jrand48'($seed)
     Return integer in range [-2**31,2**31).  Multiple independent streams
     of numbers can be obtained using `jrand48'.

Seed values
-----------

   The *$seed* above are perl scalars. When in use they are converted to 6
byte binary "strings". If the incoming value is a string of less then 6
bytes it is padded with 0xFF. If the incoming value is a string of more
than 6 bytes it is "hashed" using perl's hash function to yield a 32 bit
value which is then padded with two bytes of 0xFF. If the incoming value
is an integer it is used for 4 bytes, with two bytes of 0xFF.

AUTHOR
======

   Nick Ing-Simmons <nick@ni-s.u-net.com>

Random Number Generators
************************

NAME
====

   *Math::Random* - Random Number Generators

SYNOPSIS
========

   *      use Math::Random;

     Exports the following routines by default (see `DEFAULT ROUTINES' in
     this node):

          random_set_seed_from_phrase
          random_get_seed
          random_seed_from_phrase
          random_set_seed
          random_uniform
          random_uniform_integer
          random_permutation
          random_permuted_index
          random_normal

     In this case the extended routines (see `"EXTENDED ROUTINES"' in this
     node) can be used by    qualifying  them  explicitly  with
     `Math::Random::',   for example: `$stdexp =
     Math::Random::random_exponential();'

   *      use Math::Random qw(random_beta
                              random_chi_square
                              random_exponential
                              random_f
                              random_gamma
                              random_multivariate_normal
                              random_multinomial
                              random_noncentral_chi_square
                              random_noncentral_f
                              random_normal
                              random_permutation
                              random_permuted_index
                              random_uniform
                              random_poisson
                              random_uniform_integer
                              random_negative_binomial
                              random_binomial
                              random_seed_from_phrase
                              random_get_seed
                              random_set_seed_from_phrase
                              random_set_seed );

     Exports all the routines explicitly.  Use a subset of the list for the
     routines you want.

   *      use Math::Random qw(:all);

     Exports all the routines, as well.

DESCRIPTION
===========

   *Math::Random* is  a Perl port  of the C version of *randlib*, which is
 a suite of  routines for  generating  random deviates.  See `"RANDLIB"'
in this node for more information.

   This port supports all of the distributions  from which the *Fortran*
and C  versions generate deviates.   The major functionalities that are
excluded  are   the  multiple  generators/splitting  facility  and
antithetic  random number  generation.   These facilities,  along with
some of  the distributions which *are*  included, are probably not of
interest   except  to the   very  sophisticated   user.  If there   is
sufficient interest, the excluded   facilities will be included in   a
future  release.   The code  to   perform the  excluded facilities  is
available as *randlib* in *Fortran* and C source.

Default routines:
-----------------

   The routines which are exported by default are  the only ones that the
average Perl programmer is likely to need.

`random_set_seed_from_phrase($phrase)'
     Sets  the  seed   of the  base  generator  to   a  value determined by
     *$phrase*.  The value used for a given  *$phrase* is consistent from
     implementation to implementation  (it   does not rely on   the machine
     collating sequence).    Note:  When the   Perl processor   loads
     package  *Math::Random*  the seed  is set   to a value  based on  the
     current time.  The seed  changes  each time *Math::Random*  generates
     something random.

     The ability to set the seed is useful for debugging,  or for those who
     like reproducible runs.

`random_get_seed()'
     Returns  an   array of  length two  which  contains  the  two integers
     constituting  the seed   (assuming   a call   in array   context).  An
     invocation   in  a scalar  context  returns   the  integer 2, which is
     probably not useful.

`random_seed_from_phrase($phrase)'
     Returns   an  array of  length  two which  contains   the two integers
     consituting   the seed   (assuming a    call  in array  context).   An
     invocation   in  a scalar  context returns  the   integer  2, which is
     probably not useful.  The  seed generated is the seed  used to set the
     seed in a  call to `random_set_seed_from_phrase'.

     Note:   the  following  two calls  (for   the  same *$phrase*) are
     equivalent:

          random_set_seed(random_seed_from_phrase($phrase));

     and

          random_set_seed_from_phrase($phrase);

`random_set_seed(@seed)'
     Sets  the  seed  of the  base  generator  to  the value *@seed*[0,1].
     Usually, the  argument  *@seed* should be  the result  of  a  call to
     `random_get_seed'  or `random_seed_from_phrase'.  *@seed*[0,1] must
     be two integers in the range (1, 1) to (2147483562, 2147483398),
     inclusive.

`random_uniform($n, $low, $high)'
`random_uniform($n)'
`random_uniform()'
     When called  in an array context,  returns an array of  $n deviates
     generated from   a *uniform($low,* *$high)* distribution.    When
     called in  a scalar context,    generates and returns only  one   such
     deviate as a scalar, regardless of the value of $n.

     Argument restrictions: *$low* must be less than or equal to *$high*.

     Defaults are  (1, 0, 1).    Note:  *$high* must   be specified if
     *$low* is specified.

`random_uniform_integer($n, $low, $high)'
     When called  in an array context,  returns  an array of  $n integer
     deviates generated from  a  *uniform($low,* *$high)* distribution on
     the   integers.  When called   in a  scalar context, generates  and
     returns only one such deviate as a  scalar, regardless of the value of
     $n.

     Argument  restrictions: *$low* and *$high*  are  first rounded using
     `int()'; the resulting *$low* must be less than or equal to *$high*,
     and  the  resulting  range  *($high* - *$low)*  must not be and  the
     resulting  range  *($high - $low)*  must not be greater than
     2147483561.

     There are no defaults; all three arguments must be provided.

`random_permutation(@array)'
     Returns *@array*, randomly permuted.

`random_permuted_index($n)'
     Returns  an array  of  array indices, randomly  permuted.  The indices
     used are (0, ... ,($n -  1)).  This produces the indices used by
     `random_permutation' for a given seed, without passing arrays.

     Note: the following are equivalent:

          random_set_seed_from_phrase('jjv');
          random_permutation(@array);

     and

          random_set_seed_from_phrase('jjv');
          @array[(random_permuted_index(scalar(@array)))];

`random_normal($n, $av, $sd)'
`random_normal($n, $av)'
`random_normal($n)'
`random_normal()'
     When called in  an array context, returns  an array  of $n deviates
     generated from a *normal($av, $sd^2)* distribution.  When called in a
     scalar context,  generates  and returns  only one  such   deviate as a
     scalar, regardless of the value of $n.

     Argument restrictions: *$sd* must be non-negative.

     Defaults are (1, 0, 1).

Extended Routines:
------------------

   These routines generate deviates from many other distributions.

   Note: The parameterizations of these deviates are standard (insofar as
there *is* a  standard ...  ) but  particular attention  should be paid to
the distributions of the *beta*  and *gamma* deviates (noted in
`random_beta' and `random_gamma' below).

`random_beta($n, $aa, $bb)'
     When called in an array  context, returns an  array of $n  deviates
     generated from  the  *beta* distribution  with parameters  *$aa* and
     *$bb*.  The density of the beta is:

     X^(*$aa* - 1) * (1 - X)^(*$bb* - 1) / B(*$aa* , *$bb*) for 0 < X < 1.

     When called in  a scalar context, generates  and returns only one such
     deviate as a scalar, regardless of the value of $n.

     Argument restrictions:  Both *$aa* and *$bb* must  not  be less than
     `1.0E-37'.

     There are no defaults; all three arguments must be provided.

`random_binomial($n, $nt, $p)'
     When called  in an array context,  returns an array  of $n outcomes
     generated  from the  binomial  distribution with  number  of trials
     *$nt* and probability of an  event in each  trial $p.  When called in
     a scalar context, generates and returns  only one such outcome as a
     scalar, regardless of the value of $n.

     Argument restrictions: *$nt*  is rounded  using `int()'; the  result
     must be non-negative.  $p must be between 0 and 1 inclusive.

     There are no defaults; both arguments must be provided.

`random_chi_square($n, $df)'
     When called in an  array context, returns an  array of $n  deviates
     generated from the *chi-square*  distribution with *$df* degrees  of
     freedom.  When called in a  scalar context, generates and returns only
     one such deviate as a scalar, regardless of the value of $n.

     Argument restrictions: *$df* must be positive.

     There are no defaults; both arguments must be provided.

`random_exponential($n, $av)'
`random_exponential($n)'
`random_exponential()'
     When  called in an  array context, returns  an array of $n deviates
     generated from the *exponential* distribution with mean *$av*.  When
     called    in a scalar  context, generates   and  returns only one such
     deviate as a scalar, regardless of the value of $n.

     Argument restrictions: *$av* must be non-negative.

     Defaults are (1, 1).

`random_f($n, $dfn, $dfd)'
     When called  in an array  context, returns an  array of $n deviates
     generated from the F  (variance ratio) distribution with degrees of
     freedom *$dfn* (numerator) and *$dfd* (denominator).  When called in
     a scalar context,  generates and  returns only  one such deviate  as a
     scalar, regardless of the value of $n.

     Argument restrictions: Both *$dfn* and *$dfd* must be positive.

     There are no defaults; all three arguments must be provided.

`random_gamma($n, $a, $r)'
     When called in  an array context, returns  an array of  $n deviates
     generated from  the  *gamma* distribution  with  parameters *$a* and
     $r.  The density of the gamma is:

     (*$a***$r) / Gamma($r) * X**($r - 1) * Exp(-*$a**X)

     When called in  a scalar context, generates and  returns only one such
     deviate as a scalar, regardless of the value of $n.

     Argument restrictions: Both *$a* and $r must be positive.

     There are no defaults; all three arguments must be provided.

`random_multinomial($n, @p)'
     When called in an array  context, returns single observation from  the
     *multinomial* distribution, with $n events classified into as many
     categories as the length of *@p*.   The probability of an event being
     classified into category i is given by the ith element of *@p*.  The
     observation is an array with length equal to *@p*, so when called in
     a scalar  context it  returns  the length  of @p.   The sum of  the
     elements of the observation is equal to $n.

     Argument  restrictions: $n is  rounded  with `int()' before it  is
     used; the  result  must be  non-negative.   *@p* must have  length at
     least 2.  All elements of *@p* except the  last must be between 0 and
     1  inclusive, and sum to  no  more than   0.99999.  Note: The  last
     element of *@p* is a dummy to indicate  the number of categories, and
     it is adjusted to bring the sum of the elements of *@p* to 1.

     There are no defaults; both arguments must be provided.

`random_multivariate_normal($n, @mean, @covar)'
     When  called in an array context,  returns  an array of $n deviates
     (each   deviate  being    an  array  reference) generated   from   the
     *multivariate  normal*  distribution with  mean  vector *@mean*  and
     variance-covariance  matrix  *@covar*.     When called  in  a  scalar
     context,  generates and  returns only  one  such  deviate  as an array
     reference, regardless of the value of $n.

     Argument restrictions: If the dimension of the deviate to be generated
     is p,  *@mean*  should be a   length p array  of real  numbers.
     *@covar* should be  a length p array of  references to length p
     arrays of real  numbers  (i.e.  a  p  by  p  matrix).   Further,
     *@covar* should be a symmetric positive-definite matrix, although the
     Perl code does  not check positive-definiteness, and the underlying C
     code    assumes  the  matrix  is   symmetric.    Given that   the
     variance-covariance matrix is  symmetric, it   doesn't matter if   the
     references  refer   to rows  or columns.   If  a non-positive definite
     matrix is passed  to the function,  it  will abort with the  following
     message:

          COVM not positive definite in SETGMN

     Also,  a    non-symmetric   *@covar* may    produce  deviates without
     complaint,  although they may not  be  from the expected distribution.
     For  these reasons, you  are   encouraged  to *verify  the  arguments
     passed*.

     The Perl code *does*   check  the dimensionality of *@mean*   and
     *@covar* for consistency.  It does so by  checking that the length of
     the argument  vector  passed is  odd,  that  what  should be the  last
     element of *@mean* and the first element  of *@covar* look like they
     are a number followed by an array reference respectively, and that the
     arrays referred to in *@covar* are as long as *@mean*.

     There are no defaults; all three arguments must be provided.

`random_negative_binomial($n, $ne, $p)'
     When  called in an  array context, returns  an array of $n outcomes
     generated from the  *negative  binomial* distribution with number  of
     events *$ne* and  probability of an event  in each trial $p.  When
     called  in  a scalar   context, generates  and  returns only  one such
     outcome as a scalar, regardless of the value of $n.

     Argument restrictions: *$ne* is   rounded using `int()', the  result
     must be positive.  $p must be between 0 and 1 exclusive.

     There are no defaults; both arguments must be provided.

`random_noncentral_chi_square($n, $df, $nonc)'
     When called in  an array context, returns  an array  of $n deviates
     generated  from the *noncentral  chi-square* distribution with *$df*
     degrees of freedom and noncentrality  parameter *$nonc*.  When called
     in a scalar context, generates and returns only  one such deviate as a
     scalar, regardless of the value of $n.

     Argument restrictions:   *$df* must be at  least  1, *$nonc* must be
     non-negative.

     There are no defaults; all three arguments must be provided.

`random_noncentral_f($n, $dfn, $dfd, $nonc)'
     When called in  an array context, returns an  array of  $n deviates
     generated from the *noncentral F*  (variance ratio) distribution with
     degrees of freedom *$dfn* (numerator)  and *$dfd* (denominator); and
     noncentrality parameter *$nonc*.   When  called in a  scalar context,
     generates and returns only one such deviate as a scalar, regardless of
     the value of $n.

     Argument restrictions:  *$dfn* must  be at least   1, *$dfd* must be
     positive, and *$nonc* must be non-negative.

     There are no defaults; all four arguments must be provided.

`random_poisson($n, $mu)'
     When called  in an array context,  returns an array  of $n outcomes
     generated  from the Poisson  distribution  with mean  *$mu*.  When
     called  in a  scalar   context, generates and  returns  only  one such
     outcome as a scalar, regardless of the value of $n.

     Argument restrictions: *$mu* must be non-negative.

     There are no defaults; both arguments must be provided.

ERROR HANDLING
==============

   The Perl code should croak if bad arguments are passed or if the
underlying C code  cannot allocate the  necessary memory.  The only error
which should kill the job without  croaking is a non-positive definite
   variance-covariance      matrix      passed        to
`random_multivarite_normal' (see `"EXTENDED ROUTINES"' in this node).

RANDLIB
=======

   *randlib*  is available in *Fortran* and  C source form, and will soon
be available in *Fortran90* source as well.  *randlib.c* can be obtained
from     *statlib*.  Send mail   whose  message   is *'send randlib.c.shar
from general'* to:

     statlib@lib.stat.cmu.edu

   *randlib.c*   can  also  be    obtained    by  anonymous  ftp   to:

     odin.mdacc.tmc.edu (143.111.62.32)

   where it is available as

     /pub/source/randlib.c-1.3.tar.gz

   For obvious reasons, the original *randlib*  (in *Fortran*) has been
renamed to

     /pub/source/randlib.f-1.3.tar.gz

   on the same machine.

   Our FTP index is on file `./pub/index'.

   If you have Internet access and a browser you might note the following
web site addresses:

   University of Texas M. D. Anderson Cancer Center Home Page:

     http://utmdacc.mdacc.tmc.edu/

   Department of Biomathematics Home Page:

     http://odin.mdacc.tmc.edu/

   Available Software:

     http://odin.mdacc.tmc.edu/anonftp/

SUPPORT
=======

   This work  was supported  in part by  grant CA-16672 from the National
Cancer Institute.  We are grateful  to Larry and  Pat McNeil of Corpus
Cristi for their generous support.  Some equipment used in this effort was
provided by IBM as part of a cooperative study agreement; we thank them.

CODE MANIPULATION
=================

   The   C  version of  *randlib*  was  obtained  by  translating the
original   *Fortran*     *randlib*  using  *PROMULA.FORTRAN*,   and
performing some hand crafting of the result.

   Information on *PROMULA.FORTRAN* can be obtained from:

     PROMULA Development Corporation
      3620 N. High Street, Suite 301
     			 Columbus, Ohio 43214
     			    (614) 263-5454

   `wrapper.c'  was created  by   using  *SWIG*, and  performing   some
modification of the result.    *SWIG* also produced the skeleton   of
`Random.pm'.

   Information on *SWIG* can be obtained from:

     http://www.cs.utah.edu/~beazley/SWIG

   and

     ftp://ftp.cs.utah.edu/pub/beazley/SWIG

SOURCES
=======

   The following routines,  which  were  written by others   and  lightly
modified for consistency in packaging, are included in *randlib*.

Bottom Level Routines
     These routines are a transliteration of the *Pascal* in the reference
     to *Fortran*, and thence to C.

     L'Ecuyer, P., and Cote, S. "Implementing  a Random Number Package with
     Splitting  Facilities."  ACM  Transactions   on Mathematical Software,
     17:98-111 (1991).

Exponential
     This code was obtained from Netlib.

     Ahrens, J. H., and Dieter, U.  "Computer Methods for Sampling from the
     Exponential and Normal  Distributions."  Comm. ACM, 15,10 (Oct. 1972),
     873-882.

Gamma
     (Case R >= 1.0)

     Ahrens, J. H., and Dieter, U. "Generating Gamma Variates by a Modified
     Rejection Technique."  Comm. ACM, 25,1 (Jan. 1982), 47-54.  Algorithm
     GD

     (Case 0.0 <= R <= 1.0)

     Ahrens, J. H.,  and  Dieter, U.  "Computer Methods  for Sampling  from
     Gamma, Beta, Poisson and Binomial Distributions."  Computing, 12
     (1974), 223-246.  Adaptation of algorithm GS.

Normal
     This code was obtained from netlib.

     Ahrens, J. H., and  Dieter, U.   "Extensions of  Forsythe's Method for
     Random Sampling  from the Normal Distribution."  Math. Comput., 27,124
     (Oct. 1973), 927-937.

Binomial
     This code was kindly sent to Dr. Brown by Dr. Kachitvichyanukul.

     Kachitvichyanukul, V., and Schmeiser,  B. W.  "Binomial Random Variate
     Generation."  Comm. ACM, 31, 2 (Feb. 1988), 216.

Poisson
     This code was obtained from netlib.

     Ahrens, J. H., and Dieter, U. "Computer Generation of Poisson Deviates
     from Modified Normal Distributions."  ACM Trans.  Math. Software, 8, 2
     (June 1982), 163-179.

Beta
     This code was written by us following the recipe in the following.

     Cheng, R. C. H.  "Generating  Beta Variables  with  Nonintegral  Shape
     Parameters."  Comm. ACM, 21:317-322 (1978). (Algorithms BB and BC)

Linpack
     Routines   `SPOFA' and  `SDOT' are  used    to perform  the Cholesky
     decomposition of   the covariance matrix  in  `SETGMN'  (used for the
     generation of multivariate normal deviates).

     Dongarra, J. J., Moler,   C.  B., Bunch, J.   R., and  Stewart, G.  W.
     Linpack User's Guide.  SIAM Press, Philadelphia.  (1979)

Multinomial
     The  algorithm is from  page 559  of Devroye,  Luc Non-Uniform  Random
     Variate Generation.  New York: Springer-Verlag, 1986.

Negative Binomial
     The  algorithm is from  page 480  of Devroye,  Luc Non-Uniform  Random
     Variate Generation.  New York: Springer-Verlag, 1986.

VERSION
=======

   This POD documents *Math::Random* version 0.61.

AUTHORS
=======

   * *Math::Random* (the Perl port  of *Randlib*) was put  together by
     John Venier  and Barry W. Brown with help from  *SWIG*.  For  version
     0.61, Geoffrey Rommel made various cosmetic changes.

   * *randlib* was compiled and written  by: Barry W. Brown, James Lovato,
     Kathy Russell, and John Venier.

   * Correspondence   regarding   *Math::Random* or   *randlib* should be
     addressed to John Venier by email to

          venier@odin.mdacc.tmc.edu

   * Our address is:

          Department of Biomathematics, Box 237
          	 The University of Texas, M.D. Anderson Cancer Center
                 1515 Holcombe Boulevard
          	  Houston, TX 77030

   * Geoffrey Rommel may be reached at grommel@sears.com.

LEGALITIES
==========

   * The programs in the  Perl code distributed with *Math::Random* and in
       the C code `helper.c', as    well as  the documentation, are
     copyright by John  Venier and  Barry  W.  Brown for the  University of
     Texas M.  D.  Anderson Cancer Center in 1997.  They may be distributed
     and used under the same conditions as Perl.

   * The code in `wrapper.c' is lightly modified from the output of *SWIG*.
     See `"CODE MANIPULATION"' in this node.

   * `randlib.c',  `com.c',  and `randlib.h'   are from  *randlib* (See
     `"RANDLIB"' in this node) and are distributed with the following
     legalities:

     Code that appeared  in an    ACM  publication  is subject  to    their
     algorithms policy:

     Submittal of  an  algorithm    for publication  in   one of   the  ACM
     Transactions implies that unrestricted use  of the algorithm within  a
     computer is permissible.   General permission  to copy and  distribute
     the algorithm without fee is granted provided that the copies  are not
     made  or   distributed for  direct   commercial  advantage.    The ACM
     copyright notice and the title of the publication and its date appear,
     and  notice is given that copying  is by permission of the Association
     for Computing Machinery.  To copy otherwise, or to republish, requires
     a fee and/or specific permission.

     Krogh, F.  "Algorithms Policy."  ACM  Tran.  Math.  Softw.  13 (1987),
     183-186.

     We place the Randlib code that we have written in the public domain.

   * *Math::Randlib* and *randlib*  are distributed  with NO WARRANTY.
     See `"NO WARRANTY"' in this node.

NO WARRANTY
===========

   WE PROVIDE  ABSOLUTELY  NO WARRANTY  OF ANY  KIND  EITHER  EXPRESS  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 THIS
PROGRAM PROVE  DEFECTIVE, YOU ASSUME  THE COST  OF  ALL NECESSARY
SERVICING, REPAIR OR CORRECTION.

   IN NO  EVENT  SHALL THE UNIVERSITY  OF TEXAS OR  ANY  OF ITS COMPONENT
INSTITUTIONS INCLUDING M. D.   ANDERSON HOSPITAL BE LIABLE  TO YOU FOR
DAMAGES, INCLUDING ANY  LOST PROFITS, LOST MONIES,   OR OTHER SPECIAL,
INCIDENTAL   OR  CONSEQUENTIAL DAMAGES   ARISING   OUT  OF  THE USE OR
INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA OR ITS
ANALYSIS BEING  RENDERED INACCURATE OR  LOSSES SUSTAINED  BY THIRD PARTIES
FROM) THE PROGRAM.

   (Above NO WARRANTY modified from the GNU NO WARRANTY statement.)

Perl extension for rounding numbers
***********************************

NAME
====

   Math::Round - Perl extension for rounding numbers

SYNOPSIS
========

     use Math::Round qw(...those desired... or :all);

     $rounded = round($scalar);
     @rounded = round(LIST...);
     $rounded = nearest($target, $scalar);
     @rounded = nearest($target, LIST...);

     # and other functions as described below

DESCRIPTION
===========

   *Math::Round* supplies functions that will round numbers in different
ways.  The functions round and nearest are exported by default; others are
available as described below.  "use ... qw(:all)" exports all functions.

FUNCTIONS
=========

round LIST
     Rounds the number(s) to the nearest integer.  In scalar context,
     returns a single value; in list context, returns a list of values.
     Numbers that are halfway between two integers are rounded "to
     infinity"; i.e., positive values are rounded up (e.g., 2.5 becomes 3)
     and negative values down (e.g., -2.5 becomes -3).

round_even LIST
     Rounds the number(s) to the nearest integer.  In scalar context,
     returns a single value; in list context, returns a list of values.
     Numbers that are halfway between two integers are rounded to the
     nearest even number; e.g., 2.5 becomes 2, 3.5 becomes 4, and -2.5
     becomes -2.

round_odd LIST
     Rounds the number(s) to the nearest integer.  In scalar context,
     returns a single value; in list context, returns a list of values.
     Numbers that are halfway between two integers are rounded to the
     nearest odd number; e.g., 3.5 becomes 3, 4.5 becomes 5, and -3.5
     becomes -3.

round_rand LIST
     Rounds the number(s) to the nearest integer.  In scalar context,
     returns a single value; in list context, returns a list of values.
     Numbers that are halfway between two integers are rounded up or down
     in a random fashion.  For example, in a large number of trials, 2.5
     will become 2 half the time and 3 half the time.

nearest TARGET, LIST
     Rounds the number(s) to the nearest multiple of the target value.
     TARGET must be positive.  In scalar context, returns a single value;
     in list context, returns a list of values.  Numbers that are halfway
     between two multiples of the target will be rounded to infinity.  For
     example:

          nearest(10, 44)    yields  40
          nearest(10, 46)            50
          nearest(10, 45)            50
          nearest(25, 328)          325
          nearest(.1, 4.567)          4.6
          nearest(10, -45)          -50

nearest_rand TARGET, LIST
     Rounds the number(s) to the nearest multiple of the target value.
     TARGET must be positive.  In scalar context, returns a single value;
     in list context, returns a list of values.  Numbers that are halfway
     between two multiples of the target will be rounded up or down in a
     random fashion.  For example, in a large number of trials,
     nearest(10, 45) will yield 40 half the time and 50 half the time.

STANDARD FLOATING-POINT DISCLAIMER
==================================

   If the numbers to be rounded are stored as floating-point, they will be
subject, as usual, to the mercies of your hardware, your C compiler, etc.
Thus, numbers that are supposed to be halfway between two others may be
stored in a slightly different way and thus behave surprisingly.

AUTHOR
======

   Math::Round was written by Geoffrey Rommel <GROMMEL@cpan.org> in
October 2000.

Perl extension for SO3 rotations
********************************

NAME
====

   Math::SO3 - Perl extension for SO3 rotations

   (Useful for: implementing orientation in 3d scenes. One major nice
feature of this package is to prevent numerical drift that makes rotation
matrices nonorthogonal when combining lots of them. And no, this is a
direct implementation, of SO3 it does not use quaternions and SU2->SO3
homomorphism.)

SYNOPSIS
========

     use Math::SO3;

     $rotation=Math::SO3->new("zr" => 3.14159/2,
     			   "xr" => 3.14159/4,
     			   "zr" => 3.14159/8);

     $rotation=Math::SO3->new("zd" => 90,
     			   "xd" => 90,
     			   "zr" => 3.14159/6);

     $rotation->invert();

     $rotation->turn("zr" => 3.14159/2, "xr" => 3.14159/4);

     $rotation->turn_round_axis((pack "d3", 1,1,1), 30, "degrees");

     $rotation->combine($rotation_after);

     $rotation->translate_vectors($vec1, $vec2,
                                  $vec3, $vec4, @more_vectors);

     $rotation->inv_translate_vectors($vec1, $vec2, $vec3,
     				   $vec4, @more_vectors);

     ($angle, $dir)=$rotation->turning_angle_and_dir("d");

     ($phi, $theta, $psi)=$rotation->euler_angles_zxz("d");

     ($heading, $pitch, $roll)=$rotation->euler_angles_yxz("d");

     $rotation->format_matrix();
     $rotation->format_matrix("%16.8f");

     $rotation->format_eigenvector();
     $rotation->format_eigenvector("%16.8f");

     $rotation->format_euler_zxz();
     $rotation->format_euler_zxz("%16.8f");

     $rotation->format_euler_yxz();
     $rotation->format_euler_yxz("%16.8f");

DESCRIPTION
===========

     Internal representation: SO3s are blessed refs to strings
     of size 3*3*sizeof(double) which contain the rotation
     matrix elements in standard C order. THIS IS PART OF THE
     OFFICIAL INTERFACE, so you may use this information, if
     you want. (It simply doesn't make much sense to
     inherit from purely mathematical data types like this one,
     so this doesn't hurt.)

     Note: whenever the text below says "d" is used for angles
     in degrees, any string starting with a lowercase "d" will
     work. Same goes for "r" for rad. If you entirely leave it
     away, default is "r". So you have much freedom in choosing
     those terms which are most descriptive and most readable.

     Note: some textbooks on Mechanics (like the very good and
     very influential one by Goldstein) follow the convention

     (e1')    (   ) (e1)
     (e2')  = ( M ) (e2)
     (e3')    (   ) (e3)

     This is not very fortunate, since it introduces some nasty
     ambiguity: it's easy to misinterpret the "vector-rotation
     matrix" M as the coefficient-rotation matrix, which,
     however, is just M^T.

     Matrix/vector calculus is exploited best if one agrees to
     write coefficient vectors as column vectors and the "array
     of base vectors" as a row vector (e1 e2 e3). Just look here:

     (a1)
       a1*e1 + a2*e2 + a3*e3 = (e1 e2 e3) (a2)
     (a3)

     Therefore, WE use the convention

     (a1')    (   ) (a1)
     (a2')  = ( M ) (a2)
     (a3')    (   ) (a3)

     (   )
       (e1 e2 e3) = (e1' e2' e3') ( M )
     (   )

     For details, see e.g. "Misner, Thorne, Wheeler:
     Gravitation". Unfortunately, the "wrong way" is rather
     widespread. Even OpenGL seems to want us to think this
     way. Please try not to get too confused about this; or
     better, if you are confused: yes, it's not entirely
     trivial what's going on here. Our three-dimensional space
     *is* a bit complicated.  But there is a recipe to master
     it: practice. Once you can think of one constellation in
     two different coordinate systems, you have won.

     In rigid body mechanics, it's best to think of this M as
     the matrix, which, when multiplied-right with a column
     space-coordinate vector (cscv) gives the corresponding
     column body-coordinate vector (cbcv).

     $rotation=Math::SO3->new("zr" => 3.14159/2,
     			   "xr" => 3.14159/4,
     			   "zr" => 3.14159/8);

     Create a new SO3-rotation matrix. You may specify an
     arbitrary number of rotations performed on the identity
     matrix. In the above case, if you think of $rotation as
     the matrix translating column-space-coordinate-vectors
     to column-body-coordinate-vectors (from here on called
     cscv->cbcv), these rotations you specify here will be
     applied to the body, rotating the body round one of its
     body axes. Important: Leftmost rotation will be applied
     first.  "zr" means rotate round z-axis, angle is in rad
     (full turn= 2pi rad); "xd" would mean: rotate round
     x-axis, angle is in degrees (full turn=360 degrees). Can
     be mixed.

     May also act as a copying constructor, as in:
      $copy=$rotation->new().

     $rotation->invert();

     Invert a rotation.

     $rotation->turn("zr" => 3.14159/2, "xr" => 3.14159/4);

     Just as you can specify rotations at SO3 creation,
     you may add a few more later on. Although "numerical drift" can
     build up, it is not possible for the rotation to get noticeably
     non-orthogonal.

     $rotation->turn_round_axis((pack "d3", 1,1,1), 30, "degrees");

     Turn the body round the axis given in space coordinates.

     $rotation->combine($rotation_after);

     left-multiplies with $rotation_after, that is, executes
     $rotation_after after $rotation, in the sense defined
     above.

     $rotation->translate_vectors($vec1, $vec2,
                                  $vec3, $vec4, @other_vectors);

     Destructively replace each single one of a list of
     cscv's by the corresponding cbcv's. Note that vectors
     must be packed-double-strings:
     $vec=pack("d3",$xcoord,$ycoord,$zcoord);

     Note: if vectors are "longer", say, like pack("d4", 5,8,10,1),
     only the first three coordinates will be replaced.
     This is very useful when working with homogenous coordinates.

     $rotation->inv_translate_vectors($vec1, $vec2,
                                      $vec3, $vec4, @other_vectors);

     Just the other way round, going cbcv -> cscv.

     ($angle, $dir)=$rotation->turning_angle_and_dir("d");

     Euler's theorem states that in three dimensions, every
     combination of rotations may be expressed as a single
     rotation round a given direction.  This determines angle
     and direction Say "d" if you want degrees, "r" for rad.

     FIXME code for this function is a bit weird and really
     should be reviewed. So please, you NASA guys, don't use
     it to compute RTG-satellite trajectories.

     ($phi, $theta, $psi)=$rotation->euler_angles_zxz("d");

     Returns just the famous Euler angles corresponding to a
     rotation. Specify "d" if you want degrees, "r" for rad.

     Note: this is designed for speed, and may, for a very
     small fraction of all possible angles, give bad results
     due to division by a small quantity.

     ($heading, $pitch, $roll)=$rotation->euler_angles_yxz("d");

     Standard zxz euler angles have one problem: if theta
     is very small, phi and psi rotations nearly go in
     the same direction, therefore, it's a bit difficult
     to see from coordinates if two rotations are very
     similar or are absolutely not. This is an alternative
     angle specification which is very common in aeronautics.
     Probably just the thing you need if you want to build
     a flight simulator.

     Note: accuracy see above.

     $rotation->format_matrix();
     $rotation->format_matrix("%16.8f");

     Computes a string
     "[[m00 m01 m02][m10 m11 m12][m20 m21 m22]]"
     displaying the matrix elements. Optionally, a sprintf
     format-string may be specified for the matrix
     elements. Default is "%10.5f".

     $rotation->format_eigenvector();
     $rotation->format_eigenvector("%16.8f");

     Similarly, computes a string like
     "<rotate   92.06153 deg round [   0.88972    0.07784   -0.44982]>"

     $rotation->format_euler_zxz();
     $rotation->format_euler_zxz("%16.8f");

     Similarly, computes a string like
     "<D_z(psi= 330.00000 deg) D_x(theta=  80.00000 deg) D_z(phi= 340.00000 deg)>"

     $rotation->format_euler_yxz();
     $rotation->format_euler_yxz("%16.8f");

     Just the same, but string is like
     "<D_z(heading= 338.30608 deg) D_x(pitch= -24.51349 deg) D_z(roll= 348.25034 deg)>"

     Basically, these functions were added as a quick way to
     get debugging info.  Therefore, all angles are given in
     degrees, since these are more readable.

AUTHOR AND LICENSE
==================

   Copyright 1999 Thomas Fischbacher

   (tf@cip.physik.uni-muenchen.de)

   License: GNU Lesser General Public License (aka GNU LGPL) Copy of the
LGPL not included, since it should come with your copy of perl. You may
find it at

   http://www.gnu.org/copyleft/lesser.html

SEE ALSO
========

   perl(1).

do math with correct handling of significant figures
****************************************************

NAME
====

   Math::SigFigs - do math with correct handling of significant figures

SYNOPSIS
========

   If you only need to use CountSigFigs and FormatSigFigs, use the first
form.  If you are going to be doing arithmetic, use the second line.

     use Math::SigFigs;
     use Math::SigFigs qw(:all);

   The following routines do simple counting/formatting:

     $n=&CountSigFigs($num);
     $num=&FormatSigFigs($num,$n);

   Use the following routines to do arithmetic operations.

     $num=&addSF($n1,$n2);
     $num=&subSF($n1,$n2);
     $num=&multSF($n1,$n2);
     $num=&divSF($n1,$n2);

DESCRIPTION
===========

   In many scientific applications, it is often useful to be able to format
numbers with a given number of significant figures, or to do math in such
a way as to maintain the correct number of significant figures.  The rules
for significant figures are too complicated to be handled solely using the
sprintf function (unless you happen to be Randal Schwartz :-).

   These routines allow you to correctly handle significan figures.

   It can count the number of significan figures, format a number to a
given number of significant figures, and do basic arithmetic.

ROUTINES
========

CountSigFigs
          $n=&CountSigFigs($N);

     This returns the number of significant figures in a number.  It
     returns () if $N is not a number.

          $N      $n
          -----   --
          240     2
          240.    3
          241     3
          0240    2
          0.03    1
          0       0
          0.0     0

FormatSigFigs
          $str=&FormatSigFigs($N,$n)

     This returns a string containing $N formatted to $n significant
     figures.  This will work for all cases except something like "2400"
     formatted to 3 significant figures.

          $N     $n   $str
          ------ --   -------
          2400    1   2000
          2400    2   2400
          2400    3   2400
          2400    4   2400.
          2400    5   2400.0

          141     3   141.
          141     2   140

          0.039   1   0.04
          0.039   2   0.039

          9.9     1   10
          9.9     2   9.9
          9.9     3   9.90

addSF, subSF, multSF, divSF
     These routines add/subtract/multiply/divide two numbers while
     maintaining the proper number of significant figures.

KNOWN PROBLEMS
==============

   These routines do not work with scientific notation (exponents).  As a
result, it is impossible to unambiguously format some numbers.  For
example,

     $str=&FormatSigFigs("2400",3);

   will by necessity return the string "2400" which does NOT have 3
significant figures.  This is not a bug.  It is simply a fundamental
problem with working with significant figures when not using scientific
notation.

AUTHOR
======

   Sullivan Beck (sbeck@cise.ufl.edu)

SYNOPSIS          require Math::Spline;     $spline=new Math::Spline(\@x,\@y)     $y_interp=$spline->evaluate($x);
==================================================================================================================

     use Math::Spline qw(spline linsearch binsearch);
     use Math::Derivative qw(Derivative2);
     @y2=Derivative2(\@x,\@y);
     $index=binsearch(\@x,$x);
     $index=linsearch(\@x,$x,$index);
     $y_interp=spline(\@x,\@y,\@y2,$index,$x);

DESCRIPTION
===========

   This package provides cubic spline interpolation of numeric data. The
data is passed as references to two arrays containing the x and y
ordinates. It may be used as an exporter of the numerical functions or,
more easily as a class module.

   The *Math::Spline* class constructor new takes references to the arrays
of x and y ordinates of the data. An interpolation is performed using the
evaluate method, which, when given an x ordinate returns the interpolate y
ordinate at that value.

   The *spline* function takes as arguments references to the x and y
ordinate array, a reference to the 2nd derivatives (calculated using
*Derivative2*, the low index of the interval in which to interpolate and
the x ordinate in that interval. Returned is the interpolated y ordinate.
Two functions are provided to look up the appropriate index in the array
of x data. For random calls *binsearch* can be used - give a reference to
the x ordinates and the x loopup value it returns the low index of the
interval in the data in which the value lies. Where the lookups are
strictly in ascending sequence (e.g. if interpolating to produce a higher
resolution data set to draw a curve) the *linsearch* function may more
efficiently be used. It performs like *binsearch*, but requires a third
argument being the previous index value, which is incremented if necessary.

NOTE
====

   requires Math::Derivative module

EXAMPLE
=======

     require Math::Spline;
     my @x=(1,3,8,10);
     my @y=(1,2,3,4);
     $spline=new Math::Spline(\@x,\@y);
     print $spline->evaluate(5)."\n";

   produces the output

   2.44

HISTORY
=======

   $Log: Spline.pm,v $ Revision 1.1  1995/12/26 17:28:17  willijar Initial
revision

BUGS
====

   Bug reports or constructive comments are welcome.

AUTHOR
======

   John A.R. Williams <J.A.R.Williams@aston.ac.uk>

SEE ALSO
========

   "Numerical Recipies: The Art of Scientific Computing" W.H. Press, B.P.
Flannery, S.A. Teukolsky, W.T. Vetterling.  Cambridge University Press.
ISBN 0 521 30811 9.

trigonometric functions
***********************

NAME
====

   Math::Trig - trigonometric functions

SYNOPSIS
========

     use Math::Trig;

     $x = tan(0.9);
     $y = acos(3.7);
     $z = asin(2.4);

     $halfpi = pi/2;

     $rad = deg2rad(120);

DESCRIPTION
===========

   Math::Trig defines many trigonometric functions not defined by the core
Perl which defines only the `sin()' and `cos()'.  The constant pi is also
defined as are a few convenience functions for angle conversions.

TRIGONOMETRIC FUNCTIONS
=======================

   The tangent

tan
   The cofunctions of the sine, cosine, and tangent (cosec/csc and
cotan/cot are aliases)

   *csc*, *cosec*, sec, sec, *cot*, *cotan*

   The arcus (also known as the inverse) functions of the sine, cosine,
and tangent

   asin, acos, atan

   The principal value of the arc tangent of y/x

   atan2(y, x)

   The arcus cofunctions of the sine, cosine, and tangent (acosec/acsc and
acotan/acot are aliases)

   *acsc*, *acosec*, *asec*, *acot*, *acotan*

   The hyperbolic sine, cosine, and tangent

   sinh, cosh, tanh

   The cofunctions of the hyperbolic sine, cosine, and tangent (cosech/csch
and cotanh/coth are aliases)

   *csch*, *cosech*, *sech*, *coth*, *cotanh*

   The arcus (also known as the inverse) functions of the hyperbolic sine,
cosine, and tangent

   asinh, acosh, atanh

   The arcus cofunctions of the hyperbolic sine, cosine, and tangent
(acsch/acosech and acoth/acotanh are aliases)

   *acsch*, *acosech*, *asech*, *acoth*, *acotanh*

   The trigonometric constant pi is also defined.

   $pi2 = 2 * pi;

ERRORS DUE TO DIVISION BY ZERO
------------------------------

   The following functions

     acoth
     acsc
     acsch
     asec
     asech
     atanh
     cot
     coth
     csc
     csch
     sec
     sech
     tan
     tanh

   cannot be computed for all arguments because that would mean dividing
by zero or taking logarithm of zero. These situations cause fatal runtime
errors looking like this

     cot(0): Division by zero.
     (Because in the definition of cot(0), the divisor sin(0) is 0)
     Died at ...

   or

     atanh(-1): Logarithm of zero.
     Died at...

   For the `csc', `cot', `asec', `acsc', `acot', `csch', `coth', `asech',
`acsch', the argument cannot be 0 (zero).  For the atanh, `acoth', the
argument cannot be 1 (one).  For the atanh, `acoth', the argument cannot
be `-1' (minus one).  For the tan, sec, tanh, `sech', the argument cannot
be *pi/2 + k * pi*, where k is any integer.

SIMPLE (REAL) ARGUMENTS, COMPLEX RESULTS
----------------------------------------

   Please note that some of the trigonometric functions can break out from
the *real axis* into the *complex plane*. For example `asin(2)' has no
definition for plain real numbers but it has definition for complex
numbers.

   In Perl terms this means that supplying the usual Perl numbers (also
known as scalars, please see Perldata (perl.info)) as
input for the trigonometric functions might produce as output results that
no more are simple real numbers: instead they are complex numbers.

   The Math::Trig handles this by using the Math::Complex package which
knows how to handle complex numbers, please see Math/Complex,
for more information. In practice you need not to worry
about getting complex numbers as results because the Math::Complex takes
care of details like for example how to display complex numbers. For
example:

     print asin(2), "\n";

   should produce something like this (take or leave few last decimals):

     1.5707963267949-1.31695789692482i

   That is, a complex number with the real part of approximately `1.571'
and the imaginary part of approximately `-1.317'.

PLANE ANGLE CONVERSIONS
=======================

   (Plane, 2-dimensional) angles may be converted with the following
functions.

     $radians  = deg2rad($degrees);
     $radians  = grad2rad($gradians);

     $degrees  = rad2deg($radians);
     $degrees  = grad2deg($gradians);

     $gradians = deg2grad($degrees);
     $gradians = rad2grad($radians);

   The full circle is 2 pi radians or *360* degrees or *400* gradians.

RADIAL COORDINATE CONVERSIONS
=============================

   *Radial coordinate systems* are the *spherical* and the *cylindrical*
systems, explained shortly in more detail.

   You can import radial coordinate conversion functions by using the
`:radial' tag:

     use Math::Trig ':radial';

     ($rho, $theta, $z)     = cartesian_to_cylindrical($x, $y, $z);
     ($rho, $theta, $phi)   = cartesian_to_spherical($x, $y, $z);
     ($x, $y, $z)           = cylindrical_to_cartesian($rho, $theta, $z);
     ($rho_s, $theta, $phi) = cylindrical_to_spherical($rho_c, $theta, $z);
     ($x, $y, $z)           = spherical_to_cartesian($rho, $theta, $phi);
     ($rho_c, $theta, $z)   = spherical_to_cylindrical($rho_s, $theta, $phi);

   *All angles are in radians*.

COORDINATE SYSTEMS
------------------

   *Cartesian* coordinates are the usual rectangular *(x, y,
z)*-coordinates.

   Spherical coordinates, *(rho, theta, pi)*, are three-dimensional
coordinates which define a point in three-dimensional space.  They are
based on a sphere surface.  The radius of the sphere is *rho*, also known
as the *radial* coordinate.  The angle in the *xy*-plane (around the
z-axis) is *theta*, also known as the *azimuthal* coordinate.  The angle
from the z-axis is *phi*, also known as the *polar* coordinate.  The
`North Pole' is therefore *0, 0, rho*, and the `Bay of Guinea' (think of
the missing big chunk of Africa) *0, pi/2, rho*.  In geographical terms
*phi* is latitude (northward positive, southward negative) and *theta* is
longitude (eastward positive, westward negative).

   *BEWARE*: some texts define *theta* and *phi* the other way round, some
texts define the *phi* to start from the horizontal plane, some texts use
r in place of *rho*.

   Cylindrical coordinates, *(rho, theta, z)*, are three-dimensional
coordinates which define a point in three-dimensional space.  They are
based on a cylinder surface.  The radius of the cylinder is *rho*, also
known as the *radial* coordinate.  The angle in the *xy*-plane (around the
z-axis) is *theta*, also known as the *azimuthal* coordinate.  The third
coordinate is the z, pointing up from the *theta*-plane.

3-D ANGLE CONVERSIONS
---------------------

   Conversions to and from spherical and cylindrical coordinates are
available.  Please notice that the conversions are not necessarily
reversible because of the equalities like pi angles being equal to *-pi*
angles.

cartesian_to_cylindrical
          ($rho, $theta, $z) = cartesian_to_cylindrical($x, $y, $z);

cartesian_to_spherical
          ($rho, $theta, $phi) = cartesian_to_spherical($x, $y, $z);

cylindrical_to_cartesian
          ($x, $y, $z) = cylindrical_to_cartesian($rho, $theta, $z);

cylindrical_to_spherical
          ($rho_s, $theta, $phi) = cylindrical_to_spherical($rho_c, $theta, $z);

     Notice that when `$z' is not 0 `$rho_s' is not equal to `$rho_c'.

spherical_to_cartesian
          ($x, $y, $z) = spherical_to_cartesian($rho, $theta, $phi);

spherical_to_cylindrical
          ($rho_c, $theta, $z) = spherical_to_cylindrical($rho_s, $theta, $phi);

     Notice that when `$z' is not 0 `$rho_c' is not equal to `$rho_s'.

GREAT CIRCLE DISTANCES
======================

   You can compute spherical distances, called *great circle distances*,
by importing the `great_circle_distance' function:

     use Math::Trig 'great_circle_distance'

     $distance = great_circle_distance($theta0, $phi0, $theta1, $phi1, [, $rho]);

   The *great circle distance* is the shortest distance between two points
on a sphere.  The distance is in `$rho' units.  The `$rho' is optional, it
defaults to 1 (the unit sphere), therefore the distance defaults to
radians.

   If you think geographically the *theta* are longitudes: zero at the
Greenwhich meridian, eastward positive, westward negative-and the *phi*
are latitudes: zero at the North Pole, northward positive, southward
negative.  NOTE: this formula thinks in mathematics, not geographically:
the *phi* zero is at the North Pole, not at the Equator on the west coast
of Africa (Bay of Guinea).  You need to subtract your geographical
coordinates from *pi/2* (also known as 90 degrees).

     $distance = great_circle_distance($lon0, pi/2 - $lat0,
                                       $lon1, pi/2 - $lat1, $rho);

EXAMPLES
========

   To calculate the distance between London (51.3N 0.5W) and Tokyo (35.7N
139.8E) in kilometers:

     use Math::Trig qw(great_circle_distance deg2rad);

     # Notice the 90 - latitude: phi zero is at the North Pole.
     	@L = (deg2rad(-0.5), deg2rad(90 - 51.3));
     @T = (deg2rad(139.8),deg2rad(90 - 35.7));

     $km = great_circle_distance(@L, @T, 6378);

   The answer may be off by few percentages because of the irregular
(slightly aspherical) form of the Earth.  The used formula

     lat0 = 90 degrees - phi0
     lat1 = 90 degrees - phi1
     d = R * arccos(cos(lat0) * cos(lat1) * cos(lon1 - lon01) +
                            sin(lat0) * sin(lat1))

   is also somewhat unreliable for small distances (for locations
separated less than about five degrees) because it uses arc cosine which
is rather ill-conditioned for values close to zero.

BUGS
====

   Saying `use Math::Trig;' exports many mathematical routines in the
caller environment and even overrides some (sin, cos).  This is construed
as a feature by the Authors, actually... ;-)

   The code is not optimized for speed, especially because we use
Math::Complex and thus go quite near complex numbers while doing the
computations even when the arguments are not. This, however, cannot be
completely avoided if we want things like `asin(2)' to give an answer
instead of giving a fatal runtime error.

AUTHORS
=======

   Jarkko Hietaniemi <`jhi@iki.fi'> and Raphael Manfredi
<`Raphael_Manfredi@pobox.com'>.

Perl interface to a truly random number generator function
**********************************************************

NAME
====

   TrulyRandom - Perl interface to a truly random number generator function

SYNOPSIS
========

     use Math::TrulyRandom;

     $random = truly_random_value();

DESCRIPTION
===========

   The *TrulyRandom* module provides an ability to generate truly random
numbers from within Perl programs.  The source of the randomness is from
interrupt timing discrepancies.

EXAMPLE
=======

     $random = truly_random_value();

BUGS
====

   The random numbers take a long time (in computer terms) to generate, so
are only really useful for seeding pseudo random sequence generators.

COPYRIGHT
=========

   This implementation derives from the truly random number generator
function developed by Matt Blaze and Don Mitchell, and is copyright of
AT&T.  Other parts of this perl extension are copyright of Systemics Ltd (
http://www.systemics.com/ ).

Unit conversion
***************

NAME
====

   Math::Units - Unit conversion

SYNOPSIS
========

   use Math::Units qw(convert);

   my $out_value = convert($in_value, 'in unit', 'out unit');

DESCRIPTION
===========

   The Math::Units module converts a numeric value in one unit of
measurement to some other unit.  The units must be compatible, i.e. length
can not be converted to volume.  If a conversion can not be made an
exception is thrown.

   A combination chaining and reduction algorithm is used to perform the
most direct unit conversion possible.  Units may be written in several
different styles.  An abbreviation table is used to convert from common
long-form unit names to the (more or less) standard abbreviations that the
units module uses internally.  All multiplicative unit conversions are
cached so that future conversions can be performed very quickly.

   Too many units, prefixes and abbreviations are supported to list here.
See the source code for a complete listing.

EXAMPLES
========

   print "5 mm == ", convert(5, 'mm', 'in'), " inches\n"; print "72
degrees Farenheit == ", convert(72, 'F', 'C'), " degrees Celsius\n"; print
"1 gallon == ", convert(1, 'gallon', 'cm^3'), " cubic centimeters\n";
print "4500 rpm == ", convert(4500, 'rpm', 'Hz'), " Hertz\n";

Some basic numeric stats on vectors
***********************************

NAME
====

     Math::VecStat - Some basic numeric stats on vectors

SYNOPSIS
========

     use Math::VecStat qw(max min maxabs minabs sum average);
     $max=max(@vector);
     $max=max(\@vector);
     ($max,$imax)=max(@vector);
     ($max,$imax)=max(\@vector);
     $min=min(@vector);
     $min=min(\@vector);
     ($max,$imin)=min(@vector);
     ($max,$imin)=min(\@vector);
     $max=maxabs(@vector);
     $max=maxabs(\@vector);
     ($max,$imax)=maxabs(@vector);
     ($max,$imax)=maxabs(\@vector);
     $min=minabs(@vector);
     $min=minabs(\@vector);
     ($max,$imin)=minabs(@vector);
     ($max,$imin)=minabs(\@vector);
     $sum=sum($v1,$v2,...);
     $sum=sum(@vector);
     $sum=sum(\@vector);
     $average=average($v1,$v2,...);
     $av=average(@vector);
     $av=average(\@vector);
     $ref=vecprod($scalar,\@vector);
     $ok=ordered(@vector);
     $ok=ordered(\@vector);
     $ref=sumbyelement(\@vector1,\@vector2);
     $ref=diffbyelement(\@vector1,\@vector2);
     $ok=allequal(\@vector1,\@vector2);
     $ref=convolute(\@vector1,\@vector2);

DESCRIPTION
===========

   This package provides some basic statistics on numerical vectors. All
the subroutines can take a reference to the vector to be operated on. In
some cases a copy of the vector is acceptable, but is not recommended for
efficiency.

max(@vector), max(\@vector)
     return the maximum value of given values or vector. In an array
     context returns the value and the index in the array where it occurs.

min(@vector), min(\@vector)
     return the minimum value of given values or vector, In an array
     context returns the value and the index in the array where it occurs.

maxabs(@vector), maxabs(\@vector)
     return the maximum value of absolute of the given values or vector. In
     an array context returns the value and the index in the array where it
     occurs.

minabs(@vector), minabs(\@vector)
     return the minimum value of the absolute of the given values or
     vector. In an array context returns the value and the index in the
     array where it occurs.

sum($v1,$v2,...), sum(@vector), sum(\@vector)
     return the sum of the given values or vector

average($v1,$v2,..), average(@vector), average(\@vector)
     return the average of the given values or vector

vecprod($a,$v1,$v2,..), vecprod($a,@vector), vecprod( $a, \@vector )
     return a vector built by multiplying the scalar $a by each element of
     the  @vector.

ordered($v1,$v2,..), ordered(@vector), ordered(\@vector)
     return nonzero iff the vector is nondecreasing with respect to its
     index.  To be used like

          if( ordered( $lowBound, $value, $highBound ) ){

     instead of the (slightly) more clumsy

          if( ($lowBound <= $value) && ($value <= $highBound) ) {

sumbyelement( \@array1, \@array2 ), diffbyelement(\@array1,\@array2)
     return the element-by-element sum or difference of two
     identically-sized vectors. Given

          $s = sumbyelement( [10,20,30], [1,2,3] );
          $d = diffbyelement( [10,20,30], [1,2,3] );

     $s will be `[11,22,33]', $d will be `[9,18,27]'.

allequal( \@array1, \@array2 )
     returns true if and only if the two arrays are numerically identical.

convolute( \@array1, \@array2 )
     return a reference to an array containing the element-by-element
     product of the two input arrays. I.e.,

          $r = convolute( [1,2,3], [-1,2,1] );

     returns a reference to

          [-1,4,3]

HISTORY
=======

     $Log: VecStat.pm,v $
     Revision 1.7  2000/10/24 15:28:00  spinellia@acm.org
     Added functions allequal diffbyelement
     Created a reasonable test suite.

     Revision 1.6  2000/06/29 16:06:37  spinellia@acm.org
     Added functions vecprod, convolute, sumbyelement

     Revision 1.5  1997/02/26 17:20:37  willijar
     Added line before pod header so pod2man installs man page correctly

     Revision 1.4  1996/02/20 07:53:10  willijar
     Added ability to return index in array contex to max and min
     functions. Added minabs and maxabs functions.
     Thanks to Mark Borges <mdb@cdc.noaa.gov> for these suggestions.

     Revision 1.3  1996/01/06 11:03:30  willijar
     Fixed stupid bug that crept into looping in min and max functions

     Revision 1.2  1995/12/26 09:56:38  willijar
     Oops - removed xy data functions.

     Revision 1.1  1995/12/26 09:39:07  willijar
     Initial revision

BUGS
====

   Let me know. I welcome any appropriate additions for this package.

AUTHORS
=======

   John A.R. Williams <J.A.R.Williams@aston.ac.uk> Andrea Spinelli
<spinellia@acm.org>

Perl extension for the Mcrypt cryptography library
**************************************************

NAME
====

   Mcrypt - Perl extension for the Mcrypt cryptography library

SYNOPSIS
========

     use Mcrypt;

     # Procedural routines

     $td = Mcrypt::mcrypt_load($algorithm, $algorithm_dir,
     			    $mode, $mode_dir);

     Mcrypt::mcrypt_get_key_size($td);   # in bytes
     Mcrypt::mcrypt_get_iv_size($td);    # in bytes
     Mcrypt::mcrypt_get_block_size($td); # in bytes

     Mcrypt::mcrypt_init($td, $key, $iv);

     $encryptedstr = Mcrypt::mcrypt_encrypt($td, $decryptedstr);
     $decryptedstr = Mcrypt::mcrypt_decrypt($td, $encryptedstr);

     Mcrypt::mcrypt_end($td);

     # Object-oriented methods

     $td = Mcrypt->new( algorithm => $algorithm,
     		     mode => $mode );

     $keysize = $td->{KEY_SIZE};
     $ivsize  = $td->{IV_SIZE};
     $blksize = $td->{BLOCK_SIZE};

     $td->init($key, $iv);

     $encryptedstr = $td->encrypt($decryptedstr);
     $decryptedstr = $td->decrypt($encryptedstr);

     # If the $td goes out of context,
     # the destructor will do this for you
     $td->end();

DESCRIPTION
===========

   This module wraps the libmcrypt encryption library for easy and
convenient use from within perl.  Encryption and decryption using a
variety of algorithms is as easy as a few simple lines of perl.

Exported constants
==================

   The predefined groups of exports in the use statements are as follows:

   use Mcrypt qw(:ALGORITHMS);

   Exports the BLOWFISH DES 3DES 3WAY GOST SAFER_SK64 SAFER_SK128 CAST_128
XTEA RC2 TWOFISH CAST_256 SAFERPLUS LOKI97 SERPENT RIJNDAEL_128
RIJNDAEL_192 RIJNDAEL_256 ENIGMA ARCFOUR WAKE libmcrypt algorithms.  See
the mcrypt(3) man page for more details.

   use Mcrypt qw(:MODES);

   Exports the CBC ECB CFB OFB bOFB STREAM modes of encryption.  See the
mcrypt(3) man page for more details.

   use Mcrypt qw(:FUNCS);

   Exports the following functions: mcrypt_load, mcrypt_unload,
mcrypt_init, mcrypt_end, mcrypt_encrypt, mcrypt_decrypt,
mcrypt_get_block_size, mcrypt_get_iv_size, mcrypt_get_key_size.

EXAMPLES
========

     # Procedural approach:
     # create an ecryption descriptor:
     #   ALGORITHM: blowfish (256 bit key + 16 byte IV)
     #   MODE:      cfb
     # The user application has set:
     #   $method to either "encrypt" or "decrypt"
     #   $infile to the input filename
     #   $outfile to the output filename
     my($td) = Mcrypt::mcrypt_load( Mcrypt::BLOWFISH, '',
     				 Mcrypt::CFB, '' );
     my($key) = "32 bytes of your apps secret key";  # secret key
     my($iv) = "16 bytes of rand"; # shared initialization vector
     Mcrypt::mcrypt_init($td, $key, $iv) || die "Could not initialize td";
     print Mcrypt::mcrypt_encrypt($td, $_) while(<>);
     Mcrypt::mcrypt_end($td);

     # OO approach of the above except decrypting
     my($td) = Mcrypt->new( algorithm => Mcrypt::BLOWFISH,
                            mode => Mcrypt::CFB,
                            verbose => 0 );
     my($key) = "k" x $td->{KEY_SIZE};
     my($iv) = "i" x $td->{IV_SIZE};
     $td->init($key, $iv);
     print $td->decrypt($_) while (<>);
     $td->end();

AUTHOR
======

   Theo Schlossnagle <jesus@omniti.com>

SEE ALSO
========

   The libmcrypt man page: mcrypt(3).  Other libmcrypt information is
available at http://mcrypt.hellug.gr/.

Perl interface to the MegaHAL natural language             conversation simulator.
**********************************************************************************

NAME
====

     MegaHAL - Perl interface to the MegaHAL natural language
               conversation simulator.

SYNOPSIS
========

     use MegaHAL;

     $megahal = new MegaHAL('Path'     => './',
                            'Banner'   => 0,
                            'Prompt'   => 0,
                            'Wrap'     => 0,
                            'AutoSave' => 0);

     $text = $megahal->initial_greeting();
     $text = $megahal->do_reply($message);

DESCRIPTION
===========

     Conversation simulators are computer programs which give
     the appearance of conversing with a user in natural
     language.  Such programs are effective because they
     exploit the fact that human beings tend to read much more
     meaning into what is said than is actually there; we are
     fooled into reading structure into chaos, and we
     interpret non-sequitur as valid conversation.

     This package provides a Perl interface to the MegaHAL
     conversation simulator written by Jason Hutchens.

USAGE
=====

     $megahal = new MegaHAL('Path'     => './',
                            'Banner'   => 0,
                            'Prompt'   => 0,
                            'Wrap'     => 0,
                            'AutoSave' => 0);

     Creates a new MegaHAL object.  The object constructor can
     optionaly receive the following named parameters:

     'Path'   - The path to MegaHALs brain or training file
                (megahal.brn and megahal.trn respectively).
                If 'Path' is not specified the current working
                directory is assumed.

     'Banner' - A flag which enables/disables the banner
                which is displayed when MegaHAL starts up.
                The default is to disable the banner.

     'Prompt' - A flag which enables/disables the prompt. This
                flag is only useful when MegaHAL is run
                interactively and is disabled by default.

     'Wrap'   - A flag which enables/disables word wrapping of
                MegaHALs responses when the lines exceed 80
                characters in length.  The default is to
                disable word wrapping.

     $text = $megahal->initial_greeting();

     Returns a string containing the initial greeting which is
     created by MegaHAL at startup.

     $text = $megahal->do_reply($message);

     Generates reply $text to a given message $message.

BUGS
====

     None known at this time.

AUTHORS
=======

     The Perl MegaHAL interface was written by Cory Spencer
     <cspencer@interchange.ubc.ca>

     MegaHAL was originally written by and is copyright
     Jason Hutchens <hutch@ciips.ee.uwa.edu.au>

supply memory-based FILEHANDLE methods
**************************************

NAME
====

   MemHandle - supply memory-based FILEHANDLE methods

SYNOPSIS
========

     use MemHandle;
     use IO::Seekable;

     my $mh = new MemHandle;
     print $mh "foo\n";
     $mh->print( "bar\n" );
     printf $mh "This is a number: %d\n", 10;
     $mh->printf( "a string: \"%s\"\n", "all strings come to those who wait" );

     my $len = $mh->tell();  # Use $mh->tell();
                             # tell( $mh ) will NOT work!
     $mh->seek(0, SEEK_SET); # Use $mh->seek($where, $whence)
                             # seek($mh, $where, $whence)
                             # will NOT work!

     my $memory = $mh->mem();

     Here's the real meat:

     my $mh = new MemHandle;
     my $old = select( $mh );
     .
     .
     .
     print "foo bar\n";
     print "baz\n";
     &MyPrintSub();
     select( $old );

     print "here it all is: ", $mh->mem(), "\n";

DESCRIPTION
===========

   Generates inherits from IO::Handle and IO::Seekable. It provides an
interface to the file routines which uses memory instead.  See perldoc
IO::Handle, and perldoc IO::Seekable as well as Perlfunc (perl.info),
for more detailed descriptions of the provided
built-in functions:

     print
     printf
     readline
     sysread
     syswrite
     getc
     gets

   The following functions are provided, but tie doesn't allow them to be
tied to the built in functions.  They should be used by calling the
appropriate method on the MemHandle object.

     seek
     tell

   call them like this:

     my $mh = new MemHandle();
     .
     .
     .
     my $pos = $mh->tell();
     $mh->seek( 0, SEEK_SET );

CONSTRUCTOR
===========

new( [mem] )
     Creates a `MemHandle', which is a reference to a newly created symbol
     (see the Symbol package).  It then ties the FILEHANDLE to
     `MemHandle::Tie' (see `"Tying FileHandles"', see Perltie (perl.info)).
     Tied methods in `MemHandle::Tie' translate
     file operations into reads/writes into a string, which can be
     accessed by calling `MemHandle::mem'.

METHODS
=======

seek( POS, WHENCE )
     Sets the read/write position to WHENCE + POS.  WHENCE is one of the
     constants which are available from IO::Seekable or POSIX:

          SEEK_SET # absolute position from the beginning.
          SEEK_CUR # offset from the current location.
          SEEK_END # from the end (POS can be negative).

tell()
     Returns the current position of the mem-file, similiar to the way tell
     would.  (See Perlfunc (perl.info)).

mem( [mem] )
     gets or sets the memory.  If called with a parameter, it copies it to
     the memory and sets the position to be immediately after (so if you
     write more to it, you append the string).  Returns the current value
     of memory.

AUTHOR
======

   "Sheridan C. Rawlins" <scr14@cornell.edu>

SEE ALSO
========

   See Perl (perl.info).  See Perlfunc (perl.info).
`"Tying FileHandles"', see Perltie (perl.info).  perldoc
IO::Handle.  perldoc IO::Seekable.  perldoc Symbol.

The package which ties the MemHandle to memory.
***********************************************

NAME
====

   MemHandle::Tie - The package which ties the MemHandle to memory.

SYNOPSIS
========

DESCRIPTION
===========

   This should not be used except by MemHandle.  It provides functions for
tie-ing a FILEHANDLE.  See `"Tying FileHandles"', see Perltie (perl.info),
for more detail.

AUTHOR
======

   "Sheridan C. Rawlins" <scr14@cornell.edu>

SEE ALSO
========

   See Perl (perl.info).  See Perlfunc (perl.info).
`"Tying FileHandles"', see Perltie (perl.info).  perldoc
MemHandle.

Make your functions faster by trading space for time
****************************************************

NAME
====

   Memoize - Make your functions faster by trading space for time

SYNOPSIS
========

     use Memoize;
     memoize('slow_function');
     slow_function(arguments);    # Is faster than it was before

   This is normally all you need to know.  However, many options are
available:

     memoize(function, options...);

   Options include:

     NORMALIZER => function
     INSTALL => new_name

     SCALAR_CACHE => 'MEMORY'
     SCALAR_CACHE => ['TIE', Module, arguments...]
             SCALAR_CACHE => ['HASH', \%cache_hash ]
     SCALAR_CACHE => 'FAULT'
     SCALAR_CACHE => 'MERGE'

     LIST_CACHE => 'MEMORY'
     LIST_CACHE => ['TIE', Module, arguments...]
             LIST_CACHE => ['HASH', \%cache_hash ]
     LIST_CACHE => 'FAULT'
     LIST_CACHE => 'MERGE'

DESCRIPTION
===========

   `Memoizing' a function makes it faster by trading space for time.  It
does this by caching the return values of the function in a table.  If you
call the function again with the same arguments, `memoize' jmups in and
gives you the value out of the table, instead of letting the function
compute the value all over again.

   Here is an extreme example.  Consider the Fibonacci sequence, defined
by the following function:

     # Compute Fibonacci numbers
     sub fib {
       my $n = shift;
       return $n if $n < 2;
       fib($n-1) + fib($n-2);
     }

   This function is very slow.  Why?  To compute fib(14), it first wants
to compute fib(13) and fib(12), and add the results.  But to compute
fib(13), it first has to compute fib(12) and fib(11), and then it comes
back and computes fib(12) all over again even though the answer is the
same.  And both of the times that it wants to compute fib(12), it has to
compute fib(11) from scratch, and then it has to do it again each time it
wants to compute fib(13).  This function does so much recomputing of old
results that it takes a really long time to run--fib(14) makes 1,200 extra
recursive calls to itself, to compute and recompute things that it already
computed.

   This function is a good candidate for memoization.  If you memoize the
`fib' function above, it will compute fib(14) exactly once, the first time
it needs to, and then save the result in a table.  Then if you ask for
fib(14) again, it gives you the result out of the table.  While computing
fib(14), instead of computing fib(12) twice, it does it once; the second
time it needs the value it gets it from the table.  It doesn't compute
fib(11) four times; it computes it once, getting it from the table the
next three times.  Instead of making 1,200 recursive calls to `fib', it
makes 15.  This makes the function about 150 times faster.

   You could do the memoization yourself, by rewriting the function, like
this:

     # Compute Fibonacci numbers, memoized version
     { my @fib;
       	  sub fib {
         my $n = shift;
         return $fib[$n] if defined $fib[$n];
         return $fib[$n] = $n if $n < 2;
         $fib[$n] = fib($n-1) + fib($n-2);
       }
             }

   Or you could use this module, like this:

     use Memoize;
     memoize('fib');

     # Rest of the fib function just like the original version.

   This makes it easy to turn memoizing on and off.

   Here's an even simpler example: I wrote a simple ray tracer; the
program would look in a certain direction, figure out what it was looking
at, and then convert the `color' value (typically a string like `red') of
that object to a red, green, and blue pixel value, like this:

     for ($direction = 0; $direction < 300; $direction++) {
       # Figure out which object is in direction $direction
       $color = $object->{color};
       ($r, $g, $b) = @{&ColorToRGB($color)};
       ...
     }

   Since there are relatively few objects in a picture, there are only a
few colors, which get looked up over and over again.  Memoizing
`ColorToRGB' speeded up the program by several percent.

DETAILS
=======

   This module exports exactly one function, `memoize'.  The rest of the
functions in this package are None of Your Business.

   You should say

     memoize(function)

   where function is the name of the function you want to memoize, or a
reference to it.  `memoize' returns a reference to the new, memoized
version of the function, or undef on a non-fatal error.  At present, there
are no non-fatal errors, but there might be some in the future.

   If function was the name of a function, then `memoize' hides the old
version and installs the new memoized version under the old name, so that
`&function(...)' actually invokes the memoized version.

OPTIONS
=======

   There are some optional options you can pass to `memoize' to change the
way it behaves a little.  To supply options, invoke `memoize' like this:

     memoize(function, NORMALIZER => function,
     		  INSTALL => newname,
                               SCALAR_CACHE => option,
                       LIST_CACHE => option
     		 );

   Each of these options is optional; you can include some, all, or none
of them.

INSTALL
-------

   If you supply a function name with INSTALL, memoize will install the
new, memoized version of the function under the name you give.  For
example,

     memoize('fib', INSTALL => 'fastfib')

   installs the memoized version of `fib' as `fastfib'; without the
INSTALL option it would have replaced the old `fib' with the memoized
version.

   To prevent `memoize' from installing the memoized version anywhere, use
`INSTALL => undef'.

NORMALIZER
----------

   Suppose your function looks like this:

     # Typical call: f('aha!', A => 11, B => 12);
     sub f {
       my $a = shift;
       my %hash = @_;
       $hash{B} ||= 2;  # B defaults to 2
       $hash{C} ||= 7;  # C defaults to 7

     # Do something with $a, %hash
     	}

   Now, the following calls to your function are all completely equivalent:

     f(OUCH);
     f(OUCH, B => 2);
     f(OUCH, C => 7);
     f(OUCH, B => 2, C => 7);
     f(OUCH, C => 7, B => 2);
     (etc.)

   However, unless you tell `Memoize' that these calls are equivalent, it
will not know that, and it will compute the values for these invocations
of your function separately, and store them separately.

   To prevent this, supply a NORMALIZER function that turns the program
arguments into a string in a way that equivalent arguments turn into the
same string.  A NORMALIZER function for f above might look like this:

     sub normalize_f {
       my $a = shift;
       my %hash = @_;
       $hash{B} ||= 2;
       $hash{C} ||= 7;

     join($;, $a, map ($_ => $hash{$_}) sort keys %hash);
     	}

   Each of the argument lists above comes out of the `normalize_f'
function looking exactly the same, like this:

     OUCH^\B^\2^\C^\7

   You would tell `Memoize' to use this normalizer this way:

     memoize('f', NORMALIZER => 'normalize_f');

   `memoize' knows that if the normalized version of the arguments is the
same for two argument lists, then it can safely look up the value that it
computed for one argument list and return it as the result of calling the
function with the other argument list, even if the argument lists look
different.

   The default normalizer just concatenates the arguments with $; in
between.  This always works correctly for functions with only one
argument, and also when the arguments never contain $; (which is normally
character #28, control-\.  )  However, it can confuse certain argument
lists:

     normalizer("a\034", "b")
     normalizer("a", "\034b")
     normalizer("a\034\034b")

   for example.

   The default normalizer also won't work when the function's arguments
are references.  For exampple, consider a function g which gets two
arguments: A number, and a reference to an array of numbers:

     g(13, [1,2,3,4,5,6,7]);

   The default normalizer will turn this into something like
`"13\024ARRAY(0x436c1f)"'.  That would be all right, except that a
subsequent array of numbers might be stored at a different location even
though it contains the same data.  If this happens, `Memoize' will think
that the arguments are different, even though they are equivalent.  In
this case, a normalizer like this is appropriate:

     sub normalize { join ' ', $_[0], @{$_[1]} }

   For the example above, this produces the key "13 1 2 3 4 5 6 7".

   Another use for normalizers is when the function depends on data other
than those in its arguments.  Suppose you have a function which returns a
value which depends on the current hour of the day:

     sub on_duty {
               my ($problem_type) = @_;
       my $hour = (localtime)[2];
               open my $fh, "$DIR/$problem_type" or die...;
               my $line;
               while ($hour-- > 0)
                 $line = <$fh>;
               }
       return $line;
     }

   At 10:23, this function generates the tenth line of a data file; at
3:45 PM it generates the 15th line instead.  By default, `Memoize' will
only see the $problem_type argument.  To fix this, include the current
hour in the normalizer:

     sub normalize { join ' ', (localtime)[2], @_ }

   The calling context of the function (scalar or list context) is
propagated to the normalizer.  This means that if the memoized function
will treat its arguments differently in list context than it would in
scalar context, you can have the normalizer function select its behavior
based on the results of wantarray.  Even if called in a list context, a
normalizer should still return a single string.

`SCALAR_CACHE', `LIST_CACHE'
----------------------------

   Normally, `Memoize' caches your function's return values into an
ordinary Perl hash variable.  However, you might like to have the values
cached on the disk, so that they persist from one run of your program to
the next, or you might like to associate some other interesting semantics
with the cached values.

   There's a slight complication under the hood of `Memoize': There are
actually *two* caches, one for scalar values and one for list values.
When your function is called in scalar context, its return value is cached
in one hash, and when your function is called in list context, its value
is cached in the other hash.  You can control the caching behavior of both
contexts independently with these options.

   The argument to `LIST_CACHE' or `SCALAR_CACHE' must either be one of
the following five strings:

     MEMORY
     TIE
     FAULT
     MERGE
             HASH

   or else it must be a reference to a list whose first element is one of
these four strings, such as `[TIE, arguments...]'.

MEMORY
     MEMORY means that return values from the function will be cached in
     an ordinary Perl hash variable.  The hash variable will not persist
     after the program exits.  This is the default.

TIE
     TIE means that the function's return values will be cached in a tied
     hash.  A tied hash can have any semantics at all.  It is typically
     tied to an on-disk database, so that cached values are stored in the
     database and retrieved from it again when needed, and the disk file
     typically persists after your pogram has exited.

     If TIE is specified as the first element of a list, the remaining
     list elements are taken as arguments to the tie call that sets up the
     tied hash.  For example,

          SCALAR_CACHE => [TIE, DB_File, $filename, O_RDWR | O_CREAT, 0666]

     says to tie the hash into the DB_File package, and to pass the
     $filename, `O_RDWR | O_CREAT', and `0666' arguments to the tie call.
     This has the effect of storing the cache in a DB_File database whose
     name is in $filename.

     Other typical uses of TIE:

          LIST_CACHE => [TIE, GDBM_File, $filename, O_RDWR | O_CREAT, 0666]
          SCALAR_CACHE => [TIE, MLDBM, DB_File, $filename, O_RDWR|O_CREAT, 0666]
          LIST_CACHE => [TIE, My_Package, $tablename, $key_field, $val_field]

     This last might tie the cache hash to a package that you wrote
     yourself that stores the cache in a SQL-accessible database.  A
     useful use of this feature: You can construct a batch program that
     runs in the background and populates the memo table, and then when you
     come to run your real program the memoized function will be
     screamingly fast because all its results have been precomputed.

HASH
     HASH allows you to specify that a particular hash that you supply
     will be used as the cache.  You can tie this hash beforehand to give
     it any behavior you want.

`FAULT'
     `FAULT' means that you never expect to call the function in scalar
     (or list) context, and that if `Memoize' detects such a call, it
     should abort the program.  The error message is one of

          `foo' function called in forbidden list context at line ...
          `foo' function called in forbidden scalar context at line ...

`MERGE'
     `MERGE' normally means the function does not distinguish between list
     and sclar context, and that return values in both contexts should be
     stored together.  `LIST_CACHE => MERGE' means that list context
     return values should be stored in the same hash that is used for
     scalar context returns, and `SCALAR_CACHE => MERGE' means the same,
     mutatis mutandis.  It is an error to specify `MERGE' for both, but it
     probably does something useful.

     Consider this function:

          sub pi { 3; }

     Normally, the following code will result in two calls to pi:

          $x = pi();
          ($y) = pi();
          $z = pi();

     The first call caches the value 3 in the scalar cache; the second
     caches the list (3) in the list cache.  The third call doesn't call
     the real pi function; it gets the value from the scalar cache.

     Obviously, the second call to pi is a waste of time, and storing its
     return value is a waste of space.  Specifying `LIST_CACHE => MERGE'
     will make `memoize' use the same cache for scalar and list context
     return values, so that the second call uses the scalar cache that was
     populated by the first call.  pi ends up being cvalled only once, and
     both subsequent calls return 3 from the cache, regardless of the
     calling context.

     Another use for `MERGE' is when you want both kinds of return values
     stored in the same disk file; this saves you from having to deal with
     two disk files instead of one.  You can use a normalizer function to
     keep the two sets of return values separate.  For example:

          memoize 'myfunc',
            NORMALIZER => 'n',
            SCALAR_CACHE => [TIE, MLDBM, DB_File, $filename, ...],
            LIST_CACHE => MERGE,
          ;

          sub n {
            my $context = wantarray() ? 'L' : 'S';
            # ... now compute the hash key from the arguments ...
            $hashkey = "$context:$hashkey";
          }

     This normalizer function will store scalar context return values in
     the disk file under keys that begin with `S:', and list context
     return values under keys that begin with `L:'.

OTHER FACILITIES
================

`unmemoize'
-----------

   There's an `unmemoize' function that you can import if you want to.
Why would you want to?  Here's an example: Suppose you have your cache
tied to a DBM file, and you want to make sure that the cache is written
out to disk if someone interrupts the program.  If the program exits
normally, this will happen anyway, but if someone types control-C or
something then the program will terminate immediately without
synchronizing the database.  So what you can do instead is

     $SIG{INT} = sub { unmemoize 'function' };

   Thanks to Jonathan Roy for discovering a use for `unmemoize'.

   `unmemoize' accepts a reference to, or the name of a previously
memoized function, and undoes whatever it did to provide the memoized
version in the first place, including making the name refer to the
unmemoized version if appropriate.  It returns a reference to the
unmemoized version of the function.

   If you ask it to unmemoize a function that was never memoized, it
croaks.

flush_cache
-----------

   `flush_cache(function)' will flush out the caches, discarding all the
cached data.  The argument may be a funciton name or a reference to a
function.  For finer control over when data is discarded or expired, see
the documentation for `Memoize::Expire', included in this package.

   Note that if the cache is a tied hash, flush_cache will attempt to
invoke the CLEAR method on the hash.  If there is no CLEAR method, this
will cause a run-time error.

   An alternative approach to cache flushing is to use the HASH option
(see above) to request that `Memoize' use a particular hash variable as
its cache.  Then you can examine or modify the hash at any time in any way
you desire.

CAVEATS
=======

   Memoization is not a cure-all:

   * Do not memoize a function whose behavior depends on program state
     other than its own arguments, such as global variables, the time of
     day, or file input.  These functions will not produce correct results
     when memoized.  For a particularly easy example:

          sub f {
            time;
          }

     This function takes no arguments, and as far as `Memoize' is
     concerned, it always returns the same result.  `Memoize' is wrong, of
     course, and the memoized version of this function will call time once
     to get the current time, and it will return that same time every time
     you call it after that.

   * Do not memoize a function with side effects.

          sub f {
            my ($a, $b) = @_;
                    my $s = $a + $b;
            print "$a + $b = $s.\n";
          }

     This function accepts two arguments, adds them, and prints their sum.
     Its return value is the numuber of characters it printed, but you
     probably didn't care about that.  But `Memoize' doesn't understand
     that.  If you memoize this function, you will get the result you
     expect the first time you ask it to print the sum of 2 and 3, but
     subsequent calls will return 1 (the return value of print) without
     actually printing anything.

   * Do not memoize a function that returns a data structure that is
     modified by its caller.

     Consider these functions:  `getusers' returns a list of users somehow,
     and then main throws away the first user on the list and prints the
     rest:

          sub main {
            my $userlist = getusers();
            shift @$userlist;
            foreach $u (@$userlist) {
              print "User $u\n";
            }
          }

          sub getusers {
            my @users;
            # Do something to get a list of users;
            \@users;  # Return reference to list.
          }

     If you memoize `getusers' here, it will work right exactly once.  The
     reference to the users list will be stored in the memo table.  main
     will discard the first element from the referenced list.  The next
     time you invoke main, `Memoize' will not call `getusers'; it will
     just return the same reference to the same list it got last time.  But
     this time the list has already had its head removed; main will
     erroneously remove another element from it.  The list will get shorter
     and shorter every time you call main.

     Similarly, this:

          $u1 = getusers();
          $u2 = getusers();
          pop @$u1;

     will modify $u2 as well as $u1, because both variables are references
     to the same array.  Had `getusers' not been memoized, $u1 and $u2
     would have referred to different arrays.

PERSISTENT CACHE SUPPORT
========================

   You can tie the cache tables to any sort of tied hash that you want to,
as long as it supports TIEHASH, FETCH, STORE, and EXISTS.  For example,

     memoize 'function', SCALAR_CACHE =>
                                 [TIE, GDBM_File, $filename, O_RDWR|O_CREAT, 0666];

   works just fine.  For some storage methods, you need a little glue.

   SDBM_File doesn't supply an EXISTS method, so included in this package
is a glue module called `Memoize::SDBM_File' which does provide one.  Use
this instead of plain SDBM_File to store your cache table on disk in an
SDBM_File database:

     memoize 'function',
                     SCALAR_CACHE =>
                     [TIE, Memoize::SDBM_File, $filename, O_RDWR|O_CREAT, 0666];

   `NDBM_File' has the same problem and the same solution.

   Storable isn't a tied hash class at all.  You can use it to store a
hash to disk and retrieve it again, but you can't modify the hash while
it's on the disk.  So if you want to store your cache table in a Storable
database, use `Memoize::Storable', which puts a hashlike front-end onto
Storable.  The hash table is actually kept in memory, and is loaded from
your Storable file at the time you memoize the function, and stored back
at the time you unmemoize the function (or when your program exits):

     memoize 'function',
                     SCALAR_CACHE => [TIE, Memoize::Storable, $filename];

     memoize 'function',
                     SCALAR_CACHE => [TIE, Memoize::Storable, $filename, 'nstore'];

   Include the `nstore' option to have the Storable database written in
`network order'.  (See Storable, for more details about
this.)

EXPIRATION SUPPORT
==================

   See Memoize::Expire, which is a plug-in module that adds expiration
functionality to Memoize.  If you don't like the kinds of policies that
Memoize::Expire implements, it is easy to write your own plug-in module to
implement whatever policy you desire.

BUGS
====

   The test suite is much better, but always needs improvement.

   There used to be some problem with the way `goto &f' works under
threaded Perl, because of the lexical scoping of `@_'.  This is a bug in
Perl, and until it is resolved, Memoize won't work with these Perls.  This
is probably still the case, although I have not been able to try it out.
If you encounter this problem, you can fix it by chopping the source code
a little.  Find the comment in the source code that says `--- THREADED
PERL COMMENT---' and comment out the active line and uncomment the
commented one.  Then try it again.

   Here's a bug that isn't my fault: Some versions of DB_File won't let
you store data under a key of length 0.  That means that if you have a
function f which you memoized and the cache is in a DB_File database, then
the value of `f()' (f called with no arguments) will not be memoized.  Let
us all breathe deeply and repeat this mantra: "Gosh, Keith, that sure was
a stupid thing to do."

MAILING LIST
============

   To join a very low-traffic mailing list for announcements about
`Memoize', send an empty note to `mjd-perl-memoize-request@plover.com'.

AUTHOR
======

   Mark-Jason Dominus (`mjd-perl-memoize+@plover.com'), Plover Systems co.

   See the `Memoize.pm' Page at http://www.plover.com/~mjd/perl/Memoize/
for news and upgrades.  Near this page, at
http://www.plover.com/~mjd/perl/MiniMemoize/ there is an article about
memoization and about the internals of Memoize that appeared in The Perl
Journal, issue #13.  (This article is also included in the Memoize
distribution as `article.html'.)

   To join a mailing list for announcements about `Memoize', send an empty
message to `mjd-perl-memoize-request@plover.com'.  This mailing list is
for announcements only and has extremely low traffic--about four messages
per year.

THANK YOU
=========

   Many thanks to Jonathan Roy for bug reports and suggestions, to Michael
Schwern for other bug reports and patches, to Mike Cariaso for helping me
to figure out the Right Thing to Do About Expiration, to Joshua Gerth,
Joshua Chamas, Jonathan Roy, Mark D. Anderson, and Andrew Johnson for more
suggestions about expiration, to Ariel Scolnikov for delightful messages
about the Fibonacci function, to Dion Almaer for thought-provoking
suggestions about the default normalizer, to Walt Mankowski and Kurt
Starsinic for much help investigating problems under threaded Perl, to
Alex Dudkevich for reporting the bug in prototyped functions and for
checking my patch, to Tony Bass for many helpful suggestions, to Philippe
Verdret for enlightening discussion of Hook::PrePostCall, to Nat
Torkington for advice I ignored, to Chris Nandor for portability advice,
to Randal Schwartz for suggesting the 'flush_cache function, and to Jenda
Krynicky for being a light in the world.

Plug-in module for automatic expiration of memoized values
**********************************************************

NAME
====

   Memoize::Expire - Plug-in module for automatic expiration of memoized
values

SYNOPSIS
========

     use Memoize;
     memoize 'function',
       SCALAR_CACHE => [TIE, Memoize::Expire,
     	  	     LIFETIME => $lifetime,    # In seconds
     		     NUM_USES => $n_uses,
                        TIE      => [Module, args...],
     		    ],

DESCRIPTION
===========

   Memoize::Expire is a plug-in module for Memoize.  It allows the cached
values for memoized functions to expire automatically.  This manual
assumes you are already familiar with the Memoize module.  If not, you
should study that manual carefully first, paying particular attention to
the TIE feature.

   Memoize::Expire is a layer of software that you can insert in between
Memoize itself and whatever underlying package implements the cache.  (By
default, plain hash variables implement the cache.)  The layer expires
cached values whenever they get too old, have been used too often, or both.

   To specify a real-time timeout, supply the LIFETIME option with a
numeric value.  Cached data will expire after this many seconds, and will
be looked up afresh when it expires.  When a data item is looked up
afresh, its lifetime is reset.

   If you specify NUM_USES with an argument of n, then each cached data
item will be discarded and looked up afresh after the nth time you access
it.  When a data item is looked up afresh, its number of uses is reset.

   If you specify both arguments, data will be discarded from the cache
when either expiration condition holds.

   If you want the cache to persist between invocations of your program,
supply a TIE option to specify the package name and arguments for a the
tied hash that will implement the persistence.  For example:

     use Memoize;
     use DB_File;
     memoize 'function',
       SCALAR_CACHE => [TIE, Memoize::Expire,
     	  	     LIFETIME => $lifetime,    # In seconds
     		     NUM_USES => $n_uses,
                        TIE      => [DB_File, $filename, O_CREAT|O_RDWR, 0666],
     		    ], ...;

INTERFACE
=========

   There is nothing special about Memoize::Expire.  It is just an example.
If you don't like the policy that it implements, you are free to write
your own expiration policy module that implements whatever policy you
desire.  Here is how to do that.  Let us suppose that your module will be
named MyExpirePolicy.

   Short summary: You need to create a package that defines four methods:

TIEHASH
     Construct and return cache object.

EXISTS
     Given a function argument, is the corresponding function value in the
     cache, and if so, is it fresh enough to use?

FETCH
     Given a function argument, look up the corresponding function value in
     the cache and return it.

STORE
     Given a function argument and the corresponding function value, store
     them into the cache.

   The user who wants the memoization cache to be expired according to
your policy will say so by writing

     memoize 'function',
       SCALAR_CACHE => [TIE, MyExpirePolicy, args...];

   This will invoke MyExpirePolicy->TIEHASH(args).
MyExpirePolicy::TIEHASH should do whatever is appropriate to set up the
cache, and it should return the cache object to the caller.

   For example, MyExpirePolicy::TIEHASH might create an object that
contains a regular Perl hash (which it will to store the cached values)
and some extra information about the arguments and how old the data is and
things like that.  Let us call this object `C'.

   When Memoize needs to check to see if an entry is in the cache already,
it will invoke C->EXISTS(key).  key is the normalized function argument.
MyExpirePolicy::EXISTS should return 0 if the key is not in the cache, or
if it has expired, and 1 if an unexpired value is in the cache.  It should
not return undef, because there is a bug in some versions of Perl that
will cause a spurious FETCH if the EXISTS method returns undef.

   If your EXISTS function returns true, Memoize will try to fetch the
cached value by invoking C->FETCH(key).  MyExpirePolicy::FETCH should
return the cached value.  Otherwise, Memoize will call the memoized
function to compute the appropriate value, and will store it into the
cache by calling C->STORE(key, value).

   Here is a very brief example of a policy module that expires each cache
item after ten seconds.

     package Memoize::TenSecondExpire;

     sub TIEHASH {
       my ($package) = @_;
       my %cache;
       bless \%cache => $package;
     }

     sub EXISTS {
       my ($cache, $key) = @_;
       if (exists $cache->{$key} &&
                   $cache->{$key}{EXPIRE_TIME} > time) {
         return 1
       } else {
         return 0;  # Do NOT return `undef' here.
       }
     }

     sub FETCH {
       my ($cache, $key) = @_;
       return $cache->{$key}{VALUE};
     }

     sub STORE {
       my ($cache, $key, $newvalue) = @_;
       $cache->{$key}{VALUE} = $newvalue;
       $cache->{$key}{EXPIRE_TIME} = time + 10;
     }

   To use this expiration policy, the user would say

     use Memoize;
     memoize 'function',
         SCALAR_CACHE => [TIE, Memoize::TenSecondExpire];

   Memoize would then call function whenever a cached value was entirely
absent or was older than ten seconds.

   It's nice if you allow a TIE argument to TIEHASH that ties the
underlying cache so that the user can specify that the cache is persistent
or that it has some other interesting semantics.  The sample
`Memoize::Expire' module demonstrates how to do this.  It implements a
policy that expires cache items when they get too old or when they have
been accessed too many times.

   Another sample module, `Memoize::Saves', is included with this package.
It implements a policy that allows you to specify that certain function
values whould always be looked up afresh.  See the documentation for
details.

ALTERNATIVES
============

   Joshua Chamas's Tie::Cache module may be useful as an expiration
manager.  (If you try this, let me know how it works out.)

   If you develop any useful expiration managers that you think should be
distributed with Memoize, please let me know.

CAVEATS
=======

   This module is experimental, and may contain bugs.  Please report bugs
to the address below.

   Number-of-uses is stored as a 16-bit unsigned integer, so can't exceed
65535.

   Because of clock granularity, expiration times may occur up to one
second sooner than you expect.  For example, suppose you store a value
with a lifetime of ten seconds, and you store it at 12:00:00.998 on a
certain day.  Memoize will look at the clock and see 12:00:00.  Then 9.01
seconds later, at 12:00:10.008 you try to read it back.  Memoize will look
at the clock and see 12:00:10 and conclude that the value has expired.
Solution: Build an expiration policy module that uses Time::HiRes to
examine a clock with better granularity.  Contributions are welcome.  Send
them to:

AUTHOR
======

   Mark-Jason Dominus (mjd-perl-memoize+@plover.com)

   Mike Cariaso provided valuable insight into the best way to solve this
problem.

SEE ALSO
========

   perl(1)

   The Memoize man page.

   http://www.plover.com/~mjd/perl/Memoize/  (for news and updates)

   I maintain a mailing list on which I occasionally announce new versions
of Memoize.  The list is for announcements only, not discussion.  To join,
send an empty message to mjd-perl-memoize-request@Plover.com.

Expiry plug-in for Memoize that adds LRU cache expiration
*********************************************************

NAME
====

   Memoize - Expiry plug-in for Memoize that adds LRU cache expiration

SYNOPSIS
========

     use Memoize;

     memoize('slow_function',
     	    TIE => [Memoize::ExpireLRU,
     		    CACHESIZE => n,
     	           ]);

   Note that one need not use this module. It will be found by the Memoize
module.

   The argument to CACHESIZE must be an integer. Normally, this is all
that is needed. Additional options are available:

     TUNECACHESIZE => m,
     INSTANCE => 'descriptive_name',
     TIE => '[DB_File, $filename, O_RDWR | O_CREATE, 0666]'

DESCRIPTION
===========

   For the theory of Memoization, please see the Memoize module
documentation. This module implements an expiry policy for Memoize that
follows LRU semantics, that is, the last n results, where n is specified
as the argument to the CACHESIZE parameter, will be cached.

PERFORMANCE TUNING
==================

   It is often quite difficult to determine what size cache will give
optimal results for a given function. To aid in determining this,
ExpireLRU includes cache tuning support. Enabling this causes a definite
performance hit, but it is often useful before code is released to
production.

   To enable cache tuning support, simply specify the optional
`TUNECACHESIZE' parameter with a size greater than that of the CACHESIZE
parameter.

   When the program exits, a set of statistics will be printed to stderr.
If multiple routines have been memoized, separate sets of statistics are
printed for each routine. The default names are somewhat cryptic: this is
the purpose of the INSTANCE parameter. The value of this parameter will be
used as the identifier within the statistics report.

DIAGNOSTIC METHODS
==================

   Two additional routines are available but not exported.
Memoize::ExpireLRU::ShowStats returns a string identical to the statistics
report printed to STDERR at the end of the program if test caches have
been enabled; Memoize::ExpireLRU::DumpCache takes the instance name of a
memoized function as a parameter, and returns a string describing the
current state of that instance.

AUTHOR
======

   Brent B. Powers (B2Pi), Powers@B2Pi.com

   Copyright(c) 1999 Brent B. Powers. All rights reserved. This program is
free software, you may redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   Memoize

Plug-in module to specify which return values should be memoized
****************************************************************

NAME
====

   Memoize::Saves - Plug-in module to specify which return values should
be memoized

SYNOPSIS
========

     use Memoize;

     memoize 'function',
       SCALAR_CACHE => [TIE, Memoize::Saves,
                        CACHE => [ "word1", "word2" ],
     		       DUMP  => [ "word3", "word4" ],
     		       REGEX => "Regular Expression",
     		       TIE      => [Module, args...],
     		      ],

DESCRIPTION
===========

   Memoize::Saves is a plug-in module for Memoize.  It allows the user to
specify which values should be cached or which should be dumped.  Please
read the manual for Memoize for background information.

   Use the CACHE option to specify a list of return values which should be
memoized.  All other values will need to be recomputed each time.

   Use the DUMP option to specify a list of return values which should not
be memoized.  Only these values will need to be recomputed each time.

   Use the REGEX option to specify a Regular Expression which must match
for the return value to be saved.  You can supply either a plain text
string or a compiled regular expression using qr//.  Obviously the second
method is prefered.

   Specifying multiple options will result in the least common denominator
being saved.

   You can use the TIE option to string multiple Memoize Plug-ins together:

   memoize ('printme',           SCALAR_CACHE =>              [TIE,
Memoize::Saves,               REGEX => qr/my/,               TIE   =>
[Memoize::Expire,                         LIFETIME => 5,
     TIE => [ GDBM_File, $filename,
O_RDWR | O_CREAT, 0666]                        ]              ]          );

CAVEATS
=======

   This module is experimental, and may contain bugs.  Please report bugs
to the address below.

   If you are going to use Memoize::Saves with Memoize::Expire it is
import to use it in that order.  Memoize::Expire changes the return value
to include expire information and it may no longer match your CACHE, DUMP,
or REGEX.

AUTHOR
======

   Joshua Gerth <gerth@teleport.com>

SEE ALSO
========

   perl(1)

   The Memoize man page.

base class for metadata
***********************

NAME
====

   Metadata::Base - base class for metadata

SYNOPSIS
========

     package Metadata::FOO

     use vars(@ISA);
     ...
     @ISA=qw(Metadata::Base);
     ...

DESCRIPTION
===========

   Metadata:Base class - the core functionality for handling metadata.

CONSTRUCTOR
===========

new [OPTIONS]
     Create a new Metadata object with an optional hash of options to
     describe the metadata characteristics.  Currently only the following
     can be set:

    DEBUG
          Set if debugging should be enabled from creation.  This can also
          be set and read by the debug method below.  If this is not
          defined, it is set to the current class debugging state which
          can be read from the class method `debug' in this node described
          below.

    ORDERED
          Set if the metadata elements are ordered

COPY CONSTRUCTOR
================

clone
     Create a new identical Metadata object from this one.

CLASS METHODS
=============

debug [VALUE]
     If VALUE is given, sets the debugging state of this class and returns
     the old state.  Otherwise returns the current debugging state.

seconds_to_iso8601 SECONDS
     Convert the *SECONDS* value to (subset of) ISO-8601 format
     YYYY-MM-DDThh:mm:SSZ representing the GMT/UTC value.

iso8601_to_seconds VALUE
     Convert 6 ISO-8601 subset formats to a seconds value.  The 6 formats
     are those proposed for the Dublin Core date use:

          YYYY
          YYYY-MM
          YYYY-MM-DD
          YYYY-MM-DDThh:mm
          YYYY-MM-DDThh:mm:ssTZ
          YYYY-MM-DDThh:mm:ss.ssTZ

     where TZ can be 'Z', +hh:mm or -hh:mm

     NOTE: This method rounds towards the start of the period (it should
     really return two values for start and end).

METHODS
=======

debug [VALUE]
     If VALUE is given, sets the debugging state of this object and
     returns the old state.  Otherwise returns the current debugging
     state.  The default debugging state is determined by the class debug
     state.

set ELEMENT, VALUE, [INDEX]
     Set element *ELEMENT* to VALUE.  If VALUE is an array reference, the
     existing array is used to as all the existing sub-values.  Otherwise
     if INDEX is given, sets the particular sub-value of *ELEMENT*,
     otherwise appends to the end of the existing list of sub-values for
     *ELEMENT*.

get ELEMENT, [INDEX]
     Return the contents of the given *ELEMENT*.  In an array context
     returns the sub-values as an array, in a scalar context they are all
     returned separated by spaces. If INDEX is given, returns the value of
     the given sub-value.

delete ELEMENT, [INDEX}
     Delete the given *ELEMENT*.  If an INDEX is given, remove just that
     sub-value.

exists ELEMENT, [INDEX]
     Returns a defined value if the given *ELEMENT* and/or sub-value INDEX
     exists.

size [ELEMENT]
     Returns number of elements with no argument or the number of subvalues
     for the given *ELEMENT* or undef if *ELEMENT* does not exist.

elements
     Return a list of the elements (in the correct order if there is one).

order [ORDER]
     If *ORDER* is given, sets that as the order of the elements and
     returns the old order list.  Otherwise, returns the current order of
     the elements.  If the elements are not ordered, returns undef.

validate ELEMENT, VALUE, [INDEX]
     This method is intended to be overriden by subclasses.  It is called
     when a element value is being set.  The method should return either a
     list of *ELEMENT*, VALUE and INDEX values to use or an undefined value
     in which case no element will be set.

validate_elements ELEMENT, [INDEX]
     This method is intended to be overriden by subclasses.  It is called
     when a element and/or index is being read.  The method should return
     a list of *ELEMENT* and INDEX values to use.

as_string =item format
     Returns a string representing the metadata, suitable for storing (in
     a text file).  This is different from the pack method because this
     value is meant to be the native encoding format of the metadata,
     usually human readable, wheras pack uses the minimum space.

pack
     Return a packed string representing the metadata format.  This can be
     used with unpack to restore the values.

unpack VALUE
     Initialise the metadata from the packed VALUE which must be the value
     made by the pack method.

read HANDLE
     Reads from the given file handle and initialises the metadata
     elements.  Returns undef if end of file is seen.

write HANDLE
     Write to the given file handle a formatted version of this metadata
     format.  Likely to use format in most implementations.

reset
     Reset the metadata object to the default ones (including any passed
     with the constructor) and then do a clear.

clear
     Remove any stored elements in this metadata object.  This can be used
     in conjuction with read to prevent the overhead of many new
     operations when reading metadata objects from files.

get_date_as_seconds ELEMENT
     Assuming *ELEMENT* is stored in a date format, returns the number of
     seconds since 1st January 1970.

set_date_as_seconds ELEMENT, VALUE
     Set *ELEMENT* encoded as a date corresponding to VALUE which is the
     number of seconds since 1st January 1970.

AUTHOR
======

   By Dave Beckett - http://purl.org/net/dajobe/

COPYRIGHT
=========

   Copyright (C) 1997-2001 Dave Beckett - http://purl.org/net/dajobe/ All
rights reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

metadata class for HTTP log records
***********************************

NAME
====

   Metadata::HTTP - metadata class for HTTP log records

SYNOPSIS
========

     use Metadata::HTTP
     ...
     $i=new Metadata::HTTP;
     open(IN, $logfile);
     while($i->read('IN')) {
       print $i->get('agent'),"\n";
     }
     ...

DESCRIPTION
===========

   The Metadata::HTTP class allows the handling of HTTP log records as
metadata objects using the Metadata/Base, class.

   The following fields are set after using the read method:

     host ident authuser
     date day month year time hour min sec
     timezone (in format +/-NNNN)
     status bytes
     request - 'GET /foo' etc

   Optionally set:   referer (if supported by log)   agent (if supported
by log)   http-version (if present)   command - GET, POST, etc.    path
- operand to command

CONSTRUCTOR
===========

new [OPTIONS]
     An optional hash of options can be given to the constructor to set
     various options.  There is only one *Metadata::HTTP* options defined:

    DEBUG
          This class has a separate debug class / object method that works
          in the same fashion as the *Metadata::Base* method debug.
          Setting it here also sets the debugging on the base
          *Metadata::Base* object too.

METHODS
=======

   The methods here describe the differences from the Metadata/Base,
class methods.

read HANDLE
     Reads a single line from the file descriptor and uses it to fill the
     fields of the HTTP metadata object.

format [URL]
     Returns the original HTTP line used in the parsing.

SEE ALSO
========

   See Metadata/Base,

AUTHOR
======

   By Dave Beckett - http://purl.org/net/dajobe/

COPYRIGHT
=========

   Copyright (C) 1997-2001 Dave Beckett - http://purl.org/net/dajobe/ All
rights reserved.

IAFA Template metadata class
****************************

NAME
====

   Metadata::IAFA - IAFA Template metadata class

SYNOPSIS
========

     use Metadata::IAFA
     ...
     $i=new Metadata::IAFA;
     $i->set('element1', [qw(v1 v2 v3)]);
     $i->set('element2', 'v2');

     my $val=$i->get('element2);
     for my $v ($i->get('element1') {
       ...
     }
     ...

DESCRIPTION
===========

   The Metadata::IAFA class supports IAFA Templates metadata using the
Metadata/Base, class and customises it for IAFA
Templates where element names have *variants* to represent to sub-values.

CONSTRUCTOR
===========

new [OPTIONS]
     An optional hash of options can be given to the constructor to set
     various options.  There are currently three *Metadata::IAFA* options
     defined:

    STRICT
          This is defined to turn on strict interpretation of the draft
          IAFA Templates standard.  See the read method for what this
          implies.

    TEMPLATE_TYPE
          Set the template type for this IAFA Template (default is
          DOCUMENT).  The alternate ways to set this are via the
          template_type or set methods.

    DEBUG
          This class has a separate debug class / object method that works
          in the same fashion as the *Metadata::Base* method debug.
          Setting it here also sets the debugging on the base
          *Metadata::Base* object too.

    WRAP
          When formatting the metadata for output, word wrap the results
          so that they fit into 80-columns.  This is done using the
          Text::Wrap class.

METHODS
=======

   The methods here describe the differences from the Metadata/Base,
class methods.

set ELEMENT, VALUE, [INDEX]
get ELEMENT, [INDEX]
exists ELEMENT, [INDEX]
     These methods work in the same way as the *Metadata::Base::set*
     methods except that *ELEMENT* can contain the *variant* if it is of
     the form: *ELEMENT*-INDEX where INDEX is a decimal number.

template_type [TEMPLATE-TYPE]
     The Template-Type of the metadata can be set by the set method but it
     is stored separately from the regular elements and can only be
     retrieved from using this method when it is called with no arguments.

read HANDLE
     Implements reading a single IAFA Template from the given *HANDLE*.
     This is done in a generous style (different from the draft standard),
     rather than ending the template on a blank line, uses empty lines and
     thus allows element values to contain multiple paragraphs separated by
     entirely white space lines.

format
     Returns a formatted version of the IAFA Template suitable for writing
     to a file (and reading in with the read method).

get_date_as_seconds ELEMENT
     This handles the strict IAFA format as well as a format of YYYY-MM-DD
     and a raw decimal number-of-seconds.

decode_uri_element VALUE
     Return a list of three elements from decoding the VALUE as a URI
     element: the base file name, the full path and the destination path
     (if a symlink).  If the URI is just a plain URI, the full path will be
     empty.

encode_uri_element URI =item encode_uri_element FILE, PATH
     Return an encoding for either a *URI* or a local FILE and its remote
     PATH (symlink).

order_template_type TEMPLATE-TYPE
     Return an ordering of the *TEMPLATE-TYPE* suitable for sort.

SEE ALSO
========

   See Metadata/Base, Text/Wrap,

AUTHOR
======

   By Dave Beckett - http://purl.org/net/dajobe/

COPYRIGHT
=========

   Copyright (C) 1997-2001 Dave Beckett - http://purl.org/net/dajobe/ All
rights reserved.

SOIF object metadata class
**************************

NAME
====

   Metadata::SOIF - SOIF object metadata class

SYNOPSIS
========

     use Metadata::SOIF
     ...
     $i=new Metadata::SOIF;
     $i->set('element1', [qw(v1 v2 v3)]);
     $i->set('element2', 'v2');

     my $val=$i->get('element2);
     for my $v ($i->get('element1') {
       ...
     }
     ...

DESCRIPTION
===========

   The Metadata::SOIF class supports SOIF objects metadata using the
Metadata/Base, class and customises it for SOIF objects
where element names have *variants* to represent to sub-values.

   SOIF was developed by the Harvest project - the Structured Objects
Interchange Format - to be used for distributed resource discovery.  See
the Harvest Project home page at http://harvest.transarc.com/ for more
details.

CONSTRUCTOR
===========

new [OPTIONS]
     An optional hash of options can be given to the constructor to set
     various options.  There are currently two *Metadata::SOIF* options
     defined:

    DEBUG
          This class has a separate debug class / object method that works
          in the same fashion as the *Metadata::Base* method debug.
          Setting it here also sets the debugging on the base
          *Metadata::Base* object too.

    SPLIT
          In the read method, split the SOIF values on newlines to give
          multiple subvalues (default off).

METHODS
=======

   The methods here describe the differences from the Metadata/Base,
class methods.

template_type [TEMPLATE TYPE]
     The template type of the metadata can be set by this method if an
     *TEMPLATE TYPE* is given.  The old value is returned when it is set or
     returned when this method is called with no arguments.

url [URL]
     The URL of the metadata can be set by this method if an URL is given.
     The old value is returned when it is set or returned when this method
     is called with no arguments.

read HANDLE, [URL]
     Implements reading a single SOIF object from the given *HANDLE*.
     Optionally allows the setting of the SOIF URL for the object in
     preference for the one read from the *HANDLE*

format [URL]
     Returns a formatted version of the SOIF object suitable for writing
     to a file (and reading in with the read method).  Optionally allows
     the setting of the object URL to use in formatting.

SEE ALSO
========

   See Metadata/Base,

AUTHOR
======

   By Dave Beckett <*D.J.Beckett@ukc.ac.uk*>.

COPYRIGHT
=========

   Copyright 1997 Dave Beckett.  All rights reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl extension for Mhash Hash library
*************************************

NAME
====

   Mhash - Perl extension for Mhash Hash library

DISCLAIMER
==========

   If you have use for this, please try and use it and report any bugs you
find.  Feedback and comments from users of this module is important for
further development.

SYNOPSIS
========

A STANDARD HASHING EXAMPLE
--------------------------

     use Mhash qw( mhash_hex ) ;
     my $data  = "this is my secret data";
     $hash_hex = mhash_hex(Mhash::MHASH_MD5, $data) ;

AN EXAMPLE PROGRAM USING HMAC
-----------------------------

     use Mhash qw( mhash_hmac_hex ) ;
     my $key  = "Jefe" ;
     my $data = "what do ya want for nothing?" ;
     my $hash_hex = mhash_hmac_hex(Mhash::MHASH_MD5, $data, $key) ;
     # $hash_hex should be 750c783e6ab0b503eaa86e310a5db738 according to RFC 2104.

     **NOTE** Please read the section on EXPORT TAGS below for information on the MHASH_ constants and the how to manage your namespace.

DEPENDENCIES
============

   This interface is dependent on the MHASH library.  Please download and
install the latest mhash-x.x.x.tar.gz at ftp://mhash.sourceforge.net/dl/.
As of this writing, the latest is mhash-0.8.3.tar.gz.  Additional
information about the mhash library can be found at
http://mhash.sourceforge.net.

   The MHASH library MUST be found in your library path when using this
module.  In Linux, libmhash is defaultly installed in /usr/local/lib - in
this case, be sure that the /usr/local/lib path is in your
/etc/ld.so.conf.  Don't forget to run /sbin/ldconfig to update your linker
cache after mhash library installation!

DESCRIPTION
===========

   This is an perl interface to the Mhash hash library, which provides a
uniform interface to a large number of hash algorithms (also known as
"one-way" algorithms).  These algorithms can be used to compute checksums,
message digests, and other signatures. Mhash support HMAC generation (a
mechanism for message authentication using cryptographic hash functions,
and is described in RFC2104). HMAC can be used to create message digests
using a secret key, so that these message digests cannot be regenerated
(or replaced) by someone else.  At the time of writing this, the library
supports the algorithms: SHA1, GOST, HAVAL, MD5, RIPEMD160, TIGER, and
CRC32 checksums.

   Here is the list of hash constants which are currently supported by the
Mhash module:

     MHASH_CRC32

     MHASH_MD5

     MHASH_SHA1

     MHASH_GOST

     MHASH_RIPEMD160

     MHASH_TIGER

     MHASH_GOST

     MHASH_CRC32B

     MHASH_HAVAL224

     MHASH_HAVAL192

     MHASH_HAVAL160

EXPORT TAGS
===========

:Functions
----------

     This tag exports all the functions related to Mhash.  This tag should be imported for convenience unless you are going to be importing specific functions into your namespace by hand.  This tag is automatically imported if no export tags are supplied as in the above example.

   The following functions are imported with this export tag:

   mhash mhash_hex mhash_hmac mhash_hmac_hex mhash_count
mhash_get_block_size mhash_get_hash_name

   example:

     use Mhash;
         OR
     use Mhash(:Functions) ;

:Types
------

     This tag exports the cipher constants defined by the list of hash types above in DESCRIPTION.  It is recommended you import this tag for ease of use.  If you are concerned with polluting your namespace, do not import this tag, and use the form Mhash::MHASH_HASHNAME when supplying the cipher to the Mhash functions.

   example:

     use Mhash(:Types :Functions) ;
     $blah = mhash(MHASH_MD5, $data) ;

PROGRAMMING FUNCTIONS AND METHODS
=================================

   The following methods are available:

   mhash(), mhash_hex()

   mhash() applies a hash function specified by hash to the data and
returns the resulting hash (also called digest).   mhash_hex() computes
the hash and returns the hash value in hexadecimal form.

     $hash = mhash($hash, $data) ;

   $hash is one of the MHASH_ciphername constants.

   $data is the data which shall be hashed.

   mhash_hmac(), mhash_hmac_hex()

     mhash_hmac() computes a HMAC hash and returns the binary hash value.
     mhash_hmac_hex() computes a HMAC hash and returns the hash value in hexadecimal form.

     $hash_hmac = mhash_hmac($hash, $data, $key) ;

   $hash is one of the MHASH_ciphername constants.

   $data is the data which shall be hashed.

   $key is the key supplied to the hash algorithm. It must be kept secret.
It should be the blocksize of the current hash - use
mhash_get_block_size() to get the blocksize.

   mhash_get_block_size()

   Mhash_get_block_size() is used to get the size of a block of the
specified hash.  Mhash_get_block_size() takes one argument, the hash and
returns the size in bytes or false, if the hash does not exist.

     $blocksize = mhash_get_block_size($hash) ;

   $hash is one of the MHASH_ciphername constants.

   mhash_get_hash_name()

     Mhash_get_hash_name() gets the name of the specified hash.  Mhash_get_hash_name() takes one argument, the hash and returns the name of the hash as a string or false, if the hash does not exist.

     $hashname = mhash_get_hash_name($hash) ;

   $hash is one of the MHASH_ciphername constants.

   mhash_count()

     Mhash_count() returns the highest available hash id. Hashes are numbered from 0 to this hash id.

     Mhash_count() takes no arguments.

TODO
====

     - More bug testing.
     - detection of libmhash installation
     - support for the key generation functions of mhash

AUTHOR
======

   Kuo, Frey. <kero@3SHEEP.COM>.

CREDITS
-------

   Mavroyanopoulos, Nikos <nmav@hellug.gr>, Schumann, Sasha
<sascha@schumann.2ns.de> - for the libmhash library.

SEE ALSO
========

   mhash(3).

uses mmap to map in a file as a perl variable
*********************************************

NAME
====

   Mmap - uses mmap to map in a file as a perl variable

SYNOPSIS
========

     use Mmap;

     mmap($foo, 0, PROT_READ, MAP_SHARED, FILEHANDLE) or die "mmap: $!";
     @tags = $foo =~ /<(.*?)>/g;
     munmap($foo) or die "munmap: $!";

     mmap($bar, 8192, PROT_READ|PROT_WRITE, MAP_SHARED, FILEHANDLE);
     substr($bar, 1024, 11) = "Hello world";

DESCRIPTION
===========

   The Mmap module lets you use mmap to map in a file as a perl variable
rather than reading the file into dynamically allocated memory. It depends
on your operating system supporting UNIX or POSIX.1b mmap, of course. You
need to be careful how you use such a variable. Some programming
constructs may create copies of a string which, while unimportant for
smallish strings, are far less welcome if you're mapping in a file which
is a few gigabytes big. If you use PROT_WRITE and attempt to write to the
file via the variable you need to be even more careful. One of the few
ways in which you can safely write to the string in-place is by using
substr as an lvalue and ensuring that the part of the string that you
replace is exactly the same length.

mmap(VARIABLE, LENGTH, PROTECTION, FLAGS, FILEHANDLE, OFFSET)
     Maps LENGTH bytes of (the underlying contents of) FILEHANDLE into your
     address space, starting at offset OFFSET and makes VARIABLE refer to
     that memory. The OFFSET argument can be omitted in which case it
     defaults to zero. The LENGTH argument can be zero in which case a
     stat is done on FILEHANDLE and the size of the underlying file is
     used instead.

     The PROTECTION argument should be some ORed combination of the
     constants PROT_READ, PROT_WRITE and PROT_EXEC or else PROT_NONE. The
     constants PROT_EXEC and PROT_NONE are unlikely to be useful here but
     are included for completeness.

     The FLAGS argument must include either MAP_SHARED or MAP_PRIVATE (the
     latter is unlikely to be useful here).  If your platform supports it,
     you may also use MAP_ANON or MAP_ANONYMOUS.  If your platform
     supplies MAP_FILE as a non-zero constant (necessarily non-POSIX) then
     you should also include that in FLAGS. POSIX.1b does not specify
     MAP_FILE as a FLAG argument and most if not all versions of Unix have
     MAP_FILE as zero.

     mmap returns 1 on success and undef on failure.

munmap(VARIABLE)
     Unmaps the part of your address space which was previously mapped in
     with a call to `mmap(VARIABLE, ...)' and makes VARIABLE become
     undefined.

     munmap returns 1 on success and undef on failure.

Constants
     The Mmap module exports the following constants into your namespace
      MAP_SHARED MAP_PRIVATE MAP_ANON MAP_ANONYMOUS MAP_FILE
     PROT_EXEC PROT_NONE PROT_READ PROT_WRITE

     Of the constants beginning MAP_, only MAP_SHARED and MAP_PRIVATE are
     defined in POSIX.1b and only MAP_SHARED is likely to be useful.

AUTHOR
======

   Malcolm Beattie, 21 June 1996.

Perl module for creation of voiceboxes.
***************************************

NAME
====

   Modem::VBox - Perl module for creation of voiceboxes.

SYNOPSIS
========

     use Modem::VBox;

DESCRIPTION
===========

   Oh well ;) Not written yet! An example script (`vbox') is included in
the distro, though.

AUTHOR
======

   Marc Lehmann <pcg@goof.com>.

SEE ALSO
========

   perl(1), see Modem/Vgetty, a similar but uglier
interface.

interface to vgetty(8)
**********************

NAME
====

   Modem::Vgetty - interface to vgetty(8)

SYNOPSIS
========

     use Modem::Vgetty;
     $v = new Modem::Vgetty;

     $string = $v->receive;
     $v->send($string);
     $string = $v->expect($str1, $str2, ...);
     $v->waitfor($string);
     $rv = $v->chat($expect1, $send1, $expect2, $send2, ...);

     $ttyname = $v->getty;
     $rv = $v->device($dev_type);
     $rv = $v->autostop($bool);
     $rv = $v->modem_type; # !!! see the docs below.

     $rv = $v->beep($freq, $len);
     $rv = $v->dial($number);
     $rv = $v->play($filename);
     $rv = $v->record($filename);
     $rv = $v->wait($seconds);
     $rv = $v->play_and_wait($filename);
     $v->stop;

     $v->add_handler($event, $handler_name, $handler);
     $v->del_handler($event, $handler_name);
     $v->enable_events;
     $v->disable_events;

     $number = $v->readnum($message, $tmout, $repeat);

     $v->shutdown;

DESCRIPTION
===========

   `Modem::Vgetty' is an encapsulation object for writing applications for
voice modems using the *vgetty(8)* or *vm(8)* package. The answering
machines and sofisticated voice applications can be written using this
module.

OVERVIEW
========

   *Voice modem* is a special kind of modem, which (besides the normal
data and/or fax mode) can communicate also in voice mode. It means it can
record sounds it hears from the phone line to the file, Play-back recorded
files, it can beep to the line, and it can detect various standard sounds
coming from the line (busy tone, silence, dual tone modulation frequency
(DTMF) keypad tones, etc).  An example of the voice modem can be the ZyXEL
U1496, US Robotics Sportster (not Courier), etc.

   To use this software with the voice modem you need to have the
*vgetty(8)* package installed. *Vgetty* is distributed as a part of
*mgetty* package. In fact, *vgetty* is a *mgetty(8)* with the voice
extensions. Vgetty has some support for scripting - when it receives an
incoming call, it runs a voice shell (it is program specified in the
*voice.conf* file) as its child process, establishes the read and write
pipes to it, and tells it the number of the appropriate descriptors in the
environment variables. Voice shell can now communicate with *vgetty*. It
can tell *vgetty* "Play this file", or "Record anything you hear to that
file", or "Notify me when user hangs up", etc. Sophisticated voice systems
and answering machines can be build on top of *vgetty*.

   *mgetty* (including the *vgetty*) is available at the following URL:

     ftp://alpha.greenie.net/pub/mgetty/

   Originally there was a (Bourne) shell interface to *vgetty* only.  The
*Modem::Vgetty* module allows user to write the voice shell in Perl.  The
typical use is to write a script and point the *vgetty* to it (in
*voice.conf* file). The script will be run when somebody calls in.
Another use is running voice shell from the *vm(8)* program, which can for
example dial somewhere and say something.

QUICK START
===========

     #!/usr/bin/perl
     use Modem::Vgetty;
     my $v = new Modem::Vgetty;
     $v->add_handler('BUSY_TONE', 'endh', sub { $v->stop; exit(0); });
     local $SIG{ALRM} = sub { $v->stop; };
     $v->enable_events;
     $v->record('/tmp/hello.rmd');
     alarm(20);
     $v->waitfor('READY');
     $v->shutdown;

   The above example installs the simple `exit now'-style handler for the
BUSY_TONE event (which is sent by *vgetty* when user hangs up) and then
records the *hello.rmd* file. Put this text into a file and then point
*vgetty* to it in the *voice.conf*. After you dial into your voice modem,
you can record a 20-seconds of some message.  Verify that */tmp/hello.rmd*
exists. Now delete the line contaning the word "record" and two subsequent
lines and insert to the file the following line instead of them:

     $v->play_and_wait('/tmp/hello.rmd');

   Now call the voice modem and listen to the sounds you have just
recorded.

METHODS
=======

Begin and end of communication
------------------------------

   The *Modem::Vgetty* object will initialize the communication pipes to
the *vgetty* at the creation time - in the constructor. The closing of the
communication is done via the shutdown method:

     $v->shutdown;

   The module will call this method itself from the destructor, if you do
not call it explicitly.

Low-level communication
-----------------------

   Users probably don't want to use these methods directly. Use the
higher-level functions instead.

receive
     This method returns a string received from the *vgetty*. It parses
     the string for the event types and runs appropriate event handlers.
     If event handler is run it waits for another string.

send($string)
     This method sends the string $string to the *vgetty* process.

expect($string1, $string2, ...)
     Receives a string from *vgetty* (using the receive method described
     above) and returns it iff it is equal to one of the strings in the
     argument list. When something different is received, this method
     returns undef.

waitfor($string)
     Waits until the string *$sring* is received from *vgetty* (using the
     receive method described above).  =item chat($expect1, $sent1,
     $expect2, $sent2, ...)

     A chat-script with *vgetty*. Arguments are interpreted as the
     received-sent string pairs. A received string equals to the empty
     string means that no receive method will be called at that place.
     This can be used for constructing chat scripts beginning with the
     sent string instead of the received one.

Vgetty control methods
----------------------

   There are miscellaneous methods for controllig *vgetty* and querying its
status.

getty
     Returns the name of the modem special file (e.g. */dev/ttyC4*).

device($name)
     Sets the port of the voice modem input and output is done to.
     Possible values are qw(NO_DEVICE DIALUP_LINE EXTERNAL_MICROPHONE
     INTERNAL_SPEAKER LOCAL_HANDSET).

autostop($bool)
     With autostop on, the voicelib will automatically abort a play in
     progress and return READY. This is useful for faster reaction times
     for voice menus. Possible arguments are qw(ON OFF).  Note: The
     interface should probably be changed to accept the Perl boolean
     arguments (undef, something else). Returns defined value on success,
     undef on failure.

modem_type
     *vgetty* currently has no way of telling voice shell the type of the
     current modem. This method is a proposed interface for determining
     this type. Currently returns undef. The appropriate low-level
     interface has to be implemented in *vgetty* first.

Voice commands
--------------

beep($freq, $len)
     Sends a beep through the chosen device using given frequency (HZ) and
     length (in miliseconds).  Returns a defined value on success or undef
     on failure.  The state of the vgetty changes to "BEEPING" and *vgetty*
     returns "READY" after a beep is finshed. Example:

          $v->beep(50,10);
          # Possibly do something else
          $v->waitfor('READY');

dial($number)
     Modem tries to dial a given number. The *vgetty* changes its state to
     "DIALING" and returns "READY" after the dialing is finished.

play($filename)
     The *vgetty* tries to play the given file as a raw modem data.  See
     the "Voice data" section for details on creating the raw modem data
     file. It changes the state to "PLAYING" and returns "READY" after
     playing the whole file.

record($filename)
     The *vgetty* records the voice it can hear on the line to the given
     file.  It uses the raw modem data format (which can be re-played
     using the play subroutine). *vgetty* changes its state to "RECORDING"
     and you need to manually stop the recording using the stop method
     after some time (or, you can set *autostop* and wait for any event -
     silence, busy tone, etc).

wait($seconds)
     The modem waits for a given number of seconds. Changes its state to
     "WAITING" and returns "READY" after the wait is finished. Example:

          $v->wait(5);
          $v->waitfor('READY');

stop
     The *vgetty* stops anything it is currently doing and returns to the
     command state. You must use stop when you want to call another
     *beep*, *dial*, play, record or wait before the previous one is
     finished. The *vgetty* returns "READY" after the stop is called. So
     it is possible to interrupt a main routine waiting for "READY" from
     the event handler:

          my $dtmf;
          $v->add_handler('RECEIVED_DTMF', 'readnum',
          	sub { my $self=shift; $self->stop; $dtmf = $_[2]; });
          $v->enable_events;
          $v->wait(10);
          $v->waitfor('READY');

     In the previous example the waitfor method can be finished either by
     the 10-second timeout expired, or by the 'READY' generated by the
     stop in the event handler. See also the Events section.

play_and_wait($file)
     It is an abbreviation for the following:

          $v->play($file);
          $v->waitfor('READY');

     It is repeated so much time in the voice applications so I have
     decided to make a special routine for it. I may add the similar
     routines for *dial*, record, *beep* and even wait in the future
     releases.

Event handler methods
---------------------

add_handler($event, $handler_name, $handler)
     Installs a call-back routine $handler for the event type $event.  The
     call-back routine is called with three arguments. The first one is
     the Modem::Vgetty object itself, the second one is the event name and
     the third one is optional event argument.  The *$handler_name*
     argument can be anything. It is used when you want to delete this
     handler for identificating it.

del_handler($event, $handler_name)
     This method deletes the handler $handler_name for the $event event.
     The result of unregistering the handler from the event handler of the
     same event is unspecified. It may or may not be called.

enable_events
     Tells the *vgetty* that the voice shell is willing to dispatch events.
     No events are sent by *vgetty* until this method is called.

disable_events
     Tells the *vgetty* that the voice shell doesn't want to receive any
     events anymore.

The *readnum* method
--------------------

readnum($message, $tmout, $repeat)
     The applications often need to read the multi-digit number via the
     DTMF tones.  This routine plays the *$message* to the voice object
     and then waits for the sequence of the DTMF keys finished by the `#'
     key. If no key is pressed for *$tmout* of seconds, it re-plays the
     message again. It returns failure if no key is pressed after the
     message is played *$repeat*-th time. It returns a string (a sequence
     of DTMF tones 0-9,A-D and `*') without the final `#'. When some DTMF
     tones are received and no terminating `#' or other tone is received
     for *$tmout* seconds, the routine returns the string it currently has
     without waiting for the final '#'.  DTMF tones are accepted even at
     the time the *$message* is played.  When the DTMF tone is received,
     the playing of the *$message* is (with some latency, of course)
     stopped.

     NOTE: The interface of this routine can be changed in future releases,
     because I am not (yet) decided whether the current interface is the
     best one.  See also the EXAMPLES section where the source code of
     this routine (and its co-routine) is discussed.

EVENTS
======

Introduction
------------

   Events are asynchronous messages sent by *vgetty* to the voice shell.
The *Modem::Vgetty* module dispatches events itself in the receive method.
User can register any number of handlers for each event.  When an event
arrives, all handlers for that event are called (in no specified order).

Event types
-----------

   At this time, the *Modem::Vgetty* module recognizes the following event
types (description is mostly re-typed from the *vgetty* documentation):

BONG_TONE
     The modem detected a bong tone on the line.

BUSY_TONE
     The modem detected busy tone on the line (when dialing to the busy
     number or when caller finished the call).

CALL_WAITING
     Defined in IS-101 (I think it is when the line receives another
     call-in when some call is already in progress. -Yenya).

DIAL_TONE
     The modem detected dial tone on the line.

DATA_CALLING_TONE
     The modem detected data calling tone on the line.

DATA_OR_FAX_DETECTED
     The modem detected data or fax calling tones on the line.

FAX_CALLING_TONE
     The modem detected fax calling tone on the line.

HANDSET_ON_HOOK
     Locally connected handset went on hook.

HANDSET_OFF_HOOK
     Locally connected handset went off hook.

LOOP_BREAK
     Defined in IS-101.

LOOP_POLARITY_CHANGE
     Defined in IS-101.

NO_ANSWER
     After dialing the modem didn't detect answer for the time give in
     dial_timeout in voice.conf.

NO_DIAL_TONE
     The modem didn't detect dial tone (make sure your modem is connected
     properly to your telephone company's line, or check the ATX command
     if dial tone in your system differs from the standard).

NO_VOICE_ENERGY
     It means that the modem detected voice energy at the beginning of the
     session, but after that there was a period of some time of silence
     (the actual time can be set using the *rec_silence_len* and
     *rec_silence_treshold* parameters in *voice.conf*).

RING_DETECTED
     The modem detected an incoming ring.

RINGBACK_DETECTED
     The modem detected a ringback condition on the line.

RECEIVE_DTMF
     The modem detected a dtmf code. The actual code value (one of 0-9, *,
     #, A-D) is given to the event handler as the third argument.

SILENCE_DETECTED
     The modem detected that there was no voice energy at the beginning of
     the session and after some time of silence (the actual time can be
     set using the *rec_silence_len* and *rec_silence_treshold* parameters
     in *voice.conf*).

SIT_TONE
     Defined in IS-101.

TDD_DETECTED
     Defined in IS-101.

VOICE_DETECTED
     The modem detected a voice signal on the line. IS-101 does not
     define, how the modem makes this decision, so be careful.

UNKNOWN_EVENT
     None of the above :)

VOICE DATA
==========

   Voice shell can send the voice data to the modem using the play method
and record them using the record method. The ".rmd" extension (Raw Modem
Data) is usually used for these files. The ".rmd" is not a single format -
every modem has its own format (sampling frequency, data bit depth, etc).
There is a *pvftools* package for converting the sound files (it is a set
of filters similar to the *netpbm* for image files). The *pvftormd(1)*
filter can be used to create the RMD files for all known types of modems.

EXAMPLES
========

Answering machine
-----------------

   A simple answering machine can look like this:

     #!/usr/bin/perl
     use Modem::Vgetty;
     	my $voicemaster = 'root@localhost';
     	my $tmout = 30;
     	my $finish = 0;
     my $v = new Modem::Vgetty;
     $v->add_handler('BUSY_TONE', 'finish',
     		sub { $v->stop; $finish=1; });
     $v->add_handler('SILENCE_DETECTED', 'finish',
     		sub { $v->stop; $finish=1; });
     	local $SIG{ALRM} = sub { $v->stop; };
     $v->enable_events;
     $v->play_and_wait('/path/welcome.rmd');
     $v->beep(100,10);
     	$v->waitfor('READY');
     	if ($finish == 0) {
     		my $num = 0;
     		$num++ while(-r "/path/$num.rmd");
     		$v->record("/path/$num.rmd");
     		alarm $tmout;
     		$v->waitfor('READY');
     	}
     	system "echo 'Play with rmdtopvf /path/$num.rmd|pvftoau >/dev/audio'" .
     		 " | mail -s 'New voice message' $voicemaster";
     exit 0;

   See the *examples/answering_machine.pl* in the source distribution,
which contains a more configurable version of the above text.  It first
sets the event handlers for the case of busy tone (the caller hangs up) or
silence (the caller doesn't speak at all). The handler stops *vgetty* from
anything it is currently doing and sets the $finish variable to 1. Then
the reception of the events is enabled and the welcome message is played.
Then the answering machine beeps and starts to record the message. Note
that we need to check the $finish variable before we start recording to
determine if user hanged up the phone. Now we find the first filename
<number>.rmd such that this file does not exist and we start to record the
message to this file. We record until user hangs up the phone or until the
timeout occurs.

Readnum routine
---------------

   An interesting application of the low-level routines is the
*Voice::Modem::readnum* method. The calling sequence of this method has
been discussed above. The source code for this routine and its co-routine
will be discussed here, so that you can write your own variants of
*readnum* (which in fact does not have too general interface). See also
the source code of *Vgetty.pm* for the *readnum* source.

   The *readnum* routine needs to have its own event handler for the
*RECEIVED_DTMF* event and the way the handler can communicate with this
routine. In our solution we use "static" variables:

     my $_readnum_number = '';
     my $_readnum_timeout = 10;
     my $_readnum_in_timeout = 1;

   The event handler will add the new character to the end of the
*$_readnum_number* variable. The *$_readnum_timeout* is the number of
seconds both *readnum* and the event handler should wait for the next
keypress, and the *$_readnum_in_timeout* is a flag used by the event
handler for notifying the main *readnum* routine that it forced the
*vgetty* to emit the `READY' message because of the final `#' has been
received.

     sub _readnum_event {
     	my $self = shift;
     	my $input = shift; # Unused. Should be 'RECEIVED_DTMF'.
     	my $dtmf = shift;

     if ($dtmf eq '#') { # Stop the reading now.
     	$_readnum_in_timeout = 0;
     	$self->stop;
     	$self->{LOG}->print("_readnum_event(): Got #; stopping\n");
     	return;
     }
     $_readnum_number .= $dtmf;
     $self->stop;
     $self->expect('READY');
     # Restart the wait again.
     $_readnum_in_timeout = 1;
     $self->wait($_readnum_timeout);
     	}

   The event handler is installed for the `RECEIVED_DTMF' event only, so it
doesn't need to check for the *$input* value. The actual DTMF key is in
the third parameter, *$dtmf*. Note that the handler will be called when
*vgetty* is PLAYING or WAITING and the *readnum* routine will be waiting
for the `READY' message. This allows us to immediately interrupt waiting
by the *$self-*stop> (which emits the `READY' message).  So when the `#'
DTMF tone is received, we send a stop to *vgetty*.  If something else is
received, we stop the *vgetty* too but we enter a new wait using
*$self-*wait>.

     sub readnum {
     	my $self = shift;
     	my $message = shift;
     	my $timeout = shift;
     	my $times = shift;
     	$_readnum_number = '';
     	$_readnum_in_timeout = 1;
     	$_readnum_timeout = $timeout if $timeout != 0;
     	$times = 3 if $times == 0;

     # Install the handler.
     $self->add_handler('RECEIVED_DTMF', 'readnum', \&_readnum_event);
     while($_readnum_in_timeout != 0 && $_readnum_number eq ''
     	&& $times-- > 0) {
     	$self->play_and_wait($message);
     	last if $_readnum_in_timeout == 0;
     	while ($_readnum_in_timeout != 0) {
     		$self->wait($_readnum_timeout);
     		$self->expect('READY');
     	}
     }
     return undef if $times < 0;
     $self->del_handler('RECEIVED_DTMF', 'readnum');
     $self->stop;
     $self->expect('READY');
     $_readnum_number;
     	}

   The *readnum* routine just sets up the event handler, then plays the
*$message* and waits for the input (possibly several times).  The main
work is done in the event handler. At the end the handler is unregistered
and the final value is returned.

Callme script
-------------

   In the examples subdirectory of the source distribution there is a
*callme.pl* script. This dials the given number and plays the given
message. Use the following command to run it:

     vm shell -S /usr/bin/perl callme.pl <number> <message>.rmd

BUGS
====

   There may be some, but it will more likely be in the *vgetty* itself.
On the other hand, there can be typos in this manual (English is not my
native language) or some parts of the interface that should be redesigned.
Feel free to mail any comments on this module to me.

TODO
====

Modem type recognition
     The *vgetty* should be able to tell the voice shell the name of the
     current modem type.

The _wait() routines
     I need to implement the routines similar to *play_and_wait* for other
     *vgetty* states as well.

Debugging information
     The module has currently some support for writing a debug logs (use
     the $Modem::Vgetty::testing = 1 and watch the /var/log/voicelog
     file). This needs to be re-done using (I think) Sys::Syslog.  I need
     to implement some kind of log-levels, etc.

Mgetty/Vgetty 1.1.17
     Need to figure out what is new in 1.1.17 (I use 1.1.14 now). I think
     new *vgetty* can play more than one file in the single `PLAY' command,
     it (I think) have some support for sending voice data from/to the
     voice shell via the pipe, etc.

AUTHOR
======

   The *Modem::Vgetty* package was written by Jan "Yenya" Kasprzak
<kas@fi.muni.cz>. Feel free to mail me any suggestions etc.  on this
module. Module itself is available from CPAN, but be sure to check the
following address, where the development versions can be found:

     http://www.fi.muni.cz/~kas/vgetty/

COPYRIGHT
=========

   Copyright (c) 1998 Jan "Yenya" Kasprzak <kas@fi.muni.cz>. All rights
reserved. This package is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

a quick way to check argument counts for methods
************************************************

NAME
====

   Module::Check_Args - a quick way to check argument counts for methods

SYNOPSIS
========

   use Module::Check_Args;

   exact_argcount *$argcnt*;

   range_argcount *$minargs*, *$maxargs*;

   atleast_argcount *$minargs*;

   atmost_argcount *$maxargs*;

DESCRIPTION
===========

   When writing a complex program, some of the hardest problems to track
down are subroutines that aren't called with the right arguments.  Perl
provides a means to check this at compile time, but there is no way to do
this for subroutines that take a variable number of arguments or for
object methods.  `Module::Check_Args' provides routines that check the
number of arguments passed to their callers and raise an exception if the
number passed doesn't match the number expected.  It's possible to specify
that the number of arguments must be exactly n, at most n, at least n, or
between n and m.

   When using these routines from within a method, be sure to account for
the implicit first argument containing the object reference or class name!

   By default, the four _argcount routines are exported.

   By importing the following pseudo-symbols, you can request various
behaviors from `Module::Check_Args':

use Module::Check_Args qw(-die);
     Specifies that an argument count mismatch is a fatal error.  The
     message will give the file and line number of the call containing the
     bad number of arguments.  This is the default.

use Module::Check_Args qw(-warn);
     An argument mismatch is a warning only.

use Module::Check_Args qw(-off);
     No argument-count checking is performed.  The four checking routines
     are still exported, so that you don't need to change code that
     contains them, but they are dummy procedures.

   If you have multiple packages that use Module::Check_Args, each one can
have different behavior.

Routines
--------

exact_argcount *$argcnt*;
     Specifies that the caller must have exactly *$argcnt* arguments.

range_argcount *$minargs*, *$maxargs*;
     Specifies that the caller must have at least *$minargs* arguments but
     no more than *$maxargs*.

atleast_argcount *$minargs*;
     Specifies that the caller must have at least *$minargs* arguments,
     but can have any number more than that.

atmost_argcount *$maxargs*;
     Specifies that the caller must have at most *$maxargs* arguments, but
     can have any number up to that, including zero.

DIAGNOSTICS
===========

wrong argument count to Module::Check_Args::*routine*
     One of the argument count checking routines was itself called with an
     invalid argument count.  This is always a fatal error regardless of
     the behavior specified in the use declaration.

file(line): too many arguments to *routine* - was %d, should be no greater than %d
file(line): not enough arguments to *routine* - was %d, should be at least %d
file(line): wrong number of arguments to *routine* - was %d, should be between %d and %d
file(line): wrong number of arguments to *routine* - was %d, should be %d
     *routine* was called with an invalid number of arguments at the
     indicated location.  These messages are either fatal errors or
     warnings depending on the behavior specified in the use declaration.

no behavior set for Module::Check_Args - 'import' never called?
     One of the argument count check routines was called, but no behavior
     (-die, -warn) had ever been set.  This can only happen if you use
     something like the following combination of commands:

          use Module::Check_Args ();
          ...
          &Module::Check_Args::exact_argcount(3);

     Don't do that.

SEE ALSO
========

   perlfunc -f caller

AUTHOR
======

   Kevin Michael Vail <kevin@vailstar.com>

Reload %INC files when updated on disk
**************************************

NAME
====

   Module::Reload - Reload %INC files when updated on disk

SYNOPSIS
========

     Module::Reload->check;

DESCRIPTION
===========

   When Perl pulls a file via require, it stores the filename in the
global hash %INC.  The next time Perl tries to require the same file, it
sees the file in %INC and does not reload from disk.  This module's
handler iterates over %INC and reloads the file if it has changed on disk.

   Set $Module::Reload::Debug to enable debugging output.

BUGS
====

   A growing number of pragmas (base, fields, etc.) assume that they are
loaded once only.  When you reload the same file again, they tend to
become confused and break.  If you feel motivated to submit patches for
these problems, I would encourage that.

SEE ALSO
========

   Event

AUTHOR
======

   Copyright © 1997-1998 Doug MacEachern & Joshua Pritikin.  All rights
reserved.

   This package is free software and is provided "as is" without express
or implied warranty.  It may be used, redistributed and/or modified under
the terms of the Perl Artistic License (see
http://www.perl.com/perl/misc/Artistic.html)

Combine several other modules into one package   =head1  SYNOPSIS
*****************************************************************

NAME
====

   ModuleBundle - Combine several other modules into one package

   =head1 SYNOPSIS

   Create a package that looks like this:

     package XYZ;
     use X;
     use Y;
     use Z;
     use ModuleBundle;
     @ISA = 'ModuleBundle;
     1;

   Now if you say

     use XYZ;

   that is the same as saying

     use X;
     use Y;
     use Z;

DESCRIPTION
===========

   See the SYNOPSIS.

AUTHOR
======

   Mark-Jason Dominus (mjd-perl-bundle@plover.com)

Methods for interaction with Mon client
***************************************

NAME
====

   Mon::Client - Methods for interaction with Mon client

SYNOPSIS
========

     use Mon::Client;

DESCRIPTION
===========

     Mon::Client is used to interact with "mon" clients. It supports
     a protocol-independent API for retrieving the status of the mon
     server, and performing certain operations, such as disableing hosts
     and service checks.

METHODS
=======

new
     Creates a new object. A hash can be supplied which sets the default
     values. An example which contains all of the variables that you can
     initialize:

          $c = new Mon::Client (
          	host => "monhost",
          	port => 2583,
          	username => "foo",
          	password => "bar",
          );

password (pw)
     If *pw* is provided, sets the password. Otherwise, returns the
     currently set password.

host (host)
     If host is provided, sets the mon host. Otherwise, returns the
     currently set mon host.

port (portnum)
     If *portnum* is provided, sets the mon port number. Otherwise,
     returns the currently set port number.

username (user)
     If user is provided, sets the user login. Otherwise, returns the
     currently set user login.

prot
     If protocol is provided, sets the protocol, specified by a string
     which is of the form "1.2.3", where "1" is the major revision, "2" is
     the minor revision, and "3" is the sub-minor revision.  If protocol
     is not provided, the currently set protocol is returned.

protid ([protocol])
     Returns true if client and server protocol match, false otherwise.
     Implicitly called by connect. If protocol is specified as an integer,
     supplies that protocol version to the server for verification.

version
     Returns the protocol version of the remote server.

error
     Returns the error string from set by the last method, or undef if
     there was no error.

connected
     Returns 0 (not connected) or 1 (connected).

connect (%args)
     Connects to the server. If host and port have not been set, uses the
     defaults. Returns undef on error.  If $args{"skip_protid"} is true,
     skip protocol identification upon connect.

disconnect
     Disconnects from the server. Return undef on error.

login ( %hash )
     *%hash* is optional, but if specified, should contain two keys,
     username and password.

     Performs the "login" command to authenticate the user to the server.
     Uses username and password if specified, otherwise uses the username
     and password previously set by those methods, respectively.

checkauth ( command )
     Checks to see if the specified command, as executed by the current
     user, is authorized by the server, without actually executing the
     command.  Returns 1 (command is authorized) or 0 (command is not
     authorized).

disable_watch ( watch )
     Disables *watch*.

disable_service ( watch, service )
     Disables a service, as specified by *watch* and service.

disable_host ( host )
     Disables host.

enable_watch ( watch )
     Enables *watch*.

enable_service ( watch, service )
     Enables a service as specified by *watch* and service.

enable_host ( host )
     Enables host.

set ( group, service, var, val )
     Sets var in *group,service* to val. Returns undef on error.

get ( group, service, var )
     Gets variable var in *group,service* and returns it, or undef on
     error.

quit
     Logs out of the server. This method should be followed by a call to
     the disconnect method.

list_descriptions
     Returns a hash of service descriptions, indexed by watch and service.
     For example:

          %desc = $mon->list_descriptions;
          print "$desc{'watchname'}->{'servicename'}\n";

list_deps
     Lists dependency expressions and their components for all services.
     If there is no dependency for a particular service, then the value
     will be "NONE".

          %deps = $mon->list_deps;
          foreach $watch (keys %deps) {
          	foreach $service (keys %{$deps{$watch}}) {
          	    my $sref = \%{$deps{$watch}->{$service}};
          	    print "expr ($watch,$service) = $sref->{expression}\n";
          	    print "components ($watch,$service) = @{$sref->{components}}\n";
          	}
          }

list_group ( hostgroup )
     Lists members of *hostgroup*. Returns an array of each member.

list_watch
     Returns an array of all the defined watch groups and services.

          foreach $w ($mon->list_watch) {
          	print "group=$w->[0] service=$w->[1]\n";
          }

list_opstatus ( [group1, service1], ... )
     Returns a hash of per-service operational statuses, as indexed by
     watch and service. The list of anonymous arrays is optional, and if
     is not provided then the status of all groups and services will be
     queried.

          %s = $mon->list_opstatus;
          foreach $watch (keys %s) {
          	foreach $service (keys %{$s{$watch}}) {
          	    foreach $var (keys %{$s{$watch}{$service}}) {
          	    	print "$watch $service $var=$s{$watch}{$service}{$var}\n";
          	    }
          	}
          }

list_failures
     Returns a hash in the same manner as list_opstatus, but only the
     services which are in a failure state.

list_successes
     Returns a hash in the same manner as list_opstatus, but only the
     services which are in a success state.

list_disabled
     Returns a hash of disabled watches, services, and hosts.

          %d = $mon->list_disabled;

          foreach $group (keys %{$d{"hosts"}}) {
          	foreach $host (keys %{$d{"hosts"}{$group}}) {
          	    print "host $group/$host disabled\n";
          	}
          }

          foreach $watch (keys %{$d{"services"}}) {
          	foreach $service (keys %{$d{"services"}{$watch}}) {
          	    print "service $watch/$service disabled\n";
          	}
          }

          for (keys %{$d{"watches"}}) {
          	print "watch $_ disabled\n";
          }

list_alerthist
     Returns an array of hash references containing the alert history.

          @a = $mon->list_alerthist;

          for (@a) {
          	print join (" ",
          	    $_->{"type"},
          	    $_->{"watch"},
          	    $_->{"service"},
          	    $_->{"time"},
          	    $_->{"alert"},
          	    $_->{"args"},
          	    $_->{"summary"},
          	    "\n",
          	);
          }

list_dtlog
     Returns an array of hash references containing the downtime log.

     @a = $mon->list_dtlog

          for (@a) {
            print join (" ",
                $_->{"timeup"},
                $_->{"group"},
                $_->{"service"},
                $_->{"failtime"},
                $_->{"downtime"},
                $_->{"interval"},
                $_->{"summary"},
                "\n",
            );
          }

list_failurehist
     Returns an array of hash references containing the failure history.

          @f = $mon->list_failurehist;

          for (@f) {
          	print join (" ",
          	    $_->{"watch"},
          	    $_->{"service"},
          	    $_->{"time"},
          	    $_->{"summary"},
          	    "\n",
          	);
          }

list_pids
     Returns an array of hash references containing the list of process IDs
     of currently active monitors run by the server.

          @p = $mon->list_pids;

          $server = shift @p;

          for (@p) {
          	print join (" ",
          	    $_->{"watch"},
          	    $_->{"service"},
          	    $_->{"pid"},
          	    "\n",
          	);
          }

list_state
     Lists the state of the scheduler. Returns a two-element array. The
     first element of the array is 0 if the scheduler is stopped, and 1 if
     the scheduler is currently running. The second element of the array
     returned is the string "scheduler running" if the scheduler is
     currently running, and if the scheduler is stopped, the second
     element is the time(2) that the scheduler was stopped.

          @s = $mon->list_state;

          if ($s[0] == 0) {
          	print "scheduler stopped since " . localtime ($s[1]) . "\n";
          }

start
     Starts the scheduler.

stop
     Stops the scheduler.

reset
     Resets the server.

reload ( what )
     Causes the server to reload its configuration. *what* is an optional
     argument, and currently the only supported option is auth, which
     reloads the authorization file.

term
     Terminates the server.

set_maxkeep
     Sets the maximum number of history entries to store in memory.

get_maxkeep
     Returns the maximum number of history entries to store in memory.

test ( test, group, service [, exitval, period])
     Schedules a service test to run immediately, or tests an alert for a
     given period. test must be *monitor*, alert, *startupalert*, or
     *upalert*. To test alerts, the *exitval* and period must be supplied.
     Periods are identified by their label in the mon config file. If there
     are no period tags, then the actual period string must be used,
     exactly as it is listed in the config file.

test_config
     Tests the syntax of the configuration file. Returns a two-element
     array. The first element of the array is 0 if the syntax of the
     config file is invalid, and 1 if the syntax of the config file is OK.
     The second element of the array returned is the failure message, if
     the config file has invalid syntax, and the result code if the config
     file syntax is OK. This function returns undef if it cannot get a
     connection or a response from the mon server.

     Config file checking stops as soon as an error is found, so you will
     need to run this command more than once if you have multiple errors
     in your config file in order to find them all.

          @s = $mon->test_config;

          if ($s[0] == 0) {
              print "error in config file:\n" . $s[1] . "\n";
          }

ack ( group, service, text )
     When *group/service* is in a failure state, acknowledges this with
     text, and disables all further alerts during this failure period.

loadstate ( state )
     Loads state.

savestate ( state )
     Saves state.

servertime
     Returns the time on the server using the same output as the time(2)
     system call.

send_trap ( %vars )
     Sends a trap to a remote mon server. Here is an example:

          $mon->send_trap (
          	group		=> "remote-group",
          	service		=> "remote-service",
          	retval		=> 1,
          	opstatus	=> "operational status",
          	summary		=> "summary line",
          	detail		=> "multi-line detailed information",
          );

     *retval* must be a nonnegative integer.

     *opstatus* must be one of fail, ok, *coldstart*, *warmstart*,
     *linkdown*, *unknown*, timeout,  *untested*.

     Returns undef on error.

Methods for parsing / dumping a protocol block
**********************************************

NAME
====

   Mon::Protocol - Methods for parsing / dumping a protocol block

SYNOPSIS
========

     use Mon::Protocol;

DESCRIPTION
===========

METHODS
=======

new
     Creates a new object. A hash can be supplied which sets the default
     values. An example which contains all of the variables that you can
     initialize:

          $c = new Mon::Protocol;

dump_data
     Returns the current internal structure as a string dump suitable for
     passing to parse_data.

parse_data
     Parses a command block (from begin_block to end_block), as generated
     by dump_data.

type(*new_type*)
     Sets or returns the type of the current command block. See @TYPES for
     valid type codes.

     In the future, it is possible that this module will perform additional
     checking based on the type, for now it is left to the application to
     interpret this.

`get_section_list'
     Returns an array containing all section names within the block.

`get_section'(*section_name*)
     Returns a hash containing the key/value pairs of the specific section.

`delete_section'(*section_name*)
     Completely removes the specified section from the block.

`add_to_section'(*section_name*,*$hash_ref*)
     Adds the key/value pairs in the hash to the specified section.

          $foo->add_to_section("_hostgroup", { "ns1.baz.com" -> "ok" });

`delete_from_section'(*section_name*,$key)
     Deletes the key/value pair from the section.

          $foo->delete_from_section("_hostgroup", "ns1.baz.com");

error
     Should any of the functions return an error (-1), this function can
     be used to retrieve a more elaborate error message and to reset the
     internal error state.

decode SNMP trap
****************

NAME
====

   Mon::SNMP - decode SNMP trap

SYNOPSIS
========

     use Mon::SNMP;

     $trap = new Mon::SNMP;

     $trap->buffer($snmptrap);

     %traphash = $trap->decode;

     $error = $trap->error;

DESCRIPTION
===========

   Mon::SNMP provides methods to decode SNMP trap PDUs. It is based on
Graham Barr's Convert::BER module, and its purpose is to provide SNMP trap
handling to "mon".

METHODS
=======

new
     creates a new Mon::SNMP object.

buffer ( buffer )
     Assigns a raw SNMP trap message to the object.

decode
     Decodes a SNMP trap message, and returns a hash of the variable
     assignments for the SNMP header and trap protocol data unit of the
     associated message. The hash consists of the following members:

          version         =>      SNMP version (1)
          community       =>      community string
          ent_OID         =>      enterprise OID of originating agent
          agentaddr       =>      IP address of originating agent
          generic_trap    =>      /COLDSTART|WARMSTART|LINKDOWN|LINKUP|AUTHFAIL|EGPNEIGHBORLOSS|ENTERPRISESPECIFIC/
          specific_trap   =>      specific trap type (integer)
          timeticks       =>      timeticks (integer)
          varbindlist     =>      { oid1 => value, oid2 => value, ... }

ERRORS
======

   All methods return a hash with no elements upon errors which they
detect, and the detail of the error is available from the

EXAMPLES
========

     use Mon::SNMP;

     $trap = new Mon::SNMP;

     $trap->buffer($snmptrap);

     %traphash = $trap->decode;

     foreach $oid (keys $traphash{"varbindlist"}) {
     	$val = $traphash{"varbindlist"}{$oid};
     	print "oid($oid) = val($val)\n";
     }

ENVIRONMENT
===========

   None.

SEE ALSO
========

   Graham Barr's Convert::BER module.

NOTES
=====

CAVEATS
=======

   Mon::SNMP depends upon Convert::BER to do the real work.

SYNOPSIS
========

     use Morse;

     print "S-O-S\n";

DESCRIPTION
===========

   The first time you run a program under `use Morse', the module converts
your program to Morse code. The code continues to work exactly as it did
before, but now it looks like this:

     use Morse;
     	.--.-..--..---.-.--..--.-..--..---.-.--.
     	.-.-........---..-..---.-..-.--..---.--.
     	..-.---......-...-...-..--..-.-.-.--.-..
     	----..-.-.--.-..--..-.-...---.-..---.--.
     	.-...-..--.---...-.-....

DIAGNOSTICS
===========

`Can't encode '%s''
     Morse could not access the source file to modify it.

`Can't transmit '%s''
     Morse could not access the source file to execute it.

AUTHOR
======

   Damian Conway (as if you couldn't guess)

COPYRIGHT
=========

     Copyright (c) 2001, Damian Conway. All Rights Reserved.
      This module is free software. It may be used, redistributed
     and/or modified under the terms of the Perl Artistic License
       (see http://www.perl.com/perl/misc/Artistic.html)

Mortal Kombat program termination
*********************************

NAME
====

   Mortal::Kombat - Mortal Kombat program termination

SYNOPSIS
========

     use Mortal::Kombat;
     # ...
     # exit successfully
     flawless victory;

     use Mortal::Kombat;
     $screwedup and fatality "Scorpion has whomped you,";

DESCRIPTION
===========

   This is a gimmick module.  It merely gives you three functions,
flawless(), victory(), and fatality(), each of which can be used without
parentheses for a nice english look.

   The suggested uses are:

     flawless victory;  # same as 'exit 0'

   and

     fatality "some error message";  # same as die "some error message";

   That's it.  If you've got any suggestions, you can email me.  Don't be
ashamed.

AUTHOR
======

     Jeff "japhy" Pinyan
     CPAN ID: PINYAN
     japhy@pobox.com
     http://www.pobox.com/~japhy/

Perl interfaces to the mSQL and mysql databases
***********************************************

NAME
====

   Msql / Mysql - Perl interfaces to the mSQL and mysql databases

SYNOPSIS
========

     use Msql;

     $dbh = Msql->connect;
     $dbh = Msql->connect($host);
     $dbh = Msql->connect($host, $database);

     or

     use Mysql;

     $dbh = Mysql->connect(undef, $database, $user, $password);
     $dbh = Mysql->connect($host, $database, $user, $password);

     $dbh->selectdb($database);

     @arr = $dbh->listdbs;
     @arr = $dbh->listtables;

     $quoted_string = $dbh->quote($unquoted_string);
     $error_message = $dbh->errmsg;
     $error_number = $dbh->errno;   # MySQL only

     $sth = $dbh->listfields($table);
     $sth = $dbh->query($sql_statement);

     @arr = $sth->fetchrow;
     @arr = $sth->fetchcol($col_number);
     %hash = $sth->fetchhash;

     $sth->dataseek($row_number);

     $sth->as_string;

     @indices = $sth->listindices                   # only in mSQL 2.0
     @arr = $dbh->listindex($table,$index)          # only in mSQL 2.0
     ($step,$value) = $dbh->getsequenceinfo($table) # only in mSQL 2.0

     $rc = $dbh->shutdown();
     $rc = $dbh->createdb($database);
     $rc = $dbh->dropdb($database);

DESCRIPTION
===========

   This package is designed as close as possible to its C API counterpart.
The manual that comes with mSQL or MySQL describes most things you need.
Due to popular demand it was decided though, that this interface does not
use StudlyCaps (see below).

   The version you have selected is an adaption still under development,
please consult the file "Changes" in your distribution.

   Internally you are dealing with the two classes `Msql' and
`Msql::Statement' or `Mysql' and `Mysql::Statement', respectively.  You
will never see the latter, because you reach it through a statement handle
returned by a query or a listfields statement. The only class you name
explicitly is Msql or Mysql. They offer you the connect command:

     $dbh = Msql->connect;
     $dbh = Msql->connect($host);
     $dbh = Msql->connect($host, $database);

     or

     $dbh = Mysql->connect(undef, undef, $user, $password);
     $dbh = Mysql->connect($host, undef, $user, $password);
     $dbh = Mysql->connect($host, $database, $user, $password);

   This connects you with the desired host/database. With no argument or
with an empty string as the first argument it connects to the UNIX socket,
which has a much better performance than the TCP counterpart. A database
name as the second argument selects the chosen database within the
connection. The return value is a database handle if the connect succeeds,
otherwise the return value is undef.

   You will need this handle to gain further access to the database.

     $dbh->selectdb($database);

   If you have not chosen a database with the connect command, or if you
want to change the connection to a different database using a database
handle you have got from a previous connect, then use selectdb.

     $sth = $dbh->listfields($table);
     $sth = $dbh->query($sql_statement);

   These two work rather similar as descibed in the mSQL or MySQL manual.
They return a statement handle which lets you further explore what the
server has to tell you. On error the return value is undef. The object
returned by listfields will not know about the size of the table, so a
numrows() on it will return the string "N/A";

     @arr = $dbh->listdbs();
     @arr = $dbh->listtables;

   An array is returned that contains the requested names without any
further information.

     @arr = $sth->fetchrow;

   returns an array of the values of the next row fetched from the server.
Similar does

     %hash = $sth->fetchhash;

   return a complete hash. The keys in this hash are the column names of
the table, the values are the table values. Be aware, that when you have a
table with two identical column names, you will not be able to use this
method without trashing one column. In such a case, you should use the
fetchrow method.

     @arr = $sth->fetchcol($colnum);

   returns an array of the values of each row for column $colnum.  Note
that this reads the entire table and leaves the row offset at the end of
the table; be sure to use $sth->dataseek() to reset it if you want to
re-examine the table.

     $sth->dataseek($row_number);

   lets you specify a certain offset of the data associated with the
statement handle. The next fetchrow will then return the appropriate row
(first row being 0).

No close statement
------------------

   Whenever the scalar that holds a database or statement handle loses its
value, Msql chooses the appropriate action (frees the result or closes the
database connection). So if you want to free the result or close the
connection, choose to do one of the following:

undef the handle
use the handle for another purpose
let the handle run out of scope
exit the program.
Error messages
--------------

   Both drivers, Msql and Mysql implement a method ->errmsg(), which
returns a textual error message. Mysql additionally supports a method
->errno returning the corresponding error number. Note that Msql's errmsg
is a static method, thus it is legal to fetch

     Msql->errmsg();

   Mysql doesn't support this, fetching the error message is only valid via

     $dbh->errmsg();

   I recommend, that even Msql users restrict themselves to the latter for
portability reasons. There are also global variables $Msql::db_errstr and
$Mysql::db_errstr, which always hold the last error message. The former is
reset with the next executed command, the latter not. Usually there's no
need for accessing the global variables, with one exception: If the
connect method fails, you need them.

The -w switch
-------------

   With Msql and Mysql the -w switch is your friend! If you call your perl
program with the -w switch you get the warnings from ->errmsg on STDERR.
This is a handy method to get the error messages from the msql server
without coding it into your program.

   If you want to know in greater detail what's going on, set the
environment variables that are described in David's manual. David's
debugging aid is excellent, there's nothing to be added.

   If you want to use the -w switch but do not want to see the error
messages from the msql daemon, you can set the variables $Msql::QUIET or
$Mysql::QUIET to some true value, and they will be supressed.

->quote($str [, $length])
-------------------------

   returns the argument enclosed in single ticks (") with any special
character escaped according to the needs of the API.

   For mSQL this means, any single tick within the string is escaped with
a backslash and backslashes are doubled. Currently (as of msql-1.0.16) the
API does not allow to insert NUL's (ASCII 0) into tables. The quote method
does not fix this deficiency.

   MySQL allows NUL's or any other kind of binary data in strings. Thus
the quote method will additionally escape NUL's as \0.

   If you pass undefined values to the quote method, it returns the string
NULL.

   If a second parameter is passed to quote, the result is truncated to
that many characters.

NULL fields
-----------

   NULL fields in tables are returned to perl as undefined values.

Metadata
--------

   Now lets reconsider the above methods with regard to metadata.

Database Handle
---------------

   As said above you get a database handle with

     $dbh = Msql->connect($host, $database);

     or

     $dbh = Mysql->connect($host, $database);

   The database handle knows about the socket, the host, and the database
it is connected to.

   You get at the three values with the methods

     $scalar = $dbh->sock;
     $scalar = $dbh->host;
     $scalar = $dbh->database;

   Mysql additionally supports

     $scalar = $dbh->user;
     $scalar = $dbh->sockfd;

   where the latter is the file descriptor of the socket used by the
database connection. This is the same as $dbh->sock for mSQL.

Statement Handle
----------------

   Two constructor methods return a statement handle:

     $sth = $dbh->listfields($table);
     $sth = $dbh->query($sql_statement);

   $sth knows about all metadata that are provided by the API:

     $scalar = $sth->numrows;
     $scalar = $sth->numfields;

     @arr  = $sth->table;       the names of the tables of each column
     @arr  = $sth->name;        the names of the columns
     @arr  = $sth->type;        the type of each column, defined in msql.h
     	                     and accessible via Msql::CHAR_TYPE,
     	                     &Msql::INT_TYPE, &Msql::REAL_TYPE or
                                &Mysql::FIELD_TYPE_STRING,
                                &Mysql::FIELD_TYPE_LONG, ...
     @arr  = $sth->isnotnull;   array of boolean
     @arr  = $sth->isprikey;    array of boolean
     @arr  = $sth->isnum;       array of boolean
     @arr  = $sth->length;      array of the possibble maximum length of each
                                field in bytes
     @arr  = $sth->maxlength;   array of the actual maximum length of each field
                                in bytes. Be careful when using this attribute
                                under MsqlPerl: The server doesn't offer this
                                attribute, thus it is calculated by fetching
                                all rows. This might take a long time and you
                                might need to call $sth->dataseek.

   Mysql additionally supports

     $scalar  = $sth->affectedrows  number of rows in database affected by query
     $scalar  = $sth->insertid      the unique id given to a auto_increment field.
     $string  = $sth->info()        more info from some queries (ALTER TABLE...)
     $arrref  = $sth->isblob;       array of boolean

   The array methods (table, name, type, is_not_null, is_pri_key, length,
affected_rows, is_num and blob) return an array in array context and an
array reference (see Perlref (perl.info), and `perlldsc' in
this node for details) when called in a scalar context. The scalar context
is useful, if you need only the name of one column, e.g.

     $name_of_third_column = $sth->name->[2]

   which is equivalent to

     @all_column_names = $sth->name;
     $name_of_third_column = $all_column_names[2];

New in mSQL 2.0
---------------

   The query() function in the API returns the number of rows affected by
a query. To cite the mSQL API manual, this means...

     If the return code is greater than 0, not only does it imply
     success, it also indicates the number of rows "touched" by the query
     (i.e. the number of rows returned by a SELECT, the number of rows
     modified by an update, or the number of rows removed by a delete).

   As we are returning a statement handle on selects, we can easily check
the number of rows returned. For non-selects we behave just the same as
mSQL-2.

   To find all indices associated with a table you can call the
`listindices()' method on a statement handle. To find out the columns
included in an index, you can call the `listindex($table,$index)' method
on a database handle.

   There are a few new column types in mSQL 2. You can access their
numeric value with these functions defined in the Msql package:
IDENT_TYPE, NULL_TYPE, TEXT_TYPE, DATE_TYPE, UINT_TYPE, MONEY_TYPE,
TIME_TYPE, IDX_TYPE, SYSVAR_TYPE.

   You cannot talk to a 1.0 server with a 2.0 client.

   You cannot link to a 1.0 library and to a 2.0 library *at the same
time*. So you may want to build two different Msql modules at a time, one
for 1.0, another for 2.0, and load whichever you need. Check out what the
-I switch in perl is for.

   Everything else seems to remain backwards compatible.

@EXPORT
-------

   For historical reasons the constants CHAR_TYPE, INT_TYPE, and REAL_TYPE
are in @EXPORT instead of @EXPORT_OK. This means, that you always have
them imported into your namespace. I consider it a bug, but not such a
serious one, that I intend to break old programs by moving them into
EXPORT_OK.

Displaying whole tables in one go
---------------------------------

   A handy method to show the complete contents of a statement handle is
the as_string method. This works similar to the msql monitor with a few
exceptions:

the width of a column
     is calculated by examining the width of all entries in that column

control characters
     are mapped into their backslashed octal representation

backslashes
     are doubled (`\\ instead of \')

numeric values
     are adjusted right (both integer and floating point values)

   The differences are illustrated by the following table:

   Input to msql (a real carriage return here replaced with ^M):

     CREATE TABLE demo (
       first_field CHAR(10),
       second_field INT
     ) \g

     INSERT INTO demo VALUES ('new
     line',2)\g
     INSERT INTO demo VALUES ('back\\slash',1)\g
     INSERT INTO demo VALUES ('cr^Mcrnl
     nl',3)\g

   Output of msql:

     +-------------+--------------+
     | first_field | second_field |
     +-------------+--------------+
     | new
         line    | 2            |
     | back\slash  | 1            |
         crnlr
         nl  | 3            |
     +-------------+--------------+

   Output of pmsql:

     +----------------+------------+
     |first_field     |second_field|
     +----------------+------------+
     |new\012line     |           2|
     |back\\slash     |           1|
     |cr\015crnl\012nl|           3|
     +----------------+------------+

Version information
-------------------

   The version of Msql and Mysql is always stored in $Msql::VERSION or
$Mysql::VERSION as it is perl standard.

   The mSQL API implements methods to access some internal configuration
parameters: gethostinfo, getserverinfo, and getprotoinfo.  All three are
available both as class methods or via a database handle. But under no
circumstances they are associated with a database handle. All three return
global variables that reflect the last connect() command within the
current program. This means, that all three return empty strings or zero
before the first call to connect().

   This situation is better with MySQL: The methods are valid only in
connection with a database handle.

Administration
--------------

   shutdown, createdb, dropdb, reloadacls are all accessible via a
database handle and implement the corresponding methods to what msqladmin
does.

   The mSQL and MySQL engines do not permit that these commands are
invoked by users without sufficient privileges. So please make sure to
check the return and error code when you issue one of them.

     $rc = $dbh->shutdown();
     $rc = $dbh->createdb($database);
     $rc = $dbh->dropdb($database);

   It should be noted that database deletion is *not prompted for* in any
way. Nor is it undo-able from within Perl.

     B<Once you issue the dropdb() method, the database will be gone!>

   These methods should be used at your own risk.

StudlyCaps
----------

   Real Perl Programmers (C) usually don't like to type ListTables but
prefer list_tables or *listtables*. The mSQL API uses StudlyCaps
everywhere and so did early versions of MsqlPerl. Beginning with $VERSION
1.06 all methods are internally in lowercase, but may be written however
you please. Case is ignored and you may use the underline to improve
readability.

   The price for using different method names is neglectible. Any method
name you use that can be transformed into a known one, will only be
defined once within a program and will remain an alias until the program
terminates. So feel free to run fetch_row or connecT or ListDBs as in your
old programs. These, of course, will continue to work.

PREREQUISITES
=============

   mSQL is a database server and an API library written by David Hughes.
To use the adaptor you definitely have to install these first.

   MySQL is a libmysqlclient.a library written by Michael Widenius This
was originally inspired by MySQL.

AUTHOR
======

   andreas koenig `koenig@franz.ww.TU-Berlin.DE'

SEE ALSO
========

   Alligator Descartes wrote a database driver for Tim Bunce's DBI. I
recommend anybody to carefully watch the development of this module
(`DBD::mSQL'). Msql is a simple, stable, and fast module, and it will be
supported for a long time. But it's a dead end. I expect in the medium
term, that the DBI efforts result in a richer module family with better
support and more functionality. Alligator maintains an interesting page on
the DBI development: http://www.arcana.co.uk/technologia/perl/DBI

Relational Database Management System for Msql
**********************************************

NAME
====

   *Msql::RDBMS* - Relational Database Management System for Msql

SYNOPSIS
========

     use Msql::RDBMS;

     $rdbms = new Msql::RDBMS;
     $rdbms->show;

DESCRIPTION
===========

   This is a fully catalog driven database management system for Perl 5
and mini-SQL. You should use it in conjunction with the sqldef.pl script
which will generate data definition language for your tables.

GENERATING DATA DEFINITION LANGUAGE
===================================

   You must pass the name of a schema definition file to sqldef.pl (an
example, *schema.def*, is included in the examples/ subdirectory of the
distribution).  See `sqldef.pl' in this node.

USAGE
=====

   You can call up the entire Relational Database Management System from
your browser with a URL like this:

     http://bozos.on.the.bus/sample.cgi?db=demo

   Where *sample.cgi* is a Perl script containing the three lines of code
shown in SYNOPSIS.

DEBUGGING
=========

   You can get some debugging information, which consists of a CGI::dump,
and an SQL statement, if relevant, by including debug=1 in the URL.

TODO
====

     Generate forms for interactive data definition.
     Enforce referential integrity (cascade/block deletes).
     * Enforce uniqueness for label columns.
     * Add fancy display options that support automagic hyperlinking of
        URLs and email addresses.

   * denotes feature present in the original PHP/FI version.

AUTHOR
======

   Brian Jepson <bjepson@conan.ids.net>

   Paul Sharpe <paul@miraclefish.com>

   You may distribute this under the same terms as Perl itself.

SEE ALSO
========

   `sqldef.pl' in this node

   CGI::CGI, CGI::Carp, Msql

error()
     The error handling method will handle errors in two ways.  The first
     is to pass it no values whatsoever; it will check the mini-SQL
     connection for errors, and register any error that is found with the
     list of errors for this form. The second way to use this is to pass
     in a user-defined error, which will be registered in the list of
     errors, but this will not check the mini-SQL connection for errors.
     This is a good method to invoke after any SQL call; it returns true
     if there was an error, and all errors will get displayed when you
     invoke display_page().

errors()
     This method displays all of the errors in the list of errors. Each
     error is displayed in a threatening red color. This is normally
     called by display_page(), but if you want to annoy your users, you
     should call it as often as possible.

printbuff()
     Adds some text to the HTML buffer.

MySQL::GUI     makes windows for connecting to and interacting with databases.
******************************************************************************

NAME
====

   MySQL::GUI     makes windows for connecting to and interacting with
databases.

SYNOPSIS
========

     use MySQL::GUI;

     my $gui = new MySQL::GUI;

     $gui->go;

AUTHOR
======

   Jettero Heller jettero@cpan.org

   http://www.voltar.org

SEE ALSO
========

   perl(1), MySQL::GUI(3), MySQL::GUI::connector(3),
MySQL::GUI::connector::dbase(3), MySQL::GUI::connection(3).

MySQL::GUI::connection   a window for interacting with the database.
********************************************************************

NAME
====

   MySQL::GUI::connection   a window for interacting with the database.

SYNOPSIS
========

     use strict;
     use MySQL::GUI::connector;
     use MySQL::GUI::connection;

     my $connector = new MySQL::GUI::connector;
     my $c;

     $connector->set_callback( \&connected_callback );

     show $connector;

     sub connected_callback {
         my $dbo = shift;

     if($dbo) {
         $connector->print("I got connected!", 2);
         $c = new MySQL::GUI::connection($dbo);
     }
       }

     sub submit_callback {
         my $dbqt = shift; # passed in by the callback
         # short for database query text

     if($dbqt =~ /^(select|show|desc)/i) {
         my $q  = $c->ready($dbqt); $q->execute or return;
         my $hr = $q->fetchrow_hashref;

     return if not $hr;

     $c->set_field_names( keys %$hr );
     $c->freeze;  # puts the CList on hold
                  # so it doesn't blink during the updates.

     my @row;
     my $max_rows = 50;
     {
         foreach(@row) {
             $_ = defined($_) ? $_ : "NULL";
             s/^\s*//;
             s/\s*$//;
         }
         $c->populate_table_row( values %$hr );
         $max_rows--;

     last if not $max_rows;
     redo if $hr = $q->fetchrow_hashref;
               }
               $c->thaw;
               $c->set_field_widths( (map 10*length($_), (keys %$hr)) );

     $c->store_query;
     $c->clear_query;

     my $paren="";
     if(not $max_rows) {
         $paren = " (truncated to $ROW_LIM rows)";
     }

     $c->print("found " . $q->rows . " rows$paren... " . (time - $t) , 10);
           } else {
     $c->print("unsupported query type", 4);
           }
       }

AUTHOR
======

     Jettero Heller <jettero@voltar.org>

SEE ALSO
========

   perl(1), MySQL::GUI(3), MySQL::GUI::connector(3),
MySQL::GUI::connector::dbase(3), MySQL::GUI::connection(3).

MySQL::GUI::connector   a window for connecting to databases.
*************************************************************

NAME
====

   MySQL::GUI::connector   a window for connecting to databases.

SYNOPSIS
========

     use strict;
     use MySQL::GUI::connector;

     my $connector = new MySQL::GUI::connector;

     $connector->set_callback( \&connected_callback );

     show $connector;

     sub connected_callback {
         my $dbo = shift;
         my $tsp = 2; # two second pause

     $connector->print("I got connected!", $tsp) if $dbo;
       }

     $connector->exit;

AUTHOR
======

     Jettero Heller <jettero@voltar.org>

SEE ALSO
========

   perl(1), MySQL::GUI(3), MySQL::GUI::connector(3),
MySQL::GUI::connector::dbase(3), MySQL::GUI::connection(3).

Perl extension    to make the db stuff a little less painless.
**************************************************************

NAME
====

   MySQL::GUI::connector::dbase - Perl extension   to make the db stuff a
little less painless.

SYNOPSIS
========

     use strict;
     use MySQL::GUI::connector::dbase;

     # to do db transactions
     my $dbo = new MySQL::GUI::connector::dbase;
     my $dbh = $dbo->handle;
     my $sth = $dbh->prepare("select * from something");
     my $STH = $dbo->ready("select * from something"); # shortcut. ;)

     # the dbase.pm uses the .my.cnf to be able to connect pretty like that...
     # you can override it.  After the $dbo is connected this will
     # not do anything!  Note that there is no connect function.

     $dbo->disconnect;

     $dbo->set_db(   "cool_db"   );
     $dbo->set_host( "localhost" );
     $dbo->set_user( "jettero"   );
     $dbo->set_pass( "S3crET"    );

     my $sth =
         $dbo->ready("select * from cool_table");  # this connects automajikcally;
                                               # so does the $dbo->handle function.

     $dbo->trace( 1 ); # will do what you expect before/after connect,
                       # and will persist even after a $dbo->disconnect.

     # to read a .my.cnf
     my $temp = new MySQL::GUI::connector::dbase;
     my ($u, $p, $d, $h) = $temp->get_defaults;
     undef $temp;

AUTHOR
======

     Jettero Heller <jettero@voltar.org>

SEE ALSO
========

   perl(1), MySQL::GUI(3), MySQL::GUI::connector(3),
MySQL::GUI::connector::dbase(3), MySQL::GUI::connection(3).

Perl interfaces to the mSQL and mysql databases
***********************************************

NAME
====

   Msql / Mysql - Perl interfaces to the mSQL and mysql databases

SYNOPSIS
========

     use Msql;

     $dbh = Msql->connect;
     $dbh = Msql->connect($host);
     $dbh = Msql->connect($host, $database);

     or

     use Mysql;

     $dbh = Mysql->connect(undef, $database, $user, $password);
     $dbh = Mysql->connect($host, $database, $user, $password);

     $dbh->selectdb($database);

     @arr = $dbh->listdbs;
     @arr = $dbh->listtables;

     $quoted_string = $dbh->quote($unquoted_string);
     $error_message = $dbh->errmsg;
     $error_number = $dbh->errno;   # MySQL only

     $sth = $dbh->listfields($table);
     $sth = $dbh->query($sql_statement);

     @arr = $sth->fetchrow;
     @arr = $sth->fetchcol($col_number);
     %hash = $sth->fetchhash;

     $sth->dataseek($row_number);

     $sth->as_string;

     @indices = $sth->listindices                   # only in mSQL 2.0
     @arr = $dbh->listindex($table,$index)          # only in mSQL 2.0
     ($step,$value) = $dbh->getsequenceinfo($table) # only in mSQL 2.0

     $rc = $dbh->shutdown();
     $rc = $dbh->createdb($database);
     $rc = $dbh->dropdb($database);

DESCRIPTION
===========

   This package is designed as close as possible to its C API counterpart.
The manual that comes with mSQL or MySQL describes most things you need.
Due to popular demand it was decided though, that this interface does not
use StudlyCaps (see below).

   The version you have selected is an adaption still under development,
please consult the file "Changes" in your distribution.

   Internally you are dealing with the two classes `Msql' and
`Msql::Statement' or `Mysql' and `Mysql::Statement', respectively.  You
will never see the latter, because you reach it through a statement handle
returned by a query or a listfields statement. The only class you name
explicitly is Msql or Mysql. They offer you the connect command:

     $dbh = Msql->connect;
     $dbh = Msql->connect($host);
     $dbh = Msql->connect($host, $database);

     or

     $dbh = Mysql->connect(undef, undef, $user, $password);
     $dbh = Mysql->connect($host, undef, $user, $password);
     $dbh = Mysql->connect($host, $database, $user, $password);

   This connects you with the desired host/database. With no argument or
with an empty string as the first argument it connects to the UNIX socket,
which has a much better performance than the TCP counterpart. A database
name as the second argument selects the chosen database within the
connection. The return value is a database handle if the connect succeeds,
otherwise the return value is undef.

   You will need this handle to gain further access to the database.

     $dbh->selectdb($database);

   If you have not chosen a database with the connect command, or if you
want to change the connection to a different database using a database
handle you have got from a previous connect, then use selectdb.

     $sth = $dbh->listfields($table);
     $sth = $dbh->query($sql_statement);

   These two work rather similar as descibed in the mSQL or MySQL manual.
They return a statement handle which lets you further explore what the
server has to tell you. On error the return value is undef. The object
returned by listfields will not know about the size of the table, so a
numrows() on it will return the string "N/A";

     @arr = $dbh->listdbs();
     @arr = $dbh->listtables;

   An array is returned that contains the requested names without any
further information.

     @arr = $sth->fetchrow;

   returns an array of the values of the next row fetched from the server.
Similar does

     %hash = $sth->fetchhash;

   return a complete hash. The keys in this hash are the column names of
the table, the values are the table values. Be aware, that when you have a
table with two identical column names, you will not be able to use this
method without trashing one column. In such a case, you should use the
fetchrow method.

     @arr = $sth->fetchcol($colnum);

   returns an array of the values of each row for column $colnum.  Note
that this reads the entire table and leaves the row offset at the end of
the table; be sure to use $sth->dataseek() to reset it if you want to
re-examine the table.

     $sth->dataseek($row_number);

   lets you specify a certain offset of the data associated with the
statement handle. The next fetchrow will then return the appropriate row
(first row being 0).

No close statement
------------------

   Whenever the scalar that holds a database or statement handle loses its
value, Msql chooses the appropriate action (frees the result or closes the
database connection). So if you want to free the result or close the
connection, choose to do one of the following:

undef the handle
use the handle for another purpose
let the handle run out of scope
exit the program.
Error messages
--------------

   Both drivers, Msql and Mysql implement a method ->errmsg(), which
returns a textual error message. Mysql additionally supports a method
->errno returning the corresponding error number. Note that Msql's errmsg
is a static method, thus it is legal to fetch

     Msql->errmsg();

   Mysql doesn't support this, fetching the error message is only valid via

     $dbh->errmsg();

   I recommend, that even Msql users restrict themselves to the latter for
portability reasons. There are also global variables $Msql::db_errstr and
$Mysql::db_errstr, which always hold the last error message. The former is
reset with the next executed command, the latter not. Usually there's no
need for accessing the global variables, with one exception: If the
connect method fails, you need them.

The -w switch
-------------

   With Msql and Mysql the -w switch is your friend! If you call your perl
program with the -w switch you get the warnings from ->errmsg on STDERR.
This is a handy method to get the error messages from the msql server
without coding it into your program.

   If you want to know in greater detail what's going on, set the
environment variables that are described in David's manual. David's
debugging aid is excellent, there's nothing to be added.

   If you want to use the -w switch but do not want to see the error
messages from the msql daemon, you can set the variables $Msql::QUIET or
$Mysql::QUIET to some true value, and they will be supressed.

->quote($str [, $length])
-------------------------

   returns the argument enclosed in single ticks (") with any special
character escaped according to the needs of the API.

   For mSQL this means, any single tick within the string is escaped with
a backslash and backslashes are doubled. Currently (as of msql-1.0.16) the
API does not allow to insert NUL's (ASCII 0) into tables. The quote method
does not fix this deficiency.

   MySQL allows NUL's or any other kind of binary data in strings. Thus
the quote method will additionally escape NUL's as \0.

   If you pass undefined values to the quote method, it returns the string
NULL.

   If a second parameter is passed to quote, the result is truncated to
that many characters.

NULL fields
-----------

   NULL fields in tables are returned to perl as undefined values.

Metadata
--------

   Now lets reconsider the above methods with regard to metadata.

Database Handle
---------------

   As said above you get a database handle with

     $dbh = Msql->connect($host, $database);

     or

     $dbh = Mysql->connect($host, $database);

   The database handle knows about the socket, the host, and the database
it is connected to.

   You get at the three values with the methods

     $scalar = $dbh->sock;
     $scalar = $dbh->host;
     $scalar = $dbh->database;

   Mysql additionally supports

     $scalar = $dbh->user;
     $scalar = $dbh->sockfd;

   where the latter is the file descriptor of the socket used by the
database connection. This is the same as $dbh->sock for mSQL.

Statement Handle
----------------

   Two constructor methods return a statement handle:

     $sth = $dbh->listfields($table);
     $sth = $dbh->query($sql_statement);

   $sth knows about all metadata that are provided by the API:

     $scalar = $sth->numrows;
     $scalar = $sth->numfields;

     @arr  = $sth->table;       the names of the tables of each column
     @arr  = $sth->name;        the names of the columns
     @arr  = $sth->type;        the type of each column, defined in msql.h
     	                     and accessible via Msql::CHAR_TYPE,
     	                     &Msql::INT_TYPE, &Msql::REAL_TYPE or
                                &Mysql::FIELD_TYPE_STRING,
                                &Mysql::FIELD_TYPE_LONG, ...
     @arr  = $sth->isnotnull;   array of boolean
     @arr  = $sth->isprikey;    array of boolean
     @arr  = $sth->isnum;       array of boolean
     @arr  = $sth->length;      array of the possibble maximum length of each
                                field in bytes
     @arr  = $sth->maxlength;   array of the actual maximum length of each field
                                in bytes. Be careful when using this attribute
                                under MsqlPerl: The server doesn't offer this
                                attribute, thus it is calculated by fetching
                                all rows. This might take a long time and you
                                might need to call $sth->dataseek.

   Mysql additionally supports

     $scalar  = $sth->affectedrows  number of rows in database affected by query
     $scalar  = $sth->insertid      the unique id given to a auto_increment field.
     $string  = $sth->info()        more info from some queries (ALTER TABLE...)
     $arrref  = $sth->isblob;       array of boolean

   The array methods (table, name, type, is_not_null, is_pri_key, length,
affected_rows, is_num and blob) return an array in array context and an
array reference (see Perlref (perl.info), and `perlldsc' in
this node for details) when called in a scalar context. The scalar context
is useful, if you need only the name of one column, e.g.

     $name_of_third_column = $sth->name->[2]

   which is equivalent to

     @all_column_names = $sth->name;
     $name_of_third_column = $all_column_names[2];

New in mSQL 2.0
---------------

   The query() function in the API returns the number of rows affected by
a query. To cite the mSQL API manual, this means...

     If the return code is greater than 0, not only does it imply
     success, it also indicates the number of rows "touched" by the query
     (i.e. the number of rows returned by a SELECT, the number of rows
     modified by an update, or the number of rows removed by a delete).

   As we are returning a statement handle on selects, we can easily check
the number of rows returned. For non-selects we behave just the same as
mSQL-2.

   To find all indices associated with a table you can call the
`listindices()' method on a statement handle. To find out the columns
included in an index, you can call the `listindex($table,$index)' method
on a database handle.

   There are a few new column types in mSQL 2. You can access their
numeric value with these functions defined in the Msql package:
IDENT_TYPE, NULL_TYPE, TEXT_TYPE, DATE_TYPE, UINT_TYPE, MONEY_TYPE,
TIME_TYPE, IDX_TYPE, SYSVAR_TYPE.

   You cannot talk to a 1.0 server with a 2.0 client.

   You cannot link to a 1.0 library and to a 2.0 library *at the same
time*. So you may want to build two different Msql modules at a time, one
for 1.0, another for 2.0, and load whichever you need. Check out what the
-I switch in perl is for.

   Everything else seems to remain backwards compatible.

@EXPORT
-------

   For historical reasons the constants CHAR_TYPE, INT_TYPE, and REAL_TYPE
are in @EXPORT instead of @EXPORT_OK. This means, that you always have
them imported into your namespace. I consider it a bug, but not such a
serious one, that I intend to break old programs by moving them into
EXPORT_OK.

Displaying whole tables in one go
---------------------------------

   A handy method to show the complete contents of a statement handle is
the as_string method. This works similar to the msql monitor with a few
exceptions:

the width of a column
     is calculated by examining the width of all entries in that column

control characters
     are mapped into their backslashed octal representation

backslashes
     are doubled (`\\ instead of \')

numeric values
     are adjusted right (both integer and floating point values)

   The differences are illustrated by the following table:

   Input to msql (a real carriage return here replaced with ^M):

     CREATE TABLE demo (
       first_field CHAR(10),
       second_field INT
     ) \g

     INSERT INTO demo VALUES ('new
     line',2)\g
     INSERT INTO demo VALUES ('back\\slash',1)\g
     INSERT INTO demo VALUES ('cr^Mcrnl
     nl',3)\g

   Output of msql:

     +-------------+--------------+
     | first_field | second_field |
     +-------------+--------------+
     | new
         line    | 2            |
     | back\slash  | 1            |
         crnlr
         nl  | 3            |
     +-------------+--------------+

   Output of pmsql:

     +----------------+------------+
     |first_field     |second_field|
     +----------------+------------+
     |new\012line     |           2|
     |back\\slash     |           1|
     |cr\015crnl\012nl|           3|
     +----------------+------------+

Version information
-------------------

   The version of Msql and Mysql is always stored in $Msql::VERSION or
$Mysql::VERSION as it is perl standard.

   The mSQL API implements methods to access some internal configuration
parameters: gethostinfo, getserverinfo, and getprotoinfo.  All three are
available both as class methods or via a database handle. But under no
circumstances they are associated with a database handle. All three return
global variables that reflect the last connect() command within the
current program. This means, that all three return empty strings or zero
before the first call to connect().

   This situation is better with MySQL: The methods are valid only in
connection with a database handle.

Administration
--------------

   shutdown, createdb, dropdb, reloadacls are all accessible via a
database handle and implement the corresponding methods to what msqladmin
does.

   The mSQL and MySQL engines do not permit that these commands are
invoked by users without sufficient privileges. So please make sure to
check the return and error code when you issue one of them.

     $rc = $dbh->shutdown();
     $rc = $dbh->createdb($database);
     $rc = $dbh->dropdb($database);

   It should be noted that database deletion is *not prompted for* in any
way. Nor is it undo-able from within Perl.

     B<Once you issue the dropdb() method, the database will be gone!>

   These methods should be used at your own risk.

StudlyCaps
----------

   Real Perl Programmers (C) usually don't like to type ListTables but
prefer list_tables or *listtables*. The mSQL API uses StudlyCaps
everywhere and so did early versions of MsqlPerl. Beginning with $VERSION
1.06 all methods are internally in lowercase, but may be written however
you please. Case is ignored and you may use the underline to improve
readability.

   The price for using different method names is neglectible. Any method
name you use that can be transformed into a known one, will only be
defined once within a program and will remain an alias until the program
terminates. So feel free to run fetch_row or connecT or ListDBs as in your
old programs. These, of course, will continue to work.

PREREQUISITES
=============

   mSQL is a database server and an API library written by David Hughes.
To use the adaptor you definitely have to install these first.

   MySQL is a libmysqlclient.a library written by Michael Widenius This
was originally inspired by MySQL.

AUTHOR
======

   andreas koenig `koenig@franz.ww.TU-Berlin.DE'

SEE ALSO
========

   Alligator Descartes wrote a database driver for Tim Bunce's DBI. I
recommend anybody to carefully watch the development of this module
(`DBD::mSQL'). Msql is a simple, stable, and fast module, and it will be
supported for a long time. But it's a dead end. I expect in the medium
term, that the DBI efforts result in a richer module family with better
support and more functionality. Alligator maintains an interesting page on
the DBI development: http://www.arcana.co.uk/technologia/perl/DBI

Tied access to ndbm files
*************************

NAME
====

   NDBM_File - Tied access to ndbm files

SYNOPSIS
========

     use NDBM_File;
     use Fcntl;       # for O_ constants

     tie(%h, 'NDBM_File', 'Op.dbmx', O_RDWR|O_CREAT, 0640);

     untie %h;

DESCRIPTION
===========

   See `tie', see Perlfunc (perl.info), `tie', see
Perldbmfilter (perl.info),

Perl module implementing a NIS daemon.
**************************************

NAME
====

   NIS::DBM - Perl module implementing a NIS daemon.

SYNOPSIS
========

     use NIS::DBM;

DESCRIPTION
===========

   NIS::DBM trivializes the implementation of daemons and other scripts
which maintain the NIS databases by presenting them as a hash keyed by
both username and user id.  If a numeric username exists in the byname
databases, the number associated with that username will be used as the
user id.  This is the same behavior as chown and *chgrp*.

   NIS::DBM maintains three caches of information to construct an accurate
view of the NIS databases as modified by the program.  The caches are for
actual records from the database, modifications to the database, and
deletions from the database.  The caches have the following precedence:
deletions, modifications, and general cache.  The caches may be flushed to
the database files at any time or upon object destruction.

NIS::DBM API
============

NIS::DBM constructor
     This will construct a new NIS::DBM object.  The arguments may be given
     in a variaty of ways:

          tie %nis, NIS::DBM, ( 'config filename' );
          tie %nis, NIS::DBM, ( { config_file => 'filename',
                                  sections   => [ 'sec1', ... ],
                                  default_keys => { keys1 => value1, ... },
                                  required_keys => [ key1, key2, ... ]
                                } );
          tie %nis, NIS::DBM, ( config_file => 'filename',
                                sections   => [ 'sec1', ... ],
                                default_keys => { keys1 => value1, ... },
                                required_keys => [ key1, key2, ... ]
                                );
          tie %nis, NIS::DBM, ( filename => '/path/to/conf/file'
                                program_tag => 'string'
                                defaults => { keys1 => value1, ... },
                                required => [ key1, key2, ... ]
                                );

FETCH
     Given a username or user id, FETCH will return the NIS record as a
     hash reference.  FETCH will first consult any caches maintained by the
     tied object to provide current information that may not be available
     in the database files.

STORE
     Given a username or user id, STORE will make any modifications to the
     caches necessary for the databases to reflect the changes when
     flushed.  These same chaches are consulted by FETCH.

DELETE
     Given a username or user id, DELETE marks the record for deletion.
     The record is not available for FETCHing or testing for *EXIST*ance.

CLEAR
     This is called when the hash is assigned an empty hash or array.  This
     function is not implemented.  You cannot remove the NIS user databases
     using this module.

EXISTS
     Given a username or user id, will return true if the key exists in the
     modification, addition, or general cache or in the actual database.
     Will return false regardless of the existance in any database or
     cache if the record is marked for deletion.

FIRSTKEY
     This function will initialize an array of keys and return the first.
     The keys are unordered.

NEXTKEY
     This function will return the next key in the array of keys.

DESTROY
     Flushes any changes in the chaches to the database files and closes
     them.  This behavior may be overridden by the *set_option(FLUSH=*0)>
     method.

get_options
     Returns a list of options currently set for the object.

get_option
     Given a key, returns the value of the option.

set_option
     Given a key/value pair, sets the option to the value.  The following
     options are currently used:

flush
     If FLUSH is set, any changes in the caches will be written out to the
     database files.  The caches will be cleared after a flush if data is
     actually written.

OPTIONS
=======

CLOBBER
          0 -> databases are read only
          1 -> STORE but not DELETE
          2 -> STORE and DELETE enabled

FLUSH
          0 -> do not flush changes from the caches to the databases
          1 -> flush changes from the caches to the databases
               (by either the flush or DESTROY methods)

PUSH
          0 -> do not push changes to other machines
          1 -> push changes if needed to other machines

key_set
     If this is set to either *byuid* or byname then only the keys in the
     respective files (i.e., uids or usernames) are available as keys.
     Otherwise, the default behavior is to assume username first and uid
     last.

name_db_files
uid_db_files
use_adjunct
     If this is set, the difference between adjunct and non-adjunct files
     is recognized.  Otherwise, the normal NIS behavior is used.  If a
     file is in the list of dbm files with the string `adjunct' in the
     name, then the preparation phase of tieing the hash to the dbm files
     will set this flag.

yp_top
yp_src
yp_push_cmd
IDIOMS
======

   The following are some idioms using the NIS::DBM tied hash.  The
username and user id are available via $username and $uid respectively.

Delete User
          my $userinfo = $nishash{$username || $uid};
          delete $nishash{$$userinfo{'username'}};
          delete $nishash{$$userinfo{'uid'}};

Change User's Username
          my $userinfo = $nishash{$username || $uid};
          delete $nishash{$$userinfo{'username'}};
          $$userinfo{'username'} = $new_username;
          $$nishash{$new_username} = $userinfo;
          $$nishash{$$userinfo{'uid'}} = $userinfo;

Change User's UID
          my $userinfo = $nishash{$username || $uid};
          delete $nishash{$$userinfo{'uid'}};
          $$userinfo{'username'} = $new_uid;
          $$nishash{$new_uid} = $userinfo;
          $$nishash{$$userinfo{'username'}} = $userinfo;

Add New User
          my $userinfo = { username => $username,
                           uid      => $uid,
                           gid      => $gid,
                           gecos    => $gecos,
                           home     => $home,
                           shell    => $shell,
                           password => crypt($password, $salt)
                         };
          $nishash{$username} = $userinfo;
          $nishash{$uid} = $userinfo;

AUTHORS
=======

   James G. Smith, <jgsmith@tamu.edu> Philip C. Kizer, <pckizer@tamu.edu>

COPYRIGHT
=========

   Copyright (c) 1999, Texas A&M University.  All rights reserved.

   Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

     1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
     2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
     3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTERS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

SEE ALSO
========

   perl(1), Net::NIS(3).

a minimal NNTP server
*********************

NAME
====

   NNML::Server - a minimal NNTP server

SYNOPSIS
========

     perl -MNNML::Server -e server
     perl -MNNML::Server -e unspool

DESCRIPTION
===========

   *NNML::Server* server implements a minimal NNTP server. It is (hope-)
fully conformant to rfc977. In addition the commands `XOVER' and
`AUTHINFO' are implemented.

   Supported commands:

     ARTICLE, AUTHINFO, BODY, GROUP, HEAD, HELP, IHAVE, LAST, LIST,
     MODE, NEWGROUPS, NEWNEWS, NEXT, POST, QUIT, SLAVE, STAT

     XOVER, XHDR, LIST NEWSGROUPS ng-spec

     The main reason for writing this was to synchronize my mail directories
     across different hosts. The Mail directories are MH-Style with a F<.overview>
     file in each folder and an F<active> file in the base
     directory. These are maintained by the B<Emacs> B<Gnus> backend
     B<NNML>. To get started, you can generate/update this files using the
     B<overview> program. Upon C<POST> and C<IHAVE> commands this files
     will also be updated.

   To start from scratch use:

     touch /tmp/active;
     perl -MNNML::Server -e 'server(base => "/tmp", port => 3000)'

   To export your mh-Mail use:

     perl overview -base ~/Mail
     perl -MNNML::Server -e 'server(base => "$ENV{HOME}/Mail", port => 3000)'

   The command POST and *IHAVE* honour the `Newsgroups' header if not
overwritten by the `X-Nnml-Groups' header. Articles will contain an
appropriate `X-Nnml-Groups' header when retrieved by message-id.

   When the client submits the `SLAVE' command, all forther post requests
are spooled in `$Config-'spool> (usually `~/Mail/NNML.spool') for
performance reasons. You can process the spooled articles by submitting
the `XUNSPOOL' command or by calling

     perl -MNNML::Server -e unspool

   Rejected articles will be saven in `$Config-'bad> (usually
`~/Mail/NNML.bad')

AUTHORIZATION
=============

   To enable access restrictions use:

     perl -MNNML::Auth -e "NNML::Auth::add_user($ENV{LOGANME}, 'passwd', \
       'read', 'write', 'admin')"

   If base`/passwd' exists, three levels of authorization are recognized:

admin
     Users with permission admin may shut down the server using `SHUT'.
     Also these users may create new groups simply by posting to them.
     Permission admin is also required for the `XUNSPOOL' command.

write
     Users with permission write may use the POST and *IHAVE* commands.

read
     All other commands require the read permission.

FEATURES
========

   Version 1.06 implements the `MODE GZIP' command. After submiting this
commands, all articles, heads and bodies will be piped through `gzip -cf |
mimencode'. The server will recognize post requeste using the same pipe
automatically. This will speed up *nnmirror* if the line is sufficiant
slow.

BUGS
====

   The server handles multiple connections in a single thread. So a hung
POST or `IHAVE' would block all connections. Therfore a post request is
interrupted if the server could not read any bytes for 30 seconds. The
Client is notified by message 441. If the client continues to send the
article, it is interpreted by the command loop.

SEE ALSO
========

   The overview(1) and *nnmirror*(1) manpages.

AUTHOR
======

   Ulrich Pfeifer <`pfeifer@ls6.informatik.uni-dortmund.de'>

Perl extension for non-vivifying exists and defined functions
*************************************************************

NAME
====

   NVDefined - Perl extension for non-vivifying exists and defined
functions

SYNOPSIS
========

     use NVDefined;

     ...

     if (NVExists(\%hash, qw(key1 key2 ... keyn ))) {
         ...
     }

     if (NVDefined(\%hash, qw(key1 key2 ... keyn))) {
         ...
     }

DESCRIPTION
===========

   This module has been superseded by Hash::NoVivify, qv.

AUTHOR
======

   Brent B. Powers (B2Pi), Powers@B2Pi.com

   Copyright(c) 1999 Brent B. Powers. All rights reserved. This program is
free software, you may redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   perl(1), perlfunc(1).

   Net::AIM - Perl extension for AOL Instant Messenger TOC protocol

SYNOPSIS
========

     use Net::AIM;

     $aim = new Net::AIM;
     $conn = $aim->newconn(Screenname   => 'Perl AIM',
                           Password     => 'ilyegk');
     $aim->start;

DESCRIPTION
===========

   This module implements an OO interface to the Aol Instant Messenger TOC
protocol.

   This version contains not much more than hacked code that merely
connects to the aol TOC servers and acts on instant messages.

METHODS
=======

Net::AIM->new()
     This is the Net::AIM constructor.  No arguments needed.

$aim->debug($debug)
     Set whether to print DEBUGGING information to STDERRR.  Accepts
     $debug which should be a boolean value.

$aim->set($key, $val)
     This method is simply sets $key to $val in an internal hash for
     variables

$aim->get($key)
     This method is simply gets the value of $key from the  internal hash

$aim->newconn()
     This method creates a new AIM::Connection object

$aim->getconn()
     This method returns a pointer to the AIM::Connection object

$aim->do_one_loop()
     This executes one read off the socket.

$aim->start()
     This just starts an infinte loop of $aim->do_one_loop;

$aim->timeout($secs);
     This sets or returns the current timeout in seconds for the select
     loop.  Takes 1 optional argument.  Fractional timeout values are ok.

$aim->add_buddy($send_bool, $group, @buddies);
     This adds @buddies to your buddy list, under the group $group.  if
     $send_bool evaluates to TRUE then the toc_add_buddy command is sent
     to the server.  Otherwise it is not sent out.  This function will
     also save the list internally.

$aim->add_permit($send_bool, $group, @buddies);
     This adds @buddies to your permit list, under the group $group.  if
     $send_bool evaluates to TRUE then the toc_add_permit command is sent
     to the server.  Otherwise it is not sent out.  This function will
     also save the list internally.

$aim->add_deny($send_bool, $group, @buddies);
     This adds @buddies to your deny list, under the group $group.  if
     $send_bool evaluates to TRUE then the toc_add_deny command is sent to
     the server.  Otherwise it is not sent out.  This function will also
     save the list internally.

$aim->remove_buddy($send_bool, $group, @buddies);
     This removes @buddies from your buddy list. $group must be the group
     they were orginally set with for them to be deleted from the internal
     $aim memory and prevent them from getting added again incase a
     set_config method is called.

     if $send_bool evaluates to TRUE then the toc_add_deny command is sent
     to the server.  Otherwise it is not sent out.  This function will
     also save the list internally.

$aim->set_idle($idle_time)
     This method sets our idle time to `$idle_time'.  If $idle_time is
     omitted it will be set to 0.

$aim->get_info($screen_name)
     Sends an info request to the server for $screen_name. The server
     should reply with a URL which will contain the info requested about
     the user.

$aim->set_info($info)
     This method sets your info or profile information to $info on the
     server.

$aim->evil($user, $anon)
     Warn `$screen_name'.  `$anon': boolean value which will determine
     whether to warn the user anonymously or normally.  Anonymous warnings
     are less severe.

$aim->send($message)
     Send $message to the server.  This is used internally by other
     functions to send commands to the server.

          $aim->send('toc_add_buddy perlaim')

$aim->chat_invite($room, $msg, @buddies)
     Invite @buddies to $room with the message $msg

$aim->chat_accept($room_id)
     This will accept an invitation that was sent to us for $room_id

$aim->chat_leave($room_id)
     This method instructs the server to take you out of the room $room_id

$aim->chat_whisper($room_id,$user,$msg)
     Whisper $msg to $user in the room $room_id

$aim->chat_send($room_id, $message)
     Send $message in chat room $room_id

$aim->chat_join($roomname)
     Send a request to enter the room $roomname

$aim->send_im($screen_name, $message)
     This method sends `$message' to `$screen_name'.

$aim->list_rooms();
     This method returns an @array of rooms each consisting of
     ID:ROOM_NAME. For instance:    '235236:Perl AIM Chat12'
     '234323:Perl AIM Chat13'    '235832:Perl AIM Chat14'    '125082:Perl
     AIM Chat15'

$aim->get_roomname($id)
     This method returns the name of the room with id $id.

$aim->set_roomname($id, $roomname)
     This saves $roomname in the $aim object in a %hash keyed on $id.

$aim->del_roomname($id)
     Deletes $id and it's associate value from our roomname hash in $aim

$aim->encode($str)
     This method returns $str encoded as per the TOC specs: escaped
     special chars ({}[]$) and enclosed in quotes (")

$aim->send_config()
     This method instructs the module to send our configurations which are
     the mode (permit/deny/all) and our buddy list to the server and to
     set it as our saved config on the server

$aim->send_buddies()
     This method instructs the module to send all our current buddies to
     the AOL server.

$set_config_str($config_str, add_bool)
     This parses a config string of the form:       g Buddies       p
     permit1       p permit2       d deny1       d deny2       b budd1
      b budd2

     Key:     g - Buddy Group (All Buddies until the next g or the end of
     config are in this group.)      b - A Buddy     p - Person on permit
     list     d - Person on deny list     m - Permit/Deny Mode.  Possible
     values are         1 - Permit All         2 - Deny All         3 -
     Permit Some         4 - Deny Some

$aim->normalize($data)
     This method normalizes $data by killing all but strict alphnumeric
     characters.  Typically used for screen_names.

AUTHOR
======

   * Written by Aryeh Goldsmith <perlaim@aryeh.net>, AIM:Perl AIM

URL
===

   The Net::AIM project: http://www.aryeh.net/Net-AIM/

   The Net::AIM bot list: http://www.nodoubtyo.com/aimbots/

SEE ALSO
========

   perl(1)

Interface to an AIM connection
******************************

NAME
====

   Net::AIM::Connection - Interface to an AIM connection

DESCRIPTION
===========

   This module handles the connection and communications between us and
the server.  It parses the incoming data and hands it off to handler
methods if they are defined.  It currently supports and follows the TOC
protocol and contains methods to send out our information and messages.

METHODS
=======

Net::AIM::Connection->new($hash_ref)
          Net::AIM::Connection-Greater_Than_Special_Sequencenew( {
          	 Screenname => 'perlaim',
          	 Password => 'ilyegk',
          	 TocServer => 'toc.oscar.aol.com',
          	 TocPort => 9898,
          	 AuthServer => 'login.oscar.aol.com',
          	 AuthPort => 1234
               }

     Creates a new Connection object and tries to connect to the  AIM TOC
     server.  This method creates and objet and calls connect with all the
     arguments passed to it.

$aim_conn->new($hash_ref)
          $aim_conn-Greater_Than_Special_Sequencenew( {
          	 Screenname => 'perlaim',  #required
          	 Password => 'ilyegk',  #required
          	 TocServer => 'toc.oscar.aol.com'
          	 TocPort => 9898
          	 AuthServer => 'login.oscar.aol.com'
          	 AuthPort => 1234
            } );

     Sets up a connection to the AOL TOC server.

$aim->normalize($data)
     This method normalizes $data by killing all but strict alphnumeric
     characters.  Typically used for screen_names.

$aim_conn->send_im($screen_name, $message)
     This method sends $message to $screen_name.

$aim_conn->set_idle($idle_time)
     This method sets our idle time to `$idle_time'.  If $idle_time is
     omitted it will be set to 0.

$aim_conn->add_buddy(@buddies)
     This method adds `@buddies' to our buddy list that is set on the
     server.

$aim_conn->add_permit(@buddies)
     This method adds `@buddies' to our permit list that is set on the
     server.

$aim_conn->add_deny(@buddies)
     This method adds `@buddies' to our deny list that is set on the
     server.

$aim_conn->remove_buddy(@buddies)
     This method removes `@buddies' from our buddy list that is set on the
     server.

$aim_conn->set_away($message)
     This method sets our idle time to $idle_time.  If $idle_time is
     omitted it will be set to 0.

$aim_conn->get_info($screen_name)
     Sends an info request to the server for $screen_name. The server
     should reply with a URL which will contain the info requested about
     the user.

$aim_conn->set_info($info)
     This method sets your info or profile information to $info on the
     server.

$aim_conn->evil($user, $anon)
     Warn $screen_name.  $anon: boolean value which will determine whether
     to warn the user anonymously or normally.  Anonymous warnings are
     less severe.

$aim_conn->send($message)
     Send $message to the server.  This is used internally by other
     functions to send commands to the server.

          $aim_conn->send('toc_add_buddy perlaim')

$aim_conn->chat_invite($room, $msg, @buddies)
     Invite @buddies to $room with the message $msg

$aim_conn->chat_accept($room_id)
     This will accept an invitation that was sent to us for $room_id

$aim_conn->chat_leave($room_id)
     This method instructs the server to take you out of the room $room_id

$aim_conn->chat_whisper($room_id,$user,$msg)
     Whisper $msg to $user in the room $room_id

$aim_conn->chat_send($room_id, $message)
     Send $message in chat room $room_id

$aim_conn->chat_join($roomname)
     Send a request to enter the room $roomname

$aim_conn->connected()
     Returns a boolean value based on the state of the object's socket.

$aim->debug($debug)
     Set whether to print DEBUGGING information to STDERRR.  Accepts
     $debug which should be a boolean value.

$aim_conn->set_handler($evttype, \&coderef)
     Set a sub routine to be called when $event is encountered:
     $aim_conn->set_handler('error', \&on_errror);
     $aim_conn->set_handler('im_in', \&on_im);

$aim_conn->encode($str)
     This method returns $str encoded as per the TOC specs: escaped
     special chars ({}[]$) and enclosed in quotes (")

$aim_conn->encodePass($password)
     This method roasts $password according to the TOC specs. The roasted
     password is returned.

$aim_conn->send_confg($cfg_str)
     Sends $cfg_str to the server to be used as configuration values for
     the account.

$aim_conn->read_and_parse()
     Read a chunk of data off the connection to the server parse it and
     send it off to any defined handlers.

AUTHOR
======

   Aryeh Goldsmith <perlaim@aryeh.net>.

URL
===

   The Net::AIM project: http://www.aryeh.net/Net-AIM/

   The Net::AIM bot list: http://www.nodoubtyo.com/aimbots/

SEE ALSO
========

   perl(1)

Object to hold event data
*************************

NAME
====

   Net::AIM::Event - Object to hold event data

DESCRIPTION
===========

   This module holds data about an event which is any instruction we get
from the server.

METHODS
=======

Net::AIM::Event->new($type, $from, $to, @args)
     Net::AIM::Event constructor.  Takes 4 args    * The type of event
     * The originator (screenname or server)    * To/Destination (us -
     remnants from IRC module days...)     * @ARGS

$aim_event->dump()
     Print the event to STDERR good for debugging

$aim_event->args(@args)
     Sets the event's argument list to @args if it is provided.  Otherwise
     it returns the event's argument list.

$aim_event->from($from)
     Sets the originator of this event if $from is provided.  Otherwise it
     returns the event's originator.  Usually either a ScreenName|Server

$aim_event->to(@to)
     Sets the recipients of this event if @to is provided.  Otherwise it
     returns the event's recipient list.

$aim_event->trans($error_code)
     This method takes a numeric $error_code and returns a string
     representing the definition of the error code, or undef if the
     $error_code is unknown.

$aim_event->type($type)
     Sets the type of this event if $type is provided.  Otherwise it
     returns the event's type.

AUTHOR
======

   Aryeh Goldsmith <perlaim@aryeh.net>.

URL
===

   The Net::AIM project: http://www.aryeh.net/Net-AIM/

   The Net::AIM bot list: http://www.nodoubtyo.com/aimbots/

SEE ALSO
========

   perl(1)

Object-Oriented interface to the AOL Instant Messenger TOC client protocol
**************************************************************************

NAME
====

   Net::AOLIM - Object-Oriented interface to the AOL Instant Messenger TOC
client protocol

SYNOPSIS
========

   The really short form:

     use Net::AOLIM;
     $aim = Net::AOLIM->new('username' => $user,
     			   'password' => $pass,
     			   'callback' => \&handler);

     $aim->signon;

     $aim->toc_send_im($destuser, $message);

NOTES
=====

   Error conditions will be stored in $main::IM_ERR, with any arguments to
the error condition stored in $main::IM_ERR_ARGS.

   The hash %Net::AOLIM::ERROR_MSGS contains english translations of all of
the error messages that are either internal to the module or particular to
the TOC protocol.

   Errors may take arguments indicating a more specific failure condition.
In this case, they will either be stored in $main::IM_ERR_ARGS or they
will come from the server ERROR message.  To insert the arguments in the
proper place, use a construct similar to:

     $ERROR = $Net::AOLIM::ERROR_MSGS{$IM_ERR};
     $ERROR =~ s/\$ERR_ARG/$IM_ERR_ARGS/g;

   This assumes that the error code is stored in $IM_ERR and the error
argument is stored in $IM_ERR_ARGS.

   All methods will return undef on error, and will set $main::IM_ERR and
$main::IM_ERR_ARGS as appropriate.

DESCRIPTION
===========

   This section documents every member function of the Net::AOLIM class.

$Net::AOLIM->new()
------------------

   This is the Net::AOLIM Constructor.

   It should be called with following arguments (items with default values
are optional):

     'username' => login
     'password' => password
     'callback' => \&callbackfunction
     'server' => servername (default toc.oscar.aol.com)
     'port' => port number (default 1234)
     'allow_srv_settings' => <1 | 0> (default 1)
     'login_server' => login server (default login.oscar.aol.com)
     'login_port' => login port (default 5198)
     'aim_agent' => agentname (max 200 char) (default 'TOC1.0' where
     		X is the version number)  There have been some reports
     		that changing this may cause TOC servers to stop
     		responding to signon requests

   callback is the callback function that handles incoming data from the
server (already digested into command plus args).  This is the meat of the
client program.

   allow_srv_settings is a boolean that dictates whether the object should
modify the user configuration on the server.  If allow_srv_settings is
false, the server settings will be ignored and will not be modified.
Otherwise, the server settings will be read in and parsed, and will be
modified by calls that modify the buddy list.

   aim_agent is the name of the client program as reported to the TOC
server

   Returns a blessed instantiation of Net::AOLIM.

$aim->signon()
--------------

   Call this after calling new() and after setting initial buddy listings
with `add_buddies()', `im_permit()', `im_deny()', `im_permit_all()', and
`im_deny_all()' as necessary.

   Returns undef on failure, setting $main::IM_ERR and $main::IM_ERR_ARGS
as appropriate.  Returns 0 on success.

   This function is also called every time we receive a SIGN_ON packet
from the server.  This is because we are required to react in a specific
way to the SIGN_ON packet, and this method contains all necessary
functionality.  We should only receive SIGN_ON while connected if we have
first received a PAUSE (see the *TOC(7)* documentation included with this
package for details of how PAUSE works).

$aim->read_sflap_packet()
-------------------------

   This method returns data from a single waiting SFLAP packet on the
server socket.  The returned value is the payload section of the SFLAP
packet which is completely unparsed.

   Most users will never need to call this method.

   For more information, see ROLLING YOUR OWN below and the *TOC(7)*
manpage.

$aim->send_sflap_packet($type, $data, $formatted, $noterm)
----------------------------------------------------------

   This method sends an SFLAP packet to the server.

   $type is one of the SFLAP types (see *TOC(7)*).

   $data is the payload to send.

   If `$formatted' evaluates to true, the data is assumed to be the
completely formed payload of the SFLAP packet; otherwise, the payload will
be packed as necessary.  This defaults to 0.  In either case, the header
is prepended to the payload.

   If `$noterm' evaluates to true, the payload will not be terminated with
a '\0'.  Otherwise, it will be terminated.  If `$formatted' is true, this
option is ignored and no null is appended.  This defaults to 0.

   Most users will never need to use this method.

   For more information, see *TOC(7)* and ROLLING YOUR OWN below.

$aim->srv_socket()
------------------

   This method returns a reference to the socket to which the server is
connected.  It must be dereferenced before it can be used.  Thus:

   `$foo = $aim->srv_socket();' `recv($$foo, $recv_buffer, $length,
$flags);'

   Most users will never need to directly access the server socket.

   For more information, see the *TOC(7)* manpage and *ROLLING YOUR OWN*
below.

$aim->pw_roast($password)
-------------------------

   This method returns the 'roasted' version of a password.  A roasted
password is the original password XORed with the roast string 'Tic/Toc'
(which is repeated until the length is the same as the password length).

   This method is called automatically in $aim->signon.  Most users will
never need this method.

   For more information, see the *TOC(7)* manpage and *ROLLING YOUR OWN*
below.

$aim->norm_uname($username)
---------------------------

   This method returns the 'normalized' version of a username.  A
normalized username has all spaces removed and is all lowercase.  All
usernames sent to the server should be normalized first if they are an
argument to a TOC command.

   All methods in this class automatically normalize username arguments to
the server; thus, most users will never use this method.

   For more information, see the *TOC(7)* manpage and *ROLLING YOUR OWN*
below.

$aim->toc_format_msg($command[, $arg1[, arg2[, ...]]])
------------------------------------------------------

   This method formats a message properly for sending to the TOC server.
That is, it is escaped and quoted, and the fields are appended with spaces
as specified by the protocol.

   Note that all methods in this class automatically format messages
appropriately; most users will never need to call this method.

   See *TOC(7)* and ROLLING YOUR OWN below.

$aim->toc_send_im($uname, $msg, $auto)
--------------------------------------

   This method sends an IM message $msg to the user specified by `$uname'.
The third argument indicates whether or not this IM should be sent as an
autoreply, which may produce different behavior from the remote client
(but has no direct effect on the content of the IM).

$aim->add_buddies($group, $buddy1[, $buddy2[, ...]])
----------------------------------------------------

   This method, which should only be called *before signon()*, adds
buddies to the initial local buddy list in group `$group'.  Once
`signon()' is called, use add_online_buddies instead.

$aim->add_online_buddies($group, $buddy1[, $buddy2[, ...]])
-----------------------------------------------------------

   This method takes the same arguments as `add_buddies()', but is
intended for use after `signon()' has been called.

   If allow_srv_settings is true (see new()), it will also set the
settings on the server to the new settings.

$aim->remove_online_buddies($buddy1[, $buddy2[, ...]])
------------------------------------------------------

   Removes all arguments from the buddy list (removes from all groups).

   If allow_srv_settings is true (see new()), it will also set the
settings on the server to the new settings.

$aim->current_buddies(\%buddyhash)
----------------------------------

   This method fills the hash referenced by `\%buddyhash' with the
currently stored buddy information.  Each key in the returned hash is the
name of a buddy group, and the corresponding value is a list of the
members of that group.

$aim->current_permits()
-----------------------

   This method takes no arguments.  It returns the current 'permit' list.

$aim->current_denies()
----------------------

   This method takes no arguments.  It returns the current 'deny' list.

$aim->im_permit($user1[, $user2[, ...]])
----------------------------------------

   This method should only be called *before signon()*.  It adds all
arguments to the current permit list and deletes the current deny list.
It also sets the permit mode to 'permit some'.

   If you would like to do this while online, use the `add_im_permit()'
method instead.

$aim->im_deny($user1[, $user2[, ...]])
--------------------------------------

   This method should only be called *before signon()*.  It adds all
arguments to the current deny list and deletes the current permit list.
It also sets the permit mode to 'deny some'.

   If you would like to do this while online, use the `add_im_permit()'
method instead.

$aim->add_im_permit($user1[, $user2[, ...]])
--------------------------------------------

   This is the method that should be called if you are online and wish to
add users to the permit list.  It will, as a consequence, delete the
current deny list and set the current mode to 'permit some'.

$aim->add_im_deny($user1[, $user2[, ...]])
------------------------------------------

   This is the method that should be used if you are online and wish to
add users to the deny list.  It will, as a consequence, delete the current
permit list and set the current mode to 'deny some'.

$aim->im_deny_all()
-------------------

   This method should be called only *before signon()*.  It will delete
both the permit and deny list and set the mode to 'deny all'.

$aim->im_permit_all()
---------------------

   This method should be called only *before signon()*.  It will delete
both the permit and deny list and set the mode to 'permit all'.

$aim->add_im_deny_all()
-----------------------

   This is the method that should be used if you are online and wish to go
into 'deny all' mode.  It will also delete both the permit and deny lists.

$aim->add_im_permit_all()
-------------------------

   This is the method that should be used if you are online and wish to go
into 'permit all' mode.  It will also delete both the permit and deny
lists.

$aim->toc_evil($user, $anon)
----------------------------

   This method will apply 'evil' to the specified user `$user'.  If
`$anon' evaluates to true, the evil will be done anonymously.

$aim->toc_chat_join($exchange, $room_name)
------------------------------------------

   This method will join the chat room specified by `$exchange' and
`$room_name'.  Currently, the only valid value for `$exchange' is 4.

   See the *TOC(7)* manpage included with this package for more
information on chatting.

$aim->toc_chat_send($roomid, $message)
--------------------------------------

   This method will send the message `$message' to the room `$roomid'
(which should be the room ID provided by the server in response to a
toc_chat_join or toc_accept_invite).

   You will receive this message back from the server as well, so your UI
does not have to handle this message in a special way.

$aim->toc_chat_whisper($roomid, $dstuser, $message)
---------------------------------------------------

   This method sends the message `$message' to `$dstuser' in the room
`$roomid'.

   The server will not send you a copy of this message, so your user
interface should have a special case for displaying outgoing whispers.

$aim->toc_chat_evil($roomid, $dstuser, $anon)
---------------------------------------------

   This will apply evil to the user `$dstuser' in room `$room'.  If
`$anon' evaluates to true, it will be applied anonymously.

   Please note that this functionality is currently disabled by the TOC
servers.

$aim->toc_chat_invite($roomid, $msgtext, $buddy1[, $buddy2[, ...]])
-------------------------------------------------------------------

   This method will invite all users `$buddy1..$buddyN' to room `$roomid'
with invitation text `$msgtext'.

$aim->toc_chat_leave($roomid)
-----------------------------

   This method will notify the server that you have left room `$roomid'.

$aim->toc_chat_accept($roomid)
------------------------------

   This method accepts a chat invitation to room `$roomid'.  You do not
have to send a `toc_chat_join()' message if you have been invited and
accept with this method.

$aim->toc_get_info($username)
-----------------------------

   This method requests info on user $username.  See *TOC(7)* for more
information on what the server returns.

$aim->toc_set_info($info)
-------------------------

   This method sets the information for the current user to the ASCII text
(HTML formatted) contained in $info.

$aim->toc_set_away($msg)
------------------------

   This method sets or unsets the away message.  If $msg is undefined,
away is unset.  Otherwise, away is set with the message in $msg.

$aim->toc_get_dir($username)
----------------------------

   This method sends a request to the server for directory information on
$username.  See *TOC(7)* for information on what the server will return.

$aim->toc_set_dir($userinfo)
----------------------------

   This method sets the information on the current user to the string
provided as `$userinfo'.  See *TOC(7)* for more information on the format
of the `$userinfo' string.

$aim->toc_dir_search($searchstr)
--------------------------------

   This method will search the directory using `$searchstr'.  See *TOC(7)*
for more information on how this string should look.

$aim->toc_set_idle($seconds)
----------------------------

   This method sets the number of seconds that the client has been idle.
If it is 0, the idle is cleared.  Otherwise, the idle is set and the
server will continue to count up the idle time (thus, you need only call
`idle()' once in order to become idle).

$aim->ui_add_fh($filehandle, \&callback)
----------------------------------------

   This method will add a filehandle to the select() loop that will be
called with `ui_dataget()'.  If information is found to be on that
filehandle, the callback will be executed.  It is the responsibility of
the callback to read the data off the socket.

   *Please be sure to set autoflushing on all filehandles passed to this
method!*

$aim->ui_del_fh($filehandle)
----------------------------

   The filehandle `$filehandle' will be removed from the select() loop and
it will no longer be checked for input nor its callback activated.

$aim->ui_all_fh()
-----------------

   This method returns a list of all filehandles currently in the select()
loop.

$aim->ui_exists_fh($filehandle)
-------------------------------

   This method will return true if `$filehandle' is in the select loop.
Otherwise, it will return undefined.

$aim->ui_set_callback(\&callback)
---------------------------------

   This method will change the callback function for the server socket to
the method referenced by \&callback.  This allows you to change the
callback from the one specified when the object was created.  (Imagine the
possibilities-dynamically created callback functions using `eval()'...
mmmm...)

$aim->ui_get_callback($filehandle)
----------------------------------

   This method returns a reference to the callback associated with
$filehandle, or the callback associated with the server socket if
$filehandle is undefined.

$aim->ui_dataget($timeout)
--------------------------

   This is the workhorse method in this object.  When this method is
called, it will go through a single select() loop to find if any
filehandles are ready for reading.  If $timeout is defined, the select()
timeout will be that number of seconds (fractions are OK).  Otherwise,
select() will block.

   For each filehandle that is ready for reading, this function will call
the appropriate callback function.  It is the responsibility of the
callback to read the data off the filehandle and handle it appropriately.
The exception to this rule is the server socket, whose data will be read
and passed to the server socket callback function.  All pasrsing of data
from the server into edible chunks will be done for you before the server
socket callback function is called.  From there, it is up to to the client
program to parse the server responses appropriately.  They will be passed
such that each field in the server response is one argument to the
callback (the number of arguments will be correct).  For more information
on the information coming from the server, see *TOC(7)*.

   This method returns undef on an error (including errors from callbacks,
which should be signified by returning undef) and returns the number of
filehandles that were read otherwise.

ROLLING YOUR OWN
================

   This section deals with usage that deals directly with the server
connection and bypasses the ui_* interface and/or the toc_* interface.  If
you are happy calling ui_dataget et al., do not bother reading this
section.  If, however, you plan not to use the provided interfaces, or if
you want to know more of what is going on, continue on.

   First of all, if you do not plan to use the provided interface to the
server socket, you will need to be able to access the server socket
directly.  In order to do this, use $aim->srv_socket:

     $srv_sock = $aim->srv_socket;

   This will return a pointer to the socket.  You will need to dereference
it in order to use it.

   In general, however, even if you are rolling your own, you will
probably not need to use `recv()' or the like.  `read_sflap_packet()' will
handle unwrapping the data coming from the server and will return the
payload of the packet as a single scalar.  Using this will give you the
data coming from the server in a form that you can `split()' to get the
message and its arguments.  In order to facilitate such splitting,
`%Net::AOLIM::SERVER_MSG_ARGS' is supplied.  For each valid server message,
`$Net::AOLIM::SERVER_MSG_ARGS{$msg}' will return one less than the proper
number of splits to perform on the data coming from the server.  The
intended use is such:

     ($msg, $rest) = split(/:/, $aim->read_sflap_packet(), 2);
     @msg_args = split(/:/, $rest, $Net::AOLIM::SERVER_MSG_ARGS{$msg});

   Now you have the server message in $msg and the arguments in
`@msg_args'.

   To send packets to the server without having to worry about making
SFLAP packets, use `send_sflap_packet()'.  If you have a string to send to
the server (which is not formatted), you would use:

     $aim->send_sflap_packet($SFLAP_TYPE_DATA, $message, 0, 0);

   The SFLAP types (listed in *TOC(7)* are:

     $SFLAP_TYPE_SIGNON
     $SFLAP_TYPE_DATA
     $SFLAP_TYPE_ERROR
     $SFLAP_TYPE_SIGNOFF
     $SFLAP_TYPE_KEEPALIVE

   Most of the time you will use $SFLAP_TYPE_DATA.

   If you want to roll your own messages, read the code for
`send_sflap_packet()' and you should be able to figure it out.  Note that
the header is always supplied by `send_sflap_packet()'.  Specifying
`formatted' will only make `send_sflap_data()' assume that `$message' is a
preformatted payload.  Specifying `$noterm' will prevent
`send_sflap_packet()' from adding a trailing '\0' to the payload.  If it
is already formatted, `send_sflap_packet' will ignore `$noterm'.

   Messages sent to the server should be escaped and formatted properly as
defined in *TOC(7)*.  `$aim->toc_format_msg' will do just this; supply it
with the TOC command and the arguments to the TOC command (each as
separate strings) and it will return a single string that is formatted
appropriately.

   All usernames sent as TOC command arguments must be normalized (see
*TOC(7)*).  `$aim->norm_uname()' will do just this.  Make sure to
normalize usernames before passing them as arguments to
`$aim->toc_format_msg()'.

   `pw_roast' performs roasting as defined in *TOC(7)*.  It is not very
exciting.  I do not see why it is that you would ever need to do this, as
`$aim->signon()' handles this for you (and the roasted password is stored
in `$aim->{'roastedp'}').  However, if you want to play with it, there it
is.

EXAMPLES
========

   See the file `example.pl' for an example of how to interact with this
class.

FILES
=====

   `example.pl'

   A sample client that demonstrates how this object could be used.

SEE ALSO
========

   See also *TOC(7)*.

AUTHOR
======

   Copyright (C) 2000 Riad Wahby <*rsw@mit.edu*> All rights reserved This
program is free software.  You may redistribute it and/or modify it under
the same terms as Perl itself.

HISTORY
=======

   0.01     Initial Beta Release. (7/7/00)

   *0.1*     First public (CPAN) release. (7/14/00)

   *0.11*     Re-release under a different name with minor changes to the
  documentation. (7/16/00)

   *0.12*     Minor modification to fix a condition in which the server's
  connection closing could cause an infinite loop.

   *1.0*     Changed the client agent string to TOC1.0 to fix a problem
where     connections were sometimes ignored.  Also changed the default
signon     port to 5198 and the login port to 1234.

Critical Path Account Provisioning Protocol
*******************************************

NAME
====

   Net::APP - Critical Path Account Provisioning Protocol

SYNOPSIS
========

     use Net::APP;

     #constructor
     $app = new Net::APP ( 'host:port',
                           User     => $user,
                           Domain   => $domain,
                           Password => $password,
                           Timeout  => 60,
                           Debug    => 1,
                         ) or die $@;

     #commands
     $app->ver( 'ver' => $Net::APP::APP_VERSION );
     $app->login ( User     => $user,
                   Domain   => $domain,
                   Password => $password,
                 );

     $app->create_domain ( Domain => $domain );
     $app->delete_domain ( Domain => $domain );
     #etc. (see the Account Provisioning Protocol Developer's Guide, section 3.3)

     #command status
     $message = $app->message;
     $code = $app->code;
     $bool = $app->ok();

     #destructor
     $app->close();

DESCRIPTION
===========

   This module implements a client interface to Critical Path's Account
Provisioning Protocol, enabling a perl application to talk to APP servers.
This documentation assumes that you are familiar with the APP protocol
documented in the Account Provisioning Protocol Developer's Guide.

   A new Net::APP object must be created with the new method.  Once this
has been done, all APP commands are accessed via method calls on the
object.

METHODS
=======

new ( HOST:PORT [ , OPTIONS ] )
     This is the constructor for a new Net::APP object.  `HOST' and `PORT'
     specify the host and port to connect to in cleartext.  Typically this
     connection is proxied via Safe Passage Secure Tunnel to Critical Path.

     This method will connect to the APP server and execute the ver method.

     OPTIONS are passed in a hash like fastion, using key and value pairs.
     Possible options are:

     Timeout - Set a timeout value (defaults to 120)

     Debug - Enable debugging information (see the debug method in
     Net/Cmd)

     User, Domain, Password - if these exist, the new method will also
     execute the login method automatically.

     If the constructor fails undef will be returned and an error message
     will be in $@.

ver
login
create_domain
delete_domain
etc.
     See the Account Provisioning Protocol Developer's Guide for details.
     Commands need not be in upper case, and options are passed in a
     hash-like fashion, as a list of key-value pairs.

     All options return a reference to a list containing the lines of the
     reponse, or undef upon failure.  The first line is parsed for the
     status code and message.  You can check the status code and message
     using the normal Net::Cmd message, code, ok, and status methods.

     Only the get_num_domain_mailboxes, get_mailbox_availability and
     get_mailbox_status methods currently return any additional response
     information.  No attempt is (yet) made to parse this data.

message
     Returns the text message returned from the last command.

code
     Returns the response code from the last command (see the Account
     Provisioning Protcol Developer's Guide, chapter 4).  The code `-1' is
     used to represent unparsable output from the APP server, in which
     case the entire first line of the response is returned by the
     *messsage* method.

ok
     Returns true if the last code was an acceptable response.

status
     Since the APP protocol has no concept of a "most significant digit"
     (see `status', see Net/Cmd), this is a noisy synonym for
     code.

INTERNAL METHODS
================

   These methods are not intended to be called by the user.

_app_command ( COMMAND [ , OPTIONS ] )
     Sends *COMMAND*, encoded as per the Account Provisioning Protocol
     Developer's Guide, section 3.2.  OPTIONS are passed in a hash like
     fashion, using key and value pairs.

_app_response
     Gets a response from the server.  Returns a reference to a list
     containing the lines, or undef upon failure.  You can check the
     status code and message using the normal Net::Cmd message, code, ok,
     and status methods.

INTERNAL SUBROUTINES
====================

   These subroutines are not intended to be called by the user.

_quote
     Doubles double quotes.

     This is untested for strings containing consecutive double quotes.

AUTHOR
======

   Ivan Kohler <ivan-netapp@sisd.com>.

   This module is not sponsored or endorsed by Critical Path.

COPYRIGHT
=========

   Copyright (c) 1999 Ivan Kohler.  Copyright (c) 1999 Silicon Interactive
Software Design.  All rights reserved.  This program is free software; you
can redistribute it and/or modify it under the same terms as Perl itself.

VERSION
=======

   $Id: APP.pm,v 1.1.1.1 1999/06/21 10:11:11 ivan Exp $

   This module currently implements APP v2.1, as documented in the Account
Provisioning Protocol Developers Guide v2.1.

BUGS
====

   The Account Provisioning Protocol Developer's Guide is not publicly
available.

   It appears that Safe Passage Secure Tunnel establishes a standard SSL
connection.  It should be possible to use Net::SSLeay and connect to the
APP server directly.

   Sending values with consecutive double quote characters is untested.

   The get_num_domain_mailboxes, get_mailbox_availability and
get_mailbox_status methods currently return response information.  No
attempt is (yet) made to parse this data.

SEE ALSO
========

   Critical Path <http://www.cp.net/>, Safe Passage Secure Tunnel
<http://www.c2.net/products/spst>, `Net::SSLeay' in this node, see
Net/Cmd, perl(1).

HISTORY
=======

   $Log: APP.pm,v $ Revision 1.1.1.1  1999/06/21 10:11:11  ivan new project

load various Net::Bind modules
******************************

NAME
====

   Net::Bind - load various Net::Bind modules

SYNOPSIS
========

     use Net::Bind;

DESCRIPTION
===========

   `Net::Bind' provides a simple mechanism to load all of the `Net::Bind'
modules in one fell swoop.

   Currently, this includes the following modules:

     Net::Bind::Resolv

   Futures releases will include:

     Net::Bind::Boot
     Net::Bind::Zone
     Net::Bind::Dump
     Net::Bind::Conf

AUTHOR
======

   Kevin Johnson <`kjj@pobox.com'>

COPYRIGHT
=========

   Copyright (c) 1997 Kevin Johnson <kjj@pobox.com>.

   All rights reserved. This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

a class to munge /etc/resolv.conf data.
***************************************

NAME
====

   Net::Bind::Resolv - a class to munge /etc/resolv.conf data.

SYNOPSIS
========

   `use Net::Bind::Resolv;'

DESCRIPTION
===========

   This class provides an object oriented perl interface to
`/etc/resolv.conf' data.

   Here is an example snippet of code:

     use Net::Bind::Resolv;
     my $res = new Net::Bind::Resolv('/etc/resolv.conf');
     print $res->domain, "\n";

   Or how about:

     use Net::Bind::Resolv;
     use IO::File;
     my $res = new Net::Bind::Resolv;
     $res->comment("Programmatically generated\nDo not edit by hand");
     $res->domain('arf.fz');
     $res->nameservers('0.0.0.0');
     $res->options('debug');
     print $res->as_string;

METHODS
=======

new([$filename])
----------------

   Returns a reference to a new `Net::Bind::Resolv' object.  If $filename
is given then use that pass the value to a call to `read_from_file'.

read_from_string($string)
-------------------------

   Populates the object with the parsed contents of $string.  Returns 1 is
no errors were encounters, otherwise it returns 0.

   The following directives are understood.

   * domain DOMAIN

   * search SEARCHLIST...

     If a search directive and domain directive are found in the same
     file, the last one encountered will be recorded and all previous ones
     will be ignored.

   * nameserver IP_ADDR

     Each instance of a nameserver directive will cause the given
     `IP_ADDR' to be remembered.

   * sortlist SORTLIST...

   * options OPTIONS...

   There are very few requirements placed on the data in $string.
Multiple entries of certain directives, while technically incorrect, will
cause the last occurrence of the given directive to be the one remembered.
If there is sufficient precedence for this to be otherwise, let me know.

   There is no requirement for the arguments to the directives to be valid
pieces of data.  That job is delagated to local policy methods to be
applied against the object.

read_from_file($filename)
-------------------------

   Populates the object with the parsed contents of $filename.  This
really just a wrapper around `read_from_string'.  Returns 0 if errors were
encountered, otherwise it returns 1.

clear
-----

   Zeros out the internal data in the object.  This needs to be done if
multiple `read_from_string' methods are called on a given
`Net::Bind::Resolv' object and you do not want to retain the previous
values in the object.

domain([$domain])
-----------------

   Returns the value of the domain directive.  If $domain is specified,
then set the domain to the given value and the searchlist, if defined in
the object, is undefined.

nameservers([@values])
----------------------

   Returns (in order) the list of nameserver entries.  If called in an
array context it returns an array, otherwise it returns an array reference.

   If `@values' is specified, then set the nameserver list to the given
values.  Any items in `@values' that are list references are dereferences
as they are added.

searchlist([@values])
---------------------

   Returns an array reference containing the items for the search
directive.  If called in an array context it returns an array, otherwise
it returns an array reference.

   If a list of values is specified, then set the searchlist to those
values and the domain, if defined in the object, is undefined.  Any items
in `@values' that are list references are dereferenced as they are added.

sortlist([@values])
-------------------

   Returns an array reference containing the items for the `sortlist'
directive.  If called in an array context it returns an array, otherwise
it returns an array reference.

   If a list of values is specified, then set the sortlist to those
values.  Any items in `@values' that are list references are dereferenced
as they are added.

options([@values])
------------------

   Returns the items for the options directive.  If called in an array
context it returns an array, otherwise it returns an array reference.

   If a list of values is specified, then set the options to those values.
Any items in `@values' that are list references are dereferenced as they
are added.

comments([@strings])
--------------------

   Returns the comments for the object.  If called in an array context it
returns an array, otherwise it returns an array reference.

   If a list of strings is specified, then set the comments to those
values after splitting the items on a `NEWLINE' boundary.  This allows
several combinations of arrays, array refs, or strings with embedded
newlines to be specified.  There is no need to prefix any of the comment
lines with a comment character (`[;\#]'); the as_string automagically
commentifies (:-) the comment strings.

   Any items in `@strings' that are list references are dereferenced as
they are added.

as_string
---------

   Returns a string representing the contents of the object.  Technically,
this string could be used to populate a `resolv.conf' file, but use print
for that.  The <print> method is a wrapper around this method.  The data
is generated in the following order:

     comments
     domain	(mutually exclusive with search)
     search	(mutually exclusive with domain)
     nameservers   (one line for each nameserver entry)
     sortlist
     options

print($fh)
----------

   A wrapper around as_string that prints a valid `resolver(5)'
representation of the data in the object to the given filehandle.

check([$policy])
----------------

   Performs a policy/validity check of the data contained in the object
using the given subroutine `&policy'.  The given `$policy' routine is
called as `&$policy($self)'.  If `$policy' is not given it defaults to
using default_policy_check.  It returns the return status of the policy
check routine.

default_policy_check
--------------------

   A simple wrapper around various `check_*' methods.

check_domain
------------

   Returns 1 if the domain member of the object is defined and is a valid
rfc1035 domain name, otherwise returns 0.

check_searchlist
----------------

   Returns 1 if the searchlist member of the object is defined and
contains only valid rfc1035 domain names, otherwise returns 0.

check_nameservers
-----------------

   Returns 1 if the nameservers member of the object is defined and
contains only ip-addresses, otherwise returns 0.

   Uses `valid_ip' to do the real work.

check_sortlist
--------------

   Returns 1 if the sortlist member of the object is defined and contains
only ip-address/netmasks, otherwise returns 0.

   Uses `valid_netmask' to do the real work.

check_options
-------------

   Returns 1 if the options member of the object is empty or contains only
valid options, otherwise returns 0.

   Currently recognized options are:

   * debug

   * ndots:N

qtynameservers
--------------

   Returns the quantity of nameserver entries present.

CAVEATS
=======

   The `read_from_{file|string}' methods and the print method are not
isomorphic.  Given an arbitrary file or string which is read in, the
output of print is not guaranteed to be an exact duplicate of the original
file.  In the special case of files that are generated with this module,
the results will be isomorphic, assuming no modifications were made to the
data between when it was read in and subsequently written back out.

   Since Net::Bind::Resolv does not impose many requirements on the values
of the various directives present in a `/etc/resolv.conf' file, it is
important to apply the appropriate policy methods against the object
before writing it to a file that will be used by the resolver.  Consider
yourself warned!

AUTHOR
======

   Kevin Johnson <`kjj@pobox.com'>

COPYRIGHT
=========

   Copyright (c) 1997 Kevin Johnson <kjj@pobox.com>.

   All rights reserved. This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

various routines common across Net::Bind packages.
**************************************************

NAME
====

   Net::Bind::Utils - various routines common across Net::Bind packages.

DESCRIPTION
===========

   A catch-all place for various routines that useful across most, if not
all, of the `Net::Bind' interfaces.

   This module is not designed to be subclassable.

ROUTINES
========

valid_domain($domain)
---------------------

   Returns 1 if the given $domain string is defined and is a valid rfc1035
domain name, otherwise returns 0.

valid_ip($ip)
-------------

   Returns 1 if the given $ip string is defined and is an ip address,
otherwise returns 0.

   The check for a valid ip address is currently very simple minded.  It
merely checks for a dotted-quad with all non-negative numbers with no
number larger than 254.

valid_netmask($netmask)
-----------------------

   Returns 1 if the given `$netmask' string is defined and is a netmask,
otherwise return 0.

   The check for a valid netmask is currently very simple minded.  It
merely checks for a dotted-quad with all non-negative numbers with no
number larger than 255.

AUTHOR
======

   Kevin Johnson <`kjj@pobox.com'>

COPYRIGHT
=========

   Copyright (c) 1997 Kevin Johnson <kjj@pobox.com>.

   All rights reserved. This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

String search interface to CDDB datbase
***************************************

NAME
====

   Net::CDDBScan - String search interface to CDDB datbase

SYNOPSIS
========

   `use Net::CDDBScan;'

     Grab a list of all songs for Madonna
     	$cddb = Net::CDDBScan->new(CONT =>1);
     $songs = $cddb->getsongs("madonna");
     print $songs{$_},'\n' foreach %{$songs};
     $cddb->close();

DESCRIPTION
===========

   Net::CDDBScan is an interface to the www.cddb.com website; or more
specifically to their online search engine for the cddb database.
Originally created as a small part of a greater application.  This module
allows you to take any existing string like "tricky" or "for whom the bell
tolls" and get the artist name, all albums from said artist and all songs
on ANY album said artist has ever worked on. (Or close enough: This is
assuming the cddb database has a record of the given artist/album/song.)

USING Net::CDDBScan
===================

*1. Creating a Net::CDDBScan object*
     You first must create a Net::CDDBScan object.

     `my $cddb = Net::CDDBScan->new()'

     new() has the following optional parameters:

          DEBUG: Debug has 2 levels, the first level shows all urls, albums
          and songs as it finds them. The second level also shows all internal function
          calls.  You shouldn't ever need to use level 2 but it's there if you feel
          the need.

     DEBUG

     Level 1: *`$cddb = Net::CDDBScan->new(DEBUG =>1)'*

     Level 2: *`$cddb = Net::CDDBScan->new(DEBUG =>2)'*

     Pretty simple I would think.  These currently print to stdout, but I
     may change that to stderr in the future as it would seem easier to
     redirect to error logs all debug output without also getting the std
     output you may still want in stdout.

     *CONT*

     CONT is used to tell Net::CDDBScan if you want it to continue or not.
     Default is no since it can take longer then you may desire. If you
     ask for a list of albums for the band Portishead.

     *`$albums = $cddb->getalbums("portishead");'*

     Net::CDDBScan will retrieve a list of albums, but only one page
     worth, that is it will only grab 1 html page worth of data (usually
     7-9 items).  But, if you want Net::CDDBScan to get ALL albums for a
     band, then you can set CONT as:

     *`$cddb = Net::CDDBScan->new(CONT =>1);'*

     This will cause Net::CDDBScan to continue through all pages gathering
     albums until none are left.  NOTE: This also works for songs, but not
     for artist (since one entry is enough to tell us who the artist is.
     This may change in the future as you may want to know all possible
     artists for a song or album).

*2. Getting a list of all albums for a given artist.*
     getalbums()

     NOTE: Must use the *CONT* contructor option to get 'ALL' albums

     $albums = $cddb->getalbums("medusa");

     print $albums{$_},'\n' foreach (keys %$albums);

     Returns a reference to a hash of album urls and names (The key is the
     url and the value is the album name). This function also takes any
     cddb.com url or partial url in the following formats:

     *http://www.cddb.com/xm/search?f=artist&q=medusa*

     *www.cddb.com/xm/search?f=artist&q=medusa*

     */xm/search?f=artist&q=medusa*

     */xm/search?q=medusa*

     *medusa* etc... you get the idea.

     The reason for taking all these types of urls/strings is based on the
     internal usage of this function.  These formats are not planned to
     change.

*3. Getting a list of all songs for all albums of a given artist.*
     getsongs()

          $songs = $cddb->getsongs("cocteau twins");
          print $songs{$_},'\n' foreach (keys %$songs);

     This function accepts all the url/string formats that *getalbums()*
     takes and otherwise acts just like getalbums() including returning a
     hashref of urls and song names.

*4. Determining an Artist name based on an album or song name.*
     getartist()

     "Mezzanine" is the name of a Massive Attach album

     $artist = $cddb->getartist("mezzanine");

     NOTE: Currently you cannot do:

     $artist = $cddb->getartist('less then strangers');

     i.e. You cannot use ANY string for an artist search.  Sorry, it's a
     limitation of the cddb.com search engine.  I'm currently working on a
     work-around. You can use any of the cddb url formats listed above.

     $songs = $cddb->getsongs('less then strangers');

     @urls = key %{$songs};

     $artist = $cddb->getartist($urls[0]);

NOTICE
======

   Be aware this module is in *BETA* stage.  Some major changes have
happened as I said they would. The biggest change is that getalbums() and
getsongs() return hashrefs instead of arrayrefs now. Sorry for the change,
but this makes room for much more functionality down the road. More
changes are expected which will allow much cleaner usage, much more
functionality and caching of data to a local cddb database (optional). If
you have any comments, suggestions and/or patches you'd like to submit.
Please email me at dshultz@redchip.com

AUTHOR
======

   Copyright 1998-2000, David J. Shultz All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  Address bug reports and comments to:
dshultz@redchip.com

BUGS
====

   This section intentionally left blank.

SEE ALSO
========

   perl(1).

Network Command class (as used by FTP, SMTP etc)
************************************************

NAME
====

   Net::Cmd - Network Command class (as used by FTP, SMTP etc)

SYNOPSIS
========

     use Net::Cmd;

     @ISA = qw(Net::Cmd);

DESCRIPTION
===========

   `Net::Cmd' is a collection of methods that can be inherited by a sub
class of IO::Handle. These methods implement the functionality required
for a command based protocol, for example FTP and SMTP.

USER METHODS
============

   These methods provide a user interface to the `Net::Cmd' object.

debug ( VALUE )
     Set the level of debug information for this object. If VALUE is not
     given then the current state is returned. Otherwise the state is
     changed to VALUE and the previous state returned.

     Set the level of debug information for this object. If no argument is
     given then the current state is returned. Otherwise the state is
     changed to $valueand the previous state returned.  Different packages
     may implement different levels of debug but, a  non-zero value result
     in copies of all commands and responses also being sent to STDERR.

     If VALUE is undef then the debug level will be set to the default
     debug level for the class.

     This method can also be called as a static method to set/get the
     default debug level for a given class.

message ()
     Returns the text message returned from the last command

code ()
     Returns the 3-digit code from the last command. If a command is
     pending then the value 0 is returned

ok ()
     Returns non-zero if the last code value was greater than zero and
     less than 400. This holds true for most command servers. Servers
     where this does not hold may override this method.

status ()
     Returns the most significant digit of the current status code. If a
     command is pending then `CMD_PENDING' is returned.

datasend ( DATA )
     Send data to the remote server, converting LF to CRLF. Any line
     starting with a '.' will be prefixed with another '.'.  DATA may be
     an array or a reference to an array.

dataend ()
     End the sending of data to the remote server. This is done by
     ensuring that the data already sent ends with CRLF then sending
     '.CRLF' to end the transmission. Once this data has been sent dataend
     calls response and returns true if response returns CMD_OK.

CLASS METHODS
=============

   These methods are not intended to be called by the user, but used or
over-ridden by a sub-class of `Net::Cmd'

debug_print ( DIR, TEXT )
     Print debugging information. DIR denotes the direction *true* being
     data being sent to the server. Calls debug_text before printing to
     STDERR.

debug_text ( TEXT )
     This method is called to print debugging information. TEXT is the
     text being sent. The method should return the text to be printed

     This is primarily meant for the use of modules such as FTP where
     passwords are sent, but we do not want to display them in the
     debugging information.

command ( CMD [, ARGS, ... ])
     Send a command to the command server. All arguments a first joined
     with a space character and CRLF is appended, this string is then sent
     to the command server.

     Returns undef upon failure

unsupported ()
     Sets the status code to 580 and the response text to 'Unsupported
     command'.  Returns zero.

response ()
     Obtain a response from the server. Upon success the most significant
     digit of the status code is returned. Upon failure, timeout etc.,
     undef is returned.

parse_response ( TEXT )
     This method is called by response as a method with one argument. It
     should return an array of 2 values, the 3-digit status code and a
     flag which is true when this is part of a multi-line response and
     this line is not the list.

getline ()
     Retrieve one line, delimited by CRLF, from the remote server. Returns
     undef upon failure.

     NOTE: If you do use this method for any reason, please remember to add
     some debug_print calls into your method.

ungetline ( TEXT )
     Unget a line of text from the server.

read_until_dot ()
     Read data from the remote server until a line consisting of a single
     '.'.  Any lines starting with '..' will have one of the '.'s removed.

     Returns a reference to a list containing the lines, or undef upon
     failure.

EXPORTS
=======

   `Net::Cmd' exports six subroutines, five of these, `CMD_INFO', `CMD_OK',
`CMD_MORE', `CMD_REJECT' and `CMD_ERROR' ,correspond to possible results
of response and status. The sixth is `CMD_PENDING'.

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

COPYRIGHT
=========

   Copyright (c) 1995-1997 Graham Barr. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Local configuration data for libnet
***********************************

NAME
====

   Net::Config - Local configuration data for libnet

SYNOPSYS
========

     use Net::Config qw(%NetConfig);

DESCRIPTION
===========

   `Net::Config' holds configuration data for the modules in the libnet
distribuion. During installation you will be asked for these values.

   The configuration data is held globally in a file in the perl
installation tree, but a user may override any of these values by
providing thier own. This can be done by having a `.libnetrc' file in
thier home directory. This file should return a reference to a HASH
containing the keys described below.  For example

     # .libnetrc
     {
         nntp_hosts => [ "my_prefered_host" ],
     	ph_hosts   => [ "my_ph_server" ],
     }
     __END__

METHODS
=======

   `Net::Config' defines the following methods. They are methods as they
are invoked as class methods. This is because `Net::Config' inherits from
`Net::LocalCfg' so you can override these methods if you want.

requires_firewall HOST
     Attempts to determine if a given host is outside your firewall.
     Possible return values are.

          -1  Cannot lookup hostname
           0  Host is inside firewall (or there is no ftp_firewall entry)
           1  Host is outside the firewall

     This is done by using hostname lookup and the local_netmask entry in
     the configuration data.

NetConfig VALUES
================

nntp_hosts
snpp_hosts

pop3_hosts
smtp_hosts
ph_hosts
daytime_hosts
time_hosts
     Each is a reference to an array of hostnames (in order of preference),
     which should be used for the given protocol

inet_domain
     Your internet domain name

ftp_firewall
     If you have an FTP proxy firewall (*NOT* a HTTP or SOCKS firewall)
     then this value should be set to the firewall hostname. If your
     firewall does not listen to port 21, then this value should be set to
     `"hostname:port"' (eg `"hostname:99"')

ftp_ext_passive
ftp_int_pasive
     FTP servers normally work on a non-passive mode. That is when you
     want to transfer data you have to tell the server the address and
     port to connect to.

     With some firewalls this does not work as te server cannot connect to
     your machine (because you are beind a firewall) and the firewall does
     not re-write te command. In this case you should set ftp_ext_passive
     to a *true* value.

     Some servers are configured to only work in passive mode. If you have
     one of these you can force `Net::FTP' to always transfer in passive
     mode, when not going via a firewall, by cetting `ftp_int_passive' to
     a *true* value.

local_netmask
     A reference to a list of netmask strings in the form
     `"134.99.4.0/24"'.  These are used by the requires_firewall function
     to determine if a given host is inside or outside your firewall.

   The following entries are used during installation & testing on the
libnet package

test_hosts
     If true them make test may attempt to connect to hosts given in the
     configuration.

test_exists
     If true the Configure will check each hostname given that it exists

Perform domain lookups on 2-letter and 3-letter TLDs
****************************************************

NAME
====

   Net::DLookup - Perform domain lookups on 2-letter and 3-letter TLDs

SYNOPSIS
========

     use Net::DLookup;

     # Initialize Net::DLookup object
     my $dlu = Net::DLookup -> new;

     # Replace domain definitions from a file
     $dlu -> LoadTLD($file, 1);

     # Add domain definitions from a file
     $dlu -> LoadTLD($file, 0);

     # Check domain name validity and assign it to the object
     @errors = $dlu -> IsValid($domain);

     # Return availability
     @response = $dlu -> DoWhois(0);

     # Return availability and registrar information
     @response = $dlu -> DoWhois(1);

DESCRIPTION
===========

   Net::DLookup performs domain lookups for 2-letter and 3-letter top
level domains.  It also verifies the validity of domain names by checking
punctuation, length, metacharacters, etc..

   Information for currently recognized top level domains is included
within the module. This list may be replaced or added to by calling
$dlu->LoadTLD().

   With the advent of new registrars for 3-letter top level domains, it's
become difficult to get the whois output from a single domain lookup,
unless you know what registration agency to look at.  Net::DLookup solves
this problem by checking Internic's database first and then performing a
second query to the respective registrar for full whois output.

USAGE
=====

   These functions must be used in order:

   Of course:

     use Net::DLookup;

   Create an object that contains the default top level domains.

     my $dlu = Net::DLookup -> new;

   Validate domain name ($domaintocheck) and associate it with the object.
This must be the full domain name, such as yourdomain.com.

     my @errors = $dlu -> IsValid($domaintocheck);

   It checks for the following possible errors:

Is 67 characters or less for 3-letter TLDs
Is not a 3rd level domain for 3-letter TLDs (me.yourdomain.com)
Is 26 characters or less for 2-letter TLDs
Is not a 4th level domain for 2-letter TLDs (me.yourdomain.co.uk)
Does not start or end with a non-alphanumeric character
Does not contain non alphanumeric characters (except a dash) within the domain name
Is a valid TLD*
   * All CCTLDs (Country Code TLDs) currently listed at IANA as well as
the .com, .net, .org, .edu and .mil are checked

   @errors will contain a list of all possible errors that the domain name
may have, such as:

Domain name can't start or end with non-alphanumeric character.
Domains with the .com extension cannot exceed 67 characters.
   Last, the domain lookup.

     @response = $domain->Net::DLookup::DoWhois();

Is domain registered?   1 for yes; 0 for no
Name of Registration Agency or Country
URL of Registration Agency for TLD
Whois Server for TLD
Whois Output
A "worded" reponse for domain availability "{domain} is available"
   If you're looking up a 3-letter TLD domain (.com, .net, .org, .edu and
.mil), you have the choice to NOT perform the second lookup.  This would
be useful if you're just checking for domain availability and don't care
who's already registered it.  You can disable the second lookup by
removing the 1.  This will give you Internic's plain Jane, uninformative
whois information.

     @response = $domain->Net::DLookup::DoWhois(1);

RESTRICTIONS
============

   Net::DLookup requires that the Sockets (included with the Perl
distribution) module is installed.

VERSION
=======

   Net::DLookup Version 1.01  6/10/2000

CAVEATS
=======

   Registration agencies are finicky beasts.  They may change their whois
server, urls, or responses (that this module relies on) without notice.
As of 6/10/2000, the agency data in the module is accurate.

CREDITS
=======

   Many thanks goes to Michael Chase for the new LoadTLD() and DumpTLD()
routines.

AUTHOR
======

   D. Jasmine Merced  <djasmine@tnsgroup.com>, CPAN ID: DJASMINE

   The Perl Archive  <http://www.perlarchive.com>

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.  If you make modifications, the
author would like to know so that they can be incorporated into future
releases.

Perl interface to the DNS resolver
**********************************

NAME
====

   Net::DNS - Perl interface to the DNS resolver

SYNOPSIS
========

   `use Net::DNS;'

DESCRIPTION
===========

   Net::DNS is a collection of Perl modules that act as a Domain Name
System (DNS) resolver.  It allows the programmer to perform DNS queries
that are beyond the capabilities of gethostbyname and gethostbyaddr.

   The programmer should be somewhat familiar with the format of a DNS
packet and its various sections.  See RFC 1035 or *DNS and BIND* (Albitz &
Liu) for details.

Resolver Objects
----------------

   A resolver object is an instance of the `Net::DNS::Resolver' class.  A
program can have multiple resolver objects, each maintaining its own state
information such as the nameservers to be queried, whether recursion is
desired, etc.

Packet Objects
--------------

   `Net::DNS::Resolver' queries return `Net::DNS::Packet' objects.  Packet
objects have five sections:

   * The header section, a `Net::DNS::Header' object.

   * The question section, a list of `Net::DNS::Question' objects.

   * The answer section, a list of `Net::DNS::RR' objects.

   * The authority section, a list of `Net::DNS::RR' objects.

   * The additional section, a list of `Net::DNS::RR' objects.

   The `Net::DNS::Update' package is a front-end to `Net::DNS::Packet' for
creating packet objects to be used in dynamic updates.

Header Objects
--------------

   `Net::DNS::Header' objects represent the header section of a DNS packet.

Question Objects
----------------

   `Net::DNS::Question' objects represent the question section of a DNS
packet.

RR Objects
----------

   `Net::DNS::RR' is the base class for DNS resource record (RR) objects in
the answer, authority, and additional sections of a DNS packet.

   Don't assume that RR objects will be of the type you requested - always
check an RR object's type before calling any of its methods.

METHODS
=======

   See the manual pages listed above for other class-specific methods.

version
-------

     print Net::DNS->version, "\n";

   Returns the version of Net::DNS.

mx
--

     # Use a default resolver -- can't get an error string this way.
     use Net::DNS;
     @mx = mx("foo.com");

     # Use your own resolver object.
     use Net::DNS;
     $res = new Net::DNS::Resolver;
     @mx = mx($res, "foo.com");

   Returns a list of `Net::DNS::RR::MX' objects representing the MX
records for the specified name; the list will be sorted by preference.
Returns an empty list if the query failed or no MX records were found.

   This method does not look up A records - it only performs MX queries.

   See `' in this node for a more complete example.

yxrrset
-------

   Use this method to add an "RRset exists" prerequisite to a dynamic
update packet.  There are two forms, value-independent and value-dependent:

     # RRset exists (value-independent)
     $packet->push("pre", yxrrset("foo.bar.com A"));

   Meaning:  At least one RR with the specified name and type must exist.

     # RRset exists (value-dependent)
     $packet->push("pre", yxrrset("foo.bar.com A 10.1.2.3"));

   Meaning:  At least one RR with the specified name and type must exist
and must have matching data.

   Returns a `Net::DNS::RR' object or undef if the object couldn't be
created.

nxrrset
-------

   Use this method to add an "RRset does not exist" prerequisite to a
dynamic update packet.

     $packet->push("pre", nxrrset("foo.bar.com A"));

   Meaning:  No RRs with the specified name and type can exist.

   Returns a `Net::DNS::RR' object or undef if the object couldn't be
created.

yxdomain
--------

   Use this method to add a "name is in use" prerequisite to a dynamic
update packet.

     $packet->push("pre", yxdomain("foo.bar.com"));

   Meaning:  At least one RR with the specified name must exist.

   Returns a `Net::DNS::RR' object or undef if the object couldn't be
created.

nxdomain
--------

   Use this method to add a "name is not in use" prerequisite to a dynamic
update packet.

     $packet->push("pre", nxdomain("foo.bar.com"));

   Meaning:  No RR with the specified name can exist.

   Returns a `Net::DNS::RR' object or undef if the object couldn't be
created.

rr_add
------

   Use this method to add RRs to a zone.

     $packet->push("update", rr_add("foo.bar.com A 10.1.2.3"));

   Meaning:  Add this RR to the zone.

   RR objects created by this method should be added to the "update"
section of a dynamic update packet.  The TTL defaults to 86400 seconds (24
hours) if not specified.

   Returns a `Net::DNS::RR' object or undef if the object couldn't be
created.

rr_del
------

   Use this method to delete RRs from a zone.  There are three forms:
delete an RRset, delete all RRsets, and delete an RR.

     # Delete an RRset.
     $packet->push("update", rr_del("foo.bar.com A"));

   Meaning:  Delete all RRs having the specified name and type.

     # Delete all RRsets.
     $packet->push("update", rr_del("foo.bar.com"));

   Meaning:  Delete all RRs having the specified name.

     # Delete an RR.
     $packet->push("update", rr_del("foo.bar.com A 10.1.2.3"));

   Meaning:  Delete all RRs having the specified name, type, and data.

   RR objects created by this method should be added to the "update"
section of a dynamic update packet.

   Returns a `Net::DNS::RR' object or undef if the object couldn't be
created.

EXAMPLES
========

   The following examples show how to use the `Net::DNS' modules.  See the
other manual pages and the demo scripts included with the source code for
additional examples.

   See the `Net::DNS::Update' manual page for an example of performing
dynamic updates.

Look up a host's addresses.
---------------------------

     use Net::DNS;
     $res = new Net::DNS::Resolver;
     $query = $res->search("foo.bar.com");
     if ($query) {
         foreach $rr ($query->answer) {
             next unless $rr->type eq "A";
             print $rr->address, "\n";
         }
     }
     else {
         print "query failed: ", $res->errorstring, "\n";
     }

Find the nameservers for a domain.
----------------------------------

     use Net::DNS;
     $res = new Net::DNS::Resolver;
     $query = $res->query("foo.com", "NS");
     if ($query) {
         foreach $rr ($query->answer) {
             next unless $rr->type eq "NS";
             print $rr->nsdname, "\n";
         }
     }
     else {
         print "query failed: ", $res->errorstring, "\n";
     }

Find the MX records for a domain.
---------------------------------

     use Net::DNS;
     $name = "foo.com";
     $res = new Net::DNS::Resolver;
     @mx = mx($res, $name);
     if (@mx) {
         foreach $rr (@mx) {
             print $rr->preference, " ", $rr->exchange, "\n";
         }
     }
     else {
         print "can't find MX records for $name: ", $res->errorstring, "\n";
     }

Print a domain's SOA record in zone file format.
------------------------------------------------

     use Net::DNS;
     $res = new Net::DNS::Resolver;
     $query = $res->query("foo.com", "SOA");
     if ($query) {
         ($query->answer)[0]->print;
     }
     else {
         print "query failed: ", $res->errorstring, "\n";
     }

Perform a zone transfer and print all the records.
--------------------------------------------------

     use Net::DNS;
     $res = new Net::DNS::Resolver;
     $res->nameservers("ns.foo.com");
     @zone = $res->axfr("foo.com");
     foreach $rr (@zone) {
         $rr->print;
     }

Perform a background query and do some other work while waiting for the answer.
-------------------------------------------------------------------------------

     use Net::DNS;
     $res = new Net::DNS::Resolver;
     $socket = $res->bgsend("foo.bar.com");
     until ($res->bgisready($socket)) {
         # do some work here while waiting for the answer
         # ...and some more here
     }
     $packet = $res->bgread($socket);
     $packet->print;

Send a background query and use select to determine when the answer has arrived.
--------------------------------------------------------------------------------

     use Net::DNS;
     use IO::Select;
     $timeout = 5;
     $res = new Net::DNS::Resolver;
     $bgsock = $res->bgsend("foo.bar.com");
     $sel = new IO::Select($bgsock);
     # Add more sockets to $sel if desired.
     @ready = $sel->can_read($timeout);
     if (@ready) {
         foreach $sock (@ready) {
             if ($sock == $bgsock) {
                 $packet = $res->bgread($bgsock);
                 $packet->print;
                 $bgsock = undef;
             }
     	  # Check for the other sockets.
     	  $sel->remove($sock);
     	  $sock = undef;
         }
     }
     else {
         print "timed out after $timeout seconds\n";
     }

BUGS
====

   `Net::DNS' is slow.  Real slow.

   For other items to be fixed, please see the TODO file included with the
source distribution.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

AUTHOR INFORMATION
==================

   Michael Fuhr <mfuhr@dimensional.com>
http://www.dimensional.com/~mfuhr/perldns/

SEE ALSO   `perl(1)' in this node, see Net/DNS/Resolver, Net/DNS/Packet, Net/DNS/Update, Net/DNS/Header, Net/DNS/Question, Net/DNS/RR, RFC 1035, *DNS and BIND* by Paul Albitz & Cricket Liu
==================================================================================================================================================================================================================================================================================================================================

DNS packet header class
***********************

NAME
====

   Net::DNS::Header - DNS packet header class

SYNOPSIS
========

   `use Net::DNS::Header;'

DESCRIPTION
===========

   A `Net::DNS::Header' object represents the header portion of a DNS
packet.

METHODS
=======

new
---

     $header = new Net::DNS::Header;
     $header = new Net::DNS::Header(\$data);

   Without an argument, new creates a header object appropriate for making
a DNS query.

   If new is passed a reference to a scalar containing DNS packet data, it
creates a header object from that data.

   Returns undef if unable to create a header object (e.g., if the data is
incomplete).

print
-----

     $header->print;

   Dumps the header data to the standard output.

string
------

     print $header->string;

   Returns a string representation of the header object.

id
--

     print "query id = ", $header->id, "\n";
     $header->id(1234);

   Gets or sets the query identification number.

qr
--

     print "query response flag = ", $header->qr, "\n";
     $header->qr(0);

   Gets or sets the query response flag.

opcode
------

     print "query opcode = ", $header->opcode, "\n";
     $header->opcode("UPDATE");

   Gets or sets the query opcode (the purpose of the query).

aa
--

     print "answer is ", $header->aa ? "" : "non-", "authoritative\n";
     $header->aa(0);

   Gets or sets the authoritative answer flag.

tc
--

     print "packet is ", $header->tc ? "" : "not ", "truncated\n";
     $header->tc(0);

   Gets or sets the truncated packet flag.

rd
--

     print "recursion was ", $header->rd ? "" : "not ", "desired\n";
     $header->rd(0);

   Gets or sets the recursion desired flag.

ra
--

     print "recursion is ", $header->ra ? "" : "not ", "available\n";
     $header->ra(0);

   Gets or sets the recursion available flag.

rcode
-----

     print "query response code = ", $header->rcode, "\n";
     $header->rcode("SERVFAIL");

   Gets or sets the query response code (the status of the query).

qdcount, zocount
----------------

     print "# of question records: ", $header->qdcount, "\n";
     $header->qdcount(2);

   Gets or sets the number of records in the question section of the
packet.  In dynamic update packets, this field is known as `zocount' and
refers to the number of RRs in the zone section.

ancount, prcount
----------------

     print "# of answer records: ", $header->ancount, "\n";
     $header->ancount(5);

   Gets or sets the number of records in the answer section of the packet.
In dynamic update packets, this field is known as `prcount' and refers to
the number of RRs in the prerequisite section.

nscount, upcount
----------------

     print "# of authority records: ", $header->nscount, "\n";
     $header->nscount(2);

   Gets or sets the number of records in the authority section of the
packet.  In dynamic update packets, this field is known as `upcount' and
refers to the number of RRs in the update section.

arcount, adcount
----------------

     print "# of additional records: ", $header->arcount, "\n";
     $header->arcount(3);

   Gets or sets the number of records in the additional section of the
packet.  In dynamic update packets, this field is known as `adcount'.

data
----

     $hdata = $header->data;

   Returns the header data in binary format, appropriate for use in a DNS
query packet.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Update, Net/DNS/Question,
see Net/DNS/RR, RFC 1035 Section 4.1.1

DNS packet object class
***********************

NAME
====

   Net::DNS::Packet - DNS packet object class

SYNOPSIS
========

   `use Net::DNS::Packet;'

DESCRIPTION
===========

   A `Net::DNS::Packet' object represents a DNS packet.

METHODS
=======

new
---

     $packet = new Net::DNS::Packet(\$data);
     $packet = new Net::DNS::Packet(\$data, 1);  # set debugging

     $packet = new Net::DNS::Packet("foo.com");
     $packet = new Net::DNS::Packet("foo.com", "MX", "IN");

     ($packet, $err) = new Net::DNS::Packet(\$data);

   If passed a reference to a scalar containing DNS packet data, new
creates a packet object from that data.  A second argument can be passed
to turn on debugging output for packet parsing.

   If passed a domain, type, and class, new creates a packet object
appropriate for making a DNS query for the requested information.  The
type and class can be omitted; they default to A and IN.

   If called in array context, returns a packet object and an error
string.  The error string will only be defined if the packet object is
undefined (i.e., couldn't be created).

   Returns undef if unable to create a packet object (e.g., if the packet
data is truncated).

data
----

     $data = $packet->data;

   Returns the packet data in binary format, suitable for sending to a
nameserver.

header
------

     $header = $packet->header;

   Returns a `Net::DNS::Header' object representing the header section of
the packet.

question, zone
--------------

     @question = $packet->question;

   Returns a list of `Net::DNS::Question' objects representing the
question section of the packet.

   In dynamic update packets, this section is known as `zone' and
specifies the zone to be updated.

answer, pre, prerequisite
-------------------------

     @answer = $packet->answer;

   Returns a list of `Net::DNS::RR' objects representing the answer
section of the packet.

   In dynamic update packets, this section is known as pre or
`prerequisite' and specifies the RRs or RRsets which must or must not
preexist.

authority, update
-----------------

     @authority = $packet->authority;

   Returns a list of `Net::DNS::RR' objects representing the authority
section of the packet.

   In dynamic update packets, this section is known as update and
specifies the RRs or RRsets to be added or delted.

additional
----------

     @additional = $packet->additional;

   Returns a list of `Net::DNS::RR' objects representing the additional
section of the packet.

print
-----

     $packet->print;

   Prints the packet data on the standard output in an ASCII format
similar to that used in DNS zone files.

string
------

     print $packet->string;

   Returns a string representation of the packet.

answerfrom
----------

     print "packet received from ", $packet->answerfrom, "\n";

   Returns the IP address from which we received this packet.  User-created
packets will return undef for this method.

answersize
----------

     print "packet size: ", $packet->answersize, " bytes\n";

   Returns the size of the packet in bytes as it was received from a
nameserver.  User-created packets will return undef for this method (use
`length $packet'->data instead).

push
----

     $packet->push("pre", $rr);
     $packet->push("update", $rr);
     $packet->push("additional", $rr);

     $packet->push("update", $rr1, $rr2, $rr3);
     $packet->push("update", @rr);

   Adds RRs to the specified section of the packet.

dn_comp
-------

     $compname = $packet->dn_comp("foo.bar.com", $offset);

   Returns a domain name compressed for a particular packet object, to be
stored beginning at the given offset within the packet data.  The name
will be added to a running list of compressed domain names for future use.

dn_expand
---------

     use Net::DNS::Packet qw(dn_expand);
     ($name, $nextoffset) = dn_expand(\$data, $offset);

     ($name, $nextoffset) = Net::DNS::Packet::dn_expand(\$data, $offset);

   Expands the domain name stored at a particular location in a DNS
packet.  The first argument is a reference to a scalar containing the
packet data.  The second argument is the offset within the packet where
the (possibly compressed) domain name is stored.

   Returns the domain name and the offset of the next location in the
packet.

   Returns *(undef, undef)* if the domain name couldn't be expanded.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Update,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1035 Section 4.1,
RFC 2136 Section 2

DNS question class
******************

NAME
====

   Net::DNS::Question - DNS question class

SYNOPSIS
========

   `use Net::DNS::Question'

DESCRIPTION
===========

   A `Net::DNS::Question' object represents a record in the question
section of a DNS packet.

METHODS
=======

new
---

     $question = new Net::DNS::Question("foo.com", "MX", "IN");

   Creates a question object from the domain, type, and class passed as
arguments.

qname, zname
------------

     print "qname = ", $question->qname, "\n";
     print "zname = ", $question->zname, "\n";

   Returns the domain name.  In dynamic update packets, this field is
known as `zname' and refers to the zone name.

qtype, ztype
------------

     print "qtype = ", $question->qtype, "\n";
     print "ztype = ", $question->ztype, "\n";

   Returns the record type.  In dymamic update packets, this field is
known as `ztype' and refers to the zone type (must be SOA).

qclass, zclass
--------------

     print "qclass = ", $question->qclass, "\n";
     print "zclass = ", $question->zclass, "\n";

   Returns the record class.  In dynamic update packets, this field is
known as `zclass' and refers to the zone's class.

print
-----

     $question->print;

   Prints the question record on the standard output.

string
------

     print $qr->string, "\n";

   Returns a string representation of the question record.

data
----

     $qdata = $question->data($packet, $offset);

   Returns the question record in binary format suitable for inclusion in
a DNS packet.

   Arguments are a `Net::DNS::Packet' object and the offset within that
packet's data where the `Net::DNS::Question' record is to be stored.  This
information is necessary for using compressed domain names.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Update, Net/DNS/Header,
see Net/DNS/RR, RFC 1035 Section 4.1.2

DNS Resource Record class
*************************

NAME
====

   Net::DNS::RR - DNS Resource Record class

SYNOPSIS
========

   `use Net::DNS::RR'

DESCRIPTION
===========

   `Net::DNS::RR' is the base class for DNS Resource Record (RR) objects.
See also the manual pages for each RR type.

METHODS
=======

   WARNING!!!  Don't assume the RR objects you receive from a query are of
a particular type - always check an object's type before calling any of
its methods.  If you call an unknown method, you'll get a nasty warning
message and `Net::DNS::RR' will return undef to the caller.

new (from string)
-----------------

     $a = new Net::DNS::RR("foo.bar.com. 86400 A 10.1.2.3");
     $mx = new Net::DNS::RR("bar.com. 7200 MX 10 mailhost.bar.com.");
     $cname = new Net::DNS::RR("www.bar.com 300 IN CNAME www1.bar.com");
     $txt = new Net::DNS::RR("baz.bar.com 3600 HS TXT 'text record'");

   Returns a `Net::DNS::RR' object of the appropriate type and initialized
from the string passed by the user.  The format of the string is that used
in zone files, and is compatible with the string returned by
`Net::DNS::RR'->string.

   The name and RR type are required; all other information is optional.
If omitted, the TTL defaults to 0 and the RR class defaults to IN.
Omitting the optional fields is useful for creating the empty RDATA
sections required for certain dynamic update operations.  See the
`Net::DNS::Update' manual page for additional examples.

   All names must be fully qualified.  The trailing dot (.) is optional.

new (from hash)
---------------

     $rr = new Net::DNS::RR(
     	Name    => "foo.bar.com",
     	TTL     => 86400,
     	Class   => "IN",
         Type    => "A",
     	Address => "10.1.2.3",
     );

     $rr = new Net::DNS::RR(
     	Name    => "foo.bar.com",
         Type    => "A",
     );

   Returns an RR object of the appropriate type, or a `Net::DNS::RR'
object if the type isn't implemented.  See the manual pages for each RR
type to see what fields the type requires.

   The Name and Type fields are required; all others are optional.  If
omitted, `TTL' defaults to 0 and Class defaults to IN.  Omitting the
optional fields is useful for creating the empty RDATA sections required
for certain dynamic update operations.

   The fields are case-insensitive, but starting each with uppercase is
recommended.

print
-----

     $rr->print;

   Prints the record to the standard output.  Calls the string method to
get the RR's string representation.

string
------

     print $rr->string, "\n";

   Returns a string representation of the RR.  Calls the rdatastr method
to get the RR-specific data.

rdatastr
--------

     $s = $rr->rdatastr;

   Returns a string containing RR-specific data.  Subclasses will need to
implement this method.

name
----

     $name = $rr->name;

   Returns the record's domain name.

type
----

     $type = $rr->type;

   Returns the record's type.

class
-----

     $class = $rr->class;

   Returns the record's class.

ttl
---

     $ttl = $rr->ttl;

   Returns the record's time-to-live (TTL).

rdlength
--------

     $rdlength = $rr->rdlength;

   Returns the length of the record's data section.

rdata
-----

     $rdata = $rr->rdata

   Returns the record's data section as binary data.

BUGS
====

   This version of `Net::DNS::RR' does little sanity checking on
user-created RR objects.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Update, Net/DNS/Header,
see Net/DNS/Question, RFC 1035
Section 4.1.3

DNS A resource record
*********************

NAME
====

   Net::DNS::RR::A - DNS A resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS Address (A) resource records.

METHODS
=======

address
-------

     print "address = ", $rr->address, "\n";

   Returns the RR's address field.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1035 Section 3.4.1

DNS AAAA resource record
************************

NAME
====

   Net::DNS::RR::AAAA - DNS AAAA resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS IPv6 Address (AAAA) resource records.

METHODS
=======

address
-------

     print "address = ", $rr->address, "\n";

   Returns the RR's address field.

BUGS
====

   The string method returns only the preferred method of address
representation ("x:x:x:x:x:x:x:x", as documented in RFC 1884, Section 2.2,
Para 1).

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1886 Section 2, RFC
1884 Sections 2.2 & 2.4.4

DNS AFSDB resource record
*************************

NAME
====

   Net::DNS::RR::AFSDB - DNS AFSDB resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS AFS Data Base (AFSDB) resource records.

METHODS
=======

subtype
-------

     print "subtype = ", $rr->subtype, "\n";

   Returns the RR's subtype field.  Use of the subtype field is documented
in RFC 1183.

hostname
--------

     print "hostname = ", $rr->hostname, "\n";

   Returns the RR's hostname field.  See RFC 1183.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1183 Section 1

DNS CNAME resource record
*************************

NAME
====

   Net::DNS::RR::CNAME - DNS CNAME resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS Canonical Name (CNAME) resource records.

METHODS
=======

cname
-----

     print "cname = ", $rr->cname, "\n";

   Returns the RR's canonical name.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1035 Section 3.3.1

DNS EID resource record
***********************

NAME
====

   Net::DNS::RR::EID - DNS EID resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS Endpoint Identifier (EID) resource records.

METHODS
=======

rdlength
--------

     print "rdlength = ", $rr->rdlength, "\n";

   Returns the length of the record's data section.

rdata
-----

     $rdata = $rr->rdata;

   Returns the record's data section as binary data.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR,
draft-ietf-nimrod-dns-*xx*.txt

DNS HINFO resource record
*************************

NAME
====

   Net::DNS::RR::HINFO - DNS HINFO resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS Host Information (HINFO) resource records.

METHODS
=======

cpu
---

     print "cpu = ", $rr->cpu, "\n";

   Returns the CPU type for this RR.

os
--

     print "os = ", $rr->os, "\n";

   Returns the operating system type for this RR.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1035 Section 3.3.2

DNS ISDN resource record
************************

NAME
====

   Net::DNS::RR::ISDN - DNS ISDN resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS ISDN resource records.

METHODS
=======

address
-------

     print "address = ", $rr->address, "\n";

   Returns the RR's address field.

sa
--

     print "subaddress = ", $rr->sa, "\n";

   Returns the RR's subaddress field.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1183 Section 3.2

DNS LOC resource record
***********************

NAME
====

   Net::DNS::RR::LOC - DNS LOC resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS Location (LOC) resource records.  See RFC 1876 for
details.

METHODS
=======

version
-------

     print "version = ", $rr->version, "\n";

   Returns the version number of the representation; programs should
always check this.  `Net::DNS' currently supports only version 0.

size
----

     print "size = ", $rr->size, "\n";

   Returns the diameter of a sphere enclosing the described entity, in
centimeters.

horiz_pre
---------

     print "horiz_pre = ", $rr->horiz_pre, "\n";

   Returns the horizontal precision of the data, in centimeters.

vert_pre
--------

     print "vert_pre = ", $rr->vert_pre, "\n";

   Returns the vertical precision of the data, in centimeters.

latitude
--------

     print "latitude = ", $rr->latitude, "\n";

   Returns the latitude of the center of the sphere described by the size
method, in thousandths of a second of arc.  2**31 represents the equator;
numbers above that are north latitude.

longitude
---------

     print "longitude = ", $rr->longitude, "\n";

   Returns the longitude of the center of the sphere described by the size
method, in thousandths of a second of arc.  2**31 represents the prime
meridian; numbers above that are east longitude.

latlon
------

     ($lat, $lon) = $rr->latlon;
     system("xearth", "-pos", "fixed $lat $lon");

   Returns the latitude and longitude as floating-point degrees.  Positive
numbers represent north latitude or east longitude; negative numbers
represent south latitude or west longitude.

altitude
--------

     print "altitude = ", $rr->altitude, "\n";

   Returns the altitude of the center of the sphere described by the size
method, in centimeters, from a base of 100,000m below the WGS 84 reference
spheroid used by GPS.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

   Some of the code and documentation is based on RFC 1876 and on code
contributed by Christopher Davis.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1876

DNS MB resource record
**********************

NAME
====

   Net::DNS::RR::MB - DNS MB resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS Mailbox (MB) resource records.

METHODS
=======

madname
-------

     print "madname = ", $rr->madname, "\n";

   Returns the domain name of the host which has the specified mailbox.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1035 Section 3.3.3

DNS MG resource record
**********************

NAME
====

   Net::DNS::RR::MG - DNS MG resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS Mail Group (MG) resource records.

METHODS
=======

mgmname
-------

     print "mgmname = ", $rr->mgmname, "\n";

   Returns the RR's mailbox field.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1035 Section 3.3.6

DNS MINFO resource record
*************************

NAME
====

   Net::DNS::RR::MINFO - DNS MINFO resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS Mailbox Information (MINFO) resource records.

METHODS
=======

rmailbx
-------

     print "rmailbx = ", $rr->rmailbx, "\n";

   Returns the RR's responsible mailbox field.  See RFC 1035.

emailbx
-------

     print "emailbx = ", $rr->emailbx, "\n";

   Returns the RR's error mailbox field.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1035 Section 3.3.7

DNS MR resource record
**********************

NAME
====

   Net::DNS::RR::MR - DNS MR resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS Mail Rename (MR) resource records.

METHODS
=======

newname
-------

     print "newname = ", $rr->newname, "\n";

   Returns the RR's new name field.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1035 Section 3.3.8

DNS MX resource record
**********************

NAME
====

   Net::DNS::RR::MX - DNS MX resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS Mail Exchanger (MX) resource records.

METHODS
=======

preference
----------

     print "preference = ", $rr->preference, "\n";

   Returns the preference for this mail exchange.

exchange
--------

     print "exchange = ", $rr->exchange, "\n";

   Returns name of this mail exchange.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1035 Section 3.3.9

DNS NAPTR resource record
*************************

NAME
====

   Net::DNS::RR::NAPTR - DNS NAPTR resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS Naming Authority Pointer (NAPTR) resource records.

METHODS
=======

order
-----

     print "order = ", $rr->order, "\n";

   Returns the order field.

preference
----------

     print "preference = ", $rr->preference, "\n";

   Returns the preference field.

flags
-----

     print "flags = ", $rr->flags, "\n";

   Returns the flags field.

service
-------

     print "service = ", $rr->service, "\n";

   Returns the service field.

regexp
------

     print "regexp = ", $rr->regexp, "\n";

   Returns the regexp field.

replacement
-----------

     print "replacement = ", $rr->replacement, "\n";

   Returns the replacement field.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

   *Net::DNS::RR::NAPTR* is based on code contributed by Ryan Moats.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 2168

DNS NIMLOC resource record
**************************

NAME
====

   Net::DNS::RR::NIMLOC - DNS NIMLOC resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS Nimrod Locator (NIMLOC) resource records.

METHODS
=======

rdlength
--------

     print "rdlength = ", $rr->rdlength, "\n";

   Returns the length of the record's data section.

rdata
-----

     $rdata = $rr->rdata;

   Returns the record's data section as binary data.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR,
draft-ietf-nimrod-dns-*xx*.txt

DNS NS resource record
**********************

NAME
====

   Net::DNS::RR::NS - DNS NS resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS Name Server (NS) resource records.

METHODS
=======

nsdname
-------

     print "nsdname = ", $rr->nsdname, "\n";

   Returns the domain name of the nameserver.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1035 Section 3.3.11

DNS NSAP resource record
************************

NAME
====

   Net::DNS::RR::NSAP - DNS NSAP resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS Network Service Access Point (NSAP) resource records.

METHODS
=======

idp
---

     print "idp = ", $rr->idp, "\n";

   Returns the RR's initial domain part (the AFI and IDI fields).

dsp
---

     print "dsp = ", $rr->dsp, "\n";

   Returns the RR's domain specific part (the DFI, AA, Rsvd, RD, Area, ID,
and SEL fields).

afi
---

     print "afi = ", $rr->afi, "\n";

   Returns the RR's authority and format identifier.  `Net::DNS' currently
supports only AFI 47 (GOSIP Version 2).

idi
---

     print "idi = ", $rr->idi, "\n";

   Returns the RR's initial domain identifier.

dfi
---

     print "dfi = ", $rr->dfi, "\n";

   Returns the RR's DSP format identifier.

aa
--

     print "aa = ", $rr->aa, "\n";

   Returns the RR's administrative authority.

rsvd
----

     print "rsvd = ", $rr->rsvd, "\n";

   Returns the RR's reserved field.

rd
--

     print "rd = ", $rr->rd, "\n";

   Returns the RR's routing domain identifier.

area
----

     print "area = ", $rr->area, "\n";

   Returns the RR's area identifier.

id
--

     print "id = ", $rr->id, "\n";

   Returns the RR's system identifier.

sel
---

     print "sel = ", $rr->sel, "\n";

   Returns the RR's NSAP selector.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1706.

DNS NULL resource record
************************

NAME
====

   Net::DNS::RR::NULL - DNS NULL resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS Null (NULL) resource records.

METHODS
=======

rdlength
--------

     print "rdlength = ", $rr->rdlength, "\n";

   Returns the length of the record's data section.

rdata
-----

     $rdata = $rr->rdata;

   Returns the record's data section as binary data.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1035 Section 3.3.10

DNS PTR resource record
***********************

NAME
====

   Net::DNS::RR::PTR - DNS PTR resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS Pointer (PTR) resource records.

METHODS
=======

ptrdname
--------

     print "ptrdname = ", $rr->ptrdname, "\n";

   Returns the domain name associated with this record.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1035 Section 3.3.12

DNS PX resource record
**********************

NAME
====

   Net::DNS::RR::PX - DNS PX resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS X.400 Mail Mapping Information (PX) resource records.

METHODS
=======

preference
----------

     print "preference = ", $rr->preference, "\n";

   Returns the preference given to this RR.

map822
------

     print "map822 = ", $rr->map822, "\n";

   Returns the RFC822 part of the RFC1327 mapping information.

mapx400
-------

     print "mapx400 = ", $rr->mapx400, "\n";

   Returns the X.400 part of the RFC1327 mapping information.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1664 Section 4, RFC
1327

DNS RP resource record
**********************

NAME
====

   Net::DNS::RR::RP - DNS RP resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS Responsible Person (RP) resource records.

METHODS
=======

mbox
----

     print "mbox = ", $rr->mbox, "\n";

   Returns a domain name that specifies the mailbox for the responsible
person.

txtdname
--------

     print "txtdname = ", $rr->txtdname, "\n";

   Returns a domain name that specifies a TXT record containing further
information about the responsible person.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1183 Section 2.2

DNS RT resource record
**********************

NAME
====

   Net::DNS::RR::RT - DNS RT resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS Route Through (RT) resource records.

METHODS
=======

preference
----------

     print "preference = ", $rr->preference, "\n";

   Returns the preference for this route.

intermediate
------------

     print "intermediate = ", $rr->intermediate, "\n";

   Returns the domain name of the intermediate host.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1183 Section 3.3

DNS SOA resource record
***********************

NAME
====

   Net::DNS::RR::SOA - DNS SOA resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS Start of Authority (SOA) resource records.

METHODS
=======

mname
-----

     print "mname = ", $rr->mname, "\n";

   Returns the domain name of the original or primary nameserver for this
zone.

rname
-----

     print "rname = ", $rr->rname, "\n";

   Returns a domain name that specifies the mailbox for the person
responsible for this zone.

serial
------

     print "serial = ", $rr->serial, "\n";

   Returns the zone's serial number.

refresh
-------

     print "refresh = ", $rr->refresh, "\n";

   Returns the zone's refresh interval.

retry
-----

     print "retry = ", $rr->retry, "\n";

   Returns the zone's retry interval.

expire
------

     print "expire = ", $rr->expire, "\n";

   Returns the zone's expire interval.

minimum
-------

     print "minimum = ", $rr->minimum, "\n";

   Returns the minimum (default) TTL for records in this zone.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1035 Section 3.3.13

DNS SRV resource record
***********************

NAME
====

   Net::DNS::RR::SRV - DNS SRV resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS Service (SRV) resource records.

METHODS
=======

priority
--------

     print "priority = ", $rr->priority, "\n";

   Returns the priority for this target host.

weight
------

     print "weight = ", $rr->weight, "\n";

   Returns the weight for this target host.

port
----

     print "port = ", $rr->port, "\n";

   Returns the port on this target host for the service.

target
------

     print "target = ", $rr->target, "\n";

   Returns the target host.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 2052

DNS TXT resource record
***********************

NAME
====

   Net::DNS::RR::TXT - DNS TXT resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS Text (TXT) resource records.

METHODS
=======

txtdata
-------

     print "txtdata = ", $rr->txtdata, "\n";

   Returns the descriptive text.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1035 Section 3.3.14

DNS X25 resource record
***********************

NAME
====

   Net::DNS::RR::X25 - DNS X25 resource record

SYNOPSIS
========

   `use Net::DNS::RR';

DESCRIPTION
===========

   Class for DNS X25 resource records.

METHODS
=======

psdn
----

     print "psdn = ", $rr->psdn, "\n";

   Returns the PSDN address.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Packet,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, RFC 1183 Section 3.1

DNS resolver class
******************

NAME
====

   Net::DNS::Resolver - DNS resolver class

SYNOPSIS
========

   `use Net::DNS::Resolver;'

DESCRIPTION
===========

   Instances of the `Net::DNS::Resolver' class represent resolver objects.
A program can have multiple resolver objects, each maintaining its own
state information such as the nameservers to be queried, whether recursion
is desired, etc.

   Resolver configuration is read from the following files, in the order
indicated:

     /etc/resolv.conf
     $HOME/.resolv.conf
     ./.resolv.conf

   The following keywords are recognized in resolver configuration files:

domain
     The default domain.

search
     A space-separated list of domains to put in the search list.

nameserver
     A space-separated list of nameservers to query.

   Files except for `/etc/resolv.conf' must be owned by the effective
userid running the program or they won't be read.  In addition, several
environment variables can also contain configuration information; see `'
in this node.

METHODS
=======

new
---

     $res = new Net::DNS::Resolver;

   Creates a new DNS resolver object.

print
-----

     $res->print;

   Prints the resolver state on the standard output.

string
------

     print $res->string;

   Returns a string representation of the resolver state.

searchlist
----------

     @searchlist = $res->searchlist;
     $res->searchlist("foo.com", "bar.com", "baz.org");

   Gets or sets the resolver search list.

nameservers
-----------

     @nameservers = $res->nameservers;
     $res->nameservers("192.168.1.1", "192.168.2.2", "192.168.3.3");

   Gets or sets the nameservers to be queried.

port
----

     print "sending queries to port ", $res->port, "\n";
     $res->port(9732);

   Gets or sets the port to which we send queries.  This can be useful for
testing a nameserver running on a non-standard port.  The default is port
53.

search
------

     $packet = $res->search("mailhost");
     $packet = $res->search("mailhost.foo.com");
     $packet = $res->search("192.168.1.1");
     $packet = $res->search("foo.com", "MX");
     $packet = $res->search("user.passwd.foo.com", "TXT", "HS");

   Performs a DNS query for the given name, applying the searchlist if
appropriate.  The search algorithm is as follows:

  1. If the name contains at least one dot, try it as is.

  2. If the name doesn't end in a dot then append each item in the search
     list to the name.  This is only done if dnsrch is true.

  3. If the name doesn't contain any dots, try it as is.

        The record type and class can be omitted; they default to A and
IN.  If the name looks like an IP address (4 dot-separated numbers), then
an appropriate PTR query will be performed.

   Returns a `Net::DNS::Packet' object, or undef if no answers were found.

query
-----

     $packet = $res->query("mailhost");
     $packet = $res->query("mailhost.foo.com");
     $packet = $res->query("192.168.1.1");
     $packet = $res->query("foo.com", "MX");
     $packet = $res->query("user.passwd.foo.com", "TXT", "HS");

   Performs a DNS query for the given name; the search list is not
applied.  If the name doesn't contain any dots and defnames is true then
the default domain will be appended.

   The record type and class can be omitted; they default to A and IN.  If
the name looks like an IP address (4 dot-separated numbers), then an
appropriate PTR query will be performed.

   Returns a `Net::DNS::Packet' object, or undef if no answers were found.

send
----

     $packet = $res->send($packet_object);
     $packet = $res->send("mailhost.foo.com");
     $packet = $res->send("foo.com", "MX");
     $packet = $res->send("user.passwd.foo.com", "TXT", "HS");

   Performs a DNS query for the given name.  Neither the searchlist nor
the default domain will be appended.

   The argument list can be either a `Net::DNS::Packet' object or a list
of strings.  The record type and class can be omitted; they default to A
and IN.  If the name looks like an IP address (4 dot-separated numbers),
then an appropriate PTR query will be performed.

   Returns a `Net::DNS::Packet' object whether there were any answers or
not.  Use `$packet'->header->`ancount' or `$packet'->`answer' to find out
if there were any records in the answer section.  Returns undef if there
was an error.

bgsend
------

     $socket = $res->bgsend($packet_object);
     $socket = $res->bgsend("mailhost.foo.com");
     $socket = $res->bgsend("foo.com", "MX");
     $socket = $res->bgsend("user.passwd.foo.com", "TXT", "HS");

   Performs a background DNS query for the given name, i.e., sends a query
packet to the first nameserver listed in $res->nameservers and returns
immediately without waiting for a response.  The program can then perform
other tasks while waiting for a response from the nameserver.

   The argument list can be either a `Net::DNS::Packet' object or a list
of strings.  The record type and class can be omitted; they default to A
and IN.  If the name looks like an IP address (4 dot-separated numbers),
then an appropriate PTR query will be performed.

   Returns an IO::Socket object.  The program must determine when the
socket is ready for reading and call $res->bgread to get the response
packet.  You can use $res->bgisready or IO::Select to find out if the
socket is ready before reading it.

bgread
------

     $packet = $res->bgread($socket);
     undef $socket;

   Reads the answer from a background query (see `' in this node).  The
argument is an IO::Socket object returned by bgsend.

   Returns a `Net::DNS::Packet' object or undef on error.

   The programmer should close or destroy the socket object after reading
it.

bgisready
---------

     $socket = $res->bgsend("foo.bar.com");
     until ($res->bgisready($socket)) {
     	# do some other processing
     }
     $packet = $res->bgread($socket);
     $socket = undef;

   Determines whether a socket is ready for reading.  The argument is an
IO::Socket object returned by $res->bgsend.

   Returns true if the socket is ready, false if not.

axfr
----

     @zone = $res->axfr;
     @zone = $res->axfr("foo.com");
     @zone = $res->axfr("passwd.foo.com", "HS");

   Performs a zone transfer from the first nameserver listed in
nameservers.  If the zone is omitted, it defaults to the first zone listed
in the resolver's search list.  If the class is omitted, it defaults to IN.

   Returns a list of `Net::DNS::RR' objects, or undef if the zone transfer
failed.

   The redundant SOA record that terminates the zone transfer is not
returned to the caller.

   Here's an example that uses a timeout:

     $res->tcp_timeout(10);
     @zone = $res->axfr("foo.com");
     if (@zone) {
         foreach $rr (@zone) {
             $rr->print;
         }
     }
     else {
         print "Zone transfer failed: ", $res->errorstring, "\n";
     }

tcp_timeout
-----------

     print "TCP timeout: ", $res->tcp_timeout, "\n";
     $res->tcp_timeout(10);

   Get or set the TCP timeout in seconds.  A timeout of undef means
indefinite.  The default is 120 seconds (2 minutes).

retrans
-------

     print "retrans interval: ", $res->retrans, "\n";
     $res->retrans(3);

   Get or set the retransmission interval.  The default is 5.

retry
-----

     print "number of tries: ", $res->retry, "\n";
     $res->retry(2);

   Get or set the number of times to try the query.  The default is 4.

recurse
-------

     print "recursion flag: ", $res->recurse, "\n";
     $res->recurse(0);

   Get or set the recursion flag.  If this is true, nameservers will be
requested to perform a recursive query.  The default is true.

defnames
--------

     print "defnames flag: ", $res->defnames, "\n";
     $res->defnames(0);

   Get or set the defnames flag.  If this is true, calls to query will
append the default domain to names that contain no dots.  The default is
true.

dnsrch
------

     print "dnsrch flag: ", $res->dnsrch, "\n";
     $res->dnsrch(0);

   Get or set the dnsrch flag.  If this is true, calls to search will
apply the search list.  The default is true.

debug
-----

     print "debug flag: ", $res->debug, "\n";
     $res->debug(1);

   Get or set the debug flag.  If set, calls to search, query, and send
will print debugging information on the standard output.  The default is
false.

usevc
-----

     print "usevc flag: ", $res->usevc, "\n";
     $res->usevc(1);

   Get or set the usevc flag.  If true, then queries will be performed
using virtual circuits (TCP) instead of datagrams (UDP).  The default is
false.

igntc
-----

     print "igntc flag: ", $res->igntc, "\n";
     $res->igntc(1);

   Get or set the igntc flag.  If true, truncated packets will be ignored.
If false, truncated packets will cause the query to be retried using TCP.
The default is false.

errorstring
-----------

     print "query status: ", $res->errorstring, "\n";

   Returns a string containing the status of the most recent query.

answerfrom
----------

     print "last answer was from: ", $res->answerfrom, "\n";

   Returns the IP address from which we received the last answer in
response to a query.

answersize
----------

     print "size of last answer: ", $res->answersize, "\n";

   Returns the size in bytes of the last answer we received in response to
a query.

ENVIRONMENT
===========

   The following environment variables can also be used to configure the
resolver:

RES_NAMESERVERS
---------------

     # Bourne Shell
     RES_NAMESERVERS="192.168.1.1 192.168.2.2 192.168.3.3"
     export RES_NAMESERVERS

     # C Shell
     setenv RES_NAMESERVERS "192.168.1.1 192.168.2.2 192.168.3.3"

   A space-separated list of nameservers to query.

RES_SEARCHLIST
--------------

     # Bourne Shell
     RES_SEARCHLIST="foo.com bar.com baz.org"
     export RES_SEARCHLIST

     # C Shell
     setenv RES_SEARCHLIST "foo.com bar.com baz.org"

   A space-separated list of domains to put in the search list.

LOCALDOMAIN
-----------

     # Bourne Shell
     LOCALDOMAIN=foo.com
     export LOCALDOMAIN

     # C Shell
     setenv LOCALDOMAIN foo.com

   The default domain.

RES_OPTIONS
-----------

     # Bourne Shell
     RES_OPTIONS="retrans:3 retry:2 debug"
     export RES_OPTIONS

     # C Shell
     setenv RES_OPTIONS "retrans:3 retry:2 debug"

   A space-separated list of resolver options to set.  Options that take
values are specified as option:value.

BUGS
====

   Error reporting and handling needs to be improved.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS, Net/DNS/Packet,
see Net/DNS/Update,
Net/DNS/Header, Net/DNS/Question,
see Net/DNS/RR, `resolver(5)' in this
node, RFC 1035, RFC 1034 Section 4.3.5

Create a DNS update packet
**************************

NAME
====

   Net::DNS::Update - Create a DNS update packet

SYNOPSIS
========

   `use Net::DNS::Update;'

DESCRIPTION
===========

   `Net::DNS::Update' is a front-end for creating `Net::DNS::Packet'
objects to be used for making DNS dynamic updates.  Programmers should
refer to RFC 2136 for the semantics of dynamic updates.

   WARNING:  This code is still under development and shouldn't be used to
maintain a production nameserver.

METHODS
=======

new
---

     $packet = new Net::DNS::Update;
     $packet = new Net::DNS::Update("foo.com");
     $packet = new Net::DNS::Update("foo.com", "HS");

   Returns a `Net::DNS::Packet' object suitable for performing a DNS
dynamic update.  Specifically, it creates a packet with the header opcode
set to UPDATE and the zone record type to SOA (per RFC 2136, Section 2.3).

   Programs must use the push method to add RRs to the prerequisite,
update, and additional sections before performing the update.

   Arguments are the zone name and the class.  If the zone is omitted, the
default domain will be taken from the resolver configuration.  If the
class is omitted, it defaults to IN.

   Future versions of `Net::DNS' may provide a simpler interface for
making dynamic updates.

EXAMPLES
========

   The first example below shows a complete program; subsequent examples
show only the creation of the update packet.

Add a new host
--------------

     #!/usr/local/bin/perl -w

     use Net::DNS;

     # Create the update packet.
     $update = new Net::DNS::Update("bar.com");

     # Prerequisite is that no A records exist for the name.
     $update->push("pre", nxrrset("foo.bar.com. A"));

     # Add two A records for the name.
     $update->push("update", rr_add("foo.bar.com. 86400 A 192.168.1.2"));
     $update->push("update", rr_add("foo.bar.com. 86400 A 172.16.3.4"));

     # Send the update to the zone's primary master.
     $res = new Net::DNS::Resolver;
     $res->nameservers("primary-master.bar.com");
     $reply = $res->send($update);

     # Did it work?
     if (defined $reply) {
     	if ($reply->header->rcode eq "NOERROR") {
     	    print "Update succeeded\n";
     	}
     	else {
             print "Update failed: ", $reply->header->rcode, "\n";
     	}
     }
     else {
         print "Update failed: ", $res->errorstring, "\n";
     }

Add an MX record for a name that already exists
-----------------------------------------------

     $update = new Net::DNS::Update("foo.com");
     $update->push("pre", yxdomain("foo.com"));
     $update->push("update", rr_add("foo.com MX 10 mailhost.foo.com"));

Add a TXT record for a name that doesn't exist
----------------------------------------------

     $update = new Net::DNS::Update("foo.com");
     $update->push("pre", nxdomain("info.foo.com"));
     $update->push("update", rr_add("info.foo.com TXT 'yabba dabba doo'"));

Delete all A records for a name
-------------------------------

     $update = new Net::DNS::Update("bar.com");
     $update->push("pre", yxrrset("foo.bar.com A"));
     $update->push("update", rr_del("foo.bar.com A"));

Delete all RRs for a name
-------------------------

     $update = new Net::DNS::Update("foo.com");
     $update->push("pre", yxdomain("byebye.foo.com"));
     $update->push("update", rr_del("byebye.foo.com"));

BUGS
====

   This code is still under development and shouldn't be used to maintain
a production nameserver.

COPYRIGHT
=========

   Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, see Net/DNS,
Net/DNS/Resolver, Net/DNS/Header,
Net/DNS/Packet, Net/DNS/Question,
see Net/DNS/RR, RFC 2136

Perl extension for portable daemons
***********************************

NAME
====

   Net::Daemon - Perl extension for portable daemons

SYNOPSIS
========

     # Create a subclass of Net::Daemon
     require Net::Daemon;
     package MyDaemon;
     @MyDaemon::ISA = qw(Net::Daemon);

     sub Run ($) {
       # This function does the real work; it is invoked whenever a
       # new connection is made.
     }

WARNING
=======

   THIS IS ALPHA SOFTWARE. It is *only* 'Alpha' because the interface (API)
is not finalised. The Alpha status does not reflect code quality or
stability.

DESCRIPTION
===========

   Net::Daemon is an abstract base class for implementing portable server
applications in a very simple way. The module is designed for Perl 5.005
and threads, but can work with fork() and Perl 5.004.

   The Net::Daemon class offers methods for the most common tasks a daemon
needs: Starting up, logging, accepting clients, authorization, restricting
its own environment for security and doing the true work. You only have to
override those methods that aren't appropriate for you, but typically
inheriting will safe you a lot of work anyways.

Constructors
------------

     $server = Net::Daemon->new($attr, $options);

     $connection = $server->Clone($socket);

   Two constructors are available: The new method is called upon startup
and creates an object that will basically act as an anchor over the
complete program. It supports command line parsing via `Getopt::Long (3)'
in this node.

   Arguments of new are *$attr*, an hash ref of attributes (see below) and
*$options* an array ref of options, typically command line arguments (for
example *\@ARGV*) that will be passed to *Getopt::Long::GetOptions*.

   The second constructor is Clone: It is called whenever a client
connects. It receives the main server object as input and returns a new
object. This new object will be passed to the methods that finally do the
true work of communicating with the client. Communication occurs over the
socket $socket, Clone's argument.

   Possible object attributes and the corresponding command line arguments
are:

catchint (*-nocatchint*)
     On some systems, in particular Solaris, the functions accept(),
     read() and so on are not safe against interrupts by signals. For
     example, if the user raises a USR1 signal (as typically used to
     reread config files), then the function returns an error EINTR.  If
     the catchint option is on (by default it is, use *-nocatchint* to
     turn this off), then the package will ignore EINTR errors whereever
     possible.

chroot (*-chroot=dir*)
     (UNIX only)  After doing a bind(), change root directory to the given
     directory by doing a chroot(). This is usefull for security
     operations, but it restricts programming a lot. For example, you
     typically have to load external Perl extensions before doing a
     chroot(), or you need to create hard links to Unix sockets. This is
     typically done in the config file, see the -configfile option. See
     also the -group and -user options.

     If you don't know chroot(), think of an FTP server where you can see a
     certain directory tree only after logging in.

clients
     An array ref with a list of clients. Clients are hash refs, the
     attributes accept (0 for denying access and 1 for permitting) and
     mask, a Perl regular expression for the clients IP number or its host
     name. See `"Access control"' in this node below.

configfile (*-configfile=file*)
     Net::Daemon supports the use of config files. These files are assumed
     to contain a single hash ref that overrides the arguments of the new
     method. However, command line arguments in turn take precedence over
     the config file. See the `"Config File"' in this node section below
     for details on the config file.

debug (*-debug*)
     Turn debugging mode on. Mainly this asserts that logging messages of
     level "debug" are created.

facility (*-facility=mode*)
     (UNIX only) Facility to use for `Sys::Syslog (3)' in this node. The
     default is *daemon*.

group (*-group=gid*)
     After doing a bind(), change the real and effective GID to the given.
     This is usefull, if you want your server to bind to a privileged port
     (<1024), but don't want the server to execute as root. See also the
     -user option.

     GID's can be passed as group names or numeric values.

localaddr (*-localaddr=ip*)
     By default a daemon is listening to any IP number that a machine has.
     This attribute allows to restrict the server to the given IP number.

localpath (*-localpath=path*)
     If you want to restrict your server to local services only, you'll
     prefer using Unix sockets, if available. In that case you can use
     this option for setting the path of the Unix socket being created.
     This option implies *-proto=unix*.

localport (*-localport=port*)
     This attribute sets the port on which the daemon is listening. It
     must be given somehow, as there's no default.

logfile (*-logfile=file*)
     By default logging messages will be written to the syslog (Unix) or
     to the event log (Windows NT). On other operating systems you need to
     specify a log file. The special value "STDERR" forces logging to
     stderr.

*loop-child* (*-loop-child*)
     This option forces creation of a new child for loops. (See the
     *loop-timeout* option.) By default the loops are serialized.

*loop-timeout* (*-loop-timeout=secs*)
     Some servers need to take an action from time to time. For example the
     Net::Daemon::Spooler attempts to empty its spooling queue every 5
     minutes. If this option is set to a positive value (zero being the
     default), then the server will call its Loop method every
     "loop-timeout" seconds.

     Don't trust too much on the precision of the interval: It depends on
     a number of factors, in particular the execution time of the Loop()
     method. The loop is implemented by using the select function. If you
     need an exact interval, you should better try to use the alarm()
     function and a signal handler. (And don't forget to look at the
     catchint option!)

     It is recommended to use the *loop-child* option in conjunction with
     *loop-timeout*.

mode (*-mode=modename*)
     The Net::Daemon server can run in three different modes, depending on
     the environment.

     If you are running Perl 5.005 and did compile it for threads, then
     the server will create a new thread for each connection. The thread
     will execute the server's Run() method and then terminate. This mode
     is the default, you can force it with "-mode=threads".

     If threads are not available, but you have a working fork(), then the
     server will behave similar by creating a new process for each
     connection.  This mode will be used automatically in the absence of
     threads or if you use the "-mode=fork" option.

     Finally there's a single-connection mode: If the server has accepted a
     connection, he will enter the Run() method. No other connections are
     accepted until the Run() method returns. This operation mode is
     usefull if you have neither threads nor fork(), for example on the
     Macintosh.  For debugging purposes you can force this mode with
     "-mode=single".

options
     Array ref of Command line options that have been passed to the server
     object via the new method.

parent
     When creating an object with Clone the original object becomes the
     parent of the new object. Objects created with new usually don't have
     a parent, thus this attribute is not set.

pidfile (*-pidfile=file*)
     (UNIX only) If this option is present, a PID file will be created at
     the given location.

proto (*-proto=proto*)
     The transport layer to use, by default *tcp* or *unix* for a Unix
     socket. It is not yet possible to combine both.

socket
     The socket that is connected to the client; passed as $client argument
     to the Clone method. If the server object was created with new, this
     attribute can be undef, as long as the Bind method isn't called.
     Sockets are assumed to be IO::Socket objects.

user (*-user=uid*)
     After doing a bind(), change the real and effective UID to the given.
     This is usefull, if you want your server to bind to a privileged port
     (<1024), but don't want the server to execute as root. See also the
     -group and the -chroot options.

     UID's can be passed as group names or numeric values.

version (*-version*)
     Supresses startup of the server; instead the version string will be
     printed and the program exits immediately.

   Note that most of these attributes (facility, mode, localaddr,
localport, pidfile, version) are meaningfull only at startup. If you set
them later, they will be simply ignored. As almost all attributes have
appropriate defaults, you will typically use the localport attribute only.

Command Line Parsing
--------------------

     my $optionsAvailable = Net::Daemon->Options();

     print Net::Daemon->Version(), "\n";

     Net::Daemon->Usage();

   The Options method returns a hash ref of possible command line options.
The keys are option names, the values are again hash refs with the
following keys:

template
     An option template that can be passed to *Getopt::Long::GetOptions*.

description
     A description of this option, as used in Usage

   The Usage method prints a list of all possible options and returns.  It
uses the Version method for printing program name and version.

Config File
-----------

   If the config file option is set in the command line options or in the
in the "new" args, then the method

     $server->ReadConfigFile($file, $options, $args)

   is invoked. By default the config file is expected to contain Perl
source that returns a hash ref of options. These options override the "new"
args and will in turn be overwritten by the command line options, as
present in the $options hash ref.

   A typical config file might look as follows, we use the DBI::ProxyServer
as an example:

     # Load external modules; this is not required unless you use
     # the chroot() option.
     #require DBD::mysql;
     #require DBD::CSV;

     {
     	# 'chroot' => '/var/dbiproxy',
     	'facility' => 'daemon',
     	'pidfile' => '/var/dbiproxy/dbiproxy.pid',
     	'user' => 'nobody',
     	'group' => 'nobody',
     	'localport' => '1003',
     	'mode' => 'fork'

     # Access control
             'clients' => [
         # Accept the local
         {
     	'mask' => '^192\.168\.1\.\d+$',
                     'accept' => 1
                 },
         # Accept myhost.company.com
         {
     	'mask' => '^myhost\.company\.com$',
                     'accept' => 1
                 }
         # Deny everything else
         {
     	'mask' => '.*',
     	'accept' => 0
         }
             ]
         }

Access control
--------------

   The Net::Daemon package supports a host based access control scheme. By
default access is open for anyone. However, if you create an attribute
$self->{'clients'}, typically in the config file, then access control is
disabled by default. For any connection the client list is processed: The
clients attribute is an array ref to a list of hash refs. Any of the hash
refs may contain arbitrary attributes, including the following:

mask
     A Perl regular expression that has to match the clients IP number or
     its host name. The list is processed from the left to the right,
     whenever a 'mask' attribute matches, then the related hash ref is
     choosen as client and processing the client list stops.

accept
     This may be set to true or false (default when omitting the
     attribute), the former means accepting the client.

Event logging
-------------

     $server->Log($level, $format, @args);
     $server->Debug($format, @args);
     $server->Error($format, @args);
     $server->Fatal($format, @args);

   The Log method is an interface to `Sys::Syslog (3)' in this node or
`Win32::EventLog (3)' in this node. It's arguments are *$level*, a syslog
level like debug, notice or err, a format string in the style of printf
and the format strings arguments.

   The Debug and Error methods are shorthands for calling Log with a level
of debug and err, respectively. The Fatal method is like Error, except it
additionally throws the given message as exception.

   See `Net::Daemon::Log(3)' in this node for details.

Flow of control
---------------

     $server->Bind();
     # The following inside Bind():
     if ($connection->Accept()) {
         $connection->Run();
     } else {
         $connection->Log('err', 'Connection refused');
     }

   The Bind method is called by the application when the server should
start. Typically this can be done right after creating the server object
$server. Bind usually never returns, except in case of errors.

   When a client connects, the server uses Clone to derive a connection
object *$connection* from the server object. A new thread or process is
created that uses the connection object to call your classes Accept
method. This method is intended for host authorization and should return
either FALSE (refuse the client) or TRUE (accept the client).

   If the client is accepted, the Run method is called which does the true
work. The connection is closed when Run returns and the corresponding
thread or process exits.

Error Handling
--------------

   All methods are supposed to throw Perl exceptions in case of errors.

MULTITHREADING CONSIDERATIONS
=============================

   All methods are working with lexically scoped data and handle data
only, the exception being the OpenLog method which is invoked before
threading starts. Thus you are safe as long as you don't share handles
between threads. I strongly recommend that your application behaves
similar.

EXAMPLE
=======

   As an example we'll write a simple calculator server. After connecting
to this server you may type expressions, one per line. The server
evaluates the expressions and prints the result. (Note this is an example,
in real life we'd never implement such a security hole. :-)

   For the purpose of example we add a command line option *-base* that
takes 'hex', 'oct' or 'dec' as values: The servers output will use the
given base.

     # -*- perl -*-
     #
     # Calculator server
     #
     require 5.004;
     use strict;

     require Net::Daemon;

     package Calculator;

     use vars qw($VERSION @ISA);
     $VERSION = '0.01';
     @ISA = qw(Net::Daemon); # to inherit from Net::Daemon

     sub Version ($) { 'Calculator Example Server, 0.01'; }

     # Add a command line option "--base"
     sub Options ($) {
         my($self) = @_;
         my($options) = $self->SUPER::Options();
         $options->{'base'} = { 'template' => 'base=s',
     			     'description' => '--base                  '
     				    . 'dec (default), hex or oct'
     			      };
         $options;
     }

     # Treat command line option in the constructor
     sub new ($$;$) {
         my($class, $attr, $args) = @_;
         my($self) = $class->SUPER::new($attr, $args);
         if ($self->{'parent'}) {
     	  # Called via Clone()
     	  $self->{'base'} = $self->{'parent'}->{'base'};
         } else {
     	  # Initial call
     	  if ($self->{'options'}  &&  $self->{'options'}->{'base'}) {
     	      $self->{'base'} = $self->{'options'}->{'base'}
             }
         }
         if (!$self->{'base'}) {
     	  $self->{'base'} = 'dec';
         }
         $self;
     }

     sub Run ($) {
         my($self) = @_;
         my($line, $sock);
         $sock = $self->{'socket'};
         while (1) {
     	  if (!defined($line = $sock->getline())) {
     	      if ($sock->error()) {
     		  $self->Error("Client connection error %s",
     			       $sock->error());
     	      }
     	      $sock->close();
     	      return;
     	  }
     	  $line =~ s/\s+$//; # Remove CRLF
     	  my($result) = eval $line;
     	  my($rc);
     	  if ($self->{'base'} eq 'hex') {
     	      $rc = printf $sock ("%x\n", $result);
     	  } elsif ($self->{'base'} eq 'oct') {
     	      $rc = printf $sock ("%o\n", $result);
     	  } else {
     	      $rc = printf $sock ("%d\n", $result);
     	  }
     	  if (!$rc) {
     	      $self->Error("Client connection error %s",
     			   $sock->error());
     	      $sock->close();
     	      return;
     	  }
         }
     }

     package main;

     my $server = Calculator->new({'pidfile' => 'none',
     				'localport' => 2000}, \@ARGV);
     $server->Bind();

KNOWN PROBLEMS
==============

   Most, or even any, known problems are related to the Sys::Syslog module
which is by default used for logging events under Unix. I'll quote some
examples:

Usage: Sys::Syslog::_PATH_LOG at ...
     This problem is treated in perl bug 20000712.003. A workaround is
     changing line 277 of Syslog.pm to

          my $syslog = &_PATH_LOG() || croak "_PATH_LOG not found in syslog.ph";

AUTHOR AND COPYRIGHT
====================

     Net::Daemon is Copyright (C) 1998, Jochen Wiedmann
                                        Am Eisteich 9
                                        72555 Metzingen
                                        Germany

     Phone: +49 7123 14887
     Email: joe@ispsoft.de

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `RPC::pServer(3)' in this node, `Netserver::Generic(3)' in this node,
`Net::Daemon::Log(3)' in this node, `Net::Daemon::Test(3)' in this node

Utility functions for logging
*****************************

NAME
====

   Net::Daemon::Log - Utility functions for logging

SYNOPSIS
========

     # Choose logging method: syslog or Win32::EventLog
     $self->{'facility'} = 'mail'; # Default: Daemon
     $self->{'logfile'} = undef;   # Default

     # Choose logging method: stderr
     $self->{'logfile'} = 1;

     # Choose logging method: IO handle
     my $file = IO::File->new("my.log", "a");
     $self->{'logfile'} = $file;

     # Debugging messages (equivalent):
     $self->Log('debug', "This is a debugging message");
     $self->Debug("This is a debugging message");

     # Error messages (equivalent):
     $self->Log('err', "This is an error message");
     $self->Error("This is an error message");

     # Fatal error messages (implies 'die')
     $self->Fatal("This is a fatal error message");

WARNING
=======

   THIS IS ALPHA SOFTWARE. It is *only* 'Alpha' because the interface (API)
is not finalised. The Alpha status does not reflect code quality or
stability.

DESCRIPTION
===========

   Net::Daemon::Log is a utility class for portable logging messages.  By
default it uses syslog (Unix) or Win32::EventLog (Windows), but logging
messages can also be redirected to stderr or a log file.

Generic Logging
---------------

     $self->Log($level, $msg, @args);

   This is the generic interface. The logging level is in syslog style,
thus one of the words 'debug', 'info', 'notice', 'err' or 'crit'.  You'll
rarely need info and notice and I can hardly imagine a reason for crit
(critical). In 95% of all cases debug and err will be sufficient.

   The logging string $msg is a format string similar to printf.

Utility methods
---------------

     $self->Debug($msg, @args);
     $self->Error($msg, @args);
     $self->Fatal($msg, @args);

   These are replacements for logging with levels debug and err. The
difference between the latter two is that Fatal includes throwing a Perl
exception.

Chossing a logging target
-------------------------

   By default logging will happen to syslog (Unix) or EventLog (Windows).
However you may choose logging to stderr by setting

     $self->{'logfile'} = 1;

   This is required if neither of syslog and EventLog is available. An
alternative option is setting

     $self->{'logfile'} = $handle;

   where $handle is any object supporting a print method, for example an
IO::Handle object. Usually the logging target is choosen as soon as you
call $self->Log() the first time. However, you may force choosing the
target by doing a

     $self->OpenLog();

   before calling Log the first time.

MULTITHREADING
==============

   The Multithreading capabitities of this class are depending heavily on
the underlying classes Sys::Syslog, Win32::EventLog or IO::Handle.  If
they are thread safe, you can well assume that this package is too. (The
exception being that you should better call $self->OpenLog() before
threading.)

AUTHOR AND COPYRIGHT
====================

     Net::Daemon is Copyright (C) 1998, Jochen Wiedmann
                                        Am Eisteich 9
                                        72555 Metzingen
                                        Germany

     Phone: +49 7123 14887
     Email: joe@ispsoft.de

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::Daemon(3)' in this node, `Sys::Syslog(3)' in this node,
`Win32::EventLog(3)' in this node, `IO::Handle(3)' in this node

perl extensions for portable ssl daemons
****************************************

NAME
====

   Net::Daemon::SSL - perl extensions for portable ssl daemons

SYNOPSIS
========

     use Net::Daemon::SSL;
     package MyDaemon;
     @MyDaemon::ISA = qw (Net::Daemon::SSL);
     sub Run
     {
         my $this = shift;
         my $buffer;
         $this->{socket}->print ( "vasja was here\n" );
         $this->{socket}->sysread ( $buffer, 100 ); # Attention! getline() method
                                                    # do not work with IO::Socket::SSL
                                                    # version 0.73
                                                    # see perldoc IO::Socket::SSL
                                                    # for more details
     }
     package main;
     my $daemon = new MyDaemon ( {}, \ @ARGV ); # you can use --help command line key
     $daemon || die "error create daemon instance: $!\n";
     $daemon->Bind();

DESCRIPTION
===========

   This class implements an IO::Socket::SSL functionality for Net::Daemon
class. See perldoc Net::Daemon for more information about Net::Daemon
usage.

Options
-------

   This method add IO::Socket::SSL specific options ( SSL_use_cert,
SSL_verify_mode, SSL_key_file, SSL_cert_file, SSL_ca_path, SSL_ca_file ) to
generic Net::Daemon options. See perldoc IO::Socket::SSL for description of
this options

Bind
----

   This method creates an IO::Socket::SSL::SafeAccept socket, stores this
socket into $this->{socket} and passes control to parent
Net::Daemon::Bind. The IO::Socket::SSL::SafeAccept is a class inherited
from IO::Socket::SSL with the only difference from parent class - the
accept() method of this class returns EINTR on *any* error. This trick is
needed to "hack" Net::Daemon::Bind functionality: if this method gets an
error from accept() ( Net::Daemon::SSL auth error, for example ) it will
call Fatal() method and die unless this is a EINTR error.

AUTHOR AND COPYRIGHT
====================

     Net::Daemon::SSL (C) Michael Kulakov, Zenon N.S.P. 2000
                          125124, 19, 1-st Jamskogo polja st,
                          Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::Daemon(3)' in this node, `IO::Socket::SSL(3)' in this node

support functions for testing Net::Daemon servers
*************************************************

NAME
====

   Net::Daemon::Test - support functions for testing Net::Daemon servers

SYNOPSIS
========

     # This is the server, stored in the file "servertask".
     #
     # Create a subclass of Net::Daemon::Test, which in turn is
     # a subclass of Net::Daemon
     use Net::Daemon::Test ();
     package MyDaemon;
     @MyDaemon::ISA = qw(Net::Daemon::Test);

     sub Run {
     	# Overwrite this and other methods, as you like.
     }

     my $self = Net::Daemon->new(\%attr, \@options);
     eval { $self->Bind() };
     if ($@) {
     	die "Server cannot bind: $!";
     }
     eval { $self->Run() };
     if ($@) {
     	die "Unexpected server termination: $@";
     }

     # This is the client, the real test script, note we call the
     # "servertask" file below:
     #
     # Call the Child method to spawn a child. Don't forget to use
     # the timeout option.
     use Net::Daemon::Test ();

     my($handle, $port) = eval {
         Net::Daemon::Test->Child(5, # Number of subtests
     				 'servertask', '--timeout', '20')
     };
     if ($@) {
     	print "not ok 1 $@\n";
     	exit 0;
     }
     print "ok 1\n";

     # Real tests following here
     ...

     # Terminate the server
     $handle->Terminate();

DESCRIPTION
===========

   This module is a frame for creating test scripts of Net::Daemon based
server packages, preferrably using Test::Harness, but that's your choice.

   A test consists of two parts: The client part and the server part.  The
test is executed by the child part which invokes the server part, by
spawning a child process and invoking an external Perl script.  (Of course
we woultn't need this external file with fork(), but that's the best
possibility to make the test scripts portable to Windows without requiring
threads in the test script.)

   The server part is a usual Net::Daemon application, for example a script
like dbiproxy. The only difference is that it derives from
Net::Daemon::Test and not from Net::Daemon, the main difference is that
the Bind method attempts to allocate a port automatically. Once a port is
allocated, the number is stored in the file "ndtest.prt".

   After spawning the server process, the child will wait ten seconds
(hopefully sufficient) for the creation of ndtest.prt.

AVAILABLE METHODS
=================

Server part
-----------

Options
     Adds an option *-timeout* to Net::Daemon: The server's Run method
     will die after at most 20 seconds.

Bind
     (Instance method) This is mainly the default Bind method, but it
     attempts to find and allocate a free port in two ways: First of all,
     it tries to call Bind with port 0, most systems will automatically
     choose a port in that case. If that seems to fail, ports 30000-30049
     are tried. We hope, one of these will succeed. :-)

Run
     (Instance method) Overwrites the Net::Daemon's method by adding a
     timeout.

   sub Run ($) {     my $self = shift;     $self->Run(); }

Client part
-----------

Child
     (Class method) Attempts to spawn a server process. The server process
     is expected to create the file 'ndtest.prt' with the port number.

     The method returns a process handle and a port number. The process
     handle offers a method *Terminate* that may later be used to stop the
     server process.

AUTHOR AND COPYRIGHT
====================

     Net::Daemon is Copyright (C) 1998, Jochen Wiedmann
                                        Am Eisteich 9
                                        72555 Metzingen
                                        Germany

     Phone: +49 7123 14887
     Email: joe@ispsoft.de

     All rights reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SEE ALSO
========

   `Net::Daemon(3)' in this node, `Test::Harness(3)' in this node

client API for accessing dictionary servers (RFC 2229)
******************************************************

NAME
====

   Net::Dict - client API for accessing dictionary servers (RFC 2229)

SYNOPSIS
========

     use Net::Dict;

     $dict = Net::Dict->new("some.host.name");
     $h = $dict->define("word");
     foreach $i (@{$h}) {
         ($db, $def) = @{$i};
     	. . .
     }

DESCRIPTION
===========

   `Net::Dict' is a class implementing a simple Dict client in Perl as
described in RFC2229.  It provides wrappers for a subset of the RFC2229
commands.

OVERVIEW
========

   Quotation from RFC2229:

     The Dictionary Server Protocol (DICT) is a TCP transaction based
     query/response protocol that allows a client to access dictionary
     definitions from a set of natural language dictionary databases.

CONSTRUCTOR
===========

     $dict = Net::Dict->new (HOST [,OPTIONS]);

   This is the constructor for a new Net::Dict object. `HOST' is the name
of the remote host on which a Dict server is running.

   If the `HOST' value is an empty string, the default behavior is to try
dict.org, alt0.dict.org, alt1.dict.org, and alt2.dict.org, in that order.

   OPTIONS are passed in a hash like fashion, using key and value pairs.
Possible options are:

ConfigFile
     The path to the configuration file (see dict(1) for details on the
     format of the config. file). The config file entries override the
     default definitions (e.g. server name and port), but are overriden by
     an explicit definitions in the constructor.

HTML
     Give an output of 'match' and 'define' in HTML.

Port
     The port number to connect to on the remote machine for the Dict
     connection (a default port number is 2628, according to RFC2229).

Client
     The string to send as the CLIENT identifier.  If not set, then a
     default identifier for Net::Dict is sent.

Timeout
     Set a timeout value (defaults to 120)

Debug
     debug level (see the debug method in Net/Cmd)

METHODS
=======

   Unless otherwise stated all methods return either a *true* or false
value, with *true* meaning that the operation was a success. When a method
states that it returns a value, failure will be returned as undef or an
empty list.

serverInfo()
     returns a string, containing the information about the server.

dbs()
     returns a hash, containing an ID of the dictionary as a key and
     description as the value.

dbInfo($dbname)
     returns a string, containing description of the dictionary $dbname.

setDicts(@dicts)
     sets the set of dictionaries, that will be searched during the
     successive define() calls. Defaults to '*'. No existance checks are
     performed by this interface, so you'd better make sure the
     dictionaries you specify are on the server (e.g. by calling dbs()).

strats()
     returns an array, containing an ID of a matching strategy as a key
     and a verbose description as a value.

define($word [, @dbs])
     returns a reference to an array, whose members are lists, consisting
     of two elements: the dictionary name and the definition.  If no
     dictionaries are specified, those set by setDicts() are used.

match($word, $strategy [, @dbs])
     same as define(), but a matching using the specified strategies is
     performed. Return array of lists, consisting of dictionary - match
     pairs.

dbTitle($dbname)
     Returns the title string for the specified dictionary.  This is the
     same string returned by the dbs() method for all databases.

UNIMPLEMENTED
=============

   The following RFC2229 commands have not been implemented:

authentication
     The authentication protocol isn't currently implemented.

REPORTING BUGS
==============

   When reporting bugs/problems please include as much information as
possible.  It may be difficult for me to reproduce the problem as almost
every setup is different.

   A small script which yields the problem will probably be of help. It
would also be useful if this script was run with the extra options `Debug
=> 1' passed to the constructor, and the output sent with the bug report.
If you cannot include a small script then please include a Debug trace
from a run of your program which does yield the problem.

EXAMPLES
========

   The examples directory of the Net-Dict distribution includes simple.pl,
which illustrates basic use of the module.

AUTHOR
======

   Net::Dict was written by Dmitry Rubinstein
<dimrub@wisdom.weizmann.ac.il>, using Net::FTP and Net::SMTP as a pattern
and a model for imitation.

   The module is now maintained by Neil Bowers <neilb@cre.canon.co.uk>

SEE ALSO
========

   See Net/Netrc, Net/Cmd,

   dict(1), dictd(8), RFC 2229
http://www.cis.ohio-state.edu/htbin/rfc/rfc2229.html http://www.dict.org/

COPYRIGHT
=========

   Copyright (C) 2001 Canon Research Centre Europe, Ltd.

   Copyright (c) 1998 Dmitry Rubinstein. All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Attempt to evaluate the current host's internet name and domain
***************************************************************

NAME
====

   Net::Domain - Attempt to evaluate the current host's internet name and
domain

SYNOPSIS
========

     use Net::Domain qw(hostname hostfqdn hostdomain);

DESCRIPTION
===========

   Using various methods *attempt* to find the Fully Qualified Domain Name
(FQDN) of the current host. From this determine the host-name and the
host-domain.

   Each of the functions will return undef if the FQDN cannot be
determined.

hostfqdn ()
     Identify and return the FQDN of the current host.

hostname ()
     Returns the smallest part of the FQDN which can be used to identify
     the host.

hostdomain ()
     Returns the remainder of the FQDN after the hostname has been removed.

AUTHOR
======

   Graham Barr <gbarr@pobox.com>.  Adapted from Sys::Hostname by David
Sundstrom <sunds@asictest.sc.ti.com>

COPYRIGHT
=========

   Copyright (c) 1995-1998 Graham Barr. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

A dummy Inetd server
********************

NAME
====

   Net::DummyInetd - A dummy Inetd server

SYNOPSIS
========

     use Net::DummyInetd;
     use Net::SMTP;

     $inetd = new Net::DummyInetd qw(/usr/lib/sendmail -ba -bs);

     $smtp  = Net::SMTP->new('localhost', Port => $inetd->port);

DESCRIPTION
===========

   `Net::DummyInetd' is just what it's name says, it is a dummy inetd
server.  Creation of a `Net::DummyInetd' will cause a child process to be
spawned off which will listen to a socket. When a connection arrives on
this socket the specified command is fork'd and exec'd with STDIN and
STDOUT file descriptors duplicated to the new socket.

   This package was added as an example of how to use `Net::SMTP' to
connect to a sendmail process, which is not the default, via SIDIN and
STDOUT.  A `Net::Inetd' package will be available in the next release of
`libnet'

CONSTRUCTOR
===========

new ( CMD )
     Creates a new object and spawns a child process which listens to a
     socket.  `CMD' is a list, which will be passed to exec when a new
     process needs to be created.

METHODS
=======

port
     Returns the port number on which the *DummyInetd* object is listening

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

COPYRIGHT
=========

   Copyright (c) 1995-1997 Graham Barr. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

FTP Client class
****************

NAME
====

   Net::FTP - FTP Client class

SYNOPSIS
========

     use Net::FTP;

     $ftp = Net::FTP->new("some.host.name", Debug => 0);
     $ftp->login("anonymous",'me@here.there');
     $ftp->cwd("/pub");
     $ftp->get("that.file");
     $ftp->quit;

DESCRIPTION
===========

   `Net::FTP' is a class implementing a simple FTP client in Perl as
described in RFC959.  It provides wrappers for a subset of the RFC959
commands.

OVERVIEW
========

   FTP stands for File Transfer Protocol.  It is a way of transferring
files between networked machines.  The protocol defines a client (whose
commands are provided by this module) and a server (not implemented in
this module).  Communication is always initiated by the client, and the
server responds with a message and a status code (and sometimes with data).

   The FTP protocol allows files to be sent to or fetched from the server.
Each transfer involves a *local file* (on the client) and a *remote file*
(on the server).  In this module, the same file name will be used for both
local and remote if only one is specified.  This means that transferring
remote file `/path/to/file' will try to put that file in `/path/to/file'
locally, unless you specify a local file name.

   The protocol also defines several standard *translations* which the
file can undergo during transfer.  These are ASCII, EBCDIC, binary, and
byte.  ASCII is the default type, and indicates that the sender of files
will translate the ends of lines to a standard representation which the
receiver will then translate back into their local representation.  EBCDIC
indicates the file being transferred is in EBCDIC format.  Binary (also
known as image) format sends the data as a contiguous bit stream.  Byte
format transfers the data as bytes, the values of which remain the same
regardless of differences in byte size between the two machines (in theory
- in practice you should only use this if you really know what you're
doing).

CONSTRUCTOR
===========

new (HOST [,OPTIONS])
     This is the constructor for a new Net::FTP object. `HOST' is the name
     of the remote host to which a FTP connection is required.

     OPTIONS are passed in a hash like fashion, using key and value pairs.
     Possible options are:

     *Firewall* - The name of a machine which acts as a FTP firewall. This
     can be overridden by an environment variable `FTP_FIREWALL'. If
     specified, and the given host cannot be directly connected to, then
     the connection is made to the firewall machine and the string
     `@hostname' is appended to the login identifier. This kind of setup
     is also refered to as a ftp proxy.

     *BlockSize* - This is the block size that Net::FTP will use when doing
     transfers. (defaults to 10240)

     Port - The port number to connect to on the remote machine for the
     FTP connection

     Timeout - Set a timeout value (defaults to 120)

     Debug - debug level (see the debug method in Net/Cmd)

     Passive - If set to a non-zero value then all data transfers will be
     done using passive mode. This is not usually required except for some
     dumb servers, and some firewall configurations. This can also be set
     by the environment variable `FTP_PASSIVE'.

     Hash - If TRUE, print hash marks (#) on STDERR every 1024 bytes.  This
     simply invokes the `hash()' method for you, so that hash marks are
     displayed for all transfers.  You can, of course, call `hash()'
     explicitly whenever you'd like.

     If the constructor fails undef will be returned and an error message
     will be in $@

METHODS
=======

   Unless otherwise stated all methods return either a *true* or false
value, with *true* meaning that the operation was a success. When a method
states that it returns a value, failure will be returned as undef or an
empty list.

login ([LOGIN [,PASSWORD [, ACCOUNT] ] ])
     Log into the remote FTP server with the given login information. If
     no arguments are given then the `Net::FTP' uses the `Net::Netrc'
     package to lookup the login information for the connected host.  If
     no information is found then a login of anonymous is used.  If no
     password is given and the login is anonymous then the users Email
     address will be used for a password.

     If the connection is via a firewall then the authorize method will be
     called with no arguments.

authorize ( [AUTH [, RESP]])
     This is a protocol used by some firewall ftp proxies. It is used to
     authorise the user to send data out.  If both arguments are not
     specified then authorize uses `Net::Netrc' to do a lookup.

site (ARGS)
     Send a SITE command to the remote server and wait for a response.

     Returns most significant digit of the response code.

type (TYPE [, ARGS])
     This method will send the TYPE command to the remote FTP server to
     change the type of data transfer. The return value is the previous
     value.

ascii ([ARGS]) binary([ARGS]) ebcdic([ARGS]) byte([ARGS])
     Synonyms for type with the first arguments set correctly

     NOTE ebcdic and byte are not fully supported.

rename ( OLDNAME, NEWNAME )
     Rename a file on the remote FTP server from `OLDNAME' to `NEWNAME'.
     This is done by sending the RNFR and RNTO commands.

delete ( FILENAME )
     Send a request to the server to delete FILENAME.

cwd ( [ DIR ] )
     Attempt to change directory to the directory given in $dir.  If $dir
     is `".."', the FTP `CDUP' command is used to attempt to move up one
     directory. If no directory is given then an attempt is made to change
     the directory to the root directory.

cdup ()
     Change directory to the parent of the current directory.

pwd ()
     Returns the full pathname of the current directory.

rmdir ( DIR )
     Remove the directory with the name DIR.

mkdir ( DIR [, RECURSE ])
     Create a new directory with the name DIR. If `RECURSE' is *true* then
     mkdir will attempt to create all the directories in the given path.

     Returns the full pathname to the new directory.

ls ( [ DIR ] )
     Get a directory listing of DIR, or the current directory.

     In an array context, returns a list of lines returned from the
     server. In a scalar context, returns a reference to a list.

dir ( [ DIR ] )
     Get a directory listing of DIR, or the current directory in long
     format.

     In an array context, returns a list of lines returned from the
     server. In a scalar context, returns a reference to a list.

get ( REMOTE_FILE [, LOCAL_FILE [, WHERE]] )
     Get `REMOTE_FILE' from the server and store locally. `LOCAL_FILE' may
     be a filename or a filehandle. If not specified the the file will be
     stored in the current directory with the same leafname as the remote
     file.

     If WHERE is given then the first WHERE bytes of the file will not be
     transfered, and the remaining bytes will be appended to the local
     file if it already exists.

     Returns `LOCAL_FILE', or the generated local file name if `LOCAL_FILE'
     is not given.

put ( LOCAL_FILE [, REMOTE_FILE ] )
     Put a file on the remote server. `LOCAL_FILE' may be a name or a
     filehandle.  If `LOCAL_FILE' is a filehandle then `REMOTE_FILE' must
     be specified. If `REMOTE_FILE' is not specified then the file will be
     stored in the current directory with the same leafname as
     `LOCAL_FILE'.

     Returns `REMOTE_FILE', or the generated remote filename if
     `REMOTE_FILE' is not given.

     NOTE: If for some reason the transfer does not complete and an error
     is returned then the contents that had been transfered will not be
     remove automatically.

put_unique ( LOCAL_FILE [, REMOTE_FILE ] )
     Same as put but uses the `STOU' command.

     Returns the name of the file on the server.

append ( LOCAL_FILE [, REMOTE_FILE ] )
     Same as put but appends to the file on the remote server.

     Returns `REMOTE_FILE', or the generated remote filename if
     `REMOTE_FILE' is not given.

unique_name ()
     Returns the name of the last file stored on the server using the
     `STOU' command.

mdtm ( FILE )
     Returns the *modification time* of the given file

size ( FILE )
     Returns the size in bytes for the given file as stored on the remote
     server.

     NOTE: The size reported is the size of the stored file on the remote
     server.  If the file is subsequently transfered from the server in
     ASCII mode and the remote server and local machine have different
     ideas about "End Of Line" then the size of file on the local machine
     after transfer may be different.

supported ( CMD )
     Returns TRUE if the remote server supports the given command.

hash ( [FILEHANDLE_GLOB_REF],[ BYTES_PER_HASH_MARK] )
     Called without parameters, or with the first argument false, hash
     marks are suppressed.  If the first argument is true but not a
     reference to a file handle glob, then \*STDERR is used.  The second
     argument is the number of bytes per hash mark printed, and defaults
     to 1024.  In all cases the return value is a reference to an array of
     two:  the filehandle glob reference and the bytes per hash mark.

   The following methods can return different results depending on how
they are called. If the user explicitly calls either of the pasv or port
methods then these methods will return a *true* or false value. If the
user does not call either of these methods then the result will be a
reference to a `Net::FTP::dataconn' based object.

nlst ( [ DIR ] )
     Send a `NLST' command to the server, with an optional parameter.

list ( [ DIR ] )
     Same as nlst but using the LIST command

retr ( FILE )
     Begin the retrieval of a file called FILE from the remote server.

stor ( FILE )
     Tell the server that you wish to store a file. FILE is the name of
     the new file that should be created.

stou ( FILE )
     Same as stor but using the `STOU' command. The name of the unique
     file which was created on the server will be available via the
     unique_name method after the data connection has been closed.

appe ( FILE )
     Tell the server that we want to append some data to the end of a file
     called FILE. If this file does not exist then create it.

   If for some reason you want to have complete control over the data
connection, this includes generating it and calling the response method
when required, then the user can use these methods to do so.

   However calling these methods only affects the use of the methods above
that can return a data connection. They have no effect on methods get, put,
put_unique and those that do not require data connections.

port ( [ PORT ] )
     Send a `PORT' command to the server. If `PORT' is specified then it
     is sent to the server. If not the a listen socket is created and the
     correct information sent to the server.

pasv ()
     Tell the server to go into passive mode. Returns the text that
     represents the port on which the server is listening, this text is in
     a suitable form to sent to another ftp server using the port method.

   The following methods can be used to transfer files between two remote
servers, providing that these two servers can connect directly to each
other.

pasv_xfer ( SRC_FILE, DEST_SERVER [, DEST_FILE ] )
     This method will do a file transfer between two remote ftp servers. If
     `DEST_FILE' is omitted then the leaf name of `SRC_FILE' will be used.

pasv_xfer_unique ( SRC_FILE, DEST_SERVER [, DEST_FILE ] )
     Like pasv_xfer but the file is stored on the remote server using the
     STOU command.

pasv_wait ( NON_PASV_SERVER )
     This method can be used to wait for a transfer to complete between a
     passive server and a non-passive server. The method should be called
     on the passive server with the `Net::FTP' object for the non-passive
     server passed as an argument.

abort ()
     Abort the current data transfer.

quit ()
     Send the QUIT command to the remote FTP server and close the socket
     connection.

Methods for the adventurous
---------------------------

   `Net::FTP' inherits from `Net::Cmd' so methods defined in `Net::Cmd' may
be used to send commands to the remote FTP server.

quot (CMD [,ARGS])
     Send a command, that Net::FTP does not directly support, to the remote
     server and wait for a response.

     Returns most significant digit of the response code.

     WARNING This call should only be used on commands that do not require
     data connections. Misuse of this method can hang the connection.

THE dataconn CLASS
==================

   Some of the methods defined in `Net::FTP' return an object which will
be derived from this class.The dataconn class itself is derived from the
IO::Socket::INET class, so any normal IO operations can be performed.
However the following methods are defined in the dataconn class and IO
should be performed using these.

read ( BUFFER, SIZE [, TIMEOUT ] )
     Read `SIZE' bytes of data from the server and place it into `BUFFER',
     also performing any <CRLF> translation necessary. TIMEOUT is
     optional, if not given the the timeout value from the command
     connection will be used.

     Returns the number of bytes read before any <CRLF> translation.

write ( BUFFER, SIZE [, TIMEOUT ] )
     Write `SIZE' bytes of data from `BUFFER' to the server, also
     performing any <CRLF> translation necessary. TIMEOUT is optional, if
     not given the the timeout value from the command connection will be
     used.

     Returns the number of bytes written before any <CRLF> translation.

abort ()
     Abort the current data transfer.

close ()
     Close the data connection and get a response from the FTP server.
     Returns *true* if the connection was closed successfully and the
     first digit of the response from the server was a '2'.

UNIMPLEMENTED
=============

   The following RFC959 commands have not been implemented:

ALLO
     Allocates storage for the file to be transferred.

SMNT
     Mount a different file system structure without changing login or
     accounting information.

HELP
     Ask the server for "helpful information" (that's what the RFC says) on
     the commands it accepts.

MODE
     Specifies transfer mode (stream, block or compressed) for file to be
     transferred.

SYST
     Request remote server system identification.

STAT
     Request remote server status.

STRU
     Specifies file structure for file to be transferred.

REIN
     Reinitialize the connection, flushing all I/O and account information.

REPORTING BUGS
==============

   When reporting bugs/problems please include as much information as
possible.  It may be difficult for me to reproduce the problem as almost
every setup is different.

   A small script which yields the problem will probably be of help. It
would also be useful if this script was run with the extra options `Debug
=' 1> passed to the constructor, and the output sent with the bug report.
If you cannot include a small script then please include a Debug trace
from a run of your program which does yield the problem.

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

SEE ALSO
========

   See Net/Netrc, Net/Cmd,

   ftp(1), ftpd(8), RFC 959
http://www.cis.ohio-state.edu/htbin/rfc/rfc959.html

CREDITS
=======

   Henry Gabryjelski <henryg@WPI.EDU> - for the suggestion of creating
directories recursively.

   Nathan Torkington <gnat@frii.com> - for some input on the documentation.

   Roderick Schertler <roderick@gate.net> - for various inputs

COPYRIGHT
=========

   Copyright (c) 1995-1998 Graham Barr. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Perl extension for simplifying common usages of Net::FTP.
*********************************************************

NAME
====

   Net::FTP::Common - Perl extension for simplifying common usages of
Net::FTP.

SYNOPSIS
========

     use Net::FTP::Common;
     %net_ftp_config = ( Debug   => 1, Timeout => 120 );

     %common_cfg     =
       (
         User => 'username',          # overwrite anonymous user default
         Pass => 'password',          # overwrite list@rebol.com pass default
         Dir  => 'pub',               # overwrite slash default
         Type => 'A'                  # overwrite I (binary) default
        );

     $ez = Net::FTP::Common->new(\%net_ftp_config, \%common_cfg);

     $host = 'ftp.rebol.com';

     # Get a listing of a remote directory:
     @listing =	$ez->dir($host);

     # Make a directory on the remote machine
     $ez->mkdir($host, Dir => '/pub/newdir/1/2/3', Recurse => 1);

     # Get a file from the remote machine
     $ez->get($host, File => 'codex.txt', LocalFile => '/tmp/crypto.txt');

     # Send a file to the remote machine
     $ez->send($host, File => 'codex.txt');

     # test for a file's existence on the remote machine (using =~)
     @file = $ez->grep($host, File => '[A-M]*[.]txt');
     # a synonym for grep is glob (no difference, just another name)
     @file = $ez->glob($host, File => 'n.*-file.t?t');

     # test for a file on the remote machine (using eq)
     $ez->check($host, File => 'needed-file.txt');
     # note this is no more than you manually calling:
     # (scalar grep { $_ = 'needed-file.txt' } $ez->dir($host)) > 0;
     # or manually calling
     # (scalar $ez->grep($host, File => 'needed-file.txt')) > 0

     # can we login to the machine?
     $ez->login($host) || die "cant login: $@";

DESCRIPTION
===========

   This module is intended to make the common uses of Net::FTP a one-line
affair. Also, it made the development of Net::FTP::Shell straightfoward.

   Note well: though Net::FTP works in the stateful way that the FTP
protocol does, Net::FTP::Common works in a stateless "one-hit" fashion.
That is, for each separate call to the API, a connection is established,
the particular Net::FTP::Common functionality is performed and the
connection is dropped.  The disadvantage of this approach is the (usually
irrelevant and insignificant) over head of connection and disconnection.
The advantage is that there is much less chance of incurring failure due
to timeout.

TRAPS FOR THE UNWARY
--------------------

   *      @file = $ez->grep($host, File => '[A-M]*[.]txt');

          is correct

          @file = $ez->grep($host, '[A-M]*[.]txt');

     looks correct but is not because you did not name the argument as you
     are supposed to.

   * In the current dain-bramaged interface, you can catch the bozak when
     you accidentally forget to specify the $host argument to
     Net::FTP::Common's API functions.

     Since no one seems to be using this, I may in fact rework the API to
     allow the host to be a default instead of requiring it's
     specification.

EXPORT
------

   None by default.

AUTHOR
======

   T. M. Brannon <tbone@cpan.org>

SEE ALSO
========

   REBOL (www.rebol.com) is a language which supports 1-line internet
processing for the schemes of mailto:, http:, daytime:, and ftp:.

   A Perl implementation of REBOL is in the works at www.metaperl.com.

Perl extension for shell use of Net::FTP::Common
************************************************

NAME
====

   Net::FTP::Shell - Perl extension for shell use of Net::FTP::Common

SYNOPSIS
========

     # from the DOS/Unix shell...
     shell> please.pl get  gnu emacs.tgz        # ... will ftp a file to gnu acct
     shell> please.pl send gnu vi-sucks.truth   # ... will ftp a file to gnu acct
     shell> please.pl dir  gnu                  # ... will list directory of gnu acct
     shell> please.pl mkdir gnu /new/wares      # ... must use absolute path
     shell> please.pl check gnu 'emacs-30.tar.gz'
     shell> please.pl glob  gnu '.*.tar.gz'     # ... not a glob, but a regexp
     shell> please.pl describe gnu
     ----- account named "gnu" --------
     username:  wareboy
     password:  gnupass
     host:      ftp.gnu.org
     directory: /users/wareboy
     xfer_type: I (binary transfers... ascii is A)
     Debug    : 1
     Timeout  : 240

DESCRIPTION
===========

   This is a module which was designed when point-to-point FTP
communication between two people is not possible (ie, for firewall
reasons) but they need to exchange files and they have a common FTP
account somewhere.

PREREQUISITES
=============

   * Net::FTP::Common (CPAN id: TBONE)

   * User (CPAN id: TBONE)

   * Config::IniFiles

     note that IniFiles 1.6 has a small problem with the regular
     expression on line 399:

          elsif (($parm, $val) = /\s*([\S\s]+?)\s*=\s*(.*)/) {	# new parameter

     should be

          elsif (($parm, $val) = /\s*([\S\s]+?)\s*=\s*(\S*)/) {	# new parameter

     I have sent in a bug report. Until then, patch your Config::IniFiles
     to the above before sending any problem reports with this module.

INSTALLATION (Important)
========================

   Installing the module is easy:

     perl Makefile.PL
     make install

   Then, you can either type

     perl install.pl

   and have a default .ncfg placed in your home directory or you can do the
manual process described below:

Manual Process
--------------

   You must create a file named ".ncfg" and place in your home directory.
On Unix, you can find your home directory by typing

     echo $HOME

   On Windows, open a command shell and type

   set USERPROFILE

   The .ncfg file is written in Windows INI-file syntax. Here is a sample
one:

     [Default]
     User = heave
     Pass = ho
     Host = 229.117.122.180
     Dir  = /download

     [Instinet]
     Dir = /download/instinet

     [Rydex]
     Dir = /download/rydex

     [Socgen]
     Dir = /download/socgen

     [Linda]
     Dir = /download/linda

     [Terrence]
     Dir = /download/terrence

     Then you can simply use the please.pl Perl script to send things:

     perl please.pl send Linda love-letter.txt
     perl please.pl send Terrence resume.doc

AUTHOR
======

   T. M. Brannon, tbone@cpan.org

SEE ALSO
========

   www.metaperl.com, www.rebol.com, Net::FTP::Common, Net::FTP

A secure, extensible and configurable Perl FTP server
*****************************************************

NAME
====

   Net::FTPServer - A secure, extensible and configurable Perl FTP server

SYNOPSIS
========

     ftpd [--help] [-d] [-v] [-p port] [-s] [-S] [-V] [-C conf_file] [-P pidfile]

DESCRIPTION
===========

   `Net::FTPServer' is a secure, extensible and configurable FTP server
written in Perl.

   Current features include:

     * Authenticated FTP access.
     * Anonymous FTP access.
     * Complete implementation of current RFCs.
     * ASCII or binary type file transfers.
     * Active or passive mode file transfers.
     * Run standalone or from inetd(8).
     * Security features: chroot, resource limits, tainting,
       protection against buffer overflows.
     * IP-based and/or IP-less virtual hosts.
     * Complete access control system.
     * Anonymous read-only FTP personality.
     * Virtual filesystem allows files to be served
       from a database.
     * Directory aliases and CDPATH support.
     * Extensible command set.

INSTALLING AND RUNNING THE SERVER
=================================

   A standard `ftpd.conf' file is supplied with the server.  You should
study the comments in the file and edit it to your satisfaction, and then
copy it to `/etc/ftpd.conf'.

     cp ftpd.conf /etc/
     chown root.root /etc/ftpd.conf
     chmod 0755 /etc/ftpd.conf

   Two start-up scripts are supplied with the ftp server, to run it in two
common configurations: either as a full FTP server or as an anonymous-only
read-only FTP server. The scripts are `ftpd' and `ro-ftpd'. You may need to
edit these scripts if Perl is not stored in the standard place on your
system (the default path is `/usr/bin/perl').

   You should copy the appropriate script, either `ftpd' or `ro-ftpd' to a
suitable place (for example: `/usr/sbin/in.ftpd').

     cp ftpd /usr/sbin/in.ftpd
     chown root.root /usr/sbin/in.ftpd
     chmod 0755 /usr/sbin/in.ftpd

STANDALONE SERVER
-----------------

   If you have a high load site, you will want to run `Net::FTPServer' as
a standalone server. To start `Net::FTPServer' as a standalone server, do:

     /usr/sbin/in.ftpd -S

   You may want to add this to your local start-up files so that the
server starts automatically when you boot the machine.

   To stop the server, do:

     killall in.ftpd

RUNNING FROM INETD
------------------

   Add the following line to `/etc/inetd.conf':

     ftp stream tcp nowait root /usr/sbin/tcpd in.ftpd

   (This assumes that you have the `tcpd' package installed to provide
basic access control through `/etc/hosts.allow' and `/etc/hosts.deny'.
This access control is in addition to any access control which you may
configure through `/etc/ftpd.conf'.)

   After editing this file you will need to inform `inetd':

     killall -HUP inetd

COMMAND LINE FLAGS
==================

     --help       Display help and exit
     -d, -v       Enable debugging
     -p PORT      Listen on port PORT instead of the default port
     -s           Run in daemon mode (default: run from inetd)
     -S           Run in background and in daemon mode
     -V           Show version information and exit
     -C CONF      Use CONF as configuration file (default: /etc/ftpd.conf)
     -P PIDFILE   Save pid into PIDFILE (daemon mode only)
     --test       Test mode (used only in automatic testing scripts)

CONFIGURING AND EXTENDING THE SERVER
====================================

   `Net::FTPServer' can be configured and extended in a number of
different ways.

   Firstly, almost all common server configuration can be carried out by
editing the configuration file `/etc/ftpd.conf'.

   Secondly, commands can be loaded into the server at run-time to provide
custom extensions to the common FTP command set.  These custom commands
are written in Perl.

   Thirdly, one of several different supplied *personalities* can be
chosen. Personalities can be used to make deep changes to the FTP server:
for example, there is a supplied personality which allows the FTP server
to serve files from a relational database. By subclassing
`Net::FTPServer', `Net::FTPServer::DirHandle' and
`Net::FTPServer::FileHandle' you may also write your own personalities.

   The next sections talk about each of these possibilities in turn.

EDITING /etc/ftpd.conf
----------------------

   A standard `/etc/ftpd.conf' file is supplied with `Net::FTPServer' in
the distribution. This contains all possible configurable options,
information about them and defaults. You should consult the comments in
this file for authoritative information.

LOADING CUSTOMIZED SITE COMMANDS
--------------------------------

   It is very simple to write custom SITE commands. These commands are
available to users when they type "SITE XYZ" in a command line FTP client
or when they define a custom SITE command in their graphical FTP client.

   SITE commands are unregulated by RFCs. You may define any commands and
give them any names and any function you wish. However, over time various
standard SITE commands have been recognized and implemented in many FTP
servers. `Net::FTPServer' also implements these. They are:

     SITE VERSION      Display the server software version.
     SITE EXEC         Execute a shell command on the server (in
                       C<Net::FTPServer> this is disabled by default!)
     SITE ALIAS        Display chdir aliases.
     SITE CDPATH       Display chdir paths.
     SITE CHECKMETHOD  Implement checksums.
     SITE CHECKSUM
     SITE IDLE         Get or set the idle timeout.

   The following commands are found in `wu-ftpd', but not currently
implemented by `Net::FTPServer': SITE CHMOD, SITE GPASS, SITE GROUP, SITE
GROUPS, SITE INDEX, SITE MINFO, SITE NEWER, SITE UMASK.

   So when you are choosing a name for a SITE command, it is probably best
not to choose one of the above names, unless you are specifically
implementing or overriding that command.

   Custom SITE commands have to be written in Perl. However, there is very
little you need to understand in order to write these commands - you will
only need a basic knowledge of Perl scripting.

   As our first example, we will implement a `SITE README' command.  This
command just prints out some standard information.

   Firstly create a file called `/usr/local/lib/site_readme.pl' (you may
choose a different path if you want). The file should contain:

     sub {
       my $self = shift;
       my $cmd = shift;
       my $rest = shift;

     $self->reply (200,
                   "This is the README file for mysite.example.com.",
                   "Mirrors are contained in /pub/mirrors directory.",
                   "       :       :       :       :       :",
                   "End of the README file.");
       }

   Edit `/etc/ftpd.conf' and add the following command:

   site command: readme /usr/local/lib/site_readme.pl

   and restart the FTP server (check your system log [/var/log/messages]
for any syntax errors or other problems). Here is an example of a user
running the SITE README command:

     ftp> quote help site
     214-The following commands are recognized:
     214-    ALIAS   CHECKMETHOD     EXEC    README
     214-    CDPATH  CHECKSUM        IDLE    VERSION
     214 You can also use HELP to list general commands.
     ftp> site readme
     200-This is the README file for mysite.example.com.
     200-Mirrors are contained in /pub/mirrors directory.
     200-       :       :       :       :       :
     200 End of the README file.

   Our second example demonstrates how to use parameters (the `$rest'
argument). This is the `SITE ECHO' command.

     sub {
       my $self = shift;
       my $cmd = shift;
       my $rest = shift;

     # Split the parameters up.
     my @params = split /\s+/, $rest;

     # Quote each parameter.
     my $reply = join ", ", map { "'$_'" } @params;

     $self->reply (200, "You said: $reply");
       }

   Here is the `SITE ECHO' command in use:

     ftp> quote help site
     214-The following commands are recognized:
     214-    ALIAS   CHECKMETHOD     ECHO    IDLE
     214-    CDPATH  CHECKSUM        EXEC    VERSION
     214 You can also use HELP to list general commands.
     ftp> site echo hello how are you?
     200 You said: 'hello', 'how', 'are', 'you?'

   Our third example is more complex and shows how to interact with the
virtual filesystem (VFS). The `SITE SHOW' command will be used to list
text files directly (the user normally has to download the file and view
it locally). Hence `SITE SHOW readme.txt' should print the contents of the
`readme.txt' file in the local directory (if it exists).

   All file accesses must be done through the VFS, not by directly
accessing the disk. If you follow this convention then your commands will
be secure and will work correctly with different back-end personalities
(in particular when "files" are really blobs in a relational database).

     sub {
       my $self = shift;
       my $cmd = shift;
       my $rest = shift;

     # Get the file handle.
     my ($dirh, $fileh, $filename) = $self->_get ($rest);

     # File doesn't exist or not accessible. Return an error.
     unless ($fileh)
       {
     	$self->reply (550, "File or directory not found.");
     	return;
       }

     # Check it's a simple file.
     my ($mode) = $fileh->status;

     unless ($mode eq "f")
       {
     	$self->reply (550,
     		      "SITE SHOW command is only supported on plain files.");
     	return;
       }

     # Try to open the file.
     my $file = $fileh->open ("r");

     unless ($file)
       {
     	$self->reply (550, "File or directory not found.");
     	return;
       }

     # Copy data into memory.
     my @lines = ();

     while ($_ = $file->getline)
       {
     	# Remove any native line endings.
     	s/[\n\r]+$//;

     push @lines, $_;
           }

     # Close the file handle.
     $file->close;

     # Send the file back to the user.
     $self->reply (200, "File $filename:", @lines, "End of file.");
       }

   This code is not quite complete. A better implementation would also
check the "retrieve rule" (so that people couldnE<39>t use `SITE SHOW' in
order to get around access control limitations which the server
administrator has put in place). It would also check the file more closely
to make sure it was a text file and would refuse to list very large files.

   Here is an example (abbreviated) of a user using the `SITE SHOW'
command:

     ftp> site show README
     200-File README:
     200-$Id: FTPServer.pm,v 1.33 2001/02/22 15:46:12 rich Exp $
     200-
     200-Net::FTPServer - A secure, extensible and configurable Perl FTP server.
     [...]
     200-To contact the author, please email: Richard Jones <rich@annexia.org>
     200 End of file.

STANDARD PERSONALITIES
----------------------

   Currently `Net::FTPServer' is supplied with three standard
personalities. These are:

     Full    The complete read/write anonymous/authenticated FTP
             server which serves files from a standard Unix filesystem.

     RO      A small read-only anonymous-only FTP server similar
             in functionality to Dan Bernstein's publicfile
             program.

     DBeg1   An example FTP server which serves files to a PostgreSQL
             database. This supports files and hierarchical
             directories, multiple users (but not file permissions)
             and file upload.

   The standard Full personality will not be explained here.

   The *RO* personality is the Full personality with all code related to
writing files, creating directories, deleting, etc.  removed. The RO
personality also only permits anonymous logins and does not contain any
code to do ordinary authentication. It is therefore safe to use the RO
personality where you are only interested in serving files to anonymous
users and do not want to worry about crackers discovering a way to trick
the FTP server into writing over a file.

   The *DBeg1* personality is a complete read/write FTP server which
stores files as BLOBs (Binary Large OBjects) in a PostgreSQL relational
database. The personality supports file download and upload and contains
code to authenticate users against a users table in the database (database
"users" are thus completely unrelated to real Unix users). The *DBeg1* is
intended only as an example. It does not support advanced features such as
file permissions and quotas. As part of the schoolmaster.net project
Bibliotech Ltd. have developed an even more advanced database personality
which supports users, groups, access control lists, quotas, recursive
moves and copies and many other features. However this database
personality is not available as source.

   To use the DBeg1 personality you must first run a PostgreSQL server
(version 6.4 or above) and ensure that you have access to it from your
local user account.  Use the `initdb', `createdb' and `createuser'
commands to create the appropriate user account and database (please
consult the PostgreSQL administrators manual for further information about
this - I do not answer questions about basic PostgreSQL knowledge).

   Here is my correctly set up PostgreSQL server, accessed from my local
user account "rich":

     cruiser:~$ psql
     Welcome to the POSTGRESQL interactive sql monitor:
       Please read the file COPYRIGHT for copyright terms of POSTGRESQL

     type \? for help on slash commands
     type \q to quit
     type \g or terminate with semicolon to execute query
        You are currently connected to the database: rich

     rich=> \d
     Couldn't find any tables, sequences or indices!

   You will also need the following Perl modules installed: DBI, DBD::Pg.

   Now you will need to create a database called "ftp" and populate it
with data. This is how to do this:

     createdb ftp
     psql ftp < doc/eg1.sql

   Check that no ERRORs are reported by PostgreSQL.

   You should now be able to start the FTP server by running the following
command (not as root):

     ./dbeg1-ftpd -S -p 2000 -C ftpd.conf

   If the FTP server doesnE<39>t start correctly, you should check the
system log file [/var/log/messages].

   Connect to the FTP server as follows:

     ftp localhost 2000

   Log in as either rich/123456 or dan/123456 and then try to move around,
upload and download files, create and delete directories, etc.

SUBCLASSING THE Net::FTPServer CLASSES
--------------------------------------

   By subclassing `Net::FTPServer', `Net::FTPServer::DirHandle' and/or
`Net::FTPServer::FileHandle' you can create custom personalities for the
FTP server.

   Typically by overriding the hooks in the `Net::FTPServer' class you can
change the basic behaviour of the FTP server - turning it into an
anonymous read-only server, for example.

   By overriding the hooks in `Net::FTPServer::DirHandle' and
`Net::FTPServer::FileHandle' you can create virtual filesystems: serving
files into and out of a database, for example.

   The current manual page contains information about the hooks in
`Net::FTPServer' which may be overridden.

   See `Net::FTPServer::DirHandle(3)' in this node for information about
the methods in `Net::FTPServer::DirHandle' which may be overridden.

   See `Net::FTPServer::FileHandle(3)' in this node for information about
the methods in `Net::FTPServer::FileHandle' which may be overridden.

   The most reasonable way to create your own personality is to extend one
of the existing personalities. Choose the one which most closely matches
the personality that you want to create. For example, suppose that you
want to create another database personality. A good place to start would
be by copying `lib/Net/FTPServer/DBeg1/*.pm' to a new directory
`lib/Net/FTPServer/MyDB/' (for example). Now edit these files and
substitute "MyDB" for "DBeg1". Then examine each subroutine in these files
and modify them, consulting the appropriate manual page if you need to.

VIRTUAL HOSTS
-------------

   `Net:FTPServer' is capable of hosting multiple FTP sites on a single
machine. Because of the nature of the FTP protocol, virtual hosting is
almost always done by allocating a single separate IP address per FTP
site. However, `Net::FTPServer' also supports an experimental IP-less
virtual hosting system, although this requires modifications to the client.

   Normal (IP-based) virtual hosting is carried out as follows:

     * For each FTP site, allocate a separate IP address.
     * Configure IP aliasing on your normal interface so that
       the single physical interface responds to multiple
       virtual IP addresses.
     * Add entries (A records) in DNS mapping each site's
       name to a separate IP address.
     * Add reverse entries (PTR records) in DNS mapping each
       IP address back to the site hostname. It is important
       that both forward and reverse DNS is set up correctly,
       else virtual hosting may not work.
     * In /etc/ftpd.conf you will need to add a virtual host
       section for each site like this:

     <Host sitename>

     ip: 1.2.3.4
     ... any specific configuration options for this site ...

     </Host>

     You don't in fact need the "ip:" part assuming that
     your forward and reverse DNS are set up correctly.
      * If you want to specify a lot of external sites, or
     generate the configuration file automatically from a
     database or a script, you may find the <Include filename>
     syntax useful.

   There are examples in `/etc/ftpd.conf'. Here is how IP-based virtual
hosting works:

     * The server starts by listening on all interfaces.
     * A connection arrives at one of the IP addresses and a
       process is forked off.
     * The child process finds out which interface the
       client connected to and reverses the name.
     * If:
         the IP address matches one of the "ip:" declarations
         in any of the "Host" sections,
       or:
         there is a reversal for the name, and the name
         matches one of the "Host" sections in the configuration
         file,
       then:
         configuration options are read from that
         section of the file and override any global configuration
         options specified elsewhere in the file.
     * Otherwise, the global configuration options only
       are used.

   IP-less virtual hosting is an experimental feature. It requires the
client to send a `HOST' command very early on in the command stream -
before USER and PASS. The `HOST' command explicitly gives the hostname
that the FTP client is attempting to connect to, and so allows many FTP
sites to be multiplexed onto a single IP address. At the present time, I
am not aware of any FTP clients which implement the `HOST' command,
although they will undoubtedly become more common in future.

   This is how to set up IP-less virtual hosting:

     * Add entries (A or CNAME records) in DNS mapping the
       name of each site to a single IP address.
     * In /etc/ftpd.conf you will need to list the same single
       IP address to which all your sites map:

     virtual host multiplex: 1.2.3.4

     * In /etc/ftpd.conf you will need to add a virtual host
       section for each site like this:

     <Host sitename>

     ... any specific configuration options for this site ...

     </Host>

   Here is how IP-less virtual hosting works:

     * The server starts by listening on one interface.
     * A connection arrives at the IP address and a
       process is forked off.
     * The IP address matches "virtual host multiplex"
       and so no IP-based virtual host processing is done.
     * One of the first commands that the client sends is
       "HOST" followed by the hostname of the site.
     * If there is a matching "Host" section in the
       configuration file, then configuration options are
       read from that section of the file and override any
       global configuration options specified elsewhere in
       the file.
     * If there is no matching "Host" section then the
       global configuration options alone are used.

   The client is not permitted to issue the `HOST' command more than once,
and is not permitted to issue it after login.

VIRTUAL HOSTING AND SECURITY
----------------------------

   Only certain configuration options are available inside the <Host>
sections of the configuration file.  Generally speaking, the only
configuration options you can put here are ones which take effect after the
site name has been determined - hence "allow anonymous" is OK (since
itE<39>s an option which is parsed after determining the site name and
during log in), but "port" is not (since it is parsed long before any
clients ever connect).

   Make sure your default global configuration is secure. If you are using
IP-less virtual hosting, this is particularly important, since if the
client never sends a `HOST' command, the client gets the global
configuration. Even with IP-based virtual hosting it may be possible for
clients to sometimes get the global configuration, for example if your
local name server fails.

   IP-based virtual hosting always takes precedence above IP-less virtual
hosting.

   With IP-less virtual hosting, access control cannot be performed on a
per-site basis. This is because the client has to issue commands (ie. the
`HOST' command at least) before the site name is known to the server.
However you may still have a global "access control rule".

METHODS
=======

Net::FTPServer->run ([\@ARGV]);
     This is the main entry point into the FTP server. It starts the FTP
     server running. This function never normally returns.

     If no arguments are given, then command line arguments are taken from
     the global `@ARGV' array.

$ftps->reply ($code, $line, [$line, ...])
     This function sends a standard single line or multi-line FTP server
     reply to the client. The $code should be one of the standard reply
     codes listed in RFC 959. The one or more `$line' arguments are the
     (free text) of the reply. Do not include carriage returns at the end
     of each `$line'.  This function adds the correct line ending format
     as specified in the RFC.

$ftps->config ($name);
     Read configuration option $name from the configuration file.

$ftps->ip_host_config ($ip_addr);
     Look for a <Host> section which contains "ip: $ip_addr".  If one is
     found, return the site name of the Host section. Otherwise return
     undef.

$sock = $self->open_data_connection;
     Open a data connection. Returns the socket (an instance of
     IO::Socket) or undef if it fails for some reason.

$self->pre_configuration_hook ();
     Hook: Called before command line arguments and configuration file are
     read.

     Status: optional.

     Notes: You may append your own information to
     `$self-'{version_string}> from this hook.

$self->options_hook (\@args);
     Hook: Called before command line arguments are parsed.

     Status: optional.

     Notes: You can use this hook to supply your own command line
     arguments.  If you parse any arguments, you should remove them from
     the @args array.

$self->post_configuration_hook ();
     Hook: Called after all command line arguments and configuration file
     have been read and parsed.

     Status: optional.

$self->post_bind_hook ();
     Hook: Called only in daemon mode after the control port is bound but
     before starting the accept infinite loop block.

     Status: optional.

$self->pre_accept_hook ();
     Hook: Called in daemon mode only just before `accept(2)' is called in
     the parent FTP server process.

     Status: optional.

$self->post_accept_hook ();
     Hook: Called both in daemon mode and in inetd mode just after the
     connection has been accepted. This is called in the child process.

     Status: optional.

$rv = $self->access_control_hook;
     Hook: Called after `accept(2)'-ing the connection to perform access
     control. Detailed request information is contained in the $self
     object.  If the function returns -1 then the socket is immediately
     closed and no FTP processing happens on it. If the function returns 0,
     then normal access control is performed on the socket before FTP
     processing starts. If the function returns 1, then normal access
     control is not performed on the socket and FTP processing begins
     immediately.

     Status: optional.

$rv = $self->process_limits_hook;
     Hook: Called after `accept(2)'-ing the connection to perform
     per-process limits (eg. by using the setrlimit(2) system call).
     Access control has already been performed and detailed request
     information is contained in the `$self' object.

     If the function returns -1 then the socket is immediately closed and
     no FTP processing happens on it. If the function returns 0, then
     normal per-process limits are applied before any FTP processing
     starts. If the function returns 1, then normal per-process limits are
     not performed and FTP processing begins immediately.

     Status: optional.

$rv = $self->authentication_hook ($user, $pass, $user_is_anon)
     Hook: Called to perform authentication. If the authentication
     succeeds, this should return 0. If the authentication fails, this
     should return -1.

     Status: required.

$self->user_login_hook ($user, $user_is_anon)
     Hook: Called just after user `$user' has successfully logged in. A
     good place to change uid and chroot if necessary.

     Status: optional.

$dirh = $self->root_directory_hook;
     Hook: Return an instance of a subclass of Net::FTPServer::DirHandle
     corresponding to the root directory.

     Status: required.

$self->pre_command_hook;
     Hook: This hook is called just before the server begins to wait for
     the client to issue the next command over the control connection.

     Status: optional.

$rv = $self->command_filter_hook ($cmdline);
     Hook: This hook is called immediately after the client issues command
     `$cmdline', but before any checking or processing is performed on the
     command. If this function returns -1, then the server immediately
     goes back to waiting for the next command. If this function returns
     0, then normal command filtering is carried out and the command is
     processed. If this function returns 1 then normal command filtering
     is not performed and the command processing begins immediately.

     Important Note: This hook must be careful not to overwrite the global
     $_ variable.

     Do not use this function to add your own commands. Instead use the
     `$self->{command_table}' and `$self->{site_command_table}' hashes.

     Status: optional.

$error = $self->transfer_hook ($mode, $file, $sock, \$buffer);
          $mode     -  Open mode on the File object (Either reading or writing)
          $file     -  File object as returned from DirHandle::open
          $sock     -  Data IO::Socket object used for transfering
          \$buffer  -  Reference to current buffer about to be written

     The \$buffer is passed by reference to minimize the stack overhead
     for efficiency purposes only.  It is not meant to be modified by the
     transfer_hook subroutine.  (It can cause corruption if the length of
     $buffer is modified.)

     Hook: This hook is called after reading $buffer and before writing
     $buffer to its destination.  If arg1 is "r", $buffer was read from
     the File object and written to the Data socket.  If arg1 is "w",
     $buffer will be written to the File object because it was read from
     the Data Socket.  The return value is the error for not being able to
     perform the write.  Return undef to avoid aborting the transfer
     process.

     Status: optional.

$self->post_command_hook
     Hook: This hook is called after all command processing has been
     carried out on this command.

     Status: optional.

BUGS
====

   The SIZE, REST and RETR commands probably do not work correctly in
ASCII mode.

   REST does not work before STOR/STOU/APPE (is it supposed to?)

   You cannot abort a transfer in progress yet. Nor can you check the
status of a transfer in progress. Using the telnet interrupt commands can
cause the FTP server to fail.

   User upload/download limits.

   Limit number of clients. Limit number of clients by host or IP address.

   The following commands are recognized by `wu-ftpd', but are not yet
implemented by `Net::FTPServer':

     SITE CHMOD   There is a problem supporting this with our VFS.
     SITE GPASS   Group functions are not really relevant for us.
     SITE GROUP   -"- ditto -"-
     SITE GROUPS  -"- ditto -"-
     SITE INDEX   This is a synonym for SITE EXEC.
     SITE MINFO   This command is no longer supported by wu-ftpd.
     SITE NEWER   This command is no longer supported by wu-ftpd.
     SITE UMASK   This command is difficult to support with VFS.

   Symbolic links are not handled elegantly (or indeed at all) yet.

   The program needs to log a lot more general transfer and access
information to syslog.

   Equivalent of ProFTPDE<39>s "DisplayReadme" function.

   The ability to hide dot files (probably best to build this into the VFS
layer). This should apply across all commands.  See ProFTPDE<39>s
"IgnoreHidden" function.

   Do ident (RFC913) authentication at login. Have a way to turn this on
and off.

   Access to LDAP authentication database (can currently be done using a
PAM module). In general, we should support pluggable authentication.

   Log formatting similar to ProFTPD command LogFormat.

   More timeouts to avoid various denial of service attacks. For example,
the server should always timeout when waiting too long for an active data
connection.

   Support for IPv6 (see RFC 2428), EPRT, EPSV commands.

   Upload and download tar.gz/zip files automatically.

   See also "XXX" comments in the code for other problems, missing features
and bugs.

FILES
=====

     /etc/ftpd.conf
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/DirHandle.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/FileHandle.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/Handle.pm

AUTHORS
=======

   Richard Jones (rich@annexia.org).

COPYRIGHT
=========

   Copyright (C) 2000 Biblio@Tech Ltd., Unit 2-3, 50 Carnwath Road,
London, SW6 3EG, UK

SEE ALSO
========

   `Net::FTPServer::Handle(3)' in this node,
`Net::FTPServer::FileHandle(3)' in this node,
`Net::FTPServer::DirHandle(3)' in this node, `Authen::PAM(3)' in this node,
`Net::FTP(3)' in this node, `perl(1)' in this node, RFC 765, RFC 959, RFC
1579, RFC 2389, RFC 2428, RFC 2577, RFC 2640, Extensions to FTP Internet
Draft draft-ietf-ftpext-mlst-NN.txt.

The example DB FTP server personality
*************************************

NAME
====

   Net::FTPServer::DBeg1::DirHandle - The example DB FTP server personality

SYNOPSIS
========

     use Net::FTPServer::DBeg1::DirHandle;

DESCRIPTION
===========

METHODS
=======

AUTHORS
=======

   Richard Jones (rich@annexia.org).

COPYRIGHT
=========

   Copyright (C) 2000 Biblio@Tech Ltd., Unit 2-3, 50 Carnwath Road,
London, SW6 3EG, UK

SEE ALSO
========

   `Net::FTPServer(3)' in this node, `perl(1)' in this node

The full FTP server personality
*******************************

NAME
====

   Net::FTPServer::DBeg1::FileHandle - The full FTP server personality

SYNOPSIS
========

     use Net::FTPServer::DBeg1::FileHandle;

DESCRIPTION
===========

METHODS
=======

AUTHORS
=======

   Richard Jones (rich@annexia.org).

COPYRIGHT
=========

   Copyright (C) 2000 Biblio@Tech Ltd., Unit 2-3, 50 Carnwath Road,
London, SW6 3EG, UK

SEE ALSO
========

   `Net::FTPServer(3)' in this node, `perl(1)' in this node

The example DB FTP server personality
*************************************

NAME
====

   Net::FTPServer::DBeg1::IOBlob - The example DB FTP server personality

SYNOPSIS
========

     use Net::FTPServer::DBeg1::IOBlob;

DESCRIPTION
===========

METHODS
=======

$io = Net::FTPServer::DBeg1::IOBlob ('r', $dbh, $blob_id);
$io = Net::FTPServer::DBeg1::IOBlob ('w', $dbh, $blob_id);
     Create an IO handle for reading or writing a PostgreSQL blob.

$io->getc ();
     Read 1 byte from the buffer and return it

$io->read ($buffer, $nbytes, [$offset]);
$io->sysread ($buffer, $nbytes, [$offset]);
     Read `$nbytes' from the handle and place them in `$buffer' at offset
     $offset.

$io->write ($buffer, $nbytes, [$offset]);
$io->syswrite ($buffer, $nbytes, [$offset]);
     Write `$nbytes' to the handle from `$buffer' offset $offset.

$io->print ($buffer);
$io->close;
     Close the IO handle.

AUTHORS
=======

   Richard Jones (rich@annexia.org).

COPYRIGHT
=========

   Copyright (C) 2000 Biblio@Tech Ltd., Unit 2-3, 50 Carnwath Road,
London, SW6 3EG, UK

SEE ALSO
========

   `Net::FTPServer(3)' in this node, `perl(1)' in this node

The DB example FTP server personality
*************************************

NAME
====

   Net::FTPServer::DBeg1::Server - The DB example FTP server personality

SYNOPSIS
========

     dbeg1-ftpd [-d] [-v] [-p port] [-s] [-S] [-V] [-C conf_file]

DESCRIPTION
===========

   `Net::FTPServer::DBeg1::Server' is the example DB-based FTP server
personality. This personality implements a simple FTP server with a
PostgreSQL database back-end.

METHODS
=======

FILES
=====

     /etc/ftpd.conf
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/DirHandle.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/FileHandle.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/Handle.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/DBeg1/Server.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/DBeg1/DirHandle.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/DBeg1/FileHandle.pm

AUTHORS
=======

   Richard Jones (rich@annexia.org).

COPYRIGHT
=========

   Copyright (C) 2000 Biblio@Tech Ltd., Unit 2-3, 50 Carnwath Road,
London, SW6 3EG, UK

SEE ALSO
========

   `Net::FTPServer(3)' in this node, `Authen::PAM(3)' in this node,
`Net::FTP(3)' in this node, `perl(1)' in this node, RFC 765, RFC 959, RFC
1579, RFC 2389, RFC 2428, RFC 2577, RFC 2640, Extensions to FTP Internet
Draft draft-ietf-ftpext-mlst-NN.txt.

A Net::FTPServer directory handle.
**********************************

NAME
====

   Net::FTPServer::DirHandle - A Net::FTPServer directory handle.

SYNOPSIS
========

     use Net::FTPServer::DirHandle;

DESCRIPTION
===========

METHODS
=======

$dirh = new Net::FTPServer::DirHandle ($ftps);
     Create a new directory handle. The directory handle corresponds to
     "/".

$dirh = $dirh->parent;
     Return the parent directory of the directory $dirh. If the directory
     is already "/", this returns the same directory handle.

$rv = $dirh->is_root;
     Return true if the current directory is the root directory.

$handle = $dirh->get ($filename);
     Return the file or directory $handle corresponding to the file
     $filename in directory $dirh. If there is no file or subdirectory of
     that name, then this returns undef.

$ref = $dirh->list ([$wildcard]);
     Return a list of the contents of directory $dirh. The list returned
     is a reference to an array of pairs:

          [ $filename, $handle ]

     The list returned does not include "." or "..".

     The list is sorted into alphabetical order automatically.

$ref = $dirh->list_status ([$wildcard]);
     Return a list of the contents of directory $dirh and status
     information. The list returned is a reference to an array of triplets:

          [ $filename, $handle, $statusref ]

     where $statusref is the tuple returned from the status method (see
     Net/FTPServer/Handle).

     The list returned does not include "." or "..".

     The list is sorted into alphabetical order automatically.

$rv = $dirh->delete;
     Delete the current directory. If the delete command was successful,
     then return 0, else if there was an error return -1.

     It is normally only possible to delete a directory if it is empty.

$rv = $dirh->mkdir ($name);
     Create a subdirectory called $name within the current directory $dirh.

$file = $dirh->open ($filename, "r"|"w"|"a");
     Open or create a file called $filename in the current directory,
     opening it for either read, write or append. This function returns a
     IO::File handle object.

$rv = $dirh->can_write;
     Return true if the current user can write into the current directory
     (ie. create files, rename files, delete files, etc.).

$rv = $dirh->can_delete;
     Return true if the current user can delete the current directory.

$rv = $dirh->can_enter;
     Return true if the current user can enter the current directory.

$rv = $dirh->can_list;
     Return true if the current user can list the current directory.

$rv = $dirh->can_rename;
     Return true if the current user can rename the current directory.

$rv = $dirh->can_mkdir;
     Return true if the current user can create subdirectories of the
     current directory.

AUTHORS
=======

   Richard Jones (rich@annexia.org).

COPYRIGHT
=========

   Copyright (C) 2000 Biblio@Tech Ltd., Unit 2-3, 50 Carnwath Road,
London, SW6 3EG, UK

SEE ALSO
========

   `Net::FTPServer(3)' in this node, `perl(1)' in this node

A Net::FTPServer file handle.
*****************************

NAME
====

   Net::FTPServer::FileHandle - A Net::FTPServer file handle.

SYNOPSIS
========

     use Net::FTPServer::FileHandle;

DESCRIPTION
===========

METHODS
=======

$filename = $fileh->filename;
     Return the filename (last) component.

$dirh = $fileh->dir;
     Return the directory which contains this file.

$fh = $fileh->open (["r"|"w"|"a"]);
     Open a file handle (derived from IO::Handle, see `IO::Handle(3)' in
     this node) in either read or write mode.

$rv = $fileh->delete;
     Delete the current file. If the delete command was successful, then
     return 0, else if there was an error return -1.

$rv = $fileh->can_read;
     Return true if the current user can read the given file.

$rv = $fileh->can_write;
     Return true if the current user can overwrite the given file.

$rv = $fileh->can_append
     Return true if the current user can append to the given file.

$rv = $fileh->can_rename;
     Return true if the current user can change the name of the given file.

$rv = $fileh->can_delete;
     Return true if the current user can delete the given file.

AUTHORS
=======

   Richard Jones (rich@annexia.org).

COPYRIGHT
=========

   Copyright (C) 2000 Biblio@Tech Ltd., Unit 2-3, 50 Carnwath Road,
London, SW6 3EG, UK

SEE ALSO
========

   `Net::FTPServer(3)' in this node, `perl(1)' in this node

The full FTP server personality
*******************************

NAME
====

   Net::FTPServer::Full::DirHandle - The full FTP server personality

SYNOPSIS
========

     use Net::FTPServer::Full::DirHandle;

DESCRIPTION
===========

METHODS
=======

$handle = $dirh->get ($filename);
     Return the file or directory $handle corresponding to the file
     $filename in directory $dirh. If there is no file or subdirectory of
     that name, then this returns undef.

$dirh = $dirh->parent;
     Return the parent directory of the directory $dirh. If the directory
     is already "/", this returns the same directory handle.

$ref = $dirh->list ([$wildcard]);
     Return a list of the contents of directory $dirh. The list returned
     is a reference to an array of pairs:

          [ $filename, $handle ]

     The list returned does not include "." or "..".

     The list is sorted into alphabetical order automatically.

$ref = $dirh->list_status ([$wildcard]);
     Return a list of the contents of directory $dirh and status
     information. The list returned is a reference to an array of triplets:

          [ $filename, $handle, $statusref ]

     where $statusref is the tuple returned from the status method (see
     Net/FTPServer/Handle).

     The list returned does not include "." or "..".

     The list is sorted into alphabetical order automatically.

($mode, $perms, $nlink, $user, $group, $size, $time) = $handle->status;
     Return the file or directory status. The fields returned are:

          $mode     Mode        'd' = directory,
                                'f' = file,
                                and others as with
                                the file(1) -type option.
          $perms    Permissions Permissions in normal octal numeric format.
          $nlink    Link count
          $user     Username    In printable format.
          $group    Group name  In printable format.
          $size     Size        File size in bytes.
          $time     Time        Time (usually mtime) in Unix time_t format.

     In derived classes, some of this status information may well be
     synthesized, since virtual filesystems will often not contain
     information in a Unix-like format.

$rv = $handle->move ($dirh, $filename);
     Move the current file (or directory) into directory $dirh and call it
     $filename. If the operation is successful, return 0, else return -1.

     Underlying filesystems may impose limitations on moves: for example,
     it may not be possible to move a directory; it may not be possible to
     move a file to another directory; it may not be possible to move a
     file across filesystems.

$rv = $dirh->delete;
     Delete the current directory. If the delete command was successful,
     then return 0, else if there was an error return -1.

     It is normally only possible to delete a directory if it is empty.

$rv = $dirh->mkdir ($name);
     Create a subdirectory called $name within the current directory $dirh.

$file = $dirh->open ($filename, "r"|"w"|"a");
     Open or create a file called $filename in the current directory,
     opening it for either read, write or append. This function returns a
     IO::File handle object.

$rv = $dirh->can_write;
     Return true if the current user can write into the current directory
     (ie. create files, rename files, delete files, etc.).

$rv = $dirh->can_delete;
     Return true if the current user can delete the current directory.

$rv = $dirh->can_enter;
     Return true if the current user can enter the current directory.

$rv = $dirh->can_list;
     Return true if the current user can list the current directory.

$rv = $dirh->can_rename;
     Return true if the current user can rename the current directory.

$rv = $dirh->can_mkdir;
     Return true if the current user can create subdirectories of the
     current directory.

AUTHORS
=======

   Richard Jones (rich@annexia.org).

COPYRIGHT
=========

   Copyright (C) 2000 Biblio@Tech Ltd., Unit 2-3, 50 Carnwath Road,
London, SW6 3EG, UK

SEE ALSO
========

   `Net::FTPServer(3)' in this node, `perl(1)' in this node

The full FTP server personality
*******************************

NAME
====

   Net::FTPServer::Full::FileHandle - The full FTP server personality

SYNOPSIS
========

     use Net::FTPServer::Full::FileHandle;

DESCRIPTION
===========

METHODS
=======

$dirh = $fileh->dir;
     Return the directory which contains this file.

$fh = $fileh->open (["r"|"w"|"a"]);
     Open a file handle (derived from IO::Handle, see `IO::Handle(3)' in
     this node) in either read or write mode.

($mode, $perms, $nlink, $user, $group, $size, $time) = $handle->status;
     Return the file or directory status. The fields returned are:

          $mode     Mode        'd' = directory,
                                'f' = file,
                                and others as with
                                the file(1) -type option.
          $perms    Permissions Permissions in normal octal numeric format.
          $nlink    Link count
          $user     Username    In printable format.
          $group    Group name  In printable format.
          $size     Size        File size in bytes.
          $time     Time        Time (usually mtime) in Unix time_t format.

     In derived classes, some of this status information may well be
     synthesized, since virtual filesystems will often not contain
     information in a Unix-like format.

$rv = $handle->move ($dirh, $filename);
     Move the current file (or directory) into directory $dirh and call it
     $filename. If the operation is successful, return 0, else return -1.

     Underlying filesystems may impose limitations on moves: for example,
     it may not be possible to move a directory; it may not be possible to
     move a file to another directory; it may not be possible to move a
     file across filesystems.

$rv = $fileh->delete;
     Delete the current file. If the delete command was successful, then
     return 0, else if there was an error return -1.

$rv = $fileh->can_read;
     Return true if the current user can read the given file.

$rv = $fileh->can_write;
     Return true if the current user can overwrite the given file.

$rv = $fileh->can_append
     Return true if the current user can append to the given file.

$rv = $fileh->can_rename;
     Return true if the current user can change the name of the given file.

$rv = $fileh->can_delete;
     Return true if the current user can delete the given file.

AUTHORS
=======

   Richard Jones (rich@annexia.org).

COPYRIGHT
=========

   Copyright (C) 2000 Biblio@Tech Ltd., Unit 2-3, 50 Carnwath Road,
London, SW6 3EG, UK

SEE ALSO
========

   `Net::FTPServer(3)' in this node, `perl(1)' in this node

The full FTP server personality
*******************************

NAME
====

   Net::FTPServer::Full::Server - The full FTP server personality

SYNOPSIS
========

     ftpd [-d] [-v] [-p port] [-s] [-S] [-V] [-C conf_file]

DESCRIPTION
===========

   `Net::FTPServer::Full::Server' is the full FTP server personality. This
personality implements a complete FTP server with similar functionality to
*wu-ftpd*.

METHODS
=======

$rv = $self->authentication_hook ($user, $pass, $user_is_anon)
     Perform login against `/etc/passwd' or the PAM database.

$self->user_login_hook ($user, $user_is_anon)
     Hook: Called just after user `$user' has successfully logged in.

$dirh = $self->root_directory_hook;
     Hook: Return an instance of Net::FTPServer::FullDirHandle
     corresponding to the root directory.

FILES
=====

     /etc/ftpd.conf
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/DirHandle.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/FileHandle.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/Handle.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/Full/Server.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/Full/DirHandle.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/Full/FileHandle.pm

AUTHORS
=======

   Richard Jones (rich@annexia.org).

COPYRIGHT
=========

   Copyright (C) 2000 Biblio@Tech Ltd., Unit 2-3, 50 Carnwath Road,
London, SW6 3EG, UK

SEE ALSO
========

   `Net::FTPServer(3)' in this node, `Authen::PAM(3)' in this node,
`Net::FTP(3)' in this node, `perl(1)' in this node, RFC 765, RFC 959, RFC
1579, RFC 2389, RFC 2428, RFC 2577, RFC 2640, Extensions to FTP Internet
Draft draft-ietf-ftpext-mlst-NN.txt.

A generic Net::FTPServer file or directory handle.
**************************************************

NAME
====

   Net::FTPServer::Handle - A generic Net::FTPServer file or directory
handle.

SYNOPSIS
========

     use Net::FTPServer::Handle;

DESCRIPTION
===========

METHODS
=======

$handle = Net::FTPServer::Handle->new ($ftps);
     Create a new handle. You would normally call this from a derived
     class.

$rv = $handle->equals ($other_handle);
     Decide if two handles refer to the same thing (file or directory).

($mode, $perms, $nlink, $user, $group, $size, $time) = $handle->status;
     Return the file or directory status. The fields returned are:

          $mode     Mode        'd' = directory,
                                'f' = file,
                                and others as with
                                the file(1) -type option.
          $perms    Permissions Permissions in normal octal numeric format.
          $nlink    Link count
          $user     Username    In printable format.
          $group    Group name  In printable format.
          $size     Size        File size in bytes.
          $time     Time        Time (usually mtime) in Unix time_t format.

     In derived classes, some of this status information may well be
     synthesized, since virtual filesystems will often not contain
     information in a Unix-like format.

$name = $handle->pathname;
     Return the full path of this file or directory. The path consists of
     all components separated by "/" characters.

     If the object is a directory, then the pathname will have a "/"
     character at the end.

$name = $handle->filename;
     Return the filename part of the path. If the file is a directory,
     then this function returns "".

$name = $handle->dirname;
     Return the directory name part of the path. The directory name always
     has a trailing "/" character.

$rv = $handle->move ($dirh, $filename);
     Move the current file (or directory) into directory $dirh and call it
     $filename. If the operation is successful, return 0, else return -1.

     Underlying filesystems may impose limitations on moves: for example,
     it may not be possible to move a directory; it may not be possible to
     move a file to another directory; it may not be possible to move a
     file across filesystems.

$rv = $handle->delete;
     Delete the current file or directory. If the delete command was
     successful, then return 0, else if there was an error return -1.

     Different underlying file systems may impose restrictions on this
     command: for example, it may not be possible to delete directories,
     or only if they are empty.

     This is a virtual function which is actually implemented in one of
     the subclasses.

AUTHORS
=======

   Richard Jones (rich@annexia.org).

COPYRIGHT
=========

   Copyright (C) 2000 Biblio@Tech Ltd., Unit 2-3, 50 Carnwath Road,
London, SW6 3EG, UK

SEE ALSO
========

   `Net::FTPServer(3)' in this node, `perl(1)' in this node

Store files in local memory
***************************

NAME
====

   Net::FTPServer::InMem::DirHandle - Store files in local memory

SYNOPSIS
========

     use Net::FTPServer::InMem::DirHandle;

DESCRIPTION
===========

METHODS
=======

AUTHORS
=======

   Richard Jones (rich@annexia.org).

COPYRIGHT
=========

   Copyright (C) 2000 Biblio@Tech Ltd., Unit 2-3, 50 Carnwath Road,
London, SW6 3EG, UK

SEE ALSO
========

   `Net::FTPServer(3)' in this node, `perl(1)' in this node

Store files in local memory
***************************

NAME
====

   Net::FTPServer::InMem::FileHandle - Store files in local memory

SYNOPSIS
========

     use Net::FTPServer::InMem::FileHandle;

DESCRIPTION
===========

METHODS
=======

AUTHORS
=======

   Richard Jones (rich@annexia.org).

COPYRIGHT
=========

   Copyright (C) 2000 Biblio@Tech Ltd., Unit 2-3, 50 Carnwath Road,
London, SW6 3EG, UK

SEE ALSO
========

   `Net::FTPServer(3)' in this node, `perl(1)' in this node

Store files in local memory
***************************

NAME
====

   Net::FTPServer::InMem::Server - Store files in local memory

SYNOPSIS
========

     inmem-ftpd [-d] [-v] [-p port] [-s] [-S] [-V] [-C conf_file]

DESCRIPTION
===========

   `Net::FTPServer::InMem::Server' is the example FTP server personality.
This personality implements a simple FTP server which stores files in
local memory. This personality is used mainly for automatic testing in the
test suites (see the `t/' directory in the distribution).

METHODS
=======

FILES
=====

     /etc/ftpd.conf
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/DirHandle.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/FileHandle.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/Handle.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/InMem/Server.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/InMem/DirHandle.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/InMem/FileHandle.pm

AUTHORS
=======

   Richard Jones (rich@annexia.org).

COPYRIGHT
=========

   Copyright (C) 2000 Biblio@Tech Ltd., Unit 2-3, 50 Carnwath Road,
London, SW6 3EG, UK

SEE ALSO
========

   `Net::FTPServer(3)' in this node.

The anonymous, read-only FTP server personality
***********************************************

NAME
====

   Net::FTPServer::RO::DirHandle - The anonymous, read-only FTP server
personality

SYNOPSIS
========

     use Net::FTPServer::RO::DirHandle;

DESCRIPTION
===========

METHODS
=======

$handle = $dirh->get ($filename);
     Return the file or directory $handle corresponding to the file
     $filename in directory $dirh. If there is no file or subdirectory of
     that name, then this returns undef.

$dirh = $dirh->parent;
     Return the parent directory of the directory $dirh. If the directory
     is already "/", this returns the same directory handle.

$ref = $dirh->list ([$wildcard]);
     Return a list of the contents of directory $dirh. The list returned
     is a reference to an array of pairs:

          [ $filename, $handle ]

     The list returned does not include "." or "..".

     The list is sorted into alphabetical order automatically.

$ref = $dirh->list_status ([$wildcard]);
     Return a list of the contents of directory $dirh and status
     information. The list returned is a reference to an array of triplets:

          [ $filename, $handle, $statusref ]

     where $statusref is the tuple returned from the status method (see
     Net/FTPServer/Handle).

     The list returned does not include "." or "..".

     The list is sorted into alphabetical order automatically.

($mode, $perms, $nlink, $user, $group, $size, $time) = $handle->status;
     Return the file or directory status. The fields returned are:

          $mode     Mode        'd' = directory,
                                'f' = file,
                                and others as with
                                the file(1) -type option.
          $perms    Permissions Permissions in normal octal numeric format.
          $nlink    Link count
          $user     Username    In printable format.
          $group    Group name  In printable format.
          $size     Size        File size in bytes.
          $time     Time        Time (usually mtime) in Unix time_t format.

     In derived classes, some of this status information may well be
     synthesized, since virtual filesystems will often not contain
     information in a Unix-like format.

$rv = $handle->move ($dirh, $filename);
     Move the current file (or directory) into directory $dirh and call it
     $filename. If the operation is successful, return 0, else return -1.

     Underlying filesystems may impose limitations on moves: for example,
     it may not be possible to move a directory; it may not be possible to
     move a file to another directory; it may not be possible to move a
     file across filesystems.

$rv = $dirh->delete;
     Delete the current directory. If the delete command was successful,
     then return 0, else if there was an error return -1.

     It is normally only possible to delete a directory if it is empty.

$rv = $dirh->mkdir ($name);
     Create a subdirectory called $name within the current directory $dirh.

$file = $dirh->open ($filename, "r"|"w"|"a");
     Open or create a file called $filename in the current directory,
     opening it for either read, write or append. This function returns a
     IO::File handle object.

$rv = $dirh->can_write;
     Return true if the current user can write into the current directory
     (ie. create files, rename files, delete files, etc.).

$rv = $dirh->can_delete;
     Return true if the current user can delete the current directory.

$rv = $dirh->can_enter;
     Return true if the current user can enter the current directory.

$rv = $dirh->can_list;
     Return true if the current user can list the current directory.

$rv = $dirh->can_rename;
     Return true if the current user can rename the current directory.

$rv = $dirh->can_mkdir;
     Return true if the current user can create subdirectories of the
     current directory.

AUTHORS
=======

   Richard Jones (rich@annexia.org).

COPYRIGHT
=========

   Copyright (C) 2000 Biblio@Tech Ltd., Unit 2-3, 50 Carnwath Road,
London, SW6 3EG, UK

SEE ALSO
========

   `Net::FTPServer(3)' in this node, `perl(1)' in this node

The anonymous, read-only FTP server personality
***********************************************

NAME
====

   Net::FTPServer::RO::FileHandle - The anonymous, read-only FTP server
personality

SYNOPSIS
========

     use Net::FTPServer::RO::FileHandle;

DESCRIPTION
===========

METHODS
=======

$dirh = $fileh->dir;
     Return the directory which contains this file.

$fh = $fileh->open (["r"|"w"|"a"]);
     Open a file handle (derived from IO::Handle, see `IO::Handle(3)' in
     this node) in either read or write mode.

($mode, $perms, $nlink, $user, $group, $size, $time) = $handle->status;
     Return the file or directory status. The fields returned are:

          $mode     Mode        'd' = directory,
                                'f' = file,
                                and others as with
                                the file(1) -type option.
          $perms    Permissions Permissions in normal octal numeric format.
          $nlink    Link count
          $user     Username    In printable format.
          $group    Group name  In printable format.
          $size     Size        File size in bytes.
          $time     Time        Time (usually mtime) in Unix time_t format.

     In derived classes, some of this status information may well be
     synthesized, since virtual filesystems will often not contain
     information in a Unix-like format.

$rv = $handle->move ($dirh, $filename);
     Move the current file (or directory) into directory $dirh and call it
     $filename. If the operation is successful, return 0, else return -1.

     Underlying filesystems may impose limitations on moves: for example,
     it may not be possible to move a directory; it may not be possible to
     move a file to another directory; it may not be possible to move a
     file across filesystems.

$rv = $fileh->delete;
     Delete the current file. If the delete command was successful, then
     return 0, else if there was an error return -1.

$rv = $fileh->can_read;
     Return true if the current user can read the given file.

$rv = $fileh->can_write;
     Return true if the current user can overwrite the given file.

$rv = $fileh->can_append
     Return true if the current user can append to the given file.

$rv = $fileh->can_rename;
     Return true if the current user can change the name of the given file.

$rv = $fileh->can_delete;
     Return true if the current user can delete the given file.

AUTHORS
=======

   Richard Jones (rich@annexia.org).

COPYRIGHT
=========

   Copyright (C) 2000 Biblio@Tech Ltd., Unit 2-3, 50 Carnwath Road,
London, SW6 3EG, UK

SEE ALSO
========

   `Net::FTPServer(3)' in this node, `perl(1)' in this node

The anonymous read-only FTP server personality
**********************************************

NAME
====

   Net::FTPServer::RO::Server - The anonymous read-only FTP server
personality

SYNOPSIS
========

     ftpd [-d] [-v] [-p port] [-s] [-S] [-V] [-C conf_file]

DESCRIPTION
===========

   `Net::FTPServer::RO::Server' is the anonymous read-only FTP server
personality. This personality implements a complete FTP server with
similar functionality to *wu-ftpd*, except that it is not possible to
write and all logins must be anonymous.

METHODS
=======

$rv = $self->authentication_hook ($user, $pass, $user_is_anon)
     Perform login against `/etc/passwd' or the PAM database.

$self->user_login_hook ($user, $user_is_anon)
     Hook: Called just after user `$user' has successfully logged in.

$dirh = $self->root_directory_hook;
     Hook: Return an instance of Net::FTPServer::RO::DirHandle
     corresponding to the root directory.

FILES
=====

     /etc/ftpd.conf
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/DirHandle.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/FileHandle.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/Handle.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/RO/Server.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/RO/DirHandle.pm
     /usr/lib/perl5/site_perl/5.005/Net/FTPServer/RO/FileHandle.pm

AUTHORS
=======

   Richard Jones (rich@annexia.org).

COPYRIGHT
=========

   Copyright (C) 2000 Biblio@Tech Ltd., Unit 2-3, 50 Carnwath Road,
London, SW6 3EG, UK

SEE ALSO
========

   `Net::FTPServer(3)' in this node, `Authen::PAM(3)' in this node,
`Net::FTP(3)' in this node, `perl(1)' in this node, RFC 765, RFC 959, RFC
1579, RFC 2389, RFC 2428, RFC 2577, RFC 2640, Extensions to FTP Internet
Draft draft-ietf-ftpext-mlst-NN.txt.

a Perl implementation of a finger client.
*****************************************

NAME
====

   Net::Finger - a Perl implementation of a finger client.

SYNOPSIS
========

     use Net::Finger;

     # You can put the response in a scalar...
     $response = finger('corbeau@execpc.com');
     unless ($response) {
         warn "Finger problem: $Net::Finger::error";
     }

     # ...or an array.
     @lines = finger('corbeau@execpc.com', 1);

DESCRIPTION
===========

   Net::Finger is a simple, straightforward implementation of a finger
client in Perl - so simple, in fact, that writing this documentation is
almost unnecessary.

   This module has one automatically exported function, appropriately
entitled `finger()'. It takes two arguments:

   * A username or email address to finger. (Yes, it does support the
     vaguely deprecated "user@host@host" syntax.) If you need to use a port
     other than the default finger port (79), you can specify it like so:
     "username@hostname:port".

   * (Optional) A boolean value for verbosity. True == verbose output. If
     you don't give it a value, it defaults to false. Actually, whether
     this output will differ from the non-verbose version at all is up to
     the finger server.

   `finger()' is context-sensitive. If it's used in a scalar context, it
will return the server's response in one large string. If it's used in an
array context, it will return the response as a list, line by line. If an
error of some sort occurs, it returns undef and puts a string describing
the error into the package global variable `$Net::Finger::error'. If you'd
like to see some excessively verbose output describing every step
`finger()' takes while talking to the other server, put a true value in
the variable `$Net::Finger::debug'.

   Here's a sample program that implements a very tiny, stripped-down
finger(1):

     #!/usr/bin/perl -w

     use Net::Finger;
     use Getopt::Std;
     use vars qw($opt_l);

     getopts('l');
     $x = finger($ARGV[0], $opt_l);

     if ($x) {
         print $x;
     } else {
         warn "$0: error: $Net::Finger::error\n";
     }

BUGS
====

   * Doesn't yet do non-blocking requests. (FITNR. Really.)

   * Doesn't do local requests unless there's a finger server running on
     localhost.

   * Contrary to the name's implications, this module involves no
     teledildonics.

AUTHOR
======

   Dennis Taylor, <corbeau@execpc.com>

SEE ALSO
========

   perl(1), finger(1), RFC 1288.

generic sockets interface handling
**********************************

NAME
====

   Net::Gen - generic sockets interface handling

SYNOPSIS
========

     use Net::Gen;

DESCRIPTION
===========

   The `Net::Gen' module provides basic services for handling socket-based
communications.  It supports no particular protocol family directly,
however, so it is of direct use primarily to implementors of other
modules.  To this end, several housekeeping functions are provided for the
use of derived classes, as well as several inheritable methods.  The
`Net::Gen' class does inherit from IO::Handle, thus making its methods
available.  See `METHODS', see IO/Handle, for details on
those methods.  However, some of those methods are overridden, so be sure
to check the methods described below to be sure.  (In particular, the
fcntl and ioctl methods are overridden.)

   Also provided in this distribution are `Net::Inet', `Net::TCP',
`Net::TCP::Server', `Net::UDP', `Net::UNIX', and `Net::UNIX::Server',
which are layered atop `Net::Gen'.

Public Methods
--------------

   The public methods are listed alphabetically below.  Here is an
indication of their functional groupings:

Creation and setup
     new, new_from_fd, new_from_fh, init, checkparams, open, connect,
     bind, listen

Parameter manipulation
     setparams, setparam, delparams, delparam, getparams, getparam,
     param_saver

Low-level control
     unbind, condition, getsopt, getropt, setsopt, setropt, fcntl, ioctl

Medium-level control
     getsockinfo, shutdown, stopio, close

Informational
     isopen, isconnected, isbound, didlisten, fhvec, getfh, fileno

I/O
     send, sendto, put, recv, get, getline, gets, select, accept

Utility routines
     format_addr, format_local_addr, format_remote_addr

Tied filehandle support
     SEND, PRINT, PRINTF, RECV, READLINE, READ, GETC, WRITE, CLOSE, EOF,
     BINMODE, FILENO, TIEHANDLE

Tied scalar support
     FETCH, STORE, TIESCALAR

Accessors
     Any of the keys known to the getparam and setparams methods may be
     used as an *accessor* function.  See `"Known Object Parameters"' in
     this node below, and the related sections in the derived classes.
     For an example, see `"blocking"' in this node below.

   The descriptions, listed alphabetically:

accept
     Usage:

          $newobj = $obj->accept;

     Returns a new object in the same class as the given object if an
     accept() call succeeds, and undef otherwise.  If the accept() call
     succeeds, the new object is marked as being open, connected, and
     bound.  This can fail unexpectedly if the listening socket is
     non-blocking or if the object has a timeout parameter.  See the
     discussion of non-blocking sockets and timeouts in `' in this node
     below.

bind
     Usage:

          $ok = $obj->bind;

     Makes a call to the bind() builtin on the filehandle associated with
     the object.  The arguments to bind() are determined from the current
     parameters of the object.  First, if the filehandle has previously
     been bound or connected, it is closed.  Then, if it is not currently
     open, a call to the open method is made.  If all that works (which
     may be a no-op), then the following list of possible values is tried
     for the bind() builtin:  First, the srcaddrlist object parameter, if
     its value is an array reference.  The elements of the array are tried
     in order until a bind() succeeds or the list is exhausted.  Second,
     if the srcaddrlist parameter is not set to an array reference, if the
     srcaddr parameter is a non-null string, it will be used.  Finally, if
     neither srcaddrlist nor srcaddr is suitably set, the AF parameter
     will be used to construct a sockaddr structure which will be mostly
     zeroed, and the bind() will be attempted with that.  If the bind()
     fails, undef will be returned at this point.  Otherwise, a call to
     the getsockinfo method will be made, and then the value from a call
     to the isbound method will be returned.

     If all that seems too confusing, don't worry.  Most clients will
     never need to do an explicit bind call, anyway.  If you're writing a
     server or a privileged client which does need to bind to a particular
     local port or address, and you didn't understand the foregoing
     discussion, you may be in trouble.  Don't panic until you've checked
     the discussion of binding in the derived class you're using, however.

BINMODE
     Usage:

          binmode(TIEDFH);

     A no-op provided for the tied file handle support of perl 5.005_57.
     The sockets managed by this module are always set binmode() anyway.

blocking
     Usage:

          $isblocking = $obj->blocking;
          $oldblocking = $obj->blocking($newvalue);

     The blocking method is an example of an *accessor* method.  The above
     usage examples are (effectively) equivalent to the following code
     snippets, respectively:

          $isblocking = $obj->getparam('blocking');

          $oldblocking = $obj->getparam('blocking');
          $obj->setparams({blocking=>$newvalue});

     The getparam method call is skipped if the accessor method was called
     in void context.

checkparams
     Usage:

          $ok = $obj->checkparams;

     Verifies that all previous parameter assignments are valid.
     (Normally called only via the init method, rather than directly.)

close
CLOSE
     Usage:

          $ok = $obj->close;
          $ok = close(TIEDFH);

     The close method is like a call to the shutdown method followed by a
     call to the stopio method.  It is the standard way to close down an
     object.

condition
     Usage:

          $obj->condition;

     (Re-)establishes the condition of the associated filehandle after an
     open() or accept().  (In other words, the open and accept methods
     call the condition method.)  Sets the socket to be autoflushed and
     marks it binmode().  This method attempts to set the socket blocking
     or non-blocking, depending on the state of the object's blocking
     parameter.  (It may update that parameter if the socket's state
     cannot be made to match.)  No useful value is returned.

connect
     Usage:

          $ok = $obj->connect;

     Attempts to establish a connection for the object.  [Note the special
     information for re-trying connects on non-blocking sockets, later in
     this section.]

     First, if the object is currently connected or has been connected
     since the last time it was opened, its close method is called.  Then,
     if the object is not currently open, its open method is called.  If
     it's not open after that, undef is returned.  If it is open, and if
     either of its srcaddrlist or srcaddr parameters are set to indicate
     that a bind() is desired, and it is not currently bound, its bind
     method is called.  If the bind method is called and fails, undef is
     returned.  (Most of the foregoing is a no-op for simple clients, so
     don't panic.)

     Next, if the dstaddrlist object parameter is set to an array
     reference, a call to connect() is made for each element of the list
     until it succeeds or the list is exhausted.  If the dstaddrlist
     parameter is not an array reference, a single attempt is made to call
     connect() with the dstaddr object parameter.  If no connect() call
     succeeded, undef is returned.  Finally, a call is made to the
     object's getsockinfo method, and then the value from a call to its
     isconnected method is returned.

     Each of the attempts with the connect() builtin is timed out
     separately.  If there is no timeout parameter for the object, and the
     socket is blocking (which is the default), the timeout period is
     strictly at the mercy of your operating system.  If there is no
     timeout parameter and the socket is non-blocking, that's effectively
     the same as having a timeout parameter value of 0.  If there is a
     timeout parameter, the socket is made non-blocking temporarily (see
     `"param_saver"' in this node below), and the indicated timeout value
     will be used to limit the connection attempt.  An attempt is made to
     preserve any meaningful $! values when all connection attempts have
     failed.  In particular, if the timeout parameter is 0, then each
     failed connect returns without completing the processing of the
     dstaddrlist object parameter.  This is so that the re-try logic for
     connections in progress will be more useful.

     If, on entry to the connect method, the object is already marked as
     having a connection in progress (`$obj->isconnecting' returns true),
     then the connection will be re-tried with a timeout of 0 to see
     whether it has succeeded in the meanwhile.  The appropriate
     success/fail condition for that check will be returned, with no
     further processing of the dstaddrlist object parameter.

     Note that the derived classes tend to provide additional capabilities
     which make the connect method easier to use than the above
     description would indicate.

delparam
     Usage:

          $ok = $obj->delparam($keyname);

     Sugar-coated call to the delparams method.

delparams
     Usage:

          $ok = $obj->delparams(\@keynames);

     Removes the settings for the specified parameters.  Uses the
     setparams method (with undef for the values) to validate that the
     removal is allowed by the owning object.  If the invocation of
     setparams is successful, then the parameters in question are removed.
     Returns 1 if all the removals were successful, and undef otherwise.

didlisten
     Usage:

          $ok = $obj->didlisten;

     Returns true if the object's listen method has been used
     successfully, and the object is still bound.  If this method has not
     been overridden by a derived class, the value is undef on failure and
     the `$maxqueue' value used for the listen() builtin on success.

EOF
     Usage:

          $iseof = $obj->EOF();
          $iseof = eof(TIEDFH);

     Provided for tied filehandle support.  Determines whether select()
     says that a read would work immediately, and tries it if so.  If the
     read was tried and returned an eof condition, 1 is returned.  The
     return is 0 on read errors or when select() said that a read would
     block.  Note that this interferes with use of the select() built-in,
     since it has to buffer the read data if the read was successful.

fcntl
     Usage:

          $rval = $obj->fcntl($func, $value);

     Returns the result of an fcntl() call on the associated I/O stream.

fhvec
     Usage:

          $vecstring = $obj->fhvec;

     Returns a vector suitable as an argument to the 4-argument select()
     call.  This is for use in doing selects with multiple I/O streams.
     See also `"select"' in this node.

fileno
FILENO
     Usage:

          $fnum = $obj->fileno;
          $fnum = fileno(TIEDFH);

     Returns the actual file descriptor number for the underlying socket.
     See `"getfh"' in this node for some restrictions as to the safety of
     using this.

format_addr
     Usage:

          $string = $obj->format_addr($sockaddr);
          $string = format_addr Module $sockaddr;

     Returns a formatted representation of the address.  This is a method
     so that it can be overridden by derived classes.  It is used to
     implement "pretty-printing" methods for source and destination
     addresses.

format_local_addr
     Usage:

          $string = $obj->format_local_addr;

     Returns a formatted representation of the local socket address
     associated with the object.

format_remote_addr
     Usage:

          $string = $obj->format_remote_addr;

     Returns a formatted representation of the remote socket address
     associated with the object.

get
     This is just a sugar-coated way to call the recv method which will
     work with indirect-object syntax.  See `"recv"' in this node for
     details.

GETC
     Usage:

          $char = $obj->GETC;
          $char = getc(TIEDFH);

     This method uses the recv method with a $flags argument of 0 and a
     $maxlen argument of 1 to emulate the getc() builtin.  Like that
     builtin, it returns a string representing the character read when
     successful, and undef on eof or errors.  This method exists for the
     support of tied filehandles.  It's unreliable for non-blocking
     sockets.

getfh
     Usage:

          $fhandle = $obj->getfh;

     I've strongly resisted giving people direct access to the filehandle
     embedded in the object because of the problems of mixing `stdio' input
     calls and traditional socket-level I/O.  However, if you're sure you
     can keep things straight, here are the rules under which it's safe to
     use the embedded filehandle:

        * Don't use perl's own `stdio' calls.  Stick to sysread() and
          recv().

        * Don't use the object's getline method, since that stores a
          read-ahead buffer in the object which only the object's own
          get/recv and getline methods know to return to you.  (The
          object's select method knows about the buffer enough to tell you
          that a read will succeed if there's saved data, though.)
          Similarly, avoid the object's EOF method.

        * Please don't change the state of the socket behind my back.  That
          means no close(), shutdown(), connect(), bind(), or listen()
          built-ins.  Use the corresponding methods instead, or all bets
          are off.  Of course, if you're only using this module to get the
          connect() or bind() processing, and you're going to discard the
          object after you've done your I/O, then it's OK to use the
          built-ins for I/O.  Just don't expect my code to know what you
          did behind my back.

     That $fh is a glob ref, by the way, but that doesn't matter for
     calling the built-in I/O primitives.

getline
     Usage:

          $line = $obj->getline;

     This is a simulation of `scalar(<$filehandle>)' that doesn't let
     stdio confuse the get/recv method.  As such, its return value is not
     necessarily a complete line when the socket is non-blocking.

getlines
     Usage:

          @lines = $obj->getlines;

     This is a lot like `@lines = <$filehandle>', except that it doesn't
     let stdio confuse the get/recv method.  It's unreliable on
     non-blocking sockets.  It will produce a fatal (but trappable) error
     if not called in list context.  (In other words, it uses the die()
     builtin when not called in list context.)

getparam
     Usage:

          $value = $obj->getparam($key, $defval, $def_if_undef);
          $value = $obj->getparam($key, $defval);
          $value = $obj->getparam($key);

     Returns the current setting for the named parameter (in the current
     object), or the specified default value if the parameter is not in
     the object's current parameter list.  If the optional `$def_if_undef'
     parameter is true, then undefined values will be treated the same as
     non-existent keys, and thus will return the supplied default value
     (`$defval').

getparams
     Usage:

          %hash = $obj->getparams(\@keynames, $noundefs);
          %hash = $obj->getparams(\@keynames);
          $llen = $obj->getparams(\@keynames, $noundefs);
          $llen = $obj->getparams(\@keynames);

     Returns a hash as a list (not a reference) consisting of the key-value
     pairs corresponding to the specified keyname list.  Only those keys
     which exist in the current parameter list of the object will be
     returned.  If the `$noundefs' parameter is present and true, then
     existing keys with undefined values will be suppressed as with
     non-existent keys.  If called in scalar context, returns the number
     of values which would have been returned in list context.  (This is
     twice the number of key-value pairs, in case that wasn't clear.)

getropt
     Usage:

          $optsetting = $obj->getropt($level, $option);
          $optsetting = $obj->getropt($optname);

     Returns the raw value from a call to the getsockopt() builtin.  If
     both the `$level' and $option arguments are given as numbers, the
     getsockopt() call will be made even if the given socket option is not
     registered with the object.  Otherwise, the return value for
     unregistered options will be undef with the value of $! set as
     described below for the getsopt method.

gets
     Usage:

          $line = $obj->gets;

     This is a simulation of `scalar(<$filehandle>)' that doesn't let
     stdio confuse the get/recv method.  (The gets method is just an alias
     for the getline method, for partial compatibility with the POSIX
     module.)  This method is deprecated.  Use the getline method by that
     name, instead.  The gets method may disappear in a future release.

getsockinfo
     Usage:

          ($localsockaddr, $peersockaddr) = $obj->getsockinfo;
          $peersockaddr = $obj->getsockinfo;

     Attempts to determine connection parameters associated with the
     object.  If a getsockname() call on the associated filehandle
     succeeds, the srcaddr object parameter is set to that returned
     sockaddr.  If a getpeername() call on the associated filehandle
     succeeds, the dstaddr parameter is set to that returned sockaddr.  In
     scalar context, if both socket addresses were found, the
     getpeername() value is returned, otherwise undef is returned.  In
     list context, the getsockname() and getpeername() values are
     returned, unless both are undefined.

     Derived classes normally override this method with one which provides
     friendlier return information appropriate to the derived class, and
     which establishes more of the object parameters.

getsopt
     Usage:

          @optvals = $obj->getsopt($level, $option);
          @optvals = $obj->getsopt($optname);

     Returns the unpacked values from a call to the getsockopt() builtin.
     In order to do the unpacking, the socket option must have been
     registered with the object.  See the additional discussion of socket
     options in `' in this node below.

     Since registered socket options are known by name as well as by their
     level and option values, it is possible to make calls using only the
     option name.  If the name is not registered with the object, the
     return value is the same as that for `getsopt $obj -1,-1', which is
     an empty return array and $! set appropriately (should be `EINVAL').

     Examples:

          ($sotype) = $obj->getsopt('SO_TYPE');
          @malinger = $obj->getsopt(SOL_SOCKET, SO_LINGER);
          ($sodebug) = $obj->getsopt('SOL_SOCKET', 'SO_DEBUG');

init
     Usage:

          return undef unless $self->init;

     Verifies that all previous parameter assignments are valid (via
     checkparams).  Returns the incoming object on success, and undef on
     failure.  This method is normally called from the new method
     appropriate to the class of the created object.

ioctl
     Usage:

          $rval = $obj->ioctl($func, $value);

     Returns the result of an ioctl() call on the associated I/O stream.

isbound
     Usage:

          $ok = $obj->isbound;

     Returns true if the object's bind method has been used successfully,
     and the binding is still in effect.  If this method has not been
     overridden by a derived class, the value is the saved return value of
     the call to the bind() builtin (if it was called).

isconnected
     Usage:

          $ok = $obj->isconnected;

     Returns true if the object's connect method has been used
     successfully to establish a "session", and that session is still
     connected.  If this method has not been overridden by a derived
     class, the value is the saved return value of the call to the
     connect() builtin (if it was called).

isconnecting
     Usage:

          $ok = $obj->isconnecting;

     Returns true if the object's connect method has been used with a
     timeout or on a non-blocking socket, and the connect() did not
     complete.  In other words, the failure from the connect() builtin
     indicated that the operation was still in progress.  (A rejected
     connection or a connection which exceeded the operating system's
     timeout is said to have completed unsuccessfully, rather than not to
     have completed.)

isopen
     Usage:

          $ok = $obj->isopen;

     Returns true if the object currently has a socket attached to its
     associated filehandle, and false otherwise.  If this method has not
     been overridden by a derived class, the value is the saved return
     value of the call to the socket() builtin (if it was called).

listen
     Usage:

          $ok = $obj->listen($maxqueue);
          $ok = $obj->listen;

     Makes a call to the listen() builtin on the filehandle associated
     with the object.  Propagates the return value from listen().  If the
     `$maxqueue' parameter is missing, it defaults to the value of the
     object's maxqueue parameter, or the value of `SOMAXCONN'.  If the
     `SOMAXCONN' constant is not available in your configuration, the
     default value used for the listen method is 5.  This method will fail
     if the object is not bound and cannot be made bound by a simple call
     to its bind method.

new
     Usage:

          $obj = $classname->new();
          $obj = $classname->new(\%parameters);

     Returns a newly-initialised object of the given class.  If called for
     a class other than `Net::Gen', no validation of the supplied
     parameters will be performed.  (This is so that the derived class can
     add the parameter validation it needs to the object before allowing
     validation.)

new_from_fd
new_from_fh
     Usage:

          $obj = $classname->new_from_fh(*FH);
          $obj = $classname->new_from_fh(\*FH);
          $obj = $classname->new_from_fd(fileno($fh));

     Returns a newly-initialised object of the given class, open on a
     newly-dup()ed copy of the given filehandle or file descriptor.  As
     many of the standard object parameters as possible will be determined
     from the passed filehandle.  This is determined (in part) by calling
     the corresponding new, init, and getsockinfo methods for the new
     object.

     Only real filehandles or file descriptor numbers are allowed as
     arguments.  This method makes no attempt to resolve filehandle names.
     Yes, despite having two names, there's really just one method.

open
     Usage:

          $ok = $obj->open;

     Makes a call to the socket() builtin, using the current object
     parameters to determine the desired protocol family, socket type, and
     protocol number.  If the object was already open, its stopio method
     will be called before socket() is called again.  The object
     parameters consulted (and possibly updated) are PF, AF, proto, type,
     and blocking.  Returns true if the socket() call results in an open
     filehandle, undef otherwise.

param_saver
paramSaver
     Usage:

          my $savedstuff = $obj->param_saver(@param_names);
          my $savedstuff = $obj->paramSaver(@param_names);

     Saves the values (or lack thereof) for the indicated parameter names
     by wrapping them (and the original object) in an object blessed into
     an alternate package.  When this `saver' object is destroyed
     (typically because the `my' variable went out of scope), the previous
     values of the parameters for the original object will be restored.
     This allows for temporary changes to an object's parameter settings
     without the worry of whether an inopportune die() will prevent the
     restoration of the original settings.

     An example (from the connect method):

          my $saveblocking = $self->param_saver('blocking');

     (This is used when there is a timeout parameter for the object.)

print
PRINT
     See `' in this node for details, as this method is just an alias for
     the put method.  The PRINT alias is for the support of tied
     filehandles.

PRINTF
     Usage:

          $ok = $obj->PRINTF($format, @args);
          $ok = printf TIEDFH $format, @args;

     This method uses the sprintf() builtin and the PRINT method to send
     the @args values to the filehandle associated with the object, using
     the $format format string.  It exists for the support of tied
     filehandles.

put
     Usage:

          $ok = $obj->put(@whatever);
          $ok = put $obj @whatever;

     This method uses the print() builtin to send the @whatever arguments
     to the filehandle associated with the object.  That filehandle is
     always marked for autoflushing by the open method, so the method is
     in effect equivalent to this:

          $ok = $obj->send(join($, , @whatever) . $\ , 0);

     However, since multiple fwrite() calls are sometimes involved in the
     actual use of print(), this method can be more efficient than the
     above code sample for large strings in the argument list.  It's a bad
     idea except on stream sockets (`SOCK_STREAM') though, since the
     record boundaries are unpredictable through `stdio'.  It's also a bad
     idea on non-blocking sockets, since the amount of data actually
     written to the socket is unknown.  This method makes no attempt to
     trap `SIGPIPE'.

READ
     Usage:

          $numread = $obj->READ($buffer, $maxlen);
          $numread = $obj->READ($buffer, $maxlen, $offset);
          $numread = read(TIEDFH, $buffer, $maxlen);
          $numread = read(TIEDFH, $buffer, $maxlen, $offset);

     This method uses the recv method (with a flags argument of 0) to
     emulate the read() and sysread() builtins.  This is specifically for
     the support of tied filehandles.  Like the emulated builtins, this
     method returns the number of bytes successfully read, or undef on
     error.

READLINE
     Usage:

          $line = $obj->READLINE;
          @lines = $obj->READLINE;
          $line = readline(TIEDFH);	# or $line = <TIEDFH>;
          @lines = readline(TIEDFH);	# or @lines = <TIEDFH>;

     This method supports the use of the <> (or readline()) operator on
     tied filehandles.  In scalar context, it uses the getline method.  In
     list context, it reads all remaining input on the socket (until eof,
     which makes this unsuitable for connectionless socket types such as
     UDP), and splits it into lines based on the current value of the $/
     variable.  The return value is unreliable for non-blocking sockets.

RECV
     Usage:

          $from = $obj->RECV($buffer, $maxlen, $flags);
          $from = $obj->RECV($buffer, $maxlen);
          $from = $obj->RECV($buffer);

     This method calls the recv() method with the arguments and return
     rearranged to match the recv() builtin.  This is for the support of
     tied filehandles.

recv
     Usage:

          $record = $obj->recv($maxlen, $flags, $whence);
          $record = $obj->recv($maxlen, $flags);
          $record = $obj->recv($maxlen);
          $record = $obj->recv;

     This method calls the recv() builtin, and returns a buffer (if one is
     received) or undef on eof or error.  If an eof is seen on the socket
     (as checked with its ckeof method), then $!  will be 0 on return.  If
     the `$whence' argument is supplied, it will be filled in with the
     sending socket address if possible.  If the $flags argument is not
     supplied, it defaults to 0.  If the `$maxlen' argument is not
     supplied, it is defaulted to the receive buffer size of the
     associated filehandle (if known), or the preferred blocksize of the
     associated filehandle (if known, which it usually won't be), or 8192.

select
     Usage:

          ($nfound, $timeleft, $rbool, $wbool, $xbool) =
          	$obj->select($doread, $dowrite, $doxcept, $timeout);
          $nfound = $obj->select($doread, $dowrite, $doxcept, $timeout);

     Issues a 4-argument select() call for the associated I/O stream.  All
     arguments are optional.  The $timeout argument is the same as the
     fourth argument to the select() builtin.  The first three are
     booleans, used to determine whether the method should include the
     object's I/O stream in the corresponding parameter to the select()
     call.  The return in list context is the standard two values from
     select(), follwed by booleans indicating whether the actual select()
     call found reading, writing, or exception to be true.  In scalar
     context, the routine returns only the count of the number of matching
     conditions.  This is probably only useful when you're checking just
     one of the three possible conditions.

SEND
send
     Usage:

          $ok = $obj->send($buffer, $flags, $destsockaddr);
          $ok = $obj->send($buffer, $flags);
          $ok = $obj->send($buffer);

     This method calls the send() builtin (three- or four-argument form).
     The $flags parameter is defaulted to 0 if not supplied.  If the
     `$destsockaddr' value is missing or undefined, and the socket is
     connected (`$obj->isconnected' returns true), then the three-argument
     form of the send() builtin will be used.  Otherwise, the
     `$destsockaddr' parameter will be defaulted from the last recv() peer
     address for the same kind of message (depending on whether `MSG_OOB'
     is set in the $flags parameter).  A defined `$destsockaddr' will
     result in a four-argument send() call.  The return value from the
     send() builtin is returned.  This method makes no attempt to trap
     `SIGPIPE'.

sendto
     Usage:

          $ok = $obj->sendto($buffer, $destsockaddr, $flags);
          $ok = $obj->sendto($buffer, $destsockaddr);

     This method calls the send() builtin (four-argument form).  The
     $flags parameter is defaulted to 0 if not supplied.  The return value
     from the send() builtin is returned.  This method makes no attempt to
     trap `SIGPIPE'.

setparam
     Usage:

          $ok = $obj->setparam($key, $value, $newonly, $checkup);
          $ok = $obj->setparam($key, $value, $newonly);
          $ok = $obj->setparam($key, $value);

     Sets a single new parameter.  Uses the setparams method, and has the
     same rules for the handling of the `$newonly' and `$checkup'
     parameters.  Returns 1 if the set was successful, and undef otherwise.

setparams
     Usage:

          $ok = $obj->setparams(\%newparams, $newonly, $checkup);
          $ok = $obj->setparams(\%newparams, $newonly);
          $ok = $obj->setparams(\%newparams);

     Sets new parameters from the given hashref, with validation.  This is
     done in a loop over the *key, value* pairs from the `newparams'
     parameter.  The precise nature of the validation depends on the
     `$newonly' and `$checkup' parameters (which are optional), but in all
     cases the keys to be set are checked against those registered with
     the object.  If the `$newonly' parameter is negative, the value from
     the hashref will only be set if there is not already a defined value
     associated with that key, but the skipping of the setting of the
     value is silent.  If the `$newonly' parameter is not negative or if
     there is no existing defined value, if the `$checkup' parameter is
     false then the setting of the new value is skipped if the new value
     is identical to the old value.  If those checks don't cause the
     setting of a new value to be skipped, then if the `$newonly'
     parameter is positive and there is already a defined value for the
     specified key, a warning will be issued and the new value will not be
     set.

     If none of the above checks cause the setting of a new value to be
     skipped, but if the specified key has a validation routine, that
     routine will be called with the given object, the current key, and
     the proposed new value as parameters.  It is allowed for the
     validation routine to alter the new-value argument to change what
     will be set.  (This is useful when changing a hostname to be in
     canonical form, for example.)  If the validation routine returns a
     non-null string, that will be used to issue a warning, and the new
     value will not be set.  If the validation routine returns a null
     string (or if there is no validation routine), the new value will
     (finally) get set for the given key.

     The setparams method returns 1 if all parameters were successfully
     set, and undef otherwise.

setropt
     Usage:

          $ok = $obj->setropt($level, $option, $rawvalue);
          $ok = $obj->setropt($optname, $rawvalue);

     Returns the result from a call to the setsockopt() builtin.  If the
     $level and $option arguments are both given as numbers, the
     setsockopt() call will be made even if the option is not registered
     with the object.  Otherwise, unregistered options will fail as for
     the setsopt method, below.

setsopt
     Usage:

          $ok = $obj->setsopt($level, $option, @optvalues);
          $ok = $obj->setsopt($optname, @optvalues);

     Returns the result from a call to the setsockopt() builtin.  In order
     to be able to pack the `@optvalues', the option must be registered
     with the object, just as described in `' in this node above.

shutdown
     Usage:

          $ok = $obj->shutdown($how);
          $ok = $obj->shutdown;

     Calls the shutdown() builtin on the filehandle associated with the
     object.  This method is a no-op, returning 1, if the filehandle is
     not connected.  The `$how' parameter is as per the shutdown()
     builtin, which in turn should be as described in the shutdown(2)
     manpage.  If the `$how' parameter is not present, it is assumed to be
     `SHUT_RDWR' (which is 2 on most UNIX systems).

     Returns 1 if it has nothing to do, otherwise propagates the return
     from the shutdown() builtin.

stopio
     Usage:

          $ok = $obj->stopio;

     Calls the close() builtin on the filehandle associated with the
     object, unless that filehandle is already closed.  Returns 1 or the
     return value from the close() builtin.  This method is primarily for
     the use of server modules which need to avoid shutdown calls at
     inappropriate times.  This method calls the delparams method for the
     keys of srcaddr and dstaddr.

unbind
     Usage:

          $obj->unbind;

     Removes any saved binding for the object.  Unless the object is
     currently connected, this will result in a call to its close method,
     in order to ensure that any previous binding is removed.  Even if the
     object is connected, the srcaddrlist object parameter is removed (via
     the object's delparams method).  The return value from this method is
     indeterminate.

wasconnected
     Usage:

          $was = $obj->wasconnected;

     Returns true if the object has had a successful connect() completion
     since it was last opened.  Returns false after a close() or on a new
     object.  Also returns true if `$obj->isconnecting' is true.

WRITE
     Usage:

          $nwritten = $obj->WRITE($buf, $len);
          $nwritten = $obj->WRITE($buf, $len, $offset);
          $nwritten = syswrite(TIEDFH, $buf, $len);
          $nwritten = syswrite(TIEDFH, $buf, $len, $offset);

     This method exists for support of syswrite() on tied filehandles.  It
     calls the syswrite() builtin on the underlying filehandle with the
     same parameters.

Protected Methods
-----------------

   Yes, I know that Perl doesn't really have protected methods as such.
However, these are the methods which are only useful for implementing
derived classes, and not for the general user.

ckeof
     Usage:

          $wasiteof = $obj->ckeof;

     After a 0-length read in the get() routine, it calls this method to
     determine whether such a 0-length read meant EOF.  The default method
     supplied here checks for non-blocking sockets (if necessary), and for
     a `SOCK_STREAM' socket.  If EOF_NONBLOCK is true, or if the
     VAL_O_NONBLOCK flag was not set in the fcntl() flags for the socket,
     or if the error code was not VAL_EAGAIN, and the socket is of type
     `SOCK_STREAM', then this method returns true.  It returns a false
     value otherwise.  This method is overridable for classes like
     `Net::Dnet', which support `SOCK_SEQPACKET' and need to make a
     protocol-family-specific check to tell a 0-length packet from EOF.

initsockopts
     Usage:

          $classname->initsockopts($level, \%optiondesc);

     Given a prototype optiondesc hash ref, updates it to include all the
     data needed for the values it can find, and deletes the ones it
     can't.  For example, here's a single entry from such a prototype
     optiondesc:

          'SO_LINGER' => ['II'],

     Given that, and the $level of `SOL_SOCKET', and the incoming class
     name of `Net::Gen', initsockopts will attempt to evaluate `SO_LINGER'
     in package `Net::Gen', and if it succeeds it will fill out the rest
     of the information in the associated array ref, and add another key
     to the hash ref for the value of `SO_LINGER' (which is 128 on my
     system).  If it can't evaluate that psuedo-constant, it will simply
     delete that entry from the referenced hash.  Assuming a successful
     evaluation of this entry, the resulting entries would look like this:

          'SO_LINGER' => ['II', SO_LINGER+0, SOL_SOCKET+0, 2],
          SO_LINGER+0 => ['II', SO_LINGER+0, SOL_SOCKET+0, 2],

     (All right, so the expressions would be known values, but maybe you
     get the idea.)

     A completed optiondesc hash is a set of key-value pairs where the
     value is an array ref with the following elements:

          [pack template, option value, option level, pack array len]

     Such a completed optiondesc is one of the required arguments to the
     register_options method (see below).

register_options
registerOptions
     Usage:

          $obj->register_options($levelname, $level, \%optiondesc);

     This method attaches the socket options specified by the given option
     descriptions hash ref and the given level (as text and as a number)
     to the object.  The registered set of socket options is in fact a
     hashref of hashrefs, where the keys are the level names and level
     numbers, and the values are the optiondesc hash refs which get
     registered.

     Example:

          $self->register_options('SOL_SOCKET', SOL_SOCKET+0, \%sockopts);

register_param_handlers
registerParamHandlers
     Usage:

          $obj->register_param_handlers(\@keynames, \@keyhandlers);
          $obj->register_param_handlers(\%key_handler_pairs);

     This method registers the referenced keynames (if they haven't
     already been registered), and establishes the referenced keyhandlers
     as validation routines for those keynames.  Each element of the
     keyhandlers array must be a code reference.  When the setparams
     method invokes the handler, it will be called with three arguments:
     the target object, the keyname in question, and the proposed new
     value (which may be undef, especially if being called from the
     delparams method).  See the other discussion of validation routines
     in the setparams method description, above.

register_param_keys
registerParamKeys
     Usage:

          $obj->register_param_keys(\@keynames);

     This method registers the referenced keynames as valid parameters for
     setparams and the like for this object.  The new methods can store
     arbitrary parameter values, but the init method will later ensure
     that all those keys eventually got registered.  This out-of-order
     setup is allowed because of possible cross-dependencies between the
     various parameters, so they have to be set before they can be
     validated (in some cases).

_accessor
     Usage:

          $value = $obj->_accessor($what);
          $oldvalue = $obj->_accessor($what, $newvalue);

     This method implements the use of the known parameter keys as get/set
     methods.  It's used by the customised AUTOLOAD to generate such
     accessor functions as they're referenced.  See `"blocking"' in this
     node above for an example.

Known Socket Options
--------------------

   These are the socket options known to the `Net::Gen' module itself:

     `SO_ACCEPTCONN', `SO_BROADCAST', `SO_DEBUG', `SO_DONTROUTE',
     `SO_ERROR', `SO_EXPANDED_RIGHTS', `SO_FAMILY', `SO_KEEPALIVE',
     `SO_LINGER', `SO_OOBINLINE', `SO_PAIRABLE', `SO_RCVBUF',
     `SO_RCVLOWAT', `SO_RCVTIMEO', `SO_REUSEADDR', `SO_REUSEPORT',
     `SO_SNDBUF', `SO_SNDLOWAT', `SO_SNDTIMEO', `SO_STATE', `SO_TYPE',
     `SO_USELOOPBACK', `SO_XSE'

Known Object Parameters
-----------------------

   These are the object parameters registered by the `Net::Gen' module
itself:

AF
     Address family (will default from PF, and vice versa).

blocking
     Set to 0 when a socket has been marked as non-blocking, and to 1
     otherwise.  If it's undef, it'll be treated as though it were set to
     1.  The use of anything which even looks like `stdio' calls on
     non-blocking sockets as at your own risk.  If you don't know how to
     work with non-blocking sockets already, the results of trying them
     may surprise you.

dstaddr
     The result of getpeername(), or an ephemeral proposed connect()
     address.

dstaddrlist
     A reference to an array of socket addresses to try for connect().

maxqueue
     An override of the default maximum queue depth parameter for
     listen().  This will be used if the $maxqueue argument to listen() is
     not supplied.

netgen_fakeconnect
     This parameter is set true to keep the connect method from really
     calling the connect() built-in if the socket has not had an source
     address specified and it is not bound.  This is used by the
     `Net::UNIX' and `Net::UDP' modules to keep from exercising a bug in
     some socket implementations with respect to how datagram sockets are
     handled.  (This was specifically done in response to quirks of
     Solaris 2.5.1.)  Instead, the connect method simply sets the dstaddr
     object parameter, which the send method will respect.

PF
     Protocol family for this object.

proto
     The protocol to pass to the socket() call (often defaulted to 0).

reuseaddr
     A boolean, indicating whether the bind method should do a
     setsockopt() call to set `SO_REUSEADDR' to 1.

reuseport
     A boolean, indicating whether the bind method should do a
     setsockopt() call to set `SO_REUSEPORT' to 1.

srcaddr
     The result of getsockname(), or an ephemeral proposed bind() address.

srcaddrlist
     A reference to an array of socket addresses to try for bind().

timeout
     The maximum time to wait for connect() or accept() attempts to
     succeed.  See the discussion of timeouts and non-blocking sockets in
     `' in this node above.

type
     The socket type to create (`SOCK_STREAM', `SOCK_DGRAM', etc.)

Non-Method Subroutines
----------------------

pack_sockaddr
     Usage:

          $connect_address = pack_sockaddr($family, $fam_addr);

     Returns a packed `struct sockaddr' corresponding to the provided
     $family (which must be a number) and the address-family-specific
     $fam_addr (pre-packed).

unpack_sockaddr
     Usage:

          ($family, $fam_addr) = unpack_sockaddr($packed_address);

     The inverse of pack_sockaddr().

     Various socket-related errno values.  See `":errnos"' in this node
     for the list.  These routines will always be defined, but they will
     return 0 if the corresponding error symbol was not found on your
     system.

EOF_NONBLOCK
     Returns a boolean value depending on whether a read from a
     non-blocking socket can distinguish an end-of-file condition from a
     no-data-available condition.  This corresponds to the value available
     from the Config module as `$Config::Config{'d_eofnblk'}'), except
     that EOF_NONBLOCK is always defined.

RD_NODATA
     Gives the integer return value found by the Configure script for a
     read() system call on a non-blocking socket which has no data
     available.  This is similar to the string representation of the value
     available from the Config module as `$Config::Config{'rd_nodata'}'.

VAL_EAGAIN
     Gives the value of the error symbol found by the Configure script
     which is set by a non-blocking filehandle when no data is available.
     This differs from the value available from the Config module
     (`$Config::Config{'eagain'}') in that the latter is a string,
     typically `"EAGAIN"'.

VAL_O_NONBLOCK
     Gives the value found by the Configure script for setting a
     filehandle non-blocking.  The value available from the Config module
     is a string representing the value found
     (`$Config::Config{'o_nonblock'}'), whereas the value from
     VAL_O_NONBLOCK is an integer, suitable for passing to sysopen() or
     for eventual use in fcntl().

Exports
-------

default
     None.

exportable
     `AF_APPLETALK' `AF_CCITT' `AF_CHAOS' `AF_CTF' `AF_DATAKIT'
     `AF_DECnet' `AF_DLI' `AF_ECMA' `AF_HYLINK' `AF_IMPLINK' `AF_INET'
     `AF_ISO' `AF_LAST' `AF_LAT' `AF_LINK' `AF_NETMAN' `AF_NS' `AF_OSI'
     `AF_PUP' `AF_ROUTE' `AF_SNA' `AF_UNIX' `AF_UNSPEC' `AF_USER' `AF_WAN'
     `AF_X25' `EADDRINUSE' `EADDRNOTAVAIL' `EAFNOSUPPORT' `EAGAIN'
     `EALREADY' `EBADF' `EBADMSG' `ECONNABORTED' `ECONNREFUSED'
     `ECONNRESET' `EDESTADDRREQ' `EHOSTDOWN' `EHOSTUNREACH' `EINPROGRESS'
     `EINVAL' `EISCONN' `EMSGSIZE' `ENETDOWN' `ENETRESET' `ENETUNREACH'
     `ENOBUFS' `ENODATA' `ENOENT' `ENOPROTOOPT' `ENOSR' `ENOSTR'
     `ENOTCONN' `ENOTSOCK' EOF_NONBLOCK `EOPNOTSUPP' `EPFNOSUPPORT'
     `EPROTO' `EPROTONOSUPPORT' `EPROTOTYPE' `ESHUTDOWN' `ESOCKTNOSUPPORT'
     `ETIME' `ETIMEDOUT' `ETOOMANYREFS' `EWOULDBLOCK' pack_sockaddr
     `PF_APPLETALK' `PF_CCITT' `PF_CHAOS' `PF_CTF' `PF_DATAKIT'
     `PF_DECnet' `PF_DLI' `PF_ECMA' `PF_HYLINK' `PF_IMPLINK' `PF_INET'
     `PF_ISO' `PF_LAST' `PF_LAT' `PF_LINK' `PF_NETMAN' `PF_NS' `PF_OSI'
     `PF_PUP' `PF_ROUTE' `PF_SNA' `PF_UNIX' `PF_UNSPEC' `PF_USER' `PF_WAN'
     `PF_X25' RD_NODATA `SHUT_RD' `SHUT_RDWR' `SHUT_WR' `SOCK_DGRAM'
     `SOCK_RAW' `SOCK_RDM' `SOCK_SEQPACKET' `SOCK_STREAM' `SOL_SOCKET'
     `SOMAXCONN' `SO_ACCEPTCONN' `SO_BROADCAST' `SO_DEBUG' `SO_DONTROUTE'
     `SO_ERROR' `SO_EXPANDED_RIGHTS' `SO_FAMILY' `SO_KEEPALIVE'
     `SO_LINGER' `SO_OOBINLINE' `SO_PAIRABLE' `SO_RCVBUF' `SO_RCVLOWAT'
     `SO_RCVTIMEO' `SO_REUSEADDR' `SO_REUSEPORT' `SO_SNDBUF' `SO_SNDLOWAT'
     `SO_SNDTIMEO' `SO_STATE' `SO_TYPE' `SO_USELOOPBACK' `SO_XSE'
     unpack_sockaddr VAL_EAGAIN VAL_O_NONBLOCK

tags
     The following *:tags* are available for grouping exported items
     together:

    :af
          `AF_APPLETALK' `AF_CCITT' `AF_CHAOS' `AF_CTF' `AF_DATAKIT'
          `AF_DECnet' `AF_DLI' `AF_ECMA' `AF_HYLINK' `AF_IMPLINK'
          `AF_INET' `AF_ISO' `AF_LAST' `AF_LAT' `AF_LINK' `AF_NETMAN'
          `AF_NS' `AF_OSI' `AF_PUP' `AF_ROUTE' `AF_SNA' `AF_UNIX'
          `AF_UNSPEC' `AF_USER' `AF_WAN' `AF_X25'

    :errnos
          `EADDRINUSE' `EADDRNOTAVAIL' `EAFNOSUPPORT' `EAGAIN' `EALREADY'
          `EBADF' `EBADMSG' `ECONNABORTED' `ECONNREFUSED' `ECONNRESET'
          `EDESTADDRREQ' `EHOSTDOWN' `EHOSTUNREACH' `EINPROGRESS' `EINVAL'
          `EISCONN' `EMSGSIZE' `ENETDOWN' `ENETRESET' `ENETUNREACH'
          `ENOBUFS' `ENODATA' `ENOENT' `ENOPROTOOPT' `ENOSR' `ENOSTR'
          `ENOTCONN' `ENOTSOCK' `EOPNOTSUPP' `EPFNOSUPPORT' `EPROTO'
          `EPROTONOSUPPORT' `EPROTOTYPE' `ESHUTDOWN' `ESOCKTNOSUPPORT'
          `ETIME' `ETIMEDOUT' `ETOOMANYREFS' `EWOULDBLOCK'

    :families
          The union of the :af and :pf tags.

    :NonBlockVals
    :non_block_vals
          EOF_NONBLOCK RD_NODATA VAL_EAGAIN VAL_O_NONBLOCK

    :pf
          `PF_APPLETALK' `PF_CCITT' `PF_CHAOS' `PF_CTF' `PF_DATAKIT'
          `PF_DECnet' `PF_DLI' `PF_ECMA' `PF_HYLINK' `PF_IMPLINK'
          `PF_INET' `PF_ISO' `PF_LAST' `PF_LAT' `PF_LINK' `PF_NETMAN'
          `PF_NS' `PF_OSI' `PF_PUP' `PF_ROUTE' `PF_SNA' `PF_UNIX'
          `PF_UNSPEC' `PF_USER' `PF_WAN' `PF_X25'

    :routines
          pack_sockaddr unpack_sockaddr

    :shutflags
          `SHUT_RD' `SHUT_WR' `SHUT_RDWR'

    :sockopts
          `SO_ACCEPTCONN' `SO_BROADCAST' `SO_DEBUG' `SO_DONTROUTE'
          `SO_ERROR' `SO_EXPANDED_RIGHTS' `SO_FAMILY' `SO_KEEPALIVE'
          `SO_LINGER' `SO_OOBINLINE' `SO_PAIRABLE' `SO_RCVBUF'
          `SO_RCVLOWAT' `SO_RCVTIMEO' `SO_REUSEADDR' `SO_REUSEPORT'
          `SO_SNDBUF' `SO_SNDLOWAT' `SO_SNDTIMEO' `SO_STATE' `SO_TYPE'
          `SO_USELOOPBACK' `SO_XSE'

    :sockvals
          `SOL_SOCKET' `SOCK_STREAM' `SOCK_DGRAM' `SOCK_RAW' `SOCK_RDM'
          `SOCK_SEQPACKET'

    :ALL
          All of the above.

THREADING STATUS
================

   This module has been tested with threaded perls, and should be as
thread-safe as perl itself.  (As of 5.005_03 and 5.005_57, that's not all
that safe just yet.)

SEE ALSO
========

   Net::Inet(3), Net::UNIX(3), Net::Dnet(3)

AUTHOR
======

   Spider Boardman <spider@Orb.Nashua.NH.US>

Communicate with a Goofey server
********************************

NAME
====

   Net::Goofey - Communicate with a Goofey server

SYNOPSIS
========

     use Net::Goofey;

     $Goofey = Net::Goofey->new();
     $Goofey->signon();

DESCRIPTION
===========

   `Net::Goofey' is a class implementing a simple Goofey client in Perl.

CONSTRUCTOR
===========

new ( [ USERNAME [, PASSWORD [, HOST [, PORT ] ] ] ])
     This is the constructor for a new Goofey object.

     USERNAME defaults, in order, to the environment variables
     `GOOFEYUSER', USER then `LOGNAME'.

     PASSWORD defaults to the contents of the file `$HOME/.goofeypw'.

     `HOST' and `PORT' refer to the remote host to which a Goofey
     connection is required.

     The constructor returns the open socket, or undef if an error has
     been encountered.

FUNCTIONS =item signon ( );
===========================

   Register this client as the resident one.

   Send a message to a goofey user (Will clients handle their own
iteration for multi-user messages, or should we? For now I'm assuming that
they will do it.)

   Delete your last message to USERNAME, provided (of course) they haven't
read it.

   Register for goofey.

   Valid commands:    create          Register new user    sendpw
Request your existing password be emailed to you    alias <name>
Register this machine as an alias    request <name>  Request another
goofey name to alias current one

   List  that  user's  finger  information.

   List the locations and idle times of user.  If user is empty then all
users are listed, but their  idle times  are not queried: the last
obtained idle time is printed.  Users those idle times are more than 1
hour are not listed.  =cut

   sub list {    my $self = shift;    my $username = shift;

   return $self->do_message("l $username"); }

   Sets you quiet.  The server will then keep your messages until you
unquiet.  This mode lets through messages from anybody on your unquiet
alias, though.

   Sets you quiet to everybody.

   Repeats certain messages

   Sets you unquiet.

   Sets you unquiet.

   Listens for a command from the Goofey server.  If we don't already have
an open port to them, opens it.

   Returns version information.

AUTHOR
======

   Bek Oberin <bekj@netizen.com.au>

CREDITS
=======

   Kirrily Robert <skud@netizen.com.au>

COPYRIGHT
=========

   Copyright (c) 1998 Bek Oberin.  All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl extension to determine in which network group a IP belongs to.
*******************************************************************

NAME
====

   Net::GrpNetworks - Perl extension to determine in which network group a
IP belongs to.

SYNOPSIS
========

     use Net::GrpNetworks;

     $grpnet = new Net::GrpNetworks();

     $grpnet->add(group name, network block, netmask);
     $GroupName = $grpnet->find(IP);

DESCRIPTION
===========

   Net::GrpNetworks creates network groups and allows researching for
specific IPs discovering in which network group each IP belongs to.

   For example:

     use Net::GrpNetworks;

     $grpnet = new Net::GrpNetworks();

     $grpnet->add("New York", "210.210.10.0", "255.255.255.0");
     $grpnet->add("New York", "210.210.11.0", "255.255.255.0");
     $grpnet->add("New York", "210.210.12.0", "255.255.254.0");
     $grpnet->add("Rio de Janeiro", "200.255.49.128", "255.255.255.128");
     $grpnet->add("Rio de Janeiro", "200.255.50.0", "255.255.252.0");
     $grpnet->add("Rio de Janeiro", "200.255.60.0", "255.255.255.0");

     $City = $grpnet->find("200.255.60.10");  # $City will be set to "Rio de Janeiro"
     if ( $City = $grpnet->find("210.210.9.5") ) # Will be false

COPYRIGHT
=========

     Copyright (c) 1997 Andre Rodrigues Viegas. All rights reserved. This
     program is free software; you can redistribute it and/or modify it
     under the same terms as Perl itself.

AUTHOR
======

   Andre R. Viegas, andre.viegas@writeme.com.br

Create sockets that are tunnels through an HTTP 1.1 proxy
*********************************************************

NAME
====

   Net::HTTPTunnel - Create sockets that are tunnels through an HTTP 1.1
proxy

SYNOPSIS
========

   This is a module that creates sockets that are tunnels through an HTTP
1.1 proxy that supports the SSL CONNECT method.  For more information on
this method, see *"Tunneling TCP based protocols through Web proxy
servers"* by Ari Luotonen.

     use Net::HTTPTunnel;

     $ht = Net::HTTPTunnel->new( 'proxy-host' => some.host.com
                                 'proxy-port' => 80
                                 'remote-host' => other.host.com
                                 'remote-port' => 443 );

   If successful, $ht will be a socket that acts as if it is connected
directly to remote-host:remote-port because all bits will be routed
untouched through the proxy.

   The Net::HTTPTunnel constructor returns undef on an error.

NOTES
=====

   Most proxies limit CONNECT tunnels to those which have either 443 or
563 as the destination port.  If you are experiencing errors and are
trying to connect to a port other than one of those two, it is likely you
are running into such a problem.  The only way around this (assuming you
cannot control the proxy settings) is to set up a listener on the remote
machine that you can then connect to any port through.

   Unfortunately, this tunneling method only works for tcp connections.
There is no equivalent way of doing UDP connections.  However, with a bit
of ingenuity such a scheme can certainly be devised--imagine again the
scenario of a TCP listener on the other end of the tunnel.  One could wrap
the UDP packets in TCP, transport them through the tunnel, and unwrap them
at the other end with very little trouble.

   More information on the HTTP protocol and tunneling can be found in the
Luotonen paper referenced above, as well as in RFCs 1945 and 2068.

DESCRIPTION
===========

   The only member function in Net::HTTPTunnel not inherited from
IO::Socket::INET is the constructor new().  New takes the following
name-value pairs of arguments:

   'remote-host' => 'some.host.com' [required]    The system to which you
want the tunnel to connect.

   'remote-port' => 563 [required]    The port on that system.  See note
above about port number selection.

   'proxy-host' => 'some.host.com' [required]    The proxy through which
this connection will be made.

   'proxy-port' => 80 [required]    The port on the proxy to which a
connection should be made.

   'http-ver' => '1.1' [optional; default is 1.0]    The version of HTTP
reported in the CONNECT request.  There is no reason to change this unless
the proxy requires a different version.

   'proxy-user' => 'foo' [optional]    The username to use for proxy
authentication, if required.

   'proxy-pass' => 'bar' [optional]    The password for proxy
authentication, if required.

   'user-agent' => 'baz' [optional]    The user-agent string to pass along
to the HTTP proxy.  If not specified, it will not be sent.  If you are
worried about being spotted as an abberation in the server logs, perhaps
it is better to set this to something fairly tame like "Mozilla/4.0".

   If the connection is successful, a socket will be returned.  On error,
undef is returned instead.

EXAMPLES
========

   See SYNOPSIS, above.

SEE ALSO
========

   RFC 1945 -- "Hypertext Transfer Protocol - HTTP/1.0"

   RFC 2068 -- "Hypertext Transfer Protocol - HTTP/1.1"

   "Tunneling TCP based protocols through Web proxy servers" -- Ari
Luotonen.

AUTHOR
======

   Copyright (C) 2001 Riad Wahby <*rsw@mit.edu*> All rights reserved This
program is free software.  You may redistribute it and/or modify it under
the same terms as Perl itself.

HISTORY
=======

   *0.1* Initial Release

   *0.2* Fixed two bugs, one which included an additional carriage return
with proxy authorization, and one which prevented the http-ver option from
being recognized.

Perl libraries for the Hotline internet client
**********************************************

NAME
====

   Net::Hotline - Perl libraries for the Hotline internet client

SYNOPSIS
========

     use Net::Hotline;

DESCRIPTION
===========

   The Net::Hotline module simply loads Net::Hotline::Client.  For more
information on the Net::Hotline::Client module, please see its
documentation.  For more information on Hotline, see
http://www.hotlinesw.com/

AUTHOR
======

   John C. Siracusa (siracusa@mindspring.com)

COPYRIGHT
=========

   Copyright(c) 1999 by John C. Siracusa.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Perl library for the Hotline internet client
********************************************

NAME
====

   Net::Hotline::Client - Perl library for the Hotline internet client

SYNOPSIS
========

     use Net::Hotline::Client;

     $hlc = new Net::Hotline::Client;
     $hlc->connect("127.0.0.1")

     $hlc->chat_handler(\&Chat_Handler);
     $hlc->msg_handler(\&Msg_Handler);

     $hlc->login(Login    => "Steve",
                 Password => "xyzzy",
                 Nickname => "Jobs",
                 Icon     => 128);

     $hlc->run();
     ...

DESCRIPTION
===========

   Net::Hotline::Client is a class implementing a Hotline internet client
in Perl.  It was specifically developed to aid in the creation of Hotline
"bots," although it's suitable for most other tasks as well. Hotline is an
internet client/server system that's sort of a cross between IRC and a BBS.
See http://www.hotlinesw.com/ for more information.

   This document assumes you have some knowledge of the Hotline client. If
not, I suggest downloading it from the URL above.  (It's shareware. Mac and
PC versions are available)

CAVEATS
=======

   The Hotline protocol is not public. (An RFC?  I wish!)  This module got
its start with the aid of the C source code from the Unix "hx" Hotline
client written by Ryan Nielsen, the beginnings of a Java Hotline bot
written by Gary Wong, and many hours spent staring at hexdumps of network
data. Some features are still not implemented, the most notable being user
administration capabilities.  Finally, I'm sure all hell will break loose
with the next major revision of Hotline.  Such is life.

GETTING STARTED
===============

   Before delving into the nitty-gritty details, it's important to
understand the philosophy behind design of this module.  If you do not
read this section first, you will probably be confused by the rest of the
documentation. Take the time now and save yourself headaches later.

   Hotline is an event-driven protocol.  A Hotline client receives packets
each time something interesting occurs on the server-a new user joins,
someone says something in chat, someone goes idle, etc.  The client
receives these packets whether it's ready for them or not.  This type of
interaction lends itself to an event-loop/callback-routine design, which
is how this module was originally implemented.  Handler routines are set
for the events you're interested in, and then the event loop is started.

   In this model, client actions are also treated as events.  To retrieve
the news, for example, the client calls a function that sends a news
request to the server and returns a task ID number.  The client then
returns to the event loop and watches the incoming packet stream for a
packet with the same task ID (it will be either a packet containing the
news or a task error packet).  In the time between when the news request
was sent and the response is received from the server, many other
unrelated events can (and probably will) occur.

   This system works great for things like bots that want to deal with
events in a non-linear fashion, but what about when you want to do things
in a more deterministic manner?  For example, imagine trying to implement a
command line FTP-like Hotline client using the event loop model.  Sure,
it's possible, but it's not pretty!  I found this out the hard way.  What's
needed are what I'm going to call "blocking tasks."  That is, function
calls that don't return until their work is done.  In this new model, the
news request function would not merely return a task ID number, it would
return the news itself (or an error, of course).

   To accomplish this, the "blocking task" version of the news retrieval
function has to do everything that you'd do in the event loop model: send a
request for the news and watch the incoming packet stream for the task
results.  There's no magic here.  Of course, the question of what to do
with those "unrelated" packets presents itself.  They can't just be ignored
because they may be telling the client something important like "you've
just been disconnected."  On the other hand, allowing them to invoke
handler routines might spin us off into another section of the code
indefinitely.

   The solution I came up with is to let the user decide.  All unrelated
events that occur during blocking tasks are subject to the bare minimum
processing needed to keep the internal state of the client object
consistent (tracking joining and leaving users, disconnect messages, etc.).
Going further, handler routines can indeed be called.  The behavior is
controlled by the client object's attributes.

   These two modes of operation are called "event loop mode" and "blocking
task mode" in the rest of the documentation. It's important to decide which
model suits your particular needs before starting your Hotline client code.
Blindly mixing and matching these techniques will get you nowhere fast.
Now, on to the good stuff...

METHODS
=======

CONNECTING
----------

connect ADDRESS
     Opens a network connection to ADDRESS, which can be an IP address or
     hostname optionally followed by a space or a colon and a port number.
     If no port is given, it defaults to 5500 (Hotline standard port)

     Examples:

          $hlc->connect("127.0.0.1:1234");
          $hlc->connect("hostname.com 5678");

     Returns 1 if successful, undef otherwise.

disconnect
     Closes the network connection.  Returns 1 if a connection was closed,
     undef if the connection wasn't open to begin with.

login PARAMETERS
     Logs into a Hotline server opened via connect(), and requests the news
     and the userlist (unless overridden by the "NoNews" and "NoUserList"
     parameters).  Arguments are in a "named parameter" format, and are
     case-sensitive.  The parameters are:

          Nickname    Your nickname (default: guest)
          Login       Your account name (default: guest)
          Password    Your account password (default: <none>)
          Icon        Your icon number (default: 410, the big red "H")
          NoNews      If true, do not request the news.
          NoUserList  If true, do not request the userlist.

     Example of use:

          $hlc->login(Login    => "Steve",
                      Password => "xyzzy",
                      Nickname => "Jobs",
                      Icon     => 128,
                      NoNews   => 1);

     If omitted, all parameters except Password will default to some sane
     (if not necessarily "sensible") value.  The news and userlist will be
     requested unless NoNews and/or NoUserList are explicitly set by the
     user.  Keep in mind that client functions like the tracking of
     connected users will not work properly without the userlist.

     In blocking task mode, login() returns 1 on success, undef if an error
     occurred, and "zero but true" ("0E-0") if the login was successful,
     but the news and/or userlist retrieval failed.

     In event loop mode, login() returns the task number if the login
     request was sent successfully, undef otherwise.

run
     Starts the event loop.  Returns when the connection has to the server
     has been closed.

SETTINGS
--------

blocking EXPR
     Turns blocking network i/o on or off depending on how EXPR evaluates
     (true turns blocking i/o on).  Returns the current setting.  Blocking
     i/o is on by default.  In this mode, the event loop will cycle each
     time data of any kind comes from the server.  This means that your
     hotline client may spend a lot of its time blocked (and therefore
     unable to do anything interesting) waiting for something to happen on
     the server.  Using non-blocking i/o will cycle through the event loop
     more frequently (see `event_timing()' below) regardless of server
     activity.

blocking_tasks EXPR
     With no arguments, returns the blocking task status.  With one
     argument, blocking tasks will be turned on or off depending on how
     EXPR evaluates (true means blocking task mode is active).  Blocking
     tasks are off by default.

clear_error
     Clears the error message text available via `last_error()'.
     `last_error()' is not cleared by the client object, so you may need to
     explicitly clear it before running a blocking task to prevent it from
     containing an old, unrelated error message if the blocking task
     somehow failed without setting `last_error()'.  (This should not
     happen, but you never know...)

connect_timeout SECS
     Sets the connection timeout to SECS seconds (if present).  Returns
     the current connection timeout.

data_fork_extension TEXT
     Sets the data fork filename extension for downloads to TEXT (if
     present).  Returns the current data fork filename extension.  The
     default setting is ".data"

downloads_dir PATH
     Sets the directory where downloaded files are placed to PATH (if
     present).  Returns the current setting.

event_timing SECS
     Sets the event loop timing to SECS seconds (if present).  Fractional
     seconds are allowed. The default setting is 1 second.  This option
     only has an effect when non-blocking i/o is active (see
     `blocking()').  Returns the current event timing setting.

handlers_during_blocking_tasks EXPR
     Allows handlers to run during blocking tasks if EXPR is present and
     evaluates to true.  Returns the current setting.  The default setting
     is off.

path_separator CHARACTER
     Sets the path separator to CHARACTER (if present).  The default
     setting is the Mac OS path separator ":".  Returns the current value
     of the path separator.  Note that this is the path separator used
     when sending commands to the server and has no bearing on what the
     path separator is on the local system.  You should not need to change
     this, since all current Hotline servers use ":" regardless of the
     platform they're running on.

rsrc_fork_extension TEXT
     Sets the resource fork filename extension for downloads to TEXT (if
     present). Returns the current resource fork filename extension.  The
     default setting is ".rsrc"

tracker ADDR
     Sets the tracker address to ADDR (if present), where ADDR is an IP
     address or hostname, optionally followed by a colon and a port
     number.  Returns the current tracker address.

xfer_bufsize BYTES
     Sets the file transfer buffer size to BYTES.  Returns the current
     buffer size.  The default is 4096 bytes.

COMMANDS
--------

   Unless otherwise specified, the methods in this section are treated as
"tasks" by Hotline. Their status (start time, finish time, error state,
etc.) is tracked internally by task number.  In event mode, they return a
task number if the request was sent successfully, and undef or an empty
list if an error occurred.  In blocking task mode, the return values vary.

   Some commands (like `chat()' and `pchat()', for example) are not
treated as "tasks" by Hotline. They always return 1 on success, rather
than a task number.  The actual completion of a such commands can only be
determined by examining the resulting data from the server.  For example,
if you `chat("hello")', you can look for that line of chat in your chat
handler.  (This is rarely necessary since the failure of such a command
usually means that you have much bigger problems.)

ban USER
ban SOCKET
     Bans the user specified by a Net::Hotline::User object or a user
     socket number.

     In blocking task mode, returns 1 on success or undef if an error
     occurred.  In event loop mode, returns a task number if the request
     was sent successfully, or undef if an error occurred.

chat LIST
     Sends the text formed by the concatenation of LIST to the server as
     "chat."  Perl newlines ("\n") are translated to
     Net::Hotline::Constants::HTLC_NEWLINE, which is Hotline's native
     newline character.

     Not treated as a task: returns 1 on success, undef or an empty list
     on failure.

chat_action LIST
     Sends the text formed by the concatenation of LIST to the server as a
     "chat action."  Perl newlines ("\n") are translated to
     Net::Hotline::Constants::HTLC_NEWLINE, which is Hotline's native
     newline character.

     Not treated as a task: returns 1 on success, undef or an empty list
     on failure.

comment PATH, TEXT
     Sets the comments for the file or folder located at PATH to TEXT. If
     TEXT is undef or an empty string, the comments for the file or folder
     will be removed.

     In blocking task mode, returns 1 on success or undef if an error
     occurred.  In event loop mode, returns a task number if the request
     was sent successfully, or undef if an error occurred.

delete_file PATH
     Deletes the file or folder located at located at PATH.

     In blocking task mode, returns 1 on success or undef if an error
     occurred.  In event loop mode, returns a task number if the request
     was sent successfully, or undef if an error occurred.

get_file PATH
     Download the file on the server located at PATH to the local directory
     set via `downloads_dir()'.  In Mac OS, file names longer than 31
     characters are truncated, preserving the filename extension (i.e.
     ".jpg") if possible.

     In blocking task mode, returns either an array (in array context) or a
     reference to an array (in scalar context) containing a
     Net::Hotline::Task object, a download reference number, and the size
     of the download on success, an undef or an empty list if an error
     occurred.  Those return values are meant to be fed to `recv_file()'
     like this (error handling omitted):

          ($task, $ref, $size) = $hlc->get_file("Folder1:file.sit");

          $hlc->recv_file($task, $ref, $size);

     In event loop mode, returns a task number if the request was sent
     successfully, and undef or an empty list if an error occurred.

get_file_resume PATH
     Resume downloading the file on the server located at PATH to the local
     directory set via `downloads_dir()'.  The partially downloaded file(s)
     must exist in the local download directory, and (on non-Mac OS
     systems) must have filename extensions matching the current settings
     of `data_fork_extension()' and `rsrc_fork_extensions()'.

     In blocking task mode, returns either an array (in array context) or a
     reference to an array (in scalar context) containing a
     Net::Hotline::Task object, a download reference number, and the size
     of the download on success, and undef or an empty list if an error
     occurred.  Those return values are meant to be fed to `recv_file()'
     like this (error handling omitted):

          ($task, $ref, $size) = $hlc->get_file_resume("Folder1:file.sit");

          $hlc->recv_file($task, $ref, $size);

     In event loop mode, returns a task number if the request was sent
     successfully, and undef or an empty list if an error occurred.

get_fileinfo PATH
     Returns a Net::Hotline::FileInfoItem object corresponding to the file
     specified by PATH, or undef if an error occurred. Should only be used
     in blocking task mode.

get_filelist PATH
     Returns an array (in array context) or a reference to an array (in
     scalar context) of Net::Hotline::FileListItem objects corresponding
     to the contents of the server directory PATH, and the scalar value 0
     if an error occurred (in order to distinguish between an empty
     directory and an error: an empty directory will return an empty list
     in array context and undef in scalar context). Should only be used in
     blocking task mode.

get_news
     Get the news from the server.

     Returns an array containing the new posts (in array context) or the
     news as a string (in scalar context) on success, and undef if an
     error occurred.  Note that successful retrieval of an empty news file
     will return an empty string ("") or an empty list. Should only be
     used in blocking task mode.

get_userinfo SOCKET
     Returns information about the user specified by SOCKET as a string, or
     undef if there was an error.  Will not work unless the userlist has
     been retrieved from the server.  Should only be used in blocking task
     mode.

get_userlist
     Returns a reference to a hash keyed by socket number containing
     Net::Hotline::User objects for all users currently logged on. Should
     only be used in blocking task mode.

icon ICON
     Sets your icon in the userlist to ICON, where ICON is an icon ID
     number.

kick USER
kick SOCKET
     Disconnects the user specified by a Net::Hotline::User object or a
     user socket number.

     In blocking task mode, returns 1 on success or undef if an error
     occurred.  In event loop mode, returns a task number if the request
     was sent successfully, or undef if an error occurred.

macbinary MACBIN_FILE, DATA_FILE, DATA_LEN, RSRC_FILE, RSRC_LEN BUF_SIZE, TYPE, CREATOR, COMMENTS, CREATED, MODIFIED, FINDER_FLAGS
     Creates a MacBinary II file at the path designated by MACBIN_FILE
     based on the file paths and other information supplied as arguments
     (see the `recv_file()' method for a description of the other
     arguments).  If MACBIN_FILE is undefined, it defaults to DATA_FILE
     with ".bin" tacked onto the end.  It returns 1 on success, and undef
     if MACBIN_FILE already exists or can't be created, if DATA_LEN is
     greater than zero and DATA_FILE can't be opened, or if RSRC_LEN is
     greater than zero and RSRC_FILE can't be opened.  The error condition
     is available via both `last_error()' and $! because macbinary() can
     be called as a method or as a function.  Example:

          # As a method
          unless($hlc->macbinary(@args))
          {
            die "macbinary: ", $hlc->last_error();
          }

          # As a function
          unless(macbinary(@args))
          {
            die "macbinary: $!";
          }

move SRC, DEST
     Moves the file or folder located at the path SRC to the directory
     located at the path DEST.  SRC should be the full path to the file or
     folder you want to move, and DEST should be the full path to the
     directory you want to move SRC too.  The file or folder name should
     only appear in the SRC path, never in the DEST path.  As a
     consequence, renaming files or folders must be done through rename()
     and cannot be rolled into a move() call.  Here's an example of a
     valid call to move():

          $hlc->move("Folder1:file1", "Folder2:");

     This moves the "file1" from "Folder1" to "Folder2"

     In blocking task mode, returns 1 on success or undef if an error
     occurred.  In event loop mode, returns a task number if the request
     was sent successfully, or undef if an error occurred.

msg USER, LIST
msg SOCKET, LIST
     Sends the text formed by the concatenation of LIST as a private
     message to the user specified by a Net::Hotline::User object or a
     user socket number.

     In blocking task mode, returns 1 on success or undef if an error
     occurred.  In event loop mode, returns a task number if the request
     was sent successfully, or undef if an error occurred.

new_folder PATH
     Create a new folder located at PATH.

     In blocking task mode, returns 1 on success or undef if an error
     occurred.  In event loop mode, returns a task number if the request
     was sent successfully, or undef if an error occurred.

nick TEXT
     Sets your nickname in the userlist to TEXT.

pchat REF, LIST
     Sends the text formed by the concatenation of LIST to the private
     chat window specified by REF.  Perl newlines ("\n") are translated to
     Net::Hotline::Constants::HTLC_NEWLINE, which is Hotline's native
     newline character.

     Not treated as a task: returns 1 on success, undef or an empty list
     on failure.

pchat_action REF, LIST
     Sends the text formed by the concatenation of LIST to the private
     chat window specified by REF as a "chat action".  Perl newlines
     ("\n") are translated to Net::Hotline::Constants::HTLC_NEWLINE, which
     is Hotline's native newline character.

     Not treated as a task: returns 1 on success, undef or an empty list
     on failure.

pchat_accept REF
     Accepts an invitaton to the private chat sepcified by REF.

     In blocking task mode, returns 1 on success.  In event loop mode,
     returns a task number if the request was sent successfully.  In both
     modes, it returns undef or an empty list if an error occurred.

pchat_decline REF
     Declines an invitaton to the private chat sepcified by REF.

     Not treated as a task: returns 1 on success, undef or an empty list
     on failure.

pchat_invite SOCKET, REF
     Invite the user specified by SOCKET to an existing private chat
     specfied by REF, or create a new private chat if REF is not given.
     There is no `pchat_create()' command.  To create a new private chat,
     you must invite someone.  Call `pchat_invite()' with your own socket
     number and no REF argument to create a new private chat with only
     yourself in it (you will not have to explicitly accept this
     invitation).

     In blocking task mode, returns 1 on success, and undef or an empty
     list if an error occurred.

     In event mode, it returns a task number if it had to create a new
     private chat (i.e. if no REF argument was given) or 1 (if inviting to
     an existing private chat) on success, and undef or an empty list if
     an error occurred.

pchat_leave REF
     Leave the private chat specified by REF.

     Not treated as a task: returns 1 on success, undef or an empty list
     on failure.

pchat_subject REF, TEXT
     Sets the subject of the private chat specified by REF to TEXT.

     Not treated as a task: returns 1 on success, undef or an empty list
     on failure.

post_news LIST
     Sends the text formed by the concatenation of LIST to the server as a
     news post.

     In blocking task mode, returns 1 on success.  In event loop mode,
     returns a task number if the request was sent successfully.  In both
     modes, it returns undef or an empty list if an error occurred.

put_file SRC_PATH, DEST_PATH, COMMENT
     Upload the file located at SRC_PATH to the server directory
     DEST_PATH, with the file comments COMMENT.  SRC_PATH must be in the
     native path format of the local system (i.e. using ":" as the path
     separator on Mac OS, and "/" on most other OSes).  DEST_PATH must be
     in Hotline's native path format (":" as the path separator). If
     COMMENT is omitted, the actual Finder comments will be read from the
     file to be uploaded if running on Mac OS.  Otherwise, the comments
     will be blank.  `put_file()' tries to upload a new file. If you are
     resuming a file upload, you must call `send_file_resume()' instead.

     In blocking task mode, returns an array (in array context) or a
     reference to an array (in scalar context) containing a
     Net::Hotline::Task object, an upload reference number, and the size
     of the upload, and undef or an empty list if an error occurred.
     Those return values are meant to be fed to `send_file()' like this
     (error handling omitted):

          ($task, $ref, $size) = $hlc->put_file("/home/john/file.gz",
                                                "Folder1:Folder2"
                                                "A fun file!");

          $hlc->send_file($task, $ref, $size);

     In event loop mode, returns a task number if the request was sent
     successfully, and undef or an empty list if an error occurred.

put_file_resume SRC_PATH, DEST_PATH, COMMENT
     Resume uploading the file located at SRC_PATH to the server directory
     DEST_PATH, with the file comments COMMENT.  SRC_PATH must be in the
     native path format of the local system (i.e. using ":" as the path
     separator on Mac OS, and "/" on most other OSes).  DEST_PATH must be
     in Hotline's native path format (":" as the path separator). If
     COMMENT is omitted, the actual Finder comments will be read from the
     file to be uploaded if running on Mac OS. Otherwise, the comments
     will be blank.  Use `put_file()' to upload a new file.

     In blocking task mode, returns an array (in array context) or a
     reference to an array (in scalar context) containing a
     Net::Hotline::Task object, an upload reference number, the size of
     the upload, and additional information needed to resume the upload,
     and undef or an empty list if an error occurred. Those return values
     are meant to be fed to `send_file()' like this (error handling
     omitted):

          ($task, $ref, $size, $rflt) =
            $hlc->put_file_resume("/home/john/file.gz",
                                  "Folder1:Folder2"
                                  "A fun file!");

          $hlc->send_file($task, $ref, $size, $rflt);

     In event loop mode, returns a task number if the request was sent
     successfully, and undef or an empty list if an error occurred.

recv_file TASK, REF, SIZE
     Starts receiving the file designated by the Net::Hotline::Task object
     TASK, the download reference number REF, and the size in bytes SIZE
     returned by get_file() (in blocking task mode) or supplied to the
     get_file() handler routine (in event loop mode).  When the download
     is complete, `recv_file()' returns  a reference to an array
     containing the following values:

          DATA_FILE      Path to the file containing the data fork.
          DATA_LEN       Length of the data fork.
          RSRC_FILE      Path to the file containing the Mac resource fork.
          RSRC_LEN       Length of the resource fork.
          BUFSIZE        Buffer size that was used during the download.
          TYPE           Four-letter Mac file type code.
          CREATOR        Four-letter Mac file creator code.
          COMMENTS       Mac Finder comments.
          CREATED        Date created (in Mac time format)
          MODIFIED       Date modified (in Mac time format)
          FINDER_FLAGS   Mac finder flags packed in two bytes.

     which are typically fed to the `macbinary()' method to create a single
     MacBinary II file from the separate resource fork and data fork
     files. (On Mac OS systems, a single Mac OS-native two-forked file is
     created, so there's no need to call `macbinary()')  Here's an example
     of typical usage (error checking omitted):

          # Event loop mode:
          # (Inside your get_file() handler subroutine)
          ...
          $ret = $hlc->recv_file($task, $ref, $size);
          $hlc->macbinary(undef, $ret);
          ...

     or

          # Blocking task mode:
          ...
          ($task, $ref, $size) = $hlc->get_file($path);
          $ret = $hlc->recv_file($task, $ref, $size);
          $hlc->macbinary(undef, $ret)
          ...

     See `macbinary()' for more details on its usage.  If either the data
     fork or resource fork is empty, the fork length returned by
     `recv_file()' will be zero and the file path returned will be undef.

rename PATH, NAME
     Renames the file or folder located at PATH to NAME.  Note that PATH
     is the full path to the target, but NAME is just the new name without
     any path specification.  Example:

          $hlc->rename("Pets:cat", "dog");

     This changes the name of the file "cat" in the folder "Pets" to "dog"

     In blocking task mode, returns 1 on success or undef if an error
     occurred.  In event loop mode, returns a task number if the request
     was sent successfully, or undef if an error occurred.

send_file TASK, REF, SIZE, RFLT
     Starts sending the file designated by the Net::Hotline::Task object
     TASK, the upload reference number REF, the size in bytes SIZE, and
     the resume information RFLT returned by `put_file()' (in blocking
     task mode) or supplied to the `put_file()' handler routine (in event
     loop mode). Returns 1 if the upload completed successfully, or undef
     if there was an error.

tracker_list TIMEOUT
     Connects to the server set via the `tracker()' method and retrieves
     the list of servers tracked by that tracker.  Returns an array (in
     array context) or a reference to an array (in scalar context) of
     Net::Hotline::TrackerListItem objects on success, and undef or an
     empty list on failure, with the error condition available via
     `last_error()'.

     The initial connection to the tracker will timeout after TIMEOUT
     seconds, or the current value set via `connection_timeout()' if
     TIMEOUT is omitted.  A TIMEOUT value of zero will disable the timeout.

     Note that this method does not return until it has retrieved the list
     of tracked servers, and that the timeout applies *only* to the initial
     connection to the tracker.  It is often the case with overloaded
     trackers that this method will hang when writing to or reading from
     the tracker (regardless of the timeout value), many times resulting
     in a die with a broken pipe error in one of the network I/O
     functions.  To avoid this, either try a more responsive tracker
     and/or wrap your `tracker_list()' call in an eval block and check
     `$@'.

REQUESTS
--------

   All the methods in this section are treated as "tasks" by Hotline. Their
status (start time, finish time, error state, etc.) is tracked internally
by task number.  They return a task number if the request was sent
successfully, undef otherwise.

   When a tasks completes, the data is stored in the appropriate
Net::Hotline::Client attribute.  For example, when a `req_news()' task
completes, the data is available via the news() method.

req_filelist PATH
     Requests the file listing for the folder specified by PATH, or the
     root directory if PATH is omitted.

req_fileinfo PATH
     Requests the file information for the file or folder specified by
     PATH.

req_news
     Requests the news from the server.

req_userinfo SOCKET
     Requests user information for the user specified by SOCKET.

req_userlist
     Request the list of users currently logged on.

ATTRIBUTES
----------

   The methods in this section return data or references to data structures
in the Net::Hotline::Client object.  Some data structures contain
references to objects.  For details on those objects, see their respective
documentation (i.e. perldoc Net::Hotline::User)

agreement
     Returns a reference to the server's user agreement text, or undef if
     there is none.

connected
     Returns true if a network connection to a server is open.

files
     Returns a reference to a hash of arrays containing
     Net::Hotline::FileListItem objects, keyed by directory path.  Here's
     some sample code that prints the entire file tree:

          $files = $hlc->files();              # Get reference to the file tree

          foreach $directory (keys(%{$files}))
          {
            print "$directory\n";              # Ex: "Uploads:Pictures"

          foreach $file (@{$files->{$directory}})
          {
            print "\t", $file->name(), "\n"; # Ex: "Picture.jpg"
          }
              }

last_activity
     Returns the time the last packet was received from the server in the
     system's native `time()' format. (Usually seconds since the Unix
     epoch.  MacPerl is probably the only odd-ball)

last_error
     Returns a text error message detailing the last error that occurred.
     Use this method to determine the cause of failure when a blocking
     task returns undef.  Example:

          ...
          $hlc->blocking_tasks(1);
          ...
          $hlc->get_filelist("Folder1") || die $hlc->last_error();

     Don't rely on `last_error()' unless you're in blocking task mode.  In
     event loop mode, set a handler routine via `task_error_handler()' and
     deal with errors there via the task object's error() and
     `error_text()' methods.

logged_in
     Returns true if currently logged into a server.

news
     Returns a reference to an array of news posts, or undef if the news
     has not yet been requested or is empty.

pchats
     Returns a reference to a hash of Net::Hotline::PrivateChat objects,
     keyed by reference number, that represent all the private chats that
     the client is currently engaged in, or undef or an empty list if not
     in any private chats.

server
     Returns the address of the server currently connected to as a
     hostname or IP address, depending on what the actual argument to
     connect() was.  If the port connected to is anything other than the
     standard Hotline port (5500), then a colon and the port number are
     tacked onto the end of the server name.  If not connected at all,
     undef is returned.

userlist
     Returns a reference to a hash of Net::Hotline::User objects keyed by
     socket number, or undef if the userlist has not yet been received.

user_by_nick REGEX
     Returns reference(s) to user objects with nicknames matching REGEX,
     and undef or an empty list if there are no matches.  Also returns
     undef or an empty list if called before the userlist has been
     retrieved from the server. REGEX is treated as a case-sensitive
     anchored regular expression internally (i.e. `/^REGEX$/'). If your
     regex matches more than one user's nickname, and `user_by_nick()' was
     called in array context, an array of references to user objects will
     be returned. Otherwise, the first user object that matched will be
     returned (as ordered by socket number, from low to high).

user_by_socket SOCKET
     Returns the user object whose socket number is equal to SOCKET, or
     undef if there is no user at that socket.

HANDLERS
--------

   The methods in this section deal with getting and setting the handler
routines for events and tasks.  If you do not set your own handler for an
event, the default handler (usually just a print to STDOUT) will be used.
You can enable and disable the default handlers with the
`default_handlers()' method.  They are disabled by default.

default_handlers EXPR
     If EXPR is omitted, it returns the default handler setting.
     Otherwise, it sets the default handler setting to EXPR (anything that
     evaluates to true is considered "on").  Default handlers are disabled
     by default.

handlers
     Returns a reference to a hash, keyed by event type strings (the
     strings in CAPS below).  The values associated with the keys are
     either code references or undef.  Event types are as follows:

          Events:

          AGREEMENT      User agreement text received.
          CHAT           New chat appeared.
          CHAT_ACTION    A new chat "action" appeared.
          COLOR          A user changed color in the userlist.
          EVENT          Next cycle in the event loop.
          ICON           A user changed icon in the userlist.
          JOIN           A user joined the server.
          LEAVE          A user left the server.
          MSG            A private message arrived.
          NEWS           News received.
          NEWS_POSTED    A news post was made by another user.
          NICK           A user changed nickname in the userlist.
          PCHAT_CHAT     New private chat appeared.
          PCHAT_ACTION   A new private chat action appeared.
          PCHAT_INVITE   An invitation to private chat arrived.
          PCHAT_JOIN     A user joined a private chat.
          PCHAT_LEAVE    A user left a private chat.
          PCHAT_SUBJECT  Private chat subject changed.
          QUIT           The server was shutdown politely.
          SERVER_MSG     A server message arrived.

          Tasks:

          BAN            Ban user task completed.
          FILE_DELETE    A file or folder was deleted.
          FILE_GET       A file download is ready to begin.
          FILE_PUT       A file upload is ready to begin.
          FILE_GET_INFO  File information received.
          FILE_SET_INFO  File information set.
          FILE_LIST      File list received.
          FILE_MKDIR     New folder created.
          FILE_MOVE      A file or folder was moved.
          KICK           Disconnect user task completed.
          LOGIN          Login task completed.
          NEWS_POST      News post task completed.
          PCHAT_ACCEPT   You have joined a private chat.
          PCHAT_CREATE   New private chat created.
          SEND_MSG       Private message sent.
          TASK_ERROR     A task error ocurred.
          USER_GETINFO   User information received.
          USER_LIST      User list received.

SET/GET HANDLERS
----------------

   The methods in this section expect either one code reference argument,
or no arguments at all.  With one argument, the handler is set to the
given code reference.  The return value is always the current value of the
handler (should be either undef or a code reference).

   The code reference should point to a subroutine that expects at least
one argument: the Net::Hotline::Client object itself (listed as "SELF"
below).  Other arguments vary according to the event being handled. In
this section, only the varying arguments to the handler subroutine are
described.

   Also note that you don't have to do the "obvious" tasks associated with
each handler.  For example, in the "leave" handler, you don't have to
remove the user from the userlist.  That will be done for you by the
Net::Hotline::Client object.

EVENTS
------

agreement_handler CODE (SELF, TEXT)
     User agreement text received.

          TEXT        Reference to the agreement text.

chat_handler CODE (SELF, TEXT)
     New chat appeared.

          TEXT        Reference to the chat text.

chat_action_handler CODE (SELF, TEXT)
     A new chat "action" appeared.

          TEXT        Reference to the chat action text.

color_handler CODE (SELF, USER, OLD_COLOR, NEW_COLOR)
     A user changed color in the userlist.

          USER        A Net::Hotline::User object.
          OLD_COLOR   The user's previous color.
          NEW_COLOR   The user's new color.

     Valid colors:

          1    Black  Active normal user.
          2    Red    Active admin user.
          3    Gray   Inactive normal user.
          4    Pink   Inactive admin user.

     The hash `%Net::Hotline::Constants::HTLC_COLORS' contains color
     number-to-name mappings.

event_loop_handler CODE (SELF, IDLE)
     Next cycle in the event loop.  Idle events only occur when
     non-blocking i/o is active.

          IDLE        True if the event is an idle event.

icon_handler CODE (SELF, USER, OLD_ICON, NEW_ICON)
     A user changed icon in the userlist.

          USER        A Net::Hotline::User object.
          OLD_ICON    The user's previous icon number.
          NEW_ICON    The user's new icon number.

join_handler CODE (SELF, USER)
     A user joined the server.

          USER        A Net::Hotline::User object.

leave_handler CODE (SELF, USER)
     A user left the server.

          USER        A Net::Hotline::User object.

msg_handler CODE (SELF, USER, TEXT, REPLY-TO)
     A private message arrived.

          USER        Reference to the sender's Net::Hotline::User object.
          TEXT        Reference to the message text.
          REPLY-TO    Reference to the text to which this is a reply (if any)

news_posted_handler CODE (SELF, TEXT)
     A news post was made by another user.

          TEXT        Reference to the news post text.

nick_handler CODE (SELF, USER, OLD_NICK, NEW_NICK)
     A user changed nickname in the userlist.

          USER        A Net::Hotline::User object.
          OLD_NICK    The user's previous nickname.
          NEW_NICK    The user's new nickname.

pchat_action_handler (SELF, REF, TEXT)
     A new private chat action appeared.

          REF         Private chat reference number.
          TEXT        Reference to the chat action text.

pchat_chat_handler (SELF, REF, TEXT)
     New private chat appeared.

          REF         Private chat reference number.
          TEXT        Reference to the chat text.

pchat_invite_handler (SELF, REF, SOCKET, NICK)
     An invitation to private chat arrived.

          REF         Private chat reference number.
          SOCKET      Socket number of the inviting user.
          NICK        Nick of the inviting user.

pchat_join_handler (SELF, PCHAT, SOCKET)
     A user joined a private chat.

          PCHAT       A Net::Hotline::PrivateChat object.
          SOCKET      Socket number of the joining user.

pchat_leave_handler (SELF, PCHAT, SOCKET)
     A user left a private chat.

          PCHAT       A Net::Hotline::PrivateChat object.
          SOCKET      Socket number of the leaving user.

     Note that the user who left will no longer be in the private chat
     object's userlist.

pchat_subject_handler (SELF, REF, TEXT)
     Private chat subject changed.

          REF         Private chat reference number.
          TEXT        Reference to the subject text.

quit_handler CODE (SELF, TEXT)
     The server was shutdown politely.

          TEXT        Reference to shutdown message text.

server_msg_handler CODE (SELF, TEXT)
     A server message arrived.

          TEXT        Reference to the message text.

TASKS
-----

ban_handler CODE (SELF, TASK)
     Ban user task completed.

          TASK        A Net::Hotline::Task object.

delete_file_handler CODE (SELF, TASK)
     A file or folder was deleted.

          TASK        A Net::Hotline::Task object.

file_info_handler CODE (SELF, TASK, INFO)
     File information received.

          TASK        A Net::Hotline::Task object.
          INFO        A Net::Hotline::FileInfoItem object.

file_list_handler CODE (SELF, TASK)
     File list received.

          TASK        A Net::Hotline::Task object.

get_file_handler CODE (SELF, TASK, REF, SIZE)
     A file download is ready to begin.

          TASK        A Net::Hotline::Task object.
          REF         Download reference number.
          SIZE        Size of download in bytes.

     If you do not set a handler for get_file(), a default handler will be
     used regardless of your `default_handlers()' setting.  The default
     handler simply does:

          SELF->recv_file(TASK, REF, SIZE);

     which initiates the file download and does not return until the
     download has completed.  If you want to download in the background,
     call fork() (or something similar) in your handler routine.

kick_handler CODE (SELF, TASK)
     Disconnect user task completed.

          TASK        A Net::Hotline::Task object.

login_handler CODE (SELF, TASK)
     Login task completed.

          TASK        A Net::Hotline::Task object.

move_file CODE (SELF, TASK)
     A file or folder was moved.

          TASK        A Net::Hotline::Task object.

new_folder CODE (SELF, TASK)
     New folder created.

          TASK        A Net::Hotline::Task object.

news_handler CODE (SELF, TASK)
     The news has arrived and is now available via the `news()' method.

          TASK        A Net::Hotline::Task object.

pchat_accept_handler (SELF, TASK, PCHAT)
     You have joined a private chat.

          TASK        A Net::Hotline::Task object.
          PCHAT       A Net::Hotline::PrivateChat object.

pchat_create (SELF, TASK, PCHAT)
     New private chat created.

          TASK        A Net::Hotline::Task object.
          PCHAT       A Net::Hotline::PrivateChat object.

     Note that you do not have to save the private chat object yourself.
     The client object keeps track of all private chats it is currently
     engaged in (the list is accessible via the `pchats()' method),
     updates the userlists as users join and leave, and deletes the
     objects when you leave the private chat.

post_news_handler CODE (SELF, TASK)
     News post task completed.

          TASK        A Net::Hotline::Task object.

put_file_handler CODE (SELF, TASK, REF, SIZE, RFLT)
     A file upload is ready to begin.

          TASK        A Net::Hotline::Task object.
          REF         Download reference number.
          SIZE        Size of the upload in bytes.
          RFLT        Data needed to resume an upload.

     If you do not set a handler for `put_file()', a default handler will
     be used regardless of your `default_handlers()' setting.  The default
     handler simply does:

          SELF->send_file(TASK, REF, SIZE, RFLT);

     which initiates the file upload and does not return until the upload
     has completed.  If you want to upload in the background, call fork()
     (or something similar) in your handler routine.

send_msg_handler CODE (SELF, TASK)
     Private message sent.

          TASK        A Net::Hotline::Task object.

set_file_info_handler CODE (SELF, TASK)
     File information set (this includes both renaming and setting file
     comments).

          TASK        A Net::Hotline::Task object.

task_error_handler CODE (SELF, TASK)
     A task error ocurred.

          TASK        A Net::Hotline::Task object.

user_info_handler CODE (SELF, TASK)
     User information received.

          TASK        A Net::Hotline::Task object.

user_list_handler CODE (SELF, TASK)
     User list received.

          TASK        A Net::Hotline::Task object.

MISCELLANEOUS
-------------

debug EXPR
     If EXPR is omitted, returns the debugging status (off by default),
     otherwise sets debugging status to EXPR (true means debugging is on).

version
     Returns the Net::Hotline::Client version string.

TO DO
=====

   * User administration.

BUGS
====

   Please send bug reports to siracusa@mindspring.com.

AUTHOR
======

   John C. Siracusa (siracusa@mindspring.com)

COPYRIGHT
=========

   Copyright(c) 1999 by John C. Siracusa.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

File object used internally by Net::Hotline::Client
***************************************************

NAME
====

   Net::Hotline::FileInfoItem - File object used internally by
Net::Hotline::Client

SYNOPSIS
========

     use Net::Hotline::FileInfoItem;

     $file = new Net::Hotline::FileInfoItem;

     $file->name("smile");
     $file->comments("A happy file.");
     ...

DESCRIPTION
===========

   Net::Hotline::FileInfoItem is a simple class for storing and retrieving
file information,  You should never have to create your own
Net::Hotline::FileInfoItem objects when using Net::Hotline::Client.
Getting and (to a lesser extent) setting attributes is all that should be
necessary.

CONSTRUCTION
============

new
     Creates a new Net::Hotline::FileInfoItem object with all attributes
     set to undef.

METHODS
=======

   All the Net::Hotline::FileInfoItem methods are simple attribute get/set
routines.  If given an argument, they set an attribute.  In all cases, they
return the current value of the attribute.

comment TEXT
     The file comments (as seen in the Mac OS Finder).

ctime NUM
     The creation time of the file, given as a Mac OS native time value.
     Add the constant Net::Hotline::Constants::HTLC_MACOS_TO_UNIX_TIME to
     it to change it to seconds since the Unix epoch.

creator TEXT
     The file creator, given as a four-letter Mac OS creator code ("TTXT",
     "SIT!", etc.)

name TEXT
     The file name.

icon
     The file icon given as a four-letter code.

mtime NUM
     The modification time of the file, given as a Mac OS native time
     value.  Add the constant
     Net::Hotline::Constants::HTLC_MACOS_TO_UNIX_TIME to it to change it
     to seconds since the Unix epoch.

ctime NUM
     The creation time of the file, given as a Mac OS native time value.
     Add the constant Net::Hotline::Constants::HTLC_MACOS_TO_UNIX_TIME to
     it to change it to seconds since the Unix epoch.

size NUM
     The size of the file in bytes.

type TEXT
     The file type, given as a four-letter Mac OS type code ("TEXT",
     "PICT", etc.), Net::Hotline::Constants::HTLC_INFO_FOLDER_TYPE for
     folders, and Net::Hotline::Constants::HTLC_INFO_FALIAS_TYPE for
     folder aliases.

AUTHOR
======

   John C. Siracusa (siracusa@mindspring.com)

COPYRIGHT
=========

   Copyright(c) 1999 by John Siracusa.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

File object used internally by Net::Hotline::Client
***************************************************

NAME
====

   Net::Hotline::FileListItem - File object used internally by
Net::Hotline::Client

SYNOPSIS
========

     use Net::Hotline::FileListItem;

     $file = new Net::Hotline::FileListItem;

     $file->name("foo.txt");
     $file->type("TEXT");
     ...

DESCRIPTION
===========

   Net::Hotline::FileListItem is a simple class for storing and retrieving
file information,  You should never have to create your own
Net::Hotline::FileListItem objects when using Net::Hotline::Client.
Getting and (to a lesser extent) setting attributes is all that should be
necessary.

CONSTRUCTION
============

new
     Creates a new Net::Hotline::FileListItem object with all attributes
     set to undef (or zero for numeric attributes).

METHODS
=======

   All the Net::Hotline::FileListItem methods are simple attribute get/set
routines.  If given an argument, they set an attribute.  In all cases, they
return the current value of the attribute.

creator TEXT
     The file creator, given as a four-letter Mac OS creator code ("TTXT",
     "SIT!", etc.)

name TEXT
     The file name.

size NUM
     The size of the file in bytes.

type TEXT
     The file type, given as a four-letter Mac OS type code ("TEXT",
     "PICT", etc.)  or Net::Hotline::Constants::HTLC_FOLDER_TYPE for
     folders.

AUTHOR
======

   John C. Siracusa (siracusa@mindspring.com)

COPYRIGHT
=========

   Copyright(c) 1999 by John Siracusa.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Private chat object used internally by Net::Hotline::Client
***********************************************************

NAME
====

   Net::Hotline::PrivateChat - Private chat object used internally by
Net::Hotline::Client

SYNOPSIS
========

     use Net::Hotline::PrivateChat;

     $pchat = new Net::Hotline::PrivateChat;

     $pchat->subject("Issue 1: Monkey beards");
     $pchat->reference(0x313337);
     ...

DESCRIPTION
===========

   Net::Hotline::PrivateChat is a simple class for storing and retrieving
private chat information,  You should never have to create your own
Net::Hotline::PrivateChat objects when using Net::Hotline::Client.  Getting
and (to a lesser extent) setting attributes is all that should be
necessary.

CONSTRUCTION
============

new REF, USERLIST, SUBJECT
     Creates a new Net::Hotline::PrivateChat object with the reference REF,
     userlist USERLIST, and subject SUBJECT, where REF is a number,
     USERLIST is a reference to a hash of Net::Hotline::User objects keyed
     by socket number, and SUBJECT is a string.  Any missing arguments
     will be set to undef.

METHODS
=======

   All the Net::Hotline::PrivateChat methods are simple attribute get/set
routines. If given an argument, they set an attribute.  In all cases, they
return the current value of the attribute.

reference NUM
     The private chat reference number.

subject TEXT
     The subject of the private chat.

userlist HASHREF
     The list of users in the private chat.

AUTHOR
======

   John C. Siracusa (siracusa@mindspring.com)

COPYRIGHT
=========

   Copyright(c) 1999 by John Siracusa.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Task object used internally by Net::Hotline::Client
***************************************************

NAME
====

   Net::Hotline::Task - Task object used internally by Net::Hotline::Client

SYNOPSIS
========

     use Net::Hotline::Task;

     $task = new Net::Hotline::Task;

     $task->start(time());
     $task->num($num++);
     ...

DESCRIPTION
===========

   Net::Hotline::Task is a simple class for storing and retrieving task
information,  You should never have to create your own Net::Hotline::Task
objects when using Net::Hotline::Client.  Getting and (to a lesser extent)
setting attributes is all that should be necessary.

CONSTRUCTION
============

new NUM, TYPE, START, SOCKET, PATH
     With no arguments, creates a new Net::Hotline::Task object with all
     attributes set to undef. With three or four arguments (PATH is
     optional), creates a new Net::Hotline::Task object with task number
     NUM, task type TYPE, start time START, user socket number SOCKET, and
     file path PATH.

METHODS
=======

   All the Net::Hotline::Task methods are simple attribute get/set
routines.  If given an argument, they set an attribute.  In all cases, they
return the current value of the attribute.

error EXPR
     The error state of the task.  A true value means there was an error.

error_text TEXT
     The error message text.  This only applies if error() returns a true
     value.

finish TIME
     The time (in platform-native time format, i.e. seconds since the epoch
     on a Unix system) that a task completed.

num NUMBER
     The unique task number.  Task numbers increase sequentially.

path PATH
     The path information associated with a task (if any).  In situations
     where two paths may be associated with a task (a "move file" task,
     for example), a reference to an array containing the paths will be
     returned.

socket NUMBER
     The unique user socket number associated with a task (if any).

start TIME
     The time (in platform-native time format) that a task was started.

type TASK_TYPE
     The HTLC_TASK_XXX constant specifying the type of task.  These
     constants are defined in Net::Hotline::Constants, and include:

          HTLC_TASK_KICK         Disconnect a user.
          HTLC_TASK_LOGIN        Log into server.
          HTLC_TASK_NEWS         Get the news.
          HTLC_TASK_NEWS_POST    Post to news.
          HTLC_TASK_FILE_DELETE  Delete a file.
          HTLC_TASK_FILE_INFO    Get file information.
          HTLC_TASK_FILE_LIST    Get a file list.
          HTLC_TASK_FILE_MKDIR   Create a new folder.
          HTLC_TASK_FILE_MOVE    Move a file.
          HTLC_TASK_SEND_MSG     Send a private message.
          HTLC_TASK_SET_INFO     Set file information.
          HTLC_TASK_USER_INFO    Get user information.
          HTLC_TASK_USER_LIST    Get the userlist.

AUTHOR
======

   John C. Siracusa (siracusa@mindspring.com)

COPYRIGHT
=========

   Copyright(c) 1999 by John Siracusa.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

File object used internally by Net::Hotline::Client
***************************************************

NAME
====

   Net::Hotline::TrackerListItem - File object used internally by
Net::Hotline::Client

SYNOPSIS
========

     use Net::Hotline::TrackerListItem;

     $file = new Net::Hotline::TrackerListItem;

     $file->address("hotline.foo.com");
     $file->port(5500);
     ...

DESCRIPTION
===========

   Net::Hotline::TrackerListItem is a simple class for storing and
retrieving tracked server information,  You should never have to create
your own Net::Hotline::TrackerListItem objects when using
Net::Hotline::Client.  Getting and (to a lesser extent) setting attributes
is all that should be necessary.

CONSTRUCTION
============

new ADDRESS, PORT, NUM_USERS, NAME, DESCRIPTION
     With exactly five arguments, creates a new
     Net::Hotline::TrackerListItem object with all attributes set.  With
     no arguments, creates a new Net::Hotline::TrackerListItem object with
     all attributes set to undef.

METHODS
=======

   All the Net::Hotline::TrackerListItem methods are simple attribute
get/set routines.  If given an argument, they set an attribute.  In all
cases, they return the current value of the attribute.

address TEXT
     The IP address of the server.

port NUM
     The port the server is running on.

num_users NUM
     The (claimed) number of users connected to the server.

name TEXT
     The server name, as set by the server administrator (i.e. "Ambrosia
     Software" or "Myth Central")

description TEXT
     The server description, as set by the server administrator.

AUTHOR
======

   John C. Siracusa (siracusa@mindspring.com)

COPYRIGHT
=========

   Copyright(c) 1999 by John Siracusa.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

User object used internally by Net::Hotline::Client
***************************************************

NAME
====

   Net::Hotline::User - User object used internally by Net::Hotline::Client

SYNOPSIS
========

     use Net::Hotline::User;

     $user = new Net::Hotline::User;
     $user->nick("joe blow");
     $user->icon(128);

     print "Nick: ", $user->nick(), "\n";
     ...

DESCRIPTION
===========

   Net::Hotline::User is a simple class for storing and retrieving user
information,  You should never have to create your own Net::Hotline::User
objects when using Net::Hotline::Client.  Getting and setting attributes
is all that should be necessary.

CONSTRUCTION
============

new SOCKET, NICK, LOGIN, ICON, COLOR
     With no arguments, creates a new Net::Hotline::User object with all
     attributes set to undef. The other option is to supply exactly 5
     arguments as listed above.

METHODS
=======

   All the Net::Hotline::User methods are simple attribute get/set
routines.  If given an argument, they set an attribute.  In all cases, they
return the current value of the attribute.

color NUMBER
     The color of the user in the userlist.  Values are numbers from 0 to
     3. The hash HTLC_COLORS defined in Net::Hotline::Constants contains
     number to name color mappings (i.e. $HTLC_COLORS{2} is "red").
     Example:

          use Net::Hotline::Constants qw(HTLC_COLORS);
          ...
          print $user->nick(), " is ", $HTLC_COLORS{$user->color()}, "\n";

icon NUMBER
     The user's icon number.  Negative values are accepted.

info TEXT
     User information as a block of "pretty-formatted" text.

login TEXT
     The user's login name.

nick TEXT
     The user's nickname in the userlist.

socket NUMBER
     The user's unique socket number.  User's are assigned a socket number
     whenthey connect to a Hotline server.

AUTHOR
======

   John C. Siracusa (siracusa@mindspring.com)

COPYRIGHT
=========

   Copyright(c) 1999 by John Siracusa.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Object oriented interface to an fnet server.
********************************************

NAME
====

   Net::ICB - Object oriented interface to an fnet server.

SYNOPSIS
========

     use Net::ICB qw(:client);

     $obj = new Net::ICB('user' => "chatter");
     ($type, @msg) = $obj->readmsg();
     exit unless ($type eq $M_PROTO);
     ($type, @msg) = $obj->readmsg();
     exit unless ($type eq $M_LOGINOK);

     my $msg = "Hello to the group";
     $obj->sendopen($msg);

DESCRIPTION
===========

   `Net::ICB' provides an object interface to a fnet/icb style chat server.
FNET or ICB is an old chat protocol dating back to 1988.  The original
code was written in fortran on some godforsaken machine at UKY by Sean
Casey.  After the server was rewritten in C, various servers sprung up and
died over the years.  As of 1998, approximately 4 public servers run, the
most popular of which peaks at ~150 people.  See http://www.icb.net/ for
more information.

PROTOCOL
========

   The ICB protocol uses only ascii text.  Packets consist of a single byte
of size, followed by up to 254 bytes of data.  The data block contains a
leading byte describing the data type, the data itself, and a trailing
null.  Multiple fields in the data are delimited by \001.

   Turn on debugging and it'll become obvious.

CLASS METHODS
=============

new - create a new Net::ICB object.
          my $obj = Net::ICB->new( [host   => $hostname,]
                                   [port   => $port,]
                                   [user   => $username,]
                                   [nick   => $nickname,]
                                   [group  => $initialgroup,]
                                   [cmd    => $command,]
                                   [passwd => $password] );

     Constructs a new Net::ICB object.  A new object is returned on
     success, null on failure with a `carp()'ed' error message.

     If any arguments are given, then new() calls connect() to establish a
     connection to an ICB server.  Also see connect().  Any missing
     parameters are taken from the *$DEF_** variables defined in
     Net::ICB.pm.

version - return the module version number.
          my $ver = Net::ICB->version();

          print $obj->version();

     Returns the Net::ICB.pm version number.  Also available as a instance
     method.

INSTANCE METHODS
================

connect - connect to an ICB server.
          $obj->connect( [host   => $hostname,]
                         [port   => $port,]
                         [user   => $username,]
                         [nick   => $nickname,]
                         [group  => $initialgroup,]
                         [cmd    => $command,]
                         [passwd => $password] );

     Establishes a connection to an ICB server and sends a login packet.
     Any missing parameters are taken from the *$DEF_** variables defined
     in Net::ICB.pm.

     Unlike new(), connect() creates a connection even in the absence of
     arguments.  Returns null on failure, check error() for specific
     failure code.

error - return the internal error string.
          die $obj->error() unless ($obj->connect());

     Returns a string pertaining to the last error.  This string is not
     cleared between operations: check the return code first.

clearerr - clear the internal error string.
          $obj->clearerr();

     Clears the internal error string.

debug - set and return the internal debug level.
          $obj->debug(1);

          print "Debug: ", $obj->debug(), "\n";

     With an argument, debug() sets the internal debug level and returns
     the new value.  Without, the current debug level is returned.

fd - return socket file descriptor.
          fileno($obj->fd());

     Returns the socket associated with the currect connection.

sendopen - send an open message to the current group.
          $obj->sendopen($msg);

     Sends a public message to the user's current group.  Returns null on
     failure, check error() for details.

sendpriv - send a private message to a particular user.
          $obj->sendpriv($nickname, $msg);

          $obj->sendpriv("$nickname $msg");

     Sends a private message to a named user.  Returns null on failure,
     check error() for details.

sendcmd - send an arbitrary command to the server.
          $obj->sendcmd("beep", $username);

          $obj->sendcmd("g", $groupname);

     Sends an arbitrary command to the server.  Available commands vary by
     server but most provide m, w, g, name.  Try "/m server help" or
     "/s_help".  Returns null on failure, check error() for details.

EXAMPLES
========

   Alter the default variables from a client.

     use Net::ICB qw(:defaults);
     $DEF_HOST = "myhost.com";
     $DEF_GROUP = "myhost";

   Check who is on a server.

     use Net::ICB qw(:client);
     my $who = Net::ICB->new(cmd => 'w');
     	die unless $who;
     	while (my ($type, @packet) = $who->readmsg()) {
     		exit if ($type eq $M_EXIT);
         print "@packet\n";
     }

AUTHOR
======

   John M Vinopal, banshee@resort.com

Pure Perl interface to an ICQ server
************************************

NAME
====

   Net::ICQ - Pure Perl interface to an ICQ server

SYNOPSIS
========

     use Net::ICQ;

     $icq = Net::ICQ->new($uin, $password);
     $icq->connect();

     $icq->add_handler('SRV_SYS_DELIVERED_MESS', \&on_msg);

     $params = {
       'type'         => 1,
       'text'         => 'Hello world',
       'receiver_uin' => 1234
     };
     $icq->send_event('CMD_SEND_MESSAGE', $params);

     $icq->start();

DESCRIPTION
===========

   `Net::ICQ' is a class implementing an ICQ client interface in pure Perl.

CONSTRUCTOR
===========

   * new (uin, password [, server [, port]])

     Creates a new Net::ICQ object.  A Net::ICQ object represents a single
     user logged into a specific ICQ server.  The UIN and password to use
     are specified as the first two parameters.  Server and port are
     optional, and default to 'icq.mirabilis.com' and '4000', respectively.

     Also, environment variables will be checked as follows:

          uin      - ICQ_UIN
          password - ICQ_PASS
          server   - ICQ_SERVER
          port     - ICQ_PORT

     Constructor parameters have the highest priority, then environment
     variables.  The built-in defaults (for server and port only) have the
     lowest priority.

     If either a UIN or password is not provided either directly or
     through environment variables, new() will return undef.

     Note that after calling new() you must next call connect() before you
     can send and receive ICQ events.

METHODS
=======

   All of the following methods are instance methods; you must call them
on a Net::ICQ object (for example, $icq->start).

   * connect

     Connects the Net::ICQ object to the server.

   * disconnect

     Disconnects the Net::ICQ object from the server.

   * connected

     Returns true if the Net::ICQ object is connected to the server, and
     false if it is not.

   * start

     If you're writing a fairly simple application that doesn't need to
     interface with other event-loop-based libraries, you can just call
     start() to begin communicating with the server.

     Note that start() will not return until the Net::ICQ object is
     disconnected from the server, either by the server itself or by your
     event-handler code calling disconnect().

   * do_one_loop

     If you don't want to (or can't) call the start() method, you must
     continuously call do_one_loop when your Net::ICQ object is connected
     to the server.  It uses select() to wait for data from the server and
     other ICQ clients, so it won't use CPU power even if you call it in a
     tight loop.  If you need to do other processing, you could call
     do_one_loop as infrequently as once every few seconds.

     This method does one processing loop, which involves looking for
     incoming data from the network, calling registered event handlers,
     sending acknowledgements for received packets, transmitting outgoing
     data over the network, and sending keepalives to the server to tell
     it that we are still online.  If it is not called often enough, you
     will not be notified of incoming events in a timely fashion, or the
     server might even think you have disconnected and start to ignore you.

   * add_handler(command_number, handler_ref)

     Sets the handler function for a specific ICQ server event.
     command_number specifies the event to handle.  You may use either the
     numeric code or the corresponding string code.  See the SERVER EVENTS
     section below for the numeric and string codes for all the events,
     along with descriptions of each event's function and purpose.
     handler_ref is a code ref for the sub that you want to handle the
     event.  See the HANDLERS section for how a handler works and what it
     needs to do.

   * send_event(command_number, params)

     Sends an event to the server.  command_number specifies the event to
     be sent.  You may use either the numeric code or the corresponding
     string code.  See the CLIENT EVENTS section below for the numeric and
     string codes for all the events, along with descriptions of each
     event's function and purpose.  params is a reference to a hash
     containing the parameters for the event.  See the CLIENT EVENTS
     section for an explanation of the correct parameters for each event.

CLIENT EVENTS
=============

   Client events are the messages an ICQ client, i.e. your code, sends to
the server.  They represent things such as a logon request, a message to
another user, or a user search request.  They are sometimes called
'commands' because they represent the 'commands' that an ICQ client can
execute.

   When you ask Net::ICQ to send an event with send_event() (described
above), you need to provide 2 things: the event name, and the parameters.

Event name
----------

   The event name is the first parameter to send_event(), and it specifies
which event you are sending.  You may either specify the string code or
the numeric code.  The section CLIENT EVENT LIST below describes all the
events and gives the codes for each.  For example: when sending a text
message to a user, you may give the event name as either the string
'CMD_SEND_MESSAGE' or the number 270.

   The hash `%Net::ICQ::cmd_codes' maps string codes to numeric codes.
`keys(%Net::ICQ::cmd_codes)' will produce a list of all the string codes.

Parameters
----------

   The parameters list is the second parameter to send_event(), and it
specifies the data for the event.  Every event has its own parameter list,
but the general idea is the same.  The parameters list is stored as a
hashref, where the hash contains a key for each parameter.  Almost all the
events utilize a regular 1-level hash where the values are plain scalars,
but a few events do require 2-level hash.  The CLIENT EVENT LIST section
lists the parameters for every client event.

   For example: to send a normal text message with the text 'Hello world'
to UIN 1234, the parameters would look like this:

     {
       'type'         => 1,
       'text'         => 'Hello world',
       'receiver_uin' => 1234
     }

A complete example
------------------

   Here is the complete code using send_event() to send the message 'Hello
world' to UIN 1234:

     $params = {
       'type'         => 1,
       'text'         => 'Hello world',
       'receiver_uin' => 1234
     };
     $icq->send_event('CMD_SEND_MESSAGE', $params);

A client interface to IMAP (Internet Message Access Protocol).
**************************************************************

NAME
====

   Net::IMAP - A client interface to IMAP (Internet Message Access
Protocol).

   *WARNING: This code is in alpha release.  Expect the interface to
change release to release.*

SYNOPSIS
========

   `use Net::IMAP;'

DESCRIPTION
===========

   `Net::IMAP' provides a perl interface to the client portion of IMAP
(Internet Message Access Protocol).

   *add more meat - describe overall design (commands, responses,
callbacks, convenience routines*

METHODS
=======

new $host, %options
-------------------

   Creates a new `Net::IMAP' object, connects to $host on port 143,
performs some preliminary setup of the session, and returns a reference to
the object.

   Once connected, it processes the connection banner sent by the server.
If the considers the session to be preauthenticated, new notes the fact,
allowing commands to be issued without logging in.

   The method also issues a capability command, and notes the result.  If
the server does support IMAP4rev1, the method closes the connection and
returns undef.

   The client will use non-synchronizing literals if the server supports
the `LITERAL+' extension (RFC2088) and the `NonSyncLits' options is set to
1.

   The following `Net::xAP' options are relevant to `Net::IMAP':

`Synchronous => 1'
`NonSyncLits => 0'
`Debug => 0'
`InternetDraft => 0'
   `Net::IMAP' also understands the following options, specific to the
module:

`EOL => 'lf''
     Controls what style of end-of-line processing to presented to the
     end-programmer.  The default, `'lf'', assumes that the programemr
     wants to fling messages terminated with bare LFs when invoking append,
     and when fetching messages.  In this case, the module will map to/from
     CRLF accordingly.

     If `EOL' is set to `'crlf'', the assumption is that the programmer
     wants messages, or portions of messages, to be terminated with CRLF.
     It also assumes the programmer is providing messages terminated with
     the string when invoking the append method, and will not provide an
     EOL mapping.

IMAP COMMAND METHODS
====================

   There are numerous commands in the IMAP protocol.  Each of these are
mapped to a corresponding method in the `Net::IMAP' module.

   Some commands can only be issued in certain protocol states.  Some
commands alter the state of the session.  These facts are indicated in the
documentation for the individual command methods.

   The following list enumerates the protocol states:

Non-authenticated
     The client has not authenticated with the server.  Most commands are
     unavailable in this state.

Authenticated
     The client has authenticated with the server.

Selected
     The client has opened a mailbox on the server.

noop
----

   Sends a noop command to the server.  It is valid in any protocol state.

   This method is useful for placating the auto-logout god, or for
triggering pending unsolicited responses from the server.

capability
----------

   The capability method retrieves the capabilities the IMAP server
supports.  This method is valid in any protocol state.

   The server sends a capability response back to the client.

   If the response does not indicate support for the `LITERAL+' extension,
the `NonSyncLits' option is forced off.

logout
------

   Logs off of the server.  This method is valid in any protocol state.

login $user, $password
----------------------

   Logs into the server using a simple plaintext password.  This method is
only valid when the protocol is in the non-authenticated state.

   If the server supports RFC2221 (IMAP4 Login Referrals), the completion
response could include a referral.  See RFC2221 for further information
about login referrals.

   If successful, the session state is changed to *authenticated*.

authenticate $authtype, @authinfo
---------------------------------

   Logs into the server using the authentication mechanism specified in
`$authtype'.  This method is only valid when the protocol is in the
non-authenticated state.

   The IMAP authenticate command is the same as that documented in RFC2222
(Simple Authentication and Security Layer (SASL)), despite the fact that
IMAP predates SASL.

   If successful, the session state is changed to *authenticated*.

   The following authentication mechanisms are currently supported:

`'login''
     This is a variation on the simple login technique, except that the
     information is transmitted in Base64.  This does not provide any
     additional security, but does allow clients to use authenticate.

`'cram-md5''
     This implements the authentication mechanism defined in RFC2195
     (IMAP/POP AUTHorize Extension for Simple Challenge/Response).  It uses
     keyed MD5 to avoid sending the password over the wire.

`'anonymous''
     This implements the authentication mechanism defined in RFC2245
     (Anonymous SASL Mechanism).  Anonymous IMAP access is intended to
     provide access to public mailboxes or newsgroups.

   The method returns undef is `$authtype' specifies an unsupported
mechanism or if the server does not advertise support for the mechanism.
The `has_authtype' method can be used to see whether the server supports a
particular authentication mechanism.

   In general, if the server supports a mechanism supported by
`Net::IMAP', the authenticate command should be used instead of the login
method.

select $mailbox
---------------

   Opens the specified mailbox with the intention of performing reading
and writing.  This method is valid only when the session is in the
authenticated or selected states.

   If successful, the server sends several responses: flags, exists,
`resent', as well as ok responses containing a `unseen', permanentflags,
uidnext, and uidvalidity codes.  If also changes the session state to
*selected*.

   If server returns a no response containing a newname response code,
this means `$mailbox' does not exist but the server thinks this is because
the folder was renamed.  In this case, try specifiying the new folder name
provided with the newname response code.

examine $mailbox
----------------

   Opens the specified mailbox in read-only mode.  This method is valid
only when the session is in the authenticated or selected states.

create $mailbox [, $partition]
------------------------------

   Creates the specified mailbox.  This method is valid only when the
session is in the authenticated or selected states.

   The optional `$partition' argument is only valid with the Cyrus IMAP
daemon.  Refer to the section 'Specifying Partitions with "create"' the
`doc/overview' file for that package for further information.  This
feature can only be used by administrators creating new mailboxes.  Other
servers will probably reject the command if this argument is used.  The
results are undefined if another server accepts a second argument.

delete $mailbox
---------------

   Deletes the specified mailbox.  Returns undef if `$mailbox' is the
currently open mailbox.  This method is valid only when the session is in
the authenticated or selected states.

rename $oldmailboxname, $newmailboxname [, $partition]
------------------------------------------------------

   Renames the mailbox specified in `$oldmailbox' to the name specified in
`$newmailbox'.  This method is valid only when the session is in the
authenticated or selected states.

   The optional `$partition' argument is only valid with the Cyrus IMAP
daemon.  Refer to the section 'Specifying Partitions with "rename"' the
`doc/overview' file for that package for further information.  This
feature can only be used by administrators.  Other servers will probably
reject the command if this argument is used.  The results are undefined if
another server accepts a third argument.

subscribe $mailbox
------------------

   Subscribe to the specified `$mailbox'.  Subscribing in IMAP is
subscribing in Usenet News, except that the server maintains the
subscription list.  This method is valid only when the session is in the
authenticated or selected states.

unsubscribe $mailbox
--------------------

   Unsubscribe from the specified `$mailbox'.  This method is valid only
when the session is in the authenticated or selected states.

list $referencename, $mailbox_pattern
-------------------------------------

   Send an IMAP list command to the server.  This method is valid only
when the session is in the authenticated or selected states.

   Although IMAP folders do not need to be implemented as directories,
think of an IMAP reference name as a parameter given to a cd or chdir
command, prior to checking for folders matching `$mailbox_pattern'.

   The `$mailbox_pattern' parameter allows a couple wildcard characters to
list subsets of the mailboxes on the server.

   * Matches zero or more characters at the specified location.

   * % Like *, matches zero or more characters at the specified location,
     but does not match hierarchy delimiter characters.

     If the last character in `$mailbox_pattern' is a %, matching levels
     of hierarchy are also returned.  In other words: subfolders.

   This method will fail, returning undef, if `$mailbox_pattern' is *.
This behavior is not built into the IMAP protocol; it is wired into
`Net::IMAP'.  Doing otherwise could be rude to both the client and server
machines.  If you want to know why, imagine doing `list('#news.', '*')' on
a machine with a full news feed.  The % character should be used to build
up a folder tree incrementally.

   If successful, the server sends a series of list responses.

   Please note that the `$referencename' is an IMAPism, not a Perl
reference.  Also note that the wildcards usable in `$mailbox_pattern' are
specific to IMAP.  Perl regexps are not usable here.

lsub $referencename, $mailbox_pattern
-------------------------------------

   Sends an IMAP `lsub' command to the server.  The `lsub' command is
similar to the list command, except that the server only returns
subscribed mailboxes.  This method is valid only when the session is in
the authenticated or selected states.

   The parameters are the same as those for the list method.

   If successful, the server sends a series of `lsub' responses.

status $mailbox, @statusattrs
-----------------------------

   Retrieves status information for the specified `$mailbox'.  This method
is valid only when the session is in the authenticated or selected states.

   Per RFC2060, the `@statusattrs' can contain any of the following
strings:

   * messages

     The number of messages in the mailbox.

   * recent

     The number of messages with the `\recent' flag set.

   * uidnext

     The UID expected to be assigned to the next mailbox appended to the
     mailbox.  This requires some explanation.  Rather than using this
     value for prefetching the next UID, it should be used to detect
     whether messages have been added to the mailbox.  The value will not
     change until messages are appended to the mailbox.

   * uidvalidity

     The unique identifier validity value of the mailbox.

   * unseen

     The number of messages without the `\seen' flag set.

   This method will fail, returning undef if `$mailbox' is the currently
open mailbox.

   If successful, the server sends one or more status responses.

   The status operation can be rather expensive on some folder
implementations, so clients should use this method sparingly.

append $mailbox, $message [, Flags => $flaglistref] [, Date => $date]
---------------------------------------------------------------------

   Appends the email message specified in `$message' to the mailbox
specified in `$mailbox'.  This method is valid only when the session is in
the authenticated or selected states.

   In general, the email message should be a real RFC822 message, although
exceptions such as draft messages are reasonable in some situations.  Also
note that the line terminators in `$message' need to be CRLF.

   The Flags option allows a set of flags to be specified for the message
when it is appended.  Servers are not required to honor this, but most, if
not all, do so.

   The Date option forces the internaldate to the specified value.  If
`$date' is a string, the format of the string is `dd-mmm-yyyy hh:mm:ss
[-+]zzzz', where dd is the day of the month (starting from 1), `mmm' is
the three-character abbreviation for the month name, `yyyy' is the 4-digit
year, `hh' is the hour, mm is the minutes, ss is the seconds, and
`[-+]zzzz' is the numeric timezone offset.  This happens to be the same
format returned by the `internaldate' item from the fetch command.  If
`$date' is a list reference, it is expected to contain two elements: a
time integer and a timezone offset string.  The timezone string is
expected to be formatted as `[-+]zzzz'.  These two values will be used to
synthesize a string in the format expected by the IMAP server.  As with
the Flags options, servers are not required to honor the Date option, but
most, if not all, do so.

   Note that the options are specified at the end of the list of method
arguments.  This is due to the fact that it is possible to have a
`$mailbox' named Flags or Date.  Processing the options at the end of the
argument list simplifies argument processing.  The order of the arguments
will be changed if enough people complain.

   If server returns a no response containing a `trycreate' response code,
this means `$mailbox' does not exist but the server thinks the command
would have succeeded if the an appropriate create command was issued.  On
the other hand, failure with no `trycreate' response code generally means
that a create should not be attempted.

check
-----

   Ask the server to perform a checkpoint of its data.  This method is
valid only when the session is in the selected state.

   While not always needed, this should be called if the client issues a
large quantity of updates to a folder in an extended session.

close
-----

   Close the current mailbox.  This method is valid only when the session
is in the selected state.

   If successful, the session state is changed to *authenticated*.

expunge
-------

   Delete messages marked for deletion.  This method is valid only when
the session is in the selected state.

   If successful, the server sends a series of expunge responses.

   It will return undef is the mailbox is marked read-only.

search [Charset => $charset,] @searchkeys
-----------------------------------------

   Searches the mailbox for messages matching the criteria contained in
`@searchkeys'.  This method is valid only when the session is in the
selected state.

   The `@searchkeys' list contains strings matching the format described
in Section 6.4.4 of RFC2060.

   If successful, the server send zero or more search responses.  Lack of
a search response means the server found no matches.  Note that the server
can send the results of one search in multiple responses.

fetch $msgset, 'all'|'full'|'fast'|$fetchattr|@fetchattrs
---------------------------------------------------------

   Retrieves data about a set of messages.  This method is valid only when
the session is in the selected state.

   The `$msgset' parameter identifies the set of messages from which to
retrieve the items of interest.  The notation accepted is similar to that
found in `.newsrc' files, except that : is used to specify ranges, instead
of -.  Thus, to specify messages 1, 2, 3, 5, 7, 8, 9, the following string
could be used: `'1:3,5,7:9''.  The character * can be used to indicate the
highest message number in the mailbox.  Thus, to specify the last 4
messages in an 8-message mailbox, you can use `'5-*''.

   The following list enumerates the items that can be retrieved with
fetch.  Refer to Section 6.4.5 of RFC2060 for a description of each of
these items.

   * body[$section]<$partial>

   * body.peek[$section]<$partial>

     Important: the response item returned for a `body.peek' is body.

   * bodystructure

   * body

   * envelope

   * flags

   * internaldate

   * rfc822

   * rfc822.header

   * rfc822.size

   * rfc822.text

   * uid

   Please note that the items returning messages, or portion of messages,
return strings terminated with CRLF.

   RFC2060 also defines several items that are actually macros for other
sets of items:

   * all

     A macro equivalent to `('flags', 'internaldate', 'rfc822.size',
     'envelope')'.

   * full

     A macro equivalent to `('flags', 'rfc822.size', 'envelope', 'body')'.

   * fast

     A macro equivalent to `('flags', 'internaldate', 'rfc822.size')'.

   The all, `full', and fast items are not intended to be used with other
items.

   If successful, the server responses with one or more fetch responses.

   If the completion response from a fetch command is no, the client
should send a noop command, to force any pending expunge responses from
the server, and retry the fetch command with `$msgset' adjusted
accordingly.

store $msgset, $itemname, @storeattrflags
-----------------------------------------

   Sets various attributes for the messages identified in `$msgset'.  This
method is valid only when the session is in the selected state.

   The `$msgset' parameter is described in the section describing fetch.

   The `$itemname' can be one of the following:

   * flags

     Replaces the current flags with the flags specified in
     `@storeattrflags'.

   * +flags

     Adds the flags specified in `@storeattrflags' to the current flags.

   * -flags

     Removes the flags specified in `@storeattrflags' from the current
     flags.

   The `$itemname' can also have `.silent' appended, which causes the
server to not send back update responses for the messages.

   If successful, and `.silent' is used used in `$itemname', the server
response with a series of fetch responses reflecting the updates to the
specified messages.

   If the completion response from a store command is no, the client
should send a noop command, to force any pending expunge responses from
the server, and retry the store command with `$msgset' adjusted
accordingly.

   The `@storeattrflags' is a list of flag strings.

copy $msgset, $mailbox
----------------------

   Copy the messages `$msgset' to the specified mailbox.  This method is
valid only when the session is in the selected state.

   The `$msgset' parameter is described in the section describing fetch.

   If server returns a no response containing a `trycreate' response code,
this means `$mailbox' does not exist but the server thinks the command
would have succeeded if the an appropriate create command was issued.  On
the other hand, failure with no `trycreate' response code generally means
that a create should not be attempted.

uid_copy $msgset, $mailbox
--------------------------

   A variant of copy that uses UIDs in `$msgset', instead of message
numbers.  This method is valid only when the session is in the selected
state.

uid_fetch $msgset, 'all'|'full'|'fast'|$fetchattr|@fetchattrs
-------------------------------------------------------------

   A variant of fetch that uses UIDs, instead of message numbers, in
`$msgset' and fetch responses.  This method is valid only when the session
is in the selected state.

uid_search [Charset => $charset,] @searchkeys
---------------------------------------------

   A variant of search that uses UIDs, instead of message numbers, in
`$msgset' and search responses.  This method is valid only when the
session is in the selected state.

uid_store $msgset, $itemname, @storeattrflags
---------------------------------------------

   A variant of store that uses UIDs, instead of message numbers, in
`$msgset' and fetch responses.  This method is valid only when the session
is in the selected state.

CONVENIENCE ROUTINES
====================

   In addition to the core protocol methods, `Net::IMAP' provides several
methods for accessing various pieces of information.

is_preauth
----------

   Returns a boolean valud indicating whether the IMAP session is
preauthenticated.

banner
------

   Returns the banner string issued by the server at connect time.

capabilities
------------

   Returns the list of capabilities supported by the server, minus the
authentication capabilities.  The list is not guaranteed to be in any
specific order.

has_capability $capname
-----------------------

   Returns a boolean value indicating whether the server supports the
specified capability.

authtypes
---------

   Returns a list of authentication types supported by the server.

has_authtype $authname
----------------------

   Returns a boolean value indicating whether the server supports the
specified authentication type.

qty_messages
------------

   Returns the quantity of messages in the currently selected folder.

qty_recent
----------

   Returns the quantity of recent messages in the currently selected
folder.

first_unseen
------------

   Returns the message number of the first unseen messages in the
currently selected folder.

uidvalidity
-----------

   Returns the uidvalidity value for the currently selected folder.  This
is useful for IMAP clients that cache data in persistent storage.  Cache
data for a mailbox should only be considered valid if the uidvalidity is
the same for both cached data and the remote mailbox.  See Section 2.3.1.1
of RFC2060 for further details.

uidnext
-------

   Returns the uidnext value for the currently selected folder.

permanentflags
--------------

   Returns the list of permanent flags the server has identified for the
currently open mailbox.

   If a `\*' flag is present, the server allows new persistent keywords to
be created.

is_permanentflag $flag
----------------------

   Returns a boolean value indicating whether the server considers $flag
to be a permanent flag.

flags
-----

   Returns a list of the flags associated with the mailbox.

has_flag $flag
--------------

   Returns a boolean value indicating whether the given $flag is defined
for the mailbox.

mailbox
-------

   Returns the name of the currently open mailbox.  Returns undef if no
mailbox is currently open.

is_readonly
-----------

   Returns a boolean value indicating whether the currently open mailbox
is read-only.

The following methods are available if the server advertises support for RFC2342 (IMAP4 Namespace).  Refer to that RFC for additional information.
**************************************************************************************************************************************************

NAMESPACE EXTENSION
===================

   The following methods are available if the server advertises support
for RFC2342 (IMAP4 Namespace).  Refer to that RFC for additional
information.

namespace
---------

   Sends a namespace command to the server, if the server advertises
support for the extension extension.

ACCESS CONTROL EXTENSION
========================

   The following methods are available if the server advertises support
for RFC2086 (IMAP4 ACL Extension).  Refer to that RFC for additional
information.

setacl $mailbox, $identifier, $modrights
----------------------------------------

   Sets the access control list for $identifier on `$mailbox' according to
the rights contained in `$modrights'.

   The $identifier typically identifies an account name, but can also
specify abstract entities, such as groups.

   The format for `$modrights' is documented in RFC2086.

getacl $mailbox
---------------

   Retrieves the access control list for `$mailbox'.

deleteacl $mailbox, $identifier
-------------------------------

   Deletes all access control list entries for $identifier from `$mailbox'.

listrights $mailbox, $identifier
--------------------------------

   List the rights available to $identifier for `$mailbox'.

myrights $mailbox
-----------------

   List the rights the current user has for `$mailbox'.

QUOTA EXTENSION
===============

   The following methods are available if the server advertises support
for RFC2087 (IMAP4 Quota Extension).  Refer to that RFC for additional
information.

getquota $quotaroot
-------------------

   Lists the resource usage and limits for `$quotaroot'.

setquota $quotaroot, @setquotalist
----------------------------------

   Sets the resource limits for `$quotaroot' to `@setquotalist'.

   Valid values for `@setquotalist' are server-dependant.

getquotaroot $mailbox
---------------------

   Lists the quota roots for `$mailbox'.

UIDPLUS EXTENSION
=================

   The following method is available if the server advertises support for
RFC2359 (IMAP4 UIDPLUS Extension).  Refer to that RFC for additional
information.

uid_expunge $msgset
-------------------

   A variant of expunge that allows the operation to be narrowed to the
messages with UIDs specified in `$msgset'.

   The `$msgset' parameter is described in the section describing fetch.

CALLBACKS
=========

   Many of the command methods result in the server sending back response
data.  `Net::IMAP' processes each response by parsing the data, packages
it in an appropriate object, and optionally calls a programmer-defined
callback for the response.  This callback mechanism is how programmers get
access to the data retrieved from the server.

set_untagged_callback $item, $coderef
-------------------------------------

   Assigns a programmer-defined code reference to the associated untagged
response.  When an untagged response matching $item is received,
`$coderef' is called, with the IMAP object and the associated response
object passed as parameters.

   The default callback for the ok, `bye', `bad', and no untagged
responses includes code to output the text from alert responses to stderr,
using carp.  If you set your own callback for these responses, be sure to
code handle alert codes.  Per Section 7.1 of RFC2060, clients are required
to clearly display alert messages to users.

RESPONSE OBJECTS
================

   As mention in the previous section, responses are parsed and packaged
into response objects, which are then passed to callbacks.  Each type of
response has a corresponding object class.  This section describes the
various response objects provided.

   All of the class names itemized below are prefixed with `Net::IMAP'.

   As a general rule, IMAP `nil' items are set to undef in the parsed
data, and IMAP parenthetical lists are converted to list references (of
one form or another).  In addition, atoms, quoted strings, and literals
are presented as Perl strings.

   The condition responses (ok, no, `bad', `bye', and `preauth') can
include a response code.  Refer to Section 7.1 in RFC2060 for a
description of each of the standard response codes.

Response
========

   This is the object class for completion responses.

is_tagged
---------

   Returns a boolean value indicating whether the response is tagged.  In
the case of tagged completion responses, this value is always 1.

has_trycreate
-------------

   Returns a boolean value indicating whether the `TRYCREATE' response
code is present in the response.  This can be used after a failed append
or copy command to determine whether the server thinks the operation would
succeed if a create was issued for the associated mailbox.

UntaggedResponse
================

   This class is common to all untagged server responses.

tag
---

   Returns a string containing the tag associated with the response.  In
the case of untagged responses, this is always *.

is_tagged
---------

   Returns a boolean value indicating whether the response is tagged.
Obviously, in the case of untagged responses, this value is always 0.

parent
------

   Returns a reference to the parent IMAP object.

Ok
==

   This is a container for untagged ok responses from the server.

code
----

   Returns a list reference containing response code elements in the
response.  Returns undef if no response code is present.

name
----

   Returns the name of the response.  In the case of Ok, this returns
'ok'.  This method is provided as a convenience for end-programmers
wanting to write one common subroutine for one or more of the responses
Ok, No, Bad, and Bye.

No
==

   This is a container for untagged no responses from the server.

Bad
===

   This is a container for untagged `bad' responses from the server.

Bye
===

   This is a container for untagged `bye' responses from the server.

Expunge
=======

   This is a container for expunge responses from the server.

   The information returned by qty_messages is automatically updated when
expunge responses are received.

msgnum
------

   Returns the message number specified in the expunge response.

Capability
==========

   This is a container for capability responses.

capabilities
------------

   Returns the list of capabilities supported by the server, minus the
authentication capabilities.  The list is not guaranteed to be in any
specific order.

has_capability $capname
-----------------------

   Returns a boolean value indicating whether the server supports the
specified capability.

authtypes
---------

   Returns a list of authentication types supported by the server.

has_authtype $authname
----------------------

   Returns a boolean value indicating whether the server supports the
specified authentication type.

List
====

   This is a container for list responses.

mailbox
-------

   Returns the name of the mailbox contained in the object.

delimiter
---------

   Returns the hierarchy delimiter associated with the mailbox.

flags
-----

   Returns a list of the flags associated with the mailbox.

has_flag $flag
--------------

   Returns a boolean value indicating whether the given $flag is defined
for the mailbox.

List
====

   This is a container for `lsub' responses.  It provides the same
interface as the `Net::IMAP::List' class.

Fetch
=====

   This is a container for fetch responses.

   Responses for partial fetches bear special mention.  While both the
starting byte and quantity of bytes are specified when doing partial
fetches with the fetch command, the corresponding response will only show
the starting byte.  In other words, the command `$imap->fetch(1,
'body[]<0.1024>'' will, if successful, result in a fetch response item of
`body[]<0>' containing a 1024 octet value.  To match a given response for
a partial fetch, you might need to use length to match it up with the
corresponding item specified in the fetch command.

msgnum
------

   Returns the message number identified in the response.

items
-----

   Returns the list of data item names contained in the response.  The
list is not guaranteed to be in any specific order.

item $item
----------

   Returns the data associated with the specified data item.

   The following list enumerates the data types associated with each fetch
item:

envelope
     Net::IMAP::Envelope

bodystructure
     Net::IMAP::BodyStructure

body
     Net::IMAP::BodyStructure

flags
     Net::IMAP::Flags

UID
     Integer

rfc822.size
     Integer

default
     String

Status
======

   This is a container for status responses.

mailbox
-------

   Returns a string containing the mailbox the status information is
associated with.

items
-----

   Returns the list of status items contains in the status response.

item $item
----------

   Returns the value of the $item status item.

Search
======

   This is a container for search responses.

msgnums
-------

   Returns the list of message numbers contained in the response.

Flags
=====

   This is a container for flags responses.

flags
-----

   Returns the list of flags contained in the response.

has_flag $flag
--------------

   Returns a boolean value indicating whether the specified flag is
contained in the response.

   As a convenience, the information from the flags response is also
stored in the parent `Net::IMAP' object, and is available via `Net::IMAP'
versions of the flags and `has_flags' methods.

Exists
======

   This is a container for exists responses.

exists
------

   Returns the quantity of messages in the currently selected mailbox.

   This is information is also available in the qty_messages method in the
`Net::IMAP' class.

Recent
======

   This is a container for recent responses.

recent
------

   Returns the number of messages with the `\recent' flag set.

   This information is also available in the qty_recent method in the
`Net::IMAP' class.

Namespace
=========

   This is a container for namespace responses.

personal [$namespace]
---------------------

   With no argument specified, returns a list of personal namespaces.  If
$namespace is specified, returns the delimiter character for the specific
personal namespace.

other_users [$namespace]
------------------------

   With no argument specified, returns a list of other users' namespaces.
If $namespace is specified, returns the delimiter character for the
specific other users' namespace.

shared [$namespace]
-------------------

   With no argument specified, returns a list of shared namespaces.  If
$namespace is specified, returns the delimiter character for the specific
shared namespace.

ACL
===

   This is a container for `acl' responses>

mailbox
-------

   Returns the name of the mailbox associated with the given ACL data.

identifiers
-----------

   Returns a list of identifiers contained in the ACL data.

identifier $identifier
----------------------

Listrights
==========

   This is a container for `listrights' responses.

mailbox
-------

   Returns the name of the mailbox associated with the given rights.

identifier
----------

   Returns a string containing the identifier associated with the rights.

rights
------

   Returns a string containing the rights contained in the response.

Myrights
========

   This is a container for `myrights' responses>

mailbox
-------

   Returns the name of the mailbox associated with the given rights.

rights
------

   Returns a string containing the rights contained in the response.

Quota
=====

   This is a container for `quota' responses.

quotaroot
---------

   Returns a string containing the name of the quota root in the response.

quotas
------

   Returns a list of the quotas contained in the response.

usage $quota
------------

   Returns the usage value associated with the given `$quota'.  Returns
undef is the given `$quota' is not present in the response.

limit $quota
------------

   Returns the usage limit associated with the given `$quota'.  Returns
undef is the given `$quota' is not present in the response.

Quotaroot
=========

   This is a container for quotaroot responses.

mailbox
-------

   Returns the name of the mailbox associated with the quotaroot data.

quotaroots
----------

   If called in an array context, returns the list of quotaroots
associated with the mailbox.  If called in a scalar context, returns a
list reference.

MISC FETCH OBJECTS
==================

   A fetch response can be relatively complicated.  This section documents
various classes and methods associated with the various pieces of
information available in fetch responses.

BodyStructure
=============

   This is a container for bodystructure items in fetch responses.

type
----

   Returns a string containing the MIME type of the message.  This is the
left-hand portion of a MIME media type.  For example, the type of
`text/plain' is text.

subtype
-------

   Returns a string containing the MIME subtype of the message.  This is
the right-hand portion of a MIME media type.  For example, the subtype of
`text/plain' is `plain'.

parameters
----------

   Returns a reference to a hash containing the key/value attribute pairs
in the `Content-Type' field.

   If, for example, the `Content-Type' field was:

     Content-Type: text/plain; charset=us-ascii

   The hash would contain one entry the a key of charset, and a value of
`us-ascii'.  The key is always forced to be lowercase, but the case of the
value is retained from the server.

disposition
-----------

   Returns the disposition type in the `Content-Disposition' field.
Returns undef if no such field exists.

disp_parameters
---------------

   Returns a reference to a hash containing the key/value attributer pairs
in the `Content-Disposition' field.  A reference to an empty hash is
returned if no such field exists, or if there are no parameters in the
field.

language
--------

   Returns a reference to a list of the language tags present in the
`Content-Language' field.  Returns a reference to an empty hash if no such
field is present.

Multipart
=========

   This is a container for C<BodyStructure objects that are multipart
entities.

parts
-----

   Returns a list reference of the body parts contained in the multipart
entity.

Bodypart
========

   This is a container for singlepart entities in BodyStructure and
Multipart objects.

id
--

   Return a string containing the contents of the `Content-ID' field, if
one is present, otherwise returns undef.

description
-----------

   Return a string containing the contents of the `Content-Description'
field, if one is present, otherwise returns undef.

encoding
--------

   Returns a string containing the contents of the
`Content-Transfer-Encoding' field.  Returns undef if no such field is in
the entity.

size
----

   Returns the number of octets in the entity.

lines
-----

   If the MIME content type is `message/rfc822' or the major type is text,
returns the number of lines in the entity, else returns undef.

envelope
--------

   If the MIME content type is `message/rfc822, returns a
C<Net::IMAP::Envelope' object, otherwise returns undef.

bodystructure
-------------

   If the MIME content type is `message/rfc822, returns a
C<Net::IMAP::BodyStructure' object, otherwise returns undef.

md5
---

   Returns a string containing the contents of the `Content-MD5' field.
Returns undef if no such field is in the entity.

Envelope
========

   This is a container for envelope data in fetch responses.

   For those familiar with SMTP, this is not the same type envelope.
Rather, it is a composite structure containing key source, destination,
and reference information in the message.  When retrieved from the server,
it is populated into a `Net::IMAP::Envelope' object.  The following
methods are available.

date
----

   Returns a string with the contents of the Date field.

subject
-------

   Returns a string with the contents of the Subject field.

from
----

   Returns a list reference of `Net::IMAP::Addr' objects with the contents
of the From field.

sender
------

   Returns a list reference of `Net::IMAP::Addr' objects with the contents
of the `Sender' field.  If no `Sender' field is present in the message,
the server will default it to the contents of the From field.

reply_to
--------

   Returns a list reference of `Net::IMAP::Addr' objects with the contents
of the `Reply-To' field.  If no `Reply-To' field is present in the
message, the server will default it to the contents of the From field.

to
--

   Returns a list reference of `Net::IMAP::Addr' objects with the contents
of the Tofield.  Will return undef if no To field exists in the message.

cc
--

   Returns a list reference of `Net::IMAP::Addr' objects with the contents
of the Cc field.  Will return undef if no Cc field exists in the message.

bcc
---

   Returns a list reference of `Net::IMAP::Addr' objects with the contents
of the Bcc field.  Will return undef if no Bcc field exists in the message.

in_reply_to
-----------

   Returns a string with the contents of the `In-Reply-To' field.  Returns
undef if no such field is present in the message.

message_id
----------

   Returns a string with the contents of the Date field.  Returns undef if
no such field is present in the message.

Addr
====

   This is a container for address structures in Envelope objects.

phrase
------

   Returns a string containing the phrase portion of the address, or undef
if no phrase is present.

route
-----

   Returns a string containing the route portion of the address, or undef
if no route information is present.

localpart
---------

   Returns a string containing the localpart portion of the address, or
undef if no localpart is present.

domain
------

   Returns a string containing the domain portion of the address, or undef
if no domain is present.

as_string
---------

   Returns a string representation of the contents of the object.

CAVEATS
=======

   Minimal testing has been done against the various IMAP server
implementations.  Refer to BUGS for known bugs/malfeatures.

AUTHOR
======

   Kevin Johnson <`kjj@pobox.com'>

COPYRIGHT
=========

   Copyright (c) 1997-1999 Kevin Johnson <kjj@pobox.com>.

   All rights reserved. This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

Perl extension for simple IMAP account handling, mostly  compatible with Net::POP3.
***********************************************************************************

NAME
====

   Net::IMAP::Simple - Perl extension for simple IMAP account handling,
mostly compatible with Net::POP3.

SYNOPSIS
========

     use Net::IMAP::Simple;

     # open a connection to the IMAP server
     $server = new Net::IMAP::Simple( 'someserver' );

     # login
     $server->login( 'someuser', 'somepassword' );

     # select the desired folder
     $number_of_messages = $server->select( 'somefolder' );

     # go through all the messages in the selected folder
     foreach $msg ( 1..$number_of_messages ) {

     if ( $server->seen( $msg ) {
         print "This message has been read before...\n"
     }

     # get the message, returned as a reference to an array of lines
     $lines = $server->get( $msg );

     # print it
     print @$lines;

     # get the message, returned as a temporary file handle
     $fh = $server->getfh( $msg );
     print <$fh>;
     close $fh;

     }

     # the list of all folders
     @folders = $server->mailboxes();

     # create a folder
     $server->create_mailbox( 'newfolder' );

     # rename a folder
     $server->rename_mailbox( 'newfolder', 'renamedfolder' );

     # delete a folder
     $server->delete_mailbox( 'renamedfolder' );

     # copy a message to another folder
     $server->copy( $self, $msg, 'renamedfolder' );

     # close the connection
     $server->quit();

DESCRIPTION
===========

   This module is a simple way to access IMAP accounts. The API is mostly
equivalent to the Net::POP3 one, with some aditional methods for mailbox
handling.

BUGS
====

   I don't know how the module reacts to nested mailboxes.

   This module was only tested under the following servers:

   * Netscape IMAP4rev1 Service 3.6

   * MS Exchange 5.5.1960.6 IMAPrev1 (Thanks to Edward Chao)

   * Cyrus IMAP Server v1.5.19 (Thanks to Edward Chao)

   Expect some problems with servers from other vendors (then again, if
all of them are implementing the IMAP protocol, it should work - but we
all know how it goes).

AUTHOR
======

   Joao Fonseca, joao_g_fonseca@yahoo.com

SEE ALSO
========

   Net::IMAP(1), Net::POP3(1).

COPYRIGHT
=========

   Copyright (c) 1999 Joao Fonseca. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Perl extension for manipulating IPv4/IPv6 addresses
***************************************************

NAME
====

   IP - Perl extension for manipulating IPv4/IPv6 addresses

SYNOPSIS
========

     use Net::IP;

     my $ip = new IP ('193.0.1/24') or die (Net::IP::Error());
     print ("IP  : ".$ip->ip()."\n");
     print ("Sho : ".$ip->short()."\n");
     print ("Bin : ".$ip->binip()."\n");
     print ("Int : ".$ip->intip()."\n");
     print ("Mask: ".$ip->mask()."\n");
     print ("Last: ".$ip->last_ip()."\n");
     print ("Len : ".$ip->prefixlen()."\n");
     print ("Size: ".$ip->size()."\n");
     print ("Type: ".$ip->iptype()."\n");
     print ("Rev:  ".$ip->reverse_ip()."\n");

DESCRIPTION
===========

   This module provides functions to deal with *IPv4/IPv6* addresses. The
module can be used as a class, allowing the user to instantiate IP
objects, which can be single IP addresses, prefixes, or ranges of
addresses. There is also a procedural way of accessing most of the
functions. Most subroutines can take either *IPv4* or *IPv6* addresses
transparently.

OBJECT-ORIENTED INTERFACE
=========================

Object Creation
---------------

   A Net::IP object can be created from a single IP address:

   $ip = new Net::IP ('193.0.1.46') || die ...

   Or from a Classless Prefix (a /24 prefix is equivalent to a C class):

     $ip = new Net::IP ('195.114.80/24') || die ...

   Or from a range of addresses:

     $ip = new Net::IP ('20.34.101.207 - 201.3.9.99') || die ...

     The new() function accepts IPv4 and IPv6 addresses:

     $ip = new Net::IP ('dead:beef::/32') || die ...

   Optionnaly, the function can be passed the version of the IP.
Otherwise, it tries to guess what the version is (see *_is_ipv4()* and
*_is_ipv6()*).

     $ip = new IP ('195/8',4); # Class A

OBJECT METHODS
==============

   Most of these methods are front-ends for the real functions, which use a
procedural interface. Most functions return undef on failure, and a true
value on success. A detailed description of the procedural interface is
provided below.

set
---

   Set an IP address in an existing IP object. This method has the same
functionality as the new() method, except that it reuses an existing
object to store the new IP.

   `$ip->set('130.23.1/24',4);'

   Like new(), set() takes two arguments - a string used to build an IP
address, prefix, or range, and optionally, the IP version of the
considered address.

   It returns an IP object on success, and undef on failure.

error
-----

   Return the current object error string. The error string is set
whenever one of the methods produces an error. Also, a global, class-wide
*Error()* function is avaliable.

   `warn ($ip->error());'

errno
-----

   Return the current object error number. The error number is set
whenever one of the methods produces an error. Also, a global $ERRNO
variable is set when an error is produced.

   `warn ($ip->errno());'

ip
--

   Return the IP address (or first IP of the prefix or range) in quad
format, as a string.

   `print ($ip->ip());'

binip
-----

   Return the IP address as a binary string of 0s and 1s.

   `print ($ip->binip());'

prefixlen
---------

   Return the length in bits of the current prefix.

   `print ($ip->prefixlen());'

version
-------

   Return the version of the current IP object (4 or 6).

   `print ($ip->version());'

size
----

   Return the number of IP addresses in the current prefix or range.  Use
of this function requires Math::BigInt.

   `print ($ip->size());'

binmask
-------

   Return the binary mask of the current prefix, if applicable.

   `print ($ip->binmask());'

mask
----

   Return the mask in quad format of the current prefix.

   `print ($ip->mask());'

prefix
------

   Return the full prefix (ip+prefix length) in quad (standard) format.

   `print ($ip->prefix());'

intip
-----

   Convert the IP in integer format and return it as a Math::BigInt object.

   `print ($ip->intip());'

short
-----

   Return the IP in short format: IPv4 addresses are unchanged, but IPv6
addresses can be written in the '::' format (ex: ab32:f000::).

   `print ($ip->short());'

iptype
------

   Return the IP Type - this describes the type of an IP (Public, Private,
Reserved, etc.)

   `print ($ip->iptype());'

reverse_ip
----------

   Return the reverse IP for a given IP address (in.addr. format).

   `print ($ip->reserve_ip());'

last_bin
--------

   Return the last IP of a prefix/range in binary format.

   `print ($ip->last_bin());'

last_ip
-------

   Return the last IP of a prefix/range in quad format.

   `print ($ip->last_ip());'

find_prefixes
-------------

   This function finds all the prefixes that can be found between the two
addresses of a range. The function returns a list of prefixes.

   `@list = $ip->find_prefixes($other_ip));'

bincomp
-------

   Binary comparaison of two IP objects. The function takes an operation
and an IP object as arguments. It returns a boolean value.

   The operation can be one of: lt: less than (smaller than) lte: smaller
or equal to gt: greater than gte: greater or equal to

   `if ($ip->bincomp('lt',$ip2) {...}'

binadd
------

   Binary addition of two IP objects. The value returned is an IP object.

   `my $sum = $ip->binadd($ip2);'

aggregate
---------

   Aggregate 2 IPs - Append one range/prefix of IPs to another. The last
address of the first range must be the one immediately preceding the first
address of the second range. A new IP object is returned.

   `my $total = $ip->aggregate($ip2);'

overlaps
--------

   Check if two IP ranges/prefixes overlap each other. The value returned
by the function should be one of:      0  no overlap      1  ranges overlap
   -1  range2 is included in range1     -2  range1 is included in range2
undef  problem

   `if ($ip->overlaps($ip2)==1) {...};'

PROCEDURAL INTERFACE
====================

   These functions do the real work in the module. Like the OO methods,
most of these return undef on failure. In order to access error codes and
strings, instead of using $ip->error() and $ip->errno(), use the global
functions `Error()' and `Errno()'.

   The functions of the procedural interface are not exported by default.
In order to import these functions, you need to modify the use statement
for the module:

   `use Net::IP qw(:PROC);'

Error
-----

   Returns the error string corresponding to the last error generated in
the module. This is also useful for the OO interface, as if the new()
function fails, we cannot call $ip->error() and so we have to use Error().

   warn Error();

Errno
-----

   Returns a numeric error code corresponding to the error string returned
by Error.

ip_iptobin
----------

   Transform an IP address into a bit string.

     Params  : IP address, IP version
     Returns : binary IP string on success, undef otherwise

   `$binip = ip_iptobin ($ip,6);'

ip_bintoip
----------

   Transform a bit string into an IP address

     Params  : binary IP, IP version
     Returns : IP address on success, undef otherwise

   `$ip = ip_bintoip ($binip,6);'

ip_bintoint
-----------

   Transform a bit string into a BigInt.

     Params  : binary IP
     Returns : BigInt

   `$bigint = new Math::BigInt (ip_bintoint($binip));'

ip_inttobin
-----------

   Transform a BigInt into a bit string.  Warning: sets warnings (-w) off.
This is necessary because Math::BigInt is not compliant.

     Params  : BigInt, IP version
     Returns : binary IP

   `$binip = ip_inttobin ($bigint);'

ip_get_type
-----------

   Try to guess the IP version of an IP address.

     Params  : IP address
     Returns : 4, 6, 0(unable to determine)

   `$version = ip_get_type ($ip)'

ip_is_ipv4
----------

   Check if an IP address is of type 4.

     Params  : IP address
     Returns : 1 (yes) or 0 (no)

   `ip_is_ipv4($ip) and print "$ip is IPv4";'

ip_is_ipv6
----------

   Check if an IP address is of type 6.

     Params            : IP address
     Returns           : 1 (yes) or 0 (no)

   `ip_is_ipv6($ip) and print "$ip is IPv6";'

ip_expand_address
-----------------

   Expand an IP address from compact notation.

     Params  : IP address, IP version
     Returns : expanded IP address or undef on failure

   `$ip = ip_expand_address ($ip,4);'

ip_get_mask
-----------

   Get IP mask from prefix length.

     Params  : Prefix length, IP version
     Returns : Binary Mask

   `$mask = ip_get_mask ($len,6);'

ip_last_address_bin
-------------------

   Return the last binary address of a prefix.

     Params  : First binary IP, prefix length, IP version
     Returns : Binary IP

   C<$lastbin = ip_last_address_bin ($ip,$len,6);

ip_splitprefix
--------------

   Split a prefix into IP and prefix length.  If it was passed a simple
IP, it just returns it.

     Params  : Prefix
     Returns : IP, optionnaly length of prefix

   `($ip,$len) = ip_splitprefix ($prefix)'

ip_prefix_to_range
------------------

   Get a range of IPs from a prefix.

     Params  : Prefix, IP version
     Returns : First IP, last IP

   `($ip1,$ip2) = ip_prefix_to_range ($prefix,6);'

ip_bincomp
----------

   Compare binary Ips with <, >, <=, >=.   Operators are lt(<), lte(<=),
gt(>), and gte(>=)

   Params  : First binary IP, operator, Last binary IP     Returns : 1
(yes), 0 (no), or undef (problem)

   `ip_bincomp ($ip1,'lt',$ip2) == 1 or do {}'

ip_binadd
---------

   Add two binary IPs.

     Params  : First binary IP, Last binary IP
     Returns : Binary sum or undef (problem)

   `$binip = ip_binadd ($bin1,$bin2);'

ip_get_prefix_length
--------------------

   Get the prefix length for a given range of 2 IPs.

     Params  : First binary IP, Last binary IP
     Returns : Length of prefix or undef (problem)

   `$len = ip_get_prefix_length ($ip1,$ip2);'

ip_range_to_prefix
------------------

   Return all prefixes between two IPs.

     Params  : First IP, Last IP, IP version
     Returns : List of Prefixes or undef (problem)

   The prefixes returned have the form q.q.q.q/nn.

   `@prefix = ip_range_to_prefix ($ip1,$ip2,6);'

ip_compress_address
-------------------

   Compress an IPv6 address. Just returns the IP if it is an IPv4.

     Params  : IP, IP version
     Returns : Compressed IP or undef (problem)

   `$ip = ip_compress_adress ($ip);'

ip_is_overlap
-------------

   Check if two ranges of IPs overlap.

     Params  : Four binary IPs (begin of range 1,end1,begin2,end2), IP version
     Returns : 1    (ranges overlap)
               0    (no overlap)
              -1    (range1 includes range2)
              -2    (range2 includes range1)
     	     undef (problem)

   `ip_is_overlap($rb1,$re1,$rb2,$re2,4) and do {};'

ip_get_embedded_ipv4
--------------------

   Get an IPv4 embedded in an IPv6 address

     Params  : IPv6
     Returns : IPv4 string or undef (not found)

   `$ip4 = ip_get_embedded($ip6);'

ip_check_mask
-------------

   Check the validity of a binary IP mask

     Params  : Mask
     Returns : 1 or undef (invalid)

   `ip_check_mask($binmask) or do {};'

   Checks if mask has only 1s followed by 0s.

ip_aggregate
------------

   Aggregate 2 ranges of binary IPs

     Params  : 1st range (1st IP, Last IP), last range (1st IP, last IP), IP version
     Returns : prefix or undef (invalid)

   `$prefix = ip_aggregate ($bip1,$eip1,$bip2,$eip2) || die ...'

ip_iptype
---------

   Return the type of an IP (Public, Private, Reserved)

     Params  : IP to test, IP version
     Returns : type or undef (invalid)

   `$type = ip_iptype ($ip);'

ip_check_prefix
---------------

   Check the validity of a prefix

     Params  : binary IP, length of prefix, IP version
     Returns : 1 or undef (invalid)

   Checks if the variant part of a prefix only has 0s, and the length is
correct.

   `ip_check_prefix ($ip,$len,$ipv) or do {};'

ip_reverse
----------

   Get a reverse name from a prefix

     Params  : IP, length of prefix, IP version
     Returns : Reverse name or undef (error)

   `$reverse = ip_reverse ($ip);'

ip_normalize
------------

   Normalize data to a range/prefix of IP addresses

     Params  : Data String (Single IP, Range, Prefix)
     Returns : ip1, ip2 (if range/prefix) or undef (error)

   `($ip1,$ip2) = ip_normalize ($data);'

BUGS
====

   The Math::BigInt library is needed for functions that use integers.
These are ip_inttobin, ip_bintoint, and the size method. In a next version,
Math::BigInt will become optionnal.

AUTHORS
=======

   Manuel Valente <mvalente@ripe.net>.

   Original IPv4 code by Monica Cortes Sack <mcortes@ripe.net>.

   Original IPv6 code by Lee Wilmot <lee@ripe.net>.

BASED ON
========

   ipv4pack.pm, iplib.pm, iplibncc.pm.

SEE ALSO
========

   perl(1).

Perl extension for manipulating IPv4 addresses.
***********************************************

NAME
====

   Net::IPv4Addr - Perl extension for manipulating IPv4 addresses.

SYNOPSIS
========

     use Net::IPv4Addr qw( :all );

     my ($ip,$cidr) = ipv4_parse( "127.0.0.1/24" );
     my ($ip,$cidr) = ipv4_parse( "192.168.100.10 / 255.255.255.0" );

     my ($net,$msk) = ipv4_network( "192.168.100.30" );

     my $broadcast  = ipv4_broadcast( "192.168.100.30/26" );

     if ( ipv4_in_network( "192.168.100.0", $her_ip ) ) {
       print "Welcome !";
     }

     etc.

DESCRIPTION
===========

   Net::IPv4Addr provides functions for parsing IPv4 addresses both in
traditional address/netmask format and in the new CIDR format.  There are
also methods for calculating the network and broadcast address and also to
see check if a given address is in a specific network.

ADDRESSES
=========

   All of Net::IPv4Addr functions accepts addresses in many format. The
parsing is very liberal.

   All these addresses would be accepted:

     127.0.0.1
     192.168.001.010/24
     192.168.10.10/255.255.255.0
     192.168.30.10 / 21
     10.0.0.0 / 255.0.0.0
     255.255.0.0

   Those wouldn't though:

     272.135.234.0
     192.168/16

   Most functions accepts the address and netmask or masklength in the
same scalar value or as separate values. That is either

     my($ip,$masklength) = ipv4_parse($cidr_str);
     my($ip,$masklength) = ipv4_parse($ip_str,$msk_str);

USING
=====

   No functions are exported by default. Either use the :all tag to import
them all or explicitly import those you need.

FUNCTIONS
=========

ipv4_parse
          my ($ip,$msklen) = ipv4_parse($cidr_str);
          my $cidr = ipv4_parse($ip_str,$msk_str);
          my ($ip) = ipv4_parse($ip_str,$msk_str);

     Parse an IPv4 address and in scalar context the address in CIDR
     format and in an array context the address and the mask length.

     If the parameters doesn't contains a netmask or a mask length, in
     scalar context only the IPv4 address is returned and in an array
     context the mask length is undefined.

     If the function cannot parse its input, it croaks. Trap it using eval
     if don't like that.

ipv4_network
          my $cidr = ipv4_network($ip_str);
          my $cidr = ipv4_network($cidr_str);
          my ($net,$msk) = ipv4_network( $net_str, $msk_str);

     In scalar context, this function returns the network in CIDR format in
     which the address is. In array context, it returns the network
     address and its mask length as a two elements array. If the input is
     an host without a netmask of mask length, the default netmask is
     assumed.

     Again, the function croak if the input is invalid.

ipv4_broadcast
          my ($broadcast) = ipv4_broadcast($ip_str);
          my $broadcast   = ipv4_broadcast($ip_str,$msk_str);

     This function returns the broadcast address. If the input doesn't
     contains a netmask or mask length, the default netmask is assumed.

     This function croaks if the input is invalid.

ipv4_network
          my $cidr = ipv4_network($net_str);
          my $cidr = ipv4_network($cidr_sstr);
          my ($net,$msk) = ipv4_network( $ip_str, $mask_str);

     In scalar context, this function returns the network in CIDR format in
     which the address is. In array context, it returns the network
     address and its mask length as a two elements array. If the input is
     an host without a netmask or mask length, the default netmask is
     assumed.

     Again, the function croak if the input is invalid.

ipv4_in_network
          print "Yes" if ipv4_in_network( $cidr_str1, $cidr_str2);
          print "Yes" if ipv4_in_network( $ip_str1, $mask_str1, $cidr_str2 );
          print "Yes" if ipv4_in_network( $ip1, $mask1, $ip2, $msk2 );

     This function checks if the second network is contained in the first
     one and it implements the following semantics :

          If net1 or net2 is a magic address (0.0.0.0 or 255.255.255.255)
          than this function returns true.

          If net1 is an host, net2 will be in the same net only if
          it is the same host.

          If net2 is an host, it will be contained in net1 only if
          it is part of net1.

          If net2 is only part of net1 if it is entirely contained in
          net1.

     Trap bad input with eval or else.

ipv4_checkip
          if ($ip = ipv4_checkip($str) ) {
          	# Do something
          }

     Return the IPv4 address in the string or undef if the input doesn't
     contains a valid IPv4 address.

ipv4_cidr2msk
          my $netmask = ipv4_cidr2msk( $cidr );

     Returns the netmask corresponding to the mask length given in input.
     As usual, croaks if it doesn't like your input (in this case a number
     between 0 and 32).

ipv4_msk2cidr
          my $masklen = ipv4_msk2cidr( $msk );

     Returns the mask length of the netmask in input. As usual, croaks if
     it doesn't like your input.

AUTHOR
======

   Francis J. Lacoste <francis.lacoste@iNsu.COM>

COPYRIGHT
=========

   Copyright (c) 1999, 2000 iNsu Innovations Inc.  All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the terms as perl itself.

SEE ALSO
========

   perl(1) ipv4calc(1).

Perl interface to the Internet Relay Chat protocol
**************************************************

NAME
====

   Net::IRC - Perl interface to the Internet Relay Chat protocol

SYNOPSIS
========

     use Net::IRC;

     $irc = new Net::IRC;
     $conn = $irc->newconn(Nick    => 'some_nick',
                           Server  => 'some.irc.server.com',
     	                  Port    =>  6667,
     			  Ircname => 'Some witty comment.');
     $irc->start;

DESCRIPTION
===========

   Welcome to Net::IRC, a work in progress. First intended to be a quick
tool for writing an IRC script in Perl, Net::IRC has grown into a
comprehensive Perl implementation of the IRC protocol (RFC 1459),
supported and developed by several members of the EFnet IRC channel #perl.

   There are 4 component modules which make up Net::IRC:

   * Net::IRC

     The wrapper for everything else, containing methods to generate
     Connection objects (see below) and a connection manager which does an
     event loop on all available filehandles. Sockets or files which are
     readable (or writable, or whatever you want it to select() for) get
     passed to user-supplied handler subroutines in other packages or in
     user code.

   * Net::IRC::Connection

     The big time sink on this project. Each Connection instance is a
     single connection to an IRC server. The module itself contains
     methods for every single IRC command available to users (Net::IRC
     isn't designed for writing servers, for obvious reasons), methods to
     set, retrieve, and call handler functions which the user can set
     (more on this later), and too many cute comments. Hey, what can I
     say, we were bored.

   * Net::IRC::Event

     Kind of a struct-like object for storing info about things that the
     IRC server tells you (server responses, channel talk, joins and
     parts, et cetera). It records who initiated the event, who it
     affects, the event type, and any other arguments provided for that
     event. Incidentally, the only argument passed to a handler function.

   * Net::IRC::DCC

     The analogous object to Connection.pm for connecting, sending and
     retrieving with the DCC protocol. Instances of DCC.pm are invoked from
     `Connection->new_{send,get,chat}' in the same way that `IRC->newconn'
     invokes `Connection->new'. This will make more sense later, we
     promise.

   The central concept that Net::IRC is built around is that of handlers
(or hooks, or callbacks, or whatever the heck you feel like calling them).
We tried to make it a completely event-driven model, a la Tk - for every
conceivable type of event that your client might see on IRC, you can give
your program a custom subroutine to call. But wait, there's more! There are
3 levels of handler precedence:

   * Default handlers

     Considering that they're hardwired into Net::IRC, these won't do much
     more than the bare minimum needed to keep the client listening on the
     server, with an option to print (nicely formatted, of course) what it
     hears to whatever filehandles you specify (STDOUT by default). These
     get called only when the user hasn't defined any of his own handlers
     for this event.

   * User-definable global handlers

     The user can set up his own subroutines to replace the default
     actions for every IRC connection managed by your program. These only
     get invoked if the user hasn't set up a per-connection handler for
     the same event.

   * User-definable per-connection handlers

     Simple: this tells a single connection what to do if it gets an event
     of this type. Supersedes global handlers if any are defined for this
     event.

   And even better, you can choose to call your custom handlers before or
after the default handlers instead of replacing them, if you wish. In
short, it's not perfect, but it's about as good as you can get and still be
documentable, given the sometimes horrendous complexity of the IRC
protocol.

GETTING STARTED
===============

Initialization
--------------

   To start a Net::IRC script, you need two things: a Net::IRC object, and
a Net::IRC::Connection object. The Connection object does the dirty work of
connecting to the server; the IRC object handles the input and output for
it.  To that end, say something like this:

     use Net::IRC;

     $irc = new Net::IRC;

     $conn = $irc->newconn(Nick    => 'some_nick',
                           Server  => 'some.irc.server.com');

   ...or something similar. Acceptable parameters to newconn() are:

   * Nick

     The nickname you'll be known by on IRC, often limited to a maximum of
     9 letters. Acceptable characters for a nickname are `[\w{}[]\`^|-]'.
     If you don't specify a nick, it defaults to your username.

   * Server

     The IRC server to connect to. There are dozens of them across several
     widely-used IRC networks, but the oldest and most popular is EFNet
     (Eris Free Net), home to #perl. See http://www.irchelp.org/ for lists
     of popular servers, or ask a friend.

   * Port

     The port to connect to this server on. By custom, the default is 6667.

   * Username

     On systems not running identd, you can set the username for your
     user@host to anything you wish. Note that some IRC servers won't
     allow connections from clients which don't run identd.

   * Ircname

     A short (maybe 60 or so chars) piece of text, originally intended to
     display your real name, which people often use for pithy quotes and
     URLs. Defaults to the contents of your GECOS field.

   * Password

     If the IRC server you're trying to write a bot for is
     password-protected, no problem. Just say "`Password =' 'foo'>" and
     you're set.

     =back

Handlers
--------

   Once that's over and done with, you need to set up some handlers if you
want your bot to do anything more than sit on a connection and waste
resources.  Handlers are references to subroutines which get called when a
specific event occurs. Here's a sample handler sub:

     # What to do when the bot successfully connects.
     sub on_connect {
         my $self = shift;

     print "Joining #IRC.pm...";
     $self->join("#IRC.pm");
     $self->privmsg("#IRC.pm", "Hi there.");
         }

   The arguments to a handler function are always the same:

$_[0]:
     The Connection object that's calling it.

$_[1]:
     An Event object (see below) that describes what the handler is
     responding to.

   Got it? If not, see the examples in the irctest script that came with
this distribution. Anyhow, once you've defined your handler subroutines,
you need to add them to the list of handlers as either a global handler
(affects all Connection objects) or a local handler (affects only a single
Connection). To do so, say something along these lines:

     $self->add_global_handler('376', \&on_connect);     # global
     $self->add_handler('msg', \&on_msg);                # local

   376, incidentally, is the server number for "end of MOTD", which is an
event that the server sends to you after you're connected. See Event.pm
for a list of all possible numeric codes. The 'msg' event gets called
whenever someone else on IRC sends your client a private message. For a
big list of possible events, see the *Event List* section in the
documentation for Net::IRC::Event.

Getting Connected
-----------------

   When you've set up all your handlers, the following command will put
your program in an infinite loop, grabbing input from all open connections
and passing it off to the proper handlers:

     $irc->start;

   Note that new connections can be added and old ones dropped from within
your handlers even after you call this. Just don't expect any code below
the call to start() to ever get executed.

   If you're tying Net::IRC into another event-based module, such as
perl/Tk, there's a nifty `do_one_loop()' method provided for your
convenience. Calling `$irc->do_one_loop()' runs through the IRC.pm event
loop once, hands all ready filehandles over to the appropriate handler
subs, then returns control to your program.

METHOD DESCRIPTIONS
===================

   This section contains only the methods in IRC.pm itself. Lists of the
methods in Net::IRC::Connection, Net::IRC::Event, or Net::IRC::DCC are in
their respective modules' documentation; just `perldoc
Net::IRC::Connection' (or Event or DCC or whatever) to read them.
Functions take no arguments unless otherwise specified in their
description.

   By the way, expect Net::IRC to use AutoLoader sometime in the future,
once it becomes a little more stable.

   * addconn()

     Adds the specified object's socket to the select loop in
     `do_one_loop()'.  This is mostly for the use of Connection and DCC
     objects (and for pre-0.5 compatibility)... for most (read: all)
     purposes, you can just use `addfh()', described below.

     Takes at least 1 arg:

       1. An object whose socket needs to be added to the select loop

       2. *Optional:* A string consisting of one or more of the letters r,
          w, and e.  Passed directly to `addfh()'... see the description
          below for more info.

   * addfh()

     This sub takes a user's socket or filehandle and a sub to handle it
     with and merges it into `do_one_loop()''s list of select()able
     filehandles. This makes integration with other event-based systems
     (Tk, for instance) a good deal easier than in previous releases.

     Takes at least 2 args:

       1. A socket or filehandle to monitor

       2. A reference to a subroutine. When select() determines that the
          filehandle is ready, it passes the filehandle to this
          (presumably user-supplied) sub, where you can read from it,
          write to it, etc. as your script sees fit.

       3. *Optional:* A string containing any combination of the letters
          r, w or e (standing for read, write, and error, respectively)
          which determines what conditions you're expecting on that
          filehandle. For example, this line select()s $fh (a filehandle,
          of course) for both reading and writing:

               $irc->addfh( $fh, \&callback, "rw" );

   * do_one_loop()

     select()s on all open filehandles and passes any ready ones to the
     appropriate handler subroutines. Also responsible for executing
     scheduled events from `Net::IRC::Connection->schedule()' on time.

   * new()

     A fairly vanilla constructor which creates and returns a new Net::IRC
     object.

   * newconn()

     Creates and returns a new Connection object. All arguments are passed
     straight to `Net::IRC::Connection->new()'; examples of common
     arguments can be found in the Synopsis or *Getting Started* sections.

   * removeconn()

     Removes the specified object's socket from `do_one_loop()''s list of
     select()able filehandles. This is mostly for the use of Connection
     and DCC objects (and for pre-0.5 compatibility)... for most (read:
     all) purposes, you can just use `removefh()', described below.

     Takes 1 arg:

       1. An object whose socket or filehandle needs to be removed from
          the select loop

   * removefh()

     This method removes a given filehandle from `do_one_loop()''s list of
     selectable filehandles.

     Takes 1 arg:

       1. A socket or filehandle to remove

   * start()

     Starts an infinite event loop which repeatedly calls `do_one_loop()'
     to read new events from all open connections and pass them off to any
     applicable handlers.

   * timeout()

     Sets or returns the current select() timeout for the main event loop,
     in seconds (fractional amounts allowed). See the documentation for the
     select() function for more info.

     Takes 1 optional arg:

       1. *Optional:* A new value for the select() timeout for this IRC
          object.

AUTHORS
=======

   * Conceived and initially developed by Greg Bacon <gbacon@adtran.com>
     and Dennis Taylor <dennis@funkplanet.com>.

   * Ideas and large amounts of code donated by Nat "King" Torkington
     <gnat@frii.com>.

   * Currently being hacked on, hacked up, and worked over by the members
     of the Net::IRC developers mailing list. For details, see
     http://www.execpc.com/~corbeau/irc/list.html .

URL
===

   Up-to-date source and information about the Net::IRC project can be
found at http://netirc.betterbox.net/ .

SEE ALSO
========

   * perl(1).

   * RFC 1459: The Internet Relay Chat Protocol

   * http://www.irchelp.org/, home of fine IRC resources.

Object-oriented interface to a single IRC connection
****************************************************

NAME
====

   Net::IRC::Connection - Object-oriented interface to a single IRC
connection

SYNOPSIS
========

   Hard hat area: This section under construction.

DESCRIPTION
===========

   This documentation is a subset of the main Net::IRC documentation. If
you haven't already, please "perldoc Net::IRC" before continuing.

   Net::IRC::Connection defines a class whose instances are individual
connections to a single IRC server. Several Net::IRC::Connection objects
may be handled simultaneously by one Net::IRC object.

METHOD DESCRIPTIONS
===================

   This section is under construction, but hopefully will be finally
written up by the next release. Please see the `irctest' script and the
source for details about this module.

AUTHORS
=======

   Conceived and initially developed by Greg Bacon <gbacon@adtran.com> and
Dennis Taylor <dennis@funkplanet.com>.

   Ideas and large amounts of code donated by Nat "King" Torkington
<gnat@frii.com>.

   Currently being hacked on, hacked up, and worked over by the members of
the Net::IRC developers mailing list. For details, see
http://www.execpc.com/~corbeau/irc/list.html .

URL
===

   Up-to-date source and information about the Net::IRC project can be
found at http://netirc.betterbox.net/ .

SEE ALSO
========

   * perl(1).

   * RFC 1459: The Internet Relay Chat Protocol

   * http://www.irchelp.org/, home of fine IRC resources.

Object-oriented interface to a single DCC connection
****************************************************

NAME
====

   Net::IRC::DCC - Object-oriented interface to a single DCC connection

SYNOPSIS
========

   Hard hat area: This section under construction.

DESCRIPTION
===========

   This documentation is a subset of the main Net::IRC documentation. If
you haven't already, please "perldoc Net::IRC" before continuing.

   Net::IRC::DCC defines a few subclasses that handle DCC CHAT, GET, and
SEND requests for inter-client communication. DCC objects are created by
`Connection->new_{chat,get,send}()' in much the same way that
`IRC->newconn()' creates a new connection object.

METHOD DESCRIPTIONS
===================

   This section is under construction, but hopefully will be finally
written up by the next release. Please see the `irctest' script and the
source for details about this module.

AUTHORS
=======

   Conceived and initially developed by Greg Bacon <gbacon@adtran.com> and
Dennis Taylor <dennis@funkplanet.com>.

   Ideas and large amounts of code donated by Nat "King" Torkington
<gnat@frii.com>.

   Currently being hacked on, hacked up, and worked over by the members of
the Net::IRC developers mailing list. For details, see
http://www.execpc.com/~corbeau/irc/list.html .

URL
===

   Up-to-date source and information about the Net::IRC project can be
found at http://netirc.betterbox.net/ .

SEE ALSO
========

   * perl(1).

   * RFC 1459: The Internet Relay Chat Protocol

   * http://www.irchelp.org/, home of fine IRC resources.

A class for passing event data between subroutines
**************************************************

NAME
====

   Net::IRC::Event - A class for passing event data between subroutines

SYNOPSIS
========

   None yet. These docs are under construction.

DESCRIPTION
===========

   This documentation is a subset of the main Net::IRC documentation. If
you haven't already, please "perldoc Net::IRC" before continuing.

   Net::IRC::Event defines a standard interface to the salient information
for just about any event your client may witness on IRC. It's about as
close as we can get in Perl to a struct, with a few extra nifty features
thrown in.

METHOD DESCRIPTIONS
===================

   This section is under construction, but hopefully will be finally
written up by the next release. Please see the `irctest' script and the
source for details about this module.

LIST OF EVENTS
==============

   Net::IRC is an entirely event-based system, which takes some getting
used to at first. To interact with the IRC server, you tell Net::IRC's
server connection to listen for certain events and activate your own
subroutines when they occur. Problem is, this doesn't help you much if you
don't know what to tell it to look for. Below is a list of the possible
events you can pass to Net::IRC, along with brief descriptions of each...
hope this helps.

Common events
-------------

   * nick

     The "nick" event is triggered when the client receives a NICK
     message, meaning that someone on a channel with the client has
     changed eir nickname.

   * quit

     The "quit" event is triggered upon receipt of a QUIT message, which
     means that someone on a channel with the client has disconnected.

   * join

     The "join" event is triggered upon receipt of a JOIN message, which
     means that someone has entered a channel that the client is on.

   * part

     The "part" event is triggered upon receipt of a PART message, which
     means that someone has left a channel that the client is on.

   * mode

     The "mode" event is triggered upon receipt of a MODE message, which
     means that someone on a channel with the client has changed the
     channel's parameters.

   * topic

     The "topic" event is triggered upon receipt of a TOPIC message, which
     means that someone on a channel with the client has changed the
     channel's topic.

   * kick

     The "kick" event is triggered upon receipt of a KICK message, which
     means that someone on a channel with the client (or possibly the
     client itself!) has been forcibly ejected.

   * public

     The "public" event is triggered upon receipt of a PRIVMSG message to
     an entire channel, which means that someone on a channel with the
     client has said something aloud.

   * msg

     The "msg" event is triggered upon receipt of a PRIVMSG message which
     is addressed to one or more clients, which means that someone is
     sending the client a private message. (Duh. :-)

   * notice

     The "notice" event is triggered upon receipt of a NOTICE message,
     which means that someone has sent the client a public or private
     notice. (Is that sufficiently vague?)

   * ping

     The "ping" event is triggered upon receipt of a PING message, which
     means that the IRC server is querying the client to see if it's
     alive. Don't confuse this with CTCP PINGs, explained later.

   * other

     The "other" event is triggered upon receipt of any number of
     unclassifiable miscellaneous messages, but you're not likely to see
     it often.

   * invite

     The "invite" event is triggered upon receipt of an INVITE message,
     which means that someone is permitting the client's entry into a +i
     channel.

   * kill

     The "kill" event is triggered upon receipt of a KILL message, which
     means that an IRC operator has just booted your sorry arse offline.
     Seeya!

   * disconnect

     The "disconnect" event is triggered when the client loses its
     connection to the IRC server it's talking to. Don't confuse it with
     the "leaving" event. (See below.)

   * leaving

     The "leaving" event is triggered just before the client deliberately
     closes a connection to an IRC server, in case you want to do anything
     special before you sign off.

   * umode

     The "umode" event is triggered when the client changes its personal
     mode flags.

   * error

     The "error" event is triggered when the IRC server complains to you
     about anything. Sort of the evil twin to the "other" event, actually.

CTCP Requests
-------------

   * cping

     The "cping" event is triggered when the client receives a CTCP PING
     request from another user. See the irctest script for an example of
     how to properly respond to this common request.

   * cversion

     The "cversion" event is triggered when the client receives a CTCP
     VERSION request from another client, asking for version info about
     its IRC client program.

   * csource

     The "csource" event is triggered when the client receives a CTCP
     SOURCE request from another client, asking where it can find the
     source to its IRC client program.

   * ctime

     The "ctime" event is triggered when the client receives a CTCP TIME
     request from another client, asking for the local time at its end.

   * cdcc

     The "cdcc" event is triggered when the client receives a DCC request
     of any sort from another client, attempting to establish a DCC
     connection.

   * cuserinfo

     The "cuserinfo" event is triggered when the client receives a CTCP
     USERINFO request from another client, asking for personal information
     from the client's user.

   * cclientinfo

     The "cclientinfo" event is triggered when the client receives a CTCP
     CLIENTINFO request from another client, asking for whatever the hell
     "clientinfo" means.

   * cerrmsg

     The "cerrmsg" event is triggered when the client receives a CTCP
     ERRMSG request from another client, notifying it of a protocol error
     in a preceding CTCP communication.

   * cfinger

     The "cfinger" event is triggered when the client receives a CTCP
     FINGER request from another client. How to respond to this should
     best be left up to your own moral stance.

   * caction

     The "caction" event is triggered when the client receives a CTCP
     ACTION message from another client. I should hope you're getting the
     hang of how Net::IRC handles CTCP requests by now...

CTCP Responses
--------------

   * crping

     The "crping" event is triggered when the client receives a CTCP PING
     response from another user. See the irctest script for an example of
     how to properly respond to this common event.

   * crversion

     The "crversion" event is triggered when the client receives a CTCP
     VERSION response from another client.

   * crsource

     The "crsource" event is triggered when the client receives a CTCP
     SOURCE response from another client.

   * crtime

     The "crtime" event is triggered when the client receives a CTCP TIME
     response from another client.

   * cruserinfo

     The "cruserinfo" event is triggered when the client receives a CTCP
     USERINFO response from another client.

   * crclientinfo

     The "crclientinfo" event is triggered when the client receives a CTCP
     CLIENTINFO response from another client.

   * crfinger

     The "crfinger" event is triggered when the client receives a CTCP
     FINGER response from another client. I'm not even going to consider
     making a joke about this one.

DCC Events
----------

   * dcc_open

     The "dcc_open" event is triggered when a DCC connection is
     established between the client and another client.

   * dcc_update

     The "dcc_update" event is triggered when any data flows over a DCC
     connection.  Useful for doing things like monitoring file transfer
     progress, for instance.

   * dcc_close

     The "dcc_close" event is triggered when a DCC connection closes,
     whether from an error or from natural causes.

   * chat

     The "chat" event is triggered when the person on the other end of a
     DCC CHAT connection sends you a message. Think of it as the private
     equivalent of "msg", if you will.

Numeric Events
--------------

   * There's a whole lot of them, and they're well-described elsewhere.
     Please see the IRC RFC (1495, at
     http://cs-ftp.bu.edu/pub/irc/support/IRC_RFC ) for a detailed
     description, or the Net::IRC::Event.pm source code for a quick list.

AUTHORS
=======

   Conceived and initially developed by Greg Bacon <gbacon@adtran.com> and
Dennis Taylor <dennis@funkplanet.com>.

   Ideas and large amounts of code donated by Nat "King" Torkington
<gnat@frii.com>.

   Currently being hacked on, hacked up, and worked over by the members of
the Net::IRC developers mailing list. For details, see
http://www.execpc.com/~corbeau/irc/list.html .

URL
===

   Up-to-date source and information about the Net::IRC project can be
found at http://netirc.betterbox.net/ .

SEE ALSO
========

   * perl(1).

   * RFC 1459: The Internet Relay Chat Protocol

   * http://www.irchelp.org/, home of fine IRC resources.

lookup the username on the remote end of a TCP/IP connection
************************************************************

NAME
====

   Net::Ident - lookup the username on the remote end of a TCP/IP
connection

SYNOPSIS
========

     use Net::Ident;

     $username = Net::Ident::lookup(SOCKET, $timeout);

     $username = Net::Ident::lookupFromInAddr($localsockaddr,
     					   $remotesockaddr, $timeout);

     $obj = Net::Ident->new(SOCKET, $timeout);
     $obj = Net::Ident->newFromInAddr($localsockaddr, $remotesockaddr,
     					$timeout);
     $status = $obj->query;
     $status = $obj->ready;
     $username = $obj->username;
     ($username, $opsys, $error) = $obj->username;
     $fh = $obj->getfh;
     $txt = $obj->geterror;

     use Net::Ident 'ident_lookup';

     $username = ident_lookup(SOCKET, $timeout);

     use Net::Ident 'lookupFromInAddr';

     $username = lookupFromInAddr($localsockaddr, $remotesockaddr, $timeout);

     use Net::Ident ':fh';

     $username = SOCKET->ident_lookup($timeout);

     use Net::Ident ':apache';

     # my Apache $r;
     $c = $r->connection;
     $username = $c->ident_lookup($timeout);

OVERVIEW
========

   *Net::Ident* is a module that looks up the username on the remote side
of a TCP/IP connection through the ident (auth/tap) protocol described in
RFC1413 (which supersedes RFC931). Note that this requires the remote site
to run a daemon (often called *identd*) to provide the requested
information, so it is not always available for all TCP/IP connections.

DESCRIPTION
===========

   You can either use the simple interface, which does one ident lookup at
a time, or use the asynchronous interface to perform (possibly) many
simultaneous lookups, or simply continue serving other things while the
lookup is proceeding.

Simple Interface
----------------

   The simple interface comes in four varieties. An object oriented method
call of a FileHandle object, an object oriented method of an
Apache::Connection object, and as one of two different simple subroutine
calls. Other than the calling method, these routines behave exactly the
same.

`Net::Ident::lookup (SOCKET' [`, $timeout'])
     *Net::Ident::lookup* is an exportable function. However, due to the
     generic name of the lookup function, it is recommended that you
     instead import the alias function *Net::Ident::ident_lookup*. Both
     functions are exported through `@EXPORT_OK', so you'll have to
     explicitly ask for it if you want the function *ident_lookup* to be
     callable from your program.

     You can pass the socket using either a string, which doesn't have to
     be qualified with a package name, or using the more modern FileHandle
     calling styles: as a glob or as a reference to a glob. The Socket has
     to be a connected TCP/IP socket, ie. something which is either
     connect()ed or accept()ed. The optional timeout parameter specifies a
     timeout in seconds. If you do not specify a timeout, or use a value
     of undef, there will be no timeout (apart from any default system
     timeouts like TCP connection timeouts).

`Net::Ident::lookupFromInAddr ($localaddr, $remoteaddr' [`, $timeout'])
     *Net::Ident::lookupFromInAddr* is an exportable function (via
     `@EXPORT_OK').  The arguments are the local and remote address of a
     connection, in packed "sockaddr" format (the kind of thing that
     getsockname returns). The optional timeout value specifies a timeout
     in seconds, see also the description of the timeout value in the
     `Net::Ident::lookup' section above.

     The given localaddr must have the IP address of a local interface of
     the machine you're calling this on, otherwise an error will occur.

     You can use this function whenever you have a local and remote socket
     address, but no direct access to the socket itself. For example,
     because you are parsing the output of "netstat" and extracting socket
     address, or because you are writing a mod_perl script under apache
     (in that case, also see the Apache::Connection method below).

`ident_lookup SOCKET' [$timeout]
     When you import the "magic" tag ':fh' using `use Net::Ident ':fh';',
     the *Net::Ident* module extends the FileHandle class with one extra
     method call, *ident_lookup*. It assumes that the object (a
     FileHandle) it is operating on, is a connected TCP/IP socket, ie.
     something which is either connect()ed or accept()ed. The optional
     parameter specifies the timeout in seconds, just like the timeout
     parameter of the function calls above.

     Some people do not like the way that "proper" object design is broken
     by letting one module add methods to another class. This is why,
     starting from version 1.20, you have to explicitly ask for this
     behaviour to occur.  Personally, I this it's a compromise: if you
     want an object-oriented interface, then either you make a derived
     class, like a FileHandleThatCanPerformIdentLookups, and make sure all
     appropriate internal functions get wrappers that do the necessary
     re-blessing. Or, you simply extend the FileHandle class. And since
     Perl doesn't object to this (pun intended :), I find this an
     acceptable solution. But you might think otherwise.

`ident_lookup Apache::Connection' [$timeout]
     When you import the "magic" tag ':apache' using `use Net::Ident
     ':apache';', the *Net::Ident* module extends the *Apache::Connection*
     class with one extra method call, *ident_lookup*. This method takes
     one optional parameter: a timeout value in seconds.

     This is a similar convenience function as the
     FileHandle::ident_lookup method, to be used with mod_perl scripts
     under Apache.

   What these functions return depends on the context:

scalar context
     In scalar context, these functions return the remote username on
     success, or undef on error. "Error" is rather broad, it might mean:
     some network error occurred, function arguments are invalid, the
     remote site is not responding (in time) or is not running an ident
     daemon, or the remote site ident daemon says there's no user
     connected with that particular connection.

     More precisely, the functions return whatever the remote daemon
     specified as the ID that belongs to that particular connection. This
     is often the username, but it doesn't necessarily have to be. Some
     sites, out of privacy and/or security measures, return an opaque ID
     that is unique for each user, but is not identical to the username.
     See *RFC1413* for more information.

array context
     In array context, these functions return: `($username, $opsys,
     $error)'.  The $username is the remote username or ID, as returned in
     the scalar context, or undef on error.

     The *$opsys* is the remote operating system as reported by the remote
     ident daemon, or undef on a network error, or *"ERROR"* when the
     remote ident daemon reported an error. This could also contain the
     character set of the returned username. See RFC1413.

     The $error is the error message, either the error reported by the
     remote ident daemon (in which case *$opsys* is *"ERROR"*), or the
     internal message from the *Net::Ident* module, which includes the
     system errno $! whenever possible. A likely candidate is *"Connection
     refused"* when the remote site isn't running an ident daemon, or
     *"Connection timed out"* when the remote site isn't answering our
     connection request.

     When $username has a value, $error is always undef, and vice versa.

EXAMPLE
-------

   The following code is a complete example, implementing a server that
waits for a connection on a port, tells you who you are and what time it
is, and closes the connection again. The majority of the code will look
very familiar if you just read Perlipc (perl.info).

   Excersize this server by telnetting to it, preferably from a machine
that has a suitable ident daemon installed.

     #!/usr/bin/perl -w

     use Net::Ident;
     # uncomment the below line if you want lots of debugging info
     # $Net::Ident::DEBUG = 2;
     use Socket;
     use strict;

     sub logmsg { print "$0 $$: @_ at ", scalar localtime, "\n" }

     my $port = shift || 2345;
     my $proto = getprotobyname('tcp');
     socket(Server, PF_INET, SOCK_STREAM, $proto) or die "socket: $!";
     setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) or
       die "setsockopt: $!";
     bind(Server, sockaddr_in($port, INADDR_ANY)) or die "bind: $!";
     listen(Server,SOMAXCONN) or die "listen: $!";

     logmsg "server started on port $port";

     my $paddr;

     for ( ; $paddr = accept(Client,Server); close Client) {
     	my($port,$iaddr) = sockaddr_in($paddr);
     	my $name = gethostbyaddr($iaddr,AF_INET) || inet_ntoa($iaddr);
     	logmsg "connection from $name [" . inet_ntoa($iaddr) .
     	  "] at port $port";

     	my $username = Client->ident_lookup(30) || "~unknown";
     	logmsg "User at $name:$port is $username";

     	print Client "Hello there, $username\@$name, it's now ",
     	   scalar localtime, "\n";
     }

Asynchronous Interface
----------------------

   The asynchronous interface is meant for those who know the ins and outs
of the select() call (the 4-argument version of select(), but I didn't
need saying that, did I?). This interface is completely object oriented.
The following methods are available:

`new Net::Ident SOCKET, $timeout'
     This constructs a new Net::Ident object, and initiates the connection
     to the remote ident daemon. The parameters are the same as described
     above for the *Net::Ident::lookup* subroutine. This method returns
     immediately, the supplied $timeout is only stored in the object and
     used in future methods.

     If you want to implement your own timeout, that's fine. Simply throw
     away the object when you don't want it anymore.

     The constructor will always succeed. When it detects an error,
     however, it returns an object that "has already failed" internally. In
     this case, all methods will return undef except for the `geterror'
     method, wich will return the error message.

     The timeout is not implemented using `alarm()'. In fact you can use
     `alarm()' completely independant of this library, they do not
     interfere.

`newFromInAddr $localaddr, $remoteaddr, $timeout'
     Alternative constructor, that takes two packed sockaddr structures.
     Otherwise behaves identical to the new constructor above.

`query $obj'
     This object method queries the remote rfc931 deamon, and blocks until
     the connection to the ident daemon is writable, if necessary (but you
     are supposed to make sure it is, of course). Returns true on success
     (or rather it returns the $obj itself), or undef on error.

`ready $obj' [`$blocking']
     This object method returns whether the data received from the remote
     daemon is complete (true or false). Returns undef on error. Reads any
     data from the connection.  If *$blocking* is true, it blocks and
     waits until all data is received (it never returns false when blocking
     is true, only true or undef). If *$blocking* is not true, it doesn't
     block at all (unless... see below).

     If you didn't call `query $obj' yet, this method calls it for you,
     which means it can block, regardless of the value of *$blocking*,
     depending on whether the connection to the ident is writable.

     Obviously, you are supposed to call this routine whenever you see that
     the connection to the ident daemon is readable, and act appropriately
     when this returns true.

     Note that once *ready* returns true, there are no longer checks on
     timeout (because the networking part of the lookup is over anyway).
     This means that even `ready $obj' can return true way after the
     timeout has expired, provided it returned true at least once before
     the timeout expired. This is to be construed as a feature.

`username $obj'
     This object method parses the return from the remote ident daemon, and
     blocks until the query is complete, if necessary (it effectively calls
     `ready $obj 1' for you if you didn't do it yourself). Returns the
     parsed username on success, or undef on error. In an array context,
     the return values are the same as described for the
     *Net::Ident::lookup* subroutine.

`getfh $obj'
     This object method returns the internal FileHandle used for the
     connection to the remote ident daemon. Invaluable if you want it to
     dance in your select() ring. Returns undef when an error has occurred.

`geterror $obj'
     This object method returns the error message in case there was an
     error. undef when there was no error.

   An asynchronous example implementing the above server in a
multi-threaded way via select, is left as an excersize for the interested
reader.

DISCLAIMER
==========

   I make NO WARRANTY or representation, either express or implied, with
respect to this software, its quality, accuracy, merchantability, or
fitness for a particular purpose.  This software is provided "AS IS", and
you, its user, assume the entire risk as to its quality and accuracy.

AUTHOR
======

   Jan-Pieter Cornet, <johnpc@xs4all.nl>

COPYRIGHT
=========

   Copyright (c) 1995, 1997, 1999 Jan-Pieter Cornet. All rights reserved.
You can distribute and use this program under the same terms as Perl
itself.

REVISION HISTORY
================

V1.20
     August 2, 1999. Finally implemented the long-asked-for
     lookupFromInAddr method. Other changes:

        * No longer imports ident_lookup into package FileHandle by
          default, unless you explicitly ask for it (or unless you
          installed it that way during compile time for compatibility
          reasons).

        * Allow adding an ident_lookup method to the Apache::Connection
          class, as a convenience for mod_perl script writers.

        * Rewritten tests, included test for the Apache::Connection method
          by actually launching apache and performing ident lookups from
          within mod_perl.

        * Moved selection of FileHandle/IO::Handle class out of the
          Makefile.PL.  PAUSE/CPAN didn't really like modules that weren't
          present in the distribution, and it didn't allow you to upgrade
          your perl version underneath.

V1.11
     Jan 15th, 1997. Several bugfixes, and some slight interface changes:

        * constructor now called new instead of `initconnect', constructor
          now always succeeds, if something has gone wrong in the
          constructor, all methods return undef (like getfh), except for
          `geterror', which returns the error message.

        * The recommended exported function is now `ident_lookup' instead
          of lookup

        * Fixed a bug: now chooses O_NDELAY or O_NONBLOCK from %Config,
          instead of hardcoding O_NDELAY (argh)

        * Adding a method to FileHandle would break in perl5.004, it
          should get added in IO::Handle. Added intelligence in
          Makefile.PL to detect that and choose the appropriate package.

        * Miscellaneous pod fixes.

        * Test script now actually tests multiple different things.

V1.10
     Jan 11th, 1997. Complete rewrite for perl5. Requires perl5.002 or up.

V1.02
     Jan 20th, 1995. Quite a big bugfix: "connection refused" to the ident
     port would kill the perl process with a SIGPIPE if the connect didn't
     immediately signal it (ie. almost always on remote machines). Also
     recognises the perl5 package separator :: now on fully qualified
     descriptors. This is still perl4-compatible, a perl5- only version
     would require a rewrite to make it neater.  Fixed the constants
     normally found in .ph files (but you shouldn't use those anyway).

     [this release wasn't called *Net::Ident*, of course, it was called
     *rfc931.pl*]

V1.01
     Around November 1994. Removed a spurious *perl5 -w* complaint. First
     public release.  Has been tested against *perl 5.000* and *perl
     4.036*.

V1.00
     Dunno, somewhere 1994. First neat collection of dusty routines put in
     a package.

SEE ALSO
========

   See Socket, RFC1413, RFC931

Internet socket interface module
********************************

NAME
====

   Net::Inet - Internet socket interface module

SYNOPSIS
========

     use Net::Gen;		# optional
     use Net::Inet;

DESCRIPTION
===========

   The `Net::Inet' module provides basic services for handling
socket-based communications for the Internet protocol family.  It inherits
from `Net::Gen', and is a base for `Net::TCP' and `Net::UDP'.

Public Methods
--------------

new
     Usage:

          $obj = new Net::Inet;
          $obj = new Net::Inet $desthost, $destservice;
          $obj = new Net::Inet \%parameters;
          $obj = new Net::Inet $desthost, $destservice, \%parameters;
          $obj = 'Net::Inet'->new();
          $obj = 'Net::Inet'->new($desthost, $destservice);
          $obj = 'Net::Inet'->new(\%parameters);
          $obj = 'Net::Inet'->new($desthost, $destservice, \%parameters);

     Returns a newly-initialised object of the given class.  If called for
     a derived class, no validation of the supplied parameters will be
     performed.  (This is so that the derived class can set up the
     parameter validation it needs in the object before allowing the
     validation.)  Otherwise, it will cause the parameters to be validated
     by calling its init method.  In particular, this means that if both a
     host and a service are given, then an object will only be returned if
     a connect() call was successful, or if the object is non-blocking and
     a connect() call is in progress.

     The examples above show the indirect object syntax which many prefer,
     as well as the guaranteed-to-be-safe static method call.  There are
     occasional problems with the indirect object syntax, which tend to be
     rather obscure when encountered.  See

     <URL:http://www.rosat.mpe-garching.mpg.de/mailing-lists/perl-porters/1998-01/msg01674.html>
     for details.

init
     Usage:

          return undef unless $self->init;
          return undef unless $self->init(\%parameters);
          return undef unless $self->init($desthost, $destservice);
          return undef unless $self->init($desthost, $destservice, \%parameters);

     Verifies that all previous parameter assignments are valid (via
     checkparams).  Returns the incoming object on success, and undef on
     failure.  Usually called only via a derived class's init method or
     its own new call.

bind
     Usage:

          $ok = $obj->bind;
          $ok = $obj->bind($lclhost, $lclservice);
          $ok = $obj->bind($lclhost, $lclservice, \%parameters);

     Sets up the srcaddrlist object parameter with the specified $lclhost
     and $lclservice arguments if supplied (via the thishost and thisport
     object parameters), and then returns the value from the inherited
     bind method.  Changing of parameters is also allowed, mainly for
     setting debug status or timeouts.

     Example:

          $ok = $obj->bind(0, 'echo(7)'); # attach to the local TCP echo port

unbind
     Usage:

          $obj->unbind;

     Deletes the thishost and thisport object parameters, and then
     (assuming that succeeds, which it should) returns the value from the
     inherited unbind method.

connect
     Usage:

          $ok = $obj->connect;
          $ok = $obj->connect($host, $service);
          $ok = $obj->connect($host, $service, \%parameters);

     Attempts to establish a connection for the object.  If the $host or
     $service arguments are specified, they will be used to set the
     desthost and destservice/destport object parameters, with
     side-effects of setting up the dstaddrlist object parameter.  Then,
     the result of a call to the inherited connect method will be
     returned.  Changing of parameters is also allowed, mainly for setting
     debug status or timeouts.

format_addr
     Usage:

          $string = $obj->format_addr($sockaddr);
          $string = $obj->format_addr($sockaddr, $numeric_only);
          $string = format_addr Module $sockaddr;
          $string = format_addr Module $sockaddr, $numeric_only;

     Returns a formatted representation of the address.  This is a method
     so that it can be overridden by derived classes.  It is used to
     implement "pretty-printing" methods for source and destination
     addresses.  If the $numeric_only argument is true, the address and
     port number will be used even if they can be resolved to names.
     Otherwise, the resolved hostname and service name will be used if
     possible.

format_local_addr
     Usage:

          $string = $obj->format_local_addr;
          $string = $obj->format_local_addr($numeric_only);

     Returns a formatted representation of the local socket address
     associated with the object.  A sugar-coated way of calling the
     format_addr method for the srcaddr object parameter.

format_remote_addr
     Usage:

          $string = $obj->format_remote_addr;

     Returns a formatted representation of the remote socket address
     associated with the object.  A sugar-coated way of calling the
     format_addr method for the dstaddr object parameter.

getsockinfo
     An augmented form of `Net::Gen::getsockinfo'.  Aside from updating
     more object parameters, it behaves the same as that in the base
     class.  The additional object parameters which get set are lcladdr,
     lclhost, lclport, lclservice, remaddr, remhost, remport, and
     remservice.  (They are described in `"Known Object Parameters"' in
     this node below.)

   There are also various *accessor* methods for the object parameters.
See `Accessors', see Net/Gen, for calling details.  See `"Known
Object Parameters"' in this node below for those defined by this class.

Protected Methods
-----------------

   [See the note in `"Protected Methods"', see Net/Gen, about my
definition of protected methods in Perl.]

   None.

Known Socket Options
--------------------

   These are the socket options known to the `Net::Inet' module itself:

     `IP_HDRINCL' `IP_RECVDSTADDR' `IP_RECVOPTS' `IP_RECVRETOPTS' `IP_TOS'
     `IP_TTL' `IP_ADD_MEMBERSHIP' `IP_DROP_MEMBERSHIP' `IP_MULTICAST_IF'
     `IP_MULTICAST_LOOP' `IP_MULTICAST_TTL' `IP_OPTIONS' `IP_RETOPTS'

Known Object Parameters
-----------------------

   These are the object parameters registered by the `Net::Inet' module
itself:

IPproto
     The name of the Internet protocol in use on the socket associated
     with the object.  Set as a side-effect of setting the proto object
     parameter, and vice versa.

proto
     Used the same way as with `Net::Gen', but has a handler attached to
     keep it in sync with IPproto.

thishost
     The source host name or address to use for the bind method.  When
     used in conjunction with the thisservice or thisport object
     parameter, causes the srcaddrlist object parameter to be set, which
     is how it affects the bind() action.  This parameter is validated,
     and must be either a valid internet address or a hostname for which
     an address can be found.  If a hostname is given, and multiple
     addresses are found for it, then each address will be entered into
     the srcaddrlist array reference.

desthost
     The destination host name or address to use for the connect method.
     When used in conjunction with the destservice or destport object
     parameter, causes the dstaddrlist object parameter to be set, which
     is how it affects the connect() action.  This parameter is validated,
     and must be either a valid internet address or a hostname for which
     an address can be found.  If a hostname is given, and multiple
     addresses are found for it, then each address will be entered into
     the dstaddrlist array reference, in order.  This allows the connect
     method to attempt a connection to each address, as per RFC 1123.

thisservice
     The source service name (or number) to use for the bind method.  An
     attempt will be made to translate the supplied service name with
     getservbyname().  If that succeeds, or if it fails but the supplied
     value was strictly numeric, the port number will be set in the
     thisport object parameter.  If the supplied value is not numeric and
     can't be translated, the attempt to set the value will fail.
     Otherwise, this causes the srcaddrlist object parameter to be
     updated, in preparation for an invocation of the bind method
     (possibly implicitly from the connect method).

thisport
     The source service number (or name) to use for the bind method.  An
     attempt will be made to translate the supplied service name with
     getservbyname() if it is not strictly numeric.  If that succeeds, the
     given name will be set in the thisservice parameter, and the resolved
     port number will be set in the thisport object parameter.  If the
     supplied value is strictly numeric, and a call to getservbyport can
     resolve a name for the service, the thisservice parameter will be
     updated appropriately.  If the supplied value is not numeric and
     can't be translated, the attempt to set the value will fail.
     Otherwise, this causes the srcaddrlist object parameter to be
     updated, in preparation for an invocation of the bind method
     (possibly implicitly from the connect method).

destservice
     The destination service name (or number) to use for the connect
     method.  An attempt will be made to translate the supplied service
     name with getservbyname().  If that succeeds, or if it fails but the
     supplied value was strictly numeric, the port number will be set in
     the destport object parameter.  If the supplied value is not numeric
     and can't be translated, the attempt to set the value will fail.
     Otherwise, if the desthost parameter has a defined value, this causes
     the dstaddrlist object parameter to be updated, in preparation for an
     invocation of the connect method.

destport
     The destination service number (or name) to use for the connect
     method.  An attempt will be made to translate the supplied service
     name with getservbyname() if it is not strictly numeric.  If that
     succeeds, the given name will be set in the destservice parameter,
     and the resolved port number will be set in the destport parameter.
     If the supplied value is strictly numeric, and a call to
     getservbyport can resolve a name for the service, the destservice
     parameter will be updated appropriately.  If the supplied value is
     not numeric and can't be translated, the attempt to set the value
     will fail.  Otherwise, if the desthost parameter has a defined value,
     this causes the dstaddrlist object parameter to be updated, in
     preparation for an invocation of the connect method.

lcladdr
     The local IP address stashed by the getsockinfo method after a
     successful bind() or connect() call.

lclhost
     The local hostname stashed by the getsockinfo method after a
     successful bind() or connect(), as resolved from the lcladdr object
     parameter.

lclport
     The local port number stashed by the getsockinfo method after a
     successful bind() or connect() call.

lclservice
     The local service name stashed by the getsockinfo method after a
     successful bind() or connect(), as resolved from the lclport object
     parameter.

remaddr
     The remote IP address stashed by the getsockinfo method after a
     successful connect() call.

remhost
     The remote hostname stashed by the getsockinfo method after a
     successful connect() call, as resolved from the remaddr object
     parameter.

remport
     The remote port number stashed by the getsockinfo method after a
     successful connect() call.

remservice
     The remote service name stashed by the getsockinfo method after a
     successful connect() call, as resolved from the remport object
     parameter.

Non-Method Subroutines
----------------------

inet_aton
     Usage:

          $in_addr = inet_aton('192.0.2.1');

     Returns the packed `AF_INET' address in network order, if it is
     validly formed, or undef on error.  This used to be a separate
     implementation in this package, but is now inherited from the Socket
     module.

inet_addr
     A synonym for inet_aton() (for old fogeys like me who forget about
     the new name).  (Yes, I know it's different in C, but in Perl there's
     no need to propagate the old inet_addr() braindamage of being unable
     to handle "255.255.255.255", so I didn't.)

inet_ntoa
     Usage:

          $addr_string = inet_ntoa($in_addr);

     Returns the ASCII representation of the `AF_INET' address provided
     (if possible), or undef on error.  This used to be a separate
     implementation in this package, but is now inherited from the Socket
     module.

htonl
htons
ntohl
ntohs
     As you'd expect, I think.

pack_sockaddr_in
     Usage:

          $connect_address = pack_sockaddr_in($family, $port, $in_addr);
          $connect_address = pack_sockaddr_in($port, $in_addr);

     Returns the packed `struct sockaddr_in' corresponding to the provided
     $family, $port, and $in_addr arguments.  The $family and $port
     arguments must be numbers, and the $in_addr argument must be a packed
     `struct in_addr' such as the trailing elements from perl's
     gethostent() return list.  This differs from the implementation in
     the Socket module in that the `$family' argument is available (though
     optional).

unpack_sockaddr_in
     Usage:

          ($family, $port, $in_addr) = unpack_sockaddr_in($connected_address);

     Returns the address family, port, and packed `struct in_addr' from
     the supplied packed `struct sockaddr_in'.  This is the inverse of
     pack_sockaddr_in().  This differs from the implementation in the
     Socket module in that the `$family' value from the socket address is
     returned (and might not be AF_INET).

INADDR_UNSPEC_GROUP
INADDR_ALLHOSTS_GROUP
INADDR_ALLRTRS_GROUP
INADDR_MAX_LOCAL_GROUP
     Constant routines returning the unspecified local, all hosts,
     all routers, or the maximum possible local IP multicast group
     address, respectively.  These routines return results in the form of
     a packed `struct inaddr' much like the INADDR_ANY result described in
     `INADDR_ANY', see Socket.

IN_CLASSA
IN_CLASSB
IN_CLASSC
IN_CLASSD
IN_MULTICAST
IN_EXPERIMENTAL
IN_BADCLASS
     Usage:

          $boolean = IN_EXPERIMENTAL(INADDR_ALLHOSTS_GROUP);
          $boolean = IN_CLASSA(0x7f000001);

     These routines return the *network class* information for the
     supplied IP address.  Of these, only IN_BADCLASS() and IN_MULTICAST()
     are really useful in today's Internet, since the advent of CIDR
     (classless Internet domain routing).  In particular,
     IN_EXPERIMENTAL() is at the mercy of your vendor's definition.  The
     first example above will be true only on older systems, which almost
     certainly don't support IP multicast anyway.  The argument to any of
     these functions can be either a packed `struct inaddr' such as that
     returned by inet_ntoa() or unpack_sockaddr_in(), or an integer (or
     integer expression) giving an IP address in host byte order.

IPOPT_CLASS
IPOPT_COPIED
IPOPT_NUMBER
     Usage:

          $optnum = IPOPT_NUMBER($option);

     These routines extract information from IP option numbers, as per the
     information on IP options in RFC 791.

...
     Other constants which relate to parts of IP or ICMP headers or
     vendor-defined socket options, as listed in `"Exports"' in this node
     below.

Exports
-------

default
     INADDR_ALLHOSTS_GROUP INADDR_ALLRTRS_GROUP INADDR_ANY
     INADDR_BROADCAST INADDR_LOOPBACK INADDR_MAX_LOCAL_GROUP INADDR_NONE
     INADDR_UNSPEC_GROUP `IPPORT_RESERVED' `IPPORT_USERRESERVED'
     `IPPORT_DYNAMIC' `IPPROTO_EGP' `IPPROTO_EON' `IPPROTO_GGP'
     `IPPROTO_HELLO' `IPPROTO_ICMP' `IPPROTO_IDP' `IPPROTO_IGMP'
     `IPPROTO_IP' `IPPROTO_IPIP' `IPPROTO_MAX' `IPPROTO_PUP' `IPPROTO_RAW'
     `IPPROTO_RSVP' `IPPROTO_TCP' `IPPROTO_TP' `IPPROTO_UDP' htonl htons
     inet_addr inet_aton inet_ntoa ntohl ntohs

exportable
     `DEFTTL' `ICMP_ADVLENMIN' `ICMP_ECHO' `ICMP_ECHOREPLY'
     `ICMP_INFOTYPE' `ICMP_IREQ' `ICMP_IREQREPLY' `ICMP_MASKLEN'
     `ICMP_MASKREPLY' `ICMP_MASKREQ' `ICMP_MAXTYPE' `ICMP_MINLEN'
     `ICMP_PARAMPROB' `ICMP_REDIRECT' `ICMP_REDIRECT_HOST'
     `ICMP_REDIRECT_NET' `ICMP_REDIRECT_TOSHOST' `ICMP_REDIRECT_TOSNET'
     `ICMP_SOURCEQUENCH' `ICMP_TIMXCEED' `ICMP_TIMXCEED_INTRANS'
     `ICMP_TIMXCEED_REASS' `ICMP_TSLEN' `ICMP_TSTAMP' `ICMP_TSTAMPREPLY'
     `ICMP_UNREACH' `ICMP_UNREACH_HOST' `ICMP_UNREACH_NEEDFRAG'
     `ICMP_UNREACH_NET' `ICMP_UNREACH_PORT' `ICMP_UNREACH_PROTOCOL'
     `ICMP_UNREACH_SRCFAIL' IN_BADCLASS IN_CLASSA `IN_CLASSA_HOST'
     `IN_CLASSA_MAX' `IN_CLASSA_NET' `IN_CLASSA_NSHIFT'
     `IN_CLASSA_SUBHOST' `IN_CLASSA_SUBNET' `IN_CLASSA_SUBNSHIFT'
     IN_CLASSB `IN_CLASSB_HOST' `IN_CLASSB_MAX' `IN_CLASSB_NET'
     `IN_CLASSB_NSHIFT' `IN_CLASSB_SUBHOST' `IN_CLASSB_SUBNET'
     `IN_CLASSB_SUBNSHIFT' IN_CLASSC `IN_CLASSC_HOST' `IN_CLASSC_MAX'
     `IN_CLASSC_NET' `IN_CLASSC_NSHIFT' IN_CLASSD `IN_CLASSD_HOST'
     `IN_CLASSD_NET' `IN_CLASSD_NSHIFT' IN_EXPERIMENTAL `IN_LOOPBACKNET'
     IN_MULTICAST `IPFRAGTTL' `IPOPT_CIPSO' IPOPT_CLASS `IPOPT_CONTROL'
     IPOPT_COPIED `IPOPT_DEBMEAS' `IPOPT_EOL' `IPOPT_LSRR' `IPOPT_MINOFF'
     `IPOPT_NOP' IPOPT_NUMBER `IPOPT_OFFSET' `IPOPT_OLEN' `IPOPT_OPTVAL'
     `IPOPT_RESERVED1' `IPOPT_RESERVED2' `IPOPT_RIPSO_AUX' `IPOPT_RR'
     `IPOPT_SATID' `IPOPT_SECURITY' `IPOPT_SECUR_CONFID' `IPOPT_SECUR_EFTO'
     `IPOPT_SECUR_MMMM' `IPOPT_SECUR_RESTR' `IPOPT_SECUR_SECRET'
     `IPOPT_SECUR_TOPSECRET' `IPOPT_SECUR_UNCLASS' `IPOPT_SSRR' `IPOPT_TS'
     `IPOPT_TS_PRESPEC' `IPOPT_TS_TSANDADDR' `IPOPT_TS_TSONLY'
     `IPPORT_TIMESERVER' `IPTOS_LOWDELAY' `IPTOS_PREC_CRITIC_ECP'
     `IPTOS_PREC_FLASH' `IPTOS_PREC_FLASHOVERRIDE' `IPTOS_PREC_IMMEDIATE'
     `IPTOS_PREC_INTERNETCONTROL' `IPTOS_PREC_NETCONTROL'
     `IPTOS_PREC_PRIORITY' `IPTOS_PREC_ROUTINE' `IPTOS_RELIABILITY'
     `IPTOS_THROUGHPUT' `IPTTLDEC' `IPVERSION' `IP_ADD_MEMBERSHIP'
     `IP_DEFAULT_MULTICAST_LOOP' `IP_DEFAULT_MULTICAST_TTL' `IP_DF'
     `IP_DROP_MEMBERSHIP' `IP_HDRINCL' `IP_MAXPACKET' `IP_MAX_MEMBERSHIPS'
     `IP_MF' `IP_MSS' `IP_MULTICAST_IF' `IP_MULTICAST_LOOP'
     `IP_MULTICAST_TTL' `IP_OPTIONS' `IP_RECVDSTADDR' `IP_RECVOPTS'
     `IP_RECVRETOPTS' `IP_RETOPTS' `IP_TOS' `IP_TTL' `MAXTTL'
     `MAX_IPOPTLEN' `MINTTL' `SUBNETSHIFT' pack_sockaddr_in
     unpack_sockaddr_in

tags
     The following :tags are in `%EXPORT_TAGS', with the associated
     exportable values as listed:

    :sockopts
          `IP_HDRINCL' `IP_RECVDSTADDR' `IP_RECVOPTS' `IP_RECVRETOPTS'
          `IP_TOS' `IP_TTL' `IP_ADD_MEMBERSHIP' `IP_DROP_MEMBERSHIP'
          `IP_MULTICAST_IF' `IP_MULTICAST_LOOP' `IP_MULTICAST_TTL'
          `IP_OPTIONS' `IP_RETOPTS'

    :routines
          pack_sockaddr_in unpack_sockaddr_in inet_ntoa inet_aton
          inet_addr htonl ntohl htons ntohs `ICMP_INFOTYPE' IN_BADCLASS
          IN_EXPERIMENTAL IN_MULTICAST IPOPT_CLASS IPOPT_COPIED
          IPOPT_NUMBER

    :icmpvalues
          `ICMP_ADVLENMIN' `ICMP_ECHO' `ICMP_ECHOREPLY' `ICMP_IREQ'
          `ICMP_IREQREPLY' `ICMP_MASKLEN' `ICMP_MASKREPLY' `ICMP_MASKREQ'
          `ICMP_MAXTYPE' `ICMP_MINLEN' `ICMP_PARAMPROB' `ICMP_REDIRECT'
          `ICMP_REDIRECT_HOST' `ICMP_REDIRECT_NET' `ICMP_REDIRECT_TOSHOST'
          `ICMP_REDIRECT_TOSNET' `ICMP_SOURCEQUENCH' `ICMP_TIMXCEED'
          `ICMP_TIMXCEED_INTRANS' `ICMP_TIMXCEED_REASS' `ICMP_TSLEN'
          `ICMP_TSTAMP' `ICMP_TSTAMPREPLY' `ICMP_UNREACH'
          `ICMP_UNREACH_HOST' `ICMP_UNREACH_NEEDFRAG' `ICMP_UNREACH_NET'
          `ICMP_UNREACH_PORT' `ICMP_UNREACH_PROTOCOL'
          `ICMP_UNREACH_SRCFAIL'

    :ipoptions
          `IPOPT_CIPSO' `IPOPT_CONTROL' `IPOPT_DEBMEAS' `IPOPT_EOL'
          `IPOPT_LSRR' `IPOPT_MINOFF' `IPOPT_NOP' `IPOPT_OFFSET'
          `IPOPT_OLEN' `IPOPT_OPTVAL' `IPOPT_RESERVED1' `IPOPT_RESERVED2'
          `IPOPT_RIPSO_AUX' `IPOPT_RR' `IPOPT_SATID' `IPOPT_SECURITY'
          `IPOPT_SECUR_CONFID' `IPOPT_SECUR_EFTO' `IPOPT_SECUR_MMMM'
          `IPOPT_SECUR_RESTR' `IPOPT_SECUR_SECRET' `IPOPT_SECUR_TOPSECRET'
          `IPOPT_SECUR_UNCLASS' `IPOPT_SSRR' `IPOPT_TS' `IPOPT_TS_PRESPEC'
          `IPOPT_TS_TSANDADDR' `IPOPT_TS_TSONLY' `MAX_IPOPTLEN'

    :iptosvalues
          `IPTOS_LOWDELAY' `IPTOS_PREC_CRITIC_ECP' `IPTOS_PREC_FLASH'
          `IPTOS_PREC_FLASHOVERRIDE' `IPTOS_PREC_IMMEDIATE'
          `IPTOS_PREC_INTERNETCONTROL' `IPTOS_PREC_NETCONTROL'
          `IPTOS_PREC_PRIORITY' `IPTOS_PREC_ROUTINE' `IPTOS_RELIABILITY'
          `IPTOS_THROUGHPUT'

    :protocolvalues
          `DEFTTL' INADDR_ALLHOSTS_GROUP INADDR_ALLRTRS_GROUP INADDR_ANY
          INADDR_BROADCAST INADDR_LOOPBACK INADDR_MAX_LOCAL_GROUP
          INADDR_NONE INADDR_UNSPEC_GROUP `IN_LOOPBACKNET'
          `IPPORT_RESERVED' `IPPORT_USERRESERVED' `IPPORT_DYNAMIC'
          `IPPROTO_EGP' `IPPROTO_EON' `IPPROTO_GGP' `IPPROTO_HELLO'
          `IPPROTO_ICMP' `IPPROTO_IDP' `IPPROTO_IGMP' `IPPROTO_IP'
          `IPPROTO_IPIP' `IPPROTO_MAX' `IPPROTO_PUP' `IPPROTO_RAW'
          `IPPROTO_RSVP' `IPPROTO_TCP' `IPPROTO_TP' `IPPROTO_UDP'
          `IPFRAGTTL' `IPTTLDEC' `IPVERSION' `IP_DF' `IP_MAXPACKET' `IP_MF'
          `IP_MSS' `MAXTTL' `MAX_IPOPTLEN' `MINTTL'

    :ipmulticast
          `IP_ADD_MEMBERSHIP' `IP_DEFAULT_MULTICAST_LOOP'
          `IP_DEFAULT_MULTICAST_TTL' `IP_DROP_MEMBERSHIP'
          `IP_MAX_MEMBERSHIPS' `IP_MULTICAST_IF' `IP_MULTICAST_LOOP'
          `IP_MULTICAST_TTL'

    :deprecated
          `IN_CLASSA_HOST' `IN_CLASSA_MAX' `IN_CLASSA_NET'
          `IN_CLASSA_NSHIFT' `IN_CLASSA_SUBHOST' `IN_CLASSA_SUBNET'
          `IN_CLASSA_SUBNSHIFT' `IN_CLASSB_HOST' `IN_CLASSB_MAX'
          `IN_CLASSB_NET' `IN_CLASSB_NSHIFT' `IN_CLASSB_SUBHOST'
          `IN_CLASSB_SUBNET' `IN_CLASSB_SUBNSHIFT' `IN_CLASSC_HOST'
          `IN_CLASSC_MAX' `IN_CLASSC_NET' `IN_CLASSC_NSHIFT'
          `IN_CLASSD_HOST' `IN_CLASSD_NET' `IN_CLASSD_NSHIFT' IN_CLASSA
          IN_CLASSB IN_CLASSC IN_CLASSD `IPPORT_TIMESERVER' `SUBNETSHIFT'

    :ALL
          All of the above exportable items.

NOTES
=====

   Anywhere a service or port argument is used above, the allowed syntax
is either a service name, a port number, or a service name with a
caller-supplied default port number.  Examples are `'echo'', 7, and
`'echo(7)'', respectively.  For a service argument, a bare port number
must be translatable into a service name with getservbyport() or an error
will result.  A service name must be translatable into a port with
getservbyname() or an error will result.  However, a service name with a
default port number will succeed (by using the supplied default) even if
the translation with getservbyname() fails.

THREADING STATUS
================

   This module has been tested with threaded perls, and should be as
thread-safe as perl itself.  (As of 5.005_03 and 5.005_57, that's not all
that safe just yet.)

SEE ALSO
========

   Net::Gen(3), Net::TCP(3), Net::UDP(3)

AUTHOR
======

   Spider Boardman <spider@Orb.Nashua.NH.US>

Perl extension to access network interfaces
*******************************************

NAME
====

   Net::Interface - Perl extension to access network interfaces

SYNOPSIS
========

     use Net::Interface;

     $if = Net::Interface->new ("lo0");
     $if->mtu (1024);

     foreach (Net::Interface->interfaces ()) {print $_->name;}

DESCRIPTION
===========

   Net::Interface is designed to make the use of ifconfig(1) and friends
unnecessary from within Perl.  It provides methods to get at set all the
attributes of an interface, and even create new logical or physical
interfaces (if your O/S supports it).

AUTHOR
======

   Stephen Zander <gibreel@pobox.com>

SEE ALSO
========

   perl(1), ifconfig(8)

Jabber Perl Library
*******************

NAME
====

   Net::Jabber - Jabber Perl Library

SYNOPSIS
========

     Net::Jabber provides a Perl user with access to the Jabber
     Instant Messaging protocol.

     For more information about Jabber visit:

       http://www.jabber.org

DESCRIPTION
===========

     Net::Jabber is a convenient tool to use for any perl scripts
     that would like to utilize the Jabber Instant Messaging
     protocol.  While not a client in and of itself, it provides
     all of the necessary back-end functions to make a CGI client
     or command-line perl client feasible and easy to use.
     Net::Jabber is a wrapper around the rest of the official
     Net::Jabber::xxxxxx packages.

     There is an example script, client.pl, that provides you with
     an example a very simple Jabber client that logs a user in and
     displays any messages they receive.

     There is also an example transport script, transport.pl,
     that shows how to write a transport that gets a message,
     converts the entire message to uppercase, and send it back
     to the sender.

PACKAGES
========

     Net::Jabber::Client - this package contains the code needed to
     communicate with a Jabber server: login, wait for messages,
     send messages, and logout.  It uses XML::Stream to read the
     stream from the server and based on what kind of tag it
     encounters it calls a function to handle the tag.

     Net::Jabber::Component - this package contains the code needed
     to write a server component.  A component is a program tha handles
     the communication between a jabber server and some outside
     program or communications pacakge (IRC, talk, email, etc...)
     With this module you can write a full component in just
     a few lines of Perl.  It uses XML::Stream to communicate with
     its host server and based on what kind of tag it encounters it
     calls a function to handle the tag.  This replaces the Transport
     module as of the new Jabber server v1.1.2.

     Net::Jabber::Transport - *****REMOVED***** this package no
     longer exists.

     Net::Jabber::Protocol - a collection of high-level functions
     that Client and transport use to make their lives easier.
     These functions are included through AUTOLOAD and delegates.

     Net::Jabber::JID - the Jabber IDs consist of three parts:
     user id, server, and resource.  This module gives you access
     to those components without having to parse the string
     yourself.

     Net::Jabber::Message - everything needed to create and read
     a <message/> received from the server.

     Net::Jabber::Presence - everything needed to create and read
     a <presence/> received from the server.

     Net::Jabber::IQ - IQ is a wrapper around a number of modules
     that provide support for the various Info/Query namespaces that
     Jabber recognizes.

     Net::Jabber::Query - this module uses delegates and autoloading
     to provide access to all of the Query modules listed below.

     Net::Jabber::Query::Agent - provides access to the information
     about an agent that the server supports.

     Net::Jabber::Query::Agents - the list of agents, see agent above,
     that the server supports.

     Net::Jabber::Query::Auth - everything needed to authenticate a
     session to the server.

     Net::Jabber::Query::Fneg - feature negoation between the client
     and server.

     Net::Jabber::Query::Oob - support for out of bandwidth file
     transfers.

     Net::Jabber::Query::Register - everything needed to create a new
     Jabber account on the server.

     Net::Jabber::Query::Roster - everything needed to manage and query
     the server side Rosters.

     Net::Jabber::Query::Roster::Item - access to an item from the
     roster.

     Net::Jabber::Query::Time - exchange time information with the
     target recipient (either server or client).

     Net::Jabber::Query::Version - exchange version information with
     the target recipient (either server or client).

     Net::Jabber::X::Delay - specifies the delays that the message
     went through before begin delivered.

     Net::Jabber::X::Oob - out of bandwidth file transers.

     Net::Jabber::X::Roster - support for embedded roster items.

     Net::Jabber::X::Roster::Item - access to the item in a roster.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://perl.jabber.org/

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber Client Library
*********************

NAME
====

   Net::Jabber::Client - Jabber Client Library

SYNOPSIS
========

     Net::Jabber::Client is a module that provides a developer easy access
     to the Jabber Instant Messaging protocol.

DESCRIPTION
===========

     Client.pm uses Protocol.pm to provide enough high level APIs and
     automation of the low level APIs that writing a Jabber Client in
     Perl is trivial.  For those that wish to work with the low level
     you can do that too, but those functions are covered in the
     documentation for each module.

     Net::Jabber::Client provides functions to connect to a Jabber server,
     login, send and receive messages, set personal information, create
     a new user account, manage the roster, and disconnect.  You can use
     all or none of the functions, there is no requirement.

     For more information on how the details for how Net::Jabber is written
     please see the help for Net::Jabber itself.

     For a full list of high level functions available please see
     Net::Jabber::Protocol.

Basic Functions
---------------

     use Net::Jabber;

     $Con = new Net::Jabber::Client();

     $Con->Connect(hostname=>"jabber.org");

     if ($Con->Connected()) {
       print "We are connected to the server...\n";
     }

     #
     # For the list of available function see Net::Jabber::Protocol.
     #

     $Con->Disconnect();

METHODS
=======

Basic Functions
---------------

     new(debuglevel=>0|1|2, - creates the Client object.  debugfile
         debugfile=>string,   should be set to the path for the debug
         debugtime=>0|1)      log to be written.  If set to "stdout"
                              then the debug will go there.  debuglevel
                              controls the amount of debug.  For more
                              information about the valid setting for
                              debuglevel, debugfile, and debugtime see
                              Net::Jabber::Debug.

     Connect(hostname=>string, - opens a connection to the server listed
     	    port=>integer)      in the host name value, on the port
                                 listed.  The defaults for the two are
     				localhost and 5222.

     Disconnect() - closes the connection to the server.

     Connected() - returns 1 if the Transport is connected to the server,
                   and 0 if not.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org.

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber Component Library
************************

NAME
====

   Net::Jabber::Component - Jabber Component Library

SYNOPSIS
========

     Net::Jabber::Component is a module that provides a developer easy access
     to developing server components in the Jabber Instant Messaging protocol.

DESCRIPTION
===========

     Component.pm seeks to provide enough high level APIs and automation of
     the low level APIs that writing a Jabber Component in Perl is trivial.
     For those that wish to work with the low level you can do that too,
     but those functions are covered in the documentation for each module.

     Net::Jabber::Component provides functions to connect to a Jabber server,
     login, send and receive messages, set personal information, create
     a new user account, manage the roster, and disconnect.  You can use
     all or none of the functions, there is no requirement.

     For more information on how the details for how Net::Jabber is written
     please see the help for Net::Jabber itself.

     For a full list of high level functions available please see
     Net::Jabber::Protocol.

Basic Functions
---------------

     use Net::Jabber;

     $Con = new Net::Jabber::Component();

     $Con->Connect(hostname=>"jabber.org",
                   secret=>"foo");

     or

     $Con->Connect(connectiontype=>"exec");

     if ($Con->Connected()) {
       print "We are connected to the server...\n";
     }

     #
     # For the list of available function see Net::Jabber::Protocol.
     #

     $Con->Disconnect();

METHODS
=======

Basic Functions
---------------

     new(debuglevel=>0|1|2, - creates the Component object.  debugfile
         debugfile=>string,   should be set to the path for the debug
         debugtime=>0|1)      log to be written.  If set to "stdout"
                              then the debug will go there.  debuglevel
                              controls the amount of debug.  For more
                              information about the valid setting for
                              debuglevel, debugfile, and debugtime see
                              Net::Jabber::Debug.

     Connect(hostname=>string,       - opens a connection to the server
     	    port=>integer,            based on the value of connectiontype.
     	    secret=>string,           The two valid setings are:
     	    componentname=>string,      accept - TCP/IP remote connection
     	    connectiontype=>string)              (default)
                                         exec   - STDIN/OUT local connection
                                       If accept then it connects to the
                                       server listed in the hostname value,
                                       on the port listed.  The defaults
                                       for the two are localhost and 5222.
                                       The secret is the password needed
                                       to attach the hostname, and the
                                       componentname is the name that
                                       server and clients will know the
                                       component by (both used for security
                                       purposes).
                                       If exec then the module reads from
                                       STDIN and writes to STDOUT.  The
                                       server will start the script at run
                                       time and will restart the script if
                                       it exits or dies.  No secret is
                                       needed since this configuration is
                                       specified by the server admin and so
                                       it is assumed that they trust your
                                       script.

     Disconnect() - closes the connection to the server.

     Connected() - returns 1 if the Component is connected to the server,
                   and 0 if not.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org.

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber Data Library
*******************

NAME
====

   Net::Jabber::Data - Jabber Data Library

SYNOPSIS
========

     Net::Jabber::Data is a companion to the Net::Jabber::XDB module. It
     provides the user a simple interface to set and retrieve all
     parts of a Jabber XDB Data.

DESCRIPTION
===========

     Net::Jabber::Data differs from the other Net::Jabber::* modules in that
     the XMLNS of the data is split out into more submodules under
     Data.  For specifics on each module please view the documentation
     for each Net::Jabber::Data::* module.  The available modules are:

     Net::Jabber::Data::Agent      - Agent Namespace
     Net::Jabber::Data::Agents     - Supported Agents list from server
     Net::Jabber::Data::Auth       - Simple Client Authentication
     Net::Jabber::Data::AutoUpdate - Auto-Update for clients
     Net::Jabber::Data::Filter     - Messaging Filter
     Net::Jabber::Data::Fneg       - Feature Negotiation
     Net::Jabber::Data::Oob        - Out of Bandwidth File Transfers
     Net::Jabber::Data::Register   - Registration requests
     Net::Jabber::Data::Roster     - Buddy List management
     Net::Jabber::Data::Search     - Searching User Directories
     Net::Jabber::Data::Time       - Client Time
     Net::Jabber::Data::Version    - Client Version

     Each of these modules provide Net::Jabber::Data with the functions
     to access the data.  By using delegates and the AUTOLOAD function
     the functions for each namespace is used when that namespace is
     active.

     To access a Data object you must create an XDB object and use the
     access functions there to get to the Data.  To initialize the XDB with
     a Jabber <xdb/> you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the xdb
     you can access the data tag by doing the following:

     use Net::Jabber;

     sub xdbCB {
       my $xdb = new Net::Jabber::XDB(@_);
       my $data = $mesage->GetData();
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new xdb to send to the server:

     use Net::Jabber;

     my $xdb = new Net::Jabber::XDB();
     $data = $xdb->NewData("jabber:xdb:register");

     Now you can call the creation functions for the Data as defined in the
     proper namespaces.  See below for the general <data/> functions, and
     in each data module for those functions.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $xmlns     = $XDB->GetXMLNS();

     $str       = $XDB->GetXML();
     @xdb        = $XDB->GetTree();

Creation functions
------------------

     $Data->SetXMLNS("jabber:xdb:roster");

METHODS
=======

Retrieval functions
-------------------

     GetXMLNS() - returns a string with the namespace of the data that
                  the <xdb/> contains.

     GetXML() - returns the XML string that represents the <xdb/>. This
                is used by the Send() function in Client.pm to send
                this object as a Jabber XDB.

     GetTree() - returns an array that contains the <xdb/> tag in XML::Parser
                 Tree format.

Creation functions
------------------

     SetXMLNS(string) - sets the xmlns of the <data/> to the string.

CUSTOM Data MODULES
===================

     Part of the flexability of this module is that you can write your own
     module to handle a new namespace if you so choose.  The SetDelegates
     function is your way to register the xmlns and which module will
     provide the missing access functions.

     To register your namespace and module, you can either create an XDB
     object and register it once, or you can use the SetDelegates
     function in Client.pm to do it for you:

     my $Client = new Net::Jabber::Client();
     $Client->AddDelegate(namespace=>"blah:blah",
     			 parent=>"Net::Jabber::Data",
     			 delegate=>"Blah::Blah");

       or

     my $Transport = new Net::Jabber::Transport();
     $Transport->AddDelegate(namespace=>"blah:blah",
     			    parent=>"Net::Jabber::Data",
     			    delegate=>"Blah::Blah");

     Once you have the delegate registered you need to define the access
     functions.  Here is a an example module:

     package Blah::Blah;

     sub new {
       my $proto = shift;
       my $class = ref($proto) || $proto;
       my $self = { };
       $self->{VERSION} = $VERSION;
       bless($self, $proto);
       return $self;
     }

     sub SetBlah {
       shift;
       my $self = shift;
       my ($blah) = @_;
       return &Net::Jabber::SetXMLData("single",$self->{DATA},"blah","$blah",{});
     }

     sub GetBlah {
       shift;
       my $self = shift;
       return &Net::Jabber::GetXMLData("value",$self->{DATA},"blah","");
     }

     1;

     Now when you create a new Data object and call GetBlah on that object
     it will AUTOLOAD the above function and handle the request.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber XDB Authentication Module
********************************

NAME
====

   Net::Jabber::Data::Auth - Jabber XDB Authentication Module

SYNOPSIS
========

     Net::Jabber::Data::Auth is a companion to the Net::Jabber::Data module.
     It provides the user a simple interface to set and retrieve all parts
     of a Jabber Authentication data.

DESCRIPTION
===========

     To initialize the Data with a Jabber <xdb/> and then access the auth
     data you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the xdb:

     use Net::Jabber;

     sub xdbCB {
       my $xdb = new Net::Jabber::XDB(@_);
       my $auth = $xdb->GetData();
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new Data auth to send to the server:

     use Net::Jabber;

     $client = new Net::Jabber::Client();
     ...

     $xdb = new Net::Jabber::XDB();
     $auth = $xdb->NewData("jabber:xdb:auth");
     ...

     $client->Send($xdb);

     Using $auth you can call the creation functions below to populate the
     tag before sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $username = $auth->GetUsername();
     $password = $auth->GetPassword();
     $digest   = $auth->GetDigest();
     $resource = $auth->GetResource();

Creation functions
------------------

     $auth->SetAuth(resource=>'Anonymous');
     $auth->SetAuth(username=>'test',
                    password=>'user',
                    resource=>'Test Account');

     $auth->SetUsername('bob');
     $auth->SetPassword('bobrulez');
     $auth->SetDigest('');
     $auth->SetResource('Bob the Great');

Test functions
--------------

     $test = $auth->DefinedUsername();
     $test = $auth->DefinedPassword();
     $test = $auth->DefinedDigest();
     $test = $auth->DefinedResource();

METHODS
=======

Retrieval functions
-------------------

     GetUsername() - returns a string with the username in the <data/>.

     GetPassword() - returns a string with the password in the <data/>.

     GetDigest() - returns a string with the SHA-1 digest in the <data/>.

     GetResource() - returns a string with the resource in the <data/>.

Creation functions
------------------

     SetAuth(username=>string, - set multiple fields in the <xdb/> at one
             password=>string,   time.  This is a cumulative and over
             digest=>string,     writing action.  If you set the "username"
             resource=>string)   twice, the second setting is what is
                                 used.  If you set the password, and then
                                 set the resource then both will be in the
                                 <data/> tag.  For valid settings read
                                 the specific Set functions below.

     SetUsername(string) - sets the username for the account you are
                           trying to connect with.  Leave blank for
                           an anonymous account.

     SetPassword(string) - sets the password for the account you are
                           trying to connect with.  Leave blank for
                           an anonymous account.

     SetDigest(string) - sets the SHA-1 digest for the account you are
                         trying to connect with.  Leave blank for
                         an anonymous account.

     SetResource(string) - sets the resource for the account you are
                           trying to connect with.  Leave blank for
                           an anonymous account.

Test functions
--------------

     DefinedUsername() - returns 1 if <username/> exists in the <xdb/>,
                         0 otherwise.

     DefinedPassword() - returns 1 if <password/> exists in the <xdb/>,
                         0 otherwise.

     DefinedDigest() - returns 1 if <digest/> exists in the <xdb/>,
                       0 otherwise.

     DefinedResource() - returns 1 if <resource/> exists in the <xdb/>,
                         0 otherwise.

AUTHOR
======

   By Ryan Eatmon in July of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber Debug Library
********************

NAME
====

   Net::Jabber::Debug - Jabber Debug Library

SYNOPSIS
========

     Net::Jabber::Debug is a module that provides a developer easy access
     to logging debug information.

DESCRIPTION
===========

     Debug is a helper module for the Net::Jabber modules.  It provides
     the Net::Jabber modules with an object to control where, how, and
     what is logged.

Basic Functions
---------------

     $Debug = new Net::Jabber::Debug();

     $Debug->Init(level=>2,
     	         file=>"stdout",
       	         header=>"MyScript");

     $Debug->Log("Connection established");

METHODS
=======

Basic Functions
---------------

     new(hash) - creates the Debug object.  The hash argument is passed
                 to the Init function.  See that function description
                 below for the valid settings.

     Init(level=>integer,  - initializes the debug object.  The level
          file=>string,      determines the maximum level of debug
          header=>string,    messages to log:
          setdefault=>0|1,     0 - Base level Output (default)
          usedefault=>0|1,     1 - High level API calls
          time=>0|1)           2 - Low level API calls
                               ...
                               N - Whatever you want....
                             The file determines where the debug log
                             goes.  You can either specify a path to
                             a file, or "stdout" (the default).  "stdout"
                             tells Debug to send all of the debug info
                             sent to this object to go to stdout.
                             header is a string that will preappended
                             to the beginning of all log entries.  This
                             makes it easier to see what generated the
                             log entry (default is "Debug").
                             setdefault saves the current filehandle
                             and makes it available for other Debug
                             objects to use.  To use the default set
                             usedefault to 1.  The time parameter
                             specifies whether or not to add a timestamp
                             to the beginning of each logged line.

     LogN(array) - Logs the elements of the array at the corresponding
                   debug level N.  If you pass in a reference to an
                   array or hash then they are printed in a readable
                   way.  (ie... Log0, Log2, Log100, etc...)

EXAMPLE
=======

     $Debug = new Net::Jabber:Debug(level=>2,
                                    header=>"Example");

     $Debug->Log0("test");

     $Debug->Log2("level 2 test");

     $hash{a} = "atest";
     $hash{b} = "btest";

     $Debug->Log1("hashtest",\%hash);

     You would get the following log:

     Example: test
     Example: level 2 test
     Example: hashtest { a=>"atest" b=>"btest" }

     If you has set the level to 1 instead of 2 you would get:

     Example: test
     Example: hashtest { a=>"atest" b=>"btest" }

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org.

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber Dialback Module
**********************

NAME
====

   Net::Jabber::Dialback - Jabber Dialback Module

SYNOPSIS
========

     Net::Jabber::Dialback is a companion to the Net::Jabber::Server
     module.  It provides the user a simple interface to set and retrieve
     all parts of a Jabber Server Dialback.

DESCRIPTION
===========

     To initialize the Dialback with a Jabber <db:*/> you must pass it
     the XML::Parser Tree array.  For example:

     my $dialback = new Net::Jabber::Dialback(@tree);

     There has been a change from the old way of handling the callbacks.
     You no longer have to do the above, a Net::Jabber::Dialback object
     is passed to the callback function for the message:

     use Net::Jabber;

     sub dialback {
       my ($DB) = @_;
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new message to send to the server:

     use Net::Jabber;

     $DB = new Net::Jabber::Dialback("verify");
     $DB = new Net::Jabber::Dialback("result");

     Please see the specific documentation for Net::Jabber::Dialback::Result
     and Net::Jabber::Dialback::Verify

     For more information about the array format being passed to the
     CallBack please read the Net::Jabber::Client documentation.

AUTHOR
======

   By Ryan Eatmon in January of 2001 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber Dialback Result Module
*****************************

NAME
====

   Net::Jabber::Dialback::Result - Jabber Dialback Result Module

SYNOPSIS
========

     Net::Jabber::Dialback::Result is a companion to the Net::Jabber::Dialback
     module.  It provides the user a simple interface to set and retrieve all
     parts of a Jabber Dialback Result.

DESCRIPTION
===========

     To initialize the Result with a Jabber <log/> you must pass it the
     XML::Parse::Tree array.  For example:

     my $dialback = new Net::Jabber::Dialback::Result(@tree);

     There has been a change from the old way of handling the callbacks.
     You no longer have to do the above, a Net::Jabber::Dialback::Result
     object is passed to the callback function for the dialback:

     use Net::Jabber;

     sub dialback {
       my ($Result) = @_;
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new dialback to send to the server:

     use Net::Jabber;

     $Result = new Net::Jabber::Dialback::Result();

     Now you can call the creation functions below to populate the tag before
     sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $to         = $Result->GetTo();
     $from       = $Result->GetFrom();
     $type       = $Result->GetType();

     $data       = $Result->GetData();

     $str        = $Result->GetXML();
     @dialback   = $Result->GetTree();

Creation functions
------------------

     $Result->SetResult(from=>"jabber.org",
     		       to=>"jabber.com",
     		       data=>key);
     $Result->SetTo("jabber.org");
     $Result->SetFrom("jabber.com");
     $Result->SetType("valid");
     $Result->SetData(key);

Test functions
--------------

     $test = $Result->DefinedTo();
     $test = $Result->DefinedFrom();
     $test = $Result->DefinedType();

METHODS
=======

Retrieval functions
-------------------

     GetTo() -  returns a string with server that the <db:result/> is being
                sent to.

     GetFrom() -  returns a string with server that the <db:result/> is being
                  sent from.

     GetType() - returns a string with the type <db:result/> this is.

     GetData() - returns a string with the cdata of the <db:result/>.

     GetXML() - returns the XML string that represents the <db:result/>.
                This is used by the Send() function in Server.pm to send
                this object as a Jabber Dialback Result.

     GetTree() - returns an array that contains the <db:result/> tag
                 in XML::Parser::Tree format.

Creation functions
------------------

     SetResult(to=>string,   - set multiple fields in the <db:result/>
               from=>string,   at one time.  This is a cumulative
               type=>string,   and over writing action.  If you set
               data=>string)   the "from" attribute twice, the second
                               setting is what is used.  If you set
                               the type, and then set the data
                               then both will be in the <db:result/>
                               tag.  For valid settings read the
                               specific Set functions below.

     SetTo(string) - sets the to attribute.

     SetFrom(string) - sets the from attribute.

     SetType(string) - sets the type attribute.  Valid settings are:

     valid
     invalid

     SetData(string) - sets the cdata of the <db:result/>.

Test functions
--------------

     DefinedTo() - returns 1 if the to attribute is defined in the
                   <db:result/>, 0 otherwise.

     DefinedFrom() - returns 1 if the from attribute is defined in the
                     <db:result/>, 0 otherwise.

     DefinedType() - returns 1 if the type attribute is defined in the
                     <db:result/>, 0 otherwise.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber Dialback Verify Module
*****************************

NAME
====

   Net::Jabber::Dialback::Verify - Jabber Dialback Verify Module

SYNOPSIS
========

     Net::Jabber::Dialback::Verify is a companion to the Net::Jabber::Dialback
     module.  It provides the user a simple interface to set and retrieve all
     parts of a Jabber Dialback Verify.

DESCRIPTION
===========

     To initialize the Verify with a Jabber <log/> you must pass it the
     XML::Parse::Tree array.  For example:

     my $dialback = new Net::Jabber::Dialback::Verify(@tree);

     There has been a change from the old way of handling the callbacks.
     You no longer have to do the above, a Net::Jabber::Dialback::Verify
     object is passed to the callback function for the dialback:

     use Net::Jabber;

     sub dialback {
       my ($Verify) = @_;
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new dialback to send to the server:

     use Net::Jabber;

     $Verify = new Net::Jabber::Dialback::Verify();

     Now you can call the creation functions below to populate the tag before
     sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $to         = $Verify->GetTo();
     $from       = $Verify->GetFrom();
     $type       = $Verify->GetType();
     $id         = $Verify->GetID();
     $data       = $Verify->GetData();

     $str        = $Verify->GetXML();
     @dialback   = $Verify->GetTree();

Creation functions
------------------

     $Verify->SetVerify(from=>"jabber.org",
     		       to=>"jabber.com",
     		       id=>id,
     		       data=>key);
     $Verify->SetTo("jabber.org");
     $Verify->SetFrom("jabber.com");
     $Verify->SetType("valid");
     $Verify->SetID(id);
     $Verify->SetData(key);

Test functions
--------------

     $test = $Verify->DefinedTo();
     $test = $Verify->DefinedFrom();
     $test = $Verify->DefinedType();
     $test = $Verify->DefinedID();

METHODS
=======

Retrieval functions
-------------------

     GetTo() -  returns a string with server that the <db:verify/> is being
                sent to.

     GetFrom() -  returns a string with server that the <db:verify/> is being
                  sent from.

     GetType() - returns a string with the type <db:verify/> this is.

     GetID() - returns a string with the id <db:verify/> this is.

     GetData() - returns a string with the cdata of the <db:verify/>.

     GetXML() - returns the XML string that represents the <db:verify/>.
                This is used by the Send() function in Server.pm to send
                this object as a Jabber Dialback Verify.

     GetTree() - returns an array that contains the <db:verify/> tag
                 in XML::Parser::Tree format.

Creation functions
------------------

     SetVerify(to=>string,   - set multiple fields in the <db:verify/>
               from=>string,   at one time.  This is a cumulative
               type=>string,   and over writing action.  If you set
               id=>string,     the "from" attribute twice, the second
               data=>string)   setting is what is used.  If you set
                               the type, and then set the data
                               then both will be in the <db:verify/>
                               tag.  For valid settings read the
                               specific Set functions below.

     SetTo(string) - sets the to attribute.

     SetFrom(string) - sets the from attribute.

     SetType(string) - sets the type attribute.  Valid settings are:

     valid
     invalid

     SetID(string) - sets the id attribute.

     SetData(string) - sets the cdata of the <db:verify/>.

Test functions
--------------

     DefinedTo() - returns 1 if the to attribute is defined in the
                   <db:verify/>, 0 otherwise.

     DefinedFrom() - returns 1 if the from attribute is defined in the
                     <db:verify/>, 0 otherwise.

     DefinedType() - returns 1 if the type attribute is defined in the
                     <db:verify/>, 0 otherwise.

     DefinedID() - returns 1 if the id attribute is defined in the
                     <db:verify/>, 0 otherwise.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber Info/Query Library
*************************

NAME
====

   Net::Jabber::IQ - Jabber Info/Query Library

SYNOPSIS
========

     Net::Jabber::IQ is a companion to the Net::Jabber module. It
     provides the user a simple interface to set and retrieve all {iq}->
     parts of a Jabber IQ.

DESCRIPTION
===========

     Net::Jabber::IQ differs from the other Net::Jabber::* modules in that
     the XMLNS of the query is split out into more submodules under
     IQ.  For specifics on each module please view the documentation
     for each Net::Jabber::Query::* module.  To see the list of avilable
     namspaces and modules see Net::Jabber::Query.

     To initialize the IQ with a Jabber <iq/> you must pass it the
     XML::Parser Tree array.  For example:

     my $iq = new Net::Jabber::IQ(@tree);

     There has been a change from the old way of handling the callbacks.
     You no longer have to do the above, a Net::Jabber::IQ object is passed
     to the callback function for the iq:

     use Net::Jabber;

     sub iq {
       my ($IQ) = @_;
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new iq to send to the server:

     use Net::Jabber;

     $IQ = new Net::Jabber::IQ();
     $IQType = $IQ->NewQuery( type );
     $IQType->SetXXXXX("yyyyy");

     Now you can call the creation functions for the IQ, and for the <query/>
     on the new Query object itself.  See below for the <iq/> functions, and
     in each query module for those functions.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $to         = $IQ->GetTo();
     $toJID      = $IQ->GetTo("jid");
     $from       = $IQ->GetFrom();
     $fromJID    = $IQ->GetFrom("jid");
     $id         = $IQ->GetID();
     $type       = $IQ->GetType();
     $error      = $IQ->GetError();
     $errorCode  = $IQ->GetErrorCode();

     $queryTag   = $IQ->GetQuery();
     $queryTree  = $IQ->GetQueryTree();

     $str        = $IQ->GetXML();
     @iq         = $IQ->GetTree();

Creation functions
------------------

     $IQ->SetIQ(tYpE=>"get",
     	       tO=>"bob@jabber.org",
     	       query=>"info");

     $IQ->SetTo("bob@jabber.org");
     $IQ->SetFrom("me\@jabber.org");
     $IQ->SetType("set");

     $IQ->SetIQ(to=>"bob\@jabber.org",
                errorcode=>403,
                error=>"Permission Denied");
     $IQ->SetErrorCode(403);
     $IQ->SetError("Permission Denied");

     $IQObject = $IQ->NewQuery("jabber:iq:auth");
     $IQObject = $IQ->NewQuery("jabber:iq:roster");

     $iqReply = $IQ->Reply();
     $iqReply = $IQ->Reply("client");
     $iqReply = $IQ->Reply("transport");

Test functions
--------------

     $test = $IQ->DefinedTo();
     $test = $IQ->DefinedFrom();
     $test = $IQ->DefinedID();
     $test = $IQ->DefinedType();
     $test = $IQ->DefinedError();
     $test = $IQ->DefinedErrorCode();

METHODS
=======

Retrieval functions
-------------------

     GetTo()      - returns either a string with the Jabber Identifier,
     GetTo("jid")   or a Net::Jabber::JID object for the person who is
                    going to receive the <iq/>.  To get the JID
                    object set the string to "jid", otherwise leave
                    blank for the text string.

     GetFrom()      -  returns either a string with the Jabber Identifier,
     GetFrom("jid")    or a Net::Jabber::JID object for the person who
                       sent the <iq/>.  To get the JID object set
                       the string to "jid", otherwise leave blank for the
                       text string.

     GetType() - returns a string with the type <iq/> this is.

     GetID() - returns an integer with the id of the <iq/>.

     GetError() - returns a string with the text description of the error.

     GetErrorCode() - returns a string with the code of error.

     GetQuery() - returns a Net::Jabber::Query object that contains the data
                  in the <query/> of the <iq/>.

     GetQueryTree() - returns an XML::Parser::Tree object that contains the
                      data in the <query/> of the <iq/>.

     GetXML() - returns the XML string that represents the <iq/>. This
                is used by the Send() function in Client.pm to send
                this object as a Jabber IQ.

     GetTree() - returns an array that contains the <iq/> tag in XML::Parser
                 Tree format.

Creation functions
------------------

     SetIQ(to=>string|JID,    - set multiple fields in the <iq/> at one
           from=>string|JID,    time.  This is a cumulative and over
           id=>string,          writing action.  If you set the "to"
           type=>string,        attribute twice, the second setting is
           errorcode=>string,   what is used.  If you set the status, and
           error=>string)       then set the priority then both will be in
                                the <iq/> tag.  For valid settings read the
                                specific Set functions below.

     SetTo(string) - sets the to attribute.  You can either pass a string
     SetTo(JID)      or a JID object.  They must be a valid Jabber
                     Identifiers or the server will return an error message.
                     (ie.  jabber:bob@jabber.org, etc...)

     SetFrom(string) - sets the from attribute.  You can either pass a string
     SetFrom(JID)      or a JID object.  They must be a valid Jabber
                       Identifiers or the server will return an error message.
                       (ie.  jabber:bob@jabber.org, etc...)

     SetType(string) - sets the type attribute.  Valid settings are:

     get      request information
     set      set information
     result   results of a get

     SetErrorCode(string) - sets the error code of the <iq/>.

     SetError(string) - sets the error string of the <iq/>.

     NewQuery(string) - creates a new Net::Jabber::Query object with the
                        namespace in the string.  In order for this function
                        to work with a custom namespace, you must define and
                        register that namespace with the IQ module.  For more
                        information please read the documentation for
                        Net::Jabber::Query.  NOTE: Jabber does not support
                        custom IQs at the time of this writing.  This was just
                        including in case they do at some point.

     Reply(type=>string) - creates a new IQ object and populates the to/from
                           fields.  The type will be set in the <iq/>.

Test functions
--------------

     DefinedTo() - returns 1 if the to attribute is defined in the <iq/>,
                   0 otherwise.

     DefinedFrom() - returns 1 if the from attribute is defined in the <iq/>,
                     0 otherwise.

     DefinedID() - returns 1 if the id attribute is defined in the <iq/>,
                   0 otherwise.

     DefinedType() - returns 1 if the type attribute is defined in the <iq/>,
                     0 otherwise.

     DefinedError() - returns 1 if <error/> is defined in the <iq/>,
                      0 otherwise.

     DefinedErrorCode() - returns 1 if the code attribute is defined in
                          <error/>, 0 otherwise.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber JID Module
*****************

NAME
====

   Net::Jabber::JID - Jabber JID Module

SYNOPSIS
========

     Net::Jabber::JID is a companion to the Net::Jabber module.
     It provides the user a simple interface to set and retrieve all
     parts of a Jabber JID (userid on a server).

DESCRIPTION
===========

     To initialize the JID you must pass it the string that represents the
     jid from the Jabber XML packet.  Inside the Jabber modules this is
     done automatically and the JID object is returned instead of a string.
     For example, in the callback function for the Jabber object foo:

     use Net::Jabber;

     sub foo {
       my $foo = new Net::Jabber::Foo(@_);
       my $from = $foo->GetFrom();
       my $JID = new Net::Jabber::JID($from);
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new JID to send to the server:

     use Net::Jabber;

     $JID = new Net::Jabber::JID();

     Now you can call the creation functions below to populate the tag before
     sending it.

Retrieval functions
-------------------

     $userid   = $JID->GetUserID();
     $server   = $JID->GetServer();
     $resource = $JID->GetResource();

     $JID      = $JID->GetJID();
     $fullJID  = $JID->GetJID("full");

Creation functions
------------------

     $JID->SetJID(userid=>"bob",
     		 server=>"jabber.org",
     		 resource=>"Work");

     $JID->SetJID("blue@moon.org/Home");

     $JID->SetUserID("foo");
     $JID->SetServer("bar.net");
     $JID->SetResource("Foo Bar");

METHODS
=======

Retrieval functions
-------------------

     GetUserID() - returns a string with the Jabber userid of the JID.
                   If the string is an address (bob%jabber.org) then
                   the function will return it as an address
                   (bob@jabber.org).

     GetServer() - returns a string with the Jabber server of the JID.

     GetResource() - returns a string with the Jabber resource of the JID.

     GetJID()       - returns a string that represents the JID stored
     GetJID("full")   within.  If the "full" string is specified, then
                      you get the full JID, including Resource, which
                      should be used to send to the server.

Creation functions
------------------

     SetJID(userid=>string,   - set multiple fields in the jid at
            server=>string,     one time.  This is a cumulative
            resource=>string)   and over writing action.  If you set
     SetJID(string)             the "userid" attribute twice, the second
                                setting is what is used.  If you set
                                the server, and then set the resource
                                then both will be in the jid.  If all
                                you pass is a string, then that string
                                is used as the JID.  For valid settings
                                read the specific Set functions below.

     SetUserID(string) - sets the userid.  Must be a valid userid or the
                         server will complain if you try to use this JID
                         to talk to the server.  If the string is an
                         address then it will be converted to the %
                         form suitable for using as a Jabber User ID.

     SetServer(string) - sets the server.  Must be a valid host on the
                         network or the server will not be able to talk
                         to it.

     SetResource(string) - sets the resource of the userid to talk to.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber Key Library
******************

NAME
====

   Net::Jabber::Key - Jabber Key Library

SYNOPSIS
========

     Net::Jabber::Key is a module that provides a developer easy access
     to generating, caching, and comparing keys.

DESCRIPTION
===========

     Key.pm is a helper module for the Net::Jabber::Transport.  When the
     Transport talks to a Client it sends a key and expects to get that
     key back from the Client.  This module provides an API to generate,
     cache, and then compare the key send from the Client.

Basic Functions
---------------

     $Key = new Net::Jabber::Key();

     $key = $Key->Generate();

     $key = $Key->Create("bob\@jabber.org");

     $test = $Key->Compare("bob\@jabber.org","some key");

METHODS
=======

Basic Functions
---------------

     new(debug=>string,       - creates the Key object.  debug should
         debugfh=>FileHandle,   be set to the path for the debug
         debuglevel=>integer)   log to be written.  If set to "stdout"
                                then the debug will go there.  Also, you
                                can specify a filehandle that already
                                exists and use that.  debuglevel controls
                                the amount of debug.  0 is none, 1 is
                                normal, 2 is all.

     Generate() - returns a key in Digest SHA1 form based on the current
                  time and the PID.

     Create(cacheString) - generates a key and caches it with the key
                           of cacheString.  Create returns the key.

     Compare(cacheString, - compares the key stored in the cache under
             keyString)     cacheString with the keyString.  Returns 1
                            if they match, and 0 otherwise.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org.

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber Log Module
*****************

NAME
====

   Net::Jabber::Log - Jabber Log Module

SYNOPSIS
========

     Net::Jabber::Log is a companion to the Net::Jabber module.
     It provides the user a simple interface to set and retrieve all
     parts of a Jabber Log.

DESCRIPTION
===========

     To initialize the Log with a Jabber <log/> you must pass it the
     XML::Parser Tree array.  For example:

     my $log = new Net::Jabber::Log(@tree);

     There has been a change from the old way of handling the callbacks.
     You no longer have to do the above, a Net::Jabber::Log object is passed
     to the callback function for the log:

     use Net::Jabber;

     sub log {
       my ($Log) = @_;
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new log to send to the server:

     use Net::Jabber;

     $Log = new Net::Jabber::Log();

     Now you can call the creation functions below to populate the tag before
     sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $from       = $Log->GetFrom();
     $fromJID    = $Log->GetFrom("jid");
     $type       = $Log->GetType();
     $data       = $Log->GetData();

     $str        = $Log->GetXML();
     @log        = $Log->GetTree();

Creation functions
------------------

     $Log->SetLog(type=>"error",
     		 from=>"users.jabber.org",
     		 data=>"The moon is full... I can't run anymore.");
     $Log->SetFrom("foo.jabber.org");
     $Log->SetType("warn");
     $Log->SetData("I can't find a config file.  Using defaults.");

Test functions
--------------

     $test = $Log->DefinedFrom();
     $test = $Log->DefinedType();

METHODS
=======

Retrieval functions
-------------------

     GetFrom()      -  returns either a string with the Jabber Identifier,
     GetFrom("jid")    or a Net::Jabber::JID object for the person who
                       sent the <log/>.  To get the JID object set
                       the string to "jid", otherwise leave blank for the
                       text string.

     GetType() - returns a string with the type <log/> this is.

     GetData() - returns a string with the cdata of the <log/>.

     GetXML() - returns the XML string that represents the <log/>.
                This is used by the Send() function in Client.pm to send
                this object as a Jabber Log.

     GetTree() - returns an array that contains the <log/> tag
                 in XML::Parser Tree format.

Creation functions
------------------

     SetLog(from=>string|JID, - set multiple fields in the <log/>
            type=>string,       at one time.  This is a cumulative
            data=>string)       and over writing action.  If you set
                                the "from" attribute twice, the second
                                setting is what is used.  If you set
                                the type, and then set the data
                                then both will be in the <log/>
                                tag.  For valid settings read the
                                specific Set functions below.

     SetFrom(string) - sets the from attribute.  You can either pass a string
     SetFrom(JID)      or a JID object.  They must be valid Jabber
                       Identifiers or the server will return an error log.
                       (ie.  jabber:bob@jabber.org/Silent Bob, etc...)

     SetType(string) - sets the type attribute.  Valid settings are:

     notice     general logging
     warn       warning
     alert      critical error (can still run but not
                correctly)
     error      fatal error (cannot run anymore)

     SetData(string) - sets the cdata of the <log/>.

Test functions
--------------

     DefinedFrom() - returns 1 if the from attribute is defined in the
                     <log/>, 0 otherwise.

     DefinedType() - returns 1 if the type attribute is defined in the
                     <log/>, 0 otherwise.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber Message Module
*********************

NAME
====

   Net::Jabber::Message - Jabber Message Module

SYNOPSIS
========

     Net::Jabber::Message is a companion to the Net::Jabber module.
     It provides the user a simple interface to set and retrieve all
     parts of a Jabber Message.

DESCRIPTION
===========

     To initialize the Message with a Jabber <message/> you must pass it the
     XML::Parser Tree array.  For example:

     my $message = new Net::Jabber::Message(@tree);

     There has been a change from the old way of handling the callbacks.
     You no longer have to do the above, a Net::Jabber::Message object is
     passed to the callback function for the message:

     use Net::Jabber;

     sub message {
       my ($Mess) = @_;
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new message to send to the server:

     use Net::Jabber;

     $Mess = new Net::Jabber::Message();

     Now you can call the creation functions below to populate the tag before
     sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $to         = $Mess->GetTo();
     $toJID      = $Mess->GetTo("jid");
     $from       = $Mess->GetFrom();
     $fromJID    = $Mess->GetFrom("jid");
     $resource   = $Mess->GetResource();
     $type       = $Mess->GetType();
     $subject    = $Mess->GetSubject();
     $body       = $Mess->GetBody();
     @body       = $Mess->GetBody("full");
     $thread     = $Mess->GetThread();
     $priority   = $Mess->GetPriority();
     $error      = $Mess->GetError();
     $errCode    = $Mess->GetErrorCode();
     @xTags      = $Mess->GetX();
     @xTags      = $Mess->GetX("my:namespace");
     @xTrees     = $Mess->GetXTrees();
     @xTrees     = $Mess->GetXTrees("my:namespace");

     $str        = $Mess->GetXML();
     @message    = $Mess->GetTree();

     $date       = $Mess->GetTimeStamp();

Creation functions
------------------

     $Mess->SetMessage(TO=>"bob\@jabber.org/Working Bob",
     		      Subject=>"Lunch",
     		      BoDy=>"Let's go grab some lunch!",
     		      priority=>100);
     $Mess->SetTo("test\@jabber.org");
     $Mess->SetFrom("me\@jabber.org");
     $Mess->SetType("groupchat");
     $Mess->SetSubject("This is a test");
     $Mess->SetBody("This is a test of the emergency broadcast system...");
     $Mess->SetThread("AE912B3");
     $Mess->SetPriority(1);

     $Mess->SetMessage(to=>"bob\@jabber.org",
                       errorcode=>403,
                       error=>"Permission Denied");
     $Mess->SetErrorCode(403);
     $Mess->SetError("Permission Denied");

     $X = $Mess->NewX("jabber:x:delay");
     $X = $Mess->NewX("my:namespace");
     $X = $Mess->NewX(Net::Jabber::X::XXXXX);

     $Reply = $Mess->Reply();
     $Reply = $Mess->Reply(template=>"transport-filter");

Test functions
--------------

     $test = $Mess->DefinedTo();
     $test = $Mess->DefinedFrom();
     $test = $Mess->DefinedType();
     $test = $Mess->DefinedSubject();
     $test = $Mess->DefinedBody();
     $test = $Mess->DefinedThread();
     $test = $Mess->DefinedPriority();
     $test = $Mess->DefinedErrorCode();
     $test = $Mess->DefinedError();

METHODS
=======

Retrieval functions
-------------------

     GetTo()      - returns either a string with the Jabber Identifier,
     GetTo("jid")   or a Net::Jabber::JID object for the person who is
                    going to receive the <message/>.  To get the JID
                    object set the string to "jid", otherwise leave
                    blank for the text string.

     GetFrom()      -  returns either a string with the Jabber Identifier,
     GetFrom("jid")    or a Net::Jabber::JID object for the person who
                       sent the <message/>.  To get the JID object set
                       the string to "jid", otherwise leave blank for the
                       text string.

     GetResource() - returns a string with the Jabber Resource of the
                     person who sent the <message/>.

     GetType() - returns a string with the type <message/> this is.

     GetSubject() - returns a string with the subject of the <message/>.

     GetBody(string) - returns the data in the <body/> tag depending on the
                       value of the string passed to it.  The string
                       represents the mark up level to return.

     none   returns a string with just the text of
            the <body/> (default)
     full   returns an XML::Paser::Tree with everything
            in the <body/>

     GetThread() - returns a string that represents the thread this
                   <message/> belongs to.

     GetPriority() - returns an integer with the priority of the <message/>.

     GetError() - returns a string with the data of the <error/> tag.

     GetErrorCode() - returns a string with the code of the <error/> tag.

     GetX(string) - returns an array of Net::Jabber::X objects.  The string
                    can either be empty or the XML Namespace you are looking
                    for.  If empty then GetX returns every <x/> tag in the
                    <message/>.  If an XML Namespace is sent then GetX
                    returns every <x/> tag with that Namespace.

     GetXTrees(string) - returns an array of XML::Parser::Tree objects.  The
                         string can either be empty or the XML Namespace you
                         are looking for.  If empty then GetXTrees returns
                         every <x/> tag in the <message/>.  If an XML
                         Namespace is sent then GetXTrees returns every
                         <x/> tag with that  Namespace.

     GetXML() - returns the XML string that represents the <message/>.
                This is used by the Send() function in Client.pm to send
                this object as a Jabber Message.

     GetTree() - returns an array that contains the <message/> tag
                 in XML::Parser Tree format.

     GetTimeStamp() - returns a string that represents the time this message
                      object was created (and probably received) for sending
                      to the client.  If there is an <x/> delay tag then that
                      time is used to show when the message was sent.

Creation functions
------------------

     SetMessage(to=>string|JID,     - set multiple fields in the <message/>
                from=>string|JID,     at one time.  This is a cumulative
                type=>string,         and over writing action.  If you set
                subject=>string,      the "to" attribute twice, the second
                body=>string,         setting is what is used.  If you set
                thread=>string,       the subject, and then set the body
                priority=>integer,    then both will be in the <message/>
                errorcode=>string,    tag.  For valid settings read the
                error=>string)        specific Set functions below.

     SetTo(string) - sets the to attribute.  You can either pass a string
     SetTo(JID)      or a JID object.  They must be valid Jabber
                     Identifiers or the server will return an error message.
                     (ie.  jabber:bob@jabber.org/Silent Bob, etc...)

     SetFrom(string) - sets the from attribute.  You can either pass a string
     SetFrom(JID)      or a JID object.  They must be valid Jabber
                       Identifiers or the server will return an error message.
                       (ie.  jabber:bob@jabber.org/Silent Bob, etc...)

     SetType(string) - sets the type attribute.  Valid settings are:

     chat           defines a chat style message
     error          defines an error message
     groupchat      defines a chatroom message
     normal         defines a normal message (default)

     SetSubject(string) - sets the subject of the <message/>.

     SetBody(string) - sets the body of the <message/>.

     SetThread(string) - sets the thread of the <message/>.  You should
                         copy this out of the message being replied to so
                         that the thread is maintained.

     SetPriority(integer) - sets the priority of this <message/>.  The
                            higher the priority the more likely the client
                            will deliver the message, even if the user has
                            specified no messages.

     SetErrorCode(string) - sets the error code of the <message/>.

     SetError(string) - sets the error string of the <message/>.

     NewX(string) - creates a new Net::Jabber::X object with the namespace
                    in the string.  In order for this function to work with
                    a custom namespace, you must define and register that
                    namespace with the X module.  For more information
                    please read the documentation for Net::Jabber::X.

     Reply(template=>string,       - creates a new Message object and
           replytransport=>string)   populates the to/from based on
                                     the value of template.  The following
                                     templates are available:

     normal: (default)
          just sets the to/from

     transport-filter:
          the transport will send the
          reply to the address from the
          to.  ie( bob%j.org@transport.j.org
          would send to bob@j.org)

     transport-filter-reply:
          the transport will send the
          reply to the address from the
          to.  ie( bob%j.org@transport.j.org
          would send to bob@j.org) and
          set the from to be
          sender@replytransport.  That
          way a two way filter can occur.

Test functions
--------------

     DefinedTo() - returns 1 if the to attribute is defined in the <message/>,
                   0 otherwise.

     DefinedFrom() - returns 1 if the from attribute is defined in the
                     <message/>, 0 otherwise.

     DefinedType() - returns 1 if the type attribute is defined in the
                     <message/>, 0 otherwise.

     DefinedSubject() - returns 1 if <subject/> is defined in the <message/>,
                        0 otherwise.

     DefinedBody() - returns 1 if <body/> is defined in the <message/>,
                     0 otherwise.

     DefinedThread() - returns 1 if <thread/> is defined in the <message/>,
                       0 otherwise.

     DefinedPriority() - returns 1 if <priority/> is defined in the <message/>,
                         0 otherwise.

     DefinedErrorCode() - returns 1 if <error/> is defined in the <message/>,
                          0 otherwise.

     DefinedError() - returns 1 if the code attribute is defined in the
                      <error/>, 0 otherwise.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber Presence Module
**********************

NAME
====

   Net::Jabber::Presence - Jabber Presence Module

SYNOPSIS
========

     Net::Jabber::Presence is a companion to the Net::Jabber module.
     It provides the user a simple interface to set and retrieve all
     parts of a Jabber Presence.

DESCRIPTION
===========

     To initialize the Presence with a Jabber <presence/> you must pass it
     the XML::Parser Tree array.  For example:

     my $presence = new Net::Jabber::Presence(@tree);

     There has been a change from the old way of handling the callbacks.
     You no longer have to do the above, a Net::Jabber::Presence object is
     passed to the callback function for the presence:

     use Net::Jabber;

     sub presence {
       my ($Pres) = @_;
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new presence to send to the server:

     use Net::Jabber;

     $Pres = new Net::Jabber::Presence();

     Now you can call the creation functions below to populate the tag before
     sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $to         = $Pres->GetTo();
     $toJID      = $Pres->GetTo("jid");
     $from       = $Pres->GetFrom();
     $fromJID    = $Pres->GetFrom("jid");
     $type       = $Pres->GetType();
     $status     = $Pres->GetStatus();
     $priority   = $Pres->GetPriority();
     $show       = $Pres->GetShow();
     @xTags      = $Pres->GetX();
     @xTags      = $Pres->GetX("my:namespace");
     @xTrees     = $Pres->GetXTrees();
     @xTrees     = $Pres->GetXTrees("my:namespace");

     $str        = $Pres->GetXML();
     @presence   = $Pres->GetTree();

Creation functions
------------------

     $Pres->SetPresence(TYPE=>"online",
     		       StatuS=>"Open for Business",
     		       iCoN=>"normal");
     $Pres->SetTo("bob\@jabber.org");
     $Pres->SetFrom("jojo\@jabber.org");
     $Pres->SetType("unavailable");
     $Pres->SetStatus("Taking a nap");
     $Pres->SetPriority(10);
     $Pres->SetShow("away");

     $X = $Pres->NewX("jabber:x:delay");
     $X = $Pres->NewX("my:namespace");

     $Reply = $Pres->Reply();
     $Reply = $Pres->Reply(type=>"subscribed");

Test functions
--------------

     $test = $Pres->DefinedTo();
     $test = $Pres->DefinedFrom();
     $test = $Pres->DefinedType();
     $test = $Pres->DefinedStatus();
     $test = $Pres->DefinedPriority();
     $test = $Pres->DefinedShow();

METHODS
=======

Retrieval functions
-------------------

     GetTo()      - returns either a string with the Jabber Identifier,
     GetTo("jid")   or a Net::Jabber::JID object for the person who is
                    going to receive the <presence/>.  To get the JID
                    object set the string to "jid", otherwise leave
                    blank for the text string.

     GetFrom()      -  returns either a string with the Jabber Identifier,
     GetFrom("jid")    or a Net::Jabber::JID object for the person who
                       sent the <presence/>.  To get the JID object set
                       the string to "jid", otherwise leave blank for the
                       text string.

     GetType() - returns a string with the type <presence/> this is.

     GetStatus() - returns a string with the current status of the resource.

     GetPriority() - returns an integer with the priority of the resource
                     The default is 0 if there is no priority in this presence.

     GetShow() - returns a string with the state the client should show.

     GetX(string) - returns an array of Net::Jabber::X objects.  The string can
                    either be empty or the XML Namespace you are looking for.
                    If empty then GetX returns every <x/> tag in the
                    <presence/>.  If an XML Namespace is sent then GetX
                    returns every <x/> tag with that Namespace.

     GetXTrees(string) - returns an array of XML::Parser::Tree objects.  The
                         string can either be empty or the XML Namespace you
                         are looking for.  If empty then GetXTrees returns every
                         <x/> tag in the <presence/>.  If an XML Namespace is
                         sent then GetXTrees returns every <x/> tag with that
                         Namespace.

     GetXML() - returns the XML string that represents the <presence/>.
                This is used by the Send() function in Client.pm to send
                this object as a Jabber Presence.

     GetTree() - returns an array that contains the <presence/> tag
                 in XML::Parser Tree format.

Creation functions
------------------

     SetPresence(to=>string|JID     - set multiple fields in the <presence/>
                 from=>string|JID,    at one time.  This is a cumulative
                 type=>string,        and over writing action.  If you set
                 status=>string,      the "to" attribute twice, the second
                 priority=>integer,   setting is what is used.  If you set
                 meta=>string,        the status, and then set the priority
                 icon=>string,        then both will be in the <presence/>
                 show=>string,        tag.  For valid settings read the
                 loc=>string)         specific Set functions below.

     SetTo(string) - sets the to attribute.  You can either pass a string
     SetTo(JID)      or a JID object.  They must be valid Jabber
                     Identifiers or the server will return an error message.
                     (ie.  jabber:bob@jabber.org/Silent Bob, etc...)

     SetFrom(string) - sets the from attribute.  You can either pass a string
     SetFrom(JID)      or a JID object.  They must be valid Jabber
                       Identifiers or the server will return an error message.
                       (ie.  jabber:bob@jabber.org/Silent Bob, etc...)

     SetType(string) - sets the type attribute.  Valid settings are:

     available       available to receive messages; default
     unavailable     unavailable to receive anything
     subscribe       ask the recipient to subscribe you
     subscribed      tell the sender they are subscribed
     unsubscribe     ask the recipient to unsubscribe you
     unsubscribed    tell the sender they are unsubscribed
     probe           probe

     SetStatus(string) - sets the status tag to be whatever string the user
                         wants associated with that resource.

     SetPriority(integer) - sets the priority of this resource.  The highest
                            resource attached to the jabber account is the
                            one that receives the messages.

     SetShow(string) - sets the name of the default symbol to display for this
                       resource.

     NewX(string) - creates a new Net::Jabber::X object with the namespace
                    in the string.  In order for this function to work with
                    a custom namespace, you must define and register that
                    namespace with the X module.  For more information
                    please read the documentation for Net::Jabber::X.

     Reply(type=>string) - creates a new Presence object and populates
                           the to/from fields.  The type will be set in
                           the <presence/>.

Test functions
--------------

     DefinedTo() - returns 1 if the to attribute is defined in the <presence/>,
                   0 otherwise.

     DefinedFrom() - returns 1 if the from attribute is defined in the
                     <presence/>, 0 otherwise.

     DefinedType() - returns 1 if the type attribute is defined in the
                     <presence/>, 0 otherwise.

     DefinedStatus() - returns 1 if <status/> is defined in the <presence/>,
                       0 otherwise.

     DefinedPriority() - returns 1 if <priority/> is defined in the
                         <presence/>, 0 otherwise.

     DefinedShow() - returns 1 if <show/> is defined in the <presence/>,
                     0 otherwise.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber Protocol Library
***********************

NAME
====

   Net::Jabber::Protocol - Jabber Protocol Library

SYNOPSIS
========

     Net::Jabber::Protocol is a module that provides a developer easy access
     to the Jabber Instant Messaging protocol.  It provides high level functions
     to both Net::Jabber::Client and Net::Jabber::Transport.  These functions
     are automatically indluded in those modules through AUTOLOAD and delegates.

DESCRIPTION
===========

     Protocol.pm seeks to provide enough high level APIs and automation of
     the low level APIs that writing a Jabber Client/Transport in Perl is
     trivial.  For those that wish to work with the low level you can do
     that too, but those functions are covered in the documentation for
     each module.

     Net::Jabber::Protocol provides functions to login, send and receive
     messages, set personal information, create a new user account, manage
     the roster, and disconnect.  You can use all or none of the functions,
     there is no requirement.

     For more information on how the details for how Net::Jabber is written
     please see the help for Net::Jabber itself.

     For more information on writing a Client see Net::Jabber::Client.

     For more information on writing a Transport see Net::Jabber::Transport.

Basic Functions
---------------

     use Net::Jabber;

     $Con = new Net::Jabber::Client();            # From Net::Jabber::Client
     $status = $Con->Connect(name=>"jabber.org"); #

     or

     $Con = new Net::Jabber::Transport();         #
     $status = $Con->Connect(name=>"jabber.org",  # From Net::Jabber::Transport
     			    secret=>"bob");      #

     $Con->SetCallBacks(send=>\&sendCallBack,
     		       receive=>\&receiveCallBack,
     		       message=>\&messageCallBack,
     		       iq=>\&handleTheIQTag);

     $error = $Con->GetErrorCode();
     $Con->SetErrorCode("Timeout limit reached");

     $Con->Process();
     $Con->Process(5);

     $Con->Send($object);
     $Con->Send("<tag>XML</tag>");

     $Con->Disconnect();

ID Functions
------------

     $id         = $Con->SendWithID($sendObj);
     $id         = $Con->SendWithID("<tag>XML</tag>");
     $receiveObj = $Con->SendAndReceiveWithID($sendObj);
     $receiveObj = $Con->SendAndReceiveWithID("<tag>XML</tag>");
     $yesno      = $Con->ReceivedID($id);
     $receiveObj = $Con->GetID($id);
     $receiveObj = $Con->WaitForID($id);

Namespace Functions
-------------------

     $Con->AddDelegate(parentttype=>"query",
                       namespace=>"foo::bar",
                       parent=>"Foo::Bar");

     $Con->AddDelegate(parenttype=>"x",
     		      namespace=>"foo::bar::bob",
     		      parent=>"Foo::Bar",
     		      delegate=>"Foo::Bar::Bob");

Message Functions
-----------------

     $Con->MessageSend(to=>"bob@jabber.org",
     		      subject=>"Lunch",
     		      body=>"Let's go grab some...\n";
     		      thread=>"ABC123",
     		      priority=>10);

Presence Functions
------------------

     $Con->PresenceSend();

Subscription Functions
----------------------

     $Con->Subscription(type=>"subscribe",
     		       to=>"bob@jabber.org");

     $Con->Subscription(type=>"unsubscribe",
     		       to=>"bob@jabber.org");

     $Con->Subscription(type=>"subscribed",
     		       to=>"bob@jabber.org");

     $Con->Subscription(type=>"unsubscribed",
     		       to=>"bob@jabber.org");

PresenceDB Functions
--------------------

     $Con->PresenceDBParse(Net::Jabber::Presence);

     $Con->PresenceDBDelete("bob\@jabber.org");
     $Con->PresenceDBDelete(Net::Jabber::JID);

     $presence  = $Con->PresenceDBQuery("bob\@jabber.org");
     $presence  = $Con->PresenceDBQuery(Net::Jabber::JID);

     @resources = $Con->PresenceDBResources("bob\@jabber.org");
     @resources = $Con->PresenceDBResources(Net::Jabber::JID);

IQ  Functions
-------------

IQ::Agents Functions
--------------------

     %agents = $Con->AgentsGet();
     %agents = $Con->AgentsGet(to=>"transport.jabber.org");

IQ::Auth Functions
------------------

     @result = $Con->AuthSend();
     @result = $Con->AuthSend(username=>"bob",
     			     password=>"bobrulez",
     			     resource=>"Bob");

IQ::Register Functions
----------------------

     %hash   = $Con->RegisterRequest();
     %hash   = $Con->RegisterRequest(to=>"transport.jabber.org");

     @result = $Con->RegisterSend(usersname=>"newuser",
     				 resource=>"New User",
     				 password=>"imanewbie",
                                  email=>"newguy@new.com",
                                  key=>"some key");

IQ::Roster Functions
--------------------

     %roster = $Con->RosterParse($iq);
     %roster = $Con->RosterGet();
     $Con->RosterAdd(jid=>"bob\@jabber.org",
     		    name=>"Bob");
     $Con->RosterRemove(jid=>"bob@jabber.org");

IQ::Search Functions
--------------------

     %fields = $Con->SearchRequest();
     %fields = $Con->SearchRequest(to=>"users.jabber.org");

     $Con->SearchSend(name=>"",
                      first=>"Bob",
                      last=>"",
                      nick=>"bob",
                      email=>"",
                      key=>"som key");

IQ::Time Functions
------------------

     $Con->TimeQuery();
     $Con->TimeQuery(to=>"bob@jabber.org");

     %result = $Con->TimeQuery(waitforid=>1);
     %result = $Con->TimeQuery(to=>"bob@jabber.org",
     			      waitforid=>1);

     $Con->TimeSend(to=>"bob@jabber.org");

IQ::Version Functions
---------------------

     $Con->VersionQuery();
     $Con->VersionQuery(to=>"bob@jabber.org");

     %result = $Con->VersionQuery(waitforid=>1);
     %result = $Con->VersionQuery(to=>"bob@jabber.org",
     				 waitforid=>1);

     $Con->VersionSend(to=>"bob@jabber.org",
                       name=>"Net::Jabber",
                       ver=>"1.0a",
                       os=>"Perl");

X Functions
-----------

     $Con->SXPMSend(to=>'bob@jabber.org',
                    type=>'chat',
                    boardheight=>400,
                    boardwidth=>400,
                    map=>{ '#'=>'',
                           ' '=>'None',
                           'a'=>'#FFFFFF',
                           'b'=>'#FF0000',
                           ...
                         }
                    data=>"4 .3 . 2 .2  .3 .4 ",
                    datawidth=>5
                   );

METHODS
=======

Basic Functions
---------------

     GetErrorCode() - returns a string that will hopefully contain some
                      useful information about why a function returned
                      an undef to you.

     SetErrorCode(string) - set a useful error message before you return
                            an undef to the caller.

     SetCallBacks(message=>function,  - sets the callback functions for
                  presence=>function,   the top level tags listed.  The
     		 iq=>function,         available tags to look for are
                  send=>function,       <message/>, <presence/>, and
                  receive=>function)    <iq/>.  If a packet is received
                                        with an ID which is found in the
                                        registerd ID list (see RegisterID
                                        below) then it is not sent to
                                        these functions, instead it
                                        is inserted into a LIST and can
                                        be retrieved by some functions
                                        we will mention later.

     Process(integer) - takes the timeout period as an argument.  If no
                        timeout is listed then the function blocks until
                        a packet is received.  Otherwise it waits that
                        number of seconds and then exits so your program
                        can continue doing useful things.  NOTE: This is
                        important for GUIs.  You need to leave time to
                        process GUI commands even if you are waiting for
                        packets.

     IMPORTANT: You need to check the output of every
     Process.  If you get an undef or "" then the
     connection died and you should behave accordingly.

     Send(object) - takes either a Net::Jabber::xxxxx object or an XML
     Send(string)   string as an argument and sends it to the server.

ID Functions
------------

     SendWithID(object) - takes either a Net::Jabber::xxxxx object or an
     SendWithID(string)   XML string as an argument, adds the next
                          available ID number and sends that packet to
                          the server.  Returns the ID number assigned.

     SendAndReceiveWithID(object) - uses SendWithID and WaitForID to
     SendAndReceiveWithID(string)   provide a complete way to send and
                                    receive packets with IDs.  Can take
                                    either a Net::Jabber::xxxxx object
                                    or an XML string.  Returns the
                                    proper Net::Jabber::xxxxx object
                                    based on the type of packet received.

     ReceivedID(integer) - returns 1 if a packet has been received with
                           specified ID, 0 otherwise.

     GetID(integer) - returns the proper Net::Jabber::xxxxx object based
                      on the type of packet received with the specified
                      ID.  If the ID has been received the GetID returns
                      0.

     WaitForID(integer) - blocks until a packet with the ID is received.
                          Returns the proper Net::Jabber::xxxxx object
                          based on the type of packet received

     NOTE:  Only <iq/> officially support ids, so sending a <message/>, or
            <presence/> with an id is a risk.  Both clients must support
            this for these functions to work.

Namespace Functions
-------------------

     AddDelegate(parenttype=>string, - this tells the Net::Jabber modules
                 namespace=>string,    about the new namespace.  The
                 parent=>string,       namespaces determines how the xmlns
                 delegate=>string)     looks in the tag.  The parent is
                                       the name of the module to create
                                       when you use this namespace.  The
                                       delegate is only needed if the
                                       parent module uses delegates to
                                       distinguish between namespaces
                                       (like the Net::Jabber::IQ and
                                       Net::Jabber::X modules do).  The
                                       delegate must be a valid Perl
                                       Module.  The parenttype specifies
                                       the type of namespace this is in
                                       the Jabber world.  (Added to allow
                                       namespaces to be reused between
                                       Query, X, and Data.)  The current
                                       valid settings for parenttype are:
                                         query     for <iq/> queries
                                         x         for <x/> packets
                                         data      for <xdb/> data
                                       The way to determine which one
                                       to use is figure out which one
                                       of the above best fits the mode
                                       that you are using this namespace
                                       in.

Message Functions
-----------------

     MessageSend(hash) - takes the hash and passes it to SetMessage in
                         Net::Jabber::Message (refer there for valid
                         settings).  Then it sends the message to the
                         server.

Presence Functions
------------------

     PresenceSend() - sends an empty Presence to the server to tell it
                      that you are available

Subscription Functions
----------------------

     Subscription(hash) - taks the hash and passes it to SetPresence in
                          Net::Jabber::Presence (refer there for valid
                          settings).  Then it sends the subscription to
                          server.

     The valid types of subscription are:

     subscribe    - subscribe to JID's presence
     unsubscribe  - unsubscribe from JID's presence
     subscribed   - response to a subscribe
     unsubscribed - response to an unsubscribe

PresenceDB Functions
--------------------

     PresenceDBParse(Net::Jabber::Presence) - for every presence that you
                                              receive pass the Presence
                                              object to the DB so that
                                              it can track the resources
                                              and priorities for you.
                                              Returns either the presence
                                              passed in, if it not able
                                              to parsed for the DB, or the
                                              current presence as found by
                                              the PresenceDBQuery function.

     PresenceDBDelete(string|Net::Jabber::JID) - delete thes JID entry
                                                 from the DB.

     PresenceDBQuery(string|Net::Jabber::JID) - returns the NJ::Presence
                                                that was last received for
                                                the highest priority of this
                                                JID.  You can pass it a
                                                string or a NJ::JID object.

     PresenceDBResources(string|Net::Jabber::JID) - returns an array of
                                                    resources in order
                                                    from highest priority
                                                    to lowest.

IQ Functions
------------

IQ::Agents Functions
--------------------

     AgentsGet(to=>string, - takes all of the information and
     AgentsGet()             builds a Net::Jabber::IQ::Agents packet.
                             It then sends that packet either to the
                             server, or to the specified transport,
                             with an ID and waits for that ID to return.
                             Then it looks in the resulting packet and
                             builds a hash that contains the values
                             of the agent list.  The hash is layed out
                             like this:  (NOTE: the jid is the key to
                             distinguish the various agents)

     $hash{<JID>}->{order} = 4
                 ->{name} = "ICQ Transport"
                 ->{transport} = "ICQ #"
                 ->{description} = "ICQ...blah..."
                 ->{service} = "icq"
                 ->{register} = 1
                 ->{search} = 1
               etc...

     The order field determines the order that
     it came from the server in... in case you
     care.  For more info on the valid fields
     see the Net::Jabber::Query::Agent module.

IQ::Auth Functions
------------------

     AuthSend(username=>string, - takes all of the information and
              password=>string,   builds a Net::Jabber::IQ::Auth packet.
              resource=>string)   It then sends that packet to the
                                  server with an ID and waits for that
                                  ID to return.  Then it looks in
     	                         resulting packet and determines if
     	                         authentication was successful for not.
                                  The array returned from AuthSend looks
                                  like this:
                                    [ type , message ]
                                  If type is "ok" then authentication
                                  was successful, otherwise message
                                  contains a little more detail about the
                                  error.

IQ::Register Functions
----------------------

     RegisterRequest(to=>string) - send an <iq/> request to the specified
     RegisterRequest()             server/transport, if not specified it
                                   sends to the current active server.
                                   The function returns a hash that
                                   contains the required fields.   Here
                                   is an example of the hash:

                                      $hash{old}    - The old way of doing
                                                      registers.
                                      $hash{isntructions} - How to fill out
                                                            the form.
                                      $hash{form}   - The new dynamic forms
                                                      that replace the old
                                                      way of doing things.

     In $hash{form}, the fields that are
     present are the required fields the
     server needs.

     RegisterSend(hash) - takes the contents of the hash and passes it
     	                 to the SetRegister function in the module
                          Net::Jabber::Query::Register.  This function
     	                 returns an array that looks like this:

                             [ type , message ]

     If type is "ok" then registration was
     successful, otherwise message contains a
     little more detail about the error.

IQ::Roster Functions
--------------------

     RosterParse(IQ object) - returns a hash that contains the roster
                              parsed into the following data structure:

     $roster{'bob@jabber.org'}->{name}
                         - Name you stored in the roster

     $roster{'bob@jabber.org'}->{subscription}
                         - Subscription status
                           (to, from, both, none)

     $roster{'bob@jabber.org'}->{ask}
                                           - The ask status from this user
                                             (subscribe, unsubscribe)

     $roster{'bob@jabber.org'}->{groups}
                                           - Array of groups that
                                             bob@jabber.org is in

     RosterGet() - sends an empty Net::Jabber::IQ::Roster tag to the
                   server so the server will send the Roster to the
                   client.  Returns the above hash from RosterParse.

     RosterAdd(hash) - sends a packet asking that the jid be
                       added to the roster.  The hash format
     	              is defined in the SetItem function
                       in the Net::Jabber::Query::Roster::Item
                       module.

     RosterRemove(hash) - sends a packet asking that the jid be
                          removed from the roster.  The hash
     	                 format is defined in the SetItem function
                          in the Net::Jabber::Query::Roster::Item
                          module.

IQ::Search Functions
--------------------

     SearchRequest(to=>string) - send an <iq/> request to the specified
     SearchRequest()             server/transport, if not specified it
                                 sends to the current active server.
                                 The function returns a hash that
                                 contains the required fields.   Here
                                 is an example of the hash:

     $fields{intructions} = "do this..."
                                        $fields{key} = "some key"
                                        $fields{name} = ""
                                        ...

     The fields that are present are the
     required fields the server needs.  If
     the hash is undefined then there was
     an error with the request.

     SearchSend(to=>string|JID, - takes the contents of the hash and
     	       hash)             passes it to the SetSearch function
                                  in the module Net::Jabber::Query::Search.
                                  And then send the packet.

IQ::Time Functions
------------------

     TimeQuery(to=>string,     - asks the jid specified for its local time.
               waitforid=>0|1)   If the to is blank, then it queries the
     TimeQuery()                 server.  Returns a hash with the various
                                 items set if waitforid is set to 1:

     $time{utc}     - Time in UTC
     $time{tz}      - Timezone
     $time{display} - Display string

     TimeSend(to=>string) - sends the current UTC time to the specified
                            jid.

IQ::Version Functions
---------------------

     VersionQuery(to=>string,     - asks the jid specified for its
                  waitforid=>0|1)   client version information.  If the
     VersionQuery()                 to is blank, then it queries the
                                    server.  Returns ahash with the
                                    various items set if waitforid is
                                    set to 1:

     $version{name} - Name
     $version{ver}  - Version
     $version{os}   - Operating System/
                        Platform

     VersionSend(to=>string,   - sends the specified version information
                 name=>string,   to the jid specified in the to.
                 ver=>string,
                 os=>string)

X Functions
-----------

     SXPMSend(to=>string,   - sends the specified sxpm information to the
              type=>string,   jid in the to with the message type being
              hash)           set in the type.  See the Net::Jabber::SXPM
                              module for valid values for the hash.
                              This function returns the Net::Jabber::Message
                              object sent to the jid.

AUTHOR
======

   Revised by Ryan Eatmon in December 1999.

   By Thomas Charron in July of 1999 for http://jabber.org..

   Based on a screenplay by Jeremie Miller in May of 1999 for
http://jabber.org/

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber Query Library
********************

NAME
====

   Net::Jabber::Query - Jabber Query Library

SYNOPSIS
========

     Net::Jabber::Query is a companion to the Net::Jabber::IQ module. It
     provides the user a simple interface to set and retrieve all
     parts of a Jabber IQ Query.

DESCRIPTION
===========

     Net::Jabber::Query differs from the other Net::Jabber::* modules in that
     the XMLNS of the query is split out into more submodules under
     Query.  For specifics on each module please view the documentation
     for each Net::Jabber::Query::* module.  The available modules are:

     Net::Jabber::Query::Agent      - Agent Namespace
     Net::Jabber::Query::Agents     - Supported Agents list from server
     Net::Jabber::Query::Auth       - Simple Client Authentication
     Net::Jabber::Query::AutoUpdate - Auto-Update for clients
     Net::Jabber::Query::Filter     - Messaging Filter
     Net::Jabber::Query::Fneg       - Feature Negotiation
     Net::Jabber::Query::Oob        - Out of Bandwidth File Transfers
     Net::Jabber::Query::Register   - Registration requests
     Net::Jabber::Query::Roster     - Buddy List management
     Net::Jabber::Query::Search     - Searching User Directories
     Net::Jabber::Query::Time       - Client Time
     Net::Jabber::Query::Version    - Client Version

     Each of these modules provide Net::Jabber::Query with the functions
     to access the data.  By using delegates and the AUTOLOAD function
     the functions for each namespace is used when that namespace is
     active.

     To access a Query object you must create an IQ object and use the
     access functions there to get to the Query.  To initialize the IQ with
     a Jabber <iq/> you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the iq
     you can access the query tag by doing the following:

     use Net::Jabber;

     sub iqCB {
       my $iq = new Net::Jabber::IQ(@_);
       my $query = $mesage->GetQuery();
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new iq to send to the server:

     use Net::Jabber;

     my $iq = new Net::Jabber::IQ();
     $query = $iq->NewQuery("jabber:iq:register");

     Now you can call the creation functions for the Query as defined in the
     proper namespaces.  See below for the general <query/> functions, and
     in each query module for those functions.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $xmlns     = $IQ->GetXMLNS();

     $str       = $IQ->GetXML();
     @iq        = $IQ->GetTree();

Creation functions
------------------

     $Query->SetXMLNS("jabber:iq:roster");

METHODS
=======

Retrieval functions
-------------------

     GetXMLNS() - returns a string with the namespace of the query that
                  the <iq/> contains.

     GetXML() - returns the XML string that represents the <iq/>. This
                is used by the Send() function in Client.pm to send
                this object as a Jabber IQ.

     GetTree() - returns an array that contains the <iq/> tag in XML::Parser
                 Tree format.

Creation functions
------------------

     SetXMLNS(string) - sets the xmlns of the <query/> to the string.

CUSTOM Query MODULES
====================

     Part of the flexability of this module is that you can write your own
     module to handle a new namespace if you so choose.  The SetDelegates
     function is your way to register the xmlns and which module will
     provide the missing access functions.

     To register your namespace and module, you can either create an IQ
     object and register it once, or you can use the SetDelegates
     function in Client.pm to do it for you:

     my $Client = new Net::Jabber::Client();
     $Client->AddDelegate(namespace=>"blah:blah",
     			 parent=>"Net::Jabber::Query",
     			 delegate=>"Blah::Blah");

       or

     my $Transport = new Net::Jabber::Transport();
     $Transport->AddDelegate(namespace=>"blah:blah",
     			    parent=>"Net::Jabber::Query",
     			    delegate=>"Blah::Blah");

     Once you have the delegate registered you need to define the access
     functions.  Here is a an example module:

     package Blah::Blah;

     sub new {
       my $proto = shift;
       my $class = ref($proto) || $proto;
       my $self = { };
       $self->{VERSION} = $VERSION;
       bless($self, $proto);
       return $self;
     }

     sub SetBlah {
       shift;
       my $self = shift;
       my ($blah) = @_;
       return &Net::Jabber::SetXMLData("single",$self->{QUERY},"blah","$blah",{});
     }

     sub GetBlah {
       shift;
       my $self = shift;
       return &Net::Jabber::GetXMLData("value",$self->{QUERY},"blah","");
     }

     1;

     Now when you create a new Query object and call GetBlah on that object
     it will AUTOLOAD the above function and handle the request.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber Query Agent Module
*************************

NAME
====

   Net::Jabber::Query::Agent - Jabber Query Agent Module

SYNOPSIS
========

     Net::Jabber::Query::Agent is a companion to the Net::Jabber::Query
     module. It provides the user a simple interface to set and retrieve all
     parts of a Jabber Query Agent.

DESCRIPTION
===========

     To initialize the Agent with a Jabber <iq/> you must pass it the
     XML::Parser Tree array from the module trying to access the <iq/>.
     In the callback function:

     use Net::Jabber;

     sub iqCB {
       my $iq = new Net::Jabber::IQ(@_);
       my $agent = $iq->GetQuery();
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new Agent to send to the server:

     use Net::Jabber;

     $iq = new Net::Jabber::IQ();
     $agent = $iq->NewQuery("jabber:iq:agent");

     Now you can call the creation functions below.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $jid         = $agent->GetJID();
     $name        = $agent->GetName();
     $description = $agent->GetDescription();
     $transport   = $agent->GetTransport();
     $service     = $agent->GetService();
     $register    = $agent->GetRegister();
     $search      = $agent->GetSearch();
     $groupchat   = $agent->GetGroupChat();
     $agents      = $agent->GetAgents();

Creation functions
------------------

     $agent->SetAgent(jid=>"users.jabber.org",
     		     name=>"Jabber User Directory",
     	             description=>"You may register and create a public
                                    searchable profile, and search for
                                    other registered Jabber users.",
     		     service=>"jud",
     		     register=>"",
     		     search=>"");

     $agent->SetJID("icq.jabber.org");
     $agent->SetName("ICQ Transport");
     $agent->SetDescription("This is the ICQ Transport");
     $agent->SetTransport("ICQ#");
     $agent->SetService("icq");
     $agent->SetRegister();
     $agent->SetSearch();
     $agent->SetGroupChat();
     $agent->SetAgents();

Test functions       $test = $agent->DefinedJID();     $test = $agent->DefinedName();     $test = $agent->DefinedDescription();     $test = $agent->DefinedTransport();     $test = $agent->DefinedService();     $test = $agent->DefinedRegister();     $test = $agent->DefinedSearch();     $test = $agent->DefinedGroupChat();     $test = $agent->DefinedAgents();
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

METHODS
=======

Retrieval functions
-------------------

     GetJID() - returns a string with the JID of the agent to send
                messages to.

     GetName() - returns a string with the name of the agent.

     GetDescription() - returns a string with the description of
                        the agent.

     GetTransport() - returns a string with the transport of the agent.

     GetService() - returns a string with the service name of the agent.

     GetRegister() - returns a 1 if the agent supports registering,
                     0 if not.

     GetSearch() - returns a 1 if the agent supports searching, 0 if not.

     GetGroupChat() - returns a 1 if the agent supports groupchat, 0 if not.

     GetAgents() - returns a 1 if the agent supports sub-agents, 0 if not.

Creation functions
------------------

     SetAgent(jid=>string,         - set multiple fields in the <iq/> at one
              name=>string,          time.  This is a cumulative and over
              description=>string,   writing action.  If you set the "jid"
              transport=>string,     attribute twice, the second setting is
              service=>string,       what is used.  If you set the name, and
              register=>string,      then set the search then both will be in
              search=>string,        the <iq/> tag.  For valid settings read the
              groupchat=>string)     specific Set functions below.
              agents=>string)

     SetJID(string) - sets the jid="..." of the agent.

     SetName(string) - sets the <name/> of the agent.

     SetDescription(string) - sets the <description/> of the agent.

     SetTransport(string) - sets the <transport/> of the agent.

     SetService(string) - sets the <service/> of the agent.

     SetRegister() - if the function is called then a <search/> is
                     is put in the <query/> to signify searching is
                     available.

     SetSearch() - if the function is called then a <search/> is
                   is put in the <query/> to signify searching is
                   available.

     SetGroupChat() - if the function is called then a <groupchat/> is
                      is put in the <query/> to signify groupchat is
                      available.

     SetAgents() - if the function is called then a <agents/> is
                   is put in the <query/> to signify sub-agents are
                   available.

Test functions     DefinedJID() - returns 1 if jid is in the parrent tag,                   0 otherwise.
--------------------------------------------------------------------------------------------------------

     DefinedName() - returns 1 if <name/> is in the parent tag,
                     0 otherwise.

     DefinedDescription() - returns 1 if <description/> is in the parent tag,
                            0 otherwise.

     DefinedTransport() - returns 1 if <transport/> is in the parent tag,
                          0 otherwise.

     DefinedService() - returns 1 if <service/> is in the parent tag,
                        0 otherwise.

     DefinedRegister() - returns 1 if <register/> is in the parent tag,
                         0 otherwise.

     DefinedSearch() - returns 1 if <search/> is in the parent tag,
                       0 otherwise.

     DefinedGroupChat() - returns 1 if <groupchat/> is in the parent tag,
                          0 otherwise.

     DefinedAgents() - returns 1 if <agents/> is in the parent tag,
                       0 otherwise.

AUTHOR
======

   By Ryan Eatmon in July of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber Query Agents Module
**************************

NAME
====

   Net::Jabber::Query::Agents - Jabber Query Agents Module

SYNOPSIS
========

     Net::Jabber::Query::Agents is a companion to the Net::Jabber::Query
     module. It provides the user a simple interface to set and retrieve all
     parts of a Jabber Query Agents.

DESCRIPTION
===========

     To initialize the Agents with a Jabber <iq/> you must pass it the
     XML::Parser Tree array from the module trying to access the <iq/>.
     In the callback function:

     use Net::Jabber;

     sub iqCB {
       my $iq = new Net::Jabber::IQ(@_);
       my $agents = $iq->GetQuery();
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new Agents request to send to the server:

     use Net::Jabber;

     $client = new Net::Jabber::Client();

     $iq = new Net::Jabber::IQ();
     $agents = $iq->NewQuery("jabber:iq:agents");

     $client->Send($iq);

     Or you can call the creation functions below before sending.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     @agents      = $agents->GetAgents();
     @agentTreess = $agents->GetAgentTrees();

Creation functions
------------------

     $agent = $agents->NewAgent();
     $agent = $agents->NewAgent(jid=>"icq.jabber.org",
     			       name=>"ICQ Transport",
     			       description=>"This is the ICQ Transport",
     			       transport=>"ICQ#",
     			       service=>"icq",
     			       register=>"",
     			       search=>"");

METHODS
=======

Retrieval functions
-------------------

     GetAgents() - returns an array of Net::Jabber::Query::Agent
                   objects.  For more info on this object see the
                   docs for Net::Jabber::Query::Agent.

     GetAgentTrees() - returns an array of XML::Parser objects that
                       contain the data for each agent.

Creation functions
------------------

     NewAgent(hash) - creates and returns a new Net::Jabber::Query::Agent
                      object.  The argument hash is passed to the SetAgent
                      function.  Check the Net::Jabber::Query::Agent
                      man page for the valid values.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber IQ Authentication Module
*******************************

NAME
====

   Net::Jabber::Query::Auth - Jabber IQ Authentication Module

SYNOPSIS
========

     Net::Jabber::Query::Auth is a companion to the Net::Jabber::Query module.
     It provides the user a simple interface to set and retrieve all parts
     of a Jabber Authentication query.

DESCRIPTION
===========

     To initialize the Query with a Jabber <iq/> and then access the auth
     query you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the iq:

     use Net::Jabber;

     sub iqCB {
       my $iq = new Net::Jabber::IQ(@_);
       my $auth = $iq->GetQuery();
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new Query auth to send to the server:

     use Net::Jabber;

     $client = new Net::Jabber::Client();
     ...

     $iq = new Net::Jabber::IQ();
     $auth = $iq->NewQuery("jabber:iq:auth");
     ...

     $client->Send($iq);

     Using $auth you can call the creation functions below to populate the
     tag before sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $username = $auth->GetUsername();
     $password = $auth->GetPassword();
     $resource = $auth->GetResource();
     $digest   = $auth->GetDigest();
     $hash     = $auth->GetHash();
     $token    = $auth->GetToken();
     $sequence = $auth->GetSequence();

Creation functions
------------------

     $auth->SetAuth(resource=>'Anonymous');
     $auth->SetAuth(username=>'test',
                    password=>'user',
                    resource=>'Test Account');

     $auth->SetUsername('bob');
     $auth->SetPassword('bobrulez');
     $auth->SetResource('Bob the Great');
     $auth->SetDigest('');

     $auth->SetToken('some token');
     $auth->SetSequence(456);

     $auth->SetHash('some hash');

Test functions
--------------

     $test = $auth->DefinedUsername();
     $test = $auth->DefinedPassword();
     $test = $auth->DefinedResource();
     $test = $auth->DefinedDigest();
     $test = $auth->DefinedHash();
     $test = $auth->DefinedToken();
     $test = $auth->DefinedSequence();

METHODS
=======

Retrieval functions
-------------------

     GetUsername() - returns a string with the username in the <query/>.

     GetPassword() - returns a string with the password in the <query/>.

     GetResource() - returns a string with the resource in the <query/>.

     GetDigest() - returns a string with the SHA-1 digest in the <query/>.

     GetHash() - returns a string with the hash in the <query/>.

     GetToken() - returns a string with the token in the <query/>.

     GetSequence() - returns a string with the sequence number in the <query/>.

Creation functions
------------------

     SetAuth(username=>string, - set multiple fields in the <iq/> at one
             password=>string,   time.  This is a cumulative and over
             resource=>string,   writing action.  If you set the "username"
             digest=>string,     twice, the second setting is what is
             hash=>string,       used.  If you set the password, and then
             token=>string,      set the resource then both will be in the
             sequence=>string)   <query/> tag.  For valid settings read
                                 the specific Set functions below.

     SetUsername(string) - sets the username for the account you are
                           trying to connect with.  Leave blank for
                           an anonymous account.

     SetPassword(string) - sets the password for the account you are
                           trying to connect with.  Leave blank for
                           an anonymous account.

     SetResource(string) - sets the resource for the account you are
                           trying to connect with.  Leave blank for
                           an anonymous account.

     SetDigest(string) - sets the SHA-1 digest for the account you are
                         trying to connect with.  Leave blank for
                         an anonymous account.

     SetHash(string) - sets the SHA-1 digest for the account you are
                       trying to connect to using 0k.

     SetToken(string) - sets the value for the token that is to be used
                        for 0k connections.

     SetSequence(string) - sets the sequence number the other side is
                           supposed to use to connect with 0k.

Test functions
--------------

     DefinedUsername() - returns 1 if <username/> exists in the <iq/>,
                         0 otherwise.

     DefinedPassword() - returns 1 if <password/> exists in the <iq/>,
                         0 otherwise.

     DefinedResource() - returns 1 if <resource/> exists in the <iq/>,
                         0 otherwise.

     DefinedDigest() - returns 1 if <digest/> exists in the <iq/>,
                       0 otherwise.

     DefinedHash() - returns 1 if <hash/> exists in the <iq/>,
                     0 otherwise.

     DefinedToken() - returns 1 if <token/> exists in the <iq/>,
                      0 otherwise.

     DefinedSequence() - returns 1 if <sequence/> exists in the <iq/>,
                         0 otherwise.

AUTHOR
======

   By Ryan Eatmon in July of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber IQ AutoUpdate Module
***************************

NAME
====

   Net::Jabber::Query::AutoUpdate - Jabber IQ AutoUpdate Module

SYNOPSIS
========

     Net::Jabber::Query::AutoUpdate is a companion to the Net::Jabber::Query
     module.  It provides the user a simple interface to set and retrieve
     all parts of a Jabber AutoUpdate query.

DESCRIPTION
===========

     To initialize the Query with a Jabber <iq/> and then access the autoupdate
     query you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the iq:

     use Net::Jabber;

     sub iqCB {
       my $iq = new Net::Jabber::IQ(@_);
       my $autoupdate = $iq->GetQuery();
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new Query autoupdate to send to the server:

     use Net::Jabber;

     $client = new Net::Jabber::Client();
     ...

     $iq = new Net::Jabber::IQ();
     $autoupdate = $iq->NewQuery("jabber:iq:autoupdate");
     ...

     $client->Send($iq);

     Using $autoupdate you can call the creation functions below to populate the
     tag before sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $release     = $autoupdate->GetRelease();
     $release     = $autoupdate->GetRelease("beta");
     $release     = $autoupdate->GetRelease("dev");

     @releaseTree = $autoupdate->GetReleaseTree();
     @releaseTree = $autoupdate->GetReleaseTree("beta");
     @releaseTree = $autoupdate->GetReleaseTree("dev");

Creation functions
------------------

     $release = $autoupdate->AddRelease();
     $release = $autoupdate->AddRelease(type=>"beta",
                                        version=>"1.0b",
                                        desc=>"Beta...",
                                        url=>"http://xxx.yyy/zzz.tar.gz",
                                        priority=>"optional");

METHODS
=======

Retrieval functions
-------------------

     GetRelease(string) - returns a Net::Jabber::Query::AutoUpdate::Release
                          object that contains the data for that release.
                          The string determines which release is returned:

                            release - returns the latest stable release
                            beta    - returns the latest beta release
                            dev     - returns the latest dev release in CVS

                          If string is blank or undefined, then the "release"
                          version is returned.

     GetReleaseTree(string) - returns an XML::Parser tree that contains the
                              release specified in string.  If string is
                              empty or undefined then it defaults to
                              "release".

Creation functions
------------------

     AddRelease(type=>string, - created a new Release object and populates
                hash)           it with the hash.  The has is passed to the
                                SetRelease function, check the module for
                                valid settings.  The valid setting for type
                                are:

     release - to indicate the latest stable
               release
     beta    - to indicate the latest beta
               release
     dev     - to indicate the latest dev release
               in CVS

     If type is blank or undefined, then "release"
     is assumed.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber IQ AutoUpdate Release Module
***********************************

NAME
====

   Net::Jabber::Query::AutoUpdate::Release - Jabber IQ AutoUpdate Release
Module

SYNOPSIS
========

     Net::Jabber::Query::AutoUpdate::Release is a companion to the
     Net::Jabber::Query::AutoUpdate module.  It provides the user a simple
     interface to set and retrieve all parts of a Jabber AutoUpdate Release.

DESCRIPTION
===========

     To initialize the Item with a Jabber <iq/> and then access the auth
     query you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the iq:

     use Net::Jabber;

     sub iq {
       my $iq = new Net::Jabber::IQ(@_);
       my $autoupdate = $iq->GetQuery();
       my $release = $roster->GetRelease();
       .
       .
       .
     }

     You now have access to all of the retrieval functions available below.

     To create a new IQ Roster Item to send to the server:

     use Net::Jabber;

     $Client = new Net::Jabber::Client();
     ...

     $iq = new Net::Jabber::IQ();
     $autoupdate = $iq->NewQuery("jabber:iq:autoupdate");
     $release = $roster->AddRelease(type=>"beta");
     ...

     $client->Send($iq);

     Using $release you can call the creation functions below to populate the
     tag before sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $version     = $release->GetVersion();
     $description = $release->GetDesc();
     $url         = $release->GetURL();
     $priority    = $release->GetPriority();

     @release     = $release->GetTree();
     $str          = $release->GetXML();

Creation functions
------------------

     $release->SetRelease(version=>"1.3.2",
     		         desc=>"Bob's Client for Jabber",
     		         url=>"http://www.bobssite.com/client.1.3.2.tar.gz",
     		         priority=>"optional");
     $release->SetVersion('5.6');
     $release->SetDesc('A description of the client');
     $release->SetURL('http://somesite/path/client.tar.gz');
     $release->SetPriority("mandatory");

Test functions
--------------

     $test = $release->DefinedVersion();
     $test = $release->DefinedDesc();
     $test = $release->DefinedURL();
     $test = $release->DefinedPriority();

METHODS
=======

Retrieval functions
-------------------

     GetVersion() - returns a string with the version number of this release.

     GetDesc() - returns a string with the description of this release.

     GetURL() - returns a string with the URL for downloading this release.

     GetPriority() - returns a string with the priority of this release.

     optional  - The user can get it if they want to
     mandatory - The user must get this version

     GetXML() - returns the XML string that represents the <presence/>.
                This is used by the Send() function in Client.pm to send
                this object as a Jabber Presence.

     GetTree() - returns an array that contains the <presence/> tag
                 in XML::Parser Tree format.

Creation functions
------------------

     SetRelease(version=>string,  - set multiple fields in the release
                desc=>string,       at one time.  This is a cumulative
                url=>string,        and overwriting action.  If you
                priority=>string,   set the "url" twice, the second
                                    setting is what is used.  If you set
                                    the desc, and then set the
                                    priority then both will be in the
                                    release tag.  For valid settings
                                    read the specific Set functions below.

     SetVersion(string) - sets the version number of this release.

     SetDesc(string) - sets the description of this release.

     SetURL(string) - sets the url for downloading this release.

     SetPriotity(string) - sets the priority of this release.  If "" or not
                           "optional" or "mandatory" then this defaults to
                           "optional".

Test functions
--------------

     DefinedVersion() - returns 1 if <version/> is defined in the query, 0
                        otherwise.

     DefinedDesc() -  returns 1 if <desc/> is defined in the query, 0
                      otherwise.

     DefinedURL() -  returns 1 if <url/> is defined in the query, 0
                     otherwise.

     DefinedPriority() -  returns 1 if priority is defined in the query, 0
                          otherwise.

AUTHOR
======

   By Ryan Eatmon in July of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber IQ Filter Module
***********************

NAME
====

   Net::Jabber::Query::Filter - Jabber IQ Filter Module

SYNOPSIS
========

     Net::Jabber::Query::Filter is a companion to the Net::Jabber::Query module.
     It provides the user a simple interface to set and retrieve all parts
     of a Jabber IQ Filter query.

DESCRIPTION
===========

     To initialize the IQ with a Jabber <iq/> and then access the filter
     query you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the iq:

     use Net::Jabber;

     sub iq {
       my $iq = new Net::Jabber::IQ(@_);
       my $filter = $iq->GetQuery();
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new IQ filter to send to the server:

     use Net::Jabber;

     $client = new Net::Jabber::Client();
     ...

     $iq = new Net::Jabber::IQ();
     $filter = $iq->NewQuery("jabber:iq:filter");
     ...

     $client->Send($iq);

     Using $filter you can call the creation functions below to populate the
     tag before sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     @rules     = $filter->GetRules();
     @ruleTrees = $filter->GetRuleTrees();

Creation functions
------------------

     $rule   = $filter->AddRule();
     $rule   = $filter->AddRule(jid=>"bob\@jabber.org",
                                name=>"Bob",
                                groups=>["school","friends"]);

METHODS
=======

Retrieval functions
-------------------

     GetRules() - returns an array of Net::Jabber::Query::Filter::Rule objects.
                  These can be modified or accessed with the functions
                  available to them.

     GetRuleTrees() - returns an array of XML::Parser objects that contain
                      the data for each rule.

Creation functions
------------------

     AddRule(hash) - creates and returns a new Net::Jabbber::Query::Filter::Rule
                     object.  The argument hash is passed to the SetRule
                     function.  Check the Net::Jabber::Query::Filter::Rule
                     for valid values.

AUTHOR
======

   By Ryan Eatmon in June of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber IQ Filter Rule Module
****************************

NAME
====

   Net::Jabber::Query::Filter::Rule - Jabber IQ Filter Rule Module

SYNOPSIS
========

     Net::Jabber::Query::Filter::Rule is a companion to the
     Net::Jabber::Query::Filter module.  It provides the user a simple
     interface to set and retrieve all parts of a Jabber Filter Rule.

DESCRIPTION
===========

     To initialize the Rule with a Jabber <iq/> and then access the filter
     query you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the iq:

     use Net::Jabber;

     sub iq {
       my $iq = new Net::Jabber::IQ(@_);
       my $filter = $iq->GetQuery();
       my @rules = $filter->GetRules();
       foreach $rule (@rules) {
         ...
       }
       .
       .
       .
     }

     You now have access to all of the retrieval functions available below.

     To create a new IQ Filter Rule to send to the server:

     use Net::Jabber;

     $Client = new Net::Jabber::Client();
     ...

     $iq = new Net::Jabber::IQ();
     $filter = $iq->NewQuery("jabber:iq:filter");
     $rule = $filter->AddRule();
     ...

     $client->Send($iq);

     Using $rule you can call the creation functions below to populate the
     tag before sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     %conditions  = $rule->GetConditions();
     $body        = $rule->GetBody();
     $from        = $rule->GetFrom();
     $resource    = $rule->GetResource();
     $show        = $rule->GetShow();
     $size        = $rule->GetSize();
     $subject     = $rule->GetSubject();
     $time        = $rule->GetTime();
     $type        = $rule->GetType();
     $unavailable = $rule->GetUnavailable();

     %actions     = $rule->GetActions();
     $drop        = $rule->GetDrop();
     $edit        = $rule->GetEdit();
     $error       = $rule->GetError();
     $reply       = $rule->GetReply();
     $forward     = $rule->GetForward();
     $offline     = $rule->GetOffline();

     $continue    = $rule->GetContinue();

Creation functions
------------------

     $rule->SetRule(unavailable=>1,
                    offline=>1);
     $rule->SetRule(from=>"bob\@jabber.org",
                    forward=>"me\@jabber.org/Pager");
     $rule->SetRule(from=>"ex-wife\@jabber.org",
                    reply=>"I don't want to talk you...");

     $rule->SetBody("free");                              # Future condition
     $rule->SetFrom("bob");                               # Future condition
     $rule->SetResource("Home");                          # Future condition
     $rule->SetShow("dnd");                               # Future condition
     $rule->SetSize(1024);                                # Future condition
     $rule->SetSubject("sex");                            # Future condition
     $rule->SetTime("20000502T01:01:01");                 # Future condition
     $rule->SetType("chat");                              # Future condition
     $rule->SetUnavailable();

     $rule->SetDrop();
     $rule->SetEdit();                                    # Future Action
     $rule->SetError("This JID is not a valid address");
     $rule->SetForward("foo\@bar.com/FooBar");
     $rule->SetOffline();
     $rule->SetReply("I don't want to talk you...");

     $rule->SetContinue();

Defined functions
-----------------

     $test = $rule->DefinedBody();
     $test = $rule->DefinedFrom();
     $test = $rule->DefinedResource();
     $test = $rule->DefinedShow();
     $test = $rule->DefinedSize();
     $test = $rule->DefinedSubject();
     $test = $rule->DefinedTime();
     $test = $rule->DefinedType();
     $test = $rule->DefinedUnavailable();

     $test = $rule->DefinedDrop();
     $test = $rule->DefinedEdit();
     $test = $rule->DefinedError();
     $test = $rule->DefinedForward();
     $test = $rule->DefinedOffline();
     $test = $rule->DefinedReply();

     $test = $rule->DefinedContinue();

METHODS
=======

Retrieval functions
-------------------

     GetConditions() - returns a hash with the condition name and the value
                       of the tag as the value in the hash.  For example:

     $conditions{unavailable} = 1;
     $conditions{resource} = "Pager";
     $conditions{type} = "chat";

     GetBody() - returns the string that the <rule/> uses to match in the body
                 for this condition.
                 **** This condition is still under development ****
                 **** in mod_filter.                            ****

     GetFrom() - returns the string that the <rule/> uses to match in the from
                 for this condition.
                 **** This condition is still under development ****
                 **** in mod_filter.                            ****

     GetResource() - returns the string that the <rule/> uses to match in the
                     resource of the to for this condition.
                     **** This condition is still under development ****
                     **** in mod_filter.                            ****

     GetShow() - returns the string that the <rule/> uses to match in the show
                 for this condition.
                 **** This condition is still under development ****
                 **** in mod_filter.                            ****

     GetSize() - returns the string that the <rule/> uses to match in the size
                 for this condition.
                 **** This condition is still under development ****
                 **** in mod_filter.                            ****

     GetSubject() - returns the string that the <rule/> uses to match in the
                    subject for this condition.
                    **** This condition is still under development ****
                    **** in mod_filter.                            ****

     GetTime() - returns the string that the <rule/> uses to match the time
                 for this condition.
                 **** This condition is still under development ****
                 **** in mod_filter.                            ****

     GetType() - returns the string that the <rule/> uses to match the type
                 for this condition.
                 **** This condition is still under development ****
                 **** in mod_filter.                            ****

     GetUnavailable() - returns 1 if this condition is set, 0 otherwise.
                        This condition is used to specify that you are
                        unavailable.

     GetActions() - returns a hash with the condition name and the value
                    of the tag as the value in the hash.  For example:

                       $actions{reply} = "I'm not in the office right now.";
                       $actions{continue} = 1;

     GetDrop() - returns 1 if the message is to be dropped, 0 otherwise.

     GetEdit() - **** This condition is still under development ****
                 **** in mod_filter.                            ****

     GetError() - returns the string that the <rule/> uses to return in
                  error message.

     GetReply() - returns the string that is sent for this action.

     GetForward() - returns the JID of the account to forward the message
                    to for this action.

     GetOffline() - returns 1 if the message is to go to the offline message
                    list, 0 otherwise.

     GetContinue() - returns 1 if there is a <continue/> tag in the <rule/>,
                     0 otherwise.  This allows you to chain multiple actions
                     in order for one set of conditions.

Creation functions
------------------

     SetRule(body=>string,      - set multiple fields in the <rule/>
             from=>string,        at one time.  This is a cumulative
             resource=>string,    and overwriting action.  If you
             show=>string,        set the "body" twice, the second
             size=>string,        setting is what is used.  If you set
             time=>string,        the show, and then set the
             type=>string,        offline then both will be in the
             unavailable=>0|1,    <rule/> tag.  For valid settings
             edit=>string,        read the specific Set functions below.
             error=>string,
             forward=>string,
             offline=>0|1,
             reply=>string,
             continue=>0|1)

     SetBody(string) - sets the string that the <rule/> uses to match against
                       in the body.

     SetFrom(string) - sets the string that the <rule/> uses to match against
                       in the from.

     SetResource(string) - sets the string that the <rule/> uses to match
                           against in the resource of the from JID.

     SetShow(string) - sets the string that the <rule/> uses to match against
                       in the show.

     SetSize(string) - sets the string that the <rule/> uses to match against
                       for the size of the message.

     SetSubject(string) - sets the string that the <rule/> uses to match against
                          in the subject.

     SetTime(string) - sets the string that the <rule/> uses to match against
                       for the time the message is received.

     SetType(string) - sets the string that the <rule/> uses to match against
                       for the type of message.

     SetUnavailable() - adds an <unavailable/> to the <rule/> to match if you
                        are offline.

     SetDrop() - sets that the <rule/> should drop the message from the queue.

     SetEdit(string) - sets the string that the <rule/> uses to execute the edit
                       action on.

     SetError(string) - sets the string that goes into the error message for
                        this action.

     SetForward(string) - sets the JID that the message is forwarded to for
                          this action.

     SetOffline() - sets that the message goes into the offline queue.

     SetReply(string) - sets the string that goes into the reply message for
                        this action.

     SetContinue() - sets that this <rule/> is continued in the next <rule/>.

Defined functions
-----------------

     DefinedBody() - returns 1 if there is a <body/> tag in the <rule/>,
                     0 otherwise.

     DefinedFrom() - returns 1 if there is a <from/> tag in the <rule/>,
                     0 otherwise.

     DefinedResource() - returns 1 if there is a <resource/> tag in the
                         <rule/>, 0 otherwise.

     DefinedShow() - returns 1 if there is a <show/> tag in the <rule/>,
                     0 otherwise.

     DefinedSize() - returns 1 if there is a <size/> tag in the <rule/>,
                     0 otherwise.

     DefinedSubject() - returns 1 if there is a <subject/> tag in the
                        <rule/>, 0 otherwise.

     DefinedTime() - returns 1 if there is a <time/> tag in the <rule/>,
                     0 otherwise.

     DefinedType() - returns 1 if there is a <type/> tag in the <rule/>,
                     0 otherwise.

     DefinedUnavailable() - returns 1 if there is a <unavailable/> tag
                            in the <rule/>, 0 otherwise.

     DefinedDrop() - returns 1 if there is a <drop/> tag in the <rule/>,
                     0 otherwise.

     DefinedEdit() - returns 1 if there is a <edit/> tag in the <rule/>,
                     0 otherwise.

     DefinedError() - returns 1 if there is a <error/> tag in the <rule/>,
                     0 otherwise.

     DefinedForward() - returns 1 if there is a <forward/> tag in the <rule/>,
                     0 otherwise.

     DefinedOffline() - returns 1 if there is a <offline/> tag in the <rule/>,
                     0 otherwise.

     DefinedReply() - returns 1 if there is a <reply/> tag in the <rule/>,
                     0 otherwise.

     DefinedContinue() - returns 1 if there is a <continue/> tag in the <rule/>,
                     0 otherwise.

AUTHOR
======

   By Ryan Eatmon in June of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber IQ Feature Negotiotation Module
**************************************

NAME
====

   Net::Jabber::Query::Fneg - Jabber IQ Feature Negotiotation Module

SYNOPSIS
========

     Net::Jabber::Query::Fneg is a companion to the Net::Jabber::Query module.
     It provides the user a simple interface to set and retrieve all parts
     of a Jabber Feature Negotiotation query.

DESCRIPTION
===========

     To initialize the IQ with a Jabber <iq/> and then access the fneg
     query you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the iq:

     use Net::Jabber;

     sub iqCB {
       my $iq = new Net::Jabber::IQ(@_);
       my $fneg = $iq->GetQuery();
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new IQ fneg to send to the server:

     use Net::Jabber;

     $client = new Net::Jabber::Client();
     ...

     $iq = new Net::Jabber::IQ();
     $fneg = $iq->NewQuery("jabber:iq:fneg");
     ...

     $client->Send($iq);

     Using $fneg you can call the creation functions below to populate the
     tag before sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions     @namespaces = $auth->GetNS();
-----------------------------------------------------

Creation functions     $auth->AddNS("bar:foo:namespace");
---------------------------------------------------------

METHODS
=======

Retrieval functions     GetNS() - returns an array of namespaces that the <query/> contains.
--------------------------------------------------------------------------------------------

Creation functions     AddNS(string) - adds the single namespace to the list in the <query/>.
---------------------------------------------------------------------------------------------

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber Query Out Of Bandwidth File Transfer Module
**************************************************

NAME
====

   Net::Jabber::Query::Oob - Jabber Query Out Of Bandwidth File Transfer
Module

SYNOPSIS
========

     Net::Jabber::Query::Oob is a companion to the Net::Jabber::Query module.
     It provides the user a simple interface to set and retrieve all
     parts of a Jabber Query Oob.

DESCRIPTION
===========

     To initialize the Oob with a Jabber <iq/> you must pass it the
     XML::Parser Tree array from the module trying to access the <iq/>.
     In the callback function:

     use Net::Jabber;

     sub iqCB {
       my $iq = new Net::Jabber::IQ(@_);
       my $oob = $iq->GetQuery();
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new Oob to send to the server:

     use Net::Jabber;

     $iq = new Net::Jabber::IQ();
     $oob = $iq->NewQuery("jabber:iq:oob");

     Now you can call the creation functions below.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $url  = $oob->GetURL();
     $desc = $oob->GetDesc();

Creation functions
------------------

     $oob->SetOob(UrL=>"http://my.web.server.com/~me/pics/bob.jpg",
     	         desc=>"Picture of Bob, the one and only");

     $oob->SetURL("http://my.web.server.com/~me/pics/bobandme.jpg");
     $oob->SetDesc("Bob and Me at the Open Source conference");

Defined functions
-----------------

     $test = $oob->DefinedURL();
     $test = $oob->DefinedDesc();

METHODS
=======

Retrieval functions
-------------------

     GetURL() - returns a string with the URL of the file being sent Oob.

     GetDesc() - returns a string with the description of the file being
                  sent Oob.

Creation functions
------------------

     SetOob(url=>string,  - set multiple fields in the <iq/> at one
            desc=>string)   time.  This is a cumulative and over
                            writing action.  If you set the "url"
                            attribute twice, the second setting is
                            what is used.  If you set the url, and
                            then set the desc then both will be in
                            the <iq/> tag.  For valid settings read the
                            specific Set functions below.

     SetURL(string) - sets the URL for the file being sent Oob.

     SetDesc(string) - sets the description for the file being sent Oob.

Defined functions
-----------------

     DefinedURL() - returns 1 if <url/> is in the <iq/>, 0 otherwise.

     DefinedDesc() - returns 1 if <desc/> is in the <iq/>, 0 otherwise.

AUTHOR
======

   By Ryan Eatmon in July of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber IQ Registration Module
*****************************

NAME
====

   Net::Jabber::Query::Register - Jabber IQ Registration Module

SYNOPSIS
========

     Net::Jabber::Query::Register is a companion to the Net::Jabber::Query module.
     It provides the user a simple interface to set and retrieve all parts
     of a Jabber IQ Registration query.

DESCRIPTION
===========

     To initialize the IQ with a Jabber <iq/> and then access the register
     query you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the iq:

     use Net::Jabber;

     sub iq {
       my $iq = new Net::Jabber::IQ(@_);
       my $register = $iq->GetQuery();
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new IQ register to send to the server:

     use Net::Jabber;

     $client = new Net::Jabber::Client();
     ...

     $iq = new Net::Jabber::IQ();
     $register = $iq->NewQuery("jabber:iq:register");
     ...

     $client->Send($iq);

     Using $register you can call the creation functions below to populate the
     tag before sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $instructions = $register->GetInstructions();

     $username   = $register->GetUsername();
     $password   = $register->GetPassword();
     $name       = $register->GetName();
     $first      = $register->GetFirst();
     $last       = $register->GetLast();
     $nick       = $register->GetNick();
     $email      = $register->GetEmail();
     $address    = $register->GetAddress();
     $city       = $register->GetCity();
     $state      = $register->GetState();
     $zip        = $register->GetZip();
     $phone      = $register->GetPhone();
     $url        = $register->GetURL();
     $date       = $register->GetDate();
     $misc       = $register->GetMisc();
     $text       = $register->GetText();
     $key        = $register->GetKey();
     $remove     = $register->GetRemove();
     $registered = $register->GetRegistered();

     %fields = $register->GetFields();

Client Creation functions
-------------------------

     $register->SetRegister(username=>'test',
                            password=>'user',
                            name=>'Test Account');

     $register->SetUsername('bob');
     $register->SetPassword('bobrulez');
     $register->SetName('Bob the Great');
     $register->SetFirst('Bob');
     $register->SetLast('Smith');
     $register->SetNick('bobocity');
     $register->SetEmail('bob\@bob.net');
     $register->SetAddress('121 Bob St.');
     $register->SetCity('Bobville');
     $register->SetState('TX');
     $register->SetZip('70000');
     $register->SetPhone('(555)555-5555');
     $register->SetURL('http://www.bob.net');
     $register->SetDate('04/17/2000');
     $register->SetMisc('...');
     $register->SetText('...');
     $register->SetKey('...');
     $register->SetRemove();

Server Creation functions
-------------------------

     $register->SetRegister(instructions=>'Fill out the following fields...',
     			   username=>'',
                            password=>'',
                            name=>'',
     	       	           email=>'');

     $register->SetInstructions('Fill out all of the fields...');

     $register->SetUsername();
     $register->SetPassword();
     $register->SetName();
     $register->SetFirst();
     $register->SetLast();
     $register->SetNick();
     $register->SetEmail();
     $register->SetAddress();
     $register->SetCity();
     $register->SetState();
     $register->SetZip();
     $register->SetPhone();
     $register->SetURL();
     $register->SetDate();
     $register->SetMisc();
     $register->SetText();
     $register->SetKey();
     $register->SetRemove();
     $register->SetRegistered();

Test functions
--------------

     $test = $register->DefinedUsername();
     $test = $register->DefinedPassword();
     $test = $register->DefinedName();
     $test = $register->DefinedFirst();
     $test = $register->DefinedLast();
     $test = $register->DefinedNick();
     $test = $register->DefinedEmail();
     $test = $register->DefinedAddress();
     $test = $register->DefinedCity();
     $test = $register->DefinedState();
     $test = $register->DefinedZip();
     $test = $register->DefinedPhone();
     $test = $register->DefinedURL();
     $test = $register->DefinedDate();
     $test = $register->DefinedMisc();
     $test = $register->DefinedText();
     $test = $register->DefinedKey();
     $test = $register->DefinedRemove();
     $test = $register->DefinedRegistered();

METHODS
=======

Retrieval functions
-------------------

     GetInstructions() - returns a string with the instructions in the <query/>.

     GetUsername() - returns a string with the username in the <query/>.

     GetPassword() - returns a string with the password in the <query/>.

     GetName() - returns a string with the name in the <query/>.

     GetFirst() - returns a string with the fisrt in the <query/>.

     GetLast() - returns a string with the last in the <query/>.

     GetNick() - returns a string with the nick in the <query/>.

     GetEmail() -  returns a string with the email in the <query/>.

     GetAddress() -  returns a string with the address in the <query/>.

     GetCity() -  returns a string with the city in the <query/>.

     GetState() -  returns a string with the state in the <query/>.

     GetZip() -  returns a string with the zip in the <query/>.

     GetPhone() -  returns a string with the phone in the <query/>.

     GetURL() -  returns a string with the URL in the <query/>.

     GetDate() -  returns a string with the date in the <query/>.

     GetMisc() -  returns a string with the misc in the <query/>.

     GetText() -  returns a string with the text in the <query/>.

     GetKey() -  returns a string with the key in the <query/>.

     GetRemove() -  returns a string with the remove in the <query/>.

     GetRegistered() -  returns a string with the registered in the <query/>.

     GetFields() -  returns a hash with the keys being the fields
                    contained in the <query/> and the values the
                    contents of the tags.

Creation functions
------------------

     SetRegister(instructions=>string, - set multiple fields in the <iq/>
     	      username=>string,       at one time.  This is a cumulative
                 password=>string,       and over writing action.  If you
                 name=>string,           set the "username" twice, the second
                 first=>string,          setting is what is used.  If you set
                 last=>string,           the password, and then set the
                 nick=>string,           name then both will be in the
                 email=>string,          <query/> tag.  For valid settings
                 address=>string,        read  the specific Set functions below.
                 city=>string,
                 state=>string,
                 zip=>string,
                 phone=>string,
                 url=>string,
                 date=>string,
                 misc=>string,
                 text=>string,
                 key=>string,
                 remove=>string,
     	      registered=>string)

     SetUsername(string) - sets the username for the account you are
                           trying to create.  Set string to "" to send
                           <username/> for instructions.

     SetPassword(string) - sets the password for the account you are
                           trying to create.  Set string to "" to send
                           <password/> for instructions.

     SetName(string) - sets the name for the account you are
                       trying to create.  Set string to "" to send
                       <name/> for instructions.

     SetFirst(string) - sets the first for the account you are
                       trying to create.  Set string to "" to send
                       <first/> for instructions.

     SetLast(string) - sets the last for the account you are
                       trying to create.  Set string to "" to send
                       <last/> for instructions.

     SetNick(string) - sets the nick for the account you are
                       trying to create.  Set string to "" to send
                       <nick/> for instructions.

     SetEmail(string) - sets the email for the account you are
                        trying to create.  Set string to "" to send
                        <email/> for instructions.

     SetAddress(string) - sets the addess for the account you are
                          trying to create.  Set string to "" to send
                          <address/> for instructions.

     SetCity(string) - sets the city for the account you are
                       trying to create.  Set string to "" to send
                       <city/> for instructions.

     SetState(string) - sets the state for the account you are
                        trying to create.  Set string to "" to send
                        <state/> for instructions.

     SetZip(string) - sets the zip code for the account you are
                      trying to create.  Set string to "" to send
                      <zip/> for instructions.

     SetPhone(string) - sets the phone for the account you are
                        trying to create.  Set string to "" to send
                        <phone/> for instructions.

     SetURL(string) - sets the url for the account you are
                      trying to create.  Set string to "" to send
                      <url/> for instructions.

     SetDate(string) - sets the date for the account you are
                       trying to create.  Set string to "" to send
                       <date/> for instructions.

     SetMisc(string) - sets the misc for the account you are
                       trying to create.  Set string to "" to send
                       <misc/> for instructions.

     SetText(string) - sets the text for the account you are
                       trying to create.  Set string to "" to send
                       <text/> for instructions.

     SetKey(string) - sets the key for the server/transport you are trying
                      to regsiter to.

     SetRemove() - sets the remove for the account you are trying to
                   delete so that the account will be removed from the
                   server/transport.

     SetRegistered() - sets the registered for the account you are trying to
                       create so that the account will know that it is
                       already registered.

Test functions
--------------

     DefinedUsername() - returns 1 if there is a <username/> in the query,
                         0 if not.

     DefinedPassword() - returns 1 if there is a <password/> in the query,
                         0 if not.

     DefinedName() - returns 1 if there is a <name/> in the query,
                     0 if not.

     DefinedFirst() - returns 1 if there is a <first/> in the query,
                     0 if not.

     DefinedLast() - returns 1 if there is a <last/> in the query,
                     0 if not.

     DefinedNick() - returns 1 if there is a <nick/> in the query,
                     0 if not.

     DefinedEmail() - returns 1 if there is a <email/> in the query,
                      0 if not.

     DefinedAddress() - returns 1 if there is a <address/> in the query,
                        0 if not.

     DefinedCity() - returns 1 if there is a <city/> in the query,
                     0 if not.

     DefinedState() - returns 1 if there is a <state/> in the query,
                      0 if not.

     DefinedZip() - returns 1 if there is a <zip/> in the query,
                    0 if not.

     DefinedPhone() - returns 1 if there is a <phone/> in the query,
                      0 if not.

     DefinedURL() - returns 1 if there is a <url/> in the query,
                    0 if not.

     DefinedDate() - returns 1 if there is a <date/> in the query,
                     0 if not.

     DefinedMisc() - returns 1 if there is a <misc/> in the query,
                     0 if not.

     DefinedText() - returns 1 if there is a <text/> in the query,
                     0 if not.

     DefinedKey() - returns 1 if there is a <key/> in the query,
                    0 if not.

     DefinedRemove() - returns 1 if there is a <remove/> in the query,
                       0 if not.

     DefinedRegistered() - returns 1 if there is a <registered/> in the query,
                           0 if not.

AUTHOR
======

   By Ryan Eatmon in July of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber IQ Roster Module
***********************

NAME
====

   Net::Jabber::Query::Roster - Jabber IQ Roster Module

SYNOPSIS
========

     Net::Jabber::Query::Roster is a companion to the Net::Jabber::Query module.
     It provides the user a simple interface to set and retrieve all parts
     of a Jabber IQ Roster query.

DESCRIPTION
===========

     To initialize the IQ with a Jabber <iq/> and then access the roster
     query you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the iq:

     use Net::Jabber;

     sub iq {
       my $iq = new Net::Jabber::IQ(@_);
       my $roster = $iq->GetQuery();
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new IQ roster to send to the server:

     use Net::Jabber;

     $client = new Net::Jabber::Client();
     ...

     $iq = new Net::Jabber::IQ();
     $roster = $iq->NewQuery("jabber:iq:roster");
     ...

     $client->Send($iq);

     Using $roster you can call the creation functions below to populate the
     tag before sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     @items     = $roster->GetItems();
     @itemTrees = $roster->GetItemTrees();

Creation functions
------------------

     $item   = $roster->AddItem();
     $item   = $roster->AddItem(jid=>"bob\@jabber.org",
                                name=>"Bob",
                                groups=>["school","friends"]);

METHODS
=======

Retrieval functions
-------------------

     GetItems() - returns an array of Net::Jabber::Query::Roster::Item objects.
                  These can be modified or accessed with the functions
                  available to them.

     GetItemTrees() - returns an array of XML::Parser objects that contain
                      the data for each item.

Creation functions
------------------

     AddItem(hash) - creates and returns a new Net::Jabbber::Query::Roster::Item
                     object.  The argument hash is passed to the SetItem
                     function.  Check the Net::Jabber::Query::Roster::Item
                     for valid values.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber IQ Roster Item Module
****************************

NAME
====

   Net::Jabber::Query::Roster::Item - Jabber IQ Roster Item Module

SYNOPSIS
========

     Net::Jabber::Query::Roster::Item is a companion to the
     Net::Jabber::Query::Roster module.  It provides the user a simple
     interface to set and retrieve all parts of a Jabber Roster Item.

DESCRIPTION
===========

     To initialize the Item with a Jabber <iq/> and then access the roster
     query you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the iq:

     use Net::Jabber;

     sub iq {
       my $iq = new Net::Jabber::IQ(@_);
       my $roster = $iq->GetQuery();
       my @items = $roster->GetItems();
       foreach $item (@items) {
         ...
       }
       .
       .
       .
     }

     You now have access to all of the retrieval functions available below.

     To create a new IQ Roster Item to send to the server:

     use Net::Jabber;

     $Client = new Net::Jabber::Client();
     ...

     $iq = new Net::Jabber::IQ();
     $roster = $iq->NewQuery("jabber:iq:roster");
     $item = $roster->AddItem();
     ...

     $client->Send($iq);

     Using $Item you can call the creation functions below to populate the
     tag before sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $jid          = $item->GetJID();
     $jidJID       = $item->GetJID("jid");
     $name         = $item->GetName();
     $subscription = $item->GetSubscription();
     $ask          = $item->GetAsk();
     @groups       = $item->GetGroups();

     @item         = $item->GetTree();
     $str          = $item->GetXML();

Creation functions
------------------

     $item->SetItem(jid=>'bob@jabber.org',
     		   name=>'Bob',
     		   subscription=>'both',
     		   groups=>[ 'friends','school' ]);

     $item->SetJID('bob@jabber.org');
     $item->SetName('Bob');
     $item->SetSubscription('both');
     $item->SetAsk('both');
     $item->SetGroups(['friends','school']);

Test functions
--------------

     $test = $item->DefinedJID();
     $test = $item->DefinedName();
     $test = $item->DefinedSubscription();
     $test = $item->DefinedAsk();
     $test = $item->DefinedGroup();

METHODS
=======

Retrieval functions
-------------------

     GetJID()      - returns either a string with the Jabber Identifier,
     GetJID("jid")   or a Net::Jabber::JID object for the person who is
                     listed in this <item/>.  To get the JID object set the
                     string to "jid", otherwise leave blank for the text
                     string.

     GetName() - returns a string with the name of the jabber ID.

     GetSubscription() - returns a string with the current subscription
                         of this <item/>.

     none    means no one is getting <presence/> tags
     to      means we are getting their <presence/>
             but they are not getting ours
     from    means we are not getting their <presence/>
             but they are getting ours
     both    means we are getting their <presence/>
             and they are getting ours
     remove  remove this jid from the roster

     GetAsk() - returns a string with the current ask of this <item/>.
                This is the pending request by you to this JID, usually
                handled by the server.

     GetGroups() - returns an array of strings with the names of the groups
                  that this <item/> belongs to.

     GetXML() - returns the XML string that represents the <presence/>.
                This is used by the Send() function in Client.pm to send
                this object as a Jabber Presence.

     GetTree() - returns an array that contains the <presence/> tag
                 in XML::Parser Tree format.

Creation functions
------------------

     SetItem(jid=>string|JID,      - set multiple fields in the <item/>
             name=>string,           at one time.  This is a cumulative
             subscription=>string,   and overwriting action.  If you
             ask=>string,            set the "ask" twice, the second
             groups=>array)          setting is what is used.  If you set
                                     the name, and then set the
                                     jid then both will be in the
                                     <item/> tag.  For valid settings
                                     read the specific Set functions below.
                                     Note: group does not behave in this
                                     manner.  For each group setting a
                                     new <group/> tag will be created.

     SetJID(string) - sets the Jabber Identifier.  You can either pass a
     SetJID(JID)      string or a JID object.  They must be valid Jabber
                      Identifiers or the server will return an error message.
                      (ie.  jabber:bob@jabber.org/Silent Bob, etc...)

     SetName(string) - sets the name this roster item should show in the
                       roster.

     SetSubscription(string) - sets the subscription that this roster item
                               has.

     SetAsk(string) - sets the ask for the <item/>.

     SetGroups(array) - sets the group for each group in the array.

Test functions
--------------

     DefinedJID() - returns 1 if jid is defined in the <item/>, 0 otherwise.

     DefinedName() - returns 1 if name is defined in the <item/>, 0 otherwise.

     DefinedSubscription() - returns 1 if subscription is defined in the
                             <item/>, 0 otherwise.

     DefinedAsk() - returns 1 if ask is defined in the <item/>, 0 otherwise.

     DefinedGroup() - returns 1 if there is a <group/> tag in the <item/>,
                      0 otherwise.

AUTHOR
======

   By Ryan Eatmon in July of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber IQ Search Module
***********************

NAME
====

   Net::Jabber::Query::Search - Jabber IQ Search Module

SYNOPSIS
========

     Net::Jabber::Query::Search is a companion to the Net::Jabber::Query module.
     It provides the user a simple interface to set and retrieve all parts
     of a Jabber IQ Search query.

DESCRIPTION
===========

     To initialize the IQ with a Jabber <iq/> and then access the search
     query you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the iq:

     use Net::Jabber;

     sub iq {
       my $iq = new Net::Jabber::IQ(@_);
       my $search = $iq->GetQuery();
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new IQ search to send to the server:

     use Net::Jabber;

     $client = new Net::Jabber::Client();
     ...

     $iq = new Net::Jabber::IQ();
     $search = $iq->NewQuery("jabber:iq:search");
     ...

     $client->Send($iq);

     Using $search you can call the creation functions below to populate the
     tag before sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $name         = $search->GetName();
     $first        = $search->GetFirst();
     $given        = $search->GetGiven();
     $last         = $search->GetLast();
     $family       = $search->GetFamily();
     $nick         = $search->GetNick();
     $email        = $search->GetEmail();
     $key          = $search->GetKey();
     $instructions = $search->GetInstructions();

     %fields       = $search->GetFields();

     @items        = $search->GetItems();
     @itemTrees    = $search->GetItemTrees();
     %results      = $search->GetResults();

     $truncated    = $search->GetTruncated();

Creation functions
------------------

     $search->SetSearch(key=>"somekey",
                        name=>"",
                        first=>"",
                        last=>"",
                        nick=>"bob",
                        email=>"");
     $search->SetSearch(instructions=>"Fill in a field to search".
                                      " for any matching Jabber users.",
                        key=>"somekey",
                        name=>"",
                        first=>"",
                        last=>"",
                        nick=>"",
                        email=>"");

     $search->SetInstructions("Fill out the form...");
     $search->SetKey("somekey");
     $search->SetName("");
     $search->SetFirst("Bob");
     $search->SetGiven("Bob");
     $search->SetLast("Smith");
     $search->SetFamily("Smith");
     $search->SetNick("");
     $search->SetEmail("");

     $search->SetTruncated();

     $item   = $search->AddItem();
     $item   = $search->AddItem(jid=>"bob\@jabber.org",
                                name=>"Bob Smith",
     			       first=>"Bob",
     			       last=>"Smith",
     			       nick=>"bob");

Test fucntions
--------------

     $test = $search->DefinedName();
     $test = $search->DefinedFirst();
     $test = $search->DefinedGiven();
     $test = $search->DefinedLast();
     $test = $search->DefinedFamily();
     $test = $search->DefinedNick();
     $test = $search->DefinedEmail();
     $test = $search->DefinedKey();
     $test = $search->DefinedInstructions();

     $test = $search->DefinedTruncated();

METHODS
=======

Retrieval functions
-------------------

     GetInstructions() - returns a string that contains the instructions
                         for using this search query.

     GetKey() - returns a string that contains the value of key from the
                search agent.

     GetName() - returns a string that contains the value of name in the
                 search query.

     GetFirst() - returns a string that contains the value of first in the
                  search query.

     GetGiven() - returns a string that contains the value of given name
                  in the search query.

     GetLast() - returns a string that contains the value of last in the
                 search query.

     GetFamily() - returns a string that contains the value of the family
                   name in the search query.

     GetNick() - returns a string that contains the value of nick in the
                 search query.

     GetEmail() - returns a string that contains the value of email in the
                  search query.

     GetFields() - returns a hash that contains the fields required by the
                   sender in $hash{tag} = value format.

     GetItems() - returns an array of Net::Jabber::Query::Search::Item
                  objects. These can be modified or accessed with the
                  functions available to them.

     GetItemTrees() - returns an array of XML::Parser objects that contain
                      the data for each item.

     GetResults() - returns an hash that represents the data in the Item
                    trees.  The hash looks like this:

     $results{jid1}->{field1} = "value1";
                     {field2} = "value2";
                     {field3} = "value3";
     $results{jid2}->{field1} = "value1";
                     {field2} = "value2";
                     {field3} = "value3";

     GetTruncated() - returns 1 if <truncated/> exists in the search query,
                      0 otherwise.

Creation functions
------------------

     SetSearch(instructions=>string, - set multiple fields in the <query/>
               key=>string,            at one time.  This is a cumulative
               name=>string,           and overwriting action.  If you
               first=>string,          set the "name" twice, the second
               given=>string,          setting is what is used.  If you set
               last=>string,           the first, and then set the
               family=>string)         last then both will be in the
               nick=>string,           search.  For valid settings read
               email=>string)          the specific Set functions below.

     SetInstructions(string) - sets the value of the instructions in the
                               <query/>.

     SetKey(string) - sets the value of key in the <query/>.

     SetName(string) - sets the value of name in the <query/>.  If "" then
                       it creates an empty tag.

     SetFirst(string) - sets the value of first in the <query/>.  If "" then
                        it creates an empty tag.

     SetGiven(string) - sets the value of given in the <query/>.  If "" then
                        it creates an empty tag.

     SetLast(string) - sets the value of last in the <query/>.  If "" then
                       it creates an empty tag.

     SetFamily(string) - sets the value of family in the <query/>.  If "" then
                         it creates an empty tag.

     SetNick(string) - sets the value of nick in the <query/>.  If "" then
                       it creates an empty tag.

     SetEmail(string) - sets the value of email in the <query/>.  If "" then
                        it creates an empty tag.

     SetTruncated() - adds a <truncated/> tag to the <query/> to indicate that
                      the search results were truncated.

     AddItem(hash) - creates and returns a new Net::Jabbber::Query::Search::Item
                     object.  The argument hash is passed to the SetItem
                     function.  Check the Net::Jabber::Query::Search::Item
                     for valid values.

Test functions
--------------

     DefinedInstructions() - returns 1 if there is a <instructions/> in
                             the query, 0 if not.

     DefinedKey() - returns 1 if there is a <key/> in the query, 0 if not.

     DefinedName() - returns 1 if there is a <name/> in the query, 0 if not.

     DefinedFirst() - returns 1 if there is a <first/> in the query, 0 if not.

     DefinedGiven() - returns 1 if there is a <given/> in the query, 0 if not.

     DefinedLast() - returns 1 if there is a <last/> in the query, 0 if not.

     DefinedFamily() - returns 1 if there is a <family/> in the query, 0 if not.

     DefinedNick() - returns 1 if there is a <nick/> in the query, 0 if not.

     DefinedEmail() - returns 1 if there is a <email/> in the query, 0 if not.

     DefinedTruncated() - returns 1 if there is a <truncated/> in the query,
                          0 if not.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber IQ Search Item Module
****************************

NAME
====

   Net::Jabber::Query::Search::Item - Jabber IQ Search Item Module

SYNOPSIS
========

     Net::Jabber::Query::Search::Item is a companion to the
     Net::Jabber::Query::Search module.  It provides the user a simple
     interface to set and retrieve all parts of a Jabber Search Item.

DESCRIPTION
===========

     To initialize the Item with a Jabber <iq/> and then access the search
     query you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the iq:

     use Net::Jabber;

     sub iq {
       my $iq = new Net::Jabber::IQ(@_);
       my $search = $iq->GetQuery();
       my @items = $search->GetItems();
       foreach $item (@items) {
         ...
       }
       .
       .
       .
     }

     You now have access to all of the retrieval functions available below.

     To create a new IQ Search Item to send to the server:

     use Net::Jabber;

     $Client = new Net::Jabber::Client();
     ...

     $iq = new Net::Jabber::IQ();
     $search = $iq->NewQuery("jabber:iq:search");
     $item = $search->AddItem();
     ...

     $client->Send($iq);

     Using $Item you can call the creation functions below to populate the
     tag before sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $jid    = $item->GetJID();
     $jidJID = $item->GetJID("jid");
     $name   = $item->GetName();
     $first  = $item->GetFirst();
     $given  = $item->GetGiven();
     $last   = $item->GetLast();
     $family = $item->GetFamily();
     $nick   = $item->GetNick();
     $email  = $item->GetEmail();

     %result = $item->GetResult();

     @item   = $item->GetTree();
     $str    = $item->GetXML();

Creation functions
------------------

     $item->SetItem(jid=>'bob@jabber.org',
     		   name=>'Bob',
     		   first=>'Bob',
     		   last=>'Smith',
     		   nick=>'bob',
     		   email=>'bob@hotmail.com');

     $item->SetJID('bob@jabber.org');
     $item->SetName('Bob Smith');
     $item->SetFirst('Bob');
     $item->SetGiven('Bob');
     $item->SetLast('Smith');
     $item->SetFamily('Smith');
     $item->SetNick('bob');
     $item->SetEmail('bob@bobworld.com');

Test functions
--------------

     $test = $item->DefinedName();
     $test = $item->DefinedFirst();
     $test = $item->DefinedGiven();
     $test = $item->DefinedLast();
     $test = $item->DefinedFamily();
     $test = $item->DefinedNick();
     $test = $item->DefinedEmail();

METHODS
=======

Retrieval functions
-------------------

     GetJID()      - returns either a string with the Jabber Identifier,
     GetJID("jid")   or a Net::Jabber::JID object for the account that is
                     listed in this <item/>.  To get the JID object set the
                     string to "jid", otherwise leave blank for the text
                     string.

     GetName() - returns a string with the full name of the account being
                 returned.

     GetFirst() - returns a string with the first name of the account being
                  returned.

     GetGiven() - returns a string with the given name of the account being
                  returned.

     GetLast() - returns a string with the last name of the jabber account
                 being returned.

     GetFamily() - returns a string with the family name of the jabber
                   account being returned.

     GetNick() - returns a string with the nick of the jabber account being
                 returned.

     GetEmail() - returns a string with the email of the jabber account being
                  returned.

     GetResult() - returns a hash with all of the valid fields set.  Here is
                   the way the hash might look.

     $result{last} = "Smith";
     $result{first} = "Bob";

     GetXML() - returns the XML string that represents the <presence/>.
                This is used by the Send() function in Client.pm to send
                this object as a Jabber Presence.

     GetTree() - returns an array that contains the <presence/> tag
                 in XML::Parser Tree format.

Creation functions
------------------

     SetItem(jid=>string|JID, - set multiple fields in the <item/>
             name=>string,      at one time.  This is a cumulative
             first=>string,     and overwriting action.  If you
             given=>string,     set the "name" twice, the second
             last=>string,      setting is what is used.  If you set
             family=>string)    the first, and then set the
             nick=>string,      last then both will be in the
             email=>string)     <item/> tag.  For valid settings
                                read the specific Set functions below.

     SetJID(string) - sets the Jabber Identifier.  You can either pass a
     SetJID(JID)      string or a JID object.  They must be valid Jabber
                      Identifiers or the server will return an error message.
                      (ie.  jabber:bob@jabber.org/Silent Bob, etc...)

     SetName(string) - sets the name this search item should show in the
                       search.

     SetFirst(string) - sets the first name this search item should show
                        in the search.

     SetGiven(string) - sets the given name this search item should show
                        in the search.

     SetLast(string) - sets the last name this search item should show in
                       the search.

     SetFamily(string) - sets the family name this search item should show
                         in the search.

     SetNick(string) - sets the nick this search item should show in the
                       search.

     SetEmail(string) - sets the email this search item should show in the
                        search.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber IQ Time Module
*********************

NAME
====

   Net::Jabber::Query::Time - Jabber IQ Time Module

SYNOPSIS
========

     Net::Jabber::Query::Time is a companion to the Net::Jabber::Query module.
     It provides the user a simple interface to set and retrieve all parts
     of a Jabber Time query.

DESCRIPTION
===========

     To initialize the Query with a Jabber <iq/> and then access the time
     query you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the iq:

     use Net::Jabber;

     sub iqCB {
       my $iq = new Net::Jabber::IQ(@_);
       my $time = $iq->GetQuery();
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new Query time to send to the server:

     use Net::Jabber;

     $client = new Net::Jabber::Client();
     ...

     $iq = new Net::Jabber::IQ();
     $time = $iq->NewQuery("jabber:iq:time");
     ...

     $client->Send($iq);

     Using $time you can call the creation functions below to populate the
     tag before sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $utc      = $time->GetUTC();
     $timezone = $time->GetTZ();
     $display  = $time->GetDisplay();

Creation functions
------------------

     $time->SetTime(utc=>'20000314T09:50:00',
                    tz=>'EST',
                    display=>'2000/03/14 09:50 AM');

     $time->SetUTC('20000419T13:05:34');
     $time->SetTZ('CST');
     $time->SetDisplay('2000/04/19 01:50 PM');

Test functions
--------------

     $test = $time->DefinedUTC();
     $test = $time->DefinedTZ();
     $test = $time->DefinedDisplay();

METHODS
=======

Retrieval functions
-------------------

     GetUTC() - returns a string with the universal time constant time in
                the <query/>.

     GetTZ() - returns a string with the timezone in the <query/>.

     GetDisplay() - returns a string with the displayin the <query/>.

Creation functions
------------------

     SetTime(utc=>string,     - set multiple fields in the <iq/> at one
             tz=>string,        time.  This is a cumulative and over
             display=>string)   writing action.  If you set the "utc"
                                twice, the second setting is what is
                                used.  If you set the tz, and then
                                set the display then both will be in the
                                <query/> tag.  For valid settings read
                                the specific Set functions below.

     SetUTC(string) - sets the universal time constant time for the
                      <query/>.  The format for the UTC is:

                        yyyymmddThh:nn:ss

     yyyy - year
     mm   - month
     dd   - day
     hh   - hour
     nn   - minute
     ss   - second

     SetTZ(string) - sets the timezone of the local client in the <query/>.

     SetDisplay(string) - sets the string to display as the local time in
                          UTC format in the remote client.

Test functions
--------------

     DefinedUTC() - returns 1 if <utc/> exists in the query, 0 otherwise.

     DefinedTZ() - returns 1 if <tz/> exists in the query, 0 otherwise.

     DefinedDisplay() - returns 1 if <display/> exists in the query,
                        0 otherwise.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber IQ Version Module
************************

NAME
====

   Net::Jabber::Query::Version - Jabber IQ Version Module

SYNOPSIS
========

     Net::Jabber::Query::Version is a companion to the Net::Jabber::Query module.
     It provides the user a simple interface to set and retrieve all parts
     of a Jabber Version query.

DESCRIPTION
===========

     To initialize the Query with a Jabber <iq/> and then access the version
     query you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the iq:

     use Net::Jabber;

     sub iqCB {
       my $iq = new Net::Jabber::IQ(@_);
       my $version = $iq->GetQuery();
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new Query version to send to the server:

     use Net::Jabber;

     $client = new Net::Jabber::Client();
     ...

     $iq = new Net::Jabber::IQ();
     $version = $iq->NewQuery("jabber:iq:version");
     ...

     $client->Send($iq);

     Using $version you can call the creation functions below to populate the
     tag before sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $name = $version->GetName();
     $ver  = $version->GetVer();
     $os   = $version->GetOS();

Creation functions
------------------

     $version->SetVersion(name=>'Net::Jabber',
                          ver=>'1.0',
                          os=>'Perl');

     $version->SetName('JabberClient');
     $version->SetVer('0.1');
     $version->SetOS('Perl/Tk');

Test functions
--------------

     $test = $version->DefinedName();
     $test = $version->DefinedVer();
     $test = $version->DefinedOS();

METHODS
=======

Retrieval functions
-------------------

     GetName() - returns a string with the name in the <query/>.

     GetVer() - returns a string with the version in the <query/>.

     GetOS() - returns a string with the os in the <query/>.

Creation functions
------------------

     SetVersion(name=>string, - set multiple fields in the <iq/> at one
                ver=>string,    time.  This is a cumulative and over
                os=>string)     writing action.  If you set the "name"
                                twice, the second setting is what is
                                used.  If you set the ver, and then
                                set the os then both will be in the
                                <query/> tag.  For valid settings read
                                the specific Set functions below.

     SetName(string) - sets the name of the local client for the <query/>.

     SetVer(string) - sets the version of the local client in the <query/>.

     SetOS(string) - sets the os, or cross-platform language, of the local
                     client in the <query/>.

Test functions
--------------

     DefinedName() - returns 1 if <name/> exists in the query, 0 otherwise.

     DefinedVer() - returns 1 if <version/> exists in the query, 0 otherwise.

     DefinedOS() - returns 1 if <os/> exists in the query, 0 otherwise.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber Server Library
*********************

NAME
====

   Net::Jabber::Server - Jabber Server Library

SYNOPSIS
========

     Net::Jabber::Server is a module that provides a developer easy access
     to developing applications that need an embedded Jabber server.

DESCRIPTION
===========

     Server.pm seeks to provide enough high level APIs and automation of
     the low level APIs that writing and spawning a Jabber Server in Perl
     is trivial.  For those that wish to work with the low level you can
     do that too, but those functions are covered in the documentation for
     each module.

     Net::Jabber::Server provides functions to run a full Jabber server that
     accepts incoming connections and delivers packets to external Jabber
     servers.  You can use all or none of the functions, there is no requirement.

     For more information on how the details for how Net::Jabber is written
     please see the help for Net::Jabber itself.

     For a full list of high level functions available please see
     Net::Jabber::Protocol.

Basic Functions
---------------

     use Net::Jabber;

     $Server = new Net::Jabber::Server();

     $Server->Start();
     $Server->Start(jabberxml=>"custom_jabber.xml",
     	           hostname=>"foobar.net");

     $Server->Stop();

METHODS
=======

Basic Functions
---------------

     new(debuglevel=>0|1|2, - creates the Server object.  debugfile
         debugfile=>string,   should be set to the path for the debug
         debugtime=>0|1)      log to be written.  If set to "stdout"
                              then the debug will go there.  debuglevel
                              controls the amount of debug.  For more
                              information about the valid setting for
                              debuglevel, debugfile, and debugtime see
                              Net::Jabber::Debug.

     Start(hostname=>string, - starts the server listening on the proper
     	  jaberxml=>string)   ports.  hostname is a quick way of telling
                               the server the hostname to listen on.
                               jabberxml defines the path to a different
                               jabberd configuration file (default is
                               "./jabber.xml").

     Stop() - stops the server from running and shuts down all sub programs.

AUTHOR
======

   By Ryan Eatmon in January of 2001 for http://jabber.org.

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber Transport Library
************************

NAME
====

   Net::Jabber::Transport - Jabber Transport Library

SYNOPSIS
========

     Net::Jabber::Transport is a module that provides a developer easy access
     to tranports in the Jabber Instant Messaging protocol.

DESCRIPTION
===========

     Transport.pm seeks to provide enough high level APIs and automation of
     the low level APIs that writing a Jabber Transport in Perl is trivial.
     For those that wish to work with the low level you can do that too,
     but those functions are covered in the documentation for each module.

     Net::Jabber::Transport provides functions to connect to a Jabber server,
     login, send and receive messages, set personal information, create
     a new user account, manage the roster, and disconnect.  You can use
     all or none of the functions, there is no requirement.

     For more information on how the details for how Net::Jabber is written
     please see the help for Net::Jabber itself.

     For a full list of high level functions available please see
     Net::Jabber::Protocol.

Basic Functions
---------------

     use Net::Jabber;

     $Con = new Net::Jabber::Transport();

     $Con->Connect(hostname=>"jabber.org");

     if ($Con->Connected()) {
       print "We are connected to the server...\n";
     }

     #
     # For the list of available function see Net::Jabber::Protocol.
     #

     $Con->Disconnect();

METHODS
=======

Basic Functions
---------------

     new(debuglevel=>0|1|2, - creates the Transport object.  debugfile
         debugfile=>string,   should be set to the path for the debug
         debugtime=>0|1)      log to be written.  If set to "stdout"
                              then the debug will go there.  debuglevel
                              controls the amount of debug.  For more
                              information about the valid setting for
                              debuglevel, debugfile, and debugtime see
                              Net::Jabber::Debug.

     Connect(hostname=>string,      - opens a connection to the server
     	    port=>integer,           listedt in the hostname value,
     	    secret=>string,          on the port listed.  The defaults
     	    transportname=>string)   for the two are localhost and 5222.
     				     The secret is the password needed
                                      to attach the hostname, and the
                                      transportname is the name that
                                      server and clients will know the
                                      transport by.

     Disconnect() - closes the connection to the server.

     Connected() - returns 1 if the Transport is connected to the server,
                   and 0 if not.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org.

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber X Module
***************

NAME
====

   Net::Jabber::X - Jabber X Module

SYNOPSIS
========

     Net::Jabber::X is a companion to the Net::Jabber module. It
     provides the user a simple interface to set and retrieve all
     parts of a Jabber X.

DESCRIPTION
===========

     Net::Jabber::X differs from the other Net::Jabber::* modules in that
     the XMLNS of the query is split out into more submodules under
     X.  For specifics on each module please view the documentation
     for each Net::Jabber::X::* module.  The available modules are:

     Net::Jabber::X::AutoUpdate - Auto Update information
     Net::Jabber::X::Delay      - Message Routing and Delay Information
     Net::Jabber::X::GC         - GroupChat
     Net::Jabber::X::Ident      - Rich Identification
     Net::Jabber::X::Oob        - Out Of Band File Transfers
     Net::Jabber::X::Roster     - Roster Items for embedding in messages

     Each of these modules provide Net::Jabber::X with the functions
     to access the data.  By using delegates and the AUTOLOAD function
     the functions for each namespace is used when that namespace is
     active.

     To access an X object you must create a Message object and use the
     access functions there to get to the X.  To initialize the Message with
     a Jabber <message/> you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the message
     you can access the x tags for the namespace "my:namespace" by doing
     the following:

     use Net::Jabber;

     sub messageCB {
       my $message = new Net::Jabber::Message(@_);
       my @xTags = $mesage->GetX("my:namespace");
       my $xTag;
       foreach $xTag (@xTags) {
         .
         .
         .
       }
     }

     You now have access to all of the retrieval functions available.

     To create a new x to send to the server:

     use Net::Jabber;

     my $message = new Net::Jabber::Message();
     my $x = $message->NewX("jabber:x:ident");

     Now you can call the creation functions for the X as defined in the
     proper namespace.  See below for the general <x/> functions, and in
     each query module for those functions.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $xmlns     = $X->GetXMLNS();

     $str       = $X->GetXML();
     @x         = $X->GetTree();

Creation functions
------------------

     $X->SetXMLNS("jabber:x:delay");

METHODS
=======

Retrieval functions
-------------------

     GetXMLNS() - returns a string with the namespace of the query that
                  the <x/> contains.

     GetXML() - returns the XML string that represents the <x/>. This
                is used by the Send() function in Client.pm to send
                this object as a Jabber X.

     GetTree() - returns an array that contains the <x/> tag in XML::Parser
                 Tree format.

Creation functions
------------------

     SetXMLNS(string) - sets the xmlns of the <x/> to the string.

CUSTOM X MODULES
================

     Part of the flexability of this module is that you can write your own
     module to handle a new namespace if you so choose.  The SetDelegates
     function is your way to register the xmlns and which module will
     provide the missing access functions.

     To register your namespace and module, you can either create an X
     object and register it once, or you can use the SetDelegates
     function in Client.pm to do it for you:

     my $Client = new Net::Jabber::Client();
     $Client->AddDelegate(namespace=>"blah:blah",
     			 parent=>"Net::Jabber::X",
     			 delegate=>"Blah::Blah");

       or

     my $Transport = new Net::Jabber::Transport();
     $Transport->AddDelegate(namespace=>"blah:blah",
     			    parent=>"Net::Jabber::X",
     			    delegate=>"Blah::Blah");

       Once you have the delegate registered you need to define the access
       functions.  Here is a an example module:

     package Blah::Blah;

     sub new {
       my $proto = shift;
       my $class = ref($proto) || $proto;
       my $self = { };
       $self->{VERSION} = $VERSION;
       bless($self, $proto);
       return $self;
     }

     sub SetBlah {
       shift;
       my $self = shift;
       my ($blah) = @_;
       return &Net::Jabber::SetXMLData("single",$self->{X},"blah","$blah",{});
     }

     sub GetBlah {
       shift;
       my $self = shift;
       return &Net::Jabber::GetXMLData("value",$self->{X},"blah","");
     }

     1;

     Now when you create a new X object and call GetBlah on that object
     it will AUTOLOAD the above function and handle the request.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber X AutoUpdate Delegate
****************************

NAME
====

   Net::Jabber::X::AutoUpdate - Jabber X AutoUpdate Delegate

SYNOPSIS
========

     Net::Jabber::X::AutoUpdate is a companion to the Net::Jabber::X module.
     It provides the user a simple interface to set and retrieve all
     parts of a Jabber X AutoUpdate.

DESCRIPTION
===========

     To initialize the AutoUpdate with a Jabber <x/> you must pass it the
     XML::Parser Tree array from the module trying to access the <x/>.
     In the callback function:

     use Net::Jabber;

     sub iq {
       my $foo = new Net::Jabber::Foo(@_);

     my @xTags = $foo->GetX("jabber:x:autoupdate");

     my $xTag;
     foreach $xTag (@xTags) {
     	$xTag->....

     }
     .
     .
     .
         }

     You now have access to all of the retrieval functions available.

     To create a new AutoUpdate to send to the server:

     use Net::Jabber;

     $foo = new Net::Jabber::Foo();
     $x = $foo->NewX("jabber:x:autoupdate");

     Now you can call the creation functions below.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $jid = $xTag->GetJID();

Creation functions
------------------

     $xTag->SetX(jid=>"update.jabber.org");

     $xTag->SetJID("update.jabber.com");

METHODS
=======

Retrieval functions
-------------------

     GetJID() - returns a string with the Jabber Identifier of the
                agent that is going to handle the update.

Creation functions
------------------

     SetX(jid=>string) - set multiple fields in the <x/> at one
                         time.  This is a cumulative and over
                         writing action.  If you set the "jid"
                         attribute twice, the second setting is
                         what is used.  For valid settings read the
                         specific Set functions below.

     SetJID(string) - sets the JID of the agent that is going to handle the
                      update.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber X Delay Delegate
***********************

NAME
====

   Net::Jabber::X::Delay - Jabber X Delay Delegate

SYNOPSIS
========

     Net::Jabber::X::Delay is a companion to the Net::Jabber::X module.
     It provides the user a simple interface to set and retrieve all
     parts of a Jabber X Delay.

DESCRIPTION
===========

     To initialize the Delay with a Jabber <x/> you must pass it the
     XML::Parser Tree array from the module trying to access the <x/>.
     In the callback function:

     use Net::Jabber;

     sub iq {
       my $foo = new Net::Jabber::Foo(@_);

     my @xTags = $foo->GetX("jabber:x:delay");

     my $xTag;
     foreach $xTag (@xTags) {
     	$xTag->....

     }
     .
     .
     .
         }

     You now have access to all of the retrieval functions available.

     To create a new Delay to send to the server:

     use Net::Jabber;

     $foo = new Net::Jabber::Foo();
     $xTag = $foo->NewX("jabber:x:delay");

     Now you can call the creation functions below.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $from      = $xTag->GetFrom();
     $stamp     = $xTag->GetStamp();
     $message   = $xTag->GetMessage();

Creation functions
------------------

     $xTag->SetDelay(FRom=>"jabber:foo.bar.com",
     	            message=>"Stored offline");

     $xTag->SetFrom("bob@jabber.org");
     $xTag->SetStamp();
     $xTag->SetStamp("20000124T10:54:00");
     $xTag->SetMessage("Stored Offline");

METHODS
=======

Retrieval functions
-------------------

     GetFrom() - returns a string with the Jabber Identifier of the
                 person who added the delay.

     GetStamp() - returns a string that represents the time stamp of
                  the delay.

     GetMessage() - returns a string with the message that describes
                    the nature of the delay.

Creation functions
------------------

     SetDelay(from=>string,    - set multiple fields in the <x/> at one
              stamp=>string,     time.  This is a cumulative and over
              message=>string)   writing action.  If you set the "from"
                                 attribute twice, the second setting is
                                 what is used.  If you set the status, and
                                 then set the priority then both will be in
                                 the <x/> tag.  For valid settings read the
                                 specific Set functions below.

     SetFrom(string) - sets the from attribute of the server adding the
                       delay.

     SetStamp(string) - sets the timestamp of the delay.  If the string is
                        left blank then the module adds the current date/time
                        in the proper format as the stamp.

     SetMessage(string) - sets description of the delay.

     =head2 Test functions

     DefinedFrom() - returns 1 if the from attribute exists in the x,
                     0 otherwise.

     DefinedStamp() - returns 1 if the stamp attribute exists in the x,
                      0 otherwise.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber X Encrypted Module
*************************

NAME
====

   Net::Jabber::X::Encrypted - Jabber X Encrypted Module

SYNOPSIS
========

     Net::Jabber::X::Encrypted is a companion to the Net::Jabber::X module.
     It provides the user a simple interface to set and retrieve all
     parts of a Jabber X Encrypted.

DESCRIPTION
===========

     To initialize the Encrypted with a Jabber <x/> you must pass it the
     XML::Parser Tree array from the module trying to access the <x/>.
     In the callback function:

     use Net::Jabber;

     sub iq {
       my $foo = new Net::Jabber::Foo(@_);

     my @xTags = $foo->GetX("jabber:x:encrypted");

     my $xTag;
     foreach $xTag (@xTags) {
     	$xTag->....

     }
     .
     .
     .
         }

     You now have access to all of the retrieval functions available.

     To create a new Encrypted to send to the server:

     use Net::Jabber;

     $foo = new Net::Jabber::Foo();
     $x = $foo->NewX("jabber:x:encrypted");

     Now you can call the creation functions below.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $message = $xTag->GetMessage();

Creation functions
------------------

     $xTag->SetEncrypted(message=>data);

     $xTag->SetMessage(data);

METHODS
=======

Retrieval functions
-------------------

     GetMessage() - returns a string with the message data.

Creation functions
------------------

     SetEncrypted(message=>string) - set multiple fields in the <x/> at one
                                     time.  This is a cumulative and over
                                     writing action.  If you set the
                                     "message" data twice, the second
                                     setting is what is used.  If you set the
                                     message, and then set another field
                                     then both will be in the <x/> tag.  For
                                     valid settings read the specific Set
                                     functions below.

     SetMessage(string) - sets the data for the message.

AUTHOR
======

   By Ryan Eatmon in December of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber X Form Module
********************

NAME
====

   Net::Jabber::X::Form - Jabber X Form Module

SYNOPSIS
========

     Net::Jabber::X::Form is a companion to the Net::Jabber::X module.
     It provides the user a simple interface to set and retrieve all parts
     of a Jabber X Form.

DESCRIPTION
===========

     To initialize the X with a Jabber <x/> and then access the form
     query you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the x:

     use Net::Jabber;

     sub foo {
       my $foo = new Net::Jabber::Foo(@_);
       my $form = $foo->GetX();
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new X form to send to the server:

     use Net::Jabber;

     $client = new Net::Jabber::Client();
     ...

     $foo = new Net::Jabber::Foo();
     $form = $foo->NewX("jabber:x:form");
     ...

     $client->Send($foo);

     Using $form you can call the creation functions below to populate the
     tag before sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     @fields     = $form->GetFields();
     @fieldTrees = $form->GetFieldTrees();

Creation functions
------------------

     $field   = $form->AddField();
     $field   = $form->AddField(jid=>"bob\@jabber.org",
                                name=>"Bob",
                                groups=>["school","friends"]);

METHODS
=======

Retrieval functions
-------------------

     GetFields() - returns an array of Net::Jabber::X::Form::Field objects.
                  These can be modified or accessed with the functions
                  available to them.

     GetFieldTrees() - returns an array of XML::Parser objects that contain
                      the data for each field.

Creation functions
------------------

     AddField(hash) - creates and returns a new Net::Jabbber::X::Form::Field
                     object.  The argument hash is passed to the SetField
                     function.  Check the Net::Jabber::X::Form::Field
                     for valid values.

AUTHOR
======

   By Ryan Eatmon in February of 2001 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber X Form Field Module
**************************

NAME
====

   Net::Jabber::X::Form::Field - Jabber X Form Field Module

SYNOPSIS
========

     Net::Jabber::X::Form::Field is a companion to the
     Net::Jabber::X::Form module.  It provides the user a simple
     interface to set and retrieve all parts of a Jabber Form Field.

DESCRIPTION
===========

     To initialize the Field with a Jabber <x/> and then access the </x>
     you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the object
     type foo:

     use Net::Jabber;

     sub foo {
       my $foo = new Net::Jabber::Foo(@_);

     my @xTags = $foo->GetX("jabber:x:form");

     my $xTag;
     foreach $xTag (@xTags) {
       my @fields = $xTag->GetFields();
     	my $field;
     	foreach $field (@fields) {
     	  $field->GetXXXX();
     	  .
     	  .
     	  .
     	}
     }
     .
     .
     .
         }

     You now have access to all of the retrieval functions available below.

     To create a new X Form Field to send to another user:

     use Net::Jabber;

     $Client = new Net::Jabber::Client();
     ...

     $foo = new Net::Jabber::Foo();
     $form = $foo->NewX("jabber:x:form");
     $foo = $form->AddField();
     ...

     $client->Send($foo);

     Using $field you can call the creation functions below to populate the
     tag before sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $type    = $field->GetType();
     $var     = $field->GetVar();
     $label   = $field->GetLabel();
     $value   = $field->GetValue();
     $order   = $field->GetOrder();

     @options = $field->GetOptions();

     @field   = $field->GetTree();
     $str     = $field->GetXML();

Creation functions
------------------

     $field->SetField(type=>"entry",
     		     var=>"icqnum",
     		     label=>"ICQ #",
     		     order=>1);
     $field->SetType('pulldown');
     $field->SetVar('sex');
     $field->SetLabel('Sex');
     $field->SetOrder('2');
     $field->AddOption(value=>"m",
     		      label=>"Male");
     $field->AddOption(value=>"f",
     		      label=>"Female");
     $field->AddOption(value=>"u",
     		      label=>"Unknown");

Test functions
--------------

     $test = $field->DefinedType();
     $test = $field->DefinedVar();
     $test = $field->DefinedLabel();
     $test = $field->DefinedOrder();

METHODS
=======

Retrieval functions
-------------------

     GetType() - returns a string with type of field this is.

     GetVar() - returns a string with variable name that the field sets.
                This is meant to be used as an index to a hash, but mainly
                so that when returned to the server the thing parsing it
                can quickly see which value goes with what variable.

     GetLabel() - returns a string with label that should be displayed in
                  front of the widget for this field.

     GetValue() - returns a string with the value that this is field is set
                  to.  If set then this should be the default value for the
                  field in the widget, otherwise it is the value that the
                  program returned.

     GetOrder() - returns an integer with the order that this field should
                  be displayed in on the form.  So a field with order=1
                  should be displayed, or prompted, before the field with
                  order=2.

     GetXML() - returns the XML string that represents the <field/>.

     GetTree() - returns an array that contains the <field/> tag
                 in XML::Parser Tree format.

Creation functions
------------------

     SetField(type=>string,   - set multiple fields in the <field/>
              var=>string,      at one time.  This is a cumulative
              label=>string,    and overwriting action.  If you
              value=>string,    set the "var" twice, the second
              order=>integer)   setting is what is used.  If you set
                                the tpe, and then set the
                                label then both will be in the
                                <field/> tag.  For valid settings
                                read the specific Set functions below.

     SetType(string) - sets the type of field that this <field/> is.

     SetVar(string) - sets the var name for the <field/>.

     SetLabel(string) - sets the label that should be shown next to the
                        widget in the form.

     SetValue(string) - sets the value of the field.

     SetOrder(integer) - sets the order to show the field in.

Test functions
--------------

     DefinedType() - returns 1 if the type attribute is set in the <field/>,
                     0 otherwise.

     DefinedVar() - returns 1 if the var attribute is set in the <field/>,
                    0 otherwise.

     DefinedLabel() - returns 1 if the label attribute is set in the <field/>,
                      0 otherwise.

     DefinedOrder() - returns 1 if the order attribute is set in the <field/>,
                      0 otherwise.

AUTHOR
======

   By Ryan Eatmon in February of 2001 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber X Form Field Option Module
*********************************

NAME
====

   Net::Jabber::X::Form::Field::Option - Jabber X Form Field Option Module

SYNOPSIS
========

     Net::Jabber::X::Form::Field::Option is a companion to the
     Net::Jabber::X::Form::Field module.  It provides the user a simple
     interface to set and retrieve all parts of a Jabber Form Field
     Option.

DESCRIPTION
===========

     To initialize the Option with a Jabber <x/> and then access the </x>
     you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the object
     type foo:

     use Net::Jabber;

     sub foo {
       my $foo = new Net::Jabber::Foo(@_);

     my @xTags = $foo->GetX("jabber:x:form");

     my $xTag;
     foreach $xTag (@xTags) {
       my @fields = $xTag->GetFields();
     	my $field;
     	foreach $field (@fields) {
     	  if ($field->GetType() eq "option") {
     	    foreach my $option ($field->GetOptions()) {
     	      $option->GetXXXX();
     	    }
     	  }
     	  .
     	  .
     	  .
     	}
     }
     .
     .
     .
         }

     You now have access to all of the retrieval functions available below.

     To create a new X Form Field Option to send to another user:

     use Net::Jabber;

     $Client = new Net::Jabber::Client();
     ...

     $foo = new Net::Jabber::Foo();
     $form = $foo->NewX("jabber:x:form");
     $field = $form->AddField(tpye=>"option");
     $option = $field->AddOption();
     ...

     $client->Send($foo);

     Using $field you can call the creation functions below to populate the
     tag before sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $label  = $option->GetLabel();
     $value  = $option->GetValue();

     @option = $option->GetTree();
     $str    = $option->GetXML();

Creation functions
------------------

     $option->SetOption(label=>"Male",
     		       value=>"m");

     $option->SetLabel('Yes');
     $option->SetValue('1');

Test functions
--------------

     $test = $option->DefinedLabel();
     $test = $option->DefinedValue();

METHODS
=======

Retrieval functions
-------------------

     GetLabel() - returns a string with the label that the option should have
                  in the GUI.

     GetValuel() - returns a string with the value that the option should have
                   when selected.

     GetXML() - returns the XML string that represents the <presence/>.
                This is used by the Send() function in Client.pm to send
                this object as a Jabber Presence.

     GetTree() - returns an array that contains the <presence/> tag
                 in XML::Parser Tree format.

Creation functions
------------------

     SetOption(label=>string, - set multiple options in the <option/>
               value=>string)   at one time.  This is a cumulative
                                and overwriting action.  If you
                                set the "label" twice, the second
                                setting is what is used.  If you set
                                the label, and then set the
                                value then both will be in the
                                <option/> tag.  For valid settings
                                read the specific Set functions below.

     SetLabel(string) - sets the label to show in the GUI for this option.

     SetValue(string) - sets the value to set the field to when this option
                        is selected in the GUI.

Test functions
--------------

     DefinedLabel() - returns 1 if the label attribute is set in the <field/>,
                      0 otherwise.

     DefinedValue() - returns 1 if the value attribute is set in the <field/>,
                      0 otherwise.

AUTHOR
======

   By Ryan Eatmon in February of 2001 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber X GroupChat Delegate
***************************

NAME
====

   Net::Jabber::X::GC - Jabber X GroupChat Delegate

SYNOPSIS
========

     Net::Jabber::X::GC is a companion to the Net::Jabber::X module.
     It provides the user a simple interface to set and retrieve all
     parts of a Jabber X GroupChat.

     The main purpose for this module is to handle nick changes from
     a groupchat server (i.e. IRC, etc...)

DESCRIPTION
===========

     To initialize the GC with a Jabber <x/> you must pass it the
     XML::Parser Tree array from the module trying to access the <x/>.
     In the callback function:

     use Net::Jabber;

     sub iq {
       my $foo = new Net::Jabber::Foo(@_);

     my @xTags = $foo->GetX("jabber:x:gc");

     my $xTag;
     foreach $xTag (@xTags) {
     	$xTag->....

     }
     .
     .
     .
         }

     You now have access to all of the retrieval functions available.

     To create a new GC to send to the server:

     use Net::Jabber;

     $foo = new Net::Jabber::Foo();
     $xTag = $foo->NewX("jabber:x:gc");

     Now you can call the creation functions below.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $nick = $xTag->GetNick();

Creation functions
------------------

     $xTag->SetGC(nick=>"bob");

     $xTag->SetNick("bob_");

METHODS
=======

Retrieval functions
-------------------

     GetNick() - returns a string with the Jabber Identifier of the
                 person who added the gc.

Creation functions
------------------

     SetGC(nick=>string) - set multiple fields in the <x/> at one
                           time.  This is a cumulative and over
                           writing action.  If you set the "nick"
                           attribute twice, the second setting is
                           what is used.  If you set the nick, and
                           then set another field then both will be in
                           the <x/> tag.  For valid settings read the
                           specific Set functions below.

     SetNick(string) - sets the new nick sent from the server.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber X Ident Delegate
***********************

NAME
====

   Net::Jabber::X::Ident - Jabber X Ident Delegate

SYNOPSIS
========

     Net::Jabber::X::Ident is a companion to the Net::Jabber::X module.
     It provides the user a simple interface to set and retrieve all
     parts of a Jabber X Ident.

DESCRIPTION
===========

     To initialize the Ident with a Jabber <x/> you must pass it the
     XML::Parser Tree array from the module trying to access the <x/>.
     In the callback function:

     use Net::Jabber;

     sub iq {
       my $foo = new Net::Jabber::Foo(@_);

     my @xTags = $foo->GetX("jabber:x:ident");

     my $xTag;
     foreach $xTag (@xTags) {
     	$xTag->....

     }
     .
     .
     .
         }

     You now have access to all of the retrieval functions available.

     To create a new Ident to send to the server:

     use Net::Jabber;

     $foo = new Net::Jabber::Foo();
     $x = $foo->NewX("jabber:x:ident");

     Now you can call the creation functions below.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $from        = $xTag->GetFrom();
     $to          = $xTag->GetTo();
     $replyto     = $xtag->GetReplyTo();
     $cc          = $xTag->GetCC();
     $forwardedby = $xTag->GetForwardedBy();

Creation functions
------------------

     $xTag->SetX(FRom=>"jabber:foo.bar.com",
     	        replyTo=>"bob@jabber.org");

     $xTag->SetFrom("bob@jabber.org");
     $xTag->SetFromID("bob@jabber.org");

     $xTag->SetTo("bob@jabber.org");
     $xTag->SetToID("bob@jabber.org");

     $xTag->SetReplyTo("bob@jabber.org");
     $xTag->SetReplyToID("bob@jabber.org");

     $xTag->SetCC("bob@jabber.org");
     $xTag->SetCCID("bob@jabber.org");

     $xTag->SetForwardedBy("bob@jabber.org");
     $xTag->SetForwardedByID("bob@jabber.org");

METHODS
=======

Retrieval functions
-------------------

     GetFrom() - returns a string with the Jabber Identifier of the
                 person who added the ident.

     GetStamp() - returns a string that represents the time stamp of
                  the ident.

     GetMessage() - returns a string with the message that describes
                    the nature of the ident.

     GetXMLNS() - returns a string with the namespace of the query that
                  the <iq/> contains.

Creation functions
------------------

     SetX(from=>string,       - set multiple fields in the <x/> at one
          stamp=>string,        time.  This is a cumulative and over
          message=>string)      writing action.  If you set the "from"
                                attribute twice, the second setting is
                                what is used.  If you set the status, and
                                then set the priority then both will be in
                                the <x/> tag.  For valid settings read the
                                specific Set functions below.

     SetFrom(string) - sets the from attribute of the server adding the
                       ident.

     SetStamp(string) - sets the timestamp of the ident.  If the string is
                        left blank then the module adds the current date/time
                        in the proper format as the stamp.

     SetMessage(string) - sets description of the ident.

     =head1 AUTHOR

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber X Out Of Bandwidth File Transfer Module
**********************************************

NAME
====

   Net::Jabber::X::Oob - Jabber X Out Of Bandwidth File Transfer Module

SYNOPSIS
========

     Net::Jabber::X::Oob is a companion to the Net::Jabber::X module.
     It provides the user a simple interface to set and retrieve all
     parts of a Jabber X Oob.

DESCRIPTION
===========

     To initialize the Oob with a Jabber <x/> you must pass it the
     XML::Parser Tree array from the module trying to access the <x/>.
     In the callback function:

     use Net::Jabber;

     sub iq {
       my $foo = new Net::Jabber::Foo(@_);

     my @xTags = $foo->GetX("jabber:x:oob");

     my $xTag;
     foreach $xTag (@xTags) {
     	$xTag->....

     }
     .
     .
     .
         }

     You now have access to all of the retrieval functions available.

     To create a new Oob to send to the server:

     use Net::Jabber;

     $foo = new Net::Jabber::Foo();
     $x = $foo->NewX("jabber:x:oob");

     Now you can call the creation functions below.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $url  = $xTag->GetURL();
     $desc = $xTag->GetDesc();

Creation functions
------------------

     $xTag->SetOob(UrL=>"http://my.web.server.com/~me/pics/bob.jpg",
     	          desc=>"Picture of Bob, the one and only");

     $xTag->SetURL("http://my.web.server.com/~me/pics/bobandme.jpg");
     $xTag->SetDesc("Bob and Me at the Open Source conference");

METHODS
=======

Retrieval functions
-------------------

     GetURL() - returns a string with the URL of the file being sent Oob.

     GetDesc() - returns a string with the description of the file being
                  sent Oob.

Creation functions
------------------

     SetOob(url=>string,  - set multiple fields in the <x/> at one
            desc=>string)   time.  This is a cumulative and over
                            writing action.  If you set the "url"
                            attribute twice, the second setting is
                            what is used.  If you set the url, and
                            then set the desc then both will be in
                            the <x/> tag.  For valid settings read the
                            specific Set functions below.

     SetURL(string) - sets the URL for the file being sent Oob.

     SetDesc(string) - sets the description for the file being sent Oob.

Test functions
--------------

     DefinedURL() - returns 1 if <url/> exists in the x, 0 otherwise.

     DefinedDesc() - returns 1 if <desc/> exists in the x, 0 otherwise.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber X Reply Presence Notification
************************************

NAME
====

   Net::Jabber::X::ReplyPres - Jabber X Reply Presence Notification

SYNOPSIS
========

     Net::Jabber::X::ReplyPres is a companion to the Net::Jabber::X module.
     It provides the user a simple interface to set and retrieve all
     parts of a Jabber X Reply Presence.

     The main purpose for this module is to handle the presence that is sent
     when a user is typing a reply to you.

DESCRIPTION
===========

     To initialize the ReplyPres with a Jabber <x/> you must pass it the
     XML::Parser Tree array from the module trying to access the <x/>.
     In the callback function:

     use Net::Jabber;

     sub presence {
       my $foo = new Net::Jabber::Foo(@_);

     my @xTags = $foo->GetX("jabber:x:replypres");

     my $xTag;
     foreach $xTag (@xTags) {
     	$xTag->....

     }
     .
     .
     .
         }

     You now have access to all of the retrieval functions available.

     To create a new ReplyPres to send to the server:

     use Net::Jabber;

     $foo = new Net::Jabber::Foo();
     $xTag = $foo->NewX("jabber:x:replypres");

     Now you can call the creation functions below.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     n/a

Creation functions
------------------

     n/a

METHODS
=======

Retrieval functions
-------------------

     n/a

Creation functions
------------------

     n/a

AUTHOR
======

   By Ryan Eatmon in November of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber X Roster Module
**********************

NAME
====

   Net::Jabber::X::Roster - Jabber X Roster Module

SYNOPSIS
========

     Net::Jabber::X::Roster is a companion to the Net::Jabber::X module.
     It provides the user a simple interface to set and retrieve all parts
     of a Jabber X Roster.

DESCRIPTION
===========

     To initialize the X with a Jabber <x/> and then access the roster
     query you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the x:

     use Net::Jabber;

     sub foo {
       my $foo = new Net::Jabber::Foo(@_);
       my $roster = $foo->GetX();
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new X roster to send to the server:

     use Net::Jabber;

     $client = new Net::Jabber::Client();
     ...

     $foo = new Net::Jabber::Foo();
     $roster = $foo->NewX("jabber:x:roster");
     ...

     $client->Send($foo);

     Using $roster you can call the creation functions below to populate the
     tag before sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     @items     = $roster->GetItems();
     @itemTrees = $roster->GetItemTrees();

Creation functions
------------------

     $item   = $roster->AddItem();
     $item   = $roster->AddItem(jid=>"bob\@jabber.org",
                                name=>"Bob",
                                groups=>["school","friends"]);

METHODS
=======

Retrieval functions
-------------------

     GetItems() - returns an array of Net::Jabber::X::Roster::Item objects.
                  These can be modified or accessed with the functions
                  available to them.

     GetItemTrees() - returns an array of XML::Parser objects that contain
                      the data for each item.

Creation functions
------------------

     AddItem(hash) - creates and returns a new Net::Jabbber::X::Roster::Item
                     object.  The argument hash is passed to the SetItem
                     function.  Check the Net::Jabber::X::Roster::Item
                     for valid values.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber X Roster Item Module
***************************

NAME
====

   Net::Jabber::X::Roster::Item - Jabber X Roster Item Module

SYNOPSIS
========

     Net::Jabber::X::Roster::Item is a companion to the
     Net::Jabber::X::Roster module.  It provides the user a simple
     interface to set and retrieve all parts of a Jabber Roster Item.

DESCRIPTION
===========

     To initialize the Item with a Jabber <x/> and then access the </x>
     you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the object
     type foo:

     use Net::Jabber;

     sub foo {
       my $foo = new Net::Jabber::Foo(@_);

     my @xTags = $foo->GetX("jabber:x:roster");

     my $xTag;
     foreach $xTag (@xTags) {
       my @items = $xTag->GetItems();
     	my $item;
     	foreach $item (@items) {
     	  $item->GetXXXX();
     	  .
     	  .
     	  .
     	}
     }
     .
     .
     .
         }

     You now have access to all of the retrieval functions available below.

     To create a new X Roster Item to send to another user:

     use Net::Jabber;

     $Client = new Net::Jabber::Client();
     ...

     $foo = new Net::Jabber::Foo();
     $roster = $foo->NewX("jabber:x:roster");
     $foo = $roster->AddItem();
     ...

     $client->Send($foo);

     Using $item you can call the creation functions below to populate the
     tag before sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $jid          = $item->GetJID();
     $jidJID       = $item->GetJID("jid");
     $name         = $item->GetName();
     @groups       = $item->GetGroups();

     @item         = $item->GetTree();
     $str          = $item->GetXML();

Creation functions
------------------

     $item->SetItem(jid=>'bob@jabber.org',
     		   name=>'Bob',
     		   subscription=>'both',
     		   groups=>[ 'friends','school' ]);

     $item->SetJID('bob@jabber.org');
     $item->SetName('Bob');
     $item->SetGroups(['friends','school']);

METHODS
=======

Retrieval functions
-------------------

     GetJID()      - returns either a string with the Jabber Identifier,
     GetJID("jid")   or a Net::Jabber::JID object for the person who is
                     listed in this <item/>.  To get the JID object set the
                     string to "jid", otherwise leave blank for the text
                     string.

     GetName() - returns a string with the name of the jabber ID.

     GetGroups() - returns an array of strings with the names of the groups
                  that this <item/> belongs to.

     GetXML() - returns the XML string that represents the <presence/>.
                This is used by the Send() function in Client.pm to send
                this object as a Jabber Presence.

     GetTree() - returns an array that contains the <presence/> tag
                 in XML::Parser Tree format.

Creation functions
------------------

     SetItem(jid=>string|JID, - set multiple fields in the <item/>
             name=>string,      at one time.  This is a cumulative
             groups=>array)     and overwriting action.  If you
                                set the "name" twice, the second
                                setting is what is used.  If you set
                                the name, and then set the
                                jid then both will be in the
                                <item/> tag.  For valid settings
                                read the specific Set functions below.
                                Note: groups does not behave in this
                                manner.  For each group setting a
                                new <group/> tag will be created.

     SetJID(string) - sets the Jabber Identifier.  You can either pass a
     SetJID(JID)      string or a JID object.  They must be valid Jabber
                      Identifiers or the server will return an error message.
                      (ie.  jabber:bob@jabber.org/Silent Bob, etc...)

     SetName(string) - sets the name to show in the roster instead of the
                       JID.

     SetGroups(array) - sets the group for each group in the array.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber X SXPM Delegate
**********************

NAME
====

   Net::Jabber::X::SXPM - Jabber X SXPM Delegate

SYNOPSIS
========

     Net::Jabber::X::SXPM is a companion to the Net::Jabber::X module.
     It provides the user a simple interface to set and retrieve all
     parts of a Jabber X SXPM.

DESCRIPTION
===========

     To initialize the SXPM with a Jabber <x/> you must pass it the
     XML::Parser Tree array from the module trying to access the <x/>.
     In the callback function:

     use Net::Jabber;

     sub iq {
       my $foo = new Net::Jabber::Foo(@_);

     my @xTags = $foo->GetX("jabber:x:sxpm");

     my $xTag;
     foreach $xTag (@xTags) {
     	$xTag->....

     }
     .
     .
     .
         }

     You now have access to all of the retrieval functions available.

     To create a new SXPM to send to the server:

     use Net::Jabber;

     $foo = new Net::Jabber::Foo();
     $xTag = $foo->NewX("jabber:x:sxpm");

     Now you can call the creation functions below.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $data        = $xTag->GetData();
     $datawidth   = $xTag->GetDataWidth();
     $datax       = $xTag->GetDataX();
     $datay       = $xTag->GetDataY();
     $boardheight = $xTag->GetBoardHeight();
     $boardwidth  = $xTag->GetBoardWidth();

     @maps      = $xTag->GetMaps();

Creation functions
------------------

     $xTag->SetSXPM(boardwidth=>400,
                    boardheight=>600);
     $xTag->SetSXPM(data=>"3 a2 a  a2 a3 ",
                    datawidth=>4,
     		   datax=>100,
     		   datay=>300);

     $xTag->SetData(" a aa a");
     $xTag->SetDataWidth(2);
     $xTag->SetDataX(15);
     $xTag->SetDataY(40);
     $xTag->SetBoardHeight(200);
     $xTag->SetBoardWidth(200);

     $map = $xTag->AddMap();

METHODS
=======

Retrieval functions
-------------------

     GetData() - returns a string with the compressed sxpm data in it.
                 To uncompress it, run through the string and anytime
                 you encounter a number, replace the number and following
                 character with that number of that character:

     10a5b10a = aaaaaaaaaabbbbbaaaaaaaaaa

     The use the GetDataWidth() function to get the width
     of a line and break the line to some number of width
     wide strings and that becomes the update block for the
     sxpm.

     GetDataWidth() - how long a row of the block is so that you can
                      chop up the sxpm block you were sent.

     GetDataX() - the x coordinate to overlay the sxpm data at.

     GetDataY() - the x coordinate to overlay the sxpm data at.

     GetBoardHeight() - returns an integer with the height of the new board
                        to create, or to resize the current board to.

     GetBoardWidth() - returns an integer with the width of the new board
                       to create, or to resize the current board to.

     GetMaps() - returns an array of Net::Jabber::X::SXPM::Map objects.
                 These can be modified or accessed with the functions
                 available to them.

Creation functions
------------------

     SetSXPM(data=>string,         - set multiple fields in the <x/> at one
             datawidth=>integer,     time.  This is a cumulative and over
             datax=>integer,         writing action.  If you set the "data"
             datay=>integer)         value twice, the second setting is
             boardheight=>integer,   what is used.  If you set the boardheight,
             boardwidth=>integer)    and then set the boardwidth then both
                                     will be in the <x/> tag.  For valid
                                     settings read the specific Set functions
                                     below.

     SetData(string) - sets the <data/> cdata to the string.  The string
                       must be valid sxpm data.

     SetDataWidth(integer) - sets the width so that the other side can
                             decode the sxpm data correctly.

     SetDataX(integer) - sets the x coordinate to anchor the sxpm data at.

     SetDataY(integer) - sets the y coordinate to anchor the sxpm data at.

     SetBoardHeight(string) - sets the board height when creating a new board,
                              or resizing the current board.

     SetBoardWidth(string) - sets the board width when creating a new board,
                             or resizing the current board.

     AddMap(XML::Parser tree) - creates a new Net::Jabbber::X::SXPM::Map
                                object and populates it with the tree if one
                                was passed in.  This returns the pointer to
                                the <map/> so you can modify it with the
                                creation functions from that module.

Test functions
--------------

     DefinedData() - returns 1 if the <data/> tag exists in the x,
                     0 otherwise.

     DefinedDataWidth() - returns 1 if the width attribute exists in the
                          <data/> tag, 0 otherwise.

     DefinedDataX() - returns 1 if the x attribute exists in the </data>
                      tag, 0 otherwise.

     DefinedDataY() - returns 1 if the y attribute exists in the </data>
                      tag, 0 otherwise.

     DefinedBoard() - returns 1 if there is a <board/> tag in the <x/>.

     DefinedBoardHeight() - returns 1 if the height attribute exists in the
                           <board/> tag, 0 otherwise.

     DefinedBoardWidth() - returns 1 if the width attribute exists in the
                          <board/> tag, 0 otherwise.

AUTHOR
======

   By Ryan Eatmon in January of 2001 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber X SXPM Map Module
************************

NAME
====

   Net::Jabber::X::SXPM::Map - Jabber X SXPM Map Module

SYNOPSIS
========

     Net::Jabber::X::SXPM::Map is a companion to the
     Net::Jabber::X::SXPM module.  It provides the user a simple
     interface to set and retrieve all parts of a Jabber SXPM Map.

DESCRIPTION
===========

     To initialize the Map with a Jabber <x/> and then access the </x>
     you must pass it the XML::Parser Tree array from the
     Net::Jabber::Client module.  In the callback function for the object
     type foo:

     use Net::Jabber;

     sub foo {
       my $foo = new Net::Jabber::Foo(@_);

     my @xTags = $foo->GetX("jabber:x:sxpm");

     my $xTag;
     foreach $xTag (@xTags) {
       my @maps = $xTag->GetMaps();
     	my $map;
     	foreach $map (@maps) {
     	  $map->GetXXXX();
     	  .
     	  .
     	  .
     	}
     }
     .
     .
     .
         }

     You now have access to all of the retrieval functions available below.

     To create a new IQ SXPM Map to send to the server:

     use Net::Jabber;

     $Client = new Net::Jabber::Client();
     ...

     $foo = new Net::Jabber::Foo();
     $sxpm = $foo->NewX("jabber:x:sxpm");
     $foo = $sxpm->AddMap();
     ...

     $client->Send($foo);

     Using $map you can call the creation functions below to populate the
     tag before sending it.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $char  = $map->GetChar();
     $color = $map->GetColor();

     @map   = $map->GetTree();
     $str   = $map->GetXML();

Creation functions
------------------

     $map->SetMap(char=>"@");     # for erasing a pixel
     $map->SetMap(char=>"a",
     		 color=>"#FFFFFF");

     $map->SetChar('b');
     $map->SetColor('#FF0000');

METHODS
=======

Retrieval functions
-------------------

     GetChar() - returns a string with the character of the <map/>.

     GetColor() - returns a string with the RGB color of the <map/>.

     GetXML() - returns the XML string that represents the <presence/>.
                This is used by the Send() function in Client.pm to send
                this object as a Jabber Presence.

     GetTree() - returns an array that contains the <presence/> tag
                 in XML::Parser Tree format.

Creation functions
------------------

     SetMap(char=>string,  - set multiple fields in the <map/>
            color=>string)   at one time.  This is a cumulative
                             and overwriting action.  If you
                             set the "char" twice, the second
                             setting is what is used.  If you set
                             the char, and then set the color
                             then both will be in the <map/>
                             tag.  For valid settings read the
                             specific Set functions below.

     SetChar(string) - sets the character that is associated with this
                       color map entry.

     SetColor(string) - sets the color that is associated with this
                        color map entry.  Must be in RGB #xxxxxx format.

AUTHOR
======

   By Ryan Eatmon in January of 2001 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber X Signed Module
**********************

NAME
====

   Net::Jabber::X::Signed - Jabber X Signed Module

SYNOPSIS
========

     Net::Jabber::X::Signed is a companion to the Net::Jabber::X module.
     It provides the user a simple interface to set and retrieve all
     parts of a Jabber X Signed.

DESCRIPTION
===========

     To initialize the Signed with a Jabber <x/> you must pass it the
     XML::Parser Tree array from the module trying to access the <x/>.
     In the callback function:

     use Net::Jabber;

     sub iq {
       my $foo = new Net::Jabber::Foo(@_);

     my @xTags = $foo->GetX("jabber:x:signed");

     my $xTag;
     foreach $xTag (@xTags) {
     	$xTag->....

     }
     .
     .
     .
         }

     You now have access to all of the retrieval functions available.

     To create a new Signed to send to the server:

     use Net::Jabber;

     $foo = new Net::Jabber::Foo();
     $x = $foo->NewX("jabber:x:signed");

     Now you can call the creation functions below.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $signature = $xTag->GetSignature();

Creation functions
------------------

     $xTag->SetSigned(signature=>data);

     $xTag->SetSignature(data);

METHODS
=======

Retrieval functions
-------------------

     GetSignature() - returns a string with the signature data.

Creation functions
------------------

     SetSigned(signature=>string) - set multiple fields in the <x/> at one
                                    time.  This is a cumulative and over
                                    writing action.  If you set the
                                    "signature" attribute twice, the second
                                    setting is what is used.  If you set the
                                    signature, and then set another field
                                    then both will be in the <x/> tag.  For
                                    valid settings read the specific Set
                                    functions below.

     SetSignature(string) - sets the data for the signature

AUTHOR
======

   By Ryan Eatmon in December of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Jabber XDB Library
******************

NAME
====

   Net::Jabber::XDB - Jabber XDB Library

SYNOPSIS
========

     Net::Jabber::XDB is a companion to the Net::Jabber module. It
     provides the user a simple interface to set and retrieve all
     parts of a Jabber XDB.

DESCRIPTION
===========

     Net::Jabber::XDB differs from the other Net::Jabber::* modules in that
     the XMLNS of the data is split out into more submodules under
     XDB.  For specifics on each module please view the documentation
     for each Net::Jabber::Data::* module.  To see the list of avilable
     namspaces and modules see Net::Jabber::Data.

     To initialize the XDB with a Jabber <xdb/> you must pass it the
     XML::Parser Tree array.  For example:

     my $xdb = new Net::Jabber::XDB(@tree);

     There has been a change from the old way of handling the callbacks.
     You no longer have to do the above, a Net::Jabber::XDB object is passed
     to the callback function for the xdb:

     use Net::Jabber;

     sub xdb {
       my ($XDB) = @_;
       .
       .
       .
     }

     You now have access to all of the retrieval functions available.

     To create a new xdb to send to the server:

     use Net::Jabber;

     $XDB = new Net::Jabber::XDB();
     $XDBType = $XDB->NewData( type );
     $XDBType->SetXXXXX("yyyyy");

     Now you can call the creation functions for the XDB, and for the <data/>
     on the new Data object itself.  See below for the <xdb/> functions, and
     in each data module for those functions.

     For more information about the array format being passed to the CallBack
     please read the Net::Jabber::Client documentation.

Retrieval functions
-------------------

     $to       = $XDB->GetTo();
     $toJID    = $XDB->GetTo("jid");
     $from     = $XDB->GetFrom();
     $fromJID  = $XDB->GetFrom("jid");
     $type     = $XDB->GetType();

     $data     = $XDB->GetData();
     $dataTree = $XDB->GetDataTree();

     $str      = $XDB->GetXML();
     @xdb     d  = $XDB->GetTree();

Creation functions
------------------

     $XDB->SetXDB(tYpE=>"get",
     		 tO=>"bob@jabber.org");

     $XDB->SetTo("bob@jabber.org");
     $XDB->SetFrom("me\@jabber.org");
     $XDB->SetType("set");

     $XDBObject = $XDB->NewData("jabber:iq:auth");
     $XDBObject = $XDB->NewData("jabber:iq:roster");

     $xdbReply = $XDB->Reply();
     $xdbReply = $XDB->Reply("client");
     $xdbReply = $XDB->Reply("transport");

Test functions
--------------

     $test = $XDB->DefinedTo();
     $test = $XDB->DefinedFrom();
     $test = $XDB->DefinedType();

METHODS
=======

Retrieval functions
-------------------

     GetTo()      - returns either a string with the Jabber Identifier,
     GetTo("jid")   or a Net::Jabber::JID object for the person who is
                    going to receive the <xdb/>.  To get the JID
                    object set the string to "jid", otherwise leave
                    blank for the text string.

     GetFrom()      -  returns either a string with the Jabber Identifier,
     GetFrom("jid")    or a Net::Jabber::JID object for the person who
                       sent the <xdb/>.  To get the JID object set
                       the string to "jid", otherwise leave blank for the
                       text string.

     GetType() - returns a string with the type <xdb/> this is.

     GetData() - returns a Net::Jabber::Data object that contains the data
                  in the <data/> of the <xdb/>.

     GetDataTree() - returns an XML::Parser::Tree object that contains the
                      data in the <data/> of the <xdb/>.

     GetXML() - returns the XML string that represents the <xdb/>. This
                is used by the Send() function in Client.pm to send
                this object as a Jabber XDB.

     GetTree() - returns an array that contains the <xdb/> tag in XML::Parser
                 Tree format.

Creation functions
------------------

     SetXDB(to=>string|JID,    - set multiple fields in the <xdb/> at one
            from=>string|JID,    time.  This is a cumulative and over
            id=>string,          writing action.  If you set the "to"
            type=>string,        attribute twice, the second setting is
            errorcode=>string,   what is used.  If you set the status, and
            error=>string)       then set the priority then both will be in
                                 the <xdb/> tag.  For valid settings read the
                                 specific Set functions below.

     SetTo(string) - sets the to attribute.  You can either pass a string
     SetTo(JID)      or a JID object.  They must be a valid Jabber
                     Identifiers or the server will return an error message.
                     (ie.  jabber:bob@jabber.org, etc...)

     SetFrom(string) - sets the from attribute.  You can either pass a string
     SetFrom(JID)      or a JID object.  They must be a valid Jabber
                       Identifiers or the server will return an error message.
                       (ie.  jabber:bob@jabber.org, etc...)

     SetType(string) - sets the type attribute.  Valid settings are:

     get      request information
     set      set information
     result   results of a get

     NewData(string) - creates a new Net::Jabber::Data object with the
                        namespace in the string.  In order for this function
                        to work with a custom namespace, you must define and
                        register that namespace with the XDB module.  For more
                        information please read the documentation for
                        Net::Jabber::Data.  NOTE: Jabber does not support
                        custom XDBs at the time of this writing.  This was just
                        including in case they do at some point.

     Reply(type=>string) - creates a new XDB object and populates the to/from
                           fields.  The type will be set in the <xdb/>.

Test functions
--------------

     DefinedTo() - returns 1 if the to attribute is defined in the <xdb/>,
                   0 otherwise.

     DefinedFrom() - returns 1 if the from attribute is defined in the <xdb/>,
                     0 otherwise.

     DefinedType() - returns 1 if the type attribute is defined in the <xdb/>,
                     0 otherwise.

AUTHOR
======

   By Ryan Eatmon in May of 2000 for http://jabber.org..

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Lightweight Directory Access Protocol
*************************************

NAME
====

   Net::LDAP - Lightweight Directory Access Protocol

SYNOPSIS
========

     use Net::LDAP;

     $ldap = Net::LDAP->new('ldap.bigfoot.com') or die "$@";

     $ldap->bind ;    # an anonymous bind

     $mesg = $ldap->search (  # perform a search
                            base   => "c=US",
                            filter => "(&(sn=Barr) (o=Texas Instruments))"
                           );

     $mesg->code && die $mesg->error;

     foreach $entry ($mesg->all_entries) { $entry->dump; }

     $ldap->unbind;   # take down session

     $ldap = Net::LDAP->new('ldap.umich.edu');

     $ldap->bind (   # bind to a directory with dn and password
                  dn       => 'cn=root, o=University of Michigan, c=us',
                  password => 'secret'
                 );

     $result = $ldap->add (
                   dn   => 'cn = Barbara Jensen, o=University of Michigan, c=us',
                   attr => [ 'cn'   => ['Barbara Jensen', 'Barbs Jensen'],
                    	 'sn    => 'Jensen',
                    	 'mail' => 'b.jensen@umich.edu',
                    	 'objectclass' => ['top', 'person',
                                               'organizationalPerson',
                                               'inetOrgPerson' ],
                           ]
                 );

     $result->code && warn "failed to add entry: ", $result->error ;

DESCRIPTION
===========

   Net::LDAP is a collection of modules that implements a LDAP services API
for Perl programs. The module may be used to search directories or perform
maintenance functions such as add, deleting or modify entries in an LDAP
directory.

   This document assumes that the reader has some knowledge of the LDAP
protocol.

CONSTRUCTOR
===========

new ( HOST [, OPTIONS ] )
     Creates a new Net::LDAP object and opens a connection to the named
     host.  OPTIONS is a list of key-value pairs, valid options are :-

    port
          Port to connect to on the remote server.

    timeout
          Timeout passed to `IO::Socket|IO::Socket' in this node when
          connecting the remote server.  (Default: 120)

    debug
          If passed a non-zero value then debug data will be sent to
          `STDERR'. The bits of this value are :-

               1   Show outgoing packets (using asn_hexdump).
               2   Show incoming packets (using asn_hexdump).
               4   Show outgoing packets (using asn_dump).
               8   Show incoming packets (using asn_dump).

    async
          Perform all operations asynchronously if passed a *true* value.

    onerror
          If set then Net::LDAP will check all responses for errors on all
          methods if the object is in synchronous mode. If an error is
          detected then the specified action will be taken. Valid values
          and their actions are.

         die
               Net::LDAP will croak with an appropriate message.

         warn
               Net::LDAP will warn with an appropriate message.

         undef
               Net::LDAP will warn with an appropriate message if -w is in
               effect.  The method that was called will return undef

         CODEREF
               The given coderef will be called in a scalar context with a
               single argument, the result message. The value returned
               will be the return value for the method that was called.

     Example

          $ldap = Net::LDAP->new('remote.host', async => 1);

METHODS
=======

   Each of the following methods take as arguments some number of fixed
parameters followed by options, these options are passed in a named
fashion, for example

     $mesg = $ldap->bind( "me", password => "mypasswd");

   The return value from these methods is an object derived from the
`Net::LDAP::Message|Net::LDAP::Message' in this node class. The methods of
this class allow you to examine the status of request.

abandon ( ID [, OPTIONS ] )
     Request server to abandon a request. The id to abandon may be passed
     as the first parameter or as part of the options list. The ID may be
     a number or a object which is a sub-class of
     `Net::LDAP::Message|Net::LDAP::Message' in this node, returned from a
     previous method call.

    id
          This option is here for *compatibility only*, and may be removed
          in future.  Previous releases did not take the ID argument which
          replaces this option.

    control
          See `' in this node below

    callback
          See `' in this node below

     Example

          $mesg = $ldap->search( @search_args );

          $ldap->abandon( $mesg ); # This could be written as $mesg->abandon

add ( DN [, OPTIONS ] )
     Add an entry to the directory. The *DN* argument can be either a
     `Net::LDAP::Entry|Net::LDAP::Entry' in this node object or a string.

    dn
          This option is here for *compatibility only*, and may be removed
          in future.  Previous releases did not take the *DN* argument
          which replaces this option.

    attrs
          This argument is a reference to a list of attribute-value pairs.
          Attributes with multiple values can be added as either multiple
          entries or the value could be a reference to a list of values.

          This argument is not used if *DN* is a
          `Net::LDAP::Entry|Net::LDAP::Entry' in this node object.

    control
          See `' in this node below

    callback
          See `' in this node below

     Example

          # $entry is an object of class Net::LDAP::Entry
          $mesg = $ldap->add( $entry );

          $mesg = $ldap->add( $DN,
            attrs => [
              name  => 'Graham Barr',
              attr  => 'value1',
              attr  => 'value2',
              multi => [qw(value1 value2)]
            ]
          );

bind ( [ DN [, OPTIONS ]] )
     Bind to the server. *DN* is the DN to bind as. An anonymous bind may
     be done by calling bind without any arguments.

    dn
          This option is here for *compatibility only*, and may be removed
          in future.  Previous releases did not take the *DN* argument
          which replaces this option.

    control
          See `' in this node below

    callback
          See `' in this node below

     Only one of the following should be given, if none are given then
     noauth is assumed.

    noauth
    anonymous
          Bind without any password, the value passed with this option is
          ignored. This is the default if no arguments are given.

    password
          Bind with the given password.

    kerberos41
          Bind using Kerberos V4.1 **not supported**.

    kerberos42
          Bind using Kerberos V4.2 **not supported**.

    sasl
          Bind using a SASL mechanism. The argument given should be a
          sub-class of `Authen::SASL|Authen::SASL' in this node.

     Example

          $ldap->bind; # Anonymous bind

          $ldap->bind( $DN, password => $password);

          # $sasl is an object of class Authen::SASL
          $ldap->bind( $DN, sasl => $sasl, version => 3);

compare ( DN, OPTIONS )
     Perform a comparison on the server.  *DN* is the DN which the
     comparison is to be performed. *DN* May be a string or a
     `Net::LDAP::Entry|Net::LDAP::Entry' in this node object.

    dn
          This option is here for *compatibility only*, and may be removed
          in future.  Previous releases did not take the *DN* argument
          which replaces this option.

    attr
          The name of the attribute to compare.

    value
          The value to compare with.

    control
          See `' in this node below.

    callback
          See `' in this node below.

     Example

          $ldap->compare( $DN,
            attr  => 'cn',
            value => 'Graham Barr'
          );

delete ( DN [, OPTIONS ] )
     Delete *DN* from the server. *DN* May be a string or a
     `Net::LDAP::Entry|Net::LDAP::Entry' in this node object.

    dn
          This option is here for *compatibility only*, and may be removed
          in future.  Previous releases did not take the *DN* argument
          which replaces this option.

    control
          See `' in this node below.

    callback
          See `' in this node below.

     Example

          $ldap->delete( $dn );

moddn ( DN, OPTIONS )
     Modify the DN for *DN* on the server. *DN* May be a string or a
     `Net::LDAP::Entry|Net::LDAP::Entry' in this node object.

    dn
          This option is here for *compatibility only*, and may be removed
          in future.  Previous releases did not take the *DN* argument
          which replaces this option.

    newrdn
          This value should be a new RDN to assign to *DN*.

    deleteoldrdn
          This value should be *true* if the existing RDN is to be deleted.

    newsuperior
          If given this value should be the DN of the new superior for
          *DN*.

    control
          See `' in this node below.

    callback
          See `' in this node below.

     Example

          $ldap->moddn( $dn, newrdn => 'cn=Graham Barr');

modify ( DN, OPTIONS )
     Modify the contents of *DN* on the server. *DN* May be a string or a
     `Net::LDAP::Entry|Net::LDAP::Entry' in this node object.

    dn
          This option is here for *compatibility only*, and may be removed
          in future.  Previous releases did not take the *DN* argument
          which replaces this option.

    add
          The add option should be a reference to a HASH. The values of the
          HASH are the attributes to add, and the values may be a string
          or a reference to a list of values.

    delete
          A reference to an ARRAY of attributes to delete or a reference
          to a HASH (as in add) if only specific values should be deleted.
          If the value for any attribute in the HASH is a reference to an
          empty ARRAY the all instances of the attribute will be deleted.

    replace
          The <replace> option takes a argument in the same form as add,
          but will cause any existing attributes with the same name to be
          replaced. If the value for any attribute in the HASH is a
          reference to an empty ARRAY the all instances of the attribute
          will be deleted.

    changes
          This is an alternative to add, delete and replace where the
          whole operation can be given in a single argument. The argument
          should be a reference to an ARRAY.

          Values in the ARRAY are used in pairs, the first is the operation
          add, delete or replace and the second is a reference to an ARRAY
          of attribute values.

          The attribute value list is also used in pairs. The first value
          in each pair is the attribute name and the second is a reference
          to a list of values.

          Use this form if you want to control the order in which the
          operations will be performed.

    control
          See `' in this node below.

    callback
          See `' in this node below.

     Example

          $ldap->modify( $dn, add => { sn => 'Barr' } );

          $ldap->modify( $dn, delete => [qw(faxNumber)]);

          $ldap->modify( $dn, delete => { 'telephoneNumber' => '911' });

          $ldap->modify( $dn, replace => { 'email' => 'gbarr@pobox.com' });

          $ldap->modify( $dn,
            changes => [
              add     => [ sn => 'Barr' ],              # Add sn=Barr
              delete  => [ faxNumber => []], 	       # Delete all fax numbers
              delete  => [ telephoneNumber => ['911']], # delete phone number 911
              replace => [ email => 'gbarr@pobox.com']  # change email address
            ]
          );

search ( OPTIONS )
     Request that a search be performed.  This can be used to read
     attributes from a single entry, from entries immediately below a
     particular entry, or a whole subtree of entries.

     The result is an object of class
     `Net::LDAP::Search|Net::LDAP::Search' in this node.

    base
          The DN that is the base object entry relative to which the
          search is to be performed.

    scope
          By default the search is performed on the whole tree below the
          specified base object. This may be chaned by specifying a scope
          parameter with one of the following values.

         base
               Search only the base object.

         one
               Search the entries immediately below the base object.

         sub
               Search the whole tree below the base object. This is the
               default.

    deref
          By default aliases are dereferenced to locate the base object
          for the search, but not when searching subordinates of the base
          object. This may be changed by specifying a deref parameter with
          one of the following values.

         never
               Do not dereference aliases in searching or in locating the
               base object of the search.

         search
               Dereference aliases in subordinates of the base object in
               searching, but not in locating the base object of the
               search.

         find
               Dereference aliases in locating the base object of the
               search, but not when searching subordinates of the base
               object. This is the default.

         always
               Dereference aliases both in searching and in locating the
               base object of the search.

    sizelimit
          A sizelimit that restricts the maximum number of entries to be
          returned as a result of the search. A value of 0, and the
          default, means that no restriction is requested.  Servers may
          enforce a maximum number of entries to return.

    timelimit
          A timelimit that restricts the maximum time (in seconds) allowed
          for a search. A value of 0, and the default, means that no
          timelimit will be requested.

    typesonly
          An indicator as to whether search results should contain both
          attribute types and values, or just attribute types.  Setting
          this parameter to a *true* value causes only attribute types (no
          values) to be returned.  Setting this field to a false causes
          both attribute types and values to be returned. The default is
          to return both attribute types and values.

    filter
          A filter that defines the conditions an entry in the directory
          must meet in order for it to be returned by the search. This may
          be a string or a `Net::LDAP::Filter|Net::LDAP::Filter' in this
          node object. See `Net::LDAP::Filter|Net::LDAP::Filter' in this
          node for a defintion of the filter format.

    attrs
          A reference to a list of attributes to be returned for each
          entry that matches the search filter.

          If not specified, then the server will return the attributes
          that are specified as accessible by default given your bind
          credentials.

          Certain additional attributes such as "createtimestamp" and other
          operational attributes may also be available for the asking:

               $ldap->search( ... , attrs => ['createtimestamp'] , ... );

          To retreive the default attributes and additional ones, use '*'.

               $ldap->search( ... , attrs => ['*', 'createtimestamp'] , ... );

    control
          See `' in this node below.

    callback
          See `' in this node below.

     Example

          $mesg = $ldap->search(
            base   => $base_dn,
            scope  => 'sub',
            filter => '(|(objectclass=rfc822mailgroup)(sn=jones))'
          );

          Net::LDAP::LDIF->new(\*STDOUT,"w")->write($mesg->entries);

unbind
     The unbind method does not take any parameters and will unbind you
     from the server. While some servers may allow you to re-bind or
     perform other operations after unbinding, the only portable operation
     is closing the connection. In the case that you wish to switch to
     another set of credentials while continuing to use the same
     connection, re-binding with another DN and password, without
     unbind-ing, will generally work.

     Example

          $ldap->unbind;

   The following methods are for convenience.

async
     Returns *true* if the LDAP operations are being performed
     asynchronously.

debug ( [ VALUE ] )
     If VALUE is given the debug bit-value will be set to VALUE and the
     previous value will be returned. If not given the bit-value will
     remain unchanged and will be returned.

sync ( [ MESG ] )
     Calling this method will synchronize the client with the server. It
     will not return until all requests have been completed, or id *MESG*
     is given it will return when *MESG* has been completed.

     Returns an error code defined in
     `Net::LDAP::Constant|Net::LDAP::Constant' in this node.

version
     Returns the version of the LDAP protocol that is being used.

CONTROLS
========

   Many of the methods described above accept a control option.  This
allows the user to pass controls to the server as described in LDAPv3. The
value to the control argument may be either a single control or a
reference to an array of controls.

   A control is a reference to a HASH and should contain the three
elements below. If any of the controls are blessed then the methoc to_asn
will be called which should return a reference to a HASH containing the
three elements described below.

type
     This element must be present and is the name of the type of control
     being requested.

critical
     critical is optional and should be a boolean value, if it is not
     specified then it is assumed to be false.

value
     If the control being requested requires a value then this element
     should hold the value for the server.

CALLBACKS
=========

   Most of the above commands accept a callback option. This option should
be a reference to a subroutine. This subroutine will be called for each
packet received from the server as a response to the request sent.

   When the subroutine is called the first argument will be the
`Net::LDAP::Message|Net::LDAP::Message' in this node object which was
returned from the method.

   If the request is a search then multiple packets can be received from
the server. Each entry is received as a separate packet. For each of these
the subroutine will be called with a `Net::LDAP::Entry|Net::LDAP::Entry'
in this node object as the second argument.

   During a search the server may also send a list of references. When such
a list is received then the subroutine will be called with a
`Net::LDAP::Reference|Net::LDAP::Reference' in this node object as the
second argument.

LDAP ERROR CODES
================

   Net::LDAP also exports constants for the error codes that can be
received from the server, see `Net::LDAP::Constant|Net::LDAP::Constant' in
this node.

SEE ALSO
========

   `Net::LDAP::Constant|Net::LDAP::Constant' in this node,
`Net::LDAP::Control|Net::LDAP::Control' in this node,
`Net::LDAP::Entry|Net::LDAP::Entry' in this node,
`Net::LDAP::Filter|Net::LDAP::Filter' in this node,
`Net::LDAP::Message|Net::LDAP::Message' in this node,
`Net::LDAP::Reference|Net::LDAP::Reference' in this node,
`Net::LDAP::Search|Net::LDAP::Search' in this node, `Other online
documentation|Net::LDAP::RFC' in this node

   The homepage for the perl-ldap modules can be found at
http://www.pobox.com/~gbarr/perl-ldap/.

ACKNOWLEDGEMENTS
================

   This document is based on a document originally written by Russell
Fulton <r.fulton@auckland.ac.nz>.

   Chris Ridd @isode.com for the many hours spent testing and contribution
of the ldap* command line utilities.

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

   Please report any bugs, or post any suggestions, to the perl-ldap
mailing list <perl-ldap-dev@lists.sourceforge.net>

COPYRIGHT
=========

   Copyright (c) 1997-2000 Graham Barr. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

BER encoding for LDAP
*********************

NAME
====

   Net::LDAP::BER - BER encoding for LDAP

SYNOPSIS
========

     use Net::LDAP::BER;

     $ber = Net::LDAP::BER->new;

     $ber->encode( # A bind encode
       SEQUENCE => [
         INTEGER  => $mesg->mesg_id,
         REQ_BIND => [
           INTEGER     => $version,
           LDAPDN      => $dn || "",
           $auth_type  => $passwd
         ],
         OPTIONAL => [ BER => $ctrl ]
       ]
     );

     $ber->decode( # The decode in Net::LDAP::Message
       $self->result_tag => [
         ENUM     => \$code,
         STRING   => \$dn,
         STRING   => \$error,
         OPTIONAL => [
           LDAP_REFERRAL => [
             STRING => $referral = []
           ]
         ]
       ]
     );

DESCRIPTION
===========

   `Net::LDAP::BER' is a sub-class of Convert/BER, and
inherits all its methods from Convert/BER. It defines
the following tags

REQ_BIND
     [APPLICATION 0] SEQUENCE

REQ_UNBIND
     [APPLICATION 2] NULL

REQ_SEARCH
     [APPLICATION 3] SEQUENCE

REQ_MODIFY
     [APPLICATION 6] SEQUENCE

REQ_ADD
     [APPLICATION 8] SEQUENCE

REQ_DELETE
     [APPLICATION 10] STRING

REQ_MODDN
     [APPLICATION 12] SEQUENCE

REQ_COMPARE
     [APPLICATION 15] SEQUENCE

REQ_ABANDON
     [APPLICATION 16] INTEGER

REQ_EXTEND
     [APPLICATION 17] SEQUENCE

RES_BIND
     [APPLICATION 1] SEQUENCE

RES_SEARCH_ENTRY
     [APPLICATION 4] SEQUENCE

RES_SEARCH_RESULT
     [APPLICATION 5] SEQUENCE

RES_SEARCH_REF
     [APPLICATION 19] SEQUENCE

RES_MODIFY
     [APPLICATION 7] SEQUENCE

RES_ADD
     [APPLICATION 9] SEQUENCE

RES_DELETE
     [APPLICATION 11] SEQUENCE

RES_MODDN
     [APPLICATION 13] SEQUENCE

RES_COMPARE
     [APPLICATION 15] SEQUENCE

RES_EXTEND
     [APPLICATION 24] SEQUENCE

AUTH_NONE
     [CONTEXT 0] STRING

AUTH_SIMPLE
     [CONTEXT 0] STRING

AUTH_KRBV41
     [CONTEXT 1] STRING

AUTH_KRBV42
     [CONTEXT 2] STRING

AUTH_SASL
     [CONTEXT 3] SEQUENCE

SASL_CREDENTIALS
     [CONTEXT 7] STRING

SASL_MECHANISM
     STRING

FILTER_AND
     [CONTEXT 0] SEQUENCE

FILTER_OR
     [CONTEXT 1] SEQUENCE

FILTER_NOT
     [CONTEXT 2] SEQUENCE

FILTER_EQ
     [CONTEXT 3] SEQUENCE

FILTER_SUBSTRS
     [CONTEXT 4] SEQUENCE

FILTER_GE
     [CONTEXT 5] SEQUENCE

FILTER_LE
     [CONTEXT 6] SEQUENCE

FILTER_PRESENT
     [CONTEXT 7] STRING

FILTER_APPROX
     [CONTEXT 8] SEQUENCE

SUBSTR_INITIAL
     [CONTEXT 0] STRING

SUBSTR_ANY
     [CONTEXT 1] STRING

SUBSTR_FINAL
     [CONTEXT 2] STRING

LDAPDN
     STRING

LDAPOID
     STRING

LDAP_CONTROLS
     [CONTEXT 0] SEQUENCE

LDAP_REFERRAL
     [CONTEXT 3] SEQUENCE

EXTEND_REQ_NAME
     [CONTEXT 0] STRING

EXTEND_REQ_VALUE
     [CONTEXT 1] STRING

MOD_SUPERIOR
     [CONTEXT 0] STRING

SEE ALSO
========

   See Net/LDAP, Convert/BER,

ACKNOWLEDGEMENTS
================

   This document is based on a document originally written by Russell
Fulton <`r.fulton@auckland.ac.nz'>.

AUTHOR
======

   Graham Barr <`gbarr@pobox.com'>.

   Please report any bugs, or post any suggestions, to the perl-ldap
mailing list
``<perl-ldap@mail.med.cornell.edu>|mailto:perl-ldap@mail.med.cornell.edu'
in this node'.

COPYRIGHT
=========

   Copyright (c) 1997-2000 Graham Barr. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Constants for use with Net::LDAP
********************************

NAME
====

   Net::LDAP::Constant - Constants for use with Net::LDAP

SYNOPSIS
========

     use Net::LDAP qw(LDAP_SUCCESS LDAP_PROTOCOL_ERROR);

     # import all constants
     use Net::LDAP qw(:all);

DESCRIPTION
===========

   *Net::LDAP::Constant* exports constant subroutines for the following
LDAP error codes.

LDAP_SUCCESS
     Operation completed without error

LDAP_OPERATIONS_ERROR
     Server encountered an internal error

LDAP_PROTOCOL_ERROR
     Unrecognized version number or incorrect PDU structure

LDAP_TIMELIMIT_EXCEEDED
     The time limit on a search operation has been exceeded

LDAP_SIZELIMIT_EXCEEDED
     The maximum number of search results to return has been exceeded.

LDAP_COMPARE_FALSE
     This code is returned when a compare request completes and the
     attribute value given is not in the entry specified

LDAP_COMPARE_TRUE
     This code is returned when a compare request completes and the
     attribute value given is in the entry specified

LDAP_AUTH_METHOD_NOT_SUPPORTED
     Unrecognized SASL mechanism name

LDAP_STRONG_AUTH_REQUIRED
     The server requires authentication be performed with a SASL mechanism

LDAP_PARTIAL_RESULTS
     Returned to version 2 clients when a referral is returned. The
     response will contain a list of URL's for other servers.

LDAP_REFERRAL
     The server is referring the client to another server. The response
     will contain a list of URL's

LDAP_ADMIN_LIMIT_EXCEEDED
     The server has exceed the maximum number of entries to search while
     gathering a list of search result candidates

LDAP_UNAVAILABLE_CRITICAL_EXT
     A control or matching rule specified in the request is not supported
     by the server

LDAP_CONFIDENTIALITY_REQUIRED
     This result code is returned when confidentiality is required to
     perform a given operation

LDAP_SASL_BIND_IN_PROGRESS
     The server requires the client to send a new bind request, with the
     same SASL mechanism, to continue the authentication process

LDAP_NO_SUCH_ATTRIBUTE
     The request referenced an attribute that does not exist

LDAP_UNDEFINED_TYPE
     The request contains an undefined attribute type

LDAP_INAPPROPRIATE_MATCHING
     An extensible matching rule in the given filter does not apply to the
     specified attribute

LDAP_CONSTRAINT_VIOLATION
     The request contains a value which does not meet with certain
     constraints.  This result can be returned as a consequence of

        * The request was to add or modify a user password, and the
          password fails to meet the criteria the server is configured to
          check. This could be that the password is too short, or a
          recognizable word (e.g. it matches one of the attributes in the
          users entry) or it matches a previous password used by the same
          user.

        * The request is a bind request to a user account that has been
          locked

LDAP_TYPE_OR_VALUE_EXISTS
     The request attempted to add an attribute type or value that already
     exists

LDAP_INVALID_SYNTAX
     Some part of the request contained an invalid syntax. It could be a
     search with an invalid filter or a request to modify the schema and
     the given schema has a bad syntax.

LDAP_NO_SUCH_OBJECT
     The server cannot find an object specified in the request

LDAP_ALIAS_PROBLEM
     Server encountered a problem while attempting to dereference an alias

LDAP_INVALID_DN_SYNTAX
     The request contained an invalid DN

LDAP_IS_LEAF
     The specified entry is a leaf entry

LDAP_ALIAS_DEREF_PROBLEM
     Server encountered a problem while attempting to dereference an alias

LDAP_INAPPROPRIATE_AUTH
     The server requires the client which had attempted to bind
     anonymously or without supplying credentials to provide some form of
     credentials

LDAP_INVALID_CREDENTIALS
     The wrong password was supplied or the SASL credentials could not be
     processed

LDAP_INSUFFICIENT_ACCESS
     The client does not have sufficient access to perform the requested
     operation

LDAP_BUSY
     The server is too busy to perform requested operation

LDAP_UNAVAILABLE
     The server in unavailable to perform the request, or the server is
     shutting down

LDAP_UNWILLING_TO_PERFORM
     The server is unwilling to perform the requested operation

LDAP_LOOP_DETECT
     The server was unable to perform the request due to an internal loop
     detected

LDAP_SORT_CONTROL_MISSING
     The search contained a "virtual list view" control, but not a
     server-side sorting control, which is required when a "virtual list
     view" is given.

LDAP_INDEX_RANGE_ERROR
     The search contained a control for a "virtual list view" and the
     results exceeded the range specified by the requested offsets.

LDAP_NAMING_VIOLATION
     The request violates the structure of the DIT

LDAP_OBJECT_CLASS_VIOLATION
     The request specifies a change to an existing entry or the addition
     of a new entry that does not comply with the servers schema

LDAP_NOT_ALLOWED_ON_NONLEAF
     The requested operation is not allowed on an entry that has child
     entries

LDAP_NOT_ALLOWED_ON_RDN
     The requested operation ill affect the RDN of the entry

LDAP_ALREADY_EXISTS
     The client attempted to add an entry that already exists. This can
     occur as a result of

        * An add request was submitted with a DN that already exists

        * A modify DN requested was submitted, where the requested new DN
          already exists

        * The request is adding an attribute to the schema and an
          attribute with the given OID or name already exists

LDAP_NO_OBJECT_CLASS_MODS
     Request attempt to modify the object class of an entry that should
     not be modified

LDAP_RESULTS_TOO_LARGE
     The results of the request are to large

LDAP_AFFECTS_MULTIPLE_DSAS
     The requested operation needs to be performed on multiple servers
     where the requested operation is not permitted

LDAP_OTHER
     An unknown error has occurred

LDAP_SERVER_DOWN
     Net::LDAP cannot establish a connection or the connection has been
     lost

LDAP_LOCAL_ERROR
     An error occurred in Net::LDAP

LDAP_ENCODING_ERROR
     Net::LDAP encountered an error while encoding the request packet that
     would have been sent to the server

LDAP_DECODING_ERROR
     Net::LDAP encountered an error while decoding a response packet from
     the server.

LDAP_TIMEOUT
     Net::LDAP timeout while waiting for a response from the server

LDAP_AUTH_UNKNOWN
     The method of authentication requested in a bind request is unknown to
     the server

LDAP_FILTER_ERROR
     An error occurred while encoding the given search filter.

LDAP_USER_CANCELED
     The user canceled the operation

LDAP_PARAM_ERROR
     An invalid parameter was specified

LDAP_NO_MEMORY
     Out of memory error

LDAP_CONNECT_ERROR
     A connection to the server could not be established

LDAP_NOT_SUPPORTED
     An attempt has been made to use a feature not supported by Net::LDAP

LDAP_CONTROL_NOT_FOUND
     The controls required to perform the requested operation were not
     found.

LDAP_NO_RESULTS_RETURNED
     No results were returned from the server.

LDAP_MORE_RESULTS_TO_RETURN
     There are more results in the chain of results.

LDAP_CLIENT_LOOP
     A loop has been detected. For example when following referals.

LDAP_REFERRAL_LIMIT_EXCEEDED
     The referral hop limit has been exceeded.

SEE ALSO
========

   `Net::LDAP|Net::LDAP' in this node,
`Net::LDAP::Message|Net::LDAP::Message' in this node

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

   Please report any bugs, or post any suggestions, to the perl-ldap
mailing list <perl-ldap-dev@lists.sourceforge.net>

COPYRIGHT
=========

   Copyright (c) 1998-2000 Graham Barr. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

LDAPv3 control object base class
********************************

NAME
====

   Net::LDAP::Control - LDAPv3 control object base class

SYNOPSIS
========

     use Net::LDAP::Control;
     use Net::LDAP::Constant qw( LDAP_CONTROL_MATCHEDVALS );

     $ctrl = Net::LDAP::Control->new(
       type     => "1.2.3.4",
       value    => "help",
       critical => 0
     );

     $mesg = $ldap->search( @args, control => [ $ctrl ]);

     $ctrl = Net::LDAP::Control->new( type => LDAP_CONTROL_MATCHEDVALS );

DESCRIPTION
===========

   `Net::LDAP::Control' is a base-class for LDAPv3 control objects.

CONSTRUCTORS
============

new ARGS
     ARGS is a list of name/value pairs, valid arguments are.

    critical
          A booloean value, if TRUE and the control is unrecognized by the
          server or is inappropriate for the requested operation then the
          server will return an error and the operation will not be
          performed.

          If FALSE and the control is unrecognized by the server or is
          inappropriate for the requested operation then the server will
          ignore the control and perform the requested operation as if the
          control was not given.

          If absent, FALSE is assume.

    type
          A dotted-decimal representation of an OBJECT IDENTIFIER which
          uniquely identifies the control. This prevents conflicts between
          control names.

          This may be ommitted if the contructor is being called on a
          sub-class of Net::LDAP::Control which has registered to be
          associated with an OID.  If the contructor is being called on
          the Net::LDAP::Control package, then this argument must be
          given.  If the given OID has been registered by a package, then
          the returned object will be of the type registered to handle
          that OID.

    value
          Optional information associated with the control. It's format is
          specific to the particular control.

from_asn ASN
     ASN is a HASH reference, normally extracted from a PDU. It will
     contain a type element and optionally critical and value elements. On
     return ASN will be blessed into a package. If type is a registered
     OID, then ASN will be blessed into the registered package, if not
     then ASN will be blessed into Net::LDAP::Control.

     This constructor is used internally by Net::LDAP and assumes that HASH
     passed contains a valid control. It should be used with *caution*.

METHODS
=======

   In addition to the methods listed below, each of the named parameters
to new is also avaliable as a method. type will return the OID of the
control object. value and critical are set/get methods and will return the
current value for each attribute if called without arguments, but may also
be called with arguments to set new values.

error
     If there has been an error returns a description of the error,
     otherwise it will return undef

init
     init will be called as the last step in both contructors. What it
     does will depend on the sub-class. It must always return the object.

register OID
     register is provided for sub-class implementors. It should be called
     as a class method on a sub-class of Net::LDAP::Control with the OID
     that the class will handle. Net::LDAP::Control will remember this
     class and OID pair and use it in the following situations.

        * new is called as a class method on the Net::LDAP::Control
          package and OID is passed as the type. The returned object will
          be blessed into the package that registered the OID.

        * new is called as a class method on a registered package and the
          type is not specified. The type will be set to the OID
          registered by that package.

        * from_asn is called to construct an object from ASN. The returned
          object will be blessed into the package which was registered to
          handle the OID in the ASN.

to_asn
     Returns a structure suitable for passing to Convert::ASN1 for
     encoding. This method will be called by `Net::LDAP|Net::LDAP' in this
     node when the control is used.

     The base class implementation of this method will call the value
     method without arguments to allow a sub-class to encode it's value.
     Sub-classes should not need to override this method.

valid
     Returns true if the object is valid and can be encoded. The default
     implementation for this method is to return TRUE if there is no
     error, but sub-classes may override that.

SEE ALSO
========

   `Net::LDAP|Net::LDAP' in this node

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

   Please report any bugs, or post any suggestions, to the perl-ldap
mailing list <perl-ldap-dev@lists.sourceforge.net>

COPYRIGHT
=========

   Copyright (c) 1999-2000 Graham Barr. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

LDAPv3 Paged results control object
***********************************

NAME
====

   Net::LDAP::Control::Paged - LDAPv3 Paged results control object

SYNOPSIS
========

     use Net::LDAP;
     use Net::LDAP::Control::Paged;
     use Net::LDAP::Constant qw( LDAP_CONTROL_PAGED );

     $ldap = Net::LDAP->new( "ldap.mydomain.eg" );

     $page = Net::LDAP::Control::Paged->new( size => 100 );

     @args = ( base     => "cn=subnets,cn=sites,cn=configuration,$BASE_DN",
     	   scope    => "subtree",
     	   filter   => "(objectClass=subnet)",
     	   callback => \&process_entry, # Call this sub for each entry
     	   control  => [ $page ],
     );

     my $cookie;
     while(1) {
       # Perform search
       my $mesg = $ldap->search( @args );

     # Only continue on LDAP_SUCCESS
     $mesg->code and last;

     # Get cookie from paged control
     my($resp)  = $mesg->control( LDAP_CONTROL_PAGED ) or last;
     $cookie    = $resp->cookie or last;

     # Set cookie in paged control
     $page->cookie($cookie);
      }

     if ($cookie) {
       # We had an abnormal exit, so let the server know we do not want any more
       $page->cookie($cookie);
       $page->size(0);
       $ldap->search( @args );
     }

DESCRIPTION
===========

   `Net::LDAP::Control::Paged' provides an interface for the creation and
manipulatrion of objects that represent the `pagedResultsControl' as
described by RFC-2696.

CONSTRUCTOR ARGUMENTS
=====================

   In addition to the constructor arguments described in
`Net::LDAP::Control|Net::LDAP::Control' in this node the following are
provided.

cookie
     The value to use as the cookie. This is not normally set when an
     object is created, but is set from the cookie value returned bu the
     server. This associates a search with a previous search, so the
     server knows to return the page of entries following the entries it
     returned the previous time.

size
     The page size that is required. This is the maximum number of entries
     that the server will return to the search request.

METHODS
=======

   As with `Net::LDAP::Control|Net::LDAP::Control' in this node each
constructor argument described above is also avaliable as a method on the
object which will return the current value for the attribute if called
without an argument, and set a new value for the attribute if called with
an argument.

SEE ALSO
========

   `Net::LDAP|Net::LDAP' in this node,
`Net::LDAP::Control|Net::LDAP::Control' in this node,
http://info.internet.isi.edu/in-notes/rfc/files/rfc2696.txt

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

   Please report any bugs, or post any suggestions, to the perl-ldap
mailing list <perl-ldap-dev@lists.sourceforge.net>

COPYRIGHT
=========

   Copyright (c) 2000 Graham Barr. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Server Side Sort (SSS) control object
*************************************

NAME
====

   Net::LDAP::Control::Sort - Server Side Sort (SSS) control object

SYNOPSIS
========

     use Net::LDAP::Control::Sort;
     use Net::LDAP::Constant qw(LDAP_CONTROL_SORTRESULT);

     $sort = Net::LDAP::Control::Sort->new(
       order => "cn -phone"
     );

     $mesg = $ldap->search( @args, control => [ $sort ]);

     ($resp) = $mesg->control( LDAP_CONTROL_SORTRESULT );

     print "Results are sorted\n" if $resp and !$resp->result;

DESCRIPTION
===========

   `Net::LDAP::Control::Sort' is a sub-class of
`Net::LDAP::Control|Net::LDAP::Control' in this node.  It provides a class
for manipulating the LDAP Server Side Sort (SSS) request control
`1.2.840.113556.1.4.473' as defined in RFC-2891

   If the server supports sorting, then the response from a search
operation will include a sort result control. This control is handled by
`Net::LDAP::Control::SortResult|Net::LDAP::Control::SortResult' in this
node.

CONSTRUCTOR ARGUMENTS
=====================

order
     A string which defines how entries may be sorted. It consists of
     multiple directives, spearated by whitespace. Each directive
     describes how to sort entries using a single attribute. If two
     entries have identical attributes, then the next directive in the
     list is used.

     Each directive specifies a sorting order as follows

          -attributeType:orderingRule

     The leading - is optional, and if present indicates that the sorting
     order should be reversed. `attributeType' is the attribute name to
     sort by. `orderingRule' is optional and indicates the rule to use for
     the sort and should be valid for the given `attributeType'.

     Any one attributeType should only appear once in the sorting list.

     Examples

          "cn"         sort by cn using the default ordering rule for the cn attribute
          "-cn"        sort by cn using the reverse of the default ordering rule
          "age cn"     sort by age first, then by cn using the default ordering rules
          "cn:1.2.3.4" sort by cn using the ordering rule defined as 1.2.3.4

METHODS
=======

   As with `Net::LDAP::Control|Net::LDAP::Control' in this node each
constructor argument described above is also avaliable as a method on the
object which will return the current value for the attribute if called
without an argument, and set a new value for the attribute if called with
an argument.

SEE ALSO
========

   `Net::LDAP|Net::LDAP' in this node,
`Net::LDAP::Control::SortResult|Net::LDAP::Control::SortResult' in this
node, `Net::LDAP::Control|Net::LDAP::Control' in this node,
http://info.internet.isi.edu/in-notes/rfc/files/rfc2891.txt

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

   Please report any bugs, or post any suggestions, to the perl-ldap
mailing list <perl-ldap-dev@lists.sourceforge.net>

COPYRIGHT
=========

   Copyright (c) 1999-2000 Graham Barr. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Server Side Sort (SSS) result control object
********************************************

NAME
====

   Net::LDAP::Control::SortResult - Server Side Sort (SSS) result control
object

SYNOPSIS
========

     use Net::LDAP::Control::Sort;
     use Net::LDAP::Constant qw(LDAP_CONTROL_SORTRESULT);
     use Net::LDAP::Util qw(ldap_error_name);

     $sort = Net::LDAP::Control::Sort->new(
       order => "cn -age"
     );

     $mesg = $ldap->search( @args, control => [ $sort ]);

     ($resp) = $mesg->control( LDAP_CONTROL_SORTRESULT );

     if ($resp) {
       if ($resp->result) {
         my $attr = $resp->attr;
         print "Problem sorting, ",ldap_error_name($resp->result);
         print " ($attr)" if $attr;
         print "\n";
       }
       else {
         print "Results are sorted\n";
       }
     }
     else {
       print "Server does not support sorting\n";
     }

DESCRIPTION
===========

   `Net::LDAP::Control::SortResult' is a sub-class of
`Net::LDAP::Control|Net::LDAP::Control' in this node.  It provides a class
for manipulating the LDAP sort request control `1.2.840.113556.1.4.474' as
defined in RFC-2891

   A sort result control will be returned by the server in response to a
search with a Server Side Sort control. If a sort result control is not
returned then the user may assume that the server does not support sorting
and the results are not sorted.

CONSTRUCTOR ARGUMENTS
=====================

attr
     If result indicates that there was a problem with sorting and that
     problem was due to one of the attributes specified in the sort
     control. attr is set to the name of the attribute causing the problem.

result
     This is the result code that describes if the sort operation was
     sucessful. If will be one of the result codes describes below.

METHODS
=======

   As with `Net::LDAP::Control|Net::LDAP::Control' in this node each
constructor argument described above is also avaliable as a method on the
object which will return the current value for the attribute if called
without an argument, and set a new value for the attribute if called with
an argument.

RESULT CODES
============

   Possible results from a sort request are listed below. See
`Net::LDAP::Constant|Net::LDAP::Constant' in this node for a definition of
each.

LDAP_SUCCESS
LDAP_OPERATIONS_ERROR
LDAP_TIMELIMIT_EXCEEDED
LDAP_STRONG_AUTH_REQUIRED
LDAP_ADMIN_LIMIT_EXCEEDED
LDAP_NO_SUCH_ATTRIBUTE
LDAP_INAPPROPRIATE_MATCHING
LDAP_INSUFFICIENT_ACCESS
LDAP_BUSY
LDAP_UNWILLING_TO_PERFORM
LDAP_OTHER
SEE ALSO
========

   `Net::LDAP|Net::LDAP' in this node,
`Net::LDAP::Control::Sort|Net::LDAP::Control::Sort' in this node,
`Net::LDAP::Control|Net::LDAP::Control' in this node,
http://info.internet.isi.edu/in-notes/rfc/files/rfc2891.txt

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

   Please report any bugs, or post any suggestions, to the perl-ldap
mailing list <perl-ldap-dev@lists.sourceforge.net>

COPYRIGHT
=========

   Copyright (c) 1999-2000 Graham Barr. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

LDAPv3 Virtual List View control object
***************************************

NAME
====

   Net::LDAP::Control::VLV - LDAPv3 Virtual List View control object

SYNOPSIS
========

     use Net::LDAP;
     use Net::LDAP::Control::VLV;
     use Net::LDAP::Constant qw( LDAP_CONTROL_VLVRESPONSE );

     $ldap = Net::LDAP->new( "ldap.mydomain.eg" );

     # Get the first 20 entries
     $vlv  = Net::LDAP::Control::VLV->new(
     	   before  => 0,	# No entries from before target entry
     	   after   => 19,	# 19 entries after target entry
     	   content => 0,	# List size unknown
     	   offset  => 1,	# Target entry is the first
     	 );
     $sort = Net::LDAP::Control::Sort->new( sort => 'cn' );

     @args = ( base     => "o=Ace Industry, c=us",
     	   scope    => "subtree",
     	   filter   => "(objectClass=inetOrgPerson)",
     	   callback => \&process_entry, # Call this sub for each entry
     	   control  => [ $vlv, $sort ],
     );

     $mesg = $ldap->search( @args );

     # Get VLV response control
     ($resp)  = $mesg->control( LDAP_CONTROL_VLVRESPONSE ) or die;
     $vlv->response( $resp );

     # Set the control to get the last 20 entries
     $vlv->end;

     $mesg = $ldap->search( @args );

     # Get VLV response control
     ($resp)  = $mesg->control( LDAP_CONTROL_VLVRESPONSE ) or die;
     $vlv->response( $resp );

     # Now get the previous page
     $vlv->scroll_page( -1 );

     $mesg = $ldap->search( @args );

     # Get VLV response control
     ($resp)  = $mesg->control( LDAP_CONTROL_VLVRESPONSE ) or die;
     $vlv->response( $resp );

     # Now page with first entry starting with "B" in the middle
     $vlv->before(9);	# Change page to show 9 before
     $vlv->after(10);	# Change page to show 10 after
     $vlv->assert("B");	# assert "B"

     $mesg = $ldap->search( @args );

DESCRIPTION
===========

   `Net::LDAP::Control::VLV' provides an interface for the creation and
manipulation of objects that represent the Virtual List View as described
by draft-ietf-ldapext-ldapv3-vlv-03.txt.

   When using a Virtual List View control in a search, it must be
accompanied by a sort control. See
`Net::LDAP::Control::Sort|Net::LDAP::Control::Sort' in this node

CONSTRUCTOR ARGUMENTS
=====================

   In addition to the constructor arguments described in
`Net::LDAP::Control|Net::LDAP::Control' in this node the following are
provided.

after
     Set the number of entries the server should return from the list after
     the target entry.

assert
     Set the assertion value user to locate the target entry. This value
     should be a legal value to compare with the first attribute in the
     sort control that is passed with the VLV control. The target entry is
     the first entry in the list which is greater than or equal the assert
     value.

before
     Set the number of entries the server should return from the list
     before the target entry.

content
     Set the number of entries in the list. On the first search this value
     should be set to zero. On subsequent searches it should be set to the
     length of the list, as returned by the server in the VLVResponse
     control.

context
     Set the context identifier.  On the first search this value should be
     set to zero. On subsequent searches it should be set to the context
     value returned by the server in the VLVResponse control.

offset
     Set the offset of the target entry.

METHODS
-------

   As with `Net::LDAP::Control|Net::LDAP::Control' in this node each
constructor argument described above is also avaliable as a method on the
object which will return the current value for the attribute if called
without an argument, and set a new value for the attribute if called with
an argument.

   The offset and assert attributes are mutually exclusive. Setting one or
the other will cause previous values set by the other to be forgotten. The
content attribute is also associated with the offset attribute, so setting
assert will cause any content value to be forgotten.

end
     Set the target entry to the end of the list. This method will change
     the before and after attributes so that the target entry is the last
     in the page.

response VLV_RESPONSE
     Set the attributes in the control as per VLV_RESPONSE. VLV_RESPONSE
     should be a control of type
     `Net::LDAP::Control::VLVResponse|Net::LDAP::Control::VLVResponse' in
     this node returned from the server. response will populate the
     context, offset and content attibutes of the control with the values
     from VLV_RESPONSE. Because this sets the offset attribute, any
     previous setting of the assert attribute will be forgotten.

scroll NUM
     Move the target entry by NUM entries. A positive NUM will move the
     target entry towards the end of the list and a negative NUM will move
     the target entry towards the start of the list. Returns the index of
     the new target entry, or undef if the current target is identified by
     an assertion.

     scroll may change the before and after attributes if the scroll value
     would cause the page to go off either end of the list. But the page
     size will be maintained.

scroll_page NUM
     Scroll by NUM pages. This method simple calculates the current page
     size and calls scroll with `NUM * $page_size'

start
     Set the target entry to the start of the list. This method will
     change the before and after attributes to the the target entry is the
     first entry in the page.

SEE ALSO
========

   `Net::LDAP|Net::LDAP' in this node,
`Net::LDAP::Control|Net::LDAP::Control' in this node,
`Net::LDAP::Control::Sort|Net::LDAP::Control::Sort' in this node,
`Net::LDAP::Control::VLVResponse|Net::LDAP::Control::VLVResponse' in this
node

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

   Please report any bugs, or post any suggestions, to the perl-ldap
mailing list <perl-ldap-dev@lists.sourceforge.net>

COPYRIGHT
=========

   Copyright (c) 2000 Graham Barr. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

LDAPv3 Virtual List View server response
****************************************

NAME
====

   Net::LDAP::Control::VLVResponse - LDAPv3 Virtual List View server
response

SYNOPSIS
========

   See `Net::LDAP::Control::VLV|Net::LDAP::Control::VLV' in this node

DESCRIPTION
===========

   `Net::LDAP::Control::VLVResponse' is a sub-class of
`Net::LDAP::Control|Net::LDAP::Control' in this node.  It provides a class
for manipulating the LDAP Virtual List View Response control

   If the server supports Virtual List Views, then the response from a
search operation will include a VLVResponse control.

CONSTRUCTOR ARGUMENTS
=====================

   In addition to the constructor arguments described in
`Net::LDAP::Control|Net::LDAP::Control' in this node the following are
provided.

content
     An estimate of the number of entries in the complete list. This value
     should be used in any subsequent Virtual List View control using the
     same list.

context
     An arbitary value which is used to associate subsequent requests with
     the request which this control is a response for. This value should
     be copied by the client into the Virtual List View control for any
     subsequent search that uses the same list.

result
     A result code indicating the result of the Virtual List View request.
     This may be any of the codes listed below.

target
     The list offset of the target entry.

METHODS
=======

   As with `Net::LDAP::Control|Net::LDAP::Control' in this node each
constructor argument described above is also avaliable as a method on the
object which will return the current value for the attribute if called
without an argument, and set a new value for the attribute if called with
an argument.

RESULT CODES
============

   Possible results from a sort request are listed below. See
`Net::LDAP::Constant|Net::LDAP::Constant' in this node for a definition of
each.

LDAP_SUCCESS
LDAP_OPERATIONS_ERROR
LDAP_TIMELIMIT_EXCEEDED
LDAP_ADMIN_LIMIT_EXCEEDED
LDAP_INSUFFICIENT_ACCESS
LDAP_BUSY
LDAP_UNWILLING_TO_PERFORM
LDAP_OTHER
LDAP_SORT_CONTROL_MISSING
LDAP_INDEX_RANGE_ERROR
SEE ALSO
========

   `Net::LDAP|Net::LDAP' in this node,
`Net::LDAP::Control|Net::LDAP::Control' in this node,
http://info.internet.isi.edu/in-notes/rfc/files/rfc2696.txt

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

   Please report any bugs, or post any suggestions, to the perl-ldap
mailing list <perl-ldap-dev@lists.sourceforge.net>

COPYRIGHT
=========

   Copyright (c) 2000 Graham Barr. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

A DSML Writer and Reader for Net::LDAP
**************************************

NAME
====

   Net::LDAP::DSML - A DSML Writer and Reader for Net::LDAP

SYNOPSIS
========

     use Net::LDAP;
     use Net::LDAP::DSML;
     use IO::File;

     my $server = "localhost";
     my $file = "testdsml.xml";
     my $ldap = Net::LDAP->new($server);

     $ldap->bind();

     my $dsml = Net::LDAP::DSML->new();

     my $file = "testdsml.xml";

     my $io = IO::File->new($file,"w") or die ("failed to open $file as filehandle.$!\n");
     $dsml->open($io) or die ("DSML problems opening $file.$!\n"); ;

     #or

     open (IO,">$file") or die("failed to open $file.$!");

     $dsml->open(*IO) or die ("DSML problems opening $file.$!\n");

     my $mesg = $ldap->search(
                              base     => 'o=airius.com',
                              scope    => 'sub',
                              filter   => 'ou=accounting',
                              callback => sub {
     					 my ($mesg,$entry) =@_;
     					 $dsml->write($entry) if (ref $entry eq 'Net::LDAP::Entry');
     				       }
                               );

     die ("search failed with ",$mesg->code(),"\n") if $mesg->code();

     $dsml->write($schema);
     $dsml->finish();

     print "Finished printing DSML\n";
     print "Starting to process DSML\n";

     $dsml = new Net::LDAP::DSML();
     $dsml->process($file, entry => \&processEntry);

     #future when schema support is available will be
     #$dsml->process($file, entry => \&processEntry, schema => \&processSchema);

     sub processEntry {
       my $entry = shift;

       $entry->dump();
     }

DESCRIPTION
===========

   Directory Service Markup Language (DSML) is the XML standard for
representing directory service information in XML.

   At the moment this module only reads and writes DSML entry entities. It
cannot process any schema entities because schema entities are processed
differently than elements.

   Eventually this module will be a full level 2 consumer and producer
enabling you to give you full DSML conformance.

   The module uses callbacks to improve performance (at least the
appearance of improving performance ;) and to reduce the amount of memory
required to parse large DSML files. Every time a single entry or schema is
processed we pass the Net::LDAP object (either an Entry or Schema object)
to the callback routine.

AUTHOR
======

   Mark Wilcox mark@mwjilcox.com

SEE ALSO
========

   `Net::LDAP|Net::LDAP' in this node, `XML::Parser|XML::Parser' in this
node

COPYRIGHT
=========

   Copyright (c) 2000 Graham Barr and Mark Wilcox. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

An LDAP entry object
********************

NAME
====

   Net::LDAP::Entry - An LDAP entry object

SYNOPSIS
========

     use Net::LDAP;

     $ldap = Net::LDAP->new($host);
     $mesg = $ldap->search(@search_args);

     my $max = $mesg->count;
     for($i = 0 ; $i < $max ; $i++) {
       my $entry = $mesg->entry($i);
       foreach my $attr ($entry->attributes) {
         print join("\n ",$attr, $entry->get_value($attr)),"\n";
       }
     }

     # or

     use Net::LDAP::Entry;

     $entry = Net::LDAP::Entry->new;

     $entry->add(
       attr1 => 'value1',
       attr2 => [qw(value1 value2)]
     );

     $entry->delete( 'unwanted' );

     $entry->replace(
       attr1 => 'newvalue'
       attr2 => [qw(new values)]
     );

     $entry->update( $ldap ); # update directory server

DESCRIPTION
===========

   The *Net::LDAP::Entry* object represents a single entry in the
directory.  It is a container for attribute-value pairs.

   A *Net::LDAP::Entry* object can be used in two situations. The first and
probably most common use is in the result of a search to the directory
server.

   The other is where a new object is created locally and then a single
command is sent to the directory server to add, modify or replace an
entry. Entries for this purpose can also be created by reading an LDIF
file with the `Net::LDAP::LDIF|Net::LDAP::LDIF' in this node module.

CONSTRUCTOR
===========

new
     Create a new entry object with the changetype set to `'add''

METHODS
=======

add ( ATTR => VALUE [, ATTR2 => VALUE2 ... ] )
     Add one or more new attributes to the entry. Each value must be a
     scalar variable or a reference to an array. The values given will be
     added to the values which already exist for the given attributes.

          $entry->add( 'sn' => 'Barr');

          $entry->add( 'street' => [ '1 some road','nowhere']);

     NOTE: these changes are local to the client and will not appear on
     the directory server until the update method is called.

attributes ( [ OPTIONS ] )
     Return a list of attributes that this entry has.

     OPTIONS is a list of name/value pairs, valid options are :-

    nooptions
          If TRUE, return a list of the attribute names excluding any
          options. For example for the entry

               name: Graham Barr
               name;en-us: Bob
               jpeg;binary: **binary data**

          the return list would be `( 'name', 'jpeg' )'.

changetype ( [ TYPE ] )
     If called without arguments it returns the type of operation that
     would be performed when the update method is called. If called with
     an argument it will set the changetype to TYPE.

     Possible values for TYPE are

    add
          The update method will call the add method on the client object,
          which will result in the entry being added to the directory
          server.

    delete
          The update method will call the delete method on the client
          object, which will result in the entry being removed from the
          directory server.

    modify
          The update method will call the modify method on the client
          object, which will result in any changes that have been made
          locally being made to the entry on the directory server.

delete ( [ ATTR [, ATTR2 ... ]] )
     Delete the given attributes from the entry. If no attributes are
     passed then the next call to update will cause the entry to be
     deleted from the server.

     NOTE: these changes are local to the client and will not appear on
     the directory server until the update method is called.

dn ( [ DN ] )
     Set or get the DN for the entry. With no arguments dn will return the
     current DN. If an argument is given then it will change the DN for
     the entry and return the previous value.

     NOTE: these changes are local to the client and will not appear on
     the directory server until the update method is called.

exists ( ATTR )
     Returns TRUE if the entry has an attribute called ATTR.

get_value ( ATTR [, OPTIONS ] )
     Get the values for the attribute ATTR. In a list context returns all
     values for the given attribute, or the empty list if the attribute
     does not exist. In a scalar context returns the first value for the
     attribute or undef if the attribute does not exist.

     The return value may be changed by OPTIONS, which is a list of name
     => value pairs, valid options are :-

    alloptions
          If TRUE then the result will be a hash reference. The keys of
          the hash will be the options and the hash value will be the
          values for those attributes.  For example if an entry had

               name: Graham Barr
               name;en-us: Bob

          Then a get for attribute "name" with alloptions set would return

               {
                 ''       => [ 'Graham Barr' ],
                 ';en-us' => [ 'Bob' ]
               }

    asref
          If TRUE then the result will be a reference to an array
          containing all the values for the attribute, or undef if the
          attribute does not exist.

     NOTE: In the interest of performance the array references returned by
     get_value are references to structures held inside the entry object.
     These values and thier contents should *NOT* be modified directly.

replace ( ATTR => VALUE [, ATTR2 => VALUE2 ... ] )
     Similar to add, except that the values given will replace any values
     that already exist for the given attributes.

     NOTE: these changes are local to the client and will not appear on
     the directory server until the update method is called.

update ( CLIENT )
     Update the directory server with any changes that have been made
     locally to the attributes of this entry. This means any calls that
     have been made to add, replace or delete since the last call to
     changetype or update was made.

     This method *cannot* be used to modify the DN of the entry on the
     server, for that see the moddn method in `Net::LDAP|Net::LDAP' in
     this node.

     CLIENT is a Net::LDAP object where the update will be sent to.

     The result will be an object of type
     `Net::LDAP::Message|Net::LDAP::Message' in this node as returned by
     the add, modify or delete method called on CLIENT.

SEE ALSO
========

   `Net::LDAP|Net::LDAP' in this node, `Net::LDAP::LDIF|Net::LDAP::LDIF'
in this node

AUTHOR
======

   Graham Barr <gbarr@pobox.com>.

   Please report any bugs, or post any suggestions, to the perl-ldap
mailing list <perl-ldap-dev@lists.sourceforge.net>.

COPYRIGHT
=========

   Copyright (c) 1997-2000 Graham Barr. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

PERL LDAP by Example
********************

NAME
====

   Net::LDAP::Examples - PERL LDAP by Example

DESCRIPTION
===========

   The following examples are of course PERL code, found to work with the
Net::LDAP modules.

   The intent of this document is to give the reader a *cut and paste*
jump start to getting an LDAP application working.

   Below you will find snippets of code that should work as-is with only a
small amount of work to correct any variable assignments and LDAP
specifics, e.g. Distinguished Name Syntax, related to the user's own
implementation.

   The Standard Operating Proceedure that is followed here is:

  1. Package		- use Net::LDAP

  2. Initialization	- new

  3. Binding		- bind

  4. Operation	- add modify moddn search

  5. Processing	- displaying data from a search

  6. Error		- displaying error information

  7. Unbinding	- unbind
        Look to each of these for a snippet of code to meet your needs.

   *What is not covered in these examples at this time:*

abandon and compare methods
callback subroutines
CODE
====

PACKAGE - Definitions
---------------------

     use Net::LDAP qw(:all);			# use for all code

     use Net::LDAP::Util qw(ldap_error_name
                            ldap_error_text) ; 	# use for Error handling

INITIALIZING
------------

     $ldap = Net::LDAP->new("yourLDAPhost.yourCompany.com") or die "$@";

BINDING
-------

     $mesg = $ldap->bind( version => 3 );    	# use for searches

     $mesg = $ldap->bind("$userToAuthenticate",
                          password => "$passwd",
                          version => 3 );		# use for changes/edits

     # see your LDAP administrator for information concerning the
     # user authentication setup at your site.

OPERATION - Generating a SEARCH
-------------------------------

     sub LDAPsearch
     	{
     	  my ($ldap,$searchString,$attrs,$base) = @_ ;

     # if they don't pass a base... set it for them

     if (!$base ) { $base = "o=mycompany, c=mycountry"; }

     # if they don't pass an array of attributes...
     # set up something for them

     if (!$attrs ) { $attrs = ['cn','mail' ]; }

     my $result = $ldap->search (
           base    => "$base",
           scope   => "sub",
           filter  => "$searchString",
           attrs   =>  $attrs
           );

     }

     my @Attrs = ();		# request all available attributes
     				# to be returned.

     my $result = LDAPsearch($ldap,"sn=*",\@Attrs);

PROCESSING - Displaying SEARCH Results
--------------------------------------

     #------------
     #
     # Accessing the data as if in a structure
     #  i.e. Using the "as_struct"  method
     #

     my $href = $result->as_struct;

     # get an array of the DN names

     my @arrayOfDNs  = keys %$href ;        # use DN hashes

     # process each DN using it as a key

     foreach (@arrayOfDNs) {
        print $_,"\n";
        my $valref = $$href{$_};

     # get an array of the attribute names
     # passed for this one DN.
     my @arrayOfAttrs = sort keys %$valref; #use Attr hashes

     my $attrName;
     foreach $attrName (@arrayOfAttrs) {

     # skip any binary data: yuck!
                  next if ( $attrName =~ /;binary$/ );

     # get the attribute value (pointer) using the
         	     # attribute name as the hash
     my $attrVal =  @$valref{$attrName} ;
        print "\t $attrName: @$attrVal \n";
     }
                print "#-------------------------------\n";
      	   # End of that DN
              }
           #
           #  end of as_struct method
           #
           #--------

     #------------
     #
     # handle each of the results independently
     # ... i.e. using the walk through method
     #
     	my @entries = $result->entries;

     my $entr ;
     foreach $entr ( @entries )
        {
         print "DN: ",$entr->dn,"\n";
         #my @attrs = sort $entr->attributes;

     my $attr;
                foreach $attr ( sort $entr->attributes ){
     		#skip binary we can't handle
         next if ( $attr =~ /;binary$/ );
         print "  $attr : ",$entr->get_value($attr),"\n";
         }

     #print "@attrs\n";
         print "#-------------------------------\n";
                }

     #
     # end of walk through method
     #------------

OPERATION - Modifying entries
-----------------------------

     #
     #   Modify
     #
     #  for each of the modifies below you'll need to supply
     #  a full DN (Distinguished Name) for the $dn variable.
     #   example:
     #    cn=Jo User,ou=person,o=mycompany,c=mycountry
     #
     #   I would recommend doing a search (listed above)
     #   then use the dn returned to populate the $dn variable.

     #
     #  Do we only have one result returned from the search?

     if ( $result->count != 1 ) { exit ; }  # Nope.. exit

     my $dn = $entries[0]->dn;	   # yes.. get the DN

     #######################################
     #
     #   MODIFY using a HASH
     #

     my %ReplaceHash = ( keyword => "x", proxy => "x" );

     my $result = LDAPmodifyUsingHash($ldap,$dn, \%ReplaceHash );

     sub LDAPmodifyUsingHash
       {
       my ($ldap,$dn,$whatToChange ) = @_ ;
       my $result = $ldap->modify($dn,
                              replace => { %$whatToChange }
                                );
       return ($result );
       }

     #######################################
     #
     #   MODIFY using a ARRAY List
     #

     my @ReplaceArrayList = [  'keyword', "xxxxxxxxxx" ,
                                'proxy' , "yyyyyyyyyy"   ];

     my $result = LDAPmodifyUsingArrayList($ldap,$dn, \@ReplaceArrayList );

     sub LDAPmodifyUsingArrayList
       {
       my ($ldap,$dn,$whatToChange ) = @_ ;
       my $result = $ldap->modify($dn,
                        changes => [
                        replace => @$whatToChange
                        ]
                        );
        return ($result );
       }

     #######################################
     #
     #   MODIFY using a ARRAY
     #

     my @ReplaceArray	= (  'keyword', "xxxxxxxxxx" ,
                               'proxy' , "yyyyyyyyyy"   );

     my $result = LDAPmodifyUsingArray($ldap,$dn, \@ReplaceArray );

     sub LDAPmodifyUsingArray
       {
       my ($ldap,$dn,$whatToChange ) = @_ ;
       my $result = $ldap->modify($dn,
                        changes => [
                        replace => [ @$whatToChange ]
                        ]
                        );
        return ($result );
       }

     #######################################
     #
     #   MODIFY an existing record using 'Changes'
     #    (or combination of add/delete/replace)
     #

     my @whatToChange ;
     my @ReplaceArray ;
     my @DeleteArray ;
     my @AddArray ;

     push @AddArray, 'cn',"me myself";
     push @ReplaceArray, 'sn','!@#$%^&*()__+Hello THere';
     push @ReplaceArray, 'cn',"me myself I";
     push @DeleteArray, 'cn',"me myself";

     if ( $#ReplaceArray > 0 ) {
         push @whatToChange, 'replace' ;
         push @whatToChange, \@ReplaceArray  ;
        }
     if ( $#DeleteArray > 0 ) {
         push @whatToChange, 'delete' ;
         push @whatToChange, \@DeleteArray  ;
        }
     if ( $#AddArray > 0 ) {
         push @whatToChange, 'add' ;
         push @whatToChange, \@AddArray  ;
        }

     $result = LDAPmodify($ldap,$dn, \@whatToChange );

     sub LDAPmodify
     {
        my ($ldap,$dn,$whatToChange) = @_ ;

     my $result = $ldap->modify($dn,
                      changes => [
                      @$whatToChange
                      ]
                      );
          return ($result );
         }

OPERATION - Changing the RDN
----------------------------

     my $newRDN = "cn=Joseph User";

     my $result = LDAPrdnChange($ldap,$dn,$newRDN,"archive");

     sub LDAPrdnChange
     {
      my ($ldap,$dn,$whatToChange,$action) = @_ ;

     my $branch ;

     #
     # if the archive action is selected, move this
     # entry to another place in the directory.
     #
     if ( $action =~ /archive/i )  {
        $branch = "ou=newbranch,o=mycompany,c=mycountry";
        }

     #
     # use the 'deleteoldrdn' to keep from getting
     # multivalues in the NAMING attribute.
     # in most cases that would be the 'CN' attribute
     #
     my $result = $ldap->moddn($dn,
               newrdn => $whatToChange,
               deleteoldrdn => '1',
               newsuperior => $branch
               );

     return ($result );

     }

OPERATION - Adding a new Record
-------------------------------

     my $DNbranch = "ou=bailiwick, o=mycompany, c=mycountry";

     #
     # check with your Directory Schema or Administrator
     # for the correct objectClass... I'm sure it'll be different
     #
     my $CreateArray = [
     	     objectClass => ["top","person","organizationalPerson"],
                       cn => "Jane User",
                      uid => "0000001",
                       sn => "User",
                	    mail => "JaneUser@mycompany.com"
                 ];

     #
     # create the  new DN to look like this
     # " cn=Jo User + uid=0000001 , ou=bailiwick, o=mycompany, c=mycountry "
     #
     # NOTE: this DN  MUST be changed to meet your implementation
     #

     my $NewDN =  "@$CreateArray[2]=".
                  "@$CreateArray[3]+".
                  "@$CreateArray[4]=".
                  "@$CreateArray[5],".
                  $DNbranch;

     LDAPentryCreate($ldap,$NewDN,$CreateArray);

     #
     # CreateArray is a reference to an anonymous array
     # you have to dereference it in the  subroutine it's
     # passed to.
     #

     sub LDAPentryCreate
     {

     my ($ldap,$dn,$whatToCreate) = @_ ;
     my $result = $ldap->add( $dn, attrs => [  @$whatToCreate ] );
     return ($result );

     }

ERROR - Retrieving and Displaying ERROR information
---------------------------------------------------

     use Net::LDAP::Util qw( ldap_error_name
                         ldap_error_text) ;

     if ( $result->code ) {
       #
       # if we've got an error... record it
       #
       LDAPerror("Searching",$result);
       }

     sub LDAPerror
       {
         my ($from,$mesg) = @_;
         print "Return code: ",$mesg->code ;
         print "\tMessage: ", ldap_error_name($mesg->code);
         print " :",        ldap_error_text($mesg->code);
         print "MessageID: ",$mesg->mesg_id;
         print "\tDN: ",$mesg->dn;

     #---
       	# Programmer note:
       	#
       	#  "$mesg->error"  DOESN'T work!!!
       	#
       	#print "\tMessage: ", $mesg->error;
       	#-----

     }

UNBIND
------

     $ldap->unbind;

LDAP SCHEMA RETRIEVAL
=====================

   The following code snippet shows how to retrieve schema information.

   The first procedure is to initialize a new LDAP object using the same
procedures as listed at the beginning of this document.

   The second procedure is to bind to your directory server.  Some servers
may require authentication to retrieve the schema from the directory
server.  This procedure is listed at the beginning of this document too.

   After a successful bind you are ready to retrieve the schema
information.  You do this by initializing a schema object.

     $schema = $ldap->schema();

   In this case Net::LDAP will attempt to determine the dn under which the
schema can be found. First it will look for the attribute
`subschemasubentry' in the root DSE. If that cannot be found then it will
default to the assumption of `cn=schema'

   Alternatively you can specify the dn where the schema is to be found
with

     $schema = $ldap->schema(dn => $dn);

   Once we have a dn to search for, Net::LDAP will fetch the schema entry
with

     $mesg = $self->search(
       base   => $dn,
       scope  => 'base',
       filter => '(objectClass=*)',
     );

   Once the schema object has been initialized, schema methods are used to
retrieve the data.  There are a number of ways this can be done.
Information on the schema methods can be found in the Net::LDAP::Schema
pod documentation.

   The following is a code snippet showing how to get and display
information about returned attributes.

     #
     # Get the attributes
     #

     @attributes = $schema->attributes();
     #
     # Display the attributes
     #

     foreach ( @attributes)
     {
           print "attributeType\n";

     #
     # Get and display the oid number of the objectclass.
     #
     $oid = $schema->name2oid( "$_" );

     #
     # Get the various items associated with
     # this attribute.
     #
     @attribute_items = $schema->items( "$oid" );
     #
     # Read returned item names and display their associated data.
     #
     foreach $value ( @attribute_items )
     {
        # We know we are dealing with an attribute, ignore type.
        next if ( $value eq 'type');  # Type  holds oc or at
        #
        # Read the data for this item of this oid.
        #
        @item = $schema->item( $oid, $value );
        #
        # Some item names have no data, the name itself is data.
        # This type of item has 1 as data.
        #
        if ( defined(@item) && $item[0] == 1 )
        {
        print "\t$value\n";
        next;
        }
        if ( defined(@item) && $#item >= 0 )
        {
        print "\t$value:  @item\n";
        }

     }
       }

   The process is the basically the same for getting objectClass
information.  Where schema->attributes() is used, substitute
schema->objectclasses().  From that point on the process is the same for
both objectClasses and attributes.

BUGS
====

   None known, but there may be some

AUTHOR  (of this document)
==========================

   Russell Biggs <rgb@ticnet.com>

COPYRIGHT
=========

   All rights to this document are hereby relinquished to Graham Barr.

Frequently Asked Questions about Net::LDAP
******************************************

NAME
====

   Net::LDAP::FAQ - Frequently Asked Questions about Net::LDAP

SYNOPSIS
========

     perldoc Net::LDAP::FAQ

DESCRIPTION
===========

   This document serves to answer the most frequently asked questions on
both the perl-ldap Mailing List and those sent to Graham Barr.

GENERAL
=======

What is perl-ldap ?
-------------------

   perl-ldap is the distribution name. The perl-ldap distribution contains
the Net::LDAP modules.

Why another perl LDAP implementation ?
--------------------------------------

   perl-ldap's goal is to be as portable as possible. It does this by
being implemented completely in perl. So basically anywhere that perl runs
perl-ldap will run. This is not true for other implementations which
require a C compiler.

Where can I get it ?
--------------------

   Perl-ldap is available from CPAN. You will find it in the
authors/id/GBARR directory. Alternatively you can download the latest
version from  http://www.cpan.org/search?dist=perl-ldap

Is there a web page for perl-ldap ?
-----------------------------------

   Yes there is at http://perl-ldap.sourceforge.net/

Is there a mailing list ?
-------------------------

   Yes there is at perl-ldap-dev@lists.sourceforge.net

   You can subscribe to this list at
http://lists.sourceforge.net/mailman/listinfo/perl-ldap-dev

Is the mailing list archived ?
------------------------------

   Archives of messages since we switched to using sourceforge can be
found at

     http://www.geocrawler.com/lists/3/SourceForge/3482/0/

   Please be aware that the geocrawler system munges code that is in the
email messages.  In particular, apostrophes (') are turned into back ticks
(`) and newlines escapes (\n) are removed (and probably other escapes as
well).

   There is also an archive of the perl-ldap mailing list at
http://www.xray.mpe.mpg.de/mailing-lists/perl-ldap/ which also has
messages from before the move to sourceforge.  The xray archive does not
munge email messages.

Is there any online documentation ?
-----------------------------------

   Yes. perl-ldap has online documentation at
http://perl-ldap.sourceforge.net/ which will have the latest documentation
available.

Is there a public CVS repository ?
----------------------------------

   Yes, it is located at sourceforge.net

Can I get perl-ldap from the public CVS repository?
---------------------------------------------------

   Yes, any one can pull perl-ldap from the public CVS repository on
sourceforge.net.

   There are several ways this can be done.

   Web;

   You can download it from SourceForge by following the release link:

   The 2 lines in the following example should be put together as one
continuous line.  Example;

     http://download.sourceforge.net/perl-ldap/perl-ldap-0.20.tar.gz

   CVS;

   You can download latest version of perl-ldap from SourceForge by
executing a anonymous CVS "get" command.  When the password is requested
press the enter key.

   The 2 lines in the following example should be put together as one
continuous line.  Example;

     cvs -d:pserver:anonymous@cvs.perl-ldap.sourceforge.net:/cvsroot/perl-ldap

   Web page;

   Most of the time there is a URL link on the perl-ldap home page on
sourceforge that points to the latest released version of perl-ldap.  Due
to the fact that humans must update the web page to point to a new release
it sometimes does not get updated as quickly as it should.

What is CVS.
------------

   "CVS" is an acronym for the "Concurrent Versions System".  CVS is a
"Source Control" or "Revision Control" tool designed to keep track of
source changes made by groups of developers working on the same files,
allowing them to stay in sync with each other as each individual chooses.

LDAP AND DIRECTORY TERMINOLOGY.
===============================

   In order to help the user understand the perl-ldap module better some
key LDAP terminology is defined here.

What is a directory.
--------------------

   A directory is a special purpose database that usually contains typed
information such as text strings, binary data, or X.509 certificates.

What is LDAP.
-------------

   LDAP stands for Lightweight Directory Access Protocol.  The word
*Protocol* is the key word in the definition given in the preceding
sentence, LDAP is *NOT* hardware or software.  It is a protocol that
defines how a client and server will communicate with one another.

   The Lightweight Directory Access Protocol is defined in a series of
Requests For Comments, better known as RFC(s).  The RFCs can be found on
the Internet.  A very good source for all of the LDAP RFCs can be found in
the OpenLDAP, http://www.OpenLDAP.org/ , software bundle that can be
downloaded free of charge from the Internet.  Some of the more important
RFC numbers are RFC 1777 for LDAPv2 and RFC 2251 for LDAPv3.

What is a LDAP Directory.
-------------------------

   In the strictest terms of the definition there is no such thing as a
LDAP directory.  To be practical about this situation every day directory
professionals refer to their directory as " a LDAP directory" because it
is easy to say and it does convey the type of protocol used to communicate
with their directory.  Using this definition a LDAP directory is a
directory whose server software conforms to the Lightweight Directory
Access Protocol when communicating with a client.

What is an Entry.
-----------------

   The traditional directory definition of a directory object is called an
Entry. Entries are composed of attributes that contain the information to
be recorded about an object.

   Another non-traditional definition of a directory object is called a
record.  Some directory professionals prefer to use this definition
because of the confusion that sometimes results when using the term Entry.

What is a Distinguished Name.
-----------------------------

   Every entry in a directory, whether it is X.500 or LDAP, has a
Distinguished Name, or DN.  It is a unique Entry identifier through out
the complete directory.  No two Entries can have the same DN within the
same directory.

   Example of a DN:

     cn=Road Runner, ou=bird, dc=carton, dc=com
     ou=bird, dc=carton, dc=com
     dc=carton, dc=com
     dc=com

What is a Relative Distinguished Name.
--------------------------------------

   Every Entry in a directory, whether it is X.500 or LDAP, has a
Distinguished Name which is made up of a sequence of Relative
Distinguished Names, or RDNs.  The sequences of RDNs are separated by
commas (,) or semi-colons (;).  There can be more than one identical RDN
in a directory, but they must be in different bases, or branches, of the
directory.

   Example of a DN:

     cn=Road Runner,ou=bird,dc=carton,dc=com

     RDNs of the proceeding DN:
     RDN => cn=Road Runner
     RDN => ou=bird
     RDN => dc=carton
     RDN => dc=com

   The RDNs are delimited by a comma.

What is a Naming RDN.
---------------------

   Example of a DN:

     cn=Road Runner,ou=bird,dc=carton,dc=com

     Naming RDN of the proceeding DN:

     cn=Road Runner

   Most of the time when directory professionals refer to the RDN of an
entry, this is the RDN that they are referring to.

What is a search base.
----------------------

   A search base is a Distinguished Name that is the starting point of
search queries.

   Example of a DN:

     cn=Road Runner,ou=bird,dc=carton,dc=com

   Possible search base(s) for the proceeding DN:

     Base => cn=Road Runner,ou=bird,dc=carton,dc=com
     Base => ou=bird,dc=carton,dc=com
     Base => dc=carton,dc=com
     Base => dc=com

   Setting the search base to the lowest possible branch of the directory
will speed up searches considerably.

What is an attribute.
---------------------

   The entry(s) in a directory are composed of attributes that contain
information about the object.  Each attribute has a type and can contain
one or more values.  The attribute type is associated with a syntax that
defines what kind of information can be stored in the attributes values
and controls how directory operations on the attribute behave.  What
attributes are required and allowed in a entry is controlled by content
rules that are defined on a per-server basis or by a special attribute in
each entry called an objectClass.

PERL-LDAP INSTALLATION
======================

How do I install perl-ldap ?
----------------------------

   To install the modules that are in the perl-ldap distribution follow the
same steps that you would for most other distributions found on CPAN, that
is

     # replace 0.13 with the version you have

     gunzip perl-ldap-0.13.tar.gz
     tar xvf perl-ldap-0.13.tar
     cd perl-ldap-0.13

     perl Makefile.PL
     make
     make test
     make install

But I do not have make, how can I install perl-ldap ?
-----------------------------------------------------

   Well as luck would have it the modules in perl-ldap do not do anything
complex, so a simple copy is enough to install. First run

     perl -V

   This will output information about the version of perl you have
installed. Near the bottom you will find something like

     @INC:
       /usr/local/perl/perl5.005/lib/5.00502/sun4-solaris
       /usr/local/perl/perl5.005/lib/5.00502
       /usr/local/perl/perl5.005/lib/site_perl/5.005/sun4-solaris
       /usr/local/perl/perl5.005/lib/site_perl/5.005
       .

   This is a list of directories that perl searches when it is looking for
a module. The directory you need is the site_perl directory, but without
the system architecture name, in this case it is
`/usr/local/perl/perl5.005/lib/site_perl/5.005'. The files required can
then be installed with

     # replace 0.13 with the version you have

     gunzip perl-ldap-0.13.tar.gz
     tar xvf perl-ldap-0.13.tar
     cd perl-ldap-0.13/lib

     cp * /usr/local/perl/perl5.005/lib/site_perl/5.005

What other modules will I need ?
--------------------------------

   perl-ldap does use other modules. Some are required, but some are
optional (ie required to use certain features)

Convert::ASN1
     This module is required for perl-ldap to work.

     You can obtain the latest release from
     http://search.cpan.org/search?module=Convert::ASN1

Digest::MD5
     This module is optional. It also requires a C compiler when
     installing.  You only need to install Digest::MD5 if you want to use
     the SASL authentication method.

     You can obtain the latest release from
     http://search.cpan.org/search?module=Digest::MD5

URI::ldap
     This module is optional. You only need to install URI::ldap if you are
     going to need to parse ldap referrals. `Net::LDAP|Net::LDAP' in this
     node does not do this automatically yet, so this module is not used
     by perl-ldap.

     You can obtain the latest release from
     http://search.cpan.org/search?module=URI::ldap

OpenSSL and IO::Socket::SSL for Net::LDAPS
     If you want to use Net::LDAP::LDAPS you will need this module and the
     OpenSSL software package.

     You can obtain the latest release of IO::Socket::SSL from
     http://search.cpan.org/search?module=IO::Socket::SSL

     You can obtain the latest release of OpenSSL from
     http://www.openssl.org/

     If you are using a Linux system, many of the distributions have RPM
     packages that you can install.  Use your favorite web search engine
     to find the package that you need.

XML::Parser
     If you want to use Net::LDAP::DSML you will need this module.

     You can obtain the latest release from
     http://search.cpan.org/search?module=XML::Parser

USING NET::LDAP
===============

How do I connect to my server ?
-------------------------------

   The connection to the server is created when you create a new Net::LDAP
object, e.g.

     $ldap = Net::LDAP->new($server);

Net::LDAP->new sometimes returns undef, why ?
---------------------------------------------

   The constructor will return undef if there was a problem connecting to
the specified server. Any error message will be available in $@

How can I tell when the server returns an error, bind() always returns true ?
-----------------------------------------------------------------------------

   Most methods in Net::LDAP return a
`Net::LDAP::Message|Net::LDAP::Message' in this node object, or a sub-class
of that. This object will hold the results from the server, including and
result code.

   So, for example, to determine the result of the bind operation.

     $mesg = $ldap->bind( $dn, password => $passwd);

     if ( $mesg->code ) {
       # Handle error codes here
     }

I did a search on my directory using the 'search' method. Where did the results go ?
------------------------------------------------------------------------------------

   Your search results are stored in a 'search object' container.
Consider the following:

     use Net::LDAP;

     $ldap = Net::LDAP->new('ldap.acme.com') or die "$@";
     $mesg = $ldap->search(
                           base   => "o=acme.com",
                           filter => "uid=jsmith",
                          );

   $mesg is a search object container. It is a reference blessed into the
`Net::LDAP::Search|Net::LDAP::Search' in this node package. By calling
methods on this object you can obtain information about the result and
also the individual entries.

   The first thing to check is if the search was successful. This is done
with with the method `$mesg-'code>. This method will return the status code
that the server returned. A success will yield a zero value, but there are
other values, some of which could also be considered a success.  See
`Net::LDAP::Constant|Net::LDAP::Constant' in this node

     use Net::LDAP::Util qw(ldap_error_text);

     die ldap_error_text($mesg->code)
       if $mesg->code;

   There are two ways in which you can access the entries. You can access
then with an index or you can treat the container like a stack and shift
each entry in turn. For example

     # as an array

     # How many entries were returned from the search
     my $max = $mesg->count;

     for( my $index = 0 ; $index < $max ; $index++) {
       my $entry = $mesg->entry($index);
       # ...
     }

     # or as a stack

     while( my $entry = $mesg->shift_entry) {
       # ...
     }

   In each case $entry is an entry object container. It is a reference
blessed into the `Net::LDAP::Entry|Net::LDAP::Entry' in this node package.
By calling methods on this object you can obtain information about the
entry.

   For example, to obtain the DN for the entry

     $dn = $entry->dn;

   To obtain the attributes that a given entry has

     @attrs = $entry->attributes;

   And to get the list of values for a given attribute

     @values = $entry->get( 'sn' );

   And to get the first of the values for a given attribute

     $values = $entry->get( 'cn' );

   One thing to remember is that attribute names are case insensitive, so
'sn', 'Sn', 'sN' and 'SN' are all the same.

   So, if you want to print all the values for the attribute `'ou'' then
this is as simple as

     foreach ($entry->get_value( 'ou' )) {
         print $_,"\n";
       }

   Now if you just want to print all the values for all the attributes you
can do

     foreach my $attr ($entry->attributes) {
       foreach my $value ($entry->get_value($attr)) {
         print $attr, ": ", $value, "\n";
       }
     }

How do I limit the scope of a directory search.
-----------------------------------------------

   You limit the scope of a directory search by setting the scope
parameter of search request.  Consider the following:

     use Net::LDAP;

     $ldap = Net::LDAP->new('ldap.acme.com') or die "$@";
     $mesg = $ldap->search(
                           base   => "o=acme.com",
                           scope  => 'sub',
                           filter => "uid=jsmith",
                          );

   Values for the scope parameter are as follows.

     base  Search only the base object.

     one   Search the entries immediately below the base
           object.

     sub   Search the whole tree below the base object.
           This is the default.

USING NET::LDAPS
================

Using a potentially encrypted (SSL) network connection, how do I connect to my server?
--------------------------------------------------------------------------------------

   This class is a subclass of Net::LDAP so all the normal Net::LDAP
methods can be used with a Net::LDAPS object; see the documentation for
Net::LDAP to find out how to query a directory server using the LDAP
protocol.

   The connection to the server is created when you create a new Net::LDAPS
object, e.g.

     $ldaps = Net::LDAPS->new($server,
                              port => '10000',
                              verify => 'require',
                              capath => '/usr/local/cacerts/',
                              );

   There are additional options to the LDAPS new method and several
additional methods are included in the LDAPS object class.

   For further information and code examples read the LDAPS module
documentation;  perldoc Net::LDAPS

USING LDAP GROUPS.
==================

What are LDAP groups.
---------------------

   LDAP groups are a collection of distinguished names (DN) that are
listed in an attribute called member.  One *important note* to remember is
that a group can be a collection of groups.  This does *NOT* imply that
the subgroups will be flattened into one big group.

   Two scripts for working with groups are available in the contrib
directory.  They are isMember.pl and printMembers.pl.

How do you format a filter to search for entries whose 'member' attribute has a particular value?
-------------------------------------------------------------------------------------------------

   Asking for (member=*) is OK - the directory uses the equality matching
rule which is defined for the member attribute.

   Asking for (member=c*) is not OK - there is no defined substring
matching rule for the member attribute. That's because the member values
are *not* strings, but distinguished names. There is no substring matching
rule for DNs, see RFC 2256 section 5.50.

   What you have to do is get the results of (member=*) and then select
the required results from the returned values. You need to do this using
knowledge of the string representation of DNs defined in RFC 2253, which
is important because the same DN can have different string
representations. So you need to perform some canonicalization if you want
to be correct.

USING DSML.
===========

How can I access DSML features from PERL-LDAP.
----------------------------------------------

   Directory Service Markup Language (DSML) is the XML standard for
representing directory service information in XML.

   Support for DSML is include in PERL-LDAP starting with version .20.

   At the moment this module only reads and writes DSML entry entities. It
cannot process any schema entities because schema entities are processed
differently than elements.

   Eventually this module will be a full level 2 consumer and producer
enabling you to give you full DSML conformance.

   The specification for DSML is at http://www.dsml.org

   For further information and code examples read the DSML module
documentation;  perldoc Net::LDAP::DSML

USING CONTROLS AND VIRTUAL LISTS.
=================================

How do I access the Control features.
-------------------------------------

   Support for LDAP version 3 Control objects is included in perl-ldap
starting with version .20.

   For further information and code examples read the Control module
documentation;  perldoc Net::LDAP::Control

How do I access the Virtual List features.
------------------------------------------

   Support for Virtual Lists is included in perl-ldap starting with
version .20.

   For further information and code examples read the Control module
documentation;  perldoc Net::LDAP::Control

GENERAL QUESTIONS.
==================

Are there any other code examples.
----------------------------------

   Yes, there is an Examples pod file.  To view the pod do the following
command;  perldoc Net::LDAP::Examples

   There is user contributed software in the contrib directory that is
supplied with the PERL-LDAP distribution.  This is an excellent source of
information on how to use the PERL-LDAP module.

Can I contribute perl scripts that use perl-ldap to the contrib section?
------------------------------------------------------------------------

   Any one can submit a perl script that uses perl-ldap for inclusion in
the contrib section.  Graham Barr will determine if the script will be
included and will do the initial check in of the script to the CVS system
on sourceforge.  Graham will make you the owner/developer of the script.

   There are a couple of requirements for consideration.

   You must supply a one line description of your script to be included in
the contrib readme file.

   Inside the script will be the pod documentation for the script.  No
auxiliary documentation will be allowed.  For examples of how to do this
see the tklkup or schema scripts currently in the contrib section.

   If Graham decides to include your script in the contrib section, you
must register with sourceforge before your scripts will be put into the
contrib CVS system.

Is possible to get a complete entry, dn and attributes  without specifying the attributes name?
-----------------------------------------------------------------------------------------------

   Yes, just specify you want a list of no attributes back. The RFC says
that this tells the server to return all readable attributes back (there
may be access controls to prevent some from being returned.)

   So in the search method, just set (for LDAPv2):

     attrs => [ ]

   If you are using LDAPv3, you can specify an attribute called "*"
instead, which lets you ask for additional (eg operational) attributes in
the same search.

     attrs => [ "*" ]

How do I put a jpeg photo into a entry in the directory.
--------------------------------------------------------

   Follow the following code example, replacing the (...) with whatever is
relevant to your setup.

     use Net::LDAP;
     use Net::LDAP::Util qw(ldap_error_text);
     use CGI;

     local $/ = undef;
     my $jpeg = <$filename>;

     my $ldap = new Net::LDAP(...);
     my $res = $ldap->bind(...);
        $res = $ldap->modify(...,
                      add => [ 'jpegPhoto' => [ $jpeg ] ]);
        $res = $ldap->unbind();

How do I add a jpeg photo into a entry in the directory via html -forms.
------------------------------------------------------------------------

   Follow the following code example, replacing the (...) with whatever is
relevant to your setup.

     use Net::LDAP;
     use Net::LDAP::Util qw(ldap_error_text);
     use CGI;

     my $q = new CGI;

     print $q->header;
     print $q->start_html(-title => 'Change JPEG photo');

     if ($q->param('Update')) {
             my $filename = $q->param('jpeg');
             local $/ = undef;
             my $jpeg = <$filename>;

     my $ldap = new Net::LDAP(...);
     my $res = $ldap->bind(...);
     $res = $ldap->modify(...,
                     add => [ 'jpegPhoto' => [ $jpeg ] ]);
     $res = $ldap->unbind();
       } else {
     print $q->start_multipart_form();
     print $q->filefield(-name => 'jpeg', -size => 50);
     print $q->submit('Update');
     print $q->end_form();
       }

     print $q->end_html();

How do I avoid file type and data type miss-matching when loading data from a Win32 system.
-------------------------------------------------------------------------------------------

   When loading a binary attribute with data read from a file on a Win32
system, it has been noted that you should set "binmode" on the file before
reading the file contents into the data array.

   Another possible solution to this problem is to convert the binary data
into a base64 encoded string and then store the encoded string in the
file.  Then when reading the file, decode the base64 encoded string back
to binary and then use perl ldap to store the data in the directory.

How do I create a Microsoft Exchange user.
------------------------------------------

   This is a solution provide by a perl-ldap user.

   This code works with ActiveState Perl running on WinNT 4. Please note
that this requires the Win32::Perms module, and needs valid NT account
info to replace the placeholders.

     use Net::LDAP qw(:all);
     use Net::LDAP::Util;
     use Win32::Perms;

     #Constants taken from ADSI Type Library
     $ADS_RIGHT_EXCH_ADD_CHILD = 1;
     $ADS_RIGHT_EXCH_DELETE = 0x10000;
     $ADS_RIGHT_EXCH_DS_REPLICATION = 64;
     $ADS_RIGHT_EXCH_DS_SEARCH = 256;
     $ADS_RIGHT_EXCH_MAIL_ADMIN_AS = 32;
     $ADS_RIGHT_EXCH_MAIL_RECEIVE_AS = 16;
     $ADS_RIGHT_EXCH_MAIL_SEND_AS = 8;
     $ADS_RIGHT_EXCH_MODIFY_ADMIN_ATT = 4;
     $ADS_RIGHT_EXCH_MODIFY_SEC_ATT = 128;
     $ADS_RIGHT_EXCH_MODIFY_USER_ATT = 2;

     $EXCH_USER_RIGHTS = $ADS_RIGHT_EXCH_MAIL_RECEIVE_AS |
     $ADS_RIGHT_EXCH_MAIL_SEND_AS |
     $ADS_RIGHT_EXCH_MODIFY_USER_ATT;

     $exch = new Net::LDAP('server', debug =>0) || die $@;

     $exch->bind( 'cn=admin_user,cn=nt_domain,cn=admin', version =>3,
     password=>'password');

     $myObj = Win32::Perms->new();
     $Result = $myObj->Owner('nt_domain\user_name');
     $myObj->Group('nt_domain\Everyone');
     $myObj->Allow('nt_domain\user_name',
     $EXCH_USER_RIGHTS,OBJECT_INHERIT_ACE);
     $BinarySD = $myObj->GetSD(SD_RELATIVE);
     $TextSD = uc(unpack( "H*", $BinarySD ));
     Win32::Perms::ResolveSid('nt_domain\user_name', $sid);
     $mysid = uc(unpack("H*",$sid));

     $result = $exch->add ( dn   =>
                   'cn=user_name,cn=container,ou=site,o=organisation',
                   attr => [ 'objectClass' => ['organizationalPerson'],
                             'cn'   => 'directory_name',
                             'uid' => 'mail_nickname',
                             'mail' => 'smtp_address',
                           'assoc-nt-account' => [ $mysid ],
                           'nt-security-descriptor' => [ $TextSD ],
                           'mailPreferenceOption'  => 0
                           ]
                 );

     print ldap_error_name($result->code);

Using X.509 certificates.
=========================

How do I store X.509 certificates in the directory?
---------------------------------------------------

   The first problem here is that there are many different formats to hold
certificates in, for example PEM, DER, PKCS#7 and PKCS#12. The directory
*only* uses the DER format (more correctly, it only uses the BER format)
which is a binary format.

   Your first job is to ensure that your certificates are therefore in
DER/BER format. You could use OpenSSL to convert from PEM like this:

     openssl x509 -inform PEM -in cert.pem -outform DER -out cert.der

   Consult the OpenSSL documentation to find out how to perform other
conversions.

   To add a certificate to the directory, just slurp in the DER/BER
certificate into a scalar variable, and add it to the entry's
userCertificate attribute. How you do that will depend on which version of
LDAP you are using.

   To slurp in the certificate try something like this:

     my $cert;
     {
     	local $/ = undef; # Slurp mode
     	open CERT, "cert.der" or die;
     	$cert = <CERT>;
     	close CERT;
     }
     # The certificate is now in $cert

   For LDAPv2, because most directory vendors ignore the string
representation of certificates defined in RFC 1778, you should add this
value to the directory like this:

     $res = $ldap->modify("cn=My User, o=My Company,c=XY",
     		add => [
     			'userCertificate' => [ $cert ]
     		]);
     die "Modify failed (" . ldap_error_name($res->code) . ")\n"
     	if $res->code;

   For LDAPv3, you must do this instead:

     $res = $ldap->modify("cn=My User, o=My Company, c=XY",
     		add => [
     			'userCertificate;binary' => [ $cert ]
     		]);
     die "Modify failed (" . ldap_error_name($res->code) . ")\n"
     	if $res->code;

   Of course, the entry you are trying to add the certificate to must use
object classes that permit the userCertificate attribute, otherwise the
modify will fail with an object class violation error. The inetOrgPerson
structural object class permits userCertificates, as does the
strongAuthenticationUser auxiliary object class. Others might also.

ADDITIONAL DIRECTORY AND LDAP RESOURCES.
========================================

URL(s).
-------

   Deploying LDAP http://bostonlight.com/ldap/

   Directory Services Mark Language (DSML) http://www.dsml.org/

   Jeff Hodges's Kings Mountain LDAP
http://www.kingsmountain.com/ldapRoadmap.shtml

   Mark Wahl's LDAP World at Innosoft.  http://www.innosoft.com/ldapworld/

   Open Source LDAP Directory Server.  http://www.openldap.org/

   CriticalPath http://www.cp.net/

   Innosoft http://www.innosoft.com

   IPlanet - Netscape and SUN Alliance http://www.iplanet.com/

   MessagingDirect http://www.messagingdirect.com/

   Netscape Directory Developers Area
http://developer.netscape.com/directory/

   Nexor's X.500 and Internet Directories
http://www.nexor.com/info/directory.htm/

   SUN JAVA JNDI (Java Naming and Directory Interface)
http://www.java.sun.com/jndi/

BOOK(s)
-------

   Developing LDAP and ADSI Clients for Microsoft(R) Exchange.  By Sven B.
Schreiber.  ISBN:  0201657775

   Implementing LDAP.  By Mark Wilcox.  ISBN:  1861002211

   LDAP : Programming Directory-Enabled Applications With Lightweight
Directory Access Protocol.  By Tim Howes, Mark Smith.  ISBN:  1578700000

   LDAP Programming with Java.  By Rob Weltman, Tony Dahbura.  ISBN:
0201657589

   Understanding and Deploying Ldap Directory Services.  By Tim Howes,
Mark Smith, Gordon Good, Timothy A. Howe ISBN:  1578700701

AUTHOR(s)
=========

   Any good FAQ is made up of many authors, everyone that contributes
information to the perl-ldap mail list is a potential author.

   An attempt to maintain this FAQ is being done by Clif Harden
<charden@texoma.net>.

   The original author of this FAQ was Graham Barr <gbarr@pobox.com>

   Please report any bugs, or post any suggestions, to the perl-ldap
mailing list  <perl-ldap-dev@lists.sourceforge.net>.

COPYRIGHT
=========

   Copyright (c) 1999-2000 Graham Barr. All rights reserved. This document
is distributed, and may be redistributed, under the same terms as Perl
itself.

representation of LDAP filters
******************************

NAME
====

   Net::LDAP::Filter - representation of LDAP filters

SYNOPSIS
========

     use Net::LDAP::Filter;

     $filter = Net::LDAP::Filter->new( $filter_str );

DESCRIPTION
===========

CONSTRUCTOR
===========

new ( FILTER )
     Create a new object and parse FILTER.

METHODS
=======

parse ( FILTER )
     Parse FILTER. The next call to ber will return this filter encoded.

asn
     Return the data structure suitable for passing directly to
     Convert/ASN1, to encode a filter object.

as_string
     Return the filter in text form.

print ( [ FH ] )
     Print the text representation of the filter to FH, or the currently
     selected output handle if FH is not given.

FILTER SYNTAX
=============

   Below is the syntax for a filter given in RFC-2254
http://info.internet.isi.edu/in-notes/rfc/files/rfc2254.txt

     filter       = "(" filtercomp ")"
     filtercomp   = and / or / not / item
     and          = "&" filterlist
     or           = "|" filterlist
     not          = "!" filter
     filterlist   = 1*filter
     item         = simple / present / substring / extensible
     simple       = attr filtertype value
     filtertype   = equal / approx / greater / less
     equal        = "="
     approx       = "~="
     greater      = ">="
     less         = "<="
     extensible   = attr [":dn"] [":" matchingrule] ":=" value
                    / [":dn"] ":" matchingrule ":=" value
     present      = attr "=*"
     substring    = attr "=" [initial] any [final]
     initial      = value
     any          = "*" *(value "*")
     final        = value
     attr         = AttributeDescription from Section 4.1.5 of RFC-2251
     matchingrule = MatchingRuleId from Section 4.1.9 of RFC-2251
     value        = AttributeValue from Section 4.1.6 of RFC-2251

     Special Character encodings
     ---------------------------
        *               \2a, \*
        (               \28, \(
        )               \29, \)
        \               \5c, \\
        NUL             \00

SEE ALSO
========

   `Net::LDAP|Net::LDAP' in this node, `Other online
documentation|Net::LDAP::RFC' in this node

ACKNOWLEDGEMENTS
================

   This document is based on a document originally written by Russell
Fulton <r.fulton@auckland.ac.nz>.

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

   Please report any bugs, or post any suggestions, to the perl-ldap
mailing list <perl-ldap-dev@lists.sourceforge.net>.

COPYRIGHT
=========

   Copyright (c) 1997-2000 Graham Barr. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

LDIF reading and writing
************************

NAME
====

   Net::LDAP::LDIF - LDIF reading and writing

SYNOPSIS
========

     use Net::LDAP::LDIF;

     $ldif = Net::LDAP::LDIF->new( "file.ldif", "r" );
     while( $entry = $ldif->read() ) {
     	  # Do things with $entry
     }
     $ldif->done();

     $ldif = Net::LDAP::LDIF->new( $fh, "r" );
     @entries = $ldif->read();

DESCRIPTION
===========

   *Net::LDAP::LDIF* provides a means to convert between
`Net::LDAP::Entry|Net::LDAP::Entry' in this node objects and LDAP entries
represented in LDIF format files. Reading and writing are supported and
may manipulate single entries or lists of entries.

   As when reading an entire file into memory with perl normally, take into
account the possibility of memory use when loading an LDIF file in one go.

CONSTRUCTOR
===========

new ( [ FILE [, MODE]] )
     FILE may be the name of a file or an already open filehandle. If a
     filename is passed in then it will be opened with the mode specified.

     MODE defaults to "r" for read. You may specify "w" to for
     write+truncate or "a" for write+append.

METHODS
=======

read
     In a similar fashion to the perl <$fh> operator, read will read one
     entry or the entire file depending on whether it is called in a
     scalar or array context.

read_cmd
write ( ENTRIES )
write_cmd ( ENTRIES )
done
     This method signals that the LDIF object is no longer needed. If a
     file was opened automatically when the object was created it will be
     closed. This method is called automatically via DESTROY when the
     object goes out of scope.

          $ldif->done();

AUTHOR
======

   Graham Barr <gbarr@pobox.com>.

   Please report any bugs, or post any suggestions, to the perl-ldap
mailing list <perl-ldap-dev@lists.sourceforge.net>.

COPYRIGHT
=========

   Copyright (c) 1997-2000 Graham Barr. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Message response from LDAP server
*********************************

NAME
====

   Net::LDAP::Message - Message response from LDAP server

SYNOPSIS
========

     use Net::LDAP;

DESCRIPTION
===========

   *Net::LDAP::Message* is a base class for the objects returned by the
`Net::LDAP|Net::LDAP' in this node methods `abandon|Net::LDAP' in this
node, `add|Net::LDAP' in this node, `bind|Net::LDAP' in this node,
`compare|Net::LDAP' in this node, `delete|Net::LDAP' in this node,
`modify|Net::LDAP' in this node, `moddn|Net::LDAP' in this node,
`search|Net::LDAP' in this node and `unbind|Net::LDAP' in this node.

   The sub-class `Net::LDAP::Search|Net::LDAP::Search' in this node
returned by `search|Net::LDAP' in this node also defines many methods.

   If the `Net::LDAP|Net::LDAP' in this node object is in async mode then
all these methods, except done, will cause a wait until the request is
completed.

METHODS
=======

code
     The code value in the result message from the server. Normally for a
     success zero will be returned. `Constants|Net::LDAP::Constant' in
     this node for the result codes can be imported from the
     `Net::LDAP|Net::LDAP' in this node module.

control [ OID ]
     Return a list of controls returned from the server. If OID is given
     then only controls with type equal to OID will be returned.

dn
     The DN in the result message from the server.

done
     Returns *true* if the request has been completed.

error
     The error message in the result message from the server. If the
     server did not include an error message, then the result of
     `ldap_error_desc|Net::LDAP::Util' in this node with the error code
     from the result message.

is_error
     Returns *true* if the result code is considered to be an error for
     the operation.

mesg_id
     The message id of the request message sent to the server.

referrals
     Returns a list of referrals from the result message.

server_error
     The error message returned by the server, or undef if the server did
     not provide a message.

sync
     Wait for the server to complete the request.

SEE ALSO
========

   `Net::LDAP|Net::LDAP' in this node,
`Net::LDAP::Search|Net::LDAP::Search' in this node,
`Net::LDAP::Constant|Net::LDAP::Constant' in this node,
`Net::LDAP::Util|Net::LDAP::Util' in this node

ACKNOWLEDGEMENTS
================

   This document is based on a document originally written by Russell
Fulton <r.fulton@auckland.ac.nz>.

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

   Please report any bugs, or post any suggestions, to the perl-ldap
mailing list <perl-ldap-dev@lists.sourceforge.net>.

COPYRIGHT
=========

   Copyright (c) 1997-2000 Graham Barr. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

List of related RFC's
*********************

NAME
====

   Net::LDAP::RFC - List of related RFC's

SYNOPSIS
========

     none

DESCRIPTION
===========

   The LDAP protocol is defined in the following RFC's

RFC-2251 - Lightweight Directory Access Protocol (v3).
     http://info.internet.isi.edu/in-notes/rfc/files/rfc2251.txt

RFC-2251 - Lightweight Directory Access Protocol (v3).
     http://info.internet.isi.edu/in-notes/rfc/files/rfc2251.txt

RFC-2252 - Attribute Syntax Definitions.
     http://info.internet.isi.edu/in-notes/rfc/files/rfc2252.txt

RFC-2253 - UTF-8 String Representation of Distinguished Names.
     http://info.internet.isi.edu/in-notes/rfc/files/rfc2253.txt

RFC-2254 - The String Representation of LDAP Search Filters.
     http://info.internet.isi.edu/in-notes/rfc/files/rfc2254.txt

RFC-2255 - The LDAP URL Format.
     http://info.internet.isi.edu/in-notes/rfc/files/rfc2255.txt

RFC-2256 - A Summary of the X.500(96) User Schema for use with LDAPv3.
     http://info.internet.isi.edu/in-notes/rfc/files/rfc2256.txt

RFC-2696 - LDAP Control Extension for Simple Paged Results Manipulation
     http://info.internet.isi.edu/in-notes/rfc/files/rfc2696.txt

search reference
****************

NAME
====

   Net::LDAP::Reference - search reference

SYNOPSIS
========

     use Net::LDAP;

     $ldap->search( @search_args, callback => \&process);

     sub process {
       my $mesg = shift;
       my $obj = shift;
       if (!$obj) {
         # Search complete
       }
       elsif ($obj->isa('Net::LDAP::Reference')) {
         my $ref;

         foreach $ref ($obj->references) {
           # process ref
         }
       }
       else {
         # Process Net::LDAP::Entry
       }
     }

DESCRIPTION
===========

METHODS
=======

references
     Returns a list of references from the server.

SEE ALSO
========

   `Net::LDAP|Net::LDAP' in this node,
`Net::LDAP::Search|Net::LDAP::Search' in this node

AUTHOR
======

   Graham Barr <gbarr@pobox.com>.

   Please report any bugs, or post any suggestions, to the perl-ldap
mailing list <perl-ldap-dev@lists.sourceforge.net>.

COPYRIGHT
=========

   Copyright (c) 1997-2000 Graham Barr. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Load and manipulate an LDAP v3 Schema
*************************************

NAME
====

   Net::LDAP::Schema - Load and manipulate an LDAP v3 Schema

SYNOPSIS
========

     use Net::LDAP;
     use Net::LDAP::Schema;

     #
     # Read schema from server
     #
     $ldap = Net::LDAP->new( $server );
     $ldap->bind();
     $schema = $ldap->schema();

     #
     # Load from LDIF
     #
     $schema = Net::LDAP->new;
     $schema->parse( "schema.ldif" ) or die $schema->error;

DESCRIPTION
===========

   *Net::LDAP::Schema* provides a means to load an LDAP schema and query it
for information regarding supported objectclasses, attributes and syntaxes.

METHODS
=======

   Where a method is stated as taking the 'name or oid' of a schema item
(which may be an object class, attribute or syntax) then a
case-insensitive name or raw oid (object identifier, in dotted numeric
string form, e.g. 2.5.4.0) may be supplied.

attributes
     With no arguments, returns a list of the names all attributes in the
     schema.

          @atts = $schema->attributes();

     If called with an argument which is the name or oid of a known object
     class, returns a list of the attributes which may (or must) be
     present in the OC.

          @person_atts = $schema->attributes( "person" );

     Return value is an array or array reference depending on calling
     context, or empty list on error.

dump
     Given an argument which is the name of a file, and the file or
     directory has write permission, will dump the raw schema information
     to a file.  If no argument is given the raw schema information is
     dumped to standard out.

          $result = $schema->dump( "./schema.dump" );

          or

          $result = $schema->dump();

     If no schema data is returned from directory server, the method will
     return undefined.  Otherwise a value of 1 is always returned.

error
     Returns the last error encountered.

is_objectclass, is_attribute, is_syntax, is_matchingrule
     Given the name or oid of a schema item (object class, attribute,
     syntax or matchingrule respectively) returns the assoicated OID or
     undef if the name or oid is not of the appropriate type.

          # Is foo a known OC?
          $oid = $schema->is_objectclass( "foo" );
          # No? Bale out.
          die( "Not an objectclass" ) unless $oid;
          # Yes...so we can do this
          @must = $schema->must( $oid );

item
     Given two arguments, first of which is the name or oid of a known
     object class or attribute and second of which is the name of the
     item, returns the item's data value.  The item's value may be
     undefined.

          @item = $schema->item( $oid, "desc" );

     Return value is an array or a value depending on calling context.

items
     Given an argument which is the name or oid of a known object class or
     attribute, returns the items available for this attribute or object
     class.  The returned item name may have an undefined value.

          @items = $schema->items( $oid );

     Return value is an array or array reference depending on calling
     context.

matchingrules
     Returns a list of the names of all matchingrules in the schema.

          @mrs = $schema->matchingrules();

     Return value is an array or array reference depending on calling
     context.

may
     Given an argument which is the name or oid of a known object class,
     returns the name of the attributes which are optional in the class.

          @may = $schema->may( $oc );

     Return value is an array or array reference depending on calling
     context.

must
     Given an argument which is the name or oid of a known object class,
     returns the name of the attributes which are mandatory in the class

          @must = $schema->must( $oc );

     Return value is an array or array reference depending on calling
     context.

name2oid
     Given the name of a schema item (object class, attribute or syntax)
     returns the assoicated OID or undef if it is not recognised.

objectclasses
     Returns a list of the names of all objectclasses in the schema.

          @ocs = $schema->objectclasses();

     Return value is an array or array reference depending on calling
     context.

parse
     Takes a single argument which can be any of, A message objected
     returned from an LDAP search, a Net::LDAP::Entry object or the name
     of a file containing an LDIF form of the schema.

     If the argument is a message result from a search, Net::LDAP::Schema
     will parse the schema from the first entry returned.

     Returns true on success and undef on error.

superclass
     Given an argument which is the name or oid of a known objectclass,
     returns the list of names of the immediate superclasses.

syntax
     Given an argument which is the name or oid of a known attribute,
     returns the name of the attribute's syntax (or the syntax of the
     attributes superior if the syntax is inherited).

          $name_syntax = $schema->syntax( "commonName" );

syntaxes
     Returns a list of the names of all objectclasses in the schema. (The
     name of a syntax is not well defined. It may be an OID or abbreviated
     description).

          @syns = $schema->syntaxes();

     Return value is an array or array reference depending on calling
     context.

SEE ALSO
========

   `Net::LDAP|Net::LDAP' in this node, `Other online
documentation|Net::LDAP::RFC' in this node

AUTHORS
=======

   Graham Barr <gbarr@pobox.com> John Berthels <jjb@nexor.co.uk>

   Please report any bugs, or post any suggestions, to the perl-ldap
mailing list <perl-ldap-dev@lists.sourceforge.net>.

COPYRIGHT
=========

   Copyright (c) 1998-2000 Graham Barr. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Object returned by Net::LDAP search method
******************************************

NAME
====

   Net::LDAP::Search - Object returned by Net::LDAP search method

SYNOPSIS
========

     use Net::LDAP;

     $mesg = $ldap->search( @search_args );

     @entries = $mesg->entries;

DESCRIPTION
===========

   A *Net::LDAP::Search* object is returned from the `search|Net::LDAP' in
this node method of a `Net::LDAP|Net::LDAP' in this node object. It is a
container object which holds the results of the search.

METHODS
=======

   *Net::LDAP::Search* inherits from
`Net::LDAP::Message|Net::LDAP::Message' in this node, and so supports all
methods defined in `Net::LDAP::Message|Net::LDAP::Message' in this node.

as_struct
     Returns a reference to a HASH, where the keys are the DN's of the
     results and the values are HASH references. These second level HASH's
     hold the attributes such that the keys are the attribute names, in
     lowercase, and the values are references to and ARRAY holding the
     values.

     This method will block until the whole search request has finished.

count
     Returns the number of entries returned by the server.

     This method will block until the whole search request has finished.

entry ( INDEX )
     Return the N'th entry, which will be a
     `Net::LDAP::Entry|Net::LDAP::Entry' in this node object. If INDEX is
     greater than the total number of entries returned then undef will be
     returned.

     This method will block until the search request has returned enough
     entries.

entries
     Return an array of `Net::LDAP::Entry|Net::LDAP::Entry' in this node
     objects hat were returned from the server.

     This method will block until the whole search request has finished.

pop_entry
     Pop an entry from the internal list of
     `Net::LDAP::Entry|Net::LDAP::Entry' in this node objects for this
     search. If there are not more entries then undef is returned.

     This call will block, if the list is empty, until the server returns
     another entry.

references
     Return a list of references that the server returned. This will be a
     list of `Net::LDAP::Reference|Net::LDAP::Reference' in this node
     objects.

sorted ( [ ATTR ] )
     Return a list of `Net::LDAP::Entry|Net::LDAP::Entry' in this node
     objects, sorted by ATTR. If ATTR is not given then the entries will
     be sorted by their DN.

shift_entry
     Shift an entry from the internal list of
     `Net::LDAP::Entry|Net::LDAP::Entry' in this node objects for this
     search. If there are not more entries then undef is returned.

     This call will block, if the list is empty, until the server returns
     another entry.

SEE ALSO
========

   `Net::LDAP|Net::LDAP' in this node,
`Net::LDAP::Message|Net::LDAP::Message' in this node,
`Net::LDAP::Entry|Net::LDAP::Entry' in this node,
`Net::LDAP::Reference|Net::LDAP::Reference' in this node

ACKNOWLEDGEMENTS
================

   This document is based on a document originally written by Russell
Fulton <r.fulton@auckland.ac.nz>.

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

   Please report any bugs, or post any suggestions, to the perl-ldap
mailing list <perl-ldap-dev@lists.sourceforge.net>.

COPYRIGHT
=========

   Copyright (c) 1997-2000 Graham Barr. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Utility functions
*****************

NAME
====

   Net::LDAP::Util - Utility functions

SYNOPSIS
========

     use Net::LDAP::Util qw(ldap_error_text
                            ldap_error_name
                            ldap_error_desc
                           );

     $mesg = $ldap->search( .... );

     die "Error ",ldap_error_name($mesg->code) if $mesg->code;

DESCRIPTION
===========

   *Net::LDAP::Util* is a collection of utility functions for use with the
`Net::LDAP|Net::LDAP' in this node modules.

FUNCTIONS
=========

ldap_error_name ( NUM )
     Returns the name corresponding with the error number passed in. If the
     error is not known the a string in the form `"LDAP error code
     %d(0x%02X)"' is returned.

ldap_error_text ( NUM )
     Returns the text from the POD description for the given error. If the
     error code given is unknown then undef is returned.

ldap_error_desc ( NUM )
     Returns a short text description of the error.

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

COPYRIGHT
=========

   Copyright (c) 1999-2000 Graham Barr. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

use LDAP over an SSL connection
*******************************

NAME
====

   Net::LDAPS - use LDAP over an SSL connection

SYNOPSIS
========

     use Net::LDAPS;

     $ldaps = new Net::LDAPS('myhost.example.com',
                             port => '10000',
                             verify => 'require',
                             capath => '/usr/local/cacerts/');

DESCRIPTION
===========

   Communicate using the LDAP protocol to a directory server using a
potentially encrypted (SSL) network connection.

   This class is a subclass of Net::LDAP so all the normal Net::LDAP
methods can be used with a Net::LDAPS object; see the documentation for
Net::LDAP to find out how to query a directory server using the LDAP
protocol.

CONSTRUCTOR
===========

new ( HOST [, OPTIONS ] )
     Create a new connection. HOST is the hostname to contact. OPTIONS is a
     number of key/value pairs - additional keys to those understood by
     Net::LDAP::new are:

    verify
          How to verify the server's certificate, either 'none' (the
          server may provide a cert but don't verify it - this may mean
          you are be connected to the wrong server), 'optional' (verify if
          the server offers a cert), or 'require' (the server must provide
          a cert, and it must be valid.) If you set verify to optional or
          require, you must also set either cafile or capath.

    ciphers
          Specify which subset of cipher suites are permissible for this
          connection, using the standard OpenSSL string format. The
          default value for ciphers is 'ALL', which permits all ciphers.

    clientcert
    clientkey
          If you want to use the client to offer a certificate to the
          server for SSL authentication (which is not the same as for the
          LDAP Bind operation) then set clientcert to the user's
          certificate file, and clientkey to the user's private key file.

    capath
    cafile
          When verifying the server's certificate, either set capath to the
          pathname of the directory containing CA certificates, or set
          cafile to the filename containing the certificate of the CA who
          signed the server's certificate.

          The directory in 'capath' must contain certificates named using
          the hash value of themselves. To generate these names, use
          OpenSSL thusly:

               ln -s cacert.pem `openssl x509 -hash -nout < cacert.pem`.0

          (assuming that the certificate of the CA is in cacert.pem.)

ADDITIONAL METHODS
==================

cipher
     Returns the cipher mode being used by the connection, in the string
     format used by OpenSSL.

certificate
     Returns an X509_Certificate object containing the server's
     certificate. See the IO::Socket::SSL documentation for information
     about this class.

     For example, to get the subject name (in a peculiar OpenSSL-specific
     format, different from RFC 1779 and RFC 2253) from the server's
     certificate, do this:

          print "Subject DN: " . $ldaps->certificate->subject_name . "\n";

SEE ALSO
========

   `Net::LDAP|Net::LDAP' in this node, `IO::Socket::SSL|IO::Socket::SSL'
in this node

BUGS
====

   Several apparently bogus warnings are emitted when initializing the two
underlying modules used by Net::LDAPS, namely IO::Socket::SSL and
Net::SSLeay. To avoid these, don't initialize via 'use Net::LDAPS' and
instead try initializing Net::LDAPS like this:

     BEGIN {
         # Turn off all warnings etc whilst initializing
         # IO::Socket::SSL and Net::SSLeay.
         local $^W = 0;
         no strict;
         require Net::SSLeay;
         # The /dev/urandom is a device on Linux that returns
         # random data.
         Net::SSLeay::randomize('/dev/urandom');
         require Net::LDAPS;
     }

AUTHOR
======

   Chris Ridd <chris.ridd@messagingdirect.com>

COPYRIGHT
=========

   Copyright (c) 2000, Chris Ridd and Graham Barr. All rights reserved.
This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl5 Module Supporting LDAP API
********************************

NAME
====

   Net::LDAPapi - Perl5 Module Supporting LDAP API

SYNOPSIS
========

     use Net::LDAPapi;

     See individual items and Example Programs for Usage

DESCRIPTION
===========

     This module allows Perl programmers to access and manipulate an LDAP
     based Directory.

     Versions beginning with 1.40 support both the original "C API" and
     new "Perl OO" style interface methods.  With version 1.42, I've added
     named arguments.

THE INTIAL CONNECTION
=====================

     All connections to the LDAP server are started by creating a new
     "blessed object" in the Net::LDAPapi class.  This can be done quite
     easily by the following type of statement.

     $ld = new Net::LDAPapi($hostname);

     Where $hostname is the name of your LDAP server.  If you are not using
     the standard LDAP port (389), you will also need to supply the portnumber.

     $ld = new Net::LDAPapi($hostname,15555);

     The new method can also be called with named arguments.

     $ld = new Net::LDAPapi(-host=>$hostname,-port=>15389);

     Note that with namd arguments, the order of the arguments is
     insignificant.

BINDING
=======

     After creating a connection to the LDAP server, you will always need to
     bind to the server prior to performing any LDAP related functions.  This
     can be done with the 'bind' methods.

     An anonymous bind can be performed without arguments:

     $status = $ld->bind_s;

     A simple bind can be performed by specifying the DN and PASSWORD of
     the user you are authenticating as:

     $status = $ld->bind_s($dn,$password);

     Note that if $password above was "", you would be doing a reference bind,
     which would return success even if the password in the directory was
     non-null.  Thus if you were using the bind to check a password entered
     with one in the directory, you should first check to see if $password was
     NULL.

     If your LDAP C Library supports Kerberos, you can also do Kerberos binds
     simply by adding the LDAP_AUTH_KRBV4 option.  For example:

     $status = $ld->bind_s($dn,$password,LDAP_AUTH_KRBV4);

     For all of the above operations, you could compare $status to LDAP_SUCCESS
     to see if the operation was successful.

     Additionally, you could use 'bind' rather than 'bind_s' if you wanted to
     use the Asynchronous LDAP routines.  The asynchronous routines would return
     a MSGID rather than a status.  To find the status of an Asynchronous bind,
     you would need to first obtain the result with a call to $ld->result.  See
     the entry for result later in the man page, as well as the 'ldapwalk.pl'
     example for further information on obtaining results from Asynchronous
     operations.

     The bind operations can also accept named arguments.

     $status = $ld->bind_s(-dn=>$dn,-password=>$password,-type=>LDAP_AUTH_SIMPLE);

     As with all other commands that support named arguments, the order of
     the arguments makes no difference.

GENERATING AN ADD/MODIFY HASH
=============================

     For the add and modify routines you will need to generate
     a list of attributes and values.

     You will do this by creating a HASH table.  Each attribute in the
     hash contains associated values.  These values can be one of three
     things.

     - SCALAR VALUE    (ex. "Clayton Donley")
     - ARRAY REFERENCE (ex. ["Clayton Donley","Clay Donley"])
     - HASH REFERENCE  (ex. {"r",["Clayton Donley"]}
          note:  the value inside the HASH REFERENCE must currently
     	         be an ARRAY REFERENCE.

     The key inside the HASH REFERENCE must be one of the following for a
     modify operation:
       - "a" for LDAP_MOD_ADD (Add these values to the attribute)
       - "r" for LDAP_MOD_REPLACE (Replace these values in the attribute)
       - "d" for LDAP_MOD_DELETE (Delete these values from the attribute)

     Additionally, in add and modify operations, you may specify "b" if the
     attributes you are adding are BINARY (ex. "rb" to replace binary).

     Currently, it is only possible to do one operation per add/modify
     operation, meaning you can't do something like:

     {"d",["Clayton"],"a",["Clay"]}   <-- WRONG!

     Using any combination of the above value types, you can do things like:

     %ldap_modifications = (
        "cn", "Clayton Donley",                    # Replace 'cn' values
        "givenname", ["Clayton","Clay"],           # Replace 'givenname' values
        "mail", {"a",["donley\@cig.mcel.mot.com"],  #Add 'mail' values
        "jpegphoto", {"rb",[$jpegphotodata]},      # Replace Binary jpegPhoto
     );

     Then remember to call the add or modify operations with a REFERENCE to
     this HASH.  Something like:

     $ld->modify_s($modify_dn,\%ldap_modifications);

GETTING/SETTING LDAP INTERNAL VALUES
====================================

     The following methods exist to obtain internal values within a
     Net::LDAPapi object:

     o errno - The last error-number returned by the LDAP library for this
       connection.
             ex:  print "Error Number: " . $ld->errno . "\n";

     o errstring - The string equivalent of 'errno'.
             ex:  print "Error: " . $ld->errstring . "\n";

     o ld - Reference to the actual internal LDAP structure.  Only useful if
       you needed to obtain this pointer for use in non-OO routines.
             ex:  $ldptr = $ld->ld;

     o entry - Reference to the current entry.  Not typically needed, but method
       supplied, just in case.
             ex:  $entry = $ld->entry;

     o msgid - Get msgid from an LDAP Result.
             ex:  $msgid = $ld->msgid;  #  msgid of current result
             ex:  $msgid = $ld->msgid($result) # msgid of $result

     o msgtype - Get msgtype from an LDAP Result.
     	  ex:  $msgtype = $ld->msgtype;  # msgtype of current result
             ex:  $msgtype = $ld->msgtype($result) # msgtype of $result

     These methods are only useful for GETTING internal information, not setting
     it.  No methods are currently available for SETTING these internal values.

GETTING AND SETTING LDAP SESSION OPTIONS
========================================

     The get_option and set_option methods can be used to get and set LDAP
     session options.

     The following LDAP options can be set or gotten with these methods:
     	LDAP_OPT_DEREF - Dereference
     	LDAP_OPT_SIZELIMIT - Maximum Number of Entries to Return
     	LDAP_OPT_TIMELIMIT - Timeout for LDAP Operations
     	LDAP_OPT_REFERRALS - Follow Referrals

     For both get and set operations, the first argument is the relivant
     option.  In get, the second argument is a reference to a scalar variable
     that will contain the current value of the option.  In set, the second
     argument is the value at which to set this option.

     Examples:
       $ld->set_option(LDAP_OPT_SIZELIMIT,50);
       $ld->get_option(LDAP_OPT_SIZELIMIT,\$size);

     When setting LDAP_OPT_REFERRALS, the second argument is either LDAP_OPT_ON
     or LDAP_OPT_OFF.  Other options require a number.

     Both get_option and set_option return 0 on success and non-zero otherwise.

SSL SUPPORT
===========

     When compiled with the Netscape SDK, this module now supports SSL.
     I do not have an SSL capable server, but I'm told this works.  The
     functions available are:

     o ssl - Turn on SSL for this connection.
       Install I/O routines to make SSL over LDAP possible
     o ssl_client_init($certdbpath,$certdbhandle)
       Initialize the secure parts (called only once)

     Example:
       $ld = new Net::LDAPapi("host",LDAPS_PORT);
       $ld->ssl_client_init($certdbpath,$certdbhandle);
       $ld->ssl;

SETTING REBIND PROCESS
======================

     As of version 1.42, rebinding now works properly.

     The set_rebind_proc method is used to set a PERL function to supply DN,
     PASSWORD, and AUTHTYPE for use when the server rebinds (for referals,
     etc...).

     Usage should be something like:
       $rebind_ref = \&my_rebind_proc;
       $ld->set_rebind_proc($rebind_ref);

     You can then create the procedure specified.  It should return 3 values.

     Example:
       sub my_rebind_proc
       {
          return($dn,$pass,LDAP_AUTH_SIMPLE);
       }

SUPPORTED METHODS
=================

abandon MSGID
          This cancels an asynchronous LDAP operation that has not completed.  It
          returns an LDAP STATUS code upon completion.

          Example:

          $status = ldap_abandon($ld, $msgid);

add DN ATTR
          Begins an an asynchronous LDAP Add operation.  It returns a MSGID or -1
          upon completion.

          Example:

          %attributes = (
             "cn", ["Clayton Donley","Clay Donley"] #Add Multivalue cn
             "sn", "Donley",			      #Add sn
             "telephoneNumber", "+86-10-65551234",  #Add telephoneNumber
             "objectClass", ["person","organizationalPerson"],
                              # Add Multivalue objectClass
             "jpegphoto", {"b",[$jpegphoto]},  # Add Binary jpegphoto
          );

          $entrydn = "cn=Clayton Donley, o=Motorola, c=US";

          $msgid = $ld->add($entrydn, \%attributes);

          Note that in most cases, you will need to be bound to the LDAP server
          as an administrator in order to add users.

add_s DN ATTR
          Synchronous version of the 'add' method.  Arguments are identical
          to the 'add' method, but this operation returns an LDAP STATUS,
          not a MSGID.

          Example:

          $ld->add_s($entrydn, \%attributes);

          See the section on creating the modify structure for more information
          on populating the ATTRIBUTES field for Add and Modify operations.

bind DN PASSWORD TYPE
          Asynchronous method for binding to the LDAP server.  It returns a
          MSGID.

          Examples:

          $msgid = $ld->bind;
          $msgid = $ld->bind("cn=Clayton Donley, o=Motorola, c=US", "abc123");

bind_s DN PASSWORD TYPE
          Synchronous method for binding to the LDAP server.  It returns
          an LDAP STATUS.

          Examples:

          $status = $ld->bind_s;
          $status = $ld->bind_s("cn=Clayton Donley, o=Motorola, c=US", "abc123");

compare DN ATTR VALUE
          Asynchronous method for comparing a value with the value contained
          within DN.  Returns a MSGID.

          Example:

          $msgid = $ld->compare("cn=Clayton Donley, o=Motorola, c=US", \
          		$type,$value);

compare_s DN ATTR VALUE
          Synchronous method for comparing a value with the value contained
          within DN.  Returns an LDAP STATUS.

          Example:

          $status = $ld->compare_s("cn=Clayton Donley, o=Motorola, c=US", \
          		$type, $value);

count_entries
          Calculates and returns the number of entries in an LDAP result chain.

          Example:

          $number = $ld->count_entries;

delete DN
          Asynchronous method to delete DN.  Returns a MSGID or -1 if error.

          Example:

          $msgid = $ld->delete("cn=Clayton Donley, o=Motorola, c=US");

delete_s DN
          Synchronous method to delete DN.  Returns an LDAP STATUS.

          Example:

          $status = $ld->delete_s("cn=Clayton Donley, o=Motorola, c=US");

dn2ufn DN
          Converts a Distinguished Name (DN) to a User Friendly Name (UFN).
          Returns a string with the UFN.

          Since this operation doesn't require an LDAP object to work, you
          could technically access the function directly as 'ldap_dn2ufn' rather
          that the object oriented form.

          Example:

          $ufn = $ld->dn2ufn("cn=Clayton Donley, o=Motorola, c=US");

explode_dn DN NOTYPES
          Splits the DN into an array comtaining the separate components of
          the DN.  Returns an Array.  NOTYPES is a 1 to remove attribute
          types and 0 to retain attribute types.

          Can also be accessed directly as 'ldap_explode_dn' if no session is
          initialized and you don't want the object oriented form.

          Only available when compiled with Netscape SDK.

          Example:

          @components = $ld->explode_dn($dn,0);

explode_rdn RDN NOTYPES
          Same as explode_dn, except that the first argument is a
          Relative Distinguished Name.  NOTYPES is a 1 to remove attribute
          types and 0 to retain attribute types.  Returns an array with
          each component.

          Can also be accessed directly as 'ldap_explode_rdn' if no session is
          initialized and you don't want the object oriented form.

          Only available with Netscape SDK.

          Example:

          @components = $ld->explode_rdn($rdn,0);

first_attribute
          Returns pointer to first attribute name found in the current entry.
          Note that this only returning attribute names (ex: cn, mail, etc...).
          Returns a string with the attribute name.

          Returns an empty string when no attributes are available.

          Example:

          $attr = $ld->first_attribute;

first_entry
          Sets internal pointer to the first entry in a chain of results.  Returns
          an empty string when no entries are available.

          Example:

          $entry = $ld->first_entry;

get_dn
          Returns a string containing the DN for the specified entry or an
          empty string if an error occurs.

          Example:

          $dn = $ld->get_dn;

get_values ATTR
          Obtain a list of all values associated with a given attribute.
          Returns an empty list if none are available.

          Example:

          @values = $ld->get_values("cn");

          This would put all the 'cn' values for $entry into the array @values.

get_values_len ATTR
          Retrieves a set of binary values for the specified attribute.

          Example:

          @values = $ld->get_values_len("jpegphoto");

          This would put all the 'jpegphoto' values for $entry into the array @values.
          These could then be written to a file, or further processed.

is_ldap_url URL
          Checks to see if a specified URL is a valid LDAP Url.  Returns 0 on false
          and 1 on true.

          Example:

          $isurl = $ld->is_ldap_url("ldap://x500.my.org/o=Org,c=US");

msgfree
          Frees the current LDAP result.  Returns the type of message freed.

          Example:

          $type = $ld->msgfree;

modify DN MOD
          Asynchronous method to modify an LDAP entry.  DN is the DN to
          modify and MOD contains a hash-table of attributes and values.  If
          multiple values need to be passed for a specific attribute, a
          reference to an array must be passed.

          Returns the MSGID of the modify operation.

          Example:

          %mods = (
            "telephoneNumber", "",     #remove telephoneNumber
            "sn", "Test",              #set SN to TEST
            "mail", ["me\@abc123.com","me\@second-home.com"],  #set multivalue 'mail'
            "pager", {"a",["1234567"]},  #Add a Pager Value
            "jpegphoto", {"rb",[$jpegphoto]},  # Replace Binary jpegphoto
          );

          $msgid = $ld->modify($entrydn,\%mods);

          The above would remove the telephoneNumber attribute from the entry
          and replace the "sn" attribute with "Test".  The value in the "mail"
          attribute for this entry would be replaced with both addresses
          specified in @mail.  The "jpegphoto" attribute would be replaced with
          the binary data in $jpegphoto.

modify_s DN MOD
          Synchronous version of modify method.  Returns an LDAP STATUS.  See the
          modify method for notes and examples of populating the MOD
          parameter.

          Example:

          $status = $ld->modify_s($entrydn,\%mods);

modrdn2 DN NEWRDN DELETE
          Asynchronous method to change the name of an entry.  DELETE
          is non-zero if you wish to remove the attribute values from the
          old name.  Returns a MSGID.

          Example:

          $msgid = $ld->modrdn2("cn=Clayton Donley, o=Motorola, c=US", \
          		"cn=Clay Donley",0);

modrdn2_s DN NEWRDN DELETE
          Synchronous method to change the name of an entry.  DELETE is
          non-zero if you wish to remove the attribute values from the old
          name.  Returns an LDAP STATUS.

          Example:

          $status = $ld->modrdn2_s("cn=Clayton Donley, o=Motorola, c=US", \
          		"cn=Clay Donley",0);

next_attribute
          Similar to first_attribute, but obtains next attribute.
          Returns a string comtaining the attribute name.  An empty string
          is returned when no further attributes exist.

          Example:

          $attr = $ld->next_attribute;

next_entry
          Moves internal pointer to the next entry in a chain of search results.

          Example:

          $entry = $ld->next_entry;

perror MSG
          If an error occurs while performing an LDAP function, this procedure
          will display it.  You can also use the err and errstring methods to
          manipulate the error number and error string in other ways.

          Note that this function does NOT terminate your program.  You would
          need to do any cleanup work on your own.

          Example:

          $ld->perror("add_s");

result MSGID ALL TIMEOUT
          Retrieves the result of an operation initiated using an asynchronous
          LDAP call.  Returns the type of result returned or -1 if error.

          MSGID is the MSGID returned by the Asynchronous LDAP call.  Set ALL to
          0 to receive entries as they arrive, or non-zero to receive all entries
          before returning.  Set TIMEOUT to the number of seconds to wait for the
          result, or -1 for no timeout.

          Example:

          $type = $ld->result($msgid,0,1);

result2error FREEIT
          Returns the LDAP error code from an LDAP result message.  FREEIT will
          free the memory occupied by the result if set non-zero.

          This routine also updates message returned by err and errstring
          methods.

          Example:

          $lderrno = $ld->result2error(0);

search BASE SCOPE FILTER ATTRS ATTRSONLY
          Begins an asynchronous LDAP search.  Returns a MSGID or -1 if an
          error occurs.  BASE is the base object for the search operation.
          FILTER is a string containing an LDAP search filter.  ATTRS is a
          reference to an array containing the attributes to return.  An
          empty array would return all attributes.  ATTRSONLY set to non-zero
          will only obtain the attribute types without values.

          SCOPE is one of the following:
          		LDAP_SCOPE_BASE
          		LDAP_SCOPE_ONELEVEL
          		LDAP_SCOPE_SUBTREE

          Example:

          @attrs = ("cn","sn");    # Return specific attributes
          @attrs = ();             # Return all Attributes

          $msgid = $ld->search("o=Motorola, c=US",LDAP_SCOPE_SUBTREE, \
          		"(sn=Donley),\@attrs,0);

search_s BASE SCOPE FILTER ATTRS ATTRSONLY
          Performs a synchronous LDAP search.  Returns an LDAP STATUS.  BASE
          is the base object for the search operation.  FILTER is a string
          containing an LDAP search filter.  ATTRS is a reference to an array
          containing the attributes to return.  An empty array would return all
          attributes.  ATTRSONLY set to non-zero will only obtain the attribute
          types without values.

          SCOPE is one of the following:
          		LDAP_SCOPE_BASE
          		LDAP_SCOPE_ONELEVEL
          		LDAP_SCOPE_SUBTREE

          Example:

          @attrs = ("cn","sn");    # Return specific attributes
          @attrs = ();             # Return all attributes

          $status = $ld->search_s("o=Motorola, c=US",LDAP_SCOPE_SUBTREE, \
          		"(sn=Donley)",\@attrs,0);

search_st BASE SCOPE FILTER ATTRS ATTRSONLY TIMEOUT
          Performs a synchronous LDAP search with a TIMEOUT.  See search_s
          for a description of parameters.  Returns an LDAP STATUS.  Results are
          put into RESULTS.  TIMEOUT is a number of seconds to wait before giving
          up, or -1 for no timeout.

          Example:

          $status = $ld->search_st("o=Motorola, c=US",LDAP_SCOPE_SUBTREE, \
          		"(sn=Donley),[],0,3);

unbind
          Unbind LDAP connection with specified SESSION handler.

          Example:

          $ld->unbind;

url_parse URL
          Parses an LDAP URL into separate components.  Returns a HASH reference
          with the following keys, if they exist in the URL:

          host		- LDAP Host
          port		- LDAP Port
          dn    	- LDAP Base DN
          attr		- LDAP Attributes to Return (ARRAY Reference)
          filter	- LDAP Search Filter
          scope		- LDAP Search Scope
          options	- Netscape key specifying LDAP over SSL

          Example:

          $urlref = $ld->url_parse("ldap://ldap.my.org/o=My,c=US");

url_search URL ATTRSONLY
          Perform an asynchronous search using an LDAP URL.  URL is the LDAP
          URL to search on.  ATTRSONLY determines whether we are returning
          the values for each attribute (0) or only returning the attribute
          names (1).  Results are retrieved and parsed identically to a call
          to the search method.

          Returns a non-negative MSGID upon success.

          Example:

          $msgid = $ld->url_search($my_ldap_url,0);

url_search_s URL ATTRSONLY
          Synchronous version of the url_search method.  Results are retrieved
          and parsed identically to a call to the search_s method.

          Returns LDAP_SUCCESS upon success.

          Example:

          $status = $ld->url_search_s($my_ldap_url,0);

url_search_st URL ATTRSONLY TIMEOUT
          Similar to the url_search_s method, except that it allows a timeout
          to be specified.  The timeout is specified as seconds.  A timeout of
          0 specifies an unlimited timeout.  Results are retrieved and parsed
          identically to a call to the search_st method.

          Returns LDAP_SUCCESS upon success.

          Example:

          $status = $ld->url_search_s($my_ldap_url,0,2);

AUTHOR
======

   Clayton Donley, donley@wwa.com http://miso.wwa.com/~donley/

SEE ALSO
========

   perl(1).

Interface to Sun's Network Information Service
**********************************************

NAME
====

   Net::NIS - Interface to Sun's Network Information Service

DESCRIPTION
===========

   The Net::NIS interface comes in two parts.  The first part is the raw
implementation of the NIS API.  The second is the object interface,
described in `Net::NIS::Table' in this node.  This document describes the
NIS API implementation.

   The NIS package implements all functions described in the `ypclnt(3N)'
in this node manual page.

   The following commands have been implemented:

yp_bind($domain)
     Bind the process to a NIS server for the domain $domain.  This
     function is rarely needed.  See `yp_bind(3N)' in this node.

yp_unbind($domain)
     Unbind the process from the specified $domain.  This function is also
     rarely required.  See `yp_unbind(3N)' in this node.

$domain = yp_get_default_domain()
     Return the host's local domain.  (The same as the `domainname' in
     this node program).  See `yp_get_default_domain(3N)' in this node.

($status, $value) = yp_match($domain, $map, $key)
     Return the $value for the given $key in the $map for the domain
     $domain.  The $key must be an exact match for an item in the map
     (*i.e.* yp_match does no partial matching.  The $value is only valid
     if $status is equal to $YP_SUCCESS.

($status, $key, $value) = yp_first($domain, $map)
     Return the first key-value pair from $map in $domain.  As the NIS maps
     are stored in a DBM table, the order of the returned values is not
     obvious.

($status, $key, $value) = yp_next($domain, $map, $key)
     Return the next key-value pair from $map in $domain.  The $key must be
     provided from the previous `yp_first' in this node or `yp_next' in
     this node.  The `yp_first' in this node/`yp_next' in this node method
     is not recommended, as under some circumstances, entries can be
     skipped or returned twice.  `yp_all' in this node is a better
     interface to use.

($status, \%values) = yp_all($domain, $map)
     The `yp_all' in this node call returns an entire map in the %values
     associative array.

($status, $order) = yp_order($domain, $map)
     This function returns the order number for $domain.  Whatever that is.
     It mustn't be very important, since it's not implemented on NIS+
     servers running in "YP-compatibility mode".  I put it in for
     completeness.

($status, $name) = yp_master($domain, $map)
     Returns the machine name of the master server for a map.

$error = yperr_string($status)
     Returns a string representation of the error code passed in $status.

$status = ypprot_err($code)
     Translates a NIS name service protocol error code to a ypclnt layer
     error code.  Only used for the C version of `yp_all' in this node,
     and it is only implemented here for completeness.

ERROR CODES
===========

   The $status variable returned by the above functions can have one of
the following values:

     $Net::NIS::ERR_ACCESS		Access violation
     $Net::NIS::ERR_BADARGS	Args to function are bad
     $Net::NIS::ERR_BADDB		yp data base is bad
     $Net::NIS::ERR_BUSY		Database is busy
     $Net::NIS::ERR_DOMAIN		Can't bind to a server which serves this domain
     $Net::NIS::ERR_KEY		No such key in map
     $Net::NIS::ERR_MAP		No such map in server's domain
     $Net::NIS::ERR_NODOM		Local domain name not set
     $Net::NIS::ERR_PMAP		Can't communicate with portmapper
     $Net::NIS::ERR_NOMORE		No more records in map database
     $Net::NIS::ERR_RESRC		Local resource allocation failure
     $Net::NIS::ERR_RPC		RPC failure
     $Net::NIS::ERR_YPBIND		Can't communicate with ypbind
     $Net::NIS::ERR_YPERR		Internal yp server or client interface error
     $Net::NIS::ERR_YPSERV		Can't communicate with ypserv
     $Net::NIS::ERR_VERS		YP version mismatch

AUTHOR
======

   Copyright (c) 1995 Rik Harris (*rik.harris@fulcrum.com.au*). All rights
reserved.  This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

   The Network Information Service (NIS) was formerly known as Sun Yellow
Pages (YP). The functionality of the two remains the same; only the name
has changed.  The name Yellow Pages is a registered trademark in the
United Kingdom of British Telecommunications plc, and may not be used
without permission.

colnames
--------

   colnames returns the column headings for the NIS+ table.  If called in
an array context, it returns an array containing the column names in the
order in which they appear in the table.  If called in a scalar context,
it returns a reference to a hash with keys being column names, and values
being an integer representing the column's position.

   e.g.

   $table = Net::NISPlus::Table('hosts.org_dir'); $cols = $table->colnames;

   will end up with $cols being:

   $cols->{'cname'} = 0; $cols->{'name'} = 1; $cols->{'addr'} = 2;
$cols->{'comment'} = 3;

   and

   $table = Net::NISPlus::Table('hosts.org_dir');  @cols =
$table->colnames;

   will end up with @cols being:

   @cols = ('cname', 'name', 'addr', 'comment')

   NOTE: as the colnames method behaves differently depending on what
context it is called in, it may not always behave as you expect.  For
example, the following two code fragments are not equivalent:

   my($colnames) = $table->colnames;

   and

   my($colnames); $colnames = $table->colnames;

   The first calls colnames in an array context, and the second in a
scalar context.

add
---

   Add an entry to the table.  Any columns not specified will be set to
null strings.

   $table->add('key1' => 'value1', 'key2' => 'value2');

   or

   $table->add(['key1' => 'key1', 'key2' => 'value2'], 	['key1' => 'key3',
'key2' => 'value4'])

addinfo
-------

   Add an entry to the table, setting the info variable as we go.  Any
columns not specified will be set to null strings.

   $table->addinfo([key1, key2],   ['values' => [ 'value1', 'value2' ],
'access' => access,    'domain' => domain,    'owner' => owner,    'group'
=> group],   [...])

remove
------

   Remove a single entry from the table.  If the key/value pairs match
more that one entry, an error occurs, and no entries are removed.  Use
removem to remove multiple entries with a single command.

   $table->remove({'key1' => 'value1', 'key2' => 'value2'});

   or

   $table->remove("[key1=value1,key2=value2]");

   If you specify the table name in the indexed name form, it will be
removed and replaced with the full name determined when the table object
was created (and accessible with $table->fullName);

removem
-------

   Remove one or more entries from the table. All entries which match the
key/value pairs will be removed. Use remove to remove a single entry.

   $table->removem({'key1' => 'value1', 'key2' => 'value2'});

   or

   $table->removem("[key1=value1,key2=value2]");

   If you specify the table name in the indexed name form, it will be
removed and replaced with the full name determined when the table object
was created (and accessible with $table->fullName);

clear
-----

   Remove all entries from the table

   $table->clear();

modify
------

   Change fields in a table entry.

   $table->modify({'key1' => 'value1', 'key2' => 'value2'}, {'key3' =>
'newvalue3'});

   or

   $table->modify("[key1=value1,key2=value2]", {'key3' => 'newvalue3'});

   If you specify the table name in the indexed name form, it will be
removed and replaced with the full name determined when the table object
was created (and accessible with $table->fullName);

first_entry
-----------

   first_entry retrieves the first entry in the table.  Data is returned
in an array.

   @fields = $table->first_entry();

next_entry
----------

   next_entry successively returns the next entry in the table.
first_entry should be called before next_entry.  Data is returned in an
array.

   @fields = $table->next_entry();

isColname
---------

   returns TRUE if the given argument is a valid column name for the table

   $table->isColname("name");

Object Interface to Sun's Network Information Service
*****************************************************

NAME
====

   Net::NIS::Table - Object Interface to Sun's Network Information Service

DESCRIPTION
===========

   The NIS interface comes in two parts.  The first part is the raw
implementation of the NIS API, described in Net/NIS.  The
second is the object interface.  This document describes the object
interface implementation.

   The Table object represents an individual NIS map.  A NIS map is bound
to a Table object with the new method:

     $obj = Net::NIS::Table->new($map, [ $domain ]);

   For example,

     $hostsmap = Net::NIS::Table->new("hosts.byname");

   This will create a Table object bound to the `hosts.byname' NIS map in
the default NIS domain.  All operations on the $hostsmap object will
relate to the `hosts.byname' map.

   You can also specify a non-default domain:

     $hostsmap = Net::NIS::Table->new("hosts.byname", "my.domain.com.au");

   Once a Table object has been bound to a NIS map, the following methods
are available:

$value = $obj->match($key)
     Returns the value for a given key.  If you only wish to look up one or
     two values, this function is more efficient, as it retrieves the items
     one at a time.  If you wish to retrieve many items (where many is
     dependent on the size of the map, and probably what sort of machine
     you are on), it is better to use the `list' in this node interface,
     which uses just one RPC call to retreive the entire map.

\%data = $obj->list()
     Return a reference to an associative array which contains the entire
     NIS map.  The keys in the %data array correspond to the keys in the
     NIS map.  If any error occurs that prevents the retrieval of the map,
     then the undefined value is returned.  In this case, your program can
     use the status method to determine the cause of the error.

\%data = $obj->search($srchkey)
     Return a reference to an associative array which contains all entries
     that have keys that contain the $srchkey.  If any error occurs that
     prevents the retrieval of the map, then the undefined value is
     returned.  In this case, your program can use the status method to
     determine the cause of the error.

$status = $obj->status()
     Returns the status code for the last operation.  If the last operation
     succeeded, then the status code is 0.  The status codes returned by
     this method are described below in the ERROR CODES section.

$status = $obj->status_string()
     Returns the character representation of the status code for the last
     operation.  If the last operation succeeded, then the status code is
     something like "operation succeeded".  The exact strings returned by
     this function are implementation dependent, and should not be used
     for comparison purposes.  Use the status call, as described above.

ERROR CODES
===========

   The status method described above can return one of the following
values:

     $Net::NIS::ERR_ACCESS		Access violation
     $Net::NIS::ERR_BADARGS	Args to function are bad
     $Net::NIS::ERR_BADDB		yp data base is bad
     $Net::NIS::ERR_BUSY		Database is busy
     $Net::NIS::ERR_DOMAIN		Can't bind to a server which serves this domain
     $Net::NIS::ERR_KEY		No such key in map
     $Net::NIS::ERR_MAP		No such map in server's domain
     $Net::NIS::ERR_NODOM		Local domain name not set
     $Net::NIS::ERR_PMAP		Can't communicate with portmapper
     $Net::NIS::ERR_NOMORE		No more records in map database
     $Net::NIS::ERR_RESRC		Local resource allocation failure
     $Net::NIS::ERR_RPC		RPC failure
     $Net::NIS::ERR_YPBIND		Can't communicate with ypbind
     $Net::NIS::ERR_YPERR		Internal yp server or client interface error
     $Net::NIS::ERR_YPSERV		Can't communicate with ypserv
     $Net::NIS::ERR_VERS		YP version mismatch

AUTHOR
======

   Copyright (c) 1995 Rik Harris (*rik.harris@fulcrum.com.au*). All rights
reserved.  This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

   The Network Information Service (NIS) was formerly known as Sun Yellow
Pages (YP). The functionality of the two remains the same; only the name
has changed.  The name Yellow Pages is a registered trademark in the
United Kingdom of British Telecommunications plc, and may not be used
without permission.

TIEHASH() interface to NIS+ tables
**********************************

NAME
====

   Net::NISplusTied - TIEHASH() interface to NIS+ tables

SYNOPSIS
========

     use Net::NISplusTied;

     tie (%hash, Net::NISplusTied, 'your.table.domain.');

     ### lookups
     $arrayref = $hash {'field=key'};
     $arrayref = $hash {'field1=key1,field2=key2'};
     $arrayref = $hash {{field => $key}};
     $arrayref = $hash {{field1 => $key1, field2 => $key2}};

     $hashref = $hash {'field1=key'} [0];
     $value = $hash {'field1=key'} [0] {field2};

     ### modify value
     $hash {'field1=key'} = {field2 => $newvalue2, field3 => $newvalue3};
     $hash {{field1 => $key}} = {field2 => $newvalue2, field3 => $newvalue3};

     ### delete entry
     delete $hash {'field1=key'};
     delete $hash {{field => $key}};

     ### iterate through table
     # not implemented #

DESCRIPTION
===========

   The *Net::NISplusTied* allows you to treat NIS+ tables as if they were
perl hashes, using tie() semantics.  It has cultural links to Rick Harris
(Rik.Harris@fulcrum.com.au) NISperl module, although the design goals were
different.  All you can do with *Net::NISplusTied* is to manipulate NIS+
tables.  If you need faithful NIS+ API implementation, consider using
NISperl instead.  The assumption was that one would rarely need to create
and delete NIS+ tables and groups from perl, at least not often enough to
be seriously inconvenienced by `system 'nistbladm' ...' etc.

tie()
-----

   The third argument to tie() is the fully qualified name of the table
you wish to tie.  The module disregards NIS_PATH settings.

FETCH()
-------

   Hash lookups should have NIS+ indexes as the keys, with no square
brackets.  The following are shell and perl eqivavlents:

   *shell:*

     nismatch [name=bob,age=33],users.my.domain.

   perl:

     tie (%users, Net::NISplusTied, 'users.my.domain.');
     $results = $users {'name=bob,age=33'};

   The value returned from a lookup is an array ref.  Array elements are
hash refs representing the individual entries.  Hashes are keyed by the
table columns.  The following would print user bob's login shell setting
from the stock passwd.org_dir file:

     tie (%passwd, Net::NISplusTied, 'passwd.org_dir.your.domain.');
     print $passwd {'name=bob'} [0] {shell};

STORE()
-------

   The STORE() method need some explanations.  It takes  scalar as a key
and hash ref as a value. If the result of key lookup returns exactly one
entry, this entry is replaced. If there is none or more than one, entry is
added to the table. It is up to you to ensure that the indexes stay unique,
since the module will not do this.  Consider the following table:

     field1		field2		field3
     ---------------------------------------------
     apple		cat		...
     apple		dog		...
     orange		cat		...

     tie (%table, Net::NISplusTied, ...);

   The following piece of code

     $table {'field1=apple,field2=cat'} = {field3 => 'whatever'};

   will chnage entry [1], but

     $table {'field1=apple'} = {field2 => 'cat', field3 => 'whatever'};

   will add a new entry to the table, since field1=apple is not unique.

DELETE()
--------

     delete $passwd {'name=bob'}

   does what you think it does.  Be careful however, REM_MULTIPLE flag is
set, and running

     delete $passwd {''}

   will remove ALL ENTRIES from the table.

DESTROY()
---------

   `destroy $passwd;' frees up the memory taken by the hash.  You should
not normally need this.

NOTE
====

   Copyright (c) 1998 Ilya Ketris. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

AUTHOR
======

   Ilya Ketris, ilya@gde.to

SEE ALSO
========

   perl(1), perlguts(1), nis(1)

NNTP Client class
*****************

NAME
====

   Net::NNTP - NNTP Client class

SYNOPSIS
========

     use Net::NNTP;

     $nntp = Net::NNTP->new("some.host.name");
     $nntp->quit;

DESCRIPTION
===========

   `Net::NNTP' is a class implementing a simple NNTP client in Perl as
described in RFC977. `Net::NNTP' inherits its communication methods from
`Net::Cmd'

CONSTRUCTOR
===========

new ( [ HOST ] [, OPTIONS ])
     This is the constructor for a new Net::NNTP object. `HOST' is the
     name of the remote host to which a NNTP connection is required. If not
     given two environment variables are checked, first `NNTPSERVER' then
     `NEWSHOST', then `Net::Config' is checked, and if a host is not found
     then news is used.

     OPTIONS are passed in a hash like fashion, using key and value pairs.
     Possible options are:

     Timeout - Maximum time, in seconds, to wait for a response from the
     NNTP server, a value of zero will cause all IO operations to block.
     (default: 120)

     Debug - Enable the printing of debugging information to STDERR

     *Reader* - If the remote server is INN then initially the connection
     will be to nnrpd, by default `Net::NNTP' will issue a `MODE READER'
     command so that the remote server becomes innd. If the `Reader'
     option is given with a value of zero, then this command will not be
     sent and the connection will be left talking to nnrpd.

METHODS
=======

   Unless otherwise stated all methods return either a *true* or false
value, with *true* meaning that the operation was a success. When a method
states that it returns a value, failure will be returned as undef or an
empty list.

article ( [ MSGID|MSGNUM ], [FH] )
     Retrieve the header, a blank line, then the body (text) of the
     specified article.

     If FH is specified then it is expected to be a valid filehandle and
     the result will be printed to it, on sucess a true value will be
     returned. If FH is not specified then the return value, on sucess,
     will be a reference to an array containg the article requested, each
     entry in the array will contain one line of the article.

     If no arguments are passed then the current article in the currently
     selected newsgroup is fetched.

     `MSGNUM' is a numeric id of an article in the current newsgroup, and
     will change the current article pointer.  `MSGID' is the message id of
     an article as shown in that article's header.  It is anticipated that
     the client will obtain the `MSGID' from a list provided by the newnews
     command, from references contained within another article, or from the
     message-id provided in the response to some other commands.

     If there is an error then undef will be returned.

body ( [ MSGID|MSGNUM ], [FH] )
     Like article but only fetches the body of the article.

head ( [ MSGID|MSGNUM ], [FH] )
     Like article but only fetches the headers for the article.

nntpstat ( [ MSGID|MSGNUM ] )
     The nntpstat command is similar to the article command except that no
     text is returned.  When selecting by message number within a group,
     the nntpstat command serves to set the "current article pointer"
     without sending text.

     Using the nntpstat command to select by message-id is valid but of
     questionable value, since a selection by message-id does not alter
     the "current article pointer".

     Returns the message-id of the "current article".

group ( [ GROUP ] )
     Set and/or get the current group. If `GROUP' is not given then
     information is returned on the current group.

     In a scalar context it returns the group name.

     In an array context the return value is a list containing, the number
     of articles in the group, the number of the first article, the number
     of the last article and the group name.

ihave ( MSGID [, MESSAGE ])
     The ihave command informs the server that the client has an article
     whose id is `MSGID'.  If the server desires a copy of that article,
     and `MESSAGE' has been given the it will be sent.

     Returns *true* if the server desires the article and `MESSAGE' was
     successfully sent,if specified.

     If `MESSAGE' is not specified then the message must be sent using the
     datasend and dataend methods from Net/Cmd,

     `MESSAGE' can be either an array of lines or a reference to an array.

last ()
     Set the "current article pointer" to the previous article in the
     current newsgroup.

     Returns the message-id of the article.

date ()
     Returns the date on the remote server. This date will be in a UNIX
     time format (seconds since 1970)

postok ()
     postok will return *true* if the servers initial response indicated
     that it will allow posting.

authinfo ( USER, PASS )
list ()
     Obtain information about all the active newsgroups. The results is a
     reference to a hash where the key is a group name and each value is a
     reference to an array. The elements in this array are:- the first
     article number in the group, the last article number in the group and
     any information flags about the group.

newgroups ( SINCE [, DISTRIBUTIONS ])
     `SINCE' is a time value and `DISTRIBUTIONS' is either a distribution
     pattern or a reference to a list of distribution patterns.  The
     result is the same as list, but the groups return will be limited to
     those created after `SINCE' and, if specified, in one of the
     distribution areas in `DISTRIBUTIONS'.

newnews ( SINCE [, GROUPS [, DISTRIBUTIONS ]])
     `SINCE' is a time value. `GROUPS' is either a group pattern or a
     reference to a list of group patterns. `DISTRIBUTIONS' is either a
     distribution pattern or a reference to a list of distribution
     patterns.

     Returns a reference to a list which contains the message-ids of all
     news posted after `SINCE', that are in a groups which matched
     `GROUPS' and a distribution which matches `DISTRIBUTIONS'.

next ()
     Set the "current article pointer" to the next article in the current
     newsgroup.

     Returns the message-id of the article.

post ( [ MESSAGE ] )
     Post a new article to the news server. If `MESSAGE' is specified and
     posting is allowed then the message will be sent.

     If `MESSAGE' is not specified then the message must be sent using the
     datasend and dataend methods from Net/Cmd,

     `MESSAGE' can be either an array of lines or a reference to an array.

slave ()
     Tell the remote server that I am not a user client, but probably
     another news server.

quit ()
     Quit the remote server and close the socket connection.

Extension methods
-----------------

   These methods use commands that are not part of the RFC977
documentation. Some servers may not support all of them.

newsgroups ( [ PATTERN ] )
     Returns a reference to a hash where the keys are all the group names
     which match PATTERN, or all of the groups if no pattern is specified,
     and each value contains the description text for the group.

distributions ()
     Returns a reference to a hash where the keys are all the possible
     distribution names and the values are the distribution descriptions.

subscriptions ()
     Returns a reference to a list which contains a list of groups which
     are recommended for a new user to subscribe to.

overview_fmt ()
     Returns a reference to an array which contain the names of the fields
     returned by xover.

active_times ()
     Returns a reference to a hash where the keys are the group names and
     each value is a reference to an array containing the time the groups
     was created and an identifier, possibly an Email address, of the
     creator.

active ( [ PATTERN ] )
     Similar to list but only active groups that match the pattern are
     returned.  PATTERN can be a group pattern.

xgtitle ( PATTERN )
     Returns a reference to a hash where the keys are all the group names
     which match PATTERN and each value is the description text for the
     group.

xhdr ( HEADER, MESSAGE-SPEC )
     Obtain the header field `HEADER' for all the messages specified.

     The return value will be a reference to a hash where the keys are the
     message numbers and each value contains the text of the requested
     header for that message.

xover ( MESSAGE-SPEC )
     The return value will be a reference to a hash where the keys are the
     message numbers and each value contains a reference to an array which
     contains the overview fields for that message.

     The names of the fields can be obtained by calling overview_fmt.

xpath ( MESSAGE-ID )
     Returns the path name to the file on the server which contains the
     specified message.

xpat ( HEADER, PATTERN, MESSAGE-SPEC)
     The result is the same as xhdr except the is will be restricted to
     headers where the text of the header matches PATTERN

xrover
     The XROVER command returns reference information for the article(s)
     specified.

     Returns a reference to a HASH where the keys are the message numbers
     and the values are the References: lines from the articles

listgroup ( [ GROUP ] )
     Returns a reference to a list of all the active messages in `GROUP',
     or the current group if `GROUP' is not specified.

reader
     Tell the server that you are a reader and not another server.

     This is required by some servers. For example if you are connecting to
     an INN server and you have transfer permission your connection will
     be connected to the transfer daemon, not the NNTP daemon. Issuing
     this command will cause the transfer daemon to hand over control to
     the NNTP daemon.

     Some servers do not understand this command, but issuing it and
     ignoring the response is harmless.

UNSUPPORTED
===========

   The following NNTP command are unsupported by the package, and there are
no plans to do so.

     AUTHINFO GENERIC
     XTHREAD
     XSEARCH
     XINDEX

DEFINITIONS
===========

MESSAGE-SPEC
     `MESSAGE-SPEC' is either a single message-id, a single message
     number, or a reference to a list of two message numbers.

     If `MESSAGE-SPEC' is a reference to a list of two message numbers and
     the second number in a range is less than or equal to the first then
     the range represents all messages in the group after the first
     message number.

     NOTE For compatibility reasons only with earlier versions of Net::NNTP
     a message spec can be passed as a list of two numbers, this is
     deprecated and a reference to the list should now be passed

PATTERN
     The `NNTP' protocol uses the `WILDMAT' format for patterns.  The
     WILDMAT format was first developed by Rich Salz based on the format
     used in the UNIX "find" command to articulate file names. It was
     developed to provide a uniform mechanism for matching patterns in the
     same manner that the UNIX shell matches filenames.

     Patterns are implicitly anchored at the beginning and end of each
     string when testing for a match.

     There are five pattern matching operations other than a strict
     one-to-one match between the pattern and the source to be checked for
     a match.

     The first is an asterisk * to match any sequence of zero or more
     characters.

     The second is a question mark ? to match any single character. The
     third specifies a specific set of characters.

     The set is specified as a list of characters, or as a range of
     characters where the beginning and end of the range are separated by
     a minus (or dash) character, or as any combination of lists and
     ranges. The dash can also be included in the set as a character it if
     is the beginning or end of the set. This set is enclosed in square
     brackets. The close square bracket ] may be used in a set if it is
     the first character in the set.

     The fourth operation is the same as the logical not of the third
     operation and is specified the same way as the third with the
     addition of a caret character ^ at the beginning of the test string
     just inside the open square bracket.

     The final operation uses the backslash character to invalidate the
     special meaning of the a open square bracket [, the asterisk,
     backslash or the question mark. Two backslashes in sequence will
     result in the evaluation of the backslash as a character with no
     special meaning.

    Examples
    `[^]-]'
          matches any single character other than a close square bracket
          or a minus sign/dash.

          matches any string that ends with the string "bdc" including the
          string "bdc" (without quotes).

    `[0-9a-zA-Z]'
          matches any single printable alphanumeric ASCII character.

    `a??d'
          matches any four character string which begins with a and ends
          with d.

SEE ALSO
========

   See Net/Cmd,

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

COPYRIGHT
=========

   Copyright (c) 1995-1997 Graham Barr. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

parse, manipulate and lookup IP network blocks
**********************************************

NAME
====

   Net::Netmask - parse, manipulate and lookup IP network blocks

SYNOPSIS
========

     use Net::Netmask;

     $block = new Net::Netmask (network block)
     $block = new Net::Netmask (network block, netmask)

     print $block->desc() 		# a.b.c.d/bits
     print $block->base()
     print $block->mask()
     print $block->hostmask()
     print $block->bits()
     print $block->size()
     print $block->maxblock()
     print $block->broadcast()
     print $block->next()
     print $block->match($ip);
     print $block->nth(1);

     for $ip ($block->enumerate()) { }

     for $zone ($block->inaddr()) { }

     my $table = {};
     $block->storeNetblock()
     $block->storeNetblock($table)

     $block = findNetblock(ip)
     $block = findNetblock(ip, $table)

DESCRIPTION
===========

   Net::Netblock parses and understand IPv4 CIDR blocks.  It's built with
an object-oriented interface.  Nearly all functions are methods that
operate on a Net::Netblock object.

   There are methods that provide the nearly all bits of information about
a network block that you might want.

CONSTRUCTING
============

   Net::Netmask objects are created with an IP address and optionally a
mask.  There are many forms that are recognized:

'140.174.82.0/24'
     The preferred form.

'140.174.82.0:255.255.255.0'

'140.174.82.0', '255.255.255.0'

'140.174.82.0', '0xffffff00'

'140.174.82.4'
     A /32 block.

'140.174.82'
     Always a /24 block.

'140.174'
     Always a /16 block.

'140'
     Always a /8 block.

'140.174.82/24'

'140.174/16'
'default'
     0.0.0.0/0 (the default route)

METHODS
=======

base()
     Returns base address of the network block as a string.  Eg:
     140.174.82.0.  Base does not give an indication of the size of the
     network block.

mask()
     Returns the netmask as a string. Eg: 255.255.255.0.

*hostmask*()
     Returns the host mask which is the oposite of the netmask.  Eg:
     0.0.0.255.

bits()
     Returns the netmask as a number of bits in the network portion of the
     address for this block.  Eg: 24.

size()
     Returns the number of IP addresses in a block.  Eg: 256.

*broadcast*()
     The blocks broadcast address. (The last IP address inside the block.)
     Eg: 192.168.1.0/24 => 192.168.1.255

next()
     The first IP address following the block. (The IP address following
     the broadcase address.) Eg: 192.168.1.0/24 => 192.168.2.0

match($ip)
     Returns a true if the IP number $ip matches the given network. That
     is, a true value is returned if $ip is between base() amd broadcast().
     For example, if we have the network 192.168.1.0/24, then

          192.168.0.255 => 0
          192.168.1.0   => "0 "
          192.168.1.1   => 1
          ...
          192.168.1.255 => 255

     $ip should be a dotted-quad (eg: "192.168.66.3")

     It just happens that the return value is the position within the
     block.  Since zero is a legal position, the true string "0 " is
     returned in it's place.  "0 " is numerically zero though.  When
     wanting to know the position inside the block, a good idiom is:

          $pos = $block->match($ip) || die;
          $pos += 0;

*maxblock*()
     Much of the time, it is not possible to determine the size of a
     network block just from it's base address.  For example, with the
     network block '140.174.82.0/27', if you only had the '140.174.82.0'
     portion you wouldn't be able to tell for certain the size of the
     block.  '140.174.82.0' could be anything from a '/23' to a '/32'.
     The *maxblock*() method gives the size of the larges block that the
     current block's address would allow it to be.  The size is given in
     bits.  Eg: 23.

*enumerate*()
     Returns a list of all the IP addresses in the block.  Be very careful
     not to use this function of large blocks.  The IP addresses are
     returned as strings.  Eg: '140.174.82.0', '140.174.82.1', ...
     '140.174.82.255'.

*nth*($index)
     Returns the nth element of the array that *enumerate* would return if
     it were called.  So, to get the first usable address in a block, use
     *nth*(1).  To get the broadcast address, use *nth*(-1).  To get the
     last usable adress, use *nth*(-2).

*inaddr*()
     Returns an inline list of tuples.  There is a tuple for each DNS zone
     name in the block.  If the block is smaller than a /24, then the zone
     of the enclosing /24 is returned.

     Each tuple contains: the DNS zone name, the last component of the
     first IP address in the block in that zone, the last component of the
     last IP address in the block in that zone.

     Examples: the list returned for the block '140.174.82.0/23' would be:
     '82.174.140.in-addr.arpa', 0, 255, '83.174.140.in-addr.arpa', 0, 255.
     The list returned for the block '140.174.82.64/27' would be:
     '82.174.140.in-addr.arpa', 64, 95.

*storeNetblock*([$t])
     Adds the current block to an table of network blocks.  The table can
     be used to query which network block a given IP address is in.

     The optional argument allows there to be more than one table.  By
     default, an internal table is used.   If more than one table is
     needed, then supply a reference to a HASH to store the data in.

FUNCTIONS
=========

*findNetblock*(ip, [$t])
     Search the table of network blocks (created with *storeNetBlock*) to
     find if any of them contain the given IP address.  The IP address is
     expected to be a string.

     The return value is either a Net::Netblock object or undef.

COPYRIGHT
=========

   Copyright (C) 1998, David Muir Sharnoff.   All rights reserved.
License hearby granted for anyone to use this module at their own risk.
Please feed useful changes back to muir@idiom.com.

OO interface to users netrc file
********************************

NAME
====

   Net::Netrc - OO interface to users netrc file

SYNOPSIS
========

     use Net::Netrc;

     $mach = Net::Netrc->lookup('some.machine');
     $login = $mach->login;
     ($login, $password, $account) = $mach->lpa;

DESCRIPTION
===========

   `Net::Netrc' is a class implementing a simple interface to the .netrc
file used as by the ftp program.

   `Net::Netrc' also implements security checks just like the ftp program,
these checks are, first that the .netrc file must be owned by the user and
second the ownership permissions should be such that only the owner has
read and write access. If these conditions are not met then a warning is
output and the .netrc file is not read.

THE .netrc FILE
===============

   The .netrc file contains login and initialization information used by
the auto-login process.  It resides in the user's home directory.  The
following tokens are recognized; they may be separated by spaces, tabs, or
new-lines:

machine name
     Identify a remote machine name. The auto-login process searches the
     .netrc file for a machine token that matches the remote machine
     specified.  Once a match is made, the subsequent .netrc tokens are
     processed, stopping when the end of file is reached or an- other
     machine or a default token is encountered.

default
     This is the same as machine name except that default matches any
     name.  There can be only one default token, and it must be after all
     machine tokens.  This is normally used as:

          default login anonymous password user@site

     thereby giving the user automatic anonymous login to machines not
     specified in .netrc.

login name
     Identify a user on the remote machine.  If this token is present, the
     auto-login process will initiate a login using the specified name.

password string
     Supply a password.  If this token is present, the auto-login process
     will supply the specified string if the remote server requires a
     password as part of the login process.

account string
     Supply an additional account password.  If this token is present, the
     auto-login process will supply the specified string if the remote
     server requires an additional account password.

macdef name
     Define a macro. `Net::Netrc' only parses this field to be compatible
     with ftp.

CONSTRUCTOR
===========

   The constructor for a `Net::Netrc' object is not called new as it does
not really create a new object. But instead is called lookup as this is
essentially what it does.

lookup ( MACHINE [, LOGIN ])
     Lookup and return a reference to the entry for MACHINE. If LOGIN is
     given then the entry returned will have the given login. If LOGIN is
     not given then the first entry in the .netrc file for MACHINE will be
     returned.

     If a matching entry cannot be found, and a default entry exists, then
     a reference to the default entry is returned.

METHODS
=======

login ()
     Return the login id for the netrc entry

password ()
     Return the password for the netrc entry

account ()
     Return the account information for the netrc entry

lpa ()
     Return a list of login, password and account information fir the
     netrc entry

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

SEE ALSO
========

   See Net/Netrc, Net/Cmd,

COPYRIGHT
=========

   Copyright (c) 1995-1998 Graham Barr. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

CCSO Nameserver Client class
****************************

NAME
====

   Net::PH - CCSO Nameserver Client class

SYNOPSIS
========

     use Net::PH;

     $ph = Net::PH->new("some.host.name",
                        Port    => 105,
                        Timeout => 120,
                        Debug   => 0);

     if($ph) {
         $q = $ph->query({ field1 => "value1" },
                         [qw(name address pobox)]);

         if($q) {
         }
     }

     # Alternative syntax

     if($ph) {
         $q = $ph->query('field1=value1',
                         'name address pobox');

         if($q) {
         }
     }

DESCRIPTION
===========

   `Net::PH' is a class implementing a simple Nameserver/PH client in Perl
as described in the CCSO Nameserver - Server-Client Protocol. Like other
modules in the Net:: family the `Net::PH' object inherits methods from
`Net::Cmd'.

CONSTRUCTOR
===========

new ( [ HOST ] [, OPTIONS ])
          $ph = Net::PH->new("some.host.name",
                             Port    => 105,
                             Timeout => 120,
                             Debug   => 0
                            );

     This is the constructor for a new Net::PH object. `HOST' is the name
     of the remote host to which a PH connection is required.

     If `HOST' is not given, then the `SNPP_Host' specified in
     `Net::Config' will be used.

     OPTIONS is an optional list of named options which are passed in a
     hash like fashion, using key and value pairs. Possible options are:-

     Port - Port number to connect to on remote host.

     Timeout - Maximum time, in seconds, to wait for a response from the
     Nameserver, a value of zero will cause all IO operations to block.
     (default: 120)

     Debug - Enable the printing of debugging information to STDERR

METHODS
=======

   Unless otherwise stated all methods return either a *true* or false
value, with *true* meaning that the operation was a success. When a method
states that it returns a value, failure will be returned as undef or an
empty list.

query( SEARCH [, RETURN ] )
          $q = $ph->query({ name => $myname },
          		    [qw(name email schedule)]);

          foreach $handle (@{$q}) {
          	foreach $field (keys %{$handle}) {
                  $c = ${$handle}{$field}->code;
                  $v = ${$handle}{$field}->value;
                  $f = ${$handle}{$field}->field;
                  $t = ${$handle}{$field}->text;
                  print "field:[$field] [$c][$v][$f][$t]\n" ;
          	}
          }

     Search the database and return fields from all matching entries.

     The SEARCH argument is a reference to a HASH which contains
     field/value pairs which will be passed to the Nameserver as the
     search criteria.

     RETURN is optional, but if given it should be a reference to a list
     which contains field names to be returned.

     The alternative syntax is to pass strings instead of references, for
     example

          $q = $ph->query('name=myname',
          		    'name email schedule');

     The SEARCH argument is a string that is passed to the Nameserver as
     the search criteria. The strings being passed should not contain any
     carriage returns, or else the query command might fail or return
     invalid data.

     RETURN is optional, but if given it should be a string which will
     contain field names to be returned.

     Each match from the server will be returned as a HASH where the keys
     are the field names and the values are `Net::PH:Result' objects
     (code, value, field, text).

     Returns a reference to an ARRAY which contains references to HASHs,
     one per match from the server.

change( SEARCH , MAKE )
          $r = $ph->change({ email => "*.domain.name" },
                           { schedule => "busy");

     Change field values for matching entries.

     The SEARCH argument is a reference to a HASH which contains
     field/value pairs which will be passed to the Nameserver as the
     search criteria.

     The MAKE argument is a reference to a HASH which contains field/value
     pairs which will be passed to the Nameserver that will set new values
     to designated fields.

     The alternative syntax is to pass strings instead of references, for
     example

          $r = $ph->change('email="*.domain.name"',
                           'schedule="busy"');

     The SEARCH argument is a string to be passed to the Nameserver as the
     search criteria. The strings being passed should not contain any
     carriage returns, or else the query command might fail or return
     invalid data.

     The MAKE argument is a string to be passed to the Nameserver that
     will set new values to designated fields.

     Upon success all entries that match the search criteria will have the
     field values, given in the Make argument, changed.

login( USER, PASS [, ENCRYPT ])
          $r = $ph->login('username','password',1);

     Enter login mode using USER and PASS. If `ENCRYPT' is given and is
     *true* then the password will be used to encrypt a challenge text
     string provided by the server, and the encrypted string will be sent
     back to the server. If `ENCRYPT' is not given, or false then the
     password will be sent in clear text (*this is not recommended*)

logout()
          $r = $ph->logout();

     Exit login mode and return to anonymous mode.

fields( [ FIELD_LIST ] )
          $fields = $ph->fields();
          foreach $field (keys %{$fields}) {
              $c = ${$fields}{$field}->code;
              $v = ${$fields}{$field}->value;
              $f = ${$fields}{$field}->field;
              $t = ${$fields}{$field}->text;
              print "field:[$field] [$c][$v][$f][$t]\n";
          }

     In a scalar context, returns a reference to a HASH. The keys of the
     HASH are the field names and the values are `Net::PH:Result' objects
     (code, value, field, text).

     In an array context, returns a two element array. The first element
     is a reference to a HASH as above, the second element is a reference
     to an array which contains the tag names in the order that they were
     returned from the server.

     `FIELD_LIST' is a string that lists the fields for which info will be
     returned.

add( FIELD_VALUES )
          $r = $ph->add( { name => $name, phone => $phone });

     This method is used to add new entries to the Nameserver database. You
     must successfully call `login' in this node before this method can be
     used.

     Note that this method adds new entries to the database. To modify an
     existing entry use `change' in this node.

     `FIELD_VALUES' is a reference to a HASH which contains field/value
     pairs which will be passed to the Nameserver and will be used to
     initialize the new entry.

     The alternative syntax is to pass a string instead of a reference,
     for example

          $r = $ph->add('name=myname phone=myphone');

     `FIELD_VALUES' is a string that consists of field/value pairs which
     the new entry will contain. The strings being passed should not
     contain any carriage returns, or else the query command might fail or
     return invalid data.

delete( FIELD_VALUES )
          $r = $ph->delete('name=myname phone=myphone');

     This method is used to delete existing entries from the Nameserver
     database.  You must successfully call `login' in this node before
     this method can be used.

     Note that this method deletes entries to the database. To modify an
     existing entry use `change' in this node.

     `FIELD_VALUES' is a string that serves as the search criteria for the
     records to be deleted. Any entry in the database which matches this
     search criteria will be deleted.

id( [ ID ] )
          $r = $ph->id('709');

     Sends ID to the Nameserver, which will enter this into its logs. If
     ID is not given then the UID of the user running the process will be
     sent.

status()
     Returns the current status of the Nameserver.

siteinfo()
          $siteinfo = $ph->siteinfo();
          foreach $field (keys %{$siteinfo}) {
              $c = ${$siteinfo}{$field}->code;
              $v = ${$siteinfo}{$field}->value;
              $f = ${$siteinfo}{$field}->field;
              $t = ${$siteinfo}{$field}->text;
              print "field:[$field] [$c][$v][$f][$t]\n";
          }

     Returns a reference to a HASH containing information about the
     server's site. The keys of the HASH are the field names and values are
     `Net::PH:Result' objects (code, value, field, text).

quit()
          $r = $ph->quit();

     Quit the connection

Q&A
===

   How do I get the values of a Net::PH::Result object?

     foreach $handle (@{$q}) {
         foreach $field (keys %{$handle}) {
             $my_code  = ${$q}{$field}->code;
             $my_value = ${$q}{$field}->value;
             $my_field = ${$q}{$field}->field;
             $my_text  = ${$q}{$field}->text;
         }
     }

   How do I get a count of the returned matches to my query?

     $my_count = scalar(@{$query_result});

   How do I get the status code and message of the last `$ph' command?

     $status_code    = $ph->code;
     $status_message = $ph->message;

SEE ALSO
========

   See Net/Cmd,

AUTHORS
=======

   Graham Barr <gbarr@pobox.com> Alex Hristov <hristov@slb.com>

ACKNOWLEDGMENTS
===============

   Password encryption code ported to perl by Broc Seib <bseib@purdue.edu>,
Purdue University Computing Center.

   Otis Gospodnetic <otisg@panther.middlebury.edu> suggested passing
parameters as string constants. Some queries cannot be executed when
passing parameters as string references.

     Example: query first_name last_name email="*.domain"

COPYRIGHT
=========

   The encryption code is based upon cryptit.c, Copyright (C) 1988 by
Steven Dorner, and Paul Pomes, and the University of Illinois Board of
Trustees, and by CSNET.

   All other code is Copyright (c) 1996-1997 Graham Barr <gbarr@pobox.com>
and Alex Hristov <hristov@slb.com>. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Post Office Protocol 3 Client class (RFC1081)
*********************************************

NAME
====

   Net::POP3 - Post Office Protocol 3 Client class (RFC1081)

SYNOPSIS
========

     use Net::POP3;

     # Constructors
     $pop = Net::POP3->new('pop3host');
     $pop = Net::POP3->new('pop3host', Timeout => 60);

DESCRIPTION
===========

   This module implements a client interface to the POP3 protocol, enabling
a perl5 application to talk to POP3 servers. This documentation assumes
that you are familiar with the POP3 protocol described in RFC1081.

   A new Net::POP3 object must be created with the new method. Once this
has been done, all POP3 commands are accessed via method calls on the
object.

EXAMPLES
========

     Need some small examples in here :-)

CONSTRUCTOR
===========

new ( [ HOST, ] [ OPTIONS ] )
     This is the constructor for a new Net::POP3 object. `HOST' is the
     name of the remote host to which a POP3 connection is required.

     If `HOST' is not given, then the `POP3_Host' specified in
     `Net::Config' will be used.

     OPTIONS are passed in a hash like fashion, using key and value pairs.
     Possible options are:

     *ResvPort* - If given then the socket for the `Net::POP3' object will
     be bound to the local port given using bind when the socket is
     created.

     Timeout - Maximum time, in seconds, to wait for a response from the
     POP3 server (default: 120)

     Debug - Enable debugging information

METHODS
=======

   Unless otherwise stated all methods return either a *true* or false
value, with *true* meaning that the operation was a success. When a method
states that it returns a value, failure will be returned as undef or an
empty list.

user ( USER )
     Send the USER command.

pass ( PASS )
     Send the PASS command. Returns the number of messages in the mailbox.

login ( [ USER [, PASS ]] )
     Send both the the USER and PASS commands. If PASS is not given the
     `Net::POP3' uses `Net::Netrc' to lookup the password using the host
     and username. If the username is not specified then the current user
     name will be used.

     Returns the number of messages in the mailbox. However if there are no
     messages on the server the string `"0E0"' will be returned. This is
     will give a true value in a boolean context, but zero in a numeric
     context.

     If there was an error authenticating the user then undef will be
     returned.

apop ( USER, PASS )
     Authenticate with the server identifying as USER with password PASS.
     Similar ti `login' in this node, but the password is not sent in
     clear text.

     To use this method you must have the MD5 package installed, if you do
     not this method will return undef

top ( MSGNUM [, NUMLINES ] )
     Get the header and the first `NUMLINES' of the body for the message
     `MSGNUM'. Returns a reference to an array which contains the lines of
     text read from the server.

list ( [ MSGNUM ] )
     If called with an argument the list returns the size of the message
     in octets.

     If called without arguments a reference to a hash is returned. The
     keys will be the `MSGNUM''s of all undeleted messages and the values
     will be their size in octets.

get ( MSGNUM [, FH ] )
     Get the message `MSGNUM' from the remote mailbox. If FH is not given
     then get returns a reference to an array which contains the lines of
     text read from the server. If FH is given then the lines returned
     from the server are printed to the filehandle FH.

last ()
     Returns the highest `MSGNUM' of all the messages accessed.

popstat ()
     Returns a list of two elements. These are the number of undeleted
     elements and the size of the mbox in octets.

ping ( USER )
     Returns a list of two elements. These are the number of new messages
     and the total number of messages for USER.

uidl ( [ MSGNUM ] )
     Returns a unique identifier for `MSGNUM' if given. If `MSGNUM' is not
     given uidl returns a reference to a hash where the keys are the
     message numbers and the values are the unique identifiers.

delete ( MSGNUM )
     Mark message `MSGNUM' to be deleted from the remote mailbox. All
     messages that are marked to be deleted will be removed from the
     remote mailbox when the server connection closed.

reset ()
     Reset the status of the remote POP3 server. This includes reseting the
     status of all messages to not be deleted.

quit ()
     Quit and close the connection to the remote POP3 server. Any messages
     marked as deleted will be deleted from the remote mailbox.

NOTES
=====

   If a `Net::POP3' object goes out of scope before quit method is called
then the reset method will called before the connection is closed. This
means that any messages marked to be deleted will not be.

SEE ALSO
========

   See Net/Netrc, Net/Cmd,

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

COPYRIGHT
=========

   Copyright (c) 1995-1997 Graham Barr. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Send Numeric/AlphaNumeric Pages to any pager/phone around  the world through the SimpleWire network.
****************************************************************************************************

NAME
====

   Net::Pager - Send Numeric/AlphaNumeric Pages to any pager/phone around
the world through the SimpleWire network.

SYNOPSIS
========

   NOTE!: Version 2.00 is not compatible with Net::Pager 1.12.  All
client/server communication has been redesigned with XML in mind.  Thus,
this module had to dramatically change and so did the interface.  I
apologize for this, but the change has boosted performance 200-300% with
the addition of asynchronous paging and the many other enhancements.

   `use Net::Pager;'

   See all the documenation and example code in both this installation
package and on the www.simplewire.com website.  The sendpage.pl,
checkstatus.pl, and the servicelist.pl show great example code for every
feature supported in v2.00.  These are located on both the
www.simplewire.com website and in the /eg directory with the
Net-Pager-2.00.tar.gz file.

DESCRIPTION
===========

   Net::Pager is a global numeric and alphanumeric paging interface via the
Internet. It is the first and only way to interface any brand or type of
pager through one consistent protocol without using the telephone network.
SimpleWire has defined a XML paging standard so paging technology can be
better utilized.

   The module interacts with SimleWire's Remote Procedure Calls. This new
standard, and subsequently this Perl module, has a great deal of
development energy behind it.

   For futher support or questions, you should visit s website at
*www.simplewire.com* where you can visit our developer support forum, faq,
or download the most recent documentation.  SimpleWire's site has more
example code.

NEW FEATURES IN 2.00
====================

     * The module was totally re-written since XML has been introduced
       as the language for all client/server communication between this
       client tool and the SimpleWire network.
     * Support for asynchronous sending of pages has been added.  This
       means that network delays are now handled by the SimpleWire servers
       rather than the client tools. This has eliminated any timeout
       bugs that might occur, since SimpleWire can now respond immediately.
     * Object oriented design following the HTTP::Response and
       HTTP::Request methodology.  Clients now construct Net::Pager::Request
       objects, submit various requests through this object, and use
       the Net::Pager::Response object to analyze the response from the
       SimpleWire servers.  This resulted in three more objects:
       Net::Pager::Common, Net::Pager::Request, and Net::Pager::Response.
     * SimpleWire now captures more error messages from each paging service.
       A good example is the attempt to send pages to Sprint PCS phones
       even though text messaging costs extra and most users don't have
       it.  SimpleWire now catches this kind of error.
     * Added new services: Verizon, VoiceStream/OmniPoint
       Bell Mobility, and Weblink Wireless Two-Way.
     	* Introduction of a ticket system where a TICKET ID is assigned
       to every sendpage transaction.  This allows clients to check on
       the status of pages sent asynchronously or to check up on older
       pages sent through our system.
     * Added support for sending a page to a simplewire alias.  This
       means clients can now send pages to an alias instead of a pin
       and service id, provided that the alias is setup and registered
       on the SimpleWire network.
     * Fixed small issue with clients entering pins that contain a dash
     	  or a period.  Our servers will now filter out this garbage to
       ensure proper formatting of the pin.
     * Added support for Subscriber IDs and Subscriber passwords.
     * Added an optional delimiter parameter to be passed along with a page
       so that client tools can override our default delimiter to
       seperate the from, callback, and text fields in messages.
     * Fixed timeout bugs by using LWP::UserAgent instead of our own
       networking code.
     * SimpleWire can now support proxy servers via the LWP::UserAgent
       module.  However, this will take custom tweaking of our
     	  Net::Pager moduele until native support is added.
     * Revised the system for remotely retrieving our service list.  Many new
       options have been added so that the list comes back sorted or
       filtered in whatever way you like.
     * Improved functions to use with the service list.  New functions
       include DBI-like interface for retrieval and looping.  Such
       functions are fetchrow_service, fetchall_services, and fetchrow_rewind.
     * Fixed small bug that was related to timeouts where 2 or 3 duplicated
       pages would be sent off.  This was solved via LWP and smarter
       error checking before moving onto the next simplewire server.

AUTHOR
======

   Joe Lauer <joelauer@rootlevel.com>

COPYRIGHT
=========

   Copyright (c) 2000 Rootlevel. All rights reserved. This program is free
software; you can redistribute it and/or modify it under the same terms as
Perl itself.

Patricia Trie perl module for fast IP address lookups
*****************************************************

NAME
====

   Net::Patricia - Patricia Trie perl module for fast IP address lookups

SYNOPSIS
========

     use Net::Patricia;

     my $pt = new Net::Patricia;

     $pt->add_string('127.0.0.0/8', \$user_data);
     $pt->match_string('127.0.0.1');
     $pt->match_exact_string('127.0.0.0');
     $pt->match_integer(2130706433); # 127.0.0.1
     $pt->match_exact_integer(2130706432, 8); # 127.0.0.0
     $pt->remove_string('127.0.0.0/8');
     $pt->climb(sub { print "climbing at node $_[0]\n" });

     undef $pt; # automatically destroys the Patricia Trie

DESCRIPTION
===========

   This module uses a Patricia Trie data structure to quickly perform IP
address prefix matching for applications such as IP subnet, network or
routing table lookups.  The data structure is based on a radix tree using
a radix of two, so sometimes you see patricia implementations called
"radix" as well.  The term "Trie" is derived from the word "retrieval" but
is pronounced like "try".  Patricia stands for "Practical Algorithm to
Retrieve Information Coded as Alphanumeric", and was first suggested for
routing table lookups by Van Jacobsen.  Patricia Trie performance
characteristics are well-known as it has been employed for routing table
lookups within the BSD kernel since the 4.3 Reno release.

   The BSD radix code is thoroughly described in "TCP/IP Illustrated,
Volume 2" by Wright and Stevens and in the paper "A Tree-Based Packet
Routing Table for Berkeley Unix" by Keith Sklower.

METHODS
=======

new - create a new Net::Patricia object
          $pt = new Net::Patricia;

     This is the class' constructor - it returns a `Net::Patricia' object
     upon success or undef on failure.  For now, the constructor takes no
     arguments, and defaults to creating a tree which uses AF_INET IPv4
     address and mask values as keys.  In the future it will probably take
     one argument such as AF_INET or AF_INET6 to specify whether or not you
     are use 32-bit IP addresses as keys or 128-bit IPv6 addresses.

     The `Net::Patricia' object will be destroyed automatically when there
     are no longer any references to it.

add_string
          $pt->add_string(key_string[,user_data]);

     The first argument, key_string, is a network or subnet specification
     in canonical form, e.g. "10.0.0.0/8", where the number after the slash
     represents the number of bits in the netmask.  If no mask width is
     specified, the longest possible mask is assumed, i.e. 32 bits for
     AF_INET addresses.

     The second argument, user_data, is optional.  If supplied, it should
     be a SCALAR value (which may be a perl reference) specifying the user
     data that will be stored in the Patricia Trie node.  Subsequently,
     this value will be returned by the match methods described below to
     indicate a successful search.  Remember that perl references and
     objects are represented as SCALAR values and therefore the user data
     can be complicated data objects.

     If no second argument is passed, the key_string will be stored as the
     user data and therfore will likewise be returned by the match
     functions.

     On success, this method returns the user_data passed as the second
     argument or key_string if no user data was specified.  It returns
     undef on failure.

match_string
          $pt->match_string(key_string);

     This method searches the Patricia Trie to find a matching node,
     according to normal subnetting rules for the address and mask
     specified.

     The key_string argument is a network or subnet specification in
     canonical form, e.g. "10.0.0.0/8", where the number after the slash
     represents the number of bits in the netmask.  If no mask width value
     is specified, the longest mask is assumed, i.e. 32 bits for AF_INET
     addresses.

     If a matching node is found in the Patricia Trie, this method returns
     the user data for the node.  This method returns undef on failure.

match_exact_string
          $pt->match_exact_string(key_string);

     This method searches the Patricia Trie to find a matching node.  Its
     semantics are exactly the same as those described for match_string
     except that the key must match a node exactly.  I.e. it is not
     sufficient that the address and mask specified merely falls within the
     subnet specified by a particular node.

match_integer
          $pt->match_integer(integer[,mask_bits]);

     This method searches the Patricia Trie to find a matching node,
     according to normal subnetting rules for the address and mask
     specified.  Its semantics are similar to those described for
     match_string except that the key is specified using an integer (i.e.
     SCALAR), such as that returned by perl's unpack function for values
     converted using the "N" (network-ordered long).  Note that this
     argument is not a packed network-ordered long.

     Just to be completely clear, the integer argument should be a value of
     the sort produced by this code:

          use Socket;
          $integer = unpack("N", inet_aton("10.0.0.0"));

match_exact_integer
          $pt->match_exact_integer(integer[,mask_bits]);

     This method searches the Patricia Trie to find a matching node.  Its
     semantics are exactly the same as match_integer except that the key
     must match a node exactly.  I.e. it is not sufficient that the address
     and mask specified merely falls within the subnet specified by a
     particular node.

remove_string
          $pt->remove_string(key_string);

     This method removes the node which exactly matches the the address and
     mask specified from the Patricia Trie.

     If the matching node is found in the Patricia Trie, it is removed, and
     this method returns the user data for the node.  This method returns
     undef on failure.

climb
          $pt->climb([CODEREF]);

     This method climbs the Patricia Trie, visiting each node as it does
     so.

     The CODEREF argument is optional.  It is a perl code reference used to
     specify a user-defined subroutine to be called when visiting each
     node.  The node's user data will be passed as the sole argument to
     that subroutine.

     This method returns the number of nodes successfully visited while
     climbing the Trie.  That is, without a CODEREF argument, it simply
     counts the number of nodes in the Patricia Trie.

     Note that currently the return value from your CODEREF subroutine is
     ignored.  In the future the climb method may return the number of
     times your subroutine returned non-zero, as it is called once per
     node.  So, if you are currently relying on the climb return value to
     accurately report a count of the number of nodes in the Patricia
     Trie, it would be prudent to have your subroutine return a non-zero
     value.

     This method is called climb() rather than walk() because climbing
     trees (and therfore tries) is a more popular pass-time than walking
     them.

BUGS
====

   I've only had the opportunity to test this code on GNU/Linux and
Solaris.  [Why is it that I have fewer platforms available to me in
academia than I used to have in the private industry?  Ugh.]  As such I am
somewhat concerned about the portability of the C code on which this
module is based and whether or not the resulting objects will link on
other platforms.  Please send me reports, preferably including fixes for
my Makefile.PL files and such.

   This is the first XSUB perl extension that I have written.  Consider
yourself warned! ;^)  I'm particularly concerned as to whether or not my
XS code is correct and whether or not this code leaks memory.  I've made
an effort to avoid leaks in my use of the C patricialib API and in my
manipulation of perl xVs, but am not sure if I have been successful in
either case.  If leaks are discovered please report them to me as they are
surely my fault and not that of the authors of the code on which this
module is based.

   Methods to add or remove nodes using integer arguments are yet to be
implemented.  This was a lower priority since it is less necessary to
avoid the overhead involved in translation from a string representation
since add and remove operations are usually performed less frequently than
matching operations.

   This modules does not yet support AF_INET6 (IP version 6) 128 bit
addresses, although the underlying patricialib C code does.

   When passing a CODEREF argument to the climb method, the return value
from your CODEREF subroutine is currently ignored.  In the future the
climb method may return the number of times your subroutine returned
non-zero, as it is called once per node.  So, if you are currently relying
on the climb return value to accurately report a count of the number of
nodes in the Patricia Trie, it would be prudent to have your subroutine
return a non-zero value.

AUTHOR
======

   Dave Plonka <plonka@doit.wisc.edu>

   Copyright (C) 2000  Dave Plonka.  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 product includes software developed by the University of Michigan,
Merit Network, Inc., and their contributors.  See the copyright file in
the patricialib sub-directory of the distribution for details.

   patricialib, the C library used by this perl extension, is an extracted
version of MRT's patricia code from radix.[ch], which was worked on by
Masaki Hirabaru and Craig Labovitz.  For more info on MRT see:

     http://www.mrtd.net/

   The MRT patricia code owes some heritage to GateD's radix code, which
in turn owes something to the BSD kernel.

SEE ALSO
========

   perl(1), Socket, Net::Netmask, Text::Trie, Tree::Trie.

   Tree::Radix and Net::RoutingTable are modules by Daniel Hagerty
<hag@linnaean.org> written entirely in perl, unlike this module.  At the
time of this writing, they are works-in-progress but may be available at:

     http://www.linnaean.org/~hag/

Interface to pcap(3) LBL packet capture library
***********************************************

NAME
====

   *Net::Pcap* - Interface to pcap(3) LBL packet capture library

SYNOPSIS
========

     use Net::Pcap;

DESCRIPTION
===========

   *Net::Pcap* is a Perl binding to the LBL pcap(3) library, version 0.4.
The README for libpcap describes itself as:

     "a system-independent interface for user-level packet capture.
     libpcap provides a portable framework for low-level network
     monitoring.  Applications include network statistics collection,
     security monitoring, network debugging, etc."

FUNCTIONS
=========

   All functions defined by *Net::Pcap* are direct mappings to the libpcap
functions.  Consult the pcap(3) documentation and source code for more
information.

   Arguments that change a parameter, for example *Net::Pcap::lookupdev()*,
are passed that parameter as a reference.  This is to retain compatibility
with previous versions of *Net::Pcap*.

Lookup functions
----------------

Net::Pcap::lookupdev(\$err);
     Returns the name of a network device that can be used with
     *Net::Pcap::open_live() function*.  On error, the $err parameter is
     filled with an appropriate error message else it is undefined.

*Net::Pcap::lookupnet($dev, \$net, \$mask, \$err);*
     Determine the network number and netmask for the device specified in
     $dev.  The function returns 0 on success and sets the $net and $mask
     parameters with values.  On failure it returns -1 and the $err
     parameter is filled with an appropriate error message.

Packet capture functions
------------------------

*Net::Pcap::open_live($dev, $snaplen, $promisc, $to_ms, \$err);*
     Returns a packet capture descriptor for looking at packets on the
     network.  The $dev parameter specifies which network interface to
     capture packets from.  The $snaplen and $promisc parameters specify
     the maximum number of bytes to capture from each packet, and whether
     to put the interface into promiscuous mode, respectively.  The $to_ms
     parameter specifies a read timeout in ms.  The packet descriptor will
     be undefined if an error occurs, and the $err parameter will be set
     with an appropriate error message.

*Net::Pcap::loop($pcap_t, $cnt, \&callback_fn, $user_data);*
     Read $cnt packets from the packet capture descriptor $pcap_t and call
     the perl function &callback_fn with an argument of $user_data.  If
     $cnt is negative, then the function loops forever or until an error
     occurs.

     The callback function is also passed packet header information and
     packet data like so:

          sub process_pkt {
              my($user_data, $hdr, $pkt) = @_;

          ...
            }

     The header information is a reference to a hash containing the
     following fields.

        * len

          The total length of the packet.

        * caplen

          The actual captured length of the packet data.  This corresponds
          to the snapshot length parameter passed to
          *Net::Pcap::open_live()*.

        * tv_sec

          Seconds value of the packet timestamp.

        * tv_usec

          Microseconds value of the packet timestamp.

*Net::Pcap::open_offline($filename, \$err);*
     Return a packet capture descriptor to read from a previously created
     "savefile".  The returned descriptor is undefined if there was an
     error and in this case the $err parameter will be filled.  Savefiles
     are created using the Net::Pcap::dump_* commands.

Net::Pcap::close($pcap_t);
     Close the packet capture device associated with descriptor $pcap_t.

*Net::Pcap::dispatch($pcap_t, $cnt, \&callback_fn, $user_data);*
     Collect $cnt packets and process them with callback function
     &callback_fn.  if $cnt is -1, all packets currently buffered are
     processed.  If $cnt is 0, process all packets until an error occurs.

*Net::Pcap::next($pcap_t, \%hdr);*
     Return the next available packet on the interface associated with
     packet descriptor $pcap_t.  Into the %hdr hash is stored the received
     packet header.  If not packet is available, the return value and
     header is undefined.

*Net::Pcap::compile($pcap_t, \$filter_t, $filter_str, $optimize, $netmask);*
     Compile the filter string contained in $filter_str and store it in
     $filter_t.  A description of the filter language can be found in the
     libpcap source code, or the manual page for tcpdump(8) .  The filter
     is optimized the filter if the $optimize variable is true.  The
     netmask of the network device must be specified in the $netmask
     parameter.  The function returns 0 if the compilation was successful,
     or -1 if there was a problem.

*Net::Pcap::setfilter($pcap_t, $filter_t);*
     Associate the compiled filter stored in $filter_t with the packet
     capture descriptor $pcap_t.

Savefile commands
-----------------

*Net::Pcap::dump_open($pcap_t, $filename);*
     Open a savefile for writing and return a descriptor for doing so.  If
     $filename is "-" data is written to standard output.  On error, the
     return value is undefined and *Net::Pcap::geterr()* can be used to
     retrieve the error text.

*Net::Pcap::dump($pcap_dumper_t, \%hdr, $pkt);*
     Dump the packet described by header %hdr and packet data $pkt to the
     savefile associated with $pcap_dumper_t.  The packet header has the
     same format as that passed to the *Net::Pcap::loop()* callback.

Net::Pcap::dump_close($pcap_dumper_t);
     Close the savefile associated with descriptor $pcap_dumper_t.

Status functions
----------------

Net::Pcap::datalink($pcap_t);
     Returns the link layer type associated with the currently open device.

Net::Pcap::snapshot($pcap_t);
     Returns the snapshot length (snaplen) specified in the call to
     *Net::Pcap::open_live()*.

Net::Pcap::is_swapped($pcap_t);
     This function returns true if the endianess of the currently open
     savefile is different from the endianess of the machine.

Net::Pcap::major_version($pcap_t);
     Return the major version number of the pcap library used to write the
     currently open savefile.

Net::Pcap::minor_version($pcap_t);
     Return the minor version of the pcap library used to write the
     currently open savefile.

*Net::Pcap::stats($pcap_t, \%stats);*
     Returns a hash containing information about the status of packet
     capture device $pcap_t.  The hash contains the following fields.

        * *ps_recv*

          The number of packets received by the packet capture software.

        * *ps_drop*

          The number of packets dropped by the packet capture software.

        * *ps_ifdrop*

          The number of packets dropped by the network interface.

Net::Pcap::file($pcap_t);
     Return the filehandle associated with a savefile opened with
     *Net::Pcap::open_offline()*.

Net::Pcap::fileno($pcap_t);
     Return the file number of the network device opened with
     *Net::Pcap::open_live()*.

Error handling
--------------

Net::Pcap::geterr($pcap_t);
     Return an error message for the last error associated with the packet
     capture device $pcap_t.

Net::Pcap::strerror($errno);
     Return a string describing error number $errno.

*Net::Pcap::perror($pcap_t, $prefix);*
     Print the text of the last error associated with descriptor $pcap_t on
     standard error, prefixed by $prefix.

LIMITATIONS
===========

   The following limitations apply to this version of *Net::Pcap*.

   * At present, only one callback function and user data scalar can be
     current at any time as they are both stored in global variables.

EXAMPLES
========

   See the 't' directory of the *Net::Pcap* distribution for examples on
using this module.

COPYRIGHT
=========

   Copyright (c) 1999-2000 Tim Potter. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   pcap(3), tcpdump(8)

   The source code for libpcap is available from
*ftp://ftp.ee.lbl.gov/libpcap.tar.Z*

AUTHOR
======

   Tim Potter <tpot@frungy.org>

Utility routines for Net::Pcap module
*************************************

NAME
====

   `Net::PcapUtils' - Utility routines for Net::Pcap module

SYNOPSIS
========

     require Net::Pcap 0.03;
     use Net::PcapUtils;

     # Call function for all packets received

     Net::PcapUtils::loop(\&callbackfn, [optional args]);

     # Return the next packet available on the interface

     ($pkt, %hdr) = Net::PcapUtils::next($pcap_t);

     # Open a network device for processing

     $pcap_t = Net::PcapUtils::open([optional args]);

DESCRIPTION
===========

   Net::PcapUtils is a module to sit in front of Net::Pcap in order to
hide some of the pcap(3) initialisation by providing sensible defaults.
This enables a programmer to easily write small, specific scripts for a
particular purpose without having to worry about too many details.

   The functions implemented in Net::PcapUtils are named after those in
Net::Pcap.  The loop function sits in a loop and executes a callback for
each packet received, while next retrieves the next packet from the
network device, and open returns an opened packet descriptor suitable for
use with other Net::Pcap routines.

Functions
---------

*Net::PcapUtils::loop(\&callback_fn, [ARG => value]);*
     Given a callback function and a list of optional named parameterss,
     open a network interface, configure it, and execute the callback
     function for each packet received on the interface.  If the SAVEFILE
     parameter is present, a saved file of that name will be opened for
     reading, else the network interface specified by the DEV parameter
     will be opened.  If no saved file or device is specified, the
     interface returned by Net::Pcap::lookupdev() is opened.

     The optional arguments are those which are normally passed to the
     pcap_open_live() function from the pcap(3) library.  Their defaults
     are given below.

          my %args = (
              SNAPLEN => 100,         # Num bytes to capture from packet
          	PROMISC => 1,           # Operate in promiscuous mode?
              TIMEOUT => 1000,        # Read timeout (ms)
              NUMPACKETS => -1,       # Pkts to read (-1 = loop forever)
              FILTER => '',           # Filter string
          	USERDATA => '',         # Passed as first arg to callback fn
          	SAVEFILE => '',         # Default save file
          	DEV => '',              # Network interface to open
              );

     Consult the documentation for the pcap(3) library for more details on
     the nature of these parameters.

     On error, this function returns an error string describing the error.
     An empty string is returned upon success.

*Net::PcapUtils::open([ARG => value]);*
     Return a packet capture descriptor.  The optional arguments passed to
     this function are the same as those which can be passed to
     Net::PcapUtils::loop().

     If the open() command was successful, it returns a reference to a
     packet capture descriptor, else a string containing an error message.

Net::PcapUtils::next($pcap_t);
     Return the next packet available on the interface specified by packet
     capture descriptor $pcap_t.  This may be obtained from the
     Net::PcapUtils::open() function, Net::Pcap::open_live() or
     Net::Pcap::open_offline().

EXAMPLE
=======

   The following script prints a message for each IP packet received.

     #!/usr/bin/perl -w

     use strict;
     use Net::PcapUtils;

     sub process_pkt {
         print("packet\n");
     }

     Net::PcapUtils::loop(\&process_pkt, FILTER => 'ip');

SEE ALSO
========

   The `Net::Pcap' module for XS bindings to the `pcap(3)' library.

   The pcap library is available from ftp://ftp.ee.lbl.gov/libpcap.tar.Z

COPYRIGHT
=========

     Copyright (c) 1995,1996,1997,1998,1999 ANU and CSIRO on behalf of
     the participants in the CRC for Advanced Computational Systems
     ('ACSys').

     ACSys makes this software and all associated data and documentation
     ('Software') available free of charge.  You may make copies of the
     Software but you must include all of this notice on any copy.

     The Software was developed for research purposes and ACSys does not
     warrant that it is error free or fit for any purpose.  ACSys
     disclaims any liability for all claims, expenses, losses, damages
     and costs any user may incur as a result of using, copying or
     modifying the Software.

AUTHOR
======

   Tim Potter <tpot@acsys.anu.edu.au>

check a remote host for reachability
************************************

NAME
====

   Net::Ping - check a remote host for reachability

SYNOPSIS
========

     use Net::Ping;

     $p = Net::Ping->new();
     print "$host is alive.\n" if $p->ping($host);
     $p->close();

     $p = Net::Ping->new("icmp");
     foreach $host (@host_array)
     {
         print "$host is ";
         print "NOT " unless $p->ping($host, 2);
         print "reachable.\n";
         sleep(1);
     }
     $p->close();

     $p = Net::Ping->new("tcp", 2);
     while ($stop_time > time())
     {
         print "$host not reachable ", scalar(localtime()), "\n"
             unless $p->ping($host);
         sleep(300);
     }
     undef($p);

     # For backward compatibility
     print "$host is alive.\n" if pingecho($host);

DESCRIPTION
===========

   This module contains methods to test the reachability of remote hosts
on a network.  A ping object is first created with optional parameters, a
variable number of hosts may be pinged multiple times and then the
connection is closed.

   You may choose one of three different protocols to use for the ping.
With the "tcp" protocol the ping() method attempts to establish a
connection to the remote host's echo port.  If the connection is
successfully established, the remote host is considered reachable.  No
data is actually echoed.  This protocol does not require any special
privileges but has higher overhead than the other two protocols.

   Specifying the "udp" protocol causes the ping() method to send a udp
packet to the remote host's echo port.  If the echoed packet is received
from the remote host and the received packet contains the same data as the
packet that was sent, the remote host is considered reachable.  This
protocol does not require any special privileges.

   If the "icmp" protocol is specified, the ping() method sends an icmp
echo message to the remote host, which is what the UNIX ping program does.
If the echoed message is received from the remote host and the echoed
information is correct, the remote host is considered reachable.
Specifying the "icmp" protocol requires that the program be run as root or
that the program be setuid to root.

Functions
---------

Net::Ping->new([$proto [, $def_timeout [, $bytes]]]);
     Create a new ping object.  All of the parameters are optional.  $proto
     specifies the protocol to use when doing a ping.  The current choices
     are "tcp", "udp" or "icmp".  The default is "udp".

     If a default timeout ($def_timeout) in seconds is provided, it is used
     when a timeout is not given to the ping() method (below).  The timeout
     must be greater than 0 and the default, if not specified, is 5
     seconds.

     If the number of data bytes ($bytes) is given, that many data bytes
     are included in the ping packet sent to the remote host. The number of
     data bytes is ignored if the protocol is "tcp".  The minimum (and
     default) number of data bytes is 1 if the protocol is "udp" and 0
     otherwise.  The maximum number of data bytes that can be specified is
     1024.

$p->ping($host [, $timeout]);
     Ping the remote host and wait for a response.  $host can be either the
     hostname or the IP number of the remote host.  The optional timeout
     must be greater than 0 seconds and defaults to whatever was specified
     when the ping object was created.  If the hostname cannot be found or
     there is a problem with the IP number, undef is returned.  Otherwise,
     1 is returned if the host is reachable and 0 if it is not.  For all
     practical purposes, undef and 0 and can be treated as the same case.

$p->close();
     Close the network connection for this ping object.  The network
     connection is also closed by "undef $p".  The network connection is
     automatically closed if the ping object goes out of scope (e.g. $p is
     local to a subroutine and you leave the subroutine).

pingecho($host [, $timeout]);
     To provide backward compatibility with the previous version of
     Net::Ping, a pingecho() subroutine is available with the same
     functionality as before.  pingecho() uses the tcp protocol.  The
     return values and parameters are the same as described for the ping()
     method.  This subroutine is obsolete and may be removed in a future
     version of Net::Ping.

WARNING
=======

   pingecho() or a ping object with the tcp protocol use alarm() to
implement the timeout.  So, don't use alarm() in your program while you
are using pingecho() or a ping object with the tcp protocol.  The udp and
icmp protocols do not use alarm() to implement the timeout.

NOTES
=====

   There will be less network overhead (and some efficiency in your
program) if you specify either the udp or the icmp protocol.  The tcp
protocol will generate 2.5 times or more traffic for each ping than either
udp or icmp.  If many hosts are pinged frequently, you may wish to
implement a small wait (e.g. 25ms or more) between each ping to avoid
flooding your network with packets.

   The icmp protocol requires that the program be run as root or that it
be setuid to root.  The tcp and udp protocols do not require special
privileges, but not all network devices implement the echo protocol for
tcp or udp.

   Local hosts should normally respond to pings within milliseconds.
However, on a very congested network it may take up to 3 seconds or longer
to receive an echo packet from the remote host.  If the timeout is set too
low under these conditions, it will appear that the remote host is not
reachable (which is almost the truth).

   Reachability doesn't necessarily mean that the remote host is actually
functioning beyond its ability to echo packets.

   Because of a lack of anything better, this module uses its own routines
to pack and unpack ICMP packets.  It would be better for a separate module
to be written which understands all of the different kinds of ICMP packets.

Perl extension for direct-to-lpd printing.
******************************************

NAME
====

   Net::Printer - Perl extension for direct-to-lpd printing.

SYNOPSIS
========

     use Net::Printer;

     # Create new Printer Object
     $lineprinter = new Net::Printer(
     				  filename    => "/home/jdoe/myfile.txt",
     				  printer     => "lp",
     				  server      => "printserver",
     				  port        => 515,
     				  lineconvert => "YES"
     				  );
     # Print the file
     $result = $lineprinter->printfile();

     # Print a string
     $result =
       $lineprinter->printstring("Smoke me a kipper, I'll be back for breakfast.");

     # Get Queue Status
     $result = $lineprinter->queuestatus();

DESCRIPTION
===========

     Perl module for directly printing to a print server/printer without
     having to create a pipe to either lpr or lp.  This essentially
     mimics what the BSD LPR program does by connecting directly to the
     line printer printer port (almost always 515), and transmitting
     the data and control information to the print server.

     Please note that this module only talks to print servers that
     speak BSD.  It will not talk to printers using SMB or SysV unless
     they are set up as BSD printers.

Parameters
----------

     filename    - [optional] absolute path to the file you wish to print.

     printer     - [optional] Name of the printer you wish to print to.
                   Default "lp".

     server      - [optional] Name of the server that is running
                   lpd/lpsched.  Default "localhost".

     port        - [optional] The port you wish to connect to.
                   Default "515".

     lineconvert - [optional] Perform LF -> LF/CR translation.
                   Default "NO"

Functions
---------

     I<printfile> prints a specified file to the printer.  Returns a 1 on
     success, otherwise returns a string containing the error.

     I<printstring> prints a specified string to the printer as if it
     were a complete file  Returns a 1 on success, otherwise returns a
     string containing the error.

     I<queuestatus> returns the current status of the print queue.  I
     recommend waiting a short period of time between printing and
     issueing a queuestatus to give your spooler a chance to do it's
     thing.  5 seconds tends to work for me.

NOTES
=====

     When printing text, if you have the infamous "stair-stepping"
     problem, try setting lineconvert to "YES".  This should, in most
     cases, rectify the problem.

     Running with the -w option will cause the interpreter to complain
     about a couple of sprintf statements.  These can be safely ignored.

AUTHOR
======

   C. M. Fuhrman, cfuhrman@tfcci.com

SEE ALSO
========

   Socket, lpr(1), lp(1), perl(1).

Perl Remote Method Invocation (RMI) base class and utilities.
*************************************************************

NAME
====

   Net::RMI - Perl Remote Method Invocation (RMI) base class and utilities.

SYNOPSIS
========

     $d = serialize(\%sourceData);

     %destinationData = %{ deserialize($d) };

DESCRIPTION
===========

   This is the base class for Perl RMI. It provided some basic methods
common to both the client and server, and provides for data serialization.

METHODS
=======

set
     Sets an object's parameter to the specified value.

          Parameters: the parameter's name and value.
          Returns: nothing.

get
     Gets an object's parameter value.

          Parameters: the parameter's name.
          Returns: the parameter's value.

stripEOLN
     Removes a SINGLE traling 0x0A (LF) character from the end of a scalar.

          Parameters: a scalar.
          Returns: a scalar.

serialize
     Serializes an arbitrarily deep (or shallow for that matter) Perl data
     structure into a scalar.

          Parameter: a reference to a scalar, array, or hash.
          Returns: a scalar containing the serialized data.

deserialize
     Converts a scalar containing serialized data back into the data
     structures it represents.

          Parameters: a scalar containing the serialized data.
          Returns: a reference to a scalar, array, or hash.

SEE ALSO
========

   See Net/RMI/Server, and Net/RMI/Client.

AUTHOR
======

   Stephen Pandich, pandich@yahoo.com

   <a HREF="mailto:pandich@yahoo.com">Contact the Author</a>

Perl client-side extension for Remote Method Invocation (RMI).
**************************************************************

NAME
====

   Net::RMI::Client - Perl client-side extension for Remote Method
Invocation (RMI).

SYNOPSIS
========

     use Net::RMI::Client;

     # Initialize the client
     @servers = qw(localhost);
     $client = new Net::RMI::Client(@servers);

     # Refresh it's function list.
     $client->pollAllServers();

     $result = $client->RM_someFunction(@someParameters));

DESCRIPTION
===========

   The client portion of Net::RMI, contains the methods neccessary to find
and invoke remote methods. Remote methods can be invoked explicitly via
the `$client-'RM_someFunction> or implicitly via a more subtly mechanism:

     sub AUTOLOAD {
     	my $function = $AUTOLOAD;
     	$function =~ s/^.+::(.+)$/RM_$1/;
     	return $client->$function(@_);
     }

     someUnusedFunctionName(@someParameters);

   As the AUTOLOAD function will catch this attempt, and forward it to the
Net::RMI::Client instance (in this example called $client).

METHODS
=======

AUTOLOAD
     This function looks for all functions called that begin with "RM_".
     It then attempt to invoke those methods remotely, by taking all text
     after the "RM_" and using it as the remote function name.

          Parameters: none.
          Returns: the results of the RMI.

new
     The new method creates a new RMI client and defines its initial list
     of RMI method servers.

          Parameters: a list of method servers.
          Returns: a new instance.

addServer
     Adds one or more method servers to the list of servers for this
     client.

          Parameters: a list of method servers.
          Returns: nothing.

addServerFunction
     Adds a specific server, function name pair to the list of available
     remote methods for this client.

          Parameters: a server name and port, function name, function's
          	parameter list and return-type.
          Returns: nothing.

getFunction
     Gets a specific server, function name pair based on function name.
     If multiple servers provide a function with the same name, they are
     picked in round-robin fashion.

          Parameters: the function name.
          Returns: the method server's name and port, the function's
          	parameter list and return-type.

refresh
     An alias for pollAllServers.

     (See Below.)

pollAllServers
     Iterates over all method-servers for this client and retrieves the
     information about all functions available on those servers.

          Parameters: none.
          Returns: nothing.

pollServer
     Retrieves all information, including function parameters and
     return-type, for all functions on a specific method-server.

          Parameters: the method-server's name and port.
          Returns: nothing.

SEE ALSO
========

   See Net/RMI, and Net/RMI/Server.

AUTHOR
======

   Stephen Pandich, pandich@yahoo.com

   <a HREF="mailto:pandich@yahoo.com">Contact the Author</a>

Perl server-side extension for Remote Method Invocation (RMI).
**************************************************************

NAME
====

   Net::RMI::Server - Perl server-side extension for Remote Method
Invocation (RMI).

SYNOPSIS
========

     use Net::RMI::Server;

     $s = new Net::RMI::Server ||
     	die "Error: could not create object.\n";

     sub add2Numbers ($$) {
     	my ($n1, $n2) = @_;
     	return $n1 + $n2;
     }

     $function = "add2Numbers";
     $s->registerFunction($function, \&$function, ['$', '$'], '$');

     $s->listen();

DESCRIPTION
===========

   The server portion of Net::RMI, contains the methods for registering
and serving remotely invoked methods.

   Functions may only receive scalars or references. Complex data types
(i.e., arrays and hashes), must be passed by reference. Scalars, may also
be optionally passed by reference.

   Functions may only return scalars or references. Complex data types
(i.e., arrays and hashes), must be return as a reference. Scalars, may
also be optionally returned as a reference.

METHODS
=======

new
     Creates a new method-server.

          Parameters: none.
          Returns: a new instance of this class.

listen
     Listens forever for remote method requests.

          Parameters: none.
          Returns: never returns.

getFunction
     Returns a pointer to the function referenced by the function name.

          Parameters: the function's name.
          Returns: a reference to the function code.

getFunctionInfo
     Returns the "meta-information" about the function reference by the
     function name.

          Parameters: the function's name.
          Returns: the function's parameter list and return-type.

registerFunction
     Register's a local method with this remote-method server.

          Parameters: the function's name, code, parameter list and
          	return-list.
          Returns: nothing.

listFunctions
          Parameters: none.
          Returns: a list of functions registered to this method-server instance.

REAPER
     Reaps the zombie children, stolen with thanks from the Perl Cookbook.

          Parameters: none.
          Returns: nothing.

SEE ALSO
========

   See Net/RMI, and Net/RMI/Client.

AUTHOR
======

   Stephen Pandich, pandich@yahoo.com

   <a HREF="mailto:pandich@yahoo.com">Contact the Author</a>

there are file for RRP protocol and operations.
***********************************************

NAME
====

   Net::RRP - there are file for RRP protocol and operations.

SYNOPSIS
========

     use IO::Socket::SSL;

     use Net::RRP::Protocol;
     use Net::RRP::Request::Add;
     use Net::RRP::Entity::Domain;

     my $socket = new IO::Socket::SSL ( ... );
     my $protocol = new Net::RRP::Protocol ( socket => $socket );

     $protocol->getHello();

     my $entity   = new Net::RRP::Entity::Domain();
     $entity->setAttribute ( 'DomainName' => 'test.ru' );
     $entity->setAttribute ( 'NameServer' => [ 'ns1.test.ru', 'ns2.test.ru' ] );

     my $request  = new Net::RRP::Request::Add();
     $request->setEntity ( $entity );
     $request->setOption ( Period => 10 );

     $protocol->sendRequest ( $request );
     my $response = $protocol->getResponse ();

     die unless $request->isSuccessResponse ( $response );

DESCRIPTION
===========

   Net::RRP - there are file for RRP protocol and operations.

AUTHOR AND COPYRIGHT
====================

     Net::RRP (C) Zenon N.S.P., Michael Kulakov, 2000
                  125124, 19, 1-st Jamskogo polja st,
                  Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   RFC 2832, `Net::RRP::Codec(3)' in this node, `Net::RRP::Protocol(3)' in
this node, `Net::RRP::Request(3)' in this node, `Net::RRP::Entity(3)' in
this node, `Net::RRP::Response(3)' in this node, `Net::RRP::Toolkit(3)' in
this node, `Net::RRP::Entity::Domain(3)' in this node,
`Net::RRP::Entity::NameServer(3)' in this node,
`Net::RRP::Request::Add(3)' in this node, `Net::RRP::Request::Check(3)' in
this node, `Net::RRP::Request::Del(3)' in this node,
`Net::RRP::Request::Describe(3)' in this node, `Net::RRP::Request::Mod(3)'
in this node, `Net::RRP::Request::Quit(3)' in this node,
`Net::RRP::Request::Session(3)' in this node,
`Net::RRP::Request::Status(3)' in this node,
`Net::RRP::Request::Transfer(3)' in this node,
`Net::RRP::Request::Renew(3)' in this node, `Net::RRP::Response::n200(3)'
in this node, `Net::RRP::Response::n210(3)' in this node,
`Net::RRP::Response::n211(3)' in this node, `Net::RRP::Response::n212(3)'
in this node, `Net::RRP::Response::n213(3)' in this node,
`Net::RRP::Response::n220(3)' in this node, `Net::RRP::Response::n420(3)'
in this node, `Net::RRP::Response::n421(3)' in this node,
`Net::RRP::Response::n500(3)' in this node, `Net::RRP::Response::n501(3)'
in this node, `Net::RRP::Response::n502(3)' in this node,
`Net::RRP::Response::n503(3)' in this node, `Net::RRP::Response::n504(3)'
in this node, `Net::RRP::Response::n505(3)' in this node,
`Net::RRP::Response::n506(3)' in this node, `Net::RRP::Response::n507(3)'
in this node, `Net::RRP::Response::n508(3)' in this node,
`Net::RRP::Response::n509(3)' in this node, `Net::RRP::Response::n520(3)'
in this node, `Net::RRP::Response::n521(3)' in this node,
`Net::RRP::Response::n530(3)' in this node, `Net::RRP::Response::n531(3)'
in this node, `Net::RRP::Response::n532(3)' in this node,
`Net::RRP::Response::n533(3)' in this node, `Net::RRP::Response::n534(3)'
in this node, `Net::RRP::Response::n535(3)' in this node,
`Net::RRP::Response::n536(3)' in this node, `Net::RRP::Response::n540(3)'
in this node, `Net::RRP::Response::n541(3)' in this node,
`Net::RRP::Response::n542(3)' in this node, `Net::RRP::Response::n543(3)'
in this node, `Net::RRP::Response::n544(3)' in this node,
`Net::RRP::Response::n545(3)' in this node, `Net::RRP::Response::n546(3)'
in this node, `Net::RRP::Response::n547(3)' in this node,
`Net::RRP::Response::n548(3)' in this node, `Net::RRP::Response::n549(3)'
in this node, `Net::RRP::Response::n550(3)' in this node,
`Net::RRP::Response::n551(3)' in this node, `Net::RRP::Response::n552(3)'
in this node, `Net::RRP::Response::n553(3)' in this node,
`Net::RRP::Response::n554(3)' in this node, `Net::RRP::Response::n555(3)'
in this node, `Net::RRP::Response::n556(3)' in this node

codec class for serialization/deserialization of Net::RRP::Request/Response
***************************************************************************

NAME
====

   Net::RRP::Codec - codec class for serialization/deserialization of
Net::RRP::Request/Response

SYNOPSIS
========

     use Net::RRP::RRP::Codec;
     my $codec = new Net::RRP::Codec();

DESCRIPTION
===========

   Net::RRP::Codec - codec class for serialization/deserialization of
Net::RRP::Request/Response

new
---

   Constructor of this class.

   Example:

     use Net::RRP::RRP::Codec;
     my $codec = new Net::RRP::Codec();

decodeRequest
-------------

   This method get the buffer with unparsed rrp request && decode it and
return Net::RRP::Request object.  The real return object is a instance of
Net::RRP::Request::$requestName class. This method dynamic loads required
class ( package ). Next, we a parse the Entity part of RRP request and
construct the instance of Net::RRP::Entity::$entityName class ( with
dynamic loading of this class ) and add entity attributes to this object.
After this, parser process the rrp request options and add it's to request
object. When all done, method return a constructed rrp request object.
This method say throw() at any errors.

   Example:

     my $request = $codec->decodeRequest ( $buffer );

   This method encode the rrp request to buffer for send it's to any
stream.

   Example:

     my $buffer = $codec->encodeRequest ( $request );

decodeResponse
--------------

   This method constructs the instance of Net::RRP::Response::n$NNN class
from input buffer, where the $NNN is a response number ( the
Net::RRP::Response::n$NNN loads dynamic ). This method say throw() at any
errors;

   Example: my $response = $codec->decodeResponse ( $buffer );

encodeResponse
--------------

   This method get the instance of Net::RRP::Response child class and
encodes it's to rrp format.

   Example:

     my $buffer = $codec->encodeResponse ( $response );

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Codec (C) Michael Kulakov, Zenon N.S.P. 2000
                         125124, 19, 1-st Jamskogo polja st,
                         Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Request(3)' in this node, `Net::RRP::Response(3)' in this
node, `Net::RRP::Entity(3)' in this node, RFC 2832

rrp entity abstraction class
****************************

NAME
====

   Net::RRP::Entity - rrp entity abstraction class

SYNOPSIS
========

     use Net::RRP::Entity;
     my $entity = new Net::RRP::Entity();

DESCRIPTION
===========

   This is a base class for all Entity::* classes.

new
---

   This is a constructor. Example:

     use Net::RRP::Entity;
     my $entity = new Net::RRP::Entity();
     my $entity1 = new Net::RRP::Entity( key => [ 'value' ] );

getName
-------

   Return a *real* name of this entity. You must overwrite this method at
child class. Example:

     my $entityName = $entity->getName();
     print STDERR "EntityName is $entityName\n";

setAttribute
------------

   Setup attribte with name $attributeName to a $attributeValue.
$attributeValue must be a array ref. Example:

     $entity->setAttribute ( $attributeName, $attributeValue );
     $entity->setAttribute ( 'DomainName', [ 'test.ru' ] );
     $entity->setAttribute ( 'NameServer', [ 'ns1.ttt.ru', 'ns2.qqq.ru' ] );

getAttribute
------------

   Return a value of $attributeName attribute. Example:

     print STDERR $entity->getAttribute ( 'NameServer' )->[ 0 ];

   Can throw Net::RRP::Exception::MissingRequiredAttribute exception

getAttributes
-------------

   Return the hash ref of the all entity attributes. Example:

     my $attributes = $entity->getAttributes();
     foreach my $attributeName ( keys %$attributes )
     {
          print $attributeName . ' ' . $attributes->{ $$attributeName }->[ 0 ];
     }

getPrimaryAttributeValue
------------------------

   return a "primary" attribute value

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Entity (C) Michael Kulakov, Zenon N.S.P. 2000
                          125124, 19, 1-st Jamskogo polja st,
                          Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Request(3)' in this node, `Net::RRP::Response(3)' in this
node, `Net::RRP::Codec(3)' in this node, RFC 2832,
`Net::RRP::Exception::MissingRequiredAttribute(3)' in this node

rrp contact entity representation.
**********************************

NAME
====

   Net::RRP::Entity::Contact - rrp contact entity representation.

SYNOPSIS
========

     use Net::RRP::Entity::Contact;
     my $contactEntity = new Net::RRP::Entity::Contact ( name => 'contactname',
     						     fax  => 'password',
     						     .... );

DESCRIPTION
===========

   This is a rrp contact entity representation class.

getName
-------

   return a 'Contact'

setAttribute
------------

   Add check constraint to attributes. Only firstname, lastname,
middlename, address, phone, email and fax attributes may be exists

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Entity::Contact (C) Michael Kulakov, Zenon N.S.P. 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Entity(3)' in this node, `Net::RRP::Codec(3)' in this node,
RFC 2832, `Net::RRP::Exception::InvalidAttributeName(3)' in this node

rrp domain entity representation.
*********************************

NAME
====

   Net::RRP::Entity::Domain - rrp domain entity representation.

SYNOPSIS
========

     use Net::RRP::Entity::Domain;
     my $domainEntity = new Net::RRP::Entity::Domain ( DomainName => [ 'domain.ru' ],
     						   NameServer => [ 'ns1.domain.ru' ] );
     my $domainEntity1 = new Net::RRP::Entity::Domain ();
     $domainEntity1->setAttribute ( DomainName => [ 'domain.ru' ] );
     $domainEntity1->setAttribute ( NameServer => [ 'ns1.domain.ru' ] );

DESCRIPTION
===========

   This is a rrp domain entity representation class.

getName
-------

   return a 'Domain'

setAttribute
------------

   Add check constraint to attributes. Only DomainName and NameServer
attributes can exists.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Entity::Domain (C) Michael Kulakov, Zenon N.S.P. 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Entity(3)' in this node, `Net::RRP::Codec(3)' in this node,
RFC 2832, `Net::RRP::Exception::InvalidAttributeName(3)' in this node

rrp domain entity representation.
*********************************

NAME
====

   Net::RRP::Entity::NameServer - rrp domain entity representation.

SYNOPSIS
========

     use Net::RRP::Entity::NameServer;
     my $nameServerEntity = new Net::RRP::Entity::NameServer ( NameServer => [ 'ns1.domain.ru' ],
     						       IPAddress  => [ '1.1.1.1' ] );
     my $nameServerEntity1 = new Net::RRP::Entity::NameServer ();
     $nameServerEntity1->setAttribute ( NameServer => [ 'ns1.domain.ru' ] );
     $nameServerEntity1->setAttribute ( IPAddress  => [ '1.1.1.1' ] );

DESCRIPTION
===========

   This is a rrp name server entity representation class.

getName
-------

   return a 'NameServer'

setAttribute
------------

   Add check constraint to attributes. Only NameServer and IPAddress
attributes can exists.

getPrimaryAttributeValue
------------------------

   return a "primary" attribute value

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Entity::NameServer (C) Michael Kulakov, Zenon N.S.P. 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Entity(3)' in this node, `Net::RRP::Codec(3)' in this node,
RFC 2832, `Net::RRP::Exception::InvalidAttributeName(3)' in this node

rrp owner entity representation.
********************************

NAME
====

   Net::RRP::Entity::Owner - rrp owner entity representation.

SYNOPSIS
========

     use Net::RRP::Entity::Owner;
     my $ownerEntity = new Net::RRP::Entity::Owner ( name     => 'ownername',
     						 password => 'password',
     						 .... );

DESCRIPTION
===========

   This is a rrp owner entity representation class.

getName
-------

   return a 'Owner'

setAttribute
------------

   Add check constraint to attributes. Only OwnerName and NameServer
attributes can exists.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Entity::Owner (C) Michael Kulakov, Zenon N.S.P. 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Entity(3)' in this node, `Net::RRP::Codec(3)' in this node,
RFC 2832, `Net::RRP::Exception::InvalidAttributeName(3)' in this node

rrp registrar entity representation.
************************************

NAME
====

   Net::RRP::Entity::Registrar - rrp registrar entity representation.

SYNOPSIS
========

     use Net::RRP::Entity::Registrar;
     my $registrarEntity = new Net::RRP::Entity::Registrar ( name     => 'registrarname',
     							 password => 'password',
     							 .... );

DESCRIPTION
===========

   This is a rrp registrar entity representation class.

getName
-------

   return a 'Registrar'

setAttribute
------------

   Add check constraint to attributes. Only name, password, techcontact,
status may be exists

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Entity::Registrar (C) Michael Kulakov, Zenon N.S.P. 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Entity(3)' in this node, `Net::RRP::Codec(3)' in this node,
RFC 2832, `Net::RRP::Exception::InvalidAttributeName(3)' in this node

rrp replica entity representation.
**********************************

NAME
====

   Net::RRP::Entity::Replica - rrp replica entity representation.

SYNOPSIS
========

     use Net::RRP::Entity::Replica;
     my $replicaEntity = new Net::RRP::Entity::Replica ( name => 'replicaname',
     						      => 'password',
     							 .... );

DESCRIPTION
===========

   This is a rrp replica entity representation class.

getName
-------

   return a 'Replica'

setAttribute
------------

   Add check constraint to attributes. Only techcontact, serial, name and
password may be exists

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Entity::Replica (C) Michael Kulakov, Zenon N.S.P. 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Entity(3)' in this node, `Net::RRP::Codec(3)' in this node,
RFC 2832, `Net::RRP::Exception::InvalidAttributeName(3)' in this node

rrp protocol
************

NAME
====

   Net::RRP::Protocol - rrp protocol

SYNOPSIS
========

     use Net::RRP::Protocol;
     my $protocol = new Net::RRP::Protocol ( %parameters_for_IO_Socket_SSL_new );
     my $protocol1 = new Net::RRP::Protocol ( socket => $io_socket_ssl_object );

DESCRIPTION
===========

   This class implements rrp command ( request/response ) communications
over socket ( IO::Socket::SSL )

new
---

   This is a comstructor. You must setup complete paraters for initiliaze
of IO::Socket::SSL instance or pass already initilized socket at 'socket'
key.

     use Net::RRP::Protocol;
     my $protocol = new Net::RRP::Protocol ( %parameters_for_IO_Socket_SSL_new );
     my $protocol1 = new Net::RRP::Protocol ( socket => $io_socket_ssl_object );

   See `IO::Socket::SSL(3)' in this node for more details about
IO::Socket::SSL parameters.

getRequest
----------

   Get Net::RRP::Request class instance from socket. See
`Net::RRP::Codec(3)' in this node for more details about parsing of stream
&& get Net::RRP::Request instance.

     my $request = $protocol->getRequest ();

getResponse
-----------

   Get Net::RRP::Response class instance from socket. See
`Net::RRP::Codec(3)' in this node for more details about parsing of stream
&& get Net::RRP::Response instance.

     my $response = $protocol->getResponse ();

sendRequest
-----------

   Send rrp request to socket. Example:

     $protocol->sendRequest ( $request );

   throw throw Net::RRP::Exception::IOError if io errors.

sendResponse
------------

   Send rrp response to socket. Example:

     $protocol->sendResponse ( $response );

   throw throw Net::RRP::Exception::IOError if io errors.

sendHello()
-----------

   Send a "hello" message to a socket at the server part. You can pass
registryName, version and buildDate parameters to this call.

     $protocol->hello ( registryName => "RU",
     		    version      => '1.1.0',
     		    buildDate    => 'Mon Jun 19 14:04:00 MSK 2000' ).

   Return true if ok and false at errors.

getHello
--------

   Get "hello" from scream

     $protocol->getHello();

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Protocol (C) Michael Kulakov, Zenon N.S.P. 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Request(3)' in this node, `Net::RRP::Response(3)' in this
node, `Net::RRP::Codec(3)' in this node, RFC 2832

rrp request abstraction class
*****************************

NAME
====

   Net::RRP::Request - rrp request abstraction class

SYNOPSIS
========

     use Net::RRP::Request;
     my $request = new Net::RRP::Request;

DESCRIPTION
===========

   This is a base class for all Request::* classes.

new
---

   The constructor. You can pass entity && options attributes to this
method. Example:

     my $request = new Net::RRP::Request ( entity  => new Net::RRP::Entity ( .... ),
                                           options => { key => 'value' } );
     my $request1 = new Net::RRP::Request ( );

getName
-------

   Return a *real* name of this request. You must overwrite this method at
child class. Example:

     my $requestName = $request->getName();
     print STDERR "EntityName is $requestName\n";

setEntity
---------

   Setup the rrp entity for this request. Example:

     $request->setEntity ( new Net::RRP::Entity ( ... ) );

getEntity
---------

   Return a entity of this request. Example:

     my $entity = $request->getEntity();

   Can throw Net::RRP::Exception::MissingRequiredEntity exception

getOption
---------

   Return a request option by $optionName. Example:

     print $request->getOption ( $optionName );
     print $request->getOption ( 'ttt' ); # no '-' here

   Can throw Net::RRP::Exception::MissingCommandOption() exception.

setOption
---------

   Set $optionName rrp request option to the $optionValue. Example:

     $request->setOption ( $optionName =>  $optionValue );
     $request->setOption ( tt => 'qq' );

getOptions
----------

   Return a hash ref to the request options. Example:

     my $options = $request->gtOptions();
     map { print "$_ = " . $options->{$_} } keys %$options;

isSuccessResponse
-----------------

   Return a true if response is successfull.

     my $protocol = new Net::RRP::Protocol ( .... );
     my $request  = new Net::RRP::Request::Add ( .... );
     $protocol->sendRequest ( $request );
     my $response = $protocol->getResponse ();
     die "error" unless $request->isSuccessResponse ( $response );

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Request (C) Michael Kulakov, Zenon N.S.P. 2000
                           125124, 19, 1-st Jamskogo polja st,
                           Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Entity(3)' in this node, `Net::RRP::Response(3)' in this
node, `Net::RRP::Codec(3)' in this node, RFC 2832,
`Net::RRP::Exception::MissingCommandOption(3)' in this node,
`Net::RRP::Exception::MissingRequiredEntity(3)' in this node

rrp add request representation.
*******************************

NAME
====

   Net::RRP::Request::Add - rrp add request representation.

SYNOPSIS
========

     use Net::RRP::Request::Add;
     my $addRequest = new Net::RRP::Request::Add
        ( entity  => new Net::RRP::Entity::Domain
          ( DomainName => [ 'domain.ru' ],
     	NameServer => [ 'ns1.domain.ru' ] ),
          options => { Period => 10 } );
     my $addRequest1 = new Net::RRP::Request::Add ();
     $addRequest1->setEntity ( new Net::RRP::Entity::Domain
     			   ( DomainName => [ 'domain.ru' ],
     			     NameServer => [ 'ns1.domain.ru' ] ) );
     $addRequest1->setOption ( Period => 10 );

DESCRIPTION
===========

   This is a rrp add request representation class.

getName
-------

   return a 'Add'

setEntity
---------

   throw Net::RRP::Exception::InvalidEntityValue exception unless entity
is Net::RRP::Entity::Domain or Net::RRP::Entity::NameServer

setOption
---------

   Support for Registrar and Serial options.  pass Period option. Throw
Net::RRP::Exception::InvalidCommandOption exception at other options.
Throw Net::RRP::Exception::InvalidOptionValue unless passed value is
numeric.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Request::Add (C) Michael Kulakov, Zenon N.S.P. 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Request(3)' in this node, `Net::RRP::Codec(3)' in this node,
`Net::RRP::Entity::Domain(3)' in this node,
`Net::RRP::Entity::NameServer(3)' in this node, RFC 2832,
`Net::RRP::Exception::InvalidEntityValue(3)' in this node,
`Net::RRP::Exception::InvalidCommandOption(3)' in this node,
`Net::RRP::Exception::InvalidOptionValue(3)' in this node

rrp check request representation.
*********************************

NAME
====

   Net::RRP::Request::Check - rrp check request representation.

SYNOPSIS
========

     use Net::RRP::Request::Check;
     my $checkRequest = new Net::RRP::Request::Check
        ( entity  => new Net::RRP::Entity::Domain ( DomainName => [ 'domain.ru' ] ) );
     my $checkRequest1 = new Net::RRP::Request::Check ();
     $checkRequest1->setEntity ( new Net::RRP::Entity::NameServer ( NameServer => [ 'ns1.domain.ru' ] ) );

DESCRIPTION
===========

   This is a rrp check request representation class.

getName
-------

   return a 'Check'

setEntity
---------

   throw Net::RRP::Exception::InvalidEntityValue unless entity is
Net::RRP::Entity::Domain or Net::RRP::Entity::NameServer

setOption
---------

   throw Net::RRP::Exception::InvalidCommandOption;

isSuccessResponse
-----------------

   Command: CHECK Success: 210, 211, 212, 213

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Request::Check (C) Michael Kulakov, Zenon N.S.P. 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Request(3)' in this node, `Net::RRP::Codec(3)' in this node,
`Net::RRP::Entity::Domain(3)' in this node,
`Net::RRP::Entity::NameServer(3)' in this node, RFC 2832,
`Net::RRP::Exception::InvalidEntityValue(3)' in this node,
`Net::RRP::Exception::InvalidCommandOption(3)' in this node,

rrp delete request representation.
**********************************

NAME
====

   Net::RRP::Request::Del - rrp delete request representation.

SYNOPSIS
========

     use Net::RRP::Request::Del;
     my $deleteRequest = new Net::RRP::Request::Del
        ( entity  => new Net::RRP::Entity::Domain  ( DomainName => [ 'domain.ru' ] ) );
     my $deleteRequest1 = new Net::RRP::Request::Del ();
     $deleteRequest1->setEntity ( new Net::RRP::Entity::Domain ( DomainName => [ 'domain.ru' ] ) );

DESCRIPTION
===========

   This is a rrp delete request representation class.

getName
-------

   return a 'Del'

setEntity
---------

   throw Net::RRP::Exception::InvalidEntityValue unless entity is
Net::RRP::Entity::Domain or Net::RRP::Entity::NameServer

setOption
---------

   Pass to parent method for Registrar and Serial options, throw
Net::RRP::Exception::InvalidCommandOption () immediate if other option

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Request::Del (C) Michael Kulakov, Zenon N.S.P. 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Request(3)' in this node, `Net::RRP::Codec(3)' in this node,
`Net::RRP::Entity::Domain(3)' in this node,
`Net::RRP::Entity::NameServer(3)' in this node, RFC 2832,
`Net::RRP::Exception::InvalidEntityValue(3)' in this node,
`Net::RRP::Exception::InvalidCommandOption(3)' in this node,

rrp delete request representation.
**********************************

NAME
====

   Net::RRP::Request::Delete - rrp delete request representation.

SYNOPSIS
========

     use Net::RRP::Request::Delete;
     my $deleteRequest = new Net::RRP::Request::Delete
        ( entity  => new Net::RRP::Entity::Domain  ( DomainName => [ 'domain.ru' ] ) );
     my $deleteRequest1 = new Net::RRP::Request::Delete ();
     $deleteRequest1->setEntity ( new Net::RRP::Entity::Domain ( DomainName => [ 'domain.ru' ] ) );

DESCRIPTION
===========

   This is a rrp delete request representation class.

getName
-------

   return a 'Delete'

setEntity
---------

   throw Net::RRP::Exception::InvalidEntityValue unless entity is
Net::RRP::Entity::Domain or Net::RRP::Entity::NameServer

setOption
---------

   throw Net::RRP::Exception::InvalidCommandOption () immediate

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Request::Delete (C) Michael Kulakov, Zenon N.S.P. 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Request(3)' in this node, `Net::RRP::Codec(3)' in this node,
`Net::RRP::Entity::Domain(3)' in this node,
`Net::RRP::Entity::NameServer(3)' in this node, RFC 2832,
`Net::RRP::Exception::InvalidEntityValue(3)' in this node,
`Net::RRP::Exception::InvalidCommandOption(3)' in this node,

rrp describe request representation.
************************************

NAME
====

   Net::RRP::Request::Describe - rrp describe request representation.

SYNOPSIS
========

     use Net::RRP::Request::Describe;
     my $describeRequest = new Net::RRP::Request::Describe ( Target => 'Protocol' );
     my $describeRequest1 = new Net::RRP::Request::Describe ();
     $describeRequest1->setOption ( Target => 'Protocol' );

DESCRIPTION
===========

   This is a rrp describe request representation class.

getName
-------

   return a 'Describe'

setEntity
---------

   throw Net::RRP::Exception::InvalidEntityValue immediate

setOption
---------

   Pass only Target option with Protocol value. Throw
Net::RRP::Exception::InvalidCommandOption in other case.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Request::Describe (C) Michael Kulakov, Zenon N.S.P. 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Request(3)' in this node, `Net::RRP::Codec(3)' in this node,
RFC 2832

rrp mod request representation.
*******************************

NAME
====

   Net::RRP::Request::Mod - rrp mod request representation.

SYNOPSIS
========

     use Net::RRP::Request::Mod;
     my $modRequest = new Net::RRP::Request::Mod
        ( entity  => new Net::RRP::Entity::Domain
          ( DomainName => [ 'domain.ru' ],
     	NameServer => [ 'ns1.domain.ru' ] ) );
     my $modRequest1 = new Net::RRP::Request::Mod ();
     $modRequest1->setEntity ( new Net::RRP::Entity::Domain
     			   ( DomainName => [ 'domain.ru' ],
     			     NameServer => [ 'ns1.domain.ru' ] ) );

DESCRIPTION
===========

   This is a rrp mod request representation class.

getName
-------

   return a 'Mod'

setEntity
---------

   throw Net::RRP::Exception::InvalidEntityValue unless entity is
Net::RRP::Entity::Domain or Net::RRP::Entity::NameServer

setOption
---------

   Support for Registrar and Serial options, throw
Net::RRP::Exception::InvalidCommandOption if other option

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Request::Mod (C) Michael Kulakov, Zenon N.S.P. 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Request(3)' in this node, `Net::RRP::Codec(3)' in this node,
`Net::RRP::Entity::Domain(3)' in this node,
`Net::RRP::Entity::NameServer(3)' in this node, RFC 2832,
`Net::RRP::Exception::InvalidCommandOption(3)' in this node,
`Net::RRP::Exception::InvalidEntityValue(3)' in this node

rrp quit request representation.
********************************

NAME
====

   Net::RRP::Request::Quit - rrp quit request representation.

SYNOPSIS
========

     use Net::RRP::Request::Quit;
     my $quitRequest = new Net::RRP::Request::Quit ()

DESCRIPTION
===========

   This is a rrp quit request representation class.

getName
-------

   return a 'Quit'

setEntity
---------

   throw Net::RRP::Exception::InvalidEntityValue immediate

setOption
---------

   throw Net::RRP::Exception::InvalidCommandOption () immediate

isSuccessResponse
-----------------

   Only 200 response successfull for quit.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Request::Quit (C) Michael Kulakov, Zenon N.S.P. 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Request(3)' in this node, `Net::RRP::Codec(3)' in this node,
RFC 2832, `Net::RRP::Exception::InvalidCommandOption(3)' in this node,
`Net::RRP::Exception::InvalidEntityValue(3)' in this node

rrp renew request representation.
*********************************

NAME
====

   Net::RRP::Request::Renew - rrp renew request representation.

SYNOPSIS
========

     use Net::RRP::Request::Renew;
     my $renewRequest = new Net::RRP::Request::Renew
        ( entity  => new Net::RRP::Entity::Domain ( DomainName => 'domain.ru' )
          options => { Period => 10, CurrentExpirationYear => 2000 } );

DESCRIPTION
===========

   This is a rrp renew request representation class.

getName
-------

   return a 'Renew'

setEntity
---------

   throw Net::RRP::Exception::InvalidEntityValue unless entity is
Net::RRP::Entity::Domain

setOption
---------

   Pass only Period && CurrentExpirationYear option. Throw
Net::RRP::Exception::InvalidCommandOption at other case.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Request::Renew (C) Michael Kulakov, Zenon N.S.P. 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Request(3)' in this node, `Net::RRP::Codec(3)' in this node,
`Net::RRP::Entity::Domain(3)' in this node,
`Net::RRP::Entity::NameServer(3)' in this node, RFC 2832,
`Net::RRP::Exception::InvalidCommandOption(3)' in this node,
`Net::RRP::Exception::InvalidEntityValue(3)' in this node

rrp reverse request representation. This command must reverse protocol for replication issues.
**********************************************************************************************

NAME
====

   Net::RRP::Request::Reverse - rrp reverse request representation. This
command must reverse protocol for replication issues.

SYNOPSIS
========

     use Net::RRP::Request::Reverse;
     my $reverseRequest = new Net::RRP::Request::Reverse ();

DESCRIPTION
===========

   This is a rrp reverse request representation class. RRP rfc extension.

getName
-------

   return a 'Reverse'

setEntity
---------

   throw Net::RRP::Exception::InvalidEntityValue immediate

setOption
---------

   throw Net::RRP::Exception::InvalidCommandOption () immediate

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Request::Reverse (C) Vladimir B. Grebenschikov
                                    TSB "Russian Express"
                                    vova@express.ru

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Request(3)' in this node, `Net::RRP::Codec(3)' in this node,
RFC 2832, `Net::RRP::Exception::InvalidCommandOption(3)' in this node,
`Net::RRP::Exception::InvalidEntityValue(3)' in this node

rrp session request representation.
***********************************

NAME
====

   Net::RRP::Request::Session - rrp session request representation.

SYNOPSIS
========

     use Net::RRP::Request::Session;
     my $sessionRequest = new Net::RRP::Request::Session ( Id       => 'reg1',
     						       Password => '***' );
     my $sessionRequest1 = new Net::RRP::Request::Session ();
     $sessionRequest1->setOption ( Id          => 'reg1' );
     $sessionRequest1->setOption ( Password    => '***'  );
     $sessionRequest1->setOption ( NewPassword => '****' );

DESCRIPTION
===========

   This is a rrp session request representation class.

getName
-------

   return a 'Session'

setEntity
---------

   throw Net::RRP::Exception::InvalidEntityValue immediate

setOption
---------

   Pass only Id, Password, NewPassword options

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Request::Session (C) Michael Kulakov, Zenon N.S.P. 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Request(3)' in this node, `Net::RRP::Codec(3)' in this node,
RFC 2832, `Net::RRP::Exception::InvalidCommandOption(3)' in this node,
`Net::RRP::Exception::InvalidEntityValue(3)' in this node

rrp status request representation.
**********************************

NAME
====

   Net::RRP::Request::Status - rrp status request representation.

SYNOPSIS
========

     use Net::RRP::Request::Status;
     my $statusRequest = new Net::RRP::Request::Status
        ( entity  => new Net::RRP::Entity::Domain ( DomainName => [ 'domain.ru' ] ) );
     my $statusRequest1 = new Net::RRP::Request::Status ();
     $statusRequest1->setEntity ( new Net::RRP::Entity::NameServer ( NameServer => [ 'ns1.domain.ru' ] ) );

DESCRIPTION
===========

   This is a rrp status request representation class.

getName
-------

   return a 'Status'

setEntity
---------

   throw Net::RRP::Exception::InvalidEntityValue unless entity is
Net::RRP::Entity::Domain or Net::RRP::Entity::NameServer

setOption
---------

   throw Net::RRP::Exception::InvalidCommandOption

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Request::Status (C) Michael Kulakov, Zenon N.S.P. 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Request(3)' in this node, `Net::RRP::Codec(3)' in this node,
`Net::RRP::Entity::Domain(3)' in this node,
`Net::RRP::Entity::NameServer(3)' in this node, RFC 2832,
`Net::RRP::Exception::InvalidCommandOption(3)' in this node,
`Net::RRP::Exception::InvalidEntityValue(3)' in this node

rrp transfer request representation.
************************************

NAME
====

   Net::RRP::Request::Transfer - rrp transfer request representation.

SYNOPSIS
========

     use Net::RRP::Request::Transfer;
     my $transferRequest = new Net::RRP::Request::Transfer
        ( entity  => new Net::RRP::Entity::Domain ( DomainName => [ 'domain.ru' ] ),
          options => { Approve => 'no' } )
     my $transferRequest1 = new Net::RRP::Request::Transfer ();
     $transferRequest1->setEntity ( new Net::RRP::Entity::Domain ( DomainName => [ 'domain.ru' ] );
     $transferRequest1->setOption ( Approve => 'no' );

DESCRIPTION
===========

   This is a rrp transfer request representation class.

getName
-------

   return a 'Transfer'

setEntity
---------

   throw Net::RRP::Exception::InvalidEntityValue unless entity is
Net::RRP::Entity::Domain

setOption
---------

   Pass only Approve option and yes/no value

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Request::Transfer (C) Michael Kulakov, Zenon N.S.P. 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Request(3)' in this node, `Net::RRP::Codec(3)' in this node,
`Net::RRP::Entity::Domain(3)' in this node, RFC
2832,`Net::RRP::Exception::InvalidCommandOption(3)' in this node,
`Net::RRP::Exception::InvalidEntityValue(3)' in this node,
`Net::RRP::Exception::InvalidOptionValue(3)' in this node

the base class for the Net::RRP::Response::* classes
****************************************************

NAME
====

     Net::RRP::Response - the base class for the Net::RRP::Response::* classes

SYNOPSIS
========

     use Net::RRP::Response;
     my $response = new Net::RRP::Response ();

DESCRIPTION
===========

   This is a base class of all Response::* classes. Child class must
overwrite a getCode method and setup own constrains for attributes at
setAttribute method. Child classes must named Net::RRP::Response::nNNN,
where NNN is a response number.

new
---

   The constructor. You can setup attributes and description. Example:

     use Net::RRP::Response;
     my $response = new Net::RRP::Response ();
     my $otherResponse = new Net::RRP::Response ( attributes  => { qq => 'tt'},
     					      description => 'this is a response description' );

newFromException
----------------

   Construct new response object from exception infomation;

     my $response = newFromException Net::RRP::Response ( new Net::RRP::Exception ( "description", $code ) );

getCode
-------

   This method return a code (number) of response. Must be overwrited at
child classes. Example:

     my $responseNumber = $response->getCode;

getDescription
--------------

   Get response description. Example:

     my $description = $response->getDescription();

setDescription
--------------

   Set response description. Example:

     $response->setDescription ( 'this is a response description' );

getAttribute
------------

   Return a named response attribute. Example:

     my $attribute = $response->getAttribute ( 'name' );

setAttribute
------------

   Setup a named attribute. Example:

     $response->setAttribute ( 'name' => 'value' );

getAttributes
-------------

   Get response attributes hash ref. Example:

     my $attributes = $response->getAttributes;
     map { print "$_ = " . $attributes->{$_} } keys %$attributes;

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response (C) Michael Kulakov, Zenon N.S.P. 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Entity(3)' in this node, `Net::RRP::Request(3)' in this
node, `Net::RRP::Codec(3)' in this node, `Net::RRP::Exception(3)' in this
node, RFC 2832

the rrp response 200 representation
***********************************

NAME
====

   Net::RRP::Response::n200 - the rrp response 200 representation

SYNOPSIS
========

     use Net::RRP::Response::n200;
     my $response = new Net::RRP::Response::n200;

DESCRIPTION
===========

   Net::RRP::Response::n200 - the 200 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n200 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 210 representation
***********************************

NAME
====

   Net::RRP::Response::n210 - the rrp response 210 representation

SYNOPSIS
========

     use Net::RRP::Response::n210;
     my $response = new Net::RRP::Response::n210;

DESCRIPTION
===========

   Net::RRP::Response::n210 - the 210 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n210 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 211 representation
***********************************

NAME
====

   Net::RRP::Response::n211 - the rrp response 211 representation

SYNOPSIS
========

     use Net::RRP::Response::n211;
     my $response = new Net::RRP::Response::n211;

DESCRIPTION
===========

   Net::RRP::Response::n211 - the 211 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n211 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 212 representation
***********************************

NAME
====

   Net::RRP::Response::n212 - the rrp response 212 representation

SYNOPSIS
========

     use Net::RRP::Response::n212;
     my $response = new Net::RRP::Response::n212;

DESCRIPTION
===========

   Net::RRP::Response::n212 - the 212 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n212 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 213 representation
***********************************

NAME
====

   Net::RRP::Response::n213 - the rrp response 213 representation

SYNOPSIS
========

     use Net::RRP::Response::n213;
     my $response = new Net::RRP::Response::n213;

DESCRIPTION
===========

   Net::RRP::Response::n213 - the 213 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n213 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 220 representation
***********************************

NAME
====

   Net::RRP::Response::n220 - the rrp response 220 representation

SYNOPSIS
========

     use Net::RRP::Response::n220;
     my $response = new Net::RRP::Response::n220;

DESCRIPTION
===========

   Net::RRP::Response::n220 - the 220 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n220 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 420 representation
***********************************

NAME
====

   Net::RRP::Response::n420 - the rrp response 420 representation

SYNOPSIS
========

     use Net::RRP::Response::n420;
     my $response = new Net::RRP::Response::n420;

DESCRIPTION
===========

   Net::RRP::Response::n420 - the 420 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n420 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 421 representation
***********************************

NAME
====

   Net::RRP::Response::n421 - the rrp response 421 representation

SYNOPSIS
========

     use Net::RRP::Response::n421;
     my $response = new Net::RRP::Response::n421;

DESCRIPTION
===========

   Net::RRP::Response::n421 - the 421 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n421 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 500 representation
***********************************

NAME
====

   Net::RRP::Response::n500 - the rrp response 500 representation

SYNOPSIS
========

     use Net::RRP::Response::n500;
     my $response = new Net::RRP::Response::n500;

DESCRIPTION
===========

   Net::RRP::Response::n500 - the 500 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n500 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 501 representation
***********************************

NAME
====

   Net::RRP::Response::n501 - the rrp response 501 representation

SYNOPSIS
========

     use Net::RRP::Response::n501;
     my $response = new Net::RRP::Response::n501;

DESCRIPTION
===========

   Net::RRP::Response::n501 - the 501 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n501 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 502 representation
***********************************

NAME
====

   Net::RRP::Response::n502 - the rrp response 502 representation

SYNOPSIS
========

     use Net::RRP::Response::n502;
     my $response = new Net::RRP::Response::n502;

DESCRIPTION
===========

   Net::RRP::Response::n502 - the 502 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n502 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 503 representation
***********************************

NAME
====

   Net::RRP::Response::n503 - the rrp response 503 representation

SYNOPSIS
========

     use Net::RRP::Response::n503;
     my $response = new Net::RRP::Response::n503;

DESCRIPTION
===========

   Net::RRP::Response::n503 - the 503 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n503 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 504 representation
***********************************

NAME
====

   Net::RRP::Response::n504 - the rrp response 504 representation

SYNOPSIS
========

     use Net::RRP::Response::n504;
     my $response = new Net::RRP::Response::n504;

DESCRIPTION
===========

   Net::RRP::Response::n504 - the 504 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n504 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 505 representation
***********************************

NAME
====

   Net::RRP::Response::n505 - the rrp response 505 representation

SYNOPSIS
========

     use Net::RRP::Response::n505;
     my $response = new Net::RRP::Response::n505;

DESCRIPTION
===========

   Net::RRP::Response::n505 - the 505 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n505 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 506 representation
***********************************

NAME
====

   Net::RRP::Response::n506 - the rrp response 506 representation

SYNOPSIS
========

     use Net::RRP::Response::n506;
     my $response = new Net::RRP::Response::n506;

DESCRIPTION
===========

   Net::RRP::Response::n506 - the 506 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n506 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 507 representation
***********************************

NAME
====

   Net::RRP::Response::n507 - the rrp response 507 representation

SYNOPSIS
========

     use Net::RRP::Response::n507;
     my $response = new Net::RRP::Response::n507;

DESCRIPTION
===========

   Net::RRP::Response::n507 - the 507 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n507 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 508 representation
***********************************

NAME
====

   Net::RRP::Response::n508 - the rrp response 508 representation

SYNOPSIS
========

     use Net::RRP::Response::n508;
     my $response = new Net::RRP::Response::n508;

DESCRIPTION
===========

   Net::RRP::Response::n508 - the 508 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n508 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 509 representation
***********************************

NAME
====

   Net::RRP::Response::n509 - the rrp response 509 representation

SYNOPSIS
========

     use Net::RRP::Response::n509;
     my $response = new Net::RRP::Response::n509;

DESCRIPTION
===========

   Net::RRP::Response::n509 - the 509 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n509 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 520 representation
***********************************

NAME
====

   Net::RRP::Response::n520 - the rrp response 520 representation

SYNOPSIS
========

     use Net::RRP::Response::n520;
     my $response = new Net::RRP::Response::n520;

DESCRIPTION
===========

   Net::RRP::Response::n520 - the 520 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n520 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 521 representation
***********************************

NAME
====

   Net::RRP::Response::n521 - the rrp response 521 representation

SYNOPSIS
========

     use Net::RRP::Response::n521;
     my $response = new Net::RRP::Response::n521;

DESCRIPTION
===========

   Net::RRP::Response::n521 - the 521 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n521 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 530 representation
***********************************

NAME
====

   Net::RRP::Response::n530 - the rrp response 530 representation

SYNOPSIS
========

     use Net::RRP::Response::n530;
     my $response = new Net::RRP::Response::n530;

DESCRIPTION
===========

   Net::RRP::Response::n530 - the 530 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n530 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 531 representation
***********************************

NAME
====

   Net::RRP::Response::n531 - the rrp response 531 representation

SYNOPSIS
========

     use Net::RRP::Response::n531;
     my $response = new Net::RRP::Response::n531;

DESCRIPTION
===========

   Net::RRP::Response::n531 - the 531 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n531 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 532 representation
***********************************

NAME
====

   Net::RRP::Response::n532 - the rrp response 532 representation

SYNOPSIS
========

     use Net::RRP::Response::n532;
     my $response = new Net::RRP::Response::n532;

DESCRIPTION
===========

   Net::RRP::Response::n532 - the 532 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n532 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 533 representation
***********************************

NAME
====

   Net::RRP::Response::n533 - the rrp response 533 representation

SYNOPSIS
========

     use Net::RRP::Response::n533;
     my $response = new Net::RRP::Response::n533;

DESCRIPTION
===========

   Net::RRP::Response::n533 - the 533 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n533 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 534 representation
***********************************

NAME
====

   Net::RRP::Response::n534 - the rrp response 534 representation

SYNOPSIS
========

     use Net::RRP::Response::n534;
     my $response = new Net::RRP::Response::n534;

DESCRIPTION
===========

   Net::RRP::Response::n534 - the 534 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n534 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 535 representation
***********************************

NAME
====

   Net::RRP::Response::n535 - the rrp response 535 representation

SYNOPSIS
========

     use Net::RRP::Response::n535;
     my $response = new Net::RRP::Response::n535;

DESCRIPTION
===========

   Net::RRP::Response::n535 - the 535 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n535 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 536 representation
***********************************

NAME
====

   Net::RRP::Response::n536 - the rrp response 536 representation

SYNOPSIS
========

     use Net::RRP::Response::n536;
     my $response = new Net::RRP::Response::n536;

DESCRIPTION
===========

   Net::RRP::Response::n536 - the 536 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n536 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 540 representation
***********************************

NAME
====

   Net::RRP::Response::n540 - the rrp response 540 representation

SYNOPSIS
========

     use Net::RRP::Response::n540;
     my $response = new Net::RRP::Response::n540;

DESCRIPTION
===========

   Net::RRP::Response::n540 - the 540 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n540 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 541 representation
***********************************

NAME
====

   Net::RRP::Response::n541 - the rrp response 541 representation

SYNOPSIS
========

     use Net::RRP::Response::n541;
     my $response = new Net::RRP::Response::n541;

DESCRIPTION
===========

   Net::RRP::Response::n541 - the 541 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n541 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 542 representation
***********************************

NAME
====

   Net::RRP::Response::n542 - the rrp response 542 representation

SYNOPSIS
========

     use Net::RRP::Response::n542;
     my $response = new Net::RRP::Response::n542;

DESCRIPTION
===========

   Net::RRP::Response::n542 - the 542 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n542 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 543 representation
***********************************

NAME
====

   Net::RRP::Response::n543 - the rrp response 543 representation

SYNOPSIS
========

     use Net::RRP::Response::n543;
     my $response = new Net::RRP::Response::n543;

DESCRIPTION
===========

   Net::RRP::Response::n543 - the 543 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n543 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 544 representation
***********************************

NAME
====

   Net::RRP::Response::n544 - the rrp response 544 representation

SYNOPSIS
========

     use Net::RRP::Response::n544;
     my $response = new Net::RRP::Response::n544;

DESCRIPTION
===========

   Net::RRP::Response::n544 - the 544 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n544 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 545 representation
***********************************

NAME
====

   Net::RRP::Response::n545 - the rrp response 545 representation

SYNOPSIS
========

     use Net::RRP::Response::n545;
     my $response = new Net::RRP::Response::n545;

DESCRIPTION
===========

   Net::RRP::Response::n545 - the 545 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n545 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 546 representation
***********************************

NAME
====

   Net::RRP::Response::n546 - the rrp response 546 representation

SYNOPSIS
========

     use Net::RRP::Response::n546;
     my $response = new Net::RRP::Response::n546;

DESCRIPTION
===========

   Net::RRP::Response::n546 - the 546 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n546 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 547 representation
***********************************

NAME
====

   Net::RRP::Response::n547 - the rrp response 547 representation

SYNOPSIS
========

     use Net::RRP::Response::n547;
     my $response = new Net::RRP::Response::n547;

DESCRIPTION
===========

   Net::RRP::Response::n547 - the 547 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n547 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 548 representation
***********************************

NAME
====

   Net::RRP::Response::n548 - the rrp response 548 representation

SYNOPSIS
========

     use Net::RRP::Response::n548;
     my $response = new Net::RRP::Response::n548;

DESCRIPTION
===========

   Net::RRP::Response::n548 - the 548 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n548 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 549 representation
***********************************

NAME
====

   Net::RRP::Response::n549 - the rrp response 549 representation

SYNOPSIS
========

     use Net::RRP::Response::n549;
     my $response = new Net::RRP::Response::n549;

DESCRIPTION
===========

   Net::RRP::Response::n549 - the 549 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n549 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 550 representation
***********************************

NAME
====

   Net::RRP::Response::n550 - the rrp response 550 representation

SYNOPSIS
========

     use Net::RRP::Response::n550;
     my $response = new Net::RRP::Response::n550;

DESCRIPTION
===========

   Net::RRP::Response::n550 - the 550 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n550 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 551 representation
***********************************

NAME
====

   Net::RRP::Response::n551 - the rrp response 551 representation

SYNOPSIS
========

     use Net::RRP::Response::n551;
     my $response = new Net::RRP::Response::n551;

DESCRIPTION
===========

   Net::RRP::Response::n551 - the 551 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n551 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 552 representation
***********************************

NAME
====

   Net::RRP::Response::n552 - the rrp response 552 representation

SYNOPSIS
========

     use Net::RRP::Response::n552;
     my $response = new Net::RRP::Response::n552;

DESCRIPTION
===========

   Net::RRP::Response::n552 - the 552 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n552 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 553 representation
***********************************

NAME
====

   Net::RRP::Response::n553 - the rrp response 553 representation

SYNOPSIS
========

     use Net::RRP::Response::n553;
     my $response = new Net::RRP::Response::n553;

DESCRIPTION
===========

   Net::RRP::Response::n553 - the 553 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n553 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 554 representation
***********************************

NAME
====

   Net::RRP::Response::n554 - the rrp response 554 representation

SYNOPSIS
========

     use Net::RRP::Response::n554;
     my $response = new Net::RRP::Response::n554;

DESCRIPTION
===========

   Net::RRP::Response::n554 - the 554 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n554 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 555 representation
***********************************

NAME
====

   Net::RRP::Response::n555 - the rrp response 555 representation

SYNOPSIS
========

     use Net::RRP::Response::n555;
     my $response = new Net::RRP::Response::n555;

DESCRIPTION
===========

   Net::RRP::Response::n555 - the 555 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n555 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

the rrp response 556 representation
***********************************

NAME
====

   Net::RRP::Response::n556 - the rrp response 556 representation

SYNOPSIS
========

     use Net::RRP::Response::n556;
     my $response = new Net::RRP::Response::n556;

DESCRIPTION
===========

   Net::RRP::Response::n556 - the 556 rrp response representation. See
base class `Net::RRP::Response(3)' in this node for more details.

AUTHOR AND COPYRIGHT
====================

     Net::RRP::Response::n556 (C) Zenon N.S.P. Michael Kulakov 2000
                            125124, 19, 1-st Jamskogo polja st,
                            Moscow, Russian Federation

     mkul@cpan.org

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `Net::RRP::Response(3)' in this node, `Net::RRP::Codec(3)' in this
node, RFC 2832

big hole of usefull methods :)
******************************

NAME
====

   Net::RRP::Toolkit - big hole of usefull methods :)

DESCRIPTION
===========

   Net::RRP::Toolkit - big hole of usefull methods :) By default, methods
not exported to caller namespape. You can export same methods to your
namespace using

     use Net::RRP::Toolkit qw(method_list);

   in your code;

decodeTilde($)
--------------

   Decode leading tilde (~) in file path.

   Example:

     use Net::RRP::Toolkit;
     my $path = '~mkul/dvp/Classes';
     my $fullPath = Net::RRP::Toolkit::decodeTilde($path);

   OR

     use Net::RRP::Toolkit qw(decodeTilde);
     my $fullPath = decodeTilde('~mkul/dvp/Classes');

safeCall($)
-----------

   safe call syscalls with repeat at EINTR errors

     use Net::RRP::Toolkit;
     my $result = Net::RRP::Toolkit::safeCall ( sub { open "qwa" } );
     die $! unless $result;

safeCopy(@)
-----------

   safe copy files.  1) copy source file to temporary file 2) rename
temporary file to destanation file

     input parameters: hash
       keys      =>    values
     Required parameters
       srcFile        source file name
       dstFile        destanation file name
     This parameters can be omited
       bufferSize     size of copy buffer, default is 128
       tmpMask        mask for temporary file name.
                      Default if "$toFileName.$$.$counter"

   Permission of destanation file is equal of source file Source file is
locked (lockf) by LOCK_SH Temporary destanation file locked by LOCK_EX

   Return true if ok or die if errors.

   example:  use Net::RRP::Toolkit;  Net::RRP::Toolkit::safeCopy ( srcFile
=> 'temp.passwd',                      dstFile => '/etc/passwd' );

lowerKeys($)
------------

   Lower all first level keys in hash

   Input: hash reference.

   Output: hash rerefence with lower keys

   example:  use Net::RRP::Toolkit;  my $hash = { KEY1 => 1,
KEY2 => { KEY3 => 3 }};  print Data::Dumper->Dump ( [
Net::RRP::Toolkit::lowerKeys ( $hash ) ] ) . "\n";

   output:   { key1 => 1,     key2 => { KEY3 => 3} }

pathSubtract($$)
----------------

   Path subscraction routine

   input: two _absolute_ directory paths

   output: reletive path of first path concerning of second path

   example:  use Net::RRP::Toolkit;  print Net::RRP::Toolkit::pathSubtract
( "/var/1", "/var/2" );

   output:  ../2

RADIUS dictionary parser
************************

NAME
====

   Net::Radius::Dictionary - RADIUS dictionary parser

SYNOPSIS
========

     use Net::Radius::Dictionary;

     my $dict = new Net::Radius::Dictionary "/etc/radius/dictionary";
     $dict->readdict("/some/other/file");
     my $num = $dict->attr_num('User-Name');
     my $name = $dict->attr_name(1);
     my $vsa_num = $dict->vsattr_num(9, 'cisco-avpair');
     my $vsa_name = $dict->vsattr_name(9, 1);

DESCRIPTION
===========

   This is a simple module that reads a RADIUS dictionary file and parses
it, allowing conversion between dictionary names and numbers.
Vendor-Specific attributes are supported in a way consistent to the
standards.

METHODS
-------

   new

   Returns a new instance of a Net::Radius::Dictionary object.  If given
an (optional) filename, it calls *readdict* for you.

   ->*readdict*

   Parses a dictionary file and learns the name<->number mappings.

   ->*attr_num*($attrname)

   Returns the number of the named attribute.

   ->*attr_type*($attrname)

   Returns the type (string, integer, *ipaddr*, or time) of the named
attribute.

   ->*attr_name*($attrnum)

   Returns the name of the attribute with the given number.

   ->*attr_numtype*($attrnum)

   Returns the type of the attribute with the given number.

   ->*attr_has_val*($attrnum)

   Returns a true or false value, depending on whether or not the numbered
attribute has any known value constants.

   ->*val_has_name*($attrnum)

   Alternate (bad) name for *attr_has_val*.

   ->*val_num*($attrnum, $valname)

   Returns the number of the named value for the attribute number supplied.

   ->*val_name*

   Returns the name of the numbered value for the attribute number
supplied.

   There's an equivalent family of accessor methods for Vendor-Specific
attributes and its values. Those methods are identical to their standard
attributes counterparts with two exceptions. Their names have a *vsa*
prepended to the accessor name and the first argument to each one is the
vendor code on which they apply.

CAVEATS
=======

   This module is mostly for the internal use of Net::Radius::Packet, and
may otherwise cause insanity and/or blindness if studied.

AUTHOR
======

   Christopher Masto <chris@netmonger.net>, Luis E. Munoz <lem@cantv.net>
contributed the VSA code.

SEE ALSO
========

   Net::Radius::Packet

Object-oriented Perl interface to RADIUS packets
************************************************

NAME
====

   Net::Radius::Packet - Object-oriented Perl interface to RADIUS packets

SYNOPSIS
========

     use Net::Radius::Packet;
     use Net::Radius::Dictionary;

     my $d = new Net::Radius::Dictionary "/etc/radius/dictionary";

     my $p = new Net::Radius::Packet $d, $data;
     $p->dump;

     if ($p->attr('User-Name' eq "lwall") {
       my $resp = new Net::Radius::Packet $d;
       $resp->set_code('Access-Accept');
       $resp->set_identifier($p->identifier);
       $resp->set_authenticator($p->authenticator);
       $resp->set_attr('Reply-Message') = "Welcome, Larry!\r\n";
       my $respdat = auth_resp($resp->pack, "mysecret");
       ...

DESCRIPTION
===========

   RADIUS (RFC2138) specifies a binary packet format which contains
various values and attributes.  Net::Radius::Packet provides an interface
to turn RADIUS packets into Perl data structures and vice-versa.

   Net::Radius::Packet does not provide functions for obtaining RADIUS
packets from the network.  A simple network RADIUS server is provided as an
example at the end of this document.

PACKAGE METHODS
---------------

new Net::Radius::Packet $dictionary, $data
     Returns a new Net::Radius::Packet object.  $dictionary is an optional
     reference to a Net::Radius::Dictionary object.  If not supplied, you
     must call *set_dict*.  If $data is supplied, unpack will be called for
     you to initialize the object.

OBJECT METHODS
--------------

   There are actually two families of object methods. The ones described
below deal with standard RADIUS attributes. An additional set of methods
handle the Vendor-Specific attributes as defined in the RADIUS protocol.
Those methods behave in much the same way as the ones below with the
exception that the prefix *vs* must be applied before the attr in most of
the names. The vendor code must also be included as the first parameter of
the call.

   The *vsattr* and *set_vsattr* methods, used to query and set
Vendor-Specific attributes return an array reference with the values of
each instance of the particular attribute in the packet. This difference
is required to support multiple VSAs with different parameters in the same
packet.

->*set_dict*($dictionary)
     Net::Radius::Packet needs access to a Net::Radius::Dictionary object
     to do packing and unpacking.  set_dict must be called with an
     appropriate dictionary reference (see Net/Radius/Dictionary)
     before you can use ->pack or ->unpack.

->unpack($data)
     Given a raw RADIUS packet $data, unpacks its contents so that they
     can be retrieved with the other methods (code, attr, etc.).

->pack
     Returns a raw RADIUS packet suitable for sending to a RADIUS client
     or server.

->code
     Returns the Code field as a string.  As of this writing, the following
     codes are defined:

          Access-Request          Access-Accept
          Access-Reject           Accounting-Request
          Accounting-Response     Access-Challenge
          Status-Server           Status-Client

-><set_code>($code)
     Sets the Code field to the string supplied.

->identifier
     Returns the one-byte Identifier used to match requests with responses,
     as a character value.

->*set_identifier*
     Sets the Identifier byte to the character supplied.

->*authenticator*
     Returns the 16-byte Authenticator field as a character string.

->*set_authenticator*
     Sets the Authenticator field to the character string supplied.

->attr($name)
     Retrieves the value of the named Attribute.  Attributes will be
     converted automatically based on their dictionary type:

          STRING     Returned as a string.
          INTEGER    Returned as a Perl integer.
          IPADDR     Returned as a string (a.b.c.d)
          TIME       Returned as an integer

->*set_attr*($name, $val)
     Sets the named Attribute to the given value.  Values should be
     supplied as they would be returned from the attr method.

->password($secret)
     The RADIUS Password attribute is encoded with a shared secret.  Use
     this method to return the decoded version.

->dump
     Prints the packet's contents to STDOUT.

EXPORTED SUBROUTINES
--------------------

*auth_resp*($packed_packet, $secret)
     Given a (packed) RADIUS packet and a shared secret, returns a new
     packet with the Authenticator field changed in accordace with RADIUS
     protocol requirements.

NOTES
=====

   This document is (not yet) intended to be a complete description of how
to implement a RADIUS server.  Please see the RFCs (at
ftp://ftp.livingston.com/pub/radius/) for that.  The following is a brief
description of the procedure:

     1. Receive a RADIUS request from the network.
     2. Unpack it using this package.
     3. Examine the attributes to determine the appropriate response.
     4. Construct a response packet using this package.
        Copy the Identifier and Authenticator fields from the request,
        set the Code as appropriate, and fill in whatever Attributes
        you wish to convey in to the server.
     5. Call the pack method and use the auth_resp function to
        authenticate it with your shared secret.
     6. Send the response back over the network.
     7. Lather, rinse, repeat.

EXAMPLE
=======

     #!/usr/local/bin/perl -w

     use Net::Radius::Dictionary;
     use Net::Radius::Packet;
     use Net::Inet;
     use Net::UDP;
     use Fcntl;
     use strict;

     # This is a VERY simple RADIUS authentication server which responds
     # to Access-Request packets with Access-Accept.  This allows anyone
     # to log in.

     my $secret = "mysecret";  # Shared secret on the term server

     # Parse the RADIUS dictionary file (must have dictionary in current dir)
     my $dict = new Net::Radius::Dictionary "dictionary"
       or die "Couldn't read dictionary: $!";

     # Set up the network socket (must have radius in /etc/services)
     my $s = new Net::UDP { thisservice => "radius" } or die $!;
     $s->bind or die "Couldn't bind: $!";
     $s->fcntl(F_SETFL, $s->fcntl(F_GETFL,0) | O_NONBLOCK)
       or die "Couldn't make socket non-blocking: $!";

     # Loop forever, recieving packets and replying to them
     while (1) {
       my ($rec, $whence);
       # Wait for a packet
       my $nfound = $s->select(1, 0, 1, undef);
       if ($nfound > 0) {
     	# Get the data
     	$rec = $s->recv(undef, undef, $whence);
     	# Unpack it
     	my $p = new Net::Radius::Packet $dict, $rec;
     	if ($p->code eq 'Access-Request') {
     	  # Print some details about the incoming request (try ->dump here)
     	  print $p->attr('User-Name'), " logging in with password ",
     		$p->password($secret), "\n";
     	  # Create a response packet
     	  my $rp = new Net::Radius::Packet $dict;
     	  $rp->set_code('Access-Accept');
     	  $rp->set_identifier($p->identifier);
     	  $rp->set_authenticator($p->authenticator);
     	  # (No attributes are needed.. but you could set IP addr, etc. here)
     	  # Authenticate with the secret and send to the server.
     	  $s->sendto(auth_resp($rp->pack, $secret), $whence);
     	}
     	else {
     	  # It's not an Access-Request
     	  print "Unexpected packet type recieved.";
     	  $p->dump;
     	}
       }
     }

AUTHOR
======

   Christopher Masto, <chris@netmonger.net>. VSA support by Luis E. Munoz,
<lem@cantv.net>. Fix for unpacking 3COM VSAs contributed by Ian Smith
<iansmith@ncinter.net>. Information for packing of 3Com VSAs provided by
Quan Choi <Quan_Choi@3com.com>

SEE ALSO
========

   Net::Radius::Dictionary

Perl extension for manipulate raw ip packets with interface to *libpcap*
************************************************************************

NAME
====

   Net::RawIP - Perl extension for manipulate raw ip packets with
interface to *libpcap*

SYNOPSIS
========

     use Net::RawIP;
     $a = new Net::RawIP;
     $a->set({ip => {saddr => 'my.target.lan',daddr => 'my.target.lan'},
              tcp => {source => 139,dest => 139,psh => 1, syn => 1}});
     $a->send;
     $a->ethnew("eth0");
     $a->ethset(source => 'my.target.lan',dest =>'my.target.lan');
     $a->ethsend;
     $p = $a->pcapinit("eth0","dst port 21",1500,30);
     $f = dump_open($p,"/my/home/log");
     loop $p,10,\&dump,$f;

DESCRIPTION
===========

   This package provides a class object which can be used for creating,
manipulating and sending a raw ip packets with optional feature for
manipulating ethernet headers.

   NOTE: Ethernet related methods are implemented on Linux and *BSD only

Exported constants
==================

     PCAP_ERRBUF_SIZE
     PCAP_VERSION_MAJOR
     PCAP_VERSION_MINOR
     lib_pcap_h

Exported functions
==================

   open_live open_offline dump_open lookupdev lookupnet dispatch loop dump
compile setfilter next datalink snapshot is_swapped major_version
minor_version stats file fileno perror geterr strerror close dump_close
timem linkoffset

   By default exported functions are the loop,dispatch,*dump_open*,dump,
open_live,*timem*,*linkoffset*,*ifaddrlist*,*rdev*. You have to use the
export tag *pcap* for export all of the pcap functions.  Please read the
docs for the libpcap and look at `Net::RawIP::libpcap(3pm)' in this node.
The exported functions the loop and the dispatch can run a perl code refs
as a callbacks for packet analyzing and printing.  If *dump_open* opens
and returns a valid file descriptor,this descriptor can be used in the
perl callback as a perl filehandle.Also fourth parameter for loop and
dispatch can be an array or a hash reference and it can be unreferensed in
a perl callback. The function next returns a string scalar (next
packet).Function *timem()* returns a string scalar which looking like
sec.*microsec*, where the sec and the *microsec* are the values which
returned by gettimeofday(3) , if *microsec* is less than 100000 then zeros
will be added to the left side of *microsec* for adjusting to six digits.
The function which called *linkoffset* returns a number of the bytes in
the link protocol header e.g. 14 for a Ethernet or 4 for a Point-to-Point
protocol.This function has one input parameter (pcap_t* which is returned
by open_live).

   The *ifaddrlist* function returns a hash reference,in this hash keys are
all running network devices,values are ip addresses of those devices in an
internet address format.

   The *rdev* function returns a name of the outgoing device for given
destination address.  It has one input parameter (destination address in
an internet address or a domain name or a host byteorder int formats).

   Please look at the examples.

CONSTRUCTOR
===========

   new   ({               ip       => {IPKEY => IPVALUE,...},
ARGPROTO => {PROTOKEY => PROTOVALUE,...} 	  })

   The ip is the key of the hash which value is a reference of the hash
with parameters of the iphdr in the current IP packet.

   The *`IPKEY'* is one of they (version *ihl* tos *tot_len* id *frag_off*
ttl protocol check *saddr* *daddr*).  You can to specify all
parameters,even check.If you do not specify parameter, then value by
default will be used.  Of course the checksum will be calculated if you do
not specify non-zero value for it.  The values of the *saddr* and the
*daddr* can be like www.oracle.com or 205.227.44.16, even they can be an
integer  if you know what is 205.227.44.16 as an unsigned int in the host
format ;).

   The *`ARGPROTO'* is one of they (*tcp* *udp* *icmp* generic), this key
has used for DEFINE subclass of the Net::RawIP. *If you not specify a
ARGPROTO then by default value is the tcp*.

   You *HAVE TO* initialize the subclass of the Net::RawIP object before
use.

   Here is a code for initializing the udp subclass in the Net::RawIP
object.

   $a = new Net::RawIP({udp =>{}});

   or

   $a = new Net::RawIP({ip => { tos => 22 }, udp => { source => 22,dest
=>23 } });

   You could *NOT* change the subclass in the object after.

   The default values of the ip hash are (4,5,16,0,0,0x4000,64,6,0,0,0)
for the *tcp* or (4,5,16,0,0,0x4000,64,17,0,0,0) for the *udp* or
(4,5,16,0,0,0x4000,64,1,0,0,0) for the *icmp* or
(4,5,16,0,0,0x4000,64,0,0,0,0) for the generic.

   The *`PROTOKEY'* is one of (source dest seq *ack_seq* *doff* *res1*
*res2* urg ack *psh* *rst* *syn* *fin* window check *urg_ptr* data) for
the tcp or

   one of (type code check *gateway* id sequence *unused* mtu data) for
the icmp or

   one of (source dest len check data) for the udp or just

   data for the generic.

   You have to specify just *gateway* - (int) or (id and sequence) -
(short and short) or (mtu and *unused*) - (short and short) for the icmp
because in the real icmp packet it's the C union.

   The default values are (0,0,0,0,5,0,0,0,0,0,0,0,0,0xffff,0,0,") for the
tcp and                   (0,0,0,0,0,0,0,0,") for the icmp and
     (0,0,0,0,") for the udp and                   (") for the generic.

   The valid values for urg ack *psh* *rst* *syn* *fin* are 0 or 1.  The
value of data is a string. Length of the result packet will be calculated
if you do not specify non-zero value for *tot_len*.

METHODS
=======

proto
     returns the name of the subclass current object e.g. *tcp*.  No input
     parameters.

packet
     returns a scalar which contain the packed ip packet of the current
     object.  No input parameters.

set
     is a method for set the parameters to the current object. The given
     parameters must look like the parameters for the constructor.

bset($packet,$eth)
     is a method for set the parameters for the current object.  *$packet*
     is a scalar which contain binary structure (an ip or an eth packet).
     This scalar must match with the subclass of the current object.  If
     *$eth* is given and it have a non-zero value then assumed that packet
     is a ethernet packet,otherwise it is a ip packet.

get
     is a method for get the parameters from the current object. This
     method returns the array which will be filled with an asked
     parameters in order as they have ordered in packet if you'd call it
     with an array context.  If this method is called with a scalar
     context then it returns a hash reference.  In that hash will stored
     an asked parameters as values,the keys are their names.

     The input parameter is a hash reference. In this hash can be three
     keys.  They are a ip and an one of the *ARGPROTO*s. The value must be
     an array reference. This array contain asked parameters.  E.g. you
     want to know current value of the tos from the iphdr and the flags of
     the tcphdr.  Here is a code :

          ($tos,$urg,$ack,$psh,$rst,$syn,$fin) = $packet->get({
                    ip => [qw(tos)],
          	    tcp => [qw(psh syn urg ack rst fin)]
          	    });

     The members in the array can be given in any order.

     For get the ethernet parameters you have to use the key *eth* and the
     values of the array (dest,source,proto). The values of the dest and
     the source will look like the output of the ifconfig(8) e.g.
     00:00:E8:43:0B:2A.

send($delay,$times)
     is a method which has used for send raw ip packet.  The input
     parameters are the delay seconds and the times for repeating send.
     If you do not specify parameters for the send,then packet will be
     sent once without delay.  If you do specify for the times a negative
     value then packet will be sent forever.  E.g. you want to send the
     packet for ten times with delay equal to one second.  Here is a code :

     $packet->send(1,10); The delay could be specified not only as integer
     but and as 0.25 for sleep to 250 ms or 3.5 to sleep for 3 seconds and
     500 ms.

pcapinit($device,$filter,$psize,$timeout)
     is a method for some a pcap init. The input parameters are a device,a
     string with a program for a filter,a packet size,a timeout.  This
     method will call the function open_live,then compile the filter
     string by compile(), set the filter and returns the pointer (*pcap_t
     **).

pcapinit_offline($fname)
     is a method for an offline pcap init.The input parameter is a name of
     the file which contains raw output of the libpcap dump function.
     Returns the pointer (*pcap_t **).

*ethnew*(*$device*,dest => *ARGOFDEST*,source => *ARGOFSOURCE*)
     is a method for init the ethernet subclass in the current object,
     *$device* is a required parameter,dest and source are an optional,
     *$device* is an ethernet device e.g. *eth0*, an *ARGOFDEST* and an
     *ARGOFSOURCE* are a the ethernet addresses in the ethernet header of
     the current object.

     The *ARGOFDEST* and the *ARGOFSOURCE* can be given as a string which
     contain just 6 bytes of the real ethernet address or like the output
     of the ifconfig(8) e.g. 00:00:E8:43:0B:2A or just an ip address or a
     hostname of a target, then a mac address will be discovered
     automatically.

     The ethernet frame will be sent with given addresses.  By default the
     source and the dest will be filled with a hardware address of the
     *$device*.

     NOTE: For use methods which are related to the ethernet you have to
     before initialize ethernet subclass by *ethnew*.

ethset
     is a method for set an ethernet parameters in the current object.
     The given parameters must look like parameters for the *ethnew*
     without a *$device*.

ethsend
     is a method for send an ethernet frame.  The given parameters must
     look like a parameters for the send.

*send_eth_frame*($frame,$times,$delay)
     is a method for send any ethernet frame which you may construct by
     hands.*$frame* is a packed ethernet frame exept destination and
     source fields(these fields can be setting by ethset or *ethnew*).
     Another parameters must look like the parameters for the send.

*optset*(OPTPROTO => { type => [...],data => [...] },...)
     is a method for set an IP and a TCP options.  The parameters for the
     optset must be given as a key-value pairs.  The *OPTPROTO*,s are the
     prototypes of the options(ip,*tcp*),values are the hashes
     references.The keys in this hashes are type and data.  The value of
     the type is an array reference.  This array must be filled with an
     integers.Refer to a RFC for a valid types.The value of the data also
     is an array reference. This array must be filled with strings which
     must contain all bytes from a option except bytes with type and
     length of an option.Of course indexes in those arrays must be equal
     for the one option.If type is equal to 0 or 1 then there is no bytes
     with a length and a data,but you have to specify zero data for
     compability.

*optget*(OPTPROTO => { type => [...] },...)
     is a method for get an IP and a TCP options.  The parameters for the
     optget must be given as key-value pairs.  The *OPTPROTO* is the
     prototype of the options(ip,*tcp*),the values are the hashes
     references.The key is the type.The value of the type is an array
     reference.  The return value is an array which will be filled with
     asked types,lengths,datas of the each type of the option in order as
     you have asked.If you do not specify type then all
     types,lengths,datas of an options will be returned.  E.g. you want to
     know all the IP options from the current object.  Here is a code:

     @opts = $a->optget(ip => {});

     E.g. you want to know just the IP options with the type which equal
     to 131 and 137.  Here is a code:

     ($t131,$l131,$d131,$t137,$l137,$d137) = $a->optget(
                     ip =>{ 				        type =>[(131,137)] 				        }
          );

optunset
     is a method for unset a subclass of the IP or the TCP options from a
     current object.It can be used if you  won't use options in the
     current object later.  This method must be used only after the
     *optset*.  The parameters for this method are the *OPTPROTO*'s.  E.g.
     you want to unset an IP options.  Here is a code:

     $a->optunset('ip');

     E.g. you want to unset a TCP and an IP options.  Here is a code:

     $a->optunset('ip','tcp');

AUTHOR
======

   Sergey Kolychev <ksv@al.lg.ua>

COPYRIGHT
=========

   Copyright (c) 1998,1999 Sergey Kolychev. All rights reserved. This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1),Net::RawIP::libpcap(3pm),tcpdump(1),RFC 791-793,RFC 768.

An interface to *libpcap* in Net::RawIP(3pm)
********************************************

NAME
====

   Net::RawIP::libpcap - An interface to *libpcap* in Net::RawIP(3pm)

DESCRIPTION
===========

     Function    The input parameters           The output parameters

     open_live   a network                      Return value is a pcap_t*
                 device(eth0,ppp0,...);         If retval less than zero
                 a snap length;                 then $err filled with
                 a promisc - boolean;           an error string.
     	     a timeout in sec;
     	     $err is an undef scalar;

     open_offline   a filename which is filled  Return value is pcap_t*
                    with a raw output of dump;  If retval less than zero
                    $err is an unfef scalar;    then $err filled with
     		                            an error string.

     dump_open  pcap_t*;                        Return value is a FILE*
                $err;

     lookupdev  $err;			    Return value is a name
                                                of first device which is
     					    found by libpcap

     lookupnet  a network device;               a netnumber;
                a netnumer is undef;            a netmask;
     	    a netmask is undef;             If retval less than zero
     	    $err is undef;                  then $err filled with
     				            an error string.

     dispatch   a scalar with pcap_t*;          No output parameters.
                number of packets for proce-
     	    ssing;
     	    reference to the perl call-
     	    back,this callback will be
     	    called with 3 parameters:
     	    $_[0] is fourth parameter
     	    from dispatch,
     	    $_[1] is a scalar with struc-
     	    ture pcap_pkthdr for a current
     	    packet,
     	    $_[2] is a scalar with a current
     	    packet;
     	    fourth parameter could be
     	    an array or a hash reference
     	    or a pointer (FILE*) returned
     	    by dump_open,it can be unre-
     	    ferenced in the perl call-
     	    back or be used as a perl
     	    filehandle in that callback.

     loop 	    As for dispatch.                As for dispatch.

     dump       As for a perl callback          No output.
                but $_[0] must be a pointer
     	    (FILE*) only.

     compile    a scalar with pcap_t*;        a scalar with bpf_program.
                a bpf_program is undef;       If retval is less than zero
     	    a scalar with filter string;  then there was a problem with
     	    a boolean value (optimize or  filter grammar.
     	    not);
     	      a scalar with netmask;

     setfilter  a scalar with pcap_t*;        If retval is less than zero
     	    a scalar with bpf_program     then there was a problem while
     	    returned by compile.          settting filter.

     next     a scalar with pcap_t*;          A scalar with next packet;
              a scalar with with struc-       a scalar with with structure
     	  ture pcap_pkthdr for a current  pcap_pkthdr also will be modi
     	  packet,originally is undef.     filed for an every packet and
     		                          it can be accessed but for read
     					  only.

     datalink  a scalar with pcap_t*;         Retval is the link  layer type,
                                              e.g. DLT_EN10MB.

     snapshot  a scalar with pcap_t*;         Retval is the snapshot length
                                              specified when open_live was
     					  called.

     is_swapped  a scalar with pcap_t*;       returns true if the current
                                              savefile uses a different
     					  byte order than the current
     					  system.

     major_version  a scalar with pcap_t*;    returns the major number
                                              of the version of the pcap
     					  used to write the savefile.

     minor_version  a scalar with pcap_t*;    returns the minor number of the
                                              version of the pcap used to
     					  write the savefile.

     file       a scalar with pcap_t*;        returns the name of the
                                              savefile.

     stats      a scalar with pcap_t*;        If retval 0 then a scalar
                a scalar with structure       with structure pcap_stat will
     	    pcap_stat,originally undef    be filled with the
                                              packet statistics.

     fileno    a scalar with pcap_t*;        returns  the  file descriptor
                                             number of the savefile.
     					 A core perl function is
     					 available as CORE::fileno.

     geterr   a scalar with pcap_t*;         returns  the  error  text
                                             pertaining to the last pcap
     				         library error.

     perror   a scalar with pcap_t*;         prints the text of the last
              a scalar with prefix;          pcap  library error on stderr,
     		                         prefixed by prefix.

     close    a scalar with pcap_t*;         closes the files associated with
                                             pcap_t* and deallocates
     					 resources.
     	                                 A core perl function is
     					 available as CORE::close.

     dump_close  a scalar with pcap_t*;      closes the savefile.

AUTHOR
======

   Sergey Kolychev <ksv@al.lg.ua>

SEE ALSO
========

   Net::RawIP(3pm),pcap(3).

Perl extension for the client side of the REXEC protocol.
*********************************************************

NAME
====

   Net::Rexec - Perl extension for the client side of the REXEC protocol.

SYNOPSIS
========

     use Net::Rexec 'rexec';
     ($rc, @output) = rexec(host, command, [userid, [password]]);

DESCRIPTION
===========

   Invokes REXEC protocol to execute command on host using userid and
password.  If userid or password are omitted then they are retrieved from
the netrc file.  $rc is 0 if command was invoked on host, 1 otherwise
unless the fork to invoke command fails in which case it is 2.  Output is
put into @output.

AUTHOR
======

   Fila Kolodny <fila@ibi.com>.

SEE ALSO
========

   Net::Netrc(3pm).

Perl extension for secure copy protocol
***************************************

NAME
====

   Net::SCP - Perl extension for secure copy protocol

SYNOPSIS
========

     #procedural interface
     use Net::SCP qw(scp iscp);
     scp($source, $destination);
     iscp($source, $destination); #shows command, asks for confirmation, and
                                  #allows user to type a password on tty

     #OO interface
     $scp = Net::SCP->new( "hostname", "username" );
     #with named params
     $scp = Net::SCP->new( { "host"=>$hostname, "user"=>$username } );
     $scp->get("filename") or die $scp->{errstr};
     $scp->put("filename") or die $scp->{errstr};
     #tmtowtdi
     $scp = new Net::SCP;
     $scp->scp($source, $destination);

     #Net::FTP-style
     $scp = Net::SCP->new("hostname");
     $scp->login("user");
     $scp->cwd("/dir");
     $scp->size("file");
     $scp->get("file");
     $scp->quit;

DESCRIPTION
===========

   Simple wrappers around ssh and scp commands.

SUBROUTINES
===========

scp SOURCE, DESTINATION
     Can be called either as a subroutine or a method; however, the
     subroutine interface is depriciated.

     Calls scp in batch mode, with the -B -p -q and -r options.  Returns
     false upon error, with a text error message accessable in
     $scp->{errstr}.

     Returns false and sets the *errstr* attribute if there is an error.

iscp SOURCE, DESTINATION
     Can be called either as a subroutine or a method; however, the
     subroutine interface is depriciated.

     Prints the scp command to be execute, waits for the user to confirm,
     and (optionally) executes scp, with the -p and -r flags.

     Returns false and sets the *errstr* attribute if there is an error.

METHODS
=======

new HOSTNAME [ USER ] | HASHREF
     This is the constructor for a new Net::SCP object.  You must specify a
     hostname, and may optionally provide a user.  Alternatively, you may
     pass a hashref of named params, with the following keys:

          host - hostname
          user - username
          interactive - bool
          cwd - current working directory on remote server

login [USER]
     Compatibility method.  Optionally sets the user.

cwd CWD
     Sets the cwd (used for a subsequent get or put request without a full
     pathname).

get REMOTE_FILE [, LOCAL_FILE]
     Uses scp to transfer REMOTE_FILE from the remote host.  If a local
     filename is omitted, uses the basename of the remote file.

size FILE
     Returns the size in bytes for the given file as stored on the remote
     server.  Returns 0 on error, and sets the *errstr* attribute.  In the
     case of an actual zero-length file on the remote server, the special
     value '0e0' is returned, which evaluates to zero when used as a
     number, but is true.

     (Implementation note: An ssh connection is established to the remote
     machine and wc is used to determine the file size.)

put LOCAL_FILE [, REMOTE_FILE]
     Uses scp to trasnfer LOCAL_FILE to the remote host.  If a remote
     filename is omitted, uses the basename of the local file.

binary
     Compatibility method: does nothing; returns true.

AUTHORS
=======

   Ivan Kohler <ivan-netscp_pod@420.am> Anthony Deaver
<bishop@projectmagnus.org>

   Thanks to Jon Gunnip <jon@soundbite.com> for fixing a bug with size().

BUGS
====

   Still has no-OO cruft.

   In order to work around some problems with commercial SSH2, if the
source file is on the local system, and is not a directory, the -r flag is
omitted.

   It's probably better just to use SSH1 or OpenSSH
<http://www.openssh.com/>

   The Net::FTP-style OO stuff is kinda lame.  And incomplete.

SEE ALSO
========

   scp(1), ssh(1)

Send SMS messages to ANY device.
********************************

NAME
====

   Net::SMS - Send SMS messages to ANY device.

SYNOPSIS
========

   Net::SMS is a global short text messaging service interface via the
Internet.  It brings you the first and only way to send SMS messages
through one easy interface.  SimpleWire has defined an XML SMS standard
and will make numerous tools available for developer's use so that SMS
technology can be better utilized.  Currently, this interface supports
more than just SMS enabled devices and can send messages to ANY protocol.

PREREQUISITES
=============

   The following packages are required in order to run or even install
Net::SMS.

     * LWP::UserAgent >= 5.47
     * XML::DOM (libxml-enno) >= 1.02
     * Net::Pager >= 2.00

DESCRIPTION
===========

   Net::SMS is the perl interface to SimpleWire's expanding messaging
network.  The module interacts with SimleWire's Remote Procedure Calls.
The Remote Procedure Calls provide an XML API and the protocol is open to
all developers.  For futher support or questions, you should visit
SimpleWire's website at *www.simplewire.com*.  There you will find support
and documentation including the white paper explaining the SimpleWire XML
API.

SMS OVERVIEW
============

   SMS stands for short-text messaging service.  The current version of
this module takes a minimalist approach to SMS, but upcoming versions plan
to take full advantage of SMS.

   A SMS message will require a minimum of 3 to 5 properties to be set
within a request object.  The first property, a PIN, is the Pager
Identification Number.  This is typically the phone number of the device
you are trying to message.  This number does not include a 1 before the
area code and typically looks like 3135551212.  The second property, a
*Service ID*, is a proprietary service number assigned by SimpleWire.  The
Service ID tells SimpleWire where to route your message.  For example, a
Service ID of 7 sends a message to AT&T.  The third property, the From
field, is typically an optional field that is simply the sender's name.
An example would be "Joe".  The fourth property, the Callback field, is
typically an optional field that is simply the sender's callback number.
An example would be "3135551212".   The fifth and last property is the
Text field.  This is not optional and is the alphanumeric message you wish
to send.  This just explains the basic properties, but be aware that MANY
more properties and functions exist within the Net::SMS::Request and
Net::SMS::Response objects.  More documentation is available via a perldoc
commond on both of those objects.

Net::SMS OVERVIEW
=================

   See EXAMPLES section below to see working code.

   The first step to using the Net::SMS module is to make sure
LWP:UserAgent and XML::DOM are fully and correctly installed. Net::SMS
works in conjunction with Net::SMS::Request and Net::SMS::Response in
order to create requests and receive responses from the SimpleWire network.

   Basically, you instantiate a new Net::SMS object via $sms = new Net::SMS
and this object handles communication with the simplewire servers.  The
next step is to instantiate a new Net::SMS::Request object and then set
its properties.  This means you set the PIN, callback number, from,
message text, etc.  There are numerous properties and they are all
explained in full via a perldoc on Net::SMS::Request.

   Then pass in the new Net::SMS::Request object to the $sms->request()
function and your message will be sent.  The $sms->request() function will
return with a new Net::SMS::Response object.  Just like the
Net::SMS::Request object, the Net::SMS::Response object has many
properties and functions available.  They are fully explained via a
perldoc on Net::SMS::Response.

   That's all it takes to send a short-text message.  However, the Net::SMS
package provides much more functionality then these basic features.  The
perldoc for Net::SMS::Request and Net::SMS::Response will explain every
feature available.

EXAMPLES
========

   All perl scripts or modules that use Net::SMS must include these lines
before the code attempts to access any functions in the Net::SMS package.

     use Net::SMS
     use Net::SMS::Request

   After properly including these two modules above, your code is ready to
begin sending a message.  The following code will construct a basic
Net::SMS::Request object and send off a message.

     use Net::SMS
     use Net::SMS::Request

     # Construct a new SMS object
     my $sms = Net::SMS->new();
     # Construct a new SMS::Request object
     my $r = new Net::SMS::Request;
     # Set the type of request to 'sendpage'
     $r->set_sendpage;

     # Set the service id.  Check www.simplewire.com for a full listing
     # of the services that are supported.
     $r->service_id(2);
     $r->pin("1234567890");
     $r->from("Joe Lauer");
     $r->callback("9876543210");
     $r->text("Hello World From Net::SMS 1.00");

     # Send the request off and get a Net::SMS::Response object back.
     $response = $sms->request($r);

     # Check out what happened.
     if ($response->is_success) {
         print "Success!\n";
         print "Error Code: " . $response->error_code . "\n";
         print "Error Description: " . $response->error_description . "\n";
         print "Your ticket number is: " . $response->ticket_id . "\n";
     } else {
         print "Error occurred!\n";
         print "Error Code: " . $response->error_code . "\n";
         print "Error Description: " . $response->error_description . "\n";
     }

   Besides being able to send a message to a PIN and Service ID, a message
can be sent to an Alias if a device has been registered on
www.simplewire.com.  Just replace the the these lines from above:

     $r->service_id(2);
     $r->pin("1234567890");

   With this one line:

     $r->alias('email@email.com');

   *Again there are more features explained in a perldoc on
Net::SMS::Request*.  These include features ranging from asynchronous
sending of messages to setting the delimiter to seperate the from,
callback, and text fields.

   The second type of request supported in Net::SMS::Request is a
'servicelist'.  This request will fetch the service list from SimpleWire
and the associated service id's for each provider.  This is useful for
populating a <select> box for websites.  The following code will grab the
list and set two optional parameters so that only the information
necessary for populating a <select> box is retrieved from SimpleWire.  The
code will then print out some of the results in two different ways.

     use Net::SMS;
     use Net::SMS::Request;

     my $sms = Net::SMS->new();
     my $r = new Net::SMS::Request;

     $r->set_servicelist;
     $r->option_type("production");
     # This could be "all" so that every field is retrieved
     $r->option_fields("selectbox");

     # Send the request now
     $response = $sms->request($r);

     if ($response->is_success) {
         print "Success!\n";
         print "Error Code: " . $response->error_code . "\n";
         print "Error Description: " . $response->error_description . "\n";
     } else {
         print "Error occurred!\n";
         print "Error Code: " . $response->error_code . "\n";
         print "Error Description: " . $response->error_description . "\n";
     }

     # Grab all the services and plop them into an array of hashes
     @services = $response->fetchall_services();

     foreach $ser (@services) {
         print $ser->{ID} . "\n";
     }

     # Grab a row at a time into a hash like DBI
     while ($row = $response->fetchrow_service) {

     foreach $var (keys %{ $row }) {
         print $row->{$var} . "\t";
     }

     print "\n";

     }

   The third type of request supported in Net::SMS::Request is a
'checkstatus'.  This request will fetch the status of a previously sent
message.  Every 'sendpage' request that passes most error checking will be
assigned a ticket.  It is this ticket that needs to be sent thru during a
'checkstatus' request.  The following code example will check the status
of a previously sent message.

     use Net::SMS;
     use Net::SMS::Request;

     # Note that you will have had to do a sendpage and get a TICKET_ID
     # back for you to check with.

     my $sms = Net::SMS->new();
     my $r = new Net::SMS::Request;

     $r->set_checkstatus;

     # Set the ticket id to check.
     $r->ticket_id("D9VZ1-3MTWX-28UM0-8H1L7");

     # Request it.
     $response = $sms->request($r);

     # Check the response that was returned
     if ($response->is_success) {
         print "Success!\n";
         print "The status code: " . $response->status_code . "\n";
         print "The status description: " . $response->status_description . "\n";
     } else {
         print "Error occurred!\n";
         print "Error Code: " . $response->error_code . "\n";
         print "Error Description: " . $response->error_description . "\n";
     }

   Any further code questions can either be answered via a perldoc on
Net::SMS::Request or Net::SMS::Response.  Support can also be obtained by
emailing techsupport@simplewire.com.

SEE ALSO
========

   Net::SMS::Request, Net::SMS::Response, www.simplewire.com on the web.

AUTHOR
======

   Joe Lauer <joelauer@simplewire.com> www.simplewire.com

COPYRIGHT
=========

   Copyright (c) 2000 SimpleWire. All rights reserved. This program is free
software; you can redistribute it and/or modify it under the same terms as
Perl itself.

a module to send SMS messages using the Genie web2sms gateway (htto://www.genie.co.uk/).
****************************************************************************************

NAME
====

   Net::SMS::Genie - a module to send SMS messages using the Genie web2sms
gateway (htto://www.genie.co.uk/).

SYNOPSIS
========

     my $sms = Net::SMS->new(
         username => 'yourname',
         password => 'yourpassword',
         recipient => 07713123456,
         subject => 'a test',
         message => 'a test message',
     );

     $sms->verbose( 1 );
     $sms->message( 'a different message' );
     print "sending message to mobile number ", $sms->recipient();

     $sms->send();

DESCRIPTION
===========

   A perl module to send SMS messages, using the Genie web2sms gateway.
This module will only work with mobile phone numbers that have been
registered with Genie (http://www.genie.co.uk/) and uses form submission
to a URL that may be subject to change.

AUTHOR
======

   Ave Wrigley <Ave.Wrigley@itn.co.uk>

COPYRIGHT
=========

   Copyright (c) 2001 Ave Wrigley. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Constructs a request object to be used in conjunction with Net::SMS.
********************************************************************

NAME
====

   Net::SMS::Request - Constructs a request object to be used in
conjunction with Net::SMS.

SYNOPSIS
========

   Net::SMS::Request is a helper object for Net::SMS.  It is the object
that constructs the request to use with the Net::SMS object.

PREREQUISITES
=============

   See the prerequisites for Net::SMS.

DESCRIPTION
===========

   Net::SMS::Request generally requires you to set the request type, set a
few requried parameters, and then pass it to the Net::SMS::request()
method.  Each property and method is enumerated below.   Each property and
method is sectioned off based on the type of request they fit under.
Common methods and properties for each request type are listed first.

GENERAL NOTE ABOUT PROPERTIES
=============================

   All properties are either set to their default or are null.  Once a
property or method is called its state moves from undef to defined and
whatever it was defined to.  This could cause problems if you are not
careful.  A good example is the delimiter() property.  If you set it to an
empty string then it will now be an empty string in the message you send
off.  The only way to get rid of it so that it uses the default on the
SimpleWire network is to make this call delimiter(undef) which will erase
any call ever made to that function.  This same method can be applied to
any function used within this module.  Passing undef to it will erase it.

COMMON METHODS and PROPERTIES
=============================

   See below for more methods and properties available for each type of
request that SimpleWire can currently handle.

   *as_xml()*

   Returns the current data structure of the Net::SMS::Request object in
XML.  This is also the XML that will get sent to the SimpleWire API.

   *is_checkstatus()*

   Returns true or false based on whether or not the current object is set
to a 'checkstatus' request.

   *is_sendpage()*

   Returns true or false based on whether or not the current object is set
to a 'sendpage' request.

   *is_servicelist()*

   Returns true or false based on whether or not the current object is set
to a 'servicelist' request.

   *request_type($str)*

   Sets the request type if $str is passed in, or gets the current request
type if $str is omitted.

   *subscriber_id($str)*

   Sets the subscriber id if $str is passed in, or gets the current
subscriber id if $str is omitted.  A subscriber id is assigned when a
customer signs up on www.simplewire.com.  Developers and small volume
users are allowed to use Net::SMS for free, but grabbing a free subscriber
id will help us track the popularity of certain tools.  Please sign up for
free if you are going to use this module to send any quantity of messages.

   *timeout($str)*

   Sets the client side timeout if $str is passed in, or gets the current
client side timeout if $str is omitted.  The client side timeout controls
how long a client will wait for client/simplewire server connections.  You
might also want to check out the *option_timeout()* function for setting
the timeout for the simplewire server/carrier connection.

   *user_agent($str)*

   Sets the user agent if $str is passed in, or gets the current user agent
if $str is omitted.  The user agent is a string like "Perl/Net-SMS/1.00"
and is strictly for statistics on the SimpleWire network.

   *user_ip($str)*

   Sets the user ip if $str is passed in, or gets the current user ip if
$str is omitted.  The user ip is the IP Address of the computer or device
that a request is on the behalf of.  An example would be a website sending
a page off for a visiting websurfer.  The websurfer's IP would be set here.

SENDPAGE REQUEST METHODS and PROPERTIES
=======================================

   These methods are available for sending a message thru SimpleWire.  A
'sendpage' request basically requests SimpleWire to send a message.  A
ticket id will be assigned on our network for messages that make it past
our preliminary error checking.  This ticket id will eventually allow all
sorts of fancy features including our support for two-way messaging fairly
soon.

   *set_sendpage()*

   Sets the current request to a 'sendpage'.   This will allow a message
to be sent thru the SimpleWire network.

   *option_method($str)*

   Sets the optional method parameter if $str is passed in, or gets the
current method if $str is omitted.  This directs which method SimpleWire
should use to send the message.  The current options are 'synch'
(synchronous) or 'asynch' (asynchronous).  Synchronous is the default
method and it means SimpleWire will attempt to immediately deliver your
message to the carrier/provider.  Asynchronous is optional and it means we
will put your message into a queue.  The status of that message can be
checked later via the 'checkstatus' request.

   *option_timeout($str)*

   Sets the SimpleWire server timeout if $str is passed in, or gets the
current timeout if $str is omitted.  This controls how long the SimpleWire
server will wait during connections with the carrier/provider.  The
default timeout is 30 seconds on the SimpleWire network.

   *option_delimiter($str)*

   Sets the delimiter if $str is passed in, or gets the current delimiter
if $str is omitted.  This is undef by default, but this controls the
characters that seperate the from, callback, and text fields in the final
message.  The default delimiter on our network is " |" but it can be
overridden here.

   *alias($str)*

   Sets the alias if $str is passed in, or gets the current alias if $str
is omitted.  The alias is the SimpleWire alias if a device has been
registered on SimpleWire.  Ability to register devices thru this client
tool will be coming in later versions.  This property will override a pin
and service_id setting.

   *service_id($str)*

   Sets the Service ID if $str is passed in, or gets the current Service ID
if $str is omitted.  The service id is the propietary id assigned by
SimpleWire to every carrier or provider that we support.  A service list
can either be downloaded via a 'servicelist' request or browsed on the
www.simplewire.com website.  An example would be '7' for AT&T.

   *pin($str)*

   Sets the pin if $str is passed in, or gets the current pin if $str is
omitted.  The pin is the PIN or Pager Identification Number.  A PIN is
typically the device's phone number without the 1 for the area code.
However, the PIN is different for some carriers like PageNet.  Check the
www.simplewire.com website for more help.

   *from($str)*

   Sets the from if $str is passed in, or gets the current from if $str is
omitted.   The from is whoever is sending the message.  This field is
optional in most cases.

   *callback($str)*

   Sets the callback if $str is passed in, or gets the current callback if
$str is omitted.  The callback is the number that the user would like to
be called back at.  This field is optional except for numeric paging
services.

   *text($str)*

   Sets the text if $str is passed in, or gets the current text if $str is
omitted.  The text is the message that will be sent to the device.  The
maximum text length differs for each service and can only be obtained via
a 'servicelist' request or on the www.simplewire.com website.

CHECKSTATUS REQUEST METHODS and PROPERTIES
==========================================

   *set_checkstatus()*

   Sets the current request to a 'checkstatus'.   This will allow a
previously sent message to be checked on SimpleWire.  This request is
useful if a message was sent asynchronously and the client would like to
see if the page got delivered correctly.

   *ticket_id($str)*

   Sets the ticket id if $str is passed in, or gets the current ticket id
if $str is omitted.  The ticket id is always 23 characters long and looks
something like "D9VZ1-3MTWX-28UM0-8H1L7".  This ticket id is assigned by
SimpleWire during a 'sendpage' request.

SERVICELIST REQUEST METHODS and PROPERTIES
==========================================

   This allows the client tool to download our real time list of supported
service providers/carriers and their associated service ids.  This request
is useful for populating <select> boxes on websites.  This request also
allows the client tool to get information like the maximum text length
allowed for each service.

   *set_servicelist()*

   Sets the current request to a 'servicelist'.

   *option_type($str)*

   Sets the type if $str is passed in, or gets the current type if $str is
omitted.  The type is the kind of service list that the client tool would
like to download.  The default is "production" which is every service that
SimpleWire currently supports and updates.  Other possible options include
"development" and "all".  The names are intuitive and describe what type
of service list you want to get.

   *option_fields($str)*

   Sets the fields if $str is passed in, or gets the current fields if
$str is omitted.  The fields is what fields the client tool wants back
about each service.  The default is "all" which will obviously get every
available field.  However, the other option of "selectbox" will only get
the fields necessary to populate a <select> box on a website.  Since the
service list is so large this can help cut down on Internet lag.

EXAMPLES
========

   All examples are in the perldoc for Net::SMS.

   Any further code questions can either be answered via a perldoc on
Net::SMS or Net::SMS::Response.  Support can also be obtained by emailing
techsupport@simplewire.com.

SEE ALSO
========

   Net::SMS, Net::SMS::Response, www.simplewire.com on the web.

AUTHOR
======

   Joe Lauer <joelauer@simplewire.com> www.simplewire.com

COPYRIGHT
=========

   Copyright (c) 2000 SimpleWire. All rights reserved. This program is free
software; you can redistribute it and/or modify it under the same terms as
Perl itself.

An object that represents the response back from a request sent to SimpleWire.  To be used in conjunction with Net::SMS and Net::SMS::Request.
**********************************************************************************************************************************************

NAME
====

   Net::SMS::Response - An object that represents the response back from a
request sent to SimpleWire.  To be used in conjunction with Net::SMS and
Net::SMS::Request.

SYNOPSIS
========

   Net::SMS::Response is a helper object for Net::SMS.  It is the object
that represents the response from the SimpleWire network after a call to
the Net::SMS::request() function.

PREREQUISITES
=============

   See the prerequisites for Net::SMS.

DESCRIPTION
===========

   Net::SMS::Response provides all the functionality to analyze a response
back from a request sent to SimpleWire.

COMMON METHODS and PROPERTIES
=============================

   is_success()

   Returns true or false and represents whether the request sent was
considered a success or failure.  For example, the error code won't
represent this correctly since error codes of 0 - 10 are considered
successes.  Call this function to check whether the request was successful.

   *error_code()*

   Returns the error code in the response from SimpleWire.  Every single
request will have an error code available.  Error codes can be obtained as
a Word document or PDF from the www.simplewire.com website.

   *error_description()*

   Returns the error description in the response from SimpleWire.  Every
single request will have an error description available.  Error
descriptions can be obtained as a Word document or PDF from the
www.simplewire.com website.

   *as_xml()*

   Returns the current data structure of the Net::SMS::Response object in
XML.

   *is_checkstatus()*

   Returns true or false based on whether or not the current object is set
to a 'checkstatus' request.

   *is_sendpage()*

   Returns true or false based on whether or not the current object is set
to a 'sendpage' request.

   *is_servicelist()*

   Returns true or false based on whether or not the current object is set
to a 'servicelist' request.

   *request_type()*

   Gets the current request type.  Will return a string like
"servicelist", "sendpage", etc.

SENDPAGE REQUEST METHODS and PROPERTIES
=======================================

   *ticket_id()*

   Gets the ticket id from the 'sendpage' request.  Note that some
sendpage requests might not generate a ticket id if they fail some
preliminary error checking on our server.  Preliminary errors include
things like badly formed XML posted to our API.

SERVICELIST REQUEST METHODS and PROPERTIES
==========================================

   A 'servicelist' request will return a large list of services that
SimpleWire currently supports.  Each service will be dumped into its own
hash.  There are too many different keys that can be sent back to go thru
them all here, so I suggest that you just loop thru each key in the hash
to see how many different keys exist.  Another easy way to see what keys
exist is to print out the response as XML with code like:

     print $response->as_xml();

   The key for each hash will be the exact same as whatever exists between
each <service and /> tags.  For example if <service ID="18"/> exists then
the hash key would be ID.

   *fetchall_services()*

   Returns the entire service list as an array of hashes.  The following
code will access whatever is returned.

     # Grab all the services and plop them into an array of hashes
     @services = $response->fetchall_services();

     foreach $ser (@services) {
         print $ser->{ID} . "\n";
     }

   *fetchrow_service()*

   This method is like the DBI package if you have ever used that.  It
allows you to return one hash at a time and it will auto increment the
placeholder.  So you can iterate over the entire list in this fashion:

     # Grab a row at a time into a hash like DBI
     while ($row = $response->fetchrow_service) {

     foreach $var (keys %{ $row }) {
         print $row->{$var} . "\t";
     }

     print "\n";

     }

   It will return a false when it reaches the end and it will exit the
loop for you.

   *fetchrow_rewind()*

   This function resets the placeholder for the fetchrow_service()
function and rewinds you back to the beginning of the list.  This is
useful for needing the list in multiple areas but only downloading it one
time.

CHECKSTATUS REQUEST METHODS and PROPERTIES
==========================================

   The 'checkstatus' request will return a status code and a status
description.  They both corrospond to the same meanings as the error code
and description.  However, the error code and description strictly relate
to the 'checkstatus' transaction, while the status code and description
describe what happened to the previously sent message.  If the ticket id
passed in during the 'checkstatus' request generates an error then its
possible no status code or description will exist.

   *status_code()*

   Returns the status code associated with the ticket id.  The code
corrosponds to the error codes in the error_code() function.

   *status_description()*

   Returns the status description associated with the ticket id.  The
description corrosponds to the error descriptions in the
error_description() function.

EXAMPLES
========

   All examples are in the perldoc for Net::SMS.

   Any further code questions can either be answered via a perldoc on
Net::SMS or Net::SMS::Response.  Support can also be obtained by emailing
techsupport@simplewire.com.

SEE ALSO
========

   Net::SMS, Net::SMS::Response, www.simplewire.com on the web.

AUTHOR
======

   Joe Lauer <joelauer@simplewire.com> www.simplewire.com

COPYRIGHT
=========

   Copyright (c) 2000 SimpleWire. All rights reserved. This program is free
software; you can redistribute it and/or modify it under the same terms as
Perl itself

Simple Mail Transfer Protocol Client
************************************

NAME
====

   Net::SMTP - Simple Mail Transfer Protocol Client

SYNOPSIS
========

     use Net::SMTP;

     # Constructors
     $smtp = Net::SMTP->new('mailhost');
     $smtp = Net::SMTP->new('mailhost', Timeout => 60);

DESCRIPTION
===========

   This module implements a client interface to the SMTP and ESMTP
protocol, enabling a perl5 application to talk to SMTP servers. This
documentation assumes that you are familiar with the concepts of the SMTP
protocol described in RFC821.

   A new Net::SMTP object must be created with the new method. Once this
has been done, all SMTP commands are accessed through this object.

   The Net::SMTP class is a subclass of Net::Cmd and IO::Socket::INET.

EXAMPLES
========

   This example prints the mail domain name of the SMTP server known as
mailhost:

     #!/usr/local/bin/perl -w

     use Net::SMTP;

     $smtp = Net::SMTP->new('mailhost');
     print $smtp->domain,"\n";
     $smtp->quit;

   This example sends a small message to the postmaster at the SMTP server
known as mailhost:

     #!/usr/local/bin/perl -w

     use Net::SMTP;

     $smtp = Net::SMTP->new('mailhost');

     $smtp->mail($ENV{USER});
     $smtp->to('postmaster');

     $smtp->data();
     $smtp->datasend("To: postmaster\n");
     $smtp->datasend("\n");
     $smtp->datasend("A simple test message\n");
     $smtp->dataend();

     $smtp->quit;

CONSTRUCTOR
===========

new Net::SMTP [ HOST, ] [ OPTIONS ]
     This is the constructor for a new Net::SMTP object. `HOST' is the
     name of the remote host to which a SMTP connection is required.

     If `HOST' is not given, then the `SMTP_Host' specified in
     `Net::Config' will be used.

     OPTIONS are passed in a hash like fashion, using key and value pairs.
     Possible options are:

     Hello - SMTP requires that you identify yourself. This option
     specifies a string to pass as your mail domain. If not given a guess
     will be taken.

     Timeout - Maximum time, in seconds, to wait for a response from the
     SMTP server (default: 120)

     Debug - Enable debugging information

     Example:

          $smtp = Net::SMTP->new('mailhost',
          			   Hello => 'my.mail.domain'
          			   Timeout => 30,
                                 Debug   => 1,
          			  );

METHODS
=======

   Unless otherwise stated all methods return either a *true* or false
value, with *true* meaning that the operation was a success. When a method
states that it returns a value, failure will be returned as undef or an
empty list.

banner ()
     Returns the banner message which the server replied with when the
     initial connection was made.

domain ()
     Returns the domain that the remote SMTP server identified itself as
     during connection.

hello ( DOMAIN )
     Tell the remote server the mail domain which you are in using the EHLO
     command (or HELO if EHLO fails).  Since this method is invoked
     automatically when the Net::SMTP object is constructed the user should
     normally not have to call it manually.

etrn ( DOMAIN )
     Request a queue run for the DOMAIN given.

mail ( ADDRESS [, OPTIONS] )
send ( ADDRESS )
send_or_mail ( ADDRESS )
send_and_mail ( ADDRESS )
     Send the appropriate command to the server MAIL, SEND, SOML or SAML.
     `ADDRESS' is the address of the sender. This initiates the sending of
     a message. The method recipient should be called for each address
     that the message is to be sent to.

     The mail method can some additional ESMTP OPTIONS which is passed in
     hash like fashion, using key and value pairs.  Possible options are:

          Size        => <bytes>
          Return      => <???>
          Bits        => "7" | "8"
          Transaction => <ADDRESS>
          Envelope    => <ENVID>

reset ()
     Reset the status of the server. This may be called after a message
     has been initiated, but before any data has been sent, to cancel the
     sending of the message.

recipient ( ADDRESS [, ADDRESS [ ...]] [, OPTIONS ] )
     Notify the server that the current message should be sent to all of
     the addresses given. Each address is sent as a separate command to
     the server.  Should the sending of any address result in a failure
     then the process is aborted and a false value is returned. It is up
     to the user to call reset if they so desire.

     The recipient method can some additional OPTIONS which is passed in
     hash like fashion, using key and value pairs.  Possible options are:

          Notify    =>
          SkipBad   => ignore bad addresses

     If `SkipBad' is true the recipient will not return an error when a
     bad address is encountered and it will return an array of addresses
     that did succeed.

to ( ADDRESS [, ADDRESS [...]] )
     A synonym for recipient.

data ( [ DATA ] )
     Initiate the sending of the data from the current message.

     DATA may be a reference to a list or a list. If specified the contents
     of DATA and a termination string `".\r\n"' is sent to the server. And
     the result will be true if the data was accepted.

     If DATA is not specified then the result will indicate that the server
     wishes the data to be sent. The data must then be sent using the
     datasend and dataend methods described in Net/Cmd.

expand ( ADDRESS )
     Request the server to expand the given address Returns an array which
     contains the text read from the server.

verify ( ADDRESS )
     Verify that `ADDRESS' is a legitimate mailing address.

help ( [ $subject ] )
     Request help text from the server. Returns the text or undef upon
     failure

quit ()
     Send the QUIT command to the remote SMTP server and close the socket
     connection.

SEE ALSO
========

   See Net/Cmd,

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

COPYRIGHT
=========

   Copyright (c) 1995-1997 Graham Barr. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

A native Perl SMTP Server implementation for Perl.
**************************************************

NAME
====

   Net::SMTP::Server - A native Perl SMTP Server implementation for Perl.

SYNOPSIS
========

     use Carp;
     use Net::SMTP::Server;
     use Net::SMTP::Server::Client;
     use Net::SMTP::Server::Relay;

     $server = new Net::SMTP::Server('localhost', 25) ||
       croak("Unable to handle client connection: $!\n");

     while($conn = $server->accept()) {
       # We can perform all sorts of checks here for spammers, ACLs,
       # and other useful stuff to check on a connection.

     # Handle the client's connection and spawn off a new parser.
     # This can/should be a fork() or a new thread,
     # but for simplicity...
     my $client = new Net::SMTP::Server::Client($conn) ||
     	croak("Unable to handle client connection: $!\n");

     # Process the client.  This command will block until
     # the connecting client completes the SMTP transaction.
     $client->process || next;

     # In this simple server, we're just relaying everything
     # to a server.  If a real server were implemented, you
     # could save email to a file, or perform various other
     # actions on it here.
     my $relay = new Net::SMTP::Server::Relay($client->{FROM},
     					     $client->{TO},
     					     $client->{MSG});
       }

DESCRIPTION
===========

   The Net::SMTP::Server module implements an RFC 821 compliant SMTP
server, completely in Perl.  It's extremely extensible, so adding in
things like spam filtering, or more advanced routing and handling features
can be easily handled.  An additional module, Net::SMTP::Server::Relay has
also been implemented as an example of just one application of this
extensibility.  See the pod for more details on that module.  This
extension has been tested on both Unix and Win32 platforms.

   Creating a new server is as trivial as:

     $server = new Net::SMTP::Server($host, $port);

   This creates a new SMTP::Server.  Both $host and $port are optional,
and default to the current hostname and the standard SMTP port (25).
However, if you run on a multi-homed machine, you may want to explicitly
specify which interface to bind to.

   The server loop should look something like this:

     while($conn = $server->accept()) {
       my $client = new Net::SMTP::Server::Client($conn) ||
     	croak("Unable to handle client connection: $!\n");

     $client->process;
       }

   The server will continue to accept connections forever.  Once we have a
connection, we create a new Net::SMTP::Server::Client.  This is a new
client connection that will now be handled.  The reason why processing
doesn't begin here is to allow for any extensibility or hooks a user may
want to add in after we've accepted the client connection, but before we
give the initial welcome message to the client.  Once we're ready to
process an SMTP session, we call $client->process.  This may HANG while
the SMTP transaction takes place, as the client and server are
communicating back and forth (and if there's a lot of data to transmit,
well...).

   Once $client->process returns, various fields have been filled in.
Those are:

     $client->{TO}    -- This is an array containing the intended
                         recipients for this message.  There may be
                         multiple recipients for any given message.

     $client->{FROM}  -- This is the sender of the given message.
     $client->{MSG}   -- The actual message data. :)

   The SMTP::Server module performs no other processing for the user.
It's meant to give you the building blocks of an extensible SMTP server
implementation.  For example, using the MIME modules, you can easily
process $client->{MSG} to handle MIME attachments, etc.  Or you could
implement ACLs to control who can connect to the server, or what actions
are taken.  Finally, a suggested use that the author himself uses, is as
an SMTP relay.  There are lots of times I need access to an SMTP server
just to send a message, but don't have access to one for whatever reason
(firewalls, permissions, etc).  You can run your own SMTP server whether
under Unix or Win32 environments, and simply point your favorite mail
client to it when sending messages.  See the Net::SMTP::Server::Relay
modules for details on that use.

AUTHOR AND COPYRIGHT Net::SMTP::Server / SMTP::Server is Copyright(C) 1999,   MacGyver (aka Habeeb J. Dihu) <macgyver@tos.net>.  ALL RIGHTS RESERVED.
=====================================================================================================================================================

   You may distribute this package under the terms of either the GNU
General Public License or the Artistic License, as specified in the Perl
README file.

SEE ALSO
========

   Net::SMTP::Server::Client, Net::SMTP::Server::Relay

Client session handling for Net::SMTP::Server.
**********************************************

NAME
====

   Net::SMTP::Server::Client - Client session handling for
Net::SMTP::Server.

SYNOPSIS
========

     use Carp;
     use Net::SMTP::Server;
     use Net::SMTP::Server::Client;
     use Net::SMTP::Server::Relay;

     $server = new Net::SMTP::Server('localhost', 25) ||
       croak("Unable to handle client connection: $!\n");

     while($conn = $server->accept()) {
       # We can perform all sorts of checks here for spammers, ACLs,
       # and other useful stuff to check on a connection.

     # Handle the client's connection and spawn off a new parser.
     # This can/should be a fork() or a new thread,
     # but for simplicity...
     my $client = new Net::SMTP::Server::Client($conn) ||
     	croak("Unable to handle client connection: $!\n");

     # Process the client.  This command will block until
     # the connecting client completes the SMTP transaction.
     $client->process || next;

     # In this simple server, we're just relaying everything
     # to a server.  If a real server were implemented, you
     # could save email to a file, or perform various other
     # actions on it here.
     my $relay = new Net::SMTP::Server::Relay($client->{FROM},
     					     $client->{TO},
     					     $client->{MSG});
       }

DESCRIPTION
===========

   The Net::SMTP::Server::Client module implements all the session
handling required for a Net::SMTP::Server::Client connection.  The above
example demonstrates how to use Net::SMTP::Server::Client with
Net::SMTP::Server to handle SMTP connections.

   $client = new Net::SMTP::Server::Client($conn)

   Net::SMTP::Server::Client accepts one argument that must be a handle to
a connection that will be used for communication.

   Once you have a new client session, simply call:

   $client->process

   This processes an SMTP transaction.  THIS MAY APPEAR TO HANG -
ESPECIALLY IF THERE IS A LARGE AMOUNT OF DATA BEING SENT.  Once this
method returns, the server will have processed an entire SMTP transaction,
and is ready to continue.

   Once $client->process returns, various fields have been filled in.
Those are:

     $client->{TO}    -- This is an array containing the intended
                         recipients for this message.  There may be
                         multiple recipients for any given message.

     $client->{FROM}  -- This is the sender of the given message.
     $client->{MSG}   -- The actual message data. :)

AUTHOR AND COPYRIGHT Net::SMTP::Server / SMTP::Server is Copyright(C) 1999,    MacGyver (aka Habeeb J. Dihu) <macgyver@tos.net>.  ALL RIGHTS RESERVED.
======================================================================================================================================================

   You may distribute this package under the terms of either the GNU
General Public License or the Artistic License, as specified in the Perl
README file.

SEE ALSO
========

   Net::SMTP::Server::Server, Net::SMTP::Server::Relay

A simple relay module for Net::SMTP::Server.
********************************************

NAME
====

   Net::SMTP::Server::Relay - A simple relay module for Net::SMTP::Server.

SYNOPSIS
========

     use Carp;
     use Net::SMTP::Server;
     use Net::SMTP::Server::Client;
     use Net::SMTP::Server::Relay;

     $server = new Net::SMTP::Server('localhost', 25) ||
       croak("Unable to handle client connection: $!\n");

     while($conn = $server->accept()) {
       # We can perform all sorts of checks here for spammers, ACLs,
       # and other useful stuff to check on a connection.

     # Handle the client's connection and spawn off a new parser.
     # This can/should be a fork() or a new thread,
     # but for simplicity...
     my $client = new Net::SMTP::Server::Client($conn) ||
     	croak("Unable to handle client connection: $!\n");

     # Process the client.  This command will block until
     # the connecting client completes the SMTP transaction.
     $client->process || next;

     # In this simple server, we're just relaying everything
     # to a server.  If a real server were implemented, you
     # could save email to a file, or perform various other
     # actions on it here.
     my $relay = new Net::SMTP::Server::Relay($client->{FROM},
     					     $client->{TO},
     					     $client->{MSG});
       }

DESCRIPTION
===========

   The Net::SMTP::Server::Relay module implements simple SMTP relaying for
use with the Net::SMTP::Server module.  All this module does is to take a
given message and iterate through the list of recipients, doing DNS
lookups for the associated MX record and delivering the messages.  This
module makes extensive use of the plethora of other modules already
implemented for Perl (specifically the DNS and Net::SMTP modules in this
case), and should give but a glimpse of the potential for extending the
Net::SMTP::Server's functionality to provide a full-featured SMTP server,
native to Perl.

   The above example illustrates the use of the Net::SMTP::Server::Relay
modules - you simply have to instantiate the module, passing along the
sender, recipients, and message.  More formally:

     $relay = new Net::SMTP::Server::Relay($from, @to, $msg);

   Where $from is the sender, @to is an array containing the list of
recipients, and $msg is the message to relay.

AUTHOR AND COPYRIGHT Net::SMTP::Server / SMTP::Server is Copyright(C) 1999,    MacGyver (aka Habeeb J. Dihu) <macgyver@tos.net>.  ALL RIGHTS RESERVED.
======================================================================================================================================================

   You may distribute this package under the terms of either the GNU
General Public License or the Artistic License, as specified in the Perl
README file.

SEE ALSO
========

   Net::SMTP::Server::Server, Net::SMTP::Server::Client

Simple Network Management Protocol
**********************************

NAME
====

   Net::SNMP - Simple Network Management Protocol

SYNOPSIS
========

   The module Net::SNMP implements an object oriented interface to the
Simple Network Management Protocol.  Perl applications can use the module
to retrieve or update information on a remote host using the SNMP
protocol. Net::SNMP is implemented completely in Perl, requires no
compiling, and uses only standard Perl modules. Both SNMPv1 and SNMPv2c
(Community-Based SNMPv2) are supported by the module. The Net::SNMP module
assumes that the user has a basic understanding of the Simple Network
Management Protocol and related network management concepts.

DESCRIPTION
===========

   The module Net::SNMP abstracts the intricate details of the Simple
Network Management Protocol by providing a high level programming
interface to the protocol.  Each Net::SNMP object provides a one-to-one
mapping between a Perl object and a remote SNMP agent or manager.  Once an
object is created, it can be used to perform all of the basic protocol
exchange actions defined by SNMP.

   A Net::SNMP object can be created such that it has either "blocking" or
"non-blocking" properties.  By default, the methods used to send SNMP
messages do not return until the protocol exchange has completed
successfully or a timeout period has expired. This behavior gives the
object a "blocking" property because the flow of the code is stopped until
the method returns.

   The optional named argument "*-nonblocking*" can be passed to the object
constructor with a true value to give the object "non-blocking" behavior.
A method invoked by a non-blocking object queues the SNMP message and
returns immediately allowing the flow of the code to continue. The queued
SNMP messages are not sent until an event loop is entered by calling the
`snmp_event_loop()' method.  When the SNMP messages are sent, any response
to the messages invokes the subroutine defined by the user when the
message was originally queued. The event loop exits when all messages have
been removed from the queue by either receiving a response or when the
number of retries for the object has been exceeded.

Blocking Objects
----------------

   The default behavior of the methods associated with a Net::SNMP object
is to block the code flow until the method completes.  For methods that
initiate a SNMP protocol exchange requiring a response, a hash reference
containing the results of the query are returned. The undefined value is
returned by all methods when a failure has occurred. The error() method
can be used to determine the cause of the failure.

   The hash reference returned by a SNMP protocol exchange points to a hash
constructed from the VarBindList contained in the SNMP GetResponse-PDU.
The hash is created using the ObjectName and the ObjectSyntax pairs in the
VarBindList.  The keys of the hash consist of the OBJECT IDENTIFIERs in
dotted notation corresponding to each ObjectName in the VarBindList.  The
value of each hash entry is set equal to the value of the corresponding
ObjectSyntax.  This hash reference can also be retrieved using the
`var_bind_list()' method.

Non-blocking Objects
--------------------

   When a Net::SNMP object is created having non-blocking behavior, the
invocation of a method associated with the object returns immediately,
allowing the flow of the code to continue.  When a method is invoked that
would initiate a SNMP protocol exchange requiring a response, either a
true value (i.e. 0x1) is returned immediately or the undefined value is
returned if there was a failure.  The error() method can be used to
determine the cause of the failure.

Callback Argument
     Most methods associated with a non-blocking object have an optional
     named argument called "*-callback*".  The *-callback* argument
     expects a reference to a subroutine or to an array whose first
     element must be a reference to a subroutine.  The subroutine defined
     by the *-callback* option is executed when a response to a SNMP
     message is received, an error condition has occurred, or the number
     of retries for the message has been exceeded.

     When the *-callback* argument only contains a subroutine reference,
     the subroutine is evaluated passing a copy of the original Net::SNMP
     object as the only parameter.  The copy of the object has all of the
     properties that the original object had when the message was queued,
     and will also contain the results of the SNMP protocol exchange.  If
     the *-callback* argument was defined as an array reference, all
     elements in the array are passed to the subroutine after the copy of
     the Net::SNMP object.  The first element, which is required to be a
     reference to a subroutine, is removed before the remaining arguments
     are passed to that subroutine.

     Once one method is invoked with the *-callback* argument, this
     argument stays with the object and is used by any further calls to
     methods using the *-callback* option if the argument is absent.  The
     undefined value may be passed to the *-callback* argument to delete
     the callback subroutine.

     NOTE: The subroutine being passed with the *-callback* named argument
     should not cause blocking itself.  This will cause all the actions in
     the event loop to be stopped, defeating the non-blocking property of
     the Net::SNMP module.

Delay Argument
     An optional argument *-delay* can also be passed to non-blocking
     objects.  The *-delay* argument instructs the object to wait the
     number of seconds passed to the argument before excuting the method.
     The delay period starts when the event loop is entered.  The *-delay*
     parameter is applied to all methods associated with the object once
     it is specified.  The delay value must be set back to 0 seconds to
     disable the delay parameter.

   The contents of the VarBindList contained in the SNMP GetResponse-PDU
can be retrieved by calling the `var_bind_list()' method associated with
the copy of the original object.  The value returned by the
`var_bind_list()' method is a hash reference created using the ObjectName
and the ObjectSyntax pairs in the VarBindList.  The keys of the hash
consist of the OBJECT IDENTIFIERs in dotted notation corresponding to each
ObjectName in the VarBindList.  The value of each hash entry is set equal
to the value of the corresponding ObjectSyntax.  The undefined value is
returned if there has been a failure and the error() method may be used to
determine the reason.

METHODS
=======

   Most methods associated with a Net::SNMP object take different
parameters based on the "blocking" or "non-blocking" property of the
object.  When named arguments are used with methods, two different styles
are supported. All examples in this documentation use the dashed-option
style:

     $object->method(-argument => $value);

   However, the IO:: style is also allowed:

     $object->method(Argument => $value);

session() - create a new Net::SNMP object
-----------------------------------------

     ($session, $error) = Net::SNMP->session(
                             [-hostname    => $hostname,]
                             [-community   => $community,]
                             [-port        => $port,]
                             [-nonblocking => $nonblocking,]
                             [-version     => $version,]
                             [-timeout     => $seconds,]
                             [-retries     => $count,]
                             [-mtu         => $octets,]
                             [-translate   => $translate,]
                             [-debug       => $debug]
                          );

   This is the constructor for Net::SNMP objects.  In scalar context, a
reference to a new Net::SNMP object is returned if the creation of the
object is successful.  In list context, a reference to a new Net::SNMP
object and an empty error message string is returned.  If a failure
occurs, the object reference is returned as the undefined value.  The
error string may be used to determine the cause of the error.

   The *-hostname*, *-community*, *-port*, and *-nonblocking* arguments are
basic properties of a Net::SNMP object and cannot be changed after the
object is created.  All other arguments have methods that allow their
values to be modified after the Net::SNMP object has been created.  See
the methods corresponding to these named arguments for their valid ranges
and default values.

   All arguments are optional and will take default values in the absence
of a corresponding named argument.

   * The default value for the remote *-hostname* is "localhost".  The
     hostname can either be a network hostname or the dotted IP address of
     the host.

   * The default value for the SNMP *-community* name is "public".

   * The default value for the destination UDP *-port* number is 161.
     This is the port on which hosts using default values expect to
     receive all SNMP messages except for traps.  Port number 162 is the
     default port used by hosts expecting to receive SNMP traps.

   * The default value for the *-nonblocking* property is 0x0 (false).

close() - clear the UDP socket reference, buffers, and errors
-------------------------------------------------------------

     $session->close;

   This method clears the UDP socket reference, the errors, hash pointers,
and buffers associated with the object.  Once closed, the Net::SNMP object
can no longer be used to send or received SNMP messages.

snmp_event_loop() - enter the non-blocking object event loop
------------------------------------------------------------

     $session->snmp_event_loop;

   This method enters the event loop associated with non-blocking Net::SNMP
objects.  The method exits when all queued SNMP messages have been
responded to or have timed out.  This method is also exported as the stand
alone function `snmp_event_loop()' by default (see `"EXPORTS"' in this
node).

get_request() - send a SNMP get-request to the remote agent
-----------------------------------------------------------

   Blocking

     $response = $session->get_request(@oids);

   Non-blocking

     $ok = $session->get_request(
                        [-callback   => sub {},]
                        [-delay      => $seconds,]
     	         	    -varbindlist => \@oids
                     );

   This method performs a SNMP get-request query to gather data from the
remote agent on the host associated with the Net::SNMP object.  The
blocking form of the method takes a list of OBJECT IDENTIFIERs in dotted
notation. Each OBJECT IDENTIFER is placed into a single SNMP
GetRequest-PDU in the same order that it held in the original list.  When
the object is in non-blocking mode, the list is passed as an array
reference to the *-varbindlist* named argument.

   A reference to a hash is returned in blocking mode which contains the
contents of the VarBindList.  In non-blocking mode, a true value is
returned when no error has occurred.  In either mode the undefined value
is returned when an error has occurred.  The error() method may be used to
determine the cause of the failure.

get_next_request() - send a SNMP get-next-request to the remote agent
---------------------------------------------------------------------

   Blocking

     $response = $session->get_next_request(@oids);

   Non-blocking

     $ok = $session->get_next_request(
                        [-callback   => sub {},]
                        [-delay      => $seconds,]
                        -varbindlist => \@oids
                     );

   This method performs a SNMP get-next-request query to gather data from
the remote agent on the host associated with the Net::SNMP object.  The
blocking form of the method takes a list of OBJECT IDENTIFIERs in dotted
notation. Each OBJECT IDENTIFER is placed into a single SNMP
GetNextRequest-PDU in the same order that it held in the original list.
When the object is in non-blocking mode, the list is passed as an array
reference to the *-varbindlist* named argument.

   A reference to a hash is returned in blocking mode which contains the
contents of the VarBindList.  In non-blocking mode, a true value is
returned when no error has occurred.  In either mode the undefined value
is returned when an error has occurred.  The error() method may be used to
determine the cause of the failure.

set_request() - send a SNMP set-request to the remote agent
-----------------------------------------------------------

   Blocking

     $response = $session->set_request(@oid_type_value);

   Non-blocking

     $ok = $session->set_request(
                        [-callback   => sub {},]
                        [-delay      => $seconds,]
                        -varbindlist => \@oid_type_value
                     );

   This method is used to modify data on the remote agent that is
associated with the Net::SNMP object using a SNMP set-request.  The
blocking form of the method takes a list of values consisting of groups of
an OBJECT IDENTIFIER, an object type, and the actual value to be set.  The
OBJECT IDENTIFIERs in each trio are to be in dotted notation.  The object
type is a byte corresponding to the ASN.1 type of value that is to be set.
Each of the supported types have been defined and are exported by the
package by default (see `"EXPORTS"' in this node).  When the object is in
non-blocking mode, the list is passed as an array reference to the
*-varbindlist* named argument.

   A reference to a hash is returned in blocking mode which contains the
contents of the VarBindList.  In non-blocking mode, a true value is
returned when no error has occurred.  In either mode the undefined value
is returned when an error has occurred.  The error() method may be used to
determine the cause of the failure.

trap() - send a SNMP trap to the remote manager
-----------------------------------------------

   Blocking

     $value = $session->trap(
                           [-enterprise   => $oid,]
                           [-agentaddr    => $ipaddress,]
                           [-generictrap  => $generic,]
                           [-specifictrap => $specific,]
                           [-timestamp    => $timeticks,]
                           [-varbindlist  => \@oid_type_value]
                         );

   Non-blocking

     $value = $session->trap(
                           [-delay        => $seconds,]
                           [-enterprise   => $oid,]
                           [-agentaddr    => $ipaddress,]
                           [-generictrap  => $generic,]
                           [-specifictrap => $specific,]
                           [-timestamp    => $timeticks,]
                           [-varbindlist  => \@oid_type_value]
                         );

   This method sends a SNMP trap to the remote manager associated with the
Net::SNMP object.  All arguments are optional and will be given the
following defaults in the absence of a corresponding named argument:

   * The default value for the trap *-enterprise* is "1.3.6.1.4.1", which
     corresponds to "iso.org.dod.internet.private.enterprises".  The
     enterprise value is expected to be an OBJECT IDENTIFER in dotted
     notation.

   * The default value for the trap *-agentaddr* is the local IP address
     from the host on which the script is running.  The agent-addr is
     expected to be an IpAddress in dotted notation.

   * The default value for the *-generictrap* type is 6 which corresponds
     to "enterpriseSpecific".  The generic-trap types are defined and can
     be exported upon request (see `"EXPORTS"' in this node).

   * The default value for the *-specifictrap* type is 0.  No pre-defined
     values are available for specific-trap types.

   * The default value for the trap *-timestamp* is the "uptime" of the
     script.  The "uptime" of the script is the number of hundredths of
     seconds that have elapsed since the script began running.  The
     time-stamp is expected to be a TimeTicks number in hundredths of
     seconds.

   * The default value for the trap *-varbindlist* is an empty array
     reference.  The variable-bindings are expected to be in an array
     format consisting of groups of an OBJECT IDENTIFIER, an object type,
     and the actual value of the object.  This is identical to the list
     expected by the `set_request()' method.  The OBJECT IDENTIFIERs in
     each trio are to be in dotted notation.  The object type is a byte
     corresponding to the ASN.1 type for the value. Each of the supported
     types have been defined and are exported by default (see `"EXPORTS"'
     in this node).

   Upon success, the number of bytes transmitted is returned when the
object is in blocking mode.  A true value is returned when successful in
non-blocking mode.  The undefined value is returned when a failure has
occurred.  The error() method can be used to determine the cause of the
failure. Since there are no acknowledgements for Trap-PDUs, there is no
way to determine if the remote host actually received the trap.

   NOTE: When the object is in non-blocking mode, the trap is not sent
until the event loop is entered.

get_bulk_request() - send a SNMPv2 get-bulk-request to the remote agent
-----------------------------------------------------------------------

   Blocking

     $response = $session->get_bulk_request(
                              [-nonrepeaters   => $nonrepeaters,]
                              [-maxrepetitions => $maxrepetitions,]
                              -varbindlist     => \@oids
                           );

   Non-blocking

     $ok = $session->get_bulk_request(
                        [-callback       => sub {},]
                        [-delay          => $seconds,]
                        [-nonrepeaters   => $nonrepeaters,]
                        [-maxrepetitions => $maxrepetitions,]
                        -varbindlist     => \@oids
                     );

   This method performs a SNMP get-bulk-request query to gather data from
the remote agent on the host associated with the Net::SNMP object.  All
arguments are optional except *-varbindlist* and will be given the
following defaults in the absence of a corresponding named argument:

   * The default value for the get-bulk-request *-nonrepeaters* is 0.  The
     non-repeaters value specifies the number of variables in the
     variable-bindings list for which a single successor is to be returned.

   * The default value for the get-bulk-request *-maxrepetitions* is 0. The
     max-repetitions value specifies the number of successors to be
     returned for the remaining variables in the variable-bindings list.

   * The *-varbindlist* argument expects an array reference consisting of
     a list of OBJECT IDENTIFIERs in dotted notation.  Each OBJECT
     IDENTIFER is placed into a single SNMP GetBulkRequest-PDU in the same
     order that it held in the original list.

   A reference to a hash is returned in blocking mode which contains the
contents of the VarBindList.  In non-blocking mode, a true value is
returned when no error has occurred.  In either mode the undefined value
is returned when an error has occurred.  The error() method may be used to
determine the cause of the failure.

   NOTE: This method can only be used when the version of the object is
set to SNMPv2c.

inform_request() - send a SNMPv2 inform-request to the remote manager
---------------------------------------------------------------------

   Blocking

     $response = $session->inform_request(@oid_type_value);

   Non-blocking

     $ok = $session->inform_request(
                        [-callback   => sub {},]
                        [-delay      => $seconds,]
                        -varbindlist => \@oid_type_value
                     );

   This method is used to provide management information to the remote
manager associated with the Net::SNMP object using a SNMPv2
inform-request.  In blocking mode, the method takes a list of values
consisting of groups of an OBJECT IDENTIFIER, an object type, and the
actual value to be defined.  The OBJECT IDENTIFIERs in each trio are to be
in dotted notation.  The object type is a byte corresponding to the ASN.1
type of value that is identified. Each of the supported types have been
defined and are exported by the package by default (see `"EXPORTS"' in
this node).  When the object is in non-blocking mode, the list is passed
as an array reference to the *-varbindlist* named argument.

   The first two variable-bindings fields in the inform-request are
specified by SNMPv2 and should be:

   * sysUpTime.0 - ['1.3.6.1.2.1.1.3.0', TIMETICKS, $timeticks]

   * snmpTrapOID.0 - ['1.3.6.1.6.3.1.1.4.1.0', OBJECT_IDENTIFIER, $oid]

   A reference to a hash is returned in blocking mode which contains the
contents of the VarBindList.  In non-blocking mode, a true value is
returned when no error has occurred.  In either mode the undefined value
is returned when an error has occurred.  The error() method may be used to
determine the cause of the failure.

   NOTE: This method can only be used when the version of the object is
set to SNMPv2c.

snmpv2_trap() - send a SNMPv2 snmpV2-trap to the remote manager
---------------------------------------------------------------

   Blocking

     $response = $session->snmpv2_trap(@oid_type_value);

   Non-blocking

     $ok = $session->snmpv2_trap(
                        [-delay      => $seconds,]
                        -varbindlist => \@oid_type_value
                     );

   This method sends a SNMPv2 snmpV2-trap to the remote manager associated
with the Net::SNMP object. In blocking mode, the method takes a list of
values consisting of groups of an OBJECT IDENTIFIER, an object type, and
the actual value to be defined. The OBJECT IDENTIFIERs in each trio are to
be in dotted notation.  The object type is a byte corresponding to the
ASN.1 type of value that is identified. Each of the supported types have
been defined and are exported by the package by default (see `"EXPORTS"'
in this node).  When the object is in non-blocking mode, the list is
passed as an array reference to the *-varbindlist* named argument.

   The first two variable-bindings fields in the snmpV2-trap are specified
by SNMPv2 and should be:

   * sysUpTime.0 - ['1.3.6.1.2.1.1.3.0', TIMETICKS, $timeticks]

   * snmpTrapOID.0 - ['1.3.6.1.6.3.1.1.4.1.0', OBJECT_IDENTIFIER, $oid]

   Upon success, the number of bytes transmitted is returned when the
object is in blocking mode.  A true value is returned when in successful
in non-blocking mode.  The undefined value is returned when a failure has
occurred.  The error() method can be used to determine the cause of the
failure. Since there are no acknowledgements for SNMPv2-Trap-PDUs, there
is no way to determine if the remote host actually received the
snmpV2-trap.

   NOTE: This method can only be used when the version of the object is
set to SNMPv2c.

   NOTE: When the object is in non-blocking mode, the snmpV2-trap is not
sent until the event loop is entered.

get_table() - retrieve a table from the remote agent
----------------------------------------------------

   Blocking

     $response = $session->get_table($oid);

   Non-blocking

     $ok = $session->get_table(
                        -baseoid   => $oid,
                        [-callback => sub {},]
                        [-delay    => $seconds]
                     );

   This method performs repeated SNMP get-next-request or get-bulk-request
(when using SNMPv2c) queries to gather data from the remote agent on the
host associated with the Net::SNMP object.  In blocking mode, the method
takes a single OBJECT IDENTIFIER which is used as the base object for the
SNMP requests.  Repeated SNMP requests are issued until the OBJECT
IDENTIFER in the response is no longer a subtree of the base OBJECT
IDENTIFIER.  When the object is in non-blocking mode, the OBJECT
IDENTIFIER must be passed to the *-baseoid* named argument.

   A reference to a hash is returned in blocking mode which contains the
contents of the VarBindList.  In non-blocking mode, a true value is
returned when no error has occurred.  In either mode the undefined value
is returned when an error has occurred.  The error() method may be used to
determine the cause of the failure.

   WARNING: Results from this method can become very large if the base
OBJECT IDENTIFIER is close to the root of the SNMP MIB tree.

version() - set or get the SNMP version for the object
------------------------------------------------------

     $rfc_version = $session->version([$version]);

   This method is used to set or get the current SNMP version associated
with the Net::SNMP object.  The module supports SNMP version-1 (SNMPv1)
and SNMP version-2c (SNMPv2c).  The default version used by the module is
SNMP version-1.

   The method accepts the digit '1' or the string 'SNMPv1' for SNMP
version-1 and the digit '2', or the strings '2c', 'SNMPv2', or 'SNMPv2c'
for SNMP version-2c.  The undefined value is returned upon an error and
the error() method may be used to determine the cause.

   The method returns the current value for the SNMP version.  The
returned value is the corresponding version number defined by the RFCs for
the protocol version field (i.e. SNMPv1 == 0 and SNMPv2c == 1).

error() - get the current error message from the object
-------------------------------------------------------

     $error_message = $session->error;

   This method returns a text string explaining the reason for the last
error.  An empty string is returned if no error has occurred.

hostname() - get the associated hostname from the object
--------------------------------------------------------

     $hostname = $session->hostname;

   This method returns the hostname string that is associated with the
object.

error_status() - get the current SNMP error-status from the object
------------------------------------------------------------------

     $error_status = $session->error_status;

   This method returns the numeric value of the error-status contained in
the last SNMP GetResponse-PDU.

error_index() - get the current SNMP error-index from the object
----------------------------------------------------------------

     $error_index = $session->error_index;

   This method returns the numeric value of the error-index contained in
the last SNMP GetResponse-PDU.

var_bind_list() - get the hash reference to the last SNMP response
------------------------------------------------------------------

     $response = $session->var_bind_list;

   This method returns a hash reference created using the ObjectName and
the ObjectSyntax pairs in the VarBindList of the last SNMP GetResponse-PDU
received by the object. The keys of the hash consist of the OBJECT
IDENTIFIERs in dotted notation corresponding to each ObjectName in the
VarBindList.  If any OBJECT IDENTIFIERs passed to the method began with a
leading dot, all of the OBJECT IDENTIFIER hash keys will be prefixed with
a leading dot.  The value of each hash entry is set equal to the value of
the corresponding ObjectSyntax.  The undefined value is returned if there
has been a failure and the error() method may be used to determine the
reason.

timeout() - set or get the current timeout period for the object
----------------------------------------------------------------

     $seconds = $session->timeout([$seconds]);

   This method returns the current value for the UDP timeout for the
Net::SNMP object.  This value is the number of seconds that the object
will wait for a response from the agent on the remote host.  The default
timeout is 5.0 seconds.

   If a parameter is specified, the timeout for the object is set to the
provided value if it falls within the range 1.0 to 60.0 seconds.  The
undefined value is returned upon an error and the error() method may be
used to determine the cause.

retries() - set or get the current retry count for the object
-------------------------------------------------------------

     $count = $session->retries([$count]);

   This method returns the current value for the number of times to retry
sending a SNMP message to the remote host.  The default number of retries
is 1.

   If a parameter is specified, the number of retries for the object is
set to the provided value if it falls within the range 0 to 20. The
undefined value is returned upon an error and the error() method may be
used to determine the cause.

mtu() - set or get the current MTU for the object
-------------------------------------------------

     $octets = $session->mtu([$octets]);

   This method returns the current value for the Maximum Transport Unit
for the Net::SNMP object.  This value is the largest value in octets for
an SNMP message that can be transmitted or received by the object.  The
default MTU is 1500 octets.

   If a parameter is specified, the Maximum Transport Unit is set to the
provided value if it falls within the range 484 to 65535 octets.  The
undefined value is returned upon an error and the error() method may be
used to determine the cause.

translate() - enable or disable the translation mode for the object
-------------------------------------------------------------------

     $mask = $session->translate([$mode]);

     or

     $mask = $session->translate([
                          [ # Perl anonymous ARRAY reference
                             ['-all'            => $mode1,]
                             ['-octetstring     => $mode2,]
                             ['-null'           => $mode3,]
                             ['-timeticks'      => $mode4,]
                             ['-opaque'         => $mode5,]
                             ['-nosuchobject'   => $mode6,]
                             ['-nosuchinstance' => $mode7,]
                             ['-endofmibview'   => $mode8]
                          ]
                       ]);

   When the object decodes the GetResponse-PDU that is returned in
response to a SNMP message, certain values are translated into a more
"human readable" form.  By default the following translations occur:

   * OCTET STRINGs and Opaques containing non-printable characters are
     converted into a hexadecimal representation prefixed with "0x".

   * TimeTicks integer values are converted to a time format.

   * NULL values return the string "NULL" instead of an empty string.

   * noSuchObject exception values return the string "noSuchObject"
     instead of an empty string.  If translation is not enabled, the SNMP
     error-status field is set to 128 which is equal to the exported
     definition NOSUCHOBJECT (see `"EXPORTS"' in this node).

   * noSuchInstance exception values return the string "noSuchInstance"
     instead of an empty string.  If translation is not enabled, the SNMP
     error-status field is set to 129 which is equal to the exported
     definition NOSUCHINSTANCE (see `"EXPORTS"' in this node).

   * endOfMibView exception values return the string "endOfMibView"
     instead of an empty string.  If translation is not enabled, the SNMP
     error-status field is set to 130 which is equal to the exported
     definition ENDOFMIBVIEW (see `"EXPORTS"' in this node).

   The `translate()' method can be invoked with two different types of
arguments.

   If the argument passed is any Perl variable type except an array
reference, the translation mode for all ASN.1 type is set to either
enabled or disabled depending on the value of the passed parameter.  Any
value that Perl would treat as a true value will set the mode to be
enabled for all types, while a false value will disable translation for
all types.

   A reference to an array can be passed to the `translate()' method in
order to defined the translation mode on a per ASN.1 type basis.  The
array is expected to contain a list of named argument pairs for each ASN.1
type that is to be modified.  The arguments in the list are applied in the
order that they are passed in via the array.  Arguments at the end of the
list supercede those passed earlier in the list.  The argument "-all" can
be used to specify that the mode is to apply to all ASN.1 types.  Only the
arguments for the ASN.1 types that are to be modified need to be included
in the list.

   The `translate()' method returns a bit mask indicating which ASN.1 types
are to be translated.  Definitions of the bit to ASN.1 type mappings can be
exported using the ":translate" tag (see `"EXPORTS"' in this node).  The
undefined value is returned upon an error and the error() method may be
used to determine the cause.

debug() - set or get the debug mode for the module
--------------------------------------------------

     $mode = $session->debug([$mode]);

   This method is used to enable or disable debugging for the Net::SNMP
module. By default, debugging is off.  If a parameter is specified, the
debug mode is set to either enabled or disabled depending on the value of
the passed parameter.  Any value that Perl would treat as a true value
will set the mode to be enabled, while a false value will disable
debugging.  The current state of the debugging mode is returned by the
method.  Debugging can also be enabled using the stand along function
`snmp_debug()'.  This function can be exported by request (see `"EXPORTS"'
in this node).

FUNCTIONS
=========

oid_context_match() - determine if an OID has a specified MIB context
---------------------------------------------------------------------

     $value = oid_context_match($base_oid, $oid);

   This function takes two OBJECT IDENTIFIERs in dotted notation and
returns a true value (i.e. 0x1) if the second OBJECT IDENTIFIER is equal
to or is a subtree of the first OBJECT IDENTIFIER in the SNMP Management
Information Base (MIB).  This function can be used in conjunction with the
`get-next-request()' or `get-bulk-request()' methods to determine when a
OBJECT IDENTIFIER in the GetResponse-PDU is no longer in the desired MIB
context.

oid_lex_sort() - sort a list of OBJECT IDENTIFIERs lexicographically
--------------------------------------------------------------------

     @sorted_oids = oid_lex_sort(@oids);

   This function takes a list of OBJECT IDENTIFIERs in dotted notation and
returns the listed sorted in lexicographical order.

ticks_to_time() - convert TimeTicks to formatted time
-----------------------------------------------------

     $time = ticks_to_time($timeticks);

   This function takes an ASN.1 TimeTicks value and returns a string
representing the time defined by the value.  The TimeTicks value is
expected to be a non-negative integer value representing the time in
hundredths of a second since some epoch.  The returned string will display
the time in days, hours, and seconds format according to the value of the
TimeTicks argument.

EXPORTS
=======

Default
     INTEGER, INTEGER32, OCTET_STRING, NULL, OBJECT_IDENTIFIER, IPADDRESS,
     COUNTER, COUNTER32, GAUGE, GAUGE32, UNSIGNED32, TIMETICKS, OPAQUE,
     COUNTER64, NOSUCHOBJECT, NOSUCHINSTANCE, ENDOFMIBVIEW, snmp_event_loop

Exportable
     INTEGER, INTEGER32, OCTET_STRING, NULL, OBJECT_IDENTIFIER, SEQUENCE,
     IPADDRESS, COUNTER, COUNTER32, GAUGE, GAUGE32, UNSIGNED32, TIMETICKS,
     OPAQUE, COUNTER64, NOSUCHOBJECT, NOSUCHINSTANCE, ENDOFMIBVIEW,
     GET_REQUEST, GET_NEXT_REQUEST, GET_RESPONSE, SET_REQUEST, TRAP,
     GET_BULK_REQUEST, INFORM_REQUEST, SNMPV2_TRAP, COLD_START,
     WARM_START, LINK_DOWN, LINK_UP, AUTHENTICATION_FAILURE,
     EGP_NEIGHBOR_LOSS, ENTERPRISE_SPECIFIC, SNMP_VERSION_1,
     SNMP_VERSION_2C, SNMP_PORT, SNMP_TRAP_PORT, snmp_debug,
     snmp_event_loop, oid_context_match, oid_lex_sort, ticks_to_time,
     TRANSLATE_NONE, TRANSLATE_OCTET_STRING, TRANSLATE_NULL,
     TRANSLATE_TIMETICKS, TRANSLATE_OPAQUE, TRANSLATE_NOSUCHOBJECT,
     TRANSLATE_NOSUCHINSTANCE, TRANSLATE_ENDOFMIBVIEW, TRANSLATE_ALL

Tags

    :asn1
          INTEGER, INTEGER32, OCTET_STRING, NULL, OBJECT_IDENTIFIER,
          SEQUENCE, IPADDRESS, COUNTER, COUNTER32, GAUGE, GAUGE32,
          UNSIGNED32, TIMETICKS, OPAQUE, COUNTER64, NOSUCHOBJECT,
          NOSUCHINSTANCE, ENDOFMIBVIEW, GET_REQUEST, GET_NEXT_REQUEST,
          GET_RESPONSE, SET_REQUEST, TRAP, GET_BULK_REQUEST,
          INFORM_REQUEST, SNMPV2_TRAP

    :generictrap
          COLD_START, WARM_START, LINK_DOWN, LINK_UP,
          AUTHENTICATION_FAILURE, EGP_NEIGHBOR_LOSS, ENTERPRISE_SPECIFIC

    :snmp
          SNMP_VERSION_1, SNMP_VERSION_2C, SNMP_PORT, SNMP_TRAP_PORT,
          snmp_debug, snmp_event_loop, oid_context_match, oid_lex_sort,
          ticks_to_time

    :translate
          TRANSLATE_NONE, TRANSLATE_OCTET_STRING, TRANSLATE_NULL,
          TRANSLATE_TIMETICKS, TRANSLATE_OPAQUE, TRANSLATE_NOSUCHOBJECT,
          TRANSLATE_NOSUCHINSTANCE, TRANSLATE_ENDOFMIBVIEW, TRANSLATE_ALL

    :ALL
          All of the above exportable items.

EXAMPLES
========

Blocking get-request for sysUpTime
----------------------------------

   This example gets the sysUpTime from a remote host:

     #! /usr/local/bin/perl

     use strict;
     use vars qw($session $error $response);

     use Net::SNMP;

     ($session, $error) = Net::SNMP->session(
        -hostname  => shift || 'localhost',
        -community => shift || 'public',
        -port      => shift || 161
     );

     if (!defined($session)) {
        printf("ERROR: %s.\n", $error);
        exit 1;
     }

     my $sysUpTime = '1.3.6.1.2.1.1.3.0';

     if (!defined($response = $session->get_request($sysUpTime))) {
        printf("ERROR: %s.\n", $session->error());
        $session->close();
        exit 1;
     }

     printf("sysUpTime for host '%s' is %s\n",
        $session->hostname(),
        $response->{$sysUpTime}
     );

     $session->close();

     exit 0;

Blocking set-request of sysContact
----------------------------------

   This example sets the sysContact information on the remote host to
"Help Desk":

     #! /usr/local/bin/perl

     use strict;
     use vars qw($session $error $response);

     use Net::SNMP;

     ($session, $error) = Net::SNMP->session(
        -hostname  => shift || 'localhost',
        -community => shift || 'private',
        -port      => shift || 161
     );

     if (!defined($session)) {
        printf("ERROR: %s.\n", $error);
        exit 1;
     }

     my $sysContact = '1.3.6.1.2.1.1.4.0';
     my $contact    = 'Help Desk';

     $response = $session->set_request($sysContact, OCTET_STRING, $contact);

     if (!defined($response)) {
        printf("ERROR: %s.\n", $session->error());
        $session->close();
        exit 1;
     }

     printf("sysContact for host '%s' set to '%s'\n",
        $session->hostname(),
        $response->{$sysContact}
     );

     $session->close();

     exit 0;

Non-blocking get-request for sysUpTime on multiple hosts
--------------------------------------------------------

   This example polls several hosts for their sysUpTime using non-blocking
objects and reports a warning if this value is less than the value from
the last poll:

     #! /usr/local/bin/perl

     use strict;
     use vars qw(@hosts @sessions $polls $last_poll_time $sleep);

     use Net::SNMP qw(snmp_event_loop ticks_to_time);

     # List of hosts to poll
     @hosts = qw(1.1.1.1 1.1.1.2 localhost);

     # Poll interval (in seconds).  This value should be greater than
     # the number of retries times the timeout value.
     my $interval = 60;

     # Maximum number of polls
     my $max_polls = 10;

     # Create a session for each host
     foreach (@hosts) {
        my ($session, $error) = Net::SNMP->session(
           -hostname    => $_,
           -nonblocking => 0x1,   # Create non-blocking objects
           -translate   => [
              -timeticks => 0x0   # Turn off so sysUpTime is numeric
           ]
        );
        if (!defined($session)) {
           printf("ERROR: %s.\n", $error);
           foreach (@sessions) { $_->[0]->close(); }
           exit 1;
        }

     # Create an array of arrays which contain the new
     # object and the last sysUpTime.

     push(@sessions, [$session, 0]);
        }

     my $sysUpTime = '1.3.6.1.2.1.1.3.0';

     while (++$polls <= $max_polls) {

     $last_poll_time = time();

     # Queue each of the queries for sysUpTime
     foreach (@sessions) {
        $_->[0]->get_request(
            -varbindlist => [$sysUpTime],
            -callback    => [\&validate_sysUpTime_cb, \$_->[1]]
        );
     }

     # Enter the event loop
     snmp_event_loop();

     # Sleep until the next poll time
     $sleep = $interval - (time() - $last_poll_time);
     if (($sleep < 1) || ($polls >= $max_polls)) { next; }
     sleep($sleep);

     print "\n";
        }

     # Not necessary, but it is nice to clean up after yourself
     foreach (@sessions) { $_->[0]->close(); }

     exit 0;

     sub validate_sysUpTime_cb
     {
        my ($this, $last_uptime) = @_;

     if (!defined($this->var_bind_list())) {
        printf("%-15s  ERROR: %s\n", $this->hostname(), $this->error());
     } else {
        my $uptime = $this->var_bind_list()->{$sysUpTime};
        if ($uptime < ${$last_uptime}) {
           printf("%-15s  WARNING: %s is less than %s\n",
              $this->hostname(),
              ticks_to_time($uptime),
              ticks_to_time(${$last_uptime})
           );
        } else {
           printf("%-15s  Ok (%s)\n",
              $this->hostname(),
              ticks_to_time($uptime)
           );
        }
        # Store the new sysUpTime
        ${$last_uptime} = $uptime;
     }

     $this->error_status();
        }

AUTHOR
======

   David M. Town <david.town@marconi.com>

ACKNOWLEDGMENTS
===============

   The original concept for this module was based on `SNMP_Session.pm'
written by Simon Leinen <simon@switch.ch>.

   The Abstract Syntax Notation One (ASN.1) encode and decode methods were
derived by example from the CMU SNMP package whose copyright follows:
Copyright (c) 1988, 1989, 1991, 1992 by Carnegie Mellon University.  All
rights reserved.

COPYRIGHT
=========

   Copyright (c) 1998-2000 David M. Town.  All rights reserved.  This
program is free software; you may redistribute it and/or modify it under
the same terms as Perl itself.

provide simple methods to gain interface data via
*************************************************

NAME
====

   Net::SNMP::Interfaces - provide simple methods to gain interface data
via

   SNMP

SYNOPSIS
========

     use Net::SNMP::Interfaces;

     my $interfaces = Net::SNMP::Interfaces->new(Hostname => 'localhost',
                                                 Community => 'public' );

     my @ifnames = $interfaces->all_interfaces();

DESCRIPTION
===========

   Net::SNMP::Interfaces aims to provide simple object methods to obtain
information about a host's network interfaces ( be it a server a router or
whatever ).  The motivation was largely to allow a programmer to use SNMP
to obtain this information without needing to know a great deal about the
gory details.

   The module uses Net::SNMP under the hood to do the dirty work although
the user shouldn't have to worry about that ( the Net::SNMP object is
available though for those who might feel the need ).

   The actual details for a particular interface are obtained from the
methods of Net::SNMP::Interfaces::Details - objects of which type can be
obtained for the methods all_interfaces() and interface().

   Of course the simpler interface has its limitations and there may well
be things that you would like to do which you cant do with this module -
in which case I would recommend that you get a good book on SNMP and use
Net::SNMP :)

   The module uses blocking SNMP requests at the current time so if some
of the methods are taking too long you may want to time them out yourself
using alarm().

METHODS
-------

new(  HASH %args )
     The constructor of the class. It takes three arguments that are passed
     to Net::SNMP :

    Hostname
          The name of the host which you want to connect to. Defaults to
          'localhost'.

    Community
          The SNMP community string which you want to use for this
          session.  The default is 'public'.

    Port
          The UDP port that the SNMP service is listening on.  The default
          is 161.

     There is a also a fourth optional argument 'RaiseError' which
     determines the behaviour of the module in the event there is an error
     while creating the SNMP.  Normally new() will return undef if there
     was an error but if RaiseError is set to a true value it will die()
     printing the error string to STDERR.

     Because the interfaces are discovered in the constructor, if the
     module is to be used in a long running program to monitor a host where
     interfaces might be added or removed it is recommended that the object
     returned by new() is periodically destroyed and a new one constructed.

if_names()
     Returns a list of the interface names.

if_indices()
     Returns a list of the indices of the interfaces - this probably
     shouldn't be necessary but is here for completeness anyway.  If you
     dont know what the index is for you are safe to ignore this.

error()
     Returns the text of the last Net::SNMP error.  This method only makes
     sense if the previous method call indicated an error by a false
     return.

session()
     Returns the Net::SNMP session object for this instance. Or a false
     value if there is no open session.  This might be used to call
     methods on the Net::SNMP object if some facility is needed that isnt
     supplied by this module.

all_interfaces()
     Returns a list of Net::SNMP::Interface::Details objects corresponding
     to the interfaces discovered on this host.  In scalar context it will
     return a reference to an array.

interface( SCALAR $name )
     Returns a Net::SNMP::Interfaces::Details object for the named
     interface.  Returns undef if the supplied name is not a known
     interface.

          $in_octs = $self->ifInOctets('eth0');

     Please see the documentation for Net::SNMP::Interfaces::Details for
     more on these methods.

AUTHOR
======

   Jonathan Stowe <jns@gellyfish.com>

COPYRIGHT
=========

   Copyright (c) Jonathan Stowe 2000.  All rights reserved.  This is free
software it can be ditributed and/or modified under the same terms as Perl
itself.

SEE ALSO
========

   perl(1), Net::SNMP, Net::SNMP::Interfaces::Details.

Object methods to obtain interface data.
****************************************

NAME
====

   Net::SNMP::Interfaces::Details - Object methods to obtain interface
data.

SYNOPSIS
========

     $in_octets = $interface->ifInOctets();

DESCRIPTION
===========

   This class represents an individual interface as discovered by
Net::SNMP::Interfaces.  Although it is possible to call the contructor
directly it is primarily intended that these objects should be returned by
methods of Net::SNMP::Interfaces.

new  HASH $args
     The constructor for the class.  User code should probably never need
     to call the constructor directly as Net::SNMP::Interface::Details
     objects are returned by the Net::SNMP::Interfaces methods
     all_interfaces() and interface().

     There are three mandatory arguments:

    Session
          A valid Net::SNMP object which will be used to make the requests
          for the interface information.  This Net::SNMP object should
          currently only be of the blocking variety as no provision has
          been made for non-blocking requests at present.

    Index
          The SNMP ifTable index for this interface.

    Name
          The name of this interface (e.g. 'eth0' ).

     The Name and Index arguments should have previously been obtained by
     SNMP requests to the same host as the Session object has been created
     for.

name
     Returns the name of this interace.

index
     Returns the index of this interface.

session
     Returns the Net::SNMP session object that is being used to make
     requests for this interface.  This probably is not needed but is here
     for completeness' sake.

IANAifType
     Converts from an IANAifType integer value as will be returned by
     ifType to its text equivalent.

     The remainder of the methods are named after the literal names for the
     SNMP entries for network interfaces.  The following descriptions are
     taken from the IF-MIB with some additional comment from the author
     where necessary.

    ifIndex
          A unique value, greater than zero, for each interface.  It is
          recommended that values are assigned contiguously starting from
          1.  The value for each interface sub-layer must remain constant
          at least from one re-initialization of the entity's network
          management system to the next re-initialization.

    ifDescr
          A textual string containing information about the interface.
          This string should include the name of the manufacturer, the
          product name and the version of the interface hardware/software.

          (In practice this will be name of the interface e.g. 'eth0')

    ifType
          The type of interface.  Additional values for ifType are
          assigned by the Internet Assigned Numbers Authority (IANA),
          through updating the syntax of the IANAifType textual convention.

    ifMtu
          The size of the largest packet which can be sent/received on the
          interface, specified in octets.  For interfaces that are used
          for transmitting network datagrams, this is the size of the
          largest network datagram that can be sent on the interface.

    ifSpeed
          An estimate of the interface's current bandwidth in bits per
          second.  For interfaces which do not vary in bandwidth or for
          those where no accurate estimation can be made, this object
          should contain the nominal bandwidth.  If the bandwidth of the
          interface is greater than the maximum value reportable by this
          object then this object should report its maximum value
          (4,294,967,295) and ifHighSpeed must be used to report the
          interace's speed.  For a sub-layer which has no concept of
          bandwidth, this object should be zero.

    ifPhysAddress
          The interface's address at its protocol sub-layer.  For example,
          for an 802.x interface, this object normally contains a MAC
          address.  The interface's media-specific MIB must define the bit
          and byte ordering and the format of the value of this object.
          For interfaces which do not have such an address (e.g., a serial
          line), this object should contain an octet string of zero length.

    ifAdminStatus
          The desired state of the interface.  The testing(3) state
          indicates that no operational packets can be passed.  When a
          managed system initializes, all interfaces start with
          ifAdminStatus in the down(2) state.  As a result of either
          explicit management action or per configuration information
          retained by the managed system, ifAdminStatus is then changed to
          either the up(1) or testing(3) states (or remains in the down(2)
          state).

    ifOperStatus
          The current operational state of the interface.  The testing(3)
          state indicates that no operational packets can be passed.  If
          ifAdminStatus is down(2) then ifOperStatus should be down(2).
          If ifAdminStatus is changed to up(1) then ifOperStatus should
          change to up(1) if the interface is ready to transmit and
          receive network traffic; it should change to dormant(5) if the
          interface is waiting for external actions (such as a serial line
          waiting for an incoming connection); it should remain in the
          down(2) state if and only if there is a fault that prevents it
          from going to the up(1) state; it should remain in the
          notPresent(6) state if the interface has missing (typically,
          hardware) components.

    ifLastChange
          The value of sysUpTime at the time the interface entered its
          current operational state.  If the current state was entered
          prior to the last re-initialization of the local network
          management subsystem, then this object contains a zero value.

    ifInOctets
          The total number of octets received on the interface, including
          framing characters.  Discontinuities in the value of this
          counter can occur at re-initialization of the management system,
          and at other times as indicated by the value of
          ifCounterDiscontinuityTime.

    ifInUcastPkts
          The number of packets, delivered by this sub-layer to a higher
          (sub-)layer, which were not addressed to a multicast or
          broadcast address at this sub-layer.  Discontinuities in the
          value of this counter can occur at re-initialization of the
          management system, and at other times as indicated by the value
          of ifCounterDiscontinuityTime.

    ifInNUcastPkts
          The number of packets, delivered by this sub-layer to a higher
          (sub-)layer, which were addressed to a multicast or broadcast
          address at this sub-layer.  Discontinuities in the value of this
          counter can occur at re-initialization of the management system,
          and at other times as indicated by the value of
          ifCounterDiscontinuityTime.  This object is deprecated in favour
          of ifInMulticastPkts and ifInBroadcastPkts.

    ifInDiscards
          The number of inbound packets which were chosen to be discarded
          even though no errors had been detected to prevent their being
          deliverable to a higher-layer protocol.  One possible reason for
          discarding such a packet could be to free up buffer space.
          Discontinuities in the value of this counter can occur at
          re-initialization of the management system, and at other times
          as indicated by the value of ifCounterDiscontinuityTime.

    ifInErrors
          For packet-oriented interfaces, the number of inbound packets
          that contained errors preventing them from being deliverable to
          a higher-layer protocol.  For character-oriented or fixed-length
          interfaces, the number of inbound transmission units that
          contained errors preventing them from being deliverable to a
          higher-layer protocol.  Discontinuities in the value of this
          counter can occur at re-initialization of the management system,
          and at other times as indicated by the value of
          ifCounterDiscontinuityTime.

    ifInUnknownProtos
          For packet-oriented interfaces, the number of packets received
          via the interface which were discarded because of an unknown or
          unsupported protocol.  For character-oriented or fixed-length
          interfaces that support protocol multiplexing the number of
          transmission units received via the interface which were
          discarded because of an unknown or unsupported protocol.  For
          any interface that does not support protocol multiplexing, this
          counter will always be 0.  Discontinuities in the value of this
          counter can occur at re-initialization of the management system,
          and at other times as indicated by the value of
          ifCounterDiscontinuityTime.

    ifOutOctets
          The total number of octets transmitted out of the interface,
          including framing characters.  Discontinuities in the value of
          this counter can occur at re-initialization of the management
          system, and at other times as indicated by the value of
          ifCounterDiscontinuityTime.

    ifOutUcastPkts
          The total number of packets that higher-level protocols
          requested be transmitted, and which were not addressed to a
          multicast or broadcast address at this sub-layer, including
          those that were discarded or not sent.  Discontinuities in the
          value of this counter can occur at re-initialization of the
          management system, and at other times as indicated by the value
          of ifCounterDiscontinuityTime.

    ifOutNUcastPkts
          The total number of packets that higher-level protocols
          requested be transmitted, and which were addressed to a
          multicast or broadcast address at this sub-layer, including
          those that were discarded or not sent.  Discontinuities in the
          value of this counter can occur at re-initialization of the
          management system, and at other times as indicated by the value
          of ifCounterDiscontinuityTime.  This object is deprecated in
          favour of ifOutMulticastPkts and ifOutBroadcastPkts.

    ifOutDiscards
          The number of outbound packets which were chosen to be discarded
          even though no errors had been detected to prevent their being
          transmitted.  One possible reason for discarding such a packet
          could be to free up buffer space.  Discontinuities in the value
          of this counter can occur at re-initialization of the management
          system, and at other times as indicated by the value of
          ifCounterDiscontinuityTime.

    ifOutErrors
          For packet-oriented interfaces, the number of outbound packets
          that could not be transmitted because of errors.  For
          character-oriented or fixed-length interfaces, the number of
          outbound transmission units that could not be transmitted
          because of errors.  Discontinuities in the value of this counter
          can occur at re-initialization of the management system, and at
          other times as indicated by the value of
          ifCounterDiscontinuityTime.

    ifOutQLen
          The length of the output packet queue (in packets).

    ifSpecific
          A reference to MIB definitions specific to the particular media
          being used to realize the interface.  It is recommended that
          this value point to an instance of a MIB object in the
          media-specific MIB, i.e., that this object have the semantics
          associated with the InstancePointer textual convention defined
          in RFC 1903.  In fact, it is recommended that the media-
          specific MIB specify what value ifSpecific should/can take for
          values of ifType.  If no MIB definitions specific to the
          particular media are available, the value should be set to the
          OBJECT IDENTIFIER { 0 0 }.

AUTHOR
======

   Jonathan Stowe <jns@gellyfish.com>

COPYRIGHT
=========

   Copyright (c) Jonathan Stowe 2000.  All rights reserved.  This is free
software it can be distributed and/or modified under the same terms as
Perl itself.

SEE ALSO
========

   perl(1), Net::SNMP, Net::SNMP::Interfaces.

Simple Network Pager Protocol Client
************************************

NAME
====

   Net::SNPP - Simple Network Pager Protocol Client

SYNOPSIS
========

     use Net::SNPP;

     # Constructors
     $snpp = Net::SNPP->new('snpphost');
     $snpp = Net::SNPP->new('snpphost', Timeout => 60);

NOTE
====

   This module is not complete, yet !

DESCRIPTION
===========

   This module implements a client interface to the SNPP protocol, enabling
a perl5 application to talk to SNPP servers. This documentation assumes
that you are familiar with the SNPP protocol described in RFC1861.

   A new Net::SNPP object must be created with the new method. Once this
has been done, all SNPP commands are accessed through this object.

EXAMPLES
========

   This example will send a pager message in one hour saying "Your lunch
is ready"

     #!/usr/local/bin/perl -w

     use Net::SNPP;

     $snpp = Net::SNPP->new('snpphost');

     $snpp->send( Pager   => $some_pager_number,
     	         Message => "Your lunch is ready",
     	         Alert   => 1,
     	         Hold    => time + 3600, # lunch ready in 1 hour :-)
     	       ) || die $snpp->message;

     $snpp->quit;

CONSTRUCTOR
===========

new ( [ HOST, ] [ OPTIONS ] )
     This is the constructor for a new Net::SNPP object. `HOST' is the
     name of the remote host to which a SNPP connection is required.

     If `HOST' is not given, then the `SNPP_Host' specified in
     `Net::Config' will be used.

     OPTIONS are passed in a hash like fashion, using key and value pairs.
     Possible options are:

     Timeout - Maximum time, in seconds, to wait for a response from the
     SNPP server (default: 120)

     Debug - Enable debugging information

     Example:

          $snpp = Net::SNPP->new('snpphost',
          			   Debug => 1,
          			  );

METHODS
=======

   Unless otherwise stated all methods return either a *true* or false
value, with *true* meaning that the operation was a success. When a method
states that it returns a value, failure will be returned as undef or an
empty list.

reset ()
help ()
     Request help text from the server. Returns the text or undef upon
     failure

quit ()
     Send the QUIT command to the remote SNPP server and close the socket
     connection.

EXPORTS
=======

   `Net::SNPP' exports all that `Net::CMD' exports, plus three more
subroutines that can bu used to compare against the result of status.
These are :- `CMD_2WAYERROR', `CMD_2WAYOK', and `CMD_2WAYQUEUED'.

SEE ALSO
========

   See Net/Cmd, RFC1861

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

COPYRIGHT
=========

   Copyright (c) 1995-1997 Graham Barr. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

a SOCKS client class
********************

NAME
====

   Net::SOCKS - a SOCKS client class

SYNOPSIS
========

     Establishing a connection:

     my $sock = new Net::SOCKS(socks_addr => '192.168.1.3',
                    socks_port => 1080,
                    user_id => 'the_user',
                    user_password => 'the_password',
                    force_nonanonymous => 1,
                    protocol_version => 5);

     # connect to finger port and request finger information for some_user
     my $f= $sock->connect(peer_addr => '192.168.1.3', peer_port => 79);
     print $f "some_user\n";    # example writing to socket
     while (<$f>) { print }     # example reading from socket
     $sock->close();

     Accepting an incoming connection:

     my $sock = new Net::SOCKS(socks_addr => '192.168.1.3',
                    socks_port => 1080,
                    user_id => 'the_user',
                    user_password => 'the_password',
                    force_nonanonymous => 1,
                    protocol_version => 5);

     my ($ip, $ip_dot_dec, $port) = $sock->bind(peer_addr => "128.10.10.11",
                            peer_port => 9999);

     $f= $sock->accept();
     print $f "Hi!  Type something.\n";    # example writing to socket
     while (<$f>) { print }                # example reading from socket
     $sock->close();

DESCRIPTION
===========

     my $sock = new Net::SOCKS(socks_addr => '192.168.1.3',
                    socks_port => 1080,
                    user_id => 'the_user',
                    user_password => 'the_password',
                    force_nonanonymous => 1,
                    protocol_version => 5);

     To connect to a SOCKS server, specify the SOCKS server's
     hostname, port number, SOCKS protocol version, username, and
     password.  Username and password are optional if you plan
     to use a SOCKS server that doesn't require any authentication.
     If you would like to force the connection to be
     nonanoymous, set the force_nonanonymous parameter.

     my $f= $sock->connect(peer_addr => '192.168.1.3', peer_port => 79);

     To connect to another machine using SOCKS, use the connect method.
     Specify the host and port number as parameters.

     my ($ip, $ip_dot_dec, $port) = $sock->bind(peer_addr => "192.168.1.3",
                            peer_port => 9999);

     If you wanted to accept a connection with SOCKS, specify the host
     and port of the machine you expect a connection from.  Upon
     success, bind() returns the ip address and port number that
     the SOCKS server is listening at on your behalf.

     $f= $sock->accept();

     If a call to bind() returns a success status code SOCKS_OKAY,
     a call to the accept() method will return when the peer host
     connects to the host/port that was returned by the bind() method.
     Upon success, accept() returns SOCKS_OKAY.

     $sock->close();

     Closes the connection.

SEE ALSO
========

     RFC 1928, RFC 1929.

AUTHOR
======

     Clinton Wong, clintdw@netcom.com

COPYRIGHT
=========

     Copyright (c) 1997-1998 Clinton Wong. All rights reserved.
     This program is free software; you can redistribute it
     and/or modify it under the same terms as Perl itself.

Perl extension for secure shell
*******************************

NAME
====

   Net::SSH - Perl extension for secure shell

SYNOPSIS
========

     use Net::SSH qw(ssh issh sshopen2 sshopen3);

     ssh('user@hostname', $command);

     issh('user@hostname', $command);

     sshopen2('user@hostname', $reader, $writer, $command);

     sshopen3('user@hostname', $reader, $writer, $error, $command);

DESCRIPTION
===========

   Simple wrappers around ssh commands.

SUBROUTINES
===========

ssh [USER@]HOST, COMMAND [, ARGS ... ]
     Calls ssh in batch mode.

issh [USER@]HOST, COMMAND [, ARGS ... ]
     Prints the ssh command to be executed, waits for the user to confirm,
     and (optionally) executes the command.

sshopen2 [USER@]HOST, READER, WRITER, COMMAND [, ARGS ... ]
     Connects the supplied filehandles to the ssh process (in batch mode).

sshopen3 HOST, WRITER, READER, ERROR, COMMAND [, ARGS ... ]
     Connects the supplied filehandles to the ssh process (in batch mode).

EXAMPLE
=======

     use Net::SSH qw(sshopen2);
     use strict;

     my $user = "username";
     my $host = "hostname";
     my $cmd = "command";

     sshopen2("$user\@$host", *READER, *WRITER, "$cmd") || die "ssh: $!";

     while (<READER>) {
         chomp();
         print "$_\n";
     }

     close(READER);
     close(WRITER);

AUTHOR
======

   Ivan Kohler <ivan-netssh_pod@420.am>

CREDITS
=======

     John Harrison <japh@in-ta.net> contributed an example for the documentation.

BUGS
====

   Not OO.

   Look at IPC::Session (also fsh)

SEE ALSO
========

   ssh(1), see IPC/Open2, IPC/Open3,

Perl client Interface to SSH
****************************

NAME
====

   Net::SSH::Perl - Perl client Interface to SSH

SYNOPSIS
========

     use Net::SSH::Perl;
     my $ssh = Net::SSH::Perl->new($host);
     $ssh->login($user, $pass);
     my($stdout, $stderr, $exit) = $ssh->cmd($cmd);

DESCRIPTION
===========

   *Net::SSH::Perl* is an all-Perl module implementing an ssh client.  It
enables you to simply and securely execute commands on remote machines,
and receive the STDOUT, STDERR, and exit status of that remote command.

   It contains built-in support for various methods of authenticating with
the server (password authentication, RSA challenge-response
authentication, etc.). It completely implements the I/O buffering, packet
transport, and user authentication layers of the SSH protocol, and makes
use of external Perl libraries (in the Crypt:: family of modules) to
handle encryption of all data sent across the insecure network. It can
also read your existing SSH configuration files (`/etc/ssh_config', etc.),
RSA identity files, known hosts files, etc.

   One advantage to using *Net::SSH::Perl* over wrapper-style
implementations of ssh clients is that it saves on process overhead: you
no longer need to fork and execute a separate process in order to connect
to an sshd. Depending on the amount of time and memory needed to fork a
process, this win can be quite substantial; particularly if you're running
in a persistent Perl environment (mod_perl, for example), where forking a
new process is a drain on process and memory resources.

   It also simplifies the process of using password-based authentications;
when writing a wrapper around ssh you probably need to use Expect to
control the ssh client and give it your password.  *Net::SSH::Perl* has
built-in support for the authentication protocols, so there's no longer
any hassle of communicating with any external processes.

BASIC USAGE
===========

   Usage of *Net::SSH::Perl* is very simple.

Net::SSH::Perl->new($host, %params)
-----------------------------------

   To set up a new connection, call the new method, which connects to
$host and returns a *Net::SSH::Perl* object.

   new accepts the following named parameters in *%params*:

   * cipher

     Specifies the name of the encryption cipher that you wish to use for
     this connection. This must be one of the supported ciphers
     (currently, IDEA, *DES*, *DES3*, and *Blowfish*); specifying an
     unsupported cipher is a fatal error. The default cipher is IDEA.

   * port

     The port of the *sshd* daemon to which you wish to connect; if not
     specified, this is assumed to be the default ssh port.

   * debug

     Set to a true value if you want debugging messages printed out while
     the connection is being opened. These can be helpful in trying to
     determine connection problems, etc. The messages are similar (and in
     some cases exact) to those written out by the ssh client when you use
     the -v option.

     Defaults to false.

   * interactive

     Set to a true value if you're using *Net::SSH* interactively.  This
     is used in determining whether or not to display password prompts,
     for example. It's basically the inverse of the *BatchMode* parameter
     in ssh configuration.

     Defaults to false.

   * privileged

     Set to a true value if you want to bind to a privileged port locally.
     You'll need this if you plan to use Rhosts or Rhosts-RSA
     authentication, because the remote server requires the client to
     connect on a privileged port. Of course, to bind to a privileged port
     you'll need to be root.

     If you don't provide this parameter, and *Net::SSH::Perl* detects
     that you're running as root, this will automatically be set to true.
     Otherwise it defaults to false.

   * identity_files

     A list of RSA identity files to be used in RSA authentication.  The
     value of this argument should be a reference to an array of strings,
     each string identifying the location of an identity file.

     If you don't provide this, RSA authentication defaults to using
     "$ENV{HOME}/.ssh/identity".

   * compression

     If set to a true value, compression is turned on for the session
     (assuming that the server supports it).

     Compression is off by default.

     Note that compression requires that you have the *Compress::Zlib*
     module installed on your system. If the module can't be loaded
     successfully, compression is disabled; you'll receive a warning
     stating as much if you having debugging on (debug set to 1), and you
     try to turn on compression.

   * compression_level

     Specifies the compression level to use if compression is enabled
     (note that you must provide both the compression and
     *compression_level* arguments to set the level; providing only this
     argument will not turn on encryption).

     The default value is 6.

   * use_pty

     Set this to 1 if you want to request a pseudo tty on the remote
     machine. This is really only useful if you're setting up a shell
     connection (see the *shell* method, below); and in that case, unless
     you've explicitly declined a pty (by setting *use_pty* to 0), this
     will be set automatically to 1. In other words, you probably won't
     need to use this, often.

     The default is 1 if you're starting up a shell, and 0 otherwise.

   * options

     Used to specify additional options to the configuration settings;
     useful for specifying options for which there is no separate
     constructor argument. This is analogous to the -o command line flag
     to the ssh program.

     If used, the value should be a reference to a list of option
     directives in the format used in the config file. For example:

          my $ssh = Net::SSH::Perl->new("host", options => [
              "BatchMode yes", "RhostsAuthentication no" ]);

$ssh->login([ $user [, $password ] ])
-------------------------------------

   Sets the username and password to be used when authenticating with the
*sshd* daemon. The username *$user* is required for all authentication
protocols (to identify yourself to the remote server), but if you don't
supply it the username of the user executing the program is used.

   The password $password is needed only for password authentication (it's
not used for RSA passphrase authentication, though perhaps it should be).
And if you're running in an interactive session and you've not provided a
password, you'll be prompted for one.

($out, $err, $exit) = $ssh->cmd($cmd, [ $stdin ])
-------------------------------------------------

   Runs the command *$cmd* on the remote server and returns the stdout,
stderr, and exit status of that command.

   If *$stdin* is provided, it's supplied to the remote command *$cmd* on
standard input.

   NOTE: the ssh protocol does not easily support (so far as I know)
running multiple commands per connection, unless those commands are
chained together so that the remote shell can evaluate them. Because of
this, a new socket connection is created each time you call cmd, and
disposed of afterwards. In other words, this code:

     my $ssh = Net::SSH::Perl->new("host1");
     $ssh->login("user1", "pass1");

     $ssh->cmd("foo");
     $ssh->cmd("bar");

   will actually connect to the *sshd* on the first invocation of cmd,
then disconnect; then connect again on the second invocation of cmd, then
disconnect again.

   This is less than ideal, obviously. Future version of *Net::SSH::Perl*
may find ways around that.

$ssh->shell
-----------

   Opens up an interactive shell on the remote machine and connects it to
your STDIN. This is most effective when used with a pseudo tty; otherwise
you won't get a command line prompt, and it won't look much like a shell.
For this reason-unless you've specifically declined one-a pty will be
requested from the remote machine, even if you haven't set the *use_pty*
argument to new (described above).

   This is really only useful in an interactive program.

   In addition, you'll probably want to set your terminal to raw input
before calling this method. This lets *Net::SSH::Perl* process each
character and send it off to the remote machine, as you type it.

   To do so, use Term::ReadKey in your program:

     use Term::ReadKey;
     ReadMode('raw');
     $ssh->shell;
     ReadMode('restore');

   In fact, you may want to place the restore line in an END block, in
case your program exits prior to reaching that line.

   If you need an example, take a look at `eg/pssh', which uses almost
this exact code to implement an ssh shell.

$ssh->register_handler($packet_type, $subref)
---------------------------------------------

   Registers an anonymous subroutine handler *$subref* to handle packets
of type *$packet_type* during the client loop. The client loop is entered
after the client has sent a command to the remote server, and after any
STDIN data has been sent; it consists of reading packets from the server
(STDOUT packets, STDERR packets, etc.) until the server sends the exit
status of the command executed remotely. At this point the client exits
the client loop and disconnects from the server.

   When you call the cmd method, the client loop by default simply sticks
STDOUT packets into a scalar variable and returns that value to the
caller. It does the same for STDERR packets, and for the process exit
status. (See the docs for cmd).

   You can, however, override that default behavior, and instead process
the packets yourself as they come in. You do this by calling the
*register_handler* method and giving it a packet type *$packet_type* and a
subroutine reference *$subref*. Your subroutine will receive as arguments
the *Net::SSH::Perl* object (with an open connection to the sshd), and a
*Net::SSH::Perl::Packet* object, which represents the packet read from the
server.

   *$packet_type* should be an integer constant; you can import the list
of constants into your namespace by explicitly loading the
*Net::SSH::Perl::Constants* module:

     use Net::SSH::Perl::Constants qw( :msg );

   This will load all of the MSG constants into your namespace so that you
can use them when registering the handler. To do that, use this method.
For example:

     $ssh->register_handler(SSH_SMSG_STDOUT_DATA, sub {
         my($ssh, $packet) = @_;
         print "I received this: ", $packet->get_str;
     });

   To learn about the methods that you can call on the packet object, take
a look at the *Net::SSH::Perl::Packet* docs, as well as the
*Net::SSH::Perl::Buffer* docs (the *get_** and *put_** methods).

   Obviously, writing these handlers requires some knowledge of the
contents of each packet. For that, read through the SSH RFC, which
explains each packet type in detail. There's a *get_** method for each
datatype that you may need to read from a packet.

ADVANCED METHODS
================

   Your basic SSH needs will hopefully be met by the methods listed above.
If they're not, however, you may want to use some of the additional
methods listed here. Some of these are aimed at end-users, while others
are probably more useful for actually writing an authentication module, or
a cipher, etc.

$ssh->config
------------

   Returns the *Net::SSH::Perl::Config* object managing the configuration
data for this SSH object. This is constructed from data passed in to the
constructor new (see above), merged with data read from the user and
system configuration files. See the *Net::SSH::Perl::Config* docs for
details on methods you can call on this object (you'll probably be more
interested in the get and set methods).

$ssh->sock
----------

   Returns the socket connection to sshd. If your client is not connected,
dies.

$ssh->debug($msg)
-----------------

   If debugging is turned on for this session (see the debug parameter to
the new method, above), writes $msg to `STDERR'. Otherwise nothing is done.

$ssh->incoming_data
-------------------

   Incoming data buffer, an object of type *Net::SSH::Perl::Buffer*.
Returns the buffer object.

   The idea behind this is that we our socket is non-blocking, so we
buffer input and periodically check back to see if we've read a full
packet. If we have a full packet, we rip it out of the incoming data
buffer and process it, returning it to the caller who presumably asked for
it.

   This data "belongs" to the underlying packet layer in
*Net::SSH::Perl::Packet*. Unless you really know what you're doing you
probably don't want to disturb that data.

$ssh->set_cipher($cipher_name)
------------------------------

   Sets the cipher for the SSH session *$ssh* to *$cipher_name* (which
must be a valid cipher name), and turns on encryption for that session.

$ssh->send_cipher
-----------------

   Returns the "send" cipher object. This is the object that encrypts
outgoing data.

   If it's not defined, encryption is not turned on for the session.

$ssh->receive_cipher
--------------------

   Returns the "receive" cipher object. This is the object that decrypts
incoming data.

   If it's not defined, encryption is not turned on for the session.

   NOTE: the send and receive ciphers and two *different* objects, each
with its own internal state (initialization vector, in particular). Thus
they cannot be interchanged.

$ssh->compression([ $level ])
-----------------------------

   Without arguments, returns the current compression level for the
session. If given an argument *$level*, sets the compression level and
turns on compression for the session.

   Note that this should not be used to turn compression off. In fact, I
don't think there's a way to turn compression off. But in other words,
don't try giving this method a value of 0 and expect that to turn off
compression. It won't.

   If the return value of this method is undefined or 0, compression is
turned off.

$ssh->send_compression
----------------------

   Returns the "send" compression object/stream. This is a
*Compress::Zlib* deflation (compression) stream; we keep it around because
it contains state that needs to be used throughout the session.

$ssh->receive_compression
-------------------------

   Returns the "receive" compression object/stream. This is a
*Compress::Zlib* inflation (uncompression) stream; we keep it around
because it contains state that needs to be used throughout the session.

$ssh->session_key
-----------------

   Returns the session key, which is simply 32 bytes of random data and is
used as the encryption/decryption key.

$ssh->session_id
----------------

   Returns the session ID, which is generated from the server's host and
server keys, and from the check bytes that it sends along with the keys.
The server may require the session ID to be passed along in other packets,
as well (for example, when responding to RSA challenges).

$packet = $ssh->packet_start($packet_type)
------------------------------------------

   Starts building a new packet of type *$packet_type*. This is just a
handy method for lazy people. Internally it calls
*Net::SSH::Perl::Packet::new*, so take a look at those docs for more
details.

SUPPORT
=======

   For samples/tutorials, take a look at the scripts in `eg/' in the
distribution directory.

   If you have any questions, code samples, bug reports, or feedback,
please email them to:

     ben@rhumba.pair.com

AUTHOR & COPYRIGHT
==================

   Benjamin Trott, ben@rhumba.pair.com

   Except where otherwise noted, Net::SSH::Perl is Copyright 2001 Benjamin
Trott. All rights reserved. Net::SSH::Perl is free software; you may
redistribute it and/or modify it under the same terms as Perl itself.

Base authentication class, plus utility methods
***********************************************

NAME
====

   Net::SSH::Perl::Auth - Base authentication class, plus utility methods

SYNOPSIS
========

     use Net::SSH::Perl::Cipher;

     # Get list of supported authentication IDs.
     my $supported = Net::SSH::Perl::Auth::supported();

     # Translate an auth name into an ID.
     my $id = Net::SSH::Perl::Auth::id($name);

     # Translate an auth ID into a name.
     my $name = Net::SSH::Perl::Auth::name($id);

     # Get the order in which auth methods are tested.
     my $order = Net::SSH::Perl::Auth::order();

DESCRIPTION
===========

   *Net::SSH::Perl::Auth* provides a base class for each of the
authentication method classes. In addition, it defines a set of utility
methods that can be called either as functions or object methods.

UTILITY METHODS
===============

supported( [ $auth_id [, $server_supports ] ])
----------------------------------------------

   Without arguments, returns a reference to an array of auth methods
supported by *Net::SSH::Perl*. These are methods that have working
Net::SSH::Perl::Auth:: implementations, essentially.

   With one argument *$auth_id*, returns a true value if that auth method
is supported by *Net::SSH::Perl*, and false otherwise.

   With two arguments, *$auth_id* and *$server_supports*, returns true if
the auth represented by *$auth_id* is supported both by *Net::SSH::Perl*
and by the sshd server. The list of methods supported by the server should
be in *$server_supports*, a bit mask sent from the server during the
session identification phase.

   Can be called either as a non-exported function, i.e.

     my $i_support = Net::SSH::Perl::Auth::supported();

   or as an object method of a *Net::SSH::Perl::Auth* object, or an object
of a subclass (in which case the first argument should be
*$server_supports*, not the *$auth_id*):

     if ($auth->supported($server_supports)) {
         print "Server supports auth method $auth";
     }

id( [ $auth_name ] )
--------------------

   Translates an auth method name into an ID (suitable for sending to the
sshd server, for example).

   If given *$auth_name* translates that name into the corresponding ID.
If called as an object method, translates the object's auth class name
into the ID.

name( [ $auth_id ] )
--------------------

   Translates an auth method ID into a name.

   If given *$auth_id* translates that ID into the corresponding name. If
called as an object method, returns the (stripped) object's auth class
name; for example, if the object were of type
*Net::SSH::Perl::Auth::Rhosts*, name would return *Rhosts*.

auth_order()
------------

   Returns a reference to an array containing auth method IDs. These IDs
describe the order in which authentication should be tested against the
server. So, for example, if the array listed (2, 4, 3), then the client
should test: RSA, then Rhosts-RSA, then Password authentication.

AUTH USAGE
==========

Net::SSH::Perl::Auth->new($auth_name, $ssh)
-------------------------------------------

   Instantiates a new auth object of the type *$auth_name*, and gives it
the *Net::SSH::Perl* object *$ssh*, which should contain an open connetion
to an sshd server.

   Returns the auth object, which will be blessed into the actual auth
subclass.

$valid = $auth->authenticate()
------------------------------

   Talks to the sshd server to authenticate the user; if valid, returns
true, and if invalid, returns false.

AUTH DEVELOPMENT
================

   Classes implementing an authentication method must implement the
following two methods:

   * $class->new($ssh)

     Given a *Net::SSH::Perl* object *$ssh*, should construct a new auth
     object and bless it into $class, presumably.

   * $class->authenticate()

     Authenticate the current user with the remote daemon. This requires
     following the messaging protocol defined for your authentication
     method. All of the data you need-user name, password (if required),
     etc.-should be in the *$ssh* object.

     Returns 1 if the authentication is successful, 0 otherwise.

AUTHOR & COPYRIGHTS
===================

   Please see the Net::SSH::Perl manpage for author, copyright, and
license information.

Password authentication plugin
******************************

NAME
====

   Net::SSH::Perl::Auth::Password - Password authentication plugin

SYNOPSIS
========

     use Net::SSH::Perl::Auth;
     my $auth = Net::SSH::Perl::Auth->new('Password', $ssh);
     print "Valid auth" if $auth->authenticate;

DESCRIPTION
===========

   *Net::SSH::Perl::Auth::Password* performs password authentication with
a remote sshd server. When you create a new password auth object, you give
it an *$ssh* object, which should contain an open connection to an ssh
daemon, as well as the data that the authentication module needs to
proceed.

   The authenticate method will enter into a dialog with the server. For
password authentication, all that needs to be done is to send a password
(encrypted by the standard SSH encryption layer) to the server, and wait
for its response. If the *$ssh* object doesn't already have a password
that you've given it, *Net::SSH::Perl::Auth::Password* will check to see
if you're in an interactive session (see the docs for *Net::SSH::Perl*),
and if so will issue a prompt, asking you to enter your password.  If the
session is not interactive (if it's in batch mode), we send a blank
password to comply with the protocol, but odds are the authentication will
then fail.

AUTHOR & COPYRIGHTS
===================

   Please see the Net::SSH::Perl manpage for author, copyright, and
license information.

Perform RSA authentication
**************************

NAME
====

   Net::SSH::Perl::Auth::RSA - Perform RSA authentication

SYNOPSIS
========

     use Net::SSH::Perl::Auth;
     my $auth = Net::SSH::Perl::Auth->new('RSA', $ssh);
     print "Valid auth" if $auth->authenticate;

DESCRIPTION
===========

   *Net::SSH::Perl::Auth::RSA* performs RSA authentication with a remote
sshd server. When you create a new RSA auth object, you give it an *$ssh*
object, which should contain an open connection to an ssh daemon, as well
as any data that the authentication module needs to proceed. In this case,
for example, the *$ssh* object might contain a list of RSA identity files
(see the docs for *Net::SSH::Perl*).

   The authenticate method tries to load the user's public and private
keys, for each of the files listed as identity files. If you haven't
listed any identity files, `$ENV{HOME}/.ssh/identity' is used by default.
For each identity, authenticate enters into a dialog with the sshd server.

   The client sends the public key to the server, then waits for a
challenge. Once this challenge is received, the client must decrypt the
challenge using the private key (loaded from the identity file). When
loading the private key, you may need to enter a passphrase to decrypt the
private key itself; first authenticate tries to decrypt the key using an
empty passphrase (which requires no user intervention). If this fails, the
client checks to see if it's running in an interactive session. If so, it
queries the user for a passphrase, which is then used to decrypt the
private key. If the session is non-interactive and the private key cannot
be loaded, the client simply sends a dummy response to the RSA challenge,
to comply with the SSH protocol.

   Otherwise, if the private key has been loaded, and the challenge
decrypted, the client sends its response to the server, then waits for
success or failure.

AUTHOR & COPYRIGHTS
===================

   Please see the Net::SSH::Perl manpage for author, copyright, and
license information.

Perform Rhosts authentication
*****************************

NAME
====

   Net::SSH::Perl::Auth::Rhosts - Perform Rhosts authentication

SYNOPSIS
========

     use Net::SSH::Perl::Auth;
     my $auth = Net::SSH::Perl::Auth->new('Rhosts', $ssh);
     print "Valid auth" if $auth->authenticate;

DESCRIPTION
===========

   *Net::SSH::Perl::Auth::Rhosts* performs Rhosts authentication with a
remote sshd server. When you create a new Rhosts auth object, you give it
an *$ssh* object, which should contain an open connection to an ssh
daemon, as well as any data that the authentication module needs to
proceed. In this case, the *$ssh* object must contain the name of the user
trying to open the connection.

   Rhosts authentication is fairly simple from a protocol point of view.
However, note that the sshd server will require your client to be running
on a privileged port (below 1024); this will, in turn, likely require your
client to be running as root. If your client is not running on a
privileged port, the Rhosts authentication request will be denied.

   If you're running as root, *Net::SSH::Perl* should automatically detect
that and try to start up on a privileged port. If for some reason that
isn't happening, take a look at the *Net::SSH::Perl* docs.

   With that aside, to use Rhosts authentication the client sends a
request to the server to authenticate it, including the name of the user
trying to authenticate. The server uses its *shosts.equiv*, *hosts.equiv*,
etc. files to determine whether the user/host should be allowed access.

AUTHOR & COPYRIGHTS
===================

   Please see the Net::SSH::Perl manpage for author, copyright, and
license information.

Perform Rhosts-RSA authentication
*********************************

NAME
====

   Net::SSH::Perl::Auth::Rhosts_RSA - Perform Rhosts-RSA authentication

SYNOPSIS
========

     use Net::SSH::Perl::Auth;
     my $auth = Net::SSH::Perl::Auth->new('Rhosts_RSA', $ssh);
     print "Valid auth" if $auth->authenticate;

DESCRIPTION
===========

   *Net::SSH::Perl::Auth::Rhosts_RSA* performs Rhosts with RSA
authentication with a remote sshd server. This is standard Rhosts
authentication, plus a challenge-response phase where the server
RSA-authenticates the client based on its host key. When you create a new
Rhosts_RSA auth object, you give it an *$ssh* object, which should contain
an open connection to an ssh daemon, as well as any data that the
authentication module needs to proceed. In this case, the *$ssh* object
must contain the name of the user trying to open the connection.

   Note that the sshd server will require two things from your client:

  1. Privileged Port sshd will require your client to be running on a
     privileged port (below 1024); this will, in turn, likely require your
     client to be running as root. If your client is not running on a
     privileged port, the Rhosts-RSA authentication request will be denied.

     If you're running as root, *Net::SSH::Perl* should automatically
     detect that and try to start up on a privileged port. If for some
     reason that isn't happening, take a look at the *Net::SSH::Perl* docs.

  2. Private Host Key In order to do RSA-authentication on your host key,
     your client must be able to read the host key. This will likely be
     impossible unless you're running as root, because the private host
     key file (`/etc/ssh_host_key') is readable only by root.

        With that aside, to use Rhosts-RSA authentication the client sends
a request to the server to authenticate it, including the name of the user
trying to authenticate, as well as the public parts of the host key. The
server first ensures that the host can be authenticated using standard
Rhosts authentication (*shosts.equiv*, *hosts.equiv*, etc.).  If the
client passes this test, the server sends an encrypted challenge to the
client. The client must decrypt this challenge using its private host key,
then respond to the server with its response.

   Once the response has been sent, the server responds with success or
failure.

AUTHOR & COPYRIGHTS
===================

   Please see the Net::SSH::Perl manpage for author, copyright, and
license information.

Low-level read/write buffer class
*********************************

NAME
====

   Net::SSH::Perl::Buffer - Low-level read/write buffer class

SYNOPSIS
========

     use Net::SSH::Perl::Buffer;
     my $buffer = Net::SSH::Perl::Buffer->new;

     ## Add a 32-bit integer.
     $buffer->put_int32(10932930);

     ## Get it back.
     my $int = $buffer->get_int32;

DESCRIPTION
===========

   *Net::SSH::Perl::Buffer* implements the low-level binary buffer needed
by the *Net::SSH::Perl* suite. Specifically, a *Net::SSH::Perl::Buffer*
object is what makes up the data segment of a packet transferred between
server and client (a *Net::SSH::Perl::Packet* object).

   Buffers contain integers, strings, characters, etc. Because of the use
of GMP integers in SSH, buffers can also contain multiple-precision
integers (represented internally by *Math::GMP* objects).

   Note: the method documentation here is in what some might call a
slightly backwards order. The reason for this is that the get and put
methods (listed first) are probably what most users/developers of
*Net::SSH::Perl* need to care about; they're high-level methods used to
get/put data from the buffer. The other methods (LOW-LEVEL METHODS) are
much more low-level, and typically you won't need to use them explicitly.

GET AND PUT METHODS
===================

   All of the *get_** and *put_** methods respect the internal offset
state in the buffer object. This means that, for example, if you call
*get_int16* twice in a row, you can be ensured that you'll get the next two
16-bit integers in the buffer. You don't need to worry about the number of
bytes a certain piece of data takes up, for example.

$buffer->get_int8
-----------------

   Returns the next 8-bit integer from the buffer (which is really just
the ASCII code for the next character/byte in the buffer).

$buffer->put_int8
-----------------

   Appends an 8-bit integer to the buffer (which is really just the
character corresponding to that integer, in ASCII).

$buffer->get_int16
------------------

   Returns the next 16-bit integer from the buffer.

$buffer->put_int16($integer)
----------------------------

   Appends a 16-bit integer to the buffer.

$buffer->get_int32
------------------

   Returns the next 32-bit integer from the buffer.

$buffer->put_int32($integer)
----------------------------

   Appends a 32-bit integer to the buffer.

$buffer->get_char
-----------------

   More appropriately called *get_byte*, perhaps, this returns the next
byte from the buffer.

$buffer->put_char($bytes)
-------------------------

   Appends a byte (or a sequence of bytes) to the buffer.  There is no
restriction on the length of the byte string $bytes; if it makes you
uncomfortable to call put_char to put multiple bytes, you can instead call
this method as *put_chars*. It's the same thing.

$buffer->get_str
----------------

   Returns the next "string" from the buffer. A string here is represented
as the length of the string (a 32-bit integer) followed by the string
itself.

$buffer->put_str($string)
-------------------------

   Appends a string (32-bit integer length and the string itself) to the
buffer.

$buffer->get_mp_int
-------------------

   Returns a *Math::GMP* object representing a multiple precision integer
read from the buffer. In the buffer itself, an mp_int is represented by a
16-bit integer (the number of bits in the integer), and the integer itself.

$buffer->put_mp_int($mp_int)
----------------------------

   Appends a multiple precision integer (16-bit integer bit count and the
integer itself) to the buffer.

LOW-LEVEL METHODS
=================

Net::SSH::Perl::Buffer->new
---------------------------

   Creates a new buffer object and returns it. The buffer is empty.

   This method takes no arguments.

$buffer->append($bytes)
-----------------------

   Appends raw data $bytes to the end of the in-memory buffer. Generally
you don't need to use this method unless you're initializing an empty
buffer, because when you need to add data to a buffer you should generally
use one of the *put_** methods.

$buffer->empty
--------------

   Empties out the buffer object.

$buffer->bytes([ $offset [, $length [, $replacement ]]])
--------------------------------------------------------

   Behaves exactly like the substr built-in function, except on the buffer
*$buffer*. Given no arguments, bytes returns the entire buffer; given one
argument $offset, returns everything from that position to the end of the
string; given $offset and $length, returns the segment of the buffer
starting at $offset and consisting of $length bytes; and given all three
arguments, replaces that segment with *$replacement*.

   This is a very low-level method, and you generally won't need to use it.

   Also be warned that you should not intermix use of this method with use
of the *get_** and *put_** methods; the latter classes of methods maintain
internal state of the buffer offset where arguments will be gotten from
and put, respectively. The bytes method gives no thought to this internal
offset state.

$buffer->length
---------------

   Returns the length of the buffer object.

$buffer->offset
---------------

   Returns the internal offset state.

   If you insist on intermixing calls to bytes with calls to the *get_**
and *put_** methods, you'll probably want to use this method to get some
status on that internal offset.

$buffer->dump
-------------

   Returns a hex dump of the buffer.

$buffer->insert_padding
-----------------------

   A helper method: pads out the buffer so that the length of the
transferred packet will be evenly divisible by 8, which is a requirement
of the SSH protocol.

AUTHOR & COPYRIGHTS
===================

   Please see the Net::SSH::Perl manpage for author, copyright, and
license information.

Base cipher class, plus utility methods
***************************************

NAME
====

   Net::SSH::Perl::Cipher - Base cipher class, plus utility methods

SYNOPSIS
========

     use Net::SSH::Perl::Cipher;

     # Get list of supported cipher IDs.
     my $supported = Net::SSH::Perl::Cipher::supported();

     # Translate a cipher name into an ID.
     my $id = Net::SSH::Perl::Cipher::id($name);

     # Translate a cipher ID into a name.
     my $name = Net::SSH::Perl::Cipher::name($id);

DESCRIPTION
===========

   *Net::SSH::Perl::Cipher* provides a base class for each of the
encryption cipher classes. In addition, it defines a set of utility
methods that can be called either as functions or object methods.

UTILITY METHODS
===============

supported( [ $ciph_id [, $server_supports ] ])
----------------------------------------------

   Without arguments, returns a reference to an array of ciphers supported
by *Net::SSH::Perl*. These are ciphers that have working
Net::SSH::Perl::Cipher:: implementations, essentially.

   With one argument *$ciph_id*, returns a true value if that cipher is
supported by *Net::SSH::Perl*, and false otherwise.

   With two arguments, *$ciph_id* and *$server_supports*, returns true if
the cipher represented by *$ciph_id* is supported both by *Net::SSH::Perl*
and by the sshd server. The list of ciphers supported by the server should
be in *$server_supports*, a bit mask sent from the server during the
session identification phase.

   Can be called either as a non-exported function, i.e.

     my $i_support = Net::SSH::Perl::Cipher::supported();

   or as an object method of a *Net::SSH::Perl::Cipher* object, or an
object of a subclass:

     if ($ciph->supported($server_supports)) {
         print "Server supports cipher $ciph";
     }

id( [ $cipher_name ] )
----------------------

   Translates a cipher name into a cipher ID.

   If given *$cipher_name* translates that name into the corresponding ID.
If called as an object method, translates the object's cipher class name
into the ID.

name( [ $cipher_id ] )
----------------------

   Translates a cipher ID into a cipher name.

   If given *$cipher_id* translates that ID into the corresponding name.
If called as an object method, returns the (stripped) object's cipher
class name; for example, if the object were of type
*Net::SSH::Perl::Cipher::IDEA*, name would return IDEA.

CIPHER USAGE
============

Net::SSH::Perl::Cipher->new($cipher_name, $key)
-----------------------------------------------

   Instantiates a new cipher object of the type *$cipher_name* with the
key $key; returns the cipher object, which will be blessed into the actual
cipher subclass.

   If *$cipher_name* is the special type *'None'* (no encryption cipher),
the object will actually be blessed directly into the base class, and text
to be encrypted and decrypted will be passed through without change.

$cipher->encrypt($text)
-----------------------

   Encrypts $text and returns the encrypted string.

$cipher->decrypt($text)
-----------------------

   Decrypts $text and returns the decrypted string.

CIPHER DEVELOPMENT
==================

   Classes implementing an encryption cipher must implement the following
three methods:

   * $class->new($key)

     Given a key $key, should construct a new cipher object and bless it
     into $class, presumably.

   * $cipher->encrypt($text)

     Given plain text $text, should encrypt the text and return the
     encrypted string.

   * $cipher->decrypt($text)

     Given encrypted text $text, should decrypt the text and return the
     decrypted string.

AUTHOR & COPYRIGHTS
===================

   Please see the Net::SSH::Perl manpage for author, copyright, and
license information.

Wrapper for SSH Blowfish support
********************************

NAME
====

   Net::SSH::Perl::Cipher::Blowfish - Wrapper for SSH Blowfish support

SYNOPSIS
========

     use Net::SSH::Cipher;
     my $cipher = Net::SSH::Cipher->new('Blowfish', $key);
     print $cipher->encrypt($plaintext);

DESCRIPTION
===========

   *Net::SSH::Perl::Cipher::Blowfish* provides Blowfish encryption support
for *Net::SSH::Perl*. To do so it wraps around either *Crypt::Blowfish* or
*Crypt::Blowfish_PP*; the former is a C/XS implementation of the blowfish
algorithm, and the latter is a Perl implementation.
*Net::SSH::Perl::Cipher::Blowfish* prefers to use *Crypt::Blowfish*,
because it's faster, so we try to load that first. If it fails, we fall
back to *Crypt::Blowfish_PP*.  Note that, when using *Crypt::Blowfish_PP*,
you'll experience a very noticeable decrease in performance.

   The blowfish used here is in CBC filter mode with a key length of 32
bytes.

   SSH adds an extra wrinkle with respect to its blowfish algorithm:
before and after encryption/decryption, we have to swap the bytes in the
string to be encrypted/decrypted. The byte-swapping is done four bytes at
a time, and within each of those four-byte blocks we reverse the bytes.
So, for example, the string `foobarba' turns into `boofabra'. We swap the
bytes in this manner in the string before we encrypt/decrypt it, and swap
the encrypted/decrypted string again when we get it back.

AUTHOR & COPYRIGHTS
===================

   Please see the Net::SSH::Perl manpage for author, copyright, and
license information.

CBC Implementation
******************

NAME
====

   Net::SSH::Perl::Cipher::CBC - CBC Implementation

SYNOPSIS
========

     use Net::SSH::Cipher::CBC;
     my $cbc = Net::SSH::Cipher::CBC->new($cipher_obj);
     print $cbc->encrypt($plaintext);

DESCRIPTION
===========

   *Net::SSH::Perl::Cipher::CBC* provides a CBC (cipher block chaining)
implementation for SSH encryption ciphers.

AUTHOR & COPYRIGHTS
===================

   This code is based in part on the *Crypt::CBC* code originally
developed by Systemics Ltd.

   Please see the Net::SSH::Perl manpage for author, copyright, and
license information.

CFB Implementation
******************

NAME
====

   Net::SSH::Perl::Cipher::CFB - CFB Implementation

SYNOPSIS
========

     use Net::SSH::Cipher::CFB;
     my $cbc = Net::SSH::Cipher::CFB->new($cipher_obj);
     print $cbc->encrypt($plaintext);

DESCRIPTION
===========

   *Net::SSH::Perl::Cipher::CFB* provides a CFB (cipher feedback)
implementation for SSH encryption ciphers.

AUTHOR & COPYRIGHTS
===================

   This code is based in part on the *Crypt::CFB* code originally
developed by Systemics Ltd.

   Please see the Net::SSH::Perl manpage for author, copyright, and
license information.

Wrapper for SSH DES support
***************************

NAME
====

   Net::SSH::Perl::Cipher::DES - Wrapper for SSH DES support

SYNOPSIS
========

     use Net::SSH::Cipher;
     my $cipher = Net::SSH::Cipher->new('DES', $key);
     print $cipher->encrypt($plaintext);

DESCRIPTION
===========

   *Net::SSH::Perl::Cipher::DES* provides DES encryption support for
*Net::SSH::Perl*. To do so it wraps around *Crypt::DES*, a C/XS
implementation of the DES algorithm.

   The DES algorithm used here is in CBC filter mode with a key length of
8 bytes.

AUTHOR & COPYRIGHTS
===================

   Please see the Net::SSH::Perl manpage for author, copyright, and
license information.

Wrapper for SSH 3DES support
****************************

NAME
====

   Net::SSH::Perl::Cipher::DES3 - Wrapper for SSH 3DES support

SYNOPSIS
========

     use Net::SSH::Cipher;
     my $cipher = Net::SSH::Cipher->new('DES3', $key);
     print $cipher->encrypt($plaintext);

DESCRIPTION
===========

   *Net::SSH::Perl::Cipher::DES3* provides 3DES encryption support for
*Net::SSH::Perl*. To do so it wraps around *Crypt::DES*, a C/XS
implementation of the DES algorithm.

   The 3DES (three-key triple-DES) algorithm used here is in CBC mode with
a key length of 24 bytes.

   The first 8 bytes of the key are used as the first DES key, the second
8 bytes for the second key, etc. If the key $key that you pass to new is
only 16 bytes, the first 8 bytes of $key will be used as the key for both
the first and third DES ciphers.

AUTHOR & COPYRIGHTS
===================

   Please see the Net::SSH::Perl manpage for author, copyright, and
license information.

Wrapper for SSH IDEA support
****************************

NAME
====

   Net::SSH::Perl::Cipher::IDEA - Wrapper for SSH IDEA support

SYNOPSIS
========

     use Net::SSH::Cipher;
     my $cipher = Net::SSH::Cipher->new('IDEA', $key);
     print $cipher->encrypt($plaintext);

DESCRIPTION
===========

   *Net::SSH::Perl::Cipher::IDEA* provides IDEA encryption support for
*Net::SSH::Perl*. To do so it wraps around *Crypt::IDEA*, a C/XS
implementation of the IDEA algorithm.

   The IDEA algorithm used here is in CFB filter mode with a key length of
16 bytes.

AUTHOR & COPYRIGHTS
===================

   Please see the Net::SSH::Perl manpage for author, copyright, and
license information.

Load and manage SSH configuration
*********************************

NAME
====

   Net::SSH::Perl::Config - Load and manage SSH configuration

SYNOPSIS
========

     use Net::SSH::Perl::Config;
     my $cfg = Net::SSH::Perl::Config->new($host, foo => 'bar');
     $cfg->read_config($config_file);
     my $v = $cfg->get('foo');

DESCRIPTION
===========

   *Net::SSH::Perl::Config* manages configuration data for
*Net::SSH::Perl*. It merges options handed to it at object construction
with options read from configuration files.  Just as in the actual ssh
program, the first obtained value of a configuration parameter is the
value that's used; in other words, values given in the original parameter
list will always override values read from configuration files.

   The configuration files should be in the same format used for the ssh
command line program; see the ssh manpage for information on this format.
*Net::SSH::Perl::Config* understands a subset of the configuration
directives that can live in these files; this subset matches up with the
functionality that *Net::SSH::Perl* can support. Unknown keywords will
simply be skipped.

USAGE
=====

Net::SSH::Perl::Config->new($host, %args)
-----------------------------------------

   Constructs a new configuration container object and returns that
object. $host is the host to which you're applying this configuration; you
can leave it out (pass in an undefined or empty argument) if it's not
applicable to you.

   $host is needed for parsing the host-specific sections of the
configuration files; the Host keyword restricts a set of directives as
applying to a particular host (or set of hosts). When it encounters such a
section, *Net::SSH::Perl::Config* will skip all of the directives in the
section unless the host matches $host.

   *%args* can contain the same arguments that you can pass to the new
method of *Net::SSH::Perl*-those arguments are eventually passed through
to this method when setting up the SSH object. The elements in *%args*
override values in the configuration files.

$cfg->read_config($file)
------------------------

   Reads in the configuration file $file and adds any appropriate
configuration data to the settings maintained by the *$cfg* object. If
$file is unreadable, simply returns quietly.

   As stated above, values read from the configuration files are overriden
by those passed in to the constructor.  Furthermore, if you're reading
from several config files in sequence, values read from the first files
will override those read from the second, third, fourth, etc. files.

$cfg->merge_directive($line)
----------------------------

   Merges the directive option *$line* into the configuration settings in
*$cfg*. *$line* should be an option in the format used in the config file,
eg. *"BatchMode yes"*. This is useful for merging in directives that are
not necessarily in the config file, similar to how the -o option works in
the ssh command line program.

$cfg->get($key)
---------------

   Returns the value of the configuration parameter $key, and undefined if
that parameter has not been set.

$cfg->set($key, $value)
-----------------------

   Sets the value of the parameter $key to $value, and returns the new
value.

AUTHOR & COPYRIGHTS
===================

   Please see the Net::SSH::Perl manpage for author, copyright, and
license information.

Exportable constants
********************

NAME
====

   Net::SSH::Perl::Constants - Exportable constants

SYNOPSIS
========

     use Net::SSH::Perl::Constants qw( constants );

DESCRIPTION
===========

   *Net::SSH::Perl::Constants* provides a list of common and useful
constants for use in communicating with an sshd server, etc.

   None of the constants are exported by default; you have to explicitly
ask for them. Some of the constants are grouped into bundles that you can
grab all at once, or you can just take the individual constants, one by
one.

   If you wish to import a group, your use statement should look something
like this:

     use Net::SSH::Perl::Constants qw( :group );

   Here are the groups:

   * msg

     All of the MSG constants. In the SSH packet layer protocol, each
     packet is identified by its type; for example, you have a packet type
     for starting RSA authentication, a different type for sending a
     command, etc. The MSG constants are used when creating a new packet,
     then:

          my $packet = $ssh->packet_start( I<msg_constant> );

     See the *Net::SSH::Perl::Packet* and *Net::SSH::Perl* docs for
     details.

     *Net::SSH::Perl* doesn't support all of the features of the ssh
     client, so it doesn't need all of its MSG constants. For a full list
     of such constants, and an explanation of each, see the SSH RFC.

     Here's the list of MSG constants supported by *Net::SSH::Perl*:
     SSH_MSG_NONE, SSH_MSG_DISCONNECT, SSH_SMSG_PUBLIC_KEY,
     SSH_CMSG_SESSION_KEY, SSH_CMSG_USER, SSH_CMSG_AUTH_RHOSTS,
     SSH_CMSG_AUTH_RSA, SSH_SMSG_AUTH_RSA_CHALLENGE,
     SSH_CMSG_AUTH_RSA_RESPONSE, SSH_CMSG_AUTH_PASSWORD,
     SSH_CMSG_EXEC_SHELL, SSH_CMSG_EXEC_CMD, SSH_SMSG_SUCCESS,
     SSH_SMSG_FAILURE, SSH_CMSG_STDIN_DATA, SSH_SMSG_STDOUT_DATA,
     SSH_SMSG_STDERR_DATA, SSH_CMSG_EOF, SSH_SMSG_EXITSTATUS,
     SSH_MSG_IGNORE, SSH_CMSG_EXIT_CONFIRMATION, SSH_CMSG_AUTH_RHOSTS_RSA,
     SSH_MSG_DEBUG, SSH_CMSG_REQUEST_COMPRESSION.

   * hosts

     The HOST constants: HOST_OK, HOST_NEW, and HOST_CHANGED.  These are
     returned from the `_check_host_in_hostfile' routine in
     *Net::SSH::Perl::Util*. See that docs for that routine for an
     explanation of the meaning of these constants.

   Other exportable constants, not belonging to a group, are:

   * PROTOCOL_MAJOR

   * PROTOCOL_MINOR

     These two constants describe the version of the protocol supported by
     this SSH client (ie., *Net::SSH::Perl*).  They're used when
     identifying the client to the server and vice versa.

   * PRIVATE_KEY_ID_STRING

     A special ID string written to private key files; if the ID string in
     the file doesn't match this, we stop reading the private key file.

   * MAX_PACKET_SIZE

     The maximum size of a packet in the packet layer.

AUTHOR & COPYRIGHTS
===================

   Please see the Net::SSH::Perl manpage for author, copyright, and
license information.

Packet layer of SSH protocol
****************************

NAME
====

   Net::SSH::Perl::Packet - Packet layer of SSH protocol

SYNOPSIS
========

     use Net::SSH::Perl::Packet;

     # Send a packet to an ssh daemon.
     my $pack = Net::SSH::Perl::Packet->new($ssh, type => SSH_MSG_NONE);
     $pack->send;

     # Receive a packet.
     my $pack = Net::SSH::Perl::Packet->read($ssh);

DESCRIPTION
===========

   *Net::SSH::Perl::Packet* implements the packet-layer piece of the SSH
protocol. Messages between server and client are sent as binary data
packets, which are encrypted (once the two sides have agreed on the
encryption cipher, that is).

   Packets are made up primarily of a packet type, which describes the
type of message and data contained therein, and the data itself. In
addition, each packet: indicates its length in a 32-bit unsigned integer;
contains padding to pad the length of the packet to a multiple of 8 bytes;
and is verified by a 32-bit crc checksum.

   Refer to the SSH RFC for more details on the packet protocol and the
SSH protocol in general.

USAGE
=====

Net::SSH::Perl::Packet->new($ssh, %params)
------------------------------------------

   Creates/starts a new packet in memory. *$ssh* is a *Net::SSH::Perl*
object, which should already be connected to an ssh daemon. *%params* can
contain the following keys:

   * type

     The message type of this packet. This should be one of the values
     exported by *Net::SSH::Perl::Constants* from the msg tag; for
     example, *SSH_MSG_NONE*.

   * data

     A *Net::SSH::Perl::Buffer* object containing the data in this packet.
     Realistically, there aren't many times you'll need to supply this
     argument: when sending a packet, it will be created automatically;
     and when receiving a packet, the read method (see below) will create
     the buffer automatically, as well.

Net::SSH::Perl::Packet->read($ssh)
----------------------------------

   Reads a packet from the ssh daemon and returns that packet.

   This method will block until an entire packet has been read.  The
socket itself is non-blocking, but the method waits (using select) for
data on the incoming socket, then processes that data when it comes in. If
the data makes up a complete packet, the packet is returned to the caller.
Otherwise read continues to try to read more data.

Net::SSH::Perl::Packet->read_poll($ssh)
---------------------------------------

   Checks the data that's been read from the sshd to see if that data
comprises a complete packet. If so, that packet is returned. If not,
returns undef.

   This method does not block.

Net::SSH::Perl::Packet->read_expect($ssh, $type)
------------------------------------------------

   Reads the next packet from the daemon and dies if the packet type does
not match $type. Otherwise returns the read packet.

$packet->send([ $data ])
------------------------

   Sends a packet to the ssh daemon. $data is optional, and if supplied
specifies the buffer to be sent in the packet (should be a
*Net::SSH::Perl::Buffer* object).  In addition, $data, if specified, must
include the packed message type.

   If $data is not specified, send sends the buffer internal to the
packet, which you've presumably filled by calling the *put_** methods (see
below).

$packet->type
-------------

   Returns the message type of the packet *$packet*.

$packet->data
-------------

   Returns the message buffer from the packet *$packet*; a
*Net::SSH::Perl::Buffer* object.

Net::SSH::Perl::Buffer methods
------------------------------

   Calling methods from the *Net::SSH::Perl::Buffer* class on your
*Net::SSH::Perl::Packet* object will automatically invoke those methods on
the buffer object internal to your packet object (which is created when
your object is constructed). For example, if you executed the following
code:

     my $packet = Net::SSH::Perl::Packet->new($ssh, type => SSH_CMSG_USER);
     $packet->put_str($user);

   this would construct a new packet object *$packet*, then fill its
internal buffer by calling the *put_str* method on it.

   Refer to the *Net::SSH::Perl::Buffer* documentation (the GET AND PUT
METHODS section) for more details on those methods.

AUTHOR & COPYRIGHTS
===================

   Please see the Net::SSH::Perl manpage for author, copyright, and
license information.

Shared utility functions
************************

NAME
====

   Net::SSH::Perl::Util - Shared utility functions

SYNOPSIS
========

     use Net::SSH::Perl::Util qw( ... );

DESCRIPTION
===========

   *Net::SSH::Perl::Util* contains a variety of exportable utility
functions used by the various *Net::SSH::Perl* modules. These range from
hostfile routines, to RSA encryption routines, etc.

   The routines are exportable by themselves, ie.

     use Net::SSH::Perl::Util qw( routine_name );

   In addition, some of the routines are grouped into bundles that you can
pull in by export tag, ie.

     use Net::SSH::Perl::Util qw( :bundle );

   The groups are:

   * hosts

     Routines associated with hostfile-checking, addition, etc.  Contains
     `_check_host_in_hostfile' and `_add_host_to_hosfile'.

   * rsa

     Routines associated with RSA encryption, decryption, and
     authentication. Contains `_rsa_public_encrypt',
     `_rsa_private_decrypt', and `_respond_to_rsa_challenge'.

   * mp

     Routines associated with multiple-precision integers and the
     generation and manipulation of same. Contains `_mp_linearize' and
     `_compute_session_id'.

   * all

     All routines. Contains all of the routines listed below.

FUNCTIONS
=========

_crc32($data)
-------------

   Returns a CRC32 checksum of $data. This uses *String::CRC32* internally
to do its magic, with the caveat that the "init state" of the checksum is
`0xFFFFFFFF', and the result is xor-ed with `0xFFFFFFFF'.

_compute_session_id($check_bytes, $host_key, $public_key)
---------------------------------------------------------

   Given the check bytes (*$check_bytes*) and the server host and public
keys (*$host_key* and *$public_key*, respectively), computes the session
ID that is then used to uniquely identify the session between the server
and client.

   *$host_key* and *$public_key* should be hash references with three
keys: bits, n, and e. n and e should be multiple-precision integers
(*Math::GMP* objects).

   Returns the session ID.

_mp_linearize($length, $key)
----------------------------

   Converts a multiple-precision integer $key into a byte string.  $length
should be the number of bytes to linearize, which is generally the number
of bytes in the key.

   Note that, unlike the key arguments to `_compute_session_id', $key here
is just the multiple-precision integer, not the hash reference.

   Returns the linearized string.

_check_host_in_hostfile($host, $host_file, $host_key)
-----------------------------------------------------

   Looks up $host in *$host_file* and checks the stored host key against
*$host_key* to determine the status of the host.

   If the host is not found, returns HOST_NEW.

   If the host is found, and the keys match, returns HOST_OK.

   If the host is found, and the keys don't match, returns HOST_CHANGED,
which generally indicates a problem.

_add_host_to_hostfile($host, $host_file, $host_key)
---------------------------------------------------

   Opens up the known hosts file *$host_file* and adds an entry for $host
with host key *$host_key*. Dies if *$host_file* can't be opened for
writing.

_load_public_key($key_file)
---------------------------

   Given the location of a public key file *$key_file*, reads the public
key from that file.

   If called in list context, returns the key and the comment associated
with the key. If called in scalar context, returns only the key.

   Dies if: the key file *$key_file* can't be opened for reading; or the
key file is "bad" (the ID string in the file doesn't match the
PRIVATE_KEY_ID_STRING constant).

   The key returned is in the form of a public key-a hash reference with
three keys: bits, n, and e. n and e and multiple-precision integers
(*Math::GMP* objects).

_load_private_key($key_file, $passphrase)
-----------------------------------------

   Given the location of a private key file *$key_file*, and an optional
passphrase to decrypt the key, reads the private key from that file.

   If called in list context, returns the key and the comment associated
with the key. If called in scalar context, returns only the key.

   Dies if: the key file *$key_file* can't be opened for reading; the key
file is "bad" (the ID string in the file doesn't match the
PRIVATE_KEY_ID_STRING constant); the file is encrypted using an
unsupported encryption cipher; or the passphrase *$passphrase* is
incorrect.

   The key returned is in the form of a private key-a hash reference with
there keys: bits, n, e, d, u, p, and q. All but bits are multiple-precision
integers (*Math::GMP* objects).

_read_passphrase($prompt)
-------------------------

   Uses Term::ReadKey with echo off to read a passphrase, after issuing
the prompt *$prompt*. Echo is restored once the passphrase has been read.

_respond_to_rsa_challenge($ssh, $challenge, $key)
-------------------------------------------------

   Decrypts the RSA challenge *$challenge* using $key, then the response
(MD5 of decrypted challenge and session ID) to the server, using the
*$ssh* object, in an RSA response packet.

_rsa_public_encrypt($data, $key)
--------------------------------

   Encrypts the multiple-precision integer $data (a *Math::GMP* object)
using $key.

   Returns the encrypted data, also a *Math::GMP* object.

_rsa_private_decrypt($data, $key)
---------------------------------

   Decrypts the multiple-precision integer $data (a *Math::GMP* object)
using $key.

   Returns the decrypted data, also a *Math::GMP* object.

AUTHOR & COPYRIGHTS
===================

   Please see the Net::SSH::Perl manpage for author, copyright, and
license information.

Extensible, general Perl server engine
**************************************

NAME
====

   Net::Server - Extensible, general Perl server engine

SYNOPSIS
========

     package MyPackage;

     use Net::Server;
     @ISA = qw(Net::Server);

     sub process_request {
        #...code...
     }

     MyPackage->run();

FEATURES
========

     * Single Server Mode
     * Inetd Server Mode
     * Preforking Mode
     * Forking Mode
     * Multi port accepts on Single, Preforking, and Forking modes
     * User customizable hooks
     * Chroot ability after bind
     * Change of user and group after bind
     * Basic allow/deny access control
     * Taint clean
     * Written in Perl
     * Protection against buffer overflow
     * Clean process flow
     * Extensibility

DESCRIPTION
===========

   `Net::Server' is an extensible, generic Perl server engine.
`Net::Server' combines the good properties from `Net::Daemon' (0.34),
`NetServer::Generic' (1.03), and `Net::FTPServer' (1.0), and also from
various concepts in the Apache Webserver.

   `Net::Server' attempts to be a generic server as in `Net::Daemon' and
`NetServer::Generic'.  It includes with it the ability to run as an inetd
process (`Net::Server::INET'), a single connection server (`Net::Server'
or `Net::Server::Single'), a forking server (`Net::Server::Fork'), or as a
preforking server (`Net::Server::PreFork').  In all but the inetd type, the
server provides the ability to connect to one or to multiple server ports.

   `Net::Server' uses ideologies of `Net::FTPServer' in order to provide
extensibility.  The additional server types are made possible via
"personalities" or sub classes of the `Net::Server'.  By moving the
multiple types of servers out of the main `Net::Server' class, the
`Net::Server' concept is easily extended to other types (in the near
future, we would like to add a "Thread" personality).

   `Net::Server' borrows several concepts from the Apache Webserver.
`Net::Server' uses "hooks" to allow custom servers such as SMTP, HTTP,
POP3, etc. to be layered over the base `Net::Server' class.  In addition
the `Net::Server::PreFork' class borrows concepts of min_start_servers,
max_servers, and min_waiting servers.  `Net::Server::PreFork' also uses
the concept of an flock serialized accept when accepting on multiple ports.

PERSONALITIES
=============

   `Net::Server' is built around a common class (Net::Server) and is
extended using sub classes, or `personalities'.  Each personality
inherits, overrides, or enhances the base methods of the base class.

   Included with the Net::Server package are several basic personalities,
each of which has their own use.

Fork
     Found in the module Net/Server/Fork.pm (see Net/Server/Fork).
     This server binds to one or more ports and then
     waits for a connection.  When a client request is received, the
     parent forks a child, which then handles the client and exits.  This
     is good for moderately hit services.

INET
     Found in the module Net/Server/INET.pm (see Net/Server/INET).
     This server is designed to be used with inetd.
     The `pre_bind', bind, accept, and `post_accept' are all overridden as
     these services are taken care of by the INET daemon.

MultiType
     Found in the module Net/Server/MultiType.pm (see
     Net/Server/MultiType).  This server has no
     server functionality of its own.  It is designed for servers which
     need a simple way to easily switch between different personalities.
     Multiple server_type parameters may be given and
     Net::Server::MultiType will cycle through until it finds a class that
     it can use.

PreFork
     Found in the module Net/Server/PreFork.pm (see
     Net/Server/PreFork).  This server binds to one
     or more ports and then forks min_servers child process.  The server
     will make sure that at any given time there are spare_servers
     available to receive a client request, up to max_servers.  Each of
     these children will process up to max_requests client connections.
     This type is good for a heavily hit site, and should scale well for
     most applications.  (Multi port accept is accomplished using flock to
     serialize the children).

Single
     All methods fall back to Net::Server.  This personality is provided
     only as parallelism for Net::Server::MultiType.

   `Net::Server' was partially written to make it easy to add new
personalities.  Using separate modules built upon an open architecture
allows for easy addition of new features, a separate development process,
and reduced code bloat in the core module.

SAMPLE
======

   The following is a very simple server.  The main functionality occurs
in the process_request method call as shown below.  Notice the use of
timeouts to prevent Denial of Service while reading.  (Other examples of
using `Net::Server' can, or will, be included with this distribution).

     #!/usr/bin/perl -w -T
     #--------------- file test.pl ---------------

     package MyPackage;

     use strict;
     use vars qw(@ISA);
     use Net::Server::PreFork; # any personality will do

     @ISA = qw(Net::Server::PreFork);

     MyPackage->run();
     exit;

     ### over-ridden subs below

     sub process_request {
       my $self = shift;
       eval {

     local $SIG{ALRM} = sub { die "Timed Out!\n" };
     my $timeout = 30; # give the user 30 seconds to type a line

     my $previous_alarm = alarm($timeout);
     while( <STDIN> ){
       s/\r?\n$//;
       print "You said \"$_\"\r\n";
       alarm($timeout);
     }
     alarm($previous_alarm);

     };

     if( $@=~/timed out/i ){
       print STDOUT "Timed Out.\r\n";
       return;
     }

     }

     1;

     #--------------- file test.pl ---------------

   Playing this file from the command line will invoke a Net::Server using
the PreFork personality.  When building a server layer over the
Net::Server, it is important to use features such as timeouts to prevent
Denial of Service attacks.

ARGUMENTS
=========

   There are four possible ways to pass arguments to Net::Server.  They
are *passing on command line*, *using a conf file*, *passing parameters to
run*, or *using a pre-built object to call the run method*.

   Arguments consist of key value pairs.  On the commandline these pairs
follow the POSIX fashion of `--key value' or `--key=value', and also
`key=value'.  In the conf file the parameter passing can best be shown by
the following regular expression: ($key,$val)=~/^(\w+)\s+(\S+?)\s+$/.
Passing arguments to the run method is done as follows:
`Net::Server-'run(key1 => 'val1')>.  Passing arguments via a prebuilt
object can best be shown in the following code:

     #!/usr/bin/perl -w -T
     #--------------- file test2.pl ---------------
     package MyPackage;
     use strict;
     use vars (@ISA);
     use Net::Server;
     @ISA = qw(Net::Server);

     my $server = bless {
       key1 => 'val1',
       }, 'MyPackage';

     $server->run();
     #--------------- file test.pl ---------------

   All four methods for passing arguments may be used at the same time.
Once an argument has been set, it is not over written if another method
passes the same argument.  `Net::Server' will look for arguments in the
following order:

     1) Arguments contained in the prebuilt object.
     2) Arguments passed on command line.
     3) Arguments passed to the run method.
     4) Arguments passed via a conf file.

   Key/value pairs used by the server are removed by the configuration
process so that server layers on top of `Net::Server' can pass and read
their own parameters.  Currently, Getopt::Long is not used. The following
arguments are available in the default `Net::Server' or
`Net::Server::Single' modules.  (Other personalities may use additional
parameters and may optionally not use parameters from the base class.)

     Key               Value            Default
     conf_file         "filename"       undef

     log_level         0-5              1
     log_file          "filename"       undef
     pid_file          "filename"       undef

     port              \d+              20203
     host              "host"           "localhost"
     proto             "proto"          "tcp"
     listen            \d+              10

     reverse_lookups   1                undef
     allow             /regex/          none
     deny              /regex/          none

     chroot            "directory"      undef
     user              (uid|username)   "nobody"
     group             (gid|group)      "nobody"
     background        1                undef

conf_file
     Filename from which to read additional key value pair arguments for
     starting the server.  Default is undef.

log_level
     Ranges from 0 to 5 in level.  Specifies what level of error will be
     logged.  "O" means logging is off.  "5" means very verbose.  These
     levels should be able to correlate to syslog levels.  Default is 1.

log_file
     Name of log file to be written to.  If no name is given and hook is
     not overridden, log goes to STDERR.  Default is undef.

pid_file
     Filename to store pid of parent process.  Generally applies only to
     forking servers.  Default is none (undef).

port
     Local port on which to bind.  If low port, process must start as
     root.  If multiple ports are given, all will be bound at server
     startup.  May be of the form `host:port/proto', `host:port', or port,
     where host represents a hostname residing on the local box, where
     port represents either the number of the port (eg. "80") or the
     service designation (eg.  "http"), and where proto represents the
     protocol to be used.  If the protocol is not specified, proto will
     default to the proto specified in the arguments.  If proto is not
     specified there it will default to "tcp".  If host is not specified,
     host will default to host specified in the arguments.  If host is not
     specified there it will default to "localhost".  Default port is
     20203.

host
     Local host or addr upon which to bind port.  See IO/Socket.

proto
     Protocol to use when binding ports.  See IO/Socket.

listen
          See L<IO::Socket>

reverse_lookups
     Specify whether to lookup the hostname of the connected IP.
     Information is cached in server object under peerhost property.
     Default is to not use reverse_lookups (undef).

allow/deny
     May be specified multiple times.  Contains regex to compare to
     incoming peeraddr or peerhost (if reverse_lookups has been enabled).
     If allow or deny options are given, the incoming client must match an
     allow and not match a deny or the client connection will be closed.
     Defaults to empty array refs.

chroot
     Directory to chroot to after bind process has taken place and the
     server is still running as root.  Defaults to undef.

user
     Userid or username to become after the bind process has occured.
     Defaults to "nobody."  If you would like the server to run as root,
     you will have to specify user equal to "root".

group
     Groupid or groupname to become after the bind process has occured.
     Defaults to "nobody."  If you would like the server to run as root,
     you will have to specify group equal to "root".

background
     Specifies whether or not the server should fork after the bind method
     to release itself from the command line.  Defaults to undef.

PROPERTIES
==========

   All of the ARGUMENTS listed above become properties of the server
object under the same name.  These properties, as well as other internal
properties, are available during hooks and other method calls.

   The structure of a Net::Server object is shown below:

     $self = bless( {
                      'server' => {
                                    'key1' => 'val1',
                                    # more key/vals
                                  }
                    }, 'Net::Server' );

   This structure was chosen so that all server related properties are
grouped under a single key of the object hashref.  This is so that other
objects could layer on top of the Net::Server object class and still have
a fairly clean namespace in the hashref.

   You may get and set properties in two ways.  The suggested way is to
access properties directly via

     my $val = $self->{server}->{key1};

   Accessing the properties directly will speed the server process.  A
second way has been provided for object oriented types who believe in
methods.  The second way consists of the following methods:

     my $val = $self->get_property( 'key1' );
     my $self->set_property( key1 => 'val1' );

   Properties are allowed to be changed at any time with caution (please
do not undef the sock property or you will close the client connection).

CONFIGURATION FILE
==================

   `Net::Server' allows for the use of a configuration file to read in
server parameters.  The format of this conf file is simple key value
pairs.  Comments and white space are ignored.

     #-------------- file test.conf --------------

     ### user and group to become
     user        somebody
     group       everybody

     ### logging ?
     log_file    /var/log/server.log
     log_level   3
     pid_file    /tmp/server.pid

     ### access control
     allow       .+\.(net|com)
     allow       domain\.com
     deny        a.+

     ### background the process?
     background  1

     ### ports to bind (this should bind
     ### 127.0.0.1:20205 and localhost:20204)
     host        127.0.0.1
     port        localhost:20204
     port        20205

     ### reverse lookups ?
     # reverse_lookups on

     #-------------- file test.conf --------------

PROCESS FLOW
============

   The process flow is written in an open, easy to override, easy to hook,
fashion.  The basic flow is shown below.

     $self->configure_hook;

     $self->configure(@_);

     $self->post_configure;

     $self->post_configure_hook;

     $self->pre_bind;

     $self->bind;

     $self->post_bind_hook;

     $self->post_bind;

     $self->pre_loop_hook;

     $self->loop;

     ### routines inside a standard $self->loop
     # $self->accept;
     # $self->run_client_connection;
     # $self->done;

     $self->pre_server_close_hook;

     $self->server_close;

   The server then exits.

   During the client processing phase (`$self->run_client_connection'),
the following represents the program flow:

     $self->post_accept;

     $self->get_client_info;

     $self->post_accept_hook;

     if( $self->allow_deny

     && $self->allow_deny_hook ){

         $self->process_request;

     }else{

     $self->request_denied_hook;

     }

     $self->post_process_request_hook;

     $self->post_process_request;

   The process then loops and waits for the next connection.  For a more
in depth discussion, please read the code.

HOOKS
=====

   `Net::Server' provides a number of "hooks" allowing for servers layered
on top of `Net::Server' to respond at different levels of execution.

`$self->configure_hook()'
     This hook takes place immediately after the `->run()' method is
     called.  This hook allows for setting up the object before any built
     in configuration takes place.  This allows for custom configurability.

`$self->post_configure_hook()'
     This hook occurs just after the reading of configuration parameters
     and initiation of logging and pid_file creation.  It also occurs
     before the `->pre_bind()' and `->bind()' methods are called.  This
     hook allows for verifying configuration parameters.

`$self->post_bind_hook()'
     This hook occurs just after the bind process and just before any
     chrooting, change of user, or change of group occurs.  At this point
     the process will still be running as the user who started the server.

`$self->pre_loop_hook()'
     This hook occurs after chroot, change of user, and change of group
     has occured.  It allows for preparation before looping begins.

`$self->post_accept_hook()'
     This hook occurs after a client has connected to the server.  At this
     point STDIN and STDOUT are mapped to the client socket.  This hook
     occurs before the processing of the request.

`$self->allow_deny_hook()'
     This hook allows for the checking of ip and host information beyond
     the `$self->allow_deny()' routine.  If this hook returns 1, the
     client request will be processed, otherwise, the request will be
     denied processing.

`$self->request_denied_hook()'
     This hook occurs if either the `$self->allow_deny()' or
     `$self->allow_deny_hook()' have taken place.

`$self->post_process_request_hook()'
     This hook occurs after the processing of the request, but before the
     client connection has been closed.

`$self->pre_server_close_hook()'
     This hook occurs before the server begins shutting down.

`$self->write_to_log_hook'
     This hook handles writing to log files.  The default hook is to write
     to STDERR, or to the filename contained in the parameter log_file.
     The arguments passed are a log level of 0 to 5 (5 being very
     verbose), and a log line.  If it is desired to use the syslog, a
     customized hook may be put in place.  (A future version may include
     this as a configurable option).

`$self->fatal_hook'
     This hook occurs when the server has encountered an unrecoverable
     error.  Arguments passed are the error message, the package, file,
     and line number.  The hook may close the server, but it is suggested
     that it simply return and use the built in shut down features.

TO DO
=====

   There are several tasks to perform before the alpha label can be
removed from this software:

Use It
     The best way to further the status of this project is to use it.
     There are immediate plans to use this as a base class in implementing
     some mail servers and banner servers on a high hit site.

Thread Personality
     Some servers offer a threaded server.  Create `Net::Server::Thread'
     as a new personality.

Other Personalities
     Explore any other personalities

Sig Handling
     Solidify which signals are handled by base class.  Possibly catch
     more that are ignored currently.

`HUP'
     Allow for a clean hup allowing for re-exec and re-read of
     configuration files.  This includes multiport mode.

Net::HTTPServer, etc
     Create various types of servers.  Possibly, port exising servers to
     user Net::Server as a base layer.

More documentation
     Show more examples and explain process flow more.

Better Tests
     Do better tests during "make test"

FILES
=====

     The following files are installed as part of this
     distribution.

     Net/Server.pm
     Net/Server/Fork.pm
     Net/Server/INET.pm
     Net/Server/MultiType.pm
     Net/Server/PreFork.pm
     Net/Server/Single.pm

AUTHOR
======

   Paul T. Seamons paul@seamons.com

THANKS
======

   Thanks to Rob Brown for help with miscellaneous concepts such as
tracking down the serialized select via flock ala Apache.  Thanks to
Jonathan J. Miner for patching a blatant problem in the reverse lookups.

SEE ALSO
========

   Please see also Net/Server/Fork,
Net/Server/INET, Net/Server/PreFork,
see Net/Server/MultiType,
Net/Server/Single,

COPYRIGHT
=========

     Copyright (C) 2001, Paul T Seamons
                         paul@seamons.com

     This package may be distributed under the terms of either the
     GNU General Public License
       or the
     Perl Artistic License

     All rights reserved.

Net::Server personality
***********************

NAME
====

   Net::Server::Fork - Net::Server personality

SYNOPSIS
========

     use Net::Server::Fork;
     @ISA = qw(Net::Server::Fork);

     sub process_request {
        #...code...
     }

     Net::Server::Fork->run();

DESCRIPTION
===========

   Please read the pod on Net::Server first.  This module is a
personality, or extension, or sub class, of the Net::Server module.

   This personality binds to one or more ports and then waits for a client
connection.  When a connection is received, the server forks a child.  The
child handles the request and then closes.

ARGUMENTS
=========

   There are no additional arguments beyond the Net::Server base class.

CONFIGURATION FILE
==================

   See Net/Server.

PROCESS FLOW
============

   Process flow follows Net::Server until the post_accept phase.  At this
point a child is forked.  The parent is immediately able to wait for
another request.  The child handles the request and then exits.

HOOKS
=====

   There are no additional hooks in Net::Server::Fork.

TO DO
=====

   See Net/Server,

FILES
=====

     The following files are installed as part of this
     distribution.

     Net/Server.pm
     Net/Server/Fork.pm
     Net/Server/INET.pm
     Net/Server/MultiType.pm
     Net/Server/PreFork.pm
     Net/Server/Single.pm

AUTHOR
======

   Paul T. Seamons paul@seamons.com

SEE ALSO
========

   Please see also Net/Server/Fork,
Net/Server/INET, Net/Server/PreFork,
see Net/Server/MultiType,
Net/Server/Single,

Net::Server personality
***********************

NAME
====

   Net::Server::INET - Net::Server personality

SYNOPSIS
========

     use Net::Server::INET;
     @ISA = qw(Net::Server::INET);

     sub process_request {
        #...code...
     }

     Net::Server::INET->run();

DESCRIPTION
===========

   Please read the pod on Net::Server first.  This module is a
personality, or extension, or sub class, of the Net::Server module.

   This personality is intended for use with inetd.  It offers no methods
beyond the Net::Server base class.  This module operates by overriding the
pre_bind, bind, accept, and post_accept methods to let all socket
processing to be done by inetd.

CONFIGURATION FILE
==================

   See Net/Server.

PROCESS FLOW
============

   See Net/Server,

HOOKS
=====

   There are no additional hooks in Net::Server::INET.

TO DO
=====

   See Net/Server,

FILES
=====

     The following files are installed as part of this
     distribution.

     Net/Server.pm
     Net/Server/Fork.pm
     Net/Server/INET.pm
     Net/Server/MultiType.pm
     Net/Server/PreFork.pm
     Net/Server/Single.pm

AUTHOR
======

   Paul T. Seamons paul@seamons.com

SEE ALSO
========

   Please see also Net/Server/Fork,
Net/Server/INET, Net/Server/PreFork,
see Net/Server/MultiType,
Net/Server/Single,

Net::Server personality
***********************

NAME
====

   Net::Server::MultiType - Net::Server personality

SYNOPSIS
========

     use Net::Server::MultiType;
     @ISA = qw(Net::Server::MultiType);

     sub process_request {
        #...code...
     }

     my @types = qw(PreFork Fork Single);

     Net::Server::MultiType->run(server_type=>\@types);

DESCRIPTION
===========

   Please read the pod on Net::Server first.  This module is a
personality, or extension, or sub class, of the Net::Server module.

   This personality is intended to allow for easy use of multiple
Net::Server personalities.  Given a list of server types,
Net::Server::MultiType will require one at a time until it finds one that
is installed on the system.  It then adds that package to its @ISA, thus
inheriting the methods of that personality.

ARGUMENTS
=========

   In addition to the command line arguments of the Net::Server base
class, Net::Server::MultiType contains one other configurable parameter.

     Key               Value            Default
     server_type       'server_type'    'Single'

server_type
     May be called many times to build up an array or possible
     server_types.  At execution, Net::Server::MultiType will find the
     first available one and then inherit the methods of that personality

CONFIGURATION FILE
==================

   `Net::Server::PreFork' allows for the use of a configuration file to
read in server parameters.  The format of this conf file is simple key
value pairs.  Comments and white space are ignored.

     #-------------- file test.conf --------------

     ### multi type info
     ### try PreFork first, then go to Single
     server_type PreFork
     server_type Single

     ### server information
     min_servers   20
     max_servers   80
     spare_servers 10

     max_requests  1000

     ### user and group to become
     user        somebody
     group       everybody

     ### logging ?
     log_file    /var/log/server.log
     log_level   3
     pid_file    /tmp/server.pid

     ### access control
     allow       .+\.(net|com)
     allow       domain\.com
     deny        a.+

     ### background the process?
     background  1

     ### ports to bind
     host        127.0.0.1
     port        localhost:20204
     port        20205

     ### reverse lookups ?
     # reverse_lookups on

     #-------------- file test.conf --------------

PROCESS FLOW
============

   See Net/Server,

HOOKS
=====

   There are no additional hooks in Net::Server::MultiType.

TO DO
=====

   See Net/Server,

FILES
=====

     The following files are installed as part of this
     distribution.

     Net/Server.pm
     Net/Server/Fork.pm
     Net/Server/INET.pm
     Net/Server/MultiType.pm
     Net/Server/PreFork.pm
     Net/Server/Single.pm

AUTHOR
======

   Paul T. Seamons paul@seamons.com

SEE ALSO
========

   Please see also Net/Server/Fork,
Net/Server/INET, Net/Server/PreFork,
see Net/Server/MultiType,
Net/Server/Single,

Net::Server personality
***********************

NAME
====

   Net::Server::PreFork - Net::Server personality

SYNOPSIS
========

     use Net::Server::PreFork;
     @ISA = qw(Net::Server::PreFork);

     sub process_request {
        #...code...
     }

     Net::Server::PreFork->run();

DESCRIPTION
===========

   Please read the pod on Net::Server first.  This module is a
personality, or extension, or sub class, of the Net::Server module.

   This personality binds to one or more ports and then forks min_servers
child process.  The server will make sure that at any given time there are
spare_servers available to receive a client request, up to max_servers.
Each of these children will process up to max_requests client connections.
This type is good for a heavily hit site, and should scale well for most
applications.  (Multi port accept is accomplished using flock to serialize
the children).

SAMPLE CODE
===========

   Please see the sample listed in Net::Server.

COMMAND LINE ARGUMENTS
======================

   In addition to the command line arguments of the Net::Server base
class, Net::Server::PreFork contains several other configurable parameters.

     Key               Value            Default
     min_servers       \d+              5
     spare_servers     \d+              1
     max_servers       \d+              10
     max_requests      \d+              1000

     lock_file         "filename"       POSIX::tmpnam

     check_for_dead    \d+              30
     check_for_waiting \d+              20

min_servers
     The minimum number of servers to keep running.

spare_servers
     The minimum number of servers to have waiting for requests.

max_servers
     The maximum number of child servers to start.

max_requests
     The number of client connections to receive before a child terminates.

lock_file
     Filename to use in multi-port accept in order to flock serialize the
     accept sequece between the children.  This will default to a
     generated temporary filename.  This file will be removed when the
     server closes.

check_for_dead
     Seconds to wait before checking to see if a child died without
     letting the parent know.

check_for_waiting
     Seconds to wait before checking to see if there are too many waiting
     child processes.  Extra processes are killed.  A time period is used
     rather than min_spare_servers and max_spare_server parameters to
     avoid constant forking and killing when client requests are coming in
     close to the spare server thresholds.

CONFIGURATION FILE
==================

   `Net::Server::PreFork' allows for the use of a configuration file to
read in server parameters.  The format of this conf file is simple key
value pairs.  Comments and white space are ignored.

     #-------------- file test.conf --------------

     ### server information
     min_servers   20
     max_servers   80
     spare_servers 10

     max_requests  1000

     ### user and group to become
     user        somebody
     group       everybody

     ### logging ?
     log_file    /var/log/server.log
     log_level   3
     pid_file    /tmp/server.pid

     ### access control
     allow       .+\.(net|com)
     allow       domain\.com
     deny        a.+

     ### background the process?
     background  1

     ### ports to bind
     host        127.0.0.1
     port        localhost:20204
     port        20205

     ### reverse lookups ?
     # reverse_lookups on

     #-------------- file test.conf --------------

PROCESS FLOW
============

   Process flow follows Net::Server until the loop phase.  At this point
min_servers are forked and wait for connections.  When a child accepts a
connection, finishs processing a client, or exits, it relays that
information to the parent, which keeps track and makes sure there are
enough children to fulfill min_servers, spare_servers, and max_servers.

HOOKS
=====

   There are two additional hooks in the PreFork server.

`$self->child_init_hook()'
     This hook takes place immeditately after the child process forks from
     the parent and before the child begins accepting connections.  It is
     intended for any addiotional chrooting or other security measures.
     It is suggested that all perl modules be used by this point, so that
     the most shared memory possible is used.

`$self->child_finish_hook()'
     This hook takes place immediately before the child tells the parent
     that it is exiting.  It is intended for saving out logged information
     or other general cleanup.

TO DO
=====

   See Net/Server,

FILES
=====

     The following files are installed as part of this
     distribution.

     Net/Server.pm
     Net/Server/Fork.pm
     Net/Server/INET.pm
     Net/Server/MultiType.pm
     Net/Server/PreFork.pm
     Net/Server/Single.pm

AUTHOR
======

   Paul T. Seamons paul@seamons.com

SEE ALSO
========

   Please see also Net/Server/Fork,
Net/Server/INET, Net/Server/PreFork,
see Net/Server/MultiType,
Net/Server/Single,

Net::Server personality
***********************

NAME
====

   Net::Server::Single - Net::Server personality

SYNOPSIS
========

     use Net::Server::MultiType;
     @ISA = qw(Net::Server::MultiType);

     sub process_request {
        #...code...
     }

     my @types = qw(PreFork Single Fork);

     Net::Server::MultiType->run(server_type=>\@types);

DESCRIPTION
===========

   This module offers no functionality beyond the Net::Server base class.
This modules only purpose is to provide parallelism for the MultiType
personality.

   See Net/Server,

A Perl extension for writing spooling daemons
*********************************************

NAME
====

   Net::Spooler - A Perl extension for writing spooling daemons

SYNOPSIS
========

     # Create a subclass of Net::Spooler
     use Net::Spooler;
     package MySpooler;
     @MySpooler::ISA = qw(Net::Spooler);

     # Inherit everything, except a single method:
     sub ProcessFile {
       my $self = shift; my $file = shift;

     # Try to process the file here
     ...

     # Raise an exception, if something went wrong:
     die "Failed: $!" unless Something();

     # Return to indicate sucess.
       }

     # Create and run the spooler
     package main;
     my $spooler = Net::Spooler->new(
         'spool-dir' => '/var/myspooler'
     );
     $spooler->Bind();

DESCRIPTION
===========

   This package contains a spooling daemon, in other words a process, that
accepts files from an outside source (currently a Unix or TCP/IP socket),
stores them in a spooling directory and processes them.

   The package is implemented as an abstract base class: It is not usefull
in itself, but you can get your spooling daemon easily by deriving a
concrete subclass from `Net::Spooler'. In the best case you can inherit
everything and overwrite just a single method, the *ProcessFile* method,
which attempts to process a single file from the spooling directory.

   `Net::Spooler' is in turn derived from the `Net::Daemon' package, thus
it borrows class design, in particular methods and attributes, from
`Net::Daemon'. See Net/Daemon, for details on this
superclass.

   However, there are a few additions to `Net::Daemon':

Attributes
----------

   Like in `Net::Daemon', attributes can be set via the command line, in
the config file or as constructor arguments (order descending from most
important). And remember, that you can use the `Net::Daemon' attributes
too! See Net/Daemon.

admin (B<-admin=<email>)
     The administrators email address. From time to time it may happen,
     that the admin receives an email in case of problems.

expiretime (*-expiretime=<time>*)
     If processing a file fails repeatedly, the file may finally expire.
     This means that the file will be removed from the spool directory and
     a message is sent to the administrator.

     The default value are 432000 seconds (5 days). A value of 0 means
     that expiration never happens.

     Example: Expire after 3 days.

          --expiretime=259200

maxsixe (*-maxsize=<maxsize>*)
     By default the maximum size of a file is restricted to 100000 bytes
     and larger files will be rejected. This option is changing the size,
     a value of 0 means disabling the limitation.

     Example: Disable max size

          --maxsize=0

processtimeout (*-processtimeout=<timeout>*)
     If processing a single file may result in an endless loop, or simply
     run too long, then you may specify a timeout. The daemon will raise a
     signal after the given amount of seconds and stop processing the
     file, as if the method `ProcessFile' raised an exception.

     The default value is 0 seconds which means that no timeout is used.

     Example: Use a timeout of 30 seconds.

          --processtimeout=30

*loop-timeout* (*-loop-timeout=<time>*)
     If processing a file failed, the spooler will reprocess the file
     later by forking a child process after the given amount of seconds,
     by default 300 seconds (5 minutes). This child process will run
     through all scheduled file

*spool-dir* (*-spool-dir=<dir>*)
     If the daemon accepts files, they are stored in the *spool directory*.
     There's no default, you must set this attribute.

     Example: Use `/var/myspooler' as a spool directory.

          --spool-dir=/var/myspooler

tmpfiles
     This attribute is for internal use only. It contains an hash ref, the
     keys being temporary file names to be removed later.

Methods
-------

   As already said, the `Net::Spooler' package inherits from `Net::Daemon'.
All methods of the superclass are still valid in `Net::Spooler', in
particular access control and the like. See Net/Daemon,
for details.

Processing a file
          $self->ProcessFile($file)

     (Instance method) Called for processing a single file. This is
     typically the only method you have to overwrite.

     The method raises an exception in case of errors. If an exception is
     raised, the scheduler will later retry to process the file until it
     expires. See the *queuetime* and expiretime attributes above.

     If processing a file exceeds the processtimeout (see above), then the
     scheduler will cancel processing the method and continue as if it
     raised an exception. (This timeout can be disabled by setting it to 0,
     the default value.)

     If the method returns without raising an exception, then the scheduler
     assumes that the file was processed successfully and remove it from
     the spool directory.

Choosing file names
          my $sfile = $self->SequenceFile();
          my $seq = $self->Sequence($sfile);
          my $dfile = $self->DataFile($seq);
          my $cfile = $self->ControlFile($seq);

     (Instance methods) If the daemon receives a new file, it has to
     choose a name for it. These names are constructed as follows:

     First of all, a so-called sequence number is generated by calling the
     method Sequence. By default these are the numbers 1, 2, 3, ...  in 8
     hex digits (00000001, 00000002, 00000003, ...). The last generated
     sequence number is always stored in the sequence file (by default
     `$spool-dir/.sequence', set by calling the *SequenceFile* method).

     Two files are generated for processing the file: The *data file* is
     the unmodified file, as received by the client. The *control file*
     contains information used internally by `Net::Spooler', for example
     the time and date of spooling this file. By default the names
     `$spool-dir/$seq.dat' and `$spool-dir/$seq.ctl' are used, generated
     by calling the methods DataFile and *ControlFile*. Temporary file
     names are derived by adding the suffix `.tmp'.

     Typically you rarely need to overwrite these methods.

Accepting a file from the client
          $self->ReadFile($socket, $fh, $file, $control);

     (Instance method) This method is actually reading the file $file from
     the socket $socket. The file is already opened and the method must use
     the file handle $fh for writing into $file. (The file name is passed
     for creating error messages only.)

     The method may store arbitrary data in the hash ref $control: This
     hash ref is stored in the control file later.

     The default implementation is accepting a raw file on the socket. You
     should overwrite the method, if you are accepting structured data,
     for example 4 bytes of file size and then the raw file. However, if
     you do overwrite this method, you should consider the *maxsize*
     attribute. (See above.)

     A Perl exception is raised in case of problems.

Creating the control file
          $self->ControlFile($fh, $file, $control);

     (Instance method) Creates the control file $file by writing the hash
     ref $control into the open file handle $fh. (The file name $file is
     passed for use in error messages only.)

     The default implementation is using the Data::Dumper module for
     serialization of $control and then writing the dumped hash ref into
     $fh.

     A Perl exception is raised in case of problems; nothing is returned
     otherwise.

Reading the control file
          my $ctrl = $self->ReadControlFile($file);

     (Instance method) This method reads a control file, as created by the
     *ControlFile* method and creates an instance of
     *Net::Spooler::Control*.

     The default implementation does a simple require (in a Safe
     compartment for security reasons, see the Safe, package
     for details) for loading the hash ref from the file. The hash ref is
     then blessed into the package corresponding to $self: The package
     name of $self is taken by appending the string *::Control*.

     The method returns nothing, a Perl exception is thrown in case of
     trouble.

AUTHOR AND COPYRIGHT
====================

   This package is

     Copyright (C) 1999		Jochen Wiedmann
                                   Am Eisteich 9
     			        72555 Metzingen
     				Germany

     E-Mail: joe@ispsoft.de

     All rights reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SEE ALSO
========

     L<Net::Daemon(3)>

Count hosts in named subnets
****************************

NAME
====

   Net::Subnet::Count - Count hosts in named subnets

SYNOPSIS
========

     use Net::Subnet::Count;
     use IP::Address;

     my $counter = new Net::Subnet::Count;

     $counter->add('subnet-00', new IP::Address("10.0.0.0/24"));
     $counter->add('other', @array_of_ip_addresses);
     $counter->add('other', @another_array_of_ip_addresses);

     $counter->cache(10);

     $counter->count(new IP::Address("10.0.3.17"));
     $counter->count(@array_of_ip_addresses);

     $counter->valcount(new IP::Address("10.0.3.17"), 23);
     @array_of_ipaddr_and_values = (new IP::Address("10.0.3.17"), 23,
     				new IP::Address("101.0.23.107"), 2);
     $counter->valcount(@array_of_ipaddr_and_values);

     my $r_count = $counter->result;

     foreach my $subnet (keys %{$r_count}) {
         print "Subnet $subnet had ", $r_count->{$subnet}, " visits.\n";
     }

DESCRIPTION
===========

   This module implements a symplistic way to match individual IP
Addresses to subnets. It can be used to, among other things, help analyze
HTTPD logs.

   The following methods are implemented.

`->new'
     Creates a new counter. This method can be called passing as argument a
     hash where the keys are the name of the subnet group and the values
     are references to arrays of `IP::Address' objects referencing each
     specific subnet. This is probably ok for static initializations.

`->add'
     Adds a subnet group. The first parameter is the name of the group
     being added. If it's a new name, a new entry will be created. Else the
     given subnets are added to the existing ones, like in the example
     above.

`->count'
     Verifies if the `IP::Address'es are contained in any of the given
     subnets. If this is the case, the corresponding totals are updated.

`->valcount'
     The same as `->count' but the argument is an array consisting of
     `IP::Address'es and value pairs.

`->result'
     Returns a reference to a hash containing the respective totals for
     each subnet group. The key to the hash is the subnet name given with
     `->add', the value is how many `IP::Address' objects have been found
     to match that subnet group.

`->cache'
     Since in usual applications `IP::Addresses' from the same subnet will
     tend to be grouped in clusters like in the case of HTTPD logs some
     caching is attempted to speed things up. The caching consists in
     storing the last few entries matched in an LRU list which is checked
     before going through all the stored subnets.

     This can improve response times if tuned sensibly, however consider
     that every miss will cause every entry in the cache to be checked
     twice, one in the cache and one in the normal process so it's
     important to tune the cache.

     The default cache size is 5, which can be changed by calling the
     `->cache' method as in the example. The old value of the cache size
     is returned.

AUTHOR
======

   Luis E. Munoz <lem@cantv.net>. Alvaro Carvajal <alvaro@cantv.net>
contributed the valcount method.

SEE ALSO
========

   perl(1), IP::Address(1).

Perl extension for sending syslog messages directly to a remote syslogd.
************************************************************************

NAME
====

   Net::Syslog - Perl extension for sending syslog messages directly to a
remote syslogd.

SYNOPSIS
========

     use Net::Syslog;
     my $s=new Net::Syslog(Facility=>'local4',Priority=>'debug');
     $s->send('see this in syslog',Priority=>'info');

DESCRIPTION
===========

   Net::Syslog implements the intra-host syslog forwarding protocol.  It
is not intended to replace the Sys::Syslog or Unix::Syslog modules, but
instead to provide a method of using syslog when a local syslogd is
unavailable or when you don't want to write syslog messages to the local
syslog.

   The new call sets up default values, any of which can be overridden in
the send call.  Keys (listed with default values) are:

     Name		<calling script name>
     Facility 	local5
     Priority 	err
     SyslogPort    	514
     SyslogHost    	127.0.0.1

   Valid Facilities are: 	kern, user, mail, daemon, auth, syslog,
lpr, news, uucp, cron, 	authpriv, ftp, local0, local1, local2, local3,
local4, local5, local6

   Valid Priorities are: 	emerg, alert, crit, err, warning, notice,
info, debug

AUTHOR
======

   Les Howard, les@lesandchris.com

SEE ALSO
========

   syslog(3), Sys::Syslog(3), syslogd(8), Unix::Syslog(3), IO::Socket,
perl(1)

TCP sockets interface module
****************************

NAME
====

   Net::TCP - TCP sockets interface module

SYNOPSIS
========

     use Net::Gen;		# optional
     use Net::Inet;		# optional
     use Net::TCP;

DESCRIPTION
===========

   The `Net::TCP' module provides services for TCP communications over
sockets.  It is layered atop the `Net::Inet' and `Net::Gen' modules, which
are part of the same distribution.

Public Methods
--------------

   The following methods are provided by the `Net::TCP' module itself,
rather than just being inherited from `Net::Inet' or `Net::Gen'.

new
     Usage:

          $obj = new Net::TCP;
          $obj = new Net::TCP $host, $service;
          $obj = new Net::TCP \%parameters;
          $obj = new Net::TCP $host, $service, \%parameters;
          $obj = 'Net::TCP'->new();
          $obj = 'Net::TCP'->new($host, $service);
          $obj = 'Net::TCP'->new(\%parameters);
          $obj = 'Net::TCP'->new($host, $service, \%parameters);

     Returns a newly-initialised object of the given class.  If called for
     a derived class, no validation of the supplied parameters will be
     performed.  (This is so that the derived class can add the parameter
     validation it needs to the object before allowing the validation.)
     Otherwise, it will cause the parameters to be validated by calling
     its init method, which `Net::TCP' inherits from `Net::Inet'.  In
     particular, this means that if both a host and a service are given,
     then an object will only be returned if a connect() call was
     successful (or is still in progress, if the object is non-blocking).

     The examples above show the indirect object syntax which many prefer,
     as well as the guaranteed-to-be-safe static method call.  There are
     occasional problems with the indirect object syntax, which tend to be
     rather obscure when encountered.  See

     <URL:http://www.rosat.mpe-garching.mpg.de/mailing-lists/perl-porters/1998-01/msg01674.html>
     for details.

Protected Methods
-----------------

   none.

Known Socket Options
--------------------

   These are the socket options known to the `Net::TCP' module itself:

     `TCP_NODELAY' `TCP_MAXSEG' `TCP_RPTR2RXT'

Known Object Parameters
-----------------------

   There are no object parameters registered by the `Net::TCP' module
itself.

TIESCALAR
---------

   Tieing of scalars to a TCP handle is supported by inheritance from the
TIESCALAR method of `Net::Gen'.  That method only succeeds if a call to a
new method results in an object for which the isconnected method returns
true, which is why it is mentioned in connection with this module.

   Example:

     tie $x,Net::TCP,0,'finger' or die;
     $x = "-s\015\012";
     print $y while defined($y = $x);
     untie $x;

   This is an expensive re-implementation of finger -s on many machines.

   Each assignment to the tied scalar is really a call to the put method
(via the STORE method), and each read from the tied scalar is really a
call to the getline method (via the FETCH method).

Exports
-------

default
     none

exportable
     `TCPOPT_EOL' `TCPOPT_MAXSEG' `TCPOPT_NOP' `TCPOPT_WINDOW'
     `TCP_MAXSEG' `TCP_MAXWIN' `TCP_MAX_WINSHIFT' `TCP_MSS' `TCP_NODELAY'
     `TCP_RPTR2RXT' `TH_ACK' `TH_FIN' `TH_PUSH' `TH_RST' `TH_SYN' `TH_URG'

tags
     The following *:tags* are available for grouping related exportable
     items:

    :sockopts
          `TCP_NODELAY' `TCP_MAXSEG' `TCP_RPTR2RXT'

    :tcpoptions
          `TCPOPT_EOL' `TCPOPT_MAXSEG' `TCPOPT_NOP' `TCPOPT_WINDOW'

    :protocolvalues
          `TCP_MAXWIN' `TCP_MAX_WINSHIFT' `TCP_MSS' `TH_ACK' `TH_FIN'
          `TH_PUSH' `TH_RST' `TH_SYN' `TH_URG'

    :ALL
          All of the above exportable items.

THREADING STATUS
================

   This module has been tested with threaded perls, and should be as
thread-safe as perl itself.  (As of 5.005_03 and 5.005_57, that's not all
that safe just yet.)

SEE ALSO
========

   Net::Inet(3), Net::Gen(3), Net::TCP::Server(3)

AUTHOR
======

   Spider Boardman <spider@Orb.Nashua.NH.US>

TCP sockets interface module for listeners and servers
******************************************************

NAME
====

   Net::TCP::Server - TCP sockets interface module for listeners and
servers

SYNOPSIS
========

     use Net::Gen;		# optional
     use Net::Inet;		# optional
     use Net::TCP;		# optional
     use Net::TCP::Server;

DESCRIPTION
===========

   The `Net::TCP::Server' module provides services for TCP communications
over sockets.  It is layered atop the `Net::TCP', `Net::Inet', and
`Net::Gen' modules, which are part of the same distribution.

Public Methods
--------------

   The following methods are provided by the `Net::TCP::Server' module
itself, rather than just being inherited from `Net::TCP', `Net::Inet', or
`Net::Gen'.

new
     Usage:

          $obj = new Net::TCP::Server;
          $obj = new Net::TCP::Server $service;
          $obj = new Net::TCP::Server $service, \%parameters;
          $obj = new Net::TCP::Server $lcladdr, $service, \%parameters;
          $obj = 'Net::TCP::Server'->new();
          $obj = 'Net::TCP::Server'->new($service);
          $obj = 'Net::TCP::Server'->new($service, \%parameters);
          $obj = 'Net::TCP::Server'->new($lcladdr, $service, \%parameters);

     Returns a newly-initialised object of the given class.  This is much
     like the regular new method of the other modules in this
     distribution, except that it makes it easier to specify just a
     service name or port number, and it automatically does a setsockopt()
     call to set `SO_REUSEADDR' to make the bind() more likely to succeed.
     The `SO_REUSEADDR' is really done in a base class, but it's enabled
     by defaulting the reuseaddr object parameter to 1 in this constructor.

     The examples above show the indirect object syntax which many prefer,
     as well as the guaranteed-to-be-safe static method call.  There are
     occasional problems with the indirect object syntax, which tend to be
     rather obscure when encountered.  See

     <URL:http://www.rosat.mpe-garching.mpg.de/mailing-lists/perl-porters/1998-01/msg01674.html>
     for details.

     Simple example for server setup:

          $lh = 'Net::TCP::Server'->new(7788) or die;
          while ($sh = $lh->accept) {
          	defined($pid=fork) or die "fork: $!\n";
          	if ($pid) {		# parent doesn't need client fh
          	    $sh->stopio;
          	    next;
          	}
          	# child doesn't need listener fh
          	$lh->stopio;
          	# do per-connection stuff here
          	exit;
          }

     Note that signal-handling for the child processes is not included in
     this example.  See `"Internet TCP Clients and Servers"', see
     Perlipc (perl.info), for related examples which manage
     subprocesses.  However, on many operating systems, a simple
     `$SIG{CHLD} = 'IGNORE';' will prevent the server process from
     collecting `zombie' subprocesses.

Protected Methods
-----------------

   none.

Known Socket Options
--------------------

   There are no socket options specific to the `Net::TCP::Server' module.

Known Object Parameters
-----------------------

   There are no object parameters registered by the `Net::TCP::Server'
module itself.

Exports
-------

default
     none

exportable
     none

tags
     none

THREADING STATUS
================

   This module has been tested with threaded perls, and should be as
thread-safe as perl itself.  (As of 5.005_03 and 5.005_57, that's not all
that safe just yet.)

SEE ALSO
========

   Net::TCP(3), Net::Inet(3), Net::Gen(3)

AUTHOR
======

   Spider Boardman <spider@Orb.Nashua.NH.US>

TFTP Client class
*****************

NAME
====

   Net::TFTP - TFTP Client class

SYNOPSIS
========

     use Net::TFTP;

     $tftp = Net::TFTP->new("some.host.name", BlockSize => 1024);

     $tftp->ascii;

     $tftp->get("remotefile", "localfile");

     $tftp->get("remotefile", \*STDOUT);

     $fh = $tftp->get("remotefile");

     $tftp->binary;

     $tftp->put("localfile", "remotefile");

     $tftp->put(\*STDOUT, "remotefile");

     $fh = $tftp->put("remotefile");

     $err = $tftp->error

     $tftp->quit;

DESCRIPTION
===========

   `Net::TFTP' is a class implementing a simple *Trivial File Transfer
Protocol* client in Perl as described in RFC1350. `Net::TFTP' also
supports the TFTP Option Extension (as described in RFC2347), with the
following options

     RFC2348 Blocksize Option

CONSTRUCTOR
===========

new ( [ HOST ] [, OPTIONS ])
     Create a new Net::TFTP object where HOST is the default host to
     connect to and OPTIONS are the default transfer options. Valid
     options are

          Option     Description                                           Default
          ------     -----------                                           -------
          Timeout    Timeout in seconds before retry	                     5
          Retries    Maximum number of retries				     5
          Port	    Port to send data to                                    69
          Mode	    Mode to transfer data in, "octet" or "netascii"     "netascii"
          BlockSize  Negotiate size of blocks to use in the transfer        512

METHODS
=======

get ( REMOTE_FILE [, LOCAL ] [, OPTIONS ])
     Get REMOTE_FILE from the server. OPTIONS can be any that are accepted
     by new plus the following

          Host    Override default host

     If the LOCAL option is missing the get will return a filehandle. This
     filehandle must be read ASAP as the server will otherwise timeout.

     If the LOCAL option is given then it can be a file name or a
     reference.  If it is a reference it is assumed to be a reference that
     is valid as a filehandle. get will return *true* if the transfer is
     sucessful and undef otherwise.

     Valid filehandles are

        * A sub-class of IO::Handle

        * A tied filehandle

        * A GLOB reference (eg `\*STDOUT')

put ( [ LOCAL, ] REMOTE_FILE [, OPTIONS])
     Put a file to the server as REMOTE_FILE. OPTIONS can be any that are
     accepted by new plus the following

          Host    Override default host

     If the LOCAL option is missing the put will return a filehandle. This
     filehandle must be written to ASAP as the server will otherwise
     timeout.

     If the LOCAL option is given then it can be a file name or a
     reference.  If it is a reference it is assumed to be a valid
     filehandle as descibed above.  put will return *true* if the transfer
     is sucessful and undef otherwise.

error
     If there was an error then this method will return an error string.

host ( [ HOST ] )
timeout ( [ TIMEOUT ] )
port ( [ PORT ] )
mode ( [ MODE ] )
retries ( [ VALUE ] )
block_size ( [ VALUE ] )
debug ( [ VALUE ] )
     Set or get the values for the various options. If an argument is
     passed then a new value is set for that option and the previous value
     returned.  If no value is passed then the current value is returned.

ascii
netascii
     Set the transfer mode to `"netascii"'

binary
octet
     Set the transfer mode to `"octet"'

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

COPYRIGHT
=========

   Copyright (c) 1998 Graham Barr. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

interact with TELNET port or other TCP ports
********************************************

NAME
====

   Net::Telnet - interact with TELNET port or other TCP ports

SYNOPSIS
========

   `use Net::Telnet ();'

   see METHODS section below

DESCRIPTION
===========

   Net::Telnet allows you to make client connections to a TCP port and do
network I/O, especially to a port using the TELNET protocol.  Simple I/O
methods such as print, get, and getline are provided.  More sophisticated
interactive features are provided because connecting to a TELNET port
ultimately means communicating with a program designed for human
interaction.  These interactive features include the ability to specify a
time-out and to wait for patterns to appear in the input stream, such as
the prompt from a shell.

   Other reasons to use this module than strictly with a TELNET port are:

   * You're not familiar with sockets and you want a simple way to make
     client connections to TCP services.

   * You want to be able to specify your own time-out while connecting,
     reading, or writing.

   * You're communicating with an interactive program at the other end of
     some socket or pipe and you want to wait for certain patterns to
     appear.

   Here's an example that prints who's logged-on to the remote host
sparky.  In addition to a username and password, you must also know the
user's shell prompt, which for this example is `bash$'

     use Net::Telnet ();
     $t = new Net::Telnet (Timeout => 10,
                           Prompt => '/bash\$ $/');
     $t->open("sparky");
     $t->login($username, $passwd);
     @lines = $t->cmd("/usr/bin/who");
     print @lines;

   More examples are in the EXAMPLES section below.

   Usage questions should be directed to the Usenet newsgroup
comp.lang.perl.modules.

   Contact me, Jay Rogers <jay@rgrs.com>, if you find any bugs or have
suggestions for improvement.

What To Know Before Using
-------------------------

   * All output is flushed while all input is buffered.  Each object
     contains its own input buffer.

   * The output record separator for print() and `cmd()' is set to `"\n"'
     by default, so that you don't have to append all your commands with a
     newline.  See `output_record_separator()' to change the behavior.

   * The methods login() and `cmd()' use the prompt setting in the object
     to determine when a login or remote command is complete.  The method
     will fail with a time-out if you don't set the prompt correctly.

   * Use a combination of print() and `waitfor()' as an alternative to
     login() or `cmd()' when they don't do what you want.

   * Errors such as timing-out are handled according to the errmode
     action.  The default action is to print an error message to standard
     error and have the program die.  See `errmode()' for more information.

   * To avoid unexpected backslash interpretation, always use single quotes
     instead of double quotes to construct a match operator argument for
     `prompt()' and `waitfor()' (e.g. `'/bash\$ $/'').  If you're
     constructing a DOS like file path, you'll need to use four backslashes
     to represent one (e.g. `'/c:\\\\users\\\\bill>$/i'').

     Of course don't forget about regexp metacharacters like ., [, or `$'.
     You'll only need a single backslash to quote them.  The anchor
     metacharacters ^ and `$' refer to positions in the input buffer.

   * In the input stream, each sequence of *carriage return* and *line
     feed* (i.e. `"\015\012"' or CR LF) is converted to `"\n"'.  In the
     output stream, each occurrence of `"\n"' is converted to a sequence
     of CR LF.  See binmode() to change the behavior.  TCP protocols
     typically use the ASCII sequence, carriage return and line feed to
     designate a newline.

   * Timing-out while making a connection is disabled for machines that
     don't support the `alarm()' function.  Most notably these include
     Win32 machines.

     More universal support for connection time-outs will be in a later
     release.

   * You'll need to be running at least Perl version 5.002 to use this
     module.  This module does not require any libraries that don't already
     come with a standard Perl distribution.

     If you have the IO:: libraries installed (they come standard with
     perl5.004 and later) then IO::Socket::INET is used as a base class,
     otherwise FileHandle is used.

   * Contact me, Jay Rogers <jay@rgrs.com>, if you find any bugs or have
     suggestions for improvement.

Debugging
---------

   The typical bug causes a time-out error because you've made incorrect
assumptions about what the remote side actually sends.  The easiest way to
reconcile what the remote side sends with your expectations is to use
`input_log()' or `dump_log()'.

   `dump_log()' allows you to see the data being sent from the remote side
before any translation is done, while `input_log()' shows you the results
after translation.  The translation includes converting end of line
characters and stripping and responding to TELNET protocol commands.

Style of Named Parameters
-------------------------

   Two different styles of named parameters are supported.  This document
only shows the IO:: style:

     Net::Telnet->new(Timeout => 20);

   however the dash-option style is also allowed:

     Net::Telnet->new(-timeout => 20);

Connecting to a Remote Win32 Machine
------------------------------------

   By default, Windows machines don't come with a TELNET service.
However, third party TELNET servers can be acquired to provide access to a
DOS shell.  As is all too familiar, many of these servers are of inferior
quality.

   One particularly nasty problem is a server that sends ANSI terminal
escape sequences despite being told not to.  These escape sequences make
your job of parsing the data much more difficult.  You can sometimes avoid
this with a server that prompts you for *console mode*.  Choose no to
console mode.

METHODS
=======

   In the calling sequences below, square brackets [] represent optional
parameters.

new - create a new Net::Telnet object
          $obj = Net::Telnet->new([Binmode    => $mode,]
                                  [Cmd_remove_mode => $mode,]
                                  [Dump_Log   => $filename,]
                                  [Errmode    => $errmode,]
                                  [Fhopen     => $filehandle,]
                                  [Host       => $host,]
                                  [Input_log  => $file,]
                                  [Input_record_separator => $char,]
                                  [Option_log => $file,]
                                  [Output_log => $file,]
                                  [Output_record_separator => $char,]
                                  [Port       => $port,]
                                  [Prompt     => $matchop,]
                                  [Telnetmode => $mode,]
                                  [Timeout    => $secs,]);

     This is the constructor for Net::Telnet objects.  A new object is
     returned on success, the *$errmode* action is performed on failure -
     see `errmode()'.  The arguments are short-cuts to methods of the same
     name.

     If the $host argument is given then the object is opened by
     connecting to TCP $port on $host.  Also see open().  The new object
     returned is given the following defaults in the absence of
     corresponding named arguments:

          The default Host is `"localhost"'

          The default Port is 23

          The default Prompt is `'/[\$%#>] $/''

          The default Timeout is 10

          The default *Errmode* is `"die"'

          The default *Output_record_separator* is `"\n"'

          The default *Input_record_separator* is `"\n"'

          The default *Binmode* is 0, which means do newline translation

          The default *Cmd_remove_mode* is `"auto"'.

binmode - toggle newline translation
          $mode = $obj->binmode;

          $prev = $obj->binmode($mode);

     This method controls whether or not sequences of carriage returns and
     line feeds (CR LF or more specifically `"\015\012"') are translated.
     By default they are translated (i.e. binmode is 0).

     If no argument is given, the current mode is returned.

     If $mode is 1 then binmode is *on* and newline translation is not
     done.

     If $mode is 0 then binmode is *off* and newline translation is done.
     In the input stream, each sequence of CR LF is converted to `"\n"'
     and in the output stream, each occurrence of `"\n"' is converted to a
     sequence of CR LF.

     Note that input is always buffered.  Changing binmode doesn't effect
     what's already been read into the buffer.  Output is not buffered and
     changing binmode will have an immediate effect.

break - send TELNET break character
          $ok = $obj->break;

     This method sends the TELNET break character.  This character is
     provided because it's a signal outside the USASCII character set which
     is currently given local meaning within many systems.  It's intended
     to indicate that the Break Key or the Attention Key was hit.

buffer - scalar reference to object's input buffer
          $ref = $obj->buffer;

     This method returns a scalar reference to the input buffer for $obj.
     Data in the input buffer is data that has been read from the remote
     side but has yet to be read by the user.  Modifications to the input
     buffer are returned by a subsequent read.

buffer_empty - discard all data in object's input buffer
          $obj->buffer_empty;

     This method removes all data in the input buffer for $obj.

close - close object
          $ok = $obj->close;

     This method closes the socket, file, or pipe associated with the
     object.

cmd - issue command and retrieve output
          $ok = $obj->cmd($string);
          $ok = $obj->cmd(String   => $string,
                          [Output  => $ref,]
                          [Prompt  => $match,]
                          [Timeout => $secs,]
                          [Cmd_remove_mode => $mode,]);

          @output = $obj->cmd($string);
          @output = $obj->cmd(String   => $string,
                              [Output  => $ref,]
                              [Prompt  => $match,]
                              [Timeout => $secs,]
                              [Cmd_remove_mode => $mode,]);

     This method sends the command $string, and reads the characters sent
     back by the command up until and including the matching prompt.  It's
     assumed that the program to which you're sending is some kind of
     command prompting interpreter such as a shell.

     In a scalar context the characters read are discarded and a boolean is
     returned indicating the success or failure of sending the command
     string and reading the prompt.  Note that in order to return on error,
     `errmode()' must not be set to `"die"'.

     In an array context, just the output generated by the command is
     returned, one line per element.  In other words, all the characters in
     between the echoed back command string and the prompt are returned.
     If the command happens to return no output, an array containing one
     element, the null string is returned.  This is so the array will
     indicate true in a boolean context.

     Many command interpreters echo back the command sent.  In most
     situations, this method removes the first line returned from the
     remote side (i.e. the echoed back command).  See `cmd_remove_mode()'
     for more control over this feature.

     Use `dump_log()' to debug when this method keeps timing-out and you
     don't think it should.

     Consider using a combination of print() and `waitfor()' as an
     alternative to this method when it doesn't do what you want, e.g. the
     command you run prompts for input.

     Optional named arguments are provided to override the current settings
     of prompt, timeout, and cmd_remove_mode.

     The Output named argument provides an alternative method of receiving
     command output.  If you pass a scalar reference, all the output (even
     if it contains multiple lines) is returned in the referenced scalar.
     If you pass an array or hash reference, the lines of output are
     returned in the referenced array or hash.

cmd_remove_mode - toggle removal of echoed commands
          $mode = $obj->cmd_remove_mode;

          $prev = $obj->cmd_remove_mode($mode);

     This method controls how to deal with echoed back commands in the
     output returned by cmd().  Typically, when you send a command to the
     remote side, the first line of output returned is the command echoed
     back.  Use this mode to remove the first line of output normally
     returned by cmd().

     If no argument is given, the current mode is returned.

     If $mode is 0 then the command output returned from cmd() has no
     lines removed.  If $mode is a positive integer, then the first $mode
     lines of command output are stripped.

     By default, $mode is set to `"auto"'.  Auto means that whether or not
     the first line of command output is stripped, depends on whether or
     not the remote side offered to echo.  By default, Net::Telnet always
     accepts an offer to echo by the remote side.  You can change the
     default to reject such an offer using `option_accept()'.

dump_log - log all I/O in dump format
          $fh = $obj->dump_log;

          $fh = $obj->dump_log($fh);

          $fh = $obj->dump_log($filename);

     This method starts or stops dump format logging of all the object's
     input and output.  The dump format shows the blocks read and written
     in a hexadecimal and printable character format.  This method is
     useful when debugging, however you might want to first try
     `input_log()' as it's more readable.

     If no argument is given, the current log filehandle is returned.  A
     null string indicates logging is off.

     To stop logging, use a null string as an argument.

     If an open filehandle is given, it is used for logging and returned.
     Otherwise, the argument is assumed to be the name of a file, the file
     is opened and a filehandle to it is returned.

eof - end of file indicator
          $eof = $obj->eof;

     This method indicates if end of file has been read.  Because the input
     is buffered this isn't the same thing as $obj has closed.  In other
     words $obj can be closed but there still can be stuff in the buffer
     to be read.  Under this condition you can still read but you won't be
     able to write.

errmode -  define action to be performed on error
          $mode = $obj->errmode;

          $prev = $obj->errmode($mode);

     This method gets or sets the action used when errors are encountered
     using the object.  The first calling sequence returns the current
     error mode.  The second calling sequence sets it to $mode and returns
     the previous mode.  Valid values for $mode are `"die"' (the default),
     `"return"', a *coderef*, or an *arrayref*.

     When mode is `"die"' and an error is encountered using the object,
     then an error message is printed to standard error and the program
     dies.

     When mode is `"return"' then the method generating the error places
     an error message in the object and returns the undefined value in a
     scalar context and a null list in list context.  The error message may
     be obtained using `errmsg()'.

     When mode is a *coderef*, then when an error is encountered *coderef*
     is called with the error message as its first argument.  Using this
     mode you may have your own subroutine handle errors.  If *coderef*
     itself returns then the method generating the error returns undefined
     or a null list depending on context.

     When mode is an *arrayref*, the first element of the array must be a
     *coderef*.  Any elements that follow are the arguments to *coderef*.
     When an error is encountered, the *coderef* is called with its
     arguments.  Using this mode you may have your own subroutine handle
     errors.  If the *coderef* itself returns then the method generating
     the error returns undefined or a null list depending on context.

errmsg - most recent error message
          $msg = $obj->errmsg;

          $prev = $obj->errmsg(@msgs);

     The first calling sequence returns the error message associated with
     the object.  The null string is returned if no error has been
     encountered yet.  The second calling sequence sets the error message
     for the object to the concatenation of *@msgs* and returns the
     previous error message.  Normally, error messages are set internally
     by a method when an error is encountered.

error - perform the error mode action
          $obj->error(@msgs);

     This method concatenates *@msgs* into a string and places it in the
     object as the error message.  Also see `errmsg()'.  It then performs
     the error mode.  Also see `errmode()'.

     If the error mode doesn't cause the program to die then the undefined
     value or a null list is returned depending on context.

     This method is primarily used by this class or a sub-class to perform
     the user requested action when an error is encountered.

fhopen - use already open filehandle for I/O
          $ok = $obj->fhopen($fh);

     This method associates the open filehandle $fh with $obj for further
     I/O.  Filehandle $fh must already be opened.

     Suppose you want to use the features of this module to do I/O to
     something other than a TCP port, for example STDIN or a filehandle
     opened to read from a process.  Instead of opening the object for I/O
     to a TCP port by using open() or new(), call this method instead.

get - read block of data
          $data = $obj->get([Timeout => $secs,]);

     This method reads a block of data from the object and returns it along
     with any buffered data.  If no buffered data is available to return,
     it will wait for data to read using the timeout specified in the
     object.  You can override that timeout using *$secs*.  Also see
     `timeout()'.  If buffered data is available to return, it also checks
     for a block of data that can be immediately read.

     On eof an undefined value is returned.  On time-out or other errors
     the error mode action is performed.

     An undefined value is returned for both eof and time-out when errmode
     is not set to `"die"'.  Use eof() and `timed_out()' to distinguish.

getline - read next line
          $line = $obj->getline([Timeout => $secs,]);

     This method reads and returns the next line of data from the object.
     You can use `input_record_separator()' to change the notion of what
     separates a line.  The default is `"\n"'.

     If a line isn't immediately available, this method blocks waiting for
     a line or the time-out.  You can override the object's timeout for
     this method using *$secs*.  Also see `timeout()'.

     On eof an undefined value is returned.  On time-out or other errors
     the error mode action is performed.

     An undefined value is returned for both eof and time-out when errmode
     is not set to `"die"'.  Use eof() and `timed_out()' to distinguish.

getlines - read next lines
          @lines = $obj->getlines([Timeout => $secs,]);

     This method reads and returns the next available lines of data from
     the object.  You can use `input_record_separator()' to change the
     notion of what separates a line.  The default is `"\n"'.

     If a line isn't immediately available, this method blocks waiting for
     one or more lines, or time-out.  You can override the object's timeout
     for this method using *$secs*.  Also see `timeout()'.

     On eof a null array is returned.  On time-out or other errors, the
     error mode action is performed.

     A null array is returned for both eof and time-out when errmode is
     not set to `"die"'.  Use eof() and `timed_out()' to distinguish.

host - name of remote host
          $host = $obj->host;

          $prev = $obj->host($host);

     This method designates the remote host.  With no argument this method
     returns the current host name set in the object.  With an argument it
     sets the current host name to $host and returns the previous host
     name.  You may indicate the remote host using either a hostname or an
     IP address.

input_log - log all input
          $fh = $obj->input_log;

          $fh = $obj->input_log($fh);

          $fh = $obj->input_log($filename);

     This method starts or stops logging of input.  This is useful when
     debugging.  Also see `dump_log()'.  Because most command interpreters
     echo back commands received, its likely all your output will also be
     in this log.  Note that input logging occurs after newline
     translation.  See binmode() for details on newline translation.

     If no argument is given, the log filehandle is returned.  A null
     string indicates logging is off.

     To stop logging, use a null string as an argument.

     If an open filehandle is given, it is used for logging and returned.
     Otherwise, the argument is assumed to be the name of a file, the file
     is opened for logging and a filehandle to it is returned.

input_record_separator - input line delimiter
          $rs = $obj->input_record_separator;

          $prev = $obj->input_record_separator($rs);

     This method designates the line delimiter for input.  It's used with
     `getline()', `getlines()', and `cmd()' to determine lines in the
     input.

     With no argument this method returns the current input record
     separator set in the object.  With an argument it sets the input
     record separator to *$rs* and returns the previous value.

lastline - last line read
          $line = $obj->lastline;

          $prev = $obj->lastline($line);

     This method saves the last line read from the object.  This may be a
     useful error message when the remote side abnormally closes the
     connection.  Typically the remote side will print an error message
     before closing.

     With no argument this method returns the last line read from the
     object.  With an argument it sets the last line read to *$line* and
     returns the previous value.  Normally, only internal methods set the
     last line.

login - perform standard login
          $ok = $obj->login($username, $password);

          $ok = $obj->login(Name     => $username,
                            Password => $password,
                            [Prompt  => $match,]
                            [Timeout => $secs,]);

     This method performs a standard login by waiting for a login prompt
     and responding with $username, then waiting for the password prompt
     and responding with $password, and then waiting for the command
     interpreter prompt.  If any of those prompts sent by the remote side
     don't match what's expected, this method will time-out - unless
     timeout is turned off.

     Login prompts must match either of the case insensitive patterns:

          /login[: ]*$/i
          /username[: ]*$/i

     Password prompts must match the case insensitive pattern:

          /password[: ]*$/i

     The command interpreter prompt must match the current setting of
     prompt.

     Use `dump_log()' to debug when this method keeps timing-out and you
     don't think it should.

     Consider using a combination of print() and `waitfor()' as an
     alternative to this method when it doesn't do what you want, e.g. the
     remote host doesn't send a username prompt.

     Optional named arguments are provided to override the current settings
     of prompt and timeout.

max_buffer_length - maximum size of input buffer
          $len = $obj->max_buffer_length;

          $prev = $obj->max_buffer_length($len);

     This method designates the maximum size of the input buffer.  An error
     is generated when a read causes the buffer to exceed this limit.  The
     default value is 1,048,576 bytes (1MB).  The input buffer can grow
     much larger than the block size when you continuously read using
     `getline()' or `waitfor()' and the data stream contains no newlines
     or matching waitfor patterns.

     With no argument this method returns the current maximum buffer length
     set in the object.  With an argument it sets the maximum buffer length
     to *$len* and returns the previous value.

open - connect to port on remote host
          $ok = $obj->open($host);

          $ok = $obj->open([Host    => $host,]
                           [Port    => $port,]
                           [Timeout => $secs,]);

     This method opens a TCP connection to $port on $host.  If either
     argument is missing then the current value of `host()' or `port()' is
     used.  An optional named argument is provided to override the current
     setting of timeout.

     On time-out or other connection errors, the error mode action is
     performed.

     Time-outs don't work for this method on machines that don't implement
     SIGALRM - most notably Win32 machines.  For those machines, an error
     is returned when the system reaches its own time-out while trying to
     connect.

     A side effect of this method is to reset the alarm interval associated
     with SIGALRM.

option_accept - indicate willingness to accept a TELNET option
          $fh = $obj->option_accept([Do   => $telopt,]
                                    [Dont => $telopt,]
                                    [Will => $telopt,]
                                    [Wont => $telopt,]);

     This method is used to indicate whether to accept or reject an offer
     to enable a TELNET option made by the remote side.  If you're using
     Do or *Will* to indicate a willingness to enable, then a notification
     callback must have already been defined by a prior call to
     `option_callback()'.  See `option_callback()' for details on
     receiving enable/disable notification of a TELNET option.

     You can give multiple Do, *Dont*, *Will*, or *Wont* arguments for
     different TELNET options in the same call to this method.

     The following example describes the meaning of the named arguments.  A
     TELNET option, such as `TELOPT_ECHO' used below, is an integer
     constant that you can import from Net::Telnet.  See the source in file
     Telnet.pm for the complete list.

          Do => `TELOPT_ECHO'

               we'll accept an offer to enable the echo option on the
               local side

          *Dont* => `TELOPT_ECHO'

               we'll reject an offer to enable the echo option on the
               local side

          *Will* => `TELOPT_ECHO'

               we'll accept an offer to enable the echo option on the
               remote side

          *Wont* => `TELOPT_ECHO'

               we'll reject an offer to enable the echo option on the
               remote side

     Use `option_send()' to send a request to the remote side to enable or
     disable a particular TELNET option.

option_callback - define the option negotiation callback
          $coderef = $obj->option_callback;

          $prev = $obj->option_callback($coderef);

     This method defines the callback subroutine that's called when a
     TELNET option is enabled or disabled.  Once defined, the
     option_callback may not be undefined.  However, calling this method
     with a different *$coderef* changes it.

     Here are the circumstances that invoke *$coderef*:

          An option becomes enabled because the remote side requested an
          enable and `option_accept()' had been used to arrange that it be
          accepted.

          The remote side arbitrarily decides to disable an option that is
          currently enabled.  Note that Net::Telnet always accepts a
          request to disable from the remote side.

          `option_send()' was used to send a request to enable or disable
          an option and the response from the remote side has just been
          received.  Note, that if a request to enable is rejected then
          *$coderef* is still invoked even though the option didn't change.

     Here are the arguments passed to *&$coderef*:

          &$coderef($obj, $option, $is_remote,
                    $is_enabled, $was_enabled, $buf_position);

          1.  $obj is the Net::Telnet object

          2.  $option is the TELNET option.  Net::Telnet exports constants
          for the various TELNET options which just equate to an integer.

          3.  *$is_remote* is a boolean indicating for which side the
          option applies.

          4.  *$is_enabled* is a boolean indicating the option is enabled
          or disabled

          5.  *$was_enabled* is a boolean indicating the option was
          previously enabled or disabled

          6.  *$buf_position* is an integer indicating the position in the
          object's input buffer where the option takes effect.  See
          `buffer()' to access the object's input buffer.

option_log - log all TELNET options sent or received
          $fh = $obj->option_log;

          $fh = $obj->option_log($fh);

          $fh = $obj->option_log($filename);

     This method starts or stops logging of all TELNET options being sent
     or received.  This is useful for debugging when you send options via
     `option_send()' or you arrange to accept option requests from the
     remote side via `option_accept()'.  Also see `dump_log()'.

     If no argument is given, the log filehandle is returned.  A null
     string indicates logging is off.

     To stop logging, use a null string as an argument.

     If an open filehandle is given, it is used for logging and returned.
     Otherwise, the argument is assumed to be the name of a file, the file
     is opened for logging and a filehandle to it is returned.

option_send - send TELNET option negotiation request
          $ok = $obj->option_send([Do    => $telopt,]
                                  [Dont  => $telopt,]
                                  [Will  => $telopt,]
                                  [Wont  => $telopt,]
                                  [Async => $boolean,]);

     This method is not yet implemented.  Look for it in a future version.

option_state - get current state of a TELNET option
          $hashref = $obj->option_state($telopt);

     This method returns a hashref containing a copy of the current state
     of TELNET option *$telopt*.

     Here are the values returned in the hash:

          $hashref->{remote_enabled}

               boolean that indicates if the option is enabled on the
               remote side.

          $hashref->{remote_enable_ok}

               boolean that indicates if it's ok to accept an offer to
               enable this option on the remote side.

          $hashref->{remote_state}

               string used to hold the internal state of option
               negotiation for this option on the remote side.

          $hashref->{local_enabled}

               boolean that indicates if the option is enabled on the
               local side.

          $hashref->{local_enable_ok}

               boolean that indicates if it's ok to accept an offer to
               enable this option on the local side.

          $hashref->{local_state}

               string used to hold the internal state of option
               negotiation for this option on the local side.

output_field_separator - field separator for print
          $ofs = $obj->output_field_separator;

          $prev = $obj->output_field_separator($ofs);

     This method designates the output field separator for print().
     Ordinarily the print method simply prints out the comma separated
     fields you specify.  Set this to specify what's printed between
     fields.

     With no argument this method returns the current output field
     separator set in the object.  With an argument it sets the output
     field separator to *$ofs* and returns the previous value.

output_log - log all output
          $fh = $obj->output_log;

          $fh = $obj->output_log($fh);

          $fh = $obj->output_log($filename);

     This method starts or stops logging of output.  This is useful when
     debugging.  Also see `dump_log()'.  Because most command interpreters
     echo back commands received, its likely all your output would also be
     in an input log.  See `input_log()'.  Note that output logging occurs
     before newline translation.  See binmode() for details on newline
     translation.

     If no argument is given, the log filehandle is returned.  A null
     string indicates logging is off.

     To stop logging, use a null string as an argument.

     If an open filehandle is given, it is used for logging and returned.
     Otherwise, the argument is assumed to be the name of a file, the file
     is opened for logging and a filehandle to it is returned.

output_record_separator - output line delimiter
          $ors = $obj->output_record_separator;

          $prev = $obj->output_record_separator($ors);

     This method designates the output record separator for print().
     Ordinarily the print operator simply prints out the comma separated
     fields you specify, with no trailing newline or record separator
     assumed.  Set this variable to specify what's printed at the end of
     the print.

     Note: the output record separator is set to `"\n"' by default, so
     there's no need to append all your commands with a newline.

     With no argument this method returns the current output record
     separator set in the object.  With an argument it sets the output
     record separator to *$ors* and returns the previous value.

port - remote port
          $port = $obj->port;

          $prev = $obj->port($port);

     This method designates the remote TCP port.  With no argument this
     method returns the current port number.  With an argument it sets the
     current port number to $port and returns the previous port.  If $port
     is a service name, then first it's converted to a port number using
     the perl function `getservbyname()'.

print - write to object
          $ok = $obj->print(@list);

     This method prints a string or a comma-separated list of strings to
     the opened object and returns non-zero if all data was successfully
     written.

     By default, the `output_record_separator()' is set to `"\n"' in order
     to have your commands automatically end with a newline.  In most cases
     your output is being read by a command interpreter which won't accept
     a command until newline is read.  This is similar to someone typing a
     command and hitting the return key.

     On failure, it's possible that some data was written.  If you choose
     to try and recover from a print timing-out, use `print_length()' to
     determine how much was written before time-out occurred.

print_length - number of bytes written by print
          $num = $obj->print_length;

     This returns the number of bytes successfully written by the most
     recent print().

prompt - pattern to match a prompt
          $matchop = $obj->prompt;

          $prev = $obj->prompt($matchop);

     This method sets the pattern used to find a prompt in the input
     stream.  It must be a string representing a valid perl pattern match
     operator.  The methods login() and `cmd()' try to read until matching
     the prompt.  They will fail with a time-out error if the pattern
     you've chosen doesn't match what the remote side sends.

     With no argument this method returns the prompt set in the object.
     With an argument it sets the prompt to *$matchop* and returns the
     previous value.

     The default prompt is `'/[\$%#>] $/''

     Always use single quotes, instead of double quotes, to construct
     *$matchop* (e.g. `'/bash\$ $/'').  If you're constructing a DOS like
     file path, you'll need to use four backslashes to represent one (e.g.
     `'/c:\\\\users\\\\bill>$/i'').

     Of course don't forget about regexp metacharacters like ., [, or `$'.
     You'll only need a single backslash to quote them.  The anchor
     metacharacters ^ and `$' refer to positions in the input buffer.

telnetmode - turn off/on telnet command interpretation
          $mode = $obj->telnetmode;

          $prev = $obj->telnetmode($mode);

     This method controls whether or not TELNET commands in the data stream
     are recognized and handled.  The TELNET protocol uses certain
     character sequences sent in the data stream to control the session.
     If the port you're connecting to isn't using the TELNET protocol, then
     you should turn this mode off.  The default is *on*.

     If no argument is given, the current mode is returned.

     If $mode is 0 then telnet mode is off.  If $mode is 1 then telnet
     mode is on.

timed_out - time-out indicator
          $boolean = $obj->timed_out;

          $prev = $obj->timed_out($boolean);

     This method indicates if a previous read or write method timed-out.

     With no argument this method returns true if a previous method
     timed-out.  With an argument it sets the indicator.  Normally, only
     internal methods set this indicator.

timeout - I/O time-out interval
          $secs = $obj->timeout;

          $prev = $obj->timeout($secs);

     This method sets the timeout interval that's used when performing I/O
     or connecting to a port.  When a method doesn't complete within the
     timeout interval then it's an error and the error mode action is
     performed.

     The timeout may be expressed as a relative or absolute value.  If
     *$secs* is greater than or equal to the time the program was started,
     as determined by $^T, then it's the absolute time when time-out
     occurs.  Also see the perl function `time()'.  A relative time-out
     happens *$secs* from when the I/O method begins.

     If *$secs* is 0 then time-out occurs if the data cannot be
     immediately read or written.  Use the undefined value to turn off
     timing-out.

     With no argument this method returns the timeout set in the object.
     With an argument it sets the timeout to *$secs* and returns the
     previous value.

waitfor - wait for pattern in the input
          $ok = $obj->waitfor($matchop);
          $ok = $obj->waitfor([Match   => $matchop,]
                              [String  => $string,]
                              [Timeout => $secs,]);

          ($prematch, $match) = $obj->waitfor($matchop);
          ($prematch, $match) = $obj->waitfor([Match   => $matchop,]
                                              [String  => $string,]
                                              [Timeout => $secs,]);

     This method reads until a pattern match or string is found in the
     input stream.  All the characters before and including the match are
     removed from the input stream.  On time-out, eof, or other errors the
     error mode action is performed.

     In an array context the characters before the match and the matched
     characters are returned in *$prematch* and *$match*.

     You can specify more than one pattern or string by simply providing
     multiple Match and/or String named arguments.  A *$matchop* must be a
     string representing a valid Perl pattern match operator.  The $string
     is just a substring to find in the input stream.

     Use `dump_log()' to debug when this method keeps timing-out and you
     don't think it should.

     An optional named argument is provided to override the current setting
     of timeout.

     To avoid unexpected backslash interpretation, always use single quotes
     instead of double quotes to construct a match operator argument for
     `prompt()' and `waitfor()' (e.g. `'/bash\$ $/'').  If you're
     constructing a DOS like file path, you'll need to use four backslashes
     to represent one (e.g. `'/c:\\\\users\\\\bill>$/i'').

     Of course don't forget about regexp metacharacters like ., [, or `$'.
     You'll only need a single backslash to quote them.  The anchor
     metacharacters ^ and `$' refer to positions in the input buffer.

SEE ALSO
========

RFC 854
     TELNET Protocol Specification

     ftp://ftp.isi.edu/in-notes/rfc854.txt

RFC 1143
     Q Method of Implementing TELNET Option Negotiation

     ftp://ftp.isi.edu/in-notes/rfc1143.txt

TELNET Option Assignments
     ftp://ftp.isi.edu/in-notes/iana/assignments/telnet-options

EXAMPLES
========

   This example gets the current weather forecast for Brainerd, Minnesota.

     my ($forecast, $t);

     use Net::Telnet ();
     $t = new Net::Telnet;
     $t->open("rainmaker.wunderground.com");

     ## Wait for first prompt and "hit return".
     $t->waitfor('/continue:.*$/');
     $t->print("");

     ## Wait for second prompt and respond with city code.
     $t->waitfor('/city code.*$/');
     $t->print("BRD");

     ## Read and print the first page of forecast.
     ($forecast) = $t->waitfor('/[ \t]+press return to continue/i');
     print $forecast;

     exit;

   This example checks a POP server to see if you have mail.

     my ($hostname, $line, $passwd, $pop, $username);

     $hostname = "your_destination_host_here";
     $username = "your_username_here";
     $passwd = "your_password_here";

     use Net::Telnet ();
     $pop = new Net::Telnet (Telnetmode => 0);
     $pop->open(Host => $hostname,
                Port => 110);

     ## Read connection message.
     $line = $pop->getline;
     die $line unless $line =~ /^\+OK/;

     ## Send user name.
     $pop->print("user $username");
     $line = $pop->getline;
     die $line unless $line =~ /^\+OK/;

     ## Send password.
     $pop->print("pass $passwd");
     $line = $pop->getline;
     die $line unless $line =~ /^\+OK/;

     ## Request status of messages.
     $pop->print("list");
     $line = $pop->getline;
     print $line;

     exit;

   Here's an example you can use to down load a file of any type.  The
file is read from the remote host's standard output using cat.  To prevent
any output processing, the remote host's standard output is put in raw
mode using the Bourne shell.  The Bourne shell is used because some
shells, notably tcsh, prevent changing tty modes.  Upon completion, FTP
style statistics are printed to stderr.

     my ($block, $filename, $host, $hostname, $k_per_sec, $line,
         $num_read, $passwd, $prevblock, $prompt, $size, $size_bsd,
         $size_sysv, $start_time, $total_time, $username);

     $hostname = "your_destination_host_here";
     $username = "your_username_here";
     $passwd = "your_password_here";
     $filename = "your_download_file_here";

     ## Connect and login.
     use Net::Telnet ();
     $host = new Net::Telnet (Timeout => 30,
                              Prompt => '/[%#>] $/');
     $host->open($hostname);
     $host->login($username, $passwd);

     ## Make sure prompt won't match anything in send data.
     $prompt = '_funkyPrompt_';
     $host->prompt("/$prompt\$/");
     $host->cmd("set prompt = '$prompt'");

     ## Get size of file.
     ($line) = $host->cmd("/bin/ls -l $filename");
     ($size_bsd, $size_sysv) = (split ' ', $line)[3,4];
     if ($size_sysv =~ /^\d+$/) {
         $size = $size_sysv;
     }
     elsif ($size_bsd =~ /^\d+$/) {
         $size = $size_bsd;
     }
     else {
         die "$filename: no such file on $hostname";
     }

     ## Start sending the file.
     binmode STDOUT;
     $host->binmode(1);
     $host->print("/bin/sh -c 'stty raw; cat $filename'");
     $host->getline;    # discard echoed back line

     ## Read file a block at a time.
     $num_read = 0;
     $prevblock = '';
     $start_time = time;
     while (($block = $host->get) and ($block !~ /$prompt$/o)) {
         if (length $block >= length $prompt) {
             print $prevblock;
             $num_read += length $prevblock;
             $prevblock = $block;
         }
         else {
             $prevblock .= $block;
         }

     }
     $host->close;

     ## Print last block without trailing prompt.
     $prevblock .= $block;
     $prevblock =~ s/$prompt$//;
     print $prevblock;
     $num_read += length $prevblock;
     die "error: expected size $size, received size $num_read\n"
         unless $num_read == $size;

     ## Print totals.
     $total_time = (time - $start_time) || 1;
     $k_per_sec = ($size / 1024) / $total_time;
     $k_per_sec = sprintf "%3.1f", $k_per_sec;
     warn("$num_read bytes received in $total_time seconds ",
          "($k_per_sec Kbytes/s)\n");

     exit;

AUTHOR
======

   Jay Rogers <jay@rgrs.com>

COPYRIGHT
=========

   Copyright 1997, 2000 by Jay Rogers.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

interact with a Cisco router
****************************

NAME
====

   Net::Telnet::Cisco - interact with a Cisco router

SYNOPSIS
========

     use Net::Telnet::Cisco;

     my $cs = Net::Telnet::Cisco->new( Host => '123.123.123.123' );
     $cs->login( 'login', 'password' );

     # Turn off paging
     my @cmd_output = $cs->cmd( 'terminal length 0' );

     # Execute a command
     @cmd_output = $cs->cmd( 'show running-config' );
     print @cmd_output;

     # Generate an error on purpose
     # This error handler prints the errmsg and continues.
     $cs->errmode( sub { print @_, "\n" } );

     @cmd_output = $cs->cmd( 'asdf' ); # Bad command.

     print "-" x 30, "\n";
     print "Last prompt: <",  $cs->last_prompt, ">\n";
     print "Last command: <", $cs->last_cmd,    ">\n";
     print "Last error: <",   $cs->errmsg,      ">\n";
     print "Cmd output: <",   @cmd_output,      ">\n";
     print "-" x 30, "\n";

     # Try out enable mode
     if ( $cs->enable("enable_password") ) {
         @cmd_output = $cs->cmd('show privilege');
         print "Cmd output: <", @cmd_output, ">\n";
     } else {
         warn "Can't enable: " . $cs->errmsg;
     }

     $cs->close;

DESCRIPTION
===========

   Net::Telnet::Cisco provides additional functionality to Net::Telnet for
dealing with Cisco routers.

   Things you should know:

   The default cmd_prompt is /[\w().-]*[\$#>]\s?(?:\(enable\))?\s*$/,
suitable for matching promtps like 'rtrname$ ', 'rtrname# ', and 'rtrname>
(enable) '.

   cmd() parses router-generated error messages - the kind that begin with
a '%' - and stows them in $obj->errmsg(), so that errmode can be used to
perform automatic error-handling actions.

FIRST
=====

   Before you use Net::Telnet::Cisco, you should probably have a good
understanding of Net::Telnet, so perldoc Net::Telnet first, and then come
back to Net::Telnet::Cisco to see where the improvements are.

   Some things are easier to accomplish with Net::SNMP. SNMP has three
advantages: it's faster, handles errors better, and doesn't use any vtys
on the router. SNMP does have some limitations, so for anything you can't
accomplish with SNMP, there's Net::Telnet::Cisco.

METHODS
=======

   New methods not found in Net::Telnet follow:

enable - enter enabled mode
          $ok = $obj->enable;

          $ok = $obj->enable( $password );

     This method changes privilege level to enabled mode, (i.e. root)

     If an argument is provided by the caller, it will be used as a
     password.

     enable() returns 1 on success and undef on failure.

disable - leave enabled mode
          $ok = $obj->disable;

     This method exits the router's privileged mode.

last_prompt - displays the last prompt matched by prompt()
          $match = $obj->last_prompt;

     last_prompt() will return " if the program has not yet matched a
     prompt.

login - login to a router.
          $ok = $obj->login($username, $password);

          $ok = $obj->login(Name     => $username,
                            Password => $password,
                            [Prompt  => $match,]
                            [Timeout => $secs,]);

     Net::Telnet::Cisco will correctly log into a router if the session
     begins with a password prompt (and ignores the login or username step
     entirely).

AUTHOR
======

   Joshua_Keroes@eli.net $Date: 2000/07/30 22:16:51 $

   It would greatly amuse the author if you would send email to him and
tell him how you are using Net::Telnet::Cisco.

SEE ALSO
========

   Net::Telnet, Net::SNMP

COPYRIGHT
=========

   Copyright (c) 2000 Joshua Keroes, Electric Lightwave Inc.  All rights
reserved. This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

time and daytime network client interface
*****************************************

NAME
====

   Net::Time - time and daytime network client interface

SYNOPSIS
========

     use Net::Time qw(inet_time inet_daytime);

     print inet_time();		# use default host from Net::Config
     print inet_time('localhost');
     print inet_time('localhost', 'tcp');

     print inet_daytime();	# use default host from Net::Config
     print inet_daytime('localhost');
     print inet_daytime('localhost', 'tcp');

DESCRIPTION
===========

   `Net::Time' provides subroutines that obtain the time on a remote
machine.

inet_time ( [HOST [, PROTOCOL [, TIMEOUT]]])
     Obtain the time on `HOST', or some default host if `HOST' is not given
     or not defined, using the protocol as defined in RFC868. The optional
     argument PROTOCOL should define the protocol to use, either `tcp' or
     `udp'. The result will be a time value in the same units as returned
     by time() or undef upon failure.

inet_daytime ( [HOST [, PROTOCOL [, TIMEOUT]]])
     Obtain the time on `HOST', or some default host if `HOST' is not given
     or not defined, using the protocol as defined in RFC867. The optional
     argument PROTOCOL should define the protocol to use, either `tcp' or
     `udp'. The result will be an ASCII string or undef upon failure.

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

COPYRIGHT
=========

   Copyright (c) 1995-1998 Graham Barr. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

traceroute(1) functionality in perl
***********************************

NAME
====

   Net::Traceroute - traceroute(1) functionality in perl

SYNOPSIS
========

     use Net::Traceroute;
     $tr = Net::Traceroute->new(host=> "life.ai.mit.edu");
     if($tr->found) {
     	my $hops = $tr->hops;
     	if($hops > 1) {
     	    print "Router was " .
     		$tr->hop_query_host($tr->hops - 1, 1) . "\n";
     	}
     }

DESCRIPTION
===========

   This module implements traceroute(1) functionality for perl5.  It
allows you to trace the path IP packets take to a destination.  It is
currently implemented as a parser around the system traceroute command.

OVERVIEW
========

   A new Net::Traceroute object must be created with the new method.
Depending on exactly how the constructor is invoked, it may perform the
traceroute immediately, or it may return a "template" object that can be
used to set parameters for several subsequent traceroutes.

   Methods are available for accessing information about a given
traceroute attempt.  There are also methods that view/modify the options
that are passed to the object's constructor.

   To trace a route, UDP packets are sent with a small TTL (time-to-live)
field in an attempt to get intervening routers to generate ICMP
TIME_EXCEEDED messages.

CONSTRUCTOR
===========

     $obj = Net::Traceroute->new([base_port	=> $base_port,]
     				[debug		=> $debuglvl,]
     				[max_ttl	=> $max_ttl,]
     				[host		=> $host,]
     				[queries	=> $queries,]
     				[query_timeout	=> $query_timeout,]
     				[timeout	=> $timeout,]);
     $frob = $obj->new([options]);

   This is the constructor for a new Net::Traceroute object.  If given
host, it will actually perform the traceroute; otherwise it will return an
empty template object.  This can be used to setup a template object with
some preset defaults for firing off multiple traceroutes.

   Given an existing Net::Traceroute object $obj as a template, you can
call $obj->new() with the usual parameters.  The same rules apply about
defining host; that is, traceroute will be run if it is defined.  You can
always pass host => undef in the constructor call.

   To use a template objects to perform a traceroute, you invoke new on it
and pass a host option.

   Possible options are:

   host - A host to traceroute to.  If you don't set this, you get a
Traceroute object with no traceroute data in it.  The module always uses
IP addresses internally and will attempt to lookup host names via
inet_aton.

   *base_port* - Base port number to use for the UDP queries.  Traceroute
assumes that nothing is listening to port `base_port' to `base_port +
(nhops - 1)' where nhops is the number of hops required to reach the
destination address.  Default is what the system traceroute uses (normally
33434).  `Traceroute''s -p option.

   *debuglvl* - A number indicating how verbose debug information should
be.  Please include debug=>9 output in bug reports.

   *max_ttl* - Maximum number of hops to try before giving up.  Default is
what the system traceroute uses (normally 30).  `Traceroute''s -m option.

   *queries* - Number of times to send a query for a given hop.  Defaults
to whatever the system traceroute uses (3 for most traceroutes).
`Traceroute''s -q option.

   *query_timeout* - How many seconds to wait for a response to each query
sent.  Uses the system traceroute's default value of 5 if unspecified.
`Traceroute''s -w option.

   timeout - Maximum time, in seconds, to wait for the traceroute to
complete.  If not specified, the traceroute will not return until the host
has been reached, or traceroute counts to infinity (`max_ttl' * `queries'
* `query_timeout').  Note that this option is implemented by
Net::Traceroute, not the underlying traceroute command.

METHODS
=======

Controlling traceroute invocation
---------------------------------

   Each of these methods return the current value of the option specified
by the corresponding constructor option.  They will set the object's
instance variable to the given value if one is provided.

   Changing an instance variable will only affect newly performed
traceroutes.  Setting a different value on a traceroute object that has
already performed a trace has no effect.

   See the constructor documentation for information about each
method/constructor option.

base_port([PORT])
max_ttl([PORT])
queries([QUERIES])
query_timeout([TIMEOUT])
host([HOST])
timeout([TIMEOUT])
Obtaining information about a Trace
-----------------------------------

   These methods return information about a traceroute that has already
been performed.

   Any of the methods in this section that return a count of something or
want an Nth type count to identify something employ one based counting.

stat
     Returns the status of a given traceroute object.  One of
     TRACEROUTE_OK, TRACEROUTE_TIMEOUT, or TRACEROUTE_UNKNOWN (each defined
     as an integer).  TRACEROUTE_OK will only be returned if the host was
     actually reachable.

found
     Returns 1 if the host was found, undef otherwise.

hops
     Returns the number of hops that it took to reach the host.

hop_queries(HOP)
     Returns the number of queries that were sent for a given hop.  This
     should normally be the same for every query.

hop_query_stat(HOP, QUERY)
     Return the status of the given HOP's QUERY.  The return status can be
     one of the following (each of these is actually an integer constant
     function defined in Net::Traceroute's export list):

    TRACEROUTE_OK
          Reached the host, no problems.

    TRACEROUTE_TIMEOUT
          This query timed out.

    TRACEROUTE_UNKNOWN
          Your guess is as good as mine.  Shouldn't happen too often.

    TRACEROUTE_UNREACH_NET
          This hop returned an ICMP Network Unreachable.

    TRACEROUTE_UNREACH_HOST
          This hop returned an ICMP Host Unreachable.

    TRACEROUTE_UNREACH_PROTO
          This hop returned an ICMP Protocol unreachable.

    TRACEROUTE_UNREACH_NEEDFRAG
          Indicates that you can't reach this host without fragmenting your
          packet further.  Shouldn't happen in regular use.

    TRACEROUTE_UNREACH_SRCFAIL
          A source routed packet was rejected for some reason.  Shouldn't
          happen.

    TRACEROUTE_UNREACH_FILTER_PROHIB
          A firewall or similar device has decreed that your traffic is
          disallowed by administrative action.  Suspect sheer, raving
          paranoia.

    TRACEROUTE_BSDBUG
          The destination machine appears to exhibit the 4.[23]BSD time
          exceeded bug.

hop_query_host(HOP, QUERY)
     Return the dotted quad IP address of the host that responded to HOP's
     QUERY.

hop_query_time(HOP, QUERY)
     Return the round trip time associated with the given HOP's query.  If
     your system's traceroute supports fractional second timing, so will
     Net::Traceroute.

BUGS
====

   Net::Traceroute parses the output of the system traceroute command.  As
such, it may not work on your system.  Support for more traceroute outputs
(e.g. Windows, HPUX) could be done, although currently the code assumes
there is "One true traceroute".

   The actual functionality of traceroute could also be implemented
natively in perl or linked in from a C library.

   As of 0.7 (the first public release) I consider the interface stable.
Violent changes to interface are always possible, but I will retain
compatibility with this interface in future releases.

SEE ALSO
========

   traceroute(1)

AUTHOR
======

   Daniel Hagerty <hag@ai.mit.edu>

COPYRIGHT
=========

   Copyright 1998, 1999 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.

UDP sockets interface module
****************************

NAME
====

   Net::UDP - UDP sockets interface module

SYNOPSIS
========

     use Net::Gen;		# optional
     use Net::Inet;		# optional
     use Net::UDP;

DESCRIPTION
===========

   The `Net::UDP' module provides services for UDP communications over
sockets.  It is layered atop the `Net::Inet' and `Net::Gen' modules, which
are part of the same distribution.

Public Methods
--------------

   The following methods are provided by the `Net::UDP' module itself,
rather than just being inherited from `Net::Inet' or `Net::Gen'.

new
     Usage:

          $obj = new Net::UDP;
          $obj = new Net::UDP $desthost, $destservice;
          $obj = new Net::UDP \%parameters;
          $obj = new Net::UDP $desthost, $destservice, \%parameters;
          $obj = 'Net::UDP'->new();
          $obj = 'Net::UDP'->new($desthost);
          $obj = 'Net::UDP'->new($desthost, $destservice);
          $obj = 'Net::UDP'->new(\%parameters);
          $obj = 'Net::UDP'->new($desthost, $destservice, \%parameters);

     Returns a newly-initialised object of the given class.  If called for
     a derived class, no validation of the supplied parameters will be
     performed.  (This is so that the derived class can add the parameter
     validation it needs to the object before allowing the validation.)
     Otherwise, it will cause the parameters to be validated by calling
     its init method, which `Net::UDP' inherits from `Net::Inet'.  In
     particular, this means that if both a host and a service are given,
     that an object will only be returned if a connect() call was
     successful.

     The examples above show the indirect object syntax which many prefer,
     as well as the guaranteed-to-be-safe static method call.  There are
     occasional problems with the indirect object syntax, which tend to be
     rather obscure when encountered.  See

     <URL:http://www.rosat.mpe-garching.mpg.de/mailing-lists/perl-porters/1998-01/msg01674.html>
     for details.

PRINT
     Usage:

          $ok = $obj->PRINT(@args);
          $ok = print $tied_fh @args;

     This method, intended to be used with tied filehandles, behaves like
     one of two inherited methods from the `Net::Gen' class, depending on
     the setting of the object parameter unbuffered_output.  If that
     parameter is false (the default), then the normal print() builtin is
     used.  If the unbuffered_output parameter is true, then each print()
     operation will actually result in a call to the send method,
     requiring that the object be connected or that its message is in
     response to its last normal recv() (with a flags parameter of 0).
     The value of the $\ variable is ignored in that case, but the $,
     variable is still used if the `@args' array has multiple elements.

READLINE
     Usage:

          $line_or_datagram = $obj->READLINE;
          $line_or_datagram = <TIED_FH>;
          $line_or_datagram = readline(TIED_FH);
          @lines_or_datagrams = $obj->READLINE;
          @lines_or_datagrams = <TIED_FH>;
          @lines_or_datagrams = readline(TIED_FH);

     This method, intended to be used with tied filehandles, behaves like
     one of two inherited methods from the `Net::Gen' class, depending on
     the setting of the object parameter unbuffered_input.  If that
     parameter is false (the default), then this method does
     line-buffering of its input as defined by the current setting of the
     $/ variable.  If the <unbuffered_input> parameter is true, then the
     input records will be exact recv() datagrams, disregarding the
     setting of the $/ variable.  Note that invoking the READLINE method
     in list context is likely to hang, since UDP sockets typically don't
     return EOF.

Protected Methods
-----------------

   none.

Known Socket Options
--------------------

   There are no object parameters registered by the `Net::UDP' module
itself.

Known Object Parameters
-----------------------

   The following object parameters are registered by the `Net::UDP' module
(as distinct from being inherited from `Net::Gen' or `Net::Inet'):

unbuffered_input
     If true, the READLINE operation on tied filehandles will return each
     recv() buffer as though it were a single separate line, independently
     of the setting of the $/ variable.  The default is false, which
     causes the READLINE interface to return lines split at boundaries as
     appropriate for $/.  (The READLINE method for tied filehandles is the
     `<FH>' operation.)  Note that calling the READLINE method in list
     context is likely to hang.

unbuffered_output
     If true, the PRINT operation on tied filehandles will result in calls
     to the send() builtin rather than the print() builtin, as described
     in `' in this node above.  The default is false, which causes the
     PRINT method to use the print() builtin.

unbuffered_IO
     This object parameter's value is unreliable on getparam or getparams
     method calls.  It is provided as a handy way to set both the
     unbuffered_output and unbuffered_input object parameters to the same
     value at the same time during new calls.

TIESCALAR support
-----------------

   Tieing of scalars to a UDP handle is supported by inheritance from the
TIESCALAR method of `Net::Gen'.  That method only succeeds if a call to a
new method results in an object for which the isconnected method returns
true, which is why it is mentioned in regard to this module.

   Example:

     tie $x,'Net::UDP',0,'daytime' or die "tie to Net::UDP: $!";
     $x = "\n"; $x = "\n";
     print $y if defined($y = $x);
     untie $x;

   This is an expensive re-implementation of date on many machines.

   Each assignment to the tied scalar is really a call to the put method
(via the STORE method), and each read from the tied scalar is really a
call to the READLINE method (via the FETCH method).

TIEHANDLE support
-----------------

   As inherited from `Net::Inet' and `Net::Gen', with the addition of
unbuffered I/O options for the READLINE and PRINT methods.

Exports
-------

   none

THREADING STATUS
================

   This module has been tested with threaded perls, and should be as
thread-safe as perl itself.  (As of 5.005_03 and 5.005_57, that's not all
that safe just yet.)

SEE ALSO
========

   Net::Inet(3), Net::Gen(3)

AUTHOR
======

   Spider Boardman <spider@Orb.Nashua.NH.US>

UNIX-domain sockets interface module
************************************

NAME
====

   Net::UNIX - UNIX-domain sockets interface module

SYNOPSIS
========

     use Net::Gen;		# optional
     use Net::UNIX;

DESCRIPTION
===========

   The `Net::UNIX' module provides services for UNIX-domain socket
communication.  It is layered atop the `Net::Gen' module, which is part of
the same distribution.

Public Methods
--------------

   The following methods are provided by the `Net::UNIX' module itself,
rather than just being inherited from `Net::Gen'.

new
     Usage:

          $obj = new Net::UNIX;
          $obj = new Net::UNIX $pathname;
          $obj = new Net::UNIX \%parameters;
          $obj = new Net::UNIX $pathname, \%parameters;
          $obj = 'Net::UNIX'->new();
          $obj = 'Net::UNIX'->new($pathname);
          $obj = 'Net::UNIX'->new(\%parameters);
          $obj = 'Net::UNIX'->new($pathname, \%parameters);

     Returns a newly-initialised object of the given class.  If called for
     a derived class, no validation of the supplied parameters will be
     performed.  (This is so that the derived class can add the parameter
     validation it needs to the object before allowing the validation.)
     Otherwise, it will cause the parameters to be validated by calling
     its init method.  In particular, this means that if a pathname is
     given, an object will be returned only if a connect() call was
     successful.

     The examples above show the indirect object syntax which many prefer,
     as well as the guaranteed-to-be-safe static method call.  There are
     occasional problems with the indirect object syntax, which tend to be
     rather obscure when encountered.  See

     <URL:http://www.rosat.mpe-garching.mpg.de/mailing-lists/perl-porters/1998-01/msg01674.html>
     for details.

init
     Usage:

          return undef unless $self = $self->init;
          return undef unless $self = $self->init(\%parameters);
          return undef unless $self = $self->init($pathname);
          return undef unless $self = $self->init($pathname, \%parameters);

     Verifies that all previous parameter assignments are valid (via
     checkparams).  Returns the incoming object on success, and undef on
     failure.  Usually called only via a derived class's init method or
     its own new call.

bind
     Usage:

          $ok = $obj->bind;
          $ok = $obj->bind($pathname);
          $ok = $obj->bind($pathname,\%newparameters);

     Updates the object with the supplied new parameters (if supplied),
     then sets up the srcaddrlist object parameter with the specified
     $pathname argument (if supplied), and then returns the value from the
     inherited bind method.

     Example:

          $ok = $obj->bind('/tmp/.fnord'); # start a service on /tmp/.fnord

connect
     Usage:

          $ok = $obj->connect;
          $ok = $obj->connect($pathname);
          $ok = $obj->connect($pathname,\%newparameters);

     Attempts to establish a connection for the object.  If the
     `newparams' argument is specified, it will be used to update the
     object parameters.  Then, if the $pathname argument is specified, it
     will be used to set the dstaddrlist object parameter.  Finally, the
     result of a call to the inherited connect method will be returned.

format_addr
     Usage:

          $string = $obj->format_addr($sockaddr);
          $string = format_addr Module $sockaddr;

     Returns a formatted representation of the socket address.  This is
     normally just a pathname, or the constant string ".

PRINT
     Usage:

          $ok = $obj->PRINT(@args);
          $ok = print $tied_fh @args;

     This method, intended to be used with tied filehandles, behaves like
     one of two inherited methods from the `Net::Gen' class, depending on
     the setting of the object parameter unbuffered_output and whether the
     socket is a SOCK_STREAM (stream) socket or a datagram socket (the
     default).  If that parameter is false (the default) or the socket is
     a stream socket, then the normal print() builtin is used.  If the
     unbuffered_output parameter is true for a datagram socket, then each
     print() operation will actually result in a call to the send method.
     The value of the $\ variable is ignored in that case, but the $,
     variable is still used if the `@args' array has multiple elements.

READLINE
     Usage:

          $line_or_datagram = $obj->READLINE;
          $line_or_datagram = <TIED_FH>;
          $line_or_datagram = readline(TIED_FH);
          @lines_or_datagrams = $obj->READLINE;
          @lines_or_datagrams = <TIED_FH>;
          @lines_or_datagrams = readline(TIED_FH);

     This method, intended to be used with tied filehandles, behaves like
     one of two inherited methods from the `Net::Gen' class, depending on
     the setting of the object parameter unbuffered_input and whether the
     socket is a SOCK_STREAM (stream) socket or a datagram socket (the
     default).  If that parameter is false (the default) or the socket is
     a stream socket, then this method does line-buffering of its input as
     defined by the current setting of the $/ variable.  If the
     unbuffered_input parameter is true for a datagram socket, then the
     input records will be exact recv() datagrams, disregarding the
     setting of the $/ variable.

Protected Methods
-----------------

   [See the description in `"Protected Methods"', see Net/Gen,
for my definition of protected methods in Perl.]

   None.

Known Socket Options
--------------------

   There are no socket options known to the `Net::UNIX' module itself.

Known Object Parameters
-----------------------

   The following object parameters are registered by the `Net::UNIX' module
(as distinct from being inherited from `Net::Gen'):

unbuffered_input
     If true, the READLINE operation on tied filehandles which are
     datagram sockets will return each recv() buffer as though it were a
     single separate line, independently of the setting of the $/
     variable.  The default is false, which causes the READLINE interface
     to return lines split at boundaries as appropriate for $/.  (The
     READLINE method for tied filehandles is the `<FH>' operation.)

unbuffered_output
     If true, the PRINT operation on tied filehandles which are datagram
     sockets will result in calls to the send() builtin rather than the
     print() builtin, as described in `' in this node above.  The default
     is false, which causes the PRINT method to use the print() builtin.

unbuffered_IO
     This object parameter's value is unreliable on getparam or getparams
     method calls.  It is provided as a handy way to set both the
     unbuffered_output and unbuffered_input object parameters to the same
     value at the same time during new calls.

TIESCALAR
---------

   Tieing of scalars to a UNIX-domain handle is supported by inheritance
from the TIESCALAR method of `Net::Gen'.  That method only succeeds if a
call to a new method results in an object for which the isconnected method
returns a true result.  Thus, for `Net::UNIX', TIESCALAR will not succeed
unless the `pathname' argument is given.

   Each assignment to the tied scalar is really a call to the put method
(via the STORE method), and each read from the tied scalar is really a
call to the READLINE method (via the FETCH method).

TIEHANDLE support
-----------------

   As inherited from `Net::Gen', with the addition of unbuffered datagram
I/O options for the FETCH, READLINE, and PRINT methods.

Non-Method Subroutines
----------------------

pack_sockaddr_un
     Usage:

          $connect_address = pack_sockaddr_un($family, $pathname);
          $connect_address = pack_sockaddr_un($pathname);

     Returns the packed `struct sockaddr_un' corresponding to the provided
     $family and $pathname arguments.  The $family argument as assumed to
     be `AF_UNIX' if it is missing.  This is otherwise the same as the
     pack_sockaddr_un() routine in the Socket module.

unpack_sockaddr_un
     Usage:

          ($family, $pathname) = unpack_sockaddr_un($connected_address);
          $pathname = unpack_sockaddr_un($connected_address);

     Returns the address family and pathname (if known) from the supplied
     packed `struct sockaddr_un'.  This is the inverse of
     pack_sockaddr_un().  It differs from the implementation in the Socket
     module in its return of the `$family' value, and in that it trims the
     returned pathname at the first null character.

Exports
-------

default
     None.

exportable
     pack_sockaddr_un unpack_sockaddr_un

tags
     The following *:tags* are available for grouping exportable items:

    :routines
          pack_sockaddr_un unpack_sockaddr_un

    :ALL
          All of the above exportable items.

THREADING STATUS
================

   This module has been tested with threaded perls, and should be as
thread-safe as perl itself.  (As of 5.005_03 and 5.005_57, that's not all
that safe just yet.)

SEE ALSO
========

   Net::Gen(3), Net::UNIX::Server(3)

AUTHOR
======

   Spider Boardman <spider@Orb.Nashua.NH.US>

UNIX-domain sockets interface module for listeners
**************************************************

NAME
====

   Net::UNIX::Server - UNIX-domain sockets interface module for listeners

SYNOPSIS
========

     use Net::Gen;		# optional
     use Net::UNIX;		# optional
     use Net::UNIX::Server;

DESCRIPTION
===========

   The `Net::UNIX::Server' module provides additional services for
UNIX-domain socket communication.  It is layered atop the `Net::UNIX' and
`Net::Gen' modules, which are part of the same distribution.

Public Methods
--------------

   The following methods are provided by the `Net::UNIX::Server' module
itself, rather than just being inherited from `Net::UNIX' or `Net::Gen'.

new
     Usage:

          $obj = new Net::UNIX::Server;
          $obj = new Net::UNIX::Server $pathname;
          $obj = new Net::UNIX::Server $pathname, \%parameters;
          $obj = 'Net::UNIX::Server'->new();
          $obj = 'Net::UNIX::Server'->new($pathname);
          $obj = 'Net::UNIX::Server'->new($pathname, \%parameters);

     Returns a newly-initialised object of the given class.  This is much
     like the regular new methods of other modules in this distribution,
     except that it does a bind rather than a connect, and it does a
     listen.  Unless specified otherwise with a type object parameter, the
     underlying socket will be a datagram socket (`SOCK_DGRAM').

     The examples above show the indirect object syntax which many prefer,
     as well as the guaranteed-to-be-safe static method call.  There are
     occasional problems with the indirect object syntax, which tend to be
     rather obscure when encountered.  See

     <URL:http://www.rosat.mpe-garching.mpg.de/mailing-lists/perl-porters/1998-01/msg01674.html>
     for details.

     See Net/TCP/Server, for an example of running a
     server.  The differences are only in the module names and the fact
     that UNIX-domain sockets bind to a pathname rather than to a port
     number.  Of course, that example is for stream (`type = SOCK_STREAM')
     sockets rather than for datagrams.  UNIX-domain datagram sockets
     don't need to do an accept() (and can't where I've tested this code),
     and can't answer back to their clients unless those clients have also
     bound to a specific path name.

init
     Usage:

          return undef unless $self = $self->init;
          return undef unless $self = $self->init(\%parameters);
          return undef unless $self = $self->init($pathname);
          return undef unless $self = $self->init($pathname, \%parameters);

     Verifies that all previous parameter assignments are valid (via
     checkparams).  Returns the incoming object on success, and undef on
     failure.  Usually called only via a derived class's init method or
     its own new call.

Protected Methods
-----------------

   [See the description in `"Protected Methods"', see Net/Gen,
for my definition of protected methods in Perl.]

   None.

Known Socket Options
--------------------

   There are no socket options known to the `Net::UNIX::Server' module
itself.

Known Object Parameters
-----------------------

   There are no object parameters registered by the `Net::UNIX::Server'
module itself.

Exports
-------

default
     None.

exportable
     None.

tags
     The following *:tags* are available for grouping exportable items:

    :ALL
          All of the above exportable items.

THREADING STATUS
================

   This module has been tested with threaded perls, and should be as
thread-safe as perl itself.  (As of 5.005_03 and 5.005_57, that's not all
that safe just yet.)

SEE ALSO
========

   Net::UNIX(3), Net::Gen(3)

AUTHOR
======

   Spider Boardman <spider@Orb.Nashua.NH.US>

A package to send packets to power on computers.
************************************************

NAME
====

   Net::Wake - A package to send packets to power on computers.

SYNOPSIS
========

   To send a wake-on-lan packet via UDP:

   Net::Wake::by_udp('192.168.1.2', '00:00:87:A0:8A:D2');

DESCRIPTION
===========

   This package sends wake-on-lan packets to turn on machines that are
wake-on-lan capable.

   For now there is only one function in this package:

   Net::Wake::by_udp(host, mac_address, [port]);

   One can omit the colons in the mac_address, but not leading zeros.

SEE ALSO
========

     http://www.pc.ibm.com/us/infobrf/iblan.html
     http://www.nec-computers.com/about/tech/wp-wakeon.html

COPYRIGHT
=========

   Copyright 1999 Clinton Wong

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Get and parse "whois" domain data from InterNIC
***********************************************

NAME
====

   Net::Whois - Get and parse "whois" domain data from InterNIC

SYNOPSIS
========

   Note that all fields except "name" and "tag" may be undef because
"whois" information is erratically filled in.

   use Net::Whois; use Carp;

     my $w = new Net::Whois::Domain $dom
     or die "Can't connect to Whois server\n;

     unless ($w->ok) { croak "No match for $dom";}

     print "Domain: ", $w->domain, "\n";
     print "Name: ", $w->name, "\n";
     print "Tag: ", $w->tag, "\n";
     print "Address:\n", map { "    $_\n" } $w->address;
     print "Country: ", $w->country, "\n";
     print "Name Servers:\n", map { "    $$_[0] ($$_[1])\n" }
     @{$w->servers};
     my ($c, $t);
     if ($c = $w->contacts) {
       print "Contacts:\n";
       for $t (sort keys %$c) {
         print "    $t:\n";
         print map { "\t$_\n" } @{$$c{$t}};
       }
     }
     print "Record created:", $w->record_created ;
     print "Record updated:", $w->record_updated ;

DESCRIPTION
===========

   Net::Whois::Domain new() attempts to retrieve and parse the given
domain's "whois" information from the InterNIC (whois.internic.net).  If
the server could not be contacted, is too busy, or otherwise does not
process the query then the constructor does not return a reference and
your object is undefined.  If the constructor returns a reference, that
reference can be used to access the various attributes of the domains'
whois entry assuming that there was a match.  The member function ok
returns 1 if a match 0 if no match.

   Note that the Locale::Country module (part of the Locale-Codes
distribution) is used to recognize spelled-out country names; if that
module is not present, only two-letter country abbreviations will be
recognized.

   The server consulted is "whois.internic.net". You can only get .org,
.edu, .net, .com domains from Internic. Other whois servers for other
Top-Level-Domains (TLD) return information in a different syntax and are
not supported at this time. Also, only queries for domains are valid.
Querying for a network will fail utterly since those are not kept in the
whois.internic.net server (a future enhancement will add a network lookup
function). Querying for NIC handles won't work since they have a different
return syntax than a domain. Domains other than those listed won't work
they're not in the server. A future enhancment planned will send the query
to the appropriate server based on its TLD.

AUTHOR
======

   Originally written by Chip Salzenberg (chip@pobox.com) in April of 1997
for Idle Communications, Inc.  In September of 1998 Dana Hudes
(dhudes@hudes.org) found this but it was broken and he needed it so he
fixed it.  In August, 1999 Dana and Chip agreed to become co-maintainers
of the module.  Dana released a new version of Net::Whois to CPAN and
resumed active development.

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself. If you make modifications, the author
would like to know so that they can be incorporated into future releases.

Whois Client Interface for Perl5.
*********************************

NAME
====

   Net::XWhois - Whois Client Interface for Perl5.

SYNOPSIS
========

     use Net::XWhois;

     $whois = new Net::XWhois Domain => "vipul.net" ;
     $whois = new Net::XWhois Domain => "bit.ch",
                              Server => "domreg.nic.ch",
                              Retain => 1,
                              Parser => {
                                 nameservers => 'nserver:\s+(\S+)',
                              };

DESCRIPTION
===========

   The Net::XWhois class provides a generic client framework for doing
Whois queries and parsing server response.

   The class maintains an array of whois servers and associated lists of
top level domains they serve for transparently selecting servers
appropriate for different queries.  The server details are, therefore,
hidden from the user and "vipul.net" (from InterNIC), gov.ru (from RIPE)
and "bit.ch" (from domreg.nic.ch) are queried in the same manner.  This
behaviour can be overridden by specifying different bindings at object
construction or by registering associations with the class.  See
`"register_associations()"' in this node and `"new()"' in this node.

   One of the more important features of this module is to enable the
design of consistent and predictable interfaces to incompatible whois
response formats.  The Whois RFC (954) does not define a template for
presenting server data; consequently there is a large variation in layout
styles as well as content served across servers.

   To overcome this, Net::XWhois maintains another set of tables - parsing
rulesets - for a few, popular response formats. (See `"%PARSERS"' in this
node). These parsing tables contain section names (labels) together with
regular expressions that match the corresponding section text. The section
text is accessed "via" labels which are available as data instance methods
at runtime. By following a consistent nomenclature for labels, semantically
related information encoded in different formats can be accessed with the
same methods.

CONSTRUCTOR
===========

new ()
     Creates a Net::XWhois object.  Takes an optional argument, a hash,
     that specifies the domain name to be queried.  Calls lookup() if a
     name is provided. The argument hash can also specify a whois server,
     a parsing rule-set or a parsing rule-set format. (See
     `"personality()"' in this node).  Omitting the argument will create
     an "empty" object that can be used for accessing class data.

personality ()
     Alters an object's personality.  Takes a hash with following
     arguments.  (Note: These arguments can also be passed to the
     constructor).

    Domain
          Domain name to be queried.

    Server
          Server to query.

    Parser
          Parsing Rule-set.  See `"%PARSERS"' in this node.

               Parser => {
                 name            => 'domain:\s+(\S+)\n',
                 nameservers     => 'nserver:\s+(\S+)',
                 contact_emails  => 'e-mail:\s+(\S+\@\S+)',
               };

    Format
          A pre-defined parser format like INTERNIC, INTERNIC_FORMAT, RIPE,
          RIPE_CH, JAPAN etc.

               Format => 'INTERNIC_CONTACT',

    Nocache
          Force XWhois to ignore the cached records.

    Error
          Determines how a network connection error is handled. By default
          Net::XWhois will croak() if it can't connect to the whois
          server. The Error attribute specifies a function call name that
          will be invoked when a network connection error occurs. Possible
          values are croak, carp, confess (imported from Carp.pm) and
          ignore (a blank function provided by Net::XWhois). You can, of
          course, write your own function to do error handling, in which
          case you'd have to provide a fully qualified function name.
          Example: main::logerr.

    Timeout
          Timeout value for establishing a network connection with the
          server. The default value is 60 seconds.

CLASS DATA & ACCESS METHODS
===========================

%PARSERS
     An associative array that contains parsing rule-sets for various
     response formats.  Keys of this array are format names and values are
     hash refs that contain section labels and corresponding parser code.
     The parser code can either be a regex or a reference to a subroutine.
     In the case of a subroutine, the whois 'response' information is
     available to the sub in $_[0].  Parsers can be added and extended
     with the register_parser() method.  Also see `Data Instance Methods'
     in this node.

     my %PARSERS  = (    INTERNIC => {     contact_tech    => 'Technical
     Contact.*?\n(.*?)(?=\...      contact_zone    => 'Zone
     Contact.*?\n(.*?)(?=\s*\n[...      contact_billing => 'Billing
     Contact.*?\n(.*?)(?=\s*...      contact_emails  =>
     \&example_email_parser   },   { etc. ... },  );

          sub example_email_parser {

          # Note that the default internal implemenation for
          # the INTERNIC parser is not a user-supplied code
          # block.  This is just an instructive example.

          my @matches = $_[0] =~ /(\S+\@\S+)/sg;
          return @matches;
           }

     See XWhois.pm for the complete definition of %PARSERS.

%ASSOC
     %ASSOC is a table that associates server names with response formats
     and the top-level domains they serve.  You'd need to modity this
     table if you wish to extend the module's functionality to handle a
     new set of domain names.  Or alter existing information.
     register_association() provides an interface to this array.  See
     XWhois.pm for the complete definition.

          %ASSOC = (
           'whois.internic.net' =>
                 [ INTERNIC,  [ qw/com net org/ ] ],
           'whois.nic.net.sg'   =>
                 [ RIPE,      [ qw/sg/ ] ],
           'whois.aunic.net'    =>
                 [ RIPE,      [ qw/au/ ] ]

register_parser()
     Extend, modify and override entries in %PARSERS. Accepts a hash with
     three keys - Name, Retain and Parser.  If the format definition for
     the specified format exists and the Retain key holds a true value,
     the keys from the specified Parser are added to the existing
     definition. A new definition is created when Retain is false/not
     specified.

          my $w = new Net::Whois;
          $w->register_parser (
             Name   => "INTERNIC",
             Retain => 1,
             Parser => {
                 creation_time => 'created on (\S*?)\.\n',
                 some_randome_entity => \&random_entity_subroutine
             };

          Instructions on how to create a workable random_entity_subroutine
          are availabe in the I<%PARSERS> description, above.

register_association()
     Override and add entries to %ASSOC.  Accepts a hash that contains
     representation specs for a whois server. The keys of this hash are
     server machine names and values are list-refs to the associated
     response formats and the top-level domains handled by the servers.
     See Net/XWhois.pm for more details.

          my $w = new Net::XWhois;
          $w->register_association (
              'whois.aunic.net' => [ RIPE, [ qw/au/ ] ]
          );

register_cache()
     By default, Net::XWhois caches all whois responses and commits them,
     as separate files, to /tmp/whois.  register_cache () gets and sets
     the cache directory. Setting to "undef" will disable caching.

          $w->register_cache ( "/some/place/else" );
          $w->register_cache ( undef );

OBJECT METHODS
==============

*Data Instance Methods*
     Access to the whois response data is provided via AUTOLOADED methods
     specified in the Parser.  The methods return scalar or list data
     depending on the context.

     Internic Parser provides the following methods:

    name()
          Domain name.

    status()
          Domain Status when provided.  When the domain is on hold, this
          method will return "On Hold" string.

    nameservers()
          Nameservers along with their IPs.

    registrant
          Registrant's name and address.

    contact_admin()
          Administrative Contact.

    contact_tech()
          Technical Contact.

    contact_zone()
          Zone Contact.

    contact_billing()
          Billing Contact.

    contact_emails()
          List of email addresses of contacts.

    contact_handles()
          List of contact handles in the response.  Contact and Domain
          handles are valid query data that can be used instead of contact
          and domain names.

    domain_handles()
          List of domain handles in the response.   Can be used for sorting
          out reponses that contain multiple domain names.

lookup()
     Does a whois lookup on the specified domain.  Takes the same
     arguments as new().

          my $w = new Net::XWhois;
          $w->lookup ( Domain => "perl.com" );
          print $w->response ();

EXAMPLES
========

   Look at example programs that come with this package.  "whois" is a
replacement for the standard RIPE/InterNIC whois client.  "creation"
overrides the Parser value at object init and gets the Creation Time of an
InterNIC domain.  "creation2" does the same thing by extending the Class
Parser.  "contacts" queries and prints information about domain's
Tech/Billing/Admin contacts.

   contribs/ containts parsers for serveral whois servers, which have not
been patched into the module.

AUTHOR
======

   Vipul Ved Prakash <mail@vipul.net>

THANKS
======

   Curt Powell <curt.powell@sierraridge.com>, Matt Spiers
<matt@pavilion.net>, Richard Dice <rdice@pobox.com>, Robert Chalmers
<robert@chalmers.com.au> for patches, bug-reports and many cogent
suggestions.

MAILING LIST
============

   Net::XWhois development has moved to the sourceforge mailing,
xwhois-devel@lists.sourceforge.net.  Please send all Net::XWhois related
communication directly to the list address.  The subscription interface is
at: http://lists.sourceforge.net/mailman/listinfo/xwhois-devel

COPYRIGHT
=========

   Copyright (c) 1998-2000 Vipul Ved Prakash.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Perl extension for talking to Z39.50 servers.
*********************************************

NAME
====

   Net::Z3950 - Perl extension for talking to Z39.50 servers.

SYNOPSIS
========

   (This code blocks in reads: see below for sample non-blocking code
which allows multiple servers to be searched in parallel.)

     use Net::Z3950;
     $conn = new Net::Z3950::Connection('server.host.name', 210);
     $rs = $conn->search('au=kernighan or su=unix');
     foreach $rec ($rs->records()) {
     	print $rec->render();
     }

DESCRIPTION
===========

   This module provides a Perl interface to the Z39.50 information
retrieval protocol (aka. ISO 23950), a mature and powerful protocol used
in application domains as diverse as bibliographic information,
geo-spatial mapping, museums and other cultural heritage information, and
structured vocabulary navigation.

   Two basic approaches are possible to building clients with this module:

   * The simple synchronous approach considers blocking reads acceptable,
     and therefore allows a straightforward style of imperative
     programming.  This approach is suitable for clients which only talk
     to one server at a time, and is exemplified by the code in the
     SYNOPSIS section above.

   * The more complex asynchronous approach, appropriate for clients which
     multiplex simultaneous connections, requires a slightly less familiar
     event-driven programming style, as exemplified in the ASYNCHRONOUS
     SYNOPSIS section below.

   (The simpler synchronous interface functions are implemented as a thin
layer on top of the asynchronous functions.)

ASYNCHRONOUS SYNOPSIS
=====================

   (This code does not block in reads, and so is suitable for broadcast
clients which search multiple servers simultaneously: see below for
simpler sample code that blocks in reads.)

     ### No point filling this in until we have it working.

FUNCTIONS
=========

   The `Net::Z3950' module itself provides very few functions: most of the
functionality is provided by the daughter modules included by `Net::Z3950'
- `Net::Z3950::Manager', `Net::Z3950::Connection', etc.

errstr()
--------

     $errcode = $conn->errcode();
     $errmsg = Net::Z3950::errmsg($errcode);
     print "error $errcode ($errmsg)\n";

   Returns an English-language string describing the error indicated by
the Z39.50 BIB-1 diagnostic error code *$errcode*.

opstr()
-------

     $str = Net::Z3950::opstr($conn->errop());
     print "error occurred in $str\n";

   Returns an English-language string describing the operation indicated
by the argument, which must be one of the `Net::Z3950::Op::*' constants
described in the documentation for the `Net::Z3950::Connection' class's
op() method.

AUTHOR
======

   Mike Taylor <mike@tecc.co.uk>

   First version Tuesday 23rd May 2000.

SEE ALSO
========

   This module is built on Index Data's Yaz (Yet Another Z39.50) toolkit,
which is freely available at http://indexdata.dk/yaz/

   Index Data also provide a variety of other useful Z39.50 software
including the free server/database Zebra, the commercial server/database
Z'mbol, a Tcl interface to Z39.50 called Ir/Tcl, and a free web-to-Z39.50
gateway called Zap.  See their home page at http://indexdata.dk/

   The best source of information about Z39.50 itself is the official
Mainenance Agency at http://lcweb.loc.gov/z3950/agency/

Read-only objects representing decoded Z39.50 APDUs
***************************************************

NAME
====

   Net::Z3950::APDU - Read-only objects representing decoded Z39.50 APDUs

SYNOPSIS
========

   *You probably shouldn't be reading this!*

     package Net::Z3950::APDU::SomeSpecificSortOfAPDU;
     use Net::Z3950::APDU;
     @ISA = qw(Net::Z3950::APDU);
     @FIELDS = qw(names of APDU fields);

DESCRIPTION
===========

   This class provides a trivial base for the various read-only APDUs
implemented as a part of the Net::Z3950 module.  Its role is simply to
supply named methods providing read-only access to the same-named fields.
The set of fields is specified by the derived class's package-global
`@FIELDS' array.

   *You don't need to understand or use this class in order to use the
Net::Z3950 module.  It's purely an implementation detail.  In fact, I
probably should never even have written this documentation.  Forget I said
anything.  Go and read the next section.*

SUBCLASSES
==========

   The following classes are all trivial derivations of `Net::Z3950::APDU',
and represent specific types of APDU.  Each such class is characterised by
the set of data-access methods it supplies: these are listed below.

   Each method takes no arguments, and returns the information implied by
its name.  See the relevant sections of the Z39.50 Standard for
information on the interpretation of this information - for example,
section 3.2.1 (Initialization Facility) describes the elements of the
Net::Z3950::APDU::InitResponse class.

   *Actually, you don't need to understand or use any of these classes
either: they're used internally in the implementation, so this
documentation is provided as a service to those who will further develop
this module in the future.*

Net::Z3950::APDU::InitResponse
------------------------------

     referenceId()
     preferredMessageSize()
     maximumRecordSize()
     result()
     implementationId()
     implementationName()
     implementationVersion()

Net::Z3950::APDU::SearchResponse
--------------------------------

     referenceId()
     resultCount()
     numberOfRecordsReturned()
     nextResultSetPosition()
     searchStatus()
     resultSetStatus()
     presentStatus()
     records()

Net::Z3950::APDU::PresentResponse
---------------------------------

     referenceId()
     numberOfRecordsReturned()
     nextResultSetPosition()
     presentStatus()
     records()

Net::Z3950::APDU::NamePlusRecordList
------------------------------------

   No methods - just treat as a reference to an array of
Net::Z3950::APDU::NamePlusRecord

Net::Z3950::APDU::NamePlusRecord
--------------------------------

     databaseName()
     which()
     databaseRecord()
     surrogateDiagnostic()
     startingFragment()
     intermediateFragment()
     finalFragment()

   Only one of the last five methods will return anything - you can find
out which one by inspecting the return value of the `which()' method,
which always takes one of the following values:

   * Net::Z3950::NamePlusRecord::DatabaseRecord

   * Net::Z3950::NamePlusRecord::SurrogateDiagnostic

   * Net::Z3950::NamePlusRecord::StartingFragment

   * Net::Z3950::NamePlusRecord::IntermediateFragment

   * Net::Z3950::NamePlusRecord::FinalFragment

   When `which()' is `Net::Z3950::NamePlusRecord::DatabaseRecord', the
object returned from the `databaseRecord()' method will be a decoded
Z39.50 EXTERNAL.  Its type may be any of the following (and may be tested
using `$rec->isa('Net::Z3950::APDU::Whatever')' if necessary.)

   * Net::Z3950::Record::SUTRS (a subclass of Net::Z3950::APDU::SUTRS)

   * Net::Z3950::Record::GRS1 (a subclass of Net::Z3950::APDU::GRS1)

   * Net::Z3950::Record::USMARC (a subclass of Net::Z3950::APDU::USMARC)
     and similarly, Net::Z3950::Record::UKMARC,
     Net::Z3950::Record::NORMARC, *etc*.

     ### others, not yet supported

Net::Z3950::APDU::SUTRS, Net::Z3950::APDU::USMARC, Net::Z3950::APDU::UKMARC, Net::Z3950::APDU::NORMARC, Net::Z3950::APDU::LIBRISMARC, Net::Z3950::APDU::DANMARC
---------------------------------------------------------------------------------------------------------------------------------------------------------------

   No methods - just treat as a string.

Net::Z3950::APDU::GRS1
----------------------

   No methods - just treat as a reference to an array of
`Net::Z3950::APDU::TaggedElement'

Net::Z3950::APDU::TaggedElement;
--------------------------------

     tagType()
     tagValue()
     tagOccurrence()
     content()

Net::Z3950::APDU::ElementData
-----------------------------

     which()
     numeric()
     string()
     subtree()

   Only one of the last three methods will return anything - you can find
out which one by inspecting the return value of the `which()' method,
which always takes one of the following values:

   * Net::Z3950::ElementData::Numeric

   * Net::Z3950::ElementData::String

   * Net::Z3950::ElementData::subtree

   * ### others, not yet supported

Net::Z3950::APDU::DiagRecs
--------------------------

   No methods - just treat as a reference to an array of object
references.  The objects will typically be of class
`Net::Z3950::APDU::DefaultDiagFormat', but careful callers will check
this, since any kind of EXTERNAL may be provided instead.

Net::Z3950::APDU::DefaultDiagFormat;
------------------------------------

     diagnosticSetId()
     condition()
     addinfo()

Net::Z3950::APDU::OID
---------------------

   No methods - just treat as a reference to an array of integers.

AUTHOR
======

   Mike Taylor <mike@tecc.co.uk>

   First version Saturday 27th May 2000.

Connection to a Z39.50 server, with request queue
*************************************************

NAME
====

   Net::Z3950::Connection - Connection to a Z39.50 server, with request
queue

SYNOPSIS
========

     $conn = new Net::Z3950::Connection($hostname, $port);
     $rs = $conn->search('au=kernighan and su=unix');
     # or
     $mgr = $conn->manager();
     $conn = $mgr->wait();
     if ($mgr->failed()) {
     	die "error " . $conn->errcode() .
     		"( " . $conn->addinfo() . ")" .
     		" in " . Net::Z3950::opstr($conn->errop());
     }

DESCRIPTION
===========

   A connection object represents an established connection to a
particular server on a particular port, together with options such as the
default database in which to search.  It maintains a queue of outstanding
requests (searches executed against it, fetches executed against result
sets instantiated against it) etc.

METHODS
=======

new()
-----

     $conn = new Net::Z3950::Connection($mgr, $host, $port);

   Creates and returns a new connection, under the control of the manager
*$mgr*, to the server on the specified $host and $port.  If the $port
argument is omitted, the `z3950' service is used; if this is not defined,
port 210 is used.

   The manager argument may be undef, or may be omitted completely; in
either case, the connection is created under the control of a "default
manager", a reference to which may be subsequently retrieved with the
manager() method.  Multiple connections made with no explicitly-specified
manager in this way will all share the same implicit manager.  The default
manager is initially in synchronous mode.

   If the connection is created in synchronous mode, (or, if the
constructor call doesn't specify a mode, if the manager controlling the
new connection is synchronous), then the constructor does not return until
either the connection is forged or an error occurs in trying to do so.
(In the latter case, error information is stored in the manager
structure.)  If the connection is asynchronous, then the new object is
created and returned before the connection is forged; this will happen in
parallel with subsequent actions.

   Any of the standard options (including synchronous or asynchronous
mode) may be specified as additional arguments.  Specifically:

     $conn = new Net::Z3950::Connection($mgr, $host, $port, mode => 'async');

   Works as expected.

option()
--------

     $value = $conn->option($type);
     $value = $conn->option($type, $newval);

   Returns *$conn*'s value of the standard option $type, as registered in
*$conn* itself, in the manager which controls it, or in the global
defaults.

   If *$newval* is specified, then it is set as the new value of that
option in *$conn*, and the option's old value is returned.

manager()
---------

     $mgr = $conn->manager();

   Returns a reference to the manager controlling *$conn*.  If *$conn* was
created with an explicit manager, then this method will always return that
function; otherwise, it returns a reference to the single global "default
manager" shared by all other connections.

startSearch()
-------------

     $conn->startSearch($srch);
     $conn->startSearch(-ccl => 'au=kernighan and su=unix');
     $conn->startSearch(-prefix => '@and @attr 1=1 kernighan @attr 1=21 unix');
     $conn->startSearch('@and @attr 1=1 kernighan @attr 1=21 unix');

   Inititiates a new search against the Z39.50 server to which *$conn* is
connected.  Since this can never fail (:-), it `die()s' if anything goes
wrong.  But that will never happen.  ("Surely the odds of that happening
are million to one, doctor?")

   The query itself can be specified in a variety of ways:

   * A `Net::Z3950::Query' object may be passed in.

   * A query-type option may be passed in, together with the query string
     itself as its argument.  Currently recognised query types are `-ccl'
     (using the standard CCL query syntax, interpreted by the server),
     `-ccl2rpn' (CCL query compiled by the client into a type-1 query) and
     `-prefix' (using Index Data's prefix query notation).

   * A query string alone may be passed in.  In this case, it is
     interpreted according to the query type previously established as a
     default for *$conn* or its manager.

   The various query types are described in more detail in the
documentation of the `Net::Z3950::Query' class.

search()
--------

     $rs = $conn->search($srch);

   This utility method performs a blocking search, returning a reference
to the result set generated by the server.  It takes the same arguments as
startSearch()

op()
----

     op = $conn->op();
     if (op == Net::Z3950::Op::Search) { # ...

   When a connection has been returned from the `Net::Z3950::Manager'
class's wait() method, it's known that *something* has happened to it.
This method may then be called to find out what.  It returns one of the
following values:

`Net::Z3950::Op::Error'
     An error occurred.  The details may be obtained via the `errcode()',
     `addinfo()' and `errop()' methods described below.

`Net::Z3950::Op::Init'
     An init response was received.  The response object may be obtained
     via the initResponse() method described below.

`Net::Z3950::Op::Search'
     A search response was received.  The result set may be obtained via
     the `resultSet()' method described below.

`Net::Z3950::Op::Get'
     One or more result-set records have become available.  They may be
     obtained via the records() method described below.

errcode(), addinfo(), errop()
-----------------------------

     if ($conn->op() == Net::Z3950::Op::Error) {
     	print "error number: ", $conn->errcode(), "\n";
     	print "error message: ", $conn->errmsg(), "\n";
     	print "additional info: ", $conn->errcode(), "\n";
     	print "in function: ", Net::Z3950::opstr($conn->errop()), "\n";
     }

   When an error is known to have occurred on a connection, the error code
(from the BIB-1 diagnosic set) can be retrieved via the `errcode()'
method, any additional information via the `addinfo()' method, and the
operation that was being attempted when the error occurred via the
`errop()' method.  (The error operation returned takes one of the values
that may be returned from the op() method.)

   As a convenience, `$conn-'errmsg()> is equivalent to
`Net::Z3950::diagbib1_str($conn-'errcode())>.

initResponse()
--------------

     if ($op == Net::Z3950::Op::Init) {
     	$rs = $conn->initResponse();

   When a connection is known to have received an init response, the
response may be accessed via the connection's initResponse() method.

searchResponse(), resultSet()
-----------------------------

     if ($op == Net::Z3950::Op::Search) {
     	$sr = $conn->searchResponse();
     	$rs = $conn->resultSet();

   When a connection is known to have received a search response, the
response may be accessed via the connection's `searchResponse()', and the
search result may be accessed via the connection's `resultSet()' method.

resultSets()
------------

     @rs = $conn->resultSets();

   Returns a list of all the result sets that have been created across the
connection *$conn* and have not subsequently been deleted.

records()
---------

     if ($op == Net::Z3950::Op::Get) {
     	@recs = $conn->records();

   When a connection is known to have some result-set records available,
they may be accessed via the connection's records() method, which returns
an array of zero or more `Net::Z3950::Record' references.

   Zero records are only returned if there are no more records on the
server satisfying the get() requests that have been made on the
appropriate result set associated with *$conn*.

   *### What happens if the client issues several sets of get requests on
the same result set, and those requests can only be satisfied by repeated
PRESENT requests?  This is unclear, and suggests that the interface needs
rethinking.  Perhaps we need a method to return a reference to a
particular result set for which records have arrived?  Watch this space
...*

AUTHOR
======

   Mike Taylor <mike@tecc.co.uk>

   First version Tuesday 23rd May 2000.

SEE ALSO
========

   `Net::Z3950::Query'

State manager for multiple Z39.50 connections.
**********************************************

NAME
====

   Net::Z3950::Manager - State manager for multiple Z39.50 connections.

SYNOPSIS
========

     $mgr = new Net::Z3950::Manager(mode => 'async');
     $conn = $mgr->connect($hostname, $port);
     # Set up some more connections, then:
     while ($conn = $mgr->wait()) {
     	# Handle message on $conn
     }

DESCRIPTION
===========

   A manager object encapsulates the Net::Z3950 module's global state -
preferences for search parsing, preferred record syntaxes, compiled
configuration files, etc. - as well as a list of references to all the
open connections.  It main role is to handle multiplexing between the
connections that are opened on it.

   We would normally expect there to be just one manager object in a
program, but I suppose there's no reason why you shouldn't make more if
you want.

   Simple programs - those which therefore have no requirement for
multiplexing, perhaps because they connect only to a single server - do
not need explicitly to create a manager at all: an anonymous manager is
implicitly created along with the connection.

METHODS
=======

new()
-----

     $mgr = new Net::Z3950::Manager();

   Creates and returns a new manager.  Any of the standard options may be
specified as arguments; in addition, the following manager-specific
options are recognised:

mode
     Must be either sync or async; if omitted, defaults to sync.  The mode
     affects various details of subsequent behaviour - for example, see
     the description of the `Net::Z3950::Connection' class's new() method.

option()
--------

     $value = $mgr->option($type);
     $value = $mgr->option($type, $newval);

   Returns *$mgr*'s value of the standard option $type, as registered in
*$mgr* or in the global defaults.

   If *$newval* is specified, then it is set as the new value of that
option in *$mgr*, and the option's old value is returned.

connect()
---------

     $conn = $mgr->connect($hostname, $port);

   Creates a new connection under the control of the manager *$mgr*.  The
connection will be forged to the server on the specified $port of
<$hostname>.

   Additional standard options may be specified after the $port argument.

   (This is simply a sugar function to `Net::Z3950::Connection-'new()>)

wait()
------

     $conn = $mgr->wait();

   Waits for an event to occur on one of the connections under the control
of *$mgr*, yielding control to any other event handlers that may have been
registered with the underlying event loop.

   When a suitable event occurs - typically, a response is received to an
earlier INIT, SEARCH or PRESENT - the handle of the connection on which it
occurred is returned: the handle can be further interrogated with its op()
and related methods.

connections()
-------------

     @conn = $mgr->connections();

   Returns a list of all the connections that have been opened under the
control of the manager *$mgr* and have not subsequently been closed.

resultSets()
------------

     @rs = $mgr->resultSets();

   Returns a list of all the result sets that have been created across the
connections associated with the manager *$mgr* and have not subsequently
been deleted.

AUTHOR
======

   Mike Taylor <mike@tecc.co.uk>

   First version Tuesday 23rd May 2000.

SEE ALSO
========

   List of standard options.

   Discussion of the Net::Z3950 module's use of the Event module.

base class for records retrieved from a Z39.50 server
*****************************************************

NAME
====

   Net::Z3950::Record - base class for records retrieved from a Z39.50
server

SYNOPSIS
========

     $rs = $conn->resultSet();
     $rec = $rs->record($n);
     print $rec->render();

DESCRIPTION
===========

   A Record object represents a record retrieved from a Z39.50 server.  In
fact, the `Net::Z3950::Record' class itself is never instantiated:
instead, the Net::Z3950 module creates objects of subclasses such as
Net::Z3950::Record::SUTRS, Net::Z3950::Record::GRS1 and
`Net::Z3950::Record::USMARC'.  This class defines a common interface which
must be supported by all such subclasses.

METHODS
=======

nfields()
---------

     $count = $rec->nfields();

   Returns the number of fields in the record *$rec*.

render()
--------

     print $rec->render();

   Returns a human-readable string representing the content of the record
*$rec* in a form appropriate to its specific type.

rawdata()
---------

     $raw = $rec->rawdata();

   Returns the raw form of the data in the record, which will in general
be different in form for different record syntaxes.

SUBCLASSES
==========

Net::Z3950::Record::SUTRS
-------------------------

   Represents a a record using the Simple Unstructured Text Record Syntax
(SUTRS) - a simple flat string containing the record's data in a form
suitable for presentation to humans (so that the same thing is returned by
the render() and rawdata() methods return the same thing.)

   See Appendix REC.2 (Simple Unstructured Text Record Syntax) of the
Z39.50 Standard for more information.

Net::Z3950::Record::GRS1
------------------------

   Represents a record using Generic Record Syntax 1 (GRS1) - a list of
tagged fields where each tag is made up of a tag type and tag value, and
each field may be of any type, including numeric, string, and recursively
contained sub-record.  Fields may also be annotated with metadata, variant
information etc.

   See Appendix REC.5 (Generic Record Syntax 1) of the Z39.50 Standard for
more information.

Net::Z3950::Record::USMARC, Net::Z3950::Record::UKMARC, Net::Z3950::Record::NORMARC, Net::Z3950::Record::LIBRISMARC, Net::Z3950::Record::DANMARC
------------------------------------------------------------------------------------------------------------------------------------------------

   Represents a record using the appropriate MARC (MAchine Readable
Catalogue) format - binary formats used extensively in libraries.

   For further information on the MARC formats, see the Library of
Congress Network Development and MARC Standards Office web page at
http://lcweb.loc.gov/marc/ and the MARC module in Ed Summers's directory
at CPAN, http://cpan.valueclick.com/authors/id/E/ES/ESUMMERS/

### others, not yet supported
-----------------------------

AUTHOR
======

   Mike Taylor <mike@tecc.co.uk>

   First version Sunday 4th May 2000.

result set received in response to a Z39.50 search
**************************************************

NAME
====

   Net::Z3950::ResultSet - result set received in response to a Z39.50
search

SYNOPSIS
========

     if ($conn->op() == Net::Z3950::Op::Search) {
     	$rs = $conn->resultSet();
     	$size = $rs->size();

DESCRIPTION
===========

   A ResultSet object represents the set of records found by a Z39.50
server in response to a search.  At any given time, none, some or all of
the records may have been physcially transferred to the client; a cache is
maintained.

   Note that there is no constructor for this class (or at least, none
that I'm going to tell you about :-)  ResultSet objects are always created
by the Net::Z3950 module itself, and are returned to the caller via the
`Net::Z3950::Connection' class's `resultSet()' method.

METHODS
=======

size()
------

     $nrecords = $rs->size();

   Returns the number of records in the result set *$rs*

record()
--------

     $rec = $rs->record($n);

   Returns a reference to $nth record in the result set *$rs*, if the
content of that record is known.  Valid values of $n range from 1 to the
return value of the size() method.

   If the record is not available, an undefined value is returned, and
diagnostic information made available via *$rs*'s `errcode()' and
`addinfo()' methods.

   As a special case, when the connection is anychronous, the `errcode()'
may be zero, indicating simply that the record has not yet been fetched
from the server.  In this case, the calling code should try again later.
(How much later?  As a rule of thumb, after it's done "something else",
such as request another record or issue another search.)  This can never
happen in synchronous mode.

records()
---------

     @records = $rs->records();
     foreach $rec (@records) {
         print $rec->render();
     }

   This utility method returns a list of all the records in the result set
I$<rs>.  Because Perl arrays are indexed from zero, the first record is
`$records[0]', the second is `$records[1]', etc.

   If not all the records associated with *$rs* have yet been transferred
from the server, then they need to be transferred at this point.  This
means that the records() method may block, and so is not recommended for
use in applications that interact with multiple servers simultaneously.
It does also have the side-effect that subsequent invocations of the
record() method will always immediately return either a legitimate record
or a "real error" rather than a "not yet" indicator.

   If an error occurs, an empty list is returned.  Since this is also
what's returned when the search had zero hits, well-behaved applications
will consult `$rs-'size()> in these circumstances to determine which of
these two conditions pertains.  After an error has occurred, details may
be obtained via the result set's `errcode()' and `addinfo()' methods.

   If a non-empty list is returned, then individual elements of that list
may still be undefined, indicating that corresponding record could not be
fetched.  In order to get more information, it's necessary to attempt to
fetch the record using the record() method, then consult the `errcode()'
and `addinfo()' methods.

   *Unwarranted personal opinion*: all in all, this method is a pleasant
short-cut for trivial programs to use, but probably carries too many
caveats to be used extensively in serious applications.

errcode(), addinfo()
--------------------

     if (!defined $rs->record($n)) {
     	print "error number: ", $rs->errcode(), "\n";
     	print "additional info: ", $rs->errcode(), "\n";
     }

   When a result set's record() method returns an undefined value,
indicating an error, it also sets into the result set the BIB-1 error code
and additional information returned by the server.  They can be retrieved
via the `errcode()' and `addinfo()' methods.

option()
--------

     $value = $rs->option($type);
     $value = $rs->option($type, $newval);

   Returns *$rs*'s value of the standard option $type, as registered in
*$rs* itself, in the connection across which it was created, in the
manager which controls that connection, or in the global defaults.

   If *$newval* is specified, then it is set as the new value of that
option in *$rs*, and the option's old value is returned.

AUTHOR
======

   Mike Taylor <mike@tecc.co.uk>

   First version Sunday 28th May 2000.

tutorial for the Net::Z3950 module
**********************************

NAME
====

   Net::Z3950::Tutorial - tutorial for the Net::Z3950 module

SYNOPSIS
========

   Apparently, every POD document has to have a SYNOPSIS.  So here's one.

DESCRIPTION
===========

   `Net::Z3950' is a Perl module for writing Z39.50 clients.  (If you want
to write a Z39.50 server, you want the `Net::Z3950::SimpleServer' module.)

   Its goal is to hide all the messy details of the Z39.50 protocol - at
least by default - while providing access to all of its glorious power.
Sometimes, this involves revealing the messy details after all, but at
least this is the programmer's choice.  The result is that writing Z39.50
clients works the way it should according my favourite of the various Perl
mottos: "Simple things should be simple, and difficult things should be
possible."

   If you don't know what Z39.50 is, then the best place to find out is at
http://lcweb.loc.gov/z3950/agency/ the web site of the Z39.50 Maintenance
Agency.  Among its many other delights, this site contains a complete
downloadable soft-copy of the standard itself.  In briefest summary,
Z39.50 is the international standard for distributed searching and
retrieval.

A VERY SIMPLE CLIENT
====================

   The `Net::Z3950' distribution includes a couple of sample clients in
the `samples' directory.  The simplest of them, `trivial.pl' reads as
follows:

     use Net::Z3950;
     $conn = new Net::Z3950::Connection('indexdata.dk', 210,
     				   databaseName => 'gils');
     $rs = $conn->search('mineral');
     print "found ", $rs->size(), " records:\n";
     my $rec = $rs->record(1);
     print $rec->render();

   This complete program retrieves from the database called "gils" on the
Z39.50 server on port 210 of `indexdata.dk' the first record matching the
search "mineral", and renders it in human-readable form.  Typical output
would look like this:

     6 fields:
     (1,1) 1.2.840.10003.13.2
     (1,14) "2"
     (2,1) {
         (1,19) "UTAH EARTHQUAKE EPICENTERS"
         (3,Acronym) "UUCCSEIS"
     }
     (4,52) "UTAH GEOLOGICAL AND MINERAL SURVEY"
     (4,1) "ESDD0006"
     (1,16) "198903"

HOW IT WORKS
============

   Let's pick the trivial client apart line by line (it won't take long!)

     use Net::Z3950;

   This line simply tells Perl to pull in the `Net::Z3950' module - a
prerequisite for using types like `Net::Z3950::Connection'.

     $conn = new Net::Z3950::Connection('indexdata.dk', 210,
     				   databaseName => 'gils');

   Creates a new connection to the Z39.50 server on port 210 of the host
`indexdata.dk', noting that searches on this connection will default to
the database called "gils".  A reference to the new connection is stored
in `$conn'.

     $rs = $conn->search('mineral');

   Performs a single-word search on the connection referenced by `$conn'
(in the previously established default database, "gils".)  In response,
the server generates an *result set*, notionally containing all the
matching records; a reference to the new connection is stored in `$rs'.

     print "found ", $rs->size(), " records:\n";

   Prints the number of records in the new result set `$rs'.

     my $rec = $rs->record(1);

   Fetches from the server the first record in the result set `$rs',
requesting the default record syntax (GRS-1) and the default element set
(brief, "b"); a reference to the newly retrieved record is stored in
`$rec'.

     print $rec->render();

   Prints a human-readable rendition of the record `$rec'.  The exact
format of the rendition is dependent on issues like the record syntax of
the record that the server sent.

MORE COMPLEX BEHAVIOUR
======================

Searching
---------

   Searches may be specified in one of two different syntaxes, both of
which will be familiar to users of the Yaz toolkit.  The default syntax is
so-called Prefix Query Notation, or PQN, a bespoke format invented by
Index Data to map simply to the Z39.50 type-1 query structure.  The other
is the Common Command Language, or CCL, an international standard query
language often used in libraries.

   CCL queries may be interpreted on the client side and translated into a
type-1 query which is forwarded to the server; or it may be sent "as is"
for the server to interpret as it may.

   The interpretation of the search string may be specified by passing an
argument of `-prefix', `-ccl' or `-ccl2rpn' to the search() method before
the search string itself, as follows:

   *Prefix Queries*

     $rs = $conn->search(-prefix => '@or rock @attr 1=21 mineral');

   Prefix Query Notation is fully described in section 4.1 (*Query Syntax
Parsers*) of the Yaz toolkit documentation, *YAZ User's Guide and
Reference*.

   Briefly, however, keywords begin with an `@'-sign, and all other words
are interpreted as search terms.  Keywords include the binary operators
`@and' and `@or', which join together the two operands that follow them,
and `@attr', which introduces a type=value expression specifying an
attribute to be applied to the following term.

   So:

   * `fruit' searches for the term "fruit",

   * `@and fruit fish' searches for records containing both "fruit" and
     "fish",

   * `@or fish chicken' searches for records containing either "fish" or
     "chicken" (or both),

   * `@and fruit @or fish chicken' searches for records containing both
     "fruit" and at least one of "fish" or "chicken".

   * `@or rock @attr 1=21 mineral' searches for records either containing
     "rock" or "mineral", but with the "mineral" search term carrying an
     attribute of type 1, with value 21 (typically interpreted to mean
     that the search term must occur in the "subject" field of the record.)

   *CCL Queries*

     $rs = $conn->search(-ccl2rpn => 'rock or su=mineral');
     $rs = $conn->search(-ccl => 'rock or su=mineral');

   CCL is formally specified in the international standard ISO 8777
(*Commands for interactive text searching*) and also described in section
4.1 (*Query Syntax Parsers*) of the Yaz toolkit documentation, *YAZ User's
Guide and Reference*.

   Briefly, however, there is a set of well-known keywords including and,
or and not.  Words other than these are interpreted as search terms.
Operating grouping (precedence) is specified by parentheses, and the
semantics of a search term may be modified by prepending one or more
comma-separated qualifiers qualifiers and an equals sign.

   So:

   * `fruit' searches for the term "fruit",

   * `fruit and fish' searches for records containing both "fruit" and
     "fish",

   * `fish or chicken' searches for records containing either "fish" or
     "chicken" (or both),

   * `fruit and (fish or chicken)' searches for records containing both
     "fruit" and at least one of "fish" or "chicken".

   * `rock or su=mineral' searches for records either containing "rock" or
     "mineral", but with the "mineral" search term modified by the
     qualifier "su" (typically interpreted to mean that the search term
     must occur in the "subject" field of the record.)

   For CCL searches sent directly to the server (query type `ccl'), the
exact interpretation of the qualifiers is the server's responsibility.
For searches compiled on the client side (query side `ccl2rpn') the
interpretation of the qualifiers in terms of type-1 attributes is
determined by the contents of a file called *### not yet implemented*.
The format of this file is described in the Yaz documentation.

   *Setting Search Defaults*

   As an alternative to explicitly specifying the query type when invoking
the search() method, you can change the connection's default query type
using its option() method:

     $conn->option(querytype => 'prefix');
     $conn->option(querytype => 'ccl');
     $conn->option(querytype => 'ccl2rpn');

   The connection's current default query type can be retrieved using
option() with no "value" argument:

     $qt = $conn->option('querytype');

   The option() method can be used to set and get numerous other defaults
described in this document and elsewhere; this method exists not only on
connections but also on managers (q.v.) and result sets.

   Another important option is `databaseName', whose value specifies which
database is to be searched.

Retrieval
---------

   *Element Set*

   The default element set is "b" (brief).  To change this, set the result
set's `elementSetName' option:

     $rs->option(elementSetName => "f");

   *Record Syntax*

   The default record syntax preferred by the `Net::Z3950' module is GRS-1
(the One True Record syntax).  If, however, you need to ask the server for
a record using a different record syntax, then the way to do this is to
set the `preferredRecordSyntax' option of the result set from which the
record is to be fetched:

     $rs->option(preferredRecordSyntax =>
                 Net::Z3950::RecordSyntax::SUTRS);

   The record syntaxes which may be requested are listed in the
`Net::Z3950::RecordSyntax' enumeration in the file `Net/Z3950.pm'; they
include `Net::Z3950::RecordSyntax::GRS1', `Net::Z3950::RecordSyntax::SUTRS'
and `Net::Z3950::RecordSyntax::USMARC'.

   (As always, option() may also be invoked with no "value" parameter to
return the current value of the option.)

WHAT TO DO WITH YOUR RECORDS
============================

   Once you've retrieved a record, what can you do with it?

   There are two broad approaches.  One is just to display it to the user:
this can always be done with the render() method, as used in the sample
code above, whatever the record syntax of the record.

   The more sophisticated approach is to perform appropriate analysis and
manipulation of the raw record according to the record syntax.  The raw
data is retrieved using the rawdata() method, and the record syntax can be
determined using the universal isa() method:

     $raw = $rec->rawdata();
     if ($rec->isa('Net::Z3950::Record::GRS1')) {
     	process_grs1_record($raw);
     elsif ($rec->isa('Net::Z3950::Record::USMARC')) {
     	process_marc_record($raw);
     } # etc.

   For further manipulation of MARC records, we recommend the existing
MARC module in Ed Summers's directory at CPAN,
http://cpan.valueclick.com/authors/id/E/ES/ESUMMERS/

   The raw data of GRS-1 records in the `Net::Z3950' module closely
follows the structure of physcial GRS-1 records - see Appendices REC.5
(*Generic Record Syntax 1*), TAG (*TagSet Definitions and Schemas*) and
RET (*Z39.50 Retrieval*) of the standard more details.

   The raw GRS-1 data is intended to be more or less self-describing, but
here is a summary.

   * The raw data is a reference to an array of elements, each representing
     one of the fields of the record.

   * Each element is a `Net::Z3950::APDU::TaggedElement' object.  These
     objects support the accessor methods `tagType()', `tagValue()',
     `tagOccurrence()' and `content()'; the first three of these return
     numeric values, or strings in the less common case of string
     tag-values.

   * The content of an element is an object of one of the subtypes of
     `Net::Z3950::ElementData'.  These include
     `Net::Z3950::ElementData::Numeric' and
     `Net::Z3950::ElementData::String' (both self-explanatory), and
     `Net::Z3950::ElementData::OID' (a reference to an array of integers).
     The fourth, and more interesting content-type is
     `Net::Z3950::ElementData::Subtree' - a reference to another whole
     Net::Z3950::Record::GRS1, enabling arbitrary recursive nesting.

   In the future, we plan to take you away from all this by introducing a
`Net::Z3950::Data' module which provides a DOM-like interface for walking
hierarchically structured records independently of their record syntax.
Keep watchin', kids!

CHANGING SESSION PARAMETERS
===========================

   As with customising searching or retrieval behaviour, whole-session
behaviour is customised by setting options.  However, this needs to be
done before the session is created, because the Z39.50 protocol doesn't
provide a method for changing (for example) the preferred message size of
an existing connection.

   In the `Net::Z3950' module, this is done by creating a manager - a
controller for one or more connections.  Then the manager's options can be
set; then connections which are opened through the manager use the
specified values for those options.

   As a matter of fact, every connection is made through a manager.  If
one is not specified in the connection constructor, then the "default
manager" is used; it's automatically created the first time it's needed,
then re-used for any other connections that need it.

Make or Find a Manager
----------------------

   A new manager is created as follows:

     $mgr = new Net::Z3950::Manager();

   Once the manager exists, a new connection can be made through it by
specifying the manager reference as the first option to the connection
constructor:

     $conn = new Net::Z3950::Connection($mgr, 'indexdata.dk', 210);

   Or equivalently,

     $conn = $mgr->connect('indexdata.dk', 210);

   In order to retrieve the manager through which a connection was made,
whether it was the implicit default manager or not, use the manager()
method:

     $mgr = $conn->manager();

Set the Parameters
------------------

   There are two ways to set parameters.  One we have already seen: the
option() method can be used to get and set option values for managers just
as it can for connections and result sets:

     $pms = $mgr->option('preferredMessageSize');
     $mgr->option(preferredMessageSize => $pms*2);

   Alternatively, options may be passed to the manager constructor when
the manager is first created:

     $mgr = new Net::Z3950::Manager(
     	preferredMessageSize => 100*1024,
     	maximumRecordSize => 10*1024*1024,
     	preferredRecordSyntax => Net::Z3950::RecordSyntax::GRS1);

   This is *exactly* equivalent to creating a "vanilla" manager with `new
Net::Z3950::Manager()', then setting the three options with the option()
method.

   *Message Size Parameters*

   The `preferredMessageSize' and `maximumRecordSize' parameters can be
used to specify values of the corresponding parameters which are proposed
to the server at initialisation time (although the server is not bound to
honour them.)  See sections 3.2.1.1.4 (*Preferred-message-size and
Exceptional-message-size*) and 3.3 (*Message/Record Size and
Segmentation*) of the Z39.50 standard itself for details.

   Both options default to one megabyte.

   *Implementation Identification*

   The `implementationId', `implementationName' and
`implementationVersion' options can be used to control the corresponding
parameters in initialisation request sent to the server to identify the
client.  The default values are listed below in the section OPTION
INHERITANCE.

   Authentication

   The user, password and `groupid' options can be specified for a manager
so that they are passed as identification tokens at initialisation time to
any connections opened through that manager.  The three options are
interpreted as follows:

   * If user is not specified, then authentication is omitted (which is
     more or less the same as "anonymous" authentication).

   * If user is specified but not password, then the value of the user
     option is passed as an "open" authentication token.

   * If both user and password are specified, then their values are passed
     in an "idPass" authentication structure, together with the value of
     group if is it specified.

   By default, all three options are undefined, so no authentication is
used.

OPTION INHERITANCE
==================

   The values of options are inherited from managers to connections,
result sets and finally to records.

   This means that when a record is asked for an option value (whether by
an application invoking its option() method, or by code inside the module
that needs to know how to behave), that value is looked for first in the
record's own table of options; then, if it's not specified there, in the
options of the result set from which the record was retrieved; then if
it's not specified there, in those of the connection across which the
result set was found; and finally, if not specified there either, in the
options for the manager through which the connection was created.

   Similarly, option values requested from a result set are looked up (if
not specified in the result set itself) in the connection, then the
manager; and values requested from a connection fall back to its manager.

   This is why it made sense in an earlier example (see the section *Set
the Parameters*) to specify a value for the `preferredRecordSyntax' option
when creating a manager: the result of this is that, unless overridden, it
will be the preferred record syntax when any record is retrieved from any
result set retrieved from any connection created through that manager.  In
effect, it establishes a global default.  Alternatively, one might specify
different defaults on two different connections.

   In all cases, if the manager doesn't have a value for the requested
option, then a hard-wired default is used.  The defaults are as follows.
(Please excuse the execrable formatting - that's what pod2html does, and
there's no sensible way around it.)

mode
     `'sync'' (Determines whether a given connection is in synchronous or
     asynchronous mode.)

`preferredMessageSize'
     `1024*1024'

`maximumRecordSize'
     `1024*1024'

user
     undef

password
     undef

`groupid'
     undef

`implementationId'
     `'Mike Taylor (id=169)''

`implementationName'
     `'Net::Z3950.pm (Perl)''

`implementationVersion'
     `$Net::Z3950::VERSION'

`querytype'
     `'prefix''

`databaseName'
     `'Default''

`smallSetUpperBound'
     0 (This and the next four options provide flexible control for
     run-time details such as what record syntax to use when returning
     records.  See sections 3.2.2.1.4 (*Small-set-element-set-names and
     Medium-set-element-set-names*) and 3.2.2.1.6 (*Small-set-upper-bound,
     Large-set-lower-bound, and Medium-set-present-number*) of the Z39.50
     standard itself for details.)

`largeSetLowerBound'
     1

`mediumSetPresentNumber'
     0

`smallSetElementSetName'
     'f'

`mediumSetElementSetName'
     'b'

`preferredRecordSyntax'
     `Net::Z3950::RecordSyntax::GRS1'

`elementSetName'
     'b'

   Any other option's value is undefined.

ASYNCHRONOUS MODE
=================

   I don't propose to discuss this at the moment, since I think it's more
important to get the Tutorial out there with the synchronous stuff in
place than to write the asynchronous stuff.  I'll do it soon, honest.

   *### Note to self - write this section!*

NOW WHAT?
=========

   This tutorial is only an overview of what can be done with the
`Net::Z3950' module.  If you need more information that it provides, then
you need to read the more technical documentation on the individual
classes that make up the module - `Net::Z3950' itself,
`Net::Z3950::Manager', `Net::Z3950::Connection', `Net::Z3950::ResultSet'
and `Net::Z3950::Record'.

AUTHOR
======

   Mike Taylor <mike@tecc.co.uk>

   First version Sunday 28th January 2001.

by-name interface to Perl's built-in gethost*() functions
*********************************************************

NAME
====

   Net::hostent - by-name interface to Perl's built-in gethost*() functions

SYNOPSIS
========

     use Net::hostnet;

DESCRIPTION
===========

   This module's default exports override the core gethostbyname() and
gethostbyaddr() functions, replacing them with versions that return
"Net::hostent" objects.  This object has methods that return the similarly
named structure field name from the C's hostent structure from `netdb.h';
namely name, aliases, addrtype, length, and addr_list.  The aliases and
addr_list methods return array reference, the rest scalars.  The addr
method is equivalent to the zeroth element in the addr_list array
reference.

   You may also import all the structure fields directly into your
namespace as regular variables using the :FIELDS import tag.  (Note that
this still overrides your core functions.)  Access these fields as
variables named with a preceding `h_'.  Thus, `$host_obj->name()'
corresponds to $h_name if you import the fields.  Array references are
available as regular array variables, so for example `@{
$host_obj->aliases() }' would be simply @h_aliases.

   The gethost() function is a simple front-end that forwards a numeric
argument to gethostbyaddr() by way of Socket::inet_aton, and the rest to
gethostbyname().

   To access this functionality without the core overrides, pass the use
an empty import list, and then access function functions with their full
qualified names.  On the other hand, the built-ins are still available via
the `CORE::' pseudo-package.

EXAMPLES
========

     use Net::hostent;
     use Socket;

     @ARGV = ('netscape.com') unless @ARGV;

     for $host ( @ARGV ) {

     unless ($h = gethost($host)) {
     	warn "$0: no such host: $host\n";
     	next;
     }

     printf "\n%s is %s%s\n",
     	    $host,
     	    lc($h->name) eq lc($host) ? "" : "*really* ",
     	    $h->name;

     print "\taliases are ", join(", ", @{$h->aliases}), "\n"
     		if @{$h->aliases};

     if ( @{$h->addr_list} > 1 ) {
     	my $i;
     	for $addr ( @{$h->addr_list} ) {
     	    printf "\taddr #%d is [%s]\n", $i++, inet_ntoa($addr);
     	}
     } else {
     	printf "\taddress is [%s]\n", inet_ntoa($h->addr);
     }

     if ($h = gethostbyaddr($h->addr)) {
     	if (lc($h->name) ne lc($host)) {
     	    printf "\tThat addr reverses to host %s!\n", $h->name;
     	    $host = $h->name;
     	    redo;
     	}
     }
      }

NOTE
====

   While this class is currently implemented using the Class::Struct
module to build a struct-like class, you shouldn't rely upon this.

AUTHOR
======

   Tom Christiansen

libnet Frequently Asked Questions
*********************************

NAME
====

   libnetFAQ - libnet Frequently Asked Questions

DESCRIPTION
===========

Where to get this document
--------------------------

   This document is distributed with the libnet disribution, and is also
avaliable on the libnet web page at

     http://www.pobox.com/~gbarr/libnet/

How to contribute to this document
----------------------------------

   You may mail corrections, additions, and suggestions to me
gbarr@pobox.com.

Author and Copyright Information
================================

   Copyright (c) 1997-1998 Graham Barr. All rights reserved.  This
document is free; you can redistribute it and/or modify it under the terms
of the Artistic Licence.

Disclaimer
----------

   This information is offered in good faith and in the hope that it may
be of use, but is not guaranteed to be correct, up to date, or suitable
for any particular purpose whatsoever.  The authors accept no liability in
respect of this information or its use.

Obtaining and installing libnet
===============================

What is libnet ?
----------------

   libnet is a collection of perl5 modules which all related to network
programming. The majority of the modules avaliable provided the client
side of popular server-client protocols that are used in the internet
community.

Which version of perl do I need ?
---------------------------------

   libnet has been know to work with versions of perl from 5.002 onwards.
However if your release of perl is prior to perl5.004 then you will need to
obtain and install the IO distribution from CPAN. If you have perl5.004 or
later then you will have the IO modules in your installation already, but
CPAN may contain updates.

What other modules do I need ?
------------------------------

   The only modules you will need installed are the modules from the IO
distribution. If you have perl5.004 or later you will already have these
modules.

What machines support libnet ?
------------------------------

   libnet itself is an entirly perl-code distribution so it should work on
any machine that perl runs on. However IO may not work with some machines
and earlier releases of perl. But this should not be the case with perl
version 5.004 or later.

Where can I get the latest libnet release
-----------------------------------------

   The latest libnet release is always on CPAN, you will find it in

     http://www.perl.com/CPAN/modules/by-module/Net/

     The latest release and information is also avaliable on the libnet web page
     at

     http://www.pobox.com/~gbarr/libnet/

Using Net::FTP
==============

How do I download files from a FTP server ?
-------------------------------------------

   An example taken from an article posted to comp.lang.perl.misc

     #!/your/path/to/perl

     # a module making life easier

     use Net::FTP;

     # for debuging: $ftp = Net::FTP->new('site','Debug',10);
     # open a connection and log in!

     $ftp = Net::FTP->new('target_site.somewhere.xxx');
     $ftp->login('username','password');

     # set transfer mode to binary

     $ftp->binary();

     # change the directory on the ftp site

     $ftp->cwd('/some/path/to/somewhere/');

     foreach $name ('file1', 'file2', 'file3') {

     # get's arguments are in the following order:
     # ftp server's filename
     # filename to save the transfer to on the local machine
     # can be simply used as get($name) if you want the same name

     $ftp->get($name,$name);
         }

     # ftp done!

     $ftp->quit;

How do I transfer files in binary mode ?
----------------------------------------

   To transfer files without <LF><CR> translation Net::FTP provides the
binary method

     $ftp->binary;

How can I get the size of a file on a remote FTP server ?
---------------------------------------------------------

How can I get the modification time of a file on a remote FTP server ?
----------------------------------------------------------------------

How can I change the permissions of a file on a remote server ?
---------------------------------------------------------------

   The FTP protocol does not have a command for changing the permissions
of a file on the remote server. But some ftp servers may allow a chmod
command to be issued via a SITE command, eg

     $ftp->quot('site chmod 0777',$filename);

   But this is not guaranteed to work.

Can I do a reget operation like the ftp command ?
-------------------------------------------------

How do I get a directory listing from a FTP server ?
----------------------------------------------------

Changeing directory to "" does not fail ?
-----------------------------------------

   Passing an argument of "" to ->cwd() has the same affect of calling
->cwd() without any arguments. Turn on Debug (*See below*) and you will
see what is happening

     $ftp = Net::FTP->new($host, Debug => 1);
     $ftp->login;
     $ftp->cwd("");

   gives

     Net::FTP=GLOB(0x82196d8)>>> CWD /
     Net::FTP=GLOB(0x82196d8)<<< 250 CWD command successful.

I am behind a SOCKS firewall, but the Firewall option does not work ?
---------------------------------------------------------------------

   The Firewall option is only for support of one type of firewall. The
type supported is a ftp proxy.

   To use Net::FTP, or any other module in the libnet distribution,
through a SOCKS firewall you must create a socks-ified perl executable by
compiling perl with the socks library.

I am behind a FTP proxy firewall, but cannot access machines outside ?
----------------------------------------------------------------------

   Net::FTP implements the most popular ftp proxy firewall approach. The
sceme implemented is that where you loginin to the firewall with
`user@hostname'

   I have heard of one other type of firewall which requires a login to the
firewall with an accont, then a second login with `user@hostname'. You can
still use Net::FTP to traverse these firewalls, but a more manual approach
must be taken, eg

     $ftp = Net::FTP->new($firewall) or die $@;
     $ftp->login($firewall_user, $firewall_passwd) or die $ftp->message;
     $ftp->login($ext_user . '@' . $ext_host, $ext_passwd) or die $ftp->message.

My ftp proxy firewall does not listen on port 21
------------------------------------------------

   FTP servers usually listen on the same port number, port 21, as any
other FTP server. But there is no reason why thi has to be the case.

   If you pass a port number to Net::FTP then it assumes this is the port
number of the final destination. By default Net::FTP will always try to
connect to the firewall on port 21.

   Net::FTP uses IO::Socket to open the connection and IO::Socket allows
the port number to be specified as part of the hostname. So this problem
can be resolved by either passing a Firewall option like `"hostname:1234"'
or by setting the ftp_firewall option in Net::Config to be a string in in
the same form.

Is it possible to change the file permissions of a file on an FTP server ?
--------------------------------------------------------------------------

   The answer to this is "maybe". The FTP protocol does not specify a
command to change file permissions on a remote host. However many servers
do allow you to run the chmod command via the SITE command. This can be
done with

     $ftp->site('chmod','0775',$file);

I have seen scripts call a method message, but cannot find it documented ?
--------------------------------------------------------------------------

   Net::FTP, like several other packages in libnet, inherits from
Net::Cmd, so all the methods described in Net::Cmd are also avaliable on
Net::FTP objects.

Why does Net::FTP not implement mput and mget methods
-----------------------------------------------------

   The quick answer is because they are easy to implement yourself. The
long answer is that to write these in such a way that multiple platforms
are supported correctly would just require too much code. Below are some
examples how you can implement these yourself.

   sub mput {   my($ftp,$pattern) = @_;   foreach my $file (<$pattern>) {
  $ftp->put($file) or warn $ftp->message;   } }

   sub mget {   my($ftp,$pattern) = @_;   foreach my $file
($ftp->ls($pattern)) {     $ftp->get($file) or warn $ftp->message;   } }

Using Net::SMTP
===============

Why can't the part of an Email address after the @ be used as the hostname ?
----------------------------------------------------------------------------

   The part of an Email address which follows the @ is not necessarily a
hostname, it is a mail domain. To find the name of a host to connect for a
mail domain you need to do a DNS MX lookup

Why does Net::SMTP not do DNS MX lookups ?
------------------------------------------

   Net::SMTP implements the SMTP protocol. The DNS MX lookup is not part
of this protocol.

The verify method always returns true ?
---------------------------------------

   Well it may seem thay way, but it does not. The verify method returns
true if the command suceeded. If you pass verify an address which the
server would normally have to forward to another machine the the command
will suceed with something like

     252 Couldn't verify <someone@there> but will attempt delivery anyway

   This command will only fail if you pass it an address in a domain the
the server directly delivers for, and that address does not exist.

Debugging scripts
=================

How can I debug my scripts that use Net::* modules ?
----------------------------------------------------

   Most of the libnet client classes allow options to be passed to the
constructor, in most cases one option is called Debug. Passing this option
with a non-zero value will turn on a protocol trace, which will be sent to
STDERR. This trace can be useful to see what commands are being sent to
the remote server and what responces are being received back.

     #!/your/path/to/perl

     use Net::FTP;

     my $ftp = new Net::FTP($host, Debug => 1);
     $ftp->login('gbarr','password');
     $ftp->quit;

   this script would output something like

     Net::FTP: Net::FTP(2.22)
     Net::FTP:   Exporter
     Net::FTP:   Net::Cmd(2.0801)
     Net::FTP:   IO::Socket::INET
     Net::FTP:     IO::Socket(1.1603)
     Net::FTP:       IO::Handle(1.1504)

     Net::FTP=GLOB(0x8152974)<<< 220 imagine FTP server (Version wu-2.4(5) Tue Jul 29 11:17:18 CDT 1997) ready.
     Net::FTP=GLOB(0x8152974)>>> user gbarr
     Net::FTP=GLOB(0x8152974)<<< 331 Password required for gbarr.
     Net::FTP=GLOB(0x8152974)>>> PASS ....
     Net::FTP=GLOB(0x8152974)<<< 230 User gbarr logged in.  Access restrictions apply.
     Net::FTP=GLOB(0x8152974)>>> QUIT
     Net::FTP=GLOB(0x8152974)<<< 221 Goodbye.

   The first few lines tell you the modules that Net::FTP uses and thier
versions, this is usefule data to me when a user reports a bug. The last
seven lines show the communication with the server. Each line has three
parts. The first part is the object itself, this is useful for separating
the output if you are using mutiple objects. The second part is either
`<<<<' to show data coming from the server or `&gt&gt&gt&gt' to show data
going to the server. The remainder of the line is the command being sent
or responce being received.

AUTHOR AND COPYRIGHT
====================

   Copyright (c) 1997 Graham Barr.  All rights reserved.

by-name interface to Perl's built-in getnet*() functions
********************************************************

NAME
====

   Net::netent - by-name interface to Perl's built-in getnet*() functions

SYNOPSIS
========

     use Net::netent qw(:FIELDS);
     getnetbyname("loopback") 		or die "bad net";
     printf "%s is %08X\n", $n_name, $n_net;

     use Net::netent;

     $n = getnetbyname("loopback") 		or die "bad net";
     { # there's gotta be a better way, eh?
         @bytes = unpack("C4", pack("N", $n->net));
         shift @bytes while @bytes && $bytes[0] == 0;
     }
     printf "%s is %08X [%d.%d.%d.%d]\n", $n->name, $n->net, @bytes;

DESCRIPTION
===========

   This module's default exports override the core getnetbyname() and
getnetbyaddr() functions, replacing them with versions that return
"Net::netent" objects.  This object has methods that return the similarly
named structure field name from the C's netent structure from `netdb.h';
namely name, aliases, addrtype, and net.  The aliases method returns an
array reference, the rest scalars.

   You may also import all the structure fields directly into your
namespace as regular variables using the :FIELDS import tag.  (Note that
this still overrides your core functions.)  Access these fields as
variables named with a preceding `n_'.  Thus, `$net_obj->name()'
corresponds to $n_name if you import the fields.  Array references are
available as regular array variables, so for example `@{
$net_obj->aliases() }' would be simply @n_aliases.

   The getnet() function is a simple front-end that forwards a numeric
argument to getnetbyaddr(), and the rest to getnetbyname().

   To access this functionality without the core overrides, pass the use
an empty import list, and then access function functions with their full
qualified names.  On the other hand, the built-ins are still available via
the `CORE::' pseudo-package.

EXAMPLES
========

   The getnet() functions do this in the Perl core:

     sv_setiv(sv, (I32)nent->n_net);

   The gethost() functions do this in the Perl core:

     sv_setpvn(sv, hent->h_addr, len);

   That means that the address comes back in binary for the host
functions, and as a regular perl integer for the net ones.  This seems a
bug, but here's how to deal with it:

     use strict;
     use Socket;
     use Net::netent;

     @ARGV = ('loopback') unless @ARGV;

     my($n, $net);

     for $net ( @ARGV ) {

     unless ($n = getnetbyname($net)) {
      	warn "$0: no such net: $net\n";
      	next;
     }

     printf "\n%s is %s%s\n",
      	    $net,
      	    lc($n->name) eq lc($net) ? "" : "*really* ",
      	    $n->name;

     print "\taliases are ", join(", ", @{$n->aliases}), "\n"
      		if @{$n->aliases};

     # this is stupid; first, why is this not in binary?
     # second, why am i going through these convolutions
     # to make it looks right
     {
      	my @a = unpack("C4", pack("N", $n->net));
      	shift @a while @a && $a[0] == 0;
      	printf "\taddr is %s [%d.%d.%d.%d]\n", $n->net, @a;
     }

     if ($n = getnetbyaddr($n->net)) {
      	if (lc($n->name) ne lc($net)) {
      	    printf "\tThat addr reverses to net %s!\n", $n->name;
      	    $net = $n->name;
      	    redo;
      	}
     }
      }

NOTE
====

   While this class is currently implemented using the Class::Struct
module to build a struct-like class, you shouldn't rely upon this.

AUTHOR
======

   Tom Christiansen

by-name interface to Perl's built-in getproto*() functions
**********************************************************

NAME
====

   Net::protoent - by-name interface to Perl's built-in getproto*()
functions

SYNOPSIS
========

     use Net::protoent;
     $p = getprotobyname(shift || 'tcp') || die "no proto";
     printf "proto for %s is %d, aliases are %s\n",
        $p->name, $p->proto, "@{$p->aliases}";

     use Net::protoent qw(:FIELDS);
     getprotobyname(shift || 'tcp') || die "no proto";
     print "proto for $p_name is $p_proto, aliases are @p_aliases\n";

DESCRIPTION
===========

   This module's default exports override the core getprotoent(),
getprotobyname(), and getnetbyport() functions, replacing them with
versions that return "Net::protoent" objects.  They take default second
arguments of "tcp".  This object has methods that return the similarly
named structure field name from the C's protoent structure from `netdb.h';
namely name, aliases, and proto.  The aliases method returns an array
reference, the rest scalars.

   You may also import all the structure fields directly into your
namespace as regular variables using the :FIELDS import tag.  (Note that
this still overrides your core functions.)  Access these fields as
variables named with a preceding `p_'.  Thus, `$proto_obj->name()'
corresponds to $p_name if you import the fields.  Array references are
available as regular array variables, so for example `@{
$proto_obj->aliases() }' would be simply @p_aliases.

   The getproto() function is a simple front-end that forwards a numeric
argument to getprotobyport(), and the rest to getprotobyname().

   To access this functionality without the core overrides, pass the use
an empty import list, and then access function functions with their full
qualified names.  On the other hand, the built-ins are still available via
the `CORE::' pseudo-package.

NOTE
====

   While this class is currently implemented using the Class::Struct
module to build a struct-like class, you shouldn't rely upon this.

AUTHOR
======

   Tom Christiansen

by-name interface to Perl's built-in getserv*() functions
*********************************************************

NAME
====

   Net::servent - by-name interface to Perl's built-in getserv*() functions

SYNOPSIS
========

     use Net::servent;
     $s = getservbyname(shift || 'ftp') || die "no service";
     printf "port for %s is %s, aliases are %s\n",
        $s->name, $s->port, "@{$s->aliases}";

     use Net::servent qw(:FIELDS);
     getservbyname(shift || 'ftp') || die "no service";
     print "port for $s_name is $s_port, aliases are @s_aliases\n";

DESCRIPTION
===========

   This module's default exports override the core getservent(),
getservbyname(), and getnetbyport() functions, replacing them with
versions that return "Net::servent" objects.  They take default second
arguments of "tcp".  This object has methods that return the similarly
named structure field name from the C's servent structure from `netdb.h';
namely name, aliases, port, and proto.  The aliases method returns an
array reference, the rest scalars.

   You may also import all the structure fields directly into your
namespace as regular variables using the :FIELDS import tag.  (Note that
this still overrides your core functions.)  Access these fields as
variables named with a preceding `n_'.  Thus, `$serv_obj->name()'
corresponds to $s_name if you import the fields.  Array references are
available as regular array variables, so for example `@{
$serv_obj->aliases() }' would be simply @s_aliases.

   The getserv() function is a simple front-end that forwards a numeric
argument to getservbyport(), and the rest to getservbyname().

   To access this functionality without the core overrides, pass the use
an empty import list, and then access function functions with their full
qualified names.  On the other hand, the built-ins are still available via
the `CORE::' pseudo-package.

EXAMPLES
========

     use Net::servent qw(:FIELDS);

     while (@ARGV) {
         my ($service, $proto) = ((split m!/!, shift), 'tcp');
         my $valet = getserv($service, $proto);
         unless ($valet) {
             warn "$0: No service: $service/$proto\n"
             next;
         }
         printf "service $service/$proto is port %d\n", $valet->port;
         print "alias are @s_aliases\n" if @s_aliases;
     }

NOTE
====

   While this class is currently implemented using the Class::Struct
module to build a struct-like class, you shouldn't rely upon this.

AUTHOR
======

   Tom Christiansen

A base class for protocols such as IMAP, ACAP, IMSP, and ICAP.
**************************************************************

NAME
====

   Net::xAP - A base class for protocols such as IMAP, ACAP, IMSP, and
ICAP.

SYNOPSIS
========

   `use Net::xAP;'

   *WARNING: This code is in alpha release.  Expect the interface to
change from release to release.*

DESCRIPTION
===========

   This base class implements the substrate common across the IMAP, ACAP,
IMSP, and ICAP protocols.  It provides the interface to the network calls
and implements a small amount of glue to assist in implementing interfaces
to this protocol family.

END-PROGRAMMER METHODS
======================

   The following methods are potentially useful for end-programmers.

last_command_time
-----------------

   Return what time the most recent command was sent to the server.  The
return value is a time integer.

connection
----------

   Returns the connection object being used by the object.

PROTOCOL-DEVELOPER METHODS
==========================

   The following methods are probably only useful to protocol developers.

new $host, $peerport [, %options]
---------------------------------

   Create a new instance of Net::xAP, connects to $host, and returns a
reference to the object.

   The $host parameter is the name of the host to contact.  If $host
starts with a / character, the parameter is assumed to contain the name of
a program and the given program is spawned as a child process.  This is
useful for driving programs that can be operated interactively from the
command-line, such as UW-imapd.

   The `$peerport' parameter specifies the TCP port used for the network
connection. The parameter should be in the syntax understood by
`IO::Socket::INET->new'.  This parameter is ignored if a child process is
spawned.

   The %options parameter specifies any options to use.  The following
list enumerates the options, and their default values, currently
understood by `Net::xAP':

`Synchronous => 1'
     Setting this option causes `Net::xAP' to issue a response method
     immediately after sending the command to the server.  Currently, this
     option should always be left on.  Non-synchronous command/response
     processing has not been tested.

     One down-side to Synchronous mode is that commands cannot be sent to
     the server from within a callback.  Instead, the results should be
     saved, and the commands should be sent after the current command has
     completed.

`NonSyncLits => 0'
     Setting this option causes `Net::xAP' to use non-synchronizing
     literals.  This should only be enabled if the protocol and server this
     feature.

`Debug => 0'
     Setting this option causes debug output to be written to stderr.  See
     the debug_print method for a description of the output format.

`InternetDraft => 0'
     Setting this option adds support for various extensions that are still
     in Internet Draft.  This option is only intended to be used by
     protocol developers.  Most bug reports related to this feature will be
     ignored.

   All options are also passed to the internal call to
`IO::Socket::INET->new', unless a child IMAP process is spawned.

command $callback, $command [, @args]
-------------------------------------

   The command is used to send commands to the server.

   The `$callback' parameter should be a reference to a subroutine. It
will be called when a response is received from the server.

   `@args' is a list of $type-$value pairs.  The $type indicates what type
of data type to use for $value.  This is used to control the encoding
necessary to pass the command arguments to the server.

   The following $types are understood:

`ATOM'
     The data will sent raw to the server.

`ASTRING'
     The data will be sent to the server as an atom, a quoted string, or a
     literal depending on the content of $value.

`PARENS'
     The data in $value will be interpreted as an array reference and be
     sent inside a pair of parentheses.

STRING
     The data will be sent to the server as either a quoted string or
     literal depending on the content of $value.

`QSTRING'
     The data will be sent to the server as a quoted string.

   If the `Synchronous' option is set this method will return a response
object, otherwise it will return the sequence number associated with the
command just sent to the server.

parse_fields $str
-----------------

   Splits the specified $str into fields.  A list reference is returned
contain the individual fields.  Parenthetical clauses are represented as
nested list references of arbitrary depth.  Quoted strings are stripped of
their surrounding quotes and escaped \\ and `\"' characters are unescaped.

response
--------

   Reads response lines from the server until one of the lines is a
completion response.  For each response, the appropriate callbacks are
triggered.  This is automatically called if the `Synchronous' option is on.

getline
-------

   Get one 'line' of data from the server, including any literal payloads.

close_connection
----------------

   Closes the connection to the server, returning the results of the
operation.

sequence
--------

   Returns the sequence number of the last command issued to the server.

next_sequence
-------------

   Returns the sequence number that will be assigned to the next command
issued.

pending
-------

   Returns a list of sequence numbers for the commands that are still
awaiting a complete response from the server.

   The list is sorted numerically.

debug [$boolean]
----------------

   Returns the value of the debug option for the object.

   If $boolean is specified, the debug state is set to the given value.

debug_print $direction, $text
-----------------------------

   Prints $text to `STDERR', preceded by an indication of traffic
direction, the object reference, and a timestamp. The parameter $direction
is used to indicate the direction of the traffic related to the debug
call.  Use 0 for data being sent to the server, or 1 for data coming from
the server.

debug_text $text
----------------

   A stub method intended to be overridden by subclasses.  It provides
subclasses with the ability to make alterations to $text before being
output by debug_print method.  The base class version does no alteration
of $text.

RESPONSE OBJECTS
================

   A response object is the data type returned by the response method.  A
few convenience routines are provided at the Net::xAP level that are
likely to be common across several protocols.

new
---

   Creates a new response object.

tag
---

   Returns the tag associated with the response object.

status
------

   Returns the command status associated with the response object.  This
will be OK, `NO', or BAD.

text
----

   Returns the human readable text assocated with the status of the
response object.

   This will typically be overridden by a subclass of the `xAP' class to
handle things like status codes.

status_code
-----------

   Returns a list reference containing the response code portion of the
server response.

CAVEATS
=======

   With only a few exceptions, the methods provided in this class are
intended for use by developers adding support for additional protocols.
Don't muck with this level, unless you know what you're doing.

AUTHOR
======

   Kevin Johnson <`kjj@pobox.com'>

COPYRIGHT
=========

   Copyright (c) 1997-1999 Kevin Johnson <kjj@pobox.com>.

   All rights reserved. This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

Manipulate IP Addresses easily
******************************

NAME
====

   NetAddr::IP - Manipulate IP Addresses easily

SYNOPSIS
========

     use NetAddr::IP qw($Use_CIDR_Notation $Always_Display_Mask);

     # Initialization of NetAddr::IP objects
     my $ip = new NetAddr::IP "10.0.0.1";
     my $subnet = new NetAddr::IP("10.0.0.0", "255.255.255.0");
     my $othersubnet = new NetAddr::IP("10.0.0.0", "24");
     my $yetanothersubnet = new NetAddr::IP "10.0.0.0/24";
     my $serialsubnet = new NetAddr::IP($min, $max, $bits);

     # A proper subnet (or undef if any host but is set)
     my $subnet_ok = new_subnet NetAddr::IP("10.0.0.0", "24");
     my $subnet_undef = new_subnet NetAddr::IP("10.0.0.1", "24");

     # A numeric representation of a subnet/host address
     my $address = $ip->to_numeric();
     my ($min, $max, $bits) = $ip->to_numeric();

     # A string representation of an address or subnet
     print "My ip address is ", $ip->to_string, "\n";

     # Just the string or the mask part...
     print "My ip address alone is ", $ip->addr_to_string, "\n";
     print "and my netmask is ", $ip->mask_to_string, "\n";

     # Enumeration of all the addresses within a given subnet, keeping
     # the original mask
     my @hosts = $subnet->enum;
     for $i (@hosts) {
         print "address ", $i->to_string,
         " belongs to subnet ", $subnet->to_string, "\n";
     }

     # You can also produce the list of host addresses in a given subnet
     my @hosts = $subnet->host_enum;
     for $i (@hosts) {
         print "Host ", $i->to_string,
         " is in subnet ", $subnet->to_string, "\n";
     }

     # This calculates network and broadcast addresses for a subnet
     my $network = $subnet->network;
     my $broadcast = $subnet->broadcast;
     print "Subnet ", $subnet->to_string, " has broadcast address ",
       $broadcast->to_string, " and network number ", $network->to_string,
       "\n";

     # Checks to see if a host address or subnet is contained within another
     # subnet
     if ($subnet->contains $ip) {
         print "Host ", $ip->to_string, " is contained in ",
         $subnet->to_string, "\n";
     }

     # Masks and address components can be copied from object to object
     $ip1->set_addr($ip2);
     $ip1->set_mask($subnet);

     # Ammount of hosts in a subnet can also be easily calculated
     $max_hosts_in_subnet = $subnet->how_many - 2;

     # A range of IP Addresses
     @range = $ip->range($final_ip); # From $ip to $final_ip
     @range = $ip->range(@dont_know_which_is_larger);
     				# From the smallest on the list + $ip to
     				# the largest

     # Usable addresses in a subnet
     $first_address = $subnet->first;
     $last_address = $subnet->last;

     # Compact subnets or addresses into the largest possible CIDR block
     @compact_block = NetAddr::IP::compact(@many_small_ip_address_blocks);

     # Split a set of blocks into smaller subnets
     @small_subnets = NetAddr::IP::expand(@ip_address_blocks);

     # Obtain a numeric representation of an IP address
     my $number = $ip->addr_number;

     # How many bits are there in the mask?
     my $masklen = $ip->mask_bits;

DESCRIPTION
===========

   This module provides a simple interface to the tedious bit manipulation
involved when handling IP address calculations. It also helps by performing
range comparisons between subnets as well as other frequently used
functions.

   Most of the primitive functions return a NetAddr::IP object.

   The variables *$Use_CIDR_Notation*  and *$Always_Display_Mask*  affect
how the ->to_string function will present its result. The names are
hopefully intuitive enough. Note that IP addresses are not properly
compacted (ie, 200.44.0/18 is written as 200.44.0.0/18) because this
adapts to the widely adopted but incorrect notation. Perhaps a later
version will include a variable to change this.

   This code has not been widely tested yet. Endianness problems might very
well exist. Please email the author if such problems are found.

   This software is (c) Luis E. Munoz. It can be used under the terms of
the perl artistic license provided that proper credit is preserved and that
the original documentation is not removed.

   This software comes with the same warranty as perl itself (ie, none), so
by using it you accept any and all the liability.

AUTHOR
======

   Luis E. Munoz <lem@cantv.net>

SEE ALSO
========

   perl(1).

Count hosts in named subnets
****************************

NAME
====

   NetAddr::IP::Count - Count hosts in named subnets

SYNOPSIS
========

     use NetAddr::IP::Count;
     use NetAddr::IP;

     my $counter = new NetAddr::IP::Count;

     $counter->add('subnet-00', new NetAddr::IP("10.0.0.0/24"));
     $counter->add('other', @array_of_ip_addresses);
     $counter->add('other', @another_array_of_ip_addresses);

     $counter->cache(10);

     $counter->count(new NetAddr::IP("10.0.3.17"));
     $counter->count(@array_of_ip_addresses);

     $counter->valcount(new NetAddr::IP("10.0.3.17"), 23);
     @array_of_ipaddr_and_values = (new NetAddr::IP("10.0.3.17"), 23,
     				new NetAddr::IP("101.0.23.107"), 2);
     $counter->valcount(@array_of_ipaddr_and_values);

     my $r_count = $counter->result;

     foreach my $subnet (keys %{$r_count}) {
         print "Subnet $subnet had ", $r_count->{$subnet}, " visits.\n";
     }

DESCRIPTION
===========

   This module implements a symplistic way to match individual IP
Addresses to subnets. It can be used to, among other things, help analyze
HTTPD logs.

   The following methods are implemented.

`->new'
     Creates a new counter. This method can be called passing as argument a
     hash where the keys are the name of the subnet group and the values
     are references to arrays of `NetAddr::IP' objects referencing each
     specific subnet. This is probably ok for static initializations.

`->add'
     Adds a subnet group. The first parameter is the name of the group
     being added. If it's a new name, a new entry will be created. Else the
     given subnets are added to the existing ones, like in the example
     above.

`->count'
     Verifies if the `NetAddr::IP'es are contained in any of the given
     subnets. If this is the case, the corresponding totals are updated.

`->valcount'
     The same as `->count' but the argument is an array consisting of
     `NetAddr::IP'es and value pairs.

`->result'
     Returns a reference to a hash containing the respective totals for
     each subnet group. The key to the hash is the subnet name given with
     `->add', the value is how many `NetAddr::IP' objects have been found
     to match that subnet group.

`->cache'
     Since in usual applications `NetAddr::IPes' from the same subnet will
     tend to be grouped in clusters like in the case of HTTPD logs some
     caching is attempted to speed things up. The caching consists in
     storing the last few entries matched in an LRU list which is checked
     before going through all the stored subnets.

     This can improve response times if tuned sensibly, however consider
     that every miss will cause every entry in the cache to be checked
     twice, one in the cache and one in the normal process so it's
     important to tune the cache.

     The default cache size is 5, which can be changed by calling the
     `->cache' method as in the example. The old value of the cache size
     is returned.

AUTHOR
======

   Luis E. Munoz <lem@cantv.net>. Alvaro Carvajal <alvaro@cantv.net>
contributed the valcount method.

SEE ALSO
========

   perl(1), NetAddr::IP(1).

modules to assemble/disassemble network packets at the protocol level.
**********************************************************************

NAME
====

   `NetPacket' - modules to assemble/disassemble network packets at the
protocol level.

SYNOPSIS
========

     # NetPacket is a base class only

DESCRIPTION
===========

   `NetPacket' provides a base class for a cluster of modules related to
decoding and encoding of network protocols.  Each `NetPacket' descendent
module knows how to encode and decode packets for the network protocol it
implements.  Consult the documentation for the module in question for
protocol-specific implementation.

   Note that there is no inheritance in the `NetPacket::' cluster of
modules other than each protocol module being a `NetPacket'.  This was
seen to be too restrictive as imposing inheritance relationships (for
example between the IP, UDP and TCP protocols) would make things like
tunneling or other unusual situations difficult.

WRITING YOUR OWN `NetPacket::' MODULE
=====================================

   You are encouraged to write additional `NetPacket::' modules as well as
improve existing ones.  Contact the maintainer of the module in question
with your suggestions or changes.

   The following sections are a list of suggestions and conventions for
writing a `NetPacket::' module.

Naming Conventions
------------------

   When creating a module in the `NetPacket::' namespace, it is suggested
that you stick to a couple of conventions when naming packet contents.
This will hopefully lead to a consistent namespace making the
`NetPacket::' easier to use.

   Content names are all lowercase, with underscores separating multiple
words.  The following abbreviations are recommended:

     Word		Abbreviation
     --------------------------------
     source		src
     destination		dest
     checksum		cksum
     identifier		id
     version		ver
     protocol		proto

Required Methods
----------------

   encode(), decode(), strip()

Required Fields
---------------

   Every NetPacket:: object should have the following fields.

_parent
     A link to the parent `NetPacket::' object in which this `NetPacket::'
     object is encaulated.  This field is undefined if there is no parent
     object.

_frame
     A copy of the raw data of the packet.

data
     This field should contain the data encapsulated in the packet (i.e any
     headers or trailers stripped off) or undef if the packet contains no
     data.  Note that in this sense, "data" is taken to mean information
     not relevant to the particular protocol being decoded.  For example,
     an ARP packet contains many header fields but no data.  A UDP
     datagram, however contains header fields and a payload.

Tags
----

COPYRIGHT
=========

     Copyright (c) 1995,1996,1997,1998,1999 ANU and CSIRO on behalf of
     the participants in the CRC for Advanced Computational Systems
     ('ACSys').

     ACSys makes this software and all associated data and documentation
     ('Software') available free of charge.  You may make copies of the
     Software but you must include all of this notice on any copy.

     The Software was developed for research purposes and ACSys does not
     warrant that it is error free or fit for any purpose.  ACSys
     disclaims any liability for all claims, expenses, losses, damages
     and costs any user may incur as a result of using, copying or
     modifying the Software.

AUTHOR
======

   Tim Potter <tpot@acsys.anu.edu.au>

Assemble and disassemble ARP (Address Resolution Protocol) packets.
*******************************************************************

NAME
====

   `NetPacket::ARP' - Assemble and disassemble ARP (Address Resolution
Protocol) packets.

SYNOPSIS
========

     use NetPacket::ARP;

     $tcp_obj = NetPacket::ARP->decode($raw_pkt);
     $tcp_pkt = NetPacket::ARP->encode(params...);   # Not implemented

DESCRIPTION
===========

   `NetPacket::ARP' provides a set of routines for assembling and
disassembling packets using ARP (Address Resolution Protocol).

Methods
-------

`NetPacket::ARP->decode([RAW PACKET])'
     Decode the raw packet data given and return an object containing
     instance data.  This method will quite happily decode garbage input.
     It is the responsibility of the programmer to ensure valid packet data
     is passed to this method.

`NetPacket::ARP->encode(param => value)'
     Return a ARP packet encoded with the instance data specified.  Not
     implemented.

Functions
---------

`NetPacket::ARP::strip([RAW PACKET])'
     Return the encapsulated data (or payload) contained in the TCP packet.
     Since no payload data is encapulated in an ARP packet (only instance
     data), this function returns undef.

Instance data
-------------

   The instance data for the `NetPacket::ARP' object consists of the
following fields.

htype
     Hardware type.

proto
     Protocol type.

hlen
     Header length.

plen
     Protocol length.

opcode
     One of the following constants:

        * ARP_OPCODE_REQUEST

        * ARP_OPCODE_REPLY

        * RARP_OPCODE_REQUEST

        * RARP_OPCODE_REPLY

sha
     Source hardware address.

spa
     Source protocol address.

tha
     Target hardware address.

tpa
     Target protocol address.

Exports
-------

default
     none

exportable
     none

tags
     The following tags group together related exportable items.

    :ALL
          All the above exportable items.

EXAMPLE
=======

   Print out arp requests on the local network.

   #!/usr/bin/perl

   use Net::PcapUtils; use NetPacket::Ethernet qw(:types); use
NetPacket::ARP;

   sub process_pkt {     my ($arg, $hdr, $pkt) = @_;

     my $eth_obj = NetPacket::Ethernet->decode($pkt);

     if ($eth_obj->{type} == ETH_TYPE_ARP) {
     	my $arp_obj = NetPacket::ARP->decode($eth_obj->{data}, $eth_obj);
     	print("source hw addr=$arp_obj->{sha}, " .
     	      "dest hw addr=$arp_obj->{tha}\n");
     }
     }

   Net::PcapUtils::loop(\&process_pkt);

TODO
====

Implement encode() function
Does this work for protocols other than IP?  Need to read RFC.
Example is a bit silly
COPYRIGHT
=========

     Copyright (c) 1995,1996,1997,1998,1999 ANU and CSIRO on behalf of
     the participants in the CRC for Advanced Computational Systems
     ('ACSys').

     ACSys makes this software and all associated data and documentation
     ('Software') available free of charge.  You may make copies of the
     Software but you must include all of this notice on any copy.

     The Software was developed for research purposes and ACSys does not
     warrant that it is error free or fit for any purpose.  ACSys
     disclaims any liability for all claims, expenses, losses, damages
     and costs any user may incur as a result of using, copying or
     modifying the Software.

AUTHOR
======

   Tim Potter <tpot@acsys.anu.edu.au>

Assemble and disassemble ethernet packets.
******************************************

NAME
====

   `NetPacket::Ethernet' - Assemble and disassemble ethernet packets.

SYNOPSIS
========

     use NetPacket::Ethernet;

     $eth_obj = NetPacket::Ethernet->decode($raw_pkt);
     $eth_pkt = NetPacket::Ethernet->encode(params...);   # Not implemented
     $eth_data = NetPacket::Ethernet::strip($raw_pkt);

DESCRIPTION
===========

   `NetPacket::Ethernet' provides a set of routines for assembling and
disassembling packets using the Ethernet protocol.

Methods
-------

`NetPacket::Ethernet->decode([RAW PACKET])'
     Decode the raw packet data given and return an object containing
     instance data.  This method will quite happily decode garbage input.
     It is the responsibility of the programmer to ensure valid packet data
     is passed to this method.

`NetPacket::Ethernet->encode(param => value)'
     Return an ethernet packet encoded with the instance data specified.
     Not implemented.

Functions
---------

`NetPacket::Ethernet::strip([RAW PACKET])'
     Return the encapsulated data (or payload) contained in the ethernet
     packet.  This data is suitable to be used as input for other
     `NetPacket::*' modules.

     This function is equivalent to creating an object using the
     `decode()' constructor and returning the data field of that object.

Instance data
-------------

   The instance data for the `NetPacket::Ethernet' object consists of the
following fields.

src_mac
     The source MAC address for the ethernet packet as a hex string.

dest_mac
     The destination MAC address for the ethernet packet as a hex string.

type
     The protocol type for the ethernet packet.

data
     The payload for the ethernet packet.

Exports
-------

default
     none

exportable
     ETH_TYPE_IP ETH_TYPE_ARP ETH_TYPE_APPLETALK ETH_TYPE_SNMP
     ETH_TYPE_IPv6 ETH_TYPE_PPP

tags
     The following tags group together related exportable items.

    `:types'
          ETH_TYPE_IP ETH_TYPE_ARP ETH_TYPE_APPLETALK ETH_TYPE_SNMP
          ETH_TYPE_IPv6 ETH_TYPE_PPP

    `:strip'
          Import the strip function `eth_strip' which is an alias for
          `NetPacket::Ethernet::strip'

    :ALL
          All the above exportable items.

EXAMPLE
=======

   The following script dumps ethernet frames by mac address and protocol
to standard output.

     #!/usr/bin/perl

     use strict;
     use Net::PcapUtils;
     use NetPacket::Ethernet;

     sub process_pkt {
         my($arg, $hdr, $pkt) = @_;

     my $eth_obj = NetPacket::Ethernet->decode($pkt);
     print("$eth_obj->{src_mac}:$eth_obj->{dest_mac} $eth_obj->{type}\n");
       }

     Net::PcapUtils::loop(\&process_pkt);

TODO
====

Implement encode() function
COPYRIGHT
=========

     Copyright (c) 1995,1996,1997,1998,1999 ANU and CSIRO on behalf of
     the participants in the CRC for Advanced Computational Systems
     ('ACSys').

     ACSys makes this software and all associated data and documentation
     ('Software') available free of charge.  You may make copies of the
     Software but you must include all of this notice on any copy.

     The Software was developed for research purposes and ACSys does not
     warrant that it is error free or fit for any purpose.  ACSys
     disclaims any liability for all claims, expenses, losses, damages
     and costs any user may incur as a result of using, copying or
     modifying the Software.

AUTHOR
======

   Tim Potter <tpot@acsys.anu.edu.au>

Assemble and disassemble ICMP (Internet Control Message Protocol) packets.
**************************************************************************

NAME
====

   `NetPacket::ICMP' - Assemble and disassemble ICMP (Internet Control
Message Protocol) packets.

SYNOPSIS
========

     use NetPacket::ICMP;

     $icmp_obj = NetPacket::ICMP->decode($raw_pkt);
     $icmp_pkt = NetPacket::ICMP->encode(params...);   # Not implemented
     $icmp_data = NetPacket::ICMP::strip($raw_pkt);

DESCRIPTION
===========

   `NetPacket::ICMP' provides a set of routines for assembling and
disassembling packets using ICMP (Internet Control Message Protocol).

Methods
-------

`NetPacket::ICMP->decode([RAW PACKET])'
     Decode the raw packet data given and return an object containing
     instance data.  This method will quite happily decode garbage input.
     It is the responsibility of the programmer to ensure valid packet data
     is passed to this method.

`NetPacket::IGMP->encode(param => value)'
     Return an IGMP packet encoded with the instance data specified.  Not
     implemented.

Functions
---------

`NetPacket::IGMP::strip([RAW PACKET])'
     Return the encapsulated data (or payload) contained in the ICMP
     packet.

Instance data
-------------

   The instance data for the `NetPacket::ICMP' object consists of the
following fields.

type
     The ICMP message type of this packet.

code
     The ICMP message code of this packet.

cksum
     The checksum for this packet.

data
     The encapsulated data (payload) for this packet.

Exports
-------

default
     none

exportable
     none

tags
     The following tags group together related exportable items.

    `:strip'
          Import the strip function `icmp_strip'.

    :ALL
          All the above exportable items.

EXAMPLE
=======

TODO
====

Implement encode() function
Create constants
Write example
COPYRIGHT
=========

     Copyright (c) 1995,1996,1997,1998,1999 ANU and CSIRO on behalf of
     the participants in the CRC for Advanced Computational Systems
     ('ACSys').

     ACSys makes this software and all associated data and documentation
     ('Software') available free of charge.  You may make copies of the
     Software but you must include all of this notice on any copy.

     The Software was developed for research purposes and ACSys does not
     warrant that it is error free or fit for any purpose.  ACSys
     disclaims any liability for all claims, expenses, losses, damages
     and costs any user may incur as a result of using, copying or
     modifying the Software.

AUTHOR
======

   Tim Potter <tpot@acsys.anu.edu.au>

Assemble and disassemble IGMP (Internet Group Mangement Protocol) packets.
**************************************************************************

NAME
====

   `NetPacket::IGMP' - Assemble and disassemble IGMP (Internet Group
Mangement Protocol) packets.

SYNOPSIS
========

     use NetPacket::IGMP;

     $igmp_obj = NetPacket::IGMP->decode($raw_pkt);
     $igmp_pkt = NetPacket::IGMP->encode(params...);   # Not implemented
     $igmp_data = NetPacket::IGMP::strip($raw_pkt);

DESCRIPTION
===========

   `NetPacket::IGMP' provides a set of routines for assembling and
disassembling packets using IGMP (Internet Group Mangement Protocol).

Methods
-------

`NetPacket::IGMP->decode([RAW PACKET])'
     Decode the raw packet data given and return an object containing
     instance data.  This method will quite happily decode garbage input.
     It is the responsibility of the programmer to ensure valid packet data
     is passed to this method.

`NetPacket::IGMP->encode(param => value)'
     Return an IGMP packet encoded with the instance data specified.  Not
     implemented.

Functions
---------

`NetPacket::IGMP::strip([RAW PACKET])'
     Return the encapsulated data (or payload) contained in the IGMP
     packet.  This function returns undef as there is no encapsulated data
     in an IGMP packet.

Instance data
-------------

   The instance data for the `NetPacket::IGMP' object consists of the
following fields.

version
     The IGMP version of this packet.

type
     The message type for this packet.

len
     The length (including length of header) in bytes for this packet.

subtype
     The message subtype for this packet.

cksum
     The checksum for this packet.

group_addr
     The group address specified in this packet.

data
     The encapsulated data (payload) for this packet.

Exports
-------

default
     none

exportable
     IGMP_VERSION_RFC998 IGMP_VERSION_RFC1112 IGMP_HOST_MQUERY
     IGMP_HOST_MREPORT IGMP_IP_NO_HOSTS IGMP_IP_ALL_HOSTS
     IGMP_IP_ALL_ROUTERS

tags
     The following tags group together related exportable items.

    `:strip'
          Import the strip function `igmp_strip'.

    `:versions'
          IGMP_VERSION_RFC998 IGMP_VERSION_RFC1112

    `:msgtypes'
          IGMP_HOST_MQUERY IGMP_HOST_MREPORT

    `:group_addrs'
          IGMP_IP_NO_HOSTS IGMP_IP_ALL_HOSTS IGMP_IP_ALL_ROUTERS

    :ALL
          All the above exportable items.

EXAMPLE
=======

   The following script dumps UDP frames by IP address and UDP port to
standard output.

     #!/usr/bin/perl

     use strict;
     use Net::PcapUtils;
     use NetPacket::Ethernet qw(:strip);
     use NetPacket::IP;
     use NetPacket::IGMP;

     sub process_pkt {
         my($arg, $hdr, $pkt) = @_;

     my $ip_obj = NetPacket::IP->decode(eth_strip($pkt));
     my $igmp_obj = NetPacket::IGMP->decode($ip_obj->{data});

     print("$ip_obj->{src_ip} -> $ip_obj->{dest_ip} ",
     	    "$igmp_obj->{type}/$igmp_obj->{subtype} ",
     	    "$igmp_obj->{group_addr}\n");
       }

     Net::PcapUtils::loop(\&process_pkt, FILTER => 'igmp');

TODO
====

Implement encode() function
COPYRIGHT
=========

     Copyright (c) 1995,1996,1997,1998,1999 ANU and CSIRO on behalf of
     the participants in the CRC for Advanced Computational Systems
     ('ACSys').

     ACSys makes this software and all associated data and documentation
     ('Software') available free of charge.  You may make copies of the
     Software but you must include all of this notice on any copy.

     The Software was developed for research purposes and ACSys does not
     warrant that it is error free or fit for any purpose.  ACSys
     disclaims any liability for all claims, expenses, losses, damages
     and costs any user may incur as a result of using, copying or
     modifying the Software.

AUTHOR
======

   Tim Potter <tpot@acsys.anu.edu.au>

Assemble and disassemble IP (Internet Protocol) packets.
********************************************************

NAME
====

   `NetPacket::IP' - Assemble and disassemble IP (Internet Protocol)
packets.

SYNOPSIS
========

     use NetPacket::IP;

     $ip_obj = NetPacket::IP->decode($raw_pkt);
     $ip_pkt = NetPacket::IP->encode(params...);   # Not implemented
     $ip_data = NetPacket::IP::strip($raw_pkt);

DESCRIPTION
===========

   `NetPacket::IP' provides a set of routines for assembling and
disassembling packets using IP (Internet Protocol).

Methods
-------

`NetPacket::IP->decode([RAW PACKET])'
     Decode the raw packet data given and return an object containing
     instance data.  This method will quite happily decode garbage input.
     It is the responsibility of the programmer to ensure valid packet data
     is passed to this method.

`NetPacket::IP->encode(param => value)'
     Return an IP packet encoded with the instance data specified.  Not
     implemented.

Functions
---------

`NetPacket::IP::strip([RAW PACKET])'
     Return the encapsulated data (or payload) contained in the IP packet.
     This data is suitable to be used as input for other `NetPacket::*'
     modules.

     This function is equivalent to creating an object using the
     `decode()' constructor and returning the data field of that object.

Instance data
-------------

   The instance data for the `NetPacket::IP' object consists of the
following fields.

ver
     The IP version number of this packet.

hlen
     The IP header length of this packet.

flags
     The IP header flags for this packet.

foffset
     The IP fragment offset for this packet.

tos
     The type-of-service for this IP packet.

len
     The length (including length of header) in bytes for this packet.

id
     The identification (sequence) number for this IP packet.

ttl
     The time-to-live value for this packet.

proto
     The IP protocol number for this packet.

cksum
     The IP checksum value for this packet.

src_ip
     The source IP address for this packet in dotted-quad notation.

dest_ip
     The destination IP address for this packet in dotted-quad notation.

options
     Any IP options for this packet.

data
     The encapsulated data (payload) for this IP packet.

Exports
-------

default
     none

exportable
     IP_PROTO_IP IP_PROTO_ICMP IP_PROTO_IGMP IP_PROTO_IPIP IP_PROTO_TCP
     IP_PROTO_UDP IP_VERSION_IPv4

tags
     The following tags group together related exportable items.

    `:protos'
          IP_PROTO_IP IP_PROTO_ICMP IP_PROTO_IGMP IP_PROTO_IPIP
          IP_PROTO_TCP IP_PROTO_UDP

    `:versions'
          IP_VERSION_IPv4

    `:strip'
          Import the strip function `ip_strip'.

    :ALL
          All the above exportable items.

EXAMPLE
=======

   The following script dumps IP frames by IP address and protocol to
standard output.

     #!/usr/bin/perl

     use strict;
     use Net::PcapUtils;
     use NetPacket::Ethernet qw(:strip);
     use NetPacket::IP;

     sub process_pkt {
         my ($user, $hdr, $pkt) = @_;

     my $ip_obj = NetPacket::IP->decode(eth_strip($pkt));
     print("$ip_obj->{src_ip}:$ip_obj->{dest_ip} $ip_obj->{proto}\n");
       }

     Net::PcapUtils::loop(\&process_pkt, FILTER => 'ip');

TODO
====

Implement encode() function
IP option decoding - currently stored in binary form.
Assembly of received fragments
COPYRIGHT
=========

     Copyright (c) 1995,1996,1997,1998,1999 ANU and CSIRO on behalf of
     the participants in the CRC for Advanced Computational Systems
     ('ACSys').

     ACSys makes this software and all associated data and documentation
     ('Software') available free of charge.  You may make copies of the
     Software but you must include all of this notice on any copy.

     The Software was developed for research purposes and ACSys does not
     warrant that it is error free or fit for any purpose.  ACSys
     disclaims any liability for all claims, expenses, losses, damages
     and costs any user may incur as a result of using, copying or
     modifying the Software.

AUTHOR
======

   Tim Potter <tpot@acsys.anu.edu.au>

Assemble and disassemble TCP (Transmission Control Protocol) packets.
*********************************************************************

NAME
====

   `NetPacket::TCP' - Assemble and disassemble TCP (Transmission Control
Protocol) packets.

SYNOPSIS
========

     use NetPacket::TCP;

     $tcp_obj = NetPacket::TCP->decode($raw_pkt);
     $tcp_pkt = NetPacket::TCP->encode(params...);   # Not implemented
     $tcp_data = NetPacket::TCP::strip($raw_pkt);

DESCRIPTION
===========

   `NetPacket::TCP' provides a set of routines for assembling and
disassembling packets using TCP (Transmission Control Protocol).

Methods
-------

`NetPacket::TCP->decode([RAW PACKET])'
     Decode the raw packet data given and return an object containing
     instance data.  This method will quite happily decode garbage input.
     It is the responsibility of the programmer to ensure valid packet data
     is passed to this method.

`NetPacket::TCP->encode(param => value)'
     Return a TCP packet encoded with the instance data specified.  Not
     implemented.

Functions
---------

`NetPacket::TCP::strip([RAW PACKET])'
     Return the encapsulated data (or payload) contained in the TCP
     packet.  This data is suitable to be used as input for other
     `NetPacket::*' modules.

     This function is equivalent to creating an object using the
     `decode()' constructor and returning the data field of that object.

Instance data
-------------

   The instance data for the `NetPacket::TCP' object consists of the
following fields.

src_port
     The source TCP port for the packet.

dest_port
     The destination TCP port for the packet.

seqnum
     The TCP sequence number for this packet.

acknum
     The TCP acknowledgement number for this packet.

hlen
     The header length for this packet.

reserved
     The 6-bit "reserved" space in the TCP header.

flags
     Contains the urg, ack, psh, rst, syn and fin flags for this packet.

winsize
     The TCP window size for this packet.

cksum
     The TCP checksum.

urg
     The TCP urgent pointer.

options
     Any TCP options for this packet in binary form.

data
     The encapsulated data (payload) for this packet.

Exports
-------

default
     none

exportable
     tcp_strip

tags
     The following tags group together related exportable items.

    `:strip'
          Import the strip function `tcp_strip'.

    :ALL
          All the above exportable items.

EXAMPLE
=======

   The following script is a primitive pop3 sniffer.

     #!/usr/bin/perl

     use strict;
     use Net::PcapUtils;
     use NetPacket::Ethernet qw(:strip);
     use NetPacket::IP qw(:strip);
     use NetPacket::TCP;

     sub process_pkt {
         my($arg, $hdr, $pkt) = @_;

     my $tcp_obj = NetPacket::TCP->decode(ip_strip(eth_strip($pkt)));

     if (($tcp_obj->{src_port} == 110) or ($tcp_obj->{dest_port} == 110)) {
     	  print($tcp_obj->{data});
     }
       }

     Net::PcapUtils::loop(\&process_pkt, FILTER => 'tcp');

TODO
====

Implement encode() function
Assembly of TCP fragments into a data stream
Option processing
Nicer processing of TCP flags
COPYRIGHT
=========

     Copyright (c) 1995,1996,1997,1998,1999 ANU and CSIRO on behalf of
     the participants in the CRC for Advanced Computational Systems
     ('ACSys').

     ACSys makes this software and all associated data and documentation
     ('Software') available free of charge.  You may make copies of the
     Software but you must include all of this notice on any copy.

     The Software was developed for research purposes and ACSys does not
     warrant that it is error free or fit for any purpose.  ACSys
     disclaims any liability for all claims, expenses, losses, damages
     and costs any user may incur as a result of using, copying or
     modifying the Software.

AUTHOR
======

   Tim Potter <tpot@acsys.anu.edu.au>

Assemble and disassemble UDP (User Datagram Protocol) packets.
**************************************************************

NAME
====

   `NetPacket::UDP' - Assemble and disassemble UDP (User Datagram
Protocol) packets.

SYNOPSIS
========

     use NetPacket::UDP;

     $udp_obj = NetPacket::UDP->decode($raw_pkt);
     $udp_pkt = NetPacket::UDP->encode(params...);   # Not implemented
     $udp_data = NetPacket::UDP::strip($raw_pkt);

DESCRIPTION
===========

   `NetPacket::UDP' provides a set of routines for assembling and
disassembling packets using UDP (User Datagram Protocol).

Methods
-------

`NetPacket::UDP->decode([RAW PACKET])'
     Decode the raw packet data given and return an object containing
     instance data.  This method will quite happily decode garbage input.
     It is the responsibility of the programmer to ensure valid packet data
     is passed to this method.

`NetPacket::UDP->encode(param => value)'
     Return a UDP packet encoded with the instance data specified.  Not
     implemented.

Functions
---------

`NetPacket::UDP::strip([RAW PACKET])'
     Return the encapsulated data (or payload) contained in the UDP
     packet.  This data is suitable to be used as input for other
     `NetPacket::*' modules.

     This function is equivalent to creating an object using the
     `decode()' constructor and returning the data field of that object.

Instance data
-------------

   The instance data for the `NetPacket::UDP' object consists of the
following fields.

src_port
     The source UDP port for the datagram.

dest_port
     The destination UDP port for the datagram.

len
     The length (including length of header) in bytes for this packet.

cksum
     The checksum value for this packet.

data
     The encapsulated data (payload) for this packet.

Exports
-------

default
     none

exportable
     igmp_strip IGMP_VERSION_RFC998 IGMP_VERSION_RFC1112
     IGMP_MSG_HOST_MQUERY IGMP_MSG_HOST_MREPORT IGMP_IP_NO_HOSTS
     IGMP_IP_ALL_HOSTS IGMP_IP_ALL_ROUTERS

tags
     The following tags group together related exportable items.

    `:strip'
          Import the strip function `igmp_strip'.

    `:versions'
          IGMP_VERSION_RFC998 IGMP_VERSION_RFC1112

    `:msgtypes'
          IGMP_HOST_MQUERY IGMP_HOST_MREPORT

    `:group_addrs'
          IGMP_IP_NO_HOSTS IGMP_IP_ALL_HOSTS IGMP_IP_ALL_ROUTERS

    :ALL
          All the above exportable items.

EXAMPLE
=======

   The following script dumps IGMP the contents of IGMP frames to standard
output.

     #!/usr/bin/perl

     use strict;
     use Net::PcapUtils;
     use NetPacket::Ethernet qw(:strip);
     use NetPacket::IP;
     use NetPacket::UDP;

     sub process_pkt {
         my($arg, $hdr, $pkt) = @_;

     my $ip_obj = NetPacket::IP->decode(eth_strip($pkt));
     my $udp_obj = NetPacket::UDP->decode($ip_obj->{data});

     print("$ip_obj->{src_ip}:$udp_obj->{src_port} -> ",
     	    "$ip_obj->{dest_ip}:$udp_obj->{dest_port} ",
     	    "$udp_obj->{len}\n");
       }

     Net::PcapUtils::loop(\&process_pkt, FILTER => 'udp');

TODO
====

Implement encode() function
COPYRIGHT
=========

     Copyright (c) 1995,1996,1997,1998,1999 ANU and CSIRO on behalf of
     the participants in the CRC for Advanced Computational Systems
     ('ACSys').

     ACSys makes this software and all associated data and documentation
     ('Software') available free of charge.  You may make copies of the
     Software but you must include all of this notice on any copy.

     The Software was developed for research purposes and ACSys does not
     warrant that it is error free or fit for any purpose.  ACSys
     disclaims any liability for all claims, expenses, losses, damages
     and costs any user may incur as a result of using, copying or
     modifying the Software.

AUTHOR
======

   Tim Potter <tpot@acsys.anu.edu.au>

generic TCP/IP server class
***************************

NAME
====

   Server - generic TCP/IP server class

SYNOPSIS
========

     my $server_cb = sub  {
                            my ($s) = shift ;
                            print STDOUT "Echo server: type bye to quit, exit ",
                                         "to kill the server.\n\n" ;
                            while (defined ($tmp = <STDIN>)) {
                                return if ($tmp =~ /^bye/i);
                                $s->quit() if ($tmp =~ /^exit/i);
                                print STDOUT "You said:>$tmp\n";
                          }
     my ($foo) = new NetServer::Generic;
     $foo->port(9000);
     $foo->callback($server_cb);
     $foo->mode("forking");
     print "Starting server\n";
     $foo->run();

DESCRIPTION
===========

   `NetServer::Generic' provides a (very) simple server daemon for TCP/IP
processes. It is intended to free the programmer from having to think too
hard about networking issues so that they can concentrate on doing
something useful.

   The `NetServer::Generic' object accepts the following methods, which
configure various aspects of the new server:

port
     The port to listen on.

hostname
     The local address to bind to. If no address is specified, listens for
     any connection on the designated port.

listen
     Queue size for listen.

proto
     Protocol we're listening to (defaults to tcp)

timeout
     Timeout value (see IO/Socket/INET)

allowed
     list of IP addresses or hostnames that are explicitly allowed to
     connect to the server. If empty, the default policy is to allow
     connections from anyone not in the 'forbidden' list.

     NOTE: IP addresses or hostnames may be specified as perl regular
     expressions; for example 154\.153\.4\..* matches any IP address
     beginning with '154.153.4.'; .*antipope\.org matches any hostname in
     the antipope.org domain.

forbidden
     list of IP addresses or hostnames that are refused permission to
     connect to the server. If empty, the default policy is to refuse
     connections from anyone not in the 'allowed' list (unless the allowed
     list is empty, in which case anyone may connect).

callback
     Coderef to a subroutine which handles incoming connections (called
     with one parameter - a `NetServer::Generic' object which can be used
     to shut down the session).

mode
     Can be one of *forking*, select, *select_fast*, client, *threaded*,
     or *prefork*.

     By default, *forking* mode is selected.

     *forking* mode is selected, the server handles requests by forking a
     child process to service them. If select mode is selected, the server
     uses the IO::Select class to implement a simple non-forking server.

     The select-based server may block on i/o on a heavily-loaded system.
     If you need to do non-blocking i/o you should look at
     NetServer::FastSelect.

     The client mode is special; it indicates that rather than sitting
     around waiting for an incoming connection, the server is itself a
     TCP/IP client. In client mode, hostname is the remote host to connect
     to and port is the remote port to open. The callback routine is used,
     as elsewhere, but it should be written as for a client - i.e. it
     should issue a request or command, then read.  An additional method
     exists for client mode: `trigger'. `trigger' expects a coderef as a
     parameter. This coderef is executed before the client-mode server
     spawns a child; if it returns a non-zero value the child is forked
     and opens a client connection to the target host, otherwise the
     server exits. The trigger method may be used to sleep for a random
     interval then return 1 (so that repeated clients are spawned at
     random intervals), or fork several children (on a one- time-only
     basis) then work as above (so that several clients poke at the target
     server on a random basis). The default trigger method returns 1
     immediately the first time it is called, then returns 0 - this means
     that the client makes a single connection to the target host, invokes
     the callback routine, then exits. (See the test examples which come
     with this module for examples of how to use client mode.)

     Note that client mode relies on the fork() system call.

     The *threaded* mode indicates that multithreading will be used to
     service requests. This feature requires Perl 5.005 or higher and a
     native threads library to run, so it's not 100% portable). Moreover,
     it's unreliable! Don't use this mode unless you're prepared to do some
     debugging.

     The *prefork* mode indicates that the server will bind to the
     designated port, then fork repeatedly up to `$start_servers' times
     (where `start_servers' is a scalar parameter to `NetServer::Generic').
     Each child then enters a select-based loop. (i.e. run_select), but
     exits after handling `$server_lifespan' transactions (where
     `server_lifespan' is another parameter to `NetServer::Generic').
     Every time a child handles a transaction it writes its PID and
     generation number down a pipe to the parent process, with a message
     when it exits.  The parent keeps track of how many servers are in use
     and fires up extra children (up to `$max_servers') if the number in
     use leaves less than `$min_spare_servers' free. See the example
     *preforked-shttpd* for a minimal HTTP 0.9 server implemented using
     the *prefork* mode.

   Of these, the callback method is most important; it specifies a
reference to a subroutine which effectively does whatever the server does.

   A callback subroutine is a normal Perl subroutine. It is invoked with
STDIN and STDOUT attached to an IO::Socket::INET object, so that reads
from STDIN get information from the client, and writes to STDOUT send
information to the client. Note that both STDIN and STDOUT are unbuffered.
In addition, a `NetServer::Generic' object is passed as an argument (but
the callback is free to ignore it).

   Your server reads and writes data via the socket as if it is the
standard input and standard output filehandles; for example:

     while (defined ($tmp = <STDIN>)) {  # read a line from the socket

     print STDOUT "You said: $tmp\n";    # print something to the socket

   (See IO::Handle and IO::Socket for more information on this.)

   If you're not familiar with sockets, don't get too fresh and try to
close or seek on STDIN or STDOUT; just treat them like a file.

   The server object is not strictly necessary in the callback, but comes
in handy: you can shut down the server completely by calling the quit()
method.

   When writing a callback subroutine, remember to define some condition
under which you return!

   Here's a slightly more complex server example:

     # minimal http server (HTTP/0.9):
     # this is a REALLY minimal HTTP server. It only understands GET
     # requests, does no header parsing whatsoever, and doesn't understand
     # relative addresses! Nor does it understand CGI scripts. And it ain't
     # suitable as a replacement for Apache (at least, not any time soon :).
     # The base directory for the server and the default
     # file name are defined in B<url_to_file()>, which maps URLs to
     # absolute pathnames. The server code itself is defined in the
     # closure B<$http>, which shows how simple it is to write a server
     # using this module.

     sub url_to_file($) {
       # for a given URL, turn it into an absolute pathname
       my ($u) = shift ;  # incoming URL fragment from GET request
       my ($f) = "";      # file pathname to return
       my ($htbase) = "/usr/local/etc/httpd/docs/";
       my ($htdefault) = "index.html";
       chop $u;
       if ($u eq "/") {
           $f = $htbase . $htdefault;
           return $f;
       } else {
           if ($u =~ m|^/.+|) {
               $f = $htbase;  chop $f;
               $f .= $u;
           } elsif ($u =~ m|[^/]+|) {
               $f = $htbase . $u;
           }
           if ($u =~ m|.+/$|) {
               $f .= $htdefault;
           }
           if ($f =~ /\.\./) {
               my (@path) = split("/", $f);
               my ($buff, $acc) = "";
               shift @path;
               while ($buff = shift @path) {
                   my ($tmp) = shift @path;
                   if ($tmp ne '..') {
                       unshift @path, $tmp;
                       $acc .= "/$buff";
                   }
               }
               $f = $acc;
           }
       }
       return $f;
     }

     my ($http) = sub {
        my ($fh) = shift ;
        while (defined ($tmp = <STDIN>)) {
            chomp $tmp;
            if ($tmp =~ /^GET\s+(.*)$/i) {
                $getfile = $1;
                $getfile = url_to_file($getfile);
                print STDERR "Sending $getfile\n";
                my ($in) = new IO::File();
                if ($in->open("<$getfile") ) {
                    $in->autoflush(1);
                    print STDOUT "Content-type: text/html\n\n";
                    while (defined ($line = <$in>)) {
                        print STDOUT $line;
                    }
                } else {
                    print STDOUT "404: File not found\n\n";
                }
            }
            return 0;
        }
     };

     # main program starts here

     my (%config) =  ("port"     => 9000,
                      "callback" => $http,
                      "hostname" => "public.antipope.org");

     my ($allowed) = ['.*antipope\.org',
                      '.*localhost.*'];

     my ($forbidden) = [ '194\.205\.10\.2'];

     my ($foo) = new Server(%config); # create new http server bound to port
                                      # 9000 of public.antipope.org
     $foo->allowed($allowed);         # who is allowed to connect to us
     $foo->forbidden($forbidden);     # who is refused access
     print "Starting http server on port 9000\n";
     $foo->run();
     exit 0;

Additional methods
------------------

   `NetServer::Generic' provides a couple of extra methods.

peer()
     The peer() method returns a reference to a two-element list containing
     the hostname and IP address of the host at the other end of the
     socket.  If called before a connection has been received, its value
     will be undefined.  (Don't try to assign values via *peer* unless you
     want to confuse the allowed/forbidden checking code!)

quit()
     The quit() method attempts to shut down a server. If running as a
     forking service, it does so by sending a kill -15 to the parent
     process. If running as a select-based service it returns from run().

start_servers()
     In *prefork* mode, specifies how many child servers to start up.

max_servers()
     In *prefork* mode, specifies the maximum number of children to spawn
     under load.

min_spare_servers()
     In *prefork* mode, specifies a number of spare (inactive) child
     servers; if we drop below this level (due to load), the parent will
     spawn additional children (up to a maximum of max_servers) until we
     go back over *min_spare_servers*.

server_lifespan()
     In *prefork* server mode, child servers run as select servers. After
     *server_lifespan* connections they will commit suicide and be
     replaced by the parent. If *server_lifespan* is set to 1, children
     will effectively run once then exit (like a forking server). For
     purposes of insanity, a lifespan of 0 is treated like a lifespan of 1.

servername()
     In the *prefork* server, unless you *explicitly* tell the server to
     bind to a named host, it will accept all incoming connections. Within
     a client, you may need to know what local IP address an incoming
     connection was intended for. The servername() method can be invoked
     within the child server's callback and returns a two-element arrayref
     containing the port and IP address that the connection came in on.
     For example, in the client:

          my $callback = sub {
            my $server = shift;
            my ($server_port, $server_addr) = @{ $server->servername() };
            print "Connection on $server_addr:$server_port\n";

Types of server
---------------

   A full discussion of internet servers is well beyond the scope of this
man page. Beginners may want to start with a source like `Beginning Linux
Programming' in this node (which provides a simple, lucid discussion);
more advanced readers may find Stevens' `Advanced Programming in the UNIX
environment' in this node useful.

   In general, on non-threaded systems, a forking server is slightly less
efficient than a select-based server (and uses up lots of PIDs). On the
other hand, a select-based server is not a good solution to high workloads
or time-consuming processes such as providing an NNTP news feed to an
online newsreader.

   A major issue with the select-based server code in this release is that
the IO::Select based server cannot know that a socket is ready until some
data is received over it. (It calls *can_read()* to detect sockets waiting
to be read from.) Thus, it is not suitable for writing servers like which
emit status information without first reading a request.

SEE ALSO
========

   See IO/Handle, IO/Socket, LWP,
see Perlfunc (perl.info), `"I', see Perlop (perl.info),

BUGS
====

   There are two bugs lurking in NetServer::Generic. Or maybe they're
design flaws. I don't have time to fix them right now, but maybe you'd
like to contribute an hour or two and get your name in the credits?

   Bug the first:

   NetServer::Generic attempts to make it easy to write a server by letting
the programmer concentrate on reading from STDIN and writing to STDOUT.
However, this form of i/o is line oriented.  NetServer::Generic relies on
the buffering and i/o capabilities provided by Perl and IO::Socket
respectively. It doesn't buffer its own input.

   This means that in principle a malicious attacker (or just a badly-
written client program) can write a stream of bytes to a
NetServer::Generic application and, as long as those bytes don't include a
"\n", Perl will keep gobbling it up until it runs out of virtual memory.

   This can be fixed by replacing the globbed IO::Socket::INET that is
attached to STDIN with something else - probably an object that presents
itself as an IO::Stringy but that does its own buffering, so that it will
return *either* a line, or some sort of error message in $! if it sees
something undigestible in its input stream. (If anyone wants to contribute
a patch that fixes this, please feel free; this is an open source project,
after all ...)

   Bug the second:

   The select-based server was originally written because I wanted to
share state information between some forking servers and I couldn't use
System V shared memory (the application had to be portable to a flavour of
UNIX that didn't support it).

   It works okay, up to a point, but under heavy load on Linux it can run
into major problems. Partly this may be attributable to deficiencies in
the way Linux handles the select() system call (or so Stephen Tweedie
keeps telling me), but the result is that the select-based server tends to
drop some connections when it's under stress: if two connections come in
while it's serving another, the first may never get processed before a
timeout occurs.

   A somewhat worse problem is that IO::Select doesn't do buffered (line-
oriented) input; it just checks to see if one or more bytes are waiting to
be read from one of the file handles it's got hold of. It is possible for
a couple of bytes to come in (but not a whole line), so that the
select-based server merrily tries to process a transaction and blocks
until the rest of the input arrives - thus ensuring that the server is
bottlenecked by the speed of the slowest client connection.

   Suggestion: if you need to serve lots of connections using select(),
look at the eventserver module instead. If you're a bit more ambitious,
the defect in NetServer::Generic is fixable by writing a module with a
similar API to IO::Select, but which provides buffering for the file
handles under its control and which only returns something in response to
can_read() when one of the buffers has a complete line of input waiting.

AUTHOR
======

   Charlie Stross (charle@antipope.org). With thanks for bugfixes and
patches to Marius Kjeldahl *marius@ace.funcom.com*, Art Sackett
*asackett@artsackett.com*, Claudio Garcia *cgarcia@dbitech.com*, Claudio
Calvelli *lunatic@assurdo.com*, Martin Waite
*Martin.Waite@montgomery134.freeserve.co.uk*. Debian package contributed
by Jon Middleton, *jjm@datacash.com*.

HISTORY
=======

Version 0.1
     Based on the simple forking server in Chapter 10 of "Advanced Perl
     Programming" by Sriram Srinivasan, with a modular wrapper to make it
     easy to use and configure, and a rudimentary access control system.

Version 0.2
     Added the peer() method to provide peer information.

     Bugfix to *ok_to_serve* from Marius Kjeldahl *marius@ace.funcom.com*.

     Added select-based server code, mode method to switch between forking
     and selection server modes.

     Updated test code (should do something now!)

     Added example: fortune server and client code.

     Supports NetServer::SMTP (and, internally, NetServer::vTID).

Version 0.3
     fixed test failure.

Version 1.0
     Added alpha-ish prefork server mode.

     Added alpha-ish multithreaded mode (UNSTABLE)

     Modified IP address filtering to cope with regexps (suggested by Art
     Sackett *asackett@artsackett.com*)

     Modified select() server to do non-blocking writes via a

     Non-blocking-socket class tied to STDIN/STDOUT

     Option to log new connection peer addresses via STDERR

     Extra test scripts

     Updated documentation

     Fix so it works on installations with no threading support (duh).
     Tested on Solaris, too.

     Bugfixes to the preforked mode (thanks to Art Sackett for detecting
     them). Bugfix to ok_to_serve() (thanks to Claudio Garcia,
     cgarcia@dbitech.com). Some notes on the two known bugs (related to
     buffering).

     Signal handling code was fixed to avoid leaving zombie processes
     (thanks to Luis Munoz, lem@cantv.net)

Interactively Manipulate Daemon Processes
*****************************************

NAME
====

   NetServer::Portal - Interactively Manipulate Daemon Processes

SYNOPSIS
========

     require NetServer::Portal;

     'NetServer::Portal'->default_start();  # creates server
     warn "NetServer::Portal listening on port ".(7000+($$ % 1000))."\n";

DESCRIPTION
===========

   This module implements a framework for adding interactive windows into
daemon processes.  The portal server listens on port 7000+($$%1000) by
default.

   A top-like server is included that can help debug complicated event
loops.

SEE ALSO
========

   `NetServer::Portal::Pi' in this node, see NetServer/Portal/Top,

Make event loop statistics easily available
*******************************************

NAME
====

   NetServer::Portal::Top - Make event loop statistics easily available

SYNOPSIS
========

     require NetServer::Portal::Top;

DESCRIPTION
===========

   All statistics collected by Event, are displayed in a
format similar to the popular (and excellent) top program.

PRECISE STAT DEFINITIONS
========================

   * idle

     Idle tracks the amount of time that the process cooperatively
     reliquished control to the operating system.  (Usually via `select'
     in this node or `poll' in this node.)

   * other processes

     Attempts to estimate the process's non-idle time that the operating
     system instead gave to other processes. (Actual clock time minus the
     combined total time spent in idle and in running event handlers.)
     This stat is an underestimate (lower bound) since the process can also
     be preemptively interrupted *during* event processing.

   * lag

     Lag is the percent over the *planned amount of time* that the event
     loop took to complete.  ((Actual time - planned time) / planned time)

   It is unfortunately that more intuitive stats are not available.
Benchmarking is a slippery business.  If you have ideas for improvements,
don't be shy!

SCREENSHOT
==========

     pl/3bork  [12836 @ eq1062]                                    12:15:18 [  15s]
     21 events (6 zombies); load averages: 0.33, 0.32, 0.32

      EID PRI STATE  RAN  TIME  CPU  TYPE DESCRIPTION                            P1
        0   8 sleep  247  0:09 66.7%  sys idle
       24   4 sleep  105  0:04 28.1% idle QSGTable sweep
        3   4 sleep   15  0:00  2.4% time server status
       22   4 sleep   15  0:00  1.8% time QSGTable
       12   4 cpu      4  0:00  0.8% time NetServer::Portal::Client localhost
       23   4 sleep   15  0:00  0.1% time QSGTable Detail
        2   4 sleep   15  0:00  0.0% time Qt
        7   4 sleep    8  0:00  0.0% time ObjStore::Serve checkpoint
       10   4 sleep    8  0:00  0.0% time SSL items
        9   4 sleep    8  0:00  0.0% time SSL service
        6  -1 sleep    5  0:00  0.0% time Event::Stats
       21   4 zomb     0  0:00  0.0% idle QSGTable sweep
       19   4 zomb     0  0:00  0.0% time QSGTable
       11   4 sleep    0  0:00  0.0%   io NetServer::Portal::Client localhost
        8   4 sleep    0  0:00  0.0%   io SSL
       13   4 zomb     0  0:00  0.0% time QSGTable

   The three load averages are for the most recent 15 seconds, 1 minute,
and 15 minutes, respectively.

   For efficiency, not all time intervals are available.  When you change
the time interval, it will be rounded to the closest for which there is
data.

BUGS
====

   The potential impact of multiple CPUs and kernel-level thread support
is ignored.

basic SMTP server class for Perl
********************************

NAME
====

   NetServer::SMTP - basic SMTP server class for Perl

SYNOPSIS
========

     my ($self) = NetServer::SMTP->new();
     while (<STDIN>) {
         next if (! defined($_));
         my (@vec) = split(/\s+/);
         my ($fn) = shift @vec;
         $fn = uc($fn);
         if (grep(/$fn/i, @$NetServer::SMTP::States) != 0) {
             $self->in($in);
             $self->out($out);
             $self->next_state_ok($fn) && do {
                 $self->$fn(@vec);
             };
         } else {
               print STDERR "What on earth does [$fn][",
     	                   join(" ", @vec), "] mean?\n";
         }
         if ($self->{ERROR} > 0 ) {
     	    $self->DESTROY();
     	    exit;
     	}
     }

DESCRIPTION
===========

   A class that provides a basic SMTP server object and some methods. (Note
that it doesn't provide a run method with a main execution loop - hence
the above example.)

   (`Net::SMTP' provides a corresponding client class.)

   It accepts requests in accordance with RFC 821, 4.5.1 ("Minimum
Implementation"). No attempt to verify the authenticity of the sender is
made; no attempt is made to filter out relay attacks or deliver the mail,
and it doesn't even attempt to check messages for RFC 822 compliance.
Instead, the mail is spooled in the form of a deep-frozen `NetServer::SMTP'
object, dropped into the spool directory.

   Spooled mail may be transmitted by (a) unfreezing it into a live
`NetServer::SMTP' object and (b) invoking the send() method on it.  This
is the low-level delivery mechanism; it does not include a queueing
mechanism.

   Only one delivery method is supported in the base `NetServer::SMTP'
class; this is dumb SMTP forwarding to a remote smarthost. Child classes
derived from `NetServer::SMTP' may provide alternative send() methods
which override this default, for example to supply local delivery methods,
routing, and associated transport mechanisms for transport via UUCP or
other protocols.

To-do list
----------

   RFC822 checking of incoming mail to ensure it's not totally corrupt
(via Mail::Internet?).

   Velocity checking implemented at the server level - a semaphore
maintains a count of children spawned/reaped, and if the spawn rate goes
over a designated hot limit the server will begin issuing 421 responses.

   Queued mail should be tracked via a queue database - probably a tied
DB_File.  The key to each record is the position in the queue; the value
is a record containing items like the number of retries (so far), the
filename of the message, whether to use local or remote delivery methods,
and so on.  The queue is handled in a round-robin fashion by a queue
delivery subroutine. Additional methods for queueing needed.

   Currently, mail is stored using Freeze::Thaw to dump a frozen
NetServer::SMTP object. A better solution would be to dump a
Mail::Internet object and a NetServer::SMTP object containing delivery and
queueing metainformation.  (Expect this in release 0.02.)

States
------

   `NetServer::SMTP' implements a rather minimalist mechanism for checking
that state transactions within the SMTP protocol are valid. When entering
a given state (or receiving an SMTP command), it checks the hash of arrays
`NetServer::SMTP::NFA'; this contains a list of acceptable antecedent
states for the requested command. If the current state isn't in this list,
it assumes an error has occured and complains. This is just about okay for
a simple program which is intended to receive and spool messages, but it
is not a good basis for extension (e.g. for the implementation of a full
ESMTP server architecture). In any event, state consistency checking is
carried out by calling `next_state_ok()' - more sophisticated servers will
want to override this.

   Attempts to start an ESMTP session will therefore be politely rejected.

Methods
-------

   NetServer::SMTP knows about a few standard messages, and a basic set of
SMTP commands (each of which is implemented as a method):

new()
     Create a new NetServer::SMTP object. The object is now available to
     process incoming mail. It reads from STDIN, and writes responses to
     STDOUT; it should be called via `NetServer::Generic'.

     Some initialisation parameters may be specified as a hash, or as a
     filehandle referring to a configuration file, or as a configuration
     file name.

     Initialisation parameters may not be changed once the object has been
     created; you need to destroy it and start a new one. (Don't worry,
     this isn't a major overhead.)

HELO
     Commence new session

MAIL
     Begin a new mail

RCPT
     Specify recipients

DATA
     Send data

RSET
     Reset session

NOOP
     Do nothing

QUIT
     End session (spooling mail)

   These are the minimal SMTP commands required for a basic implementation
of RFC 821. Each command is handled via the autoloader, which knows what
to do.

   In addition, NetServer::SMTP knows about the following extra commands,
which may not behave quite as you expect them to do:

HELP
     Normally, provides help on a command.

initialise()
     Called by new() to initialise the new object.  Initialisation keys
     may be specified as a hash, supplied as a parameter to the new
     object, or as a filename or file handle containing a frozen
     *NetServer::SMTP* object which is users to overlay the object.

     Recognized keys are:

    myhost
          My host name (FQDN)

    allowed
          array of aliases for hosts users allowed to send mail

    silent
          If silent, dont say hello when creating a new server (we have
          other reasons for creating NetServer::SMTP objects, once in a
          while :)

    relay
          Relay hostname (FQDN)

    ERROR
          If this flag goes non-zero, Something Bad has happened and the
          session should either terminate or refuse to proceed further

    spooldir
          Directory where spooled transactions are waiting

Process and manipulate Netscape bookmarks files
***********************************************

NAME
====

   Netscape::Bookmarks - Process and manipulate Netscape bookmarks files

SYNOPSIS
========

     use Netscape::Bookmarks;
     @bookmarks = bookmarks_array($filename);
     @bookmarks = bookmarks_lol($filename);

DESCRIPTION
===========

   This module helps you process and manipulate Netscape bookmarks files.

bookmarks_array()
-----------------

   Returns a flat array of bookmark URLs.

bookmarks_lol()
---------------

   Returns a list of lists of bookmarks, with the following elements in
each of the arrayrefs:

     0	URL
     1	Name (the text name of the bookmark)
     2	Added date
     3	Last modified date
     4	Last visited date

BUGS
====

   This module isn't very fast, but then I do have ~1300 bookmarks, which
is probably excessive.  Nevertheless, it's still easier to use this module
and the `bmgrep' script to find bookmarks than to use Netscape's bookmarks
interface.

   I don't have any other versions of Netscape available to play with, so
I only know that this works with my own copy which is v4.51 on Linux.
Please let me know if you have any problems with other versions.

FUTURE DIRECTIONS
=================

   I intend to add a feature to get a decent tree-like representation of
your folders.  I also intend to provide ways to add, delete and otherwise
manipulate bookmarks.  This will probably be non-trivial, but that's life
I guess.

AUTHOR
======

   Kirrily 'Skud' Robert

   Netizen Pty Ltd

   skud@netizen.com.au

SEE ALSO
========

   perl(1).

object class for accessing Netscape cache files
***********************************************

NAME
====

   Netscape::Cache - object class for accessing Netscape cache files

SYNOPSIS
========

   The object oriented interface:

     use Netscape::Cache;

     $cache = new Netscape::Cache;
     while (defined($url = $cache->next_url)) {
     	print $url, "\n";
     }

     while (defined($o = $cache->next_object)) {
     	print
     	  $o->{'URL'}, "\n",
     	  $o->{'CACHEFILE'}, "\n",
     	  $o->{'LAST_MODIFIED'}, "\n",
     	  $o->{'MIME_TYPE'}, "\n";
     }

   The TIEHASH interface:

     use Netscape::Cache;

     tie %cache, 'Netscape::Cache';
     foreach (sort keys %cache) {
     	print $cache{$_}->{URL}, "\n";
     }

DESCRIPTION
===========

   The *Netscape::Cache* module implements an object class for accessing
the filenames and URLs of the cache files used by the Netscape web browser.

   Note: You can also use the undocumented pseudo-URLs `about:cache',
`about:memory-cache' and `about:global-history' to access your disk cache,
memory cache and global history.

   There is also an interface for using tied hashes.

   Netscape uses the old Berkeley DB format (version 1.85) for its cache
index `index.db'. Version 2.x.x is incompatible with the old format
(`db_intro(3)' in this node), so you have either to downgrade or to
convert the database using *db_dump185* and *db_load*. See
`convert_185_2xx|' in this node for a (experimental) converter function.

CONSTRUCTOR
===========

     $cache = new Netscape::Cache(-cachedir => "$ENV{HOME}/.netscape/cache");

   This creates a new instance of the *Netscape::Cache* object class. The
*-cachedir* argument is optional. By default, the cache directory setting
is retrieved from `~/.netscape/preferences'. The index file is normally
named `index.db' on Unix systems and `FAT.DB' on Microsoft systems. It may
be changed with the *-index* argument.

   If the Netscape cache index file does not exist, a warning message will
be generated, and the constructor will return undef.

METHODS
=======

   The *Netscape::Cache* class implements the following methods:

   * rewind - reset cache index to first URL

   * next_url - get next URL from cache index

   * next_object - get next URL as a full Netscape::Cache::Object from
     cache index

   * get_object - get a Netscape::Cache::Object for a given URL

   Each of the methods are described separately below.

next_url
--------

     $url = $history->next_url;

   This method returns the next URL from the cache index. Unlike
Netscape::History, this method returns a string and not an URI::URL-like
object.

   This method is faster than next_object, since it does only evaluate the
URL of the cached file.

next_object
-----------

     $cache->next_object;

   This method returns the next URL from the cache index as a
Netscape::Cache::Object object. See below for accessing the components
(cache filename, content length, mime type and more) of this object.

get_object
----------

     $cache->get_object;

   This method returns the Netscape::Cache::Object object for a given URL.
If the URL does not live in the cache index, then the returned value will
be undefined.

delete_object
-------------

   Deletes URL from cache index and the related file from the cache.

   WARNING: Do not use delete_object while in a next_object loop!  It is
better to collect all objects for delete in a list and do the deletion
after the loop, otherwise you can get strange behavior (e.g.  malloc
panics).

rewind
------

     $cache->rewind();

   This method is used to move the internal pointer of the cache index to
the first URL in the cache index. You do not need to bother with this if
you have just created the object, but it does not harm anything if you do.

get_object_by_cachefile
-----------------------

     $o = $cache->get_object_by_cachefile($cachefile);

   Finds the corresponding entry for a cache file and returns the object,
or undef if there is no such `$cachefile'. This is useful, if you find
something in your cache directory by using grep and you want to know the
URL and other attributes of this file.

   WARNING: Do not use this method while iterating with get_url, get_object
or each, because this method does iterating itself and would mess up the
previous iteration.

get_object_by_cachefile
-----------------------

     $url = $cache->get_url_by_cachefile($cachefile);

   Finds the corresponding URL for a cache file. This method is implemented
using get_object_by_cachefile.

convert_185_2xx
---------------

     $newindex = Netscape::Cache::convert_185_2xx($origindex [, $tmploc])

   This is a (experimental) utility for converting `index.db' to the new
Berkeley DB 2.x.x format. Note that this function will not overwrite the
original `index.db', but rather copy the converted index to `$tmploc' or
`/tmp/index.$$.db', if `$tmploc' is not given.  convert_185_2xx returns
the filename of the new created index file.  The converted index is only
temporary, and all write access is useless.

   Usage example:

     my $newindex = Netscape::Cache::convert_185_2xx($indexfile);
     my $o = new Netscape::Cache -index => $newindex;

Netscape::Cache::Object
=======================

   next_object and get_object return an object of the class
Netscape::Cache::Object. This object is simply a hash, which members have
to be accessed directly (no methods).

   An example:

     $o = $cache->next_object;
     print $o->{'URL'}, "\n";

URL
     The URL of the cached object

COMPLETE_URL
     The complete URL with the query string attached (only Netscape 4.x).

CACHEFILE
     The filename of the cached URL in the cache directory. To construct
     the full path use ($cache is a *Netscape::Cache* object and $o a
     Netscape::Cache::Object object)

          $cache->{'CACHEDIR'} . "/" . $o->{'CACHEFILE'}

CACHEFILE_SIZE
     The size of the cache file.

CONTENT_LENGTH
     The length of the cache file as specified in the HTTP response header.
     In general, SIZE and CONTENT_LENGTH are equal. If you interrupt a
     transfer of a file, only the first part of the file is written to the
     cache, resulting in a smaller CONTENT_LENGTH than SIZE.

LAST_MODIFIED
     The date of last modification of the URL as unix time (seconds since
     epoch). Use

          scalar localtime $o->{'LAST_MODIFIED'}

     to get a human readable date.

LAST_VISITED
     The date of last visit.

EXPIRE_DATE
     If defined, the date of expiry for the URL.

MIME_TYPE
     The MIME type of the URL (eg. text/html or image/jpeg).

ENCODING
     The encoding of the URL (eg. x-gzip for gzipped data).

CHARSET
     The charset of the URL (eg. iso-8859-1).

NS_VERSION
     The version of Netscape which created this cache file (3 for Netscape
     2.x and 3.x, 4 for Netscape 4.0x and 5 for Netscape 4.5).

AN EXAMPLE PROGRAM
==================

   This program loops through all cache objects and prints a HTML-ified
list.  The list is sorted by URL, but you can sort it by last visit date
or size, too.

     use Netscape::Cache;

     $cache = new Netscape::Cache;

     while ($o = $cache->next_object) {
         push(@url, $o);
     }
     # sort by name
     @url = sort {$a->{'URL'} cmp $b->{'URL'}} @url;
     # sort by visit time
     #@url = sort {$b->{'LAST_VISITED'} <=> $a->{'LAST_VISITED'}} @url;
     # sort by mime type
     #@url = sort {$a->{'MIME_TYPE'} cmp $b->{'MIME_TYPE'}} @url;
     # sort by size
     #@url = sort {$b->{'CACHEFILE_SIZE'} <=> $a->{'CACHEFILE_SIZE'}} @url;

     print "<ul>\n";
     foreach (@url) {
         print
           "<li><a href=\"file:",
           $cache->{'CACHEDIR'}, "/", $_->{'CACHEFILE'}, "\">",
           $_->{'URL'}, "</a> ",
     	  scalar localtime $_->{'LAST_VISITED'}, "<br>",
           "type: ", $_->{'MIME_TYPE'},
     	  ",size: ", $_->{'CACHEFILE_SIZE'}, "\n";
     }
     print "</ul>\n";

FORMAT OF index.db
==================

   Here is a short description of the format of index.db. All integers are
in VAX byte order (little endian). Time is specified as seconds since
epoch.

     Key:

     Offset  Type/Length  Description

     0       long         Length of key entry
     4       long         Length of URL with trailing \0
     8       string       URL (null-terminated)
     +0      string       filled with \0

     Value:

     Offset  Type/Length  Description

     0       long         Length of value entry
     4       long         A version number (see NS_VERSION)
     8       long         Last modified
     12      long         Last visited
     16      long         Expire date
     20      long         Size of cachefile
     24      ...          Unknown
     29      long         Length of cache filename with trailing \0
     33      string       Cache filename (null-terminated)
     +0      ...          Unknown
     +33     long         Length of mime type with trailing \0
     +37     string       Mime type (null-terminated)
     +0      long         Length of content encoding with trailing \0
     +4      string       Content encoding (null-terminated)
     +0      long         Length of charset with trailing \0
     +4      string       Charset (null-terminated)
     +0      ...          Unknown
     +1      long         Content length
     +5      long         Length of the complete URL with trailing \0
     +9      string       Complete URL (null-terminated)

ENVIRONMENT
===========

   The *Netscape::Cache* module examines the following environment
variables:

HOME
     Home directory of the user, used to find Netscape's preferences
     (`$HOME/.netscape'). Otherwise, if not set, retrieve the home
     directory from the passwd file.

BUGS
====

   There are still some unknown fields (_XXX_FLAG_{2,3,4}).

   You can't use delete_object while looping with next_object. See the
question "What happens if I add or remove keys from a hash while iterating
over it?" in Perlfaq4 (perl.info).

   *keys()* or *each()* on the tied hash are slower than the object
oriented equivalents next_object or next_url.

SEE ALSO
========

   See Netscape/History,

AUTHOR
======

   Slaven Rezic <eserte@cs.tu-berlin.de>

   Thanks to: Fernando Santagata <lac0658@iperbole.bologna.it>

COPYRIGHT
=========

   Copyright (c) 1997 Slaven Rezic. All rights reserved.  This module is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

object class for accessing Netscape history database
****************************************************

NAME
====

   Netscape::History - object class for accessing Netscape history database

SYNOPSIS
========

     use Netscape::History;

     $history = new Netscape::History();
     while (defined($url = $history->next_url() ))
     {
     }

DESCRIPTION
===========

   The Netscape::History module implements an object class for accessing
the history database maintained by the Netscape web browser.  The history
database keeps a list of all URLs you have visited, and is used by
Netscape to change the color of URLs which you have previously visited,
for example.

   With this module, you can get at the URLs stored in a Netscape history
file, delete URLs, and add new ones. With the associated
`Netscape::HistoryURL' module you can access the information which is
associated with each URL.

   *Please Note:* the database format for the browser history was changed
with Netscape 4. Previously only the time of most recent visit was
available; now you can also get at the time of your first visit, the
number of visits, the title of the referenced page, and another value.

CONSTRUCTOR
-----------

     $history = Netscape::History->new();

   This creates a new instance of the Netscape::History object class.  You
can optionally pass the path to the history database as an argument to the
constructor, as in:

     $history = Netscape::History->new('/home/bob/.netscape/history.db');

   If you do not specify the file, then the constructor will use:

     $HOME/.netscape/history.db

   If the Netscape history database does not exist, a warning message will
be generated, and the constructor will return undef.

METHODS
=======

   The Netscape::History class implements the following methods:

   * get_url - get a specific URL from your history

   * rewind - reset history database to first URL

   * next_url - get next URL from your history

   * delete_url - remove a URL from your history

   * add_url - add a URL to the history file

   * close - close the history database

   Each of the methods is described separately below.

get_url - get a specific URL from your history
----------------------------------------------

     $url = $history->get_url( URL );

   This method is used to extract information about a specific URL from
your history database.

   This method takes a URL (which could be just a text string, or an
object of class URI::URL) and returns an instance of Netscape::HistoryURL.

next_url - get the next URL from your history database
------------------------------------------------------

     $url = $history->next_url();

   This method returns the next URL from your history database.  If you
want to process all URLs in the database, you should call the rewind
method before looping over all URLs.

   The URL returned is an instance of the Netscape::HistoryURL class,
which works just like an instance of URI::URL, but provides an extra
methods, as described in the documentation for Netscape::HistoryURL.

delete_url - remove a URL from the history database
---------------------------------------------------

     $history->delete_url($url);

   This method is used to remove a URL from your history database.  The
URL passed can be a simple text string with the URL, or an instance of
Netscape::HistoryURL, URI::URL, or any other class which can be rendered
into a string.

add_url - add a URL to the history database
-------------------------------------------

     $history->add_url( URL );

   This method is used to add a URL to a history database.  This might be
useful if you are merging information from multiple history databases, for
example.

   If the URL passed is an instance of Netscape::HistoryURL, then the
information available will be stored.

   If the URL is specified as a text string, is derived from URI::URL,
then a Netscape::HistoryURL will be created with the following:

     LAST   = current time
     FIRST  = current time
     COUNT  = 1
     EXPIRE = 1
     TITLE  = ''

   If the EXPIRE field is not set to 1, then it won't appear in Netscape's
history window. Not really sure why :-)

rewind - reset internal URL pointer to first URL in history
-----------------------------------------------------------

     $history->rewind();

   This method is used to move the history database's internal pointer to
the first URL in your history database.  You don't need to bother with
this if you have just created the object, but it doesn't harm anything if
you do.

close - close the history database
----------------------------------

     $history->close();

   This closes the history database. The destructor will do this
automatically for you, so most of time you don't actually have to bother
calling this method explicitly. Good programming style says you should
though :-)

EXAMPLES
========

DISPLAY CONTENTS OF HISTORY
---------------------------

   The following example illustrates use of this module, and the
*visit_time()* method of the URLs returned.  The program will list all
URLs visited, along with visit time.  The Date::Format module is used to
format the visit time.

     #!/usr/bin/perl -w

     use Netscape::History;
     use Date::Format;
     use strict;

     my $history;
     my $url;

     $history = new Netscape::History;
     while (defined($url = $history->next_url() ))
     {
         print "$url :\n";
         print "    First  : ", ctime($url->first_visit_time());
         print "    Last   : ", ctime($url->last_visit_time());
         print "    Count  : ", $url->visit_count(), "\n";
         print "    Expire : ", $url->expire(), "\n";
         print "    Title  : ", $url->title(), "\n";
     }
     $history->close();

MERGE TWO HISTORY FILES
-----------------------

   The following example illustrates use of the add_url method to merge
two history databases. We read all URLs from `history2.db', and merge them
into `history1.db', overwriting any duplicates.

     $history1 = new Netscape::History("history1.db");
     $history2 = new Netscape::History("history2.db");
     while (defined($url = $history2->next_url() ))
     {
         $history1->add_url($url);
     }
     $history1->close();
     $history2->close();

SEE ALSO
========

See Netscape/HistoryURL,
     When you call the `next_url' in this node method, you are returned
     instances of this class.

See DB_File,
     The Netscape history file is just a Berkeley DB File, which we access
     using the DB_File module. You can use a different DB_File compatible
     library (such as `DB_File::SV185') by running

          use Netscape::History dblib => 'DB_File::SV185'

     in which case you are only depending on the specified library and not
     DB_File.

See URI/URL,
     The underlying class for Netscape/HistoryURL,
     which provides the mechanisms for manipulating
     URLs.

See Date/Format,
     Functions for formatting time and date in strings.

AUTHOR
======

   Neil Bowers <neilb@cre.canon.co.uk>, and Richard Taylor
<rit@cre.canon.co.uk>.

COPYRIGHT
=========

   Copyright (c) 1997-2000 Canon Research Centre Europe. All rights
reserved.  This module is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

URI::URL subclass with Netscape history information
***************************************************

NAME
====

   Netscape::HistoryURL - URI::URL subclass with Netscape history
information

SYNOPSIS
========

     use Netscape::HistoryURL;

     $url = new Netscape::HistoryURL('http://foobar.com/',
                                     LAST, FIRST, COUNT, EXPIRE, TITLE);

DESCRIPTION
===========

   The `Netscape::HistoryURL' module subclasses URI/URL, to
provide a URL class with methods for accessing the information which is
stored in Netscape's *history database*.

   The history database is used to keep track of all URLs you have visited.
This is used to color previously visited URLs different, for example.  The
information stored in the history database depends on the version of
Netscape being used.

CONSTRUCTOR
===========

     $object = new Netscape::HistoryURL( URL,
                                         LAST, FIRST, COUNT, EXPIRE, TITLE );

   This creates a new instance of the Netscape::HistoryURL object class.
This supports all the methods supported by the URI::URL class.  Please see
the documentation for that module.

   The first argument passed is a string which contains a valid URL.  The
remaining arguments are information (usually) extracted from Netscape's
history database.

   *LAST* is the time the URL was last visited, and FIRST is the time when
the URL was first visited. *COUNT* is the number of times you have visited
the URL. We're not really sure what *EXPIRE* is yet.  TITLE is the title
of the referenced page.

   You will normally not use the constructor yourself; it is usually
invoked by the `next_url()' method of the Netscape::History class.

METHODS
=======

   The *Netscape::HistoryURL* class supports all methods of the URI::URL
class, and additional methods as described below.  Please see the
documentation for URI::URL for details of the other methods supported.

visit_time - return the time of last visit
------------------------------------------

     $time = $url->visit_time();

   This routine is provided for backwards compatibility with the previous
versions of this module. You should use `last_visit_time()' instead.

first_visit_time - the time you first visited the URL
-----------------------------------------------------

     $time = $url->first_visit_time();

   This method returns the time you first visited the URL, in seconds
since the last epoch.  This can then be used with any of the standard
routines for formatting as a string.  The following example uses ctime(),
from the Date::Format module:

     print "Time of last visit for $url : ", ctime($url->first_visit_time);

last_visit_time - the time you last visited the URL
---------------------------------------------------

     $time = $url->last_visit_time();

   This method returns the time you last (most recently) visited the URL,
in seconds since the last epoch.

title - the title of the associated page
----------------------------------------

     $title = $url->title();

   This method returns the title of the referenced page, if one was
available. The value will be undef otherwise.

visit_count - the number of times you have visited the page
-----------------------------------------------------------

     $count = $url->visit_count();

   This method returns the number of times you have visited the page.

expire - the expire value for the URL
-------------------------------------

     $expire = $url->expire();

   This method returns the expire values which is stored for the URL.  We
don't know what this is for yet, or the right way to interpret it.

SEE ALSO
========

Netscape::History
     An object class for accessing the Netscape history database.

URI::URL
     Base-class, which provides heaps of functionality.

AUTHOR
======

   Neil Bowers <neilb@cre.canon.co.uk> and Richard Taylor
<rit@cre.canon.co.uk>.

COPYRIGHT
=========

   Copyright (c) 1997-2000 Canon Research Centre Europe. All rights
reserved.  This module is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

emulate perl CGI programming under nsapi_perl
*********************************************

NAME
====

   Netscape::Registry - emulate perl CGI programming under nsapi_perl

SYNOPSIS
========

   In `obj.conf'

     NameTrans fn="pfx2dir"
         from="/perl" dir="/full/path/to/perl" name="perl"

     <Object name="perl">
     ObjectType fn="force-type" type="application/perl"
     Service fn="nsapi_perl_handler" module="Netscape::Registry"
     </Object>

DESCRIPTION
===========

   This module allows CGI programs written in Perl to be run within the
Netscape httpd server process.  This provides a large performance boost by
reducing overhead from the normal fork/exec/compile process for Perl CGI
programs.  Netscape::Registry is loaded into the server by nsapi_perl, the
Perl interface to the Netscape httpd API.

   For the full details of nsapi_perl, see `nsapi_perl' in this node.
Suffice it to say here that nsapi_perl provides a mechanism by which a Perl
interpreter is embedded into a Netscape server.  The NSAPI can then be
programmed to in Perl rather than in C.  This is achieved by placing the
appropriate hooks in the server configuration files; nsapi_perl will then
call whatever Perl subroutines you wish at various stages of processing a
request from a client.

   This module was inspired by and derived from Apache::Registry, which
provides the same functionality for the Apache web server.

USAGE
=====

   Basically you need to tell your Netscape server that all files
underneath a certain directory, or ending with a certain suffix, are to be
handled during the Service stage of the transaction by the Perl module
*Netscape::Registry*.  This generally involves editing the file
`obj.conf'; see `nsapi_perl' in this node and your server's documentation
for full details.  See also `' in this node.

   After this initial setup, it's essentially CGI programming as per
normal.  However, since your scripts are actually run in the server
process, it's prudent to avoid the use of global variables since they may
by left around after your script has finished.

   Netscape::Registry works with Lincoln Stein's CGI.pm module but you
should use version 2.36 or more recent; earlier versions may not clean up
global variables properly.

   Compile and run-time errors from your scripts are written to the
server's error log.

   See `' in this node for a summary of (some) known bugs.

INTERNALS
=========

   The first request for a given file causes the file to be compiled (by
eval()) into a subroutine whose package is is unique to that file.  The
modification time and length of the source file are then stored in a
global hash.

   The subroutine is then executed by a statement like this:

     eval {package->subroutine};

   Each subsequent request for the file causes Netscape::Registry to check
the time stamp and size of the file.  If the file has changed, it is
recompiled and then executed.  If the file has not changed, it is executed
immediately.

   Standard input and output are tie()d to the Netscape::Server::Socket
class.  This enables your script's output to be sent to the client.  It
also lets your script read the content of POST-type requests on the
standard input (but don't do this yourself; let CGI.pm take care of it for
you).

   The perl built-in exit() function is redefined to be a mutation of
die() - and hence trapable by the above eval() - so that it doesn't cause
grief for the server.

ENVIRONMENT
===========

   Netscape::Registry attempts to provide the same environment as for
normal CGI, but at the time of writing there are some differences.

AUTH_TYPE
     This variable is the same as under regular CGI.  It is only defined if
     the program being accessed is under access control.

CONTENT_LENGTH
     This variable is the same as under regular CGI.

CONTENT_TYPE
     This variable is the same as under regular CGI.

GATEWAY_INTERFACE
     This variable is defined as *CGI/1.1; nsapi_perl/x.y* where x and y
     are respectively the major and minor version numbers of nsapi_perl.

HTTPS
     This variable is currently hardcoded to the value OFF.  Let the
     author know if this is a problem.

     These variables, which represent the header lines from the client's
     request header, are defined the same as they would be under regular
     CGI.

PATH
     This variable is currently not defined under nsapi_perl but it is
     under (at least some of) Netscape's implementations of CGI.  I don't
     think it *should* be defined under CGI, so if you've come to rely on
     it, that's your problem :-)

PATH_INFO
     This variable is the same as under regular CGI.

PATH_TRANSLATED
     Under Netscape's implementation of CGI, this variable (if defined) is
     PATH_INFO appended to the server's document root.  Under nsapi_perl,
     this variable (if defined) is PATH_INFO appended to the full path to
     the script.  One of these implementations is probably in error.

QUERY_STRING
     This variable is the same as under regular CGI.

REMOTE_ADDR
     This variable is the same as under regular CGI.

REMOTE_HOST
     This variable is the same as under regular CGI.

REQUEST_METHOD
     This variable is the same as under regular CGI.

REMOTE_USER
     This variable is the same as under regular CGI.  It is only defined if
     the program being accessed is under access control.

SCRIPT_NAME
     This variable is the same as under regular CGI.

SERVER_NAME
     This variable is currently undefined under nsapi_perl.  This is a bug.

SERVER_PORT
     This variable is currently undefined under nsapi_perl.  This is a bug.

SERVER_PROTOCOL
     This variable is the same as under regular CGI.

SERVER_SOFTWARE
     This variable is currently undefined under nsapi_perl.  This is a bug.

SERVER_URL
     This variable is currently undefined under nsapi_perl.  This is a bug.

BUGS
====

   Command-line switches on your CGI scripts are currently ignored by
nsapi_perl.  For example, if you dutifully put

     #!/usr/bin/perl -w

   at the start of your script, it will be ignored.

   See `' in this node for some important differences in environment
variables between nsapi_perl and regular CGI.

   Extension modules that dynamically load a shared object may cause you
grief.  See the section titled *DYNAMIC LOADING OF EXTENSION MODULES* in
`nsapi_perl' in this node if you suffer problems.  The good news is that
such modules are reported to work "out of the box" on Win32.

   use CGI::Carp('fatalsToBrowser') doesn't work as expected.

   CGI programs can't - or at least shouldn't - muck with @INC.

   Expect other bugs and weirdness.  Please don't get mad; just report
them to nsapi_perl mailing list: nsapi_perl@samurai.com.

AUTHOR
======

   Benjamin Sugars <bsugars@canoe.ca>

SEE ALSO
========

   perl(1), nsapi_perl, modperl, Apache::Registry

framework for integrating Perl and Netscape servers
***************************************************

NAME
====

   Netscape::Server - framework for integrating Perl and Netscape servers

SYNOPSIS
========

     use Netscape::Server;
     use Netscape::Server qw/:request_codes/;
     use Netscape::Server qw/:protocol_codes/;
     use Netscape::Server qw/:error_codes/;
     use Netscape::Server qw/:all/;

     log_error($degree, $sub, $sn, $rq, $gripe);
     func_exec($fname, $sn, $rq, $args);

DESCRIPTION
===========

   The Netscape::Server module provides a framework for other modules that
implement an interface between Perl and the Netscape Server Application
Programming Interface (NSAPI).  Netscape::Server provides definitions of
the various NSAPI constants and server functions for error logging.

   For an overview of integrating Perl and NSAPI, see `nsapi_perl' in this
node.  Suffice it to say here that nsapi_perl provides a mechanism by
which a Perl interpreter is embedded into a Netscape server.  The NSAPI can
then be programmed to in Perl rather than in C.  This is achieved by
placing the appropriate hooks in the server configuration files;
nsapi_perl will then call whatever Perl subroutines you wish at various
stages of processing a request from a client.

   Perl modules interfacing to the NSAPI will require access to the
structures and constants defined in the NSAPI C header files.  The two
structures defined in these header files that are of most interest are the
Session structure and the Request structure.  These two structures are
represented in Perl by instances of the Netscape::Server::Request and
Netscape::Server::Session classes; see their individual man pages for full
details.

   The rest of this document describes the constants and functions
declared in the NSAPI header files that are accessible through the
Netscape::Server module.

IMPORTABLE CONSTANTS
====================

   Importable from the point of view of whoever is using Netscape::Server,
that is.

   NSAPI constants of interest to Perl fall into the following categories
(for full details, see your Netscape Server documentation or the NSAPI
header files).

Request-Response Codes
----------------------

   Request-Response codes are those constants that NSAPI C functions
return to the server to tell the server what to do next.  Similarly, Perl
subroutines called from nsapi_perl should return one of these constants.

REQ_PROCEED
     Returned by a subroutine when it has performed its task without a
     problem.

REQ_NOACTION
     Returned by a subroutine when conditions indicate it is not
     appropriate for the subroutine to perform its task.

REQ_ABORTED
     Returned by a subroutine when an error has occurred an the client's
     request cannot be completed.

REQ_EXIT
     Returned by a subroutine when a read or write error to or from the
     client has occurred and no further communication with the client is
     possible.

   See `nsapi_perl' in this node for a description of how the server
behaves when a particular constant is returned from a subroutine.

Protocol-Status Codes
---------------------

   Subroutines should use these constants to set the HTTP status of the
server's response to the request.  This should be done (using the
protocol_status() method of either Netscape::Server::Session or
Netscape::server::Request) before any data is sent to the client.  These
constants have exact analogs in the definition of the http protocol itself.

PROTOCOL_OK
     Request can be fulfilled no problem.

PROTOCOL_REDIRECT
     The client making the request should be sent to another URL.

PROTOCOL_NOT_MODIFIED
     The requested object has not been modified since the date indicated by
     the client in its initial request.

PROTOCOL_BAD_REQUEST
     The request was not understandable.

PROTOCOL_UNAUTHORIZED
     The client did not supply proper authorization to access the requested
     object.

PROTOCOL_FORBIDDEN
     The client is explicitly forbidden to access the requested object.

PROTOCOL_NOT_FOUND
     The requested object could not be found.

PROTOCOL_SERVER_ERROR
     An internal server error has occurred.

PROTOCOL_NOT_IMPLEMENTED
     The server has been asked to do something it knows it cannot do.

Error-Logging Codes
-------------------

   Error-logging codes are used by subroutines when an error has occurred.
In particular, when an error occurs, the subroutine should call the
function log_error(); see `' in this node for more details.

LOG_INFORM
     An informational message.

LOG_WARN
     A warning message.

LOG_MISCONFIG
     An internal misconfiguration or permission problem.

LOG_SECURITY
     An authentication failure.

LOG_FAILURE
     A problem internal to your subroutine.

LOG_CATASTROPHE
     A non-recoverable server error.

FUNCTIONS
=========

   The following functions may be imported in to the calling package's
namespace.

log_error
          $success = log_error($degree, $sub, $sn, $rq, $gripe);

     *$degree* is one of the constants defined in `' in this node; it
     specifies the severity of your problem.  *$sub* is a string that
     should contain the name of the subroutine producing the error.  $sn
     is an instance of Netscape::Server::Session.  *$rq* is an instance of
     Netscape::Server::Request.  $gripe is an excuse for the error you have
     begat; make it a good one.

     log_error returns true if the error has been successfully logged;
     undef otherwise (Note: the log_error function for the servers I have
     access to produces different return values than what the
     documentation says I should expect.  I have built the perl log_error()
     function based on the return values I have emprically determined.  If
     Netscape changes their API to agree with the documentation, the perl
     log_error() function might break.)

func_exec
          $proceed = func_exec($fname, $sn, $rq, $args);
          $proceed = func_exec($fname, $sn, $rq);

     Call a function from the NSAPI. Returns REQ_ABORTED if no function was
     executed, or the return code of the called function. *$fname* is the
     function name, as it would appear in a directive line from obj.conf.
     $sn is an instance of Netscape::Server::Session. *$rq* is an instance
     of Netscape::Server::Request. The optional $args is a reference to a
     hash containing argument and value pairs.

     Example:

          $proceed = func_exec('find-index', $sn, $rq,
                       {'index-names' => 'my_index'});

IMPORT TAGS
===========

   A module wishing to import Netscape::Server symbols into its namespace
can use the following tags as arguments to the *use Netscape::Server* call.

:request_codes
     Import the constants request-response codes like REQ_PROCEED,
     REQ_NOACTION, etc.

:protocol_codes
     Import the protocol-status codes like PROTOCOL_OK, PROTOCOL_REDIRECT,
     etc.

:error_codes
     Import the error-logging codes like LOG_INFORM, LOG_WARN, etc.  This
     tag also imports the *log_error()* function.

:all
     Import all constant symbols, the *log_error()* and *func_exec()*
     functions.

AUTHOR
======

   Benjamin Sugars <bsugars@canoe.ca>

   Contributions from Steve Nielsen <spn@enteract.com> and Olivier Dehon
<dehon_olivier@jpmorgan.com>.

SEE ALSO
========

   perl(1), nsapi_perl, Netscape::Server::Session,
Netscape::Server::Request

Perl interface to Netscape server Request
*****************************************

NAME
====

   Netscape::Server::Request - Perl interface to Netscape server Request

SYNOPSIS
========

     package Netscape::Server::Something;
     use Netscape::Server qw/:all/;

     sub handler {
         my($pb, $sn, $rq) = @_;
         ...
         $auth_type = $rq->auth_type;
         $path_info = $rq->path_info;
         $query_string = $rq->query_string;
         $remote_user = $rq->remote_user;
         $request_method = $rq->request_method;
         $server_protocol = $rq->server_protocol;
         $user_agent = $rq->user_agent;
         $vars = $rq->vars;
         $reqpb = $rq->reqpb;
         $headers = $rq->headers;
         $srvhdrs = $rq->srvhdrs;
         $rq->protocol_status($sn, $status, $reason);
         $proceed = $rq->protocol_start_response($sn, $rq);
         ...
     }

DESCRIPTION
===========

   The Netscape::Server::Request class provides a Perl-object interface to
the Netscape Server API Request structure.  Instances of the
Netscape::Server::Request structure are passed as arguments to all Perl
subroutines that are executed by a Netscape server that has been
integrated with Perl using nsapi_perl.

   For an overview of integrating Perl and NSAPI, see `nsapi_perl' in this
node.  Suffice it to say here that nsapi_perl provides a mechanism by
which a Perl interpreter is embedded into a Netscape server.  The NSAPI can
then be programmed to in Perl rather than in C.  This is acheived by
placing the appropriate hooks in the server configuration files;
nsapi_perl will then call whatever Perl subroutines you wish at various
stages of processing a request from a client.

   When a Perl subroutine is called by nsapi_perl, it is passed three
arguments:

     my($pb, $sn, $rq) = @_;

   *$pb* is a reference to hash to the *key=value* pairs passed to the
argument from the server configuration files; see `nsapi_perl' in this
node for more details.  $sn is an instance of Netscape::Server::Session
which has its own man page. *$rq* is an instance of
Netscape::Server::Request and is the subject of the rest of this document.

OBJECT ABSTRACTION
==================

   A request in the world of the NSAPI is an entity that encapsulates the
header data sent from the client and header data sent back by the server
during an http transaction. In addition, information internal to the
server generated in during a transaction is considered part of a request.
In the NSAPI all this information is maintained in a C structure called a
Request.

   Netscape::Server::Request provides a Perl interface to the Request
structure.  It also provides methods that cause the server to perform an
action based on the current state of the request.

   Some Netscape::Server::Request methods require that an instance of
Netcape::Server::Session be passed as an argument.  You will find that
those methods requiring this will have a synonym method defined in
Netscape::Server::Session.  This is so you don't have to remember whether
such a method is to be written as

     $rq->method($sn);

   or

     $sn->method($rq);

   where $rq is an instance of Netscape::Server::Request and $sn is an
instance of Netscape::Server::Session.  Either method call will do the
same thing.

INSTANCE METHODS
================

   Netscape::Server::Request methods can be divided into those that return
request attributes, those that access server variables, and those that
perform actions.

Request Attributes
------------------

   These methods return or set attributes of the request.

auth_type
          $auth_type = $rq->auth_type($type);

     With no arguments returns the authorization type of the request.  This
     will either be 'basic' if authorization has been provided by the
     client or undef if the client provided no authorization.  The $type
     argument sets the authorization to the value of $type.

path_info
          $path_info = $rq->path_info($path);

     With no arguments returns the extra path information appended to the
     URI of the request.  Note that this may not be defined during the
     initial stages of processing a request; usually it is defined by
     NameTrans directives.  The optional argument allows you to set the
     extra path information.

query_string
          $query_string = $rq->query_string($path);

     With no arguments returns the query string information appended to the
     URI of the request.  Note that this may not be defined during the
     initial stages of processing a request; usually it is defined by
     NameTrans directives.  The optional argument allows you to set the
     query string information.

remote_user
          $remote_user = $rq->remote_user($user);

     With no arguments returns the remote user as determined from http
     authentication.  If no authentication has been provided with the
     request this will be undef.  The optional argument allows you to set
     the remote user.

request_method
          $request_method = $rq->request_method($method);

     With no arguments returns the request method of the request.  This
     will probably be one of GET, POST, or HEAD.  The optional argument
     allows you to set the request method.

server_protocol
          $server_protocol = $rq->server_protocol($protocol);

     With no arguments returns something like "HTTP/1.0", or whatever
     protocol the server is using to process the request.  The optional
     argument allows you to set the server protocol, although I'm not sure
     how this affects server internals.

user_agent
          $user_agent = $rq->user_agent($agent);

     With no arguments returns the value sent by the browser in the
     "User-Agent" field of the http request header.  The optional argument
     allows you to set the user agent.

Server Variable Methods
-----------------------

   These methods allow you to work with the variables the server uses when
constructing a response to a request.  Each such variable is basically a
key=value pair.  The variables are grouped into 4 different categories.
Each category of variable is accessed using a method specific to that
category.

vars
     This method accesses server working variables.

          $vars = $rq->vars;
          $vars = $rq->vars($key);
          $vars = $rq->vars($key, $value);

     With no arguments returns a reference to hash containing the names and
     values of server working variables for this request.  Server working
     variables are internal variables set up by the server during the
     various stages of processing a request.  These variables describe
     things like the document root directory for the server, the full path
     to the requested file, and so on.

     With one argument returns the value of the variable named by $key, or
     undef if the variable doesn't exist.

     With two arguments sets the variable named by $key to $value.  This is
     the "official" way for one nsapi_perl subroutine to pass data to a
     second subroutine that will run later on during the request.

     I do not know of a definitive list of server working variable names,
     but the following seem to be in common usage in NSAPI documentation
     and examples.

     *auth-type*: This variable is defined by subroutines running in the
     AuthTrans stage of processing a request.  It should be to the literal
     *basic* if http authentication is in effect for this request.

     *auth-user*: This variable is defined by subroutines running in the
     AuthTrans stage of processing a request.  It should be set to the
     username as determined from the client's authentication information if
     authentication was successful.

     *ppath*: This variable initially contains the partial path as
     determined from the clients request header.  For instance if a client
     requests *http://server/file.html*, *ppath* would initially contain
     the string */file.html*.

     name: This variable can be created by a NameTrans subroutine to
     indicate that the object named by name is to be added to the set of
     active objects processing this request.  See `nsapi_perl' in this
     node and your Netscape server documentation for what an object is in
     this context.

     path: This variable contains the full path to the requested file
     after all NameTrans subroutines have run.  If don't plan on having the
     built-in NameTrans function run in addition to your subroutines, then
     you are responsible for setting this variable to the correct value.

     You can create any number of your own variables to pass information to
     subroutines that will run later on in processing of the request.

reqpb
     This method accesses client request line variables.

          $reqpb = $rq->reqpb;
          $reqpb = $rq->reqpb($key);
          $reqpb = $rq->reqpb($key, $value);

     With no arguments returns a reference to a hash containing these
     entries:

     method: The method of the request: either GET, HEAD, or POST.

     *uri*: The URI the client asked for in the request.

     protocol: The protocol of the request, as in HTTP/1.0 or something
     like that.

     *clf-request*: The full test of the first line of the client's
     request.

     With one argument this method returns the value of the field named by
     $key.

     With two arguments this method sets the field named by $key to $value.

headers
     This method accesses client request header variables.

          $headers = $rq->headers;
          $headers = $rq->headers($key);
          $headers = $rq->headers($key, $value);

     With no arguments returns a reference to hash containing the client's
     request headers.  The keys of this hash are the names of the various
     header lines conveted to all lower case, such as *user-agent* and
     cookie.  The values are whatever text appeared in that field of the
     header.

     With one argument this method returns the value of the request header
     field named by $key.  Be sure to use the all lower-case form of the
     field name.

     With two arguments sets the value of the request header field named by
     $key (again all lower-case) to $value.  Setting one of these values is
     not an ethical thing.

srvhdrs
     This method accesses server response header variables.

          $srvhdrs = $rq->srvhdrs;
          $srvhdrs = $rq->srvhdrs($key);
          $srvhdrs = $rq->srvhdrs($key, $value);

     With no arguments returns a reference to a hash containing the
     server's response headers.  The keys of this hash are the names of
     the various header lines converted to all lower case, such as
     *content-type* and *set-cookie*.  The values are whatever text
     appears in that field of the header.

     With one argument this method returns the value of the request header
     field name dby $key.  Be sure to user the all lower-case form of the
     field name.

     With two arguments sets the value of the request header field named by
     $key (again all lower-case) to $value.  This is the "official" way to
     set the server's response headers.  Make sure you do this before
     using protocol_start_response() (a method defined below).

Action Methods
--------------

   These methods cause the server to take an action based on the current
state of the request.  They are listed in the approximate sequence in
which they should be used by the nsapi_perl subroutine.  Some of these
methods indicate success or failure by returning one of the constants
defined in the Netscape::Server module.

protocol_status
          $rq->protocol_status($sn, $status, $reason);

     Sets the HTTP status of the session.  $sn is an instance of
     Netscape::Server::Session.  $status is one of the protocol-status
     constants, like PROTOCOL_OK, that can imported from Netscape::Server.
     $reason is an optional string sent to the client in the status line.
     If $reason is omitted the server will pick one based on $status
     defaulting to "unknown reason" in degenerate cases. This method
     returns nothing.

protocol_start_response
          $proceed = $rq->protocol_start_response($sn, $status, $reason);

     Initiates an http response to the client by sending an http header
     based on the current state of $sn and $rq.  $sn is an instance of
     Netscape::Server::Session.  Returns either REQ_PROCEED, REQ_NOACTION
     or REQ_ABORTED.  If REQ_PROCEED is returned the subroutine can
     continue as normal.  If REQ_NOACTION is returned, the method
     succeeded, but the client needs no actual data (perhaps because the
     client has the data in its cache.)  If REQ_ABORTED is returned, the
     method did not succeed.

   To send data to the client see net_write() in
Netscape/Server/Session.

AUTHOR
======

   Benjamin Sugars <bsugars@canoe.ca>

SEE ALSO
========

   perl(1), nsapi_perl, Netscape::Server, Netscape::Server::Session

Perl interface to Netscape server Session
*****************************************

NAME
====

   Netscape::Server::Session - Perl interface to Netscape server Session

SYNOPSIS
========

     package Netscape::Server::Something;
     use Netscape::Server qw/:all/;

     sub handler {
         my($pb, $sn, $rq) = @_;
         ...
         $remote_host = $sn->remote_host;
         $remote_addr = $sn->remote_addr;
         ...
         $sn->protocol_status($rq, $status, $reason);
         $proceed = $sn->protocol_start_response($rq);
         $sn->net_write($message);
         $sn->net_read($length, $timeout);
         $sn->sys_net_read($length, $offset);
         ...
     }

DESCRIPTION
===========

   The Netscape::Server::Session class provides a Perl-object interface to
the Netscape Server API Session structure.  Instances of the
Netscape::Server::Session class are passed as arguments to all Perl
subroutines that are executed by a Netscape server that has been
integrated with Perl using nsapi_perl.

   For an overview of integrating Perl and NSAPI, see `nsapi_perl' in this
node.  Suffice it to say here that nsapi_perl provides a mechanism by
which a Perl interpreter is embedded into a Netscape server.  The NSAPI can
then be programmed to in Perl rather than in C.  This is achieved by
placing the appropriate hooks in the server configuration files;
nsapi_perl will then call whatever Perl subroutines you wish at various
stages of processing a request from a client.

   When a Perl subroutine is called by nsapi_perl, it is passed three
arguments:

     my($pb, $sn, $rq) = @_;

   *$pb* is a reference to hash to the key=value pairs passed to the
subroutine from the server configuration files; see `nsapi_perl' in this
node for more details.  *$rq* is an instance of Netscape::Server::Request
which has its own man page. $sn is an instance of
Netscape::Server::Session and is the subject of the rest of this document.

OBJECT ABSTRACTION
==================

   In NSAPI circles, "a session is the time between the opening and the
closing of the connection between the client and the server", quoting the
Netscape server documentation.  The NSAPI stores information about a
session in a C structure called Session. This information includes the
client host's IP address and hostname, socket and buffer information about
the connection to the client, and parameters related to the client's
ability to transmit data encrypted through SSL.

   Netscape::Server::Session exposes these properties to nsapi_perl
subroutines through instance methods.  Since these properties apply
session-wide, these properties are read-only.

   In addition to allowing access to these properties, other
Netscape::Server::Session instance methods cause the server to perform
actions for the Session.  For example, the *net_write()* method sends a
message to the client.

   Some methods require that an instance of Netscape::Server::Request be
passed as an argument.  Those that do will also have synonyms in the
Netscape::Server::Request class so that you don't have to remember whether
the method is to be written as

     $sn->method($rq);

   or

     $rq->method($sn)

   where $sn is an instance of Netscape::Server::Session and $rq is an
instance of Netscape::Server::Request. Either method call will do the same
thing.

INSTANCE METHODS
================

   Netscape::Server::Session instance methods can be divided into those
that return session attributes and those that perform actions.

Session Attributes
------------------

remote_host
          $remote_host = $sn->remote_host;

     Returns the hostname of the client's host.  Returns undef if the
     hostname cannot be resolved.

remote_addr
          $remote_addr = $sn->remote_addr;

     Returns the IP address of the client's host.

Session Actions
---------------

   These methods are listed in the approximate sequence in which they
should be used by the nsapi_perl subroutine. Some of these methods
indicate success or failure by returning one of the constants defined in
the Netscape::Server module.

protocol_status
          $sn->protocol_status($rq, $status, $reason);

     Set the HTTP status of the session.  $rq is an instance of
     Netscape::Server::Request.  $status is one of the protocol-status
     constants, like PROTOCOL_OK, that can imported from Netscape::Server.
     $reason is an optional string sent to the client in the status line.
     If $reason is omitted the server will pick one based on $status
     defaulting to "unknown reason" in degenerate cases. This method
     returns nothing.

protocol_start_response
          $proceed = $sn->protocol_start_response($rq);

     Initiates an http response to the client by sending an http header
     based on the current state of $sn and $rq.  $rq is an instance of
     Netscape::Server::Request.  Returns either REQ_PROCEED, REQ_NOACTION
     or REQ_ABORTED.  If REQ_PROCEED is returned the subroutine can
     continue as normal.  If REQ_NOACTION is returned, the method
     succeeded, but the client needs no actual data (perhaps because the
     client has the data in its cache.)  If REQ_ABORTED is returned, the
     method did not succeed.

net_write
          $sn->net_write($message);

     Sends the contents of $message to the client.  Returns the number of
     bytes actually sent (which may be less than the length of message if
     there are problems).  This seems to be the preferred method to send
     data to the client.

net_read
          $sn->net_read($length);
          $sn->net_read($length, $timeout);

     Reads $length bytes of data from the body of this Session's http
     request. If $timeout is specified, its default value of 10 seconds is
     overridden. In the event of an error, $! is set to reflect errno.

sys_net_read
          $sn->sys_net_read($buffer, $length, $offset);

     Reads $length bytes of data from the body of this Session's http
     request into $buffer.  If $offset is specified, the content read will
     will written to $buffer starting at position $offset in $buffer.
     $buffer will grow or shrink as necessary. It returns the number of
     bytes read. This method can be used to read HTML form data sent to
     the server by a client; see, for instance, the READ method in
     Netscape::Server::Socket.

AUTHOR
======

   Benjamin Sugars <bsugars@canoe.ca>

   Contributions by Olivier Dehon <dehon_olivier@jpmorgan.com>.

SEE ALSO
========

   perl(1), nsapi_perl, Netscape::Server, Netscape::Server::Request

Netscape httpd/client socket class
**********************************

NAME
====

   Netscape::Server::Socket - Netscape httpd/client socket class

SYNOPSIS
========

     use Netscape::Server::Socket;
     tie(*FILEHANDLE, 'Netscape::Server::Socket', $sn, $rq);

DESCRIPTION
===========

   Netscape::Server::Socket provides a perl implementation of the socket
connection between the Netscape httpd and clients connecting to the
server.  It is intended to be used by nsapi_perl modules that wish to send
or receive data to a client.

   For the full details of nsapi_perl, see `nsapi_perl' in this node.
Suffice it to say here that nsapi_perl provides a mechanism by which a Perl
interpreter is embedded into a Netscape server.  The NSAPI can then be
programmed to in Perl rather than in C.  This is achieved by placing the
appropriate hooks in the server configuration files; nsapi_perl will then
call whatever Perl subroutines you wish at various stages of processing a
request from a client.

   The remainder of this document describes the usage and internals of
Netscape::Server::Socket.

USAGE
=====

   Users of Netscape::Server::Socket will generally want to tie a
filehandle to the class.  Subsequent transactions on that filehandle will
then read to or from the client.  Indeed, at this time, all of
Netscape::Server::Socket's class and instance methods are for use by tie().

   Generally, it is therefore sufficient to call tie() as follows

     tie(*FILEHANDLE, 'Netscape::Server::Socket', $sn, $rq);

   *FILEHANDLE is the typeglob of the filehandle you wish to tie; $sn is an
instance of Netscape::Server::Session; $rq is an instance of
Netscape::Server::Request.

   The above call will return an instance Netscape::Server::Socket if
successful.  Most likely you will not need to call instance methods on
this object.  Rather, you will let the magic of tie() call the appropriate
instance methods whenever a read or write is attempted on the tied
filehandle.

   Currently the following actions on the tied filehandle are supported:

print FILEHANDLE LIST
printf FILEHANDLE FORMAT, LIST
read FILEHANDLE,SCALAR,LENGTH,OFFSET
sysread FILEHANDLE,SCALAR,LENGTH,OFFSET
   At this time there is no support for reading from the filehandle using
the diamond operator or using getc().  In other words, doing a

     my $line = <FILEHANDLE>
     my $char = getc(FILEHANDLE);

   for a tied FILEHANDLE will not work.

   Most of you can stop reading at this point; if you're interested in the
internals of the module, read on.

METHODS
=======

   The user need not call these methods directly but can rely on the magic
of tie() to do that for them.  The methods are listed here for
completeness.

Constructor
-----------

TIEHANDLE
          my $socket = TIEHANDLE Netscape::Server::Socket, $sn, $rq;

     The TIEHANDLE method returns an instance of Netscape::Server::Socket.
     $sn is an instance of Netscape::Server::Session.  $rq is an instance
     of Netscape::Server::Request.

Instance Methods
----------------

PRINT
          $socket->PRINT(@stuff);

     Causes @stuff to be sent to the client.  Until a completely empty line
     is received, the data is assumed to comprise the http header.
     Subsequent data is assumed to comprise the http message body.  In
     other words, things like

          $socket->PRINT("Content-type: text/plain\n",
                         "\n",
                         "This came from the server\n");

     will work as expected.

PRINTF
          $socket->PRINTF($format, @stuff);

     Works like the perl built-in printf function, but sends the data to
     the client.  This is just a wrapper around PRINT(), so it has the same
     behaviour regarding the http header/body.

READ
          $socket->READ($scalar, $length, $offset);

     Attempts to read $length bytes of data from the body of the client's
     request to the server starting at $offset.  Stores the results in
     $scalar.  Returns the actual number of bytes read.

     Note that this method does not read data from the header of the
     client's request.  To do this, look at the Netscape::Server::Request
     man page.

     Note also that this method does not (yet) return undef in the case of
     an I/O error.  This is an ugly bug that will be fixed in future
     release.

AUTHOR
======

   Benjamin Sugars <bsugars@canoe.ca>

SEE ALSO
========

   perl(1), perltie(3)

   nsapi_perl, Netscape::Server::Session, Netscape::Server::Request

Perl extension for manipulating IPv4 addresses.
***********************************************

NAME
====

   Network::IPv4Addr - Perl extension for manipulating IPv4 addresses.

SYNOPSIS
========

     use Network::IPv4Addr qw( :all );

     my ($ip,$cidr) = ipv4_parse( "127.0.0.1/24" );
     my ($ip,$cidr) = ipv4_parse( "192.168.100.10 / 255.255.255.0" );

     my ($net,$msk) = ipv4_network( "192.168.100.30" );

     my $broadcast  = ipv4_broadcast( "192.168.100.30/26" );

     if ( ipv4_in_network( "192.168.100.0", $her_ip ) ) {
       print "Welcome !";
     }

     etc.

DESCRIPTION
===========

   Network::IPv4Addr provides functions for parsing IPv4 addresses both in
traditional address/netmask format and in the new CIDR format.  There are
also methods for calculating the network and broadcast address and also to
see check if a given address is in a specific network.

ADDRESSES
=========

   All of Network::IPv4Addr functions accepts addresses in many format.
The parsing is very liberal.

   All these addresses would be accepted:

     127.0.0.1
     192.168.001.010/24
     192.168.10.10/255.255.255.0
     192.168.30.10 / 21
     10.0.0.0 / 255.0.0.0
     255.255.0.0

   Those wouldn't though:

     272.135.234.0
     192.168/16

   Most functions accepts the address and netmask or masklength in the
same scalar value or as separate values. That is either

     my($ip,$masklength) = ipv4_parse($cidr_str);
     my($ip,$masklength) = ipv4_parse($ip_str,$msk_str);

USING
=====

   No functions are exported by default. Either use the :all tag to import
them all or explicitly import those you need.

FUNCTIONS
=========

ipv4_parse
          my ($ip,$msklen) = ipv4_parse($cidr_str);
          my $cidr = ipv4_parse($ip_str,$msk_str);
          my ($ip) = ipv4_parse($ip_str,$msk_str);

     Parse an IPv4 address and in scalar context the address in CIDR
     format and in an array context the address and the mask length.

     If the parameters doesn't contains a netmask or a mask length, in
     scalar context only the IPv4 address is returned and in an array
     context the mask length is undefined.

     If the function cannot parse its input, it croaks. Trap it using eval
     if don't like that.

ipv4_network
          my $cidr = ipv4_network($ip_str);
          my $cidr = ipv4_network($cidr_str);
          my ($net,$msk) = ipv4_network( $net_str, $msk_str);

     In scalar context, this function returns the network in CIDR format in
     which the address is. In array context, it returns the network
     address and its mask length as a two elements array. If the input is
     an host without a netmask of mask length, the default netmask is
     assumed.

     Again, the function croak if the input is invalid.

ipv4_broadcast
          my ($broadcast) = ipv4_broadcast($ip_str);
          my $broadcast   = ipv4_broadcast($ip_str,$msk_str);

     This function returns the broadcast address. If the input doesn't
     contains a netmask or mask length, the default netmask is assumed.

     This function croaks if the input is invalid.

ipv4_network
          my $cidr = ipv4_network($net_str);
          my $cidr = ipv4_network($cidr_sstr);
          my ($net,$msk) = ipv4_network( $ip_str, $mask_str);

     In scalar context, this function returns the network in CIDR format in
     which the address is. In array context, it returns the network
     address and its mask length as a two elements array. If the input is
     an host without a netmask or mask length, the default netmask is
     assumed.

     Again, the function croak if the input is invalid.

ipv4_in_network
          print "Yes" if ipv4_in_network( $cidr_str1, $cidr_str2);
          print "Yes" if ipv4_in_network( $ip_str1, $mask_str1, $cidr_str2 );
          print "Yes" if ipv4_in_network( $ip1, $mask1, $ip2, $msk2 );

     This function checks if the second network is contained in the first
     one and it implements the following semantics :

          If net1 or net2 is a magic address (0.0.0.0 or 255.255.255.255)
          than this function returns true.

          If net1 is an host, net2 will be in the same net only if
          it is the same host.

          If net2 is an host, it will be contained in net1 only if
          it is part of net1.

          If net2 is only part of net1 if it is entirely contained in
          net1.

     Trap bad input with eval or else.

ipv4_checkip
          if ($ip = ipv4_checkip($str) ) {
          	# Do something
          }

     Return the IPv4 address in the string or undef if the input doesn't
     contains a valid IPv4 address.

ipv4_cidr2msk
          my $netmask = ipv4_cidr2msk( $cidr );

     Returns the netmask corresponding to the mask length given in input.
     As usual, croaks if it doesn't like your input (in this case a number
     between 0 and 32).

ipv4_msk2cidr
          my $masklen = ipv4_msk2cidr( $msk );

     Returns the mask length of the netmask in input. As usual, croaks if
     it doesn't like your input.

AUTHOR
======

   Francis J. Lacoste francis.lacoste@iNsu.COM

COPYRIGHT
=========

   Copyright (c) 1999 Francis J. Lacoste and iNsu Innovations Inc.  All
rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the terms as perl itself.

SEE ALSO
========

   perl(1) ipv4calc(1).

Object for handling Usenet articles in mail or news form.
*********************************************************

NAME
====

   News::Article - Object for handling Usenet articles in mail or news
form.

SYNOPSIS
========

     use News::Article;

   See below for functions available.

DESCRIPTION
===========

   An object for representing a Usenet article (or a mail message).
Primarily written for use with mail2news and/or moderation programs.

USAGE
=====

     use News::Article;

   Article exports nothing.

   A new Article object must be created with the new method.

Article Methods
---------------

new ()
new ( SOURCE [,MAXSIZE [,MAXHEADS]] )
     Use this to create a new Article object. Makes an empty article if no
     parameters are specified, otherwise reads in an article from SOURCE
     as for read.

clone ()
     Create a new Article as an exact clone of the current one.  Returns a
     ref to the new object.

envelope ( [SENDER] )
     If SENDER is specified, sets the envelope sender to the specified
     value (which will then subsequently be used if the article is mailed).
     Returns the (new or current) envelope sender in any case.

rawheaders ()
     Returns a list (or a reference to an array if in scalar context) of
     the original header lines of the article, as read from the input
     source. Terminating newlines are not included. (Continued headers are
     returned as single strings with embedded newlines.)

header_names ()
     Returns a list of the names of all headers currently present in the
     article.

headers ([FIRST [,NEXT [,LAST]]])
     Returns a list of all header strings with no terminating newlines.
     Continued headers will have embedded newlines.

     FIRST, NEXT and LAST are optional references to arrays of header
     names. The order of the returned headers is as follows:

          - headers specified by FIRST (one value only per name)
          - headers in the order originally read in (if any)
          - headers specified by NEXT (one value only per name)
          - any remaining headers not named in LAST, sorted by name
          - headers named in LAST (all values)

headers_first (HDR...)
     Set default ordering for headers().

headers_next (HDR...)
     Set default ordering for headers().

headers_last (HDR...)
     Set default ordering for headers().

set_headers ( NAME, VALUE [, NAME, VALUE [...]] )
     For each header name supplied, replace any current occurences of the
     header with the specified value(s). Each value may be a single scalar,
     or a reference to an array of values. Returns undef without completing
     the assignments if any attempt is made to supply multiple values for a
     unique header. Undef or empty values cause the header to be deleted.
     (If an array is supplied, it is not copied.)

add_headers ( NAME, VALUE [, NAME, VALUE [...]] )
     Add new header values without affecting existing ones. Each value is
     either a single scalar, or a reference to an array of values. Returns
     undef without completing if any attempt is made to supply duplicate
     values for a unique header. (If an array reference is supplied, the
     array is copied.)

drop_headers ( NAME [, NAME [...]] )
     Delete all values of the specified header(s).

header ( NAME )
     Returns a list of values for the specified header. Returns a null list
     if the header does not exist. In scalar context, returns the first
     value found or undef.

rename_header ( SRC, DEST [, ACTION] )
     Transform the name of a header without touching the value. Fails if
     the source header does not exist. Returns undef on failure, true on
     success.

     Optional ACTION (may be "drop", "clobber", "add", or "fail"
     (default)), specifies what to do if both source and destination exist:

          ACTION     PREVIOUS DEST
          drop       unchanged      (SRC dropped)
          clobber    dropped        (SRC replaces DEST)
          add        preserved      (SRC added to DEST)
          fail       unchanged      (operation fails)

body ()
     Return the body of the article as a list of lines (no newlines), or a
     reference to an array in scalar context (the array may be modified in
     this case).

lines ()
     Returns the number of lines in the article body.

bytes ()
     Returns the total size of the article body, not counting newlines.

set_body ( BODY )
     Replace the current article body with the specified text.  Expects a
     list, each item of which is either one line, or multiple lines
     separated by newlines (but with no final newline).

add_body ( BODY )
     Append the specified text to the current article body.  Expects a
     list, each item of which is either one line, or multiple lines
     separated by newlines (but with no final newline), or a reference to
     an array of lines.

read_headers ( SOURCE, MAXSIZE )
     Read article headers (terminated by an empty line) from the specified
     source (see read for defintion of allowed sources).

     Gives up (returning undef) if more than MAXSIZE bytes are read.
     Returns the amount read.

read_body ( SOURCE, MAXSIZE )
     Read an article body from the specified source (see read). Stops at
     end of file; fails (returning undef) if MAXSIZE is reached prior to
     that point.  Returns the number of bytes read (may be 0 if the body is
     null).

     Useless trailing blank lines are removed.

read ( SOURCE [,MAXSIZE [,MAXHEADS]] )
     Reads in an article from SOURCE.

     SOURCE may be any of the following:

     - a CODE ref, which is called to return lines or chunks of data

     - an ARRAY ref, assumed to contain a list of lines with optional line
     terminators

     - a SCALAR ref, assumed to contain text with embedded newlines

     - a scalar, assumed to be a filename, which is opened and read

     - anything else is assumed to be a glob, reference to a glob, or
     reference to a filehandle, and is read from accordingly

     When reading in articles, `MAXHEADS' is the maximum header size to
     read (default 8k), and `MAXSIZE' is the maximum article body size
     (default 256k). If `MAXSIZE' is explicitly specified as 0, then no
     attempt at reading the body is made. Returns the total number of bytes
     read, or undef if either limit is reached or no headers were found.

write ( FILE )
     Write the entire article to the specified filehandle reference.

write_original ( FILE )
     Write the original headers followed by the article body to the
     specified filehandle reference.

sendmail ( [COMMAND] )
     Get or set the command and options that will be used to mail the
     article. Defaults to a system dependent value such as
     /usr/sbin/sendmail -oi -oem

mail ( [RECIPIENTS...] )
     Mails the article to the specified list of recipients, or to the
     addressed recipients in the header (To, Cc, Bcc) if none are supplied.
     Attempts to set the envelope sender to the stored envelope sender, if
     set, so unset that before mailing if you do not want this behavior.

post ( [CONN] )
     Post the article. Avoids inews due to undesirable header munging and
     unwarranted complaints to stderr. Takes an optional parameter which is
     a Net::NNTP reference.  If supplied, posts the article to it;
     otherwise opens a new reader connection and posts to that.

     Throws an exception containing the error message on failure.

ihave ( [CONN] )
     Inject the article. Takes an optional parameter which is a Net::NNTP
     reference.  If supplied, posts the article to it; otherwise opens a
     new transport connection and posts to that. All required headers must
     already be present, including Path and Message-ID.

     Throws an exception containing the error message on failure.

add_message_id ( [PREFIX [, DOMAIN] ] )
     If the current article lacks a message-id, then create one.

add_date ()
     If the current article lacks a date, then add one (in local time).

sign_pgpmoose ( GROUP, PASSPHRASE [, KEYID] )
     Signs the article according to the PGPMoose spec.  We require that
     pgp be on the path to do this.  Takes a "group" which can be either a
     newsgroup or an address, a PGP password, and an optional key id and
     returns a null list on success, the PGP error output as a list on
     failure.

     If the key id is omitted, we will assume that if the group is an
     e-mail address, the key id is that address surrounded by <>, and
     otherwise the key id will be the group with a space on either side.
     This is so that one can help PGP distinguish between the keys for
     (say) mod.config and mod.config.status.  The PGP key id should be
     something like:

          Moderator of group.name <request-address@some.host>

     The article to be signed must already have all of the headers needed
     by PGPMoose (Newsgroups, From, Subject) or this will fail. Message-ID
     is added if necessary.

verify_pgpmoose ( GROUP )
     Verifies an article signature according to the PGPMoose spec.  We
     require that pgp be on the path to do this.  Takes a "group" which can
     be either a newsgroup or an address, and an optional key id.

     Looks for a X-Auth header matching the specified group or address, and
     if found, checks the validity of the signature. If successful, returns
     the signer identity (from the PGP output), otherwise returns false.

sign_control ( KEYID, PASSPHRASE [, HEADER [...] ] )
     Signs the article in the manner used for control messages.  This is
     derived from signcontrol, written by David Lawrence, but with fewer
     sanity checks since we assume people know what they're doing.  Caveat
     programmer.

     We take a key id, a PGP password, and an optional list of extra
     headers to add to the signature.  By default, Subject, Control,
     Message-ID, Date, From, and Sender are signed. Any signed header that
     isn't present in the article will be signed with an empty value. Date
     and Message-ID are automatically added if needed.

AUTHOR
======

   Written by Andrew Gierth <andrew@erlenstar.demon.co.uk>

   Thanks to Russ Allbery <rra@stanford.edu> for comments and suggestions.

COPYRIGHT
=========

   Copyright 1997 Andrew Gierth <andrew@erlenstar.demon.co.uk>

   This code may be used and/or distributed under the same terms as Perl
itself.

derivative of News::Article for generating autoreplies
******************************************************

NAME
====

   News::AutoReply - derivative of News::Article for generating autoreplies

DESCRIPTION
===========

   Like News::Article, but must be given a reference to another article at
creation time - initialises To, In-Reply-To, References etc.  correctly as
an automatic reply.

USAGE
=====

     use News::AutoReply;

   Exports nothing.

Constructor
===========

new ( ORIGINAL )
     Construct an autoreply to a message, assuming that the Reply-To (if
     present, otherwise the From) header of `ORIGINAL' is valid.

     Returns a new Article object with no body or envelope sender, but with
     suitable headers.

     If an environment variable LOOP is defined, it is used as the contents
     of an X-Loop header added to the reply (this is useful when using this
     code in progs launched from a procmail recipe). Always preserves
     X-Loop headers in the original.

     The reference-folding code could probably be improved.

AUTHOR
======

   Andrew Gierth <andrew@erlenstar.demon.co.uk>

SOURCE
======

   Contact the author.

COPYRIGHT
=========

   Copyright 1997 Andrew Gierth <andrew@erlenstar.demon.co.uk>

   This code may be used and/or distributed under the same terms as Perl
itself.

derivative of News::Article
***************************

NAME
====

   News::FormArticle - derivative of News::Article

DESCRIPTION
===========

   Like News::Article, but designed to be constructed from a file
containing form text with substitutions.

   Currently, the source text is substituted as follows:

   Variables are denoted by $NAME or @NAME (where NAME is any simple
identifier). (The sequences $$ and @@ denote literal $ and @ characters.)
Variables of the form $NAME are expected to supply scalar values which are
interpolated; variables of the form @NAME are expected to supply lists (or
references to arrays) which are interpolated with separating newlines.

   Values of variables are found by consulting the list of sources
supplied. Each source may be either a reference to a hash, or a reference
to code.

   Source hashes may contain as values either the desired value (scalar or
reference to array), or a typeglob, or a code reference which will be
called to return the result. (Since typeglobs are allowed values, it is
possible to supply a reference to a module symbol table as a valid source.)

   Code references supplied as sources are invoked with the variable name
(including the leading $ or @) as the only parameter. In the degenerate
case, all variables accessible in the source scope may be made available
for interpolation by supplying the following as a source:

     sub { eval shift }

   If multiple sources are supplied, then each is consulted in turn until
a defined value is found.

USAGE
=====

     use News::FormArticle;

   Exports nothing.

Constructor
===========

new ( FILENAME [, SOURCE [...]] )
     Construct an article from the specified file, performing variable
     substitution with values supplied by the SOURCE parameters (see
     Description).

AUTHOR
======

   Andrew Gierth <andrew@erlenstar.demon.co.uk>

COPYRIGHT
=========

   Copyright 1997 Andrew Gierth <andrew@erlenstar.demon.co.uk>

   This code may be used and/or distributed under the same terms as Perl
itself.

derivative of News::FormArticle and News::AutoReply
***************************************************

NAME
====

   News::FormReply - derivative of News::FormArticle and News::AutoReply

DESCRIPTION
===========

   This is a "mixin" of News::FormArticle and News::AutoReply; it
generates form replies by performing substitutions on a text file.

USAGE
=====

     use News::FormReply;

   Exports nothing.

Constructor
===========

new ( ORIGINAL, FILENAME [, SOURCE [...]] )
     Construct an article as a reply to `ORIGINAL', initialised from the
     specified file, performing variable substitution with values supplied
     by the SOURCE parameters (see News::FormArticle).

     The Subject, To, References and In-Reply-To headers are setup after
     the template has been read and substituted, but a Subject header set
     in a template will not be overridden.

AUTHOR
======

   Andrew Gierth <andrew@erlenstar.demon.co.uk>

COPYRIGHT
=========

   Copyright 1997 Andrew Gierth <andrew@erlenstar.demon.co.uk>

   This code may be used and/or distributed under the same terms as Perl
itself.

Tools for gatewaying messages between news and mail.
****************************************************

NAME
====

   News::Gateway - Tools for gatewaying messages between news and mail.

SYNOPSIS
========

     use News::Gateway;
     my $gateway = News::Gateway->new (1, 'user@example.com');
     $gateway->modules ('headers', mailtonews => ['misc.test']);
     $gateway->config_file ('/path/to/config/file');
     $gateway->read (\*STDIN);
     my $error = $gateway->apply ();
     if ($error) { $gateway->error ($error) }
     $error = $gateway->post ();
     if ($error) { $gateway->error ($error) }

DESCRIPTION
===========

   This module is a collection of tools to allow gatewaying of mail
messages into newsgroups or vice versa.  It's written to be extremely
modular and extendable, so that any modification or check of incoming
messages can be dropped in.  It's intended to be usable for both a
straight gateway or a robomoderator, or even as the front end and
supporting tool set for human moderation.

   The module is intended to take input from three different sources:  an
incoming message, a set of modules that contain checks or modifications to
be performed to that message, and a configuration file that affects the
behavior of the modules.  Each module can list one or more configuration
directives that it takes, and then when those directives are encountered
in the configuration file, they're parsed and and handed off to the
module.  Then, after the message has been read in, its headers and body
are given to each module in turn, so that they can perform whatever tests
and make whatever modifications they were designed to do.

   A message is represented internally as a News::Article object that each
module has access to, allowing the headers or body to be read and
manipulated.

CONSTRUCTOR
===========

new (INTERACTIVE [, MAINTAINER [, SENDER]])
     This builds a new News::Gateway object.  `INTERACTIVE' is a true/false
     flag specifying whether the program is running interactively.  If
     true, the error() method will call die in the event of an error;
     otherwise, it will attempt to send mail to the maintainer and the
     sender of the message.  MAINTAINER is the e-mail address of the
     maintainer of the gateway, defaulting to the user the program is
     running as if not supplied.  SENDER is the envelope sender which
     should be used for all mail sent through News::Gateway, defaulting to
     MAINTAINER if not supplied.

METHODS
=======

   First, the standard methods in the order in which they are normally
called.  Some of these methods, like modules(), are normally called only
once, while others, like read(), may be called multiple times for multiple
incoming messages.  You'll almost certainly also want to read about the
config(), `config_file()', and post() directives below in `"UTILITY
MODULES"' in this node.

modules (MODULE [ => ARGUMENTS ] [, ...])
     Sets the list of modules that should be applied to each incoming
     message.  The list of modules is cumulative; in other words,
     modules() can be called multiple times to add more modules to the
     list of ones which will be applied.  This method both adds each
     supplied module name to the list of modules that will be run if
     `apply()' is called with no arguments and sets up callbacks so that
     any configuration directives that MODULE is interested in will be
     passed along to it when configuration directives are processed.

     Some modules may take arguments; if so, they can be passed in as an
     anonymous array associated with the module.  For example:

          $gateway->modules (mailtonews => ['misc.test']);

     adds mailtonews to the list of modules and passes in `misc.test' as an
     argument to it.

     Modules will be run in the order they are given to modules().

     modules() should always be called before any call to `apply()',
     config(), or `config_file()' that those modules are supposed to
     affect.

read (SOURCE [, MAXSIZE [, MAXHEAD]])
     Reads in a new message from the supplied source, which can be a file
     name, a file handle, or even an anonymous sub which will be called
     repeatedly for each line of the message until it returns undef.
     `MAXSIZE', if given, specifies the maximum size in bytes of the
     article body, and `MAXHEAD', if given, specifies the maximum size in
     bytes of the article headers.  `MAXSIZE' defaults to 256KB and
     `MAXHEAD' defaults to 8KB.

     This method returns the total number of bytes read if successful, or
     undef in the case of an error.

     This method constructs a new News::Article object and calls its
     method, so it will always support essentially the same arguments as
     the corresponding News::Article read() method.

apply (MODULES)
     This method hands the message off to each module given (if no modules
     are given, the message is given to each module registered by
     modules() in the order in which they were given to modules()) and
     lets them do whatever they wish with the article.  If a module
     returns undef, it's presumed to be successful and the message is
     given to the next module.  If a module returns a string, it's
     considered to be a failure message and `apply()' stops.

     If all modules succeed, `apply()' returns undef or the empty list.
     If a module fails, `apply()' returns a list consisting of the module
     which failed and the message it failed with in a list context; or a
     string consisting of the name of the module, a colon, a space, and
     the message it failed with in a scalar context.

     The calling script should then look at the failure message and take
     the appropriate action.

   The following additional methods are also supplied, some of which are
mostly intended for internal use.

error (ERROR)
     Handles a fatal error.  If the `INTERACTIVE' flag passed to new() was
     true, this method just calls die with the error message.  Otherwise,
     it calls `mail_error()' (part of the standard mail module), which
     attempts to mail the maintainer and the sender of the message.  If
     that fails, for whatever reason, News::Gateway calls exit with the
     right status code for a mail bounce.

     This method should be used *only* for fatal, unrecoverable errors,
     particularly when `INTERACTIVE' isn't true, since it could bounce
     mail or notify the wrong person of problems.  It's a last resort that
     goes to great lengths to try to keep the message from being lost.

get_article ()
     An accessor method that returns the underlying News::Article object.

set_article (ARTICLE)
     Takes a News::Article object and makes that the underlying message in
     that instance of News::Gateway, discarding the old one if any.

REWRITE MODULES
===============

   The following modules to perform checks or rewrites of messages are part
of the standard distribution.  To use them with a News::Gateway object,
pass them (along with anonymous arrays for their options, if any) to the
modules() method.

anykeyword
----------

   This module requires that every incoming message have at least one
keyword on the subject line.  For the purposes of this check, a keyword is
defined as anything that matches:

     /^(?:Re:\s+)?\[\S+\]/

   (in other words, something without spaces enclosed in square brackets at
the beginning of the subject line modulo any Re:).  If no keyword is found
in the incoming message, this module returns the message:

     No keyword found

   This module takes no arguments or configuration directives.

bodyheaders
-----------

   Extracts headers from the beginning of a message body and lifts them up
into the message headers.  This is to assist posters whose software makes
it difficult for them to edit the headers of their posts or mail.

   This module looks for recognized headers at the beginning of the article
body.  As long as it's seen only blank lines (possibly containing
whitespace) and recognized headers, it adds all of those headers to the
main message headers.  As soon as it finds a line that isn't a recognized
header, it stops, and if it found any headers it removes everything up to
the first non-header line from the body.

   This module takes one configuration directive:

bodyheaders HEADER [HEADER ...]
     A list of headers to look for in the beginning of the body.  The
     headers are not case sensitive, and any amount of whitespace
     (including none) is allowed after the colon.

   For example, with the directive:

     bodyheaders x-no-archive

   and a message beginning with:

     x-no-archive:yes

     Comment: hello

   an X-No-Archive header with content "yes" will be added to the message
headers and the first line of the message body after this module runs will
be the line starting with "Comment:".  Had "comment" also been listed in
the configuration directive, that header would have been lifted into the
article headers as well and this module would have continued looking.

   Whitespace on the line before the header is not allowed, and such a line
would not be recognized as a header to be lifted to the message headers.

   This module takes no arguments and cannot fail.

cleanbody
---------

   This module checks the body of an incoming article and cleans it up,
attempting to enforce standard ISO 8859-1 text.  If it's encoded in
quoted-printable, that encoding is undone.  Microsoft Word SmartQuotes are
converted into their ASCII equivalents, any Ctrl-Ms are removed, and the
module checks to make sure that the message contains no invalid characters
(outside of the standard ISO 8859-1 range) and that no lines are longer
than 79 characters.

   The messages returned by the checks in the event of failure are:

Invalid characters in body
     The body contains characters outside the range [\s!-~\xa0-\xff].

Line over 79 characters
     One or more lines in the body are over 79 characters long.

   This module takes no arguments or configuration directives.  If the
original message was in quoted-printable, it will change the
Content-Transfer-Encoding header to be "8bit".  It recognizes
quoted-printable from the MIME encoding headers.

crosspost
---------

   Limits crossposting and followups.  This module takes, in some ways, the
opposite approach from the newsgroups module; rather than listing
newsgroups which are allowed, it allows one to set a limit on the number
of groups crossposted, on the number of groups to which followups would
go, and on which groups can be crossposted to or to which followups can be
directed.

   A group can be excluded from the Newsgroups header or from the
Followup-To header in one of two ways; either messages posted to that
group or messages that direct followups to a set of newsgroups including
that group can be rejected, or that group can be silently removed from the
Newsgroups and/or Followup-To headers.  The latter behavior is generally
not recommended for robomoderators, since moderators are generally
discouraged to make decisions about where posts should be posted for the
poster.  Returning the post and asking the poster to choose a more
appropriate set of groups is generally a better approach.

   This module will remove a Followup-To header (and not add one) if its
content is/would be identical to the Newsgroups header.

   This module takes the following configuration directives:

crosspost max COUNT
     Reject any message crossposted to more than `COUNT' newsgroups.

crosspost remove|reject GROUP
     Either remove `GROUP' silently from the Newsgroups header if present
     or reject all articles crossposted to `GROUP'.

followup max COUNT
     Reject any messages that would direct followups to more than `COUNT'
     newsgroups, bearing in mind that if no Followup-To header is present,
     followups would go to all groups in the Newsgroups header.

followup remove|reject GROUP
     Either remove `GROUP' silently from the followups if present or reject
     all articles crossposted to `GROUP'.

   This module may return one of the following failure messages:

Invalid crosspost to %s
     The message was crossposted to a group mentioned in a `crosspost
     reject' directive.

Followups would go to %s
     Followups to the message would go to a group mentioned in a `followup
     reject' directive.

Excessively crossposted
     The message was crossposted to more groups than allowed by a
     `crosspost max' directive.

Followups would go to too many groups
     Followups to the message would go to more groups than allowed by a
     `followup max' directive.

   This module works with a Newsgroups header, so if other modules need to
be applied to construct the Newsgroups header, they should run before this
one.  This module takes no arguments.

headers
-------

   This module implements some general header rewriting functions,
including adding, dropping, and renaming headers and replacing header
contents.  It takes one configuration directive:

header HEADER FUNCTION [ CONTENT ]
     Specify an action on the header `HEADER'.  FUNCTION can be any of the
     following:  drop deletes a header, rename renames the original header
     to X-Original-HEADER retaining the same value, ifempty adds a header
     with content CONTENT if and only if the message doesn't already
     contain a header `HEADER', replace replaces all existing `HEADER'
     headers with one containing CONTENT, prepend adds CONTENT to the
     beginning of the first header `HEADER' or creates a new header
     `HEADER' with content CONTENT if none already exists, and reject
     returns an error if `HEADER' is present in the incoming message.

     CONTENT can contain various special variables:  $n will be replaced
     with the name of the running program, `$v' will be replaced with the
     version of News::Gateway, and $i will be replaced with a unique
     identifier formed from the current time and the process ID.  $$ will
     be replaced with `$', so to put a literal dollar sign in a header, you
     should use $$.

   For example, suppose you have a configuration file with the following
directives:

     header organization add     SNAP
     header message-id   rename
     header sender       drop
     header comment      replace $n $v
     header subject      ifempty no subject (thread id $i)

   and suppose you have an incoming message with the headers:

     Organization: Restaurant Reviews
     Message-ID: <123142@bar.org>
     Sender: foo@bar.org
     Comment: Hello
     Comment: Hello again

   After the headers module runs, the message will have a header of:

     Organization: Restaurant Reviews
     Organization: SNAP
     X-Original-Message-ID: <123142@bar.org>
     Comment: PROGRAM VERSION
     Subject: no subject (thread id ID)

   where `PROGRAM' is the name of the running program (ie, $0), VERSION is
the version of News::Gateway, and ID is a unique identifier as described
above.

   This module may fail and call error() with the following message while
reading the configuration directives:

Unknown header rewrite action %s
     A rewrite action was specified that isn't among those that are
     supported.  This probably indicates a typo.

   This module may fail in one way:

Invalid header %s
     A header that was associated with a reject action in a configuration
     directive was present in the incoming message.  Note that the header
     will be given in all lowercase.

   As a side note, if you're constructing a robomoderator for a newsgroup,
dropping or renaming the Path header in incoming messages is highly
recommended.  It turns out that some news servers will add a Path header
with their hostname before remailing the message to a moderator, and if
you keep that Path header when you post, the article will never propagate
back to the site of the original poster.

keywords
--------

   This module checks the Subject header of a message and ensures that it
starts (modulo an initial Re:) with a valid keyword.  By default, the
following keyword formats are supported:

     KEYWORD:
     KEYWORD/KEYWORD:
     [KEYWORD]
     [KEYWORD/KEYWORD]
     [KEYWORD][KEYWORD]

   If multiple keywords are given, they all have to be valid.  Keywords are
checked against a list given in a file and are case-insensitive.

   This module takes one optional argument, a reference to a sub which, if
given a subject line, returns a list of all the keywords present.  This
can be used to override the default patterns listed above.

   There is one required configuration file directive:

keywords FILENAME
     Specifies the file from which the list of valid keywords will be read.
     The file should list all valid keywords, one per line.

   Two failure messages are possible:

No keywords found
     There were no keywords in the subject header of the message.

Invalid keyword '%s'
     A keyword was found that wasn't in the list of valid keywords.

mailpath
--------

   Generates an X-Mail-Path header from the Received headers of a mail
message.  It attempts to figure out the real name of each host that the
mail passed through based on the standard comment syntax used by most
mailers, but this problem is inherently impossible to solve completely.

   X-Mail-Path is set to a !-separated list of hosts that the mail has
passed through.  If from the Received headers the name of a host appears
to be trusted, it's given; otherwise the name followed by the IP address in
brackets is given.  If the IP address isn't available, "[UNTRUSTED]" is
appended.

   The envelope sender is added to the end of the X-Mail-Path if known; if
not, "UNKNOWN" is added instead.

   mailpath takes no arguments or configuration directives and cannot fail.

mailtonews
----------

   Performs a variety of rewrites, changes, and checks necessary to do the
basic conversion of a mail message into a news message.  Most of this
involves deleting or renaming headers that a news server will not accept
or would overwrite and making sure that the required news headers are
present.

   This module does the following:  Checks to ensure there is a From
header; compacts the From header down to one line if it contained any
continuation lines since INN can't deal with continuation lines in a From
header; adds a Newsgroups header with the default group if none is
present, or checks the Newsgroups header for validity and removes
duplicate groups if one is present; drop the headers Lines, Received,
Relay-Version, and Xref which will be rejected or overwritten by the news
server; renames the headers NNTP-Posting-Host and Sender to be prefixed
with X-Original- since new ones will be generated; adds a new Sender
header pointing to the maintainer (set in the News::Gateway constructor);
renames the Message-ID header to X-Original-Message-ID if the message ID
is syntactically invalid for a news message (this will cause a new message
ID to be generated by the server); checks the In-Reply-To header if
present to see if it contains something that looks like a message ID and
if so adds it to the end of the References header if and only if it
doesn't duplicate the message ID on the end of the References header; and
sets the subject of the article to the value "(none)" if there is no
Subject header.

   This module takes one argument, the default newsgroup to post to.  A
Newsgroups header containing this group will be added if no Newsgroups
header is present in the incoming message.  This argument is optional, but
if you're gating mail messages to news messages you'll pretty much always
want to supply it.  While it's tempting to assume that all submissions to
a moderated group will already have a Newsgroups header added by the news
server, you'll find in practice that people will often mail submissions
directly to the submission address, or that news servers won't handle
things in the way that you would expect.

   This module (possibly combined with the headers module) may be
sufficient for generating the Newsgroups header if the program only
handles one newsgroup, but any more complicated situation will probably
require that a module (such as the newsgroups module) be run before this
one to generate the Newsgroups header.

   There are three possible failure messages which may be returned;

Empty body
     The body of the message was empty.  Most news servers will reject
     messages with an empty body.

Missing required From header
     The incoming message doesn't have a From header.  A From header is
     required for all messages.

No Newsgroups header or default group
     The incoming message didn't have a Newsgroups header and no argument
     was supplied to the module.  If you don't supply an argument
     specifying the default newsgroup, all incoming messages must have a
     Newsgroups header before this module is run, since a Newsgroups
     header is mandatory in a news article.

   This module takes no configuration directives.

moosesign
---------

   Does simple PGPMoose signing of messages.  This module is not a full
implementation of PGPMoose; in particular, it doesn't support all of the
crosspost handling.  It looks through the groups in the Newsgroups header
and adds a PGPMoose X-Auth header for every group in the Newsgroups header
for which a PGP key has been given.

   This module takes one configuration directive, which associates a PGP
key ID and passphrase with a newsgroup:

pgpkey NEWSGROUP PASSPHRASE KEYID
     Associates the given `KEYID' and `PASSPHRASE' with `NEWSGROUP'.
     `KEYID' is optional and will default to the name of the newsgroup
     surrounded by spaces if not given.  (This default will allow PGP to
     find the key correctly if the key ID is something like "Moderator for
     group.name <address>" while avoiding confusing group.name and
     group.name.other.)

   Note that using this module means putting the PGP passphrases for the
moderation keys in cleartext in the configuration file or in the script.

   This module takes no arguments and cannot fail.

mungeids
--------

   Programmatically munges the message IDs in the Message-ID and References
headers by adding a slash-separated list of newsgroups to which the
article is going to be posted, followed by a slash, to the beginning of
them.  We also strip off any prefix that looks like a prefix we'd generate
(any number of strings that could be a newsgroup name, separated by
slashes) to prevent threads with replies from readers of multiple
mungeid'd groups from generating constantly-growing message IDs and to
hopefully still get threading right.  For the purposes of this check, we
assume newsgroup names will contain at least one period; this module may
not work correctly for newsgroup names that do not.

   The purpose of this is for use with mailing list to newsgroup gateways.
Since messages to multiple mailing lists may all have the same message ID,
and since the same mailing list may be gated to Usenet in multiple places,
the message IDs of incoming mailing list messages need to be munged in
some fashion before being passed on to Usenet.  Ideally, however,
threading should be preserved, and replies to mailing list messages from
other people on the mailing list won't refer to the munged message ID.
This module therefore applies the same munge to all of the message IDs in
the References header as well, in the hope of maintaining threading and
still getting message ID uniqueness.

   If the message doesn't already have a Message-ID header, this module
will generate one.

   Since an accurate Newsgroups header is needed to correctly munge the
IDs, this module should run after any modules responsible for generating
that.  It also needs the final Message-ID and References header, so it
should run after the mailtonews module since that module may promote
message IDs from In-Reply-To into References and discard existing
Message-ID headers.

   This module takes one optional configuration directive:

mungeids REGEX [REGEX ...]
     `REGEX' is a regex matching newsgroups which should be used to make up
     the prefix that we'll be adding to message IDs.  If this configuration
     directive is supplied, then only newsgroups matching one of the
     supplied regexes will be used to construct the prefix.  By default,
     all newsgroups in the Newsgroups header will be used in the prefix.

   mungeids takes no arguments and cannot fail.

newsgroups
----------

   Construct the Newsgroups header for a message.  This is the general
module for this purpose, and is considerably more flexible than the simple
handling built into the mailtonews module.

   The guiding purpose of this module is to attempt to deal with
crossposting correctly in the context of a generic mail to news gateway
(where incoming mail messages may not, unlike submissions for moderated
groups, already have Newsgroups headers in them).  We're ambitious,
though, and try to also handle the case where we do have an incoming
Newsgroups header.

   All of the gory details of what this module does in every circumstance
are documented in the comment block at the beginning of the code.  If
you're really curious, I'd recommend reading that.  It's far more
information than most people are going to want to know.  Here's the
briefer summary:

   The program tells this module what the primary newsgroup is.  This
should be the group to which we should post by default.  In other words,
suppose you have several different mail to news gateway addresses for
several different groups which all feed into the same program.  To use this
module, configure such a system so that the program knows what address a
given message arrived via (either by having access to the envelope
recipient through using qmail, using procmail as a delivery agent, or some
other method, or by having each mail to news gateway alias give the
program the name of its primary newsgroup on the command line).  The
program tells this module what group that is by providing it as an
argument to the module.

   We also have a list of associations between addresses and newsgroups
given to us in configuration directives.  An address can either be a
literal address (which will be matched exactly, albeit without regard to
case) or a regex.  Note that although this module wants to know about as
many of those associations as possible, it can deal with not knowing about
them all and will generally do the right thing.  It will just tend to
multipost when it could have crossposted unless it knows which addresses
correspond to which newsgroups.

   If the incoming message doesn't have a Newsgroups header, this module
will construct one by inspecting the To and Cc headers and seeing where the
message was sent.  If the primary group corresponds to one of the
addresses in the To and Cc headers, then it will crosspost between the
groups corresponding to the recognized addresses in the To and Cc headers
(with the caveat given below).  Otherwise, it assumes that the address via
which we received the message either is one we don't know about or was
Bcc'd and posts only to the primary group.

   There is one problem with this.  If a message is addressed to a number
of different addresses, all of which eventually gate to a newsgroup, if all
of those gateways do this analysis and crosspost, the article ends up
multiposted (one copy for each group crossposted to).  The solution to
this problem is for one of the instances of the gateway program decide to
post and all of the other ones exit quietly.  We support this by returning
the error "Not primary instance" if the primary group is in the list
formed from the To and Cc headers but isn't the first group in that list.
We assume that we'll also get the mail going to the address corresponding
to the first group in that list, and that instance will do the
crossposting.  A program using this module should probably exit silently
if we return "Not primary instance".

   If the message does contain a Newsgroups header, then what we do depends
on whether our primary group is among the groups in that header, and
whether any of the addresses in the To or Cc headers correspond to groups
in that header.  The exact rules are very complicated (see the source
comments), but we ignore the Newsgroups header entirely if neither the
primary group nor the groups corresponding to addresses in the To and Cc
headers occur in it, honor it if the primary group is in it, and post only
to the groups corresponding to addreses in the To and Cc headers that
aren't in the Newsgroups header if some addresses in the To and Cc headers
correspond to groups in the Newsgroups header but our primary group isn't
in that header.  We also return "Not primary instance" where appropriate
to ensure that a post to a given set of newsgroups is only done once.

   (Yes, this is a simplification.  See the source comments for the real
complexity.)

   We also rename Message-ID to X-Original-Message-ID if we have some
expectation that otherwise we'll clash with another post (either made by
another instance of the same program or posted elsewhere).  We also rename
Newsgroups to X-Original-Newsgroups if we don't honor the supplied header.
Note that this module goes to some length to avoid renaming Message-ID
unless necessary; if you want to drop all incoming message IDs and
generate new ones, you should do that using the headers module.

   We take an argument specifying the primary group, and we take one
configuration directive in one of three forms:

group NEWSGROUP [ ADDRESS | /PATTERN/ ]
     Adds `NEWSGROUP' to the list of valid newsgroups and optionally
     associates it with either `ADDRESS' or PATTERN.  `ADDRESS' is a
     literal string that (case-insensitively) exactly matches the address
     associated with `NEWSGROUP'.  PATTERN is a Perl regex that matches
     addresses associated with `NEWSGROUP'.

group /PATTERN/
     Tells this module to consider any newsgroup matching PATTERN to be
     valid to crosspost to.  Note that this directive doesn't set up any
     address to group mappings, just changes what groups are allowed in a
     pre-existing Newsgroups header.

group FILE /PATTERN/
     Tells this module to add all newsgroups matching PATTERN in the file
     FILE to the list of valid newsgroups for crossposts.  Note that this
     directive doesn't set up any address to group mappings, just changes
     what groups are allowed in a pre-existing Newsgroups header.  FILE
     must be an absolute path (i.e., it must begin with /).

   In all of the above, the /s around PATTERN arguments are required, as
they allow unambiguous parsing of the configuration file directives.

   There are three possible failure messages returned by this module:

Invalid crossposted group %s
     The incoming message already had a Newsgroups header which included a
     group that wasn't on the list of allowable newsgroups for
     crossposting.

Not primary instance
     Although the primary group is among the groups we would normally post
     to, it isn't the "first" such group.  This probably means that
     multiple copies of the message were received by different gateways
     and this instance should exit silently since another instance will be
     doing the posting.

   In addition to that, there are two possible fatal errors that can occur
during the parsing of the configuration file and a third at the time of
parsing the incoming message.  These errors are passed to the
News::Gateway error() method.

Invalid regex /%s/: %s
     An error occurred while compiling the given regex from a PATTERN
     argument to a configuration directive.

Can't open group file %s: %s
     An error occurred while attempting to open a file from a FILE argument
     to a configuration directive.

newsgroups module missing required argument
     The newsgroups module requires an argument giving the primary
     newsgroup, or all of the tricks we use to figure out crossposting and
     where to post won't work correctly.

newstomail
----------

   Rewrites a news article into a mail message, using a set of newsgroup to
e-mail address mappings to determine which addresses to mail the resulting
message to.

   This module does the following:  Checks to make sure there's a
Newsgroups header; drops Bcc and Resent-Bcc headers in the message;
renames To, Cc, Apparently-To, Resent-To, Resent-Cc, Return-Path, and
Sender headers (if present) to the same name prefixed by X-Original- since
they may be misinterpreted by e-mail software, and sets a new To header
consisting of the e-mail addresses corresponding to all the groups in the
Newsgroups header that have defined mappings.  Duplicate addresses are
stripped out.

   This module takes one configuration file directive:

newstomail FILENAME
     Specifies the file from which the list of newsgroup to address
     mappings should be read, in the form newsgroup, whitespace, address.
     If the filename ends in .db, then the file will be assumed to be a
     Berkeley database instead, with newsgroups as the keys and addresses
     as the values.

   Two failure messages are possible:

Missing required Newsgroups header
     The incoming message doesn't have a Newsgroups header.  This module
     only handles posts and needs the Newsgroups header to determine what
     addresses to which to send the message.

No newsgroup with a mapping
     None of the newsgroups in the Newsgroups header had a mapping to an
     e-mail address, so there's nowhere to send the message.

   This module takes no arguments.

nobinaries
----------

   Checks the message to see if it is or contains a binary and rejects it
if it is.  The following checks are performed:  Ensure that no Content-Type
header in the headers or the body contains the strings "application",
"image", "audio", or "video"; ensure that no Content-Transfer-Encoding
header in the headers or the body is equal to "base64", and ensure that
encoded lines do not exceed 50% of the number of lines in the body for any
article with at least 40 lines.

   An encoded line is defined as a line beginning with an M (with optional
leading whitespace or quoting characters) and exactly 60 or 61 characters
in length, or a line containing no spaces, not starting with M or ~, and
between 59 and 80 characters in length.

   Lines meeting those criteria are counted separately (the first as
potential uuencoding, the second as potential base64 encoding), and if the
count of lines in any one category is over half of the total body lines,
the message is rejected.

   The rejection messages are:

base64 encoded
     The message contains a Content-Transfer-Encoding header with a value
     of "base64".

Invalid content type
     The message contains a Content-Type header that contains one of the
     strings "application", "image", "audio", or "video".

Apparently uuencoded
     The message body is at least 40 lines and more than 50% of those lines
     start with M (modulo whitespace and quoting) and are exactly 60 or 61
     characters long.

Apparently base64-encoded
     The message body is at least 40 lines and more than 50% of those lines
     contain no spaces, do not begin with M or ~, and are between 59 and 80
     characters long.

   This article takes no arguments or configuration directives.

previoushop
-----------

   Adds the previous host through which a mail message passed to the Path
header of the message.  It does this by looking through the raw Received
headers, finding the first Received header that specifies a host from
which the message was received, and prepending it to the Path header (or
creating a new Path header if none already exists).

   If no Received headers that contain a "from" clause are found (which may
be the case for mail originating locally), nothing is done.

   The reason for this module is to support news to mail and mail to news
gateways for the same unmoderated newsgroup.  If the mail to news address
is subscribed to a mailing list and posts to the newsgroup are sent back
to the mailing list, a loop will be created unless something is done to
stop it.  One method of stopping such loops is to alias the hostname of
the mailing list machine out of the feed to the news to mail gateway in
the news server and then use this module to put the hostname of the
mailing list machine in the Path of all articles posted through the mail
to news gateway.

   This module takes no arguments or configuration directives and cannot
fail.

whitelist
---------

   Checks to make sure that the incoming message is from a poster in a file
of valid posters.  The most common use of this module is in conjunction
with human moderation; all messages from pre-approved posters are sent
straight through via the robomoderator and the rest are relayed to a human
moderator for hand checking.

   This module takes one configuration directive:

whitelist FILE
     FILE is a list of poster addresses, one per line.  Only the address
     should be included in this file, not the name or other comments.
     Files ending in `.db' are reserved for future implementations
     (eventually, these will automatically be recognized as Berkeley db
     files for handling large lists of posters).

   There is one possible failure message:

Unknown poster %s
     The message is from a poster address which isn't in the whitelist of
     known addresses.

   In addition, during parsing of the configuration directives, one fatal
error, which would be passed to error(), is possible:

Can't open whitelist file %s: %s
     An error occurred while trying to open a file given as a FILE argument
     to a configuration directive.

   This module takes no arguments.

UTILITY MODULES
===============

   The following modules are also part of the standard distribution.
Rather than rewrite or check messages, they provide additional methods
that can be used by programs, other modules, even or the News::Gateway
core code.  Methods supplied by utility modules can be called like any
other News::Gateway method.

config
------

   This module contains the code for reading and parsing configuration
directives and calling the appropriate module callback hooks.  Nearly all
News::Gateway programs will make use of this module.

   WARNING: Information in configuration directives is *trusted* by
modules, and modules may go so far as to eval things from configuration
directives as Perl code.  This means that anyone who has access to the
configuration directives read by this module has as much control over what
a program does as someone who can edit the source.  Any necessary sanity
or security checking on the content of configuration directives must be
done before they are passed off to modules, and `config_file()' does no
such checking.

config (DIRECTIVE, ARGUMENT [, ARGUMENT ...])
     Calls the registered module callbacks for all modules who have
     expressed an interest in `DIRECTIVE'.  This bypasses any parsing, and
     the arguments are given to the callbacks exactly as passed in.
     `DIRECTIVE' is case-insensitive.

config_file (FILE | HANDLE)
     Reads in configuration directives from the supplied file name or file
     handle (which can be either an object reference or a reference to a
     typeglob) until end of file is reached.

     Blank lines and lines beginning with a `#' are ignored.  All other
     lines are parsed into a directive (the first whitespace-separated
     word) and some number of arguments, and then the parse results are
     passed along to the module which has registered interest in that
     directive.  If an argument contains embedded whitespace, it can be
     enclosed in double quotes.  A backslash will escape the next
     character, whatever it is.  A line is considered to be continued on
     the next line if it ends in a backslash, and if the line continuation
     occurs inside double quotes, a literal newline will be part of the
     string.

     For example, the following configuration directive tells the headers
     module to add a new header named X-Comment with the content "This is a
     long comment about this newsgroup":

          header x-comment add \
                 "This is a long comment about this newsgroup"

     Multiple configuration files can be read by calling `config_file()'
     multiple times.  One handy trick for simple scripts using
     News::Gateway is to put the configuration lines at the end of the
     script after an __END__ and then pass them to News::Gateway with:

          $gateway->config_file (\*DATA);

     `config_file()' should be called before any `apply()' it is supposed
     to affect.

config_line (LINE)
     Parses and handles a single configuration line, just as if it were
     read from a file (in fact, `config_file()' calls this method for each
     non-blank, non-comment line).  This can be used to feed individual
     configuration lines to the News::Gateway object without having to
     give it a file or file handle.

config_parse (LINE)
     Parses a configuration file line, returning the results as an array.
     This is the method used by `config_file()' and `config_line()' to
     parse configuration files.  This probably isn't generally useful.

   These methods adds two additional fatal error messages, which may be
passed to error().

Parse error in %s
     A configuration line was unable to be parsed.  The most likely cause
     is unbalanced double quotes.

Unknown configuration directive %s
     News::Gateway encountered a configuration directive that no module had
     expressed interest in.  Chances are you made a typo in your
     configuration file or forgot to register a module with modules() that
     you were planning on using.

mail
----

   This module separates out various functions related to sending mail into
their own module so that it can be autoloaded on demand rather than always
compiled.  The following methods are included:

mail ([ ADDRESS [, ADDRESS ...]])
     The message in its current form will be mailed to `ADDRESS', and the
     method will return true on success, false on failure.  If `ADDRESS' is
     not supplied, the message is mailed to the addresses in the standard
     mail headers (To, Cc, Bcc, and the Resent-* varients depending on
     your MTA), so this method should also be used after news to mail
     rewrites have taken place.

     *NOTE: The old mail_forward() method is DEPRECATED.*

mail_bounce (ERROR)
     Bounces the message by printing ERROR to stderr and then exiting with
     the permanent failure status code (as defined in the beginning of the
     News::Gateway source).  This should only be used as a last resort,
     particularly for robomoderators, since the bounces will go to the
     envelope sender address which is often not the same as the poster.

mail_error (ERROR)
     Attempts to send an error message to the sender of the original
     message, cc'd to the maintainer address.  Replies will be set to the
     maintainer address, the subject will be "failure notice," and a
     Precedence header of "junk" will be added, which can be used to avoid
     loops.

     If no From or Reply-To header has been seen, or if sending the mail
     fails, this method will call mail_bounce() with the same error
     message instead.

     The message sent will be:

          Hi.  I'm afraid that I was unable to post your message.  This
          is a fatal error; I've given up.  A copy of this report is
          being sent to my maintainer.  The error message I received was:

          ERROR

          --- Below this line is a copy of the message.

     followed by the original article headers and the body, with ERROR
     replaced by ERROR.  Note that if ERROR should be word-wrapped in the
     message, this must be done by the caller.

mail_filereply (FILENAME [, SOURCES])
     Mails a News::FormReply-style message to the author of the incoming
     message.  See News/FormReply, for more
     information.  FILENAME is the path to the file to use to construct
     the reply, and SOURCES for News::FormReply variables can optionally
     be provided.  The following variables are exposed to the form message
     by default:

          @BODY        Message body, possibly munged by previous modules.
          @HEADERS     Current message headers.
          @OLDHEADERS  Original message headers.
          $SUBJECT     Original subject line.
          $MAINTAINER  Maintainer of this gateway.

     Returns true if sending the mail succeeded, false if it failed.

post
----

   Implements all methods related to posting articles.  The following
methods are included:

post ([ SERVER ])
     Posts the article using the NNTP POST command.  Under most
     circumstances, this is how you want to post an article.  SERVER, if
     specified, may be either the name or IP address of a news server to
     use for posting or a reference to an open Net::NNTP connection to be
     used.  undef is returned on success; the error message is returned on
     failure.

     Before this method is called, the message headers should be rewritten
     into ones appropriate for a news message; this is one of the purposes
     of the modules.

post_ihave ([ SERVER ])
     Posts the article using the NNTP IHAVE command.  This connects to a
     news server as a transfer server rather than as a client; under most
     circumstances this is not what you want.  Unless you already know what
     IHAVE is, you may not want to use this.  In order to use this posting
     method, the article already has to have all necessary headers to be a
     properly formatted news article, including Path and Message-ID; unlike
     POST, IHAVE will not automatically fill in missing headers.

     As above, SERVER if specified may be either the name or IP address of
     a news server to use for posting or a reference to an open Net::NNTP
     connection.  undef is returned on success; the error message is
     returned on failure.

post_program (COMMAND [, ARGUMENT ... ])
     Posts the article by running a program and passing the article to it
     on stdin.  This can be used to post via inews or rnews if you so wish,
     although using the post() method is recommended under most
     circumstances.  The arguments to the command should be a list of
     strings; this command does not fork a shell so shell metacharacters
     will not be interpreted as such.

     If the program exits with status 0, success is assumed and this method
     returns undef.  If the program exits with non-zero status or some
     other error occurs, this method returns the output of the program
     (both stdout and stderr) and an error message.  The output and error
     message will be newline-terminated.

DIAGNOSTICS
===========

   In addition to the failure messages generated by modules (listed above),
the following messages may be generated by the News::Gateway core code and
would be passed to the error() method.

Autoload of %s failed: %s
     A method was called that doesn't exist in the core code and was
     unable to be loaded from a module.  Chances are you made a typo when
     referring to a News::Gateway method.

Cannot open file %s: %s
     News::Gateway attempted to open a file (probably the configuration
     file) and failed for the given reason.

Unable to load %s: %s
     One of the modules (either rewrite or utility) you used requires an
     external Perl module and was unable to load it.

Unknown module %s
     You told modules() to load a module that has no hooks registered.
     News::Gateway has to know about every module that it can use; you
     can't just copy in a new module with the others and have it work.
     Instead, put the module in the modules directory before the build
     process.

BUGS
====

   Many.  This is an *alpha* release, with all that's implied by that in
terms of bugs, interface instability, and other such concerns.  Use at
your own risk, but if you encounter a bug please let me know.  Patches in
particular are gratefully accepted.

NOTES
=====

   If you are interested in being notified of new releases, helping with
development, developing, testing, or using new modules, or even just
getting tips on how to use this module, there is a mailing list available.
To subscribe, send mail to majordomo@eyrie.org with:

     subscribe gateway-users

   in the body.

   New patches and modules are always welcome, whether from people on the
list or not, and can be mailed to the address listed below.

SEE ALSO
========

   See News/Article,

AUTHOR
======

   Russ Allbery <rra@stanford.edu>.

HISTORY
=======

   News::Gateway started as a simple mail to news Perl script, written
right after the cs.utexas.edu mail to news gateway closed and just a quick
hack for the use of people who had previously used that gateway to post to
rec.arts.comics.creative and alt.comics.lnh.  Over time, it became a
general mail to news gateway with a fairly broad set of features.

   Eventually, it became obvious that it really should have been a module
rather than a script, and it also became clear that it could be used as
the core of a robomoderator.  Since there was no real general-purpose
robomoderation software around that was nearly as flexible as I thought a
package should be, I decided to be ambitious and try to solve the general
problem.

   Then I took a complete detour to rewrite the entire thing again to use
Andrew Gierth's News::Article class, which is what I should have been
doing from the beginning.  And now, finally, it's getting closer to what
I'd envisioned.

Perl 5 module to talk to NNTP (RFC977) server
*********************************************

NAME
====

   News::NNTPClient - Perl 5 module to talk to NNTP (RFC977) server

SYNOPSIS
========

     use News::NNTPClient;

     $c = new News::NNTPClient;
     $c = new News::NNTPClient($server);
     $c = new News::NNTPClient($server, $port);
     $c = new News::NNTPClient($server, $port, $debug);

DESCRIPTION
===========

   This module implements a client interface to NNTP, enabling a Perl 5
application to talk to NNTP servers.  It uses the OOP (Object Oriented
Programming) interface introduced with Perl 5.

   NNTPClient exports nothing.

   A new NNTPClient object must be created with the new method.  Once this
has been done, all NNTP commands are accessed through this object.

   Here are a couple of short examples.  The first prints all articles in
the "test" newsgroup:

     #!/usr/local/bin/perl -w

     use News::NNTPClient;

     $c = new News::NNTPClient;

     ($first, $last) = ($c->group("test"));

     for (; $first <= $last; $first++) {
         print $c->article($first);
     }

     __END__

   This example prints the body of all articles in the "test" newsgroup
newer than one hour:

     #!/usr/local/bin/perl -w

     require News::NNTPClient;

     $c = new News::NNTPClient;

     foreach ($c->newnews("test", time - 3600)) {
         print $c->body($_);
     }

     __END__

NNTPClient Commands
-------------------

   These commands are used to manipulate the NNTPClient object, and aren't
directly related to commands available on any NNTP server.

new
     Use this to create a new NNTP connection. It takes three arguments, a
     hostname, a port and a debug flag.  It calls initialize.  Use an
     empty argument to specify defaults.

     If port is omitted or blank (""), looks for environment variable
     NNTPPORT, service "nntp", or uses 119.

     If host is omitted or empty (""), looks for environment variable
     NNTPSERVER or uses "news".

     Examples:

          $c = new News::NNTPClient;
          or
          $c = new News::NNTPClient("newsserver.some.where");
          or
          $c = new News::NNTPClient("experimental", 9999);
          or
          # Specify debug but use defaults.
          $c = new News::NNTPClient("", "", 2);

     Returns a blessed reference, representing a new NNTP connection.

initialize
     Calls port, host, connect, and response, in that order.  If any of
     these fail, initialization is aborted.

connect
     Connects to current host/port.  Not normally needed, as the new
     method does this for you.  Closes any existing connection.  Sets the
     posting status.  See the postok method.

host
     Sets the host that will be used on the next connect.  Not normally
     needed, as the new method does this for you.

     Without an argument, returns current host.

     Argument can be hostname or dotted quad, for example, "15.2.174.218".

     Returns fully qualified host name.

port
     Sets the port that will be used on the next connect.  Not normally
     needed, as the new method does this for you.

     Without an argument, returns current port.

     Argument can be port number or name.  If it is a name, it must be a
     valid service.

     Returns port number.

debug
     Sets the debug level.

     Without an argument, returns current debug level.

     There are currently three debug levels.  Level 0, level 1, and level
     2.

     At level 0 the messages described for level 1 are not produced.  Debug
     level 0 is a way of turning off messages produced by the default debug
     level 1.  Serious error messages, such as EOF (End Of File) on the
     file handle, are still produced.

     At level 1, any NNTP command that results in a result code of 400 or
     greater prints a warning message.  This is the default.

     At level 2, in addition to level 1 messages, status messages are
     printed to indicate actions taking place.

     Returns old debug value.

ok
     Returns boolean status of most recent command.  NNTP return codes less
     than 400 are considered OK.  Not often needed as most commands return
     false upon failure anyway.

okprint
     Returns boolean status of most recent command.  NNTP return codes less
     than 400 are considered OK.  Prints an error message for return codes
     of 400 or greater unless debug level is set to zero (0).

     This method is used internally by most commands, and could be
     considered to be "for internal use only".  You should use the return
     status of commands directly to determine pass-fail, or if needed the
     ok method can be used to check status later.

message
     Returns the NNTP response message of the most recent command.

     Example, as returned by NNTP server version 1.5.11t:

          $c->slave;
          print $c->message;

          Kinky, kinky.  I don't support such perversions.

code
     Returns the NNTP response code of the most recent command.

     Example:

          $c->article(1);
          print $c->code, "\n";

          412

postok
     Returns the post-ability status that was reported upon connection or
     after the mode_reader command.

eol
     Sets the End-Of-Line termination for text returned from the server.

     Returns the old EOL value.

     Default is \n.

     To set EOL to nothing, pass it the empty string.

     To query current EOL without setting it, call with no arguments.

     Example:

          $old_eol = $c->eol();     # Get original.
          $c->eol("");              # Set EOL to nothing.
          @article = $c->article(); # Fetch an article.
          $c->eol($old_eol);        # Restore value.

gmt
     Sets GMT mode.  Returns old value.  To query GMT mode without setting
     it, call with no arguments.

     A true value means that GMT mode is used in the newgroups and newnews
     functions.  A false value means that local time is used.

fourdigityear
     Sets four digit year mode.  Returns old value.  To query four digit
     year mode without setting it, call with no arguments.

     A true value means that four digit years are used in the newgroups
     and newnews functions.  A false value means that an RFC977 compliant
     two digit year is used.

     This function is available for news servers that implemented four
     digit years rather than deal with non-y2k compliment two digit years.
     RFC977 does not allow four digit years, and instead chooses the
     century closest.  I quote:

          The closest century is assumed as part of the year (i.e., 86
          specifies 1986, 30 specifies 2030, 99 is 1999, 00 is 2000).

version
     Returns version number.

     This document represents @(#) $Revision: 0.36 $.

NNTP Commands
-------------

   These commands directly correlate to NNTP server commands.  They return
a false value upon failure, true upon success.  The truth value is usually
some bit of useful information.  For example, the stat command returns
Message-ID if it is successful.

   Some commands return multiple lines.  These lines are returned as an
array in array context, and as a reference to an array in scalar context.
For example, if you do this:

     @lines = $c->article(14);

   then @lines will contain the article, one line per array element.
However, if you do this:

     $lines = $c->article(14);

   then $lines will contain a reference to an array.  This feature is for
those that don't like passing arrays from routine to routine.

mode_reader
     Some servers require this command to process NNTP client commands.
     Sets postok status.  See postok.

     Returns OK status.

article
     Retrieves an article from the server.  This is the main command for
     fetching articles.  Expects a single argument, an article number or
     Message-ID.  If you use an article number, you must be in a news
     group.  See group.

     Returns the header, a separating blank line, and the body of the
     article as an array of lines terminated by the current EOL.

     In scalar context a reference to the array is returned instead of the
     array itself.

     Examples:

          print $c->article('<art1234@soom.oom>');

          $c->group("test");

          print $c->article(99);

body
     Expects a single argument, an article number or Message-ID.

     Returns the body of an article as an array of lines terminated by the
     current EOL.

     In scalar context a reference to the array is returned instead of the
     array itself.

     See article.

head
     Expects a single argument, an article number or Message-ID.

     Returns the head of the article as an array of lines terminated by the
     current EOL.

     In scalar context a reference to the array is returned instead of the
     array itself.

     See article.

stat
     Expects a single argument, an article number or Message-ID.

     The STAT command is like the ARTICLE command except that it does not
     return any text.  It can be used to set the "current article pointer"
     if passed an article number, or to validate a Message-ID if passed a
     Message-ID.

     Returns Message-ID if successful, otherwise returns false.

last
     The "current article pointer" maintained by the server is moved to the
     previous article in the current news group.

     Returns Message-ID if successful, otherwise returns false.

next
     The "current article pointer" maintained by the server is moved to the
     next article in the current news group.

     Returns Message-ID if successful, otherwise returns false.

group
     Expects a single argument, the name of a valid news group.

     This command sets the current news group as maintained by the server.
     It also sets the server maintained "current article pointer" to the
     first article in the group.  This enables the use of certain other
     server commands, such as article, head, body, stat, last, and next.
     Also sets the current group in the NNTPClient object, which is used
     by the newnews and xindex commands.

     Returns (first, last) in list context, or "first-last" in scalar
     context, where first and last are the first and last article numbers
     as reported by the group command.  Returns false if there is an error.

     It is an error to attempt to select a non-existent news group.

     If the estimated article count is needed, it can be extracted from the
     message.  See message.

list
     Accepts one optional argument that can be used indicate the type of
     list desired.  List type depends on server.

     With an argument of "active" or with no arguments, this command
     returns a list of valid newsgroups and associated information.  The
     format is:

          group last first p

     where group is the news group name, last is the article number of the
     last article, first is the article number of the first article, and p
     is flag indicating if posting is allowed.  A 'y' flag is an indication
     that posting is allowed.

     Other possible arguments are: newsgroups, distributions, subscriptions
     for B-News, and active.times, distributions, distrib.pats, newsgroups,
     overview.fmt for INN.

     Returns an array of lines terminated by the current EOL.

     In scalar context a reference to the array is returned instead of the
     array itself.

newgroups
     Expects at least one argument representing the date/time in seconds,
     or in "YYYYMMDD HHMMSS [GMT]" format.  The GMT part is optional.  If
     you wish to use GMT with the seconds format, first call gmt.
     Remaining arguments are used as distributions.

     Example, print all new groups in the "comp" and/or "news" hierarchy as
     of one hour ago:

          print $c->newgroups(time() - 3600, "comp", "news");

     Returns list of new news group names as an array of lines terminated
     by the current EOL.

     In scalar context a reference to the array is returned instead of the
     array itself.

newnews
     Expects one, two, or more arguments.

     If the first argument is a group name, it looks for new news in that
     group, and the date/time is the second argument.  If the first
     argument represents the date/time in seconds or in "YYYYMMDD HHMMSS
     [GMT]" format, then the group is is last group set via the group
     command. If no group command has been issued then the group is "*",
     representing all groups.  If you wish to use GMT in seconds format for
     the time, first call gmt.  Remaining arguments are use to restrict
     search to certain distribution(s).

     Returns a list of Message-IDs of articles that have been posted or
     received since the specified time.

     Examples:

          # Hour old news in news group "test".
          $c->newnews("test", time() - 3600);
          or
          # Hour old in all groups.
          $c->newnews(time() - 3600);
          or
          $c->newnews("*", time() - 3600);
          or
          # Hour old news in news group "test".
          $c->group("test");
          $c->newnews(time() - 3600);

     The group argument can include an asterisk "*" to specify a range news
     groups.  It can also include multiple news groups, separated by a
     comma ",".

     Example:

          $c->newnews("comp.*.sources,alt.sources", time() - 3600);

     An exclamation point "!" may be used to negate the selection of
     certain groups.

     Example:

          $c->newnews("*sources*,!*.d,!*.wanted", time() - 3600);

     Any additional distribution arguments will be concatenated together
     and send as a distribution list.  The distribution list will limit
     articles to those that have a Distribution: header containing one of
     the distributions passed.

     Example:

          $c->newnews("*", time() - 3600, "local", "na");

     Returns Message-IDs of new articles as an array of lines terminated by
     the current EOL.

     In scalar context a reference to the array is returned instead of the
     array itself.

help
     Returns any server help information.  The format of the information is
     highly dependent on the server, but usually contains a list of NNTP
     commands recognized by the server.

     Returns an array of lines terminated by the current EOL.

     In scalar context a reference to the array is returned instead of the
     array itself.

post
     Post an article.  Expects data to be posted as an array of lines.
     Most servers expect, at a minimum, Newsgroups and Subject headers.
     Be sure to separate the header from the body with a neck, er blank
     line.

     Example:

          @header = ("Newsgroups: test", "Subject: test", "From: tester");
          @body   = ("This is the body of the article");

          $c->post(@header, "", @body);

     There aren't really three arguments.  Perl folds all arguments into a
     single list.  You could also do this:

          @article = ("Newsgroups: test", "Subject: test", "From: tester", "", "Body");
          $c->post(@article);

     or even this:

          $c->post("Newsgroups: test", "Subject: test", "From: tester", "", "Body");

     Any "\n" characters at the end of a line will be trimmed.

     Returns status.

ihave
     Transfer an article.  Expects an article Message-ID and the article to
     be sent as an array of lines.

     Example:

          # Fetch article from server on $c
          @article = $c->article($artid);

          # Send to server on $d
          if ($d->ihave($artid, @article)) {
              print "Article transfered\n";
          } else {
              print "Article rejected: ", $d->message, "\n";
          }

slave
     Doesn't do anything on most servers.  Included for completeness.

DESTROY
     This method is called whenever the the object created by
     News::NNTPClient::new is destroyed.  It calls quit to close the
     connection.

quit
     Send the NNTP quit command and close the connection.  The connection
     can be then be re-opened with the connect method.  Quit will
     automatically be called when the object is destroyed, so there is no
     need to explicitly call quit before exiting your program.

Extended NNTP Commands
----------------------

   These commands also directly correlate NNTP server commands, but are
not mentioned in RFC977, and are not part of the standard.  However, many
servers implement them, so they are included as part of this package for
your convenience.  If a command is not recognized by a server, the server
usually returns code 500, command unrecognized.

authinfo
     Expects two arguments, user and password.

date
     Returns server date in "YYYYMMDDhhmmss" format.

listgroup
     Expects one argument, a group name.  Default is current group.

     Returns article numbers as an array of lines terminated by the current
     EOL.

     In scalar context a reference to the array is returned instead of the
     array itself.

xmotd
     Expects one argument of unix time in seconds or as a string in the
     form "YYYYMMDD HHMMSS".

     Returns the news servers "Message Of The Day" as an array of lines
     terminated by the current EOL.

     In scalar context a reference to the array is returned instead of the
     array itself.

     For example, the following will always print the message of the day,
     if there is any:

          print $c->xmotd(1);
          NNTP Server News2

          News administrator is Joseph Blough <joeblo@news.foo.com>

xgtitle
     Expects one argument of a group pattern.  Default is current group.

     Returns group titles an array of lines terminated by the current EOL.

     In scalar context a reference to the array is returned instead of the
     array itself.

     Example:

          print $c->xgtitle("bit.listserv.v*");

          bit.listserv.valert-l   Virus Alert List. (Moderated)
          bit.listserv.vfort-l    VS-Fortran Discussion List.
          bit.listserv.vm-util    VM Utilities Discussion List.
          bit.listserv.vmesa-l    VM/ESA Mailing List.
          bit.listserv.vmslsv-l   VAX/VMS LISTSERV Discussion List.
          bit.listserv.vmxa-l     VM/XA Discussion List.
          bit.listserv.vnews-l    VNEWS Discussion List.
          bit.listserv.vpiej-l    Electronic Publishing Discussion

xpath
     Expects one argument of an article Message-ID.  Returns the path name
     of the file on the server.

     Example:

          print print $c->xpath(q(<43bq5l$7b5@news.dtc.hp.com>))'
          hp/test/4469

xhdr
     Fetch header for a range of articles.  First argument is name of
     header to fetch.  If omitted or blank, default to Message-ID.  Second
     argument is start of article range.  If omitted, defaults to 1.  Third
     argument is end of range.  If omitted, defaults to "".  The second
     argument can also be a Message-ID.

     Returns headers as an array of lines terminated by the current EOL.

     In scalar context a reference to the array is returned instead of the
     array itself.

     Examples:

          # Fetch Message-ID of article 1.
          $c->xhdr();

          # Fetch Subject of article 1.
          $c->xhdr("Subject");

          # Fetch Subject of article 3345.
          $c->xhdr("Subject", 3345);

          # Fetch Subjects of articles 3345-9873
          $c->xhdr("Subject", 3345, 9873);

          # Fetch Message-ID of articles 3345-9873
          $c->xhdr("", 3345,9873);

          # Fetch Subject for article with Message-ID
          $c->xhdr("Subject", '<797t0g$25f10@foo.com>');

xpat
     Fetch header for a range of articles matching one or more patterns.
     First argument is name of header to fetch.  If omitted or blank,
     default to Subject.  Second argument is start of article range.  If
     omitted, defaults to 1.  Next argument is end of range.  Remaining
     arguments are patterns to match.  Some servers use "*" for wildcard.

     Returns headers as an array of lines terminated by the current EOL.

     In scalar context a reference to the array is returned instead of the
     array itself.

     Examples:

          # Fetch Subject header of article 1.
          $c->xpat();

          # Fetch "From" header of article 1.
          $c->xpat("From");

          # Fetch "From" of article 3345.
          $c->xpat("From", 3345);

          # Fetch "From" of articles 3345-9873 matching *foo*
          $c->xpat("From", 3345, 9873, "*foo*");

          # Fetch "Subject" of articles 3345-9873 matching
          # *foo*, *bar*, *and*, *stuff*
          $c->xpat("", 3345,9873, qw(*foo* *bar* *and* *stuff*));

xover
     Expects an article number or a starting and ending article number
     representing a range of articles.

     Returns overview information for each article as an array of lines
     terminated by the current EOL.

     In scalar context a reference to the array is returned instead of the
     array itself.

     Xover generally returns items separated by tabs.  Here is an example
     that prints out the xover fields from all messages in the "test" news
     group.

          #!/usr/local/bin/perl

          require News::NNTPClient;

          $c = new News::NNTPClient;

          @fields = qw(numb subj from date mesg refr char line xref);

          foreach $xover ($c->xover($c->group("test"))) {
              %fields = ();
              @fields{@fields} = split /\t/, $xover;
              print map { "$_: $fields{$_}\n" } @fields;
              print "\n";
          }

          __END__
          				#
          =item I<xthread>

     Expects zero or one argument.  Value of argument doesn't matter.  If
     present, *dbinit* command is sent.  If absent, thread command is sent.

     Returns binary data as a scalar value.

     Format of data returned is unknown at this time.

xindex
     Expects one argument, a group name.  If omitted, defaults to the group
     set by last group command.  If there hasn't been a group command, it
     returns an error;

     Returns index information for group as an array of lines terminated by
     the current EOL.

     In scalar context a reference to the array is returned instead of the
     array itself.

xsearch
     Expects a query as an array of lines which are sent to the server,
     much like post.  Returns the result of the search as an array of lines
     or a reference to same.

     Format of query is unknown at this time.

AUTHOR
======

   Rodger Anderson  <rodger@boi.hp.com>

COPYRIGHT
=========

   Copyright 1995 Rodger Anderson. All rights reserved.  This module is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

manage newsrc files
*******************

NAME
====

   News::Newsrc - manage newsrc files

SYNOPSIS
========

     use News::Newsrc;

     $newsrc   = new News::Newsrc;

     $ok       = $newsrc->load;
     $ok       = $newsrc->load             ($file);
                 $newsrc->import_rc        ( @lines);
                 $newsrc->import_rc        (\@lines);

                 $newsrc->save;
                 $newsrc->save_as          ($file);
     @lines    = $newsrc->export_rc;

     $ok       = $newsrc-> add_group       ($group,             %options);
     $ok       = $newsrc->move_group       ($group,             %options);
     $ok       = $newsrc-> del_group       ($group);

                 $newsrc->  subscribe      ($group,             %options);
                 $newsrc->unsubscribe      ($group,             %options);

                 $newsrc->mark             ($group,  $article , %options);
                 $newsrc->mark_list        ($group, \@articles, %options);
                 $newsrc->mark_range       ($group, $from, $to, %options);

                 $newsrc->unmark           ($group,  $article , %options);
                 $newsrc->unmark_list      ($group, \@articles, %options);
                 $newsrc->unmark_range     ($group, $from, $to, %options);

          ... if $newsrc->exists           ($group);
          ... if $newsrc->subscribed       ($group);
          ... if $newsrc->marked           ($group, $article);

     $n        = $newsrc->  num_groups;
     @groups   = $newsrc->      groups;
     @groups   = $newsrc->  sub_groups;
     @groups   = $newsrc->unsub_groups;

     @articles = $newsrc->  marked_articles($group,             %options);
     @articles = $newsrc->unmarked_articles($group, $from, $to, %options);

     $articles = $newsrc->get_articles     ($group,             %options);
     $ok       = $newsrc->set_articles     ($group, $articles,  %options);

REQUIRES
========

   Perl 5.004, Set::IntSpan 1.07

EXPORTS
=======

   Nothing

DESCRIPTION
===========

   `News::Newsrc' manages newsrc files, of the style

     alt.foo: 1-21,28,31-34
     alt.bar! 3,5,9-2900,2902

   Methods are provided for

   * reading and writing newsrc files

   * adding and removing newsgroups

   * changing the order of newsgroups

   * subscribing and unsubscribing from newsgroups

   * testing whether groups exist and are subscribed

   * marking and unmarking articles

   * testing whether articles are marked

   * returning lists of newsgroups

   * returning lists of articles

NEWSRC FILES
============

   A newsrc file is an ASCII file that lists newsgroups and article
numbers.  Each line of a newsrc file describes a single newsgroup.  Each
line is divided into three fields: a group, a *subscription mark* and an
*article list*.

   Lines containing only whitespace are ignored.  Whitespace within a line
is ignored.

Group
     The group is the name of the newsgroup.  A group name may not contain
     colons (:) or exclamation points (!).

     Group names must be unique within a newsrc file.  The group name is
     required.

Subscription mark
     The *subscription mark* is either a colon (:), for subscribed groups,
     or an exclamation point (!), for unsubscribed groups.  The
     subscription mark is required.

Article list
     The *article list* is a comma-separated list of positive integers.
     The integers must be listed in increasing order.  Runs of consecutive
     integers may be abbreviated a-b, where a is the first integer in the
     run and b is the last.  The article list may be empty.

NEWSGROUP ORDER
===============

   `News::Newsrc' preserves the order of newsgroups in a newsrc file: if a
file is loaded and then saved, the newsgroup order will be unchanged.

   Methods that add or move newsgroups affect the newsgroup order.  By
default, these methods put newsgroups at the end of the newsrc file.
Other locations may be specified by passing an %options hash with a where
key to the method.  Recognized locations are:

where => `'first''
     Put the newsgroup first.

where => `'last''
     Put the newsgroup last.

where => `'alpha''
     Put the newsgroup in alphabetical order.

     If the other newsgroups are not sorted alphabetically, put the group
     at an arbitrary location.

where => [ before => *$group* ]
     Put the group immediately before *$group*.

     If *$group* does not exist, put the group last.

where => [ after => *$group* ]
     Put the group immediately after *$group*.

     If *$group* does not exist, put the group last.

where => [ number => $n ]
     Put the group at position $n in the group list.  Indices are
     zero-based.  Negative indices count backwards from the end of the
     list.

METHODS
=======

$newsrc = new `News::Newsrc'
     Creates and returns a `News::Newsrc' object.  The object contains no
     newsgroups.

$ok = $newsrc->load
$ok = $newsrc->load($file)
     Loads the newsgroups in $file into $newsrc.  If $file is omitted,
     reads `$ENV{HOME}/.newsrc'.  Any existing data in $newsrc is
     discarded.  Returns true on success.

     If $file can't be opened, load discards existing data from $newsrc
     and returns null.

     If $file contains invalid lines, load will die.  When this happens,
     the state of $newsrc is undefined.

$newsrc->`import_rc'(*@lines*)
$newsrc->`import_rc'([*@lines*])
     Imports the newsgroups in *@lines* into $newsrc.  Any existing data
     in $newsrc is discarded.

     Each line in *@lines* describes a single newsgroup, and must have the
     format described in `"NEWSRC FILES"' in this node.  If *@lines*
     contains invalid lines, `import_rc' will die.  When this happens, the
     state of $newsrc is undefined.

     `import_rc' accepts either an array or an array reference.

$newsrc->save
     Writes the contents of $newsrc back to the file from which it was
     loaded.  If load has not been called, writes to `$ENV{HOME}/.newsrc'.
     In either case, if the destination file exists, it is renamed to
     file`.bak'.

     save will die if there is an error writing the file.

$newsrc->`save_as'($file)
     Writes the contents of $newsrc to $file.  If $file exists, it is
     renamed to $file`.bak'.  Subsequent calls to save will write to $file.

     `save_as' will die if there is an error writing the file.

*@lines* = $newsrc->`export_rc'
     Returns the contents of $newsrc as a list of lines.  Each line
     describes a single newsgroup, and has the format described in
     `"NEWSRC FILES"' in this node.

     In scalar context, returns an array reference.

$ok = $newsrc->add_group(*$group*, %options)
     Adds *$group* to the list of newsgroups in $newsrc.  *$group* is
     initially subscribed.  The article list for *$group* is initially
     empty.

     By default, *$group* is added to the end of the list of newsgroups.
     Other locations may be specified in %options; see `"NEWSGROUP ORDER"'
     in this node for details.

     By default, add_group does nothing if *$group* already exists.  If
     the replace => 1 option is provided, then add_group will delete
     *$group* if it exists, and then add it.

     add_group returns true iff *$group* was added.

$ok = $newsrc->`move_group'(*$group*, %options)
     Changes the position of *$group* in $newsrc according to %options.
     See `"NEWSGROUP ORDER"' in this node for details.

     If *$group* does not exist, `move_group' does nothing and returns
     false.  Otherwise, it returns true.

$ok = $newsrc->`del_group'(*$group*)
     If *$group* exists in $newsrc, `del_group' removes it and returns
     true.  The article list for *$group* is lost.

     If *$group* does not exist in $newsrc, `del_group' does nothing and
     returns false.

$newsrc->`subscribe'(*$group*, %options)
     Subscribes to *$group*.

     *$group* will be created if it does not exist.  Its location may be
     specified in %options; see `"NEWSGROUP ORDER"' in this node for
     details.

$newsrc->`unsubscribe'(*$group*, %options)
     Unsubscribes from *$group*.

     *$group* will be created if it does not exist.  Its location may be
     specified in %options; see `"NEWSGROUP ORDER"' in this node for
     details.

$newsrc->mark(*$group*, *$article*, %options)
     Adds *$article* to the article list for *$group*.

     *$group* will be created if it does not exist.  Its location may be
     specified in %options; see `"NEWSGROUP ORDER"' in this node for
     details.

$newsrc->`mark_list'(*$group*, *\@articles*, %options)
     Adds *@articles* to the article list for *$group*.

     *$group* will be created if it does not exist.  Its location may be
     specified in %options; see `"NEWSGROUP ORDER"' in this node for
     details.

$newsrc->`mark_range'(*$group*, *$from*, *$to*, %options)
     Adds all the articles from *$from* to *$to*, inclusive, to the
     article list for *$group*.

     *$group* will be created if it does not exist.  Its location may be
     specified in %options; see `"NEWSGROUP ORDER"' in this node for
     details.

$newsrc->unmark(*$group*, *$article*, %options)
     Removes *$article* from the article list for *$group*.

     *$group* will be created if it does not exist.  Its location may be
     specified in %options; see `"NEWSGROUP ORDER"' in this node for
     details.

$newsrc->`unmark_list'(*$group*, *\@articles*, %options)
     Removes *@articles* from the article list for *$group*.

     *$group* will be created if it does not exist.  Its location may be
     specified in %options; see `"NEWSGROUP ORDER"' in this node for
     details.

$newsrc->`unmark_range'(*$group*, *$from*, *$to*, %options)
     Removes all the articles from *$from* to *$to*, inclusive, from the
     article list for *$group*.

     *$group* will be created if it does not exist.  Its location may be
     specified in %options; see `"NEWSGROUP ORDER"' in this node for
     details.

$newsrc->exists(*$group*)
     Returns true iff *$group* exists in $newsrc.

$newsrc->`subscribed'(*$group*)
     Returns true iff *$group* exists and is subscribed.

$newsrc->marked(*$group*, *$article*)
     Returns true iff *$group* exists and its article list contains
     *$article*.

$n = $newsrc->`num_groups'
     Returns the number of groups in $newsrc.

*@groups* = $newsrc->groups
     Returns the list of groups in $newsrc, in newsrc order.  In scalar
     context, returns an array reference.

*@groups* = $newsrc->`sub_groups'
     Returns the list of subscribed groups in $newsrc, in newsrc order.
     In scalar context, returns an array reference.

*@groups* = $newsrc->`unsub_groups'
     Returns the list of unsubscribed groups in $newsrc, in newsrc order.
     In scalar context, returns an array reference.

*@articles* = $newsrc->`marked_articles'(*$group*)
     Returns the list of articles in the article list for *$group*.  In
     scalar context, returns an array reference.

     *$group* will be created if it does not exist.  Its location may be
     specified in %options; see `"NEWSGROUP ORDER"' in this node for
     details.

*@articles* = $newsrc->`unmarked_articles'(*$group*, *$from*, *$to*, %options)
     Returns the list of articles from *$from* to *$to*, inclusive, that
     do not appear in the article list for *$group*.  In scalar context,
     returns an array reference.

     *$group* will be created if it does not exist.  Its location may be
     specified in %options; see `"NEWSGROUP ORDER"' in this node for
     details.

$articles = $newsrc->`get_articles'(*$group*, %options)
     Returns the article list for *$group* as a string, in the format
     described in `"NEWSRC FILES"' in this node.

     *$group* will be created if it does not exist.  Its location may be
     specified in %options; see `"NEWSGROUP ORDER"' in this node for
     details.

     If you plan to do any nontrivial processing on the article list,
     consider converting it to a `Set::IntSpan' object:

          $articles = Set::IntSpan->new($newsrc->get_articles('alt.foo'))

$ok = $newsrc->`set_articles'(*$group*, $articles, %options)
     Sets the article list for $group.  Any existing article list is lost.

     $articles is a string, as described in `"NEWSRC FILES"' in this node.

     *$group* will be created if it does not exist.  Its location may be
     specified in %options; see `"NEWSGROUP ORDER"' in this node for
     details.

     If $articles does not have the format described in `"NEWSRC FILES"'
     in this node, `set_articles' does nothing and returns false.
     Otherwise, it returns true.

DIAGNOSTICS
===========

Bad newsrc line
     A line in the newsrc file does not have the format described in
     `"NEWSRC FILES"' in this node.

Bad article list
     The article list for a newsgroup does not have the format described in
     `"NEWSRC FILES"' in this node.

News::Newsrc::save_as: Can't rename $file, $file.bak: $!
News::Newsrc::save_as: Can't open $file: $!
News::Newsrc::format: Can't write $file: $!
NOTES
=====

Error Handling
--------------

   "Don't test for errors that you can't handle."

   load returns null if it can't open the newsrc file, and dies if the
newsrc file contains invalid data.  This isn't as schizophrenic as it
seems.

   There are several ways a program could handle an open failure on the
newsrc file.  It could prompt the user to reenter the file name.  It could
assume that the user doesn't have a newsrc file yet.  If it doesn't want
to handle the error, it could go ahead and die.

   On the other hand, it is very difficult for a program to do anything
sensible if the newsrc file opens successfully and then turns out to
contain invalid data.  Was there a disk error?  Is the file corrupt?  Did
the user accidentally specify his kill file instead of his newsrc file?
And what are you going to do about it?

   Rather than try to handle an error like this, it's probably better to
die and let the user sort things out.  By the same rational, save and
`save_as' die on failure.

   Programs that must retain control can use eval{...} to protect calls
that may die.  For example, Perl/Tk runs all callbacks inside an eval{...}.
If a callback dies, Perl/Tk regains control and displays $@ in a dialog
box.  The user can then decide whether to continue or quit from the
program.

`import_rc'/`export_rc'
-----------------------

   I was going to call these methods import and export, but import turns
out not to be a good name for a method, because use also calls import, and
expects different semantics.

   I added the `_rc' suffix to import to avoid this conflict.  It's
reasonably short and somewhat mnemonic (the module manages news*rc* files).
I added the same suffix to export for symmetry.

AUTHOR
======

   Steven McDougall, swmcd@world.std.com

SEE ALSO
========

   perl(1), Set::IntSpan

COPYRIGHT
=========

   Copyright 1996-1998 by Steven McDougall. This module is free software;
you can redistribute it and/or modify it under the same terms as Perl
itself.

gather and report Usenet newsgroup statistics
*********************************************

NAME
====

   News::Scan - gather and report Usenet newsgroup statistics

SYNOPSIS
========

     use News::Scan;

     my $scan = News::Scan->new;

DESCRIPTION
===========

   This module provides a class whose objects can be used to gather and
report Usenet newsgroup statistics.

CONSTRUCTOR
===========

new ( [ OPTIONS ] )
     OPTIONS is a list of named parameters (i.e. given in key-value pairs).
     Valid options are

    Group
          The value of this option is the name of the newsgroup you wish
          to scan.

    From
          The value of this option should be either `'spool'' or `'NNTP''
          (case is not significant).  Any other value will produce an
          error (see the error method description below).  A value of
          `'spool'' indicates that you would like to scan articles in a
          spool (see the Spool option below).  A value of `'NNTP''
          indicates that articles should be retrieved from your NNTP
          server (see the NNTPServer option below).

    Spool
          The value of this option should be the path to the spool
          directory that contains the articles you would like to scan.
          This option is ignored unless the value of From is `'spool''.

    NNTPServer
          The value of this option (in the form server:port, with both
          being optional-see Net/NNTP, for the semantics
          of omitting one or both of these parameters) indicates the NNTP
          server from which to retrieve articles.  This option is ignored
          unless From is `'NNTP''.  See the description of the
          NNTPAuthLogin and NNTPAuthPasswd options below.

    NNTPAuthLogin
          The value of this option should be a valid NNTP authentication
          login for your NNTP server.  This option is only necessary if
          your NNTP server requires authentication.

    NNTPAuthPasswd
          The value of this option should be the password corresponding to
          the login in NNTPAuthLogin.  Having this hardcoded in a script
          is evil, and there should be a much better way.

    Period
          The value of this option indicates the length of the period (in
          days) immediately prior to invocation of the program from which
          you would like to scan articles.  The default period is seven
          (7) days.

    QuoteRE
          The value of this option is a Perl regular expression that
          accepts quoted lines and rejects unquoted or original lines.
          The default regular expression is `^\s{0,3}(?:'|:|\S+>|\+\+)>.

    Exclude
          The value of this option should be a reference to an array
          containing regular expressions that accept email addresses of
          posters whose articles you wish to ignore.

    Aliases
          The value of this option should be a reference to a hash whose
          keys are email addresses that should be transformed into the
          email addresses that are their corresponding values, i.e. `alias
          =' 'real@address'>.

METHODS
=======

configure ( [ OPTIONS ] )
     OPTIONS is a list of named parameters identical to those accepted by
     new.  Re-configure-ing an object after scanning is probably a bad
     idea.  This method returns undef if it encounters an error.

   The following methods are the actual underlying methods used to set and
retrieve the configuration options of the same name (modulo case):

name ( [ NEWSGROUP-NAME ] )
spool ( [ SPOOL-DIRECTORY ] )
period ( [ INTERVAL-LENGTH ] )
aliases ( [ ALIASES-HASHREF ] )
from ( `'NNTP'' | `'spool'' )
quote_re ( [ QUOTE-REGEX-ARRAYREF ] )
exclude ( [ EXCLUSION-REGEX-ARRAYREF ] )
nntp_server ( [ [ NNTP-SERVER ]:[ NNTP-PORT ] ] )
nntp_auth_login ( [ LOGIN ] )
nntp_auth_passwd ( [ PASSWORD ] )
   These methods can be used to retrieve information from the `News::Scan'
object or ask it to perform some action.

error ( [ MESSAGE ] )
     Use this method to determine whether an object has encountered an
     error condition.  The return value of error is guaranteed to be 0
     after any method completes successfully (except error).  (Keep in
     mind that this will also overwrite any previous error message.)  If
     there has been an error, this method should return some useful
     message.

     If provided, `MESSAGE' sets the object's error message.

articles
     Returns the number of articles accounted for.

volume
     Returns the volume of traffic (in bytes) to the newsgroup in the
     period.

header_volume
     Returns the volume (in bytes) generated by headers.

header_lines
     Returns the number of lines consumed by headers.

body_volume
     Returns the volume (in bytes) generated by message bodies.

body_lines
     Returns the number of lines consumed by message bodies.

orig_volume
     Returns the volume (in bytes) of text which has been determined to be
     original (see QuoteRE).  Note that original traffic is a subset of
     body traffic.

orig_lines
     Returns the number of lines that are determined to be original.

signatures
     Returns the number of messages that had a cutline (/^- $/).

sig_volume
     Returns the volume (in bytes) generated by signatures.

sig_lines
     Returns the number of lines consumed by signatures.

earliest ( [ TIME ] )
     Use this method to determine the date (in seconds since the Epoch)
     that the oldest article found within the period was posted to Usenet.

     If TIME is given, it is treated as a candidate for the earliest
     article.  If TIME is successful (i.e. is less than the previous
     earliest), this method returns 1, else 0.

latest ( [ TIME ] )
     Use this method to determine the date (in seconds since the Epoch)
     that the youngest article found within the period was posted to
     Usenet.

     If TIME is given, it is treated as a candidate for the latest
     article.  If TIME is successful (i.e. is greater than the previous
     latest), this method returns 1, else 0.

excludes
     Returns the list of regular expressions used to determine whether an
     article from a given email address should be ignored.

posters
     Returns a reference to a hash whose keys are email addresses and whose
     values are `News::Scan::Poster' objects corresponding to those email
     addresses.  See News/Scan/Poster.

threads
     Returns a reference to a hash whose keys are subjects and whose values
     are `News::Scan::Thread' objects corresponding to those subjects.  See
     News/Scan/Thread.

crossposts
     Returns a reference to a hash whose keys are newsgroup names and whose
     values are the number of times the corresponding groups have been
     crossposted to.

collect
     Use this method to mirror the articles from the specified  NNTP server
     to the specified spool.  Please be kind to the NNTP server.

scan
     Instruct the object to gather information about the newsgroup.

EXAMPLES
========

   See the `eg/' directory in the *News-Scan* distribution, available from
the CPAN-`http://www.perl.com/CPAN/'.

SEE ALSO
========

   See Perlre (perl.info), News/Scan/Poster,
see News/Scan/Thread,
News/Scan/Article, Net/NNTP,

AUTHOR
======

   Greg Bacon <gbacon@cs.uah.edu>

COPYRIGHT
=========

   Copyright (c) 1997 Greg Bacon.  All Rights Reserved.  This library is
free software.  You may distribute and/or modify it under the same terms
as Perl itself.

collect information about news articles
***************************************

NAME
====

   News::Scan::Article - collect information about news articles

SYNOPSIS
========

     use News::Scan::Article;

     my $art = News::Scan::Article->new( ARG, [ OPTIONS, ] SCAN );

DESCRIPTION
===========

   This module provides a derived class of Mail::Internet whose objects
are suitable for digesting Usenet news articles.

CONSTRUCTOR
===========

new ( ARG, [ OPTIONS, ] SCAN-OBJ )
     The ARG and OPTIONS parameters are identical to those required by
     Mail::Internet, except ARG is required.  See Mail/Internet.
     The `SCAN' parameter should be a `News::Scan'
     object.  See News/Scan.

     If the article falls into the period of interest for `SCAN', the
     object is returned, else undef.

METHODS
=======

group ( [ SCAN-OBJ ] )
     Sets or returns an object's group depending on whether `SCAN-OBJ' is
     present.

author
     Returns the article's author represented as a `Mail::Address' object.

message_id
     Returns the article's Message-ID.

subject
     Returns the article's subject.

newsgroups
     Returns the list of newsgroups this article was posted to.

size
     Returns the size of this article in bytes.

header_size
     Returns the size of this article's header in bytes.

header_lines
     Returns the number of lines consumed in this article by headers.

body_size
     Returns the size of this article's body in bytes.

body_lines
     Returns the number of lines consumed in this article by the body.

orig_size
     Returns the size of this article's original content in bytes.  See
     `"QuoteRE"', see News/Scan.

orig_lines
     Returns the number of lines consumed in this article by original
     content.  Keep in mind that original content is a subset of the body.

sig_size
     Returns the size of this article'ss signature in bytes.

sig_lines
     Returns the number of lines consumed in this article by the signature.

SEE ALSO
========

   See News/Scan, Mail/Internet,
Mail/Address,

AUTHOR
======

   Greg Bacon <gbacon@cs.uah.edu>

COPYRIGHT
=========

   Copyright (c) 1997 Greg Bacon.  All Rights Reserved.  This library is
free software.  You may distribute and/or modify it under the same terms
as Perl itself.

keep track of posters to a newsgroup
************************************

NAME
====

   News::Scan::Poster - keep track of posters to a newsgroup

SYNOPSIS
========

     use News::Scan::Poster;

     my $poster = News::Scan::Poster->new($news_scan_article_obj);

DESCRIPTION
===========

   This module provides a class whose objects can be used to keep track of
cumulative statistics for posters to a Usenet newsgroup such as header
volume or signature lines.

CONSTRUCTOR
===========

new ( ARTICLE )
     `ARTICLE' should be a `News::Scan::Article' object or inherit from the
     `News::Scan::Article' class.

     new performs some initialization and returns a `News::Scan::Poster'
     object.

METHODS
=======

address ( [ ADDRESS ] )
     Returns the address of this poster represented as a Mail::Internet
     object.

     If present, `ADDRESS' tells the object that the Mail::Internet object
     in `ADDRESS' is its address.  idea.

attrib ( [ ATTRIBUTION ] )
     Returns some nice attribution for this poster.

     If present, `ATTRIBUTION' tells the object how it shall identify
     itself when asked.

message_ids ( [ MESSAGE-ID ] )
     Returns a list of Message-IDs attributed to this poster.

     If present, `MESSAGE-ID' is added to this list of this poster's
     articles.

volume
     Returns the volume in bytes of the traffic generated by this poster.

articles
     Returns the number of articles attributed to this poster.

posted_to
     Returns a hash whose keys are newsgroup names and whose values are the
     number of times this poster has crossposted to the group of interest
     and the corresponding newsgroup.

crossposts
     Returns the total number of crossposts this poster has sent through
     the group of interest.

header_volume
     Returns the volume in bytes generated by this poster's headers.

header_lines
     Returns the number of header lines generated by this poster.

body_volume
     Returns the volume in bytes generated by this poster's message bodies.

body_lines
     Returns the number of body lines generated by this poster.

orig_volume
     Returns the volume in bytes of original content generated by this
     poster.

orig_lines
     Returns the number of original lines generated by this poster.

sig_volume
     Returns the volume in bytes generated by this poster's signatures.

sig_lines
     Returns the number of signature lines generated by this poster.

SEE ALSO
========

   See News/Scan, Mail/Address,
News/Scan/Article,

AUTHOR
======

   Greg Bacon <gbacon@cs.uah.edu>

COPYRIGHT
=========

   Copyright (c) 1997 Greg Bacon.  All Rights Reserved.  This library is
free software.  You may distribute and/or modify it under the same terms
as Perl itself.

keep track of threads in a Usenet newsgroup
*******************************************

NAME
====

   News::Scan::Thread - keep track of threads in a Usenet newsgroup

SYNOPSIS
========

     use News::Scan::Thread;

     my $thr = News::Scan::Thread->new($news_scan_article_obj);

DESCRIPTION
===========

   This module provides a class whose objects can be used to keep track of
threads of discussion in a Usenet newsgroup.

CONSTRUCTOR
===========

new ( ARTICLE )
     `ARTICLE' should be a `News::Scan::Article' object or an object of
     some class derived from `News::Scan::Article'.

     new performs some initialization and returns a `News::Scan::Thread'.

METHODS
=======

subject
     Returns this thread's subject.

volume
     Returns the volume in bytes generated in this thread.

articles
     Returns the number of posts to this thread.

header_volume
     Returns the volume in bytes of the headers in this thread's articles.

header_lines
     Returns the number of header lines in this thread's articles.

body_volume
     Returns the volume in bytes of the message bodies of this thread's
     articles.

body_lines
     Returns the number of lines in this thread's message bodies.

orig_volume
     Returns the volume in bytes of the original content of this thread's
     articles.

orig_lines
     Returns the number of original lines in this thread's articles.

sig_volume
     Returns the volume in bytes of the signatures of this thread's
     articles.

sig_lines
     Returns the number of signature lines in this thread's articles.

SEE ALSO
========

   See News/Scan, News/Scan/Article,

AUTHOR
======

   Greg Bacon <gbacon@cs.uah.edu>

COPYRIGHT
=========

   Copyright (c) 1997 Greg Bacon.  All Rights Reserved.  This library is
free software.  You may distribute and/or modify it under the same terms
as Perl itself.

Perl bindings for RedHat newt library
*************************************

NAME
====

   Newt - Perl bindings for RedHat newt library

SYNOPSIS
========

     use Newt;

     Newt::Init();
     Newt::Cls();

     #A lot of Newt operations...

     Newt::Finished();

DESCRIPTION
===========

   The Newt module implements perl bindings for the RedHat newt windowing
system, a terminal-based window and widget library for writing
applications with a simple, but user friendly, interface.

Basic Newt functions
====================

`Newt::Init()'
     Starts Newt services. You must use this command first.

`Newt::Finished()'
     Ends Newt services.

`Newt::Cls()'
     Clears the background.

`Newt::Refresh()'
     Foreces an inmediate update of the modified portions of the screen.

`Newt::Bell()'
     Sends a beep to the terminal.

`Newt::GetScreenSize()'
     Returns a tuple containing the screen dimensions.

Keyboard input
==============

`Newt::WaitForKey()'
     Stops program execution until a key is pressed.

`Newt::ClearKeyBuffer()'
     Discards the contents of the terminal's input buffer without waiting
     for additional input.

Drawing text on the root window
===============================

`Newt::DrawRootText($left, $top, $text)'
     Displays the text in the indicated position.

`Newt::PushHelpLine($text)'
     Saves the current help line on a stack and displays the new line. If
     the text is null, Newt's default help line is displayed. If text is a
     string of length 0, the help line is cleared.

`Newt::PopHelpLine()'
     Replaces the current help line with the previous one. It is important
     not to pop more lines than the ones pushed.

Suspending Newt applications
============================

   By default, Newt programs cannot be suspended by the user. Instead,
programs can specify a callback function which gets invoked whe the user
presses the suspend key. To register such function, you can do something
like this:

     sub my_cb {
       ...
     }

     Newt::SetSuspendCallback(\&my_cb);

   If the application should suspend and continue like most user
applications, the suspend callback needs two other newt functions:

     Newt::Suspend();
     Newt::Resume();

   The first one tells Newt to return the terminal to its initial state.
Once this is done, the application can suspend itself by sending SIGSTP,
fork a child program or whatever. When it wants to resume using the Newt
interface, is must call `Newt::Resume()' before doing so.

   For more information on suspending newt applications, read the original
newt documentation.

Components
==========

   Components are the basic blocks for construction of Newt interfaces.
They all are created in a similar manner. You just have to call the
constructor to receive a blessed object of the specified class:

     $object = Newt::Foo();

   Once you have a component, you can add it to a panel to create a
complex user input interface.

General component manipulation
------------------------------

   You can attach a callback for a component like this:

     sub comp_cb {
         ...
     }

     $component->AddCallback(\%comp_cb);

   Exactly when (if ever) the callback is invoked depens on the type of
the component.

   Yo can tell if a component takes or not focus when traversing a form
with the following function:

     $component->TakesFocus($true_or_false);

   It is handy to set some arbitrary information on a component for later
retrieval. You do this by setting its tag:

     $button->Tag("OK");

   If you call this function without an argument, it replies with the
actual tag for that component.

   In general when the return value of any method of a component isn't
described the method returns the component itself to allow contructions
like:

     $panel
     	->Add(0,0, $componet1->Set( .... ) )
     	->Add(0,1, Newt::Label( .... ) )
     	->Add(0,2, Newt::Panel( .... )
     	    ->Add( .... )
     	    ->Add( .... ) )
     	->Add( .... );

Buttons
-------

   There are two kinds of buttons: full and compact:

     $normal_button = Newt::Button($text);
     $compact_button = Newt::CompactButton($text);

Labels
------

   Labels are quite simple:

     $label = Newt::Label($text);

   You can set the text of an existing label like this:

     $label->Set($text);

Entry boxes
-----------

   Entry boxes are used to enter text:

     $entry = Newt::Entry($width, $flags, $initial_text);

   The initial text is optional. After an entry has been created, it's
contents can be set by using:

     $entry->Set($text, $cursor_at_end);

   The last parameter is optional, and signals if the cursor should be
moved to the end of the new value.

   To get the current value of the entry box, you do this:

     $entry->Get();

   You can filter the characters that may be entered by using a callback
filter like this:

     sub my_filter {
       my ($proposed_char, $cursor_position) = @_;

     ...

     return(0) if $char_shoud_be_ignored;
     return($proposed_char)	# Accept the char
         }

     $entry->SetFilter(\&my_filter);

   As can be seen, filter callbacks receive a char and an integer which
indicates the position that the proposed char would take on the entry.
The filter function can return the very same char to indicate that it was
accepted, but it can also return another char, to actually substitute the
original one. If the filter wants to simply reject the keystroke, it only
returns 0.

   When an entry is created, some flags may be specified. The flags are
the following and may be `OR'ed:

`NEWT::NEWT_ENTRY_SCROLL'
     If not specified, the user cannot enter text into the entry box which
     is wider than the entry box itself. This flag removes this limitation,
     and lets the user enter data of an arbitrary length.

`NEWT::NEWT_FLAG_HIDDEN'
     If specified, the value of the entry is not displayed. Useful when an
     applications needs a password.

`NEWT::NEWT_FLAG_RETURNEXIT'
     When specified, the entry will cause the form to stop running if the
     user pressed return inside the entry box. Nice shortcut for users.

Checkboxes
----------

   Newt checkboxes are peculiar, since may have more than two states. To
create a normal one (checked or unchecked), do this:

     $check = Newt::Checkbox("Normal checkbox");

   But you can create, for example, a checkbox that switches form not
checked to checked with an asterisk and then to checked with an 'M':

     $check = Newt::Checkbox("Normal checkbox", " ", " *M");

   As you can see, you can use the two optional parameters to tell the
default char first and then the possible chars.

   To know if a checkbox is checked after the for is ran, you use the
following:

     print "Is checked\n" if $check->Checked();

   And you can always get the actual state like this:

     $state = $check->Get();

Radio groups
------------

   You create two kinds of radio button groups, vertical and horizontal,
by doing this:

     $radio_group1 = Newt::VRadiogroup('Red', 'Green', 'Blue');
     $radio_group2 = Newt::HRadiogroup('Red', 'Green', 'Blue');

   You can put any number of options and the first one will always be
preselected. To know the index of the selected option after the form has
run, you do this:

     $index = $radio_group->Get();

Listboxes
---------

   Listboxes are the most complicated components Newt provides. They can
allow single or multiple selection, and are easy to update. They are
created as follows:

     $listbox = Newt::Listbox($height, $flags);

   A listbox is created at a certain position and a given height. The
$height is used for two things. First of all, it is the minimum height the
listbox will use. If there are less items in the listbox then the height,
suggests the listbox will still take up that minimum amount of space.
Secondly, if the listbox is set to be scrollable (by setting the
`NEWT_FLAG_SCROLL' flag, $height is also the maximum height of the
listbox. If the listbox may not scroll, it increases its height to display
all of its items.

   The following flags may be used when creating a listbox:

`NEWT_FLAG_SCROLL'
     The listbox should scroll to display all of the items it contains.

`NEWT_FLAG_RETURNEXIT'
     When the user presses return on an item in the list, the form should
     return.

`NEWT_FLAG_BORDER'
     A frame is drawn around the listbox, which can make it easier to see
     which listbox has the focus when a form contains multiple listboxes.

`NEWT_FLAG_MULTIPLE'
     By default, a listbox only lets the user select one item in the list
     at a time. When this flag is specified, they may select multiple items
     from the list.

   Once a listbox has been created, items are appended to the bottom like
this:

     $listbox->Append($item1, $item2, ...);

   Appending is not the only way to add items to the list. You can insert
items in any position by telling the item that should be before with the
following command:

     $listbox->Insert($before, $item1, $item2, ...);

   And you can change any item just by telling:

     $listbox->Set($original, $new);

   Of course you can delete entries:

     $listbox->Delete($item1, $item2, ...);

   Or just clear out the listbox:

     $listbox->Clear();

   You can select and unselect items, with the following:

     $listbox->Select($item1, $item2, ...);

     $listbox->Unselect($item1, $item2, ...);

     $listbox->ClearSelection();

   but if you did not sepecify the flag `NEWT_FLAG_MULTIPLE' when
constructing your listbox, only the last item on the argument list of
`Unselect()' will remain selected.

   To get a list of the selected items, just issue:

     @selected_items = $listbox->Get();

Scales
------

   Scales provide an easy way for telling the user the advance on some
lengthy operation. It is a horizontal bar graph which the application
updates as the operation continues:

     $scale = Newt::Scale($width, $fullvalue);

   It is set as expected:

     $scale->Set($amount);

Textboxes
---------

   A text box is used for displaying large amounts of text. They are
created as follows:

     $textbox = Newt::Textbox($width, $height, $flags, $text, ...);

   The $text parameter is optional, and if not supplied, the textbox is
created only, but it does not fill it with data. To do so, use:

     $textbox->Set($text, ...);

   All the arguments are simply concatenated using the double quote
operator.

   The flags that can be passed to the cronstuctor are the following:

`NEWT_FLAG_WRAP'
     All text in the textbox should be wrapped to fit the width of the
     textbox. If this flag is not specified, each newline delimited line in
     the text is truncated if it is too long to fit.

     When Newt wraps text, it tries not to break lines on spaces or tabs.
     Literal newline characters are respected, and may be used to force
     line breaks.

`NEWT_FLAG_SCROLL'
     The text shoud be scrollable. When this option is used, the scrollbar
     which is added increases the width of the area used by the textbox by
     2 characters.

Reflowing text
--------------

   When applications need to display large amounts of text, it is common
not to know exactly where the linebreaks should go. While textboxes are
quite willing to scroll the text, the programmer still must know what
width the text will look "best" at (where "best" means most exactly
rectangular; no lines much shorter or much longer then the rest). This
common is specially prevalent in internationalized programs, which need to
make a wide variety of message string look good on a screen.

   To help with this, Newt provides routines to reformat text to look
good. It tries different widths to figure out which one will look "best"
to the user. As these commons are almost always used to format text for
textbox components, Newt makes it easy to construct a textbox with
reflowed text.

   The following function reflows the provided text to a target width. the
actual width of the longest line in the returned text is between `$width -
$flexdown' and `$width + $flexup'; the actual maximum line length is
chosen to make displayed text look rectangular. The function returns a
tuple consisting of the reflowed text and the actual width and height of
it.

     ($r_text, $width, $height) = Newt::ReflowText($width,
                                                   $flexdown,
                                                   $flexup,
     						  $text);

   When the reflowed text is being placed in a textbox it may be easier to
use the following:

     $textbox = Newt::TextboxReflowed($width, $flexdown,
                                      $flexup, $flags,
     				     $text, ...);

   which creates a textbox, reflows the text, and places the reflowed text
in the listbox. Its parameters consist of the position of the final
textbox, the width and flex values for the text (which are identical to
the parameters passed to `Newt::Reflow()', and the flags for the textbox
(which are the same as the flags for C<Newt::Textbox(). This function does
not let you limit the height of the textbox, however, making limiting its
use to contructing textboxes which do not need to scroll.

   To find out how tall the textbox created by `Newt::TextboxReflowed()'
is, use `Newt::GetNumLines()', which returns the number of lines in the
textbox. For textboxes created by `Newt::TextboxReflowed()'/, this is
always the same as the height of the textbox.

   Please note that the order of the parameters of Newt::ReflowText and
Newt::TextboxReflowed differs from the C API to allow lists of text but
currently only TextboxReflowed allows this.

Scrollbars
----------

   Scrollbars may be attached to forms to let them contain more data than
they have space for. Currently, there can only be vertical scrollbars:

     $scroll = Newt::VScrollbar($height,
                                $normalColorset,
                                $thumbColorset);

   When a scrollbar is created, it is given a position on the screen, a
height, and two colors. The first color is the color used for drawing the
scrollbar, and the second color is used for drawing the thumb. This is the
only place in newt where an application specifically sets colors for a
component. It s done here to let the colors a scrollbar use match the
colors of the component the scrollbar is mated too. When a scrollbar is
being used with a form, `$normalColorset' is often `NEWT_COLORSET_WINDOW'
and `$thumbColorset' `NEWT_COLORSET_ACTCHECKBOX'.

   If you do not want to bother with colors, you can ommit the last two
parameters and let Newt use the defaults.

   As the scrollbar is normally updated by the component it is mated with,
there is no public interface for moving the thumb.

Panels
======

   Panels are high level grid-like constructs that are used to group
components. You create them by specifying the number of columns and rows
you want, as well as a caption to be used when the panel is displayed as a
toplevel:

     $panel = Newt::Panel(2, 3, "Panel example");

   When run, panesl are centered by default, but you can specify a
position relative to the topleft corner of the screen by appending two
optional integers:

     $panel = Newt::Panel(2, 3, "Panel example", 5, 5);

   Adding components to a panel is straightforward, you just have to
indicate the position the component will take in the grid:

     $panel1->Add(0, 0, $mycomponent);

   Several optional parameters my however be used when adding components:

     $panel1->Add($col,
                  $row,
                  $mycomponent,
                  $anchor,
                  $padleft,
                  $padtop,
                  $padright,
                  $padbottom,
                  $flag);

   You can specify the side of the cell to which the component will be
aligned by specifying an anchor. The anchor values avalaible are
`NEWT_ANCHOR_LEFT', `NEWT_ANCHOR_RIGHT', `NEWT_ANCHOR_TOP',
`NEWT_ANCHOR_BOTTOM'.

   You can ask for more space on the sides of the component, perhaps to
get a cleaner, less cluttered presentation using the padding parameters,
and specifiying an integer value.

   Panels may be nested. For this to be done you only have to add a panel
to another as you would with any other component.

   To run a panel as a toplevel and get user input, you may do the
following:

     ($reason, $data) = $panel->Run();

     if ($reason eq NEWT_EXIT_HOTKEY) {
       if ($data eq NEWT_KEY_F12) {
         print "F12 hotkey was pressed\n";
       } else {
         print "Some hotkey other than F12 was pressed\n";
       }
     } else {
       print 'Form terminated by button ', $data->Tag(), "\n";
     }

   As can be seen on the example, when called in a list context `Run()'
returns two values, one is the reason why the form terminated and the
other is an associated data. In a scalar context only the data is
returned. Posible values for the reason are:

`NEWT_EXIT_HOTKEY'
     The form exited because a hotkey was pressed. The associated data
     contains the key pressed, that is, one of NEWT_KEY_* values. See
     Hotkeys later for more information.

`NEWT_EXIT_COMPONENT'
     The form exited because a component was activated, a button, for
     instance a button. The associated data is a reference to the
     component involved.

Hotkeys
-------

   Normally, a panel terminates when the user presses a button, but you
can define some keys as "hotkeys" that will make the `Run()' function
return with `NEWT_EXIT_HOTKEY'. Yo do this by issuing the folowing:

     $panel->AddHotKey(NEWT_KEY_F11);

   F12 is always defined to be a hotkey.

Drawing panels instead uf running them
--------------------------------------

   When you run a panel the terminal is blocked until the user presses a
component or a key that causes the panel to exit. Sometimes is useful to
present the interface to the user without blocking the execution of code.
This can be done by only drawing the panel, not running it. It is easy to
show an advance status for a lengthy operation liek this:

     $i = 1;
     foreach (@items) {
        $label->Set("Processing item $i");
        $panel->Draw();
        $scale->Set($i);
        process_item($_);
        $i++
     }

Hiding panels
-------------

   Panels can be hidden in case you want by using the following:

     $panel->Hide()

Constants
=========

   You can import all the constants exported by this package as needed qor
using several predefined tags, with the folowing syntax:

     use Newt qw(:exits :keys);

exits NEWT_EXIT_* constants
keys NEWT_KEY_* constants
anchors NEWT_ANCHOR_* constants
colorsets NEWT_COLORSET_* constanst
flags NEWT_FLAG_* constants
entry NEWT_ENTRY_* constants
fd NEWT_FD_* constants
grid NEWT_GRID_* constants
textbox NEWT_TEXTBOX_* constants
macros
     macros to make useful buttons and panels: OK_BUTTON, CANCEL_BUTTON,
     QUIT_BUTTON, BACK_BUTTON, OK_CANCEL_PANEL, OK_BACK_PANEL. this macros
     only create componetnts which are properly tagged.

TO DO
=====

Scrollable panels.
Some forms stuff, like watching file descriptors.
SEE ALSO
========

   *Writing programs using Newt*, by Eric Troan.

THANKS TO
=========

   Eric Troan, for writing this useful library. Thanks for his tutorial,
too, from where I stole complete paragraphs for this documentation, I'm
afraid.

AUTHOR
======

   The original author of the RedHat newt library is Erik Troan,
<*ewt@redhat.com*> The author of this Perl bindings is Alejandro Escalante
Medina, <*amedina@msg.com.mx*>

DATE
====

   Version 0.1, 5th Nov 1998

Norwegian dates
***************

NAME
====

   No::Dato - Norwegian dates

SYNOPSIS
========

     use No::Dato qw(tekstdato helligdag helligdager);

     print tekstdato(time), "\n";
     if (helligdag(time)) {
         print "Idag er det ", helligdag(time), "\n";
     }

     for (helligdager()) {
         print "$_\n";
     }

DESCRIPTION
===========

   *This documentation is written in Norwegian.*

   Denne modulen tilbyr funksjoner for å håndtere det som er spesielt med
datoer på norsk.  Dette gjelder blandt annet å finne fram til de norske
helligdagene.

   Følgende funksjoner er tilgjengelig:

tekstdato($time)
     Denne rutinen returnerer en dato formatert på formen:

          Fredag, 7. februar 1997

     Argumentet er en vanlig perl $time verdi.  Hvis argumentet utelates så
     benyttes dagens dato.

helligdag($time)
     Rutinen avgjør om en gitt dato er en norsk helligdag eller ikke.  Hvis
     det er en helligdag så vil navnet på helligdagen bli returnert.  Hvis
     det er en vanlig hverdag så vil en tom streng (som er FALSE i perl)
     bli returnert.

     Argumentet kan være en vanlig $time verdi eller en streng på formen
     "ÅÅÅÅ-MM-DD".

helligdager($year)
     Denne rutinen vil returnere en liste av datostrenger, én for hver
     helligdag i året gitt som argument.  Hvis argumentet mangler vil vi
     bruke inneværende år.  Datostrengene er på formen:

          "ÅÅÅÅ-MM-DD Skjærtorsdag"

     Dvs. datoen formattert i henhold til ISO 8601 etterfulgt av navnet på
     helligdagen.  Listen vil være sortert på dato.

SEE ALSO
========

   See HTTP/Date, som kan konvertere til og fra ISO 8601
formaterte datoer (ÅÅÅÅ-MM-DD).

AUTHOR
======

   Gisle Aas <gisle@aas.no>

Check Norwegian bank account numbers
************************************

NAME
====

   No::KontoNr - Check Norwegian bank account numbers

SYNOPSIS
========

     use No::KontoNr qw(kontonr_ok);

     if (personnr_ok($nr)) {
         # ...
     }

DESCRIPTION
===========

   *This documentation is written in Norwegian.*

   Denne modulen kan brukes for å sjekke norske bankontonumre.  Det siste
sifferet i et banknummer er kontrollsiffer og må stemme overens med resten
for at det skal være et gyldig nummer.

   Modulen inneholder også funksjoner for å regne ut modulus 10 og modulus
11 kontrollsiffer.  Disse algoritmene brukes blandt annet hvis du vil
generere KID når du skal fylle ut giroblanketter.  De finnes også en
fuksjon som kan brukes for å formatere kronebeløp.

   Ingen av funksjonene eksporteres implisitt.  Du må be om dem.  Følgende
funksjoner er tilgjengelig:

kontonr_ok($nr)
     Funksjonen kontonr_ok() vil returnere FALSE hvis kontonummeret gitt
     som argument ikke er gyldig.  Hvis nummeret er gyldig så vil
     funksjonen returnere $nr på standard form (11 siffer for
     bankkontonummer og 7 siffer for gamle postgironummer) .  Nummeret som
     gis til kontonr_ok() kan inneholde blanke eller punktumer.

kontonr_f($nr)
     Funksjonen kontonr_f() vil formattere et kontonummer på standard form
     ("####.##.#####").  Hvis kontonummeret ikke er gyldig så byttes alle
     sifferene ut med "?".

kredittkortnr_ok($nr)
     Funksjonen kredittkortnr_ok() vil returnere FALSE hvis
     kredittkortnummeret gitt som argument ikke er gyldig.  Hvis nummeret
     er gyldig så vil funksjonen returnere kortselskapets navn.  Nummeret
     som gis til kredittkortnr_ok() kan inneholde blanke eller punktumer.

nok_f($tall)
     Denne funksjonen vil formatere tall på formen:

          300,50
             4.300,-

     Det skulle passe bra når man skal skrive ut kronebeløp.  Ørebeløpet
     "00" byttes ut med strengen "- ", dvs. at tallene laines opp korrekt
     hvis du høyrejusterer dem.

mod_10($tall)
     Denne funksjonen regner ut modulus 10 kontrollsifferet til tallet gitt
     som argument.  Hvis argumentet inneholder tegn som ikke er siffer så
     ignoreres de.

     Modulus 10 algoritmen benyttes blandt annet for å generere
     kontrollsiffer til de fleste internasjonale kredittkortnummer.

mod_11($tall)
     Denne funksjonen regner ut modulus 11 kontrollsifferet til tallet gitt
     som argument.  Hvis argumentet inneholder tegn som ikke er siffer så
     ignoreres de.  Når denne algoritmen benyttes så kan det være tall som
     det ikke finnes noe gyldig kontrollsiffer for, og da vil mod_11()
     returnere verdien undef.

     Modulus 11 algoritmen benyttes blandt annet for å generere
     kontrollsiffer til norske bankkontonummer.

SEE ALSO
========

   `Business::CreditCard' in this node

AUTHOR
======

   Gisle Aas <gisle@aas.no>

Check Norwegian Social security numbers
***************************************

NAME
====

   No::PersonNr - Check Norwegian Social security numbers

SYNOPSIS
========

     use No::PersonNr qw(personnr_ok);

     if (personnr_ok($nr)) {
         # ...
     }

DESCRIPTION
===========

   *This documentation is written in Norwegian.*

   Denne modulen kan brukes for å sjekke norske personnummer.  De 2 siste
siffrene i personnummerene er kontrollsiffre og må stemme overens med
resten for at det skal være et gyldig nummer.  Modulen inneholder også
funksjoner for å bestemme personens kjønn og personens fødselsdato.

   Ingen av rutinene eksporteres implisitt.  Du må be om dem.  Følgende
funksjoner er tilgjengelig:

personnr_ok($nr)
     Funksjonen personnr_ok() vil returnere FALSE hvis personnummeret gitt
     som argument ikke er gyldig.  Hvis nummeret er gyldig så vil
     funksjonen returnere $nr på standard form.  Nummeret som gis til
     personnr_ok() kan inneholde ' ' eller '-'.

er_mann($nr)
     Vil returnere TRUE hvis $nr tilhører en mann.  Rutinen vil croake hvis
     nummeret er ugyldig.

er_kvinne($nr)
     Vil returnere TRUE hvis $nr tilhører en kvinne.  Rutinen vil croake
     hvis nummeret er ugyldig.

fodt_dato($nr)
     Vil returnere personens fødselsdato på formen "ÅÅÅÅ-MM-DD".  Rutinen
     returnerer "" hvis nummeret er ugyldig.

BUGS
====

   Denne koden vil få problemer for personer født etter år 2054.

AUTHOR
======

   Gisle Aas <gisle@aas.no>

Norwegian sorting
*****************

NAME
====

   No::Sort - Norwegian sorting

SYNOPSIS
========

     use No::Sort;
     @sortert = no_sort @norske_ord;

DESCRIPTION
===========

   This module provde the function no_sort() which sort a ISO-8859/1
encoded string according to Norwegian practice.  The routine works like
the normal perl sort routine, but the optional first argument is special.
It can either be a reference to the strxfrm() function to use while
sorting or a reference to a hash used to transform the words while sorting.

   You can also import the no_xfrm() function which is used for standard
sorting.  It can be useful to base your custom transformation function on
it.  If we for instance would like to sort "Aa" as "Å" we could implement
it like this:

     use No::Sort qw(no_sort no_xfrm);
     sub my_xfrm {
         my $word = shift;
         $word =~ s/A[aA]/Å/g;
         $word =~ s/aa/å/g;
         no_xfrm($word);
     }
     @sorted = no_sort \&my_xfrm, @names;

   By the way, the my_xfrm shown in this example can be imported from this
module under the name 'no_aa_xfrm':

     use No::Sort qw(no_sort no_aa_xfrm);
     @sorted = no_sort \&no_aa_xfrm, @names;

   If you set the $No::Sort::DEBUG variable to a TRUE value, then we will
make some extra noise on STDOUT while sorting.

   The module can also export functions for up/down casing ISO-8859/1
strings.  These functions are called latin1_uc(), latin1_lc(),
latin1_ucfirst(), latin1_lcfirst().

SEE ALSO
========

   See Perllocale (perl.info),

AUTHORS
=======

   Hallvard B Furuseth <h.b.furuseth@usit.uio.no>, Gisle Aas <gisle@aas.no>

Calculate telephone call prices in Norway
*****************************************

NAME
====

   No::Telenor - Calculate telephone call prices in Norway

SYNOPSIS
========

     use No::Telenor qw(samtale_pris);
     $kr = samtale_pris($time, 3600, "N");

DESCRIPTION
===========

   *This documentation is written in Norwegian.*

   Denne modulen inneholder funksjonen samtale_pris().  Denne funksjonen
vil beregne prisen på en telefonsamtale gitt tidspunkt, varighet og takst
som parameter.  Funksjonen kjenner til Telenors sanntidstakster som
gjelder fra 1. juni 1999.  Forhåpentligvis vil jeg klare å oppdater
funksjonen etterhvert som Telenor finner på nye sprell.

samtale_pris($start, $varighet, $takst)
     Rutinen vil beregne samtale prisen i NOK.  Argumentet $start er
     starttidspunktet gitt som en standard perl 'time' verdi.  Argumentet
     $varighet er samtalens varighet i sekunder.  Argumentet $takst er en
     kort streng som forteller hvilken takst som skal brukes.  Følgende
     takser er støttet:

          N     Norgespris
          TM    Telenor Mobil
          NC    NetCom Mobil
          180   Opplysningen 180
          181   UtenlandsOpplysningen 181

BUGS
====

   Prisberegningen kan bli unøyaktig hvis samtalen foregikk i overgangen
mellom vinter- og sommertid eller omvendt.

   Prisberegningen tar ikke hensyn til at helgetakst skal benyttes på
bevegelige helligdager.

AUTHOR
======

   Gisle Aas <gisle@aas.no>

Encode bit strings into digit strings
*************************************

NAME
====

   Number::Encode - Encode bit strings into digit strings

SYNOPSIS
========

     use Number::Encode qw(nonuniform uniform);

DESCRIPTION
===========

   Provides  a mechanism  to convert  arbitrary bit-strings  into numeric
digit  strings.  The  transformation  can be  uniform  or  non-uniform
depending on the type of distribution of the numeric digits achieved.

   The former  approach is useful for  security-related applications such
as  calling  cards  and  the  such,  which  require  a  uniform  digit
distribution.  The  algorythm used to  generate uniform distributions,
while deterministic, is more constly than the non-uniform variant.

   This module is  distributed under the same terms  and warranty as Perl
itself.

EXPORT
------

   This module provides the following exports:

`my $number = nonuniform($data)'
     Converts  a  bit-string  represented  in  the example  by  the  scalar
     $data   to   a    numeric   string   representation   returned   at
     `$number'.

     The probabilistic  distribution of the digits in  the resulting number
     is not uniform. Some digits will have up to twice the chance of others
     of appearing at a given position.

`my $number = uniform($data)'
     Performs a transformation from  the bit-string provided in $data to a
     numeric string returned at  `$number'. This transformation is a bit
     more  costly but  has the  advantage  that the  digit distribution  is
     uniform.  This  function is adequate  for applications that  require a
     uniform composition  of the numeric  strings, such as password  or PIN
     number generators.

HISTORY
=======

  1. Original version; created by h2xs 1.20 with options

          -ACOXfn
          	Number::Encode
          	-v
          	1.00

AUTHOR
======

   Luis E. Munoz <lem@cantv.net>

SEE ALSO
========

   perl(1).

Perl extension for formatting numbers
*************************************

NAME
====

   Number::Format - Perl extension for formatting numbers

SYNOPSIS
========

     use Number::Format;
     my $x = new Number::Format %args;
     $formatted = $x->round($number, $precision);
     $formatted = $x->format_number($number, $precision, $trailing_zeroes);
     $formatted = $x->format_negative($number, $picture);
     $formatted = $x->format_picture($number, $picture);
     $formatted = $x->format_price($number, $precision);
     $formatted = $x->format_bytes($number, $precision);
     $number    = $x->unformat_number($formatted);

     use Number::Format qw(:subs);
     $formatted = round($number, $precision);
     $formatted = format_number($number, $precision, $trailing_zeroes);
     $formatted = format_negative($number, $picture);
     $formatted = format_picture($number, $picture);
     $formatted = format_price($number, $precision);
     $formatted = format_bytes($number, $precision);
     $number    = unformat_number($formatted);

REQUIRES
========

   Perl, version 5.003 or higher.

   POSIX.pm will be used if present to determine locale settings.

   Carp.pm is used for some error reporting.

DESCRIPTION
===========

   These functions provide an easy means of formatting numbers in a manner
suitable for displaying to the user.

   There are two ways to use this package.	 One is to declare an
object of type Number::Format, which you can think of as a formatting
engine.  The various functions defined here are provided as object methods.
The constructor new() can be used to set the parameters of the formatting
engine.  Valid parameters are:

     THOUSANDS_SEP	    - character inserted between groups of 3 digits
     DECIMAL_POINT	    - character separating integer and fractional parts
     MON_THOUSANDS_SEP - like THOUSANDS_SEP, but used for format_price
     MON_DECIMAL_POINT - like DECIMAL_POINT, but used for format_price
     INT_CURR_SYMBOL   - character(s) denoting currency (see format_price())
     DECIMAL_DIGITS    - number of digits to the right of dec point (def 2)
     DECIMAL_FILL	    - boolean; whether to add zeroes to fill out decimal
     NEG_FORMAT	    - format to display negative numbers (def ``-x'')
     KILO_SUFFIX	    - suffix to add when format_bytes formats kilobytes
     MEGA_SUFFIX	    - suffix to add when format_bytes formats megabytes

   They may be specified in upper or lower case, with or without a leading
hyphen ( - ).

   The defaults for `THOUSANDS_SEP', `DECIMAL_POINT', `MON_THOUSANDS_SEP',
`MON_DECIMAL_POINT', and `INT_CURR_SYMBOL' come from the POSIX locale
information (see Perllocale (perl.info)), if available.
If your POSIX locale does not provide `MON_THOUSANDS_SEP' and/or
`MON_DECIMAL_POINT' fields, then the `THOUSANDS_SEP' and/or
`DECIMAL_POINT' values are used for those parameters.  Some systems (e.g.
Win32 ports of Perl) do not include POSIX support.  In those systems, the
POSIX system is bypassed.

   If any of the above parameters are not specified when you invoke new(),
then the values are taken from package global variables of the same name
(e.g.  `$DECIMAL_POINT' is the default for the `DECIMAL_POINT' parameter).
If you use the `:vars' keyword on your `use Number::Format' line (see
non-object-oriented example below) you will import those variables into
your namesapce and can assign values as if they were your own local
variables.  The default values for all the parameters are:

     THOUSANDS_SEP	    = ','
     DECIMAL_POINT	    = '.'
     MON_THOUSANDS_SEP = ','
     MON_DECIMAL_POINT = '.'
     INT_CURR_SYMBOL   = 'USD '
     DECIMAL_DIGITS    = 2
     DECIMAL_FILL	    = 0
     NEG_FORMAT	    = '-x'
     KILO_SUFFIX	    = 'K'
     MEGA_SUFFIX	    = 'M'

   Note however that when you first call one of the functions in this
module *without* using the object-oriented interface, further setting of
those global variables will have no effect on non-OO calls.	It is
recommended that you use the object-oriented interface instead for fewer
headaches and a cleaner design.

   The `DECIMAL_FILL' and `DECIMAL_DIGITS' values are not set by the
Locale system, but are definable by the user.  They affect the output of
`format_number()'.	Setting `DECIMAL_DIGITS' is like giving that value as
the $precision argument to that function.  Setting `DECIMAL_FILL' to a
true value causes `format_number()' to append zeroes to the right of the
decimal digits until the length is the specified number of digits.

   `NEG_FORMAT' is only used by `format_negative()' and is a string
containing the letter 'x', where that letter will be replaced by a
positive representation of the number being passed to that function.
`format_number()' and `format_price()' utilize this feature by calling
`format_negative()' if the number was less than 0.

   `KILO_SUFFIX' and `MEGA_SUFFIX' are used by `format_bytes()' when the
value is over 1024 or 1024*1024, respectively.  The default values are "K"
and "M".

   The only restrictions on `DECIMAL_POINT' and `THOUSANDS_SEP' are that
they must not be digits, must not be identical, and must each be one
character.  There are no restrictions on `INT_CURR_SYMBOL'.

   For example, a German user might include this in their code:

     use Number::Format;
     my $de = new Number::Format(-thousands_sep   => '.',
     			      -decimal_point   => ',',
     			      -int_curr_symbol => 'DEM');
     my $formatted = $de->format_number($number);

   Or, if you prefer not to use the object oriented interface, you can do
this instead:

     use Number::Format qw(:subs :vars);
     $THOUSANDS_SEP   = '.';
     $DECIMAL_POINT   = ',';
     $INT_CURR_SYMBOL = 'DEM';
     my $formatted = format_number($number);

EXPORTS
=======

   Nothing is exported by default.	 To export the functions or the global
variables defined herein, specify the function name(s) on the import list
of the `use Number::Format' statement.  To export all functions defined
herein, use the special tag `:subs'.  To export the variables, use the
special tag `:vars'; to export both subs and vars you can use the tag :all.

METHODS
=======

new( %args )
     Creates a new Number::Format object.  Valid keys for %args are any of
     the parameters described above.	 Keys may be in all uppercase or all
     lowercase, and may optionally be preceded by a hyphen (-) character.
     Example:

          my $de = new Number::Format(-thousands_sep   => '.',
          			      -decimal_point   => ',',
          			      -int_curr_symbol => 'DEM');

round($number, $precision)
     Rounds the number to the specified precision.  If $precision is
     omitted, the value of the `DECIMAL_DIGITS' parameter is used (default
     value 2).  Both input and output are numeric (the function uses math
     operators rather than string manipulation to do its job), The value of
     $precision may be any integer, positive or negative. Examples:

          round(3.14159)       yields	 3.14
          round(3.14159, 4)    yields	 3.1416
          round(42.00, 4)      yields	 42
          round(1234, -2)      yields	 1200

     Since this is a mathematical rather than string oriented function,
     there will be no trailing zeroes to the right of the decimal point,
     and the `DECIMAL_POINT' and `THOUSANDS_SEP' variables are ignored.
     To format your number using the `DECIMAL_POINT' and `THOUSANDS_SEP'
     variables, use `format_number()' instead.

format_number($number, $precision, $trailing_zeroes)
     Formats a number by adding `THOUSANDS_SEP' between each set of 3
     digits to the left of the decimal point, substituting `DECIMAL_POINT'
     for the decimal point, and rounding to the specified precision using
     `round()'.  Note that $precision is a maximum precision specifier;
     trailing zeroes will only appear in the output if `$trailing_zeroes'
     is provided, or the parameter `DECIMAL_FILL' is set, with a value
     that is true (not zero, undef, or the empty string).  If $precision
     is omitted, the value of the `DECIMAL_DIGITS' parameter (default
     value of 2) is used.  Examples:

          format_number(12345.6789)	 yields	  '12,345.68'
          format_number(123456.789, 2)	 yields	  '123,456.79'
          format_number(1234567.89, 2)	 yields	  '1,234,567.89'
          format_number(1234567.8, 2)	 yields	  '1,234,567.8'
          format_number(1234567.8, 2, 1) yields	  '1,234,567.80'
          format_number(1.23456789, 6)	 yields	  '1.234568'

     Of course the output would have your values of `THOUSANDS_SEP' and
     `DECIMAL_POINT' instead of ',' and '.' respectively.

format_negative($number, $picture)
     Formats a negative number.  Picture should be a string that contains
     the letter x where the number should be inserted.  For example, for
     standard negative numbers you might use "-x", while for accounting
     purposes you might use "`(x)'".  If the specified number begins with
     a "-" character, that will be removed before formatting, but
     formatting will occur whether or not the number is negative.

format_picture($number, $picture)
     Returns a string based on `$picture' with the `#' characters replaced
     by digits from `$number'.  If the length of the integer part of
     $number is too large to fit, the `#' characters are replaced with
     asterisks (*) instead.  Examples:

          format_picture(100.023, 'USD ##,###.##')   yields   'USD    100.02'
          format_picture(1000.23, 'USD ##,###.##')   yields   'USD  1,000.23'
          format_picture(10002.3, 'USD ##,###.##')   yields   'USD 10,002.30'
          format_picture(100023,  'USD ##,###.##')   yields   'USD **,***.**'
          format_picture(1.00023, 'USD #.###,###')   yields   'USD 1.002,300'

     The comma (,) and period (.) you see in the picture examples should
     match the values of `THOUSANDS_SEP' and `DECIMAL_POINT',
     respectively, for proper operation.  However, the `THOUSANDS_SEP'
     characters in `$picture' need not occur every three digits; the
     *only* use of that variable by this function is to remove leading
     commas (see the first example above).  There may not be more than one
     instance of `DECIMAL_POINT' in `$picture'.

     The value of `NEG_FORMAT' is used to determine how negative numbers
     are displayed.  The result of this is that the output of this function
     my have unexpected spaces before and/or after the number.  This is
     necessary so that positive and negative numbers are formatted into a
     space the same size.  If you are only using positive numbers and want
     to avoid this problem, set NEG_FORMAT to "x".

format_price($number, $precision)
     Returns a string containing `$number' formatted similarly to
     `format_number()', except that the decimal portion may have trailing
     zeroes added to make it be exactly $precision characters long, and
     the currency string will be prefixed.

     If the `INT_CURR_SYMBOL' attribute of the object is the empty string,
     no currency will be added.

     If $precision is not provided, the default of 2 will be used.
     Examples:

          format_price(12.95)	yields	 'USD 12.95'
          format_price(12)	yields	 'USD 12.00'
          format_price(12, 3)	yields	 '12.000'

     The third example assumes that `INT_CURR_SYMBOL' is the empty string.

format_bytes($number, $precision)
     Returns a string containing `$number' formatted similarly to
     `format_number()', except that if the number is over 1024, it will be
     divided by 1024 and "K" appended to the end; or if it is over 1048576
     (1024*1024), it will be divided by 1048576 and "M" appended to the
     end.  Negative values will result in an error.

     If $precision is not provided, the default of 2 will be used.
     Examples:

          format_bytes(12.95)	yields	 '12.95'
          format_bytes(2048)	yields	 '2K'
          format_bytes(1048576) yields	 '1M'

unformat_number($formatted)
     Converts a string as returned by `format_number()', `format_price()',
     or `format_picture()', and returns the corresponding value as a
     numeric scalar.  Returns undef if the number does not contain any
     digits.  Examples:

          unformat_number('USD 12.95')	 yields	  12.95
          unformat_number('USD 12.00')	 yields	  12
          unformat_number('foobar')	 yields	  undef
          unformat_number('1234-567@.8') yields	  1234567.8

     The value of `DECIMAL_POINT' is used to determine where to separate
     the integer and decimal portions of the input.	All other non-digit
     characters, including but not limited to `INT_CURR_SYMBOL' and
     `THOUSANDS_SEP', are removed.

     If the number matches the pattern of `NEG_FORMAT' or there is a "-"
     character before any of the digits, then a negative number is
     returned.

     If the number ends with the `KILO_SUFFIX' or `MEGA_SUFFIX'
     characters, then the number returned will be multiplied by 1024 or
     1024*1024 as appropriate.

BUGS
====

   No known bugs at this time.  Please report any problems to the author.

AUTHOR
======

   William R. Ward, wrw@bayview.com

SEE ALSO
========

   perl(1).

convert to/from the number system "a,b,...z,aa,ab..."
*****************************************************

NAME
====

   Number::Latin - convert to/from the number system "a,b,...z,aa,ab..."

SYNOPSIS
========

     use Number::Latin;
     print join(' ', map int2latin($_), 1 .. 30), "\n";
      #
      # Prints:
      #  a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad

DESCRIPTION
===========

   Some applications, notably the numbering of points in outlines, use a
scheme that starts with the letter "a", goes to "z", and then starts over
with "aa" thru "az", then "ba", and so on.  (The W3C refers to this
numbering system as "lower-latin"/"upper-latin" or "lower alpha"/"upper
alpha", in discussions of HTML/CSS options for rendering of list elements
(OL/LI).)

   This module provides functions that deal with that numbering system,
converting between it and integer values.

FUNCTIONS
---------

   This module exports four functions, `int2latin', `int2Latin',
`int2LATIN', and `latin2int':

$latin = int2latin( INTEGER )
     This returns the INTEGERth item in the sequence `('a' .. 'z', 'aa',
     'ab', etc)'.  For example, `int2latin(1)' is `"a"', `int2latin(2)' is
     `"b"', `int2latin(26)' is `"z"', `int2latin(30)' is `"ad"', and so
     for any nonzero integer.

$latin = int2Latin( INTEGER )
     This is just like `int2latin', except that the return value is has an
     initial capital.  E.g., `int2Latin(30)' is `"Ad"'.

$latin = int2LATIN( INTEGER )
     This is just like `int2latin', except that the return value is in all
     uppercase.  E.g., `int2LATIN(30)' is `"AD"'.

$latin = latin2int( INTEGER )
     This converts back from latin number notation (regardless of
     capitalization!) to an integer value.  E.g., `latin2int("ad")' is 30.

NOTES
=====

   The latin numbering system is not to be confused with Roman numerals,
in spite of their names.

   The latin numbering system isn't a normal base-N number system (thus
making this module necessary), as evidenced by the fact that the item
after "z" is "aa".  If you considered this to be a base-26 numbering
system (running from a-z for 0-25), then after "z" would be "ba"; if you
considered it a base-27 numbering system (running from a-z for 1-26), then
after "z" would be "a" followed by some sort of placeholder zero.  But
it's neither.

   I vaguely remember reading, years ago, of some languages (in New
Guinea?) with count-number systems that work like the latin number system
- i.e., where either the number after "nine" is "one-MULT one", or the
number after "ten" is "one-MULT one".  However, I haven't been able to
find a reference for exactly what language(s) those were number system; I
welcome email on the subject.

COPYRIGHT
=========

   Copyright (c) 1997- by Abigail, and 2001- Sean M. Burke.  All rights
reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Roman' in this node

   `http://www.w3.org/TR/REC-CSS2/generate.html#lists'

   `http://people.netscape.com/ftang/i18n.html'

   `http://people.netscape.com/ftang/number/draft.html'

AUTHOR
======

   Initial implementation in a `comp.lang.perl.misc' post by Abigail
(`abigail@foad.org') in 1997.  Documentation, further doings, and current
maintenance by Sean M. Burke, `sburke@cpan.org'

Validate US phone numbers
*************************

NAME
====

   Number::Phone::US - Validate US phone numbers

SYNOPSIS
========

     use Number::Phone::US qw(is_valid_number);

     &do_that_thing if is_valid_number($input);

DESCRIPTION
===========

   Number::Phone::US is a simple module to validate US phone numbers.

   Currently marks as valid, phone numbers of the following forms:

     (734) 555 1212
     (734) 555.1212
     (734) 555-1212
     (734) 5551212
     (734)5551212
     734 555 1212
     734.555.1212
     734-555-1212
     7345551212
     555 1212
     555.1212
     555-1212
     5551212
     5 1212
     5.1212
     5-1212
     51212

validate_number($ )
     Use like

          if ( validate_number($number) ) { &foo; }

     returns true if $number is a properly formatted US phone number.
     does _not_ check and see if $number is a functioning number, although
     maybe it should.

     this function can also be called as: is_valid_number($number)

get_regex ()
     Use like

          $rough_regex = get_regex;
          if ( $phone =~ /$rough_regex/o ) { &foo }

     returns the rough regex string (does not enforce phone number
     consistency.)

COPYRIGHT
=========

     COPYRIGHT  2000 THE REGENTS OF THE UNIVERSITY OF MICHIGAN
     ALL RIGHTS RESERVED

     PERMISSION IS GRANTED TO USE, COPY, CREATE DERIVATIVE WORKS
     AND REDISTRIBUTE THIS SOFTWARE AND SUCH DERIVATIVE WORKS FOR
     NON-COMMERCIAL EDUCATION AND RESEARCH PURPOSES, SO LONG AS NO
     FEE IS CHARGED, AND SO LONG AS THE COPYRIGHT NOTICE ABOVE,
     THIS GRANT OF PERMISSION, AND THE DISCLAIMER BELOW APPEAR IN
     ALL COPIES MADE; AND SO LONG AS THE NAME OF THE UNIVERSITY
     OF MICHIGAN IS NOT USED IN ANY ADVERTISING OR PUBLICITY
     PERTAINING TO THE USE OR DISTRIBUTION OF THIS SOFTWARE
     WITHOUT SPECIFIC, WRITTEN PRIOR AUTHORIZATION.

     THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION AS
     TO ITS FITNESS FOR ANY PURPOSE,  AND WITHOUT WARRANTY OF ANY
     KIND,  EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
     LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
     FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF THE
     UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE FOR ANY DAMAGES,
     INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
     DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR IN
     CONNECTION WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN
     OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

SEE ALSO
========

   perl(1)

AUTHOR
======

   Hugh Kennedy <kennedyh@engin.umich.edu>

     __|   \   __|  \ |
         (     _ \  _|  .  |
        \___|_/  _\___|_|\_|

Perl extension for spelling out numbers
***************************************

NAME
====

   Number::Spell - Perl extension for spelling out numbers

SYNOPSIS
========

     use Number::Spell;
     my $str=spell_number(519252);

DESCRIPTION
===========

   Number::Spell provides functionality for spelling out numbers.
Currently only integers are supported.

   By default Number::Spell does American formatting, but can be configured
to do European formatting by calling it with the "Format => 'eu'" option:

     spell_number( ...  , Format => 'eu');

   American and European formatting differ in how they represent numbers
one billion and above.

     number 		:  	20000000000 (2 * 10^11)
     American format :	twenty billion
     European format :	twenty thousand million

   With American formatting (default) Number::Spell should work for
integers to

     nine hundred ninety nine vigintillion nine hundred ninety nine
     novemdecillion nine hundred ninety nine octodecillion nine hundred
     ninety nine septendecillion nine hundred ninety nine sexdecillion nine
     hundred ninety nine quindecillion nine hundred ninety nine
     quattuordecillion nine hundred ninety nine tredecillion nine hundred
     ninety nine duodecillion nine hundred ninety nine undecillion nine
     hundred ninety nine decillion nine hundred ninety nine nonillion nine
     hundred ninety nine octillion nine hundred ninety nine septillion nine
     hundred ninety nine sextillion nine hundred ninety nine quintillion nine
     hundred ninety nine quadrillion nine hundred ninety nine trillion nine
     hundred ninety nine billion nine hundred ninety nine million nine
     hundred ninety nine thousand nine hundred ninety nine

   and in European formatting mode is should be valid up-to

     nine hundred ninety nine thousand nine hundred ninety nine vigintillion
     nine hundred ninety nine thousand nine hundred ninety nine
     novemdecillion nine hundred ninety nine thousand nine hundred ninety
     nine octodecillion nine hundred ninety nine thousand nine hundred
     ninety nine septendecillion nine hundred ninety nine thousand nine
     hundred ninety nine sexdecillion nine hundred ninety nine thousand nine
     hundred ninety nine quindecillion nine hundred ninety nine thousand
     nine hundred ninety nine quattuordecillion nine hundred ninety nine
     thousand nine hundred ninety nine tredecillion nine hundred ninety nine
     thousand nine hundred ninety nine duodecillion nine hundred ninety nine
     thousand nine hundred ninety nine undecillion nine hundred ninety nine
     thousand nine hundred ninety nine decillion nine hundred ninety nine
     thousand nine hundred ninety nine nonillion nine hundred ninety nine
     thousand nine hundred ninety nine octillion nine hundred ninety nine
     thousand nine hundred ninety nine septillion nine hundred ninety nine
     thousand nine hundred ninety nine sextillion nine hundred ninety nine
     thousand nine hundred ninety nine quintillion nine hundred ninety nine
     thousand nine hundred ninety nine quadrillion nine hundred ninety nine
     thousand nine hundred ninety nine trillion nine hundred ninety nine
     thousand nine hundred ninety nine billion nine hundred ninety nine
     thousand nine hundred ninety nine million nine hundred ninety nine
     thousand nine hundred ninety nine

FUTURE IMPROVEMENTS
===================

     o   more formatting options.  i.e. option to get "1500" to spell as
            		 "fifteen hundred" instead of "one thousand five hundred"
     o   support for even larger numbers
     o   support for taking input as a Math::BigInt, Math::BigInteger
     o   support for taking numbers in scientific notation
     o   foreign language support
     o   support for real numbers (including Math::BigFloat)
     o   ability to convert from a "spelled" number to an arithmetic number

AUTHOR
======

   Les Howard, les@lesandchris.com

SEE ALSO
========

   perl(1).

handling of Spice number strings
********************************

NAME
====

   Number::Spice - handling of Spice number strings

SYNOPSIS
========

     use Number::Spice qw(:convert);

     print spice_to_number('5u');      # 5E-6
     print spice_to_number('1.0e4k');  # 1.0E7

     print number_to_spice(1.0e12); # 1T
     print number_to_spice(1.0e-2); # 10M (i.e. milli, not mega!)

DESCRIPTION
===========

   Number::Spice was written to support the number format used in the
syntax for netlists for the spice electrical circuit simulator. This number
format is also used in other applications, even in different fields.
Number::Spice can be used to any purpose, and does not require the
installation of the spice simulator.

   Spice syntax provides a shortcut for writing down numbers in scientific
notation, by appending a suffix to the value which corresponds to a
numeric multiplier. The following table lists the minimal suffices and the
corresponding multiplier:

     T	1.0E12
     G	1.0E9
     MEG	1.0E6
     X	1.0E6
     K	1.0E3
     M	1.0E-3
     MIL	2.54E-5 (i.e. 1/1000 inch)
     U	1.0E-6
     N	1.0E-9
     P	1.0E-12
     F	1.0E-15
     A	1.0E-18

USAGE
=====

FUNCTIONS
---------

   The following functions are provided.  All functions are available for
exporting.

pattern
     Returns the regular expression matching a Spice number.

is_spice_number($spice_number)
     Returns true is the given string matches a Spice number after removal
     of leading and trailing whitespace. Note that a plain number, i.e.
     without literal suffix, is also accepted as a valid Spice number.

split_spice_number($spice_number)
     Examines a string and returns a list holding a number and a spice
     suffix if the string holds a valid spice number. Returns undef
     otherwise.

     Note that a regular number is also considered to be a spice number,
     and an empty string will be returned as the suffix in this case.

suffix_value($suffixc)
     Returns the value of a given spice suffix, e.g. suffix_value('giga')
     yields 1.0E9.

spice_to_number($spice_number)
     Returns a regular number represented by the given spice number.
     spice_to_number() will die() if the given number is not a spice
     number.

number_to_spice($number)
     Returns the shortest spice number representing the given number.
     Note that no conversion to *mil* will be attempted, and numbers
     smaller than 1.0E-18 will not get a suffix.

normalize_spice_number($spice_number)
     Converts a spice number to its shortest form by invoking
     spice_to_number() and number_to_spice().

REGULAR EXPRESSIONS
-------------------

   In addition to the methods, the following scalars representing regular
expressions are also made available for exporting:

`$RE_NUMBER'
     matches a regular number

`$RE_SPICE_SUFFIX'
     matches any spice suffix

`$RE_SPICE_NUMBER'
     matches a spice number. Note that a regular number is considered a
     spice number with no suffix. If you need to check for pure spice
     numbers, i.e. numbers with a literal suffix, check with
     `/$RE_NUMBER$RE_SPICE_SUFFIX\b/' instead.

EXPORT TAGS
-----------

   The functions and regular expressions are tagged into the following
groups for easy importing:

convert
     spice_to_number(), number_to_spice() and normalize_spice_number()

re
     `$RE_NUMBER', `$RE_SPICE_SUFFIX' and `$RE_SPICE_NUMBER'

all
     All conversion functions and regular expressions

SEE ALSO
========

   More info on the Spice format is given in the on-line Spice3 manual at
the University of Exeter, located at
http://newton.ex.ac.uk/teaching/CDHW/Electronics2/userguide/sec2.html#2

   And to those who were looking for numbers on the Spice Girls, but
unfortunately stranded here, take a peek at their official home page:
http://c3.vmg.co.uk/spicegirls/ ;-)

AUTHOR
======

   Wim Verhaegen <wim.verhaegen@ieee.org>

COPYRIGHT
=========

   Copyright (c) 2000 Wim Verhaegen. All rights reserved.  This program is
free software; you can redistribute and/or modify it under the same terms
as Perl itself.

Generic interface to Perl Compiler backends
*******************************************

NAME
====

   O - Generic interface to Perl Compiler backends

SYNOPSIS
========

     perl -MO=Backend[,OPTIONS] foo.pl

DESCRIPTION
===========

   This is the module that is used as a frontend to the Perl Compiler.

CONVENTIONS
===========

   Most compiler backends use the following conventions: OPTIONS consists
of a comma-separated list of words (no white-space).  The -v option
usually puts the backend into verbose mode.  The `-ofile' option generates
output to file instead of stdout. The -D option followed by various
letters turns on various internal debugging flags. See the documentation
for the desired backend (named `B::Backend' for the example above) to find
out about that backend.

IMPLEMENTATION
==============

   This section is only necessary for those who want to write a compiler
backend module that can be used via this module.

   The command-line mentioned in the SYNOPSIS section corresponds to the
Perl code

     use O ("Backend", OPTIONS);

   The import function which that calls loads in the appropriate
`B::Backend' module and calls the compile function in that package,
passing it OPTIONS. That function is expected to return a sub reference
which we'll call CALLBACK. Next, the "compile-only" flag is switched on
(equivalent to the command-line option -c) and a CHECK block is registered
which calls CALLBACK. Thus the main Perl program mentioned on the
command-line is read in, parsed and compiled into internal syntax tree
form. Since the -c flag is set, the program does not start running
(excepting BEGIN blocks of course) but the CALLBACK function registered by
the compiler backend is called.

   In summary, a compiler backend module should be called "B::Foo" for
some foo and live in the appropriate directory for that name.  It should
define a function called compile. When the user types

     perl -MO=Foo,OPTIONS foo.pl

   that function is called and is passed those OPTIONS (split on commas).
It should return a sub ref to the main compilation function.  After the
user's program is loaded and parsed, that returned sub ref is invoked
which can then go ahead and do the compilation, usually by making use of
the B module's functionality.

AUTHOR
======

   Malcolm Beattie, `mbeattie@sable.ox.ac.uk'

Tied access to odbm files
*************************

NAME
====

   ODBM_File - Tied access to odbm files

SYNOPSIS
========

     use ODBM_File;

     tie(%h, 'ODBM_File', 'Op.dbmx', O_RDWR|O_CREAT, 0640);

     untie %h;

DESCRIPTION
===========

   See `tie', see Perlfunc (perl.info), `tie', see
Perldbmfilter (perl.info),

Handles Property Sets
*********************

NAME
====

   OLE::PropertySet - Handles Property Sets

   $Revision: 1.1.1.1 $ $Date: 1998/02/25 21:13:00 $

SYNOPSIS
========

     use OLE::Storage();
     use OLE::PropertySet();

     $Var = OLE::Storage -> NewVar;
     $Doc = OLE::Storage -> open ($Startup, $Var, "testfile.doc");

direct mode
     *$PS* = OLE::PropertySet->load (*$Startup*, *$Var*, *$pps*, *$Doc*)

     *@list* = string { *$PS* -> property (2, 5, 6) }

tie mode
     *$PS* = tie *%PS*, OLE::PropertySet, *$Startup*, *$Var*, *$pps*,
     *$Doc*

     *@list* = string { *$PS*{2}, *$PS*{5}, *$PS*{6} }

DESCRIPTION
===========

   OLE::PropertySet gives read access to property sets. These are streams,
that e.g. are residing inside of Structured Storage documents. Because
property set technology is not limited to these documents borders, this
package was designed to connect easily to Structured Storage documents and
to arbitrary property set streams.

   To understand the use of this package, I recommend highly to study the
tool "ldat".

dictionary
     1||O == *$PS* -> dictionary (*\%dict* [,1])

     Stores the dictionary of PropertySet *$PS* in hash *%dict*. The
     dictionary is a hash array having the property identifier numbers as
     keys and the identifier names as values. By default the default
     dictionaries defined in OLE::PropertySet are also printed out. To
     leave them out, specify the optional parameter 1.

     Normally you will not need this method, but use idset() instead.

idset
     1||O == *$PS* -> idset (*\%idset* [,1]);

     Stores the idset of PropertySet *$PS* in hash *%idset*. The idset is
     a hash array based on the really available property identifiers.
     %idset has property identifier numbers as keys and the identifier
     names according to the PropertySets dictionary as values. The optional
     parameter spares out the default dictionary (see dictionary).

     Note: Some or all id names can be empty, if they cannot be figured
     out. Nevertheless the ids are valid.

idstr
     *$idstr*||undef = *$PS* -> idstr ($id [,1])

     Returns the property identifier string for property $id according to
     the PropertySets dictionary. The optional parameter spares out the
     default dictionary (see dictionary).

load

    *$PS*||0 ==
          1. load (*$Startup*, *$Var*, *$pps*, *$Doc* [,filter])

          2. load (*$Startup*, *$Var*, $name, *\$buf* [,filter])

     load() is the constructor of OLE::PropertySet. You can call it either
     with a Property Storage id *$pps* and a Structured Storage document
     handle *$Doc* as parameters, or with an PropertySetName $name and a
     reference to a PropertySetBuffer *\$buf*.

NewVar
     *$Var* == *$PS* -> NewVar ()

     Creates a new Variable handling object and returns it. (see also:
     open)

property
     Property||scalar = *$PS* -> property (*$id1* [,*$id2* [...]])

     Returns a *$Property* or a list of *@Properties*. (See
     OLE::Storage::Property to look what to do with it / them). If you
     applied a filter when loading *$PS*, property returns a scalar or a
     list of scalars.

type
     $type||0 = PropertySet -> type (*$Doc*, *$pps*)

     $type||0 = PropertySet -> type ($name)

     Returns the type of a PropertySet according to its name. The type is
     a OLE::PropertySet internal. It can be used to determine, if a
     property is a PropertySet or not. Momentarily are existing:

          type    meaning
          ---------------------------------------------------
          0x01    property is a "\05" PropertySet
          0x10    property is a "\01CompObj" fake PropertySet
          0x00    property is no PropertySet at all

SEE ALSO
========

   See OLE/Storage/Property, demonstration
program "ldat"

AUTHOR
======

   Martin Schwartz <`schwartz@cs.tu-berlin.de'>.

An Interface to *Structured Storage* Documents.
***********************************************

NAME
====

   OLE::Storage - An Interface to *Structured Storage* Documents.

   $Revision: 1.8 $ $Date: 1998/04/28 00:39:43 $

SYNOPSIS
========

   use OLE::Storage()

   use Startup;

   *$Var* = OLE::Storage->NewVar (); *$Startup* = new Startup;

   *$Doc* = OLE::Storage->open (*$Startup*, *$Var*, $file [,$m, *\$buf*])

   *$Doc* -> directory (*$pps*, *\%Names*, "string")

   *$Doc* -> read (*$pps*, *\$buf* [,$offset, $size])

   *$Doc* -> close ()

   Detailed syntax, descriptions and further methods: below.

DESCRIPTION
===========

   Documents done at Microsoft Windows Systems are tending to be stored in
a persistant data format, that MS calls "Structured Storage". This module
gives access to Structured Storage files. Alas, the current release allows
more or less read access, only. You can modify document contents (streams)
with it, but you cannot create or delete streams, nor rename them or
change their size. Also a file locking mechanism still is missing. I hope
to offer write support with next release.

close
     1||O == *$D* -> close ()

     Close the document.

clsid
     *$clsid* == *$D* -> clsid (*$pps*)

     Returns the CLSID of the property *$pps* as CLSID Property.

color
     0||1 == *$D* -> color (*$pps*)

     Returns the "color" of the property *$pps*.

date
     *$Date* == *$D* -> name (*$pps*)

     Returns a 0x40 Property (filetime) with the creation date of property
     storage *$pps*. See OLE::Storage::Property for more information.

     Note: As of now, only directory properties have filetime stamps.

directory
     1||O == *$D* -> directory (*$pps*, *\%Names* [,method])

     Read the directory denoted by property handle *$pps*. Fills the hash
     array *%Names* with the property names as keys and property handles
     as values.  The property names are Unicode Properties. To use the
     directory hash easily you optionally can apply a Property method. You
     will probably have to use *"string"* or *"wstring"*. See
     OLE::Storage::Property for more information.

     Note: To get the root directory, call directory (0, *\%Names*).

dirhandles
     *@pps* == *$D* -> dirhandles (*$pps*)

     Similar to directory (). Returns not the names, but only the property
     handles of the directory denoted by property handle *$pps*.

     Note: Normally you will use directory () instead.  To get the root
     directory, call dirhandles(0)

Startup
     *$Startup* == *$D* -> Startup ([*$NewStartup*])

     Gets the current *$Startup* handler. If an optional argument
     *$NewStartup* is given, this new handler will be installed and
     returned.

is_directory
     1||O == *$D* -> is_directory (*$pps*)

     Returns 1 if the property handle *$pps* is refering to a directory, 0
     otherwise.

is_file
     1||O == *$D* -> is_file (*$pps*)

     Returns 1 if the property handle *$pps* is refering to a file, 0
     otherwise.

is_root
     1||O == *$D* -> is_root (*$pps*)

     Returns 1 if the property handle *$pps* is refering to the document
     root, 0 otherwise.

modify
     1||O == *$D* -> modify (*$pps*, *\$buf*, $offset, $size)

     Modifies the contents of the property file *$pps*. $size bytes of the
     file *$pps* starting at offset $offset will be replaced by $size
     bytes of the buf *$buf* starting at offset 0.

     Note: This is still very restrictive, e.g. because the size of a file
     cannot be changed. Also missing is a possibility to give an offset to
     *$buf*.

modify_trash
     1||O == *$D* -> modify_trash ($type, *\$buf*, $offset, $size)

     Modifies the contents of the trash section $type. $size bytes of the
     trash section $type starting at offset $offset will be replaced by
     $size bytes of the buf *$buf* starting at offset 0.

name
     *$Name* == *$D* -> name (*$pps*)

     Returns the name of the property *$pps* as Unicode Property.

NewVar
     *$Var* == *$D* -> NewVar ()

     Creates a new Variable handling object and returns it. (see also:
     open)

open
     *$Doc*||O == Storage -> open (*$Startup*, *$Var*, $file [,$mode,
     *\$buf*])

     Constructor. Open the document with document path $file. $mode can be
     read or read/write. If you additionally specify modus buffer, the
     document data will be read from the buffer reference you specify with
     *$buf*.  Errors will be reported to Startup object *$Startup* (if
     present).

     Open modes:

          Bit	= 0 		= 1
          0	Read Only	Read and Write
          4	File Mode	Buffer Mode

read
     1||O == *$D* -> read (*$pps*, *\$buf*, [$offset, $size])

     Read the file property *$pps* into buffer *$buf*. If there is an
     optional $offset and $size, only this part of the file will be read.

read_trash
     1||O == *$D* -> read_trash ($type, *\$buf* [,$offset, $size])

     Read the trash section $type into buffer $buf. If there is an optional
     $offset and $size, only this part of the trash section will be read.
     Trash types can be 0, 1, 2, 4, 8 or a sum of this, like (1+2+8). 0 is
     default and yields (1+2+4+8). You can find an explanation of these
     types in `lclean' in this node.

     Trash types:

          #  Type
          -------------------
          1  Big blocks
          2  Small blocks
          4  File end space
          8  System space

size
     $size||undef == *$D* -> size (*$pps*)

     Returns the size of the file property *$pps* in terms of bytes.

size_trash
     $size == *$D* -> size_trash ($type)

     Returns the byte size of the trash section $type.

Var
     *$Var* == *$D* -> Var ([*$NewVar*])

     Gets the current $Var handler. If an optional argument $NewVar is
     given, this new handler will be installed and returned.

SEE ALSO
========

   See OLE/Storage/Property, Startup,
see OLE/Storage/Var,

EXAMPLES
========

   *OLE::Storage* demonstration programs, as there are:

lls
     *Laola ls*. Lists document structures.

ldat
     *Loala Display Authress Title*. Displays content of property sets and
     shows, how by principle to fool around with Excel documents.

lclean
     Cleans and saves garbage in Structured Storage documents. Can also
     store and retrieve a file at the garbage sections.

lhalw
     *Have a look at Word*. Draws the text out of Word 6 and Word 7
     documents, supports a little bit Word 8.

WWW
===

   Latest distribution of *Laola* and *Elser* at:

     http://wwwwbs.cs.tu-berlin.de/~schwartz/pmh
     or
     http://www.cs.tu-berlin.de/~schwartz/pmh

BUGS
====

   None known. I'm waiting for your hints!

AUTHOR
======

   Martin Schwartz <`schwartz@cs.tu-berlin.de'>.

Handle functions for OLE::Storage::Var
**************************************

NAME
====

   OLE::Storage::Handler - Handle functions for OLE::Storage::Var

   $Revision: 1.1.1.1 $ $Date: 1998/02/25 21:13:00 $

SYNOPSIS
========

   use OLE::Storage::Var;

   *$Var* = new Var;

   *$Handle* = *$Var* -> handle();

   Methods will be described below. But be aware, that this package is a
little bit likely to be removed in future. Actually you should not need to
deal with it at all.

DESCRIPTION
===========

   OLE::Storage::Handler is the interface used by OLE::Storage::Var. The
purpose was to allow the installation of new Property types easily and
even at runtime.  An example of how this could look like can be found in
"lls". Anyway, this all looks pretty superfluous to me, and therefore
might be removed some nice day.

   *\&sub* == *$Var* -> add (*$from*, *$fromstr*||0, *$to*, *\&sub*
[,*$par*])

   $data = *$Var* -> convert (*$from*, *$to*, *\$buf*, *\$o*)

   *\&sub* == *$Var* -> func (*$from*, *$to* [,*$Sub* [,*$par*]])

   *\&sub* == *$Var* -> code (*$from*, *$to* [,*$Sub*])

   *$par* = *$Var* -> par (*$from*, *$to* [,*$par*])

   *$typestr* = *$Var* -> typestr ($type [,*$typestr*])

SEE ALSO
========

   See OLE/Storage/Var, demonstration program "lls"

AUTHOR
======

   Martin Schwartz <`schwartz@cs.tu-berlin.de'>.

Laola's IO interface
********************

NAME
====

   OLE::Storage::Io - Laola's IO interface

SYNOPSIS
========

   use OLE::Storage::Io();

   s.b.

DESCRIPTION
===========

   Note: OLE::Storage is doing IO by maintaining lists consisting of
($offset, $length) elements.

close
     1||O == *$Io* -> close ([*\$streambuf*])

     Destructor. Flushes cache and closes file.

flush
     1 == *$Io* -> flush ()

     Flush *$Io* cache, if caching is turned on.

name
     $name = *$Io* -> name ()

     Returns name of *$Io*.

open
     *$Io*||O == open (*$Startup*, $name, [,$mode [,*\$streambuf*]])

     Constructor. Gives access to a file or a buffer. Default $mode is 0,
     that is read only. In file mode $name is a filepath. In buffer mode a
     reference to a buffer *\$streambuf* is mandatory. Errors occuring at
     Io methods will be reported to Startup object *$Startup*.

          Bit	Mode
          0	0 read only	1 read/write
          4	0 file mode	1 buffer mode

read
     1||O == *$Io* -> read ($offset, *$len*, *\$buf* [,*$var_offset*])

     Reads *$len* bytes starting at offset $offset into buffer referenced
     by *\$buf*. If *$var_offset* is given, buffer will be filled from
     this offset on.

rw_iolist
     1||0 == *$Io* -> rw_iolist (`"r"'||`"w"', *\$buf*, *$iolistO*);

     Read Iolist *$Io* into buffer *$buf* ("r"), or write buffer to Iolist
     *$Io*.

size
     *$len* = *$Io* -> size ()

     Returns size of *$Io* in bytes.

writable
     1||O == *$Io* -> writable ()

     *$Io* is writable (1) or not (0).

write
     1||O == *$Io* -> write ($offset, *$len*, *\$buf* [,*$var_offset*])

     Writes *$len* bytes starting at offset $offset from buffer referenced
     by *\$buf* to *$Io*. If *$var_offset* is given, buffer will be read
     from this offset on.

SEE ALSO
========

   See OLE/Storage/Iolist, Startup,

AUTHOR
======

   Martin Schwartz <`schwartz@cs.tu-berlin.de'>

Data management for OLE::Storage::Io (*alpha*)
**********************************************

NAME
====

   OLE::Storage::Iolist - Data management for OLE::Storage::Io (*alpha*)

SYNOPSIS
========

   use OLE::Storage::Iolist();

   s.b.

DESCRIPTION
===========

   Note: OLE::Storage uses Iolists in conjuntion with Io interface for IO
operations. An IO entry is a two element list like ($offset, $length).

aggregate
     *$NewIolist* = *$IoL* -> aggregate (*$method*)

     Sorts and merges Iolist *$IoL*, returns the new packed Iolist
     *$NewIolist*. Returns an empty Iolist on errors (!*to be changed*!).
     *$method* can be:

          method	sort offsets	allow offset overlaps
          1		yes		no
          2		yes		yes
          3		no		no
          4		no		yes

append
     (*$o1*, $l1) == *$IoL* -> append ($o, *$l*)

     Appends an entry to Iolist. Tries to merge the Iolists last entry
     with the new one. Returns the new last entry of Iolist.

entry
     ($o, *$l*) = *$IoL* -> entry ($i)

     rval: Get entry number $i.

     ($o, *$l*) == *$IoL* -> entry ($i, $o, *$l*)

     lval: Set entry number $i to ($o, *$l*).  Returns this entry.

length
     (*$l*) = *$IoL* -> length ($i)

     rval: Get length of entry number $i.

     *$l* == *$IoL* -> length ($i, *$l*)

     lval: Set length of entry number $i to *$l*. Returns *$l*.

max
     $num = *$IoL* -> max ()

     Returns number of *$IoL*'s entries.

new
     *$IoL* = new Iolist ([*\@offset*, *\@length*])

     Iolist constructor. Returns an Iolist handle. Can be initialized with
     references to corresponding offset and length lists.

offset
     ($o) = *$IoL* -> offset ($i)

     rval: Get offset of entry number $i.

     $o == *$IoL* -> offset ($i, $o)

     lval: Set offset of entry number $i to $o. Returns $o.

push
     1 == *$IoL* -> push (*$AnotherIolist*)

     Appends all entries of *$AnotherIolist* to *$IoL*.

sumlen
     $length = *$IoL* -> sumlen ()

     Returns total length of *$IoL*'s entries.

SEE ALSO
========

   See OLE/Storage/Io,

AUTHOR
======

   Martin Schwartz <`schwartz@cs.tu-berlin.de'>

maintain Properties for OLE::Storage::Var
*****************************************

NAME
====

   OLE::Storage::Property - maintain Properties for OLE::Storage::Var

   $Revision: 1.1.1.1 $ $Date: 1998/02/25 21:13:00 $

SYNOPSIS
========

   OLE::Storage and OLE::PropertySet are returning from time to time a
kind of variables called Properties (*$Prop*). Properties could be handled
as follows:

     sub work {
        my $Prop = shift;
        if (is_scalar $Prop) {
           do_something_with ($Prop); # $Prop definitively is a scalar.
        } else {
           foreach $P (@{array $Prop}) {
              work ($P);              # $P could be an array itself.
           }
        }
     }

   $string = *$Prop* -> string()

   *$NewProp* = *$OldProp* -> cast ("string")

DESCRIPTION
===========

   OLE::Storage::Property is maintaining the Properties, that are initially
instantiated by other packages. It gives storage places to
OLE::Storage::Var, manages Property to Property conversions, Property to
scalar conversions and type information. Though you will use the member
functions of OLE::Storage::Property quite often, you should never create a
Property directly with this package. Therefore "use OLE::Storage::Property"
even was useless.

   Type implementation itself is done at OLE::Storage::Var, that offers
some private methods for OLE::Storage::Property. Both, type conversions
and type availability are quite far from being complete (as you will
notice when looking at Var.pm). For this release I cared only to have the
something->string conversions working, and therefore only them are
documented above.

array
     *\@Properties* = *$Prop* -> array()

     Returns a reference to a Property list. You have to use this to find
     out, which properties are hiding inside an array property.

Conversion: Property to perl scalar
     $scalar = *$Prop* -> method()

     Returns a scalar variable, that perl understands. Momentarily method()
     should be string() only.

Conversion: Property to Property
     *$NewProp* = *$OldProp* -> cast ("method")

     Returns a Property of type method.

is_scalar
     1||0 == *$Prop* -> is_scalar()

     Returns 1 if $Prop is a scalar variable, 0 otherwise. A property is
     scalar, if it is not an array.

is_array
     1||0 == *$Prop* -> is_array()

     Returns 1 if $Prop is some array variable, 0 otherwise.

is_varray
     1||0 == *$Prop* -> is_varray()

     Returns 1 if $Prop is a variant array variable, 0 otherwise. A
     variant array is an array, that consists out of elements with
     different types.

stype
     $type = *$Prop* -> stype()

     Returns the scalar type of property $Prop. This is useful if $Prop is
     an array and you want to know, what kind of variables it consists of.

type
     $type = *$Prop* -> type()

     Returns the type of the Property. It is a number if it is a real
     property type, and it is a string, if it is an internal property type.

typestr
     *$typestr* = *$Prop* -> typestr()

     Returns the name of the property type as string.

KNOWN BUGS
==========

   Property handling is *very* slow.

SEE ALSO
========

   See OLE/Storage/Var, demonstration program "ldat"

AUTHOR
======

   Martin Schwartz <`schwartz@cs.tu-berlin.de'>.

Variable handling for properties
********************************

NAME
====

   OLE::Storage::Var - Variable handling for properties

   $Revision: 1.1.1.1 $ $Date: 1998/02/25 21:13:00 $

SYNOPSIS
========

   use OLE::Storage::Var;

   *$Var* = new Var;

   *$Property* = *$Var* -> property (*\$buf*, $o||*\$o* [,$type])

   *$Handler* = *$Var* -> handler ()

DESCRIPTION
===========

   This package is governing the two packages OLE::Storage::Property and
OLE::Storage::Handler. It manages the binary data of properties.
OLE::Storage::Property uses methods of $Var to store and convert
properties.  OLE::Storage::Var will probably be changed very much in close
future. So what a luck, that:

   Normally the only thing you will have to do with this package is to
create an instance either via package OLE::Storage with "$Var =
OLE::Storage->NewVar", or with same method of package OLE::PropertySet.
This $Var you need to pass to OLE::Storage->open calls.

   Note: If you should to have to create new properties by your own, do it
always via this $Var interface.

SEE ALSO
========

   See OLE/Storage/Property,
OLE/Storage/Handler, demonstration program "lls"

AUTHOR
======

   Martin Schwartz <`schwartz@cs.tu-berlin.de'>.

Simple Class for OLE document interface. (Version: 0.08)
********************************************************

NAME
====

   OLE::Storage_Lite - Simple Class for OLE document interface. (Version:
0.08)

SYNOPSIS
========

     use OLE::Storage_Lite;
     use strict;
     #1. Initialize
     #1.1 From File
     my $oOl = OLE::Storage_Lite->new("some.xls");
     #1.2 From Scalar
     my $oOl = OLE::Storage_Lite->new(\$sBuff);
     #1.3 From IO::Handle object
     use IO::File;
     my $oIo = new IO::File;
     $oIo->open("<iofile.xls");
     binmode($oIo);
     my $oOl = OLE::Storage_Lite->new($oFile);
     #2. Read and Get Data
     my $oPps = $oOl->getPpsTree(1);
     #3.Save Data
     #3.1 As File
     $oPps->save("kaba.xls"); #kaba.xls
     $oPps->save('-');        #STDOUT
     #3.2 As Scalar
     $oPps->save(\$sBuff);
     #3.3 As IO::Handle object
     my $oIo = new IO::File;
     $oIo->open(">iofile.xls");
     bimode($oIo);
     $oPps->save($oIo);

DESCRIPTION
===========

   OLE::Storage_Lite allows you to read and write an OLE structured file.
Please refer OLE::Storage by Martin Schwartz.

   OLE::Storage_Lite::PPS is a class representing PPS.
OLE::Storage_Lite::PPS::Root, OLE::Storage_Lite::PPS::File and
OLE::Storage_Lite::PPS::Dir are subclasses of OLE::Storage_Lite::PPS.

new
---

   *$oOle* = OLE::Storage_Lite->new(*$sFile*);

   Constructor.  Creates a OLE::Storage_Lite object for *$sFile*.
*$sFile* must be a correct file name.

   From 0.06, *$sFile* may be a scalar reference of file contents (ex.
\$sBuff)  and IO::Handle object (including IO::File etc).

getPpsTree
----------

   *$oPpsRoot* = *oOle*->getPpsTree([$bData]);

   returns PPS as OLE::Storage_Lite::PPS::Root object.  Other PPS objects
will be included as its children.  if *$bData* is true, the objects will
have data in the file.

getPpsSearch
------------

   *$oPpsRoot* = *oOle*->getPpsTree($raName [, $bData][, $iCase] );

   returns PPSs as OLE::Storage_Lite::PPS objects that has the name
specified in *$raName* array.  if *$bData* is true, the objects will have
data in the file.  if *$iCase* is true, search with case insensitive.

getNthPps
---------

   *$oPpsRoot* = *oOle*->getNthPps($iNth [, $bData]);

   returns PPS as OLE::Storage_Lite::PPS object specified number(*$iNth*).
if *$bData* is true, the objects will have data in the file.

Asc2Ucs
-------

   *$sUcs2* = OLE::Storage_Lite::Asc2Ucs(*$sAsc*);

   Utility function.  Just adding 0x00 afeter every characters in *$sAsc*.

Ucs2Asc
-------

   *$sAsc* = OLE::Storage_Lite::Ucs2Asc(*$sUcs2*);

   Utility function.  Just deletes 0x00 afeter words in *$sUcs*.

OLE::Storage_Lite::PPS
======================

   OLE::Storage_Lite::PPS has these properties:

No
     order number in saving.

Name
     its name in UCS2 (a.k.a Unicode).

Type
     its type (1:Dir, 2:File (Data), 5: Root)

PrevPps
     previous pps (as No)

NextPps
     next pps (as No)

DirPps
     dir pps (as No).

Time1st
     timestamp1st in array ref as similar fomat of localtime.

Time2nd
     timestamp2nd in array ref as similar fomat of localtime.

StartBlock
     start block number

Size
     size of the pps

Data
     its data

Child
     its child PPSs in array ref

OLE::Storage_Lite::PPS::Root
============================

   OLE::Storage_Lite::PPS::Root has 2 methods.

new
---

   *$oRoot* = OLE::Storage_Lite::PPS::Root->new(
*$raTime1st*,                     *$raTime2nd*,
*$raChild*);

   Constructor.

   *$raTime1st*, *$raTime2nd* is a array ref as ($iSec, $iMin, $iHour,
$iDay, $iMon, $iYear, $iHSec).  $iSec means seconds, $iMin means minutes.
$iHour means hours.  $iDay means day. $iMon is month -1. $iYear is year -
1900.  $iHSec is seconds/10,000,000 in Math::BigInt.

   *$raChild* is a array ref of children PPSs.

save
----

   *$oRoot* = $o<oRoot>->save(                     *$sFile*,
     *$bNoAs*);

   Saves infomations into *$sFile*. *$sFile* is '-', this will use STDOUT.

   From 0.06, *$sFile* may be a scalar reference of file contents (ex.
\$sBuff)  and IO::Handle object (including IO::File etc).

   if *$bNoAs* is defined, this function will use the No of PPSs for
saving order.  if *$bNoAs* is undefined, this will calculate PPS saving
order.

OLE::Storage_Lite::PPS::Dir
===========================

   OLE::Storage_Lite::PPS::Dir has 1 method.

new
---

   *$oRoot* = OLE::Storage_Lite::PPS::Dir->new(
*$sName*                   [, *$raTime1st*]                   [,
*$raTime2nd*]                   [, *$raChild*]);

   Constructor.

   *$sName* is a name of the PPS.

   *$raTime1st*, *$raTime2nd* is a array ref as ($iSec, $iMin, $iHour,
$iDay, $iMon, $iYear, $iHSec).  $iSec means seconds, $iMin means minutes.
$iHour means hours.  $iDay means day. $iMon is month -1. $iYear is year -
1900.  $iHSec is seconds/10,000,000 in Math::BigInt.

   *$raChild* is a array ref of children PPSs.

OLE::Storage_Lite::PPS::File
============================

   OLE::Storage_Lite::PPS::File has 3 method.

new
---

   *$oRoot* = OLE::Storage_Lite::PPS::File->new(*$sName*, *$sData*);

   *$sName* is name of the PPS.

   *$sData* is data of the PPS.

newFile
-------

   *$oRoot* = OLE::Storage_Lite::PPS::File->newFile(*$sName*, *$sFile*);

   This function makes to use file handle for geting and storing data.

   *$sName* is name of the PPS.

   If *$sFile* is scalar, it assumes that is a filename.  If *$sFile* is
an IO::Handle object, it uses that specified handle.  If *$sFile* is undef
or ", it uses temporary file.

   CAUTION: Take care *$sFile* will be updated by append method.  So if
you want to use IO::Handle and append a data to it, you should open the
handle with "r+".

append
------

   *$oRoot* = $oPps->append($sData);

   appends specified data to that PPS.

   *$sData* is appending data for that PPS.

CAUTION
=======

   A saved file with VBA (a.k.a Macros) by this module will not work
correctly.  However modules can get the same information from the file,
the file occurs a error in application(Word, Excel ...).

COPYRIGHT
=========

   The OLE::Storage_Lite module is Copyright (c) 2000,2001 Kawai Takanori.
Japan.  All rights reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

ACKNOWLEDGEMENTS
================

   First of all, I would like to acknowledge to Martin Schwartz and his
module OLE::Storage.

AUTHOR
======

   Kawai Takanori kwitknr@cpan.org

SEE ALSO
========

   OLE::Storage

Object Oriented Programming using Closures.
*******************************************

NAME
====

   OO::Closures - Object Oriented Programming using Closures.

SYNOPSIS
========

     use OO::Closures;

     sub new {
         my (%methods, %ISA, $self);
         $self = create_object (\%methods, \%ISA, !@_);

     ...

     $self;
         }

DESCRIPTION
===========

   This package gives you a way to use Object Oriented programming using
Closures, including multiple inheritance, `SUPER::' and AUTOLOADing.

   To create the object, call the function `create_object' with three
arguments, a reference to a hash containing the methods of the object, a
reference to a hash containing the inherited objects, and a flag
determining whether the just created object is the base object or not.
This latter flag is important when it comes to trying AUTOLOAD after not
finding a method.

   `create_object' returns a closure which will act as the new object.

   Here is an example of the usage:

     use OO::Closures;
     sub dice {
         my (%methods, %ISA, $self);
         $self = create_object (\%methods, \%ISA, !@_);

     my $faces = 6;

     $methods {set}  = sub {$faces = shift;};
     $methods {roll} = sub {1 + int rand $faces};

     $self;
         }

   It is a simple object representing a die, with 2 methods, set, to set
the number of faces, and `roll', to roll the die. It does not inherit
anything. To make a roll on a 10 sided die, use:

     (my $die = dice) -> (set => 10);
     print $die -> ('roll');

   Note that since the objects are closures, method names are the first
arguments of the calls.

OBJECT VARIABLES
================

   One can make object variables available to the outside world as well.
Just like in Eiffel, for an outsider this will be indistinguishable from
accessing a argumentless method. (However, in a Perlish fashion, we will
actually allow arguments in the call). To do so, instead of putting a code
reference in the %methods hash, put a reference to a scalar in the hash.
Note that to the outside world, no more than read only access to the
variable is given.

   Here is an example:

     sub dice {
         my (%methods, %ISA, $self);
         $self = create_object (\%methods, \%ISA, !@_);

     my $faces = 6;

     $methods {set}   = sub {$faces = shift;};
     $methods {roll}  = sub {1 + int rand $faces};

     $methods {faces} = \$faces;

     $self;
         }

     (my $die = dice) -> (set => 10);
     print $die -> ('faces');

   This will print 10.

INHERITANCE
===========

   To use inheritance, we need to set the `%ISA' hash. We also need to
pass ourselves to the classes we inherited, so an inherited class can find
the base object. (This is similar to the first argument of the constructor
when using regular objects).

   Here is an example that implements multi dice, by subclassing dice.  We
will also give dice a method `print_faces' that prints the number of faces
and returns the object.

     use OO::Closures;

     sub dice {
         my (%methods, %ISA, $self);
         $self = create_object (\%methods, \%ISA, !@_);
         my $this_object = shift || $self;

     my $faces = 6;

     $methods {set}         = sub {$faces = shift};
     $methods {roll}        = sub {1 + int rand $faces};
     $methods {print_faces} = sub {print "Faces: $faces\n"; $this_object};

     $self;
         }

     sub multi_dice {
         my (%methods, %ISA, $self);
         $self = create_object (\%methods, \%ISA, !@_);
         my $this_object = shift || $self;

     %ISA  = (dice => dice $this_object);

     my $amount = 1;

     $methods {amount} = sub {$amount = shift};
     $methods {roll}   = sub {
         my $sum = 0;
         foreach (1 .. $amount) {$sum += $self -> ('dice::roll')}
         $sum;
     };

     $self;
         }

     my $die = multi_dice;
     $die -> (set    => 7);
     $die -> (amount => 4);
     print $die -> ('print_faces') -> ('roll'), "\n";
     __END__

   Notice the line `my $this_object = shift || $self;'. That will make
`$this_object' contain the base object, unlike `$self' which is the
instance of the current class.

   The class dice is subclassed in `multi_dice' by calling dice with an
extra argument, the base object. Now it's known that dice is subclassed,
and looking for AUTOLOAD if it cannot find the requested method should not
happen; that will be triggered by the base object.

   Inherited classes are named, but they are named by the inheriter, not
the inheritee. This allows you to inherit the same class multiple times,
and getting separate data and method space for it.

   When searching for methods in the inheritance tree, no order will be
garanteed. If you subclass multiple classes defining the methods with the
same name, it's better to mask those methods and explicitely redirect the
call to the class you want it to handle.

   You can call a method by prepending its class name(s); just like
regular objects.

   Inherited classes are stored in the `%ISA' hash, but since this variable
is private to the object, each object can have its own inheritance
structure. If you change a class, existing objects of the class will not
be modified.

   The pseudo class 'SUPER::' works the same way as regular objects do,
except that it works the right way. It will resolve 'SUPER::' depending on
the inherited classes of the object the method is called in; not on the
`@ISA' of the package the call is made from.

`use OO::Closures;'
===================

   By default, the module `OO::Closures' exports the function
`create_object'.  If you want this function to be known by another name,
give that name as an argument to the use statement.

     use OO::Closure 'other_name';

   Now you create objects with `other_name (\%methods, \%ISA, !@_);'

BUGS
====

   This documentation uses the word 'class' in cases where it's not really
a class in the sense of the usual object oriented way. Mark-Jason Dominus
calls this *class-less* object orientism.

HISTORY
=======

     $Log: Closures.pm,v $
     Revision 1.2  1999/08/02 06:06:04  abigail
     Bug fixes and more efficient use of code (Rick Delaney).
     Free and open software copyright/license.
     Scalar references as methods (to complement for Eiffel like features).
     CPAN friendly module.

     Revision 1.1  1998/10/01 22:54:57  abigail
     Initial revision

AUTHOR
======

   This package was written by Abigail, *abigail@delanet.com*.

COPYRIGHT and LICENSE
=====================

   This code is copyright 1998, 1999 by Abigail.

   This code is free and open software. You may use, copy, modify,
distribute, and sell this program (and any modified variants) in any way
you wish, provided you do not restrict others from doing the same.

Get or set OS/2 file attributes
*******************************

NAME
====

   OS2::Attrib - Get or set OS/2 file attributes

SYNOPSIS
========

     use OS2::Attrib qw(get_attribs set_attribs);
     $attribs = get_attribs($path);
     set_attribs($attribs, $path1, $path2, ...);

DESCRIPTION
===========

   OS2::Attrib provides access to OS/2 file attributes.  While the
read-only attribute can be handled by chmod and stat, the hidden, system,
and archive attributes cannot.

$attribs = get_attribs($path)
     Returns the attributes of $path, or the empty string if $path does
     not exist.  Attributes are returned as a five-character string in
     this format: "RHSAD".  Each letter is replaced by an underscore (_)
     if the file does not have the corresponding attribute.  (This is the
     same format as a 4OS2 directory listing.)  The attributes are:

          R  The file is read-only (not writable)
          H  The file is hidden (does not appear in directory listings)
          S  The file is a system file (does not appear in directory listings)
          A  The file needs to be archived (it has changed since last backup)
          D  The file is a directory

$count = set_attribs($attribs, $path1, [$path2, ...])
     Sets the attributes of `$path1', `$path2', etc.  You can either
     specify the complete set of attributes, or add and subtract attributes
     by using + and -.  The case and order of the attributes is not
     important.  For example, '-s+ra' will remove the system attribute and
     add the read-only and archive attributes.  You should not use
     whitespace between attributes, although underscores are OK.  See
     `get_attribs' for an explanation of the attribute values.  You cannot
     change the directory attribute; if you specify it, it is ignored.
     Returns the number of files successfully changed.

LICENSE
=======

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   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 either the GNU General Public
License or the Artistic License for more details.

AUTHOR
======

   Christopher J. Madsen <`ac608@yfn.ysu.edu'>

SEE ALSO
========

   The `OS2::ExtAttr' in this node module provides access to extended
attributes.

Perl extension to get and set focus on PM windows.
**************************************************

NAME
====

   OS2::Focus - Perl extension to get and set focus on PM windows.

SYNOPSIS
========

     use OS2::Focus ':short';
     $old_focus = QueryFocus;
     ...				# Say, create some Tk windows...
     SetFocus($old_focus) or warn "Cannot change focus, the error is $^E.\n".

DESCRIPTION
===========

EXPORT
------

   None by default.

Exportable constants
--------------------

   `HWND_DESKTOP' is exported with a tag `:win'.

Exportable functions
--------------------

   See `PMREF' documentation for the following functions:

     BOOL WinFocusChange (HWND hwndDesktop, HWND hwndSetFocus, ULONG flFocusChange)
     HWND WinQueryFocus (HWND hwndDesktop)
     BOOL WinSetFocus (HWND hwndDesktop, HWND hwndSetFocus)

   which are exported with a tag `:win'.  Use `HWND_DESKTOP' (exported with
the same tag) as the first argument for these functions.

   Prefix `Win' can be removed, the resulted functions omit the first
argument, and fill $! and $^E on error.  These functions are exported with
a tag `:short'.

AUTHOR
======

   Ilya Zakharevich, ilya@math.ohio-state.edu.

SEE ALSO
========

   perl(1).

Perl extension for blah blah blah
*********************************

NAME
====

   OS2::Proc - Perl extension for blah blah blah

SYNOPSIS
========

     use OS2::Proc;
     blah blah blah

DESCRIPTION
===========

   Stub documentation for OS2::Proc was created by h2xs. It looks like the
author of the extension was negligent enough to leave the stub unedited.

   Blah blah blah.

AUTHOR
======

   A. U. Thor, a.u.thor@a.galaxy.far.far.away

SEE ALSO
========

   perl(1).

exports constants for system() call on OS2.
*******************************************

NAME
====

   OS2::Process - exports constants for system() call on OS2.

SYNOPSIS
========

     use OS2::Process;
     $pid = system(P_PM+P_BACKGROUND, "epm.exe");

DESCRIPTION
===========

   the builtin function system() under OS/2 allows an optional first
argument which denotes the mode of the process. Note that this argument is
recognized only if it is strictly numerical.

   You can use either one of the process modes:

     P_WAIT (0)	= wait until child terminates (default)
     P_NOWAIT	= do not wait until child terminates
     P_SESSION	= new session
     P_DETACH	= detached
     P_PM		= PM program

   and optionally add PM and session option bits:

     P_DEFAULT (0)	= default
     P_MINIMIZE	= minimized
     P_MAXIMIZE	= maximized
     P_FULLSCREEN	= fullscreen (session only)
     P_WINDOWED	= windowed (session only)

     P_FOREGROUND	= foreground (if running in foreground)
     P_BACKGROUND	= background

     P_NOCLOSE	= don't close window on exit (session only)

     P_QUOTE		= quote all arguments
     P_TILDE		= MKS argument passing convention
     P_UNRELATED	= do not kill child when father terminates

Access to process properties
----------------------------

   Additionaly, subroutines my_type(), process_entry() and
`file_type(file)', get_title() and `set_title(newtitle)' are implemented.
my_type() returns the type of the current process (one of "FS", "DOS",
"VIO", "PM", "DETACH" and "UNKNOWN"), or undef on error.

`file_type(file)'
     returns the type of the executable file file, or dies on error.  The
     bits 0-2 of the result contain one of the values

    `T_NOTSPEC' (0)
          Application type is not specified in the executable header.

    `T_NOTWINDOWCOMPAT' (1)
          Application type is not-window-compatible.

    `T_WINDOWCOMPAT' (2)
          Application type is window-compatible.

    `T_WINDOWAPI' (3)
          Application type is window-API.

     The remaining bits should be masked with the following values to
     determine the type of the executable:

    `T_BOUND' (8)
          Set to 1 if the executable file has been "bound" (by the BIND
          command) as a Family API application. Bits 0, 1, and 2 still
          apply.

    `T_DLL' (0x10)
          Set to 1 if the executable file is a dynamic link library (DLL)
          module. Bits 0, 1, 2, 3, and 5 will be set to 0.

    `T_DOS' (0x20)
          Set to 1 if the executable file is in PC/DOS format. Bits 0, 1,
          2, 3, and 4 will be set to 0.

    `T_PHYSDRV' (0x40)
          Set to 1 if the executable file is a physical device driver.

    `T_VIRTDRV' (0x80)
          Set to 1 if the executable file is a virtual device driver.

    `T_PROTDLL' (0x100)
          Set to 1 if the executable file is a protected-memory dynamic
          link library module.

    `T_32BIT' (0x4000)
          Set to 1 for 32-bit executable files.

     file_type() may croak with one of the strings `"Invalid EXE
     signature"' or `"EXE marked invalid"' to indicate typical error
     conditions.  If given non-absolute path, will look on PATH, will add
     extention `.exe' if no extension is present (add extension .  to
     suppress).

process_entry()
     returns a list of the following data:

          Title of the process (in the `Ctrl-Esc' list);

          window handle of switch entry of the process (in the `Ctrl-Esc'
          list);

          window handle of the icon of the process;

          process handle of the owner of the entry in `Ctrl-Esc' list;

          process id of the owner of the entry in `Ctrl-Esc' list;

          session id of the owner of the entry in `Ctrl-Esc' list;

          whether visible in `Ctrl-Esc' list;

          whether item cannot be switched to (note that it is not actually
          grayed in the `Ctrl-Esc' list));

          whether participates in jump sequence;

          program type.  Possible values are:

               PROG_DEFAULT                       0
               PROG_FULLSCREEN                    1
               PROG_WINDOWABLEVIO                 2
               PROG_PM                            3
               PROG_VDM                           4
               PROG_WINDOWEDVDM                   7

          Although there are several other program types for WIN-OS/2
          programs, these do not show up in this field. Instead, the
          PROG_VDM or PROG_WINDOWEDVDM program types are used. For
          instance, for PROG_31_STDSEAMLESSVDM, PROG_WINDOWEDVDM is used.
          This is because all the WIN-OS/2 programs run in DOS sessions.
          For example, if a program is a windowed WIN-OS/2 program, it
          runs in a PROG_WINDOWEDVDM session. Likewise, if it's a
          full-screen WIN-OS/2 program, it runs in a PROG_VDM session.

`set_title(newtitle)'
     - does not work with some windows (if the title is set from the
     start).  This is a limitation of OS/2, in such a case $^E is set to
     372 (type

          help 372

     for a funny - and wrong  - explanation ;-).

get_title()
     is a shortcut implemented via process_entry().

AUTHOR
======

   Andreas Kaiser <ak@ananke.s.bawue.de>, Ilya Zakharevich
<ilya@math.ohio-state.edu>.

SEE ALSO
========

   `spawn*'() system calls.

Perl extension for generation of daughter packages for IBM's Software Installer.
********************************************************************************

NAME
====

   OS2::SoftInstaller - Perl extension for generation of daughter packages
for IBM's Software Installer.

SYNOPSIS
========

     use OS2::SoftInstaller;
     open PKG, '>my.pkg';
     select PKG;
     make_pkg toplevel => '.', zipfile => 'my.zip', packid => 'myzip',
       nozip => 0, exclude => undef, dirid => 'FILE', strip => 'emx/';
     select STDOUT;
     close PKG;

DESCRIPTION
===========

size_date_time_pkg(name)
------------------------

   Takes file name, returns an array `($size, $date,$time)', suitable for
`SIZE', DATE, and TIME entries of SoftInstaller.

make_pkg(...)
-------------

   The function make_pkg() takes a hash-like list of arguments. The
recognized keys are:

toplevel
     toplevel directory of the tree to duplicate.

zipfile
     name of the zipfile which corresponds to this directory in the
     distribution.

packid
     symbolic name for this zipfile, autogenerated if needed.

nozip
     Do not generate toplevel description of the ZIP file (useful if the
     same zipfile is used in multiple components).

exclude
     if defined, is a regexp for files to exclude from the generated
     package file.

dirid
     id of the directory to install to (eg, FILE or AUX7).

strip
     prefix in all the files in the ZIP file which should be removed. It is
     supposed that the default value for the directory to install to (eg,
     FILE or AUX7) already contains this prefix. (Useful to make the ZIP
     file appropriate for manual install as well.)

   We suppose that `%unzip%' has the value of something like `unzip -oj',
`%unzip_d%' is something like -d (directory to extract), and the output of
this script is included like this:

     FILE
       EXIT = 'setvar unzip=unzip -oj'

     FILE
       EXIT = 'setvar unzip_d=-d'

     INCLUDE
       NAME = 'my.pkg'

   into the parent package file.

AUTHOR
======

   Ilya Zakharevich, ilya@math.ohio-state.edu

SEE ALSO
========

   perl(1).

Perl extension for blah blah blah
*********************************

NAME
====

   OS2::WinObject - Perl extension for blah blah blah

SYNOPSIS
========

     use OS2::WinObject;
     blah blah blah

DESCRIPTION
===========

   Stub documentation for OS2::WinObject was created by h2xs. It looks
like the author of the extension was negligent enough to leave the stub
unedited.

   Blah blah blah.

EXPORT
------

   None by default.

Exportable constants
--------------------

     CO_FAILIFEXISTS
     CO_REPLACEIFEXISTS
     CO_UPDATEIFEXISTS
     OPEN_AUTO
     OPEN_BATTERY
     OPEN_CONTENTS
     OPEN_DEFAULT
     OPEN_DETAILS
     OPEN_HELP
     OPEN_PALETTE
     OPEN_PROMPTDLG
     OPEN_RUNNING
     OPEN_SETTINGS
     OPEN_STATUS
     OPEN_TREE
     OPEN_USER
     PMERR_INVALID_FLAG
     PMERR_INVALID_HPTR
     PMERR_INVALID_HWND
     PMERR_INV_HDC
     PMERR_WPDSERVER_IS_ACTIVE
     PMERR_WPDSERVER_NOT_STARTED
     SWP_ACTIVATE
     SWP_DEACTIVATE
     SWP_EXTSTATECHANGE
     SWP_FOCUSACTIVATE
     SWP_FOCUSDEACTIVATE
     SWP_HIDE
     SWP_MAXIMIZE
     SWP_MINIMIZE
     SWP_MOVE
     SWP_NOADJUST
     SWP_NOAUTOCLOSE
     SWP_NOREDRAW
     SWP_RESTORE
     SWP_SHOW
     SWP_SIZE
     SWP_ZORDER

Exportable functions
--------------------

   When accessing these functions from Perl, prefix `Win' should be
removed.

     HOBJECT WinCopyObject (HOBJECT hObjectofObject, HOBJECT hObjectofDest,
       ULONG ulReserved)
     HOBJECT WinCreateObject (PCSZ pszClassName, PCSZ pszTitle, PCSZ pszSetupString,
       PCSZ pszLocation, ULONG ulFlags)
     BOOL WinDeregisterObjectClass (PCSZ pszClassName)
     BOOL WinDestroyObject (HOBJECT hObject)
     BOOL WinEnumObjectClasses (POBJCLASS pObjClass, PULONG pulSize)
     BOOL WinFreeFileIcon (HPOINTER hptr)
     BOOL WinIsSOMDDReady (void )
     BOOL WinIsWPDServerReady (void )
     HPOINTER WinLoadFileIcon (PCSZ pszFileName, BOOL fPrivate)
     HOBJECT WinMoveObject (HOBJECT hObjectofObject, HOBJECT hObjectofDest,
       ULONG ulReserved)
     BOOL WinOpenObject (HOBJECT hObject, ULONG ulView, BOOL fFlag)
     BOOL WinQueryActiveDesktopPathname (PSZ pszPathName, ULONG ulSize)
     BOOL WinQueryDesktopBkgnd (HWND hwndDesktop, PDESKTOP pdsk)
     HWND WinQueryDesktopWindow (HAB hab, HDC hdc)
     HOBJECT WinQueryObject (PCSZ pszObjectID)
     BOOL WinQueryObjectPath (HOBJECT hobject, PSZ pszPathName, ULONG ulSize)
     HWND WinQueryObjectWindow (HWND hwndDesktop)
     BOOL WinQueryWindowPos (HWND hwnd, PSWP pswp)
     BOOL WinRegisterObjectClass (PCSZ pszClassName, PCSZ pszModName)
     BOOL WinReplaceObjectClass (PCSZ pszOldClassName, PCSZ pszNewClassName,
       BOOL fReplace)
     ULONG WinRestartSOMDD (BOOL fState)
     ULONG WinRestartWPDServer (BOOL fState)
     BOOL WinRestoreWindowPos (PCSZ pszAppName, PCSZ pszKeyName, HWND hwnd)
     BOOL WinSaveObject (HOBJECT hObject, BOOL fAsync)
     BOOL WinSaveWindowPos (HSAVEWP hsvwp, PSWP pswp, ULONG cswp)
     HBITMAP WinSetDesktopBkgnd (HWND hwndDesktop, __const__ DESKTOP *pdskNew)
     BOOL WinSetFileIcon (PCSZ pszFileName, __const__ ICONINFO *pIconInfo)
     BOOL WinSetMultWindowPos (HAB hab, __const__ SWP *pswp, ULONG cswp)
     BOOL WinSetObjectData (HOBJECT hObject, PCSZ pszSetupString)
     BOOL WinSetWindowPos (HWND hwnd, HWND hwndInsertBehind, LONG x, LONG y,
       LONG cx, LONG cy, ULONG fl)
     BOOL WinShutdownSystem (HAB hab, HMQ hmq)
     BOOL WinStoreWindowPos (PCSZ pszAppName, PCSZ pszKeyName, HWND hwnd)

AUTHOR
======

   A. U. Thor, a.u.thor@a.galaxy.far.far.away

SEE ALSO
========

   perl(1).

S/390 standard I/O functions via POSIX/XPG extensions
*****************************************************

NAME
====

   OS390::Stdio - S/390 standard I/O functions via POSIX/XPG extensions

SYNOPSIS
========

     use OS390::Stdio qw( &get_dcb &getname &pds_mem &sysdsnr
                          &mvsopen &mvswrite
                          &flush &forward &rewind &resetpos
                          &remove &tmpnam
                          &vsamdelrec &vsamlocate &vsamupdate
       # future dslist        &dsname_level &vol_ser
       # future SVC 99        &dynalloc &dynfree &svc99
                        );

     @dslist = dsname_level("FRED");
     $uniquename = tmpnam;
     $fh = mvsopen("//MY.STUFF","a recfm=F") or die $!;
     $name = getname($fh);
     print $fh "Hello, world!\n";
     flush($fh);
     rewind($fh);
     $line = <$fh>;
     undef $fh;  # closes data set
     $fh = mvsopen("dd:MYDD(MEM)", "recfm=U");
     sysread($fh,$data,128);
     close($fh);
     remove("dd:MYDD(MEM)");
     @members = pds_mem("//SYS1.SPECIAL");

DESCRIPTION
===========

   This package gives Perl scripts access via POSIX extensions to several
C stdio operations not available through Perl's CORE I/O functions.  The
specific routines are described below.  These functions are prototyped as
unary operators, with the exception of mvsopen which takes two arguments,
mvswrite which takes three arguments, dynalloc, svc99 which take several
arguments, and tmpnam which takes none.

   All of the routines are available for export, though none are exported
by default.  All of the constants used by vsamupdate to specify update
options are exported by default.  The routines are associated with the
Exporter tag FUNCTIONS, the experimental routines are associated with the
Exporter tag EXPERIMENAL, and the constants are associated with the
Exporter tag CONSTANTS, so you can more easily choose what you'd like to
import:

     # import constants, but not functions
     use OS390::Stdio;  # same as use OS390::Stdio qw( :DEFAULT );
     # import functions, but not constants
     use OS390::Stdio qw( !:CONSTANTS :FUNCTIONS );
     # import both
     use OS390::Stdio qw( :CONSTANTS :FUNCTIONS );
     # import neither
     use OS390::Stdio ();
     # import everything
     use OS390::Stdio (:CONSTANTS :FUNCTIONS :EXPERIMENTAL );

   Of course, you can also choose to import specific functions by name, as
usual.

   This package ISA IO::File, so that you can call IO/File,
methods on the handles returned by mvsopen.  The IO::File package is not
initialized, however, until you actually call a method that OS390::Stdio
doesn't provide.  This is done to save startup time for users who don't
wish to use the IO::File methods.

   In the following `DSH' refers to a data set handle such as returned by
the mvsopen routine.  For OS data sets NAME refers to either a double
slashed name such as `//BETTY.BAM', or members such as `//BETTY.BAM(BAM)';
or to dd names such as `dd:WILMA.PEBBLES'.

flush EXPR
     This function causes the contents of stdio buffers for the specified
     data set handle to be flushed.  If undef is used as the argument to
     flush, all currently open data set handles are flushed.  Like the CRTL
     fflush() routine, the buffering mode and file type can have an effect
     on when output data is flushed.  flush returns a true value if
     successful, and undef if not.

forward DSH
     forward resets the current position of the specified data set handle
     to the end of the data set.  It's really just a convenience method
     equivalent in effect to `fseek($fh,0L,SEEK_END)'.  It returns a true
     value if successful, and undef if it fails.  See also rewind and
     resetpos.

get_dcb DSH
     This function retrieves the data control block information for the
     data set handle passed to it and returns it in a hash with keys
     approximated by the names of the elements of the `fldata_t' struct
     (see the documentaton for the `fldata()' C RTL routine for further
     information).

     For example:

          use OS390::Stdio qw(mvsopen get_dcb);
          my $dshandle = mvsopen("//SEDIMENT.SLATE","r");
          my %slate_dcb = get_dcb($dshandle);
          close($dshandle);
          for (sort(keys(%slate_dcb))) {
              print "$_ = $slate_dcb{$_}\n";
          }

     For the inverse (i.e. setting data set attributes) use appropriate
     arguments with either mvsopen, dynalloc, or svc99.  For just the
     filename you can use getname in place of get_dcb.

getname DSH
     The getname function returns the data set filename associated with a
     Perl I/O handle (via `fldata()').  If an error occurs, it returns
     undef.

     As an example consider:

          $dshandle = mvsopen("//FOO.BAR","r");
          $fullname = getname($dshandle);
          $hlq = $fullname;
          $hlq =~ s/\'([^\.]+)\..*/$1/;  # strip leading ' and trailing DS names
          print "The high level qualifier (HLQ) is $hlq\n";

     or, assuming you are authorized to do so, in order to switch to a
     different HLQ:

          $mydshandle = mvsopen("//FOO.BAR","r");
          $myfullname = getname($mydshandle);
          $bobsuid = '214';
          setuid($bobsuid);
          $bobsdshandle = mvsopen("//FOO.BAR","r");
          $bobsfullname = getname($bobsdshandle);
          $bobshlq = $bobsfullname;
          $bobshlq =~ s/\'([^\.]+)\..*/$1/;
          print "Bob's pwname is ",(getpwuid($<))[0],"\n";
          print "Bob's high level qualifier (HLQ) is $bobshlq\n";

     Note that both of these examples assume that UIDs map directly to
     profile prefixes, whereas they may not in general.  To obtain more
     extensive information for a given data set handle see get_dcb.

mvsopen NAME MODE
     The mvsopen function enables you to specify optional arguments to the
     CRTL when opening a data set.  Its operation is similar to the
     built-in Perl open function (see Perlfunc (perl.info),
     for a complete description), but it will only open normal data sets;
     it cannot open pipes or duplicate existing I/O handles.  The MODE is
     typically taken from:

          qw(r w a r+ w+ a+ rb wb ab rt wt at rb+ wb+ ab+ rt+ wt+ at+)

     Additional MODE keyword parameters can be passed from:

          qw(acc= blksize= byteseek lrecl= recfm= type= asis password= noseek)

     (See the *C/C++ MVS Programming Guide* and the *C/C++ MVS Library
     Reference* descriptions of `fopen()' for detailed information on NAME
     and MODE arguments.)  If successful, mvsopen returns a data set
     handle; if an error occurs, it returns undef.

     You can use the data set handle returned by mvsopen just as you would
     any other Perl file handle.  The class OS390::Stdio ISA IO::File, so
     you can call IO::File methods using the handle returned by mvsopen.
     However, useing OS390::Stdio does not automatically use IO::File; you
     must do so explicitly in your program if you want to call IO::File
     methods.  This is done to avoid the overhead of initializing the
     IO::File package in programs which intend to use the handle returned
     by mvsopen as a normal Perl data set handle only.  When the scalar
     containing a OS390::Stdio data set handle is overwritten, undefd, or
     goes out of scope, the associated data set is closed automatically.

mvswrite DSH EXPR LEN
     The mvswrite function provides access to stdio's `fwrite()' function.
     For example:

          use OS390::Stdio qw(mvsopen mvswrite);
          my $dshandle = mvsopen("//BED.ROCK","w+");
          my $fred,$data,$chrs_written;
          $fred = 100.00;
          $data = sprintf("Fred's salary is \$%3.2f",$fred);
          $chrs_written = mvswrite($dshandle,$data,length($data));
          close($dshandle);

pds_mem NAME
     Returns a list of members for the named PDS directory.  A list with a
     single undef element is returned for PDS directories that have no
     members as well as for data set names that are not partitioned (in the
     latter case a warning may appear on STDERR depending on how
     OS390::Stdio was compiled on your system).  For example:

          use OS390::Stdio qw(pds_mem);
          my @member_list = pds_mem("//SLATE.PDS");
          foreach my $mem (@member_list) {
              print "PDS.SLATE($mem)\n";
          }

remove NAME
     This function deletes the data set (member) named in its argument,
     returning a true value if successful and undef if not.  It differs
     from the CORE Perl function unlink in that it does not try to reset
     DS access if you are not authorized to delete the data set.

resetpos DSH
     resetpos resets the current position of the specified data set handle
     to the current position.  This is useful for switching between input
     and output at a given location.  It's really just a convenience
     method equivalent in effect to `fseek($fh,0L,SEEK_CUR)'.  It returns a
     true value if successful, and undef if it fails.  See also forward
     and rewind or Perl's builtin seek.  (This was not called setpos to
     avoid namespace collision).

rewind DSH
     rewind resets the current position of the specified data set handle
     to the beginning of the data set.  It's really just a convenience
     method equivalent in effect to `seek($fh,0,0)'.  It returns a true
     value if successful, and undef if it fails.  See also forward and
     resetpos.

sysdsnr NAME
     Returns true if the named data set is available to `fopen()' in "r"
     mode.  Note that perl's built in stat() function as well as the
     various file test operators such as -r do not work with OS data sets.

tmpnam
     The tmpnam function returns a unique string which can be used as an
     HFS (POSIX) data set name when creating temporary storage.  If, for
     some reason, it is unable to generate a name, it returns undef.  Note
     that in order to ensure the creation of an OS data set try using
     mvsopen with a data set name of the form `//&&name'.

vsamdelrec DSH
     Deletes a record from a VSAM data set via the C RTL `fdelrec()'
     routine.  You must seek to the proper record before invoking
     vsamdelrec of course.  See also mvsopen, vsamlocate, and vsamupdate.

vsamlocate DSH, key, key_len, options
     Locates a record in a VSAM data set via the C RTL `flocate()' routine.
     See also mvsopen, vsamdelrec, and vsamupdate.

vsamupdate DSH, record, length
     Updates a record in a VSAM data set via the C RTL `fupdate()' routine.
     See also mvsopen, vsamdelrec, and vsamlocate.

   The following functions are experimental: V 0.001: Some are not
currently working and either produce fatal errors or simply do not work as
intended.

dsname_level
     This function returns a ds list for a given HLQ plus optional
     additional qualifiers.  It returns undef if it encounters an error.
     (The name was taken from the ISPF 3.4 panel entry).  See also vol_ser.

     V 0.003: This routine is not yet implemented and causes a fatal error.

     Until this is working properly you can from perl code things such as:

          @listcat = `tso listcat`;

dynalloc
     Dynamically allocates a data set via the C RTL `dynalloc()' routine.
     See also svc99.

     V 0.003: This routine is not yet implemented and causes a fatal error.

dynfree
     Deallocates a data set via the C RTL `dynfree()' routine.  See also
     svc99.

     V 0.003: This routine is not yet implemented and causes a fatal error.

svc99
     This function provides access to the SVC 99 system service via a C
     RTL `svc99()' call.  See the *C/C++ MVS Library Reference* for
     information on `svc99()'.

     V 0.003: This routine is not yet implemented and causes a fatal error.

vol_ser
     Returns a dslist for a given volume serial input.   (The name was
     taken from the ISPF 3.4 panel entry).

     V 0.003: This routine is not yet implemented and causes a fatal error.

REVISION
========

   This document was last revised on 13-Apr-1999, for Perl 5.005_03.

   31-Aug-1998, VERSION 0.002 for Perl 5.005_02.

Virtual base class for transactions on files containing serialized hash objects
*******************************************************************************

NAME
====

   Object::Transaction - Virtual base class for transactions on files
containing serialized hash objects

SYNOPSIS
========

     package Pkg;

     @ISA = qw(Object::Transaction);

     use Object::Transaction;

     $obj = sub new { ... }
     sub file($ref,$id) { ... }

     $obj = load Pkg $id;
     $obj->savelater();
     $obj->save();
     $obj->removelater();
     $obj->remove();
     $obj->commit();
     $obj->uncache();
     $obj->abandon();
     $oldobj = $obj->old();

     $id = sub id { ... }
     $restart_commit = sub precommit() { }
     @passby = sub presave($old) { ... }
     sub postsave($old,@passby) { ... }
     $newid = sub preload($id) { .... }
     sub postload() { ... }
     sub preremove() { ... }
     sub postremove() { ... }

DESCRIPTION
===========

   *Object::Transaction* provides transaction support for hash-based
objects that are stored one-per-file using Storable.  Multiuser access is
supported.  In the future, serializing methods other than Storable will be
supported.

   *Object::Transaction* is a virtual base class.  In order to use it, you
must inherit from it and override the new method and the file method.

   Optomistic locking is used: it is possible that a transaction will fail
because the data that is is based upon has changed out from under it.

EXAMPLE
=======

     package User;

     @ISA = qw(Object::Transaction);

     use Object::Transaction;

     my $top = "/some/path";

     sub new {
     	my ($package, $login) = @_;
     	die unless getpwnam($login);
     	return bless { 'UID' => getpwnam($login) };
     }

     sub file {
     	my ($ref, $id) = @_;
     	$id = $ref->id() unless $id;
     	return "$top/users/$id/data.storable";
     }

     sub id {
     	my ($this) = @_;
     	return $this->{'UID'};
     }

     sub preload
     {
     	my ($id) = @_;
     	return if getpwuid($id);
     	return getpwnam($id) if getpwnam($id);
     	die;
     }

     sub postload
     {
     	my ($this) = @_;
     	my ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,
     		$shell,$expire) = getpwuid($this->{'UID'});
     	$this->{'SHELL'} = $shell;
     }

     sub presave
     {
     	my ($this, $old) = @_;
     	my $id = $this->{'UID'};
     	mkdir("$top/users/$id", 0700);
     	delete $this->{'SHELL'};
     }

     sub postsave
     {
     	goto &postload;
     }

     sub postremove
     {
     	delete from pw file...
     }

     my $joe = new User "joe";
     $joe->savelater();

     my $fred = new User "fred";
     $fred->savelater();

     $joe->commit();

METHODS PROVIDED
================

   *Object::Transaction* provides the following methods.

`load($id)'
     load is the way to bring an object into memory.   It is usually
     invoked as `my $obj = load MyObject $id'.

     There are two opporunities to customize the behavior of load:
     `preload' for things that should happen before loading and `postload'
     for things that should happen after loading.

     *Object::Transaction* caches objects that are loaded.  This is done
     both for performance reasons and to make sure that only one copy of
     an object is in memory at a time.  If caching is not desired, the
     uncache method must be invoked after loading.

     X<savelater>

`savelater()'
     `savelater' is the usual method of saving an object.  The object is
     not saved at the time that `savelater' is invoked.  It is actually
     saved when commit is invoked.

     There are two opporunities to customize the behavior of `savelater':
     `presave' for things that should happen before saving and `postsave'
     for things that should happen after saving.  These are invoked when
     the object is actually being saved.

save()
     Simply `savelater' combined with a commit.

     X<removelater>

`removelater()'
     `removelater' is the usual method of removing an object.  The object
     is not removed at the time that `removelater' is invoked.  It is
     actually removed when commit is invoked.

     There are two opporunities to customize the behavior of `removelater':
     `preremove' for things that should happen before removing and
     `postremove' for things that should happen after removing.  These are
     invoked when the object is actually being removed.

remove()
     Simply `removelater' combined with a commit

     X<commit>

commit()
     commit writes all pending changes to disk.   Either all changes will
     be saved or none of them will.  Deadlocks are avoided by locking
     files in order.

     *Object::Transaction* uses opportunistic locking.  Commit can fail.
     If it fails, it will die with a message that begins `DATACHANGE:
     file'.  It is advisable to wrap your entire transaction inside an
     eval so that it can be re-tried in the event that the data on disk
     changed between the time is was loaded and commited.

     In the event of a commit failure, the object cache will be reset.  Do
     not keep any old references to objects after such a failure.

`transaction($funcref,@args)'
     `transaction()' is a wrapper for a complete transaction.
     Transactions that fail due to opportunistic locking problems will be
     re-run automatically.  Beware side-effects!

     The first parameter is a reference to a function.  Any additional
     parameters will be passed as parameters to that function.  The return
     value of `transaction()' is the return value of `&$funcref()'.

     It is not necessary to use the `transaction()' method.  Just beware
     that commit(), save(), and remove() can fail.   `transaction()' will
     keep trying until it suceeds or it failes for a reason other than an
     opportunistic locking problem.

     X<abandon>

`abandon()'
     As an alternative to commit, all changes may be abandoned.  Calling
     `abandon()' does not undo changes made to the in-memory copies of
     objects.

     X<uncache>

`uncache()'
     *Object::Transaction* caches all objects.  To flush an object from
     *Object::Transaction*'s cache, invoke the uncache method on the
     object.

     Be careful when doing this - it makes it possible to have more than
     one copy of the same object in memory.

     `uncache()' can be invoked as a class method rather than an object
     method (`Object::Transaction-'uncache()>).  When invoked as a class
     method, the entire cache is flushed.

`readlock()'
     By default *Object::Transaction* does not lock objects unless they
     are being modified.

     The `readlock()' method insures that objects are properly locked and
     unchanged during a transaction even if they are not being modified.
     `savelater()' takes precedence over `readlock()' so they can be
     combined freely.

     Paranoid programmers should use `readlock()' on most objects.

`old()'
     Return the previous version of an object.  Previous is only loosely
     defined.

REQUIRED METHODS TO OVERRIDE
============================

   The following methods must be overriden.

new
     *Object::Transaction* does not provide a contructor.  You must
     provide one yourself.

`file($ref,$id)'
     You must provide a function that returns the filename that an object
     is stored in.  The file method can be invoked in two ways: as an
     object method call without an $id parameter; or as a class method
     call with an $id parameter.

OPTIONAL METHODS TO OVERRIDE
============================

   The following methods may be overridden.

   X<preload>

`preload($id)'
     `preload()' is invoked as nearly the first step of load.   It is
     generally used to make sure that the $id is valid.  `preload()' is a
     class method rather than an object method.

     The return value of `preload' is a replacement $id.  For example, it
     might be called as `preload("Joe")' to load the user named Joe, but
     if users are numbered rather than named it could return the number
     for Joe.  A return value of undef is ignored.

     No lock on the underlying file is present at the time `preload' is
     called.

     X<postload>

`postload($id)'
     `postload' is invoked after the object has been loaded into memory but
     before transaction completeness is checked.

     The underlying file is locked at the time that `postload' is invoked.

     If a transaction rollback is required, `postload' will be invoked
     again after the object has been reverted to its pre-transaction state.

     X<presave>

`presave($old)'
     `presave()' is invoked just before an object is written to disk.

     Objects are stored on disk in the file specified by the file method.
     The directory in which that file resides must exist by the time
     `presave()' finishes.   `presave' should make the directory if it
     isn't already made.

     The underlying file may or may not be locked at the time `presave' is
     invoked.

     `presave' can be invoked as a side-effect of load if the object must
     roll back to a previous version.

     The parameter `$old' is a copy of the object as of the time it was
     first loaded into memory.

     Any return values from `presave' will be remembered and passed to
     `postsave'.

     `presave' may not invoke save(), commit(), or `savelater()'.

     X<postsave>

`postsave($old,@psv)'
     `postsave' is invoked after an object has been written to disk.

     The underlying file is always locked at the time `postsave' is
     invoked.

     Invocations of `presave' and `postsave' are always paired.

     The parameter `$old' is a copy of the object as of the time it was
     first loaded into memory.

     The parameter `@psv' is the return value from `presave'.

     `postsave' may not invoke save(), commit(), or `savelater()'.

     X<precommit>

`precommit($old)'
     `precommit' is invoked just before files are locked in commit().
     This is before `presave()'.

     Unlike `presave()' and `postsave()', `precommit()' may use
     `savelater()' to add new objects to the transaction.  If it does so,
     it must return a true value.

     X<id>

id()
     *Object::Transaction* expect to be able to find the unique identifier
     (id) for each object as `$obj-'{'ID'}>.  If that isn't the case, you
     can override the id function to provide an alternative.

PUBLIC MEMBER DATA
==================

   The following data members are used by *Object::Transaction*.

ID
     *Object::Transaction* expect to find the id for an object in
     `$obj-'{'ID'}>.  This can be overridden by defining your own id
     function.

`OLD'
     When an object is loaded into memory a copy is made.  The copy can be
     found at `$obj-'{'OLD'}>.  The copy should not be modified.  The copy
     is explicitly passed in `presave' and `postsave'.

PRIVATE MEMBER DATA
===================

   *Object::Transaction* ads a few data members to each object for its own
internal use.

   These are:

     __frozen
     __transfollowers
     __transleader
     __rollback
     __removenow
     __toremove
     __transdata
     __readonly
     __trivial

   None of these should be touched.

BUGS
====

   A program or computer crash at just the wrong moment can allow an
object that should be deleted to escape deletion.  Any future attempt to
access such an object will cause it to self-destruct.

   In some situations objects will be saved even if niether save() nor
`savelater()' is invoked.  This happens if `readlock()' is used and the
transaction leader object (one per transaction) choosen turns out to be an
object for which only `readlock()' was called.

AUTHOR
======

   David Muir Sharnoff <muir@idiom.com>

COPYRIGHT
=========

   Copyright (C) 1999-2000, Internet Journals Corporation
<www.bepress.com>.  All rights reserved.  License hearby granted for
anyone to use this module at their own risk.   Please feed useful changes
back to David Muir Sharnoff <muir@idiom.com>.

Perl extension for Ogg Vorbis streams
*************************************

NAME
====

   Ogg::Vorbis - Perl extension for Ogg Vorbis streams

SYNOPSIS
========

     use Ogg::Vorbis;
     $ogg = Ogg::Vorbis->new;
     open(INPUT, "< file.ogg");
     open(OUTPUT, "> file.pcm");
     $ogg->open(INPUT);
     $info = $ogg->info;
     %comments = %{$ogg->comment};
     $buffer = '-' x 4096;
     $big_endian_p = Ogg::Vorbis::host_is_big_endian();
     while ($bytes = $ogg->read($buffer, 4096, $big_endian_p,
                                2, 1, $current_bitstream) > 0) {
       syswrite(OUTPUT, $buffer, $bytes);
     }
     $ogg->clear;
     close(OUTPUT);
     close(INPUT);

DESCRIPTION
===========

   This is an object-oriented interface to the Ogg Vorbis libvorbisfile
convenience library.  To create a vorbisfile object, call
Ogg::Vorbis->new.  You can then open it on input streams with the open()
method, read data from it with read() method, and clean up with clear().
Other methods for obtaining information are available as in libvorbisfile.

   The info() method returns an Ogg::Vorbis::Info object.  You can access
the various fields of the vorbis_info struct with methods of the same name.

   The comment() method returns a hash of comment name => value entries.

   Currently libvorbisfile does not support writing or encoding, so you
cannot change comment values or encode a new file, but the functionality
to do so will be added soon.

AUTHOR
======

   Alex Shinn, foof@debian.org

SEE ALSO
========

   Ao(3pm), ogg123(1), oggenc(1), perl(1).

Disable named opcodes when compiling perl code
**********************************************

NAME
====

   Opcode - Disable named opcodes when compiling perl code

SYNOPSIS
========

     use Opcode;

DESCRIPTION
===========

   Perl code is always compiled into an internal format before execution.

   Evaluating perl code (e.g. via "eval" or "do 'file'") causes the code
to be compiled into an internal format and then, provided there was no
error in the compilation, executed.  The internal format is based on many
distinct opcodes.

   By default no opmask is in effect and any code can be compiled.

   The Opcode module allow you to define an *operator mask* to be in
effect when perl next compiles any code.  Attempting to compile code which
contains a masked opcode will cause the compilation to fail with an error.
The code will not be executed.

NOTE
====

   The Opcode module is not usually used directly. See the ops pragma and
Safe modules for more typical uses.

WARNING
=======

   The authors make *no warranty*, implied or otherwise, about the
suitability of this software for safety or security purposes.

   The authors shall not in any case be liable for special, incidental,
consequential, indirect or other similar damages arising from the use of
this software.

   Your mileage will vary. If in any doubt *do not use it*.

Operator Names and Operator Lists
=================================

   The canonical list of operator names is the contents of the array
PL_op_name defined and initialised in file `opcode.h' of the Perl source
distribution (and installed into the perl library).

   Each operator has both a terse name (its opname) and a more verbose or
recognisable descriptive name. The opdesc function can be used to return a
list of descriptions for a list of operators.

   Many of the functions and methods listed below take a list of operators
as parameters. Most operator lists can be made up of several types of
element. Each element can be one of

an operator name (opname)
     Operator names are typically small lowercase words like enterloop,
     leaveloop, last, next, redo etc. Sometimes they are rather cryptic
     like gv2cv, i_ncmp and ftsvtx.

an operator tag name (optag)
     Operator tags can be used to refer to groups (or sets) of operators.
     Tag names always begin with a colon. The Opcode module defines several
     optags and the user can define others using the define_optag function.

a negated opname or optag
     An opname or optag can be prefixed with an exclamation mark, e.g.,
     !mkdir.  Negating an opname or optag means remove the corresponding
     ops from the accumulated set of ops at that point.

an operator set (opset)
     An opset as a binary string of approximately 43 bytes which holds a
     set or zero or more operators.

     The opset and opset_to_ops functions can be used to convert from a
     list of operators to an opset and *vice versa*.

     Wherever a list of operators can be given you can use one or more
     opsets.  See also Manipulating Opsets below.

Opcode Functions
================

   The Opcode package contains functions for manipulating operator names
tags and sets. All are available for export by the package.

opcodes
     In a scalar context opcodes returns the number of opcodes in this
     version of perl (around 340 for perl5.002).

     In a list context it returns a list of all the operator names.  (Not
     yet implemented, use @names = opset_to_ops(full_opset).)

opset (OP, ...)
     Returns an opset containing the listed operators.

opset_to_ops (OPSET)
     Returns a list of operator names corresponding to those operators in
     the set.

opset_to_hex (OPSET)
     Returns a string representation of an opset. Can be handy for
     debugging.

full_opset
     Returns an opset which includes all operators.

empty_opset
     Returns an opset which contains no operators.

invert_opset (OPSET)
     Returns an opset which is the inverse set of the one supplied.

verify_opset (OPSET, ...)
     Returns true if the supplied opset looks like a valid opset (is the
     right length etc) otherwise it returns false. If an optional second
     parameter is true then verify_opset will croak on an invalid opset
     instead of returning false.

     Most of the other Opcode functions call verify_opset automatically
     and will croak if given an invalid opset.

define_optag (OPTAG, OPSET)
     Define OPTAG as a symbolic name for OPSET. Optag names always start
     with a colon :.

     The optag name used must not be defined already (define_optag will
     croak if it is already defined). Optag names are global to the perl
     process and optag definitions cannot be altered or deleted once
     defined.

     It is strongly recommended that applications using Opcode should use a
     leading capital letter on their tag names since lowercase names are
     reserved for use by the Opcode module. If using Opcode within a module
     you should prefix your tags names with the name of your module to
     ensure uniqueness and thus avoid clashes with other modules.

opmask_add (OPSET)
     Adds the supplied opset to the current opmask. Note that there is
     currently no mechanism for unmasking ops once they have been masked.
     This is intentional.

opmask
     Returns an opset corresponding to the current opmask.

opdesc (OP, ...)
     This takes a list of operator names and returns the corresponding list
     of operator descriptions.

opdump (PAT)
     Dumps to STDOUT a two column list of op names and op descriptions.
     If an optional pattern is given then only lines which match the (case
     insensitive) pattern will be output.

     It's designed to be used as a handy command line utility:

          perl -MOpcode=opdump -e opdump
          perl -MOpcode=opdump -e 'opdump Eval'

Manipulating Opsets
===================

   Opsets may be manipulated using the perl bit vector operators & (and),
| (or), ^ (xor) and ~ (negate/invert).

   However you should never rely on the numerical position of any opcode
within the opset. In other words both sides of a bit vector operator
should be opsets returned from Opcode functions.

   Also, since the number of opcodes in your current version of perl might
not be an exact multiple of eight, there may be unused bits in the last
byte of an upset. This should not cause any problems (Opcode functions
ignore those extra bits) but it does mean that using the ~ operator will
typically not produce the same 'physical' opset 'string' as the
invert_opset function.

TO DO (maybe)
=============

     $bool = opset_eq($opset1, $opset2)	true if opsets are logically eqiv

     $yes = opset_can($opset, @ops)	true if $opset has all @ops set

     @diff = opset_diff($opset1, $opset2) => ('foo', '!bar', ...)

Predefined Opcode Tags
======================

:base_core
          null stub scalar pushmark wantarray const defined undef

          rv2sv sassign

          rv2av aassign aelem aelemfast aslice av2arylen

          rv2hv helem hslice each values keys exists delete

          preinc i_preinc predec i_predec postinc i_postinc postdec i_postdec
          int hex oct abs pow multiply i_multiply divide i_divide
          modulo i_modulo add i_add subtract i_subtract

          left_shift right_shift bit_and bit_xor bit_or negate i_negate
          not complement

          lt i_lt gt i_gt le i_le ge i_ge eq i_eq ne i_ne ncmp i_ncmp
          slt sgt sle sge seq sne scmp

          substr vec stringify study pos length index rindex ord chr

          ucfirst lcfirst uc lc quotemeta trans chop schop chomp schomp

          match split qr

          list lslice splice push pop shift unshift reverse

          cond_expr flip flop andassign orassign and or xor

          warn die lineseq nextstate scope enter leave setstate

          rv2cv anoncode prototype

          entersub leavesub leavesublv return method method_named -- XXX loops via recursion?

          leaveeval -- needed for Safe to operate, is safe without entereval

:base_mem
     These memory related ops are not included in :base_core because they
     can easily be used to implement a resource attack (e.g., consume all
     available memory).

          concat repeat join range

          anonlist anonhash

     Note that despite the existance of this optag a memory resource attack
     may still be possible using only :base_core ops.

     Disabling these ops is a *very* heavy handed way to attempt to prevent
     a memory resource attack. It's probable that a specific memory limit
     mechanism will be added to perl in the near future.

:base_loop
     These loop ops are not included in :base_core because they can easily
     be used to implement a resource attack (e.g., consume all available
     CPU time).

          grepstart grepwhile
          mapstart mapwhile
          enteriter iter
          enterloop leaveloop unstack
          last next redo
          goto

:base_io
     These ops enable filehandle (rather than filename) based input and
     output. These are safe on the assumption that only pre-existing
     filehandles are available for use.  To create new filehandles other
     ops such as open would need to be enabled.

          readline rcatline getc read

          formline enterwrite leavewrite

          print sysread syswrite send recv

          eof tell seek sysseek

          readdir telldir seekdir rewinddir

:base_orig
     These are a hotchpotch of opcodes still waiting to be considered

          gvsv gv gelem

          padsv padav padhv padany

          rv2gv refgen srefgen ref

          bless -- could be used to change ownership of objects (reblessing)

          pushre regcmaybe regcreset regcomp subst substcont

          sprintf prtf -- can core dump

          crypt

          tie untie

          dbmopen dbmclose
          sselect select
          pipe_op sockpair

          getppid getpgrp setpgrp getpriority setpriority localtime gmtime

          entertry leavetry -- can be used to 'hide' fatal errors

:base_math
     These ops are not included in :base_core because of the risk of them
     being used to generate floating point exceptions (which would have to
     be caught using a $SIG{FPE} handler).

          atan2 sin cos exp log sqrt

     These ops are not included in :base_core because they have an effect
     beyond the scope of the compartment.

          rand srand

:base_thread
     These ops are related to multi-threading.

          lock threadsv

:default
     A handy tag name for a *reasonable* default set of ops.  (The current
     ops allowed are unstable while development continues. It will change.)

          :base_core :base_mem :base_loop :base_io :base_orig :base_thread

     If safety matters to you (and why else would you be using the Opcode
     module?)  then you should not rely on the definition of this, or
     indeed any other, optag!

:filesys_read
          stat lstat readlink

          ftatime ftblk ftchr ftctime ftdir fteexec fteowned fteread
          ftewrite ftfile ftis ftlink ftmtime ftpipe ftrexec ftrowned
          ftrread ftsgid ftsize ftsock ftsuid fttty ftzero ftrwrite ftsvtx

          fttext ftbinary

          fileno

:sys_db
          ghbyname ghbyaddr ghostent shostent ehostent      -- hosts
          gnbyname gnbyaddr gnetent snetent enetent         -- networks
          gpbyname gpbynumber gprotoent sprotoent eprotoent -- protocols
          gsbyname gsbyport gservent sservent eservent      -- services

          gpwnam gpwuid gpwent spwent epwent getlogin       -- users
          ggrnam ggrgid ggrent sgrent egrent                -- groups

:browse
     A handy tag name for a *reasonable* default set of ops beyond the
     :default optag.  Like :default (and indeed all the other optags) its
     current definition is unstable while development continues. It will
     change.

     The :browse tag represents the next step beyond :default. It it a
     superset of the :default ops and adds :filesys_read the :sys_db.  The
     intent being that scripts can access more (possibly sensitive)
     information about your system but not be able to change it.

          :default :filesys_read :sys_db

:filesys_open
          sysopen open close
          umask binmode

          open_dir closedir -- other dir ops are in :base_io

:filesys_write
          link unlink rename symlink truncate

          mkdir rmdir

          utime chmod chown

          fcntl -- not strictly filesys related, but possibly as dangerous?

:subprocess
          backtick system

          fork

          wait waitpid

          glob -- access to Cshell via <`rm *`>

:ownprocess
          exec exit kill

          time tms -- could be used for timing attacks (paranoid?)

:others
     This tag holds groups of assorted specialist opcodes that don't
     warrant having optags defined for them.

     SystemV Interprocess Communications:

          msgctl msgget msgrcv msgsnd

          semctl semget semop

          shmctl shmget shmread shmwrite

:still_to_be_decided
          chdir
          flock ioctl

          socket getpeername ssockopt
          bind connect listen accept shutdown gsockopt getsockname

          sleep alarm -- changes global timer state and signal handling
          sort -- assorted problems including core dumps
          tied -- can be used to access object implementing a tie
          pack unpack -- can be used to create/use memory pointers

          entereval -- can be used to hide code from initial compile
          require dofile

          caller -- get info about calling environment and args

          reset

          dbstate -- perl -d version of nextstate(ment) opcode

:dangerous
     This tag is simply a bucket for opcodes that are unlikely to be used
     via a tag name but need to be tagged for completness and
     documentation.

          syscall dump chroot

SEE ALSO
========

   ops(3) - perl pragma interface to Opcode module.

   Safe(3) - Opcode and namespace limited execution compartments

AUTHORS
=======

   Originally designed and implemented by Malcolm Beattie,
mbeattie@sable.ox.ac.uk as part of Safe version 1.

   Split out from Safe module version 1, named opcode tags and other
changes added by Tim Bunce.

CRL Management module.
**********************

NAME
====

   OpenCA::CRL - CRL Management module.

SYNOPSIS
========

   use OpenCA::CRL;

DESCRIPTION
===========

   This module contains functions to access CRLs infos. It, as the
OpenCA::X509 module, requires some parameters such as a reference to an
OpenCA::OpenSSL instance. This module provides a CRL->PERL Hashes parsing,
no specific crypto functions are performed.

FUNCTIONS
=========

sub new () - Create a new instance of the Class.
------------------------------------------------

     Creating a new instance of the module you can provide a
     valid crl. As a result the crl will be parsed and stored
     in local variable(s) for later usage. You can generate a
     new instance of the class either by giving an already
     issued CRL (see OpenCA::OpenSSL for documentation) or
     even generate a new CRL if you provide the CACERT and
     CAKEY. The function will return a self reference. Accepted
     parameters are:

     SHELL   - An OpenCA::OpenSSL initialized
     	  instance;
     CRL	- A valid CRL(*);
     INFILE	- A CRL file(*);
     FORMAT  - Format of the provided CRL. Supported
     	  are PEM|DER(*);
     CAKEY	- CA private key file(*);
     CACERT	- CA certificate file(*);
     DAYS	- Days the CRL will be valid(*);
     EXTS	- Extentions section (see openssl.cnf
     	  documentation)(*);

     (*) - Optional Parameters;

     EXAMPLE:

     my $self->{crl} = new OpenCA::CRL( SHELL=>$openssl, CRL=>$pemCRL );

     NOTE: When you generate a new CRL, you have to provide
           BOTH CAKEY and CACERT parameters.

sub initCRL () - Initialize internal CRL parameters.
----------------------------------------------------

     Initialize the module with a provided CRL. You can not
     generate a new CRL with this function, if you wish to
     do so you'll have to get a new instance of the class
     (see the new() function). Accepted parameters are:

     CRL     - Provided CRL(*);
     INFILE  - A CRL file (one of CRL/INFILE params
     	  is required)(*);
     FORMAT	- Provided CRL format (PEM|DER)(*);

     (*) - Optional Parameters;

     EXAMPLE:

     if( not $self->{crl}->initCRL(CRL=>$derCRL, FORMAT=>DER)) {
                          print "Error!";
                     }

sub getParsed () - Retrieve parsed CRL list
-------------------------------------------

     This function returns an HASH structure with the main CRL
     data and a list of HASH with SERIAL and DATE of revoked
     certificates. Returned value is:

     my $ret = { VERSION=>$version,
                       	    ALGORITHM=>$alg,
                       	    ISSUER=>$issuer,
                       	    LAST_UPDATE=>$last,
                       	    NEXT_UPDATE=>$next,
                       	    LIST=>[ @list ] };

     Each element of the LIST has the following format:

     	my $element = { SERIAL=>$certSerial,
     			DATE=>$revDate };

     EXAMPLE:

     print "VERSION: " . $self->{crl}->getParsed()->{VERSION};

     foreach $rev ( @{ $self->{crl}->getParsed()->{LIST} } ) {
         print "SERIAL: " . $rev->{SERIAL} . "\n";
         print "DATE: " . $rev->{DATE} . "\n";
     }

sub getPEM () - Get the CRL in a PEM format.
--------------------------------------------

     This function accept no arguments and returns the CRL in
     PEM format.

     EXAMPLE:

     $pem = $crl->getPEM();

sub getDER () - Get the CRL in a DER format.
--------------------------------------------

     This function accept no arguments and returns the CRL in
     DER format.

     EXAMPLE:

     $der = $crl->getDER();

sub getTXT () - Get the CRL in a TXT format.
--------------------------------------------

     This function accept no arguments and returns the CRL in
     TXT format.

     EXAMPLE:

     print $crl->getTXT();

AUTHOR
======

   Massimiliano Pala <madwolf@openca.org>

SEE ALSO
========

   OpenCA::X509, OpenCA::Tools, OpenCA::OpenSSL, OpenCA::REQ,
OpenCA::TRIStateCGI, OpenCA::Configuration

Perl extention to handle CRR objects.
*************************************

NAME
====

   OpenCA::CRR - Perl extention to handle CRR objects.

SYNOPSIS
========

     use OpenCA::CRR;

DESCRIPTION
===========

   This class handles CRR (Certificate Revoking Request) objects. Them can
be signed or not depending on the implementation. CRR objects begin and
end with boundaries:

     -----BEGIN CRR-----
     -----END CRR-----

   Currently implemented functions are:

     new          - Creates a new instance of the class.
     getParsed    - Returns a parsed version of the object.
     getSignature - Returns the signature (if present).
     getBody      - Get Signed Text (boundaries included).
     getCRR	     - Returns passed CRR (sig. incl.).

FUNCTIONS
=========

sub new () - Creates a new instance of the class.
-------------------------------------------------

     This function creates a new instance of the class. You have
     to provide a valid CRR data as argument.

     EXAMPLE:

     my $CRR = new OpenCA::CRR( $crrData );

sub getParsed () - Returns a parsed CRR.
----------------------------------------

     This function returns a parsed CRR as an HASH object. The
     returned object has the following structure:

     my $ret = {
         SUBMIT_DATE => $date,
         BODY => $body,
         SIGNATURE => $signature,
                         CERTIFICATE_DN => $dn,
                         CERTIFICATE_NOT_BEFORE => $notbefore,
                         CERTIFICATE_NOT_AFTER => $notafter,
                         CERTIFICATE_SERIAL => $serial,
                         CERTIFICATE_ISSUER => $issuer,
             	};

sub getSignature() - Returns signature.
---------------------------------------

     Use this function to retrieve the signature. Remember the
     signature is intended to be PKCS7 and returned value includes
     boundaries.

     EXAMPLE:

     print $CRR->getSignature();

     =head1 AUTHOR

   Massimiliano Pala <madwolf@openca.org>

SEE ALSO
========

   perl(1).

Perl extention to deal with config files.
*****************************************

NAME
====

   OpenCA::Configuration - Perl extention to deal with config files.

SYNOPSIS
========

   use OpenCA::Configuration;

DESCRIPTION
===========

   Sorry, no documentation available yet.

AUTHOR
======

   Massimiliano Pala <madwolf@openca.org>

SEE ALSO
========

   perl(1).

Perl Certificates DB Extention.
*******************************

NAME
====

   OpenCA::DB - Perl Certificates DB Extention.

SYNOPSIS
========

   use OpenCA::DB;

DESCRIPTION
===========

   Sorry, no documentation available at the moment. Please take a look at
the prova.pl program you find in main directory of the package.

   Here there is a list of the current available functions. Where there is
(*) mark, the function is to be considered private and not public.

     new {};
     	build a new DB object;

     deleteData (*) {};
     	delete data on a DBM file;

     saveData (*) {};
     	save data on a DBM file;

     getData (*) {};
     	retrieve data from a DBM file;

     getIndex {};
     	retriexe the IDX from a DBM file;

     getHash (*) {};
     	get data and put it into hash format (used for header
     	extra info retrivial);

     saveIndex {};
     	save the IDX to a DBM file;

     saveHash (*) {};
     	save an HASH to a DBM file (in a single key);

     hash2txt (*) {};
     	convert an HASH to a txt (VAR=VAL);

     txt2hash (*) {};
     	convert a TEXT to an HASH (VAR=VAL);

     deleteRecord (*) {};
     	delete an entry from the DB (and corresponding search
     	dB);

     addRecord (*) {};
     	add a record to a DB (and corresponding search dB);

     updateRecord (*) {};
     	update a dB record;

     initDB {};
     	initialize the dB structure;

     createDB (*) {};
     	create and initialize the dBs;

     getReferences {};

     getBaseType {};
     	get Base datatye given a generic one ( i.e. from PENDING_
     	REQUEST to REQUEST);

     getSearchAttributes (*) {};
     	get a list of attributes for the search facility;

     storeItem {};
     	store a given object (OpenCA::XXXX);

     getItem {};
     	retrieve an object given the serial number;

     getNextItem {};
     	get next object (or serial) given a serial;

     getPrevItem {};

     deleteItem {};

     elements {};
     	returns number of elements of a given DATATYPE;

     rows {};
     	return number of elements matching a serach;

     searchItem {};
     	returns objects/serials matching the search on generic
     	datatypes (i.e. CERTIFICATE, REQUEST);

     searchItemDB (*) {};
     	returns objects/serials matching the search on exact
     	datatypes (i.e. VALID_CERTIFICATE, PENDING_REQUEST);

     searchDB {};
     	to be removed;

     getElement {};
     	to be removed;

     matches {};
     	to be removed;

     byKey { $a->{KEY} <=> $b->{KEY} };
     	to be removed;

     getTimeString {};
     	not currently used;

     toHex (*) {};
     	convert a decimal to an hex;

AUTHOR
======

   Massimiliano Pala <madwolf@openca.org>

SEE ALSO
========

   OpenCA::OpenSSL, OpenCA::X509, OpenCA::CRL, OpenCA::REQ,
OpenCA::TRIStateCGI, OpenCA::Configuration, OpenCA::Tools

Perl Crypto Extention to OpenSSL
********************************

NAME
====

   OpenCA::OpenSSL - Perl Crypto Extention to OpenSSL

SYNOPSIS
========

     use OpenCA::OpenSSL;

DESCRIPTION
===========

   This Perl Module implements an interface to the openssl backend
program. It actually uses the openssl command and it is not fully
integrated as PERL/C mixture.

   Passing parameters to functions should be very simple as them have no
particular order and have, often, self-explaining name. Each parameter
should be passed to the function like this:

     ... ( NAME=>VALUE, NAME=>VALUE, ... );

FUNCTIONS
=========

sub new () - Creates a new Class instance.
------------------------------------------

     This functions creates a new instance of the class. It accepts
     only one parameter: the path to the backend command (openssl).
     This is due because if it cannot find the openssl command it
     will return an uninitialized class (default value is /usr/bin/
     openssl which may not fit many distributions/OSs)

     EXAMPLE:

     my $openssl->new OpenCA::OpenSSL( $path );

sub setParams () - Set internal module variables.
-------------------------------------------------

     This function can handle the internal module data such as the
     backend path or the tmp dir. Accepted parameters are:

     SHELL   - Path to the openssl command.
     CONFIG  - Path to the openssl config file.
     TMPDIR  - Temporary files directory.
     STDERR  - Where to redirect the STDERR file.

     (*) - Optional parameters;

     EXAMPLE:

     $openssl->setParams( SHELL=>'/usr/local/ssl/bin/openssl',
     		     CONFIG=>$ca/stuff/openssl.cnf,
     		     TMPDIR=>'/tmp',
     		     STDERR=>'/dev/null' );

sub genKey () - Generate a private Key.
---------------------------------------

     This functions let you generate a new private key. Accepted
     parameters are:

     BITS      - key lengh in bits(*);
     OUTFILE   - Output file name(*);
     ALGORITHM - Encryption Algorithm to be used(*);
     PASSWD    - Password to be used when encrypting(*);

     (*) - Optional parameters;

     EXAMPLE:

     my $key = $openssl->genKey( BITS=>1024 );

sub genReq () - Generate a new Request.
---------------------------------------

     This function generate a new certificate request. Accepted
     parameters are:

     OUTFILE  - Output file(*);
     KEYFILE  - File containing the key;
     PASSWD   - Password to decript key (if needed) (*);
     DN       - Subject list (as required by openssl, see
     	   the openssl.cnf doc on policy);

     (*) - Optional parameters;

     EXAMPLE:

     my $req = $openssl->genReq( KEYFILE=>"00_key.pem",
     	DN => [ "madwolf@openca.org","Max","","","" ] );

sub genCert () - Generate a certificate from a request.
-------------------------------------------------------

     This function let you generate a new certificate starting
     from the request file. It is used for self-signed certificate
     as it simply converts the request into a x509 structure.
     Accepted parameters are:

     OUTFILE   - Output file(*);
     KEYFILE   - File containing the private key;
     REQFILE   - Request File;
     PASSWD    - Password to decrypt private key(*);
     DAYS      - Validity days(*);

     (*) - Optional parameters;

     EXAMPLE:

     $cert = $openssl->genCert( KEYFILE=>"priv_key.pem",
     	REQFILE=>"req.pem",
     	DAYS=>"720" );

sub dataConvert () - Convert data to different format.
------------------------------------------------------

     This functions will convert data you pass to another format. Ir
     requires you to provide with the data's type and IN/OUT format.
     Accepted parameters are:

     DATA    - Data to be processed;
     INFILE  - Data file to be processed (one of DATA and
       	  INFILE are required and exclusive);
     DATATYPE - Data type ( CRL | CERTIFICATE | REQUEST );
     OUTFORM  - Output format (PEM|DER|NET|TXT)(*);
     INFORM   - Input format (PEM|DER|NET|TXT)(*);
     OUTFILE  - Output file(*);

     (*) - Optional parameters;

     EXAMPLE:

     print $openssl->dataConvert( INFILE=>"crl.pem",
     	OUTFORM=>"TXT" );

sub  issueCert () - Issue a certificate.
----------------------------------------

     This function should be used when you have a CA certificate and
     a request (either DER|PEM|SPKAC) and want to issue the certificate.
     Parameters used will override the configuration values (remember
     to set to appropriate value the CONFIG with the setParams func).
     Accepted parameters are:

     REQDATA       - Request;
     REQFILE       - File containing the request (one of
     		REQDATA and REQFILE are required);
     INFORM        - Input format (PEM|DER|NET|SPKAC)(*);
     PRESERVE_DN   - Preserve DN order (Y|N)(*);
     CA_NAME	      - CA sub section to be used (take a
     		look at the OpenSSL docs for adding
     		support of multiple CAs to the conf
     		file)(*);
     CAKEY	      - CA key file;
     CACERT	      - CA certificate file;
     DAYS	      - Days the certificate will be valid(*);
     START_DATE    - Starting validity date (YYMMDDHHMMSSZ)(*);
     END_DATE      - Ending validity date (YYMMDDHHMMSSZ)(*);
     PASSWD	      - Password to decrypt priv. CA key(*);
     EXTS	      - Extentions to be used (configuration
     		section of the openssl.cnf file)(*);
     REQTYPE	      - Request type (NETSCAPE|MSIE)(*);

     (*) - Optional parameters;

     EXAMPLE:

     $openssl->issueCert( REQFILE=>"myreq",
     	INFORM=>SPKAC,
     	PRESERVE_DN=>Y,
     	CAKEY=>$ca/private/cakey.pem,
     	CACERT=>$ca/cacert.pem,
     	PASSWD=>$passwd,
     	REQTYPE=>NETSCAPE );

sub revoke () - Revoke a certificate.
-------------------------------------

     This function is used to revoke a certificate. Accepted parameters
     are:

     CAKEY   - CA private key file(*);
     CACERT  - CA certificate file(*);
     PASSWD  - Password to decrypt priv. CA key(*);
     INFILE  - Input PEM formatted certificate filename(*);

     (*) - Optional parameters;

     EXAMPLE:

     if( not $openssl->revoke( INFILE=>$certFile ) ) {
     	print "Error while revoking certificate!";
     }

sub issueCrl () - Issue a CRL.
------------------------------

     This function is used to issue a CRL. Accepted parameters
     are:

     CAKEY   - CA private key file;
     CACERT  - CA certificate file;
     PASSWD  - Password to decrypt priv. CA key(*);
     DAYS    - Days the CRL will be valid for(*);
     EXTS    - Extentions to be added ( see the openssl.cnf
     	  pages for more help on this )(*);
     OUTFILE - Output file(*);
     OUTFORM - Output format (PEM|DER|NET|TXT)(*);

     (*) - Optional parameters;

     EXAMPLE:

     print $openssl->issueCrl( CAKEY=>"$ca/private/cakey.pem",
     			  CACERT=>"$ca/cacert.pem",
     			  DAYS=>7,
     			  OUTFORM=>TXT );

sub SPKAC () - Get SPKAC infos.
-------------------------------

     This function returns a text containing all major info
     about an spkac structure. Accepted parameters are:

     SPKAC     - spkac data ( SPKAC = .... ) (*);
     INFILE	  - An spkac request file (*);
     OUTFILE   - Output file (*);

     	(*) - Optional parameters;

     EXAMPLE:

     print $openssl->SPKAC( SPKAC=>$data, OUTFILE=>$target );

sub getDigest () - Get a message digest.
----------------------------------------

     This function returns a message digest. Default digest
     algorithm used is MD5. Accepted parameters are:

     DATA      - Data on which to perform digest;
     ALGORITHM - Algorithm to be used(*);

     	(*) - Optional parameters;

     EXAMPLE:

     print $openssl->getDigest( DATA=>$data,
     			   ALGORITHM=>sha1);

AUTHOR
======

   Massimiliano Pala <madwolf@openca.org>

SEE ALSO
========

   OpenCA::X509, OpenCA::CRL, OpenCA::REQ, OpenCA::TRIStateCGI,
OpenCA::Configuration

Perl extension for basic handling PKCS#7 Signatures.
****************************************************

NAME
====

   OpenCA::PKCS7 - Perl extension for basic handling PKCS#7 Signatures.

SYNOPSIS
========

   use OpenCA::PKCS7;

DESCRIPTION
===========

   This module contains all functions needed for handling PKCS#7
signatures. It requires some parameters to be passed such as a reference
to a OpenCA::OpenSSL instance.

   This module provides an interface to PKCS#7 structures, no specific
crypto functions are performed (see the OpenCA::OpenSSL module for this).

FUNCTIONS
=========

sub new () - Create a new instance of the Class.
------------------------------------------------

     This function creates an instance of the module. If you
     provide a certificate it will be parsed and stored in
     local variable(s) for later usage. The function will return
     a blessed reference.

     Accepted parameters are:

     SHELL       - Reference to an initialized
     	      OpenCA::OpenSSL instance;
     INFILE      - Signature File;
     SIGNATURE   - Signature Data;
     DATAFILE    - Data File(*);
     CA_CERT     - CA Certificate File to check chain
                                   Depth ( >0 )(*);
     CA_DIR	    - CA Certificates directory to check
     	      chain Depth ( >0 );

     (*) - Optional parameter.

     EXAMPLE:

     $x509 = new OpenCA::PKCS#7( SHELL=>$crypto,
     					  INFILE=>"TEXT.sig",
     					  DATA=>"TEXT",
     					  CACERT=>"/OpenCA/cacert.pem");

sub getSigner () - Get basic Signer Infos.
------------------------------------------

sub verifyChain () - Get and Verify basic signer Infos (CAcert needed).
-----------------------------------------------------------------------

AUTHOR
======

   Massimiliano Pala <madwolf@openca.org>

SEE ALSO
========

   OpenCA::OpenSSL, OpenCA::CRL, OpenCA::REQ, OpenCA::X509

Perl extension to easily manage Cert REQUESTs
*********************************************

NAME
====

   OpenCA::REQ - Perl extension to easily manage Cert REQUESTs

SYNOPSIS
========

     use OpenCA::REQ;

DESCRIPTION
===========

   Sorry, no help available. The REQ module is capable of importing
request like this:

     -----BEGIN HEADER-----
     VAR = NAME
     VAR = NAME
     ...
     -----END HEADER-----
     (real request text here)
     -----BEGIN PKCS7-----
     (pkcs#7 signature here
     -----END PKCS7-----

   The Real request text can be a request in every form ( DER|PEM ) or
textual (called SPKAC|RENEW|REVOKE datatype). The syntax of the latters is
VAR = NAME on each line (just like the HEADER section).

AUTHOR
======

   Massimiliano Pala <madwolf@openca.org>

SEE ALSO
========

   OpenCA::OpenSSL, OpenCA::X509, OpenCA::CRL, OpenCA::Configuration,
OpenCA::TRIStateCGI, OpenCA::Tools

Perl extension for implementing 3-state Input Objs.
***************************************************

NAME
====

   OpenCA::TRIStateCGI - Perl extension for implementing 3-state Input
Objs.

SYNOPSIS
========

     use OpenCA::TRIStateCGI;

DESCRIPTION
===========

   Sorry, no description available. Currently implemented methods derives
mostly from the CGI.pm module, please take a look at that docs. Added
methods are:

     status        -
     newInput      -
     newInputCheck -
     checkForm     -
     startTable    -
     addTableLine  -
     endTable      -
     printCopyMsg  -
     printError    -

   Deprecated methods (better use the OpenCA::Tools corresponding methods
instead) are:

     subVar        -
     getFile       -

AUTHOR
======

   Massimiliano Pala (madwolf@openca.org)

SEE ALSO
========

   CGI.pm, OpenCA::Configuration, OpenCA::OpenSSL, OpenCA::X509,
OpenCA::CRL, OpenCA::REQ, OpenCA::CRR, OpenCA::Tools

Misc Utilities PERL Extention.
******************************

NAME
====

   OpenCA::Tools - Misc Utilities PERL Extention.

SYNOPSIS
========

     use OpenCA::Tools;

DESCRIPTION
===========

   This module provides some tools to easy some standard actions. Current
functions description follows:

     new		- Returns a reference to the object.
     getDate		- Returns a Printable date string.
     copyFiles	- Copy file(s).
     moveFiles	- Move file(s).
     deleteFiles	- Delete file(s).
     cmpDate		- Compare two Printable date sting.
     isInsidePeriod	- Check wether give date is within given
     		  period.
     parseDN         - Parse a given DN returning an HASH value.

FUNCTIONS
=========

sub new () - Build new instance of the class.
---------------------------------------------

     This function returns a new instance of the class. No parameters
     needed.

     EXAMPLE:

     	my $tools = new OpenCA::Tools();

sub getDate () - Get a Printable date string.
---------------------------------------------

     Returns a string representing current time (GMT or Local).
     Accepted parameters are:

     FORMAT  - Use it to get local or GMT time.
     	  Defaults to GMT.

     EXAMPLE:

     print $tools->getDate();

sub copyFiles () - Copy file(s).
--------------------------------

     Use this function to copy file(s). Source path can contain
     wildcards (i.e. '*') that will be expanded when copying.
     Accepted parameters are:

     SRC  - Source full path.
     DEST - Destination path.

     EXAMPLE:

     $tools->copyFiles( SRC=>"test.pl", DEST=>"/tmp" );

sub moveFiles () - Move file(s).
--------------------------------

     Use this function to move file(s). Source path can contain
     wildcards (i.e. '*') that will be expanded when copying.
     Accepted parameters are:

     SRC  - Source full path.
     DEST - Destination path.

     EXAMPLE:

     $tools->moveFiles( SRC=>"test.pl", DEST=>"/tmp" );

sub deleteFiles () - Delete file(s).
------------------------------------

     Use this function to delete file(s) once provided target
     directory and filter.
     Accepted parameters are:

     DIR    - Directory containing file(s) to delete.
     FILTER - File filtering(*).

     (*) - Optional parameters;

     EXAMPLE:

     $tools->deleteFiles( DIR=>"/tmp", FILTER=>"prova.p*" );

sub cmpDate () - Compare two date strings.
------------------------------------------

     Use this function to get informations on relationship
     between the two provided date strings. Returns integer
     values like strcmp() do in C, so if DATE_1 'is later'
     than DATE_2 it returns a positive value. A negative value
     is returned in the countrart case while 0 is returned if
     the two dates are equal. Accepted parameters:

     DATE_1  - First date string.
     DATE_2  - Second date string.

     EXAMPLE:

     $tools->cmpDate( DATA_1=>"$date1", DATA_2=>"$date2" );

sub isInsidePerios - Check if date is inside a given period.
------------------------------------------------------------

     This functions returns a true (1) value if the provided
     date is within a given period. Accepted parameters are:

     DATE     - Date string to check.
     START	 - Date string indicating period's starting(*).
     END      - Date string indicating period's ending(*).

     (*) - Optional parameters;

     if( not $tools->isInsidePeriod( DATE=>$d1, START=>$d2,
     		END=>$d3 ) ) {
     	print "Non in period... \n";
     }

sub parseDN () - Parse a given DN.
----------------------------------

     This function parses a given DN string and returns an HASH
     value. Returned structure is as following:

     KEY => VALUE,

     Only the OU key is instead a list:

     OU => [ @list ]

     EXAMPLE:

     $parsed = $tools->parseDN( $dn );
     print $parsed->{CN};

     foreach $tmp ( @{ $parsed->{OU} } ) {
     	print "OU=$tmp\n";
     }

AUTHOR
======

   Massimiliano Pala <madwolf@openca.org>

SEE ALSO
========

   OpenCA::Configuration, OpenCA::TRIStateCGI, OpenCA::X509, OpenCA::CRL,
OpenCA::REQ, OpenCA::OpenSSL, perl(1).

Perl extension for basic handling x509 Certificates.
****************************************************

NAME
====

   OpenCA::X509 - Perl extension for basic handling x509 Certificates.

SYNOPSIS
========

   use OpenCA::X509;

DESCRIPTION
===========

   This module contains all functions needed for handling of X509
certificates. It requires some parameters to be passed such as a reference
to a OpenCA::OpenSSL instance.

   This module provides an interface to X509 structures, no specific
crypto functions are performed (see the OpenCA::OpenSSL module for this).
When not said different, default operational format is PEM.

FUNCTIONS
=========

sub new () - Create a new instance of the Class.
------------------------------------------------

     This function creates an instance of the module. If you
     provide a certificate it will be parsed and stored in
     local variable(s) for later usage. The function will return
     a blessed reference.

     Accepted parameters are:

     SHELL       - Reference to an initialized
     	      OpenCA::OpenSSL instance;
     CERTIFICATE - Certificate to stored in structure(*);
     INFILE      - Certificate file(*);
     FORMAT	    - Format of the provided certificate,
     	      one of PEM|DER|NET(*);

     (*) - Optional parameter.

     EXAMPLE:

     $x509 = new OpenCA::X509( SHELL=>$crypto,
     					CERTIFICATE=>$self->{cert});

sub initCert () - Use a new certificate.
----------------------------------------

     You can use a new certificate without having to get a
     new module reference. Accepted parameters are:

     CERTIFICATE   - Certificate data to be stored;
     FORMAT        - Provided certificate's format,
     		one of PEM|DER|NET(*);

     EXAMPLE:

     if( not $x509->initCert( CERTIFICATE=>$self->{cert} ) )
                     {
                         print "Error in storing certificate!";
                     }

sub getParsed () - Get an hash structure from certificate
---------------------------------------------------------

     By calling this function you can retrieve a reference to the
     parsed certificate (PERL hash). This structure will include,
     for example:

     $ret->{SERIAL}		## Serial Number
                     $ret->{DN}		## Subject DN
                     $ret->{EMAIL}		## Subject e-mail
                     $ret->{CN}		## Subject CN
                     $ret->{OU}		## Subject OU (list)
                     $ret->{O}		## Subject Organization
                     $ret->{C}		## Subject Country
                     $ret->{ISSUER}		## Issuer DN
                     $ret->{NOT_BEFORE}	## Not Before Date
                     $ret->{NOT_AFTER}	## Not After Date (Expiration)
                     $ret->{PK_ALGORITHM}	## Algorithm used (RSA,DSA,..)
                     $ret->{MODULUS}		## Modulus (Size in bits)
                     $ret->{EXPONENT}	## Exponent

     EXAMPLE:

     my $self->{parsedItem} = $x509->parseCertificate();

     print $self->{parsedItem}->{SERIAL};
     foreach $ou ( @{ $self->{parsedItem}->{OU} } ) {
     	print "OU=$ou, ";
     }

sub status () - Get certificate status
--------------------------------------

     Get certificate status using provided OpenCA::CRL initialized
     reference as argument. Returned status can be Valid, Revoked,
     Expired and Unknown. Accepted arguments:

     CRL   - Crl to check certificate status;

     The returned structure is:

     $status->{STATUS};
     $status->{REVOKATION_DATE};
     $status->{EXPIRATION_DATE};

     EXAMPLE:

     my $status = $x509->status( CRL=>$crl );
     print $status->{STATUS};

sub getPEM () - Get certificate in PEM format.
----------------------------------------------

     Get certificate in PEM format.

     EXAMPLE:

     $pem = $x509->getPEM();

sub getDER () - Get certificate in DER format.
----------------------------------------------

     Get certificate in DER format.

     EXAMPLE:

     $der = $x509->getDER();

sub getTXT () - Get certificate in TXT format.
----------------------------------------------

     Get certificate in TXT format.

     EXAMPLE:

     $der = $x509->getTXT();

AUTHOR
======

   Massimiliano Pala <madwolf@openca.org>

SEE ALSO
========

   OpenCA::OpenSSL, OpenCA::CRL, OpenCA::REQ, OpenCA::X509

A robust web application framework built to run under Apache and mod_perl
*************************************************************************

NAME
====

   OpenInteract - A robust web application framework built to run under
Apache and mod_perl

DESCRIPTION
===========

   OpenInteract is an extensible application server using Apache and
mod_perl built for developers but also to be manageable almost entirely
via the web browser. It includes:

   * A robust system of components built on templates that can access your
     data just about any way that you can think of.

   * A very flexible separation of presentation and data access: you can
     use one template for accessing data from different sources using one
     template (e.g., a listing of users from the system, from an LDAP
     server, from an NT/SMB authentication controller, etc.) or you can use
     one set of data to fill multiple templates.

   * A consistent security mechanism allowing you to control security for
     users and groups not only at the task level, but also at the
     individual data object level.

   * A simple user and group-management system that allows users to create
     their own accounts and an administrator to assign them to one or more
     groups.

   * A convenient packaging system that makes it simple for developers to
     distribute code, configuration and all other information necessary for
     an application. It also makes the installation and upgrading processes
     very straightforward and simple.

   * An integrated, database-independent method for distributing data
     necessary for a package. You should be able to install any package on
     any database that's been tested with OpenInteract. (Some of this work
     must be done by the package authors, but OpenInteract tries to make
     this as painless as possible.)

Dependencies
------------

   OpenInteract uses a number of CPAN modules, relying heavily on the
following required modules:

   *SPOPS* (Simple Perl Object Persistence with Security). This module was
developed in tandem with this framework but stands on its own as a
full-featured object serialization system. It also implements security.

   *Template Toolkit*. This is the best templating environment available
for Perl. Version 2 has major performance improvements and also includes
usability enhancements. It's also required by OI.

   *Apache::Session*. Provide datasource-independent means of session
management.

   Many others are also used - why reinvent the wheel when there are so
many other well-built ones already around around and so many interesting
problems to conquer?

   OpenInteract is usable *right now*, out of the box. That doesn't mean
we're sitting on our laurels - we're working on a number of different
features to OpenInteract which will be added soon to the 'TODO' file found
in the OpenInteract source directory.

INSTALLATION
============

   A file 'INSTALL' is included with the OpenInteract distribution. It
shows you the simple steps needed for installation. If you ask this
question on a mailing list (below), someone will likely post:

  1. Read and follow the directions in INSTALL.

  2. Read and follow the directions in INSTALL.

  3. Return to step (1).

DOCUMENTATION
=============

   OpenInteract comes with a few forms of documentation:

   * *System-wide*: These files are in HTML format and are geared for
     people first learning about OpenInteract, whether from a
     content-management view, developer view or administration view. You
     can find them in the `doc/' directory of the source distribution -
     open up the `index.html' file for a table of contents.

     The files are also installed with every website. Once you have the
     website up and running, go to:

     http://mywebsite.com/SystemDoc/

     And click on *View OpenInteract Documentation*.

   * Package: These files come in the `doc/' subdirectory of every package
     and give you some idea of what the package does and how you can do
     it. Some packages (like base) come with documentation that describe
     integral system functionality.

     To view the package documentation, go to:

     http://mywebsite.com/SystemDoc/

     And click on *View Package Documentation*. This lists the packages
     currently installed and the available documentation for each.

     Note that package documentation is somewhat lacking right now, but
     we're in the process of fixing this. In the meantime, check out the
     Module documentation below.

   * Module: Normal Perl documentation can/should be found in the modules
     that actually do the work. Since OpenInteract uses its own packaging
     system you won't be able to find them via perldoc as usual. (You
     could circumvent this by putting the package directory in the base
     installation in PERL5LIB, but this isn't recommended.)

     Instead, you can use the browser interface and go to:

     http://mywebsite.com/SystemDoc/

     And choose *View SPOPS/OpenInteract Module Documentation*. This gives
     you a web interface to view the modules (And yes, it looks fine
     through lynx.)

     Similarly, you can click on *View Perl Module Documentation* and see
     all the other Perl modules used by OpenInteract. Click on the module
     name and you'll be able to see the docs online. This is especially
     helpful for the *Template Toolkit*, which comes with a huge amount of
     documentation.

FEEDBACK
========

   We're interested in your feedback on a number of topics. In particular:

   * How did you find the installation process? Was OpenInteract simple to
     install and configure?

   * How easy was it for you to create a website, install its SQL
     structures and data and import its templates?

   * Which documentation do you feel is lacking?

   As you might tell, we're keenly aware that installation and initial
understanding can be a big barrier to entry with a fairly substantial
application like this. Feedback is crucial for us to plug the holes.

   We also hope to extend certain features (such as users and groups) to
different types of data sources, like LDAP directories. Other applications
of OpenInteract really depend on what you'd like it to do!

   Updates can be found in two places:

   CVS access, mailing list information and archives, bug tracking.

     http://sourceforge.net/projects/openinteract/

   Latest news, package repository, everything else.

     http://www.openinteract.org/

REVISION
========

   This document is for version *1.06* of OpenInteract.

CONTACT
=======

   Thanks for trying out OpenInteract! If you have any questions,
comments, thoughts, diatribes, check out the various OpenInteract mailing
lists, hosted at SourceForge at the above URL.

COPYRIGHT
=========

   OpenInteract is Copyright (c) 2001 intes.net, inc.. All rights reserved.

   The OpenInteract library(**) is free software; you can redistribute it
and/or modify it under the terms of the Perl Artistic License or the GNU
General Public License as published by the Free Software Foundation;
either version 2 of the License (see the file COPYING in the source
distribution), or (at your option) any later version.

   **"OpenInteract library" includes the core 'OpenInteract::' files:

   * OpenInteract::ApacheStartup

   * OpenInteract::Config

   * OpenInteract::Config::PerlFile

   * OpenInteract::DBI

   * OpenInteract::Error

   * OpenInteract::Package

   * OpenInteract::PackageRepository

   * OpenInteract::Request

   * OpenInteract::SPOPS

   * OpenInteract::SQLInstall

   * OpenInteract::Startup

   Along with the core packages:

   * base

   * base_box

   * base_component

   * base_error

   * base_group

   * base_security

   * base_system_documentation

   * base_template

   * base_theme

   * base_user

   * static_page

   And the following application packages:

   * classified

   * full_text

   * news

   Every other package, whether developed by intes.net, inc. or other
party, is licensed under its own terms.

Central module to call for initializing an OpenInteract website
***************************************************************

NAME
====

   OpenInteract::ApacheStartup - Central module to call for initializing
an OpenInteract website

SYNOPSIS
========

     # In an website's startup.pl file:

     #!/usr/bin/perl
     use strict;
     use OpenInteract::ApacheStartup;
     my $BASE_CONFIG = '/home/httpd/demo.openinteract.org/conf/base.conf';
     OpenInteract::ApacheStartup->initialize( $BASE_CONFIG );
     1;

DESCRIPTION
===========

   `OpenInteract::ApacheStartup' should be run from the startup.pl file of
your website. (You can probably also load it directly from your apache
config as well, but we will stick with simple things for now :)

   Its purpose is to load as many modules as possible into the parent
mod_perl process so we can share lots of memory. Sharing is good!

   Most of the actual work is done in the `OpenInteract::Startup' module,
so you might want to check the documentation for that if you are curious
how this works.

METHODS
=======

   *initialize( $config_file )*

   Your `startup.pl' file should have a definition for a configuration
file and pass it to this method, which is the only one the module contains.

TO DO
=====

BUGS
====

SEE ALSO
========

   *Configuration Guide to OpenInteract*, `mod_perl' in this node

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters <chris@cwinters.com>

centralized configuration information
*************************************

NAME
====

   OpenInteract::Config - centralized configuration information

SYNOPSIS
========

     use OpenInteract::Config;

     my $config = OpenInteract::Config->new();
     $config->read_file( '/path/to/dbi-config.info' );
     $config->set( 'debugging', 1 );

     my $dbh = DBI->connect( $config->db_dsn(),
                             $config->db_username() ),
                             $config->db_password() ),
                             { RaiseError => 1 } );

     if ( my $debug = $config->get( 'debugging' ) ) {
       print $LOG "Trace level $debug: fetching user $user_id...";
       if ( $self->fetch( $user_id ) ) {
          print $LOG "successful fetching $user_id\n";
       }
       else {
          print $LOG "cannot retrieve $user_id. Error info: ",
                     $self->error()->pop_error();
       }
     }

DESCRIPTION
===========

   Allows you to embed a configuration object that responds to get/set
requests. Different from just using key/value pairs within your object
since you do not have to worry about writing get/set methods, cluttering
up your AUTOLOAD routine, or things like that. It also allows us to create
configuration objects per module, or even per module instance, as well as
create one for the entire program/project by putting it in the
always-accessible Request object.

   Very simple interface and idea: information held in key/value pairs.
You can either retrieve the information using the get() method or by
calling the key name method on the config object. For instance, to
retrieve the information related to DBI, you could do:

     my ( $dsn, $uid, $pass ) = ( $config->db_dsn(),
                                  $config->db_username(),
                                  $config->db_password() );

   or you could do:

     my ( $dsn, $uid, $pass ) = $config->get( 'db_dsn', 'db_username', 'db_password' );

   Setting values is similarly done:

     my $font_face = $config->font_face( 'Arial, Helvetica' );

   or:

     my $font_face = $config->set( font_face => 'Arial, Helvetica' );

   Note that you might want to use the get/set method calls more
frequently for the sake of clarity.

METHODS
-------

   A description of each method follows:

   *new( %params )*

   Parameters:

     Unknown. Depends on what is being configured.

   Create the Config object. Just bless an anonymous hash and stick every
name/value pair passed into the method into the hash.

   Note: we should probably lower case all arguments passed in, but
getting/setting parameters and values should only be done via the
interface. So, in theory, we should not allow the user to set anything
here...

   *flatten_action_config()*

   Copies information from the default action into all the other action
(except the default action and those beginning with '_', which are
presumably private.)

   Returns: an arrayref of action keys (tags) for which information was
set.

   *AUTOLOAD( %params )*

   Parameters:

     Unknown (this is AUTOLOAD!)

   The first parameter, or name of the method call, is assumed to be a
configration key. Call the I<param_set() method with that and the
remainder of the values passed into the call.

   *param_set( $key, [ $value ] )*

   The first parameter is the config key, the optional second parameter is
the value we would like to set the key to.  Simply set the value if it is
passed in, then return whatever the value is.

   Possible modifications: allow the use of a third parameter, 'force',
that enables you to blank out a value. Currently this is not possible.

   *get( @keys )*

   Return a list of values for each $key passed in. If only one key is
passed in, we return a single value, not a list consisting of a single
value.

   Possible modifications: use wantarray to see if we should return a list.

   *set( %params )*

   Parameters:

     config key/value pairs

   Set the config key to its value for each pair passed in.  Return a hash
of the new key/value pairs, or a single value if only one pair was passed
in.

   Possible modifications: Use wantarray to see if we should return a hash
or a single value. Use 'force' parameter to ensure that blank (or undef)
values passed in are reflected properly.

   *get_dir( 'directory-tag' )*

   Retrieves the directory name for 'directory-tag', which within the
Config object may depend on other settings.  For instance, you could have:

     $c->set( 'base_dir', '/home/cwinters/work/cw' );
     $c->set( 'html_dir', '$BASE_DIR/html' );
     $c->set( 'image_dir', '$HTML_DIR/images' );

   and call:

     $c->get_dir( 'image_dir' );

   and receive:

     '/home/cwinters/work/cw/html/images'

   in return.

   We should probably generalize this to other types of settings, but this
Config object is probably on its last legs anyway.

ABSTRACT METHODS
================

   These are methods meant to be overridden by subclasses, so they do not
really do anything here. Useful for having a template to see what
subclasses should do, however.

   *read_config()*

   Abstract method for subclasses to override with their own means of
reading in config information (from DBI, file, CGI, whatever).

   Returns: $config_obj on success; undef on failure

   *save_config()*

   Abstract method for subclasses to override with their own means of
writing config to disk/eleswhere.

   Returns: 1 on success; undef on failure.

TODO
====

   Future work should include setting configuration values permanently for
future uses of the module. We could instantiate the configuration object
with an argument giving it a file to read the keys/values from. A DESTROY
routine could then save all changed values to the file. This would also
allow us to change looks very easily...

BUGS
====

   *Remove Configuration Values*

   Need to determine a way to remove a value for a configuration item.
Since we test for the existence of a value to determine if we are getting
or setting, a non-existent value will simply return what is there.  Not a
big deal currently.

   See *Possible modifications* entries for both set() and *param_set()*.

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters <chris@cwinters.com>

subclass of OpenInteract::Config for reading information from a perl file
*************************************************************************

NAME
====

   OpenInteract::Config::PerlFile - subclass of OpenInteract::Config for
reading information from a perl file

DESCRIPTION
===========

   Create a 'read_config' method to override the base Config method. See
*OpenInteract::Config* for usage of this base object.

   The information in the config file is perl, so we do not have to go
through any nutty contortions with types, etc.

METHODS
=======

   *read_config( $filename )*

   Read configuration directives from $filename. The configuration
directives are actually perl data structures saved in an evalable format
using Data::Dumper.

   *save_config( $filename )*

   Saves the current configuration to $filename. Normally not needed since
you are not always changing configurations left and right.

TO DO
=====

BUGS
====

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters <chris@cwinters.com>

Centralized connection location to DBI databases
************************************************

NAME
====

   OpenInteract::DBIConnect - Centralized connection location to DBI
databases

SYNOPSIS
========

     # Just get a database handle from the info in your config
     # (conf/server.perl)
     my $db = OpenInteract::DBI->connect({
                $CONFIG->{db_info}
              });

DESCRIPTION
===========

   No, we do not subclass DBI with this. No, we do not override any of the
DBI methods. Instead, we provide the means to connect to the database from
one location along with the ability to manipulate the default connection
information before we connect.

   For instance, you can setup OpenInteract in two separate databases.
When users of a certain name login (say, 'devel'), you can change the
'db_name' key of the database connection info hashref from 'webdb' to
'webdb-devel'.

   Note that this should work flawlessly with Apache::DBI, and if you are
using this on a different persistent Perl platform (say, PerlEx) then this
module gives you a single location from which to retrieve database handles
- this makes using the BEGIN/END tricks ActiveState recommends in their
FAQ pretty trivial.

METHODS
=======

   *connect( \%connnect_info, \%params )*

   Usage:

     my $db = eval { OpenInteract::DBI->connect({
                        $CONFIG->{db_info}
                     }) };
     if ( $@ ) {
       die "Cannot connect to database! Error found: $@";
     }
     my ( $sth );
     eval {
      $sth = $db->prepare( 'SELECT blah FROM bleh' );
      $sth->execute;
     };
     ...

   Returns: A DBI database handle with the following parameters set:

     RaiseError: 1
     PrintError: 0
     ChopBlanks: 1
     AutoCommit: 1 (for now...)

   The first parameter is a hashref of connection information. This should
include:

   * dsn: the last part of a fully-formed DBI data source name used to
     connect to this database. Examples:

          Full DBI DSN:     DBI:mysql:webdb
          OpenInteract DSN: webdb

          Full DBI DSN:     DBI:Sybase:server=SYBASE;database=web
          OpenInteract DSN: server=SYBASE;database=web

     So the OpenInteract DSN string only includes the database-specific
     items for DBI, the third entry in the colon-separated string.This
     third item is generally separated by semicolons and usually specifies
     a database name, hostname, packet size, protocol version, etc. See
     your DBD driver for what to do.

   * *db_name*: the name of your database

   * username: what username should we use to login to this database?

   * password: what password should we use in combination with the username
     to login to this database?

   * *driver_name*: what DBD driver is used to connect to your database?
     (Examples: 'Sybase', 'mysql', 'Oracle')

   * *db_owner*: (optional) who owns this database?

   The second parameter is also a hashref and can contain the following
keys:

   * *pre_connect*: the coderef stored here is called before the database
     handle is requested, allowing you to modify any of the information in
     the first parameter before it is sent to DBI.

     Takes the hashref of database connection info as its first parameter,
     and it must return a hashref of database connection info with the
     same conventions as the one passed in. Failure to do so means the
     changes are discarded.

   * *post_connect*: the coderef stored here is called after the database
     handle is requested and allows you to perform whatever actions on it
     that you like.

     Takes the hashref of database connection info as its first parameter
     and the newly created database handle as its second parameter.

     There currently is no return value for this callback - primarily
     because I am not sure what it might be used for :-) Suggestions
     welcome!

   Any errors encountered will result in an exception thrown via die.
Generally, there will be two errors:

   * *Connect error*: This means you cannot even connect to the database.
     This is generally a very serious error.

     You can distinguish this by doing a match on the returned error string
     for `/^Connect failed:/'. Everything after this string is the actual
     error reported by DBI.

   * *Use database error*: This means you connected to the database
     server, but were not able to 'use' your database. (If your database
     does not support the 'use' command, please contact the author.)

     You can find this error by matching the returned error string on
     `/^Use database failed: /'. Everything after this string is the
     actual error reported by DBI.

   Other errors may occur in your callbacks, but reporting them is
entirely up to you. This class does not wrap the call in an `eval {}'
block so you can capture the error and inspect it yourself. After all,
they *are* your callbacks.

STRATEGIES
==========

   Under mod_perl, you can use the simple connection-pooling module
Apache/DBI. This module is quite simple - it overrides the
connect call for `DBI' in this node. For each connect call made, it looks
at the parameters (dsn, username, password and the DBI parameters) to
determine whether it has connected to this database previously. If so, it
returns the cached connection. If not, it creates the connection and
caches it. This happens on a per-httpd-child basis, so if you have 10
httpd children you will have 10 concurrent connections to the database.
Easy, right?

   What happens if you are running multiple websites using one httpd
child? Say you have five websites running on mod_perl process group which
has the aforementioned 10 children. Since each website likely has its own
database, you will eventually have `10 x 5 = 50' connections to your
database. This can be a bad thing.

   To get around this, and assuming that all of these websites connect to
the database as the same user (which certainly is not a given),
OpenInteract allows you to specify a single database for connection. Once
the connection is handed out, OpenInteract will perform the SQL 'use'
command to switch to the correct database.

   The trigger for this is the 'db_name' key of the first parameter passed
into the connect method of this class. If this field is specified, the
method will perform the following statement:

     $dbh->do( "use $db_info->{db_name}" );

   So that you only have to keep one connection for this database open all
the time.

TO DO
=====

   *Test with PerlEx*

   Try to use the BEGIN/END tricks ActiveState recommends - do they work
with just scripts, or also with modules?

BUGS
====

SEE ALSO
========

   See Apache/DBI,

   `DBI' in this node - http://www.symbolstone.org/technology/perl/DBI

   PerlEx - http://www.activestate.com/Products/PerlEx/index.html

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters <chris@cwinters.com>

   Marcus Baker <mbaker@intes.net>

Provide central holding location for Interact errors
****************************************************

NAME
====

   OpenInteract::Error - Provide central holding location for Interact
errors

SYNOPSIS
========

     OpenInteract::Error->set( ... );
     $R->throw( ... );

     my $ei = OpenInteract::Error->get;
     print "Last error message: $ei->{system_msg}\n";

DESCRIPTION
===========

   This class provides a central location for error messages from all
Interact modules. The error information collected in these variables is
guaranteed to result from the most recent error generated by Interact.

VARIABLES
=========

   All of these variables are package variables, so you refer to them like
this:

     $OpenInteract::Error::<variable_name>
     $OpenInteract::Error::system_msg

   See the `NOTES' in this node section below for hints on making the
error variables shorter.

   *user_msg* ($)

   A generic message that is suitable for showing a user. When telling a
user something went wrong, you do not want to tell them:

     execute called with 2 bind variables when 1 are needed

   instead, you want to tell them:

     Database query failed to execute

   This variable is identical to the value thrown by the *die()* command,
so you do not normally need to refer to it.

   *system_msg* ($)

   Even though you do not want to show your users details of the error,
you still need to know them! The variable *system_msg* gives you details
regarding the error.

   type ($)

   Interact knows about a few types of errors. Some depend on your Interact
implementation (e.g., DBI, dbm, LDAP, etc.). Others can be:

     -security: There is a security violation and the action could not be
                completed

   package ($)

   Set to the package from where the error was thrown.

   method ($)

   Set to the method from where the error was thrown.

   filename ($)

   Set to the filename from where the error was thrown.

   line ($)

   Set to the line number from where the error was thrown.

   *extra* (\%)

   Different Interact classes have different information related to the
current request. For instance, DBI errors will typically fill the 'sql'
and 'values' keys. Other Interact implementations may use different keys;
see their documentation for details.

METHODS
=======

   clear ()

   Clears the current error saved in the class. Classes outside the
*OpenInteract::* hierarchy should never need to call this.

   No return value.

   get()

   Returns a hashref with all the currently set error values.

   *set( \% )*

   First clears the variables then sets them all in one fell swoop. The
variables that are set are passed in the first argument, a hashref. Also
sets both the package and method variables for you, although you can
override by setting manually.

   No return value;

   *throw( \%params )*

   Throws an error from anywhere in the system. Kept for backward
compatibility - most of the time you will use:

     $R->throw( ... );

   We simply pass the parameters (with any caller info) to the method by
the same name in the error object class.

NOTES
=====

   Some people might find it easier to alias a local package variable to
an Interact error variable. For instance, you can do:

     *err_user_msg   = \$OpenInteract::Error::user_msg;
     *err_system_msg = \$OpenInteract::Error::system_msg;
     *err_type       = \$OpenInteract::Error::type;
     *err_extra      = \%OpenInteract::Error::extra;

   And then refer to the alias in your local package:

     my $obj_list = eval { $obj->fetch_group( { where => 'this = that' } ) };
     if ( $@ ) {
       warn "Error found! Error: $@\n",
            "Error type: $err_type\n",
            "More specific: $err_system_msg\n",
            "Extra stuff:\n",
            "--$err_extra{sql}\n",
            "--$err_extra{values}\n";
     }

TO DO
=====

BUGS
====

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters <chris@cwinters.com>

Perform actions on individual packages
**************************************

NAME
====

   OpenInteract::Package - Perform actions on individual packages

SYNOPSIS
========

DESCRIPTION
===========

METHODS
=======

   *create_subdirectories( $root_dir, $main_class )*

   Creates subdirectories in a package directory - currently the list of
subdirectories is held in the package lexical @PKG_SUBDIR, plus we also
create the directories:

     $main_class
     $main_class/Handler
     $main_class/SQLInstall

   If there is no $main_class passed in, 'OpenInteract' is assumed.

   *create_package_skeleton( $package_name, $base_install_dir )*

   Creates the skeleton for a package in the current directory. The
skeleton can then be used to for a fully functioning package.

   The skeleton creates the directories found in @PKG_SUBDIR and copies a
number of files from the base OpenInteract installation to the skeleton.
These include:

     Changes
     package.conf
     MANIFEST
     MANIFEST.SKIP
     conf/spops.perl
     conf/action.perl
     doc/package.pod
     doc/titles
     template/dummy.meta
     template/dummy.tmpl
     <PackageName>/SQLInstall/<PackageName>.pm
     <PackageName>/Handler/<PackageName>.pm

   We fill in as much default information as we know in the files above,
and several of the files have helpful hints about the type information
that goes in each.

   *install_distribution*

   Install a package distribution file to the base OpenInteract
installation. We do not need to do any localization work here since we are
just putting the distribution in the base installation, so the operation
is fairly straightforward.

   More work and testing likely needs to be done here to ensure it works
on Win32 systems as well as Unix systems. The use of File/Spec,
and File/Path, should help with this, but
there are still issues with the version of Archive/Tar,
shipped with ActiveState Perl.

   *install_to_website( \%params )*

   Installs a package from the base OpenInteract installation to a
website. The package must already have defined 'website_name',
'website_dir' and 'package_dir' object_properties. Also, the directory:

     website_dir/pkg/pkg-version

   should not exist, otherwise the method will die.

   Note that we use the routines `_copy_spops_config_file()' and
`_copy_action_config_file()', which localize the `spops.perl' and
`action.perl' configuration files for the website. The localization
consists of changing the relevant class names from 'OpenInteract' to
'MyWebsiteName'.

   *export_package( \%params )*

   Exports the package whose root directory is the current directory into
a distribution file in tarred-gzipped format, also placed into the current
directory.

   Returns: Information about the new package in hashref format with the
following keys:

     name
       Name of package

     version
       Version of package

     file
       Full filename of distribution file created

   Parameters:

     config_file ($) (optional)
       Name of configuration file for package.

     config (\%) (optional)
       Hashref of package configuration file information.

   *read_config( \%params )*

   Reads in a package configuration file. This file is in a simple
name-value format, although the file supports lists and hashes as well.
Whether a parameter supports a list or a hash is defined in the package
lexical variables %CONF_LIST_KEYS and %CONF_HASH_KEYS. The reading goes
like this:

   If a key is not in %CONF_LIST_KEYS or %CONF_HASH_KEYS, it is just a
simple key/value pair; a key in %CONF_LIST_KEYS gets the value pushed onto
a stack, and a key found in %CONF_HASH_KEYS has its value split on
whitespace again and that assigned to the hashref indexed by the original
key. Once we hit the 'description' key, the rest of the file is read in at
once and assigned to the description. Note that comments and blank lines
are skipped until we get to the description when it is all just slurped in.

   Returns: hashref of configuration information with the configuration
keys as hashref keys.

   Parameters:

     file
       Full filename of package file to be read in

     info
       Hashref of package information to read package config from

     directory
       Directory from which to read the package config.

   *replace_and_copy( \%params )*

   Copy a file from one place to another and in the process do a
search-and-replace of certain keys.

   Parameters:

     from_file ($)
       File from which we should read text.

     to_file ($)
       File to which we write changed text.

     from_text (\@)
       List of keys to replace

     to_text (\@)
       Replacement values for each of the keys in 'from_text'

HELPER METHODS
==============

   *_extract_archive( $archive_filename )*

   This method is a wrapper around Archive/Tar, to try
and account for some of the differences between versions of the module.
Errors found during extraction will be found in the package lexical
`$ARCHIVE_ERROR'.

   Note that before calling this you should already be in the directory
where the archive will be extracted.

   *_create_manifest*

   Creates a MANIFEST file in the current directory. This file follows the
same rules as found in ExtUtils/Manifest, since
we use the `mkmanifest()' routine from that module.

   Note that we turn on the 'Quiet' and turn off the 'Verbose' parameters
in hopes that the operation will be silent (too confusing), but the
current version of ExtUtils::Manifest does not make its sub-operations
silent. The version shipped with 5.6.1 should take care of this.

   *_remove_directory_tree( $dir )*

   Remove a directory and all files/directories beneath it. Return the
number of removed files.

   *_change_class_name( $old_class, $new_name )*

   Changes the name from 'OpenInteract' to $new_name within $old_class.
For instance:

     my $old_class = 'OpenInteract::Handler::FormProcess';
     my $new_class = $class->_change_class_name( $old_class, 'MyWebsiteName' );
     print "New class is: $new_class\n";

     >> New class is: MyWebsiteName::Handler::FormProcess

   If the method is called from an object and the second argument
($new_name) is not given, we default it to: `$object->{website_name}'.

TO DO
=====

BUGS
====

SEE ALSO
========

   See OpenInteract/Package,

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters <chris@cwinters.com>

Operations to represent, install, remove and otherwise manipulate package repositories.
***************************************************************************************

NAME
====

   OpenInteract::PackageRepository - Operations to represent, install,
remove and otherwise manipulate package repositories.

SYNOPSIS
========

     # Get a reference to a repository

     my $repository = OpenInteract::PackageRepository->fetch(
                                        undef,
                                        { directory => '/opt/OpenInteract' } );

     # Create a new package, set some properties and save to the repository

     my $pkg_info = {
         name      => 'MyPackage',
         version   => 3.13,
         author    => 'Arthur Dent <arthurd@earth.org>',
         base_dir  => '/path/to/installed/OpenInteract',
         package_dir => 'pkg/mypackage-3.13',
      };
      $repository->save_package_info( $info );

     # Retrieve the latest version of a package

     my $info = eval { $repository->fetch_package_by_name({ name => 'MyPackage' }) };
     unless ( $info ) {
       die "No package found with that name!";
     }

     # Retrieve a specific version

     my $info = eval { $repository->fetch_package_by_name({
                                       name => 'MyPackage',
                                       version => 3.12 }) };
     unless ( $info ) {
       die "No package found with that name and version!";
     }

     # Install a package

     my $info = eval { $repository->install_package({
                           package_file => $OPT_package_file }) };
     if ( $@ ) {
       print "Could not install package! Error: $@";
     }
     else {
       print "Package $info->{name}-$info->{version} installed ok!";
     }

     # Install to website (apply package)

     my $info = eval { $repository->fetch_package_by_name({
                                       name => 'MyPackage',
                                       version => 3.12 }) };
     my $site_repository = OpenInteract::Package->fetch(
                                          undef,
                                          { directory => "/home/MyWebsiteDir" } );
     $info->{website_name} = "MyApp";
     $info->{installed_on}  = $repository->now;
     $site_repository->save_package_info( $info );

     # Create a package skeleton (for when you are developing a new
     # package)

     $repository->create_package_skeleton( $package_name );

     # Export a package into a tar.gz distribution file

     chdir( '/home/MyWebsiteDir' );
     my $status = OpenInteract::Package->export_package();
     print "Package: $status->{name}-$status->{version} ",
           "saved in $status->{file}";

     # Find a file in a package

     $repository->find_file({ package => 'MyPackage', file => 'template/mytemplate.tmpl' });
     open( TMPL, $filename ) || die "Cannot open $filename: $!";
     while ( <TMPL> ) { ... }

DESCRIPTION
===========

   This is a different type of module than many others in the
`OpenInteract::' hierarchy. Instead of being created from scratch, the
configuration information is in the class rather than in a configuration
file. It does not use a SQL database for a back end. It does not relate to
any other objects.

   Instead, all we do is represent a package repository. An OpenInteract
package repository is a collection of metadata about files installed to a
particular location, known as a package. The OpenInteract package is a
means of distributing Perl object and handler code, configuration, SQL
structures and data, templates and anything else necessary to implement a
discrete set of functionality.

   A package can exist in two places: in the base installation and in one
or more websites. (You can tell the difference when you are going through
a package information hashref because website packages have the property
'website_dir' defined.)

   The package in the base installation is the master package and should
never be changed. Since you never use it directly, you should never *need*
to change it, either. Every time you create a website the website gets a
customized copy of the master package. The website author can then change
the website package as much as desired without affecting the base
installation master package.

METHODS
=======

   *_class_initialize( $CONFIG )*

   When we initialize the class we want to use the OpenInteract
installation directory for the default package database location.

   *pre_save_action*

   Ensure that before we add a package to a database it has the 'base_dir'
property.

   *fetch_package_by_name( \%params )*

   Retrieve a package by name and/or version. If you ask for a specific
version and that version does not exist, you will get nothing back. If you
do not ask for a version, you will get the latest one available.

   Parameters:

     name ($)
       Package name to retrieve

     version ($ - optional)
       Version of package to retrieve; if you specify a version then
       *only* that version can be returned.

   Example:

     my $pkg = $pkg_class->fetch_by_name( { name => 'zigzag' } );
     if ( $pkg ) {
       print "Latest installed version of zigzag: $pkg->{version}\n";
     }

   *fetch_all_packages()*

   Returns: Arrayref of all package information hashrefs in a particular
repository.

   *verify_package( @package_names )*

   Verify that each of the packages listed in @package_names exists for
this repository.

   Returns: For each package verified a hashref of the package
information. If you pass only one name, you get a single result back;
multiple names get returned in an arrayref.

   *verify_package_list( @package_names )*

   The same as `verify_package()' except we return a list reference of
package instead of a single

   *find_file( @file_list )*

   Pass in one or more possible variations on a filename that you wish to
find within a package. If you pass multiple files, each will be checked in
order. Note that the name must include any directory prefix as well. For
instance:

     $pkg->find_file( 'template/mytemplate', 'template/mytemplate.tmpl' );

   Returns a full filename of an existing file, undef if no existing file
found matching any of the filenames passed in.

   *include_package_dir*

   Put both the base package dir and the website package_dir into  @INC.
Both directories are put onto the front of @INC, the website directory
first and then the base directory. (This enables packages found in the app
to override the base.) Both directories are first tested to ensure they
actually exist.

   Returns: directories that were unshifted onto @INC, in the same order.

   Parameters: none

TO DO
=====

BUGS
====

SEE ALSO
========

   OpenInteract documentation: *Packages in OpenInteract*

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters <chris@cwinters.com>

   Christian Lemburg <lemburg@aixonix.de> suffered through early versions
of the package management system and offered insightful feedback,
including a pointer to ExtUtils/Manifest, and the
advice to move to a text-based storage system.

container for request info and output
*************************************

NAME
====

   OpenInteract::Request - container for request info and output

SYNOPSIS
========

     # Anywhere in your website

     my $R = OpenInteract::Request->instance;
     my $user_rec = $R->user->fetch( $user_id );
     my $org_recs = $R->org->fetch_group;

     my $db_info = $R->CONFIG->db_info();
     my $dbh  = $R->db;

DESCRIPTION
===========

   The Request object is fairly simple, having only a few methods to it.
But it really ties applications together in the OpenInteract framework,
acting as an object repository, a layer between your object names and
their classes, and as a data store between different parts of the process.
Since it is 'always around' (more later), you can thus have necessary
configuration information, your database handle, cache store, template
parser or other tools at your fingertips.

   This package is designed to run under mod_perl. Since it is a subclass
of Class/Singleton, it maintains the request
object (usually $R) around for the life of the Apache child. The intended
side effect of this allows you to pluck the object from the ether from any
handler or utility you are running by simply doing:

     my $R = OpenInteract::Request->intance;

   That's it. You don't need a 'use OpenInteract::Request;' statement, you
don't need to pass the object around from method to method.

   The other job of the OpenInteract::Request object is to keep track of
where we are: which action we're using, what URL was originally requested.
etc.

PACKAGE LEXICALS
----------------

   *%OBJECTS*

   Hash holding all the general objects needed throughout this request.
Note that finish_request() cleans these up (except for the database handle
and config object) at the end of every request.

   *%ALIAS*

   Holds mapping of alias to class name. When the website is first
started, you should call:

     OpenInteract::Request->setup_aliases();

   Which turns these hash entries into subroutines so you can use the
inline method - $R->user vs $R->user(). The latter one is necessary if you
do everything strictly via AUTOLOAD. (Been there, done that...)

METHODS
=======

   *instance()*

   Returns: a blessed Request object. (Inherited from `Class::Singleton'.)

   initialize()

   Initialize the request. You can override this however you wish.

   *throw( \%params )*

   Make it easy to throw errors from anywhere in the system. All
information gets passed directly to `OpenInteract::Error', although we set
the package, filename and line information so it does not appear to the
error handler that all errors are mysteriously being thrown from
OpenInteract::Request, and all from one line, too... :)

   Note that you do not even need to instantiate an object for this:

     OpenInteract::Request->instance->throw( { ... } );

   See also documentation in OpenInteract/Error,
and the `OpenInteract::ErrorObject' in this node.

   *stash( 'name', $obj )*

   Adds an object indexed by 'name' to our stash class. If the object
already exists in the stash class, the default behavior is to simply
overwrite. (You can write a more complicated stash class if you like...)

   Examples:

     $R->stash( 'db', $db );
     $R->stash( 'apache', $apr );

   *get_stash( 'name' )*

   Retrieves the value corresponding to 'name' from the current stash
class. Note that many aliases (e.g., "$R->db") actually call 'get_stash'
internally, so you will not see this used very frequently.

   *setup_aliases()*

   Creates subroutines in the symbol table for this class matching up to
the entries in the lexical %ALIAS. You should call this when your website
first starts.

   *lookup_alias( $alias )*

   Returns a class name matching up to $alias. Use this when you do not
know the alias beforehand. You can use it in two different ways:

     1)  $R->$alias()->fetch( $id );

     2)  my $class = $R->lookup_alias( $alias );
         my $obj = $class->fetch( $id );

   *scrib( $level, $msg [, $msg, $msg, ... ] )*

   Centralized notification logging. Check the {DEBUG} key in the config
object, which is stored in the stash class, for the current debugging
level. If that level is less than the level passed in, we do nothing. But
if the value is equal to or greater than the level passed in then we
'warn' with the error.

   Note that you can pass multiple messages at once to the method - the
method join them with a single space between the messages.  e None of the
$msg items need to conetain the filename, package name, subroutine name or
line number - we pull all that from the reference material sent via
`caller' in this node.

   You can use this as a class method as well:

     OpenInteract::Request->instance->scrib( 2, "Boring log message" );

   And you can use either the object or class methods even if you have not
created and registered a config object. If you have not done so, we will
use the value of the package variable $DEBUG in this class.

   This means that setting the value of the package variable $DEBUG will
send all messages from any application at that level or lower to 'warn'.
Be careful or you will get some big honking logfiles! You might want to
use local for setting this value if you really need to.

   Finally, any log messages sent with a debug level of '0' will always go
to the log.. (We have not accounted for any weisenheimers setting the
config/class debug level to a negative number, but who would do such a
thing?)

   *lookup_conductor( [ $action ] )*

   Finds the conductor for a particular action.

   Returns a two-element list: class and method.

   If $action is not passed in, we find the name from
$R->{path}->{current}.

   *lookup_action( [ $action, \%params ] )*

   Finds information associated with a particular action from the
configuration.

   If $action is not passed in, we find the name from
$R->{path}->{current}.

   You have the option of refusing to allow the method to return a default
action if yours is not found. We use this to implement 'static' web pages.
For instance, if there is no action corresponding to the path
'/mod_perl/guide/toc', then we find the default action (which handles page
objects) and return its information.

   Returns either a two-element list (class and method) or with a 'return'
parameter value of 'info', returns a hashref with all known information
about the action.

   Parameters:

     return
       'info' means return all information about the action

     skip_default
       any true value means to *not* use the default action name, even if
       the action name is not found.

   *finish_request()*

   Cleans out this object and tells the stash class associated with the
request to do the same.

TO DO
=====

BUGS
====

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters <chris@cwinters.com>

   Christian Lemburg <lemburg@aixonix.de> bugged me about getting a
logging method (scrib) in here.

Define common behaviors for all SPOPS objects in the OpenInteract Framework
***************************************************************************

NAME
====

   OpenInteract::SPOPS - Define common behaviors for all SPOPS objects in
the OpenInteract Framework

SYNOPSIS
========

     # In configuration file
     'myobj' => {
        'isa'   => [ qw/ ... Interact::SPOPS ... / ],
     }

DESCRIPTION
===========

   Here we provide some common operations within OpenInteract that are not
implmented within the data abstraction layer itself. One of the reasons
for that is that we want to continue using both separately, so we cannot
embed ideas like a configuration object or a particular cache
implementation within SPOPS. Think of this class as a bridge between the
two.

METHODS
=======

   *log_action( $action, $id )*

   Wrapper for the *log_action_enter* method below, decides whether it
gets called. (Wrapper exists so subclasses can call log_action_enter
directly and not deal with this step.)

   Returns undef on failure, true value on success.

   *log_action_enter( $action, $id )*

   Makes an entry into the 'object_track' table, which logs all object
creations, updates and deletions. We do not note the content that changes,
but we do note who did the action and when it was done.

   Returns undef on failure, true value on success.

   *fetch_creator()*

   Retrieve an arrayref of all user objects who have 'creator' rights to a
particular object.

   *is_creator( $uid )*

   Return 1 if the object was created by $uid, undef if not.

   *fetch_updates()*

   Return an arrayref of arrayrefs, formatted:

     [ uid of updater, date of update ]

   *notify()*

   Either call from an object or from a class passing an arrayref of
objects to send to a user. Calls the as_string() method of the object,
which (if you look in the SPOPS docs), defaults to being a simple property
-> value listing. You can override this with information in your class
configuration which specifies the fields you want to use in the listing
along with associated labels.

   *html_encode( $text )*

   Returns: escaped version of $text (e.g., the character '"' will be
replaced by &quot;)

   *html_decode( $text )*

   Returns: unescaped version of $text (e.g., the entity &quot; will be
replaced by the character '"')

   It may seem silly to have these html_ methods which currently just call
the method of an external module, but we might wish to do more in the
future (for example, screen out javascript>. This way, we have a central
place to change it.

NOTES
=====

TO DO
=====

BUGS
====

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters <chris@cwinters.com>

Dispatcher for installing various SQL data from packages to database
********************************************************************

NAME
====

   OpenInteract::SQLInstall - Dispatcher for installing various SQL data
from packages to database

SYNOPSIS
========

     # Define a SQLInstaller for your package
     package OpenInteract::SQLInstall::MyPackage;

     use strict;
     use vars qw( %HANDLERS );
     %HANDLERS = (
       'create_structure' => { Sybase => \&structure_sybase,
                               Oracle => \&structure_oracle,
                               mysql  => \&structure_mysql },
       ...
     );

     sub structure_sybase { ...do stuff...}
     sub structure_oracle { ...do stuff...}
     sub structure_mysql  { ...do stuff...}

     # Use this class in a separate program
     use OpenInteract::SQLInstall;
     use OpenInteract::PackageRepository;
     use OpenInteract::Startup;
     use OpenInteract::DBI;

     my $C   = OpenInteract::Startup->create_config({
                    base_config_file => "$WEBSITE_DIR/conf/base.conf"
               });
     my $dbh = eval { OpenInteract::DBI->connect( $C->{db_info} ) };
     die "Cannot open database handle: $@"  if ( $@ );

     my $repository = OpenInteract::PackageRepository->fetch(
                                       undef, { directory => $WEBSITE_DIR } );
     my $pkg_info = $repository->fetch_package_by_name( { name => 'my_package' } );
     OpenInteract::SQLInstall->require_package_installer( $pkg_info );
     my %args = ( package => $pkg_info, config => $C, db => $dbh );
     OpenInteract::SQLInstall->apply( { %args, action => 'create_structure' } );
     OpenInteract::SQLInstall->apply( { %args, action => 'install_data' } );
     OpenInteract::SQLInstall->apply( { %args, action => 'install_security' } );

DESCRIPTION
===========

   One of the difficulties with developing an application that can
potentially work with so many different databases is that it needs to work
with so many different databases. Many of the differences among databases
are dealt with by the amazing `DBI' in this node module, but enough remain
to warrant some thought.

   This module serves two audiences:

  1. The user of OpenInteract who wants to get packages, run a few commands
     and have them simply work.

  2. The developer of OpenInteract packages who wants to develop for as
     many databases as possible without too much of a hassle.

        This module provides tools for both. The first group (users) does
not need to concern itself with how this module works - running the
various `oi_manage' commands should be sufficient.

   However, OpenInteract developers need a keen understanding of how
things work. This whole endeavor is a work-in-progress - things work, but
there will certainly be new challenges brought on by the wide variety of
applications for which OpenInteract can be used.

USER OVERVIEW
=============

   Every package has a module that has a handful of procedures specified
in such a way that OpenInteract knows what to call and for which database.
Generally, all you need to deal with is the wrapper provided by the
`oi_manage' program. For instance:

     oi_manage install_sql --website_dir=/home/httpd/myOI --package=mypackage

   This will install the SQL for the package 'mypackage' installed to your
website. As long as you have specified your database properly in your
`conf/server.perl' file, everything should flow smooth as silk.

DEVELOPER OVERVIEW
==================

   The SQL installation program of OpenInteract is a kind of mini
framework - you have the freedom to do anything you like in the handlers
for your package. But OpenInteract provides a number of tools for you as
well.

METHODS
=======

   Note that subclasses do not need to define any of these methods. They
simply need to define a package variable %HANDLERS which describes the
work done for particular actions and particular databases and the routines
to accomplish this work.

   *require_package_installer( $package_object )*

   Given a package object, finds and does a `require' in this node on the
library used to install SQL for this package.

   *apply( \%params )*

   Performs a particular SQL action for a particular package.

   Returns: 'ok' if no errors were returned, or the text of the error if
an error occurred.

   Parameters:

     action
       String with name of action to perform.

     db
       DBI database handle

     config
       OpenInteract configuration object (or just a hashref), which should
       have the key 'db_info' with information about the database in it,
       and the key 'website_name' with the name of the website.

     package
       Package object to perform action on

   *read_db_handlers( $driver_name )*

   Finds the handlers to execute for a particular database ($driver_name).
If your handler does not implement a set of handlers for $driver_name, you
can create a generic one (and hope that it works) using the key
'_default_'.

   Of course, your class may implement this however it needs. But the
method implemented in the parent allows you to define a package variable
like so:

     package MyClass::SQLInstall;

     use strict;
     use vars ( %HANDLERS );

     %HANDLERS = (
         create_structure => { that_db  => \&that_db_structure,
                               other_db => \&other_db_structure },
         install_data     => { '_default_' => \&generic_data },
         install_security => {},
     );

   Returns: hashref with the keys as the actions that can be performed and
the values as code references to apply for a database.

   *sql_class_to_website( $website_name, $text, [ $text, ... ] )*

   Does a simple substitution of 'OpenInteract' for the website on each
string you pass to it.

   Returns the strings with the substitution done in the same order.

   Example:

     my @classes = sql_class_to_website( 'MyWebsite',
                                     qw( OpenInteract::News::Handler
                                         OpenInteract::News ) );
     # @classes is now: MyWebsite::News::Handler MyWebsite::News

   *sql_class_to_oi( $website_name, $text, [ $text, ... ] )*

   Does a simple substitution of your website name to 'OpenInteract' for
each string you pass to it.

   Returns the strings with the substitution done in the same order.

   *sql_modify_increment( $driver_name, $sql, [ $sql, ... ] )*

   Modify each SQL statement to use a particular database style for
representing auto-incrementing values.

   Returns the strings with the substitution done, in the same order.

   *process_data_file( \%params )*

   Processes the datafile described by \%params. This is a fairly hefty
method, and its workings are described in `PROCESSING DATA FILES' in this
node.

   *transform_data( \%action, \@data, \%params )*

   Take the first item from a data file (the action) and perform any
indicated tasks necessary.

   Currently, the tasks implemented by this parent class are:

     transform_class_to_website (\@)
       Specify a list of fields that should have the value transformed to
       replace 'OpenInteract' with the website name

   *read_perl_file( $filename )*

   Reads in the file $filename which describes a perl data structure.
Returns the structure.

   *read_file( $filename )*

   Reads in the file $filename and returns a scalar with all the text of
the file.

   *format_status( \%info, \@status )*

PROCESSING DATA FILES
=====================

   We need to be able to pass data from one database to another and be
very flexible as to how we do it. The various data file formats have taken
care of everything I could think of - hopefully you will think up some
more.

   To begin, there are two elements to a data file. The first element
tells the installer what type of data follows - should we create objects
from them? Should we just plug the values into a SQL statement and execute
it against a particular table?

   The second element is the actual data, which is in an order determined
by the first element.

   There are several different ways to process a data file. Both are
described in detail below:

   Object Processing

   Object processing allows you to just specify the field order and the
class, then let SPOPS do the dirty work. This is the preferred way of
transferring data, but it is not always feasible. An example where it is
not feasible include linking tables that SPOPS uses but does not model.

   SQL Processing

   SQL processing allows you to present elements of a SQL statement and
plug in values as many times as necessary. This can be used most anywhere
and for anything.

Object Processing
-----------------

   The first item in the list describes the class you want to use to
create objects and the order the fields that follow are in. Here is a
simple example of the data file used to install initial groups:

     $data_group = [ { spops_class => 'OpenInteract::Group',
                       field_order => [ qw/ group_id name / ] },
                     [ 1, 'admin' ],
                     [ 2, 'public' ],
                     [ 3, 'site admin' ],
     ];

   Important note: when installing to a website, this module will
substitute the name of the website for 'OpenInteract' in 'spops_class'. So
in the above example the class for the group objects created in
'MyWebsite' will be `MyWebsite::Group' - not `OpenInteract::Group'.

   Here is a slightly abbreviated form of what steps would look like if
they were done in code:

     my $website_name = 'MyWebsite';
     my $object_class = 'OpenInteract::Group';
     $object_class =~ s/OpenInteract/$website_name/;
     my %field_num = { group_id => 0, name => 1 };
     foreach my $row ( @{ $data_rows } ) {
       my $object = $object_class->new();
       $object->{group_id} = $row->[ $field_num{group_id} ];
       $object->{name}     = $row->[ $field_num{name} ];
       $object->save({ is_add => 1, skip_security => 1,
                       skip_log => 1, skip_cache => 1 });
     }

   Easy!

   You can also specify operations to perform on the data before they are
saved with the object. The most common operation of this is in security
data:

     $security = [
                   { spops_class => 'OpenInteract::Security',
                     field_order => [ qw/ class oid scope scope_id level / ],
                     transform_class_to_website => [ qw/ class / ] },
                   [ 'OpenInteract::Group', 1, 'w', 'world', 1 ],
                   [ 'OpenInteract::Group', 2, 'w', 'world', 4 ],
                   [ 'OpenInteract::Group', 2, 'g', '2', 4  ],
                   [ 'OpenInteract::Group', 3, 'w', 'world', 4 ],
                   [ 'OpenInteract::Group', 3, 'g', '3', 8 ],
                   [ 'OpenInteract::Group', 2, 'g', '3', 8 ],
                   [ 'OpenInteract::Handler::Group', 0, 'w', 'world', 4 ],
                   [ 'OpenInteract::Handler::Group', 0, 'g', '3', 8 ]
     ];

   So these steps would look like:

     my $website_name = 'MyWebsite';
     my $object_class = 'OpenInteract::Security';
     $object_class =~ s/OpenInteract/$website_name/;
     my %field_num = { class => 0, oid => 1, scope => 2,
                       scope_id => 3, level => 4 };
     foreach my $row ( @{ $data_rows } ) {
       my $object = $object_class->new();
       $object->{class}    = $row->[ $field_num{class} ];
       $object->{oid}      = $row->[ $field_num{oid} ];
       $object->{scope}    = $row->[ $field_num{scope} ];
       $object->{scope_id} = $row->[ $field_num{scope_id} ];
       $object->{level}    = $row->[ $field_num{level} ];
       $object->{class} =~ s/OpenInteract/$website_name/;
       $object->save({ is_add => 1, skip_security => 1,
                       skip_log => 1, skip_cache => 1 });
     }

   There are currently just a few behaviors you can set to transform the
data before it gets saved, but the interface is there to do just about
anything you can imagine.

SQL Processing
--------------

   The actions performed when you just want to insert data into tables is
similar to those performed when you are inserting objects. The only
difference is that you need to specify a little more. Here is an example:

     $data_link = [ { sql_type => 'insert',
                      sql_table => 'sys_group_user',
                      field_order => [ qw/ group_id user_id / ] },
                    [ 1, 1 ]
     ];

   So we specify the action ('insert'), the table to operate on
('sys_group_user'), the order of fields in the data rows ('field_order',
just like with processing objects) and then list the data.

   More work needs to be done on this so, for instance, you could
implement cleanup routines like this:

     $cleanup = [ { sql_type => 'delete',
                    sql_table => 'sys_group_user',
                    where  => "group_id = ? and user_id = ?" },
                    [ 1, 1 ]
     ];

   Or:

     $cleanup = [ { sql_type => 'delete',
                    sql_table => 'sys_security',
                    transform_class_to_website => [ 1, 2 ] },
                    where  => "class = ? OR class = ?" },
                    [ 'OpenInteract::Group', 'OpenInteract::Handler::Group' ]
     ];

BUGS
====

TO DO
=====

   *Setup removals properly*

   See example under `SQL Processing' in this node, above.

   *Other means of abstraction*

   Using something like Alzabo (see http://alzabo.sourceforge.net/) to
provide schema and data translation abilities would be sweet. However,
Alzabo is a whole nother ball of wax on top of OpenInteract...

   *Dumping data for transfer*

   It would be nice if you could do something like:

     oi_manage dump_sql --website_dir=/home/httpd/myOI --package=mypkg

   And get in your `data/dump' directory a series of files that can be
read in by another OpenInteract website for installation. This is the pie
in the sky - developing something like this would be really cool.

   And we can, but only for SPOPS objects. It is quite simple for us to
read data from a flat file, build objects from the data and save them into
a random database - SPOPS was built for this!

   However, structures are a problem with this. Data that are not held in
objects are a problem. And dealing with dependencies is an even bigger
problem.

SEE ALSO
========

   See OpenInteract/Package, `DBI' in this node

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters <chris@cwinters.com>

Bootstrapper that reads in modules, manipulates @INC, etc.
**********************************************************

NAME
====

   OpenInteract::Startup - Bootstrapper that reads in modules, manipulates
@INC, etc.

SYNOPSIS
========

     # Startup an OpenInteract environment outside Apache and mod_perl

     use strict;
     use OpenInteract::Startup;

     my $R =  OpenInteract::Startup->setup_static_environment(
                                          '/home/httpd/MySite' );

     # For usage inside Apache/mod_perl, see OpenInteract::ApacheStartup

DESCRIPTION
===========

   This module has a number of routines that are (hopefully) independent
of the OpenInteract implementation. One of its primary goals is to make it
simple to initialize OpenInteract not only in a mod_perl context but also
a single-use context. For example, when you create a script to be run as a
cron job to do some sort of data checking (or whatever), you should not be
required to put 50 lines of initialization in your script just to create
the framework.

   This script should also minimize the modules you have to include
yourself, making it easier to add backward-compatible functionality. Most
of the time, you only need to have a 'use' statement for this module which
takes care of everything else.

METHODS
=======

   All methods use the class method invocation syntax, such as:

     OpenInteract::Startup->require_module( { class => [ $my_class ] } );

   *main_initialize( \%params )*

   This will frequently be the only method you call of this class. This
routine goes through a number of common steps:

  1. read in the base configuration file

  2. require the config class, request class and stash class

  3. create the config object

  4. process all packages (see `process_package()' in this node below)

  5. finalize the configuration (see `finalize_configuration()' in this
     node below

  6. set the config object into the stash class

  7. create aliases in the request object (optional)

  8. create/initialize all SPOPS object classes (optional)

        The return value is a list with two members. The first is an
arrayref of all SPOPS object class names that currently exist. The second
is a fully setup *OpenInteract::Config* object. Note that his may change in
the future to be a single return value of the config object with the class
names included as a parameter of it.

   Parameters:

   You must pass in either 'base_config' or 'base_config_file'.

     base_config (\%)
       A hashref with the information from the base configuration file

     base_config_file ($)
       A filename where the base configuration can be found

     alias_init (bool) (optional)
       A true value will initialize aliases within the request class; the
       default is to not perform the initialization.

     spops_init (bool) (optional)
       A true value will create/initialize all SPOPS classes (see
       SPOPS::Configure for more information); the default is to not
       perform the initialization.

     package_extra (\@) (optional)
       A list of packages not included in the filename of packages to read
       in but you want to include anyway (maybe you are testing a new
       package out). The packages included will be put at the end of the
       packages to be read in, although it is feasible that we break this
       into two extra package listings -- those to be read in before
       everything else (but still after 'base') and those to be read in
       after everything else. See if there is a need...

   *setup_static_environment( $website_dir )*

   Sometimes you want to setup OI even when you are not in a web
environment - for instance, you might need to do data reporting, data
import/export, or other tasks.

   With this method, all you need to pass in is the root directory of your
website. It will deal with everything else, including:

   * Reading in the server configuration

   * Reading in all SPOPS and action table configurations - this includes
     setting up @INC properly.

   * Setting up all aliases - SPOPS object and otherwise

   * Creating a database handle

   The only thing it does not do is setup an authentication environment
for you - to get around this (right now), you need to pass in a true value
for 'skip_log' and 'skip_security' whenever you modify and/or retrieve
objects.

   Returns: A "fully-stocked" `OpenInteract::Request' object.

   Example:

     #!/usr/bin/perl

     use strict;
     use OpenInteract::Startup;

     my $R = OpenInteract::Startup->setup_static_environment( '/home/httpd/my' );

     my $news_list = eval { $R->news->fetch_group({
                                   where => 'title like ?',
                                   value => [ '%iraq%' ],
                                   skip_security => 1 }) };
     foreach my $news ( @{ $news_list } ) {
       print "Date:  $news->{posted_on}\n",
             "Title: $news->{title}\n"
             "Story: $news->{news_item}\n";
     }

   Easy!

   *read_package_list( \%params )*

   Reads in a list of packages from a file, one package per line.

   Returns: arrayref of package names.

   Parameters:

   Choose one or the other

     config
       An OpenInteract::Config object which has 'package_list' as a key; this
       file is assumed to be in the 'config' directory, also found on the
       object.

     filename
       A scalar specifying where the packages can be read from.

   *read_base_config( \%params )*

   Reads in the base configuration file, which is a simple per-line
whitespace-separated key-value format.

   Returns a hashref with all information.

   Parameters:

     filename
       A scalar specifying where the file is located; it must have a
       fully-qualified path.

     dir
       A scalar specifying the website directory which has the file
       'conf/base.conf' under it.

   *require_module( \%params )*

   Calls require on one or a number of modules. You can specify a filename
composed of module names (one module per line) and all will be read in.
You can also specify a number of modules to read in.

   Returns: arrayref of modules successfully read in.

   Parameters:

     filename
       Name of file which has modules to read in; one module per line,
       blank lines and lines beginning with a comment (#) are skipped

     class
       Arrayref of classes to read in

   *process_package( \%params )*

   Do initial work to process a particular package. This includes reading
in all external modules and reading both the action configuration and
SPOPS configuration files for inclusion in the config object. We also
include any modules used in the action definition (if you specify a
'class' in a action definition) as well as those in the 'isa' property of
a SPOPS class definition.

   We also add the package directory to @INC, which means any 'use' or
'require' statements that need modules within the package will be able to
work. (See the *OpenInteract Guide to Packages* for more information on
what goes into a package and how it is laid out.)

   Note that we do not create/configure the SPOPS classes yet, since that
process requires that all SPOPS classes to be used exist in the
configuration. (See SPOPS/Configure, for more
details.)

   Parameters:

     package ($)
       Name of package to be processed; this should correspond to a
       particular directory in the package directory

     config (obj)
       An OpenInteract::Config object

     package_dir (\@ - optional)
       Directories where this package might be kept; if not passed in, it
       will be found from the config object

   *read_action_definition( \%params )*

   Read in a action definition file (a perl data structure) and set its
information in the config object. Multiple actions can be configured, and
we do a 'require' on any actions referenced.

   Parameters:

     filename ($)
       File where the action definion is.

     config (obj)
       OpenInteract::Config object where we set the action information.

     package (\%)
       Hashref with information about a package so we can set name/version
       info.

   *read_spops_definition( \%params )*

   Read in a module definition file (a perl data structure) and set its
information in the config object. Multiple SPOPS objects can be
configured, and we do a 'require' on any modules referenced.

   Parameters:

     filename ($)
       File where the module definion is.

     config (obj)
       OpenInteract::Config object where we set the module information.

     package (obj)
       Hashref with information about a package so we can set name/version
       info.

   *read_perl_file( \%params )*

   Simple routine to read in a file generated by or compatible with a perl
data structure and return its value. For instance, your file could have
something like the following:

     $action = {
                'boxes' => {
                    'class'     => 'OpenInteract::Handler::Boxes',
                    'security'  => 'no',
                }, ...
     };

   And the return value would be the hashref that `$module' is set to. The
actual name of the variable is irrelevant, just the data structure
assigned to it.

   Return value is the data structure in the file, or undef if the file
does not exist or the data structure is formatted incorrectly. If the
latter happens, check your error log (STDERR) and a warning will appear.

   Parameters:

     filename ($)
       File to read data structure from.

   Note: we should modify this to use SPOPS/HashFile...

   *finalize_configuration( \%params )*

   At this point, all the SPOPS and module information should be read into
the configuration object and we are ready to finish up the configuration
procedure. This means call the final SPOPS configuration, which creates
classes as necessary and puts configuration information and routines to
link the objects together. We also call the various routines in the
'request_class' (usually OpenInteract::Request) to create necessary
aliases for classes from both SPOPS and base system elements.

   Return value is an arrayref of all SPOPS classes that are configured.
Each one needs to be initialized before use, which can handily be done for
you in the `initialize_spops' method.

   Parameters:

     config (obj)
       An OpenInteract::Config configuration object. Note that the keys
       'request_class', 'SPOPS_config_class' and 'stash_class' must be
       defined in the config object prior to calling this routine.

   *initialize_spops( \%params )*

   Call the `class_initialize' method for each of the SPOPS classes
specified. This must be done before the package can be used.

   Returns an arrayref of classes successfully initialized.

   Parameters:

     class (\@)
       An arrayref of classes to initialize.

     config (obj)
       An OpenInteract::Config configuration object, needed by the
       C<class_initialize> method within the SPOPS classes.

TO DO
=====

BUGS
====

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters <chris@cwinters.com>

Interface to BBS-based groupware platforms
******************************************

NAME
====

   OurNet - Interface to BBS-based groupware platforms

MODULES
=======

     ::BBS        bmpO    Component Object Model for BBS systems
     ::BBSAgent   RmpO    Scriptable telnet-based virtual users
     ::Cell       ampO    Interface-based RPC with Relay & Locating
     ::ChatBot    RmpO    Context-free interactive Q&A engine
     ::FuzzyIndex RmcO    Inverted index for double-byte charsets
     ::Query      RmpO    Perform scriptable queries via LWP
     ::Site       RmpO    Extract web pages via templates
     ::Template   ampO    Template extraction and generation
     ::WebBuilder RmpO    HTML rendering for BBS-based services

DESCRIPTION
===========

   The OurNet:* modules are interfaces to BBS-based groupware projects,
whose platform was used in Hong Kong, China and Taiwan by est. 1 million
users. Used collaboratively, they glue BBSes together to form a
distributed service network, called 'OurNet'.

   Please refer to each individual modules' documentation for usage
information.

AUTHORS
=======

   Autrijus Tang <autrijus@autrijus.org>

COPYRIGHT
=========

   Copyright 2001 by Autrijus Tang <autrijus@autrijus.org>.

   All rights reserved.  You can redistribute and/or modify this module
under the same terms as Perl itself.

Component Object Model for BBS systems
**************************************

NAME
====

   OurNet::BBS - Component Object Model for BBS systems

SYNOPSIS
========

     use strict;
     use OurNet::BBS;

     my $backend = 'CVIC'; # same as 'OurNet::BBS::CVIC'
     my $bbsroot = '/srv/bbs/cvic';
     my $board   = 'sysop';
     my $BBS     = OurNet::BBS->new($backend, $bbsroot);
     my $brd     = $BBS->{boards}{$board};
     my $mtime;

     printf (
         "This BBS has %d boards, %d groups.\n",
         scalar keys(%{$BBS->{boards}}),
         scalar keys(%{$BBS->{groups}}),
     );

     eval { $mtime = $brd->{articles}->mtime };
     die "Error: cannot read board $board -- $@\n" if $@;

     printf (
         "The $board board has %d articles, %d toplevel archive entries.\n",
         $#{$brd->{articles}}, $#{$brd->{archives}},
     );

     # A simple Sysop board article monitor
     print "Watching for new articles...\n";

     while (1) {
         print "=== wait here ($mtime) ===\n";
         sleep 5 until ($brd->{articles}->refresh);

         foreach my $article (@{$brd->{articles}}[1..$#{$brd->{articles}}]) {
         	print "Found article: $article->{title}\n" if $article->btime > $mtime;
         }

         $mtime = $brd->{articles}->mtime;
     }

DESCRIPTION
===========

   OurNet::BBS implements a flexible object model for different BBS
backends.

   More detailed document is expected to appear soon.

AUTHORS
=======

   Chia-Liang Kao <clkao@clkao.org> Autrijus Tang <autrijus@autrijus.org>

COPYRIGHT
=========

   Copyright 2001 by Autrijus Tang <autrijus@autrijus.org>,
  Chia-Liang Kao <clkao@clkao.org>.

   All rights reserved.  You can redistribute and/or modify this module
under the same terms as Perl itself.

Scriptable telnet-based virtual users
*************************************

NAME
====

   OurNet::BBSAgent - Scriptable telnet-based virtual users

SYNOPSIS
========

     # To run it, make sure you have a 'cvic.bbs' file in the same
     # directory. Its contents is listed just below this section.

     use OurNet::BBSAgent;

     my $cvic = new OurNet::BBSAgent('cvic.bbs', undef, 'testlog');

     # $cvic->{'debug'} = 1; # Turn on for debugging

     $cvic->login($ARGV[0] || 'guest', $ARGV[1]);
     print "now at $cvic->{'state'}";
     $cvic->Hook('balloon', \&callback);
     $cvic->Loop;

     sub callback {
         ($caller, $message) = @_;
         print "Received: $message\n";
         exit if $message eq '!quit';
         $cvic->balloon_reply("$caller, I've got your message!");
     }

DESCRIPTION
===========

   OurNet::BBSAgent provides an object-oriented interface to TCP/IP-based
interactive services (e.g. BBS, IRC, ICQ and Telnet), by simulating as a
"virtual user" with action defined by a script language. The developer
could then use the same methods to access different services, to easily
implement interactive robots, spiders, or other cross-service agents.

Site Description File
---------------------

   This module has its own scripting language, which looks like this in a
site description file:

     CVIC BBS
     cvic.org:23

     =login
     wait µù¥U
       or ¨Ï¥ÎªÌ
     send $[username]\n
     doif $[password]
         wait ±K½X
         send $[password]\n\n
     endo
     send \n\n\n
     goto main

     =main
     send eeeeeeee
     wait ¥D¥\¯àªí
     till Call¾÷

     =balloon
     wait \e[1;33;46m¡¹
     till \e[37;45m\x20
     till \x20\e[0m
     exit

     =balloon_reply
     send \x12
     wait ¦^¥h¡G
     send $[message]\n
     wait [Y]
     send \n
     wait \e[m
     exit

   The first two lines describes the service's title, its IP address and
port number. Any number of 'procedures' then begins with `=procname',
which could be called like `$object-'procname([arguments])> in the
program. Each procedure is made by any number of following directives:

wait STRING =item till STRING =item   or STRING
     Tells the agent to wait until STRING is sent by remote host. Might
     time out after `$self-'{'timeout'}> seconds. Any trailing or
     directives specifies an alternative string to match.

     Additionally, `till' puts anything between the last wait or `till'
     and STRING into the return list.

send STRING
     Sends STRING to remote host.

doif CONDITION =item else CONDITION =item endo
     The usual flow control directives. Nested `doif...endo's is supported.

goto PROCEDURE =item call PROCEDURE
     Executes another procedure in the site description file. goto never
     returns, while call always will. Also, a call will not occur if the
     destination was the last executed procedure that does not end with
     exit.

exit
     Marks the termination of a procedure; also means this procedure is not
     a 'state' - that is, multiple calls to it will all be executed.

back
Event Hooks
-----------

   In addition to call the procedures one-by-one, you can 'hook' those
that begins with 'wait' (or 'call' and 'wait') so whenever the strings
they expected are received, the responsible procedure is immediately
called. You can also supply a call-back function to handle its results.

   For example, the code in `' in this node above 'hooks' a callback
function to procedure 'balloon', then enters a event loop by calling Loop,
which never terminates except when the agent receives '!quit' via the
balloon procedure.

   The internal hook table could be accessed by $obj->{'hook'}. It is
implemented via a hash of hash of hash of lists - Kids, don't try this at
home!

AUTHORS
=======

   Autrijus Tang <autrijus@autrijus.org>

COPYRIGHT
=========

   Copyright 2001 by Autrijus Tang <autrijus@autrijus.org>.

   All rights reserved.  You can redistribute and/or modify this module
under the same terms as Perl itself.

Interface-based RPC with relay & locating
*****************************************

NAME
====

   OurNet::Cell - Interface-based RPC with relay & locating

SYNOPSIS
========

     #!/usr/bin/perl -w

     use OurNet::Cell;

     $OurNet::Cell::Debug = 1;

     my $daemon = OurNet::Cell->new('Daemon', 1);
     $daemon->daemonize();

     my $storage = OurNet::Cell->new('Storage', 1);

     $storage->hook('READ.DATA', sub {$_[0]->unicast($_[1], 'WRITE.DATA',
                                      $_[2], $_[0]->{'var'}{$_[1]}{$_[2]})});
     $storage->hook('WRITE.DATA', sub {$_[0]->{'var'}{$_[1]}{$_[2]} = $_[3]});
     $storage->contact(undef, 'localhost') or die;

     my $fetch = OurNet::Cell->new('Fetch', 1);
     $fetch->hook('WRITE.DATA', sub {print "\n$_[2] is $_[3].\n"});
     $fetch->contact(undef, 'localhost') or die;
     $remote = 'Storage';
     $fetch->contact($remote) or die;
     $fetch->unicast($remote, 'WRITE.DATA', 'Test', 'successful');
     RunCells 1;
     $fetch->unicast($remote, 'READ.DATA', 'Test');
     RunCells 1;

     EndCells;

DESCRIPTION
===========

   OurNet::Cell provides a cross-platform, socket-based approach to built
a real-time, state-based, free-form inter-net information-sharing
object-model. (please-insert random-hype right-here).

   Prior to v0.1, this is highly experimental and unstable. Comments are
intentionally lacking - you shouldn't bother with this module unless
you're 1) interested in concurrent mobile agent development, 2) a perl
guru, and 3) having a lot of time to spare.

TODO
====

Cross-protocol support
     UDP and HTTP support (at least) should be in contact() and
     daemonize().

Multicast
     A multicast routing algorithm is under testing.

Findhook and Installhook
     These two are crucial to its emulation to true 'cell' behaviour.

Spawn
     Spawning-on-demanded is expected to function well, but need closer
     inspection as to how it affects smart load-balancing.

AUTHORS
=======

   Autrijus Tang <autrijus@autrijus.org>

COPYRIGHT
=========

   Copyright 2001 by Autrijus Tang <autrijus@autrijus.org>.

   All rights reserved.  You can redistribute and/or modify this module
under the same terms as Perl itself.

Context-free interactive Q&A engine
***********************************

NAME
====

   OurNet::ChatBot - Context-free interactive Q&A engine

SYNOPSIS
========

     use OurNet::ChatBot;

     $mybot = OurNet::ChatBot->new('Amber', 'Amber.bot', 0);

     while (1) {
         print 'User: ';
         print 'Amber Bot: '.$mybot->input(<STDIN>)."\n";
     }

DESCRIPTION
===========

   The ChatBot module simulates a general-purpose, context-free,
interactive Chat Bot using the OurBot(tm) engine. It reads the file stored
in ChatBot/ directory, parses synonyms and random output settings, then
return answers via the input() method.

   The lastone property is used to return/set the id of the bot's last
sentence. In conjunction of directly manipulating the CHUNKS array (which
contains all possible return values for input()), the front-end program
could prevent duplicate responses.

CAVEATS
=======

   The nextone flag-property is badly implemented.

SEE ALSO
========

   See OurNet/FuzzyIndex,

AUTHORS
=======

   Autrijus Tang <autrijus@autrijus.org>

COPYRIGHT
=========

   Copyright 2001 by Autrijus Tang <autrijus@autrijus.org>.

   All rights reserved.  You can redistribute and/or modify this module
under the same terms as Perl itself.

Inverted index for double-byte characters
*****************************************

NAME
====

   OurNet::FuzzyIndex - Inverted index for double-byte characters

SYNOPSIS
========

     use OurNet::FuzzyIndex;

     my $idxfile  = 'test.idx'; # Name of the database file
     my $pagesize = undef;      # Page size (twice of an average record)
     my $cache    = undef;      # Cache size (undef to use default)
     my $subdbs   = 0;          # Number of child dbs; 0 for none

     # Initiate the DB from scratch
     unlink $idxfile if -e $idxfile;
     my $db = OurNet::FuzzyIndex->new($idxfile, $pagesize, $cache, $subdbs);

     # Index a record: key = 'Doc1', content = 'Some text here'
     $db->insert('Doc1', 'Some text here');

     # Alternatively, parse the content first with different weights
     my %words = $db->parse("Some other text here", 5);
     %words = $db->parse_xs("Some more texts here", 2, \%words);

     # Then index the resulting hash with 'Doc2' as its key
     $db->insert('Doc2', %words);

     # Perform a query: the 2nd argument is the 'exact match' flag
     my %result = $db->query('search for some text', $MATCH_FUZZY);

     # Combine the result with another query
     %result = $db->query('more please', $MATCH_NOT, \%result);

     # Dump the results; note you have to call $db->getkey each time
     foreach my $idx (sort {$result{$b} <=> $result{$a}} keys(%result)) {
         $val = $result{$idx};
         print "Matched: ".$db->getkey($idx)." (score $val)\n";
     }

     # Set database variables
     $db->setvar('variable', "fetch success!\n");
     print $db->getvar('variable');

     # Get all records: the optional 0 says we want an array of keys
     print "These records are indexed:\n";
     print join(',', $db->getkeys(0));

     # Alternatively, get it with its internal index number
     my %allkeys = $db->getkeys(1);

DESCRIPTION
===========

   OurNet::FuzzyIndex implements a simple consecutive-letter indexing
mechanism specifically designed for multi-byte encoding maps, e.g.  big-5
or utf8.

   It uses DB_File to create an associative mapping from each character to
its consecutive one, utilizing DB_BTREE's duplicate key feature to speed
up the query time. Its scoring algorithm is also geared to reduce
redundant word's impact on the query's result.

   Although this module currently only supports big-5 and latin-1 encodings
internally, you could override the `parse.c' module for extensions, or add
your own translation maps.

KNOWN ISSUES
============

   The query() function uses a time-consuming callback function _parse_q
to parse the query string; it is expected to be changed to a simple
function that returns the whole processed list. (Fortunately, most query
strings won't be long enough to cause significant difference.)

   The MATCH_EXACT flag is misleading; FuzzyIndex couldn't tell if a query
matches the conetnt exactly from the info stored in the index file alone.
You are encouraged to write your own grep-like post filter.

TODO
====

   * Internal handling of locale/unicode mappings * Boolean / selective
search using combined MATCH_* flags * Fix bugs concerning sub_dbs

AUTHORS
=======

   Autrijus Tang <autrijus@autrijus.org>

COPYRIGHT
=========

   Copyright 2001 by Autrijus Tang <autrijus@autrijus.org>.

   All rights reserved.  You can redistribute and/or modify this module
under the same terms as Perl itself.

Perform scriptable queries via LWP
**********************************

NAME
====

   OurNet::Query - Perform scriptable queries via LWP

SYNOPSIS
========

     use OurNet::Query;

     # Set query parameters
     my ($query, $hits) = ('autrijus', 10);
     my @sites = ('Altavista', 'InfoSeek', 'Yahoo', 'Excite');
     my %found;

     # Generate a new Query object
     my $bot = OurNet::Query->new($query, $hits, @sites);

     # Perform a query
     my $found = $bot->begin(\&callback, 30); # Timeout after 30 seconds

     print '*** ' . ($found ? $found : 'No') . ' match(es) found.';

     sub callback {
         my %entry = @_;
         my $entry = \%entry;

     unless ($found{$entry{'url'}}) {
         print "*** [$entry->{'title'}]" .
                  " ($entry->{'score'})" .
                " - [$entry->{'id'}]\n"  .
          "    URL: [$entry->{'url'}]\n";
     }

     $found{$entry{'url'}}++;
         }

DESCRIPTION
===========

   OurNet::Query provides an easy interface to perform multiple queries to
internet services, and "wrap" them into your own format at once.  The
results are processed on-the-fly and are returned via callback functions.

SEE ALSO
========

   See OurNet/Site,

AUTHORS
=======

   Autrijus Tang <autrijus@autrijus.org>

COPYRIGHT
=========

   Copyright 2001 by Autrijus Tang <autrijus@autrijus.org>.

   All rights reserved.  You can redistribute and/or modify this module
under the same terms as Perl itself.

Extract web pages via templates
*******************************

NAME
====

   OurNet::Site - Extract web pages via templates

SYNOPSIS
========

     use LWP::Simple;
     use OurNet::Site;

     my ($query, $hits) = ('autrijus', 10);
     my $found;

     # Create a bot
     $bot = OurNet::Site->new('Altavista');

     # Parse the result got from LWP::Simple
     $bot->callme($self, 0, get($bot->geturl($query, $hits)), \&callmeback);

     print '*** ' . ($found ? $found : 'No') . ' match(es) found.';

     # Callback routine
     sub callmeback {
         my ($self, $himself) = @_;

     foreach my $entry (@{$himself->{'response'}}) {
         if ($entry->{'url'}) {
             print "*** [$entry->{'title'}]" .
                      " ($entry->{'score'})" .
                    " - [$entry->{'id'}]\n"  .
              "    URL: [$entry->{'url'}]\n" .
                    "    $entry->{'preview'}\n";
             $found++;
             delete($entry->{'url'});
         }
     }
         }

DESCRIPTION
===========

   This module emulates a typical search engine by reading a XML script
defining its aspects, and parses results on-the-fly accordingly.

   Note that it also takes Inforia Quest .fmt scripts, available at
http://www.inforian.com/. The author of course cannot support this usage.

BUGS
====

   Probably lots. Most notably the 'More' facilities is lacking. Also
there is no template-generating abilities. This is a must, but I couldn't
find enough motivation to do it. Maybe you could.

SEE ALSO
========

   See OurNet/Query,

AUTHORS
=======

   Autrijus Tang <autrijus@autrijus.org>

COPYRIGHT
=========

   Copyright 2001 by Autrijus Tang <autrijus@autrijus.org>.

   All rights reserved.  You can redistribute and/or modify this module
under the same terms as Perl itself.

Web rendering for BBS-based services
************************************

NAME
====

   OurNet::WebBuilder - Web rendering for BBS-based services

SYNOPSIS
========

     use OurNet::WebBuilder;

     my $tmpl = {
         dir     => \%dir,
         article => \%article,
         cgi_url => CGI->url
     };

     my $opref = {
     	'' => sub {
     	    return '!view';
     	},

     'view' => sub {
         $tmpl->{'menu'} ||= param('curdir') || $dir{'oin'}[0]{id};
      	    $tmpl->{'curdir'} ||= param('curdir') || $dir{'oin'}[0]{id};
         loadboard($tmpl->{'curdir'});

     loadarticle($_->{'id'},
     			($tmpl->{'curdir'} eq 'bbs' ? $bbs : ($oin, $tmpl->{'curdir'})))
     		foreach @{$dir{$tmpl->{'curdir'}}};

     return 'view';
     	}
         };

     OurNet::WebBuilder::Display($tmpl, $opref);

DESCRIPTION
===========

   the method Display takes $tmpl, which is a variable pool, and $opref,
which is hash of mapping from 'op' to the subroutine for that 'op'.

   The op routine fill in the $tmpl with the varialbes it would like the
variable pool to have, and returns the name of the template file that
would be used. or if the return value begins with '!', the variable pool
will be transit to the specified op again.

AUTHORS
=======

   Autrijus Tang <autrijus@autrijus.org>

COPYRIGHT
=========

   Copyright 2000 by Autrijus Tang <autrijus@autrijus.org>.

   All rights reserved.  You can redistribute and/or modify this module
under the same terms as Perl itself.

Perl extension for the Perforce API
***********************************

NAME
====

   P4::Client - Perl extension for the Perforce API

SYNOPSIS
========

     use P4::Client;
     use P4::UI;

     my $client = new P4::Client;
     my $ui = new P4::UI;

     $client->SetClient( $clientname );
     $client->SetPort ( $p4port );
     $client->SetPassword( $p4password );
     $client->Init() or die( "Failed to connect to Perforce Server" );
     $client->Run( $ui, "info" );
     $client->Run( $ui, "edit", "file.txt" );

     # OR, using Autoloaded methods instead of Client::Run().
     $client->Users( $ui );
     $client->Resolve( $ui, "-ay" );
     $client->Submit( $ui );

     $client->Final();

DESCRIPTION
===========

   This module provides a Perl interface to the Perforce API allowing you
to write Perl scripts which communicate directly with a Perforce server.

   P4::Client is the main interface through which all commands are issued.
The Perforce API is callback based though, and all interaction with the
user interface takes place through callbacks to methods of the P4::UI
object passed to the Run() method.

   To customise the behaviour of the Perforce client, you should derive
your own class from P4::UI and override the relevant methods therein.

METHODS
=======

   The following paragraphs define the methods of a P4::Client object.
Note that due to the magic of the Autoloader, the Perforce commands (
submit, client, filelog etc. ) are also available as methods ( case
insensitive ) as well as through the Run() method.

`Client::new()'
     Construct a new Client object.

`Client::Dropped()'
     Returns true if the TCP/IP connection between client and server has
     been dropped.

`Client::Final()'
     Terminate the connection and clean up. Should be called before exiting
     to cleanly disconnect.

`Client::GetClient()'
     Returns the current Perforce client name. This may have previously
     been set by SetClient(), or may be taken from the environment or
     P4CONFIG file if any. If all that fails, it will be your hostname.

`Client::GetCwd()'
     Returns the current working directory as your Perforce client sees it.

`Client::GetHost()'
     Returns the client hostname. Defaults to your hostname, but can be
     overridden with SetHost()

`Client::GetPassword()'
     Returns your Perforce password - in plain text if that's how it's
     stored and currently on all except Windows platforms, that's the way
     it's done.  Taken from a previous call to SetPassword() or extracted
     from the environment ( $ENV{P4PASSWD} ), or a P4CONFIG file.

     Note that the password is not transmitted in clear text.

`Client::GetPort()'
     Returns the current address for your Perforce server. Taken from a
     previous call to SetPort(), or from $ENV{P4PORT} or a P4CONFIG file.

`Client::Init()'
     Initializes the Perforce client and connects to the server.  Returns
     false on failure and true on success.

`Client::Run( $ui, $cmd, [$arg...] )'
     Run a Perforce command. The first argument must be a reference to a
     P4::UI object or a reference to an object derived from P4::UI. The
     methods of that object will be used to interact with the user. The
     subsequent arguments are the command you wish to run, and the
     arguments you want to pass to it. At this time, only strings and
     numbers are valid argument types although through the magic of Perl
     you can pass arrays or hashes but not references.

`Client::SetClient( $client )'
     Sets the name of your Perforce client. If you don't call this method,
     then the clientname will default according to the normal Perforce
     conventions. i.e.

       1. Value from file specified by P4CONFIG

       2. Value from `$ENV{P4CLIENT}'

       3. Hostname

`Client::SetCwd( $path )'
     Sets the current working directory for the client. This should be
     called after the Init() and before the Run().

`Client::SetPassword( $password )'
     Set the password for the Perforce user, overriding all defaults.

`Client::SetPort( [$host:]$port )'
     Set the port on which your Perforce server is listening. Defaults to:

       1. Value from file specified by P4CONFIG

       2. Value from `$ENV{P4PORT}'

       3. perforce:1666

`Client::SetProtocol( $protflag, $value )'
     Set protocol options for this session. The most common protocol
     option is the "tag" option which requests tagged output format for
     commands which would otherwise get formatted output. In API terms,
     this means the output comes through the P4::UI::OutputStat()
     interface, instead of P4::UI::OutputInfo().

     For example:

     `< $client-'SetProtocol(tag',") >>

`Client::SetUser( $username )'
     Set your Perforce username. Defaults to:

       1. Value from file specified by P4CONFIG

       2. Value from `$ENV{P4USER}'

       3. OS username

API Versions
============

   This extension has been built and tested on the Perforce 2000.2 API,
but should work with any recent version, certainly any release later than
and including 99.2.

LICENCE
=======

   Copyright (c) 1997-2001, Perforce Software, Inc.  All rights reserved.

   Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

   1.  Redistributions of source code must retain the     above copyright
notice, this list of conditions     and the following disclaimer.

   2.  Redistributions in binary form must reproduce     the above
copyright notice, this list of conditions     and the following disclaimer
in the documentation     and/or other materials provided with the
distribution.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE SOFTWARE, INC. BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

AUTHOR
======

   Tony Smith, Perforce Software ( tony@perforce.com )

SEE ALSO
========

   perl(1), P4::UI(3), Perforce API documentation.

User interface object for Perforce API
**************************************

NAME
====

   P4::UI - User interface object for Perforce API

SYNOPSIS
========

     use P4::Client;
     use P4::UI;

     my $client = new P4::Client;
     my $ui = new P4::UI;

     $client->SetClient( $clientname );
     $client->SetPort ( $p4port );
     $client->SetPassword( $p4password );
     $client->Init() or die( "Failed to connect to Perforce Server" );
     $client->Run( $ui, "info" );
     $client->Run( $ui, "edit", "file.txt" );
     $client->Final();

DESCRIPTION
===========

   This module provides a skeleton user interface for Perforce commands.
The output from the Perforce server is simply written to stdout, and input
comes from stdin. In order to do anything clever, you will need to derive
a subclass from P4::UI and override the appropriate methods.

EXPORTS
-------

     UI::new()	- Create a new user interface object

METHODS
=======

`UI::new()'
          Constructor. The only method of this class you call
          directly.

LICENCE
=======

   Copyright (c) 1997-2001, Perforce Software, Inc.  All rights reserved.

   Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

   1.  Redistributions of source code must retain the     above copyright
notice, this list of conditions     and the following disclaimer.

   2.  Redistributions in binary form must reproduce     the above
copyright notice, this list of conditions     and the following disclaimer
in the documentation     and/or other materials provided with the
distribution.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE SOFTWARE, INC. BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

AUTHOR
======

   Tony Smith, Perforce Software ( tony@perforce.com )

SEE ALSO
========

   perl(1), P4::Client(3), Perforce API documentation.

absolutely easy yet fast and powerful sql access
************************************************

NAME
====

   PApp::SQL - absolutely easy yet fast and powerful sql access

SYNOPSIS
========

     use PApp::SQL;

     my $st = sql_exec $DBH, "select ... where a = ?", $a;

     local $DBH = <database handle>;
     my $st = sql_exec \my($bind_a, $bind_b), "select a,b ...";
     my $st = sql_insertid
                 sql_exec "insert into ... values (?, ?)", $v1, $v2;
     my $a = sql_fetch "select a from ...";
     sql_fetch \my($a, $b), "select a,b ...";

     sql_exists "name from table where name like 'a%'"
        or die "a* required but not existent";

     my $db = new PApp::SQL::Database "", "DBI:mysql:test", "user", "pass";
     local $PApp::SQL::DBH = $db->checked_dbh; # does 'ping'

     sql_exec $db->dbh, "select ...";

DESCRIPTION
===========

   This module provides you with easy-to-use functions to execute sql
commands (using DBI). Despite being easy to use, they are also quite
efficient and allow you to write faster programs in less lines of code. It
should work with anything from perl-5.004_01 onwards, but I only support
5.005+.

   If the descriptions here seem terse or if you always wanted to know
what PApp is then have a look at the PApp module which uses this module
extensively but also provides you with a lot more gimmicks to play around
with to help you create cool applications ;)

GLOBAL VARIABLES
----------------

$sql_exec
     Since the `sql_exec' family of functions return a statement handle
     there must eb another way to test the return value of the execute
     call. This global variable contains the result of the most recent
     call to execute done by this module.

$PApp::SQL::DBH
     The default database handle used by this module if no `$DBH' was
     specified as argument and no `$DBH' is found in the current package.
     See `sql_exec' for a discussion.

$PApp::SQL::Database
     The current default `PApp::SQL::Database'-object. Future versions
     might automatically fall back on this database and create database
     handles from it if neccessary. At the moment this is not used by this
     module but might be nice as a placeholder for the database object
     that corresponds to $PApp::SQL::DBH.

FUNCTIONS
---------

$dbh = connect_cached $id, $dsn, $user, $pass, $flags, $connect
     (not exported by by default)

     Connect to the database given by `($dsn,$user,$pass)', while using the
     flags from $flags. These are just the same arguments as given to
     `DBI-'connect>.

     The database handle will be cached under the unique id
     `$id|$dsn|$user|$pass'. If the same id is requested later, the cached
     handle will be checked (using ping), and the connection will be
     re-established if necessary (be sure to prefix your application or
     module name to the id to make it "more" unique. Things like
     __PACKAGE__ .  __LINE__ work fine as well).

     The reason $id is necessary is that you might specify special connect
     arguments or special flags, or you might want to configure your $DBH
     differently than maybe other applications requesting the same database
     connection. If none of this is becessary for your application you can
     leave $id empty (i.e. "").

     If specified, `$connect' is a callback (e.g. a coderef) that will be
     called each time a new connection is being established, with the new
     $dbh as first argument.

     Examples:

          # try your luck opening the papp database without access info
          $dbh = connect_cached __FILE__, "DBI:mysql:papp";

$sth = sql_exec [dbh,] [bind-vals...,] "sql-statement", [arguments...]
     `sql_exec' is the most important and most-used function in this
     module.

     Runs the given sql command with the given parameters and returns the
     statement handle. The command and the statement handle will be cached
     (with the database handle and the sql string as key), so prepare will
     be called only once for each distinct sql call (please keep in mind
     that the returned statement will always be the same, so, if you call
     `sql_exec' with the same dbh and sql-statement twice (e.g. in a
     subroutine you called), the statement handle for the first call
     mustn't be used.

     The database handle (the first argument) is optional. If it is
     missing, `sql_exec' first tries to use the variable `$DBH' in the
     current (= calling) package and, if that fails, it tries to use
     database handle in $PApp::SQL::DBH, which you can set before calling
     these functions.

     The actual return value from the `$sth-'execute> call is stored in the
     package-global (and exported) variable $sql_exec.

     If any error occurs `sql_exec' will throw an exception.

     Examples:

          # easy one
          my $st = sql_exec "select name, id from table where id = ?", $id;
          while (my ($name, $id) = $st->fetchrow_array) { ... };

          # the fastest way to use dbi, using bind_columns
          my $st = sql_exec \my($name, $id),
                            "select name, id from table where id = ?",
                            $id;
          while ($st->fetch) { ...}

          # now use a different dastabase:
          sql_exec $dbh, "update file set name = ?", "oops.txt";

sql_fetch <see sql_exec>
     Execute a sql-statement and fetch the first row of results. Depending
     on the caller context the row will be returned as a list (array
     context), or just the first columns. In table form:

          CONTEXT	RESULT
          void		()
          scalar		first column
          list		array

     sql_fetch is quite efficient in conjunction with bind variables:

          sql_fetch \my($name, $amount),
                    "select name, amount from table where id name  = ?",
                    "Toytest";

     But of course the normal way to call it is simply:

          my($name, $amount) = sql_fetch "select ...", args...

     ... and it's still quite fast unless you fetch large amounts of data.

sql_fetchall <see sql_exec>
     Similarly to sql_fetch, but all result rows will be fetched (this is
     of course inefficient for large results!). The context is ignored
     (only list context makes sense), but the result still depends on the
     number of columns in the result:

          COLUMNS	RESULT
          0		()
          1		(row1, row2, row3...)
          many		([row1], [row2], [row3]...)

     Examples (all of which are inefficient):

          for (sql_fetchall "select id from table") { ... }

          my @names = sql_fetchall "select name from user";

          for (sql_fetchall "select name, age, place from user") {
             my ($name, $age, $place) = @$_;
          }

sql_exists "<table> where ...", args...
     Check wether the result of the sql-statement "select xxx from
     $first_argument" would be empty or not (that is, imagine the string
     "select from" were prepended to your statement (it isn't)). Should
     work with every database but can be quite slow, except on mysql,
     where this should be quite fast.

     Examples:

          print "user 7 exists!\n"
             if sql_exists "user where id = ?", 7;

          die "duplicate key"
             if sql_exists "user where name = ? and pass = ?", "stefan", "geheim";

$lastid = sql_insertid $sth
     Returns the last automatically created key value. It must be executed
     directly after executing the insert statement that created it. This is
     what is actually returned for various databases. If your database is
     missing, please send me an e-mail on how to implement this ;)

          mysql:    first C<AUTO_INCREMENT> column set to NULL
          postgres: C<oid> column (is there a way to get the last SERIAL?)
          sybase:   C<IDENTITY> column of the last insert (slow)
          informix: C<SERIAL> or C<SERIAL8> column of the last insert

     Except for sybase, this does not require a server access.

[old-size] = cachesize [new-size]
     Returns (and possibly changes) the LRU cache size used by `sql_exec'.
     The default is somewhere around 50 (= the 50 last recently used
     statements will be cached). It shouldn't be too large, since a simple
     linear listed is used for the cache at the moment (which, for small
     (<100) cache sizes is actually quite fast).

     The function always returns the cache size in effect before the call,
     so, to nuke the cache (for example, when a database connection has
     died or you want to garbage collect old database/statement handles),
     this construct can be used:

          PApp::SQL::cachesize PApp::SQL::cachesize 0;

reinitialize [not exported]
     Clears any internal caches (statement cache, database handle cache).
     Should be called after fork and other accidents that invalidate
     database handles.

THE DATABASE CLASS
------------------

   Again (sigh) the problem of persistency. What do you do when you have
to serialize on object that contains (or should contain) a database
handle? Short answer: you don't. Long answer: you can embed the necessary
information to recreate the dbh when needed.

   The `PApp::SQL::Database' class does that, in a relatively efficient
fashion: the overhead is currently a single method call per access (you
can cache the real dbh if you want).

$db = new <same arguments as `connect_cached'>
     The new call takes the same arguments as `connect_cached' (obviously,
     if you supply a connect callback it better is serializable, see
     `PApp::Callback' in this node!) and returns a serializable database
     class. No database handle is actually being created.

$db->dbh
     Return the database handle as fast as possible (usually just a hash
     lookup).

$db->checked_dbh
     Return the database handle, but first check that the database is still
     available and re-open the connection if necessary.

$db->dsn
     Return the DSN (`DBI' in this node) fo the database object (e.g. for
     error messages).

SEE ALSO
========

   `PApp' in this node.

AUTHOR
======

     Marc Lehmann <pcg@goof.com>
     http://www.goof.com/pcg/marc/

Library for PDF access and manipulation in Perl
***********************************************

NAME
====

   PDF - Library for PDF access and manipulation in Perl

SYNOPSIS
========

     use PDF;

     $pdf=PDF->new ;
     $pdf=PDF->new(filename);

     $result=$pdf->TargetFile( filename );

     print "is a pdf file\n" if ( $pdf->IsaPDF ) ;
     print "Has ",$pdf->Pages," Pages \n";
     print "Use a PDF Version  ",$pdf->Version ," \n";
     print "and it is crypted  " if ( $pdf->IscryptedPDF) ;

     print "filename with title",$pdf->GetInfo("Title"),"\n";
     print "and with subject ",$pdf->GetInfo("Subject"),"\n";
     print "was written by ",$pdf->GetInfo("Author"),"\n";
     print "in date ",$pdf->GetInfo("CreationDate"),"\n";
     print "using ",$pdf->GetInfo("Creator"),"\n";
     print "and converted with ",$pdf->GetInfo("Producer"),"\n";
     print "The last modification occurred ",$pdf->GetInfo("ModDate"),"\n";
     print "The associated keywords are ",$pdf->GetInfo("Keywords"),"\n";

     my (startx,starty, endx,endy) = $pdf->PageSize ($page) ;

DESCRIPTION
===========

   The main purpose of the PDF library is to provide classes and functions
that allow to read and manipulate PDF files with perl. PDF stands for
Portable Document Format and is a format proposed by Adobe.  A full
description of this format can be found in the *Portable Document
Reference Manual* by *Adobe Systems Inc.*. For more details about PDF,
refer to:

   *http://www.adobe.com/*

   The main idea is to provide some "basic" modules for access the
information contained in a PDF file. Even if at this moment is in an early
development stage, the scripts in the example directory show that it is
usable.

   *is_pdf* script test a list of files in order divide the PDF file from
the non PDF using the info provided by the files themselves. It doesn't
use the *.pdf* extension, it uses the information contained in the file.

   *pdf_version* returns the PDF level used for writing a file.

   *pdf_pages* gives the number of pages of a PDF file.

   *pagedump.pl* prints some information about individual pages in a
PDF-file. Although the information as such are not very useful, it
demontrates well some more complex aspects of the library. Check the
function *doprint* in this program on how to handle all possible data
occuring in a PDF.

   The library is now splitted in 2 section :

   *PDF::Core* that contains the data structure, the constructor and low
level access fuctions;

   *PDF::Parse* all kind of functions to parse the PDF-files and provide
information about the content.

   Check the help-files of these modules for more details.

Variables
=========

   There are 2 variables that can be accessed:

$PDF::VERSION
     Contain the version of the library installed.

$PDF::Verbose
     This variable is false by default. Change the value if you want more
     verbose output messages from library.

Copyright
=========

     Copyright (c) 1998 - 2000 Antonio Rosella Italy antro@tiscalinet.it, Johannes Blach dw235@yahoo.com

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Availability
============

   The latest version of this library is likely to be available from:

   http://www.geocities.com/CapeCanaveral/Hangar/4794/

   and at any CPAN mirror

Greetings
=========

   Fabrizio Pivari ( pivari@geocities.com ) for all the suggestions about
life, the universe and everything.  Brad Appleton ( bradapp@enteract.com )
for his suggestions about the module organization.  Thomas Drillich for
the iso latin1 support Ross Moore ( ross@ics.mq.edu.au ) for ReadInfo fix

Core Library for PDF library
****************************

NAME
====

   PDF::Core - Core Library for PDF library

SYNOPSIS
========

     use PDF::Core;

     $pdf=PDF::Core->new ;
     $pdf=PDF->new(filename);

     $res= $pdf->GetObject($ref);

     $name = UnQuoteName($pdfname);
     $string = UnQuoteString($pdfstring);

     $pdfname = QuoteName($name);
     $pdfhexstring = QuoteHexString($string);
     $pdfstring = QuoteString($string);

     $obj = PDFGetPrimitive (filehandle, \$offset);
     $line = PDFGetLine (filehandle, \$offset);

DESCRIPTION
===========

   The main purpose of the PDF::Core library is to provide the data
structure and the constructor for the more general PDF library.

Helper functions
================

   This functions are not part of the class, but perform useful services.

UnQuoteName ( string )
----------------------

   This function processes quoted characters in a PDF-name. PDF-names
returned by *GetObject* are already processed by this function.

   Returns a string.

UnQuoteString ( string )
------------------------

   This function extracts the text from PDF-strings and PDF-hexstrings.
It will process all quoted characters and remove the enclosing braces.

   WARNING: The current version doesn't handle unicode strings properly.

   Returns a string.

QuoteName ( string )
--------------------

   This function quotes problematic characters in a PDF-name. This
function should be used before writing a PDF-name back to a PDF-file.

   Returns a string.

QuoteHexString ( string )
-------------------------

   This function translates a string into a PDF-hexstring.

   Returns a string.

QuoteString ( string )
----------------------

   This function translates a string into a PDF-string. Problematic
character will be quoted.

   WARNING: The current version doesn't handle unicode strings properly.

   Returns a string.

PDFGetPrimitive ( filehandle, offset )
--------------------------------------

   This internal function is used while parsing a PDF-file. If you are not
writing extentions for this library and are parsing some special parts of
the PDF-file, stay away and use *GetObject* instead.

   This function has many quirks and limitations. Check the source for
details.

PDFGetline ( filehandle, offset )
---------------------------------

   This internal function was used to read a line from a PDF-file. It has
many limitations and you should stay away from it, if you don't know what
you are doing. Use *GetObject* or *PDFGetPrimitive* instead.

Constructor
===========

new ( [ filename ] )
--------------------

   This is the constructor of a new PDF object. If the filename is
missing, it returns an empty PDF descriptor ( can be filled with
$pdf->TargetFile). Otherwise, It acts as the *PDF::Parse::TargetFile*
method.

Methods
=======

   The available methods are:

GetObject (reference)
---------------------

   This methods returns the PDF-object for reference. The string reference
must match the regular expression /^\d+ \d+ R$/, where the first number is
the object number, the second number the generation number.

   The return value is a PDF-primitive, the type depends on the content of
the object:

undef
     The object could not be found or an error. Not all referenced objects
     need to be present in a PDF-file. This value can be ignored.

*Hash Reference*
     If (UNIVERSAL::isa ($retval, "HASH") is true, the object is a
     PDF-dictionary. The keys of the hash should be either a PDF name (eg:
     /MediaBox) or a generated value like Stream_Offset. Everything else is
     an error.

     The values of the hash can be any PDF-primitive, including PDF-arrays
     and other dictionaries.

     This is the most common value returned by GetObject. If the key
     Stream_Offset exists, the dictionary is followed by stream data,
     starting at the file offeset indicated by this value.

*Array Reference*
     If (UNIVERSAL::isa ($retval, "ARRAY") is true, the object is a
     PDF-array. Each element may be of a different type, and may contain
     further references to arrays or any other PDF-primitive.

*String matching /^\d+ \d+ R$/*
     This is a reference to another PDF-Object. This value can be passed to
     GetObject. This kind of value may appear instead of most other types.
     Some PDF-writing programs seem to have special fun writing references
     when a simple number is expected. If the final number is need, use
     code like this to resolve references:

     while ($len =~ m/^\d+ \d+ R$/) {$len = $self->GetObject ($len);	}

     Example: 22 0 R

*String matching /^\//*
     This is a Name in a PDF dictionary. This string is already processed
     by *UnQuotName* and may differ from the value in the PDF-file. In
     some very old andstrange non-standard PDF-files, this may lead to
     confusion.

     Example: /MediaBox

*String matching /^\(.*\)$/*
     This is a string. It may contain newlines, quoted characters und other
     strange stuff. Use PDF::UnQuoteString to extract the text.

     Example: (This is\na string with two \(2\) lines.)

*String matching /^<.*>$/*
     This is a hex encoded string. Use PDF::UnQuoteString to extract the
     text.

     Example: <48 45 4c4C4 F1c>

*String matching /^[\d.\+\-]+$/*
     This is probably a number.

     Example: 611

*String matching none of the above*
     this is either a PDF bareword (eg. true, false, ...) or a value
     generated by this method like Stream_Offset.

     Example: true

   To improve performance GetObject uses an internal cache for objects.
Repeated requests for the same objects are not read form the file but
satisfied from the cache. With the Variable $PDF::Core::UseObjectCache,
the caching mechanism can be turned off.

   WARNING

   Special care must be taken, when returned objects are modified. If the
object contains sub-objects, the sub-objects are not duplicated and all
changes affect all other copies of this object. Use your own copy, if you
need to modify those values.

Variables
=========

   Available variables are:

$PDF::Core::VERSION
     Contains the version of the library installed

$PDF::Core::UseObjectCache
     If this variable is true, all processed objects will be added to the
     object cache. If only header information of a PDF are read or very big
     PDF are processed, turning off the cache reduces the memory usage.

Copyright
=========

     Copyright (c) 1998 - 2000 Antonio Rosella Italy antro@tiscalinet.it, Johannes Blach dw235@yahoo.com

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Availability
============

   The latest version of this library is likely to be available from:

   http://www.geocities.com/CapeCanaveral/Hangar/4794/

create PDF files
****************

NAME
====

   PDF::Create - create PDF files

SYNOPSIS
========

     use PDF::Create;

     my $pdf = new PDF::Create('filename' => 'mypdf.pdf',
     			      'Version'  => 1.2,
     			      'PageMode' => 'UseOutlines',
     			      'Author'   => 'Fabien Tassin',
     			      'Title'    => 'My title',
     			 );
     my $root = $pdf->new_page('MediaBox' => [ 0, 0, 612, 792 ]);

     # Add a page which inherits its attributes from $root
     my $page = $root->new_page;

     # Prepare 2 fonts
     my $f1 = $pdf->font('Subtype'  => 'Type1',
      	   	        'Encoding' => 'WinAnsiEncoding',
      		        'BaseFont' => 'Helvetica');
     my $f2 = $pdf->font('Subtype'  => 'Type1',
      		        'Encoding' => 'WinAnsiEncoding',
      		        'BaseFont' => 'Helvetica-Bold');

     # Prepare a Table of Content
     my $toc = $pdf->new_outline('Title' => 'Document',
                                 'Destination' => $page);
     $toc->new_outline('Title' => 'Section 1');
     my $s2 = $toc->new_outline('Title' => 'Section 2',
                                'Status' => 'closed');
     $s2->new_outline('Title' => 'Subsection 1');

     $page->stringc($f2, 40, 306, 426, "PDF::Create");
     $page->stringc($f1, 20, 306, 396, "version $PDF::Create::VERSION");

     # Add another page
     my $page2 = $root->new_page;
     $page2->line(0, 0, 612, 792);
     $page2->line(0, 792, 612, 0);

     $toc->new_outline('Title' => 'Section 3');
     $pdf->new_outline('Title' => 'Summary');

     # Add something to the first page
     $page->stringc($f1, 20, 306, 300,
                    'by Fabien Tassin <fta@oleane.net>');

     # Add the missing PDF objects and a the footer then close the file
     $pdf->close;

DESCRIPTION
===========

   PDF::Create allows you to create PDF documents using a large number of
primitives, and emit the result as a PDF file or stream.  PDF stands for
Portable Document Format.

   Documents can have several pages, a table of content, an information
section and many other PDF elements. More functionnalities will be added
as needs arise.

   Documents are constructed on the fly so the memory footprint is not
tied to the size of the pages but only to their number.

Methods
=======

new
     To create a new PDF, send a new() message to the PDF::Create class.
     For example:

          my $pdf = new PDF::Create;

     This will create an empty PDF structure. A lot of attributes can be
     used:

          - filename: destination file that will contain the resulting
            PDF or ...

          - fh: ... an already opened filehandle

          - Version: can be 1.0 to 1.3 (default: 1.2)

          - PageMode: how the document should appear when opened.
            Allowed values are:

          - UseNone: Open document with neither outline nor thumbnails
            visible. This is the default value.

          - UseOutlines: Open document with outline visible.

          - UseThumbs: Open document with thumbnails visible.

          - FullScreen: Open document in full-screen mode. In
            full-screen mode, there is no menu bar, window controls,
            nor any other window present.

          - Author: the name of the person who created this document

          - Creator: if the document was converted into a PDF document
            from another form, this is the name of the application that
            created the original document.

          - Title: the title of the document

          - Subject: the subject of the document

          - Keywords: keywords associated with the document

     Example:

          my $pdf = new PDF::Create('filename' => 'mypdf.pdf',
                                    'Version'  => 1.2,
                                    'PageMode' => 'UseOutlines',
                                    'Author'   => 'Fabien Tassin',
                                    'Title'    => 'My title',
                               );

     The created object is returned.

close
     Add the missing sections needed to obtain a complete and valid PDF
     document then close the file if needed.

`add_comment [string]'
     Add a comment to the document.

`new_outline [parameters]'
     Add an outline to the document using the given parameters.  Return
     the newly created outline.

     Parameters can be:

     - Title: the title of the outline. Mandatory.

     - Destination: the destination of this outline. In this version, it is
     only possible to give a page as destination. The default destination
     is the current page.

     - Parent: the parent of this outline in the outlines tree. This is an
     outline object.

     Example:

          my $outline = $pdf->new_outline('Title' => 'Item 1',
                                          'Destination' => $page);
          $outline->new_outline('Title' => 'Item 1.1');
          $pdf->new_outline('Title' => 'Item 1.2',
                            'Parent' => $outline);
          $pdf->new_outline('Title' => 'Item 2');

`new_page'
     Add a page to the document using the given parameters.  Return the
     newly created page.

     Parameters can be:

     - Parent: the parent of this page in the pages tree. This is a page
     object.

     - Resources: Resources required by this page.

     - MediaBox: Rectangle specifying the natural size of the page, for
     example the dimensions of an A4 sheet of paper. The coordinates are
     measured in default user space units. It must be the reference of a 4
     values array.

     - CropBox: Rectangle specifying the default clipping region for the
     page when displayed or printed. The default is the value of the
     MediaBox.

     - ArtBox: Rectangle specifying an area of the page to be used when
     placing PDF content into another application. The default is the value
     of the CropBox. [PDF 1.3]

     - TrimBox: Rectangle specifying the intended finished size of the
     page (for example, the dimensions of an A4 sheet of paper).  In some
     cases, the MediaBox will be a larger rectangle, which includes
     printing instructions, cut marks, or other content. The default is
     the value of the CropBox. [PDF 1.3].

     - BleedBox: Rectangle specifying the region to which all page content
     should be clipped if the page is being output in a production
     environment. In such environments, a bleed area is desired, to
     accommodate physical limitations of cutting, folding, and trimming
     equipment. The actual printed page may include printer's marks that
     fall outside the bleed box. The default is the value of the CropBox.
     [PDF 1.3]

     - Rotate: Specifies the number of degrees the page should be rotated
     clockwise when it is displayed or printed. This value must be zero
     (the default) or a multiple of 90.

font
     Prepare a font using the given arguments. This font will be added to
     the document only if it is used at least once before the close method
     is called.

     Parameters can be:

     - Subtype: Type of font. PDF defines some types of fonts. It must be
     one of the predefined type Type1, Type3, TrueType or Type0.

     In this version, only Type1 is supported. This is the default value.

     - Encoding: Specifies the encoding from which the new encoding
     differs.  It must be one of the predefined encodings MacRomanEncoding,
     MacExpertEncoding or WinAnsiEncoding.

     In this version, only WinAnsiEncoding is supported. This is the
     default value.

     - BaseFont: The PostScript name of the font. It can be one of the
     following base font: Courier, Courier-Bold, Courier-BoldOblique,
     Courier-Oblique, Helvetica, Helvetica-Bold, Helvetica-BoldOblique,
     Helvetica-Oblique, Times-Roman, Times-Bold, Times-Italic,
     Times-BoldItalic, Symbol or ZapfDingbats. All of them are supported
     in this version except the last two ones.

     The default value is Helvetica.

Page methods
------------

   This section describes the methods that can be used by a
PDF::Create::Page object.

   In its current form, this class is divided into two main parts, one for
drawing (using PostScript like paths) and one for writing.

   Some methods are not described here because they must not be called
directly (e.g. new and add).

`new_page params'
     Add a sub-page to the current page.

     See `PDF::Create::new_page'

`string font size x y text'
     Add text to the current page using the font object at the given size
     and position. The point (x, y) is the bottom left corner of the
     rectangle containing the text.

     Example :

          my $f1 = $pdf->font('Subtype'  => 'Type1',
           	   	        'Encoding' => 'WinAnsiEncoding',
           		        'BaseFont' => 'Helvetica');
          $page->string($f1, 20, 306, 396, "some text");

`stringl font size x y text'
     Same as string.

`stringr font size x y text'
     Same as string but right aligned.

`stringc font size x y text'
     Same as string but centered.

`string_width font text'
     Return the size of the text using the given font in default user
     space units.  This does not contain the size of the font yet.

`line x1 y1 x2 y2'
     Draw a line between (x1, y1) and (x2, y2).

Low level drawing methods
-------------------------

`moveto x y'
     Moves the current point to (x, y), omitting any connecting line
     segment.

`lineto x y'
     Appends a straight line segment from the current point to (x, y).
     The current point is (x, y).

`curveto x1 y1 x2 y2 x3 y3'
     Appends a Bezier curve to the path. The curve extends from the current
     point to (x3 ,y3) using (x1 ,y1) and (x2 ,y2) as the Bezier control
     points. The new current point is (x3 ,y3).

`rectangle x y w h'
     Adds a rectangle to the current path.

`closepath'
     Closes the current subpath by appending a straight line segment from
     the current point to the starting point of the subpath.

`newpath'
     Ends the path without filling or stroking it.

`stroke'
     Strokes the path.

`closestroke'
     Closes and strokes the path.

fill
     Fills the path using the non-zero winding number rule.

`fill2'
     Fills the path using the even-odd rule

SEE ALSO
========

   `PDF::Create::Page(3)' in this node, `perl(1)' in this node

AUTHOR
======

   Fabien Tassin (fta@oleane.net)

COPYRIGHT
=========

   Copyright 1999, Fabien Tassin. All rights reserved.  It may be used and
modified freely, but I do request that this copyright notice remain
attached to the file. You may modify this module as you wish, but if you
redistribute a modified version, please attach a note listing the
modifications you have made.

Routines to produce formatted pages of mailing labels in PDF
************************************************************

NAME
====

   PDF::Labels - Routines to produce formatted pages of mailing labels in
PDF

SYNOPSIS
========

     use PDF::Labels;

     Requires: PDF::Create

DESCRIPTION
===========

GENERAL
-------

   Provides package PDF::Labels

   Package Global Variables:

     @PDF::Labels:PageFormats is a list of known page formats.  Each
     page format is a : delimited list of fields which provide the
     following properties about a page of labels:

     pagewidth	Width of actual page in inches
     pageheight	Height of actual page in inches
     pagexoffset	Offset from left edge of page to left
     		edge of first column of labels in inches
     pageyoffset	Offset from bottom edge of page to
     		bottom edge of lowest row of labels
     xlabels		Number of labels in each row
     ylabels		Number of labels in each column
     labelwidth	Width of each label in inches, including
     		margin
     labelheight	Height of each label in inches, including
     		margin
     labelxmar	Minimum Distance to offset printing from
     		left and right edges of label
     labelymar	Minimum distance to offset printing from
     		top and bottom edges of label
     fontsize	Size of font to use with this label
     linespacing	Line spacing (points) to use with this
     		label

SYNTAX
------

     Example

     use PDF::Create;
     use PDF::Labels;

     $pdf = new PDF::Labels(
     		$PDF::Labels::PageFormats[0],
     			filename=>'labels.pdf',
     			Author=>'PDF Labelmaker',
     			Title=>'My Labels'
     	);

     $pdf->setlabel(5);	# Start with label 5 on first page

     $pdf->label('John Doe', '1234 Some Street',
     		'Anytown, ID', '12345');
     $pdf->label('Jane Doe', '5493 Other Drive',
     		'Nowhere, CA', '92213');
     $pdf->label('Bob Smith', '392 Cedar Lane',
     		'Deep Shit, AR', '72134');

     $pdf->close();

     The above example will produce 3 labels on an 8.5x11 sheet with
     three labels in a row and 10 rows of labels.  The labels are
     2.625"x1".  This is a common sheet-feed label.  In this case, the
     three labels will be the last label of the second row and the
     first two labels of the third row.  The labels can be moved by
     changing the parameter to the setlabel call.

     Creation

     $pdf = new PDF::Labels(
     		$PageFormat,
     		PDF::Create parameters
     	)

     $PageFormat is a string containing a single element of PageFormats
     or a custom page format specification in the same format.

     PDF::Create parameters are described in the PDF::Create pod.

     Setup

     $pdf->setlabel(n)

     n is a number from 0 to maxlabels.  Subsequent calls to create
     labels will create labels starting from this position on the
     page.  Position 0 is the upper left label, working across each
     row down in columns.

     i.e.	0 1 2
     	3 4 5
     	6 7 8
     	...

     Setlabel will not go backwards.  If n is less than the current
     cursor position, a new page will be created.

     Label Creation

     $pdf->label('string1', 'string2', 'string3'[, 'string4'...])

     As much of each string as possible will be placed on a seperate
     line of the label.  If there are more strings than the label can
     hold, extra strings will not be printed.

     @(#) Labels.pm Last updated 01/02/10 18:59:54 (SCCS Version 1.8)

AUTHOR
======

   Owen DeLong, owen@delong.com

Library for parsing the PDF tree structure in Perl
**************************************************

NAME
====

   PDF::Pages - Library for parsing the PDF tree structure in Perl

SYNOPSIS
========

     use PDF ;
     use PDF::Pages ;

     $pdf_pages=PDF::Pages->new;
     $pdf_pages->ReadPageTree($pdf_struct);;

DESCRIPTION
===========

   This is a part of the more general PDF library. In this section you
will find the functions related to the page tree of a PDF file.

Constructor
===========

* new *
          This is the constructor of a new PDF tree object. It returns an
          empty PDF Page tree descriptor ( can be filled with <B ReadPageTree> ).

Methods
=======

   The available methods are :

*ReadPageTree ( pdf_struct ) *
     This method reads the information contained in the root of the page
     tree of the argument PDF document.

Copyright
=========

     Copyright 1998, Antonio Rosella antro@technologist.com

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Availability
============

   The latest version of this library is available from:

   http://www.geocities.com/CapeCanaveral/Hangar/4794/

   and from CPAN .

Library with parsing functions for PDF library
**********************************************

NAME
====

   PDF::Parse - Library with parsing functions for PDF library

SYNOPSIS
========

     use PDF::Parse;

     $pdf->TargetFile($filename);
     $pdf->LoadPageInfo;

     $version = $pdf->Version;
     $bool = $pdf->IsaPDF;
     $bool = $pdf->IscryptPDF;

     $info = $pdf->GetInfo ($key);
     $pagenum = $pdf->Pages;

     @size = $pdf->PageSize ($page);
     # or
     @size = $pdf->PageSize;

     $rotation = $pdf->PageRotation ($page);
     # or
     $rotation = $pdf->PageRotation;

DESCRIPTION
===========

   The main purpose of the PDF::Parse library is to provide parsing
functions for the more general PDF library.

Methods
=======

   The available methods are:

TargetFile ( filename )
-----------------------

   This method links the filename to the pdf descriptor and parses all
kind of header information.

LoadPageInfo
------------

   This function loads the information for all pages. This process can
take some time for big PDF-files.

Version
-------

   Returns the PDF version used for writing the object file.

IsaPDF
------

   Returns true, if the file could be parsed and is a PDF-file.

IscryptPDF
----------

   Returns true if the PDF contains a crypt object. This indicates that
the data of the PDF-File is encrypted. In this case, not all function work
as expected.

GetInfo ( key )
---------------

   Returns the various information contained in the info section of a PDF
file (if present). A PDF file can have:

     a title ==> GetInfo ("Title")
     a subject ==> GetInfo ("Subject")
     an author ==> GetInfo("Author")
     a creation date ==> GetInfo("CreationDate")
     a creator ==> GetInfo("Creator")
     a producer ==> GetInfo("Producer")
     a modification date ==> GetInfo("ModDate")
     some keywords ==> GetInfo("Keywords")

Pages
-----

   Returns the number of pages of the PDF-file.

PageSize ( [ page ] )
---------------------

   Returns the size of a page in the PDF-file. If no parameter is given,
the default size of the root page will be returned. This value may be
overridden for any page.

   If the size of an individual page is requested and the page data is not
already loaded, the method LoadPageInfo will be executed. This may take
some time for large PDF-files. The size of the root page is always
available and will never execute LoadPageInfo.

PageRotation ( [ page ] )
-------------------------

   Returns the rotation of a page in the PDF-file. If no parameter is
given, the default rotation of the root page will be returned. This value
may be overridden for any page.

   If the rotation of an individual page is requested and the page data is
not already loaded, the method LoadPageInfo will be executed. This may
take some time for large PDF-files. The rotation of the root page is
always available and will never execute LoadPageInfo.

Variables
=========

   The only available variable is :

$PDF::Parse::VERSION
     Contains the version of the library installed

Copyright
=========

     Copyright (c) 1998 - 2000 Antonio Rosella Italy antro@tiscalinet.it, Johannes Blach dw235@yahoo.com

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Availability
============

   The latest version of this library is likely to be available from:

   http://www.geocities.com/CapeCanaveral/Hangar/4794/

Main loader of PDL default modules
**********************************

NAME
====

   PDL - Main loader of PDL default modules

DESCRIPTION
===========

   Loads the default set of modules associated with PDL, making the
functions available in the current namespace. See also
`PDL::Lite|PDL::Lite' in this node or `PDL::LiteF|PDL::LiteF' in this node
if start-up time becomes an issue.

SYNOPSIS
========

     use PDL; # Is equivalent to the following:

     use PDL::Core;
     use PDL::Ops;
     use PDL::Primitive;
     use PDL::Ufunc;
     use PDL::Basic;
     use PDL::Slices;
     use PDL::Bad;
     use PDL::Version;
     use PDL::IO::Misc;

Some PDL functions intended for audio processing.
*************************************************

NAME
====

   PDL::Audio - Some PDL functions intended for audio processing.

SYNOPSIS
========

     use PDL::Audio;

DESCRIPTION
===========

   Oh well ;) Not much written yet! See my other modules for even worse
documentation ;)

NOTATION
--------

   Brackets around parameters indicate that the respective parameter is
optional and will be replaced with some default value when absent (or
undef, which might be different in other packages).

   The sampling frequency and duration are by default (see individual
descriptions) given in cycles/sample (or samples in case of a duration).
That means if you want to specify a duration of two seconds, you have to
multiply by the sampling frequency in HZ, and if you want to specify a
frequency of 440 Hz, you have to divide by the sampling frequency:

     # Syntax: gen_oscil duration*, frequency/
     $signal = gen_oscil 2*HZ, 440/HZ;
     # with a sampling frequency of 44100 Hertz:
     $signal = gen_oscil 2*44100, 440/44100;

   To help you, the required unit is given as a type suffix in the
parameter name. A "/" means that you have to divide by the sampling
frequency (to convert from Hertz) and a suffix of "*" indicates that a
multiplication is required.

   Most parameters named "size", "duration" (or marked with "*") can be
replaced by a piddle, which is then used to give length and from
(mono/stereo).

HEADER ATTRIBUTES
-----------------

   The following header attributes are stored and evaluated by most
functions. PDL::Audio provides mutator methods for all them (e.g.

   print "samplerate is ", $pdl->rate;  $pdl->comment("set the comment to
this string");

rate
     The sampling rate in hz.

filetype
     The filetype (wav, au etc..). Must be one of:

          FILE_NEXT FILE_AIFC FILE_RIFF FILE_BICSF FILE_NIST FILE_INRS FILE_ESPS
          FILE_SVX FILE_VOC FILE_SNDT FILE_RAW FILE_SMP FILE_SD2 FILE_AVR
          FILE_IRCAM FILE_SD1 FILE_SPPACK FILE_MUS10 FILE_HCOM FILE_PSION
          FILE_MAUD FILE_IEEE FILE_DESKMATE FILE_DESKMATE_2500 FILE_MATLAB
          FILE_ADC FILE_SOUNDEDIT FILE_SOUNDEDIT_16 FILE_DVSM FILE_MIDI
          FILE_ESIGNAL FILE_SOUNDFONT FILE_GRAVIS FILE_COMDISCO FILE_GOLDWAVE
          FILE_SRFS FILE_MIDI_SAMPLE_DUMP FILE_DIAMONDWARE FILE_REALAUDIO
          FILE_ADF FILE_SBSTUDIOII FILE_DELUSION FILE_FARANDOLE FILE_SAMPLE_DUMP
          FILE_ULTRATRACKER FILE_YAMAHA_SY85 FILE_YAMAHA_TX16 FILE_DIGIPLAYER
          FILE_COVOX FILE_SPL FILE_AVI FILE_OMF FILE_QUICKTIME FILE_ASF
          FILE_YAMAHA_SY99 FILE_KURZWEIL_2000 FILE_AIFF FILE_AU

path
     The filename (or file specification) used to load or save a file.

format
     Specifies the type the underlying file format uses. The samples will
     always be in short or long signed format.

     Must be one of

          FORMAT_NO_SND FORMAT_16_LINEAR FORMAT_8_MULAW FORMAT_8_LINEAR
          FORMAT_32_FLOAT FORMAT_32_LINEAR FORMAT_8_ALAW FORMAT_8_UNSIGNED
          FORMAT_24_LINEAR FORMAT_64_DOUBLE FORMAT_16_LINEAR_LITTLE_ENDIAN
          FORMAT_32_LINEAR_LITTLE_ENDIAN FORMAT_32_FLOAT_LITTLE_ENDIAN
          FORMAT_64_DOUBLE_LITTLE_ENDIAN FORMAT_16_UNSIGNED
          FORMAT_16_UNSIGNED_LITTLE_ENDIAN FORMAT_24_LINEAR_LITTLE_ENDIAN
          FORMAT_32_VAX_FLOAT FORMAT_12_LINEAR FORMAT_12_LINEAR_LITTLE_ENDIAN
          FORMAT_12_UNSIGNED FORMAT_12_UNSIGNED_LITTLE_ENDIAN COMPATIBLE_FORMAT

     PDL::Audio conviniently defines the following aliases for the
     following constants, that are already correct for the host byteorder:

          FORMAT_ULAW_BYTE FORMAT_ALAW_BYTE FORMAT_LINEAR_BYTE
          FORMAT_LINEAR_SHORT FORMAT_LINEAR_USHORT FORMAT_LINEAR_LONG
          FORMAT_LINEAR_FLOAT FORMAT_LINEAR_DOUBLE

comment
     The file comment (if any).

device
     The device to output audio. One of:

          DEV_DEFAULT DEV_READ_WRITE DEV_ADAT_IN DEV_AES_IN DEV_LINE_OUT
          DEV_LINE_IN DEV_MICROPHONE DEV_SPEAKERS DEV_DIGITAL_IN DEV_DIGITAL_OUT
          DEV_DAC_OUT DEV_ADAT_OUT DEV_AES_OUT DEV_DAC_FILTER DEV_MIXER
          DEV_LINE1 DEV_LINE2 DEV_LINE3 DEV_AUX_INPUT DEV_CD_IN DEV_AUX_OUTPUT
          DEV_SPDIF_IN DEV_SPDIF_OUT

          =back

EXPORTED CONSTANTS
------------------

   In addition to the exported constants described above (and later in the
function descriptions), this module also exports the mathematical
constants M_PI and M_2PI, so watch out for clashes!

FUNCTIONS
=========

sound_format_name format_code
-----------------------------

   Return the human-readable name of the file format with code
`format_code'.

sound_type_name type_code
-------------------------

   Return the human-readable name of the sample type with code `type_code'.

describe_audio piddle
---------------------

   Describe the audio stream contained in piddle and return it as a
string. A fresh piddle might return:

     mono sound with 27411 samples

   Whereas a freshly loaded soundfile might yield:

     stereo sound with 27411 samples, original name "kongas.wav", type 2 (RIFF),
     rate 11025/s (duration 2.49s), format 7 (8-bit unsigned)

raudio path, [option-hash], option => value, ...
------------------------------------------------

   Reads audio data into the piddle. Options can be anything, most useful
values are filetype, rate, channels and format.

     # read any file
     $pdl = raudio "file.wav";
     # read a file. if it is a raw file preset values
     $pdl = raudio "file.raw", filetype => FILE_RAW, rate => 44100, channels => 2;

waudio pdl, [option-hash], option => value, ...
-----------------------------------------------

   Writes a pdl as a file. The path is taken from the header (or the
options), e.g.:

     # write a file, using the header of another piddle
     $pdl->waudio($orig_file->gethdr);
     # write pdl as au file, take rate from the header
     $pdl->waudio(path => "piddle.au", filetype => FILE_AU, format => FORMAT_16_LINEAR;

cut_leading_silence pdl, level
------------------------------

   Cuts the leading silence (i.e. all samples with absolute value < level)
and returns the resulting part.

cut_trailing_silence pdl, level
-------------------------------

   Cuts the trailing silence.

cut_silence pdl, level
----------------------

   Calls `cut_leading_silence' and `cut_trailing_silence' and returns the
result.

playaudio pdl, [option-hash], option => value ...
-------------------------------------------------

   Play the piddle as an audio file. Options can be supplied either
through the option hash (a hash-reference), through the pdl header or the
options:

     # play a piddle that has a valid header (e.g. from raudio)
     $pdl->playaudio;
     # play it with a different samplerate
     $pdl->playaudio(rate => 22050);

ulaw2linear
-----------

linear2ulaw
-----------

alaw2linear
-----------

linear2alaw
-----------

gen_oscil duration*, freq/, phase-mod, [fm-mod/]
------------------------------------------------

gen_sawtooth duration*, freq/, phase-mod, [fm-mod/]
---------------------------------------------------

gen_square duration*, freq/, phase-mod, [fm-mod/]
-------------------------------------------------

gen_triangle duration*, freq/, phase-mod, [fm-mod/]
---------------------------------------------------

gen_pulse_train duration*, freq/, phase-mod, [fm-mod/]
------------------------------------------------------

gen_rand duration*, freq/
-------------------------

gen_rand_1f duration*
---------------------

   All of these functions generate appropriate waveforms with frequency
`freq' (cycles/sample) and phase `phase' (0..1).

   The `duration' might be either a piddle (which gives the form of the
output) or the number of samples to generate.

   The output samples are between -1 and +1 (i.e. "-1 <= s <= +1").

gen_env duration*, xvals, yvals, [base]
---------------------------------------

   Generates an interpolated envelope between the points given by xvals and
yvals.  When base == 1 (the default) then the values will be linearly
interpolated, otherwise they follow an exponential curve that is bend
inwards (base < 1) or outwards (base > 1).

     # generate a linear envelope with attack in the first 10%
     gen_env 5000, [0 1 2 9 10], [0 1 0.6 0.6 0];

gen_asymmetric_fm duration*, freq/, phase, [r , [ratio]]
--------------------------------------------------------

   `gen_asymmetric_fm' provides a way around the symmetric spectra normally
produced by FM. See Palamin and Palamin, "A Method of Generating and
Controlling Asymmetrical Spectra" JAES vol 36, no 9, Sept 88, p671-685.

gen_sum_of_cosines duration*, freq/, phase, ncosines, [fm_mod/]
---------------------------------------------------------------

   Generates a sum of n cosines `(1 + 2(cos(x) + cos(2x) + ... cos(nx)) =
sin((n+.5)x) / sin(x/2))'. Other arguments are similar to to `gen_oscil'.

gen_sine_summation duration*, freq/, phase, [nsines, [a, [b_ratio, [fm_mod/]]]]
-------------------------------------------------------------------------------

   `gen_sine_summation' provides a kind of additive synthesis. See
J.A.Moorer, "Signal Processing Aspects of Computer Music" and "The
Synthesis of Complex Audio Spectra by means of Discrete Summation
Formulae" (Stan-M-5). The basic idea is very similar to that used in
gen_sum_of_cosines generator.

   The default value for `nsines' is 1 (but zero is a valid value), for a
is 0.5 and for `b_ratio' is 1.

   (btw, either my formula is broken or the output indeed does not lie
between -1 and +1, but rather -5 .. +5).

gen_from_table duration*, frequency/, table, [phase], [fm_mod/]
---------------------------------------------------------------

   `gen_from_table' generates a waveform by repeating a waveform given in
table, linearly interpolating between successive points of the `waveform'.

partials2waveshape size*, partials, amplitudes, [phase], [fm_mod/]
------------------------------------------------------------------

   Take a list (perl list or pdl) of (integer) `partials' and a list of
`amplitudes' and generate a single wave shape that results by adding these
partial sines.

   This could (and should) be used by the `gen_from_table' generator.

gen_from_partials duration*, frequency/, partials, amplitudes, [phase], [fm_mod/]
---------------------------------------------------------------------------------

   Take a list (perl list or pdl) of (possibly noninteger) `partials' and a
list of `amplitudes' and generate the waveform resulting by summing up all
these partial sines.

filter_one_zero
---------------

filter_one_pole
---------------

filter_two_zero
---------------

filter_two_pole
---------------

filter_formant
--------------

filter_ppolar pdl, radius/, frequency/
--------------------------------------

   apply a two pole filter (given in polar form). The filter has two poles,
one at (radius,frequency), the other at (radius,-frequency). Radius is
between 0 and 1 (but less than 1), and frequency is between 0 and 0.5.
This is the standard resonator form with poles specified by the polar
coordinates of one pole.

filter_zpolar pdl, radius/, frequency/
--------------------------------------

   apply a two zero filter (given in polar form). See `filter_ppolar'.

partials2polynomial partials, [kind]
------------------------------------

   `partials2polynomial' takes a list of harmonic amplitudes and returns a
list of Chebychev polynomial coefficients. The argument `kind' determines
which kind of Chebychev polynomial we are interested in, 1st kind or 2nd
kind. (default is 1).

ring_modulate in1, in2
----------------------

   ring modulates in1 with in2 (this is just a multiply).

amplitude_modulate am_carrier, in1, in2
---------------------------------------

   amplitude modulates am_carrier and in2 with in1 (this calculates in1 *
(am_carrier + in2)).

filter_sir
----------

   Generic (short delay) impulse response filter. x is the input signal
(which is supposed to be zero for negative indices). a contains the input
(x) coefficients (a0, a1, .. an), whereas b contains the output (y)
coefficients (b0, b1, ... bn), i.e.:

     y(n) = a0 x(n) - b1 y(n-1) + a1 x(n-1) - b2 y(n-2) + a2 x(n-2) - b3 ...

   This can be used to generate fir and iir filters of any length, or even
more complicated constructs.

   `b0' (then first element of b) is being ignored currently AND SHOULD BE
SPECIFIED AS ONE FOR FUTURE COMPATIBILITY

filter_lir
----------

   Generic (long delay) impulse response filter. The difference to
filter_sir is that the filter coefficients need not be consecutive, but
instead their indices are given by the `a_x' and `b_x' (integer) vectors,
while the corresponding coefficients are in `a_y' and `b_y'. (All `a_x'
must be >= 0, while all the `b_x' must be >= 1, as you should expect).

   See filter_sir for more info.

filter_fir input, xcoeffs
-------------------------

   Apply a fir (finite impulse response) filter to input. This is the same
as calling:

     filter_sir input, xcoeffs, pdl()

filter_iir input, ycoeffs
-------------------------

   Apply a iir (infinite impulse response) filter to input. This is just
another way of saying:

     filter_sir input, pdl(1), ycoeffs

   That is, the first member of `ycoeffs' is being ignored AND SHOULD BE
SPECIFIED AS ONE FOR FUTURE COMPATIBILITY!

filter_comb input, delay*, scaler
---------------------------------

   Apply a comb filter to the piddle input. This is implemented using a
delay line with length delay (which must be 1 or larger and can be
non-integer) and a feedback scaler.

     y(n) = x(n-size-1) + scaler * y(n-size)

   See also `filter_notch'.

filter_notch input, delay*, scaler
----------------------------------

   Apply a comb filter to the piddle input. This is implemented using a
delay line with length delay (which must be 1 or larger and can be
non-integer) and a feedforward scaler.

     y(n) = x(n-size-1) * scaler + y(n-size)

   As a rule of thumb, the decay time of the feedback part is
`7*delay/(1-scaler)' samples, so to get a decay of Dur seconds, `scaler <=
1-7*delay/(Dur*Srate)'. The peak gain is `1/(1-(abs scaler))'. The peaks
(or valleys in notch's case) are evenly spaced at `srate/delay'. The
height (or depth) thereof is determined by scaler - the closer to 1.0, the
more pronounced. See Julius Smith's "An Introduction to Digital Filter
Theory" in Strawn "Digital Audio Signal Processing", or Smith's "Music
Applications of Digital Waveguides"

filter_allpass input, delay*, scaler-feedback, scaler-feedforward
-----------------------------------------------------------------

   `filter_allpass' or "moving average comb" is just like `filter_comb'
but with an added feedforward term. If `scaler-feedback == 0', we get a
moving average comb filter. If both scaler terms == 0, we get a pure delay
line.

     y(n) = feedforward*x(n-1) + x(n-size-1) + feedback*y(n-size)

design_remez_fir filter_size, bands(2,b), desired_gain(b), type, [weight(b)]         Calculates the optimal (in the Chebyshev/minimax sense) FIR filter impulse response given a set of band edges, the desired reponse on those bands, and the weight given to the error in those bands, using the Parks-McClellan exchange algorithm.
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

   The first argument (the one with the funny name) sets the filter size:
`design_remez_fir' returns as many coefficients as specified via this
parameter.

   `bands' is a vector of band edge pairs (start - end), who specify the
start and end of the bands in the filter specification.  These must be
non-overlapping and sorted in increasing order. Only values between 0 (0
Hz) and `0.5' (the Nyquist frequency) are allowed.

   `des' specifies the desired gain in these bands.

   weight can be used to give each band a different weight. If absent, a
vector of ones is used.

   type is any of the exported constants `BANDPASS', `DIFFERENTIATOR' or
`HILBERT' and can be used to select various design types (use `BANDPASS'
until this is documented ;)

filter_src input, srate, [width], [sr-mod]
------------------------------------------

   Generic sampling rate conversion, implemented by convoluting input with
a sinc function of size width (default when unspecified or zero: 5).

   `srate' determines the input rate / output rate ratio, i.e. values > 1
speed up, values < 1 slow down. Values < 0 are allowed and reverse the
signal.

   If `sr_mod' is omitted, the size of the output piddle is calculcated as
`length(input)/abs(srate)', e.g. it provides the full stretched or
shrinked input signal.

   If `sr_mod' is specified it must be as large as the desired output, i.e.
it's size determines the output size. Each value in `sr_mod' is added to
`srate' at the given point in "time", so it can be used to "modulate" the
sampling rate change.

     # create a sound effect in the style of "Forbidden Planet"
     $osc = 0.3 * gen_oscil $osc, 30 / $pdl->rate;
     $output = filter_src($input, 1, 0, $osc);

filter_contrast_enhance input, enhancement
------------------------------------------

   Contrast-enhancement phase-modulates a sound file. It's like audio MSG.
The actual algorithm is (applied to the normalised sound normalized)
`sin(input*pi/2 + (enhancement*sin(input*2*pi)))'. The result is to
brighten the sound, helping it cut through a huge mix.

filter_granulate input, expansion, [option-hash], option => value...
--------------------------------------------------------------------

   `filter_granulate' "granulates" the sound file file. It is the poor
man's way to change the speed at which things happen in a recorded sound
without changing the pitches. It works by slicing the input file into
short pieces, then overlapping these slices to lengthen (or shorten) the
result; this process is sometimes known as granular synthesis, and is
similar to the "freeze" function. The duration of each slice is length -
the longer, the more like reverb the effect. The portion of the length (on
a scale from 0 to 1.0) spent on each ramp (up or down) is `ramp'. This can
control the smoothness of the result of the overlaps. The more-or-less
average time between successive segments is `hop'.  The accuracy at which
we handle this hopping is set by the float `jitter' - if `jitter' is very
small, you may get an annoying tremolo. The overall amplitude scaler on
each segment is `scaler' - this is used to try to to avoid overflows as we
add all these zillions of segments together. `expansion' determines the
input hop in relation to the output hop; an expansion-amount of 2.0 should
more or less double the length of the original, whereas an expansion-amount
of `1.0' should return something close to the original speed.

   The defaults for the arguments/options are:

     expansion	1.0
     length(*)	0.15
     scaler		0.6
     hop(*)		0.05
     ramp		0.4
     jitter(*)	0.5
     maxsize	infinity

   The parameters/options marked with (*) actually depend on the sampling
rate, and are always multiplied by the rate attribute of the piddle
internally. If the piddle lacks that attribute, 44100 is assumed. NOTE:
This is different to most other filters, but should be ok since
`filter_granulate' only makes sense for audiofiles.

audiomix pos1, data1, pos2, data2, ...
--------------------------------------

   Generate a mix of all given piddles. The resulting piddle will contain
the sum of all data-piddles at their respective positions, so some scaling
will be necessary before or after the mixing operation (e.g. scale2short).

     # mix the sound gong1 at position 0, the sound bass5 at position 22100
     # and gong2 at position 44100. The resulting piddle will be large enough
     # to accomodate all the sounds:
     $mix = audiomix 0, $gong1, 44100, $gong2, 22100,  $gong2

filter_center piddle
--------------------

   Normalize the piddle so that it is centered around `y = 0' and has
maximal amplitude of 1.

scale2short piddle
------------------

   This method takes a sound in any format (preferably float or double) and
scales it to fit into a signed short value, suitable for playback using
`playudio' or similar functions.

gen_fft_window size*, type, [$beta]
-----------------------------------

   Creates and returns a specific fft window. The type is any of the
following.  These are (case-insensitive) strings, so you might need to
quote them.

     RECTANGULAR	just ones (the identity window)
     HANNING        0.50 - 0.50 * cos (0 .. 2pi)
     HAMMING	0.54 - 0.46 * cos (0 .. 2pi)
     WELCH		1 - (-1 .. 1) ** 2
     PARZEN		the triangle window
     BARTLETT	the symmetric triangle window
     BLACKMAN2	blackman-harris window of order 2
     BLACKMAN3	blackman-harris window of order 3
     BLACKMAN4	blackman-harris window of order 4
     EXPONENTIAL	the exponential window
     KAISER		the kaiser/bessel window (using the parameter C<beta>)
     CAUCHY		the cauchy window (using the parameter <beta>)
     POISSON	the poisson window (exponential using parameter C<beta>)
     RIEMANN	the riemann window (sinc)
     GAUSSIAN	the gaussian window of order C<beta>)
     TUKEY		the tukey window (C<beta> specifies how much of the window
     		consists of ones).
     COSCOS		the cosine-squared window (a partition of unity)
     SINC 		same as RIEMANN
     HANN		same as HANNING (his name was Hann, not Hannning)

     LIST		this "type" is special in that it returns a list of all types

cplx(2,n) = rfft real(n)
------------------------

   Do a (complex fft) of real (extended to complex so that the imaginary
part is zero), and return the complex fft result. This function tries to
use `PDL::FFTW|PDL::FFTW' in this node (which is faster for large vectors)
when available, and falls back to `PDL::FFT|PDL::FFT' in this node, which
is likely to return different phase signs (due to different kernel
functions), so beware! In fact, since `rfft' has to shuffle the data when
using PDL::FFT, the fallback is always slower.

   When using PDL::FFTW, a wisdom file ~/.pdl_wisdom is used and updated,
if possible.

real(n) = irfft cplx(2,n)
-------------------------

   The inverse transformation (see `rfft'). `irfft rfft $pdl == $pdl'
always holds.

spectrum data, [norm], [window], [beta]
---------------------------------------

   Returns the spectrum of a given pdl. If norm is absent (or undef), it
returns the magnitude of the fft of data. When norm == 1 (or `eq 'NORM'',
in any case), it returns the magnitude, normalized to be between zero and
one. If norm == 0 (or `eq 'dB'', in any case), then it returns the
magnitude in dB.

   data is multiplied with window (if not undef) before calculating the
fft, and usually contains a window created with `gen_fft_window' (using
`beta'). If window is a string, it is handed over to `gen_fft_window'
(together with the beta parameter) to create a window of suitable size.

   This function could be slightly faster.

filter_convolve
---------------

rshift
------

   Positive values shift right, negative values shift left.

polynomial
----------

Cpolynomial
-----------

linear_interpolate
------------------

   Look up the ordinate x in the function given by `fx' and `fy' and
return a linearly interpolated value (somewhat optimized for many lookups).

   `fx' specifies the ordinates (x-coordinates) of the function and most be
sorted in increasing order. `fy' are the y-coordinates of the function in
these points.

bessi0
------

real2cplx
---------

fast_sin
--------

Cr2p
----

Cp2r
----

AUTHOR
======

   Marc Lehmann <pcg@goof.com>. The ideas were mostly taken from common
lisp music (CLM), by Bill Schottstaedt `bil@ccrma.stanford.edu'. I also
borrowed many explanations (and references) from the clm docs and some
code from clm.c. Highly inspiring!

SEE ALSO
========

   perl(1), see PDL.

All the standard musical pitch names.
*************************************

NAME
====

   PDL::Audio::Pitches - All the standard musical pitch names.

SYNOPSIS
========

     use PDL::Audio::Pitches;

     print a4;  # prints 440
     print bs3; # prints 261.63

DESCRIPTION
===========

   This module defines (and exports by default(!)) all standard pitch
names:

   `cdefgab' with trailing octave, e.g. a4, `g3', `c0', `a8', `interleaved
"f" and "s", e.g. as4', `bf3', `fs6'.

AUTHOR
======

   Marc Lehmann <pcg@goof.com>

SEE ALSO
========

   perl(1), see PDL, PDL/Audio.

Over 1200 musical scales in PDL format.
***************************************

NAME
====

   PDL::Audio::Scales - Over 1200 musical scales in PDL format.

SYNOPSIS
========

     use PDL::Audio::Scales;

     @names = scale_list;

     # returns [1 1 1.5 5 7 8 8.5 1.2]
     $scale = get_scale 'arist_chromrej';

     ($scale, $desc) = get_scale 'arist_chromrej';
     # sets $desc to "Aristoxenos Rejected Chromatic, 6 + 3 + 21 parts 7"

EXAMPLE
=======

   The following script will play all the scales (unmodified, it will run
for hours) :)

     use PDL::Audio;
     use PDL::Audio::Scales;

     sub osc {
        my ($dur,$freq) = @_;
        (gen_asymmetric_fm $dur, $freq, 0.9, 0.6)*
        (gen_env $dur, [0, 1, 2, 9, 10], [0, 1, 0.6, 0.3, 0]);
     }

     for (scale_list) {
        my ($scale, $desc) = get_scale($_);
        my @mix;
        my $i;
        print "$_ [$desc] $scale\n";
        my $l = $scale->list;
        for (($scale*880)->list) {
           push @mix, ($i*0.2*44100    , osc 0.3*44100, $_/44100);
           push @mix, ($l*0.2*44100+0.1, osc 0.8*44100, $_/44100);
           $i++;
        }
        (audiomix @mix)->scale2short->playaudio;
     }

AUTHOR
======

   This file was translated from clm-2/scales.cl (common lisp music). the
original comments are:

     ;;; This file contains more than 1100 musical scales, each one
     ;;; a separate list variable, containing notes as cents or ratios.
     ;;; The first note of 1/1 or 0.0 cents is implied.  The data was
     ;;; translated from ftp://ftp.cs.ruu.nl/pub/MIDI/DOC/scales.zip
     ;;; (a collection of around 1100 files) by Bill Schottstaedt
     ;;; 24-Aug-95.
     ;;;
     ;;; These scales were brought together mostly by John Chalmers
     ;;; (non12@cyber.net) and Manuel Op de Coul (coul@ezh.nl).
     ;;;
     ;;; The reference for the Greek scales in this archive is:
     ;;; John H. Chalmers: Divisions of the Tetrachord, 1993.
     ;;; Frog Peak, Box 1052, Lebanon NH 03766, USA.
     ;;;
     ;;; If you know of scales not in this archive please send them to
     ;;; Manuel Op de Coul (coul@ezh.nl).

     ;;; since doing this translation, another 100 or so scales have been added:
     ;;;
     ;;; ----------------
     ;;; Date: Thu, 12 Oct 1995 06:58:42 -0700
     ;;; From: COUL@ezh.nl (Manuel Op de Coul)
     ;;; Subject: Updated scale archive
     ;;;
     ;;; The scale archive with the collections of John Chalmers and myself
     ;;; has been updated and contains now over 1250 scales.
     ;;; The scales.doc file contains the complete listing. It's found here:
     ;;;
     ;;; http://www.cs.ruu.nl/pub/MIDI/DOC/scales.doc (readme file, ASCII)
     ;;; http://www.cs.ruu.nl/pub/MIDI/DOC/scales.zip (ZIP file, binary)
     ;;;
     ;;; Use the "-a" option while unzipping. The size of the ZIP file is about
     ;;; 284 Kb. FTP is possible also from ftp.cs.ruu.nl.
     ;;; The file format of the scales is that of my tuning program Scala,
     ;;; which I hope will be available soon. The files are text files so also
     ;;; usable without it.
     ;;;
     ;;; Manuel Op de Coul    coul@ezh.nl
     ;;; ----------------

SEE ALSO
========

   perl(1), see PDL, PDL/Audio.

MatLab style AutoLoader for PDL
*******************************

NAME
====

   PDL::AutoLoader - MatLab style AutoLoader for PDL

SYNOPSIS
========

     use PDL::AutoLoader;
     $a = func1(...);   # Load file func1.pdl
     $b = func2(...);   # Load file func2.pdl

     $PDL::AutoLoader::Rescan = 1; # Enable re-scanning

DESCRIPTION
===========

   This module implements a MatLab style AutoLoader for PDL. If a unknown
function 'func()' is called then a file 'func.pdl' is searched for and if
found is read in to define 'func()' which is then executed.

   Files are seached for using the directories in seach path `@PDLLIB',
which is initialised from the shell environment variable `PDLLIB' which is
a colon seperated list of directories.

   e.g. in csh

     setenv PDLLIB "/home/kgb/pdllib:/local/pdllib"

   Note this is kept seperate from PERL5LIB just in case.

   As an added bonus, you can use a leading '+' on a directory name to
search not just that directory but the entire directory tree under it
(excluding symlinks).  The subdirs are determined by explicit search, and
searches occur at startup and again each time you change the number of
elements in @PDLLIB.

   For example,   setenv PDLLIB "+~kgb/PDL"

   will search /home/kgb/PDL and all its subdirectories for .pdl files.

AUTO-SCANNING
-------------

   The variable `$PDL::AutoLoader::Rescan' controls whether files are
automatically re-scanned for changes at the `perldl' command line.

   If `$PDL::AutoLoader::Rescan == 1' and the file is changed then the new
definition is reloaded auto-matically before executing the `perldl'
command line. Which means in practice you can edit files, save changes and
have `perldl' see the changes automatically.

   The default is '0' - i.e. to have this feature disabled.

   As this feature is only pertinent to the `perldl' shell it imposes no
overhead on PDL scripts. Yes Bob you can have your cake and eat it too!

   Note: files are only re-evaled if they are determined to have been
changed according to their date/time stamp.

   No doubt this interface could be improved upon some more. :-)

Sample file:
------------

     sub foo { # file 'foo.pdl' - define the 'foo' function
       my $x=shift;
       return sqrt($x**2 + $x**3 + 2);
     }
     1; # File returns true (i.e. loaded successfully)

AUTHOR
======

   Copyright(C) 1997 Karl Glazebrook (kgb@aaoepp.aao.gov.au).  All rights
reserved. There is no warranty. You are allowed to redistribute this
software / documentation under certain conditions. For details, see the
file COPYING in the PDL distribution. If this file is separated from the
PDL distribution, the copyright notice should be included in the file.

BUGS
====

   No doubt this interface could be improved upon some more. :-)

   Will probably be quite slow if `$PDL::AutoLoader::Rescan == 1' and
thousands of functions have been autoloaded.

   There could be a race condition in which the file changes while the
internal autoloader code is being executed but it should be harmless.

   Probably has not been tested enough!

PDL does not process bad values
*******************************

NAME
====

   PDL::Bad - PDL does not process bad values

DESCRIPTION
===========

   PDL has been compiled with WITH_BADVAL either 0 or undef, so it does
not contain any bad-value support code.

   Implementation details are given in PDL/BadValues.

SYNOPSIS
========

     use PDL::Bad;
     print "\nBad value support in PDL is turned " .
         $PDL::Bad::Status ? "on" : "off" . ".\n";

     Bad value support in PDL is turned off.

VARIABLES
=========

   There are currently two variables that this module defines which may be
of use.

$PDL::Bad::Status
     Set to 0

$PDL::Bad::UseNaN
     Set to 0

BUGS
====

   None - it does nothing perfectly!

AUTHOR
======

   Doug Burke (burke@ifa.hawaii.edu), 2000.

   All rights reserved. There is no warranty. You are allowed to
redistribute this software / documentation under certain conditions. For
details, see the file COPYING in the PDL distribution. If this file is
separated from the PDL distribution, the copyright notice should be
included in the file.

Discussion of bad value support in PDL
**************************************

NAME
====

   PDL::BadValues - Discussion of bad value support in PDL

DESCRIPTION
===========

What are bad values and why should I bother with them?
------------------------------------------------------

   Sometimes it's useful to be able to specify a certain value is 'bad' or
'missing'; for example CCDs used in astronomy produce 2D images which are
not perfect since certain areas contain invalid data due to imperfections
in the detector.  Whilst PDL's powerful index routines and all the
complicated business with dataflow, slices, etc etc mean that these
regions can be ignored in processing, it's awkward to do. It would be much
easier to be able to say `$c = $a + $b' and leave all the hassle to the
computer.

   If you're not interested in this, then you may (rightly) be concerned
with how this affects the speed of PDL, since the overhead of checking for
a bad value at each operation can be large.  Because of this, the code has
been written to be as fast as possible - particularly when operating on
piddles which do not contain bad values.  In fact, you should notice
essentially no speed difference when working with piddles which do not
contain bad values.

   However, if you do not want bad values, then PDL's WITH_BADVAL
configuration option comes to the rescue; if set to 0 or undef, the
bad-value support is ignored.  About the only time I think you'll need to
use this - I admit, I'm biased ;) - is if you have limited disk or memory
space, since the size of the code is increased (see below).

   You may also ask 'well, my computer supports IEEE NaN, so I already
have this'.  Well, yes and no - many routines, such as `y=sin(x)', will
propogate NaN's without the user having to code differently, but routines
such as qsort, or finding the median of an array, need to be re-coded to
handle bad values.  For floating-point datatypes, NaN and `Inf' are used
to flag bad values IF the option `BADVAL_USENAN' is set to 1 in your
config file.  Otherwise special values are used (`Default bad values|' in
this node).  I do not have any benchmarks to see which option is faster.

Code increase due to bad values
-------------------------------

   On an i386 machine running linux and perl 5.005_03, I measured the
following sizes (the Slatec code was compiled in, but none of the other
options: eg Karma, FFTW, GSL, and 3d were):

WITH_BADVAL = 0
     Size of blib directory after a successful make = *4963 kb*: blib/arch
     = 2485 kb and blib/lib = 1587 kb.

WITH_BADVAL = 1
     Size of blib directory after a successful make = *5723 kb*: blib/arch
     = 3178 kb and blib/lib = 1613 kb.

   So, the overall increase is *only* 15% - not much to pay for all the
wonders that bad values provides ;)

   The source code used for this test had the vast majority of the core
routines (eg those in Basic/) converted to use bad values, whilst very few
of the 'external' routines (ie everything else in the PDL distribution)
had been changed.

A quick overview
----------------

     perldl> p $PDL::Bad::Status
     1
     perldl> $a = sequence(4,3);
     perldl> p $a
     [
      [ 0  1  2  3]
      [ 4  5  6  7]
      [ 8  9 10 11]
     ]
     perldl> $a = $a->setbadif( $a % 3 == 2 )
     perldl> p $a
     [
      [  0   1 BAD   3]
      [  4 BAD   6   7]
      [BAD   9  10 BAD]
     ]
     perldl> $a *= 3
     perldl> p $a
     [
      [  0   3 BAD   9]
      [ 12 BAD  18  21]
      [BAD  27  30 BAD]
     ]
     perldl> p $a->sum
     120

   `demo bad' and `demo bad2' within `perldl|PDL::perldl' in this node
gives a demonstration of some of the things possible with bad values.
These are also available on PDL's web-site, at
`http://pdl.perl.org/demos/'.  See PDL/Bad, for useful
routines for working with bad values and `t/bad.t' to see them in action.

   The intention is to:

   * not significantly affect PDL for users who don't need bad value
     support

   * be as fast as possible when bad value support is installed

   If you never want bad value support, then you set WITH_BADVAL to 0 in
`perldl.conf'; PDL then has no bad value support compiled in, so will be
as fast as it used to be.

   However, in most cases, the bad value support has a negligible affect
on speed, so you should set `WITH_CONFIG' to 1! One exception is if you
are low on memory, since the amount of code produced is larger (but only
by about 15% - see `Code increase due to bad values' in this node).

   To find out if PDL has been compiled with bad value support, look at
the values of either `$PDL::Config{WITH_BADVAL}' or $PDL::Bad::Status - if
true then it has been.

   To find out if a routine supports bad values, use the badinfo command in
`perldl|PDL::perldl' in this node or the -b option to `pdldoc|PDL::pdldoc'
in this node.  This facility is currently a 'proof of concept' (or, more
realistically, a quick hack) so expect it to be rough around the edges.

   Each piddle contains a flag - accessible via `$pdl->badflag' - to say
whether there's any bad data present:

   * If *false/0*, which means there's no bad data here, the code supplied
     by the Code option to `pp_def()' is executed. This means that the
     speed should be very close to that obtained with `WITH_BADVAL=0',
     since the only overhead is several accesses to a bit in the piddles
     state variable.

   * If *true/1*, then this says there *MAY* be bad data in the piddle, so
     use the code in the BadCode option (assuming that the `pp_def()' for
     this routine has been updated to have a BadCode key).  You get all
     the advantages of threading, as with the Code option, but it will run
     slower since you are going to have to handle the presence of bad
     values.

   If you create a piddle, it will have its bad-value flag set to 0. To
change this, use `$pdl->badflag($new_bad_status)', where `$new_bad_status'
can be 0 or 1.  When a routine creates a piddle, it's bad-value flag will
depend on the input piddles: unless over-ridden (see the CopyBadStatusCode
option to `pp_def'), the bad-value flag will be set true if any of the
input piddles contain bad values.  To check that a piddle really contains
bad data, use the `check_badflag' method.

   NOTE: propogation of the badflag

   If you change the badflag of a piddle, this change is propogated to all
the children of a piddle, so

     perldl> $a = zeroes(20,30);
     perldl> $b = $a->slice('0:10,0:10');
     perldl> $c = $b->slice(',(2)');
     perldl> print ">>c: ", $c->badflag, "\n";
     >>c: 0
     perldl> $a->badflag(1);
     perldl> print ">>c: ", $c->badflag, "\n";
     >>c: 1

   No change is made to the parents of a piddle, so

     perldl> print ">>a: ", $a->badflag, "\n";
     >>a: 1
     perldl> $c->badflag(0);
     perldl> print ">>a: ", $a->badflag, "\n";
     >>a: 1

   Thoughts:

   * the badflag can ONLY be cleared IF a piddle has NO parents, and that
     this change will propogate to all the children of that piddle. I am
     not so keen on this anymore (too awkward to code, for one).

   * `$a->badflag(1)' should propogate the badflag to BOTH parents and
     children.

   This shouldn't be hard to implement (although an initial attempt
failed!).  Does it make sense though? There's also the issue of what
happens if you change the badvalue of a piddle - should these propogate to
children/parents (yes) or whether you should only be able to change the
badvalue at the 'top' level - ie those piddles which do not have parents.

   The `orig_badvalue()' method returns the compile-time value for a given
datatype. It works on piddles, PDL::Type objects, and numbers - eg

     $pdl->orig_badvalue(), byte->orig_badvalue(), and orig_badvalue(4).

   It also has a horrible name...

   To get the current bad value, use the `badvalue()' method - it has the
same syntax as `orig_badvalue()'.

   To change the current bad value, supply the new number to badvalue - eg

     $pdl->badvalue(2.3), byte->badvalue(2), badvalue(5,-3e34).

   Note: the value is silently converted to the correct C type, and
returned - ie `byte->badvalue(-26)' returns 230 on my linux machine.  It
is also a nop for floating-point types when `BADVAL_USENAN' is true.

   Note that changes to the bad value are *NOT* propogated to
previously-created piddles - they will still have the bad value set, but
suddenly the elements that were bad will become 'good', but containing the
old bad value.  See discussion below.  It's not a problem for
floating-point types, since you can't change their badvalue.

Bad values and boolean operators
--------------------------------

   For those boolean operators in `PDL::Ops|PDL::Ops' in this node,
evaluation on a bad value returns the bad value.  Whilst this means that

     $mask = $img > $thresh;

   correctly propogates bad values, it *will* cause problems for checks
such as

     do_something() if any( $img > $thresh );

   which need to be re-written as something like

     do_something() if any( setbadtoval( ($img > $thresh), 0 ) );

   When using one of the 'projection' functions in `PDL::Ufunc|PDL::Ufunc'
in this node - such as `orover|PDL::Ufunc' in this node - bad values are
skipped over (see the documentation of these functions for the current
(poor) handling of the case when all elements are bad).

A bad value for each piddle, and related issues
-----------------------------------------------

   The following is relevant only for integer types, where there is a
choice of value to use as the bad flag.

   Currently, there is one bad value for each datatype. The code is
written so that we could have a separate bad value for each piddle (stored
in the pdl structure) - this would then remove the current problem of:

     perldl> $a = byte( 1, 2, byte->badvalue, 4, 5 );
     perldl> p $a;
     [1 2 255 4 5]
     perldl> $a->badflag(1)
     perldl> p $a;
     [1 2 BAD 4 5]
     perldl> byte->badvalue(0);
     perldl> p $a;
     [1 2 255 4 5]

   ie the bad value in `$a' has lost its *bad* status using the current
implementation.  It would almost certainly cause problems elsewhere though!

IMPLEMENTATION DETAILS
======================

   During a `perl Makefile.PL', the file `Basic/Core/badsupport.p' is
created; this file contains the values of the WITH_BADVAL and
`BADVAL_USENAN' variables, and should be used by code that is executed
before the `PDL::Config' file is created (e.g. `Basic/Core/pdlcore.c.PL'.
However, most PDL code will just need to access the `%PDL::Config' array
(e.g. `Basic/Bad/bad.pd') to find out whether bad-value support is
required.

   A new flag has been added to the state of a piddle - `PDL_BADVAL'. If
unset, then the piddle does not contain bad values, and so all the support
code can be ignored. If set, it does not guarantee that bad values are
present, just that they should be checked for. Thanks to Christian,
`badflag()' - which sets/clears this flag (see `Basic/Bad/bad.pd') - will
update ALL the children/grandchildren/etc of a piddle if its state changes
(see `badflag' in `Basic/Bad/bad.pd' and `propogate_badflag' in
`Basic/Core/Core.xs.PL').  It's not clear what to do with parents: I can
see the reason for propogating a 'set badflag' request to parents, but I
think a child should NOT be able to clear the badflag of a parent.
There's also the issue of what happens when you change the bad value for a
piddle.

   The `pdl_trans' structure has been extended to include an integer value,
`bvalflag', which acts as a switch to tell the code whether to handle bad
values or not. This value is set if any of the input piddles have their
`PDL_BADVAL' flag set (although this code can be replaced by setting
`FindBadStateCode' in pp_def).  The logic of the check is going to get a
tad more complicated if I allow routines to fall back to using the Code
section for floating-point types (ie those routines with `NoBadifNaN => 1'
when `BADVAL_USENAN' is true).

   The bad values for the integer types are now stored in a structure
within the Core PDL structure - `PDL.bvals' (eg
`Basic/Core/pdlcore.h.PL'); see also `typedef badvals' in
`Basic/Core/pdl.h.PL' and the BOOT code of `Basic/Core/Core.xs.PL' where
the values are initialised to (hopefully) sensible values.  See
`PDL/Bad/bad.pd' for read/write routines to the values.

   All this means that the internals of PDL are not binary compatible with
PDL 2.1.1 and earlier; external modules will need to be recompiled.

Why not make a PDL subclass?
----------------------------

   The support for bad values could have been done as a PDL sub-class.
The advantage of this approach would be that you only load in the code to
handle bad values if you actually want to use them.  The downside is that
the code then gets separated: any bug fixes/improvements have to be done
to the code in two different files.  With the present approach the code is
in the same `pp_def' function (although there is still the problem that
both Code and BadCode sections need updating).

Default bad values
------------------

   The default/original bad values are set to (taken from the Starlink
distribution):

     #include <limits.h>

     PDL_Byte    ==  UCHAR_MAX
     PDL_Short   ==   SHRT_MIN
     PDL_Ushort  ==  USHRT_MAX
     PDL_Long    ==    INT_MIN

   If `BADVAL_USENAN == 0', then we also have

     PDL_Float   ==   -FLT_MAX
     PDL_Double  ==   -DBL_MAX

   otherwise all of NaN, `+Inf', and `-Inf' are taken to be bad for
floating-point types.  In this case, the bad value can't be changed,
unlike the integer types.

How do I change a routine to handle bad values?
-----------------------------------------------

   Examples can be found in most of the `*.pd' files in `Basic/' (and
hopefully many more places soon!).  Some of the logic might appear a bit
unclear - that's probably because it is! Comments appreciated.

   All routines should automatically propogate the bad status flag to
output piddles, unless you declare otherwise.

   If a routine explicitly deals with bad values, you must provide this
option to pp_def:

     HandleBad => 1

   This ensures that the correct variables are initialised for the
`$ISBAD' etc macros. It is also used by the automatic document-creation
routines to provide default information on the bad value support of a
routine without the user having to type it themselves (this is in its
early stages).

   To flag a routine as NOT handling bad values, use

     HandleBad => 0

   This should cause the routine to print a warning if it's sent any
piddles with the bad flag set. Primitive's intover has had this set -
since it would be awkward to convert - but I've not tried it out to see if
it works.

   If you want to handle bad values but not set the state of all the output
piddles, or if it's only one input piddle that's important, then look at
the PP rules `NewXSFindBadStatus' and `NewXSCopyBadStatus' and the
corresponding `pp_def' options:

FindBadStatusCode
     By default, FindBadStatusCode creates code which sets
     `__privtrans->bvalflag' depending on the state of the bad flag of the
     input piddles: see `findbadstatus' in `Basic/Gen/PP.pm'.

CopyBadStatusCode
     The default code here is a bit simpler than for FindBadStatusCode:
     the bad flag of the output piddles are set if `__privtrans->bvalflag'
     is true after the code has been evaluated.  Sometimes
     CopyBadStatusCode is set to an empty string, with the responsibility
     of setting the badflag of the output piddle left to the BadCode
     section (e.g. the `xxxover' routines in
     `Basic/Primitive/primitive.pd').

   If you have a routine that you want to be able to use as inplace, look
at the routines in `bad.pd' (or `ops.pd') which use the Inplace option to
see how the bad flag is propogated to children using the
`xxxBadStatusCode' options.  I decided not to automate this as rules would
be a little complex, since not every inplace op will need to propogate the
badflag (eg unary functions).

   If the option

     HandleBad => 1

   is given, then many things happen.  For integer types, the readdata code
automatically creates a variable called `<pdl name>_badval', which
contains the bad value for that piddle (see `get_xsdatapdecl()' in
`Basic/Gen/PP/PdlParObjs.pm').  However, do not hard code this name into
your code!  Instead use macros (thanks to Tuomas for the suggestion):

     '$ISBAD(a(n=>1))'  expands to '$a(n=>1) == a_badval'
     '$ISGOOD(a())'                '$a()     != a_badval'
     '$SETBAD(bob())'              '$bob()    = bob_badval'

   well, the `$a(...)' is expanded as well. Also, you can use a `$' before
the pdl name, if you so wish, but it begins to look like line noise - eg
`$ISGOOD($a())'.

   If you cache a piddle value in a variable - eg index in `slices.pd' -
the following routines are useful:

     '$ISBADVAR(c_var,pdl)'       'c_var == pdl_badval'
     '$ISGOODVAR(c_var,pdl)'      'c_var != pdl_badval'
     '$SETBADVAR(c_var,pdl)'      'c_var  = pdl_badval'

   The following have been introduced, They may need playing around with to
improve their use.

     '$PPISBAD(CHILD,[i])          'CHILD_physdatap[i] == CHILD_badval'
     '$PPISGOOD(CHILD,[i])         'CHILD_physdatap[i] != CHILD_badval'
     '$PPSETBAD(CHILD,[i])         'CHILD_physdatap[i]  = CHILD_badval'

   If `BADVAL_USENAN' is set, then it's a bit different for float and
double, where we consider NaN, `+Inf', and `-Inf' all to be bad. In this
case:

     ISBAD   becomes   finite(piddle) == 0
     ISGOOD            finite(piddle) != 0
     SETBAD            piddle          = NaN

   where the value for NaN is discussed below in `Handling NaN values|' in
this node.

   This all means that you can change

     Code => '$a() = $b() + $c();'

   to

     BadCode => 'if ( $ISBAD(b()) || $ISBAD(c()) ) {
                   $SETBAD(a());
                 } else {
                   $a() = $b() + $c();
                 }'

   leaving Code as it is. PP::PDLCode will then create a loop something
like

     if ( __trans->bvalflag ) {
          threadloop over BadCode
     } else {
          threadloop over Code
     }

   (it's probably easier to just look at the `.xs' file to see what goes
on).

Going beyond the Code section
-----------------------------

   Similar to BadCode, there's `BadBackCode', and `BadRedoDimsCode'.

   Handling `EquivCPOffsCode' is a bit different: under the assumption
that the only access to data is via the `$EQUIVCPOFFS(i,j)' macro, then we
can automatically create the 'bad' version of it; see the
`[EquivCPOffsCode]' and `[Code]' rules in PDL/PP.

Macro access to the bad flag of a piddle
----------------------------------------

   Macros have been provided to provide access to the bad-flag status of a
pdl:

     '$PDLSTATEISBAD(a)'    -> '($PDL(a)->state & PDL_BADVAL) > 0'
     '$PDLSTATEISGOOD(a)'      '($PDL(a)->state & PDL_BADVAL) == 0'

     '$PDLSTATESETBAD(a)'      '$PDL(a)->state |= PDL_BADVAL'
     '$PDLSTATESETGOOD(a)'     '$PDL(a)->state &= ~PDL_BADVAL'

   For use in `xxxxBadStatusCode' (+ other stuff that goes into the INIT:
section) there are:

     '$SETPDLSTATEBAD(a)'       -> 'a->state |= PDL_BADVAL'
     '$SETPDLSTATEGOOD(a)'      -> 'a->state &= ~PDL_BADVAL'

     '$ISPDLSTATEBAD(a)'        -> '((a->state & PDL_BADVAL) > 0)'
     '$ISPDLSTATEGOOD(a)'       -> '((a->state & PDL_BADVAL) == 0)'

Handling NaN values
-------------------

   There are two issues:

NaN as the bad value
     which is done.  To select, set `BADVAL_USENAN' to 1 in perldl.conf; a
     value of 0 falls back to treating the floating-point types the same
     as the integers.  I need to do some benchmarks to see which is faster,
     and whether it's dependent on machines (Linux seems to slow down much
     more than my sparc machine in some very simple tests I did).

Ignoring BadCode sections
     which is not.

   For *simple* routines processing floating-point numbers, we should let
the computer process the bad values (ie NaN and `Inf' values) instead of
using the code in the BadCode section.  Many such routines have been
labelled using `NoBadifNaN => 1'; however this is currently *ignored* by
PDL::PP.

   For these routines, we want to use the Code section if

     the piddle does not have its bad flag set
     the datatype is a float or double

   otherwise we use the BadCode section.  This is *NOT IMPLEMENTED*, as it
will require reasonable hacking of PP::PDLCode!

   There's also the problem of how we handle 'exceptions' - since `$a =
pdl(2) / pdl(0)' produces a bad value but doesn't update the badflag value
of the piddle.  Can we catch an exception, or do we have to trap for this
(e.g. search for exception in `Basic/Ops/ops.pd')?

   Checking for `Nan', and `Inf' is done by using the `finite()' system
call.  If you want to set a value to the NaN value, the following bit of
code can be used (this can be found in both `Basic/Core/Core.xs.PL' and
`Basic/Bad/bad.pd'):

     /* for big-endian machines */
     static union { unsigned char __c[4]; float __d; }
           __pdl_nan = { { 0x7f, 0xc0, 0, 0 } };

     /* for little-endian machines */
     static union { unsigned char __c[4]; float __d; }
           __pdl_nan = { { 0, 0, 0xc0, 0x7f } };

   To find out whether a particular machine is big endian, use the routine
`PDL::Core::Dev::isbigendian()'.

WHAT ABOUT DOCUMENTATION?
=========================

   One of the strengths of PDL is it's on-line documentation. The aim is
to use this system to provide informtion on how/if a routine supports bad
values: in many cases `pp_def()' contains all the information anyway, so
the function-writer doesn't need to do anything at all! For the cases when
this is not sufficient, there's the BadDoc option. For code written at the
perl level - ie in a .pm file - use the `=for bad' pod directive.

   This information will be available via man/pod2man/html documenation.
It's also accessible from the `perldl' shell - using the badinfo command -
and the `pdldoc' shell command - using the -b option.

   This support is at a very early stage - ie not much thought has gone
into it: comments are welcome; improvements to the code preferred ;) One
awkward problem is for `*.pm' code: you have to write a `*.pm.PL' file
which only inserts the `=for bad' directive (+ text) if bad value support
is compiled in. In fact, this is a pain when handling bad values at the
perl, rather than PDL::PP, level: perhaps I should just scrap the
WITH_BADVAL option...

CURRENT ISSUES
==============

   There are a number of areas that need work, user input, or both!  They
are mentioned elsewhere in this document, but this is just to make sure
they don't get lost.

Trapping invalid mathematical operations
----------------------------------------

   Should we add exceptions to the functions in `PDL::Ops' to set the
output bad for out-of-range input values?

     perldl> p log10(pdl(10,100,-1))

   I would like the above to produce "[1 2 BAD]", but this would slow down
operations on all piddles.  We could check for NaN/`Inf' values after the
operation, but I doubt that would be any faster.

Integration with NaN
--------------------

   When `BADVAL_USENAN' is true, the routines in `PDL::Ops' should just
fall through to the Code section - ie don't use BadCode - for float and
double data types.

Global versus per-piddle bad values
-----------------------------------

   I think all that's needed is to change the routines in
`Basic/Core/pdlconv.c.PL', although there's bound to be complications.  It
would also mean that the pdl structure would need to have a variable to
store its bad value, which would mean binary incompatability with previous
versions of PDL with bad value support.

Dataflow of the badflag
-----------------------

   Currently changes to the bad flag are propogated to the children of a
piddle, but perhaps they should also be passed on to the parents as well.

EVERYTHING ELSE
===============

   The build process has been affected. The following files are now
created during the build:

     Basic/Core/pdlcore.h      pdlcore.h.PL
                pdlcore.c      pdlcore.c.PL
                pdlapi.c       pdlapi.c.PL
                Core.xs        Core.xs.PL
                Core.pm        Core.pm.PL

   Several new files have been added:

     Basic/Pod/Badvalues.pod (ie this file)

     t/bad.t

     Basic/Bad/
     Basic/Bad/Makefile.PL
               bad.pd

     IO/NDF/NDF.xs.PL

   etc

TODO/SUGGESTIONS
================

   * Look at using per-piddle bad values.  Would mean a change to the pdl
     structure (ie binary incompatability) and the routines in
     `Basic/Core/pdlconv.c.PL' would need changing to handle this.  Most
     other routines *should not* need to be changed ...

   * what to do about `$b = pdl(-2); $a = log10($b)' - `$a' should be set
     bad, but it currently isn't.

   * Allow the operations in PDL::Ops to skip the check for bad values
     when using NaN as a bad value and processing a floating-point piddle.
     Needs a fair bit of work to PDL::PP::PDLCode.

   * `$pdl->baddata()' now updates all the children of this piddle as
     well. However, not sure what to do with parents, since:

          $b = $a->slice();
          $b->baddata(0)

     doesn't mean that `$a' shouldn't have it's badvalue cleared.
     however, after

          $b->baddata(1)

     it's sensible to assume that the parents now get flagged as
     containing bad values.

     PERHAPS you can only clear the bad value flag if you are NOT a child
     of another piddle, whereas if you set the flag then all children AND
     parents should be set as well?

     Similarly, if you change the bad value in a piddle, should this be
     propogated to parent & children? Or should you only be able to do
     this on the 'top-level' piddle? Nasty...

   * get some code set up to do benchmarks to see how much things are
     slowed down (and to check that I haven't messed things up if
     WITH_BADVAL is 0/undef).

   * some of the names aren't appealing - I'm thinking of `orig_badvalue()'
     in `Basic/Bad/bad.pd' in particular. Any suggestions appreciated.

AUTHOR
======

   Copyright (C) Doug Burke (burke@ifa.hawaii.edu), 2000.  Commercial
reproduction of this documentation in a different format is forbidden.

Basic utility functions for PDL
*******************************

NAME
====

   PDL::Basic - Basic utility functions for PDL

DESCRIPTION
===========

   This module contains basic utility functions for creating and
manipulating piddles. Most of these functions are simplified interfaces to
the more flexible functions in the modules `PDL::Primitive|PDL::Primitive'
in this node and `PDL::Slices|PDL::Slices' in this node.

SYNOPSIS
========

     use PDL::Basic;

FUNCTIONS
=========

xvals
-----

   etc. see `zeroes|PDL::Core' in this node.

yvals
-----

   etc. see `zeroes|PDL::Core' in this node.

zvals
-----

   etc. see `zeroes|PDL::Core' in this node.

xlinvals
--------

   xlinvals, ylinvals and zlinvals return a piddle with the same shape as
their first argument and linearly scaled values between the two other
arguments along the given axis.

ylinvals
--------

   See `xlinvals|' in this node for more information.

zlinvals
--------

   See `xlinvals|' in this node for more information.

hist
----

   If requested, `$xvals' gives the computed bin centres

   A nice idiom (with `PDL::Graphics::PGPLOT|PDL::Graphics::PGPLOT' in
this node) is

     bin hist $data;  # Plot histogram

sequence
--------

   etc. see `zeroes|PDL::Core' in this node.

rvals
-----

     Centre => [$x,$y,$z...] # Specify centre
     Center => [$x,$y.$z...] # synonym.

   For a more general metric, one can define, e.g.,

     sub distance {
       my ($a,$centre,$f) = @_;
       my ($r) = $a->allaxisvals-$centre;
       $f->($r);
     }
     sub l1 { sumover(abs($_[0])); }
     sub euclid { use PDL::Math 'pow'; pow(sumover(pow($_[0],2)),0.5); }
     sub linfty { maximum(abs($_[0])); }

   so now

     distance($a, $centre, \&euclid);

   will emulate rvals, while `\&l1' and `\&linfty' will generate other
well-known norms.

axisvals
--------

   This is the routine, for which `xvals|' in this node, `yvals|' in this
node etc are mere shorthands. axisvals can be used to fill along any
dimension.

   Note the 'from specification' style (see `zeroes|PDL::Core' in this
node) is not available here, for obvious reasons.

allaxisvals
-----------

   allaxisvals produces an array with axis values along each dimension,
adding an extra dimension at the start.

   `allaxisvals($piddle)->slice("($nth)")' will produce the same result as
`axisvals($piddle,$nth)' (although with extra work and not inplace).

   It's useful when all the values will be required, as in the example
given of a generalized `rvals|' in this node.

transpose
---------

   Also bound to the `~' unary operator in PDL::Matrix.

call functions in external shared libraries
*******************************************

NAME
====

   PDL::CallExt - call functions in external shared libraries

SYNOPSIS
========

     use PDL::CallExt;
     callext('file.so', 'foofunc', $x, $y); # pass piddles to foofunc()

     % perl -MPDL::CallExt -e callext_cc file.c

DESCRIPTION
===========

   callext() loads in a shareable object (i.e. compiled code) using Perl's
dynamic loader, calls the named function and passes a list of piddle
arguments to it.

   It provides a reasonably portable way of doing this, including
compiling the code with the right flags, though it requires simple perl
and C wrapper routines to be written. You may prefer to use PP, which is
much more portable. See PDL/PP. You should definitely use
the latter for a 'proper' PDL module, or if you run in to the limitations
of this module.

API
===

   callext_cc() allows one to compile the shared objects using Perl's
knowledge of compiler flags.

   The named function (e.g. 'foofunc') must take a list of piddle
structures as arguments, there is now way of doing portable general
argument construction hence this limitation.

   In detail the code in the original file.c would look like this:

     #include "pdlsimple.h" /* Declare simple piddle structs - note this .h file
     			   contains NO perl/PDL dependencies so can be used
     			   standalone */

     int foofunc(int nargs, pdlsimple **args); /* foofunc prototype */

   i.e. foofunc() takes an array of pointers to pdlsimple structs. The use
is similar to that of `main(int nargs, char **argv)' in UNIX C
applications.

   pdlsimple.h defines a simple N-dimensional data structure which looks
like this:

     struct pdlsimple {
        int    datatype;  /* whether byte/int/float etc. */
        void  *data;      /* Generic pointer to the data block */
        int    nvals;     /* Number of data values */
        PDL_Long *dims;   /* Array of data dimensions */
        int    ndims;     /* Number of data dimensions */
     };

   (PDL_Long is always a 4 byte int and is defined in pdlsimple.h)

   This is a simplification of the internal reprensation of piddles in PDL
which is more complicated because of threading, dataflow, etc. It will
usually be found somewhere like
/usr/local/lib/perl5/site_perl/PDL/pdlsimple.h

   Thus to actually use this to call real functions one would need to
right a wrapper.  e.g. to call a 2D image processing routine:

     void myimage_processer(double* image, int nx, int ny);

     int foofunc(int nargs, pdlsimple **args) {
        pdlsimple* image = pdlsimple[0];
        myimage_processer( image->data, *(image->dims), *(image->dims+1) );
        ...
     }

   Obviously a real wrapper would include more error and argument checking.

   This might be compiled (e.g. Linux):

     cc -shared -o mycode.so mycode.c

   In general Perl knows how to do this, so you should be able to get away
with:

     perl -MPDL::CallExt -e callext_cc file.c

   callext_cc() is a function defined in PDL::CallExt to generate the
correct compilation flags for shared objects.

   If their are problems you will need to refer to you C compiler manual
to find out how to generate shared libraries.

   See t/callext.t in the distribution for a working example.

   It is up to the caller to ensure datatypes of piddles are correct - if
not peculiar results or SEGVs will result.

FUNCTIONS
=========

callext
-------

   The file must be compiled with dynamic loading options (see
callext_cc). See the module docs `PDL::Callext' for a description of the
API.

callext_cc
----------

     % perl -MPDL::CallExt -e callext_cc file.c -o file.so

   This works portably because when Perl has built in knowledge of how to
do dynamic loading on the system on which it was installed.  See the
module docs `PDL::Callext' for a description of the API.

AUTHORS
=======

   Copyright (C) Karl Glazebrook 1997.  All rights reserved. There is no
warranty. You are allowed to redistribute this software / documentation
under certain conditions. For details, see the file COPYING in the PDL
distribution. If this file is separated from the PDL distribution, the
copyright notice should be included in the file.

PDL subclass which allows reading and writing of fixed-length character strings as byte PDLs
********************************************************************************************

NAME
====

   PDL::Char - PDL subclass which allows reading and writing of
fixed-length character strings as byte PDLs

SYNOPSIS
========

     use PDL;
     use PDL::Char;

     my $pchar = PDL::Char->new( [['abc', 'def', 'ghi'],['jkl', 'mno', 'pqr']] );

     $pchar->setstr(1,0,'foo');

     print $pchar; # 'string' bound to "", perl stringify function
     # Prints:
     # [
     #  ['abc' 'foo' 'ghi']
     #  ['jkl' 'mno' 'pqr']
     # ]

     print $pchar->atstr(2,0);
     # Prints:
     # ghi

DESCRIPTION
===========

   This subclass of PDL allows one to manipulate PDLs of 'byte' type as if
they were made of fixed length strings, not just numbers.

   This type of behavior is useful when you want to work with charactar
grids.  The indexing is done on a string level and not a character level
for the 'setstr' and 'atstr' commands.

   This module is in particular useful for writing NetCDF files that
include character data using the PDL::NetCDF module.

FUNCTIONS
=========

new
---

     # Convert a PDL of type 'byte' to a PDL::Char
     $strpdl1 = PDL::Char->new (sequence (byte, 4, 5)+99);

string
------

     # 'string' is overloaded to the "" operator, so:
     # print $char;
     # should have the same effect.

setstr
------

   The input string will be null-padded if the string is shorter than the
first dimension of the PDL.  It will be truncated if it is longer.

atstr
-----

handle complex numbers
**********************

NAME
====

   PDL::Complex - handle complex numbers

SYNOPSIS
========

     use PDL;
     use PDL::Complex;

DESCRIPTION
===========

   This module features a growing number of functions manipulating complex
numbers. These are usually represented as a pair `[ real imag ]' or `[
angle phase ]'. If not explicitly mentioned, the functions can work
inplace (not yet implemented!!!) and require rectangular form.

   While there is a procedural interface available (`$a/$b*$c <=' Cmul
(Cdiv $a, $b), $c)>), you can also opt to cast your pdl's into the
`PDL::Complex' datatype, which works just like your normal piddles, but
with all the normal perl operators overloaded.

   The latter means that `sin($a) + $b/$c' will be evaluated using the
normal rules of complex numbers, while other pdl functions (like max) just
treat the piddle as a real-valued piddle with a lowest dimension of size
2, so max will return the maximum of all real and imaginary parts, not the
"highest" (for some definition)

TIPS, TRICKS & CAVEATS
======================

i is a constant exported by this module, which represents `-1**0.5', i.e. the imaginary unit. it can be used to quickly and conviniently write complex constants like this: `4+3*i'.
Use `r2C(real-values)' to convert from real to complex, as in `$r = Cpow $cplx, r2C 2'. The overloaded operators automatically do that for you, all the other functions, do not. So `Croots 1, 5' will return all the fifths roots of 1+1*i (due to threading).
use `cplx(real-valued-piddle)' to cast from normal piddles intot he complex datatype. Use `real(complex-valued-piddle)' to cast back. This requires a copy, though.
BEWARE: This module has not been extensively tested. Watch out and send me bugreports!
EXAMPLE WALK-THROUGH
====================

   The complex constant five is equal to `pdl(1,0)':

     perldl> p $x = r2C 5
     [5 0]

   Now calculate the three roots of of five:

     perldl> p $r = Croots $x, 3

     [
      [  1.7099759           0]
      [-0.85498797   1.4808826]
      [-0.85498797  -1.4808826]
     ]

   Check that these really are the roots of unity:

     perldl> p $r ** 3

     [
      [             5              0]
      [             5 -3.4450524e-15]
      [             5 -9.8776239e-15]
     ]

   Duh! Could be better. Now try by multiplying $r three times with itself:

     perldl> p $r*$r*$r

     [
      [             5              0]
      [             5 -2.8052647e-15]
      [             5 -7.5369398e-15]
     ]

   Well... maybe Cpow (which is used by the `**' operator) isn't as bad as
I thought. Now multiply by i and negate, which is just a very expensive
way of swapping real and imaginary parts.

     perldl> p -($r*i)

     [
      [         -0   1.7099759]
      [  1.4808826 -0.85498797]
      [ -1.4808826 -0.85498797]
     ]

   Now plot the magnitude of (part of) the complex sine. First generate the
coefficients:

     perldl> $sin = i * zeroes(50)->xlinvals(2,4)
                      + zeroes(50)->xlinvals(0,7)

   Now plot the imaginary part, the real part and the magnitude of the sine
into the same diagram:

     perldl> line im sin $sin; hold
     perldl> line re sin $sin
     perldl> line abs sin $sin

   Sorry, but I didn't yet try to reproduce the diagram in this text. Just
run the commands yourself, making sure that you have loaded `PDL::Complex'
(and PDL::Graphics::PGPLOT).

FUNCTIONS
=========

cplx real-valued-pdl
--------------------

   Cast a real-valued piddle to the complex datatype. The first dimension
of the piddle must be of size 2. After this the usual (complex) arithmetic
operators are applied to this pdl, rather than the normal elementwise pdl
operators.  Dataflow to the complex parent works. Use sever on the result
if you don't want this.

real cplx-valued-pdl
--------------------

   Cast a complex vlaued pdl back to the "normal" pdl datatype. Afterwards
the normal elementwise pdl operators are used in operations. Dataflow to
the real parent works. Use sever on the result if you don't want this.

r2C
---

i2C
---

Cr2p
----

Cp2r
----

Cmul
----

Cscale
------

Cdiv
----

Ccmp
----

Cconj
-----

Cabs
----

Cabs2
-----

Carg
----

Csin
----

Ccos
----

Ctan a [not inplace]
--------------------

     tan (a) = -i * (exp (a*i) - exp (-a*i)) / (exp (a*i) + exp (-a*i))

Cexp
----

Clog
----

Cpow
----

Csqrt
-----

   BEGIN {*Csqrt = \&PDL::Csqrt; }

Casin
-----

   BEGIN {*Casin = \&PDL::Casin; }

Cacos
-----

   BEGIN {*Cacos = \&PDL::Cacos; }

Catan cplx [not inplace]
------------------------

   Return the complex `atan()'.

Csinh
-----

Ccosh
-----

Ctanh
-----

   BEGIN {*Ctanh = \&PDL::Ctanh; }

Casinh
------

   BEGIN {*Casinh = \&PDL::Casinh; }

Cacosh
------

   BEGIN {*Cacosh = \&PDL::Cacosh; }

Catanh
------

   BEGIN {*Catanh = \&PDL::Catanh; }

Cproj
-----

Croots
------

re cplx, im cplx
----------------

   Return the real or imaginary part of the complex number(s) given. These
are slicing operators, so data flow works. The real and imaginary parts
are returned as piddles (ref eq PDL).

rCpolynomial
------------

AUTHOR
======

   Copyright (C) 2000 Marc Lehmann <pcg@goof.com>.  All rights reserved.
There is no warranty. You are allowed to redistribute this software /
documentation as described in the file COPYING in the PDL distribution.

SEE ALSO
========

   perl(1), see PDL.

fundamental PDL functionality
*****************************

NAME
====

   PDL::Core - fundamental PDL functionality

DESCRIPTION
===========

   Methods and functions for type conversions, PDL creation, type
conversion, threading etc.

SYNOPSIS
========

     use PDL::Core;             # Normal routines
     use PDL::Core ':Internal'; # Hairy routines

FUNCTIONS
=========

pdl
---

   Note the last two are equivalent - a list is automatically converted to
a list reference for syntactic convenience. i.e. you can omit the outer []

   `pdl()' is a functional synonym for the 'new' constructor, e.g.:

     $x = new PDL [1..10];

   In order to control how undefs are handled in converting from perl
lists to PDLs, one can set the variable `$PDL::undefval'.  For example:

     $foo = [[1,2,undef],[undef,3,4]];
     $PDL::undefval = -999;
     $f = pdl $foo;
     print $f
     [
      [   1    2 -999]
      [-999    3    4]
     ]

   `$PDL::undefval' defaults to zero.

null
----

   `null()' has a special meaning to `PDL::PP|PDL::PP' in this node. It is
used to flag a special kind of empty piddle, which can grow to appropriate
dimensions to store a result (as opposed to storing a result in an
existing piddle).

nullcreate
----------

   This is an routine used by many of the threading primitives (i.e.
`sumover|PDL::Primitive' in this node, `minimum|PDL::Primitive' in this
node, etc.) to generate a null piddle for the function's output that will
behave properly for derived (or subclassed) PDL objects.

   For the above usage: If $arg is a PDL, or a derived PDL, then
`$arg->null' is returned.  If $arg is a scalar (i.e. a zero-dimensional
PDL) then `$PDL->null' is returned.

nelem
-----

dims
----

PDL::getndims
-------------

PDL::getdim
-----------

   Negative indices count from the end of the dims array.  Indices beyond
the end will return a size of 1. This reflects the idea that any pdl is
equivalent to an infinitely dimensional array in which only a finite
number of dimensions have a size different from one. For example, in that
sense a 3D piddle of shape [3,5,2] is equivalent to a
[3,5,2,1,1,1,1,1,....]  piddle. Accordingly,

     print $a->getdim(10000);

   will print 1 for most practically encountered piddles.

topdl
-----

   The difference between `pdl()|' in this node and `topdl()' is that the
latter will just 'fall through' if the argument is already a piddle. It
will return a reference and *NOT* a new copy.

   This is particulary useful if you are writing a function which is doing
some fiddling with internals and assumes a piddle argument (e.g. for
method calls). Using `topdl()' will ensure nothing breaks if passed with
'2'.

PDL::get_datatype
-----------------

   Mainly used for internal routines.

   NOTE: get_datatype returns 'just a number' not any special type object,
unlike `type|' in this node.

howbig
------

   Mainly used for internal routines.

   NOTE: NOT a method! This is because get_datatype returns 'just a
number' not any special object.

threadids
---------

doflow
------

flows
-----

PDL::new
--------

   Constructs piddle from perl numbers and lists.

PDL::copy
---------

   Since `$new = $old' just makes a new reference, the copy method is
provided to allow real independent copies to be made.

PDL::unwind
-----------

PDL::make_physical
------------------

   Ensures that a piddle gets its own allocated copy of data. This
obviously implies that there are certain piddles which do not have their
own data.  These are so called *virtual* piddles that make use of the
*vaffine* optimisation (see `PDL::Indexing|PDL::Indexing' in this node).
They do not have their own copy of data but instead store only access
information to some (or all) of another piddle's data.

   Note: this function should not be used unless absolutely neccessary
since otherwise memory requirements might be severly increased. Instead of
writing your own XS code with the need to call `make_physical' you might
want to consider using the PDL preprocessor (see `PDL::PP|PDL::PP' in this
node) which can be used to transparently access virtual piddles without the
need to physicalise them (though there are exceptions).

dummy
-----

   No relation to the 'Dungeon Dimensions' in Discworld!  Negative
positions specify relative to last dimension, i.e. `dummy(-1)' appends one
dimension at end, `dummy(-2)' inserts a dummy dimension in front of the
last dim, etc.

thread_define
-------------

   thread_define provides some support for threading (see
PDL/Indexing) at the perl level. It allows you to do things
for which you normally would have resorted to PDL::PP (see PDL/PP);
however, it is most useful to wrap existing perl functions so
that the new routine supports PDL threading.

   thread_define is used to define new *threading aware* functions. Its
first argument is a symbolic repesentation of the new function to be
defined. The string is composed of the name of the new function followed
by its signature (see PDL/Indexing, and PDL/PP)
in parentheses. The second argument is a subroutine that will be
called with the slices of the actual runtime arguments as specified by its
signature. Correct dimension sizes and minimal number of dimensions for
all arguments will be checked (assuming the rules of PDL threading, see
PDL/Indexing).

   The actual work is done by the signature class which parses the
signature string, does runtime dimension checks and the routine
`threadover' that generates the loop over all appropriate slices of pdl
arguments and creates pdls as needed.

   Similar to `pp_def' and its OtherPars option it is possible to define
the new function so that it accepts normal perl args as well as piddles.
You do this by using the `NOtherPars' parameter in the signature. The
number of `NOtherPars' specified will be passed unaltered into the
subroutine given as the second argument of thread_define. Let's illustrate
this with an example:

     PDL::thread_define 'triangles(inda();indb();indc()), NOtherPars => 2',
      PDL::over {
        ${$_[3]} .= $_[4].join(',',map {$_->at} @_[0..2]).",-1,\n";
      };

   This defines a function `triangles' that takes 3 piddles as input plus
2 arguments which are passed into the routine unaltered. This routine is
used to collect lists of indices into a perl scalar that is passed by
reference. Each line is preceded by a prefix passed as `$_[4]'. Here is
typical usage:

     $txt = '';
     triangles(pdl(1,2,3),pdl(1),pdl(0),\$txt," "x10);
     print $txt;

   resulting in the following output

     1,1,0,-1,
     2,1,0,-1,
     3,1,0,-1,

   which is used in `PDL::Graphics::TriD::VRML|PDL::Graphics::TriD::VRML'
in this node to generate VRML output.

   Currently, this is probably not much more than a POP (proof of
principle) but is hoped to be useful enough for some real life work.

   Check `PDL::PP|PDL::PP' in this node for the format of the signature.
Currently, the `[t]' qualifier and all type qualifiers are ignored.

PDL::thread
-----------

   Same as `PDL::thread1|' in this node, i.e. uses thread id 1.

diagonal
--------

PDL::thread1
------------

   Convenience function interfacing to `PDL::Slices::threadI|PDL::Slices'
in this node.

PDL::thread2
------------

   Convenience function interfacing to `PDL::Slices::threadI|PDL::Slices'
in this node.

PDL::thread3
------------

   Convenience function interfacing to `PDL::Slices::threadI|PDL::Slices'
in this node.

sever
-----

   In PDL it is possible for a piddle to be just another view into another
piddle's data. In that case we call this piddle a *virtual piddle* and the
original piddle owning the data its parent. In other languages these
alternate views sometimes run by names such as alias or *smart reference*.

   Typical functions that return such piddles are slice, xchg, index, etc.
Sometimes, however, you would like to separate the *virtual piddle* from
its parent's data and just give it a life of its own. This is simply
achieved by using sever. For example,

   In this regard it acts similar to copy. However, in general performance
is better with sever and secondly, sever doesn't lead to futile copying
when used on piddles that already have their own data.

     $a = zeroes(20);
     $a->sever;   # NOOP since $a is already its own boss!

PDL::info
---------

   Returns a string with info about a piddle. Takes an optional argument
to specify the format of information a la sprintf.  Format specifiers are
in the form `%<width><letter>' where the width is optional and the letter
is one of

T
     Type

D
     Formatted Dimensions

F
     Dataflow status

S
     Some internal flags (P=physical,V=Vaffine,C=changed)

C
     Class of this piddle, i.e. `ref $pdl'

A
     Address of the piddle struct as a unique identifier

M
     Calculated memory consumption of this piddle's data area

mslice
------

inplace
-------

   In most cases one likes to use the syntax `$y = f($x)', however in many
case the operation `f()' can be done correctly 'in place', i.e. without
making a new copy of the data for output. To make it easy to use this, we
write `f()' in such a way that it operates in-place, and use inplace to
hint that a new copy should be disabled. This also makes for clear syntax.

   Obviously this will not work for all functions, and if in doubt see the
function's documentation. However one can assume this is true for all
elemental functions (i.e. those which just operate array element by array
element like log10).

PDL::new_from_specification
---------------------------

   This is the argument processing method called by `zeroes|' in this node
and some other functions which constructs piddles from argument lists of
the form:

     [type], $nx, $ny, $nz,...

   For `$nx', `$ny', etc. 0 and 1D piddles are allowed.  Giving those has
the same effect as if saying `$arg->list', e.g.

     1, pdl(5,2), 4

   is equivalent to

     1, 5, 2, 4

   Note, however, that in all functions using `new_from_specification'
calling `func $piddle' will probably not do what you want. So to play safe
use (e.g. with zeroes)

     $pdl = zeroes $dimpdl->list;

   Calling

     $pdl = zeroes $dimpdl;

   will rather be equivalent to

     $pdl = zeroes $dimpdl->dims;

   However,

     $pdl = zeroes ushort, $dimpdl;

   will again do what you intended since it is interpreted as if you had
said

     $pdl = zeroes ushort, $dimpdl->list;

   This is unfortunate and confusing but no good solution seems obvious
that would not break existing scripts.

isempty
-------

   This function returns 1 if the piddle has zero elements. This is useful
in particular when using the indexing function which. In the case of no
match to a specified criterion, the returned piddle has zero dimension.

     perldl> $a=sequence(10)
     perldl> $i=which($a < -1)
     perldl> print "I found no matches!\n" if ($a->isempty);

   Note that having zero elements is rather different from the concept of
being a null piddle, see the `PDL::FAQ|PDL::FAQ' in this node and
`PDL::Indexing|PDL::Indexing' in this node manpages for discussions of
this.

zeroes
------

   Various forms of usage,

   (i) by specification or (ii) by template piddle:

   See also `new_from_specification|new_from_specification' in this node
for details on using piddles in the dimensions list.

ones
----

   See also `new_from_specification|new_from_specification' in this node
for details on using piddles in the dimensions list.

reshape
-------

   The data elements are preserved, obviously they will wrap differently
and get truncated if the new array is shorter.  If the new array is longer
it will be zero-padded.

   Note: an explicit copy is forced - this is the only way (for now) of
stopping a crash if $x is a slice.

flat
----

   Useful method to make a 1D piddle from an arbitrarily sized input
piddle. Data flows back and forth as usual with slicing routines.

convert
-------

   `$newtype' is a type number, for convenience they are returned by
`long()' etc when called without arguments.

Datatype_conversions
--------------------

   When called with a piddle argument, they convert to the specific
datatype.

   When called with a numeric or list / listref argument they construct a
new piddle. This is a convenience to avoid having to be long-winded and
say `$x = long(pdl(42))'

   Thus one can say:

     $a = float(1,2,3,4);           # 1D
     $a = float([1,2,3],[4,5,6]);   # 2D
     $a = float([[1,2,3],[4,5,6]]); # 2D

   Note the last two are equivalent - a list is automatically converted to
a list reference for syntactic convenience. i.e. you can omit the outer []

   When called with no arguments return a special type token.  This allows
syntactical sugar like:

     $x = ones byte, 1000,1000;

   This example creates a large piddle directly as byte datatype in order
to save memory.

   In order to control how undefs are handled in converting from perl
lists to PDLs, one can set the variable `$PDL::undefval'; see the function
`pdl()|' in this node for more details.

byte
----

short
-----

ushort
------

long
----

float
-----

double
------

type
----

   A convenience function for use with the piddle constructors, e.g.

   See the discussion of the `PDL::Type' object in PDL/Types.

list
----

   Obviously this is grossly inefficient for the large datasets PDL is
designed to handle. This was provided as a get out while PDL matured. It
should now be mostly superseded by superior constructs, such as
PP/threading. However it is still occasionally useful and is provied for
backwards compatibility.

listindices
-----------

   `@tmp' now contains the values `0..nelem($x)'.

   Obviously this is grossly inefficient for the large datasets PDL is
designed to handle. This was provided as a get out while PDL matured. It
should now be mostly superseded by superior constructs, such as
PP/threading. However it is still occasionally useful and is provied for
backwards compatibility.

set
---

   `@position' is a coordinate list, of size equal to the number of
dimensions in the piddle. Occasionally useful, mainly provided for
backwards compatibility as superseded by use of `slice|PDL::Slices' in
this node and assigment operator `.='.

at
--

   `@position' is a coordinate list, of size equal to the number of
dimensions in the piddle. Occasionally useful in a general context, quite
useful too inside PDL internals.

cat
---

   Takes a list of N piddles of same shape as argument, returns a single
piddle of dimension N+1

dog
---

   Takes a single N-dimensional piddle and splits it into a list of N-1
dimensional piddles. The breakup is done along the last dimension.  Note
the dataflown connection is still preserved by default, e.g.:

barf
----

   `barf()' is the routine PDL modules should call to report errors. This
is because `barf()' will report the error as coming from the correct line
in the module user's script rather than in the PDL module.

   It does this magic by unwinding the stack frames until it reaches a
package NOT beginning with `"PDL::"'. If you DO want it to report errors
in some module PDL::Foo (e.g. when debugging PDL::Foo) then set the
variable `$PDL::Foo::Debugging=1'.

   Additionally if you set the variable `$PDL::Debugging=1' you will get a
COMPLETE stack trace back up to the top level package.

   Finally `barf()' will try and report usage information from the PDL
documentation database if the error message is of the form 'Usage: func'.

   Remember `barf()' is your friend. *Use* it!

     barf("User has too low an IQ!");

   In C or XS code:

     barf("You have made %d errors", count);

   Note: this is one of the few functions ALWAYS exported by PDL::Core

gethdr
------

   The gethdr function retrieves whatever header information is contained
within a piddle. The header can be set with `sethdr|' in this node and is
always a hash reference and has to be dereferenced for access to the value.

   It is important to realise that you are free to insert whatever hash
reference you want in the header, so you can use it to record important
information about your piddle, and that it is not automatically copied
when you copy the piddle.  See `hdrcpy|' in this node to enable automatic
header copying.

   For instance a wrapper around rcols that allows your piddle to remember
the file it was read from and the columns could be easily written (here
assuming that no regexp is needed, extensions are left as an exercise for
the reader)

     sub ext_rcols {
        my ($file, @columns)=@_;
        my $header={};
        $$header{File}=$file;
        $$header{Columns}=\@columns;

     @piddles=rcols $file, @columns;
     foreach (@piddles) { $_->sethdr($header); }
     return @piddles;
      }

sethdr
------

   The sethdr function sets the header information for a piddle.  Normally
you would get the current header information with `gethdr|' in this node,
add/change/remove fields, then apply those changes with sethdr.

   The sethdr function must be given a hash reference.  For further
information on the header, see `gethdr|' in this node and `hdrcpy|' in
this node.

hdrcpy
------

   Normally, the optional header of a piddle is not copied automatically
in pdl operations. Switching on the hdrcpy flag using the hdrcpy method
will enable automatic hdr copying. Note that copying is *by reference* for
efficiency reasons. hdrcpy without an argument just returns the current
setting of the flag.

AUTHOR
======

   Copyright (C) Karl Glazebrook (kgb@aaoepp.aao.gov.au), Tuomas J. Lukka,
(lukka@husc.harvard.edu) and Christian Soeller (c.soeller@auckland.ac.nz)
1997.  All rights reserved. There is no warranty. You are allowed to
redistribute this software / documentation under certain conditions. For
details, see the file COPYING in the PDL distribution. If this file is
separated from the PDL distribution, the copyright notice should be
included in the file.

PDL development module
**********************

NAME
====

   PDL::Core::Dev - PDL development module

DESCRIPTION
===========

   This module encapsulates most of the stuff useful for PDL development
and is often used from within Makefile.PL's.

SYNOPSIS
========

     use PDL::Core::Dev;
     if ($^O =~ /win32/i) {
      warn "Win32 systems not yet supported. Will not build PDL::IO::Browser";
      write_dummy_make(unsupported('PDL::XXX','win32'));
      return;
     }

FUNCTIONS
=========

isbigendian
-----------

   returns 1 if the machine is big endian, 0 if little endian, or dies if
neither.  It uses the `byteorder' element of perl's `%Config' array.

trylink
-------

   Try to link some C-code making up the body of a function with a given
set of library specifiers

   return 1 if successful, 0 otherwise

   Takes 4 + 1 optional argument.

   * an informational message to print (can be empty)

   * any commands to be included at the top of the generated C program
     (typically something like `#include "mylib.h"')

   * the body of the program (in function main)

   * library flags to use for linking. Preprocessing by MakeMaker should
     be performed as needed (see options and example).

   * OPTIONS
       1. Preprocess library in the way MakeMaker does things. This is
          advisable to ensure that your code will actually work after the
          link specs have been processed by MakeMaker.

       2. Hide Controls of linking output etc is hidden from the user or
          not.  On by default.

description of the dataflow philosophy
**************************************

NAME
====

   PDL::Dataflow - description of the dataflow philosophy

SYNOPSIS
========

     perldl> $a = zeroes(10);
     perldl> $b = $a->slice("2:4:2");
     perldl> $b ++;
     perldl> print $a;
     [0 0 1 0 1 0 0 0 0 0]

WARNING
=======

   Dataflow is very experimental. Many features of it are disabled for
2.0, particularly families for one-directional dataflow. If you wish to
use one-directional dataflow for something, please contact the author
first and we'll work out how to make it functional again.

   Two-directional dataflow (which implements ->slice() etc.)  is fully
functional, however. Just about any function which returns some subset of
the values in some piddle will make a binding so that

     $a = some piddle
     $b = $a->slice("some parts");
     $b->set(3,3,10);

   also changes the corresponding element in $a. $b has become effectively
a window to some subelements of $a. You can also define your own routines
that do different types of subsets. If you don't want $b to be a window to
$a, you must do

     $b = $a->slice("some parts")->copy;

   The copying turns off all dataflow between the two piddles.

   The difficulties with one-directional dataflow are related to sequences
like

     $b = $a + 1;
     $b ++;

   where there are several possible outcomes and the semantics get a little
murky.

DESCRIPTION
===========

   Dataflow is new to PDL2.0. The basic philosophy behind dataflow is that

     > $a = pdl 2,3,4;
     > $b = $a * 2;
     > print $b
     [2 3 4]
     > $a->set(0,5);
     > print $b;
     [10 3 4]

   should work. It doesn't. It was considered that doing this might be too
confusing for novices and occasional users of the language.  Therefore,
you need to explicitly turn on dataflow, so

     > $a = pdl 2,3,4;
     > $a->doflow();
     > $b = $a * 2;
     ...

   produces the (un)expected result. The rest of this documents explains
various features and details of the dataflow implementation.

Lazy evaluation
===============

   When you calculate something like the above

     > $a = pdl 2,3,4;
     > $a->doflow();
     > $b = $a * 2;

   nothing will have been calculated at this point. Even the memory for
the contents of $b has not been allocated. Only the command

     > print $b

   will actually cause $b to be calculated. This is important to bear in
mind when doing performance measurements and benchmarks as well as when
tracking errors.

   There is an explanation for this behaviour: it may save cycles but more
importantly, imagine the following:

     > $a = pdl 2,3,4;
     > $b = pdl 5,6,7;
     > $c = $a + $b;
     ...
     > $a->resize(4);
     > $b->resize(4);
     > print $c;

   Now, if $c were evaluated between the two resizes, an error condition
of incompatible sizes would occur.

   What happens in the current version is that resizing $a raises a flag
in $c: "PDL_PARENTDIMSCHANGED" and $b just raises the same flag again.
When $c is next evaluated, the flags are checked and it is found that a
recalculation is needed.

   Of course, lazy evaluation can sometimes make debugging more painful
because errors may occur somewhere where you'd not expect them.  A better
stack trace for errors is in the works for PDL, probably so that you can
toggle a switch $PDL::traceevals and get a good trace of where the error
actually was.

Families
========

   This is one of the more intricate concepts of one-directional dataflow.
Consider the following code ($a and $b are pdls that have dataflow
enabled):

     $c = $a + $b;
     $e = $c + 1;
     $d = $c->diagonal();
     $d ++;
     $f = $c + 1;

   What should $e and $f contain now? What about when $a is changed and a
recalculation is triggered.

   In order to make dataflow work like you'd expect, a rather strange
concept must be introduced: families. Let us make a diagram:

     a   b
      \ /
       c
      /|
     / |
            e  d

   This is what PDL actually has in memory after the first three lines.
When $d is changed, we want $c to change but we don't want $e to change
because it already is on the graph. It may not be clear now why you don't
want it to change but if there were 40 lines of code between the 2nd and
4th lines, you would. So we need to make a copy of $c and $d:

     a   b
      \ /
       c' . . . c
      /|        |\
     / |        | \
            e  d' . . . d  f

   Notice that we primed the original c and d, because they do not
correspond to the objects in $c and $d any more. Also, notice the dotted
lines between the two objects: when $a is changed and this diagram is
re-evaluated, $c really does get the value of c' with the diagonal
incremented.

   To generalize on the above, whenever a piddle is mutated i.e.  when its
actual *value* is forcibly changed (not just the reference:

     $d = $d + 1

   would produce a completely different result ($c and $d would not be
bound any more whereas

     $d .= $d + 1

   would yield the same as $d++), a "family" consisting of all other
piddles joined to the mutated piddle by a two-way transformation is created
and all those are copied.

   All slices or transformations that simply select a subset of the
original pdl are two-way. Matrix inverse should be. No arithmetic
operators are.

Sources
=======

   What you were told in the previous section is not quite true: the
behaviour described is not *always* what you want. Sometimes you would
probably like to have a data "source":

     $a = pdl 2,3,4; $b = pdl 5,6,7;
     $c = $a + $b;
     line($c);

   Now, if you know that $a is going to change and that you want its
children to change with it, you can declare it into a data source (XXX
unimplemented in current version):

     $a->datasource(1);

   After this, $a++ or $a .= something will not create a new family but
will alter $a and cut its relation with its previous parents.  All its
children will follow its current value.

   So if $c in the previous section had been declared as a source, $e and
$f would remain equal.

Binding
=======

   A dataflow mechanism would not be very useful without the ability to
bind events onto changed data. Therefore, we provide such a mechanism:

     > $a = pdl 2,3,4
     > $b = $a + 1;
     > $c = $b * 2;
     > $c->bind( sub { print "A now: $a, C now: $c\n" } )
     > PDL::dowhenidle();
     A now: [2,3,4], C now: [6 8 10]
     > $a->set(0,1);
     > $a->set(1,1);
     > PDL::dowhenidle();
     A now: [1,1,4], C now: [4 4 10]

   Notice how the callbacks only get called during PDL::dowhenidle.  An
easy way to interface this to Perl event loop mechanisms (such as Tk) is
being planned.

   There are many kinds of uses for this feature: self-updating graphs,
for instance.

   Bla bla bla XXX more explanation

Limitations
===========

   Dataflow as such is a fairly limited addition on top of Perl.  To get a
more refined addition, the internals of perl need to be hacked a little. A
true implementation would enable flow of everything, including

data
data size
datatype
operations
   At the moment we only have the first two (hey, 50% in a couple of months
is not bad ;) but even this is useful by itself. However, especially the
last one is desirable since it would add the possibility of flowing
closures from place to place and would make many things more flexible.

   To get the rest working, the internals of dataflow probably need to be
changed to be a more general framework.

   Additionally, it would be nice to be able to flow data in time,
lucid-like (so you could easily define all kinds of signal processing
things).

AUTHOR
======

   Copyright(C) 1997 Tuomas J. Lukka (lukka@fas.harvard.edu).
Redistribution in the same form is allowed provided that the copyright
notice stays intact but reprinting requires a permission from the author.

functions to support debugging of PDL scripts
*********************************************

NAME
====

   PDL::Dbg - functions to support debugging of PDL scripts

SYNOPSIS
========

     use PDL;
     use PDL::Dbg;

     $c = $a->slice("5:10,2:30")->px->diagonal(3,4);
     PDL->px;

DESCRIPTION
===========

   This packages implements a couple of functions that should come in
handy when debugging your PDL scripts. They make a lot of sense while
you're doing rapid prototyping of new PDL code, let's say inside the
perldl shell.

FUNCTIONS
=========

px
--

   This function prints some information about piddles. It can be invoked
as a class method (e.g. `PDL->px' ) or as an instance method (e.g.
`$pdl->px($arg)'). If

invoked as a class method
     it prints info about all piddles found in the current package
     (*excluding* my variables). This comes in quite handy when you are
     not quite sure which pdls you have already defined, what data they
     hold , etc. px is supposed to support inheritance and prints info
     about all symbols for which an `isa($class)' is true. An optional
     string argument is interpreted as the package name for which to print
     symbols:

          perldl> PDL->px('PDL::Mypack')

     The default package is that of the caller.

invoked as an instance method
     it prints info about that particular piddle if `$PDL::debug' is true
     and returns the pdl object upon completion. It accepts an optional
     string argument that is simply prepended to the default info if it
     doesn't contain a % character. If, however, the argument contains a %
     then the string is passed to the info method to control the format of
     the printed information. This can be used to achieve customized
     output from px. See the documentation of PDL::info for further
     details.

   The output of px will be determined by the default formatting string
that is passed to the info method (unless you pass a string containing %
to px when invoking as an instance method, see above). This default string
is stored in `$PDL::Dbg::Infostr' and the default output format can be
accordingly changed by setting this variable.  If you do this you should
also change the default title string that the class method branch prints
at the top of the listing to match your new format string. The default
title is stored in the variable `$PDL::Dbg::Title'.

   For historical reasons vars is an alias for px.

vars
----

BUGS
====

   There are probably some. Please report if you find any. Bug reports
should be sent to the PDL mailing list perldl@jachw.hawaii.edu.

AUTHOR
======

   Copyright(C) 1997 Christian Soeller (c.soeller@auckland.ac.nz).  All
rights reserved. There is no warranty. You are allowed to redistribute
this software / documentation under certain conditions. For details, see
the file COPYING in the PDL distribution. If this file is separated from
the PDL distribution, the copyright notice should be included in the file.

PDL changes between V1.0 and V2.0
*********************************

NAME
====

   PDL::Delta - PDL changes between V1.0 and V2.0

DESCRIPTION
===========

   This file is an attempt to list the major user-visible changes between
PDL versions 1.0 and 2.0.

Core Changes
============

Piddles are not hashes any more:
--------------------------------

     $a = zeroes 10,10;
     $$a{FOO} = "bar"

   doesn't work. They are currently scalar references (to opaque C
structures in finer terms) because of speed as well as syntactic issues.
If you want to have a hash, use

     $a->hdr()

   which returns a reference to an anonymous hash. Also, subclassing works
if you store a piddle in the hash member "PDL".

   There are also many core enhancements to support Dataflow and Slicing
tricks, but these do not introduce any incompatbilities.

Incompatible Changes vs 1.11
----------------------------

rgrep
     Order of the arguments has changed.

copy method
     No longer copies the header. This may not be a misfeature.

Documentation Changes
=====================

   Many of the base and library pods were updated.

SEE ALSO
========

   The Changes file for exhaustive details on what changed.

   The INSTALL file for how to build PDL.

   The README file for general stuff.

HISTORY
=======

   pdldelta was inspired by *perldelta*  man page in the perl 5.004
distribution.

support for PDL online documentation
************************************

NAME
====

   PDL::Doc - support for PDL online documentation

SYNOPSIS
========

     use PDL::Doc;
     $onlinedc = new PDL::Doc ($docfile);
     @match = $onlinedc->search('m/slice|clump/');

DESCRIPTION
===========

   An implementation of online docs for PDL.

PDL documentation conventions
=============================

   For a package like PDL that has *a lot* of functions it is very
desirable to have some form of online help to make it easy for the user to
remind himself of names, calling conventions and typical usage of the
multitude of functions at his disposal. To make it straightforward to
extract the relevant information from the POD documentation in source
files that make up the PDL distribution certain conventions have been
adopted in formatting this documentation.

   The first convention says that all documentation for PDL functions
appears in the POD section introduced by

     =head1 FUNCTIONS

   Individual functions in this section are introduced by

     =head2 funcname

   where signature is the argumentlist for a PP defined function as
explained in PDL/PP. Generally, PDL documentation is in
valid POD format (see Perlpod (perl.info)) but uses the
=for directive in a special way. The =for directive is used to flag to the
PDL Pod parser that information is following that will be used to generate
online help.

   The PDL podparser is derived from the PDL::Pod::Parser class that had
to be patched in a few places, partly to fix minor bugs, partly to enhance
functionality for perusal by PDL::Doc. Since the PDL::Doc module is still
experimental the patched Pod-Parser distribution is included with the
current PDL-Doc distribution. Note that PDL::Doc will not work correctly
with the released Pod-Parser distribution.

   The PDL Pod parser recognises the following =for directives:

Ref
     indicates that the one line reference for this function follows, e.g.,

          =for ref

          Returns a piddle of lags to parent.

Sig
     the signature for the current function follows, e.g.,

          =for sig

          Signature: (a(n), [o]b(), [t]tmp(n))

Usage
     an indication of the possible calling conventions for the current
     function, e.g.,

          =for usage

          wpic($pdl,$filename[,{ options... }])

Opt
     lists options for the current function, e.g.,

          =for options

          CONVERTER  => 'ppmtogif',   # explicitly specify pbm converter
          FLAGS      => '-interlaced -transparent 0',  # flags for converter
          IFORM      => 'PGM',        # explicitly specify intermediate format
          XTRAFLAGS  => '-imagename iris', # additional flags to defaultflags
          FORMAT     => 'PCX',        # explicitly specify output image format
          COLOR      => 'bw',         # specify color conversion
          LUT        => $lut,         # use color table information

Example
     gives examples of typical usage for the current function:

          =for example

          wpic $pdl, $file;
          $im->wpic('web.gif',{LUT => $lut});
          for (@images) {
            $_->wpic($name[0],{CONVERTER => 'ppmtogif'})
          }

Bad
     provides information on how the function handles bad values (if
     `$PDL:Config{WITH_BADVAL}' is set to 1). The intention is to have
     this information automatically created for pp-compiled functions,
     although it can be over-ridden.

   The PDL podparser is implemented as a simple state machine. Any of the
above =for statements switches the podparser into a state where the
following paragraph is accepted as information for the respective field
(Ref, Usage, Opt, Example or Bad).  Only the text up to the end of the
current paragraph is accepted, for example:

     =for example

     ($x,$y) = $a->func(1,3);  # this is part of the accepted info
     $x = func($a,0,1);        # this as well

     $x = func($a,$b);         # but this isn't

   To make the resulting pod documentation also easily digestible for the
existing pod filters (pod2man, pod2text, pod2html, etc) the actual
textblock of information must be separated from the =for directive by at
least one blank line. Otherwise, the textblock will be lost in the
translation process when the "normal" podformatters are used. The general
idea behind this format is that it should be easy to extract the
information for online documentation, automatic generation of a reference
card, etc but at the same time the documentation should be translated by
the standard podformatters without loss of contents (and without requiring
any changes in the existing POD format).

   The preceding explanations should be further explained by the following
example (extracted from PDL/IO/Misc/misc.pd):

     =head2 rcols()

     =for ref

     Read ASCII whitespaced cols from file into piddles efficiently.

     If no columns are specified all are assumed
     Will optionally only process lines matching a pattern.
     Can take file name or *HANDLE.

     =for usage

     Usage: ($x,$y,...) = rcols(*HANDLE|"filename", ["/pattern/",$col1, $col2,] ...)

     e.g.,

     =for example

     ($x,$y)    = rcols 'file1'
     ($x,$y,$z) = rcols 'file2', "/foo/",3,4
     $x = PDL->rcols 'file1';

     Note: currently quotes are required on the pattern.

   which is translated by, e.g, the standard `pod2text' converter into:

     rcols()

     Read ASCII whitespaced cols from file into piddles efficiently.

     If no columns are specified all are assumed Will optionally only
     process lines matching a pattern. Can take file name or *HANDLE.

     Usage: ($x,$y,...) = rcols(*HANDLE|"filename", ["/pattern/",$col1, $col2,] ...)

     e.g.,

     ($x,$y)    = rcols 'file1'
     ($x,$y,$z) = rcols 'file2', "/foo/",3,4
     $x = PDL->rcols 'file1';

     Note: currently quotes are required on the pattern.

   It should be clear from the preceding example that readable output can
be obtained from this format using the standard converters and the reader
will hopefully get a feeling how he can easily intersperse the special
=for directives with the normal POD documentation.

Which directives should be contained in the documentation
---------------------------------------------------------

   The module documentation should start with the

     =head1 NAME

     PDL::Modulename -- do something with piddles

   section (as anyway required by pod2man) since the PDL podparser
extracts the name of the module this function belongs to from that section.

   Each function that is not only for internal use by the module should be
documented, introduced with the =head2 directive in the `=head1 FUNCTIONS'
section. The only field that every function documented along these lines
should have is the Ref field preceding a one line description of its
intended functionality (suitable for inclusion in a concise reference
card). PP defined functions (see PDL/PP) should have a Sig
field stating their signature. To facilitate maintainance of this
documentation for such functions the 'Doc' field has been introduced into
the definition of `pp_def' (see again PDL/PP) which will
take care that name and signature of the so defined function are
documented in this way (for examples of this usage see, for example, the
PDL::Slices module, especially `slices.pd' and the resulting `Slices.pm').
Similarly, the 'BadDoc' field provides a means of specifying information
on how the routine handles the presence of bad values: this will be
autpmatically created if BadDoc is not supplied, or set to undef.

   Furthermore, the documentation for each function should contain at
least one of the Usage or Examples fields. Depending on the calling
conventions for the function under consideration presence of both fields
may be warranted.

   If a function has options that should be given as a hash reference in
the form

     {Option => Value, ...}

   then the possible options (and aproppriate values) should be explained
in the textblock following the `=for Opt' directive (see example above
and, e.g., PDL::IO::Pic).

   It is well possible that some of these conventions appear to be clumsy
at times and the author is keen to hear of any suggestions for better
alternatives.

INSTANCE METHODS
================

new
---

     $onlinedc = new PDL::Doc ('file.pdl',[more files]);

addfiles
--------

   add another file to the online database associated with this object.

outfile
-------

   set the name of the output file for this online db

ensuredb
--------

   Make sure that the database is slurped in

savedb
------

   save the database (i.e., the hash of PDL symbols) to the file associated
with this object.

gethash
-------

   Return the PDL symhash (e.g. for custom search operations)

search
------

   Search a PDL symhash

   Searching is by default case insensitive. Other flags can be given by
specifying the regexp in the form `m/regex/ismx' where / can be replaced
with any other non-alphanumeric character. $fields is an array reference
for all hash fields that should be matched against the regex. Valid fields
are

     Name,    # name of the function
     Module,  # module the function belongs to
     Ref,     # the one-line reference description
     Example, # the example for this function
     Opt,     # options
     File,    # the path to the source file this docs have been extracted from

scan
----

   Scan a source file using the PDL podparser to extract information for
online documentation

scantree
--------

   Scan whole directory trees for online documentation in `.pm' (module
definition) and `*.pod' (general documentation) files (using the
File::Find module).

funcdocs
--------

   extract the complete documentation about a function from its   source
file using the PDL::Pod::Parser filter.

FUNCTIONS
=========

BUGS
====

   Quite a few shortcomings which will hopefully be fixed following
discussions on the pdl-porters mailing list.

AUTHOR
======

   Copyright 1997 Christian Soeller <c.soeller@auckland.ac.nz> and Karl
Glazebrook <kgb@aaoepp.aao.gov.au> All rights reserved. There is no
warranty. You are allowed to redistribute this software / documentation
under certain conditions. For details, see the file COPYING in the PDL
distribution. If this file is separated from the PDL distribution, the
copyright notice should be included in the file.

commands for accessing PDL doc database from 'perldl' shell
***********************************************************

NAME
====

   PDL::Doc::Perldl - commands for accessing PDL doc database from
'perldl' shell

DESCRIPTION
===========

   This module provides a simple set of functions to access the PDL
documentation of database, for use from the *perldl* shell and the
*pdldoc* command-line program.

   Currently, multiple matches are not handled very well.

SYNOPSIS
========

     use PDL::Doc::Perldl; # Load all documenation functions

FUNCTIONS
=========

apropos
-------

   To find all the manuals that come with PDL, try

     apropos 'manual:'

   and to get quick info about PDL modules say

     apropos 'module:'

   You get more detailed info about a PDL function/module/manual with the
help function

usage
-----

     inner           inner prodcuct over one dimension
                     (Module PDL::Primitive)

     Signature: inner(a(n); b(n); [o]c(); )

sig
---

   The signature is the normal dimensionality of the functions arguments.
Calling with different dimensions causes 'threading' - see PDL::PP for
more details.

help
----

   In the case of multiple matches, the first command found is printed out,
and the remaining commands listed, along with the names of their modules.

badinfo
-------

   And has a horrible name.

PDL export control
******************

NAME
====

   PDL::Exporter - PDL export control

DESCRIPTION
===========

   Implements the standard conventions for import of PDL modules in to the
namespace

   Hopefully will be extended to allow fine control of which namespace is
used.

SYNOPSIS
========

   use PDL::Exporter;

     use PDL::MyModule;       # Import default function list ':Func'
     use PDL::MyModule '';    # Import nothing (OO)
     use PDL::MyModule '...'; # Same as Exporter

AUTHOR
======

   Copyright (C) Karl Glazebrook (kgb@aaoepp.aao.gov.au).  All rights
reserved. There is no warranty. You are allowed to redistribute this
software / documentation under certain conditions. For details, see the
file COPYING in the PDL distribution. If this file is separated from the
PDL distribution, the copyright notice should be included in the file.

Frequently asked questions about PDL
************************************

NAME
====

   PDL::FAQ - Frequently asked questions about PDL

VERSION
=======

   Current FAQ version:  0.6

DESCRIPTION
===========

   This is version  0.6 of the PDL FAQ, a collection of  frequently asked
questions about PDL - the Perl Data Language.

ABOUT THIS DOCUMENT
===================

Q: 1.1    Where to find this document
-------------------------------------

   You can find the latest version of this document at
http://pdl.perl.org/faq.html .  This FAQ will be monthly posted to the PDL
mailing list perldl@jach.hawaii.edu .

Q: 1.2    How to contribute to this document
--------------------------------------------

   This is a considerably reworked version of the PDL FAQ. As such many
errors might have crept in and many updates might not have made it in.
You are explicitly encouraged to let us know about questions which you
think should be answered in this document but currently aren't. Similarly,
if you think parts of this document are unclear, please tell the FAQ
maintainer about it. Where a specific answer is taken in full from
someone's posting the authorship should be indicated, let the FAQ
maintainer know if it isn't. For more general information explicit
acknowledgement is not made in the text, but rather there is an incomplete
list of contributors at the end of this docuement. Please contact the FAQ
maintainer if you feel hard done by.

   Send your comments, additions, suggestions or corrections to the PDL
mailing list at perldl@jach.hawaii.edu or to the FAQ maintainer Jarle
Brinchmann ( jarle@astro.ox.ac.uk ). See below for instructions on how to
join the mailing lists.

GENERAL QUESTIONS
=================

Q: 2.1    What is PDL ?
-----------------------

   PDL stands for * Perl Data  Language* . To say it with the words of
Karl Glazebrook, initiator of the PDL project:

     The PDL concept is to give standard perl5 the ability
        	to COMPACTLY store and SPEEDILY manipulate the large
        	N-dimensional data sets which are the bread and butter
        	of scientific computing. e.g. $a=$b+$c can add two
        	2048x2048 images in only a fraction of a second.

   It is hoped to eventually provide tons of useful functionality for
scientific and numeric analysis.

   For readers familiar with other scientific data evaluation packages it
may be helpful to add that PDL is in many respects similar to IDL, MATLAB
and similar packages. However, it tries to improve on a number of issues
which were perceived (by the authors of PDL) as shortcomings of those
existing packages.

Q: 2.2    Who supports PDL? Who develops it?
--------------------------------------------

   PDL is supported by its users. General informal support for PDL is
provided through the PDL mailing list ( perldl@jach.hawaii.edu , see
below).

   As a Perl extension (see below) it is devoted to the idea of free and
open development put forth by the Perl community. PDL was and is being
actively developed by a loosely knit group of people around the world who
coordinate their activities through the PDL development mailing list (
pdl-porters@jach.hawaii.edu , see below). If you would like to join in the
ongoing efforts to improve PDL please join this list.

Q: 2.3    Why yet another Data Language ?
-----------------------------------------

   There are actually several reasons and everyone should decide for
himself which are the most important ones:

   * PDL is " free software " . The authors of PDL think that this concept
     has several advantages: everyone has access to the sources - > better
     debugging, easily adaptable to your own needs, extensible for your
     purposes, etc... In comparison with commercial packages such as Matlab
     and IDL this is of considerable importance for workers who want to do
     some work at home and cannot afford the considerable cost to buy
     commercial packages for personal use.

   * PDL is based on a powerful and well designed scripting language:
     Perl. In contrast to other scientific/numeric data analysis languages
     it has been designed using the language features of a proven language
     instead of having grown into existence from scratch defining the
     control structures while features were added during development
     (leading to languages that often appear clumsy and badly planned for
     most existing packages with similar scope as PDL).

   * Using Perl as the basis a PDL programmer has all the powerful
     features of Perl at his hand, right from the start. This includes
     regular expressions, associative arrays (hashes), well designed
     interfaces to the operating system, network, etc. Experience has
     shown that even in mainly numerically oriented programming it is
     often extremely handy if you have easy access to powerful
     semi-numerical or completely non-numerical functionality as well. For
     example, you might want to offer the results of a complicated
     computation as a server process to other processes on the network,
     perhaps directly accepting input from other processes on the network.
     Using Perl and existing Perl extension packages things like this are
     no problem at all (and it all will fit into your " PDL script " ).

   * Extremely easy extensibility and interoperability as PDL is a Perl
     extension; development support for Perl extensions is an integral
     part of Perl and there are already numerous extensions to standard
     Perl freely available on the network.

   * Integral language features of Perl (regular expressions, hashes,
     object modules) immensely facilitated development and implementation
     of key concepts of PDL. One of the most striking examples for this
     point is probably PDL::PP (see below), a code
     generator/parser/pre-processor that generates PDL functions from
     concise descriptions.

   * None of the existing DLs follow the Perl language rules, which the
     authors firmly believe in:

        * TIMTOWTDI: There is more than one way to do it.  Minimalist
          languages are interesting for computer scientists, but for
          users, a little bit of redundancy makes things wildly easier to
          cope with and allows individual programming styles - just as
          people speak in different ways. For many people this will
          undoubtedly be a reason to avoid PDL ;)

        * Simple things are simple, complicated things possible: Things
          that are often done should be easy to do in the language,
          whereas seldom done things shouldn't be too cumbersome.

     All existing languages violate at least one of these rules.

   * As a project for the future PDL should be able to use super computer
     features, e.g. vector capabilities/parallel processing. This will
     probably be achieved by having PDL::PP (, see below) generate
     appropriate code on such architectures to exploit these features.

   * [ fill in your personal 111 favourite reasons here...]

Q: 2.4    What is PDL good for ?
--------------------------------

   Just in case you do not yet know what the main features of PDL are and
what one could do with them, here is a (necessarily selective) list of key
features:

   PDL is well suited for matrix computations, general handling of
multidimensional data, image processing, general scientific computation,
numerical applications. It supports I/O for many popular image and data
formats, 1D (line plots), 2D (images) and 3D (volume visualisation,
surface plots via OpenGL - for instance impelmented using Mesa), graphics
display capabilities and implements lots of numerical and semi-numerical
algorithms.

   Through the powerful pre-processor it is also easy to interface Perl to
your favourite C routines, more of that further below.

Q: 2.5    What is the connection between PDL and Perl ?
-------------------------------------------------------

   PDL is a Perl5 extension package. As such it needs an existing Perl5
installation (see below) to run. Furthermore, much of PDL is written in
perl (+ some core functionality that is written in C). PDL programs are
(syntactically) just perl scripts that happen to use some of the
functionality implemented by the package " PDL " ;

Q: 2.6    What do I need to run PDL on my machine ?
---------------------------------------------------

   Since PDL is just a Perl package you need first of all an installation
of Perl on your machine. As of this writing PDL requires version 5.004 of
Perl, version 5.004_4 or higher is * strongly* recommended. More
information on where and how to get a Perl installation can be found at
the Perl home page http://www.perl.com and at many CPAN sites (if you do
not know what * CPAN* is check the answer to the next question).

   To build PDL you also need a working C compiler and support for Xsubs
the package Extutils::MakeMaker.  See also http://pdl.perl.org/ports.html
for a list of machines where PDL has been tested. If you don't have a
compiler there might be a binary distribution availabe, see "Binary
distributions" below.

   If you can (or cannot) get PDL working on a new (previously
unsupported) platform we would like to hear about it. Please, report your
success/failure to the PDL mailing list at perldl@jach.hawaii.edu . We
will do our best to assist you in porting PDL to a new system.

Q: 2.7    Where do I get it?
----------------------------

   PDL is available as source distribution in the * Comprehensive Perl
Archive Network* , or CPAN.  This archive contains not only the PDL
distribution but also just about everything else that is Perl-related.
CPAN is mirrored by dozens of sites all over the world. The main site is
ftp://ftp.funet.fi . You can find a more local CPAN site by getting the
file /pub/languages/perl/CPAN/MIRRORS from ftp://ftp.funet.fi .
Alternatively, you can point your Web browser at http://www.perl.com and
use its CPAN multiplex service. Within CPAN you find the latest released
version of PDL in the directory CPAN/modules/by-module/PDL/. Another site
that has the latest PDL distribution is http://pdl.perl.org . Thanks to
the efforts of Frossie ( frossie@jach.hawaii.edu ) there is now a mirror
site in the US at http://www.jach.hawaii.edu/~frossie/pdl-mirror/

Q: 2.8    What do I have to pay to get PDL?
-------------------------------------------

   We are delighted to be able to give you the nicest possible answer on a
question like this: PDL is *free software* and all sources are publicly
available. But still, there are some copyrights to comply with. So please,
try to be as nice as we (the PDL authors) are and try to comply with them.

   Oh, before you think it is *completely* free: you have to invest some
time to pull the distribution from the net, compile and install it and
(maybe) read the manuals.

GETTING HELP/MORE INFORMATION
=============================

Q: 3.1    Where can I get information on PDL?
---------------------------------------------

   The complete PDL documentation is available with the PDL distribution.
If you have PDL installed on your machine and are on a unix like system
then you can read the PDL manuals with the ` man' command.  ` man
PDL::Intro' will lead the way to other PDL manual pages.  In any case
(i.e. also on non-unixes) ` perldoc PDL::Intro' should work.

   The easiest way by far, however, to get familiar with PDL is to use the
PDL online help facility from within the ` perldl' shell. Just type `
perldl' at your system prompt. Once you are inside the ` perldl' shell type
` help' .  Using the ` help' and ` apropos' commands inside the shell you
should be able to find the way round the documentation. Even better, you
can immediately try your newly acquired knowledge about PDL by issuing
PDL/perl commands directly at the command line. To illustrate this
process, here is the record of a typical perldl session of a PDL beginner
(lengthy output is only symbolically reproduced in braces ( < ... ...  >
)):

     unix> perldl
        	perldl> help
        	<.... help output ....>
        	perldl> help PDL::Impatient
        	<.... man page ....>
        	perldl> $a = pdl (1,5,7.3,1.0)
        	perldl> $b = sequence float, 4, 4
        	perldl> help inner
        	<.... help on the 'inner' function ....>
        	perldl> $c = inner $a, $b
        	perldl> p $c
        	[22.6 79.8 137 194.2]

   For further sources of information that are accessible through the
internet see next question.

Q: 3.2    Are there other PDL information sources on the internet?
------------------------------------------------------------------

   First of all, for all purely Perl-related questions there are tons of
sources on the net. A good point to start is http://www.perl.com .

   The PDL home site can be accessed by pointing your web browser to
http://pdl.perl.org . It has tons of goodies for anyone interested in PDL:

   * PDL distributions

   * Online documentation

   * Pointers to an HTML archive of the PDL mailing lists

   * A list of platforms on which PDL has been successfully tested.

   * News about recently added features, ported libraries, etc.

   * Name of the current pumpkin holders for the different PDL modules (if
     you want to know what that means you better had a look at the web
     pages).

   Thanks to the efforts of Frossie ( frossie@jach.hawaii.edu ) there is
now a mirror site in the US at
http://www.jach.hawaii.edu/~frossie/pdl-mirror/ If you are interested in
PDL in general you can join the PDL mailing list perldl@jach.hawaii.edu .
This is a forum to discuss programming issues in PDL, report bugs, seek
assistance with PDL related problems, etc. To subscribe, send a message to
perldl-request@jach.hawaii.edu containing a string in the following format:

     subscribe me@my.email.address

   where you should replace the string * me@my.email.address* with your
email address. Past messages can be retrieved in digest format by
anonymous ftp from ftp://ftp.jach.hawaii.edu/pub/ukirt/frossie/pdlp/ .  A
searchable archive and a hypertext version of the traffic on this list can
be found at http://www.xray.mpe.mpg.de/mailing-lists/perldl/ .

   If you are interested in all the technical details of the ongoing PDL
development you can join the PDL developers mailing list
pdl-porters@jach.hawaii.edu . To subscribe, send a message to
pdl-porters-request@jach.hawaii.edu containing a string in the following
format:

     subscribe me@my.email.address

   where you should replace the string * me@my.email.address* with your
email address. Past messages can be retrieved in digest format by
anonymous ftp from ftp://ftp.jach.hawaii.edu/pub/ukirt/frossie/pdlp/ .  A
searchable archive and a hypertext version of the traffic on this list can
be found at http://www.xray.mpe.mpg.de/mailing-lists/pdl-porters/ .

   Crossposting between these lists should be avoided unless there is a *
very* good reason for doing that.

Q: 3.3    What is the current version of PDL ?
----------------------------------------------

   As of this writing (FAQ version 0.6 of 01/06/2000 ) the latest released
version is 2.006 . The latest versions should always be available from a
CPAN mirror site near you (see above for info on where to get PDL).

   The most current version of PDL can be obtained from the CVS repository
see `""CVS availability of PDL""' in this node below.

Q: 3.4    I want to contribute to the further development of PDL. How can I help?
---------------------------------------------------------------------------------

   If you have a certain project in mind you should check if somebody else
is already working on it or if you could benefit from existing modules. Do
so by posting your planned project to the PDL developers mailing list at
pdl-porters@jach.hawaii.edu . To subscribe, send a message to
pdl-porters-request@jach.hawaii.edu containing a string in the following
format:

     subscribe me@my.email.address

   where you should replace the string * me@my.email.address* with your
email address.  You can also read past and current mails in the searchable
hypertext version of the mailing list at
http://www.xray.mpe.mpg.de/mailing-lists/pdl-porters/ . We are always
looking for people to write code and/or documentation ;).

Q: 3.5    I think I have found a bug in the current version of PDL. What shall I do?
------------------------------------------------------------------------------------

   First, make sure that the bug/problem you came across has not already
been dealt with somewhere else in this FAQ. Secondly, you can check the
searchable archive of the PDL mailing list at  whether this bug has
already been discussed. If you still haven't found any explanations you
can post a bug report to perldl@jach.hawaii.edu .

INSTALLATION
============

Q: 4.1    I have problems installing PDL. What shall I do?
----------------------------------------------------------

   First make sure you have read the file INSTALL in the distribution.
This contains a list of common problems which are unnecessary to repeat
here. Next, check the file perldl.conf to see if by editing the
configuration options in that file you will be able to successfully build
PDL. Some of the modules need additional software installed, please refer
to the file DEPENDENCIES for further details. Make sure to edit the
location of these packages in perldl.conf if you have them in non-standard
locations.

   If you would like to save an edited perldl.conf for future builds just
copy it as ~/.perldl.conf into your home directory where it will be picked
up automatically during the PDL build process.

   If you still can't make it work properly please submit a bug report
including detailed information on the problems you encountered to the
perldl mailing list ( perldl@jach.hawaii.edu , see also above). Response is
often rapid.

Q: 4.2    Are there configuration files for PDL I have to edit?
---------------------------------------------------------------

   Most users should not have to edit any configuration files manually.
However, in some cases you might have to supply some information about
akwardly placed include files/libraries or you might want to explicitly
disable building some of the optional PDL modules.  Check the files
INSTALL and perldl.conf for details.

   If you had to manually edit perldl.conf and are happy with the results
you can keep the file handy for future reference. Place it in
~/.perldl.conf where it will be picked up automatically or use ` perl
Makefile.PL  PDLCONF=your_file_name' next time you build PDL.

Q: 4.3    Do I need other software for successfull operation?
-------------------------------------------------------------

   For the basic PDL functionality you don't need any additional software.
However, some of the optional PDL modules included in the distribution
(notably most graphics and some I/O modules) require certain other
libraries/programs to be installed. Check the file DEPENDENCIES in the
distribution for details and directions on how to get these.

Q: 4.4   PDL compilation ends with ` Error:  PL_na not declared'  or similar
----------------------------------------------------------------------------

   You have probably upgraded perl to 5.6 and tried to recompile an old
version of PDL. The solution to this problem is to upgrade to a version ( >
2.005) which should have this fixed.

   If the latest version of PDL does not fix this problem for you, and you
have made sure your old installation is not interfering, you should post a
message to the mailing-list.

BINARY DISTRIBUTIONS
====================

Q: 4.5    What binary distributions are available?
--------------------------------------------------

   Information about binary distributions of PDL can be found on
http://pdl.perl.org .  At present there are binary distributions of PDL
for Linux (RedHat and Debian), FreeBSD and Windows. If someone is
interested in providing binary distributions for other architectures, that
would be very welcome. Let us know on the pdl-porters@jach.hawaii.edu
mailing list.

Q: 4.6    Does PDL run on Linux? (And what about packages?)
-----------------------------------------------------------

   Yes, PDL does run on Linux and indeed much of the development has been
done under Linux. On http://pdl.perl.org you can find links to Debian
packages, as well as the more actively updated RedHat packages. These
should also work with Mandrake, and can possibly be converted to Debian
using ` alien' .

Q: 4.7    Does PDL run under Windows?
-------------------------------------

   To some extent is probably the fairest answer. There is no official
effort to port PDL to Windows with each release of the software, and a
volunteering effort would be much appreciated. However a port of ( 2.001 )
does already exist thanks to Christian Soeller.  A main worry on Windows
platforms is the lack of a good graphics interface, any help with this
would be very welcome.

   It is also important to note that there is no distribution of PDL
through ActiveState's ppm. Such a compilation would be very welcome!

CVS AND ON-GOING DEVELOPMENT
============================

Q: 4.8    Can I get PDL via CVS?
--------------------------------

   Yes, as of December 1999, PDL is available at the CVS repository on
http://www.sourceforge.net . The tree is updated by developers who have
accounts on Sourceforge and snapshots of the tree are released regularly
by the pumpkin holder (the pumpking).

   If you wish to access the CVS repository and install PDL from there all
you need are two simple commands, however make sure you read some of the
documentation on Sourceforge as well for full information, but the basic
command is:

     cvs -d:pserver:anonymous@cvs.PDL.sourceforge.net:/cvsroot/PDL login
     cvs -z3 -d:pserver:anonymous@cvs.PDL.sourceforge.net:/cvsroot/PDL co PDL

   When prompted for a password just press the Enter key.  Note however
that the CVS tree is to be considered a development release and as such
you are very welcome to try it out, but it is not recommended for mission
critical use and might crash unexpectedly.

Q: 4.9  I had a problem with the CVS version, how do I check if  someone has submitted a patch?
-----------------------------------------------------------------------------------------------

   The Sourceforge system contains a patch-manager which contains patches
that have not yet been applied to the distribution. This can be accessed
by first accessing the Sourceforge web site and search for PDL. This will
show you the project page for PDL and will give you access to the Patch
manager.

   In addition, if you are not subscribing to the mailinglist, check the
archive of the ` pdl-porters' and ` perldl' mailing lists.

Q: 4.10    I have gotten developer access to CVS, but I have trouble  committing uploads.
-----------------------------------------------------------------------------------------

   The first you should do is to read the Sourceforge documentation and
learn the basics about CVS. But assuming you know this here is a quick
intro from Karl Glazebrook:

     Delete your entire CVS directory structure and START AGAIN
     (there is state)

     In a clean directory:

     setenv CVS_RSH          ssh
     setenv CVSROOT          kgb@cvs.PDL.sourceforge.net:/cvsroot/PDL

     cvs co PDL

     You will need to type your password. every time you issue a cvs
     command. there is no way around this if you use non-anon
     access and you can't mix the two.

     Howevery cvs committs will now work and write back to the server.

     You will continue to have to type your password until you upload
     a key to the sourcefourve web page. Once you have done this it
     becomes painless.

PDL JARGON
==========

Q: 5.1    What is threading (is PDL a newsreader) ?
---------------------------------------------------

   Unfortunately, in the context of PDL the term threading can have two
different (but related) meanings:

   * When mentioned in the INSTALL directions and possible during the
     build process we have the usual computer science meaning of
     multithreading in mind (useful mainly on multiprocessor machines or
     clusters)

   * PDL threading of operations on piddles (as mentioned in the indexing
     docs) is the iteration of a basic operation over appropriate
     subslices of piddles, e.g. the inner product ` inner $a, $b' of a (3)
     pdl ` $a' and a (3,5,4) pdl ` $b' results in a (5,4) piddle where each
     value is the result of an inner product of the (3) pdl with a (3)
     subslice of the (3,5,4) piddle.  For details check `"PDL::Indexing"'
     in this node

   PDL threading leads naturally to potentially parallel code which can
make use of multithreading on multiprocessor machines/networks; there you
have the connection between the two types of use of the term.

Q: 5.2    What is a piddle ` (;)'  ?
------------------------------------

   Well, PDL scalar variables (which are instances of a particular class
of perl objects, i.e. blessed thingies (see `"man perlobj"' in this node
)) are in common PDL parlance often called * piddles* (for example, check
the mailing list archives). Err, clear? If not, simply use the term *
piddle* when you refer to a PDL variable (an instance of a PDL object as
you might remember) regardless of what actual data the PDL variable
contains.

TECHNICAL QUESTIONS
===================

Q: 6.1    What is perldl?
-------------------------

   Sometimes perldl is used as a synonym for PDL. Strictly speaking,
however, the name perldl is reserved for the little shell that comes with
the PDL distribution and is supposed to be used for the interactive
prototyping of PDL scripts. For details check the perldl man page.

Q: 6.2    How do I get online help for PDL?
-------------------------------------------

   Just type ` help' (shortcut = "?") at the ` perldl' prompt and proceed
from there. Another useful command is the ` apropos' (shortcut = "??")
command.

   Also try the ` demo' command in the perldl shell if you are new to PDL.

MANIPULATION OF PIDDLES
=======================

Q: 6.3    I want to access the third element of a pdl but $a[2] doesn't work ?!
-------------------------------------------------------------------------------

   See answer to the next question why the normal perl array syntax doesn't
work for pdls.

Q: 6.4    The docs say pdls are some kind of array. But why doesn't the perl array syntax work with pdls then ?
---------------------------------------------------------------------------------------------------------------

   Ok, you are right in a way. The docs say that pdls can be thought of
arrays.  More specifically, it says ( `"PDL::Impatient"' in this node ):

     I find when using perlDL it is most useful to think of
     standard perl @x variables as "lists" of generic
     "things" and PDL variables like $x as
     "arrays" which can be contained in lists or
     hashes.

   So, while pdls can be thought of as some kind of multi-dimensional
array they are * not* arrays in the perl sense. Rather, from the point of
view of perl they are some special class (which is currently implemented
as an opaque pointer to some stuff in memory) and therefore need special
functions (or 'methods' if you are using the OO version) to access
individual elements or a range of elements. The functions/methods to check
are ` at' / ` set' (see `"the section 'Sections' in PDL::Impatient"' in
this node ) or the powerful ` slice' function and friends (see
`"PDL::Slices"' in this node and `"PDL::Indexing"' in this node ).

   Finally, to confuse you completely, you can have perl arrays of plds,
e.g. $spec[3] can refer to a pdl representing ,e.g, a spectrum, where
$spec[3] is the fourth element of the perl list (or array ;) ` @spec' .
This may be confusing but is very useful !

Q: 6.5    How do I concatenate piddles?
---------------------------------------

   Most people will try to form new piddles from old piddles using some
variation over the theme: ` $a =  pdl([$b, 0, 2])' , but this does not
work. The way to concatenate piddles is to use the function ` cat' .
Similarly you can split piddles using the command ` dog' .

Q: 6.6    Sometimes I am getting these strange results when using inplace  operations?
--------------------------------------------------------------------------------------

   This question is related to the ` inplace' function. From the
documentation (see `"PDL::Impatient"' in this node manpage):

     Most functions, e.g. log(), return a result which is
              a transformation of their argument. This makes for
              good programming practice. However many operations can
              be done "in-place" and this may be required when large
              arrays are in use and memory is at a premium. For these
              circumstances the operator inplace() is provided which
              prevents the extra copy and allows the argument to be
              modified. e.g.:

     $x = log($array);          # $array unaffected
              log( inplace($bigarray) ); # $bigarray changed in situ

   And also from the doc !!:

     Obviously when used with some functions which can
              not be applied in situ (e.g. convolve()) unexpected
              effects may occur!

   Check the list of PDL functions at the end of PDL.pod which points out
` inplace' -safe functions.

Q: 6.7    What is this strange usage of the string concatenation operator  ` .='  in PDL scripts?
-------------------------------------------------------------------------------------------------

   See next question on assignment in PDL.

Q: 6.8    Why are there two different kinds of assignment in PDL ?
------------------------------------------------------------------

   This is caused by the fact that currently the assignment operator ` ='
allows only restricted overloading. For some purposes of PDL it turned out
to be necessary to have more control over the overloading of an assignment
operator. Therefore, PDL peruses the operator ` .=' for certain types of
assignments.

Q: 6.9    How do I set a set of values in a piddle?
---------------------------------------------------

   With versions of Perl prior to 5.6 this has to be done using a
temporary variable.

     perldl> $a = sequence(5); p $a
                    [0 1 2 3 4]
     perldl> $tmp = $a->slice('1:2'); p $tmp;
                    [1 2]
                    perldl> $tmp .= pdl([5, 6]);    # Note .= !!
     perldl> p $a
                    [0 5 6 3 4]

   This can also be made into one expression, which is often seen in PDL
code:

     perldl> ($tmp = $a->slice('1:2')) .= pdl([5,6])
     perldl> p $a
                    [0 5 6 3 4]

   In Perl 5.6 this assignment can be simplified using lvalue subroutines,
and this will be incorporated into PDL when 5.6 is more widespread.

Q: 6.10    Can I use a piddle in a conditional expression?
----------------------------------------------------------

   Yes you can, but not in the way you probably tried first. It is not
possible to use a piddle directly in a conditional expression since this
is usually poorly defined. Instead PDL has two very useful functions: `
any' and ` all' . Use these to test if any or all elements in a piddle
fulfils some criterion:

     perldl> $a=pdl ( 1, -2, 3);
     perldl> print '$a has at least one element < 0' if (any $a < 0);
     $a has at least one element < 0

     perldl> print '$a is not positive definite' unless (all $a > 0);
     $a is not positive definite

Q: 6.11    Logical operators and piddles -  '||' and ' & & ' doesn't work!
--------------------------------------------------------------------------

   It is a common problem that you try to make a mask array or something
similar using a construct such as

     $mask = which($piddle > 1 && $piddle < 2);

   This * does not* work! What you are looking for is the * bitwise*
logical operators '|' and ' & ' which work on an element-by-element basis.
So it is really very simple: Do not use logial operators on multi-element
piddles since that really doesn't make sense, instead write the example as:

     $mask = which($piddle > 1 & $piddle < 2);

   which works correctly.

ADVANCED TOPICS
===============

Q: 6.12    What is a null pdl ?
-------------------------------

   ` null' is a special token for 'empty piddle'. A null pdl can be used
to flag to a PDL function that it should create an appropriately sized and
typed piddle.  * Null* piddles can be used in places where a PDL function
expects an * output* or * temporary* argument.  * Output* and * temporary*
arguments are flagged in the * signature* of a PDL function with the `
[o]' and ` [t]' qualifiers (see next question if you don't know what the *
signature* of a PDL function is).  For example, you can invoke the `
sumover' function as follows:

     sumover $a, $b=null;

   which is equivalent to

     $b = sumover $a;

   If this seems still a bit murky check `"PDL:Indexing"' in this node and
`"PDL::PP"' in this node for details about calling conventions, the *
signature* and * threading* (see also below).

Q: 6.13    What is the signature of a PDL function ?
----------------------------------------------------

   The * signature* of a function is an important concept in PDL.  Many
(but not all) PDL function have a * signature* which specifies the
arguments and their (minimal) dimensionality. As an example, look at the
signature of the ` maximum' function:

     'a(n); [o] b;'

   this says that ` maximum' takes two arguments, the first of which is
(at least) one-dimensional while the second one is zero-dimensional and an
* output* argument (flagged by the ` [o]' qualifier). If the function is
called with pdls of higher dimension the function will be repeatedly
called with slices of these pdls of appropriate dimension(this is called *
threading* in PDL).

   For details and further explanations consult `"PDL::Indexing"' in this
node and `"PDL::PP"' in this node .

Q: 6.14    How can I subclass (inherit from) piddles?
-----------------------------------------------------

   The short answer is: read `"PDL::Objects"' in this node (e.g. type `
help PDL::Objects' in the * perldl* shell).

   The longer answer (extracted from `"PDL::Objects"' in this node ):
Since a PDL object is an opaque reference to a C struct, it is not
possible to extend the PDL class by e.g. extra data via subclassing (as
you could do with a hash based perl object).  To circumvent this problem
PDL has built-in support to extent the PDL class via the * has-a* relation
for blessed hashes. You can get the * HAS-A* behave like * IS-A* simply in
that you assign the PDL object to the attribute named ` PDL' and redefine
the method initialize(). For example:

     package FOO;

     @FOO::ISA = qw(PDL);
              sub initialize {
              my $class = shift;
              my $self = {
              creation_time => time(),  # necessary extension :-)
              PDL => PDL->null,         # used to store PDL object
              };
              bless $self, $class;
              }

   For another example check the script t/subclass.t in the PDL
distribution.

Q: 6.15    What on earth is this dataflow stuff ?
-------------------------------------------------

   Dataflow is an experimental project that you don't need to concern
yourself with (it should not interfere with your usual programming).
However, if you want to know, have a look at `"PDL::Dataflow"' in this
node . There are applications which will benefit from this feature (and it
is already at work behind the scenes).

Q: 6.16    What is PDL::PP?
---------------------------

   Simple answer: PDL::PP is both a glue between external libraries and
PDL and a concise language for writing PDL functions.

   Slightly longer answer: PDL::PP is used to compile very concise
definitions into XSUB routines implemented in C that can easily be called
from PDL and which automatically support threading, dataflow and other
things without you having to worry about it.

   For further details check `"PDL::PP"' in this node and the section on
"Extensions of PDL".

Q: 6.17    What happens when I have several references to the same PDL object in different variables (cloning, etc?) ?
----------------------------------------------------------------------------------------------------------------------

   Piddles behave like perl references in many respects. So when you say

     $a = pdl [0,1,2,3];
              $b = $a;

   then both $b and $a point to the same object, e.g. then saying

     $b++;

   will *not* create a copy of the original piddle but just increment in
place, of which you can convince yourself by saying

     print $a;
              [1 2 3 4]

   This should not be mistaken for dataflow which connects several
*different* objects so that data changes are propagated between the so
linked piddles (though, under certain circumstances, dataflown piddles can
share physically the same data).

   It is important to keep the " reference nature " of piddles in mind
when passing piddles into subroutines. If you modify the input pdls you
modify the original argument, * not* a copy of it. This is different from
some other array processing languages but makes for very efficient passing
of piddles between subroutines. If you do not want to modify the original
argument but rather a copy of it just create a copy explicitly (this
example also demonstrates how to properly check for an * explicit* request
to process inplace, assuming your routine can work inplace):

     sub myfunc {
              my $pdl = shift;
              if ($pdl->is_inplace)
              {$pdl->set_inplace(0)}
              else  # modify a copy by default
              {$pdl = $pdl->copy}
              $pdl->set(0,0);
              return $pdl;
              }

MISCELLANEOUS
=============

Q: 6.18    What I/O formats are supported by PDL ?
--------------------------------------------------

   The current versions of PDL already support quite a number of different
I/O formats. However, it is not always obvious which module implements
which formats. To help you find the right module for the format you
require, here is a short list of the current list of I/O formats and a
hint in which module to find the implementation:

   * A home brew fast raw (binary) I/O format for PDL is implemented by the
     FastRaw module

   * The FlexRaw module implements generic methods for the input and
     output of `raw' data arrays.  In particular, it is designed to read
     output from FORTRAN 77 UNFORMATTED files and the low-level C write
     function, even if the files are compressed or gzipped.

     It is possible that the FastRaw functionality will be included in the
     FlexRaw module at some time in the future.

   * FITS I/O is implemented by the wfits/rfits functions in PDL::IO::Misc.

   * Ascii file I/O in various formats can be achieved by using the `
     rcols' and ` rgrep' functions, also in PDL::IO::Misc.

   * PDL::IO::Pic implements an interface to the netpbm/pbm+ filters to
     read/write several popular image formats; also supported is output of
     image sequences as MPEG movies.

   * On CPAN you can find the PDL-NetCDF module that works with the current
     released version of PDL 2.004.

   For further details consult the documentation in the individual modules.

Q: 6.19    How can I stack a set of 2D arrays (images) into a 3D piddle?
------------------------------------------------------------------------

   Assuming all arrays are of the same size and in some format recognised
by rpic (see `"PDL::IO::Pic"' in this node ) you could say:

     use PDL::IO::Pic;
              @names = qw/name1.tif .... nameN.tif/;  # some file names
              $dummy = PDL->rpic($names[0]);
              $cube = PDL->zeroes($dummy->type,$dummy->dims,$#names+1); # make 3D piddle
              for (0..$#names)
              {($tmp = $cube->slice(":,:,($_)")) .= PDL->rpic($names[$_])}

   The for loop reads the actual images into a temporary 2D piddle whose
values are then assigned (using the overloaded ` .=' operator) to the
approriate slices of the 3D piddle ` $cube' .

Q: 6.20    Where are testfiles for the graphics modules?
--------------------------------------------------------

   This answer applies mainly to PDL::Graphics::TriD (PDL's device
independent 3D graphics model) which is the trickiest one in this respect.
You find some test scripts in Demos/TriD in the distribution. After you
have built PDL just change to that directory and try

     perl -Mblib <testfile>

   where ` < testfile '> ; should match the pattern ` test[0-9].p' and
watch the results. Some of the tests should bring up a window where you
can control (twiddle) the 3D objects with the mouse. Try using MB1 for
turning the objects in 3D space and MB3 to zoom in and out.

   If you have a VRML viewer plugin for netscape you can also try `
tvrml*.p' for PDL generated dynamic VRML.

   Some demos of 3D graphics with PDL can also be invoked using the `
demo' command within the perldl shell.

Q: 6.21    What is TriD or PDL::TriD or PDL::Graphics::TriD?
------------------------------------------------------------

   Questions like this should be a thing of the past with the PDL online
help system in place. Just try (after installation):

     un*x> perldl
              perldl> apropos trid

   Check the output for promising hits and then try to look up some of
them, e.g.

     perldl> help PDL::Graphics::TriD

   Note that case matters with ` help' but not with ` apropos' .

EXTENSIONS OF PDL
=================

Q: 7.1    I am looking for a package to do XXX in PDL. Where shall I look for it?
---------------------------------------------------------------------------------

   The first stop is again ` perldl' or the PDL documentation. There is
already a lot of functionality in PDL which you might be aware of. The
easiest way to look for functionality is to use the ` apropos' command:

     perldl> apropos 'integral'
     ceil            Round to integral values in floating-point format
     floor           Round to integral values in floating-point format
     intover         Project via integral to N-1 dimensions
     rint            Round to integral values in floating-point format

   Since the apropos command is no sophisticated search engine make sure
that you search on a couple of related topics and use short phrases.

   However there is a good chance that what you need is not part of the
PDL distribution. You are then well advised to check out
http://pdl.perl.org where there is a list of packages using PDL. If that
does not solve your problem, ask on the mailing-list, if nothing else you
might get assistance which will let you interface your package with PDL
yourself, see also the next question.

Q: 7.2   Can I access my C/Fortran library routines in  PDL?
------------------------------------------------------------

   Yes, you can, in fact it is very simple for many simple applications.
What you want is the PDL pre-prosessor PP ( `"PDL::PP"' in this node ).
This will allow you to make a simple interface to your C routine.

   The two functions you need to learn (at least first) are ` pp_def'
which defines the calling interface to the function, specifying input and
output parameters, and contains the code that links to the external
library. The other command is ` pp_end' which finishes the PP definitions.
For details see the `"PDL::PP"' in this node man-page, but we also have a
worked example here.

     double eight_sum(int n)
        {
             int i;
             double sum, x;
          sum = 0.0; x=0.0;
             for (i=1; i<=n; i++) {
               x++;
               sum += x/((4.0*x*x-1.0)*(4.0*x*x-1.0));
             }
             return 1.0/sum;
        }

   We will here show you an example of how you interface C code with PDL.
This is the first example and will show you how to approximate the number
8...

   The C code is shown above and is a simple function returning a double,
and expecting an integer - the number of terms in the sum - as input. This
function could be defined in a library or, as we do here, as an inline
function.

   We will postpone the writing of the Makefile till later. First we will
construct the ` .pd' file. This is the file containing PDL::PP code. We
call this ` eight.pd' .

     #
        # pp_def defines a PDL function.
        #
        pp_addhdr (
        '
        double eight_sum(int n)
        {
          int i;
          double sum, x;
       sum = 0.0; x=0.0;
          for (i=1; i<=n; i++) {
            x++;
            sum += x/((4.0*x*x-1.0)*(4.0*x*x-1.0));
           }
          return 1.0/sum;
     }
        ');

     pp_def (
                'eight',
        	Pars => 'int a(); double [o]b();',
                Code => '$b()=eight_sum($a());'
               );
     # Always make sure that you finish your PP declarations with
        # pp_done
     pp_done();

   A peculiarity with our example is that we have included the entire code
with ` pp_addhdr' instead of linking it in. This is only for the purposes
of example, in a typical application you will use ` pp_addhdr' to include
header files. Note that the argument to ` pp_addhdr' is enclosed in quotes.

   What is most important in this example is however the ` pp_def'
command. The first argument to this is the name of the new function *
eight * , then comes a hash which the real meat:

   * This gives the input parameters (here ` a' ) and the output
     parameters (here ` b' ).  The latter are indicated by the ` [o]'
     specifier. Both arguments can have a type specification as shown here.

     Many variations and further flexibility in the interface can be
     specified. See the manpage for details.

   * This switch contains the code that should be executed. As you can see
     this is a rather peculiar mix of C and Perl, but essentially it is
     just as you would write it in C, but the variables that are passed
     from PDL are treated differently and have to be referred to with a
     preceding '$'.

     There are also simple macros to pass pointers to data and to obtain
     the values of other Perl quantities, see the manual page for further
     details.

   Finally note the call to ` pp_done()' at the end of the file. This is
necessary in all PP files.

   Ok. So now we have a file with code that we dearly would like to use in
Perl via PDL. To do this we need to compile the function, and to do that
we need a Makefile.

     use PDL::Core::Dev;
        use ExtUtils::MakeMaker;
        PDL::Core::Dev->import();
     $package = ["eight.pd",Eight,PDL::Eight];
        %hash = pdlpp_stdargs($package);
     WriteMakefile( %hash );
     sub MY::postamble {pdlpp_postamble($package)};

   The code above should go in a file called Makefile.PL, which should
subsequently be called in  the standard Perl way: ` perl Makefile.PL' .
This should give you a Makefile and running ` make' should compile the
module for you and ` make install' will install it for you.

Q: 7.3    How can I interface package XXX in PDL?
-------------------------------------------------

   This question is closely related to the previous one, and as we said
there, the `"PDL::PP"' in this node pre-processor is the standard way of
interfacing external packages with PDL. The most usual way to use PDL::PP
is to write a short interface routine, see the `"PDL::PP"' in this node
manpage and the answer to the previous question for examples.

   However it is also possible to interface a package to PLD by re-writing
your function in PDL::PP directly. This can be convenient in certain
situations, in particular if you have a routine that expects a function as
input and you would like to pass the function a Perl function for
convenience.

   The `"PDL::PP"' in this node manpage is the main source of information
for writing PDL::PP extensions, but it is very useful to look for files in
the distribution of PDL as many of the core functions are written in
PDL::PP. Look for files that end in ` .pd' which is the generally accepted
suffix for PDL::PP files. But we also have a simple example here

   The following example will show you how to write a simple function that
automatically allows threading. To make this concise the example is of an
almost trivial function, but the intention is to show the basics of
writing a PDL::PP interface.

   We will write a simple function that calculates the minimum, maximum
and average of a piddle. On my machine the resulting function is 8 times
faster than the built-in function ` stats' (of course the latter also
calculates the median).

   Let's jump straight in. Here is the code (from a file called `
quickstats.pd' )

     #
        pp_def('quickstats',
        	Pars => 'a(n); [o]avg(); [o]max(); [o]min()',
        	Code => '$GENERIC(a) curmax, curmin;
        	         $GENERIC(a) tmp=0;
                         loop(n) %{
                           tmp += $a();
                           if (!n || $a() > curmax) { curmax = $a();}
                           if (!n || $a() < curmin) { curmin = $a();}
                         %}
                         $avg() = tmp/$SIZE(n);
        	         $max() = curmax;
        	         $min() = curmin;
                        '
        	);
     pp_done();

   The above might look like a confusing mixture of C and Perl, but behind
the peculiar syntax lies a very powerful language. Let us take it line by
line.

   The first line declares that we are starting the definition of a PDL:PP
function called ` quickstats' .

   The second line is very important as it specifies the input and output
parameters of the function.  ` a(n)' tells us that there is one input
parameter that we will refer to as ` a' which is expected to be a vector of
length n (likewise matrices, both square and rectangular would be written
as ` a(n,n)' and ` a(n,m)' respectively). To indicate that something is an
output parameter we put ` [o]' in front of their names, so referring back
to the code we see that avg, max and min are three output parameters, all
of which are scalar (since they have no dimensional size indicated.

   The third line starts the code definition which is essentially pure C
but with a couple of convenient functions.  ` $GENERIC' is a function that
returns the C type of its argument - here the input parameter a. Thus the
first two lines of the code section are variable declarations.

   The ` loop(n)' construct is a convenience function that loops over the
dimension called n in the parameter section. Inside this loop we calculate
the cumulative sum of the input vector and keep track of the maximum and
minimum values. Finally we assign the resulting values to the output
parameters.

   Finally we finish our function declaration with ` pp_done()' .

   To compile our new function we need to create a Makefile, which we will
just list since its creation is discussed in an earlier question.

     use PDL::Core::Dev;
        use ExtUtils::MakeMaker;
        PDL::Core::Dev->import();
     $package = ["quickstats.pd",Quickstats,PDL::Quickstats];
        %hash = pdlpp_stdargs($package);
     WriteMakefile( %hash );
     sub MY::postamble {pdlpp_postamble($package)};

   An example Makefile.PL

   Our new statistic function should now compile using the tried and
tested perl way: ` perl  Makefile.PL; make' .

   You should experiment with this function, changing the calculations and
input and output parameters. In conjunction with the PDL::PP manpage this
should allow you to quickly write more advanced routines directly in
PDL::PP.

THE WHO WHEN WHAT
=================

CHANGES
=======

   *        * markers for alpha stage functionality removed

        * restructured description

        * development/support of PDL

        * PDL and online help

        * subclassing piddles

        * new INSTALLATION section

        * how to stack 2D piddles - > 3D piddle

        * questions regarding TriD

   *        * use of perl5.004 is now required

        * PDL I/O formats

        * piddles behave like perl references

        * null PDL's and output arguments

        * signature

   *        * questions about pdls and perl array syntax

        * added requirement for C compiler in answer to 'what machines...'
          question

        * PDL jargon section

        * piddles

   *        * upgraded released/alpha version numbers

        * added another WYANDL reason

        * split into perldl/pdl-porters mailing lists

   *        * initial revision

BUGS
====

   If you find any inaccuracies in this document (or disfunctional URLs)
please report to the perldl mailing list perldl@jach.hawaii.edu or to the
current FAQ maintainer Jarle Brinchmann ( jarle@astro.ox.ac.uk ).

ACKNOWLEDGEMENTS
================

   Achim Bohnet ( ach@mpe.mpg.de ) for suggesting CoolHTML as a
prettypodder (although we have switched to XML now) and various other
improvements. Suggestions for some questions were taken from Perl Faq and
adapted for PDL.

CONTRIBUTORS
============

   Many people have contributed or given feedback on the current version
of the FAQ, here is an incomplete list of individuals whose contributions
or posts to the mailing-list have improved this FAQ at some point in time
alphabetically listed by first name: Christian Soeller, Doug Burke, Doug
Hunt, Frank Schmauder, Jarle Brinchmann, John Cerney, Karl Glazebrook,
Kurt Starsinic, Thomas Yengst, Tuomas J. Lukka.

AUTHOR AND COPYRIGHT
====================

   This document emerged from a joint effort of several PDL developers
(Karl Glazebrook ( kgb@aaoepp.aao.gov.au ), Tuomas J. Lukka ( lukka@iki.fi
), Christian Soeller ( c.soeller@auckland.ac.nz )) to compile a list of the
most frequently asked questions about PDL with answers.  Permission is
granted for verbatim copying (and formatting) of this material as part of
PDL. Permission is explicitly not granted for distribution in book or any
corresponding form. Email the current FAQ maintainer Jarle Brinchmann (
jarle@astro.ox.ac.uk ) or ask on the PDL mailing list
perldl@jach.hawaii.edu if some of the issues covered in here are unclear.

FFTs for PDL
************

NAME
====

   PDL::FFT - FFTs for PDL

DESCRIPTION
===========

   FFTs for PDL.  These work for arrays of any dimension, although ones
with small prime factors are likely to be the quickest.

   Each routine works `inplace'.

SYNOPSIS
========

     use PDL::FFT qw/:Func/;

     fft($real,$imag);
     ifft($real,$imag);
     realfft($real);
     realifft($real);

     fftnd($real,$imag);
     ifftnd($real,$imag);

     $kernel = kernctr($image,$smallk);
     fftconvolve($image,$kernel);

ALTERNATIVE FFT PACKAGES
========================

   Various other modules - such as `PDL::FFTW|PDL::FFTW' in this node and
`PDL::Slatec|PDL::Slatec' in this node - contain FFT routines.  However,
unlike PDL::FFT, these modules are optional, and so may not be installed.

FUNCTIONS
=========

fft
---

ifft
----

realfft()
---------

   The real part of the transform ends up in the first half of the array
and the imaginary part of the transform ends up in the second half of the
array.

realifft()
----------

fftnd()
-------

ifftnd()
--------

fftconvolve()
-------------

   fftconvolve works inplace, and returns an error array in kernel as an
accuracy check - all the values in it should be negligible.

   The sizes of the image and the kernel must be the same.  `kernctr|' in
this node centres a small kernel to emulate the behaviour of the direct
convolution routines.

   The speed cross-over between using straight convolution
(`PDL::Image2D::conv2d()|PDL::Image2D' in this node) and these fft
routines is for kernel sizes roughly 7x7.

kernctr()
---------

   kernctr centres a small kernel to emulate the behaviour of the direct
convolution routines.

convmath
--------

cmul
----

cdiv
----

BUGS
====

   Where the source is marked `FIX', could re-implement using phase-shift
factors on the transforms and some real-space bookkeeping, to save some
temporary space and redundant transforms.

AUTHOR
======

   This file copyright (C) 1997, 1998 R.J.R. Williams
(rjrw@ast.leeds.ac.uk), Karl Glazebrook (kgb@aaoepp.aao.gov.au), Tuomas J.
Lukka, (lukka@husc.harvard.edu).  All rights reserved. There is no
warranty. You are allowed to redistribute this software / documentation
under certain conditions. For details, see the file COPYING in the PDL
distribution. If this file is separated from the PDL distribution, the
copyright notice should be included in the file.

Linear predictive filtering
***************************

NAME
====

   PDL::Filter::LinPred - Linear predictive filtering

SYNOPSIS
========

     $a = new PDL::Filter::LinPred(
     	{NLags => 10,
     	 LagInterval => 2,
     	 LagsBehind => 2,
     	 Data => $dat});

     ($pd,$corrslic) = $a->predict($dat);

DESCRIPTION
===========

   A filter by doing linear prediction: tries to predict the next value in
a data stream as accurately as possible. The filtered data is the
predicted value. The parameters are

NLags
     Number of time lags used for prediction

LagInterval
     How many points each lag should be

LagsBehind
     If, for some strange reason, you wish to predict not the next but the
     one after that (i.e. usually f(t) is predicted from f(t-1) and f(t-2)
     etc., but with LagsBehind => 2, f(t) is predicted from f(t-2) and
     f(t-3)).

Data
     The input data, which may contain other dimensions past the first
     (time).  The extraneous dimensions are assumed to represent epochs so
     the data is just concatenated.

AutoCovar
     As an alternative to Data, you can just give the temporal
     autocorrelation function.

Smooth
     Don't do prediction or filtering but smoothing.

   The method *predict* gives a prediction for some data plus a
corresponding slice of the data, if evaluated in list context. This slice
is given so that you may, if you wish, easily plot them atop each other.

   The rest of the documentation is under lazy evaluation.

AUTHOR
======

   Copyright (C) Tuomas J. Lukka 1997.  All rights reserved. There is no
warranty. You are allowed to redistribute this software / documentation
under certain conditions. For details, see the file COPYING in the PDL
distribution. If this file is separated from the PDL distribution, the
copyright notice should be included in the file.

linear filtering for PDL
************************

NAME
====

   PDL::Filter::Linear - linear filtering for PDL

SYNOPSIS
========

     $a = new PDL::Filter::Linear(
     	{Weights => $v,
     	 Point => 10});

     $b = new PDL::Filter::Gaussian(15,2); # 15 points, 2 std devn.

     ($pred,$corrslic) = $a->predict($dat);

DESCRIPTION
===========

   A wrapper for generic linear filters.  Just for convenience. This
should in the future use DataPresenter.

   Also, this class should at some point learn to do FFT whenever it is
useful.

routines for fitting gaussians
******************************

NAME
====

   PDL::Fit::Gaussian - routines for fitting gaussians

DESCRIPTION
===========

   This module contains some custom gaussian fitting routines.  These were
developed in collaboration with Alison Offer, they do a reasonably robust
job and are quite useful.

   Gaussian fitting is something I do a lot of, so I figured it was worth
putting in my special code.

   Note this code is also used in the Karma package.

SYNOPSIS
========

     use PDL::Fit::Gaussian;
     ($cen, $pk, $fwhm, $back, $err, $fit) = fitgauss1d($x, $data);
     ($pk, $fwhm, $back, $err, $fit) = fitgauss1dr($r, $data);

FUNCTIONS
=========

fitgauss1d
----------

   Fit's a 1D Gaussian robustly free parameters are the centre, peak
height, FWHM. The background is NOT fit, because I find this is generally
unreliable, rather a median is determined in the 'outer' 10% of pixels
(i.e. those at the start/end of the data piddle). The initial estimate of
the FWHM is the length of the piddle/3, so it might fail if the piddle is
too long. (This is non-robust anyway). Most data does just fine and this
is a good default gaussian fitter.

   SEE ALSO: fitgauss1dr() for fitting radial gaussians

fitgauss1dr
-----------

   Fit's a 1D radial Gaussian robustly free parameters are the peak height,
FWHM. Centre is assumed to be X=0 (i.e. start of piddle).  The background
is NOT fit, because I find this is generally unreliable, rather a median
is determined in the 'outer' 10% of pixels (i.e. those at the end of the
data piddle). The initial estimate of the FWHM is the length of the
piddle/3, so it might fail if the piddle is too long. (This is non-robust
anyway). Most data does just fine and this is a good default gaussian
fitter.

   SEE ALSO: fitgauss1d() to fit centre as well.

BUGS
====

   May not converge for weird data, still pretty good!

AUTHOR
======

   This file copyright (C) 1999, Karl Glazebrook (kgb@aaoepp.aao.gov.au),
Gaussian fitting code by Alison Offer (aro@aaocbn.aao.gov.au).  All rights
reserved. There is no warranty. You are allowed to redistribute this
software / documentation under certain conditions. For details, see the
file COPYING in the PDL distribution. If this file is separated from the
PDL distribution, the copyright notice should be included in the file.

Levenber-Marquardt fitting routine for PDL
******************************************

NAME
====

   PDL::Fit::LM - Levenber-Marquardt fitting routine for PDL

DESCRIPTION
===========

   This module provides fitting functions for PDL. Currently, only
Levenberg-Marquardt fitting is implemented. Other procedures should be
added as required. For a fairly concise overview on fitting see Numerical
Recipes, chapter 15 "Modeling of data".

SYNOPSIS
========

     use PDL::Fit::LM;
     $ym = lmfit $x, $y, $sig, \&expfunc, $a, {Maxiter => 300};

FUNCTIONS
=========

lmfit
-----

   Options:

   The user supplied sub routine reference should accept 4 arguments

   * a vector of independent values $x

   * a vector of fitting parameters

   * a vector of dependent variables that will be assigned upon return

   * a matrix of partial derivatives with respect to the fitting parameters
     that will be assigned upon return

   As an example take this definition of a single exponential with 3
parameters (width, amplitude, offset):

     sub expdec {
       my ($x,$par,$ym,$dyda) = @_;
       my ($a,$b,$c) = map {$par->slice("($_)")} (0..2);
       my $arg = $x/$a;
       my $ex = exp($arg);
       $ym .= $b*$ex+$c;
       my (@dy) = map {$dyda->slice(",($_)")} (0..2);
       $dy[0] .= -$b*$ex*$arg/$a;
       $dy[1] .= $ex;
       $dy[2] .= 1;
     }

   Note usage of the `.=' operator for assignment

   In scalar context returns a vector of the fitted dependent variable. In
list context returns fitted y-values, vector of fitted parameters, an
estimate of the covariance matrix (as an indicator of goodness of fit) and
number of iterations performed.

tlmfit
------

   Signature:

   a threaded version of lmfit by using perl threading. Direct threading
in lmfit seemed difficult since we have an if condition in the iteration.
In principle that can be worked around by using where but .... Send a
threaded lmfit version if you work it out!

   Since we are using perl threading here speed is not really great but it
is just convenient to have a threaded version for many applications (no
explicit for-loops required, etc). Suffers from some of the current
limitations of perl level threading.

BUGS
====

   Not known yet.

AUTHOR
======

   This file copyright (C) 1999, Christian Soeller
(c.soeller@auckland.ac.nz).  All rights reserved. There is no warranty.
You are allowed to redistribute this software documentation under certain
conditions. For details, see the file COPYING in the PDL distribution. If
this file is separated from the PDL distribution, the copyright notice
should be included in the file.

routines for fitting data with linear combinations of functions.
****************************************************************

NAME
====

   PDL::Fit::Linfit - routines for fitting data with linear combinations
of functions.

DESCRIPTION
===========

   This module contains routines to perform general curve-fits to a set
(linear combination) of specified functions.

   Given a set of Data:

     (y0, y1, y2, y3, y4, y5, ...ynoPoints-1)

   The fit routine tries to model y as:

     y' = beta0*x0 + beta1*x1 + ... beta_noCoefs*x_noCoefs

   Where x0, x1, ... x_noCoefs, is a set of functions (curves) that the
are combined linearly using the beta coefs to yield an approximation of
the input data.

   The Sum-Sq error is reduced to a minimum in this curve fit.

   *Inputs:*

$data
     This is your data you are trying to fit. Size=n

$functions
     2D array. size (n, noCoefs). Row 0 is the evaluation of function x0
     at all the points in y. Row 1 is the evaluation of of function x1 at
     all the points in y, ... etc.

     Example of $functions array Structure:

     $data is a set of 10 points that we are trying to model using the
     linear combination of 3 functions.

          $functions = ( [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],  # Constant Term
          		[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ],  # Linear Slope Term
          		[ 0, 2, 4, 9, 16, 25, 36, 49, 64, 81] # quadradic term
          	    )

SYNOPSIS
========

     $yfit = linfit1d $data, $funcs

FUNCTIONS
=========

linfit1d
--------

   Uses a standard matrix inversion method to do a least squares/min chi^2
fit to data.

   Returns the fitted data and optionally the coefficients.

   One can thread over extra dimensions to do multiple fits (except the
order can not be threaded over - i.e. it must be one fixed set of fit
functions `fitFuncs'.

   The data is normalised internally to avoid overflows (using the mean of
the abs value) which are common in large polynomial series but the
returned fit, coeffs are in unnormalised units.

routines for fitting with polynomials
*************************************

NAME
====

   PDL::Fit::Polynomial - routines for fitting with polynomials

DESCRIPTION
===========

   This module contains routines for doing simple polynomial fits to data

SYNOPSIS
========

     $yfit = fitpoly1d $data;

FUNCTIONS
=========

fitpoly1d
---------

   Uses a standard matrix inversion method to do a least squares/min chi^2
polynomial fit to data. Order=2 is a linear fit (two parameters).

   Returns the fitted data and optionally the coefficients.

   One can thread over extra dimensions to do multiple fits (except the
order can not be threaded over - i.e. it must be one fixed scalar number
like "4").

   The data is normalised internally to avoid overflows (using the mean of
the abs value) which are common in large polynomial series but the
returned fit, coeffs are in unnormalised units.

BUGS
====

   May not work too well for data with large dynamic range.

SEE ALSO
========

   `"polyfit"', see PDL/Slatec,

AUTHOR
======

   This file copyright (C) 1999, Karl Glazebrook (kgb@aaoepp.aao.gov.au).
All rights reserved. There is no warranty. You are allowed to redistribute
this software documentation under certain conditions. For details, see the
file COPYING in the PDL distribution. If this file is separated from the
PDL distribution, the copyright notice should be included in the file.

useful functions
****************

NAME
====

   PDL::Func - useful functions

SYNOPSIS
========

     use PDL::Func;
     use PDL::Math;

     # somewhat pointless way to estimate cos and sin,
     # but is shows that you can thread if you want to
     # (and the library lets you)
     #
     my $obj = init PDL::Func( Interpolate => "Hermite" );
     #
     my $x = pdl( 0 .. 45 ) * 4 * 3.14159 / 180;
     my $y = cat( sin($x), cos($x) );
     $obj->set( x => $x, y => $y, bc => "simple" );
     #
     my $xi = pdl( 0.5, 1.5, 2.5 );
     my $yi = $obj->interpolate( $xi );
     #
     print "sin( $xi ) equals ", $yi->slice(':,(0)'), "\n";
     sin( [0.5 1.5 2.5] ) equals  [0.87759844 0.070737667 -0.80115622]
     #
     print "cos( $xi ) equals ", $yi->slice(':,(1)'), "\n";
     cos( [0.5 1.5 2.5] ) equals  [ 0.4794191 0.99768655 0.59846449]
     #
     print sin($xi), "\n", cos($xi), "\n";
     [0.47942554 0.99749499 0.59847214]
     [0.87758256 0.070737202 -0.80114362]

DESCRIPTION
===========

   This module aims to contain useful functions. Honest.

INTERPOLATION AND MORE
======================

   This module aims to provide a relatively-uniform interface to the
various interpolation methods available to PDL.  The idea is that a
different interpolation scheme can be used just by changing an attribute
of a `PDL::Func' object.  Some interpolation schemes (as exemplified by
the SLATEC library) also provide additional functionality, such as
integration and gradient estimation.

   Throughout this documentation, $x and `$y' refer to the function to be
interpolated whilst `$xi' and `$yi' are the interpolated values.

   The avaliable types, or *schemes*, of interpolation are listed below.
Also given are the valid attributes for each scheme: the flag value
indicates whether it can be set (s), got (g), and if it is required (r)
for the method to work.

Interpolate => Linear
     An extravagent way of calling the linear interpolation routine
     `PDL::Primitive::interpolate|PDL::Primitive' in this node.

     The valid attributes are:

          Attribute    Flag  Description
          x            sgr   x positions of data
          y            sgr   function values at x positions
          err          g     error flag

Interpolate => Hermite
     Use the piecewice cubic Hermite interpolation routines from the
     SLATEC library.  Only available if `PDL::Slatec|PDL::Slatec' in this
     node is installed.

     The valid attributes are:

          Attribute    Flag  Description
          x            sgr   x positions of data
          y            sgr   function values at x positions
          bc           sgr   boundary conditions
          g            g     estimated gradient at x positions
          err          g     error flag

     Given the initial set of points `(x,y)', an estimate of the gradient
     is made at these points, using the given boundary conditions. The
     gradients are stored in the g attribute, accessible via:

          $gradient = $obj->get( 'g' );

     However, as this gradient is only calculated 'at the last moment', g
     will only contain data after one of interpolate, `gradient', or
     `integrate' is used.

Boundary conditions for the Hermite routines
--------------------------------------------

   If your data is monotonic, and you are not too bothered about edge
effects, then the default value of `bc' of `simple' is for you.
Otherwise, take a look at the description of
`PDL::Slatec::chic|PDL::Slatec' in this node and use a hash reference for
the `bc' attribute, with the following keys:

monotonic
     0 if the interpolant is to be monotonic in each interval (so the
     gradient will be 0 at each switch point), otherwise the gradient is
     calculated using a 3-point difference formula at switch points.  If >
     0 then the interpolant is forced to lie close to the data, if < 0 no
     such control is imposed.  Default = 0.

start
     A perl list of one or two elements. The first element defines how the
     boundary condition for the start of the array is to be calculated; it
     has a range of `-5 .. 5', as given for the `ic' parameter of
     `chic|PDL::Slatec' in this node.  The second element, only used if
     options 2, 1, -1, or 2 are chosen, contains the value of the `vc'
     parameter.  Default = *[ 0 ]*.

end
     As for start, but for the end of the data.

   An example would be

     $obj->set( bc => { start => [ 1, 0 ], end => [ 1, -1 ] } )

   which sets the first derivative at the first point to 0, and at the
last point to -1.

Errors
------

   The status method provides a simple mechanism to check if the previous
method was successful.  If the function returns an error flag, then it is
stored in the err attribute.  To find out which routine was used, use the
`routine' method.

FUNCTIONS
=========

PDL::Func::init
---------------

   If not specified, the value of Interpolate is taken to be `Linear',
which means the interpolation is performed by
`PDL::Primitive::interpolate|PDL::Primitive' in this node.  A value of
`Hermite' uses piecewise cubic Hermite functions, which also allows the
integral and gradient of the data to be estimated.

PDL::Func::set
--------------

   The return value gives the number of the supplied attributes which were
actually set.

PDL::Func::get
--------------

   Given a list of attribute names, return a list of their values; in
scalar mode return a scalar value.  If the supplied list contains an
unknown attribute, get returns a value of undef for that attribute.

PDL::Func::scheme
-----------------

   Returns either `Linear' or `Hermite'.

PDL::Func::status
-----------------

   This method provides a high-level indication of the success of the last
method called (except for get which is ignored).  Returns 1 if everything
is okay, 0 if there has been a serious error, and *-1* if there was a
problem which was not serious.  In the latter case, `$obj->get("err")' may
provide more information, depending on the particular scheme in use.

PDL::Func::routine
------------------

   This is mainly useful for decoding the value stored in the err
attribute.

PDL::Func::attributes
---------------------

   Useful in case the documentation is just too opaque!

PDL::Func::interpolate
----------------------

   A status value of -1, as returned by the status method, means that some
of the `$xi' points lay outside the range of the data. The values for
these points were calculated by extrapolation (the details depend on the
scheme being used).

PDL::Func::gradient
-------------------

PDL::Func::integrate
--------------------

   The integration can either be between points of the original x array
(index), or arbitrary x values (x). For both cases, a two element piddle
should be given, to specify the start and end points of the integration.

index
     The values given refer to the indices of the points in the x array.

x
     The array contains the actual values to integrate between.

   If the status method returns a value of -1, then one or both of the
integration limits did not lie inside the x array. *Caveat emptor* with the
result in such a case.

TODO
====

   It should be relatively easy to provide an interface to other
interpolation routines, such as those provided by the Gnu Scientific
Library (GSL), or the B-spline routines in the SLATEC library.

   In the documentation, the methods are preceeded by `PDL::Func::' to
avoid clashes with functions such as set when using the help or apropos
commands within *perldl*.

HISTORY
=======

   Amalgamated `PDL::Interpolate' and `PDL::Interpolate::Slatec' to form
`PDL::Func'. Comments greatly appreciated on the current implementation,
as it is not too sensible.

AUTHOR
======

   Copyright (C) 2000 Doug Burke (burke@ifa.hawaii.edu).  All rights
reserved. There is no warranty.  You are allowed to redistribute this
software / documentation as described in the file COPYING in the PDL
distribution.

Gaussian distributions.
***********************

NAME
====

   PDL::Gaussian - Gaussian distributions.

SYNOPSIS
========

     $a = new PDL::Gaussian([3],[5]);
     $a->set_covariance(...)

DESCRIPTION
===========

   This package provides a set of standard routines to handle sets
gaussian distributions.

   A new set of gaussians is initialized by

     $a = new PDL::Gaussian(xdims,gdims);

   Where *xdims* is a reference to an array containing the dimensions in
the space the gaussian is in and *gdimslist* is a reference to an array
containing the dimensionality of the gaussian space. For example, after

     $a = new PDL::Gaussian([2],[3,4]);
     $b = new PDL::Gaussian([],[]);

   The variable `$a' contains set of 12 (=`3*4') 2-Dimensional gaussians
and $b is the simplest form: one 1D gaussian.  Currently, *xdims* may
containe either zero or one dimensions due to limitations of
`PDL::PP|PDL::PP' in this node.

   To set the distribution parameters, you can use the routines

     $a->set_covariance($cv);     # covariance matrices
     $a->set_icovariance($icv);   # inverse covariance matrices
     $a->set_mu($mu);	      # centers

   The dimensions of `$cv' and `$icv' must be `(@xdims,@xdims,@gdims)' and
the dimensions of `$mu' must be `(@xdims,@gdims)'.

   Alternatively you can use the routines

     $cv = $a->get_covariance();  # cv = reference to covariance matrix
     ...			      # Fuzz around with cv
     $a->upd_covariance();	      # update

   and similarly for `icovariance' (inverse covariance). The last sub call
is important to update the other parts of the object.

   To get a string representation of the gaussians (most useful for
debugging) use the routine

     $string = $a->asstr();

   It is possible to calculate the probability or logarithm of probability
of each of the distributions at some points.

     $a->calc_value($x,$p);
     $a->calc_lnvalue($x,$p);

   Here, $x must have dimensions `(ndims,...)' and $p must have dimensions
`(gdimslist, ...)' where the elipsis represents the same dimensions in
both variables. It is usually advisable to work with the logarithms of
probabilities to avoid numerical problems.

   It is possible to generate the parameters for the gaussians from data.
The function

     $a->fromweighteddata($data,$wt,$small_covariance);

   where $data is of dimensions `(ndims,npoints)' and `$wt' is of
dimensions `(npoints,gdimslist)', analyzes the data statistically and gives
a corresponding gaussian distribution. The parameter `$small_covariance'
is the smallest allowed covariance in any direction: if one or more of the
eigenvalues of the covariance matrix are smaller than this, they are
automatically set to `$small_covariance' to avoid singularities.

BUGS
====

   Stupid interface.

   Limitation to 1 x-dimensions is questionable (although it's hard to
imagine a case when more is needed).  Note that this does not mean that
you can only have 1-dimensional gaussians. It just means that if you want
to have a 6-dimensional gaussian, your xs must be structured like (6) and
not (2,3).  So clumping the dimensions should make things workable.

   Also, it limits you so that even if you have one variable, you need to
have the '1' dimensions explicitly everywhere.

   Singular distributions are not handled. This should use SVD and be able
to handle both infinitely narrow and wide dimensions, preferably so that
infinitely narrow dimensions can be queried like `$a-'relations()> or
something like that.

   The routines should, if the user requests for it, check all the
dimensions of the given arguments for reasonability.

AUTHOR
======

   Copyright (C) 1996 Tuomas J. Lukka (lukka@fas.harvard.edu) All rights
reserved. There is no warranty. You are allowed to redistribute this
software / documentation under certain conditions. For details, see the
file COPYING in the PDL distribution. If this file is separated from the
PDL distribution, the copyright notice should be included in the file.

An object oriented interface to PDL graphics
********************************************

NAME
====

   PDL::Graphics2D - An object oriented interface to PDL graphics

SYNOPSIS
========

   use PDL::Graphics2D; $win = PDL::Graphics2D->new(<Interface>,
<Options>);

DESCRIPTION
===========

   This is an umbrella class allowing for a simple interface to all
plotting routines in PDL. On its own it does not do any work it merely
passes information to the appropriate class. Ideally this should probably
offer a uniform interface to a variety of packages.

   This requires a lot more work before it is useful I feel, but it can be
used already.

Display PDL images on IIS devices (saoimage/ximtool)
****************************************************

NAME
====

   PDL::Graphics::IIS - Display PDL images on IIS devices
(saoimage/ximtool)

SYNOPSIS
========

     use PDL::Graphics::IIS;
     saoimage ( -geometry => '800x800' );
     iis rvals(100,100);

DESCRIPTION
===========

   This module provides an interface to any image display 'device' which
support the 'IIS protocol' - viz the SAOimage and Ximtool X-windows
programs, the old SunView imtool program and presumably even the original
IIS CRT itself if they aren't all in museums!

   These programs should be familiar to astronomer's - they are used by
the common IRAF system. The programs and their HTML documentation can be
obtained from the following URLs:

     SAOimage: http://tdc-www.harvard.edu/software/saoimage.html
     Ximtool:  http://iraf.noao.edu/iraf/web/projects/x11iraf/x11iraf.html

   Non-astronomer's may find they quite nifty for displaying 2D data.

   The Perl variable `$stdimage' is exported from the module and controls
the frame buffer configuration currently in use. The default value is
`imt1024' which specifies a `1024x1024' frame buffer. Other values
supported by the module are:

   imt512, imt800, imt1024, imt1600, imt2048, and imt4096.

   If you have a `$HOME/.imtoolrc' you can use it to specify other frame
buffer names and configurations in exactly the same way you can in IRAF.
Here is a sample file:

     -------------------snip-------------------------
     # Format:  configno nframes width height
      1  2  512  512         # imt1|imt512
      2  2  800  800         # imt2|imt800
      3  2 1024 1024         # imt3|imt1024
      4  1 1600 1600         # imt4|imt1600
      5  1 2048 2048         # imt5|imt2048
      6  1 4096 4096         # imt6|imt4096
      7  1 8192 8192         # imt7|imt8192
      8  1 1024 4096         # imt8|imt1x4
      9  2 1144  880         # imt9|imtfs    full screen (1152x900 minus frame)
     10  2 1144  764         # imt10|imtfs35 full screen at 35mm film aspect ratio
     -------------------snip-------------------------

   (Note: some versions of SAOimage may not even work if this file is not
present. If you get funny error messages about 'imtoolrc' try copying the
above to `$HOME/.imtoolrc' or `/usr/local/lib/imtoolrc')

   The Perl variable `$iisframe' is also exported from the module and
controls which display frame number to use in programs such as Ximtool
which supports multiple frames. This allows you to do useful things such
as blink between images.

   The module communicates with the IIS device down FIFO pipes (special
UNIX files) - unlike IRAF this module does a pretty decent job of
intelligently guessing which file names to use for the pipes and will
prompt for their creating if absent. Also if SAOimage or Ximtool are
started from within Perl using the module this will guarantee correct file
names!

FUNCTIONS
=========

iis
---

   Displays image on a IIS device. If `min()' or `max()' are omitted they
are autoscaled. A good demonstration of PDL threading can be had by giving
`iis()' a data *cube* - `iis()' will be repeatedly called for each plane
of the cube resulting in a poor man's movie!

   If supplied, TITLE is used to label the frame, if no title is supplied,
either the OBJECT value stored in the image header or a default string is
used (the title is restricted to a maximum length of 32 characters).

   To specify which frame to draw to, either use the package variable
`$iisframe', or the `FRAME' option.

iiscur
------

   This function puts up an interactive cursor on the IIS device and
returns the `($x,$y)' position and the character typed (`$ch') by the user.

iiscirc
-------

   Draws circles on the IIS device with specied points and colours. Because
this module uses `PDL::PP|PDL::PP' in this node threading you can supply
lists of points via 1D arrays, etc.

   An amusing PDL idiom is:

     perldl> iiscirc iiscur

   Note the colours are the same as IRAF, viz:

     201 = cursor color (white)
     202 = black
     203 = white
     204 = red
     205 = green
     206 = blue
     207 = yellow
     208 = cyan
     209 = magenta
     210 = coral
     211 = maroon
     212 = orange
     213 = khaki
     214 = orchid
     215 = turquoise
     216 = violet
     217 = wheat

saoimage
--------

   Starts up the SAOimage external program. Default FIFO devices are chosen
so as to be compatible with other IIS module functions. If no suitable
FIFOs are found it will offer to create them.

   e.g.:

ximtool
-------

   Starts up the Ximtool external program. Default FIFO devices are chosen
so as to be compatible with other IIS module functions. If no suitable
FIFOs are found it will offer to create them.

   e.g.

BUGS
====

   None known

AUTHOR
======

   Copyright (C) Karl Glazebrook 1997.  All rights reserved. There is no
warranty. You are allowed to redistribute this software / documentation
under certain conditions. For details, see the file COPYING in the PDL
distribution. If this file is separated from the PDL distribution, the
copyright notice should be included in the file.

provides access to a number of look-up tables
*********************************************

NAME
====

   PDL::Graphics::LUT - provides access to a number of look-up tables

SYNOPSIS
========

     use PDL::Graphics::PGPLOT;
     use PDL::Graphics::LUT;

     # what tables are available
     my @tables = lut_names();

     # get the reversed colour table 'smooth',
     # with the gamma intensity ramp
     my ( $l, $r, $g, $b ) = lut_data( 'smooth', 1, 'gamma' );

     # use the table idl5 in ctab
     ctab( lut_data('idl5') );

DESCRIPTION
===========

   PDL::Graphics::LUT contains a number of colour look-up tables (in rgb
format) and intensity ramps, and provides routines to access this data.
The format of the data is suitable for use by `ctab', see
PDL/Graphics/PGPLOT.

   Unlike the initial release of the package, the data tables are now
stored within the PDL distribution (see `$tabledir|' in this node and
`$rampdir|' in this node) rather than in the module itself.  Changes to
these directories will be picked up on the next call to one of the package
functions.

FUNCTIONS
=========

lut_names()
-----------

lut_ramps()
-----------

lut_data()
----------

   Returns the levels and r, g, b components of the colour table `$table'.
If `$reverse' is 1 (defaults to 0 if not supplied), then the r, g, and b
components are reversed before being returned.  If not supplied, `$ramp'
defaults to *"ramp"* (this is a linear intensity ramp).

   The returned values are piddles containing values in the range 0 to 1
inclusive, and are floats.

VARIABLES
=========

$tabledir
---------

$rampdir
--------

$suffix
-------

FURTHER INFORMATION
===================

   The colour tables were taken from the STARLINK GAIA package, and are
provided under the GNU copyleft.  See http://star-www.rl.ac.uk/ and
http://star-www.dur.ac.uk/~pdraper/ for more details.

AUTHOR
======

   Doug Burke (burke@ifa.hawaii.edu), with thanks to Peter Draper/STARLINK
for providing the colour-table data, and Christian Soeller and Karl
Glazebrook for their help.

   All rights reserved. There is no warranty. You are allowed to
redistribute this software / documentation under certain conditions. For
details, see the file COPYING in the PDL distribution. If this file is
separated from the PDL distribution, the copyright notice should be
included in the file.

a PDL interface to the OpenGL graphics library. PDL::Graphics::OpenGLOO - an Object Oriented interface to the interface.
************************************************************************************************************************

NAME
====

   PDL::Graphics::OpenGL - a PDL interface to the OpenGL graphics library.
PDL::Graphics::OpenGLOO - an Object Oriented interface to the interface.

DESCRIPTION
===========

   This package implements an interface to various OpenGL or OpenGL
emulator libraries.  Most of the interface is generated at PDL compile
time by the script opengl.pd which runs the c preprocessor on various
OpenGL include files to determine the correct C prototypes for each
configuration.  The object oriented interface defines an Object which
contains the Display, Window and Context properties of the defined OpenGL
device.  Any OpenGL function called from the OO interface will recieve
these fields from the object, they should not be passed explicitly.

   This package is primarily intended for internal use by the
PDL::Graphics::TriD package, but should also be usable in its own right.

FUNCTIONS
=========

new($class,$options)
--------------------

   Returns a new OpenGL object with attributes specified in the options
field.  These attributes are: =for ref   x,y - the position of the upper
left corner of the window (0,0)   width,height - the width and height of
the window in pixels (500,500)   parent - the parent under which the new
window should be opened (root)   mask - the user interface mask
(StructureNotifyMask)   attributes - attributes to pass to glXChooseVisual

default_options
---------------

   default options for object oriented methods

XResizeWindow(x,y)
------------------

   OO interface to XResizeWindow

glpXNextEvent()
---------------

   OO interface to glpXNextEvent

glpRasterFont()
---------------

   OO interface to the glpRasterFont function

AUTOLOAD
--------

   If the function is not prototyped in OO we assume there is no explicit
mention of the three identifying parameters (Display, Window, Context) and
try to load the OpenGL function.

glXCopyContext
--------------

   OO interface to the glXCopyContext function

glXCreateContext
----------------

   OO interface to the glXCreateContext function

glXCreateGLXPixmap
------------------

   OO interface to the glXCreateGLXPixmap function

glXDestroyContext
-----------------

   OO interface to the glXDestroyContext function

glXDestroyGLXPixmap
-------------------

   OO interface to the glXDestroyGLXPixmap function

glXGetConfig
------------

   OO interface to the glXGetConfig function

glXIsDirect
-----------

   OO interface to the glXIsDirect function

glXMakeCurrent
--------------

   OO interface to the glXMakeCurrent function

glXQueryExtension
-----------------

   OO interface to the glXQueryExtension function

glXQueryVersion
---------------

   OO interface to the glXQueryVersion function

glXSwapBuffers
--------------

   OO interface to the glXSwapBuffers function

glXGetFBConfigAttrib
--------------------

   OO interface to the glXGetFBConfigAttrib function

glXCreatePixmap
---------------

   OO interface to the glXCreatePixmap function

glXDestroyPixmap
----------------

   OO interface to the glXDestroyPixmap function

glXCreateNewContext
-------------------

   OO interface to the glXCreateNewContext function

glXQueryContext
---------------

   OO interface to the glXQueryContext function

glXMakeContextCurrent
---------------------

   OO interface to the glXMakeContextCurrent function

glXCreatePbuffer
----------------

   OO interface to the glXCreatePbuffer function

glXDestroyPbuffer
-----------------

   OO interface to the glXDestroyPbuffer function

glXQueryDrawable
----------------

   OO interface to the glXQueryDrawable function

glXSelectEvent
--------------

   OO interface to the glXSelectEvent function

glXGetSelectedEvent
-------------------

   OO interface to the glXGetSelectedEvent function

glXCreateWindow
---------------

   OO interface to the glXCreateWindow function

glXDestroyWindow
----------------

   OO interface to the glXDestroyWindow function

glXMakeCurrentReadSGI
---------------------

   OO interface to the glXMakeCurrentReadSGI function

glXBindChannelToWindowSGIX
--------------------------

   OO interface to the glXBindChannelToWindowSGIX function

glXQueryChannelDeltasSGIX
-------------------------

   OO interface to the glXQueryChannelDeltasSGIX function

glXChannelRectSGIX
------------------

   OO interface to the glXChannelRectSGIX function

glXQueryChannelRectSGIX
-----------------------

   OO interface to the glXQueryChannelRectSGIX function

glXChannelRectSyncSGIX
----------------------

   OO interface to the glXChannelRectSyncSGIX function

glXHyperpipeConfigSGIX
----------------------

   OO interface to the glXHyperpipeConfigSGIX function

glXDestroyHyperpipeConfigSGIX
-----------------------------

   OO interface to the glXDestroyHyperpipeConfigSGIX function

glXBindHyperpipeSGIX
--------------------

   OO interface to the glXBindHyperpipeSGIX function

glXQueryHyperpipeBestAttribSGIX
-------------------------------

   OO interface to the glXQueryHyperpipeBestAttribSGIX function

glXQueryHyperpipeAttribSGIX
---------------------------

   OO interface to the glXQueryHyperpipeAttribSGIX function

glXHyperpipeAttribSGIX
----------------------

   OO interface to the glXHyperpipeAttribSGIX function

glXQueryContextInfoEXT
----------------------

   OO interface to the glXQueryContextInfoEXT function

glXGetContextIDEXT
------------------

   OO interface to the glXGetContextIDEXT function

glXImportContextEXT
-------------------

   OO interface to the glXImportContextEXT function

glXFreeContextEXT
-----------------

   OO interface to the glXFreeContextEXT function

glXGetFBConfigAttribSGIX
------------------------

   OO interface to the glXGetFBConfigAttribSGIX function

glXCreateGLXPixmapWithConfigSGIX
--------------------------------

   OO interface to the glXCreateGLXPixmapWithConfigSGIX function

glXCreateContextWithConfigSGIX
------------------------------

   OO interface to the glXCreateContextWithConfigSGIX function

glXGetFBConfigFromVisualSGIX
----------------------------

   OO interface to the glXGetFBConfigFromVisualSGIX function

glXCreateGLXPbufferSGIX
-----------------------

   OO interface to the glXCreateGLXPbufferSGIX function

glXDestroyGLXPbufferSGIX
------------------------

   OO interface to the glXDestroyGLXPbufferSGIX function

glXQueryGLXPbufferSGIX
----------------------

   OO interface to the glXQueryGLXPbufferSGIX function

glXSelectEventSGIX
------------------

   OO interface to the glXSelectEventSGIX function

glXGetSelectedEventSGIX
-----------------------

   OO interface to the glXGetSelectedEventSGIX function

glXJoinSwapGroupSGIX
--------------------

   OO interface to the glXJoinSwapGroupSGIX function

glXBindSwapBarrierSGIX
----------------------

   OO interface to the glXBindSwapBarrierSGIX function

glXQueryMaxSwapBarriersSGIX
---------------------------

   OO interface to the glXQueryMaxSwapBarriersSGIX function

OpenGL Interface Functions
--------------------------

quick routines to plot lots of stuff from piddles.
**************************************************

NAME
====

     PDL::Graphics::OpenGLQ - quick routines to plot lots of stuff from piddles.

SYNOPSIS
========

     only for internal use - see source

DESCRIPTION
===========

   only for internal use - see source

AUTHOR
======

   Copyright (C) 1997,1998 Tuomas J. Lukka.  All rights reserved. There is
no warranty. You are allowed to redistribute this software / documentation
under certain conditions. For details, see the file COPYING in the PDL
distribution. If this file is separated from the PDL distribution, the
copyright notice should be included in the file.

PGPLOT enhanced interface for PDL
*********************************

NAME
====

     PDL::Graphics::PGPLOT - PGPLOT enhanced interface for PDL

SYNOPSIS
========

     perldl> $a = pdl [1..100]
     perldl> $b = sqrt($a)
     perldl> line $b
     perldl> hold
     Graphics on HOLD
     perldl> $c = sin($a/10)*2 + 4
     perldl> line $c

DESCRIPTION
===========

   PDL::Graphics::PGPLOT is a convenience interface to the PGPLOT commands,
implemented using the object oriented PGPLOT plotting package in
PDL/Graphics/PGPLOT/Window. See the
documentation for that package for in-depth information about the usage of
these commands and the options they accept.

   The list of currently availably commands:

     imag       -  Display an image (uses pgimag()/pggray() as appropriate)
     im         -  Shorthand to display an image with aspect ratio of 1
     ctab       -  Load an image colour table
     ctab_info  -  Get information about currently loaded colour table
     line       -  Plot vector as connected points
     points     -  Plot vector as points
     errb       -  Plot error bars
     cont       -  Display image as contour map
     bin        -  Plot vector as histogram (e.g. bin(hist($data)) )
     hi2d       -  Plot image as 2d histogram (not very good IMHO...)
     poly       -  Draw a polygon
     vect       -  Display 2 images as a vector field
     text       -  Write text in the plot area
     label_axes -  Print axis titles
     legend     -  Create a legend with different texts, linestyles etc.
     cursor     -  Interactively read cursor positions.
     circle     -  Draw a circle
     ellipse    -  Draw an ellipse.

   Device manipulation commands:

     hold         -  Hold current plot window range - allows overlays etc.
     release      -  Release back to autoscaling of new plot window for each
                     command
     rel          -  short alias for 'release'
     env          -  Define a plot window, put on 'hold'
     dev          -  Explicitly set a new PGPLOT graphics device
     new_window   -  Create a new plot window (use of dev is recommended)
     focus_window -  Change focus to a new window
     window_list  -  Get a list of currently exisiting plot windows
     close_window -  Close an open window

FUNCTIONS
=========

   The following is a list of the functions that are private to this
package, for the other functions please read the
PDL/Graphics/PGPLOT/Window, documentation.

dev
---

   `$device' is a PGPLOT graphics device such as "/xserve" or "/ps", if
omitted defaults to last used device (or value of env var `PGPLOT_DEV' if
first time).  `$nx', `$ny' specify sub-panelling. The function returns the
id of the newly created window - this can subsequently be used as argument
to focus_window to select the window.

   The result of this command can be modified using options. The options
recognised are the same as for new_window - which primarily and in
addition it is possible to set the default values for a window that are
defined in `PDL::PGPLOTOptions' in this node, see this for details but see
below for a synopsis.

   In addition dev recognises the option `NewWindow' which allows the user
to specify that a dev command is to create a new window rather than
closing the previous. This allows a large number of output destinations to
be open at the same time, which occasionally can be convenient.

   Here is a quick summary of the most useful additional options that can
be given:

Device
     Alternative to `$device'.

AspectRatio
     The aspect ratio of the output window

WindowWidth
     The width of the plot window in inches

AxisColour
     The axis colour to be used as default for plots in this window. In
     the same way it is possible to set the default character size
     (CharSize) and axis and box styles. See
     PDL/Graphics/PGPLOTOptions, for details.

WindowName
     The name of a window. This name can subsequently be used to refer to
     the window instead of its ID, making interactive use somewhat more
     intuitive.

     $win = dev('/xs');

   To open two windows, one small and square, one large and wide:

     $win1 = dev('/xs', {Aspect => 1, WindowWidth => 4});
     $win2 = dev('/xs', {Aspect => 0.5, WindowWidth => 10});

new_window
----------

   This function is identical to `dev' in this node except that it always
creates a new window. This means that the user is required to close all
windows explicitly using `close_window' in this node. All functionality is
otherwise like dev so see the documentation for `dev' in this node for
details of use.

close_window
------------

   This function closes a PGPLOT output device created with dev or
new_window. It requires the id of the window to close. If $id is left
undefined, the currently focussed window is deleted and focus is
transferred to the lowest numbered window in existence. If many windows
have been created and deleted this might not be what you expect, so it is
recommended to make an explicit call to `focus_window' in this node after
any call to close_window.

_get_windownumber
-----------------

   Internal function to obtain the ID of a window. This allows the user to
refer to a window with its name.

focus_window
------------

   This command is used to switch output focus to another window created by
`dev' in this node or `new_window' in this node. The window can be
referred to either by its ID or by its name.

     focus_window('X-output');  # Or focus_window($win1);
     <.. Commands ..>
     focus_window($win2);       # Or focus_window('PS-output');
     <.. Commands ..>

window_list
-----------

   `$numbers' and `$names' are anonymous arrays giving the ID numbers and
names of the open windows respectively.

A OO interface to PGPLOT windows
********************************

NAME
====

   PDL::Graphics::PGPLOT::Window - A OO interface to PGPLOT windows

SYNOPSIS
========

     perldl> use PDL::Graphics::PGPLOT::Window
     perldl> $win = PDL::Graphics::PGPLOT::Window->new({Device => '/xs'});
     perldl> $a = pdl [1..100]
     perldl> $b = sqrt($a)
     perldl> $win->line($b)
     perldl> $win->hold()
     perldl> $c = sin($a/10)*2 + 4
     perldl> $win->line($c)

   In the following documentation the commands are not shown in their OO
versions. This is for historical reasons and should not cause too much
trouble.

DESCRIPTION
===========

   This package offers a OO interface to the PGPLOT plotting package. This
is intended to replace the traditional interface in
PDL/Graphics/PGPLOT, and contains interfaces to a
large number of PGPLOT routines. Below the usage examples for each
function tend to be given in the non-OO version for historical reasons.
This will slowly be changed, but in the meantime refer to the section on
OO-interface below to see how to convert the usage information below to OO
usage (it is totally trivial).

   PDL::Graphics::PGPLOT::Window is an interface to the PGPLOT graphical
libraries.

   The list of currently availably methods:

     imag       -  Display an image (uses pgimag()/pggray() as appropriate)
     ctab       -  Load an image colour table
     ctab_info  -  Get information about currently loaded colour table
     line       -  Plot vector as connected points
     points     -  Plot vector as points
     errb       -  Plot error bars
     cont       -  Display image as contour map
     bin        -  Plot vector as histogram (e.g. bin(hist($data)) )
     hi2d       -  Plot image as 2d histogram (not very good IMHO...)
     poly       -  Draw a polygon
     vect       -  Display 2 images as a vector field
     text       -  Write text in the plot area
     label_axes -  Print axis titles
     legend     -  Create a legend with different texts, linestyles etc.
     cursor     -  Interactively read cursor positions.
     circle     -  Draw a circle
     ellipse    -  Draw an ellipse.

   Device manipulation commands:

     new          -  Constructor for a new PGPLOT output device
     close        -  Close a PGPLOT output device
     focus        -  Set focus to the given device. This should normally be
                     done behind the scenes.
     hold         -  Hold current plot window range - allows overlays etc.
     release      -  Release back to autoscaling of new plot window for each
                     command
     held         -  Returns true if the graphics is held on the current device.
     env          -  Define a plot window, put on 'hold'
     panel        -  Move to a specified plot panel when several panels are defined.
     erase        -  Erase the current window (or panel)

     options      -  Get the options set for the present output device
     id           -  The ID for the device
     device       -  The device type
     name         -  The window name

   Notes: `$transform' for image/cont etc. is used in the same way as the
`TR()' array in the underlying PGPLOT FORTRAN routine but is, fortunately,
zero-offset.

   For completeness: The transformation array connect the pixel index to a
world coordinate such that:

     X = tr[0] + tr[1]*i + tr[2]*j
     Y = tr[3] + tr[4]*i + tr[5]*j

Variable passing and extensions
-------------------------------

   In general variables are passed to the pgplot routines by using
`get_dataref' to get the reference to the values. Before passing to pgplot
routines however, the data are checked to see if they are in accordance
with the format (typically dimensionality) required by the PGPLOT routines.
This is done using the routine `checkarg' (internal to PGPLOT). This
routine checks the dimensionality of the input data. If there are
superfluous dimensions of size 1 they will be trimmed away until the
dimensionality is correct. Example:

   Assume a piddle with dimensions (1,100,1,1) is passed to line, which
expects its inputs to be vectors. `checkarg' will then return a piddle
with dimensions (100). If instead the same piddle was passed to imag,
which requires 2D piddles as output, `checkarg' would return a piddle with
dimensionality (100, 1) (Dimensions are removed from the start)

   Thus, if you want to provide support for another PGPLOT function, the
structure currently look like this (there are plans to use the Options
package to simplify the options parsing):

     # Extract the hash(es) on the commandline
     ($arg, $opt)=_extract_hash(@_);
     <Check the number of input parameters>
     <deal with $arg>
     checkarg($x, 3); # For a hypothetical 3D routine.
     ...
     pgcube($n, $x->get_dataref);
     1;

Setting options
---------------

   All routines in this package take a hash with options as an optional
input. This options hash can be used to set parameters for the subsequent
plotting without going via the PGPLOT commands.

   This is implemented such that the plotting settings (such as line width,
line style etc.) are affected only for that plot, any global changes made,
say, with `pgslw()' are preserved. Some modifications apply when using the
OO interface, see below.

Alphabetical listing of standard options
----------------------------------------

   The following options are always parsed. Whether they have any
importance depend on the routine invoked - e.g. line style is irrelevant
for imag, or the justify option is irrelevant if the display is on 'hold'.
This is indicated in the help text for the commands below.

   The options are not case sensitive and will match for unique substrings,
but this is not encouraged as obscure options might invalidate what you
thought was a unique substring.

   In the listing below examples are given of each option. The actual
option can then be used in a plot command by specifying it as an argument
to the function wanted (it can be placed anywhere in the command list).

   E.g:

     $opt={COLOR=>2};
     line $x, $y, $opt; # This will plot a line with red color

arrow
     This options allows you to set the arrow shape, and optionally size
     for arrows for the vect routine. The arrow shape is specified as a
     hash with the key FS to set fill style, ANGLE to set the opening
     angle of the arrow head, VENT to set how much of the arrow head is
     cut out and SIZE to set the arrowsize.

     The following

          $opt = {ARROW => {FS=>1, ANGLE=>60, VENT=>0.3, SIZE=>5}};

     will make a broad arrow of five times the normal size.

     Alternatively the arrow can be specified as a set of numbers
     corresponding to an extention to the syntax for pgsah. The equivalent
     to the above is

          $opt = {ARROW => pdl([1, 60, 0.3, 5})};

     For the latter the arguments must be in the given order, and if any
     are not given the default values of 1, 45, 0.3 and 1.0 respectively
     will be used.

arrowsize
     The arrowsize can be specified separately using this option to the
     options hash. It is useful if an arrowstyle has been set up and one
     wants to plot the same arrow with several sizes. Please note that it
     is not possible to set arrowsize and character size in the same call
     to a plotting function. This should not be a problem in most cases.

          $opt = {ARROWSIZE => 2.5};

axis
     Set the axis value (see `' in this node).  It can either be specified
     as a number, or by one of the following names:

          EMPTY  (-2) draw no box, axes or labels
          BOX    (-1) draw box only
          NORMAL (0)  draw box and label it with coordinates
          AXES   (1)  same as NORMAL, but also draw (X=0,Y=0) axes
          GRID   (2)  same as AXES, but also draw grid lines
          LOGX   (10) draw box and label X-axis logarithmically
          LOGY   (20) draw box and label Y-axis logarithmically
          LOGXY  (30) draw box and label both axes logarithmically

border
     Normally the limits are chosen so that the plot just fits; with this
     option you can increase (or decrease) the limits by either a relative
     (ie a fraction of the original axis width) or an absolute amount.
     Either specify a hash array, where the keys are TYPE (set to
     'relative' or 'absolute') and VALUE (the amount to change the limits
     by), or set to 1, which is equivalent to

          BORDER => { TYPE => 'rel', VALUE => 0.05 }

charsize
     Set the character/symbol size as a multiple of the standard size.

          $opt = {CHARSIZE => 1.5}

colour (or color)
     Set the colour to be used for the subsequent plotting. This can be
     specified as a number, and the most used colours can also be specified
     with name, according to the following table (note that this only
     works for the default colour map):

          0 - WHITE    1 - BLACK     2 - RED      3 - GREEN    4 - BLUE
          5 - CYAN     6 - MAGENTA   7 - YELLOW   8 - ORANGE  14 - DARKGRAY
           16 - LIGHTGRAY

filltype
     Set the fill type to be used by `poly|' in this node.  The fill can
     either be specified using numbers or name, according to the following
     table, where the recognised name is shown in capitals - it is
     case-insensitive, but the whole name must be specified.

          1 - SOLID
          2 - OUTLINE
          3 - HATCHED
          4 - CROSS_HATCHED

          $opt = {FILLTYPE => 'SOLID'};

     (see below for an example of hatched fill)

font
     Set the character font. This can either be specified as a number
     following the PGPLOT numbering or name as follows (name in capitals):

          1 - NORMAL
          2 - ROMAN
          3 - ITALIC
          4 - SCRIPT

     (Note that in a string, the font can be changed using the escape
     sequences `\fn', `\fr', `\fi' and `\fs' respectively)

          $opt = {FONT => 'ROMAN'};

     gives the same result as

          $opt = {FONT => 2};

hatching
     Set the hatching to be used if either fillstyle 3 or 4 is selected
     (see above) The specification is similar to the one for specifying
     arrows.  The arguments for the hatching is either given using a hash
     with the key ANGLE to set the angle that the hatch lines will make
     with the horizontal, SEPARATION to set the spacing of the hatch lines
     in units of 1% of `min(height, width)' of the view surface, and PHASE
     to set the offset the hatching. Alternatively this can be specified
     as a 1x3 piddle `$hatch=pdl[$angle, $sep, $phase]'.

          $opt = {FILLTYPE => 'HATCHED',
                  HATCHING => {ANGLE=>30, SEPARATION=>4}};

     Can also be specified as

          $opt = {FILL=> 'HATCHED', HATCH => pdl [30,4,0.0]};

     For another example of hatching, see `' in this node.

justify
     A boolean value which, if true, causes both axes to drawn to the same
     scale; see the PGPLOT `pgenv()' command for more information.

linestyle
     Set the line style. This can either be specified as a number following
     the PGPLOT numbering:

          1 - SOLID line
          2 - DASHED
          3 - DOT-DASH-dot-dash
          4 - DOTTED
          5 - DASH-DOT-DOT-dot

     or using name (as given in capitals above).  Thus the following two
     specifications both specify the line to be dotted:

          $opt = {LINESTYLE => 4};
          $varopt = {LINESTYLE => 'DOTTED'};

     The names are not case sensitive, but the full name is required.

linewidth
     Set the line width. It is specified as a integer multiple of 0.13 mm.

          $opt = {LINEWIDTH => 10}; # A rather fat line

OBJECT-ORIENTED INTERFACE
=========================

   This section will briefly describe how the PDL::Graphics::PGPLOT::Window
package can be used in an object-oriented (OO) approach and what the
advantages of this would be. We will start with the latter

Multiple windows.
     For the common user it is probably most interesting to use the OO
     interface when handling several open devices at the same time. If you
     have one variable for each plot device it is easier to distribute
     commands to the right device at the right time. This is the angle we
     will take in the rest of this description.

Coding and abstraction
     At a more fundamental level it is desirable to approach a situation
     where it is possible to have a generic plotting interface which gives
     access to several plotting libraries, much as PGPLOT gives access to
     different output devices. Thus in such a hypothetical package one
     would say:

          my $win1 = Graphics::new('PGPLOT', {Device => '/xs'});
          my $win2 = Graphics::new('gnuplot', {Background => 'Gray'};

     From a more practical point of of view such abstraction also comes in
     handy when you write a large program package and you do not want to
     import routines nilly-willy in which case an OO approach with method
     calls is a lot cleaner.

   Anyway, enough philosophizing, let us get down to Earth and give some
examples of the use of OO PGPLOT. As an example we will take Odd (which
happens to be a common Norwegian name) who is monitoring the birth of
rabbits in O'Fib-o-nachy's farm (alternatively he can of course be
monitoring processes or do something entirely different). Odd wants the
user to be able to monitor both the birth rates and accumulated number of
rabbits and the spatial distribution of the births. Since these are
logically different he chooses to have two windows open:

     $rate_win = PDL::Graphics::PGPLOT::Window->new({Device => '/xw',
                 Aspect => 1, WindowWidth => 5, NXPanel => 2});

     $area_win = PDL::Graphics::PGPLOT::Window->new({Device => '/xw',
                 Aspect => 1, WindowWidth => 5});

   See the documentation for `new' in this node below for a full overview
of the options you can pass to the constructor.

   Next, Odd wants to create plotting areas for subsequent plots and maybe
show the expected theoretical trends

     $rate_win->env(0, 10, 0, 1000, {XTitle => 'Days', YTitle => '#Rabbits'});
     $rate_win->env(0, 10, 0, 100, {Xtitle=>'Days', Ytitle => 'Rabbits/day'});

     $area_win->env(0, 1, 0, 1, {XTitle => 'Km', Ytitle => 'Km'});
     # And theoretical prediction.
     $rate_win->line(sequence(10), fibonacci(10), {Panel => [1, 1]});

   That is basically it. The commands should automatically focus the
relevant window. Due to the limitations of PGPLOT this might however lead
you to plot in the wrong panel... The package tries to be smart and do this
correctly, but might get it wrong at times.

FUNCTIONS
=========

   A more detailed listing of the functions and their usage follows. For
all functions we specify which options take effect and what other options
exist for the given function. The function descriptions below are all
given for the non-OO usage for historical reasons, but since the conversion
to an OO method is trivial there is no major need for concern. Whenever you
see a function example of the form

     Usage: a_simple_function($x, $y, $z [, $opt]);

   and you wish to use the OO version, just let your mind read the above
line as:

     Usage: $win->a_simple_function($x, $y, $z [, $opt]);

   where `$win' is a PDL::Graphics::PGPLOT::Window object. That is all.

Window control functions.
-------------------------

new
---

   $opt is a reference to a hash with options for the new device. The
options recognised are the following:

AspectRatio
     The aspect ratio of the image, in the sense vertical/horisontal.

Device
     The type of device to use. The syntax of this is the one used by
     PGPLOT.

Hold
     Hold the plot window so that subsequent plots can plot over existing
     plots.  This can be adjusted with the `hold()' and release() methods.

NXPanel
     The number of panels in the X-direction

NYPanel
     The number of panels in the Y-direction

WindowName
     The name to give to the window. No particular use is made of this at
     present.  It would be great if it was possible to change the title of
     the window frame.

WindowWidth
     The width of the window in inches. If this is set to 0.0, the biggest
     window consistent with the AspectRatio setting will be chosen.

WindowXSize and WindowYSize
     These two options allow an alternative setting of WindowWidth and
     AspectRatio.  Their values are actually not parsed here, but rather
     subsequently in the _setup_window routine below.

   An important point to note is that the default values of most options
can be specified by passing these to the constructor. All general options
(common to several functions) can be adjusted in such a way, but function
specific options can not be set in this way (this is a design limitation
which is unlikely to be changed).

   Thus the following call will set up a window where the default axis
colour will be yellow and where plot lines normally have red colour and
dashed linestyle.

     $win = PDL::Graphics::PGPLOT::Window->new({Device => '/xs',
             AxisColour => 'Yellow', Colour => 'Red', LineStyle => 'Dashed'});

close
-----

   Close the current window. This does not necessarily mean that the
window is removed from your screen, but it does ensure that the device is
closed.

held
----

   Function to check whether the window is held or not.

hold
----

   Holds the present window so that subsequent plot commands overplots.

panel
-----

   Move to a different panel on the plotting surface. Note that you will
need to erase it manually if that is what you require.

release
-------

   Release a plot window so that subsequent plot commands move to the next
panel or erase the plot and create a new plot.

erase
-----

   Erase a plot area. This accepts the option `Panel' or alternatively a
number or array reference which makes it possible to specify the panel to
erase when working with several panels.

Plotting functions
------------------

env
---

   `$xmin', `$xmax', `$ymin', `$ymax' are the plot boundaries.  `$justify'
is a boolean value (default is 0); if true the axes scales will be the
same (see `' in this node).  `$axis' describes how the axes should be
drawn (see `' in this node) and defaults to 0.

   If the second form is used, $justify and $axis can be set in the options
hash, for example:

     env 0, 100, 0, 50, {JUSTIFY => 1, AXIS => 'GRID', CHARSIZE => 0.7};

   In addition the following options can also be set for env:

PlotPosition
     The position of the plot on the page relative to the view surface in
     normalised coordinates as an anonymous array. The array should contain
     the lower and upper X-limits and then the lower and upper Y-limits. To
     place two plots above each other with no space between them you could
     do

          env(0, 1, 0, 1, {PlotPosition => [0.1, 0.5, 0.1, 0.5]});
          env(5, 9, 0, 8, {PlotPosition => [0.1, 0.5, 0.5, 0.9]});

Axis, Justify, Border
     See the description of general options for these options.

AxisColour
     Set the colour of the coordinate axes.

XTitle, YTitle, Title, Font, CharSize
     Axes titles and the font and size to print them.

label_axes
----------

   Draw labels for each axis on a plot.

imag
----

   Notes: `$transform' for image/cont etc. is used in the same way as the
`TR()' array in the underlying PGPLOT FORTRAN routine but is, fortunately,
zero-offset.

   There are several options related to scaling.  By default, the image is
scaled to fit the PGPLOT default viewport on the screen.  Scaling, aspect
ratio preservation, and 1:1 pixel mapping are available.  (1:1 pixel
mapping GREATLY increases the speed of pgimag, and is useful for, eg,
movie display; but it's not recommended for final output as it's not
device-independent.)

   To draw a colour bar (or wedge), either use the `DrawWedge' option, or
the `draw_wedge()' routine (once the image has been drawn).

   Options recognised:

     ITF - the image transfer function applied to the pixel values. It
           may be one of 'LINEAR', 'LOG', 'SQRT' (lower case is
           acceptable). It defaults to 'LINEAR'.
           MIN  - Sets the minimum value to be used for calculation of the
           display stretch
           MAX  - Sets the maximum value for the same
      TRANSFORM - The transform 'matrix' as a 6x1 vector for display
           PIX  - Sets the image pixel aspect ratio.  By default, imag
           stretches the image pixels so that the final image aspect
           ratio fits the viewport exactly.  Setting PIX=>1 causes
           the image aspect ratio to be preserved.  (the image is
           scaled to avoid cropping, unless you specify scaling
           manually).  Larger numbers yield "landscape mode" pixels.
          PITCH - Sets the number of image pixels per screen unit, in the Y
           direction.  The X direction is determined by PIX, which
           defaults to 1 if PITCH is specified and PIX is not.  PITCH
           causes UNIT to default to "inches" so that it is easy to say
           100dpi by specifying {PITCH=>100}.  Larger numbers yield
           higher resolution (hence smaller appearing) images.
           UNIT - Sets the screen unit used for scaling.  Must be one of the
           PGPLOT supported units (inch, mm, pixel, normalized).  You
           can refer to them by name or by number.  Defaults to pixels
           if not specified.
          SCALE - Syntactic sugar for the reciprocal of PITCH.  Makes the
           UNIT default to "pixels" so you can say "{SCALE=>1}"
           to see your image in device pixels.   Larger SCALEs lead
           to larger appearing images.
      DrawWedge - set to 1 to draw a colour bar (default is 0)
          Wedge - see the draw_wedge() routine

   The following standard options influence this command:

     AXIS, BORDER, JUSTIFY

imag1
-----

   Notes: This is syntactic sugar for imag({PIX=>1}).

draw_wedge
----------

   Adds a wedge - shows the mapping between colour and value for a pixel -
to the current image.  This can also be achieved by setting `DrawWedge' to
1 when calling the imag routine.

   The colour and font size are the same as used to draw the image axes
(although this will probably fail if you did it yourself).  To control the
size and location of the wedge, use the `Wedge' option, giving it a hash
reference containing any of the following:

Side
     Which side of the image to draw the wedge: can be one of 'B', 'L',
     'T', or 'R'. Default is 'R'.

Displacement
     How far from the egde of the image should the wedge be drawn, in
     units of character size. To draw within the image use a negative
     value. Default is 2.

Width
     How wide should the wedge be, in units of character size.  Default is
     3.

Label
     A text label to be added to the wedge.  If set, it is probably worth
     increasing the Width value by about 1 to keep the text readable.
     Default is ".

ForeGround (synonym Fg)
     The pixel value corresponding to the "maximum" colour.  If undef,
     uses the value used by imag (recommended choice).  Default is undef.

BackGround (synonym Bg)
     The pixel value corresponding to the "minimum" colour.  If undef,
     uses the value used by imag (recommended choice).  Default is undef.

ctab
----

   Usage:

   Note: See `PDL::Graphics::LUT|PDL::Graphics::LUT' in this node for
access to a large number of colour tables.

line
----

   If the 'MISSING' option is specified, those points in the `$y' vector
which are equal to the MISSING value are not plotted, but are skipped
over.  This allows one to quickly draw multiple lines with one call to
line, for example to draw coastlines for maps.

   The following standard options influence this command:

     AXIS, BORDER, COLO(U)R, JUSTIFY, LINESTYLE, LINEWIDTH, MISSING

points
------

   Options recognised:

     SYMBOL - Either a piddle with the same dimensions as $x, containing
              the symbol associated to each point or a number specifying
              the symbol to use for every point, or a name specifying the
              symbol to use according to the following (recognised name in
     	     capital letters):
               0 - SQUARE   1 - DOT     2 - PLUS     3 - ASTERISK
               4 - CIRCLE   5 - CROSS   7 - TRIANGLE 8 - EARTH
               9 - SUN     11 - DIAMOND 12- STAR
      PLOTLINE - If this is >0 a line will be drawn through the points.

   The following standard options influence this command:

     AXIS, BORDER, CHARSIZE, COLOUR, JUSTIFY, LINESTYLE, LINEWIDTH

errb
----

   Usage:

   Options recognised:

     TERM - Length of terminals in multiples of the default length
      SYMBOL - Plot the datapoints using the symbol value given, either
            as name or number - see documentation for 'points'

   The following standard options influence this command:

     AXIS, BORDER, CHARSIZE, COLOUR, JUSTIFY, LINESTYLE, LINEWIDTH

cont
----

   Notes: `$transform' for image/cont etc. is used in the same way as the
`TR()' array in the underlying PGPLOT FORTRAN routine but is, fortunately,
zero-offset.

   Options recognised:

     CONTOURS - A piddle with the contour levels
       FOLLOW - Follow the contour lines around (uses pgcont rather than
                pgcons) If this is set >0 the chosen linestyle will be
                ignored and solid line used for the positive contours
                and dashed line for the negative contours.
       LABELS - An array of strings with labels for each contour
      LABELCOLOUR - The colour of labels if different from the draw colour
                This will not interfere with the setting of draw colour
                using the colour keyword.
      MISSING - The value to ignore for contouring
        NCONTOURS - The number of contours wanted for automatical creation,
                overridden by CONTOURS
        TRANSFORM - The pixel-to-world coordinate transform vector

   The following standard options influence this command:

     AXIS, BORDER, COLOUR, JUSTIFY, LINESTYLE, LINEWIDTH

bin
---

   Options recognised:

     CENTRE - if true, the x values denote the centre of the bin
              otherwise they give the lower-edge (in x) of the bin
     CENTER - as CENTRE

   The following standard options influence this command:

     AXIS, BORDER, COLOUR, JUSTIFY, LINESTYLE, LINEWIDTH

hi2d
----

   Options recognised:

     IOFFSET - The offset for each array slice. >0 slants to the right
                                                <0 to the left.
        BIAS - The bias to shift each array slice up by.

   The following standard options influence this command:

     AXIS, BORDER, JUSTIFY

   Note that meddling with the `ioffset' and bias often will require you to
change the default plot range somewhat. It is also worth noting that if
you have TriD working you will probably be better off using
`mesh3d|PDL::Graphics::TriD' in this node or a similar command - see
PDL/Graphics/TriD.

arrow
-----

   Plot an arrow from `$x1, $y1' to `$x2, $y2'. The arrow shape can be set
using the option Arrow. See the documentation for general options for
details about this option (and the example below):

     arrow(0, 1, 1, 2, {Arrow => {FS => 1, Angle => 60, Vent => 0.3, Size => 5}});

   which draws a broad, large arrow from (0, 1) to (1, 2).

poly
----

   Options recognised:

   The following standard options influence this command:

     AXIS, BORDER, COLOUR, FILLTYPE, HATCHING, JUSTIFY, LINESTYLE,
     LINEWIDTH

circle
------

   All arguments can alternatively be given in the options hash using the
following options:

XCenter and YCenter
     The position of the center of the circle

Radius
     The radius of the circle.

ellipse
-------

   All arguments can alternatively be given in the options hash using the
following options:

MajorAxis
     The major axis of the ellipse - this must be defined or `$a' must be
     given.

MinorAxis
     The minor axis, like A this is required.

Theta (synonym Angle)
     The orientation of the ellipse - defaults to 0.0. This is given in
     radians.

XCenter and YCenter
     The coordinates of the center of the ellipse. These must be specified
     or $x and `$y' must be given.

NPoints
     The number of points used to draw the ellipse. This defaults to 100
     and might need changing in the case of very large ellipses.

rectangle
---------

   This routine draws a rectangle with the chosen fill style. Internally
it calls `poly' in this node which is somewhat slower than `pgrect' but
which allows for rotated rectangles as well. The routine recognises the
same options as poly and in addition the following

XCenter and YCenter
     The position of the center of the rectangle. XCentre and YCentre are
     valid synonyms.

XSide and YSide
     The length of the X and Y sides. If only one is specified the shape
     is taken to be square with that as the side-length, alternatively the
     user can set Side

Side
     The length of the sides of the rectangle (in this case a square) -
     syntactic sugar for setting XSide and YSide identical. This is
     overridden by XSide or YSide if any of those are set.

Angle (synonym Theta)
     The angle at which the rectangle is to be drawn. This defaults to 0.0
     and is given in radians.

vect
----

   Notes: `$transform' for image/cont etc. is used in the same way as the
`TR()' array in the underlying PGPLOT FORTRAN routine but is, fortunately,
zero-offset.

   This routine will plot a vector field. `$a' is the horizontal component
and $b the vertical component.

   Options recognised:

     SCALE - Set the scale factor for vector lengths.
       POS - Set the position of vectors.
             <0 - vector head at coordinate
             >0 - vector base at coordinate
             =0 - vector centered on the coordinate
      TRANSFORM - The pixel-to-world coordinate transform vector
        MISSING - Elements with this value are ignored.

   The following standard options influence this command:

     ARROW, ARROWSIZE, AXIS, BORDER, CHARSIZE, COLOUR, JUSTIFY,
     LINESTYLE, LINEWIDTH

transform
---------

   This function creates a transform array in the format required by the
image and contouring routines. You must call it with the dimensions of
your image as arguments or pass these as an anonymous hash - see the
example below.

Angle
     The rotation angle of the transform

ImageDimensions
     The dimensions of the image the transform is required for. The
     dimensions should be passed as a reference to an anonymous hash.

Pixinc
     The increment in output coordinate per pixel.

ImageCenter
     The centre of the image as an anonymous array  or as a scalar. In the
     latter case the x and y value for the center will be set equal to this
     scalar. This is particularly useful in the common case  when the
     center is (0, 0).

   Example:

     $im = rvals(100, 100);
     $w = PDL::Graphics::PGPLOT::Window->new({Device => '/xs'});
     $t = $w->transform(dims($im), {ImageCenter => 0,  Pixinc => 5});
     $w->imag($im, {Transform => $t});

tline
-----

   This is a threaded interface to line. This is convenient if you have a
2D array and want to plot out every line in one go. The routine will apply
any options you apply in a "reasonable" way. In the sense that it will
loop over the options wrapping over if there are less options than lines.

   Example:

     $h={Colour => ['Red', '1', 4], Linestyle => ['Solid' ,'Dashed']};
     $tx=zeroes(100,5)->xlinvals(-5,5);
     $ty = $tx + $tx->yvals;
     tline($tx, $ty, $h);

tpoints
-------

   This is a threaded interface to points. This is convenient if you have
a 2D array and want to plot out every line in one go. The routine will
apply any options you apply in a "reasonable" way. In the sense that it
will loop over the options wrapping over if there are less options than
lines.

   Example:

     $h={Colour => ['Red', '1', 4], Linestyle => ['Solid' ,'Dashed']};
     $tx=zeroes(100,5)->xlinvals(-5,5);
     $ty = $tx + $tx->yvals;
     tpoints($tx, $ty, $h);

Text routines
-------------

text
----

   Options recognised:

`ANGLE'
     The angle in degrees between the baseline of the text and the
     horisontal (increasing counter-clockwise). This defaults to 0.

`JUSTIFICATION'
     The justification of the text relative to the position specified. It
     defaults to 0.0 which gives left-justified text. A value of 0.5 gives
     centered text and a value of 1.0 gives right-justified text.

`XPos', `YPos', Text
     These gives alternative ways to specify the text and position.

   The following standard options influence this command:

     COLOUR

legend
------

   This function adds a legend to an existing plot. The action is primarily
controlled by information in the options hash, and the basic idea is that
$x and `$y' determines the upper left hand corner of the box in which the
legend goes. If the width is specified either as an argument or as an
option in the option hash this is used to determine the optimal character
size to fit the text into part of this width (defaults to 0.5 - see the
description of `Fraction' below). The rest of the width is filled out with
either lines or symbols according to the content of the `LineStyle',
Symbol, `Colour' and `LineWidth' options.

   The local options recognised are as follows:

Text
     An anonymous array of annotations, can also be specified directly.

`XPos' and `YPos'
     The X and Y position of the upper left-hand corner of the text.

Width and `Height'
     The width and/or height of each line (including symbol/line). This is
     used to determine the character size. If any of these are set to
     'Automatic' the current character size will be used.

`Fraction'
     The text and the symbol/line is set inside a box. `Fraction'
     determines how much of this box should be devoted to text. THis
     defaults to 0.5.

`TextShift'
     This option allows for fine control of the spacing between the text
     and the start of the line/symbol. It is given in fractions of the
     total width of the legend box. The default value is 0.1.

     legend 5, 5, ['A red line', 'A blue line'],
         {LineStyle => ['Solid', 'Dashed'], Colour => ['Red', 'Blue']
          LineWidth => [undef, 10]}; # undef gives default.

Cursor routines
---------------

cursor
------

   This routine has no standard input parameters, but the type of cursor
can be set by setting the option Type as a key in the anonymous hash $opt.
The first three return values from the function are always defined and
gives the position selected by the user and the character pressed.

   Depending on the cursor type selected the last two arguments might also
be defined and these give a reference position. For instance if the cursor
is selected to be `Rectangle' then the reference position gives one of the
corners of the rectangle and $x and `$y' the diagonally opposite one.

   Options recognised:

XRef, YRef
     The reference position to be used

Type
     The type of cursor. This can be selected using a number between 0 and
     7 as in PGPLOT, or alternatively you can specify these as, Default
     (0), `RadialLine' (1), `Rectangle' (2), `TwoHorizontalLines' (3),
     `TwoVerticalLines' (4), `HorizontalLine' (5), `VerticalLine' (6) and
     `CrossHair' (7) respectively. The default cursor is just the normal
     mouse cursor.

     For the `RadialLine' you must specify the reference point, whereas for
     the `Two(Vertical|Horizontal)Lines' cursor the X or Y reference point,
     respectively, must be specified.

     ($x, $y, $ch, $xref, $yref) = cursor({Type => 'Rectangle'});
     poly pdl($x, $xref, $xref, $x, $x), pdl($y, $y, $yref, $yref, $y);

   To select a region of the X-axis:

     ($x1, $y1, $ch) = cursor({Type => 'VerticalLine'});
     ($x2, $y2, $ch) = cursor({Type => 'TwoVerticalLines', XRef => $x1});

Internal routines
-----------------

_open_new_window
----------------

   Open a new window. This sets the window ID, which is the one used when
accessing a window later using `pgslct'. It also sets the window name to
something easily remembered if it has not been set before.

_setup_window
-------------

   This routine sets up a new window with its shape and size. This is also
where the two options WindowXSize and `WindowYSize' is parsed. These are
then forgotten (well, they are stored in $self->{Options}, but forget
that) and the corresponding aspect ratio and window width is stored.

   Finally the subpanels are set up using `pgsubp' and colours and
linewidth are adjusted according to whether we have a hardcopy device or
not.

_status
-------

   This routine checks the status of the window. It returns OPEN if the
window is open and CLOSED if it is closed.

_reopen
-------

   This functions reopens a window. Since this is an internal function it
does not have a lot of error-checking. Make sure the device is closed
before calling this routine.

   There is an unfortunate problem which pops up viz. that the window name
cannot be changed at this point since we are offering that to the rest of
the world. That might be sensible, but it means that the window name will
not reflect the id of the window - use id() for that (this is also why we
do not call `open_new_window' )

_advance_panel
--------------

   This routine advances one plot panel, updating the CurrentPanel as well.
If the advance will proceed past the page the page will be erased. Also
note that when you advance one panel the hold value will be changed.

_check_move_or_erase
--------------------

   This routine is a utility routine which checks if we need to move panel,
and if so will do this. It also checks if it is necessary to advance
panels, and whether they need to be erased.

_thread_options
---------------

   This function is a cludgy utility function that expands an options hash
to an array of hashes looping over options. This is mainly of use for
"threaded" interfaces to standard plotting routines.

options
-------

   Access the options used when *originally* opening the window. At the
moment this is not updated when the window is changed later.

id
--

   Access the window ID that PGPLOT uses for the present window.

device
------

   This function returns the device type of the present window.

name
----

   Accessor to set and examine the name of a window.

focus
-----

   Set focus for subsequent PGPLOT commands to this window.

info
----

   The valid values of `@item' are as below, where case is not important:

     VERSION     - What PGPLOT version is in use
     STATE       - The status of the output device, this is returns 'OPEN'
                   if the device is open and 'CLOSED' otherwise.
     USER        - The username of the owner of the spawning program.
     NOW         - The current date and time in the format 'dd-MMM-yyyy hh:mm'.
                   Most people are likely to use Perl functions for this.
     DEVICE    * - The current PGPLOT device or file, see also C<device>
     FILE      * - The filename for the current device
     TYPE      * - And the device type for the current device
     DEV/TYPE  * - This combines DEVICE and TYPE in a form that can be used
                   as input to C<new>.
     HARDCOPY  * - This is flag which is set to 'YES' if the current device is
                   a hardcopy device and 'NO' otherwise.
     TERMINAL  * - This flag is set to 'YES' if the current device is the user's
                   terminal and 'NO' otherwise.
     CURSOR    * - A flag ('YES' or 'NO') to inform whether the current device
                   has a cursor.

   Those items marced with a * only return a valid answer if the window is
open.  A question mark (?) is returned if the item is not recognised or
the information is not available.

_extract_hash
-------------

   This routine takes and array and returns the first hash reference found
as well as those elements that are not hashes. Note the latter point
because all other references to hashes in the array will be lost.

_parse_options
--------------

   This is a convenience routine for parsing a set of options. It returns
both the full set of options and those that the user has set.

_save_status
------------

   Saves the PGPLOT state so that changes to settings can be made and then
the present state restored by _restore_status.

_restore_status
---------------

   Restore the PGPLOT state. See `_save_status' in this node.

_checkarg
---------

   This routine checks and optionally alters the arguments given to it.

_standard_options_parser
------------------------

   This internal routine is the default routine for parsing options. This
routine deals with a subset of options that most routines will accept.

INTERNAL
========

   The coding tries to follow reasonable standards, so that all functions
starting with an underscore should be considered as internal and should
not be called from outside the package. In addition most routines has a
set of options. These are encapsulated and are not accessible outside the
routine. This is to avoid collisions between different variables.

AUTHOR
======

   Karl Glazebrook [kgb@aaoepp.aao.gov.au] modified by Jarle Brinchmann
(jarle@astro.ox.ac.uk) who is also responsible for the OO interface, docs
mangled by Tuomas J. Lukka (lukka@fas.harvard.edu) and Christian Soeller
(c.soeller@auckland.ac.nz). Further contributions and bugfixes from Kaj
Wiik, Doug Burke and many others.

   All rights reserved. There is no warranty. You are allowed to
redistribute this software / documentation under certain conditions. For
details, see the file COPYING in the PDL distribution. If this file is
separated from the PDL distribution, the copyright notice should be
included in the file.

Setting PGPLOT options
**********************

NAME
====

   PDL::Graphics::PGPLOTOptions - Setting PGPLOT options

SYNOPSIS
========

   use PGPLOTOptions qw('default_options');

DESCRIPTION
===========

   This package contains one function (at present) which returns
PDL::Option objects for default settings for plot windows and plot
commands. This should be complemented by functions that could affect this
such as file reading commands etc.

OPTIONS
=======

   The following is a listing of options that are set in this file and what
they do and what their default value is

Window specfic options
----------------------

   These options modify the appearance of windows and can also modify the
default settings for creation of plot axes etc.

Device
     The default PGPLOT device to use. The default value is set to the
     PGPLOT_DEV environment variable if set, otherwise to '?'.

AxisColour
     The colour with which to draw axes

HardLW, HardCH, HardFont, HardAxisColour
     The linewidth, character height, font and axis colour to use on
     hardcopy devices.

Axis
     The axis style to use. See the PDL/Graphics/PGPLOT/Window,
     documentation for details. It defaults to
     'Normal' which is a labelled box. Valid arguments are 'Empty', 'Box',
     'Normal', 'Axes', 'Grid', 'LogX', 'LogY', 'LogXY'.

AspectRatio
     The aspect ratio of the output device it defaults to 0.618.

WindowWidth
     The width of the output window in inches and defaults to as big as
     possible.

WindowXSize and WindowYSize
     These are alternatives to AspectRatio and WindowWidth.

WindowName
     The name of the window - can later be retrieved using name(). It
     defaults to 'Window'+Window ID.

NXPanel
     The number of panels in the X-direction - defaults to 1

NYPanel
     The number of panels in the Y-direction - defaults to 1

Justify
     A boolean value which, if true, causes both axes to drawn to the same
     scale; see the PGPLOT `pgenv()' command for more information.

Border
     Adjust the spacing around the plot. See the documentation in
     PDL/Graphics/PGPLOT/Window, for details.

CharSize
     The default charsize for the plot - used when annotating the axes for
     instance.

PlotPosition
     The position of the plot in normalised coordinates.

NoErase
     Allows plotting multiple panels on one plot, normally used with
     'PlotPosition'.

Plot specific options
---------------------

   For the moment see the `PDL::Graphics::PGPLOT::Window' documentation for
these.

PDL 3D interface
****************

NAME
====

   PDL::Graphics::TriD - PDL 3D interface

SYNOPSIS
========

   use PDL::Graphics::TriD;

   # After each graph, let the user rotate is and # wait for him to press
'q', then make new graph line3d($coords);       # $coords = (3,n,...)
line3d($coords,$colors);  # $colors = (3,n,...)  line3d([$x,$y,$z]);
imagrgb([$r,$g,$b]); lattice3d([$x,$y,$z]); # 2-d piddles
points3d([$x,$y,$z]);

   hold3d(); # the following graphs are on top of each other and the
previous line3d([$x,$y,$z]); line3d([$x,$y,$z+1]); $pic = grabpic3d(); #
Returns the picture in a (3,$x,$y) float piddle (0..1).

   release3d(); # the next graph will again wipe out things.

WARNING
=======

   These modules are still in a somewhat unfocused state: don't use them
yet if you don't know how to make them work if they happen to do something
strange.

DESCRIPTION
===========

   This module implements a generic 3D plotting interface for PDL.
Points, lines and surfaces (among other objects) are supported.

   With OpenGL, it is easy to manipulate the resulting 3D objects with the
mouse in real time - this helps data visualization a lot.

   With VRML, you can generate objects for everyone to see with e.g.
Silicon Graphics' Cosmo Player. You can find out more about VRML at
`http://vrml.sgi.com/' or `http://www.vrml.org/'

SELECTING A DEVICE
==================

   The default device for TriD is currently OpenGL.  You can specify a
different device either in your program or in the environment variable
`PDL_3D_DEVICE'.  The one specified in the program takes priority.

   The currently available devices are

GL
     OpenGL

GLpic
     OpenGL but off-line (pixmap) rendering and writing to a graphics file.

VRML
     VRML objects rendering. This writes a VRML file describing the scene.
     This VRML file can then be read with  a browser.

ONLINE AND OFFLINE VISUALIZATION
================================

   TriD  offers both on- and off-line visualization.  Currently the
interface  w.r.t. this division is still much in motion.

   For OpenGL you can select either on- or off-line rendering.  VRML is
currently always offline (this may change  later, if someone bothers to
write  the  java(script)  code to  contact PDL and wait for the next PDL
image over the network.

COORDINATE SPECIFICATIONS
=========================

   Specifying a set of coordinates is generally a context-dependent
operation.  For a traditional 3D surface plot, you'll want two of the
coordinates to have just the xvals and yvals of the piddle, respectively.
For a line, you would generally want to have one coordinate held at zero
and the other advancing.

   This module tries to make a reasonable way of specifying the context
while letting you do whatever you want by overriding the default
interpretation.

   The alternative syntaxes for specifying a set of coordinates (or
colors) are

   $piddle                             # MUST have 3 as first dim.
[$piddle]   [$piddle1,$piddle2]   [$piddle1,$piddle2,$piddle3]
[CONTEXT,$piddle]   [CONTEXT,$piddle1,$piddle2]
[CONTEXT,$piddle1,$piddle2,$piddle3]

   where CONTEXT is a string describing in which context you wish these
piddles to be interpreted. Each routine specifies a default context which
is explained in the routines documentation.  Context is usually used only
to understand what the user wants when he/she specifies less than 3
piddles.

   The following contexts are currently supported:

SURF2D
     A 2-D lattice. [$piddle] is interpreted as the Z coordinate over a
     lattice over the first dimension. Equivalent to [$piddle->xvals,
     $piddle->yvals, $piddle].

POLAR2D
     A 2-D polar coordinate system. [$piddle] is interpreted as the z
     coordinate over theta and r (theta = the first dimension of the
     piddle).

COLOR
     A set of colors. [$piddle] is interpreted as grayscale color
     (equivalent to [$piddle,$piddle,$piddle]).

LINE
     A line made of 1 or 2 coordinates. [$piddle] is interpreted as
     [$piddle->xvals,$piddle,0]. [$piddle1,$piddle2] is interpreted as
     [$piddle1,$piddle2,$piddle1->xvals].

   What makes contexts useful is that if you want to plot points instead
of the full surface you plotted with

     imag3d([$zcoords]);

   you don't need to start thinking about where to plot the points:

     points3d([SURF2D,$zcoords]);

   will do exactly the same.

SIMPLE ROUTINES
===============

   Because using the whole object-oriented interface for doing all your
work might be cumbersome, the following shortcut routines are supported:

FUNCTIONS
=========

line3d
------

     perldl> line3d [sqrt(rvals(zeroes(50,50))/2)]
     - Lines on surface
     perldl> line3d [$x,$y,$z]
     - Lines over X, Y, Z
     perldl> line3d $coords
     - Lines over the 3D coordinates in $coords.

   Note: line plots differ from mesh plots in that lines only go in one
direction. If this is unclear try both!

   See module documentation for more information on contexts and options

imag3d
------

     perldl> imag3d [sqrt(rvals(zeroes(50,50))/2)], {{Lines=>0};

     - Rendered image of surface

   See module documentation for more information on contexts and options

mesh3d
------

     perldl> mesh3d [sqrt(rvals(zeroes(50,50))/2)]

     - mesh of surface

   Note: a mesh is defined by two sets of lines at right-angles (i.e. this
is how is differs from line3d).

   See module documentation for more information on contexts and options

lattice3d
---------

points3d
--------

     perldl> points3d [sqrt(rvals(zeroes(50,50))/2)];
     - points on surface

   See module documentation for more information on contexts and options

imagrgb
-------

   This would be used to plot an image, specifying red, green and blue
values at each point. Note: contexts are very useful here as there are many
ways one might want to do this.

     perldl> $a=sqrt(rvals(zeroes(50,50))/2)
     perldl> imagrgb [0.5*sin(8*$a)+0.5,0.5*cos(8*$a)+0.5,0.5*cos(4*$a)+0.5]

imagrgb3d
---------

   The piddle gives the colors. The option allowed is Points, which should
give 4 3D coordinates for the corners of the polygon, either as a piddle
or as array ref.  The default is [[0,0,0],[1,0,0],[1,1,0],[0,1,0]].

     perldl> imagrgb3d $colors, {Points => [[0,0,0],[1,0,0],[1,0,1],[0,0,1]]};
     - plot on XZ plane instead of XY.

grabpic3d
---------

   The returned piddle has dimensions (3,$x,$y) and is of type float
(currently). XXX This should be altered later.

hold3d, release3d
-----------------

   or

     hold3d(1);
     hold3d(0);

keeptwiddling3d, nokeeptwiddling3d
----------------------------------

   Usually, when showing 3D images, the user is given a chance to rotate
it and then press 'q' for the next image. However, sometimes (for e.g.
animation) this is undesirable and it is more desirable to just run one
step of the event loop at a time.

   or

     keeptwiddling3d(1);
     keeptwiddling3d(0);

   When an image is added to the screen, keep twiddling it until user
explicitly presses 'q'.

twiddle3d
---------

   Let the user rotate the image in 3D space, either for one step or until
(s)he presses 'q', depending on the 'keeptwiddling3d' setting. If
'keeptwiddling3d' is not set the routine returns immediately and indicates
that a 'q' event was received by returning 1. If the only events received
were mouse events, returns 0.

CONCEPTS
========

   The key concepts (object types) of TriD are explained in the following:

Object
------

   In this 3D abstraction, everything that you can "draw" without using
indices is an Object. That is, if you have a surface, each vertex is not
an object and neither is each segment of a long curve. The whole curve (or
a set of curves) is the lowest level Object.

   Transformations and groups of Objects are also Objects.

   A Window is simply an Object that has subobjects.

Twiddling
---------

   Because there is no eventloop in Perl yet and because it would be
hassleful to do otherwise, it is currently not possible to e.g. rotate
objects with your mouse when the console is expecting input or the program
is doing other things. Therefore, you need to explicitly say
"$window->twiddle()" in order to display anything.

OBJECTS
=======

   The following types of objects are currently supported.  Those that do
not have a calling sequence described here should have their own manual
pages.

   There are objects that are not mentioned here; they are either internal
to PDL3D or in rapidly changing states. If you use them, you do so at your
own risk.

   The syntax PDL::Graphics::TriD::Scale(x,y,z) here means that you create
an object like

     $a = new PDL::Graphics::TriD::Scale($x,$y,$z);

PDL::Graphics::TriD::LineStrip
------------------------------

   This is just a line or a set of lines. The arguments are 3 1-or-more-D
piddles which describe the vertices of a continuous line and an optional
color piddle (which is 1-D also and simply defines the color between red
and blue. This will probably change).

PDL::Graphics::TriD::Lines
--------------------------

   This is just a line or a set of lines. The arguments are 3 1-or-more-D
piddles where each contiguous pair of vertices describe a line segment and
an optional color piddle (which is 1-D also and simply defines the color
between red and blue. This will probably change).

PDL::Graphics::TriD::Image
--------------------------

   This is a 2-dimensional RGB image consisting of colored rectangles.
With OpenGL, this is implemented by texturing so this should be relatively
memory and execution-time-friendly.

PDL::Graphics::TriD::Lattice
----------------------------

   This is a 2-D set of points connected by lines in 3-space.  The
constructor takes as arguments 3 2-dimensional piddles.

PDL::Graphics::TriD::Points
---------------------------

   This is simply a set of points in 3-space. Takes as arguments the x, y
and z coordinates of the points as piddles.

PDL::Graphics::TriD::Scale(x,y,z)
---------------------------------

   Self-explanatory

PDL::Graphics::TriD::Translation(x,y,z)
---------------------------------------

   Ditto

PDL::Graphics::TriD::Quaternion(c,x,y,z)
----------------------------------------

   One way of representing rotations is with quaternions. See the
appropriate man page.

PDL::Graphics::TriD::ViewPort
-----------------------------

   This is a special class: in order to obtain a new viewport, you need to
have an earlier viewport on hand. The usage is:

     $new_vp = $old_vp->new_viewport($x0,$y0,$x1,$y1);

   where $x0 etc are the coordinates of the upper left and lower right
corners of the new viewport inside the previous (relative to the previous
viewport in the (0,1) range.

   Every implementation-level window object should implement the
new_viewport method.

BUGS
====

   Not enough is there yet.

AUTHOR
======

   Copyright (C) 1997 Tuomas J. Lukka (lukka@husc.harvard.edu).
Documentation contributions from Karl Glazebrook (kgb@aaoepp.aao.gov.au).
All rights reserved. There is no warranty. You are allowed to redistribute
this software / documentation under certain conditions. For details, see
the file COPYING in the PDL distribution. If this file is separated from
the PDL distribution, the copyright notice should be included in the file.

default event handler subroutines
*********************************

NAME
====

   PDL::Graphics::TriD::ButtonControl - default event handler subroutines

FUNCTIONS
=========

new()
-----

mouse_moved
-----------

   sub mouse_moved{   print "mouse_moved @_\n" if
$PDL::Graphics::TriD::verbose; }

ButtonRelease
-------------

   sub ButtonRelease{   my ($this,$x,$y) = @_;   $this->{Win}{Active} = 0;
 print "ButtonRelease @_\n"  if $PDL::Graphics::TriD::verbose; }

ButtonPressed
-------------

set_wh
------

3D Surface contours for TriD
****************************

NAME
====

     PDL::Graphics::TriD::Contours - 3D Surface contours for TriD

SYNOPSIS
========

     use PDL::Graphics::TriD;
     use PDL::Graphics::TriD::Contours;
     $size = 25;
     $x = (xvals zeroes $size,$size) / $size;
     $y = (yvals zeroes $size,$size) / $size;
     $z = (sin($x*6.3) * sin($y*6.3)) ** 3;
     $data=new PDL::Graphics::TriD::Contours($z,
                [$z->xvals/$size,$z->yvals/$size,0]);
     PDL::Graphics::TriD::graph_object($data)

FUNCTIONS
=========

new()
-----

   where $d is a 2D pdl of data to be contoured. [$x,$y,$z] define a 3D
map of $d into the visualization space [$r,$g,$b] is an optional [3,1]
piddle specifing the contour color and $options is a hash reference to a
list of options documented below.  Contours can also be colored by value
using the set_color_table function.

     If ContourVals is specified ContourInt, ContourMin, and ContourMax
     are ignored.  If no options are specified, the algorthym tries to
     choose values based on the data supplied.  Font can also be specified or
     overwritten by the addlabels() function below.

addlabels()
-----------

   $labelint is the integer interval between labeled contours.  If you
have 8 countour levels and specify $labelint=3 addlabels will attempt to
label the 1st, 4th, and 7th contours.  $labelint defaults to 1.

   $segint specifies the density of labels on a single contour level.
Each contour level consists of a number of connected line segments,
$segint defines how many of these segments get labels.  $segint defaults
to 5, that is every fifth line segment will be labeled.

set_colortable($table)
----------------------

coldhot_colortable()
--------------------

Text tools
**********

NAME
====

   PDL::Graphics::TriD::Labels - Text tools

SYNOPSIS
========

     my $l = new PDL::Graphics::TriD::Labels($lablepoints,
     					  {Strings=>$strlist
     					   ,Font=>$font});

WARNING
=======

   This module is experimental and the interface will probably change.

DESCRIPTION
===========

   This module is used to write Labels on the graphs of TriD

AUTHOR
======

   Copyright (C) 1997 Tuomas J. Lukka (lukka@husc.harvard.edu).
   2000 James P.  Edwards (jedwards@inmet.gov.br) All rights reserved.
There is no warranty. You are allowed to redistribute this software /
documentation under certain conditions. For details, see the file COPYING
in the PDL distribution. If this file is separated from the PDL
distribution, the copyright notice should be included in the file.

Mathematical Graph objects for PDL
**********************************

NAME
====

   PDL::Graphics::TriD::MathGraph - Mathematical Graph objects for PDL

SYNOPSIS
========

   see the file Demos/TriD/tmathgraph.p in the PDL distribution.

WARNING
=======

   This module is experimental and the interface will probably change.

DESCRIPTION
===========

   This module exists for plotting mathematical graphs (consisting of
nodes and arcs between them) in 3D and optimizing the placement of the
nodes so that the graph is visualizable in a clear way.

AUTHOR
======

   Copyright (C) 1997 Tuomas J. Lukka (lukka@husc.harvard.edu).

   All rights reserved. There is no warranty. You are allowed to
redistribute this software / documentation under certain conditions. For
details, see the file COPYING in the PDL distribution. If this file is
separated from the PDL distribution, the copyright notice should be
included in the file.

Simple Graph Objects for TriD
*****************************

NAME
====

     PDL::Graphics::TriD::Objects - Simple Graph Objects for TriD

SYNOPSIS
========

     Look in PDL/Demos/TkTriD_demo.pm for several examples, the code
     in PDL/Demos/TriD1.pm and PDL/Demos/TriD2.pm also uses objects
     but it hides them from the user.

DESCRIPTION
===========

   GObjects can be either stand-alone or in Graphs, scaled properly.  All
the points used by the object must be in the member {Points}.  I guess we
can afford to force data to be copied (X,Y,Z) -> (Points)...

OBJECTS
=======

PDL::Graphics::TriD::GObject
----------------------------

   Inherits from base PDL::Graphics::TriD::Object and adds fields Points,
Colors and Options.  Need lots more here...

Helper routines for Three-dimensional graphics
**********************************************

NAME
====

     PDL::Graphics::TriD::Rout - Helper routines for Three-dimensional graphics

DESCRIPTION
===========

   This module is for miscellaneous PP-defined utility routines for the
PDL::Graphics::TriD module. Currently, there are

FUNCTIONS
=========

combcoords
----------

   Combine x, y and z to a single piddle the first dimension of which is
3. This routine does dataflow automatically.

repulse
-------

   repulse uses a hash table of cubes to quickly calculate a repulsive
force that vanishes at infinity for many objects. For use by the module
`PDL::Graphics::TriD::MathGraph|PDL::Graphics::TriD::MathGraph' in this
node.  For definition of the potential, see the actual function.

attract
-------

   attract is used to calculate an attractive force for many objects, of
which some attract each other (in a way like molecular bonds).  For use by
the module `PDL::Graphics::TriD::MathGraph|PDL::Graphics::TriD::MathGraph'
in this node.  For definition of the potential, see the actual function.

vrmlcoordsvert
--------------

contour_segments
----------------

   $c is a contour value (or a list of contour values)

   $data is an [m,n] array of values at each point

   `$points' is a list of [3,m,n] points, it should be a grid
monotonically increasing with m and n.

   contour_segments returns a reference to a Perl array of line segments
associated with each value of $c.  It does not (yet) handle missing data
values.

Algorthym
     The data array represents samples of some field observed on the
     surface described by points.  For each contour value we look for
     intersections on the line segments joining points of the data.  When
     an intersection is found we look to the adjoining line segments for
     the other end(s) of the line segment(s).  So suppose we find an
     intersection on an x-segment.  We first look down to the left
     y-segment, then to the right y-segment and finally across to the next
     x-segment.  Once we find one in a box (two on a point) we can quit
     because there can only be one.  After we are done with a given
     x-segment, we look to the leftover possibilities for the adjoining
     y-segment.  Thus the contours are built as a collection of line
     segments rather than a set of closed polygons.

AUTHOR
======

   Copyright (C) 2000 James P. Edwards Copyright (C) 1997 Tuomas J. Lukka.
All rights reserved. There is no warranty. You are allowed to redistribute
this software / documentation under certain conditions. For details, see
the file COPYING in the PDL distribution. If this file is separated from
the PDL distribution, the copyright notice should be included in the file.

A Tk widget interface to the PDL::Graphics::TriD.
*************************************************

NAME
====

   PDL::Graphics::TriD::Tk - A Tk widget interface to the
PDL::Graphics::TriD.

SYNOPSIS
========

     my $MW = MainWindow->new();
     my $TriDW = $MW->Tk( )->pack(-expand=>1, -fill=>'both');
     $TriDW->MainLoop;

DESCRIPTION
===========

   The widget is composed of a Frame and the Display device of the TriD
output.  It inherits all of the attributes of a Tk Frame.  All of the
events associated with this window are handled through Tk with the
exception of the <expose> event which must be handled by TriD because the
Frame is never exposed.  Default Mouse bindings, defined for button1 and
button3, control TriD object orientation and size respectively.

FUNCTIONS
=========

Populate
--------

MainLoop
--------

GLinit
------

refresh
-------

AUTOLOAD
--------

buttonmotion
------------

Author
======

   *James P. Edwards, Instituto Nacional de Meteorologia Brasil*

   jedwards@inmet.gov.br

TriD VRML backend
*****************

NAME
====

   PDL::Graphics::TriD::VRML - TriD VRML backend

SYNOPSIS
========

     BEGIN { $PDL::Graphics::TriD::device = "VRML"; }

     use PDL::Graphics::TriD;
     use PDL::LiteF;

     # set some vrml parameters
     my $set = tridsettings(); # get the defaults
     $set->browser_com('netscape/unix');
     $set->compress();
     $set->file('/www-serv/vrml/dynamic_scene.wrl.gz');

     line3d([$x,$y,$z]); # plot some lines and view the scene with a browser

DESCRIPTION
===========

   This module implements the VRML for PDL::Graphics::TriD (the generic 3D
plotting interface for PDL). You can use this backend either (a) for
generating 3D graphics on your machine which can be directly viewed with a
VRML browser or (b) generate dynamic VRML worlds to distribute over the
web.

   With VRML, you can generate objects for everyone to see with e.g.
Silicon Graphics' Cosmo Player. You can find out more about VRML at
`http://vrml.sgi.com/' or `http://www.vrml.org/'

BUGS
====

   Probably incomplete/buggy implementation of some TriD features.

AUTHOR
======

   Copyright (C) 1997, 1998 Christian Soeller (c.soeller@auckland.ac.nz).
All rights reserved. There is no warranty. You are allowed to redistribute
this software / documentation under certain conditions. For details, see
the file COPYING in the PDL distribution. If this file is separated from
the PDL distribution, the copyright notice should be included in the file.

2D data browser for PDL
***********************

NAME
====

   PDL::IO::Browser - 2D data browser for PDL

DESCRIPTION
===========

   cursor terminal browser for piddles.

SYNOPSIS
========

     use PDL::IO::Browser;

FUNCTIONS
=========

browse
------

browse
------

   This uses the CURSES library to allow one to scroll around a PDL array
using the cursor keys.

AUTHOR
======

   Copyright (C) Robin Williams 1997 (rjrw@ast.leeds.ac.uk).  All rights
reserved. There is no warranty. You are allowed to redistribute this
software / documentation under certain conditions. For details, see the
file COPYING in the PDL distribution. If this file is separated from the
PDL distribution, the copyright notice should be included in the file.

A simple, fast and convenient io format for PerlDL.
***************************************************

NAME
====

   PDL::IO::FastRaw - A simple, fast and convenient io format for PerlDL.

SYNOPSIS
========

     use PDL;
     use PDL::IO::FastRaw;

     writefraw($pdl,"fname");         # write a raw file

     $pdl2 = readfraw("fname");       # read a raw file
     $pdl2 = PDL->readfraw("fname");

     $pdl3 = mapfraw("fname2",{ReadOnly => 1}); # mmap a file, don't read yet

     $pdl4 = maptextfraw("fname3",{...}); # map a text file into a 1-D pdl.

DESCRIPTION
===========

   This is a very simple and fast io format for PerlDL.  The disk data
consists of two files, a header metadata file in ASCII and a binary file
consisting simply of consecutive bytes, shorts or whatever.

   It is hoped that this will not only make for a simple PerlDL module for
saving and retrieving these files but also make it easy for other programs
to use these files.

   The format of the ASCII header is simply

     <typeid>
     <ndims>
     <dim0> <dim1> ...

   The binary files are in general NOT interchangeable between different
architectures since the binary file is simply dumped from the memory
region of the piddle.  This is what makes the approach efficient.

   It is also possible to mmap the file which can give a large speedup in
certain situations as well as save a lot of memory by using a disk file as
virtual memory. When a file is mapped, parts of it are read only as they
are accessed in the memory (or as the kernel decides: if you are reading
the pages in order, it may well preread some for you).

   Note that memory savings and copy-on-write are operating-system
dependent - see Core.xs and your operating system documentation for exact
semantics of whatever. Basically, if you write to a mmapped file without
ReadOnly, the change will be reflected in the file immediately. ReadOnly
doesn't really make it impossible to write to the piddle but maps the
memory privately so the file will not be changed when you change the
piddle. Be aware though that mmapping a 40Mb file without ReadOnly spends
no virtual memory but with ReadOnly it does reserve 40Mb.

FUNCTIONS
=========

readfraw
--------

writefraw
---------

mapfraw
-------

Dims, Datatype
     If creating a new file or if you want to specify your own header data
     for the file, you can give an array reference and a scalar,
     respectively.

Creat
     Create the file. Also writes out a header for the file.

Trunc
     Set the file size. Automatically enabled with Creat. NOTE: This also
     clears the file to all zeroes.

ReadOnly
     Disallow writing to the file.

maptextfraw
-----------

   Note that this function maps the raw format so if you are using an
operating system which does strange things to e.g.  line delimiters upon
reading a text file, you get the raw (binary) representation.

   The file doesn't really need to be text but it is just mapped as one
large binary chunk.

   This function is just a convenience wrapper which firsts stats the file
and sets the dimensions and datatype.

BUGS
====

   Should be documented better. writefraw and readfraw should also have
options (the author nowadays only uses mapfraw ;)

AUTHOR
======

   Copyright (C) Tuomas J. Lukka 1997.  All rights reserved. There is no
warranty. You are allowed to redistribute this software / documentation
under certain conditions. For details, see the file COPYING in the PDL
distribution. If this file is separated from the PDL distribution, the
copyright notice should be included in the file.

A flexible binary i/o format for PerlDL.
****************************************

NAME
====

   PDL::IO::FlexRaw - A flexible binary i/o format for PerlDL.

SYNOPSIS
========

     use PDL;
     use PDL::IO::FlexRaw;

     ($x,$y,...) = readflex("filename" [, $hdr])
     ($x,$y,...) = mapflex("filename" [, $hdr] [, $opts])

     $hdr = writeflex($file, $pdl1, $pdl2,...)
     writeflexhdr($file, $hdr)

DESCRIPTION
===========

   FlexRaw is a generic method for the input and output of `raw' data
arrays.  In particular, it is designed to read output from FORTRAN 77
UNFORMATTED files and the low-level C write function, even if the files
are compressed or gzipped.  As in FastRaw, the data file is supplemented
by a header file (although this can be replaced by the optional `$hdr'
argument).  More information can be included in the header file than for
FastRaw - the description can be extended to several data objects within a
single input file.

   For example, to read the output of a FORTRAN program

     real*4 a(4,600,600)
     open (8,file='banana',status='new',form='unformatted')
     write (8) a
     close (8)

   the header file (`banana.hdr') could look like

     # FlexRaw file header
     # Header word for F77 form=unformatted
     Byte 1 4
     # Data
     Float 3            # this is ignored
              4 600 600
     Byte 1 4           As is this, as we've got all dims

   The data can then be input using

     $a = (readflex('banana'))[1];

   The format of the hdr file is an extension of that used by FastRaw.
Comment lines (starting with #) are allowed, as are descriptive names (as
elsewhere: byte, short, ushort, long, float, double) for the data types -
note that case is ignored by FlexRaw.  After the type, one integer
specifies the number of dimensions of the data `chunk', and subsequent
integers the size of each dimension.  So the specifier above (`Float 3 4
600 600') describes our FORTRAN array.  A scalar can be described as
`float 0' (or `float 1 1', or `float 2 1 1', etc.).  When all the
dimensions are read - or a # appears after whitespace - the rest of the
current input line is ignored.

   What about the extra 4 bytes at the head and tail, which we just threw
away?  These are added by FORTRAN (at least on Suns, Alphas and Linux),
and specify the number of bytes written by each WRITE - the same number is
put at the start and the end of each chunk of data.  You may need to know
all this in some cases.  In general, FlexRaw tries to handle it itself, if
you simply add a line saying `f77' to the header file, before any data
specifiers:

     # FlexRaw file header for F77 form=unformatted
     F77
     # Data
     Float 3
     4 600 600

   - the redundancy in FORTRAN data files even allows FlexRaw to
automatically deal with files written on other machines which use
back-to-front byte ordering.  This won't always work - it's a 1 in 4
billion chance it won't, even if you regularly read 4Gb files!  Also, it
currently doesn't work for compressed files, so you can say `swap' (again
before any data specifiers) to make certain the byte order is swapped.

   The optional `$hdr' argument allows the use of an anonymous array to
give header information, rather than using a .hdr file.  For example,

     $header = [
         {Type => 'f77'},
         {Type => 'float', NDims => 3, Dims => [ 4,600,600 ] }
     ];
     @a = readflex('banana',$header);

   reads our example file again.  As a special case, when NDims is 1, Dims
may be given as a scalar.

   Within PDL, readflex and writeflex can be used to write several pdls to
a single file - e.g.

     use PDL;
     use PDL::IO::FastRaw;

     @pdls = ($pdl1, $pdl2, ...);
     $hdr = writeflex("fname",@pdls);
     @pdl2 = readflex("fname",$hdr);

     writeflexhdr("fname",$hdr);
     @pdl3 = readflex("fname");

   - writeflex produces the data file and returns the file header as an
anonymous hash, which can be written to a .hdr file using writeflexhdr.

   The reading of compressed data is switched on automatically if the
filename requested ends in .gz or .Z, or if the originally specified
filename does not exist, but one of these compressed forms does.

   Mapflex memory maps, rather than reads, the data files.  Its interface
is similar to `readflex'.  Extra options specify if the data is to be
loaded `ReadOnly', if the data file is to be `Creat'-ed anew on the basis
of the header information or `Trunc'-ated to the length of the data read.
The extra speed of access brings with it some limitations: mapflex won't
read compressed data, auto-detect f77 files or read f77 files written by
more than a single unformatted write statement.  More seriously, data
alignment constraints mean that mapflex cannot read some files, depending
on the requirements of the host OS (it may also vary depending on the
setting of the `uac' flag on any given machine).  You may have run into
similar problems with common blocks in FORTRAN.

   For instance, floating point numbers may have to align on 4 byte
boundaries - if the data file consists of 3 bytes then a float, it cannot
be read.  Mapflex will warn about this problem when it occurs, and return
the PDLs mapped before the problem arose.  This can be dealt with either
by reorganizing the data file (large types first helps, as a
rule-of-thumb), or more simply by using `readflex'.

BUGS
====

   The test on two dimensional byte arrays fail using g77 2.7.2, but not
Sun f77.  I hope this isn't my problem!

   Assumes gzip is on the PATH.

   Can't auto-swap compressed files, because it can't seek on them.

   The header format may not agree with that used elsewhere.

   Should it handle handles?

   Mapflex should warn and fallback to reading on SEGV?  Would have to
make sure that the data was written back after it was `destroyed'.

FUNCTIONS
=========

readflex
--------

writeflex
---------

mapflex
-------

AUTHOR
======

   Copyright (C) Robin Williams <rjrw@ast.leeds.ac.uk> 1997.  All rights
reserved. There is no warranty. You are allowed to redistribute this
software / documentation under certain conditions. For details, see the
file COPYING in the PDL distribution. If this file is separated from the
PDL distribution, the copyright notice should be included in the file.

Grib file utilities for perl
****************************

NAME
====

   PDL::IO::Grib - Grib file utilities for perl

SYNOPSIS
========

     use PDL;
     use PDL::IO::Grib;

     $gh = new PDL::IO::Grib;
     $gh->readgrib("filename");
     $gh->getfield("fieldname");

DESCRIPTION
===========

   Grib.pm allows the user to read files in the grib FORM FM 92-IX Ext.
GRIB Edition 1 - it may not read all possible grib format combinations.
The Grib format has 4 sections (PDS, GDS, BMS, BDS), two of which (GDS,
BMS) are optional.  Each field of a section is described in the definition
by an offset in bytes from the beginning of the section and a length.  The
contents of each field can vary widely according to the center of origin
of the data.  This decoder reads the entire section into a PDL and only
decodes fields on request, it has a default decoding method and allows the
user to define methods not known to this decoder.  So for example, the
first 3 bytes of the PDS section describes the length of that section,
each of the next 10 bytes can be decoded as unsigned integers.  Bytes 11
and 12 may be two seperate integers or one two-byte integer depending on
the value of byte 10.  It gets worse from there...

FUNCTIONS
=========

new
---

Grib::readgrib
--------------

Grib::getfield
--------------

Grib::showinventory
-------------------

get_grib1_date()
----------------

anyfield
--------

.gribtables
===========

   The .gribtables file is searched for first in the working directory then
in the user's home directory.  The format is rather simple - anything
following a *#* sign is a comment otherwise a

   name:pds[9]:pds[4]:pds[10]:pds[11]:pds[12]

   is expected where name can be anything as long as it begins with an
alpha character and does not containb{:} and the pds[#] refers to the
octet number in the pds sector of the grib file.  Fields 11 and 12 are
optional in the file and if not found all of the records which match
fields 9 4 10 will be combined into a single 3d dataset by getfield

   So suppose the file .gribtables contains the entry

   T_PG:11:2:100

   to specify 3d temperature on a pressure grid, then to get the 500mb
pressure you would do

   $t500 = $gh->getfield ("T_PG:500");

Author
======

   Jim Edwards <jedwards@inmet.gov.br>

Field tools for Grib files
**************************

NAME
====

     PDL::IO::Grib::Field - Field tools for Grib files

SYNOPSIS
========

     use PDL;
     use PDL::IO::Grib;

     $gh = new PDL::IO::Grib;
     $gh->readgrib("filename");
     $gh->getfield("fieldname");
     $f = $gh->anyfield();

DESCRIPTION
===========

   Field.pm gives you access to the individual fields of a Grib file. Here
is the code that attempts to decipher each of the sections associated with
the format.  All of the data is read into PDLs (one for each section) and
it only deciphers those pdls on demand.  It only knows how to decipher a
small subset of the possibilities at this time, but should allow the
developer to write and test new or local decipher methods easily.  Of
course if you write a new method and can cleanly merge it with whats
working please feel free to send it back to me.

FUNCTIONS
=========

new
---

name
----

id
--

initialize
----------

read_section
------------

pds_has_octet12
---------------

pds_attribute
-------------

gds_attribute
-------------

bms_attribute
-------------

bds_attribute
-------------

section_dump
------------

PDL::packint3
-------------

PDL::unpackint3
---------------

PDL::packint2
-------------

PDL::unpackint2
---------------

gds_vertical_parameters
-----------------------

read_data
---------

write_bds
---------

write
-----

shamelessly stolen code
***********************

NAME
====

     PDL::IO::Grib::Wgrib - shamelessly stolen code

SYNOPSIS
========

     Helper routines for PDL::IO::Grib

DESCRIPTION
===========

   This module is for miscellaneous PP-defined utility routines for the
PDL::IO::Grib module.

AUTHOR
======

   Copyright (C) 2000 James P. Edwards All rights reserved. There is no
warranty. You are allowed to redistribute this software / documentation
under certain conditions. For details, see the file COPYING in the PDL
distribution. If this file is separated from the PDL distribution, the
copyright notice should be included in the file.

FUNCTIONS
=========

BDSunpack
---------

decode_ref_val
--------------

encode_ref_val
--------------

misc IO routines for PDL
************************

NAME
====

   PDL::IO::Misc - misc IO routines for PDL

DESCRIPTION
===========

   A mixture of basic I/O functionality

SYNOPSIS
========

     use PDL::IO::Misc;

FUNCTIONS
=========

rfits()
-------

   Suffix magic:

     # Automatically uncompress via gunzip pipe
     $pdl = rfits('file.fits.gz');
     # Automatically uncompress via uncompress pipe
     $pdl = rfits('file.fits.Z');

     $pdl = rfits('file.fits[2]'); # Read HDU extension #2
     $pdl = rfits('file.fits.gz[3]'); # Read HDU extension #3

   The default is to read the primary HDU. One can read other HDU's by
using the [n] syntax, the second one is [1]. This works as long as they
are IMAGE extensions - this module does not do FITS tables!

   FITS Headers stored in piddle and can be retrived with $a->gethdr.  The
`hdrcpy|PDL::Core' in this node flag of the piddle is set so that the
header is copied to new piddles.

   This header is a reference to a hash where the hash keys are the
keywords in the FITS header. It is important to note that for strings, the
surrounding quotes are kept to ensure that strings that look like numbers
are kept as strings. This is also of importance if you create your own
header information and you want the value to be printed out as a string.
Each record (comprising keyword, value, and any comment string) must fit
within 80 characters; any value that is too long is truncated (silently).

   Comments in headers are stored as `$$h{COMMENT}{<Keyword>}' where $h is
the header retrieved with `$a->gethdr'.  History entries in the header are
stored as `$$h{HISTORY}', which is an anonymous array for each HISTORY
entry in the header.

wfits()
-------

   Suffix magic:

     # Automatically compress through pipe to gzip
     wfits $pdl, 'filename.fits.gz';
     # Automatically compress through pipe to compress
     wfits $pdl, 'filename.fits.Z';

   $BITPIX is optional and coerces the output format.

rcols()
-------

   There are two calling conventions - the old version, where a pattern
can be specified after the filename/handle, and the new version where
options are given as as hash reference. This reference can be given as
either the second or last argument.

   The default behaviour is to ignore lines beginning with a # character
and lines that only consist of whitespace. Options exist to only read from
lines that match, or do not match, supplied patterns, and to set the types
of the created piddles.

   Can take file name or *HANDLE, and if no columns are specified, all are
assumed. For the allowed types, see `Datatype_conversions', see
PDL/Core.

   Options:

   EXCLUDE or IGNORE - ignore lines matching this pattern (default
*'/^#/'*).

   INCLUDE or KEEP - only use lines which match this pattern (default ").

   LINES - which line numbers to use. Line numbers start at 0 and the
syntax is 'a:b:c' to use every c'th matching line between a and b (default
").

   DEFTYPE - default data type for stored data (if not specified, use the
type stored in `$PDL::IO::Misc::deftype', which starts off as double).

   TYPES - reference to an array of data types, one element for each column
to be read in.  Any missing columns use the DEFTYPE value (default []).

   PERLCOLS - an array of column numbers which are to be read into perl
arrays rather than piddles. References to these arrays are returned after
the requested piddles (default undef).

     # read in lines containing the string foo, where the first
     # example also ignores lines that with a # character.
     ($x,$y,$z) = rcols 'file2', 0,4,5, { INCLUDE => '/foo/' };
     ($x,$y,$z) = rcols 'file2', 0,4,5,
                    { INCLUDE => '/foo/', EXCLUDE => '' };

     # ignore the first 27 lines of the file, reading in as ushort's
     ($x,$y) = rcols 'file3', { LINES => '27:-1', DEFTYPE => ushort };
     ($x,$y) = rcols 'file3',
                 { LINES => '27:', TYPES => [ ushort, ushort ] };

     # read in the first column as a perl array and the next two as piddles
     ($x,$y,$name) = rcols 'file4', 1, 2, { PERLCOLS => [ 0 ] };
     printf "Number of names read in = %d\n", 1 + $#$name;

   Notes:

   1. Quotes are required on patterns.

   2. Columns are separated by whitespace by default, use
`$PDL::IO::Misc::colsep' to specify an alternate separator.

   3. For PDL-2.003, the meaning of the 'c' value in the LINES option has
changed: it now only counts matching lines rather than all lines as in
previous versions of PDL.

   4. LINES => '-1:0:3' may not work as you expect, since lines are skipped
when read in, then the whole array reversed.

wcols()
-------

   If no columns are specified all are assumed.  Will optionally only
process lines matching a pattern.  Can take file name or *HANDLE, and if
no file/filehandle is given defaults to STDOUT.

   Options:

   HEADER - prints this string before the data. If the string is not
terminated by a newline, one is added (default ").

   e.g.,

     wcols "%10.3f", $a,$b; # Formatted
     wcols "%10.3f %10.5g", $a,$b; # Individual column formatting

     wcols $a,$b, { HEADER => "#   a   b" };

   Note: columns are separated by whitespace by default, use
$PDL::IO::Misc::colsep to specify an alternate separator.

swcols()
--------

rgrep()
-------

   Usage

   e.g.

   i.e. the vectors `$a' and $b get the progressive values of $1, $2 etc.

rdsa()
------

   Requires non-PDL DSA module. Contact Frossie (frossie@jach.hawaii.edu)
Usage:

   Not yet tested with PDL-1.9X versions

isbigendian()
-------------

rasc()
------

rcube
-----

   This IO function allows direct reading of files into a large data cube,
Obviously one could use cat() but this is more memory efficient.

   The reading function (e.g. rfits, readfraw) (passed as a reference) and
files are the arguments.

   The cube is created as the same X,Y dims and datatype as the first
image specified. The Z dim is simply the number of images.

bswap2
------

bswap4
------

bswap8
------

AUTHOR
======

   Copyright (C) Karl Glazebrook 1997.  All rights reserved. There is no
warranty. You are allowed to redistribute this software / documentation
under certain conditions. For details, see the file COPYING in the PDL
distribution. If this file is separated from the PDL distribution, the
copyright notice should be included in the file.

PDL Module for reading and writing Starlink N-dimensional data structures as PDLs.
**********************************************************************************

NAME
====

   PDL::IO::NDF - PDL Module for reading and writing Starlink
N-dimensional data structures as PDLs.

SYNOPSIS
========

     use PDL::IO::NDF;

     $a = PDL->rndf($file);

     $a = rndf('test_image');
     $a = rndf('test_image', 1);

     $a->wndf($file);
     wndf($a, 'out_image');

     propndfx($a, 'template', 'out_image');

DESCRIPTION
===========

   This module adds the ability to read and write Starlink N-dimensional
data files as N-dimensional PDLs.

FUNCTIONS
=========

rndf()
------

   The '.sdf' suffix is optional. The optional second argument turns off
automatic quality masking and returns a quality array as well.

   BUG? `rndf('bob.sdf',1)' calls ndf_sqmf(1,...), which means that the
quality array is turned into bad pixels - ie the *opposite* of above. Or
am I confused?

   Header information and NDF Extensions are stored in the piddle as a hash
which can be retreived with the `$pdl->gethdr' command.  Array extensions
are stored in the header as follows:

     $a - the base DATA_ARRAY

   If `$hdr = $a->gethdr';

   then:

     %{$hdr}        contains all the FITS headers plus:
     $$hdr{Error}   contains the Error/Variance PDL
     $$hdr{Quality} The quality byte array (if reqeusted)
     @{$$hdr{Axis}} Is an array of piddles containing the information
                    for axis 0, 1, etc.
     $$hdr{NDF_EXT} Contains all the NDF extensions
     $$hdr{Hist}    Contains the history information
     $$hdr{NDF_EXT}{_TYPES}
                    Data types for non-PDL NDF extensions so that
                    wndf can reconstruct a NDF.

   All extension information is stored in the header hash array.
Extension structures are preserved in hashes, so that the PROJ_PARS
component of the IRAS.ASTROMETRY extension is stored in
`$$hdr{NDF_EXT}{IRAS}{ASTROMETRY}{'PROJ_PARS'}'. All array structures are
stored as arrays in the Hdr: numeric arrays are stored as PDLs, logical
and character arrays are stored as plain Perl arrays. FITS arrays are a
special case and are expanded as scalars into the header.

   PDL does not have a signed byte datatype, so any '_BYTE' data is read
into a byte (unsigned) piddle and a warning is printed to STDOUT.

wndf()
------

   wndf can be used for writing PDLs to NDF files.  The '.sdf' suffix is
optional. All the extensions created by rndf are supported by wndf.  This
means that error, axis and quality arrays will be written if they exist.
Extensions are also reconstructed by using their name (ie FIGARO.TEST
would be expanded as a FIGARO extension and a TEST component). Hdr
keywords Label, Title and Units are treated as special cases and are
written to the label, title and units fields of the NDF.

   Header information is written to corresponding NDF extensions.  NDF
extensions can also be created in the {NDF} hash by using a key containing
'.', ie {NDF}{'IRAS.DATA'} would write the information to an IRAS.DATA
extension in the NDF. rndf stores this as `$$hdr{NDF}{IRAS}{DATA}' and the
two systems are interchangeable.

   rndf stores type information in {NDF}{'_TYPES'} and below so that wndf
can reconstruct the data type of non-PDL extensions. If no entry exists in
_TYPES, wndf chooses between characters, integer and double on a best
guess basis.  Any perl arrays are written as CHAR array extensions (on the
assumption that numeric arrays will exist as PDLs).

propndfx()
----------

   Routine to write a PDL to an NDF by copying the extension information
from an existing NDF and writing DATA,VARIANCE, QUALITY and AXIS info from
a PDL (if they exist).

   Extensions, labels and history are propogated from the old NDF.  No new
extension information is written.

   This command has been superseded by `wndf()|' in this node.

NOTES
=====

   The perl NDF module must be available. This is available from the
author or from Starlink (http://www.starlink.rl.ac.uk).

   If an NDF is read which contains AST World Coordinate information (a
.WCS component) this information is currently ignored. Currently WCS
information can only be written and stored using standard FITS headers.
See http://rlspc5.bnsc.rl.ac.uk/star/docs/sun211.htx/sun211.html#xref_ for
more information on AST.

AUTHOR
======

   This module was written by Tim Jenness <t.jenness@jach.hawaii.edu>.
Copyright (C) Tim Jenness 1997-2000. All Rights Reserved.

SEE ALSO
========

   See PDL/FAQ, for general information on the Perl Data
language, `NDF' in this node for information on the NDF module.

image I/O for PDL
*****************

NAME
====

   PDL::IO::Pic - image I/O for PDL

DESCRIPTION
===========

Image I/O for PDL based on the netpbm package.
----------------------------------------------

   This package implements I/O for a number of popular image formats by
exploiting the xxxtopnm and pnmtoxxx converters from the netpbm package
(which is based on the original pbmplus by Jef Poskanzer).

   Netpbm is available at
ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/ Pbmplus (on
which netpbm is based) might work as well, I haven't tried it.  If you
want to read/write JPEG images you additionally need the two converters
cjpeg/djpeg which come with the libjpeg distribution (the "official"
archive site for this software is ftp://ftp.uu.net/graphics/jpeg).

   Image I/O for all formats is established by reading and writing only
the PNM format directly while the netpbm standalone apps take care of the
necessary conversions. In accordance with netpbm parlance PNM stands here
for 'portable any map' meaning any of the PBM/PGM/PPM formats.

   As it appeared to be a reasonable place this package also contains the
routine wmpeg to write mpeg movies from PDLs representing image stacks
(the image stack is first written as a sequence of PPM images into some
temporary directory). For this to work you additionally need the program
mpeg_encode from the Berkeley multimedia package.

   You find mpeg_encode at
ftp://mm-ftp.cs.berkeley.edu/pub/multimedia/mpeg/encode (they even have
binaries for a number of platforms).

Configuration
-------------

   The executables from the netpbm package are assumed to be in your path.
Problems in finding the executables may show up as PNM format errors when
calling wpic/rpic. If you run into this kind of problem run your program
with perl -w so that perl prints a message if it can't find the filter
when trying to open the pipe.

FUNCTIONS
=========

rpiccan, wpiccan
----------------

   finds out if PDL::IO::Pic can read/write certain image formats.  When
called without arguments returns a list of supported formats. When called
with an argument returns true if format is supported on your computer
(requires appropriate filters in your path), false otherwise.

rpic
----

   Options

   Reads image files in most of the formats supported by netpbm. You can
explicitly specify a supported format by additionally passing a hash
containing the FORMAT key as in

     $im = rpic ($file, {FORMAT => 'GIF'});

   This is especially useful if the particular format isn't identified by
a magic number and doesn't have the 'typical' extension or you want to
avoid the check of the magic number if your data comes in from a pipe.
The function returns a pdl of the appropriate type upon completion.
Option parsing uses the PDL/Options, module and
therefore supports minimal options matching.

   You can also read directly into an existing pdl that has to have the
right size(!). This can come in handy when you want to read a sequence of
images into a datacube, e.g.

     $stack = zeroes(byte,3,500,300,4);
     rpic $stack->slice(':,:,:,(0)'),"PDL.jpg";

   reads an rgb image (that had better be of size (500,300)) into the
first plane of a 3D RGB datacube (=4D pdl datacube). You can also do
transpose/inversion upon read that way.

wpic
----

   Write out an image file. Function will try to guess correct image
format from the filename extension, e.g.

     $pdl->wpic("image.gif")

   will write a gif file. The data written out will be scaled to byte if
input is of type float/double. Input data that is of a signed integer type
and contains negative numbers will be rejected (assuming the user should
have the desired conversion to an unsigned type already). A number of
options can be specified (as a hash reference) to get more direct control
of the image format that is being written. Valid options are (key =>
example_value):

   Option parsing uses the PDL/Options, module and
therefore supports minimal options matching. A detailed explanation of
supported options follows.

CONVERTER
     directly specify the converter, you had better know what you are
     doing, e.g.

          CONVERTER  => 'ppmtogif',

FLAGS
     flags to use with the converter; ignored if
     !defined($$hints{CONVERTER}), e.g. with the gif format

          FLAGS      => '-interlaced -transparent 0',

IFORM
     intermediate PNM/PPM/PGM/PBM format to use; you can append the
     strings 'RAW' or 'ASCII' to enforce those modes, eg IFORMAT=>'PGMRAW'
     or

          IFORM    => 'PGM',

XTRAFLAGS
     additional flags to use with an automatically chosen converter, this
     example works when you write SGI files (but will give an error
     otherwise)

          XTRAFLAGS => '-imagename iris',

FORMAT
     explicitly select the format you want to use. Required if wpic cannot
     figure out the desired format from the file name extension. Supported
     types are currently TIFF,GIF,SGI,PNM,JPEG,PS,RAST(Sun Raster),IFF,PCX,
     e.g.

          FORMAT     => 'PCX',

COLOR
     you want black and white (value *bw*), other possible value is
     *bwdither* which will write a dithered black&white image from the
     input data, data conversion will be done appropriately, e.g.

          COLOR      => 'bw',

LUT
     This is a palette image and the value of this key should be a pdl
     containg an RGB lookup table (3,x), e.g.

          LUT        => $lut,

   Using the CONVERTER hint you can also build a pipe and perform several
netpbm operations to get the special result you like. Using it this way
the first converter/filecommand in the pipe should be specified with the
CONVERTER hint and subsequent converters + flags in the FLAGS hint. This
is because wpic tries to figure out the required format to be written by
wpnm based on the first converter. Be careful when using the PBMBIN var as
it will only be prepended to the converter. If more converters are in the
FLAGS part specify the full path unless they are in your PATH anyway.

   Example:

     $im->wpic('test.ps',{CONVERTER  => 'pgmtopbm',
     		    FLAGS => "-dither8 | pnmtops" })

   Some of the options may appear silly at the moment and probably are.
The situation will hopefully improve as people use the code and the need
for different/modified options becomes clear. The general idea is to make
the function perl compliant: easy things should be easy, complicated tasks
possible.

wmpeg
-----

   Writes a stack of rgb images as an mpeg movie. Expects a 4-D pdl of
type byte as input. First dim has to be 3 since it is interpreted as
interlaced RGB.  Some of the input data restrictions will have to be
relaxed in the future but routine serves as a proof of principle at the
moment. It uses the program mpeg_encode from the Berkeley multimedia
package (see also text at the top of this package). Mpeg parameters
written by this routines haven't been tweaked in any way yet (in other
words, lots of room for improvement). For an example how to use the
routine see appropriate test that comes with this package.  Currently,
wmpeg doesn't allow modification of the parameters written through its
calling interface. This will change in the future as needed.

   In the future it might be much nicer to implement a movie perl object
that supplies methods for manipulating the image stack (insert, cut,
append commands) and a final movie->make() call would invoke mpeg_encode
on the picture stack (which will only be held on disk). This should get
around the problem of having to hold a huge amount of data in memory to be
passed into wmpeg (when you are, e.g. writing a large animation from PDL3D
rendered fly-throughs). Having said that, the actual storage requirements
might not be so big in the future any more if you could pass 'virtual'
transform pdls into wmpeg  that will only be actually calculated when
accessed by the wpic routines, you know what I mean...

BUGS
====

   Currently only a random selection of converters/formats provided by
pbmplus/netpbm is supported. It is hoped that the more important formats
are covered. Other formats can be added as needed. Please send patches to
the author.

AUTHOR
======

   Copyright (C) 1996,1997 Christian Soeller <c.soeller@auckland.ac.nz>
All rights reserved. There is no warranty. You are allowed to redistribute
this software / documentation under certain conditions. For details, see
the file COPYING in the PDL distribution. If this file is separated from
the PDL distribution, the copyright notice should be included in the file.

pnm format I/O for PDL
**********************

NAME
====

   PDL::IO::Pnm - pnm format I/O for PDL

SYNOPSIS
========

     use PDL::IO::Pnm;
     $im = wpnm $pdl, $file, $format[, $raw];
     rpnm $stack->slice(':,:,:,(0)'),"PDL.ppm";

DESCRIPTION
===========

pnm I/O for PDL.
----------------

FUNCTIONS
=========

rpnm
----

   Reads a file in pnm format (ascii or raw) into a pdl (magic numbers
P1-P6).  Based on the input format it returns pdls with arrays of size
(width,height) if binary or grey value data (pbm and pgm) or
(3,width,height) if rgb data (ppm). This also means for a palette image
that the distinction between an image and its lookup table is lost which
can be a problem in cases (but can hardly be avoided when using
netpbm/pbmplus).  Datatype is dependent on the maximum
grey/color-component value (for raw and binary formats always PDL_B). rpnm
tries to read chopped files by zero padding the missing data (well it
currently doesn't, it barfs; I'll probably fix it when it becomes a
problem for me ;). You can also read directly into an existing pdl that
has to have the right size(!). This can come in handy when you want to
read a sequence of images into a datacube.

   For details about the formats see appropriate manpages that come with
the netpbm/pbmplus packages.

   reads an rgb image (that had better be of size (500,300)) into the
first plane of a 3D RGB datacube (=4D pdl datacube). You can also do
inplace transpose/inversion that way.

wpnm
----

   Writes data in a pdl into pnm format (ascii or raw) (magic numbers
P1-P6).  The $format is required (normally produced by wpic) and routine
just checks if data is compatible with that format. All conversions should
already have been done. If possible, usage of wpic is preferred. Currently
RAW format is chosen if compliant with range of input data. Explicit
control of ASCII/RAW is possible through the optional $raw argument. If
RAW is set to zero it will enforce ASCII mode. Enforcing RAW is somewhat
meaningless as the routine will always try to write RAW format if the data
range allows (but maybe it should reduce to a RAW supported type when RAW
== 'RAW'?). For details about the formats consult appropriate manpages
that come with the netpbm/pbmplus packages.

BUGS
====

   The stderr of the converters is redirected to a file. The filename is
currently generated in a probably non-portable way. A method that avoids a
file (and is portable) would be prefered.

   rpnm currently relies on the fact that the header is separated from the
image data by a newline. This is not required by the p[bgp]m formats (in
fact any whitespace is allowed) but most of the pnm writers seem to comply
with that. Truncated files are currently treated ungracefully (rpnm just
barfs).

AUTHOR
======

   Copyright (C) 1996,1997 Christian Soeller <c.soeller@auckland.ac.nz>
All rights reserved. There is no warranty. You are allowed to redistribute
this software / documentation under certain conditions. For details, see
the file COPYING in the PDL distribution. If this file is separated from
the PDL distribution, the copyright notice should be included in the file.

FUNCTIONS
=========

pnminraw
--------

   read a raw pnm file. The type argument is only there to determine the
type of the operation when creating `im' or trigger the appropriate type
conversion (maybe we want a byte+ here so that `im' follows *strictly* the
type of type).

pnminascii
----------

pnmout
------

   This function is implemented this way so that threading works naturally.

Miscellaneous 2D image processing functions
*******************************************

NAME
====

   PDL::Image2D - Miscellaneous 2D image processing functions

DESCRIPTION
===========

   Miscellaneous 2D image processing functions - for want of anywhere else
to put them

SYNOPSIS
========

     use PDL::Image2D;

FUNCTIONS
=========

conv2d
------

   For large kernels, using a FFT routine, such as
`fftconvolve()|PDL::FFT' in this node in `PDL::FFT', will be quicker.

med2d
-----

   Note: only points in the kernel >0 are included in the median, other
points are weighted by the kernel value (medianing lots of zeroes is
rather pointless)

patch2d
-------

   `$bad' is a 2D mask array where 1=bad pixel 0=good pixel.  Pixels are
replaced by the average of their non-bad neighbours; if all neighbours are
bad, the original data value is copied across.

patchbad2d
----------

   Pixels are replaced by the average of their non-bad neighbours; if all
neighbours are bad, the output is set bad.  If the input piddle contains
no bad values, then a straight copy is performed (see `patch2d|' in this
node).

max2d_ind
---------

   Contributed by Tim Jeness

centroid2d
----------

   `$box' is the full-width of the box, i.e. the window is `+/- $box/2'.

cc8compt
--------

   Connected 8-component labeling of 0,1 image - i.e. find seperate
segmented objects and fill object pixels with object number

polyfill
--------

   This function works inplace, i.e. modifies `im'.

polyfillv
---------

rot2d
-----

   This function rotates an image through an `angle' between -90 and + 90
degrees. Uses/doesn't use antialiasing depending on the aa flag.  Pixels
outside the rotated image are set to `bg'.

   Code modified from pnmrotate (Copyright Jef Poskanzer) with an
algorithm based on "A Fast Algorithm for General  Raster  Rotation"  by
Alan Paeth, Graphics Interface '86, pp. 77-81.

   Use the `rotnewsz' function to find out about the dimension of the
newly created image

     ($newcols,$newrows) = rotnewsz $oldn, $oldm, $angle;

bilin2d
-------

rescale2d
---------

fitwarp2d
---------

   Given a set of points in the output plane (`$u,$v'), find the best-fit
(using singular-value decomposition) 2D polynomial to describe the mapping
back to the image plane (`$x,$y').  The order of the fit is controlled by
the `$nf' parameter (the maximum power of the polynomial is `$nf - 1'),
and you can restrict the terms to fit using the FIT option.

   `$px' and `$py' are np by np element piddles which describe a
polynomial mapping (of order `np-1') from the output `(u,v)' image to the
input `(x,y)' image:

     x = sum(j=0,np-1) sum(i=0,np-1) px(i,j) * u^i * v^j
     y = sum(j=0,np-1) sum(i=0,np-1) py(i,j) * u^i * v^j

   Please note that this storage is the transpose of that used by the
`polywarp' routine in IDL.

   The transformation is returned for the reverse direction (ie output to
input image) since that is what is required by the `warp2d()|' in this
node routine.  The `applywarp2d()|' in this node routine can be used to
convert a set of `$u,$v' points given `$px' and `$py'.

   Options:

FIT
     FIT allows you to restrict which terms of the polynomial to fit: only
     those terms for which the FIT piddle evaluates to true will be
     evaluated.  If a 2D piddle is sent in, then it is used for the x and
     y polynomials; otherwise `$fit->slice(":,:,(0)")' will be used for
     `$px' and `$fit->slice(":,:,(1)")' will be used for `$py'.

THRESH
     Remove all singular values whose valus is less than THRESH times the
     largest singular value.

   The number of points must be at least equal to the number of terms to
fit (`$nf*$nf' points for the default value of FIT).

applywarp2d
-----------

   Convert a set of points (stored in 1D piddles `$u,$v') to `$x,$y' using
the 2-D polynomial with coefficients stored in `$px' and `$py'.  See
`fitwarp2d()|' in this node for more information on the format of `$px'
and `$py'.

warp2d
------

   Apply the polynomial transformation encoded in the `$px' and `$py'
piddles to warp the input image `$img' into the output image `$out'.  It
is similar to the `poly_2d' routine in IDL.

   The format for the polynomial transformation is described in the
documentation for the `fitwarp2d()|' in this node routine.

   At each point `x,y', the closest 16 pixel values are combined with an
interpolation kernel to calculate the value at `u,v'.  The interpolation
is therefore done in the image, rather than Fourier, domain.  By default,
a tanh kernel is used, but this can be changed using the KERNEL option
discussed below (the choice of kernel depends on the frequency content of
the input image).

   The routine is based on the `warping' command from the Eclipse
data-reduction package - see http://www.eso.org/eclipse/ - and for further
details on image resampling see Wolberg, G., "Digital Image Warping",
1990, IEEE Computer Society Press (ISBN 0-8186-8944-7).

   Currently the output image is the same size as the input one, which
means data will be lost if the transformation reduces the pixel scale.
This will (hopefully) be changed soon.

   The options are:

   KERNEL is used to specify which interpolation kernel to use (to see
what these kernels look like, use the `warp2d_kernel()|' in this node
routine).  The options are:

tanh
     Hyperbolic tangent: the approximation of an ideal box filter by the
     product of symmetric tanh functions.

sinc
     For a correctly sampled signal, the ideal filter in the fourier
     domain is a rectangle, which produces a sinc interpolation kernel in
     the spatial domain:

          sinc(x) = sin(pi * x) / (pi * x)

     However, it is not ideal for the `4x4' pixel region used here.

sinc2
     This is the square of the sinc function.

lanczos
     Although defined differently to the tanh kernel, the result is very
     similar in the spatial domain.  The Lanczos function is defined as

          L(x) = sinc(x) * sinc(x/2)  if abs(x) < 2
               = 0                       otherwise

hann
     This kernel is derived from the following function:

          H(x) = a + (1-a) * cos(2*pi*x/(N-1))  if abs(x) < 0.5*(N-1)
               = 0                                 otherwise

     with `a = 0.5' and N currently equal to 2001.

hamming
     This kernel uses the same `H(x)' as the Hann filter, but with `a =
     0.54'.

   `NOVAL' gives the value used to indicate that a pixel in the output
image does not map onto one in the input image.

warp2d_kernel
-------------

   The valid values for $name are the same as the KERNEL option of
`warp2d()|' in this node.

AUTHORS
=======

   Copyright (C) Karl Glazebrook 1997 with additions by Robin Williams
(rjrw@ast.leeds.ac.uk), Tim Jeness (timj@jach.hawaii.edu), and Doug Burke
(burke@ifa.hawaii.edu).

   All rights reserved. There is no warranty. You are allowed to
redistribute this software / documentation under certain conditions. For
details, see the file COPYING in the PDL distribution. If this file is
separated from the PDL distribution, the copyright notice should be
included in the file.

useful image processing routines which work in N-dimensions
***********************************************************

NAME
====

   PDL::ImageND - useful image processing routines which work in
N-dimensions

DESCRIPTION
===========

   In some cases (though not as many as one would like) it is possible to
write general routines that operate on N-dimensional objects.

   An example in this module is a N-Dim convolution algorithm I made up
one day - it works but the boundary condtions are a bit funny.

SYNOPSIS
========

     use PDL::ImageND;

FUNCTIONS
=========

convolve
--------

   Convolve an array with a kernel, both of which are N-dimensional.

   Note because of the algorithm used (writing N-dim routines is not easy
on the brain!) the boundary conditions are a bit strange. They wrap, but
up to the NEXT row/column/cube-slice/etc. If this is a problem consider
using zero-padding or something.

ninterpol()
-----------

   `ninterpol' uses interpol to find a linearly interpolated value in N
dimensions, assuming the data is spread on a uniform grid.  To use an
arbitrary grid distribution, need to find the grid-space point from the
indexing scheme, then call `ninterpol' - this is far from trivial (and
ill-defined in general).

rebin
-----

   Rebin an N-dimensional array to newly specified dimensions.  Specifying
`Norm' keeps the sum constant, otherwise the intensities are kept
constant.  If more template dimensions are given than for the input pdl,
these dimensions are created; if less, the final dimensions are maintained
as they were.

   So if `$a' is a 10 x 10 pdl, then `rebin($a,15)' is a 15 x 10 pdl,
while `rebin($a,15,16,17)' is a 15 x 16 x 17 pdl (where the values along
the final dimension are all identical).

circ_mean_p
-----------

circ_mean
---------

AUTHORS
=======

   Copyright (C) Karl Glazebrook 1997.  All rights reserved. There is no
warranty. You are allowed to redistribute this software / documentation
under certain conditions. For details, see the file COPYING in the PDL
distribution. If this file is separated from the PDL distribution, the
copyright notice should be included in the file.

some utility functions for RGB image data handling
**************************************************

NAME
====

   PDL::ImageRGB - some utility functions for RGB image data handling

DESCRIPTION
===========

   Collection of a few commonly used routines involved in handling of RGB,
palette and grayscale images. Not much more than a start. Should be a good
place to exercise some of the thread/map/clump PP stuff.

   Other stuff that should/could go here:

   * color space conversion

   * common image filters

   * image rebinning

SYNOPSIS
========

     use PDL::ImageRGB;

FUNCTIONS
=========

cquant
------

   This function does color reduction for <=8bit displays and accepts 8bit
RGB and 8bit palette images. It does this through an interface to the
ppm_quant routine from the pbmplus package that implements the median cut
routine which intellegently selects the 'best' colors to represent your
image on a <= 8bit display (based on the median cut algorithm). Optional
args: $ncols sets the maximum nunmber of colours used for the output image
(defaults to 256).  There are images where a different color reduction
scheme gives better results (it seems this is true for images containing
large areas with very smoothly changing colours).

   Returns a list containing the new palette image (type PDL_Byte) and the
RGB colormap.

interlrgb
---------

   Input should be of an integer type and the lookup table (3,x,...). Will
perform the lookup for any N-dimensional input pdl (i.e. 0D, 1D, 2D, ...).
Uses the index command but will not dataflow by default. If you want it to
dataflow the dataflow_forward flag must be set in the $lut piddle (you can
do that by saying $lut->set_dataflow_f(1)).

rgbtogr
-------

   Performs a conversion of an RGB input image (3,x,....) to a greyscale
image (x,.....) using standard formula:

     Grey = 0.301 R + 0.586 G + 0.113 B

bytescl
-------

   By default $top=255, otherwise you have to give the desired top value
as an argument to bytescl. Normally bytescl doesn't rescale data that fits
already in the bounds 0..$top (it only does the type conversion if
required).  If you want to force it to rescale so that the max of the
output is at $top and the min at 0 you give a negative $top value to
indicate this.

BUGS
====

   This package doesn't yet contain enough useful functions!

AUTHOR
======

   Copyright 1997 Christian Soeller <c.soeller@auckland.ac.nz> All rights
reserved. There is no warranty. You are allowed to redistribute this
software / documentation under certain conditions. For details, see the
file COPYING in the PDL distribution. If this file is separated from the
PDL distribution, the copyright notice should be included in the file.

PDL for the impatient (quick overview)
**************************************

NAME
====

   PDL::Impatient - PDL for the impatient (quick overview)

SYNOPSIS
========

   Executive summary of what PDL is about.

DESCRIPTION
===========

Introduction
------------

   Perl is an extremely good and versatile scripting language, well suited
to beginners and allows rapid prototyping. However until recently it did
not support data structures which allowed it to do fast number crunching.

   However with the development of Perl v5, Perl acquired 'Objects'. To put
it simply users can define their own special data types, and write custom
routines to manipulate them either in low level languages (C and Fortran)
or in Perl itself.

   This has been fully exploited by the PerlDL developers. The 'PDL'
module is a complete Object-Oriented extension to Perl (although you don't
have to know what an object is to use it) which allows large N-dimensional
data sets, such as large images, spectra, time series, etc to be stored
*efficiently* and manipulated *en masse*.  For example  with the PDL
module we can write the perl code `$a=$b+$c', where $b and $c are large
datasets (e.g. 2048x2048 images), and get the result in only a fraction of
a second.

   PDL variables (or 'piddles' as they have come to be known) support a
wide range of fundamental data types - arrays can be bytes, short integers
(signed or unsigned), long integers, floats or double precision floats.
And because of the Object-Oriented nature of PDL new customised datatypes
can be derived from them.

   As well as the PDL modules, that can be used by normal perl programs,
PerlDL comes with a command line perl shell, called 'perldl', which
supports command line editing. In combination with the various PDL
graphics modules this allows data to be easily played with and visualised.

Help
----

   PDL contains extensive documentation, available both within the
*perldl* shell and from the command line, using the `pdldoc' program.  For
further information try either of:

     perldl> help help
     $ pdldoc

   HTML copies of the documentation should also be available.  To find
their location, try the following:

     perldl> foreach ( map{"$_/PDL/HtmlDocs"}@INC ) { p "$_\n" if -d $_ }

Perl Datatypes and how PDL extends them
---------------------------------------

   The fundamental perl data structures are scalar variables, e.g. $x,
which can hold numbers or strings, lists or arrays of scalars, e.g. `@x',
and associative arrays/hashes of scalars, e.g. `%x'.

   perl v5 introduces to perl data structures and objects. A simple scalar
variable $x now be a user-defined data type or full blown object (it
actually holds a reference (a smart "pointer") to this but that is not
relevant for ordinary use of perlDL)

   The fundamental idea behind perlDL is to allow $x to hold a whole 1D
spectrum, or a 2D image, a 3D data cube, and so on up to large
N-dimensional data sets. These can be manipulated all at once, e.g.  `$a =
$b + 2' does a vector operation on each value in the spectrum/image/etc.

   You may well ask: "Why not just store a spectrum as a simple perl `@x'
style list with each pixel being a list item?"  The two key answers to
this are memory and *speed*.  Because we know our spectrum consists of
pure numbers we can compactly store them in a single block of memory
corresponding to a C style numeric array. This takes up a LOT less memory
than the equivalent perl list. It is then easy to pass this block of
memory to a fast addition routine, or to any other C function which deals
with arrays.  As a result perlDL is very fast -- for example one can
mulitiply a 2048*2048 image in exactly the same time as it would take in C
or FORTRAN (0.1 sec on my SPARC). A further advantage of this is that for
simple operations (e.g. `$x += 2') one can manipulate the whole array
without caring about its dimensionality.

   I find when using perlDL it is most useful to think of standard perl
`@x' variables as "lists" of generic "things" and PDL variables like $x as
"arrays" which can be contained in lists or hashes. Quite often in my
perlDL scripts I have `@x' contain a list of spectra, or a list of images
(or even a mix!). Or perhaps one could have a hash (e.g.  `%x') of
images... the only limit is memory!

   perlDL variables support a range of data types - arrays can be bytes,
short integers (signed or unsigned), long integers, floats or double
precision floats.

Usage
-----

   PerlDL is loaded into your perl script using this command:

     use PDL;  # in perl scripts: use the standard perlDL modules

   There are also a lot of extension modules, e.g.
`PDL::Graphics::TriD|PDL::Graphics::TriD' in this node.  Most of these
(but not all as sometimes it is not appropriate) follow a standard
convention. If you say:

     use PDL::Graphics::TriD;

   You import everything in a standard list from the module. Sometimes you
might want to import nothing (e.g. if you want to use OO syntax all the
time and save the import tax). For these you say:

     use PDL::Graphics::TriD '';

   And the blank quotes " are regonised as meaning 'nothing'. You can also
specify a list of functions to import in the normal Perl way.

   There is also an interactive shell, `perldl', see *perldl*.

To create a new PDL variable
----------------------------

   Here are some ways of creating a PDL variable:

     $a = pdl [1..10];             # 1D array
     $a = pdl (1,2,3,4);           # Ditto
     $b = pdl [[1,2,3],[4,5,6]];   # 2D 3x2 array
     $b = pdl 42                   # 0-dimensional scalar
     $c = pdl $a;                  # Make a new copy

     $d = byte [1..10];            # See "Type conversion"
     $e = zeroes(3,2,4);           # 3x2x4 zero-filled array

     $c = rfits $file;             # Read FITS file

     @x = ( pdl(42), zeroes(3,2,4), rfits($file) ); # Is a LIST of PDL variables!

   The `pdl()|PDL::Core' in this node function is used to initialise a PDL
variable from a scalar, list, list reference or another PDL variable.

   In addition all PDL functions automatically convert normal perl scalars
to PDL variables on-the-fly.

   (also see "Type Conversion" and "Input/Output" sections below)

Arithmetic (and boolean expressions)
------------------------------------

     $a = $b + 2; $a++; $a = $b / $c; # Etc.

     $c=sqrt($a); $d = log10($b+100); # Etc

     $e = $a>42; # Vector conditional

     $e = 42*($a>42) + $a*($a<=42); # Cap top

     $b = $a->log10 unless any ($a <= 0); # avoid floating point error

     $a = $a / ( max($a) - min($a) );

     $f = where($a, $a > 10); # where returns a piddle of elements for
                              # which the condition is true

     print $a; # $a in string context prints it in a N-dimensional format

   (and other perl operators/functions)

   When using piddles in conditional expressions (i.e. if, `unless' and
while constructs) only piddles with exactly one element are allowed, e.g.

     $a = pdl (1,0,0,1);
     print "is set" if $a->index(2);

   Note that the boolean operators return in general multielement piddles.
Therefore, the following will raise an error

     print "is ok" if $a > 3;

   since `$a > 3' is a piddle with 4 elements. Rather use
`all|PDL::Primitive' in this node or `any|PDL::Primitive' in this node to
test if all or any of the elements fulfill the condition:

     print "some are > 3" if any $a>3;
     print "can't take logarithm" unless all $a>0;

   There are also many predefined functions, which are described on other
manpages. Check PDL/Index.

Matrix functions
----------------

   'x' is hijacked as the matrix multiplication operator. e.g.  `$c = $a x
$b';

   perlDL is row-major not column major so this is actually `c(i,j) =
sum_k a(k,j) b(i,k)' - but when matrices are printed the results will look
right. Just remember the indices are reversed.  e.g.:

     $a = [                   $b = [
           [ 1  2  3  0]            [1 1]
           [ 1 -1  2  7]            [0 2]
           [ 1  0  0  1]            [0 2]
          ]                         [1 1]
                                   ]

     gives $c = [
                 [ 1 11]
                 [ 8 10]
                 [ 2  2]
                ]

   Note: `transpose()|PDL::Basic::transpose' in this node does what it
says and is a convenient way to turn row vectors into column vectors. It
is bound to the unary operator '~' for convenience.

How to write a simple function
------------------------------

     sub dotproduct {
         my ($a,$b) = @_;
         return sum($a*$b) ;
     }
     1;

   If put in file dotproduct.pdl would be autoloaded if you are using
`PDL::AutoLoader|PDL::AutoLoader' in this node (see below).

   Of course, this function is already available as the
`inner|PDL::Primitive' in this node function, see PDL/Primitive.

Type Conversion
---------------

   Default for pdl() is double. Conversions are:

     $a = float($b);
     $c = long($d);   # "long" is generally a 4 byte int
     $d = byte($a);

   Also double(), short(), ushort().

   These routines also automatically convert perl lists to allow the
convenient shorthand:

     $a = byte [[1..10],[1..10]];  # Create 2D byte array
     $a = float [1..1000];         # Create 1D float array

   etc.

Piddles and boolean expressions
-------------------------------

Printing
--------

   Automatically expands array in N-dimensional format:

     print $a;

     $b = "Answer is = $a ";

Sections
--------

   perlDL betrays its perl/C heritage in that arrays are zero-offset.
Thus a 100x100 image has indices `0..99,0..99'.

   Furthermore [Which modules!?!],  the convention is that the center of
the pixel (0,0) IS at coordinate (0.0,0.0). Thus the above image ranges
from `-0.5..99.5, -0.5..99.5' in real space. All perlDL graphics functions
conform to this defintion and hide away the unit-offsetness of, for
example, the PGPLOT FORTRAN library.

   Again following the usual convention coordinate (0,0) is displayed at
the bottom left when displaying an image. It appears at the top left when
using "`print $a'" etc.

     $b = $a->slice("$x1:$x2,$y1:$y1,$z1:$z2"); # Take subsection

     # Set part of $bigimage to values from $smallimage
     ($tmp = $bigimage->slice("$xa:$xb,$ya:$yb")) .= $smallimage;

     $newimage = ins($bigimage,$smallimage,$x,$y,$z...) # Insert at x,y,z

     $c  = nelem ($a); # Number of pixels

     $val = at($object, $x,$y,$z...)    # Pixel value at position
     $val = $object->at($x,$y,$z...)    # equivalent
     set($myimage, $x, $y, ... $value)  # Set value in image

     $b = xvals($a); # Fill array with X-coord values (also yvals(), zvals(),
                     # axisvals($x,$axis) and rvals() for radial distance
                     # from centre).

Input/Output
------------

   The `PDL::IO' modules implement several useful IO format functions.  It
would be too much to give examples of each so you are referred to the
individual manpages for details.

PDL::IO::Misc
     Ascii, FITS and FIGARO/NDF IO routines.

PDL::IO::FastRaw
     Using the raw data types of your machine, an unportable but blindingly
     fast IO format. Also supports memory mapping to conserve memory as
     well as get more speed.

PDL::IO::FlexRaw
     General raw data formats.

PDL::IO::Browser
     A Curses browser for arrays.

PDL::IO::Pnm
     Portaple bitmap and pixmap support.

PDL::IO::Pic
     Using the previous module and netpbm, makes it possible to easily
     write GIF, jpeg and whatever with simple commands.

Graphics
--------

   The philosophy behind perlDL is to make it work with a variety of
existing graphics libraries since no single package will satisfy all needs
and all people and this allows one to work with packages one already knows
and likes.  Obviously there will be some overlaps in functionality and
some lack of consistency and uniformity. However this allows PDL to keep
up with a rapidly developing field - the latest PDL modules provide
interfaces to OpenGL and VRML graphics!

PDL::Graphics::PGPLOT
     PGPLOT provdes a simple library for line graphics and image display.

     There is an easy interface to this in the internal module
     `PDL::Graphics::PGPLOT|PDL::Graphics::PGPLOT' in this node, which
     calls routines in the separately available PGPLOT top-level module.

PDL::Graphics::IIS
     Many astronomers like to use SAOimage and Ximtool (or there
     derivations/clones). These are useful free widgets for inspection and
     visualisation of images. (They are not provided with perlDL but can
     easily be obtained from their official sites off the Net.)

     The `PDL::Graphics::IIS|PDL::Graphics::IIS' in this node package
     provides allows one to display images in these ("IIS" is the name of
     an ancient item of image display hardware whose protocols these tools
     conform to.)

Karma
     The `PDL::Graphics::Karma|PDL::Graphics::Karma' in this node module
     provides an interface to the Karma visualisation suite. This is a set
     of GUI applications which are specially designed for visualising
     noisy 2D and 3D data sets.

PDL::Graphics::TriD
     See `PDL::Graphics::TriD|PDL::Graphics::TriD' in this node (the name
     sucks...).  this is a collection of 3D routines for OpenGL and (soon)
     VRML and other 3D formats which allow 3D point, line, and surface
     plots from PDL.

Autoloading
-----------

   See PDL/AutoLoader. This allows one to autoload
functions on demand, in a way perhaps familiar to users of MatLab.

   One can also write PDL extensions as normal Perl modules.

perldl shell
------------

   The perl script `perldl' provides a simple command line - if the latest
Readlines/ReadKey modules have beeen installed `perldl' detects this and
enables command line recall and editing. See the manpage for details.

   e.g.:

     jhereg% perldl
     perlDL shell v1.30
      PDL comes with ABSOLUTELY NO WARRANTY. For details, see the file
      'COPYING' in the PDL distribution. This is free software and you
      are welcome to redistribute it under certain conditions, see
      the same file for details.
     ReadLines enabled
     Reading PDL/default.perldlrc...
     Found docs database /home/kgb/soft/dev/lib/perl5/site_perl/PDL/pdldoc.db
     Type 'help' for online help
     Type 'demo' for online demos
     Loaded PDL v2.005
     perldl> $x = rfits 'm51.fits'
     BITPIX =  16  size = 65536 pixels
     Reading  131072 bytes
     BSCALE = 1.0000000000E0 &&  BZERO = 0.0000000000E0

     perldl> imag $x
     Loaded PGPLOT
     Displaying 256 x 256 image from 24 to 500 ...

   You can also run it from the perl debugger (`perl -MPDL -d -e 1') if
you want.

   Miscellaneous shell features:

p
     The shell aliases p to be a convenient short form of print, e.g.

          perldl> p ones 5,3
          [
           [1 1 1 1 1]
           [1 1 1 1 1]
           [1 1 1 1 1]
          ]

Initialization
     The files `~/.perldlrc' and `local.perldlrc' (in the current
     directory) are sourced if found. This allows the user to have global
     and local PDL code for startup.

Help
     Type 'help'! One can search the PDL documentation, and look up
     documentation on any function.

Escape
     Any line starting with the `#' character is treated as a shell
     escape. This character is configurable by setting the perl variable
     `$PERLDL_ESCAPE'. This could, for example, be set in `~/.perldlrc'.

Overload operators
------------------

   The following builtin perl operators and functions have been overloaded
to work on PDL variables:

     + - * / > < >= <= << >> & | ^ == != <=> ** % ! ~
     sin log abs atan2 sqrt cos exp

   [All the unary functions (sin etc.) may be used with inplace() - see
"Memory" below.]

Object-Orientation and perlDL
-----------------------------

   PDL operations are available as functions and methods.  Thus one can
derive new types of object, to represent custom data classes.

   By using overloading one can make mathematical operators do whatever
you please, and PDL has some built-in tricks which allow existing PDL
functions to work unchanged, even if the underlying data representation is
vastly changed!  See PDL/Objects,

Memory usage and references
---------------------------

   Messing around with really huge data arrays may require some care.
perlDL provides many facilities to let you perform operations on big
arrays without generating extra copies though this does require a bit more
thought and care from the programmer.

   NOTE: On some most systems it is better to configure perl (during the
build options) to use the system `malloc()' function rather than perl's
built-in one. This is because perl's one is optimised for speed rather
than consumption of virtual memory - this can result in a factor of two
improvement in the amount of memory storage you can use.  The Perl malloc
in 5.004 and later does have a number of compile-time options you can use
to tune the behaviour.

Simple arithmetic
     If $a is a big image (e.g. occupying 10MB) then the command

          $a = $a + 1;

     eats up another 10MB of memory. This is because the expression `$a+1'
     creates a temporary copy of `$a' to hold the result, then `$a' is
     assigned a reference to that.  After this, the original `$a' is
     destroyed so there is no *permanent* memory waste. But on a small
     machine, the growth in the memory footprint can be considerable.  It
     is obviously done this way so `$c=$a+1' works as expected.

     Also if one says:

          $b = $a;     # $b and $a now point to same data
          $a = $a + 1;

     Then $b and `$a' end up being different, as one naively expects,
     because a new reference is created and `$a' is assigned to it.

     However if `$a' was a huge memory hog (e.g. a 3D volume) creating a
     copy of it may not be a good thing. One can avoid this memory
     overhead in the above example by saying:

          $a++;

     The operations `++,+=,--,-=', etc. all call a special "in-place"
     version of the arithmetic subroutine. This means no more memory is
     needed - the downside of this is that if `$b=$a' then $b is also
     incremented. To force a copy explicitly:

          $b = pdl $a; # Real copy

     or, alternatively, perhaps better style:

          $b = $a->copy;

Functions
     Most functions, e.g. `log()', return a result which is a
     transformation of their argument. This makes for good programming
     practice. However many operations can be done "in-place" and this may
     be required when large arrays are in use and memory is at a premium.
     For these circumstances the operator `inplace()|PDL::Core' in this
     node is provided which prevents the extra copy and allows the
     argument to be modified. e.g.:

          $x = log($array);          # $array unaffected
          log( inplace($bigarray) ); # $bigarray changed in situ

     WARNINGS:

       1. The usual caveats about duplicate references apply.

       2. Obviously when used with some functions which can not be applied
          in situ (e.g. `convolve()') unexpected effects may occur! We try
          to indicate inplace()-safe functions in the documentation.

       3. Type conversions, such as`float()', may cause hidden copying.

Ensuring piddleness
-------------------

   If you have written a simple function and you don't want it to blow up
in your face if you pass it a simple number rather than a PDL variable.
Simply call the function `topdl()|PDL::Core' in this node first to make it
safe. e.g.:

     sub myfiddle { my $pdl = topdl(shift); $pdl->fiddle_foo(...); ... }

   `topdl()' does NOT perform a copy if a pdl variable is passed - it just
falls through - which is obviously the desired behaviour. The routine is
not of course necessary in normal user defined functions which do not care
about internals.

AUTHOR
======

   Copyright (C) Karl Glazebrook (kgb@aaoepp.aao.gov.au), Tuomas J. Lukka,
(lukka@husc.harvard.edu) and Christian Soeller (c.soeller@auckland.ac.nz)
1997.  Commercial reproduction of this documentation in a different format
is forbidden.

an index of PDL documentation
*****************************

NAME
====

   PDL::Index - an index of PDL documentation

DESCRIPTION
===========

   A meta document listing the documented PDL modules and the PDL manual
dcouments

PDL manuals
===========

   * `PDL::BadValues|PDL::BadValues' in this node - Discussion of bad
     value support in PDL

   * `PDL::Dataflow|PDL::Dataflow' in this node - description of the
     dataflow philosophy

   * `PDL::Delta|PDL::Delta' in this node - PDL changes between V1.0 and
     V2.0

   * `PDL::FAQ|PDL::FAQ' in this node - Frequently asked questions about
     PDL

   * `PDL::Impatient|PDL::Impatient' in this node - PDL for the impatient
     (quick overview)

   * `PDL::Index|PDL::Index' in this node - an index of PDL documentation

   * `PDL::Indexing|PDL::Indexing' in this node - how to index piddles.

   * `PDL::Internals|PDL::Internals' in this node - description of the
     current internals

   * `PDL::Intro|PDL::Intro' in this node - Introduction to the Perl Data
     Language

   * `PDL::Objects|PDL::Objects' in this node - Object-Orientation, what
     is it and how to exploit it

   * `PDL::PP|PDL::PP' in this node - Generate PDL routines from concise
     descriptions

   * `PDL::Philosophy|PDL::Philosophy' in this node - what's behind PDL?

   * `PDL::Tips|PDL::Tips' in this node - Small tidbits of useful arcana.
     Programming tidbits and such.

PDL modules
===========

   * `PDL::PDL|PDL::PDL' in this node - Main loader of PDL default modules

   * `PDL::Audio|PDL::Audio' in this node - Some PDL functions intended
     for audio processing.

   * `PDL::Audio::Pitches|PDL::Audio::Pitches' in this node - All the
     standard musical pitch names.

   * `PDL::Audio::Scales|PDL::Audio::Scales' in this node - Over 1200
     musical scales in PDL format.

   * `PDL::AutoLoader|PDL::AutoLoader' in this node - MatLab style
     AutoLoader for PDL

   * `PDL::Bad|PDL::Bad' in this node - PDL does not process bad values

   * `PDL::Basic|PDL::Basic' in this node - Basic utility functions for PDL

   * `PDL::CallExt|PDL::CallExt' in this node - call functions in external
     shared libraries

   * `PDL::Char|PDL::Char' in this node - PDL subclass which allows
     reading and writing of fixed-length character strings as byte PDLs

   * `PDL::Complex|PDL::Complex' in this node - handle complex numbers

   * `PDL::Core|PDL::Core' in this node - fundamental PDL functionality

   * `PDL::Dbg|PDL::Dbg' in this node - functions to support debugging of
     PDL scripts

   * `PDL::Doc|PDL::Doc' in this node - support for PDL online
     documentation

   * `PDL::Doc::Perldl|PDL::Doc::Perldl' in this node - commands for
     accessing PDL doc database from 'perldl' shell

   * `PDL::Exporter|PDL::Exporter' in this node - PDL export control

   * `PDL::FFT|PDL::FFT' in this node - FFTs for PDL

   * `PDL::Filter::LinPred|PDL::Filter::LinPred' in this node - Linear
     predictive filtering

   * `PDL::Filter::Linear|PDL::Filter::Linear' in this node - linear
     filtering for PDL

   * `PDL::Fit::Gaussian|PDL::Fit::Gaussian' in this node - routines for
     fitting gaussians

   * `PDL::Fit::LM|PDL::Fit::LM' in this node - Levenber-Marquardt fitting
     routine for PDL

   * `PDL::Fit::Linfit|PDL::Fit::Linfit' in this node - routines for
     fitting data with linear combinations of functions.

   * `PDL::Fit::Polynomial|PDL::Fit::Polynomial' in this node - routines
     for fitting with polynomials

   * `PDL::Func|PDL::Func' in this node - useful functions

   * `PDL::Gaussian|PDL::Gaussian' in this node - Gaussian distributions.

   * `PDL::Graphics2D|PDL::Graphics2D' in this node - An object oriented
     interface to PDL graphics

   * `PDL::Graphics::IIS|PDL::Graphics::IIS' in this node - Display PDL
     images on IIS devices (saoimage/ximtool)

   * `PDL::Graphics::LUT|PDL::Graphics::LUT' in this node - provides
     access to a number of look-up tables

   * `PDL::Graphics::OpenGLQ|PDL::Graphics::OpenGLQ' in this node - quick
     routines to plot lots of stuff from piddles.

   * `PDL::Graphics::PGPLOT|PDL::Graphics::PGPLOT' in this node - PGPLOT
     enhanced interface for PDL

   * `PDL::Graphics::PGPLOT::Window|PDL::Graphics::PGPLOT::Window' in this
     node - A OO interface to PGPLOT windows

   * `PDL::Graphics::PGPLOTOptions|PDL::Graphics::PGPLOTOptions' in this
     node - Setting PGPLOT options

   * `PDL::Graphics::TriD|PDL::Graphics::TriD' in this node - PDL 3D
     interface

   *

     `PDL::Graphics::TriD::ButtonControl|PDL::Graphics::TriD::ButtonControl'
     in this node - default event handler subroutines

   * `PDL::Graphics::TriD::Contours|PDL::Graphics::TriD::Contours' in this
     node - 3D Surface contours for TriD

   * `PDL::Graphics::TriD::Labels|PDL::Graphics::TriD::Labels' in this
     node - Text tools

   * `PDL::Graphics::TriD::MathGraph|PDL::Graphics::TriD::MathGraph' in
     this node - Mathematical Graph objects for PDL

   * `PDL::Graphics::TriD::Rout|PDL::Graphics::TriD::Rout' in this node -
     Helper routines for Three-dimensional graphics

   * `PDL::Graphics::TriD::Tk|PDL::Graphics::TriD::Tk' in this node - Tk
     windows / widgets / menus for TriD.

   * `PDL::Graphics::TriD::VRML|PDL::Graphics::TriD::VRML' in this node -
     TriD VRML backend

   * `PDL::IO::Browser|PDL::IO::Browser' in this node - 2D data browser
     for PDL

   * `PDL::IO::FastRaw|PDL::IO::FastRaw' in this node - A simple, fast and
     convenient io format for PerlDL.

   * `PDL::IO::FlexRaw|PDL::IO::FlexRaw' in this node - A flexible binary
     i/o format for PerlDL.

   * `PDL::IO::Grib|PDL::IO::Grib' in this node - Grib file utilities for
     perl

   * `PDL::IO::Grib::Field|PDL::IO::Grib::Field' in this node - Field
     tools for Grib files

   * `PDL::IO::Grib::Wgrib|PDL::IO::Grib::Wgrib' in this node -
     shamelessly stolen code

   * `PDL::IO::Misc|PDL::IO::Misc' in this node - misc IO routines for PDL

   * `PDL::IO::NDF|PDL::IO::NDF' in this node - PDL Module for reading and
     writing Starlink

   * `PDL::IO::Pic|PDL::IO::Pic' in this node - image I/O for PDL

   * `PDL::IO::Pnm|PDL::IO::Pnm' in this node - pnm format I/O for PDL

   * `PDL::Image2D|PDL::Image2D' in this node - Miscellaneous 2D image
     processing functions

   * `PDL::ImageND|PDL::ImageND' in this node - useful image processing
     routines which work in N-dimensions

   * `PDL::ImageRGB|PDL::ImageRGB' in this node - some utility functions
     for RGB image data handling

   * `PDL::Lite|PDL::Lite' in this node - minimum PDL module OO loader

   * `PDL::LiteF|PDL::LiteF' in this node - minimum PDL module function
     loader

   * `PDL::Math|PDL::Math' in this node - extended mathematical operations
     and special functions

   * `PDL::Ops|PDL::Ops' in this node - Fundamental mathematical operators

   * `PDL::Opt::Simplex|PDL::Opt::Simplex' in this node - Simplex
     optimization routines

   * `PDL::Options|PDL::Options' in this node - simplifies option passing
     by hash in PerlDL

   * `PDL::Pod::Html|PDL::Pod::Html' in this node - module to convert pod
     files to HTML

   * `PDL::Primitive|PDL::Primitive' in this node - primitive operations
     for pdl

   * `PDL::Reduce|PDL::Reduce' in this node - a reduce function for PDL

   * `PDL::Slatec|PDL::Slatec' in this node - PDL interface to the slatec
     numerical programming library

   * `PDL::Slices|PDL::Slices' in this node - Stupid index tricks

   * `PDL::Tests|PDL::Tests' in this node - tests for some PP features

   * `PDL::Types|PDL::Types' in this node - define fundamental PDL
     Datatypes

   * `PDL::Ufunc|PDL::Ufunc' in this node - primitive ufunc operations for
     pdl

HISTORY
=======

   Automatically generated by scantree.pl for PDL version 2.1.1.

how to index piddles.
*********************

NAME
====

   PDL::Indexing - how to index piddles.

DESCRIPTION
===========

   This manpage should serve as a first tutorial on the indexing and
threading features of *PDL*.

   This manpage is still in alpha development and not yet complete. "Meta"
comments that point out deficiencies/omissions of this document will be
surrounded by square brackets ([]), e.g. [ Hopefully I will be able to
remove this paragraph at some time in the future ]. Furthermore, it is
possible that there are errors in the code examples. Please report any
errors to Christian Soeller (c.soeller@auckland.ac.nz).

   Still to be done are (please bear with us and/or ask on the mailing
list, see `PDL::FAQ|PDL::FAQ' in this node):

   * document perl level threading

   * threadids

   * update and correct description of slice

   * new functions in slice.pd (affine, lag, splitdim)

   * reworking of paragraph on explicit threading

Indexing and threading with PDL
===============================

   A lot of the flexibility and power of PDL relies on the indexing and
looping features of the perl extension. Indexing allows access to the data
of a pdl object in a very flexible way. Threading provides efficient
implicit looping functionality (since the loops are implemented as
optimized C code).

   Pdl objects (later often called "pdls") are perl objects that represent
multidimensional arrays and operations on those. In contrast to simple
perl `@x' style lists the array data is compactly stored in a single block
of memory thus taking up a lot less memory and enabling use of fast C code
to implement operations (e.g. addition, etc) on pdls.

pdls can have children
----------------------

   Central to many of the indexing capabilities of PDL are the relation of
"parent" and "child" between pdls. Many of the indexing commands create a
new pdl from an existing pdl. The new pdl is the "child" and the old one
is the "parent". The data of the new pdl is defined by a transformation
that specifies how to generate (compute) its data from the parent's data.
The relation between the child pdl and its parent are often bidirectional,
meaning that changes in the child's data are propagated back to the
parent. (Note: You see, we are aiming in our terminology already towards
the new dataflow features. The kind of dataflow that is used by the
indexing commands (about which you will learn in a minute) is always in
operation, not only when you have explicitly switched on dataflow in your
pdl by saying `$a->doflow'. For further information about data flow check
the dataflow manpage.)

   Another way to interpret the pdls created by our indexing commands is
to view them as a kind of intelligent pointer that points back to some
portion or all of its parent's data. Therefore, it is not surprising that
the parent's data (or a portion of it) changes when manipulated through
this "pointer". After these introductory remarks that hopefully prepared
you for what is coming (rather than confuse you too much) we are going to
dive right in and start with a description of the indexing commands and
some typical examples how they might be used in PDL programs. We will
further illustrate the pointer/dataflow analogies in the context of some
of the examples later on.

   There are two different implementations of this "smart pointer"
relationship: the first one, which is a little slower but works for any
transformation is simply to do the transformation forwards and backwards
as necessary. The other is to consider the child piddle a "virtual"
piddle, which only stores a pointer to the parent and access information
so that routines which use the child piddle actually directly access the
data in the parent.  If the virtual piddle is given to a routine which
cannot use it, PDL transparently physicalizes the virtual piddle before
letting the routine use it.

   Currently (1.94_01) all transformations which are "affine", i.e. the
indices of the data item in the parent piddle are determined by a linear
transformation (+ constant) from the indices of the child piddle result in
virtual piddles. All other indexing routines (e.g. `->index(...)') result
in physical piddles.  All routines compiled by PP can accept affine
piddles (except those routines that pass pointers to external library
functions).

   Note that whether something is affine or not does not affect the
semantics of what you do in any way: both

     $a->index(...) .= 5;
     $a->slice(...) .= 5;

   change the data in `$a'. The affinity does, however, have a significant
impact on memory usage and performance.

Slicing pdls
------------

   Probably the most important application of the concept of parent/child
pdls is the representation of rectangular slices of a physical pdl by a
virtual pdl. Having talked long enough about concepts let's get more
specific. Suppose we are working with a 2D pdl representing a 5x5 image
(its unusually small so that we can print it without filling several
screens full of digits ;).

     perldl> $im = sequence(5,5)
     perldl> p $im

     [
      [ 0  1  2  3  4]
      [ 5  6  7  8  9]
      [10 11 12 13 14]
      [15 16 17 18 19]
      [20 21 22 23 24]
     ]

     perldl> help vars
     PDL variables in package main::

     Name         Type   Dimension       Flow  State          Mem
     ----------------------------------------------------------------
     $im          Double D [5,5]                P            0.20Kb

   [ here it might be appropriate to quickly talk about the `help vars'
command that provides information about pdls in the interactive `perldl'
shell that comes with pdl.  ]

   Now suppose we want to create a 1-D pdl that just references one line
of the image, say line 2; or a pdl that represents all even lines of the
image (imagine we have to deal with even and odd frames of an interlaced
image due to some peculiar behaviour of our frame grabber). As another
frequent application of slices we might want to create a pdl that
represents a rectangular region of the image with top and bottom reversed.
All these effects (and many more) can be easily achieved with the powerful
slice function:

     perldl> $line = $im->slice(':,(2)')
     perldl> $even = $im->slice(':,1:-1:2')
     perldl> $area = $im->slice('3:4,3:1')
     perldl> help vars  # or just PDL->vars
     PDL variables in package main::

     Name         Type   Dimension       Flow  State          Mem
     ----------------------------------------------------------------
     $even        Double D [5,2]                -C           0.00Kb
     $im          Double D [5,5]                P            0.20Kb
     $line        Double D [5]                  -C           0.00Kb
     $area        Double D [2,3]                -C           0.00Kb

   All three "child" pdls are children of `$im' or in the other (largely
equivalent) interpretation pointers to data of `$im'.  Operations on those
virtual pdls access only those portions of the data as specified by the
argument to slice. So we can just print line 2:

     perldl> p $line
     [10 11 12 13 14]

   Also note the difference in the "Flow State" of $area above and below:

     perldl> p $area
     perldl> help $area
     This variable is Double D [2,3]                VC           0.00Kb

   The following demonstrates that `$im' and `$line' really behave as you
would exspect from a pointer-like object (or in the dataflow picture: the
changes in `$line''s data are propagated back to `$im'):

     perldl> $im++
     perldl> p $line
     [11 12 13 14 15]
     perldl> $line += 2
     perldl> p $im

     [
      [ 1  2  3  4  5]
      [ 6  7  8  9 10]
      [13 14 15 16 17]
      [16 17 18 19 20]
      [21 22 23 24 25]
     ]

   Note how assignment operations on the child virtual pdls change the
parent physical pdl and vice versa (however, the basic "=" assignment
doesn't, use ".=" to obtain that effect. See below for the reasons).  The
virtual child pdls are something like "live links" to the "original"
parent pdl. As previously said, they can be thought of to work similiar to
a C-pointer. But in contrast to a C-pointer they carry a lot more
information. Firstly, they specify the structure of the data they
represent (the dimensionality of the new pdl) and secondly, specify how to
create this structure from its parents data (the way this works is buried
in the internals of PDL and not important for you to know anyway (unless
you want to hack the core in the future or would like to become a PDL guru
in general (for a definition of this strange creature see
`PDL::Internals|PDL::Internals' in this node)).

   The previous examples have demonstrated typical usage of the slice
function. Since the slicing functionality is so important here is an
explanation of the syntax for the string argument to slice:

     $vpdl = $a->slice('ind0,ind1...')

   where `ind0' specifies what to do with index No 0 of the pdl `$a', etc.
Each element of the comma separated list can have one of the following
forms:

':'
     Use the whole dimension

'n'
     Use only index n. The dimension of this index in the resulting
     virtual pdl is 1. An example involving those first two index formats:

          perldl> $column = $im->slice('2,:')
          perldl> $row = $im->slice(':,0')
          perldl> p $column

          [
           [ 3]
           [ 8]
           [15]
           [18]
           [23]
          ]

          perldl> p $row

          [
           [1 2 3 4 5]
          ]

          perldl> help $column
          This variable is Double D [1,5]                VC           0.00Kb

          perldl> help $row
          This variable is Double D [5,1]                VC           0.00Kb

'(n)'
     Use only index n. This dimension is removed from the resulting pdl
     (relying on the fact that a dimension of size 1 can always be
     removed). The distinction between this case and the previous one
     becomes important in assignments where left and right hand side have
     to have appropriate dimensions.

          perldl> $line = $im->slice(':,(0)')
          perldl> help $line
          This variable is Double D [5]                  -C           0.00Kb

          perldl> p $line
          [1 2 3 4 5]

     Spot the difference to the previous example?

'n1:n2' or 'n1:n2:n3'
     Take the range of indices from `n1' to `n2' or (second form) take the
     range of indices from `n1' to `n2' with step `n3'. An example for the
     use of this format is the previous definition of the subimage
     composed of even lines.

          perldl> $even = $im->slice(':,1:-1:2')

     This example also demonstrates that negative indices work like they do
     for normal perl style arrays by counting backwards from the end of the
     dimension. If `n2' is smaller than `n1' (in the example -1 is
     equivalent to index 4) the elements in the virtual pdl are effectively
     reverted with respect to its parent.

     Add a dummy dimension. The size of this dimension will be 1 by default
     or equal to n if the optional numerical argument is given.

     Now, this is really something a bit strange on first sight. What is a
     dummy dimension? A dummy dimension inserts a dimension where there
     wasn't one before. How is that done ? Well, in the case of the new
     dimension having size 1 it can be easily explained by the way in which
     you can identify a vector (with m elements) with an `(1,m)' or `(m,1)'
     matrix. The same holds obviously for higher dimensional objects. More
     interesting is the case of a dummy dimensions of size greater than one
     (e.g. `slice('*5,:')'). This works in the same way as a call to the
     `dummy|PDL::Core' in this node function creates a new dummy dimension.
     So read on and check its explanation below.

'([n1:n2[:n3]]=i)'
     [Not yet implemented ??????]  With an argument like this you make
     *generalised diagonals*. The diagonal will be dimension no. i of the
     new output pdl and (if optional part in brackets specified) will
     extend along the range of indices specified of the respective parent
     pdl's dimension. In general an argument like this only makes sense if
     there are other arguments like this in the same call to slice. The
     part in brackets is optional for this type of argument. All arguments
     of this type that specify the same target dimension i have to relate
     to the same number of indices in their parent dimension. The best way
     to explain it is probably to give an example, here we make a pdl that
     refers to the elements along the space diagonal of its parent pdl (a
     cube):

          $cube = zeroes(5,5,5);
          $sdiag = $cube->slice('(=0),(=0),(=0)');

     The above command creates a virtual pdl that represents the diagonal
     along the parents' dimension no. 0, 1 and 2 and makes its dimension 0
     (the only dimension) of it. You use the extended syntax if the
     dimension sizes of the parent dimensions you want to build the
     diagonal from have different sizes or you want to reverse the sequence
     of elements in the diagonal, e.g.

          $rect = zeroes(12,3,5,6,2);
          $vpdl = $rect->slice('2:7,(0:1=1),(4),(5:4=1),(=1)');

     So the elements of $vpdl will then be related to those of its parent
     in way we can express as:

          vpdl(i,j) = rect(i+2,j,4,5-j,j)       0<=i<5, 0<=j<2

   [ work in the new index function: `$b = $a->index($c);' ???? ]

There are different kinds of assignments in PDL
-----------------------------------------------

   The previous examples have already shown that virtual pdls can be used
to operate on or access portions of data of a parent pdl. They can also be
used as lvalues in assignments (as the use of `++' in some of the examples
above has already demonstrated). For explicit assignments to the data
represented by a virtual pdl you have to use the overloaded `.=' operator
(which in this context we call *propagated assignment*). Why can't you use
the normal assignment operator =?

   Well, you definitely still can use the '=' operator but it wouldn't do
what you want. This is due to the fact that the '=' operator cannot be
overloaded in the same way as other assignment operators. If we tried to
use '=' to try to assign data to a portion of a physical pdl through a
virtual pdl we wouldn't achieve the desired effect (instead the variable
representing the virtual pdl (a reference to a blessed thingy) would after
the assignment just contain the reference to another blessed thingy which
would behave to future assignments as a "physical" copy of the original
rvalue [this is actually not yet clear and subject of discussions in the
PDL developers mailing list]. In that sense it would break the connection
of the pdl to the parent [ isn't this behaviour in a sense the opposite of
what happens in dataflow, where `.=' breaks the connection to the parent?
].

   E.g.

     perldl> $line = $im->slice(':,(2)')
     perldl> $line = zeroes(5);
     perldl> $line++;
     perldl> p $im

     [
      [ 1  2  3  4  5]
      [ 6  7  8  9 10]
      [13 14 15 16 17]
      [16 17 18 19 20]
      [21 22 23 24 25]
     ]

     perldl> p $line
     [1 1 1 1 1]

   But using `.='

     perldl> $line = $im->slice(':,(2)')
     perldl> $line .= zeroes(5)
     perldl> $line++
     perldl> p $im

     [
      [ 1  2  3  4  5]
      [ 6  7  8  9 10]
      [ 1  1  1  1  1]
      [16 17 18 19 20]
      [21 22 23 24 25]
     ]

     perldl> print $line
     [1 1 1 1 1]

   Also, you can substitute

     perldl> $line .= 0;

   for the assignment above (the zero is converted to a scalar piddle,
with no dimensions so it can be assigned to any piddle).

   Related to the assignment feature is a little trap for the unwary:
since perl currently does not allow subroutines to return lvalues the
following shortcut of the above is flagged as a compile time error:

     perldl> $im->slice(':,(2)') .= zeroes(5)->xvals->float

   instead you have to say something like

     perldl> ($pdl = $im->slice(':,(2)')) .= zeroes(5)->xvals->float

   We hope that future versions of perl will allow the simpler syntax
(i.e. allow subroutines to return lvalues).  [Note: perl v5.6.0 does allow
this, but it is an experimental feature. However, early reports suggest it
works in simple situations]

   Note that there can be a problem with assignments like this when lvalue
and rvalue pdls refer to overlapping portions of data in the parent pdl:

     # revert the elements of the first line of $a
     ($tmp = $a->slice(':,(1)')) .= $a->slice('-1:0,(1)');

   Currently, the parent data on the right side of the assignments is not
copied before the (internal) assignment loop proceeds. Therefore, the
outcome of this assignment will depend on the sequence in which elements
are assigned and almost certainly not do what you wanted.  So the
semantics are currently *undefined* for now and liable to change anytime.
To obtain the desired behaviour, use

     ($tmp = $a->slice(':,(1)')) .= $a->slice('-1:0,(1)')->copy;

   which makes a physical copy of the slice or

     ($tmp = $a->slice(':,(1)')) .= $a->slice('-1:0,(1)')->sever;

   which returns the same slice but severs the connection of the slice to
its parent.

Other functions that manipulate dimensions
------------------------------------------

   Having talked extensively about the `slice|PDL::Slices' in this node
function it should be noted that this is not the only PDL indexing
function. There are additional indexing functions which are also useful
(especially in the context of threading which we will talk about later).
Here are a list and some examples how to use them.

dummy
     inserts a dummy dimension of the size you specify (default 1) at the
     chosen location. You can't wait to hear how that is achieved?  Well,
     all elements with index `(X,x,Y)' (`0<=x<size_of_dummy_dim') just map
     to the element with index `(X,Y)' of the parent pdl (where X and Y
     refer to the group of indices before and after the location where the
     dummy dimension was inserted.)

     This example calculates the x coordinate of the centroid of an image
     (later we will learn that we didn't actually need the dummy dimension
     thanks to the magic of implicit threading; but using dummy dimensions
     the code would also work in a threadless world; though once you have
     worked with PDL threads you wouldn't want to live without them again).

          # centroid
          ($xd,$yd) = $im->dims;
          $xc = sum($im*xvals(zeroes($xd))->dummy(1,$yd))/sum($im);

     Let's explain how that works in a little more detail. First, the
     product:

          $xvs = xvals(zeroes($xd));
          print $xvs->dummy(1,$yd);      # repeat the line $yd times
          $prod = $im*xvs->dummy(1,$yd); # form the pixelwise product with
                                         # the repeated line of x-values

     The rest is then summing the results of the pixelwise product together
     and normalising with the sum of all pixel values in the original image
     thereby calculating the x-coordinate of the "center of mass" of the
     image (interpreting pixel values as local mass) which is known as the
     centroid of an image.

     Next is a (from the point of view of memory consumption) very cheap
     conversion from greyscale to RGB, i.e. every pixel holds now a triple
     of values instead of a scalar. The three values in the triple are,
     fortunately, all the same for a grey image, so that our trick works
     well in that it maps all the three members of the triple to the same
     source element:

          # a cheap greyscale to RGB conversion
          $rgb = $grey->dummy(0,3)

     Unfortunately this trick cannot be used to convert your old B/W
     photos to color ones in the way you'd like. :(

     Note that the memory usage of piddles with dummy dimensions is
     especially sensitive to the internal representation. If the piddle
     can be represented as a virtual affine ("vaffine") piddle, only the
     control structures are stored. But if $b in

          $a = zeroes(10000);
          $b = $a->dummy(1,10000);

     is made physical by some routine, you will find that the memory usage
     of your program has suddenly grown by 100Mb.

diagonal
     replaces two dimensions (which have to be of equal size) by one
     dimension that references all the elements along the "diagonal" along
     those two dimensions. Here, we have two examples which should appear
     familiar to anyone who has ever done some linear algebra. Firstly,
     make a unity matrix:

          # unity matrix
          $e = zeroes(float, 3, 3); # make everything zero
          ($tmp = $e->diagonal(0,1)) .= 1; # set the elements along the diagonal to 1
          print $e;

     Or the other diagonal:

          ($tmp = $e->slice(':-1:0')->diagonal(0,1)) .= 2;
          print $e;

     (Did you notice how we used the slice function to revert the sequence
     of lines before setting the diagonal of the new child, thereby setting
     the cross diagonal of the parent ?)  Or a mapping from the space of
     diagonal matrices to the field over which the matrices are defined,
     the trace of a matrix:

          # trace of a matrix
          $trace = sum($mat->diagonal(0,1));  # sum all the diagonal elements

xchg and mv
     `xchg|PDL::Slices' in this node exchanges or "transposes" the two
     specified dimensions.  A straightforward example:

          # transpose a matrix (without explicitly reshuffling data and
          # making a copy)
          $prod = $a x $a->xchg(0,1);

     `$prod' should now be pretty close to the unity matrix if `$a' is an
     orthogonal matrix. Often xchg will be used in the context of threading
     but more about that later.

     `mv|PDL::SLices' in this node works in a similar fashion. It moves a
     dimension (specified by its number in the parent) to a new position
     in the new child pdl:

          $b = $a->mv(4,0);  # make the 5th dimension of $a the first in the
                             # new child $b

     The difference between xchg and mv is that xchg only changes the
     position of two dimensions with each other, whereas mv inserts the
     first dimension to the place of second, moving the other dimensions
     around accordingly.

clump
     collapses several dimensions into one. Its only argument specifies how
     many dimensions of the source pdl should be collapsed (starting from
     the first). An (admittedly unrealistic) example is a 3D pdl which
     holds data from a stack of image files that you have just read in.
     However, the data from each image really represents a 1D time series
     and has only been arranged that way because it was digitized with a
     frame grabber. So to have it again as an array of time sequences you
     say

          perldl> $seqs = $stack->clump(2)
          perldl> help vars
          PDL variables in package main::

          Name         Type   Dimension       Flow  State          Mem
          ----------------------------------------------------------------
          $seqs        Double D [8000,50]            -C           0.00Kb
          $stack       Double D [100,80,50]          P            3.05Mb

     Unrealistic as it may seem, our confocal microscope software writes
     data (sometimes) this way. But more often you use clump to achieve a
     certain effect when using implicit or explicit threading.

Calls to indexing functions can be chained
------------------------------------------

   As you might have noticed in some of the examples above calls to the
indexing functions can be nicely chained since all of these functions
return a newly created child object. However, when doing extensive index
manipulations in a chain be sure to keep track of what you are doing, e.g.

     $a->xchg(0,1)->mv(0,4)

   moves the dimension 1 of `$a' to position 4 since when the second
command is executed the original dimension 1 has been moved to position 0
of the new child that calls the mv function. I think you get the idea (in
spite of my convoluted explanations).

Propagated assignments ('.=') and dummy dimensions
--------------------------------------------------

   A sublety related to indexing is the assignment to pdls containing dummy
dimensions of size greater than 1. These assignments (using `.=') are
forbidden since several elements of the lvalue pdl point to the same
element of the parent. As a consequence the value of those parent elements
are potentially ambiguous and would depend on the sequence in which the
implementation makes the assignments to elements. Therefore, an assignment
like this:

     $a = pdl [1,2,3];
     $b = $a->dummy(1,4);
     $b .= yvals(zeroes(3,4));

   can produce unexpected results and the results are explicitly
*undefined* by PDL because when PDL gets parallel computing features, the
current result may well change.

   From the point of view of dataflow the introduction of
greater-size-than-one dummy dimensions is regarded as an irreversible
transformation (similar to the terminology in thermodynamics) which
precludes backward propagation of assignment to a parent (which you had
explicitly requested using the `.=' assignment). A similar problem to
watch out for occurs in the context of threading where sometimes dummy
dimensions are created implicitly during the thread loop (see below).

Reasons for the parent/child (or "pointer") concept
---------------------------------------------------

   [ this will have to wait a bit ]

     XXXXX being memory efficient
     XXXXX in the context of threading
     XXXXX very flexible and powerful way of accessing portions of pdl data
           (in much more general way than sec, etc allow)
     XXXXX efficient implementation
     XXXXX difference to section/at, etc.

How to make things physical again
---------------------------------

   [ XXXXX fill in later when everything has settled a bit more ]

     ** When needed (xsub routine interfacing C lib function)
     ** How achieved (->physical)
     ** How to test (isphysical (explain how it works currently))
     ** ->copy and ->sever

Threading
=========

   In the previous paragraph on indexing we have already mentioned the
term occasionally but now its really time to talk explicitly about
"threading" with pdls. The term threading has many different meanings in
different fields of computing. Within the framework of PDL it could
probably be loosely defined as an implicit looping facility. It is
implicit because you don't specify anything like enclosing for-loops but
rather the loops are automatically (or 'magically') generated by PDL based
on the dimensions of the pdls involved. This should give you a first idea
why the index/dimension manipulating functions you have met in the
previous paragraphs are especially important and useful in the context of
threading.  The other ingredient for threading (apart from the pdls
involved) is a function that is threading aware (generally, these are
`PDL::PP|PDL::PP' in this node compiled functions) and that the pdls are
"threaded" over.  So much about the terminology and now let's try to shed
some light on what it all means.

Implicit threading - a first example
------------------------------------

   There are two slightly different variants of threading. We start with
what we call "implicit threading". Let's pick a practical example that
involves looping of a function over many elements of a pdl. Suppose we
have an RGB image that we want to convert to greyscale. The RGB image is
represented by a 3-dim pdl `im(3,x,y)' where the first dimension contains
the three color components of each pixel and x and y are width and height
of the image, respectively. Next we need to specify how to convert a
color-triple at a given pixel into a greyvalue (to be a realistic example
it should represent the relative intensity with which our color
insensitive eye cells would detect that color to achieve what we would
call a natural conversion from color to greyscale). An approximation that
works quite well is to compute the grey intensity from each RGB triplet
(r,g,b) as a weighted sum

     greyvalue = 77/256*r + 150/256*g + 29/256*b =
         inner([77,150,29]/256, [r,g,b])

   where the last form indicates that we can write this as an inner
product of the 3-vector comprising the weights for red, green and blue
components with the 3-vector containing the color components.
Traditionally, we might have written a function like the following to
process the whole image:

     my @dims=$im->dims;
     # here normally check that first dim has correct size (3), etc
     $grey=zeroes(@dims[1,2]);   # make the pdl for the resulting grey image
     $w = pdl [77,150,29] / 256; # the vector of weights
     for ($j=0;$j<dims[2];$j++) {
        for ($i=0;$i<dims[1];$i++) {
            # compute the pixel value
            $tmp = inner($w,$im->slice(':,(i),(j)'));
     	set($grey,$i,$j,$tmp); # and set it in the greyscale image
        }
     }

   Now we write the same using threading (noting that inner is a threading
aware function defined in the `PDL::Primitive|PDL::Primitive' in this node
package)

     $grey = inner($im,pdl([77,150,29]/256));

   We have ended up with a one-liner that automatically creates the pdl
`$grey' with the right number and size of dimensions and performs the
loops automatically (these loops are implemented as fast C code in the
internals of PDL).  Well, we still owe you an explanation how this 'magic'
is achieved.

How does the example work ?
---------------------------

   The first thing to note is that every function that is threading aware
(these are without exception functions compiled from concise descriptions
by `PDL::PP|PDL::PP' in this node, later just called PP-functions) expects
a defined (minimum) number of dimensions (we call them core dimensions)
from each of its pdl arguments. The `inner|PDL::Primitive' in this node
function expects two one-dimensional (input) parameters from which it
calculates a zero-dimensional (output) parameter. We write that
symbolically as `inner((n),(n),[o]())' and call it inner's signature,
where n represents the size of that dimension. n being equal in the first
and second parameter means that those dimensions have to be of equal size
in any call. As a different example take the outer product which takes two
1D vectors to generate a 2D matrix, symbolically written as
`outer((n),(m),[o](n,m))'. The `[o]' in both examples indicates that this
(here third) argument is an output argument. In the latter example the
dimensions of first and second argument don't have to agree but you see
how they determine the size of the two dimensions of the output pdl.

   Here is the point when threading finally enters the game. If you call
PP-functions with pdls that have more than the required core dimensions
the first dimensions of the pdl arguments are used as the core dimensions
and the additional extra dimensions are threaded over. Let us demonstrate
this first with our example above

     $grey = inner($im,$w); # w is the weight vector from above

   In this case $w is 1D and so supplied just the core dimension, `$im' is
3D, more specifically `(3,x,y)'. The first dimension (of size 3) is the
required core dimension that matches (as required by inner) the first (and
only) dimension of `$w'. The second dimension is the first thread
dimension (of size x) and the third is here the second thread dimension
(of size y). The output pdl is automatically created (as requested by
setting `$grey' to "null" prior to invocation). The output dimensions are
obtained by appending the *loop dimensions* (here `(x,y)') to the core
output dimensions (here 0D) to yield the final dimensions of the
autocreated pdl (here `0D+2D=2D' to yield a 2D output of size `(x,y)').

   So the above command calls the core functioniality that computes the
inner product of two 1D vectors `x*y' times with `$w' and all 1D slices of
the form `(':,(i),(j)')' of `$im' and sets the respective elements of the
output pdl `$grey(i,j)' to the result of each computation. We could write
that symbolically as

     $grey(0,0) = f($w,$im(:,(0),(0)))
     $grey(1,0) = f($w,$im(:,(1),(0)))
         .
         .
         .
     $grey(x-2,y-1) = f($w,$im(:,(x-2),(y-1)))
     $grey(x-1,y-1) = f($w,$im(:,(x-1),(y-1)))

   But this is done automatically by PDL without writing any explicit perl
loops.  We see that the command really creates an output pdl with the
right dimensions and sets the elements indeed to the result of the
computation for each pixel of the input image.

   When even more pdls and extra dimensions are involved things get a bit
more complicated. We will first give the general rules how the thread
dimensions depend on the dimensions of input pdls enabling you to figure
out the dimensionality of an autocreated output pdl (for any given set of
input pdls and core dimensions of the PP-function in question). The
general rules will most likely appear a bit confusing on first sight so
that we'll set out to illustrate the usage with a set of further examples
(which will hopefully also demonstrate that there are indeed many
practical situations where threading comes in extremly handy).

A call for coding discipline
----------------------------

   Before we point out the other technical details of threading, please
note this call for programming discipline when using threading:

   In order to preserve human readability, PLEASE comment any nontrivial
expression in your code involving threading.  Most importantly, for any
subroutine, include information at the beginning about what you expect the
dimensions to represent (or ranges of dimensions).

   As a warning, look at this undocumented function and try to guess what
might be going on:

     sub lookup {
       my ($im,$palette) = @_;
       my $res;
       index($palette->xchg(0,1),
                  $im->long->dummy(0,($palette->dim)[0]),
                  ($res=null));
       return $res;
     }

   Would you agree that it might be difficult to figure out expected
dimensions, purpose of the routine, etc ?  (If you want to find out what
this piece of code does, see below)

How to figure out the loop dimensions
-------------------------------------

   There are a couple of rules that allow you to figure out number and
size of loop dimensions (and if the size of your input pdls comply with
the threading rules). Dimensions of any pdl argument are broken down into
two groups in the following: Core dimensions (as defined by the
PP-function, see Appendix B for a list of PDL primitives) and extra
dimensions which comprises all remaining dimensions of that pdl. For
example calling a function `func' with the signature `func((n,m),[o](n))'
with a pdl `a(2,4,7,1,3)' as `f($a,($o = null))' results in the semantic
splitting of a's dimensions into: core dimensions `(2,4)' and extra
dimensions `(7,1,3)'.

R0
     Core dimensions are identified with the first N dimensions of the
     respective pdl argument (and are required). Any further dimensions are
     extra dimensions and used to determine the loop dimensions.

R1
     The number of (implicit) loop dimensions is equal to the maximal
     number of extra dimensions taken over the set of pdl arguments.

R2
     The size of each of the loop dimensions is derived from the size of
     the respective dimensions of the pdl arguments. The size of a loop
     dimension is given by the maximal size found in any of the pdls
     having this extra dimension.

R3
     For all pdls that have a given extra dimension the size must be equal
     to the size of the loop dimension (as determined by the previous
     rule) or 1; otherwise you raise a runtime exception. If the size of
     the extra dimension in a pdl is one it is implicitly treated as a
     dummy dimension of size equal to that loop dim size when performing
     the thread loop.

R4
     If a pdl doesn't have a loop dimension, in the thread loop this pdl
     is treated as if having a dummy dimension of size equal to the size
     of that loop dimension.

R5
     If output autocreation is used (by setting the relevant pdl to
     `PDL->null' before invocation) the number of dimensions of the created
     pdl is equal to the sum of the number of core output dimensions +
     number of loop dimensions. The size of the core output dimensions is
     derived from the relevant dimension of input pdls (as specified in the
     function definition) and the sizes of the other dimensions are equal
     to the size of the loop dimension it is derived from. The
     automatically created pdl will be physical (unless dataflow is in
     operation).

   In this context, note that you can run into the problem with assignment
to pdls containing greater-than-one dummy dimensions (see above).
Although your output pdl(s) didn't contain any dummy dimensions in the
first place they may end up with implicitly created dummy dimensions
according to R4.

   As an example, suppose we have a (here unspecified) PP-function with
the signature:

     func((m,n),(m,n,o),(m),[o](m,o))

   and you call it with 3 pdls `a(5,3,10,11)', `b(5,3,2,10,1,12)', and
`c(5,1,11,12)' as

     func($a,$b,$c,($d=null))

   then the number of loop dimensions is 3 (by `R0+R1' from $b and $c) with
sizes `(10,11,12)' (by R2); the two output core dimensions are `(5,2)'
(from the signature of func) resulting in a 5-dimensional output pdl $c of
size `(5,2,10,11,12)' (see R5) and (the automatically created) $d is
derived from `($a,$b,$c)' in a way that can be expressed in pdl
pseudo-code as

     $d(:,:,i,j,k) .= func($a(:,:,i,j),$b(:,:,:,i,0,k),$c(:,0,j,k))
        with 0<=i<10, 0<=j<=11, 0<=k<12

   If we analyze the color to greyscale conversion again with these rules
in mind we note another great advantage of implicit threading.  We can
call the conversion with a pdl representing a pixel (`im(3)'), a line of
rgb pixels (`im(3,x)'), a proper color image (`im(3,x,y)') or a whole
stack of RGB images (`im(3,x,y,z)'). As long as `$im' is of the form
`(3,...)' the automatically created output pdl will contain the right
number of dimensions and contain the intensity data as we exspect it since
the loops have been implicitly performed thanks to *implicit threading*.
You can easily convince yourself that calling with a color pixel `$grey'
is 0D, with a line it turns out 1D `grey(x)', with an image we get
`grey(x,y)' and finally we get a converted image stack `grey(x,y,z)'.

   Let's fill these general rules with some more life by going through a
couple of further examples. The reader may try to figure out equivalent
formulations with explicit for-looping and compare the flexibility of
those routines using implicit threading to the explicit formulation.
Furthermore, especially when using several thread dimensions it is a
useful exercise to check the relative speed by doing some benchmark tests
(which we still have to do).

   First in the row is a slightly reworked centroid example, now coded
with threading in mind.

     # threaded mult to calculate centroid coords, works for stacks as well
     $xc = sumover(($im*xvals(($im->dims)[0]))->clump(2)) /
           sumover($im->clump(2));

   Let's analyse what's going on step by step. First the product:

     $prod = $im*xvals(zeroes(($im->dims)[0]))

   This will actually work for `$im' being one, two, three, and higher
dimensional. If `$im' is one-dimensional it's just an ordinary product (in
the sense that every element of `$im' is multiplied with the respective
element of `xvals(...)'), if `$im' has more dimensions further threading
is done by adding appropriate dummy dimensions to `xvals(...)'  according
to R4.  More importantly, the two `sumover|PDL::Primitive' in this node
operations show a first example of how to make use of the dimension
manipulating commands. A quick look at sumover's signature will remind you
that it will only "gobble up" the first dimension of a given input pdl. But
what if we want to really compute the sum over all elements of the first
two dimensions? Well, nothing keeps us from passing a virtual pdl into
sumover which in this case is formed by clumping the first two dimensions
of the "parent pdl" into one. From the point of view of the parent pdl the
sum is now computed over the first two dimensions, just as we wanted,
though sumover has just done the job as specified by its signature. Got it
?

   Another little finesse of writing the code like that: we intentionally
used `sumover($pdl->clump(2))' instead of `sum($pdl)' so that we can
either pass just an image `(x,y)' or a stack of images `(x,y,t)' into this
routine and get either just one x-coordiante or a vector of x-coordinates
(of size t) in return.

   Another set of common operations are what one could call "projection
operations". These operations take a N-D pdl as input and return a (N-1)-D
"projected" pdl. These operations are often performed with functions like
`sumover|PDL::Primitive' in this node, `prodover|PDL::Primitive' in this
node, `minimum|PDL::Primitive' in this node and `maximum|PDL::Primitive'
in this node.  Using again images as examples we might want to calculate
the maximum pixel value for each line of an image or image stack. We know
how to do that

     # maxima of lines (as function of line number and time)
     maximum($stack,($ret=null));

   But what if you want to calculate maxima per column when implicit
threading always applies the core functionality to the first dimension and
threads over all others? How can we achieve that instead the core
functionality is applied to the second dimension and threading is done
over the others. Can you guess it? Yes, we make a virtual pdl that has the
second dimension of the "parent pdl" as its first dimension using the mv
command.

     # maxima of columns (as function of column number and time)
     maximum($stack->mv(0,1),($ret=null));

   and calculating all the sums of sub-slices over the third dimension is
now almost too easy

     # sums of pixles in time (assuming time is the third dim)
     sumover($stack->mv(0,2),($ret=null));

   Finally, if you want to apply the operation to all elements (like max
over all elements or sum over all elements) regardless of the dimensions of
the pdl in question clump comes in handy. As an example look at the
definition of sum (as defined in `Basic.pm'):

     sub sum {
       PDL::Primitive::sumover($name->clump(-1),($tmp=null));
       return $tmp->at(); # return a perl number, not a 0D pdl
     }

   We have already mentioned that all basic operations support threading
and assignment is no exception. So here are a couple of threaded
assignments

     perldl> $im = zeroes(byte, 10,20)
     perldl> $line = exp(-rvals(10)**2/9)
     # threaded assignment
     perldl> $im .= $line      # set every line of $im to $line
     perldl> $im2 .= 5         # set every element of $im2 to 5

   By now you probably see how it works and what it does, don't you?

   To finish the examples in this paragraph here is a function to create
an RGB image from what is called a palette image. The palette image
consists of two parts: an image of indices into a color lookup table and
the color lookup table itself. [ describe how it works ] We are going to
use a PP-function we haven't encoutered yet in the previous examples. It
is the aptly named `index|PDL::Slices' in this node function, signature
`((n),(),[o]())' (see Appendix B) with the core functionality that
`index(pdl (0,2,4,5),2,($ret=null))' will return the element with index 2
of the first input pdl. In this case, `$ret' will contain the value 4.  So
here is the example:

     # a threaded index lookup to generate an RGB, or RGBA or YMCK image
     # from a palette image (represented by a lookup table $palette and
     # an color-index image $im)
     # you can say just dummy(0) since the rules of threading make it fit
     perldl> index($palette->xchg(0,1),
                   $im->long->dummy(0,($palette->dim)[0]),
                   ($res=null));

   Let's go through it and explain the steps involved. Assuming we are
dealing with an RGB lookup-table $palette is of size `(3,x)'. First we
exchange the dimensions of the palette so that looping is done over the
first dimension of `$palette' (of size 3 that represent r, g, and b
components). Now looking at `$im', we add a dummy dimension of size equal
to the length of the number of components (in the case we are discussing
here we could have just used the number 3 since we have 3 color
components). We can use a dummy dimension since for red, green and blue
color components we use the same index from the original image, e.g.
assuming a certain pixel of `$im' had the value 4 then the lookup should
produce the triple

     [palette(0,4),palette(1,4),palette(2,4)]

   for the new red, green and blue components of the output image.
Hopefully by now you have some sort of idea what the above piece of code
is supposed to do (it is often actually quite complicated to describe in
detail how a piece of threading code works; just go ahead and experiment a
bit to get a better feeling for it).

   If you have read the threading rules carefully, then you might have
noticed that we didn't have to explicitely state the size of the dummy
dimension that we created for `$im'; when we create it with size 1 (the
default) the rules of threading make it automatically fit to the desired
size (by rule R3, in our example the size would be 3 assuming a palette of
size `(3,x)'). Since situations like this do occur often in practice this
is actually why rule R3 has been introduced (the part that makes
dimensions of size 1 fit to the thread loop dim size). So we can just say

     perldl> index($palette->xchg(0,1),$im->long->dummy(0),($res=null));

   Again, you can convince yourself that this routine will create the
right output if called with a pixel (`$im' is 0D), a line (`$im' is 1D),
an image (`$im' is 2D), ..., an RGB lookup table (palette is `(3,x)') and
RGBA lookup table (palette is `(4,x)', see e.g. OpenGL). This flexibility
is achieved by the rules of threading which are made to do the right thing
in most situations.

   To wrap it all up once again, the general idea is as follows. If you
want to achieve looping over certain dimensions and have the *core
functionality* applied to another specified set of dimensions you use the
dimension manipulating commands to create a (or several) *virtual* pdl(s)
so that from the point of view of the parent pdl(s) you get what you want
(always having the signature of the function in question and R1-R5 in
mind!). Easy, isn't it ?

Output autocreation and PP-function calling conventions
-------------------------------------------------------

   At this point we have to divert to some technical detail that has to do
with the general calling conventions of PP-functions and the automatic
creation of output arguments.  Basically, there are two ways of invoking
pdl routines, namely

     $result = func($a,$b);

   and

     func($a,$b,$result);

   If you are only using implicit threading then the output variable can
be automatically created by PDL. You flag that to the PP-function by
setting the output argument to a special kind of pdl that is returned from
a call to the function `PDL->null' that returns an essentially "empty" pdl
(for those interested in details there is a flag in the C pdl structure
for this). The dimensions of the created pdl are determined by the rules
of implicit threading: the first dimensions are the core output dimensions
to which the threading dimensions are appended (which are in turn
determined by the dimensions of the input pdls as described above).  So
you can say

     func($a,$b,($result=PDL->null));

   or

     $result = func($a,$b)

   which are *exactly* equivalent.

   Be warned that you can not use output autocreation when using explicit
threading (for reasons explained in the following section on *explicit
threading*, the second variant of threading).

   In "tight" loops you probably want to avoid the implicit creation of a
temporary pdl in each step of the loop that comes along with the
"functional" style but rather say

     # create output pdl of appropriate size only at first invocation
     $result = null;
     for (0...$n) {
          func($a,$b,$result); # in all but the first invocation $result
          func2($b);           # is defined and has the right size to
                               # take the output provided $b's dims don't change
          twiddle($result,$a); # do something from $result to $a for iteration
     }

   The take-home message of this section once more: be aware of the
limitation on output creation when using *explicit threading*.

Explicit threading
------------------

   Having so far only talked about the first flavour of threading it is
now about time to introduce the second variant. Instead of shuffling
around dimensions all the time and relying on the rules of implicit
threading to get it all right you sometimes might want to specify in a
more explicit way how to perform the thread loop. It is probably not too
surprising that this variant of the game is called *explicit threading*.
Now, before we create the wrong impression: it is not either *implicit* or
explicit; the two flavours do mix. But more about that later.

   The two most used functions with explicit threading are
`thread|PDL::Core' in this node and `unthread|PDL::Slices' in this node.
We start with an example that illustrates typical usage of the former:

     [ # ** this is the worst possible example to start with ]
     #  but can be used to show that $mat += $line is different from
     #                               $mat->thread(0) += $line
     # explicit threading to add a vector to each column of a matrix
     perldl> $mat  = zeroes(4,3)
     perldl> $line = pdl (3.1416,2,-2)
     perldl> ($tmp = $mat->thread(0)) += $line

   In this example, `$mat->thread(0)' tells PDL that you want the second
dimension of this pdl to be threaded over first leading to a thread loop
that can be expressed as

     for (j=0; j<3; j++) {
        for (i=0; i<4; i++) {
            mat(i,j) += src(j);
        }
     }

   thread takes a list of numbers as arguments which explicitly specify
which dimensions to thread over first. With the introduction of explicit
threading the dimensions of a pdl are conceptually split into three
different groups the latter two of which we have already encountered:
thread dimensions, core dimensions and extra dimensions.

   Conceptually, it is best to think of those dimensions of a pdl that
have been specified in a call to thread as being taken away from the set
of normal dimensions and put on a separate stack. So assuming we have a
pdl `a(4,7,2,8)' saying

     $b = $a->thread(2,1)

   creates a new virtual pdl of dimension `b(4,8)' (which we call the
remaining dims) that also has 2 thread dimensions of size `(2,7)'. For the
purposes of this document we write that symbolically as `b(4,8){2,7}'. An
important difference to the previous examples where only implicit
threading was used is the fact that the core dimensions are matched
against the *remaining dimensions* which are not necessarily the first
dimensions of the pdl. We will now specify how the presence of thread
dimensions changes the rules R1-R5 for threadloops (which apply to the
special case where none of the pdl arguments has any thread dimensions).

T0
     Core dimensions are matched against the first n *remaining dimensions*
     of the pdl argument (note the difference to R1). Any further
     *remaining dimensions* are *extra dimensions* and are used to
     determine the *implicit loop dimensions*.

T1a
     The number of *implicit loop dimensions* is equal to the maximal
     number of extra dimensions taken over the set of pdl arguments.

T1b
     The number of *explicit loop dimensions* is equal to the maximal
     number of thread dimensions taken over the set of pdl arguments.

T1c
     The total number of *loop dimensions* is equal to the sum of
     *explicit loop dimensions* and *implicit loop dimensions*. In the
     thread loop, *explicit loop dimensions* are threaded over first
     followed by *implicit loop dimensions*.

T2
     The size of each of the *loop dimensions* is derived from the size of
     the respective dimensions of the pdl arguments. It is given by the
     maximal size found in any pdls having this thread dimension (for
     *explicit loop dimensions*) or extra dimension (for *implicit loop
     dimensions*).

T3
     This rule applies to any *explicit loop dimension* as well as any
     *implicit loop dimension*. For all pdls that have a given
     *thread/extra dimension* the size must be equal to the size of the
     respective *explicit/implicit loop dimension* or 1; otherwise you
     raise a runtime exception. If the size of a *thread/extra dimension*
     of a pdl is one it is implicitly treated as a dummy dimension of size
     equal to the *explicit/implicit loop dimension*.

T4
     If a pdl doesn't have a *thread/extra dimension* that corresponds to
     an *explicit/implicit loop dimension*, in the thread loop this pdl is
     treated as if having a dummy dimension of size equal to the size of
     that loop dimension.

T4a
     All pdls that do have *thread dimensions* must have the same number of
     thread dimensions.

T5
     Output autocreation cannot be used if any of the pdl arguments has any
     *thread dimensions*. Otherwise R5 applies.

   The same restrictions apply with regard to implicit dummy dimensions
(created by application of T4) as already mentioned in the section on
implicit threading: if any of the output pdls has an (explicit or
implicitly created) greater-than-one dummy dimension a runtime exception
will be raised.

   Let us demonstrate these rules at work in a generic case.  Suppose we
have a (here unspecified) PP-function with the signature:

     func((m,n),(m),(),[o](m))

   and you call it with 3 pdls `a(5,3,10,11)', `b(3,5,10,1,12)', `c(10)'
and an output pdl `d(3,11,5,10,12)' (which can here not be automatically
created) as

     func($a->thread(1,3),$b->thread(0,3),$c,$d->thread(0,1))

   From the signature of func and the above call the pdls split into the
following groups of core, extra and thread dimensions (written in the form
`pdl(core dims){thread dims}[extra dims]'):

     a(5,10){3,11}[] b(5){3,1}[10,12] c(){}[10] d(5){3,11}[10,12]

   With this to help us along (it is in general helpful to write the
arguments down like this when you start playing with threading and want to
keep track of what is going on) we further deduce that the number of
explicit loop dimensions is 2 (by T1b from `$a' and $b) with sizes
`(3,11)' (by T2); 2 implicit loop dimensions (by T1a from $b and $d) of
size `(10,12)' (by T2) and the elements of are computed from the input
pdls in a way that can be expressed in pdl pseudo-code as

     for (l=0;l<12;l++)
      for (k=0;k<10;k++)
       for (j=0;j<11;j++)         effect of treating it as dummy dim (index j)
        for (i=0;i<3;i++)                         |
           d(i,j,:,k,l) = func(a(:,i,:,j),b(i,:,k,0,l),c(k))

   Uhhmpf, this example was really not easy in terms of bookeeping. It
serves mostly as an example how to figure out what's going on when you
encounter a complicated looking expression. But now it is really time to
show that threading is useful by giving some more of our so called
"practical" examples.

   [ The following examples will need some additional explanations in the
future. For the moment please try to live with the comments in the code
fragments. ]

   Example 1:

     *** inverse of matrix represented by eigvecs and eigvals
     ** given a symmetrical matrix M = A^T x diag(lambda_i) x A
     **    =>  inverse M^-1 = A^T x diag(1/lambda_i) x A
     ** first $tmp = diag(1/lambda_i)*A
     ** then  A^T * $tmp by threaded inner product
     # index handling so that matrices print correct under pdl
     $inv .= $evecs*0;  # just copy to get appropriately sized output
     $tmp .= $evecs;    # initialise, no backpropagation
     ($tmp2 = $tmp->thread(0)) /= $evals;    #  threaded division
     # and now a matrix multiplication in disguise
     PDL::Primitive::inner($evecs->xchg(0,1)->thread(-1,1),
                           $tmp->thread(0,-1),
                           $inv->thread(0,1));
     # alternative for matrix mult using implicit threading,
     # first xchg only for transpose
     PDL::Primitive::inner($evecs->xchg(0,1)->dummy(1),
                           $tmp->xchg(0,1)->dummy(2),
                           ($inv=null));

   Example 2:

     # outer product by threaded multiplication
     # stress that we need to do it with explicit call to my_biop1
     # when using explicit threading
     $res=zeroes(($a->dims)[0],($b->dims)[0]);
     my_biop1($a->thread(0,-1),$b->thread(-1,0),$res->(0,1),"*");
     # similiar thing by implicit threading with autocreated pdl
     $res = $a->dummy(1) * $b->dummy(0);

   Example 3:

     # different use of thread and unthread to shuffle a number of
     # dimensions in one go without lots of calls to ->xchg and ->mv

     # use thread/unthread to shuffle dimensions around
     # just try it out and compare the child pdl with its parent
     $trans = $a->thread(4,1,0,3,2)->unthread;

   Example 4:

     # calculate a couple of bounding boxes
     # $bb will hold BB as [xmin,xmax],[ymin,ymax],[zmin,zmax]
     # we use again thread and unthread to shuffle dimensions around
     perldl> $bb = zeroes(double, 2,3 );
     perldl> minimum($vertices->thread(0)->clump->unthread(1),
                     $bb->slice('(0),:'));
     perldl> maximum($vertices->thread(0)->clump->unthread(1),
                     $bb->slice('(1),:'));

   Example 5:

     # calculate a self-ratioed (i.e. self normalized) sequence of images
     # uses explicit threading and an implicitly threaded division
     $stack = read_image_stack();
     # calculate the average (per pixel average) of the first $n+1 images
     $aver = zeroes([stack->dims]->[0,1]);  # make the output pdl
     sumover($stack->slice(":,:,0:$n")->thread(0,1),$aver);
     $aver /= ($n+1);
     $stack /= $aver;  # normalize the stack by doing a threaded divison
     # implicit versus explicit
     # alternatively calculate $aver with implicit threading and autocreation
     sumover($stack->slice(":,:,0:$n")->mv(2,0),($aver=null));
     $aver /= ($n+1);
     #

Implicit versus explicit threading
----------------------------------

   In this paragraph we are going to illustrate when explicit threading is
preferrable over implicit threading and vice versa. But then again, this
is probably not the best way of putting the case since you already know:
the two flavours do mix. So, it's more about how to get the best of both
worlds and, anyway, in the best of perl traditions: TIMTOWTDI !

   [ Sorry, this still has to be filled in in a later release; either
refer to above examples or choose some new ones ]

   Finally, this may be a good place to justify all the technical detail
we have been going on about for a couple of pages: why threading ?

   Well, code that uses threading should be (considerably) faster than
code that uses explicit for-loops (or similar perl constructs) to achieve
the same functionality. Especially on supercomputers (with vector
computing facilities/parallel processing) PDL threading will be
implemented in a way that takes advantage of the additional facilities of
these machines. Furthermore, it is a conceptually simply construct (though
technical details might get involved at times) and can *greatly* reduce
the syntactical complexity of PDL code (but keep the admonition for
documentation in mind). Once you are comfortable with the *threading* way
of thinking (and coding) it shouldn't be too difficult to understand code
that somebody else has written than (provided he gave you an idea what
exspected input dimensions are, etc.). As a general tip to increase the
performance of your code: if you have to introduce a loop into your code
try to reformulate the problem so that you can use threading to perform
the loop (as with anything there are exceptions to this rule of thumb; but
the authors of this document tend to think that these are rare cases ;).

PDL::PP
=======

An easy way to define functions that are aware of indexing and threading (and the universe and everything)
----------------------------------------------------------------------------------------------------------

   PDL:PP is part of the PDL distribution. It is used to generate
functions that are aware of indexing and threading rules from very concise
descriptions. It can be useful for you if you want to write your own
functions or if you want to interface functions from an external library
so  that they support indexing and threading (and mabe dataflow as well,
see PDL/Dataflow). For further details check
PDL/PP.

Appendix A
==========

Affine transformations - a special class of simple and powerful transformations
-------------------------------------------------------------------------------

   [ This is also something to be added in future releases. Do we already
have the general make_affine routine in PDL ? It is possible that we will
reference another appropriate manpage from here ]

Appendix B
==========

signatures of standard PDL::PP compiled functions
-------------------------------------------------

   A selection of signatures of PDL primitives to show how many dimensions
PP compiled functions gobble up (and therefore you can figure out what
will be threaded over). Most of those functions are the basic ones defined
in `primitive.pd'

     # functions in primitive.pd
     #
     sumover	((n),[o]())
     prodover	((n),[o]())
     axisvalues     ((n))					inplace
     inner		((n),(n),[o]())
     outer		((n),(m),[o](n,m))
     innerwt	((n),(n),(n),[o]())
     inner2         ((m),(m,n),(n),[o]())
     inner2t	((j,n),(n,m),(m,k),[o]())
     index		(1D,0D,[o])
     minimum	(1D,[o])
     maximum	(1D,[o])
     wstat		((n),(n),(),[o],())
     assgn		((),())

     # basic operations
     binary operations ((),(),[o]())
     unary operations  ((),[o]())

AUTHOR & COPYRIGHT
==================

   Copyright (C) 1997 Christian Soeller (c.soeller@auckland.ac.nz) & Tuomas
J. Lukka (lukka@fas.harvard.edu). All rights reserved. Although destined
for release as a man page with the standard PDL distribution, it is not
public domain. Permission is granted to freely distribute verbatim copies
of this document provided that no modifications outside of formatting be
made, and that this notice remain intact.  You are permitted and
encouraged to use its code and derivatives thereof in your own source code
for fun or for profit as you see fit.

description of the current internals
************************************

NAME
====

   PDL::Internals - description of the current internals

DESCRIPTION
===========

Intro
-----

   This document explains various aspects of the current implementation of
PDL. If you just want to use PDL for something, you definitely do not need
to read this. Even if you want to interface your C routines to PDL or
create new `PDL::PP|PDL::PP' in this node functions, you do not need to
read this (though it may be informative). This document is primarily
intended for people interested in debugging or changing the internals of
PDL. To read this, a good understanding of the C language and programming
and data structures in general is required, as well as some perl
understanding. If you read through this document and understand all of it
and are able to point what any part of this document refers to in the PDL
core sources and additionally struggle to understand `PDL::PP|PDL::PP' in
this node, you will be awarded the title "PDL Guru" (of course, the
current version of this document is so incomplete that this is not yet the
case).

   Warning: If it seems that this document has gotten out of date, please
inform the PerlDL developers email list (address in the README file) about
it. This may well happen.

Piddles
-------

   Currently, a pdl data object is a hash ref which contains the element
PDL, which is a pointer to a pdl structure, as well as some other fields.
The file `Core.pm' uses some of these fields and the file `pdlhash.c'
converts these to C when necessary.

   The pdl struct is defined in `pdl.h' and the meanings of the fields are

magicno
     A magic number, used to check whether something really is a piddle
     when debugging.

state
     Various flags about the state of the pdl, such as whether the parents
     of this pdl have been altered at some point.

trans
     Where this pdl was obtained from. This pointer may be null, in which
     case this pdl is not getting any dataflow from anywhere.  Note,
     however that being non-null does not mean that data is flowing:

          $a = pdl 2,3,4;
          $b = pdl 4,5,6;
          $c = $a + $b;     # Note: no dataflow (not asked for)

     here, the trans field in $c contains a pointer to a transformation.
     Only when `$a' or $b is changed, is the transformation destroyed and
     the field cleared. To see whether data is flowing, check the flags
     field of the trans struct.

vafftrans
     This is intended for speeding up e.g. the chaining of affine
     transformations. See `pdlapi.c' for the code handling this.  Also,
     `slices.pd' defines some things with / for this.

sv
     Pointer to the hash object. May be null if this pdl does not have a
     perl counterpart.

datasv, data
     The field datasv is a pointer to the perl SV containing the data
     string.  These may be null before the pdl is finally physicalized.

nvals
     How many values there are in data

datatype
     The type of the data stored in the data vector.

dims, ndims
     The dimensions of this pdl. Remember to physicalize the pdl before
     using.

dimincs
     As an optimization, an increment for each dimension is stored here.
     These are required to correspond exactly to dims.  If you want to
     optimize for affine transformations, use the trans or vtrans.

threadids, nthreadids
     This is where the threading tags are stored. The way this works is
     that ndims and dims hold all dimensions of the pdl, including
     threaded dimensions. The real dimensions of the pdl extend from 0 to
     `threadids[0]-1', the thread dimensions with id 0 extend from
     `threadids[0]' to `threadids[1]-1' and the thread dimensions with the
     last id extend from `threadids[nthreadids-1]' to
     `threadids[nthreadids]-1'.  For example, if a pdl has dimensions
     `(2,3,4,5)' (= 120 elements) and `nthreadids==2' and
     `threadids={1,3,4}', there is one "real" dimensions with size 2, two
     dimensions with threadid 0 (3 and 4) and the dimensions with size 5
     has threadid 1.

progenitor, future_me
     See the section on families below

children
     The children of this pdl i.e. where data is flowing to from this pdl.

living_for
     XXX Not quite clear right now. Has to do with families

     To avoid mallocs, there is a suitable amount of space already
     allocated for each pointer in this pdl, with the ideology that if you
     have more than six-dimensional data you must be willing to settle for
     a little more overhead.

magic
     If this pdl is magical (e.g. if it is bound to something), this
     pointer is non-null and you must call the appropriate magic-handling
     routines when using the pdl.

hdrsv
     A "header" SV * that can be set and accessed from outside.  Can be
     used to include any perl object in a piddle.

Transformations
---------------

   Each transformation has a virtual table which contains various
information about that transformation. Usually transformations are
generated with `PDL::PP|PDL::PP' in this node so it's better to see that
documentation.

Freeing
-------

   Currently, not much is freed, especially when dataflow is done.  This
is bound to change pretty soon.

Threading
---------

   The file `pdlthread.c' handles most of the threading matters.  The
threading is encapsulated in the structure `pdlthread.h'.

Accessing children and parents of a piddle
------------------------------------------

   The file `Basic/Core/pdlapi.h.PL' contains useful routines for
manipulating the pdl structure (it's probably easier to read
`Basic/Core/pdlapi.h' once you've performed a build of PDL).

   An example of processing the children of a piddle is provided by the
`baddata' method of PDL::Bad (only available if you have comiled PDL with
the WITH_BADVAL option set to 1, but still useful as an example!).

   Consider the following situation:

     perldl> $a = rvals(7,7,Centre=>[3,4]);
     perldl> $b = $a->slice('2:4,3:5');
     perldl> ? vars
     PDL variables in package main::

     Name         Type   Dimension       Flow  State          Mem
     ----------------------------------------------------------------
     $a           Double D [7,7]                P            0.38Kb
     $b           Double D [3,3]                VC           0.00Kb

   Now, if I suddenly decide that `$a' should be flagged as possibly
containing bad values, using

     perldl> $a->baddata(1)

   then I want the state of $b - it's child - to be changed as well, so
that I get a 'B' in the State field:

     perldl> ? vars
     PDL variables in package main::

     Name         Type   Dimension       Flow  State          Mem
     ----------------------------------------------------------------
     $a           Double D [7,7]                PB           0.38Kb
     $b           Double D [3,3]                VCB          0.00Kb

   This bit of magic is performed by the `propogate_badflag' function,
which is listed below:

     /* newval = 1 means set flag, 0 means clear it */
     /* thanks to Christian Soeller for this */

     void propogate_badflag( pdl *it, int newval ) {
        PDL_DECL_CHILDLOOP(it)
        PDL_START_CHILDLOOP(it)
        {
     	pdl_trans *trans = PDL_CHILDLOOP_THISCHILD(it);
     	int i;
     	for( i = trans->vtable->nparents;
     	     i < trans->vtable->npdls;
     	     i++ ) {
     	    pdl *child = trans->pdls[i];

     if ( newval ) child->state |=  PDL_BADVAL;
                 else          child->state &= ~PDL_BADVAL;

     /* make sure we propogate to grandchildren, etc */
     propogate_badflag( child, newval );

     } /* for: i */
         }
         PDL_END_CHILDLOOP(it)
      } /* propogate_badflag */

   Given a piddle (`pdl *it'), the routine loops through each `pdl_trans'
structure, where access to this structure is provided by the
`PDL_CHILDLOOP_THISCHILD' macro.  The children of the piddle are stored in
the `pdls' array, after the *parents*, hence the loop from `i =
...nparents' to `i = ...nparents - 1'.  Once we have the pointer to the
child piddle, we can do what we want to it; here we change the value of
the state variable, but the details are unimportant).  What *is* important
is that we call `propogate_badflag' on this piddle, to ensure we loop
through its children. This recursion ensures we get to all the *offspring*
of a particular piddle.

   *THE FOLLOWING NEEDS TO BE CHECKED*.

   Access to *parents* is similar, with the for loop replaced by:

     for( i = 0;
          i < trans->vtable->nparents;
          i++ ) {

AUTHOR
======

   Copyright(C) 1997 Tuomas J. Lukka (lukka@fas.harvard.edu), 2000 Doug
Burke (burke@ifa.hawaii.edu).

   Redistribution in the same form is allowed but reprinting requires a
permission from the author.

Introduction to the Perl Data Language
**************************************

NAME
====

   PDL::Intro - Introduction to the Perl Data Language

   Version 2.0

   "Why is it that we entertain the belief that for every purpose odd
numbers are the most effectual?" - Pliny the Elder.

   *Karl Glazebrook [karlglazebrook@yahoo.com]*

DESCRIPTION
===========

   Perl is an extremely good and versatile scripting language, well suited
to beginners and allows rapid prototyping. However until recently it did
not support data structures which allowed it to do fast number crunching.

   However with the development of Perl v5, Perl acquired 'Objects'. To put
it simply users can define their own special data types, and write custom
routines to manipulate them either in low level languages (C and Fortran)
or in Perl itself.

   This has been fully exploited by the PerlDL developers. The 'PDL'
module is a complete Object-Oriented extension to Perl (although you don't
have to know what an object is to use it) which allows large N-dimensional
data sets, such as large images, spectra, time series, etc to be stored
*efficiently* and manipulated *en masse*.  For example  with the PDL
module we can write the perl code `$a=$b+$c', where $b and $c are large
datasets (e.g. 2048x2048 images), and get the result in only a fraction of
a second.

   PDL variables (or 'piddles' as they have come to be known) support a
wide range of fundamental data types - arrays can be bytes, short integers
(signed or unsigned), long integers, floats or double precision floats.
And because of the Object-Oriented nature of PDL new customised datatypes
can be derived from them.

   As well as the PDL modules, that can be used by normal perl programs,
PerlDL comes with a command line perl shell, called *perldl*, which
supports command line editing. In combination with the various PDL
graphics modules this allows data to be easily played with and visualised.

SYNOPSIS
========

   This manual page provides a general introduction to the underlying
philosophy of PDL and practical examples on how to use it. For details,
see:

PDL/Intro,
     This document

See PDL/Impatient,
     Quick summary - PDL for the impatient

See PDL/Philosophy,
     Why another matrix language?

See PDL/Indexing,
     An introduction to using smart indices in PDL.

`PDL::Slice' in this node
     A reference guide to the same.

See PDL/PP,
     A utility for generating extension in C language for use with PDL
     easily.

See PDL/FAQ,
     The Frequently Asked Questions list for PDL.

See PDL/Tips,
     Small tips and tricks for writing idiomatic PDL code.

See PDL/Internals,
     How does it all work?

See PDL/Dataflow,
     Tuomas has been too lazy to document this yet.

AUTHOR
======

   Copyright (C) Karl Glazebrook (karlglazebrook@yahoo.com), Tuomas J.
Lukka, (lukka@husc.harvard.edu) and Christian Soeller
(c.soeller@auckland.ac.nz) 1997 to 2000.  Commercial reproduction of this
documentation in a different format is forbidden.

minimum PDL module OO loader
****************************

NAME
====

   PDL::Lite - minimum PDL module OO loader

DESCRIPTION
===========

   Loads the smallest possible set of modules for PDL to work, without
importing an functions in to the current namespace. This is the absolute
minimum set for PDL.

   Though know functions are defined (apart from a few always exported by
Core) you can still use method syntax, viz:

     $x->wibble(42);

SYNOPSIS
========

     use PDL::Lite; # Is equivalent to the following:

     use PDL::Core '';
     use PDL::Ops '';
     use PDL::Primitive '';
     use PDL::Ufunc '';
     use PDL::Basic '';
     use PDL::Slices '';
     use PDL::Bad '';
     use PDL::Version;

minimum PDL module function loader
**********************************

NAME
====

   PDL::LiteF - minimum PDL module function loader

DESCRIPTION
===========

   Loads the smallest possible set of modules for PDL to work, making the
functions available in the current namespace. If you want something even
smaller see the `PDL::Lite|PDL::Lite' in this node module.

SYNOPSIS
========

     use PDL::LiteF; # Is equivalent to the following:

     use PDL::Core;
     use PDL::Ops;
     use PDL::Primitive;
     use PDL::Ufunc;
     use PDL::Basic;
     use PDL::Slices;
     use PDL::Bad;
     use PDL::Version;

extended mathematical operations and special functions
******************************************************

NAME
====

   PDL::Math - extended mathematical operations and special functions

SYNOPSIS
========

     use PDL::Math;

     use PDL::Graphics::TriD;
     imag3d [SURF2D,bessj0(rvals(zeroes(50,50))/2)];

DESCRIPTION
===========

   This module extends PDL with more advanced mathematical functions than
provided by standard Perl.

   All the functions have one input pdl, and one output, unless otherwise
stated.

   The functions are usually available from the system maths library,
however if they are not (determined when PDL is compiled) a version from
the Cephes math library is used.

FUNCTIONS
=========

acos
----

asin
----

atan
----

cosh
----

sinh
----

tan
---

tanh
----

ceil
----

floor
-----

rint
----

pow
---

acosh
-----

asinh
-----

atanh
-----

erf
---

erfc
----

bessj0
------

bessj1
------

bessy0
------

bessy1
------

bessjn
------

bessyn
------

lgamma
------

   This returns 2 piddles - the first set gives the log(gamma) values,
while the second set, of integer values, gives the sign of the gamma
function.  This is useful for determining factorials, amongst other things.

badmask
-------

   badmask can be run with `$a' inplace:

     badmask($a->inplace,0);
     $a->inplace->badmask(0);

isfinite
--------

erfi
----

ndtri
-----

svd
---

polyroots
---------

eigens
------

simq
----

   `$a' is an `n x n' matrix (i.e., a vector of length `n*n'), stored
row-wise: that is, `a(i,j) = a[ij]', where `ij = i*n + j'.  While this is
the transpose of the normal column-wise storage, this corresponds to
normal PDL usage.  The contents of matrix a may be altered (but may be
required for subsequent calls with flag = -1).

   $b, $x, `$ips' are vectors of length n.

   Set `flag=0' to solve.  Set `flag=-1' to do a new back substitution for
different $b vector using the same a matrix previously reduced when
`flag=0' (the `$ips' vector generated in the previous solution is also
required).

squaretotri
-----------

BUGS
====

   Hasn't been tested on all platforms to ensure Cephes versions are
picked up automatically and used correctly.

AUTHOR
======

   Copyright (C) R.J.R. Williams 1997 (rjrw@ast.leeds.ac.uk), Karl
Glazebrook (kgb@aaoepp.aao.gov.au) and Tuomas J. Lukka
(Tuomas.Lukka@helsinki.fi).

   All rights reserved. There is no warranty. You are allowed to
redistribute this software / documentation under certain conditions. For
details, see the file COPYING in the PDL distribution. If this file is
separated from the PDL distribution, the copyright notice should be
included in the file.

Object-Orientation, what is it and how to exploit it
****************************************************

NAME
====

   PDL::Objects - Object-Orientation, what is it and how to exploit it

DESCRIPTION
===========

   This still needs to be written properly.

Inheritance
-----------

   There are basically two reasons for subclassing piddles.  The first is
simply that you want to be able to use your own routines like

     $piddle->something()

   but don't want to mess up the PDL namespace (a worthy goal, indeed!).
The other is that you wish to provide special handling of some functions
or more information about the data the piddle contains.  In the first
case, you can do with

     package BAR;
     @ISA=qw/PDL/;
     sub foo {my($this) = @_; fiddle;}

     package main;
     $a = PDL::pdl(BAR,5);
     $a->foo();

   However, because a PDL object is an opaque reference to a C struct, it
is not possible to extend the PDL class by e.g. extra data via subclassing.
To circumvent this problem PerlDL has built-in support to extent the PDL
class via the *has-a* relation for blessed hashes.  You can get the
*HAS-A* behave like *IS-A* simply in that you assign the `PDL' object to
the attribute named PDL and redefine the method initialize().

     package FOO;

     @FOO::ISA = qw(PDL);
     sub initialize {
         my $class = shift;
         my $self = {
                 creation_time => time(),  # necessary extension :-)
                 PDL => null,             # used to store PDL object
                 };
         bless $self, $class;
     }

   All PDL constructors will call initialize() to make sure that your
extentions are added by all PDL constructors automaticly.   The `PDL'
attribute is used by perlDL to store the PDL object and all PDL methods
use this attribute automaticly if they are called with a blessed hash
reference instead of a PDL object (a blessed scalar).

   Do remember that if you subclass a class that is subclassed from a
piddle, you need to call SUPER::initialize.

   NEED STUFF ABOUT CODE REFs!!

Examples
--------

   You can find some simple examples of PDL subclassing in the PDL
distribution test-case files. Look in `t/subclass2.t', `t/subclass3.t',
etc.

Output Auto-Creation and Subclassed Objects
-------------------------------------------

   For PDL Functions where the output is created and returned, PDL will
either call the subclassed object's initialize or copy method to create the
output object. (See `PDL::Indexing|PDL::Indexing' in this node for a
discussion on Output Auto-Creation.) This behavior is summarized as
follows:

   * For Simple functions, defined as having a signature of

          func( a(), [o]b() )

     PDL will call $a->copy to create the output object.

     In the spirit of the perl philosophy of making *Easy Things Easy*,
     This behavior enables PDL-subclassed objects to be written without
     having to overload the many simple PDL functions in this category.

     The file t/subclass4.t in the PDL Distribution tests for this
     behavior.  See that file for an example.

   * For other functions, PDL will call $class->initialize to create the
     output object.  Where $class is the class name of the first argument
     supplied to the function.

     For these more complex cases, it is difficult to second-guess the
     subclassed-object's designer to know if a copy or a initialize is
     appropriate. So for these cases, $class->initialize is called by
     default. If this is not appropriate for you, overload the function in
     your subclass and do whatever is appropriate is the overloaded
     function's code.

AUTHOR
======

   Copyright (C) Karl Glazebrook (kgb@aaoepp.aao.gov.au), Tuomas J. Lukka,
(lukka@husc.harvard.edu) and Christian Soeller (c.soeller@auckland.ac.nz)
2000.  Commercial reproduction of this documentation in a different format
is forbidden.

Fundamental mathematical operators
**********************************

NAME
====

   PDL::Ops - Fundamental mathematical operators

DESCRIPTION
===========

   This module provides the functions used by PDL to overload the basic
mathematical operators (`+ - / *' etc.) and functions (`sin sqrt' etc.)

   It also includes the function log10, which should be a perl function so
that we can overload it!

SYNOPSIS
========

   none

FUNCTIONS
=========

plus
----

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the binary + operator.  Note that when
calling this function explicitly you need to supply a third argument that
should generally be zero (see first example).  This restriction is
expected to go away in future releases.

mult
----

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the binary * operator.  Note that when
calling this function explicitly you need to supply a third argument that
should generally be zero (see first example).  This restriction is
expected to go away in future releases.

minus
-----

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the binary - operator.  Note that when
calling this function explicitly you need to supply a third argument that
should generally be zero (see first example).  This restriction is
expected to go away in future releases.

divide
------

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the binary / operator.  Note that when
calling this function explicitly you need to supply a third argument that
should generally be zero (see first example).  This restriction is
expected to go away in future releases.

gt
--

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the binary `>' operator.  Note that when
calling this function explicitly you need to supply a third argument that
should generally be zero (see first example).  This restriction is
expected to go away in future releases.

lt
--

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the binary `<' operator.  Note that when
calling this function explicitly you need to supply a third argument that
should generally be zero (see first example).  This restriction is
expected to go away in future releases.

le
--

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the binary `<=' operator.  Note that when
calling this function explicitly you need to supply a third argument that
should generally be zero (see first example).  This restriction is
expected to go away in future releases.

ge
--

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the binary `>=' operator.  Note that when
calling this function explicitly you need to supply a third argument that
should generally be zero (see first example).  This restriction is
expected to go away in future releases.

eq
--

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the binary `==' operator.  Note that when
calling this function explicitly you need to supply a third argument that
should generally be zero (see first example).  This restriction is
expected to go away in future releases.

ne
--

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the binary `!=' operator.  Note that when
calling this function explicitly you need to supply a third argument that
should generally be zero (see first example).  This restriction is
expected to go away in future releases.

shiftleft
---------

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the binary `<<' operator.  Note that when
calling this function explicitly you need to supply a third argument that
should generally be zero (see first example).  This restriction is
expected to go away in future releases.

shiftright
----------

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the binary `>>' operator.  Note that when
calling this function explicitly you need to supply a third argument that
should generally be zero (see first example).  This restriction is
expected to go away in future releases.

or2
---

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the binary | operator.  Note that when
calling this function explicitly you need to supply a third argument that
should generally be zero (see first example).  This restriction is
expected to go away in future releases.

and2
----

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the binary & operator.  Note that when
calling this function explicitly you need to supply a third argument that
should generally be zero (see first example).  This restriction is
expected to go away in future releases.

xor
---

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the binary ^ operator.  Note that when
calling this function explicitly you need to supply a third argument that
should generally be zero (see first example).  This restriction is
expected to go away in future releases.

bitnot
------

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the unary `~' operator/function.

power
-----

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the binary `**' function.  Note that when
calling this function explicitly you need to supply a third argument that
should generally be zero (see first example).  This restriction is
expected to go away in future releases.

atan2
-----

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the binary atan2 function.  Note that when
calling this function explicitly you need to supply a third argument that
should generally be zero (see first example).  This restriction is
expected to go away in future releases.

modulo
------

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the binary % function.  Note that when
calling this function explicitly you need to supply a third argument that
should generally be zero (see first example).  This restriction is
expected to go away in future releases.

spaceship
---------

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the binary `<=>' function.  Note that when
calling this function explicitly you need to supply a third argument that
should generally be zero (see first example).  This restriction is
expected to go away in future releases.

sqrt
----

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the unary sqrt operator/function.

abs
---

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the unary abs operator/function.

sin
---

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the unary sin operator/function.

cos
---

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the unary cos operator/function.

not
---

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the unary ! operator/function.

exp
---

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the unary exp operator/function.

log
---

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the unary log operator/function.

log10
-----

   It can be made to work inplace with the `$a->inplace' syntax.  This
function is used to overload the unary log10 operator/function.

assgn
-----

AUTHOR
======

   Tuomas J. Lukka (lukka@fas.harvard.edu), Karl Glazebrook
(kgb@aaoepp.aao.gov.au), Doug Hunt (dhunt@ucar.edu), Christian Soeller
(c.soeller@auckland.ac.nz), and Doug Burke (burke@ifa.hawaii.edu).

Simplex optimization routines
*****************************

NAME
====

   PDL::Opt::Simplex - Simplex optimization routines

SYNOPSIS
========

     use PDL::Opt::Simplex;

     ($optimum,$ssize) = simplex($init,$initsize,$minsize,
     		 $maxiter,
     		 sub {evaluate_func_at($_[0])},
     		 sub {display_simplex($_[0])}
     		 );

DESCRIPTION
===========

   This package implements the commonly used simplex optimization
algorithm. The basic idea of the algorithm is to move a "simplex" of N+1
points in the N-dimensional search space according to certain rules. The
main benefit of the algorithm is that you do not need to calculate the
derivatives of your function.

   $init is a 1D vector holding the initial values of the N fitted
parameters, $optimum is a vector holding the final solution.

   $initsize is the size of $init (more...)

   $minsize is some sort of convergence criterion (more...)  - e.g.
$minsize = 1e-6

   The sub is assumed to understand more than 1 dimensions and threading.
Its signature is 'inp(nparams); [ret]out()'. An example would be

     sub evaluate_func_at {
     	my($xv) = @_;
     	my $x1 = $xv->slice("(0)");
     	my $x2 = $xv->slice("(1)");
     	return $x1**4 + ($x2-5)**4 + $x1*$x2;
     }

   Here $xv is a vector holding the current values of the parameters being
fitted which are then sliced out explicitly as $x1 and $x2.

   $ssize gives a very very approximate estimate of how close we might be
- it might be miles wrong. It is the euclidean distance between the best
and the worst vertices. If it is not very small, the algorithm has not
converged.

FUNCTIONS
=========

simplex
-------

   See module `PDL::Opt::Simplex' for more information.

CAVEATS
=======

   Do not use the simplex method if your function has local minima.  It
will not work. Use genetic algorithms or simulated annealing or conjugate
gradient or momentum gradient descent.

   They will not really work either but they are not guaranteed not to
work ;) (if you have infinite time, simulated annealing is guaranteed to
work but only after it has visited every point in your space).

SEE ALSO
========

   Ron Shaffer's chemometrics web page and references therein:
`http://chem1.nrl.navy.mil/~shaffer/chemoweb.html'.

   Numerical Recipes (bla bla bla XXX ref).

   The demonstration (Examples/Simplex/tsimp.pl and tsimp2.pl).

AUTHOR
======

   Copyright(C) 1997 Tuomas J. Lukka.  All rights reserved. There is no
warranty. You are allowed to redistribute this software / documentation
under certain conditions. For details, see the file COPYING in the PDL
distribution. If this file is separated from the PDL distribution, the
copyright notice should be included in the file.

simplifies option passing by hash in PerlDL
*******************************************

NAME
====

   PDL::Options - simplifies option passing by hash in PerlDL

SYNOPSIS
========

     use PDL::Options;

     %hash = parse( \%defaults, \%user_options);

     use PDL::Options ();

     $opt = new PDL::Options;
     $opt = new PDL::Options ( \%defaults );

     $opt->defaults ( \%defaults );
     $opt->synonyms ( { 'COLOR' => 'COLOUR' } );

     $hashref = $opt->defaults;

     $opt->options ( \%user_options );

     $hashref = $opt->options;

     $opt->incremental(1);
     $opt->full_options(0);

DESCRIPTION
===========

   Object to simplify option passing for PerlDL subroutines.  Allows you
to merge a user defined options with defaults.  A simplified (non-OO)
interface is provided.

Utility functions
=================

ifhref
------

     parse({Ext => 'TIF', ifhref($opt)});

   just return the argument if it is a hashref otherwise return an empty
hashref. Useful in conjunction with parse to return just the default
values if argument is not a hash ref

NON-OO INTERFACE
================

   A simplified non-object oriented interface is provided.  These routines
are exported into the callers namespace by default.

parse( \%defaults, \%user_options)
     This will parse user options by using the defaults.  The following
     settings are used for parsing: The options can be case-insensitive, a
     default synonym table is consulted (currently just contains a synonym
     for COLOUR), minimum-matching is turned on, translation of values is
     not performed.

     A hash (not hash reference) containing the processed options is
     returned.

          %options = parse( { LINE => 1, COLOUR => 'red'}, { COLOR => 'blue'});

iparse( \%defaults, \%user_options)
     Same as parse but matching is case insensitive

METHODS
=======

   The following methods are available to PDL::Options objects.

new()
     Constructor. Creates the object. With an optional argument can also
     set the default options.

extend (\%options)
     This will copy the existing options object and extend it with the
     requested extra options.

defaults( \%defaults )
     Method to set or return the current defaults. The argument should be
     a reference to a hash. The hash reference is returned if no arguments
     are supplied.

     The current values are reset whenever the defaults are changed.

add_synonym (\%synonyms)
     Method to add another synonym to an option set The argument should be
     a reference to a hash.

add_translation (\%translation)
     Method to add another translation rule to an option set.  The
     argument should be a reference to a hash.

synonyms( \%synonyms )
     Method to set or return the current synonyms. The argument should be
     a reference to a hash. The hash reference is returned if no arguments
     are supplied.

     This allows you to provide alternate keywords (such as allowing
     'COLOR' as an option when your defaults uses 'COLOUR').

current
     Returns the current state of the options. This is returned as a hash
     reference (although it is not a reference to the actual hash stored
     in the object). If full_options() is true the full options hash is
     returned, if full_options() is false only the modified options are
     returned (as set by the last call to options()).

translation
     Provide translation of options to more specific values that are
     recognised by the program. This allows, for example, the automatic
     translation of the string 'red' to '#ff0000'.

     This method can be used to setup the dictionary and is hash reference
     with the following structure:

          OPTIONA => {
          	        'string1' => decode1,
                      'string2' => decode2
          		},
          OPTIONB => {
                      's4' => decodeb1,
          	       }
          etc....

     Where OPTION? corresponds to the top level option name as stored in
     the defaults array (eg LINECOLOR) and the anonymous hashes provide
     the translation from string1 ('red') to decode1 ('#ff0000').

     An options string will be translated automatically during the main
     options() processing if autotrans() is set to true. Else translation
     can be initiated by the user using the translate() method.

incremental
     Specifies whether the user defined options will be treated as
     additions to the current state of the object (1) or modifications to
     the default values only (0).

     Can be used to set or return this value.  Default is false.

full_options
     Governs whether a complete set of options is returned (ie defaults +
     expanded user options), true, or if just the expanded user options
     are returned, false (ie the values specified by the user).

     This can be useful when you are only interested in the changes to the
     options rather than knowing the full state. (For example, if defaults
     contains keys for COLOUR and LINESTYLE and the user supplied a key of
     COL, you may simply be interested in the modification to COLOUR
     rather than the state of LINESTYLE and COLOUR.)

     Default is true.

casesens
     Specifies whether the user defined options will be processed
     independent of case (0) or not (1). Default is to be case insensitive.

     Can be used to set or return this value.

minmatch
     Specifies whether the user defined options will be minimum matched
     with the defaults (1) or whether the user defined options should match
     the default keys exactly. Defaults is true (1).

     If a particular key matches exactly (within the constraints imposed
     bby case sensitivity) this key will always be taken as correct even
     if others are similar. For example COL would match COL and COLOUR but
     this implementation will always return COL in this case (note that
     for CO it will return both COL and COLOUR and pick one at random.

     Can be used to set or return this value.

autotrans
     Specifies whether the user defined options will be processed via the
     translate() method immediately following the main options parsing.
     Default is to autotranslate (1).

     Can be used to set or return this value.

casesenstrans
     Specifies whether the keys in the options hash will be matched
     insensitive of case (0) during translation() or not (1). Default is
     to be case insensitive.

     Can be used to set or return this value.

minmatchtrans
     Specifies whether the keys in the options hash  will be minimum
     matched during translation(). Default is false (0).

     If a particular key matches exactly (within the constraints imposed
     bby case sensitivity) this key will always be taken as correct even
     if others are similar. For example COL would match COL and COLOUR but
     this implementation will always return COL in this case (note that
     for CO it will return both COL and COLOUR and pick one at random.

     Can be used to set or return this value.

warnonmissing
     Turn on or off the warning message printed when an options is not in
     the options hash. This can be convenient when a user passes a set of
     options that has to be parsed by several different option objects down
     the line.

debug
     Turn on or off debug messages. Default is off (0).  Can be used to
     set or return this value.

options
     Takes a set of user-defined options (as a reference to a hash) and
     merges them with the current state (or the defaults; depends on the
     state of incremental()).

     The user-supplied keys will be compared with the defaults.  Case
     sensitivity and minimum matching can be configured using the
     mimatch() and casesens() methods.

     A warning is raised if keys present in the user options are not
     present in the defaults unless warnonmissing is set.

     A reference to a hash containing the merged options is returned.

          $merged = $opt->options( { COL => 'red', Width => 1});

     The state of the object can be retrieved after this by using the
     current() method or by using the options() method with no arguments.
     If full_options() is true, all options are returned (options plus
     overrides), if full_options() is false then only the modified options
     are returned.

     Synonyms are supported if they have been configured via the synonyms()
     method.

translate
     Translate the current option values (eg those set via the options()
     method) using the provided translation().

     This method updates the current state of the object and returns the
     updated options hash as a reference.

          $ref = $opt->translate;

EXAMPLE
=======

   Two examples are shown. The first uses the simplified interface and the
second uses the object-oriented interface.

Non-OO
======

     use PDL::Options (':Func');

     %options = parse( {
     		   LINE => 1,
     		   COLOUR => 'red',
     		  },
     		  {
     		   COLOR => 'blue'
     		  }
     		);

   This will return a hash containg

     %options = (
                  LINE => 1,
                  COLOUR => 'blue'
                )

Object oriented
===============

   The following example will try to show the main points:

     use PDL::Options ();

     # Create new object and supply defaults
     $opt = new PDL::Options(   { Colour => 'red',
     	   		        LineStyle => 'dashed',
     			        LineWidth => 1
     			      }
     			   );

     # Create synonyms
     $opt->synonyms( { Color => 'Colour' } );

     # Create translation dictionary
     $opt->translation( { Colour => {
                           'blue' => '#0000ff',
     			 'red'  => '#ff0000',
     			 'green'=> '#00ff00'
     				},
     	  	        LineStyle => {
     			 'solid' => 1,
     			 'dashed' => 2,
     			 'dotted' => 3
     			 }
     		      }
     		    );

     # Generate and parse test hash
     $options = $opt->options( { Color => 'green',
     			       lines => 'solid',
     			      }
     			   );

   When this code is run, $options will be the reference to a hash
containing the following:

     Colour => '#00ff00',
     LineStyle => 1,
     LineWidth => 1

   If full_options() was set to false (0), $options would be a reference
to a hash containing:

     Colour => '#00ff00',
     LineStyle => 1

   Minimum matching and case insensitivity can be configured for both the
initial parsing and for the subsequent translating. The translation can be
turned off if not desired.

   Currently synonyms are not available for the translation although this
could be added quite simply.

AUTHOR
======

   Copyright (C) Tim Jenness 1998 (t.jenness@jach.hawaii.edu).  All rights
reserved. There is no warranty. You are allowed to redistribute this
software / documentation under certain conditions. For details, see the
file COPYING in the PDL distribution. If this file is separated from the
PDL distribution, the copyright notice should be included in the file.

Generate PDL routines from concise descriptions
***********************************************

NAME
====

   PDL::PP - Generate PDL routines from concise descriptions

SYNOPSIS
========

   e.g.

     pp_def(
     	'sumover',
     	Pars => 'a(n); [o]b();',
     	Code => 'double tmp=0;
     		loop(n) %{ tmp += $a(); %}
     		$b() = tmp;
     		'
     );

     pp_done();

DESCRIPTION
===========

   In much of what follows we will assume familiarity of the reader with
the concepts of implicit and explicit threading and index manipulations
within PDL. If you have not yet heard of these concepts or are not very
comfortable with them it is time to check PDL/Indexing.

   As you may appreciate from its name PDL::PP is a Pre-Processor, i.e.
it expands code via substitutions to make real C-code (well, actually it
outputs XS code (See *perlxs*) but that is very close to C).

Overview
========

   Why do we need PP? Several reasons: firstly, we want to be able to
generate subroutine code for each of the PDL datatypes (PDL_Byte,
PDL_Short,. etc).  AUTOMATICALLY.  Secondly, when referring to slices of
PDL arrays in Perl (e.g. `$a->slice('0:10:2,:')' or other things such as
transposes) it is nice to be able to do this transparently and to be able
to do this 'in-place' - i.e, not to have to make a memory copy of the
section. PP handles all the necessary element and offset arithmetic for
you. There are also the notions of threading (repeated calling of the same
routine for multiple slices, see PDL/Indexing) and
dataflow (see PDL/Dataflow) which use of PP allows.

   So how do you use PP? Well for the most part you just write ordinary C
code except for special PP constructs which take the form:

     $something(something else)

   or:

     PPfunction %{
       <stuff>
     %}

   The most important PP construct is the form `$array()'. Consider the
very simple PP function to sum the elements of a 1D vector (in fact this is
very similar to the actual code used by 'sumover'):

     pp_def('sumit',
             Pars => 'a(n);  [o]b();',
             Code => '
             	double tmp;
             	tmp = 0;
             	loop(n) %{
              	  tmp += $a();
              	%}
              	$b() = tmp;
     ');

   What's going on? The `Pars =>' line is very important for PP - it
specifies all the arguments and their dimensionality. We call this the
signature of the PP function (compare also the explanations in
PDL/Indexing).  In this case the routine takes a 1-D
function as input and returns a 0-D scalar as output.  The `$a()' PP
construct is used to access elements of the array a(n) for you - PP fills
in all the required C code.

   [Aside: since PP used `$var()' for its parsing you must single-quote
all Code=> arguments since you don't want perl to interpolate `$var()' into
another string - i.e. don't use "" unless you know what you are doing!
Tjl: it's usually easiest to use single quotes and
'something'.$interpolatable.'somethingelse']

   In the simple case here where all elements are accessed the PP construct
`loop(n) %{ ... %}' is used to loop over all elements in dimension n.
Note this feature of PP: ALL DIMENSIONS ARE SPECIFIED BY NAME.

   This is made clearer if we avoid the PP loop() construct and write the
loop explicitly using conventional C:

     pp_def('sumit',
             Pars => 'a(n);  [o]b();',
             Code => '
             	int i,n_size;
             	double tmp;
             	n_size = $SIZE(n);
             	tmp = 0;
             	for(i=0; i<n_size; i++) {
              	  tmp += $a(n=>i);
              	}
              	$b() = tmp;
     ');

   which does the same as before, except more long-windedly.  You can see
to get element i of a() we say `$a(n=>i)' - we are specifying the
dimension by name n. In 2D we might say:

     Pars=>'a(m,n);',
        ...
        tmp += $a(m=>i,n=>j);
        ...

   The syntax 'm=>i' borrows from Perl hashes (which are in fact used in
the implementation of PP). One could also say `$a(n=>j,m=>i)' as order is
not important.

   You can also see in the above example the use of another PP construct -
$SIZE(n) to get the length of the dimension n.

   It should, however, be noted that you shouldn't write an explicit C-loop
when you could have used the PP loop construct since PDL::PP checks
automatically the loop limits for you, usage of loop makes the code more
concise, etc. But there are certainly situations where you need explicit
control of the loop and now you know how to do it ;).

   To revisit 'Why PP?' - the above code for sumit() will be generated for
each data-type. It will operate on slices of arrays 'in-place'. It will
thread automatically - e.g. if a 2D array is given it will be called
repeatedly for each 1D row (again check PDL/Indexing,
for the details of threading).  And then b() will be a 1D array of sums of
each row.  We could call it with $a->xchg(0,1) to sum the colums instead.
And Dataflow tracing etc. will be available.

   You can see PP saves the programmer from writing a lot of needlessly
repetitive C-code - in our opinion this is one of the best features of PDL
making writing new C subroutines for PDL an amazingly concise exercise. A
second reason is the ability to make PP expand your concise code
definitions into different C code based on the needs of the computer
architecture in question. Imagine for example you are lucky to have a
supercomputer at your hands; in that case you want PDL::PP certainly to
generate code that takes advantage of the vectorising/parallel computing
features of your machine (this a project for the future). In any case, the
bottom line is that your unchanged code should still expand to working XS
code even if the internals of PDL changed.

   Also, because you are generating the code in an actual Perl script,
there are many fun things that you can do. Let's say that you need to
write both sumit (as above) and multit. With a little bit of inventivity,
we can do

     for({Name => 'sumit', Init => '0', Op => '+='},
         {Name => 'multit', Init => '1', Op => '*='}) {
     	   pp_def($_->{Name},
     		   Pars => 'a(n);  [o]b();',
     		   Code => '
     			double tmp;
     			tmp = '.$_->{Init}.';
     			loop(n) %{
     			  tmp '.$_->{Op}.' $a();
     			%}
     			$b() = tmp;
     	   ');
     }

   which defines both the functions easily. Now, if you later need to
change the signature or dimensionality or whatever, you only need to
change one place in your code.  Yeah, sure, your editor does have 'cut and
paste' and 'search and replace' but it's still less bothersome and
definitely more difficult to forget just one place and have strange bugs
creep in.  Also, adding 'orit' (bitwise or) later is a one-liner.

   And remember, you really have perl's full abilities with you - you can
very easily read any input file and make routines from the information in
that file. For simple cases like the above, the author (Tjl) currently
favors the hash syntax like the above - it's not too much more characters
than the corresponding array syntax but much easier to understand and
change.

   We should mention here also the ability to get the pointer to the
beginning of the data in memory - a prerequisite for interfacing PDL to
some libraries. This is handled with the `$P(var)' directive, see below.

   So, after this quick overview of the general flavour of programming PDL
routines using PDL::PP let's summarise in which circumstances you should
actually use this preprocessor/precompiler. You should use PDL::PP if you
want to

   * interface PDL to some external library

   * write some algorithm that would be slow if coded in perl (this is not
     as often as you think; take a look at threading and dataflow first).

   * be a PDL developer (and even then it's not obligatory)

WARNING
=======

   Because of its architecture, PDL::PP can be both flexible and easy to
use (yet exuberantly complicated) at the same time. Currently, part of the
problem is that error messages are not very informative and if something
goes wrong, you'd better know what you are doing and be able to hack your
way through the internals (or be able to figure out by trial and error
what is wrong with your args to `pp_def').

   An alternative, of course, is to ask someone about it (e.g., through the
mailing lists).

ABANDON ALL HOPE, YE WHO ENTER HERE (DESCRIPTION)
=================================================

   Now that you have some idea how to use `pp_def' to define new PDL
functions it is time to explain the general syntax of `pp_def'.  `pp_def'
takes as arguments first the name of the function you are defining and
then a hash list that can contain various keys.

   Based on these keys PP generates XS code and a .pm file. The function
`pp_done' (see example in the SYNOPSIS) is used to tell PDL::PP that there
are no more definitions in this file and it is time to generate the .xs and
.pm file.

   As a consequence, there may be several pp_def() calls inside a file (by
convention files with PP code have the extension .pd or .pp) but generally
only one pp_done().

   There are two main different types of usage of pp_def(), the 'data
operation' and 'slice operation' prototypes.

   The 'data operation' is used to take some data, mangle it and output
some other data; this includes for example the '+' operation, matrix
inverse, sumover etc and all the examples we have talked about in this
document so far. Implicit and explicit threading and the creation of the
result are taken care of automatically in those opeartions. You can even
do dataflow with `sumit', sumover, etc (don't be dismayed if you don't
understand the concept of dataflow in PDL very well yet; it is still very
much experimental).

   The 'slice operation' is a different kind of operation: in a slice
operation, you are not changing any data, you are defining correspondences
between different elements of two piddles (examples include the index
manipulation/slicing function definitions in the file `slices.pd' that is
part of the PDL distribution; but beware, this is not introductory level
stuff).

   If PDL was compiled with support for bad values (ie `WITH_BADVAL => 1'),
then additional keys are required for `pp_def', as explained below.

   If you are just interested in communicating with some external library
(for example some linear algebra/matrix library), you'll usually want the
'data operation' so we are going to discuss that first.

Data operation
==============

A simple example
----------------

   In the data operation, you must know what dimensions of data you need.
First, an example with scalars:

     pp_def('add',
     	Pars => 'a(); b(); [o]c();',
     	Code => '$c() = $a() + $b();'
     );

   That looks a little strange but let's dissect it. The first line is
easy: we're defining a routine with the name 'add'.  The second line
simply declares our parameters and the parentheses mean that they are
scalars. We call the string that defines our parameters and their
dimensionality the signature of that function. For its relevance with
regard to threading and index manipulations check the PDL/Indexing,
manpage.

   The third line is the actual operation. You need to use the dollar
signs and parentheses to refer to your parameters (this will probably
change at some point in the future, once a good syntax is found).

   These lines are all that is necessary to actually define the function
for PDL (well, actually it isn't; you aditionally need to write a
Makefile.PL (see below) and build the module (something like 'perl
Makefile.PL; make'); but let's ignore that for the moment). So now you can
do

     use MyModule;
     $a = pdl 2,3,4;
     $b = pdl 5;

     $c = add($a,$b);
     # or
     add($a,$b,($c=null)); # Alternative form, useful if $c has been
                           # preset to something big, not useful here.

   and have threading work correctly (the result is $c == [7 8 9]).

The Pars section: the signature of a PP function
------------------------------------------------

   Seeing the above example code you will most probably ask: what is this
strange `$c=null' syntax in the second call to our new add function? If
you take another look at the definition of add you will notice that the
third argument c is flagged with the qualifier `[o]' which tells PDL::PP
that this is an output argument. So the above call to add means 'create a
new $c from scratch with correct dimensions' - null is a special token for
'empty piddle' (you might ask why we haven't used the value undef to flag
this instead of the PDL specific null; we are currently thinking about it
;).

   [This should be explained in some other section of the manual as well!!]
The reason for having this syntax as an alternative is that if you have
really huge piddles, you can do

     $c = PDL->null;
     for(some long loop) {
     	# munge a,b
     	add($a,$b,$c);
     	# munge c, put something back to a,b
     }

   and avoid allocating and deallocating $c each time. It is allocated
once at the first add() and thereafter the memory stays until $c is
destroyed.

   If you just say

     $c =  add($a,$b);

   the code generated by PP will automatically fill in `$c=null' and return
the result. If you want to learn more about the reasons why PDL::PP
supports this style where output arguments are given as last arguments
check the PDL/Indexing, manpage.

   `[o]' is not the only qualifier a pdl argument can have in the
signature.  Another important qualifier is the `[t]' option which flags a
pdl as temporary.  What does that mean? You tell PDL::PP that this pdl is
only used for temporary results in the course of the calculation and you
are not interested in its value after the computation has been completed.
But why should PDL::PP want to know about this in the first place?  The
reason is closely related to the concepts of pdl auto creation (you heard
about that above) and implicit threading. If you use implicit threading
the dimensionality of automatically created pdls is actually larger than
that specified in the signature. With `[o]' flagged pdls will be created
so that they have the additional dimensions as required by the number of
implicit thread dimensions. When creating a temporary pdl, however, it
will always only be made big enough so that it can hold the result for one
iteration in a threadloop, i.e. as large as required by the signature.  So
less memory is wasted when you flag a pdl as temporary. Secondly, you can
use output auto creation with temporary pdls even when you are using
explicit threading which is forbidden for normal output pdls flagged with
`[o]' (see PDL/Indexing).

   Here is an example where we use the [t] qualifier. We define the
function `callf' that calls a C routine f which needs a temporary array of
the same size and type as the array a (sorry about the forward reference
for `$P'; it's a pointer access, see below) :

     pp_def('callf',
     	Pars => 'a(n); [t] tmp(n); [o] b()',
     	Code => 'int ns = $SIZE(n);
     		 f($P(a),$P(b),$P(tmp),ns);
     		'
     );

Argument dimensions and the signature
-------------------------------------

   Now we have just talked about dimensions of pdls and the signature. How
are they related? Let's say that we want to add a scalar + the index
number to a vector:

     pp_def('add2',
     	Pars => 'a(n); b(); [o]c(n);',
     	Code => 'loop(n) %{
     			$c() = $a() + $b() + n;
     		 %}'
     );

   There are several points to notice here: first, the Pars argument now
contains the n arguments to show that we have a single dimensions in a and
c. It is important to note that dimensions are actual entities that are
accessed by name so this declares a and c to have the *same* first
dimensions. In most PP definitions the size of named dimensions will be
set from the respective dimensions of non-output pdls (those with no `[o]'
flag) but sometimes you might want to set the size of a named dimension
explicitly through an integer parameter. See below in the description of
the OtherPars section how that works.

Type conversions and the signature
----------------------------------

   The signature also determines the type conversions that will be
performed when a PP function is invoked. So what happens when we invoke
one of our previously defined functions with pdls of different type, e.g.

     add2($a,$b,($ret=null));

   where $a is of type `PDL_Float' and $b of type `PDL_Short'? With the
signature as shown in the definition of `add2' above the datatype of the
operation (as determined at runtime) is that of the pdl with the 'highest'
type (sequence is byte < short < ushort < long < float < double). In the
add2 example the datatype of the operation is float ($a has that
datatype). All pdl arguments are then type converted to that datatype
(they are not converted inplace but a copy with the right type is created
if a pdl argument doesn't have the type of the operation).  Null pdls
don't contribute a type in the determination of the type of the operation.
However, they will be created with the datatype of the operation; here,
for example, $ret will be of type float. You should be aware of these
rules when calling PP functions with pdls of different types to take the
additional storage and runtime requirements into account.

   These type conversions are correct for most functions you normally
define with `pp_def'. However, there are certain cases where slightly
modified type conversion behaviour is desired. For these cases additional
qualifiers in the signature can be used to specify the desired properties
with regard to type conversion. These qualifiers can be combined with
those we have encountered already (the *creation qualifiers* `[o]' and
`[t]'). Let's go through the list of qualifiers that change type
conversion behaviour.

   The most important is the int qualifier which comes in handy when a pdl
argument represents indices into another pdl. Let's take a look at an
example from `PDL::Ufunc':

     pp_def('maximum_ind',
     	  Pars => 'a(n); int [o] b()',
     	  Code => '$GENERIC() cur;
     		   int curind;
     		   loop(n) %{
     		    if (!n || $a() > cur) {cur = $a(); curind = n;}
     	 	   %}
     	 	   $b() = curind;',
     );

   The function maximum_ind finds the index of the largest element of a
vector. If you look at the signature you notice that the output argument b
has been declared with the additional int qualifier.  This has the
following consequences for type conversions: regardless of the type of the
input pdl a the output pdl b will be of type `PDL_Long' which makes sense
since b will represent an index into a. Furthermore, if you call the
function with an existing output pdl b its type will not influence the
datatype of the operation (see above). Hence, even if a is of a smaller
type than b it will not be converted to match the type of b but stays
untouched, which saves memory and CPU cycles and is the right thing to do
when b represents indices. Also note that you can use the 'int' qualifier
together with other qualifiers (the `[o]' and `[t]' qualifiers). Order is
significant - type qualifiers precede creation qualifiers (`[o]' and
`[t]').

   The above example also demonstrates typical usage of the $GENERIC()
macro.  It expands to the current type in a so called generic loop. What
is a generic loop? As you already heard a PP function has a runtime
datatype as determined by the type of the pdl arguments it has been
invoked with.  The PP generated XS code for this function therefore
contains a switch like `switch (type) {case PDL_Byte: ... case PDL_Double:
...}' that selects a case based on the runtime datatype of the function
(it's called a type "loop" because there is a loop in PP code that
generates the cases).  In any case your code is inserted once for each PDL
type into this switch statement. The $GENERIC() macro just expands to the
respective type in each copy of your parsed code in this switch statement,
e.g., in the `case PDL_Byte' section `cur' will expand to `PDL_Byte' and
so on for the other case statements. I guess you realise that this is a
useful macro to hold values of pdls in some code.

   There are a couple of other qualifiers with similar effects as int.
For your convenience there are the float and double qualifiers with
analogous consequences on type conversions as int. Let's assume you have a
*very* large array for which you want to compute row and column sums with
an equivalent of the sumover function.  However, with the normal
definition of sumover you might run into problems when your data is, e.g.
of type short. A call like

     sumover($large_pdl,($sums = null));

   will result in `$sums' be of type short and is therefore prone to
overflow errors if `$large_pdl' is a very large array. On the other hand
calling

     @dims = $large_pdl->dims; shift @dims;
     sumover($large_pdl,($sums = zeroes(double,@dims)));

   is not a good alternative either. Now we don't have overflow problems
with `$sums' but at the expense of a type conversion of `$large_pdl' to
double, something bad if this is really a large pdl. That's where double
comes in handy:

     pp_def('sumoverd',
     	 Pars => 'a(n); double [o] b()',
     	 Code => 'double tmp=0;
     		  loop(n) %{ tmp += a(); %}
     		  $b() = tmp;',
     );

   This gets us around the type conversion and overflow problems. Again,
analogous to the int qualifier double results in b always being of type
double regardless of the type of a without leading to a typeconversion of
a as a side effect.

   Finally, there are the `type+' qualifiers where type is one of int or
float. What shall that mean. Let's illustrate the `int+' qualifier with
the actual definition of sumover:

     pp_def('sumover',
     	 Pars => 'a(n); int+ [o] b()',
     	 Code => '$GENERIC(b) tmp=0;
     		  loop(n) %{ tmp += a(); %}
     		  $b() = tmp;',
     );

   As we had already seen for the int, float and double qualifiers, a pdl
marked with a `type+' qualifier does not influence the datatype of the pdl
operation. Its meaning is "make this pdl at least of type type or higher,
as required by the type of the operation". In the sumover example this
means that when you call the function with an a of type PDL_Short the
output pdl will be of type PDL_Long (just as would have been the case with
the int qualifier). This again tries to avoid overflow problems when using
small datatypes (e.g. byte images).  However, when the datatype of the
operation is higher than the type specified in the `type+' qualifier b
will be created with the datatype of the operation, e.g. when a is of type
double then b will be double as well. We hope you agree that this is
sensible behaviour for sumover. It should be obvious how the `float+'
qualifier works by analogy.  It may become necessary to be able to specify
a set of alternative types for the parameters. However, this will probably
not be implemented until someone comes up with a reasonable use for it.

   Note that we now had to specify the `$GENERIC' macro with the name of
the pdl to derive the type from that argument. Why is that? If you
carefully followed our explanations you will have realised that in some
cases b will have a different type than the type of the operation.
Calling the '$GENERIC' macro with b as argument makes sure that the type
will always the same as that of b in that part of the generic loop.

   This is about all there is to say about the Pars section in a `pp_def'
call. You should remember that this section defines the signature of a PP
defined function, you can use several options to qualify certain arguments
as output and temporary args and all dimensions that you can later refer
to in the Code section are defined by name.

   It is important that you understand the meaning of the signature since
in the latest PDL versions you can use it to define threaded functions
from within perl, i.e. what we call *perl level threading*. Please check
PDL/Indexing, for details.

The Code section
----------------

   The Code section contains the actual XS code that will be in the
innermost part of a threadloop (if you don't know what a thread loop is
then you still haven't read PDL/Indexing,; do it now
;) after any PP macros (like `$GENERIC') and PP functions have been
expanded (like the loop function we are going to explain next).

   Let's quickly reiterate the sumover example:

     pp_def('sumover',
     	 Pars => 'a(n); int+ [o] b()',
     	 Code => '$GENERIC(b) tmp=0;
     		  loop(n) %{ tmp += a(); %}
     		  $b() = tmp;',
     );

   The loop construct in the Code section also refers to the dimension
name so you don't need to specify any limits: the loop is correctly sized
and everything is done for you, again.

   Next, there is the surprising fact that `$a()' and `$b()' do not
contain the index. This is not necessary because we're looping over n and
both variables know which dimensions they have so they automatically know
they're being looped over.

   This feature comes in very handy in many places and makes for much
shorter code. Of course, there are times when you want to circumvent this;
here is a function which symmetrizes a matrix and serves as an example of
how to code explicit looping:

     pp_def('symm',
     	Pars => 'a(n,n); [o]c(n,n);',
     	Code => 'loop(n) %{
     			int n2;
     			for(n2=n; n2<$SIZE(n); n2++) {
     				$c(n0 => n, n1 => n2) =
     				$c(n0 => n2, n1 => n) =
     				 $a(n0 => n, n1 => n2);
     			}
     		%}
     	'
     );

   Let's dissect what is happening. Firstly, what is this function
supposed to do? From its signature you see that it takes a 2D matrix with
equal numbers of columns and rows and outputs a matrix of the same size.
From a given input matrix $a it computes a symmetric output matrix $c
(symmetric in the matrix sense that A^T = A where ^T means matrix
transpose, or in PDL parlance $c == $c->xchg(0,1)). It does this by using
only the values on and below the diagonal of $a. In the output matrix $c
all values on and below the diagonal are the same as those in $a while
those above the diagonal are a mirror image of those below the diagonal
(above and below are here interpreted in the way that PDL prints 2D pdls).
If this explanation still sounds a bit strange just go ahead, make a
little file into which you write this definition, build the new PDL
extension (see section on Makefiles for PP code) and try it out with a
couple of examples.

   Having explained what the function is supposed to do there are a couple
of points worth noting from the syntactical point of view. First, we get
the size of the dimension named n again by using the `$SIZE' macro.
Second, there are suddenly these funny `n0' and `n1' index names in the
code though the signature defines only the dimension n. Why this? The
reason becomes clear when you note that both the first and second
dimension of $a and $b are named n in the signature of `symm'. This tells
PDL::PP that the first and second dimension of these arguments should have
the same size. Otherwise the generated function will raise a runtime error.
However, now in an access to `$a' and $c PDL::PP cannot figure out which
index n refers to any more just from the name of the index.  Therefore,
the indices with equal dimension names get numbered from left to right
starting at 0, e.g. in the above example `n0' refers to the first
dimension of `$a' and $c, `n1' to the second and so on.

   In all examples so far, we have only used the Pars and Code members of
the hash that was passed to `pp_def'. There are certainly other keys that
are recognised by PDL::PP and we will hear about some of them in the
course of this document. Find a (non-exhaustive) list of keys in Appendix
A.  A list of macros and PPfunctions (we have only encountered some of
those in the examples above yet) that are expanded in values of the hash
argument to `pp_def' is summarised in Appendix B.

   At this point, it might be appropriate to mention that PDL::PP is not a
completely static, well designed set of routines (as Tuomas puts it: "stop
thinking of PP as a set of routines carved in stone") but rather a
collection of things that the PDL::PP author (Tuomas J. Lukka) considered
he would have to write often into his PDL extension routines. PP tries to
be expandable so that in the future, as new needs arise, new common code
can be abstracted back into it. If you want to learn more on why you might
want to change PDL::PP and how to do it check the section on PDL::PP
internals.

Handling bad values
-------------------

   If you do not have bad-value support compiled into PDL you can ignore
this section and the related keys: BadCode, HandleBad, ...  (try printing
out the value of $PDL::Bad::Status - if it equals 0 then move straight on).

   There are several keys and macros used when writing code to handle bad
values. The first one is the HandleBad key:

HandleBad => 0
     This flags a pp-routine as *NOT* handling bad values. If this routine
     is sent piddles with their `badflag' set, then a warning message is
     printed to STDOUT and the piddles are processed as if the value used
     to represent bad values is a valid number. The `badflag' value is not
     propogated to the output piddles.

     An example of when this is used is for FFT routines, which generally
     do not have a way of ignoring part of the data.

HandleBad => 1
     This causes PDL::PP to write extra code that ensures the BadCode
     section is used, and that the `$ISBAD()' macro (and its brethren)
     work.

HandleBad is not given
     If any of the input piddles have their `badflag' set, then the output
     piddles will have their `badflag' set, but any supplied BadCode is
     ignored.

   The value of HandleBad is used to define the contents of the BadDoc
key, if it is not given.

   To handle bad values, code must be written somewhat differently; for
instance,

     $c() = $a() + $b();

   becomes something like

     if ( $a() != BADVAL && $b() != BADVAL ) {
        $c() = $a() + $b();
     } else {
        $c() = BADVAL;
     }

   However, we only want the second version if bad values are present in
the input piddles (and that bad-value support is wanted!) - otherwise we
actually want the original code. This is where the BadCode key comes in;
you use it to specify the code to execute if bad values may be present,
and PP uses both it and the Code section to create something like:

     if ( bad_values_are_present ) {
        fancy_threadloop_stuff {
           BadCode
        }
     } else {
        fancy_threadloop_stuff {
           Code
        }
     }

   This approach means that there is virtually no overhead when bad values
are not present (ie the `badflag|PDL::Bad' in this node routine returns 0).

   The BadCode section can use the same macros and looping constructs as
the Code section.  However, it wouldn't be much use without the following
additional macros:

$ISBAD(var)
     To check whether a piddle's value is bad, use the `$ISBAD' macro:

          if ( $ISBAD(a()) ) { printf("a() is bad\n"); }

     You can also access given elements of a piddle:

          if ( $ISBAD(a(n=>l)) ) { printf("element %d of a() is bad\n", l); }

$ISGOOD(var)
     This is the opposite of the `$ISBAD' macro.

$SETBAD(var)
     For when you want to set an element of a piddle bad.

$ISBADVAR(c_var,pdl)
     If you have cached the value of a piddle `$a()' into a c-variable
     (foo say), then to check whether it is bad, use `$ISBADVAR(foo,a)'.

$ISGOODVAR(c_var,pdl)
     As above, but this time checking that the cached value isn't bad.

$SETBADVAR(c_var,pdl)
     To copy the bad value for a piddle into a c variable, use
     `$SETBADVAR(foo,a)'.

   *TODO:* mention `$PPISBAD()' etc macros.

   Using these macros, the above code could be specified as:

     Code => '$c() = $a() + $b();',
     BadCode => '
        if ( $ISBAD(a()) || $ISBAD(b()) ) {
           $SETBAD(c());
        } else {
           $c() = $a() + $b();
        }',

   Since this is perl, TMTOWTDI, so you could also write:

     BadCode => '
        if ( $ISGOOD(a()) && $ISGOOD(b()) ) {
           $c() = $a() + $b();
        } else {
           $SETBAD(c());
        }',

   If you want access to the value of the badflag for a given piddle, you
can use the `$PDLSTATExxxx()' macros:

$PDLSTATEISBAD(pdl)
$PDLSTATEISGOOD(pdl)
$PDLSTATESETBAD(pdl)
$PDLSTATESETGOOD(pdl)
   *TODO:* mention the FindBadStatusCode and CopyBadStatusCode options to
`pp_def', as well as the BadDoc key.

Interfacing your own/library functions using PP
-----------------------------------------------

   Now, consider the following: you have your own C function (that may in
fact be part of some library you want to interface to PDL) which takes as
arguments two pointers to vectors of double:

     void myfunc(int n,double *v1,double *v2);

   The correct way of defining the PDL function is

     pp_def('myfunc',
     	Pars => 'a(n); [o]b(n);',
     	GenericTypes => [D],
     	Code => 'myfunc($SIZE(n),$P(a),$P(b));'
     );

   The `$P('par) syntax returns a pointer to the first element and the
other elements are guaranteed to lie after that.

   Notice that here it is possible to make many mistakes. First, $SIZE(n)
must be used instead of n. Second, you shouldn't put any loops in this
code. Third, here we encounter a new hash key recognised by PDL::PP : the
GenericTypes declaration tells PDL::PP to ONLY GENERATE THE TYPELOOP FOP
THE LIST OF TYPES SPECIFIED. In this case double. This has two advantages.
Firstly the size of the compiled code is reduced vastly, secondly if
non-double arguments are passed to `myfunc()' PDL will automatically
convert them to double before passing to the external C routine and
convert them back afterwards.

   One can also use Pars to qualify the types of individual arguments.
Thus one could also write this as:

     pp_def('myfunc',
     	Pars => 'double a(n); double [o]b(n);',
     	Code => 'myfunc($SIZE(n),$P(a),$P(b));'
     );

   The type specification in Pars exempts the argument from variation in
the typeloop - rather it is automatically converted too and from the type
specified. This is obviously useful in a more general example, e.g.:

     void myfunc(int n,float *v1,long *v2);

     pp_def('myfunc',
     	Pars => 'float a(n); long [o]b(n);',
     	GenericTypes => [F],
     	Code => 'myfunc($SIZE(n),$P(a),$P(b));'
     );

   Note we still use GenericTypes to reduce the size of the type loop,
obviously PP could in principle spot this and do it automatically though
the code has yet to attain that level of sophistication!

   Finally note when types are converted automatically one MUST use the
`[o]' qualifier for output variables or you hard one changes will get
optimised away by PP!

   If you interface a large library you can automate the interfacing even
further. Perl can help you again(!) in doing this. In many libraries you
have certain calling conventions. This can be exploited. In short, you can
write a little parser (which is really not difficult in perl) that then
generates the calls to `pp_def' from parsed descriptions of the functions
in that library. For an example, please check the *Slatec* interface in
the `Lib' tree of the PDL distribution. If you want to check (during
debugging) which calls to PP functions your perl code generated a little
helper package comes in handy which replaces the PP functions by
identically named ones that dump their arguments to stdout.

   Just say

     perl -MPDL::PP::Dump myfile.pd

   to see the calls to `pp_def' and friends. Try it with `ops.pd' and
`slatec.pd'. If you're interested (or want to enhance it), the source is
in Basic/Gen/PP/Dump.pm

Other macros and functions in the Code section
----------------------------------------------

   Macros: So far we have encountered the `$SIZE', `$GENERIC' and `$P'
macros.  Now we are going to quickly explain the other macros that are
expanded in the Code section of PDL::PP along with examples of their usage.

`$T'
     The `$T' macro is used for type switches. This is very useful when
     you have to use different external (e.g. library) functions depending
     on the input type of arguments. The general syntax is

          $Ttypeletters(type_alternatives)

     where `typeletters' is a permutation of a subset of the letters
     `BSULFD' which stand for Byte, Short, Ushort, etc. and
     `type_alternatives' are the expansions when the type of the PP
     operation is equal to that indicated by the respective letter. Let's
     illustrate this incomprehensible description by an example. Assuming
     you have two C functions with prototypes

          void float_func(float *in, float *out);
          void double_func(double *in, double *out);

     which do basically the same thing but one accepts float and the other
     double pointers. You could interface them to PDL by defining a generic
     function `foofunc' (which will call the correct function depending on
     the type of the transformation):

          pp_def('foofunc',
          	Pars => ' a(n); [o] b();',
          	Code => ' $TFD(float_func,double_func) ($P(a),$P(b));'
          	GenericTypes => [F,D],
          );

     Please note that you can't say

          Code => ' $TFD(float,double)_func ($P(a),$P(b));'

     since the `$T' macro expands with trailing spaces, analogously to C
     preprocessor macros.  The slightly longer form illustrated above is
     correct.  If you really want brevity, you can of course do

          '$TBSULFD('.(join ',',map {"long_identifier_name_$_"}
          	qw/byt short unseigned lounge flotte dubble/).');'

`$PP'
     The `$PP' macro is used for a so called *physical pointer access*. The
     *physical* refers to some internal optimisations of PDL (for those who
     are familiar with the PDL core we are talking about the vaffine
     optimisations). This macro is mainly for internal use and you
     shouldn't need to use it in any of your normal code.

`$COMP' (and the OtherPars section)
     The `$COMP' macro is used to access non-pdl values in the code
     section. Its name is derived from the implementation of
     transformations in PDL. The variables you can refer to using `$COMP'
     are members of the "compiled" structure that represents the PDL
     transformation in question but does not yet contain any information
     about dimensions (for further details check PDL/Internals).
     However, you can treat `$COMP' just as a black box
     without knowing anything about the implementation of transformations
     in PDL. So when would you use this macro? Its main usage is to access
     values of arguments that are declared in the OtherPars section of a
     `pp_def' definition. But then you haven't heard about the OtherPars
     key yet?!  Let's have another example that illustrates typical usage
     of both new features:

          pp_def('pnmout',
          	Pars => 'a(m)',
          	OtherPars => "char* fd",
          	GenericTypes => [B,U,S,L],
          	Code => 'PerlIO *fp;
          		 IO *io;

          io = GvIO(gv_fetchpv($COMP(fd),FALSE,SVt_PVIO));
          		 if (!io || !(fp = IoIFP(io)))
          			croak("Can\'t figure out FP");

          if (PerlIO_write(fp,$P(a),len) != len)
          				croak("Error writing pnm file");
            ');

     This function is used to write data from a pdl to a file. The file
     descriptor is passed as a string into this function. This parameter
     does not go into the Pars section since it cannot be usefully treated
     like a pdl but rather into the aptly named OtherPars section.
     Parameters in the OtherPars section follow those in the Pars section
     when invoking the function, i.e.

          open FILE,">out.dat" or die "couldn't open out.dat";
          pnmout($pdl,'FILE');

     When you want to access this parameter inside the code section you
     have to tell PP by using the `$COMP' macro, i.e. you write
     `$COMP(fd)' as in the example. Otherwise PP wouldn't know that the fd
     you are referring to is the same as that specified in the OtherPars
     section.

     Another use for the OtherPars section is to set a named dimension in
     the signature. Let's have an example how that is done:

          pp_def('setdim',
          	Pars => '[o] a(n)',
          	OtherPars => 'int ns => n',
          	Code => 'loop(n) %{ $a() = n; %}',
          );

     This says that the named dimension n will be initialised from the
     value of the *other parameter* `ns' which is of integer type (I guess
     you have realised that we use the `CType From => named_dim' syntax).
     Now you can call this function in the usual way:

          setdim(($a=null),5);
          print $a;
            [ 0 1 2 3 4 ]

     Admittedly this function is not very useful but it demonstrates how it
     works. If you call the function with an existing pdl and you don't
     need to explicitly specify the size of n since PDL::PP can figure it
     out from the dimensions of the non-null pdl. In that case you just
     give the dimension parameter as `-1':

          $a = hist($b);
          setdim($a,-1);

     That should do it.

   The only PP function that we have used in the examples so far is loop.
Additionally, there are currently two other functions which are recognised
in the Code section:

threadloop
     As we heard above the signature of a PP defined function defines the
     dimensions of all the pdl arguments involved in a *primitive*
     operation.  However, you often call the functions that you defined
     with PP with pdls that have more dimensions than those specified in
     the signature. In this case the primitive operation is performed on
     all subslices of appropriate dimensionality in what is called a
     threadloop (see also overview above and PDL/Indexing).
     Assuming you have some notion of this concept you
     will probably appreciate that the operation specified in the code
     section should be optimised since this is the tightest loop inside a
     threadloop.  However, if you revisit the example where we define the
     pnmout function, you will quickly realise that looking up the IO file
     descriptor in the inner threadloop is not very efficient when writing
     a pdl with many rows. A better approach would be to look up the IO
     descriptor once outside the threadloop and use its value then inside
     the tightest threadloop. This is exactly where the threadloop
     function comes in handy. Here is an improved definition of pnmout
     which uses this function:

          pp_def('pnmout',
          	Pars => 'a(m)',
          	OtherPars => "char* fd",
          	GenericTypes => [B,U,S,L],
          	Code => 'PerlIO *fp;
          		 IO *io;
          		 int len;

          io = GvIO(gv_fetchpv($COMP(fd),FALSE,SVt_PVIO));
          		 if (!io || !(fp = IoIFP(io)))
          			croak("Can\'t figure out FP");

          len = $SIZE(m) * sizeof($GENERIC());

          threadloop %{
             if (PerlIO_write(fp,$P(a),len) != len)
          				croak("Error writing pnm file");
          %}
            ');

     This works as follows. Normally the C code you write inside the Code
     section is placed inside a threadloop (i.e., PP generates the
     appropriate wrapping XS code around it). However, when you explicitly
     use the threadloop function, PDL::PP recognises this and doesn't wrap
     your code with an additional threadloop. This has the effect that
     code you write outside the threadloop is only executed once per
     transformation and just the code with in the surrounding `%{ ... %}'
     pair is placed within the tightest threadloop. This also comes in
     handy when you want to perform a decision (or any other code,
     especially CPU intensive code) only once per thread, i.e.

          pp_addhdr('
            #define RAW 0
            #define ASCII 1
          ');
          pp_def('do_raworascii',
          	 Pars => 'a(); b(); [o]c()',
          	 OtherPars => 'int mode',
               Code => ' switch ($COMP(mode)) {
          		    case RAW:
          			threadloop %{
                                    /* do raw stuff */
                                %}
          		        break;
          		    case ASCII:
          			threadloop %{
                                    /* do ASCII stuff */
                                %}
          		        break;
          		    default:
          			croak("unknown mode");
          		   }'
           );

types
     The types function works similar to the `$T' macro. However, with the
     types function the code in the following block (delimited by `%{' and
     `%}' as usual) is executed for all those cases in which the datatype
     of the operation is *any of* the types represented by the letters in
     the argument to type, e.g.

          Code => '...

          types(BSUL) %{
          		 /* do integer type operation */
                       %}
          types(FD) %{
          		 /* do floating point operation */
          %}
                       ...'

Other useful PP keys in data operation definitions
--------------------------------------------------

   You have already heard about the OtherPars key. Currently, there are not
many other keys for a data operation that will be useful in normal
(whatever that is) PP programming. In fact, it would be interesting to
hear about a case where you think you need more than what is provided at
the moment.  Please speak up on one of the PDL mailing lists. Most other
keys recognised by `pp_def' are only really useful for what we call *slice
operations* (see also above).

   One thing that is strongly being planned is variable number of
arguments, which will be a little tricky.

   An incomplete list of the available keys:

Inplace
     Setting this key marks the routine as working inplace - ie the input
     and output piddles are the same. An example is `$a->inplace->sqrt()'
     (or `sqrt(inplace($a))').

    Inplace => 1
          Use when the routine is a unary function, such as sqrt.

    Inplace => ['a']
          If there are more than one input piddles, specify the name of
          the one that can be changed inplace using an array reference.

    Inplace => ['a','b']
          If there are more than one output piddle, specify the name of
          the input piddle and output piddle in a 2-element array
          reference. This probably isn't needed, but left in for
          completeness.

     If bad values are being used, care must be taken to ensure the
     propogation of the badflag when inplace is being used; consider this
     excerpt from `Basic/Bad/bad.pd':

          pp_def('replacebad',HandleBad => 1,
            Pars => 'a(); [o]b();',
            OtherPars => 'double newval',
            Inplace => 1,
            CopyBadStatusCode =>
            '/* propogate badflag if inplace AND it has changed */
             if ( a == b && $ISPDLSTATEBAD(a) )
               PDL->propogate_badflag( b, 0 );

          /* always make sure the output is "good" */
          $SETPDLSTATEGOOD(b);
              ',
              ...

     Since this routine removes all bad values, then the output piddle had
     its bad flag cleared. If run inplace (so `a == b'), then we have to
     tell all the children of a that the bad flag has been cleared (to
     save time we make sure that we call `PDL->propogate_badgflag' only if
     the input piddle had its bad flag set).

     NOTE: one idea is that the documentation for the routine could be
     automatically flagged to indicate that it can be executed inplace, ie
     something similar to how HandleBad sets BadDoc if it's not supplied
     (it's not an ideal solution).

Other PDL::PP functions to support concise package definition
-------------------------------------------------------------

   So far, we have described the `pp_def' and `pp_done' functions. PDL::PP
exports a few other functions to aid you in writing concise PDL extension
package definitions.

pp_addhdr
.........

   Often when you interface library functions as in the above example you
have to include additional C include files. Since the XS file is generated
by PP we need some means to make PP insert the appropriate include
directives in the right place into the generated XS file.  To this end
there is the pp_addhdr function. This is also the function to use when you
want to define some C functions for internal use by some of the XS
functions (which are mostly functions defined by `pp_def').  By including
these functions here you make sure that PDL::PP inserts your code before
the point where the actual XS module section begins and will therefore be
left untouched by xsubpp (cf. *perlxs* and *perlxstut* manpages).

   A typical call would be

     pp_addhdr('
     #include <unistd.h>       /* we need defs of XXXX */
     #include "libprotos.h"    /* prototypes of library functions */
     #include "mylocaldecs.h"  /* Local decs */

     static void do_the real_work(PDL_Byte * in, PDL_Byte * out, int n)
     {
     	/* do some calculations with the data */
     }
     ');

   This ensures that all the constants and prototypes you need will be
properly included and that you can use the internal functions defined here
in the `pp_def's, e.g.:

     pp_def('barfoo',
     	 Pars => ' a(n); [o] b(n)',
     	 GenericTypes => '[B]',
     	 Code => ' int ns = $SIZE(n);
     		   do_the_real_work($P(a),$P(b),ns);
                    ',
     );

pp_addpm
........

   In many cases the actual PP code (meaning the arguments to `pp_def'
calls) is only part of the package you are currently implementing. Often
there is additional perl code and XS code you would normally have written
into the pm and XS files which are now automatically generated by PP. So
how to get this stuff into those dynamically generated files? Fortunately,
there are a couple of functions, generally called `pp_addXXX' that assist
you in doing this.

   Let's assume you have additional perl code that should go into the
generated pm-file. This is easily achieved with the pp_addpm command:

     pp_addpm(<<'EOD');

     =head1 NAME

     PDL::Lib::Mylib -- a PDL interface to the Mylib library

     =head1 DESCRIPTION

     This package implements an interface to the Mylib package with full
     threading and indexing support (see L<PDL::Indexing>).

     =cut

     use PGPLOT;

     =head2 use_myfunc
     	this function applies the myfunc operation to all the
     	elements of the input pdl regardless of dimensions
     	and returns the sum of the result
     =cut

     sub use_myfunc {
     	my $pdl = shift;

     myfunc($pdl->clump(-1),($res=null));

     return $res->sum;
        }

     EOD

pp_add_exported
...............

   You have probably got the idea. In some cases you also want to export
your additional functions. To avoid getting into trouble with PP which
also messes around with the `@EXPORT' array you just tell PP to add your
functions to the list of exported functions:

     pp_add_exported('', 'use_myfunc gethynx');

   Note the initial empty string argument (reason for it?).

pp_add_isa
..........

   The pp_add_isa command works like the the pp_add_exported function.
The arguments to pp_add_isa are added the @ISA list, e.g.

     pp_add_isa(' Some::Other::Class ');

pp_addxs
........

   Sometimes you want to add extra XS code of your own (that is generally
not involved with any threading/indexing issues but supplies some other
functionality you want to access from the perl side) to the generated XS
file, for example

     pp_addxs('','

     # Determine endianness of machine

     int
     isbigendian()
        CODE:
          unsigned short i;
          PDL_Byte *b;

     i = 42; b = (PDL_Byte*) (void*) &i;

     if (*b == 42)
        RETVAL = 0;
     else if (*(b+1) == 42)
        RETVAL = 1;
     else
        croak("Impossible - machine is neither big nor little endian!!\n");
     OUTPUT:
       RETVAL
       ');

   Especially pp_add_exported and pp_addxs should be used with care. PP
uses PDL::Exporter, hence letting PP export your function means that they
get added to the standard list of function exported by default (the list
defined by the export tag ":Func"). If you use pp_addxs you shouldn't try
to do anything that involves threading or indexing directly. PP is much
better at generating the appropriate code from your definitions.

pp_add_boot
...........

   Finally, you may want to add some code to the BOOT section of the XS
file (if you don't know what that is check *perlxs*). This is easily done
with the pp_add_boot command:

     pp_add_boot(<<EOB);
     	descrip = mylib_initialize(KEEP_OPEN);

     if (descrip == NULL)
        croak("Can't initialize library");

     GlobalStruc->descrip = descrip;
     GlobalStruc->maxfiles = 200;
       EOB

pp_export_nothing
.................

   By default, PP.pm puts all subs defined using the pp_def function into
the output .pm file's EXPORT list. This can create problems if you are
creating a subclassed object where you don't want any methods exported.
(i.e. the methods will only be called using the $object->method syntax).

   For these cases you can call pp_export_nothing() to clear out the
export list. Example (At the end of the .pd file):

     pp_export_nothing();
     pp_done();

pp_core_importList
..................

   By default, PP.pm puts the 'use Core;' line into the output .pm file.
This imports Core's exported names into the current namespace, which can
create problems if you are over-riding one of Core's methods in the
current file.  You end up getting messages like "Warning: sub sumover
redefined in file subclass.pm" when running the program.

   For these cases the pp_core_importList can be used to change what is
imported from Core.pm.  For example:

     pp_core_importList('()')

     This would result in

     use Core();

   being generated in the output .pm file. This would result in no names
being imported from Core.pm. Similarly, calling

     pp_core_importList(' qw/ barf /')

     would result in

     use Core qw/ barf/;

     being generated in the output .pm file. This would result in just 'barf'
     being imported from Core.pm.

Slice operation
===============

   The slice operation section of this manual is provided using dataflow
and lazy evaluation: when you need it, ask Tjl to write it.  a delivery in
a week from when I receive the email is 95% probable and two week delivery
is 99% probable.

   And anyway, the slice operations require a much more intimate knowledge
of PDL internals than the data operations. Furthermore, the complexity of
the issues involved is considerably higher than that in the average data
operation. If you would like to convince yourself of this fact take a look
at the `Basic/Slices/slices.pd' file in the PDL distribution :-).
Nevertheless, functions generated using the slice operations are at the
heart of the index manipulation and dataflow capabilities of PDL.

   Also, there are a lot of dirty issues with virtual piddles and vaffines
which we shall entirely skip here.

Slices and bad values
---------------------

   Slice operations need to be able to handle bad values (if support is
compiled into PDL). The easiest thing to do is look at
`Basic/Slices/slices.pd' to see how this works.

   Along with BadCode, there are also the `BadBackCode' and
`BadRedoDimsCode' keys for `pp_def'. However, any `EquivCPOffsCode' should
not need changing, since any changes are absorbed into the definition of
the `$EQUIVCPOFFS()' macro (ie it is handled automatically by PDL::PP>.

USEFUL ROUTINES
===============

   The PDL Core structure, defined in `Basic/Core/pdlcore.h.PL', contains
pointers to a number of routines that may be useful to you.  The majority
of these routines deal with manipulating piddles, but some are more
general:

PDL->qsort_B( PDL_Byte *xx, int a, int b )
     Sort the array `xx' between the indices a and b.  There are also
     versions for the other PDL datatypes, with postfix `_S', `_U', `_L',
     `_F', and `_D'.  Any module using this must ensure that `PDL::Ufunc'
     is loaded.

PDL->qsort_ind_B( PDL_Byte *xx, int *ix, int a, int b )
     As for `PDL->qsort_B', but this time sorting the indices rather than
     the data.

   The routine med2d in `Lib/Image2D/image2d.pd' shows how such routines
are used.

MAKEFILES FOR PP FILES
======================

   If you are going to generate a package from your PP file (typical file
extensions are `.pd' or `.pp' for the files containing PP code) it is
easiest and safest to leave generation of the appropriate commands to the
Makefile. In the following we will outline the typical format of a perl
Makefile to automatically build and install your package from a
description in a PP file. Most of the rules to build the xs, pm and other
required files from the PP file are already predefined in the
PDL::Core::Dev package. We just have to tell MakeMaker to use it.

   In most cases you can define your Makefile like

     # Makefile.PL for a package defined by PP code.

     use PDL::Core::Dev;            # Pick up development utilities
     use ExtUtils::MakeMaker;

     $package = ["mylib.pd",Mylib,PDL::Lib::Mylib];
     %hash = pdlpp_stdargs($package);
     $hash{OBJECT} .= ' additional_Ccode$(OBJ_EXT) ';
     $hash{clean}->{FILES} .= ' todelete_Ccode$(OBJ_EXT) ';
     $hash{'VERSION_FROM'} = 'mylib.pd';
     WriteMakefile(%hash);

     sub MY::postamble { pdlpp_postamble($package); }

   Here, the list in $package is: first: PP source file name, then the
prefix for the produced files and finally the whole package name.  You can
modify the hash in whatever way you like but it would be reasonable to
stay within some limits so that your package will continue to work with
later versions of PDL.

   If you don't want to use prepackaged arguments, here is a generic
Makefile.PL that you can adapt for your own needs:

     # Makefile.PL for a package defined by PP code.

     use PDL::Core::Dev;            # Pick up development utilities
     use ExtUtils::MakeMaker;

     WriteMakefile(
      'NAME'  	=> 'PDL::Lib::Mylib',
      'VERSION_FROM'	=> 'mylib.pd',
      'TYPEMAPS'     => [&PDL_TYPEMAP()],
      'OBJECT'       => 'mylib$(OBJ_EXT) additional_Ccode$(OBJ_EXT)',
      'PM'		=> { 'Mylib.pm'            => '$(INST_LIBDIR)/Mylib.pm'},
      'INC'          => &PDL_INCLUDE(), # add include dirs as required by your lib
      'LIBS'         => [''],   # add link directives as necessary
      'clean'        => {'FILES'  =>
     			  'Mylib.pm Mylib.xs Mylib$(OBJ_EXT)
     			  additional_Ccode$(OBJ_EXT)'},
     );

     # Add genpp rule; this will invoke PDL::PP on our PP file
     # the argument is an array reference where the array has three string elements:
     #   arg1: name of the source file that contains the PP code
     #   arg2: basename of the xs and pm files to be generated
     #   arg3: name of the package that is to be generated
     sub MY::postamble { pdlpp_postamble(["mylib.pd",Mylib,PDL::Lib::Mylib]); }

   To make life even easier PDL::Core::Dev defines the function
`pdlpp_stdargs' that returns a hash with default values that can be passed
(either directly or after appropriate modification) to a call to
WriteMakefile.  Currently, `pdlpp_stdargs' returns a hash where the keys
are filled in as follows:

     (
      'NAME'  	=> $mod,
      'TYPEMAPS'     => [&PDL_TYPEMAP()],
      'OBJECT'       => "$pref\$(OBJ_EXT)",
      PM 	=> {"$pref.pm" => "\$(INST_LIBDIR)/$pref.pm"},
      MAN3PODS => {"$src" => "\$(INST_MAN3DIR)/$mod.\$(MAN3EXT)"},
      'INC'          => &PDL_INCLUDE(),
      'LIBS'         => [''],
      'clean'        => {'FILES'  => "$pref.xs $pref.pm $pref\$(OBJ_EXT)"},
     )

   Here, $src is the name of the source file with PP code, `$pref' the
prefix for the generated .pm and .xs files and `$mod' the name of the
exntension module to generate.

INTERNALS
=========

   The internals of the current version consist of a large table which
gives the rules according to which things are translated and the subs
which implement these rules.

   Later on, it would be good to make the table modifiable by the user so
that different things may be tried.

   [Meta comment: here will hopefully be more in the future; currently,
your best bet will be to read the source code :-( or ask on the list (try
the latter first) ]

Appendix A: Some keys recognised by PDL::PP
===========================================

   Unless otherwise specified, the arguments are strings. Keys marked with
(bad) are only used if bad-value support is compiled into PDL.

Pars
     define the signature of your function

OtherPars
     arguments which are not pdls. Default: nothing.

Code
     the actual code that implements the functionality; several PP macros
     and PP functions are recognised in the string value

HandleBad (bad)
     If set to 1, the routine is assumed to support bad values and the
     code in the BadCode key is used if bad values are present; it also
     sets things up so that the `$ISBAD()' etc macros can be used.  If set
     to 0, cause the routine to print a warning if any of the input piddles
     have their bad flag set.

BadCode (bad)
     Give the code to be used if bad values may be present in the input
     piddles.  Only used if `HandleBad => 1'.

GenericTypes
     An array reference. The array may contain any subset of the strings
     `B', `S', `U', `L', `F' and `D', which specify which types your
     operation will accept.  This is very useful (and important!) when
     interfacing an external library.  Default: [qw/B S U L F D/]

Inplace
     Mark a function as being able to work inplace.

          Inplace => 1          if  Pars => 'a(); [o]b();'
          Inplace => ['a']      if  Pars => 'a(); b(); [o]c();'
          Inplace => ['a','b']  if  Pars => 'a(); b(); [o]c(); [o]d();'

     If bad values are being used, care must be taken to ensure the
     propogation of the badflag when inplace is being used; for instance
     see the code for `replacebad' in `Basic/Bad/bad.pd'.

Doc
     Used to specify a documentation string in Pod format. See PDL::Doc
     for information on PDL documentation conventions. Note: in the
     special case where the PP 'Doc' string is one line this is implicitly
     used for the quick reference AND the documentation!

     If the Doc field is omitted PP will generate default documentation
     (after all it knows about the Signature).

     If you really want the function NOT to be documented in any way at
     this point (e.g. for an internal routine, or because youu are doing
     it elsewhere in the code) explictly specify `Doc=>undef'.

BadDoc (bad)
     Contains the text returned by the badinfo command (in `perldl') or
     the -b switch to the `pdldoc' shell script. In many cases, you will
     not need to specify this, since the information can be automatically
     created by PDL::PP. However, as befits computer-generated text, it's
     rather stilted; it may be much better to do it yourself!

Appendix B: PP macros and functions
===================================

Macros
------

   Macros labelled by (bad) are only used if bad-value support is compiled
into PDL.

$*variablename_from_sig*()
     access a pdl (by its name) that was specified in the signature

$COMP(x)
     access a value in the private data structure of this transformation
     (mainly used to use an argument that is specified in the `OtherPar'
     section)

$SIZE(n)
     replaced at runtime by the actual size of a *named* dimension (as
     specified in the signature)

$GENERIC()
     replaced by the C type that is equal to the runtime type of the
     operation

$P(a)
     a pointer access to the PDL named a in the signature. Useful for
     interfacing to C functions

$PP(a)
     a physical pointer access to pdl a; mainly for internal use

$TXXX(Alternative,Alternative)
     expansion alternatives according to runtime type of operation, where
     XXX is some string that is matched by `/[BSULFD+]/'.

$PDL(a)
     return a pointer to the pdl data structure (pdl *) of piddle a

$ISBAD(a()) (bad)
     returns true if the value stored in `a()' equals the bad value for
     this piddle.  Requires HandleBad being set to 1.

$ISGOOD(a()) (bad)
     returns true if the value stored in `a()' does not equal the bad value
     for this piddle.  Requires HandleBad being set to 1.

$SETBAD(a()) (bad)
     Sets `a()' to equal the bad value for this piddle.  Requires
     HandleBad being set to 1.

functions
---------

`loop(DIMS) %{ ... %}'
     loop over named dimensions; limits are generated automatically by PP

`threadloop %{ ... %}'
     enclose following code in a threadloop

`types(TYPES) %{ ... %}'
     execute following code if type of operation is any of `TYPES'

SEE ALSO
========

   *PDL*

   For the concepts of threading and slicing check PDL/Indexing.

   See PDL/Internals,

   See PDL/BadValues, for information on bad values

   *perlxs*, *perlxstut*

CURRENTLY UNDOCUMENTED
======================

   RedoDimsCode, $RESIZE()

BUGS
====

   PDL::PP is still, even in its rewritten form, too complicated.  It
needs to be rethought a little as well as deconvoluted and modularized
some more (e.g. all the NS things).

   After the rewrite, this can happen a little by little, though.

Undocumented functions
----------------------

   The following functions have been added since this manual was written
and are as yet undocumented

pp_export_nothing
pp_core_importList
pp_beginwrap
pp_setversion
pp_addbegin
AUTHOR
======

   Copyright(C) 1997 Tuomas J. Lukka (lukka@fas.harvard.edu), Karl
Glaazebrook (kgb@aaocbn1.aao.GOV.AU) and Christian Soeller
(c.soeller@auckland.ac.nz). All rights reserved. Although destined for
release as a man page with the standard PDL distribution, it is not public
domain. Permission is granted to freely distribute verbatim copies of this
document provided that no modifications outside of formatting be made, and
that this notice remain intact.  You are permitted and encouraged to use
its code and derivatives thereof in your own source code for fun or for
profit as you see fit.

dump pp_xxx calls to stdout
***************************

NAME
====

   PDL::PP::Dump - dump pp_xxx calls to stdout

SYNOPSIS
========

     perl -MPDL::PP::Dump Basic/Ops/ops.pd

DESCRIPTION
===========

   The most basic PP script debugger thinkable.

AUTHOR
======

   Christian Soeller <c.soeller@auckland.ac.nz> .

Internal module to handle signatures
************************************

NAME
====

   PDL::PP::Signature - Internal module to handle signatures

DESCRIPTION
===========

   Internal module to handle signatures

SYNOPSIS
========

     use PDL::PP::Signature;

AUTHOR
======

   Copyright (C) Tuomas J. Lukka 1997 (lukka@husc.harvard.edu) and by
Christian Soeller (c.soeller@auckland.ac.nz).  All rights reserved. There
is no warranty. You are allowed to redistribute this software /
documentation under certain conditions. For details, see the file COPYING
in the PDL distribution. If this file is separated from the PDL
distribution, the copyright notice should be included in the file.

what's behind PDL?
******************

NAME
====

   PDL::Philosophy - what's behind PDL?

DESCRIPTION
===========

   This is an attempt to summarize some of the common spirit between pdl
developers in order to answer the question "Why PDL"? If you are a PDL
developer and I haven't caught your favorite ideas about PDL, please let
me know!

   An often-asked question is: Why not settle for some of the existing
systems like Matlab or IDL or GnuPlot or whatever?

Major ideas
-----------

   The first tenet of our philosophy is the "free software" idea: software
being free has several advantages (less bugs because more people see the
code, you can have the source and port it to your own working environment
with you, ... and of course, that you don't need to pay anything).

   The second idea is a pet peeve of many: many languages like matlab are
pretty well suited for their specific tasks but for a different
application, you need to change to an entirely different tool and regear
yourself mentally. Not to speak about doing an application that does two
things at once...  Because we use Perl, we have the power and ease of perl
syntax, regular expressions, hash tables etc at our fingertips at all
times.  By extending an existing language, we start from a much healthier
base than languages like matlab which have grown into existence from a
very small functionality at first and expanded little by little, making
things look badly planned. We stand by the Perl sayings: "simple things
should be simple but complicated things should be possible" and "There is
more than one way to do it" (TIMTOWTDI).

   The third idea is interoperability: we want to be able to use PDL to
drive as many tools as possible, we can connect to OpenGL or Mesa for
graphics or whatever. There isn't anything out there that's really
satisfactory as a tool and can do everything we want easily. And be
portable.

   The fourth idea is related to PDL::PP and is Tuomas's personal
favorite: code should only specify as little as possible redundant info.
If you find yourself writing very similar-looking code much of the time,
all that code could probably be generated by a simple perl script. The PDL
C preprocessor takes this to an extreme.

Minor goals and purposes
------------------------

   We want speed. Optimally, it should ultimately (e.g. with the Perl
compiler) be possible to compile PDL::PP subs to C and obtain the top
vectorized speeds on supercomputers. Also, we want to be able to calculate
things at near top speed from inside perl, by using dataflow to avoid
memory allocation and deallocation (the overhead should ultimately be only
a little over one indirect function call plus couple of ifs per function
in the pipe).

   We want handy syntax. Want to do something and cannot do it easily?
Tell us about it...

   We want lots of goodies. A good mathematical library etc.

AUTHOR
======

   Copyright(C) 1997 Tuomas J. Lukka (lukka@fas.harvard.edu).
Redistribution in the same form is allowed but reprinting requires a
permission from the author.

module to convert pod files to HTML
***********************************

NAME
====

   PDL::Pod::Html - module to convert pod files to HTML

SYNOPSIS
========

     use PDL::Pod::Html;
     pod2html([options]);

DESCRIPTION
===========

   Converts files from pod format (see Perlpod (perl.info))
to HTML format.  It can automatically generate indexes and
cross-references, and it keeps a cache of things it knows how to
cross-reference.

ARGUMENTS
=========

   PDL::Pod::Html takes the following arguments:

help
          --help

     Displays the usage message.

htmlroot
          --htmlroot=name

     Sets the base URL for the HTML files.  When cross-references are made,
     the HTML root is prepended to the URL.

infile
          --infile=name

     Specify the pod file to convert.  Input is taken from STDIN if no
     infile is specified.

outfile
          --outfile=name

     Specify the HTML file to create.  Output goes to STDOUT if no outfile
     is specified.

podroot
          --podroot=name

     Specify the base directory for finding library pods.

podpath
          --podpath=name:...:name

     Specify which subdirectories of the podroot contain pod files whose
     HTML converted forms can be linked-to in cross-references.

libpods
          --libpods=name:...:name

     List of page names (eg, "perlfunc") which contain linkable =items.

netscape
          --netscape

     Use Netscape HTML directives when applicable.

nonetscape
          --nonetscape

     Do not use Netscape HTML directives (default).

index
          --index

     Generate an index at the top of the HTML file (default behaviour).

noindex
          --noindex

     Do not generate an index at the top of the HTML file.

recurse
          --recurse

     Recurse into subdirectories specified in podpath (default behaviour).

norecurse
          --norecurse

     Do not recurse into subdirectories specified in podpath.

title
          --title=title

     Specify the title of the resulting HTML file.

verbose
          --verbose

     Display progress messages.

EXAMPLE
=======

     pod2html("pod2html",
     	     "--podpath=lib:ext:pod:vms",
     	     "--podroot=/usr/src/perl",
     	     "--htmlroot=/perl/nmanual",
     	     "--libpods=perlfunc:perlguts:perlvar:perlrun:perlop",
     	     "--recurse",
     	     "--infile=foo.pod",
     	     "--outfile=/perl/nmanual/foo.html");

AUTHOR
======

   Tom Christiansen, <tchrist@perl.com>.

BUGS
====

   Has trouble with  etc in = commands.

SEE ALSO
========

   See Perlpod (perl.info),

COPYRIGHT
=========

   This program is distributed under the Artistic License.

base class for creating pod filters and translators
***************************************************

NAME
====

   PDL::Pod::Parser - base class for creating pod filters and translators

SYNOPSIS
========

     use PDL::Pod::Parser;
     package PDL::MyParser;
     @ISA = qw(PDL::Pod::Parser);

     sub new {
         ## constructor code ...
     }

     ## implementation of appropriate subclass methods ...

     package main;
     $parser = new PDL::MyParser;
     @ARGV = ('-')  unless (@ARGV > 0);
     for (@ARGV) {
         $parser->parse_from_file($_);
     }

DESCRIPTION
===========

   *PDL::Pod::Parser* is an abstract base class for implementing filters
and/or translators to parse pod documentation into other formats. It
handles most of the difficulty of parsing the pod sections in a file and
leaves it to the subclasses to override various methods to provide the
actual translation. The other thing that *PDL::Pod::Parser* provides is
the ability to process only selected sections of pod documentation from
the input.

SECTION SPECIFICATIONS
----------------------

   Certain methods and functions provided by *PDL::Pod::Parser* may be
given one or more "section specifications" to restrict the text processed
to only the desired set of sections and their corresponding subsections.  A
section specification is a string containing one or more Perl-style
regular expressions separated by forward slashes ("/").  If you need to
use a forward slash literally within a section title you can escape it
with a backslash ("\/").

   The formal syntax of a section specification is:

*head1-title-regexp*/*head2-title-regexp*/...
   Any omitted or empty regular expressions will default to ".*".  Please
note that each regular expression given is implicitly anchored by adding
"^" and "$" to the beginning and end.  Also, if a given regular expression
starts with a "!" character, then the expression is negated (so `!foo'
would match anything except foo).

   Some example section specifications follow.

Match the NAME and SYNOPSIS sections and all of their subsections:
     `NAME|SYNOPSIS'

Match only the `Question' and `Answer' subsections of the DESCRIPTION section:
     `DESCRIPTION/Question|Answer'

Match the Comments subsection of all sections:
     `/Comments'

Match all subsections of DESCRIPTION except for Comments:
     `DESCRIPTION/!Comments'

Match the DESCRIPTION section but do not match any of its subsections:
     `DESCRIPTION/!.+'

Match all top level sections but none of their subsections:
     `/!.+'

FUNCTIONS
=========

   *PDL::Pod::Parser* provides the following functions (please note that
these are functions and not methods, they do not take an object reference
as an implicit first parameter):

version()
---------

   Return the current version of this package.

INSTANCE METHODS
================

   *PDL::Pod::Parser* provides several methods, some of which should be
overridden by subclasses.  They are as follows:

new()
-----

   This is the the constructor for the base class. You should only use it
if you want to create an instance of a *PDL::Pod::Parser* instead of one of
its subclasses. The constructor for this class and all of its subclasses
should return a blessed reference to an associative array (hash).

initialize()
------------

   This method performs any necessary base class initialization.  It takes
no arguments (other than the object instance of course).  If subclasses
override this method then they must be sure to invoke the superclass'
initialize() method.

select($section_spec1, $section_spec2, ...)
-------------------------------------------

   This is the method that is used to select the particular sections and
subsections of pod documentation that are to be printed and/or processed.
If the first argument is the string "+", then the remaining section
specifications are added to the current list of selections; otherwise the
given section specifications will replace the current list of selections.

   Each of the `$section_spec' arguments should be a section specification
as described in `"SECTION SPECIFICATIONS"' in this node.  The section
specifications are parsed by this method and the resulting regular
expressions are stored in the array referenced by `$self->{SELECTED}'
(please see the description of this member variable in `"INSTANCE DATA"'
in this node).

   This method should not normally be overridden by subclasses.

want_section($head1_title, $head2_title, ...)
---------------------------------------------

   Returns a value of true if the given section and subsection titles match
any of the section specifications passed to the select() method (or if no
section specifications were given). Returns a value of false otherwise. If
`$headN_title' is ommitted then it defaults to the current `headN' section
title in the input.

   This method should not normally be overridden by subclasses.

begin_input()
-------------

   This method is invoked by parse_from_filehandle() immediately before
processing input from a filehandle. The base class implementation does
nothing but subclasses may override it to perform any per-file
intializations.

end_input()
-----------

   This method is invoked by parse_from_filehandle() immediately after
processing input from a filehandle. The base class implementation does
nothing but subclasses may override it to perform any per-file cleanup
actions.

preprocess_line($text)
----------------------

   This methods should be overridden by subclasses that wish to perform any
kind of preprocessing for each line of input (before it has been
determined whether or not it is part of a pod paragraph). The parameter
$text is the input line and the value returned should correspond to the
new text to use in its place. If the empty string or an undefined value is
returned then no further process will be performed for this line. If
desired, this method can call the parse_paragraph() method directly with
any preprocessed text and return an empty string (to indicate that no
further processing is needed).

   Please note that the preprocess_line() method is invoked before the
preprocess_paragraph() method. After all (possibly preprocessed) lines in
a paragraph have been assembled together and it has been determined that
the paragraph is part of the pod documentation from one of the selected
sections, then preprocess_paragraph() is invoked.

   The base class implementation of this method returns the given text.

preprocess_paragraph($text)
---------------------------

   This method should be overridden by subclasses that wish to perform any
kind of preprocessing for each block (paragraph) of pod documentation that
appears in the input stream.  The parameter $text is the pod paragraph
from the input file and the value returned should correspond to the new
text to use in its place.  If the empty string is returned or an undefined
value is returned, then the given $text is ignored (not processed).

   This method is invoked by parse_paragraph(). After it returns,
parse_paragraph() examines the current cutting state (which is stored in
`$self->{CUTTING}'). If it evaluates to false then input text (including
the given $text) is cut (not processed) until the next pod directive is
encountered.

   Please note that the preprocess_line() method is invoked before the
preprocess_paragraph() method. After all (possibly preprocessed) lines in
a paragraph have been assembled together and it has been determined that
the paragraph is part of the pod documentation from one of the selected
sections, then preprocess_paragraph() is invoked.

   The base class implementation of this method returns the given text.

parse_pragmas($cmd, $text, $sep)
--------------------------------

   This method is called when an =pod directive is encountered. When such
a pod directive is seen in the input, this method is called and is passed
the command name `$cmd' (which should be "pod") and the remainder of the
text paragraph $text which appeared immediately after the command name. If
desired, the text which separated the =pod directive from its
corresponding text may be found in `$sep'.  Each word in $text is examined
to see if it is a pragma specification.  Pragma specifications are of the
form `pragma_name=pragma_value'.

   Unless the given object is an instance of the *PDL::Pod::Parser* class,
the base class implementation of this method will invoke the *pragma()*
method for each pragma specification in $text.  *If and only if* the given
object *is* an instance of the *PDL::Pod::Parser* class, the base class
version of this method will simply reproduce the =pod command exactly as
it appeared in the input.

   Derived classes should not usually need to reimplement this method.

pragma($pragma_name, $pragma_value)
-----------------------------------

   This method is invoked for each pragma encountered inside an =pod
paragraph (see the description of the *parse_pragmas()* method). The
pragma name is passed in `$pragma_name' (which should always be lowercase)
and the corresponding value is `$pragma_value'.

   The base class implementation of this method does nothing.  Derived
class implementations of this method should be able to recognize at least
the following pragmas and take any necessary actions when they are
encountered:

fill=value
     The argument value should be one of `on', `off', or previous.
     Specifies that "filling-mode" should set to 1, 0, or its previous
     value (respectively). If value is omitted then the default is `on'.
     Derived classes may use this to decide whether or not to perform any
     filling (wrapping) of subsequent text.

style=value
     The argument value should be one of bold, italic, code, `plain', or
     previous. Specifies that the current default paragraph font should be
     set to bold, italic, code, the empty string , or its previous value
     (respectively).  If value is omitted then the default is `plain'.
     Derived classes may use this to determine the default font style to
     use for subsequent text.

indent=value
     The argument value should be an integer value (with an optional
     sign).  Specifies that the current indentation level should be reset
     to the given value. If a plus (minus) sign precedes the number then
     the indentation level should be incremented (decremented) by the given
     number. If only a plus or minus sign is given (without a number) then
     the current indentation level is incremented or decremented by some
     default amount (to be determined by subclasses).

   The value returned will be 1 if the pragma name was recognized and 0 if
it wasnt (in which case the pragma was ignored).

   Derived classes should override this method if they wish to implement
any pragmas. The base class implementation of this method does nothing but
it does contain some commented-out code which subclasses may want to make
use of when implementing pragmas.

command($cmd, $text, $sep)
--------------------------

   This method should be overridden by subclasses to take the appropriate
action when a pod command paragraph (denoted by a line beginning with "=")
is encountered.  When such a pod directive is seen in the input, this
method is called and is passed the command name `$cmd' and the remainder
of the text paragraph $text which appears immediately after the command
name. If desired, the text which separated the command from its
corresponding text may be found in `$sep'.  Note that this method is not
called for =pod paragraphs.

   The base class implementation of this method simply prints the raw pod
command to the output filehandle and then invokes the textblock() method,
passing it the $text parameter.

verbatim($text)
---------------

   This method may be overridden by subclasses to take the appropriate
action when a block of verbatim text is encountered. It is passed the text
block $text as a parameter.

   The base class implementation of this method simply prints the textblock
(unmodified) to the output filehandle.

textblock($text)
----------------

   This method may be overridden by subclasses to take the appropriate
action when a normal block of pod text is encountered (although the base
class method will usually do what you want). It is passed the text block
$text as a parameter.

   In order to process interior sequences, subclasses implementations of
this method will probably want invoke the interpolate() method, passing it
the text block $text as a parameter and then perform any desired
processing upon the returned result.

   The base class implementation of this method simply prints the text
block as it occurred in the input stream).

interior_sequence($seq_cmd, $seq_arg)
-------------------------------------

   This method should be overridden by subclasses to take the appropriate
action when an interior sequence is encountered. An interior sequence is
an embedded command within a block of text which appears as a command name
(usually a single uppercase character) followed immediately by a string of
text which is enclosed in angle brackets. This method is passed the
sequence command `$seq_cmd' and the corresponding text $seq_arg and is
invoked by the interpolate() method for each interior sequence that occurs
in the string that it is passed.  It should return the desired text string
to be used in place of the interior sequence.

   Subclass implementationss of this method may wish to examine the the
array referenced by `$self->{SEQUENCES}' which is a stack of all the
interior sequences that are currently being processed (they may be
nested). The current interior sequence (the one given by
`$seq_cmd<$seq_arg>') should always be at the top of this stack.

   The base class implementation of the interior_sequence() method simply
returns the raw text of the of the interior sequence (as it occurred in
the input) to the output filehandle.

interpolate($text, $end_re)
---------------------------

   This method will translate all text (including any embedded interior
sequences) in the given text string $text and return the interpolated
result.  If a second argument is given, then it is taken to be a regular
expression that indicates when to quit interpolating the string.  Upon
return, the $text parameter will have been modified to contain only the
un-processed portion of the given string (which will not contain any text
matched by `$end_re').

   This method should probably not be overridden by subclasses.  It should
be noted that this method invokes itself recursively to handle any nested
interior sequences.

parse_paragraph($text)
----------------------

   This method takes the text of a pod paragraph to be processed and
invokes the appropriate method (one of command(), verbatim(), or
textblock()).

   This method does not usually need to be overridden by subclasses.

parse_from_filehandle($infilehandle, $outfilehandle)
----------------------------------------------------

   This method takes a glob to a filehandle (which is assumed to already be
opened for reading) and reads the entire input stream looking for blocks
(paragraphs) of pod documentation to be processed. For each block of pod
documentation encountered it will call the parse_paragraph() method.

   If a second argument is given then it should be a filehandle glob where
output should be sent (otherwise the default output filehandle is STDOUT).
If no first argument is given the default input filehandle STDIN is used.

   The input filehandle that is currently in use is stored in the member
variable whose key is "INPUT" (e.g. `$self->{INPUT}').

   The output filehandle that is currently in use is stored in the member
variable whose key is "OUTPUT" (e.g. `$self->{OUTPUT}').

   Input is read line-by-line and assembled into paragraphs (which are
separated by lines containing nothing but whitespace). The current line
number is stored in the member variable whose key is "LINE" (e.g.
`$self->{LINE}') and the current paragraph number is stored in the member
variable whose key is "PARAGRAPH" (e.g.  `$self->{PARAGRAPH}').

   This method does not usually need to be overridden by subclasses.

parse_from_file($filename, $outfile)
------------------------------------

   This method takes a filename and does the following:

   * opens the input and output files for reading (creating the
     appropriate filehandles)

   * invokes the parse_from_filehandle() method passing it the
     corresponding input and output filehandles.

   * closes the input and output files.

   If the special input filename "-" or "<&STDIN" is given then the STDIN
filehandle is used for input (and no open or close is performed).  If no
input filename is specified then "-" is implied.  If a reference is passed
instead of a filename then it is assumed to be a glob-style reference to a
filehandle.

   If a second argument is given then it should be the name of the desired
output file.  If the special output filename "-" or ">&STDOUT" is given
then the STDOUT filehandle is used for output (and no open or close is
performed). If the special output filename ">&STDERR" is given then the
STDERR filehandle is used for output (and no open or close is performed).
If no output filename is specified then "-" is implied.  If a reference is
passed instead of a filename then it is assumed to be a glob-style
reference to a filehandle.

   The name of the input file that is currently being read is stored in the
member variable whose key is "INFILE" (e.g. `$self->{INFILE}').

   The name of the output file that is currently being written is stored in
the member variable whose key is "OUTFILE" (e.g.  `$self->{OUTFILE}').

   This method does not usually need to be overridden by subclasses.

INSTANCE DATA
=============

   *PDL::Pod::Parser* uses the following data members for each of its
instances (where `$self' is a reference to such an instance):

$self->{INPUT}
--------------

   The current input filehandle.

$self->{OUTPUT}
---------------

   The current output filehandle.

$self->{INFILE}
---------------

   The name of the current input file.

$self->{OUTFILE}
----------------

   The name of the current output file.

$self->{LINE}
-------------

   The current line number from the input stream.

$self->{PARAGRAPH}
------------------

   The current paragraph number from the input stream (which includes input
paragraphs that are not part of the pod documentation).

$self->{HEADINGS}
-----------------

   A reference to an array of the current section heading titles for each
heading level (note that the first heading level title is at index 0).

$self->{SELECTED}
-----------------

   A reference to an array of references to arrays. Each subarray is a list
of anchored regular expressions (preceded by a "!" if the regexp is to be
negated). The index of the expression in the subarray should correspond to
the index of the heading title in *$self->{HEADINGS}* that it is to be
matched against.

$self->{CUTTING}
----------------

   A boolean-valued scalar which evaluates to true if text from the input
file is currently being "cut".

$self->{SEQUENCES}
------------------

   An array reference to the stack of interior sequence commands that are
currently in the middle of being processed.

NOTES
=====

   To create a pod translator to translate pod documentation to some other
format, you usually only need to create a subclass of *PDL::Pod::Parser*
which overrides the base class implementation for the following methods:

   * *pragma()*

   * command()

   * verbatim()

   * textblock()

   * interior_sequence()

   You may also want to implement the begin_input() and end_input()
methods for your subclass (to perform any needed per-file intialization or
cleanup).

   If you need to perform any preprocesssing of input before it is parsed
you may want to implement one or both of the preprocess_line() and/or
preprocess_paragraph() methods.

   Also, don't forget to make sure your subclass constructor invokes the
base class' initialize() method.

   Sometimes it may be necessary to make more than one pass over the input
files. This isn't a problem as long as none of the input files correspond
to STDIN. You can override either the parse_from_filehandle() method or
the parse_from_file() method to make the first pass yourself to collect
all the information you need and then invoke the base class method to do
the rest of the standard processing.

   Feel free to add any member data fields you need to keep track of things
like current font, indentation, horizontal or vertical position, or
whatever else you like.

   For the most part, the *PDL::Pod::Parser* base class should be able to
do most of the input parsing for you and leave you free to worry about how
to intepret the commands and translate the result.

AUTHOR
======

   Brad Appleton <Brad_Appleton-GBDA001@email.mot.com>

   Based on code for Pod::Text written by Tom Christiansen
<tchrist@mox.perl.com>

function to extract selected sections of pod documentation
**********************************************************

NAME
====

   podselect - function to extract selected sections of pod documentation

SYNOPSIS
========

     use PDL::Pod::Select;
     podselect (@filelist);
     podselect ({OUTPUT => "tmp.out"}, @filelist):
     podselect ({SELECT => ["NAME|SYNOPSIS", "OPTIONS"]}, @filelist):
     podselect ({OUTPUT => ">&STDERR", SELECT => ["DESCRIPTION"]}, "-");

DESCRIPTION
===========

   podselect() is a function which will extract specified sections of pod
documentation from an input stream. This ability is already provided in
the *PDL::Pod::Parser* module. Subclasses of *PDL::Pod::Parser* that wish
to take advantage of this feature do not need to derive from
*PDL::Pod::Select*. *PDL::Pod::Select* merely provides a single function
named podselect() which provides this capability in function form (as
opposed to object form) for extracting the raw pod docs.

podselect(\%options, @filelist)
-------------------------------

   *podselect* will print the raw (untranslated) pod documentation of all
pod sections in the given input files specified by `@filelist' according
to the given options.

   If any argument to *podselect* is a reference to a hash (associative
array) then the values with the following keys are processed as follows:

OUTPUT
     A string corresponding to the desired output file (or ">&STDOUT" or
     ">&STDERR"). The default is to use standard output.

SELECT
     A reference to an array of sections specifications (as described in
     `"SECTION SPECIFICATIONS"', see PDL/Pod/Parser)
     which indicate the desired set of pod sections and subsections to be
     selected from input. If no section specifications are given, then all
     sections of pod documentation are used.

   All other arguments should correspond to the names of input files
containing pod documentation. A file name of "-" or "<&STDIN" will be
interpeted to mean standard input (which is the default if no filenames
are given).

SEE ALSO
========

   See PDL/Pod/Parser,

AUTHOR
======

   Brad Appleton <Brad_Appleton-GBDA001@email.mot.com>

   Based on code for *pod2text* written by Tom Christiansen
<tchrist@mox.perl.com>

print a usage message using a script's embedded pod documentation
*****************************************************************

NAME
====

   pod2usage - print a usage message using a script's embedded pod
documentation

SYNOPSIS
========

     use PDL::Pod::Usage;
     pod2usage();
     pod2usage(2);
     pod2usage({EXIT => 2});
     pod2usage({EXIT => 2, VERBOSE => 0});
     pod2usage(EXIT => 1, VERBOSE => 2, OUTPUT=\*STDERR);
     pod2usage(VERBOSE => 2);

DESCRIPTION
===========

   *pod2usage* will print a usage message for the invoking script (using
its embedded pod documentation) and then exit the script with the
specified exit value. It takes a single argument which is either a numeric
value corresponding to the desired exit status (which defaults to 2), or a
reference to a hash. If more than one argument is given then the entire
argument list is assumed to be a hash. If a hash is supplied it should
contain elements with one or more of the following keys:

`EXIT'
     The desired exit status to pass to the exit() function.

VERBOSE
     The desired level of "verboseness" to use when printing the usage
     message. If the corresponding value is 0, then only the "SYNOPSIS"
     section of the pod documentation is printed. If the corresponding
     value is 1, then the "SYNOPSIS" section, along with any section
     entitled "OPTIONS", "ARGUMENTS", or "OPTIONS AND ARGUMENTS" is
     printed.  If the corresponding value is 2 or more then the entire
     manpage is printed.

OUTPUT
     A reference to a filehandle, or the pathname of a file to which the
     usage message should be written. The default is `\*STDERR' unless the
     exit value is less than 2 (in which case the default is `\*STDOUT').

INPUT
     A reference to a filehandle, or the pathname of a file from which the
     invoking script's pod documentation should be read.  It defaults to
     the file indicated by $0 ($PROGRAM_NAME for `use English;' users).

   If neither the exit value nor the verbose level is specified, then the
default is to use an exit value of 2 with a verbose level of 0.

   If an exit value is specified but the verbose level is not, then the
verbose level will default to 1 if the exit value is less than 2 and will
default to 0 otherwise.

   If a verbose level is specified but an exit value is not, then the exit
value will default to 2 if the verbose level is 0 and will default to 1
otherwise.

EXAMPLE
=======

   Most scripts should print some type of usage message to STDERR when a
command line syntax error is detected. They should also provide an option
(usually -h or `-help') to print a (possibly more verbose) usage message
to STDOUT. Some scripts may even wish to go so far as to provide a means
of printing their complete documentation to STDOUT (perhaps by allowing a
`-man' option). The following example uses *pod2usage* in combination with
Getopt::Long to do all of these things:

     use PDL::Pod::Usage;
     use Getopt::Long;

     GetOptions("help", "man")  ||  pod2usage(2);
     pod2usage(1)  if ($opt_help);
     pod2usage(VERBOSE => 2)  if ($opt_man);

CAVEATS
=======

   By default, *pod2usage()* will use $0 as the path to the pod input
file.  Unfortunately, not all systems on which Perl runs will set $0
properly (although if $0 isn't found, *pod2usage()* will search
`$ENV{PATH}').  If this is the case for your system, you may need to
explicitly specify the path to the pod docs for the invoking script using
something similar to the following:

   * `pod2usage(EXIT => 2, INPUT => "/path/to/your/pod/docs");'

AUTHOR
======

   Brad Appleton <Brad_Appleton-GBDA001@email.mot.com>

   Based on code for *Pod::Text::pod2text()* written by Tom Christiansen
<tchrist@mox.perl.com>

primitive operations for pdl
****************************

NAME
====

   PDL::Primitive - primitive operations for pdl

DESCRIPTION
===========

   This module provides some primitive and useful functions defined using
PDL::PP and able to use the new indexing tricks.

   See `PDL::Indexing|PDL::Indexing' in this node for how to use indices
creatively.  For explanation of the signature format, see
`PDL::PP|PDL::PP' in this node.

SYNOPSIS
========

     use PDL::Primitive;

FUNCTIONS
=========

inner
-----

     c = sum_i a_i * b_i

outer
-----

   Naturally, it is possible to achieve the effects of outer product
simply by threading over the "*" operator but this function is provided
for convenience.

matmult
-------

   We peruse the inner product to define matrix multiplication via a
threaded inner product

innerwt
-------

     d = sum_i a(i) b(i) c(i)

inner2
------

     d = sum_ij a(i) b(i,j) c(j)

   Note that you should probably not thread over a and c since that would
be very wasteful. Instead, you should use a temporary for `b*c'.

inner2d
-------

   Equivalent to

     $c = inner($a->clump(2), $b->clump(2))

inner2t
-------

   Efficiency comes from by using the temporary `tmp'. This operation only
scales as `N**3' whereas threading using `inner2|' in this node would scale
as `N**4'.

   The reason for having this routine is that you do not need to have the
same thread-dimensions for `tmp' as for the other arguments, which in case
of large numbers of matrices makes this much more memory-efficient.

   It is hoped that things like this could be taken care of as a kind of
closures at some point.

crossp
------

   After

   the inner product `$c*$a' and `$c*$b' will be zero, i.e. $c is
orthogonal to `$a' and $b

norm
----

indadd
------

     sum(ind) += a

     $a = 2;
     $ind = 3;
     $sum = zeroes(10);
     indadd($a,$ind, $sum);
     print $sum
     #Result: ( 2 added to element 3 of $sum)
     # [0 0 0 2 0 0 0 0 0 0]

   Threaded Example:

     $a = pdl( 1,2,3);
     $ind = pdl( 1,4,6);
     $sum = zeroes(10);
     indadd($a,$ind, $sum);
     print $sum."\n";
     #Result: ( 1, 2, and 3 added to elements 1,4,6 $sum)
     # [0 1 0 0 2 0 3 0 0 0]

conv1d
------

   By default, periodic boundary conditions are assumed (i.e. wrap around).
Alternatively, you can request reflective boundary conditions using the
Boundary option:

     {Boundary => 'reflect'} # case in 'reflect' doesn't matter

   The convolution is performed along the first dimension. To apply it
across another dimension use the slicing routines, e.g.

     $b = $a->mv(2,0)->conv1d($kernel)->mv(0,2); # along third dim

   This function is useful for threaded filtering of 1D signals.

   Compare also `conv2d|PDL::Image2D' in this node,
`convolve|PDL::ImageND' in this node, `fftconvolve|PDL::FFT' in this node,
`fftwconv|PDL::FFTW' in this node, `rfftwconv|PDL::FFTW' in this node

hclip
-----

lclip
-----

clip
----

wtstat
------

   This calculates a weighted statistic over the vector a.  The formula is

     b() = (sum_i wt_i * (a_i ** degree - avg)) / (sum_i wt_i)

stats
-----

   This utility calculates all the most useful quantities in one call.

   Note: The RMS value that this function returns in the RMS deviation
from the mean, also known as the population standard- deviation.

histogram
---------

   The histogram will contain `$numbins' bins starting from `$min', each
`$step' wide. The value in each bin is the number of values in $data that
lie within the bin limits.

   Data below the lower limit is put in the first bin, and data above the
upper limit is put in the last bin.

   The output is reset in a different threadloop so that you can take a
histogram of `$a(10,12)' into `$b(15)' and get the result you want.

   Use `hist|PDL::Basic' in this node instead for a high-level interface.

whistogram
----------

   The histogram will contain `$numbins' bins starting from `$min', each
`$step' wide. The value in each bin is the sum of the values in `$weights'
that correspond to values in $data that lie within the bin limits.

   Data below the lower limit is put in the first bin, and data above the
upper limit is put in the last bin.

   The output is reset in a different threadloop so that you can take a
histogram of `$a(10,12)' into `$b(15)' and get the result you want.

histogram2d
-----------

   The histogram will contain `$nbinx' x `$nbiny' bins, with the lower
limits of the first one at `($minx, $miny)', and with bin size `($stepx,
$stepy)'.  The value in each bin is the number of values in `$datax' and
`$datay' that lie within the bin limits.

   Data below the lower limit is put in the first bin, and data above the
upper limit is put in the last bin.

whistogram2d
------------

   The histogram will contain `$nbinx' x `$nbiny' bins, with the lower
limits of the first one at `($minx, $miny)', and with bin size `($stepx,
$stepy)'.  The value in each bin is the sum of the values in `$weights'
that correspond to values in `$datax' and `$datay' that lie within the bin
limits.

   Data below the lower limit is put in the first bin, and data above the
upper limit is put in the last bin.

fibonacci
---------

append
------

   append appends two piddles along their first dims. Rest of the
dimensions must be compatible in the threading sense. Resulting size of
first dim is the sum of the sizes of the first dims of the two argument
piddles - ie `n + m'.

axisvalues
----------

   axisvalues is the internal primitive that implements
`axisvals|PDL::Basic' in this node and alters its argument.

random
------

   etc (see `zeroes|PDL::Core' in this node).

   This is the uniform distribution between 0 and 1 (assumedly excluding 1
itself). The arguments are the same as zeroes (q.v.) - i.e. one can
specify dimensions, types or give a template.

randsym
-------

   etc (see `zeroes|PDL::Core' in this node).

   This is the uniform distribution between 0 and 1 (excluding both 0 and
1, cf `random|' in this node). The arguments are the same as zeroes (q.v.)
- i.e. one can specify dimensions, types or give a template.

grandom
-------

   etc (see `zeroes|PDL::Core' in this node).

   This is generated using the math library routine ndtri.

   Mean = 0, Stddev = 1

vsearch
-------

   Returns for each value of `$vals' the index of the least larger member
of `$xs' (which need to be in increasing order). If the value is larger
than any member of `$xs', the index to the last element of `$xs' is
returned.

     $a = pdl(.01,.86,.93,1); # Barnsley IFS probabilities cumulatively
     $b = random 20;
     $c = vsearch($b, $a); # Now, $c will have the appropriate distr.

   It is possible to use the `cumusumover|' in this node function to obtain
cumulative probabilities from absolute probabilities.

interpolate
-----------

   Given a set of points `($x,$y)', use linear interpolation to find the
values `$yi' at a set of points `$xi'.

   interpolate uses a binary search to find the suspects, er...,
interpolation indices and therefore abscissas (ie $x) have to be
*strictly* ordered (increasing or decreasing).  For interpolation at lots
of closely spaced abscissas an approach that uses the last index found as
a start for the next search can be faster (compare Numerical Recipes
`hunt' routine). Feel free to implement that on top of the binary search
if you like. For out of bounds values it just does a linear extrapolation
and sets the corresponding element of $err to 1, which is otherwise 0.

   See also `interpol|' in this node, which uses the same routine,
differing only in the handling of extrapolation - an error message is
printed rather than returning an error piddle.

interpol
--------

   interpol uses the same search method as `interpolate|' in this node,
hence $x must be *strictly* ordered (either increasing or decreasing).
The difference occurs in the handling of out-of-bounds values; here an
error message is printed.

one2nd
------

   returns an array of piddles containing the ND indexes corresponding to
the one dimensional list indices. The indices are assumed to correspond to
array `$a' clumped using `clump(-1)'. This routine is used in `whichND|'
in this node, but is useful on its own occasionally.

which
-----

   returns a pdl with indices for all those elements that are nonzero in
the mask. Note that mask really has to be 1-D (use `clump(-1)' if you need
to work with ND-images)

   If you want to return both the indices of non-zero values and the
complement, use the function `which_both|' in this node.

which_both
----------

   This works just as which, but the complement of $i will be in `$c_i'.

where
-----

   Note: $i is always 1-D, even if $x is >1-D. The first argument (the
values) and the second argument (the mask) currently have to have the same
initial dimensions (or horrible things happen).

   It is also possible to use the same mask for several piddles with the
same call:

     ($i,$j,$k) = where($x,$y,$z, $x+5>0);

whichND
-------

   returns an array of piddles containing the coordinates of the elements
that are non-zero in $mask.

AUTHOR
======

   Copyright (C) Tuomas J. Lukka 1997 (lukka@husc.harvard.edu).
Contributions by Christian Soeller (c.soeller@auckland.ac.nz) and Karl
Glazebrook (kgb@aaoepp.aao.gov.au).  All rights reserved. There is no
warranty. You are allowed to redistribute this software / documentation
under certain conditions. For details, see the file COPYING in the PDL
distribution. If this file is separated from the PDL distribution, the
copyright notice should be included in the file.

a reduce function for PDL
*************************

NAME
====

   PDL::Reduce - a reduce function for PDL

DESCRIPTION
===========

   Many languages have a reduce function used to reduce the rank of an N-D
array by one. It works by applying a selected operation along a specified
dimension. This module implements such a function for PDL by providing a
simplified interface to the existing projection functions (e.g. sumover,
maximum, average, etc).

SYNOPSIS
========

     use PDL::Reduce;
     $a = sequence 5,5;
     # reduce by adding all
     # elements along 2nd dimension
     $b = $a->reduce(add,1);
     @ops = $a->canreduce; # return a list of all allowed operations

FUNCTIONS
=========

reduce
------

   reduce dimension of piddle by one by applying an operation along the
specified dimension

   [ As an aside: if you are familiar with threading you will see that
this is actually the same as

     $b = $a->mv(1,0)->sumover

   ]

   reduce provides a simple and unified interface to the *projection*
functions and makes people coming from other data/array languages
hopefully feel more at home.

   reduce applies the named operation along the specified dimension
reducing the input piddle dimension by one. If the dimension is omitted
the operation is applied along the first dimension. To get a list of valid
operations see `canreduce' in this node.

canreduce
---------

   This list is useful if you want to make sure which operations can be
used with reduce.

PDL interface to the slatec numerical programming library
*********************************************************

NAME
====

   PDL::Slatec - PDL interface to the slatec numerical programming library

SYNOPSIS
========

     use PDL::Slatec;

     ($ndeg, $r, $ierr, $a) = polyfit($x, $y, $w, $maxdeg, $eps);

DESCRIPTION
===========

   This module serves the dual purpose of providing an interface to parts
of the slatec library and showing how to interface PDL to an external
library.  Using this library requires a fortran compiler; the source for
the routines is provided for convenience.

   Currently available are routines to: manipulate matrices; calculate
FFT's; fit data using polynomials; and interpolate/integrate data using
piecewise cubic Hermite interpolation.

Piecewise cubic Hermite interpolation (PCHIP)
---------------------------------------------

   PCHIP is the slatec package of routines to perform piecewise cubic
Hermite interpolation of data.  It features software to produce a monotone
and "visually pleasing" interpolant to monotone data.  According to
Fritsch & Carlson ("Monotone piecewise cubic interpolation", SIAM Journal
on Numerical Analysis 17, 2 (April 1980), pp. 238-246), such an
interpolant may be more reasonable than a cubic spline if the data
contains both "steep" and "flat" sections.  Interpolation of cumulative
probability distribution functions is another application.  These routines
are cryptically named (blame FORTRAN), beginning with 'ch', and accept
either float or double piddles.

   Most of the routines require an integer parameter called check; if set
to 0, then no checks on the validity of the input data are made, otherwise
these checks are made.  The value of check can be set to 0 if a routine
such as `chim|' in this node has already been successfully called.

   * If not known, estimate derivative values for the points using the
     `chim|' in this node, `chic|' in this node, or `chsp|' in this node
     routines (the following routines require both the function (f) and
     derivative (d) values at a set of points (x)).

   * Evaluate, integrate, or differentiate the resulting PCH function
     using the routines: `chfd|' in this node; `chfe|' in this node;
     `chia|' in this node; `chid|' in this node.

   * If desired, you can check the monotonicity of your data using `chcm|'
     in this node.

FUNCTIONS
=========

eigsys
------

   Note: this function should be extended to calculate only eigenvalues if
called in scalar context!

matinv
------

polyfit
-------

   Convenience wrapper routine about the polfit `slatec' function.
Separates supplied arguments and return values.

   `eps' is modified to contain the rms error of the fit.

polycoef
--------

   Convenience wrapper routine around the pcoef `slatec' function.
Separates supplied arguments and return values.

polyvalue
---------

   Convenience wrapper routine around the pvalue `slatec' function.
Separates supplied arguments and return values.

   For multiple input x positions, a corresponding y position is
calculated.

   The derivatives PDL is one dimensional (of size `nder') if a single x
position is supplied, two dimensional if more than one x position is
supplied.

svdc
----

poco
----

   Factor a real symmetric positive definite matrix and estimate the
condition number of the matrix.

geco
----

   Factor a matrix using Gaussian elimination and estimate the condition
number of the matrix.

gefa
----

podi
----

   Compute the determinant and inverse of a certain real symmetric
positive definite matrix using the factors computed by `poco|' in this
node.

gedi
----

   Compute the determinant and inverse of a matrix using the factors
computed by `geco|' in this node or `gefa|' in this node.

gesl
----

   Solve the real system `A*X=B' or `TRANS(A)*X=B' using the factors
computed by `geco|' in this node or `gefa|' in this node.

rs
--

   This subroutine calls the recommended sequence of subroutines from the
eigensystem subroutine package (EISPACK) to find the eigenvalues and
eigenvectors (if desired) of a REAL SYMMETRIC matrix.

ezffti
------

   Subroutine ezffti initializes the work array `wsave()' which is used in
both `ezfftf|' in this node and `ezfftb|' in this node.  The prime
factorization of n together with a tabulation of the trigonometric
functions are computed and stored in `wsave()'.

ezfftf
------

   *ezfftf = \&PDL::ezfftf;

ezfftb
------

   *ezfftb = \&PDL::ezfftb;

polfit
------

   Fit discrete data in a least squares sense by polynomials in one
variable. `x()', `y()' and `w()' must be of the same type.

pcoef
-----

   Convert the polfit coefficients to Taylor series form.  c and `a()'
must be of the same type.

pvalue
------

   Use the coefficients generated by polfit to evaluate the polynomial fit
of degree l, along with the first `nder' of its derivatives, at a
specified point. x and a must be of the same type.

chim
----

   Calculate the derivatives at the given set of points (`$x,$f', where $x
is strictly increasing).  The resulting set of points - `$x,$f,$d',
referred to as the cubic Hermite representation - can then be used in
other functions, such as `chfe|' in this node, `chfd|' in this node, and
`chia|' in this node.

   The boundary conditions are compatible with monotonicity, and if the
data are only piecewise monotonic, the interpolant will have an extremum
at the switch points; for more control over these issues use `chic|' in
this node.

   Error status returned by `$ierr':

   * 0 if successful.

   * > 0 if there were `ierr' switches in the direction of monotonicity
     (data still valid).

   * -1 if `nelem($x) < 2'.

   * -3 if $x is not strictly increasing.

chic
----

   Calculate the derivatives at the given points (`$x,$f', where $x is
strictly increasing).  Control over the boundary conditions is given by the
`$ic' and `$vc' piddles, and the value of `$mflag' determines the
treatment of points where monotoncity switches direction. A simpler, more
restricted, interface is available using `chim|' in this node.

   The first and second elements of `$ic' determine the boundary
conditions at the start and end of the data respectively.  If the value is
0, then the default condition, as used by `chim|' in this node, is adopted.
If greater than zero, no adjustment for monotonicity is made, otherwise if
less than zero the derivative will be adjusted.  The allowed magnitudes
for `ic(0)' are:

   * 1 if first derivative at `x(0)' is given in `vc(0)'.

   * 2 if second derivative at `x(0)' is given in `vc(0)'.

   * 3 to use the 3-point difference formula for `d(0)'.  (Reverts to the
     default b.c. if `n < 3')

   * 4 to use the 4-point difference formula for `d(0)'.  (Reverts to the
     default b.c. if `n < 4')

   * 5 to set `d(0)' so that the second derivative is continuous at `x(1)'.
     (Reverts to the default b.c. if `n < 4')

   The values for `ic(1)' are the same as above, except that the
first-derivative value is stored in `vc(1)' for cases 1 and 2.  The values
of `$vc' need only be set if options 1 or 2 are chosen for `$ic'.

   Set `$mflag = 0' if interpolant is required to be monotonic in each
interval, regardless of the data. This causes $d to be set to 0 at all
switch points. Set `$mflag' to be non-zero to use a formula based on the
3-point difference formula at switch points. If `$mflag > 0', then the
interpolant at swich points is forced to not deviate from the data by more
than `$mflag*dfloc', where `dfloc' is the maximum of the change of $f on
this interval and its two immediate neighbours.  If `$mflag < 0', no such
control is to be imposed.

   The piddle `$wk' is only needed for work space. However, I could not
get it to work as a temporary variable, so you must supply it; it is a 1D
piddle with `2*n' elements.

   Error status returned by `$ierr':

   * 0 if successful.

   * 1 if `ic(0) < 0' and `d(0)' had to be adjusted for monotonicity.

   * 2 if `ic(1) < 0' and `d(n-1)' had to be adjusted for monotonicity.

   * 3 if both 1 and 2 are true.

   * -1 if `n < 2'.

   * -3 if $x is not strictly increasing.

   * -4 if `abs(ic(0)) > 5'.

   * -5 if `abs(ic(1)) > 5'.

   * -6 if both -4 and -5  are true.

   * -7 if `nwk < 2*(n-1)'.

chsp
----

   Calculate the derivatives, using cubic spline interpolation, at the
given points (`$x,$f'), with the specified boundary conditions.  Control
over the boundary conditions is given by the `$ic' and `$vc' piddles.  The
resulting values - `$x,$f,$d' - can be used in all the functions which
expect a cubic Hermite function.

   The first and second elements of `$ic' determine the boundary
conditions at the start and end of the data respectively.  The allowed
values for `ic(0)' are:

   * 0 to set `d(0)' so that the third derivative is continuous at `x(1)'.

   * 1 if first derivative at `x(0)' is given in `vc(0').

   * 2 if second derivative at `x(0') is given in `vc(0)'.

   * 3 to use the 3-point difference formula for `d(0)'.  (Reverts to the
     default b.c. if `n < 3'.)

   * 4 to use the 4-point difference formula for `d(0)'.  (Reverts to the
     default b.c. if `n < 4'.)

   The values for `ic(1)' are the same as above, except that the
first-derivative value is stored in `vc(1)' for cases 1 and 2.  The values
of `$vc' need only be set if options 1 or 2 are chosen for `$ic'.

   The piddle `$wk' is only needed for work space. However, I could not
get it to work as a temporary variable, so you must supply it; it is a 1D
piddle with `2*n' elements.

   Error status returned by `$ierr':

   * 0 if successful.

   * -1  if `nelem($x) < 2'.

   * -3  if $x is not strictly increasing.

   * -4  if `ic(0) < 0' or `ic(0) > 4'.

   * -5  if `ic(1) < 0' or `ic(1) > 4'.

   * -6  if both of the above are true.

   * -7  if `nwk < 2*n'.

   * -8  in case of trouble solving the linear system for the interior
     derivative values.

chfd
----

   Given a piecewise cubic Hermite function - such as from `chim|' in this
node - evaluate the function (`$fe') and derivative (`$de') at a set of
points (`$xe').  If function values alone are required, use `chfe|' in
this node.  Set check to 0 to skip checks on the input data.

   Error status returned by `$ierr':

   * 0 if successful.

   * >0 if extrapolation was performed at `ierr' points (data still valid).

   * -1 if `nelem($x) < 2'

   * -3 if $x is not strictly increasing.

   * -4 if `nelem($xe) < 1'.

   * -5 if an error has occurred in a lower-level routine, which should
     never happen.

chfe
----

   Given a piecewise cubic Hermite function - such as from `chim|' in this
node - evaluate the function (`$fe') at a set of points (`$xe').  If
derivative values are also required, use `chfd|' in this node.  Set check
to 0 to skip checks on the input data.

   Error status returned by `$ierr':

   * 0 if successful.

   * >0 if extrapolation was performed at `ierr' points (data still valid).

   * -1 if `nelem($x) < 2'

   * -3 if $x is not strictly increasing.

   * -4 if `nelem($xe) < 1'.

chia
----

   Evaluate the definite integral of a a piecewise cubic Hermite function
over an arbitrary interval, given by `[$a,$b]'.  See `chid|' in this node
if the integration limits are data points.  Set check to 0 to skip checks
on the input data.

   The values of `$a' and $b do not have to lie within $x, although the
resulting integral value will be highly suspect if they are not.

   Error status returned by `$ierr':

   * 0 if successful.

   * 1 if `$a' lies outside $x.

   * 2 if $b lies outside $x.

   * 3 if both 1 and 2 are true.

   * -1 if `nelem($x) < 2'

   * -3 if $x is not strictly increasing.

   * -4 if an error has occurred in a lower-level routine, which should
     never happen.

chid
----

   Evaluate the definite integral of a a piecewise cubic Hermite function
between `x($ia)' and `x($ib)'.

   See `chia|' in this node for integration between arbitrary limits.

   Although using a fortran routine, the values of `$ia' and `$ib' are
zero offset.  Set check to 0 to skip checks on the input data.

   Error status returned by `$ierr':

   * 0 if successful.

   * -1 if `nelem($x) < 2'.

   * -3 if $x is not strictly increasing.

   * -4 if `$ia' or `$ib' is out of range.

chcm
----

   The outout piddle `$ismon' indicates over which intervals the function
is monotonic.  Set check to 0 to skip checks on the input data.

   For the data interval `[x(i),x(i+1)]', the values of `ismon(i)' can be:

   * -3 if function is probably decreasing

   * -1 if function is strictly decreasing

   * 0  if function is constant

   * 1  if function is strictly increasing

   * 2  if function is non-monotonic

   * 3  if function is probably increasing

   If `abs(ismon(i)) == 3', the derivative values are near the boundary of
the monotonicity region. A small increase produces non-monotonicity,
whereas a decrease produces strict monotonicity.

   The above applies to `i = 0 .. nelem($x)-1'. The last element of
`$ismon' indicates whether the entire function is monotonic over $x.

   Error status returned by `$ierr':

   * 0 if successful.

   * -1 if `n < 2'.

   * -3 if $x is not strictly increasing.

AUTHOR
======

   Copyright (C) 1997 Tuomas J. Lukka.  Copyright (C) 2000 Tim Jenness,
Doug Burke.  All rights reserved. There is no warranty. You are allowed to
redistribute this software / documentation under certain conditions. For
details, see the file COPYING in the PDL distribution. If this file is
separated from the PDL distribution, the copyright notice should be
included in the file.

Stupid index tricks
*******************

NAME
====

   PDL::Slices - Stupid index tricks

SYNOPSIS
========

     use PDL;
     $a = ones(3,3);
     $b = $a->slice('-1:0,(1)');
     $c = $a->dummy(2);

DESCRIPTION
===========

   This package provides many of the powerful PerlDL core index
manipulation routines. These routines are usually two-way so you can get a
unit matrix by

     $a = zeroes(1000,1000);
     $a->diagonal(0,1) ++;

   which is usually fairly efficient. See PDL/Indexing,
and PDL/Tips, for more examples.

   These functions are usually two-way:

     $b = $a->slice("1:3");
     $b += 5;   		# $a is changed!

   If you want to force a copy and no "flow" backwards, you need

     $b = $a->slice("1:3")->copy;
     $b += 5;		# $a is not changed.

   alternatively, you can use

     $b = $a->slice("1:3")->sever;

   which does not copy the struct but beware that after

     $b = $a->slice("1:3");
     $c = $b->sever;

   the variables $b and $c point to the same object but with `->copy' they
do not.

   The fact that there is this kind of flow makes PDL a very powerful
language in many ways: since you can alter the original data by altering
some easier-to-use representation of it, many things are much easier to
accomplish, just like making the above unit matrix.

FUNCTIONS
=========

index
-----

   It would be useful to have a more complete function for this at some
point, or at least a perl wrapper, that allows

     $c = $a->islice("1:2",$ind1,"3:4",$ind2);

   with many dimensions.

   This function is two-way, i.e. after

     $c = $a->index(pdl[0,5,8]);
     $c .= pdl [0,2,4];

   the changes in $c will flow back to `$a'.

index2d
-------

   It would be useful to have a more complete function for this at some
point, or at least a perl wrapper, that allows

     $c = $a->islice("1:2",$ind1,"3:4",$ind2);

   with many dimensions.

   This function is two-way, i.e. after

     $c = $a->index(pdl[0,5,8]);
     $c .= pdl [0,2,4];

   the changes in $c will flow back to `$a'.

rld
---

   Given a vector `$a' of the numbers of instances of values $b, run-length
decode to $c.

rle
---

   Given vector $c, generate a vector `$a' with the number of each element,
and a vector $b of the unique values.  Only the elements up to the first
instance of `0' in `$a' should be considered.

clump
-----

   If, for example, `$a' has dimensions `(5,3,4)' then after

   the variable $b will have dimensions `(15,4)' and the element
`$b->at(7,3)' refers to the element `$a->at(1,2,3)'.

   Use `clump(-1)' to flatten a piddle. The method `flat|PDL::Core' in
this node is provided as an alias for this functionality.

xchg
----

   Negative dimension indices count from the end.

   The command

   creates $b to be like `$a' except that the dimensions 2 and 3 are
exchanged with each other i.e.

     $b->at(5,3,2,8) == $a->at(5,3,8,2)

reorder
-------

   Similar to the `xchg|' in this node method, this method re-orders the
dimensions of a PDL. While the `xchg|' in this node method swaps the
position of two dimensions, the reorder method can change the positions of
many dimensions at once.

   The argument to reorder is an array representing where the current
dimensions should go in the new array. In the above usage, the argument to
reorder `(5,4,3,2,1,0)' indicates that the old dimensions (`$pdl''s dims)
should be re-arranged to make the new pdl (`$reOrderPDL') according to the
following:

     Old Position   New Position
     ------------   ------------
     5              0
     4              1
     3 		  2
     2		  3
     1		  4
     0		  5

     perldl> $a = sequence(5,3,2);	  # Create a 3-d Array
     perldl> p $a
     [
      [
       [ 0  1  2  3  4]
       [ 5  6  7  8  9]
       [10 11 12 13 14]
      ]
      [
       [15 16 17 18 19]
       [20 21 22 23 24]
       [25 26 27 28 29]
      ]
     ]
     perldl> p $a->reorder(2,1,0); # Reverse the order of the 3-D PDL
     [
      [
       [ 0 15]
       [ 5 20]
       [10 25]
      ]
      [
       [ 1 16]
       [ 6 21]
       [11 26]
      ]
      [
       [ 2 17]
       [ 7 22]
       [12 27]
      ]
      [
       [ 3 18]
       [ 8 23]
       [13 28]
      ]
      [
       [ 4 19]
       [ 9 24]
       [14 29]
      ]
     ]

   The above is a simple example that could be duplicated by calling
`$a->xchg(0,2)', but it demonstrates the basic functionality of reorder.

   As this is an index function, any modifications to the result PDL will
change the parent.

mv
--

   The command

   creates $b to be like `$a' except that the dimension 4 is moved to the
place 1, so:

     $b->at(1,2,3,4,5,6) == $a->at(1,5,2,3,4,6);

   The other dimensions are moved accordingly.  Negative dimension indices
count from the end.

oneslice
--------

   This is not for public use currently. See the source if you have to.
This function can be used to accomplish run-time changing of
transformations i.e. changing the size of some piddle at run-time.

   However, the mechanism is not yet finalized and this is just a
demonstration.

slice
-----

   The argument string is a comma-separated list of what to do for each
dimension. The current formats include the following, where a, b and c are
integers and can take legal array index values (including -1 etc):

:
     takes the whole dimension intact.

"
     (nothing) is a synonym for ":" (This means that `$a->slice(':,3')' is
     equal to `$a->slice(',3')').

a
     slices only this value out of the corresponding dimension.

(a)
     means the same as "a" by itself except that the resulting dimension
     of length one is deleted (so if `$a' has dims `(3,4,5)' then
     `$a->slice(':,(2),:')' has dimensions `(3,5)' whereas
     `$a->slice(':,2,:')' has dimensions `(3,1,5))'.

a:b
     slices the range a to b inclusive out of the dimension.

a:b:c
     slices the range a to b, with step c (i.e. `3:7:2' gives the indices
     `(3,5,7)'). This may be confusing to Matlab users but several other
     packages already use this syntax.

     inserts an extra dimension of width 1 and

     inserts an extra (dummy) dimension of width a.

   An extension is planned for a later stage allowing
`$a->slice('(=1),(=1|5:8),3:6(=1),4:6')' to express a multidimensional
diagonal of `$a'.

using
-----

   Plot, as a line, column 1 of `$pdl' vs. column 2

diagonalI
---------

   The diagonal is placed at the first (by number) dimension that is
diagonalized.  The other diagonalized dimensions are removed. So if `$a'
has dimensions `(5,3,5,4,6,5)' then after

   the piddle $b has dimensions `(5,3,4,6)' and `$b->at(2,1,0,1)' refers
to `$a->at(2,1,2,0,1,2)'.

   NOTE: diagonal doesn't handle threadids correctly. XXX FIX

lags
----

   I.e. if `$a' contains

     [0,1,2,3,4,5,6,7]

   then

   is a (5,2) matrix

     [2,3,4,5,6,7]
     [0,1,2,3,4,5]

   This order of returned indices is kept because the function is called
"lags" i.e. the nth lag is n steps behind the original.

splitdim
--------

   After

   the expression

     $b->at(6,4,x,y,3,6) == $a->at(6,4,x+3*y)

   is always true (x has to be less than 3).

rotate
------

threadI
-------

   Put some dimensions to a threadid.

identvaff
---------

   Mainly for internal use.

unthread
--------

   See [TBD Doc] for details and examples.

dice
----

   This function can be used to extract irregular subsets along many
dimension of a PDL, e.g. only certain rows in an image, or planes in a
cube. This can of course be done with the usual dimension tricks but this
saves having to figure it out each time!

   This method is similar in functionality to the `slice|' in this node
method, but `slice|' in this node requires that contiguous ranges or ranges
with constant offset be extracted. ( i.e. `slice|' in this node requires
ranges of the form `1,2,3,4,5' or `2,4,6,8,10'). Because of this
restriction, `slice|' in this node is more memory efficient and slightly
faster than dice

   The arguments to dice are arrays (or 1D PDLs) for each dimension in the
PDL. These arrays are used as indexes to which rows/columns/cubes,etc to
dice-out (or extract) from the $data PDL.

   Use X to select all indices along a given dimension (compare also
`mslice|PDL::Core' in this node). As usual (in slicing methods) trailing
dimensions can be omitted implying X'es for those.

   As this is an index function, any modifications to the slice change the
parent (use the `.=' operator).

dice_axis
---------

   This function can be used to extract irregular subsets along any
dimension, e.g. only certain rows in an image, or planes in a cube. This
can of course be done with the usual dimension tricks but this saves
having to figure it out each time!

   The trick to using this is that the index selects elements along the
dimensions specified, so if you have a 2D image `axis=0' will select
certain X values - i.e. extract columns

   As this is an index function, any modifications to the slice change the
parent.

AUTHOR
======

   Copyright (C) 1997 Tuomas J. Lukka.  All rights reserved. There is no
warranty. You are allowed to redistribute this software / documentation
under certain conditions. For details, see the file COPYING in the PDL
distribution. If this file is separated from the PDL distribution, the
copyright notice should be included in the file.

tests for some PP features
**************************

NAME
====

   PDL::Tests - tests for some PP features

SYNOPSIS
========

     use PDL::Tests;

     <test code>

DESCRIPTION
===========

   This module provides some PP defined test functions that are supposed
to test some features/bugs of PDL::PP.

   Strictly speaking this module shouldn't be installed with a 'make
install' but I haven't yet worked out how to do it.

Small tidbits of useful arcana. Programming tidbits and such.
*************************************************************

NAME
====

   PDL::Tips - Small tidbits of useful arcana. Programming tidbits and
such.

SYNOPSIS
========

     use PDL;

     # Whatever happens here.

DESCRIPTION
===========

   This page documents useful idioms, helpful hints and tips for using
Perl Data Language v2.0.

Help
----

   Use `help help' within *perldl* or the `pdldoc' program from the
command line for access to the PerlDL documentation.  HTML versions of the
pages should also be present, in the `HtmlDocs/PDL' directory of the PDL
distribution. To find this directory, try the following

     perldl> foreach ( map{"$_/PDL/HtmlDocs"}@INC ) { p "$_\n" if -d $_ }

Indexing idioms
---------------

   The following code normalizes a bunch of vectors in $a.  This works
regardless of the dimensionality of $a.

     $a /= $a->sumover->dummy(0);

What is actually happening?
---------------------------

   If you want to see what the code is actually doing, try the command

     PDL::Core::set_debugging(1);

   somewhere. This spews out a huge amount of debug info for PDL into
STDOUT. It is planned to eventually make this redirectable and the
messages selectable more accurately.

   Many of the messages come from `Basic/Core/pdlapi.c' and you can look
at the source to see what is going on.

   If you have any extra time to work on these mechanisms, infrom the
pdl-porters mailing list.

Memory savings
--------------

   If you are running recursively something that selects certain indices
of a large piddle, like

     while(1) {
     	$inds = where($a>0);
     	$a = $a->index($inds);
     	$b = $b->index($inds);
     	func($b,$a);
     }

   If you are not writing to $b, it saves a lot of memory to change this to

     $b = $b->index($inds)->sever;

   The new method sever is a causes the write-back relation to be
forgotten. It is like copy except it changes the original piddle and
returns it).

   Of course, the probably best way to do the above is

     $inds = xvals ($a->long);
     while(1) {
     	$inds0 = where($a>0);
     	$inds1 = $inds->index($inds)->sever;
     	$a = $a0->index($inds1);
     	$b = $b->index($inds1)->sever;
     	func($b,$a);
     }

   which doesn't save all the temporary instances of $a in memory.  See
`mandel.pl' in the Demos subdirectory of the PerlDL distribution for an
example.

PP speed
--------

   If you really want to write speedy PP code, the first thing you need to
do is to make sure that your C compiler is allowed to do the necessary
optimizations.

   What this means is that you have to allow as many variables as possible
to go into registers:

     loop(a) %{
     	$a() += $COMP(foo_member) * $b()
     %}

   expands to

     for(i=0; i<10000; i++) {
     	a[i] += __privtrans->foo_member * b[i];
     }

   is about the worst you can do, since your C compiler is not allowed to
assume that a doesn't clobber `foo_member' which completely inhibits
vectorization. Instead, do

     float foo = $COMP(foo_member);
     loop(a) %{
     	$a() += foo * $b();
     %}

   This is not a restriction caused by PP but by ANSI C semantics.  Of
course, we could copy the struct into local varibles and back but that
could cause very strange things sometimes.

   There are many other issues on organizing loops.

   We are currently planning to make PP able to do fixed-width things as
well as physical piddles (where looping over the first dimensions would be
cheaper as there are less distinct increments, which might make a
difference on machines with a small number of registers).

AUTHOR
======

   Copyright (C) Tuomas J. Lukka 1997. All rights reserved.  Duplication
in the same form and printing a copy for yourself allowed.

define fundamental PDL Datatypes
********************************

NAME
====

   PDL::Types - define fundamental PDL Datatypes

SYNOPSIS
========

     use PDL::Types;

     $pdl = ushort( 2.0, 3.0 );
     print "The actual c type used to store ushort's is '" .
        $pdl->type->realctype() . "'\n";
     The actual c type used to store ushort's is 'unsigned short'

DESCRIPTION
===========

   Internal module - holds all the PDL Type info.  This can be accessed
using the `PDL::Type' object returned by the `type|PDL::Core' in this node
method.

OBJECTS
=======

   This module contains one object - `PDL::Type' - that is returned by the
`type|PDL::Core' in this node method of a piddle.  It has several methods,
listed below, which provide an easy way to access type infotmation:

enum
     Returns the number representing this datatype (see
     `get_datatype|PDL::Core' in this node).

symbol
     Returns one of 'PDL_B', 'PDL_S', 'PDL_US', 'PDL_L', 'PDL_F' or
     'PDL_D'.

ctype
     Returns the macro used to represent this type in C code (eg
     'PDL_Long').

ppsym
     The letter used to represent this type in PP code code (eg 'U' for
     `ushort|PDL::Core' in this node).

realctype
     The actual C type used to store this type.

shortctype
     The value returned by ctype without the 'PDL_'.

primitive ufunc operations for pdl
**********************************

NAME
====

   PDL::Ufunc - primitive ufunc operations for pdl

DESCRIPTION
===========

   This module provides some primitive and useful functions defined using
PDL::PP based on functionality of what are sometimes called *ufuncs* (for
example NumPY and Mathematica talk about these).  It collects all the
functions generally used to reduce or `accumulate' along a dimension.
These all do their job across the first dimension but by using the slicing
functions you can do it on any dimension.

   The `PDL::Reduce|PDL::Reduce' in this node module provides an
alternative interface to many of the functions in this module.

SYNOPSIS
========

     use PDL::Ufunc;

FUNCTIONS
=========

prodover
--------

   This function reduces the dimensionality of a piddle by one by taking
the product along the 1st dimension.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

dprodover
---------

   This function reduces the dimensionality of a piddle by one by taking
the product along the 1st dimension.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

   Unlike `prodover|' in this node, the calculations are performed in
double precision.

cumuprodover
------------

   This function calculates the cumulative product along the 1st dimension.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

   The sum is started so that the first element in the cumulative product
is the first element of the parameter.

dcumuprodover
-------------

   This function calculates the cumulative product along the 1st dimension.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

   The sum is started so that the first element in the cumulative product
is the first element of the parameter.

   Unlike `cumuprodover|' in this node, the calculations are performed in
double precision.

sumover
-------

   This function reduces the dimensionality of a piddle by one by taking
the sum along the 1st dimension.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

dsumover
--------

   This function reduces the dimensionality of a piddle by one by taking
the sum along the 1st dimension.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

   Unlike `sumover|' in this node, the calculations are performed in double
precision.

cumusumover
-----------

   This function calculates the cumulative sum along the 1st dimension.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

   The sum is started so that the first element in the cumulative sum is
the first element of the parameter.

dcumusumover
------------

   This function calculates the cumulative sum along the 1st dimension.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

   The sum is started so that the first element in the cumulative sum is
the first element of the parameter.

   Unlike `cumusumover|' in this node, the calculations are performed in
double precision.

andover
-------

   This function reduces the dimensionality of a piddle by one by taking
the and along the 1st dimension.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

zcover
------

   This function reduces the dimensionality of a piddle by one by taking
the == 0 along the 1st dimension.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

orover
------

   This function reduces the dimensionality of a piddle by one by taking
the or along the 1st dimension.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

borover
-------

   This function reduces the dimensionality of a piddle by one by taking
the bitwise or along the 1st dimension.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

bandover
--------

   This function reduces the dimensionality of a piddle by one by taking
the bitwise and along the 1st dimension.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

intover
-------

   This function reduces the dimensionality of a piddle by one by taking
the integral along the 1st dimension.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

   Notes:

   For `n > 3', these are all `O(h^4)' (like Simpson's rule), but are
integrals between the end points assuming the pdl gives values just at
these centres: for such `functions', sumover is correct to `O(h)', but is
the natural (and correct) choice for binned data, of course.

average
-------

   This function reduces the dimensionality of a piddle by one by taking
the average along the 1st dimension.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

daverage
--------

   This function reduces the dimensionality of a piddle by one by taking
the average along the 1st dimension.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

   Unlike `average|' in this node, the calculation is performed in double
precision.

medover
-------

   This function reduces the dimensionality of a piddle by one by taking
the median along the 1st dimension.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

oddmedover
----------

   This function reduces the dimensionality of a piddle by one by taking
the oddmedian along the 1st dimension.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

   The median is sometimes not a good choice as if the array has an even
number of elements it lies half-way between the two middle values - thus
it does not always correspond to a data value. The lower-odd median is
just the lower of these two values and so it ALWAYS sits on an actual data
value which is useful in some circumstances.

pctover
-------

   Project via percentile to N-1 dimensions

   This function reduces the dimensionality of a piddle by one by finding
the specified percentile (p) along the 1st dimension.  The specified
percentile must be between 0.0 and 1.0.  When the specified percentile
falls between data points, the result is interpolated.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

oddpctover
----------

   Project via percentile to N-1 dimensions

   This function reduces the dimensionality of a piddle by one by finding
the specified percentile along the 1st dimension.  The specified
percentile must be between 0.0 and 1.0.  When the specified percentile
falls between two values, the nearest data value is the result.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

pct
---

oddpct
------

avg
---

sum
---

prod
----

davg
----

dsum
----

dprod
-----

zcheck
------

and
---

band
----

or
--

bor
---

min
---

max
---

median
------

oddmedian
---------

any
---

   Useful in conditional expressions:

all
---

   Useful in conditional expressions:

minmax
------

   This routine does not thread over the dimensions of `$pdl'; it returns
the minimum and maximum values of the whole array.  See `minmaximum|' in
this node if this is not what is required.

qsort
-----

qsorti
------

minimum
-------

   This function reduces the dimensionality of a piddle by one by taking
the minimum along the 1st dimension.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

minimum_ind
-----------

minimum_n_ind
-------------

maximum
-------

   This function reduces the dimensionality of a piddle by one by taking
the maximum along the 1st dimension.

   By using `xchg|PDL::Slices' in this node etc. it is possible to use any
dimension.

maximum_ind
-----------

maximum_n_ind
-------------

minmaximum
----------

   See also `minmax|' in this node, which clumps the piddle together.

AUTHOR
======

   Copyright (C) Tuomas J. Lukka 1997 (lukka@husc.harvard.edu).
Contributions by Christian Soeller (c.soeller@auckland.ac.nz) and Karl
Glazebrook (kgb@aaoepp.aao.gov.au).  All rights reserved. There is no
warranty. You are allowed to redistribute this software / documentation
under certain conditions. For details, see the file COPYING in the PDL
distribution. If this file is separated from the PDL distribution, the
copyright notice should be included in the file.

Create detached PGP signatures for data, securely
*************************************************

NAME
====

   PGP::Sign - Create detached PGP signatures for data, securely

SYNOPSIS
========

     use PGP::Sign;
     ($signature, $version) = pgp_sign ($keyid, $passphrase, @data);
     $signer = pgp_verify ($signature, $version, @data);
     @errors = PGP::Sign::pgp_error;

DESCRIPTION
===========

   This module is designed to do one and only one thing securely and well;
namely, generate and check detached PGP signatures for some arbitrary data.
It doesn't do encryption, it doesn't manage keyrings, it doesn't verify
signatures, it just signs things.  This is ideal for applications like
PGPMoose or control message generation that just need a fast signing
mechanism.  It supports versions 2.6, 5.0, and 6.5.2 of PGP, as well as
GnuPG, and therefore supports any of the signature types understood by
those programs provided they are installed.

   The interface is very simple; just call pgp_sign() with a key ID, a pass
phrase, and some data, or call pgp_verify() with a signature (in the form
generated by pgp_sign()), a version number (which can be undef if you don't
want to give a version), and some data.  The data can be specified in
pretty much any form you can possibly consider data and a few you might
not.  Scalars and arrays are passed along to PGP; references to arrays are
walked and passed one element at a time (to avoid making a copy of the
array); file handles, globs, or references to globs are read a line at a
time and passed to PGP; and references to code are even supported (see
below).  About the only thing that we don't handle are references to
references (which are just printed to PGP, which probably isn't what you
wanted) and hashes (which are treated like arrays, which doesn't make a
lot of sense).

   If you give either function a reference to a sub, it will repeatedly
call that sub, sending the results to PGP to be signed, until the sub
returns undef.  What this lets you do is pass the function an anonymous
sub that walks your internal data and performs some manipulations on it a
line at a time, thus allowing you to sign a slightly modified form of your
data (with initial dashes escaped, for example) without having to use up
memory to make an internal copy of it.

   In a scalar context, pgp_sign() returns the signature as an
ASCII-armored block with embedded newlines (but no trailing newline).  In
a list context, it returns a two-element list consisting of the signature
as above and the PGP version that signed it (if that information was
present in the signature).  Warning:  It's expected that in the future
this interface will change, and pgp_sign() will instead return a list
consisting of the ASCII-armored block and all headers found in the armor.

   If you're using GnuPG, pgp_sign() will pass it the option
*-force-v3-sigs* so that it will generate PGP 5.0-compatible signatures.

   pgp_sign() will return undef in the event of any sort of error.

   pgp_verify() returns the signer of the message in the case of a good
signature, the empty string in the case of a bad signature, and undef in
the event of some error.  It takes the same sort of data sources as
pgp_sign().

   pgp_error() (which isn't exported by default) returns the error
encountered by the last pgp_sign() or pgp_verify(), or undef if there was
no error.  In a list context, a list of lines is returned; in a scalar
context, a long string with embedded newlines is returned.

   Six global variables can be modified (note that these will likely
eventually be partially or completely replaced with an interface via a
PGP::Sign::config() call):

$PGP::Sign::PGPS
     The path to the program to use to generate signatures.  This is set
     at the time of installation, but can be overridden.

$PGP::Sign::PGPV
     The path to the program to use to verify signatures.  This is set at
     the time of installation, but can be overridden.  There are two
     separate variables since PGP 5.0 uses two separate program names for
     signing and verifying; for PGP 2.6, 6.5.2, or GnuPG, just set both
     this and $PGP::Sign::PGPS to the same value.

$PGP::Sign::PGPPATH
     The path to a directory containing the PGP key rings that should be
     used.  If this isn't set, all versions of PGP will use the value of
     the environment variable PGPPATH or `$HOME/.pgp' (the default).
     GnuPG will use the value of the environment variable GNUPGHOME or
     `$HOME/.gnupg'.  Note that PGP when signing may want to write
     `randseed.bin' (or `randseed.rnd') in this directory if there isn't
     already a random seed there, so if you're encountering problems with
     signing, make sure the directory PGP is using is writeable by the
     user doing the signing.  Note also that if you're using GnuPG and the
     Entropy Gathering Daemon (egd), the entropy socket or a link to it
     must be located in this directory.

$PGP::Sign::PGPSTYLE
     What style of command line arguments and responses to expect from
     PGP.  The only three valid values for this variable are "PGP2" for
     PGP 2.6 behavior, "PGP5" for PGP 5.0 behavior, "PGP6" for PGP 6.5
     behavior, and "GPG" for GnuPG behavior.  What command line arguments
     PGP::Sign uses when running PGP are entirely determined by this
     variable.  It is set at the time of installation, but can be
     overridden.

$PGP::Sign::TMPDIR
     The directory in which temporary files are created.  Defaults to
     TMPDIR if set, and `/tmp' if not.

$PGP::Sign::MUNGE
     If this variable is set to a true value, PGP::Sign will automatically
     strip trailing spaces when signing or verifying signatures.  This
     will make the resulting signatures and verification compatible with
     programs that generate attached signatures (since PGP ignores
     trailing spaces when generating or checking attached signatures).
     See the more extensive discussion of whitespace below.

ENVIRONMENT
===========

PGPPATH
     If $PGP::Sign::PGPPATH is set and $PGP::Sign::PGPSTYLE is something
     other than "GPG", PGP::Sign sets PGPPATH to tell PGP where to find
     its key rings.  (GnuPG uses a command line argument instead.)

TMPDIR
     The directory in which to create temporary files.  Can be overridden
     by changing $PGP::Sign::TMPDIR.  If not set, defaults `/tmp'.

   In addition, all environment variables that PGP normally honors will be
passed along to PGP and will likely have their expected effects.  This
includes PGPPATH, unless it is overridden (see above).

DIAGNOSTICS
===========

   Mostly the contents of @PGP::Sign::ERROR (returned by pgp_error()) are
just the output of PGP.  The exceptions are:

Execution of %s failed: %s
     We couldn't fork off a PGP process for some reason, given (at least
     as the system reported it) after the colon.

No signature from PGP (command not found?)
     We tried to generate a signature but the output from the command we
     tried to run didn't contain anything that looked like a signature.
     One common explanation for this is that the path in $PGP::Sign::PGPS
     is invalid and that binary doesn't exist.

%s returned exit status %d
     Some command that we ran, or tried to run, returned a non-zero exit
     status.  %s will contain the exact binary name that PGP::Sign was
     attempting to run.

BUGS
====

   PGP::Sign does not currently work with binary data, as it
unconditionally forces text mode in PGP by using the -t option.  This is a
high priority to fix, but I'd like to implement some sort of generic way
of setting PGP options rather than just adding more entry points.

   There's no way of generating version four DSS signatures.  This will be
fixed by the same improvement that will fix the previous bug.

   PGP, all versions that I have available, behaves differently when
generating attached signatures than when generating detached signatures.
For attached signatures, trailing whitespace in lines of the data is not
significant, but for detached signatures it is.  This, combined with the
fact that there's no way that I can see to get PGP to verify a detached
signature without using files on disk, means that in order to maintain the
intended default semantics of this module (manipulating detached
signatures), I had to use temporary files in the implementation of
pgp_verify().  PGP::Sign sets its umask before creating those temporary
files and checks for race conditions, but files may be left behind in the
event that an application using pgp_verify() crashes unexpectedly.

   Also, because of this incompatibility, you need to be aware of what the
process checking the signatures you generate is expecting.  If that process
is going to turn your signature into an attached signature for verification
(as pgpverify does for Usenet control messages), then you need to pre-munge
your data to remove trailing whitespace at the ends of lines before feeding
it to PGP.  PGP::Sign will do that for you if you set $PGP::Sign::MUNGE to
a true value.

   To add even more confusion to the mix, earlier versions of GnuPG
followed an interpretation of RFC 2440 that specified text-mode signatures
are performed against data with canonicalized line endings and with
trailing whitespace removed (see section 5.2.1).  There is no difference
specified there between attached and detached signatures, and GnuPG
treated them both the same.  Versions of GnuPG at least after 1.0 appear
to have changed to follow the PGP behavior instead.

CAVEATS
=======

   This module is fairly good at what it does, but it doesn't as yet do
very much.  I intend to provide more options and more configurability in
the future, particularly the ability to handle binary data, but that may
mean API changes.  The interface to this module should not be considered
stable yet; you may have to change your application when you upgrade to a
newer version of this module.  The README will list API changes.

RESTRICTIONS
============

   PGP::Sign passes pass phrases to PGP via an open one-ended pipe, since
this is the only secure method (both command line switches and environment
variables can potentially be read by other users on the same machine using
ps).  This should be supported by any recent version of PGP; I have tested
it against 2.6.2, 2.6.3i, 5.0, 6.5.2, GnuPG 0.9.2, and GnuPG 1.0.1.
Implicit in this mechanism, though, is the requirement that the operating
system on which you're running this module supports passing an open pipe to
an exec()ed subprocess.  This may cause portability problems to certain
substandard operating systems.

SEE ALSO
========

   pgp(1), pgps(1), pgpv(1), gpg(1), RFC 2440

AUTHOR
======

   Russ Allbery <rra@stanford.edu>.

HISTORY
=======

   Based heavily on work by Andrew Gierth <andrew@erlenstar.demon.co.uk>
and benefitting greatly from input, comments, suggestions, and help from
him, this module came about in the process of implementing PGPMoose
signatures and control message signatures for Usenet.  PGPMoose is the
idea of Greg Rose <ggr@usenix.org>, and signcontrol and pgpverify are the
idea of David Lawrence <tale@isc.org>.

   Support for PGPPATH, the test suite, some bug fixes, and the impetus to
get another version released came from Andrew Ford
<A.Ford@ford-mason.co.uk>.  Thank you.

   Original support for GnuPG from Todd Underwood <todd@nm.net> and Monte
Mitzelfelt <monte@nm.net>.

allow subroutines in the PGPLOT graphics library to be called from Perl.
************************************************************************

NAME
====

   PGPLOT - allow subroutines in the PGPLOT graphics library to be called
from Perl.

SYNOPSIS
========

     use PGPLOT;

     pgbegin(0,"/xserve",1,1);
     pgenv(1,10,1,10,0,0);
     pglabel('X','Y','My plot');
     pgpoint(7,[2..8],[2..8],17);

     # etc...

     pgend;

DESCRIPTION
===========

   Originally developed in the olden days of Perl4 (when it was known as
'pgperl' due to the necessity of making a special perl executable) PGPLOT
is now a dynamically loadable perl module which interfaces to the FORTRAN
graphics library of the same name.

   PGPLOT, originally developed as a FORTRAN library, is now available with
C bindings (which the Perl module uses), though a FORTRAN compiler is
still required to build it.

   For every PGPLOT C/FORTRAN function the module provides an equivalent
Perl function with the same arguments. Thus the user of the module should
refer to the PGPLOT manual to learn all about how to use PGPLOT and for
the complete list of available functions.  This manual comes with the
PGPLOT distribution and is also available at the WWW address:

   http://astro.caltech.edu/~tjp/pgplot/

   Also refer to the extensive set of test scripts (`test*.p') included in
the module distribution for examples of usage of all kinds of PGPLOT
routines.

   How the FORTRAN/C function calls map on to Perl calls is detailed below.

ARGUMENT MAPPING - SIMPLE NUMBERS AND ARRAYS
--------------------------------------------

   This is more or less as you might expect - use Perl scalars and Perl
arrays in place of FORTRAN/C variables and arrays.

   Any FORTRAN REAL/INTEGER/CHARACTER* scalar variable maps to a Perl
scalar (Perl doesn't care about the differences between strings and
numbers and ints and floats).

   Thus you can say:

   To draw a line to point (42,$x):

     pgdraw(42,$x);

   To plot 10 points with data in Perl arrays `@x' and `@y' with plot
symbol no. 17. Note the Perl arrays are passed by reference:

     pgpoint(10, \@x, \@y, 17);

   You can also use the old Perl4 style:

     pgpoint(10, *x, *y, 17);

   but this is deprecated in Perl5.

   Label the axes:

     pglabel("X axis", "Data units", $label);

   Draw ONE point, see how when `N=1' `pgpoint()' can take a scalar as
well as a array argument:

     pgpoint(1, $x, $y, 17);

ARGUMENT MAPPING - IMAGES AND 2D ARRAYS
---------------------------------------

   Many of the PGPLOT commands (e.g. `pggray') take 2D arrays as
arguments. Several schemes are provided to allow efficient use from Perl:

  1. Simply pass a reference to a 2D array, e.g:

          # Create 2D array

          $x=[];
          for($i=0; $i<128; $i++) {
             for($j=0; $j<128; $j++) {
               $$x[$i][$j] = sqrt($i*$j);
             }
          }
          pggray( $x, 128, 128, ...);

  2. Pass a reference to a 1D array:

          @x=();
          for($i=0; $i<128; $i++) {
             for($j=0; $j<128; $j++) {
               $x[$i][$j] = sqrt($i*$j);
             }
          }
          pggray( \@x, 128, 128, ...);

     Here @x is a 1D array of 1D arrays. (Confused? - see perldata(1)).
     Alternatively @x could be a flat 1D array with 128x128 elements, 2D
     routines such as `pggray()' etc. are programmed to do the right thing
     as long as the number of elements match.

  3. If your image data is packed in raw binary form into a character
     string you can simply pass the raw string. e.g.:

          read(IMG, $img, 32768);
          pggray($img, $xsize, $ysize, ...);

     Here the read() function reads the binary data from a file and the
     `pggray()' function displays it as a grey-scale image.

     This saves unpacking the image data in to a potentially very large 2D
     perl array. However the types must match. The string must be packed
     as a `"f*"' for example to use `pggray'. This is intended as a
     short-cut for sophisticated users. Even more sophisticated users will
     want to download the `PDL' module which provides a wealth of
     functions for manipulating binary data.

     PLEASE NOTE: As PGPLOT is a Fortran library it expects it's images to
     be be stored in row order. Thus a 1D list is interpreted as a
     sequence of rows end to end. Perl is similar to C in that 2D arrays
     are arrays of pointers thus images end up stored in column order.

     Thus using perl multidimensional arrays the coordinate ($i,$j) should
     be stored in $img[$j][$i] for things to work as expected, e.g:

          $img = [];
          for $j (0..$nx-1) for $i (0..$ny-1) {
             $$img[$j][$i] = whatever();
          }}
          pggray($$img, $nx, $ny, ...);

          Also PGPLOT displays coordinate (0,0) at the bottom left (this is
          natural as the subroutine library was written by an astronomer!).

ARGUMENT MAPPING - FUNCTION NAMES
---------------------------------

   Some PGPLOT functions (e.g. `pgfunx') take functions as callback
arguments. In Perl simply pass a subroutine reference or a name, e.g.:

     # Anonymous code reference:

     pgfunx(sub{ sqrt($_[0]) },  500, 0, 10, 0);

     # Pass by ref:

     sub foo {
       my $x=shift;
       return sin(4*$x);
     }

     pgfuny(\&foo, 360, 0, 2*$pi, 0);

     # Pass by name:

     pgfuny("foo", 360, 0, 2*$pi, 0);

ARGUMENT MAPPING - GENERAL HANDLING OF BINARY DATA
--------------------------------------------------

   In addition to the implicit rules mentioned above PGPLOT now provides a
scheme for explictly handling binary data in all routines.

   If your scalar variable (e.g. $x) holds binary data (i.e. 'packed')
then simply pass PGPLOT a reference to it (e.g. `\$x'). Thus one can say:

     read(MYDATA, $wavelens, $n*4);
     read(MYDATA, $spectrum, $n*4);
     pgline($n, \$wavelens, \$spectrum);

   This is very efficient as we can be sure the data never gets copied and
will always be interpreted as binary.

   Again see the `PDL' module for sophisticated manipulation of binary
data. `PDL' takes great advantage of these facilities.

   Be VERY careful binary data is of the right size or your segments might
get violated.

PML (PML Markup Lanuage)
************************

NAME
====

   PML (PML Markup Lanuage)

SYNOPSIS
========

   use PML;

   my $parser = new PML;

   $parser->parse('/path/to/somefile');

   my $output = $parser->execute;

DESCRIPTION
===========

   PML is a powerful text preprocessor. It supports such things as
variables, flow control and macros. After preprocessing a text file it
returns the result to your Perl script. The power comes from the fact that
you can even embed Perl code into the file that is getting processed.

   PML was originaly designed to seperate a Perl CGI script and the HTML
that it generates. What sets PML apart from other similar solutions is
that it is not just a web solution using mod_perl.  You can parse PML
files from the command line using the supplied pml script or from within
your Perl scripts using the PML Perl module.

   If you do have mod_perl, you can use the supplied mod_pml Apache module
to parse PML files from within the Apache web server.

EXAMPLE PML FILE
================

     <html>
     	<head>
     		<title>${title}</title>
     	</head>
     	<body>
     	@if(${title}) {
     		<h1>${title}</h1>
     	}
     	</body>
     </html>

DOCUMENTATION
=============

   Documentation is supplied with this module, in the doc directory.

     language.html: describes the language.

     pml-modules.html: tells you how to write a PML module

   pml-custom-app.html: tells you how to extend PML from
  within your application.

USAGE
=====

   The following is an overview of the PML API

METHOD new
----------

     Arguments:
     	1) Class or PML Object to clone
     	2) Hash Reference (Optional)

     Returns:
     	1) A PML Object

     Description:
     	new creates a new PML Object and returns the object
     	to the caller. You can optionaly pass in a hash
     	refernece, where the keys are PML variables to set
     	and the values are the values to set those variables
     	to.

METHOD parse
------------

     Arguments:
     	1) PML Object
     	2) Filename or a reference to an array of lines

     Returns:
     	1) True if parse was successful

     Description:
     	parse will parse the file or array that you give
     	it. If there is an error, such as a syntax error,
     	parse will throw an exception via die.  Therefore
     	if you want to catch the exception you should wrap
     	the call to parse in an eval block and check $@.
     	If $@ is true there was and error and the error
     	message can be found in $@.

METHOD execute
--------------

     Arguments:
     	1) PML Object
     	2) A Hash Reference (Optional)

     Returns:
     	1) The text in the file after processing it

     Description:
     	execute will process the file and return the
     	post-processed text.  You can optionaly pass in a
     	reference to a hash, where the keys are PML variables
     	to set and the values are the value to set them
     	to.  This is a good way so talk to your text file.

     You can call execute as many times as you wish.
     Each call will start afresh at the top of the parsed
     file.

METHOD v
--------

     Arguments:
     	1) PML Object

     -- or --

     2) Variable Name

     -- or --

     2) Variable Name
     3) New Value

     -- or --

     2) Hash Reference

     Returns:
     	1) Depends on Arguments, see below.

     Description:
     	The v method allows you to get and set PML variables.
     	There are a few different ways to use v, and we
     	will cover them all.

     Arguments:
     	1) PML Object

     In this case, you call v with only the object, no
     arguments. This will return an array of variable
     names. This is so you can see what variables are
     defined.

     Arguments:
     	1) PML Object
     	2) Variable Name

     This time you give a name of a variable. The v
     method will return the current value of that
     variable, or undef if it is not set.

     Arguments:
     	1) PML Object
     	2) Variable Name
     	3) Value

     Here, you give a variable name and the value to
     set it to. The v method will then set the give
     variable to the value you gave it. It should return
     the same value.

     Arguments:
     	1) PML Object
     	2) Hash Reference

     To limit method calls, you can give a hash reference
     where the keys are the variable to set and the
     values are the value to set those variables to.
     Returns 1.

METHOD parse_after
------------------

     Arguments:
     	1) PML Object
     	2) Regular Expression String or Object

     Returns:
     	1) Nothing

     Description:
     	Used before the call to parse, this method will
     	effect when parsing will start. When you call the
     	parse method, it will search for the given regex,
     	when that regex matches, parsing will begin on the
     	NEXT line.

CLASS METHOD register
---------------------

     Arguments:
     	1) Class ie PML->register(...)
     	2) A Hash, keys are described below

     Returns:
     	1) An ID number to refer to your token

     Description:
     	The register function is used to extend the PML
     	syntax. You register a callback for a new PML
     	function. When parsing the text, PML will call your
     	parser-callback to assist parsing. When executing,
     	PML will call your token-callback to process the
     	token created by your parser-callback.

     Here is what you should pass to register:

     parse => A callback. Defaults to using the
              builtin autoparser
     token => A callback. You must give this.
     name  => The name of the new PML function to add.
     type  => See Types below

     		Callbacks:

     A callback is a reference to a subroutine like this:
     	\&myfunc  -- or -- sub{}

     It can also be a reference to an array,
     where the first element is a reference to
     a subroutine and the remaining elements
     are passed to the subroutine as arguemnts
     after the standard arguments.

     Types:

     The types are constants in PML.pm.

     PML->ARG_ONLY   This means that your new
                     function will only take
                     arguments, just like the
                     builtin @set function.

     PML->BLOCK_ONLY This means that your new
                     function only takes a block
                     just like the builtin @perl
                     function.

     PML->ARG_BLOCK  This means that your new
                     function takes arguments
                     and a block, just like the
                     builtin @if function.

METHOD warning
--------------

     Arguments:
     	1) PML Object
     	2) Boolean Flag (Optional)

     Returns:
     	1) Current Warning Flag

     Description:
     	The warning method will set the warning flag to
     	the one given, if one was given. It always returns
     	the current value. If the flag is true, PML will
     	print warnings to STDERR.

METHOD use_stderr
-----------------

     Arguments:
     	1) PML Object
     	2) True to allow use of stderr, false to disallow

     Returns:
     	1) Nothing

     Description:
     	Sets the use_stderr flag for this object

SYNOPSIS
========

   Quick Usage

DESCRIPTION
===========

   What does it do?

OPTIONS
=======

   Long Usage

EXAMPLES
========

   Example usage

SEE ALSO
========

   perl(1)

AUTHOR
======

   Peter J Jones pjones@cpan.org

=head1 SYNOPSIS Quick Usage
***************************

NAME Headers.pm
===============

SYNOPSIS Quick Usage
====================

DESCRIPTION What does it do?
============================

OPTIONS Long Usage
==================

EXAMPLES Example usage
======================

SEE ALSO perl(1)
================

AUTHOR Peter J Jones pjones@cpan.org
====================================

SYNOPSIS
========

   Quick Usage

DESCRIPTION
===========

   What does it do?

OPTIONS
=======

   Long Usage

EXAMPLES
========

   Example usage

SEE ALSO
========

   perl(1)

AUTHOR
======

   Peter J Jones pjones@cpan.org

Graph Plotting Module for Perl 5
********************************

NAME
====

   PNGgraph - Graph Plotting Module for Perl 5

SYNOPSIS
========

   use PNGgraph::moduleName;

DESCRIPTION
===========

   *PNGgraph* is a *perl5* module to create and display PNG output for a
graph.  The following classes for graphs with axes are defined:

`PNGgraph::lines'
     Create a line chart.

`PNGgraph::bars'
     Create a bar chart.

`PNGgraph::points'
     Create an chart, displaying the data as points.

`PNGgraph::linespoints'
     Combination of lines and points.

`PNGgraph::area'
     Create a graph, representing the data as areas under a line.

`PNGgraph::mixed'
     Create a mixed type graph, any combination of the above. At the moment
     this is fairly limited. Some of the options that can be used with some
     of the individual graph types won't work very well. Multiple bar
     graphs in a mixed graph won't display very nicely.

   Additional types:

`PNGgraph::pie'
     Create a pie chart.

EXAMPLES
========

   See the samples directory in the distribution.

USAGE
=====

   Fill an array of arrays with the x values and the values of the data
sets.  Make sure that every array is the same size, otherwise *PNGgraph*
will complain and refuse to compile the graph.

     @data = (
         ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"],
         [    1,    2,    5,    6,    3,  1.5,    1,     3,     4]
         [ sort { $a <=> $b } (1, 2, 5, 6, 3, 1.5, 1, 3, 4) ]
     );

   If you don't have a value for a point in a certain dataset, you can use
undef, and *PNGgraph* will skip that point.

   Create a new *PNGgraph* object by calling the new operator on the graph
type you want to create (*chart* is *bars, lines, points, linespoints* or
*pie*).

     $my_graph = new PNGgraph::chart( );

   Set the graph options.

     $my_graph->set(
         x_label           => 'X Label',
         y_label           => 'Y label',
         title             => 'Some simple graph',
         y_max_value       => 8,
         y_tick_number     => 8,
         y_label_skip      => 2
     );

   Output the graph

     $my_graph->plot_to_png( "sample01.png", \@data );

METHODS AND FUNCTIONS
=====================

Methods for all graphs
----------------------

new PNGgraph::chart([width,height])
     Create a new object $graph with optional width and heigth.  Default
     width = 400, default height = 300. *chart* is either *bars, lines,
     points, linespoints, area* or *pie*.

set_text_clr( *colour name* )
     Set the colour of the text. This will set the colour of the titles,
     labels, and axis labels to *colour name*. Also see the options
     *textclr*, *labelclr* and *axislabelclr*.

set_title_font( fontname )
     Set the font that will be used for the title of the chart.  Possible
     choices are defined in GD.  *NB.* If you want to use this
     function, you'll need to use GD. At some point I'll
     rewrite this, so you can give this a number from 1 to 4, or a string
     like 'large' or 'small'. On the other hand, I might not, if Thomas
     Boutell decides to support more fonts.

plot( *\@data* )
     Plot the chart, and return the PNG data.

plot_to_png( filename, *\@data* )
     Plot the chart, and write the PNG data to filename.

set( key1 => value1, key2 => value2 .... )
     Set chart options. See OPTIONS section.

Methods for Pie charts
----------------------

set_label_font( fontname )
set_value_font( fontname )
     Set the font that will be used for the label of the pie or the values
     on the pie.  Possible choices are defined in GD.  See also
     *set_title_font*.

Methods for charts with axes.
-----------------------------

set_x_label_font ( *font name* )
set_y_label_font ( *font name* )
set_x_axis_font ( *font name* )
set_y_axis_font ( *font name* )
     Set the font for the x and y axis label, and for the x and y axis
     value labels.  See also *set_title_font*.

OPTIONS
=======

Options for all graphs
----------------------

pngx, pngy
     The width and height of the png file in pixels Default: 400 x 300.
     *NB* At the moment, these are read-only options. If you want to set
     the size of a graph, you will have to do that with the new method.

t_margin, b_margin, l_margin, r_margin
     Top, bottom, left and right margin of the PNG. These margins will be
     left blank.  Default: 0 for all.

logo
     Name of a logo file. This should be a PNG file.  Default: no logo.

logo_resize, logo_position
     Factor to resize the logo by, and the position on the canvas of the
     logo. Possible values for logo_position are 'LL', 'LR', 'UL', and
     'UR'.  (lower and upper left and right).  Default: 'LR'.

transparent
     If set to a true value, the produced PNG will have the background
     colour marked as transparent (see also option *bgclr*).  Default: 1.

interlaced
     If set to a true value, the produced PNG will be interlaced.
     Default: 1.

bgclr, fgclr, textclr, labelclr, axislabelclr, accentclr
     Background, foreground, text, label, axis label and accent colours.

dclrs (short for datacolours)
     This controls the colours for the bars, lines, markers, or pie slices.
     This should be a reference to an array of colour names as defined in
     PNGgraph/colour, (`perldoc PNGgraph::colour'
     for the names available).

          $graph->set( dclrs => [ qw(green pink blue cyan) ] );

     The first (fifth, ninth) data set will be green, the next pink, etc.
     Default: [ qw(lred lgreen lblue lyellow lpurple cyan lorange) ]

Options for graphs with axes.
-----------------------------

   options for *bars*, lines, points, *linespoints* and area charts.

long_ticks, tick_length
     If *long_ticks* is a true value, ticks will be drawn the same length
     as the axes.  Otherwise ticks will be drawn with length
     *tick_length*. if *tick_length* is negative, the ticks will be drawn
     outside the axes.  Default: long_ticks = 0, tick_length = 4.

x_ticks
     If x_ticks is a true value, ticks will be drawm for the x axis.
     These ticks are subject to the values of *long_ticks* and
     *tick_length*.  Default: 1.

y_tick_number
     Number of ticks to print for the Y axis. Use this, together with
     *y_label_skip* to control the look of ticks on the y axis.  Default:
     5.

y_number_format
     This can be either a string, or a reference to a subroutine. If it is
     a string, it will be taken to be the first argument to an sprintf,
     with the value as the second argument:

          $label = sprintf( $s->{y_number_format, $value );

     If it is a code reference, it will be executed with the value as the
     argument:

          $label = &{$s->{y_number_format}}($value);

     This can be useful, for example, if you want to reformat your values
     in currency, with the - sign in the right spot. Something like:

          sub y_format
          {
              my $value = shift;
              my $ret;

          if ($value >= 0)
          {
              $ret = sprintf("\$%d", $value * $refit);
          }
          else
          {
              $ret = sprintf("-\$%d", abs($value) * $refit);
          }

          return $ret;
              }

          $my_graph->set( 'y_number_format' => \&y_format );

     (Yes, I know this can be much shorter and more concise)

     Default: undef.

x_label_skip, y_label_skip
     Print every x_label_skipth number under the tick on the x axis, and
     every *y_label_skip*th number next to the tick on the y axis.
     Default: 1 for both.

x_all_ticks
     Force a print of all the x ticks, even if x_label_skip is set to a
     value Default: 0.

x_label_position
     Controls the position of the X axis label (title). The value for this
     should be between 0 and 1, where 0 means aligned to the left, 1 means
     aligned to the right, and 1/2 means centered.  Default: 3/4

y_label_position
     Controls the position of both Y axis labels (titles). The value for
     this should be between 0 and 1, where 0 means aligned to the bottom, 1
     means aligned to the top, and 1/2 means centered.  Default: 1/2

x_labels_vertical
     If set to a true value, the X axis labels will be printed vertically.
     This can be handy in case these labels get very long.  Default: 0.

x_plot_values, y_plot_values
     If set to a true value, the values of the ticks on the x or y axes
     will be plotted next to the tick. Also see *x_label_skip,
     y_label_skip*.  Default: 1 for both.

box_axis
     Draw the axes as a box, if true.  Default: 1.

two_axes
     Use two separate axes for the first and second data set. The first
     data set will be set against the left axis, the second against the
     right axis. If this is set to a true value, trying to use anything
     else than 2 datasets will generate an error.  Default: 0.

zero_axis
     If set to a true value, the axis for y values of 0 will always be
     drawn. This might be useful in case your graph contains negative
     values, but you want it to be clear where the zero value is. (see also
     zero_axis_only and *box_axes*).  Default: 0.

zero_axis_only
     If set to a true value, the zero axis will be drawn (see zero_axis),
     and no axis at the bottom of the graph will be drawn.  The labels for
     X values will be placed on the zero exis.  Default: 0.

y_max_value, y_min_value
     Maximum and minimum value displayed on the y axis. If two_axes is a
     true value, then y1_min_value, y1_max_value (for the left axis), and
     y2_min_value, y2_max_value (for the right axis) take precedence over
     these.

     The range (y_min_value..y_max_value) has to include all the values of
     the data points, or *PNGgraph* will die with a message.

     For bar and area graphs, the range (y_min_value..y_max_value) has to
     include 0. If it doesn't, the values will be adapted before attempting
     to draw the graph.

     Default: Computed from data sets.

axis_space
     This space will be left blank between the axes and the text.
     Default: 4.

overwrite
     If set to 0, bars of different data sets will be drawn next to each
     other. If set to 1, they will be drawn in front of each other. If set
     to 2 they will be drawn on top of each other.  Default: 0.

     If you have negative values in your data sets, setting overwrite to 2
     might produce odd results. Of course, the graph itself would be quite
     meaningless, because overwrite = 2 is meant to show some cumulative
     effect.

Options for graphs with a numerical X axis
------------------------------------------

   First of all: PNGgraph does not support numerical x axis the way it
should. Data for X axes should be equally spaced. That understood: There
is some support to make the printing of graphs with numerical X axis
values a bit better, thanks to Scott Prahl. If the option x_tick_number is
set to a defined value, PNGgraph will attempt to treat the X data as
numerical.

   Extra options are:

x_tick_number
     If set to *'auto'*, PNGgraph will attempt to format the X axis in a
     nice way, based on the actual X values. If set to a number, that's the
     number of ticks you will get. If set to undef, PNGgraph will treat X
     data as labels.  Default: undef.

x_min_value, x_max_value
     The minimum and maximum value to use for the X axis.  Default:
     computed.

x_number_format
     See y_number_format

x_label_skip
     See y_label_skip

Options for graphs with bars
----------------------------

bar_spacing
     Number of pixels to leave open between bars. This works well in most
     cases, but on some platforms, a value of 1 will be rounded off to 0.
     Default: 0

Options for graphs with lines
-----------------------------

line_types
     Which line types to use for lines and *linespoints* graphs. This
     should be a reference to an array of numbers:

          $graph->set( line_types => [3, 2, 4] );

     Available line types are 1: solid, 2: dashed, 3: dotted, 4:
     dot-dashed.

     Default: [1] (always use solid)

line_type_scale
     Controls the length of the dashes in the line types. default: 6.

line_width
     The width of the line used in lines and *linespoints* graphs, in
     pixels.  Default: 1.

Options for graphs with points
------------------------------

markers
     This controls the order of markers in points and *linespoints*
     graphs.  This should be a reference to an array of numbers:

          $graph->set( markers => [3, 5, 6] );

     Available markers are: 1: filled square, 2: open square, 3: horizontal
     cross, 4: diagonal cross, 5: filled diamond, 6: open diamond, 7:
     filled circle, 8: open circle.

     Default: [1,2,3,4,5,6,7,8]

marker_size
     The size of the markers used in points and *linespoints* graphs, in
     pixels.  Default: 4.

Options for mixed graphs
------------------------

types
     A reference to an array with graph types, in the same order as the
     data sets. Possible values are:

          $graph->set( types => [qw(lines bars points area linespoints)] );
          $graph->set( types => ['lines', undef, undef, 'bars'] );

     values that are undefined or unknown will be set to default_type.

     Default: all set to default_type

default_type
     The type of graph to draw for data sets that either have no type set,
     or that have an unknown type set.

     Default: lines

Graph legends (axestype graphs only)
------------------------------------

   At the moment legend support is minimal.

   Methods

set_legend( *@legend_keys* );
     Sets the keys for the legend. The elements of @legend_keys correspond
     to the data sets as provided to plot() or *plot_to_png()*.

     If a key is undef or an empty string, the legend entry will be
     skipped.

set_legend_font( *font name* );
     Sets the font for the legend text (see also *set_title_font*).
     Default: GD::gdTinyFont.

   Options

legend_placement
     Where to put the legend. This should be a two letter key of the form:
     'B[LCR]|R[TCB]'. The first letter sipngies the placement (Bottom or
     Right), and the second letter signifies the alignment (Left, Right,
     Center, Top, or Bottom).  Default: 'BC'

     If the legend is placed at the bottom, some calculations will be made
     to ensure that there is some 'intelligent' wrapping going on. if the
     legend is placed at the right, all entries will be placed below each
     other.

legend_spacing
     The number of pixels to place around a legend item, and between a
     legend 'marker' and the text.  Default: 4

legend_marker_width, legend_marker_height
     The width and height of a legend 'marker' in pixels.  Defaults: 12, 8

lg_cols
     If you, for some reason, need to force the legend at the bottom to
     have a specific number of columns, you can use this.  Default:
     computed

Options for pie graphs
----------------------

  1. If set to a true value, the pie chart will be drawn with a 3d look.
     Default: 1.

  2. pie_height The thickness of the pie when 3d is true.  Default: 0.1 x
     PNG y size.

  3. start_angle The angle at which the first data slice will be
     displayed, with 0 degrees being "6 o'clock".  Default: 0.

NOTES
=====

   All references to colours in the options for this module have been
shortened to clr. The main reason for this was that I didn't want to
support two spellings for the same word ('colour' and 'color')

   Wherever a colour is required, a colour name should be used from the
package PNGgraph/colour.
`perldoc PNGgraph::colour' should give you the documentation for that
module, containing all valid colour names. I will probably change this to
read the systems rgb.txt file if it is available.

   Wherever a font name is required, a font from GD, should be
used.

AUTHOR
======

   Martien Verbruggen ported to GD 1.20+ (PNG) by Steve Bonds

Contact info
------------

   for PNGgraph questions: email: sbonds@agora.rdrop.com

   for GIFgraph questions: email: mgjv@comdyn.com.au

Copyright
---------

   Copyright (C) 1995-1998 Martien Verbruggen.  Copyright (C) 1999 Steve
Bonds.  All rights reserved.  This package is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

Colour manipulation routines for use with PNGgraph
**************************************************

NAME
====

   Colour - Colour manipulation routines for use with PNGgraph

SYNOPSIS
========

   use PNGgraph::colour qw( :colours :lists :files );

DESCRIPTION
===========

   The *Colour* Package provides a few routines to convert some colour
names to RGB values. Also included are some functions to calculate the hue
and luminance of the colours, mainly to be able to sort them.

   The :colours tags can be used to import the *_rgb*, *_hue*, and
*_luminance* functions, the :lists tag for *colour_list* and
*sorted_colour_list*, and the :files tag exports the *read_rgb* function.

FUNCTIONS
=========

Colour::colour_list( *number of colours* )
     Returns a list of *number of colours* colour names known to the
     package.

Colour::sorted_colour_list( *number of colours* )
     Returns a list of *number of colours* colour names known to the
     package, sorted by luminance or hue.  *NB.* Right now it always sorts
     by luminance. Will add an option in a later stage to decide sorting
     method at run time.

Colour::_rgb( *colour name* )
     Returns a list of the RGB values of *colour name*.

Colour::_hue( *R,G,B* )
     Returns the hue of the colour with the specified RGB values.

Colour::_luminance( *R,G,B* )
     Returns the luminance of the colour with the specified RGB values.

Colour::read_rgb( `file name' )
     Reads in colours from a rgb file as used by the X11 system.

     Doing something like:

          use PNGgraph::bars;
          use PNGgraph::colour;

          PNGgraph::colour::read_rgb("rgb.txt") or die "cannot read colours";

     Will allow you to use any colours defined in rgb.txt in your graph.

PREDEFINED COLOUR NAMES
=======================

   white, lgray, gray, dgray, black, lblue, blue, dblue, gold, lyellow,
yellow, dyellow, lgreen, green, dgreen, lred, red, dred, lpurple, purple,
dpurple, lorange, orange, pink, dpink, marine, cyan, lbrown, dbrown.

event driven state machines
***************************

NAME
====

   POE - event driven state machines

SYNOPSIS
========

     #!/usr/bin/perl -w
     use strict;

     # Use POE!
     use POE;

     # Every machine is required to have a special state, _start, which
     # is used to the machine it has been successfully instantiated.
     # $_[KERNEL] is a reference to the process' global POE::Kernel
     # instance; $_[HEAP] is the session instance's local storage;
     # $_[SESSION] is a reference to the session instance itself.

     sub state_start {
       my ($kernel, $heap, $session) = @_[KERNEL, HEAP, SESSION];
       print "Session ", $session->ID, " has started.\n";
       $heap->{count} = 0;
       $kernel->yield('increment');
     }

     sub state_increment {
       my ($kernel, $heap, $session) = @_[KERNEL, HEAP, SESSION];
       print "Session ", $session->ID, " counted to ", ++$heap->{count}, ".\n";
       $kernel->yield('increment') if $heap->{count} < 10;
     }

     # The _stop state is special but not required.  POE uses it to tell
     # a session instance that it is about to be destroyed.  Stop states
     # contain last-minute resource cleanup, which often isn't necessary
     # since POE destroys $_[HEAP], and resource destruction cascades
     # down from there.

     sub state_stop {
       print "Session ", $_[SESSION]->ID, " has stopped.\n";
     }

     # Start ten instances of a session.  POE::Session constructors map
     # state names to the code that handles them.

     for (0..9) {
       POE::Session->create(
         inline_states =>
           { _start    => \&state_start,
             increment => \&state_increment,
             _stop     => \&state_stop,
           }
       );
     }

     # Start the kernel, which will run as long as there are sessions.

     $poe_kernel->run();
     exit;

DESCRIPTION
===========

   POE is an acronym of "Persistent Object Environment".  It originally
was designed as the core of a persistent object server where clients and
autonomous objects could interact in a sort of "agent space".  It was, in
this regard, very much like a MUD.  Evolution, however, seems to have
other plans.

   POE's heart is a framework for event driven state machines.  This heart
has two chambers: an event dispatcher and state machines that are driven
by dispatched events.  The modules are, respectively, POE::Kernel and
POE::Session.

   The remainder of POE consists of modules that help perform high-level
functions.  For example, POE::Wheel::ReadWrite encapsulates the logic for
select-based I/O.  Module dependencies always point towards lower level
code.  POE::Kernel and POE::Session, being at the lowest level, need none
of the others.  Since they are always required, they will be used whenever
POE itself is.

USING POE
=========

   Using POE modules can be pretty tedious.  Consider this example, which
pulls in the necessary modules for a line-based TCP server:

     use POE::Kernel;
     use POE::Session;
     use POE::Wheel::SocketFactory;
     use POE::Wheel::ReadWrite;
     use POE::Filter::Line;
     use POE::Driver::SysRW;

   Using POE directly optimizes this for laziness in two ways.  First, it
brings in POE::Kernel and POE::Session for you.  Second, subsequent
modules can be passed as parameters to the POE module without the "POE::"
prefix.

   The preceding example can then be written as:

     use POE qw( Wheel::SocketFactory Wheel::ReadWrite
                 Filter::Line Driver::SysRW
               );

WRITING POE PROGRAMS
====================

   Basic POE programs consist of four parts.

   * Preliminary program setup

     This is the usual overhead for writing a Perl program: a #! line,
     perhaps some use statements to import things, and maybe some global
     variables or configuration constants.  It's all pretty standard stuff.

          #!/usr/bin/perl -w
          use strict;
          use POE;

   * Define the program's states

     Here's where the code for each state is defined.  In a procedural
     program, it would be where subroutines are defined.  This part is
     optional in smaller programs, since states may be defined as inline
     anonymous coderefs when machines are instantiated.

          sub state_start {
            ...
          }

          sub state_increment {
            ...
          }

          sub state_stop {
            ...
          }

   * Instantiate initial machines

     POE's kernel stops when there are no more sessions to generate or
     receive transition events.  A corolary to this rule: The kernel won't
     even begin unless a session first has been created.  The SYNOPSIS
     example starts ten state machines to illustrate how POE may simulate
     threads through cooperative timeslicing.  In other words, several
     things may be run "concurrently" by taking a little care in their
     design.

          for (0..9) {
            POE::Session->create(
              inline_states =>
                { _start    => \&state_start,
                  increment => \&state_increment,
                  _stop     => \&state_stop,
                }
            );
          }

   * Start the kernel

     Almost nothing will happen until the event dispatcher starts.  A
     corolary to this rule: Nothing of much consequence will happen until
     the kernel is started.  As was previously mentioned, the kernel won't
     return until everything is finished.  This usually (but not
     necessarily) means the entire program is done, so it's common to exit
     or otherwise let the program end afterwards.

          $poe_kernel->run();
          exit;

POE's ARCHITECTURE
==================

   POE is built in distinct strata: Each layer requires the ones beneath
it but not the ones above it, allowing programs to use as much code as
they need but no more.  The layers are:

   * Events layer

     This was already discussed earlier.  It consists of an event
     dispatcher, POE::Kernel; POE::Session, which is a generic state
     machine; and POE::NFA, which is a non-deterministic finite automaton.

   * The "Wheels" I/O abstraction

     POE::Wheel is conceptually similar to a virus.  When one is
     instantiated, it injects its code into the host session.  The code
     consists of some unspecified states that perform a particular job.
     Unlike viruses, wheels remove their code when destroyed.

     POE comes with four wheels so far:

        * POE::Wheel::FollowTail

          FollowTail follows the tail of an ever-growing file.  It's
          useful for watching logs or pipes.

        * POE::Wheel::ListenAccept

          ListenAccept performs ye olde non-blocking socket listen and
          accept.  It's depreciated by SocketFactory, which does all that
          and more.

        * POE::Wheel::ReadWrite

          ReadWrite is the star of the POE::Wheel family.  It performs
          buffered I/O on unbuffered, non-blocking filehandles.  It almost
          acts like a Unix stream, only the line disciplines don't yet
          support push and pop.

          ReadWrite uses two other classes to do its dirty work: Driver and
          Filter.  Drivers do all the work, reading and/or writing from
          filehandles.  Filters do all the other work, translating
          serialized raw streams to and from logical data chunks.

          Drivers first:

             * POE::Driver::SysRW

               This is the only driver currently available.  It performs
               sysread and syswrite on behalf of Wheel::ReadWrite.  Other
               drivers, such as SendRecv, are possible, but so far there
               hasn't been a need for them.

          Filters next:

             * POE::Filter::Block

               This filter parses input as fixed-length blocks.  The
               output side merely passes data through unscathed.

             * POE::Filter::HTTPD

               This filter parses input as HTTP requests, translating them
               into HTTP::Request objects.  It accepts responses from the
               program as HTTP::Response objects, serializing them back
               into streamable HTTP responses.

             * POE::Filter::Line

               The Line filter parses incoming streams into lines and
               serializes outgoing lines into streams.  It's very basic.

             * POE::Filter::Reference

               The Reference filter is used for sending Perl structures
               between POE programs.  The sender provides references to
               structures, and Filter::Reference serializes them with
               Storable, FreezeThaw, or a serializer of your choice.  Data
               may optionally be compressed if Zlib is installed.

               The receiving side of this filter takes serialized data and
               thaws it back into perl data structures.  It returns a
               reference to the reconstituted data.

             * POE::Filter::Stream

               Filter::Stream does nothing of consequence.  It passes data
               through without any change.

        * POE::Wheel::SocketFactory

          SocketFactory creates sockets.  When creating connectionless
          sockets, such as UDP, it returns a fully formed socket right
          away.  For connecting sockets which may take some time to
          establish, it returns when a connection finally is made.
          Listening socket factories may return several sockets, one for
          each successfully accepted incoming connection.

POE COMPONENTS
==============

   A POE component consists of one or more state machines that
encapsulates a very high level procedure.  For example,
POE::Component::IRC (not included) performs nearly all the functions of a
fully featured IRC client.  This frees programmers from the tedium of
working directly with the protocol, instead letting them focus on what the
client will actually do.

   POE comes with only one core component, POE::Component::Server::TCP.
It is a thin wrapper around POE::Wheel::SocketFactory, providing the wheel
with some common default states.  This reduces the overhoad needed to
create TCP servers to its barest minimum.

   To-do: Publish a POE component SDK, which should amonut to little more
than some recommended design guidelines and MakeMaker templates for CPAN
publication.

Support Modules
===============

   Finally, there are some modules which aren't directly used but come
with POE.  These include POE::Preprocessor and the virtual base classes:
POE::Component, POE::Driver, POE::Filter and POE::Wheel.

   POE::Preprocessor is a macro processor.  POE::Kernel and POE::Session
use it to inline common code, making the modules faster and easier to
maintain.  There seem to be two drawbacks, however: Code is more difficult
to examine from the Perl debugger, and programs take a little longer to
start.  The compile-time penalty is negligible in the types of
long-running programs POE excels at, however.

   POE::Component exists merely to explain the POE::Component subclasses,
as do POE::Driver, POE::Filter and POE::Wheel.  Their manpages also
discuss options and methods which are common across all their subclasses.

ASCII ART
=========

   The ASCII art is gone.  If you want pretty pictures, contact the
author.  He's been looking for excuses to sit down with a graphics program.

OBJECT LAYER
============

   The object layer has fallen into disrepair again, and the author is
considering splitting it out as a separate Component.  If you've been
looking forward to it, let him know so he'll have an excuse to continue
with it.

SAMPLE PROGRAMS
===============

   The POE contains 28 sample programs as of this writing.  Please be
advised that some of them date from the early days of POE's development
and may not exhibit the best coding practices.

   The samples reside in the archive's ./samples directory.  The author is
considering moving them to a separate distribution to cut back on the
archive's size, but please contact him anyway if you'd like to see
something that isn't there.

Tutorials
---------

   POE's documentation is merely a reference.  It may not explain why
things happen or how to do things with POE.  The tutorial samples are
meant to compensate for this in some small ways.

   * tutorial-chat.perl

     This is the first and only tutorial to date.  It implements a simple
     chat server (not web chat) with rambling narrative comments.

Events Layer Examples
---------------------

   These examples started life as test programs, but the t/*.t type tests
are thousands of times terrificer.  Now the examples exist mainly as just
examples.

   * create.perl

     This program is essentially the same as sessions.perl, but it uses the
     newer POE::Session->create constructor rather than the original
     POE::Session->new one.

   * forkbomb.perl

     The "forkbomb" test doesn't really use fork, but it applies the
     fork-til-you-puke concept to POE's sessions.  Every session starts two
     more and exits.  It has a 200 session limit to keep it from eating
     resources forever.

   * names.perl

     The "names" test demonstrates two concepts: how to reference sessions
     by name, and how to communicate between sessions with an asynchronous
     ENQ/ACK protocol.

   * objmaps.perl

     This is a version of objsessions.perl that maps states to differently
     named object methods.

   * objsessions.perl

     This program is essentially the same as sessions.perl, but it uses
     object methods as states instead of inline coderefs.

   * packagesessions.perl

     This program is essentially the same as sessions.perl, but it uses
     package methods as states instead of inline coderefs.

   * queue.perl

     In this example, a single session is created to manage others beneath
     it.  The main session keeps a pool of children to perform asynchronous
     tasks.  Children stop as their tasks are completed, so the job queue
     controller spawns new ones to continue the work.  The pool size is
     limited to constrain the example's resource use.

   * selects.perl

     The "selects" example shows how to use POE's interface to select(2).
     It creates a simple chargen server and a client to visit it.  The
     client will disconnect after receiving a few lines from the server.
     The server will remain active until it receives SIGINT, and it will
     accept further socket connections.

   * sessions.perl

     This program is a basic example of Session construction, destruction
     and maintenance.  It's much more system friendly than forkbomb.perl.

   * signals.perl

     The "signals" example shows how sessions can watch for signals.  It
     creates two sessions that wait for signals and periodically post soft
     signals to themselves.  Soft signals avoid the underlying operating
     system, posting signal events directly through POE.  This also allows
     simulated and fictitious signals.

I/O Layer Examples
------------------

   These examples show how to use the Wheels abstraction.

   * fakelogin.perl

     The "fakelogin" example tests Wheels' ability to change the events
     they emit.  The port it listens on can be specified on the command
     line, and it listens on port 23 by default.

   * filterchange.perl

     This example tests POE::Wheel::ReadWrite's ability to change the
     filter it's using while it runs.

   * followtail.perl

     This program shows how to use POE::Wheel::FollowTail, a read-only
     wheel that follows the end of an ever-growing file.

     It creates 21 sessions: 10 that generate fictitious log files, 10 that
     follow the ends of these logs, and one timer loop to make sure none of
     the other 20 are blocking.  SIGINT will cause the program to clean up
     its /tmp files and stop.

   * httpd.perl

     This is a test of the nifty POE::Filter::HTTPD module.  The author can
     say it's nifty because he didn't write it.  The sample will try
     binding to port 80 of INADDR_ANY, but it can be given a new port on
     the command line.

   * proxy.perl

     This is a simple TCP port forwarder.

   * ref-type.perl

     The "ref-type" sample shows how POE::Filter::Reference can use
     specified serialization methods.  It's part of Philip Gwyn's work on
     POE::Component::IKC, an XML based RPC package.

   * refsender.perl and refserver.perl

     These samples use POE::Filter::Reference to pass copies of blessed and
     unblessed data between processes.  The standard Storable caveats (such
     as its inability to freeze and thaw coderefs) apply.

     refserver.perl should be run first, then refsender.  Check refserver's
     STDOUT to see what it received.

   * thrash.perl

     This is a harsh wheel test.  It sets up a simple TCP daytime server
     and a pool of clients within the same process.  The clients
     continually visit the server, creating and destroying several sockets
     a second.  The test will run faster (and thus be harsher on the
     system) if it is split into two processes.

   * udp.perl

     The "udp" sample shows how to create UDP sockets with IO::Socket and
     use them in POE.  It was a proof of concept for the SocketFactory
     wheel's UDP support.

   * watermarks.perl

     High and low watermarks are a recent addition to the ReadWrite wheel.
     This program revisits the author's good friend, the chargen server,
     this time implementing flow control.

     Seeing it in action requires a slow client.  Telnet or other raw TCP
     clients may work, especially if they are running at maximum niceness.

   * wheels.perl

     This program is a basic rot13 server.  It was used as an early test
     program for the whole Wheel abstraction's premise.

   * wheels2.perl

     The "wheels2" sample shows how to use separate input and output
     filehandles with a wheel.  It's a simple tcp socket client, piping
     betwene a socket and stdio.  Stdio is in cooked mode, with all its
     caveats.

Object Layer Examples
---------------------

   As was previously said, the object layer has fallen once again into
disrepair.  However, the olayer.perl sample program illustrates its
current state.

Proofs of Concepts
------------------

   These programs are prototypes for strange and wonderful concepts.  They
push POE's growth by stretching its capabilities to extrems and seeing
where it hurts.

   * preforkedserver.perl

     This example shows how to write pre-forking servers with POE.  It
     tends to dump core after a while, however, due signal issues in Perl,
     so it's not recommended as an example of a long running server.

     One work-around is to comment out the yield('_stop') calls (there are
     two).  These were added to cycle child servers.  The idea was borrowed
     from Apache, which only did this to thwart runaway children.  POE
     shouldn't leak memory, so churning the children shouldn't be needed.

     Still, it is a good test for one of POE's weaknesses.  This thorn in
     the author's side will remain enabled.

   * tk.perl

     The "tk" example is a prototype of POE's Tk support.  It sets up a Tk
     main window populated with some buttons and status displays.  The
     buttons and displays demonstrate FIFO, alarm and file events in the Tk
     environment.

COMPATIBILITY ISSUES
====================

   POE has tested favorably on as many Perl versions as the author can
find or harass people into trying.  This includes Linux, FreeBSD, OS/2 and
at least one unspecified version of Windows.  As far as I can tell, nobody
ever has tried it on any version of MacOS.

   POE has been tested with Perl versions as far back as 5.004_03 and as
recent as 5.6.0.  The CPAN testers are a wonderful bunch of people who
have dedicated resources to running new modules on a variety of platforms.
The latest POE tests are visible at
<http://testers.cpan.org/search?request=dist&dist=POE>.  Thanks, people!

   Please let the author know of breakage or success that hasn't been
covered already.  Thanks!

   Specific issues:

   * Various Unices

     No known problems.

   * OS/2

     No known problems.

   * Windows

     Windows support lapsed in version 0.0806 when I took out some code I
     wasn't sure was working.  Well, it was, and removing it broke POE on
     Windows.

     Douglas Couch reported that POE worked with the latest stable
     ActivePerl prior to version 5.6.0-RC1.  He said that RC1 supported
     fork and other Unix compatibilities, but it still seemed like beta
     level code.  I hope this changed with the release of 5.6.0-GA.

     Douglas writes:

          I've done some preliminary testing of the 0.0903 version and the
          re-addition of the Win32 support seems to be a success.  I'll do
          some more intensive testing in the next few days to make sure
          nothing else is broken that I haven't missed.

     And later:

          After testing out my own program and having no problems with the
          newest version (with Win32 support), I thought I'd test out some of
          the samples and relay my results.

          filterchange.perl and preforkedserver.perl both contain fork
          commands which are still unsupported by ActiveState's port of Perl,
          so they were both unsuccessful.  (this was anticipated for anything
          containing fork)

          ref-type.perl, refsender.perl, thrash.perl and wheels2.perl all ran
          up against the same unsupported POSIX macro.  According to the error
          message, my vendor's POSIX doesn't support the macro EINPROGRESS.

          [EINPROGRESS is fixed as of version 0.1003; see the Changes]

          Other than those particular problems all of the other sample scripts
          ran fine.

   * MacOS

     I have heard rumors from MacOS users that POE might work with MacPerl,
     but so far nobody has stepped forward with an actual status report.

SYSTEM REQUIREMENTS
===================

   * Recommendations

     POE would like to see certain functions, but it doesn't strictly
     require them.  For example, the sample programs use fork() in a few
     places, but POE doesn't require it to run.

     If Time::HiRes is present, POE will use it to achieve better accuracy
     in its select timeouts.  This makes alarms and delays more accurate,
     but POE is designed to work without it as well.

     POE includes no XS, and therefore it doesn't require a C compiler.  It
     should work wherever a sufficiently complete version of Perl does.

   * Hard Requirements

     POE requires Filter::Call::Util starting with version 0.1001.  This is
     part of the source filter package, Filter, version 1.18 or later.  The
     dependency is coded into Makefile.PL, and the CPAN shell can fetch and
     install this automatically for you.

     POE uses POSIX system calls and constants for portability.  There
     should be no problems using it on systems that have sufficient POSIX
     support.

     Some of POE's sample programs require a recent IO bundle, but you get
     that for free with recent versions of Perl.

   * Optional Requirements

     If you intend to use Filter::Reference, then you will need either the
     Storable or FreezeThaw module, or some other freeze/thaw package.
     Storable tends to be the fastest, and it's checked first.
     Filter::Reference can also use Compress::Zlib upon request, but it's
     not required.

     *If you intend to pass reference across machines, such as with Philip
     Gwyn's POE::Component::IKC, then be sure that both ends of the
     connection use the same version of the same libraries.  Subtle
     differences in libraries, or even between different versions of the
     same library, can cause mysterious errors when data is reconstituted
     on the receiving end.  When all else fails, upgrade to the latest
     version; this has been known to fix problems between Filter::Reference
     and Storable, for example.*

     Filter::HTTPD requires a small world of modules, including
     HTTP::Status; HTTP::Request; HTTP::Date and URI::URL.  The httpd.perl
     sample program uses Filter::HTTPD, which uses all that other stuff.

     The preforkedserver.perl sample program uses POE::Kernel::fork(),
     which in turn requires the fork() built-in function.  This may or may
     not be available on your planet.

     Other sample programs may require other modules, but the required
     modules aren't required if you don't require those specific modules.

SUPPORT RESOURCES
=================

   These are Internet resources where you may find more information about
POE.

   * The POE Mailing List

     POE has a mailing list at perl.org.  You may subscribe to it by
     sending e-mail:

          To: poe-help@perl.org
          Subject: (anything will do)

          Anything will do for the message body.

     All forms of feedback are welcome.

   * The POE Web Site

     POE has a web site where the latest development snapshot, along with
     the Changes file and other stuff may be found: <http://poe.perl.org/>

SEE ALSO
========

   This is a summary of POE's modules.

   * Events Layer

     POE::Kernel; POE::NFA; POE::Session

   * I/O Layer

     POE::Driver; POE::Driver::SysRW

     POE::Filter; POE::Filter::HTTPD; POE::Filter::Line;
     POE::Filter::Reference; POE::Filter::Stream

     POE::Wheel; POE::Wheel::FollowTail; POE::Wheel::ListenAccept;
     POE::Wheel::ReadWrite; POE::Wheel::SocketFactory

   * Object Layer

     These modules are in limbo at the moment.

     POE::Curator; POE::Object; POE::Repository; POE::Attribute::Array;
     POE::Runtime

   * Components

     POE::Component; POE::Component::Server::TCP

   * Supporting cast

     POE::Preprocessor

BUGS
====

   The Object Layer is still in early design, so it's not documented yet.

   There need to be more automated regression tests in the t/*.t
directory.  Please suggest tests; the author is short on ideas here.

   The documentation is in the process of another revision.  Here is a
progress report:

     POE                          rewritten 2000.05.15
     README                       rewritten 2000.05.16
     POE::Kernel                  rewritten 2000.05.19
     POE::Session                 rewritten 2000.05.21
     POE::Wheel                   rewritten 2000.05.22
     POE::Preprocessor            revised   2000.05.23

     POE::Component               queued
     POE::Component::Server::TCP  queued
     POE::Driver                  queued
     POE::Driver::SysRW           queued
     POE::Filter                  queued
     POE::Filter::Block           queued
     POE::Filter::HTTPD           queued
     POE::Filter::Line            queued
     POE::Filter::Reference       queued
     POE::Filter::Stream          queued
     POE::Wheel::FollowTail       queued
     POE::Wheel::ListenAccept     queued
     POE::Wheel::ReadWrite        queued
     POE::Wheel::SocketFactory    queued

AUTHORS & COPYRIGHT
===================

   POE is the combined effort of more people than I can remember
sometimes.  If I've forgotten someone, please let me know.

   * Addi

     Addi is <e-mail unknown>.

     Addi has tested POE and POE::Component::IRC on the Windows platform,
     finding bugs and testing fixes.  You'll see his name sprinkled
     throughout the Changes file.

   * Artur Bergman

     Artur Bergman is <artur@vogon-solutions.com>.

     Artur has contributed many hours and ideas.  He's also the author of
     Filter::HTTPD and Filter::Reference, as well as bits and pieces
     throughout POE.  His intangible contributions include feedback,
     testing, conceptual planning and inspiration.  POE would never have
     come this far without his support.

   * Douglas Couch

     Douglas Couch is <dscouch@purdue.edu>

     Douglas was the brave soul who stepped forward to offer valuable
     testing on the Windows platforms.  His reports helped get POE working
     on Win32 and are summarized earlier in this document.

   * Philip Gwyn

     Philip Gwyn is <gwynp@artware.qc.ca>.

     Philip extended the Wheels I/O abstraction to allow filters to be
     changed at runtime and provided patches to add the eminently cool
     Kernel and Session IDs.  He also enhanced Filter::Reference to support
     different serialization methods.  His intangible contributions include
     the discovery and/or destruction of several bugs (see the Changes
     file) and a thorough code review around version 0.06.

   * Dave Paris

     Dave Paris is <dparis@w3works.com>.  He often goes by the nickname
     "a-mused".

     Dave tested and benchmarked POE around version 0.05, discovering some
     subtle (and not so subtle) timing problems.  The pre-forking server
     was his idea.  Versions 0.06 and later should scale to higher loads
     because of his work.  His intangible contributions include lots of
     testing and feedback, some of which is visible in the Changes file.

   * Dieter Pearcey is <dieter@bullfrog.perlhacker.org>.  He goes by
     several Japanese nicknames.

     Dieter patched Wheel::FollowTail to be more useful and has contributed
     the basic Filter::Block, along with documentation!

   * Robert Seifer

     Robert Seifer is <e-mail unknown>.  He rotates IRC nicknames
     regularly.

     Robert contributed entirely too much time, both his own and his
     computers, towards the detection and eradication of a memory
     corruption bug that POE tickled in earlier Perl versions.  In the end,
     his work produced a simple compile-time hack that worked around a
     problem relating to anonymous subs, scope and @{} processing.

   * Dennis Taylor

     Dennis Taylor is <dennis@funkplanet.com>.  Dennis has been testing,
     debugging and patching bits here and there, such as Filter::Line which
     he improved by leaps in 0.1102.  He's also the author of
     POE::Component::IRC, which isn't included here but may be found at
     either <http://www.infobot.org/dev/POE/> or
     <http://www.funkplanet.com/POE/>.

   * Others?

     Anyone who has been forgotten, please contact the author.

Author
------

   * Rocco Caputo

     Rocco Caputo is <troc+poe@netrus.net>.  POE is his brainchild.

     Except where otherwise noted, POE is Copyright 1998-2000 Rocco Caputo.
     All rights reserved.  POE is free software; you may redistribute it
     and/or modify it under the same terms as Perl itself.

   Thank you for reading!

POE Stand-Alone Sessions
************************

NAME
====

   POE::Component - POE Stand-Alone Sessions

SYNOPSIS
========

   Varies from component to component.

DESCRIPTION
===========

   POE components are sessions that have been designed as stand-alone
modules.  They tend to be interfaced through POE::Kernel::post() or
call(), but this is not a formal convention.

   The POE::Component namespace was started to provide a place for others
publish their POE modules without requiring coordination with the main POE
distribution.

BUGS
====

   The POE::Component namespace should probably be coordinated, but who
has time for that?

AUTHORS & COPYRIGHTS
====================

   Please see the POE manpage or manpages for specific components.

a fully event-driven IRC client module.
***************************************

NAME
====

   POE::Component::IRC - a fully event-driven IRC client module.

SYNOPSIS
========

     use POE::Component::IRC;

   # Do this when you create your sessions. 'my client' is just a # kernel
alias to christen the new IRC connection with. (Returns # only a true or
false success flag, not an object.)  POE::Component::IRC->new('my client')
or die "Oh noooo! $!";

   # Do stuff like this from within your sessions. This line tells the #
connection named "my client" to send your session the following # events
when they happen.  $kernel->post('my client', 'register', qw(connected msg
public cdcc cping)); # You can guess what this line does.
$kernel->post('my client', 'connect', 	      { Nick     => 'Boolahman',
Server   => 'irc-w.primenet.com', 		Port     => 6669, 		Username => 'quetzal',
Ircname  => 'Ask me about my colon!', } );

DESCRIPTION
===========

   POE::Component::IRC is a POE component (who'd have guessed?) which acts
as an easily controllable IRC client for your other POE components and
sessions. You create an IRC component and tell it what events your session
cares about and where to connect to, and it sends back interesting IRC
events when they happen. You make the client do things by sending it
events. That's all there is to it. Cool, no?

   [Note that using this module requires some familiarity with the details
of the IRC protocol. I'd advise you to read up on the gory details of RFC
1459 <http://cs-pub.bu.edu/pub/irc/support/rfc1459.txt> before you get
started. Keep the list of server numeric codes handy while you program.
Needless to say, you'll also need a good working knowledge of POE, or this
document will be of very little use to you.]

   So you want to write a POE program with POE::Component::IRC? Listen up.
The short version is as follows: Create your session(s) and an alias for a
new POE::Component::IRC client. (Conceptually, it helps if you think of
them as little IRC clients.) In your session's _start handler, send the
IRC client a 'register' event to tell it which IRC events you want to
receive from it. Send it a 'connect' event at some point to tell it to
join the server, and it should start sending you interesting events every
once in a while. If you want to tell it to perform an action, like joining
a channel and saying something witty, send it the appropriate events like
so:

     $kernel->post( 'my client', 'join', '#perl' );
     $kernel->post( 'my client', 'privmsg', '#perl', 'Pull my finger!' );

   The long version is the rest of this document.

METHODS
=======

   Well, OK, there's only actually one, so it's more like "METHOD".

new
     Takes one argument: a name (kernel alias) which this new connection
     will be known by. WARNING: This method, for all that it's named "new"
     and called in an OO fashion, doesn't actually return an object. It
     returns a true or false value which indicates if the new session was
     created or not. If it returns false, check $! for the POE::Session
     error code.

INPUT
=====

   How to talk to your new IRC component... here's the events we'll accept.

Important Commands
------------------

ctcp and ctcpreply
     Sends a CTCP query or response to the nick(s) or channel(s) which you
     specify. Takes 2 arguments: the nick or channel to send a message to
     (use an array reference here to specify multiple recipients), and the
     plain text of the message to send (the CTCP quoting will be handled
     for you).

connect
     Takes one argument: a hash reference of attributes for the new
     connection (see the `SYNOPSIS' in this node section of this doc for an
     example). This event tells the IRC client to connect to a
     new/different server. If it has a connection already open, it'll close
     it gracefully before reconnecting. Possible attributes for the new
     connection are "Server", the server name; "Password", an optional
     password for restricted servers; "Port", the remote port number,
     "LocalAddr", which local IP address on a multihomed box to connect as;
     "LocalPort", the local TCP port to open your socket on; "Nick", your
     client's IRC nickname; "Username", your client's username; and
     "Ircname", some cute comment or something. connect() will supply
     reasonable defaults for any of these attributes which are missing, so
     don't feel obliged to write them all out.

dcc
     Send a DCC SEND or CHAT request to another person. Takes at least two
     arguments: the nickname of the person to send the request to and the
     type of DCC request (SEND or CHAT). For SEND requests, be sure to add
     a third argument for the filename you want to send. Optionally, you
     can add a fourth argument for the DCC transfer blocksize, but the
     default of 1024 should usually be fine.

     Incidentally, you can send other weird nonstandard kinds of DCCs too;
     just put something besides 'SEND' or 'CHAT' (say, "FOO") in the type
     field, and you'll get back "irc_dcc_foo" events when activity happens
     on its DCC connection.

dcc_accept
     Accepts an incoming DCC connection from another host. Takes one
     argument: the magic cookie from an 'irc_dcc_request' event. (See the
     'irc_dcc_request' section below for more details.)

dcc_chat
     Sends lines of data to the person on the other side of a DCC CHAT
     connection. Takes any number of arguments: the magic cookie from an
     'irc_dcc_start' event, followed by the data you wish to send. (It'll
     be chunked into lines by a POE::Filter::Line for you, don't worry.)

dcc_close
     Terminates a DCC SEND or GET connection prematurely, and causes DCC
     CHAT connections to close gracefully. Takes one argument: the magic
     cookie from an 'irc_dcc_start' or 'irc_dcc_request' event.

join
     Tells your IRC client to join a single channel of your choice. Takes
     at least one arg: the channel name (required) and the channel key
     (optional, for password-protected channels).

kick
     Tell the IRC server to forcibly evict a user from a particular
     channel. Takes at least 2 arguments: a channel name, the nick of the
     user to boot, and an optional witty message to show them as they sail
     out the door.

mode
     Request a mode change on a particular channel or user. Takes at least
     one argument: the mode changes to effect, as a single string (e.g.,
     "+sm-p+o"), and any number of optional operands to the mode changes
     (nicks, hostmasks, channel keys, whatever.) Or just pass them all as
     one big string and it'll still work, whatever. I regret that I
     haven't the patience now to write a detailed explanation, but serious
     IRC users know the details anyhow.

nick
     Allows you to change your nickname. Takes exactly one argument: the
     new username that you'd like to be known as.

notice
     Sends a NOTICE message to the nick(s) or channel(s) which you
     specify. Takes 2 arguments: the nick or channel to send a notice to
     (use an array reference here to specify multiple recipients), and the
     text of the notice to send.

part
     Tell your IRC client to leave the channels which you pass to it. Takes
     any number of arguments: channel names to depart from.

privmsg
     Sends a public or private message to the nick(s) or channel(s) which
     you specify. Takes 2 arguments: the nick or channel to send a message
     to (use an array reference here to specify multiple recipients), and
     the text of the message to send.

quit
     Tells the IRC server to disconnect you. Takes one optional argument:
     some clever, witty string that other users in your channels will see
     as you leave. You can expect to get an `irc_disconnect' event shortly
     after sending this.

register
     Takes N arguments: a list of event names that your session wants to
     listen for, minus the "irc_" prefix. So, for instance, if you just
     want a bot that keeps track of which people are on a channel, you'll
     need to listen for JOINs, PARTs, QUITs, and KICKs to people on the
     channel you're in. You'd tell POE::Component::IRC that you want those
     events by saying this:

          $kernel->post( 'my client', 'register', qw(join part quit kick) );

     Then, whenever people enter or leave a channel your bot is on
     (forcibly or not), your session will receive events with names like
     "irc_join", "irc_kick", etc., which you can use to update a list of
     people on the channel.

     Registering for `'all'' will cause it to send all IRC-related events
     to you; this is the easiest way to handle it. See the test script for
     an example.

unregister
     Takes N arguments: a list of event names which you *don't* want to
     receive. If you've previously done a 'register' for a particular event
     which you no longer care about, this event will tell the IRC
     connection to stop sending them to you. (If you haven't, it just
     ignores you. No big deal.)

Not-So-Important Commands
-------------------------

admin
     Asks your server who your friendly neighborhood server administrators
     are. If you prefer, you can pass it a server name to query, instead of
     asking the server you're currently on.

away
     When sent with an argument (a message describig where you went), the
     server will note that you're now away from your machine or otherwise
     preoccupied, and pass your message along to anyone who tries to
     communicate with you. When sent without arguments, it tells the server
     that you're back and paying attention.

info
     Basically the same as the "version" command, except that the server is
     permitted to return any information about itself that it thinks is
     relevant. There's some nice, specific standards-writing for ya, eh?

invite
     Invites another user onto an invite-only channel. Takes 2 arguments:
     the nick of the user you wish to admit, and the name of the channel to
     invite them to.

ison
     Asks the IRC server which users out of a list of nicknames are
     currently online. Takes any number of arguments: a list of nicknames
     to query the IRC server about.

links
     Asks the server for a list of servers connected to the IRC network.
     Takes two optional arguments, which I'm too lazy to document here, so
     all you would-be linklooker writers should probably go dig up the RFC.

motd
     Request the server's "Message of the Day", a document which typically
     contains stuff like the server's acceptable use policy and admin
     contact email addresses, et cetera. Normally you'll automatically
     receive this when you log into a server, but if you want it again,
     here's how to do it. If you'd like to get the MOTD for a server other
     than the one you're logged into, pass it the server's hostname as an
     argument; otherwise, no arguments.

names
     Asks the server for a list of nicknames on particular channels. Takes
     any number of arguments: names of channels to get lists of users for.
     If called without any channel names, it'll tell you the nicks of
     everyone on the IRC network. This is a really big list, so don't do
     this much.

sl
     Sends a raw line of text to the server. Takes one argument: a string
     of a raw IRC command to send to the server. It is more optimal to use
     the events this module supplies instead of writing raw IRC commands
     yourself.

stats
     Returns some information about a server. Kinda complicated and not
     terribly commonly used, so look it up in the RFC if you're curious.
     Takes as many arguments as you please.

time
     Asks the server what time it thinks it is, which it will return in a
     human-readable form. Takes one optional argument: a server name to
     query. If not supplied, defaults to current server.

topic
     Retrieves or sets the topic for particular channel. If called with
     just the channel name as an argument, it will ask the server to
     return the current topic. If called with the channel name and a
     string, it will set the channel topic to that string.

trace
     If you pass a server name or nick along with this request, it asks the
     server for the list of servers in between you and the thing you
     mentioned. If sent with no arguments, it will show you all the servers
     which are connected to your current server.

userhost
     Asks the IRC server for information about particular nicknames. (The
     RFC doesn't define exactly what this is supposed to return.) Takes any
     number of arguments: the nicknames to look up.

users
     Asks the server how many users are logged into it. Defaults to the
     server you're currently logged into; however, you can pass a server
     name as the first argument to query some other machine instead.

version
     Asks the server about the version of ircd that it's running. Takes one
     optional argument: a server name to query. If not supplied, defaults
     to current server.

who
     Lists the logged-on users matching a particular channel name,
     hostname, nickname, or what-have-you. Takes one optional argument: a
     string for it to search for. Wildcards are allowed; in the absence of
     this argument, it will return everyone who's currently logged in (bad
     move). Tack an "o" on the end if you want to list only IRCops, as per
     the RFC.

whois
     Queries the IRC server for detailed information about a particular
     user. Takes any number of arguments: nicknames or hostmasks to ask for
     information about.

whowas
     Asks the server for information about nickname which is no longer
     connected. Takes at least one argument: a nickname to look up (no
     wildcards allowed), the optional maximum number of history entries to
     return, and the optional server hostname to query.

Purely Esoteric Commands
------------------------

oper
     In the exceedingly unlikely event that you happen to be an IRC
     operator, you can use this command to authenticate with your IRC
     server. Takes 2 arguments: your username and your password.

rehash
     Tells the IRC server you're connected to to rehash its configuration
     files. Only useful for IRCops. Takes no arguments.

restart
     Tells the IRC server you're connected to to shut down and restart
     itself.  Only useful for IRCops, thank goodness. Takes no arguments.

sconnect
     Tells one IRC server (which you have operator status on) to connect to
     another. This is actually the CONNECT command, but I already had an
     event called 'connect', so too bad. Takes the args you'd expect: a
     server to connect to, an optional port to connect on, and an optional
     remote server to connect with, instead of the one you're currently on.

summon
     Don't even ask.

wallops
     Another opers-only command. This one sends a message to all currently
     logged-on opers (and +w users); sort of a mass PA system for the IRC
     server administrators. Takes one argument: some clever, witty message
     to send.

OUTPUT
======

   The events you will receive (or can ask to receive) from your running
IRC component. Note that all incoming event names your session will
receive are prefixed by "irc_", to inhibit event namespace pollution.

   If you wish, you can ask the client to send you every event it
generates. Simply register for the event name "all". This is a lot easier
than writing a huge list of things you specifically want to listen for.
FIXME: I'd really like to classify these somewhat ("basic", "oper",
"ctcp", "dcc", "raw" or some such), and I'd welcome suggestions for ways
to make this easier on the user, if you can think of some.

Important Events
----------------

irc_connected
     The IRC component will send an "irc_connected" event as soon as it
     establishes a connection to an IRC server, before attempting to log
     in. ARG0 is the server name.

     NOTE: When you get an "irc_connected" event, this doesn't mean you
     can start sending commands to the server yet. Wait until you receive
     an irc_001 event (the server welcome message) before actually sending
     anything back to the server.

     irc_ctcp_whatever events are generated upon receipt of CTCP messages.
     For instance, receiving a CTCP PING request generates an irc_ctcp_ping
     event, CTCP SOURCE generates an irc_ctcp_source event, blah blah, so
     on and so forth. ARG0 is the nick!hostmask of the sender. ARG1 is the
     channel/recipient name(s). ARG2 is the text of the CTCP message.

     Note that DCCs are handled separately - see the 'irc_dcc_request'
     event, below.

     irc_ctcpreply_whatever messages are just like irc_ctcp_whatever
     messages, described above, except that they're generated when a
     response to one of your CTCP queries comes back. They have the same
     arguments and such as irc_ctcp_* events.

irc_disconnected
     The counterpart to irc_connected, sent whenever a socket connection
     to an IRC server closes down (whether intentionally or
     unintentionally). ARG0 is the server name.

irc_error
     You get this whenever the server sends you an ERROR message. Expect
     this to usually be accompanied by the sudden dropping of your
     connection. ARG0 is the server's explanation of the error.

irc_join
     Sent whenever someone joins a channel that you're on. ARG0 is the
     person's nick!hostmask. ARG1 is the channel name.

irc_kick
     Sent whenever someone gets booted off a channel that you're on. ARG0
     is the kicker's nick!hostmask. ARG1 is the channel name. ARG2 is the
     nick of the unfortunate kickee. ARG3 is the explanation string for the
     kick.

irc_mode
     Sent whenever someone changes a channel mode in your presence, or when
     you change your own user mode. ARG0 is the nick!hostmask of that
     someone. ARG1 is the channel it affects (or your nick, if it's a user
     mode change). ARG2 is the mode string (i.e., "+o-b"). The rest of the
     args (ARG3 .. $#_) are the operands to the mode string (nicks,
     hostmasks, channel keys, whatever).

irc_msg
     Sent whenever you receive a PRIVMSG command that was addressed to you
     privately. ARG0 is the nick!hostmask of the sender. ARG1 is an array
     reference containing the nick(s) of the recipients. ARG2 is the text
     of the message.

irc_nick
     Sent whenever you, or someone around you, changes nicks. ARG0 is the
     nick!hostmask of the changer. ARG1 is the new nick that they changed
     to.

irc_notice
     Sent whenever you receive a NOTICE command. ARG0 is the nick!hostmask
     of the sender. ARG1 is an array reference containing the nick(s) or
     channel name(s) of the recipients. ARG2 is the text of the NOTICE
     message.

irc_part
     Sent whenever someone leaves a channel that you're on. ARG0 is the
     person's nick!hostmask. ARG1 is the channel name.

irc_ping
     An event sent whenever the server sends a PING query to the client.
     (Don't confuse this with a CTCP PING, which is another beast
     entirely. If unclear, read the RFC.) Note that POE::Component::IRC
     will automatically take care of sending the PONG response back to the
     server for you, although you can still register to catch the event for
     informational purposes.

irc_public
     Sent whenever you receive a PRIVMSG command that was sent to a
     channel. ARG0 is the nick!hostmask of the sender. ARG1 is an array
     reference containing the channel name(s) of the recipients. ARG2 is
     the text of the message.

irc_quit
     Sent whenever someone on a channel with you quits IRC (or gets
     KILLed). ARG0 is the nick!hostmask of the person in question. ARG1 is
     the clever, witty message they left behind on the way out.

irc_socketerr
     Sent when a connection couldn't be established to the IRC server. ARG0
     is probably some vague and/or misleading reason for what failed.

All numeric events (see RFC 1459)
     Most messages from IRC servers are identified only by three-digit
     numeric codes with undescriptive constant names like RPL_UMODEIS and
     ERR_NOTOPLEVEL. (Actually, the list of codes in the RFC is kind of
     out-of-date... the list in the back of Net::IRC::Event.pm is more
     complete, and different IRC networks have different and incompatible
     lists. Ack!) As an example, say you wanted to handle event 376
     (RPL_ENDOFMOTD, which signals the end of the MOTD message). You'd
     register for '376', and listen for 'irc_376' events. Simple, no? ARG0
     is the name of the server which sent the message. ARG1 is the text of
     the message.

Somewhat Less Important Events
------------------------------

irc_dcc_chat
     Notifies you that one line of text has been received from the client
     on the other end of a DCC CHAT connection. ARG0 is the connection's
     magic cookie, ARG1 is the nick of the person on the other end, ARG2
     is the port number, and ARG3 is the text they sent.

irc_dcc_done
     You receive this event when a DCC connection terminates normally.
     Abnormal terminations are reported by "irc_dcc_error", below. ARG0 is
     the connection's magic cookie, ARG1 is the nick of the person on the
     other end, ARG2 is the DCC type (CHAT, SEND, GET, etc.), and ARG3 is
     the port number. For DCC SEND and GET connections, ARG4 will be the
     filename, ARG5 will be the file size, and ARG6 will be the number of
     bytes transferred. (ARG5 and ARG6 should always be the same.)

irc_dcc_error
     You get this event whenever a DCC connection or connection attempt
     terminates unexpectedly or suffers some fatal error. ARG0 will be the
     connection's magic cookie, ARG1 will be a string describing the error.
     ARG2 will be the nick of the person on the other end of the
     connection.  ARG3 is the DCC type (SEND, GET, CHAT, etc.). ARG4 is
     the port number of the DCC connection, if any. For SEND and GET
     connections, ARG5 is the filename.

irc_dcc_get
     Notifies you that another block of data has been successfully received
     from to the client on the other end of a DCC SEND connection. ARG0 is
     the connection's magic cookie, ARG1 is the nick of the person on the
     other end, ARG2 is the port number, ARG3 is the filename, ARG4 is the
     total file size, and ARG5 is the number of bytes successfully
     transferred so far.

irc_dcc_request
     You receive this event when another IRC client sends you a DCC SEND or
     CHAT request out of the blue. You can examine the request and decide
     whether or not to accept it here. ARG0 is the nick of the client on
     the other end. ARG1 is the type of DCC request (CHAT, SEND, etc.).
     ARG2 is the port number. ARG3 is a "magic cookie" argument, suitable
     for sending with 'dcc_accept' events to signify that you want to
     accept the connection (see the 'dcc_accept' docs). For DCC SEND and
     GET connections, ARG4 will be the filename, and ARG5 will be the file
     size.

irc_dcc_send
     Notifies you that another block of data has been successfully
     transferred from you to the client on the other end of a DCC SEND
     connection. ARG0 is the connection's magic cookie, ARG1 is the nick of
     the person on the other end, ARG2 is the port number, ARG3 is the
     filename, ARG4 is the total file size, and ARG5 is the number of bytes
     successfully transferred so far.

irc_dcc_start
     This event notifies you that a DCC connection has been successfully
     established. ARG0 is a unique "magic cookie" argument which you can
     pass to 'dcc_chat' or 'dcc_close'. ARG1 is the nick of the person on
     the other end, ARG2 is the DCC type (CHAT, SEND, GET, etc.), and ARG3
     is the port number. For DCC SEND and GET connections, ARG4 will be
     the filename and ARG5 will be the file size.

irc_snotice
     A weird, non-RFC-compliant message from an IRC server. Don't worry
     about it. ARG0 is the text of the server's message.

AUTHOR
======

   Dennis Taylor, <dennis@funkplanet.com>

MAD PROPS
=========

   The maddest of mad props go out to Rocco "dngor" Caputo
<troc@netrus.net>, for inventing something as mind-bogglingly cool as POE,
and to Kevin "oznoid" Lenzo <lenzo@cs.cmu.edu>, for being the attentive
parent of our precocious little infobot on #perl.

   Further props to a few of the studly bughunters who made this module not
suck: Abys <abys@web1-2-3.com>, Addi <addi@umich.edu>, ResDev
<ben@reser.org>, and Roderick <roderick@argon.org>. Woohoo!

SEE ALSO
========

   Net::IRC, RFC 1459, http://www.irchelp.org/,
http://www.newts.org/~troc/poe.html, http://www.cs.cmu.edu/~lenzo/perl/,
http://www.infobot.org/,
http://newyork.citysearch.com/profile?fid=2&id=7104760,
http://www.pobox.com/~schwern/img/fishpants.jpg

Provides IRC moved message & onjoin services
********************************************

NAME
====

   POE::Component::IRC::Onjoin - Provides IRC moved message & onjoin
services

SYNOPSIS
========

   use POE::Component::IRC::Onjoin;

   my $onjoin  = POE::Component::IRC::Onjoin->new (   -nick     =>
'OnJoinBot',   -channel  => '#onjoinbot',   -servers  =>
[qw(token.rhizomatic.net binky.rhizomatic.net)],   -message  => q(Hello!
Just as an fyi, we moved to #blah), );

   $onjoin->engage();

DESCRIPTION
===========

   This module implements a class that provides moved message and onjoin
services as an IRC bot. Based on the configuration parameters passed to it
via it's constructor it will connect to a channel on a server and
immediately send everyone on that channel a message privately. It will
also send the same message to the channel itself publically at the
specified interval. All users joining the channel thereafter will also
recieve the message.

   An useful example of this would be when a channel moves either to a new
channel or network, you would be able to effectively inform anyone
connecting to the old channel about the new one.

   Class methods:

     new (constructor)

     Takes the following arguments:

     PARAMETER  TYPE      DEFAULT  DESCRIPTION

     -switches  optional  n/a      Currently only '-debug', which will spew
                                   massive debugging data.
     -nick      mandatory n/a      The nick you want the bot to be.
     -username  optional  n/a      The ident, ie username the bot will have.
     -ircname   optional  seedesc  The name visible from a /whois bot. This will
                                   default to 'POE::Component::IRC::Session'.
     -exitmsg   optional  'bye!'   Message shown when the bot is disconnected.
     -channel   mandatory n/a      The channel you want the bot to connect to.
     -servers   mandatory n/a      The servers you want the bot to connect to.
                                   It will choose one in a random fashion.
     -port      optional  6667     The port on the server you want the bot to
                                   connect to.
     -interval  optional  30       How often in minutes you want the bot to
                                   send the message publically to the channel.
     -message   mandatory n/a      The message you want to be sent to the
                                   channel and users.
     -delay     optional  5        Number of seconds to wait between messaging
                                   users. If this is set too low you will
                                   probably be knocked off per "Excess Flood".

   Oject methods:

     engage -- Takes no arguments. Initiates the connection.

TODO
====

   - Option to remember who we have messaged so we don't annoy   people by
messaging them multiple times when they join.

     If you have any ideas, suggestions, or comments by all means
     drop me an e-mail. Thank you.  ;)

AUTHOR
======

   Adam J. Foxson <afoxson@guild.net>

CREDITS
=======

   Thanks to fimmtiu@#perl for assistance with tracking down some
particularly nasty early poe bugs, and to uri@#perl for an excellent code
review.

SEE ALSO
========

   POE::Component::IRC::Onjoin::EventProcessor(3) perl(1).

POE Interface to Net::Pcap
**************************

NAME
====

   POE::Component::Pcap - POE Interface to Net::Pcap

SYNOPSIS
========

     use POE::Component::Pcap;

     POE::Component::Pcap->spawn(
     			      Alias => 'pcap',
     			      Device => 'eth0',
     			      Filter => 'host fooble or host blort',
     			      Dispatch => 'got_packet',
     			      Session => $my_session_id,
     			     );

     $poe_kernel->post( pcap => open_live =>
     		     'eth0', 80, 1, 100 );

     $poe_kernel->post( pcap => set_filter => 'arp or host zooble' );

     $poe_kernel->post( pcap => set_dispatch => 'target_state' );

     $poe_kernel->post( pcap => 'run' );

     $poe_kernel->post( pcap => 'shutdown' );

DESCRIPTION
===========

   POE::Component::Pcap provides a wrapper for using the Net::Pcap module
from POE programs.  The component creates a separate session which posts
events to a specified session and state when packets are available.

ARGUMENTS
---------

Alias
     The alias for the Pcap session.  Used to post events such as run and
     shutdown to control the component.  Defaults to `pcap' if not
     specified.

Device
     As a shortcut, the device for Net::Pcap to watch may be specified when
     creating the component.  If this argument is used,
     Net::Pcap::open_live will be called with a snaplen of 80 octets, a
     timeout of 100ms, and the interface will be put in promiscuous mode.
     If these values are not suitable, post an open_live event instead.

Filter
     Another shortcut, calls Net::Pcap::compile and Net::Pcap::setfilter to
     set a packet filter.  This can only be used if the Device argument is
     also given; otherwise a set_filter event should be posted after an
     open_live event (since Net::Pcap must have a `pcap_t' descriptor to
     work with).

Dispatch
Session
     These specify the session and state to which events should be posted
     when packets are received.

EVENTS
------

   The following examples assume that the component's alias has been set
to the default value of *pcap*.

open_live
          $_[KERNEL]->post( pcap => open_live
          		    => 'device', [snaplen], [promsic?], [timeout] );

     Calls Net::Pcap::open_live.  The device name must be specified.  The
     snaplen, promiscuous, and timeout parameters default to 80, 1, and 100
     respectively.  This event must be posted (or the Device argument must
     have been passed to spawn()) before anything else can be done with
     the component.

set_filter
          $_[KERNEL]->post( pcap => set_filter
          		    => 'host fooble or host blort' )

     Sets the Net::Pcap capture filter.  See tcpdump(8) for details on the
     filter language used by pcap(3).

set_dispatch
          $_[KERNEL]->post( pcap => set_dispatch
          		    => 'target_state', 'target_session' );

     Sets the state and session to which events are sent when packets are
     recevied.  The target session will default to the sender of the event
     if not specified.

     The event posted will have a single argument (available as ARG0)
     which will be an array reference containing the `$hdr' and `$pkt'
     parameters from Net::Pcap.  See the Net::Pcap(3) documentation for
     more details.

run
          $_[KERNEL]->post( pcap => 'run' );

     Causes the component to register a select_read and start watching for
     packets.

shutdown
          $_[KERNEL]->post( pcap => 'shutdown' );

     Shuts the component down.  Causes Net::Pcap::close to be called.

SEE ALSO
========

   Net::Pcap(3), pcap(3), tcpdump(8), POE(3), POE::Component(3)

AUTHOR
======

   Mike Fletcher, <fletch@phydeaux.org>

COPYRIGHT
=========

   Copyright 2000-2001, Mike Fletcher.  All Rights Reserved.  This is free
software; you may redistribute it and/or modify it under the same terms as
Perl itself.

Event based RSS parsing
***********************

NAME
====

   POE::Component::RSS - Event based RSS parsing

SYNOPSIS
========

     use POE qw(Component::RSS);

     POE::Component::RSS->spawn();

     $kernel->post('rss', 'parse', {
                            Item => 'item_state',
                          },
                        , $rss_string);

DESCRIPTION
===========

   POE::Component::RSS is an event based RSS parsing module. It wraps
XML::RSS and provides a POE based framework for accessing the information
provided.

   RSS parser components are not normal objects, but are instead 'spawned'
as separate sessions. This is done with PoCo::RSS's 'spawn' method, which
takes one named parameter:

`Alias =' $alias_name>
     'Alias' sets the name by which the session is known. If no alias is
     given, the component defaults to 'rss'. It's possible to spawn
     several RSS components with different names.

   Sessions communicate asynchronously with PoCo::RSS - they post requests
to it, and it posts results back.

   Parse requests are posted to the component's 'parse' state, and include
a hash of states to return results to, and a RSS string to parse, followed
by an optional identity parameter. For example:

     $kernel->post('rss', 'parse',
                          { # hash of result states
                            Item => 'item_state',
                            Channel => 'channel_state',
                            Image => 'image_state',
                            Textinput => 'textinput_state',
                            Start => 'start_state',
                            Stop => 'stop_state',
                          },
                        , $rss_string, $rss_identity_tag);

   Currently supported result events are:

`Item =' 'item_state'>
     A state to call every time an item is found within the RSS file.
     Called with a reference to a hash which contains all attributes of
     that item.

`Channel =' 'channel_state'>
     A state to call every time a channel definition is found within the
     RSS file. Called with a reference to a hash which contains all
     attributes of that channel.

`Image =' 'image_state'>
     A state to call every time an image definition is found within the
     RSS file. Called with a reference to a hash which contains all
     attributes of that image.

`Textinput =' 'textinput_state'>
     A state to call every time a textinput definition is found within the
     RSS file. Called with a reference to a hash which contains all
     attributes of that textinput.

`Start =' 'start_state'>
     A state to call at the start of parsing.

`Stop =' 'stop_state'>
     A state to call at the end of parsing.

   If an identity parameter was supplied with the parse event, the first
parameter of all result events is that identity string. This allows easy
identification of which parse a result is for.

TODO
====

   * Provide event based generation of RSS files.

   * Provide more of the information in an RSS file as events.

   * We depend on the internals of XML::RSS. This is bad and should be
     fixed.

BUGS
====

   * Some events may be emitted even if no data was found. Calling code
     should check return data to verify content.

AUTHOR
======

   Michael Stevens - michael@etla.org.

SEE ALSO
========

   perl(1). This component is built upon XML::RSS(3).

simplified TCP server
*********************

NAME
====

   POE::Component::Server::TCP - simplified TCP server

SYNOPSIS
========

     use POE;

     sub accept_handler {
       my ($socket, $remote_address, $remote_port) = @_[ARG0, ARG1, ARG2];
       # code goes here to handle the accepted socket
     }

     sub error_handler {
       my ($op, $errnum, $errstr) = @_[ARG0, ARG1, ARG2];
       warn "server encountered $op error $errnum: $errstr";
       # possibly shut down the server
     }

     new POE::Component::Server::TCP
       ( Port     => $bind_port,
         Acceptor => \&accept_handler,
         Error    => \&error_handler,  # Optional.
       );

DESCRIPTION
===========

   POE::Component::Server::TCP is a wrapper around
POE::Wheel::SocketFactory.  It abstracts the steps required to create a
TCP server, taking away equal measures of responsibility and control for
listening for and accepting remote socket connections.

   At version 1.0, the Server::TCP component takes three arguments:

   * Port

     Port is the port the listening socket will be bound to.

   * Acceptor

     Acceptor is a coderef which will be called to handle accepted sockets.
     The coderef is used as POE::Wheel::SocketFactory's SuccessState, so it
     accepts the same parameters.

   * Error

     Error is an optional coderef which will be called to handle server
     socket errors.  The coderef is used as POE::Wheel::SocketFactory's
     FailureState, so it accepts the same parameters.  If it is omitted, a
     fairly standard error handler will be provided.  The default handler
     will log the error to STDERR and shut down the server.

SEE ALSO
========

   POE::Wheel::SocketFactory

BUGS
====

   POE::Component::Server::TCP does not accept many of the options that
POE::Wheel::SocketFactory does.

AUTHORS & COPYRIGHTS
====================

   POE::Component::Server::TCP is Copyright 2000 by Rocco Caputo.  All
rights are reserved.  POE::Component::Server::TCP is free software, and it
may be redistributed and/or modified under the same terms as Perl itself.

event based wrapper for subs
****************************

NAME
====

   POE::Component::SubWrapper - event based wrapper for subs

SYNOPSIS
========

     use POE::Component::SubWrapper;
     POE::Component::SubWrapper->spawn('main');
     $kernel->post('main', 'my_sub', [ $arg1, $arg2, $arg3 ], 'callback_state');

DESCRIPTION
===========

   This is a module which provides an event based wrapper for subroutines.

   SubWrapper components are not normal objects, but are instead 'spawned'
as separate sessions. This is done with with PoCo::SubWrapper's 'spawn'
method, which takes one required and one optional argument.  The first
argument is the package name to wrap. This is required. The second
argument is optional and contains an alias to give to the session created.
If no alias is supplied, the package name is used as an alias.

   Another way to create SubWrapper components is to use the `poeize'
method, which is included in the default export list of the package. You
can simply do:

     poeize Data::Dumper;

   and Data::Dumper will be wrapped into a session with the alias
'Data::Dumper'.

   When a SubWrapper component is created, it scans the package named for
subroutines, and creates one state in the session created with the same
name of the subroutine.

   The states each accept 3 arguments:

   * An arrayref to a list of arguments to give the subroutine.

   * A state to callback with the results.

   * A string, either 'SCALAR', or 'ARRAY', allowing you to decide which
     context the function handled by this state will be called in.

   The states all call the function with the name matching the state, and
give it the supplied arguments. They then postback the results to the named
callback state. The results are contained in ARG0 and are either a scalar
if the function was called in scalar context, or an arrayref of results if
the function was called in list context.

EXAMPLES
========

   The test scripts are the best place to look for examples of
POE::Component::Subwrapper usage. A short example is given here:

     use Data::Dumper;
     poeize Data::Dumper;
     $kernel->post('Data::Dumper', 'Dumper', [ { a => 1, b => 2 ], 'callback_state, 'SCALAR');

     sub callback_handler {
       my $result = @_[ARG0];
       # do something with the string returned by Dumper({ a => 1, b => 2})
     }

   Data::Dumper is the wrapped module, Dumper is the function called, `{a
=> 1, b => 2}' is the data structure that is dumped, and $result is the
resulting string form.

EXPORT
------

   The module exports the following functions by default:

`poeize'
     A function called with a single bareword argument specifying the
     package to be wrapped.

AUTHOR
======

   Michael Stevens - michael@etla.org.

SEE ALSO
========

   perl(1).

a component to manage user authentication
*****************************************

NAME
====

   POE::Component::UserBase - a component to manage user authentication

SYNOPSIS
========

     use POE qw(Component::UserBase);

     # The UserBase can deal with many types of repositories.
     # The first kind is a simple file.
     POE::Component::UserBase->spawn
       ( Alias    => 'userbase', # defaults to 'userbase'.
         Protocol => 'file',     # The repository type.
         Cipher   => 'md5',      # defaults to 'crypt'.

     File     => '/home/jgoff/passwd',   # The path to the repository
     Dir      => '/home/jgoff/.persist', # Directory to store persistent
                                         # information.
         );

     POE::Component::UserBase->spawn
       ( Alias         => 'userbase',   # defaults to 'userbase'.
         Protocol      => 'dbi',        # The repository type.
         Cipher        => 'sha1',       # defaults to 'crypt'.

     DBHandle      => $dbh,         # Required, connected to a handle.
     Table         => 'auth',
     UserColumn    => 'user_name',  # defaults to 'username'.
     PassColumn    => 'password',   # defaults to 'password'.
     PersistColumn => 'persistent', # defaults to 'data'. This is our
                                    # persistent data storage.
         );

     # PoCo::UserBase provides generic user-management services to multiple
     # sessions.

     $kernel->post
       ( user_base => log_on => user_name  => $user_name,
                                domain     => $domain,       # optional
     		             password   => $password,     # optional
     		             persistent => $persistent_reference,
     		             response   => $authorized_state,
       );

     $kernel->post
       ( user_base => log_off => user_name => $user_name,
                                 password  => $password,    # optional
       );

     $kernel->post
       ( user_base => create => user_name => $user_name,
                                domain    => $domain,       # optional
     		             password  => $password,     # optional
       );

     $kernel->post
       ( user_base => delete => user_name => $user_name,
                                domain    => $domain,       # optional
                                password  => $password,     # optional
       );

     $kernel->post
       ( user_base => update => user_name     => $user_name,
     	                     domain        => $domain,   # optional
                                password      => $password, # optional
                                new_user_name => $new_name, # optional
     		             new_domain    => $new_dom,  # optional
     		             new_password  => $new_pass, # optional
       );

DESCRIPTION
===========

   POE::Component::UserBase handles basic user authentication and
management tasks for a POE server. It can authenticate from sources such
as a .htaccess file, database, DBM files, and flat files.

   PoCo::UserBase communicates with the client through a previously created
SocketFactory. After a client is has connected, PoCo::UserBase interrogates
the client for its username and password, and returns the connection data
from the socket along with the username and password authenticated.

   POE::Component::UserBase's spawn method takes a few parameters to
describe the depository of user names. I'd recommend that you not use any
crucial system files until you assure yourself that it's indeed safe.

   The spawn method has several common parameters. These are listed below.

Alias => $session_alias
     Alias sets the name by which the session will be known.  If no alias
     is given, the component defaults to "userbase".  The alias lets
     several sessions interact with the user manager without keeping (or
     even knowing) hard references to them.

Cipher => $cipher_type
     Cipher sets the cipher that will be used to encrypt the password
     entries.  If no cipher is given, the component defaults to "crypt".
     This uses the native crypt() function. Other cipher choices include
     'md5', 'sha1', 'md5_hex', 'sha1_hex', 'md5_base64', and
     'sha1_base64'. The 'md5' and 'sha1' cipher types are documented in
     the Digest/MD5, and Digest/SHA1,
     class.  They're simply different output formats of the original hash.

   These parameters are unique to the file Protocol type.

File => $filename
     File sets the file name that is used to store user data. This
     parameter is required.

Dir => $path_to_persistent_directory
     Dir Sets the directory that is used to hold the persistence
     information.  This directory holds the frozen persistent data,
     indexed by the user_name.

   These parameters are unique to the *dbi* Protocol type.

Connection => $dbh_connection
     Connection stores a handle to a DBI connection. The database must
     contain a table which will hold the username, password, and
     persistent data.

PersistentColumn => $persistent_data_column_name
     PersistentColumn specifies the column name used to hold the persistent
     data. If you can't allocate enough space to hold your persistent data
     in the database, then you can use the DataFile parameter to define a
     MLDBM file that will be used to hold this persistent data. The MLDBM
     data file will be keyed by the username.

DataFile => $data_file_name
     DataFile specifies the filename of the MLDBM file used to hold the
     persistent data store. Use of this parameter is incompatible with
     Data.

DomainColumn => $domain_column_name
     DomainColumn specifies the column used to store the domain column.
     It defaults to domain.

PasswordColumn => $password_column_name
     PasswordColumn specifies the column used to store the password column.
     It defaults to password.

Table => $dbi_table
     Table specifies the table name used to store username, password, and
     maybe the persistent data stored along with each user.

UserColumn => $user_column_name
     UserColumn specifies the column used to store the username column. It
     defaults to username. In the event that you use the DataFile
     parameter, this column will be kept in sync with the MLDBM file.

   Sessions communicate asynchronously with passive UserBase components.
They post their requests through several internal states, and receive data
through a state that you specify.

   Requests are posted to one of the states below:

log_on
     log_on is to be called when a client wants to authenticate a user.

          $kernel->post
            ( user_base => log_on => user_name  => $user_name,
                                     domain     => $domain,       # optional
          		             password   => $password,     # optional
          		             persistent => $persistent_reference,
          		             response   => $authorized_state,
            );

log_off
     log_off is to be called when a client is finished with a user.

          $kernel->post
            ( user_base => log_off => user_name => $user_name,
                                      password  => $password,    # optional
            );

create
     create lets you create a new user.

          $kernel->post
            ( user_base => create => user_name => $user_name,
                                     domain    => $domain,       # optional
          		             password  => $password,     # optional
            );

delete
     delete lets you delete a user.

          $kernel->post
            ( user_base => delete => user_name => $user_name,
                                     domain    => $domain,       # optional
                                     password  => $password,     # optional
            );

update
     update lets you update a user.

          $kernel->post
            ( user_base => update => user_name     => $user_name,
          	                     domain        => $domain,   # optional
                                     password      => $password, # optional
                                     new_user_name => $new_name, # optional
          		             new_domain    => $new_dom,  # optional
          		             new_password  => $new_pass, # optional
            );

   For example, authenticating a user is simply a matter of posting a
request to the `userBase' alias (or whatever you named it). It posts
responses back to either the 'authorization accepted' or 'authorizaton
failed' state. If it successfully authenticates the user, it then fills
the alias referenced in the `Persistence' parameter with the user data it
stored in the database when the user logged out.

SEE ALSO
========

   This component is built upon POE.  Please see its source
code and the documentation for its foundation modules to learn more.

   Also see the test programs in the t/ directory, and the samples in the
samples/ directory in the POE/Component/UserBase directory.

BUGS
====

   None currently known.

AUTHOR & COPYRIGHTS
===================

   POE::Component::UserBase is Copyright 1999-2000 by Jeff Goff.  All
rights are reserved.  POE::Component::UserBase is free software; you may
redistribute it and/or modify it under the same terms as Perl itself.

POE Read/Write Abstraction
**************************

NAME
====

   POE::Driver - POE Read/Write Abstraction

SYNOPSIS
========

     $driver = new POE::Driver::Something();
     $arrayref_of_data_chunks = $driver->get($filehandle);
     $queue_octets = $driver->put($arrayref_of_data_chunks);
     $queue_octets = $driver->flush($filehandle);
     $queue_messages = $driver->get_out_messages_buffered();

DESCRIPTION
===========

   Drivers provide a generic interface for low-level file I/O.  Wheels use
this interface to read and write files, sockets, and things, without
having to know the details for each.

   In theory, drivers should be pretty much interchangeable.  In practice,
there seems to be an impermeable barrier between the different SOCK_*
types.

PUBLIC DRIVER METHODS
=====================

   These methods are the generic Driver interface.  Specific drivers may
have additional methods.

   * POE::Driver::new()

     The new() method creates and initializes a new driver.  Specific
     drivers may have different constructor parameters.

   * POE::Driver::get($filehandle)

     The get() method immediately tries to read information from a
     filehandle.  It returns a reference to an array of received data
     chunks.  The array may be empty if nothing could be read.  The array
     reference it returns is a suitable parameter to POE::Filter::get().

     get() returns undef on an error.

     Wheels usually call the get() method from their read select states.

   * POE::Driver::put($arrayref_of_data_chunks)

     The put() method places raw data into the driver's output queue.  Some
     drivers may flush data from the put() method.  It accepts a reference
     to an array of writable chunks, and it returns the number of octets in
     its output queue.

     Wheels usually call the put() method from their own put() methods.

   * POE::Driver::flush($filehandle)

     The flush() method attempts to flush some data from the driver's
     output queue to the file.  It returns the number of octets remaining
     in the output queue after the flush.

     Wheels usually call the flush() method from their write select states.

   * POE::Driver::get_out_messages_buffered()

     Returns the number of messages in the driver's output buffer.  If the
     top message is partially flushed, it is still counted as a full one.

SEE ALSO
========

   POE::Driver::SysRW

BUGS
====

   There is no POE::Driver::SendRecv

AUTHORS & COPYRIGHTS
====================

   Please see the POE manpage.

POE sysread/syswrite Abstraction
********************************

NAME
====

   POE::Driver::SysRW - POE sysread/syswrite Abstraction

SYNOPSIS
========

     $driver = new POE::Driver::SysRW();
     $arrayref_of_data_chunks = $driver->get($filehandle);
     $queue_octets = $driver->put($arrayref_of_data_chunks);
     $queue_octets = $driver->flush($filehandle);
     $queue_messages = $driver->get_out_messages_buffered();

DESCRIPTION
===========

   This driver provides an abstract interface to sysread and syswrite.

PUBLIC METHODS
==============

   * POE::Driver::SysRW::new( ... );

     The new() constructor accepts one optional parameter:

          BlockSize => $block_size

     This is the maximum data size that the SysRW driver will read at once.
     If omitted, $block_size defaults to 512.

SEE ALSO
========

   POE::Driver

BUGS
====

   Oh, probably some.

AUTHORS & COPYRIGHTS
====================

   Please see the POE manpage.

POE Protocol Abstraction
************************

NAME
====

   POE::Filter - POE Protocol Abstraction

SYNOPSIS
========

     $filter = new POE::Filter::Something();
     $arrayref_of_logical_chunks =
       $filter->get($arrayref_of_raw_chunks_from_driver);
     $arrayref_of_streamable_chunks_for_driver =
        $filter->put($arrayref_of_logical_chunks);

DESCRIPTION
===========

   Filters provide a generic interface for low and medium level protocols.
Wheels use this interface to communicate in different protocols without
necessarily having to know the details for each.

   In theory, filters should be interchangeable.  In practice, stream and
block protocols tend to be incompatible.

PUBLIC FILTER METHODS
=====================

   These methods are the generic Filter interface.  Specific filters may
have additional methods.

   * POE::Filter::new()

     The new() method creates and initializes a new filter.  Specific
     filters may have different constructor parameters.

   * POE::Filter::get($arrayref_of_raw_chunks_from_driver)

     The get() method translates raw stream data into logical units.  It
     accepts a reference to an array of raw stream chunks as returned from
     POE::Driver::get().  It returns a reference to an array of complete
     logical data chunks.  There may or may not be a 1:1 correspondence
     between raw stream chunks and logical data chunks.

     Some filters may buffer partial logical units until they are completed
     in subsequent get() calls.

     The get() method returns a reference to an empty array if the stream
     doesn't include enough information for a complete logical unit.

   * POE::Filter::put($arrayref_of_logical_chunks)

     The put() method takes a reference to an array of logical data chunks.
     It serializes them into streamable representations suitable for
     POE::Driver::put().  It returns the raw streamable versions in a
     different array reference.

   * POE::Filter::get_pending()

     The get_pending() method is part of wheels' buffer swapping mechanism.
     It clears the filter's input buffer and returns a copy of whatever was
     in it.  It doesn't manipulate filters' output buffers because they
     don't exist (filters expect to receive entire logical data chunks from
     sessions, so there's no reason to buffer data and frame it).

     *Please note that relying on the get_pending() method in networked
     settings require some forethought.* For instance, POE::Filter::Stream
     never buffers data.

     Switching filters usually requires some sort of flow control,
     otherwise it's easy to cause a race condition where one side sends the
     wrong type of information for the other side's current filter.
     Framing errors will ensue.  Consider the following:

     Assume a server and client are using POE::Filter::Line.  When the
     client asks the server to switch to POE::Filter::Reference, it should
     wait for the server's ACK or NAK before changing its own filter.  This
     lets the client avoid sending referenced data while the server still
     is parsing lines.

     Here's something else to consider.  Programs using POE::Wheel::put()
     on TCP sockets cannot rely on each put data chunk arriving separately
     on the receiving end of the connection.  This is because TCP coalesces
     packets whenever possible, to minimize packet header overhead.

     Most systems have a way to disable the TCP delay (Nagle's algorithm),
     in one form or another.  If you need this, please check your C headers
     for the TCP_NODELAY socket option.  It's neither portable, nor
     supported in Perl by default.

     The filterchange.perl sample program copes with flow control while
     switching filters.

SEE ALSO
========

   POE::Filter::HTTPD; POE::Filter::Line; POE::Filter::Reference;
POE::Filter::Stream

BUGS
====

   Oh, probably some.

AUTHORS & COPYRIGHTS
====================

   Please see the POE manpage.

POE Block Protocol Abstraction
******************************

NAME
====

   POE::Filter::Block - POE Block Protocol Abstraction

SYNOPSIS
========

     $filter = new POE::Filter::Block( BlockSize => 1024 );
     $arrayref_of_blocks =
       $filter->get($arrayref_of_raw_chunks_from_driver);
     $arrayref_of_streamable_chunks_for_driver =
       $filter->put($arrayref_of_blocks);
     $arrayref_of_streamable_chunks_for_driver =
       $filter->put($single_block);
     $arrayref_of_leftovers =
       $filter->get_pending();

DESCRIPTION
===========

   The Block filter translates streams to and from blocks of bytes.  If a
block size is specified when the filter is constructed, then fixed-length
blocks of that size will be built or parsed.  Otherwise it builds and
parses length-prepended variable-sized blocks.  Programs that specify
block sizes less than 1 byte are soundly spanked, just as they deserve.

   Extra bytes are buffered until more bytes arrive to complete a block.

PUBLIC FILTER METHODS
=====================

   Please see POE::Filter.

SEE ALSO
========

   POE::Filter; POE::Filter::HTTPD; POE::Filter::Reference;
POE::Filter::Stream; POE::Filter::Line

BUGS
====

   None known.

AUTHORS & COPYRIGHTS
====================

   The Block filter was contributed by Dieter Pearcey, with changes by
Rocco Caputo.

   Please see the POE manpage for more information about authors and
contributors.

A POE-based parser for the IRC protocol.
****************************************

NAME
====

   POE::Filter::CTCP - A POE-based parser for the IRC protocol.

SYNOPSIS
========

     my $filter = POE::Filter::IRC->new();
     my @events = @{$filter->get( [ @lines ] )};
     my @msgs = @{$filter->put( [ @messages ] )};

DESCRIPTION
===========

   POE::Filter::CTCP converts normal text into thoroughly CTCP-quoted
messages, and transmogrifies CTCP-quoted messages into their normal, sane
components. Rather what you'd expect a filter to do.

   A note: the CTCP protocol sucks bollocks. If I ever meet the fellow who
came up with it, I'll shave their head and tattoo obscenities on it.  Just
read the "specification" at http://cs-pub.bu.edu/pub/irc/support/ctcp.spec
and you'll hopefully see what I mean. Quote this, quote that, quote this
again, all in different and weird ways... and who the hell needs to send
mixed CTCP and text messages? WTF? It looks like it's practically
complexity for complexity's sake. Anyhow, enough ranting. Onto the rest of
the docs...

METHODS
=======

   * new

     Creates a new POE::Filter::CTCP object. Duh. :-)   Takes no arguments.

   * get

     Takes an array reference containing one or more lines of CTCP-quoted
     text. Returns an array reference of processed, pasteurized events.

   * put

     Takes an array reference of CTCP messages to be properly quoted. This
     doesn't support CTCPs embedded in normal messages, which is a
     brain-dead hack in the protocol, so do it yourself if you really need
     it. Returns an array reference of the quoted lines for sending.

AUTHOR
======

   Dennis "fimmtiu" Taylor, <dennis@funkplanet.com>.

SEE ALSO
========

   The documentation for POE and POE::Component::IRC.

POE HTTP 1.0 (Server Side) Protocol Abstraction
***********************************************

NAME
====

   POE::Filter::HTTPD - POE HTTP 1.0 (Server Side) Protocol Abstraction

SYNOPSIS
========

     $httpd = new POE::Filter::HTTPD();
     $arrayref_with_http_response_as_string =
       $httpd->put($full_http_response_object);
     $arrayref_with_http_request_object =
       $line->get($arrayref_of_raw_data_chunks_from_driver);

DESCRIPTION
===========

   The HTTPD filter parses the first HTTP 1.0 request from an incoming
stream into an HTTP::Request object.  It accepts a single HTTP::Response
object, and returns a HTTP 1.0 stream for sending.

   Please see the documentation for HTTP::Request and HTTP::Response.

PUBLIC FILTER METHODS
=====================

   Please see POE::Filter.

SEE ALSO
========

   POE::Filter; POE::Filter::Line; POE::Filter::Reference;
POE::Filter::Stream; HTTP::Request; HTTP::Response

BUGS
====

   Keep-alive is not supported.

AUTHORS & COPYRIGHTS
====================

   The HTTPD filter was contributed by Artur Bergman.

   Please see the POE manpage for more information about authors and
contributors.

A POE-based parser for the IRC protocol.
****************************************

NAME
====

   POE::Filter::IRC - A POE-based parser for the IRC protocol.

SYNOPSIS
========

     my $filter = POE::Filter::IRC->new();
     my @events = @{$filter->get( [ @lines ] )};

DESCRIPTION
===========

   POE::Filter::IRC takes lines of raw IRC input and turns them into weird
little data structures, suitable for feeding to POE::Component::IRC. They
look like this:

     { name => 'event name', args => [ some info about the event ] }

METHODS
=======

   * new

     Creates a new POE::Filter::IRC object. Duh. :-)   Takes no arguments.

   * get

     Takes an array reference full of lines of raw IRC text. Returns an
     array reference of processed, pasteurized events.

   * put

     There is no "put" method. That would be kinda silly for this filter,
     don't you think?

AUTHOR
======

   Dennis "fimmtiu" Taylor, <dennis@funkplanet.com>.

SEE ALSO
========

   The documentation for POE and POE::Component::IRC.

POE Line Protocol Abstraction
*****************************

NAME
====

   POE::Filter::Line - POE Line Protocol Abstraction

SYNOPSIS
========

     $filter = POE::Filter::Line->new();
     $arrayref_of_lines =
       $filter->get($arrayref_of_raw_chunks_from_driver);
     $arrayref_of_streamable_chunks_for_driver =
       $filter->put($arrayref_of_lines);
     $arrayref_of_streamable_chunks_for_driver =
       $filter->put($single_line);
     $arrayref_of_leftovers =
       $filter->get_pending();

     # To use a literal newline terminator for input and output:
     $filter = POE::Filter::Line->new( Literal => "\x0D\x0A" );

     # To terminate input lines with a string regexp:
     $filter = POE::Filter::Line->new( InputRegexp   => '[!:]',
                                       OutputLiteral => "!"
                                     );

     # To terminate input lines with a compiled regexp (requires perl
     # 5.005 or newer):
     $filter = POE::Filter::Line->new( InputRegexp   => qr/[!:]/,
                                       OutputLiteral => "!"
                                     );

     # To autodetect the input line terminator:
     $filter = POE::Filter::Line->new( InputLiteral => undef );

DESCRIPTION
===========

   The Line filter translates streams to and from newline-separated lines.
The lines it returns do not contain newlines.  Neither should the lines
given to it.

   By default, incoming newline are recognized with a regular
subexpression: `/(\x0D\x0A?|\x0A\x0D?)/'.  This encompasses all sorts of
variations on CR and LF, but it has a problem.  If incoming data is broken
between CR and LF, then the second character will be interpreted as a
blank line.  This doesn't happen often, but it can happen often enough.
*People are advised to specify custom newlines in applications where blank
lines are significant.*

   By default, outgoing lines have traditional network newlines attached
to them: `"\x0D\x0A"', or CRLF.  The `OutputLiteral' parameter is used to
specify a new one.

PUBLIC FILTER METHODS
=====================

   Please see POE::Filter.

SEE ALSO
========

   POE::Filter; POE::Filter::HTTPD; POE::Filter::Reference;
POE::Filter::Stream

BUGS
====

   The default input newline regexp has a race condition where incomplete
newlines can generate spurious blank input lines.

AUTHORS & COPYRIGHTS
====================

   Please see the POE manpage.

POE Freeze/Thaw Protocol Abstraction
************************************

NAME
====

   POE::Filter::Reference - POE Freeze/Thaw Protocol Abstraction

SYNOPSIS
========

     $filter = new POE::Filter::Reference();
     $arrayref_of_perl_references =
       $filter->get($arrayref_of_raw_chunks_from_driver);
     $arrayref_of_serialized_perl_references =
        $filter->put($arrayref_of_perl_references);

DESCRIPTION
===========

   The "put" half of this filter freezes referenced Perl structures into
serialized versions for sending.  The "get" half of this filter thaws
serialized Perl structures back into references.  This provides a handy
way to ship data between processes and systems.

   Serializers should recognize that POE::Filter::Reference is used to
ship data between systems with different byte orders.

PUBLIC FILTER METHODS
=====================

   * POE::Filter::Reference::new( ... )

     The new() method creates and initializes the reference filter.  It
     accepts optional parameters to specify a serializer and the use of
     compression.  The serializer may be a package or an object; the
     compression flag is a Perl "boolean" value.

     A package serializer must have a thaw() function, and it must have
     either a freeze() or nfreeze() function.  If it has both freeze() and
     nfreeze(), then Filter::Reference will use nfreeze() for portability.
     These functions match Storable and FreezeThaw's call signatures.

     An object serializer must have a thaw() method.  It also must have
     either a freeze() or nfreeze() method.  If it has both freeze() and
     nfreeze(), then Filter::Reference will use nfreeze() for portability.
     The thaw() method accepts $self and a scalar; it should return a
     reference to the reconstituted data.  The freeze() and nfreeze()
     methods receive $self and a reference; they should return a scalar
     with the reference's serialized representation.

     If the serializer parameter is undef, a default one will be used.
     This lets programs specify compression without having to worry about
     naming a serializer.

     For example:

          # Use the default filter (either Storable or FreezeThaw).
          my $filter = new POE::Filter::Reference();

          # Use Storable explicitly, specified by package name.
          my $filter = new POE::Filter::Reference('Storable');

          # Use an object.
          my $filter = new POE::Filter::Reference($object);

          # Use an object, with compression.
          my $filter = new POE::Filter::Reference($object, 1);

          # Use the default serializer, with compression.
          my $filter = new POE::Filter::Reference(undef, 1);

     The new() method will try to require any packages it needs.

     The default behavior is to try Storable first, FreezeThaw second, and
     fail if neither is present.  This is rapidly becoming moot because of
     the PM_PREREQ entry in Makefile.PL, which makes CPAN and "make" carp
     about requirements even when they aren't required.

   * POE::Filter::Reference::get($frozen_data)

     The get() method thaws streamed, frozen data into references.
     References will be blessed, if necessary.  If the reference points to
     an object, be sure the receiving end has use'd it before calling its
     methods.

   * POE::Filter::Reference::put($reference)

     The put() method freezes references and returns their serialized,
     streamable representations.

SEE ALSO
========

   POE::Filter; POE::Filter::HTTPD; POE::Filter::Line; POE::Filter::Stream

BUGS
====

   Oh, probably some.

AUTHORS & COPYRIGHTS
====================

   The Reference filter was contributed by Arturn Bergman, with changes by
Philip Gwyn.

   Please see the POE manpage for more information about authors and
contributors.

POE Stream (Null) Protocol Abstraction
**************************************

NAME
====

   POE::Filter::Stream - POE Stream (Null) Protocol Abstraction

SYNOPSIS
========

     $filter = new POE::Filter::Stream();
     $arrayref_of_logical_chunks =
       $filter->get($arrayref_of_raw_chunks_from_driver);
     $arrayref_of_streamable_chunks_for_driver =
        $filter->put($arrayref_of_logical_chunks);

DESCRIPTION
===========

   This filter passes data through unchanged.  It is a "null" filter.

SEE ALSO
========

   POE::Filter; POE::Filter::HTTPD; POE::Filter::Line;
POE::Filter::Reference; POE::Filter::Stream

BUGS
====

   Oh, probably some.

AUTHORS & COPYRIGHTS
====================

   Please see the POE manpage.

an event dispatcher and resource watcher
****************************************

NAME
====

   POE::Kernel - an event dispatcher and resource watcher

SYNOPSIS
========

   The POE manpage includes and describes a sample program.

   POE comes with its own event loop, which is based on select() and
written exclusively in Perl.  To use it, simply:

     use POE;

   POE's functions will also map to Gtk's event loop if Gtk is used first.
No other actions are required to begin using POE with Gtk.  See
POE::Session's postback() method for mapping Gtk callbacks to POE events.
See the test program 21_gtk.t for a sample POE program that uses Gtk.

     use Gtk;
     use POE;

   POE's functions will also map to Tk's event loop if Tk is used first.
No other actions are required to begin using POE with Tk.  See
POE::Session's postback() method for mapping Tk callbacks to POE events.
See the test program 06_tk.t for a sample POE program that uses Tk.

     use Tk;
     use POE;

   POE can also encapsulate Event's event loop.  If Event is used before
POE, then POE will use it for you.  POE::Session's postback() method can
also be used here to have Event's watchers post POE events.

     use Event;
     use POE;

   Methods to manage the process' global Kernel instance:

     # Retrieve the kernel's unique identifier.
     $kernel_id = $kernel->ID;

     # Run the event loop, only returning when it has no more sessions to
     # dispatche events to.
     $kernel->run( );

   FIFO event methods:

     # Post an event to an arbitrary session.
     $kernel->post( $session, $state_name, @state_args );

     # Post an event back to the current session.
     $kernel->yield( $state_name, @state_args );

     # Synchronous state call, bypassing the event queue and returning
     # the state's return value directly.
     $state_return_value = $kernel->call( $session, $state_name, @state_args );

   Alarm and delay methods:

     # Post an event which will be delivered at an absolute Unix epoch
     # time.  This clears previous timed events for the same state.
     $kernel->alarm( $state_name, $epoch_time, @state_args );

     # Post an additional alarm, leaving existing ones in the queue.
     $kernel->alarm_add( $state_name, $epoch_time, @state_args );

     # Post an event which will be delivered after some number of
     # seconds.  This clears previous timed events for the same state.
     $kernel->delay( $state_name, $seconds, @state_args );

     # Post an additional delay, leaving existing ones in the queue.
     $kernel->delay_add( $state_name, $seconds, @state_args );

     # Return the names of pending timed events.
     @state_names = $kernel->queue_peek_alarms( );

   Symbolic name, or session alias methods:

     # Set an alias for the current session.
     $status = $kernel->alias_set( $alias );

     # Clear an alias for the current session:
     $status = $kernel->alias_remove( $alias );

     # Resolve an alias into a session reference.  Most POE::Kernel
     # methods do this for you.
     $session_reference = $kernel->alias_resolve( $alias );

     # Resolve a session ID to a session reference.  The alias_resolve
     # method does this as well, but this is faster.
     $session_reference = $kernel->ID_id_to_session( $session_id );

     # Return a session ID for a session reference.  It is functionally
     # equivalent to $session->ID.
     $session_id = $kernel->ID_session_to_id( $session_reference );

   Filehandle watcher methods:

     # Watch for read readiness on a filehandle.  Clear a read select
     # from a filehandle.
     $kernel->select_read( $file_handle, $state_name );
     $kernel->select_read( $file_handle );

     # Watch for write readiness on a filehandle.  Clear a write select
     # from a filehandle.
     $kernel->select_write( $file_handle, $state_name );
     $kernel->select_write( $file_handle );

     # Pause and resume write readiness watching.  These have lower
     # overhead than full select_write() calls.
     $kernel->select_pause_write( $file_handle );
     $kernel->select_resume_write( $file_handle );

     # Watch for out-of-bound (expedited) read readiness on a filehandle.
     # Clear an expedite select from a filehandle.
     $kernel->select_expedite( $file_handle, $state_name );
     $kernel->select_expedite( $file_handle );

     # Set and/or clear a combination of selects in one call.
     $kernel->select( $file_handle,
                      $read_state_name,     # or undef to clear it
                      $write_state_name,    # or undef to clear it
                      $expedite_state_same, # or undef to clear it
                    );

   Signal watcher and generator methods:

     # Map a signal name to its handler state.  Clear a signal-to-handler
     # mapping.
     $kernel->sig( $signal_name, $state_name );
     $kernel->sig( $signal_name );

     # Simulate a system signal by posting it through POE rather than
     # through the underlying OS.
     $kernel->signal( $session, $signal_name );

   State management methods:

     # Remove an existing state from the current machine.
     $kernel->state( $state_name );

     # Add a new inline state, or replace an existing one.
     $kernel->state( $state_name, $code_reference );

     # Add a new object or package state, or replace an existing one.
     # The object method will be the same as the state name.
     $kernel->state( $state_name, $object_ref_or_package_name );

     # Add a new object or package state, or replace an existing one.
     # The object method may be different from the state name.
     $kernel->state( $state_name, $object_ref_or_package_name, $method_name );

   External reference count methods:

     # Increment a session's external reference count.
     $kernel->refcount_increment( $session_id, $refcount_name );

     # Decrement a session's external reference count.
     $kernel->refcount_decrement( $session_id, $refcount_name );

   Kernel data accessors:

     # Return a reference to the currently active session, or to the
     # kernel if called outside any session.
     $session = $kernel->get_active_session();

   Exported symbols:

     # A reference to the global POE::Kernel instance.
     $poe_kernel

     # This is the Gtk or Tk top-level (or main) window widget.  POE uses
     # it for a couple things: It's how Tk's event loop is accessed, and
     # its closure fires the UIDESTROY signal.
     $poe_main_window

DESCRIPTION
===========

   POE::Kernel is an event dispatcher and resource watcher.  It provides a
consistent interface to the most common event loop features whether the
underlying architecture is its own, Gtk-Perl's, Tk-Perl's, or Event's.
Other loop features can be integrated with POE through POE::Session's
postback() method.

USING POE::Kernel
=================

   The POE manpage describes a shortcut for using several POE modules at
once.

   POE::Kernel supports four event loops: Its own select loop, included
with POE and coded in Perl for maximum portability; Gtk's and Tk's loops,
which let programs interact with users through a graphical interface; and
Event's loop, which is written in C for maximum performance.

   POE::Kernel uses its own loop by default, but it will adapt to
whichever external event loop is loaded before it.  POE's functions work
the same regardless of the underlying event loop.

     # Use POE's select loop.
     use POE::Kernel;

     # Use Gtk's event loop.
     use Gtk;
     use POE::Kernel;

     # Use Tk's event loop.
     use Tk;
     use POE::Kernel;

     # Use Event's loop.
     use Event;
     use POE::Kernel;

   All of the other event loops assume their native watchers will invoke
callbacks.  POE::Session's postback() method is used to create callbacks
that post POE events.  Programs can use it to take advantage of otherwise
"unsupported" native callbacks.

   It also is possible to enable assertions and debugging traces by
defining the constants that enable them before POE::Kernel does.  Every
definition follows the form:

     sub POE::Kernel::ASSERT_SOMETHING () { 1 }

   Assertions are quiet until something wrong has been detected, and then
they die right away with an error.  Their main use is for sanity checks in
POE's test suite.  Traces, on the other hand, are never fatal, but they're
terribly noisy.

   Both assertions and traces incur performance penalties, so they should
be used sparingly, if at all.  They all are off by default.

   Assertions will be discussed first.

ASSERT_DEFAULT
     The value of ASSERT_DEFAULT is used as the default value for the other
     assertion constants.  Setting this true is a quick and reliable way to
     ensure that all assertions are enabled.

ASSERT_GARBAGE
     Enabling ASSERT_GARBAGE has POE::Kernel verify its internal record
     keeping against sane conditions.  In particular, it ensures that
     sessions have released all their resources before destroying them.

ASSERT_REFCOUNT
     Setting ASSERT_REFCOUNT true enables checks for negative reference
     counts and nonzero reference counts in destroyed sessions.  It
     complements ASSERT_GARBAGE.

ASSERT_RELATIONS
     Enabling ASSERT_RELATIONS turns on parent/child referential integrity
     checks.

ASSERT_SELECT
     Setting ASSERT_SELECT true enables extra error checking in
     POE::Kernel's select logic.  It has no effect if POE is using an
     external event loop.

ASSERT_SESSIONS
     POE::Kernel normally discards events that are posted to nonexistent
     sessions.  This is a deliberate feature, but it means that certain
     typographical errors can go unnoticed.

     A true ASSERT_SESSIONS constant will cause POE to check session
     resolution and die if an unknown session is referenced.  This may
     catch problems that are otherwise difficult to spot.

   Then there are the trace options.

TRACE_DEFAULT
     TRACE_DEFAULT works like ASSERT_DEFAULT except for traces.  That is,
     its value is used as the default for the other trace constants.
     Setting it true is a quick and reliable way to turn on every type of
     trace.

TRACE_EVENTS
     The music goes around and around, and it comes out here.  Enabling
     TRACE_EVENTS causes POE::Kernel to tell you what happens to FIFO and
     alarm events: when they're enqueued, dispatched or discarded, and what
     their states return.

TRACE_GARBAGE
     TRACE_GARBAGE shows what's keeping sessions alive.  It's useful for
     determining why a session simply refuses to die, or why it won't stay
     alive.

TRACE_PROFILE
     This trace constant switches on state profiling, causing POE::Kernel
     to keep a count of every state it dispatches.  It displays a frequency
     report when the event loop finishes.

TRACE_QUEUE
     TRACE_QUEUE complements TRACE_EVENTS.  When enabled, it traces the
     contents of POE's event queues, giving some insight into how events
     are ordered.  This has become less relevant since the alarm and FIFO
     queues have separated.

TRACE_REFCOUNT
     Setting TRACE_REFCOUNT to true enables debugging output whenever an
     external reference count changes.

TRACE_SELECT
     TRACE_SELECT enables or disables statistics about POE::Kernel's
     default select loop's select parameters and return values.

POE::Kernel Exports
===================

   POE::Kernel exports two symbols for your coding enjoyment: $poe_kernel
and $poe_main_window.  POE::Kernel is implicitly used by POE itself, so
using POE gets you POE::Kernel (and its exports) for free.

$poe_kernel
     This contains a reference to the process' POE::Kernel instance.  It's
     mainly useful for getting at the kernel from places other than states.
     For example, most programs call `$poe_kernel-'run()> to run its event
     loop.

     States rarely need to use $poe_kernel directly since they receive a
     copy of it in $_[KERNEL].

$poe_main_window
     POE creates a "main" or "top-level" window when Tk or Gtk are used.
     Tk requires a main window before its events can be used, and both
     toolkits signal destruction through a top-level window callback.  That
     callback is used to fire a UIDESTROY signal when a program is closed.

     Rather than waste the window, POE exports it as $poe_main_window.

PRIVATE KERNEL METHODS
======================

   The private kernel methods are private.  All the usual "here there be
private methods" caveats apply.  As such, they won't be documented here.
The terminally curious, however, will note that POE::Kernel contains a lot
of comments.

PUBLIC KERNEL METHODS
=====================

   This section discusses in more detail the POE::Kernel methods that
appear in the SYNOPSIS.  It uses the same syntax conventions as the
perlfunc manpage.

Methods to manage the process' global Kernel instance
-----------------------------------------------------

ID
     Return the POE::Kernel instance's unique identifier.

     Every POE::Kernel instance is assigned an ID at birth.  This ID tries
     to differentiate any given instance from all the others, even if they
     exist on the same machine.  The ID is a hash of the machine's name and
     the kernel's instantiation time and process ID.

          ~/perl/poe$ perl -wl -MPOE -e 'print $poe_kernel->ID'
          rocco.homenet-39240c97000001d8

run
     Runs the chosen event loop, returning only after every session has
     stopped.  It returns immediately if no sessions have yet been started.

          $poe_kernel->run();
          exit;

     The run() method does not return a meaningful value.

FIFO event methods
------------------

   Events posted with these methods are dispatched back to sessions in
first-in/first-out order (in case you didn't know what FIFO meant).

   Sessions will not spontaneously stop if they have pending FIFO events.
In other words, FIFO events keep sessions alive.

post SESSION, STATE_NAME, PARAMETER_LIST
post SESSION, STATE_NAME
     Posts an event for STATE_NAME in SESSION.  If a PARAMETER_LIST is
     included, its values will be used as arguments to STATE_NAME.

          $_[KERNEL]->post( $session, 'do_this' );
          $_[KERNEL]->post( $session, 'do_that', $with_this, $and_this );
          $_[KERNEL]->post( $session, 'do_that', @with_these );

     The post() method a boolean value indicating whether the event was
     enqueued successfully.  The $! variable will explain why post()
     failed.

        * ESRCH

          POE cannot find SESSION.

yield STATE_NAME, PARAMETER_LIST
yield STATE_NAME
     Posts an event for STATE_NAME in the current session.  If a
     PARAMETER_LIST is included, its values will be used as arguments to
     STATE_NAME.  Observant readers will note that this is just post() to
     the current session.

     Events posted with yield() must propagate through POE's FIFO before
     they're dispatched.  This effectively yields FIFO time to other
     sessions which already have events enqueued.

          $kernel->yield( 'do_this' );
          $kernel->yield( 'do_that', @with_these );

     The yield() method does not return a meaningful value.

call SESSION, STATE_NAME, PARAMETER_LIST
call SESSION, STATE_NAME
     Calls STATE_NAME in a SESSION, bypassing the FIFO.  Values from the
     optional PARAMETER_LIST will be passed as arguments to STATE_NAME at
     dispatch time.  The call() method returns its status in $!, which is 0
     for success or a nonzero reason for failure.

          $return_value = $kernel->call( 'do_this_now' );

     POE uses call() to dispatch some resource events without FIFO latency.
     Filehandle watchers, for example, would continue noticing a handle's
     readiness until the it was serviced by a state.  This could result in
     several redundant readiness events being enqueued before the first one
     was dispatched.

     Reasons why call() might fail:

        * ESRCH

          POE disbelieves in SESSION.

Alarm and delay methods
-----------------------

   POE also manages timed events.  These are events that should be
dispatched after at a certain time or after some time has elapsed.  Alarms
and delays always are enqueued for the current session, so a SESSION
parameter is not needed.

   POE's timed events fall into two major categories: ones which are to be
dispatched at an absolute time, and ones that will be dispatched after a
certain amount of time has elapsed.

   Each category is further divided into methods that clear previous timed
events before posting new ones, and methods that post timed events in
addition to the ones already in the queue.

   POE will use Time::HiRes to increase timed events' accuracy.  It will
use the less accurate time(2) if Time::HiRes isn't available.

   Sessions will not spontaneously stop if they have pending timed events.
In other words, these events keep sessions alive.

alarm STATE_NAME, EPOCH_TIME, PARAMETER_LIST
alarm STATE_NAME, EPOCH_TIME
alarm STATE_NAME
     Clears all the timed events destined for STATE_NAME in the current
     session then optionally sets a new one.  The new timed event will be
     dispatched to STATE_NAME no earlier than EPOCH_TIME and can include
     values from an optional PARAMETER_LIST.

     The timed event queue is kept in time order.  Posting an alarm with an
     EPOCH_TIME in the past will do the obvious thing.

     The first two forms reset a one-shot timed event by clearing any
     pending ones for STATE_NAME before setting a new one.

          $kernel->alarm( 'do_this', $at_this_time, @with_these_parameters );
          $kernel->alarm( 'do_this', $at_this_time );

     The last form clears all pending timed events for the state without
     setting a new one.

          $kernel->alarm( 'do_this' );

     This method will clear timed events regardless of how they were set.

     `alarm()' returns 0 on success or a reason for its failure:

        * EINVAL

          STATE_NAME is undefined.

alarm_add STATE_NAME, EPOCH_TIME, PARAMETER_LIST
alarm_add STATE_NAME, EPOCH_TIME
     Sets an additional timed event for STATE_NAME in the current session
     without clearing previous ones.  The timed event will be dispatched no
     earlier than EPOCH_TIME.

          $kernel->alarm_add( 'do_this', $at_this_time, @with_these_parameters );
          $kernel->alarm_add( 'do_this', $at_this_time );

     Use the alarm() or delay() method to clear timed events set by
     alarm_add().

     `alarm_add()' returns 0 on success or a reason for failure:

        * EINVAL

          Either STATE_NAME or EPOCH_TIME is undefined.

delay STATE_NAME, SECONDS, PARAMETER_LIST
delay STATE_NAME, SECONDS
delay STATE_NAME
     Clears all the timed events destined for STATE_NAME in the curernt
     session then optionally sets a new one.  The new timed event will be
     dispatched to STATE_NAME after no fewer than SECONDS have elapsed. If
     the optional PARAMETER_LIST is included, then its values will be
     passed along to the state when it's invoked.

     delay() uses whichever time(2) is available to POE::Kernel.  It uses
     the more accurate Time::HiRes::time() if it's available, or plain
     time(2) if it's not.  This obviates the need to check for Time::HiRes
     in your own code.

     The timed event queue is kept in time order, and delays posted with
     negative SECONDS will do the obvious thing.  SECONDS may be fractional
     regardless of which time() function is available.

     The first two forms enqueue a new delay after the pending timed events
     for STATE_NAME are cleared.

          $kernel->delay( 'do_this', $after_this_much_time, @with_these );
          $kernel->delay( 'do_this', $after_this_much_time );

     The last form clears pending timed events without setting a new one.

          $kernel->delay( 'do_this' );

     delay() returns 0 on success or a reason for its failure:

        * EINVAL

          STATE_NAME is undefined.

delay_add STATE_NAME, SECONDS, PARAMETER_LIST
delay_add STATE_NAME, SECONDS
     Sets an additional timed event for STATE_NAME in the current session
     without clearing previous ones.  The event will be dispatched no
     sooner than SECONDS seconds hence.

          $kernel->delay_add( 'do_this', $after_this_much_time, @with_these );
          $kernel->delay_add( 'do_this', $after_this_much_time );

     Use the alarm() or delay() method to clear timed events set by
     alarm_add().

     `delay_add()' returns 0 on success or a reason for failure:

        * EINVAL

          Either STATE_NAME or SECONDS is undefined.

queue_peek_alarms
     Returns a time-ordered list of state names in the current session that
     have pending timed events.

          my @pending_alarms = $kernel->queue_peek_alarms();

Symbolic name, or session alias methods
---------------------------------------

   Methods in this section allow sessions to refer to each-other by
symbolic name or numeric ID.

   Session IDs are quite a lot like process IDs, but they are unique to
the sessions within the current POE::Kernel.  In theory, a combination of
POE::Kernel and Session IDs should be enough to uniquely identify a
particular session anywhere in the world.

   Most POE::Kernel methods resolve SESSION internally, so it's possible
to refer to sessions by a number of things.  See the alias_resolve()
description for more information.

   Sessions will not spontaneously stop if they have aliases.  In other
words, aliases keep sessions alive.

alias_set ALIAS
     Sets an ALIAS for the current session.  ALIAS then may be used nearly
     everywhere instead of SESSION.  Sessions may have more than one ALIAS;
     each must be defined in a separate alias_set() call.

          $kernel->alias_set( 'ishmael' );

     Having an alias "daemonizes" a session, allowing it to stay alive even
     when there's nothing for it to do.  Sessions can use this to become
     autonomous services that other sessions refer to by name.

          $kernel->alias_set( 'httpd' );
          $kernel->post( 'httpd', 'set_handler', 'URI_regexp', 'my_state' );

     alias_set() returns 0 on success, or a nonzero failure indicator:

        * EEXIST

          The alias already is assigned to a different session.

alias_remove ALIAS
     Clears an existing ALIAS from the current session.  ALIAS will no
     longer refer to this session.

          $kernel->alias_remove( 'shirley' );

     The session will begin its destruction if the alias was all that kept
     it alive.

     alias_remove() returns 0 on success or a reason for its failure:

        * ESRCH

          POE::Kernel disavows all knowledge of the alias.

        * EPERM

          The alias belongs to another session, and the current one has no
          permission to clear it.

alias_resolve ALIAS
     Resolves an alias name into a session reference.  alias_resolve() has
     been overloaded over time to look up additional things, and now ALIAS
     may be:

     A session alias:

          $session_reference = $kernel->alias_resolve( 'irc_component' );

     A stringified session reference:

          $blessed_session_reference = $kernel->alias_resolve( "$stringified_one" );

     Or a session ID:

          $session_reference = $kernel->alias_resolve( $session_id );

     alias_resolve() returns undef upon failure, setting $! to explain the
     error:

        * ESRCH

          POE::Kernel can't find ALIAS anywhere.

     The following functions work with IDs directly.  They were at one
     point depreciated, but it was decided to keep them since they're
     faster than alias_resolve() for working solely with session IDs.

     For example, Philip Gwyn's inter-kernel calls module,
     POE::Component::IKC, uses these to resolve sessions across processes.

ID_id_to_session SESSION_ID
     Resolves a session reference from a SESSION_ID.

          $session_reference = ID_id_to_session( $session_id );

     It returns a session reference on success or undef on failure.  If it
     fails, $! contains the reason why:

        * ESRCH

          POE::Kernel doesn't have session SESSION_ID.

ID_session_to_id SESSION_REFERENCE
     Resolves a session ID from a session reference.  This is virtually
     identical to SESSION_REFERENCE->ID, except that SESSION_REFERENCE may
     be stringified:

          $session_id = ID_session_to_id( $stringified_session_reference );

     It returns a session ID on success or undef in the case of a failure.
     If it fails, $! says why:

        * ESRCH

          POE::Kernel has no session matching SESSION_REFERENCE.

Filehandle watcher methods
--------------------------

   Sessions use these methods to tell POE::Kernel what type of filehandle
activity they're interested in.  POE::Kernel synchronously calls states
registered to deal with filehandle activity when one of these interesting
events occurs.

   States are called synchronously so that the filehandle activity may be
dealt with immediately.  This avoids the watcher seeing the same activity
twice.  When a state is called, it receives a copy of the filehandle in
$_[ARG0].  ARG0 is one of POE::Session's parameter offset constants; you
can read more about it in the POE::Session manpage.

   Sessions will not spontaneously stop as long as they are watching at
least one filehandle.  In other words, watching a filehandle keep a
session alive.

   States that are invoked by select watchers receive some parameters to
help them remember why they were called.

select_read FILE_HANDLE, STATE_NAME
select_read FILE_HANDLE
     Starts and stops calling the current session's STATE_NAME state when
     FILE_HANDLE becomes ready for reading.

          $kernel->select_read( $filehandle, 'do_a_read' );
          $kernel->select_read( $filehandle );

     select_read() does not return a meaningful value.

select_write FILE_HANDLE, STATE_NAME
select_write FILE_HANDLE
     Starts and stops calling the current session's STATE_NAME state when
     FILE_HANDLE becomes ready for writing.

          $kernel->select_write( $filehandle, 'flush_some_data' );
          $kernel->select_write( $filehandle );

     select_write() does not return a meaningful value.

select_expedite FILE_HANDLE, STATE_NAME
select_expedite FILE_HANDLE
     Starts and stops calling the current session's STATE_NAME state when
     FILE_HANDLE becomes ready for out-of-band reading.

          $kernel->select_expedite( $filehandle, 'do_an_oob_read' );
          $kernel->select_expedite( $filehandle );

     select_expedite() does not return a meaningful value.

select_pause_write FILE_HANDLE
select_resume_write FILE_HANDLE
     Temporarily pauses and resumes write watching on a filehandle.  These
     functions only manipulate the select(2) write bits for FILE_HANDLE.
     They don't perform full resource management on FILE_HANDLE.  This
     makes select_pause_write() and select_resume_write() ideal for data
     flushers.

          $kernel->select_pause_write( $filehandle );
          $kernel->select_resume_write( $filehandle );

     These methods don't return meaningful values.

select FILE_HANDLE, READ_STATE_NAME, WRITE_STATE_NAME, EXPEDITE_STATE_NAME
     Sets or clears read, write, and expedite watchers on a filehandle all
     together.  Watchers for defined state names will be set, and undefined
     state names will clear the corresponding watchers.

     For example, set all three:

          $kernel->select( $filehandle, 'do_a_read', 'flush', 'read_oob' );

     And to clear all three:

          $kernel->select( $filehandle );

     To configure watchers for a read-only handle:

          $kernel->select( $filehandle, 'do_a_read', undef, 'read_oob' );

     And a write-only handle:

          $kernel->select( $filehandle, undef, 'flush' );

     This method does not return a meaningful value.

Signal watcher and generator methods
------------------------------------

   Sessions always receive signal events, even if they aren't explicitly
watching for them.  These signal watcher methods merely manage mappings
between signal names and state names.  The POE::Session manpage describes
the default signal handler state, _signal, in a little more detail.

   Unlike with the previous resource watchers, sessions may spontaneously
stop even if they are hold signal name maps.  In other words, signal name
maps *do not* keep sessions alive.

   POE does not make Perl's signal handling safe by itself.  The Event
module, however, does implement safe signals, and POE will take advantage
of them when they're available.

   Most signals propagate depth first through the sessions' parent/child
relationships.  That is, they are delivered to grandchildren, then
children, then parents, then grandparents, all the way back to the global
POE::Kernel instance, which is the oldest ancestor in the tree.

   There are three signal levels: nonmaskable, terminal, and benign.

   A benign signal never stops a session, even if the session doesn't
handle it.  Most signals are benign.  Note, however, that at the time of
this writing even benign signals can crash Perl.

   A terminal signal will stop any session that doesn't handle it.  There
are relatively few terminal signals: HUP, IDLE (fictitious; explained
below), INT, KILL, QUIT, TERM.

   A nonmaskable signal always stops a session, even if the session says
it's been handled.  There are only two nonmaskable signals, and they both
are fictitious and explained shortly: ZOMBIE and UIDESTROY.

   A signal handling state's return value tells POE whether it handled the
signal.  A true return value means that the state handled the signal; a
false value indicates that the state did not.  Handling a signal does not
prevent it from propagating up the sessions' relationship tree.

   As was previously mentioned, POE generates three fictitious signals.
These notify sessions when extraordinary circumstances occur.  They are
IDLE, UIDESTROY and ZOMBIE.

   The terminal IDLE signal is posted when the only sessions remaning are
alive by virtue of having aliases.  This situation occurs when daemon
sessions exist without any clients to interact with.  POE posts IDLE to
them, giving them an opportunity to prove they're not yet dead.

   The UIDESTROY signal is, regrettably nonmaskable.  It indicates that
the program's UI has signaled its destruction.  In Gtk and Tk, it means
that the main or top-level window is being closed, and everything must go.

   ZOMBIE is a nonmaskable signal as well.  It's posted if IDLE hasn't
been effective in waking any lingering daemon sessions.  It tells the
remaining sessions that they've wasted their opportunity to do something,
and now it's time to die.

   Three system signals have special handling.  They are SIGCH?LD,
SIGPIPE, and SIGWINCH.

   POE::Kernel's SIGCHLD and SIGCLD handlers both appear to sessions as
CHLD.  The Kernel's handlers automatically call waitpid(2) on behalf of
sessions, collecting stopped child process' IDs and return values.  CHLD
signal handlers receive stopped child PIDs in $_[ARG1], and the return
value form $? in $_[ARG2].  As usual, $_[ARG0] contains 'CHLD'.

   POE::Kernel's SIGPIPE handler only posts PIPE to the currently running
session.  This may be a problem since signals are delivered asynchronously
to processes; the author has been saved so far because nobody seems to use
SIGPIPE for anything anyway.

   Finally, SIGWINCH is just ignored outright.  Window managers generate
several of these all at once, which, at the time of this writing, kills
Perl in short order.

sig SIGNAL_NAME, STATE_NAME
sig SIGNAL_NAME
     Registers or unregisters a handler for SIGNAL_NAME.  Signal names are
     the same as %SIG use, with one exception: CLD will be delivered as
     CHLD, so sessions handling CHLD will get both.

          $kernel->sig( INT => 'sigint_handler' );

     The handler for SIGNAL_NAME will be unregistered if STATE_NAME is
     omitted.

          $kernel->sig( INT );

     It is possible to register handlers for signals that the operating
     system will never deliver.  This allows sessions to watch for
     fictitious signals that are generated through POE instead of kill(2).

     The sig() method does not return a meaningful value.

signal SESSION, SIGNAL_NAME
     Posts a signal to a session through POE::Kernel rather than via
     kill(2).  SIGNAL_NAME needn't be supported by the underlying operating
     system.

          $kernel->signal( $session, 'DIEDIEDIE' );

     POE::Kernel's signal() method doesn't return a meaningful value.

State management methods
------------------------

   These methods allow sessions to modify their states at runtime.  It
would be rude to alter other sessions' states, so these methods only
affects the current session.

state STATE_NAME
state STATE_NAME, CODE_REFERENCE
state STATE_NAME, OBJECT_REFERENCE
state STATE_NAME, OBJECT_REFERENCE, OBJECT_METHOD_NAME
state STATE_NAME, PACKAGE_NAME
state STATE_NAME, PACKAGE_NAME, PACKAGE_METHOD_NAME
     Adds a new state to the current session, removes an existing state
     from it, or replaces an existing state in it.

     The first form deletes a state, regardless whether it's handled by a
     code reference, an object method or a package method.

          $kernel->state( 'do_this' );

     The second form registers a new handler or overwrites an existing one
     with a new coderef.  They were originally called inline states because
     early POE prototypes defined them with inline anonymous subs.

          $kernel->state( 'do_this', \&this_does_it );

     The third and fourth forms register a new handler or overwrite an
     existing one with an object method.  These are known as object states.
     In the third form, the object's method matches the state's name:

          $kernel->state( 'do_this', $with_this_object );

     The fourth form allows state names to be mapped to differently named
     object methods.  This example defines a mapped object state:

          $kernel->state( 'do_this', $with_this_object, $and_this_method );

     The fifth and sixth forms allow state names register a new handler or
     owerwrite an existing one with a package method.  These are known as
     package states.  In the fifth form, the package's method matches the
     state's name:

          $kernel->state( 'do_this', $with_this_package );

     The sixth form allows state names to be mapped to differently named
     package methods.  This example defines a mapped package state:

          $kernel->state( 'do_this', $with_this_package, $and_this_method );

     POE::Kernel's state() method returns 0 on success or a nonzero code
     explaining why it failed:

        * ESRCH

          POE::Kernel has no knowledge of the currently active session.
          This occurs when state() is called when no session is active.

External reference count methods
--------------------------------

   External reference counts were created so POE could cooperate with
other event loops.  They external resource watchers to prevent sessions
from spontaneously self-destructing.  Held external events essentially say
"Ok, don't die 'til I'm done."

   External reference counts are kept by name.  This feature is still
relatively new, so there is no convention in place to prevent namespace
collisions.  If anyone has ideas about this, please contact the author.

refcount_increment SESSION_ID, REFCOUNT_NAME
refcount_decrement SESSION_ID, REFCOUNT_NAME
     Increments or decrements a reference count called REFCOUNT_NAME in the
     session identified by SESSION_ID.  Returns undef on failure, or the
     new reference count on success.

          $new_count = $kernel->refcount_increment( $session_id, 'postback' );
          $new_count = $kernel->refcount_decrement( $session_id, 'postback' );

     These methods set $! upon failure:

        * ESRCH

          The session formerly known as SESSION_ID no longer (or perhaps
          never did) exist.

Kernel Data Accessors
---------------------

   These functions provide a consistent interface to the Kernel's internal
data.

get_active_session
     This function returns a reference to the session which is currently
     being invoked by the Kernel.  When no session is currently being
     invoked, it returns a reference to the Kernel itself.  This is one of
     the times where the Kernel pretends its a session.

     Note, though, that the Kernel does not have a heap.  Attempting
     something like this will fail if get_active_session() returns a
     reference to the Kernel.

          $kernel->get_active_session()->get_heap()->{key} = $value;

SEE ALSO
========

   The POE manpages contains holistic POE information.

BUGS
====

   There are no currently known bugs.  If you find one, tell the author!

AUTHORS & COPYRIGHTS
====================

   Please see the POE manpage for authors and licenses.

a Nondeterministic Finite Automaton session
*******************************************

NAME
====

   POE::NFA - a Nondeterministic Finite Automaton session

SYNOPSIS
========

     use POE::NFA;

     # Define a machine's states, each state's events, and the coderefs
     # that handle each event.
     my %states =
       ( start =>
         { event_one => \&handler_one,
           event_two => \&handler_two,
           ...,
         },
         other_state =>
         { event_n          => \&handler_n,
           event_n_plus_one => \&handler_n_plus_one,
           ...,
         },
         ...,
       );

     # Spawn a state machine, and enter an initial state/event pair.
     POE::NFA->spawn( inline_states => \%states
                    )->goto_state( $start_state, $start_event );

     # Enter a new state without the intention of returning to the
     # current one.
     $machine->goto_state( $new_state, $new_event, @args );

     # Enter a new state with the intention of resuming the current
     # state.  $return_event is the event in the calling state that will
     # be invoked when the called state returns.
     $machine->call_state( $return_event, $new_state, $new_event, @args );

     # Return from the current state to its calling state.  The caller's
     # $return_event (from a previous call_state() call) will be invoked
     # with @returns.
     $machine->return_state( @returns );

     # Force the machine to stop.  The machine also will stop if it runs
     # out of events or event sources (such as filehandles or alarms).
     $machine->stop();

DESCRIPTION
===========

   This document assumes the reader already is familiar with POE::Session.

   POE::NFA instances run a particular kind of session: the
nondeterministic finite automaton (NFA).  NFAs are state machines which
determine the next state to be in by conditions at runtime.  This is
different from DFA (deterministic FAs), which have next states determined
for them at compile time.

Resource Tracking
-----------------

   See POE::Session's documentation.

Job Control and Family Values
-----------------------------

   See POE::Session's documentation.

State Types
-----------

   See POE::Session's documentation.

   Only inline_states are supported at this time.

POE::NFA Exports
================

   See POE::Session's documentation.

   Three exported constants differ from POE::Session:

MACHINE
     This is equivalent to POE::Sesion's SESSION constant.  It holds a
     reference to the current state machine, and it's useful for calling
     methods on it:

          $_[MACHINE]->goto_state( $next_state, $next_state_entry_event );

RUNSTATE
     This is equivalent to POE::Session's HEAP constant.  It holds an
     anonymous hash reference which POE will guarantee not to touch.  Each
     POE::NFA instance gets its own RUNSTATE.  This is a great place to put
     machine-scoped data.

EVENT
     This is equivalent to POE::Session's STATE constant.  It contains the
     name of the event which invoked the current event handler.  This is
     mainly for the _default state, which may need to know what was
     supposed to be invoked.

POE::NFA's Predefined Events
============================

   See POE::Session's documentation on "Predefined States".

   POE::NFA defines four events of its own:

poe_nfa_goto_state
poe_nfa_pop_state
poe_nfa_push_state
poe_nfa_stop
     POE::NFA uses these four states internally to manage state transitions
     and stopping the machine in an orderly fashion.  There may be others
     in the future, and they will all follow the /^poe_nfa_/ naming
     convention.  To avoid conflicts, please don't define events beginning
     with "poe_nfa_".

States' Return Values
---------------------

   See POE::Session's documentation.

PUBLIC METHODS
==============

   See POE::Session's documentation.

ID
     Same as with POE::Session.

no create method
no new method
     Instead, POE::NFA uses a spawn() method to spawn a new NFA nistance.
     The NFA is defined by one or more hashes that map state/event pairs to
     handlers:

          my %machine =
            ( state_1 =>
              { event_1 => \&handler_1,
                event_2 => \&handler_2,
              },
              state_2 =>
              { event_1 => \&handler_3,
                event_2 => \&handler_4,
              },
            );

     The same event may exist in different states.  POE::NFA will call the
     appropriate handler for the current event in the current state.  For
     example, if event_1 is dispatched while the machine is in state_2,
     then handler_3 will be called.  This happens because...

          $machine{state_2}->{event_1} = \&handler_3;

     POE::NFA's spawn() method currently only accepts inline_states and
     options.

option OPTION_NAME
option OPTION_NAME, OPTION_VALUE
option NAME_VALUE_PAIR_LIST
     Same as with POE::Session.

postback EVENT_NAME, PARAMETER_LIST
     Same as with POE::Session.

goto_state NEW_STATE
goto_state NEW_STATE, ENTRY_EVENT
goto_state NEW_STATE, ENTRY_EVENT, EVENT_ARGS
     Puts the current machine into a new state.  If an ENTRY_EVENT is
     specified, then that event will be called when the machine enters the
     new state.  EVENT_ARGS, if specified, will be passed to it via
     `@_[ARG0..$#_]'.

          $_[MACHINE]->goto_state( 'next_state' );
          $_[MACHINE]->goto_state( 'next_state', 'call_this_event' );
          $_[MACHINE]->goto_state( 'next_state', 'call_this_event', @with_these_args );

stop
     This forces a machine to stop.  It's similar to posting _stop to the
     machine, but it does some extra NFA cleanup.  The machine will also
     stop gracefully if it runs out of things to do.

     `stop()' is heavy-handed.  It will force resource cleanup.  Circular
     references in the machine's RUNSTATE are not POE's responsibility.

          $_[MACHINE]->stop();

call_state RETURN_EVENT, NEW_STATE
call_state RETURN_EVENT, NEW_STATE, ENTRY_EVENT
call_state RETURN_EVENT, NEW_STATE, ENTRY_EVENT, EVENT_ARGS
     call_state is similar to goto_state, but the intention is that the
     new state will eventually return_state back.  It accepts an extra
     parameter, RETURN_EVENT, which is the event in the caller's state
     that will be called when the callee's state returns.  That is, the
     called state returns to our RETURN_EVENT.

     ENTRY_EVENT is the event in the called state that will be called when
     the machine enters it.  ENTRY_ARGS are passed to the called state's
     event via `@_[ARG0..$#_]'.

     RETURN_EVENT is the event in the *caller's* state that is invoked
     when the *callee* returns via return_state.  It receives
     return_state's RETURN_ARGS via `@_[ARG0..$#_]'.

return_state
return_state RETURN_ARGS
     Return to the most recent state which called call_state, optionally
     invoking the call_state's RETURN_EVENT, possibly with RETURN_ARGS.

          $_[MACHINE]->return_state( );
          $_[MACHINE]->return_state( 'success', $something );

SEE ALSO
========

   The POE manpage contains holistic POE information, including an up to
date list of the modules comprising it.  The POE::Session manpage is a
"must read", says the New York Times, and it covers many concepts which
this manpage casually glosses over.

BUGS
====

   See POE::Session's documentation.

   Object and package states aren't implemented.  Some other stuff is just
lashed together with twine.  POE::NFA needs some more development.

   The documentation is slapped together hastily, too.

AUTHORS & COPYRIGHTS
====================

   Please see the POE manpage for authors and licenses.

A Macro Preprocessor
********************

NAME
====

   POE::Preprocessor - A Macro Preprocessor

SYNOPSIS
========

     use POE::Preprocessor;

     macro max (one,two) {
       ((one) > (two) ? (one) : (two))
     }

     print {% max $one, $two %}, "\n";

     const PI 3.14159265359

     print "PI\n";  # Substitutions don't grok Perl!

     enum ONE TWO THREE
     enum 12 TWELVE THIRTEEN FOURTEEN
     enum + FIFTEEN SIXTEEN SEVENTEEN

     print "ONE TWO THREE TWELVE THIRTEEN FOURTEEN FIFTEEN SIXTEEN SEVENTEEN\n";

     if ($expression) {      # include
        ... lines of code ...
     }                       # include

     unless ($expression) {  # include
       ... lines of code ...
     } elsif ($expression) { # include
       ... lines of code ...
     } else {                # include
       ... lines of code ...
     }                       # include

DESCRIPTION
===========

   POE::Preprocessor is a Perl source filter that implements a simple
macro substitution language.

Macros
------

   The preprocessor defines a "macro" compile-time directive:

     macro macro_name (parameter_0, parameter_1) {
       macro code ... parameter_0 ... parameter_1 ...
     }

   The parameter list is optional for macros that don't accept parameters.

   Macros are substituted into a program with a syntax borrowed from
Iaijutsu and altered slightly to jive with Perl's native syntax.

     {% macro_name parameter_0, parameter_1 %}

Constants and Enumerations
--------------------------

   Constants are defined this way:

     const CONSTANT_NAME    'constant value'
     const ANOTHER_CONSTANT 23

   Enumerations can begin with 0:

     enum ZEROTH FIRST SECOND ...

   Or some other number:

     enum 10 TENTH ELEVENTH TWELFTH

   Or continue where the previous one left off, which is necessary because
an enumeration can't span lines:

     enum + THIRTEENTH FOURTEENTH FIFTEENTH ...

Conditional Code Inclusion (#ifdef)
-----------------------------------

   The preprocessor supports something like cpp's #if/#else/#endif by
usurping a bit of Perl's conditional syntax.  The following conditional
statements will be evaluated at compile time if they are followed by the
comment `# include':

     if (EXPRESSION) {      # include
       BLOCK;
     } elsif (EXPRESSION) { # include
       BLOCK;
     } else {               # include
       BLOCK;
     }                      # include

     unless (EXPRESSION) {  # include
       BLOCK;
     }                      # include

   The code in each conditional statement's BLOCK will be included or
excluded in the compiled code depending on the outcome of its EXPRESSION.

   Conditional includes are nestable, but else and elsif must be on the
same line as the previous block's closing brace.  This may change later.

DEBUGGING
=========

   POE::Preprocessor has three debugging constants: DEBUG (which traces
source filtering to stderr); DEBUG_INVOKE (which traces macro
substitutions); and DEBUG_DEFINE (which traces macro, const and enum
definitions).  They can be overridden prior to POE::Preprocessor's use:

     sub POE::Preprocessor::DEBUG        () { 1 } # trace preprocessor
     sub POE::Preprocessor::DEBUG_INVOKE () { 1 } # trace macro use
     sub POE::Preprocessor::DEBUG_DEFINE () { 1 } # trace macro/const/enum defs
     use POE::Preprocessor;

BUGS
====

   * Source filters are line-based, and so is the macro language.  The only
     constructs that may span lines are the brace-delimited macro
     definitions.  And those *must* span lines.

   * The regular expressions that detect and replace code are simplistic
     and may not do the right things when given challenging Perl syntax to
     parse.  This includes placing constants in strings.

   * Substitution is done in two phases: macros first, then constants.  It
     would be nicer (and more dangerous) if the phases looped around and
     around until no more substitutions occurred.

   * Optimum matches aren't, but they're better than nothing.

SEE ALSO
========

   The regexp optimizer is based on code in Ilya Zakharevich's Text::Trie.

AUTHOR & COPYRIGHT
==================

   POE::Preprocessor is Copyright 2000 Rocco Caputo.  All rights reserved.
POE::Preprocessor is free software; you may redistribute it and/or modify
it under the same terms as Perl itself.

a POE thread of execution
*************************

NAME
====

   POE::Session - a POE thread of execution

SYNOPSIS
========

   The POE manpage includes and describes a sample program.

     # Import POE::Session constants.
     use POE::Session;

   POE::Session has two different constructors.  The older one, new(), is
quite DWIMmy.  This was clever to begin with, but it has impeded
understanding and maintainability as time has passed, and now it's
somewhat depreciated.  The newer constructor, create(), is very DWIS,
which enables it to validate its parameters better and accept more of
them.  The create() constructor is therefore recommended over new().

     # This is the older, more DWIMmy session constructor.
     POE::Session->new(

     # These are called inline states because they originally were
     # defined using inline coderefs.
     state_one => \&coderef_one,
     state_two => sub { ... },

     # Plain object and package states map state names to identical
     # method names.  For example, $object_one->state_three() is called
     # to handle 'state_three':
     $object_one  => [ 'state_three', 'state_four',  'state_five'  ],
     $package_one => [ 'state_six',   'state_seven', 'state_eight' ],

     # Mapped object and package states may have different method names
     # for their state names.  For example, $package_two->method_ten()
     # is called to handle 'state_ten'.  Mapped states are defined by
     # hashrefs, which in turn define the relationships between state
     # names and their handlers' methods.
     $object_two  => { state_nine => 'method_nine', ... },
     $package_two => { state_ten  => 'method_ten', ... },

     # A list reference by itself indicates arguments to pass to the
     # session's _start state.  This can occur anywhere in the
     # constructor's parameters.
     \@start_args,
       );

     # This is the newer, more explicit constructor.
     POE::Session->create(

     # The list 'args' refers to is passed as arguments to the
     # session's special _start state.
     args => [ argument_zero, argument_one, ... ],

     # "Inline" states are named as such because they can (and
     # originally were) defined with inline anonymous coderefs.
     inline_states =>
       { state_one => \&coderef_one,
         state_two => sub { ... },
       },

     # These plain and aliased object states match the ones shown in
     # POE::Session->new's synopsis.  Note, though, that the right side
     # of the => operator is a list reference; not a hash reference.
     # 'object_states' is associated with a list reference so that
     # object references aren't stringified when they would become hash
     # keys.
     object_states =>
     [ $object_one => [ 'state_three', 'state_four', 'state_five' ],
       $object_two => { state_nine => 'method_nine' },
     ],

     # These plain and aliased package states match the ones shown in
     # POE::Session->new's synopsis.  'package_states' is associated
     # with a list reference for consistency with 'object_states'.
     package_states =>
     [ $package_one => [ 'state_six', 'state_seven', 'state_eight' },
       $package_two => { state_ten => 'method_ten' },
     ],

     # create() has one feature over new(), which is somewhat
     # depreciated and falling behind in features.  create() allows
     # session options to be set at creation time.  'options' refers to
     # a hash containing option names and initial values.
     options => \%options,

     # Specify a heap other than the default empty hashref.
     heap => [ ],
       );

   Other methods:

     # Retrieve a session's unique identifier.
     $session_id = $session->ID;

     # Retrieve a reference to the session's heap.
     $session_heap = $session->get_heap;

     # Set or clear session options.
     $session->option( trace => 1, default => 1 );
     $session->option( trace );

     # Create a postback.  This is an anonymous coderef that posts an
     # event back to the current session when called.  It's part of POE's
     # cooperation interface to other event loops and resource watchers.
     $postback_coderef = $session->postback( $state_name, @state_args );
     &{ $postback_coderef }( @additional_args );

DESCRIPTION
===========

   POE::Session is a framework that binds discrete states into machines.
It accepts states as constructor parameters, wraps them up, and notifies
POE::Kernel that it's ready to begin.  The Kernel registers the it for
resource management, then invokes its special _start state to let it know
it's cleared for take-off.

   As sessions run, they post their state transitions through the Kernel's
FIFO event queue.  The Kernel dispatches the transitions back to sessions
in turn, and the sessions invoke the appropriate states to handle them.
When several sessions do this, their state invocations are interleaved,
and cooperative multitasking ensues.  This is much more stable than the
current state of Perl's threads, and it lends itself to cleaner and more
efficient design for certain classes of programs.

Resource Tracking
-----------------

   Sessions have POE::Kernel and other event loops watch for resources on
their behalf.  They do this by asking them to invoke their states when
resources become active: "Be a dear and let me know when someone clicks on
this widget.  Thanks so much!"  In the meantime, they can continue running
other states or just do nothing with such staggering efficiency that other
sessions can run *their* states.

   Some resources need to be serviced right away or they'll faithfully
continue reporting their readiness.  Filehandles are like this.  The
states that service this sort of resource are called right away, bypassing
the Kernel's FIFO.  Otherwise the time spent between enqueuing and
dispatching the "Hi, love; your resource is ready."  event will also be
spent by POE enqueuing several copies of it.  That's bad form.  States
that service friendlier resources, such as signals, are notified through
the FIFO.

   External libraries' resource watchers usually expect to call a coderef
when a resource becomes ready.  POE::Session's postback() method provides
a coderef for them that, when called, posts notice of the event through
the Kernel's FIFO.  This allows POE to use every event watcher currently
known without requiring special code for each.  It should also support
future event watchers without requiring extra code, so sessions can take
advantage of them as soon as they're available.

   Most importantly, since POE::Kernel keeps track of everything sessions
do, it knows when they've run out of them.  Rather than let defunct
sessions forever consume memory without ever doing another thing, the
Kernel invokes their _stop states as if to say "Please switch off the
lights and lock up; it's time to go." and then destroys them.

   Likewise, if a session stops on its own and there still are opened
resource watchers, the Kernel can close them.  POE excels at long-running
services, and resource leaks shall not be tolerated.

Job Control and Family Values
-----------------------------

   Sessions are resources too, but they are watched automatically
throughout their lifetimes.  The Kernel can do this since it's keenly
aware of their arrivals and departures.  It has to be since it's managing
resources for them.

   Sessions spawn children by creating new sessions.  It's that simple.
New sessions' _parent states are invoked to tell them who their parents
are.  Likewise, their parents' _child states are invoked to let them know
when child sessions come and go.  These are very handy for job control.

State Types
-----------

   POE::Session can wrap three sorts of state.  Each has a name that
strives to describe exactly what it does, but they still need detailed
explanations, so here we go.

   * Inline states

     Inline states are merely coderefs.  They originally were defined with
     inline anonymous coderefs, like so:

          POE::Session->create(
            inline_states =>
            { state_name_one => sub { print "state one"; },
              state_name_two => sub { print "state two"; },
            }
          );

     This can be taken to the extreme, defining enormous state machines in
     a single POE::Session constructor.  Some people consider this
     delightfully Java-esque while others hate it to death.  Luckily for
     the latter people, named coderefs are also possible:

          sub state_code_one { print "state one"; }
          sub state_code_two { print "state two"; }

          POE::Session->create(
            inline_states =>
            { state_name_one => \&state_code_one,
              state_name_two => \&state_code_two,
            }
          );

   * Object states

     Then came states that could be implemented as object methods.  I
     believe Artur asked for these to interface POE with objects he'd
     already written.  In this case, every state is mapped to method call:

          POE::Session->create(
            object_states =>
            [ $object => [ 'state_name_one', 'state_name_two' ]
            ]
          );

     It's important to note that while inline_states maps to a hash
     reference, object_states maps to a list reference.  $object would have
     lost its blessing had object_states mapped to a hashref, and invoking
     its methods would be difficult.

     Sessions can bind methods from multiple objects, too:

          POE::Session->create(
            object_states =>
            [ $object_1 => [ 'state_name_one',   'state_name_two'  ],
              $object_2 => [ 'state_name_three', 'state_name_four' ],
            ]
          );

     Abigail then insisted that the hard link between state and method
     names be broken.  She uses the common convention of leading
     underscores denoting private symbols.  This conflicted with POE
     wanting to invoke _start and similarly named object methods.  So
     mapped states were born:

          POE::Session->create(
            object_states =>
            [ $object_1 => { state_one => 'method_one', state_two => 'method_two' },
              $object_2 => { state_six => 'method_six', state_ten => 'method_ten' },
            ]
          );

   * Package states

     States are little more than functions, which in turn can be organized
     into packages for convenient maintenance and use.  Package methods are
     invoked the same as object methods, so it was easy to support them
     once object states were implemented.

          POE::Session->create(
            package_states =>
            [ Package_One => [ 'state_name_one',   'state_name_two'  ],
              Package_Two => [ 'state_name_three', 'state_name_four' ],
            ]
          );

     You may have noticed that package_states maps to a list reference when
     it could just as well have mapped to a hash reference.  This was done
     for nothing more than consistency with object states.

     Mapped package states are also possible:

          POE::Session->create(
            package_states =>
            [ Package_One => { state_one => 'method_one', state_two => 'method_two' },
              Package_Two => { state_six => 'method_six', state_ten => 'method_ten' },
            ]
          );

POE::Session Exports
====================

   Each session maintains its state machine's runtime context.  Every
state receives its context as several standard parameters.  These
parameters tell the state about its Kernel, its Session, the transition,
and itself.  Any number of states' own parameters may exist after them.

   The parameters' offsets into @_ were once defined, but changing them
would break existing code.  POE::Session now defines symbolic constants
for states' parameters, and their values are guaranteed to reflect the
correct offsets into @_ no matter how its order changes.

   These are the values that make up a session's runtime context, along
with the symbolic constants that define their places in a state's
parameter list.

ARG0 =item ARG1 =item ARG2 =item ARG3 =item ARG4 =item ARG5 =item ARG6 =item ARG7 =item ARG8 =item ARG9
     These are the first ten of the state's own parameters.  The state's
     parameters are guaranteed to exist at the end of @_, so it's possible
     to pull variable numbers of them off the call stack with this:

          my @args = @_[ARG0..$#_];

     These values correspond to PARAMETER_LIST in many of POE::Kernel's
     methods.  In the following example, the words "zero" through "four"
     will be passed into "some_state" as @_[ARG0..ARG4].

          $_[KERNEL]->yield( some_state => qw( zero one two three four ) );

HEAP
     Every session includes a hash for storing arbitrary data.  This hash
     is called a heap because it was modelled after process heaps.  Each
     session has only one heap, and its data persists for the session's
     lifetime.  States that store their persistent data in the heap will
     always be saving it with the correct session, helping to ensure their
     re-entrancy with a minimum of work.

          sub _start {
            $_[HEAP]->{start_time} = time();
          }

          sub _stop {
            my $elapsed_runtime = time() - $_[HEAP]->{start_time};
            print 'Session ', $_[SESSION]->ID, " elapsed runtime: $elapsed_runtime\n";
          }

KERNEL
     States quite often must call Kernel methods.  They receive a reference
     to the Kernel in $_[KERNEL] to assist them in this endeavor.  This
     example uses $_[KERNEL] post a delayed event:

          $_[KERNEL]->delay( time_is_up => 10 );

OBJECT
     Perl passes an extra parameter to object and package methods.  This
     parameter contains the object reference or package name in which the
     method is being invoked.  POE::Session exports this parameter's offset
     (which is always 0, by the way, but let's pretend it sometimes isn't)
     in the OBJECT constant.

     In this example, the ui_update_everything state multiplexes a single
     notification into several calls to the same object's methods.

          sub ui_update_everything {
            my $object = $_[OBJECT];
            $object->update_menu();
            $object->update_main_window();
            $object->update_status_line();
          }

     Inline states are implemented as plain coderefs, and Perl doesn't pass
     them any extra information, so $_[OBJECT] is always undef for them.

SENDER
     Every state is run in response to an event.  These events can be
     posted state transitions or immediate resource service callbacks.  The
     Kernel includes a reference to the thing that generated the event
     regardless of its delivery method, and that reference is contained in
     $_[SENDER].

     The SENDER can be used to verify that an event came from where it
     ought to.  It can also be used as a return address so that responses
     can be posted back to sessions that sent queries.

     This example shows both common uses.  It posts a copy of an event back
     to its sender unless the sender happens to be itself.  The condition
     is important in preventing infinite loops.

          sub echo_event {
            $_[KERNEL]->post( $_[SENDER], $_[STATE], @_[ARG0..$#_] )
              unless $_[SENDER] == $_[SESSION];
          }

SESSION
     The SESSION parameter contains a reference to the current session.
     This provides states with access to their session's methods.

          sub enable_trace {
            $_[SESSION]->option( trace => 1 );
            print "Session ", $_[SESSION]->ID, ": dispatch trace is now on.\n";
          }

STATE
     A single state can have several different names.  For example:

          POE::Session->create(
            inline_states =>
            { one => \&some_state,
              two => \&some_state,
              six => \&some_state,
              ten => \&some_state,
            }
          );

     Sometimes it's useful for the state to know which name it was invoked
     by.  The $_[STATE] parameter contains just that.

          sub some_state {
            print( "some_state in session ", $_[SESSION]-ID,
                   " was invoked as ", $_[STATE], "\n"
                 );
          }

     $_[STATE] is often used by the _default state, which by default can be
     invoked as almost anything.

POE::Session's Predefined States
================================

   POE defines some states with standard functions.  They all begin with a
single leading underscore, and any new ones will also follow this
convention.  It's therefore recommended not to use a single leading
underscore in custom state names, since there's a small but positive
probability of colliding with future standard events.

   Predefined states generally have serious side effects.  The _start
state, for example, performs much of the task of setting up a session.
Posting a redundant _start state transition will dutifully attempt to
allocate a session that already exists, which will in turn do terrible,
horrible things to the Kernel's internal data.  Such things would normally
be outlawed outright, but the extra overhead to check for them hasn't yet
been deemed worthwhile.  Please be careful!

   Here now are the predefined standard states, why they're invoked, and
what their parameters mean.

_child
     The _child state is invoked to notify a parent session when a new
     child arrives or an old one departs.  Also see the _child state for
     more information.

     $_[ARG0] contains a string describing what the child is doing:

    'create'
          The child session has just been created.  The current session is
          its original parent.

    'gain'
          Another session has stopped, and we have just inherited this
          child from it.

    'lose'
          The child session has stopped, and we are losing it.

     $_[ARG1] is a reference to the child in question.  It will still be
     valid even if the child is in its death throes, but it won't last long
     enough to receive posted events.

     $_[ARG2] is only valid when a new session has been created ($_[ARG0]
     is 'create').  It contains the new child session's _start state's
     return value.

_default
     It's not illegal to dispatch an event that a session cannot handle.
     If such a thing occurs, the session's _default state is invoke
     instead.  If no _default state exists, then the event is discarded
     quietly.  While this is considered a feature, some people may be vexed
     by misspelled state names.  See POE::Session's option() method for
     information about catching typos.

     Strange state parameters change slightly when they invoke _default.
     The original state's name is preserved in $_[ARG0] while its arguments
     are preserved in $_[ARG1].  Everything else remains the same.

     Beware!  _default states can accidentally make programs that will only
     be stopped by SIGKILL.  This happens because _default will catch
     signals when a signal handler isn't defined.  Please read about signal
     handlers along with POE::Kernel's signal watchers for information on
     avoiding this unfortunate problem.

_parent
     The _parent state is invoked to notify a child session when it's being
     passed from one parent to another.  $_[ARG0] contains the session's
     previous parent, and $_[ARG1] contains its new one.

     The _child state is the other side of this coin.

_signal
     The _signal state is a session's default signal handler.  Every signal
     that isn't mapped to a specific state will be delivered to this one.
     If _signal doesn't exist but _default does, then _default gets it
     instead.  See the _default state's description for a reason why this
     may not be desirable.  If both _signal and _default are missing, then
     the signal is discarded unhandled.

     POE::Kernel's sig() method can map a specific signal to another state.
     The other state is called instead of _signal, unless it isn't there;
     then _default gets a chance to handle it, etc.

     $_[ARG0] contains the signal's name, as used by Perl's %SIG hash.

     A signal handler state's return value is significant.  Please read
     more about signal watchers and in the POE::Kernel manpage.

_start
     The Kernel invokes a session's _start state once the session has been
     registered and is ready to begin running.  Sessions that have no
     _start states are never started.  In fact, creating such silly
     sessions is illegal since POE wouldn't know how to start them.

     $_[SENDER] contains a reference to the new session's parent session.
     Sessions created before $poe_kernel->run() is called will have
     $_[KERNEL] for a parent.

     @_[ARG0..$#_] contain the arugments passed into the Session's
     constructor.  See the documentation for POE::Session->new() and
     POE::Session->create() for more information.

_stop
     The Kernel invokes a session's _stop state when it realizes the
     session has run out of things to do.  It then destroys the session
     once the _stop state returns.  A session's _stop state usually
     contains special destructor code, possibly to clean up things that the
     kernel can't.

     This state receives nothing special in @_[ARG0..$#_].

States' Return Values
---------------------

   States always are evaluated in a scalar context.  States that must
return more than one value should return them in an array or hash
reference.

   The values signal handling states return are significant and are
covered along with signal watchers in the POE::Kernel manpage.

   States are prohibited from returning references to objects in the POE
namespace.  It's too easy to do this accidentally, and it has often
confounded Perl's garbage collection in the past.

PUBLIC METHODS
==============

ID
     Returns the POE::Session instance's unique identifier.  This is a
     number that starts with 1 and counts up forever, or until something
     causes the number to wrap.  It's theoretically possible that session
     IDs may collide after at 4.29 billion sessions have been created.

create LOTS_OF_STUFF
     Bundles some states together into a single machine, then starts it
     running.

     LOTS_OF_STUFF looks like a hash of parameter name/value pairs, but
     it's really just a list.  It's preferred over the older, more DWIMmy
     new() constructor because each kind of parameter is explicitly named,
     and it can therefore unambiguously figure out what it is a program is
     trying to do.

    args => LISTREF
          Defines the arguments to give to the machine's _start state.
          They're passed in as @_[ARG0..$#_].

               args => [ 'arg0', 'arg1', 'etc.' ],

    heap => ANYTHING or NOTHING
          Defines the session's heap, which will be passed to each of its
          states in $_[HEAP].  Sessions are created with anonymous hash
          references by default, which are used like this:

               my $heap = $_[HEAP];
               $heap->{variable} = $value;  # simple hashref stuff

          It's possible, however, to use create's heap parameter to change
          that into a list reference, or even some sort of magical tied
          thing.  It's also possible to pre-populate a session's heap.

               POE::Session->create(
                 ...,
                 heap => [ 'mi',    # HEAP_ALIAS ( These are constants defined
                           [ ],     # HEAP_QUEUE   elsewhere.
                           0,       # HEAP_COUNT )
                         ],
                 ....,
               );

    inline_states => HASHREF
          Defines inline coderefs that make up some or all of the session's
          states.

               inline_states =>
               { _start => sub { print "arg0=$_[ARG0], arg1=$_[ARG1], etc.=$_[ARG2]\n"; }
                 _stop  => \&stop_state
               },

    object_states => LISTREF
          Defines object methods that make up some or all of the session's
          states.

          LISTREF is a list of parameter pairs.  The first member of each
          pair is an object reference.  The second member is either a list
          reference or hash reference.  When it's a list reference, the
          referenced list contains methods from the referenced object.
          The methods define states with the same names.  When it's a hash
          reference, the referenced hash contains state/method pairs which
          map state names to methods that may have different names.

          Perhaps some examples are in order!  This one defines two states,
          state_one and state_two, which are implemented as
          $object->state_one() and $object->state_two().

               object_states =>
               [ $object => [ 'state_one', 'state_two' ],
               ],

          This second example defines two other states, state_five and
          state_six, which are implemented as $object->do_five() and
          $object->do_six().

               object_states =>
               [ $object => { state_five => 'do_five',
                              state_six  => 'do_six',
                            },
               ],

          It's a lot simpler to do than to describe.

    options => HASHREF
          Sets one or more initial session options before starting it.
          Please see the POE::Session option() method for a list of
          available session options and what they do.

               option => { trace => 1, debug => 1 },

    package_states => LISTREF
          Defines package methods that make up some or all of the session's
          states.

          LISTREF is virtually identical to the one for object_states, so
          I'll just skip to the examples.  Check out object_states'
          description if you'd like more details, replacing "object" and
          "object reference" with "package" and "package name",
          respectively.

          So, here's a package_states invocation that defines two states,
          state_one and state_two, which are implemented as
          Package->state_one() and Package->state_two.

               package_states =>
               [ Package => [ 'state_one', 'state_two' ],
               ],

          And here's an invocation that defines two other states,
          state_five and state_six, to Package->do_five() and
          Package->do_six().

               package_states =>
               [ Package => { state_five => 'do_five',
                              state_six  => 'do_six',
                            },
               ],

          Easy-peasy!

new LOTS_OF_STUFF
     POE::Session's new() constructor is slighly depreciated in favor of
     the newer create() constructor.  A detailed description of
     POE::Session->new() is not forthcoming, but POE::Session's SYNOPSIS
     briefly touches upon its use.

option OPTION_NAME
option OPTION_NAME, OPTION_VALUE
option NAME_VALUE_PAIR_LIST
     Sets and/or retrieves options' values.

     The first form returns the value of a single option, OPTION_NAME.

          my $trace_value = $_[SESSION]->option( 'trace' );

     The second form sets OPTION_NAME to OPTION_VALUE, returning the
     previous value of OPTION_NAME.

          my $old_trace_value = $_[SESSION]->option( trace => $new_trace_value );

     The final form sets several options, returning a hashref containing
     their name/value pairs.

          my $old_values = $_[SESSION]->option(
            trace => $new_trace_value,
            debug => $new_debug_value,
          );
          print "Old option values:\n";
          while (my ($option, $value) = each %$old_values) {
            print "$option = $value\n";
          }

postback EVENT_NAME, PARAMETER_LIST
     Creates an anonymous coderef which, when called, posts EVENT_NAME back
     to the session.  Postbacks will keep sessions alive until they're
     destroyed.

     The EVENT_NAME event will include two parameters.  $_[ARG0] will
     contain a reference to the PARAMETER_LIST passed to postback().
     $_[ARG1] will hold a reference to the parameters given to the coderef
     when it's called.

     This example creates a Tk button that posts an "ev_counters_begin"
     event at a session whenever it's pressed.

          $poe_tk_main_window->Button
            ( -text => 'Begin Slow and Fast Alarm Counters',
              -command => $session->postback( 'ev_counters_begin' )
            )->pack;

     It can also be used to post events from Event watchers' callbacks.
     This one posts back "ev_flavor" with $_[ARG0] holding [ 'vanilla' ]
     and $_[ARG1] containing a reference to whatever parameters
     Event->flawor gives its callback.

          Event->flavor
            ( cb   => $session->postback( 'ev_flavor', 'vanilla' ),
              desc => 'post ev_flavor when Event->flavor occurs',
            );

get_heap
     Returns a reference to the session's heap.  This is the same value
     that's passed to the session in $_[HEAP].  The difference is that this
     method may be used by functions which are expected to be called by a
     session but which don't want the heap to be passed to them.  In those
     cases, the function would use $poe_kernel->get_active_session() first
     to determine the session context in which it was called:

          sub use_a_wheel {
            my @stuff_to_put = @_;
            $poe_kernel->get_active_session()->heap()->{wheel}->put(@stuff_to_put);
          }

     It probably is more efficient for sessions to pass $_[HEAP] along:

          sub use_a_wheel {
            my ($heap, @stuff_to_put) = @_;
            $heap->{wheel}->put(@stuff_to_put);
          }

     Or even:

          sub use_a_wheel {
            my $heap = shift;
            $heap->{wheel}->put(@_);
          }

     Although if you expect to have a lot of calls to &put_a_wheel() in
     your program, you may want to optimize for programmer efficiency by
     using the first form.

SEE ALSO
========

   The POE manpage contains holstic POE information, including an up to
date list of the modules comprising it.

BUGS
====

   There is a chance that session IDs may collide after Perl's integer
value wraps.  This can occur after as few as 4.29 billion sessions.

   If you find another, tell the author!

AUTHORS & COPYRIGHTS
====================

   Please see the POE manpage for authors and licenses.

high-level protocol logic
*************************

NAME
====

   POE::Wheel - high-level protocol logic

SYNOPSIS
========

     $wheel = new POE::Wheel::Something( ... )
     $wheel->put($some_logical_data_chunks);

DESCRIPTION
===========

   Wheels contain reusable chunks of high-level logic.  For example,
Wheel::FollowTail contains the algorithm for reading data from the end of
an ever growing file.  Their logic is contained in bundles of reusable
states which they insert into and remove from their owners during creation
and destruction.

   Giving a wheel to another session will not transfer related states.  As
a result, the original owner will continue receiving a wheel's events
until it's destroyed.

COMMON PUBLIC WHEEL METHODS
===========================

   These are the methods that are common to every wheel.

allocate_wheel_id
     This is a static function; it should be called as
     &POE::Wheel::allocate_wheel_id().  It returns a number that may be
     used to uniquely identify a wheel.  POE::Wheel keeps track of
     allocated IDs to avoid collisions, so it's important to free the ID
     when it's done.

free_wheel_id($wheel_id)
     Frees a wheel ID.  Used when a wheel is being destroyed.

new LOTS_OF_STUFF
     Creates a new wheel, returning its reference.  The reference holder
     should keep the wheel reference around until it's ready for the wheel
     to stop.

     Every wheel has a different purpose and requires different parameters,
     so LOTS_OF_STUFF will vary from one to the next.

DESTROY
     Perl calls DESTROY when the wheel's reference is relinquished.  This
     triggers the wheel's destruction, which releases whatever resources it
     was managing.

     When passing resources from one wheel to another, it's important to
     destroy the old wheel before creating the new one.  If the hand-off is
     not in this order, the old wheel's destruction will release the
     resource after the new one has started watching it.  The new wheel
     will then not be watching the resource, even though it ought to be.

put LIST
     Send a LIST of things through the wheel.  The LIST may only contain
     one thing, and that's ok.  Each thing in the LIST is serialized by the
     wheel's Filter, and then bufferend until the wheel's Driver can flush
     it to a filehandle.

event TYPE => STATE_NAME, ...
     Changes the states that are called when a wheel notices certain types
     of events occurring.

     The event() method's parameters are pairs of event TYPEs and the
     STATE_NAMEs to call when they occur.  Event TYPEs differ for each
     wheel, and their manpages will discuss them in greater detail.
     STATE_NAMEs may be undef, in which case the wheel will stop invoking a
     state for that TYPE of event.

          $_[HEAP]->{wheel}->event( InputState   => 'new_input_state',
                                    ErrorState   => undef,
                                    FlushedState => 'new_flushed_state',
                                  );

SEE ALSO
========

   POE::Wheel::FollowTail; POE::Wheel::ListenAccept;
POE::Wheel::ReadWrite; POE::Wheel::SocketFactory.

BUGS
====

   Wheels really ought to be replaced with a proper stream-based I/O
abstraction and POE::Component classes to replace FollowTail and
SocketFactory.

AUTHORS & COPYRIGHTS
====================

   Please see the POE manpage for authors and licenses.

POE FollowTail Protocol Logic
*****************************

NAME
====

   POE::Wheel - POE FollowTail Protocol Logic

SYNOPSIS
========

     $wheel = new POE::Wheel::FollowTail(
       Handle       => $file_handle,                 # File to tail
       Driver       => new POE::Driver::Something(), # How to read it
       Filter       => new POE::Filter::Something(), # How to parse it
       PollInterval => 1,                  # How often to check it
       InputState   => $input_event_name,  # State to call upon input
       ErrorState   => $error_event_name,  # State to call upon error
     );

DESCRIPTION
===========

   This wheel follows the end of an ever-growing file, perhaps a log file,
and generates events whenever new data appears.  It is a read-only wheel,
so it does not include a put() method.  It uses sysseek(2) wrapped in eval
{ }, so it should work okay on all sorts of files.  That is, if perl
supports select(2)'ing them on the underlying operating system.

PUBLIC METHODS
==============

   * POE::Wheel::FollowTail::event(...)

     Please see POE::Wheel.

   * POE::Wheel::FollowTail::ID()

     Returns the FollowTail wheel's unique ID.  This can be used to
     associate the wheel's events back to the wheel itself.

EVENTS AND PARAMETERS
=====================

   * PollInterval

     PollInterval is the number of seconds to wait between file checks.
     Once FollowTail re-reaches the end of the file, it waits this long
     before checking again.

   * SeekBack

     SeekBack is the number of bytes to seek back from the current end of
     file before reading.  By default, this is 4096, and data read up to
     the end of file is not returned.  (This is used to frame lines before
     returning actual data.)  If SeekBack is specified, then existing data
     up until EOF is returned, and then the wheel begins following tail.

   * InputState

     The InputState event is identical to POE::Wheel::ReadWrite's
     InputState.  It's the state to be called when the followed file
     lengthens.

     ARG0 contains a logical chunk of data, read from the end of the tailed
     file.  ARG1 contains the ID of the wheel that received this input.

   * ErrorState

     The ErrorState event contains the name of the state that will be
     called when a file error occurs.  The FollowTail wheel knows what to
     do with EAGAIN, so it's not considered a true error.  FollowTail will
     continue running even on an error, so it's up to the Session to stop
     things if that's what it wants.

     The ARG0 parameter contains the name of the function that failed.
     ARG1 and ARG2 contain the numeric and string versions of $! at the
     time of the error, respectively.  ARG3 contains the ID of the wheel
     that encountered the error; this is useful for closing the proper
     wheel when one of several has encountered an error.

     A sample ErrorState state:

          sub error_state {
            my ($operation, $errnum, $errstr) = @_[ARG0, ARG1, ARG2];
            warn "$operation error $errnum: $errstr\n";
          }

SEE ALSO
========

   POE::Wheel; POE::Wheel::ListenAccept; POE::Wheel::ReadWrite;
POE::Wheel::SocketFactory

BUGS
====

   This wheel can't tail pipes and consoles.  Blargh.

AUTHORS & COPYRIGHTS
====================

   Please see the POE manpage.

POE Listen/Accept Logic Abstraction
***********************************

NAME
====

   POE::Wheel::ListenAccept - POE Listen/Accept Logic Abstraction

SYNOPSIS
========

     $wheel = new POE::Wheel::ListenAccept(
       Handle      => $socket_handle,      # Listening socket
       AcceptState => $accept_state_name,  # Success state
       ErrorState  => $error_state_name,   # Failure state
     );

     $wheel->event( AcceptState => $new_state_name ); # Add/change state
     $wheel->event( ErrorState  => undef );           # Remove state

DESCRIPTION
===========

   ListenAccept waits for activity on a listening socket and accepts
remote connections as they arrive.  It generates events for successful and
failed connections (EAGAIN is not considered to be a failure).

   This wheel neither needs nor includes a put() method.

   ListenAccept is a good way to listen on sockets from other sources,
such as IO::Socket or plain socket() calls.

PUBLIC METHODS
==============

   * POE::Wheel::ListenAccept::event( ... )

     The event() method changes the events that a ListenAccept wheel emits
     for different conditions.  It accepts a list of event types and
     values.  Defined state names change the previous values.  Undefined
     ones turn off the given condition's events.

     For example, this event() call changes a wheel's AcceptState event and
     turns off its ErrorState event.

          $wheel->event( AcceptState => $new_accept_state_name,
                         ErrorState  => undef
                       );

   * POE::Wheel::ListenAccept::ID()

     Returns the ListenAccept wheel's unique ID.  This can be used to
     associate the wheel's events back to the wheel itself.

EVENTS AND PARAMETERS
=====================

   * AcceptState

     The AcceptState event contains the name of the state that will be
     called when a new connection has been accepted.

     The ARG0 parameter contains the accepted connection's new socket
     handle.

     ARG1 contains accept()'s return value.

     A sample AcceptState state:

          sub accept_state {
            my $accepted_handle = $_[ARG0];
            # Optional security things with getpeername might go here.
            &create_server_session($handle);
          }

   * ErrorState

     The ErrorState event contains the name of the state that will be
     called when a socket error occurs.  The ListenAccept wheel knows what
     to do with EAGAIN, so it's not considered an error worth reporting.

     The ARG0 parameter contains the name of the function that failed.
     This usually is 'accept'.  ARG1 and ARG2 contain the numeric and
     string versions of $! at the time of the error, respectively.

     A sample ErrorState state:

          sub error_state {
            my ($operation, $errnum, $errstr) = @_[ARG0, ARG1, ARG2];
            warn "$operation error $errnum: $errstr\n";
          }

SEE ALSO
========

   POE::Wheel; POE::Wheel::FollowTail; POE::Wheel::ReadWrite;
POE::Wheel::SocketFactory

BUGS
====

   Oh, probably some.

AUTHORS & COPYRIGHTS
====================

   Please see the POE manpage.

POE Read/Write Logic Abstraction
********************************

NAME
====

   POE::Wheel::ReadWrite - POE Read/Write Logic Abstraction

SYNOPSIS
========

     $wheel = new POE::Wheel::ReadWrite(

     # To read and write from the same handle, such as a socket, use
     # the Handle parameter:
     Handle       => $file_or_socket_handle,       # Handle to read/write

     # To read and write from different handles, such as a dual pipe to
     # a child process, or a console, use InputHandle and OutputHandle:
     InputHandle  => $readable_filehandle,         # Handle to read
     OutputHandle => $writable_filehandle,         # Handle to write

     Driver       => new POE::Driver::Something(), # How to read/write it

     # To read and write using the same line discipline, such as
     # Filter::Line, use the Filter parameter:
     Filter       => new POE::Filter::Something(), # How to parse in and out

     # To read and write using different line disciplines, such as
     # stream out and line in:
     InputFilter  => new POE::Filter::Something(),     # Read data one way
     OUtputFilter => new POE::Filter::SomethingElse(), # Write data another

     InputState   => $input_state_name,  # Input received state
     FlushedState => $flush_state_name,  # Output flushed state
     ErrorState   => $error_state_name,  # Error occurred state

     # To enable callbacks for high and low water events (using any one
     # of these options requires the rest):
     HighMark  => $high_mark_octets, # Outgoing high-water mark
     HighState => $high_mark_state,  # State to call when high-water reached
     LowMark   => $low_mark_octets,  # Outgoing low-water mark
     LowState  => $low_mark_state,   # State to call when low-water reached
       );

     $wheel->put( $something );
     $wheel->event( ... );

     # To set both the input and output filters at once:
     $wheel->set_filter( new POE::Filter::Something );

     # To set an input filter or an output filter:
     $wheel->set_input_filter( new POE::Filter::Something );
     $wheel->set_output_filter( new POE::Filter::Something );

     # To alter the high or low water marks:
     $wheel->set_high_mark( $new_high_mark_octets );
     $wheel->set_low_mark( $new_low_mark_octets );

     # To fetch driver statistics:
     $pending_octets   = $wheel->get_driver_out_octets();
     $pending_messages = $wheel->get_driver_out_messages();

     # To retrieve the wheel's ID:
     print $wheel->ID;

DESCRIPTION
===========

   The ReadWrite wheel does buffered, select-based I/O on a filehandle.
It generates events for common file conditions, such as when data has been
read or flushed.  This wheel includes a put() method.

PUBLIC METHODS
==============

   * POE::Wheel::ReadWrite::put($logical_data_chunk)

     The put() method uses a POE::Filter to translate the logical data
     chunk into a serialized (streamable) representation.  It then uses a
     POE::Driver to enqueue or write the data to a filehandle.  It also
     manages the wheel's write select so that any buffered data can be
     flushed when the handle is ready.

     The put() method returns a boolean value indicating whether the
     wheel's high water mark has been reached.  It will always return false
     if the wheel doesn't have a high water mark set.

     Data isn't flushed to the underlying filehandle, so it's easy for
     put() to exceed a wheel's high water mark without generating a
     HighState event.

   * POE::Wheel::ReadWrite::event(...)

     Please see POE::Wheel.

   * POE::Wheel::ReadWrite::set_filter( $poe_filter )

     The set_filter method changes the filter that the ReadWrite wheel uses
     to translate between streams and logical chunks of data.  It sets both
     the read and write filters.  It uses filters' get_pending() method to
     preserve any unprocessed input between the previous and new filters.

     Please be aware that this method has complex and perhaps non-obvious
     side effects.  The description of POE::Filter::get_pending() discusses
     them further.

     POE::Filter::HTTPD does not support the get_pending() method.
     Switching from an HTTPD filter to another one will display a reminder
     that it sn't supported.

   * POE::Wheel::ReadWrite::set_input_filter( $poe_filter )
     POE::Wheel::ReadWrite::set_output_filter( $poe_filter )

     These perform similar functions to the &set_filter method, but they
     change the input or output filters separately.

   * POE::Wheel::ReadWrite::set_high_mark( $high_mark_octets )
     POE::Wheel::ReadWrite::set_low_mark( $low_mark_octets )

     Sets the high and low watermark octet counts.  They will not take
     effect until the next $wheel->put() or internal buffer flush.
     POE::Wheel::ReadWrite->event() can change the high and low watermark
     events.

   * POE::Wheel::ReadWrite::ID()

     Returns the ReadWrite wheel's unique ID.  This can be used to
     associate the wheel's events back to the wheel itself.

EVENTS AND PARAMETERS
=====================

   * InputState

     The InputState event contains the name of the state that will be
     called for each chunk of logical data returned by the ReadWrite
     wheel's filter.

     The ARG0 parameter contains the chunk of logical data that was
     received.  ARG1 contains the ID of the wheel that received the input.

     A sample InputState state:

          sub input_state {
            my ($heap, $input, $wheel_id) = @_[HEAP, ARG0, ARG1];
            print "Echoing input from wheel $wheel_id: $input\n";
            $heap->{wheel}->put($input);     # Echo it back.
          }

   * FlushedState

     The FlushedState event contains the name of the state that will be
     called whenever the wheel's driver's output queue becomes empty.  This
     signals that all pending data has been written.  It comes with a
     single parameter, ARG0, that indicates which wheel flushed its buffer.

     A sample FlushedState state:

          sub flushed_state {
            # Stop a wheel after all outgoing data is flushed.
            # This frees the wheel's resources, including the
            # filehandle, and closes the connection.
            delete $_[HEAP]->{wheel}->{$_[ARG0]};
          }

   * ErrorState

     The ErrorState event contains the name of the state that will be
     called when a file error occurs.  The ReadWrite wheel knows what to do
     with EAGAIN, so it's not considered a true error.

     The ARG0 parameter contains the name of the function that failed.
     ARG1 and ARG2 contain the numeric and string versions of $! at the
     time of the error, respectively.  ARG3 holds the ID of the wheel that
     encountered an error; this is good for times when you have several
     wheels and need to know which one's having trouble.

     A sample ErrorState state:

          sub error_state {
            my ($heap, $operation, $errnum, $errstr, $wheel_id) =
              @_[HEAP, ARG0, ARG1..ARG3];
            warn "$operation error $errnum: $errstr\n";
            delete $heap->{wheels}->{$wheel_id}; # shut down that wheel
          }

   * HighState

     The HighState event indicates when the wheel's driver's output buffer
     has grows to reach HighMark octets of unwritten data.  This event will
     fire once when the output buffer reaches HighMark, and it will not
     fire again until a LowState event occurs.

     HighState and LowState together are used for flow control.  The idea
     is to perform some sort of throttling when HighState is called and
     resume full-speed transmission when LowState is called.

     HighState comes with ARG0, the ID of the wheel that encountered the
     high-water condition.

   * LowState

     The LowState event indicates when a wheel's driver's output buffer
     shrinks down to LowMark octets of unwritten data.  This event will
     only fire when the output buffer reaches LowMark after a HighState
     event.

     HighState and LowState together are used for flow control.  The idea
     is to perform some sort of throttling when HighState is called and
     resume full-speed transmission when LowState is called.

     LowState comes with ARG0, the ID of the wheel that encounterd the
     low-water condition.

SEE ALSO
========

   POE::Wheel; POE::Wheel::FollowTail; POE::Wheel::ListenAccept;
POE::Wheel::SocketFactory

BUGS
====

   Oh, probably some.

AUTHORS & COPYRIGHTS
====================

   Please see the POE manpage.

POE Socket Creation Logic Abstraction
*************************************

NAME
====

   POE::Wheel::SocketFactory - POE Socket Creation Logic Abstraction

SYNOPSIS
========

     use Socket; # For the constants

     # Listening Unix domain socket.
     $wheel = new POE::Wheel::SocketFactory(
       SocketDomain => AF_UNIX,               # Sets the socket() domain
       BindAddress  => $unix_socket_address,  # Sets the bind() address
       SuccessState => $success_state,        # State to call upon accept()
       FailureState => $state_failure,        # State to call upon error
       # Optional parameters (and default values):
       SocketType   => SOCK_STREAM,           # Sets the socket() type
     );

     # Connecting Unix domain socket.
     $wheel = new POE::Wheel::SocketFactory(
       SocketDomain  => AF_UNIX,              # Sets the socket() domain
       RemoteAddress => $unix_server_address, # Sets the connect() address
       SuccessState  => $success_state,       # State to call on connection
       FailureState  => $state_failure,       # State to call on error
       # Optional parameters (and default values):
       SocketType    => SOCK_STREAM,          # Sets the socket() type
       # Optional parameters (that have no defaults):
       BindAddress   => $unix_client_address, # Sets the bind() address
     );

     # Listening Internet domain socket.
     $wheel = new POE::Wheel::SocketFactory(
       BindAddress    => $inet_address,       # Sets the bind() address
       BindPort       => $inet_port,          # Sets the bind() port
       SuccessState   => $success_state,      # State to call upon accept()
       FailureState   => $state_failure,      # State to call upon error
       # Optional parameters (and default values):
       SocketDomain   => AF_INET,             # Sets the socket() domain
       SocketType     => SOCK_STREAM,         # Sets the socket() type
       SocketProtocol => 'tcp',               # Sets the socket() protocol
       ListenQueue    => SOMAXCONN,           # The listen() queue length
       Reuse          => 'no',                # Lets the port be reused
     );

     # Connecting Internet domain socket.
     $wheel = new POE::Wheel::SocketFactory(
       RemoteAddress  => $inet_address,       # Sets the connect() address
       RemotePort     => $inet_port,          # Sets the connect() port
       SuccessState   => $success_state,      # State to call on connection
       FailureState   => $state_failure,      # State to call on error
       # Optional parameters (and default values):
       SocketDomain   => AF_INET,             # Sets the socket() domain
       SocketType     => SOCK_STREAM,         # Sets the socket() type
       SocketProtocol => 'tcp',               # Sets the socket() protocol
       Reuse          => 'no',                # Lets the port be reused
     );

     $wheel->event( ... );

     $wheel->ID();

DESCRIPTION
===========

   This wheel creates sockets, generating events when something happens to
them.  Success events come with connected, ready to use sockets.  Failure
events are accompanied by error codes, similar to other wheels'.

   SocketFactory currently supports Unix domain sockets, and TCP sockets
within the Internet domain.  Other protocols are forthcoming, eventually;
let the author or mailing list know if they're needed sooner.

PUBLIC METHODS
==============

   * POE::Wheel::SocketFactory::new()

     The new() method does most of the work.  It has parameters for just
     about every aspect of socket creation: socket(), setsockopt(), bind(),
     listen(), connect() and accept().  Thankfully they all aren't used at
     the same time.

     (!!!) The new() method always returns the SocketFactory wheel's
     reference, even if the constructor didn't succeed.  This is different
     from versions before 0.1106.

     The parameters:

        * SocketDomain

          SocketDomain is the DOMAIN parameter for the socket() call.
          Currently supported values are AF_UNIX, AF_INET, PF_UNIX and
          PF_INET.  It defaults to AF_INET if omitted.

        * SocketType

          SocketType is the TYPE parameter for the socket() call.
          Currently supported values are SOCK_STREAM and SOCK_DGRAM
          (although datagram sockets aren't tested at this time).  It
          defaults to SOCK_STREAM if omitted.

        * SocketProtocol

          SocketProtocol is the PROTOCOL parameter for the socket() call.
          Protocols may be specified by name or number (see
          /etc/protocols, or the equivalent file).  The only supported
          protocol at this time is 'tcp'.  SocketProtocol is ignored for
          Unix domain sockets.  It defaults to 'tcp' if omitted from an
          Internet socket constructor.

        * BindAddress

          BindAddress is the local interface address that the socket will
          be bound to.

          For Internet domain sockets: The bind address may be a string
          containing a dotted quad, a host name, or a packed Internet
          address (without the port).  It defaults to INADDR_ANY if it's
          not specified, which will try to bind the socket to every
          interface.  If any interface has a socket already bound to the
          BindPort, then bind() (and the SocketFactory) will fail.

          For Unix domain sockets: The bind address is a path where the
          socket will be created.  It is required for server sockets and
          datagram client sockets.  If a file exists at the bind address,
          then bind() (and the SocketFactory) will fail.

        * BindPort

          BindPort is the port of the local interface(s) that the socket
          will try to bind to.  It is ignored for Unix sockets and
          recommended for Internet sockets.  It defaults to 0 if omitted,
          which will bind the socket to an unspecified available port.

          The bind port may be a number, or a name in the /etc/services (or
          equivalent) database.

        * ListenQueue

          ListenQueue specifies the length of the socket's listen() queue.
          It defaults to SOMAXCONN if omitted.  SocketFactory will ensure
          that ListenQueue doesn't exceed SOMAXCONN.

          It should go without saying that ListenQueue is only appropriate
          for listening sockets.

        * RemoteAddress

          RemoteAddress is the remote address to which the socket should
          connect.  If present, the SocketFactory will create a connecting
          socket; otherwise, the SocketFactory will make a listening
          socket.

          The remote address may be a string containing a dotted quad, a
          host name, a packed Internet address, or a Unix socket path.  It
          will be packed, with or without an accompanying RemotePort as
          necessary for the socket domain.

        * RemotePort

          RemotePort is the port to which the socket should connect.  It is
          required for connecting Internet sockets and ignored in all other
          cases.

          The remote port may be a number, or a name in the /etc/services
          (or equivalent) database.

   * POE::Wheel::SocketFactory::event(...)

     Please see POE::Wheel.

   * POE::Wheel::SocketFactory::getsockname()

     Returns the value of getsockname() as called with the SocketFactory's
     socket.

     This is useful for finding out what the SocketFactory's internal
     socket has bound to when it's been instructed to use BindAddress =>
     INADDR_ANY and/or BindPort => INADDR_ANY.

   * POE::Wheel::SocketFactory::ID()

     Returns the SocketFactory wheel's unique ID.  This can be used to
     associate the wheel's events back to the wheel itself.

EVENTS AND PARAMETERS
=====================

   * SuccessState

     The SuccessState parameter defines a state name or coderef to call
     upon a successful connect or accept.  The operation it succeeds on
     depends on the type of socket created.

     For connecting sockets, the success state/coderef is called when the
     socket has connected.  For listening sockets, the success
     state/coderef is called for each successfully accepted client
     connection.

     ARG0 contains the connected or accepted socket.

     For INET sockets, ARG1 and ARG2 hold the socket's remote address and
     port, respectively.

     For Unix client sockets, ARG1 contains the server address and ARG2 is
     undefined.  Some systems have trouble getting the address of a
     socket's remote end, so ARG1 may be undefined if there was trouble
     determining it.

     ARG3 contains a unique ID for the SocketFactory that generated the
     event.  This is useful for associating socket statuses with particular
     socket factories.

     According to _Perl Cookbook_, the remote address for accepted Unix
     domain sockets is undefined.  So ARG1 and ARG2 are, too.

   * FailureState

     The FailureState parameter defines a state name or coderef to call
     when a socket error occurs.  The SocketFactory knows what to do with
     EAGAIN, so that's not considered an error.

     The ARG0 parameter contains the name of the function that failed.
     ARG1 and ARG2 contain the numeric and string versions of $! at the
     time of the error, respectively.

     ARG3 contains a unique ID for the SocketFactory that generated the
     event.  This is useful for associating socket statuses with particular
     socket factories.

     A sample ErrorState state:

          sub error_state {
            my ($operation, $errnum, $errstr) = @_[ARG0, ARG1, ARG2];
            warn "$operation error $errnum: $errstr\n";
          }

SEE ALSO
========

   POE::Wheel; POE::Wheel::FollowTail; POE::Wheel::ListenAccept;
POE::Wheel::ReadWrite; POE::Wheel::SocketFactory

BUGS
====

   Many (if not all) of the croak/carp/warn/die statements should fire
back $state_failure instead.

AUTHORS & COPYRIGHTS
====================

   Please see the POE manpage.

Perl interface to IEEE Std 1003.1
*********************************

NAME
====

   POSIX - Perl interface to IEEE Std 1003.1

SYNOPSIS
========

     use POSIX;
     use POSIX qw(setsid);
     use POSIX qw(:errno_h :fcntl_h);

     printf "EINTR is %d\n", EINTR;

     $sess_id = POSIX::setsid();

     $fd = POSIX::open($path, O_CREAT|O_EXCL|O_WRONLY, 0644);
     	# note: that's a filedescriptor, *NOT* a filehandle

DESCRIPTION
===========

   The POSIX module permits you to access all (or nearly all) the standard
POSIX 1003.1 identifiers.  Many of these identifiers have been given
Perl-ish interfaces.  Things which are `#defines' in C, like EINTR or
O_NDELAY, are automatically exported into your namespace.  All functions
are only exported if you ask for them explicitly.  Most likely people will
prefer to use the fully-qualified function names.

   This document gives a condensed list of the features available in the
POSIX module.  Consult your operating system's manpages for general
information on most features.  Consult Perlfunc (perl.info),
for functions which are noted as being identical to
Perl's builtin functions.

   The first section describes POSIX functions from the 1003.1
specification.  The second section describes some classes for signal
objects, TTY objects, and other miscellaneous objects.  The remaining
sections list various constants and macros in an organization which
roughly follows IEEE Std 1003.1b-1993.

NOTE
====

   The POSIX module is probably the most complex Perl module supplied with
the standard distribution.  It incorporates autoloading, namespace games,
and dynamic loading of code that's in Perl, C, or both.  It's a great
source of wisdom.

CAVEATS
=======

   A few functions are not implemented because they are C specific.  If you
attempt to call these, they will print a message telling you that they
aren't implemented, and suggest using the Perl equivalent should one
exist.  For example, trying to access the setjmp() call will elicit the
message "setjmp() is C-specific: use eval {} instead".

   Furthermore, some evil vendors will claim 1003.1 compliance, but in fact
are not so: they will not pass the PCTS (POSIX Compliance Test Suites).
For example, one vendor may not define EDEADLK, or the semantics of the
errno values set by open(2) might not be quite right.  Perl does not
attempt to verify POSIX compliance.  That means you can currently
successfully say "use POSIX",  and then later in your program you find
that your vendor has been lax and there's no usable ICANON macro after
all.  This could be construed to be a bug.

FUNCTIONS
=========

_exit
     This is identical to the C function `_exit()'.

abort
     This is identical to the C function `abort()'.

abs
     This is identical to Perl's builtin `abs()' function.

access
     Determines the accessibility of a file.

          if( POSIX::access( "/", &POSIX::R_OK ) ){
          	print "have read permission\n";
          }

     Returns undef on failure.

acos
     This is identical to the C function `acos()'.

alarm
     This is identical to Perl's builtin `alarm()' function.

asctime
     This is identical to the C function `asctime()'.

asin
     This is identical to the C function `asin()'.

assert
     Unimplemented.

atan
     This is identical to the C function `atan()'.

atan2
     This is identical to Perl's builtin `atan2()' function.

atexit
     atexit() is C-specific: use END {} instead.

atof
     atof() is C-specific.

atoi
     atoi() is C-specific.

atol
     atol() is C-specific.

bsearch
     bsearch() not supplied.

calloc
     calloc() is C-specific.

ceil
     This is identical to the C function `ceil()'.

chdir
     This is identical to Perl's builtin chdir() function.

chmod
     This is identical to Perl's builtin chmod() function.

chown
     This is identical to Perl's builtin `chown()' function.

clearerr
     Use method `IO::Handle::clearerr()' instead.

clock
     This is identical to the C function `clock()'.

close
     Close the file.  This uses file descriptors such as those obtained by
     calling `POSIX::open'.

          $fd = POSIX::open( "foo", &POSIX::O_RDONLY );
          POSIX::close( $fd );

     Returns undef on failure.

closedir
     This is identical to Perl's builtin `closedir()' function.

cos
     This is identical to Perl's builtin `cos()' function.

cosh
     This is identical to the C function `cosh()'.

creat
     Create a new file.  This returns a file descriptor like the ones
     returned by `POSIX::open'.  Use `POSIX::close' to close the file.

          $fd = POSIX::creat( "foo", 0611 );
          POSIX::close( $fd );

ctermid
     Generates the path name for the controlling terminal.

          $path = POSIX::ctermid();

ctime
     This is identical to the C function `ctime()'.

cuserid
     Get the character login name of the user.

          $name = POSIX::cuserid();

difftime
     This is identical to the C function `difftime()'.

div
     div() is C-specific.

dup
     This is similar to the C function `dup()'.

     This uses file descriptors such as those obtained by calling
     `POSIX::open'.

     Returns undef on failure.

dup2
     This is similar to the C function `dup2()'.

     This uses file descriptors such as those obtained by calling
     `POSIX::open'.

     Returns undef on failure.

errno
     Returns the value of errno.

          $errno = POSIX::errno();

execl
     execl() is C-specific.

execle
     execle() is C-specific.

execlp
     execlp() is C-specific.

execv
     execv() is C-specific.

execve
     execve() is C-specific.

execvp
     execvp() is C-specific.

exit
     This is identical to Perl's builtin exit() function.

exp
     This is identical to Perl's builtin `exp()' function.

fabs
     This is identical to Perl's builtin `abs()' function.

fclose
     Use method `IO::Handle::close()' instead.

fcntl
     This is identical to Perl's builtin `fcntl()' function.

fdopen
     Use method `IO::Handle::new_from_fd()' instead.

feof
     Use method `IO::Handle::eof()' instead.

ferror
     Use method `IO::Handle::error()' instead.

fflush
     Use method `IO::Handle::flush()' instead.

fgetc
     Use method `IO::Handle::getc()' instead.

fgetpos
     Use method `IO::Seekable::getpos()' instead.

fgets
     Use method `IO::Handle::gets()' instead.

fileno
     Use method `IO::Handle::fileno()' instead.

floor
     This is identical to the C function `floor()'.

fmod
     This is identical to the C function `fmod()'.

fopen
     Use method `IO::File::open()' instead.

fork
     This is identical to Perl's builtin fork() function.

fpathconf
     Retrieves the value of a configurable limit on a file or directory.
     This uses file descriptors such as those obtained by calling
     `POSIX::open'.

     The following will determine the maximum length of the longest
     allowable pathname on the filesystem which holds `/tmp/foo'.

          $fd = POSIX::open( "/tmp/foo", &POSIX::O_RDONLY );
          $path_max = POSIX::fpathconf( $fd, &POSIX::_PC_PATH_MAX );

     Returns undef on failure.

fprintf
     fprintf() is C-specific-use printf instead.

fputc
     fputc() is C-specific-use print instead.

fputs
     fputs() is C-specific-use print instead.

fread
     fread() is C-specific-use read instead.

free
     free() is C-specific.

freopen
     freopen() is C-specific-use open instead.

frexp
     Return the mantissa and exponent of a floating-point number.

          ($mantissa, $exponent) = POSIX::frexp( 3.14 );

fscanf
     fscanf() is C-specific-use <> and regular expressions instead.

fseek
     Use method `IO::Seekable::seek()' instead.

fsetpos
     Use method `IO::Seekable::setpos()' instead.

fstat
     Get file status.  This uses file descriptors such as those obtained by
     calling `POSIX::open'.  The data returned is identical to the data
     from Perl's builtin stat function.

          $fd = POSIX::open( "foo", &POSIX::O_RDONLY );
          @stats = POSIX::fstat( $fd );

ftell
     Use method `IO::Seekable::tell()' instead.

fwrite
     fwrite() is C-specific-use print instead.

getc
     This is identical to Perl's builtin `getc()' function.

getchar
     Returns one character from STDIN.

getcwd
     Returns the name of the current working directory.

getegid
     Returns the effective group id.

getenv
     Returns the value of the specified enironment variable.

geteuid
     Returns the effective user id.

getgid
     Returns the user's real group id.

getgrgid
     This is identical to Perl's builtin `getgrgid()' function.

getgrnam
     This is identical to Perl's builtin `getgrnam()' function.

getgroups
     Returns the ids of the user's supplementary groups.

getlogin
     This is identical to Perl's builtin `getlogin()' function.

getpgrp
     This is identical to Perl's builtin `getpgrp()' function.

getpid
     Returns the process's id.

getppid
     This is identical to Perl's builtin `getppid()' function.

getpwnam
     This is identical to Perl's builtin getpwnam() function.

getpwuid
     This is identical to Perl's builtin getpwuid() function.

gets
     Returns one line from STDIN.

getuid
     Returns the user's id.

gmtime
     This is identical to Perl's builtin `gmtime()' function.

isalnum
     This is identical to the C function, except that it can apply to a
     single character or to a whole string.

isalpha
     This is identical to the C function, except that it can apply to a
     single character or to a whole string.

isatty
     Returns a boolean indicating whether the specified filehandle is
     connected to a tty.

iscntrl
     This is identical to the C function, except that it can apply to a
     single character or to a whole string.

isdigit
     This is identical to the C function, except that it can apply to a
     single character or to a whole string.

isgraph
     This is identical to the C function, except that it can apply to a
     single character or to a whole string.

islower
     This is identical to the C function, except that it can apply to a
     single character or to a whole string.

isprint
     This is identical to the C function, except that it can apply to a
     single character or to a whole string.

ispunct
     This is identical to the C function, except that it can apply to a
     single character or to a whole string.

isspace
     This is identical to the C function, except that it can apply to a
     single character or to a whole string.

isupper
     This is identical to the C function, except that it can apply to a
     single character or to a whole string.

isxdigit
     This is identical to the C function, except that it can apply to a
     single character or to a whole string.

kill
     This is identical to Perl's builtin kill() function.

labs
     labs() is C-specific, use abs instead.

ldexp
     This is identical to the C function `ldexp()'.

ldiv
     ldiv() is C-specific, use / and int instead.

link
     This is identical to Perl's builtin link() function.

localeconv
     Get numeric formatting information.  Returns a reference to a hash
     containing the current locale formatting values.

     The database for the *de* (Deutsch or German) locale.

          $loc = POSIX::setlocale( &POSIX::LC_ALL, "de" );
          print "Locale = $loc\n";
          $lconv = POSIX::localeconv();
          print "decimal_point	= ", $lconv->{decimal_point},	"\n";
          print "thousands_sep	= ", $lconv->{thousands_sep},	"\n";
          print "grouping	= ", $lconv->{grouping},	"\n";
          print "int_curr_symbol	= ", $lconv->{int_curr_symbol},	"\n";
          print "currency_symbol	= ", $lconv->{currency_symbol},	"\n";
          print "mon_decimal_point = ", $lconv->{mon_decimal_point}, "\n";
          print "mon_thousands_sep = ", $lconv->{mon_thousands_sep}, "\n";
          print "mon_grouping	= ", $lconv->{mon_grouping},	"\n";
          print "positive_sign	= ", $lconv->{positive_sign},	"\n";
          print "negative_sign	= ", $lconv->{negative_sign},	"\n";
          print "int_frac_digits	= ", $lconv->{int_frac_digits},	"\n";
          print "frac_digits	= ", $lconv->{frac_digits},	"\n";
          print "p_cs_precedes	= ", $lconv->{p_cs_precedes},	"\n";
          print "p_sep_by_space	= ", $lconv->{p_sep_by_space},	"\n";
          print "n_cs_precedes	= ", $lconv->{n_cs_precedes},	"\n";
          print "n_sep_by_space	= ", $lconv->{n_sep_by_space},	"\n";
          print "p_sign_posn	= ", $lconv->{p_sign_posn},	"\n";
          print "n_sign_posn	= ", $lconv->{n_sign_posn},	"\n";

localtime
     This is identical to Perl's builtin `localtime()' function.

log
     This is identical to Perl's builtin `log()' function.

log10
     This is identical to the C function `log10()'.

longjmp
     longjmp() is C-specific: use die instead.

lseek
     Move the file's read/write position.  This uses file descriptors such
     as those obtained by calling `POSIX::open'.

          $fd = POSIX::open( "foo", &POSIX::O_RDONLY );
          $off_t = POSIX::lseek( $fd, 0, &POSIX::SEEK_SET );

     Returns undef on failure.

malloc
     malloc() is C-specific.

mblen
     This is identical to the C function `mblen()'.

mbstowcs
     This is identical to the C function `mbstowcs()'.

mbtowc
     This is identical to the C function `mbtowc()'.

memchr
     memchr() is C-specific, use index() instead.

memcmp
     memcmp() is C-specific, use eq instead.

memcpy
     memcpy() is C-specific, use = instead.

memmove
     memmove() is C-specific, use = instead.

memset
     memset() is C-specific, use x instead.

mkdir
     This is identical to Perl's builtin `mkdir()' function.

mkfifo
     This is similar to the C function `mkfifo()'.

     Returns undef on failure.

mktime
     Convert date/time info to a calendar time.

     Synopsis:

          mktime(sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = 0)

     The month (`mon'), weekday (`wday'), and yearday (`yday') begin at
     zero.  I.e. January is 0, not 1; Sunday is 0, not 1; January 1st is
     0, not 1.  The year (year) is given in years since 1900.  I.e. The
     year 1995 is 95; the year 2001 is 101.  Consult your system's
     `mktime()' manpage for details about these and the other arguments.

     Calendar time for December 12, 1995, at 10:30 am.

          $time_t = POSIX::mktime( 0, 30, 10, 12, 11, 95 );
          print "Date = ", POSIX::ctime($time_t);

     Returns undef on failure.

modf
     Return the integral and fractional parts of a floating-point number.

          ($fractional, $integral) = POSIX::modf( 3.14 );

nice
     This is similar to the C function `nice()'.

     Returns undef on failure.

offsetof
     offsetof() is C-specific.

open
     Open a file for reading for writing.  This returns file descriptors,
     not Perl filehandles.  Use `POSIX::close' to close the file.

     Open a file read-only with mode 0666.

          $fd = POSIX::open( "foo" );

     Open a file for read and write.

          $fd = POSIX::open( "foo", &POSIX::O_RDWR );

     Open a file for write, with truncation.

          $fd = POSIX::open( "foo", &POSIX::O_WRONLY | &POSIX::O_TRUNC );

     Create a new file with mode 0640.  Set up the file for writing.

          $fd = POSIX::open( "foo", &POSIX::O_CREAT | &POSIX::O_WRONLY, 0640 );

     Returns undef on failure.

opendir
     Open a directory for reading.

          $dir = POSIX::opendir( "/tmp" );
          @files = POSIX::readdir( $dir );
          POSIX::closedir( $dir );

     Returns undef on failure.

pathconf
     Retrieves the value of a configurable limit on a file or directory.

     The following will determine the maximum length of the longest
     allowable pathname on the filesystem which holds `/tmp'.

          $path_max = POSIX::pathconf( "/tmp", &POSIX::_PC_PATH_MAX );

     Returns undef on failure.

pause
     This is similar to the C function `pause()'.

     Returns undef on failure.

perror
     This is identical to the C function `perror()'.

pipe
     Create an interprocess channel.  This returns file descriptors like
     those returned by `POSIX::open'.

          ($fd0, $fd1) = POSIX::pipe();
          POSIX::write( $fd0, "hello", 5 );
          POSIX::read( $fd1, $buf, 5 );

pow
     Computes $x raised to the power $exponent.

          $ret = POSIX::pow( $x, $exponent );

printf
     Prints the specified arguments to STDOUT.

putc
     putc() is C-specific-use print instead.

putchar
     putchar() is C-specific-use print instead.

puts
     puts() is C-specific-use print instead.

qsort
     qsort() is C-specific, use sort instead.

raise
     Sends the specified signal to the current process.

rand
     rand() is non-portable, use Perl's rand instead.

read
     Read from a file.  This uses file descriptors such as those obtained
     by calling `POSIX::open'.  If the buffer `$buf' is not large enough
     for the read then Perl will extend it to make room for the request.

          $fd = POSIX::open( "foo", &POSIX::O_RDONLY );
          $bytes = POSIX::read( $fd, $buf, 3 );

     Returns undef on failure.

readdir
     This is identical to Perl's builtin `readdir()' function.

realloc
     realloc() is C-specific.

remove
     This is identical to Perl's builtin `unlink()' function.

rename
     This is identical to Perl's builtin rename() function.

rewind
     Seeks to the beginning of the file.

rewinddir
     This is identical to Perl's builtin `rewinddir()' function.

rmdir
     This is identical to Perl's builtin `rmdir()' function.

scanf
     scanf() is C-specific-use <> and regular expressions instead.

setgid
     Sets the real group id for this process.

setjmp
     setjmp() is C-specific: use eval {} instead.

setlocale
     Modifies and queries program's locale.  The following examples assume

          use POSIX qw(setlocale LC_ALL LC_CTYPE);

     has been issued.

     The following will set the traditional UNIX system locale behavior
     (the second argument `"C"').

          $loc = setlocale( LC_ALL, "C" );

     The following will query the current LC_CTYPE category.  (No second
     argument means 'query'.)

          $loc = setlocale( LC_CTYPE );

     The following will set the LC_CTYPE behaviour according to the locale
     environment variables (the second argument "").  Please see your
     systems `setlocale(3)' in this node documentation for the locale
     environment variables' meaning or consult Perllocale (perl.info).

          $loc = setlocale( LC_CTYPE, "" );

     The following will set the LC_COLLATE behaviour to Argentinian
     Spanish. NOTE: The naming and availability of locales depends on your
     operating system. Please consult Perllocale (perl.info),
     for how to find out which locales are
     available in your system.

          $loc = setlocale( LC_ALL, "es_AR.ISO8859-1" );

setpgid
     This is similar to the C function `setpgid()'.

     Returns undef on failure.

setsid
     This is identical to the C function `setsid()'.

setuid
     Sets the real user id for this process.

sigaction
     Detailed signal management.  This uses POSIX::SigAction objects for
     the action and `oldaction' arguments.  Consult your system's sigaction
     manpage for details.

     Synopsis:

          sigaction(sig, action, oldaction = 0)

     Returns undef on failure.

siglongjmp
     siglongjmp() is C-specific: use die instead.

sigpending
     Examine signals that are blocked and pending.  This uses POSIX::SigSet
     objects for the `sigset' argument.  Consult your system's sigpending
     manpage for details.

     Synopsis:

          sigpending(sigset)

     Returns undef on failure.

sigprocmask
     Change and/or examine calling process's signal mask.  This uses
     POSIX::SigSet objects for the `sigset' and `oldsigset' arguments.
     Consult your system's sigprocmask manpage for details.

     Synopsis:

          sigprocmask(how, sigset, oldsigset = 0)

     Returns undef on failure.

sigsetjmp
     sigsetjmp() is C-specific: use eval {} instead.

sigsuspend
     Install a signal mask and suspend process until signal arrives.  This
     uses POSIX::SigSet objects for the `signal_mask' argument.  Consult
     your system's sigsuspend manpage for details.

     Synopsis:

          sigsuspend(signal_mask)

     Returns undef on failure.

sin
     This is identical to Perl's builtin `sin()' function.

sinh
     This is identical to the C function `sinh()'.

sleep
     This is identical to Perl's builtin `sleep()' function.

sprintf
     This is identical to Perl's builtin `sprintf()' function.

sqrt
     This is identical to Perl's builtin `sqrt()' function.

srand
     srand().

sscanf
     sscanf() is C-specific-use regular expressions instead.

stat
     This is identical to Perl's builtin stat() function.

strcat
     strcat() is C-specific, use .= instead.

strchr
     strchr() is C-specific, use index() instead.

strcmp
     strcmp() is C-specific, use eq instead.

strcoll
     This is identical to the C function `strcoll()'.

strcpy
     strcpy() is C-specific, use = instead.

strcspn
     strcspn() is C-specific, use regular expressions instead.

strerror
     Returns the error string for the specified errno.

strftime
     Convert date and time information to string.  Returns the string.

     Synopsis:

          strftime(fmt, sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1)

     The month (`mon'), weekday (`wday'), and yearday (`yday') begin at
     zero.  I.e. January is 0, not 1; Sunday is 0, not 1; January 1st is
     0, not 1.  The year (year) is given in years since 1900.  I.e., the
     year 1995 is 95; the year 2001 is 101.  Consult your system's
     `strftime()' manpage for details about these and the other arguments.
     If you want your code to be portable, your format (fmt) argument
     should use only the conversion specifiers defined by the ANSI C
     standard.  These are `aAbBcdHIjmMpSUwWxXyYZ%'.  The given arguments
     are made consistent as though by calling `mktime()' before calling
     your system's `strftime()' function, except that the `isdst' value is
     not affected.

     The string for Tuesday, December 12, 1995.

          $str = POSIX::strftime( "%A, %B %d, %Y", 0, 0, 0, 12, 11, 95, 2 );
          print "$str\n";

strlen
     strlen() is C-specific, use length instead.

strncat
     strncat() is C-specific, use .= instead.

strncmp
     strncmp() is C-specific, use eq instead.

strncpy
     strncpy() is C-specific, use = instead.

stroul
     stroul() is C-specific.

strpbrk
     strpbrk() is C-specific.

strrchr
     strrchr() is C-specific, use rindex() instead.

strspn
     strspn() is C-specific.

strstr
     This is identical to Perl's builtin `index()' function.

strtod
     String to double translation. Returns the parsed number and the number
     of characters in the unparsed portion of the string.  Truly
     POSIX-compliant systems set $! ($ERRNO) to indicate a translation
     error, so clear $! before calling strtod.  However, non-POSIX systems
     may not check for overflow, and therefore will never set $!.

     strtod should respect any POSIX *setlocale()* settings.

     To parse a string $str as a floating point number use

          $! = 0;
          ($num, $n_unparsed) = POSIX::strtod($str);

     The second returned item and $! can be used to check for valid input:

          if (($str eq '') || ($n_unparsed != 0) || !$!) {
              die "Non-numeric input $str" . $! ? ": $!\n" : "\n";
          }

     When called in a scalar context strtod returns the parsed number.

strtok
     strtok() is C-specific.

strtol
     String to (long) integer translation.  Returns the parsed number and
     the number of characters in the unparsed portion of the string.  Truly
     POSIX-compliant systems set $! ($ERRNO) to indicate a translation
     error, so clear $! before calling strtol.  However, non-POSIX systems
     may not check for overflow, and therefore will never set $!.

     strtol should respect any POSIX *setlocale()* settings.

     To parse a string $str as a number in some base $base use

          $! = 0;
          ($num, $n_unparsed) = POSIX::strtol($str, $base);

     The base should be zero or between 2 and 36, inclusive.  When the base
     is zero or omitted strtol will use the string itself to determine the
     base: a leading "0x" or "0X" means hexadecimal; a leading "0" means
     octal; any other leading characters mean decimal.  Thus, "1234" is
     parsed as a decimal number, "01234" as an octal number, and "0x1234"
     as a hexadecimal number.

     The second returned item and $! can be used to check for valid input:

          if (($str eq '') || ($n_unparsed != 0) || !$!) {
              die "Non-numeric input $str" . $! ? ": $!\n" : "\n";
          }

     When called in a scalar context strtol returns the parsed number.

strtoul
     String to unsigned (long) integer translation.  strtoul is identical
     to strtol except that strtoul only parses unsigned integers.  See
     strtol for details.

     Note: Some vendors supply strtod and strtol but not strtoul.  Other
     vendors that do suply strtoul parse "-1" as a valid value.

strxfrm
     String transformation.  Returns the transformed string.

          $dst = POSIX::strxfrm( $src );

sysconf
     Retrieves values of system configurable variables.

     The following will get the machine's clock speed.

          $clock_ticks = POSIX::sysconf( &POSIX::_SC_CLK_TCK );

     Returns undef on failure.

system
     This is identical to Perl's builtin `system()' function.

tan
     This is identical to the C function `tan()'.

tanh
     This is identical to the C function `tanh()'.

tcdrain
     This is similar to the C function `tcdrain()'.

     Returns undef on failure.

tcflow
     This is similar to the C function `tcflow()'.

     Returns undef on failure.

tcflush
     This is similar to the C function `tcflush()'.

     Returns undef on failure.

tcgetpgrp
     This is identical to the C function `tcgetpgrp()'.

tcsendbreak
     This is similar to the C function `tcsendbreak()'.

     Returns undef on failure.

tcsetpgrp
     This is similar to the C function `tcsetpgrp()'.

     Returns undef on failure.

time
     This is identical to Perl's builtin `time()' function.

times
     The times() function returns elapsed realtime since some point in the
     past (such as system startup), user and system times for this
     process, and user and system times used by child processes.  All
     times are returned in clock ticks.

          ($realtime, $user, $system, $cuser, $csystem) = POSIX::times();

     Note: Perl's builtin `times()' function returns four values, measured
     in seconds.

tmpfile
     Use method `IO::File::new_tmpfile()' instead.

tmpnam
     Returns a name for a temporary file.

          $tmpfile = POSIX::tmpnam();

tolower
     This is identical to Perl's builtin `lc()' function.

toupper
     This is identical to Perl's builtin `uc()' function.

ttyname
     This is identical to the C function `ttyname()'.

tzname
     Retrieves the time conversion information from the tzname variable.

          POSIX::tzset();
          ($std, $dst) = POSIX::tzname();

tzset
     This is identical to the C function `tzset()'.

umask
     This is identical to Perl's builtin umask() function.

uname
     Get name of current operating system.

          ($sysname, $nodename, $release, $version, $machine ) = POSIX::uname();

ungetc
     Use method `IO::Handle::ungetc()' instead.

unlink
     This is identical to Perl's builtin `unlink()' function.

utime
     This is identical to Perl's builtin `utime()' function.

vfprintf
     vfprintf() is C-specific.

vprintf
     vprintf() is C-specific.

vsprintf
     vsprintf() is C-specific.

wait
     This is identical to Perl's builtin wait() function.

waitpid
     Wait for a child process to change state.  This is identical to Perl's
     builtin `waitpid()' function.

          $pid = POSIX::waitpid( -1, &POSIX::WNOHANG );
          print "status = ", ($? / 256), "\n";

wcstombs
     This is identical to the C function `wcstombs()'.

wctomb
     This is identical to the C function `wctomb()'.

write
     Write to a file.  This uses file descriptors such as those obtained by
     calling `POSIX::open'.

          $fd = POSIX::open( "foo", &POSIX::O_WRONLY );
          $buf = "hello";
          $bytes = POSIX::write( $b, $buf, 5 );

     Returns undef on failure.

CLASSES
=======

POSIX::SigAction
----------------

new
     Creates a new POSIX::SigAction object which corresponds to the C
     `struct sigaction'.  This object will be destroyed automatically when
     it is no longer needed.  The first parameter is the fully-qualified
     name of a sub which is a signal-handler.  The second parameter is a
     POSIX::SigSet object, it defaults to the empty set.  The third
     parameter contains the `sa_flags', it defaults to 0.

          $sigset = POSIX::SigSet->new(SIGINT, SIGQUIT);
          $sigaction = POSIX::SigAction->new( 'main::handler', $sigset, &POSIX::SA_NOCLDSTOP );

     This POSIX::SigAction object should be used with the
     `POSIX::sigaction()' function.

POSIX::SigSet
-------------

new
     Create a new SigSet object.  This object will be destroyed
     automatically when it is no longer needed.  Arguments may be supplied
     to initialize the set.

     Create an empty set.

          $sigset = POSIX::SigSet->new;

     Create a set with SIGUSR1.

          $sigset = POSIX::SigSet->new( &POSIX::SIGUSR1 );

addset
     Add a signal to a SigSet object.

          $sigset->addset( &POSIX::SIGUSR2 );

     Returns undef on failure.

delset
     Remove a signal from the SigSet object.

          $sigset->delset( &POSIX::SIGUSR2 );

     Returns undef on failure.

emptyset
     Initialize the SigSet object to be empty.

          $sigset->emptyset();

     Returns undef on failure.

fillset
     Initialize the SigSet object to include all signals.

          $sigset->fillset();

     Returns undef on failure.

ismember
     Tests the SigSet object to see if it contains a specific signal.

          if( $sigset->ismember( &POSIX::SIGUSR1 ) ){
          	print "contains SIGUSR1\n";
          }

POSIX::Termios
--------------

new
     Create a new Termios object.  This object will be destroyed
     automatically when it is no longer needed.  A Termios object
     corresponds to the termios C struct.  new() mallocs a new one,
     getattr() fills it from a file descriptor, and setattr() sets a file
     descriptor's parameters to match Termios' contents.

          $termios = POSIX::Termios->new;

getattr
     Get terminal control attributes.

     Obtain the attributes for stdin.

          $termios->getattr()

     Obtain the attributes for stdout.

          $termios->getattr( 1 )

     Returns undef on failure.

getcc
     Retrieve a value from the c_cc field of a termios object.  The c_cc
     field is an array so an index must be specified.

          $c_cc[1] = $termios->getcc(1);

getcflag
     Retrieve the c_cflag field of a termios object.

          $c_cflag = $termios->getcflag;

getiflag
     Retrieve the c_iflag field of a termios object.

          $c_iflag = $termios->getiflag;

getispeed
     Retrieve the input baud rate.

          $ispeed = $termios->getispeed;

getlflag
     Retrieve the c_lflag field of a termios object.

          $c_lflag = $termios->getlflag;

getoflag
     Retrieve the c_oflag field of a termios object.

          $c_oflag = $termios->getoflag;

getospeed
     Retrieve the output baud rate.

          $ospeed = $termios->getospeed;

setattr
     Set terminal control attributes.

     Set attributes immediately for stdout.

          $termios->setattr( 1, &POSIX::TCSANOW );

     Returns undef on failure.

setcc
     Set a value in the c_cc field of a termios object.  The c_cc field is
     an array so an index must be specified.

          $termios->setcc( &POSIX::VEOF, 1 );

setcflag
     Set the c_cflag field of a termios object.

          $termios->setcflag( $c_cflag | &POSIX::CLOCAL );

setiflag
     Set the c_iflag field of a termios object.

          $termios->setiflag( $c_iflag | &POSIX::BRKINT );

setispeed
     Set the input baud rate.

          $termios->setispeed( &POSIX::B9600 );

     Returns undef on failure.

setlflag
     Set the c_lflag field of a termios object.

          $termios->setlflag( $c_lflag | &POSIX::ECHO );

setoflag
     Set the c_oflag field of a termios object.

          $termios->setoflag( $c_oflag | &POSIX::OPOST );

setospeed
     Set the output baud rate.

          $termios->setospeed( &POSIX::B9600 );

     Returns undef on failure.

Baud rate values
     B38400 B75 B200 B134 B300 B1800 B150 B0 B19200 B1200 B9600 B600 B4800
     B50 B2400 B110

Terminal interface values
     TCSADRAIN TCSANOW TCOON TCIOFLUSH TCOFLUSH TCION TCIFLUSH TCSAFLUSH
     TCIOFF TCOOFF

c_cc field values
     VEOF VEOL VERASE VINTR VKILL VQUIT VSUSP VSTART VSTOP VMIN VTIME NCCS

c_cflag field values
     CLOCAL CREAD CSIZE CS5 CS6 CS7 CS8 CSTOPB HUPCL PARENB PARODD

c_iflag field values
     BRKINT ICRNL IGNBRK IGNCR IGNPAR INLCR INPCK ISTRIP IXOFF IXON PARMRK

c_lflag field values
     ECHO ECHOE ECHOK ECHONL ICANON IEXTEN ISIG NOFLSH TOSTOP

c_oflag field values
     OPOST

PATHNAME CONSTANTS
==================

Constants
     _PC_CHOWN_RESTRICTED _PC_LINK_MAX _PC_MAX_CANON _PC_MAX_INPUT
     _PC_NAME_MAX _PC_NO_TRUNC _PC_PATH_MAX _PC_PIPE_BUF _PC_VDISABLE

POSIX CONSTANTS
===============

Constants
     _POSIX_ARG_MAX _POSIX_CHILD_MAX _POSIX_CHOWN_RESTRICTED
     _POSIX_JOB_CONTROL _POSIX_LINK_MAX _POSIX_MAX_CANON _POSIX_MAX_INPUT
     _POSIX_NAME_MAX _POSIX_NGROUPS_MAX _POSIX_NO_TRUNC _POSIX_OPEN_MAX
     _POSIX_PATH_MAX _POSIX_PIPE_BUF _POSIX_SAVED_IDS _POSIX_SSIZE_MAX
     _POSIX_STREAM_MAX _POSIX_TZNAME_MAX _POSIX_VDISABLE _POSIX_VERSION

SYSTEM CONFIGURATION
====================

Constants
     _SC_ARG_MAX _SC_CHILD_MAX _SC_CLK_TCK _SC_JOB_CONTROL _SC_NGROUPS_MAX
     _SC_OPEN_MAX _SC_SAVED_IDS _SC_STREAM_MAX _SC_TZNAME_MAX _SC_VERSION

ERRNO
=====

Constants
     E2BIG EACCES EADDRINUSE EADDRNOTAVAIL EAFNOSUPPORT EAGAIN EALREADY
     EBADF EBUSY ECHILD ECONNABORTED ECONNREFUSED ECONNRESET EDEADLK
     EDESTADDRREQ EDOM EDQUOT EEXIST EFAULT EFBIG EHOSTDOWN EHOSTUNREACH
     EINPROGRESS EINTR EINVAL EIO EISCONN EISDIR ELOOP EMFILE EMLINK
     EMSGSIZE ENAMETOOLONG ENETDOWN ENETRESET ENETUNREACH ENFILE ENOBUFS
     ENODEV ENOENT ENOEXEC ENOLCK ENOMEM ENOPROTOOPT ENOSPC ENOSYS ENOTBLK
     ENOTCONN ENOTDIR ENOTEMPTY ENOTSOCK ENOTTY ENXIO EOPNOTSUPP EPERM
     EPFNOSUPPORT EPIPE EPROCLIM EPROTONOSUPPORT EPROTOTYPE ERANGE EREMOTE
     ERESTART EROFS ESHUTDOWN ESOCKTNOSUPPORT ESPIPE ESRCH ESTALE
     ETIMEDOUT ETOOMANYREFS ETXTBSY EUSERS EWOULDBLOCK EXDEV

FCNTL
=====

Constants
     FD_CLOEXEC F_DUPFD F_GETFD F_GETFL F_GETLK F_OK F_RDLCK F_SETFD
     F_SETFL F_SETLK F_SETLKW F_UNLCK F_WRLCK O_ACCMODE O_APPEND O_CREAT
     O_EXCL O_NOCTTY O_NONBLOCK O_RDONLY O_RDWR O_TRUNC O_WRONLY

FLOAT
=====

Constants
     DBL_DIG DBL_EPSILON DBL_MANT_DIG DBL_MAX DBL_MAX_10_EXP DBL_MAX_EXP
     DBL_MIN DBL_MIN_10_EXP DBL_MIN_EXP FLT_DIG FLT_EPSILON FLT_MANT_DIG
     FLT_MAX FLT_MAX_10_EXP FLT_MAX_EXP FLT_MIN FLT_MIN_10_EXP FLT_MIN_EXP
     FLT_RADIX FLT_ROUNDS LDBL_DIG LDBL_EPSILON LDBL_MANT_DIG LDBL_MAX
     LDBL_MAX_10_EXP LDBL_MAX_EXP LDBL_MIN LDBL_MIN_10_EXP LDBL_MIN_EXP

LIMITS
======

Constants
     ARG_MAX CHAR_BIT CHAR_MAX CHAR_MIN CHILD_MAX INT_MAX INT_MIN LINK_MAX
     LONG_MAX LONG_MIN MAX_CANON MAX_INPUT MB_LEN_MAX NAME_MAX NGROUPS_MAX
     OPEN_MAX PATH_MAX PIPE_BUF SCHAR_MAX SCHAR_MIN SHRT_MAX SHRT_MIN
     SSIZE_MAX STREAM_MAX TZNAME_MAX UCHAR_MAX UINT_MAX ULONG_MAX USHRT_MAX

LOCALE
======

Constants
     LC_ALL LC_COLLATE LC_CTYPE LC_MONETARY LC_NUMERIC LC_TIME

MATH
====

Constants
     HUGE_VAL

SIGNAL
======

Constants
     SA_NOCLDSTOP SA_NOCLDWAIT SA_NODEFER SA_ONSTACK SA_RESETHAND
     SA_RESTART SA_SIGINFO SIGABRT SIGALRM SIGCHLD SIGCONT SIGFPE SIGHUP
     SIGILL SIGINT SIGKILL SIGPIPE SIGQUIT SIGSEGV SIGSTOP SIGTERM SIGTSTP
     SIGTTIN SIGTTOU SIGUSR1 SIGUSR2 SIG_BLOCK SIG_DFL SIG_ERR SIG_IGN
     SIG_SETMASK SIG_UNBLOCK

STAT
====

Constants
     S_IRGRP S_IROTH S_IRUSR S_IRWXG S_IRWXO S_IRWXU S_ISGID S_ISUID
     S_IWGRP S_IWOTH S_IWUSR S_IXGRP S_IXOTH S_IXUSR

Macros
     S_ISBLK S_ISCHR S_ISDIR S_ISFIFO S_ISREG

STDLIB
======

Constants
     EXIT_FAILURE EXIT_SUCCESS MB_CUR_MAX RAND_MAX

STDIO
=====

Constants
     BUFSIZ EOF FILENAME_MAX L_ctermid L_cuserid L_tmpname TMP_MAX

TIME
====

Constants
     CLK_TCK CLOCKS_PER_SEC

UNISTD
======

Constants
     R_OK SEEK_CUR SEEK_END SEEK_SET STDIN_FILENO STDOUT_FILENO
     STRERR_FILENO W_OK X_OK

WAIT
====

Constants
     WNOHANG WUNTRACED

Macros
     WIFEXITED WEXITSTATUS WIFSIGNALED WTERMSIG WIFSTOPPED WSTOPSIG

CREATION
========

   This document generated by ./mkposixman.PL version 19960129.

PPM (Perl Package Management)
*****************************

NAME
====

   ppm - PPM (Perl Package Management)

SYNOPSIS
========

     use PPM;

     PPM::InstallPackage("package" => $package, "location" => $location, "root" => $root);
     PPM::RemovePackage("package" => $package, "force" => $force);
     PPM::VerifyPackage("package" => $package, "location" => $location, "upgrade" => $upgrade);
     PPM::QueryInstalledPackages("searchRE" => $searchRE, "searchtag" => $searchtag, "ignorecase" => $ignorecase);
     PPM::InstalledPackageProperties();

     PPM::ListOfRepositories();
     PPM::RemoveRepository("repository" => $repository, "save" => $save);
     PPM::AddRepository("repository" => $repository, "location" => $location, "save" => $save);
     PPM::RepositoryPackages("location" => $location);
     PPM::RepositoryPackageProperties("package" => $package, "location" => $location);
     PPM::RepositorySummary("location" => $location);

     PPM::GetPPMOptions();
     PPM::SetPPMOptions("options" => %options, "save" => $save);

DESCRIPTION
===========

   PPM is a group of functions intended to simplify the tasks of locating,
installing, upgrading and removing software 'packages'.  It can determine
if the most recent version of a software package is installed on a system,
and can install or upgrade that package from a local or remote host.

   PPM uses files containing a modified form of the Open Software
Distribution (OSD) specification for information about software packages.
These description files, which are written in Extensible Markup Language
(XML) code, are referred to as 'PPD' files.  Information about OSD can be
found at the W3C web site (at the time of this writing,
http://www.w3.org/TR/NOTE-OSD.html).  The modifications to OSD used by PPM
are documented in PPM::ppd.

   PPD files for packages are generated from POD files using the pod2ppd
command.

USAGE
=====

PPM::InstallPackage("package" => $package, "location" => $location, "root" => $root);
     Installs the specified package onto the local system.  'package' may
     be a simple package name ('foo'), a pathname (P:\PACKAGES\FOO.PPD) or
     a URL (HTTP://www.ActiveState.com/packages/foo.ppd).  In the case of a
     simple package name, the function will look for the package's PPD file
     at 'location', if provided; otherwise, it will use information stored
     in the PPM data file (see 'Files' section below) to locate the PPD
     file for the requested package.  The package's files will be
     installed under the directory specified in 'root'; if not specified
     the default value of 'root' will be used.

     The function uses the values stored in the PPM data file to determine
     the local operating system, operating system version and CPU type.
     If the PPD for this package contains implementations for different
     platforms, these values will be used to determine which one is
     installed.

     InstallPackage() updates the PPM data file with information about the
     package installation. It stores a copy of the PPD used for
     installation, as well as the location from which this PPD was
     obtained.  This location will become the default PPD location for
     this package.

     During an installation, the following actions are performed:

          - the PPD file for the package is read
          - a directory for this package is created in the directory specified in
            <BUILDDIR> in the PPM data file.
          - the file specified with the <CODEBASE> tag in the PPD file is
            retrieved/copied into the directory created above.
          - the package is unarchived in the directory created for this package
          - individual files from the archive are installed in the appropriate
            directories of the local Perl installation.
          - perllocal.pod is updated with the install information.
          - if provided, the <INSTALL> script from the PPD is executed in the
            directory created above.
          - information about the installation is stored in the PPM data file.

PPM::RemovePackage("package" => $package, "force" => $force)
     Removes the specified package from the system.  Reads the package's
     PPD (stored during installation) for removal details.  If 'force' is
     specified, even a package required by PPM will be removed (useful
     when installing an upgrade).

PPM::VerifyPackage("package" => $package, "location" => $location, "upgrade" => $upgrade)
     Reads a PPD file for 'package', and compares the currently installed
     version of 'package' to the version available according to the PPD.
     The PPD file is expected to be on a local directory or remote site
     specified either in the PPM data file or in the 'location' argument.
     The 'location' argument may be a directory location or a URL.  The
     'upgrade' argument forces an upgrade if the installed package is not
     up-to-date.

     The PPD file for each package will initially be searched for at
     'location', and if not found will then be searched for using the
     locations specified in the PPM data file.

PPM::QueryInstalledPackages("searchRE" => $searchRE, "searchtag" => $searchtag, "ignorecase" => $ignorecase);
     Returns a hash containing information about all installed packages.
     By default, a list of all installed packages is returned.  If a
     regular expression 'searchRE' is specified, only packages matching it
     are returned.  If 'searchtag' is specified, the pattern match is
     applied to the appropriate tag (e.g., ABSTRACT).

     The data comes from the PPM data file, which contains installation
     information about each installed package.

PPM::InstalledPackageProperties();
     Returns a hash with package names as keys, and package properties as
     attributes.

PPM::RepositoryPackages("location" => $location);
     Returns a hash, with 'location' being the key, and arrays of all
     packages with package description (PPD) files available at 'location'
     as its elements.  'location' may be either a remote address or a
     directory path.  If 'location' is not specified, the default location
     as specified in the PPM data file will be used.

PPM::ListOfRepositories();
     Returns a hash containing the name of the repository and its location.
     These repositories will be searched if an explicit location is not
     provided in any function needing to locate a PPD.

PPM::RemoveRepository("repository" => $repository, "save" => $save);
     Removes the repository named 'repository' from the list of available
     repositories.  If 'save' is not specified, the change is for the
     current session only.

PPM::AddRepository("repository" => $repository, "location" => $location, "save" => $save);
     Adds the repository named 'repository' to the list of available
     repositories.  If 'save' is not specified, the change is for the
     current session only.

PPM::RepositoryPackageProperties("package" => $package, "location" => $location);
     Reads the PPD file for 'package', from 'location' or the default
     repository, and returns a hash with keys being the various tags from
     the PPD (e.g.  'ABSTRACT', 'AUTHOR', etc.).

PPM::RepositorySummary("location" => $location);
     Attempts to retrieve the summary file associated with the specified
     repository, or from all repositories if 'location' is not specified.
     The return value is a hash with the key being the repository, and the
     data being another hash of package name keys, and package detail data.

PPM::GetPPMOptions();
     Returns a hash containing values for all PPM internal options
     ('IGNORECASE', 'CLEAN', 'CONFIRM', 'ROOT', 'BUILDDIR').

PPM::SetPPMOptions("options" => %options, "save" => $save);
     Sets internal PPM options as specified in the 'options' hash, which is
     expected to be the hash previously returned by a call to
     GetPPMOptions().

EXAMPLES
========

PPM::AddRepository("repository" => 'ActiveState', "location" => "http://www.ActiveState.com/packages", "save" => 1);
     Adds a repository to the list of available repositories, and saves it
     in the PPM options file.

PPM::InstallPackage("package" => 'http://www.ActiveState.com/packages/foo.ppd');
     Installs the software package 'foo' based on the information in the
     PPD obtained from the specified URL.

PPM::VerifyPackage("package" => 'foo', "upgrade" => true)
     Compares the currently installed version of the software package
     'foo' to the one available according to the PPD obtained from the
     package-specific location provided in the PPM data file, and upgrades
     to a newer version if available.  If a location for this specific
     package is not given in PPM data file, a default location is searched.

PPM::VerifyPackage("package" => 'foo', "location" => 'P:\PACKAGES', "upgrade" => true);
     Compares the currently installed version of the software package 'foo'
     to the one available according to the PPD obtained from the specified
     directory, and upgrades to a newer version if available.

PPM::VerifyPackage("package" => 'PerlDB');
     Verifies that package 'PerlDB' is up to date, using package locations
     specified in the PPM data file.

PPM::RepositoryPackages("location" => http://www.ActiveState.com/packages);
     Returns a hash keyed on 'location', with its elements being an array
     of packages with PPD files available at the specified location.

%opts = PPM::GetPPMOptions();
$options{'CONFIRM'} = '0';
PPM::SetPPMOptions("options" => \%opts, "save" => 1);
     Sets and saves the value of the option 'CONFIRM' to '0'.

ENVIRONMENT VARIABLES
=====================

HTTP_proxy
     If the environment variable 'HTTP_proxy' is set, then it will be used
     as the address of a proxy for accessing the Internet.  If the
     environment variables 'HTTP_proxy_user' and 'HTTP_proxy_pass' are
     set, they will be used as the login and password for the proxy
     server.  If a proxy requires a certain User-Agent value (e.g.
     "Mozilla/5.0"), this can be set using the 'HTTP_proxy_agent'
     environment variable.

FILES
=====

package.ppd
     A description of a software package, in Perl Package Distribution
     (PPD) format.  More information on this file format can be found in
     XML/PPD.  PPM stores a copy of the PPD it uses to
     install or upgrade any software package.

ppm.xml - PPM data file.
     The XML format file in which PPM stores configuration and package
     installation information.  This file is created when PPM is installed,
     and under normal circumstances should never require modification other
     than by PPM itself.  For more information on this file, refer to
     XML/PPMConfig.

AUTHOR
======

   Murray Nesbitt, <`murray@ActiveState.com'>

SEE ALSO
========

   See XML/PPMConfig, .

SOAP client for PPM repository
******************************

NAME
====

   PPM::SOAPClient - SOAP client for PPM repository

SYNOPSIS
========

     use PPM::SOAPClient;
     ...
     my $client = new PPM::SOAPClient;
     my @results = $client->search( 'sarathy' );

DESCRIPTION
===========

   `PPM::SOAPClient' implements a SOAP client to be used to access a PPM
repository through a SOAP interface.  All of the functionality for making
and parsing the SOAP request is handled internally; simply access the
provided methods and you'll be returned a data structure containing the
actual response.

METHODS
=======

new ($server)
     Instantiates a new SOAP client, specifying the server that will be
     used for all later connections. '$server' should be provided as the
     URL to the SOAP server that we're going to connect to and make
     queries against.

     Note, that this method accepts both "http://" and "soap://" server
     URLs exactly the same way (we treat '`soap://'' URLs as standard HTTP
     URLs).

version ()
     Gets the version number of the SOAP server that we're connected to. If
     we're unable to contact the server or its offline, this method returns
     'undef'.

searchAbstract ($search)
     Searches within the 'ABSTRACT' field within all of the packages held
     in the repository on the server. The value '`$search'' may be a regex
     that will be used to match against the abstracts. If no value for
     '`$search'' is provided, the server treats the search to be for
     '`.*'' (everything).

searchAuthor ($search)
     Searches within the 'AUTHOR' field within all of the packages held in
     the repository on the server. The value '`$search'' may be a regex
     that will be used to match against the authors. If no value of
     '`$search'' is provided, the server treats the search to be for
     '`.*'' (everything).

searchTitle ($search)
     Searches within the 'title' field within all of the packages held in
     the repository on the server. The value '`$search'' may be a regex
     that will be used to match against the titles. If no value of
     '`$search'' is provided, the server treats the search to be for
     '`.*'' (everything).

search ($search)
     Searches through all of the fields within all of the packages held in
     the repository on the server. The value '`$search'' may be a regex
     that will be used to match against the field values. If no value of
     '`$search'' is provided, the server treats the search to be for
     '`.*'' (everything).

packages ()
     Generates a list of all of the packages currently available in the
     repository. The value returned to the caller is a list containing the
     names of all of the packages in the repository.

fetch_ppd ($pkg)
     Fetches the PPD associated with a given package. The full contents of
     the PPD are returned to the caller in XML format as a scalar value.

fetch_summary ()
     Fetches the full summary of all of the packages held in the
     repository. The full contents of the summary are returned to the
     caller in XML format as a scalar value.

_makeSOAPRequest ($method, $search)
     *INTERNAL METHOD.* Makes the SOAP request to the server, doing the
     bulk of the actual work for us.

AUTHOR
======

   Graham TerMarsch (gtermars@home.com)

SEE ALSO
========

   See PPM/SOAPServer, SOAP.

SOAP server for PPM repository
******************************

NAME
====

   PPM::SOAPServer - SOAP server for PPM repository

SYNOPSIS
========

     use SOAP::Transport::HTTP::CGI;
     my $safe_classes = {
       'PPM::SOAPServer' => undef,
       };
     SOAP::Transport::HTTP::CGI->handler( $safe_classes );

DESCRIPTION
===========

   `PPM::SOAPServer' is a module that provides an implementation of a SOAP
server to hold the PPM repository.  Note that it is not required that you
actually instantiate a copy of the server object yourself; the SOAP modules
will take care of this for you when they instantiate the SOAP server.  All
of the 'search*' methods that are provided by this module are made
available through the SOAP interface and can be accessed through a SOAP
client.

METHODS
=======

new ()
     Instantiates a new PPM::SOAPServer object, returning a reference to
     the newly created object to the caller. During instantiation, we also
     read in a full copy of the information held within the repository so
     that we can run queries against it later.

handle_request ($hdrs, $body, $envelope)
     Handles the complete request provided through the SOAP interface. This
     method determines which method is to be invoked and calls off to that
     method to generate the response which is to be returned to the
     caller. Once the response has been generated, we stuff this back into
     the envelope so that it can be returned via the SOAP server.

version ()
     Returns to the caller the version number of the SOAP server that is
     running.

searchAbstract ($params)
     Searches against the 'ABSTRACT' field within the packages held in the
     repository. Within the given parameters, a key of "search" should be
     provided containing the term to search for (which can be a regex). If
     no "search" key is provided, a complete list of all of the packages
     are returned to the caller.

     The return value provided from this method will be a reference to a
     hash containing the result set. A key named "num_results" will be
     provided, stating the number of results to be found in the result
     set. Each item in the result set will be named "result_???" where
     '???' is the number of that item in the result set. For example, a
     search returning two results would return a reference to a hash with
     keys of '`num_results'', '`result_1'', and '`result_2''.

searchAuthor ($params)
     Searches against the 'AUTHOR' field within the packages held in the
     repository. Within the given parameters, a key of "search" should be
     provided containing the term to search for (which can be a regex). If
     no "search" key is provided, a complete list of all of the packages
     are returned to the caller.

     The return value provided from this method will be a reference to a
     hash containing the result set. A key named "num_results" will be
     provided, stating the number of results to be found in the result
     set. Each item in the result set will be named "result_???" where
     '???' is the number of that item in the result set. For example, a
     search returning two results would returns a reference to a hash with
     keys of '`num_results'', '`result_1'', and '`result_2''.

searchTitle ($params)
     Searches against the 'TITLE' field within the packages held in the
     repository. Within the given parameters, a key of "search" should be
     provided containing the term to search for (which can be a regex). If
     no "search" key is provided, a complete list of all of the packages
     are returned to the caller.

     The return value provided from this method will be a reference to a
     hash containing the result set. A key named "num_results" will be
     provided, stating the number of results to be found in the result
     set. Each item in the result set will be named "result_???" where
     '???' is the number of that item in the result set. For example, a
     search returning two results would returns a reference to a hash with
     keys of '`num_results'', '`result_1'', and '`result_2''.

search ($params)
     Searches against _all_ of the fields within the packages held in the
     repository. Within the given parameters, a key of "search" should be
     provided containing the term to search for (which can be a regex). If
     no "search" key is provided, a complete list of all of the packages
     are returned to the caller.

     The return value provided from this method will be a reference to a
     hash containing the result set. A key named "num_results" will be
     provided, stating the number of results to be found in the result
     set. Each item in the result set will be named "result_???" where
     '???' is the number of that item in the result set. For example, a
     search returning two results would returns a reference to a hash with
     keys of '`num_results'', '`result_1'', and '`result_2''.

packages ()
     Generates a list of all of the packages currently available in the
     repository.

     The return value provided from this method will be a reference to a
     hash containing the result set. A key named "num_results" will be
     provided, stating the number of results to be found in the result
     set. Each item in the result set will be named "result_???" where
     '???' is the number of that item in the result set. For example, a
     repository with two packages in it would return a reference to a hash
     with keys of '`num_results'', '`result_1'', and '`result_2''.

fetch_ppd ($params)
     Fetches the PPD from our package list for a specific package. The
     parameters provided should include a key named 'package', which is the
     name of the package for which we wish to fetch the PPD for. This
     method returns to the caller a hash reference containing the matching
     results. A key named "num_results" will be present stating the number
     of matching results (either 0 or 1). If a PPD has been found for the
     requested package, a key of "result_1" will also be present, whose
     value will be the full contents of the PPD file (in XML format) as a
     scalar value.

fetch_summary ()
     Fetches a summary of the entire contents of the repository. This
     method returns to the caller a reference to a hash containing the
     following keys: '`num_results'', '`result_1''. The value of the
     '`result_1'' key is the full contents of the repository summary file
     (in XML format) as a scalar value.

_xml_escape ($val)
     *INTERNAL METHOD.* Cheap little function to escape out most of the
     things in the value we're passing back so that its at least "clean".
     This should really be using some sort of XML::Entities module to do
     the conversion, though; I've just hacked this together because these
     are the things that I encountered.

_search ($field, $search)
     *INTERNAL METHOD.* Does a general search against the fields present
     for a package within the repository, searching for a specific term
     (which could be a regex). If no '$field' value is provided, this
     method searches through _all_ of the fields present for a given
     package. If no '`$search'' value is provided, '`.*'' is deemed to be
     the matching regex (everything).

     The return value provided from this method will be a reference to a
     hash containing the result set. A key named "num_results" will be
     provided, stating the number of results to be found in the result
     set. Each item in the result set will be named "result_???" where
     '???' is the number of that item in the result set. For example, a
     search returning two results would returns a reference to a hash with
     keys of '`num_results'', '`result_1'', and '`result_2''.

_pkginfo ($package)
     *INTERNAL METHOD.* Takes the XML object representation of a package
     and turns it into a single hash reference containing only select
     portions of the package information. This hash reference is then
     returned to the caller.

_loadRepository ()
     *INTERNAL METHOD.* Loads up information about the contents of the
     repository, stuffing them into the global namespace. If the
     repository has already been loaded, this method simply returns
     without doing anything.  NOTE, that this method is _NOT_ an instance
     method; it's a package method.

AUTHOR
======

   Graham TerMarsch (gtermars@home.com)

SEE ALSO
========

   See PPM/SOAPClient, SOAP.

Handler for Palm AddressBook databases.
***************************************

NAME
====

   Palm::Address - Handler for Palm AddressBook databases.

SYNOPSIS
========

     use Palm::Address;

DESCRIPTION
===========

   The Address PDB handler is a helper class for the Palm::PDB package.
It parses AddressBook databases.

AppInfo block
-------------

   The AppInfo block begins with standard category support. See
Palm/StdAppInfo, for details.

   Other fields include:

     $pdb->{appinfo}{lastUniqueID}
     $pdb->{appinfo}{dirtyFields}

   I don't know what these are.

     $pdb->{appinfo}{fieldLabels}{name}
     $pdb->{appinfo}{fieldLabels}{firstName}
     $pdb->{appinfo}{fieldLabels}{company}
     $pdb->{appinfo}{fieldLabels}{phone1}
     $pdb->{appinfo}{fieldLabels}{phone2}
     $pdb->{appinfo}{fieldLabels}{phone3}
     $pdb->{appinfo}{fieldLabels}{phone4}
     $pdb->{appinfo}{fieldLabels}{phone5}
     $pdb->{appinfo}{fieldLabels}{phone6}
     $pdb->{appinfo}{fieldLabels}{phone7}
     $pdb->{appinfo}{fieldLabels}{phone8}
     $pdb->{appinfo}{fieldLabels}{address}
     $pdb->{appinfo}{fieldLabels}{city}
     $pdb->{appinfo}{fieldLabels}{state}
     $pdb->{appinfo}{fieldLabels}{zipCode}
     $pdb->{appinfo}{fieldLabels}{country}
     $pdb->{appinfo}{fieldLabels}{title}
     $pdb->{appinfo}{fieldLabels}{custom1}
     $pdb->{appinfo}{fieldLabels}{custom2}
     $pdb->{appinfo}{fieldLabels}{custom3}
     $pdb->{appinfo}{fieldLabels}{custom4}
     $pdb->{appinfo}{fieldLabels}{note}

   These are the names of the various fields in the address record.

     $pdb->{appinfo}{country}

   An integer: the code for the country for which these labels were
designed. The country name is available as

     $Palm::Address::countries[$pdb->{appinfo}{country}];

     $pdb->{appinfo}{misc}

   An integer. The least-significant bit is a flag that indicates whether
the database should be sorted by company. The other bits are reserved.

Sort block
----------

     $pdb->{sort}

   This is a scalar, the raw data of the sort block.

Records
-------

     $record = $pdb->{records}[N];

     $record->{fields}{name}
     $record->{fields}{firstName}
     $record->{fields}{company}
     $record->{fields}{phone1}
     $record->{fields}{phone2}
     $record->{fields}{phone3}
     $record->{fields}{phone4}
     $record->{fields}{phone5}
     $record->{fields}{address}
     $record->{fields}{city}
     $record->{fields}{state}
     $record->{fields}{zipCode}
     $record->{fields}{country}
     $record->{fields}{title}
     $record->{fields}{custom1}
     $record->{fields}{custom2}
     $record->{fields}{custom3}
     $record->{fields}{custom4}
     $record->{fields}{note}

   These are scalars, the values of the various address book fields.

     $record->{phoneLabel}{phone1}
     $record->{phoneLabel}{phone2}
     $record->{phoneLabel}{phone3}
     $record->{phoneLabel}{phone4}
     $record->{phoneLabel}{phone5}

   Most fields in an AddressBook record are straightforward: the "name"
field always gives the person's last name.

   The "phoneN" fields, on the other hand, can mean different things in
different records. There are five such fields in each record, each of
which can take on one of eight different values: "Work", "Home", "Fax",
"Other", "E-mail", "Main", "Pager" and "Mobile".

   The $record->{phoneLabel}{phone*} fields are integers. Each one is an
index into @Palm::Address::phoneLabels, and indicates which particular
type of phone number each of the $record->{phone*} fields represents.

     $record->{phoneLabel}{display}

   Like the phone* fields above, this is an index into
@Palm::Address::phoneLabels. It indicates which of the phone* fields to
display in the list view.

     $record->{phoneLabel}{reserved}

   I don't know what this is.

METHODS
=======

new
---

     $pdb = new Palm::Address;

   Create a new PDB, initialized with the various Palm::Address fields and
an empty record list.

   Use this method if you're creating an Address PDB from scratch.

new_Record
----------

     $record = $pdb->new_Record;

   Creates a new Address record, with blank values for all of the fields.
The AppInfo block will contain only an "Unfiled" category, with ID 0.

AUTHOR
======

   Andrew Arensburger <arensb@ooblick.com>

SEE ALSO
========

   Palm::PDB(3)

   Palm::StdAppInfo(3)

BUGS
====

   The new() method initializes the AppInfo block with English labels and
"United States" as the country.

Handler for Palm DateBook databases.
************************************

NAME
====

   Palm::Datebook - Handler for Palm DateBook databases.

SYNOPSIS
========

     use Palm::Datebook;

DESCRIPTION
===========

   The Datebook PDB handler is a helper class for the Palm::PDB package.
It parses DateBook databases.

AppInfo block
-------------

   The AppInfo block begins with standard category support. See
Palm/StdAppInfo, for details.

Sort block
----------

     $pdb->{sort}

   This is a scalar, the raw data of the sort block.

Records
-------

     $record = $pdb->{records}[N]

     $record->{day}
     $record->{month}
     $record->{year}

   The day, month and year of the event. For repeating events, this is the
first date at which the event occurs.

     $record->{start_hour}
     $record->{start_minute}
     $record->{end_hour}
     $record->{end_minute}

   The start and end times of the event. For untimed events, all of these
are 0xff.

     $record->{when_changed}

   This is defined and true iff the "when info" for the record has
changed. I don't know what this means.

     $record->{alarm}{advance}
     $record->{alarm}{unit}

   If the record has an alarm associated with it, the %{$record->{alarm}}
hash exists. The "unit" subfield is an integer: 0 for minutes, 1 for
hours, 2 for days. The "advance" subfield specifies how many units before
the event the alarm should ring.  *e.g.*, if "unit" is 1 and "advance" is
5, then the alarm will sound 5 hours before the event.

   If "advance" is -1, then there is no alarm associated with this event.

     %{$record->{repeat}}

   This has exists iff this is a repeating event.

     $record->{repeat}{type}

   An integer which specifies the type of repeat:

  1. no repeat.

  2. a daily event, one that occurs every day.

  3. a weekly event, one that occurs every week on the same day(s). An
     event may occur on several days every week, *e.g.*, every Monday,
     Wednesday and Friday.

     For weekly events, the following fields are defined:

          @{$record->{repeat}{repeat_days}}

     This is an array of 7 elements; each element is true iff the event
     occurs on the corresponding day. I don't know whether the array begins
     with Sunday, or with the start-of-week day as defined in the
     preferences.

          $record->{repeat}{start_of_week}

     I'm not sure what this is, but the Datebook app appears to perform
     some hairy calculations involving this.

  4. a "monthly by day" event, *e.g.*, one that occurs on the second
     Friday of every month.

     For "monthly by day" events, the following fields are defined:

          $record->{repeat}{weeknum}

     The number of the week on which the event occurs. A value of 5 means
     that the event occurs on the last week of the month.

          $record->{repeat}{daynum}

     An integer, the day of the week on which the event occurs. Again, I
     don't know whether 0 means Sunday, or the start-of-week day as defined
     in the preferences.

  5. a "monthly by date" event, *e.g.*, one that occurs on the 12th of
     every month.

  6. a yearly event, *e.g.*, one that occurs every year on December 25th.

          $record->{repeat}{frequency}

     Specifies the frequency of the repeat. For instance, if the event is a
     daily one, and $record->{repeat}{frequency} is 3, then the event
     occurs every 3 days.

     $record->{repeat}{unknown}

   I don't know what this is.

     $record->{repeat}{end_day}
     $record->{repeat}{end_month}
     $record->{repeat}{end_year}

   The last day, month and year on which the event occurs.

     @{$record->{exceptions}}
     $day   = $record->{exceptions}[N][0]
     $month = $record->{exceptions}[N][0]
     $year  = $record->{exceptions}[N][0]

   If there are any exceptions to a repeating event, *e.g.* a weekly
meeting that was cancelled one time, then the  @{$record->{exceptions}}
array is defined.

   Each element in this array is a reference to an anonymous array with
three elements: the day, month, and year of the exception.

     $record->{description}

   A text string, the description of the event.

     $record->{note}

   A text string, the note (if any) attached to the event.

METHODS
=======

new
---

     $pdb = new Palm::Datebook;

   Create a new PDB, initialized with the various Palm::Datebook fields
and an empty record list.

new_Record
----------

     $record = $pdb->new_Record;

   Creates a new Datebook record, with blank values for all of the fields.

AUTHOR
======

   Andrew Arensburger <arensb@ooblick.com>

SEE ALSO
========

   Palm::PDB(3)

   Palm::StdAppInfo(3)

Handler for Palm Mail databases.
********************************

NAME
====

   Palm::Mail - Handler for Palm Mail databases.

SYNOPSIS
========

     use Palm::Mail;

DESCRIPTION
===========

   The Mail PDB handler is a helper class for the Palm::PDB package. It
parses Mail databases.

AppInfo block
-------------

   The AppInfo block begins with standard category support. See
Palm/StdAppInfo, for details.

   Other fields include:

     $pdb->{appinfo}{sortOrder}
     $pdb->{appinfo}{unsent}
     $pdb->{appinfo}{sigOffset}

   I don't know what these are.

Sort block
----------

     $pdb->{sort}

   This is a scalar, the raw data of the sort block.

Records
-------

     $record = $pdb->{records}[N]

     $record->{year}
     $record->{month}
     $record->{day}
     $record->{hour}
     $record->{minute}

   The message's timestamp.

     $record->{is_read}

   This is defined and true iff the message has been read.

     $record->{has_signature}

   For outgoing messages, this is defined and true iff the message should
have a signature attached. The signature itself is stored in the "Saved
Preferences.prc" database, and is of type "mail" with ID 2.

     $record->{confirm_read}

   If this is defined and true, then the sender requests notification when
the message has been read.

     $record->{confirm_delivery}

   If this is defined and true, then the sender requests notification when
the message has been delivered.

     $record->{priority}

   An integer in the range 0-2, for high, normal, or low priority,
respectively.

     $record->{addressing}

   An integer in the range 0-2, indicating the addressing type: To, Cc, or
Bcc respectively. I don't know what this means.

     $record->{subject}
     $record->{from}
     $record->{to}
     $record->{cc}
     $record->{bcc}
     $record->{replyTo}
     $record->{sentTo}

   Strings, the various header fields.

     $record->{body}

   A string, the body of the message.

METHODS
=======

new
---

     $pdb = new Palm::Mail;

   Create a new PDB, initialized with the various Palm::Mail fields and an
empty record list.

   Use this method if you're creating a Mail PDB from scratch.

new_Record
----------

     $record = $pdb->new_Record;

   Creates a new Mail record, with blank values for all of the fields.

   Note: the time given by the year, month, day, `hour', and `minute'
fields in the new record are initialized to the time when the record was
created. They should be reset to the time when the message was sent.

AUTHOR
======

   Andrew Arensburger <arensb@ooblick.com>

SEE ALSO
========

   Palm::PDB(3)

   Palm::StdAppInfo(3)

Handler for Palm Memo databases.
********************************

NAME
====

   Palm::Memo - Handler for Palm Memo databases.

SYNOPSIS
========

     use Palm::Memo;

DESCRIPTION
===========

   The Memo PDB handler is a helper class for the Palm::PDB package. It
parses Memo databases.

AppInfo block
-------------

   The AppInfo block begins with standard category support. See
Palm/StdAppInfo, for details.

   Other fields include:

     $pdb->{appinfo}{sortOrder}

   I don't know what this is.

Sort block
----------

     $pdb->{sort}

   This is a scalar, the raw data of the sort block.

Records
-------

     $record = $pdb->{records}[N]

     $record->{data}

   A string, the text of the memo.

new
---

     $pdb = new Palm::Memo;

   Create a new PDB, initialized with the various Palm::Memo fields and an
empty record list.

   Use this method if you're creating a Memo PDB from scratch.

new_Record
----------

     $record = $pdb->new_Record;

   Creates a new Memo record, with blank values for all of the fields.

AUTHOR
======

   Andrew Arensburger <arensb@ooblick.com>

SEE ALSO
========

   Palm::PDB(3)

   Palm::StdAppInfo(3)

Parse Palm database files.
**************************

NAME
====

   Palm::PDB - Parse Palm database files.

SYNOPSIS
========

     use Palm::PDB;
     use SomeHelperClass;

     $pdb = new Palm::PDB;
     $pdb->Load("myfile.pdb");

     # Manipulate records in $pdb

     $pdb->Write("myotherfile.pdb");

DESCRIPTION
===========

   The Palm::PDB module provides a framework for reading and writing
database files for use on PalmOS devices such as the PalmPilot. It can
read and write both Palm Database (`.pdb') and Palm Resource (`.prc')
files.

   By itself, the PDB module is not terribly useful; it is intended to be
used in conjunction with supplemental modules for specific types of
databases, such as Palm::Raw or Palm::Memo.

   The Palm::PDB module encapsulates the common work of parsing the
structure of a Palm database. The `Load()|' in this node function reads
the file, then passes the individual chunks (header, records, etc.) to
application-specific functions for processing. Similarly, the `Write()|'
in this node function calls application-specific functions to get the
individual chunks, then writes them to a file.

METHODS
=======

new
---

     $new = new Palm::PDB();

   Creates a new PDB. $new is a reference to an anonymous hash. Some of
its elements have special significance. See `Load()|' in this node.

RegisterPDBHandlers
-------------------

     &Palm::PDB::RegisterPDBHandlers("classname", typespec...);

   Typically:

     &Palm::PDB::RegisterPDBHandlers(__PACKAGE__,
     	[ "FooB", "DATA" ],
     	);

   The $pdb->`Load()|' in this node method acts as a virtual constructor.
When it reads the header of a `.pdb' file, it looks up the file's creator
and type in a set of tables, and reblesses $pdb into a class capable of
parsing the application-specific parts of the file (AppInfo block,
records, etc.)

   RegisterPDBHandlers() adds entries to these tables; it says that any
file whose creator and/or type match any of the *typespec*s (there may be
several) should be reblessed into the class *classname*.

   Note that RegisterPDBHandlers() applies only to record databases
(`.pdb' files). For resource databases, see `RegisterPRCHandlers()|' in
this node.

   RegisterPDBHandlers() is typically called in the import() function of a
helper class. In this case, the class is registering itself, and it is
simplest just to use __PACKAGE__ for the package name:

     package PalmFoo;
     use Palm::PDB;

     sub import
     {
         &Palm::PDB::RegisterPDBHandlers(__PACKAGE__,
             [ "FooZ", "DATA" ]
             );
     }

   A *typespec* can be either a string, or an anonymous array with two
elements. If it is an anonymous array, then the first element is the
file's creator; the second element is its type. If a *typespec* is a
string, it is equivalent to specifying that string as the database's
creator, and a wildcard as its type.

   The creator and type should be either four-character strings, or the
empty string. An empty string represents a wildcard. Thus:

     &Palm::PDB::RegisterPDBHandlers("MyClass",
         [ "fOOf", "DATA" ],
         [ "BarB", "" ],
         [ "", "BazQ" ],
         "Fred"
         );

   Class MyClass will handle:

     Databases whose creator is `fOOf' and whose type is DATA.

     Databases whose creator is `BarB', of any type.

     Databases with any creator whose type is `BazQ'.

     Databases whose creator is `Fred', of any type.

   sub RegisterPDBHandlers { 	my $handler = shift;		# Name of
class that'll handle 					# these databases 	my @types = @_; 	my $item;

     foreach $item (@types)
     {
     	if (ref($item) eq "ARRAY")
     	{
     		$PDBHandlers{$item->[0]}{$item->[1]} = $handler;
     	} else {
     		$PDBHandlers{$item}{""} = $handler;
     	}
     }
     }

RegisterPRCHandlers
-------------------

     &Palm::PDB::RegisterPRCHandlers("classname", typespec...);

   Typically:

     &Palm::PDB::RegisterPRCHandlers(__PACKAGE__,
     	[ "FooZ", "CODE" ],
     	);

   RegisterPRCHandlers() is similar to `RegisterPDBHandlers()|' in this
node, but specifies a class to handle resource database (`.prc') files.

   A class for parsing applications should begin with:

     package PalmApps;
     use Palm::PDB;

     sub import
     {
         &Palm::PDB::RegisterPRCHandlers(__PACKAGE__,
             [ "", "appl" ]
             );
     }

Load
----

     $pdb->Load("filename");

   Reads the file filename, parses it, reblesses $pdb to the appropriate
class, and invokes appropriate methods to parse the application-specific
parts of the database (see `' in this node).

   Load() uses the *typespec*s given to RegisterPDBHandlers() and
RegisterPRCHandlers() when deciding how to rebless $pdb. For record
databases, it uses the *typespec*s passed to RegisterPDBHandlers(), and
for resource databases, it uses the *typespec*s passed to
RegisterPRCHandlers().

   Load() looks for matching *typespec*s in the following order, from most
to least specific:

  1. A *typespec* that specifies both the database's creator and its type
     exactly.

  2. A *typespec* that specifies the database's type and has a wildcard
     for the creator (this is rarely used).

  3. A *typespec* that specifies the database's creator and has a wildcard
     for the type.

  4. A *typespec* that has wildcards for both the creator and type.

        After Load() returns, $pdb may contain the following fields:

$pdb->{"name"}
     The name of the database.

$pdb->{"attributes"}{"resource"}
$pdb->{"attributes"}{"read-only"}
$pdb->{"attributes"}{"AppInfo dirty"}
$pdb->{"attributes"}{"backup"}
$pdb->{"attributes"}{"OK newer"}
$pdb->{"attributes"}{"reset"}
$pdb->{"attributes"}{"open"}
     These are the attribute flags from the database header. Each is true
     iff the corresponding flag is set.

$pdb->{"version"}
     The database's version number. An integer.

$pdb->{"ctime"}
$pdb->{"mtime"}
$pdb->{"baktime"}
     The database's creation time, last modification time, and time of last
     backup, in Unix `time_t' format (seconds since Jan. 1, 1970).

$pdb->{"modnum"}
     The database's modification number. An integer.

$pdb->{"type"}
     The database's type. A four-character string.

$pdb->{"creator"}
     The database's creator. A four-character string.

$pdb->{"uniqueIDseed"}
     The database's unique ID seed. An integer.

$pdb->{"2NULs"}
     The two NUL bytes that appear after the record index and the AppInfo
     block. Included here because every once in a long while, they are not
     NULs, for some reason.

$pdb->{"appinfo"}
     The AppInfo block, as returned by the $pdb->ParseAppInfoBlock() helper
     method.

$pdb->{"sort"}
     The sort block, as returned by the $pdb->ParseSortBlock() helper
     method.

@{$pdb->{"records"}}
     The list of records in the database, as returned by the
     $pdb->ParseRecord() helper method. Resource databases do not have
     this.

@{$pdb->{"resources"}}
     The list of resources in the database, as returned by the
     $pdb->ParseResource() helper method. Record databases do not have
     this.

   All of these fields may be set by hand, but should conform to the
format given above.

   # Load sub Load { 	my $self = shift; 	my $fname = shift;		#
Filename to read from 	my $buf;			# Buffer into which to read stuff

     # Open database file
     open PDB, "< $fname" or die "Can't open \"$fname\": $!\n";

     # Get the size of the file. It'll be useful later
     seek PDB, 0, 2;		# 2 == SEEK_END. Seek to the end.
     $self->{_size} = tell PDB;
     seek PDB, 0, 0;		# 0 == SEEK_START. Rewind to the beginning.

     # Read header
     my $name;
     my $attributes;
     my $version;
     my $ctime;
     my $mtime;
     my $baktime;
     my $modnum;
     my $appinfo_offset;
     my $sort_offset;
     my $type;
     my $creator;
     my $uniqueIDseed;

     read PDB, $buf, $HeaderLen;	# Read the PDB header

     # Split header into its component fields
     ($name, $attributes, $version, $ctime, $mtime, $baktime,
     $modnum, $appinfo_offset, $sort_offset, $type, $creator,
     $uniqueIDseed) =
     	unpack "a32 n n N N N N N N a4 a4 N", $buf;

     ($self->{name} = $name) =~ s/\0*$//;
     $self->{attributes}{resource} = 1 if $attributes & 0x0001;
     $self->{attributes}{"read-only"} = 1 if $attributes & 0x0002;
     $self->{attributes}{"AppInfo dirty"} = 1 if $attributes & 0x0004;
     $self->{attributes}{backup} = 1 if $attributes & 0x0008;
     $self->{attributes}{"OK newer"} = 1 if $attributes & 0x0010;
     $self->{attributes}{reset} = 1 if $attributes & 0x0020;
     $self->{attributes}{open} = 1 if $attributes & 0x0040;
     $self->{version} = $version;
     $self->{ctime} = $ctime - $EPOCH_1904;
     $self->{mtime} = $mtime - $EPOCH_1904;
     $self->{baktime} = $baktime - $EPOCH_1904;
     $self->{modnum} = $modnum;
     # _appinfo_offset and _sort_offset are private fields
     $self->{_appinfo_offset} = $appinfo_offset;
     $self->{_sort_offset} = $sort_offset;
     $self->{type} = $type;
     $self->{creator} = $creator;
     $self->{uniqueIDseed} = $uniqueIDseed;

     # Rebless this PDB object, depending on its type and/or
     # creator. This allows us to magically invoke the proper
     # &Parse*() function on the various parts of the database.

     # Look for most specific handlers first, least specific ones
     # last. That is, first look for a handler that deals
     # specifically with this database's creator and type, then for
     # one that deals with this database's creator and any type,
     # and finally for one that deals with anything.

     my $handler;
     if ($self->{attributes}{resource})
     {
     	# Look among resource handlers
     	$handler = $PRCHandlers{$self->{creator}}{$self->{type}} ||
     		$PRCHandlers{undef}{$self->{type}} ||
     		$PRCHandlers{$self->{creator}}{""} ||
     		$PRCHandlers{""}{""};
     } else {
     	# Look among record handlers
     	$handler = $PDBHandlers{$self->{creator}}{$self->{type}} ||
     		$PDBHandlers{""}{$self->{type}} ||
     		$PDBHandlers{$self->{creator}}{""} ||
     		$PDBHandlers{""}{""};
     }

     if (defined($handler))
     {
     	bless $self, $handler;
     } else {
     	# XXX - This should probably return 'undef' or something,
     	# rather than die.
     	die "No handler defined for creator \"$creator\", type \"$type\"\n";
     }

     ## Read record/resource index
     # Read index header
     read PDB, $buf, $RecIndexHeaderLen;

     my $next_index;
     my $numrecs;

     ($next_index, $numrecs) = unpack "N n", $buf;
     $self->{_numrecs} = $numrecs;

     # Read the index itself
     if ($self->{attributes}{resource})
     {
     	&_load_rsrc_index($self, \*PDB);
     } else {
     	&_load_rec_index($self, \*PDB);
     }

     # Read the two NUL bytes
     read PDB, $buf, 2;
     $self->{"2NULs"} = $buf;

     # Read AppInfo block, if it exists
     if ($self->{_appinfo_offset} != 0)
     {
     	&_load_appinfo_block($self, \*PDB);
     }

     # Read sort block, if it exists
     if ($self->{_sort_offset} != 0)
     {
     	&_load_sort_block($self, \*PDB);
     }

     # Read record/resource list
     if ($self->{attributes}{resource})
     {
     	&_load_resources($self, \*PDB);
     } else {
     	&_load_records($self, \*PDB);
     }

     # These keys were needed for parsing the file, but are not
     # needed any longer. Delete them.
     delete $self->{_index};
     delete $self->{_numrecs};
     delete $self->{_appinfo_offset};
     delete $self->{_sort_offset};
     delete $self->{_size};

     close PDB;
     }

   # _load_rec_index # Private function. Read the record index, for a
record database sub _load_rec_index { 	my $pdb = shift; 	my $fh = shift;		#
Input file handle 	my $i; my $lastoffset = 0;

     # Read each record index entry in turn
     for ($i = 0; $i < $pdb->{_numrecs}; $i++)
     {
     	my $buf;		# Input buffer

     # Read the next record index entry
     my $offset;
     my $attributes;
     my @id;			# Raw ID
     my $id;			# Numerical ID
     my $entry = {};		# Parsed index entry

     read $fh, $buf, $IndexRecLen;

     # The ID field is a bit weird: it's represented as 3
     # bytes, but it's really a double word (long) value.

     ($offset, $attributes, @id) = unpack "N C C3", $buf;
     if ($offset == $lastoffset)
     {
     print STDERR "Record $i has same offset as previous one: $offset\n";
     }
     $lastoffset = $offset;

     $entry->{offset} = $offset;
     $entry->{attributes}{expunged} = 1 if $attributes & 0x80;
     $entry->{attributes}{dirty} = 1 if $attributes & 0x40;
     $entry->{attributes}{deleted} = 1 if $attributes & 0x20;
     $entry->{attributes}{private} = 1 if $attributes & 0x10;
     $entry->{id} = ($id[0] << 16) |
     		($id[1] << 8) |
     		$id[2];

     # The lower 4 bits of the attributes field are
     # overloaded: If the record has been deleted and/or
     # expunged, then bit 0x08 indicates whether the record
     # should be archived. Otherwise (if it's an ordinary,
     # non-deleted record), the lower 4 bits specify the
     # category that the record belongs in.
     if (($attributes & 0xa0) == 0)
     {
     	$entry->{category} = $attributes & 0x0f;
     } else {
     	$entry->{attributes}{archive} = 1
     		if $attributes & 0x08;
     }

     # Put this information on a temporary array
     push @{$pdb->{_index}}, $entry;
     	}
     }

   # _load_rsrc_index # Private function. Read the resource index, for a
resource database sub _load_rsrc_index { 	my $pdb = shift; 	my $fh =
shift;		# Input file handle 	my $i;

     # Read each resource index entry in turn
     for ($i = 0; $i < $pdb->{_numrecs}; $i++)
     {
     	my $buf;		# Input buffer

     # Read the next resource index entry
     my $type;
     my $id;
     my $offset;
     my $entry = {};		# Parsed index entry

     read $fh, $buf, $IndexRsrcLen;

     ($type, $id, $offset) = unpack "a4 n N", $buf;

     $entry->{type} = $type;
     $entry->{id} = $id;
     $entry->{offset} = $offset;

     push @{$pdb->{_index}}, $entry;
     	}
     }

   # _load_appinfo_block # Private function. Read the AppInfo block sub
_load_appinfo_block { 	my $pdb = shift; 	my $fh = shift;		# Input file handle
my $len;		# Length of AppInfo block 	my $buf;		# Input
buffer

     # Sanity check: make sure we're positioned at the beginning of
     # the AppInfo block
     if (tell($fh) != $pdb->{_appinfo_offset})
     {
     	die "Bad AppInfo offset: expected ",
     		sprintf("0x%08x", $pdb->{_appinfo_offset}),
     		", but I'm at ",
     		tell($fh), "\n";
     }

     # There's nothing that explicitly gives the size of the
     # AppInfo block. Rather, it has to be inferred from the offset
     # of the AppInfo block (previously recorded in
     # $pdb->{_appinfo_offset}) and whatever's next in the file.
     # That's either the sort block, the first data record, or the
     # end of the file.

     if ($pdb->{_sort_offset})
     {
     	# The next thing in the file is the sort block
     	$len = $pdb->{_sort_offset} - $pdb->{_appinfo_offset};
     } elsif ((defined $pdb->{_index}) && (@{$pdb->{_index}} != ()))
     {
     	# There's no sort block; the next thing in the file is
     	# the first data record
     	$len = $pdb->{_index}[0]{offset} -
     		$pdb->{_appinfo_offset};
     } else {
     	# There's no sort block and there are no records. The
     	# AppInfo block goes to the end of the file.
     	$len = $pdb->{_size} - $pdb->{_appinfo_offset};
     }

     # Read the AppInfo block
     read $fh, $buf, $len;

     # Tell the real class to parse the AppInfo block
     $pdb->{appinfo} = $pdb->ParseAppInfoBlock($buf);
     }

   # _load_sort_block # Private function. Read the sort block.  sub
_load_sort_block { 	my $pdb = shift; 	my $fh = shift;		# Input file handle 	my
$len;		# Length of sort block 	my $buf;		# Input buffer

     # Sanity check: make sure we're positioned at the beginning of
     # the sort block
     if (tell($fh) != $pdb->{_sort_offset})
     {
     	die "Bad sort block offset: expected ",
     		sprintf("0x%08x", $pdb->{_sort_offset}),
     		", but I'm at ",
     		tell($fh), "\n";
     }

     # There's nothing that explicitly gives the size of the sort
     # block. Rather, it has to be inferred from the offset of the
     # sort block (previously recorded in $pdb->{_sort_offset})
     # and whatever's next in the file. That's either the first
     # data record, or the end of the file.

     if (defined($pdb->{_index}))
     {
     	# The next thing in the file is the first data record
     	$len = $pdb->{_index}[0]{offset} -
     		$pdb->{_sort_offset};
     } else {
     	# There are no records. The sort block goes to the end
     	# of the file.
     	$len = $pdb->{_size} - $pdb->{_sort_offset};
     }

     # Read the AppInfo block
     read $fh, $buf, $len;

     # XXX - Check to see if the sort block has some predefined
     # structure. If so, it might be a good idea to parse the sort
     # block here.

     # Tell the real class to parse the sort block
     $pdb->{sort} = $pdb->ParseSortBlock($buf);
     }

   # _load_records # Private function. Load the actual data records, for a
record database # (PDB) sub _load_records { 	my $pdb = shift; 	my
$fh = shift;		# Input file handle 	my $i;

     # Read each record in turn
     for ($i = 0; $i < $pdb->{_numrecs}; $i++)
     {
     	my $len;	# Length of record
     	my $buf;	# Input buffer

     # Sanity check: make sure we're where we think we
     # should be.
     if (tell($fh) != $pdb->{_index}[$i]{offset})
     {
     	die "Bad offset for record $i: expected ",
     		sprintf("0x%08x",
     			$pdb->{_index}[$i]{offset}),
     		" but it's at ",
     		sprintf("0x%08x", tell($fh)), "\n";
     }

     # Compute the length of the record: the last record
     # extends to the end of the file. The others extend to
     # the beginning of the next record.
     if ($i == $pdb->{_numrecs} - 1)
     {
     	# This is the last record
     	$len = $pdb->{_size} -
     		$pdb->{_index}[$i]{offset};
     } else {
     	# This is not the last record
     	$len = $pdb->{_index}[$i+1]{offset} -
     		$pdb->{_index}[$i]{offset};
     }

     # Read the record
     read $fh, $buf, $len;

     # Tell the real class to parse the record data. Pass
     # &ParseRecord all of the information from the index,
     # plus a "data" field with the raw record data.
     my $record;

     $record = $pdb->ParseRecord(
     	%{$pdb->{_index}[$i]},
     	"data"	=> $buf,
     	);
     push @{$pdb->{records}}, $record;
     	}
     }

   # _load_resources # Private function. Load the actual data resources,
for a resource database # (PRC) sub _load_resources { 	my $pdb = shift; 	my
$fh = shift;		# Input file handle 	my $i;

     # Read each resource in turn
     for ($i = 0; $i < $pdb->{_numrecs}; $i++)
     {
     	my $len;	# Length of record
     	my $buf;	# Input buffer

     # Sanity check: make sure we're where we think we
     # should be.
     if (tell($fh) != $pdb->{_index}[$i]{offset})
     {
     	die "Bad offset for resource $i: expected ",
     		sprintf("0x%08x",
     			$pdb->{_index}[$i]{offset}),
     		" but it's at ",
     		sprintf("0x%08x", tell($fh)), "\n";
     }

     # Compute the length of the resource: the last
     # resource extends to the end of the file. The others
     # extend to the beginning of the next resource.
     if ($i == $pdb->{_numrecs} - 1)
     {
     	# This is the last resource
     	$len = $pdb->{_size} -
     		$pdb->{_index}[$i]{offset};
     } else {
     	# This is not the last resource
     	$len = $pdb->{_index}[$i+1]{offset} -
     		$pdb->{_index}[$i]{offset};
     }

     # Read the resource
     read $fh, $buf, $len;

     # Tell the real class to parse the resource data. Pass
     # &ParseResource all of the information from the
     # index, plus a "data" field with the raw resource
     # data.
     my $resource;

     $resource = $pdb->ParseResource(
     	%{$pdb->{_index}[$i]},
     	"data"	=> $buf,
     	);
     push @{$pdb->{resources}}, $resource;
     	}
     }

Write
-----

     $pdb->Write("filename");

   Invokes methods in helper classes to get the application-specific parts
of the database, then writes the database to the file filename.

   Write() uses the following helper methods:

     PackAppInfoBlock()

     PackSortBlock()

     PackResource() or PackRecord()

new_Record
----------

     $record = Palm::PDB->new_Record();
     $record = new_Record Palm::PDB;

   Creates a new record, with the bare minimum needed:

     $record->{category}
     $record->{attributes}{expunged}
     $record->{attributes}{dirty}
     $record->{attributes}{deleted}
     $record->{attributes}{private}
     $record->{id}

   The "dirty" attribute is originally set, since this function will
usually be called to create records to be added to a database.

append_Record
-------------

     $record  = $pdb->append_Record;
     $record2 = $pdb->append_Record($record1);

   If called without any arguments, creates a new record with
`new_Record()|' in this node, and appends it to $pdb.

   If given a reference to a record, appends that record to
@{$pdb->{records}}.

   Returns a reference to the newly-appended record.

   This method updates $pdb's "last modification" time.

     $resource = Palm::PDB->new_Resource();
     $resource = new_Resource Palm::PDB;

   Creates a new resource and initializes

     $resource->{type}
     $resource->{id}

append_Resource
---------------

     $resource  = $pdb->append_Resource;
     $resource2 = $pdb->append_Resource($resource1);

   If called without any arguments, creates a new resource with
`new_Resource()|' in this node, and appends it to $pdb.

   If given a reference to a resource, appends that resource to
@{$pdb->{resources}}.

   Returns a reference to the newly-appended resource.

   This method updates $pdb's "last modification" time.

findRecordByID
--------------

     $record = $pdb->findRecordByID($id);

   Looks through the list of records in $pdb, and returns a reference to
the record with ID $id, or the undefined value if no such record was found.

delete_Record
-------------

     $pdb->delete_Record($record, $expunge);

   Marks $record for deletion, so that it will be deleted from the
database at the next sync.

   If $expunge is false or omitted, the record will be marked for deletion
with archival. If $expunge is true, the record will be marked for deletion
without archival.

   This method updates $pdb's "last modification" time.

HELPER CLASSES
==============

   $pdb->Load() reblesses $pdb into a new class. This helper class is
expected to convert raw data from the database into parsed representations
of it, and vice-versa.

   A helper class must have all of the methods listed below. The Palm::Raw
class is useful if you don't want to define all of the required methods.

ParseAppInfoBlock
-----------------

     $appinfo = $pdb->ParseAppInfoBlock($buf);

   $buf is a string of raw data. ParseAppInfoBlock() should parse this
data and return it, typically in the form of a reference to an object or
to an anonymous hash.

   This method will not be called if the database does not have an AppInfo
block.

   The return value from ParseAppInfoBlock() will be accessible as
$pdb->{appinfo}.

PackAppInfoBlock
----------------

     $buf = $pdb->PackAppInfoBlock();

   This is the converse of ParseAppInfoBlock(). It takes $pdb's AppInfo
block, $pdb->{appinfo}, and returns a string of binary data that can be
written to the database file.

ParseSortBlock
--------------

     $sort = $pdb->ParseSortBlock($buf);

   $buf is a string of raw data. ParseSortBlock() should parse this data
and return it, typically in the form of a reference to an object or to an
anonymous hash.

   This method will not be called if the database does not have a sort
block.

   The return value from ParseSortBlock() will be accessible as
$pdb->{sort}.

PackSortBlock
-------------

     $buf = $pdb->PackSortBlock();

   This is the converse of ParseSortBlock(). It takes $pdb's sort block,
$pdb->{sort}, and returns a string of raw data that can be written to the
database file.

ParseRecord
-----------

     $record = $pdb->ParseRecord(
             offset         => $offset,	# Record's offset in file
             attributes     =>		# Record attributes
                 {
           	expunged => bool,	# True iff expunged
           	dirty    => bool,	# True iff dirty
           	deleted  => bool,	# True iff deleted
           	private  => bool,	# True iff private
                 },
             category       => $category,	# Record's category number
             id             => $id,	# Record's unique ID
             data           => $buf,	# Raw record data
           );

   ParseRecord() takes the arguments listed above and returns a parsed
representation of the record, typically as a reference to a record object
or anonymous hash.

   The output from ParseRecord() will be appended to  @{$pdb->{records}}.
The records appear in this list in the same order as they appear in the
file.

   $offset argument is not normally useful, but is included for
completeness.

   The fields in %$attributes are boolean values. They are true iff the
record has the corresponding flag set.

   $category is an integer in the range 0-15, which indicates which
category the record belongs to. This is normally an index into a table
given at the beginning of the AppInfo block.

   A typical ParseRecord() method has this general form:

     sub ParseRecord
     {
         my $self = shift
         my %record = @_;

     # Parse $self->{data} and put the fields into new fields in
     # $self.

     delete $record{data};		# No longer useful
     return \%record;
         }

PackRecord
----------

     $buf = $pdb->PackRecord($record);

   The converse of ParseRecord(). PackRecord() takes a record as returned
by ParseRecord() and returns a string of raw data that can be written to
the database file.

   PackRecord() is never called when writing a resource database.

ParseResource
-------------

     $record = $pdb->ParseResource(
             type   => $type,		# Resource type
             id     => $id,		# Resource ID
             offset => $offset,		# Resource's offset in file
             data   => $buf,		# Raw resource data
           );

   ParseResource() takes the arguments listed above and returns a parsed
representation of the resource, typically as a reference to a resource
object or anonymous hash.

   The output from ParseResource() will be appended to
@{$pdb->{resources}}. The resources appear in this list in the same order
as they appear in the file.

   $type is a four-character string giving the resource's type.

   $id is an integer that uniquely identifies the resource amongst others
of its type.

   $offset is not normally useful, but is included for completeness.

PackResource
------------

     $buf = $pdb->PackResource($resource);

   The converse of ParseResource(). PackResource() takes a resource as
returned by PackResource() and returns a string of raw data that can be
written to the database file.

   PackResource() is never called when writing a record database.

BUGS
====

   These functions die too easily. They should return an error code.

   Database manipulation is still an arcane art.

   It may be possible to parse sort blocks further.

AUTHOR
======

   Andrew Arensburger <arensb@ooblick.com>

SEE ALSO
========

   Palm::Raw(3)

   Palm::Address(3)

   Palm::Datebook(3)

   Palm::Mail(3)

   Palm::Memo(3)

   Palm::ToDo(3)

   `Palm Database Files', in the ColdSync distribution.

   The Virtual Constructor (aka Factory Method) pattern is described in
`Design Patterns', by Erich Gamma *et al.*, Addison-Wesley.

Perl extension for parsing PunchClock pdb files
***********************************************

NAME
====

   Palm::PunchClock - Perl extension for parsing PunchClock pdb files

SYNOPSIS
========

     use Palm::PDB
     use Palm::PunchClock;

     $pdb = new Palm::PDB;
     $pdb->Load("PC_Div-PClk.PDB");

DESCRIPTION
===========

   The Palm::PunchClock module does an attempt to parse PuchClock pdb
files. PunchClock is a timemanagement program for PalmOS written by Psync,
Inc.

BUGS
====

   Since this module was written in a few hours with no knowlegde of
PunchClocks internal format I have only guessed at the format, thus it
only parses the most vital data. Categories and such is ignored :-)

AUTHOR
======

   Peder Stray <pederst@cpan.org>

   PunchClock is written by Psync, Inc. http://www.psync.com/

SEE ALSO
========

   perl(1), Palm::PDB(3).

Handler for "raw" Palm databases.
*********************************

NAME
====

   Palm::Raw - Handler for "raw" Palm databases.

SYNOPSIS
========

     use Palm::Raw;

   For standalone programs.

     use Palm::Raw();
     @ISA = qw( Palm::Raw );

   For Palm::PDB helper modules.

DESCRIPTION
===========

   The Raw PDB handler is a helper class for the Palm::PDB package. It is
intended as a generic handler for any database, or as a fallback default
handler.

   If you have a standalone program and want it to be able to parse any
type of database, use

     use Palm::Raw;

   If you are using Palm::Raw as a parent class for your own database
handler, use

     use Palm::Raw();

   If you omit the parentheses, Palm::Raw will register itself as the
default handler for all databases, which is probably not what you want.

   The Raw handler does no processing on the database whatsoever. The
AppInfo block, sort block, records and resources are simply strings, raw
data from the database.

   By default, the Raw handler only handles record databases (.pdb files).
If you want it to handle resource databases (.prc files) as well, you need
to call

     &Palm::PDB::RegisterPRCHandlers("Palm::Raw", "");

   in your script.

AppInfo block
-------------

     $pdb->{appinfo}

   This is a scalar, the raw data of the AppInfo block.

Sort block
----------

     $pdb->{sort}

   This is a scalar, the raw data of the sort block.

Records
-------

     @{$pdb->{records}};

   Each element in the "records" array is a scalar, the raw data of that
record.

Resources
---------

     @{$pdb->{resources}};

   Each element in the "resources" array is a scalar, the raw data of that
resource.

AUTHOR
======

   Andrew Arensburger <arensb@ooblick.com>

SEE ALSO
========

   Palm::PDB(3)

Handles standard AppInfo block
******************************

NAME
====

   Palm::StdAppInfo - Handles standard AppInfo block

SYNOPSIS
========

     package MyPDBHandler;
     use Palm::StdAppInfo();

     @ISA = qw( Palm::StdAppInfo );

DESCRIPTION
===========

   Many Palm applications use a common format for keeping track of
categories.  The `Palm::StdAppInfo' class deals with this common format.

   A standard AppInfo block begins with:

     short	renamed;	// Bitmap of renamed category names
     char	labels[16][16];	// Array of category names
     char	uniqueIDs[16];	// Category IDs
     char	lastUniqueID;
     char	padding;	// For word alignment

FUNCTIONS
=========

seed_StdAppInfo
---------------

     &Palm::StdAppInfo::seed_StdAppInfo(\%appinfo);

   Creates the standard fields in an existing AppInfo hash.

newStdAppInfo
-------------

     $appinfo = Palm::StdAppInfo->newStdAppInfo;

   Like seed_StdAppInfo, but creates the AppInfo hash and returns it.

new
---

     $pdb = new Palm::StdAppInfo;

   Create a new PDB, initialized with nothing but a standard AppInfo block.

   There are very few reasons to use this, and even fewer good ones.

parse_StdAppInfo
----------------

     $len = &Palm::StdAppInfo::parse_StdAppInfo(\%appinfo, $data);

   This function is intended to be called from within a PDB helper class's
ParseAppInfoBlock method.

   `parse_StdAppInfo()' parses a standard AppInfo block from the raw data
$data and fills in the fields in `%appinfo'. It returns the number of
bytes parsed.

ParseAppInfoBlock
-----------------

     $pdb = new Palm::StdAppInfo;
     $pdb->ParseAppInfoBlock($data);

   If your application's AppInfo block contains standard category support
and nothing else, you may choose to just inherit this method instead of
writing your own ParseAppInfoBlock method.

pack_StdAppInfo
---------------

     $data = &Palm::StdAppInfo::pack_StdAppInfo(\%appinfo);

   This function is intended to be called from within a PDB helper class's
PackAppInfoBlock method.

   pack_StdAppInfo takes an AppInfo hash and packs it as a string of raw
data that can be written to a PDB.

PackAppInfoBlock
----------------

     $pdb = new Palm::StdAppInfo;
     $data = $pdb->PackAppInfoBlock();

   If your application's AppInfo block contains standard category support
and nothing else, you may choose to just inherit this method instead of
writing your own PackAppInfoBlock method.

AUTHOR
======

   Andrew Arensburger <arensb@ooblick.com>

SEE ALSO
========

   Palm::PDB(3)

Handler for Palm ToDo databases.
********************************

NAME
====

   Palm::ToDo - Handler for Palm ToDo databases.

SYNOPSIS
========

     use Palm::ToDo;

DESCRIPTION
===========

   The ToDo PDB handler is a helper class for the Palm::PDB package. It
parses ToDo databases.

AppInfo block
-------------

   The AppInfo block begins with standard category support. See
Palm/StdAppInfo, for details.

   Other fields include:

     $pdb->{appinfo}{dirty_appinfo}
     $pdb->{appinfo}{sortOrder}

   I don't know what these are.

Sort block
----------

     $pdb->{sort}

   This is a scalar, the raw data of the sort block.

Records
-------

     $record = $pdb->{records}[N]

     $record->{due_day}
     $record->{due_month}
     $record->{due_year}

   The due date of the ToDo item. If the item has no due date, these are
undefined.

     $record->{completed}

   This is defined and true iff the item has been completed.

     $record->{priority}

   An integer. The priority of the item.

     $record->{description}

   A text string. The description of the item.

     $record->{note}

   A text string. The note attached to the item. Undefined if the item has
no note.

new
---

     $pdb = new Palm::ToDo;

   Create a new PDB, initialized with the various Palm::ToDo fields and an
empty record list.

   Use this method if you're creating a ToDo PDB from scratch.

new_Record
----------

     $record = $pdb->new_Record;

   Creates a new ToDo record, with blank values for all of the fields.

AUTHOR
======

   Andrew Arensburger <arensb@ooblick.com>

SEE ALSO
========

   Palm::PDB(3)

   Palm::StdAppInfo(3)

A simple parallel processing fork manager
*****************************************

NAME
====

   Parallel::ForkManager - A simple parallel processing fork manager

SYNOPSIS
========

     use Parallel::ForkManager;

     $pm = new Parallel::ForkManager($MAX_PROCESSES);

     foreach $data (@all_data) {
       # Forks and returns the pid for the child:
       my $pid = $pm->start and next;

     ... do some work with $data in the child process ...

     $pm->finish; # Terminates the child process
       }

DESCRIPTION
===========

   This module is intended for use in operations that can be done in
parallel where the number of processes to be forked off should be limited.
Typical use is a downloader which will be retrieving hundreds/thousands of
files.

   The code for a downloader would look something like this:

     use LWP::Simple;
     use Parallel::ForkManager;

     ...

     @links=(
       ["http://www.foo.bar/rulez.data","rulez_data.txt"],
       ["http://new.host/more_data.doc","more_data.doc"],
       ...
     );

     ...

     # Max 30 processes for parallel download
     my $pm = new Parallel::ForkManager(30);

     foreach my $linkarray (@links) {
       $pm->start and next; # do the fork

     my ($link,$fn) = @$linkarray;
     warn "Cannot get $fn from $link"
       if getstore($link,$fn) != RC_OK;

     $pm->finish; # do the exit in the child process
       }
       $pm->wait_all_childs;

   First you need to instantiate the ForkManager with the "new"
constructor. You must specify the maximum number of processes to be
created. If you specify 0, then NO fork will be done; this is good for
debugging purposes.

   Next, use $pm->start to do the fork. $pm returns 0 for the child
process, and child pid for the parent process (see also `perlfunc(1p)' in
this node). The "and next" skips the internal loop in the parent process.
NOTE: $pm->start dies if the fork fails.

   $pm->finish terminates the child process (assuming a fork was done in
the "start").

   NOTE: You cannot use $pm->start if you are already in the child
process. If you want to manage another set of subprocesses in the child
process, you must instantiate another Parallel::ForkManager object!

METHODS
=======

new $processes
     Instantiate a new Parallel::ForkManager object. You must specify the
     maximum number of children to fork off. If you specify 0 (zero), then
     no children will be forked. This is intended for debugging purposes.

start
     This method does the fork. It returns the pid of the child process
     for the parent, and 0 for the child process. If the $processes
     parameter for the constructor is 0 then, assuming you're in the child
     process, $pm->start simply returns 0.

finish
     Closes the child process by exiting. If you use the program in debug
     mode ($processes == 0), this method doesn't do anything.

wait_all_childs
     You can call this method to wait for all the processes which has been
     forked. This is a blocking wait.

EXPERIMENTAL FEATURES
=====================

   There are callbacks in the code, which can be called on events like
starting a process or on finish. This code is not tested at all, hence the
lack of documentation. If you want to try these features, please look at
the code and test them. Feel free to send me patches if you find something
wrong.

COPYRIGHT
=========

   Copyright (c) 2000 Szabó, Balázs (dLux)

   All right reserved. This program is free software; you can redistribute
it and/or modify it under the same terms as Perl itself.

AUTHOR
======

   dLux (Szabó, Balázs) <dlux@kapu.hu>

   Noah Robin <sitz@onastick.net> (documentation tweaks)

Perl interface to the MPI message passing system
************************************************

NAME
====

   Parallel::MPI - Perl interface to the MPI message passing system

SYNOPSIS
========

     use Parallel::MPI;
     MPI_Init();
     . . .
     MPI_Finalize();

DESCRIPTION
===========

   The following is a summary of the available constants and functions:

Error Handling
==============

   If an MPI error occurs, set: $Parallel::MPI::errno
$Parallel::MPI::errstr

   $Parallel::MPI::exceptions: if set, toss an exception when an error
occurs.

Exported constants
==================

     Datatypes (not all are supported!)

     MPI_2COMPLEX
     MPI_2DOUBLE_COMPLEX
     MPI_2DOUBLE_PRECISION
     MPI_2INT
     MPI_2INTEGER
     MPI_2REAL
     MPI_COMPLEX
     MPI_DATATYPE_NULL
     MPI_DOUBLE
     MPI_DOUBLE_COMPLEX
     MPI_DOUBLE_INT
     MPI_DOUBLE_PRECISION
     MPI_FLOAT
     MPI_FLOAT_INT
     MPI_INT
     MPI_INTEGER
     MPI_BYTE
     MPI_CHAR
     MPI_CHARACTER
     MPI_LOGICAL
     MPI_LONG
     MPI_LONG_DOUBLE
     MPI_LONG_DOUBLE_INT
     MPI_LONG_INT
     MPI_LONG_LONG_INT
     MPI_REAL
     MPI_SHORT
     MPI_SHORT_INT
     MPI_UNSIGNED
     MPI_UNSIGNED_CHAR
     MPI_UNSIGNED_LONG
     MPI_UNSIGNED_SHORT

     New Datatypes

     MPI_STRING

     Status

     MPI_ANY_SOURCE
     MPI_ANY_TAG

     Operations

     MPI_BAND
     MPI_BOR
     MPI_BXOR
     MPI_LAND
     MPI_LOR
     MPI_LXOR
     MPI_MAX
     MPI_MAXLOC
     MPI_MIN
     MPI_MINLOC
     MPI_OP_NULL
     MPI_PROD
     MPI_SUM

     Communicators

     MPI_COMM_NULL
     MPI_COMM_SELF
     MPI_COMM_WORLD

     Communicator and Group Comparisons

     MPI_CONGRUENT
     MPI_IDENT
     MPI_SIMILAR
     MPI_UNEQUAL
     MPI_VERSION

Exported functions
==================

     MPI_Init()
     MPI_Finalize()
     MPI_Initialized()

     MPI_Comm_rank(communicator)
     MPI_Comm_size(communicator)

     MPI_Send(\$message, length, datatype, destination, tag, communicator)
     MPI_Recv(\$message, length, datatype, source, tag, communicator)
     MPI_Sendrecv(\$message, length, datatype, destination, tag, communicator)

     MPI_Barrier(comm)
     MPI_Bcast(\$from, count, datatype, root, communicator)

     MPI_Wtime()
     MPI_Wtick()

     MPI_Abort(communicator, errorcode)

     MPI_Reduce(\$from, \$to, count, datatype, operation, root, communicator)
     MPI_Allreduce(\$from, \$to, count, datatype, operation, communicator)
     MPI_Scatter(\$from, count, type, \$to, count, type, root, communicator)
     MPI_Gather(\$from, count, type, \$to, count, type, root, communicator)

AUTHORS
=======

   Josh Wilmes and Chris Stevens

SEE ALSO
========

   MPI man pages.  The paper, "Parallel::MPI - An MPI Binding for Perl",
included in the   Parallel::MPI distribution

Validate method/function parameters
***********************************

NAME
====

   Params::Validate - Validate method/function parameters

SYNOPSIS
========

     use Params::Validate qw(:all);

     # takes named params (hash or hashref)
     sub foo
     {
         validate( @_, { foo => 1, # mandatory
     		      bar => 0, # optional
     		    }
     	      );
     }

     # takes positional params
     sub bar
     {
         # first two are mandatory, third is optional
         validate_pos( @_, 1, 1, 0 );
     }

     sub foo2
     {
         validate( @_,
     		{ foo =>
     		  # specify a type
     		  { type => ARRAYREF },

     bar =>
     # specify an interface
     { can => [ 'print', 'flush', 'frobnicate' ] },

     baz =>
     { type => SCALAR,   # a scalar ...
       callbacks =>
         # ... that is a plain integer ...
       { 'numbers only' => sub { shift() =~ /^\d+$/ },
         # ... and smaller than 90
         'less than 90' => sub { shift() < 90 },
       },
     }
     		}
     	      );
       }

DESCRIPTION
===========

   The Params::Validate module allows you to validate method or function
call parameters to an arbitrary level of specificity.  At the simplest
level, it is capable of validating the required parameters were given and
that no unspecified additional parameters were passed in.

   It is also capable of determining that a parameter is of a specific
type, that it is an object of a certain class hierarchy, that it possesses
certain methods, or applying validation callbacks to arguments.

EXPORT
------

   The module always exports the validate and `validate_pos' methods.  In
addition, it can export the following constants, which are used as part of
the type checking.  These are SCALAR, `ARRAYREF', `HASHREF', CODEREF,
`GLOB', `GLOBREF', and `SCALARREF', `UNDEF', OBJECT, and `HANDLE'.  These
are explained in the section on `Type Validation|Params::Validate' in this
node.  These constants are available via the tag `:types'.  There is also a
:all tag, which for now is equivalent to the `:types' tag.

   Finally, it is possible to import the ``set_options' in this
node|"GLOBAL" OPTIONS' function, but only by requesting it explicitly, as
it is not included in :all.  The reason for this is that this function only
needs to be called once per module and its name is potentially common
enough that exporting it without an explicit request to do so seems bound
to cause trouble.

PARAMETER VALIDATION
====================

   The validation mechanisms provided by this module can handle both named
or positional parameters.  For the most part, the same features are
available for each.  The biggest difference is the way that the validation
specification is given to the relevant subroutine.  The other difference
is in the error messages produced when validation checks fail.

   When handling named parameters, the module is capable of handling
either a hash or a hash reference transparently.

   Subroutines expecting named parameters should call the validate
subroutine like this:

     validate( @_, { parameter1 => validation spec,
                     parameter2 => validation spec,
                     ...
                   } );

   Subroutines expected positional parameters should call the
`validate_pos' subroutine like this:

     validate_pos( @_, { validation spec }, { validation spec } );

Mandatory/Optional Parameters
-----------------------------

   If you just want to specify that some parameters are mandatory and
others are optional, this can be done very simply.

   For a subroutine expecting named parameters, you would do this:

     validate( @_, { foo => 1, bar => 1, baz => 0 } );

   This says that the foo and bar parameters are mandatory and that the
`baz' parameter is optional.  The presence of any other parameters will
cause an error.

   For a subroutine expecting positional parameters, you would do this:

     validate_pos( @_, 1, 1, 0, 0 );

   This says that you expect at least 2 and no more than 4 parameters.  If
you have a subroutine that has a minimum number of parameters but can take
any maximum number, you can do this:

     validate_pos( @_, 1, 1, (0) x @_ - 2 );

   This will always be valid as long as at least two parameters are given.
A similar construct could be used for the more complex validation
parameters described further on.

   Please note that this:

     validate_pos( @_, 1, 1, 0, 1, 1 );

   makes absolutely no sense, so don't do it.  Any zeros must come at the
end of the validation specification.

Type Validation
---------------

   This module supports the following simple types, which can be `exported
as constants|EXPORT' in this node:

   * SCALAR

     A scalar which is not a reference, such as 10 or `'hello''.  A
     parameter that is undefined is not treated as a scalar.  If you want
     to allow undefined values, you will have to specify `SCALAR | UNDEF'.

   * ARRAYREF

     An array reference such as `[1, 2, 3]' or `\@foo'.

   * HASHREF

     A hash reference such as `{ a =' 1, b => 2 }> or `\%bar'.

   * CODEREF

     A subroutine reference such as `\&foo_sub' or `sub { print "hello" }'.

   * GLOB

     This one is a bit tricky.  A glob would be something like `*FOO', but
     not `\*FOO', which is a glob reference.  It should be noted that this
     trick:

          my $fh = do { local *FH; };

     makes $fh a glob, not a glob reference.  On the other hand, the
     return value from `Symbol::gensym' is a glob reference.  Either can
     be used as a file or directory handle.

   * GLOBREF

     A glob reference such as `\*FOO'.  See the `GLOB|GLOB' in this node
     entry above for more details.

   * SCALARREF

     A reference to a scalar such as `\$x'.

   * UNDEF

     An undefined value

   * OBJECT

     A blessed reference.

   * HANDLE

     This option is special, in that it is just a shortcut for `GLOB |
     GLOBREF'.  However, it seems likely that most people interested in
     either globs or glob references are likely to really be interested in
     whether what is being in is a potentially valid file or directory
     handle.

   To specify that a parameter must be of a given type when using named
parameters, do this:

     validate( @_, { foo => { type => SCALAR },
                     bar => { type => HASHREF } } );

   If a parameter can be of more than one type, just use the bitwise or
(|) operator to combine them.

     validate( @_, { foo => { type => GLOB | GLOBREF } );

   For positional parameters, this can be specified as follows:

     validate_pos( @_, { type => SCALAR | ARRAYREF }, { type => CODEREF } );

Interface Validation
--------------------

   To specify that a parameter is expected to have a certain set of
methods, we can do the following:

     validate( @_,
               { foo =>
                 # just has to be able to ->bar
                 { can => 'bar' } } );

     ... or ...

     validate( @_,
               { foo =>
                 # must be able to ->bar and ->print
                 { can => [ qw( bar print ) ] } } );

Class Validation
----------------

   A word of warning.  When constructing your external interfaces, it is
probably better to specify what you methods you expect an object to have
rather than what class it should be of (or a child of).  This will make
your API much more flexible.

   With that said, if you want to verify that an incoming parameter
belongs to a class (or child class) or classes, do:

     validate( @_,
               { foo =>
                 { isa => 'My::Frobnicator' } } );

     ... or ...

     validate( @_,
               { foo =>
                 { isa => [ qw( My::Frobnicator IO::Handle ) ] } } );
     # must be both, not either!

Callback Validation
-------------------

   If none of the above are enough, it is possible to pass in one or more
callbacks to validate the parameter.  The callback will be given the value
of the parameter as its sole argument.  Callbacks are specified as hash
reference.  The key is an id for the callback (used in error messages) and
the value is a subroutine reference, such as:

     validate( @_,
               { foo =>
                 callbacks =>
                 { 'smaller than a breadbox' => sub { shift() < $breadbox },
                   'green or blue' =>
                    sub { my $val = shift; $val eq 'green' || $val eq 'blue' } } } );

   On a side note, I would highly recommend taking a look at Damian
Conway's Regexp::Common module, which could greatly simply the callbacks
you use, as it provides patterns useful for validating all sorts of data.

Mandatory/Optional Revisited
----------------------------

   If you want to specify something such as type or interface, plus the
fact that a parameter can be optional, do this:

     validate( @_, { foo =>
                     { type => SCALAR },
                     bar =>
                     { type => ARRAYREF, optional => 1 } } );

   or this for positional parameters:

     validate_pos( @_, { type => SCALAR }, { type => ARRAYREF, optional => 1 } );

   By default, parameters are assumed to be mandatory unless specified as
optional.

USAGE NOTES
===========

Method calls
------------

   When using this module to validate the parameters passed to a method
call, you will probably want to remove the class/object from the parameter
list before calling validate or `validate_pos'.  If your method expects
named parameters, then this is necessary for the validate function to
actually work, otherwise `@_' will not contain a hash, but rather your
object (or class) *followed* by a hash.

   Thus the idiomatic usage of validate in a method call will look
something like this:

     sub method
     {
         my $self = shift;
         validate( @_, { foo => 1, bar => { type => ARRAYREF } } );
         my %params = @_;
     }

"GLOBAL" OPTIONS
================

   Because the calling syntax for the validate and `validate_pos'
functions does not make it possible to specify any options other than the
the validation spec, it is possible to set some options as
pseudo-'globals'.  These allow you to specify such things as whether or
not the validation of named parameters should be case sensitive, for one
example.

   These options are called pseudo-'globals' because these settings are
*only applied to calls originating from the package that set the options*.

   In other words, if I am in package `Foo' and I call
`Params::Validate::set_options', those options are only in effect when I
call validate from package `Foo'.

   While this is quite different from how most other modules operate, I
feel that this is necessary in able to make it possible for one
module/application to use Params::Validate while still using other modules
that also use Params::Validate, perhaps with different options set;

   The downside to this is that if you are writing an app with a standard
calling style for all functions, and your app has ten modules, *each
module must include a call to `Params::Validate::set_options'*.

Options
-------

   * ignore_case => $boolean

     This is only relevant when dealing with named parameters.  If it is
     true, then the validation code will ignore the case of parameters.
     Defaults to false.

   * strip_leading => $characters

     This too is only relevant when dealing with named parameters.  If this
     is given then any parameters starting with these characters will be
     considered equivalent to parameters without them entirely.  For
     example, if this is specified as '-', then `-foo' and foo would be
     considered identical.

   * allow_extra => $boolean

     If true, then the validation routine will allow extra parameters not
     named in the validation specification.  In the case of positional
     parameters, this allows an unlimited number of maximum parameters
     (though a minimum may still be set).  Defaults to false.

   * on_fail => $callback

     If given, this callback will be called whenever a validation check
     fails.  It will be called with a single parameter, which will be a
     string describing the failure.  This is useful if you wish to have
     this module throw exceptions as objects rather than as strings, for
     example.

     This callback is expected to die internally.  If it does not, the
     validation will proceed onwards, with unpredictable results.

     The default is to simply use Perl's builtin die function.

DISABLING VALIDATION
====================

   ** This functionality may change in the future **

   If the environment variable `NO_VALIDATION' is set to something true,
then all calls to the validation functions are turned into no-ops.  This
may be useful if you only want to use this module during development but
don't want the speed hit during production.

   I am not terribly happy with the current mechanism for doing this so
this may change in the future.

LIMITATIONS
===========

   Right now there is no way (short of a callback) to specify that
something must be of one of a list of classes, or that it must possess one
of a list of methods.  If this is desired, it can be added in the future.

   Ideally, there would be only one validation function.  If someone
figures out how to do this, please let me know.

SEE ALSO
========

   Carp::Assert and Class::Contract.

AUTHOR
======

   Dave Rolsky, <autarch@urth.org>

Generator of lexical analyzers
******************************

NAME
====

   `Parse::CLex' - Generator of lexical analyzers

SYNOPSIS
========

   See the `Parse::Lex' documentation.

DESCRIPTION
===========

   See the `Parse::Lex' documentation.

AUTHOR
======

   Philippe Verdret.

COPYRIGHT
=========

   Copyright (c) 1999 Philippe Verdret. All rights reserved.  This module
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SYNOPSIS
========

     use Parse::FixedLength;

     $phone_number=8037814191;
     parse($phone_number,
     	     \%moms_phone,
     	     [
     	       {'area_code' => 3},
     	       {'exchange'  => 3},
     	       {'number'    => 4} ] );

     for (keys %moms_phone) {
       print $_, " ", $moms_phone{$_}, $/;
     }

     # yields $moms_phone{area_code} == 803
     #        $moms_phone{exchange}  == 781
     #        $moms_phone{number}    == 4191

     =cut

DESCRIPTION
===========

   The `Parse::FixedLength' module facilitates the process of breaking a
string into its fixed-length components.

PARSING ROUTINES
================

parse()
          parse($string_to_parse, $href_storing_parse, $LOH_parse_instructions)

     This function takes a string, a reference to a hash and a reference
     to a list of hashes and stores the results of fixed length parsing
     into the hash reference passed in.

quick_parse()
     To facilitate the parsing of certain common fixed-length strings, the
     quick_parse() function takes the name of an LOH (list of hashes)
     containing formatting information, a string, and a reference to a hah
     in which to store parsing results. The currently available formatting
     routines are:

`@us_phone'
          $phone_number=8882221234;
          Parse::FixedLength::quick_parse("us_phone",$phone_number, \%lncs_phone);

`@us_ssan'

`@MM_DD_YYYY'

`@MM_DD_YY'

`@YY_MM_DD'

`@YYYY_MM_DD'
print_parsed()
     This routine can be called after parsing to print a record of parse
     results.

EXAMPLES
========

   see SYNOPSIS

AUTHOR
======

   Terrence Brannon <tbone@cpan.org>

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Generator of lexical analyzers
******************************

NAME
====

   `Parse::Lex'  - Generator of lexical analyzers

SYNOPSIS
========

     require 5.005;

     use Parse::Lex;
     @token = (
       qw(
          ADDOP    [-+]
          LEFTP    [\(]
          RIGHTP   [\)]
          INTEGER  [1-9][0-9]*
          NEWLINE  \n

         ),
       qw(STRING),   [qw(" (?:[^"]+|"")* ")],
       qw(ERROR  .*), sub {
         die qq!can\'t analyze: "$_[1]"!;
       }
      );

     Parse::Lex->trace;  # Class method
     $lexer = Parse::Lex->new(@token);
     $lexer->from(\*DATA);
     print "Tokenization of DATA:\n";

     TOKEN:while (1) {
       $token = $lexer->next;
       if (not $lexer->eoi) {
         print "Line $.\t";
         print "Type: ", $token->name, "\t";
         print "Content:->", $token->text, "<-\n";
       } else {
         last TOKEN;
       }
     }

     __END__
     1+2-5
     "a multiline
     string with an embedded "" in it"
     an invalid string with a "" in it"

DESCRIPTION
===========

   The classes `Parse::Lex' and `Parse::CLex' create lexical analyzers.
They use different analysis techniques:

   1.  `Parse::Lex' steps through the analysis by moving a pointer within
the character strings to be analyzed (use of `pos()' together with `\G'),

   2.  `Parse::CLex' steps through the analysis by consuming the data
recognized (use of s///).

   Analyzers of the `Parse::CLex' class do not allow the use of anchoring
in regular expressions.  In addition, the subclasses of `Parse::Token' are
not implemented for this type of analyzer.

   A lexical analyzer is specified by means of a list of tokens passed as
arguments to the new() method. Tokens are instances of the `Parse::Token'
class, which comes with `Parse::Lex'. The definition of a token usually
comprises two arguments: a symbolic name (like INTEGER), followed by a
regular expression. If a sub ref (anonymous subroutine) is given as third
argument, it is called when the token is recognized.  Its arguments are
the `Parse::Token' instance and the string recognized by the regular
expression.  The anonymous subroutine's return value is used as the new
string contents of the `Parse::Token' instance.

   The order in which the lexical analyzer examines the regular
expressions is determined by the order in which these expressions are
passed as arguments to the new() method. The token returned by the lexical
analyzer corresponds to the first regular expression which matches (this
strategy is different from that used by Lex, which returns the longest
match possible out of all that can be recognized).

   The lexical analyzer can recognize tokens which span multiple records.
If the definition of the token comprises more than one regular expression
(placed within a reference to an anonymous array), the analyzer reads as
many records as required to recognize the token (see the documentation for
the `Parse::Token' class).  When the start pattern is found, the analyzer
looks for the end, and if necessary, reads more records.  No backtracking
is done in case of failure.

   The analyzer can be used to analyze an isolated character string or a
stream of data coming from a file handle. At the end of the input data the
analyzer returns a `Parse::Token' instance named `EOI' (End Of Input).

Start Conditions
----------------

   You can associate start conditions with the token-recognition rules
that comprise your lexical analyzer (this is similar to what Flex
provides).  When start conditions are used, the rule which succeeds is no
longer necessarily the first rule that matches.

   A token symbol may be preceded by a start condition specifier for the
associated recognition rule. For example:

     qw(C1:TERMINAL_1  REGEXP), sub { # associated action },
     qw(TERMINAL_2  REGEXP), sub { # associated action },

   Symbol `TERMINAL_1' will be recognized only if start condition `C1' is
active.  Start conditions are activated/deactivated using the
`start(CONDITION_NAME)' and `end(CONDITION_NAME)' methods.

   `start('INITIAL')' resets the analysis automaton.

   Start conditions can be combined using AND/OR operators as follows:

     C1:SYMBOL      condition C1

     C1:C2:SYMBOL   condition C1 AND condition C2

     C1,C2:SYMBOL   condition C1 OR  condition C2

   There are two types of start conditions: inclusive and exclusive, which
are declared by class methods `inclusive()' and `exclusive()'
respectively.  With an inclusive start condition, all rules are active
regardless of whether or not they are qualified with the start condition.
With an exclusive start condition, only the rules qualified with the start
condition are active; all other rules are deactivated.

   Example (borrowed from the documentation of Flex):

     use Parse::Lex;
     @token = (
              'EXPECT', 'expect-floats', sub {
                $lexer->start('expect');
                $_[1]
              },
              'expect:FLOAT', '\d+\.\d+', sub {
                print "found a float: $_[1]\n";
                $_[1]
              },
              'expect:NEWLINE', '\n', sub {
                $lexer->end('expect') ;
                $_[1]
              },
              'NEWLINE2', '\n',
              'INT', '\d+', sub {
                print "found an integer: $_[1] \n";
                $_[1]
              },
              'DOT', '\.', sub {
                print "found a dot\n";
                $_[1]
              },
             );

     Parse::Lex->exclusive('expect');
     $lexer = Parse::Lex->new(@token);

   The special start condition ALL is always verified.

Methods
-------

analyze EXPR
     Analyzes EXPR and returns a list of pairs consisting of a token name
     followed by recognized text. EXPR can be a character string or a
     reference to a filehandle.

     Examples:

          @tokens = Parse::Lex->new(qw(PLUS [+] NUMBER \d+))->analyze("3+3+3");
          @tokens = Parse::Lex->new(qw(PLUS [+] NUMBER \d+))->analyze(\*STREAM);

buffer EXPR
buffer
     Returns the contents of the internal buffer of the lexical analyzer.
     With an expression as argument, places the result of the expression in
     the buffer.

     It is not advisable to directly change the contents of the buffer
     without changing the position of the analysis pointer (`pos()') and
     the value length of the buffer (length()).

configure(HASH)
     Instance method which permits specifying a lexical analyzer.  This
     method accepts the list of the following attribute values:

    From => EXPR
          This attribute plays the same role as the `from(EXPR)' method.
          EXPR can be a filehandle or a character string.

    Tokens => ARRAY_REF
          `ARRAY_REF' must contain the list of attribute values specifying
          the tokens to be recognized (see the documentation for
          `Parse::Token').

    Skip => REGEX
          This attribute plays the same role as the `skip(REGEX)' method.
          `REGEX' describes the patterns to skip over during the analysis.

         end EXPR
               Deactivates condition EXPR.

         eoi
               Returns TRUE when there is no more data to analyze.

         every SUB
               Avoids having to write a reading loop in order to analyze a
               stream of data. SUB is an anonymous subroutine executed
               after the recognition of each token. For example, to lex
               the string "1+2" you can write:

                    use Parse::Lex;

                    $lexer = Parse::Lex->new(
                      qw(
                         ADDOP [-+]
                         INTEGER \d+
                        ));

                    $lexer->from("1+2");
                    $lexer->every (sub {
                      print $_[0]->name, "\t";
                      print $_[0]->text, "\n";
                    });

               The first argument of the anonymous subroutine is the
               `Parse::Token' instance recognized.

         exclusive LIST
               Class method declaring the conditions present in LIST to be
               exclusive.

         flush
               If saving of the consumed strings is activated, flush()
               returns and clears the buffer containing the character
               strings recognized up to now.  This is only useful if
               `hold()' has been called to activate saving of consumed
               strings.

         from EXPR
         from
               `from(EXPR)' allows specifying the source of the data to be
               analyzed. The argument of this method can be a string (or
               list of strings), or a reference to a filehandle.  If no
               argument is given, `from()' returns the filehandle if
               defined, or undef if input is a string.  When an argument
               EXPR is used, the return value is the calling lexer object
               itself.

               By default it is assumed that data are read from STDIN.

               Examples:

                    $handle = new IO::File;
                    $handle->open("< filename");
                    $lexer->from($handle);

                    $lexer->from(\*DATA);
                    $lexer->from('the data to be analyzed');

         getSub
               getSub returns the anonymous subroutine that performs the
               lexical analysis.

               Example:

                    my $token = '';
                    my $sub = $lexer->getSub;
                    while (($token = &$sub()) ne $Token::EOI) {
                      print $token->name, "\t";
                      print $token->text, "\n";
                    }

                       # or

                    my $token = '';
                    local *tokenizer = $lexer->getSub;
                    while (($token = tokenizer()) ne $Token::EOI) {
                      print $token->name, "\t";
                      print $token->text, "\n";
                    }

         getToken
               Same as `token()' method.

         hold EXPR
         hold
               Activates/deactivates saving of the consumed strings.  The
               return value is the current setting (TRUE or FALSE).  Can
               be used as a class method.

               You can obtain the contents of the buffer using the flush
               method, which also empties the buffer.

         inclusive LIST
               Class method declaring the conditions present in LIST to be
               inclusive.

         length EXPR
         length
               Returns the length of the current record.  `length EXPR'
               sets the length of the current record.

         line EXPR
         line
               Returns the line number of the current record.  `line EXPR'
               sets the value of the line number.  Always returns 1 if a
               character string is being analyzed.  The readline() method
               increments the line number.

         name EXPR
         name
               `name EXPR' lets you give a name to the lexical analyzer.
               name() return the value of this name.

         next
               Causes searching for the next token. Return the recognized
               `Parse::Token' instance. Returns the `Token::EOI' instance
               at the end of the data.

               Examples:

                    $lexer = Parse::Lex->new(@token);
                    print $lexer->next->name;   # print the token type
                    print $lexer->next->text;   # print the token content

         nextis SCALAR_REF
               Variant of the next() method. Tokens are placed in
               `SCALAR_REF'. The method returns 1 as long as the token is
               not `EOI'.

               Example:

                    while($lexer->nextis(\$token)) {
                       print $token->text();
                    }

         new LIST
               Creates and returns a new lexical analyzer. The argument of
               the method is a list of `Parse::Token' instances, or a list
               of triplets permitting their creation.  The triplets
               consist of: the symbolic name of the token, the regular
               expression necessary for its recognition, and possibly an
               anonymous subroutine that is called when the token is
               recognized. For each triplet, an instance of type
               `Parse::Token' is created in the calling package.

         offset
               Returns the number of characters already consumed since the
               beginning of the analyzed data stream.

         pos EXPR
         pos
               `pos EXPR' sets the position of the beginning of the next
               token to be recognized in the current line (this doesn't
               work with analyzers of the `Parse::CLex' class).  `pos()'
               returns the number of characters already consumed in the
               current line.

         readline
               Reads data from the input specified by the `from()' method.
               Returns the result of the reading.

               Example:

                    use Parse::Lex;

                    $lexer = Parse::Lex->new();
                    while (not $lexer->eoi) {
                      print $lexer->readline() # read and print one line
                    }

         reset
               Clears the internal buffer of the lexical analyzer and
               erases all tokens already recognized.

         restart
               Reinitializes the analysis automaton. The only active
               condition becomes the condition `INITIAL'.

         setToken TOKEN
               Sets the token to `TOKEN'. Useful to requalify a token
               inside the anonymous subroutine associated with this token.

         skip EXPR
         skip
               EXPR is a regular expression defining the token separator
               pattern (by default `[ \t]+'). `skip('')' sets this to no
               pattern.  With no argument, `skip()' returns the value of
               the pattern.  `skip()' can be used as a class method.

               Changing the skip pattern causes recompilation of the
               lexical analyzer.

               Example:

                    Parse::Lex->skip('\s*#(?s:.*)|\s+');
                    @tokens = Parse::Lex->new('INTEGER' => '\d+')->analyze(\*DATA);
                    print "@tokens\n"; # print INTEGER 1 INTEGER 2 INTEGER 3 INTEGER 4 EOI
                    __END__
                    1 # first string to skip
                    2
                    3# second string to skip
                    4

         start EXPR
               Activates condition EXPR.

         state EXPR
               Returns the state of the condition represented by EXPR.

         token
               Returns the instance corresponding to the last recognized
               token. In case no token was recognized, return the special
               token named DEFAULT.

         tokenClass EXPR
         tokenClass
               Indicates which is the class of the tokens to be created
               from the list passed as argument to the new() method.  If
               no argument is given, returns the name of the class.  By
               default the class is `Parse::Token'.

         trace OUTPUT
         trace
               Class method which activates trace mode. The activation of
               trace mode must take place before the creation of the
               lexical analyzer. The mode can then be deactivated by
               another call of this method.

               OUTPUT can be a file name or a reference to a filehandle
               where the trace will be redirected.

ERROR HANDLING
==============

   To handle the cases of token non-recognition, you can define a specific
token at the end of the list of tokens that comprise our lexical analyzer.
If searching for this token succeeds, it is then possible to call an
error handling function:

     qw(ERROR  (?s:.*)), sub {
       print STDERR "ERROR: buffer content->", $_[0]->lexer->buffer, "<-\n";
       die qq!can\'t analyze: "$_[1]"!;
     }

EXAMPLES
========

   ctokenizer.pl - Scan a stream of data using the `Parse::CLex' class.

   tokenizer.pl - Scan a stream of data using the `Parse::Lex' class.

   every.pl - Use of the every method.

   sexp.pl - Interpreter for prefix arithmetic expressions.

   sexpcond.pl - Interpeter for prefix arithmetic expressions, using
conditions.

BUGS
====

   Analyzers of the `Parse::CLex' class do not allow the use of regular
expressions with anchoring.

SEE ALSO
========

   `Parse::Token', `Parse::LexEvent', `Parse::YYLex'.

AUTHOR
======

   Philippe Verdret. Documentation translated to English by Vladimir
Alexiev and Ocrat.

ACKNOWLEDGMENTS
===============

   Version 2.0 owes much to suggestions made by Vladimir Alexiev.  Ocrat
has significantly contributed to improving this documentation.  Thanks
also to the numerous people who have sent me bug reports and occasionally
fixes.

REFERENCES
==========

   Friedl, J.E.F. Mastering Regular Expressions. O'Reilly & Associates
1996.

   Mason, T. & Brown, D. - Lex & Yacc. O'Reilly & Associates, Inc. 1990.

   FLEX - A Scanner generator (available at ftp://ftp.ee.lbl.gov/ and
elsewhere)

COPYRIGHT
=========

   Copyright (c) 1995-1999 Philippe Verdret. All rights reserved.  This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Generator of event-oriented lexical analyzers (1.00 ALPHA)
**********************************************************

NAME
====

   `Parse::LexEvent' - Generator of event-oriented lexical analyzers (1.00
ALPHA)

SYNOPSIS
========

     use Parse::LexEvent;

     sub string {
       print $_[0]->name, ": $_[1]\n";
     }
     sub comment {
       print $_[0]->name, ": $_[1]\n";
     }
     sub remainder {
       print $_[0]->name, ": $_[1]\n";
     }

     $lexer = Parse::LexEvent->new()->configure(
          From => \*DATA,
          Tokens =>
            [
             Type => 'Simple', Name => 'ccomment', Handler => 'comment',
                  Regex => '//.*\n',
             Type => 'Delimited', Name => 'comment', Handler => 'comment',
                  Start => '/[*]', End => '[*]/',
             Type => 'Quoted', Name => 'squotes', Handler => 'string', Quote => qq!\'!,
             Type => 'Quoted', Name => 'dquotes', Handler => 'string', Quote => qq!\"!,
             Type => 'Simple', Name => 'remainder',
                  Regex => '(?s:[^/\'\"]+)', ReadMore => 1,
            ]
         )->parse();
     __END__
     /*
       C comment
     */
     // C++ comment
     var d = "string in double quotes";
     var s = 'string in single quotes';
     var i = 10;
     var y = 100;

DESCRIPTION
===========

   `Parse::LexEvent' generates lexical analyzers in the fashion of
`Parse::Lex', but the generated analyzers emit an event at the finish of
recognition of each token.  This event corresponds to the call of a
procedure whose name is that of the token.  It is possible to give a
different name to this procedure by making use of the Handler parameter
when defining a token.

   An application using `Parse::LexEvent' must define the required
procedures.  These procedures take the token object as first argument and
the recognized character string as the second.

   `Parse::LexEvent' inherits from `Parse::ALex' and possesses all the
methods described in the documentation of the `Parse::Lex' class, except
for the methods `analyze()', `every()' next(), and `nextis()'.

Methods
-------

parse()
     This method runs the analysis of data specified by `from()'.

EXAMPLES
========

   cparser.pl - This analyzer recognizes three types of structures: C ou
C++ comments, strings within quotation marks, and the rest.  It emits an
event specific to each.  You can use it, for example, to analyze C, C++ or
Javascript programs.

SEE ALSO
========

   `Parse::Lex', `Parse::Token'.

AUTHOR
======

   Philippe Verdret.

COPYRIGHT
=========

   Copyright (c) 1999 Philippe Verdret. All rights reserved.  This module
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

parse a configuration file written in Perl
******************************************

NAME
====

   Parse::PerlConfig - parse a configuration file written in Perl

SYNOPSIS
========

     use Parse::PerlConfig;
     my $parsed = Parse::PerlConfig::parse(
         File            =>      "/etc/perlapp/conf",
         Handlers        =>      [\%config, \&config],
     );

DESCRIPTION
===========

   This module is useful for parsing a configuration file written in Perl
and obtaining the values defined therein.  This is achieved through the
parse() function, which creates a namespace, reads in Perl code, evals it,
and then examines the namespace's symbol table.  Symbols are then
processed into a hash and returned.

Export
------

   The parse() function is exportable upon request.

Parsing
-------

   Parsing is not a simple do("filename").  Instead the filenames
specified are opened, read, eval'd, and closed.  The justification for
this being twofold:

no @INC search
     I did not want surprises in what file was found; do("file") searches
     @INC.

lexicals
     I wanted to be able to insert lexicals for the code in the file to
     see.  Being able to define variables without having them parsed back
     out (remember, the namespace is searched) is a nice feature.

   Parsing (in this manner) requires a namespace.  By default, the
namespace is constructed by appending Namespace_Base to a unique
identifier (currently, an encoded version of the filename, but don't rely
on this).  You can override this behaviour by specifying an explicit
Namespace argument.

   Prior to eval'ing the contents of a configuration file the lexical hash
%parse_perl_config is initialized with several keys (documented below); if
a Lexicals argument was given each of the lexicals specified are
initialized.

   There are a few caveats; lexicals specified in the Lexicals argument
cannot override %parse_perl_config; keys specified in Lexicals cannot be
code references, because code references cannot currently be reliably
reconstructed; modifications to %parse_perl_config keys (other than Error,
documented below) are discouraged, as the results are not defined.

   The %parse_perl_config hash contains the following keys:

Error
     Making this key a true value will cause the error handler Error_eval
     to be called with the value.

Namespace
     The namespace the file is being evaluated in.

Filename
     The name of the file being parsed.

Parse_Args
     A hash of the arguments passed to parse().

   Once the namespace has been setup, and the code eval'd, it is then
parse()'s job to go through the namespace's symbol table and look for
"things".  What it looks for depends on the Thing_Order and Symbols
arguments.

   After that, handlers are updated, and a hash reference of what was
parsed out is returned.

The parse subroutine
====================

Arguments
---------

   parse() takes a list of key-value pairs as its arguments and adds them
to an argument hash.  If the first argument to parse() is a hash or array
reference, it is dereferenced and used as if it were specified as a list.
All elements following this argument are added to the arguments hash, and
they override any settings specified by the reference.

   This means the call:

     parse(
         { Files => "/home/me/config.conf", Error_default => 'fwarn' },
         Files => "/home/you/config.conf"
     );

   causes parse()'s argument hash to consist of the following (ignoring
default settings):

     Files           =>  "/home/you/config.conf",
     Error_default   =>  "fwarn",

   Simply replace the braces, {}, with brackets, [], and you get the same
result.  This makes it convenient to store commonly-used arguments to
parse() in a hash or array, and efficiently pass these arguments to
parse(), while still allowing a seperate Files argument for each call.

   The below itemization of parse()'s arguments describes key-value pairs.
Each item consists of a key name and a description of the expected value
for that key.

   The value description requires some explanation.

   A single pipe, "|", indicates alternative values; only one of the values
must be specified.

   Values bracketed with "<" and ">" indicate that value is not literal,
but figurative.  So, in the case of <coderef>, you must specify a code
reference (a closure or reference to a named subroutine), not the literal
string "<coderef>".  Values without such bracketing are literal.

   Braces, {}, indicate a hash reference is required; brackets, [],
indicate an array reference is required.

   Below each key-value description is a description of the default
setting, followed by a description of what the argument means.

Files <filename> | [<filename> ...]
          default: none, this argument is required

     This is the file or files you wish to parse.  If a file cannot be
     parsed for any reason the entire parse is not abandoned, the file is
     simply skipped (after calling an appropriate error handling function).

File <filename>
     Equivalent to Files <filename>.

Handlers <hashref>|<coderef> | [<hashref>|<coderef> ...]
          default: none

     By default, parse() simply returns a hash reference of symbol names
     and their values.  Given a Handlers argument, parse() will add
     key-value pairs to each hash reference specified, and call each code
     reference specified with a single argument, the hash reference it
     returns.

Handler <hashref>|<coderef>
     Equivalent to Handlers <hashref>|<coderef>.

Lexicals <hashref>
          default: none

     The key-value pairs in the specified hashref are made into lexical
     variables in the configuration eval.  See the section on Parsing for
     further information.

Thing_Order <string>|<arrayref>
          default: '$@%&i*'

     Specifies the default thing order for symbols parsed from each
     configuration file.  See the section Things for further information.

Taint_Clean <boolean>
          default: false

     If set to any true value the filehandle opened on the configuration
     file is untainted before evaling the code contained therein.  Because
     this involves loading IO::Handle, which involves quite a bit of code,
     the option is turned off by default.  You *will* get taint exceptions
     if you don't specify this option while running in -T mode.

     Also, as the namespace is currently constructed, having a tainted
     filename will cause the namespace name to be tainted, so it is also
     untainted.  In the case of an explicitly specified Namespace value,
     it will also be untainted.

     No other values are untainted.  This includes any key-value pairs
     specified by the Lexicals argument; you must untaint those yourself,
     since there is no reasonable way for parse() to determine how best to
     untaint them.

Symbols <hashref>
          default: empty hashref

     This is an override for the Thing_Order argument above.  The keys in
     the specified hashref are symbols you want parsed specially, the
     values the thing order (either a string or array reference).  See the
     section Things for further information regarding thing order.

Namespace <string>
          default: generated from Namespace_Base and a unique identifier

     This option explicitly specifies the namespace the files are parsed
     in.  See the section Parsing for further information.

Namespace_Base <string>
          default: Parse::PerlConfig::ConfigFile

     Unless the Namespace argument is specified, the namespace a file is
     parsed in is generated by appending a cleaned up version of the
     filename to this setting.  See the section Parsing for further
     information.

     See the section Error Handling for further information.

Things
------

   "Things" (as taken from the Perl documentation, regarding the
*foo{THING} syntax) are the Perl datatypes.  These include scalars,
arrays, hashes, subroutines, IO handles, and globs.

   Anywhere a "things" argument is required you can specify one of two
things; a string containing the special "thing" characters, or an array
reference of each thing's actual name.  The thing characters are as
follows: `$' for scalar, % for a hash, `@' for an array, & for a
subroutine, i for an IO handle, and * for a glob.  The full name for each
coincides with the full name for each datatype in their respective glob
slots: SCALAR for a scalar, HASH for a hash, ARRAY for an array, CODE for
a subroutine, IO for an IO handle, and GLOB for a glob.

Exception Handling
------------------

   parse() takes various Error_* and Warn_* arguments that determine how it
handles any problems it encounters.  Each argument can take one of several
values.

default
     The error handling specifed by Error_default in the case of an Error_*
     argument, or Warn_default in the case of a Warn_* argument, is used.

noop
     The error is ignored.

warn
     Results in a call to CORE::warn() with a trailing newline, but only if
     $^W is set to a true value.

fwarn
     Like warn, but the warning is raised regardless of $^W's value.

die
     Results in a call to CORE::die() with a trailing newline.

<code reference>
     The code reference will be called with a single argument, that of the
     error message.  The error message is guaranteed to contain no
     trailing newlines (in case the code reference decides to die() or
     warn()).

   There are various handler arguments.  Unless otherwise specified, the
default handler is used (Error_default's or Warn_default's value).

Warn_default
          default: noop

     The default warning handler.

Warn_preparse
     Called just before a file is parsed to indicate parsing is about to
     begin.

Warn_eval
     Called with any warnings issued by the eval'd file.

Error_default
          default: warn

     The default error handler.

Error_argument
     Called if there is a problem with one of the arguments specified.

Error_file_is_dir
     Called if a configuration file specified was discovered to be a
     directory.

Error_failed_open
     Called if the open attempt on a configuration file fails.

Error_eval
     Called if the variable $parse_perl_config{Error} is set in the
     configuration file, or if there was an eval error.

Error_unknown_thing
     Called if there is a problem with a thing character or thing name in
     a thing argument (thing thing thing).

Error_unknown_handler
     Called if an unknown reference is encountered in the Handlers
     argument.

Error_invalid_lexical
     Called if an invalid lexical name or a CODE reference value is
     encountered in the Lexicals argument.

Error_invalid_namespace
     Called if either the constructed namespace (using Namespace_Base) or a
     specified Namespace value is invalid.  This may indicate an error in
     the construction of a namespace name (the generation of a unique
     identifier), but it's most likely you specified Namespace_Base or
     Namespace with invalid characters.

BUGS
====

   Due to the fact that the scalar slot in a glob is always filled it is
not possible to distinguish from a scalar that was never defined (e.g.
`@foo' was, but `$foo' was never mentioned) from one that is simply undef.
Because of this, for example, if you have a thing order of `$@' and code
along the lines of `$foo = undef; @foo = ();' the 'foo' key of the hash
will be an array reference, despite there being a scalar and `$' coming
first in the thing order.

TODO
====

   t/parse/symbols.t, t/parse/multi-file.t, t/parse/namespace.t

AUTHOR
======

   Michael Fowler <michael@shoebox.net>

Generate Recursive-Descent Parsers
**********************************

NAME
====

   Parse::RecDescent - Generate Recursive-Descent Parsers

VERSION
=======

   This document describes version 1.80 of Parse::RecDescent, released
January 20, 2001.

SYNOPSIS
========

     use Parse::RecDescent;

     # Generate a parser from the specification in $grammar:

     $parser = new Parse::RecDescent ($grammar);

     # Generate a parser from the specification in $othergrammar

     $anotherparser = new Parse::RecDescent ($othergrammar);

     # Parse $text using rule 'startrule' (which must be
     # defined in $grammar):

     $parser->startrule($text);

     # Parse $text using rule 'otherrule' (which must also
     # be defined in $grammar):

     $parser->otherrule($text);

     # Change the universal token prefix pattern
     # (the default is: '\s*'):

     $Parse::RecDescent::skip = '[ \t]+';

     # Replace productions of existing rules (or create new ones)
     # with the productions defined in $newgrammar:

     $parser->Replace($newgrammar);

     # Extend existing rules (or create new ones)
     # by adding extra productions defined in $moregrammar:

     $parser->Extend($moregrammar);

     # Global flags (useful as command line arguments under -s):

     $::RD_ERRORS	   # unless undefined, report fatal errors
     $::RD_WARN	   # unless undefined, also report non-fatal problems
     $::RD_HINT	   # if defined, also suggestion remedies
     $::RD_TRACE	   # if defined, also trace parsers' behaviour
     $::RD_AUTOSTUB	   # if defined, generates "stubs" for undefined rules
     $::RD_AUTOACTION   # if defined, appends specified action to productions

DESCRIPTION
===========

Overview
--------

   Parse::RecDescent incrementally generates top-down recursive-descent
text parsers from simple *yacc*-like grammar specifications. It provides:

   * Regular expressions or literal strings as terminals (tokens),

   * Multiple (non-contiguous) productions for any rule,

   * Repeated and optional subrules within productions,

   * Full access to Perl within actions specified as part of the grammar,

   * Simple automated error reporting during parser generation and parsing,

   * The ability to commit to, uncommit to, or reject particular
     productions during a parse,

   * The ability to pass data up and down the parse tree ("down" via
     subrule argument lists, "up" via subrule return values)

   * Incremental extension of the parsing grammar (even during a parse),

   * Precompilation of parser objects,

   * User-definable reduce-reduce conflict resolution via "scoring" of
     matching productions.

Using Parse::RecDescent
-----------------------

   Parser objects are created by calling `Parse::RecDescent::new', passing
in a grammar specification (see the following subsections). If the grammar
is correct, new returns a blessed reference which can then be used to
initiate parsing through any rule specified in the original grammar. A
typical sequence looks like this:

     $grammar = q {
     		# GRAMMAR SPECIFICATION HERE
     	     };

     $parser = new Parse::RecDescent ($grammar) or die "Bad grammar!\n";

     # acquire $text

     defined $parser->startrule($text) or print "Bad text!\n";

   The rule through which parsing is initiated must be explicitly defined
in the grammar (i.e. for the above example, the grammar must include a
rule of the form: "startrule: <subrules>".

   If the starting rule succeeds, its value (see below) is returned.
Failure to generate the original parser or failure to match a text is
indicated by returning undef. Note that it's easy to set up grammars that
can succeed, but which return a value of 0, "0", or "".  So don't be
tempted to write:

     $parser->startrule($text) or print "Bad text!\n";

   Normally, the parser has no effect on the original text. So in the
previous example the value of $text would be unchanged after having been
parsed.

   If, however, the text to be matched is passed by reference:

     $parser->startrule(\$text)

   then any text which was consumed during the match will be removed from
the start of $text.

Rules
-----

   In the grammar from which the parser is built, rules are specified by
giving an identifier (which must satisfy /[A-Za-z]\w*/), followed by a
colon *on the same line*, followed by one or more productions, separated
by single vertical bars. The layout of the productions is entirely
free-format:

     rule1:	production1
          |  production2 |
     	production3 | production4

   At any point in the grammar previously defined rules may be extended
with additional productions. This is achieved by redeclaring the rule with
the new productions. Thus:

     rule1: a | b | c
     rule2: d | e | f
     rule1: g | h

   is exactly equivalent to:

     rule1: a | b | c | g | h
     rule2: d | e | f

   Each production in a rule consists of zero or more items, each of which
may be either: the name of another rule to be matched (a "subrule"), a
pattern or string literal to be matched directly (a "token"), a block of
Perl code to be executed (an "action"), a special instruction to the
parser (a "directive"), or a standard Perl comment (which is ignored).

   A rule matches a text if one of its productions matches. A production
matches if each of its items match consecutive substrings of the text. The
productions of a rule being matched are tried in the same order that they
appear in the original grammar, and the first matching production
terminates the match attempt (successfully). If all productions are tried
and none matches, the match attempt fails.

   Note that this behaviour is quite different from the "prefer the longer
match" behaviour of *yacc*. For example, if *yacc* were parsing the rule:

     seq : 'A' 'B'
         | 'A' 'B' 'C'

   upon matching "AB" it would look ahead to see if a 'C' is next and, if
so, will match the second production in preference to the first. In other
words, *yacc* effectively tries all the productions of a rule
breadth-first in parallel, and selects the "best" match, where "best"
means longest (note that this is a gross simplification of the true
behaviour of *yacc* but it will do for our purposes).

   In contrast, Parse::RecDescent tries each production depth-first in
sequence, and selects the "best" match, where "best" means first. This is
the fundamental difference between "bottom-up" and "recursive descent"
parsing.

   Each successfully matched item in a production is assigned a value,
which can be accessed in subsequent actions within the same production
(or, in some cases, as the return value of a successful subrule call).
Unsuccessful items don't have an associated value, since the failure of an
item causes the entire surrounding production to immediately fail. The
following sections describe the various types of items and their success
values.

Subrules
--------

   A subrule which appears in a production is an instruction to the parser
to attempt to match the named rule at that point in the text being parsed.
If the named subrule is not defined when requested the production
containing it immediately fails (unless it was "autostubbed" - see
`Autostubbing' in this node).

   A rule may (recursively) call itself as a subrule, but not as the
left-most item in any of its productions (since such recursions are usually
non-terminating).

   The value associated with a subrule is the value associated with its
`$return' variable (see `"Actions"' in this node below), or with the last
successfully matched item in the subrule match.

   Subrules may also be specified with a trailing repetition specifier,
indicating that they are to be (greedily) matched the specified number of
times. The available specifiers are:

     subrule(?)	# Match one-or-zero times
     subrule(s)	# Match one-or-more times
     subrule(s?)	# Match zero-or-more times
     subrule(N)	# Match exactly N times for integer N > 0
     subrule(N..M)	# Match between N and M times
     subrule(..M)	# Match between 1 and M times
     subrule(N..)	# Match at least N times

   Repeated subrules keep matching until either the subrule fails to
match, or it has matched the minimal number of times but fails to consume
any of the parsed text (this second condition prevents the subrule
matching forever in some cases).

   Since a repeated subrule may match many instances of the subrule
itself, the value associated with it is not a simple scalar, but rather a
reference to a list of scalars, each of which is the value associated with
one of the individual subrule matches. In other words in the rule:

     program: statement(s)

   the value associated with the repeated subrule "statement(s)" is a
reference to an array containing the values matched by each call to the
individual subrule "statement".

   Repetition modifieres may include a separator pattern:

     program: statement(s /;/)

   specifying some sequence of characters to be skipped between each
repetition.  This is really just a shorthand for the <leftop:...> directive
(see below).

Tokens
------

   If a quote-delimited string or a Perl regex appears in a production,
the parser attempts to match that string or pattern at that point in the
text. For example:

     typedef: "typedef" typename identifier ';'

     identifier: /[A-Za-z_][A-Za-z0-9_]*/

   As in regular Perl, a single quoted string is uninterpolated, whilst a
double-quoted string or a pattern is interpolated (at the time of
matching, not when the parser is constructed). Hence, it is possible to
define rules in which tokens can be set at run-time:

     typedef: "$::typedefkeyword" typename identifier ';'

     identifier: /$::identpat/

   Note that, since each rule is implemented inside a special namespace
belonging to its parser, it is necessary to explicitly quantify variables
from the main package.

   Regex tokens can be specified using just slashes as delimiters or with
the explicit `m<delimiter>......<delimiter>' syntax:

     typedef: "typedef" typename identifier ';'

     typename: /[A-Za-z_][A-Za-z0-9_]*/

     identifier: m{[A-Za-z_][A-Za-z0-9_]*}

   A regex of either type can also have any valid trailing parameter(s)
(that is, any of [cgimsox]):

     typedef: "typedef" typename identifier ';'

     identifier: / [a-z_] 		# LEADING ALPHA OR UNDERSCORE
     	      [a-z0-9_]*	# THEN DIGITS ALSO ALLOWED
     	    /ix			# CASE/SPACE/COMMENT INSENSITIVE

   The value associated with any successfully matched token is a string
containing the actual text which was matched by the token.

   It is important to remember that, since each grammar is specified in a
Perl string, all instances of the universal escape character '\' within a
grammar must be "doubled", so that they interpolate to single '\'s when
the string is compiled. For example, to use the grammar:

     word:	    /\S+/ | backslash
     line:	    prefix word(s) "\n"
     backslash:  '\\'

   the following code is required:

     $parser = new Parse::RecDescent (q{

     word:	    /\\S+/ | backslash
     line:	    prefix word(s) "\\n"
     backslash:  '\\\\'

     });

Terminal Separators
-------------------

   For the purpose of matching, each terminal in a production is considered
to be preceded by a "prefix" - a pattern which must be matched before a
token match is attempted. By default, the prefix is optional whitespace
(which always matches, at least trivially), but this default may be reset
in any production.

   The variable `$Parse::RecDescent::skip' stores the universal prefix,
which is the default for all terminal matches in all parsers built with
Parse::RecDescent.

   The prefix for an individual production can be altered by using the
`<skip:...>' directive (see below).

Actions
-------

   An action is a block of Perl code which is to be executed (as the block
of a do statement) when the parser reaches that point in a production. The
action executes within a special namespace belonging to the active parser,
so care must be taken in correctly qualifying variable names (see also
`Start-up Actions' in this node below).

   The action is considered to succeed if the final value of the block is
defined (that is, if the implied do statement evaluates to a defined value
- *even one which would be treated as "false"*). Note that the value
associated with a successful action is also the final value in the block.

   An action will fail if its last evaluated value is undef. This is
surprisingly easy to accomplish by accident. For instance, here's an
infuriating case of an action that makes its production fail, but only
when debugging *isn't* activated:

     description: name rank serial_number
     		{ print "Got $item[2] $item[1] ($item[3])\n"
     			if $::debugging
     		}

   If `$debugging' is false, no statement in the block is executed, so the
final value is undef, and the entire production fails. The solution is:

     description: name rank serial_number
     		{ print "Got $item[2] $item[1] ($item[3])\n"
     			if $::debugging;
     		  1;
     		}

   Within an action, a number of useful parse-time variables are available
in the special parser namespace (there are other variables also
accessible, but meddling with them will probably just break your parser.
As a general rule, if you avoid referring to unqualified variables -
especially those starting with an underscore - inside an action, things
should be okay):

`@item' and `%item'
     The array slice `@item[1..$#item]' stores the value associated with
     each item (that is, each subrule, token, or action) in the current
     production. The analogy is to $1, $2, etc. in a *yacc* grammar.  Note
     that, for obvious reasons, `@item' only contains the values of items
     before the current point in the production.

     The first element (`$item[0]') stores the name of the current rule
     being matched.

     `@item' is a standard Perl array, so it can also be indexed with
     negative numbers, representing the number of items back from the
     current position in the parse:

          stuff: /various/ bits 'and' pieces "then" data 'end'
          		{ print $item[-2] }  # PRINTS data
          				     # (EASIER THAN: $item[6])

     The `%item' hash complements the <@item> array, providing named
     access to the same item values:

          stuff: /various/ bits 'and' pieces "then" data 'end'
          		{ print $item{data}  # PRINTS data
          				     # (EVEN EASIER THAN USING @item)

     The results of named subrules are stored in the hash under each
     subrule's name, whilst all other items are stored under a "named
     positional" key that indictates their ordinal position within their
     item type: __STRINGn__, __PATTERNn__, __DIRECTIVEn__, __ACTIONn__:

          stuff: /various/ bits 'and' pieces "then" data 'end' { save }
                          { print $item{__PATTERN1__}, # PRINTS 'various'
                                  $item{__STRING2__},  # PRINTS 'then'
                                  $item{__ACTION1__},  # PRINTS RETURN
          						     # VALUE OF save
                          }

     If you want proper *named* access to patterns or literals, you need
     to turn them into separate rules:

          stuff: various bits 'and' pieces "then" data 'end'
                          { print $item{various}  # PRINTS various
                          }

          various: /various/

     The special entry `$item{__RULE__}' stores the name of the current
     rule (i.e. the same value as `$item[0]'.

     The advantage of using `%item', instead of `@items' is that it
     removes the need to track items positions that may change as a grammar
     evolves. For example, adding an interim `<skip>' directive of action
     can silently ruin a trailing action, by moving an `@item' element
     "down" the array one place. In contrast, the named entry of `%item'
     is unaffected by such an insertion.

     A limitation of the `%item' hash is that it only records the last
     value of a particular subrule. For example:

          range: '(' number '..' number )'
                          { $return = $item{number} }

     will return only the value corresponding to the *second* match of the
     number subrule. In other words, successive calls to a subrule
     overwrite the corresponding entry in `%item'. Once again, the
     solution is to rename each subrule in its own rule:

          range: '(' from_num '..' to_num )'
                          { $return = $item{from_num} }

          from_num: number
          to_num:   number

`@arg' and `%arg'
     The array `@arg' and the hash `%arg' store any arguments passed to
     the rule from some other rule (see `"Subrule argument lists' in this
     node). Changes to the elements of either variable do not propagate
     back to the calling rule (data can be passed back from a subrule via
     the `$return' variable - see next item).

`$return'
     If a value is assigned to `$return' within an action, that value is
     returned if the production containing the action eventually matches
     successfully. Note that setting `$return' *doesn't* cause the current
     production to succeed. It merely tells it what to return if it *does*
     succeed.  Hence `$return' is analogous to $$ in a *yacc* grammar.

     If `$return' is not assigned within a production, the value of the
     last component of the production (namely: `$item[$#item]') is
     returned if the production succeeds.

`$commit'
     The current state of commitment to the current production (see
     `"Directives"' in this node below).

`$skip'
     The current terminal prefix (see `"Directives"' in this node below).

$text
     The remaining (unparsed) text. Changes to $text *do not propagate*
     out of unsuccessful productions, but do survive successful
     productions. Hence it is possible to dynamically alter the text being
     parsed - for example, to provide a `#include'-like facility:

          hash_include: '#include' filename
                                  { $text = ::loadfile($item[2]) . $text }

          filename: '<' /[a-z0-9._-]+/i '>'  { $return = $item[2] }
                  | '"' /[a-z0-9._-]+/i '"'  { $return = $item[2] }

`$thisline' and `$prevline'
     `$thisline' stores the current line number within the current parse
     (starting from 1). `$prevline' stores the line number for the last
     character which was already successfully parsed (this will be
     different from `$thisline' at the end of each line).

     For efficiency, `$thisline' and `$prevline' are actually tied hashes,
     and only recompute the required line number when the variable's value
     is used.

     Assignment to `$thisline' adjusts the line number calculator, so that
     it believes that the current line number is the value being assigned.
     Note that this adjustment will be reflected in all subsequent line
     numbers calculations.

     Modifying the value of the variable $text (as in the previous
     `hash_include' example, for instance) will confuse the line counting
     mechanism. To prevent this, you should call
     `Parse::RecDescent::LineCounter::resync($thisline)' *immediately*
     after any assignment to the variable $text (or, at least, before the
     next attempt to use `$thisline').

     Note that if a production fails after assigning to or resync'ing
     `$thisline', the parser's line counter mechanism will usually be
     corrupted.

     Also see the entry for `@itempos'.

     The line number can be set to values other than 1, by calling the
     start rule with a second argument. For example:

          $parser = new Parse::RecDescent ($grammar);

          $parser->input($text, 10);      # START LINE NUMBERS AT 10

`$thiscolumn' and `$prevcolumn'
     `$thiscolumn' stores the current column number within the current line
     being parsed (starting from 1). `$prevcolumn' stores the column number
     of the last character which was actually successfully parsed. Usually
     `$prevcolumn == $thiscolumn-1', but not at the end of lines.

     For efficiency, `$thiscolumn' and `$prevcolumn' are actually tied
     hashes, and only recompute the required column number when the
     variable's value is used.

     Assignment to `$thiscolumn' or `$prevcolumn' is a fatal error.

     Modifying the value of the variable $text (as in the previous
     `hash_include' example, for instance) may confuse the column counting
     mechanism.

     Note that `$thiscolumn' reports the column number before any
     whitespace that might be skipped before reading a token. Hence if you
     wish to know where a token started (and ended) use something like
     this:

          rule: token1 token2 startcol token3 endcol token4
                          { print "token3: columns $item[3] to $item[5]"; }

          startcol: // { $thiscolumn }    # NEED THE // TO STEP PAST TOKEN SEP
          endcol:      { $prevcolumn }

     Also see the entry for `@itempos'.

`$thisoffset' and `$prevoffset'
     `$thisoffset' stores the offset of the current parsing position
     within the complete text being parsed (starting from 0).
     `$prevoffset' stores the offset of the last character which was
     actually successfully parsed. In all cases `$prevoffset ==
     $thisoffset-1'.

     For efficiency, `$thisoffset' and `$prevoffset' are actually tied
     hashes, and only recompute the required offset when the variable's
     value is used.

     Assignment to `$thisoffset' or <$prevoffset> is a fatal error.

     Modifying the value of the variable $text will not affect the offset
     counting mechanism.

     Also see the entry for `@itempos'.

`@itempos'
     The array `@itempos' stores a hash reference corresponding to each
     element of `@item'. The elements of the hash provide the following:

          $itempos[$n]{offset}{from}      # VALUE OF $thisoffset BEFORE $item[$n]
          $itempos[$n]{offset}{to}        # VALUE OF $prevoffset AFTER $item[$n]
          $itempos[$n]{line}{from}        # VALUE OF $thisline BEFORE $item[$n]
          $itempos[$n]{line}{to}          # VALUE OF $prevline AFTER $item[$n]
          $itempos[$n]{column}{from}      # VALUE OF $thiscolumn BEFORE $item[$n]
          $itempos[$n]{column}{to}        # VALUE OF $prevcolumn AFTER $item[$n]

     Note that the various `$itempos[$n]...{from}' values record the
     appropriate value after any token prefix has been skipped.

     Hence, instead of the somewhat tedious and error-prone:

          rule: startcol token1 endcol
                startcol token2 endcol
                startcol token3 endcol
                          { print "token1: columns $item[1]
                                                to $item[3]
                                   token2: columns $item[4]
                                                to $item[6]
                                   token3: columns $item[7]
                                                to $item[9]" }

          startcol: // { $thiscolumn }    # NEED THE // TO STEP PAST TOKEN SEP
          endcol:      { $prevcolumn }

     it is possible to write:

          rule: token1 token2 token3
                          { print "token1: columns $itempos[1]{column}{from}
                                                to $itempos[1]{column}{to}
                                   token2: columns $itempos[2]{column}{from}
                                                to $itempos[2]{column}{to}
                                   token3: columns $itempos[3]{column}{from}
                                                to $itempos[3]{column}{to}" }

     Note however that (in the current implementation) the use of
     `@itempos' anywhere in a grammar implies that item positioning
     information is collected *everywhere* during the parse. Depending on
     the grammar and the size of the text to be parsed, this may be
     prohibitively expensive and the explicit use of `$thisline',
     `$thiscolumn', etc. may be a better choice.

`$thisparser'
     A reference to the Parse::RecDescent object through which parsing was
     initiated.

     The value of `$thisparser' propagates down the subrules of a parse
     but not back up. Hence, you can invoke subrules from another parser
     for the scope of the current rule as follows:

          rule: subrule1 subrule2
              | { $thisparser = $::otherparser } <reject>
              | subrule3 subrule4
              | subrule5

     The result is that the production calls "subrule1" and "subrule2" of
     the current parser, and the remaining productions call the named
     subrules from `$::otherparser'. Note, however that "Bad Things" will
     happen if `::otherparser' isn't a blessed reference and/or doesn't
     have methods with the same names as the required subrules!

`$thisrule'
     A reference to the `Parse::RecDescent::Rule' object corresponding to
     the rule currently being matched.

`$thisprod'
     A reference to the `Parse::RecDescent::Production' object
     corresponding to the production currently being matched.

`$score' and `$score_return'
     $score stores the best production score to date, as specified by an
     earlier `<score:...>' directive. $score_return stores the
     corresponding return value for the successful production.

     See `Scored productions' in this node.

   Warning: the parser relies on the information in the various `this...'
objects in some non-obvious ways. Tinkering with the other members of
these objects will probably cause Bad Things to happen, unless you
*really* know what you're doing. The only exception to this advice is that
the use of `$this...->{local}' is always safe.

Start-up Actions
----------------

   Any actions which appear before the first rule definition in a grammar
are treated as "start-up" actions. Each such action is stripped of its
outermost brackets and then evaluated (in the parser's special namespace)
just before the rules of the grammar are first compiled.

   The main use of start-up actions is to declare local variables within
the parser's special namespace:

     { my $lastitem = '???'; }

     list: item(s)   { $return = $lastitem }

     item: book      { $lastitem = 'book'; }
           bell      { $lastitem = 'bell'; }
           candle    { $lastitem = 'candle'; }

   but start-up actions can be used to execute any valid Perl code within
a parser's special namespace.

   Start-up actions can appear within a grammar extension or replacement
(that is, a partial grammar installed via `Parse::RecDescent::Extend()' or
`Parse::RecDescent::Replace()' - see `Incremental Parsing' in this node),
and will be executed before the new grammar is installed. Note, however,
that a particular start-up action is only ever executed once.

Autoactions
-----------

   It is sometimes desirable to be able to specify a default action to be
taken at the end of every production (for example, in order to easily
build a parse tree). If the variable `$::RD_AUTOACTION' is defined when
`Parse::RecDescent::new()' is called, the contents of that variable are
treated as a specification of an action which is to appended to each
production in the corresponding grammar. So, for example, to construct a
simple parse tree:

     $::RD_AUTOACTION = q { [@item] };

     parser = new Parse::RecDescent (q{
         expression: and_expr '||' expression | and_expr
         and_expr:   not_expr '&&' and_expr   | not_expr
         not_expr:   '!' brack_expr           | brack_expr
         brack_expr: '(' expression ')'       | identifier
         identifier: /[a-z]+/i
         });

   which is equivalent to:

     parser = new Parse::RecDescent (q{
         expression: and_expr '&&' expression
                         { [@item] }
                   | and_expr
                         { [@item] }

     and_expr:   not_expr '&&' and_expr
                     { [@item] }
             |   not_expr
                     { [@item] }

     not_expr:   '!' brack_expr
                     { [@item] }
             |   brack_expr
                     { [@item] }

     brack_expr: '(' expression ')'
                     { [@item] }
               | identifier
                     { [@item] }

     identifier: /[a-z]+/i
                     { [@item] }
     });

   Alternatively, we could take an object-oriented approach, use different
classes for each node (and also eliminating redundant intermediate nodes):

     $::RD_AUTOACTION = q
       { $#item==1 ? $item[1] : new ${"$item[0]_node"} (@item[1..$#item]) };

     parser = new Parse::RecDescent (q{
         expression: and_expr '||' expression | and_expr
         and_expr:   not_expr '&&' and_expr   | not_expr
         not_expr:   '!' brack_expr           | brack_expr
         brack_expr: '(' expression ')'       | identifier
         identifier: /[a-z]+/i
         });

   which is equivalent to:

     parser = new Parse::RecDescent (q{
         expression: and_expr '&&' expression
                         { new expression_node (@item[1..3]) }
                   | and_expr

     and_expr:   not_expr '&&' and_expr
                     { new and_expr_node (@item[1..3]) }
             |   not_expr

     not_expr:   '!' brack_expr
                     { new not_expr_node (@item[1..2]) }
             |   brack_expr

     brack_expr: '(' expression ')'
                     { new brack_expr_node (@item[1..3]) }
               | identifier

     identifier: /[a-z]+/i
                     { new identifer_node (@item[1]) }
     });

   Note that, if a production already ends in an action, no autoaction is
appended to it. For example, in this version:

     $::RD_AUTOACTION = q
       { $#item==1 ? $item[1] : new ${"$item[0]_node"} (@item[1..$#item]) };

     parser = new Parse::RecDescent (q{
         expression: and_expr '&&' expression | and_expr
         and_expr:   not_expr '&&' and_expr   | not_expr
         not_expr:   '!' brack_expr           | brack_expr
         brack_expr: '(' expression ')'       | identifier
         identifier: /[a-z]+/i
                         { new terminal_node($item[1]) }
         });

   each identifier match produces a `terminal_node' object, not an
`identifier_node' object.

   A level 1 warning is issued each time an "autoaction" is added to some
production.

Autotrees
---------

   A commonly needed autoaction is one that builds a parse-tree. It is
moderately tricky to set up such an action (which must treat terminals
differently from non-terminals), so Parse::RecDescent simplifies the
process by providing the `<autotree>' directive.

   If this directive appears at the start of grammar, it causes
Parse::RecDescent to insert autoactions at the end of any rule except
those which already end in an action. The action inserted depends on
whether the production is an intermediate rule (two or more items), or a
terminal of the grammar (i.e. a single pattern or string item).

   So, for example, the following grammar:

     <autotree>

     file    : command(s)
     command : get | set | vet
     get     : 'get' ident ';'
     set     : 'set' ident 'to' value ';'
     vet     : 'check' ident 'is' value ';'
     ident   : /\w+/
     value   : /\d+/

   is equivalent to:

     file    : command(s)                    { bless \%item, $item[0] }
     command : get                           { bless \%item, $item[0] }
             | set                           { bless \%item, $item[0] }
             | vet                           { bless \%item, $item[0] }
     get     : 'get' ident ';'               { bless \%item, $item[0] }
     set     : 'set' ident 'to' value ';'    { bless \%item, $item[0] }
     vet     : 'check' ident 'is' value ';'  { bless \%item, $item[0] }

     ident   : /\w+/          { bless {__VALUE__=>$item[1]}, $item[0] }
     value   : /\d+/          { bless {__VALUE__=>$item[1]}, $item[0] }

   Note that each node in the tree is blessed into a class of the same name
as the rule itself. This makes it easy to build object-oriented processors
for the parse-trees that the grammar produces. Note too that the last two
rules produce special objects with the single attribute '__VALUE__'. This
is because they consist solely of a single terminal.

   This autoaction-ed grammar would then produce a parse tree in a data
structure like this:

     {
       file => {
                 command => {
                              [ get => {
                                         identifier => { __VALUE__ => 'a' },
                                       },
                                set => {
                                         identifier => { __VALUE__ => 'b' },
                                         value      => { __VALUE__ => '7' },
                                       },
                                vet => {
                                         identifier => { __VALUE__ => 'b' },
                                         value      => { __VALUE__ => '7' },
                                       },
                               ],
                            },
               }
     }

   (except, of course, that each nested hash would also be blessed into
the appropriate class).

Autostubbing
------------

   Normally, if a subrule appears in some production, but no rule of that
name is ever defined in the grammar, the production which refers to the
non-existent subrule fails immediately. This typically occurs as a result
of misspellings, and is a sufficiently common occurance that a warning is
generated for such situations.

   However, when prototyping a grammar it is sometimes useful to be able
to use subrules before a proper specification of them is really possible.
For example, a grammar might include a section like:

     function_call: identifier '(' arg(s?) ')'

     identifier: /[a-z]\w*/i

   where the possible format of an argument is sufficiently complex that
it is not worth specifying in full until the general function call syntax
has been debugged. In this situation it is convenient to leave the real
rule `arg' undefined and just slip in a placeholder (or "stub"):

     arg: 'arg'

   so that the function call syntax can be tested with dummy input such as:

     f0()
     f1(arg)
     f2(arg arg)
     f3(arg arg arg)

   et cetera.

   Early in prototyping, many such "stubs" may be required, so
Parse::RecDescent provides a means of automating their definition.  If the
variable `$::RD_AUTOSTUB' is defined when a parser is built, a subrule
reference to any non-existent rule (say, `sr'), causes a "stub" rule of
the form:

     sr: 'sr'

   to be automatically defined in the generated parser.  A level 1 warning
is issued for each such "autostubbed" rule.

   Hence, with `$::AUTOSTUB' defined, it is possible to only partially
specify a grammar, and then "fake" matches of the unspecified (sub)rules
by just typing in their name.

Look-ahead
----------

   If a subrule, token, or action is prefixed by "...", then it is treated
as a "look-ahead" request. That means that the current production can (as
usual) only succeed if the specified item is matched, but that the matching
*does not consume any of the text being parsed*. This is very similar to
the `/(?=...)/' look-ahead construct in Perl patterns. Thus, the rule:

     inner_word: word ...word

   will match whatever the subrule "word" matches, provided that match is
followed by some more text which subrule "word" would also match (although
this second substring is not actually consumed by "inner_word")

   Likewise, a "...!" prefix, causes the following item to succeed (without
consuming any text) if and only if it would normally fail. Hence, a rule
such as:

     identifier: ...!keyword ...!'_' /[A-Za-z_]\w*/

   matches a string of characters which satisfies the pattern
`/[A-Za-z_]\w*/', but only if the same sequence of characters would not
match either subrule "keyword" or the literal token '_'.

   Sequences of look-ahead prefixes accumulate, multiplying their positive
and/or negative senses. Hence:

     inner_word: word ...!......!word

   is exactly equivalent the the original example above (a warning is
issued in cases like these, since they often indicate something left out,
or misunderstood).

   Note that actions can also be treated as look-aheads. In such cases,
the state of the parser text (in the local variable $text) after the
look-ahead action is guaranteed to be identical to its state before the
action, regardless of how it's changed *within* the action (unless you
actually undefine $text, in which case you get the disaster you deserve
:-).

Directives
----------

   Directives are special pre-defined actions which may be used to alter
the behaviour of the parser. There are currently eighteen directives:
`<commit>', `<uncommit>', `<reject>', `<score>', `<autoscore>', `<skip>',
`<resync>', `<error>', `<rulevar>', `<matchrule>', `<leftop>', `<rightop>',
`<defer>', `<nocheck>', `<perl_quotelike>', `<perl_codeblock>',
`<perl_variable>', and `<token>'.

Committing and uncommitting
     The `<commit>' and `<uncommit>' directives permit the recursive
     descent of the parse tree to be pruned (or "cut") for efficiency.
     Within a rule, a `<commit>' directive instructs the rule to ignore
     subsequent productions if the current production fails. For example:

          command: 'find' <commit> filename
                 | 'open' <commit> filename
                 | 'move' filename filename

     Clearly, if the leading token 'find' is matched in the first
     production but that production fails for some other reason, then the
     remaining productions cannot possibly match. The presence of the
     `<commit>' causes the "command" rule to fail immediately if an
     invalid "find" command is found, and likewise if an invalid "open"
     command is encountered.

     It is also possible to revoke a previous commitment. For example:

          if_statement: 'if' <commit> condition
                                  'then' block <uncommit>
                                  'else' block
                      | 'if' <commit> condition
                                  'then' block

     In this case, a failure to find an "else" block in the first
     production shouldn't preclude trying the second production, but a
     failure to find a "condition" certainly should.

     As a special case, any production in which the first item is an
     `<uncommit>' immediately revokes a preceding `<commit>' (even though
     the production would not otherwise have been tried). For example, in
     the rule:

          request: 'explain' expression
                 | 'explain' <commit> keyword
                 | 'save'
                 | 'quit'
                 | <uncommit> term '?'

     if the text being matched was "explain?", and the first two
     productions failed, then the `<commit>' in production two would cause
     productions three and four to be skipped, but the leading
     `<uncommit>' in the production five would allow that production to
     attempt a match.

     Note in the preceding example, that the `<commit>' was only placed in
     production two. If production one had been:

          request: 'explain' <commit> expression

     then production two would be (inappropriately) skipped if a leading
     "explain..." was encountered.

     Both `<commit>' and `<uncommit>' directives always succeed, and their
     value is always 1.

Rejecting a production
     The `<reject>' directive immediately causes the current production to
     fail (it is exactly equivalent to, but more obvious than, the action
     `{undef}'). A `<reject>' is useful when it is desirable to get the
     side effects of the actions in one production, without prejudicing a
     match by some other production later in the rule. For example, to
     insert tracing code into the parse:

          complex_rule: { print "In complex rule...\n"; } <reject>

          complex_rule: simple_rule '+' 'i' '*' simple_rule
                      | 'i' '*' simple_rule
                      | simple_rule

     It is also possible to specify a conditional rejection, using the
     form `<reject:*condition*>', which only rejects if the specified
     condition is true. This form of rejection is exactly equivalent to
     the action `{(*condition*)?undef:1}>'.  For example:

          command: save_command
                 | restore_command
                 | <reject: defined $::tolerant> { exit }
                 | <error: Unknown command. Ignored.>

     A `<reject>' directive never succeeds (and hence has no associated
     value). A conditional rejection may succeed (if its condition is not
     satisfied), in which case its value is 1.

     As an extra optimization, Parse::RecDescent ignores any production
     which *begins* with an unconditional `<reject>' directive, since any
     such production can never successfully match or have any useful
     side-effects. A level 1 warning is issued in all such cases.

     Note that productions beginning with conditional `<reject:...>'
     directives are never "optimized away" in this manner, even if they
     are always guaranteed to fail (for example: `<reject:1>')

     Due to the way grammars are parsed, there is a minor restriction on
     the condition of a conditional `<reject:...>': it cannot contain any
     raw '<' or '>' characters. For example:

          line: cmd <reject: $thiscolumn > max> data

     results in an error when a parser is built from this grammar (since
     the grammar parser has no way of knowing whether the first > is a
     "less than" or the end of the `<reject:...>'.

     To overcome this problem, put the condition inside a do{} block:

          line: cmd <reject: do{$thiscolumn > max}> data

     Note that the same problem may occur in other directives that take
     arguments. The same solution will work in all cases.

Skipping between terminals
     The `<skip>' directive enables the terminal prefix used in a
     production to be changed. For example:

          OneLiner: Command <skip:'[ \t]*'> Arg(s) /;/

     causes only blanks and tabs to be skipped before terminals in the Arg
     subrule (and any of *its* subrules>, and also before the final `/;/'
     terminal.  Once the production is complete, the previous terminal
     prefix is reinstated. Note that this implies that distinct
     productions of a rule must reset their terminal prefixes individually.

     The `<skip>' directive evaluates to the previous terminal prefix, so
     it's easy to reinstate a prefix later in a production:

          Command: <skip:","> CSV(s) <skip:$item[1]> Modifier

     The value specified after the colon is interpolated into a pattern,
     so all of the following are equivalent (though their efficiency
     increases down the list):

          <skip: "$colon|$comma">   # ASSUMING THE VARS HOLD THE OBVIOUS VALUES

          <skip: ':|,'>

          <skip: q{[:,]}>

          <skip: qr/[:,]/>

     There is no way of directly setting the prefix for an entire rule,
     except as follows:

          Rule: <skip: '[ \t]*'> Prod1
              | <skip: '[ \t]*'> Prod2a Prod2b
              | <skip: '[ \t]*'> Prod3

     or, better:

          Rule: <skip: '[ \t]*'>
              (
                  Prod1
                | Prod2a Prod2b
                | Prod3
              )

     *Note: Up to release 1.51 of Parse::RecDescent, an entirely different
     mechanism was used for specifying terminal prefixes. The current
     method is not backwards-compatible with that early approach. The
     current approach is stable and will not to change again.*

Resynchronization
     The `<resync>' directive provides a visually distinctive means of
     consuming some of the text being parsed, usually to skip an erroneous
     input. In its simplest form `<resync>' simply consumes text up to and
     including the next newline (`"\n"') character, succeeding only if the
     newline is found, in which case it causes its surrounding rule to
     return zero on success.

     In other words, a `<resync>' is exactly equivalent to the token
     `/[^\n]*\n/' followed by the action `{ $return = 0 }' (except that
     productions beginning with a `<resync>' are ignored when generating
     error messages). A typical use might be:

          script : command(s)

          command: save_command
                 | restore_command
                 | <resync> # TRY NEXT LINE, IF POSSIBLE

     It is also possible to explicitly specify a resynchronization
     pattern, using the `<resync:*pattern*>' variant. This version
     succeeds only if the specified pattern matches (and consumes) the
     parsed text. In other words, `<resync:*pattern*>' is exactly
     equivalent to the token `/*pattern*/' (followed by a `{ $return = 0 }'
     action). For example, if commands were terminated by newlines or
     semi-colons:

          command: save_command
                 | restore_command
                 | <resync:[^;\n]*[;\n]>

     The value of a successfully matched `<resync>' directive (of either
     type) is the text that it consumed. Note, however, that since the
     directive also sets `$return', a production consisting of a lone
     `<resync>' succeeds but returns the value zero (which a calling rule
     may find useful to distinguish between "true" matches and "tolerant"
     matches).  Remember that returning a zero value indicates that the
     rule *succeeded* (since only an undef denotes failure within
     Parse::RecDescent parsers.

Error handling
     The `<error>' directive provides automatic or user-defined generation
     of error messages during a parse. In its simplest form `<error>'
     prepares an error message based on the mismatch between the last item
     expected and the text which cause it to fail. For example, given the
     rule:

          McCoy: curse ',' name ', I'm a doctor, not a' a_profession '!'
               | pronoun 'dead,' name '!'
               | <error>

     the following strings would produce the following messages:

    "Amen, Jim!"
               ERROR (line 1): Invalid McCoy: Expected curse or pronoun
                               not found

    "Dammit, Jim, I'm a doctor!"
               ERROR (line 1): Invalid McCoy: Expected ", I'm a doctor, not a"
                               but found ", I'm a doctor!" instead

    "He's dead,\n"
               ERROR (line 2): Invalid McCoy: Expected name not found

    "He's alive!"
               ERROR (line 1): Invalid McCoy: Expected 'dead,' but found
                               "alive!" instead

    "Dammit, Jim, I'm a doctor, not a pointy-eared Vulcan!"
               ERROR (line 1): Invalid McCoy: Expected a profession but found
                               "pointy-eared Vulcan!" instead

     Note that, when autogenerating error messages, all underscores in any
     rule name used in a message are replaced by single spaces (for example
     "a_production" becomes "a production"). Judicious choice of rule
     names can therefore considerably improve the readability of automatic
     error messages (as well as the maintainability of the original
     grammar).

     If the automatically generated error is not sufficient, it is
     possible to provide an explicit message as part of the error
     directive. For example:

          Spock: "Fascinating ',' (name | 'Captain') '.'
               | "Highly illogical, doctor."
               | <error: He never said that!>

     which would result in all failures to parse a "Spock" subrule
     printing the following message:

          ERROR (line <N>): Invalid Spock:  He never said that!

     The error message is treated as a "qq{...}" string and interpolated
     when the error is generated (not when the directive is specified!).
     Hence:

          <error: Mystical error near "$text">

     would correctly insert the ambient text string which caused the error.

     There are two other forms of error directive: `<error?>' and
     `<error?: msg>'. These behave just like `<error>' and `<error: msg>'
     respectively, except that they are only triggered if the rule is
     "committed" at the time they are encountered. For example:

          Scotty: "Ya kenna change the Laws of Phusics," <commit> name
                | name <commit> ',' 'she's goanta blaw!'
                | <error?>

     will only generate an error for a string beginning with "Ya kenna
     change the Laws o' Phusics," or a valid name, but which still fails
     to match the corresponding production. That is,
     `$parser->Scotty("Aye, Cap'ain")' will fail silently (since neither
     production will "commit" the rule on that input), whereas
     `$parser->Scotty("Mr Spock, ah jest kenna do'ut!")'  will fail with
     the error message:

          ERROR (line 1): Invalid Scotty: expected 'she's goanta blaw!'
                          but found 'I jest kenna do'ut!' instead.

     since in that case the second production would commit after matching
     the leading name.

     Note that to allow this behaviour, all `<error>' directives which are
     the first item in a production automatically uncommit the rule just
     long enough to allow their production to be attempted (that is, when
     their production fails, the commitment is reinstated so that
     subsequent productions are skipped).

     In order to *permanently* uncommit the rule before an error message,
     it is necessary to put an explicit `<uncommit>' before the `<error>'.
     For example:

          line: 'Kirk:'  <commit> Kirk
              | 'Spock:' <commit> Spock
              | 'McCoy:' <commit> McCoy
              | <uncommit> <error?> <reject>
              | <resync>

     Error messages generated by the various `<error...>' directives are
     not displayed immediately. Instead, they are "queued" in a buffer and
     are only displayed once parsing ultimately fails. Moreover,
     `<error...>' directives that cause one production of a rule to fail
     are automatically removed from the message queue if another
     production subsequently causes the entire rule to succeed.  This
     means that you can put `<error...>' directives wherever useful
     diagnosis can be done, and only those associated with actual parser
     failure will ever be displayed. Also see `"Gotchas"' in this node.

     As a general rule, the most useful diagnostics are usually generated
     either at the very lowest level within the grammar, or at the very
     highest. A good rule of thumb is to identify those subrules which
     consist mainly (or entirely) of terminals, and then put an
     `<error...>' directive at the end of any other rule which calls one
     or more of those subrules.

     There is one other situation in which the output of the various types
     of error directive is suppressed; namely, when the rule containing
     them is being parsed as part of a "look-ahead" (see `"Look-ahead"' in
     this node). In this case, the error directive will still cause the
     rule to fail, but will do so silently.

     An unconditional `<error>' directive always fails (and hence has no
     associated value). This means that encountering such a directive
     always causes the production containing it to fail. Hence an
     `<error>' directive will inevitably be the last (useful) item of a
     rule (a level 3 warning is issued if a production contains items
     after an unconditional `<error>' directive).

     An `<error?>' directive will *succeed* (that is: fail to fail :-), if
     the current rule is uncommitted when the directive is encountered. In
     that case the directive's associated value is zero. Hence, this type
     of error directive can be used before the end of a production. For
     example:

          command: 'do' <commit> something
                 | 'report' <commit> something
                 | <error?: Syntax error> <error: Unknown command>

     Warning: The `<error?>' directive does not mean "always fail (but do
     so silently unless committed)". It actually means "only fail (and
     report) if committed, otherwise *succeed*". To achieve the "fail
     silently if uncommitted" semantics, it is necessary to use:

          rule: item <commit> item(s)
              | <error?> <reject>      # FAIL SILENTLY UNLESS COMMITTED

     However, because people seem to expect a lone `<error?>' directive to
     work like this:

          rule: item <commit> item(s)
              | <error?: Error message if committed>
              | <error:  Error message if uncommitted>

     Parse::RecDescent automatically appends a `<reject>' directive if the
     `<error?>' directive is the only item in a production. A level 2
     warning (see below) is issued when this happens.

     The level of error reporting during both parser construction and
     parsing is controlled by the presence or absence of four global
     variables: `$::RD_ERRORS', `$::RD_WARN', `$::RD_HINT', and
     <$::RD_TRACE>. If `$::RD_ERRORS' is defined (and, by default, it is)
     then fatal errors are reported.

     Whenever `$::RD_WARN' is defined, certain non-fatal problems are also
     reported.  Warnings have an associated "level": 1, 2, or 3. The
     higher the level, the more serious the warning. The value of the
     corresponding global variable (`$::RD_WARN') determines the *lowest*
     level of warning to be displayed. Hence, to see all warnings, set
     `$::RD_WARN' to 1.  To see only the most serious warnings set
     `$::RD_WARN' to 3.  By default `$::RD_WARN' is initialized to 3,
     ensuring that serious but non-fatal errors are automatically reported.

     See `"DIAGNOSTICS"' for a list of the varous error and warning
     messages that Parse::RecDescent generates when these two variables
     are defined.

     Defining any of the remaining variables (which are not defined by
     default) further increases the amount of information reported.
     Defining `$::RD_HINT' causes the parser generator to offer more
     detailed analyses and hints on both errors and warnings.  Note that
     setting `$::RD_HINT' at any point automagically sets `$::RD_WARN' to
     1.

     Defining `$::RD_TRACE' causes the parser generator and the parser to
     report their progress to STDERR in excruciating detail (although,
     without hints unless $::RD_HINT is separately defined). This detail
     can be moderated in only one respect: if `$::RD_TRACE' has an integer
     value (N) greater than 1, only the N characters of the "current
     parsing context" (that is, where in the input string we are at any
     point in the parse) is reported at any time.

     `$::RD_TRACE' is mainly useful for debugging a grammar that isn't
     behaving as you expected it to. To this end, if `$::RD_TRACE' is
     defined when a parser is built, any actual parser code which is
     generated is also written to a file named "RD_TRACE" in the local
     directory.

     Note that the four variables belong to the "main" package, which
     makes them easier to refer to in the code controlling the parser, and
     also makes it easy to turn them into command line flags ("-RD_ERRORS",
     "-RD_WARN", "-RD_HINT", "-RD_TRACE") under *perl -s*.

Specifying local variables
     It is occasionally convenient to specify variables which are local to
     a single rule. This may be achieved by including a `<rulevar:...>'
     directive anywhere in the rule. For example:

          markup: <rulevar: $tag>

          markup: tag {($tag=$item[1]) =~ s/^<|>$//g} body[$tag]

     The example `<rulevar: $tag>' directive causes a "my" variable named
     $tag to be declared at the start of the subroutine implementing the
     `markup' rule (that is, before the first production, regardless of
     where in the rule it is specified).

     Specifically, any directive of the form: `<rulevar:*text*>' causes a
     line of the form `my *text*;' to be added at the beginning of the
     rule subroutine, immediately after the definitions of the following
     local variables:

          $thisparser     $commit
          $thisrule       @item
          $thisline       @arg
          $text           %arg

     This means that the following `<rulevar>' directives work as expected:

          <rulevar: $count = 0 >

          <rulevar: $firstarg = $arg[0] || '' >

          <rulevar: $myItems = \@item >

          <rulevar: @context = ( $thisline, $text, @arg ) >

          <rulevar: ($name,$age) = $arg{"name","age"} >

     If a variable that is also visible to subrules is required, it needs
     to be local'd, not my'd. `rulevar' defaults to my, but if local is
     explicitly specified:

          <rulevar: local $count = 0 >

     then a local-ized variable is declared instead, and will be available
     within subrules.

     Note however that, because all such variables are "my" variables,
     their values *do not persist* between match attempts on a given rule.
     To preserve values between match attempts, values can be stored
     within the "local" member of the `$thisrule' object:

          countedrule: { $thisrule->{"local"}{"count"}++ }
                       <reject>
                     | subrule1
                     | subrule2
                     | <reject: $thisrule->{"local"}{"count"} == 1>
                       subrule3

     When matching a rule, each `<rulevar>' directive is matched as if it
     were an unconditional `<reject>' directive (that is, it causes any
     production in which it appears to immediately fail to match).  For
     this reason (and to improve readability) it is usual to specify any
     `<rulevar>' directive in a separate production at the start of the
     rule (this has the added advantage that it enables Parse::RecDescent
     to optimize away such productions, just as it does for the `<reject>'
     directive).

Dynamically matched rules
     Because regexes and double-quoted strings are interpolated, it is
     relatively easy to specify productions with "context sensitive"
     tokens. For example:

          command:  keyword  body  "end $item[1]"

     which ensures that a command block is bounded by a "*<keyword>*...end
     *<same keyword>*" pair.

     Building productions in which subrules are context sensitive is also
     possible, via the `<matchrule:...>' directive. This directive behaves
     identically to a subrule item, except that the rule which is invoked
     to match it is determined by the string specified after the colon.
     For example, we could rewrite the command rule like this:

          command:  keyword  <matchrule:body>  "end $item[1]"

     Whatever appears after the colon in the directive is treated as an
     interpolated string (that is, as if it appeared in `qq{...}'
     operator) and the value of that interpolated string is the name of
     the subrule to be matched.

     Of course, just putting a constant string like body in a
     `<matchrule:...>' directive is of little interest or benefit.  The
     power of directive is seen when we use a string that interpolates to
     something interesting. For example:

          command:        keyword <matchrule:$item[1]_body> "end $item[1]"

          keyword:        'while' | 'if' | 'function'

          while_body:     condition block

          if_body:        condition block ('else' block)(?)

          function_body:  arglist block

     Now the command rule selects how to proceed on the basis of the
     keyword that is found. It is as if command were declared:

          command:        'while'    while_body    "end while"
                 |        'if'       if_body       "end if"
                 |        'function' function_body "end function"

     When a `<matchrule:...>' directive is used as a repeated subrule, the
     rule name expression is "late-bound". That is, the name of the rule
     to be called is re-evaluated *each time* a match attempt is made.
     Hence, the following grammar:

          { $::species = 'dogs' }

          pair:   'two' <matchrule:$::species>(s)

          dogs:   /dogs/ { $::species = 'cats' }

          cats:   /cats/

     will match the string "two dogs cats cats" completely, whereas it will
     only match the string "two dogs dogs dogs" up to the eighth letter. If
     the rule name were "early bound" (that is, evaluated only the first
     time the directive is encountered in a production), the reverse
     behaviour would be expected.

Deferred actions
     The `<defer:...>' directive is used to specify an action to be
     performed when (and only if!) the current production ultimately
     succeeds.

     Whenever a `<defer:...>' directive appears, the code it specifies is
     converted to a closure (an anonymous subroutine reference) which is
     queued within the active parser object. Note that, because the
     deferred code is converted to a closure, the values of any "local"
     variable (such as $text, <@item>, etc.) are preserved until the
     deferred code is actually executed.

     If the parse ultimately succeeds and the production in which the
     `<defer:...>' directive was evaluated formed part of the successful
     parse, then the deferred code is executed immediately before the
     parse returns. If however the production which queued a deferred
     action fails, or one of the higher-level rules which called that
     production fails, then the deferred action is removed from the queue,
     and hence is never executed.

     For example, given the grammar:

          sentence: noun trans noun
                  | noun intrans

          noun:     'the dog'
                          { print "$item[1]\t(noun)\n" }
              |     'the meat'
                          { print "$item[1]\t(noun)\n" }

          trans:    'ate'
                          { print "$item[1]\t(transitive)\n" }

          intrans:  'ate'
                          { print "$item[1]\t(intransitive)\n" }
                 |  'barked'
                          { print "$item[1]\t(intransitive)\n" }

     then parsing the sentence `"the dog ate"' would produce the output:

          the dog  (noun)
          ate      (transitive)
          the dog  (noun)
          ate      (intransitive)

     This is because, even though the first production of sentence
     ultimately fails, its initial subrules `noun' and trans do match, and
     hence they execute their associated actions.  Then the second
     production of sentence succeeds, causing the actions of the subrules
     `noun' and `intrans' to be executed as well.

     On the other hand, if the actions were replaced by `<defer:...>'
     directives:

          sentence: noun trans noun
                  | noun intrans

          noun:     'the dog'
                          <defer: print "$item[1]\t(noun)\n" >
              |     'the meat'
                          <defer: print "$item[1]\t(noun)\n" >

          trans:    'ate'
                          <defer: print "$item[1]\t(transitive)\n" >

          intrans:  'ate'
                          <defer: print "$item[1]\t(intransitive)\n" >
                 |  'barked'
                          <defer: print "$item[1]\t(intransitive)\n" >

     the output would be:

          the dog  (noun)
          ate      (intransitive)

     since deferred actions are only executed if they were evaluated in a
     production which ultimately contributes to the successful parse.

     In this case, even though the first production of sentence caused the
     subrules `noun' and trans to match, that production ultimately failed
     and so the deferred actions queued by those subrules were subsequently
     disgarded. The second production then succeeded, causing the entire
     parse to succeed, and so the deferred actions queued by the (second)
     match of the `noun' subrule and the subsequent match of `intrans'
     *are* preserved and eventually executed.

     Deferred actions provide a means of improving the performance of a
     parser, by only executing those actions which are part of the final
     parse-tree for the input data.

     Alternatively, deferred actions can be viewed as a mechanism for
     building (and executing) a customized subroutine corresponding to the
     given input data, much in the same way that autoactions (see
     `"Autoactions"' in this node) can be used to build a customized data
     structure for specific input.

     Whether or not the action it specifies is ever executed, a
     `<defer:...>' directive always succeeds, returning the number of
     deferred actions currently queued at that point.

Parsing Perl
     Parse::RecDescent provides limited support for parsing subsets of
     Perl, namely: quote-like operators, Perl variables, and complete code
     blocks.

     The `<perl_quotelike>' directive can be used to parse any Perl
     quote-like operator: `'a string'', `m/a pattern/', `tr{ans}{lation}',
     etc.  It does this by calling Text::Balanced::quotelike().

     If a quote-like operator is found, a reference to an array of eight
     elements is returned. Those elements are identical to the last eight
     elements returned by Text::Balanced::extract_quotelike() in an array
     context, namely:

    [0]
          the name of the quotelike operator - 'q', 'qq', 'm', 's', 'tr' -
          if the operator was named; otherwise undef,

    [1]
          the left delimiter of the first block of the operation,

    [2]
          the text of the first block of the operation (that is, the
          contents of a quote, the regex of a match, or substitution or
          the target list of a translation),

    [3]
          the right delimiter of the first block of the operation,

    [4]
          the left delimiter of the second block of the operation if there
          is one (that is, if it is a s, tr, or y); otherwise undef,

    [5]
          the text of the second block of the operation if there is one
          (that is, the replacement of a substitution or the translation
          list of a translation); otherwise undef,

    [6]
          the right delimiter of the second block of the operation (if
          any); otherwise undef,

    [7]
          the trailing modifiers on the operation (if any); otherwise
          undef.

     If a quote-like expression is not found, the directive fails with the
     usual undef value.

     The `<perl_variable>' directive can be used to parse any Perl
     variable: $scalar, @array, %hash, $ref->{field}[$index], etc.  It
     does this by calling Text::Balanced::extract_variable().

     If the directive matches text representing a valid Perl variable
     specification, it returns that text. Otherwise it fails with the usual
     undef value.

     The `<perl_codeblock>' directive can be used to parse
     curly-brace-delimited block of Perl code, such as: { $a = 1; f() =~
     m/pat/; }.  It does this by calling
     Text::Balanced::extract_codeblock().

     If the directive matches text representing a valid Perl code block,
     it returns that text. Otherwise it fails with the usual undef value.

Constructing tokens
     Eventually, Parse::RecDescent will be able to parse tokenized input,
     as well as ordinary strings. In preparation for this joyous day, the
     `<token:...>' directive has been provided.  This directive creates a
     token which will be suitable for input to a Parse::RecDescent parser
     (when it eventually supports tokenized input).

     The text of the token is the value of the immediately preceding item
     in the production. A `<token:...>' directive always succeeds with a
     return value which is the hash reference that is the new token. It
     also sets the return value for the production to that hash ref.

     The `<token:...>' directive makes it easy to build a
     Parse::RecDescent-compatible lexer in Parse::RecDescent:

          my $lexer = new Parse::RecDescent q
          {
                  lex:    token(s)

          token:  /a\b/                      <token:INDEF>
               |  /the\b/                    <token:DEF>
               |  /fly\b/                    <token:NOUN,VERB>
               |  /[a-z]+/i { lc $item[1] }  <token:ALPHA>
               |  <error: Unknown token>

          };

     which will eventually be able to be used with a regular
     Parse::RecDescent grammar:

          my $parser = new Parse::RecDescent q
          {
                  startrule: subrule1 subrule 2

                  # ETC...
          };

     either with a pre-lexing phase:

          $parser->startrule( $lexer->lex($data) );

     or with a lex-on-demand approach:

          $parser->startrule( sub{$lexer->token(\$data)} );

     But at present, only the `<token:...>' directive is actually
     implemented. The rest is vapourware.

Specifying operations
     One of the commonest requirements when building a parser is to specify
     binary operators. Unfortunately, in a normal grammar, the rules for
     such things are awkward:

          disjunction:    conjunction ('or' conjunction)(s?)
                                  { $return = [ $item[1], @{$item[2]} ] }

          conjunction:    atom ('and' atom)(s?)
                                  { $return = [ $item[1], @{$item[2]} ] }

     or inefficient:

          disjunction:    conjunction 'or' disjunction
                                  { $return = [ $item[1], @{$item[2]} ] }
                     |    conjunction
                                  { $return = [ $item[1] ] }

          conjunction:    atom 'and' conjunction
                                  { $return = [ $item[1], @{$item[2]} ] }
                     |    atom
                                  { $return = [ $item[1] ] }

     and either way is ugly and hard to get right.

     The `<leftop:...>' and `<rightop:...>' directives provide an easier
     way of specifying such operations. Using `<leftop:...>' the above
     examples become:

          disjunction:    <leftop: conjunction 'or' conjunction>
          conjunction:    <leftop: atom 'and' atom>

     The `<leftop:...>' directive specifies a left-associative binary
     operator.  It is specified around three other grammar elements
     (typically subrules or terminals), which match the left operand, the
     operator itself, and the right operand respectively.

     A `<leftop:...>' directive such as:

          disjunction:    <leftop: conjunction 'or' conjunction>

     is converted to the following:

          disjunction:    ( conjunction ('or' conjunction)(s?)
                                  { $return = [ $item[1], @{$item[2]} ] } )

     In other words, a `<leftop:...>' directive matches the left operand
     followed by zero or more repetitions of both the operator and the
     right operand. It then flattens the matched items into an anonymous
     array which becomes the (single) value of the entire `<leftop:...>'
     directive.

     For example, an `<leftop:...>' directive such as:

          output:  <leftop: ident '<<' expr >

     when given a string such as:

          cout << var << "str" << 3

     would match, and `$item[1]' would be set to:

          [ 'cout', 'var', '"str"', '3' ]

     In other words:

          output:  <leftop: ident '<<' expr >

     is equivalent to a left-associative operator:

          output:  ident                                  { $return = [$item[1]]       }
                |  ident '<<' expr                        { $return = [@item[1,3]]     }
                |  ident '<<' expr '<<' expr              { $return = [@item[1,3,5]]   }
                |  ident '<<' expr '<<' expr '<<' expr    { $return = [@item[1,3,5,7]] }
                #  ...etc...

     Similarly, the `<rightop:...>' directive takes a left operand, an
     operator, and a right operand:

          assign:  <rightop: var '=' expr >

     and converts them to:

          assign:  ( (var '=' {$return=$item[1]})(s?) expr
                                  { $return = [ @{$item[1]}, $item[2] ] } )

     which is equivalent to a right-associative operator:

          assign:  var                            { $return = [$item[1]]       }
                |  var '=' expr                   { $return = [@item[1,3]]     }
                |  var '=' var '=' expr           { $return = [@item[1,3,5]]   }
                |  var '=' var '=' var '=' expr   { $return = [@item[1,3,5,7]] }
                #  ...etc...

     Note that for both the `<leftop:...>' and `<rightop:...>' directives,
     the directive does not normally return the operator itself, just a
     list of the operands involved. This is particularly handy for
     specifying lists:

          list: '(' <leftop: list_item ',' list_item> ')'
                          { $return = $item[2] }

     There is, however, a problem: sometimes the operator is itself
     significant.  For example, in a Perl list a comma and a `=>' are both
     valid separators, but the `=>' has additional stringification
     semantics.  Hence it's important to know which was used in each case.

     To solve this problem the `<leftop:...>' and `<rightop:...>'
     directives do return the operator(s) as well, under two circumstances.
     The first case is where the operator is specified as a subrule. In
     that instance, whatever the operator matches is returned (on the
     assumption that if the operator is important enough to have its own
     subrule, then it's important enough to return).

     The second case is where the operator is specified as a regular
     expression. In that case, if the first bracketed subpattern of the
     regular expression matches, that matching value is returned (this is
     analogous to the behaviour of the Perl split function, except that
     only the first subpattern is returned).

     In other words, given the input:

          ( a=>1, b=>2 )

     the specifications:

          list:      '('  <leftop: list_item separator list_item>  ')'

          separator: ',' | '=>'

     or:

          list:      '('  <leftop: list_item /(,|=>)/ list_item>  ')'

     cause the list separators to be interleaved with the operands in the
     anonymous array in `$item[2]':

          [ 'a', '=>', '1', ',', 'b', '=>', '2' ]

     But the following version:

          list:      '('  <leftop: list_item /,|=>/ list_item>  ')'

     returns only the operators:

          [ 'a', '1', 'b', '2' ]

          Of course, none of the above specifications handle the case of an empty
          list, since the C<Less_Than_Special_Sequenceleftop:...Greater_Than_Special_Sequence> and C<Less_Than_Special_Sequencerightop:...Greater_Than_Special_Sequence> directives
          require at least a single right or left operand to match. To specify
          that the operator can match "trivially",
          it's necessary to add a C<(?)> qualifier to the directive:

          list:      '('  <leftop: list_item /(,|=>)/ list_item>(?)  ')'

     Note that in almost all the above examples, the first and third
     arguments of the `<leftop:...>' directive were the same subrule. That
     is because `<leftop:...>''s are frequently used to specify
     "separated" lists of the same type of item. To make such lists easier
     to specify, the following syntax:

          list:   element(s /,/)

     is exactly equivalent to:

          list:   <leftop: element /,/ element>

     Note that the separator must be specified as a raw pattern (i.e.  not
     a string or subrule).

Scored productions
     By default, Parse::RecDescent grammar rules always accept the first
     production that matches the input. But if two or more productions may
     potentially match the same input, choosing the first that does so may
     not be optimal.

     For example, if you were parsing the sentence "time flies like an
     arrow", you might use a rule like this:

          sentence: verb noun preposition article noun { [@item] }
                  | adjective noun verb article noun   { [@item] }
                  | noun verb preposition article noun { [@item] }

     Each of these productions matches the sentence, but the third one is
     the most likely interpretation. However, if the sentence had been
     "fruit flies like a banana", then the second production is probably
     the right match.

     To cater for such situtations, the `<score:...>' can be used.  The
     directive is equivalent to an unconditional `<reject>', except that
     it allows you to specify a "score" for the current production. If
     that score is numerically greater than the best score of any
     preceding production, the current production is cached for later
     consideration. If no later production matches, then the cached
     production is treated as having matched, and the value of the item
     immediately before its `<score:...>' directive is returned as the
     result.

     In other words, by putting a `<score:...>' directive at the end of
     each production, you can select which production matches using
     criteria other than specification order. For example:

          sentence: verb noun preposition article noun { [@item] } <score: sensible(@item)>
                  | adjective noun verb article noun   { [@item] } <score: sensible(@item)>
                  | noun verb preposition article noun { [@item] } <score: sensible(@item)>

     Now, when each production reaches its respective `<score:...>'
     directive, the subroutine `sensible' will be called to evaluate the
     matched items (somehow). Once all productions have been tried, the
     one which `sensible' scored most highly will be the one that is
     accepted as a match for the rule.

     The variable $score always holds the current best score of any
     production, and the variable $score_return holds the corresponding
     return value.

     As another example, the following grammar matches lines that may be
     separated by commas, colons, or semi-colons. This can be tricky if a
     colon-separated line also contains commas, or vice versa. The grammar
     resolves the ambiguity by selecting the rule that results in the
     fewest fields:

          line: seplist[sep=>',']  <score: -@{$item[1]}>
              | seplist[sep=>':']  <score: -@{$item[1]}>
              | seplist[sep=>" "]  <score: -@{$item[1]}>

          seplist: <skip:""> <leftop: /[^$arg{sep}]*/ "$arg{sep}" /[^$arg{sep}]*/>

     Note the use of negation within the `<score:...>' directive to ensure
     that the seplist with the most items gets the lowest score.

     As the above examples indicate, it is often the case that all
     productions in a rule use exactly the same `<score:...>' directive.
     It is tedious to have to repeat this identical directive in every
     production, so Parse::RecDescent also provides the `<autoscore:...>'
     directive.

     If an `<autoscore:...>' directive appears in any production of a
     rule, the code it specifies is used as the scoring code for every
     production of that rule, except productions that already end with an
     explicit `<score:...>' directive. Thus the rules above could be
     rewritten:

          line: <autoscore: -@{$item[1]}>
          line: seplist[sep=>',']
              | seplist[sep=>':']
              | seplist[sep=>" "]

          sentence: <autoscore: sensible(@item)>
                  | verb noun preposition article noun { [@item] }
                  | adjective noun verb article noun   { [@item] }
                  | noun verb preposition article noun { [@item] }

     Note that the `<autoscore:...>' directive itself acts as an
     unconditional `<reject>', and (like the `<rulevar:...>' directive) is
     pruned at compile-time wherever possible.

Dispensing with grammar checks
     During the compilation phase of parser construction,
     Parse::RecDescent performs a small number of checks on the grammar
     it's given. Specifically it checks that the grammar is not
     left-recursive, that there are no "insatiable" constructs of the form:

          rule: subrule(s) subrule

     and that there are no rules missing (i.e. referred to, but never
     defined).

     These checks are important during development, but can slow down
     parser construction in stable code. So Parse::RecDescent provides the
     <nocheck> directive to turn them off. The directive can only appear
     before the first rule definition, and switches off checking
     throughout the rest of the current grammar.

     Typically, this directive would be added when a parser has been
     thoroughly tested and is ready for release.

Subrule argument lists
----------------------

   It is occasionally useful to pass data to a subrule which is being
invoked. For example, consider the following grammar fragment:

     classdecl: keyword decl

     keyword:   'struct' | 'class';

     decl:      # WHATEVER

   The `decl' rule might wish to know which of the two keywords was used
(since it may affect some aspect of the way the subsequent declaration is
interpreted). Parse::RecDescent allows the grammar designer to pass data
into a rule, by placing that data in an *argument list* (that is, in
square brackets) immediately after any subrule item in a production.
Hence, we could pass the keyword to `decl' as follows:

     classdecl: keyword decl[ $item[1] ]

     keyword:   'struct' | 'class';

     decl:      # WHATEVER

   The argument list can consist of any number (including zero!) of
comma-separated Perl expressions. In other words, it looks exactly like a
Perl anonymous array reference. For example, we could pass the keyword,
the name of the surrounding rule, and the literal 'keyword' to `decl' like
so:

     classdecl: keyword decl[$item[1],$item[0],'keyword']

     keyword:   'struct' | 'class';

     decl:      # WHATEVER

   Within the rule to which the data is passed (`decl' in the above
examples) that data is available as the elements of a local variable
`@arg'. Hence `decl' might report its intentions as follows:

     classdecl: keyword decl[$item[1],$item[0],'keyword']

     keyword:   'struct' | 'class';

     decl:      { print "Declaring $arg[0] (a $arg[2])\n";
                  print "(this rule called by $arg[1])" }

   Subrule argument lists can also be interpreted as hashes, simply by
using the local variable `%arg' instead of `@arg'. Hence we could rewrite
the previous example:

     classdecl: keyword decl[keyword => $item[1],
                             caller  => $item[0],
                             type    => 'keyword']

     keyword:   'struct' | 'class';

     decl:      { print "Declaring $arg{keyword} (a $arg{type})\n";
                  print "(this rule called by $arg{caller})" }

   Both `@arg' and `%arg' are always available, so the grammar designer may
choose whichever convention (or combination of conventions) suits best.

   Subrule argument lists are also useful for creating "rule templates"
(especially when used in conjunction with the `<matchrule:...>'
directive). For example, the subrule:

     list:     <matchrule:$arg{rule}> /$arg{sep}/ list[%arg]
                     { $return = [ $item[1], @{$item[3]} ] }
         |     <matchrule:$arg{rule}>
                     { $return = [ $item[1]] }

   is a handy template for the common problem of matching a separated list.
For example:

     function: 'func' name '(' list[rule=>'param',sep=>';'] ')'

     param:    list[rule=>'name',sep=>','] ':' typename

     name:     /\w+/

     typename: name

   When a subrule argument list is used with a repeated subrule, the
argument list goes before the repetition specifier:

     list:   /some|many/ thing[ $item[1] ](s)

   The argument list is "late bound". That is, it is re-evaluated for every
repetition of the repeated subrule.  This means that each repeated attempt
to match the subrule may be passed a completely different set of arguments
if the value of the expression in the argument list changes between
attempts. So, for example, the grammar:

     { $::species = 'dogs' }

     pair:   'two' animal[$::species](s)

     animal: /$arg[0]/ { $::species = 'cats' }

   will match the string "two dogs cats cats" completely, whereas it will
only match the string "two dogs dogs dogs" up to the eighth letter. If the
value of the argument list were "early bound" (that is, evaluated only the
first time a repeated subrule match is attempted), one would expect the
matching behaviours to be reversed.

   Of course, it is possible to effectively "early bind" such argument
lists by passing them a value which does not change on each repetition.
For example:

     { $::species = 'dogs' }

     pair:   'two' { $::species } animal[$item[2]](s)

     animal: /$arg[0]/ { $::species = 'cats' }

   Arguments can also be passed to the start rule, simply by appending them
to the argument list with which the start rule is called (after the "line
number" parameter). For example, given:

     $parser = new Parse::RecDescent ( $grammar );

     $parser->data($text, 1, "str", 2, \@arr);

     #             ^^^^^  ^  ^^^^^^^^^^^^^^^
     #               |    |         |
     # TEXT TO BE PARSED  |         |
     # STARTING LINE NUMBER         |
     # ELEMENTS OF @arg WHICH IS PASSED TO RULE data

   then within the productions of the rule data, the array `@arg' will
contain `("str", 2, \@arr)'.

Alternations
------------

   Alternations are implicit (unnamed) rules defined as part of a
production. An alternation is defined as a series of '|'-separated
productions inside a pair of round brackets. For example:

     character: 'the' ( good | bad | ugly ) /dude/

   Every alternation implicitly defines a new subrule, whose
automatically-generated name indicates its origin:
"_alternation_<I>_of_production_<P>_of_rule<R>" for the appropriate values
of <I>, <P>, and <R>. A call to this implicit subrule is then inserted in
place of the brackets. Hence the above example is merely a convenient
short-hand for:

     character: 'the'
                _alternation_1_of_production_1_of_rule_character
                /dude/

     _alternation_1_of_production_1_of_rule_character:
                good | bad | ugly

   Since alternations are parsed by recursively calling the parser
generator, any type(s) of item can appear in an alternation. For example:

     character: 'the' ( 'high' "plains"      # Silent, with poncho
                      | /no[- ]name/         # Silent, no poncho
                      | vengeance_seeking    # Poncho-optional
                      | <error>
                      ) drifter

   In this case, if an error occurred, the automatically generated message
would be:

     ERROR (line <N>): Invalid implicit subrule: Expected
                       'high' or /no[- ]name/ or generic,
                       but found "pacifist" instead

   Since every alternation actually has a name, it's even possible to
extend or replace them:

     parser->Replace(
             "_alternation_1_of_production_1_of_rule_character:
                     'generic Eastwood'"
                     );

   More importantly, since alternations are a form of subrule, they can be
given repetition specifiers:

     character: 'the' ( good | bad | ugly )(?) /dude/

Incremental Parsing
-------------------

   Parse::RecDescent provides two methods - `Extend' and Replace - which
can be used to alter the grammar matched by a parser. Both methods take
the same argument as `Parse::RecDescent::new', namely a grammar
specification string

   `Parse::RecDescent::Extend' interprets the grammar specification and
adds any productions it finds to the end of the rules for which they are
specified. For example:

     $add = "name: 'Jimmy-Bob' | 'Bobby-Jim'\ndesc: colour /necks?/";
     parser->Extend($add);

   adds two productions to the rule "name" (creating it if necessary) and
one production to the rule "desc".

   `Parse::RecDescent::Replace' is identical, except that it first resets
are rule specified in the additional grammar, removing any existing
productions.  Hence after:

     $add = "name: 'Jimmy-Bob' | 'Bobby-Jim'\ndesc: colour /necks?/";
     parser->Replace($add);

   are are *only* valid "name"s and the one possible description.

   A more interesting use of the `Extend' and Replace methods is to call
them inside the action of an executing parser. For example:

     typedef: 'typedef' type_name identifier ';'
                    { $thisparser->Extend("type_name: '$item[3]'") }
            | <error>

     identifier: ...!type_name /[A-Za-z_]w*/

   which automatically prevents type names from being typedef'd, or:

     command: 'map' key_name 'to' abort_key
                    { $thisparser->Replace("abort_key: '$item[2]'") }
            | 'map' key_name 'to' key_name
                    { map_key($item[2],$item[4]) }
            | abort_key
                    { exit if confirm("abort?") }

     abort_key: 'q'

     key_name: ...!abort_key /[A-Za-z]/

   which allows the user to change the abort key binding, but not to
unbind it.

   The careful use of such constructs makes it possible to reconfigure a a
running parser, eliminating the need for semantic feedback by providing
syntactic feedback instead. However, as currently implemented, `Replace()'
and `Extend()' have to regenerate and re-eval the entire parser whenever
they are called. This makes them quite slow for large grammars.

   In such cases, the judicious use of an interpolated regex is likely to
be far more efficient:

     typedef: 'typedef' type_name/ identifier ';'
                    { $thisparser->{local}{type_name} .= "|$item[3]" }
            | <error>

     identifier: ...!type_name /[A-Za-z_]w*/

     type_name: /$thisparser->{local}{type_name}/

Precompiling parsers
--------------------

   Normally Parse::RecDescent builds a parser from a grammar at run-time.
That approach simplifies the design and implementation of parsing code,
but has the disadvantage that it slows the parsing process down - you have
to wait for Parse::RecDescent to build the parser every time the program
runs. Long or complex grammars can be particularly slow to build, leading
to unacceptable delays at start-up.

   To overcome this, the module provides a way of "pre-building" a parser
object and saving it in a separate module. That module can then be used to
create clones of the original parser.

   A grammar may be precompiled using the `Precompile' class method.  For
example, to precompile a grammar stored in the scalar $grammar, and
produce a class named PreGrammar in a module file named PreGrammar.pm, you
could use:

     use Parse::RecDescent;

     Parse::RecDescent->Precompile($grammar, "PreGrammar");

   The first argument is the grammar string, the second is the name of the
class to be built. The name of the module file is generated automatically
by appending ".pm" to the last element of the class name. Thus

     Parse::RecDescent->Precompile($grammar, "My::New::Parser");

   would produce a module file named Parser.pm.

   It is somewhat tedious to have to write a small Perl program just to
generate a precompiled grammar class, so Parse::RecDescent has some special
magic that allows you to do the job directly from the command-line.

   If your grammar is specified in a file named grammar, you can generate
a class named Yet::Another::Grammar like so:

     > perl -MParse::RecDescent - grammar Yet::Another::Grammar

   This would produce a file named `Grammar.pm' containing the full
definition of a class called Yet::Another::Grammar. Of course, to use that
class, you would need to put the `Grammar.pm' file in a directory named
`Yet/Another', somewhere in your Perl include path.

   Having created the new class, it's very easy to use it to build a
parser. You simply use the new module, and then call its new method to
create a parser object. For example:

     use Yet::Another::Grammar;
     my $parser = Yet::Another::Grammar->new();

   The effect of these two lines is exactly the same as:

     use Parse::RecDescent;

     open GRAMMAR_FILE, "grammar" or die;
     local $/;
     my $grammar = <GRAMMAR_FILE>;

     my $parser = Parse::RecDescent->new($grammar);

   only considerably faster.

   Note however that the parsers produced by either approach are exactly
the same, so whilst precompilation has an effect on *set-up* speed, it has
no effect on *parsing* speed. RecDescent 2.0 will address that problem.

A Metagrammar for Parse::RecDescent
-----------------------------------

   The following is a specification of grammar format accepted by
`Parse::RecDescent::new' (specified in the Parse::RecDescent grammar
format!):

     grammar    : components(s)

     component  : rule | comment

     rule       : "\n" identifier ":" production(s?)

     production : items(s)

     item       : lookahead(?) simpleitem
                | directive
                | comment

     lookahead  : '...' | '...!'                   # +'ve or -'ve lookahead

     simpleitem : subrule args(?)                  # match another rule
                | repetition                       # match repeated subrules
                | terminal                         # match the next input
                | bracket args(?)                  # match alternative items
                | action                           # do something

     subrule    : identifier                       # the name of the rule

     args       : {extract_codeblock($text,'[]')}  # just like a [...] array ref

     repetition : subrule args(?) howoften

     howoften   : '(?)'                            # 0 or 1 times
                | '(s?)'                           # 0 or more times
                | '(s)'                            # 1 or more times
                | /(\d+)[.][.](/\d+)/              # $1 to $2 times
                | /[.][.](/\d*)/                   # at most $1 times
                | /(\d*)[.][.])/                   # at least $1 times

     terminal   : /[/]([\][/]|[^/])*[/]/           # interpolated pattern
                | /"([\]"|[^"])*"/                 # interpolated literal
                | /'([\]'|[^'])*'/                 # uninterpolated literal

     action     : { extract_codeblock($text) }     # embedded Perl code

     bracket    : '(' Item(s) production(s?) ')'   # alternative subrules

     directive  : '<commit>'                       # commit to production
                | '<uncommit>'                     # cancel commitment
                | '<resync>'                       # skip to newline
                | '<resync:' pattern '>'           # skip <pattern>
                | '<reject>'                       # fail this production
                | '<reject:' condition '>'         # fail if <condition>
                | '<error>'                        # report an error
                | '<error:' string '>'             # report error as "<string>"
                | '<error?>'                       # error only if committed
                | '<error?:' string '>'            #   "    "    "    "
                | '<rulevar:' /[^>]+/ '>'          # define rule-local variable
                | '<matchrule:' string '>'         # invoke rule named in string

     identifier : /[a-z]\w*/i                      # must start with alpha

     comment    : /#[^\n]*/                        # same as Perl

     pattern    : {extract_bracketed($text,'<')}   # allow embedded "<..>"

     condition  : {extract_codeblock($text,'{<')}  # full Perl expression

     string     : {extract_variable($text)}        # any Perl variable
                | {extract_quotelike($text)}       #   or quotelike string
                | {extract_bracketed($text,'<')}   #   or balanced brackets

GOTCHAS
=======

   This section describes common mistakes that grammar writers seem to
make on a regular basis.

1. Expecting an error to always invalidate a parse
--------------------------------------------------

   A common mistake when using error messages is to write the grammar like
this:

     file: line(s)

     line: line_type_1
         | line_type_2
         | line_type_3
         | <error>

   The expectation seems to be that any line that is not of type 1, 2 or 3
will invoke the `<error>' directive and thereby cause the parse to fail.

   Unfortunately, that only happens if the error occurs in the very first
line.  The first rule states that a file is matched by one or more lines,
so if even a single line succeeds, the first rule is completely satisfied
and the parse as a whole succeeds. That means that any error messages
generated by subsequent failures in the line rule are quietly ignored.

   Typically what's really needed is this:

     file: line(s) eofile    { $return = $item[1] }

     line: line_type_1
         | line_type_2
         | line_type_3
         | <error>

     eofile: /^\Z/

   The addition of the `eofile' subrule  to the first production means that
a file only matches a series of successful line matches *that consume the
complete input text*. If any input text remains after the lines are
matched, there must have been an error in the last line. In that case the
`eofile' rule will fail, causing the entire file rule to fail too.

   Note too that `eofile' must match `/^\Z/' (end-of-text), not `/^\cZ/'
or `/^\cD/' (end-of-file).

   And don't forget the action at the end of the production. If you just
write:

     file: line(s) eofile

   then the value returned by the file rule will be the value of its last
item: `eofile'. Since `eofile' always returns an empty string on success,
that will cause the file rule to return that empty string. Apart from
returning the wrong value, returning an empty string will trip up code
such as:

     $parser->file($filetext) || die;

   (since "" is false).

   Remember that Parse::RecDescent returns undef on failure, so the only
safe test for failure is:

     defined($parser->file($filetext)) || die;

DIAGNOSTICS
===========

   Diagnostics are intended to be self-explanatory (particularly if you
use *-RD_HINT* (under *perl -s*) or define `$::RD_HINT' inside the
program).

   Parse::RecDescent currently diagnoses the following:

   * Invalid regular expressions used as pattern terminals (fatal error).

   * Invalid Perl code in code blocks (fatal error).

   * Lookahead used in the wrong place or in a nonsensical way (fatal
     error).

   * "Obvious" cases of left-recursion (fatal error).

   * Missing or extra components in a `<leftop>' or `<rightop>' directive.

   * Unrecognisable components in the grammar specification (fatal error).

   * "Orphaned" rule components specified before the first rule (fatal
     error) or after an `<error>' directive (level 3 warning).

   * Missing rule definitions (this only generates a level 3 warning,
     since you may be providing them later via
     `Parse::RecDescent::Extend()').

   * Instances where greedy repetition behaviour will almost certainly
     cause the failure of a production (a level 3 warning - see `"ON-GOING
     ISSUES AND FUTURE DIRECTIONS"' in this node below).

   * Attempts to define rules named 'Replace' or 'Extend', which cannot be
     called directly through the parser object because of the predefined
     meaning of `Parse::RecDescent::Replace' and
     `Parse::RecDescent::Extend'. (Only a level 2 warning is generated,
     since such rules can still be used as subrules).

   * Productions which consist of a single `<error?>' directive, and which
     therefore may succeed unexpectedly (a level 2 warning, since this
     might conceivably be the desired effect).

   * Multiple consecutive lookahead specifiers (a level 1 warning only,
     since their effects simply accumulate).

   * Productions which start with a `<reject>' or `<rulevar:...>'
     directive. Such productions are optimized away (a level 1 warning).

   * Rules which are autogenerated under `$::AUTOSTUB' (a level 1 warning).

AUTHOR
======

   Damian Conway (damian@conway.org)

BUGS AND IRRITATIONS
====================

   There are undoubtedly serious bugs lurking somewhere in this much code
:-) Bug reports and other feedback are most welcome.

   Ongoing annoyances include:

   * There's no support for parsing directly from an input stream.  If and
     when the Perl Gods give us regular expressions on streams, this
     should be trivial (ahem!) to implement.

   * The parser generator can get confused if actions aren't properly
     closed or if they contain particularly nasty Perl syntax errors
     (especially unmatched curly brackets).

   * The generator only detects the most obvious form of left recursion
     (potential recursion on the first subrule in a rule). More subtle
     forms of left recursion (for example, through the second item in a
     rule after a "zero" match of a preceding "zero-or-more" repetition,
     or after a match of a subrule with an empty production) are not found.

   * Instead of complaining about left-recursion, the generator should
     silently transform the grammar to remove it. Don't expect this
     feature any time soon as it would require a more sophisticated
     approach to parser generation than is currently used.

   * The generated parsers don't always run as fast as might be wished.

   * The meta-parser should be bootstrapped using Parse::RecDescent :-)

ON-GOING ISSUES AND FUTURE DIRECTIONS
=====================================

  1. Repetitions are "incorrigibly greedy" in that they will eat
     everything they can and won't backtrack if that behaviour causes a
     production to fail needlessly.  So, for example:

          rule: subrule(s) subrule

     will never succeed, because the repetition will eat all the subrules
     it finds, leaving none to match the second item. Such constructions
     are relatively rare (and `Parse::RecDescent::new' generates a warning
     whenever they occur) so this may not be a problem, especially since
     the insatiable behaviour can be overcome "manually" by writing:

          rule: penultimate_subrule(s) subrule

          penultimate_subrule: subrule ...subrule

     The issue is that this construction is exactly twice as expensive as
     the original, whereas backtracking would add only 1/N to the cost (for
     matching N repetitions of `subrule'). I would welcome feedback on the
     need for backtracking; particularly on cases where the lack of it
     makes parsing performance problematical.

  2. Having opened that can of worms, it's also necessary to consider
     whether there is a need for non-greedy repetition specifiers. Again,
     it's possible (at some cost) to manually provide the required
     functionality:

          rule: nongreedy_subrule(s) othersubrule

          nongreedy_subrule: subrule ...!othersubrule

     Overall, the issue is whether the benefit of this extra functionality
     outweighs the drawbacks of further complicating the (currently
     minimalist) grammar specification syntax, and (worse) introducing
     more overhead into the generated parsers.

  3. An `<autocommit>' directive would be nice. That is, it would be
     useful to be able to say:

          command: <autocommit>
          command: 'find' name
                 | 'find' address
                 | 'do' command 'at' time 'if' condition
                 | 'do' command 'at' time
                 | 'do' command
                 | unusual_command

     and have the generator work out that this should be "pruned" thus:

          command: 'find' name
                 | 'find' <commit> address
                 | 'do' <commit> command <uncommit>
                          'at' time
                          'if' <commit> condition
                 | 'do' <commit> command <uncommit>
                          'at' <commit> time
                 | 'do' <commit> command
                 | unusual_command

     There are several issues here. Firstly, should the `<autocommit>'
     automatically install an `<uncommit>' at the start of the last
     production (on the grounds that the "command" rule doesn't know
     whether an "unusual_command" might start with "find" or "do") or
     should the "unusual_command" subgraph be analysed (to see if it
     *might* be viable after a "find" or "do")?

     The second issue is how regular expressions should be treated. The
     simplest approach would be simply to uncommit before them (on the
     grounds that they *might* match). Better efficiency would be obtained
     by analyzing all preceding literal tokens to determine whether the
     pattern would match them.

     Overall, the issues are: can such automated "pruning" approach a
     hand-tuned version sufficiently closely to warrant the extra set-up
     expense, and (more importantly) is the problem important enough to
     even warrant the non-trivial effort of building an automated solution?

COPYRIGHT
=========

   Copyright (c) 1997-2000, Damian Conway. All Rights Reserved.  This
module is free software. It may be used, redistributed and/or modified
under the terms of the Perl Artistic License   (see
http://www.perl.com/perl/misc/Artistic.html)

Perl extension for blah blah blah
*********************************

NAME
====

   Parse::RecDescent::Consumer - Perl extension for blah blah blah

SYNOPSIS
========

     use Parse::RecDescent::Consumer;

   # then in a Parse::RecDescent grammar...

   url: <rulevar: $C> url: { $C = Consumer($text) } httpurl {
REBOL::url->new(value => $C->($text)) }    | { $C = Consumer($text) }
ftpurl  { REBOL::url->new(value => $C->($text)) }

DESCRIPTION
===========

   A common need when writing grammars is to know how much text was
consumed at different points in a parse. Usually, this involves a lot of
brain-twisting unwinding of of highly nested list-of-lists (of lists...).
Instead this module allows you to take the low-road approach. You simply
create a `Consumer' which records the current text about to be parsed.

   After you have successfully transitioned through the desired tokens,
you simply re-call your `Consumer' and it gives you the text that was
consumed during the token transitions without you having to unravel a
highly nested list-of-lists (of lists...).

IMPLEMENTATION
==============

   when you first call Consumer(), you are returned a closure which has
the current text remaining to be parsed in it. When you evaluate the
closure, passing it the (more or less consumed) new text, the closure
calculates the difference in length between the two texts, and returns a
substring of the first equating to the amount of text consumed between
calls:

     sub Parse::RecDescent::Consumer {
      my $text=shift;
      my $closure = sub {
        my $new_length=length($_[0]);
        my $original_text = $text;
        my $original_length = length($text);
        return substr($original_text, 0, ($original_length-$new_length));
      }
     }

EXPORT
------

   None by default.

AUTHOR
======

   A. U. Thor, a.u.thor@a.galaxy.far.far.away

SEE ALSO
========

   perl(1).

Processor for templates containing Perl expressions
***************************************************

NAME
====

   Parse::Template - Processor for templates containing Perl expressions

SYNOPSIS
========

     use Parse::Template;

     my %template =
       (
        'TOP' =>  q!Text before %%$self->eval('DATA')%% text after!,
        'DATA' => q!Insert data: ! .
                  q!1. List: %%"@list$N"%%! .
                  q!2. Hash: %%"$hash{'key_value'}$N"%%! .
                  q!3. File content: %%print <FH>%%! .
                  q!4. Sub: %%&SUB()$N%%!
       );

     my $tmplt = new Parse::Template (%template);
     open FH, "< foo";

     $tmplt->env('var' => '(value!)');
     $tmplt->env('list' => [1, 2, 10],
                 'N' => "\n",
                 'FH' => \*FH,
                 'SUB' => sub { "->content generated by a sub<-" },
                 'hash' => { 'key_value' => q!It\'s an hash value! });
     print $tmplt->eval('TOP'), "\n";

DESCRIPTION
===========

   The `Parse::Template' class evaluates Perl expressions placed within a
text.  This class can be used as a code generator, or a generator of
documents in various document formats (HTML, XML, RTF, etc.).

   The principle of template-based text generation is simple.  A template
consists of a text which includes expressions to be evaluated.
Interpretation of these expressions generates text fragments which are
substituted in place of the expressions.  In the case of `Parse::Template'
the expressions to be evaluated are placed within two `%%'.

   Evaluation takes place within an environment in which, for example, you
can place data structures which will serve to generate the parts to be
completed.

     TEMPLATE
                Text + Perl Expression
        |
        +-----> Evaluation ----> Text(document or program)
        |
                Subs + Data structures
                 ENVIRONMENT

   The `Parse::Template' class permits decomposing a template into parts.
These parts are defined by a hash passed as an argument to the class
constructor: `Parse::Template-'>`new('someKey', '... text with expressions
to evaluate ...')'.  Within a part, a sub-part can beincluded by means of
an expression of the form:

     $self->eval('SUB_PART_NAME')

   `$self' designates the instance of the `Parse::Template' class.  In an
expression you can also use the `$part' which contains the part of the
template where the expression is found.

   Within an expression it is possible to specify only the name of a part
to be inserted.  In this case a subroutine with the name of this part is
generated dynamically.  In the example given in the synopsis, the
insertion of the `TOP' part can thus be rewritten as follows:

     'TOP' => q!Text before %%DATA()%% text after!

   `DATA()' is placed within `%%' and is in effect treated as an
expression to be evaluated.

   The subroutines take arguments.  In the following example, the argument
is used to control the depth of recursive calls of a template:

     print Parse::Template->new(
       'TOP' => q!%%$_[0] < 10 ? '[' . TOP($_[0] + 1) . ']' : ''%%!
      )->eval('TOP', 0);

   `$_[0]' initially contains 0. `TOP' is included as long as the argument
is less than 10.  For each inclusion, 1 is added to the argument.

   The `env()' method permits constructing the environment required for
evaluation of a template.  Each entry to be defined within this
environment must be specified using a key consisting of the name of the
symbol to be created, associated with a reference whose type is that of
the entry to be created within this environment (for example, a reference
to an array to create an array).  A scalar variable is defined by
associating the name of the variable with its value.  A scalar variable
containing a reference is defined by writing `'var'='>`\$variable', where
`$variable' is a lexical variable that contains the reference.

   Each instance of `Parse::Template' is defined within a specific class,
a subclass of `Parse::Template'.  The subclass contains the environment
specific to the template and inherits methods from the `Parse::Template'
class.

   In case of a syntax error in the evalutaion of an expression,
`Parse::Template' tries to indicate the template part and the expression
that is "incriminated".  If the variable `$Parse::Template::CONFESS'
contains the value TRUE, the stack of evaluations is printed.

METHODS
=======

new HASH
     Constructor for the class. HASH is a hash which defines the template
     text.

     Example:

          use Parse::Template;
          $t = new Parse::Template('key' => 'associated text');

env HASH
env SYMBOL
     Permits defining the environment that is specific to a template.

     `env(SYMBOL)' returns the reference associated with the symbol, or
     undef if the symbol is not defined.  The reference that is returned
     is of the type indicated by the character (`&, $, %, @, *') that
     prefixes the symbol.

     Examples:

          $tmplt->env('LIST' => [1, 2, 3])}   Defines a list

          @{$tmplt->env('*LIST')}             Returns the list

          @{$tmplt->env('@LIST')}             Ditto

eval PART_NAME
     Evaluates the template part designated by `PART_NAME'.  Returns the
     string resulting from this evaluation.

getPart PART_NAME
     Returns the designated part of the template.

ppregexp REGEXP
     Preprocesses a regular expression so that it can be inserted into a
     template where the regular expression delimiter is either a "/" or a
     "!".

setPart PART_NAME => TEXT
     `setPart()' permits defining a new entry in the hash that defines the
     contents of the template.

EXAMPLES
========

   The `Parse::Template' class can be used in all sorts of amusing ways.
Here are a few illustrations.

   The first example shows how to generate an HTML document by using a
data structure placed within the evaluation environment.  The template
consists of two parts, DOC and SECTION.  The SECTION part is called within
the DOC part to generate as many sections as there are elements in the
array `section_content'.

     my %template = ('DOC' => <<'END_OF_DOC;', 'SECTION' => <<'END_OF_SECTION;');
     <html>
     <head></head>
     <body>
     %%
     my $content;
     for (my $i = 0; $i <= $#section_content; $i++) {
       $content .= SECTION($i);
     }
     $content;
     %%
     </body>
     </html>
     END_OF_DOC;
     %%
     $section_content[$_[0]]->{Content} =~ s/^/<p>/mg;
     join '', '<H1>', $section_content[$_[0]]->{Title}, '</H1>', $section_content[$_[0]]->{Content};
     %%
     END_OF_SECTION;

     my $tmplt = new Parse::Template (%template);

     $tmplt->env('section_content' => [
         {
          Title => 'First Section',
          Content => 'Nothing to declare'
         },
         {
          Title => 'Second section',
          Content => 'Nothing else to declare'
         }
        ]
         );

     print $tmplt->eval('DOC'), "\n";

   The second example shows how to generate an HTML document using a
functional notation, in other words, obtaining the text:

     <P><B>text in bold</B><I>text in italic</I></P>

   from

     P(B("text in bold"), I("text in italic"))

   The Perl expression that permits producing the content of an element is
very simple, and reduces to:

     join '', @_

   The content to be evaluated is the same regardless of the tag and can
therefore be placed within a variable.  We therefore obtain the following
template:

     my $ELT_CONTENT = q!%%join '', @_%%!;
     my $HTML_T1 = new Parse::Template(
           'DOC' => '%%P(B("text in bold"), I("text in italic"))%%',
           'P' => qq!<P>$ELT_CONTENT</P>!,
           'B' => qq!<B>$ELT_CONTENT</B>!,
           'I' => qq!<I>$ELT_CONTENT</I>!,
          );
     print $HTML_T1->eval('DOC'), "\n";

   We can go further by making use of the `$part' variable, which is
defined by default in the environment of evaluation of the template:

     $ELT_CONTENT = q!%%"<$part>" . join('', @_) . "</$part>"%%!;
     $HTML_T2 = new Parse::Template(
           'DOC' => '%%P(B("text in bold"), I("text in italic"))%%',
           'P' => qq!$ELT_CONTENT!,
           'B' => qq!$ELT_CONTENT!,
           'I' => qq!$ELT_CONTENT!,
          );
     print $HTML_T2->eval('DOC'), "\n";

   Let's look at another step which automates the production of
expressions from the list of HTML tags which are of interest to us:

     $DOC = q!P(B("text in bold"), I("text in italic"))!;

     $ELT_CONTENT = q!%%"<$part>" . join('', @_) . "</$part>"%%!;
     $HTML_T3 = new Parse::Template(
          'DOC' => qq!%%$DOC%%!,
          map { $_ => $ELT_CONTENT } qw(P B I)
         );
     print $HTML_T3->eval('DOC'), "\n";

   With a slight transformation it is possible to use a method-invocation
notation:

     $ELT_CONTENT = q!%%shift(@_); "<$part>" . join('', @_) . "</$part>"%%!;
     $HTML_T4 = new Parse::Template(
          map { $_ => $ELT_CONTENT } qw(P B I)
         );
     print $HTML_T4->P(
                       $HTML_T4->B("text in bold"),
                       $HTML_T4->I("text in italic")
                      ), "\n";

   The `shift(@_)' permits getting rid of the template object, which we
don't need within the expression.

   `Parse::Template' was initially created to serve as a code generator
for the `Parse::Lex' class.  You will find other examples of its use in
the classes `Parse::Lex', `Parse::CLex' and `Parse::Token'.

NOTES CONCERNING THE CURRENT VERSION
====================================

   I would be very interested to receive your comments and suggestions.
English documentation isn't up to date.

BUG
===

   Instances are not destroyed.  Therefore, do not use this class to
create a large number of instances.

AUTHOR
======

   Philippe Verdret (with translation of documentation into English by
Ocrat).

COPYRIGHT
=========

   Copyright (c) 1995-2000 Philippe Verdret. All rights reserved.  This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Perl module for parsing plain text files
****************************************

NAME
====

   Parse::Text - Perl module for parsing plain text files

SYNOPSIS
========

     use Parse::Text;

DESCRIPTION
===========

   This is currently a place holder for a very powerful, full feature plain
text parser.

EXPORT
------

   None by default.

AUTHOR
======

   Casey Tweten, <crt@kiski.net>

SEE ALSO
========

   See Perl (perl.info).

Definition of tokens used by `Parse::Lex'
*****************************************

NAME
====

   `Parse::Token' - Definition of tokens used by `Parse::Lex'

SYNOPSIS
========

     require 5.005;

     use Parse::Lex;
     @token = qw(
         ADDOP    [-+]
         INTEGER  [1-9][0-9]*
        );

     $lexer = Parse::Lex->new(@token);
     $lexer->from(\*DATA);

     $content = $INTEGER->next;
     if ($INTEGER->status) {
       print "$content\n";
     }
     $content = $ADDOP->next;
     if ($ADDOP->status) {
       print "$content\n";
     }
     if ($INTEGER->isnext(\$content)) {
       print "$content\n";
     }
     __END__
     1+2

DESCRIPTION
===========

   The `Parse::Token' class and its derived classes permit defining the
tokens used by `Parse::Lex' or `Parse::LexEvent'.

   The creation of tokens can be done by means of the new() or `factory()'
methods.  The `Lex::new()' method of the `Parse::Lex' package indirectly
creates instances of the tokens to be recognized.

   The next() or `isnext()' methods of the `Parse::Token' package permit
interfacing the lexical analyzer with a syntactic analyzer of recursive
descent type.  For interfacing with `byacc', see the `Parse::YYLex'
package.

   `Parse::Token' is included indirectly by means of `use Parse::Lex' or
`use Parse::LexEvent'.

Methods
=======

action
     Returns the anonymous subroutine defined within the `Parse::Token'
     object.

factory LIST
factory ARRAY_REF
     The `factory(LIST)' method creates a list of tokens from a list of
     specifications, which include for each token: a name, a regular
     expression, and possibly an anonymous subroutine.  The list can also
     include objects of class `Parse::Token' or of a class derived from it.

     The `factory(ARRAY_REF)' method permits creating tokens from
     specifications of type attribute-value:

          Parse::Token->factory([Type => 'Simple',
                                 Name => 'EXAMPLE',
                                 Regex => '.+']);

     Type indicates the type of each token to be created (the package
     prefix is not indicated).

     `factory()' creates a series of tokens but does not import these
     tokens into the calling package.

     You could for example write:

          %keywords =
            qw (
                PROC  undef
                FUNC  undef
                RETURN undef
                IF    undef
                ELSE  undef
                WHILE undef
                PRINT undef
                READ  undef
               );
          @tokens = Parse::Token->factory(%keywords);

     and install these tokens in a symbol table in the following manner:

          foreach $name (keys %keywords) {
          	  ${$name} = pop @tokens;
            $symbol{"\L$name"} = [${$name}, ''];
          }

     `${$name}' is the token instance.

     During the lexical analysis phase, you can use the tokens in the
     following manner:

          qw(IDENT [a-zA-Z][a-zA-Z0-9_]*),  sub {
             $symbol{$_[1]} = [] unless defined $symbol{$_[1]};
             my $type = $symbol{$_[1]}[0];
             $lexer->setToken((not defined $type) ? $VAR : $type);
             $_[1];  # THE TOKEN TEXT
           }

     This permits indicating that any symbol of unknown type is a variable.

     In this example we have used `$_[1]' which corresponds to the text
     recognized by the regular expression.  This text associated with the
     token must be returned by the anonymous subroutine.

get EXPR
     get obtains the value of the attribute named by the result of
     evaluating EXPR.  You can also use the name of the attribute as a
     method name.

getText
     Returns the character string that was recognized by means of this
     `Parse::Token' object.

     Same as the text() method.

isnext EXPR
isnext
     Returns the status of the token. The consumed string is put into EXPR
     if it is a reference to a scalar.

name
     Returns the name of the token.

next
     Activate searching for the lexeme defined by the regular expression
     contained in the object. If this lexeme is recognized on the character
     stream to analyze, next returns the string found and sets the status
     of the object to true.

new SYMBOL_NAME, REGEXP, SUB
new SYMBOL_NAME, REGEXP
     Creates an object of type Parse::Token::Simple or
     Parse::Token::Segmented. The arguments of the new() method are,
     respectively: a symbolic name, a regular expression, and possibly an
     anonymous subroutine.  The subclasses of `Parse::Token' permit
     specifying tokens by means of a list of attribute-values.

     REGEXP is either a simple regular expression, or a reference to an
     array containing from one to three regular expressions.  In the first
     case, the instance belongs to the Parse::Token::Simple class.  In the
     second case, the instance belongs to the Parse::Token::Segmented
     class.  The tokens of this type permit recognizing structures of type
     character string delimited by quotation marks, comments in a C
     program, etc.  The regular expressions are used to recognize:

     1. The beginning of the lexeme,

     2. The "body" of the lexeme; if this second expression is missing,
     `Parse::Lex' uses "(?:.*?)",

     3. the end of the lexeme; if this last expression is missing then the
     first one is used. (Note! The end of the lexeme cannot span several
     lines).

     Example:

          qw(STRING), [qw(" (?:[^"\\\\]+|\\\\(?:.|\n))* ")],

     These regular expressions can recognize multi-line strings delimited
     by quotation marks, where the backslash is used to quote the
     quotation marks appearing within the string. Notice the quadrupling of
     the backslash.

     Here is a variation of the previous example which uses the s option
     to include newline in the characters recognized by ".":

          qw(STRING), [qw(" (?s:[^"\\\\]+|\\\\.)* ")],

     (Note: it is possible to write regular expressions which are more
     efficient in terms of execution time, but this is not our objective
     with this example.  See *Mastering Regular Expressions*.)

     The anonymous subroutine is called when the lexeme is recognized by
     the lexical analyzer. This subroutine takes two arguments: `$_[0]'
     contains the token instance, and `$_[1]' contains the string
     recognized by the regular expression. The scalar returned by the
     anonymous subroutine defines the character string memorized in the
     token instance.

     In the anonymous subroutine you can use the positional variables $1,
     $2, etc. which correspond to the groups of parentheses in the regular
     expression.

regexp
     Returns the regular expression of the `Token' object.

set LIST
     Allows marking a token with a list of attribute-value pairs.

     An attribute name can be used as a method name.

setText EXPR
     The value of EXPR defines the character string associated with the
     lexeme.

     Same as the `text(EXPR)' method.

status EXPR
status
     Indicates if the last search of the lexeme succeeded or failed.
     `status EXPR' overrides the existing value and sets it to the value
     of EXPR.

text EXPR
text
     text() returns the character string recognized by means of the token.
     The value of EXPR sets the character string associated with the
     lexeme.

trace OUTPUT
trace
     Class method which activates/deactivates a trace of the lexical
     analysis.

     OUTPUT can be a file name or a reference to a filehandle to which the
     trace will be directed.

Subclasses of Parse::Token
==========================

   Subclasses of the `Parse::Token' class are being defined.  They permit
recognizing specific structures such as, for example, strings within
double-quotes, C comments, etc.  Here are the subclasses which I am
working on:

   Parse::Token::Simple : tokens of this class are defined by means of a
single regular expression.

   Parse::Token::Segmented : tokens of this class are defined by means of
three regular expressions.  Reading of new data is done automatically.

   Parse::Token::Delimited : permits recognizing, for example, C language
comments.

   Parse::Token::Quoted : permits recognizing, for example, character
strings within quotation marks.

   `Parse::Token::Nested' : permits recognizing nested structures such as
parenthesized expressions.  NOT DEFINED.

   These classes are recently created and no doubt contain some bugs.

Parse::Token::Action
--------------------

   Tokens of the Parse::Token::Action class permit inserting arbitrary
Perl expressions within a lexical analyzer.  An expression can be used for
instance to print out internal variables of the analyzer:

   * `$LEX_BUFFER' : contents of the buffer to be analyzed

   * `$LEX_LENGTH' : length of the character string being analyzed

   * `$LEX_RECORD' : number of the record being analyzed

   * `$LEX_OFFSET' : number of characters already consumed since the start
     of the analysis.

   * `$LEX_POS' : position reached by the analysis as a number of
     characters since the start of the buffer.

   The class constructor accepts the following attributes:

   * Name : the name of the token

   * Expr : a Perl expression

   Example :

     $ACTION = new Parse::Token::Action(
                                   Name => 'ACTION',
                                   Expr => q!print "LEX_POS: $LEX_POS\n" .
                                   "LEX_BUFFER: $LEX_BUFFER\n" .
                                   "LEX_LENGTH: $LEX_LENGTH\n" .
                                   "LEX_RECORD: $LEX_RECORD\n" .
                                   "LEX_OFFSET: $LEX_OFFSET\n"
                                   ;!,
                                  );

Parse::Token::Simple
--------------------

   The class constructor accepts the following attributes:

   * Handler : the value indicates the name of a function to call during
     an analysis performed by an analyzer of class `Parse::LexEvent'.

   * Name : the associated value is the name of the token.

   * `Regex' : the associated value is a regular expression corresponding
     to the pattern to be recognized.

   * `ReadMore' : if the associated value is 1, the recognition of the
     token continues after reading a new record.  The strings recognized
     are concatenated.  This attribute only has effect during analysis of a
     character stream.

   * `Sub' : the associated value must be an anonymous subroutine to be
     executed after the token is recognized.  This function is only used
     with analyzers of class `Parse::Lex' or `Parse::CLex'.

   Example.        new Parse::Token::Simple(Name => 'remainder',
                    Regex => '[^/\'\"]+',
ReadMore => 1);

Parse::Token::Segmented
-----------------------

   The definition of these tokens includes three regular expressions.
During analysis of a data stream, new data is read as long as the end of
the token has not been reached.

   The class constructor accepts the following attributes:

   * Handler : the value indicates the name of a function to call during
     analysis performed by an analyzer of class `Parse::LexEvent'.

   * Name : the associated value is the name of the token.

   * `Regex' : the associated value must be a reference to an array that
     contains three regular expressions.

   * `Sub' : the associated value must be an anonymous subroutine to be
     executed after the token is recognized.  This function is only used
     with analyzers of class `Parse::Lex' or `Parse::CLex'.

Parse::Token::Quoted
--------------------

   Parse::Token::Quoted is a subclass of Parse::Token::Segmented.  It
permits recognizing character strings within double quotes or single
quotes.

   Examples.

     ---------------------------------------------------------
      Start    End            Escaping
     ---------------------------------------------------------
       '        '              ''
       "        "              ""
       "        "              \
     ---------------------------------------------------------

   The class constructor accepts the following attributes:

   * End : The associated value is a regular expression permitting
     recognizing the end of the token.

   * Escape : The associated value indicates the character used to escape
     the delimiter.  By default, a double occurrence of the terminating
     character escapes that character.

   * Handler : the value indicates the name of a function to be called
     during an analysis performed by an analyzer of class
     `Parse::LexEvent'.

   * Name : the associated value is the name of the token.

   * Start : the associated value is a regular expression permitting
     recognizing the start of the token.

   * `Sub' : the associated value must be an anonymous subroutine to be
     executed after the token is recognized.  This function is only used
     with analyzers of class `Parse::Lex' or `Parse::CLex'.

   Example.        new Parse::Token::Quoted(Name => 'squotes',
                  Handler => 'string',
Escape => '\\',                                Quote => qq!\'!,
                  );

Parse::Token::Delimited
-----------------------

   Parse::Token::Delimited is a subclass of Parse::Token::Segmented.  It
permits, for example, recognizing C language comments.

   Examples.

     ---------------------------------------------------------
       Start   End     Constraint
                       on the contents
     ---------------------------------------------------------
       /*       */                         C Comment
       <!--     -->      No '--'           XML Comment
       <!--     -->                        SGML Comment
       <?       ?>                         Processing instruction
                                           in SGML/XML
     ---------------------------------------------------------

   The class constructor accepts the following attributes:

   * End : The associated value is a regular expression permitting
     recognizing the end of the token.

   * Handler : the value indicates the name of a function to be called
     during an analysis performed by an analyzer of class
     `Parse::LexEvent'.

   * Name : the associated value is the name of the token.

   * Start : the associated value is a regular expression permitting
     recognizing the start of the token.

   * `Sub' : the associated value must be an anonymous subroutine to be
     executed after the token is recognized.  This function is only used
     with analyzers of class `Parse::Lex' or `Parse::CLex'.

   Example.        new Parse::Token::Delimited(Name => 'comment',
                        Start => '/[*]',
End => '[*]/'                                  );

Parse::Token::Nested - Not defined
----------------------------------

   Examples.

     ----------------------------------------------------------
       Start   End
     ----------------------------------------------------------
       (        )                      Symbolic Expressions
       {        }                      Rich Text Format Groups
     ----------------------------------------------------------

BUGS
====

   The implementation of subclasses of tokens is not complete for
analyzers of the `Parse::CLex' class.  I am not too keen to do it, since
an implementation for classes `Parse::Lex' and `Parse::LexEvent' seems
quite sufficient.

AUTHOR
======

   Philippe Verdret. Documentation translated to English by Vladimir
Alexiev and Ocrat.

ACKNOWLEDGMENTS
===============

   Version 2.0 owes much to suggestions made by Vladimir Alexiev.  Ocrat
has significantly contributed to improving this documentation.  Thanks
also to the numerous persons who have made comments or sometimes sent bug
fixes.

REFERENCES
==========

   Friedl, J.E.F. Mastering Regular Expressions. O'Reilly & Associates
1996.

   Mason, T. & Brown, D. - Lex & Yacc. O'Reilly & Associates, Inc. 1990.

COPYRIGHT
=========

   Copyright (c) 1995-1999 Philippe Verdret. All rights reserved. This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

class for parsing text with embedded tokens
*******************************************

NAME
====

   Parse::Tokens - class for parsing text with embedded tokens

SYNOPSIS
========

     use Parse::Tokens;
     @ISA = ('Parse::Tokens');

     # overide SUPER::token
     sub token
     {
       my( $self, $token ) = @_;
       # $token->[0] - left bracket
       # $token->[1] - contents
       # $token->[2] - right bracket
       # do something with the token...
     }

     # overide SUPER::token
     sub ether
     {
       my( $self, $text ) = @_;
       # do something with the text...
     }

DESCRIPTION
===========

   `Parse::Tokens' provides a base class for parsing delimited strings
from text blocks. Use `Parse::Tokens' as a base class for your own module
or script. Very similar in style to HTML::Parser.

Functions
=========

autoflush()
     Turn on autoflushing causing the template cash (not the text) to be
     purged before each parse();.

delimiters()
     Specify delimiters as an array reference pointing to the left and
     right delimiters. Returns array reference containing two array
     references of delimiters and escaped delimiters.

flush()
     Flush the template cash.

parse()
     Run the parser.

new()
     Pass parameter as a hash reference. Options are: TEXT - a block of
     text; DELIMITERS - a array reference consisting of the left and right
     token delimiters (eg ['<?', '?>']); AUTOFLUSH - 0 or 1 (default).
     While these are all optional at initialization, both TEXT and
     DELIMITERS must be set prior to calling parse() or as parameters to
     parse().

text()
     Load text.

AUTHOR
======

   Steve McKay, steve@colgreen.com

COPYRIGHT
=========

   Copyright 2000 by Steve McKay. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   perl(1).

Visual LALR parser debugger
***************************

NAME
====

   Parse::Vipar - Visual LALR parser debugger

SYNOPSIS
========

   % vipar expr.y [-data=DATAFILE]

   DATAFILE would contain a list of tokens, one per line, with optional
values after them separated by whitespace. Example:

     number
     '+'
     number
     '*'
     number

DESCRIPTION
===========

   Presents a visual display of a LALR parser in action.

AUTHOR
======

   Steve Fink <steve@fink.com>

SEE ALSO
========

   Parse::YALALR

Yet Another LALR parser
***********************

NAME
====

   Parse::YALALR - Yet Another LALR parser

SYNOPSIS
========

     From the command line:
     % yalalr [--lang=c] [--lang=perl] grammar.y

     In a program:
     use Parse::YALALR::Build;
     use Parse::YALALR::Run;

     open(GRAMMAR, "<expr.y") or die "open expr.y: $!";
     $builder = Parse::YALALR::Build->new("perl", \*GRAMMAR);
     $builder->build_table();
     $parser = $builder->{parser};
     @inputstream = ([number=>10], ["'+'"=> undef ], [number=>20]);
     $_->[0] = $parser->{symmap}->get_index($_->[0]) foreach (@inputstream);
     Parse::YALALR::Run::run_parser($parser, \@inputstream);

DESCRIPTION
===========

   Generates an LALR parser from an input grammar. Really just intended as
a companion to Parse::Vipar, but (sorta) works standalone. Does not yet
generate a standalone parser.

   run_parser will also accept a CODE ref to use as a lexer. Every
invocation should return a pair (token, value). The above example is
equivalent to

     $lexer = { my $i = 0; sub {
     			     my ($t,$v)=@{$inputstream[$i++]};
     			     ($parser->get_index($t), $v)
     			   }
     	  };
     Parse::YALALR::Run::run_parser($parser, $lexer);

AUTHOR
======

   Steve Fink <steve@fink.com>

SEE ALSO
========

   Parse::YALALR

version of Parse::Lex to be used by a byacc parser.
***************************************************

NAME
====

   Parse::YYLex - version of Parse::Lex to be used by a byacc parser.

SYNOPSIS
========

   *Parse::Lex* requires this perl version:   require 5.004;   use
Parse::YYLex;

   If using a procedural parser:   Parse::YYLex->create ...; # exports
&yylex and $yylval     # see Parse::Lex for the token table args <...>
Parse::YYLex::lex->from(\*FH);   require 'MyParser.pl';  # generated by
byacc   yyparse();

   If using an object-oriented parser:   $lexer = new Parse::YYLex ...;
# see Parse::Lex for the token table args <...>   use MyParser;  #
generated by byacc5   $parser = new MyParser($lexer->getyylex, \&yyerror,
$debug);                                   # you must write &yyerror
$lexer->from(\*STREAM);   $parser->yyparse(*STREAM);

   To get the token definitions from `MyParser.ph' instead of `y.tab.ph'
or to change the skip regexp (default whitespace), do this before calling
new or create:   Parse::YYLex->ytab('MyParser.ph');
Parse::YYLex->skip(");

DESCRIPTION
===========

   Often times you'd use a lexer in conjunction with a parser.  And most
of the time you'd want to generate that parser with a yacc parser
generator. *Parse::YYLex* is a derivative of *Parse::Lex* compatible with
yacc parsers, by adapting it to the byacc calling conventions:

   * The parser wants to receive integer token types as defined in
     `y.tab.ph' instead of the symbolic types that *Parse::Lex* returns.

   * The parser wants its tokens as two components (type and value),
     whereas *Parse::Lex* returns one object with these two components.
     Furthermore, a procedural parser wants the value stored in a variable
     `$yylval'.

   * The parser wants to receive the tokens by calling a yylex function,
     not an object method. Thus we have to give the parser a curried form
     of the lexer function, where the self argument is fixed.

Procedural Parsers
------------------

   Yacc (and Bison) traditionally generate C or C++ parsers.  Fortunately,
Berkeley yacc has been modified to generate Perl, see
ftp://ftp.sterling.com/local/perl-byacc.tar.Z

   Byacc with the -P option generates procedural perl code that is
compatible with both perl4 and perl5. (However you cannot use
*Parse::YYLex* with perl4.) Use this variant for quick hacks, as it is
more convenient than the one below. In this case `Parse::YYLex-create'>
instantiates a lexer and exports a `&yylex' function (the lexer) and a
`$yylval' variable (the token value) to its caller's namespace (which
should be the namespace of the parser).

   If you need to call any object methods of the created lexer (see
*Parse::Lex* for documentation), use the `$Parse::YYLex::lex' variable.

Object-Oriented Parsers
-----------------------

   Another byacc modification (I call it byacc5) generates object-oriented
Perl5 code:   CPAN/authors/id/JAKE/perl5-byacc-patches-0.5.tar.gz

   Use this variant if you need more than one parser, you need
flexibility, or you simply like OO. In this case you need to use new, and
pass the return value of *getyylex* (a reference to the curried lexing
function) to the parser.  The lexing function returns a two-element array,
the token type and value.

Numeric Token Table
-------------------

   Yacc parsers insist on using numeric token types, and define these in a
file customarily named `y.tab.ph'. That is where *Parse::YYLex* will look
by default, and the file has to be in the @INC path (which includes the
current directory).

   You can specify a different token table before calling new or create:
Parse::YYLex->ytab('MyParser.ph');

LIMITATIONS
===========

   `Parse::YYLex' is based on *Parse::Lex* which requires perl 5.004 and
will not work with earlier versions. A slightly different version,
*Parse::CLex*, works with earlier perl versions. It would be easy to allow
a choice between *Parse::Lex* and *Parse::CLex*, but the latter has some
limitations, and presently seems to have some bugs.

AUTHOR
======

   Vladimir Alexiev <vladimir@cs.ualberta.ca>

SEE ALSO
========

   byacc(1), see Parse/Lex.

Perl extension for generating and using LALR parsers.
*****************************************************

NAME
====

   Parse::Yapp - Perl extension for generating and using LALR parsers.

SYNOPSIS
========

     yapp -m MyParser grammar_file.yp

     ...

     use MyParser;

     $parser=new MyParser();
     $value=$parser->YYParse(yylex => \&lexer_sub, yyerror => \&error_sub);

     $nberr=$parser->YYNberr();

     $parser->YYData->{DATA}= [ 'Anything', 'You Want' ];

     $data=$parser->YYData->{DATA}[0];

DESCRIPTION
===========

   Parse::Yapp (Yet Another Perl Parser compiler) is a collection of
modules that let you generate and use yacc like thread safe (reentrant)
parsers with perl object oriented interface.

   The script yapp is a front-end to the Parse::Yapp module and let you
easily create a Perl OO parser from an input grammar file.

The Grammar file
----------------

Comments
     Through all your files, comments are either Perl style, introduced by
     *#* up to the end of line, or C style, enclosed between  */** and
     **/*.

`Tokens and string literals'
     Through all the grammar files, two kind of symbols may appear:
     *Non-terminal* symbols, called also *left-hand-side* symbols, which
     are the names of your rules, and Terminal symbols, called also Tokens.

     Tokens are the symbols your lexer function will feed your parser with
     (see below). They are of two flavours: symbolic tokens and string
     literals.

     Non-terminals and symbolic tokens share the same identifier syntax:

          [A-Za-z][A-Za-z0-9_]*

     String literals are enclosed in single quotes and can contain almost
     anything. They will be output to your parser file double-quoted,
     making any special character as such. '"', '$' and '@' will be
     automatically quoted with '\', making their writing more natural. On
     the other hand, if you need a single quote inside your literal, just
     quote it with '\'.

     You cannot have a literal *'error'* in your grammar as it would
     confuse the driver with the error token. Use a symbolic token instead.
     In case you inadvertently use it, this will produce a warning telling
     you you should have written it error and will treat it as if it were
     the error token, which is certainly NOT what you meant.

`Grammar file syntax'
     It is very close to yacc syntax (in fact, *Parse::Yapp* should compile
     a clean *yacc* grammar without any modification, whereas the opposite
     is not true).

     This file is divided in three sections, separated by `%%':

          header section
          %%
          rules section
          %%
          footer section

    *The Header Section* section may optionally contain:

          One or more code blocks enclosed inside `%{' and `%}' just like
          in yacc. They may contain any valid Perl code and will be copied
          verbatim at the very beginning of the parser module. They are
          not as useful as they are in yacc, but you can use them, for
          example, for global variable declarations, though you will
          notice later that such global variables can be avoided to make a
          reentrant parser module.

          Precedence declarations, introduced by `%left', `%right' and
          `%nonassoc' specifying associativity, followed by the list of
          tokens or litterals having the same precedence and associativity.
          The precedence beeing the latter declared will be having the
          highest level.  (see the yacc or bison manuals for a full
          explanation of how they work, as they are implemented exactly
          the same way in Parse::Yapp)

          `%start' followed by a rule's left hand side, declaring this
          rule to be the starting rule of your grammar. The default, when
          `%start' is not used, is the first rule in your grammar section.

          `%token' followed by a list of symbols, forcing them to be
          recognized as tokens, generating a syntax error if used in the
          left hand side of a rule declaration.  Note that in Parse::Yapp,
          you *don't* need to declare tokens as in yacc: any symbol not
          appearing as a left hand side of a rule is considered to be a
          token.  Other yacc declarations or constructs such as `%type'
          and `%union' are parsed but (almost) ignored.

          `%expect' followed by a number, suppress warnings about number
          of Shift/Reduce conflicts when both numbers match, a la bison.

    *The Rule Section* contains your grammar rules:
          A rule is made of a left-hand-side symbol, followed by a ':' and
          one or more right-hand-sides separated by '|' and terminated by
          a `';'':

               exp:    exp '+' exp
                   |   exp '-' exp
                   ;

          A right hand side may be empty:

               input:  #empty
                   |   input line
                   ;

          (if you have more than one empty rhs, Parse::Yapp will issue a
          warning, as this is usually a mistake, and you will certainly
          have a reduce/reduce conflict)

          A rhs may be followed by an optional `%prec' directive, followed
          by a token, giving the rule an explicit precedence (see yacc
          manuals for its precise meaning) and optionnal semantic action
          code block (see below).

               exp:   '-' exp %prec NEG { -$_[1] }
                   |  exp '+' exp       { $_[1] + $_[3] }
                   |  NUM
                   ;

          Note that in Parse::Yapp, a lhs *cannot* appear more than once as
          a rule name (This differs from yacc).

    `The footer section'
          may contain any valid Perl code and will be appended at the very
          end of your parser module. Here you can write your lexer, error
          report subs and anything relevant to you parser.

    `Semantic actions'
          Semantic actions are run every time a *reduction* occurs in the
          parsing flow and they must return a semantic value.

          They are (usually, but see below `In rule actions') written at
          the very end of the rhs, enclosed with `{ }', and are copied
          verbatim to your parser file, inside of the rules table.

          Be aware that matching braces in Perl is much more difficult than
          in C: inside strings they don't need to match. While in C it is
          very easy to detect the beginning of a string construct, or a
          single character, it is much more difficult in Perl, as there
          are so many ways of writing such literals. So there is no check
          for that today. If you need a brace in a double-quoted string,
          just quote it (`\{' or `\}'). For single-quoted strings, you
          will need to make a comment matching it *in th right order*.
          Sorry for the inconvenience.

               {
                   "{ My string block }".
                   "\{ My other string block \}".
                   qq/ My unmatched brace \} /.
                   # Force the match: {
                   q/ for my closing brace } /
                   q/ My opening brace { /
                   # must be closed: }
               }

          All of these constructs should work.

          In Parse::Yapp, semantic actions are called like normal Perl sub
          calls, with their arguments passed in `@_', and their semantic
          value are their return values.

          $_[1] to $_[n] are the parameters just as $1 to $n in yacc, while
          $_[0] is the parser object itself.

          Having $_[0] beeing the parser object itself allows you to call
          parser methods. Thats how the yacc macros are implemented:

               yyerrok is done by calling $_[0]->YYErrok
               YYERROR is done by calling $_[0]->YYError
               YYACCEPT is done by calling $_[0]->YYAccept
               YYABORT is done by calling $_[0]->YYAbort

          All those methods explicitly return undef, for convenience.

               YYRECOVERING is done by calling $_[0]->YYRecovering

          Four useful methods in error recovery sub

               $_[0]->YYCurtok
               $_[0]->YYCurval
               $_[0]->YYExpect
               $_[0]->YYLexer

          return respectivly the current input token that made the parse
          fail, its semantic value (both can be used to modify their
          values too, but *know what you are doing* ! See *Error reporting
          routine* section for an example), a list which contains the
          tokens the parser expected when the failure occured and a
          reference to the lexer routine.

          Note that if `$_[0]->YYCurtok' is declared as a `%nonassoc'
          token, it can be included in `$_[0]->YYExpect' list whenever the
          input try to use it in an associative way. This is not a bug:
          the token IS expected to report an error if encountered.

          To detect such a thing in your error reporting sub, the following
          example should do the trick:

               grep { $_[0]->YYCurtok eq $_ } $_[0]->YYExpect
                   and do {
               #Non-associative token used in an associative expression
                   };

          Accessing semantics values on the left of your reducing rule is
          done through the method

               $_[0]->YYSemval( index )

          where index is an integer. Its value being *1 .. n* returns the
          same values than *$_[1] .. $_[n]*, but *-n .. 0* returns values
          on the left of the rule beeing reduced (It is related to *$-n ..
          $0 .. $n* in yacc, but you cannot use *$_[0]* or *$_[-n]*
          constructs in Parse::Yapp for obvious reasons)

          There is also a provision for a user data area in the parser
          object, accessed by the method:

               $_[0]->YYData

          which returns a reference to an anonymous hash, which let you
          have all of your parsing data held inside the object (see the
          Calc.yp or ParseYapp.yp files in the distribution for some
          examples).  That's how you can make you parser module reentrant:
          all of your module states and variables are held inside the
          parser object.

          Note: unfortunatly, method calls in Perl have a lot of overhead,
               and when YYData is used, it may be called a huge number
            of times. If your are not a *real* purist and efficiency
          is your concern, you may access directly the user-space
          in the object: $parser->{USER} wich is a reference to an
          anonymous hash array, and then benchmark.

          If no action is specified for a rule, the equivalant of a default
          action is run, which returns the first parameter:

               { $_[1] }

    `In rule actions'
          It is also possible to embed semantic actions inside of a rule:

               typedef:    TYPE { $type = $_[1] } identlist { ... } ;

          When the Parse::Yapp's parser encounter such an embedded action,
          it modifies the grammar as if you wrote (although @x-1 is not a
          legal lhs value):

               @x-1:   /* empty */ { $type = $_[1] };
               typedef:    TYPE @x-1 identlist { ... } ;

          where x is a sequential number incremented for each "in rule"
          action, and *-1* represents the "dot position" in the rule where
          the action arises.

          In such actions, you can use *$_[1]..$_[n]* variables, which are
          the semantic values on the left of your action.

          Be aware that the way Parse::Yapp modifies your grammar because
          of *in rule actions* can produce, in some cases, spurious
          conflicts that wouldn't happen otherwise.

    `Generating the Parser Module'
          Now that you grammar file is written, you can use yapp on it to
          generate your parser module:

               yapp -v Calc.yp

          will create two files `Calc.pm', your parser module, and
          `Calc.output' a verbose output of your parser rules, conflicts,
          warnings, states and summary.

          What your are missing now is a lexer routine.

    `The Lexer sub'
          is called each time the parser need to read the next token.

          It is called with only one argument that is the parser object
          itself, so you can access its methods, specially the

               $_[0]->YYData

          data area.

          It is its duty to return the next token and value to the parser.
          They must be returned as a list of two variables, the first one
          is the token known by the parser (symbolic or literal), the
          second one beeing anything you want (usualy the content of the
          token, or the literal value) from a simple scalar value to any
          complex reference, as the parsing driver never use it but to
          call semantic actions:

               ( 'NUMBER', $num )
               or
               ( '>=', '>=' )
               or
               ( 'ARRAY', [ @values ] )

          When the lexer reach the end of input, it must return the "
          empty token with an undef value:

               ( '', undef )

          Note that your lexer should never return `'error'' as token
          value: for the driver, this is the error token used for error
          recovery and would lead to odd reactions.

          Now that you have your lexer written, maybe you will need to
          output meaningful error messages, instead of the default which
          is to print 'Parse error.' on STDERR.

          So you will need an Error reporting sub.

          item `Error reporting routine'

          If you want one, write it knowing that it is passed as parameter
          the parser object. So you can share information whith the lexer
          routine quite easily.

          You can also use the `$_[0]->YYErrok' method in it, which will
          resume parsing as if no error occured. Of course, since the
          invalid token is still invalid, you're supposed to fix the
          problem by yourself.

          The method `$_[0]->YYLexer' may help you, as it returns a
          reference to the lexer routine, and can be called as

               ($tok,$val)=&{$_[0]->Lexer}

          to get the next token and semantic value from the input stream.
          To make them current for the parser, use:

               ($_[0]->YYCurtok, $_[0]->YYCurval) = ($tok, $val)

          and know what you're doing...

    Parsing
          Now you've got everything to do the parsing.

          First, use the parser module:

               use Calc;

          Then create the parser object:

               $parser=new Calc;

          Now, call the YYParse method, telling it where to find the lexer
          and error report subs:

               $result=$parser->YYParse(yylex => \&Lexer,
                                      yyerror => \&ErrorReport);

          (assuming Lexer and ErrorReport subs have been written in your
          current package)

          The order in which parameters appear is unimportant.

          Et voila.

          The YYParse method will do the parse, then return the last
          semantic value returned, or undef if error recovery cannot
          recover.

          If you need to be sure the parse has been successful (in case
          your last returned semantic value *is* undef) make a call to:

               $parser->YYNberr()

          which returns the total number of time the error reporting sub
          has been called.

    `Error Recovery'
          in Parse::Yapp is implemented the same way it is in yacc.

    `Debugging Parser'
          To debug your parser, you can call the YYParse method with a
          debug parameter:

               $parser->YYParse( ... , yydebug => value, ... )

          where value is a bitfield, each bit representing a specific
          debug output:

               Bit Value    Outputs
               0x01         Token reading (useful for Lexer debugging)
               0x02         States information
               0x04         Driver actions (shifts, reduces, accept...)
               0x08         Parse Stack dump
               0x10         Error Recovery tracing

          To have a full debugging ouput, use

               debug => 0x1F

          Debugging output is sent to STDERR, and be aware that it can
          produce `huge' outputs.

    `Standalone Parsers'
          By default, the parser modules generated will need the
          Parse::Yapp module installed on the system to run. They use the
          Parse::Yapp::Driver which can be safely shared between parsers
          in the same script.

          In the case you'd prefer to have a standalone module generated,
          use the -s switch with yapp: this will automagically copy the
          driver code into your module so you can use/distribute it
          without the need of the Parse::Yapp module, making it really a
          `Standalone Parser'.

          If you do so, please remember to include Parse::Yapp's copyright
          notice in your main module copyright, so others can know about
          Parse::Yapp module.

    `Source file line numbers'
          by default will be included in the generated parser module,
          which will help to find the guilty line in your source file in
          case of a syntax error.  You can disable this feature by
          compiling your grammar with yapp using the -n switch.

BUGS AND SUGGESTIONS
====================

   If you find bugs, think of anything that could improve Parse::Yapp or
have any questions related to it, feel free to contact the author.

AUTHOR
======

   Francois Desarmenien  <francois@fdesar.net>

SEE ALSO
========

   yapp(1) perl(1) yacc(1) bison(1).

COPYRIGHT
=========

   The Parse::Yapp module and its related modules and shell scripts are
copyright (c) 1998-2001 Francois Desarmenien, France. All rights reserved.

   You may use and distribute them under the terms of either the GNU
General Public License or the Artistic License, as specified in the Perl
README file.

   If you use the "standalone parser" option so people don't need to
install Parse::Yapp on their systems in order to run you software, this
copyright noticed should be included in your software copyright too, and
the copyright notice in the embedded driver should be left untouched.

engine for bringing any text documents alive with bits of embedded Perl
***********************************************************************

NAME
====

   Text::iPerl - engine for bringing any text documents alive with bits of
embedded Perl

SYNOPSIS
========

     use Text::iPerl;
     include 'documentname';

   or

     perl -MText::iPerl -e include <infile >outfile

   See `iperl' in this node for a far more comfortable command-line variant

DESCRIPTION
===========

   This is the engine of an inverse Perl interpreter, which controls
normal text with macro invocations and specially marked bits of Perl.
This setup of the document is always the same, though details may vary
according to the style in effect.  (See set_style.)  The engine is invoked
with include, or its variants include_filehandle and include_string.  It
treats a given document in two phases, with two or three aspects:

Markup Style
------------

   Bits of Perl to be evaluated have to be specially marked up as such.
How this is done differs greatly depending on the style in effect.  But
apart from different syntaxes there are only two fundamental ways in which
Perl can be embedded: non-printing and printing.  Not all styles provide
both ways.  The difference between these two ways is to be seen as
default-functionality and is not restrictive.  Non-printing Perl may very
well use the print statement, or system-commands to output something via
STDOUT into the output stream.  If system-commands are used you should
first turn on autoflushing (`$| = 1') to ensure that output order is
preserved.

Perl
----

   The whole document is actually reinverted or transformed into a
Perl-programme, where each bit of normal text gets transformed into a
semicolon-terminated Perl-statement.  The markup around bits of
non-printing Perl simply gets removed and a terminating semicolon added,
which almost never hurts.  If you want a bit of non-printing Perl to
control the preceding or following bit of normal text, you can prevent the
semicolon by starting or ending the Perl code with `\;'.  You can delimit
the bit of normal text with a bit of non-printing Perl containing only a
semicolon.

   Printing bits of Perl, on the other hand, get passed as an argument
list to a print statement, or to printf, if it starts with %.  If a
printing bit of Perl is empty, $_ is printed.  If it is a literal integer,
`$_[*n*]' is printed.

   There are several interesting things you can do with syntactically
incomplete bits of Perl.  You can seal the fate of the following bit of
plain text by preceding it with an expression followed by and or or and
terminated with `\;'.  Or you can have dangling curly braces of an
`if-elsif-else'-statement.  They might also be of a loop, which will likely
contain one or more printing bits of Perl.

   Dangling curly braces may even be of a sub, which will then print the
contained plain text when called.  Likewise they may be of an anonymous sub
which could be the second argument to define.

   There are no syntactic extensions to Perl, just a couple of variables
and functions like include or define.

Macros
------

   Normal text gets output as is, unless we have macro-definitions.  If
macros are defined, at runtime every bit of normal text gets repeatedly
scanned for macros, which are expanded until no more macro invocations are
found, i.e. macro expansions occur depth-first.  Macros are functions
returning a string.  If they also print something, that comes in the
output stream before the returned string and is not subject to repeated
scanning.  Scanning starts again where the last macro was found, so if a
macro returns what might be the second part of a macro name together with
the preceding text, that is not found.  (See define, undefine & macro.)

   Macro invocations consist of the macro name, a string of letters,
digits and underscores, optionally usually immediately followed by a
parenthesized Perl parameter list.  Note that even if the macro is
surrounded by a bit of Perl with a my-variable, that variable will not be
visible, since macro invocations are evaluated later, not seen at compile
time.  Depending on the style, macro invocations may be surrounded by
additional syntactic sugar.  (See $macro_start and friends.)

@EXPORT
=======

   Text::iPerl exports the following functions by default:

   include, include_string, include_filehandle, define, undefine, macro

@EXPORT_OK
----------

   Text::iPerl optionally exports the following function and variables:

   set_style, $cache, $comment_level, debug, %debug, $documents,
`@documents', $joiner, $macro_end, $macro_name_end, $macro_start,
$macro_start_dollar1, $max_macro_growth, $max_macro_expansions, $printfer,
%trace

FUNCTIONS
=========

debug WHEN, STRING
debug WHEN, CODEREF
define STRING, EXPR
define STRING
define
     Defines a macro whose value may be interpolated into bits of plain
     text in scalar context.  STRING or $_ should be a string consisting
     of letters, digits and underscores, which is the name of the macro.
     EXPR is the body of the macro.  If it is a reference to a function
     the macro interpolation will call that.  If it is a string-reference
     the macro is an alias to that macro or to that Perl-builtin, which
     doesn't allow a function reference to be taken.  If it is missing,
     the macro is a soft reference to a Perl-function of the same name.

     If the second argument is a string (should be single-quoted), its
     variables will be interpolated at the moment the macro gets called.
     The macro arguments may of course be accessed as `'... $_[0] ...
     $_[1] ...'', but there is a more comfortable possibility.  The first
     argument to define may contain parameter specifications in
     parentheses after the name.  These are a comma separated list of
     scalar variables with optionally a list variable at the end.  Each of
     these variables may be assigned to, giving the named parameter a
     default value.

     For styles like `cpp' which don't allow embedding Perl-expressions
     into the document, you can use any one of the following to get a
     Perl-evaluating macro:

          define PERL => '@_';
          define 'PERL( $eval = $_ )', '$eval';
          define PERL => sub { $_[0] };
          define PERL => sub { print $_[0]; '' };

     The first allows multiple arguments, to be separated by $".  The
     second gives a Perl-typical default argument of $_.  The third simply
     evaluates one argument.  The fourth does the same, but, the value
     being printed, it will not be reparsed for further macro-invocations.

include EXPR, *REPEATCOUNT*, *HUSH*
include EXPR, *REPEATCOUNT*
include EXPR
include
     Includes a document, parsing it as iPerl and merging the result into
     the current output.  EXPR works just like in open.  If no filename is
     given, reads from STDIN.  If filename is not a full path, then if
     called from within a known file, the file is searched in the
     directory of that document, else in the current directory.  If it is
     not found there, the directories in `@opt_I' followed by those in
     `@include' are searched, unless filename starts with `./'.

     The second argument may be an integer (often 1), meaning to include
     the file only if that filename hasn't already been included that many
     times.  Since this can be fooled by multiple links to the same file,
     or if you use chdir, the second argument may also be a reference to
     an integer (e.g. \1).  In that case the physical identity of the file
     is used, rather than the filename.

     The third argument, when true, means to continue silently when the
     file was not found.

     Note that include is simply a Perl function, thus a run-time affair.
     This means that if you define any functions within the included
     document, they are not known within the including one.  You can
     either mark them as such for the compiler (ampersand and/or parens)
     or you can place the include statement within a `BEGIN {}' block.

include_filehandle *FILEHANDLE*
     Likewise, but reads from the *FILEHANDLE*.

          #! /usr/local/bin/perl
          use Text::iPerl;
          include_filehandle DATA;
          __END__
          Self-parsing iPerl document goes here.

include_string EXPR
include_string
     Likewise, but parses EXPR or $_ if none.

macro STRING
macro
     Returns undef or the macro-definition of STRING, either as a
     code-reference, or the name as a string if the macro is a soft
     reference to a Perl function.  Without an argument returns the list
     of defined macro-names.

          if( defined macro 'mymacro' ) { ... }
          foreach( macro ) { ... }

return
     The normal Perl keyword, returns from a document when used at its
     top-level, i.e. outside of functions, macros or macro invocations,
     save for the m4-style pseudo-macros.  This means, that the rest of
     the document is not processed and output.

set_style STRING[, *ARGUMENT* ...]
set_style CODEREF
     Set one of the following iPerl-styles.  The various styles are more
     or less adapted to various document types.  But of course any style
     can be used anywhere.  Sometimes this requires some extra care, for
     example HTML documents may contain the sequence `!<' which can lead
     to startling effects when used with the bang style.

     It can sometimes be useful to have two different styles in a
     document, for example if you want to do some time-consuming offline
     treatment in a document that will nevertheless later be an active
     web-document.

     The macro invocation style is the only one to be immediately
     effective, being a runtime affair.  The styles for embedded bits of
     Perl, being a compiletime affair, only become effective for the next
     iPerl-documents to be included.

     The mnemonic for the variously used `{...}' is a Perl block, though
     here it is simply a stretch of interpolated Perl code, that does not
     define a block.  The mnemonic for `<...>' is a Perl input operator,
     but inverted here, since the document reads from Perl code.  STRING
     may be one of the following:

    'bang'
    'unix'
          Everything on the same line after `#' is deleted depending on
          $comment_level.

          Lines starting with a ! are bits of Perl.  This reminds of
          interactive unix programs which thus allow a shell escape.

          Perl within lines, potentially spanning several lines, is
          enclosed in `!{' and `}!'.  This reminds of Perl blocks, but
          does not delimit a block.  As a special case `!}!' without
          whitespace is equivalent to `!{}}!', i.e. one closing brace.

          Perl values to be printed to the document are enclosed in `!<'
          and `>!'.  This reminds of the Perl read operator, inverted here
          in that the document reads from a Perl expression.

          Macros may be optionally preceded by &, useful to set them off
          from preceding alphanumeric characters.

    'control'
          Lines starting with a `^A' are bits of Perl.  This reminds of
          the beginning of the alphabet, hence of the line.

          Perl within lines, potentially spanning several lines, is
          enclosed in `^B' and `^E'.  This reminds of beginning and end.

          Perl values to be printed to the document are enclosed in `^P'
          and `^E'.  This reminds of print and end.

    'cpp'
          Everything on the same line after `//' or from `/*' upto next
          `*/' is deleted depending on $comment_level.

          Lines starting with a `#' are bits of Perl.  They may be
          continued over several lines, as long as each line ends with a \.

    generic => *COMMENT*, *BEFOREPRINT*, *AFTERPRINT*, *BEFORE*, *AFTER*
          Arguments are 5 regexps, which may not make backreferences via
          parentheses.  This allows you to define your own simple style.
          Anything matching *COMMENT* is simply ignored.  *BEFOREPRINT*
          and *AFTERPRINT* markup a printing bit of Perl.  And *BEFORE*
          and *AFTER* markup a plain bit of Perl.

    'm4'
          Perl within lines, potentially spanning several lines, is
          enclosed in the pseudo-macro `perl({' and `})'.  This reminds of
          Perl blocks, but does not delimit a block.  As a special case
          `perl(})' without whitespace is equivalent to `perl({}})', i.e.
          one closing brace.

          Perl values to be printed to the document are enclosed in the
          pseudo-macro `perl(<' and `>)'.  This reminds of the Perl read
          operator, inverted here in that the document reads from a Perl
          expression.

          Everything from the pseudo-macro `dnl' through end of line is
          deleted.

          The customary m4 macros `decr', define (iPerl semantics), `defn',
          `errprint', eval, `ifdef', `ifelse', include (iPerl semantics),
          `incr', index, len, `maketemp', `m4exit', `sinclude', substr,
          `syscmd', `sysval', `traceoff', `traceon', `translit' (with an
          additional optional 4th argument for the modifiers of tr) and
          undefine are predefined.

          The customary m4 macros `changecom', `changequote', `divert',
          `divnum', `dumpdef', `m4wrap', `popdef', `pushdef', shift and
          `undivert' are not implemented.

          No macro expansion takes place after a `#'.  This could be
          changed with $macro_start and friends, but note that the above
          mentioned pseudo-macros are already expanded at compile-time.
          Changing this within the document would lead to two different
          comment-styles being used.

          Remember that macro arguments are Perl code, not just bits of
          quoted or unquoted string.

    pod => ARG
    'pod'
          This style can do two things with files containing pod (plain old
          documentation).  For one thing, if ARG is true, it can eliminate
          any pod from document.  It then does nothing else.  This allows
          pod to reside in any file.

          For another, if ARG is missing or false, the pod is extracted
          from the file, processed with embedded Perl, allowing pods to be
          dynamic and spread across several files.  The Perl embedded
          within the pod has nothing to do with the programme that
          contains the pod, even if that is a Perl programme.  This is
          because, from a pod-point-of-view, everything that is not pod is
          ignored.

          Paragraphs starting with `=for perl' or multiple paragraphs
          surrounded by `=begin perl' and `=end perl' contain plain Perl
          code that can control the pod.

          Perl within paragraphs, is enclosed in `P<{' and `}>'.  This
          reminds of Perl blocks, but does not delimit a block.  As a
          special case `P<}>' without whitespace is equivalent to `P<{}}>',
          i.e. one closing brace.

          Perl values to be printed to the document are enclosed in `P<'
          and `>'.  This reminds of the Perl read operator, inverted here
          in that the document reads from a Perl expression.

          `M<' and `>' delimit a macro call within a paragraph.

    'xml'
    'sgml'
          Everything from `<!--' upto next `-->' is deleted depending on
          $comment_level.

          Bits of Perl are enclosed in `<script runat=server>' and
          `</script>' or `<server>' and `</server>'.  Attributes, such as
          `language=Perl' are ignored but recomended to prevent
          mistreatment by other parsers.  More general alternate tags are
          `<perl>' and `</perl>'.  As a more convenient (though probably
          not XML or SGML compliant) alternative, closer to the other
          iPerl-styles, bits of Perl may be enclosed in `<{' and `}>'.  As
          a special case `<}>' without whitespace is equivalent to
          `<{}}>', i.e. one closing brace.  The alternatives are likely not
          recognized by WISIWYG-HTML editors, not being proper HTML, and
          even the server tag might be a Netscape feature, which other
          editors cannot handle.  Even the `script' tag can be problematic
          since it may conditionally include one stretch of text or
          another, which cannot be done with Javascript, thus confusing an
          editor which unconditionally sees both stretches of text.

          Perl values to be printed to the document are enclosed in `&<'
          and `>;'.  This reminds of the Perl read operator, inverted here
          in that the document reads from a Perl expression.  Alternately,
          only within `<' and `>' (actually `<' is not checked for, due to
          the forward looking nature of the parser, but should anyway be
          present before any `>'), Perl values to be printed to the
          document are enclosed in a pair of ``'.  When this is not
          followed by a = the result is surrounded with double quotes.

          Entities (iPerl macros) are enclosed in & and `;'.  If the
          enclosed text is not a defined macro, it is left as an XML
          entity.

    CODEREF
          *NOTE: Since the parsing of a document has to be made more
          efficient, the way this CODEREF works will be totally changed in
          the future.*

          Sets a function and returns the old one, which may have been a
          builtin one.

          The function gets four arguments, 0) a string containing the yet
          unparsed rest of the document, 1) a subregexp to match a
          beginning of line, 2) a subregexp to put before a comment
          matcher and 3) a subregexp to put after a comment matcher.  The
          regexps are only relevant if your style cares about beginnings
          of line or comments.  The comment regexps are provided depending
          on $comment_level.  Regexps 1) and 2) also depend on whether the
          last match (optional 5th return value, see below) ended with a
          newline.  Otherwise the beginning of string will not match a
          beginning of line.

          It gets called repeatedly during parsing of a document and
          should return a list of 4 or 5 elements: 0) leading plain text,
          1) printing Perl expr, 2) plain Perl, 3) the rest to be treated
          next time and optionally 4) the matched string or at least its
          last character.  Those elements not matching anything should be
          undef, epsecially 1) since if it is the empty string, $_ will
          get printed at that point.  When it returns undef as the rest,
          it won't get called again for that document.

undefine EXPR
undefine
     Removes the definedness of EXPR or $_.

VARIABLES
=========

@autostyle_by_contents
     Hash-like list of regexps to match against document to determine the
     mode to use when $style starts with `'auto''.  Unlike a hash, this
     list is processed sequentially until a match is found.

@autostyle_by_name
     Hash-like list of regexps to match against filenames (actually against
     `$documents[-1]') to determine the mode to use when $style starts with
     `'auto''.  Unlike a hash, this list is processed sequentially until a
     match is found.

$cache
     Make include cache the compiled form of the document for quick reuse
     when called again for the same file if `true'.

     Due to a Perl-bug with nested closures, source code, rather than byte
     code, is cached when it contains the word sub.

$comment_level
     What to do with comments in a document when compiling it.  Concerns
     comments in the host part (like `/* ... */' in style cpp), not Perl
     comments.  Values are:

     0:  Do not touch comments in document.

     1:  Remove comments in document, when they go exactly from a
     beginning of line to an end of line.

     2:  Like 1, but there may be whitespace before the comment start or
     after the comment end.

     3:  Remove all comments in document.

     This may be hairy, since iPerl has no knowledge of the host
     document's syntax and will remove everything that looks like a
     comment.  In Perl or Korn shell, for example, `#' does not start a
     comment in all syntactic contexts.  Or a C programme might contain
     `/* ... */' within a string.  So this variable defaults to 1, which
     is fairly safe.

%debug
     Perform debugging for all flags associated with a true value:

          c   generated Perl code
          E   show intern evaluations
          F   say current input file fullname
          f   say current input file basename
          i   say calls to include-functions
          L   say location where debugger was called internally
          p   show searching files in @include
          t   trace for all macro calls, not only those in %trace
          V   automatically implies any other letter

     The following flags are only relevant if t is set or for macros in
     %trace:

          a   show actual arguments
          e   show expansion

     You can add any other letter if you intend to use it in your own
     calls to debug.

$documents
     Incremented for each document included.

@documents
     Contains the list of all nested includes currently active, innermost
     last.  Where a filename is not known for the document, contains the
     strings `'<FILEHANDLE>'', `'<STDIN>'' or `'<STRING>''.

@include
     Second list of directories where include searches for files not found
     in the same directory as the file where include was called.  Defaults
     to `/usr/include' followed by the contents of `@INC'.

$joiner
     Regexp (defaults to `\;') to match what must be at the beginning or
     end of a bit of Perl to suppress the semicolon at that point.

$macro_end
$macro_name_end
$macro_start

$macro_start_dollar1
     $macro_start, $macro_name_end and $macro_end are regexps describing
     the syntactic sugar which is eliminated around macro invocations.
     If, as in style m4, $macro_start has to look backwards, it should
     contain one paren-pair matching the portion of text not to discard,
     and $macro_start_dollar1 should then be true.  These change every
     time a set_style is called explicitly or implicitly.

     If $macro_start and $macro_name_end don't contain the regexp `\b',
     macros will be found in the middle of words.  Or you can use the
     latter variable to allow whitespace before the argument list, or
     prevent it alltogether with a negative lookahead for a parenthesis.

$max_macro_growth
     One bit of plain text may grow by no more than this factor through
     macro expansions.

$max_macro_expansions
     In one bit of plain text no more than this many macro expansions may
     occur.

@opt_I
     First list of directories where include searches for files not found
     in the same directory as the file where include was called.  This is
     not set by `Text::iPerl' but is used if set outside.  The strange
     name comes from the fact that `iperl' like the various invokers of
     the C preprocessor and some m4 implementations use the -I option for
     this.

$preoutput_handler
     *Not yet implemented.*

     Coderef called and reset every time iPerl wants to output a bit of
     plain text.  Will normally be set by programmes to offer some
     initialization that can be overridden by the beginning of a document.

$printfer
     Regexp (defaults to %) to match what must be at the beginning of a
     printing bit of Perl to use printf instead of print.

$style
     This is the name of the style currently in effect.  If this starts
     with `'auto'', the style used for an included document is determined
     in three steps as follows.  This variable is then set to `auto:
     *style*'.

    Style specified in the file
          This is identical to Emacs' local variables specification inside
          a file. There are two possibilities (here shown for style bang):
          On the first line, or on the second if the first line is a
          shebang magic number (`#! *interpreter*'), with possibly other
          semicolon separated variables for use by Emacs:

               -*- iPerl-style: "bang" -*-

          Or, within the last 3000 characters of the document and not
          followed by a page break (`^L'), `/*' and `*/' being examples of
          optional comment delimiters, which, if present, must however be
          identical on all lines, with possibly other specification-lines
          only used by Emacs:

               /* Local Variables: */
               /* iPerl-style: "bang" */
               /* End: */

          The style must be given as a double-quoted literal string.  This
          can appear anywhere, i.e. in a bit of Perl as a comment or
          string or in the host document.  If neither of these appear the
          next step is tried.

    Document-name matched against `@autostyle_by_name'
          If no match is found, the next step is tried.

    Document-contents matched against `@autostyle_by_contents'
          If no match is found, the style of the including document is
          maintained.  If there is none, we die.

@_Text_iPerl
     Closure needed for internal purposes visible within your document.
     The effects of changing this variable are not defined.

%trace
     Debug macro operations for all macros who's name is associated with a
     true value, irrespective of the flags in %debug.

SEE ALSO
========

   `iperl' in this node, `web-iPerl' in this node, `iPerl.el' in this
node, see Perl (perl.info), http://beam.to/iPerl/

Perl module for manipulating a password file stored in a BerkeleyDB hash
************************************************************************

NAME
====

   Passwd::DB - Perl module for manipulating a password file stored in a
BerkeleyDB hash

SYNOPSIS
========

     use Passwd::DB;

     $db = Passwd::DB->new("/usr/local/databases/db_ftp_users");
     $db = Passwd::DB->new("/usr/local/databases/db_ftp_users", 'create');
     @info = $db->getpwnam('bob');
     @info = $db->getpwuid('100');
     @minfo = $db->mgetpwnam('bob');
     $err = $db->modpwinfo(@minfo);
     $err = $db->setpwinfo(@minfo);
     $err = $db->rmpwnam('bob');

     use Passwd::DB qw(init_db getpwnam getpwuid mgetpwnam modpwinfo setpwinfo rmpwnam);

     Passwd::DB->init_db("/usr/local/databases/db_ftp_users");
     Passwd::DB->init_db("/usr/local/databases/db_ftp_users", 1);
     init_db("/usr/local/db_bob",1);
     @info = getpwnam('bob');
     @info = getpwuid('100');
     @minfo = mgetpwnam('bob');
     $err = modpwinfo(@minfo);
     $err = setpwinfo(@minfo);
     $err = rmpwnam('bob');

DESCRIPTION
===========

   Passwd::DB provides basic password routines.  It augments getpwnam and
getpwuid functions with setpwinfo, modpwinfo, rmpwnam, mgetpwnam.  The
routines can be used both in object context or straight.  When used in
non-object context a call to init_db is required to initialize the global
data base structure.  This does mean that you can have only one active
database when used in non-object context.

   new and init_db can be called with an optional second argument.  If it
is set to 1 or 'create' the database will be created if it doesn't already
exist.

   getpwnam and getpwuid are the same as their respective core
counterparts.

   setpwinfo and modpwinfo are called with arrays containing (in order):
name, crypted_password, uid, gid, gecos, home_directory, shell

   rmpwnam is called with a scalar containing the login name.

   mgetpwnam returns the same array that getpwnam returns without the
'unused' age or comment fields.

   setpwinfo does a create/modify of the user.  modpwinfo only does a
modify, it will return an error if the user doesn't exist.

   rmpwnam removes the user with the given login.  It returns an error if
the user doesn't exist.

   Right now all functions croak when they can't open the database.  This
will change if the majority of people don't like this behavior.

   Error return values:   < 0   system error occurred, error value should
be in $!      0   no error     1   operation failed     2   operation
failed because user does not exist

Exported functions on the OK basis
==================================

     getpwnam
     getpwuid
     mgetpwnam
     modpwinfo
     setpwinfo
     rmpwnam
     init_db

AUTHOR
======

   Eric Estabrooks, eric@urbanrage.com

SEE ALSO
========

   perl(1).

Perl module for manipulating the passwd and shadow files
********************************************************

NAME
====

   Passwd::Linux - Perl module for manipulating the passwd and shadow files

SYNOPSIS
========

     use Passwd::Linux qw(modpwinfo setpwinfo rmpwnam mgetpwnam);

     $err = modpwinfo(@info);
     $err = setpwinfo(@info);
     $err = rmpwnam($name);
     @info = mgetpwnam($name);

DESCRIPTION
===========

   Passwd::Linux provides additional password routines.  It augments the
getpw* functions with setpwinfo, modpwinfo, rmpwnam, mgetpwnam.  You need
to run most of the functions as root or as someone who has permission to
modify the shadow file.

   setpwinfo and modpwinfo are called with arrays containing (in order):
name, crypted_password, uid, gid, gecos, home_directory, shell

   rmpwnam is called with a scalar containing the login name

   mgetpwnam returns the same array that getpwnam returns without the
'unused' age or comment fields it also returns the crypted password if run
with root permissions.

   setpwinfo does a create/modify of the user.  modpwinfo only does a
modify, it will return an error if the user doesn't exist.

   rmpwnam removes the user with the given login from both the password
and shadow files.  It returns an error if the user doesn't exist.

   This module does call syslog in the C portion, but it doesn't call
openlog.  If you wish to see the error output of the syslog you must do an
openlog in your perl script.

   You must be running as root in order to use this module. If it
successfully completes an operation and you are not root then you have a
huge security problem on your box.

   This module as distributed does not allow operations to occur on uid 0
files

   Return values:   < 0	system error occurred, error value should be in $!
   0   no error     1   operation attempt on uid 0     2   user does not
exist

Exported functions on the OK basis
==================================

     modpwinfo
     setpwinfo
     rmpwnam
     mgetpwnam

AUTHOR
======

   Eric Estabrooks,  eric@urbanrage.com

SEE ALSO
========

   perl(1).

Perl module for manipulating the passwd and shadow files
********************************************************

NAME
====

   Passwd::Solaris - Perl module for manipulating the passwd and shadow
files

SYNOPSIS
========

     use Passwd::Solaris qw(modpwinfo setpwinfo rmpwnam mgetpwnam);

     $err = modpwinfo(@info);
     $err = setpwinfo(@info);
     $err = rmpwnam($name);
     @info = mgetpwnam($name);

DESCRIPTION
===========

   Passwd::Solaris provides additional password routines.  It augments the
getpw* functions with setpwinfo, modpwinfo, rmpwnam, mgetpwnam.  You need
to run most of the functions as root or as someone who has permission to
modify the shadow file.

   setpwinfo and modpwinfo are called with arrays containing (in order):
name, crypted_password, uid, gid, gecos, home_directory, shell

   rmpwnam is called with a scalar containing the login name

   mgetpwnam returns the same array that getpwnam returns without the
'unused' age or comment fields it also returns the crypted password if run
with root permissions.

   setpwinfo does a create/modify of the user.  modpwinfo only does a
modify, it will return an error if the user doesn't exist.

   rmpwnam removes the user with the given login from both the password
and shadow files.  It returns an error if the user doesn't exist.

   This module does call syslog in the C portion, but it doesn't call
openlog.  If you wish to see the error output of the syslog you must do an
openlog in your perl script.

   You must be running as root in order to use this module. If it
successfully completes an operation and you are not root then you have a
huge security problem on your box.

   This module as distributed does not allow operations to occur on uid 0
files

   Return values:   < 0	system error occurred, error value should be in $!
   0   no error     1   operation attempt on uid 0     2   user does not
exist

Exported functions on the OK basis
==================================

     modpwinfo
     setpwinfo
     rmpwnam
     mgetpwnam

AUTHOR
======

   Eric Estabrooks,  eric@urbanrage.com

SEE ALSO
========

   perl(1).

General
=======

   Apart from this documentation there are also some commentated examples
of some Widgets, as well as a complete example for the GUI of a
Setup-program (app2.pl).

using widgets
-------------

   A new Widget is always created by

     $WIDGET_REFERENCE=Paw::WIDGETNAME->new(PARAMETERNAME=>VALUE).

   The PARAMETERs must be passed as HASH (PARAMETERNAME=>VALUE) to the
widget, even if there is only one parameter for the widget.  The methods
of a widget are used by

     $WIDGET_REFERENCE->METHOD(PARAMETER)
     $WIDGET_REFERENCE->METHOD(PARAMETER1=>VALUE1, PARAMETER2=>VALUE2)

   If the method permits only one or zero parameters, it's not necessary
to designate the parameter in a HASH, for example

     $window->put($widget).

   If more than 1 parameter is possible, then each parameter must be
designated by it's name, for example

     $window->abs_move_curs(new_x=>5, new_y=>6) #is okay,

   while

     $window->abs_move_curs(5) # is not okay
     $window->put_dir("h")     # is quite permitted.

Initialisation
--------------

   Every program that uses this modul looks the same in the first lines of
code.

     #!/usr/bin/perl
     use Curses;
     use widget;
     ($columns, $rows)=Paw::init_widgetset();

   $columns and $rows contains the terminal width and height.  This values
can be used to calculate the size or position of other windows, for example

     $main_win=Paw::Window->new(abs_x=>1, abs_y=>1,
                               height=$rows-3, width=>$columns-2,
                               color=>1, statusbar=>1);

Colors
------

   While the initialisation of the widgetset, some colorpairs are set.

     init_pair(1, COLOR_WHITE, COLOR_BLUE);   #default colors
     init_pair(31, COLOR_BLACK, COLOR_BLACK); #shadow
     init_pair(30, COLOR_BLACK, COLOR_CYAN);  #pulldown menu
     init_pair(29, COLOR_BLACK, COLOR_BLUE);  #filedialog

   Already defined colors are black, red, green, yellow, blue, magenta,
cyan, and white New colorpairs can be created by :

     init_pair(pair, foreground_color, background_color);

   Further information about the colormodel can be found in the
documentation of the curses lib (man ncurses, perldoc Curses).

Widgetpacker
------------

   There are two ways how to get widgets into a window.  The first one is
to use the put($widget) function of the window, the second way is to use
boxes (recommended).

   without boxes:

     #put the $label2 into the window
     $win2->put($label2);
     #tell to packer to put the next widget horizontally to the $label2
     $win2->put_dir("h");   # horizontal packen
     #keep on putting widgets ...
     $win2->put($butt1);    # Button for Faktor 2
     $win2->put($label3);   # Faktor 3
     $win2->put($butt2);    # Button for Faktor 3
     $win2->put($label4);   # Faktor 4
     $win2->put($butt3);    # Button for Faktor 4
     #switch the packer to vertikal-mode...
     $win2->put_dir("v");
     #...to get the label under the other widgets.
     $win2->put($label5);   # "Ergebnis : ..."

   We will get

     $label2 $butt1 $label3 $butt2 $label4 $butt3
     $label5

   or

     Faktor 2 [ ] Faktor 3 [ ] Faktor 4 [ ]
     Ergebnis : 200

   This type of widget-packing is nice for smaller GUIs and surely a fast
solution but you will come very fast to the boundaries of your
possibilities.  Then the boxes seems to be the better solution.

   A box takes up several widgets and puts them always either horizontal
or vertically.  The Clou at a box is that it can also take up other boxes.
It is possible that a horizontal box is to be packed into a vertical box
and this in any depth.  If you  know the widgetpacker of GTK or TK, you
know this widgetpacker too.

     ###########################################
     # 7 Buttons building an H
     ###########################################

     $vbox0->put($b1);

     $hbox1->put($b2);
     $hbox1->put($b3);

     $vbox0->put($hbox1);
     $vbox0->put($b4);

     $hbox0->put($vbox0);

     $vbox1->put($b5);
     $vbox1->put($b6);
     $vbox1->put($b7);

     $hbox0->put($vbox1);

     $win->put($hbox0);

   We will get:

     [1]   [5]
     [2][3][6]
     [4]   [7]

SEE ALSO
========

   Paw::Box          container for other Widgets

   Paw::Button       simple Button (optionally with label)

   Paw::Filedialog   filedialog Widget

   Paw::Label        simple text label

   Paw::Line         h/v line (seperator for menus)

   Paw::Listbox      box with selectable lines

   Paw::Menu         pulldown menus

   Paw::Popup        popup window with text and buttons

   Paw::Progressbar  a progressbar

   Paw::Radiobutton  a group of buttons but only one can be selected

   Paw::Scrollbar    scrollbar for other widgets (listbox...) no mouse
support

   Paw::Statusbar    bottomline for windows

   Paw::Text_entry   enter one line of text

   Paw::Textbox      box with more lines of text (buggy !!!)

   Paw::Window       container for other widgets

COPYRIGHT
=========

   Copyright (c) 1999 SuSE GmbH, Nuernberg, Germany. All rights reserved.

Box Widget
==========

   *$box=Paw::Box-*new($direction, [$name], [$title], [$color],
[$orientation])>;

   Parameter

     $direction   => Direction in that the widgets will be packed
                     "v"ertically or "h"orizontally

     $color       => The colorpair must be generated with
                     Curses::init_pair(pair_nr, COLOR_fg, COLOR_bg)
                     [optionally]

     $name        => Name of the box [optionally]

     $orientation => "topleft", "topright", "bottomleft", "bottomright",
                     "center" and "grow" are the possible parameters.
                     They indicate how the box will behave on
                     modifications of the terminal size.
                     Either it keeps it's distance to the indicated
                     terminal side, it remains centered or it
                     grows/shrinks with the new terminal size
                     (default is the orientation of the parent-widget)
                     [ optionally ].'
     B<Example>

     $box=Paw::Box->new(direction=>"v",title=>"Start",color=>1);

put($widget)
------------

   put the widget into the box.

   Example

     $box->put($button0);

set_border(["shade"])
---------------------

   activate the border of the box optionally also with shadows.

   Example

     $box->set_border("shade"); or $win->set_border();

abs_move_curs($new_x, $new_y);
------------------------------

   Sets the packer to the absolute position in the box (negative values
lay outside of the box).

   Example

     $box->abs_move_curs(new_x=>1);

rel_move_curs($new_x, $new_y);
------------------------------

   Sets the packer relative to the current position in the box (also
negative values are possible).

   Example

     $box->rel_move_curs(new_y=>3, new_x=>-2);

Box Widget
==========

   *$box=Paw::Box::new($direction, [$name], [$title], [$color],
[$orientation])*;

   Parameter

     $direction   => Richtung in welche die Widgets gepackt werden sollen
                     "v"ertikal oder "h"orizont

     $color       => Das Farbpaar (colorpair) muss mit
                     Curses::init_pair(pair_nr, COLOR_fg, COLOR_bg)
                     erzeugt werden[optional]

     $name        => Name der Box [optional]

     $orientation => "topleft", "topright", "bottomleft", "bottomright",
                     "center" und "grow" sind die moeglichen Parameter.
                     Sie geben an wie sich die Box bei Änderung der
                     Terminalgroesse verhaelt. Entweder behaelt es seinen
                     Abstand zu der angegebenen Seite bei, es bleibt
                     zentriert oder es waechst bzw. schrumpft mit dem
                     Terminal.
                     (default ist die "Orientation" des Elternwidgets)
                     [optional]

   *Beispiel*

     $box=Paw::Box::new(direction=>"v",title=>"Start",color=>1);

put($widget)
------------

   pack das Widget in die Box

   *Beispiel*

     $box->put($button0);

set_border(["shade"])
---------------------

   aktiviert den Rahmen der Box optional auch mit Schatten.

   *Beispiel*

     $box->set_border("shade"); oder $win->set_border();

abs_move_curs($new_x, $new_y);
------------------------------

   Setzt den Packer an die absolute Position in der Box (negative Werte
liegen ausserhalb der Box).

   *Beispiel*

     $box->abs_move_curs(new_x=>1);

rel_move_curs($new_x, $new_y);
------------------------------

   Setzt den Packer relativ zur momentanen Position in der Box (auch
negative Werte moeglich).

   *Beispiel*

     $box->rel_move_curs(new_y=>3, new_x=>-2);

Button Widget
=============

   *$button=Paw::Button-*new([$color], [$name], [\&callback], [$label]);>

   Parameter

     color    => the colorpair must be generated with
                 Curses::init_pair(pair_nr, COLOR_fg, COLOR_bg)
                 [optionally]

     name     => name of the button [optionally]

     callback => reference to the function which will be called
                 when pushing the button. [optionally]

     label    => text in the button. If the button contains text,
                 it is not possible to see if it is pushed or not.
                 [optionally]

   Example

     $button=Paw::Button->new(callback=>\&button_callback);

   Callback

     sub button_callback {
         my $this = shift;             # Referenz to the button

         $data = $edit->get_text();
         $box->add_row($data);
         return;
     }

set_button()
------------

   Sets the button into the status " pressed "

   Example

     $button->set_button();      # [x]

release_button()
----------------

   Sets the button into the status "not pressed"

   Example

     $button->release_button();      # [ ]

push_button()
-------------

   the button changes it status.

   Example

     $button->push_button();      # [x]->[ ], [ ]->[x]

abs_move_widget($new_x, $new_y)
-------------------------------

   the widget moves to the new absolute screen position.  if you set only
one of the two parameters, the other one keeps the old value.

   Example

     $button->abs_move_widget( new_x=>5 );      #y-pos is the same

get_widget_pos()
----------------

   returns an array of two values, the x-position and the y-position of
the widget.

   Example

     ($xpos,$ypos)=$button->get_widget_pos();

set_color($color_pair)
----------------------

   Set a new color_pair for the widget.

   Example

     $button->set_color(3);

set_border(["shade"])
---------------------

   activates the border of the widget (optionally also with shadows).

   Example

     $widget->set_border("shade"); or $widget->set_border();

Button Widget
=============

   *$button=Paw::Button::new([$color], [$name], [\&callback], [$label]);*

   Parameter

     $color   => Das Farbpaar (colorpair) muss mit
                 Curses::init_pair(pair_nr, COLOR_fg, COLOR_bg)
                 erzeugt werden[optional]

     name     => Name des button [optional]

     callback => Reference auf die Function die beim druecken des
                 Button aufgerufen wird. [optional]

     label    => Text in dem Button. Wenn der Button einen Text
                 enthaelt, ist optisch nicht mehr feststellbar,
                 ob der Button gedrueckt ist. [optional]

   *Beispiel*

     $button=Paw::Button::new(callback=>\&button_callback);

   Callback

   Wird der Button betaetigt, so wird die Callback-Funktion angesprungen.

     sub button_callback {
         my $this = shift;             # Referenz to the button

         $data = $edit->get_text();
         $box->add_row($data);
         return;
     }

set_button()
------------

   Setzt den Button in den definierten Zustand "gedrueckt".

   *Beispiel*

     $button->set_button();      # [x]

release_button()
----------------

   Setzt den Button in den definierten Zustand "nicht gedrueckt"

   *Beispiel*

     $button->release_button();      # [ ]

push_button()
-------------

   Der Button wechselt seinen Zustand.

   *Beispiel*

     $button->push_button();      # [x]->[ ], [ ]->[x]

abs_move_widget($new_x, $new_y)
-------------------------------

   Das Widget verschiebt sich auf die neue absolute Schirm Position.  Wird
nur einer der Parameter angegeben, so behaelt der andere seinen Wert bei.

   *Beispiel*

     $button->abs_move_widget( new_x=>5 );      #y-pos bleibt wie sie ist

get_widget_pos()
----------------

   Gibt ein Array mit den beiden Wertde (x-Position, y-Position) zurueck.

   *Beispiel*

     ($xpos,$ypos)=$button->get_widget_pos();

set_color($color_pair)
----------------------

   Setzt ein neues color_pair.

   *Beispiel*

     $button->set_color(3);

set_border(["shade"])
---------------------

   aktiviert den Rahmen der Box. Optional auch mit Schatten.

   *Beispiel*

     $box->set_border("shade"); or $win->set_border();

Filedialog
==========

   *$fd=Paw::Filedialog-*new([$height], [$width], [$name], [$dir])>;

   Parameter

     $height    => number of rows [optionally]

     $width     => number of columns [optionally]

     $name      => name of the widget [optionally]

     $dir       => the directory in which the filedialog
                   will be started ("." default) [optionally]

   When the filedialogbox is closed by the "ok"-button, it returns an
array of all marked filenames (without path)

   Example

     $fd=Paw::Filedialog->new(dir=>"/etc");

set_dir($path)
--------------

   Set the directory where the filedialog will begin.

   Example

     $fd->set_dir();       # start in "."
     $fd->set_dir("/etc"); # start in "/etc"

get_dir($scalar)
----------------

   Returns the path of the filedialogbox.

   Example

     $path=$fd->get_dir();  #$path = "/etc" (for example).

draw()
------

   Raises the filedialog. If the box is closed by the "ok-button", it
returns an array of all marked filenames (without path). If the box is
closed by the "cancel-button", no return of the marked files takes place.

   Example

     @files=$fd->draw();

set_border(["shade"])
---------------------

   activates the border of the widget (optionally also with shadows).

   Example

     $widget->set_border("shade"); or $widget->set_border();

Filedialog
==========

   *$fd=Paw::Filedialog::new([$height], [$width], [$name], [$dir])*;

   Parameter

     $height    => Anzahl der Reihen [optional]

     $width     => Anzahl der Spalten [optional]

     $name      => Name des Widgets [optional]

     $dir       => Das Verzeichnis in dem der Filedialog starten soll
                   ("." default) [optional]

   Wen der Filedialog mit dem "Ok-Button" verlassen wird, so gibt er ein
Array aller markierten Filenamen zurueck.

   *Beispiel*

     $fd=Paw::Filedialog::new(dir=>"/etc");

set_dir($path)
--------------

   Setzt das Verzeichnis in dem der Filedialog starten soll

   *Beisiel*

     $fd->set_dir();       # start in "."
     $fd->set_dir("/etc"); # start in "/etc"

get_dir($scalar)
----------------

   Gibt den Pfad zurueck in dem sich die Filedialogbox befindet.

   *Beispiel*

     $path=$fd->get_dir();  #$path = "/etc" (for example).

draw()
------

   Stellt die Filedialogbox am Schirm da. Wenn die Box ueber "Ok"
geschlossen wird, so gibt sie ein Array aller markierten Filenamen (ohne
Pfad) zurueck. Wird die Box ueber "Cancel" verlassen, erfolgt keine
Rueckgabe der marktierten Files.

   *Beispiel*

     @files=$fd->draw();

set_border(["shade"])
---------------------

   aktiviert den Rahmen der Box. Optional auch mit Schatten.

   *Beispiel*

     $box->set_border("shade"); or $win->set_border();

Label Widget
============

   *$label=Paw::Label-*new($text, [$color], [$name]);>

   Example

     $label=Paw::Label->new(text=>"Text", color=>3, name=>"Linux_Label");

   Parameter

     text  => Text of the label

     color => The colorpair must be generated with
              Curses::init_pair(pair_nr, COLOR_fg, COLOR_bg)
              [optionally]

     name  => Name of the widget [optionally]

set_text($text)
---------------

   Change the text of the label to the string $text.

   Example

     $label->set_text("changed label text");

get_text();
-----------

   returns the label-text.

   Example

     $text=$label->get_text();

abs_move_widget($new_x, $new_y)
-------------------------------

   the widget moves to the new absolute screen position.  if you set only
one of the two parameters, the other one keeps the old value.

   Example

     $label->abs_move_widget( new_x=>5 );      #y-pos is the same

get_widget_pos()
----------------

   returns an array of two values, the x-position and the y-position of
the widget.

   Example

     ($xpos,$ypos)=$label->get_widget_pos();

set_color($color_pair)
----------------------

   Set a new color_pair for the widget.

   Example

     $box->set_color(3);

set_border(["shade"])
---------------------

   activates the border of the widget (optionally also with shadows).

   Example

     $widget->set_border("shade"); or $widget->set_border();

Label Widget
============

   *$label=Paw::Label::new($text, [$color], [$name]);*

   *Beispiel*

     $label=Paw::Label::new(text=>"Text", color=>3, name=>"Linux_Label");

   Parameter

     text  => Text des Labels

     color => Das Farbpaar (colorpair) muss mit
              Curses::init_pair(pair_nr, COLOR_fg, COLOR_bg)
              erzeugt werden[optional]

     name  => Name des Fensters [optional]

set_text($text)
---------------

   Ändert den Text des Labels auf den String in $text.

   *Beispiel*

     $label->set_text("changed label text");

get_text();
-----------

   Gibt den Text des Labels zurueck.

   *Beispiel*

     $text=$label->get_text();

abs_move_widget($new_x, $new_y)
-------------------------------

   the widget moves to the new absolute screen position.  if you set only
one of the two parameters, the other one keeps the old value.

   Example

     $label->abs_move_widget( new_x=>5 );      #y-pos is the same

get_widget_pos()
----------------

   returns an array of two values, the x-position and the y-position of
the widget.

   Example

     ($xpos,$ypos)=$label->get_widget_pos();      #y-pos is the same

set_color($color_pair)
----------------------

   Set a new color_pair for the widget.

   Example

     $label->set_color(3);

abs_move_widget($new_x, $new_y)
-------------------------------

   Das Widget verschiebt sich auf die neue absolute Schirm Position.  Wird
nur einer der Parameter angegeben, so behaelt der andere seinen Wert bei.

   *Beispiel*

     $label->abs_move_widget( new_x=>5 );      #y-pos bleibt wie sie ist

get_widget_pos()
----------------

   returns an array of two values, the x-position and the y-position of
the widget.  Gibt ein Array mit den beiden Wertde (x-Position, y-Position)
zurueck.

   *Beispiel*

     ($xpos,$ypos)=$label->get_widget_pos();

set_color($color_pair)
----------------------

   Setzt ein neues color_pair.

   *Beispiel*

     $label->set_color(3);

set_border(["shade"])
---------------------

   aktiviert den Rahmen der Box. Optional auch mit Schatten.

   *Beispiel*

     $box->set_border("shade"); or $win->set_border();

Line Widget
===========

   *$line=Paw::Line-*new($length, [$name], [$char], [$direction])>;

   Parameter

     $name      => name of the widget [optionally]

     $char      => character that will be used to build the line
                   (ACS_HLINE) [optionally]

     $direction => "v"ertically or "h"orizontally (default) [optional]

     $length    => length in characters of the line

   Example

     $l=Paw::Line->new(length=>$columns, char=>"#");

abs_move_widget($new_x, $new_y)
-------------------------------

   the widget moves to the new absolute screen position.  if you set only
one of the two parameters, the other one keeps the old value.

   Example

     $l->abs_move_widget( new_x=>5 );      #y-pos is the same

get_widget_pos()
----------------

   returns an array of two values, the x-position and the y-position of
the widget.

   Example

     ($xpos,$ypos)=$l->get_widget_pos();

set_color($color_pair)
----------------------

   Set a new color_pair for the widget.

   Example

     $box->set_color(3);

set_border(["shade"])
---------------------

   activates the border of the widget (optionally also with shadows).

   Example

     $widget->set_border("shade"); or $widget->set_border();

Line Widget
===========

   *$line=Paw::Line::new($length, [$name], [$char], [$direction])*;

   Parameter

     $name      => Name des Widgets [optional]

     $char      => Zeichen aus dem die Linie aufgebaut wird (ACS_HLINE)
                   [optional]

     $direction => Richtung in der die Linie liegen soll "v" bzw. "h"
                   (h = default) [optional]

     $length    => Laenge der Linie

   Example

     $l=Paw::Line::new(length=>$columns, char=>"#");

abs_move_widget($new_x, $new_y)
-------------------------------

   Das Widget verschiebt sich auf die neue absolute Schirm Position.  Wird
nur einer der Parameter angegeben, so behaelt der andere seinen Wert bei.

   *Beispiel*

     $l->abs_move_widget( new_x=>5 );      #y-pos bleibt wie sie ist

get_widget_pos()
----------------

   Gibt ein Array mit den beiden Wertde (x-Position, y-Position) zurueck.

   *Beispiel*

     ($xpos,$ypos)=$l->get_widget_pos();

set_color($color_pair)
----------------------

   Setzt ein neues color_pair.

   *Beispiel*

     $l->set_color(3);

set_border(["shade"])
---------------------

   aktiviert den Rahmen der Box. Optional auch mit Schatten.

   *Beispiel*

     $box->set_border("shade"); or $win->set_border();

Listbox
=======

   *$lb=Paw::Listbox-*new($height, $width, [$colored], [$name]);>

   Parameter

     $height  => Number of rows

     $width   => Number of columns

     $colored => 1 turns on the colored mode
                 (see also "add_row") default=0 [optionally]

     $name    => Name of the widget [optionally]

   Example

     $lb=Paw::Listbox->new(width=>10, height=>15, colored=>1);

clear_listbox()
---------------

   deletes all entrys out of the listbox

   Example

     $listbox->clear_listbox();

add_row($data, $color), add_row(\@data);
----------------------------------------

   adds a data-row into the listbox. When the color mode is activated, you
can give a second parameter as color-pair number.  Alternatively you can
give a refernce to an array to the listbox and it will put gradually each
array element into the box.  If the color mode is on, each second element
of the array must be a color-pair number.

   Example

     $listbox->add_row("Test", 3);

del_row($number)
----------------

   deletes the row with the number "$number". Start counting at zero.

   Example

     $listbox->del_row(4);

change_rows($first, $second);
-----------------------------

   swaps the $first and the $second row of the listbox.

   Example

     $listbox->change_rows($lower, $upper);

number_of_data()
----------------

   returns the number of data-rows in the listbox.

   Example

     $data=$listbox->number_of_data();

get_pushed_rows("data"), get_pushed_rows("linenumbers");
--------------------------------------------------------

   returns an array of all pushed data-rows, either the linenumbers or the
data.

   Example

     @data_rows=$listbox->get_pushed_rows("linenumbers");

get_all_rows();
---------------

   returns an array with the complete contents of the listbox.

   Example

     @full_data=$listbox->get_all_rows();

abs_move_widget($new_x, $new_y)
-------------------------------

   the widget moves to the new absolute screen position.  if you set only
one of the two parameters, the other one keeps the old value.

   Example

     $listbox->abs_move_widget( new_x=>5 );      #y-pos is the same

get_widget_pos()
----------------

   returns an array of two values, the x-position and the y-position of
the widget.

   Example

     ($xpos,$ypos)=$listbox->get_widget_pos();

set_border(["shade"])
---------------------

   activates the border of the widget (optionally also with shadows).

   Example

     $widget->set_border("shade"); or $widget->set_border();

Listbox
=======

   *$lb=Paw::Listbox::new($height, $width, [$colored], [$name]);*

   Parameter

     $height  => Anzahl der Reihen

     $width   => Anzahl der Spalten

     $colored => 1 schaltet den Farbmodus ein
                 (siehe Methode add_row) default=0 [optional]

     $name    => Name des Widgets [optional]

   *Beispiel*

     $lb=Paw::Listbox::new(width=>10, height=>15, colored=>1);

clear_listbox()
---------------

   entfernt alle Eintraege aus der Listbox

   *Beispiel*

     $listbox->clear_listbox();

add_row($data, $color), add_row(\@data);
----------------------------------------

   packt eine Zeile in die Listbox. Wenn der Farbmodus aktiv ist, kann
noch ein Farbpaar als weiterer Parameter uebergeben werden.  Wird eine
Referenz auf ein Array uebergeben, so werden nach und nach alle Elemente
des Arrays in die Listbox gepackt.  Ist hier der Colormodus aktiv, so
*muss* jedes zweite Element eine Farbpaar Nummer sein.

   *Beispiel*

     $listbox->add_row("Test", 3);

del_row($number)
----------------

   entfernt die Zeile mit der Nummer $number

   *Beispiel*

     $listbox->del_row(4);

change_rows($first, $second);
-----------------------------

   tauscht die beiden Zeilen in der Listbox

   *Beispiel*

     $listbox->change_rows($lower, $upper);

number_of_data()
----------------

   gibt die Anzahl der Reihen in der Listbox zurueck.

   *Beispiel*

     $data=$listbox->number_of_data();

get_pushed_rows("data"), get_pushed_rows("linenumbers");
--------------------------------------------------------

   gibt ein Array mit allen aktiven Reihen der Listbox zurueck. Entweder
die Zeilennummer(linenumber) oder direkt den Inhalt (data)

   *Beispiel*

     @data_rows=$listbox->get_pushed_rows("linenumbers");

get_all_rows();
---------------

   gibt ein Array mit dem kompletten Inhalt der Listbox zurueck.

   *Beispiel*

     @full_data=$listbox->get_all_rows();

abs_move_widget($new_x, $new_y)
-------------------------------

   Das Widget verschiebt sich auf die neue absolute Schirm Position.  Wird
nur einer der Parameter angegeben, so behaelt der andere seinen Wert bei.

   *Beispiel*

     $listbox->abs_move_widget( new_x=>5 );      #y-pos is the same

get_widget_pos()
----------------

   Gibt ein Array mit den beiden Wertde (x-Position, y-Position) zurueck.

   *Beispiel*

     ($xpos,$ypos)=$listbox->get_widget_pos();

set_border(["shade"])
---------------------

   aktiviert den Rahmen der Box. Optional auch mit Schatten.

   *Beispiel*

     $box->set_border("shade"); or $win->set_border();

Pulldown Menu
=============

   *$pdm=Paw::Paw-*Menu->new($title, [$name], [$border]);>

   Parameter

     $title  => visible title

     $name   => name of the widget [optionally]

     $border => only "shade" as option so far [optionally]

   Example

     $pdm=Paw::Menu->new(title=>"Datei", border=>"shade");

add_menu_point($text, \&callback), add_menu_point($other_menu)
--------------------------------------------------------------

   generates a new menupoint (with name "$text") and branches on the
function "callback", if it is activated.  There is also the possibility to
give just another menu and you will get a Pulldown Menu in the Pulldown
Menu.

   Example

     $men->add_menu_point("Beep", \&menu_beep);

     #Pulldownmenu "$men" in Pulldownmenu "$men2".
     $men2->add_menu_point($men);

Pulldown Menu
=============

   *$pdm=Paw::Menu::new($title, [$name], [$border]);*

   Parameter

     $titel  => sichtbarer Titel des Pulldownmenus

     $name   => Name des Widgets [optional]

     $border => bisher nur "shade" als option [optional]

   *Beispiel*

     $pdm=Paw::Menu::new(title=>"Datei", border=>"shade");

add_menu_point($text, \&callback), add_menu_point($other_menu)
--------------------------------------------------------------

   erzeugt einen Menupunkt (Text) und springt die Funktion callback an,
wenn er aktiviert wird.  Es besteht auch die Moeglichkeit nur ein anderes
Menu zu uebergeben. Dadurch entstehen Untermenus.

   *Beispiel*

     $men->add_menu_point("Beep", \&menu_beep);

     #Pulldownmenu "$men" in Pulldownmenu "$men2".
     $men2->add_menu_point($men);

Allgemeines
===========

   Neben dieser Dokumentation befinden sich auch noch dokumentierte
Beispiele für einige Widgets im Unterverzeichnis example, sowie ein
komplettes Beispiel für die Oberfläche eines Setup Programms (app2.pl).

Widget handling
---------------

   Ein neues Widget wird immer mit

     $WIDGET_REFERENCE=Paw::WIDGETNAME::new(PARAMETERNAME=>VALUE).

   erzeugt. Dabei müssen die PARAMETER immer als HASH übergeben werden
Diese Regel gilt auch wenn nur ein Parameter übergeben wird. Die
Reihenfolge in der die PARAMETER übergeben werden ist dabei egal.  Die
Methoden eines Widgets werden mit

     $WIDGET_REFERENCE->METHOD(PARAMETER)
     $WIDGET_REFERENCE->METHOD(PARAMETER1=>VALUE1, PARAMETER2=>VALUE2)

   aufgerufen. Wenn einen Methode nur einen oder keinen Parameter erlaubt,
wird auf die Benennung des Parameters verzichtet

     $window->put($widget).

   Sollten mehr als 1 Parameter möglich sein, so muss wieder jeder
Parameter benannt werden, wobei auch hier die Reihenfolge der Parameter
egal ist.

     $window->abs_move_curs(new_x=>5, new_y=>6) #is okay,
     $window->abs_move_curs(5)                  # is not okay
     $window->put_dir("h")                      # is quite permitted.

Initialisierung
---------------

   Jedes Programm, welches dieses Modul einsetzt, beginnt im Grunde gleich
:

     #!/usr/bin/perl
     use Curses;
     use widget;
     ($columns, $rows)=Paw::init_widgetset();

   die Variablen $columns und $rows enthalten die Breite und Höhe des
Terminals und können z.B. verwendet werden, um die Grösse weiterer Fenster
in Abhängigkeit von der Terminalgrösse zu berechnen.

     $main_win=Paw::Window::new(abs_x=>1, abs_y=>1,
                                height=$rows-3, width=>$columns-2,
                                color=>1, statusbar=>1);

Farben
------

   Beim initialisieren des Widgetsets werden einige Color_Pairs bereits
gesetzt.  Dazu gehören:

     init_pair(1, COLOR_WHITE, COLOR_BLUE);   #default colors
     init_pair(31, COLOR_BLACK, COLOR_BLACK); #shadow
     init_pair(30, COLOR_BLACK, COLOR_CYAN);  #pulldown menu
     init_pair(29, COLOR_BLACK, COLOR_BLUE);  #filedialog

   Als Farben stehen black, red, green, yellow, blue, magenta, cyan, und
white zur Verfügung.  Neue color_pairs können mit

     init_pair(pair, foreground_color, background_color);

   erzeugt werden.  Für weitere Informationen zum Farbmodell empfehle ich
die Dokumentation der Curses Lib (man ncurses, bzw. man init_color und
perldoc Curses).

Widgetpacker
------------

   Es gibt zwei Möglichkeiten Widgets in ein Fenster zu bekommen.  Zum
einen kann man direkt die put Funktion des Fensters nehmen, zum anderen
kann man den Umweg über Boxen nehmen.  Zuerst mal ohne Boxen :

     #put the $label2 into the window
     $win2->put($label2);
     #tell to packer to put the next widget horizontally to the $label2
     $win2->put_dir("h");   # horizontal packen
     #keep on putting widgets ...
     $win2->put($butt1);    # Button for Faktor 2
     $win2->put($label3);   # Faktor 3
     $win2->put($butt2);    # Button for Faktor 3
     $win2->put($label4);   # Faktor 4
     $win2->put($butt3);    # Button for Faktor 4
     #switch the packer to vertikal-mode...
     $win2->put_dir("v");
     #...to get the label under the other widgets.
     $win2->put($label5);   # "Ergebnis : ..."

   Man bekommt dann

     $label2 $butt1 $label3 $butt2 $label4 $butt3
     $label5

   bzw.

     Faktor 2 [ ] Faktor 3 [ ] Faktor 4 [ ]
     Ergebnis : 200

   Diese Art Widgets zu packen ist für kleinere Oberflächen zwar eine
schnelle Lösung, man stösst aber auch ebenso schnell an die Grenzen der
Möglichkeiten. Hier kommen dann die Boxen zum Zuge.

   Eine Box nimmt mehrere Widgets auf und packt diese immer entweder
horizontal oder vertikal.  Der Clou an der Sache ist aber das eine Box
auch eine andere Box aufnehmen kann. Es ist also möglich ein horizontale
Box in eine vertikale Box zu packen und das in beliebiger Tiefe. Auf diese
Art lässt sich nahezu alles realisieren. Wer den Widgetpacker von GTK oder
TK kennt, der weiss auch wie es hier funktioniert.

     ###########################################
     # 7 Buttons building an H
     ###########################################

     $vbox0->put($b1);

     $hbox1->put($b2);
     $hbox1->put($b3);

     $vbox0->put($hbox1);
     $vbox0->put($b4);

     $hbox0->put($vbox0);

     $vbox1->put($b5);
     $vbox1->put($b6);
     $vbox1->put($b7);

     $hbox0->put($vbox1);

     $win->put($hbox0);

   Man bekommt dann:

     [1]   [5]
     [2][3][6]
     [4]   [7]

COPYRIGHT
=========

   Copyright (c) 1999 SuSE GmbH, Nuernberg, Germany. All rights reserved.

Popup Window
============

   *$popup=Paw::Popup-*new([$height], [$width], [$shade], \@buttons,
\$text, [$name]);>

   Parameter

     $height   => number of rows [optionally]

     $width    => number of columns [optionally]

     $shade    => popup box has a shadow (shade=>1)

     $name     => name of the widget [optionally]

     \@buttons => an array of strings for the labels on the buttons
                  in the box.

     \$text    => reference to a scalar with the Text.

     B<Example>

     @butt=('Okay', 'Cancel');
     $text=('Do you really want to continue ?');
     $pu=Popup::new(height=>20, width=>20,
                        buttons=>\@butt, text=>\$text);

   If a button is pressed, the box closes and the number of the button is
returned (beginning by 0).

draw();
-------

   raises the popup-window, returns the number of the pushed button.

   Example

     $button=$pu->draw();

set_border(["shade"])
---------------------

   activates the border of the widget (optionally also with shadows).

   Example

     $widget->set_border("shade"); or $widget->set_border();

Popup Window
============

   *$popup=Paw::Popup::new($height, $width, \@buttons, \$text, [$name]);*

   Parameter

     $height   => Anzahl der Reihen

     $width    => Anzahl der Spalten

     $name     => Name des Widgets [optional]

     \@buttons => Ein Array von Strings fuer die Label der Buttons in der Box.

     \$text    => Eine Refernez auf ein Scalar mit dem Text

   *Beispiel*

     @butt=("Okay", "Cancel");
     $text=("Do you really not want to continue ?");
     $pu=Paw::Popup::new(height=>20, width=>20,
                         buttons=>\@butt, text=>\$text);

   Wenn ein Button gedrueckt wird, schliesst sich die Box und es wird die
Nummer des Buttons zurueck gegeben (beginnend bei 0).

draw();
-------

   Stellt das Popup Fenster am Schirm da, gibt den gedrueckten Button
zurueck.

   *Beispiel*

     $button=$pu->draw();

set_border(["shade"])
---------------------

   aktiviert den Rahmen der Box. Optional auch mit Schatten.

   *Beispiel*

     $box->set_border("shade"); or $win->set_border();

Listbox
=======

   *$lb= new Paw::Popup_menu ( \@data, [$size], [$width], [$default],
[$color], [\&callback], [$name]);*

   Parameter

     \@data     => Reference to an array that contains the entries

     $size      => Number of entries that are shown without scrolling,
                   if the widget is pushed [default is 5]

     $width     => Number of columns [default is 15]

     $default   => Number of the default element (starting at 0)
                   [default is 0]

     $name      => Name of the widget [optionally]

     $color     => the colorpair must be generated with
                   Curses::init_pair(pair_nr, COLOR_fg, COLOR_bg)
                   [optionally]

     \&callback => will be called when the value has changed.
                   the $this reference is given to it and no return value will be parsed

   Example

     $data = [ "one", "two", "three", "four" ];
     $pm=Paw::Popup_menu->new( data => $data, width=>10, size=>8 );

get_choice()
------------

   returns the choosen value of the box as string

   Example

     $choice = $pm->get_choice();

set_choice($number)
-------------------

   sets the choosen value of the box. $number is the element number in the
array

   Example

     $pm->set_choice(3);

Button Widget
=============

   *$pb=Paw::Progressbar-*new( \$variable, [$from], [$to], [$blocks],
[$color], [$name] );>

   Parameter

     variable => a reference to a scalar variable which
                 should be represented by the progressbar

     from     => the minimum value (defaults to 0)

     to       => the maximum value (defaults to 100)

     blocks   => the number ob blocks between 'from' and 'to'
                 defaults to 10

     name     => name of the progressbar [optionally]

     color    => the colorpair must be generated with
                 Curses::init_pair(pair_nr, COLOR_fg, COLOR_bg)
                 [optionally]

   Example

     $pb=Paw::Progressbar->new( from=>-10, to=>10, blocks=>25, color=>3 );

Button Widget
=============

   *$pb=Paw::Progressbar-*new( \$variable, [$from], [$to], [$blocks],
[$color], [$name] );>

   Parameter

     variable => Referenz auf ein Skalar welches durch den
     	          Progrssbar repraesentiert werden soll

     from     => der Minimum Wert (default ist 0)

     to       => der Maximum Wert (default ist 100)

     blocks   => Die Anzahl der Bloecke zwischen
                 Minimum und Maximum (default ist 10)

     name     => Name des Progressbar [optional]

     $color   => Das Farbpaar (colorpair) muss mit
                 Curses::init_pair(pair_nr, COLOR_fg, COLOR_bg)
                 erzeugt werden[optional]

   *Beispiel*

     $pb=Paw::Progressbar->new( from=>-10, to=>10, blocks=>25, color=>3 );

Radiobutton Widget
==================

   *$rb=Paw::Radiobutton-*new(\@labels, [$direction], [$color], [$name],
[\&callback]);>

   Parameter

     \@labels   => array of label for the buttons,
                   one element for each button.

     $color     => The colorpair must be generated with
                   Curses::init_pair(pair_nr, COLOR_fg, COLOR_bg)
                   [optionally]

     $name      => name of the widget [optionally]

     \&callback => reference to a function which will be executed
                   if the radiobutton is being pressed. [optional]

     $direction => "h"orizontally or "v"ertically (default) [optionally]

   Example

     @labels=("Red", "Green", "Blue");
     $rb=Paw::Radiobutton->new(labels=>\@labels, direction=>"v");

   Callback

   Similarly as with the normal button.

set_button()
------------

   the aktive button will be set/pushed.

   Example

     $rb->set_button();

get_pressed()
-------------

   returns the number of the pressed button. (starting at 0).

   Example

     $pushed_button=$rb->get_pressed();

abs_move_widget($new_x, $new_y)
-------------------------------

   the widget moves to the new absolute screen position.  if you set only
one of the two parameters, the other one keeps the old value.

   Example

     $rb->abs_move_widget( new_x=>5 );      #y-pos is the same

get_widget_pos()
----------------

   returns an array of two values, the x-position and the y-position of
the widget.

   Example

     ($xpos,$ypos)=$rb->get_widget_pos();

set_color($color_pair)
----------------------

   Set a new color_pair for the widget.

   Example

     $box->set_color(3);

set_border(["shade"])
---------------------

   activates the border of the widget (optionally also with shadows).

   Example

     $widget->set_border("shade"); or $widget->set_border();

Radiobutton Widget
==================

   *$rb=Paw::Radiobutton::new(\@labels, [$direction], [$color], [$name],
[\&callback]);*

   Parameter

     \@labels   => Die Label fuer die Buttons.
                   Hiermit wird auch Anzahl der Buttons festgelegt.

     $color     => Das Farbpaar (colorpair) muss mit
                   Curses::init_pair(pair_nr, COLOR_fg, COLOR_bg)
                   erzeugt werden[optional]

     $name      => Name des Widgets [optional]

     \&callback => Referenz auf Function die bei betaetigen des Radiobuttons
                   angesprungen wird. [optional]

     $direction => Richtung in der die Buttons liegen sollen "h" bzw. "v"
                   (default) [optional]

   *Beispiel*

     @labels=("Red", "Green", "Blue");
     $rb=Paw::Radiobutton::new(labels=>\@labels, direction=>"v");

   Callback

   Ähnlich wie beim "normalen" Button wird bei Betaetigung des
Radiobuttons die Callback Funktion angesprungen. (perldoc Paw::Button)

set_button()
------------

   Der aktive Button wird gesetzt/gedrueckt.

   *Beispiel*

     $rb->set_button();

get_pressed()
-------------

   gibt die Nummer des Buttons zurueck der gedrueckt ist (Zaehlung
beginnend bei 0).

   *Beispiel*

     $pushed_button=$rb->get_pressed();

abs_move_widget($new_x, $new_y)
-------------------------------

   Das Widget verschiebt sich auf die neue absolute Schirm Position.  Wird
nur einer der Parameter angegeben, so behaelt der andere seinen Wert bei.

   *Beispiel*

     $rb->abs_move_widget( new_x=>5 );      #y-pos is the same

get_widget_pos()
----------------

   Gibt ein Array mit den beiden Wertde (x-Position, y-Position) zurueck.

   *Beispiel*

     ($xpos,$ypos)=$rb->get_widget_pos();

set_color($color_pair)
----------------------

   Setzt ein neues color_pair.

   *Beispiel*

     $box->set_color(3);

set_border(["shade"])
---------------------

   aktiviert den Rahmen der Box. Optional auch mit Schatten.

   *Beispiel*

     $box->set_border("shade"); or $win->set_border();

Scrollbar
=========

   *$sb=Paw::Scrollbar-*new($widget, [$name]);  #a little bit buggy>

   Parameter

     $name      => Name des Widgets [optional]

     $widget    => A reference to the widget which will be
                   "scrollbared".

   Example

     $sb=Paw::Scrollbar->new(widget=>$listbox, name=>"List Scrollbar");

Scrollbar
=========

   *$sb=Paw::Scrollbar::new($widget, [$name]);  #a little bit buggy*

   Parameter

     $name      => Name des Widgets [optional]

     $widget    => A reference to the widget which will be
                   "scrollbared".

   *Beispiel*

     $sb=Paw::Scrollbar::new(widget=>$listbox, name=>"List Scrollbar");

Textentry Widget
================

   *$te=Paw::Text_entry-*new($width, [$cursor_color], [$color], [$name],
[\&callback], [$text], [$side], [$echo], [$max_length] );>

   Parameter

     width        => width of the text-entry (in other words: columns)

     color        => the colorpair must be generated with
                   Curses::init_pair(pair_nr, COLOR_fg, COLOR_bg)
                   [optionally]

     cursor_color => same like color but only for the cursor

     name         => name of the widget [optionally]

     callback     => reference to the function that will be
                   executed each time you press a key in the entry.
                   [optionally]

     text         => default text for the entry [optionally]

     orientation  => "left"(default) or "right"
                   for left/right-justified text.

     echo         => 0, 1  oder 2 : 0=no echo of the entered text,
                   1=Stars instead of characters, 2=full echo (default)
                   (0 and 1 good for passwords) [optional]

     max_length   => maximum length of the entry (default = 1024)

   Example

     $te=Paw::Text_entry->new(width=>15, text=>"PLEASE ENTER NAME",
                                  max_length=>25);

   Callback

   The callback function will be started each time you press a key in the
text-entry.  The object reference ($this) and the key value will be given
to the callback.  This will give you the chance to allow only digits or
whatever you want.  You must return the key-value or no text will ever
reach into the widget.

   sub callback {    my $this = shift;    my $key  = shift;

     [... do some stuff ...]

     return $key;
     }

get_text()
----------

   returns the text of the entry.

   Example

     $text=$te->get_text();

set_text($text)
---------------

   set the text in the entry to $text.

   Example

     $te->set_text("default");

abs_move_widget($new_x, $new_y)
-------------------------------

   the widget moves to the new absolute screen position.  if you set only
one of the two parameters, the other one keeps the old value.

   Example

     $te->abs_move_widget( new_x=>5 );      #y-pos is the same

get_widget_pos()
----------------

   returns an array of two values, the x-position and the y-position of
the widget.

   Example

     ($xpos,$ypos)=$te->get_widget_pos();

set_color($color_pair)
----------------------

   Set a new color_pair for the widget.

   Example

     $box->set_color(3);

set_border(["shade"])
---------------------

   activates the border of the widget (optionally also with shadows).

   Example

     $widget->set_border("shade"); or $widget->set_border();

Textentry Widget
================

   *$te=Paw::Text_entry::new($width, [$color], [$name], [\&callback],
[$text], [$side], [$echo], [$max_length]);*

   Parameter

     width      => Breite des Text Entrys

     color      => Das Farbpaar (colorpair) muss mit
                   Curses::init_pair(pair_nr, COLOR_fg, COLOR_bg)
                   erzeugt werden[optional]

     name       => Name des Widgets [optional]

     callback   => Referenz auf Funktion die bei jedem Tastendruck
                   angesprungen wird. [optional]

     text       => Ein Text der im Entry stehen soll. [optional]

     orientation=> "left"(default) oder "right" fuer links- bzw.
                   rechtsbuendigen Text

     echo       => 0, 1  oder 2 : 0=keine Wiedergabe des eingegebenen Textes,
                   1=´*´ statt Buchstaben, 2=volle Widergabe (default)
                   (0 und 1 fuer z.B. Passwoerter) [optional]

     max_length => Maximale Laenge einer Eingabe (default = 1024)

   *Beispiel*

     $te=Paw::Text_entry::new(width=>15, text=>"PLEASE ENTER NAME",
                              max_length=>25);

   Callback

   Die Callback Funktion wird bei jedem Tastendruck angesprungen, dabei
wird die Objekt-Referenz ($this) sowie der Wert der gedrueckten Taste
uebergeben.  Dieser muss auch wieder zurueck gegeben werden, wenn er in
das Textentry soll.  So laesst sich eine Art Filter programmieren, der
z.B. nur Ziffern zulaesst.

   sub callback {    my $this = shift;    my $key  = shift;

     [... Programmcode ...]

     return $key;
     }

get_text()
----------

   gibt den Text des Entry's zurueck

   *Beispiel*

     $text=$te->get_text();

set_text($text)
---------------

   setzt den Text im Entry.

   *Beispiel*

     $te->set_text("default");

abs_move_widget($new_x, $new_y)
-------------------------------

   Das Widget verschiebt sich auf die neue absolute Schirm Position.  Wird
nur einer der Parameter angegeben, so behaelt der andere seinen Wert bei.

   *Beispiel*

     $te->abs_move_widget( new_x=>5 );      #y-pos is the same

get_widget_pos()
----------------

   Gibt ein Array mit den beiden Wertde (x-Position, y-Position) zurueck.

   *Beispiel*

     ($xpos,$ypos)=$te->get_widget_pos();

set_color($color_pair)
----------------------

   Setzt ein neues color_pair.

   *Beispiel*

     $box->set_color(3);

set_border(["shade"])
---------------------

   aktiviert den Rahmen der Box. Optional auch mit Schatten.

   *Beispiel*

     $box->set_border("shade"); or $win->set_border();

Textbox
=======

   *$popup=Paw::Textbox-*new($height, $width, \$text, [$color],
[$cursor_color], [$name], [$edit]);>

   Parameter

     $height       => number of rows

     $width        => number of columns

     \$text        => reference to a scalar that contains the text.

     $edit         => text edit able (0/1) default is 0

     $color        => the colorpair must be generated with
                      Curses::init_pair(pair_nr, COLOR_fg, COLOR_bg)
                      [optionally]

     $cursor_color => same like color but only for the cursor

     $name         => Name of the widget [optionally]

   Example

     $data=("This is free software with ABSOLUTELY NO WARRANTY.\n");
     $pu=Paw::Textbox->new(height=>20, width=>20, text=>\$text);

set_border(["shade"])
---------------------

   activates the border of the widget (optionally also with shadows).

   Example

     $widget->set_border("shade"); or $widget->set_border();

Textbox
=======

   *$popup=Paw::Textbox::new($height, $width, \$text, [$name], [$edit] );*

   Parameter

     $height => Anzahl der Reihen

     $width  => Anzahl der Spalten

     \$text  => Referenz auf den Text.

     $edit   => editierbarer Text ?
                (0=nein, 1=ja). Standard ist 0

   *Beispiel*

     $data=("This is free software with ABSOLUTELY NO WARRANTY.\n")
     $pu=Paw::Paw_textbox->new(height=>20, width=>20, text=>\$data);

set_border(["shade"])
---------------------

   aktiviert den Rahmen der Box. Optional auch mit Schatten.

   *Beispiel*

     $box->set_border("shade"); or $win->set_border();

Window
======

   *$window=Paw::Window-*new($height, $width, [$abs_x], [$abs_y],
[$color], [$name], [\&callback], [\$statusbar], [$orientation],
[\&time_function]);>

   Parameter

     $height         => number of rows

     $width          => number of columns

     $abs_x          => absolute x-coordinate at the screen
                        [optionally]

     $abs_y          => absolute y-coordinate at the screen
                        [optionally]

     $color          => the colorpair must be generated with
                        Curses::init_pair(pair_nr, COLOR_fg, COLOR_bg)
                        [optionally]

     $name           => name of the widget [optionally]

     \&callback      => reference to the function which will be
                        executed on each key-press.
                        [optionally]

     $quit_key       => Key-Code which terminates the window
                        [optionally]

     \@statusbar     => Reference of an array with 10 elements
                        [optionally]

     \$statusbar     => a reference on a scalar-string wich should
                        appear as text in the statusbar [optional]
                        Since it concerns a reference,
                        the text can be changed at run time.

     $orientation    => "topleft", "topright", "bottomleft",
                        "bottomright", "center"  "grow"
                        are the possible parameters.
                        They indicate how the box will behave on
                        modifications of the terminal size.
                        Either it keeps it's distance to the
                        indicated terminal side, it remains
                        centered or it grows/shrinks with
                        the new terminal size
                        (default is "center") [optionally].

     $title          => Title of the box (will be shown in the top-left
                        corner of the box [optionally]

     \&time_function => This function will be called about
                        every 0,1 seconds as long as
                        the window has the focus.

   Example

     $window=Paw::Window->new(height=>20, width=>10,
                                  color=>2, callback=>\&function,
                                  statusbar=>\$status, quit_key=>KEY_F(10));

   Callback

   The callback method usually is a loop which constantly checks the
keyboard for pressed keys and passes those key-codes to the active widget.
The internal callback routine, which one is used if none callback Function
for the window is defined, for example :

     sub Paw_main_loop {

         my $main_win = $_[0];

         my $i = "";
         $main_win->_refresh();
         while ( not $main_win->{close_it} and
                     ($i ne $main_win->{quit_key}) )
         {
             $this->{main_win} = $main_win;
             $i = getch();                  # read key
             &{$main_win->{time_function}} if ( defined $main_win->{time_function} );
             if ( $i ne -1 ) {
                 $main_win->key_press($i);  # keycode to widgetset
                 $main_win->_refresh();
             }
             else {
                 $main_win->_refresh() if ( defined $main_win->{time_function} );
             }
         };
         Curses::clear();
         $main_win->{close_it}=0;
         endwin();
     }

   if the getch() Function don't receive a key-code for about 0,1 seconds,
then it will be left again and "$i" contains the value " -1 ".
$widget->key_press($i) passes the key-code to the active widget.

get_window_parameter()
----------------------

   returns the most important parameters of the window.

   Example

     ($cols, $rows, $color)=$win->get_window_parameter();

put_dir($direction)
-------------------

   sets the pack-direction of the next widget. "v"ertically or
"h"orizontally.  This function can be walked around by using boxes.

   Example

     $win->put_dir("h");

close_win();
------------

   The window loses the focus. If no other window takes over the focus,
the program ends.

   Example

     $win->close_win();

put($widget)
------------

   put the widget into the window.

   Example

     $win->put($button0);

set_border(["shade"])
---------------------

   activate the border of the window, optionally with shadow.

   Example

     $win->set_border("shade"); oder $win->set_border();

set_focus($widget_name)
-----------------------

   Sets the focus not on the next widget but on the "$widget_name" named
one.  Required however that the widget has a name.

   Example

     $win->set_focus($button0);

abs_move_curs($new_x, $new_y);
------------------------------

   Sets the packer to the absolute position in the box (negative values
lay outside of the box).

   Example

     $win->abs_move_curs(new_y=>5, new_x=>2);

rel_move_curs($new_x, $new_y);
------------------------------

   Sets the packer relative to the current position in the box (also
negative values are possible).

   Example

     $win->rel_move_curs(new_x=>-5);

Window
======

   *$window=Paw::Window::new($height, $width, [$abs_x], [$abs_y],
[$color], [$name], [\&callback], [\$statusbar], [$orientation],
[\&time_function]);*

   Parameter

     $height         => Anzahl der Reihen (Laenge)

     $width          => Anzahl der Spalten (Breite)

     $abs_x          => Absolute x-Koordiante am Schirm [optional]

     $abs_y          => Absolute y-Koordiante am Schirm [optional]

     $color          => Das Farbpaar (colorpair) muss mit
                        Curses::init_pair(pair_nr, COLOR_fg, COLOR_bg)
                        erzeugt werden [optional]

     $name           => Name des Fensters [optional]

     \&callback      => Referenz auf Funktion die bei jedem Tastendruck
                        angesprungen wird. [optional]

     $quit_key       => Taste die das Fenster schliesst [optional]

     \@statusbar     => Referenz auf ein Array mit 10 Eintraegen [optional]

     \$statusbar     => eine Referenz auf ein Scalar welcher als Text
                        im Statusbar stehen soll [optional]
                        Da es sich um eine Referenz handelt,
                        kann sich der Text waehrend der Laufzeit aendern.

     $orientation    => "topleft", "topright", "bottomleft", "bottomright",
                        "center" und "grow" sind die moeglichen
                        Parameter. Sie geben an wie sich das
                        Fenster bei Aenderung des Terminalgroesse
                        verhaelt. Entweder behaelt es seinen
                        Abstand zu der angegebenen Seite bei,
                        es bleibt zentriert oder es waechst
                        bzw. schrumpft mit der neuen Terminalgroesse.
                        (default ist "center") [optional].

     $title          => Titel der Box (wird oben links an der Box dargestellt)
                        [optional]

     \&time_function => Die Funktion wird ca. alle 0,1 s angesprungen
                        so lange das Fenster den Focus hat.

   *Beispiel*

     $window=Paw::Window::new(height=>20, width=>10,
                              color=>2, callback=>\&function,
                              statusbar=>\$status, quit_key=>KEY_F(10));

   Callback

   Die Callback Methode ist in der Regel eine Schleife die laufend die
Tastatur abfragt und gedrueckte Tasten an die Widgets im Fenster
weitergibt. Die interne Callback Routine welche benutzt wird falls keine
Callback Function fuer das Fenster definiert wurde lautet zum Beispiel :

     sub Paw_main_loop {

         my $main_win = $_[0];

         my $i = "";
         $main_win->_refresh();
         while ( not $main_win->{close_it} and
                     ($i ne $main_win->{quit_key}) )
         {
             $this->{main_win} = $main_win;
             $i = getch();                  # read key
             &{$main_win->{time_function}} if ( defined $main_win->{time_functio
             if ( $i ne -1 ) {
                 $main_win->key_press($i);  # keycode to widgetset
                 $main_win->_refresh();
             }
             else {
                 $main_win->_refresh() if ( defined $main_win->{time_function} )
             }
         };
         Curses::clear();
         $main_win->{close_it}=0;
         endwin();
     }

   Empfaengt die getch() Function nach ca. 0.1 Sekunden keinen Tastendruck,
so wird sie wieder verlassen und die $i Variable enthaelt den Wert "-1".
Die key_press Methdode reicht die Taste an die Widgets weiter.

get_window_parameter()
----------------------

   Gibt die wichtigsten Parameter eines Fensters zurueck.

   *Beispiel*

     ($cols, $rows, $color)=$win->get_window_parameter();

put_dir($direction)
-------------------

   Setzt die Richtung in die das naechste Widget gepackt werden soll.
Direction kann "v" oder "h" fuer vertikal bzw. horizontal sein.  Diese
Funktion kann voellig durch benutzen von Boxen umgangen werden.

   *Beispiel*

     $win->put_dir("h");

close_win();
------------

   Das Fenster verliert den Focus. Wenn kein anderes Fenster den Focus
uebernimmt, kommt das dem Programmende gleich.

   *Beispiel*

     $win->close_win();

put($widget)
------------

   Packt das Widget in das Fenster.

   *Beispiel*

     $win->put($button0);

set_border(["shade"])
---------------------

   aktiviert den Rahmen des Fensters optional auch mit Schatten.

   *Beispiel*

     $win->set_border("shade"); oder $win->set_border();

set_focus($widget_name)
-----------------------

   Setzt den Focus nicht auf das eigentlich naechste Widget, sondern auf
das Übergebene. Erfordert allerdings das das Widget einen Namen hat.

   *Beispiel*

     $win->set_focus($button0);

abs_move_curs($new_x, $new_y);
------------------------------

   Setzt den Packer an die absolute Position im Fenster (negative Werte
liegen ausserhalb des Fensters).

   *Beispiel*

     $win->abs_move_curs(new_y=>5, new_x=>2);

rel_move_curs($new_x, $new_y);
------------------------------

   Setzt den Packer relativ zur momentanen Position im Fenster (auch
negative Werte moeglich).

   *Beispiel*

     $win->rel_move_curs(new_x=>-5);

provides easy access to Penguin module.
***************************************

NAME
====

     Penguin::Easy -- provides easy access to Penguin module.

SYNOPSIS
========

     use Penguin::Easy;
     my $ep = new Penguin::Easy Title => 'Easy Program',
     			     Name => 'James Duncan',
     			     Sig => $my_pgp_sig,
     			     Code => $my_perl_code;
     $results = $ep->run;
     print "$results\n";

DESCRIPTION
===========

   `Penguin::Easy' is an OO module, that provides quick-and-dirty access
to the penguin module for those not wanting to learn the nittygrittys
about it.  The Easy module provides transparent access to the `Penguin'
module, even to the extent of deciding whether the Penguin code should be
transparently wrapped, or PGP wrapped (if you include a sig in the call to
the new method,  it will use PGP).

NOTES
=====

   While writing this little module,  I've decided that `Wrapper' is
perhaps one of the funniest words I have ever seen.  It has completly lost
all meaning.

Perl extension wrapper for the ARM 2.0 implementation
*****************************************************

NAME
====

   Perf::ARM - Perl extension wrapper for the ARM 2.0 implementation

SYNOPSIS
========

     use Perf::ARM;

     my ($appl_id,$tran_handle, $tran_id, $rc);

     ($appl_id=Perf::ARM::arm_init( "$0", "*", 0,0,0)) ||
       die "arm_init() failed \n";
     $tran_id=Perf::ARM::arm_getid($appl_id, "simple_tran",
       "detail_$$", 0,0,0);
     $tran_handle=Perf::ARM::arm_start($tran_id, 0,0,0);

     #  do the unit of work to be measured
     &do_my_work(@my_args)

     $rc=Perf::ARM::arm_stop($tran_handle, 0, 0,0,0);

     $rc=Perf::ARM::arm_end($appl_id, 0,0,0);

DESCRIPTION
===========

   This serves as a simple wrapper around the ARM C routines:

   arm_init(char *,char *,long ,char *,long );     [ returns long  ]

   arm_getid(long ,char *,char *,long ,char *,long );     [ returns long  ]

   arm_start(long ,long ,char *,long );     [ returns long  ]

   arm_update(long ,long ,char *,long );     [ returns long  ]

   arm_stop(long ,long ,long ,char *,long );     [ returns long  ]

   arm_end(long ,long ,char *,long );     [ returns long  ]

Exported functions, with ARM defines
====================================

     extern arm_int32_t  arm_init(
       char*        appl_name,
       char*        appl_user_id,
       arm_int32_t  flags,
       char*        data,
       arm_int32_t  data_size);
     extern arm_int32_t  arm_getid(
       arm_int32_t  appl_id,
       char*        tran_name,
       char*        tran_detail,
       arm_int32_t  flags,
       char*        data,
       arm_int32_t  data_size);
     extern arm_int32_t  arm_start(
       arm_int32_t  tran_id,
       arm_int32_t  flags,
       char*        data,
       arm_int32_t  data_size);
     extern arm_int32_t  arm_update(
       arm_int32_t  start_handle,
       arm_int32_t  flags,
       char*        data,
       arm_int32_t  data_size);
     extern arm_int32_t  arm_stop(
       arm_int32_t  start_handle,
       arm_int32_t  tran_status,
       arm_int32_t  flags,
       char*        data,
       arm_int32_t  data_size);
     extern arm_int32_t  arm_end(
       arm_int32_t  appl_id,
       arm_int32_t  flags,
       char*        data,
       arm_int32_t  data_size);

AUTHOR
======

   bryan_backer@hp.com

SEE ALSO
========

   ARM FAQ at http://www.cmg.org/regions/cmgarmw/armfaq.html

   Glance docs at http://www.openview.hp.com/products/

   CMG ARM Working Group info page at http://www.cmg.org/regions/cmgarmw/

   HP-UX: /opt/perf/include/arm.h or /usr/include/arm.h

frame class to transform PerlPoint::Parser output
*************************************************

NAME
====

   PerlPoint::Backend - frame class to transform PerlPoint::Parser output

VERSION
=======

   This manual describes version *0.07*.

SYNOPSIS
========

     # load the module:
     use PerlPoint::Backend;

     # build the backend
     my ($backend)=new PerlPoint::Backend(name=>'synopsis');

     # register handlers
     $backend->register(DIRECTIVE_BLOCK, \&handleBlock);
     $backend->register(DIRECTIVE_COMMENT, \&handleComment);
     $backend->register(DIRECTIVE_DOCUMENT, \&handleDocument);
     $backend->register(DIRECTIVE_HEADLINE, \&handleHeadline);
     $backend->register(DIRECTIVE_POINT, \&handlePoint);
     $backend->register(DIRECTIVE_SIMPLE, \&handleSimple);
     $backend->register(DIRECTIVE_TAG, \&handleTag);
     $backend->register(DIRECTIVE_TEXT, \&handleText);
     $backend->register(DIRECTIVE_VERBATIM, \&handleVerbatim);

     # finally run the backend
     $backend->run(\@streamData);

DESCRIPTION
===========

   After an ASCII text is parsed by an PerlPoint::Parser object, the
original text is transformed into stream data hold in a Perl array. To
process this intermediate stream further (mostly to generate output in a
certain document description language), a program has to walk through the
stream and to process its tokens.

   Well, PerlPoint::Backend provides a class which encapsulates this walk
in objects which deal with the stream, while the translator programmer is
focussed on generating the final representation of the original text. This
is done by registering handlers which will be called when their target
objects are discovered in the intermediate stream.

METHODS
=======

new()
-----

   The constructor builds and prepares a new backend object. You may have
more than one object at a certain time, they work independently.

   Parameters: All parameters except of the class parameter are named
(pass them by hash).

class
     The class name.

name
     Because there can be more than exactly one backend object, your object
     should be named. This is not necessarily a need but helpful reading
     traces.

trace
     This parameter is optional. It is intended to activate trace code
     while the object methods run. You may pass any of the "TRACE_..."
     constants declared in PerlPoint::Constants, combined by addition as
     in the following example:

          trace => TRACE_NOTHING+TRACE_BACKEND,

     In fact, only TRACE_NOTHING and TRACE_BACKEND take effect to backend
     objects.

     If you omit this parameter or pass TRACE_NOTHING, no traces will be
     displayed.

display
     This parameter is optional. It controls the display of runtime
     messages like informations or warnings in all object methods. By
     default, all messages are displayed. You can suppress these
     informations partially or completely by passing one or more of the
     "DISPLAY_..." variables declared in PerlPoint::Constants.

     Constants can be combined by addition.

   *Returns:* the new object.

   Example:

     my ($parser)=new PerlPoint::Backend(name=>'example');

register()
----------

   After building a new object by new() the object can be prepared by
calls of the register method.

   If the object walks through the data stream generated by
PerlPoint::Parser, it will find several directives. A directive is a data
struture flagging that a certain document part (or even formatting) starts
or is completed.  E.g. a headline is represented by headline start
directive followed by tokens for the headline contents followed by a
headline completion directive.

   By using this method, you can register directive specific functions
which should be called when the related directives are discovered. The
idea is that such a function can produce a target language construct
representing exactly the same document token that is modelled by the
directive. E.g. if your target language is HTML and you register a
headline handler and a headline start is found, this handler can generate
a "<HEAD>" tag. This is quite simple.

   According to this design, the object will pass the following data to a
registered function:

directive
     the directive detected, this should be the same the function was
     registered for. See PerlPoint::Constants for a list of directives.

start/stop flag
     The document stream generated by the parser is strictly synchronous.
     Everything except of plain strings is represented by an open directive
     and a close directive, which may embed other parts of the document.
     A headline begins, something is in, then it is complete. It's the
     same for every tag or paragraph and even for the whole document.

     So well, because of this structure, a handler registered for a certain
     directive is called for opening directives as well as for closing
     directives. To decide which case is true, a callback receives this
     parameter. It's always one of the constants DIRECTIVE_START or
     DIRECTIVE_COMPLETED.

     For simple strings (words, spaces etc.) and line number hints, the
     callback will always be called with DIRECTIVE_START.

directive values, if available
     Certain directives provide additional data such as the headline level
     or the original documents name which are passed to their callbacks
     additionally.  See the following list:

    Documents
          transfer the *basename* of the original ASCII document being
          parsed;

    Headlines
          transfer the headline level;

    Ordered list points
               optionally transfer a fix point number;

    Tags
          transfer the tag name ("I", "B" etc.).

   To express this by a prototype, all registered functions should have an
interface of "$$:@".

   Parameters:

object
     a backend object as made by new();

directive
     the directive this handler is registered for. See
     PerlPoint::Constants for a list of directives.

handler
     the function to be called if a pointed directive is entered while the
     run() method walks through the document stream.

   *Returns:* no certain value;

   Example:

     $backend->register(DIRECTIVE_HEADLINE, \&handleHeadline);

   where handleHeadline could be something like

     sub handleDocument
      {
       my ($directive, $startStop, $level)=@_;
       confess "Something is wrong\n"
         unless $directive==DIRECTIVE_HEADLINE;
       if ($startStop==DIRECTIVE_START)
         {print "<head$level>";}
       else
         {print "</head>";}
      }

SEE ALSO
========

PerlPoint::Parser
     A parser for Perl Point ASCII texts.

PerlPoint::Constants
     Public PerlPoint::... module constants.

AUTHOR
======

   Jochen Stenzel (perl@jochen-stenzel.de), 1999-2000. All rights reserved.

   This module is free software, you can redistribute it and/or modify it
under the terms of the Artistic License distributed with Perl version
5.003 or (at your option) any later version. Please refer to the Artistic
License that came with your Perl distribution for more details.

   The Artistic License should have been included in your distribution of
Perl. It resides in the file named "Artistic" at the top-level of the Perl
source tree (where Perl was downloaded/unpacked - ask your system
administrator if you dont know where this is).  Alternatively, the current
version of the Artistic License distributed with Perl can be viewed
on-line on the World-Wide Web (WWW) from the following URL:
http://www.perl.com/perl/misc/Artistic.html

DISCLAIMER
==========

   This software is distributed in the hope that it will be useful, but is
provided "AS IS" WITHOUT WARRANTY OF ANY KIND, either expressed or
implied, INCLUDING, without limitation, the implied warranties of
MERCHANTABILITY and FITNESS FOR A PARTICULAR PURPOSE.

   The ENTIRE RISK as to the quality and performance of the software IS
WITH YOU (the holder of the software).  Should the software prove
defective, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
CORRECTION.

   IN NO EVENT WILL ANY COPYRIGHT HOLDER OR ANY OTHER PARTY WHO MAY CREATE,
MODIFY, OR DISTRIBUTE THE SOFTWARE BE LIABLE OR RESPONSIBLE TO YOU OR TO
ANY OTHER ENTITY FOR ANY KIND OF DAMAGES (no matter how awful - not even
if they arise from known or unknown flaws in the software).

   Please refer to the Artistic License that came with your Perl
distribution for more details.

public PerlPoint::... module constants
**************************************

NAME
====

   PerlPoint::Constants - public PerlPoint::... module constants

VERSION
=======

   This manual describes version *0.11*.

DESCRIPTION
===========

   The module declares a number of constants shared between other
*PerlPoint::...* modules.

SYNOPSIS
========

   The usage of the provided constants is described in the manuals of the
using modules PerlPoint::Parser and PerlPoint::Backend.

CONSTANTS
=========

Stream directive constants
--------------------------

   These constants are built into *directives* which the parser produces
in its output (that is, the representation format it translates an ASCII
text in to be subsequently processed by a backend).

DIRECTIVE_BLOCK
     flags a block paragraph;

DIRECTIVE_COMMENT
     flags a comment;

DIRECTIVE_COMPLETE
     a format entity is completed;

DIRECTIVE_DOCUMENT
     flags a complete document (made from one ASCII file);

DIRECTIVE_DLIST
     flags a "definition list";

DIRECTIVE_DPOINT
     flags a "definition point" paragraph;

DIRECTIVE_DPOINT_ITEM
     flags a "definition point" item (the stuff to be defined);

DIRECTIVE_HEADLINE
     flags a headline;

DIRECTIVE_LIST_LSHIFT
     control directive, shift a list left;

DIRECTIVE_LIST_RSHIFT
     control directive, shift a list right;

DIRECTIVE_NEW_LINE
     a backend hint to inform about a new source line;

DIRECTIVE_OLIST
     flags an "ordered list";

DIRECTIVE_OPOINT
     flags an "ordered point" paragraph;

DIRECTIVE_SIMLPE
     a pseudo directive, used to flag simple strings in backends;

DIRECTIVE_START
     a format entity starts;

DIRECTIVE_TAG
     flags a tag;

DIRECTIVE_TEXT
     flags a text paragraph;

DIRECTIVE_ULIST
     flags an "unordered list";

DIRECTIVE_UPOINT
     flags an "unordered point" paragraph;

DIRECTIVE_VARSET
     a backend hint propagating a variable setting;

DIRECTIVE_VERBATIM
     flags a verbatim block paragraph;

Trace constants
---------------

   They activate trace code.

TRACE_BACKEND
     activates backend traces;

TRACE_LEXER
     activates the traces of the lexical analysis.

TRACE_NOTHING
     deactivates all trace codes. (In fact, it *does not activate* any
     trace.  If you decide to combine it with other trace constants, it
     will cause nothing.)

TRACE_PARAGRAPHS
     activates traces which show the paragraphs recognized when they are
     entered or completed.

TRACE_PARSER
     activates the traces of the syntactical analysis.

TRACE_SEMANTIC
     activates the traces of the semantic analysis.

TRACE_ACTIVE
     activates the traces of active contents evaluation.

Display constants
-----------------

   determine if information messages should be suppressed.

DISPLAY_ALL
     all messages are displayed. (More correctly, no message is suppressed.
     If you combine this constant with other display constants, it will
     take no effect.)

DISPLAY_NOINFO
     suppresses information messages;

DISPLAY_NOWARN
     suppresses warnings;

Cache constants
---------------

   specify how presentation files shall be cached.

CACHE_OFF
     Files are reparsed completely regardless of cache data. Existing
     cache data remain untouched.

CACHE_ON
     While reading the presentation descriptions, cached and unchanged
     paragraphs are reloaded from the cache if possible. New or modified
     paragraphs are stored to accelerate repeated reading.

     Please note that this will not overwrite or remove previously stored
     cache data for modified or deleted paragraphs. Old cache data remains
     in the cache, while new data is added - the cache size continously
     grows.

CACHE_CLEANUP
     Cleans up an existing cache before the parser starts (and possibly
     rebuilds it).

SEE ALSO
========

PerlPoint::Parser
     A parser for Perl Point ASCII texts.

PerlPoint::Backend
     A frame class to write Perl Point backends.

AUTHOR
======

   Copyright (c) Jochen Stenzel (perl@jochen-stenzel.de), 1999-2000. All
rights reserved.

   This module is free software, you can redistribute it and/or modify it
under the terms of the Artistic License distributed with Perl version
5.003 or (at your option) any later version. Please refer to the Artistic
License that came with your Perl distribution for more details.

   The Artistic License should have been included in your distribution of
Perl. It resides in the file named "Artistic" at the top-level of the Perl
source tree (where Perl was downloaded/unpacked - ask your system
administrator if you dont know where this is).  Alternatively, the current
version of the Artistic License distributed with Perl can be viewed
on-line on the World-Wide Web (WWW) from the following URL:
http://www.perl.com/perl/misc/Artistic.html

DISCLAIMER
==========

   This software is distributed in the hope that it will be useful, but is
provided "AS IS" WITHOUT WARRANTY OF ANY KIND, either expressed or
implied, INCLUDING, without limitation, the implied warranties of
MERCHANTABILITY and FITNESS FOR A PARTICULAR PURPOSE.

   The ENTIRE RISK as to the quality and performance of the software IS
WITH YOU (the holder of the software).  Should the software prove
defective, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
CORRECTION.

   IN NO EVENT WILL ANY COPYRIGHT HOLDER OR ANY OTHER PARTY WHO MAY CREATE,
MODIFY, OR DISTRIBUTE THE SOFTWARE BE LIABLE OR RESPONSIBLE TO YOU OR TO
ANY OTHER ENTITY FOR ANY KIND OF DAMAGES (no matter how awful - not even
if they arise from known or unknown flaws in the software).

   Please refer to the Artistic License that came with your Perl
distribution for more details.

a PerlPoint Parser
******************

NAME
====

   PerlPoint::Parser - a PerlPoint Parser

VERSION
=======

   This manual describes version *0.32*.

SYNOPSIS
========

     # load the module:
     use PerlPoint::Parser;

     # build the parser and run it
     # to get intermediate data in @stream
     my ($parser)=new PerlPoint::Parser;
     $parser->run(
                  stream  => \@stream,
                  tags    => \%tags,
                  files   => \@files,
                 );

DESCRIPTION
===========

   The PerlPoint format, initially designed by Tom Christiansen, is
intended to provide a simple and portable way to generate slides without
the need of a proprietary product. Slides can be prepared in a text editor
of your choice, generated on a any platform where you find perl, and
presented by any browser which can render the chosen output format.

   To sum it up, *PerlPoint Software takes an ASCII text and transforms it
into slides written in a certain document description language.* This is,
by tradition, usually HTML, but you may decide to use another format like
XML, SGML, TeX or whatever you want.

   Well, this sounds fine, but how to build a translator which transforms
ASCII into the output format of your choice? Thats what PerlPoint::Parser
is made for.  It performs the first translation step by parsing ASCII and
transforming it into an intermediate stream format, which can be processed
by a subsequently called translator backend. By separating parsing and
output generation we get the flexibility to write as many backends as
necessary by using the same parser frontend for all translators.

   PerlPoint::Parser supports the complete GRAMMAR with exception of
*certain* tags. Tags *are* supported the *most common way*: the parser
recognizes any tag which is declared by the author of a translator. This
way the parser can be used for various flavours of the PerlPoint language
without having to be modified. So, if there is a need of a certain new
flag, it can quickly be added without any change to PerlPoint::Parser.

   The following chapters describe the input format (GRAMMAR) and the
generated stream format (STREAM FORMAT). Finally, the class methods are
described to show you how to build a parser.

GRAMMAR
=======

   This chapter describes how a PerlPoint ASCII slide description has to be
formatted to pass PerlPoint::Parser parsers.

   *Please note* that the input format does not completely determine how
the output will be designed. The final format depends on the backend which
has to be called after the parser to transform its output into a certain
document description language. The final *appearance* depends on the
*browsers* behaviour.

   Each PerlPoint document is made of paragraphs.

The paragraphs
--------------

   All paragraphs start at the beginning of their first line. The first
character or string in this line determines which paragraph is recognized.

   A paragraph is completed by an empty line (which may contain
whitespaces).  Exceptions are described.

   Carriage returns in paragraphs which are completed by an empty line are
transformed into a whitespace

Comments
     start with "//" and reach until the end of the line.

Headlines
     start with one or more  "=" characters.  The number of "=" characters
     represents the headline level.

          =First level headline

          ==Second level headline

          ===Multi
            line
           headline
          example

Lists
     *Points* or *unordered lists* start with a "*" character.

          * This is a first point.

          * And, I forgot,
            there is something more to point out.

     There are *ordered lists* as well, and *they* start with a hash sign
     ("#"):

          # First, check the number of this.

          # Second, don't forget the first.

     The hash signs are intended to be replaced by numbers by a backend.

     Because PerlPoint works on base of paragraphs, any paragraph
     different to an ordered list point *closes an ordered list*. If you
     wish the list to be continued use a double hash sign in case of the
     single one in the point that reopens the list.

          # Here the ordered list begins.

          ? $includeMore

          ## This is point 2 of the list that started before.

          # In subsequent points, the usual single hash sign works as
            expected again.

     List continuation works list level specific (see below for level
     details).  A list cannot be continued in another chapter. Using "##"
     in the first point of a new list takes no special effect: the list
     will begin as usual (with number 1).

     *Definition lists* are a third list variant. Each item starts with the
     described phrase enclosed by a pair of colons, followed by the
     definition text:

          :first things: are usually described first,

          :others:       later then.

     All lists can be nested. A new level is introduced by a special
     paragraph called *"list indention"* which starts with a ">". A list
     level can be terminated by a *"list indention stop"* paragraph
     containing of a "<" character. (These startup characters symbolize
     "level shifts".)

          * First level.

          * Still there.

     >

          * A list point of the 2nd level.

     <

          * Back on first level.

     Level shifts are accepted between list items *only*.

Texts
     are paragraphs like points but begin *immediatly* without a startup
     character:

          This is a simple text.

          In this new text paragraph,
          we demonstrate the multiline feature.

Blocks
     are intended to contain examples or code with tag recognition.  This
     means that the parser will discover embedded tags. On the other hand,
     it means that one may have to escape ">" characters outside tags.
     Blocks begin with an *indentation* and are completed by the next
     empty line.

          * Look at these examples:

          A block.

          I<Another> block.
          Escape "\>".

          Examples completed.

     Subsequent blocks are joined together automatically: the intermediate
     empty lines which would usually complete a block are translated into
     real empty lines *within* the block. This makes it easier to
     integrate real code sequences as one block, regardless of the empty
     lines included. However, one may explicitly *wish* to separate
     subsequent blocks and can do so by delimiting them by a special
     control paragraph:

          * Separated subsequent blocks:

          The first block.

          -

          The second block.

Verbatim blocks
     are similar to blocks in indentation but deactivate pattern
     recognition. That means the embedded text is not scanned for tags and
     empty lines and may therefore remain as it was in its original place,
     possibly a script.

     These special blocks need a special syntax. They are realized as here
     documents.  Start with a here document clause flagging which string
     will close the "here document":

          <<EOC

          # compare
          $rc=3>2?4:5; # contains ">" which has not to be escaped;

          EOC

Tables
     are supported as well, they start with an @ sign which is followed by
     the column delimiter:

          @|
           column 1   |   column 2   |  column 3
            aaa       |    bbb       |   ccc
            uuu       |    vvvv      |   www

     There is also a more sophisticated way to describe tables, see the
     tag section below.

Conditions
     start with a  "?" character. If active contents is enabled, the
     paragraph text is evaluated as Perl code. The (boolean) evaluation
     result then determines if subsequent PerlPoint is read and parsed. If
     the result is false, all subsequent paragraphs until the next
     condition are *skipped*.

     Note that base data is made available by a hash global (package) hash
     reference $PerlPoint. See run() for details about how to set these
     data up.

     Conditions can be used to maintain various language versions of a
     presentation in one source file:

          ? $PerlPoint->{targetLanguage} eq 'German'

     Or you could enable parts of your document by date:

          ? time>$dateOfTalk

     or by a special setting:

          ? $PerlPoint->{userSettings}{setting}

     Please note that the condition code shares its variables with
     embedded and included code.

     To make usage easier and to improve readability, condition code is
     evaluated with disabled warnings (the language variable in the
     example above may not even been set).

     Translator authors might want to provide predefined variables such as
     "$language" in the example.

Variable assignment paragraphs
     Variables can be used in the text and will be automatically replaced
     by their string values (if declared).

          The next paragraph sets a variable.

          $var=var

          This variable is called $var.

     All variables are made available to embedded and included Perl code
     as well as to conditions and can be accessed there as package
     variables of "main::" (or whatever package name the Safe object is
     set up to). Because a variable is already replaced by the parser if
     possible, you have to use the fully qualified name or to guard the
     variables "$" prefix character to do so:

          \EMBED{lang=perl}join(' ', $main::var, \$var)\END_EMBED

     Variable modifications by embedded or included Perl *do not* affect
     the variables visible to the parser. (This is true for conditions as
     well.) This means that

          $var=10
          \EMBED{lang=perl}$main::var*=2;\END_EMBED

     causes *$var* to be different on parser and code side - the parser
     will still use a value of 10, while embedded code works on with a
     value of 20.

Macro or alias definitions
     Sometimes certain text parts are used more than once. It would be a
     relieve to have a shortcut instead of having to insert them again and
     again. The same is true for tag combinations a user may prefer to
     use. That's what aliases (or "macros") are designed for. They allow a
     presentation author to declare his own shortcuts and to use them like
     a tag. The parser will resolve such aliases, replace them by the
     defined replacement text and work on with this replacement.

     An alias declaration starts with a "+" character followed
     *immediately* by the alias name (without backslash prefix), followed
     *immediately* by a colon.  (No additional spaces here.)  *All text
     after this colon up to the paragraph closing empty line is stored as
     the replacement text.* So, whereever you will use the new macro, the
     parser will replace it by this text and *reparse* the result.  This
     means that your macro text can contain any valid construction like
     tags or other macros.

     The replacement text may contain strings embedded into doubled
     underscores like "__this__". This is a special syntax to mark that
     the macro takes parameters of these names (e.g. "this"). If a tag is
     used and these parameters are set, their values will replace the
     mentioned placeholders. The special placeholder "__body__" is used to
     mark the place where the macro body is to place.

     Here are a few examples:

          +RED:\FONT{color=red}<__body__>

          +F:\FONT{color=__c__}<__body__>

          +IB:\B<\I<__body__>>

          This \IB<text> is \RED<colored>.

          +TEXT:Macros can be used to abbreviate longer
          texts as well as other tags
          or tag combinations.

          +HTML:\EMBED{lang=html}

          Tags can be \RED<\I<nested>> into macros. And \I<\F{c=blue}<vice versa>>.
          \IB<\RED<This>> is formatted by nested macros.
          \HTML This is <i>embedded HTML</i>\END_EMBED.

          Please note: \TEXT

     An empty macro text *undefines* the macro (if it was already known).

          // undeclare the IB alias
          +IB:

     Please note that the current implementation is still called
     experimental because there may be still untested cases.

     An alias can be used like a tag.

Tags
----

   Tags are directives embedded into the text stream, commanding how
certain parts of the text should be interpreted.

   PerlPoint::Parser parsers can recognize all tags which are build of a
backslash and a number of alphanumeric characters (usually capitals).

     \TAG

   *Tag options* are optional and follow the tag name immediately, enclosed
by a pair of corresponding curly braces. Each option is a simple string
assignment. The value should be quoted if /^\w+$/ does not match it.

     \TAG{par1=value1 par2="www.perl.com" par3="words and blanks"}

   The *tag body* is anything you want to make the tag valid for. It is
optional as well and immediately follows the optional parameters, enclosed
by "<" and ">":

     \TAG<body>
     \TAG{par=value}<body>

   Tags can be nested.

   To provide a maximum of flexibility, tags are declared *outside* the
parser.  This way a translator programmer is free to implement the tags he
needs. It is recommended to always support the basic tags *\I*, *\B*, *\C*
and *\IMAGE*. On the other hand,a few tags of special meaning are reserved
and cannot be declared by users, because they are handled by the parser
itself. These are:

\INCLUDE
     It is possible to include a file into the input stream. Have a look:

          \INCLUDE{type=HTML file=filename}

     This imports the file "filename". The file contents is made part of
     the generated stream, but not parsed. This is useful to include
     target language specific, preformatted parts.

     If, however, the file type is specified as "PP", the file contents is
     made part of the input stream and parsed. In this case a special tag
     option "headlinebase" can be specified to define a headline base
     level used as an offset to all headlines in the included document.
     This makes it easier to share partial documents with others, or to
     build complex documents by including separately maintained parts, or
     to include one and the same part at different headline levels.

          Example: If "\INCLUDE{type=PP file=file headlinebase=20}" is
                   specified and "file" contains a one level headline
                   like "=Main topic of special explanations"
                   this headline is detected with a level of 21.

     Pass the special keyword "CURRENT_LEVEL" to this tag option if you
     want to set just the current headline level as an offset. This
     results in "subchapters".

          Example:

          ===Headline 3

          \INCLUDE{type=PP file=file headlinebase=CURRENT_LEVEL}

     A given offset is reset when the included document is parsed
     completely.

     A second special option *smart* commands the parser to include the
     file only unless this was already done before. This is intended for
     inclusion of pure alias/macro definition or variable assignment files.

          \INCLUDE{type=PP file="common-macros.pp" smart=1}

     A PerlPoint file can be included wherever a tag is allowed, but
     sometimes it has to be arranged slightly: if you place the inclusion
     directive at the beginning of a new paragraph and your included
     PerlPoint starts by a paragraph of another type than text, you should
     begin the included file by an empty line to let the parser detect the
     correct paragraph type. Here is an example: if the inclusion
     directive is placed like

          // include PerlPoint
          \INCLUDE{type=pp file="file.pp"}

     and file.pp immediately starts with a verbatim block like

          <<VERBATIM
              verbatim
          VERBATIM

     , *the inclusion directive already opens a new paragraph* which is
     detected to be "text" (because there is no special startup
     character). Now in the included file, from the parsers point of view
     the included PerlPoint is simply a continuation of this text, because
     a paragraph ends with an empty line. This trouble can be avoided by
     beginning such an included file by an empty line, so that its first
     paragraph can be detected correctly.

     The second special case is a file type of "Perl". If active contents
     is enabled, included Perl code is read into memory and evaluated like
     *embedded* Perl. The results are made part of the input stream to be
     parsed.

          // execute a perl script and include the results
          \INCLUDE{type=perl file="disk-usage.pl"}

     As another option files may be declared to be of type "example". This
     makes the file placed into the source as a verbatim block, without
     need to copy its contents into the source.

          // include an external script as an example
          \INCLUDE{type=example file="script.csh"}

     All lines of the example file are included as they are but can be
     indented on request.  To do so, just set the special option "indent"
     to a positive numerical value equal to the number of spaces to be
     inserted before each line.

          // external example source, indented by 3 spaces
          \INCLUDE{type=example file="script.csh" indent=3}

     Including external scripts this way can accelerate PerlPoint
     authoring significantly, especially if the included files are still
     subject to changes.

     It is possible to filter the file types you wish to include (with
     exception of "pp" and "example"), see below for details. *In any
     case*, the mentioned file has to exist.

\EMBED and \END_EMBED
     Target format code does not necessarily need to be imported - it can
     be directly *embedded* as well. This means that one can write target
     language code within the input stream using \EMBED:

          \EMBED{lang=HTML}
          This is <i><b>embedded</b> HTML</i>. The parser detects <i>no</i>
          PerlPoint tag here, except of <b>END_EMBED</b>.
          \END_EMBED

     Because this is handled by tags, not by paragraphs, it can be placed
     directly in a text like this:

          These \EMBED{lang=HTML}<i>italics</i>\END_EMBED are formatted
          by HTML code.

     Please note that the EMBED tag does not accept a tag body to avoid
     ambigities.

     Both tag and embedded text are made part of the intermediate stream.
     It is the backends task to deal with it. The only exception of this
     rule is the embedding of Perl code, which is evaluated by the parser.
     The reply of this code is made part of the input stream and parsed as
     usual.

     It is possible to filter the languages you wish to embed (with
     exception of "PP"), see below for details.

\TABLE and \END_TABLE
     It was mentioned above that tables can be build by table paragraphs.
     Well, there is a tag variant of this:

          \TABLE{bg=blue separator="|" border=2}
          \B<column 1>  |  \B<column 2>  | \B<column 3>
             aaaa       |     bbbb       |  cccc
             uuuu       |     vvvv       |  wwww
          \END_TABLE

     This is sligthly more powerfull than the paragraph syntax: you can set
     up several table features like the border width yourself, and you can
     format the headlines as you like.

What about special formatting?
------------------------------

   Earlier versions of pp2html supported special format hints like the HTML
expression "&gt;" for the ">" character, or "&uuml;" for "ü".
PerlPoint::Parser does not support this directly because such hints are
specific to the *output format* - if someone wants to translate into TeX,
it might be curious for him to use HTML syntax in his ASCII text. Further
more, such hints can be handled *completely* by a backend which finds them
unchanged in the produced output stream.

   The same is true for special headers and trailers. It is a backend task
to add them if necessary. The parser does handle the input only.

STREAM FORMAT
=============

   It is suggested to use PerlPoint::Backend to evaluate the intermediate
format.  Nevertheless, here is the documentation of this format.

   The generated stream is an array of tokens. Most of them are very simple
representing just their contents - words, spaces and so on. Example:

     "These three words."

   would be streamed into

     "These" + " " + "three" + " "+ "words."

   Note that the final dot *is part* of the last token. From a document
description view, this should make no difference, its just a string
containing special characters or not.

   Well, besides this "main stream", there are *formatting directives*.
They flag the *beginning* or *completion* of a certain format - this means
a whole document, a paragraph or a real formatting like italicising. Every
format is *embedded* into a start and a completion directive - except of
simple tokens.

   In the current implementation, a directive is a reference to an array
of mostly two fields: a directive constant showing which format is
related, and a start or completion hint, which is a constant, too. The
used constants are declared in PerlPoint::Constants. Directives can pass
additional informations in additional fields. By now, the headline
directives use this feature to show the headline level, as well as the tag
ones to provide tag type information and the document ones to keep the
name of the original document. Further more, ordered list point can
request a fix number this way.

     # this example shows a tag directive
     ... [DIRECTIVE_TAG, DIRECTIVE_START, "I"]
     + "formatted" + " " + "strings"
     + [DIRECTIVE_TAG, DIRECTIVE_COMPLETE, "I"] ...

   To recognize whether a token is a basic or a directive, the ref()
function can be used. However, this handling should be done by
PerlPoint::Backend transparently and is documented here for information
purposes only.

   Original line numbers are no part of the stream.

   This is the complete generator format. It is designed to be simple but
powerful.

METHODS
=======

new()
-----

   The constructor builds and prepares a new parser object.

   Parameters:

The class name.
   *Return value:* The new object in case of success.

   Example:

     my ($parser)=new PerlPoint::Parser;

run() This function starts the parser for a number of passed files.
-------------------------------------------------------------------

   Parameters: All parameters except of the object parameter are named
(pass them by hash).

activeBaseData
     This optional parameter allows to pass common data to all active
     contents (conditions, embedded and included Perl) by a *hash
     reference*. By convention, a translator at least passes the target
     language and user settings by

          activeBaseData => {
                             targetLanguage => "lang",
                             userSettings   => \%userSettings,
                            },

     User settings are intended to allow the specification of per call
     settings by a user, e.g. to include special parts. By using this
     convention, users can easily specify such a part the following way

          ? $PerlPoint->{userSettings}{setting}

          Special part.

          ? 1

     It is up to a translator author to declare translator specific
     settings (and to document them). The passed values can be as complex
     as necessary as long as it can be duplicated by `Storable::dclone()'.

     Whenever active contents is invoked, the passed hash reference is
     copied (duplicated by `Storable::dclone()') into the Safe objects
     namespace (see safe) as a global variable $PerlPoint. This way,
     modifications by invoked code do not effect subsequently called code
     snippets, base data are always fresh.

activeDataInit
     Reserved to pass hook functions to be called preparing every active
     contents invokation. *The hook is still unimplemented.*

cache
     This optional parameter controls source file paragraph caching.

     By default, a source file is parsed completely everytime you pass it
     to the parser. This is no problem with tiny sources but can delay
     your work if you are dealing with large sources which have to be
     translated periodically into presentations while they are written.
     Typically most of the paragraphs remain unchanged from version to
     version, but nevertheless everything is usually reparsed which means
     a waste of time. Well, to improve this a paragraph cache can be
     activated by setting this option to CACHE_ON.

     The parser caches each *initial source file* individually. That means
     that if three files are passed to the parser with activated caching,
     three cache files will be written. They are placed in the source file
     directory, named .<source file>.ppcache. Please note that the
     paragraphs of *included* sources are cached in the cache file of the
     main document because they may have to be evaluated differently
     depending on inclusion context.

     What acceleration can be expected? Well, this *strongly* depends on
     your source structure. Efficiency will grow with longer paragraphs,
     reused paragraphs and paragraph number. It will be reduced by heavy
     usage of active contents, macros and embedding because every
     paragraph that refers to parts defined externally is not strongly
     determined by itself and therefore it cannot be cached. Here is a
     list of all reasons which cause a paragraph to be excluded from
     caching:

    Usage of variables
          Every occurence of anything looking like a replacable variable
          (`$var' or `${var}').  Even if this variable has no assigned
          value at caching time, this could have been changed when the
          paragraph will be reread later.

    Usage of macros
          A macro means "unreproducable contents" because its definition
          is (potentially) subject to changes.

    Embedded parts
          Obviously dynamic parts may change from one version to another,
          but even static parts could have to be interpreted differently
          because a user can set up new filters.

    Included files
          An \INCLUDE tag immediately disables caching for the paragraph
          it resides in because the loaded file may change its contents.
          This is not really a restriction because the included paragraphs
          themselves *are* cached if possible.

     Even with all these restrictions about 50% of a real life document of
     more than 150 paragraphs (with a large number of used macros) could
     be cached. This saved 20% of the runtime in subsequent parser calls
     (with the pp2html translator by Lorenz Domke).

     New cache entries are always added which means that old entries are
     never replaced and a cache file tends to grow. If you ever wish to
     clean up a cache file completely pass CACHE_CLEANUP to this option.

     To avoid trouble CACHE_CLEANUP is *strongly* recommended after adding
     new alias definitions (that means, alias names which were unknown
     before), unless the special control tag `\ACCEPT_ALL' is declared
     (see tags for details). Otherwise, unchanged paragraphs containing
     the backslashed string which is an alias now would be restored *from
     cache* so that the new alias would take no effect.

          // Text before: \NEW has no meaning and is evaluated
          // as a simple word "NEW" - the backslash is removed silently.
          // This paragraph will be cached because it does not contain an
          // alias/macro.
          There could be \NEW aliases someday.

          // Now consider this is the next turn and \NEW was declared
          // an alias now. But the paragraph using new remained unchanged,
          // so I<it is restored from cache>.

     This seems to be a rather seldom case but users should be informed
     about this behaviour if you provide the cache feature to them.

     To deactivate caching explicitly pass CACHE_OFF.  *An existing cache
     will not be destroyed.*

     Settings can be combined by *addition*.

          # clean up the cache, then refill it
          cache => CACHE_CLEANUP+CACHE_ON,

          # clean up the cache and deactivate it
          cache => CACHE_CLEANUP+CACHE_OFF,

     The CACHE_OFF value is overwritten by any other setting.

     It is suggested to make this setting available to translator users to
     let them decide when a cache should be used.

     *Please note* that there is a problem with line numbers if paragraphs
     are restored from cache because of the behaviour of perls paragraph
     mode. In this mode, the <> operator reads in any number of newlines
     between paragraphs but supplies only one of them. That is why I do
     not get the real number of lines in a paragraph and therefore cannot
     store them. To work around this, two strategies can be used. First,
     do not use more than exactly one newline between paragraphs. (This
     strategy is not for real life users, of course, but in this case
     restored numbers would be correct.) Second, remember that source line
     numbers are only interesting in error messages. If the parser detects
     an error, it therefore says: error "there or later" when a cache hit
     already occured. If the real number is wished the parser could be
     reinvoked then with deactivated cache and will report it.

     *Second note:* cache files are not locked while using them. If you
     need this feature please let me know.

display
     This parameter is optional. It controls the display of runtime
     messages like informations or warnings. By default, all messages are
     displayed. You can suppress these informations partially or
     completely by passing one or more of the "DISPLAY_..." variables
     declared in PerlPoint::Constants.  Constants should be combined by
     addition.

files
     a reference to an array of files to be scanned.

filter
     a regular expression describing the target language. This setting, if
     used, prevents all embedded or included source code of other
     languages than the set one from inclusion into the generated stream.
     This accelerates both parsing and backend handling. The pattern is
     evaluated case insensitively.

          Example: pass "html|perl" to allow HTML and Perl.

     To illustrate this, imagine a translator to PostScript. If it reads a
     Perl Point file which includes native HTML, this translator cannot
     handle such code.  The backend would have to skip the HTML
     statements. With a "PostScript" filter, the HTML code will not appear
     in the stream.

     This enables PerlPoint texts prepared for various target languages.
     If an author really needs plain target language code to be embedded
     into PerlPoint, he could provide versions for various languages.
     Translators using a filter will then receive exactly the code of
     their target language, if provided.

     Please note that you cannot filter out PerlPoint code or files.

     By default, no filter is set.

linehints
     If set to a true value, the parser will embed line hints into the
     stream whenever a new source line begins.

     A line hint has the form

          [DIRECTIVE_NEW_LINE, DIRECTIVE_START, {file=>filename, line=>number}]

     and is suggested to be handled by a backend callback.

     Please note that currently source line numbers are not guaranteed to
     be correct if stream parts are restored from cache (see there for
     details).

     The default value is 0.

object
     the parser object made by new();

safe
     an object of the Safe class which comes with perl. It is used to
     evaluate embedded Perl code in a safe environment. By letting the
     caller of run() provide this object, a translator author can make the
     level of safety fully configurable by users. Usually, the following
     should work

          use Safe;
          ...
          $parser->run(safe=>new Safe, ...);

     Active Perl contents is *suppressed* if this setting is omitted or if
     anything else than a Safe object is passed. (There are currently
     three types of active contents: embedded or included Perl and
     condition paragraphs.)

stream
     A reference to an array where the generated output stream should be
     stored in.

     Application programmers may want to tie this array if the target ASCII
     texts are expected to be large (long ASCII texts can result in large
     stream data which may occupy a lot of memory). Because of the fact
     that the parser stores stream data *by paragraph*, memory consumption
     can be reduced significantly by tying the stream array.

     It is recommended to pass an empty array. Stored data will not be
     overwritten, the parser *appends* its data instead (by push()).

tags
     A reference to a hash which keys are the tags that should be
     recognized.  For example, pass "I", "B" and "C" to implement the well
     known POD tags.

     Take care to pass capitalized tag keys only. Non capitalized keys
     cannot be recognized by convention.

     If a tag is discovered, the parser will produce an open and a close
     directive in the output stream containing the tags name as stored in
     the hash. Look at this example:

          # you pass
          tags => {I=>1, B=>1, C=>1},

          # the tags are recognized in a text like
          "... \I<bla \B<blu> \C<> blo>..."

          # for which the parser will produce something like
          ... [DIRECTIVE_TAG, DIRECTIVE_START, 'I']
          + "bla" + " "
          + [DIRECTIVE_TAG, DIRECTIVE_START, 'B']
          + "blu"
          + [DIRECTIVE_TAG, DIRECTIVE_COMPLETE, 'B']
          + " "
          + [DIRECTIVE_TAG, DIRECTIVE_START, 'C']
          + [DIRECTIVE_TAG, DIRECTIVE_COMPLETE, 'C']
          + " " + "blo"
          + [DIRECTIVE_TAG, DIRECTIVE_COMPLETE, 'I']

     It is suggested to handle tags by backend callbacks.

     The parser takes no attention to the hash values.

     Note that any tag that is not declared in this hash *cannot* be
     discovered by the parser and will not be passed to the stream - they
     are recognized as simple strings (*without* the leading backslash).

     As a new experimental feature, this default behaviour can be
     modified. If a tag name "\ACCEPT_ALL" is passed, *anything that looks
     like a tag will be recognized as a tag*. (Take care to guard all
     backslashes which shall not start a tag or macro!) This feature is
     built in to simplify processing by different backends which may
     implement different tag sets.

trace
     This parameter is optional. It is intended to activate trace code
     while the method runs. You may pass any of the "TRACE_..." constants
     declared in PerlPoint::Constants, combined by addition as in the
     following example:

          # show the traces of both
          # lexical and syntactical analysis
          trace => TRACE_LEXER+TRACE_PARSER,

     If you omit this parameter or pass TRACE_NOTHING, no traces will be
     displayed.

var2stream
     If set to a true value, the parser will propagate variable settings
     into the stream by adding additional DIRECTIVE_VARSET directives.

     A variable propagation has the form

          [DIRECTIVE_VARSET, DIRECTIVE_START, {var=>varname, value=>value}]

     and is suggested to be handled by a backend callback.

     The default value is 0.

vispro
     activates "process visualization" which simply means that a user will
     see progress messages while the parser reads the documents. The
     numerical value of this setting determines how often the progress
     message shall be updated by a *paragraph interval*:

          # inform every five paragraphs
          vispro => 5,

     Process visualization is automatically suppressed unless STDERR is
     connected to a terminal, if this option is omitted, display was set
     to DISPLAY_NOINFO or parser traces are activated.

   *Return value:* A "true" value in case of success, "false" otherwise. A
call is performed successfully if there was neither a syntactical nor a
semantic error in the parsed files.

   Example:

     $parser->run(
                  stream  => \@streamData,
                  tags    => \%tagHash,
                  files   => \@ARGV,
                  filter  => 'HTML',
                  cache   => CACHE_ON,
                  trace   => TRACE_PARAGRAPHS,
                 );

EXAMPLE
=======

   The following code shows a minimal but complete parser.

     # pragmata
     use strict;

     # load modules
     use PerlPoint::Parser;

     # declare variables
     my (@streamData, %tagHash);

     # declare list of tag openers
     @tagHash{qw(B C I IMG E)}=();

     # build parser
     my ($parser)=new PerlPoint::Parser;
     # and call it
     $parser->run(
                  stream  => \@streamData,
                  tags    => \%tagHash,
                  files   => \@ARGV,
                 );

NOTES
=====

Format
------

   The PerlPoint format was initially designed by *Tom Christiansen*, who
wrote an HTML slide generator for it, too.

   *Lorenz Domke* added a number of additional useful and interesting
features to the original implementation. At a certain point, we decided to
redesign the tool to make it a base for slide generation not only into
HTML but into various document description languages.

   The PerlPoint format implemented by this parser version is slightly
different from the original design. Presentations written for Perl Point
1.0 will not pass the parser but can simply be converted into the new
format. We designed the new format as a team of *Lorenz Domke*, *Stephen
Riehm* and me.

Storable updates
----------------

   From version 0.24 on the Storable module is a prerequisite of the
parser package because Storable is used to store and retrieve cache data
in files. If you update your Storable installation it *might* happen that
its internal format changes and therefore stored cache data becomes
unreadable. Simply remove the cache files (see FILES) and rerun the parser
to rebuild the cache, or call the parsers run() method with cache set to
`CACHE_CLEAN' for the same effect.

FILES
=====

   If caches are used, the parser writes cache files where the initial
sources are stored. They are named .<source file>.ppcache.

SEE ALSO
========

PerlPoint::Constants
     Constants used by parser functions and in the STREAM FORMAT.

PerlPoint::Backend
     A frame class to write backends basing on the *STREAM OUTPUT*.

pp2html
     The inital PerlPoint tool designed and provided by Tom Christiansen.
     A new translator by *Lorenz Domke* using *PerlPoint::Package*.

AUTHOR
======

   Copyright (c) Jochen Stenzel (perl@jochen-stenzel.de), 1999-2001. All
rights reserved.

   This module is free software, you can redistribute it and/or modify it
under the terms of the Artistic License distributed with Perl version
5.003 or (at your option) any later version. Please refer to the Artistic
License that came with your Perl distribution for more details.

   The Artistic License should have been included in your distribution of
Perl. It resides in the file named "Artistic" at the top-level of the Perl
source tree (where Perl was downloaded/unpacked - ask your system
administrator if you dont know where this is).  Alternatively, the current
version of the Artistic License distributed with Perl can be viewed
on-line on the World-Wide Web (WWW) from the following URL:
http://www.perl.com/perl/misc/Artistic.html.

   PerlPoint::Parser is built using *Parse::Yapp* a way that users have
not to explicitly install *Parse::Yapp* themselves. According to the
copyright note of *Parse::Yapp* I have to mention the following:

   "The Parse::Yapp module and its related modules and shell scripts are
copyright (c) 1998-1999 Francois Desarmenien, France. All rights reserved.

   You may use and distribute them under the terms of either the GNU
General Public License or the Artistic License, as specified in the Perl
README file."

DISCLAIMER
==========

   This software is distributed in the hope that it will be useful, but is
provided "AS IS" WITHOUT WARRANTY OF ANY KIND, either expressed or
implied, INCLUDING, without limitation, the implied warranties of
MERCHANTABILITY and FITNESS FOR A PARTICULAR PURPOSE.

   The ENTIRE RISK as to the quality and performance of the software IS
WITH YOU (the holder of the software).  Should the software prove
defective, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
CORRECTION.

   IN NO EVENT WILL ANY COPYRIGHT HOLDER OR ANY OTHER PARTY WHO MAY CREATE,
MODIFY, OR DISTRIBUTE THE SOFTWARE BE LIABLE OR RESPONSIBLE TO YOU OR TO
ANY OTHER ENTITY FOR ANY KIND OF DAMAGES (no matter how awful - not even
if they arise from known or unknown flaws in the software).

   Please refer to the Artistic License that came with your Perl
distribution for more details.

PerlBug DataBase
****************

NAME
====

   Perlbug - PerlBug DataBase

DESCRIPTION
===========

   Bug tracking system, written in perl, running on UNIX, using Mysql.

   For installation instructions see the INSTALL file.

SYNOPSIS
========

   New bugs are created by mailing perlbug@perl.org or perlbug@perl.com

   Said bug is entered in the database, and given a new bugid, the mail is
then forwarded to perl5-porters with the bugid in the subject line..

   perl5-porters is continously tracked for relevant mails to attach to
said bug.

   There are web(http://bugs.perl.org), email(bugdb@perl.org and
help@bugs.perl.org) and command line(bugdb) frontends to query and
administrate the bugs.

   Regular overviews are emailed to p5p, and outstanding bugs are mailed
to active admins for their attention.

TODO
====

   Oracle support

   perlTK interface

   Comprehensive test suite (though 100+ isn't that bad for a start?)

CLASSES
=======

   For those that are interested the Perlbug module hierarchy goes
something like this:

     (ISA) Config  Do  TM    (HASA) Log Format
           |       |   |
           -------------            --- ------
                    |
              (ISA) Base
                    --------------------
                    |  |      |        |
                  Web  Cmd    Tk       Email
                  ---  ---    --       -----------------------------
                  |    |      |        |        |        |         |
        perlbug.cgi    bugdb  bugtk    tron.pl  mail.pl  cron.cmd  hist.cmd ...

SCRIPTS
=======

   The perlbugtron relies on the following (6 active) scripts:

   perlbug.cgi is the web interface.

   bugdb is a command line interface.

   bugtk is the on the todo list as a Tk interface.

   tron.pl tracks mailing lists, relying on header information to identify
new bugs and replies to existing ones.  Accepts mail for perlbug@perl.org
and perlbug@perl.com and relevant target mailing lists.

   mail.pl is a query and administrative email front end, examining both
Subject: and To: line for instructions.  Accepts mail for bugdb@perl.org
and *@bugs.perl.org.

   cron.com is the regular cron job interface to backups, weekly
notifications etc.

   hist.cmd is a parser of directories of archived mail (treated as per
tron.pl).

COMMANDS
========

   A couple of useful commands, assuming you're in ~perlbug/scripts:

   Send mail into the db:

     cat some_mail | ./tron.pl

   Slurp up archived mails:

     ./hist.cmd -d /path/to/email/archives

   Query the db via the email interface:

     cat my_admin_cmds | ./mail.pl

     Or via the command line:

     ./bugdb

     Send active admins unclosed bugs and an overview to master_list(p5p),
     dump current database for reference/backup:

     crontab -e 3 5 * * 1 ./cron.cmd

BUGS
====

   What bugs ?-)

   You have a couple of choices, (with the output of 'make test
TEST_VERBOSE=1'):

     1. Mail perlbug@perl.org which will assign a bugid.

     2. Mail the author (richard@perl.org) directly.

     3. Mail admins@bugs.perl.org which will Cc: to all active admins.

     4. Subscribe to bugmongers@perl.org (a mailing list for those interested in perl bugs).

     4. Or try perl5-porters@perl.org (p5p) for a more generic solution.

AUTHOR
======

   Richard Foley richard@perl.org perlbug@rfi.net (c) 1999 2000

CONTRIBUTORS
============

   The system was given a kick start by Christopher Masto, NetMonger
Communications <chris@netmonger.net>.

   It's development has been overseen originally by Chip Salzenburg
<chip@perlsupport.com> and later by Nathan Torkington <gnat@frii.com>.

   There have been numerous suggestions, feedback and patches from various
people, in particular (in alphabetical order):

   Mike Guy <mjtg@cam.ac.uk>

   Richard Soderberg <rs@oregonnet.com>

   Robert Spier <rspier@pobox.com>

   Hugo van der Sanden <hv@crypt0.demon.co.uk>

   Special thanks to Tom Phoenix <rootbeer@redcat.com>.

COPYRIGHT
=========

   Copyright (c) 1999 2000 Richard Foley richard@rfi.net. All rights
reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Module for bringing together Config, Log, Format, Do, TM, Mysql etc.
********************************************************************

NAME
====

   Perlbug::Base - Module for bringing together Config, Log, Format, Do,
TM, Mysql etc.

DESCRIPTION
===========

   Methods for perlbug database access, all_flags, check_user, get_list,
get_data, clean_up, etc.

SYNOPSIS
========

     my $o_base = Perlbug::Base->new;

     my %user = $o_base->user_data('richard');

     print "User is: ".$user{'username'};

METHODS
=======

new
     Create new Perlbug object, (see also `Description' in this node
     above):

          my $pb = Perlbug->new();

url
     Store and return the given url.

do
     Wrap a Perlbug::Do command

          my $i_ok = $pb->do('b', 'bugid');

debug
     Wrap o_log->debug calls

dodgy_addresses
     Returns quoted, OR-d dodgy addresses prepared for a pattern match
     ...|...|...

          my $regex = $o_obj->dodgy_addresses('from'); # $rex = 'perlbug\@perl\.com|perl5\-porters\@perl\.org|...'

link
     Wrap o_log->link calls

AUTOLOAD
     Wrapper for debug functions, translates this:

     	$o_obj->debug3($data); # to

          $o_obj->{'o_log'}->debug(3, $data); # this

dump
     Wrap Data::Dumper catering for www also.

can_update
     Check if current user is allowed to update given item/s.

          print 'yes' if $o_perlbug->can_update([$user||$bid||$mid||$bid|$pid]);

fatal
     Wrap o_log->fatal calls

start
finish
format
     Wrap o_format->format calls

format_overview
     Wrap o_format->overview calls

format_schema
     Wrap o_format->schema calls

copy
     Wrap Log::copy

flags
     Returns array of options for given type.

          my @list = $pb->flags('category');

all_flags
     Return all flags available in db keyed by type.

          my %flags = $pb->all_flags;

          %flags = ( # now looks like this:
          	'category'	=> ['core', 'docs', 'install'], 	# ...
          	'status'	=> ['open', 'onhold', 'onhold'], 	# ...
          	# ...
          );

date_hash
active_admins
     Returns active admins from db.

          my @active = $pb->active_admins;

active_admin_addresses
     Returns active admin addresses from db.

          my @addrs = $pb->active_admin_addresses;

user_data
     Return (cached) data on given user

          my %data = $pb->user_data('richard');

help
     Returns help message for perlbug database.

          my $help = $pb->help;

spec
     Returns spec message for perlbug database.

          my $spec = $pb->spec();

flow
     Details how the mail / web mechanism flows

administration_failure
     Deal with a failed administration attempt

          my $i_ok = $self->administration_failure($bid, $user, $commands);

check_user
     Checks given user is registered in the database as an admin.

     Sets userid in `admin' in this node and thereby `status' in this node
     for later reference.

          $pb->check_user($user_name);

isadmin
     Stores and returns current admin userid (post check_user), checks
     whether system is restricted or not.

          next unless $pb->isadmin;

status
     Returns 'A' or 'U' depending on whether user is an admin or a 'mere'
     user.

          my $thing = ($self->status eq 'A') ? 'key' : 'lock';

ok
     Checks bugid is in valid format (looks like a bugid) (uses get_id):

          &do_this($id) if $pb->ok($id);

get_id
     Determine if the string contains a valid bug ID

_switches
     Stores and returns ref to list of switches given by calling script.
     Only these will be parsed within the command hash in
     `process_commands' in this node.

          my $switches = $pb->_switches(qw(e t T s S h l)); #sample

result
     Storage area (file) for results from queries, returns the FH.

          my $res = $pb->result('store this stuff'); #store

fh
     Wrapper for Log fh

set_site
     Set the site directory for text files, headers, todos etc.

read
append
     Wrapper for Log append

get_results
     Return the results of the queries from this session.

          my $a_data = $pb->get_results;

get_list
     Returns a simple list of items (column values?), from a sql query.

          my @list = $pb->get_data('SELECT bugid FROM tm_bug');

get_data
     Returns a list of hash references, from a sql query.

          my @hash_refs = $pb->get_data('SELECT * FROM tm_bug');

exec
     Returns statement handle from sql query.

          my $sth = $pb->exec("INSERT @data INTO table");

exists
     Does this bugid exist in the db?

tm_parent_child
     Assign to given bugid, given list of parent and child bugids

current_status
     Get's current status of bug for reference.

tm_bug_patch
     Assign to given bugid, given list of patchids, return valid, @pids

tm_bug_note
     Assign to given bugid, given list of note ids, return valid, @nids

tm_bug_test
     Assign to given bugid, given list of testids, return valid, @tids

notify_cc
     Notify tm_cc addresses of changes, current status of bug.

track
     Track some function or modification to the db.

          $i_tracked = $self->track($type, $id, $entry);

ck822
     Email address checker (RFC822) courtesy Tom Christiansen/Jeffrey
     Friedl.

          print (($o_email->ck822($addr)) ? "yup($addr)\n" : "nope($addr)\n");

htpasswd
     Modify, add, delete, comment out entries in .htpasswd

          $i_ok = $o_web->htpasswd($userid, $pass);   # entry ok?

          @entries = $o_web->htpasswd;                # returns list of entries ('userid:passwd', 'user2:pass2'...)

clean_up
     Clean up previous (logs and results) activity whenever run.

     Exits when done.

insert_bug
     Insert a bug into the database

          my ($i_ok, $bid, $mid) = $o_obj->insert_bug(@args);

parse_flags
     Return the 'AND ...' or 'SET ...' condition for a tm_bug query given
     the flags from the status, category and severity columns WITHOUT the
     leading 'AND' or a leading ', ' separator.

          my $stuff = $pb->parse_flags([('o', 'build')], 'AND');
          # $stuff is now "status = 'open' AND category = 'build'"
          my $sql = "SELECT * FROM some_table WHERE $stuff";
          # or
          my $stuff = $pb->parse_flags([('o', 'build')], 'SET');
          # $stuff is now "status = 'open', category = 'build'"
          my $sql = "UPDATE tm_bug SET $stuff WHERE bugid = 'xyz'";

          =cut

     sub parse_flags {     my $self = shift;     my ($str, $type) = @_;
     $str = (ref($str) eq 'ARRAY') ? join(' ', @{$str}) : $str;     my
     $this = ($type eq 'AND') ? 'AND ' : ',   '; # AND|SET
     $self->debug(2, "Parsing str ($str), type ($type) ... this ($this)");
        my @tm_flags = $self->get_list('SELECT DISTINCT type FROM
     tm_flags'); 	my $sql = undef;     my %seen = (); 	FLAG: 	foreach
     my $f (@tm_flags) { 		$self->debug(3, "Parsing flag ($f)");
        my @opts = $self->get_list("SELECT DISTINCT LOWER(flag) FROM
     tm_flags WHERE type = '$f'");         OPT: 		foreach my $opt (@opts) {
               $self->debug(4, "Comparing str ($str) and opt ($opt)");
             STR: 			foreach my $bit (split ' ', lc($str)) {
     next unless $bit =~ /\w/; 				if ($opt =~ /\b$bit/i) {
             my $line = " $this $f = '$opt' "; 					$seen{$opt}++;
            $self->debug(4, "Flag ($f) matched, line ($line) made.");
                    $sql .= $line;                     next FLAG;
            } else {                     $self->debug(4, "Flag ($f) not
     matched: opt($opt) bit($bit)");                 }             }
      }         $self->debug(3, "Flag ($f) set sql ($sql)");     } 	$sql
     =~ s/^(.+)?$type\s*$/$1/; 	$sql =~ s/^[\,\s]+(\w.+)$/ $1/; 	if
     (!(scalar(keys %seen) >= 1)) { 		$sql .= " AND bugid = 'non-plaus_ible
     bug id!' AND bugid = 'no flag found protector :-)' ";
     $self->debug(0, "Setting duff flag to protect against all bugs being
     returned: '$sql': ".Dumper(\%seen)); 	}     # $sql =
     (length($sql) > 4) ? substr($sql, 4) : $sql; #   start
     $self->debug(2, "Parse ($str, $type) result: sql($sql)");     return
     $sql; }

parse_str
          my %cmds = $o_obj->parse_str('patch_<bugid>_etc' | (qw(patchid bugid etc));

Command line interface to perlbug database.
*******************************************

NAME
====

   Perlbug::Cmd - Command line interface to perlbug database.

DESCRIPTION
===========

   Command line interface to perlbug database.

SYNOPSIS
========

     use Perlbug::Cmd;

     my $o_perlbug = Perlbug::Cmd->new;

     my $result = $o_perlbug->cmd;

     print $result; # == 1 (hopefully :-)

METHODS
=======

new
     Create new Perlbug::Cmd object:

          my $pb = Perlbug::Cmd->new();

cmd
     Call the command line interface:

     	$o_perlbug->cmd;

process
     Processes the command given, gets and truncates the results, calls
     scroll

scroll
     Scroll the available data if necessary.

history
     History mechanism accessor

doh
     Wraps help message

doH
     History of commands

parse_commands
     Parses the subject and body of the email message into a command hash,
     hash is placed in $pb->result, returns ref to said hash:

          my $h_ref = $pb->parse_commands($sbj, $bdy);

process_commands
     Steps through hash created by `parse_commands' in this node, and
     executes each outstanding command, so long as the command has been
     allowed via `switches' in this node.  Returns valid == 1 or error
     message.

          my $outcome = $pb->process_commands($ref_to_hashed_commands);

AUTHOR
======

   Richard Foley perlbug@rfi.net 2000

Perlbug Configuration data handler
**********************************

NAME
====

   Perlbug::Config - Perlbug Configuration data handler

DESCRIPTION
===========

   Configuration data for the Perlbug bug tracking system.

   Be sure to set the 'Perlbug_SiteConfig' environment variable to the
correct site configuration file, and/or fix the line above.

   Set methods are provided only for `current()' in this node parameters,
the rest are all gettable only, and settable from the configuration file.

SYNOPSIS
========

     my $o_conf = Perlbug::Config->new;

     my $debug = $o_conf->current('debug');				# 0 or as set in Configuration file

     my $new_debug = $o_conf->current('debug', 2);		# 2 !

     my @current_data = $o_conf->get_keys('current'); 	# have a look

METHODS
=======

new
     Create new Config object with all prefs set.

          my $conf = Perlbug::Config->new;

get_config_data
     Retrieve data from site configuration file

          my ($ok, $h_data) = get_config_data($config_file_location);

update_data
     Update config data structure for current/local environment

          my ($ok, $h_data) = &update_data(\%data);

check_data
     Check config data structure

          my ($ok, $h_data) = check_data(\%data);

get_date
     Returns common date for use throughout Perlbug.

          my $date = get_date;     # -> 19980815

get_keys
     Return list of keys of given key, ignoring comment fields.

get_vals
     Return list of values of given key, ignoring comment fields.

dump
     Returns prefs, via Data::Dumper for debugging, all if no argument
     given.

     Be sure to call it in a list context:

          print $Conf->dump('system');

current
     Current modifiable environment.

     Get     my $debuglevel = $o_obj->current('debug');

     Set     my $incremented = $o_obj->current('debug',
     $self->current('debug') + 1);

methods
     Access methods to data, non are directly modifiable, see the
     Configuration file.

          my $target_address = $o_obj->target('generic');

AUTHOR
======

   Richard Foley perlbug@rfi.net 21.Oct.1999

Commands (switches) for generic interface to perlbug database.
**************************************************************

NAME
====

   Perlbug::Do - Commands (switches) for generic interface to perlbug
database.

DESCRIPTION
===========

   Methods for various functions against the perlbug database.

SYNOPSIS
========

   Use like this:

     $o_obj->dod(2); # set debug level to '2'

     =head1 METHODS

new
     Create new Perlbug::Do object:

          my $do = Perlbug::Do->new();

get_switches
     Returns array of current switches, rather than string

          my @switches = $o_mail->get_switches('user');

doh
     Returns help message built from a hash_ref, commands may be
     overwritten by sending in a hash.

     Syntax for the hash is 'key => description (sample args)':

          $o_obj->doh({
          	'e' => 'email me a copy too (email@address.com)', 	# add
          	'H' => 'Help - more detailed info ()',				# replace
          	'z' => '', 											# unrequired
          });

dod
     Switches debugging on (1).

doD
     Dumps database for backup and recovery.

dom
     Return the given message(id), places the `format', see Perlbug,
     ed result in to the results array.

          my $res = $do->dom([@messageids]);

doM
     Create new message

          my $i_ok = $do->doM($bugid, 'message', 'etc');

     #       rjsf -> ($xstr, $content, $hdr, $to, $from, $subject) #
     reverse order

dop
     Return the given patch(id), places the `format', see Perlbug,
     ed result in to the results array.

          my $res = $do->dop([@patchids]);

doP
     Assign to given bugid, given patch, return i_ok

          $i_ok = $o_obj->doP('tid_chid_versid', 'patch...here', 'hdr', 'sbj', 'frm', 'to);

dot
     Return the given test(id), places the `format', see Perlbug,
     ed result in to the results array.

          my $res = $do->dot([@testids]);

doT
     Assign to given bugid, given test, return i_ok

          $i_ok = $o_obj->doT('tid_chid_versid', 'test...here', 'hdr', 'sbj', 'frm', 'to);

dob
     Return the given bug(id), places the `format', see Perlbug,
     ed result in to the result array.

          my $i_bugs = $do->dob([@bugids]);

          # $i_bugs = num of bugs succesfully processed

doB
     Return the given bug(id), with all the messages assigned to it, calls
     dob()

          my $i_bugs = $do->doB([@bugids]);

          # $i_bugs = num of bugs succesfully processed

dou
     Get the given user, checks if active

     print $o_do->dou($userid);

doc
     Retrieve bug based on the existing category, severity or status flags.

          my $res = $do->doc('open build');

doC
     Retrieve messages, as per doB() where category, severity or status
     fulfills the following optional flags: o (open), c (closed), b
     (build), p (patch), u (utilities) ...

     Wrapper for l<doc>.

dos
     Retrieve data based on the subject line of a bug

          my $res = $do->dos('open build');

dor
     Retrieve data based on contents of the Body of a message

          my $res = $do->dor('open build');

don
     Get the note for this noteid

doN
     Assign to given bugid, given notes, return $i_nid or 0

     Accepts ($bugid, $note, $header) or ([($bugid, $note, $header)])

doq
     Gets the sql _q_ query statement given in the body of the message,
     executes it, and returns the result in the result array.

doQ
     Returns the database schema, for use with SQL statements.

doL
     Returns the current (or given later) logfile.

     =cut

     sub doL { # Log (all) 	my $self = shift; 	$self->debug('IN',
     @_); 	my ($input) = @_;     my ($given) = (ref($input) eq
     'ARRAY') ? @{$input} : $input;     ($given == 1) && ($given =
     'today');     $self->start("L $given"); 	my $fh =
     $self->fh('log'); # , pb_log_\d{8} 	my $LOG = "; 	if
     (defined $fh) { 	    $fh->seek(0,0); 	    while (<$fh>) {
      $LOG .= $_; 	    } 	    $fh->seek(0, 2); 	    my $length =
     length($LOG); 	    $self->debug(2, "log ($fh) length ($length) read");
     } else {         $self->debug(0, "Can't read LOG from undefined fh
     ($fh)");     } 	$self->result($LOG, 3); 	$self->finish; 	my
     $i_ok = (length($LOG) >= 1) ? 1 : 0; 	$self->debug('OUT',
     $i_ok); 	return $i_ok; }

dol
     Just the stored log results from this process.

dof
     Sets the appropriate format for use by `Format' in this node methods,
     overrides default 'a' set earlier.

          $o_obj->dof('h');

stats
     Get stats from db for overview usage.

          my $h_data = $self->stats;

doo
     Returns a summary overview of the bugs, bugs, messages etc. in the
     database.

          $i_ok = $o_do->doo(); # data in result via formatting...

doO
     Returns a similar overview of the bugs, in GUI format using GIFgraph
     and/or AA-lib?

          Still to do

doa
     ONLY do this if registered as admin of bug.  in which case dok could
     still dok(\@bids) these bugids...  or should it automatically add id
     as admin?

admin_of_bug
     Checks given bugid and administrator against tm_bug_user.

     Returns 1 if administrator listed against bug, 0 otherwise.

doA
dok
     Klaim the bug(id) given

doK
     UnKlaim the bug(id) given

dox
     Delete bug from tm_bug table.

     Use doX for messages associated with bugs.

doX
     Delete given bugid messages from tm_message.

doi
     Initiate new admin entry, including htpasswd entry, (currently rf
     only)

          userid=test_user:
          password=p*ss33*t:
          address=perlbugtest@rfi.net:
          match_address=.*\@rfi\.net:
          name=Richard Foley:

     or

          userid=test_user:password=p*ss33*t:address=perlbugtest@rfi.net:match_address=.*\@rfi\.net:name=Richard Foley

doI
     Disable a user entry

_doz
     Update: only to be used by perlbug@rfi.net (disabled)

          $ok = $o_obj->_doz($filename, $data);

doy
     Password renewal

          $i_ok = $o_obj->doy($user, $pass);

AUTHOR
======

   Richard Foley perlbug@rfi.net Oct 1999

Email interface to perlbug database.
************************************

NAME
====

   Perlbug::Email - Email interface to perlbug database.

DESCRIPTION
===========

   Email interface to perlbug database.

SYNOPSIS
========

     use Perlbug::Email;

     use Mail::Internet;

     my $o_mail = Mail::Internet->new(*STDIN);

     my $o_perlbug = Perlbug::Email->new($o_mail);

     my $call = $o_perlbug->switch;

     my $result = $o_perlbug->$call($o_mail);

     print $result; # =1 (hopefully :-)

METHODS
=======

new
     Create new Perlbug::Email object:

          my $pb = Perlbug::Email->new($o_mail); # Mail::Internet

_original_mail
     Maintain original

original
     Returns original field/s from header

mailing
     Switch mailing on/off, also sets email->mailer to 'test' if off

splice
     Returns the original mail spliced up into useful bits, set from
     `parse_mail' in this node or `switch' in this node, or given as arg.

          my ($o_hdr, $header, $body) = $self->splice; # or splice($o_mail);

parse_mail
     Given a mail (Mail::Internet) object, parses it into command hash,
     also checks the header for X-Perlbug loop and the address of the
     sender via `check_user' in this node.

          my $h_commands = $pb->parse_mail($mail);

from
     Sort out the wheat from the chaff, use the first valid ck822 address:

          my $from = $self->from($replyto, $from, @alternatives);

check_header
     Checks (incoming) email header against our X-Perlbug flags, also
     slurps up the Message-Id for future reference.

          my $i_ok = $o_perlbug->check_header($o_hdr); # or undef

check_user
     Checks the address given (From usually) against the tm_user table,
     sets user or admin access priviliges via the switches mechanism
     accordingly.

     Returns admin name

          my $admin = $pb->check_user($mail->('From')); # -> user_id || blank

return_info
     Takes data ($a_stuff), which may be a ref to the result array, and
     mails it to the From or Reply-To address, Cc:-ing it to any address
     given by the -e flag.

          my $i_ok = $pb->return_info($o_mail, $a_stuff);

_mail
     Get and set the incoming mail object (Mail::Internet)

     Returned (used) via `splice()' in this node

doh
     Wraps help message

doH
     Returns more detailed help.

get_header
     Get new perlbug Mail::Header, filled with appropriate values, based
     on given header.

          my $o_hdr = $o_email->get_header();						   # completely clean

          my $o_hdr = $o_email->get_header($o_old_header);           # plain (coerced as from us)

          my $o_hdr = $o_email->get_header($o_old_header, 'remap');  # maintain headers (nearly transparent)

default
     Operates on given tag, from bugdb@perl.org: we're sending this out
     from here.

     Affects Message-Id(new), From(bugdb), Reply-To(maintainer) lines

     Keeps Subject|To|Cc for later modification?

     Filters anything else

          my @lines = $self->default($tag, @lines);

remap
     Operating on a given tag, remaps (To|Cc) -> forwarding address,
     removes duplicates.

     Attempt to remain moderately invisible by maintaining all other
     original headers.

          my @lines = $self->remap($tag, @lines);

send_mail
     Send a mail with protection.

          my $ok = $email->send_mail($o_hdr, $body);

tester
     If test mail, turn header to maintainer and return header data for
     insertion

defense
     Set mail defaults for _all_ mail emanating from here, calls
     `clean_header()' in this node, `trim_to()' in this node.

          my $o_hdr = $self->defense($o_hdr);

clean_header
     Clean header of non-compliant 822 address lines using
     Mail::Address::parse()

          my $o_hdr = $o_mail->clean_header($o_hdr);

trim_to
     Takes the header and returns it without any dodgy to, or cc addresses
     (or undef):

          my $o_hdr = $o_obj->trim_to($o_hdr);

get_forward
     Operating on a single (or blank) address, returns a list of
     forwarding addresses.

          my $to = $perlbug->get_forward('perlbug@perl.org'); # perl5-porters@perl.org

          my $to = $perlbug->get_forward('perl-win32-porters@perl.org'); # perl-win32-porters@perl.org

              my $to = $perlbug->get_forward();                   # perl5-porters@perl.org

              my @to = $perlbug->get_forward();                   # perl5-porters@perl.org perl-win32-porters@perl.org etc...

switch
     Returns appropriate method name to call to handle this mail.

     This enables you to bypass the suggested method with your own call
     (be it on your own head :-):

          my $call = $pb->switch(Mail::Internet->new(\$STDIN);

do_new
     Deal with a new bug

do_note
     Wrapper for a new note

do_patch
     Wrapper for a new patch

do_test
     Wrapper for a new test

scan
     Scan for perl relevant data putting found or default switches in
     $h_data.  Looking for both category=docs and
     '\brunning\s*under\ssome\s*perl' style markers.

          my $h_data = $o_mail->scan($body);

          my $res = $o_mail->bug_set($tid, $h_data);

do_reply
     Deal with a reply to an existing bug - no acknowledgement, no forward
     (quiet)

header2admin
     Given a Mail::Header object attempts to return a valid create admin
     command

          my $data = $o_email->header2admin($o_hdr);

doe
     Email address to 'Cc:' to

          -e me.too@some.where.org

doy
     New password

dov
     Volunteer proposed bug modifications

          propose_close_<bugid>@bugs.perl.org

          my $i_ok = $o_obj->dov('tid close patch');

doV
     Volunteer a new administrator

          register_MYUSERID@bugs.perl.org

doa
     admin a bug

          close_<bugid>_patch_macos@bugs.perl.org

doP
     Recieve a patch

          patch_<version>*_<changeid>*_<bugid>*@bugs.perl.org

doT
     Recieve a test

          test_<bugid>@bugs.perl.org

doN
     Recieve a note

          note_<bugid>*@bugs.perl.org

dow
     Forward (weiterleiten) mail onto all active administrators

          admin(s)@bugs.perl.org

          my $i_ok = $o_obj->dow($body);

do_quiet
     Drop out quietly, no entry in database, silent dump into black hole.

do_bounce
     Deal with a bounced mail

assign_bugs
     Assign to this admin, so many, of these unclaimed bugs.

     N.B. the claimed bugs are shifted off the end of the referenced array!

          $ok = $pb->assign_bugs($admin, 5, \@unclaimed);

check_mail
     Check headers against various given parameters, attempts to read all
     required lines/data.

          # call													# Scope		Regex
          my $o_new = $o_mail->process_header($o_hdr, $context);	# Mail::Send object (ready to go)
          my @should 	 = $o_hdr->get('X-Perlbug-Match');			# Subject: 	\-h\s\-o
          my @shouldnt = $o_hdr->get('X-Perlbug-Match-Non');		# To: 		\s*perlbug\@perl\.com
          my @failures = $o_hdr->get('X-Perlbug-Match-Bad');		# To: 		\s*perlbug\@perl\.org

          ($i_ok, $feedback) = $o_bugmail->check_mail($o_new, $body, \@should, \@shouldnt, \@shouldfail);

          warn "Mail header check failure: ($feedback)\n" unless $i_ok == 1;

doD
     Mail me a copy of the latest database dump

scan_header
     Scan a typical *@bugs.perl.org header

          my ($cmd, $body) = $o_mail->scan_header($o_hdr, $body);

          To: line can be any of:

          close_<bugid>_@bugs.perl.org  = bug admin request

          register@bugs.perl.org        = admin registration request

          admins@bugs.perl.org          = admin mail forward

     Subject: line may look like:

          -h -o

          -H -d2 -l -A close 20000721.002 lib -r patch -e some@one.net

admin_of_bug
     Checks given bugid and administrator against tm_bug_user,
     tm_bugs::sourceaddr, tm_cc.

     Now you can admin a bug if you're on the source address, or the Cc:
     list.

administration_failure
     Deal with a failed administration attempt

          my $i_ok = $self->administration_failure($tid, $user, $commands);

in_master_list
     Checks given address against ok-to-be-administrator email address list

          my $i_ok = $o_obj->in_master_list($address);

AUTHOR
======

   Richard Foley perlbug@rfi.net 1999 2000

Command line interface to fixing perlbug database.
**************************************************

NAME
====

   Perlbug::Fix - Command line interface to fixing perlbug database.

DESCRIPTION
===========

   Command line interface to fixing incorrect perlbug data.

   Note: `mig()' in this node will migrate from pre-2.26 database
structure to current usage.

USAGE
=====

     lowercase is indicator/report

     	UPPERcase expands/effects

     	> h		# help

     	> H		# Helpful help

     	> f		# view erroneous flags

     	> F		# Fix erroneous flags

     	> mig	# check stuff

     	> MIG 	# Fix stuff (migrate...)

     	> 		# etc.

METHODS
=======

new
     Create new Perlbug::Fix object:

          my $o_fix = Perlbug::Fix->new();

process
     Processes the command given, gets and truncates the results, calls
     scroll

flags
     Set flags to " in tm_tickets where flag is unknown in tm_flags

map_flags
     Adjust bug flags, note, this also updates the flags table with
     missing values!

cc
     Correct tm_cc table

bugs
     Correct tm_tickets table

messages
     Correct messages table

notes
     Correct notes table

claimants
     Correct claimants table

patches
     Correct patch relations table

users
     Correct users table

action
     Process action on behalf of caller

          my $i_ok = $self->action('tm_table', 'UPDATE x SET y WHERE z etc...');

mig
     Migrate whole database

x0
     Migrate log

x1
     Migrate notes

x2
     Migrate patches

x3
     Migrate tests

x99
     Remove MIGRATE deadwood if everythings is OK

x31
     Update tm_claimants from tm_logs by userid

x32
     Assumes bugids in db, messages in dir, find messages which were not
     forwarded, forward them.

     Not the same as an historic trawl, which is looking for new/replies,
     etc.

xspecial
     Specials

AUTHOR
======

   Richard Foley perlbug@rfi.net 2000

Formats for email interface to perlbug database.
************************************************

NAME
====

   Perlbug::Format - Formats for email interface to perlbug database.

DESCRIPTION
===========

   Different formats which can be applied to the data returned from the
perlbug database via l<Perlbug> (l<Web>, l<Email> and l<Cmd>) interfaces:
*aAhHl*

   If html is required, `-f h' should be used.  The first letter following
the -f switch is the only one used to define which format to use for all
results emanating from a single email, `-f h' being set by default for a
web call.

   Specific objects supported include: Bugs, Messages, Users, Patches,
Tests and Notes.

   Currently this is not relevant for the -q (sql query) switch, as there
is little value in attempting to second guess what may be called for in
sql statements.

SYNOPSIS
========

     my $o_fmt = Perlbug::Format->new;

     my %data = (
     	'some'	=> 'data',
     	'other'	=> 'stuff',
     );

     my $str = $o_fmt->fmt(\%data);

     print $str; # 'some=data\nother=stuff\n'

FORMATS
=======

     a ascii short - minimal listings default for mail interface

     A ASCII long  - maximal block style listings

     h html short  - minimal listings default for web interface

     H HTML short  - maximal block style listings

     l lean list   - ascii but purely for parsing minimal data

     L lean HTML   - like l, but with html links - yek

METHODS
=======

new
     Create new Perlbug::Format object:

          my $do = Perlbug::Format->new();

context
     Set context ascii or html, sets pre- and post- values

line_break
     Return the current line-break

pre
     Return the current pre-setting

pre
     Return the current post-setting

fmt
     Default printout (of given hash, or anything) - very basic formatter
     of simple data.

     %data = (         'this' => 'that',         'here' => [qw(there up
     down turnaround)],     );

     	print $pb->fmt(\%data);

     this=that here=there up down turnaround

_fmt_sql
     Format sql queries

format_data
     Formats this, and writes (via a format) to results file.

     If it recognises the object via: bug(id), message(id), patch(id),
     note(id), user(id) the appropriate formatting is applied.

          my $res = $format->format_data(\%this);

format_fields
     Format individual entries for output, handles bugs, messages, users,
     patches, tests, notes

          my $h_tkt = $o_perlbug->format_fields($h_tkt);

schema
     Schema for database, should allow the database to format this for us
     ...

overview
     Formating for overview.

          $fmt{'bugs'} = $data{'bugs'};

format_this
     Wrapper for calls to filehandle, local data.

          my $res = $obj->format_this('res', "FORMAT_$type_$format", $max);

          # $res = ''

_current_target
     Any call which includes `format_this()' in this node, `format_data'
     in this node etc. will automatically set the _current_target to a
     copy of that data.  This can then be inspected from here.

          print Dumper($obj->_current_target);

start
     Sets start header for results.

     =cut

     sub start { 	return ";     my $self    = shift;     my $flag    =
     shift;     my $format  = shift || $self->current('format') || 'a';
     $self->debug(3, "Section: $flag");     my $start = ";     if
     ($format eq 'a') {         $start = "$flag: \n";     } elsif ($format
     eq 'A') {         $start = qq|

          ==============================================================================
          Section: $flag
          ------------------------------------------------------------------------------

     |;     } elsif ($format eq 'h') {         $start = '<p>';     } elsif
     ($format eq 'H') {         $start = '<hr>';     } else {
     $self->debug(0, "Unknown format options: '$format'");     }
     $self->result($start, 1);     return "; }

     sub finish { 	my $self = shift; 	return "; }

     # format WWW fields #

     ------------------------------------------------------------------------------

format_bug_fields
     Format individual bug entries for placement

          my $h_tkt = $o_web->format_bug_fields($h_tkt);

format_message_fields
     Format individual message entries for placement

          my $h_msg = $o_web->format_message_fields($h_msg);

format_patch_fields
     Format individual patch entries for placement

          my $h_pat = $o_web->format_patch_fields($h_pat);

format_test_fields
     Format individual test entries for placement

          my $h_test = $o_web->format_test_fields($h_test);

format_note_fields
     Format individual note entries for placement

          my $h_msg = $o_web->format_note_fields($h_msg);

format_user_fields
     Format individual user entries for placement

          my $h_usr = $o_web->format_user_fields($h_usr);

href
     Return list of perlbug.cgi?req=id&... hyperlinks to given list).

     Maintains format, rng etc.

          my @links = $o_web->href('bid', \@bids, 'visible element of link', [optional subject hint]);

mailto
     Return mailto: for a particular ticket

          my $mailto = $o_web->mailto($h_tkt);

popup
     Returns appropriate (cached) popup with optional default value
     inserted.

          my $popup = $web->popup('status', $unique_id, $default);

          $self->debug(3, "Admin ($1) of bug ($id) called.");
          $tkt{'category'}   = $self->popup('category', 	$tkt{'category'}, $id.'_category');
          $tkt{'osname'}     = $self->popup('osname', 	$id.'_osname',    $tkt{'osname'});
          $tkt{'select'}     = $cgi->checkbox(-'name'=>'bugid', -'checked' => '', -'value'=> $id);
          $tkt{'severity'}   = $self->popup('severity', 	$id.'_severity',   $tkt{'severity'});
          $tkt{'status'}     = $self->popup('status', 	$id.'_status',     $tkt{'status'});

FORMAT_B_l
     Lean ascii format for tickets:

FORMAT_B_A
     Default ASCII format for bugs:

     ...

FORMAT_B_L
     Lean html format for tickets:

FORMAT_B_h
     Html minimal format: ...

FORMAT_B_H
     Html, tabled in block format: ...

FORMAT_O_a
     Formating for overview (default).  ...

     =cut

     format FORMAT_O_a_TOP = PerlBug Database overview, figures in
     brackets() are still open:

     ------------------------------------------------------------------------------
     .

     format FORMAT_O_a =  @<<<<<< $fmt{'_pre'} Bugs     Messages Patches
     Tests  Notes  Admins  24hrs   7days   30days   90days  @<<<<<<<
     @<<<<<<< @<<<<<< @<<<<< @<<<<< @<<<<<< @<<<<<< @<<<<<< @<<<<<<< @<<<<<
     $fmt{'bugs'}, $fmt{'messages'}, $fmt{'patches'}, $fmt{'tests'},
     $fmt{'notes'}, $fmt{'administrators'}, $fmt{'days1'}, $fmt{'days7'},
     $fmt{'days30'}, $fmt{'days90'} Ratios:     Open to Closed   Closed to
     Open   Msgs to Bugs     Bugs to Admins             @<<<<<<<<<<<<<
     @<<<<<<<<<<<<<   @<<<<<<<<<<<<<   @<<<<<<<<<<<<<<<
     $fmt{'ratio_o2c'}, $fmt{'ratio_c2o'}, $fmt{'ratio_m2t'},
     $fmt{'ratio_t2a'} Status:     Open       Closed     Busy       Onhold
        Abandoned  Duplicate             @<<<<<<<<< @<<<<<<<<< @<<<<<<<<<
     @<<<<<<<<< @<<<<<<<<< @<<<<<<<<<             $fmt{'open'},
     $fmt{'closed'}, $fmt{'busy'}, $fmt{'onhold'}, $fmt{'abandoned'},
     $fmt{'duplicate'} Category:   Install    Library    Patch      Core
        Docs       Utilities             @<<<<<<<<< @<<<<<<<<< @<<<<<<<<<
     @<<<<<<<<< @<<<<<<<<< @<<<<<<<<<             $fmt{'install'},
     $fmt{'library'}, $fmt{'patch'}, $fmt{'core'}, $fmt{'docs'},
     $fmt{'utilities'}             Unknown    Notabug    OK
     @<<<<<<<<< @<<<<<<<<< @<<<<<<<<<             $fmt{'unknown'},
     $fmt{'notabug'}, $fmt{'ok'} Severity:   Fatal      High       Medium
       Low        Wishlist             @<<<<<<<<< @<<<<<<<<< @<<<<<<<<<
     @<<<<<<<<< @<<<<<<<<<             $fmt{'fatal'}, $fmt{'high'},
     $fmt{'medium'}, $fmt{'low'}, $fmt{'wishlist'} OS:         Generic
     Linux      Win32      MacOS      Solaris    Hpux      Aix
     @<<<<<<<<< @<<<<<<<<< @<<<<<<<<< @<<<<<<    @<<<<<<<<< @<<<<<<<<
     @<<<<<<<<             $fmt{'generic'}, $fmt{'linux'},
     $fmt{'mswin32'}, $fmt{'macos'}, $fmt{'solaris'}, $fmt{'hpux'},
     $fmt{'aix'},  @<<<<<< $fmt{'_post'} .

FORMAT_O_h_TOP
     Formatting for html overview.

FORMAT_S_a
     Default format for Schema fields for database (top elsewhere).

FORMAT_S_h
     Html format for Schema fields for database (top elsewhere
     temporarily).

FORMAT_M_l
     Messages lean format.

FORMAT_M_a
     Messages list format.

FORMAT_M_A
     Messages block ASCII format.

FORMAT_M_h
     Messages in list html format.

FORMAT_M_H
     Messages in block html format.

FORMAT_U_l
     User list format.

FORMAT_U_a
     User list format.

FORMAT_U_h
     User in list html format.

FORMAT_H_l
     History list format.

FORMAT_H_a
     History list format.

FORMAT_H_h
     History in list html format.

FORMAT_N_l
     Note lean format.

FORMAT_N_a
     Note list format.

FORMAT_N_A
     Note block ASCII format.

FORMAT_N_h
     Note in list html format.

FORMAT_N_H
     Note in block html format.

FORMAT_P_l
     Patch lean format.

FORMAT_P_a
     Patch list format.

FORMAT_P_A
     Patch block ASCII format.

FORMAT_P_h
     Note in list html format.

FORMAT_P_H
     Patch in block html format

FORMAT_T_l
     Test lean format.

FORMAT_T_a
     Test list format.

FORMAT_T_A
     Test block ASCII format.

FORMAT_T_h
     Test in list html format.

FORMAT_T_H
     Test in block html format

AUTHOR
======

   Richard Foley perlbug@rfi.net Oct 1999

Module for generic logging/debugging functions to all Perlbug.
**************************************************************

NAME
====

   Perlbug::Log - Module for generic logging/debugging functions to all
Perlbug.

DESCRIPTION
===========

   Expected to be called from sub-classes, this needs some more work to
cater comfortably for non-method calls.

SYNOPSIS
========

     my $o_log = Perlbug::Log->new('log' => $log, 'res' => $res);

     $o_log->append('res', "other data\n");

     $o_log->append('log', "some data\n");

     $o_log->append('res', "OK\n");

     my $a_data = $o_log->read('res');

     print $a_data; # 'other data\nOK\n'

METHODS
=======

new
     Create new Perlbug::Log object

          my $obj = Perlbug::Log->new('log' => $log, 'res' => $res, 'rng' => $rng, 'debug' => 2);

debug
     Debug method, logs to `' in this node, with different levels of
     tracking:

          $pb->debug('duff usage');                # undefined second arg (treated as level 0)
          $pb->debug(0, 'always tracked'));        # $Perlbug::Debug >= 0
          $pb->debug(1, 'tracked if debug >= 1');  # key calls
          	$pb->debug(2, 'tracked if debug >= 2');  # key calls plus data
          	$pb->debug(3, 'tracked if debug >= 3');  # includes caller info etc.

          	$pb->debug('in', 'args');    	# in|out 		(2++, (data 4++))
          $pb->debug('out', 'result');    # in|out,		(2++, (data 4++))

fatal
     Deals with a fatal condition by logging and dieing, traps dies to
     come out here:

          &do_this or $pb->fatal($message);

logg
     Logs args to log file, which is either 'pb_19980822', or
     pb_backup_log.  Expected to be used via `' in this node.

          &do_this($self, 'x') and $pb->logg('Done that');

fh
     Define and return filehandles, keyed by 3 character string for our
     own purposes, otherwise the file name sitting in the system('text')
     dir.

          $o_log->fh($file, '+>>', 0755);

append
     Storage area (file) for results from queries, returns the FH.

          my $pos = $log->append('res', 'store this stuff');

          # $pos is position in file

read
     Return the results of the queries from this session.

          my $a_data = $log->read('res');

truncate
     Truncate this file

          my $i_ok = $log->truncate('res');

prioritise
     Set priority nicer by given integer, or by 12.

set_user
     Sets the given user to the runner of this script.

copy
     Copy this to there

          $ok = $log->copy($file1, $file2);

          @file1_data = $log->copy($file1, $file2);

link
     link this to there

          $ok = $log->link($source, $target, [-f]);

create
     Create new file with this data:

          $ok = $self->create("$dir/$file.tmp", $data);

syntax_check
     Check syntax on given file

          $ok = $self->syntax_check("$dir/$file.tmp");

DESTROY
     Cleanup log and result files.

AUTHOR
======

   Richard Foley perlbug@rfi.net Oct 1999 2000

Perlbug test module placeholder
*******************************

NAME
====

   Perlbug::Test - Perlbug test module placeholder

DESCRIPTION
===========

   x

SYNOPSIS
========

     y

METHODS
=======

new
     Create new Perlbug::Test object:

          my $o_test = Perlbug::Test->new();				# generic

          my $o_email_test = Perlbug::Test->new('Email'); # guess :-)

AUTHOR
======

   Richard Foley perlbug@rfi.net 2000

Perlbug test module placeholder
*******************************

NAME
====

   Perlbug::Test - Perlbug test module placeholder

DESCRIPTION
===========

   x

SYNOPSIS
========

     y

METHODS
=======

new
     Create new Perlbug::Test object:

          my $o_test = Perlbug::Test->new();				# generic

          my $o_email_test = Perlbug::Test->new('Email'); # guess :-)

AUTHOR
======

   Richard Foley perlbug@rfi.net 2000

Bug support functions for Perlbug
*********************************

NAME
====

   Perlbug::TM - Bug support functions for Perlbug

DESCRIPTION
===========

   Access to the database, bug get, set, id methods for Perlbug.

SYNOPSIS
========

     my $o_tm = Perlbug::TM->new;

     my $id = $o_tm->get_id('some long string with a tid [20010732.003] in it somewhere');

     print "ID: $id\n"; # 20010732.003

METHODS
=======

new
     Create new Perlbug::TM object:

          my $do = Perlbug::TM->new();

new_id
     Generate new_id for perlbug - YUK

get_id
     Determine if the string contains a valid bug ID.

          my ($ok, $tid) = $obj->get_id($str);

AUTHOR
======

   Chris Masto chrism@netmonger.net and Richard Foley perlbug@rfi.net Oct
1999

Table access
************

NAME
====

   Perlbug::Table - Table access

DESCRIPTION
===========

   Simple access to all database tables

USAGE
=====

     my $o_bug = $Perlbug::Table->new('BUG', 'ticketid');

     print "Our table has ".$o_bug->columns." columns\n";

     my $h_data = $o_bug->fetch($bug_id);

     print "Bug subject: ->$$h_data{'subject'}<- \n";

METHODS
=======

new
     Call with table name

          my $o_message = $Perlbug::Table->new('MESSAGE', 'primarykey');

     If 'primarykey' is not given, it will be built from
     "ref($class).'ID'": no support for multiple column primary key
     combos, yet.

Perlbug test module placeholder
*******************************

NAME
====

   Perlbug::Test - Perlbug test module placeholder

DESCRIPTION
===========

   x

SYNOPSIS
========

     y

METHODS
=======

new
     Create new Perlbug::Test object:

          my $o_test = Perlbug::Test->new();				# generic

          my $o_email_test = Perlbug::Test->new('Email'); # guess :-)

AUTHOR
======

   Richard Foley perlbug@rfi.net 2000

Perlbug testing module
**********************

NAME
====

   Perlbug::Testing - Perlbug testing module

DESCRIPTION
===========

   Utility functions for Perlbug test scripts.

   If run within a 'make test' sequence, the prints will normally only
appear from the todo, ok and `notOK' calls.

   Output is seen from output when `TEST_VERBOSE' is set to 1, or when the
script is being run directly.

   Note that files with iseven(filename)s (test_2, test_8, etc) are
normally expected to succeed with the given function test, and odd names
are expected to fail, thus giving a checkable failure.

   Names with only a zero, ie: my_test_0 are purely placeholders, and
should be ignored.

SYNOPSIS
========

     use Perlbug::Testing;
     	use Testing;
     	plan('todo' => 8); # will do nine(9)
     	my $test = 0;

     	my $o_test = Perlbug::Testing->new('Email'); # currently ignored
     	my @tests = get_tests('testmails/head2head', qw(this that etc));

     	my ($i_ok, $data) = $o_test->check_header(*STDIN); # for example
     	if ($i_ok == 1) { # == 1 (hopefully :-) || 0 :-(
     		ok($test);
     	} else {
     		notok($test);
     	}

     	output($test, 'data');
     	output("done test($test)");

METHODS
=======

new
     Create new Perlbug::Testing object:

          my $o_test = Perlbug::Testing->new();				# generic

          my $o_email_test = Perlbug::Testing->new('Email'); # guess :-)

output
     prints given args

iseven
     Return 0(odd) or 1(even) based on last number of given filename

          my $num = iseven($filename);

get_tests
     Wraps getting test material from test directory, incorporates test
     count.

          my @test = get_tests($t_dir, qw(this that and the other));

AUTHOR
======

   Richard Foley perlbug@rfi.net 2000

Web interface to perlbug database.
**********************************

NAME
====

   Perlbug::Web - Web interface to perlbug database.

DESCRIPTION
===========

   Methods for web access to perlbug database via Perlbug,
module.

SYNOPSIS
========

     my $o_web = Perlbug::Web->new;

     print $o_web->header;

     print $o_web->request('help');

     print $o_web->footer;

METHODS
=======

new
     Create new Perlbug::Web object.

          my $web = Perlbug::Web->new;

setup
     Setup Perlbug::Web

          $o_perlbug->setup($cgi);

check_user
     Access authentication via http, we just prime ourselves with data
     from the db as well.

     Should really be integrated as a database lookup via Apache, but we
     do not know this will be the webserver?

header
     Return consistent header.

          print $web->header;

switch
     Parse switch

request
     Handle all web requests

overview
     Wrapper for doo method

graph
     Display pie or mixed graph for category of bugs etc., mixed to come.

nid
     Wrapper for don note access

tid
     Wrapper for dot test id access

pid
     Wrapper for dop patch id access

bid
     Wrapper for dob bugid access

patches
     Wrapper for dop patchid access

uid
     Wrapper for dou user/administrator access

hist
     History mechanism for bugs and users.

     Move formatting to Format::history !!!

headers
     Headers for all objects (m, n, p, t) by id

mheader
     Headers for message

pheader
     Headers for patches

nheader
     Headers for notes

theader
     Headers for tests

bidmids
     Wrapper for bugid and messageid access

mids
     Wrapper for retrieve by messageid access

delete
     Wrapper for delete access

update
     Wrapper for update access

nocc
     Wrapper for nocc update access

sql_query
     Open field sql query processor

web_query
     Form bug search web query results

current_buttons
     Returns array of relevant buttons by context key

          my @buttons = $o_web->current_buttons('search update reset', scalar(@uids), [$colspan]);

footer
     Return consistent footer.

          print $web->footer;

administrators
     List of administrators

spec
     Returns specifications for the Perlbug system.

help
     Web based help menu for perlbug.

          print $web->help;

administration_failure
     Deal with a failed administration attempt

          my $i_ok = $self->administration_failure($bid, $user, $commands);

todo
     To do list, may be appended to

adminfaq
     adminFAQ

search
     Search form into result

          with chosen params as defaults...

case
     Handle case sensitivity from web search form.

format_web_query
     Produce SQL query for bug search from CGI query.

          my $query = $web->format_web_query;

wildcard
     Convert '*' into '%' for sqlquery

          my $string = $self->wildcard('5.*');

web_update
     For bugs and users

tenify
     Create range of links to split (by tens or more) bugids from web
     query result.

          $self->tenify(\@_bids, 7); # in chunks of 7

range
     Store and retrieve range of bugs, swap between using filesystem and
     database?

          $id = $o_web->range($id, $data); 		# get and set

comment
     Return string as html comment

          my $commented = $o_web->comment(qq|<input type="text" name="dont_know" value="vaguer_still">|);

hide
AUTHOR
======

   Richard Foley perlbug@rfi.net Oct 1999

Object Persistence in SQL Databases.
************************************

NAME
====

   Persistence::Database::SQL - Object Persistence in SQL Databases.

SYNOPSIS
========

     use Persistence::Database::SQL;

     my $db = new Persistence::Database::SQL
       ( Engine => 'Postgres',
         Database => $database_name,
         Table => $table_name,
         Template => $template_hashref );

     my (@objects) = $db->search
       ( Key => $key,
         Regex => $regex );

     for $obj (@objects) {
       $db->table('expired');
       $obj->commit();
       $db->table($table_name);
       $obj->expire();
     }

     my $dbhandle = $db->dbhandle();

     my $query = "SELECT oid,* FROM $table_name WHERE $field=$value";
     my $sth = $dbhandle->prepare($query); $sth->execute();
     while (@row = $sth->fetchrow()) {
       my $obj = new Persistence::Object::Postgres
         ( __Dope => $db,
           __Oid => $row[0] );
       $obj->expire();
     }

DESCRIPTION
===========

   This module provides a store of persistent objects using various DBMS
engines. It works in association with a lower level persistent object
implementation, such as Persistence::Object::Postgres.

   Using a template mapping object properties to PostgreSQL class fields,
it is possible to automatically generate DBMS fields out of the object
data, which allows you to use SQL indexing and querying facilities on your
database of persistent objects.

CONSTRUCTOR
===========

new()
     Creates a new Database Object.

          my $database = new Persistence::Database::SQL
            (
              Engine => 'Postgres',           # Required
              Database => $database_name,
              Table => $table_name,
              Template => $template_hashref,

          Host => $db_host,               # Optional
          Port => $db_port,
          Username => $db_username,
          Password => $db_password

          Createfields => $boolean,
          Createtables => $boolean
              );

     Takes a hash argument with following possible keys:

     *Engine*

     The name of the underlying DBMS engine, for which there must be a
     Persistence::Object::Engine class available. Currently, the only
     available engine is 'Postgres'. This attribute is required.

     Database

     The name of the database. A database by this name must exist
     previously within the DBMS system in use with sufficient priveleges
     for the user. This attribute is required.

     Table

     The table within the database to use for object storage. A table by
     this name must exist previously within the DBMS system in use with
     sufficient priveleges for the user. This attribute is required, and
     can be later changed with the table() method.

     Template

     A reference to a hash that maps persistent object key names to
     database field names. Key names that are mapped in the template will
     be extracted and stored in separate database fields. In the degenerate
     case where you provide an empty hash for the mapping template, only
     the complete object dump is stored.

     The complete object dump will always be stored, in a database field
     called __dump, which will be created if it doesn't exist. If the
     database user doesn't have sufficient priveleges to alter tables, and
     the __dump field doesn't exist in the database, commit() will fail.

     This attribute is required, and can be later changed with the
     template() method.

     Host

     The name or IP address of the database server. A default value is
     provided by the DBMS-specific object class if this attribute is
     omitted.

     Port

     The port on which the database server can be accessed. A default value
     is provided by the DBMS-specific object class if this attribute is
     omitted.

     Username

     The username to use to acccess the database server. A default value,
     usually the username of the user running the program, is provided by
     the DBMS-specific object class if this attribute is omitted.

     Password

     The password for the user. A default value may be provided by the
     DBMS-specific object class if this attribute is omitted, though it
     would probably be an empty string.

     *Createfields*

     Whether or not new fields should be created in the database to meet
     the needs of complying with the mapping template. If true, fields will
     silently be created in the database. For this to work, the database
     user must have sufficient priveleges within the database system.

     If false, data will not be stored in a separate database field even if
     a mapping for it exists in the template, unless the field in question
     already exists in the database.

     The default is true. This attribute can be queried and changed on the
     fly with the createfields() method.

     *Createtables*

     Whether or not new tables should be created in the database if they
     are referenced but don't already exist. If true, tables will
     automatically be created as needed. For this to work, the database
     user must have sufficient priveleges within the database system.

     If false, tables will not be automatically created, which will cause
     commit() and load() to fail if asked to operate on a nonexistent
     table.

     The default is true. This attribute can be queried and changed on the
     fly with the createtables() method.

     NOTE: This is not yet implemented. For the moment, tables are NOT
     automatically created, regardless of the value of this attribute.

OBJECT METHODS
==============

search()
     Searches the database for objects whose field values match the regular
     expression specified.

          $database->search
            ( Key => $key,
              Regex => $regex );

dbhandle()
     Returns the handle to the database connection. You could use this to
     execute arbitrary SQL queries on the database.

          $handle = $database->dbhandle()

BUGS
====

   * Error checking needs work.

SEE ALSO
========

   Persistence::Object::Postgres(3), Data::Dumper(3),
Persistence::Object::Simple(3), perlobj(1), perlbot(1), perltoot(1).

AUTHOR
======

   Persistence::Database::SQL is Copyright (c) 2000 Ashish Gulhati
<hash@netropolis.org>. All Rights Reserved.

ACKNOWLEDGEMENTS
================

   Thanks to Barkha for inspiration, laughs and all 'round good times; to
Vipul for Persistence::Object::Simple, the constant use and abuse of which
resulted in the writing of this module; and of-course, to Larry Wall,
Richard Stallman, and Linus Torvalds.

LICENSE
=======

   This code is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   It would be nice if you would mail your patches to me, and I would love
to hear about projects that make use of this module.

DISCLAIMER
==========

   This is free software. If it breaks, you own both parts.

Object Persistence with PostgreSQL.
***********************************

NAME
====

   Persistence::Object::Postgres - Object Persistence with PostgreSQL.

SYNOPSIS
========

     use Persistence::Database::SQL;

     my $db = new Persistence::Database::SQL
       ( Engine => 'Postgres',
         Database => $database_name,
         Table => $table_name,
         Template => $template_hashref );

     my $object1 = new Persistence::Object::Postgres
       ( __Dope => $db,
         $key => $value );

     my $object2 = new Persistence::Object::Postgres
       ( __Dope => $db,
         __Oid => $object_id );

     $object1->{$key} = $object2->{$key};

     $object_id = $object1->commit();
     $object2->expire();

DESCRIPTION
===========

   This module provides persistence facilities to its objects. Object
definitions are stored in a PostgreSQL database as stringified perl data
structures, generated with Data::Dumper. Persistence is achieved with a
blessed hash container that holds the object data.

   Using a template mapping object properties to PostgreSQL class fields,
it is possible to automatically generate PostgreSQL fields out of the
object data, which allows you to use poweful PostgreSQL indexing and
querying facilities on your database of persistent objects.

   This module is intended for use in conjunction with the object database
class Persistence::Database::SQL, which provides persistent object
database handling functionality for multiple DBMS back-ends.
Persistence::Object::Postgres is the module that implements methods for
the PostgreSQL back-end.

CONSTRUCTOR
===========

new()
     Creates a new Persistent Object.

          my $object = new Persistence::Object::Postgres
            ( __Dope => $database );

     Takes a hash argument with following possible keys:

     __Dope

     The Database of Persistent Entities. This attribute is required and
     should have as its value a Persistence::Database::SQL object
     corresponding to the database being used.

     *__Oid*

     An optional Object ID. If this attribute is specified, an attempt is
     made to load the corresponding persistent object. If no corresponding
     object exists, this attribute is silently ignored.

OBJECT METHODS
==============

commit()
     Commits the object to the database.

          $object->commit();

expire()
     Irrevocably destroys the object. Removes the persistent entry from the
     DOPE.

          $object->expire();

     If you want to keep a backup of the object before destroying it, use
     commit() to store it in a different table or database.

          $db->table('expired');
          $object->commit;
          $db->table('active');
          $object->expire();

Inheriting Persistence::Object::Postgres
========================================

   In most cases you would want to inherit this module to provide
persistence for your own classes. If you use your objects to store refs to
class data, you'd need to bind and detach these refs at load() and
commit(). Otherwise, you'll end up with a separate copy of class data for
every object which will eventually break your code. See perlobj(1),
perlbot(1), and perltoot(1), on why you should use objects to access class
data.

BUGS
====

   * Error checking needs work.

   * __Oid is ignored by new() if an object of this ID doesn't already
     exist. That's because Postgres generates an oid for us at commit()
     time. This is a potential compatibility issue as many other database
     engines don't work like postgres in this regard.

     A more generic solution would be to ignore the Postgres oid field and
     create a unique identifier of our own at commit(), or use the user
     specified __Oid. This will probably be implemented in a future
     version, but code written with the assumption that __Oid is ignored
     should still work fine. __Oid just won't be ignored, is all.

SEE ALSO
========

   Persistence::Database::SQL(3), Data::Dumper(3),
Persistence::Object::Simple(3), perlobj(1), perlbot(1), perltoot(1).

AUTHOR
======

   Persistence::Object::Postgres is Copyright (c) 2000 Ashish Gulhati
<hash@netropolis.org>. All Rights Reserved.

ACKNOWLEDGEMENTS
================

   Thanks to Barkha for inspiration, laughs and all 'round good times; to
Vipul for Persistence::Object::Simple, the constant use and abuse of which
resulted in the writing of this module; and of-course, to Larry Wall,
Richard Stallman, and Linus Torvalds.

LICENSE
=======

   This code is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   It would be nice if you would mail your patches to me, and I would love
to hear about projects that make use of this module.

DISCLAIMER
==========

   This is free software. If it breaks, you own both parts.

Object Persistence with Data::Dumper.
*************************************

NAME
====

   Persistence::Object::Simple - Object Persistence with Data::Dumper.

SYNOPSIS
========

     use Persistence::Object::Simple;
     my $perobj = new Persistence::Object::Simple ( __Fn   => $path );
     my $perobj = new Persistence::Object::Simple ( __Dope => $directory );
     my $perobj = new Persistence::Object;
     my $perobj->commit ();

DESCRIPTION
===========

   P::O::S provides persistence functionality to its objects.  Object
definitions are stored as stringified perl data structures, generated with
Data::Dumper, that are amenable to manual editing and external processing
from outside the class interface.

   Persistence is achieved with a blessed hash container that holds the
object data. The container can store objects that employ non-hash
structures as well. See `"Inheriting Persistence::Object::Simple"' in this
node, `"Class Methods"' in this node and the persistent list class example
(examples/Plist.pm).

CONSTRUCTOR
===========

new()
     Creates a new Persistent Object or retrieves an existing object
     definition.  Takes a hash argument with following possible keys:

    __Fn
          Pathname of the file that contains the persistent object
          definition. __Fn is treated as the object identifier and
          required at object retrieval.

    __Dope
          The Directory of Persistent Entities.  P::O::S generates a
          unique filename to store object data in the specified directory.
          The object identifier is the complete pathname of the object's
          persistent image and is placed in the __Fn instance variable.
          This argument is ignored when __Fn is provided.

    __Create
          A boolean attribute that can either take a "Yes" or a "No"
          value. It informs the method whether to create an object image
          if one doesn't already exist.  __Create is "yes" by default.

    __Random
          Random string used as input for computing the unique object
          name. This should be used when unpredictable object names are
          required for security reasons. The random string can be
          generated with Crypt::Random, a module which provides
          cryptographically secure random numbers.

     When new() is called without any arguments it uses a unique file in
     the default DOPE, "/tmp", to store the object definition. The default
     DOPE can be altered with the dope() method.

          $po = new Persistence::Object::Simple
                ( __Fn => "/tmp/codd/suse5.2.codd" );

          # -- generates a unique filename  in /tmp/codd
          $po  = new Persistence::Object::Simple
                ( __Dope => "/tmp/codd" );
          print $po->{ __Fn };

          # -- generates a unique filename in defalt dope (/tmp)
          $po  = new Persistence::Object::Simple;
          print $po->{ __Fn };

METHODS
=======

commit()
     Commits the object to disk.  Like new() it takes __Fn and __Dope
     arguments, but __Dope takes precedence.  When a __Dope is provided,
     the directory portion of the object filename is ignored and the
     object is stored in the specified directory.

          $perobj->commit ();
          $perobj->commit (  __Fn   => $foo );
          $perobj->commit (  __Dope => $bar );

     Commit() can also store non-object data refs. See `"Class Methods"'
     in this node.

expire()
     Irrevocably destructs the object.  Removes the persistent entry from
     the DOPE.

          $perobj->expire ();

     If you want to keep a backup of the object before destroying it, use
     commit() to store in a different location. Undefing $obj->{ __Fn }
     before writing to the disk will force commit() to store the object in
     a unique file in the specified DOPE.

          $perobj->{ __Fn } = undef;
          $perobj->commit ( __Dope => "/tmp/dead" );
          $perobj->expire ();

move()
     Moves the object to a different DOPE.

          $perobj->move ( __Dope => "/some/place/else" );

     Specifying __Fnalter attribute will force move() to drop the existing
     file name and generate a new one in specified directory. This can be
     useful when backing up objects that may have the same filename.

     $perobj-> ( __Dope => 'queues/backup',                 __Fnalter => 1
     );

lock()
     Gets an exclusive lock.  The owner of the lock can commit() without
     unlocking.

          $perobj->lock ();

unlock()
     Releases the lock.

          $perobj->unlock ();

dumper()
     Returns the Data::Dumper instance bound to the object.  Should be
     called before commit() to change Data::Dumper behavior.

          my $dd = $perobj->dumper ();
          $dd->purity (1);
          $dd->terse  (1);  # -- smaller dumps.
          $perobj->commit ();

     See Data/Dumper.

load()
     Class method that retrieves and builds the object.  Takes a filename
     argument.  Don't call this directly, use new () for object retrieval.

     Persistence::Object::Simple->load (         __Fn =>
     '/tmp/dope/myobject'     );

Inheriting Persistence::Object::Simple
======================================

   In most cases you would want to inherit this module.  It does not
provide instance data methods so the object data functionality must be
entirely provided by the inheriting module. Moreover, if you use your
objects to store refs to class data, you'd need to bind and detach these
refs at load() and commit().  Otherwise, you'll end up with a separate
copy of class data with every object which will eventually break your
code.  See Perlobj (perl.info), Perlbot (perl.info),
and Perltoot (perl.info), on why you
should use objects to access class data.

   Persistence::Database inherits this module to provide a transparently
persistent database class.  It overrides new(), load() and commit()
methods.  There is no class data to bind/detach, but load() and commit()
are overridden to serve as examples/templates for derived classes.  Data
instance methods, AUTOLOADed at runtime, automatically commit() when data
is stored in Instance Variables.  For more details, Read The Fine Sources.

Class Methods
=============

   load() and commit() can be used for storing non-object references.
commit() and load() can be invoked as class methods with a "Data" argument.
Some examples:

     # generates a unique filename in /tmp
     my $fn = Persistence::Object::Simple->commit (
         __Dope => "/tmp", Data => $x );

     @list = 0..100;
     Persistence::Object::Simple->commit
      ( __Fn => '/tmp/datarefs/numbers',
        Data => \@list;
      );

     $list = Persistence::Object::Simple->load
      ( __Fn => '/tmp/datarefs/numbers' );

     $" = "\n"; print "@$list";

SEE ALSO
========

   Data::Dumper(3), Persistence::User(3), perl(1).

AUTHOR
======

   Vipul Ved Prakash, mail@vipul.net

COPYRIGHT
=========

   Copyright (c) 1998, Vipul Ved Prakash.  All rights reserved.  This code
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

CONTRIBUTORS
============

     Mike Blazer <blazer@mail.nevalink.ru>
     Holger Heimann <hh@it-sec.de>

A framework of classes that provides persistence for Perl objects
*****************************************************************

NAME
====

   Persistent - A framework of classes that provides persistence for Perl
objects

SYNOPSIS
========

     use Persistent::File;
     use English;  # import readable variable names like $EVAL_ERROR

     eval {  ### in case an exception is thrown ###

     ### allocate a persistent object ###
     my $person = new Persistent::File('people.txt');

     ### define attributes of the object ###
     $person->add_attribute('firstname', 'ID', 'VarChar', undef, 10);
     $person->add_attribute('lastname',  'ID', 'VarChar', undef, 20);
     $person->add_attribute('telnum', 'Persistent',
                            'VarChar', undef, 15);
     $person->add_attribute('bday', 'Persistent', 'DateTime', undef);
     $person->add_attribute('age', 'Transient', 'Number', undef, 2);

     ### query the datastore for some objects ###
     $person->restore_where(qq{
                               lastname = 'Flintstone' and
                               telnum =~ /^[(]?650/
                              });
     while ($person->restore_next()) {
       printf "name = %s, tel# = %s\n",
              $person->firstname . ' ' . $person->lastname,
              $person->telnum;
     }
       };

     if ($EVAL_ERROR) {  ### catch those exceptions! ###
       print "An error occurred: $EVAL_ERROR\n";
     }

ABSTRACT
========

   This framework of classes makes it easier to store and retrieve Perl
objects to and from various types of data stores.  Using the common
interface that all of these classes inherit, you can store objects to
various types of data stores such as text and DBM files, relational
databases, LDAP directories and so on, all with the same programming
interface.  You can also query and retrieve these objects from the various
types of data stores by using the query/search language of the data store.
Currently, there are three types of data stores that have been
implemented:

     o Perl based data stores (memory, text, and DBM files)
     o SQL based data stores (Oracle, Sybase, MySQL, and mSQL databases)
     o LDAP based data stores

   So you have the consistency of the common inherited interface with the
flexibility of the data store's native query language.

   The most current version of the Persistent framework of classes is
always available at:

     http://www.bigsnow.org/persistent
     ftp://ftp.bigsnow.org/pub/persistent

Architecture of the Persistent Framework
----------------------------------------

   The Persistent framework of classes starts with an abstract base class,
Base.pm, that defines the interface for all of the Persistent subclasses.
The subclasses inherit the interface from the base class class and provide
the implementations for the various types of data stores that they
support.  The class diagram for the framework looks something like this:

     +-----------+
     |           |
     |  Base.pm  |-------------------------+
     | (abstract)|                         |
     +-----------+                         |
       |       |                           |
                    +-----+       +------------+              |
                    |                          |              |
              +-----------+              +-----------+  +-----------+
              |           |              |           |  |           |
              | Memory.pm |              |   DBI.pm  |  |  LDAP.pm  |
              |           |              | (abstract)|  |           |
              +-----------+              +-----------+  +-----------+
                /       \                   /       \
               /         \                 /         \
              /           \               /           \
       +-----------+  +-----------+  +-----------+  +-----------+
       |           |  |           |  |           |  |           |
       |  File.pm  |  |   DBM.pm  |  | Oracle.pm |  | Sybase.pm |
       |           |  |           |  |           |  |           |
       +-----------+  +-----------+  +-----------+  +-----------+

INSTALLATION
============

   Because of the inheritance involved in the Persistent framework, the
Persistent/Base, package will need to be installed
first.  The Persistent/Base, package does include
the Persistent/Memory, Persistent/File,
and Persistent/DBM, classes since
the modules that they require are part of the standard Perl distribution.
After the Persistent/Base, package has been
installed, the other subclasses such as `Persistent::DBI' in this node and
Persistent/LDAP, may be installed.

   The installation of these packages is like any other standard CPAN
package.  You can find complete instructions in the README file that comes
with each package.

DESCRIPTION
===========

   Before we get started describing the methods in detail, it should be
noted that all error handling in this framework of classes is done with
exceptions.  In Perl, you throw an exception by calling die or in our case
by calling croak (from the Carp module).  You catch Perl exceptions by
using an eval block such as the following code does:

     eval {
       open FILE, $filename or die "$!";
       ### more stuff... ###
     };

     if ($@ ne '') {
       warn "exception caught: $@\n";
       ### clean up... ###
     }

   By checking the special variable *$@* (or $EVAL_ERROR if the English
module is used), you can determine whether or not an exception occurred
within the eval block.  Some people worry when they see an eval that the
code will be compiled dynamically and possibly more than once.  But,
because it is an eval block (not a string), the code is only compiled
once, which is at the same time as the surrounding code.

   So be sure to put an eval block around all of your code that uses the
Persistent methods so you can catch any exceptions that may occur.  Now,
on to the methods!

Instantiating a Persistent Class
--------------------------------

   There are two ways to create a Persistent object.  The first way is by
directly instantiating a Persistent class.  That is what we will cover in
this section.

   Instantiating a Persistent class is very simple, but it does vary for
each Persistent class.  All that is required is calling the constructor for
the Persistent class and passing the required arguments.  The constructor
arguments for each class are documented in the documentation for each
class.  So check the documentation for the specific class's constructor
before you call it.  Here's an example that creates a
Persistent/File, object:

     use Persistent::File;

     eval {
       ### call the constructor ###
       my $car = new Persistent::File('cars.txt');

     ### define attributes of the object ###
     ### NOTE: This is covered in detail later! ;) ###
     $this->add_attribute('firstname', 'id',
                          'VarChar',  undef, 10);
     $this->add_attribute('lastname',  'id',
                          'VarChar',  undef, 20);
     $this->add_attribute('telnum',    'persistent',
                          'VarChar',  undef, 15);
     $this->add_attribute('bday',      'persistent',
                          'DateTime', undef);
     $this->add_attribute('age',       'transient',
                          'Number',   undef, 2);
       };

     if ($@) {
       warn "Exception caught: $@\n";
     }

   There is only one argument passed to the constructor in this example
and it is the name of the file where the data is stored.  All possible
constructor arguments for the Persistent/File,
class can be found in its documentation.

   The only thing left to do is define the attributes of the object and
this is covered in one of the following sections, `Defining the Attributes
of an Object' in this node.

Subclassing a Persistent Class
------------------------------

   The second way to create a Persistent object is by subclassing a
Persistent class.  This is useful when the Persistent object will be used
by multiple programs or when custom methods for the class will be written.

   An additional class will be created in this approach and it will
inherit from a Persistent class such as Persistent::DBM like in the
following example:

     package Person;

     ### we are a subclass of an all-powerful Persistent class ###
     use Persistent::DBM;
     @ISA = qw(Persistent::DBM);

     sub initialize {   ### ALWAYS implement this method ###
       my $this = shift;

     ### call any ancestor initialization methods ###
     $this->SUPER::initialize(@_);

     ### define attributes of the object ###
     ### NOTE: This is covered in detail later! ;) ###
     $this->add_attribute('firstname', 'ID',
                          'VarChar',  undef, 10);
     $this->add_attribute('lastname',  'ID',
                          'VarChar',  undef, 20);
     $this->add_attribute('telnum',    'Persistent',
                          'VarChar',  undef, 15);
     $this->add_attribute('bday',      'Persistent',
                          'DateTime', undef);
     $this->add_attribute('age',       'Transient',
                          'Number',   undef, 2);
       }

     sub print {  ### custom method ###
       my $this = shift;

     printf("%-10s %-10s %15s %s %2s\n",
            defined $this->firstname ? $this->firstname : 'undef',
            defined $this->lastname ? $this->lastname : 'undef',
            defined $this->telnum ? $this->telnum : 'undef',
            defined $this->bday ? $this->bday : 'undef',
            defined $this->age ? $this->age : 'undef');
       }

     1;

   Defining the attributes of the object (and the method add_attribute) is
explained in the next section.  To actually create an instance of this
class, you just call the constructor of this class like so:

     use Person;

     eval {
       ### call the constructor ###
       my $person = new Person('people.dbm', undef, 'DB_File');

     ### call Persistent methods here... ###
       };

     if ($@) {
       warn "Exception caught: $@\n";
     }

   The constructor (the method new) is not defined in the Person class,
but in one of the parent classes and so it is inherited.  Now you just
need to define the attributes of the object, which is explained in the
next section, and your object will be ready to use.

Defining the Attributes of an Object
------------------------------------

   Defining of the attributes is either done after instantiating a
Persistent class or in the initialize method of the subclass.  The method
*add_attribute* is used to define an attribute and add it to the object.
The arguments to this method are the following:

     $this->add_attribute($name, $type, $datatype, @args);

   Parameters:

$name
     Name of the attribute.  The rules for this can vary since the name
     needs to be a valid name for a Perl method (subroutine) and follow the
     rules for the data store that is being used by the Persistent class.
     For example, if you are using the Persistent::Oracle class, then the
     name needs to be a valid name for a Perl method and an Oracle column.

$type
     Type of the attribute.  The valid types are Identity, Persistent, and
     *Transient*.  Identity attributes are what make the object unique.
     These attributes can be used to uniquely identify a single object and
     are stored in the data store.  Persistent attributes are stored in
     the data store along with the Identity attributes.  Transient
     attributes are values that are not stored in the data store.  You
     currently cannot query for an object based on a value in a transient
     field.  All of the type arguments can be abbreviated to a shorter
     form; only a single character such as 'I', 'P', or 'T' is required.
     The type arguments are also case-insensitive, so 'ident', 'persist',
     or 'trans' would work as arguments.

$datatype
     Data type of the attribute.  The valid data types currently are: Char,
     VarChar, String, Number, and DateTime.  The *@args* arguments that
     follow $datatype are passed as arguments to the constructor of the
     data type.  So refer to the documentation for the data type for more
     details.  The data type documents are:

     Persistent/DataType/Char,

     See Persistent/DataType/VarChar,

     See Persistent/DataType/String,

     See Persistent/DataType/Number,

     See Persistent/DataType/DateTime,

     The data type is not case-sensitive, but no abbreviation is allowed.

*@args*
     Arguments for the data type of the attribute.  Usually these consist
     of an initial value, length, etc.

   Here is an example of defining attributes for an object:

     $this->add_attribute('firstname', 'id',
                          'VarChar',  undef, 10);
     $this->add_attribute('lastname',  'id',
                          'VarChar',  undef, 20);
     $this->add_attribute('telnum',    'persistent',
                          'VarChar',  undef, 15);
     $this->add_attribute('bday',      'persistent',
                          'DateTime', undef);
     $this->add_attribute('age',       'transient',
                          'Number',   undef, 2);

   In this example, five attributes were added to the object.  The first
two make up the attributes that uniquely identify this object and the
third and forth are just attributes that will be saved in the data store.
The fifth attribute is temporary and so will not be saved to the data
store.  All of the attributes are initialized to undef and all of them
have an initial maximum length except for the DateTime attribute.  See the
data type documentation for more information on possible initialization
(constructor) arguments.

Accessing the Attributes of an Object
-------------------------------------

   To access the attributes of an object, you just invoke an attribute as
a method of the object.  So it should look something like this:

     $object->attribute($value);     ### set the attribute's value ###
     $value = $object->attribute();  ### get the attribute's value ###

   Here is an example that uses the object that we created and defined
earlier:

     ### set the attributes ###
     $person->firstname('Fred');
     $person->lastname('Flintstone');
     $person->telnum('650-555-1111');
     $person->age(45);
     $person->bday('1954-01-23 22:09:54');

     ### print the attributes ###
     printf("%-10s %-10s %15s %s %2s\n",
            $person->firstname,
            $person->lastname,
            $person->telnum,
            $person->bday,
            $person->age);

   For those of you interested, we just take advantage of the Perl
AUTOLOAD feature to implement these attribute accessor methods.  Pretty
cool, eh?  ;)

   If you have a collision between an attribute name and a method that is
part of the Persistent interface then you can use the value method to
access an attribute's value.  It works like this:

     ### get the attribute's value ###
     $value = $object->value($attribute);

     ### set the attribute's value ###
     $object->value($attribute, $value);

   Here is an example:

     ### set the attributes ###
     $person->value('firstname', 'Fred');
     $person->value('lastname', 'Flintstone');
     $person->value('telnum', '650-555-1111');
     $person->value('age', 45);
     $person->value('bday', '1954-01-23 22:09:54');

     ### print the attributes ###
     printf("%-10s %-10s %15s %s %2s\n",
            $person->value('firstname'),
            $person->value('lastname'),
            $person->value('telnum'),
            $person->value('bday'),
            $person->value('age'));

   When the value of an attribute is being set, the value arguments that
are passed must be in a valid format for the data type of the attribute.
You can find valid formats of values for the data types in their
respective documentation.  Look at the section for their value method.
The data type documentation can be found in:

   Persistent/DataType/Char,

   See Persistent/DataType/VarChar,

   See Persistent/DataType/String,

   See Persistent/DataType/Number,

   See Persistent/DataType/DateTime,

Accessing the Attribute Data of an Object
-----------------------------------------

   Instead of using all of the individual accessor methods to access the
attributes of an object, you can access all of the data as a hash with the
data method.  This method will return a reference to a hash containing
values of all of the Identity and Persistent attributes of the object.
You can also set all of the Identity and Persistent fields of the object
by passing the data method a reference to a hash containing all of the
values.  Of course, in both cases the keys of the hash are the attribute
names and the values are the actual attribute values.  Here is an example:

     ### set the attributes  ###
     $person->data({firstname => 'Marge', lastname => 'Simpson'});

     ### get and print the attributes ###
     my $href = $person->data();
     foreach my $key (keys %$href) {
       print "key = $key, value = $href->{$key}\n";
     }

Clearing the Attributes of an Object
------------------------------------

   Really easy, just do this:

     $object->clear();

   All attributes (Identity, Persistent, and Transient) are set to undef.

Setting the Data Store of an Object
-----------------------------------

   Sometimes, you may want to change the data store for an object.  You
can do this with the *datastore* method.  This method is implementation
dependent, so you will need to refer to the documentation for the
Persistent class that you using.  Here is an example that uses the
Persistent/File, class:

     use Persistent::File;
     my $person = new Persistent::File('people.txt', '|');
     $person->restore('Betty', 'Rubble');  ### covered later! ###
     $person->datastore('employees.txt', '|');
     $person->save();  ### covered later! ###

   In this example, the object was copied from the 'people.txt' file to
the 'employees.txt' file by changing the data store and saving the object.
Refer to the Persistent/File, documentation for a
description of the *datastore* arguments.

   The *datastore* method will also return either information regarding
the datastore or a reference or some sort of handle to the data store.
This can come in handy if you are trying to keep the number of connections
to a database or file handles to a minimum.  Because you can pass them on
to newly created objects like this:

     my $person = new Persistent::Oracle('dbi:Oracle:ORCL',
                                         'scott', 'tiger', 'emp');
     my $dept = new Persistent::Oracle($person->datastore(), 'dept');

   In this example, both the *$person* and *$dept* objects share the same
database connection.  Of course, the return values from the *datastore*
methods vary for each Persistent class implementation.  So, check the
documentation for the Persistent class.

Inserting an Object
-------------------

   After you set all of the Identity fields of an object and optionally
any of the Persistent fields, you can insert the object into the data
store.  If you have previously restored the object from the data store
that you are about to insert into, then the insert will either fail or the
object in the data store will be overwritten depending on the
implementation of the Persistent class that you are using.  Use of the
insert method looks something like this:

     $object->insert();

Updating an Object
------------------

   After you have inserted an object into a data store or retrieved an
object from a data store, you may update it.  If the object does not
already exist in the data store that you are about to update, then the
update may fail depending on the implementation of the Persistent class.
Use of the update method looks something like this:

     $object->update();

Saving an Object
----------------

   As you can see, it can get pretty complicated at times determining
whether or not you need to insert or update an object.  Here is where the
save method can come in handy.  With the save method, it will check the
internal state of the object and determine whether it needs to do an
insert or an update.  Its use looks something like this:

     ### do stuff with the object ... ###
     $person->firstname('Ted');
     ...

     ### Ooops!  Do I insert or update the object? ###
     ### No worries!  I'll just save it.  :) ###
     $person->save();

   The save method should return a true value if the object did previously
exist in the data store and a false value if it did not.  Unfortunately,
not all Persistent classes are implemented this way and so once again you
will need to check the documentation for the Persistent class that you are
using.

Restoring an Object
-------------------

   To restore an object from a datastore, you just need to pass the values
of the Identity attributes for the object you wish to restore to the
restore method.  Here is an example that restores a *Person* object that
has Identity attributes of *firstname* and *lastname*:

     $person->restore('Wilma', 'Flintstone');

   The order of the Identity attributes matters.  In this example, the
*firstname* attribute was added first and the *lastname* attribute was
added second.  And of course, the attributes were added to the object
using the *add_attribute* method.  The definition of the attributes
probably looked something like this:

     ### define attributes of the object ###
     $person->add_attribute('firstname', 'ID', 'VarChar', undef, 10);
     $person->add_attribute('lastname',  'ID', 'VarChar', undef, 20);

Restoring all Objects
---------------------

   To restore all objects from a data store, invoke the *restore_all*
method and loop through the objects one at a time using the *restore_next*
method.  The *restore_next* method will restore an object from the data
store, one at a time, until there are no more objects left to restore.  It
will return a true value when it has restored an object and a false value
when an object has not been restored and there are no more left to
restore.  Here is an example:

     $person->restore_all();
     while ($person->restore_next()) {
       print "Restored: ";  $person->print();
     }

   You can also sort the objects so that you can process the objects in a
certain order.  For instance, lets sort the objects by *lastname* then
*firstname*:

     $person->restore_all('lastname, firstname');
     while ($person->restore_next()) {
       print "Restored: ";  $person->print();
     }

   How about sorting them by last name in ascending order, then first
name, and then bday in descending order?

     $person->restore_all('lastname ASC, firstname, bday DESC');
     while ($person->restore_next()) {
       print "Restored: ";  $person->print();
     }

   Pretty cool, eh?  To you SQL gurus, this should look familiar.  It is
just a SQL ORDER BY clause.  You can now sort your objects from any type
of data store without having code a sort routine.  :)

   The *restore_all* method also returns the number of objects restored
from the data store.

Conditionally Restoring Objects
-------------------------------

   Sometimes you want to restore a group of objects that meet a certain
set of conditions.  The *restore_where* method allows selective restoring
of objects.  Its usage looks something like this:

     $object->restore_where($where, $order_by);
     while ($object->restore_next()) {
         ### do something with $object ###
     }

   The $where argument is implementation (data store) dependent, but for
the Perl based and SQL based implementations is nearly identical to a SQL
WHERE clause.  Refer to the documentation for the Persistent subclass
implemented for the data store for more on the syntax of the $where
argument.  The $order_by argument is the same for all implementations and
is a SQL ORDER BY clause.  Both of these arguments are optional.

   The best way to understand this method is to take a look at a few
examples.  Here is one that fetches all people who have a last name of
Flintstone and live in the 650 area code:

     use Persistent::File;
     my $person = new Persistent::File('people.txt', '|');
     $person->restore_where(
       "lastname = 'Flintstone' and telnum =~ /^[(]?650/"
     );
     while ($person->restore_next()) {
       print "Restored: ";  print_person($person);
     }

   In this example, we restored all of those people from a text file.
Nearly the same code works with an Oracle database.  Here is what the
Oracle code would look like:

     use Persistent::Oracle;
     my $person = new Persistent::Oracle('dbi:Oracle:ORCL',
                                         'scott', 'tiger', 'people');
     $person->restore_where(
       "lastname = 'Flintstone' and telnum like '650%'"
     );
     while ($person->restore_next()) {
       print "Restored: ";  print_person($person);
     }

   This code would work for any SQL compliant database (Sybase, MySQL,
mSQL, etc.)  Performing this query using the LDAP based Persistent class
would look like this:

     use Persistent::LDAP;
     my $person = new Persistent::LDAP('localhost', 389,
     				   'cn=Directory Manager', 'test1234',
     				   'ou=Engineering,o=Big Snow Org,c=US');
     $person->restore_where(
       "& (lastname=Flintstone)(telnum=650*)"
     );
     while ($person->restore_next()) {
       print "Restored: ";  print_person($person);
     }

   Please refer to the Persistent/LDAP,
documentation for a full explanation of the LDAP search filters used in
the *restore_where* method.  And refer to the `Persistent::DBI' in this
node documentation for further explanation of the SQL WHERE BY clauses
used.

   For the Perl based subclasses (Persistent::DBM, Persistent::File,
Persistent::Memory) the comparison operators supported are: <=, >=, <, >,
!=, ==.  And of course you can use =~ for regular expression matching.
The boolean operators to join the comparison operators together are: and,
or.  And of course parentheses are allowed and free.  You can really use
any valid Perl expression since the $where argument is just munged a bit
and then evaled.

   In some cases, you may be making comparisons with strings that have
quotes in them.  If this is the case, you can use the quote method to take
care of escaping those pesky quotes.

     $person->restore_where(
       sprintf("lastname = %s and telnum =~ /^[(]?650/",
               $person->quote($lastname)));
     while ($person->restore_next()) {
       print "Restored: ";  $person->print();
     }

   Now, if any last names contain quotes, they will be escaped and your
program won't break.

   The *restore_where* method also returns the number of objects restored
from the data store.

     $num_objs = $person->restore_where("lastname = 'Smith'");

OTHER METHODS OF INTEREST
=========================

data_type - Returns the Data Type of an Attribute
-------------------------------------------------

     eval {
       my $data_type = $person->data_type($attribute);
     };
     croak "Exception caught: $@" if $@;

   Returns the data type of an attribute.  This method throws Perl
execeptions so use it with an eval block.

   Parameters:

$attribute
     Name of an attribute of the object.

   Returns:

$data_type
     Name of the data type of an attribute.

data_type_params - Returns the Data Type Parameters of an Attribute
-------------------------------------------------------------------

     eval {
       my $params_ref = $person->data_type_params($attribute);
     };
     croak "Exception caught: $@" if $@;

   Returns the data type parameters of an attribute.  The parameters are
dependent on the data type.  This method throws Perl execeptions so use it
with an eval block.

   Parameters:

$attribute
     Name of an attribute of the object.

   Returns:

*\@data_type_params*
     Reference to an array containing the data type parameters for the
     attribute.

data_type_object - Returns the Data Type Object of an Attribute
---------------------------------------------------------------

     eval {
       my $data_type_obj = $person->data_type_object($attribute);
     };
     croak "Exception caught: $@" if $@;

   Returns the data type object of an attribute.  This method throws Perl
execeptions so use it with an eval block.

   Parameters:

$attribute
     Name of an attribute of the object.

   Returns:

$data_type_obj
     Data type object for the attribute.

quote - Quotes a String Literal for Use in a Query
--------------------------------------------------

     $person->restore_where(sprintf("lastname = %s",
                                    $person->quote($lastname)));

   Quotes a string literal for use in a query clause (*$where_by* argument
in *restore_where* method) by escaping any special characters (such as
quotation marks) contained within the string and adding the required type
of outer quotation marks.  This method does not throw exceptions.

   Parameters:

$str
     String to quote and escape.

   Returns:

$quoted_str
     Quoted and escaped string.

debug - Returns/Sets the Debugging Flag
---------------------------------------

     ### set the debugging flag ###
     $object->debug($flag);

     ### get the debugging flag ###
     $flag = $object->debug();

   Returns (and optionally sets) the debugging flag of an object.  This
method does not throw Perl execeptions.

   Parameters:

$flag
     If set to a true value then debugging is on, otherwise, a false value
     means off.

EXAMPLES
========

   I used quite a few examples throughout this documentation, so I
recommend taking a look at those.  But, if you are looking for a complete
example, take a look in the examples directory that is part of the
Persistent Base package or any of the subclasses.  You should find quite a
few complete working examples there.

SEE ALSO
========

   See Persistent/Base, Persistent/DBM,
see Persistent/File,
Persistent/Memory, Persistent/DataType/Char,
see Persistent/DataType/DateTime,
see Persistent/DataType/Number,
see Persistent/DataType/String,
see Persistent/DataType/VarChar,

BUGS
====

   This software is definitely a work in progress.  Though, we've used it
on more than 10 real world applications.  So if you find any bugs please
email them to me with a subject of 'Persistent Bug' at:

     winters@bigsnow.org

   And you know, include the regular stuff, OS, Perl version, snippet of
code, etc.

ACKNOWLEDGMENTS
===============

   We got a lot of great ideas from the *Advanced Perl Programming* book
by Sriram Srinivasan, especially Chapters 10 and 11 on Persistence.  This
is an excellent book.  It covers many adavnced topics like object-oriented
Perl and persistence, extremely well.  In fact, even if you are not a Perl
programmer, but you want to learn about OO, I would recommend it.

   A special thanks to some of our first users that without their feedback
it would have taken a lot longer.

   Thanks!

John Geldner
Denise Skarupski
Weston Stander
Scott Stevelinck
David Vandegrift
AUTHORS
=======

     David Winters <winters@bigsnow.org>
     Greg Bossert  <bossert@suddensound.com>

   Greg and I came up with the initial idea of a reuseable storage class
and it kept evolving into what we have here today.  We've used it in many
applications and it has saved us much development time.  I hope you find
it as useful!

COPYRIGHT
=========

   Copyright (c) 1998-2000 David Winters.  All rights reserved. This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

An Abstract Persistent Base Class
*********************************

NAME
====

   Persistent::Base - An Abstract Persistent Base Class

SYNOPSIS
========

     ### we are a subclass of ... ###
     use Persistent::Base;
     @ISA = qw(Persistent::Base);

ABSTRACT
========

   This is an abstract class used by the Persistent framework of classes
to implement persistence with various types of data stores.  This class
provides the methods and interface for implementing Persistent classes.
Refer to the Persistent, documentation for a very
thorough introduction to using the Persistent framework of classes.

   This class is part of the Persistent base package which is available
from:

     http://www.bigsnow.org/persistent
     ftp://ftp.bigsnow.org/pub/persistent

DESCRIPTION
===========

   Before we get started describing the methods in detail, it should be
noted that all error handling in this class is done with exceptions.  So
you should wrap an eval block around all of your code.  Please see the
Persistent, documentation for more information on
exception handling in Perl.

ABSTRACT METHODS THAT NEED TO BE OVERRIDDEN IN THE SUBCLASS
===========================================================

datastore - Sets/Returns the Data Store Parameters
--------------------------------------------------

     eval {
       ### set the data store ###
       $person->datastore(@args);

     ### get the data store ###
     $href = $person->datastore();
       };
       croak "Exception caught: $@" if $@;

   Returns (and optionally sets) the data store of the object.  This
method throws Perl execeptions so use it with an eval block.

   Setting the data store can involve anything from initializing a
connection to opening a file.  Getting a data store usually means
returning information pertaining to the data store in a useful form, such
as a connection to a database or a location of a file.

   This method requires implementing.

   Parameters:

Varies by implementation.
   Returns:

Varies by implementation.
insert - Insert an Object into the Data Store
---------------------------------------------

     eval {
       $person->insert();
     };
     croak "Exception caught: $@" if $@;

   Inserts an object into the data store.  This method throws Perl
execeptions so use it with an eval block.

   This method requires implementing.

   Parameters:

None.
   Returns:

None.
   See the Persistent, documentation for more
information.

delete - Delete an Object from the Data Store
---------------------------------------------

     eval {
       $person->delete();
     };
     croak "Exception caught: $@" if $@;

   Deletes an object from the data store.  This method throws Perl
execeptions so use it with an eval block.

   This method requires implementing.

   Parameters:

*@id*
     Values of the Identity attributes of the object.  This argument is
     optional and will default to the Identifier values of the object as
     the default.

   Returns:

$flag
     A true value if the object previously existed in the data store (it
     was deleted), and a false value if not (nothing to delete).

   See the Persistent, documentation for more
information.

restore_where - Conditionally Restoring Objects
-----------------------------------------------

     use Persistent::File;

     eval {
       my $person = new Persistent::File('people.txt', '|');
       $person->restore_where(
         "lastname = 'Flintstone' and telnum =~ /^[(]?650/",
         "lastname, firstname, telnum DESC"
       );
       while ($person->restore_next()) {
         print "Restored: ";  print_person($person);
       }
     };
     croak "Exception caught: $@" if $@;

   Restores objects from the data store that meet the specified
conditions.  The objects are returned one at a time by using the
*restore_next* method and in a sorted order if specified.  This method
throws Perl execeptions so use it with an eval block.

   Since this is a Perl implemented Persistent class, the *restore_where*
method expects all patterm matching to use Perl regular expressions.

   This method requires implementing.

   Parameters:

$where
     Conditional expression for the requested objects.  The format of this
     expression is similar to a SQL WHERE clause.  This argument is
     optional.

$order_by
     Sort expression for the requested objects.  The format of this
     expression is similar to a SQL ORDER BY clause.  This argument is
     optional.

   Returns:

$num_of_objs
     The number of objects that match the conditions.

   See the Persistent, documentation for more
information.

SEE ALSO
========

   See Persistent, Persistent/Base,
Persistent/DBM, Persistent/File,
see Persistent/Memory,

BUGS
====

   This software is definitely a work in progress.  So if you find any
bugs please email them to me with a subject of 'Persistent Bug' at:

     winters@bigsnow.org

   And you know, include the regular stuff, OS, Perl version, snippet of
code, etc.

AUTHORS
=======

     David Winters <winters@bigsnow.org>

COPYRIGHT
=========

   Copyright (c) 1998-2000 David Winters.  All rights reserved. This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

A Persistent Class implemented using a DBM File
***********************************************

NAME
====

   Persistent::DBM - A Persistent Class implemented using a DBM File

SYNOPSIS
========

     use Persistent::DBM;
     use English;  # import readable variable names like $EVAL_ERROR

     eval {  ### in case an exception is thrown ###

     ### allocate a persistent object ###
     my $person = new Persistent::DBM('people.dbm');

     ### define attributes of the object ###
     $person->add_attribute('firstname', 'ID', 'VarChar', undef, 10);
     $person->add_attribute('lastname',  'ID', 'VarChar', undef, 20);
     $person->add_attribute('telnum', 'Persistent',
                            'VarChar', undef, 15);
     $person->add_attribute('bday', 'Persistent', 'DateTime', undef);
     $person->add_attribute('age', 'Transient', 'Number', undef, 2);

     ### query the datastore for some objects ###
     $person->restore_where(qq{
                               lastname = 'Flintstone' and
                               telnum =~ /^[(]?650/
                              });
     while ($person->restore_next()) {
       printf "name = %s, tel# = %s\n",
              $person->firstname . ' ' . $person->lastname,
              $person->telnum;
     }
       };

     if ($EVAL_ERROR) {  ### catch those exceptions! ###
       print "An error occurred: $EVAL_ERROR\n";
     }

ABSTRACT
========

   This is a Persistent class that uses DBM files to store and retrieve
objects.  This class can be instantiated directly or subclassed.  The
methods described below are unique to this class, and all other methods
that are provided by this class are documented in the Persistent,
documentation.  The Persistent,
documentation has a very thorough introduction to using the Persistent
framework of classes.

   This class is part of the Persistent base package which is available
from:

     http://www.bigsnow.org/persistent
     ftp://ftp.bigsnow.org/pub/persistent

DESCRIPTION
===========

   Before we get started describing the methods in detail, it should be
noted that all error handling in this class is done with exceptions.  So
you should wrap an eval block around all of your code.  Please see the
Persistent, documentation for more information on
exception handling in Perl.

METHODS
=======

new - Object Constructor
------------------------

     use Persistent::DBM;

     eval {
       my $obj = new Persistent::DBM($file, $field_delimiter, $type);
     };
     croak "Exception caught: $@" if $@;

   Allocates an object.  This method throws Perl execeptions so use it
with an eval block.

   Parameters:

These are the same as for the *datastore* method below.
datastore - Sets/Returns the Data Store Parameters
--------------------------------------------------

     eval {
       ### set the data store ###
       $obj->datastore($file, $field_delimiter, $type);

     ### get the data store ###
     $file = $obj->datastore();
       };
       croak "Exception caught: $@" if $@;

   Returns (and optionally sets) the data store of the object.  This
method throws Perl execeptions so use it with an eval block.

   Parameters:

$file
     File to use as the data store.

$field_delimiter
     Delimiter used to separate the attributes of the object in the data
     store.  This argument is optional and will be initialized to the value
     of the special Perl variable $; (or $SUBSCRIPT_SEPARATOR if you are
     using the English module) as a default or if set to undef.

$type
     Type of DBM file to use.  This is probably one of these: NDBM_File,
     DB_File, GDBM_File, SDBM_File, or ODBM_File.  This argument is
     optional and will default to AnyDBM_File.  See the AnyDBM_File
     documentation for more information.

   Returns:

$file
     File used as the data store.

insert - Insert an Object into the Data Store
---------------------------------------------

     eval {
       $obj->insert();
     };
     croak "Exception caught: $@" if $@;

   Inserts an object into the data store.  This method throws Perl
execeptions so use it with an eval block.

   Parameters:

None.
   Returns:

None.
   See the Persistent, documentation for more
information.

update - Update an Object in the Data Store
-------------------------------------------

     eval {
       $obj->update();
     };
     croak "Exception caught: $@" if $@;

   Updates an object in the data store.  This method throws Perl
execeptions so use it with an eval block.

   Parameters:

*@id*
     Values of the Identity attributes of the object.  This argument is
     optional and will default to the Identifier values of the object as
     the default.

     This argument is useful if you are updating the Identity attributes of
     the object and you already have all of the attribute values so you do
     not need to restore the object (like a CGI request with hidden fields,
     maybe).  So you can just set the Identity attributes of the object to
     the new values and then pass the old Identity values as arguments to
     the update method.  For example, if Pebbles Flintstone married Bam
     Bam Rubble, then you could update her last name like this:

          ### Pebbles already exists in the data store, but we don't ###
          ### want to do an extra restore because we already have    ###
          ### all of the attribute values ###

          $person->lastname('Rubble');
          $person->firstname('Pebbles');
          ### set the rest of the attributes ... ###

          $person->update('Flintstone', 'Pebbles');

     Or, if don't want to set all of the object's attributes, you can just
     restore it and then update it like this:

          ### restore object from data store ###
          if ($person->restore('Flintstone', 'Pebbles')) {
            $person->lastname('Rubble');
            $person->update();
          }

   Returns:

$flag
     A true value if the object previously existed in the data store (it
     was updated), and a false value if not (it was inserted).

   See the Persistent, documentation for more
information.

save - Save an Object to the Data Store
---------------------------------------

     eval {
       $person->save();
     };
     croak "Exception caught: $@" if $@;

   Saves an object to the data store.  The object is inserted if it does
not already exist in the data store, otherwise, it is updated.  This
method throws Perl execeptions so use it with an eval block.

   Parameters:

None.
   Returns:

$flag
     A true value if the object previously existed in the data store (it
     was updated), and a false value if not (it was inserted).

   See the Persistent, documentation for more
information.

delete - Delete an Object from the Data Store
---------------------------------------------

     eval {
       $obj->delete();
       ### or ###
       $obj->delete(@id);
     };
     croak "Exception caught: $@" if $@;

   Deletes an object from the data store.  This method throws Perl
execeptions so use it with an eval block.

   Parameters:

*@id*
     Values of the Identity attributes of the object.  This argument is
     optional and will default to the Identifier values of the object as
     the default.

   Returns:

$flag
     A true value if the object previously existed in the data store (it
     was deleted), and a false value if not (nothing to delete).

   See the Persistent, documentation for more
information.

restore - Restore an Object from the Data Store
-----------------------------------------------

     eval {
       $obj->restore(@id);
     };
     croak "Exception caught: $@" if $@;

   Restores an object from the data store.  This method throws Perl
execeptions so use it with an eval block.

   Parameters:

*@id*
     Values of the Identity attributes of the object.  This method throws
     Perl execeptions so use it with an eval block.

   Returns:

$flag
     A true value if the object previously existed in the data store (it
     was restored), and a false value if not (nothing to restore).

   See the Persistent, documentation for more
information.

restore_where - Conditionally Restoring Objects
-----------------------------------------------

     use Persistent::DBM;

     eval {
       my $person = new Persistent::DBM('people.dbm', '|', 'NDBM_File');
       $person->restore_where(
         "lastname = 'Flintstone' and telnum =~ /^[(]?650/",
         "lastname, firstname, telnum DESC"
       );
       while ($person->restore_next()) {
         print "Restored: ";  print_person($person);
       }
     };
     croak "Exception caught: $@" if $@;

   Restores objects from the data store that meet the specified
conditions.  The objects are returned one at a time by using the
*restore_next* method and in a sorted order if specified.  This method
throws Perl execeptions so use it with an eval block.

   Since this is a Perl based Persistent class, the *restore_where* method
expects the $where argument to use Perl expressions.

   Parameters:

$where
     Conditional expression for the requested objects.  The format of this
     expression is similar to a SQL WHERE clause.  This argument is
     optional.

$order_by
     Sort expression for the requested objects.  The format of this
     expression is similar to a SQL ORDER BY clause.  This argument is
     optional.

   Returns:

$num_of_objs
     The number of objects that match the conditions.

   See the Persistent, documentation for more
information.

SEE ALSO
========

   See Persistent, Persistent/Base,
Persistent/File, Persistent/Memory,

NOTES
=====

   You may notice some lock files (with a '.lock' extension) in the same
directory as your data files.  These are used to control access to the
data files.

BUGS
====

   This software is definitely a work in progress.  So if you find any
bugs please email them to me with a subject of 'Persistent Bug' at:

     winters@bigsnow.org

   And you know, include the regular stuff, OS, Perl version, snippet of
code, etc.

AUTHORS
=======

     David Winters <winters@bigsnow.org>

COPYRIGHT
=========

   Copyright (c) 1998-2000 David Winters.  All rights reserved. This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

An Abstract DataType Base Class
*******************************

NAME
====

   Persistent::DataType::Base - An Abstract DataType Base Class

SYNOPSIS
========

     ### we are a subclass of ... ###
     use Persistent::DataType::Base;
     @ISA = qw(Persistent::DataType::Base);

ABSTRACT
========

   This is an abstract base class used by the Persistent framework of
classes to implement the attributes of objects.  This class provides
methods for implementing data types.

   This class is not instantiated.  Instead, it is inherited from or
subclassed by DataType classes.

   This class is part of the Persistent base package which is available
from:

     http://www.bigsnow.org/persistent
     ftp://ftp.bigsnow.org/pub/persistent

DESCRIPTION
===========

   Before we get started describing the methods in detail, it should be
noted that all error handling in this class is done with exceptions.  So
you should wrap an eval block around all of your code.  Please see the
Persistent, documentation for more information on
exception handling in Perl.

METHODS
=======

debug - Accesses the Debugging Flag
-----------------------------------

     ### set the debugging flag ###
     $object->debug($flag);

     ### get the debugging flag ###
     $flag = $object->debug();

   Returns (and optionally sets) the debugging flag of an object.  This
method does not throw Perl execeptions.

   Parameters:

$flag
     If set to a true value then debugging is on, otherwise, a false value
     means off.

Constructor - Creates a DataType Object
---------------------------------------

     eval {
       my $datatype = new Persistent::DataType::Object(@args);
     };
     croak "Exception caught: $@" if $@;

   Initializes a data type object.  This method throws Perl execeptions so
use it with an eval block.

   This method is abstract and needs implementing.

value - Accesses the Value of the DataType
------------------------------------------

     eval {
       ### set the value ###
       $datatype->value($new_value);

     ### get the value ###
     $value = $datatype->value();
       };
       croak "Exception caught: $@" if $@;

   Returns (and optionally sets) the value of a DataType object.  This
method throws Perl execeptions so use it with an eval block.

   This method is abstract and needs implementing.

get_compare_op - Returns the Comparison Operator
------------------------------------------------

     $cmp_op = $obj->get_compare_op();

   Returns the comparison operator of a DataType object.  This method does
not throw Perl execeptions.

   This method is abstract and needs implementing.

   Can return a couple of different comparison operators:

'cmp'
     if the value of the object should be compared as a string.

'<=>'
     if the value of the object should be compared as a number.

SEE ALSO
========

   See Persistent, Persistent/DataType/Char,
see Persistent/DataType/DateTime,
see Persistent/DataType/Number,
see Persistent/DataType/String,
see Persistent/DataType/VarChar,

BUGS
====

   This software is definitely a work in progress.  So if you find any
bugs please email them to me with a subject of 'Persistent::DataType Bug'
at:

     winters@bigsnow.org

   And you know, include the regular stuff, OS, Perl version, snippet of
code, etc.

AUTHORS
=======

     David Winters <winters@bigsnow.org>

COPYRIGHT
=========

   Copyright (c) 1998-2000 David Winters.  All rights reserved. This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

A Fixed Length Character String Class
*************************************

NAME
====

   Persistent::DataType::Char - A Fixed Length Character String Class

SYNOPSIS
========

     use Persistent::DataType::Char;
     use English;

     eval {  ### in case an exception is thrown ###

     ### allocate a string ###
     my $string = new Persistent::DataType::Char($value,
                                                 $max_length);

     ### get/set value of string ###
     $value = $string->value($new_value);

     ### get length of string ###
     my $length = $string->length();

     ### get/set maximum length of string ###
     my $max = $string->max_length($new_max);

     ### returns 'eq' for strings ###
     my $cmp_op = $string->get_compare_op();
       };

     if ($EVAL_ERROR) {  ### catch those exceptions! ###
       print "An error occurred: $EVAL_ERROR\n";
     }

ABSTRACT
========

   This is a fixed length character string class used by the Persistent
framework of classes to implement the attributes of objects.  This class
provides methods for accessing the value, length, maximum length, and
comparison operator of a fixed length character string.  A fixed length
string (Char) always has a finite maximum length that can not be exceeded.
If the string is shorter than this maximum length, then the string is
padded with spaces on the trailing end.  This is different from a
character string (String) which can have an unlimited maximum length and a
variable length string (VarChar) which is not padded.

   This class is usually not invoked directly, at least not when used with
the Persistent framework of classes.  However, the constructor arguments
of this class are usually of interest when defining the attributes of a
Persistent object since the *add_attribute* method of the Persistent
classes instantiates this class directly.  Also, the arguments to the
value method are of interest when dealing with the accessor methods of the
Persistent classes since the accessor methods pass their arguments to the
value method and return the string value from the value method.

   This class is part of the Persistent base package which is available
from:

     http://www.bigsnow.org/persistent
     ftp://ftp.bigsnow.org/pub/persistent

DESCRIPTION
===========

   Before we get started describing the methods in detail, it should be
noted that all error handling in this class is done with exceptions.  So
you should wrap an eval block around all of your code.  Please see the
Persistent, documentation for more information on
exception handling in Perl.

METHODS
=======

Constructor - Creates the Char Object
-------------------------------------

     eval {
       my $string = new Persistent::DataType::Char($value,
                                                   $max_length);
     };
     croak "Exception caught: $@" if $@;

   Initializes a fixed length character string object.  This method throws
Perl execeptions so use it with an eval block.

   Parameters:

$value
     Actual value of the string.  This argument is optional and may be set
     to undef.

$max_length
     Maximum length of the string value.  This argument is optional and
     will be initialized to the length of the $value as a default or 1 if
     no $value argument is passed.

value - Accesses the Value of the String
----------------------------------------

     eval {
       ### set the value ###
       $string->value($value);

     ### get the value ###
     $value = $string->value();
       };
       croak "Exception caught: $@" if $@;

   Sets the value of the string and/or returns the value.  This method
throws Perl execeptions so use it with an eval block.

   Parameters:

$value
     Actual value of the string.  This argument is optional and may be set
     to undef.  The value returned will be padded with spaces if the length
     is less than the maximum length.

length - Returns the Length of the String
-----------------------------------------

     eval {
       $value = $string->length();
     };
     croak "Exception caught: $@" if $@;

   Returns the length of the string which is always the same as the
maximum length for a fixed length string.  This method throws Perl
execeptions so use it with an eval block.

   Parameters:

None
max_length - Accesses the Maximum Length of the String
------------------------------------------------------

     eval {
       ### set the maximum length ###
       $string->max_length($new_max);

     ### get the maximum length ###
     $max_length = $string->max_length();
       };
       croak "Exception caught: $@" if $@;

   Sets the maximum length of the string and/or returns it.  This method
throws Perl execeptions so use it with an eval block.

   Parameters:

$max_length
     Maximum length of the string value.  The maximum length must be
     greater than zero, otherwise, an exception is thrown.

SEE ALSO
========

   See Persistent, Persistent/DataType/DateTime,
see Persistent/DataType/Number,
see Persistent/DataType/String,
see Persistent/DataType/VarChar,

BUGS
====

   This software is definitely a work in progress.  So if you find any
bugs please email them to me with a subject of 'Persistent Bug' at:

     winters@bigsnow.org

   And you know, include the regular stuff, OS, Perl version, snippet of
code, etc.

AUTHORS
=======

     David Winters <winters@bigsnow.org>

COPYRIGHT
=========

   Copyright (c) 1998-2000 David Winters.  All rights reserved. This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

A Date and Time Class
*********************

NAME
====

   Persistent::DataType::DateTime - A Date and Time Class

SYNOPSIS
========

     use Persistent::DataType::DateTime;
     use English;

     eval {  ### in case an exception is thrown ###

     ### allocate a date ###
     my $date = new Persistent::DataType::DateTime(localtime);

     ### get/set value of date ###
     $value = $date->value($year, $month, $day,
     			  $hours, $minutes, $seconds);

     ### get/set year of the date ###
     $year = $date->year($new_year);

     ### get/set month of the date ###
     $month = $date->month($new_month);

     ### get/set day of the date ###
     $day = $date->day($new_day);

     ### get/set hours of the date ###
     $hours = $date->hours($new_hours);

     ### get/set minutes of the date ###
     $minutes = $date->minutes($new_minutes);

     ### get/set seconds of the date ###
     $seconds = $date->seconds($new_seconds);

     ### returns 'cmp' for dates ###
     my $cmp_op = $date->get_compare_op();
       };

     if ($EVAL_ERROR) {  ### catch those exceptions! ###
       print "An error occurred: $EVAL_ERROR\n";
     }

ABSTRACT
========

   This is a date and time class used by the Persistent framework of
classes to implement the attributes of objects.  This class provides
methods for accessing a date in a variety of formats.

   This class is usually not invoked directly, at least not when used with
the Persistent framework of classes.  However, the constructor arguments
of this class are usually of interest when defining the attributes of a
Persistent object since the *add_attribute* method of the Persistent
classes instantiates this class directly.  Also, the arguments to the
value method are of interest when dealing with the accessor methods of the
Persistent classes since the accessor methods pass their arguments to the
value method and return the string value from the value method.

   This class is part of the Persistent base package which is available
from:

     http://www.bigsnow.org/persistent
     ftp://ftp.bigsnow.org/pub/persistent

DESCRIPTION
===========

   Before we get started describing the methods in detail, it should be
noted that all error handling in this class is done with exceptions.  So
you should wrap an eval block around all of your code.  Please see the
Persistent, documentation for more information on
exception handling in Perl.

METHODS
=======

Constructor - Create a New DateTime Object
------------------------------------------

     use Persistent::DataType::DateTime;

     eval {
       $date = new Persistent::DataType::DateTime($datestring);
       $date = new Persistent::DataType::DateTime('now');
       $date = new Persistent::DataType::DateTime('');
       $date = new Persistent::DataType::DateTime(undef);
       $date = new Persistent::DataType::DateTime($year, $month, $day,
     					       $hour, $min, $sec);
       $date = new Persistent::DataType::DateTime(localtime);
     };
     croak "Exception caught: $@" if $@;

   Initializes a DateTime object.  This method throws Perl execeptions so
use it with an eval block.

   This constructor accepts several forms of arguments:

$datestring
     If the sole argument is a string, it is assumed to contain the date
     and time in the following format:

          YYYY-MM-DD hh:mm:ss
                   or
          YYYY/MM/DD hh:mm:ss

     This is also the format that is returned by the value method of this
     object.

     Another valid format to pass is the following:

          DD-Mon-YYYY

     where Mon is the three letter abbreviation for the month.  The case of
     the letters is not sensitive (i.e. jan or Jan or JAN is alright).

'now'
     If the sole argument is the word 'now', then the current date and time
     are used.

undef or *the empty string (")*
     If the sole argument is undef or the empty string ("), then the date
     and time are set to undef.

*$year, $month, $day, $hour, $min, $sec*
     If more than one argument is given (and less than 7), it is assumed
     that the date and time are being given as a series of integers in the
     above order where their formats are the following:

          $year = 0 .. 9999  ### 4 digit year ###
          $month = 1 .. 12
          $day = 1 .. 31
          $hours = 0 .. 23
          $minutes = 0 .. 59
          $seconds = 0 .. 59

*$sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst*
     If more than six arguments are passed, it is assumed that the date and
     time are being given as a series of integers in the above order, which
     happens to be the same order as the array that the Perl built-ins,
     localtime and gmtime, return.  See the *perlfunc* manpage for more
     information.

value - Accesses the Value of the Date
--------------------------------------

     eval {
       $date_string = $date->value($datestring);
       $date_string = $date->value('now');
       $date_string = $date->value('');
       $date_string = $date->value(undef);
       $date_string = $date->value($year, $month, $day,
     				$hour, $min, $sec);
       $date_string = $date->value(localtime);
     };
     croak "Exception caught: $@" if $@;

   Returns (and optionally sets) the value of the DateTime object.  This
method throws Perl execeptions so use it with an eval block.

   The arguments are as described above in `"Constructor -- Create a New
DateTime Object"' in this node.

get_compare_op - Returns the Comparison Operator for DateTime
-------------------------------------------------------------

     $cmp_op = $date->get_compare_op();

   Returns the comparison operator for the DateTime class which is 'cmp'.
This method does not throw execeptions.

   Parameters:

None
year - Accesses the Year of the Date
------------------------------------

     eval {
       ### set the year ###
       $date->year($new_year);

     ### get the year ###
     $year = $date->year();
       };
       croak "Exception caught: $@" if $@;

   Returns (and optionally sets) the year of the DateTime object.  This
method throws Perl execeptions so use it with an eval block.

   Parameters:

$year
     A 4-digit year.  The year must be >= 0 and <= 9999.  If it is undef
     then the year will be set to undef.

month - Accesses the Month of the Date
--------------------------------------

     eval {
       ### set the month ###
       $date->month($new_month);

     ### get the month ###
     $month = $date->month();
       };
       croak "Exception caught: $@" if $@;

   Returns (and optionally sets) the month of the DateTime object.  This
method throws Perl execeptions so use it with an eval block.

   Parameters:

$month
     The month must be >= 1 and <= 12.  If it is undef then the month will
     be set to undef.

day - Accesses the Day of the Date
----------------------------------

     eval {
       ### set the day ###
       $date->day($new_day);

     ### get the day ###
     $day = $date->day();
       };
       croak "Exception caught: $@" if $@;

   Returns (and optionally sets) the day of the DateTime object.  This
method throws Perl execeptions so use it with an eval block.

   Parameters:

$day
     The day must be >= 1 and <= 31.  If it is undef then the day will be
     set to undef.

hours - Accesses the Hours of the Date
--------------------------------------

     eval {
       ### set the hours ###
       $date->hours($new_hours);

     ### get the hours ###
     $hours = $date->hours();
       };
       croak "Exception caught: $@" if $@;

   Returns (and optionally sets) the hours of the DateTime object.  This
method throws Perl execeptions so use it with an eval block.

   Parameters:

$hours
     The hours must be >= 0 and <= 23.  If it is undef then the hours will
     be set to undef.

minutes - Accesses the Minutes of the Date
------------------------------------------

     eval {
       ### set the minutes ###
       $date->minutes($new_minutes);

     ### get the minutes ###
     $minutes = $date->minutes();
       };
       croak "Exception caught: $@" if $@;

   Returns (and optionally sets) the minutes of the DateTime object.  This
method throws Perl execeptions so use it with an eval block.

   Parameters:

$minutes
     The minutes must be >= 1 and <= 59.  If it is undef then the minutes
     will be set to undef.

seconds - Accesses the Seconds of the Date
------------------------------------------

     eval {
       ### set the seconds ###
       $date->seconds($new_seconds);

     ### get the seconds ###
     $seconds = $date->seconds();
       };
       croak "Exception caught: $@" if $@;

   Returns (and optionally sets) the seconds of the DateTime object.  This
method throws Perl execeptions so use it with an eval block.

   Parameters:

$seconds
     The seconds must be >= 0 and <= 59.  If it is undef then the seconds
     will be set to undef.

SEE ALSO
========

   See Persistent, Persistent/DataType/Char,
see Persistent/DataType/Number,
see Persistent/DataType/String,
see Persistent/DataType/VarChar,

BUGS
====

   This software is definitely a work in progress.  So if you find any
bugs please email them to me with a subject of 'Persistent Bug' at:

     winters@bigsnow.org

   And you know, include the regular stuff, OS, Perl version, snippet of
code, etc.

AUTHORS
=======

     David Winters <winters@bigsnow.org>

COPYRIGHT
=========

   Copyright (c) 1998-2000 David Winters.  All rights reserved. This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

A Floating Point and Integer Class
**********************************

NAME
====

   Persistent::DataType::Number - A Floating Point and Integer Class

SYNOPSIS
========

     use Persistent::DataType::Number;
     use English;

     eval {  ### in case an exception is thrown ###

     ### allocate a number ###
     my $number = new Persistent::DataType::Number($value,
                                                   $precision,
     						  $scale);

     ### get/set value of number ###
     $value = $number->value($new_value);

     ### get/set precision of the number ###
     $precision = $number->precision($new_precision);

     ### get/set scale of number ###
     $scale = $number->scale($new_scale);

     ### returns '<=>' for numbers ###
     my $cmp_op = $number->get_compare_op();
       };

     if ($EVAL_ERROR) {  ### catch those exceptions! ###
       print "An error occurred: $EVAL_ERROR\n";
     }

ABSTRACT
========

   This is a floating point and integer class used by the Persistent
framework of classes to implement the attributes of objects.  This class
provides methods for accessing the value, precision, scale, and comparison
operator of a number.

   This class is usually not invoked directly, at least not when used with
the Persistent framework of classes.  However, the constructor arguments
of this class are usually of interest when defining the attributes of a
Persistent object since the *add_attribute* method of the Persistent
classes instantiates this class directly.  Also, the arguments to the
value method are of interest when dealing with the accessor methods of the
Persistent classes since the accessor methods pass their arguments to the
value method and return the string value from the value method.

   This class is part of the Persistent base package which is available
from:

     http://www.bigsnow.org/persistent
     ftp://ftp.bigsnow.org/pub/persistent

DESCRIPTION
===========

   Before we get started describing the methods in detail, it should be
noted that all error handling in this class is done with exceptions.  So
you should wrap an eval block around all of your code.  Please see the
Persistent, documentation for more information on
exception handling in Perl.

METHODS
=======

Constructor - Creates the Number Object
---------------------------------------

     eval {
       my $number = new Persistent::DataType::Number($value,
                                                     $precision,
                                                     $scale);
     };
     croak "Exception caught: $@" if $@;

   Initializes a number object.  This method throws Perl execeptions so
use it with an eval block.

   Parameters:

$value
     Actual value of the number; this may be a floating point or integer.
     This argument is optional and may be set to undef.

$precision
     The number of digits in the number not including the decimal point or
     the sign.  This argument is optional and will be initialized to the
     precision of the $value argument as a default.

$scale
     The number of digits after the decimal point.  This argument is
     optional and will be initialized to the scale of the $value argument
     as a default.

value - Accesses the Value of the Number
----------------------------------------

     eval {
       ### set the value ###
       $number->value($value);

     ### get the value ###
     $value = $number->value();
       };
       croak "Exception caught: $@" if $@;

   Sets the value of the number and/or returns the value.  This method
throws Perl execeptions so use it with an eval block.

   Parameters:

$value
     Actual value of the number; this may be a floating point or integer.
     This argument is optional and may be set to undef.

get_compare_op - Returns the Comparison Operator
------------------------------------------------

     $cmp_op = $number->get_compare_op();

   Returns the comparison operator for the Number class which is '<=>'.
This method does not throw execeptions.

   Parameters:

None
precision - Accesses the Precision of the Number
------------------------------------------------

     eval {
       ### set the precision ###
       $number->precision($new_precision);

     ### get the precision ###
     $precision = $number->precision();
       };
       croak "Exception caught: $@" if $@;

   Sets the precision of the number and/or returns it.  This method throws
Perl execeptions so use it with an eval block.

   Parameters:

$precision
     The number of digits in the number not including the decimal point or
     the sign.  The precision must be >= 0.  If it is undef or the empty
     string ("), then it is set to 0.

scale - Accesses the Scale of the Number
----------------------------------------

     eval {
       ### set the scale ###
       $number->scale($new_scale);

     ### get the scale ###
     $scale = $number->scale();
       };
       croak "Exception caught: $@" if $@;

   Sets the scale of the number and/or returns it.  This method throws
Perl execeptions so use it with an eval block.

   Parameters:

$scale
     The number of digits after the decimal point.  The scale must be >= 0.
     If it is undef or the empty string ("), then it is set to 0.

SEE ALSO
========

   See Persistent, Persistent/DataType/Char,
see Persistent/DataType/DateTime,
see Persistent/DataType/String,
see Persistent/DataType/VarChar,

BUGS
====

   This software is definitely a work in progress.  So if you find any
bugs please email them to me with a subject of 'Persistent Bug' at:

     winters@bigsnow.org

   And you know, include the regular stuff, OS, Perl version, snippet of
code, etc.

AUTHORS
=======

     David Winters <winters@bigsnow.org>

COPYRIGHT
=========

   Copyright (c) 1998-2000 David Winters.  All rights reserved. This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

A Character String Class
************************

NAME
====

   Persistent::DataType::String - A Character String Class

SYNOPSIS
========

     use Persistent::DataType::String;
     use English;

     eval {  ### in case an exception is thrown ###

     ### allocate a string ###
     my $string = new Persistent::DataType::String($value,
                                                   $max_length);

     ### get/set value of string ###
     $value = $string->value($new_value);

     ### get length of string ###
     my $length = $string->length();

     ### get/set maximum length of string ###
     my $max = $string->max_length($new_max);

     ### returns 'eq' for strings ###
     my $cmp_op = $string->get_compare_op();
       };

     if ($EVAL_ERROR) {  ### catch those exceptions! ###
       print "An error occurred: $EVAL_ERROR\n";
     }

ABSTRACT
========

   This is a character string class used by the Persistent framework of
classes to implement the attributes of objects.  This class provides
methods for accessing the value, length, maximum length, and comparison
operator of a character string.

   This class is usually not invoked directly, at least not when used with
the Persistent framework of classes.  However, the constructor arguments
of this class are usually of interest when defining the attributes of a
Persistent object since the *add_attribute* method of the Persistent
classes instantiates this class directly.  Also, the arguments to the
value method are of interest when dealing with the accessor methods of the
Persistent classes since the accessor methods pass their arguments to the
value method and return the string value from the value method.

   This class is part of the Persistent base package which is available
from:

     http://www.bigsnow.org/persistent
     ftp://ftp.bigsnow.org/pub/persistent

DESCRIPTION
===========

   Before we get started describing the methods in detail, it should be
noted that all error handling in this class is done with exceptions.  So
you should wrap an eval block around all of your code.  Please see the
Persistent, documentation for more information on
exception handling in Perl.

METHODS
=======

Constructor - Creates the String Object
---------------------------------------

     eval {
       my $string = new Persistent::DataType::String($value,
                                                     $max_length);
     };
     croak "Exception caught: $@" if $@;

   Initializes a character string object.  This method throws Perl
execeptions so use it with an eval block.

   Parameters:

$value
     Actual value of the string.  This argument is optional and may be set
     to undef.

$max_length
     Maximum length of the string value.  This argument is optional and
     will be initialized to an unlimitied length (0) as a default.

value - Accesses the Value of the String
----------------------------------------

     eval {
       ### set the value ###
       $string->value($value);

     ### get the value ###
     $value = $string->value();
       };
       croak "Exception caught: $@" if $@;

   Sets the value of the string and/or returns the value.  This method
throws Perl execeptions so use it with an eval block.

   Parameters:

$value
     Actual value of the string.  This argument is optional and may be set
     to undef.

get_compare_op - Returns the Comparison Operator
------------------------------------------------

     $cmp_op = $string->get_compare_op();

   Returns the comparison operator for the String class which is 'cmp'.
This method does not throw execeptions.

   Parameters:

None
length - Returns the Length of the String
-----------------------------------------

     eval {
       $value = $string->length();
     };
     croak "Exception caught: $@" if $@;

   Returns the length of the string.  This method throws Perl execeptions
so use it with an eval block.

   Parameters:

None
max_length - Accesses the Maximum Length of the String
------------------------------------------------------

     eval {
       ### set the maximum length ###
       $string->max_length($new_max);

     ### get the maximum length ###
     $max_length = $string->max_length();
       };
       croak "Exception caught: $@" if $@;

   Sets the maximum length of the string and/or returns it.  This method
throws Perl execeptions so use it with an eval block.

   Parameters:

$max_length
     Maximum length of the string value.  If the maximum length is set to
     undef, the empty string ("), or 0, then the string has an unlimited
     maximum length.

SEE ALSO
========

   See Persistent, Persistent/DataType/Char,
see Persistent/DataType/DateTime,
see Persistent/DataType/Number,
see Persistent/DataType/VarChar,

BUGS
====

   This software is definitely a work in progress.  So if you find any
bugs please email them to me with a subject of 'Persistent Bug' at:

     winters@bigsnow.org

   And you know, include the regular stuff, OS, Perl version, snippet of
code, etc.

AUTHORS
=======

     David Winters <winters@bigsnow.org>

COPYRIGHT
=========

   Copyright (c) 1998-2000 David Winters.  All rights reserved. This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

A Variable Length Character String Class
****************************************

NAME
====

   Persistent::DataType::VarChar - A Variable Length Character String Class

SYNOPSIS
========

     use Persistent::DataType::VarChar;
     use English;

     eval {  ### in case an exception is thrown ###

     ### allocate a string ###
     my $string = new Persistent::DataType::VarChar($value,
                                                    $max_length);

     ### get/set value of string ###
     $value = $string->value($new_value);

     ### get length of string ###
     my $length = $string->length();

     ### get/set maximum length of string ###
     my $max = $string->max_length($new_max);

     ### returns 'eq' for strings ###
     my $cmp_op = $string->get_compare_op();
       };

     if ($EVAL_ERROR) {  ### catch those exceptions! ###
       print "An error occurred: $EVAL_ERROR\n";
     }

ABSTRACT
========

   This is a variable length character string class used by the Persistent
framework of classes to implement the attributes of objects.  This class
provides methods for accessing the value, length, maximum length, and
comparison operator of a variable length character string.  A variable
length string (VarChar) always has a finite maximum length that can not be
exceeded.  This is different from a character string (String) which can
have an unlimited maximum length.

   This class is usually not invoked directly, at least not when used with
the Persistent framework of classes.  However, the constructor arguments
of this class are usually of interest when defining the attributes of a
Persistent object since the *add_attribute* method of the Persistent
classes instantiates this class directly.  Also, the arguments to the
value method are of interest when dealing with the accessor methods of the
Persistent classes since the accessor methods pass their arguments to the
value method and return the string value from the value method.

   This class is part of the Persistent base package which is available
from:

     http://www.bigsnow.org/persistent
     ftp://ftp.bigsnow.org/pub/persistent

DESCRIPTION
===========

   Before we get started describing the methods in detail, it should be
noted that all error handling in this class is done with exceptions.  So
you should wrap an eval block around all of your code.  Please see the
Persistent, documentation for more information on
exception handling in Perl.

METHODS
=======

Constructor - Creates the VarChar Object
----------------------------------------

     eval {
       my $string = new Persistent::DataType::VarChar($value,
                                                      $max_length);
     };
     croak "Exception caught: $@" if $@;

   Initializes a variable length character string object.  This method
throws Perl execeptions so use it with an eval block.

   Parameters:

$value
     Actual value of the string.  This argument is optional and may be set
     to undef.

$max_length
     Maximum length of the string value.  This argument is optional and
     will be initialized to the length of the $value as a default or 1 if
     no $value argument is passed.

max_length - Accesses the Maximum Length of the String
------------------------------------------------------

     eval {
       ### set the maximum length ###
       $string->max_length($new_max);

     ### get the maximum length ###
     $max_length = $string->max_length();
       };
       croak "Exception caught: $@" if $@;

   Sets the maximum length of the string and/or returns it.  This method
throws Perl execeptions so use it with an eval block.

   Parameters:

$max_length
     Maximum length of the string value.  The maximum length must be
     greater than zero, otherwise, an exception is thrown.

SEE ALSO
========

   See Persistent, Persistent/DataType/Char,
see Persistent/DataType/DateTime,
see Persistent/DataType/Number,
see Persistent/DataType/String,

BUGS
====

   This software is definitely a work in progress.  So if you find any
bugs please email them to me with a subject of 'Persistent Bug' at:

     winters@bigsnow.org

   And you know, include the regular stuff, OS, Perl version, snippet of
code, etc.

AUTHORS
=======

     David Winters <winters@bigsnow.org>

COPYRIGHT
=========

   Copyright (c) 1998-2000 David Winters.  All rights reserved. This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

A Persistent Class implemented using a Text File
************************************************

NAME
====

   Persistent::File - A Persistent Class implemented using a Text File

SYNOPSIS
========

     use Persistent::File;
     use English;  # import readable variable names like $EVAL_ERROR

     eval {  ### in case an exception is thrown ###

     ### allocate a persistent object ###
     my $person = new Persistent::File('people.txt');

     ### define attributes of the object ###
     $person->add_attribute('firstname', 'ID', 'VarChar', undef, 10);
     $person->add_attribute('lastname',  'ID', 'VarChar', undef, 20);
     $person->add_attribute('telnum', 'Persistent',
                            'VarChar', undef, 15);
     $person->add_attribute('bday', 'Persistent', 'DateTime', undef);
     $person->add_attribute('age', 'Transient', 'Number', undef, 2);

     ### query the datastore for some objects ###
     $person->restore_where(qq{
                               lastname = 'Flintstone' and
                               telnum =~ /^[(]?650/
                              });
     while ($person->restore_next()) {
       printf "name = %s, tel# = %s\n",
              $person->firstname . ' ' . $person->lastname,
              $person->telnum;
     }
       };

     if ($EVAL_ERROR) {  ### catch those exceptions! ###
       print "An error occurred: $EVAL_ERROR\n";
     }

ABSTRACT
========

   This is a Persistent class that uses text files to store and retrieve
objects.  This class can be instantiated directly or subclassed.  The
methods described below are unique to this class, and all other methods
that are provided by this class are documented in the Persistent,
documentation.  The Persistent,
documentation has a very thorough introduction to using the Persistent
framework of classes.

   This class is part of the Persistent base package which is available
from:

     http://www.bigsnow.org/persistent
     ftp://ftp.bigsnow.org/pub/persistent

DESCRIPTION
===========

   Before we get started describing the methods in detail, it should be
noted that all error handling in this class is done with exceptions.  So
you should wrap an eval block around all of your code.  Please see the
Persistent, documentation for more information on
exception handling in Perl.

METHODS
=======

new - Object Constructor
------------------------

     use Persistent::File;

     eval {
       my $person = new Persistent::File($file, $field_delimiter);
     };
     croak "Exception caught: $@" if $@;

   Allocates an object.  This method throws Perl execeptions so use it
with an eval block.

   Parameters:

These are the same as for the *datastore* method below.
datastore - Sets/Returns the Data Store Parameters
--------------------------------------------------

     eval {
       ### set the data store ###
       $person->datastore($file, $field_delimiter);

     ### get the data store ###
     $file = $person->datastore();
       };
       croak "Exception caught: $@" if $@;

   Returns (and optionally sets) the data store of the object.  This
method throws Perl execeptions so use it with an eval block.

   Parameters:

$file
     File to use as the data store.

$field_delimiter
     Delimiter used to separate the attributes of the object in the data
     store.  This argument is optional and will be initialized to the value
     of the special Perl variable $; (or $SUBSCRIPT_SEPARATOR if you are
     using the English module) as a default.

   Returns:

$file
     File used as the data store.

insert - Insert an Object into the Data Store
---------------------------------------------

     eval {
       $person->insert();
     };
     croak "Exception caught: $@" if $@;

   Inserts an object into the data store.  This method throws Perl
execeptions so use it with an eval block.

   Parameters:

None.
   Returns:

None.
   See the Persistent, documentation for more
information.

update - Update an Object in the Data Store
-------------------------------------------

     eval {
       $person->update();
     };
     croak "Exception caught: $@" if $@;

   Updates an object in the data store.  This method throws Perl
execeptions so use it with an eval block.

   Parameters:

*@id*
     Values of the Identity attributes of the object.  This argument is
     optional and will default to the Identifier values of the object as
     the default.

     This argument is useful if you are updating the Identity attributes of
     the object and you already have all of the attribute values so you do
     not need to restore the object (like a CGI request with hidden fields,
     maybe).  So you can just set the Identity attributes of the object to
     the new values and then pass the old Identity values as arguments to
     the update method.  For example, if Pebbles Flintstone married Bam
     Bam Rubble, then you could update her last name like this:

          ### Pebbles already exists in the data store, but we don't ###
          ### want to do an extra restore because we already have    ###
          ### all of the attribute values ###

          $person->lastname('Rubble');
          $person->firstname('Pebbles');
          ### set the rest of the attributes ... ###

          $person->update('Flintstone', 'Pebbles');

     Or, if don't want to set all of the object's attributes, you can just
     restore it and then update it like this:

          ### restore object from data store ###
          if ($person->restore('Flintstone', 'Pebbles')) {
            $person->lastname('Rubble');
            $person->update();
          }

   Returns:

$flag
     A true value if the object previously existed in the data store (it
     was updated), and a false value if not (it was inserted).

   See the Persistent, documentation for more
information.

save - Save an Object to the Data Store
---------------------------------------

     eval {
       $person->save();
     };
     croak "Exception caught: $@" if $@;

   Saves an object to the data store.  The object is inserted if it does
not already exist in the data store, otherwise, it is updated.  This
method throws Perl execeptions so use it with an eval block.

   Parameters:

None.
   Returns:

$flag
     A true value if the object previously existed in the data store (it
     was updated), and a false value if not (it was inserted).

   See the Persistent, documentation for more
information.

delete - Delete an Object from the Data Store
---------------------------------------------

     eval {
       $person->delete();
     };
     croak "Exception caught: $@" if $@;

   Deletes an object from the data store.  This method throws Perl
execeptions so use it with an eval block.

   Parameters:

*@id*
     Values of the Identity attributes of the object.  This argument is
     optional and will default to the Identifier values of the object as
     the default.

   Returns:

$flag
     A true value if the object previously existed in the data store (it
     was deleted), and a false value if not (nothing to delete).

   See the Persistent, documentation for more
information.

restore - Restore an Object from the Data Store
-----------------------------------------------

     eval {
       $person->restore(@id);
     };
     croak "Exception caught: $@" if $@;

   Restores an object from the data store.  This method throws Perl
execeptions so use it with an eval block.

   Parameters:

*@id*
     Values of the Identity attributes of the object.  This method throws
     Perl execeptions so use it with an eval block.

   Returns:

$flag
     A true value if the object previously existed in the data store (it
     was restored), and a false value if not (nothing to restore).

   See the Persistent, documentation for more
information.

restore_where - Conditionally Restoring Objects
-----------------------------------------------

     use Persistent::File;

     eval {
       my $person = new Persistent::File('people.txt', '|');
       $person->restore_where(
         "lastname = 'Flintstone' and telnum =~ /^[(]?650/",
         "lastname, firstname, telnum DESC"
       );
       while ($person->restore_next()) {
         print "Restored: ";  print_person($person);
       }
     };
     croak "Exception caught: $@" if $@;

   Restores objects from the data store that meet the specified
conditions.  The objects are returned one at a time by using the
*restore_next* method and in a sorted order if specified.  This method
throws Perl execeptions so use it with an eval block.

   Since this is a Perl based Persistent class, the *restore_where* method
expects the $where argument to use Perl expressions.

   Parameters:

$where
     Conditional expression for the requested objects.  The format of this
     expression is similar to a SQL WHERE clause.  This argument is
     optional.

$order_by
     Sort expression for the requested objects.  The format of this
     expression is similar to a SQL ORDER BY clause.  This argument is
     optional.

   Returns:

$num_of_objs
     The number of objects that match the conditions.

   See the Persistent, documentation for more
information.

SEE ALSO
========

   See Persistent, Persistent/Base,
Persistent/DBM, Persistent/Memory,

NOTES
=====

   You may notice some lock files (with a '.lock' extension) in the same
directory as your data files.  These are used to control access to the
data files.

BUGS
====

   This software is definitely a work in progress.  So if you find any
bugs please email them to me with a subject of 'Persistent Bug' at:

     winters@bigsnow.org

   And you know, include the regular stuff, OS, Perl version, snippet of
code, etc.

AUTHORS
=======

     David Winters <winters@bigsnow.org>

COPYRIGHT
=========

   Copyright (c) 1998-2000 David Winters.  All rights reserved. This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

A Persistent Class implemented using a LDAP Directory
*****************************************************

NAME
====

   Persistent::LDAP - A Persistent Class implemented using a LDAP Directory

SYNOPSIS
========

     use Persistent::LDAP;
     use English;  # import readable variable names like $EVAL_ERROR

     eval {  ### in case an exception is thrown ###

     ### allocate a persistent object ###
     my $person =
       new Persistent::LDAP('localhost', 389,
     			   'cn=Directory Manager', 'test1234',
     			   'ou=Engineering,o=Big Snow Org,c=US');

     ### declare attributes of the object ###
     $person->add_attribute('uid',             'ID',         'String');
     $person->add_attribute('userpassword',    'Persistent', 'String');
     $person->add_attribute('objectclass',     'Persistent', 'String');
     $person->add_attribute('givenname',       'Persistent', 'String');
     $person->add_attribute('sn',              'Persistent', 'String');
     $person->add_attribute('cn',              'Persistent', 'String');
     $person->add_attribute('mail',            'Persistent', 'String');
     $person->add_attribute('telephonenumber', 'Persistent', 'String');

     ### query the datastore for some objects ###
     $person->restore_where('& (objectclass=person)(mail=*bigsnow.org)',
     			   'sn, givenname');
     while ($person->restore_next()) {
       printf("name = %s, email = %s\n",
              $person->givenname . ' ' . $person->sn,
              $person->mail);
     }
       };

     if ($EVAL_ERROR) {  ### catch those exceptions! ###
       print "An error occurred: $EVAL_ERROR\n";
     }

ABSTRACT
========

   This is a Persistent class that uses a LDAP directory to store and
retrieve objects.  This class can be instantiated directly or subclassed.
The methods described below are unique to this class, and all other
methods that are provided by this class are documented in the
Persistent, documentation.  The Persistent,
documentation has a very thorough introduction to using the Persistent
framework of classes.

   This class is part of the Persistent LDAP package which is available
from:

     http://www.bigsnow.org/persistent
     ftp://ftp.bigsnow.org/pub/persistent

DESCRIPTION
===========

   Before we get started describing the methods in detail, it should be
noted that all error handling in this class is done with exceptions.  So
you should wrap an eval block around all of your code.  Please see the
Persistent, documentation for more information on
exception handling in Perl.

METHODS
=======

new - Object Constructor
------------------------

     use Persistent::LDAP;

     eval {
       my $obj = new Persistent::LDAP($host, $port,
     				   $bind_dn, $password,
     				   $base_dn);
     };
     croak "Exception caught: $@" if $@;

   Allocates an object.  This method throws Perl execeptions so use it
with an eval block.

   Parameters:

These are the same as for the *datastore* method below.
datastore - Sets/Returns the Data Store Parameters
--------------------------------------------------

     eval {
       ### set the data store ###
       $ldap = $obj->datastore($host, $port, $bind_dn, $password,
                               $base_dn);
       ### or set it like this ###
       $ldap = $obj->datastore($ldap, $base_dn);

     ### get the data store ###
     $ldap = $obj->datastore();
       };
       croak "Exception caught: $@" if $@;

   Returns (and optionally sets) the data store of the object.  This
method throws Perl execeptions so use it with an eval block.

   Parameters:

$host
     Hostname or IP address of the remote (LDAP Directory) server

$port
     Port to connect to on the remote server

$bind_dn
     Bind to the LDAP directory with the given DN

$password
     Password for the bind DN

$base_dn
     The base DN to start all searches/updates

$ldap (also a return value)
     Connection to the LDAP directory

insert - Insert an Object into the Data Store
---------------------------------------------

     eval {
       $obj->insert();
     };
     croak "Exception caught: $@" if $@;

   Inserts an object into the data store.  This method throws Perl
execeptions so use it with an eval block.

   Parameters:

None.
   Returns:

None.
   See the Persistent, documentation for more
information.

update - Update an Object in the Data Store
-------------------------------------------

     eval {
       $obj->update();
     };
     croak "Exception caught: $@" if $@;

   Updates an object in the data store.  This method throws Perl
execeptions so use it with an eval block.

   Parameters:

*@id*
     Values of the Identity attributes of the object.  This argument is
     optional and will default to the Identifier values of the object as
     the default.

     This argument is useful if you are updating the Identity attributes of
     the object and you already have all of the attribute values so you do
     not need to restore the object (like a CGI request with hidden fields,
     maybe).  So you can just set the Identity attributes of the object to
     the new values and then pass the old Identity values as arguments to
     the update method.  For example, if Pebbles Flintstone married Bam
     Bam Rubble, then you could update her last name like this:

          ### Pebbles already exists in the data store, but we don't ###
          ### want to do an extra restore because we already have    ###
          ### all of the attribute values ###

          $person->uid('pflintstone');      ### new value of ID attribute ###
          $person->sn('Rubble');            ### new lastname ###
          $person->commonname('Pebbles');   ### old firstname ###
          ### set the rest of the attributes ... ###

          $person->update('prubble');   ### old value of ID attribute ###

     Or, if don't want to set all of the object's attributes, you can just
     restore it and then update it like this:

          ### restore object from data store ###
          if ($person->restore('pflintstone')) {
            $person->uid('prubble');
            $person->sn('Rubble');
            $person->update();
          }

   Returns:

$flag
     A true value if the object previously existed in the data store (it
     was updated), and a false value if not (it was inserted).

   See the Persistent, documentation for more
information.

save - Save an Object to the Data Store
---------------------------------------

     eval {
       $person->save();
     };
     croak "Exception caught: $@" if $@;

   Saves an object to the data store.  The object is inserted if it does
not already exist in the data store, otherwise, it is updated.  This
method throws Perl execeptions so use it with an eval block.

   Parameters:

None.
   Returns:

$flag
     A true value if the object previously existed in the data store (it
     was updated), and a false value if not (it was inserted).

   See the Persistent, documentation for more
information.

delete - Delete an Object from the Data Store
---------------------------------------------

     eval {
       $obj->delete();
       ### or ###
       $obj->delete(@id);
     };
     croak "Exception caught: $@" if $@;

   Deletes an object from the data store.  This method throws Perl
execeptions so use it with an eval block.

   Parameters:

*@id*
     Values of the Identity attributes of the object.  This argument is
     optional and will default to the Identifier values of the object as
     the default.

   Returns:

$flag
     A true value if the object previously existed in the data store (it
     was deleted), and a false value if not (nothing to delete).

   See the Persistent, documentation for more
information.

restore - Restore an Object from the Data Store
-----------------------------------------------

     eval {
       $obj->restore(@id);
     };
     croak "Exception caught: $@" if $@;

   Restores an object from the data store.  This method throws Perl
execeptions so use it with an eval block.

   Parameters:

*@id*
     Values of the Identity attributes of the object.  This method throws
     Perl execeptions so use it with an eval block.

   Returns:

$flag
     A true value if the object previously existed in the data store (it
     was restored), and a false value if not (nothing to restore).

   See the Persistent, documentation for more
information.

restore_where - Conditionally Restoring Objects
-----------------------------------------------

     use Persistent::LDAP;

     eval {
       ### allocate a persistent object ###
       my $person =
         new Persistent::LDAP('localhost', 389,
     			   'cn=Directory Manager', 'test1234',
     			   'ou=Engineering,o=Big Snow Org,c=US');

     ### query the datastore for some objects ###
     $person->restore_where('& (objectclass=person)(mail=*bigsnow.org)',
     			   'sn, givenname');
     while ($person->restore_next()) {
       printf("name = %s, email = %s\n",
              $person->givenname . ' ' . $person->sn,
              $person->mail);
     }
       };
       croak "Exception caught: $@" if $@;

   Restores objects from the data store that meet the specified
conditions.  The objects are returned one at a time by using the
*restore_next* method and in a sorted order if specified.  This method
throws Perl execeptions so use it with an eval block.

   Since this is a LDAP implemented Persistent class, the *restore_where*
method expects a RFC-2254 compliant LDAP search filter as the first
argument, $where.  Please see the `Net::LDAP::Filter' documentation or
RFC-2254 for more information.  A good starting point for finding RFCs on
the web is the following:

     http://www.yahoo.com/Computers_and_Internet/Standards/RFCs/

   The second argument, $order_by, should be a valid SQL ORDER BY clause.
Which is just a comma separated list of attribute values to sort by with
an optional ASC or DESC token to sort in ascending or descending order.
Please refer to a SQL reference for a more detailed explanation of ORDER
BY clauses.

   Since LDAP directories allow multiple values for an attribute, when an
attribute with multiple values is used to sort by (used in an ORDER BY
clause), only the first value of the attribute is used for sorting.  For
more information on attributes with multiple values, please see the
following section in this document on using accessor methods.

   Parameters:

$where
     Conditional expression for the requested objects.  This is a RFC-2254
     compliant LDAP search filter.  This argument is optional.

$order_by
     Sort expression for the requested objects.  The format of this
     expression is similar to a SQL ORDER BY clause.  This argument is
     optional.

   Returns:

$num_of_objs
     The number of objects that match the conditions.

   See the Persistent, documentation for more
information.

Accessor Methods - Accessing the Attributes of an Object
--------------------------------------------------------

     eval {
       ### getting attribute values ###
       my $mail = $person->mail();            ### a single value ###
       my @classes = $person->objectclass();  ### multiple values ###

     ### setting attribute values ###
     $person->mail($newmail);               ### a single value ###
     my @new_classes = ('top', 'person', 'organizationalPerson');
     $person->objectclass(@new_classes);    ### multiple values ###
     $person->objectclass(\@new_classes);   ### multiple values by ref ###
       };
       croak "Exception caught: $@" if $@;

   Sets/gets the value(s) of the attributes of the object.  Since this
method is implemented using a LDAP directory, multiple values for an
attribute are allowed.  So in order to handle this, the accessor methods
can be used in an array context or a scalar context.  If the attribute has
only a single value then access it in a scalar context.  And if the
attribute allows multiple values then access it in an array context.  If
the attribute has multiple values and it is accessed in a scalar context
only the first value will be returned but if a single value is passed to
it then the attribute will be set to the single scalar value.

   Example:

     $person->objectclass('top', 'person', 'inetOrgPerson');
     $class = $person->objectclass();
     ### $class == 'top' ###
     @classes = $person->objectclass();
     ### @classes == ('top', 'person', 'inetOrgPerson') ###

   This method throws Perl execeptions so use it with an eval block.

   Parameters:

$value or *@values* or *\@values*
     Value(s) of the attribute of the object.  The value(s) can be either a
     single scalar value, an array of multiple values, or a reference to an
     array of multiple values.

   Returns:

$value or *@values*
     Returns a scalar value if used in a scalar context and returns an
     array when used in an array context.

   See the Persistent, documentation for more
information.

data - Accessing the Attribute Data of an Object
------------------------------------------------

     eval {
       ### set the attributes  ###
       $person->data({givenname => 'Marge', sn => 'Simpson'});

     ### get and print the attributes ###
     my $href = $person->data();
     print "name  = ", $href->{'givenname'} . ' ' . $href->{'sn'};
     print "email = ", $href->{'mail'};
       };
       croak "Exception caught: $@" if $@;

   Returns or sets all of the values of the attributes.  If an attribute
has multiple values then a reference to an array of values is returned for
that attribute.  And to set multiple values to an attribute, a reference
to an array of values should be passed.

   Example:

     ### get the multiple values for the attribute ###
     my $href = $person->data();
     my @classes = @{$href->{'objectclass'}};   ### superfluous copy ###
     print "objectclasses = ", join(', ', @classes), "\n";

     ### set the multiple values for the attribute ###
     my @new_classes = ('top', 'person');
     $person->data({objectclass => \@new_classes});

   This method throws Perl execeptions so use it with an eval block.

   Parameters:

\%hash
     A hash with keys that are the names of the attributes and values that
     are the values of the attributes.  This argument is optional and is
     used for setting the value(s) of the attributes.

   Returns:

\%hash
     Same as the argument above except that it is the returned value(s) of
     the attributes.

   See the Persistent, documentation for more
information.

SEE ALSO
========

   See Persistent, Persistent/Base,

BUGS
====

   This software is definitely a work in progress.  So if you find any
bugs please email them to me with a subject of 'Persistent Bug' at:

     winters@bigsnow.org

   And you know, include the regular stuff, OS, Perl version, snippet of
code, etc.

AUTHORS
=======

     David Winters <winters@bigsnow.org>

COPYRIGHT
=========

   Copyright (c) 1998-2000 David Winters.  All rights reserved. This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

A Persistent Class implemented using Memory (RAM)
*************************************************

NAME
====

   Persistent::Memory - A Persistent Class implemented using Memory (RAM)

SYNOPSIS
========

     use Persistent::Memory;
     use English;  # import readable variable names like $EVAL_ERROR

     eval {  ### in case an exception is thrown ###

     ### allocate a persistent object ###
     my $person = new Persistent::Memory();

     ### define attributes of the object ###
     $person->add_attribute('firstname', 'ID', 'VarChar', undef, 10);
     $person->add_attribute('lastname',  'ID', 'VarChar', undef, 20);
     $person->add_attribute('telnum', 'Persistent',
                            'VarChar', undef, 15);
     $person->add_attribute('bday', 'Persistent', 'DateTime', undef);
     $person->add_attribute('age', 'Transient', 'Number', undef, 2);

     ### query the datastore for some objects ###
     $person->restore_where(qq{
                               lastname = 'Flintstone' and
                               telnum =~ /^[(]?650/
                              });
     while ($person->restore_next()) {
       printf "name = %s, tel# = %s\n",
              $person->firstname . ' ' . $person->lastname,
              $person->telnum;
     }
       };

     if ($EVAL_ERROR) {  ### catch those exceptions! ###
       print "An error occurred: $EVAL_ERROR\n";
     }

ABSTRACT
========

   This is a Persistent class that uses memory (RAM) to store and retrieve
objects.  This can be useful when you want to create a cache of objects
(i.e. a server-side web cache).  This class can be instantiated directly
or subclassed.  The methods described below are unique to this class, and
all other methods that are provided by this class are documented in the
Persistent, documentation.  The Persistent,
documentation has a very thorough introduction to using the
Persistent framework of classes.

   This class is part of the Persistent base package which is available
from:

     http://www.bigsnow.org/persistent
     ftp://ftp.bigsnow.org/pub/persistent

DESCRIPTION
===========

   Before we get started describing the methods in detail, it should be
noted that all error handling in this class is done with exceptions.  So
you should wrap an eval block around all of your code.  Please see the
Persistent, documentation for more information on
exception handling in Perl.

METHODS
=======

new - Object Constructor
------------------------

     use Persistent::Memory;

     eval {
       my $person = new Persistent::Memory($field_delimiter);
     };
     croak "Exception caught: $@" if $@;

   Allocates an object.  This method throws Perl execeptions so use it
with an eval block.

   Parameters:

These are the same as for the *datastore* method below.
datastore - Sets/Returns the Data Store Parameters
--------------------------------------------------

     eval {
       ### set the data store ###
       $person->datastore($field_delimiter);

     ### get the data store ###
     $href = $person->datastore();
       };
       croak "Exception caught: $@" if $@;

   Returns (and optionally sets) the data store of the object.  This
method throws Perl execeptions so use it with an eval block.

   Parameters:

$field_delimiter
     Delimiter used to separate the attributes of the object in the data
     store.  This argument is optional and will be initialized to the value
     of the special Perl variable $; (or $SUBSCRIPT_SEPARATOR if you are
     using the English module) as a default.

   Returns:

$href
     Reference to the hash used as the data store.

insert - Insert an Object into the Data Store
---------------------------------------------

     eval {
       $person->insert();
     };
     croak "Exception caught: $@" if $@;

   Inserts an object into the data store.  This method throws Perl
execeptions so use it with an eval block.

   Parameters:

None.
   Returns:

None.
   See the Persistent, documentation for more
information.

delete - Delete an Object from the Data Store
---------------------------------------------

     eval {
       $person->delete();
     };
     croak "Exception caught: $@" if $@;

   Deletes an object from the data store.  This method throws Perl
execeptions so use it with an eval block.

   Parameters:

*@id*
     Values of the Identity attributes of the object.  This argument is
     optional and will default to the Identifier values of the object as
     the default.

   Returns:

$flag
     A true value if the object previously existed in the data store (it
     was deleted), and a false value if not (nothing to delete).

   See the Persistent, documentation for more
information.

restore - Restore an Object from the Data Store
-----------------------------------------------

     eval {
       $person->restore(@id);
     };
     croak "Exception caught: $@" if $@;

   Restores an object from the data store.  This method throws Perl
execeptions so use it with an eval block.

   Parameters:

*@id*
     Values of the Identity attributes of the object.  This method throws
     Perl execeptions so use it with an eval block.

   Returns:

$flag
     A true value if the object previously existed in the data store (it
     was restored), and a false value if not (nothing to restore).

   See the Persistent, documentation for more
information.

restore_where - Conditionally Restoring Objects
-----------------------------------------------

     use Persistent::Memory;

     eval {
       my $person = new Persistent::Memory('|');
       $person->restore_where(
         "lastname = 'Flintstone' and telnum =~ /^[(]?650/",
         "lastname, firstname, telnum DESC"
       );
       while ($person->restore_next()) {
         print "Restored: ";  print_person($person);
       }
     };
     croak "Exception caught: $@" if $@;

   Restores objects from the data store that meet the specified
conditions.  The objects are returned one at a time by using the
*restore_next* method and in a sorted order if specified.  This method
throws Perl execeptions so use it with an eval block.

   Since this is a Perl based Persistent class, the *restore_where* method
expects the $where argument to use Perl expressions.

   Parameters:

$where
     Conditional expression for the requested objects.  The format of this
     expression is similar to a SQL WHERE clause.  This argument is
     optional.

$order_by
     Sort expression for the requested objects.  The format of this
     expression is similar to a SQL ORDER BY clause.  This argument is
     optional.

   Returns:

$num_of_objs
     The number of objects that match the conditions.

   See the Persistent, documentation for more
information.

SEE ALSO
========

   See Persistent, Persistent/Base,
Persistent/DBM, Persistent/Memory,

NOTES
=====

   This Persistent class does not lock the data store (a hash in this
case) before reading or writing it.  This should not be a problem unless
you are using threaded Perl or forking processes that share an object of
this class.

BUGS
====

   This software is definitely a work in progress.  So if you find any
bugs please email them to me with a subject of 'Persistent Bug' at:

     winters@bigsnow.org

   And you know, include the regular stuff, OS, Perl version, snippet of
code, etc.

AUTHORS
=======

     David Winters <winters@bigsnow.org>

COPYRIGHT
=========

   Copyright (c) 1998-2000 David Winters.  All rights reserved. This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

provide a perl API for talking to CSO ph servers.
*************************************************

NAME
====

   Ph - provide a perl API for talking to CSO ph servers.

SYNOPSIS
========

     use Ph;

NOTICE
======

   This version of Ph.pm is not compatbile with pre-2.0 versions.  Users
of older versions (primarily at QUALCOMM) will need to convert their
scripts to be compatible with this version of Ph.pm.  (This was done to
make Ph.pm more object-oriented, allowing multiple connections at once.)

DESCRIPTION
===========

   The *Ph* module provides a uniform API for *perl* scripts that need to
talk to CSO ph servers.  It handles many of the messy details
automatically.  It also maintains an open connection to the server,
minimizing the costs of repeated openings and closings of server
connections (and the associated costs on the server of repeatedly forking
off short-lived processes to service requests made by the client.)

   In order to use the *Ph* protocol module, you will need to have the
IO/Socket, support and associated perl modules installed.
You wil also need to use perl 5.003 or later. (See Perl (perl.info).)
You should already be familiar with perl data
structures and perl references.  If not, read Perldata (perl.info),
and Perlref (perl.info).

   It is assumed that you are already familiar with the ph protocol.  If
you are not, please read *The CCSO Nameserver Server-Client Protocol* by
Steven Dorner and Paul Pomes.  It contains all of the descriptions of the
various ph requests that one can make.  (This API does simplify the
problems associated with parsing server responses.)

CONSTRUCTOR
===========

new ( [ARGS])
     The constructor takes a number of arguments.

     PhServer: Remote Ph server name (default is 'ns').

     PhPort:	Remove Ph port (default is 'ns', or '105').

     Debug: If set, module debugging is enabled.

GLOBALS
=======

$DefaultPhPort
     This constant value is the default port to make connections on if one
     is not specified as an argument to Connect.  Its default value is the
     value assigned to 'ns' in `/etc/services', or 105.

$DefaultPhServer
     The default ph server to use if not specified in the arguments to
     Connect.  This defaults to 'ns'.

METHODS
=======

   The following methods are provided as part of the API.

Add ENTRY
     This is a request to create a new ph record.  The record has fields
     with values specified by ENTRY, which can be either a reference to an
     associative array, or it may just be a string itself.  Hero login
     status is required.  A boolean return indicates whether the change
     was successful or not.

Change QUERY CHANGES
     This is a request to modify existing ph record(s).  The QUERY is a
     reference to an associative array, or a query string (Exactly as for
     the Query subroutine.)  The CHANGES is another reference to an
     associative array (or scalar string), containing the field names to be
     changed, and the new values that they are to hold.  The value returned
     is the ph result code returned by the server.  NOTE: Fields that are
     Encrypted (e.g. password) cannot be changed, yet! I will implement
     this as soon as I better understand how the encryption works.  The
     return value is a boolean variable indicating whether or not the
     change was successful.

Connect SERVER PORT
     This is a request to establish a connection to a ph server.  In
     addition, several other requests are sent to the server.  They are
     id, `siteinfo', and fields.  The returned values are stored in
     variables for use later.  Only one connection to a server can be
     active within a perl program at any one time.  Returns truth on
     success, false on failure.

Delete ENTRY
     This deletes an entire record from the ph server.  The record is
     selected by the query matching ENTRY, which is either a reference to
     an associative array, or a string query specification.  The value
     returned is the result code returned by the ph server.  *USE WITH
     CAUTION!* Hero mode is required.  Returns true of false to indicate
     successful or failed results.

Disconnect
     This disconnects from the server.  It sends the quit request before
     closing, to be polite to the server.  This is also called
     automatically by the package destructor, if necessary.  No return
     value is used.

ErrorMessage CODE
     This returns a string representation of the message associated with
     the result code returned by the server.

Fields
     Returns an associative array containing the field attributes for the
     fields defined by the currently connected ph server.   The keys are
     the field names, and the values are references to an attribute
     description hash:

          name	the field name
          max		the maximum length of the field
          desc	textual description for the field
          *		other flags (e.g. Default, Lookup, Public) for the field

GetLastCode
     This returns the last positive result code returned by the Ph server.

GetLastMessage
     This returns the last message returned by the Ph server.  This can be
     useful in determining the cause of failure - it sometimes provides
     more detail than is possible with just the GetLastCode value.

IsConnected
     This returns a boolean value which indicates whether or not an active
     connection to a server has been established.

Login ALIAS PASSWORD
     This request logs into the server, if possible.  It should use the
     `answer' method rather than the less secure clear method to encrypt
     the response.  Unfortunately, the `cryptit.c' file included with the
     ph distribution is incredibly, well, *cryptic*!  I am not exactly
     sure what it is doing, and converting it to perl is proving tiresome.
     (I have been told that the encryption is based upon a 3-rotor enigma.
     If anyone is feeling ambitious enough to provide a perl equivalent,
     I would be happy to fix this routine.)  A truth value is returned to
     the caller to indicate whether the login succeeded or not.

Logout
     Simply put, logout of the ph server!  (Obviously, you must be logged
     in first!)  CAUTION: There is a serious bug in some Ph servers which
     prevents the logout action from removing any privileges.  A hero mode
     session that has been logged out can still destroy the database
     (accidentally or on purpose).  This was discovered the hard way by the
     author of this package, who had to reenter his entire ph record by
     hand after running over this bug!

SiteInfo
     Returns an associative array containing the results of the `siteinfo'
     ph request for the currently connected server.  Each key corresponds
     to a field name in the returned result.

Version
     This function is used merely to determine the RCS revision number of
     the module that you are using.  Newer versions may be posted from time
     to time, and this allows you to determine if you are using the latest
     version of the Ph module.

AUTHOR
======

   This module was written entirely in perl by Garrett D'Amore.  It is
Copyright 1995, Qualcomm, Inc.  You can reach the author at the e-mail
address *garrett@qualcomm.com*.

Perl extension for interpreting a file of                          periodic (like weekly) events and assigning                          actual dates to them. Used to feed the                          calendar plotting software.
***********************************************************************************************************************************************************************************************************************************

NAME
====

   PlotCalendar::DateDesc - Perl extension for interpreting a file of
                   periodic (like weekly) events and assigning
             actual dates to them. Used to feed the
  calendar plotting software.

SYNOPSIS
========

     require PlotCalendar::DateDesc;

     my ($month, $year) = (3,1999);

     # ----    set the month and year
       my $trans = PlotCalendar::DateDesc->new($month, $year);

     # ----    parse a description and return the day of the month
     my $day = 'first monday and third monday';
        print "$day : ",join(',',@{$trans->getdom($day)}),"\n";

     $day = 'last monday and third monday';
     print "$day : ",join(',',@{$trans->getdom($day)}),"\n";

     $day = 'last fri and third Monday';
     print "$day : ",join(',',@{$trans->getdom($day)}),"\n";

     # ----    parse a description and return the date as mm/dd/yyyy
        $day = 'last fri and third Monday';
     print "$day dates: ", join(',',@{$trans->getdates($day)}),"\n";

     What gets returned by both routines is a pointer to an array of answers

DESCRIPTION
===========

     input descriptions may be one of :
     a day of the week (monday, tuesday, etc)
     a qualified day of the week (first monday, second tuesday, last sunday)
     compound statements are allowed : mon and wed, first mon and third mon

     Qualifiers are : first, second, third, fourth, fifth, last
     Compounds are only formed with 'and' and are not associative

AUTHOR
======

     Alan Jackson
     March 1999
     ajackson@icct.net

SEE ALSO
========

   PlotCalendar::Month PlotCalendar::Day

This is an all perl replacement for parts of                           Date::Calc. I'd love to use it, but I ran into                           trouble installing the compiled C onto my                            hosting service account, since I can't                           do a compile over there (it'd cost $$)                           So I have reproduced those functions I needed                           in perl. Oh well.
************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************

NAME
====

   PlotCalendar::DateTools - This is an all perl replacement for parts of
                        Date::Calc. I'd love to use it, but I ran into
                      trouble installing the compiled C onto my
               hosting service account, since I can't
     do a compile over there (it'd cost $$)                           So
I have reproduced those functions I needed                           in
perl. Oh well.

SYNOPSIS
========

     require PlotCalendar::DateTools;

     my ($day, $month, $year) = (5,3,1999);
     my $dayname = 'Tuesday';

     # ----    initialize tool

     my $dow = Day_of_Year($yr,$mon,$day);

     my $numdays = Days_in_Month($yr,$mon);

     my $dow = Decode_Day_of_Week($dayname);

     my $dowfirst = Day_of_Week($yr,$mon,$day);

     my ($nyr, $nmon, $nday) = Add_Delta_Days($yr,$mon,$day, $numdays);

     my $dayname = Day_of_Week_to_Text($dow)

     my $month = Month_to_Text($mon);

     my $doy = Day_of_Year($year,$mon,$day);

DESCRIPTION
===========

     A perl-only clone of a subset of Date::Calc

AUTHOR
======

     Alan Jackson
     April 1999
     ajackson@icct.net

REQUIREMENTS
============

     Requires modules :
             Exporter
             Carp
             Time::DaysInMonth
             Time::JulianDay

SEE ALSO
========

   PlotCalendar::Month PlotCalendar::Day

Generate ascii or html for a single day in a calendar
*****************************************************

NAME
====

   PlotCalendar::Day - Generate ascii or html for a single day in a
calendar

SYNOPSIS
========

   Creates a Day object for plotting as ASCII, HTML, or in a Perl/Tk
Canvas. Intended to be gathered together by Month.pm to create a
traditional calendar.

DESCRIPTION
===========

   Measurements in pixels because - well, because. It seemed simpler when
I made the decision. And it works for both Tk and HTML.

   The day is laid out like this :

     ------------------------------------------
     |         |        |                     |
     | digit   | digit  | Main day name       |
     |         |        |                     |
     |         |        |                     |
     |         |        |                     |
     |---------|--------|                     | <- bgcolmain
     |                                        |
     |                                        |
     |                                        |
     | Optional text                          |
     |      .                                 |
     |                                        |
     | Optional Text                          |
     |      .                                 |
     |      .                                 |
     |      .                                 |
     |      .                                 |
     | Optional text                          |
     |      .                                 |
     |      .                                 |
     |      .                                 |
     |      .                                 |
     ------------------------------------------

     Globals : height, width, dayfont, mainfont, optfont, fgcol,
     bgcolmain, digit

     Optionals : dayname, optext[...]

     Font sizes in HTML translate as (rounding up) :
         6->-1
         8->+0
         10->+1
         12->+2
         14->+3

   Various quantities can be set globally, or over-ridden for specific
cases.

   This is really meant to be called by month.pm to construct a calendar,
but calling it with a *really big size* is a way to "zoom in" on a given
day

EXAMPLE
=======

     require PlotCalendar::Day;

     my $digit=10 ; # do it for the tenth
     my $day = PlotCalendar::Day->new($digit);

     #	 These are values with default settings, so these are optional

     ------------ size of whole thing in pixels, X,Y
     	$day -> size(100,100);
     ------------ Global foreground and background colors
     	$day -> color('BLACK','#33cc00',);
     	$day -> color('WHITE','RED',);
     ------------ Font sizes for digits, dayname, and optional text
     	$day -> font('14','10','8');
     ------------ styles for digits, dayname, and optional text
     ------------ b=bold, i=italic, u=underline, n=normal
     	$day -> style('bi','nbu','i');
     ------------ Clip text to avoid wrapping? (yes/no)
     	$day -> cliptext('yes');

     #	HTML only options

         ------------ is it allowed to expand vertically if there is too much text?
     $day -> htmlexpand('yes');

     #	These values are defaulted to blank

     ------------ day name
     	$day -> dayname('Groundhog Day');
     ------------ if set, name is a hotlink
     	$day -> nameref('<A href="http://ooga.booga.com/">');
     ------------ if set, text string is a hotlink. Note that an array is getting
     ------------ passed. Text is passed as an array also. Each line of text is
     ------------ an array element. THis example hotlinks only the first 2 lines.
     	$day -> textref('<A href="http://booga.booga.com/">','<A href="mailto:>');
     ------------ Text strings, passed as elemnts of an array
     	$day -> text('text string 1','text string 2','abcdefghijklmno 0 1 2 3 4 5 6 7 8 9 0',);
     ------------ override default text colors and set each string individually
     	$day -> textcolor('BLUE','RED','GREEN',);
     ------------ override default text sizes and set each string individually
     	$day -> textsize('8','10','8',);
     ------------ override default text styles and set each string individually
     	$day -> textstyle('b','u','bi',);

     ------------ wrap a reference around the entire cell
     	$day->htmlref('<A href="http://this_is_a_url/">');

     ------------ unload what I set
     	my @size = $day->size;
     	my @color = $day->color;
     	my @font = $day->font;
     	my @text = $day->text;
     	my $dayname = $day->dayname;

     #	So, what do we have now?

     ------------ Create an ascii text cell
     	#my $text = $day -> gettext;

     ------------ Create and return html for a cell in a table
     	my $html = $day -> gethtml;

     ------------ Create and return Tk code (not implemented yet)
     	#my $tk = $day -> gettk;

     print "<HTML><BODY>\n";
     print "<H1>Normal Day</H1>\n";
     print "<TABLE BORDER=1><TR>\n";
     print $html;
     print "</TR></TABLE>\n";

AUTHOR
======

     Alan Jackson
     March 1999
     ajackson@icct.net

Plot an ASCII or HTML calendar
******************************

NAME
====

     PlotCalendar::Month - Plot an ASCII or HTML calendar

SYNOPSIS
========

   Creates a Month object for plotting as ASCII, HTML, or in a Perl/Tk
Canvas. Calls Day.pm for the individual days within the calendar.

DESCRIPTION
===========

   Measurements in pixels because - well, because. It seemed simpler when
I made the decision. And it works for both Tk and HTML.

   The month is laid out like this :

     Month_name                          Year

     ---------------------------------------------------------------
     | Sun    | Mon    | Tue    | Wed   | Thu    | Fri    | Sat    |
     ---------------------------------------------------------------
     |        |        |        |       |        |        |        |
     | day    | day    |        |       |        |        |        |
     |        |        |        |       |        |        |        |
     |--------|--------|--------|-------|--------|--------|--------|
     |        |        |        |       |        |        |        |
     | day    | day    |        |       |        |        |        |
     |        |        |        |       |        |        |        |
     |--------|--------|--------|-------|--------|--------|--------|
     |        |        |        |       |        |        |        |
     | day    | day    |        |       |        |        |        |
     |        |        |        |       |        |        |        |
     |--------|--------|--------|-------|--------|--------|--------|
     |        |        |        |       |        |        |        |
     | day    | day    |        |       |        |        |        |
     |        |        |        |       |        |        |        |
     |--------|--------|--------|-------|--------|--------|--------|
     |        |        |        |       |        |        |        |
     | day    | day    |        |       |        |        |        |
     |        |        |        |       |        |        |        |
     |--------|--------|--------|-------|--------|--------|--------|
     |        |        |        |       |        |        |        |
     | day    | day    |        |       |        |        |        | optional
     |        |        |        |       |        |        |        | row
     |--------|--------|--------|-------|--------|--------|--------|

     Globals : height, width, fgcol,
     bgcolmain,

     References expect to be given the entire thing, that is
     <A HREF="http://yaddayaddayadda/">
     or
     <A HREF="mailto:george_tirebiter@noway.nohow">

     The software will terminate it with a </A> at the right spot.

EXAMPLE
=======

     require PlotCalendar::Month;

     my $month = PlotCalendar::Month->new(01,1999); # Jan 1999

     # global values, to be applied to all cells

     ------------------------- size of whole calendar
     $month -> size(700,700); # width, height in pixels
     ------------------------- font sizes for digit, name of day, and text
     $month -> font('14','10','8');
     ------------------------- clip text if it wants to wrap?
     $month -> cliptext('yes');
     ------------------------- This can be any day you want
     $month -> firstday('Sun'); # First column is Sunday
     ------------------------- If this is not set, regular text will be used.
     ------------------------- If it is set, then in that directory should be
     ------------------------- gif files named 0.gif, 1.gif ... January.gif, ...
     $month -> artwork('/home/ajackson/public_html/cgi-bin/Calendar/Calendar_art3/');

     #	arrays of values, if not an array, apply to all cells, if an array
     #  apply to each cell, indexed by day-of-month

     The colors are the standard values used in html
     Textstyle encoding is b=bold, i=italic, u=underline, n=normal
     Fontsize = 6-14, roughly point sizes

     my @text;
     my @daynames;
     my @nameref;
     my @bgcolor;
     my @colors = ('WHITE','#33cc00','#FF99FF','#FF7070','#FFB0B0',);
     my (@textcol,@textsize,@textstyle,@textref);
     my @style = ('i','u','b',);
     my @url;

     ----------- build some random color and text fields as a demo

     for (my $i=1;$i<=31;$i++) {
     	$daynames[$i] = "Day number $i";
     	$nameref[$i] = "<A HREF=\"http://www.$i.ca\">";
     	$bgcolor[$i] = $colors[$i%5];
     	@{$text[$i]} = ("Text 1 for $i","Second $i text","$i bit of text",);
     	@{$textref[$i]} = ("<A HREF=\"http://www.$i.com/\">","Second $i text","<A HREF=\"http://www.$i.net/\">",);
     	@{$textcol[$i]} = ($colors[($i+1)%5],$colors[($i+2)%5],$colors[($i+3)%5]);
     	@{$textsize[$i]} = ("8","10","8",);
     	@{$textstyle[$i]} = @style;
     	@style = reverse(@style);
     	$url[$i] = '<A href="http://some.org/name_number_' . $i . '">';
     }

     ------------------------- Set global values
     $month -> fgcolor('BLACK',); #  Global foreground color
     $month -> bgcolor(@bgcolor); # Background color per day
     $month -> styles('b','bi','ui',); # Global text styles

     #	Comments

     my @prefs = ('before','after','after');
     my @comments = (['Comment one'],["Comment two","and so on"],['Comment three']);
     my @comcol = qw(b g b);
     my @comstyle = qw(n b bi);
     my @comsize = qw(8 10 14);

     ------------------------- Comments get stuck into an otherwise empty cell
     $month->comments(\@prefs,\@comments,\@comcol,\@comstyle,\@comsize);

     ------------------------- Wrap a hotlink around the whole day, for each day
     $month -> htmlref(@url);

     ------------------------- set the names for every day
     $month -> dayname(@daynames);
     ------------------------- wrap the name in a hotlink
     $month -> nameref(@nameref);

     ------------------------- set the text and it's properties for each day
     $month -> text(@text);
     $month -> textcolor(@textcol);
     $month -> textsize(@textsize);
     $month -> textstyle(@textstyle);
     $month -> textref(@textref);

     #	global HTML only options

     ----------------- allow days to expand vertically to accomodate text

     $month -> htmlexpand('yes');

     #	grab an ascii calendar and print it

     my $text = $month -> getascii;

     print $text;

     ------------------- get the html calendar

     my $html = $month -> gethtml;

     print "<HTML><BODY>\n";
     print $html;

SEE ALSO
========

     Also look at Day.pm

DEPENDENCIES
============

     PlotCalendar::DateTools

   This is a pure perl replacement for Date::Calc. I needed it because
Date::Calc contains C code which my web hosting service did not have
available for CGI-BIN stuff.

AUTHOR
======

     Alan Jackson
     March 1999
     ajackson@icct.net

[Delphi|VB|Java]-like Perl preprocessor
***************************************

NAME
====

   PlusPlus - [Delphi|VB|Java]-like Perl preprocessor

SYNOPSIS
========

     use PlusPlus;

     my $nested_hash = {outer => {inner => {a => 1, b => 2, c => 3}}}

     $nested_hash.outer.inner.a = 5;      # dot syntax for variables

     $dbh.do ("DROP DATABASE TEST");      # dot syntax for methods

     with ($nested_hash.outer.inner) {    # 'with' operator
         ($.a, $.c) = (10, 30);
         print " b = $.b\n";
     };

DESCRIPTION
===========

   *PlusPlus* is a quick and (maybe) a little bit dirty way to have some
additional comfort when working with nested Perl data structures. This
module allows some extensions to the Perl syntax.

   *PlusPlus* is a source filter (preprocessor) based on the module Filter.

DOT SYNTAX
----------

   Using *PlusPlus*, you can dramatically clearify your code by typing

     $foo.bar.baz

     each time instead of

     $foo -> {bar} -> {baz}

   Yes, of course, the dot means the concatenation operator. So, you might
suppose a collision in case like

     $foo.$bar

     What would it be: I<"$foo.$bar"> or I<$foo->{$bar}>? Please, remind:
     when using B<PlusPlus>, always type at least one space aside of your
     concatenation dot. So,

     $foo.$bar      eq  $foo->{$bar}
     $foo . $bar    eq  "$foo$bar"

   And what about the method calls? It's very similar (see SYNOPSYS). But,
note: the method call must be followed by an open paranthesis, even if the
argument list is void.

     $st.finish	   eq  $st -> {finish}
     $st.finish ()  eq  $st -> finish ()

WITH
----

   The *PlusPlus* preprocessor introduces the with operator in the manner
similar to Borland (C) Delphi (R) and MS ($) VB (...). Each fragment of
code like

     with ($foo) {
     	...
     };

   is mapped to

     do { my $__with__prefix__ = ($foo);
     	...
     };

     All variables like $.bar are renamed to $__with__prefix__.bar.
     It is very unprobably that you use the variable named $__with__prefix__,
     but, in any case, you are warned.

   And, please, don't forget to put a semicolon after the closing brace:
with is do, not while.

AUTHOR
======

   D. E. Ovyanko, do@mobile.ru

SEE ALSO
========

   Filter(3).

check pod documents for syntax errors
*************************************

NAME
====

   Pod::Checker, podchecker() - check pod documents for syntax errors

SYNOPSIS
========

     use Pod::Checker;

     $syntax_okay = podchecker($filepath, $outputpath, %options);

     my $checker = new Pod::Checker %options;
     $checker->parse_from_file($filepath, \*STDERR);

OPTIONS/ARGUMENTS
=================

   `$filepath' is the input POD to read and `$outputpath' is where to
write POD syntax error messages. Either argument may be a scalar
indicating a file-path, or else a reference to an open filehandle.  If
unspecified, the input-file it defaults to `\*STDIN', and the output-file
defaults to `\*STDERR'.

podchecker()
------------

   This function can take a hash of options:

*-warnings* => val
     Turn warnings on/off. See `"Warnings"' in this node.

DESCRIPTION
===========

   *podchecker* will perform syntax checking of Perl5 POD format
documentation.

   *NOTE THAT THIS MODULE IS CURRENTLY IN THE BETA STAGE!*

   It is hoped that curious/ambitious user will help flesh out and add the
additional features they wish to see in Pod::Checker and *podchecker* and
verify that the checks are consistent with Perlpod (perl.info).

   The following checks are currently preformed:

   * Unknown '=xxxx' commands, unknown 'X<...>' interior-sequences, and
     unterminated interior sequences.

   * Check for proper balancing of =begin and =end. The contents of such a
     block are generally ignored, i.e. no syntax checks are performed.

   * Check for proper nesting and balancing of =over, =item and =back.

   * Check for same nested interior-sequences (e.g.  `L<...L<...>...>').

   * Check for malformed or nonexisting entities `E<...>'.

   * Check for correct syntax of hyperlinks `L<...>'. See Perlpod (perl.info),
     for details.

   * Check for unresolved document-internal links. This check may also
     reveal misspelled links that seem to be internal links but should be
     links to something else.

DIAGNOSTICS
===========

Errors
------

   * empty =headn

     A heading (=head1 or =head2) without any text? That ain't no heading!

   * =over on line N without closing =back

     The =over command does not have a corresponding =back before the next
     heading (=head1 or =head2) or the end of the file.

   * =item without previous =over

   * =back without previous =over

     An =item or =back command has been found outside a =over/=back block.

   * No argument for =begin

     A =begin command was found that is not followed by the formatter
     specification.

   * =end without =begin

     A standalone =end command was found.

   * Nested =begin's

     There were at least two consecutive =begin commands without the
     corresponding =end. Only one =begin may be active at a time.

   * =for without formatter specification

     There is no specification of the formatter after the =for command.

   * unresolved internal link NAME

     The given link to NAME does not have a matching node in the current
     POD. This also happend when a single word node name is not enclosed in
     "".

   * Unknown command "*CMD*"

     An invalid POD command has been found. Valid are =head1, =head2,
     =over, =item, =back, =begin, =end, =for, =pod, =cut

   * Unknown interior-sequence "*SEQ*"

     An invalid markup command has been encountered. Valid are: `B<>',
     `C<>', `E<>', `F<>', `I<>', `L<>', `S<>', `X<>', `Z<>'

   * nested commands *CMD*<...*CMD*<...>...>

     Two nested identical markup commands have been found. Generally this
     does not make sense.

   * garbled entity STRING

     The STRING found cannot be interpreted as a character entity.

   * Entity number out of range

     An entity specified by number (dec, hex, oct) is out of range (1-255).

   * malformed link L<>

     The link found cannot be parsed because it does not conform to the
     syntax described in Perlpod (perl.info).

   * nonempty Z<>

     The `Z<>' sequence is supposed to be empty.

   * empty X<>

     The index entry specified contains nothing but whitespace.

   * Spurious text after =pod / =cut

     The commands =pod and =cut do not take any arguments.

   * Spurious character(s) after =back

     The =back command does not take any arguments.

Warnings
--------

   These may not necessarily cause trouble, but indicate mediocre style.

   * multiple occurence of link target name

     The POD file has some =item and/or `=head' commands that have the
     same text. Potential hyperlinks to such a text cannot be unique then.

   * line containing nothing but whitespace in paragraph

     There is some whitespace on a seemingly empty line. POD is very
     sensitive to such things, so this is flagged. *vi* users switch on
     the list option to avoid this problem.

   * file does not start with =head

     The file starts with a different POD directive than head.  This is
     most probably something you do not want.

   * No numeric argument for =over

     The =over command is supposed to have a numeric argument (the
     indentation).

   * previous =item has no contents

     There is a list =item right above the flagged line that has no text
     contents. You probably want to delete empty items.

   * preceding non-item paragraph(s)

     A list introduced by =over starts with a text or verbatim paragraph,
     but continues with =items. Move the non-item paragraph out of the
     =over/=back block.

   * =item type mismatch (one vs. *two*)

     A list started with e.g. a bulletted =item and continued with a
     numbered one. This is obviously inconsistent. For most translators the
     type of the first =item determines the type of the list.

   * N unescaped `<>' in paragraph

     Angle brackets not written as `<lt>' and `<gt>' can potentially cause
     errors as they could be misinterpreted as markup commands.

   * Unknown entity

     A character entity was found that does not belong to the standard ISO
     set or the POD specials `verbar' and `sol'.

   * No items in =over

     The list opened with =over does not contain any items.

   * No argument for =item

   * empty section in previous paragraph

     The previous section (introduced by a `=head' command) does not
     contain any text. This usually indicates that something is missing.
     Note: A =head1 followed immediately by =head2 does not trigger this
     warning.

   * Verbatim paragraph in NAME section

     The NAME section (`=head1 NAME') should consist of a single paragraph
     with the script/module name, followed by a dash `-' and a very short
     description of what the thing is good for.

   * Hyperlinks

     There are some warnings wrt. hyperlinks: Leading/trailing whitespace,
     newlines in hyperlinks, brackets `()'.

RETURN VALUE
============

   *podchecker* returns the number of POD syntax errors found or -1 if
there were no POD commands at all found in the file.

EXAMPLES
========

   *[T.B.D.]*

INTERFACE
=========

   While checking, this module collects document properties, e.g. the nodes
for hyperlinks (`=headX', =item) and index entries (`X<>').  POD
translators can use this feature to syntax-check and get the nodes in a
first pass before actually starting to convert. This is expensive in terms
of execution time, but allows for very robust conversions.

`$checker->poderror( @args )'
`$checker->poderror( {%opts}, @args )'
     Internal method for printing errors and warnings. If no options are
     given, simply prints "@_". The following options are recognized and
     used to form the output:

          -msg

     A message to print prior to `@args'.

          -line

     The line number the error occurred in.

          -file

     The file (name) the error occurred in.

          -severity

     The error level, should be 'WARNING' or 'ERROR'.

`$checker->num_errors()'
     Set (if argument specified) and retrieve the number of errors found.

`$checker->name()'
     Set (if argument specified) and retrieve the canonical name of POD as
     found in the `=head1 NAME' section.

`$checker->node()'
     Add (if argument specified) and retrieve the nodes (as defined by
     `=headX' and =item) of the current POD. The nodes are returned in the
     order of their occurence. They consist of plain text, each piece of
     whitespace is collapsed to a single blank.

`$checker->idx()'
     Add (if argument specified) and retrieve the index entries (as
     defined by `X<>') of the current POD. They consist of plain text,
     each piece of whitespace is collapsed to a single blank.

`$checker->hyperlink()'
     Add (if argument specified) and retrieve the hyperlinks (as defined by
     `L<>') of the current POD. They consist of an 2-item array: line
     number and Pod::Hyperlink object.

AUTHOR
======

   Brad Appleton <bradapp@enteract.com> (initial version), Marek Rouchal
<marek@saftsack.fs.uni-bayreuth.de>

   Based on code for *Pod::Text::pod2text()* written by Tom Christiansen
<tchrist@mox.perl.com>

compile POD into an object tree
*******************************

NAME
====

   Pod::Compiler - compile POD into an object tree

SYNOPSIS
========

     use Pod::Compiler;

DESCRIPTION
===========

   This package, based on `Pod::Parser|Pod::Parser' in this node, compiles
a given POD document into an object tree (based on
`Tree::DAG_Node|Tree::DAG_Node' in this node).  It prints errors and
warnings about the POD it reads. The result can be used to conveniently
convert the POD into any other format.

   The resulting objects have a variety of methods to ease the subsequent
conversion.

   There are two script based on this package, namely
`podchecker2|podchecker2' in this node, an enhanced POD syntax checker and
`podlint|podlint' in this node, which beautifies the POD of a given file.

   This package is object-oriented, which means that you can quite easily
build a derived package and override some methods in case the given
behaviour does not exactly suit your needs.

Package Functions
-----------------

   The following functions can be imported and called from a script, e.g.
like this:

     use Pod::Compiler qw(pod_compile);
     my $root = pod_compile('myfile.pod');

pod_compile( { %options } , $file )
pod_compile( $file )
     Compile the given $file using some %options and return the root of
     the object tree representing the POD in $file. The return value is
     either undef if some fatal error occured or an object of type
     Pod::root. See below for methods applicable to this class and for the
     options.

     The special option `-compiler => 'class'' lets you specify an
     alternate (derived) compiler class rather than *Pod::Compiler*.

Compiler Object Interface
-------------------------

   The following section describes the OO interface of *Pod::Compiler*.

$c = Pod::Compiler->new( %options )
     Set up a new compiler object. Options (see below) can be passed as a
     hash, e.g.

          $c = Pod::Compiler->new( -warnings => 0 ); # don't be silly

     *Pod::Compiler* inherits from Pod::Parser. See Pod/Parser,
     for additional methods.

$c->initialize()
     Initalize, set defaults. The following options are set to the given
     defaults unless they have been defined at object creation:

          -errors => 1

     Print POD syntax errors (using *messagehandler*) if option value is
     true.

          -warnings => 1

     Print POD syntax warnings (using *messagehandler*) if option value is
     true.

          -idlength => 20

     Pod::Compiler creates a unique node id for each `=head', =item and
     `X<>', consisting only of `\w' characters. The option value specifies
     how many characters from the original node text are used for the node
     id by the built-in *make_unique_node_id* method. See below for more
     information.

          -ignore => 'BCFS'

     This option specifies which interior sequences (e.g. `B<...>') are
     ignored when nested in itself, e.g. `B<...B<...>...>'.  The inner B
     is simply discarded if the corresponding letter appears in the option
     value string.

          -unwrap => 'I'

     This option specifies which interior sequences (e.g. `I<...>') are
     unwrapped when nested in itself, e.g. `I<...I<...>...>' is turned
     into `I<...>...I<...>'. While some destination formats may handle
     such nestings appropriately, other might have problems.  This option
     solves it right away. By the way, from a typographical point of view,
     italics are often used for emphasis. In order to emphasize something
     within an emphasis, one reverts to the non-italic font.

          name => ''

     This is used to store the (logical) name of the POD, i.e. for example
     the module name as it appears in `use module;'. It is used internally
     only to detect internal links pointing to the explicit page name.
     Example: You compile the file `Compiler.pm' which contains the
     package `Pod::Compiler'.  You set name to `Pod::Compiler' (there is
     no safe automatic way to do so).  Thus if the file includes a link
     like `L<Pod::Compiler/messagehandler>' it is recognized as an internal
     link and it is checked whether it resolves. Of course you should have
     written the link as `L</messagehandler>'...

          -perlcode => 0

     If set to true, the compiler will also return the Perl code blocks as
     objects Pod::perlcode, rather than only the POD embedded in the file.
     This is used e.g. by `podlint|podlint' in this node.

$c->option( $name , $value )
     Get or set the compile option (see above) given by $name. If $value is
     defined, the option is set to this value. The resulting (or
     unchanged) value is returned.

$c->messagehandler( $severity , $message )
     This method is called every time a warning or error occurs.
     *$severity* is one of 'ERROR' or 'WARNING', *$message* is a one-line
     string.  The built-in method simply does

          warn "$severity: $message\n";

$c->name( [ $name ] )
     Set/retrieve the name property, i.e. the canonical Pod name (e.g.
     `Pod::HTML'). See above for more details.

$c->root()
     Return the root element (instance of class Pod::root) representing
     the compiled POD document. See below for more info about its methods.

$c->make_unique_node_id($string)
     Turn given text string into a document unique node id.  Can be
     overridden to adapt this to specific formatter needs.  Basically this
     method takes a string and must return something (more or less
     dependent on the string) that is unique for this POD document. The
     built-in method maps all consecutive non-word characters and
     underlines to a single underline and truncates the result to
     *-idlength* (see options above). If the result already exists, a
     suffix `_n' is appended, where n is a number starting with 1.  A
     different method could e.g. just return ascending numbers, but if you
     think of HTML output, a node id that resembles the text and has a fair
     chance to remain constant over subsequent compiles of the same
     document gives the opportunity to link to such anchors from external
     documents.

NOTES
=====

Building POD converters
-----------------------

   The *Pod::Compiler* module is designed to serve as a basis for complex
POD converters, e.g. to HTML, FrameMaker or LaTeX that can handle multiple
POD documents with a table of contents, an index and most imporant
hyperlinks/crossreferences.

   The following flow outlines how such a converter may work:

   * Getting the documents to be converted

     Interpreting command line arguments and options, the converter should
     gather all the POD files to be converted. Note that because of the
     structure of POD hyperlinks and restrictions in the anchor format of
     the individual destination formats you'll almost certainly will need a
     two-pass apporach where you process all documents at once. See
     Pod/Find, for some useful helpers in locating POD
     documents. The documents are stored as Pod::doc in a
     Pod::doc::collection.

   * Compiling all documents

     The next step would be a loop over all documents, calling
     *Pod::Compiler* on each document. This checks the syntax, prints
     errors and warnings and generates an object tree and information
     about the document's hyperlink anchors. The latter (a
     Pod::node::collection) is stored in the Pod::doc, the former is saved
     to a temporary file (see also File/Temp) with the
     help of Storable.

   * Converting the documents

     The second loop over all documents does the actual conversion. If you
     do not care very much about OO principles, you may extend the *Pod::**
     packages by e.g. a as_html method, so that you can say
     `(Pod::root)->as_html'. Or you use the `walk_down' method of
     *Tree::DAG_Node* to traverse the object tree and convert the
     individual objects in the callback.

     The existing Pod::doc::collection is used to resolve the hyperlinks.
     Each node already has a node id assigned.

     The result is saved to the destination files and the temporary files
     can be removed.

   * Table of contents and index

     During or after the final conversion one can build a TOC and an index,
     derived from the `=headX' and =item/`X<>' respectively.  Strategies
     for the index could be: Only the `X<>' entries, single worded
     =head2/=item, all hyperlink anchors that were hit during conversion,
     all =items, ...

SEE ALSO
========

   See Pod/Checker, Pod/Parser,
Pod/Find, `pod2man' in this node, `pod2text' in this node,
see Pod/Man,

AUTHOR
======

   Marek Rouchal <marekr@cpan.org>

HISTORY
=======

   A big deal of this code has been recycled from a variety of existing
Pod converters, e.g. by Tom Christiansen and Russ Allbery. A lot of ideas
came from Nick Ing-Simmons' *PodToHtml*.

module to convert pod files to DocBook SGML
*******************************************

NAME
====

   Pod::DocBook - module to convert pod files to DocBook SGML

SYNOPSIS
========

     use Pod::DocBook;
     pod2docbook( [options] );

DESCRIPTION
===========

   Converts files from pod format ( see Perlpod (perl.info),
) to DocBook format.  It can automatically generate indexes and
cross-references, and it keeps a cache of things it knows how to
cross-reference.

ARGUMENTS
=========

   Pod::DocBook takes the following arguments:

help
          --help

     Displays the usage message.

infile
          --infile=name

     Specify the pod file to convert.  Input is taken from STDIN if no
     infile is specified.

outfile
          --outfile=name

     Specify the HTML file to create.  Output goes to STDOUT if no outfile
     is specified.

title
          --title=title

     Specify the title of the resulting HTML file.

no-header
          --no-header

     Doesn't write a default header out for the DTD.

no-footer
          --no-footer

     Doesn't write a default footer out for the DTD.

root-id
          --root-id

     Specifies the root identifier for the base element used in chapter
     and section tags. The default is *pod2docbook-ch-1*.

verbose
          --verbose

     Display progress messages.

EXAMPLE
=======

     pod2docbook( "pod2docbook", "--infile=foo.pod",
                  "--outfile=/perl/nmanual/foo.sgml" );

AUTHOR
======

   Alligator Descartes <descarte@arcana.co.uk> from the original
`pod2html' in this node source code by Tom Christiansen,
<tchrist@perl.com>, for it is he. Many thanks to Chris Maden of O'Reilly &
Associations for doing serious road-testing on this module.

BUGS
====

   Has trouble with  etc in = commands.

LIMITATIONS
===========

   Nested =over/=back lists are not supported within DocBook.

SEE ALSO
========

   See Perlpod (perl.info),

COPYRIGHT
=========

   This program is distributed under the Artistic License.

Convert POD data to formatted DSR input
***************************************

NAME
====

   Pod::Dsr - Convert POD data to formatted DSR input

SYNOPSIS
========

     use Pod::Dsr;
     my $parser = Pod::Dsr->new (release => $VERSION, section => 8);

     # Read POD from STDIN and write to STDOUT.
     $parser->parse_from_filehandle;

     # Read POD from file.pod and write to file.1.
     $parser->parse_from_file ('file.pod', 'file.1');

DESCRIPTION
===========

   Pod::Dsr is a module to convert documentation in the POD format (the
preferred language for documenting Perl) into Digital Standard Runoff (DSR)
input.  The resulting DSR code is suitable for display on a terminal using
RUNOFF(1) and TYPE(1), or printing using RUNOFF(1) and PRINT(1).  It is
conventionally invoked using the driver script *pod2rno*, but it can also
be used directly.

   As a derived class from Pod::Parser, Pod::Dsr supports the same methods
and interfaces.  See Pod/Parser, for all the details;
briefly, one creates a new parser with `Pod::Dsr->new()' and then calls
either parse_from_filehandle() or parse_from_file().

   new() can take options, in the form of key/value pairs that control the
behavior of the parser.  See below for details.

   If no options are given, Pod::Dsr uses the name of the input file with
any trailing `.pod', `.pm', or `.pl' stripped as the man page title, to
section 1 unless the file ended in `.pm' in which case it defaults to
section 3, to a centered title of "User Contributed Perl Documentation", to
a centered footer of the Perl version it is run with, and to a left-hand
footer of the modification date of its input (or the current date if given
STDIN for input).

   Besides the obvious pod conversions, Pod::Dsr also takes care of
formatting func(), func(n), and simple variable references like $foo or
@bar so you don't have to use code escapes for them; complex expressions
like `$fred{'stuff'}' will still need to be escaped, though.  It also
translates dashes that aren't used as hyphens into en dashes, makes long
dashes-like this-into proper em dashes, fixes "paired quotes," makes C++
and PI look right, puts a little space between double underbars, and
escapes stuff that runoff treats as special so that you don't have to.

   The recognized options to new() are as follows.  All options take a
single argument.

center
     Sets the centered page header to use instead of "User Contributed Perl
     Documentation".

date
     Sets the left-hand footer.  By default, the modification date of the
     input file will be used, or the current date if stat() can't find
     that file (the case if the input is from STDIN), and the date will be
     formatted as DD-MMM-YYYY.

quotes
     Sets the quote marks used to surround C<> text.  If the value is a
     single character, it is used as both the left and right quote; if it
     is two characters, the first character is used as the left quote and
     the second as the right quoted; and if it is four characters, the
     first two are used as the left quote and the second two as the right
     quote.  This may also be set to the special value none, in which case
     no quote marks are added around C<> text.

release
     Set the centered footer.  By default, this is the version of Perl you
     run Pod::Dsr under.

section
     Set the section for the `.HEADER LEVEL' command.  The standard section
     numbering convention is to use 1 for user commands, 2 for system
     calls, 3 for functions, 4 for devices, 5 for file formats, 6 for
     games, 7 for miscellaneous information, and 8 for administrator
     commands.  There is a lot of variation here, however; some systems
     (like Solaris) use 4 for file formats, 5 for miscellaneous
     information, and 7 for devices.  Still others use 1m instead of 8, or
     some mix of both.  About the only section numbers that are reliably
     consistent are 1, 2, and 3.  By default, section 1 will be used
     unless the file ends in .pm in which case section 3 will be selected.

   The standard Pod::Parser method parse_from_filehandle() takes up to two
arguments, the first being the file handle to read POD from and the second
being the file handle to write the formatted output to.  The first defaults
to STDIN if not given, and the second defaults to STDOUT.  The method
parse_from_file() is almost identical, except that its two arguments are
the input and output disk files instead.  See Pod/Parser,
for the specific details.

DIAGNOSTICS
===========

Invalid link %s
     (W) The POD source contained a `L<>' sequence that Pod::Dsr was
     unable to parse.  You should never see this error message; it probably
     indicates a bug in Pod::Dsr.

Invalid quote specification "%s"
     (F) The quote specification given (the quotes option to the
     constructor) was invalid.  A quote specification must be one, two, or
     four characters long.

%s:%d: Unknown command paragraph "%s".
     (W) The POD source contained a non-standard command paragraph
     (something of the form `=command args') that Pod::Dsr didn't know
     about.  It was ignored.

Unknown escape E<%s>
     (W) The POD source contained an `E<>' escape that Pod::Dsr didn't
     know about.  `E<%s>' was printed verbatim in the output.

Unknown sequence %s
     (W) The POD source contained a non-standard interior sequence
     (something of the form `X<>') that Pod::Dsr didn't know about.  It
     was ignored.

%s: Unknown command paragraph "%s" on line %d.
     (W) The POD source contained a non-standard command paragraph
     (something of the form `=command args') that Pod::Dsr didn't know
     about. It was ignored.

Unmatched =back
     (W) Pod::Man encountered a =back command that didn't correspond to an
     =over command.

BUGS
====

   The lint-like features and strict POD format checking done by pod2man
are not yet implemented and should be, along with the corresponding `lax'
option.

   The NAME section should be recognized specially and index entries
emitted for everything in that section.

   The preamble added to each output file is a bit verbose, and should be
made to be more flexible (e.g. support optional .LAYOUT commands).

   Some of the automagic applied to file names assumes Unix directory
separators.

   Pod::Dsr is excessively slow.

SEE ALSO
========

   `Pod::Parser|Pod::Parser' in this node, perlpod(1), pod2rno(1),
runoff(1), type(1), print(1), DSR(1)

   Please see the file `README.runoff' in the Pod2VMSHlp distribution for
more information on RUNOFF and the DSR language.

   Also, please see pod2man(1) for extensive documentation on writing
manual pages if you've not done it before and aren't familiar with the
conventions.

AUTHOR
======

   Peter Prymmer pvhp@best.com, based *very* heavily on Pod::Man by Russ
Allbery which was in turn based upon the original pod2man by Tom
Christiansen and Larry Wall.

find POD documents in directory trees
*************************************

NAME
====

   Pod::Find - find POD documents in directory trees

SYNOPSIS
========

     use Pod::Find qw(pod_find simplify_name);
     my %pods = pod_find({ -verbose => 1, -inc => 1 });
     foreach(keys %pods) {
        print "found library POD `$pods{$_}' in $_\n";
     }

     print "podname=",simplify_name('a/b/c/mymodule.pod'),"\n";

DESCRIPTION
===========

   *Pod::Find* provides a function *pod_find* that searches for POD
documents in a given set of files and directories. It returns a hash with
the file names as keys and the POD name as value. The POD name is derived
from the file name and its position in the directory tree.

   E.g. when searching in `$HOME/perl5lib', the file
`$HOME/perl5lib/MyModule.pm' would get the POD name *MyModule*, whereas
`$HOME/perl5lib/Myclass/Subclass.pm' would be *Myclass::Subclass*. The
name information can be used for POD translators.

   Only text files containing at least one valid POD command are found.

   A warning is printed if more than one POD file with the same POD name
is found, e.g. `CPAN.pm' in different directories. This usually indicates
duplicate occurrences of modules in the *@INC* search path.

   The function *simplify_name* is equivalent to *basename*, but also
strips Perl-like extensions (.pm, .pl, .pod) and extensions like `.bat',
`.cmd' on Win32 and OS/2, respectively.

   Note that neither *pod_find* nor *simplify_name* are exported by
default so be sure to specify them in the use statement if you need them:

     use Pod::Find qw(pod_find simplify_name);

OPTIONS
=======

   The first argument for *pod_find* may be a hash reference with options.
The rest are either directories that are searched recursively or files.
The POD names of files are the plain basenames with any Perl-like extension
(.pm, .pl, .pod) stripped.

*-verbose*
     Print progress information while scanning.

*-perl*
     Apply Perl-specific heuristics to find the correct PODs. This includes
     stripping Perl-like extensions, omitting subdirectories that are
     numeric but do not match the current Perl interpreter's version id,
     suppressing `site_perl' as a module hierarchy name etc.

*-script*
     Search for PODs in the current Perl interpreter's installation
     *scriptdir*. This is taken from the local `Config|Config' in this
     node module.

*-inc*
     Search for PODs in the current Perl interpreter's *@INC* paths. This
     automatically considers paths specified in the PERL5LIB environment.

AUTHOR
======

   Marek Rouchal <marek@saftsack.fs.uni-bayreuth.de>, heavily borrowing
code from Nick Ing-Simmons' PodToHtml.

SEE ALSO
========

   See Pod/Parser, Pod/Checker,

SYNOPSIS
========

     use Pod::GroveBuilder;
     $grove = Pod::GroveBuilder->new ($sysid);

DESCRIPTION
===========

   `Pod::GroveBuilder' uses Pod::Parser to create SGML::Grove objects.
The resulting SGML::Grove objects can then be used by any module that
supports them, including writing SGML/XML output (SGML::Writer),
formatting the POD to Ascii or HTML (Quilt), or using SGML::Grove
iterators to perform multiple passes over the POD or working with multiple
PODs at the same time.

   `Pod::GroveBuilder->new ($sysid)' creates a grove from a `$sysid', a
`$sysid' may be a file name or a FileHandle object.

   GroveBuilder will build a grove that is hierarchical, for example,
`head2' sections will be contained inside of `head1' sections, and `item'
paragraphs will be contained within lists, etc.

     HEAD1
       "text"
       HEAD2
         LIST
           ITEM
             "text"
           ITEM
             "text"
       HEAD2
        "text"

   See `SGML::Grove' for details on using the grove returned by
`Pod::GroveBuilder'.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), Pod::Parser(3), SGML::Grove(3), SGML::Writer(3), Quilt(3).

translate HTML into POD
***********************

NAME
====

   Pod::HTML2Pod - translate HTML into POD

SYNOPSIS
========

     # Use the program 'html2pod' that comes in this dist, or:
     use Pod::HTML2Pod;
     print Pod::HTML2Pod::convert(
       'file' => 'my_stuff.html',  # input file
       'a_href' => 1,  # try converting links
     );

DESCRIPTION
===========

   Larry Wall once said (1999-08-27, on the `pod-people' list, I do
believe): "The whole point of pod is to get people to document stuff they
wouldn't document in any other form."

   To that end, I wrote this module so that people who are unpracticed
with POD but in a hurry to simply document their programs or modules,
could write their documentation in simple HTML, and convert that to POD.
That's what this module does.

   Specifically, this module bends over backwards to try to turn even
vaguely plausable HTML into POD - and when in doubt, it simply ignores
things that it doesn't know about, or can't render.

FUNCTIONS
=========

   This module provides one documented function, which it does not export:

Pod::HTML2Pod::convert( ...options... )
   This returns a single scalar value containing the converted POD text,
with some comments after the end.

   This function takes options:

'file' => FILENAME,
     Specifies that the HTML code is to be read from the filename given.

'handle' => *HANDLE,
     Specifies that the HTML code is to be read from the open filehandle
     given (e.g., `$fh_obj', `*HANDLE', `*HANDLE{IO}', etc.)  If you
     specify this, but fail to specify an actual handle object, inscrutible
     errors may result.

'content' => STRING,
     Specifies that the HTML code is in the string given.  (Alternately,
     pass a reference to the scalar: `'content' => \$stuff'.)

'tree' => OBJ,
     Specifies that the HTML document is contained in the given
     HTML::TreeBuilder object (or HTML::Element object, at least).

'a_name' => BOOLEAN,
     Specifies whether you want to try converting `<a name="...">'
     elements.  By default this is off - i.e., such elements are ignored.

'a_href' => BOOLEAN,
     Specifies whether you want to try converting `<a href="...">'
     elements.  By default this is off - i.e., such elements are ignored.
     If on, bear in mind that relative URLs cannot be properly converted to
     POD - any relative URLs will be complained about in comments after
     the end of the document.  Normal absolute URLs will be treated as best
     they can be.  Note that URLs beginning "pod:..." will be turned into
     POD links to whatever follows; that is, "pod:Getopt::Std" is turned
     into `L<Getopt::Std>'

'debug' => INTEGER,
     Puts Pod::HTML2Pod into verbose debug mode for the duration of
     processing this this HTML document.  INTEGER can be 0 for no debug
     output, 1 for a moderate amount that will cause the HTML syntax tree
     to be be dumped at the start of the conversion, and 2 for that plus a
     dump of the intermediate POD doctree, plus a few more inscrutible
     diagnostic messages.  Looking at the trees dumped might be helpful in
     making sense of error messages that refer to a particular node in the
     parse tree.

GUIDELINES
==========

   Don't write crappy HTML and expect this module to understand it.

   Don't take the output of pod2html and feed it to this, just because you
think it'd be neat to try it.  You'll just learn really unpleasant things
about Pod::Html - and that's fine if that means you'll use it to improve
Pod::Html, but it's rather the long way around.

   However, do use this module to convert simple HTML into POD, bearing in
mind these simple truths:

   POD can't do tables, images, forms, imagemaps, layers, CSS, embedded
Java applets or any other kind of object, FONT, or BLINK.  So don't try to
do any of these things.

   Use `<h1>' and `<h2>' for headings.

   If you want to have a block of literal example code, put it in a
`<pre>'.

   Keep things simple.

   Remember: Just because it comes out of Pod::HTML2Pod doesn't mean it's
happy normal pod.  You can do lots of things in HTML that will produce POD
that is strange but technically legal (like having huge and complex
content in a `<h1>'/=head1) but that will make perldoc scream bloody
murder about nroff macros stretched past their limit.

   Try to avoid using a WYSIWYG HTML editor, as they often produce scary
source.  Ditto for taking selecting "Save as... HTML" in your word
processor.  You can always try it, but look at the HTML to survey the
damage before you try converting it to POD.

   Always look at the POD that's been output by HTML2Pod - never just
blindly include it.

   Consider starting from this template:

     <html>
     <head>
      <title>Things::Stuff</title>
      <!-- html2pod ignores everything outside the body anyway -->
     </head>
     <body>
     <h1>NAME</h1>

     Things::Stuff -- does some things with stuff

     <h1>SYNOPSIS</h1>
     <!-- example code -->
     <pre>
       use HTML::Stuff;
       do some more stuff;
       la la la la la;
       oogah;
     </pre>

     <h1>DESCRIPTION</h1>

     This module does things with stuff.  It exports these functions:

     <dl>
     <dt><code>thingify( ... )</code>
     <dd>This function takes stuff, and returns their value as things.

     <dt><code>destuffulate( ... )</code>
     <dd>This function returns the things, from stuff.
      <p>It will throw a fatal exception if applied to things.
      <br>So don't do that.

     <dt><code>enthinction( ... )</code>
     <dd>This is where I run out of ways to make up silly sentences
      involving "thing" and "stuff".  Mostly.

     </dl>

     <h2>Caveats and WYA's</h2>

     Things to be wary of:

     <ul>
     <li>The things.
     <li>And the stuff
      <p>Don't forget about that stuff.  Gotta keep an eye on that.
     </ul>

     <h1>BUGS</h1>

     Stuff is hard.

     <h1>SEE ALSO</h1>

     <a href="pod:Class::Classless">Class::Classless</a>,
     <a href="pod:strict">strict</a>,
     <a href="pod:Lingua::EN::Numbers::Ordinate"
      >Lingua::EN::Numbers::Ordinate</a>,
     <a href="pod:perlvar">perlvar</a>,

     <!-- I use the secret-sauce 'pod:' scheme as a back door for making
      simple cross-references to POD man pages -->

     <h1>COPYRIGHT</h1>

     Copyright 2000, Joey Jo-Jo Jr. Shabadoo.

     <!-- just one suggested phrasing for the license... -->
     <p>This library is free software; you can redistribute it and/or modify
     it under the same terms as Perl itself.

     <h1>AUTHOR</h1>
     Joey Jo-Jo Jr. Shabadoo, <code>jojojo@shabadoo.int</code>
     </body>
     </html>

BUG REPORTS
===========

   If you do find a case where this converter misinterprets what you
consider straightforward HTML (which you should really really have run
thru an HTML syntax checker, by the way!), report it to me as a bug, at
`sburke@cpan.org'.

   Be sure to include the entire document that causes the error - then
specify exactly what you consider the error to be.

BUGS AND CAVEATS
================

   * Doesn't try to turn "smart quotes" characters into simple " and '.
Maybe should?

   * Fails to turn

     foo thing&nbsp;bar&nbsp;baz quux

   into

     foo S<thing bar baz> quux

   I.e., currently just turns `&nbsp;''s into normal spaces.

   * Numeric entities (`E<num>') are used when necessary - but these are
not understood by some older POD converters.

   * No HTML that you provide will turn into `F<...>'

   * Currently maps

     <A HREF="foo">bar</A>

   to

     X<foo>bar

   but is this correct?

SEE ALSO
========

   See Perlpod (perl.info), Pod/Html,
HTML/TreeBuilder,

   And HTML Tidy, at `http://www.w3.org/People/Raggett/tidy/'

COPYRIGHT
=========

   Copyright (c) 2000 Sean M. Burke. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Sean M. Burke `sburke@cpan.org'

Convert POD to tree of LWP's HTML::Element and hence HTML or PostScript
***********************************************************************

NAME
====

   Pod::HTML_Elements - Convert POD to tree of LWP's HTML::Element and
hence HTML or PostScript

SYNOPSIS
========

     use Pod::HTML_Elements;

     my $parser = new Pod::HTML_Elements;
     $parser->parse_from_file($pod,'foo.html');

     my $parser = new Pod::HTML_Elements PostScript => 1;
     $parser->parse_from_file($pod,'foo.ps');

DESCRIPTION
===========

   *Pod::HTML_Elements* is subclass of `*Pod::Parser* in this node'. As
the pod is parsed a tree of *See HTML/Element,* objects is
built to represent HTML for the pod.

   At the end of each pod HTML or PostScript representation is written to
the output file.

BUGS
====

   Parameter pass-through to HTML/FormatPS, needs to
be implemented.

SEE ALSO
========

   See Perlpod (perl.info), Pod/Parser,
HTML/Element, HTML/FormatPS,

AUTHOR
======

   Nick Ing-Simmons <nick@ni-s.u-net.com>

convert POD data to formatted VMS HLP Help module text.
*******************************************************

NAME
====

   Pod::Hlp - convert POD data to formatted VMS HLP Help module text.

SYNOPSIS
========

     use Pod::Hlp;

     pod2hlp("perlfunc.pod",$top_help_level,*Filehandle);

   Also:

     pod2hlp < input.pod

   Also:

     perl pod2hlb

DESCRIPTION
===========

   Pod::Hlp is a module that can convert documentation in the POD format
(such as can be found throughout the Perl distribution) into formatted VMS
`*.HLP' files.  Such files can be inserted into an .HLB library through
the `LIBRARY/HELP/REPLACE' system call, or via the use of the `pod2hlb'
script supplied with the kit.  A separate `pod2hlp' program is included
that is primarily a wrapper for Pod::Hlp.

   The single function `pod2hlp()' can take one, two, or three arguments.
The first should be the name of a file to read the pod from, or "<&STDIN"
to read from STDIN.   A second argument, if provided, should be an integer
indicating the help header level of the file as a whole where `'1'' is the
default.  A third argument, if provided, should be a filehandle glob where
output should be sent.

AUTHOR
======

   Peter Prymmer <pvhp@best.com>

   based heavily on Pod::Text by:

   Tom Christiansen <tchrist@mox.perl.com>

TODO
====

   Cleanup work.  VT escapes should be substituted for the Term::Cap ones.
The input and output locations need to be more flexible.

module to convert pod files to HTML
***********************************

NAME
====

   Pod::Html - module to convert pod files to HTML

SYNOPSIS
========

     use Pod::Html;
     pod2html([options]);

DESCRIPTION
===========

   Converts files from pod format (see Perlpod (perl.info))
to HTML format.  It can automatically generate indexes and
cross-references, and it keeps a cache of things it knows how to
cross-reference.

ARGUMENTS
=========

   Pod::Html takes the following arguments:

backlink
          --backlink="Back to Top"

     Adds "Back to Top" links in front of every HEAD1 heading (except for
     the first).  By default, no backlink are being generated.

css
          --css=stylesheet

     Specify the URL of a cascading style sheet.

flush
          --flush

     Flushes the item and directory caches.

header
          --header
          --noheader

     Creates header and footer blocks containing the text of the NAME
     section.  By default, no headers are being generated.

help
          --help

     Displays the usage message.

htmldir
          --htmldir=name

     Sets the directory in which the resulting HTML file is placed.  This
     is used to generate relative links to other files. Not passing this
     causes all links to be absolute, since this is the value that tells
     Pod::Html the root of the documentation tree.

htmlroot
          --htmlroot=name

     Sets the base URL for the HTML files.  When cross-references are made,
     the HTML root is prepended to the URL.

index
          --index
          --noindex

     Generate an index at the top of the HTML file.  This is the default
     behaviour.

infile
          --infile=name

     Specify the pod file to convert.  Input is taken from STDIN if no
     infile is specified.

libpods
          --libpods=name:...:name

     List of page names (eg, "perlfunc") which contain linkable =items.

netscape
          --netscape
          --nonetscape

     Use Netscape HTML directives when applicable.  By default, they will
     not be used.

outfile
          --outfile=name

     Specify the HTML file to create.  Output goes to STDOUT if no outfile
     is specified.

podpath
          --podpath=name:...:name

     Specify which subdirectories of the podroot contain pod files whose
     HTML converted forms can be linked-to in cross-references.

podroot
          --podroot=name

     Specify the base directory for finding library pods.

quiet
          --quiet
          --noquiet

     Don't display *mostly harmless* warning messages.  These messages
     will be displayed by default.  But this is not the same as verbose
     mode.

recurse
          --recurse
          --norecurse

     Recurse into subdirectories specified in podpath (default behaviour).

title
          --title=title

     Specify the title of the resulting HTML file.

verbose
          --verbose
          --noverbose

     Display progress messages.  By default, they won't be displayed.

EXAMPLE
=======

     pod2html("pod2html",
     	     "--podpath=lib:ext:pod:vms",
     	     "--podroot=/usr/src/perl",
     	     "--htmlroot=/perl/nmanual",
     	     "--libpods=perlfunc:perlguts:perlvar:perlrun:perlop",
     	     "--recurse",
     	     "--infile=foo.pod",
     	     "--outfile=/perl/nmanual/foo.html");

ENVIRONMENT
===========

   Uses $Config{pod2html} to setup default options.

AUTHOR
======

   Tom Christiansen, <tchrist@perl.com>.

SEE ALSO
========

   See Perlpod (perl.info),

COPYRIGHT
=========

   This program is distributed under the Artistic License.

documentation projects builder in HTML, PS and PDF formats
**********************************************************

NAME
====

   Pod::HtmlPsPdf - documentation projects builder in HTML, PS and PDF
formats

SYNOPSIS
========

     pod2hpp [options] configuration_file_location

   Options:

     -h    this help
     -v    verbose
     -i    podify pseudo-pod items (s/^* /=item */)
     -s    create the splitted html version
     -t    create tar.gz
     -p    generate PS file
     -d    generate PDF file
     -f    force a complete rebuild
     -a    print available hypertext anchors
     -l    do hypertext links validation
     -e    slides mode (for presentations)
     -m    executed from Makefile (forces rebuild,
     				no PS/PDF file,
     				no tgz archive!)

DESCRIPTION
===========

   This code knows to do following with a collection of your POD files.

  1. Generate HTMLs

  2. Generate a split version HTML, creating html file for each pod
     section, and having everything interlinked of course. This version is
     used best for the search.

  3. Generate a single book-like version in PostScript format

  4. Generate a single book-like version in PDF format

  5. Complete the POD on the fly from the files in POD format. This is used
     to ease the generating of the presentations slides, so one can use *
     instead of a long =over/=item/.../=item/=back strings. The rest is
     done as before. Take a look at the special version of the html2ps
     format to generate nice slides in *conf/html2ps-slides.conf*.

  6. If you turn the slides mode on, it automatically turns the -i (*
     preprocessing) mode and does a page break before each =head tag.

        You can customise the look and feel of the HTML files, PS and
therefore the PDF by tweaking the template files in *./tmpl* directory.

   You can change look and feel of the PS (PDF) versions by modifying
*./conf/html2ps.conf*.  Be careful that if your documentation that you
want to put in one PS or PDF file is very big and you tell html2ps to put
the TOC at the beginning you will need lots of memory because it won't
write a single byte to the disk before it gets all the HTML markup
converted to PS.

   To generate HTML this code use a slightly modified version of the
Pod::Html code and than does a lot of massage on the resulting HTML. I've
tried to keep the pod2html code modified as little as possible, so when a
new versions of the original Pod::Html module will be released I'll be
able to merge the changes with my version.

EXTENDED POD SYNTAX
===================

   I've extended the POD syntax to accomodate my own needs. Note that this
can be always converted back to the standard POD. To see the extended
syntax, refer to the *docs/extended_pod.pod* in the package distribution.

CONFIGURATION
=============

   All you have to prepare is a single config file that you then pass as
an argument to `pod2hpp':

     pod2hpp [options] /full/path/to/config/file

   Use the file *project.config* supplied in the directory sample. Modify
it to be suit your documentation project layout.

   Note that *sample/bin/build* script automatically locates your
project's directory, so you can move your project around filesystem
without changing anything.

   *sample/README.sample* explains the layout of the directories. The
easiest way to learn to use this package is to look at the
`Apache::mod_perl_guide' package available at CPAN. I've developed the
package `Pod::HtmlPsPdf' especially for `Apache::mod_perl_guide'.

PREREQUISITES
=============

   All these are not required if all you want is to generate only the html
version.

   * ps2pdf

     Needed to generate the PDF version

   * Storable

     Perl module available from CPAN (http://cpan.org/)

     Allows source modification control, so if you modify only one file you
     will not have to rebuild everything to get the updated HTML/PS/PDF
     files.

SUPPORT
=======

   Notice that this tool relies on two tools (ps2pdf and html2ps) which I
don't support. So if you have any problem first make sure that it's not a
problem of these tools.

   Note that while `html2ps' is included in this distribution, it's
written in the old style Perl, so if you have patches send them along, but
I won't try to fix/modify this code otherwise. I didn't write this utility.

   This package works for me on Linux RedHat and Mandrake systems. I
release it only to share. Unfortunately I don't have time to help with
each available platform.  If you have a problem, please don't contact me.
I'm not going to solve it. If you solve the problem, I'll gladly accept
the patch for others to benefit. Remember that this is a free software.

BUGS
====

   Huh? Probably many...

AUTHOR
======

   Stas Bekman <stas@stason.org>

SEE ALSO
========

   perl(1), Pod::HTML(3), html2ps(1), ps2pod(1), Storable(3)

COPYRIGHT
=========

   This program is distributed under the Artistic License, like the Perl
itself.

module to convert pod files to HTML
***********************************

NAME
====

   Pod::Html - module to convert pod files to HTML

SYNOPSIS
========

     use Pod::Html;
     pod2html([options]);

DESCRIPTION
===========

   Converts files from pod format (see Perlpod (perl.info))
to HTML format.  It can automatically generate indexes and
cross-references, and it keeps a cache of things it knows how to
cross-reference.

ARGUMENTS
=========

   Pod::Html takes the following arguments:

help
          --help

     Displays the usage message.

htmlroot
          --htmlroot=name

     Sets the base URL for the HTML files.  When cross-references are made,
     the HTML root is prepended to the URL.

infile
          --infile=name

     Specify the pod file to convert.  Input is taken from STDIN if no
     infile is specified.

outfile
          --outfile=name

     Specify the HTML file to create.  Output goes to STDOUT if no outfile
     is specified.

podroot
          --podroot=name

     Specify the base directory for finding library pods.

podpath
          --podpath=name:...:name

     Specify which subdirectories of the podroot contain pod files whose
     HTML converted forms can be linked-to in cross-references.

libpods
          --libpods=name:...:name

     List of page names (eg, "perlfunc") which contain linkable =items.

netscape
          --netscape

     Use Netscape HTML directives when applicable.

nonetscape
          --nonetscape

     Do not use Netscape HTML directives (default).

index
          --index

     Generate an index at the top of the HTML file (default behaviour).

noindex
          --noindex

     Do not generate an index at the top of the HTML file.

recurse
          --recurse

     Recurse into subdirectories specified in podpath (default behaviour).

norecurse
          --norecurse

     Do not recurse into subdirectories specified in podpath.

title
          --title=title

     Specify the title of the resulting HTML file.

verbose
          --verbose

     Display progress messages.

EXAMPLE
=======

     pod2html("pod2html",
     	     "--podpath=lib:ext:pod:vms",
     	     "--podroot=/usr/src/perl",
     	     "--htmlroot=/perl/nmanual",
     	     "--libpods=perlfunc:perlguts:perlvar:perlrun:perlop",
     	     "--recurse",
     	     "--infile=foo.pod",
     	     "--outfile=/perl/nmanual/foo.html");

AUTHOR
======

   Originally written by Tom Christiansen, <tchrist@perl.com>.

   Modified by Stas Bekman <stas@stason.org>.

BUGS
====

   Has trouble with  etc in = commands.

SEE ALSO
========

   See Perlpod (perl.info),

COPYRIGHT
=========

   This program is distributed under the Artistic License.

objects representing POD input paragraphs, commands, etc.
*********************************************************

NAME
====

   Pod::InputObjects - objects representing POD input paragraphs,
commands, etc.

SYNOPSIS
========

     use Pod::InputObjects;

REQUIRES
========

   perl5.004, Carp

EXPORTS
=======

   Nothing.

DESCRIPTION
===========

   This module defines some basic input objects used by Pod::Parser when
reading and parsing POD text from an input source. The following objects
are defined:

Pod::InputSource
     An object corresponding to a source of POD input text. It is mostly a
     wrapper around a filehandle or IO::Handle-type object (or anything
     that implements the `getline()' method) which keeps track of some
     additional information relevant to the parsing of PODs.

Pod::Paragraph
     An object corresponding to a paragraph of POD input text. It may be a
     plain paragraph, a verbatim paragraph, or a command paragraph (see
     Perlpod (perl.info)).

Pod::InteriorSequence
     An object corresponding to an interior sequence command from the POD
     input text (see Perlpod (perl.info)).

Pod::ParseTree
     An object corresponding to a tree of parsed POD text. Each "node" in
     a parse-tree (or *ptree*) is either a text-string or a reference to a
     Pod::InteriorSequence object. The nodes appear in the parse-tree in
     they order in which they were parsed from  left-to-right.

   Each of these input objects are described in further detail in the
sections which follow.

Pod::InputSource
================

   This object corresponds to an input source or stream of POD
documentation. When parsing PODs, it is necessary to associate and store
certain context information with each input source. All of this
information is kept together with the stream itself in one of these
Pod::InputSource objects. Each such object is merely a wrapper around an
IO::Handle object of some kind (or at least something that implements the
`getline()' method). They have the following methods/attributes:

new()
-----

     my $pod_input1 = Pod::InputSource->new(-handle => $filehandle);
     my $pod_input2 = new Pod::InputSource(-handle => $filehandle,
                                           -name   => $name);
     my $pod_input3 = new Pod::InputSource(-handle => \*STDIN);
     my $pod_input4 = Pod::InputSource->new(-handle => \*STDIN,
                                            -name => "(STDIN)");

   This is a class method that constructs a Pod::InputSource object and
returns a reference to the new input source object. It takes one or more
keyword arguments in the form of a hash. The keyword `-handle' is required
and designates the corresponding input handle. The keyword `-name' is
optional and specifies the name associated with the input handle
(typically a file name).

name()
------

     my $filename = $pod_input->name();
     $pod_input->name($new_filename_to_use);

   This method gets/sets the name of the input source (usually a filename).
If no argument is given, it returns a string containing the name of the
input source; otherwise it sets the name of the input source to the
contents of the given argument.

handle()
--------

     my $handle = $pod_input->handle();

   Returns a reference to the handle object from which input is read (the
one used to contructed this input source object).

was_cutting()
-------------

     print "Yes.\n" if ($pod_input->was_cutting());

   The value of the `cutting' state (that the cutting() method would have
returned) immediately before any input was read from this input stream.
After all input from this stream has been read, the `cutting' state is
restored to this value.

Pod::Paragraph
==============

   An object representing a paragraph of POD input text.  It has the
following methods/attributes:

new()
-----

     my $pod_para1 = Pod::Paragraph->new(-text => $text);
     my $pod_para2 = Pod::Paragraph->new(-name => $cmd,
                                         -text => $text);
     my $pod_para3 = new Pod::Paragraph(-text => $text);
     my $pod_para4 = new Pod::Paragraph(-name => $cmd,
                                        -text => $text);
     my $pod_para5 = Pod::Paragraph->new(-name => $cmd,
                                         -text => $text,
                                         -file => $filename,
                                         -line => $line_number);

   This is a class method that constructs a Pod::Paragraph object and
returns a reference to the new paragraph object. It may be given one or
two keyword arguments. The `-text' keyword indicates the corresponding
text of the POD paragraph. The `-name' keyword indicates the name of the
corresponding POD command, such as head1 or item (it should not contain
the = prefix); this is needed only if the POD paragraph corresponds to a
command paragraph. The `-file' and `-line' keywords indicate the filename
and line number corresponding to the beginning of the paragraph

cmd_name()
----------

     my $para_cmd = $pod_para->cmd_name();

   If this paragraph is a command paragraph, then this method will return
the name of the command (*without* any leading = prefix).

text()
------

     my $para_text = $pod_para->text();

   This method will return the corresponding text of the paragraph.

raw_text()
----------

     my $raw_pod_para = $pod_para->raw_text();

   This method will return the raw text of the POD paragraph, exactly as
it appeared in the input.

cmd_prefix()
------------

     my $prefix = $pod_para->cmd_prefix();

   If this paragraph is a command paragraph, then this method will return
the prefix used to denote the command (which should be the string "=" or
"==").

cmd_separator()
---------------

     my $separator = $pod_para->cmd_separator();

   If this paragraph is a command paragraph, then this method will return
the text used to separate the command name from the rest of the paragraph
(if any).

parse_tree()
------------

     my $ptree = $pod_parser->parse_text( $pod_para->text() );
     $pod_para->parse_tree( $ptree );
     $ptree = $pod_para->parse_tree();

   This method will get/set the corresponding parse-tree of the
paragraph's text.

file_line()
-----------

     my ($filename, $line_number) = $pod_para->file_line();
     my $position = $pod_para->file_line();

   Returns the current filename and line number for the paragraph object.
If called in an array context, it returns a list of two elements: first
the filename, then the line number. If called in a scalar context, it
returns a string containing the filename, followed by a colon (':'),
followed by the line number.

Pod::InteriorSequence
=====================

   An object representing a POD interior sequence command.  It has the
following methods/attributes:

new()
-----

     my $pod_seq1 = Pod::InteriorSequence->new(-name => $cmd
                                               -ldelim => $delimiter);
     my $pod_seq2 = new Pod::InteriorSequence(-name => $cmd,
                                              -ldelim => $delimiter);
     my $pod_seq3 = new Pod::InteriorSequence(-name => $cmd,
                                              -ldelim => $delimiter,
                                              -file => $filename,
                                              -line => $line_number);

     my $pod_seq4 = new Pod::InteriorSequence(-name => $cmd, $ptree);
     my $pod_seq5 = new Pod::InteriorSequence($cmd, $ptree);

   This is a class method that constructs a Pod::InteriorSequence object
and returns a reference to the new interior sequence object. It should be
given two keyword arguments.  The `-ldelim' keyword indicates the
corresponding left-delimiter of the interior sequence (e.g. '<').  The
`-name' keyword indicates the name of the corresponding interior sequence
command, such as I or B or C. The `-file' and `-line' keywords indicate
the filename and line number corresponding to the beginning of the
interior sequence. If the `$ptree' argument is given, it must be the last
argument, and it must be either string, or else an array-ref suitable for
passing to *Pod::ParseTree::new* (or it may be a reference to an
Pod::ParseTree object).

cmd_name()
----------

     my $seq_cmd = $pod_seq->cmd_name();

   The name of the interior sequence command.

prepend()
---------

     $pod_seq->prepend($text);
     $pod_seq1->prepend($pod_seq2);

   Prepends the given string or parse-tree or sequence object to the
parse-tree of this interior sequence.

append()
--------

     $pod_seq->append($text);
     $pod_seq1->append($pod_seq2);

   Appends the given string or parse-tree or sequence object to the
parse-tree of this interior sequence.

nested()
--------

     $outer_seq = $pod_seq->nested || print "not nested";

   If this interior sequence is nested inside of another interior
sequence, then the outer/parent sequence that contains it is returned.
Otherwise undef is returned.

raw_text()
----------

     my $seq_raw_text = $pod_seq->raw_text();

   This method will return the raw text of the POD interior sequence,
exactly as it appeared in the input.

left_delimiter()
----------------

     my $ldelim = $pod_seq->left_delimiter();

   The leftmost delimiter beginning the argument text to the interior
sequence (should be "<").

right_delimiter()
-----------------

   The rightmost delimiter beginning the argument text to the interior
sequence (should be ">").

parse_tree()
------------

     my $ptree = $pod_parser->parse_text($paragraph_text);
     $pod_seq->parse_tree( $ptree );
     $ptree = $pod_seq->parse_tree();

   This method will get/set the corresponding parse-tree of the interior
sequence's text.

file_line()
-----------

     my ($filename, $line_number) = $pod_seq->file_line();
     my $position = $pod_seq->file_line();

   Returns the current filename and line number for the interior sequence
object.  If called in an array context, it returns a list of two elements:
first the filename, then the line number. If called in a scalar context,
it returns a string containing the filename, followed by a colon (':'),
followed by the line number.

DESTROY()
---------

   This method performs any necessary cleanup for the interior-sequence.
If you override this method then it is *imperative* that you invoke the
parent method from within your own method, otherwise *interior-sequence
storage will not be reclaimed upon destruction!*

Pod::ParseTree
==============

   This object corresponds to a tree of parsed POD text. As POD text is
scanned from left to right, it is parsed into an ordered list of
text-strings and Pod::InteriorSequence objects (in order of appearance). A
Pod::ParseTree object corresponds to this list of strings and sequences.
Each interior sequence in the parse-tree may itself contain a parse-tree
(since interior sequences may be nested).

new()
-----

     my $ptree1 = Pod::ParseTree->new;
     my $ptree2 = new Pod::ParseTree;
     my $ptree4 = Pod::ParseTree->new($array_ref);
     my $ptree3 = new Pod::ParseTree($array_ref);

   This is a class method that constructs a `Pod::Parse_tree' object and
returns a reference to the new parse-tree. If a single-argument is given,
it must be a reference to an array, and is used to initialize the root
(top) of the parse tree.

top()
-----

     my $top_node = $ptree->top();
     $ptree->top( $top_node );
     $ptree->top( @children );

   This method gets/sets the top node of the parse-tree. If no arguments
are given, it returns the topmost node in the tree (the root), which is
also a Pod::ParseTree. If it is given a single argument that is a
reference, then the reference is assumed to a parse-tree and becomes the
new top node.  Otherwise, if arguments are given, they are treated as the
new list of children for the top node.

children()
----------

   This method gets/sets the children of the top node in the parse-tree.
If no arguments are given, it returns the list (array) of children (each
of which should be either a string or a Pod::InteriorSequence.  Otherwise,
if arguments are given, they are treated as the new list of children for
the top node.

prepend()
---------

   This method prepends the given text or parse-tree to the current
parse-tree.  If the first item on the parse-tree is text and the argument
is also text, then the text is prepended to the first item (not added as a
separate string).  Otherwise the argument is added as a new string or
parse-tree before the current one.

append()
--------

   This method appends the given text or parse-tree to the current
parse-tree.  If the last item on the parse-tree is text and the argument
is also text, then the text is appended to the last item (not added as a
separate string).  Otherwise the argument is added as a new string or
parse-tree after the current one.

raw_text()
----------

     my $ptree_raw_text = $ptree->raw_text();

   This method will return the raw text of the POD parse-tree exactly as
it appeared in the input.

DESTROY()
---------

   This method performs any necessary cleanup for the parse-tree.  If you
override this method then it is *imperative* that you invoke the parent
method from within your own method, otherwise *parse-tree storage will not
be reclaimed upon destruction!*

SEE ALSO
========

   See Pod/Parser, Pod/Select,

AUTHOR
======

   Brad Appleton <bradapp@enteract.com>

Convert Pod data to formatted Latex
***********************************

NAME
====

   Pod::LaTeX - Convert Pod data to formatted Latex

SYNOPSIS
========

     use Pod::LaTeX;
     my $parser = Pod::LaTeX->new ( );

     $parser->parse_from_filehandle;

     $parser->parse_from_file ('file.pod', 'file.tex');

DESCRIPTION
===========

   `Pod::LaTeX' is a module to convert documentation in the Pod format
into Latex. The `*pod2latex* in this node|pod2latex' X<pod2latex> command
uses this module for translation.

   `Pod::LaTeX' is a derived class from `Pod::Select|Pod::Select' in this
node.

OBJECT METHODS
==============

   The following methods are provided in this module. Methods inherited
from Pod::Select are not described in the public interface.

initialize
     Initialise the object. This method is subclassed from Pod::Parser.
     The base class method is invoked. This method defines the default
     behaviour of the object unless overridden by supplying arguments to
     the constructor.

     Internal settings are defaulted as well as the public instance data.
     Internal hash values are accessed directly (rather than through a
     method) and start with an underscore.

     This method should not be invoked by the user directly.

Data Accessors
--------------

   The following methods are provided for accessing instance data. These
methods should be used for accessing configuration parameters rather than
assuming the object is a hash.

   Default values can be supplied by using these names as keys to a hash
of arguments when using the new() constructor.

AddPreamble
     Logical to control whether a latex preamble is to be written.  If
     true, a valid latex preamble is written before the pod data is
     written.  This is similar to:

          \documentclass{article}
          \begin{document}

     but will be more complicated if table of contents and indexing are
     required.  Can be used to set or retrieve the current value.

          $add = $parser->AddPreamble();
          $parser->AddPreamble(1);

     If used in conjunction with AddPostamble a full latex document will
     be written that could be immediately processed by latex.

AddPostamble
     Logical to control whether a standard latex ending is written to the
     output file after the document has been processed.  In its simplest
     form this is simply:

          \end{document}

     but can be more complicated if a index is required.  Can be used to
     set or retrieve the current value.

          $add = $parser->AddPostamble();
          $parser->AddPostamble(1);

     If used in conjunction with `AddPreaamble' a full latex document will
     be written that could be immediately processed by latex.

Head1Level
     The latex sectioning level that should be used to correspond to a pod
     =head1 directive. This can be used, for example, to turn a =head1
     into a latex `subsection'. This should hold a number corresponding to
     the required position in an array containing the following elements:

          [0] chapter
          [1] section
          [2] subsection
          [3] subsubsection
          [4] paragraph
          [5] subparagraph

     Can be used to set or retrieve the current value:

          $parser->Head1Level(2);
          $sect = $parser->Head1Level;

     Setting this number too high can result in sections that may not be
     reproducible in the expected way. For example, setting this to 4
     would imply that `=head3' do not have a corresponding latex section
     (=head1 would correspond to a `paragraph').

     A check is made to ensure that the supplied value is an integer in the
     range 0 to 5.

     Default is for a value of 1 (i.e. a section).

Label
     This is the label that is prefixed to all latex label and index
     entries to make them unique. In general, pods have similarly titled
     sections (NAME, DESCRIPTION etc) and a latex label will be multiply
     defined if more than one pod document is to be included in a single
     latex file. To overcome this, this label is prefixed to a label
     whenever a label is required (joined with an underscore) or to an
     index entry (joined by an exclamation mark which is the normal index
     separator). For example, `\label{text}' becomes `\label{Label_text}'.

     Can be used to set or retrieve the current value:

          $label = $parser->Label;
          $parser->Label($label);

     This label is only used if UniqueLabels is true.  Its value is set
     automatically from the NAME field if ReplaceNAMEwithSection is true.
     If this is not the case it must be set manually before starting the
     parse.

     Default value is undef.

LevelNoNum
     Control the point at which latex section numbering is turned off.
     For example, this can be used to make sure that latex sections are
     numbered but subsections are not.

     Can be used to set or retrieve the current value:

          $lev = $parser->LevelNoNum;
          $parser->LevelNoNum(2);

     The argument must be an integer between 0 and 5 and is the same as the
     number described in Head1Level method description. The number has
     nothing to do with the pod heading number, only the latex sectioning.

     Default is 2. (i.e. latex subsections are written as `subsection*'
     but sections are numbered).

MakeIndex
     Controls whether latex commands for creating an index are to be
     inserted into the preamble and postamble

          $makeindex = $parser->MakeIndex;
          $parser->MakeIndex(0);

     Irrelevant if both AddPreamble and AddPostamble are false (or
     equivalently, UserPreamble and UserPostamble are set).

     Default is for an index to be created.

ReplaceNAMEwithSection
     This controls whether the NAME section in the pod is to be translated
     literally or converted to a slightly modified output where the section
     name is the pod name rather than "NAME".

     If true, the pod segment

          =head1 NAME

          pod::name - purpose

          =head1 SYNOPSIS

     is converted to the latex

          \section{pod::name\label{pod_name}\index{pod::name}}

          Purpose

          \subsection*{SYNOPSIS\label{pod_name_SYNOPSIS}%
                       \index{pod::name!SYNOPSIS}}

     (dependent on the value of Head1Level and LevelNoNum). Note that
     subsequent head1 directives translate to subsections rather than
     sections and that the labels and index now include the pod name
     (dependent on the value of UniqueLabels).

     The Label is set from the pod name regardless of any current value of
     Label.

          $mod = $parser->ReplaceNAMEwithSection;
          $parser->ReplaceNAMEwithSection(0);

     Default is to translate the pod literally.

StartWithNewPage
     If true, each pod translation will begin with a latex `\clearpage'.

          $parser->StartWithNewPage(1);
          $newpage = $parser->StartWithNewPage;

     Default is false.

TableOfContents
     If true, a table of contents will be created.  Irrelevant if
     AddPreamble is false or UserPreamble is set.

          $toc = $parser->TableOfContents;
          $parser->TableOfContents(1);

     Default is false.

UniqueLabels
     If true, the translator will attempt to make sure that each latex
     label or index entry will be uniquely identified by prefixing the
     contents of Label. This allows multiple documents to be combined
     without clashing common labels such as DESCRIPTION and SYNOPSIS

          $parser->UniqueLabels(1);
          $unq = $parser->UniqueLabels;

     Default is true.

UserPreamble
     User supplied latex preamble. Added before the pod translation data.

     If set, the contents will be prepended to the output file before the
     translated data regardless of the value of AddPreamble.  MakeIndex
     and TableOfContents will also be ignored.

UserPostamble
     User supplied latex postamble. Added after the pod translation data.

     If set, the contents will be prepended to the output file after the
     translated data regardless of the value of AddPostamble.  MakeIndex
     will also be ignored.

Lists
     Contains details of the currently active lists.    The array contains
     Pod::List objects. A new Pod::List object is created each time a list
     is encountered and it is pushed onto this stack. When the list
     context ends, it is popped from the stack. The array will be empty if
     no lists are active.

     Returns array of list information in list context Returns array ref
     in scalar context

Subclassed methods
------------------

   The following methods override methods provided in the Pod::Select base
class. See Pod::Parser and Pod::Select for more information on what these
methods require.

begin_pod
     Writes the latex preamble if requested.

end_pod
     Write the closing latex code.

command
     Process basic pod commands.

verbatim
     Verbatim text

textblock
     Plain text paragraph.

interior_sequence
     Interior sequence expansion

List Methods
------------

   Methods used to handle lists.

begin_list
     Called when a new list is found (via the over directive).  Creates a
     new Pod::List object and stores it on the list stack.

          $parser->begin_list($indent, $line_num);

end_list
     Called when the end of a list is found (the back directive).  Pops
     the Pod::List object off the stack of lists and writes the latex code
     required to close a list.

          $parser->end_list($line_num);

add_item
     Add items to the list. The first time an item is encountered
     (determined from the state of the current Pod::List object) the type
     of list is determined (ordered, unnumbered or description) and the
     relevant latex code issued.

          $parser->add_item($paragraph, $line_num);

Methods for headings
--------------------

head
     Print a heading of the required level.

          $parser->head($level, $paragraph, $parobj);

     The first argument is the pod heading level. The second argument is
     the contents of the heading. The 3rd argument is a Pod::Paragraph
     object so that the line number can be extracted.

Internal methods
----------------

   Internal routines are described in this section. They do not form part
of the public interface. All private methods start with an underscore.

_output
     Output text to the output filehandle. This method must be always be
     called to output parsed text.

          $parser->_output($text);

     Does not write anything if a =begin or =for is active that should be
     ignored.

_replace_special_chars
     Subroutine to replace characters that are special in latex with the
     escaped forms

          $escaped = $parser->_replace_special_chars($paragraph);

     Need to call this routine before interior_sequences are munged but
     not if verbatim.

     Special characters and the latex equivalents are:

          }     \}
          {     \{
          _     \_
          $     \$
          %     \%
          &     \&
          \     $\backslash$
          ^     \^{}
          ~     \~{}
          |     $|$

_create_label
     Return a string that can be used as an internal reference in a latex
     document (i.e. accepted by the `\label' command)

          $label = $parser->_create_label($string)

     If UniqueLabels is true returns a label prefixed by Label() This can
     be suppressed with an optional second argument.

          $label = $parser->_create_label($string, $suppress);

     If a second argument is supplied (of any value including undef) the
     Label() is never prefixed. This means that this routine can be called
     to create a Label() without prefixing a previous setting.

_create_index
     Similar to _create_label except an index entry is created.  If
     UniqueLabels is true, the index entry is prefixed by the current
     Label and an exclamation mark.

          $ind = $parser->_create_index($paragraph);

     An exclamation mark is used by `makeindex' to generate sub-entries in
     an index.

_clean_latex_commands
     Removes latex commands from text. The latex command is assumed to be
     of the form `\command{ text }'. "text" is retained

          $clean = $parser->_clean_latex_commands($text);

NOTES
=====

   Compatible with `latex2e' only. Can not be used with latex v2.09 or
earlier.

   A subclass of Pod::Select so that specific pod sections can be
converted to latex by using the select method.

   Some HTML escapes are missing and many have not been tested.

SEE ALSO
========

   See Pod/Parser, Pod/Select,
`pod2latex' in this node

AUTHORS
=======

   Tim Jenness <t.jenness@jach.hawaii.edu>

COPYRIGHT
=========

   Copyright (C) 2000 Tim Jenness. All Rights Reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

REVISION
========

   $Id: LaTeX.pm,v 1.6 2000/08/21 09:05:03 timj Exp $

Convert POD data to formatted *roff input
*****************************************

NAME
====

   Pod::Man - Convert POD data to formatted *roff input

SYNOPSIS
========

     use Pod::Man;
     my $parser = Pod::Man->new (release => $VERSION, section => 8);

     # Read POD from STDIN and write to STDOUT.
     $parser->parse_from_filehandle;

     # Read POD from file.pod and write to file.1.
     $parser->parse_from_file ('file.pod', 'file.1');

DESCRIPTION
===========

   Pod::Man is a module to convert documentation in the POD format (the
preferred language for documenting Perl) into *roff input using the man
macro set.  The resulting *roff code is suitable for display on a terminal
using nroff(1), normally via man(1), or printing using troff(1).  It is
conventionally invoked using the driver script pod2man, but it can also be
used directly.

   As a derived class from Pod::Parser, Pod::Man supports the same methods
and interfaces.  See Pod/Parser, for all the details;
briefly, one creates a new parser with `Pod::Man->new()' and then calls
either parse_from_filehandle() or parse_from_file().

   new() can take options, in the form of key/value pairs that control the
behavior of the parser.  See below for details.

   If no options are given, Pod::Man uses the name of the input file with
any trailing `.pod', `.pm', or `.pl' stripped as the man page title, to
section 1 unless the file ended in `.pm' in which case it defaults to
section 3, to a centered title of "User Contributed Perl Documentation", to
a centered footer of the Perl version it is run with, and to a left-hand
footer of the modification date of its input (or the current date if given
STDIN for input).

   Pod::Man assumes that your *roff formatters have a fixed-width font
named CW.  If yours is called something else (like CR), use the fixed
option to specify it.  This generally only matters for troff output for
printing.  Similarly, you can set the fonts used for bold, italic, and
bold italic fixed-width output.

   Besides the obvious pod conversions, Pod::Man also takes care of
formatting func(), func(n), and simple variable references like $foo or
@bar so you don't have to use code escapes for them; complex expressions
like `$fred{'stuff'}' will still need to be escaped, though.  It also
translates dashes that aren't used as hyphens into en dashes, makes long
dashes-like this-into proper em dashes, fixes "paired quotes," makes C++
and PI look right, puts a little space between double underbars, makes
ALLCAPS a teeny bit smaller in troff(1), and escapes stuff that *roff
treats as special so that you don't have to.

   The recognized options to new() are as follows.  All options take a
single argument.

center
     Sets the centered page header to use instead of "User Contributed Perl
     Documentation".

date
     Sets the left-hand footer.  By default, the modification date of the
     input file will be used, or the current date if stat() can't find
     that file (the case if the input is from STDIN), and the date will be
     formatted as YYYY-MM-DD.

fixed
     The fixed-width font to use for vertabim text and code.  Defaults to
     CW.  Some systems may want CR instead.  Only matters for troff(1)
     output.

fixedbold
     Bold version of the fixed-width font.  Defaults to CB.  Only matters
     for troff(1) output.

fixeditalic
     Italic version of the fixed-width font (actually, something of a
     misnomer, since most fixed-width fonts only have an oblique version,
     not an italic version).  Defaults to CI.  Only matters for troff(1)
     output.

fixedbolditalic
     Bold italic (probably actually oblique) version of the fixed-width
     font.  Pod::Man doesn't assume you have this, and defaults to CB.
     Some systems (such as Solaris) have this font available as CX.  Only
     matters for troff(1) output.

quotes
     Sets the quote marks used to surround C<> text.  If the value is a
     single character, it is used as both the left and right quote; if it
     is two characters, the first character is used as the left quote and
     the second as the right quoted; and if it is four characters, the
     first two are used as the left quote and the second two as the right
     quote.

     This may also be set to the special value none, in which case no quote
     marks are added around C<> text (but the font is still changed for
     troff output).

release
     Set the centered footer.  By default, this is the version of Perl you
     run Pod::Man under.  Note that some system an macro sets assume that
     the centered footer will be a modification date and will prepend
     something like "Last modified: "; if this is the case, you may want
     to set release to the last modified date and date to the version
     number.

section
     Set the section for the `.TH' macro.  The standard section numbering
     convention is to use 1 for user commands, 2 for system calls, 3 for
     functions, 4 for devices, 5 for file formats, 6 for games, 7 for
     miscellaneous information, and 8 for administrator commands.  There
     is a lot of variation here, however; some systems (like Solaris) use
     4 for file formats, 5 for miscellaneous information, and 7 for
     devices.  Still others use 1m instead of 8, or some mix of both.
     About the only section numbers that are reliably consistent are 1, 2,
     and 3.

     By default, section 1 will be used unless the file ends in .pm in
     which case section 3 will be selected.

   The standard Pod::Parser method parse_from_filehandle() takes up to two
arguments, the first being the file handle to read POD from and the second
being the file handle to write the formatted output to.  The first defaults
to STDIN if not given, and the second defaults to STDOUT.  The method
parse_from_file() is almost identical, except that its two arguments are
the input and output disk files instead.  See Pod/Parser,
for the specific details.

DIAGNOSTICS
===========

roff font should be 1 or 2 chars, not "%s"
     (F) You specified a *roff font (using fixed, fixedbold, etc.) that
     wasn't either one or two characters.  Pod::Man doesn't support *roff
     fonts longer than two characters, although some *roff extensions do
     (the canonical versions of nroff(1) and troff(1) don't either).

Invalid link %s
     (W) The POD source contained a `L<>' sequence that Pod::Man was
     unable to parse.  You should never see this error message; it probably
     indicates a bug in Pod::Man.

Invalid quote specification "%s"
     (F) The quote specification given (the quotes option to the
     constructor) was invalid.  A quote specification must be one, two, or
     four characters long.

%s:%d: Unknown command paragraph "%s".
     (W) The POD source contained a non-standard command paragraph
     (something of the form `=command args') that Pod::Man didn't know
     about.  It was ignored.

Unknown escape E<%s>
     (W) The POD source contained an `E<>' escape that Pod::Man didn't
     know about.  `E<%s>' was printed verbatim in the output.

Unknown sequence %s
     (W) The POD source contained a non-standard interior sequence
     (something of the form `X<>') that Pod::Man didn't know about.  It
     was ignored.

Unmatched =back
     (W) Pod::Man encountered a =back command that didn't correspond to an
     =over command.

BUGS
====

   The lint-like features and strict POD format checking done by pod2man
are not yet implemented and should be, along with the corresponding `lax'
option.

   The NAME section should be recognized specially and index entries
emitted for everything in that section.  This would have to be deferred
until the next section, since extraneous things in NAME tends to confuse
various man page processors.

   The handling of hyphens, en dashes, and em dashes is somewhat fragile,
and one may get the wrong one under some circumstances.  This should only
matter for troff(1) output.

   When and whether to use small caps is somewhat tricky, and Pod::Man
doesn't necessarily get it right.

   Pod::Man doesn't handle font names longer than two characters.  Neither
do most troff(1) implementations, but GNU troff does as an extension.  It
would be nice to support as an option for those who want to use it.

   The preamble added to each output file is rather verbose, and most of
it is only necessary in the presence of E<> escapes for non-ASCII
characters.  It would ideally be nice if all of those definitions were only
output if needed, perhaps on the fly as the characters are used.

   Some of the automagic applied to file names assumes Unix directory
separators.

   Pod::Man is excessively slow.

SEE ALSO
========

   `Pod::Parser|Pod::Parser' in this node, perlpod(1), pod2man(1),
nroff(1), troff(1), man(1), man(7)

   Ossanna, Joseph F., and Brian W. Kernighan.  "Troff User's Manual,"
Computing Science Technical Report No. 54, AT&T Bell Laboratories.  This is
the best documentation of standard nroff(1) and troff(1).  At the time of
this writing, it's available at
http://www.cs.bell-labs.com/cm/cs/cstr.html.

   The man page documenting the man macro set may be man(5) instead of
man(7) on your system.  Also, please see pod2man(1) for extensive
documentation on writing manual pages if you've not done it before and
aren't familiar with the conventions.

AUTHOR
======

   Russ Allbery <rra@stanford.edu>, based *very* heavily on the original
pod2man by Tom Christiansen <tchrist@mox.perl.com>.

POD Object Model
****************

NAME
====

   Pod::POM - POD Object Model

SYNOPSIS
========

     use Pod::POM;

     my $parser = Pod::POM->new(\%options);

     # parse from a text string
     my $pom = $parser->parse_text($text)
         || die $parser->error();

     # parse from a file specified by name or filehandle
     my $pom = $parser->parse_text($file)
         || die $parser->error();

     # parse from text or file
     my $pom = $parser->parse($text_or_file)
         || die $parser->error();

     # examine any warnings raised
     foreach my $warning ($parser->warnings()) {
     	warn $warning, "\n";
     }

     # print table of contents using each =head1 title
     foreach my $head1 ($pom->head1()) {
     	print $head1->title(), "\n";
     }

     # print each section
     foreach my $head1 ($pom->head1()) {
     	print $head1->title(), "\n";
         print $head1->content();
     }

     # print the entire document as HTML
     use Pod::POM::View::HTML;
     print Pod::POM::View::HTML->print($pom);

     # create custom view
     package My::View;
     use base qw( Pod::POM::View::HTML );

     sub view_head1 {
     	my ($self, $item) = @_;
     	return "<h2>", $item->title->present($self), "</h2>\n\n";
     	$item->content->present($self);
     }

     package main;
     print My::View->print($pom);

DESCRIPTION
===========

   This module implements a parser to convert Pod documents into a simple
object model form known hereafter as the Pod Object Model.  The object
model is generated as a hierarchical tree of nodes, each of which
represents a different element of the original document.  The tree can be
walked manually and the nodes examined, printed or otherwise manipulated.
In addition, Pod::POM supports and provides view objects which can
automatically traverse the tree, or section thereof, and generate an
output representation in one form or another.

   Let's look at a typical Pod document by way of example.

     =head1 NAME

     My::Module - just another My::Module

     =head1 DESCRIPTION

     This is My::Module, a deeply funky piece of Perl code.

     =head2 METHODS

     My::Module implements the following methods

     =over 4

     =item new(\%config)

     This is the constructor method.  It accepts the following
     configuration options:

     =over 4

     =item name

     The name of the thingy.

     =item colour

     The colour of the thingy.

     =back

     =item print()

     This prints the thingy.

     =back

     =head1 AUTHOR

     My::Module was written by me Less_Than_Special_Sequenceme@here.orgGreater_Than_Special_Sequence

   This document contains 3 main sections, NAME, DESCRIPTION and AUTHOR,
each of which is delimited by an opening =head1 tag.  NAME and AUTHOR each
contain only a single line of text, but DESCRIPTION is more interesting.
It contains a line of text followed by the =head2 subsection, METHODS.
This contains a line of text and a list extending from the `=over 4' to the
final =back just before the AUTHOR section starts.  The list contains 2
items, new(\%config), which itself contains some text and a list of 2
items, and print().

   Presented as plain text and using indentation to indicate the element
nesting, the model then looks something like this :

     NAME
         My::Module - just another My::Module

     DESCRIPTION
     	This is My::Module, a deeply funky piece of Perl code.

     METHODS
     	    My::Module implements the following methods

     * new(\%config)
         This is the constructor method.  It accepts the
         following configuration options:

     * name
     		    The name of the thingy.

     * colour
     		    The colour of the thingy.

     * item print()
         This prints the thingy.

     AUTHOR
         My::Myodule was written by me <me@here.org>

   Those of you familiar with XML may prefer to think of it in the
following way:

     <pod>
       <head1 title="NAME">
         <p>My::Module - just another My::Module</p>
       </head1>

     <head1 title="DESCRIPTION">
       <p>This is My::Module, a deeply funky piece of
          Perl code.</p>

     <head2 title="METHODS">
     	  <p>My::Module implements the following methods</p>

     <over indent=4>
       <item title="item new(\%config)">
         <p>This is the constructor method.  It accepts
            the following configuration options:</p>

     <over indent=4>
     		<item title="name">
         <p>The name of the thingy.</p>
       </item>

     <item title="colour">
       <p>The colour of the thingy.</p>
     </item>
                   </over>
                 </item>

     <item title="print()">
     	      <p>This prints the thingy.</p>
     	    </item>
               </over>
             </head2>
           </head1>

     <head1 title="AUTHOR">
     	<p>My::Myodule was written by me &lt;me@here.org&gt;
     </head1>
         </pod>

   Notice how we can make certain assumptions about various elements.  For
example, we can assume that any =head1 section we find begins a new
section and implicitly ends any previous section.  Similarly, we can
assume an =item ends when the next one begins, and so on.  In terms of the
XML example shown above, we are saying that we're smart enough to add a
`</head1>' element to terminate any previously opened `<head1>' when we
find a new =head1 tag in the input document.

   However you like to visualise the content, it all comes down to the
same underlying model.  The job of the Pod::POM module is to read an input
Pod document and build an object model to represent it in this structured
form.

   Each node in the tree (i.e. element in the document) is represented by
a Pod::POM::Node::* object.  These encapsulate the attributes for an
element (such as the title for a =head1 tag) and also act as containers
for further Pod::POM::Node::* objects representing the content of the
element.  Right down at the leaf nodes, we have simple object types to
represent formatted and verbatim text paragraphs and other basic elements
like these.

Parsing Pod
-----------

   The Pod::POM module implements the methods parse_file($file),
parse_text($text) and parse($file_or_text) to parse Pod files and input
text.  They return a Pod::POM::Node::Pod object to represent the root of
the Pod Object Model, effectively the `<pod>' element in the XML tree
shown above.

     use Pod::POM;

     my $parser = Pod::POM->new();
     my $pom = $parser->parse_file($filename)
         || die $parser->error();

   The parse(), parse_text() and parse_file() methods return undef on
error.  The error() method can be called to retrieve the error message
generated.  Parsing a document may also generate non-fatal warnings.
These can be retrieved via the warnings() method which returns a reference
to a list when called in scalar context or a list of warnings when called
in list context.

     foreach my $warn ($parser->warnings()) {
     	warn $warn, "\n";
     }

   Alternatively, the 'warn' configuration option can be set to have
warnings automatically raised via `warn()' as they are encountered.

     my $parser = Pod::POM->new( warn => 1 );

Walking the Object Model
------------------------

   Having parsed a document into an object model, we can then select
various items from it.  Each node implements methods (via AUTOLOAD) which
correspond to the attributes and content elements permitted within in.

   So to fetch the list of '=head1' sections within our parsed document,
we would do the following:

     my $sections = $pom->head1();

   Methods like this will return a list of further Pod::POM::Node::*
objects when called in list context or a reference to a list when called
in scalar context.  In the latter case, the list is blessed into the
Pod::POM::Node::Content class which gives it certain magical properties
(more on that later).

   Given the list of Pod::POM::Node::Head1 objects returned by the above,
we can print the title attributes of each like this:

     foreach my $s (@$sections) {
     	print $s->title();
     }

   Let's look at the second section, DESCRIPTION.

     my $desc = $sections->[1];

   We can print the title of each subsection within it:

     foreach my $ss ($desc->head2()) {
     	print $ss->title();
     }

   Hopefully you're getting the idea by now, so here's a more studly
example to print the title for each item contained in the first list
within the METHODS section:

     foreach my $item ($desc->head2->[0]->over->[0]->item) {
     	print $item->title(), "\n";
     }

Element Content
---------------

   This is all well and good if you know the precise structure of a
document in advance.  For those more common cases when you don't, each
node that can contain other nodes provides a 'content' method to return a
complete list of all the other nodes that it contains.  The 'type' method
can be called on any node to return its element type (e.g. 'head1',
'head2', 'over', item', etc).

     foreach my $item ($pom->content()) {
     	my $type = $item->type();
     	if ($type eq 'head1') {
     	    ...
     	}
     	elsif ($type eq 'head2') {
     	    ...
     	}
     	...
     }

   The content for an element is represented by a reference to a list,
blessed into the Pod::POM::Node::Content class.  This provides some magic
in the form of an overloaded stringification operator which will
automatically print the contents of the list if you print the object
itself.  In plain English, or rather, in plain Perl, this means you can do
things like the following:

     foreach my $head1 ($pom->head1()) {
     	print '<h1>', $head1->title(), "</h1>\n\n";
     	print $head1->content();
     }

     # print all the root content
     foreach my $item ($pom->content()) {
     	print $item;
     }

     # same as above
     print $pom->content();

   In fact, all Pod::POM::Node::* objects provide this same magic, and
will attempt to Do The Right Thing to present themselves in the
appropriate manner when printed.  Thus, the following are all valid.

     print $pom;			# entire document
     print $pom->content;	# content of document
     print $pom->head1->[0];	# just first section
     print $pom->head1;		# print all sections
     foreach my $h1 ($pom->head1()) {
     	print $h1->head2();	# print all subsections
     }

Output Views
------------

   To understand how the different elements go about presenting themselves
in "the appropriate manner", we must introduce the concept of a view.  A
view is quite simply a particular way of looking at the model.  In real
terms, we can think of a view as being some kind of output type generated
by a pod2whatever converter.  Notionally we can think in terms of reading
in an input document, building a Pod Object Model, and then generating an
HTML view of the document, and/or a LaTeX view, a plain text view, and so
on.

   A view is represented in this case by an object class which contains
methods for displaying each of the different element types that could be
encountered in any Pod document.  There's a method for displaying =head1
sections (view_head1()), another method for displaying =head2 sections
(view_head2()), one for =over (view_over()), another for =item
(view_item()) and so on.

   If we happen to have a reference to a $node and we know it's a 'head1'
node, then we can directly call the right view method to have it displayed
properly:

     $view = 'Pod::POM::View::HTML';
     $view->view_head1($node);

   Thus our earlier example can be modified to be *slightly* less laborious
and *marginally* more flexible.

     foreach my $node ($pom->content) {
     	my $type = $node->type();
     	if ($type eq 'head1') {
     	    print $view->view_head1($node);
     	}
     	elsif ($type eq 'head2') {
     	    print $view->view_head2($node);
     	}
     	...
     }

   However, this is still far from ideal.  To make life easier, each
Pod::POM::Node::* class inherits (or possibly redefines) a
`present($view)' method from the Pod::POM::Node base class.  This method
expects a reference to a view object passed as an argument, and it simply
calls the appropriate view_xxx() method on the view object, passing itself
back as an argument.  In object parlance, this is known as "double
dispatch".  The beauty of it is that you don't need to know what kind of
node you have to be able to print it.  You simply pass it a view object
and leave it to work out the rest.

     foreach my $node ($pom->content) {
     	print $node->present($view);
     }

   If $node is a Pod::POM::Node::Head1 object, then the view_head1($node)
method gets called against the $view object.  Otherwise, if it's a
Pod::POM::Node::Head2 object, then the view_head2($node) method is
dispatched.  And so on, and so on, with each node knowing what it is and
where it's going as if determined by some genetically pre-programmed
instinct.  Fullfilling their destinies, so to speak.

   Double dispatch allows us to do away with all the explicit type
checking and other nonsense and have the node objects themselves worry
about where they should be routed to.  At the cost of an extra method call
per node, we get programmer convenience, and that's usually a Good Thing.

   Let's have a look at how the view and node classes might be implemented.

     package Pod::POM::View::HTML;

     sub view_pod {
     	my ($self, $node) = @_;
     	return $node->content->present($self);
     }

     sub view_head1 {
     	my ($self, $node) = @_;
     	return "<h1>", $node->title->present($self), "</h1>\n\n"
     	     . $node->content->present($self);
     }

     sub view_head2 {
     	my ($self, $node) = @_;
     	return "<h2>", $node->title->present($self), "</h2>\n\n"
     	     . $node->content->present($self);
     }

     ...

     package Pod::POM::Node::Pod;

     sub present {
     	my ($self, $view) = @_;
     	$view->view_pod($self);
     }

     package Pod::POM::Node::Head1;

     sub present {
     	my ($self, $view) = @_;
     	$view->view_head1($self);
     }

     package Pod::POM::Node::Head2;

     sub present {
     	my ($self, $view) = @_;
     	$view->view_head2($self);
     }

     ...

   Some of the view_xxx methods make calls back against the node objects
to display their attributes and/or content.  This is shown in, for
example, the view_head1() method above, where the method prints the
section title in `<h1>'...`<h1>' tags, followed by the remaining section
content.

   Note that the title() attribute is printed by calling its present()
method, passing on the reference to the current view.  Similarly, the
content present() method is called giving it a chance to Do The Right
Thing to present itself correctly via the view object.

   There's a good chance that the title attribute is going to be regular
text, so we might be tempted to simply print the title rather than call
its present method.

     sub view_head1 {
     	my ($self, $node) = @_;
     	# not recommended, prefer $node->title->present($self)
     	return "<h1>", $node->title(), "</h1>\n\n", ...
     }

   However, it is entirely valid for titles and other element attributes,
as well as regular, formatted text blocks to contain code sequences, such
like `B<this>' and `I<this>'.  These are used to indicate different markup
styles, mark external references or index items, and so on.  What's more,
they can be `B<nested I<indefinately>>'.  Pod::POM takes care of all this
by parsing such text, along with any embedded sequences, into Yet Another
Tree, the root node of which is a Pod::POM::Node::Text object, possibly
containing other Pod::POM::Node::Sequence objects.  When the text is
presented, the tree is automatically walked and relevant callbacks made
against the view for the different sequence types.  The methods called
against the view are all prefixed 'view_seq_', e.g.  'view_seq_bold',
'view_seq_italic'.

   Now the real magic comes into effect.  You can define one view to
render bold/italic text in one style:

     package My::View::Text;
     use base qw( Pod::POM::View::Text );

     sub view_seq_bold {
     	my ($self, $text) = @_;
     	return "*$text*";
     }

     sub view_seq_italic {
     	my ($self, $text) = @_;
     	return "_$text_";
     }

   And another view to render it in a different style:

     package My::View::HTML;
     use base qw( Pod::POM::View::HTML );

     sub view_seq_bold {
     	my ($self, $text) = @_;
     	return "<b>$text</b>";
     }

     sub view_seq_italic {
     	my ($self, $text) = @_;
     	return "<i>$text</i>";
     }

   Then, you can easily view a Pod Object Model in either style:

     my $text = 'My::View::Text';
     my $html = 'My::View::HTML';

     print $pom->present($text);
     print $pom->present($html);

   And you can apply this technique to any node within the object model.

     print $pom->head1->[0]->present($text);
     print $pom->head1->[0]->present($html);

   In these examples, the view passed to the present() method has been a
class name.  Thus, the view_xxx methods get called as class methods, as if
written:

     My::View::Text->view_head1(...);

   If your view needs to maintain state then you can create a view object
and pass that to the present() method.

     my $view = My::View->new();
     $node->present($view);

   In this case the view_xxx methods get called as object methods.

     sub view_head1 {
     	my ($self, $node) = @_;
     	my $title = $node->title();
     	if ($title eq 'NAME' && ref $self) {
     	    $self->{ title } = $title();
     	}
     	$self->SUPER::view_head1($node);
     }

   Whenever you print a Pod::POM::Node::* object, or do anything to cause
Perl to stringify it (such as including it another quoted string "like
$this"), then its present() method is automatically called.  When called
without a view argument, the present() method uses the default view
specified in $Pod::POM::DEFAULT_VIEW, which is, by default,
'Pod::POM::View::Pod'.  This view regenerates the original Pod document,
although it should be noted that the output generated may not be exactly
the same as the input.  The parser is smart enough to detect some common
errors (e.g. not terminating an =over with a =back) and correct them
automatically.  Thus you might find a =back correctly placed in the
output, even if you forgot to add it to the input.  Such corrections raise
non-fatal warnings which can later be examined via the warnings() method.

   You can update the $Pod::POM::DEFAULT_VIEW package variable to set the
default view, or call the default_view() method.  The default_view()
method will automatically load any package you specify.  If setting the
package variable directly, you should ensure that any packages required
have been pre-loaded.

     use My::View::HTML;
     $Pod::POM::DEFAULT_VIEW = 'My::View::HTML';

   or

     Pod::POM->default_view('My::View::HTML');

Template Toolkit Views
----------------------

   One of the motivations for writing this module was to make it easier to
customise Pod documentation to your own look and feel or local formatting
conventions.  By clearly separating the content (represented by the Pod
Object Model) from the presentation style (represented by one or more
views) it becomes much easier to achieve this.

   The latest version (2.01) of the Template Toolkit provides a Pod::POM
plugin to interface to this module.  In addition, it supports a new VIEW
directive which allows you to define the presentation elements as template
blocks.  At the time of writing, version 2.01 hasn't been officially
released to CPAN, but a preview is available from the Template Toolkit web
site:

     http://www.template-toolkit.org/

   The precise syntax and structure of the VIEW directive is subject to
change, but at present it can be used to define a view something like this:

     [% VIEW myview %]
        [% BLOCK view_head1 %]
           <h1>[% item.title.present(view) %]</h1>
           [% item.content.present(view) %]
        [% END %]

        [% BLOCK view_head2 %]
           <h2>[% item.title.present(view) %]</h2>
           [% item.content.present(view) %]
        [% END %]

     ...

     [% END %]

   A plugin is provided to interface to the Pod::POM module:

     [% USE pom = Pod.POM(myfile) %]

   The returned Pod Object Model instance can then be navigated and
presented via the view in almost any way imaginable:

     <h1>Table of Contents</h1>
     <ul>
     [% FOREACH section = pom.head1 %]
        <li>[% section.title.present(view) %]
     [% END %]
     </ul>

     <hr>

     [% FOREACH section = pom.head1 %]
        [% section.present(myview) %]
     [% END %]

   As noted above this is all still experimental but should stabilise with
the release of the Template Toolkit 2.01, expected some time late in
January 2001.  This documentation will be updated at that time.

METHODS
=======

new(\%config)
-------------

   Constructor method which instantiates and returns a new Pod::POM parser
object.

     use Pod::POM;

     my $parser = Pod::POM->new();

   A reference to a hash array of configuration options may be passed as
an argument.

     my $parser = Pod::POM->new( { warn => 1 } );

   For convenience, configuration options can also be passed as a list of
(key => value) pairs.

     my $parser = Pod::POM->new( warn => 1 );

   The following configuration options are defined:

code
     This option can be set to have all non-Pod parts of the input document
     stored within the object model as 'code' elements, represented by
     objects of the Pod::POM::Node::Code class.  It is disabled by default
     and code sections are ignored.

          my $parser = Pod::POM->new( code => 1 );
          my $podpom = $parser->parse(\*DATA);

          foreach my $code ($podpom->code()) {
          	print "<pre>$code</pre>\n";
          }

          __DATA__
          This is some program code.

          =head1 NAME

          ...

     This will generate the output:

          <pre>This is some program code.</pre>

     Note that code elements are stored within the POM element in which
     they are encountered.  For example, the code element below embedded
     within between Pod sections is stored in the array which can be
     retrieved by calling `$podpom->head1->[0]->code()'.

          =head1 NAME

          My::Module::Name;

          =cut

          Some program code embedded in Pod.

          =head1 SYNOPSIS

          ...

warn
     Non-fatal warnings encountered while parsing a Pod document are stored
     internally and subsequently available via the warnings() method.

          my $parser = Pod::POM->new();
          my $podpom = $parser->parse_file($filename);

          foreach my $warning ($parser->warnings()) {
          	warn $warning, "\n";
          }

     The 'warn' option can be set to have warnings raised automatically
     via `warn()' as and when they are encountered.

          my $parser = Pod::POM->new( warn => 1 );
          my $podpom = $parser->parse_file($filename);

     If the configuration value is specified as a subroutine reference then
     the code will be called each time a warning is raised, passing the
     warning message as an argument.

          sub my_warning {
          	my $msg = shift;
          	warn $msg, "\n";
          };

          my $parser = Pod::POM->new( warn => \&my_warning );
          my $podpom = $parser->parse_file($filename);

parse_file($file)
-----------------

   Parses the file specified by name or reference to a file handle.
Returns a reference to a Pod::POM::Node::Pod object which represents the
root node of the Pod Object Model on success.  On error, undef is returned
and the error message generated can be retrieved by calling error().

     my $podpom = $parser->parse_file($filename)
         || die $parser->error();

     my $podpom = $parser->parse_file(\*STDIN)
         || die $parser->error();

   Any warnings encountered can be examined by calling the warnings()
method.

     foreach my $warn ($parser->warnings()) {
     	warn $warn, "\n";
     }

parse_text($text)
-----------------

   Parses the Pod text string passed as an argument into a Pod Object
Model, as per parse_file().

parse($text_or_$file)
---------------------

   General purpose method which attempts to Do The Right Thing in calling
parse_file() or parse_text() according to the argument passed.

   A hash reference can be passed as an argument that contains a 'text' or
'file' key and corresponding value.

     my $podpom = $parser->parse({ file => $filename })
         || die $parser->error();

   Otherwise, the argument can be a reference to an input handle which is
passed off to parse_file().

     my $podpom = $parser->parse(\*DATA)
         || die $parser->error();

   If the argument is a text string that looks like Pod text (i.e. it
contains '=' at the start of any line) then it is passed to parse_text().

     my $podpom = $parser->parse($podtext)
         || die $parser->error();

   Otherwise it is assumed to be a filename and is passed to parse_file().

     my $podpom = $parser->parse($podfile)
         || die $parser->error();

NODE TYPES, ATTRIBUTES AND ELEMENTS
===================================

   This section lists the different nodes that may be present in a Pod
Object Model.  These are implemented as Pod::POM::Node::* object instances
(e.g. head1 => Pod::POM::Node::Head1).  To present a node, a view should
implement a method which corresponds to the node name prefixed by 'view_'
(e.g. head1 => view_head1()).

pod
     The pod node is used to represent the root node of the Pod Object
     Model.

     Content elements: head1, head2, over, begin, for, verbatim, text,
     code.

head1
     A head1 node contains the Pod content from a =head1 tag up to the
     next =head1 tag or the end of the file.

     Attributes: title

     Content elements: head2, over, begin, for, verbatim, text, code.

head2
     A head2 node contains the Pod content from a =head2 tag up to the
     next =head1 or =head2 tag or the end of the file.

     Attributes: title

     Content elements: over, begin, for, verbatim, text, code.

over
     The over node encloses the Pod content in a list starting at an =over
     tag and continuing up to the matching =back tag.  Lists may be nested
     indefinately.

     Attributes: indent (default: 4)

     Content elements: over, item, begin, for, verbatim, text, code.

item
     The item node encloses the Pod content in a list item starting at an
     =item tag and continuing up to the next =item tag or a =back tag
     which terminates the list.

     Attributes: title (default: *)

     Content elements: over, begin, for, verbatim, text, code.

begin
     A begin node encloses the Pod content in a conditional block starting
     with a =begin tag and continuing up to the next =end tag.

     Attributes: format

     Content elements: verbatim, text, code.

for
     A for node contains a single paragraph containing text relevant to a
     particular format.

     Attributes: format, text

verbatim
     A verbatim node contains a verbatim text paragraph which is prefixed
     by whitespace in the source Pod document (i.e. indented).

     Attributes: text

text
     A text node contains a regular text paragraph.  This may include
     embedded inline sequences.

     Attributes: text

code
     A code node contains Perl code which is by default, not considered to
     be part of a Pod document.  The code configuration option must be set
     for Pod::POM to generate code blocks, otherwise they are ignored.

     Attributes: text

INLINE SEQUENCES
================

   Embedded sequences are permitted within regular text blocks (i.e. not
verbatim) and title attributes.  To present these sequences, a view should
implement methods corresponding to the sequence name, prefixed by
'view_seq_' (e.g. bold => view_seq_bold()).

code
     Code extract, e.g. C<my code>

bold
     Bold text, e.g. B<bold text>

italic
     Italic text, e.g. I<italic text>

link
     A link (cross reference), e.g. L<My::Module>

space
     Text contains non-breaking space, e.g.S<Buffy The Vampire Slayer>

file
     A filename, e.g. F</etc/lilo.conf>

index
     An index entry, e.g. X<Angel>

zero
     A zero-width character, e.g. Z<>

entity
     An entity escape, e.g. E<lt>

BUNDLED MODULES AND TOOLS
=========================

   The Pod::POM module distribution includes a number of sample view
objects for rendering Pod Object Models into particular formats.  These
are incomplete and may require some further work, but serve at present to
illustrate the principal and can be used as the basis for your own view
objects.

Pod::POM::View::Pod
     Regenerates the model as Pod.

Pod::POM::View::Text
     Presents the model as plain text.

Pod::POM::View::HTML
     Presents the model as HTML.

   A script is provided for converting Pod documents to other format by
using the view objects provided.  The `pom2' script should be called with
two arguments, the first specifying the output format, the second the
input filename.  e.g.

     $ pom2 text My/Module.pm > README
     $ pom2 html My/Module.pm > ~/public_html/My/Module.html

   You can also create symbolic links to the script if you prefer and
leave it to determine the output format from its own name.

     $ ln -s pom2 pom2text
     $ ln -s pom2 pom2html
     $ pom2text My/Module.pm > README
     $ pom2html My/Module.pm > ~/public_html/My/Module.html

   The distribution also contains a trivial script, `pomcheck', which
checks a Pod document for well-formedness by simply parsing it into a Pod
Object Model with warnings enabled.  Warnings are printed to STDERR.

     $ pomcheck My/Module.pm

   The -f option can be set to have the script attempt to fix any problems
it encounters.  The regenerated Pod output is printed to STDOUT.

     $ pomcheck -f My/Module.pm > newfile

AUTHOR
======

   Andy Wardley <abw@kfs.org>

VERSION
=======

   This is version 0.1 of the Pod::POM module.

COPYRIGHT
=========

   Copyright (C) 2000, 2001 Andy Wardley.  All Rights Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   For the definitive reference on Pod, see Perlpod (perl.info).

   For an overview of Pod::POM internals and details relating to
subclassing of POM nodes, see Pod/POM/Node.

   There are numerous other fine Pod modules available from CPAN which
perform conversion from Pod to other formats.  In many cases these are
likely to be faster and quite possibly more reliable and/or complete than
this module.  But as far as I know, there aren't any that offer the same
kind of flexibility in being able to customise the generated output.  But
don't take my word for it - see your local CPAN site for further details:

     http://www.cpan.org/modules/by-module/Pod/

base class for a POM node
*************************

NAME
====

   Pod::POM::Node - base class for a POM node

SYNOPSIS
========

     package Pod::POM::Node::Over;
     use base qw( Pod::POM::Node );
     use vars qw( %ATTRIBS @ACCEPT $EXPECT $ERROR );

     %ATTRIBS =   ( indent => 4 );
     @ACCEPT  = qw( over item begin for text verbatim );
     $EXPECT  = qw( back );

     package main;
     my $list = Pod::POM::Node::Over->new(8);
     $list->add('item', 'First Item');
     $list->add('item', 'Second Item');
     ...

DESCRIPTION
===========

   This documentation describes the inner workings of the Pod::POM::Node
module and gives a brief overview of the relationship between it and its
derived classes.  It is intended more as a guide to the internals for
interested hackers than as general user documentation.  See Pod/POM,
for information on using the modules.

   This module implements a base class node which is subclassed to
represent different elements within a Pod Object Model.

     package Pod::POM::Node::Over;
     use base qw( Pod::POM::Node );

   The base class implements the new() constructor method to instantiate
new node objects.

     my $list = Pod::POM::Node::Over->new();

   The characteristics of a node can be specified by defining certain
variables in the derived class package.  The `%ATTRIBS' hash can be used
to denote attributes that the node should accept.  In the case of an =over
node, for example, an indent attribute can be specified which otherwise
defaults to 4.

     package Pod::POM::Node::Over;
     use base qw( Pod::POM::Node );
     use vars qw( %ATTRIBS $ERROR );

     %ATTRIBS = ( indent => 4 );

   The new() method will now expect an argument to set the indent value,
or will use 4 as the default if no argument is provided.

     my $list = Pod::POM::Node::Over->new(8);	# indent: 8
     my $list = Pod::POM::Node::Over->new( );	# indent: 4

   If the default value is undefined then the argument is mandatory.

     package Pod::POM::Node::Head1;
     use base qw( Pod::POM::Node );
     use vars qw( %ATTRIBS $ERROR );

     %ATTRIBS = ( title => undef );

     package main;
     my $head = Pod::POM::Node::Head1->new('My Title');

   If a mandatory argument isn't provided then the constructor will return
undef to indicate failure.  The $ERROR variable in the derived class
package is set to contain a string of the form "$type expected a
$attribute".

     # dies with error: "head1 expected a title"
     my $head = Pod::POM::Node::Head1->new()
     	|| die $Pod::POM::Node::Head1::ERROR;

   For convenience, the error() subroutine can be called as a class method
to retrieve this value.

     my $type = 'Pod::POM::Node::Head1';
     my $head = $type->new()
     	|| die $type->error();

   The `@ACCEPT' package variable can be used to indicate the node types
that are permitted as children of a node.

     package Pod::POM::Node::Head1;
     use base qw( Pod::POM::Node );
     use vars qw( %ATTRIBS @ACCEPT $ERROR );

     %ATTRIBS =   ( title => undef );
     @ACCEPT  = qw( head2 over begin for text verbatim );

   The add() method can then be called against a node to add a new child
node as part of its content.

     $head->add('over', 8);

   The first argument indicates the node type.  The `@ACCEPT' list is
examined to ensure that the child node type is acceptable for the parent
node.  If valid, the constructor for the relevant child node class is
called passing any remaining arguments as attributes.  The new node is
then returned.

     my $list = $head->add('over', 8);

   The error() method can be called against the parent node to retrieve
any constructor error generated by the child node.

     my $list = $head->add('over', 8);
     die $head->error() unless defined $list;

   If the child node is not acceptable to the parent then the add() method
returns one of the constants IGNORE, REDUCE or REJECT, as defined in
Pod::POM::Constants.  These return values are used by the Pod::POM parser
module to implement a simple shift/reduce parser.

   In the most common case, IGNORE is returned to indicate that the parent
node doesn't know anything about the new child node.  The parser uses this
as an indication that it should back up through the parse stack until it
finds a node which *will* accept this child node.  Through this mechanism,
the parser is able to implicitly terminate certain POD blocks.  For
example, a list item initiated by a =item tag will not accept another
=item tag, but will instead return IGNORE.  The parser will back out until
it finds the enclosing =over node which *will* accept it.  Thus, a new
=item implicitly terminates any previous =item.

   The `$EXPECT' package variable can be used to indicate a node type
which a parent expects to terminate itself.  An =over node, for example,
should always be terminated by a matching =back.  When such a match is
made, the add() method returns REDUCE to indicate successful termination.

     package Pod::POM::Node::Over;
     use base qw( Pod::POM::Node );
     use vars qw( %ATTRIBS @ACCEPT $EXPECT $ERROR );

     %ATTRIBS =   ( indent => 4 );
     @ACCEPT  = qw( over item begin for text verbatim );
     $EXPECT  = qw( back );

     package main;
     my $list = Pod::POM::Node::Over->new();
     my $item = $list->add('item');
     $list->add('back');			# returns REDUCE

   If a child node isn't specified in the `@ACCEPT' list or doesn't match
any `$EXPECT' specified then REJECT is returned.  The parent node sets an
internal error of the form "$type expected a terminating $expect".  The
parser uses this to detect missing POD tags.  In nearly all cases the
parser is smart enough to fix the incorrect structure and downgrades any
errors to warnings.

     # dies with error 'over expected terminating back'
     ref $list->add('head1', 'My Title')	    # returns REJECT
         || die $list->error();

   Each node contains a 'type' field which contains a simple string
indicating the node type, e.g. 'head1', 'over', etc.  The $NODES and
$NAMES package variables (in the base class) reference hash arrays which
map these names to and from package names (e.g. head1 <=>
Pod::POM::Node::Head1).

     print $list->{ type };	# 'over'

   An AUTOLOAD method is provided to access to such internal items for
those who don't like violating an object's encapsulation.

     print $list->type();

   Nodes also contain a 'content' list, blessed into the
Pod::POM::Node::Content class, which contains the content (child elements)
for the node.  The AUTOLOAD method returns this as a list reference or as
a list of items depending on the context in which it is called.

     my $items = $list->content();
     my @items = $list->content();

   Each node also contains a content list for each individual child node
type that it may accept.

     my @items = $list->item();
     my @text  = $list->text();
     my @vtext = $list->verbatim();

   The present() method is used to present a node through a particular
view.  This simply maps the node type to a method which is then called
against the view object.  This is known as 'double dispatch'.

     my $view = Pod::POM::View::HTML;
     print $list->present($view);

   The method name is constructed from the node type prefixed by 'view_'.
Thus the following are roughly equivalent.

     $list->present($view);

     $view->view_list($list);

   The benefit of the former over the latter is, of course, that the
caller doesn't need to know or determine the type of the node.  The node
itself is in the best position to determine what type it is.

AUTHOR
======

   Andy Wardley <abw@kfs.org>

COPYRIGHT
=========

   Copyright (C) 2000, 2001 Andy Wardley.  All Rights Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   Consult Pod/POM, for a general overview and examples of
use.

helpers for POD parsing and conversion
**************************************

NAME
====

   Pod::ParseUtils - helpers for POD parsing and conversion

SYNOPSIS
========

     use Pod::ParseUtils;

     my $list = new Pod::List;
     my $link = Pod::Hyperlink->new('Pod::Parser');

DESCRIPTION
===========

   *Pod::ParseUtils* contains a few object-oriented helper packages for
POD parsing and processing (i.e. in POD formatters and translators).

Pod::List
---------

   Pod::List can be used to hold information about POD lists (written as
=over ... =item ... =back) for further processing.  The following methods
are available:

new()
     Create a new list object. Properties may be specified through a hash
     reference like this:

          my $list = Pod::List->new({ -start => $., -indent => 4 });

     See the individual methods/properties for details.

file()
     Without argument, retrieves the file name the list is in. This must
     have been set before by either specifying *-file* in the new() method
     or by calling the file() method with a scalar argument.

start()
     Without argument, retrieves the line number where the list started.
     This must have been set before by either specifying *-start* in the
     new() method or by calling the start() method with a scalar argument.

indent()
     Without argument, retrieves the indent level of the list as specified
     in `=over n'. This must have been set before by either specifying
     *-indent* in the new() method or by calling the indent() method with
     a scalar argument.

type()
     Without argument, retrieves the list type, which can be an arbitrary
     value, e.g. `OL', `UL', ... when thinking the HTML way.  This must
     have been set before by either specifying *-type* in the new() method
     or by calling the type() method with a scalar argument.

rx()
     Without argument, retrieves a regular expression for simplifying the
     individual item strings once the list type has been determined. Usage:
     E.g. when converting to HTML, one might strip the leading number in
     an ordered list as `<OL>' already prints numbers itself.  This must
     have been set before by either specifying *-rx* in the new() method
     or by calling the rx() method with a scalar argument.

item()
     Without argument, retrieves the array of the items in this list.  The
     items may be represented by any scalar.  If an argument has been
     given, it is pushed on the list of items.

parent()
     Without argument, retrieves information about the parent holding this
     list, which is represented as an arbitrary scalar.  This must have
     been set before by either specifying *-parent* in the new() method or
     by calling the parent() method with a scalar argument.

tag()
     Without argument, retrieves information about the list tag, which can
     be any scalar.  This must have been set before by either specifying
     *-tag* in the new() method or by calling the tag() method with a
     scalar argument.

Pod::Hyperlink
--------------

   Pod::Hyperlink is a class for manipulation of POD hyperlinks. Usage:

     my $link = Pod::Hyperlink->new('alternative text|page/"section in page"');

   The Pod::Hyperlink class is mainly designed to parse the contents of the
`L<...>' sequence, providing a simple interface for accessing the
different parts of a POD hyperlink for further processing. It can also be
used to construct hyperlinks.

new()
     The new() method can either be passed a set of key/value pairs or a
     single scalar value, namely the contents of a `L<...>' sequence. An
     object of the class Pod::Hyperlink is returned. The value undef
     indicates a failure, the error message is stored in `$@'.

parse($string)
     This method can be used to (re)parse a (new) hyperlink, i.e. the
     contents of a `L<...>' sequence. The result is stored in the current
     object.

markup($string)
     Set/retrieve the textual value of the link. This string contains
     special markers `P<>' and `Q<>' that should be expanded by the
     translator's interior sequence expansion engine to the
     formatter-specific code to highlight/activate the hyperlink. The
     details have to be implemented in the translator.

text()
     This method returns the textual representation of the hyperlink as
     above, but without markers (read only). Depending on the link type
     this is one of the following alternatives (the + and * denote the
     portions of the text that are marked up):

          the +perl+ manpage
          the *$|* entry in the +perlvar+ manpage
          the section on *OPTIONS* in the +perldoc+ manpage
          the section on *DESCRIPTION* elsewhere in this document

warning()
     After parsing, this method returns any warnings encountered during the
     parsing process.

line(), file()
     Just simple slots for storing information about the line and the file
     the link was encountered in. Has to be filled in manually.

page()
     This method sets or returns the POD page this link points to.

node()
     As above, but the destination node text of the link.

alttext()
     Sets or returns an alternative text specified in the link.

type()
     The node type, either section or item. As an unofficial type, there
     is also `hyperlink', derived from e.g. `L<http://perl.com>'

link()
     Returns the link as contents of `L<>'. Reciprocal to parse().

Pod::Cache
----------

   Pod::Cache holds information about a set of POD documents, especially
the nodes for hyperlinks.  The following methods are available:

new()
     Create a new cache object. This object can hold an arbitrary number of
     POD documents of class Pod::Cache::Item.

item()
     Add a new item to the cache. Without arguments, this method returns a
     list of all cache elements.

find_page($name)
     Look for a POD document named $name in the cache. Returns the
     reference to the corresponding Pod::Cache::Item object or undef if
     not found.

Pod::Cache::Item
----------------

   Pod::Cache::Item holds information about individual POD documents, that
can be grouped in a Pod::Cache object.  It is intended to hold information
about the hyperlink nodes of POD documents.  The following methods are
available:

new()
     Create a new object.

page()
     Set/retrieve the POD document name (e.g. "Pod::Parser").

description()
     Set/retrieve the POD short description as found in the `=head1 NAME'
     section.

path()
     Set/retrieve the POD file storage path.

file()
     Set/retrieve the POD file name.

nodes()
     Add a node (or a list of nodes) to the document's node list. Note that
     the order is kept, i.e. start with the first node and end with the
     last.  If no argument is given, the current list of nodes is returned
     in the same order the nodes have been added.  A node can be any
     scalar, but usually is a pair of node string and unique id for the
     `find_node' method to work correctly.

find_node($name)
     Look for a node or index entry named $name in the object.  Returns
     the unique id of the node (i.e. the second element of the array
     stored in the node arry) or undef if not found.

idx()
     Add an index entry (or a list of them) to the document's index list.
     Note that the order is kept, i.e. start with the first node and end
     with the last.  If no argument is given, the current list of index
     entries is returned in the same order the entries have been added.
     An index entry can be any scalar, but usually is a pair of string and
     unique id.

AUTHOR
======

   Marek Rouchal <marek@saftsack.fs.uni-bayreuth.de>, borrowing a lot of
things from `pod2man' in this node and `pod2roff' in this node as well as
other POD processing tools by Tom Christiansen, Brad Appleton and Russ
Allbery.

SEE ALSO
========

   `pod2man' in this node, `pod2roff' in this node, see Pod/Parser,
see Pod/Checker, `pod2html' in this node

base class for creating POD filters and translators
***************************************************

NAME
====

   Pod::Parser - base class for creating POD filters and translators

SYNOPSIS
========

     use Pod::Parser;

     package MyParser;
     @ISA = qw(Pod::Parser);

     sub command {
         my ($parser, $command, $paragraph, $line_num) = @_;
         ## Interpret the command and its text; sample actions might be:
         if ($command eq 'head1') { ... }
         elsif ($command eq 'head2') { ... }
         ## ... other commands and their actions
         my $out_fh = $parser->output_handle();
         my $expansion = $parser->interpolate($paragraph, $line_num);
         print $out_fh $expansion;
     }

     sub verbatim {
         my ($parser, $paragraph, $line_num) = @_;
         ## Format verbatim paragraph; sample actions might be:
         my $out_fh = $parser->output_handle();
         print $out_fh $paragraph;
     }

     sub textblock {
         my ($parser, $paragraph, $line_num) = @_;
         ## Translate/Format this block of text; sample actions might be:
         my $out_fh = $parser->output_handle();
         my $expansion = $parser->interpolate($paragraph, $line_num);
         print $out_fh $expansion;
     }

     sub interior_sequence {
         my ($parser, $seq_command, $seq_argument) = @_;
         ## Expand an interior sequence; sample actions might be:
         return "*$seq_argument*"     if ($seq_command eq 'B');
         return "`$seq_argument'"     if ($seq_command eq 'C');
         return "_${seq_argument}_'"  if ($seq_command eq 'I');
         ## ... other sequence commands and their resulting text
     }

     package main;

     ## Create a parser object and have it parse file whose name was
     ## given on the command-line (use STDIN if no files were given).
     $parser = new MyParser();
     $parser->parse_from_filehandle(\*STDIN)  if (@ARGV == 0);
     for (@ARGV) { $parser->parse_from_file($_); }

REQUIRES
========

   perl5.005, Pod::InputObjects, Exporter, Symbol, Carp

EXPORTS
=======

   Nothing.

DESCRIPTION
===========

   Pod::Parser is a base class for creating POD filters and translators.
It handles most of the effort involved with parsing the POD sections from
an input stream, leaving subclasses free to be concerned only with
performing the actual translation of text.

   Pod::Parser parses PODs, and makes method calls to handle the various
components of the POD. Subclasses of Pod::Parser override these methods to
translate the POD into whatever output format they desire.

QUICK OVERVIEW
==============

   To create a POD filter for translating POD documentation into some other
format, you create a subclass of Pod::Parser which typically overrides
just the base class implementation for the following methods:

   * command()

   * verbatim()

   * textblock()

   * interior_sequence()

   You may also want to override the begin_input() and end_input() methods
for your subclass (to perform any needed per-file and/or per-document
initialization or cleanup).

   If you need to perform any preprocesssing of input before it is parsed
you may want to override one or more of preprocess_line() and/or
preprocess_paragraph().

   Sometimes it may be necessary to make more than one pass over the input
files. If this is the case you have several options. You can make the
first pass using Pod::Parser and override your methods to store the
intermediate results in memory somewhere for the end_pod() method to
process. You could use Pod::Parser for several passes with an appropriate
state variable to control the operation for each pass. If your input
source can't be reset to start at the beginning, you can store it in some
other structure as a string or an array and have that structure implement
a *getline()* method (which is all that parse_from_filehandle() uses to
read input).

   Feel free to add any member data fields you need to keep track of things
like current font, indentation, horizontal or vertical position, or
whatever else you like. Be sure to read `"PRIVATE METHODS AND DATA"' in
this node to avoid name collisions.

   For the most part, the Pod::Parser base class should be able to do most
of the input parsing for you and leave you free to worry about how to
intepret the commands and translate the result.

   Note that all we have described here in this quick overview is the
simplest most straightforward use of Pod::Parser to do stream-based
parsing. It is also possible to use the *Pod::Parser::parse_text* function
to do more sophisticated tree-based parsing. See `"TREE-BASED PARSING"' in
this node.

PARSING OPTIONS
===============

   A *parse-option* is simply a named option of Pod::Parser with a value
that corresponds to a certain specified behavior. These various behaviors
of Pod::Parser may be enabled/disabled by setting or or unsetting one or
more *parse-options* using the parseopts() method.  The set of currently
accepted parse-options is as follows:

*-want_nonPODs* (default: unset)
     Normally (by default) Pod::Parser will only provide access to the POD
     sections of the input. Input paragraphs that are not part of the
     POD-format documentation are not made available to the caller (not
     even using preprocess_paragraph()). Setting this option to a
     non-empty, non-zero value will allow preprocess_paragraph() to see
     non-POD sections of the input as well as POD sections. The cutting()
     method can be used to determine if the corresponding paragraph is a
     POD paragraph, or some other input paragraph.

*-process_cut_cmd* (default: unset)
     Normally (by default) Pod::Parser handles the =cut POD directive by
     itself and does not pass it on to the caller for processing. Setting
     this option to a non-empty, non-zero value will cause Pod::Parser to
     pass the =cut directive to the caller just like any other POD command
     (and hence it may be processed by the command() method).

     Pod::Parser will still interpret the =cut directive to mean that
     "cutting mode" has been (re)entered, but the caller will get a chance
     to capture the actual =cut paragraph itself for whatever purpose it
     desires.

*-warnings* (default: unset)
     Normally (by default) Pod::Parser recognizes a bare minimum of pod
     syntax errors and warnings and issues diagnostic messages for errors,
     but not for warnings. (Use Pod::Checker to do more thorough checking
     of POD syntax.) Setting this option to a non-empty, non-zero value
     will cause Pod::Parser to issue diagnostics for the few warnings it
     recognizes as well as the errors.

   Please see `"parseopts()"' in this node for a complete description of
the interface for the setting and unsetting of parse-options.

RECOMMENDED SUBROUTINE/METHOD OVERRIDES
=======================================

   Pod::Parser provides several methods which most subclasses will probably
want to override. These methods are as follows:

command()
=========

     $parser->command($cmd,$text,$line_num,$pod_para);

   This method should be overridden by subclasses to take the appropriate
action when a POD command paragraph (denoted by a line beginning with "=")
is encountered. When such a POD directive is seen in the input, this
method is called and is passed:

`$cmd'
     the name of the command for this POD paragraph

$text
     the paragraph text for the given POD paragraph command.

`$line_num'
     the line-number of the beginning of the paragraph

`$pod_para'
     a reference to a Pod::Paragraph object which contains further
     information about the paragraph command (see Pod/InputObjects,
     for details).

   Note that this method *is* called for =pod paragraphs.

   The base class implementation of this method simply treats the raw POD
command as normal block of paragraph text (invoking the textblock() method
with the command paragraph).

verbatim()
==========

     $parser->verbatim($text,$line_num,$pod_para);

   This method may be overridden by subclasses to take the appropriate
action when a block of verbatim text is encountered. It is passed the
following parameters:

$text
     the block of text for the verbatim paragraph

`$line_num'
     the line-number of the beginning of the paragraph

`$pod_para'
     a reference to a Pod::Paragraph object which contains further
     information about the paragraph (see Pod/InputObjects,
     for details).

   The base class implementation of this method simply prints the textblock
(unmodified) to the output filehandle.

textblock()
===========

     $parser->textblock($text,$line_num,$pod_para);

   This method may be overridden by subclasses to take the appropriate
action when a normal block of POD text is encountered (although the base
class method will usually do what you want). It is passed the following
parameters:

$text
     the block of text for the a POD paragraph

`$line_num'
     the line-number of the beginning of the paragraph

`$pod_para'
     a reference to a Pod::Paragraph object which contains further
     information about the paragraph (see Pod/InputObjects,
     for details).

   In order to process interior sequences, subclasses implementations of
this method will probably want to invoke either interpolate() or
parse_text(), passing it the text block $text, and the corresponding line
number in `$line_num', and then perform any desired processing upon the
returned result.

   The base class implementation of this method simply prints the text
block as it occurred in the input stream).

interior_sequence()
===================

     $parser->interior_sequence($seq_cmd,$seq_arg,$pod_seq);

   This method should be overridden by subclasses to take the appropriate
action when an interior sequence is encountered. An interior sequence is
an embedded command within a block of text which appears as a command name
(usually a single uppercase character) followed immediately by a string of
text which is enclosed in angle brackets. This method is passed the
sequence command `$seq_cmd' and the corresponding text `$seq_arg'. It is
invoked by the interpolate() method for each interior sequence that occurs
in the string that it is passed. It should return the desired text string
to be used in place of the interior sequence.  The `$pod_seq' argument is
a reference to a Pod::InteriorSequence object which contains further
information about the interior sequence.  Please see
Pod/InputObjects, for details if you need to access this
additional information.

   Subclass implementations of this method may wish to invoke the nested()
method of `$pod_seq' to see if it is nested inside some other
interior-sequence (and if so, which kind).

   The base class implementation of the interior_sequence() method simply
returns the raw text of the interior sequence (as it occurred in the
input) to the caller.

OPTIONAL SUBROUTINE/METHOD OVERRIDES
====================================

   Pod::Parser provides several methods which subclasses may want to
override to perform any special pre/post-processing. These methods do not
have to be overridden, but it may be useful for subclasses to take
advantage of them.

new()
=====

     my $parser = Pod::Parser->new();

   This is the constructor for Pod::Parser and its subclasses. You *do
not* need to override this method! It is capable of constructing subclass
objects as well as base class objects, provided you use any of the
following constructor invocation styles:

     my $parser1 = MyParser->new();
     my $parser2 = new MyParser();
     my $parser3 = $parser2->new();

   where `MyParser' is some subclass of Pod::Parser.

   Using the syntax `MyParser::new()' to invoke the constructor is not
recommended, but if you insist on being able to do this, then the subclass
*will* need to override the new() constructor method. If you do override
the constructor, you must be sure to invoke the initialize() method of the
newly blessed object.

   Using any of the above invocations, the first argument to the
constructor is always the corresponding package name (or object
reference). No other arguments are required, but if desired, an
associative array (or hash-table) my be passed to the new() constructor,
as in:

     my $parser1 = MyParser->new( MYDATA => $value1, MOREDATA => $value2 );
     my $parser2 = new MyParser( -myflag => 1 );

   All arguments passed to the new() constructor will be treated as
key/value pairs in a hash-table. The newly constructed object will be
initialized by copying the contents of the given hash-table (which may
have been empty). The new() constructor for this class and all of its
subclasses returns a blessed reference to the initialized object
(hash-table).

initialize()
============

     $parser->initialize();

   This method performs any necessary object initialization. It takes no
arguments (other than the object instance of course, which is typically
copied to a local variable named `$self'). If subclasses override this
method then they must be sure to invoke `$self->SUPER::initialize()'.

begin_pod()
===========

     $parser->begin_pod();

   This method is invoked at the beginning of processing for each POD
document that is encountered in the input. Subclasses should override this
method to perform any per-document initialization.

begin_input()
=============

     $parser->begin_input();

   This method is invoked by parse_from_filehandle() immediately before
processing input from a filehandle. The base class implementation does
nothing, however, subclasses may override it to perform any per-file
initializations.

   Note that if multiple files are parsed for a single POD document
(perhaps the result of some future `=include' directive) this method is
invoked for every file that is parsed. If you wish to perform certain
initializations once per document, then you should use begin_pod().

end_input()
===========

     $parser->end_input();

   This method is invoked by parse_from_filehandle() immediately after
processing input from a filehandle. The base class implementation does
nothing, however, subclasses may override it to perform any per-file
cleanup actions.

   Please note that if multiple files are parsed for a single POD document
(perhaps the result of some kind of `=include' directive) this method is
invoked for every file that is parsed. If you wish to perform certain
cleanup actions once per document, then you should use end_pod().

end_pod()
=========

     $parser->end_pod();

   This method is invoked at the end of processing for each POD document
that is encountered in the input. Subclasses should override this method
to perform any per-document finalization.

preprocess_line()
=================

     $textline = $parser->preprocess_line($text, $line_num);

   This method should be overridden by subclasses that wish to perform any
kind of preprocessing for each line of input (before it has been
determined whether or not it is part of a POD paragraph). The parameter
$text is the input line; and the parameter `$line_num' is the line number
of the corresponding text line.

   The value returned should correspond to the new text to use in its
place.  If the empty string or an undefined value is returned then no
further processing will be performed for this line.

   Please note that the preprocess_line() method is invoked before the
preprocess_paragraph() method. After all (possibly preprocessed) lines in
a paragraph have been assembled together and it has been determined that
the paragraph is part of the POD documentation from one of the selected
sections, then preprocess_paragraph() is invoked.

   The base class implementation of this method returns the given text.

preprocess_paragraph()
======================

     $textblock = $parser->preprocess_paragraph($text, $line_num);

   This method should be overridden by subclasses that wish to perform any
kind of preprocessing for each block (paragraph) of POD documentation that
appears in the input stream. The parameter $text is the POD paragraph from
the input file; and the parameter `$line_num' is the line number for the
beginning of the corresponding paragraph.

   The value returned should correspond to the new text to use in its
place If the empty string is returned or an undefined value is returned,
then the given $text is ignored (not processed).

   This method is invoked after gathering up all the lines in a paragraph
and after determining the cutting state of the paragraph, but before
trying to further parse or interpret them. After preprocess_paragraph()
returns, the current cutting state (which is returned by
`$self->cutting()') is examined. If it evaluates to true then input text
(including the given $text) is cut (not processed) until the next POD
directive is encountered.

   Please note that the preprocess_line() method is invoked before the
preprocess_paragraph() method. After all (possibly preprocessed) lines in
a paragraph have been assembled together and either it has been determined
that the paragraph is part of the POD documentation from one of the
selected sections or the `-want_nonPODs' option is true, then
preprocess_paragraph() is invoked.

   The base class implementation of this method returns the given text.

METHODS FOR PARSING AND PROCESSING
==================================

   Pod::Parser provides several methods to process input text. These
methods typically won't need to be overridden (and in some cases they
can't be overridden), but subclasses may want to invoke them to exploit
their functionality.

parse_text()
============

     $ptree1 = $parser->parse_text($text, $line_num);
     $ptree2 = $parser->parse_text({%opts}, $text, $line_num);
     $ptree3 = $parser->parse_text(\%opts, $text, $line_num);

   This method is useful if you need to perform your own interpolation of
interior sequences and can't rely upon interpolate to expand them in
simple bottom-up order order.

   The parameter $text is a string or block of text to be parsed for
interior sequences; and the parameter `$line_num' is the line number
curresponding to the beginning of $text.

   parse_text() will parse the given text into a parse-tree of "nodes."
and interior-sequences.  Each "node" in the parse tree is either a
text-string, or a Pod::InteriorSequence.  The result returned is a
parse-tree of type Pod::ParseTree. Please see Pod/InputObjects,
for more information about Pod::InteriorSequence and
Pod::ParseTree.

   If desired, an optional hash-ref may be specified as the first argument
to customize certain aspects of the parse-tree that is created and
returned. The set of recognized option keywords are:

*-expand_seq* => *code-ref*|*method-name*
     Normally, the parse-tree returned by parse_text() will contain an
     unexpanded Pod::InteriorSequence object for each interior-sequence
     encountered. Specifying *-expand_seq* tells parse_text() to "expand"
     every interior-sequence it sees by invoking the referenced function
     (or named method of the parser object) and using the return value as
     the expanded result.

     If a subroutine reference was given, it is invoked as:

          &$code_ref( $parser, $sequence )

     and if a method-name was given, it is invoked as:

          $parser->method_name( $sequence )

     where $parser is a reference to the parser object, and `$sequence' is
     a reference to the interior-sequence object.  [NOTE: If the
     interior_sequence() method is specified, then it is invoked according
     to the interface specified in `"interior_sequence()"' in this node].

*-expand_text* => *code-ref*|*method-name*
     Normally, the parse-tree returned by parse_text() will contain a
     text-string for each contiguous sequence of characters outside of an
     interior-sequence. Specifying *-expand_text* tells parse_text() to
     "preprocess" every such text-string it sees by invoking the referenced
     function (or named method of the parser object) and using the return
     value as the preprocessed (or "expanded") result. [Note that if the
     result is an interior-sequence, then it will not be expanded as
     specified by the *-expand_seq* option; Any such recursive expansion
     needs to be handled by the specified callback routine.]

     If a subroutine reference was given, it is invoked as:

          &$code_ref( $parser, $text, $ptree_node )

     and if a method-name was given, it is invoked as:

          $parser->method_name( $text, $ptree_node )

     where $parser is a reference to the parser object, $text is the
     text-string encountered, and `$ptree_node' is a reference to the
     current node in the parse-tree (usually an interior-sequence object
     or else the top-level node of the parse-tree).

*-expand_ptree* => *code-ref*|*method-name*
     Rather than returning a Pod::ParseTree, pass the parse-tree as an
     argument to the referenced subroutine (or named method of the parser
     object) and return the result instead of the parse-tree object.

     If a subroutine reference was given, it is invoked as:

          &$code_ref( $parser, $ptree )

     and if a method-name was given, it is invoked as:

          $parser->method_name( $ptree )

     where $parser is a reference to the parser object, and `$ptree' is a
     reference to the parse-tree object.

interpolate()
=============

     $textblock = $parser->interpolate($text, $line_num);

   This method translates all text (including any embedded interior
sequences) in the given text string $text and returns the interpolated
result. The parameter `$line_num' is the line number corresponding to the
beginning of $text.

   interpolate() merely invokes a private method to recursively expand
nested interior sequences in bottom-up order (innermost sequences are
expanded first). If there is a need to expand nested sequences in some
alternate order, use *parse_text* instead.

parse_paragraph()
=================

     $parser->parse_paragraph($text, $line_num);

   This method takes the text of a POD paragraph to be processed, along
with its corresponding line number, and invokes the appropriate method
(one of command(), verbatim(), or textblock()).

   For performance reasons, this method is invoked directly without any
dynamic lookup; Hence subclasses may not override it!

parse_from_filehandle()
=======================

     $parser->parse_from_filehandle($in_fh,$out_fh);

   This method takes an input filehandle (which is assumed to already be
opened for reading) and reads the entire input stream looking for blocks
(paragraphs) of POD documentation to be processed. If no first argument is
given the default input filehandle STDIN is used.

   The `$in_fh' parameter may be any object that provides a *getline()*
method to retrieve a single line of input text (hence, an appropriate
wrapper object could be used to parse PODs from a single string or an
array of strings).

   Using `$in_fh->getline()', input is read line-by-line and assembled
into paragraphs or "blocks" (which are separated by lines containing
nothing but whitespace). For each block of POD documentation encountered
it will invoke a method to parse the given paragraph.

   If a second argument is given then it should correspond to a filehandle
where output should be sent (otherwise the default output filehandle is
STDOUT if no output filehandle is currently in use).

   NOTE: For performance reasons, this method caches the input stream at
the top of the stack in a local variable. Any attempts by clients to
change the stack contents during processing when in the midst executing of
this method *will not affect* the input stream used by the current
invocation of this method.

   This method does not usually need to be overridden by subclasses.

parse_from_file()
=================

     $parser->parse_from_file($filename,$outfile);

   This method takes a filename and does the following:

   * opens the input and output files for reading (creating the
     appropriate filehandles)

   * invokes the parse_from_filehandle() method passing it the
     corresponding input and output filehandles.

   * closes the input and output files.

   If the special input filename "-" or "<&STDIN" is given then the STDIN
filehandle is used for input (and no open or close is performed). If no
input filename is specified then "-" is implied.

   If a second argument is given then it should be the name of the desired
output file. If the special output filename "-" or ">&STDOUT" is given
then the STDOUT filehandle is used for output (and no open or close is
performed). If the special output filename ">&STDERR" is given then the
STDERR filehandle is used for output (and no open or close is performed).
If no output filehandle is currently in use and no output filename is
specified, then "-" is implied.

   This method does not usually need to be overridden by subclasses.

ACCESSOR METHODS
================

   Clients of Pod::Parser should use the following methods to access
instance data fields:

errorsub()
==========

     $parser->errorsub("method_name");
     $parser->errorsub(\&warn_user);
     $parser->errorsub(sub { print STDERR, @_ });

   Specifies the method or subroutine to use when printing error messages
about POD syntax. The supplied method/subroutine must return TRUE upon
successful printing of the message. If undef is given, then the warn
builtin is used to issue error messages (this is the default behavior).

     my $errorsub = $parser->errorsub()
     my $errmsg = "This is an error message!\n"
     (ref $errorsub) and &{$errorsub}($errmsg)
         or (defined $errorsub) and $parser->$errorsub($errmsg)
             or  warn($errmsg);

   Returns a method name, or else a reference to the user-supplied
subroutine used to print error messages. Returns undef if the warn builtin
is used to issue error messages (this is the default behavior).

cutting()
=========

     $boolean = $parser->cutting();

   Returns the current `cutting' state: a boolean-valued scalar which
evaluates to true if text from the input file is currently being "cut"
(meaning it is not considered part of the POD document).

     $parser->cutting($boolean);

   Sets the current `cutting' state to the given value and returns the
result.

parseopts()
===========

   When invoked with no additional arguments, parseopts returns a hashtable
of all the current parsing options.

     ## See if we are parsing non-POD sections as well as POD ones
     my %opts = $parser->parseopts();
     $opts{'-want_nonPODs}' and print "-want_nonPODs\n";

   When invoked using a single string, parseopts treats the string as the
name of a parse-option and returns its corresponding value if it exists
(returns undef if it doesn't).

     ## Did we ask to see '=cut' paragraphs?
     my $want_cut = $parser->parseopts('-process_cut_cmd');
     $want_cut and print "-process_cut_cmd\n";

   When invoked with multiple arguments, parseopts treats them as
key/value pairs and the specified parse-option names are set to the given
values. Any unspecified parse-options are unaffected.

     ## Set them back to the default
     $parser->parseopts(-warnings => 0);

   When passed a single hash-ref, parseopts uses that hash to completely
reset the existing parse-options, all previous parse-option values are
lost.

     ## Reset all options to default
     $parser->parseopts( { } );

   See `"PARSING OPTIONS"' in this node for more information on the name
and meaning of each parse-option currently recognized.

output_file()
=============

     $fname = $parser->output_file();

   Returns the name of the output file being written.

output_handle()
===============

     $fhandle = $parser->output_handle();

   Returns the output filehandle object.

input_file()
============

     $fname = $parser->input_file();

   Returns the name of the input file being read.

input_handle()
==============

     $fhandle = $parser->input_handle();

   Returns the current input filehandle object.

input_streams()
===============

     $listref = $parser->input_streams();

   Returns a reference to an array which corresponds to the stack of all
the input streams that are currently in the middle of being parsed.

   While parsing an input stream, it is possible to invoke
parse_from_file() or parse_from_filehandle() to parse a new input stream
and then return to parsing the previous input stream. Each input stream to
be parsed is pushed onto the end of this input stack before any of its
input is read. The input stream that is currently being parsed is always
at the end (or top) of the input stack. When an input stream has been
exhausted, it is popped off the end of the input stack.

   Each element on this input stack is a reference to Pod::InputSource
object. Please see Pod/InputObjects, for more
details.

   This method might be invoked when printing diagnostic messages, for
example, to obtain the name and line number of the all input files that
are currently being processed.

top_stream()
============

     $hashref = $parser->top_stream();

   Returns a reference to the hash-table that represents the element that
is currently at the top (end) of the input stream stack (see
`"input_streams()"' in this node). The return value will be the undef if
the input stack is empty.

   This method might be used when printing diagnostic messages, for
example, to obtain the name and line number of the current input file.

PRIVATE METHODS AND DATA
========================

   Pod::Parser makes use of several internal methods and data fields which
clients should not need to see or use. For the sake of avoiding name
collisions for client data and methods, these methods and fields are
briefly discussed here. Determined hackers may obtain further information
about them by reading the Pod::Parser source code.

   Private data fields are stored in the hash-object whose reference is
returned by the new() constructor for this class. The names of all private
methods and data-fields used by Pod::Parser begin with a prefix of "_" and
match the regular expression `/^_\w+$/'.

_push_input_stream()
====================

     $hashref = $parser->_push_input_stream($in_fh,$out_fh);

   This method will push the given input stream on the input stack and
perform any necessary beginning-of-document or beginning-of-file
processing. The argument `$in_fh' is the input stream filehandle to push,
and `$out_fh' is the corresponding output filehandle to use (if it is not
given or is undefined, then the current output stream is used, which
defaults to standard output if it doesnt exist yet).

   The value returned will be reference to the hash-table that represents
the new top of the input stream stack. *Please Note* that it is possible
for this method to use default values for the input and output file
handles. If this happens, you will need to look at the INPUT and OUTPUT
instance data members to determine their new values.

_pop_input_stream()
===================

     $hashref = $parser->_pop_input_stream();

   This takes no arguments. It will perform any necessary end-of-file or
end-of-document processing and then pop the current input stream from the
top of the input stack.

   The value returned will be reference to the hash-table that represents
the new top of the input stream stack.

TREE-BASED PARSING
==================

   If straightforward stream-based parsing wont meet your needs (as is
likely the case for tasks such as translating PODs into structured markup
languages like HTML and XML) then you may need to take the tree-based
approach. Rather than doing everything in one pass and calling the
interpolate() method to expand sequences into text, it may be desirable to
instead create a parse-tree using the parse_text() method to return a
tree-like structure which may contain an ordered list list of children
(each of which may be a text-string, or a similar tree-like structure).

   Pay special attention to `"METHODS FOR PARSING AND PROCESSING"' in this
node and to the objects described in Pod/InputObjects.
The former describes the gory details and parameters
for how to customize and extend the parsing behavior of Pod::Parser.
Pod::InputObjects provides several objects that may all be used
interchangeably as parse-trees. The most obvious one is the Pod::ParseTree
object. It defines the basic interface and functionality that all things
trying to be a POD parse-tree should do. A Pod::ParseTree is defined such
that each "node" may be a text-string, or a reference to another
parse-tree.  Each Pod::Paragraph object and each Pod::InteriorSequence
object also supports the basic parse-tree interface.

   The parse_text() method takes a given paragraph of text, and returns a
parse-tree that contains one or more children, each of which may be a
text-string, or an InteriorSequence object. There are also
callback-options that may be passed to parse_text() to customize the way
it expands or transforms interior-sequences, as well as the returned
result. These callbacks can be used to create a parse-tree with
custom-made objects (which may or may not support the parse-tree
interface, depending on how you choose to do it).

   If you wish to turn an entire POD document into a parse-tree, that
process is fairly straightforward. The parse_text() method is the key to
doing this successfully. Every paragraph-callback (i.e. the polymorphic
methods for command(), verbatim(), and textblock() paragraphs) takes a
Pod::Paragraph object as an argument. Each paragraph object has a
parse_tree() method that can be used to get or set a corresponding
parse-tree. So for each of those paragraph-callback methods, simply call
parse_text() with the options you desire, and then use the returned
parse-tree to assign to the given paragraph object.

   That gives you a parse-tree for each paragraph - so now all you need is
an ordered list of paragraphs. You can maintain that yourself as a data
element in the object/hash. The most straightforward way would be simply
to use an array-ref, with the desired set of custom "options" for each
invocation of *parse_text*. Let's assume the desired option-set is given
by the hash %options. Then we might do something like the following:

     package MyPodParserTree;

     @ISA = qw( Pod::Parser );

     ...

     sub begin_pod {
         my $self = shift;
         $self->{'-paragraphs'} = [];  ## initialize paragraph list
     }

     sub command {
         my ($parser, $command, $paragraph, $line_num, $pod_para) = @_;
         my $ptree = $parser->parse_text({%options}, $paragraph, ...);
         $pod_para->parse_tree( $ptree );
         push @{ $self->{'-paragraphs'} }, $pod_para;
     }

     sub verbatim {
         my ($parser, $paragraph, $line_num, $pod_para) = @_;
         push @{ $self->{'-paragraphs'} }, $pod_para;
     }

     sub textblock {
         my ($parser, $paragraph, $line_num, $pod_para) = @_;
         my $ptree = $parser->parse_text({%options}, $paragraph, ...);
         $pod_para->parse_tree( $ptree );
         push @{ $self->{'-paragraphs'} }, $pod_para;
     }

     ...

     package main;
     ...
     my $parser = new MyPodParserTree(...);
     $parser->parse_from_file(...);
     my $paragraphs_ref = $parser->{'-paragraphs'};

   Of course, in this module-author's humble opinion, I'd be more inclined
to use the existing Pod::ParseTree object than a simple array. That way
everything in it, paragraphs and sequences, all respond to the same core
interface for all parse-tree nodes. The result would look something like:

     package MyPodParserTree2;

     ...

     sub begin_pod {
         my $self = shift;
         $self->{'-ptree'} = new Pod::ParseTree;  ## initialize parse-tree
     }

     sub parse_tree {
         ## convenience method to get/set the parse-tree for the entire POD
         (@_ > 1)  and  $_[0]->{'-ptree'} = $_[1];
         return $_[0]->{'-ptree'};
     }

     sub command {
         my ($parser, $command, $paragraph, $line_num, $pod_para) = @_;
         my $ptree = $parser->parse_text({<<options>>}, $paragraph, ...);
         $pod_para->parse_tree( $ptree );
         $parser->parse_tree()->append( $pod_para );
     }

     sub verbatim {
         my ($parser, $paragraph, $line_num, $pod_para) = @_;
         $parser->parse_tree()->append( $pod_para );
     }

     sub textblock {
         my ($parser, $paragraph, $line_num, $pod_para) = @_;
         my $ptree = $parser->parse_text({<<options>>}, $paragraph, ...);
         $pod_para->parse_tree( $ptree );
         $parser->parse_tree()->append( $pod_para );
     }

     ...

     package main;
     ...
     my $parser = new MyPodParserTree2(...);
     $parser->parse_from_file(...);
     my $ptree = $parser->parse_tree;
     ...

   Now you have the entire POD document as one great big parse-tree. You
can even use the *-expand_seq* option to *parse_text* to insert whole
different kinds of objects. Just don't expect Pod::Parser to know what to
do with them after that. That will need to be in your code. Or,
alternatively, you can insert any object you like so long as it conforms
to the Pod::ParseTree interface.

   One could use this to create subclasses of *Pod::Paragraphs* and
*Pod::InteriorSequences* for specific commands (or to create your own
custom node-types in the parse-tree) and add some kind of *emit()* method
to each custom node/subclass object in the tree. Then all you'd need to do
is recursively walk the tree in the desired order, processing the children
(most likely from left to right) by formatting them if they are
text-strings, or by calling their *emit()* method if they are
objects/references.

SEE ALSO
========

   See Pod/InputObjects, Pod/Select,

   Pod::InputObjects defines POD input objects corresponding to command
paragraphs, parse-trees, and interior-sequences.

   Pod::Select is a subclass of Pod::Parser which provides the ability to
selectively include and/or exclude sections of a POD document from being
translated based upon the current heading, subheading, subsubheading, etc.

AUTHOR
======

   Brad Appleton <bradapp@enteract.com>

   Based on code for Pod::Text written by Tom Christiansen
<tchrist@mox.perl.com>

A POD to PDF translator
***********************

NAME
====

   Pdf.pm - A POD to PDF translator

SYNOPSIS
========

   All systems:

     pod2pdf([options])

     Also from the shell prompt in conjunction with the script "pod2pdf" (see "scripts/pod2pdf"):

     $ pod2pdf [options] <file>

   E<nbsp>

DESCRIPTION
===========

   `pod2pdf' translates single POD (Perl Plain Old Documentation) files
and translates them to `PDF' (Adobe Portable Document Format) files.
Future extensions to this program may permit translation of multiple POD
files into a single book. At this stage the emphasis is on simplicity and
ease of use. The output `PDF' file takes the name of the input file with
the suffix `.pdf'.

   `PDF Outlines' are created at three levels corresponding to =head1,
=head2 and =item. The `outline' headings are reproduced as a `Table of
Contents' page. Long =item strings are curtailed to a length which will
fit reasonably in the space available on the page. When the `PDF' document
is viewed on screen, the `outlines' (sometimes known as Bookmarks) provide
links to the appropriate page. When the document is printed the `ToC'
provides the same facility.

   Links of the form `xyz.pm' in this node and links to named destinations
are not implemented since it is rarely possible to resolve the link except
in the limited instance of links to named destinations in the document
itself. Links to URL addresses (including http, ftp and mailto) are active
however and call the resident default browser. How that responds to the
call will depend to some extent on the type of browser and the environment
in which it finds itself.

   The POD specification `perlpod.pod' allows blocks of text to be
enclosed by =begin and =end markers. The block-type my be indicated by a
string after =begin (for example `=begin html' would indicate an HTML
block) of which *roff, man, latex, tex and html* are recognised entities.
Specification `perlpod.pod' goes on to say that *"A formatter that can
utilize that format will use the section, otherwise it will be completely
ignored."* This seems to defeat the object of the documentation since
quite different output might be expected according to which translator was
used. It is doubtful if that would necessarily be the author's intention.

   This translator, `Pdf.pm', in all cases reproduces the section enclosed
by a `=begin/=end' pair (or any paragraph following =for which is
similarly defined in `perlpod.pod') but in a special color so as to give a
visual warning to the reader that special meaning might attach to the
block of text.

   The primary objective is to produce a translation of a POD file of good
typographical quality which can be printed on any printer (particularly
low-cost non-PostScript ink-jet printers) in any environment. In this
connection it must be recognised that some authors use POD mark-up more
intelligently and to better effect than others. Not infrequently mistakes
in formatting (frequently the absence of a blank line to end a block)
result in files which do not translate properly on some or all
translators. `PDF' files provide the very useful ability to quickly screen
the translation for visual checking before the file is despatched to the
printer.

OPTIONS
=======

   In the interests of simplicity and ease of use the number of options
has been kept to a minimum. However an option to set paper size remains an
unavoidable necessity untill such time as the world can agree on one
standard. Only *A4* and *USLetter* are preprogrammed, other custom sizes
will require an edit to the `Pdf.pm' code.

   Options are implemented using Getopt::Long using the syntax `--[key]='
as indicated below. The order in which options are entered is immaterial.

*Paper size*
     The default paper size is A4 (which may be re-editied to a custom
     size):

          my $x_size = 595;  # default page width  (pixels)
          my $y_size = 842;  # default page height (pixels)

          The option:

          --paper=usletter

          sets the North American standard size:

          my $x_size = 612;  # US letter page width  (pixels)
          my $y_size = 792;  # US letter page height (pixels)

          The program will accept any (reasonable) paper size.

*Error reporting*
     Limited error reporting to STDERR may be turned on by setting
     `$verbose':

          --verbose=1     # progress reports
          --verbose=2     # more extensive progress reports about links

          =item B<Input filename>

     The input file name may be entered in various ways on most sytems. It
     may be included as an option, or as a string argument to `pod2pdf',
     or as an item in `@ARGV' or finally, as a command line entry on
     systems which support command lines. As an option the syntax is:

          --podname=filename

          =item B<Duplex printing>

     The output is always "duplex" in the sense that the pages are
     "handed" with the page number (for example) at the bottom right (on
     odd pages) and the bottom left (on even pages). However not everyone
     possesses a duplex printer capable of automatically printing on both
     sides of the paper, but fortunately most if not all printers are
     capable of printing all the odd sides in one pass and all the even
     pages (on the reverse side of the paper) in a second pass, which
     achieves the same result. Even if that is either not possible or not
     worth the effort, and the whole document is printed single sided, the
     handing of the pages is no great drawback. There is really no
     compelling need for the complication of a switch to select simplex or
     duplex mode.

*Document name*
     Since the program is restricted to processing single POD files the
     input file name can be used as the output file name distinguished
     simply by adding the extension `.pdf' to that name. If a file of that
     name already exists it will be overwritten without warning.

EXAMPLES
========

Example 1 (all platforms)
          use Pod::Pdf;
          push @ARGV, qw(--paper usletter --verbose 1);
          # alternatively "push @ARGV, qw(-paper usletter -verbose 1)"
          # but NB "push @ARGV, '--verbose 2'" will NOT work
          push @ARGV, 'podfilename';
          pod2pdf(@ARGV);

Example 2 (all platforms)
          use Pod::Pdf;
          pod2pdf(
              '--paper=usletter',
              'podfilename'
          );

Example 3 (all platforms)
          use Pod::Pdf;
          pod2pdf(
              '--paper=usletter',
              '--verbose=2',
              '--podfile=podfilename'
          );

Example 4 (MacOS droplet)
          use Pod::Pdf;
          unshift @ARGV, '--paper=usletter';
          pod2pdf(@ARGV);

AUTHOR
======

   Alan J. Fry

e-mail `mailto:ajf@afco.demon.co.uk' in this node
WWW `http:' in this node
HISTORY
=======

Version 1.0 released 04 April 2000
Version 1.1 released 18 April 2000
     This version supports active URI links and features improved
     formatting.

     For many helpful suggestions sincere thanks (in alphabetical order)
     to:

     Stas Bekman <sbekman@stason.org>

     Rob Carraretto <carraretto@telus.net>

     M. Christian Hanson <chanson@banta-im.com>

     Marcus Harnisch <harnisch@mikrom.de>

     Johannes la PoutrŽ <jlpoutre@corp.nl.home.com>

     Henrik Tougaard <ht000@foa.dk>

Version 1.2 released 26 May 2000
     This version has essentially the same functionality as version 1.1
     but is reshaped into modular format. In reshaping the module grateful
     thanks are due to Axel Rose `http:' in this node whose suggestion to
     place the opening statements of the program into the subroutine
     `pod2pdf' has been adopted together with his proposals for exporting
     the function name. This arrangement brings `Pdf.pm' more into line
     with the structure of other POD translators. His assistance in
     testing the module on a variety of platforms (MacOS, Linux and
     Windows) has been invaluable as has his advice on the structure of
     the interface and many fine details too numerous to mention
     individually.

VERSION
=======

v1.2 Friday, 26 May 2000
COPYRIGHT
=========

© Alan J. Fry April 2000
This program is distributed under the terms of the Artistic Licence

Convert POD data to formatted ASCII text
****************************************

NAME
====

   Pod::PlainText - Convert POD data to formatted ASCII text

SYNOPSIS
========

     use Pod::PlainText;
     my $parser = Pod::PlainText->new (sentence => 0, width => 78);

     # Read POD from STDIN and write to STDOUT.
     $parser->parse_from_filehandle;

     # Read POD from file.pod and write to file.txt.
     $parser->parse_from_file ('file.pod', 'file.txt');

DESCRIPTION
===========

   Pod::PlainText is a module that can convert documentation in the POD
format (the preferred language for documenting Perl) into formatted ASCII.
It uses no special formatting controls or codes whatsoever, and its
output is therefore suitable for nearly any device.

   As a derived class from Pod::Parser, Pod::PlainText supports the same
methods and interfaces.  See Pod/Parser, for all the
details; briefly, one creates a new parser with `Pod::PlainText->new()'
and then calls either parse_from_filehandle() or parse_from_file().

   new() can take options, in the form of key/value pairs, that control the
behavior of the parser.  The currently recognized options are:

alt
     If set to a true value, selects an alternate output format that,
     among other things, uses a different heading style and marks =item
     entries with a colon in the left margin.  Defaults to false.

indent
     The number of spaces to indent regular text, and the default
     indentation for =over blocks.  Defaults to 4.

loose
     If set to a true value, a blank line is printed after a =head1
     heading.  If set to false (the default), no blank line is printed
     after =head1, although one is still printed after =head2.  This is
     the default because it's the expected formatting for manual pages; if
     you're formatting arbitrary text documents, setting this to true may
     result in more pleasing output.

sentence
     If set to a true value, Pod::PlainText will assume that each sentence
     ends in two spaces, and will try to preserve that spacing.  If set to
     false, all consecutive whitespace in non-verbatim paragraphs is
     compressed into a single space.  Defaults to true.

width
     The column at which to wrap text on the right-hand side.  Defaults to
     76.

   The standard Pod::Parser method parse_from_filehandle() takes up to two
arguments, the first being the file handle to read POD from and the second
being the file handle to write the formatted output to.  The first defaults
to STDIN if not given, and the second defaults to STDOUT.  The method
parse_from_file() is almost identical, except that its two arguments are
the input and output disk files instead.  See Pod/Parser,
for the specific details.

DIAGNOSTICS
===========

Bizarre space in item
     (W) Something has gone wrong in internal =item processing.  This
     message indicates a bug in Pod::PlainText; you should never see it.

Can't open %s for reading: %s
     (F) Pod::PlainText was invoked via the compatibility mode pod2text()
     interface and the input file it was given could not be opened.

Unknown escape: %s
     (W) The POD source contained an `E<>' escape that Pod::PlainText
     didn't know about.

Unknown sequence: %s
     (W) The POD source contained a non-standard internal sequence
     (something of the form `X<>') that Pod::PlainText didn't know about.

Unmatched =back
     (W) Pod::PlainText encountered a =back command that didn't correspond
     to an =over command.

RESTRICTIONS
============

   Embedded Ctrl-As (octal 001) in the input will be mapped to spaces on
output, due to an internal implementation detail.

NOTES
=====

   This is a replacement for an earlier Pod::Text module written by Tom
Christiansen.  It has a revamped interface, since it now uses Pod::Parser,
but an interface roughly compatible with the old Pod::Text::pod2text()
function is still available.  Please change to the new calling convention,
though.

   The original Pod::Text contained code to do formatting via termcap
sequences, although it wasn't turned on by default and it was problematic
to get it to work at all.  This rewrite doesn't even try to do that, but a
subclass of it does.  Look for `Pod::Text::Termcap|Pod::Text::Termcap' in
this node.

SEE ALSO
========

   `Pod::Parser|Pod::Parser' in this node,
`Pod::Text::Termcap|Pod::Text::Termcap' in this node, pod2text(1)

AUTHOR
======

   Russ Allbery <rra@stanford.edu>, based *very* heavily on the original
Pod::Text by Tom Christiansen <tchrist@mox.perl.com> and its conversion to
Pod::Parser by Brad Appleton <bradapp@enteract.com>.

Perl extension for converting Pod to old style Pod.
***************************************************

NAME
====

   Pod::Plainer - Perl extension for converting Pod to old style Pod.

SYNOPSIS
========

     use Pod::Plainer;

     my $parser = Pod::Plainer -> new ();
     $parser -> parse_from_filehandle(\*STDIN);

DESCRIPTION
===========

   Pod::Plainer uses Pod::Parser which takes Pod with the (new) 'C<< ..
>>' constructs and returns the old(er) style with just 'C<>'; '<' and '>'
are replaced by 'E<lt>' and 'E<gt>'.

   This can be used to pre-process Pod before using tools which do not
recognise the new style Pods.

EXPORT
------

   None by default.

AUTHOR
======

   Robin Barker, rmb1@cise.npl.co.uk

SEE ALSO
========

   See Pod/Parser.

Pod::Rtf
********

NAME
====

   Pod::Rtf

SYNOPSIS
========

     $parser = new Pod::Rtf();
     $parser->parse_from_filehandle(\*STDIN)  if (@ARGV == 0);
     for (@ARGV) {
        my $file = $_;
        $file =~ s/\..*$//;
        $Pod::Rtf::pound_note = $_;
        $Pod::Rtf::dollar_note = $file;
        $Pod::Rtf::K_note = $file;
        $parser->parse_from_file($_);
     }

DESCRIPTION
===========

   Uses Pod::Parser to convert pod documentation to Rich Text Format (rtf)
suitable for compilation by a Windows Help compiler.

SEE ALSO
========

   See Perl (perl.info).  See Pod/Rtf,
Pod/Parser.

AUTHOR
======

   Peter Prymmer.

extract selected sections of POD from input
*******************************************

NAME
====

   Pod::Select, podselect() - extract selected sections of POD from input

SYNOPSIS
========

     use Pod::Select;

     ## Select all the POD sections for each file in @filelist
     ## and print the result on standard output.
     podselect(@filelist);

     ## Same as above, but write to tmp.out
     podselect({-output => "tmp.out"}, @filelist):

     ## Select from the given filelist, only those POD sections that are
     ## within a 1st level section named any of: NAME, SYNOPSIS, OPTIONS.
     podselect({-sections => ["NAME|SYNOPSIS", "OPTIONS"]}, @filelist):

     ## Select the "DESCRIPTION" section of the PODs from STDIN and write
     ## the result to STDERR.
     podselect({-output => ">&STDERR", -sections => ["DESCRIPTION"]}, \*STDIN);

   or

     use Pod::Select;

     ## Create a parser object for selecting POD sections from the input
     $parser = new Pod::Select();

     ## Select all the POD sections for each file in @filelist
     ## and print the result to tmp.out.
     $parser->parse_from_file("<&STDIN", "tmp.out");

     ## Select from the given filelist, only those POD sections that are
     ## within a 1st level section named any of: NAME, SYNOPSIS, OPTIONS.
     $parser->select("NAME|SYNOPSIS", "OPTIONS");
     for (@filelist) { $parser->parse_from_file($_); }

     ## Select the "DESCRIPTION" and "SEE ALSO" sections of the PODs from
     ## STDIN and write the result to STDERR.
     $parser->select("DESCRIPTION");
     $parser->add_selection("SEE ALSO");
     $parser->parse_from_filehandle(\*STDIN, \*STDERR);

REQUIRES
========

   perl5.005, Pod::Parser, Exporter, Carp

EXPORTS
=======

   podselect()

DESCRIPTION
===========

   podselect() is a function which will extract specified sections of pod
documentation from an input stream. This ability is provided by the
Pod::Select module which is a subclass of Pod::Parser.  Pod::Select
provides a method named select() to specify the set of POD sections to
select for processing/printing. podselect() merely creates a Pod::Select
object and then invokes the podselect() followed by parse_from_file().

SECTION SPECIFICATIONS
======================

   podselect() and *Pod::Select::select()* may be given one or more
"section specifications" to restrict the text processed to only the
desired set of sections and their corresponding subsections.  A section
specification is a string containing one or more Perl-style regular
expressions separated by forward slashes ("/").  If you need to use a
forward slash literally within a section title you can escape it with a
backslash ("\/").

   The formal syntax of a section specification is:

     *head1-title-regex*/*head2-title-regex*/...

   Any omitted or empty regular expressions will default to ".*".  Please
note that each regular expression given is implicitly anchored by adding
"^" and "$" to the beginning and end.  Also, if a given regular expression
starts with a "!" character, then the expression is *negated* (so `!foo'
would match anything except foo).

   Some example section specifications follow.

Match the NAME and SYNOPSIS sections and all of their subsections:
     `NAME|SYNOPSIS'

Match only the `Question' and `Answer' subsections of the DESCRIPTION section:
     `DESCRIPTION/Question|Answer'

Match the Comments subsection of all sections:
     `/Comments'

Match all subsections of DESCRIPTION except for Comments:
     `DESCRIPTION/!Comments'

Match the DESCRIPTION section but do not match any of its subsections:
     `DESCRIPTION/!.+'

Match all top level sections but none of their subsections:
     `/!.+'

RANGE SPECIFICATIONS
====================

   podselect() and *Pod::Select::select()* may be given one or more "range
specifications" to restrict the text processed to only the desired ranges
of paragraphs in the desired set of sections. A range specification is a
string containing a single Perl-style regular expression (a regex), or
else two Perl-style regular expressions (regexs) separated by a ".."
(Perl's "range" operator is "..").  The regexs in a range specification
are delimited by forward slashes ("/").  If you need to use a forward
slash literally within a regex you can escape it with a backslash ("\/").

   The formal syntax of a range specification is:

     /*start-range-regex*/[../*end-range-regex*/]

   Where each the item inside square brackets (the ".." followed by the
end-range-regex) is optional. Each "range-regex" is of the form:

     =cmd-expr text-expr

   Where *cmd-expr* is intended to match the name of one or more POD
commands, and *text-expr* is intended to match the paragraph text for the
command. If a range-regex is supposed to match a POD command, then the
first character of the regex (the one after the initial '/') absolutely
must be an single '=' character; it may not be anything else (not even a
regex meta-character) if it is supposed to match against the name of a POD
command.

   If no *=cmd-expr* is given then the text-expr will be matched against
plain textblocks unless it is preceded by a space, in which case it is
matched against verbatim text-blocks. If no *text-expr* is given then only
the command-portion of the paragraph is matched against.

   Note that these two expressions are each implicitly anchored. This
means that when matching against the command-name, there will be an
implicit '^' and '$' around the given *=cmd-expr*; and when matching
against the paragraph text there will be an implicit '\A' and '\Z' around
the given *text-expr*.

   Unlike with section-specs, the '!' character does not have any special
meaning (negation or otherwise) at the beginning of a range-spec!

   Some example range specifications follow.

Match all `=for html' paragraphs:
     `/=for html/'

Match all paragraphs between `=begin html' and `=end html' (note that this will not work correctly if such sections are nested):
     `/=begin html/../=end html/'

Match all paragraphs between the given =item name until the end of the current section:
     `/=item mine/../=head\d/'

Match all paragraphs between the given =item until the next item, or until the end of the itemized list (note that this will not work as desired if the item contains an itemized list nested within it):
     `/=item mine/../=(item|back)/'

OBJECT METHODS
==============

   The following methods are provided in this module. Each one takes a
reference to the object itself as an implicit first parameter.

curr_headings()
===============

     ($head1, $head2, $head3, ...) = $parser->curr_headings();
     $head1 = $parser->curr_headings(1);

   This method returns a list of the currently active section headings and
subheadings in the document being parsed. The list of headings returned
corresponds to the most recently parsed paragraph of the input.

   If an argument is given, it must correspond to the desired section
heading number, in which case only the specified section heading is
returned. If there is no current section heading at the specified level,
then undef is returned.

select()
========

     $parser->select($section_spec1,$section_spec2,...);

   This method is used to select the particular sections and subsections of
POD documentation that are to be printed and/or processed. The existing
set of selected sections is *replaced* with the given set of sections.
See add_selection() for adding to the current set of selected sections.

   Each of the `$section_spec' arguments should be a section specification
as described in `"SECTION SPECIFICATIONS"' in this node.  The section
specifications are parsed by this method and the resulting regular
expressions are stored in the invoking object.

   If no `$section_spec' arguments are given, then the existing set of
selected sections is cleared out (which means all sections will be
processed).

   This method should not normally be overridden by subclasses.

add_selection()
===============

     $parser->add_selection($section_spec1,$section_spec2,...);

   This method is used to add to the currently selected sections and
subsections of POD documentation that are to be printed and/or processed.
See <select()> for replacing the currently selected sections.

   Each of the `$section_spec' arguments should be a section specification
as described in `"SECTION SPECIFICATIONS"' in this node. The section
specifications are parsed by this method and the resulting regular
expressions are stored in the invoking object.

   This method should not normally be overridden by subclasses.

clear_selections()
==================

     $parser->clear_selections();

   This method takes no arguments, it has the exact same effect as invoking
<select()> with no arguments.

match_section()
===============

     $boolean = $parser->match_section($heading1,$heading2,...);

   Returns a value of true if the given section and subsection heading
titles match any of the currently selected section specifications in
effect from prior calls to select() and add_selection() (or if there are
no explictly selected/deselected sections).

   The arguments `$heading1', `$heading2', etc. are the heading titles of
the corresponding sections, subsections, etc. to try and match.  If
`$headingN' is omitted then it defaults to the current corresponding
section heading title in the input.

   This method should not normally be overridden by subclasses.

is_selected()
=============

     $boolean = $parser->is_selected($paragraph);

   This method is used to determine if the block of text given in
`$paragraph' falls within the currently selected set of POD sections and
subsections to be printed or processed. This method is also responsible
for keeping track of the current input section and subsections. It is
assumed that `$paragraph' is the most recently read (but not yet
processed) input paragraph.

   The value returned will be true if the `$paragraph' and the rest of the
text in the same section as `$paragraph' should be selected (included) for
processing; otherwise a false value is returned.

EXPORTED FUNCTIONS
==================

   The following functions are exported by this module. Please note that
these are functions (not methods) and therefore `do not' take an implicit
first argument.

podselect()
===========

     podselect(\%options,@filelist);

   *podselect* will print the raw (untranslated) POD paragraphs of all POD
sections in the given input files specified by `@filelist' according to
the given options.

   If any argument to *podselect* is a reference to a hash (associative
array) then the values with the following keys are processed as follows:

*-output*
     A string corresponding to the desired output file (or ">&STDOUT" or
     ">&STDERR"). The default is to use standard output.

*-sections*
     A reference to an array of sections specifications (as described in
     `"SECTION SPECIFICATIONS"' in this node) which indicate the desired
     set of POD sections and subsections to be selected from input. If no
     section specifications are given, then all sections of the PODs are
     used.

*-ranges*
     A reference to an array of range specifications (as described in
     `"RANGE SPECIFICATIONS"' in this node) which indicate the desired
     range of POD paragraphs to be selected from the desired input
     sections. If no range specifications are given, then all paragraphs
     of the desired sections are used.

   All other arguments should correspond to the names of input files
containing POD sections. A file name of "-" or "<&STDIN" will be
interpeted to mean standard input (which is the default if no filenames
are given).

PRIVATE METHODS AND DATA
========================

   Pod::Select makes uses a number of internal methods and data fields
which clients should not need to see or use. For the sake of avoiding name
collisions with client data and methods, these methods and fields are
briefly discussed here. Determined hackers may obtain further information
about them by reading the Pod::Select source code.

   Private data fields are stored in the hash-object whose reference is
returned by the new() constructor for this class. The names of all private
methods and data-fields used by Pod::Select begin with a prefix of "_" and
match the regular expression `/^_\w+$/'.

_compile_section_spec()
=======================

     $listref = $parser->_compile_section_spec($section_spec);

   This function (note it is a function and not a method) takes a section
specification (as described in `"SECTION SPECIFICATIONS"' in this node)
given in `$section_sepc', and compiles it into a list of regular
expressions. If `$section_spec' has no syntax errors, then a reference to
the list (array) of corresponding regular expressions is returned;
otherwise undef is returned and an error message is printed (using carp)
for each invalid regex.

$self->{_SECTION_HEADINGS}
--------------------------

   A reference to an array of the current section heading titles for each
heading level (note that the first heading level title is at index 0).

$self->{_SELECTED_SECTIONS}
---------------------------

   A reference to an array of references to arrays. Each subarray is a list
of anchored regular expressions (preceded by a "!" if the expression is to
be negated). The index of the expression in the subarray should correspond
to the index of the heading title in `$self->{_SECTION_HEADINGS}' that it
is to be matched against.

SEE ALSO
========

   See Pod/Parser,

AUTHOR
======

   Brad Appleton <bradapp@enteract.com>

   Based on code for *pod2text* written by Tom Christiansen
<tchrist@mox.perl.com>

Extracts embedded tests and code examples from POD
**************************************************

NAME
====

   Pod::Tests - Extracts embedded tests and code examples from POD

SYNOPSIS
========

   *LOOK AT pod2test FIRST!*

     use Pod::Tests;
     $p = Pod::Tests->new;

     $p->parse_file($file);
     $p->parse_fh($fh);
     $p->parse(@code);

     my @examples = $p->examples;
     my @tests    = $p->tests;

     foreach my $example (@examples) {
         print "The example:  '$example->{code}' was on line ".
               "$example->{line}\n";
     }

     my @test_code         = $p->build_tests(@tests);
     my @example_test_code = $p->build_examples(@examples);

DESCRIPTION
===========

   *LOOK AT pod2test FIRST!  THIS IS ALPHA CODE!*

   This is a specialized POD viewer to extract embedded tests and code
examples from POD.  It doesn't do much more than that.  pod2test does the
useful work.

Embedded Tests
--------------

   Embedding tests allows tests to be placed near the code its testing.
This is a nice supplement to the traditional .t files.

   A test is denoted using either "=for testing" or a "=begin/end testing"
block.

     =item B<is_pirate>

     @pirates = is_pirate(@arrrgs);

     Go through @arrrgs and return a list of pirates.

     =begin testing

     my @p = is_pirate('Blargbeard', 'Alfonse', 'Capt. Hampton', 'Wesley');
     ok(@p == 2);

     =end testing

     =cut

     sub is_pirate {
         ....
     }

Code Examples *EXPERIMENTAL*
----------------------------

   *BIG FAT WARNING* perldoc and the various pod2* reformatters are
inconsistant in how they deal with =also.  Some warn, some display it,
some choke.  So consider this to be a *Highly Experimental Feature*.

   Code examples in documentation are rarely tested.  Pod::Tests provides
a way to do some minimalist testing of your examples.

   A code example is denoted using either "=also for example" or an "=also
begin/end example" block.

   The `=also' tag provides that examples will both be extracted and
displayed as documentation.

     =also for example
     print "Here is a fine example of something or other.";

     =also begin example

     use LWP::Simple;
     getprint "http://www.goats.com";

     =also end example

Formatting
----------

   The code examples and embedded tests are not translated from POD, thus
all the C<> and B<> style escapes are not valid.  Its literal Perl code.

Parsing
-------

   After creating a Pod::Tests object, you parse the POD by calling one of
the available parsing methods documented below.  You can call parse as
many times as you'd like, all examples and tests found will stack up
inside the object.

Testing
-------

   Once extracted, the tests can be built into stand-alone testing code
using the build_tests() and build_examples() methods.  However, it is
recommended that you first look at the pod2test program before embarking
on this.

Methods
-------

new
          $parser = Pod::Tests->new;

     Returns a new Pod::Tests object which lets you read tests and examples
     out of a POD document.

parse
          $parser->parse(@code);

     Finds the examples and tests in a bunch of lines of Perl @code.  Once
     run they're available via examples() and testing().

_init
          $parser->_init;

     Initializes the state of the parser, but not the rest of the object.
     Should be called before each parse of new POD.

_beginfor
          $parser->_beginfor($format, $pod);

     Indicates that a =for tag has been seen.  $format (what immediately
     follows '=for'), and $pod is the rest of the POD on that line.

_endfor
          $parser->endfor;

     Indicates that the current =for block has ended.

_beginblock
          $parser->_beginblock($format);

     Indicates that the parser saw a =begin tag.  $format is the word
     immediately following =begin.

_endblock
          $parser->_endblock

     Indicates that the parser saw an =end tag for the current block.

parse_fh
parse_file
          $parser->parse_file($filename);
          $parser->parse_fh($fh);

     Just like parse() except it works on a file or a filehandle,
     respectively.

examples
testing
          @examples = $parser->examples;
          @testing  = $parser->tests;

     Returns the examples and tests found in the parsed POD documents.
     Each element of @examples and @testing is a hash representing an
     individual testing block and contains information about that block.

          $test->{code}         actual testing code
          $test->{line}         line from where the test was taken

     NOTE  In the future, these will become full-blown objects.

build_tests
          my @code = $p->build_tests(@tests);

     Returns a code fragment based on the given embedded @tests.  This
     fragment is expected to print the usual "ok/not ok" (or something
     Test::Harness can read) or nothing at all.

     Typical usage might be:

          my @code = $p->build_tests($p->tests);

     This fragment is suitable for placing into a larger test script.

     NOTE Look at pod2test before embarking on your own test building.

build_examples
          my @code = $p->build_examples(@examples);

     Similar to build_tests(), it creates a code fragment which tests the
     basic validity of your example code.  Essentially, it just makes sure
     it compiles.

     This is currently very primitive.

EXAMPLES
========

   Here's the simplest example, just finding the tests and examples in a
single module.

     my $p = Pod::Tests->new;
     $p->parse_file("path/to/Some.pm");

   And one to find all the tests and examples in a directory of files.
This illustrates building a set of examples and tests through multiple
calls to parse_file().

     my $p = Pod::Tests->new;
     opendir(PODS, "path/to/some/lib/") || die $!;
     while( my $file = readdir PODS ) {
         $p->parse_file($file);
     }
     printf "Found %d examples and %d tests in path/to/some/lib\n",
            scalar $p->examples, scalar $p->tests;

   Finally, an example of parsing your own POD using the DATA filehandle.

     use Fcntl qw(:seek);
     my $p = Pod::Tests->new;

     # Seek to the beginning of the current code.
     seek(DATA, 0, SEEK_SET) || die $!;
     $p->parse_fh(\*DATA);

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

NOTES and CAVEATS
=================

   This module is currently EXPERIMENTAL and only for use by pod2test.  If
you use it, the interface *will* change from out from under you.

   It currently does not use Pod::Parser.  I couldn't figure out how to
use it.  Instead, I use a simple, home-rolled parser.  This will
eventually be split out as Pod::Parser::Simple.

SEE ALSO
========

   `pod2test' in this node, Perl 6 RFC 183  http://dev.perl.org/rfc183.pod

   Similar schemes can be found in `SelfTest' in this node and
Test/Unit.

Convert POD data to formatted ASCII text
****************************************

NAME
====

   Pod::Text - Convert POD data to formatted ASCII text

SYNOPSIS
========

     use Pod::Text;
     my $parser = Pod::Text->new (sentence => 0, width => 78);

     # Read POD from STDIN and write to STDOUT.
     $parser->parse_from_filehandle;

     # Read POD from file.pod and write to file.txt.
     $parser->parse_from_file ('file.pod', 'file.txt');

DESCRIPTION
===========

   Pod::Text is a module that can convert documentation in the POD format
(the preferred language for documenting Perl) into formatted ASCII.  It
uses no special formatting controls or codes whatsoever, and its output is
therefore suitable for nearly any device.

   As a derived class from Pod::Parser, Pod::Text supports the same
methods and interfaces.  See Pod/Parser, for all the
details; briefly, one creates a new parser with `Pod::Text->new()' and
then calls either parse_from_filehandle() or parse_from_file().

   new() can take options, in the form of key/value pairs, that control the
behavior of the parser.  The currently recognized options are:

alt
     If set to a true value, selects an alternate output format that,
     among other things, uses a different heading style and marks =item
     entries with a colon in the left margin.  Defaults to false.

indent
     The number of spaces to indent regular text, and the default
     indentation for =over blocks.  Defaults to 4.

loose
     If set to a true value, a blank line is printed after a =head1
     heading.  If set to false (the default), no blank line is printed
     after =head1, although one is still printed after =head2.  This is
     the default because it's the expected formatting for manual pages; if
     you're formatting arbitrary text documents, setting this to true may
     result in more pleasing output.

quotes
     Sets the quote marks used to surround C<> text.  If the value is a
     single character, it is used as both the left and right quote; if it
     is two characters, the first character is used as the left quote and
     the second as the right quoted; and if it is four characters, the
     first two are used as the left quote and the second two as the right
     quote.

     This may also be set to the special value none, in which case no quote
     marks are added around C<> text.

sentence
     If set to a true value, Pod::Text will assume that each sentence ends
     in two spaces, and will try to preserve that spacing.  If set to
     false, all consecutive whitespace in non-verbatim paragraphs is
     compressed into a single space.  Defaults to true.

width
     The column at which to wrap text on the right-hand side.  Defaults to
     76.

   The standard Pod::Parser method parse_from_filehandle() takes up to two
arguments, the first being the file handle to read POD from and the second
being the file handle to write the formatted output to.  The first defaults
to STDIN if not given, and the second defaults to STDOUT.  The method
parse_from_file() is almost identical, except that its two arguments are
the input and output disk files instead.  See Pod/Parser,
for the specific details.

DIAGNOSTICS
===========

Bizarre space in item
     (W) Something has gone wrong in internal =item processing.  This
     message indicates a bug in Pod::Text; you should never see it.

Can't open %s for reading: %s
     (F) Pod::Text was invoked via the compatibility mode pod2text()
     interface and the input file it was given could not be opened.

Invalid quote specification "%s"
     (F) The quote specification given (the quotes option to the
     constructor) was invalid.  A quote specification must be one, two, or
     four characters long.

%s:%d: Unknown command paragraph "%s".
     (W) The POD source contained a non-standard command paragraph
     (something of the form `=command args') that Pod::Man didn't know
     about.  It was ignored.

Unknown escape: %s
     (W) The POD source contained an `E<>' escape that Pod::Text didn't
     know about.

Unknown sequence: %s
     (W) The POD source contained a non-standard internal sequence
     (something of the form `X<>') that Pod::Text didn't know about.

Unmatched =back
     (W) Pod::Text encountered a =back command that didn't correspond to an
     =over command.

RESTRICTIONS
============

   Embedded Ctrl-As (octal 001) in the input will be mapped to spaces on
output, due to an internal implementation detail.

NOTES
=====

   This is a replacement for an earlier Pod::Text module written by Tom
Christiansen.  It has a revamped interface, since it now uses Pod::Parser,
but an interface roughly compatible with the old Pod::Text::pod2text()
function is still available.  Please change to the new calling convention,
though.

   The original Pod::Text contained code to do formatting via termcap
sequences, although it wasn't turned on by default and it was problematic
to get it to work at all.  This rewrite doesn't even try to do that, but a
subclass of it does.  Look for `Pod::Text::Termcap|Pod::Text::Termcap' in
this node.

SEE ALSO
========

   `Pod::Parser|Pod::Parser' in this node,
`Pod::Text::Termcap|Pod::Text::Termcap' in this node, pod2text(1)

AUTHOR
======

   Russ Allbery <rra@stanford.edu>, based *very* heavily on the original
Pod::Text by Tom Christiansen <tchrist@mox.perl.com> and its conversion to
Pod::Parser by Brad Appleton <bradapp@enteract.com>.

Convert POD data to formatted color ASCII text
**********************************************

NAME
====

   Pod::Text::Color - Convert POD data to formatted color ASCII text

SYNOPSIS
========

     use Pod::Text::Color;
     my $parser = Pod::Text::Color->new (sentence => 0, width => 78);

     # Read POD from STDIN and write to STDOUT.
     $parser->parse_from_filehandle;

     # Read POD from file.pod and write to file.txt.
     $parser->parse_from_file ('file.pod', 'file.txt');

DESCRIPTION
===========

   Pod::Text::Color is a simple subclass of Pod::Text that highlights
output text using ANSI color escape sequences.  Apart from the color, it
in all ways functions like Pod::Text.  See Pod/Text, for
details and available options.

   Term::ANSIColor is used to get colors and therefore must be installed
to use this module.

BUGS
====

   This is just a basic proof of concept.  It should be seriously expanded
to support configurable coloration via options passed to the constructor,
and *pod2text* should be taught about those.

SEE ALSO
========

   `Pod::Text|Pod::Text' in this node, `Pod::Parser|Pod::Parser' in this
node

AUTHOR
======

   Russ Allbery <rra@stanford.edu>.

Convert POD data to formatted overstrike text
*********************************************

NAME
====

   Pod::Text::Overstrike - Convert POD data to formatted overstrike text

SYNOPSIS
========

     use Pod::Text::Overstrike;
     my $parser = Pod::Text::Overstrike->new (sentence => 0, width => 78);

     # Read POD from STDIN and write to STDOUT.
     $parser->parse_from_filehandle;

     # Read POD from file.pod and write to file.txt.
     $parser->parse_from_file ('file.pod', 'file.txt');

DESCRIPTION
===========

   Pod::Text::Overstrike is a simple subclass of Pod::Text that highlights
output text using overstrike sequences, in a manner similar to nroff.
Characters in bold text are overstruck (character, backspace, character)
and characters in underlined text are converted to overstruck underscores
(underscore, backspace, character).  This format was originally designed
for hardcopy terminals and/or lineprinters, yet is readable on softcopy
(CRT) terminals.

   Overstruck text is best viewed by page-at-a-time programs that take
advantage of the terminal's *stand-out* and underline capabilities, such
as the less program on Unix.

   Apart from the overstrike, it in all ways functions like Pod::Text.  See
Pod/Text, for details and available options.

BUGS
====

   Currently, the outermost formatting instruction wins, so for example
underlined text inside a region of bold text is displayed as simply bold.
There may be some better approach possible.

SEE ALSO
========

   `Pod::Text|Pod::Text' in this node, `Pod::Parser|Pod::Parser' in this
node

AUTHOR
======

   Joe Smith <Joe.Smith@inwap.com>, using the framework created by Russ
Allbery <rra@stanford.edu>.

Convert POD data to ASCII text with format escapes
**************************************************

NAME
====

   Pod::Text::Color - Convert POD data to ASCII text with format escapes

SYNOPSIS
========

     use Pod::Text::Termcap;
     my $parser = Pod::Text::Termcap->new (sentence => 0, width => 78);

     # Read POD from STDIN and write to STDOUT.
     $parser->parse_from_filehandle;

     # Read POD from file.pod and write to file.txt.
     $parser->parse_from_file ('file.pod', 'file.txt');

DESCRIPTION
===========

   Pod::Text::Termcap is a simple subclass of Pod::Text that highlights
output text using the correct termcap escape sequences for the current
terminal.  Apart from the format codes, it in all ways functions like
Pod::Text.  See Pod/Text, for details and available
options.

SEE ALSO
========

   `Pod::Text|Pod::Text' in this node, `Pod::Parser|Pod::Parser' in this
node

AUTHOR
======

   Russ Allbery <rra@stanford.edu>.

Create a static syntax tree for a POD
*************************************

NAME
====

   Pod::Tree - Create a static syntax tree for a POD

SYNOPSIS
========

     use Pod::Tree;

     $tree = new Pod::Tree;
     $tree->load_file      ( $file, %options)
     $tree->load_fh        ( $fh  , %options);
     $tree->load_string    ( $pod , %options);
     $tree->load_paragraphs(\@pod , %options);

     $loaded = $tree->loaded;

     $node   = $tree->get_root;
               $tree->set_root  ($node);
     $node =   $tree->pop;
               $tree->push(@nodes);

               $tree->walk(\&sub);
     print     $tree->dump;

REQUIRES
========

   Perl 5.004, Exporter, IO::File, Pod::Tree::Node

EXPORTS
=======

   Nothing

DESCRIPTION
===========

   `Pod::Tree' parses a POD into a static syntax tree.  Applications walk
the tree to recover the structure and content of the POD.  See
``Pod::Tree::Node' in this node' for a description of the tree.

METHODS
=======

$tree = new `Pod::Tree'
     Creates a new `Pod::Tree' object.  The syntax tree is initially empty.

$ok = $tree->`load_file'($file, %options)
     Parses a POD and creates a syntax tree for it.  $file is the name of
     a file containing the POD.  Returns null iff it can't open $file.

     See `' in this node for a description of %options

$tree->`load_fh'($fh, %options)
     Parses a POD and creates a syntax tree for it.  $fh is an IO::File
     object that is open on a file containing the POD.

     See `' in this node for a description of %options

$tree->`load_string'($pod, %options)
     Parses a POD and creates a syntax tree for it.  $pod is a single
     string containing the POD.

     See `' in this node for a description of %options

$tree->`load_paragraphs'(\*@pod*, %options)
     Parses a POD and creates a syntax tree for it.  *\@pod* is a
     reference to an array of strings.  Each string is one paragraph of
     the POD.

     See `' in this node for a description of %options

$loaded = $tree->`loaded'
     Returns true iff one of the `load_'* methods has been called on $tree.

$node = $tree->`get_root'
     Returns the root node of the syntax tree.  See Pod/Tree/Node,
     for a description of the syntax tree.

$tree->`set_root'($node)
     Sets to the root of the syntax tree to $node.

$tree->push(*@nodes*)
     Pushes *@nodes* onto the end of the top-level list of nodes in $tree.

$node = $tree->pop
     Pops $node off of the end of the top-level list of nodes in $tree.

$tree->walk(*\&sub*)
     Walks the syntax tree, depth first.  Calls sub once for each node in
     the tree.  The current node is passed as the first argument to sub.

     walk descends to the children and siblings of $node iff *sub()*
     returns true.

$tree->dump
     Pretty prints the syntax tree.  This will show you how `Pod::Tree'
     interpreted your POD.

OPTIONS
=======

   These options may be passed in the %options hash to the `load_'*
methods.

`in_pod => 0'
`in_pod => 1'
     Sets the initial value of `in_pod'.  When `in_pod' is false, the
     parser ignores all text until the next =command paragraph.

     The initial value of `in_pod' defaults to false for `load_file()' and
     `load_fh()' calls and true for  `load_string()' and
     `load_paragraphs()' calls.  This is usually what you want, unless you
     want consistency.  If this isn't what you want, pass different
     initial values in the %options hash.

limit => n
     Only parse the first n paragraphs in the POD.

DIAGNOSTICS
===========

`load_file'($file)
     Returns null iff it can't open $file.

NOTES
=====

Blank lines
-----------

   PODs are defined in terms of paragraphs, and paragraphs are defined as
text delimited by two or more consecutive newlines.

   `load_file()' and `load_fh()' parse paragraphs by setting $/ to " and
calling `getline()'.  This reads paragraphs as desired; however, the
strings returned by `getline()' always have two newlines at the end, no
matter now many actually appear in the input.  I reported this as a bug
against Perl, but was told that it is a feature.

   To fix this, I would have to abandon $/ and count newlines in
`Pod::Tree'.  From a coding standpoint, this isn't difficult, but I hate
to do it: $/ ought to be good for *something*.

   Instead, `load_file()' and `load_fh()' go ahead and chomp the line
endings.  `pod2'* translators can add back `"\n\n"' if they like, but
there is no way to recover the actual number of newlines in the input.
For consistency, `load_string()' splits on `m(\n{2,})' and discards the
delimiters.  In contrast, `load_paragraphs()' doesn't mung newlines.  By
definition, text passed to `load_paragraphs()' has already been divided
into paragraphs, so any trailing newlines are taken to be part of the
paragraph in which they appear.

   None of this should be an issue for ordinary POD paragraphs.  However,
it could be a problem for =begin/=end blocks, if they pass text to a
formatter for which blank lines are significant.

`' in this node markups
-----------------------

   In the documentation of the

     L<"sec">	section in this manual page

   markup, ``perlpod' in this node' has always claimed

     (the quotes are optional)

   However, there is no way to decide from the syntax alone whether

     L<foo>

   is a link to the foo man page or a link to the foo section of this man
page.

   `Pod::Tree' parses `< LZ<'<foo> >> as a link to a section if foo looks
like a section name (e.g. contains whitespace), and as a link to a man
page otherswise.

   In practice, this tends to break links to sections.  If you want your
section links to work reliably, write them as `< LZ<'<"foo"> >> or `<
LZ<'</foo> >>.

SEE ALSO
========

   perl(1), ``Pod::Tree::Node' in this node', ``Pod::Tree::HTML' in this
node'

AUTHOR
======

   Steven McDougall, swmcd@world.std.com

COPYRIGHT
=========

   Copyright 1999-2000 by Steven McDougall. This module is free software;
you can redistribute it and/or modify it under the same terms as Perl
itself.

Generate HTML from a Pod::Tree
******************************

NAME
====

   Pod::Tree::HTML - Generate HTML from a Pod::Tree

SYNOPSIS
========

     use Pod::Tree::HTML;

     $source =   new Pod::Tree;
     $source =  "file.pod";
     $source =   new IO::File;
     $source = \$pod;
     $source = \@pod;

     $dest   =   new HTML::Stream;
     $dest   =   new IO::File;
     $dest   =  "file.html";

     $html   =   new Pod:::Tree::HTML $source, $dest, %options;

     $html->set_options(%options);
     @values = $html->get_options(@keys);

     $html->translate;

DESCRIPTION
===========

   `Pod::Tree::HTML' reads a POD and translates it to HTML.  The source
and destination are fixed when the object is created.  Options are
provided for controlling details of the translation.

   The translate method does the actual translation.

   For convenience, `Pod::Tree::HTML' can read PODs from a variety of
sources, and write HTML to a variety of destinations.  The new method
resolves the *$source* and $dest arguments.

Source resolution
-----------------

   `Pod::Tree::HTML' can obtain a POD from any of 5 sources.  new resolves
*$source* by checking these things, in order:

  1. If *$source* isa `POD::Tree', then the POD is taken from that tree.

  2. If *$source* is not a reference, then it is taken to be the name of a
     file containing a POD.

  3. If *$source* isa IO::File, then it is taken to be an IO::File object
     that is already open on a file containing a POD.

  4. If *$source* is a SCALAR reference, then the text of the POD is taken
     from that scalar.

  5. if *$source* is an ARRAY reference, then the paragraphs of the POD
     are taken from that array.

        If *$source* isn't any of these things, new dies.

Destination resolution
----------------------

   `Pod::Tree::HTML' can write HTML to any of 3 destinations.  new
resolves $dest by checking these things, in order:

  1. If $dest isa `HTML::Stream', then it writes to that stream.

  2. If $dest is a reference, then it is taken to be an IO::File object
     that is already open on the file where the HTML will be written.

  3. If $dest is not a reference, then it is taken to be the name of the
     file where the HTML will be written.

METHODS
=======

$html = new `Pod::Tree::HTML' *$source*, $dest, %options
     Creates a new `Pod::Tree::HTML' object.

     $html reads a POD from *$source*, and writes HTML to $dest.  See `'
     in this node and `' in this node for details.

     Options controlling the translation may be passed in the %options
     hash.  See `' in this node for details.

$html->`set_options'(%options)
     Sets options controlling the translation.  See `' in this node for
     details.

*@values* = $html->get_options(*@keys*)
     Returns the current values of the options specified in *@keys*.  See
     `' in this node for details.

$html->translate
     Translates the POD to HTML.  This method should only be called once.

OPTIONS
=======

base => *$url*
     Translate `L<>' sequences into HTML links relative to *$url*.

`link_map' => *$link_map*
     Sets the link mapping object.  Before emitting an L<> markup in HTML,
     translate calls

     ($base, $page, $section) = *$link_map*->map($base, $page, $section);

     Where

    $base
          is the URL given in the base option.

    $page
          is the man page named in the L<> markup.

    $section
          is the man page section given in the L<> markup.

     The map method may perform arbitrary mappings on its arguments.

     The default link_map translates `::' sequences in $page to /.

`toc' => [0|1]
     Includes or omits the table of contents.  Default is to include the
     TOC.

`hr' => *$level*
     Controls the profusion of horizontal lines in the output, as follows:

          $level   horizontal lines
          0 	     none
          1 	     between TOC and body
          2 	     after each =head1
          3 	     after each =head1 and =head2

     Default is level 1.

bgcolor => *#rrggbb*
     Set the background color to *#rrggbb*.  Default is `#fffff8', which
     is an off-white.

text => *#rrggbb*
     Set the text color to *#rrggbb*.  Default is `#fffff', which is black.

title => title
     Set the page title to title.  If no title option is given,
     `Pod::Tree::HTML' will attempt construct a title from the second
     paragrah of the POD.  This supports the following style:

          =head1 NAME

          ls - list contents of directory

LINKS and TARGETS
=================

   `Pod::Tree::HTML' automatically generates HTML name anchors for all
=head1 and =head2 command paragraphs, and for text items in =over lists.
The text of the paragraph becomes the name entity in the anchor.  Markups
are ignored and the text is escaped according to RFC 2396.

   For example, the paragraph

     =head1 C<Foo> Bar

   is translated to

     <h1><a name="Foo%20Bar"><code>Foo</code> Bar</a></h1>

   To link to a heading, simply give the text of the heading in a `L<>'
markup.  The text must match exactly; markups may vary.  Either of these
would link to the heading shown above

     L</C<Foo> Bar>
     L</Foo Bar>

   To generate HTML anchors in other places, use the index (`X<>') markup

     We can link to X<this text>.

   and link to it as usual

     L</this text> uses the index markup.

DIAGNOSTICS
===========

`Pod::Tree::HTML::new: not enough arguments'
     (F) new called with fewer than 2 arguments.

`Pod::Tree::HTML::new: Can't load POD from $source'
     (F) new couldn't resolve the *$source* argument.  See `' in this node
     for details.

`Pod::Tree::HTML::new: Can't open $dest: $!'
     (F) The destination file couldn't be opened.

SEE ALSO
========

   perl(1), ``Pod::Tree' in this node', ``Pod::Tree::Node' in this node'

AUTHOR
======

   Steven McDougall, swmcd@world.std.com

COPYRIGHT
=========

   Copyright 1999-2000 by Steven McDougall. This module is free software;
you can redistribute it and/or modify it under the same terms as Perl
itself.

nodes in a Pod::Tree
********************

NAME
====

   Pod::Tree::Node - nodes in a Pod::Tree

SYNOPSIS
========

     $node = root     Pod::Tree::Node \@paragraphs;
     $node = verbatim Pod::Tree::Node $paragraph;
     $node = command  Pod::Tree::Node $paragraph;
     $node = ordinary Pod::Tree::Node $paragraph;
     $node = letter   Pod::Tree::Node $token;
     $node = sequence Pod::Tree::Node $letter, \@children;
     $node = text     Pod::Tree::Node $text;
     $node = target   Pod::Tree::Node $target;

     is_command  $node and ...
     is_for      $node and ...
     is_item     $node and ...
     is_letter   $node and ...
     is_list     $node and ...
     is_ordinary $node and ...
     is_root     $node and ...
     is_sequence $node and ...
     is_text     $node and ...
     is_verbatim $node and ...
     is_link     $node and ...

     is_c_head1  $node and ...
     is_c_head2  $node and ...
     is_c_over   $node and ...
     is_c_back   $node and ...
     is_c_item   $node and ...
     is_c_for    $node and ...
     is_c_begin  $node and ...
     is_c_end    $node and ...

     $arg       = get_arg       $node;
     $children  = get_children  $node;
     $command   = get_command   $node;
     $item_type = get_item_type $node;
     $letter    = get_letter    $node;
     $list_type = get_list_type $node;
     $page      = get_page      $node;
     $section   = get_section   $node;
     $siblings  = get_siblings  $node;
     $target    = get_target    $node;
     $text      = get_text      $node;
     $type      = get_type      $node;
     $deep_text = get_deep_text $node;

     $node->force_text($text);
     $node->force_for;
     $node->parse_begin (\@nodes);
     $node->set_children(\@children);
     $node->make_sequences;
     $node->parse_links;
     $node->unescape;
     $node->consolidate;
     $node->make_lists;

     $node->dump;

DESCRIPTION
===========

   `Pod::Tree::Node' objects are nodes in a tree that represents a POD.
Applications walk the tree to recover the structure and content of the POD.

   Methods are provided for

   * creating nodes in the tree

   * parsing the POD into nodes

   * returning information about nodes

   * walking the tree

TREE STRUCTURE
==============

Root node
---------

   The tree descends from a single root node; is_root returns true on this
node and no other.

     $children = $root->get_children

   returns a reference to an array of nodes.  These nodes represent the
POD.

Node types
----------

   For each node, call `get_type' to discover the type of the node

     for $child (@$children)
     {
         $type = $child->get_type;
     }

   $type will be one of these strings:

'root'
     The node is the root of the tree.

'verbatim'
     The node represents a verbatim paragraph.

'ordinary'
     The node represents an ordinary paragraph.

'command'
     The node represents an =command paragraph (but not an =over
     paragraph).

'sequence'
     The node represents an interior sequence.

'target'
     The node represents the target of a link (An L<> markup).

'text'
     The node represents text that contains no interior sequences.

'list'
     The node represents an =over list.

'item'
     The node represents an item in an =over list.

'for'
     The node represents a =for paragraph, or it represents the paragraphs
     between =begin/=end commands.

   Here are instructions for walking these node types.

root node
---------

   Call

     $children = $node->get_children

   to get a list of nodes representing the POD.

verbatim nodes
--------------

   A verbatim node contains the text of a verbatim paragraph.  Call

     $text = $node->get_text

   to recover the text of the paragraph.

ordinary nodes
--------------

   An ordinary node represents the text of an ordinary paragraph.  The
text is parsed into a list of text and sequence nodes; these nodes are the
children of the ordinary node.  Call

     $children = $node->get_children

   to get a list of the children.  Iterate over this list to recover the
text of the paragraph.

command nodes
-------------

   A command node represents an =command paragraph.  Call

     $command = $node->get_command;

   to recover the name of the command.  The name is returned *without* the
equals sign.

   The text of a command paragraph is parsed into a list of text and
sequence nodes; these nodes are the children of the command node.  Call

     $children = $node->get_children;

   to get a list of the children.  Iterate over this list to recover the
text of the paragraph.

sequence nodes
--------------

   A sequence node represents a single interior sequence (a <> markup).
Call

     $node->get_letter

   to recover the original markup letter.  The contents of the markup are
parsed into a list of text and sequence nodes; these nodes are the
children of the sequence node.  Call

     $node->get_children

   to recover them.

   Z<> and E<> markups do not generate sequence nodes; these markups are
expanded by `Pod::Tree' when the tree is built.

target nodes
------------

   If a sequence node represents a link (an `L<>' markup), then

     is_link $node

   returns true and

     $target = $node->get_target

   returns a node representing the target of the link.  Call

     $page    = $target->get_page;
     $section = $target->get_section;

   to recover the man page and section that the link refers to.

   $target is used only for constructing hyper-links; the text to be
displayed for the link is recovered by walking the children of $node, as
for any other interior sequence.

text nodes
----------

   A text node represents text that contains no interior sequences.  Call

     $text = $node->get_text

   to recover the text.

list nodes
----------

   A list node represents an =over list.  Call

     $list_type = $node->get_list_type;

   to discover the type of the list. This will be one of the strings

'bullet'
'number'
'text'
   The type of a list is the type of the first item in the list.

   The children of a list node are item nodes; each item node represents
one item in the list.

   You can call

     $node->get_arg;

   to recover the indent value following the =over.

item nodes
----------

   An item node represents one item in an =over list.  Call

     $item_type = $node->get_item_type;

   to discover the type of the item.  This will be one of the strings
shown above for `list nodes' in this node.  Typically, all the items in a
list have the same type, but `Pod::Tree::Node' doesn't assume this.

   The children of an item node represent the text of the =item paragraph;
this is usually of interest only for 'text' items.  Call

     $children = $node->get_children

   to get a list of the children; these will be sequence and text nodes,
as for any other =command paragraph.

   Each item node also has a list of nodes representing all the paragraphs
following it, up to the next =item command, or the end of the list.  These
nodes are called siblings of the item node.  Call

     $siblings = $node->get_siblings

   to get a list of sibling nodes.

for nodes
---------

   for nodes represent text that is to be passed to an external formatter.
Call

     $formatter = $node->get_arg;

   to discover the name of the formatter.  Call

     $text = $node->get_text;

   to obtain the text to be passed to the formatter.  This will either be
the text of an =for command, or all of the text between =begin and =end
commands.

Walking the tree
----------------

   PODs have a recursive structure; therefore, any application that walks
a Pod::Tree must also be recursive.  See `skeleton' for an example of the
necessary code.

METHODS
=======

Constructors
------------

   These methods construct `Pod::Tree::Node' objects.  They are used to
build trees.  They aren't necessary to walk trees.

     $node = root     Pod::Tree::Node \@paragraphs;
     $node = verbatim Pod::Tree::Node $paragraph;
     $node = command  Pod::Tree::Node $paragraph;
     $node = ordinary Pod::Tree::Node $paragraph;
     $node = letter   Pod::Tree::Node $token;
     $node = sequence Pod::Tree::Node $letter, \@children;
     $node = text     Pod::Tree::Node $text;
     $node = target   Pod::Tree::Node $target;

Tests
-----

   These methods return true iff $node has the type indicated by the
method name.

     is_command  $node and ...
     is_for      $node and ...
     is_item     $node and ...
     is_letter   $node and ...
     is_link     $node and ...
     is_list     $node and ...
     is_ordinary $node and ...
     is_root     $node and ...
     is_sequence $node and ...
     is_text     $node and ...
     is_verbatim $node and ...

   These methods return true iff $node is a command node, and the command
is the one indicated by the method name.

     is_c_head1  $node and ...
     is_c_head2  $node and ...
     is_c_over   $node and ...
     is_c_back   $node and ...
     is_c_item   $node and ...
     is_c_for    $node and ...
     is_c_begin  $node and ...
     is_c_end    $node and ...

Accessors
---------

   These methods return information about nodes.  Most accessors are only
relevant for certain types of nodes.

$arg = `get_arg' $node
     Returns the argument of $node.  This is the number following an =over
     command, or the name of an external translator for =for, =begin, and
     =end commands.  Only relevant for these four command nodes.

$children = get_children $node
     Returns a reference to the list of nodes that are children of $node.
     May be called on any node.  The list may be empty.

$command = `get_command' $node
     Returns the name of a command, without the equals sign.  Only
     relevant for command nodes.

$item_type = `get_item_type' $node
     Returns the type of an item node. The type will be one of

    'bullet'
    'number'
    'text'
$letter = `get_letter' $node
     Returns the letter that introduces an interior sequence.  Only
     relevant for sequence nodes.

$list_type = `get_list_type' $node
     Returns the type of a list node.  The type of a list node is the type
     of the first item node in the list.

$page = `get_page' $node
     Returns the man page that is the target of a link.  Only relevant for
     target nodes.

$section = `get_section' $node
     Returns the section that is the target of a link.  Only relevant for
     target nodes.

$siblings = `get_siblings' $node
     Returns the siblings of a node.  May be called on any node.  Only
     item nodes have siblings.

$target = `get_target' $node
     Returns the target of a node.  Only relevant for sequence nodes that
     represent links (`L<>' markups).  `is_link' returns true on these
     nodes.

$text = get_text $node
     Returns the text of a node.  $text will not contain any interior
     sequences.  Only relevant for text nodes.

$type = `get_type' $node
     Returns the type of $node.  May be called on any node.  See `' in
     this node for descriptions of the node types.

$deep_text = `get_deep_text' $node
     Recursively walks the children of a node, catenates together the text
     from each node, and returns all that text as a single string.  All
     interior sequence markups are discarded.

     `get_deep_text' is provided as a convenience for applications that
     want to ignore markups in a POD paragraph.

Parsing
-------

   These methods manipulate the tree while it is being built.  They aren't
necessary to walk the tree.

     $node->force_text($text)
     $node->force_for;
     $node->parse_begin (\@nodes);
     $node->set_children(\@children);
     $node->make_sequences;
     $node->parse_links;
     $node->unescape;
     $node->consolidate;
     $node->make_lists;

Utility
-------

$node->dump
     Returns a string containing a pretty-printed representation of the
     node.  Calling dump on the root node of a tree will show the entire
     POD.

EXAMPLES
========

   The `t/' directory in the `Pod::Tree' distribution contains examples of
PODs, together with dumps of the trees that `Pod::Tree' constructs for
them.  The tree for `t/'file`.pod' is in `t/'file`.p_exp'.

   `Pod::Tree::Node::dump' is a simple example of code that walks a POD
tree.

   `skeleton' is a skeleton application that walks a POD tree.

SEE ALSO
========

   perl(1), ``Pod::Tree' in this node'

AUTHOR
======

   Steven McDougall, swmcd@world.std.com

COPYRIGHT
=========

   Copyright 1999-2000 by Steven McDougall. This module is free software;
you can redistribute it and/or modify it under the same terms as Perl
itself.

translate program PODs to HTML
******************************

NAME
====

   Pod::Tree::PerlBin - translate program PODs to HTML

SYNOPSIS
========

     $perl_map = new Pod::Tree::PerlMap;
     $perl_bin = new Pod::Tree::PerlBin $perl_dir, $HTML_dir, $perl_map, %opts;

     $perl_bin->scan(@path);
     $perl_bin->index;
     $perl_bin->translate;

     $top = $perl_bin->get_top_entry;

DESCRIPTION
===========

   `Pod::Tree::PerlBin' translates program PODs to HTML.

   It searches for programs in a list of directories (typically a PATH),
and searches for PODs withing the programs.  Only text (-T) files are
considered.

   `Pod::Tree::PerlBin' generates a top-level index of all the program
PODs, and writes it to *HTML_dir*`/bin.html'.

   `Pod::Tree::PerlBin' generates and uses an index of the PODs that it
finds to construct HTML links.  Other modules can also use this index.

METHODS
=======

$perl_bin = new `Pod::Tree::PerlBin' *$perl_dir*, *$HTML_dir*, *$perl_map*, %options
     Creates and returns a new `Pod::Tree::PerlBin' object.

     *$HTML_dir* is the directory where HTML files will be written.

     *$perl_map* maps program names to URLs.

     %options are passed through to `Pod::Tree::HTML'.

     The *$perl_dir* argument is included for consistency with the other
     `Pod::Tree::Perl*' modules, but is currently unused.

$perl_bin->scan(*@path*)
     Scans all the directories in *@path* for program PODs.  Only text
     (-T) files are considered.  The search does not recurse through
     subdirectories.

     Each POD that is located is entered into *$perl_map*.

$perl_bin->index
     Generates a top-level index of all the program PODs, and writes it to
     *HTML_dir*`/bin.html'.

$perl_bin->translate
     Translates each program POD found by scan to HTML.  The HTML pages
     are written to *HTML_dir*.

$perl_bin->`get_top_entry'
     Returns a hash reference of the form

          { URL         => $URL,
            description => $description }

     `Pod::Tree::PerlTop' uses this to build a top-level index of all the
     Perl PODs.

LINKING
=======

   `Pod::Tree::PerlBin' expects the second paragraph of the POD to have
the form

     name - description

   and enters name into *$perl_map*.  To link to a program POD from
another POD, write

     L<name>

REQUIRES
========

     5.005
     File::Find
     HTML::Stream
     Pod::Tree
     Pod::Tree::HTML
     Pod::Tree::PerlUtil

EXPORTS
=======

   Nothing.

SEE ALSO
========

   ``Pod::Tree::HTML' in this node', ``Pod::Tree::PerlMap' in this node',

AUTHOR
======

   Steven McDougall, swmcd@world.std.com

COPYRIGHT
=========

   Copyright 2000 by Steven McDougall.  This program is free software; you
can redistribute it and/or modify it under the same terms as Perl.

translate Perl distribution documentation to HTML
*************************************************

NAME
====

   Pod::Tree::PerlDist - translate Perl distribution documentation to HTML

SYNOPSIS
========

     $perl_map  = new Pod::Tree::PerlMap;
     $perl_dist = new Pod::Tree::PerlDist $perl_dir, $HTML_dir, $perl_map, %opts;

     $perl_dist->scan;
     $perl_dist->index;
     $perl_dist->translate;

     $top = $perl_dist->get_top_entry;

DESCRIPTION
===========

   `Pod::Tree::PerlDist' translates documents in the Perl distribution to
HTML. These include Changes, README, and assored other files that appear
in the top level of the Perl source tree.

   Files that contain PODs are parsed as PODs; files that do not contain
PODs are converted to HTML as preformatted text.

   `Pod::Tree::PerlDist' generates and uses an index of the files that it
finds to construct HTML links.  Other modules can also use this index.

METHODS
=======

$perl_dist = new `Pod::Tree::PerlDist' *$perl_dir*, *$HTML_dir*, *$perl_map*, %options
     Creates and returns a new `Pod::Tree::PerlDist' object.

     *$perl_dir* is the root of the Perl source tree.

     *$HTML_dir* is the directory where HTML files will be written.

     *$perl_map* maps file names to URLs.

     %options are passed through to `Pod::Tree::HTML'.

$perl_dist->scan
     Scans the top level of the Perl source tree for documentation files.
     Files that do not generally contain user-level documentation, such as
     source files, are ignored.  The search does not recurse through
     subdirectories.

     Each file that is located is entered into *$perl_map*.

$perl_dist->index
     Generates a top-level index of all the distribution documents, and
     writes it to *HTML_dir*`/dist.html'.

$perl_dist->translate
     Translates each distribution document found by scan to HTML.  The
     HTML pages are written to *HTML_dir*.

$perl_dist->`get_top_entry'
     Returns a hash reference of the form

          { URL         => $URL,
            description => $description }

     `Pod::Tree::PerlTop' uses this to build a top-level index of all the
     Perl PODs.

LINKING
=======

   `Pod::Tree::PerlDist' indexes files by their name.  To link to a file
named `README.win32' write

     L<README.win32>

REQUIRES
========

     5.005;
     HTML::Stream;
     Pod::Tree;
     Pod::Tree::HTML;
     Pod::Tree::PerlUtil;

EXPORTS
=======

   Nothing.

SEE ALSO
========

   ``Pod::Tree::HTML' in this node', ``Pod::Tree::PerlMap' in this node',

AUTHOR
======

   Steven McDougall, swmcd@world.std.com

COPYRIGHT
=========

   Copyright 2000 by Steven McDougall.  This program is free software; you
can redistribute it and/or modify it under the same terms as Perl.

translate `perlfunc.pod' to HTML
********************************

NAME
====

   Pod::Tree::PerlFunc - translate `perlfunc.pod' to HTML

SYNOPSIS
========

     $perl_map  = new Pod::Tree::PerlMap;
     $perl_func = new Pod::Tree::PerlFunc $perl_dir, $HTML_dir, $perl_map, %opts;

     $perl_func->scan;
     $perl_func->index;
     $perl_func->translate;

DESCRIPTION
===========

   `Pod::Tree::PerlFunc' translates `perlfunc.pod' to HTML.  It creates a
separate HTML page for each function description in `perlfunc.pod'. The
pages for the individual descriptions are named after the function and
written to a `func/' subdirectory.  `perlfunc.html' is generated as an
index to all the pages in `func/'.

   `Pod::Tree::PerlFunc' generates and uses an index of the functions that
it finds in `perlfunc.pod' to construct HTML links.  Other modules can
also use this index.

METHODS
=======

$perl_func = new `Pod::Tree::PerlFunc' *$perl_dir*, *$HTML_dir*, *$perl_map*, %options
     Creates and returns a new `Pod::Tree::PerlFunc' object.

     *$perl_dir* is the root of the Perl source tree.

     *$HTML_dir* is the directory where HTML files will be written.

     *$perl_map* maps function names to URLs.

     %options are passed through to `Pod::Tree::HTML'.

$perl_func->scan
     Reads `perlfunc.pod' and identifies all the functions in it.  Each
     function that is identified is entered into *$perl_map*.

$perl_func->index
     Generates a top-level index of all the functions.  The index is
     written to *HTML_dir*`/pod/perlfunc.html'.

$perl_func->translate
     Translates each function found by scan to HTML.  The HTML pages are
     written to *HTML_dir*`/pod/func/'.

LINKING
=======

   `Pod::Tree::PerlFunc' indexes every =item paragraph in `perlfunc.html'.
To link, for example, to the abs function, write

     L<func/abs>

REQUIRES
========

     5.005;
     Pod::Tree;
     Pod::Tree::HTML;
     Pod::Tree::PerlUtil;

EXPORTS
=======

   Nothing.

SEE ALSO
========

   ``Pod::Tree::HTML' in this node', ``Pod::Tree::PerlMap' in this node',

AUTHOR
======

   Steven McDougall, swmcd@world.std.com

COPYRIGHT
=========

   Copyright 2000 by Steven McDougall.  This program is free software; you
can redistribute it and/or modify it under the same terms as Perl.

translate module PODs to HTML
*****************************

NAME
====

   Pod::Tree::PerlLib - translate module PODs to HTML

SYNOPSIS
========

     $perl_map = new Pod::Tree::PerlMap;
     $perl_lib = new Pod::Tree::PerlLib $perl_dir, $HTML_dir, $perl_map, %opts;

     $perl_lib->scan(@INC);
     $perl_lib->index;
     $perl_lib->translate;

     $top = $perl_lib->get_top_entry;

DESCRIPTION
===========

   `Pod::Tree::PerlLib' translates module PODs to HTML.  It does a
recursive subdirectory search through a list of directories (typically
`@INC') to find PODs.

   `Pod::Tree::PerlLib' generates a top-level index of all the PODs that
it finds, and writes it to *HTML_dir*`/lib.html'.

   `Pod::Tree::PerlLib' generates and uses an index of the PODs that it
finds to construct HTML links.  Other modules can also use this index.

METHODS
=======

$perl_lib = new `Pod::Tree::PerlLib' *$perl_dir*, *$HTML_dir*, *$perl_map*, %options
     Creates and returns a new `Pod::Tree::PerlLib' object.

     *$HTML_dir* is the directory where HTML files will be written.

     *$perl_map* maps module names to URLs.

     %options are passed through to `Pod::Tree::HTML'.

     The *$perl_dir* argument is included for consistency with the other
     `Pod::Tree::Perl*' modules, but is currently unused.

$perl_lib->scan(*@INC*)
     Does a recursive subdirectory search through *@INC* to locate module
     PODs.  Each module that is identified is entered into *$perl_map*.

$perl_lib->index
     Generates a top-level index of all the modules.  The index is written
     to *HTML_dir*`/lib.html'.

$perl_lib->translate
     Translates each module POD found by scan to HTML.  The HTML pages are
     written to *HTML_dir*`/lib/', in a subdirectory hierarchy that maps
     the module names.

$perl_lib->`get_top_entry'
     Returns a hash reference of the form

          { URL         => $URL,
            description => $description }

     `Pod::Tree::PerlTop' uses this to build a top-level index of all the
     Perl PODs.

LINKING
=======

   `Pod::Tree::PerlLib' expects the second paragraph of the POD to have
the form

     Foo::Bar - description

   and enters *Foo::Bar* into *$perl_map*.  To link to a module POD, write

     L<Foo::Bar>

REQUIRES
========

     5.005;
     HTML::Stream;
     Pod::Tree;
     Pod::Tree::HTML;
     Pod::Tree::PerlUtil;

EXPORTS
=======

   Nothing.

SEE ALSO
========

   ``Pod::Tree::HTML' in this node', ``Pod::Tree::PerlMap' in this node',

AUTHOR
======

   Steven McDougall, swmcd@world.std.com

COPYRIGHT
=========

   Copyright 2000 by Steven McDougall.  This program is free software; you
can redistribute it and/or modify it under the same terms as Perl.

map names to URLs
*****************

NAME
====

   Pod::Tree::PerlMap - map names to URLs

SYNOPSIS
========

     $perl_map = new Pod::Tree::PerlMap;

     $perl_map->add_page  ($name, $file);
     $perl_map->add_func  ($func, $file);
     $perl_map->force_func(0);
     $perl_map->force_func(1);
     $perl_map->set_depth ($depth);

     ($base, $page, $section) = $perl_map->map($base, $page, $section);

DESCRIPTION
===========

   `Pod::Tree::PerlMap' maps L<> markups to URLs.

   The `Pod::Tree::Perl*' translators make entries in the map.
`Pod::Tree::HTML' uses the map to translate links before it emits them.

METHODS
=======

*$perl_map*->`add_page'($name, $file)
     Map $name to $file.  $name is the name of a POD, as used in L<>
     markups.  $file is the path to the HTML file that is the target of
     the link.

*$perl_map*->`add_func'(*$func*, $file)
     Maps *$func* to $file.  *$func* is the name of a function described
     in `perlfunc.pod'.  $file is the name of the HTML file where it is
     described.

*$perl_map*->`force_func'($state)
     Controls interpretation of links of the form L<func>.

     If $state is true, calls to map will interpret L<func> as
     L<perlfunc/func>.

     If $state is false, calls to map will interpret L<func> normally.

*$perl_map*->`set_depth'(*$depth*)
     Informs *$perl_map* of the depth of the referring page in the HTML
     directory tree.  *$perl_map* needs to know this so that it can
     construct relative links.

($base, $page, $section) =  *$perl_map*->map($base, $page, $section)
     Remaps a link.

     $base is the base URL for the HTML page, if any.  $page is the page
     given in an L<> markup.  $section is the section given in the L<>
     markup, if any.

     map returns a new $base, $page, and $section that can be used to
     construct a link to the HTML page.

REQUIRES
========

   Nothing.

EXPORTS
=======

   Nothing.

AUTHOR
======

   Steven McDougall, swmcd@world.std.com

COPYRIGHT
=========

   Copyright 2000 by Steven McDougall.  This program is free software; you
can redistribute it and/or modify it under the same terms as Perl.

translate Perl PODs to HTML
***************************

NAME
====

   Pod::Tree::PerlPod - translate Perl PODs to HTML

SYNOPSIS
========

     $perl_map = new Pod::Tree::PerlMap;
     $perl_pod = new Pod::Tree::PerlPod $perl_dir, $HTML_dir, $perl_map, %opts;

     $perl_pod->scan;
     $perl_pod->index;
     $perl_pod->translate;

     $top = $perl_pod->get_top_entry;

DESCRIPTION
===========

   `Pod::Tree::PerlPod' translates Perl PODs to HTML.  It does a recursive
subdirectory search through *$perl_dir* to find PODs.

   `Pod::Tree::PerlPod' generates a top-level index of all the PODs that
it finds, and writes it to *HTML_dir*`/pod.html'.

   `Pod::Tree::PerlPod' generates and uses an index of the PODs that it
finds to construct HTML links.  Other modules can also use this index.

METHODS
=======

$perl_pod = new `Pod::Tree::PerlPod' *$perl_dir*, *$HTML_dir*, *$perl_map*, %options
     Creates and returns a new `Pod::Tree::PerlPod' object.

     *$perl_dir* is the root of the Perl source tree.

     *$HTML_dir* is the directory where HTML files will be written.

     *$perl_map* maps POD names to URLs.

     %options are passed through to `Pod::Tree::HTML'.

$perl_pod->scan;
     Does a recursive subdirectory search through *$perl_dir* to locate
     PODs. Each POD that is located is entered into *$perl_map*.

$perl_pod->index
     Generates a top-level index of all the PODs.  The index is written to
     *HTML_dir*`/pod.html'.

$perl_pod->translate
     Translates each POD found by scan to HTML.  The HTML pages are
     written to *HTML_dir*, in a subdirectory hierarchy that mirrors the
     the Perl source distribution.

$perl_pod->`get_top_entry'
     Returns a hash reference of the form

          { URL         => $URL,
            description => $description }

     `Pod::Tree::PerlTop' uses this to build a top-level index of all the
     Perl PODs.

LINKING
=======

   `Pod::Tree::PerlPod' indexes PODs by the base name of the POD file.  To
link to `perlsub.pod', write

     L<perlsub>

REQUIRES
========

     5.005;
     File::Find;
     HTML::Stream;
     IO::File;
     Pod::Tree::HTML;
     Pod::Tree::PerlUtil;

EXPORTS
=======

   Nothing.

SEE ALSO
========

   ``Pod::Tree::HTML' in this node', ``Pod::Tree::PerlMap' in this node',

AUTHOR
======

   Steven McDougall, swmcd@world.std.com

COPYRIGHT
=========

   Copyright 2000 by Steven McDougall.  This program is free software; you
can redistribute it and/or modify it under the same terms as Perl.

generate a top-level index for Perl PODs
****************************************

NAME
====

   Pod::Tree::PerlTop - generate a top-level index for Perl PODs

SYNOPSIS
========

     $perl_map = new Pod::Tree::PerlMap;
     $perl_top = new Pod::Tree::PerlTop $perl_dir, $HTML_dir, $perl_map, %opts;

     $perl_top->index(@translators);
     $perl_top->translate;

     $top = $perl_top->get_top_entry;

DESCRIPTION
===========

   `Pod::Tree::PerlTop' generates a top-level index for Perl PODs.

   It also translates `perl.pod' to `perl.html' The translator is
specially hacked to insert links into the big verbatim paragraph that
lists all the other Perl PODs.

METHODS
=======

$perl_top = new `Pod::Tree::PerlTop' *$perl_dir*, *$HTML_dir*, *$perl_map*, %options
     Creates and returns a new `Pod::Tree::PerlTop' object.

     *$perl_dir* is the root of the Perl source tree.

     *$HTML_dir* is the directory where HTML files will be written.

     *$perl_map* maps POD names to URLs.  `Pod::Tree::PerlTop' uses it to
     resolve links in the `perl.pod' page.

     %options are passed through to `Pod::Tree::HTML'.

$perl_top->index(*@translators*)
     Generates a top-level index of all the PODs.  The index is written to
     *HTML_dir*`/index.html'.

     *@translators* is a list of other `Pod::Tree::Perl*' translator
     objects.  index makes a `get_top_entry' call on each of them to obtain
     URLs and descriptions of the pages that it links to.

$perl_top->translate
     Translates the `perl.pod' file to HTML.  The HTML page is written to
     *HTML_dir*`/pod/perl.html'

$perl_top->`get_top_entry'
     Returns a hash reference of the form

          { URL         => $URL,
            description => $description }

     `Pod::Tree::PerlTop' uses this to build a top-level index of all the
     Perl PODs.

REQUIRES
========

     5.005;
     Pod::Tree::HTML;
     Pod::Tree::PerlUtil;

EXPORTS
=======

   Nothing.

SEE ALSO
========

   ``Pod::Tree::HTML' in this node', ``Pod::Tree::PerlMap' in this node',

AUTHOR
======

   Steven McDougall, swmcd@world.std.com

COPYRIGHT
=========

   Copyright 2000 by Steven McDougall.  This program is free software; you
can redistribute it and/or modify it under the same terms as Perl.

Convert a Pod::Tree back to a POD
*********************************

NAME
====

   Pod::Tree::Pod - Convert a Pod::Tree back to a POD

SYNOPSIS
========

     use Pod::Tree::Pod;

     $tree =  new Pod::Tree;

     $dest =  new IO::File;
     $dest = "file.pod";

     $pod  =  new Pod:::Tree::HTML $tree, $dest;

     $pod->translate;

DESCRIPTION
===========

   `Pod::Tree::Pod' converts a Pod::Tree back to a POD.  The destination
is fixed when the object is created.  The translate method does the actual
translation.

   For convenience, Pod::Tree::Pod can write the POD to a variety of
destinations.  The new method resolves the $dest argument.

Destination resolution
----------------------

   `Pod::Tree::Pod' can write HTML to either of 2 destinations.  new
resolves $dest by checking these things, in order:

  1. If $dest is a reference, then it is taken to be an IO::File object
     that is already open on the file where the POD will be written.

  2. If $dest is not a reference, then it is taken to be the name of the
     file where the POD will be written.

METHODS
=======

$pod = new `Pod::Tree::Pod' $tree, $dest
     Creates a new `Pod::Tree::Pod' object.

     $tree is a `Pod::Tree' object that represents a POD.  $pod writes the
     POD to $dest.  See `' in this node for details.

$pod->translate
     Writes the text of the POD.  This method should only be called once.

DIAGNOSTICS
===========

`Pod::Tree::Pod::new: not enough arguments'
     (F) new called with fewer than 2 arguments.

`Pod::Tree::HTML::new: Can't open $dest: $!'
     (F) The destination file couldn't be opened.

NOTES
=====

   * The destination doesn't actually have to be an IO::File object.  It
     may be any object that has a print method.

SEE ALSO
========

   perl(1), ``Pod::Tree' in this node', ``Pod::Tree::Node' in this node'

AUTHOR
======

   Steven McDougall, swmcd@world.std.com

COPYRIGHT
=========

   Copyright 2000 by Steven McDougall. This module is free software; you
can redistribute it and/or modify it under the same terms as Perl itself.

print a usage message from embedded pod documentation
*****************************************************

NAME
====

   Pod::Usage, pod2usage() - print a usage message from embedded pod
documentation

SYNOPSIS
========

     use Pod::Usage

     my $message_text  = "This text precedes the usage message.";
     my $exit_status   = 2;          ## The exit status to use
     my $verbose_level = 0;          ## The verbose level to use
     my $filehandle    = \*STDERR;   ## The filehandle to write to

     pod2usage($message_text);

     pod2usage($exit_status);

     pod2usage( { -message => $message_text ,
                  -exitval => $exit_status  ,
                  -verbose => $verbose_level,
                  -output  => $filehandle } );

     pod2usage(   -msg     => $message_text ,
                  -exitval => $exit_status  ,
                  -verbose => $verbose_level,
                  -output  => $filehandle   );

ARGUMENTS
=========

   *pod2usage* should be given either a single argument, or a list of
arguments corresponding to an associative array (a "hash"). When a single
argument is given, it should correspond to exactly one of the following:

   * A string containing the text of a message to print before printing
     the usage message

   * A numeric value corresponding to the desired exit status

   * A reference to a hash

   If more than one argument is given then the entire argument list is
assumed to be a hash.  If a hash is supplied (either as a reference or as
a list) it should contain one or more elements with the following keys:

`-message'
`-msg'
     The text of a message to print immediately prior to printing the
     program's usage message.

`-exitval'
     The desired exit status to pass to the exit() function.

`-verbose'
     The desired level of "verboseness" to use when printing the usage
     message. If the corresponding value is 0, then only the "SYNOPSIS"
     section of the pod documentation is printed. If the corresponding
     value is 1, then the "SYNOPSIS" section, along with any section
     entitled "OPTIONS", "ARGUMENTS", or "OPTIONS AND ARGUMENTS" is
     printed.  If the corresponding value is 2 or more then the entire
     manpage is printed.

`-output'
     A reference to a filehandle, or the pathname of a file to which the
     usage message should be written. The default is `\*STDERR' unless the
     exit value is less than 2 (in which case the default is `\*STDOUT').

`-input'
     A reference to a filehandle, or the pathname of a file from which the
     invoking script's pod documentation should be read.  It defaults to
     the file indicated by $0 ($PROGRAM_NAME for users of `English.pm').

`-pathlist'
     A list of directory paths. If the input file does not exist, then it
     will be searched for in the given directory list (in the order the
     directories appear in the list). It defaults to the list of
     directories implied by `$ENV{PATH}'. The list may be specified either
     by a reference to an array, or by a string of directory paths which
     use the same path separator as `$ENV{PATH}' on your system (e.g., :
     for Unix, `;' for MSWin32 and DOS).

DESCRIPTION
===========

   *pod2usage* will print a usage message for the invoking script (using
its embedded pod documentation) and then exit the script with the desired
exit status. The usage message printed may have any one of three levels of
"verboseness": If the verbose level is 0, then only a synopsis is printed.
If the verbose level is 1, then the synopsis is printed along with a
description (if present) of the command line options and arguments. If the
verbose level is 2, then the entire manual page is printed.

   Unless they are explicitly specified, the default values for the exit
status, verbose level, and output stream to use are determined as follows:

   * If neither the exit status nor the verbose level is specified, then
     the default is to use an exit status of 2 with a verbose level of 0.

   * If an exit status *is* specified but the verbose level is not, then
     the verbose level will default to 1 if the exit status is less than 2
     and will default to 0 otherwise.

   * If an exit status is not specified but verbose level *is* given, then
     the exit status will default to 2 if the verbose level is 0 and will
     default to 1 otherwise.

   * If the exit status used is less than 2, then output is printed on
     STDOUT.  Otherwise output is printed on `STDERR'.

   Although the above may seem a bit confusing at first, it generally does
"the right thing" in most situations.  This determination of the default
values to use is based upon the following typical Unix conventions:

   * An exit status of 0 implies "success". For example, *diff(1)* exits
     with a status of 0 if the two files have the same contents.

   * An exit status of 1 implies possibly abnormal, but non-defective,
     program termination.  For example, *grep(1)* exits with a status of 1
     if it did not find a matching line for the given regular expression.

   * An exit status of 2 or more implies a fatal error. For example,
     *ls(1)* exits with a status of 2 if you specify an illegal (unknown)
     option on the command line.

   * Usage messages issued as a result of bad command-line syntax should go
     to `STDERR'.  However, usage messages issued due to an explicit
     request to print usage (like specifying *-help* on the command line)
     should go to STDOUT, just in case the user wants to pipe the output
     to a pager (such as *more(1)*).

   * If program usage has been explicitly requested by the user, it is
     often desireable to exit with a status of 1 (as opposed to 0) after
     issuing the user-requested usage message.  It is also desireable to
     give a more verbose description of program usage in this case.

   *pod2usage* doesn't force the above conventions upon you, but it will
use them by default if you don't expressly tell it to do otherwise.  The
ability of *pod2usage()* to accept a single number or a string makes it
convenient to use as an innocent looking error message handling function:

     use Pod::Usage;
     use Getopt::Long;

     ## Parse options
     GetOptions("help", "man", "flag1")  ||  pod2usage(2);
     pod2usage(1)  if ($opt_help);
     pod2usage(-verbose => 2)  if ($opt_man);

     ## Check for too many filenames
     pod2usage("$0: Too many files given.\n")  if (@ARGV > 1);

   Some user's however may feel that the above "economy of expression" is
not particularly readable nor consistent and may instead choose to do
something more like the following:

     use Pod::Usage;
     use Getopt::Long;

     ## Parse options
     GetOptions("help", "man", "flag1")  ||  pod2usage(-verbose => 0);
     pod2usage(-verbose => 1)  if ($opt_help);
     pod2usage(-verbose => 2)  if ($opt_man);

     ## Check for too many filenames
     pod2usage(-verbose => 2, -message => "$0: Too many files given.\n")
         if (@ARGV > 1);

   As with all things in Perl, *there's more than one way to do it*, and
*pod2usage()* adheres to this philosophy.  If you are interested in seeing
a number of different ways to invoke *pod2usage* (although by no means
exhaustive), please refer to `"EXAMPLES"' in this node.

EXAMPLES
========

   Each of the following invocations of `pod2usage()' will print just the
"SYNOPSIS" section to `STDERR' and will exit with a status of 2:

     pod2usage();

     pod2usage(2);

     pod2usage(-verbose => 0);

     pod2usage(-exitval => 2);

     pod2usage({-exitval => 2, -output => \*STDERR});

     pod2usage({-verbose => 0, -output  => \*STDERR});

     pod2usage(-exitval => 2, -verbose => 0);

     pod2usage(-exitval => 2, -verbose => 0, -output => \*STDERR);

   Each of the following invocations of `pod2usage()' will print a message
of "Syntax error." (followed by a newline) to `STDERR', immediately
followed by just the "SYNOPSIS" section (also printed to `STDERR') and
will exit with a status of 2:

     pod2usage("Syntax error.");

     pod2usage(-message => "Syntax error.", -verbose => 0);

     pod2usage(-msg  => "Syntax error.", -exitval => 2);

     pod2usage({-msg => "Syntax error.", -exitval => 2, -output => \*STDERR});

     pod2usage({-msg => "Syntax error.", -verbose => 0, -output => \*STDERR});

     pod2usage(-msg  => "Syntax error.", -exitval => 2, -verbose => 0);

     pod2usage(-message => "Syntax error.",
               -exitval => 2,
               -verbose => 0,
               -output  => \*STDERR);

   Each of the following invocations of `pod2usage()' will print the
"SYNOPSIS" section and any "OPTIONS" and/or "ARGUMENTS" sections to STDOUT
and will exit with a status of 1:

     pod2usage(1);

     pod2usage(-verbose => 1);

     pod2usage(-exitval => 1);

     pod2usage({-exitval => 1, -output => \*STDOUT});

     pod2usage({-verbose => 1, -output => \*STDOUT});

     pod2usage(-exitval => 1, -verbose => 1);

     pod2usage(-exitval => 1, -verbose => 1, -output => \*STDOUT});

   Each of the following invocations of `pod2usage()' will print the
entire manual page to STDOUT and will exit with a status of 1:

     pod2usage(-verbose  => 2);

     pod2usage({-verbose => 2, -output => \*STDOUT});

     pod2usage(-exitval  => 1, -verbose => 2);

     pod2usage({-exitval => 1, -verbose => 2, -output => \*STDOUT});

Recommended Use
---------------

   Most scripts should print some type of usage message to `STDERR' when a
command line syntax error is detected. They should also provide an option
(usually -H or `-help') to print a (possibly more verbose) usage message
to STDOUT. Some scripts may even wish to go so far as to provide a means
of printing their complete documentation to STDOUT (perhaps by allowing a
`-man' option). The following complete example uses Pod::Usage in
combination with Getopt::Long to do all of these things:

     use Getopt::Long;
     use Pod::Usage;

     my $man = 0;
     my $help = 0;
     ## Parse options and print usage if there is a syntax error,
     ## or if usage was explicitly requested.
     GetOptions('help|?' => \$help, man => \$man) or pod2usage(2);
     pod2usage(1) if $help;
     pod2usage(-verbose => 2) if $man;

     ## If no arguments were given, then allow STDIN to be used only
     ## if it's not connected to a terminal (otherwise print usage)
     pod2usage("$0: No files given.")  if ((@ARGV == 0) && (-t STDIN));
     __END__

     =head1 NAME

     sample - Using GetOpt::Long and Pod::Usage

     =head1 SYNOPSIS

     sample [options] [file ...]

     Options:
       -help            brief help message
       -man             full documentation

     =head1 OPTIONS

     =over 8

     =item B<-help>

     Print a brief help message and exits.

     =item B<-man>

     Prints the manual page and exits.

     =back

     =head1 DESCRIPTION

     B<This program> will read the given input file(s) and do something
     useful with the contents thereof.

     =cut

CAVEATS
=======

   By default, *pod2usage()* will use $0 as the path to the pod input
file.  Unfortunately, not all systems on which Perl runs will set $0
properly (although if $0 isn't found, *pod2usage()* will search
`$ENV{PATH}' or else the list specified by the `-pathlist' option).  If
this is the case for your system, you may need to explicitly specify the
path to the pod docs for the invoking script using something similar to
the following:

     pod2usage(-exitval => 2, -input => "/path/to/your/pod/docs");

AUTHOR
======

   Brad Appleton <bradapp@enteract.com>

   Based on code for *Pod::Text::pod2text()* written by Tom Christiansen
<tchrist@mox.perl.com>

ACKNOWLEDGEMENTS
================

   Steven McDougall <swmcd@world.std.com> for his help and patience with
re-writing this manpage.

Module to convert POD to XML
****************************

NAME
====

   Pod::XML - Module to convert POD to XML

SYNOPSIS
========

     use Pod::XML;
     my $parser = Pod::XML->new();
     $parser->parse_from_file("foo.pod");

DESCRIPTION
===========

   This module uses Pod::Parser to parse POD and generates XML from the
resulting parse stream. It uses its own format, described below.

XML FORMAT
==========

   The XML format is not a standardised format - if you wish to generate
some standard XML format such as docbook, please use a tool such as XSLT
to convert between this and that format.

   The format uses the namespace "http://axkit.org/ns/2000/pod2xml". Do not
try and request this URI - it is virtual. You will get a 404.

   The best way to describe the format is to show you:

     <pod xmlns="http://axkit.org/ns/2000/pod2xml">
       <head>
         <title>The first =head1 goes in here</title>
       </head>
       <sect1>
       <title>Subsequent =head1's create a sect1</title>
         <para>
         Ordinary paragraphs of text create a para tag.
         </para>
         <verbatim><![CDATA[
         Indented verbatim sections go in verbatim tags using a CDATA
         section rather than XML escaping.
         ]]></verbatim>
         <sect2>
         <title>=head2's go in sect2</title>
           <para>
           Up to =head4 is supported (despite not really being
           supported by pod), producing sect3 and
           sect4 respectively for =head3 and =head4.
           </para>
           <para>
           Bold text goes in a <strong>strong</strong> tag.
           </para>
           <para>
           Italic text goes in a <emphasis>emphasis</emphasis> tag.
           </para>
           <para>
           Code goes in a <code>code</code> tag.
           </para>
           <para>
           Lists (=over, =item, =back) go in list/item/itemtext
           tags. The itemtext element is only present if the
           =item text is <strong>not</strong> the "*" character.
           </para>
         </sect2>
       </sect1>
     </pod>

   If the first =head1 is "NAME" (like standard perl modules are supposed
to be) it takes the next paragraph as the document title. Other standard
head elements of POD are left unchanged (particularly, the SYNOPSIS and
DESCRIPTION elements of standard POD).

   Pod::XML tries to be careful about nesting sects based on the head
level in the original POD. Let me know if this doesn't work for you.

AUTHOR
======

   Matt Sergeant, matt@sergeant.org

SEE ALSO
========

   Pod::Parser

BUGS
====

   There is no xml2pod.

   POD L<> sections are barely implemented. Expect to see the <link> tag
contents change as I get more of a hang of how to parse it.

LICENSE
=======

   This is free software, you may use it and distribute it under the same
terms as Perl itself.

   perlvar - Perl predefined variables

   The following names have special meaning to Perl. Most of the
punctuational names have reasonable mnemonics, or analogues in one of the
shells. Nevertheless, if you wish to use the long variable names, you just
need to say

     use English;

   at the top of your program. This will alias all the short names to the
long names in the current package. Some of them even have medium names,
generally borrowed from *awk*.

   To go a step further, those variables that depend on the currently
selected filehandle may instead be set by calling an object method on the
FileHandle object. (Summary lines below for this contain the word HANDLE.)
First you must say

     use FileHandle;

   after which you may use either

     method HANDLE EXPR

   or

     HANDLE->method(EXPR)

   Each of the methods returns the old value of the FileHandle attribute.
The methods each take an optional EXPR, which if supplied specifies the new
value for the FileHandle attribute in question. If not supplied, most of
the methods do nothing to the current value, except for *autoflush()*,
which will assume a 1 for you, just to be different.

   A few of these variables are considered "read-only". This means that if
you try to assign to this variable, either directly or indirectly through
a reference, you'll raise a run-time exception.

X<$ARG>
X<$_>
     The default input and pattern-searching space. The following pairs are
     equivalent:

          while (<>) {...}    # only equivalent in while!
          while ($_ = <>) {...}

          /^Subject:/
          $_ =~ /^Subject:/

          tr/a-z/A-Z/
          $_ =~ tr/a-z/A-Z/

          chop
          chop($_)

     Here are the places where Perl will assume `$_' even if you don't use
     it:

     Various unary functions, including functions like *ord()* and *int()*,
     as well as the all file tests (-f, -d) except for -t, which defaults
     to STDIN.

     Various list functions like *print()* and *unlink()*.

     The pattern matching operations m//, s///, and tr/// when used
     without an `=~' operator.

     The default iterator variable in a foreach loop if no other variable
     is supplied.

     The implicit iterator variable in the *grep()* and *map()* functions.

     The default place to put an input record when a `<FH>' operation's
     result is tested by itself as the sole criterion of a while test.
     Note that outside of a while test, this will not happen.

     (Mnemonic: underline is understood in certain operations.)

X<$<digit;$<digit>>
     Contains the subpattern from the corresponding set of parentheses in
     the last pattern matched, not counting patterns matched in nested
     blocks that have been exited already. (Mnemonic: like \digit.) These
     variables are all read-only.

X<$MATCH>
X<$&>
     The string matched by the last successful pattern match (not counting
     any matches hidden within a BLOCK or *eval()* enclosed by the current
     BLOCK). (Mnemonic: like & in some editors.) This variable is
     read-only.

X<$PREMATCH>
X<$`>
     The string preceding whatever was matched by the last successful
     pattern match (not counting any matches hidden within a BLOCK or eval
     enclosed by the current BLOCK). (Mnemonic: ` often precedes a quoted
     string.) This variable is read-only.

X<$POSTMATCH>
X<$'>
     The string following whatever was matched by the last successful
     pattern match (not counting any matches hidden within a BLOCK or
     *eval()* enclosed by the current BLOCK). (Mnemonic: ' often follows a
     quoted string.) Example:

          $_ = 'abcdefghi';
          /def/;
          print "$`:$&:$'\n";         # prints abc:def:ghi

     This variable is read-only.

X<$LAST_PAREN_MATCH>
X<$+>
     The last bracket matched by the last search pattern. This is useful
     if you don't know which of a set of alternative patterns matched. For
     example:

          /Version: (.*)|Revision: (.*)/ && ($rev = $+);

     (Mnemonic: be positive and forward looking.) This variable is
     read-only.

X<$MULTILINE_MATCHING>

     Set to 1 to do multiline matching within a string, 0 to tell Perl
     that it can assume that strings contain a single line, for the
     purpose of optimizing pattern matches. Pattern matches on strings
     containing multiple newlines can produce confusing results when $* is
     0. Default is 0.  (Mnemonic: * matches multiple things.) Note that
     this variable only influences the interpretation of ^ and `$'. A
     literal newline can be searched for even when `$* == 0'.

     Use of $* is deprecated in Perl 5.

X<input_line_number> HANDLE EXPR
X<$INPUT_LINE_NUMBER>
X<$NR>
X<$.>
     The current input line number of the last filehandle that was read. An
     explicit close on the filehandle resets the line number. Since `<>'
     never does an explicit close, line numbers increase across ARGV files
     (but see examples under *eof()*). Localizing $. has the effect of also
     localizing Perl's notion of "the last read filehandle". (Mnemonic:
     many programs use "." to mean the current line number.)

X<input_record_separator> HANDLE EXPR
X<$INPUT_RECORD_SEPARATOR>
X<$RS>
X<$/>
     The input record separator, newline by default. Works like *awk*'s RS
     variable, including treating blank lines as delimiters if set to the
     null string. You may set it to a multicharacter string to match a
     multi-character delimiter. Note that setting it to `"\n\n"' means
     something slightly different than setting it to "", if the file
     contains consecutive blank lines. Setting it to "" will treat two or
     more consecutive blank lines as a single blank line. Setting it to
     `"\n\n"' will blindly assume that the next input character belongs to
     the next paragraph, even if it's a newline. (Mnemonic: / is used to
     delimit line boundaries when quoting poetry.)

          undef $/;
          $_ = <FH>;          # whole file now here
          s/\n[ \t]+/ /g;

X<autoflush> HANDLE EXPR
X<$OUTPUT_AUTOFLUSH>
X<$|>
     If set to nonzero, forces a flush after every write or print on the
     currently selected output channel. Default is 0. Note that STDOUT will
     typically be line buffered if output is to the terminal and block
     buffered otherwise. Setting this variable is useful primarily when
     you are outputting to a pipe, such as when you are running a Perl
     script under rsh and want to see the output as it's happening. This
     has no effect on input buffering. (Mnemonic: when you want your pipes
     to be piping hot.)

X<output_field_separator> HANDLE EXPR
X<$OUTPUT_FIELD_SEPARATOR>
X<$OFS>
X<$,>
     The output field separator for the print operator. Ordinarily the
     print operator simply prints out the comma separated fields you
     specify. In order to get behavior more like *awk*, set this variable
     as you would set *awk*'s OFS variable to specify what is printed
     between fields.  (Mnemonic: what is printed when there is a , in your
     print statement.)

X<output_record_separator> HANDLE EXPR
X<$OUTPUT_RECORD_SEPARATOR>
X<$ORS>
X<$\>
     The output record separator for the print operator. Ordinarily the
     print operator simply prints out the comma separated fields you
     specify, with no trailing newline or record separator assumed. In
     order to get behavior more like *awk*, set this variable as you would
     set *awk*'s ORS variable to specify what is printed at the end of the
     print. (Mnemonic: you set $\ instead of adding \n at the end of the
     print. Also, it's just like /, but it's what you get "back" from
     Perl.)

X<$LIST_SEPARATOR>
X<$">
     This is like $, except that it applies to array values interpolated
     into a double-quoted string (or similar interpreted string). Default
     is a space. (Mnemonic: obvious, I think.)

X<$SUBSCRIPT_SEPARATOR>
X<$SUBSEP>
X<$;>
     The subscript separator for multi-dimensional array emulation. If you
     refer to a hash element as

          $foo{$a,$b,$c}

     it really means

          $foo{join($;, $a, $b, $c)}

     But don't put

          @foo{$a,$b,$c}      # a slice--note the @

     which means

          ($foo{$a},$foo{$b},$foo{$c})

     Default is "\034", the same as SUBSEP in *awk*. Note that if your keys
     contain binary data there might not be any safe value for $;.
     (Mnemonic: comma (the syntactic subscript separator) is a
     semi-semicolon.  Yeah, I know, it's pretty lame, but $, is already
     taken for something more important.)

     Consider using "real" multi-dimensional arrays in Perl 5.

X<$OFMT>
X<$#>
     The output format for printed numbers. This variable is a half-hearted
     attempt to emulate *awk*'s OFMT variable. There are times, however,
     when *awk* and Perl have differing notions of what is in fact
     numeric. Also, the initial value is %.20g rather than %.6g, so you
     need to set $# explicitly to get *awk*'s value. (Mnemonic: # is the
     number sign.)

     Use of $# is deprecated in Perl 5.

X<format_page_number> HANDLE EXPR
X<$FORMAT_PAGE_NUMBER>
X<$%>
     The current page number of the currently selected output channel.
     (Mnemonic: % is page number in *nroff*.)

X<format_lines_per_page> HANDLE EXPR
X<$FORMAT_LINES_PER_PAGE>
X<$=>
     The current page length (printable lines) of the currently selected
     output channel. Default is 60. (Mnemonic: = has horizontal lines.)

X<format_lines_left> HANDLE EXPR
X<$FORMAT_LINES_LEFT>
X<$->
     The number of lines left on the page of the currently selected output
     channel. (Mnemonic: lines_on_page - lines_printed.)

X<format_name> HANDLE EXPR
X<$FORMAT_NAME>
X<$~>
     The name of the current report format for the currently selected
     output channel. Default is name of the filehandle. (Mnemonic: brother
     to $^.)

X<format_top_name> HANDLE EXPR
X<$FORMAT_TOP_NAME>
X<$^>
     The name of the current top-of-page format for the currently selected
     output channel. Default is name of the filehandle with _TOP appended.
     (Mnemonic: points to top of page.)

X<format_line_break_characters> HANDLE EXPR
X<$FORMAT_LINE_BREAK_CHARACTERS>
X<$:>
     The current set of characters after which a string may be broken to
     fill continuation fields (starting with ^) in a format. Default is
     " \n-", to break on whitespace or hyphens. (Mnemonic: a "colon" in
     poetry is a part of a line.)

X<format_formfeed> HANDLE EXPR
X<$FORMAT_FORMFEED>
X<$^L>
     What formats output to perform a formfeed. Default is \f.

X<$ACCUMULATOR>
X<$^A>
     The current value of the *write()* accumulator for *format()* lines.
     A format contains *formline()* commands that put their result into
     $^A. After calling its format, *write()* prints out the contents of
     $^A and empties. So you never actually see the contents of $^A unless
     you call *formline()* yourself and then look at it. See
     `ARRAY(0xd73c0)<' in this node> and `ARRAY(0xd7054)<' in this node>.

X<$CHILD_ERROR>
X<$?>
     The status returned by the last pipe close, backtick (```') command,
     or *system()* operator. Note that this is the status word returned by
     the *wait()* system call, so the exit value of the subprocess is
     actually (`$? >> 8'). Thus on many systems, `$? & 255' gives which
     signal, if any, the process died from, and whether there was a core
     dump. (Mnemonic: similar to *sh* and *ksh*.)

X<$OS_ERROR>
X<$ERRNO>
X<$!>
     If used in a numeric context, yields the current value of errno, with
     all the usual caveats. (This means that you shouldn't depend on the
     value of $!  to be anything in particular unless you've gotten a
     specific error return indicating a system error.) If used in a string
     context, yields the corresponding system error string. You can assign
     to $! in order to set errno if, for instance, you want $! to return
     the string for error n, or you want to set the exit value for the
     *die()* operator. (Mnemonic: What just went bang?)

X<$EVAL_ERROR>
X<$@>
     The Perl syntax error message from the last *eval()* command. If null,
     the last *eval()* parsed and executed correctly (although the
     operations you invoked may have failed in the normal fashion).
     (Mnemonic: Where was the syntax error "at"?)

     Note that warning messages are not collected in this variable. You
     can, however, set up a routine to process warnings by setting
     `$SIG'{__WARN__} below.

X<$PROCESS_ID>
X<$PID>
X<$$>
     The process number of the Perl running this script. (Mnemonic: same as
     shells.)

X<$REAL_USER_ID>
X<$UID>
X<$<;$<>
     The real uid of this process. (Mnemonic: it's the uid you came
     *FROM*, if you're running setuid.)

X<$EFFECTIVE_USER_ID>
X<$EUID>
X<$>>
     The effective uid of this process. Example:

          $< = $>;       # set real to effective uid
          ($<,$>) = ($>,$<);  # swap real and effective uid

     (Mnemonic: it's the uid you went TO, if you're running setuid.) Note:
     `$<' and `$>' can only be swapped on machines supporting *setreuid()*.

X<$REAL_GROUP_ID>
X<$GID>
X<$(>
     The real gid of this process. If you are on a machine that supports
     membership in multiple groups simultaneously, gives a space separated
     list of groups you are in. The first number is the one returned by
     *getgid()*, and the subsequent ones by *getgroups()*, one of which
     may be the same as the first number. (Mnemonic: parentheses are used
     to *GROUP* things.  The real gid is the group you *LEFT*, if you're
     running setgid.)

X<$EFFECTIVE_GROUP_ID>
X<$EGID>
X<$)>
     The effective gid of this process. If you are on a machine that
     supports membership in multiple groups simultaneously, gives a space
     separated list of groups you are in. The first number is the one
     returned by *getegid()*, and the subsequent ones by *getgroups()*,
     one of which may be the same as the first number. (Mnemonic:
     parentheses are used to *GROUP* things.  The effective gid is the
     group that's *RIGHT* for you, if you're running setgid.)

     Note: `$<', `$>', $( and $) can only be set on machines that support
     the corresponding *set[re][ug]*id()** routine. $( and $) can only be
     swapped on machines supporting *setregid()*. Because Perl doesn't
     currently use *initgroups()*, you can't set your group vector to
     multiple groups.

X<$PROGRAM_NAME>

X<$0>
     Contains the name of the file containing the Perl script being
     executed.  Assigning to $0 modifies the argument area that the
     *ps(1)* program sees. This is more useful as a way of indicating the
     current program state than it is for hiding the program you're
     running. (Mnemonic: same as *sh* and *ksh*.)

X<$[>
     The index of the first element in an array, and of the first
     character in a substring. Default is 0, but you could set it to 1 to
     make Perl behave more like *awk* (or Fortran) when subscripting and
     when evaluating the *index()* and *substr()* functions. (Mnemonic: [
     begins subscripts.)

     As of Perl 5, assignment to $[ is treated as a compiler directive, and
     cannot influence the behavior of any other file. Its use is
     discouraged.

X<$PERL_VERSION>
X<$]>
     The string printed out when you say `perl -v'. (This is currently
     *BROKEN*).  It can be used to determine at the beginning of a script
     whether the perl interpreter executing the script is in the right
     range of versions. If used in a numeric context, returns the version
     + patchlevel / 1000.  Example:

          # see if getc is available
          ($version,$patchlevel) =
                   $] =~ /(\d+\.\d+).*\nPatch level: (\d+)/;
          print STDERR "(No filename completion available.)\n"
                   if $version * 1000 + $patchlevel < 2016;

     or, used numerically,

          warn "No checksumming!\n" if $] < 3.019;

     (Mnemonic: Is this version of perl in the right bracket?)

X<$DEBUGGING>
X<$^D>
     The current value of the debugging flags. (Mnemonic: value of
     -D;switches/-D;-D switch.)

X<$SYSTEM_FD_MAX>
X<$^F>
     The maximum system file descriptor, ordinarily 2. System file
     descriptors are passed to *exec()*ed processes, while higher file
     descriptors are not. Also, during an *open()*, system file
     descriptors are preserved even if the *open()* fails. (Ordinary file
     descriptors are closed before the *open()* is attempted.) Note that
     the close-on-exec status of a file descriptor will be decided
     according to the value of $^F at the time of the open, not the time
     of the exec.

X<$INPLACE_EDIT>
X<$^I>
     The current value of the inplace-edit extension. Use undef to disable
     inplace editing. (Mnemonic: value of -i;switches/-i;-i switch.)

X<$PERLDB>
X<$^P>
     The internal flag that the debugger clears so that it doesn't debug
     itself. You could conceivable disable debugging yourself by clearing
     it.

X<$BASETIME>
X<$^T>
     The time at which the script began running, in seconds since the epoch
     (beginning of 1970). The values returned by the -M;switches/-M;-M,
     -A;switches/-A;-A and -C;switches/-C;-C filetests are based on this
     value.

X<$WARNING>
X<$^W>
     The current value of the warning switch, either TRUE or FALSE.
     (Mnemonic: related to the -w;switches/-w;-w switch.)

X<$EXECUTABLE_NAME>
X<$^X>
     The name that the Perl binary itself was executed as, from C's
     `argv[0]'.

X<$ARGV>
     contains the name of the current file when reading from <>.

X<@ARGV>
     The array `@ARGV' contains the command line arguments intended for the
     script. Note that `$#ARGV' is the generally number of arguments minus
     one, since `$ARGV[0]' is the first argument, *NOT* the command name.
     See $0 for the command name.

X<@INC>
     The array `@INC' contains the list of places to look for Perl scripts
     to be evaluated by the `do EXPR', require, or use constructs. It
     initially consists of the arguments to any -I;switches/-I;-I command
     line switches, followed by the default Perl library, probably
     "/usr/local/lib/perl", followed by ".", to represent the current
     directory. If you need to modify this at runtime, you should use the
     `use lib' pragma in order to also get the machine-dependent library
     properly loaded:

          use lib '/mypath/libdir/';
          use SomeMod;

X<%INC>
     The hash `%INC' contains entries for each filename that has been
     included via do or require. The key is the filename you specified,
     and the value is the location of the file actually found. The require
     command uses this array to determine whether a given file has already
     been included.

X<$ENV{expr}>
     The hash `%ENV' contains your current environment. Setting a value in
     ENV changes the environment for child processes.

X<$SIG{expr}>
     The hash `%SIG' is used to set signal handlers for various signals.
     Example:

          sub handler {       # 1st argument is signal name
              local($sig) = @_;
              print "Caught a SIG$sig--shutting down\n";
              close(LOG);
              exit(0);
          }

          $SIG{'INT'} = 'handler';
          $SIG{'QUIT'} = 'handler';
          ...
          $SIG{'INT'} = 'DEFAULT';    # restore default action
          $SIG{'QUIT'} = 'IGNORE';    # ignore SIGQUIT

     The `%SIG' array only contains values for the signals actually set
     within the Perl script. Here are some other examples:

          $SIG{PIPE} = Plumber;       # SCARY!!
          $SIG{"PIPE"} = "Plumber";   # just fine, assumes main::Plumber
          $SIG{"PIPE"} = \&Plumber;   # just fine; assume current Plumber
          $SIG{"PIPE"} = Plumber();   # oops, what did Plumber() return??

     The one marked scary is problematic because it's a bareword, which
     means sometimes it's a string representing the function, and
     sometimes it's going to call the subroutine call right then and
     there! Best to be sure and quote it or take a reference to it.
     *Plumber works too. See `ARRAY(0xd7228)<' in this node>.

     Certain internal hooks can be also set using the `%SIG' hash. The
     routine indicated by `$SIG'{__WARN__} is called when a warning message
     is about to be printed. The warning message is passed as the first
     argument. The presence of a __WARN__ hook causes the ordinary
     printing of warnings to STDERR to be suppressed. You can use this to
     save warnings in a variable, or turn warnings into fatal errors, like
     this:

          local $SIG{__WARN__} = sub { die $_[0] };
          eval $proggie;

     The routine indicated by `$SIG'{__DIE__} is called when a fatal
     exception is about to be thrown. The error message is passed as the
     first argument. When a __DIE__ hook routine returns, the exception
     processing continues as it would have in the absence of the hook,
     unless the hook routine itself exits via a goto, a loop exit, or a
     *die()*. The __DIE__ handler is explicitly disabled during the call,
     so that you can die from a __DIE__ handler. Similarly for __WARN__.

how to execute the Perl interpreter
***********************************

NAME
====

   perlrun - how to execute the Perl interpreter

SYNOPSIS
========

   *perl* [switches] filename args

DESCRIPTION
===========

   Upon startup, Perl looks for your script in one of the following places:

  1. Specified line by line via -e switches on the command line.

  2. Contained in the file specified by the first filename on the command
     line.  (Note that systems supporting the #! notation invoke
     interpreters this way.)

  3. Passed in implicitly via standard input.  This only works if there are
     no filename arguments-to pass arguments to a STDIN script you must
     explicitly specify a "-" for the script name.

        With methods 2 and 3, Perl starts parsing the input file from the
beginning, unless you've specified a -x switch, in which case it scans for
the first line starting with #! and containing the word "perl", and starts
there instead.  This is useful for running a script embedded in a larger
message.  (In this case you would indicate the end of the script using the
__END__ token.)

   As of Perl 5, the #! line is always examined for switches as the line is
being parsed.  Thus, if you're on a machine that only allows one argument
with the #! line, or worse, doesn't even recognize the #! line, you still
can get consistent switch behavior regardless of how Perl was invoked,
even if -x was used to find the beginning of the script.

   Because many operating systems silently chop off kernel interpretation
of the #! line after 32 characters, some switches may be passed in on the
command line, and some may not; you could even get a "-" without its
letter, if you're not careful.  You probably want to make sure that all
your switches fall either before or after that 32 character boundary.
Most switches don't actually care if they're processed redundantly, but
getting a - instead of a complete switch could cause Perl to try to
execute standard input instead of your script.  And a partial -I switch
could also cause odd results.

   Parsing of the #! switches starts wherever "perl" is mentioned in the
line.  The sequences "-*" and "- " are specifically ignored so that you
could, if you were so inclined, say

     #!/bin/sh -- # -*- perl -*- -p
     eval 'exec perl $0 -S ${1+"$@"}'
     	if 0;

   to let Perl see the -p switch.

   If the #! line does not contain the word "perl", the program named after
the #! is executed instead of the Perl interpreter.  This is slightly
bizarre, but it helps people on machines that don't do #!, because they
can tell a program that their SHELL is /usr/bin/perl, and Perl will then
dispatch the program to the correct interpreter for them.

   After locating your script, Perl compiles the entire script to an
internal form.  If there are any compilation errors, execution of the
script is not attempted.  (This is unlike the typical shell script, which
might run partway through before finding a syntax error.)

   If the script is syntactically correct, it is executed.  If the script
runs off the end without hitting an exit() or die() operator, an implicit
`exit(0)' is provided to indicate successful completion.

Switches
--------

   A single-character switch may be combined with the following switch, if
any.

     #!/usr/bin/perl -spi.bak	# same as -s -p -i.bak

   Switches include:

-0digits
     specifies the record separator ($/) as an octal number.  If there are
     no digits, the null character is the separator.  Other switches may
     precede or follow the digits.  For example, if you have a version of
     find which can print filenames terminated by the null character, you
     can say this:

          find . -name '*.bak' -print0 | perl -n0e unlink

     The special value 00 will cause Perl to slurp files in paragraph mode.
     The value 0777 will cause Perl to slurp files whole since there is no
     legal character with that value.

-a
     turns on autosplit mode when used with a -n or -p.  An implicit split
     command to the @F array is done as the first thing inside the
     implicit while loop produced by the -n or -p.

          perl -ane 'print pop(@F), "\n";'

     is equivalent to

          while (<>) {
          	@F = split(' ');
          	print pop(@F), "\n";
          }

     An alternate delimiter may be specified using -F.

-c
     causes Perl to check the syntax of the script and then exit without
     executing it.  Actually, it will execute BEGIN and use blocks, since
     these are considered part of the compilation.

-d
     runs the script under the Perl debugger.  See Perldebug (perl.info).

-Dnumber
-Dlist
     sets debugging flags.  To watch how it executes your script, use
     *-D14*.  (This only works if debugging is compiled into your Perl.)
     Another nice value is *-D1024*, which lists your compiled syntax
     tree.  And *-D512* displays compiled regular expressions. As an
     alternative specify a list of letters instead of numbers (e.g. *-D14*
     is equivalent to *-Dtls*):

          1  p  Tokenizing and Parsing
          2  s  Stack Snapshots
          4  l  Label Stack Processing
          8  t  Trace Execution
                 16  o  Operator Node Construction
                 32  c  String/Numeric Conversions
                 64  P  Print Preprocessor Command for -P
                128  m  Memory Allocation
                256  f  Format Processing
                512  r  Regular Expression Parsing
               1024  x  Syntax Tree Dump
               2048  u  Tainting Checks
               4096  L  Memory Leaks (not supported anymore)
               8192  H  Hash Dump -- usurps values()
              16384  X  Scratchpad Allocation
              32768  D  Cleaning Up

-e *commandline*
     may be used to enter one line of script.  If -e is given, Perl will
     not look for a script filename in the argument list.  Multiple -e
     commands may be given to build up a multi-line script.  Make sure to
     use semicolons where you would in a normal program.

-Fregexp
     specifies a regular expression to split on if -a is also in effect.
     If regexp has `//' around it, the slashes will be ignored.

-i*extension*
     specifies that files processed by the `<>' construct are to be edited
     in-place.  It does this by renaming the input file, opening the output
     file by the original name, and selecting that output file as the
     default for print() statements.  The extension, if supplied, is added
     to the name of the old file to make a backup copy.  If no extension
     is supplied, no backup is made.  From the shell, saying

          $ perl -p -i.bak -e "s/foo/bar/; ... "

     is the same as using the script:

          #!/usr/bin/perl -pi.bak
          s/foo/bar/;

     which is equivalent to

          #!/usr/bin/perl
          while (<>) {
          	if ($ARGV ne $oldargv) {
          	    rename($ARGV, $ARGV . '.bak');
          	    open(ARGVOUT, ">$ARGV");
          	    select(ARGVOUT);
          	    $oldargv = $ARGV;
          	}
          	s/foo/bar/;
          }
          continue {
          	print;	# this prints to original filename
          }
          select(STDOUT);

     except that the -i form doesn't need to compare $ARGV to $oldargv to
     know when the filename has changed.  It does, however, use ARGVOUT for
     the selected filehandle.  Note that STDOUT is restored as the default
     output filehandle after the loop.

     You can use eof without parenthesis to locate the end of each input
     file, in case you want to append to each file, or reset line
     numbering (see example in `eof', see Perlfunc (perl.info)).

-Idirectory
     may be used in conjunction with -P to tell the C preprocessor where
     to look for include files.  By default /usr/include and /usr/lib/perl
     are searched.

-l*octnum*
     enables automatic line-ending processing.  It has two effects:  first,
     it automatically chomps the line terminator when used with -n or -p,
     and second, it assigns "$\" to have the value of *octnum* so that any
     print statements will have that line terminator added back on.  If
     *octnum* is omitted, sets "$\" to the current value of "$/".  For
     instance, to trim lines to 80 columns:

          perl -lpe 'substr($_, 80) = ""'

     Note that the assignment `$\ = $/' is done when the switch is
     processed, so the input record separator can be different than the
     output record separator if the -l switch is followed by a -0 switch:

          gnufind / -print0 | perl -ln0e 'print "found $_" if -p'

     This sets $\ to newline and then sets $/ to the null character.

-n
     causes Perl to assume the following loop around your script, which
     makes it iterate over filename arguments somewhat like *sed -n* or
     *awk*:

          while (<>) {
          	...		# your script goes here
          }

     Note that the lines are not printed by default.  See -p to have lines
     printed.  Here is an efficient way to delete all files older than a
     week:

          find . -mtime +7 -print | perl -nle 'unlink;'

     This is faster than using the `-exec' switch of find because you don't
     have to start a process on every filename found.

     BEGIN and END blocks may be used to capture control before or after
     the implicit loop, just as in *awk*.

-p
     causes Perl to assume the following loop around your script, which
     makes it iterate over filename arguments somewhat like *sed*:

          while (<>) {
          	...		# your script goes here
          } continue {
          	print;
          }

     Note that the lines are printed automatically.  To suppress printing
     use the -n switch.  A -p overrides a -n switch.

     BEGIN and END blocks may be used to capture control before or after
     the implicit loop, just as in awk.

-P
     causes your script to be run through the C preprocessor before
     compilation by Perl.  (Since both comments and cpp directives begin
     with the # character, you should avoid starting comments with any
     words recognized by the C preprocessor such as "if", "else" or
     "define".)

-s
     enables some rudimentary switch parsing for switches on the command
     line after the script name but before any filename arguments (or
     before a -).  Any switch found there is removed from @ARGV and sets
     the corresponding variable in the Perl script.  The following script
     prints "true" if and only if the script is invoked with a *-xyz*
     switch.

          #!/usr/bin/perl -s
          if ($xyz) { print "true\n"; }

-S
     makes Perl use the PATH environment variable to search for the script
     (unless the name of the script starts with a slash).  Typically this
     is used to emulate #! startup on machines that don't support #!, in
     the following manner:

          #!/usr/bin/perl
          eval "exec /usr/bin/perl -S $0 $*"
          	    if $running_under_some_shell;

     The system ignores the first line and feeds the script to /bin/sh,
     which proceeds to try to execute the Perl script as a shell script.
     The shell executes the second line as a normal shell command, and thus
     starts up the Perl interpreter.  On some systems $0 doesn't always
     contain the full pathname, so the -S tells Perl to search for the
     script if necessary.  After Perl locates the script, it parses the
     lines and ignores them because the variable $running_under_some_shell
     is never true.  A better construct than $* would be `${1+"$@"}', which
     handles embedded spaces and such in the filenames, but doesn't work if
     the script is being interpreted by csh.  In order to start up sh
     rather than csh, some systems may have to replace the #! line with a
     line containing just a colon, which will be politely ignored by Perl.
     Other systems can't control that, and need a totally devious
     construct that will work under any of csh, sh or Perl, such as the
     following:

          eval '(exit $?0)' && eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
          & eval 'exec /usr/bin/perl -S $0 $argv:q'
          	if 0;

-T
     forces "taint" checks to be turned on.  Ordinarily these checks are
     done only when running setuid or setgid.  See Perlsec (perl.info).

-u
     causes Perl to dump core after compiling your script.  You can then
     take this core dump and turn it into an executable file by using the
     *undump* program (not supplied).  This speeds startup at the expense
     of some disk space (which you can minimize by stripping the
     executable).  (Still, a "hello world" executable comes out to about
     200K on my machine.)  If you want to execute a portion of your script
     before dumping, use the dump() operator instead.  Note: availability
     of *undump* is platform specific and may not be available for a
     specific port of Perl.

-U
     allows Perl to do unsafe operations.  Currently the only "unsafe"
     operations are the unlinking of directories while running as
     superuser, and running setuid programs with fatal taint checks turned
     into warnings.

-v
     prints the version and patchlevel of your Perl executable.

-w
     prints warnings about identifiers that are mentioned only once, and
     scalar variables that are used before being set.  Also warns about
     redefined subroutines, and references to undefined filehandles or
     filehandles opened readonly that you are attempting to write on.  Also
     warns you if you use values as a number that doesn't look like
     numbers, using an array as though it were a scalar, if your
     subroutines recurse more than 100 deep, and innumerable other things.
     See Perldiag (perl.info), and Perltrap (perl.info).

-x directory
     tells Perl that the script is embedded in a message.  Leading garbage
     will be discarded until the first line that starts with #! and
     contains the string "perl".  Any meaningful switches on that line will
     be applied (but only one group of switches, as with normal #!
     processing).  If a directory name is specified, Perl will switch to
     that directory before running the script.  The -x switch only
     controls the the disposal of leading garbage.  The script must be
     terminated with `__END__' if there is trailing garbage to be ignored
     (the script can process any or all of the trailing garbage via the
     DATA filehandle if desired).

Perl predefined variables
*************************

NAME
====

   perlvar - Perl predefined variables

DESCRIPTION
===========

Predefined Names
----------------

   The following names have special meaning to Perl.  Most of the
punctuational names have reasonable mnemonics, or analogues in one of the
shells.  Nevertheless, if you wish to use the long variable names, you
just need to say

     use English;

   at the top of your program.  This will alias all the short names to the
long names in the current package.  Some of them even have medium names,
generally borrowed from *awk*.

   To go a step further, those variables that depend on the currently
selected filehandle may instead be set by calling an object method on the
FileHandle object.  (Summary lines below for this contain the word
HANDLE.)  First you must say

     use FileHandle;

   after which you may use either

     method HANDLE EXPR

   or

     HANDLE->method(EXPR)

   Each of the methods returns the old value of the FileHandle attribute.
The methods each take an optional EXPR, which if supplied specifies the
new value for the FileHandle attribute in question.  If not supplied, most
of the methods do nothing to the current value, except for autoflush(),
which will assume a 1 for you, just to be different.

   A few of these variables are considered "read-only".  This means that if
you try to assign to this variable, either directly or indirectly through
a reference, you'll raise a run-time exception.

$ARG
$_
     The default input and pattern-searching space.  The following pairs
     are equivalent:

          while (<>) {...}	# only equivalent in while!
          while ($_ = <>) {...}

          /^Subject:/
          $_ =~ /^Subject:/

          tr/a-z/A-Z/
          $_ =~ tr/a-z/A-Z/

          chop
          chop($_)

     (Mnemonic: underline is understood in certain operations.)

$<digit>
     Contains the subpattern from the corresponding set of parentheses in
     the last pattern matched, not counting patterns matched in nested
     blocks that have been exited already.  (Mnemonic: like \digit.)
     These variables are all read-only.

$MATCH
$&
     The string matched by the last successful pattern match (not counting
     any matches hidden within a BLOCK or eval() enclosed by the current
     BLOCK).  (Mnemonic: like & in some editors.)  This variable is
     read-only.

$PREMATCH
$`
     The string preceding whatever was matched by the last successful
     pattern match (not counting any matches hidden within a BLOCK or eval
     enclosed by the current BLOCK).  (Mnemonic: ` often precedes a quoted
     string.)  This variable is read-only.

$POSTMATCH
$'
     The string following whatever was matched by the last successful
     pattern match (not counting any matches hidden within a BLOCK or
     eval() enclosed by the current BLOCK).  (Mnemonic: ' often follows a
     quoted string.)  Example:

          $_ = 'abcdefghi';
          /def/;
          print "$`:$&:$'\n";  	# prints abc:def:ghi

     This variable is read-only.

$LAST_PAREN_MATCH
$+
     The last bracket matched by the last search pattern.  This is useful
     if you don't know which of a set of alternative patterns matched.  For
     example:

          /Version: (.*)|Revision: (.*)/ && ($rev = $+);

     (Mnemonic: be positive and forward looking.)  This variable is
     read-only.

$MULTILINE_MATCHING

     Set to 1 to do multiline matching within a string, 0 to tell Perl
     that it can assume that strings contain a single line, for the purpose
     of optimizing pattern matches.  Pattern matches on strings containing
     multiple newlines can produce confusing results when "$*" is 0.
     Default is 0.  (Mnemonic: * matches multiple things.)  Note that this
     variable only influences the interpretation of "^" and "`$'".  A
     literal newline can be searched for even when `$* == 0'.

     Use of "$*" is deprecated in Perl 5.

input_line_number HANDLE EXPR
$INPUT_LINE_NUMBER
$NR
$.
     The current input line number of the last filehandle that was read.
     An explicit close on the filehandle resets the line number.  Since
     "`<>'" never does an explicit close, line numbers increase across
     ARGV files (but see examples under eof()).  Localizing $. has the
     effect of also localizing Perl's notion of "the last read
     filehandle".  (Mnemonic: many programs use "." to mean the current
     line number.)

input_record_separator HANDLE EXPR
$INPUT_RECORD_SEPARATOR
$RS
$/
     The input record separator, newline by default.  Works like *awk*'s RS
     variable, including treating blank lines as delimiters if set to the
     null string.  You may set it to a multicharacter string to match a
     multi-character delimiter.  Note that setting it to `"\n\n"' means
     something slightly different than setting it to "", if the file
     contains consecutive blank lines.  Setting it to "" will treat two or
     more consecutive blank lines as a single blank line.  Setting it to
     `"\n\n"' will blindly assume that the next input character belongs to
     the next paragraph, even if it's a newline.  (Mnemonic: / is used to
     delimit line boundaries when quoting poetry.)

          undef $/;
          $_ = <FH>; 		# whole file now here
          s/\n[ \t]+/ /g;

autoflush HANDLE EXPR
$OUTPUT_AUTOFLUSH
$|
     If set to nonzero, forces a flush after every write or print on the
     currently selected output channel.  Default is 0.  Note that STDOUT
     will typically be line buffered if output is to the terminal and block
     buffered otherwise.  Setting this variable is useful primarily when
     you are outputting to a pipe, such as when you are running a Perl
     script under rsh and want to see the output as it's happening.
     (Mnemonic: when you want your pipes to be piping hot.)

output_field_separator HANDLE EXPR
$OUTPUT_FIELD_SEPARATOR
$OFS
$,
     The output field separator for the print operator.  Ordinarily the
     print operator simply prints out the comma separated fields you
     specify.  In order to get behavior more like *awk*, set this variable
     as you would set *awk*'s OFS variable to specify what is printed
     between fields.  (Mnemonic: what is printed when there is a , in your
     print statement.)

output_record_separator HANDLE EXPR
$OUTPUT_RECORD_SEPARATOR
$ORS
$\
     The output record separator for the print operator.  Ordinarily the
     print operator simply prints out the comma separated fields you
     specify, with no trailing newline or record separator assumed.  In
     order to get behavior more like *awk*, set this variable as you would
     set *awk*'s ORS variable to specify what is printed at the end of the
     print.  (Mnemonic: you set "$\" instead of adding \n at the end of the
     print.  Also, it's just like /, but it's what you get "back" from
     Perl.)

$LIST_SEPARATOR
$"
     This is like "$," except that it applies to array values interpolated
     into a double-quoted string (or similar interpreted string).  Default
     is a space.  (Mnemonic: obvious, I think.)

$SUBSCRIPT_SEPARATOR
$SUBSEP
$;
     The subscript separator for multi-dimensional array emulation.  If you
     refer to a hash element as

          $foo{$a,$b,$c}

     it really means

          $foo{join($;, $a, $b, $c)}

     But don't put

          @foo{$a,$b,$c}	# a slice--note the @

     which means

          ($foo{$a},$foo{$b},$foo{$c})

     Default is "\034", the same as SUBSEP in *awk*.  Note that if your
     keys contain binary data there might not be any safe value for "$;".
     (Mnemonic: comma (the syntactic subscript separator) is a
     semi-semicolon.  Yeah, I know, it's pretty lame, but "$," is already
     taken for something more important.)

     Consider using "real" multi-dimensional arrays in Perl 5.

$OFMT
$#
     The output format for printed numbers.  This variable is a
     half-hearted attempt to emulate *awk*'s OFMT variable.  There are
     times, however, when *awk* and Perl have differing notions of what is
     in fact numeric.  Also, the initial value is %.20g rather than %.6g,
     so you need to set "$#" explicitly to get *awk*'s value.  (Mnemonic:
     # is the number sign.)

     Use of "$#" is deprecated in Perl 5.

format_page_number HANDLE EXPR
$FORMAT_PAGE_NUMBER
$%
     The current page number of the currently selected output channel.
     (Mnemonic: % is page number in *nroff*.)

format_lines_per_page HANDLE EXPR
$FORMAT_LINES_PER_PAGE
$=
     The current page length (printable lines) of the currently selected
     output channel.  Default is 60.  (Mnemonic: = has horizontal lines.)

format_lines_left HANDLE EXPR
$FORMAT_LINES_LEFT
$-
     The number of lines left on the page of the currently selected output
     channel.  (Mnemonic: lines_on_page - lines_printed.)

format_name HANDLE EXPR
$FORMAT_NAME
$~
     The name of the current report format for the currently selected
     output channel.  Default is name of the filehandle.  (Mnemonic:
     brother to "$^".)

format_top_name HANDLE EXPR
$FORMAT_TOP_NAME
$^
     The name of the current top-of-page format for the currently selected
     output channel.  Default is name of the filehandle with _TOP
     appended.  (Mnemonic: points to top of page.)

format_line_break_characters HANDLE EXPR
$FORMAT_LINE_BREAK_CHARACTERS
$:
     The current set of characters after which a string may be broken to
     fill continuation fields (starting with ^) in a format.  Default is
     " \n-", to break on whitespace or hyphens.  (Mnemonic: a "colon" in
     poetry is a part of a line.)

format_formfeed HANDLE EXPR
$FORMAT_FORMFEED
$^L
     What formats output to perform a formfeed.  Default is \f.

$ACCUMULATOR
$^A
     The current value of the write() accumulator for format() lines.  A
     format contains formline() commands that put their result into $^A.
     After calling its format, write() prints out the contents of $^A and
     empties.  So you never actually see the contents of $^A unless you
     call formline() yourself and then look at it.  See Perlform (perl.info),
     and `formline()', see Perlfunc (perl.info).

$CHILD_ERROR
$?
     The status returned by the last pipe close, backtick (```') command,
     or system() operator.  Note that this is the status word returned by
     the wait() system call, so the exit value of the subprocess is
     actually (`$? >> 8').  Thus on many systems, `$? & 255' gives which
     signal, if any, the process died from, and whether there was a core
     dump.  (Mnemonic: similar to *sh* and *ksh*.)

$OS_ERROR
$ERRNO
$!
     If used in a numeric context, yields the current value of errno, with
     all the usual caveats.  (This means that you shouldn't depend on the
     value of "$!" to be anything in particular unless you've gotten a
     specific error return indicating a system error.)  If used in a string
     context, yields the corresponding system error string.  You can assign
     to "$!" in order to set errno if, for instance, you want "$!" to
     return the string for error n, or you want to set the exit value for
     the die() operator.  (Mnemonic: What just went bang?)

$EVAL_ERROR
$@
     The Perl syntax error message from the last eval() command.  If null,
     the last eval() parsed and executed correctly (although the
     operations you invoked may have failed in the normal fashion).
     (Mnemonic: Where was the syntax error "at"?)

     Note that warning messages are not collected in this variable.  You
     can, however, set up a routine to process warnings by setting
     $SIG{__WARN__} below.

$PROCESS_ID
$PID
$$
     The process number of the Perl running this script.  (Mnemonic: same
     as shells.)

$REAL_USER_ID
$UID
$<
     The real uid of this process.  (Mnemonic: it's the uid you came
     *FROM*, if you're running setuid.)

$EFFECTIVE_USER_ID
$EUID
$>
     The effective uid of this process.  Example:

          $< = $>;		# set real to effective uid
          ($<,$>) = ($>,$<);	# swap real and effective uid

     (Mnemonic: it's the uid you went TO, if you're running setuid.)  Note:
     "`$<'" and "`$>'" can only be swapped on machines supporting
     setreuid().

$REAL_GROUP_ID
$GID
$(
     The real gid of this process.  If you are on a machine that supports
     membership in multiple groups simultaneously, gives a space separated
     list of groups you are in.  The first number is the one returned by
     getgid(), and the subsequent ones by getgroups(), one of which may be
     the same as the first number.  (Mnemonic: parentheses are used to
     *GROUP* things.  The real gid is the group you *LEFT*, if you're
     running setgid.)

$EFFECTIVE_GROUP_ID
$EGID
$)
     The effective gid of this process.  If you are on a machine that
     supports membership in multiple groups simultaneously, gives a space
     separated list of groups you are in.  The first number is the one
     returned by getegid(), and the subsequent ones by getgroups(), one of
     which may be the same as the first number.  (Mnemonic: parentheses are
     used to *GROUP* things.  The effective gid is the group that's
     *RIGHT* for you, if you're running setgid.)

     Note: "`$<'", "`$>'", "$(" and "$)" can only be set on machines that
     support the corresponding *set[re][ug]id()* routine.  "$(" and "$)"
     can only be swapped on machines supporting setregid().

$PROGRAM_NAME

$0
     Contains the name of the file containing the Perl script being
     executed.  Assigning to "$0" modifies the argument area that the ps(1)
     program sees.  This is more useful as a way of indicating the current
     program state than it is for hiding the program you're running.
     (Mnemonic: same as *sh* and *ksh*.)

$[
     The index of the first element in an array, and of the first character
     in a substring.  Default is 0, but you could set it to 1 to make Perl
     behave more like *awk* (or Fortran) when subscripting and when
     evaluating the index() and substr() functions.  (Mnemonic: [ begins
     subscripts.)

     As of Perl 5, assignment to "$[" is treated as a compiler directive,
     and cannot influence the behavior of any other file.  Its use is
     discouraged.

$PERL_VERSION
$]
     The string printed out when you say `perl -v'.  It can be used to
     determine at the beginning of a script whether the perl interpreter
     executing the script is in the right range of versions.  If used in a
     numeric context, returns the version + patchlevel / 1000.  Example:

          # see if getc is available
          ($version,$patchlevel) =
          	     $] =~ /(\d+\.\d+).*\nPatch level: (\d+)/;
          print STDERR "(No filename completion available.)\n"
          	     if $version * 1000 + $patchlevel < 2016;

     or, used numerically,

          warn "No checksumming!\n" if $] < 3.019;

     (Mnemonic: Is this version of perl in the right bracket?)

$DEBUGGING
$^D
     The current value of the debugging flags.  (Mnemonic: value of -D
     switch.)

$SYSTEM_FD_MAX
$^F
     The maximum system file descriptor, ordinarily 2.  System file
     descriptors are passed to exec()ed processes, while higher file
     descriptors are not.  Also, during an open(), system file descriptors
     are preserved even if the open() fails.  (Ordinary file descriptors
     are closed before the open() is attempted.)  Note that the
     close-on-exec status of a file descriptor will be decided according
     to the value of $^F at the time of the open, not the time of the exec.

$INPLACE_EDIT
$^I
     The current value of the inplace-edit extension.  Use undef to disable
     inplace editing.  (Mnemonic: value of -i switch.)

$PERLDB
$^P
     The internal flag that the debugger clears so that it doesn't debug
     itself.  You could conceivable disable debugging yourself by clearing
     it.

$BASETIME
$^T
     The time at which the script began running, in seconds since the
     epoch (beginning of 1970).  The values returned by the -M, -A and -C
     filetests are based on this value.

$WARNING
$^W
     The current value of the warning switch, either TRUE or FALSE.
     (Mnemonic: related to the -w switch.)

$EXECUTABLE_NAME
$^X
     The name that the Perl binary itself was executed as, from C's
     `argv[0]'.

$ARGV
     contains the name of the current file when reading from <>.

@ARGV
     The array @ARGV contains the command line arguments intended for the
     script.  Note that `$#ARGV' is the generally number of arguments minus
     one, since `$ARGV[0]' is the first argument, *NOT* the command name.
     See "$0" for the command name.

@INC
     The array @INC contains the list of places to look for Perl scripts to
     be evaluated by the `do EXPR', require, or use constructs.  It
     initially consists of the arguments to any -I command line switches,
     followed by the default Perl library, probably "/usr/local/lib/perl",
     followed by ".", to represent the current directory.

%INC
     The hash %INC contains entries for each filename that has been
     included via do or require.  The key is the filename you specified,
     and the value is the location of the file actually found.  The
     require command uses this array to determine whether a given file has
     already been included.

$ENV{expr}
     The hash %ENV contains your current environment.  Setting a value in
     ENV changes the environment for child processes.

$SIG{expr}
     The hash %SIG is used to set signal handlers for various signals.
     Example:

          sub handler {	# 1st argument is signal name
          	local($sig) = @_;
          	print "Caught a SIG$sig--shutting down\n";
          	close(LOG);
          	exit(0);
          }

          $SIG{'INT'} = 'handler';
          $SIG{'QUIT'} = 'handler';
          ...
          $SIG{'INT'} = 'DEFAULT';	# restore default action
          $SIG{'QUIT'} = 'IGNORE';	# ignore SIGQUIT

     The %SIG array only contains values for the signals actually set
     within the Perl script.  Here are some other examples:

          $SIG{PIPE} = Plumber;       # SCARY!!
          $SIG{"PIPE"} = "Plumber";   # just fine, assumes main::Plumber
          $SIG{"PIPE"} = \&Plumber;   # just fine; assume current Plumber
          $SIG{"PIPE"} = Plumber();   # oops, what did Plumber() return??

     The one marked scary is problematic because it's a bareword, which
     means sometimes it's a string representing the function, and
     sometimes it's going to call the subroutine call right then and
     there!  Best to be sure and quote it or take a reference to it.
     *Plumber works too.  See `perlsubs' in this node.

     Certain internal hooks can be also set using the %SIG hash.  The
     routine indicated by $SIG{__WARN__} is called when a warning message
     is about to be printed.  The warning message is passed as the first
     argument.  The presence of a __WARN__ hook causes the ordinary
     printing of warnings to STDERR to be suppressed.  You can use this to
     save warnings in a variable, or turn warnings into fatal errors, like
     this:

          local $SIG{__WARN__} = sub { die $_[0] };
          eval $proggie;

     The routine indicated by $SIG{__DIE__} is called when a fatal
     exception is about to be thrown.  The error message is passed as the
     first argument.  When a __DIE__ hook routine returns, the exception
     processing continues as it would have in the absence of the hook,
     unless the hook routine itself exits via a goto, a loop exit, or a
     die.

Perl predefined variables
*************************

NAME
====

   perlvar - Perl predefined variables

DESCRIPTION
===========

Predefined Names
----------------

   The following names have special meaning to Perl.  Most of the
punctuational names have reasonable mnemonics, or analogues in one of the
shells.  Nevertheless, if you wish to use the long variable names, you
just need to say

     use English;

   at the top of your program.  This will alias all the short names to the
long names in the current package.  Some of them even have medium names,
generally borrowed from *awk*.

   To go a step further, those variables that depend on the currently
selected filehandle may instead be set by calling an object method on the
FileHandle object.  (Summary lines below for this contain the word
HANDLE.)  First you must say

     use FileHandle;

   after which you may use either

     method HANDLE EXPR

   or

     HANDLE->method(EXPR)

   Each of the methods returns the old value of the FileHandle attribute.
The methods each take an optional EXPR, which if supplied specifies the
new value for the FileHandle attribute in question.  If not supplied, most
of the methods do nothing to the current value, except for autoflush(),
which will assume a 1 for you, just to be different.

   A few of these variables are considered "read-only".  This means that if
you try to assign to this variable, either directly or indirectly through
a reference, you'll raise a run-time exception.

$ARG
$_
     The default input and pattern-searching space.  The following pairs
     are equivalent:

          while (<>) {...}	# only equivalent in while!
          while ($_ = <>) {...}

          /^Subject:/
          $_ =~ /^Subject:/

          tr/a-z/A-Z/
          $_ =~ tr/a-z/A-Z/

          chop
          chop($_)

     (Mnemonic: underline is understood in certain operations.)

$<digit>
     Contains the subpattern from the corresponding set of parentheses in
     the last pattern matched, not counting patterns matched in nested
     blocks that have been exited already.  (Mnemonic: like \digit.)
     These variables are all read-only.

$MATCH
$&
     The string matched by the last successful pattern match (not counting
     any matches hidden within a BLOCK or eval() enclosed by the current
     BLOCK).  (Mnemonic: like & in some editors.)  This variable is
     read-only.

$PREMATCH
$`
     The string preceding whatever was matched by the last successful
     pattern match (not counting any matches hidden within a BLOCK or eval
     enclosed by the current BLOCK).  (Mnemonic: ` often precedes a quoted
     string.)  This variable is read-only.

$POSTMATCH
$'
     The string following whatever was matched by the last successful
     pattern match (not counting any matches hidden within a BLOCK or
     eval() enclosed by the current BLOCK).  (Mnemonic: ' often follows a
     quoted string.)  Example:

          $_ = 'abcdefghi';
          /def/;
          print "$`:$&:$'\n";  	# prints abc:def:ghi

     This variable is read-only.

$LAST_PAREN_MATCH
$+
     The last bracket matched by the last search pattern.  This is useful
     if you don't know which of a set of alternative patterns matched.  For
     example:

          /Version: (.*)|Revision: (.*)/ && ($rev = $+);

     (Mnemonic: be positive and forward looking.)  This variable is
     read-only.

$MULTILINE_MATCHING

     Set to 1 to do multiline matching within a string, 0 to tell Perl
     that it can assume that strings contain a single line, for the purpose
     of optimizing pattern matches.  Pattern matches on strings containing
     multiple newlines can produce confusing results when "$*" is 0.
     Default is 0.  (Mnemonic: * matches multiple things.)  Note that this
     variable only influences the interpretation of "^" and "`$'".  A
     literal newline can be searched for even when `$* == 0'.

     Use of "$*" is deprecated in Perl 5.

input_line_number HANDLE EXPR
$INPUT_LINE_NUMBER
$NR
$.
     The current input line number of the last filehandle that was read.
     An explicit close on the filehandle resets the line number.  Since
     "`<>'" never does an explicit close, line numbers increase across
     ARGV files (but see examples under eof()).  Localizing $. has the
     effect of also localizing Perl's notion of "the last read
     filehandle".  (Mnemonic: many programs use "." to mean the current
     line number.)

input_record_separator HANDLE EXPR
$INPUT_RECORD_SEPARATOR
$RS
$/
     The input record separator, newline by default.  Works like *awk*'s RS
     variable, including treating blank lines as delimiters if set to the
     null string.  You may set it to a multicharacter string to match a
     multi-character delimiter.  Note that setting it to `"\n\n"' means
     something slightly different than setting it to "", if the file
     contains consecutive blank lines.  Setting it to "" will treat two or
     more consecutive blank lines as a single blank line.  Setting it to
     `"\n\n"' will blindly assume that the next input character belongs to
     the next paragraph, even if it's a newline.  (Mnemonic: / is used to
     delimit line boundaries when quoting poetry.)

          undef $/;
          $_ = <FH>; 		# whole file now here
          s/\n[ \t]+/ /g;

autoflush HANDLE EXPR
$OUTPUT_AUTOFLUSH
$|
     If set to nonzero, forces a flush after every write or print on the
     currently selected output channel.  Default is 0.  Note that STDOUT
     will typically be line buffered if output is to the terminal and block
     buffered otherwise.  Setting this variable is useful primarily when
     you are outputting to a pipe, such as when you are running a Perl
     script under rsh and want to see the output as it's happening.
     (Mnemonic: when you want your pipes to be piping hot.)

output_field_separator HANDLE EXPR
$OUTPUT_FIELD_SEPARATOR
$OFS
$,
     The output field separator for the print operator.  Ordinarily the
     print operator simply prints out the comma separated fields you
     specify.  In order to get behavior more like *awk*, set this variable
     as you would set *awk*'s OFS variable to specify what is printed
     between fields.  (Mnemonic: what is printed when there is a , in your
     print statement.)

output_record_separator HANDLE EXPR
$OUTPUT_RECORD_SEPARATOR
$ORS
$\
     The output record separator for the print operator.  Ordinarily the
     print operator simply prints out the comma separated fields you
     specify, with no trailing newline or record separator assumed.  In
     order to get behavior more like *awk*, set this variable as you would
     set *awk*'s ORS variable to specify what is printed at the end of the
     print.  (Mnemonic: you set "$\" instead of adding \n at the end of the
     print.  Also, it's just like /, but it's what you get "back" from
     Perl.)

$LIST_SEPARATOR
$"
     This is like "$," except that it applies to array values interpolated
     into a double-quoted string (or similar interpreted string).  Default
     is a space.  (Mnemonic: obvious, I think.)

$SUBSCRIPT_SEPARATOR
$SUBSEP
$;
     The subscript separator for multi-dimensional array emulation.  If you
     refer to a hash element as

          $foo{$a,$b,$c}

     it really means

          $foo{join($;, $a, $b, $c)}

     But don't put

          @foo{$a,$b,$c}	# a slice--note the @

     which means

          ($foo{$a},$foo{$b},$foo{$c})

     Default is "\034", the same as SUBSEP in *awk*.  Note that if your
     keys contain binary data there might not be any safe value for "$;".
     (Mnemonic: comma (the syntactic subscript separator) is a
     semi-semicolon.  Yeah, I know, it's pretty lame, but "$," is already
     taken for something more important.)

     Consider using "real" multi-dimensional arrays in Perl 5.

$OFMT
$#
     The output format for printed numbers.  This variable is a
     half-hearted attempt to emulate *awk*'s OFMT variable.  There are
     times, however, when *awk* and Perl have differing notions of what is
     in fact numeric.  Also, the initial value is %.20g rather than %.6g,
     so you need to set "$#" explicitly to get *awk*'s value.  (Mnemonic:
     # is the number sign.)

     Use of "$#" is deprecated in Perl 5.

format_page_number HANDLE EXPR
$FORMAT_PAGE_NUMBER
$%
     The current page number of the currently selected output channel.
     (Mnemonic: % is page number in *nroff*.)

format_lines_per_page HANDLE EXPR
$FORMAT_LINES_PER_PAGE
$=
     The current page length (printable lines) of the currently selected
     output channel.  Default is 60.  (Mnemonic: = has horizontal lines.)

format_lines_left HANDLE EXPR
$FORMAT_LINES_LEFT
$-
     The number of lines left on the page of the currently selected output
     channel.  (Mnemonic: lines_on_page - lines_printed.)

format_name HANDLE EXPR
$FORMAT_NAME
$~
     The name of the current report format for the currently selected
     output channel.  Default is name of the filehandle.  (Mnemonic:
     brother to "$^".)

format_top_name HANDLE EXPR
$FORMAT_TOP_NAME
$^
     The name of the current top-of-page format for the currently selected
     output channel.  Default is name of the filehandle with _TOP
     appended.  (Mnemonic: points to top of page.)

format_line_break_characters HANDLE EXPR
$FORMAT_LINE_BREAK_CHARACTERS
$:
     The current set of characters after which a string may be broken to
     fill continuation fields (starting with ^) in a format.  Default is
     " \n-", to break on whitespace or hyphens.  (Mnemonic: a "colon" in
     poetry is a part of a line.)

format_formfeed HANDLE EXPR
$FORMAT_FORMFEED
$^L
     What formats output to perform a formfeed.  Default is \f.

$ACCUMULATOR
$^A
     The current value of the write() accumulator for format() lines.  A
     format contains formline() commands that put their result into $^A.
     After calling its format, write() prints out the contents of $^A and
     empties.  So you never actually see the contents of $^A unless you
     call formline() yourself and then look at it.  See Perlform (perl.info),
     and `formline()', see Perlfunc (perl.info).

$CHILD_ERROR
$?
     The status returned by the last pipe close, backtick (```') command,
     or system() operator.  Note that this is the status word returned by
     the wait() system call, so the exit value of the subprocess is
     actually (`$? >> 8').  Thus on many systems, `$? & 255' gives which
     signal, if any, the process died from, and whether there was a core
     dump.  (Mnemonic: similar to *sh* and *ksh*.)

$OS_ERROR
$ERRNO
$!
     If used in a numeric context, yields the current value of errno, with
     all the usual caveats.  (This means that you shouldn't depend on the
     value of "$!" to be anything in particular unless you've gotten a
     specific error return indicating a system error.)  If used in a string
     context, yields the corresponding system error string.  You can assign
     to "$!" in order to set errno if, for instance, you want "$!" to
     return the string for error n, or you want to set the exit value for
     the die() operator.  (Mnemonic: What just went bang?)

$EVAL_ERROR
$@
     The Perl syntax error message from the last eval() command.  If null,
     the last eval() parsed and executed correctly (although the
     operations you invoked may have failed in the normal fashion).
     (Mnemonic: Where was the syntax error "at"?)

     Note that warning messages are not collected in this variable.  You
     can, however, set up a routine to process warnings by setting
     $SIG{__WARN__} below.

$PROCESS_ID
$PID
$$
     The process number of the Perl running this script.  (Mnemonic: same
     as shells.)

$REAL_USER_ID
$UID
$<
     The real uid of this process.  (Mnemonic: it's the uid you came
     *FROM*, if you're running setuid.)

$EFFECTIVE_USER_ID
$EUID
$>
     The effective uid of this process.  Example:

          $< = $>;		# set real to effective uid
          ($<,$>) = ($>,$<);	# swap real and effective uid

     (Mnemonic: it's the uid you went TO, if you're running setuid.)  Note:
     "`$<'" and "`$>'" can only be swapped on machines supporting
     setreuid().

$REAL_GROUP_ID
$GID
$(
     The real gid of this process.  If you are on a machine that supports
     membership in multiple groups simultaneously, gives a space separated
     list of groups you are in.  The first number is the one returned by
     getgid(), and the subsequent ones by getgroups(), one of which may be
     the same as the first number.  (Mnemonic: parentheses are used to
     *GROUP* things.  The real gid is the group you *LEFT*, if you're
     running setgid.)

$EFFECTIVE_GROUP_ID
$EGID
$)
     The effective gid of this process.  If you are on a machine that
     supports membership in multiple groups simultaneously, gives a space
     separated list of groups you are in.  The first number is the one
     returned by getegid(), and the subsequent ones by getgroups(), one of
     which may be the same as the first number.  (Mnemonic: parentheses are
     used to *GROUP* things.  The effective gid is the group that's
     *RIGHT* for you, if you're running setgid.)

     Note: "`$<'", "`$>'", "$(" and "$)" can only be set on machines that
     support the corresponding *set[re][ug]id()* routine.  "$(" and "$)"
     can only be swapped on machines supporting setregid().

$PROGRAM_NAME

$0
     Contains the name of the file containing the Perl script being
     executed.  Assigning to "$0" modifies the argument area that the ps(1)
     program sees.  This is more useful as a way of indicating the current
     program state than it is for hiding the program you're running.
     (Mnemonic: same as *sh* and *ksh*.)

$[
     The index of the first element in an array, and of the first character
     in a substring.  Default is 0, but you could set it to 1 to make Perl
     behave more like *awk* (or Fortran) when subscripting and when
     evaluating the index() and substr() functions.  (Mnemonic: [ begins
     subscripts.)

     As of Perl 5, assignment to "$[" is treated as a compiler directive,
     and cannot influence the behavior of any other file.  Its use is
     discouraged.

$PERL_VERSION
$]
     The string printed out when you say `perl -v'.  It can be used to
     determine at the beginning of a script whether the perl interpreter
     executing the script is in the right range of versions.  If used in a
     numeric context, returns the version + patchlevel / 1000.  Example:

          # see if getc is available
          ($version,$patchlevel) =
          	     $] =~ /(\d+\.\d+).*\nPatch level: (\d+)/;
          print STDERR "(No filename completion available.)\n"
          	     if $version * 1000 + $patchlevel < 2016;

     or, used numerically,

          warn "No checksumming!\n" if $] < 3.019;

     (Mnemonic: Is this version of perl in the right bracket?)

$DEBUGGING
$^D
     The current value of the debugging flags.  (Mnemonic: value of -D
     switch.)

$SYSTEM_FD_MAX
$^F
     The maximum system file descriptor, ordinarily 2.  System file
     descriptors are passed to exec()ed processes, while higher file
     descriptors are not.  Also, during an open(), system file descriptors
     are preserved even if the open() fails.  (Ordinary file descriptors
     are closed before the open() is attempted.)  Note that the
     close-on-exec status of a file descriptor will be decided according
     to the value of $^F at the time of the open, not the time of the exec.

$INPLACE_EDIT
$^I
     The current value of the inplace-edit extension.  Use undef to disable
     inplace editing.  (Mnemonic: value of -i switch.)

$PERLDB
$^P
     The internal flag that the debugger clears so that it doesn't debug
     itself.  You could conceivable disable debugging yourself by clearing
     it.

$BASETIME
$^T
     The time at which the script began running, in seconds since the
     epoch (beginning of 1970).  The values returned by the -M, -A and -C
     filetests are based on this value.

$WARNING
$^W
     The current value of the warning switch, either TRUE or FALSE.
     (Mnemonic: related to the -w switch.)

$EXECUTABLE_NAME
$^X
     The name that the Perl binary itself was executed as, from C's
     `argv[0]'.

$ARGV
     contains the name of the current file when reading from <>.

@ARGV
     The array @ARGV contains the command line arguments intended for the
     script.  Note that `$#ARGV' is the generally number of arguments minus
     one, since `$ARGV[0]' is the first argument, *NOT* the command name.
     See "$0" for the command name.

@INC
     The array @INC contains the list of places to look for Perl scripts to
     be evaluated by the `do EXPR', require, or use constructs.  It
     initially consists of the arguments to any -I command line switches,
     followed by the default Perl library, probably "/usr/local/lib/perl",
     followed by ".", to represent the current directory.

%INC
     The hash %INC contains entries for each filename that has been
     included via do or require.  The key is the filename you specified,
     and the value is the location of the file actually found.  The
     require command uses this array to determine whether a given file has
     already been included.

$ENV{expr}
     The hash %ENV contains your current environment.  Setting a value in
     ENV changes the environment for child processes.

$SIG{expr}
     The hash %SIG is used to set signal handlers for various signals.
     Example:

          sub handler {	# 1st argument is signal name
          	local($sig) = @_;
          	print "Caught a SIG$sig--shutting down\n";
          	close(LOG);
          	exit(0);
          }

          $SIG{'INT'} = 'handler';
          $SIG{'QUIT'} = 'handler';
          ...
          $SIG{'INT'} = 'DEFAULT';	# restore default action
          $SIG{'QUIT'} = 'IGNORE';	# ignore SIGQUIT

     The %SIG array only contains values for the signals actually set
     within the Perl script.  Here are some other examples:

          $SIG{PIPE} = Plumber;       # SCARY!!
          $SIG{"PIPE"} = "Plumber";   # just fine, assumes main::Plumber
          $SIG{"PIPE"} = \&Plumber;   # just fine; assume current Plumber
          $SIG{"PIPE"} = Plumber();   # oops, what did Plumber() return??

     The one marked scary is problematic because it's a bareword, which
     means sometimes it's a string representing the function, and
     sometimes it's going to call the subroutine call right then and
     there!  Best to be sure and quote it or take a reference to it.
     *Plumber works too.  See `perlsubs' in this node.

     Certain internal hooks can be also set using the %SIG hash.  The
     routine indicated by $SIG{__WARN__} is called when a warning message
     is about to be printed.  The warning message is passed as the first
     argument.  The presence of a __WARN__ hook causes the ordinary
     printing of warnings to STDERR to be suppressed.  You can use this to
     save warnings in a variable, or turn warnings into fatal errors, like
     this:

          local $SIG{__WARN__} = sub { die $_[0] };
          eval $proggie;

     The routine indicated by $SIG{__DIE__} is called when a fatal
     exception is about to be thrown.  The error message is passed as the
     first argument.  When a __DIE__ hook routine returns, the exception
     processing continues as it would have in the absence of the hook,
     unless the hook routine itself exits via a goto, a loop exit, or a
     die.

package with objects for representing POD documents
***************************************************

NAME
====

   Pod::objects - package with objects for representing POD documents

SYNOPSIS
========

     require Pod::objects;
     my $root = Pod::root->new;

DESCRIPTION
===========

   The following section describes the objects returned by
`Pod::Compiler|Pod::Compiler' in this node and their methods. These
objects all inherit from `Tree::DAG_Node|Tree::DAG_Node' in this node, so
all methods described there are valid as well.

   The set/retrieve methods all work in the following way: If no argument
is specified, the corresponding value is returned. Otherwise the object's
value is set to the given argument and returned.

Common methods
--------------

   The following methods are common for all the classes:

class->new( @parameters )
     Create a new object instance of class. See the individual classes for
     valid parameters.

$obj->line( $num )
     Store/retrieve the line number where this object occurred in the
     source file. Sets and returns the new value if $num is defined and
     simply returns the value otherwise.

$obj->*as_pod*()
     This method returns the object in POD syntax, including its child
     objects. Basically this gives you the same code as in the input file.

$obj->*contents_as_pod*()
     Return this object's children in POD format.

$obj->as_text()
     This method returns the object as simple text in ISO-8859-1 encoding.
     All POD markup is discarded.

$obj->*contents_as_text*()
     Return this object's children as simple text in ISO-8859-1 encoding.
     This strips all POD markup.

Pod::root
---------

   This object represents the root of the POD document and thus serves
mainly as a storage for the following classes. It inherits from
`Storable|Storable' in this node, so that it can easily be stored to and
retrived from the file system.

Pod::root->new( %params )
     The creation method takes an optional argument `-linelength => num'.
     If this is set to a non-zero value, the *as_pod* method of
     Pod::paragraph will reformat the POD to use as much of each line up
     to num characters.

$root->store( $file )
$root->*store_fd*( $filehandle )
     Store the object (and all its contents) to the given file name/handle
     using `Storable|Storable' in this node for subsequent retrieval.

Pod::root->read( $file )
Pod::root->*read_fd*( $filehandle )
     Read the given file/handle into a Pod::root object. $file must
     contain a Pod::root object stored by `Storable|Storable' in this
     node, otherwise a fatal error is raised.

$root->*nodes*()
     Retrieves this POD's node collection, which is maintained as a
     Pod::node::collection object.

$root->errors()
     Returns the number of errors occured during parsing.

$root->warnings()
     Returns the number of warnings occured during parsing.

$root->links()
     Returns all Pod::link objects within the parsed document.

Pod::perlcode
-------------

   If the *-perlcode* option was true for *Pod::Compiler*, then these
objects represent Perl code blocks in the parsed file.

   The as_text method returns the empty string, *as_pod* the contents.

Pod::perlcode->new( $text )
     The new constructor takes an optional parameter, which is the string
     representing the code block. This string may contain newlines.

$perlcode->*contents*( $string )
     This methods sets/retrieves the code block.

$perlcode->append( $code )
     This methods appends $code to the contents.

Pod::paragraph
--------------

   This represents a simple text paragraph. See Pod::root above for an
option that forces the reformatting of the POD code of a paragraph to a
certain line length. Forced line breaks, i.e. a newline followed by
whitespace is not affected.

Pod::verbatim
-------------

   This represents a verbatim paragraph, i.e. a block that has leading
whitespace on its first line.

$verbatim->*addline*( $line )
     Adds one line to this verbatim paragraph. *$line* should not contain
     carriage returns nor newlines.

$verbatim->content( @lines )
     Set this verbatim paragraph's contents to *@lines*. If *@lines* is
     omitted, this method simply returns the current contents, i.e. an
     array of strings that reresent the individual lines.  The contents
     can be cleared completely by saying `$verbatim->content( undef )'.

Pod::head
---------

   This class represents `=headX' directives. The new method accepts a
single argument which denotes the heading level, default is 1.

$head->level( $num )
     This sets/retrieves the heading level. Officially supported are only 1
     and 2, but higher numbers are not rejected here.

$head->node( $node )
     This sets/retrieves the heading's node information. $node and the
     return value are instances of Pod::node or undef.

$head->*nodeid*()
     This retrieves the heading's node id from node above. Just a shortcut
     for `$head->node->id', and safe in case the node is not defined.
     Returns the id string or undef.

$head->*nodetext*()
     This retrieves the heading's node text from node above. Just a
     shortcut for `$head->node->text', and safe in case the node is not
     defined. Returns the node text or undef. The node text is derived
     from what comes after =item, stripping * (bullets) and `\d.?'
     (numbers) as well as all POD markup. The result is what POD links can
     link to from other documents.

Pod::list
---------

   This stores everything that is enclosed by `=over ... =back'. Note that
such a brace may not span `=head's.

$list->*autoopen*( $flag )
     This sets/retrieves the *autoopen* property. A list gets this property
     when the parser encounters an =item without a previous =over. The
     parser then opens a (implicit) list which has the *autoopen* property
     set to true.

$list->indent( $num )
     This sets/retrieves the indent level of the list, i.e. the value that
     follows =over. Default is 4.

$list->type( $string )
     This sets/retrieves the list type. The parser tries to guess this type
     from the =items it encounters. The three possible types are bullet,
     number, and `definition'. In case of doubt, `definition' wins.

$list->*has_items*()
     This retrieves the number of =items in this list.

Pod::item
---------

   This stores a list's =item.

$item->prefix( $string )
     This sets the item's prefix. A prefix can be either '*' or 'o' in
     case of a bullet list or a number, optionally followed by a dot for
     numbered lists. This is stored separately because links to such nodes
     do not contain the prefix.

     In case of a numbered list this method returns subsequent numbers for
     each item independent of what was parsed.

$item->node()
$item->*nodeid*()
$item->*nodetext*()
     See `"Pod::head"' in this node for the description of these methods.

Pod::begin
----------

   This stores everything between `=begin ... =end'. It is unclear how POD
directives in such a block should be handled. The behaviour is undefined
and may change in the future.

   *as_pod* returns the original contents, as_text returns the empty
string.

$begin->type( $string )
     This set/retrieves the begin/end block type, i.e. the first argument
     after =begin.

$begin->args( $string )
     This set/retrieves the begin/end block arguments, i.e. everything the
     follows the first argument after =begin.

$begin->*addchunk*( $string )
     This adds a chunk to the begin/end block. A chunk is a paragraph.

$begin->*contents*()
     Return the current contents, i.e. the array of all chunks.

Pod::for
--------

   This stores =for paragraphs. The *as_pod* method return the original
contents, as_text returns the empty string.

$for->type( $string )
     This sets/retrieves the formatter specification of the =for pargraph.

$for->args( $string )
     This sets/retrieves everything following the formatter specification
     up to the next newline.

$for->content( $string )
     This sets/retrieves the =for paragraph's contents, i.e. everything
     following the first newline after the =for directive.

Textual Objects
---------------

   The following sections describe objects that represent text. They have
some common methods:

$textobj->nested()
     Gives a string that contains the interior sequence codes in which this
     object is nested. A string object XXX inside `B<...I<XXX>...>' would
     thus return `BI'.

$textobj->*as_pod*()
     Gives the POD code of this object, including its children.

$textobj->as_text()
     Gives the objects text contents. No POD markup will be returned.

Pod::string
-----------

   This object contains plain ASCII strings. Note that the contents can
well include angle brackets (`<>'). When converted into POD code, these
are automatically escaped where necesary.

   The new constructor takes an optional argument: the string.

$string->content( $text )
     Set/retrieve the string's contents.

Pod::bold
---------

   This class represents the `B<...>' (bold) interior sequence.

Pod::italic
-----------

   This class represents the `I<...>' (italic) interior sequence.

Pod::code
---------

   This class represents the `C<...>' (code/courier) interior sequence.

Pod::file
---------

   This class represents the `F<...>' (file) interior sequence.

Pod::nonbreaking
----------------

   This class represents the `S<...>' (nonbreaking space) interior
sequence.

Pod::zero
---------

   This class represents the `Z<>' (zero width character) interior
sequence. Note that this sequence cannot have children.

Pod::idx
--------

   This class represents the `X<...>' (index) interior sequence.  The text
therein is not printed in the resulting manpage, but is supposed to appear
in an index with a hyperlink to the place where it occurred.

$idx->node()
$idx->*nodeid*()
$idx->*nodetext*()
     See `"Pod::head"' in this node for the description of these methods.

Pod::entity
-----------

   This class represents the `E<...>' (entity) interior sequence.  This
object has no children, just a value. Entities encountered in the POD
source that map to standard ASCII characters (most notably lt, gt, `sol'
and `verbar') are not kept as entities, but converted into or appended to
the preceding Pod::string, but only if the nesting of this entity permits.

   Entities may be specified as textual entities (`auml', `szlig', etc.),
or a numeric. The usual Perl encodings are valid here: 123 is decimal,
`0x3a' is hexadecimal, `0177' is octal.

   The new constructor takes an optional argument, namely the numeric code
of the entity to create.

   The as_text method returns the corresponding ISO-8859-1 (Latin-1)
character. Sorry, no unicode support yet.

$entity->decode( $string )
     This method can be given any type of entity encoding and sets the
     entity value to the resulting code. This code is undef if the given
     string was not recognized.

$entity->value( $num )
     Sets/retrieves the numeric value of this entity.

$entity->*as_pod*()
     Returns the POD representation of this entity. If a textual encoding
     like `auml' is known for the value it is used, otherwise decimal
     encoding.

Pod::link
---------

   This is a class for representation of POD hyperlinks. The code to parse
the corresponding POD code is entirely in *Pod::Compiler*.

Pod::link->new()
     The new() method can be passed a set of key/value pairs for one-stop
     initialization.

$link->as_text()
     This method returns the textual representation of the hyperlink as
     above, but without markers (read only). Depending on the link type
     this is one of the following alternatives (links to same or other POD
     document):

          page:    L<perl>              the perl manpage
          item:    L<perlvar/$!>        the $! entry in the perlvar manpage
          item:    L</DESTROY>          the DESTOY entry elsewhere in this
                                        document
          head:    L<perldoc/"OPTIONS"> the section on OPTIONS in the perldoc
                                        manpage
          head:    L<"DESCRIPTION">     the section on DESCRIPTION elsewhere
                                        in this document

     The following are not offical, but are supported:

          man:     L<sed(1)>              the sed(1) manpage
          url:     L<http://www.perl.com> http://www.perl.com
                   (same for ftp: news: mailto:)

     If an alternative text (`L<alttext|...>') was specified, this text
     (without POD markup) is returned.

     All POD formatters should use the same text for the different types
     of links. Clever formatters create two hyperlinks for item or section
     links to another page: one to the top of the page (the page name) and
     one to the node within the page (the node name).

$link->page()
     This method sets or returns the POD page this link points to. If
     empty, the link points to the current document itself.

$link->node()
     As above, but the destination node text (either head or item) of the
     link.

$link->*alttext*()
     Sets or returns an alternative text specified in the link.

$link->type()
     The node type, either page, man, head or item. As an unofficial type,
     there is also url, derived from e.g.  `L<http://perl.com>'

$link->*mansect*()
     The node type, either page, man, head or item.  As an unofficial type,
     there is also url, derived from e.g. `L<http://perl.com>'

$link->*as_pod*()
     Returns the link as `L<...>'.

ADDITIONAL CLASSES
==================

   The following classes to not inherit from any other package and serve as
a convenience storage for POD-related data.

Pod::node
---------

   This class stores information about a POD node, i.e. a potential
hyperlink destination. This is derived from `=headX', =item and `X<...>'
entries. See also `"Pod::node::collection"' in this node.

Pod::node->new( %params )
     Creates a new instance of Pod::node. Optional parameters are text,
     id, type. See below.

$node->text( $string )
     Sets/retrieves the node's text. The text is a plain string without any
     POD markup in ISO-8859-1 encoding.

$node->id( $string )
     Sets/retrieves the node's unique id. The id is a string that is unique
     in the POD document and can be used as a hyperlink anchor.

$node->type( $string )
     Sets/retrieves the node's type, which is either `headX' (X being a
     number), item or X, depending on from which POD construct this node
     was derived.

$node->*was_hit*()
     Increments the number of hits to this node. Should be called whenever
     a link was resolved to this node.

$node->hits()
     Retrieves the number of hits on this node.

Pod::node::collection
---------------------

   This class is merely an array that holds Pod::nodes. It provides some
methods to search in this set of nodes.

$ncollection->all()
     Return an array of all nodes. Nodes are instances of Pod::node.

$ncollection->add( @nodes )
     Add the given nodes to the collection. A fatal error occurs when
     trying to add non-Pod::nodes to the collection. Returns true.

$ncollection->*get_by_text*( $string )
     Returns an array of nodes or the first matching node (depending on
     context) that exactly matches the node text. The return value should
     normally be either the empty array or undef for no match and exactly
     one element that matches, unless several nodes with the same text are
     in the collection, which should never occur.

$ncollection->*get_by_rx*( $regexp )
     Same as above, but get the node by matching the given *$regexp* on the
     node text. A fatal error occurs if the regexp has syntax errors.

$ncollection->*get_by_id*( $string )
     Same as above, but get the node by its unique id.

$ncollection->*get_by_type*( $string )
     Same as above, but get the node by its type. The string is treated as
     a regexp, so you can get all `=head' nodes by specifying `"head"' or
     all =head1 nodes by giving "head1".

$ncollection->ids()
     Return an array of all node ids.

$ncollection->*texts*()
     Return an array of all node texts.

Pod::doc
--------

   A convenience class for storing POD document information, especially by
converters. See also `Pod::doc::collection' in this node.

Pod::doc->new( %params )
     Create a new instance of Pod::doc, assigning the given optional
     parameters. See below for the parameter names, they are identical with
     the accessor methods.

$doc->name( $string )
     Set/retrieve the canonical name of the POD document, e.g. perldoc or
     `Pod::Compiler'.

$doc->source( $file )
     Set/retrieve the source file name of the POD document, e.g.
     `/usr/local/bin/perldoc' or
     `/usr/local/lib/perl5/site_perl/Pod/Compiler.pm'.

$doc->*temp*( $file )
     Set/retrieve the temporary file name of the POD document (to be
     created by (Pod::root object)->store), e.g. `/tmp/perldoc.tmp' or
     `/tmp/Pod__Compiler.tmp'. You have to "invent" a method for generating
     temp filenames yourself, see also File/Temp.

$doc->*destination*( $file )
     Set/retrieve the destination file name of the POD document, e.g.
     `/usr/local/share/perl/html/perldoc.html' or
     `/usr/local/share/perl/Pod/Compiler.html'.

$doc->*nodes*( $nodecollection )
     Set/retrieve the this POD document's node collection. When setting,
     the given argument must be a Pod::node::collection object, otherwise a
     fatal error occurs.

Pod::doc::collection
--------------------

   This class serves as a container for a set of Pod::doc objects and
defines some methods for such a collection. This object is simply a hash
with the canonical POD name as key and the corresponding Pod::doc object
as value.

Pod::doc::collection->new()
     Create a new collection instance.

$dcollection->*all_names*()
     Return an array of all sorted documents names in the collection.

$dcollection->*all_objs*()
     Return an array of all Pod::docs in the collection. There is no
     specific sort order.

$dcollection->get( $name )
     Return the Pod::doc object associated with the name $name or undef if
     no such name is in the collection.

$dcollection->add( $name , $object )
$dcollection->add( $object )
     Add the given Pod::doc object to the collection. The two-argument
     form explicitely sets the name to $name, otherwise the objects name
     is used. Exceptions occur if arguments are missing or have the wrong
     type or the name is empty.

$dcollection->*resolve_link*( $link , $name )
     This method tries to resolve the given link (object of class
     Pod::link) in the document named $name within the document
     collection. Returns the Pod::doc and the Pod::node in case of
     success. If the node was found in the current POD (defined by $name)
     then the first return value will be the empty string. If a node was
     found, its hit count is automatically incremented. Example:

          my ($page,$node) = $dcollection->resolve_link( $link, $myname );
          unless(defined $page) {
            warn "Error: Cannot resolve link.\n";
          }
          elsif(!$page) {
            # node is in the current POD $myname
          }
          else {
            # link to another POD
          }

SEE ALSO
========

   See Pod/Compiler, Pod/Parser,
Pod/Find, Pod/Checker,

AUTHOR
======

   Marek Rouchal <marekr@cpan.org>

   *   * bolditalic**bold-italic**

     X<abc/def>

     X<foo;abc/def;xyz/qed>

     `a\bc' in this node

     `$;' in this node

     Y<a\bc/def>

     X<*abc*;abc/def>

     Back in pod.

          This is a verbatim paragraph

   * foo bar bletch This is an item.  Back to paragraphs.

   * foobar bletch.

Perl GOODS interface
********************

NAME
====

   Pogo - Perl GOODS interface

SYNOPSIS
========

     use Pogo;

     $pogo = new Pogo 'sample.cfg';  # connect to a database
     $root = $pogo->root_tie;        # get a reference to root hash in the database

     $root->{key1} = "string";       # store a string into the database
     $value = $root->{key1};         # $value is "string"

     $root->{key2} = [1,2,3];        # store a array into the database
     $arrayref = $root->{key1};      # get a reference to array in the database
     $value = $root->{key2}->[0];    # $value is 1

     $root->{key3} = {a=>1,b=>2};    # store a hash into the database
     $hashref = $root->{key3};       # get a reference to hash in the database
     $value = $root->{key3}->{b};    # $value is 2

     $root->{key4} = new Pogo::Btree;# make a B-tree hash
     $hashref = $root->{key5};       # B-tree is accessed as hash

     $root->{key5} = new Pogo::Htree;# make a H-tree(see below) hash
     $hashref = $root->{key6};       # H-tree is accessed as hash

     $root->{key6} = new Aclass;     # store a object into the database
     $obj = $root->{key4};           # $obj is a Aclass object in the database

DESCRIPTION
===========

Basic feature
-------------

   Pogo is a Perl interface of GOODS (Generic Object Oriented Database
System).  Pogo maps Perl's scalars, arrays, hashes and objects directly to
the database objects. Pogo has the data types as follows.

     - scalar
     - array
     - hash
     - H-tree (hash that hash entry table is placed as B-tree)
     - B-tree

   The value of a scalar data or an element of a collection type data is a
string or a reference to another data. Pogo uses Perl's tieing mechanism
and provide transparent accessibility to persistent data in the database.
Each data in the database can have class name string internally, so Perl
objects (i.e. reference which is blessed by a class name) can be stored in
the database.

GOODS server
------------

   GOODS which is the base of Pogo is a client-server type database. A Pogo
application needs a running GOODS server process in the same machine or
another machine which is connected with TCP/IP network. The GOODS server
program is 'goodsrv' which is installed in /usr/local/goods/bin/.  The
Pogo application and the corresponding goodsrv must use the same TCP port
to communicate with each other, so both use the same configuration file
which specifies goodsrv's hostname and TCP port number. The configuration
file must have a filename extension '.cfg'. Typical configuration file for
a local goodsrv as follows.

     1
     0: localhost:6100

   The '1' at the first line means that this database uses one goodsrv
(two or more goodsrv's are available but Pogo uses always one). The '0:
localhost:6100' at the second line means that first goodsrv is at
localhost and uses port number 6100.

   If this configuration file is saved as 'test.cfg', goodsrv can be
executed as follows.

     goodsrv test

   And the goodsrv creates a set of database files as follows. You must NOT
delete or edit directly these database files.

     test.his
     test.idx
     test.log
     test.map
     test.odb

   The running goodsrv waits commands from your console while providing
database services through the specified TCP port. You can see the database
statistics or backup the database by sending commands to the running
goodsrv. See readme.htm of GOODS.

   For practical use, goodsrv will be executed as a background process.
Pogo has two utility scripts for starting goodsrv at the background and
sending commands to the goodsrv. To start goodsrv with test.cfg, type:

     startgoodsrv test &

   This goodsrv's outputs are saved in test.goodsrv.log.  And to terminate
goodsrv, type:

     cmdgoodsrv test exit

Tie interface
-------------

Connect
     First of all, connect to a running GOODS server.

          $pogo = new Pogo $cfgfilename;

     The $cfgfilename is a configuration filename which specifies GOODS
     server.  The gotten Pogo object will be used after.

*Get root*
     Then, get a hash reference to the root B-tree data in the database.

          $root = $pogo->root_tie;

     NOTE: A persistent data in a GOODS database must be refered by another
     persistent data. If a data is not refered by another persistent data,
     it will be recovered by the GOODS garbage collection system. It means
     that at least one absolutely persistent data is necessary in each
     database. Such data is called 'root'. Pogo database's root is a
     B-tree data. The root_tie method returns a hash reference to the root
     B-tree data in the database.

*String and number*
     To store a data into the database, simply assign a perl data through
     $root.  Note that $root is a hash reference.

          $root->{key} = "value";
          $root->{pi} = 3.14;

     NOTE: Data value strings in the Pogo database can include null
     character ("\x00"). But hash key strings in the Pogo database cannot
     include null character.

     NOTE: The number 3.14 is stored as string "3.14" in the database.
     (This data conversion is an overhead. In the future revision of Pogo,
     it will be stored as number.)

     Now, you can get the values of the data in the database.

          $value = $root->{key};  # $value is "value"
          $pi = $root->{pi};      # $pi is "3.14"

*Array and hash*
     To store an array or a hash, assign its reference.

          $root->{key1} = \@array;
          $root->{key2} = [1,2,3];
          $root->{key3} = \%hash;
          $root->{key4} = {a=>1,b=>2,c=>3};
          $root->{key5} = {a=>[1,2],b=>{c=>3,d=>4}};

     Note that these assignments cause storing the contents of the array
     or hash into the database, not only the reference. Because a
     persistent data in a database cannot refer to a non persitent (i.e.
     only on memory) data. That is to say, the array or hash is copied
     into the database and its reference is assigned. In the above
     example, changing @array or %hash after assignment does not change
     the array of $root->{key1} or the hash of $root->{key3}.

     To fetch the value, normally use ->,[],{}'s.

          $value = $root->{key5}->{a}->[1];  # $value is 2
          $value = $root->{key5}{a}[1];      # -> between {} or [] can be omitted

     If the specfied value is a reference to another data in the database,
     an appropriate type reference is returned. You can use such
     references to store into and fetch from the database.

          $hashref = $root->{key4};     # get a hash reference in the database
          $hashref->{d} = 4;            # store a data
          $value = $hashref->{c};       # $value is 3

     NOTE: A CODE or IO reference cannot be stored into the database.

*Array size*
     Pogo's array is automatically enlarged when needed. But the
     enlargement causes reassignment of the data in the database.  When an
     array reference is assigned, the array size in the database is set to
     the size of the assigned array. If you can estimate the maximum array
     size, setting the array size beforehand is recommended.  To make a
     specified size array, use Pogo::Array::new method.

          $root->{sqrt} = new Pogo::Array 1000;
          for(0..999) { $root->{sqrt}->[$_] = sqrt $_; }

*Hash size*
     Pogo's hash has a static size hash entry table and cannot resize it.
     Note that the hash entry table size does not limit numbers of stored
     keys.  But if too many keys against the hash entry table size are
     stored into a Pogo's hash, it will slow down. So choose appropriate
     hash entry table size for your purpose of using hash. (In the future
     revision of Pogo, automatic hash resizing will be supported.)  When a
     hash reference is assigned, the hash entry table size in the database
     is set to it of the assigned hash.  To make a hash of specified hash
     entry table size, use Pogo::Hash::new method.

          $root->{smallhash} = new Pogo::Hash 8;
          $root->{largehash} = new Pogo::Hash 1024;

     If the size defaults, 256 is used.

*H-tree*
     A hash entry table of Pogo's hash is a static size of array, so too
     large table size is not useful. If you want to use very large hash,
     use H-tree.  A hash entry table of H-tree is placed as B-tree, so
     huge size table is available.  To make a H-tree hash of specified
     hash entry table size, use Pogo::Htree::new method.

          $root->{hugehash} = new Pogo::Htree 131072;

     If the size defaults, 65536 is used.

*B-tree*
     Another way to make huge hash is to use B-tree. In B-tree, a hash key
     itself is used as B-tree key. So hash keys are sorted automatically.
     And B-tree has no hash entry table size problem. On the other hand,
     the key indexes of Pogo's B-tree is made by the first 8 bytes of the
     hash key string. So if many keys have same first 8 bytes, searching
     such keys slows down.  To make a B-tree hash, use Pogo::Btree::new
     method.

          $root->{btree} = new Pogo::Btree;

     Note that no size is required.

     By the tie interface of Pogo, you cannot search key that partially
     matches the specified string. You can do it by Pogo::tied_object
     function and Pogo::Btree::find_key method.

          $foundkey = Pogo::tied_object($root->{btree})->find_key($string);

     Pogo::tied_object returns the behind object which is tied to the
     specified data's referent. If $root->{btree} is a B-tree,
     Pogo::tied_object($root->{btree}) returns a Pogo::Btree object. And
     Pogo::Btree::find_key method returns a key string that matches
     front-partially to the specified string.

*N-tree*
     By B-tree, key string is sorted as character string. So '10' is
     smaller than '2'. By N-tree, key string is sorted as long integer. So
     '2' is smaller than '10'. Except this feature, N-tree is same as
     B-tree.

          $root->{ntree} = new Pogo::Ntree;

Object
     A Perl object which uses only SCALAR/ARRAY/HASH references can be
     stored into the database.

          sub Foo::new { bless {name => $_[1]}, $_[0]; }
          sub Foo::name { $_[0]->{name}; }
          $root->{obj} = new Foo "bar";
          $obj = $root->{obj};            # $obj is a Foo object
          $name = $obj->name;             # $name is "bar"

     If you want to set hash entry table size or use H-tree or B-tree for
     a object, use Pogo::Hash::new_tie, Pogo::Htree::new_tie or
     Pogo::Btree::new_tie method.

          sub Bar::new {
              my($class, $name) = @_;
              my $self = new_tie Pogo::Htree 10000;
              $self->{name} = $name;
              bless $self, $class;
          }

     Note that a class using Pogo::*::new_tie is only for using with Pogo
     database.

Transaction
     Pogo has a transaction mechanism. If there is a sequence of
     operations with a database and you want to make it atomic, use
     transaction mechanism.  The term 'atomic' means that the sequence of
     operations are all done successfully or nothing is done. It means
     also that another database client cannot interrupt the sequence.

     To make a per database transaction, use Pogo::begin_transaction,
     Pogo::abort_transaction and Pogo::end_transaction methods.

          $root->{key} = 1;

          $pogo->begin_transaction;
          $root->{key} = 2;
          $pogo->abort_transaction;    # abort: cancel above assignment
          $value = $root->{key};       # $value is 1

          $pogo->begin_transaction;
          $root->{key} = 3;
          $pogo->end_transaction;      # end: above assignment is valid
          $value = $root->{key};       # $value is 3

     Note that these methods must be called through a concrete Pogo
     object. Calling as class method is not available.

     This transaction locks a whole database. So a long time transaction
     lowers concurrent database access performance.

     To make a per data transaction, use Pogo::atomic_call method.

          $root->{key} = \@array;
          Pogo::atomic_call(\&sortarray, $root->{key});
          sub sortarray { my $aref = shift; @$aref = sort @$aref; }

     While calling sortarray, $root->{key} is locked. So another databse
     client cannot disturb the sorting. And the sorting is done without
     halfway fail.

     An abortion by the user is not supported for a per data transaction.

*Passive action*
     If you need a script which watches a data in the database and does
     some jobs when the data is modified by another database client, use
     Pogo::wait_modification function.

          $result = Pogo::wait_modification($root->{key}, 5);

     When this sentence is executed, execution stops until the data
     $root->{key} is modified by another database client or 5 seconds
     passes. $result is 1 by data modification, 0 by timeout.

     If the timeout seconds defaults, it waits forever.

Database browser
----------------

   Pogo has a database browsing script 'browse'. To browse the database of
test.cfg, type:

     browse test

   Then browse displays as follows and wait for your command.

     test.cfg opened
     root=(HASH(Btree)(10000))>

   Type 'ls' to list the root B-tree hash contents. It displays as follows
for example. For a reference to another data, it displays class name, data
type and object id.

     {aobj} = Aclass(HASH(Hash)(1012d))
     {index} = (HASH(Btree)(10282))
     {list} = (ARRAY(10036))
     {name} = "test"

   Type 'cd index' to change current data to $root->{index}. Then the
prompt is changed as follows for example.

     root{index}=(HASH(Btree))>

   Type 'cd' to return root. Type 'cd ..' to change to parent. And type
'exit' to terminate browse.

Methods
-------

   All but indicated as 'class method' are object methods. The symbol []
means optional argument.

$pogo = Pogo->new [config_filename]
     Class method. This makes and returns a Pogo object. If specified
     config_filename, connect to the running GOODS server which is
     specified by config_filename. The corresponding GOODS server must be
     already running.

$pogo->open config_filename
     If a Pogo object does not connect to the GOODS server yet, this
     method does it.

$pogo->close
     This disconnects to the GOODS server. You may not use this method,
     because it is called when the Pogo object is destroyed automatically.

$pogo->root
     This makes and returns a Pogo::Btree object corresponding to the root
     B-tree.

$pogo->root_tie
     This makes and returns a reference to a hash which is tied to a
     Pogo::Btree object corresponding to the root B-tree.

$pogo->begin_transaction
     This starts a database global transacion.

$pogo->abort_transaction
     This aborts the transacion which was started by
     Pogo::begin_transaction.

$pogo->end_transaction
     This ends the transacion which was started by Pogo::begin_transaction.

$obj = Pogo::Scalar->new [pogoobj]
     Class method. Makes and returns a Pogo::Scalar object.  If Pogo
     object pogoobj is specified, the created object is stored the
     database.

$scalarref = Pogo::Scalar->new_tie [pogoobj [,class]]
     Class method. Makes a Pogo::Scalar object and ties a scalar to it and
     returns a reference to the tied scalar.  If Pogo object pogoobj is
     specified, the created object is stored the database.  If class name
     class is specified, the reference is blessed by the class.

$obj = Pogo::Array->new [size [,pogoobj]]
     Class method. Makes and returns a Pogo::Array object of specified
     size.  If size defaults, 1 is used.  If Pogo object pogoobj is
     specified, the created object is stored the database.

$arrayref = Pogo::Array->new_tie [size [,pogoobj [,class]]]
     Class method. Makes a Pogo::Array object of specified size and ties a
     array to it and returns a reference to the tied array.  If size
     defaults, 1 is used.  If Pogo object pogoobj is specified, the
     created object is stored the database.  If class name class is
     specified, the reference is blessed by the class.

$obj = Pogo::Hash->new [size [,pogoobj]]
     Class method. Makes and returns a Pogo::Hash object of specified hash
     entry table size.  If size defaults, 256 is used.  If Pogo object
     pogoobj is specified, the created object is stored the database.

$hashref = Pogo::Hash->new_tie [size [,pogoobj [,class]]]
     Class method. Makes a Pogo::Hash object of specified hash entry table
     size and ties a hash to it and returns a reference to the tied hash.
     If size defaults, 256 is used.  If Pogo object pogoobj is specified,
     the created object is stored the database.  If class name class is
     specified, the reference is blessed by the class.

$obj = Pogo::Htree->new [size [,pogoobj]]
     Class method. Makes and returns a Pogo::Htree object of specified hash
     entry table size.  If size defaults, 65536 is used.  If Pogo object
     pogoobj is specified, the created object is stored the database.

$hashref = Pogo::Htree->new_tie [size [,pogoobj [,class]]]
     Class method. Makes a Pogo::Htree object of specified hash entry
     table size and ties a hash to it and returns a reference to the tied
     hash. If size defaults, 65536 is used.  If Pogo object pogoobj is
     specified, the created object is stored the database.  If class name
     class is specified, the reference is blessed by the class.

$obj = Pogo::Btree->new [pogoobj]
     Class method. Makes and returns a Pogo::Btree object.  If Pogo object
     pogoobj is specified, the created object is stored the database.

$hashref = Pogo::Btree->new_tie [pogoobj [,class]]
     Class method. Makes a Pogo::Btree object and ties a hash to it and
     returns a reference to the tied hash.  If Pogo object pogoobj is
     specified, the created object is stored the database.  If class name
     class is specified, the reference is blessed by the class.

$obj = Pogo::Ntree->new [pogoobj]
     Class method. Makes and returns a Pogo::Ntree object.  If Pogo object
     pogoobj is specified, the created object is stored the database.

$hashref = Pogo::Ntree->new_tie [pogoobj [,class]]
     Class method. Makes a Pogo::Ntree object and ties a hash to it and
     returns a reference to the tied hash.  If Pogo object pogoobj is
     specified, the created object is stored the database.  If class name
     class is specified, the reference is blessed by the class.

     NOTE: An object created by these Pogo::*::new and Pogo::*::new_tie is
     on the memory unless Pogo object is specified as an argument, not yet
     persistent. When it is assigned into a existing persistent data in a
     database, it becomes persistent. When Pogo object is specified as an
     argument, the gotten object is stored in the database, but it is not
     yet persistent too. When it is refered by a existing persitent data
     in the database, it becomes persistent.

Utility functions
-----------------

Pogo::type_of
     This returns an array of reference type, class name, tied class name
     of the specfied data.

          ($reftype, $class, $tiedclass) = Pogo::type_of($root->{key});

     Typical return values are:

          () : not a reference
          ('ARRAY', '', 'Pogo::Array') : an array
          ('HASH', '', 'Pogo::Btree') : a B-tree hash
          ('HASH', 'Aclass', 'Pogo::Hash') : an Aclass object

Pogo::tied_object
     This returns a Pogo::* object which is tied to the referent of the
     specified Pogo data.

Pogo::equal
     This requires two arguments of Pogo data and returns 1 if its
     datatabase objects are same, 0 if different.

Pogo::object_id
     This returns a database object id of the specified Pogo data.

Pogo::atomic_call
     This calls the specified function atomicly and returns its return
     value.

          $result = Pogo::atomic_call(\&func, $data, @args);

     The first argument \&func is a reference to a subroutine. The second
     argument $data is a Pogo data. This data is locked between calling.
     This is same as below exept the locking.

          $result = func($data, @args);

     The func is called in a scalar context, and returned value is convert
     to a integer number.

Pogo::wait_modification
     This waits the modification of the specified data by another database
     client until the specified seconds passes. And returns 1 by data
     modification, 0 by timeout.

          $result = Pogo::wait_modification($data, $sec);

     If the timeout seconds defaults, it waits forever.

Raw methods
-----------

   These methods below are used by the tie interaface internally.

Pogo::Var
     Pogo::Var is a abstract base class of all Pogo::* classes below. No
     Pogo::Var object is available.

          Pogo::Var::get_class
          Pogo::Var::set_class
          Pogo::Var::begin_transaction
          Pogo::Var::abort_transaction
          Pogo::Var::end_transaction
          Pogo::Var::call
          Pogo::Var::equal
          Pogo::Var::wait_modification
          Pogo::Var::object_id

Pogo::Scalar
          Pogo::Scalar::get
          Pogo::Scalar::set

Pogo::Array
          Pogo::Array::get
          Pogo::Array::set
          Pogo::Array::get_size
          Pogo::Array::set_size
          Pogo::Array::clear
          Pogo::Array::push
          Pogo::Array::pop
          Pogo::Array::insert
          Pogo::Array::remove

Pogo::Hash
          Pogo::Hash::get
          Pogo::Hash::set
          Pogo::Hash::exists
          Pogo::Hash::remove
          Pogo::Hash::clear
          Pogo::Hash::first_key
          Pogo::Hash::next_key

Pogo::Htree
          Pogo::Htree::get
          Pogo::Htree::set
          Pogo::Htree::exists
          Pogo::Htree::remove
          Pogo::Htree::clear
          Pogo::Htree::first_key
          Pogo::Htree::next_key

Pogo::Btree
          Pogo::Btree::get
          Pogo::Btree::set
          Pogo::Btree::exists
          Pogo::Btree::remove
          Pogo::Btree::clear
          Pogo::Btree::first_key
          Pogo::Btree::last_key
          Pogo::Btree::next_key
          Pogo::Btree::prev_key
          Pogo::Btree::find_key

AUTHOR
======

   Sey Nakajima <sey@jkc.co.jp>

SEE ALSO
========

   readme.htm of GOODS

Perl GOODS interface
********************

NAME
====

   Pogo - Perl GOODS interface

SYNOPSIS
========

     use Pogo;

     $pogo = new Pogo 'sample.cfg';  # ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ËÀÜÂ³
     $root = $pogo->root_tie;        # ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Îroot¥Ï¥Ã¥·¥å¤Ø¤Î»²¾È¤òÆÀ¤ë

     $root->{key1} = "string";       # Ê¸»úÎó¤ò¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë³ÊÇ¼
     $value = $root->{key1};         # $value ¤Ï "string"

     $root->{key2} = [1,2,3];        # ÇÛÎó¤ò¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë³ÊÇ¼
     $arrayref = $root->{key1};      # ¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤ÎÇÛÎó¤Ø¤Î»²¾È¤òÆÀ¤ë
     $value = $root->{key2}->[0];    # $value ¤Ï 1

     $root->{key3} = {a=>1,b=>2};    # ¥Ï¥Ã¥·¥å¤ò¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë³ÊÇ¼
     $hashref = $root->{key3};       # ¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Î¥Ï¥Ã¥·¥å¤Ø¤Î»²¾È¤òÆÀ¤ë
     $value = $root->{key3}->{b};    # $value ¤Ï 2

     $root->{key4} = new Pogo::Btree;# B¥Ä¥ê¡¼¥Ï¥Ã¥·¥å¤òºî¤ë
     $hashref = $root->{key5};       # B¥Ä¥ê¡¼¤Ï¥Ï¥Ã¥·¥å¤È¤·¤Æ¥¢¥¯¥»¥¹¤Ç¤­¤ë

     $root->{key5} = new Pogo::Htree;# H¥Ä¥ê¡¼¥Ï¥Ã¥·¥å¤òºî¤ë
     $hashref = $root->{key6};       # H¥Ä¥ê¡¼¤Ï¥Ï¥Ã¥·¥å¤È¤·¤Æ¥¢¥¯¥»¥¹¤Ç¤­¤ë

     $root->{key6} = new Aclass;     # ¥ª¥Ö¥¸¥§¥¯¥È¤ò¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë³ÊÇ¼
     $obj = $root->{key4};           # $obj ¤Ï¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Î Aclass ¥ª¥Ö¥¸¥§¥¯¥È

DESCRIPTION
===========

³µÍ×
----

   Pogo ¤Ï GOODS (Generic Object Oriented Database System)¤Î Perl ¥¤¥ó¥¿
¡¼¥Õ¥§¡¼¥¹¤Ç¤¹¡£Pogo ¤Ï Perl ¤Î¥¹¥«¥é¤äÇÛÎó¤ä¥Ï¥Ã¥·¥å¤ä¥ª¥Ö¥¸¥§¥¯¥È¤ò
¥À¥¤¥ì¥¯¥È¤Ë¥Ç¡¼¥¿¥Ù¡¼¥¹¥ª¥Ö¥¸¥§¥¯¥È¤ËÂÐ±þ¤Å¤±¤Þ¤¹¡£Pogo ¤Ë¤Ï¼¡¤Î¥Ç¡¼
¥¿¥¿¥¤¥×¤¬¤¢¤ê¤Þ¤¹¡£

     - ¥¹¥«¥é¡¼
     - ÇÛÎó
     - ¥Ï¥Ã¥·¥å
     - H¥Ä¥ê¡¼ (¥Ï¥Ã¥·¥å¥¨¥ó¥È¥êÉ½¤¬B¥Ä¥ê¡¼¤È¤Ê¤Ã¤Æ¤¤¤ë¥Ï¥Ã¥·¥å)
     - B¥Ä¥ê¡¼

   ¥¹¥«¥é¡¼¥Ç¡¼¥¿¤ä½¸¹ç¥¿¥¤¥×¥Ç¡¼¥¿¤ÎÍ×ÁÇ¤ÎÃÍ¤Ï¡¢Ê¸»úÎó¤«¡¢Â¾¤Î¥Ç¡¼¥¿¤Ø¤Î
»²¾È¤Ç¤¹¡£Pogo ¤Ï Perl ¤Î tie ¤Î»ÅÁÈ¤ß¤òÍøÍÑ¤·¤Æ¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Î±ÊÂ³¥Ç
¡¼¥¿¤Ø¤ÎÆ©²áÅª¤Ê¥¢¥¯¥»¥¹ÊýË¡¤òÄó¶¡¤·¤Þ¤¹¡£¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Î³Æ¥Ç¡¼¥¿¤ÏÆâ
ÉôÅª¤Ë¥¯¥é¥¹Ì¾¤ò»ý¤Æ¤ë¤Î¤Ç¡¢Perl ¤Î¥ª¥Ö¥¸¥§¥¯¥È¡Ê¤Ä¤Þ¤ê¥¯¥é¥¹Ì¾¤Ç bless
¤µ¤ì¤¿»²¾È¡Ë¤ò¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Ë³ÊÇ¼¤Ç¤­¤Þ¤¹¡£

GOODS ¥µ¡¼¥Ð¡¼
--------------

   Pogo ¤Î¥Ù¡¼¥¹¤È¤Ê¤Ã¤Æ¤¤¤ë GOODS ¤Ï¡¢¥¯¥é¥¤¥¢¥ó¥È¥µ¡¼¥Ð¡¼·¿¤Î¥Ç¡¼¥¿¥Ù¡¼
¥¹¤Ç¤¹¡£Pogo ¤Î¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤Ï¡¢Æ±¤¸¥Þ¥·¥ó¾å¤« TCP/IP ¤Ç¤Ä¤Ê¤¬¤Ã¤¿
Â¾¤Î¥Þ¥·¥ó¾å¤ÇÆ°ºîÃæ¤Î¡¢GOODS ¥µ¡¼¥Ð¡¼¥×¥í¥»¥¹¤òÉ¬Í×¤È¤·¤Þ¤¹¡£GOODS ¥µ
¡¼¥Ð¡¼¤Î¥×¥í¥°¥é¥à¤Ï¡Ögoodsrv¡×¤È¤¤¤¦Ì¾Á°¤Ç¡¢/usr/local/goods/bin/ ¤Ë
¥¤¥ó¥¹¥È¡¼¥ë¤µ¤ì¤Þ¤¹¡£Pogo ¤Î¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤È¤½¤ì¤ËÂÐ±þ¤¹¤ë goodsrv
¤Ï¤ª¸ß¤¤¤ËÄÌ¿®¤¹¤ë¤¿¤á¤ËÆ±¤¸ TCP ¥Ý¡¼¥È¤ò»È¤¦É¬Í×¤¬¤¢¤ê¤Þ¤¹¡£¤½¤Î¤¿¤á
¤ËÎ¾¼Ô¤Ï¡¢goodsrv ¤Î¥Û¥¹¥ÈÌ¾¤È TCP ¥Ý¡¼¥ÈÈÖ¹æ¤òµ­ºÜ¤·¤¿Æ±¤¸ÀßÄê¥Õ¥¡¥¤
¥ë¤ò»²¾È¤·¤Þ¤¹¡£ÀßÄê¥Õ¥¡¥¤¥ë¤Ï¡Ö.cfg¡×¤Î³ÈÄ¥»Ò¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó¡£¥í
¡¼¥«¥ë¥Þ¥·¥ó¾å¤Î goodsrv ¤ËÂÐ¤¹¤ëÅµ·¿Åª¤ÊÀßÄê¥Õ¥¡¥¤¥ë¤Ï¼¡¤Î¤è¤¦¤ÊÆâÍÆ
¤Ë¤Ê¤ê¤Þ¤¹¡£

     1
     0: localhost:6100

   £±¹ÔÌÜ¤Î¡Ö1¡×¤Ï¤³¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬°ì¤Ä¤Î goodsrv ¤ò»È¤¦¤³¤È¤ò°ÕÌ£¤·¤Þ¤¹
¡ÊÆó¤Ä°Ê¾å»È¤¦¤³¤È¤â²ÄÇ½¤Ç¤¹¤¬ Pogo ¤Ç¤Ï°ì¤Ä¤·¤«»È¤¤¤Þ¤»¤ó¡Ë¡£Æó¹ÔÌÜ¤Î
¡Ö0: localhost:6100¡×¤Ï¡¢°ì¤ÄÌÜ¤Î goodsrv ¤¬¡¢localhost ¤Ë¤¢¤Ã¤Æ¡¢¥Ý¡¼
¥ÈÈÖ¹æ6100¤ò»È¤¦¤³¤È¤ò°ÕÌ£¤·¤Æ¤¤¤Þ¤¹¡£

¤³¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤¬¡¢¡Ötest.cfg¡×¤È¤·¤Æºî¤é¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¡¢goodsrv¤Ï¼¡¤Î¤è¤¦¤Ëµ¯Æ°¤Ç¤­¤Þ¤¹¡£

     goodsrv test

   ¤¹¤ë¤È¡¢goodsrv ¤Ï¼¡¤Ë¼¨¤¹°ìÁÈ¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¥Õ¥¡¥¤¥ë¤òºîÀ®¤·¤Þ¤¹¡£¤³¤ì
¤é¤Î¥Õ¥¡¥¤¥ë¤òºï½ü¤·¤¿¤êÄ¾ÀÜÊÔ½¸¤·¤¿¤ê¤ÏÀäÂÐ¤Ë¤·¤Ê¤¤¤Ç¤¯¤À¤µ¤¤¡£

     test.his
     test.idx
     test.log
     test.map
     test.odb

   µ¯Æ°¤·¤¿ goodsrv ¤Ï¥³¥ó¥½¡¼¥ë¤«¤é¤Î¥³¥Þ¥ó¥ÉÆþÎÏ¤òÂÔ¤Á¤Ä¤Ä¡¢»ØÄê¤µ¤ì¤¿
TCP ¥Ý¡¼¥È¤òÄÌ¤¸¤Æ¥Ç¡¼¥¿¥Ù¡¼¥¹¥µ¡¼¥Ó¥¹¤òÄó¶¡¤·¤Þ¤¹¡£¥³¥Þ¥ó¥É¤Ë¤è¤Ã¤Æ¡¢
¥Ç¡¼¥¿¥Ù¡¼¥¹¤ÎÅý·×¾ðÊó¤ò¸«¤¿¤ê¡¢¥Ð¥Ã¥¯¥¢¥Ã¥×¤ò¼è¤Ã¤¿¤ê¤Ç¤­¤Þ¤¹¡£GOODS ¤Î
readme.htm ¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡£

   ¼ÂÍÑ¾å¤Ï¡¢goodsrv ¤Ï¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¥×¥í¥»¥¹¤È¤·¤Æµ¯Æ°¤µ¤ì¤ë¤³¤È¤Ë¤Ê¤ë
¤Ç¤·¤ç¤¦¡£Pogo ¤Ï¡¢goodsrv ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤Çµ¯Æ°¤¹¤ë¤¿¤á¤È¡¢¤½¤Î
goodsrv ¤Ë¥³¥Þ¥ó¥É¤òÁ÷¤ë¤¿¤á¤Î¡¢Æó¤Ä¤Î¥æ¡¼¥Æ¥£¥ê¥Æ¥£¡¼¥¹¥¯¥ê¥×¥È¤òÍÑ°Õ
¤·¤Æ¤¤¤Þ¤¹¡£goodsrv ¤ò¡¢test.cfg ¤Ë½¾¤Ã¤Æµ¯Æ°¤¹¤ë¤Ë¤Ï¼¡¤Î¤è¤¦¤Ë¤·¤Þ¤¹¡£

     startgoodsrv test &

   ¤³¤Î¾ì¹ç¡¢goodsrv¤Î²èÌÌ½ÐÎÏ¤Ïtest.goodsrv.log¤ËÊÝÂ¸¤µ¤ì¤Þ¤¹¡£
goodsrv¤ò½ªÎ»¤¹¤ë¤Ë¤Ï¡¢¼¡¤Î¤è¤¦¤Ë¤·¤Þ¤¹¡£

     cmdgoodsrv test exit

tie¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹
-------------------

ÀÜÂ³
     ¤Þ¤ººÇ½é¤Ë¡¢¼Â¹ÔÃæ¤ÎGOODS¥µ¡¼¥Ð¡¼¤ËÀÜÂ³¤·¤Þ¤¹¡£

          $pogo = new Pogo $cfgfilename;

     $cfgfilename ¤Ï GOODS ¥µ¡¼¥Ð¡¼¤ò»ØÄê¤¹¤ëÀßÄê¥Õ¥¡¥¤¥ëÌ¾¤Ç¤¹¡£¤³¤ì¤ÇÆÀ¤é
     ¤ì¤¿ Pogo ¥ª¥Ö¥¸¥§¥¯¥È¤Ï°Ê²¼¤Ç»ÈÍÑ¤·¤Þ¤¹¡£

¥ë¡¼¥È¤òÆÀ¤ë
     ¼¡¤Ë¡¢¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Î¥ë¡¼¥ÈB¥Ä¥ê¡¼¤Ø¤Î»²¾È¤òÆÀ¤Þ¤¹¡£

          $root = $pogo->root_tie;

     ¥Î¡¼¥È¡§GOODS ¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Î±ÊÂ³¥Ç¡¼¥¿¤Ï¡¢É¬¤ºÂ¾¤Î±ÊÂ³¥Ç¡¼¥¿¤«¤é»²¾È
     ¤µ¤ì¤Æ¤¤¤Ê¤¯¤Æ¤Ï¤Ê¤ê¤Þ¤»¤ó¡£¤â¤·¤¢¤ë¥Ç¡¼¥¿¤¬¤É¤Î±ÊÂ³¥Ç¡¼¥¿¤«¤é¤â»²¾È¤µ
     ¤ì¤Ê¤¯¤Ê¤ë¤È¡¢¤½¤Î¥Ç¡¼¥¿¤Ï GOODS ¤Î¥¬¥Ù¡¼¥¸¥³¥ì¥¯¥·¥ç¥ó¥·¥¹¥Æ¥à¤Ë¤è¤Ã
     ¤Æ²ó¼ý¤µ¤ì¤Þ¤¹¡£¤³¤Î¤³¤È¤«¤é¡¢¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤Ï¾¯¤Ê¤¯¤È¤â°ì¤Ä¤Ï¡¢ÀäÂÐÅª
     ¤Ê±ÊÂ³¥Ç¡¼¥¿¤¬¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¤È¤¤¤¦¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡£¤½¤ì¤¬¥ë¡¼¥È¤È¸Æ¤Ð
     ¤ì¤ë¥Ç¡¼¥¿¤Ç¤¹¡£Pogo ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥ë¡¼¥È¤Ï B ¥Ä¥ê¡¼¥Ç¡¼¥¿¤Ç¤¹¡£
     root_tie ¥á¥½¥Ã¥É¤Ï¡¢¤³¤Î¥ë¡¼¥È B ¥Ä¥ê¡¼¥Ç¡¼¥¿¤Ø¤Î»²¾È¤òÊÖ¤·¤Þ¤¹¡£

Ê¸»úÎó¤È¿ôÃÍ
     ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¥Ç¡¼¥¿¤ò³ÊÇ¼¤¹¤ë¤Ë¤Ï¡¢Ã±¤Ë Perl ¤Î¥Ç¡¼¥¿¤ò $root ¤òÄÌ¤¸
     ¤ÆÂåÆþ¤¹¤ë¤À¤±¤Ç¤¹¡£$root ¤Ï¥Ï¥Ã¥·¥å»²¾È¤Ç¤¢¤ë¤³¤È¤ËÃí°Õ¤·¤Æ¤¯¤À¤µ¤¤¡£

          $root->{key} = "value";
          $root->{pi} = 3.14;

     ¥Î¡¼¥È¡§Pogo ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ç¤Ï¡¢¥Ç¡¼¥¿ÃÍÊ¸»úÎó¤Ë¤Ï¥Ì¥ëÊ¸»ú¡Ê"\x00"¡Ë¤ò
     ´Þ¤à¤³¤È¤¬¤Ç¤­¤Þ¤¹¤¬¡¢¥Ï¥Ã¥·¥å¥­¡¼Ê¸»úÎó¤Ë¤Ï´Þ¤à¤³¤È¤¬¤Ç¤­¤Þ¤»¤ó¡£

     ¥Î¡¼¥È¡§¿ôÃÍ3.14¤ÏÊ¸»úÎó"3.14"¤È¤·¤Æ³ÊÇ¼¤µ¤ì¤Þ¤¹¡£¤³¤Î¥Ç¡¼¥¿ÊÑ´¹¤Ï¥ª¡¼
     ¥Ð¡¼¥Ø¥Ã¥É¤Ç¤¹¤Î¤Ç¡¢¾­Íè¤Î Pogo ¤Ç¤ÏÄ¾ÀÜ¿ôÃÍ¤È¤·¤Æ³ÊÇ¼¤¹¤ë¤è¤¦¤Ë¤Ê¤ë¤Ç
     ¤·¤ç¤¦¡£

     ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¥Ç¡¼¥¿¤ò³ÊÇ¼¤·¤¿¤é¡¢¤½¤ì¤ò¼è¤ê½Ð¤¹¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£

          $value = $root->{key};  # $value ¤Ï "value"
          $pi = $root->{pi};      # $pi ¤Ï "3.14"

ÇÛÎó¤È¥Ï¥Ã¥·¥å
     ÇÛÎó¤ä¥Ï¥Ã¥·¥å¤ò³ÊÇ¼¤¹¤ë¤Ë¤Ï¡¢»²¾È¤òÂåÆþ¤·¤Þ¤¹¡£

          $root->{key1} = \@array;
          $root->{key2} = [1,2,3];
          $root->{key3} = \%hash;
          $root->{key4} = {a=>1,b=>2,c=>3};
          $root->{key5} = {a=>[1,2],b=>{c=>3,d=>4}};

     ¤³¤ÎÂåÆþ¤Ï¡¢»²¾È¤À¤±¤ò³ÊÇ¼¤¹¤ë¤Î¤Ç¤Ï¤Ê¤¯¡¢¤½¤ÎÇÛÎó¤ä¥Ï¥Ã¥·¥å¤ÎÃæÌ£¤â¥Ç
     ¡¼¥¿¥Ù¡¼¥¹¤Ë³ÊÇ¼¤µ¤ì¤ë¤È¤¤¤¦¤³¤È¤ËÃí°Õ¤·¤Æ¤¯¤À¤µ¤¤¡£¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Î±Ê
     Â³¥Ç¡¼¥¿¤Ï¡¢Èó±ÊÂ³¡Ê¤Ä¤Þ¤ê¥á¥â¥ê¾å¤Î¡Ë¥Ç¡¼¥¿¤ò»²¾È¤¹¤ë¤³¤È¤Ï¤Ç¤­¤Þ¤»¤ó
     ¤Î¤Ç¡£¤Ä¤Þ¤ê¡¢ÇÛÎó¤ä¥Ï¥Ã¥·¥å¤Î¥³¥Ô¡¼¤¬¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Ëºî¤é¤ì¤Æ¤½¤Î»²¾È
     ¤¬ÂåÆþ¤µ¤ì¤ë¤³¤È¤Ë¤Ê¤ë¤ï¤±¤Ç¤¹¡£¾å¤ÎÎã¤Ç¸À¤¨¤Ð¡¢ÂåÆþ¸å¤Ë@array ¤ä %
     hash ¤òÊÑ¹¹¤·¤Æ¤â¡¢$root->{key1}¤ÎÇÛÎó¤ä $root->{key3}¤Î¥Ï¥Ã¥·¥å¤¬ÊÑ¹¹
     ¤µ¤ì¤ë¤ï¤±¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡£

     ³ÊÇ¼¤·¤¿ÃÍ¤òÆÀ¤ë¤Ë¤Ï¡¢ÉáÄÌ¤Ë -> ¤ä [] ¤ä {} ¤Îµ­¹æ¤ò»È¤¨¤Ð¤è¤¤¡£

          $value = $root->{key5}->{a}->[1];  # $value ¤Ï 2
          $value = $root->{key5}{a}[1];      # {} ¤ä [] ¤Î´Ö¤Î -> ¤Ï¾ÊÎ¬²ÄÇ½

     ¤â¤·»ØÄê¤·¤¿ÃÍ¤¬¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤ÎÊÌ¤Î¥Ç¡¼¥¿¤Ø¤Î»²¾È¤Ç¤¢¤Ã¤¿¾ì¹ç¤Ï¡¢Á³¤ë
     ¤Ù¤­·¿¤Î»²¾È¤¬ÆÀ¤é¤ì¤Þ¤¹¡£¤½¤Î»²¾È¤Ï¡¢¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¥Ç¡¼¥¿¤ò³ÊÇ¼¤·¤¿¤ê
     ÆÀ¤¿¤ê¤¹¤ë¤Î¤Ë»È¤¨¤Þ¤¹¡£

          $hashref = $root->{key4};     # ¥Ï¥Ã¥·¥å»²¾È¤òÆÀ¤ë
          $hashref->{d} = 4;            # ¥Ç¡¼¥¿¤ò³ÊÇ¼¤¹¤ë
          $value = $hashref->{c};       # $value ¤Ï 3

     ¥Î¡¼¥È¡§CODE¤ÈIO¤Î»²¾È¤Ï¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë³ÊÇ¼¤¹¤ë¤³¤È¤Ï¤Ç¤­¤Þ¤»¤ó¡£

ÇÛÎó¤Î¥µ¥¤¥º
     Pogo ¤ÎÇÛÎó¤ÏÉ¬Í×¤Ê¤È¤­¤Ë¼«Æ°Åª¤ËÂç¤­¤¯¤Ê¤ê¤Þ¤¹¡£¤·¤«¤·¡¢¤³¤ì¤Ï¥Ç¡¼¥¿
     ¥Ù¡¼¥¹Æâ¤Î¥Ç¡¼¥¿¤ÎºÆÇÛÃÖ¤ò¤È¤â¤Ê¤¤¤Þ¤¹¡£ÇÛÎó»²¾È¤¬ÂåÆþ¤µ¤ì¤¿¤È¤­¤Ë¤Ï¡¢
     ¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤ËÀßÄê¤µ¤ì¤Þ¤¹¤¬¡¢¤â¤·ºÇÂç¥µ¥¤¥º¤¬¸«ÀÑ¤â¤ì¤ë¤Ê¤é¡¢¤¢¤é
     ¤«¤¸¤á¥µ¥¤¥º¤òÀßÄê¤·¤Æ¤ª¤¯¤³¤È¤ò¤ª´«¤á¤·¤Þ¤¹¡£¥µ¥¤¥º¤ò»ØÄê¤·¤ÆÇÛÎó¤òºî
     ¤ë¤Ë¤Ï¡¢Pogo::Array::new ¥á¥½¥Ã¥É¤ò»È¤¤¤Þ¤¹¡£

          $root->{sqrt} = new Pogo::Array 1000;
          for(0..999) { $root->{sqrt}->[$_] = sqrt $_; }

¥Ï¥Ã¥·¥å¤Î¥µ¥¤¥º
     Pogo ¤Î¥Ï¥Ã¥·¥å¤Ï¡¢¸ÇÄê¥µ¥¤¥º¤Î¥Ï¥Ã¥·¥å¥¨¥ó¥È¥êÉ½¤ò»ý¤Á¡¢¤½¤Î¥µ¥¤¥º¤ò
     ÊÑ¹¹¤¹¤ë¤³¤È¤Ï¤Ç¤­¤Þ¤»¤ó¡£¥Ï¥Ã¥·¥å¥¨¥ó¥È¥êÉ½¤Î¥µ¥¤¥º¤Ï¡¢³ÊÇ¼¤Ç¤­¤ë¥­¡¼
     ¤Î¿ô¤òÀ©¸Â¤¹¤ë¤ï¤±¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¤¬¡¢¥Ï¥Ã¥·¥å¥¨¥ó¥È¥êÉ½¤Î¥µ¥¤¥º¤ËÂÐ¤·¤Æ
     Â¿¤¹¤®¤ë¥­¡¼¤ò³ÊÇ¼¤¹¤ë¤ÈÃÙ¤¯¤Ê¤ê¤Þ¤¹¡£¤Ç¤¹¤«¤é¡¢¥Ï¥Ã¥·¥å¤ÎÍÑÅÓ¤Ë±þ¤¸¤Æ
     Å¬ÀÚ¤Ê¥Ï¥Ã¥·¥å¥¨¥ó¥È¥êÉ½¤Î¥µ¥¤¥º¤òÁª¤Ö¤³¤È¤¬É¬Í×¤Ç¤¹¡£¡Ê¾­Íè¤Î Pogo ¤Ç
     ¤Ï¼«Æ°Åª¤Ê¥Ï¥Ã¥·¥å¥¨¥ó¥È¥êÉ½¤Î¥µ¥¤¥º³ÈÄ¥¤¬¥µ¥Ý¡¼¥È¤µ¤ì¤ë¤è¤¦¤Ë¤Ê¤ë¤Ç¤·
     ¤ç¤¦¡£¡Ë¥Ï¥Ã¥·¥å»²¾È¤¬ÂåÆþ¤µ¤ì¤ë¤È¤­¤Ë¤Ï¡¢¤½¤Î¥Ï¥Ã¥·¥å¤ÈÆ±¤¸¥Ï¥Ã¥·¥å¥¨
     ¥ó¥È¥êÉ½¤Î¥µ¥¤¥º¤¬ÀßÄê¤µ¤ì¤Þ¤¹¡£¥Ï¥Ã¥·¥å¥¨¥ó¥È¥êÉ½¤Î¥µ¥¤¥º¤ò»ØÄê¤·¤Æ¥Ï
     ¥Ã¥·¥å¤òºî¤ë¤Ë¤Ï¡¢Pogo::Hash::new ¥á¥½¥Ã¥É¤ò»È¤¤¤Þ¤¹¡£

          $root->{smallhash} = new Pogo::Hash 8;
          $root->{largehash} = new Pogo::Hash 1024;

     ¥µ¥¤¥º¤ò¾ÊÎ¬¤¹¤ë¤È¡¢256¤Ë¤Ê¤ê¤Þ¤¹¡£

H¥Ä¥ê¡¼
     Pogo ¤Î¥Ï¥Ã¥·¥å¤Î¥Ï¥Ã¥·¥å¥¨¥ó¥È¥êÉ½¤Ï¸ÇÄê¥µ¥¤¥º¤ÎÇÛÎó¤Ê¤Î¤Ç¡¢¤¢¤Þ¤êÂç
     ¤­¤Ê¥µ¥¤¥º¤Î¥Ï¥Ã¥·¥å¤Ï¼ÂÍÑÅª¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡£¤â¤·Èó¾ï¤ËÂç¤­¤Ê¥Ï¥Ã¥·¥å¤¬
     É¬Í×¤Ê¤é¡¢H ¥Ä¥ê¡¼¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡£H ¥Ä¥ê¡¼¤Î¥Ï¥Ã¥·¥å¥¨¥ó¥È¥êÉ½¤Ï B
     ¥Ä¥ê¡¼¤Ë¤Ê¤Ã¤Æ¤¤¤ë¤Î¤Ç¡¢µðÂç¤Ê¥µ¥¤¥º¤¬²ÄÇ½¤Ç¤¹¡£¥Ï¥Ã¥·¥å¥¨¥ó¥È¥êÉ½¤Î¥µ
     ¥¤¥º¤ò»ØÄê¤·¤Æ H ¥Ä¥ê¡¼¤òºî¤ë¤Ë¤Ï¡¢Pogo::Htree::new
     ¥á¥½¥Ã¥É¤ò»È¤¤¤Þ¤¹¡£

          $root->{hugehash} = new Pogo::Htree 131072;

     ¥µ¥¤¥º¤ò¾ÊÎ¬¤¹¤ë¤È¡¢65536¤Ë¤Ê¤ê¤Þ¤¹¡£

B¥Ä¥ê¡¼
     ¤â¤¦¤Ò¤È¤Ä¤ÎµðÂç¥Ï¥Ã¥·¥å¤òºî¤ëÊýË¡¤Ï¡¢B ¥Ä¥ê¡¼¤Ç¤¹¡£B ¥Ä¥ê¡¼¤Ç¤Ï¡¢¥Ï¥Ã
     ¥·¥å¤Î¥­¡¼¼«ÂÎ¤¬ B ¥Ä¥ê¡¼¤Î¥­¡¼¤È¤Ê¤ê¤Þ¤¹¡£¤½¤Î¤¿¤á¤Ë¥­¡¼¤Ï¼«Æ°Åª¤ËÀ°
     Îó¤µ¤ì¤ë¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡£¤Þ¤¿¡¢¥Ï¥Ã¥·¥å¥¨¥ó¥È¥êÉ½¤Î¥µ¥¤¥º¤Î¥µ¥¤¥º¤ÎÌäÂê
     ¤Ï¤¢¤ê¤Þ¤»¤ó¡£¤½¤Î°ìÊý¤Ç¡¢Pogo ¤Î B ¥Ä¥ê¡¼¤Î¥­¡¼º÷°ú¤Ï¥­¡¼Ê¸»úÎó¤ÎÀèÆ¬
     8¥Ð¥¤¥È¤«¤éºî¤é¤ì¤ë¤¿¤á¡¢¤â¤·Â¿¤¯¤Î¥­¡¼¤¬ÀèÆ¬8¥Ð¥¤¥È¤¬Æ±¤¸¤Ç¤¢¤ë¤È¡¢¤½
     ¤Î¥­¡¼¤ò¸¡º÷¤ÏÃÙ¤¯¤Ê¤ê¤Þ¤¹¡£B ¥Ä¥ê¡¼¤òºî¤ë¤Ë¤Ï¡¢Pogo::Btree::new ¥á¥½
     ¥Ã¥É¤ò»È¤¤¤Þ¤¹¡£

          $root->{btree} = new Pogo::Btree;

     ¥µ¥¤¥º¤Î»ØÄê¤ÏÉ¬Í×¤¢¤ê¤Þ¤»¤ó¡£

     tie ¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤Ç¤Ï¡¢¤¢¤ëÊ¸»úÎó¤ËÉôÊ¬°ìÃ×¤¹¤ë¥Ï¥Ã¥·¥å¥­¡¼¤òÃµ¤¹¤È
     ¤¤¤¦¤³¤È¤Ï¤Ç¤­¤Þ¤»¤ó¡£¤½¤ì¤Ë¤Ï¡¢Pogo::tied_object ¤È Pogo::Btree::find
     _key ¤ò»È¤¤¤Þ¤¹¡£

          $foundkey = Pogo::tied_object($root->{btree})->find_key($string);

     Pogo::tied_object ¤Ï¡¢¥Ç¡¼¥¿¤Î»²¾ÈÀè¤Ë tie ¤µ¤ì¤¿±£¤ì¤¿¥ª¥Ö¥¸¥§¥¯¥È¤ò
     ÊÖ¤·¤Þ¤¹¡£$root->{btree}¤¬ B ¥Ä¥ê¡¼¤Ç¤¢¤ì¤Ð¡¢Pogo::tied_object($root->
     {btree}) ¤Ï Pogo::Btree ¥ª¥Ö¥¸¥§¥¯¥È¤Ë¤Ê¤ê¤Þ¤¹¡£¤½¤·¤Æ¡¢Pogo::Btree::
     find_key
     ¥á¥½¥Ã¥É¤Ï¡¢»ØÄê¤µ¤ì¤¿Ê¸»úÎó¤ËÁ°ÊýÉôÊ¬°ìÃ×¤¹¤ë¥­¡¼¤òÊÖ¤·¤Þ¤¹¡£

N¥Ä¥ê¡¼
     B ¥Ä¥ê¡¼¤Ç¥­¡¼¤òÀ°¿ôÃÍ¤È¤·¤Æ°·¤¤¤¿¤¤¾ì¹ç¤¬¤¢¤ê¤Þ¤¹¡£¤Ä¤Þ¤ê¡¢¡Ö10¡×¤¬
     ¡Ö2¡×¤è¤ê¸å¤Ë¤Ê¤ë¤è¤¦¤Ë¤·¤¿¤¤¡ÊB ¥Ä¥ê¡¼¤Ç¤ÏÊ¸»úÎó¤È¤·¤Æ°·¤¦¤Î¤ÇµÕ¤Ë¤Ê
     ¤ë¡Ë¡£¤½¤¦¤¤¤¦¾ì¹ç¤Ë¤Ï N ¥Ä¥ê¡¼¤ò»È¤¨¤Ð¡¢¥­¡¼¤Ï long À°¿ôÃÍ¤È¤·¤Æ°·¤ï
     ¤ì¤Þ¤¹¡£¤½¤ÎÅÀ¤ò½ü¤±¤Ð B ¥Ä¥ê¡¼¤ÈÆ±¤¸¤Ç¤¹¡£

          $root->{ntree} = new Pogo::Ntree;

¥ª¥Ö¥¸¥§¥¯¥È
     SCALAR/ARRAY/HASH »²¾È¤À¤±¤ò»È¤Ã¤Æ¤¤¤ë Perl ¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ì¤Ð¡¢Pogo
     ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë³ÊÇ¼¤Ç¤­¤Þ¤¹¡£

          sub Foo::new { bless {name => $_[1]}, $_[0]; }
          sub Foo::name { $_[0]->{name}; }
          $root->{obj} = new Foo "bar";
          $obj = $root->{obj};            # $obj ¤Ï Foo ¥ª¥Ö¥¸¥§¥¯¥È
          $name = $obj->name;             # $name ¤Ï "bar"

     ¤â¤·¡¢¥ª¥Ö¥¸¥§¥¯¥È¤Ç»È¤¦¥Ï¥Ã¥·¥å¥¨¥ó¥È¥êÉ½¤Î¥µ¥¤¥º¤ò»ØÄê¤·¤¿¤«¤Ã¤¿¤ê¡¢
     H ¥Ä¥ê¡¼¤ä B ¥Ä¥ê¡¼¤ò»È¤¤¤¿¤¤¤È¤¤¤¦¾ì¹ç¤Ï¡¢Pogo::Hash::new_tie¡¢Pogo::
     Htree::new_tie¡¢Pogo::Btree::new_tie ¤Î¥á¥½¥Ã¥É¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡£

          sub Bar::new {
              my($class, $name) = @_;
              my $self = new_tie Pogo::Htree 10000;
              $self->{name} = $name;
              bless $self, $class;
          }

     Pogo::*::new_tie ¤ò»È¤Ã¤¿¥¯¥é¥¹¤Ï Pogo ¥Ç¡¼¥¿¥Ù¡¼¥¹ÍÑ¤Ë¤Ê¤ë¤³¤È¤ËÃí°Õ
     ¤·¤Æ¤¯¤À¤µ¤¤¡£

¥È¥é¥ó¥¶¥¯¥·¥ç¥ó
     Pogo ¤Ë¤Ï¥È¥é¥ó¥¶¥¯¥·¥ç¥óµ¡¹½¤¬¤¢¤ê¤Þ¤¹¡£¤â¤·¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤Ä¤¤¤Æ¤Î°ì
     Ï¢¤ÎÁàºî¤ò¡ÖÉÔ²ÄÊ¬¡×¤È¤·¤¿¤¤¾ì¹ç¡¢¥È¥é¥ó¥¶¥¯¥·¥ç¥ó¤ò»È¤¤¤Þ¤¹¡£¡ÖÉÔ²Ä
     Ê¬¡×¤È¤Ï¡¢°ìÏ¢¤ÎÁàºî¤¬¤¹¤Ù¤ÆÀ®¸ùÎ¢¤Ë¼Â¹Ô¤µ¤ì¤ë¤«¡¢¤¢¤ë¤¤¤Ï²¿¤â¹Ô¤ï¤ì¤Ê
     ¤¤¤«¡¢¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¤³¤È¤ò°ÕÌ£¤·¤Þ¤¹¡£¤Þ¤¿¡¢Â¾¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¥¯¥é¥¤¥¢
     ¥ó¥È¤¬¡¢¤½¤Î°ìÏ¢¤ÎÁàºî¤Ë³ä¤ê¹þ¤ó¤ÇÍè¤Ê¤¤¤³¤È¤â°ÕÌ£¤·¤Æ¤¤¤Þ¤¹¡£

     ¥Ç¡¼¥¿¥Ù¡¼¥¹Á´ÂÎ¤Ë¤Ä¤¤¤Æ¤Î¥È¥é¥ó¥¶¥¯¥·¥ç¥ó¤òÁàºî¤¹¤ë¤Ë¤Ï¡¢Pogo::
     begin_transaction¡¢Pogo::abort_transaction¡¢Pogo::end_transaction ¤Î¥á
     ¥½¥Ã¥É¤ò»È¤¤¤Þ¤¹¡£

          $root->{key} = 1;

          $pogo->begin_transaction;
          $root->{key} = 2;
          $pogo->abort_transaction;    # Ãæ»ß: ¾å¤ÎÂåÆþ¤Ï¥­¥ã¥ó¥»¥ë¤µ¤ì¤ë
          $value = $root->{key};       # $value ¤Ï 1 ¤Î¤Þ¤Þ

          $pogo->begin_transaction;
          $root->{key} = 3;
          $pogo->end_transaction;      # ½ªÎ»: ¾å¤ÎÂåÆþ¤ÏÍ­¸ú
          $value = $root->{key};       # $value ¤Ï 3

     ¤³¤ì¤é¤Î¥á¥½¥Ã¥É¤Ï¡¢¥¯¥é¥¹¥á¥½¥Ã¥É¤È¤·¤Æ¤Ç¤Ï¤Ê¤¯¡¢¥ª¥Ö¥¸¥§¥¯¥È¥á¥½¥Ã¥É
     ¤È¤·¤Æ¸Æ¤Ð¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó¡£

     ¤³¤Î¥È¥é¥ó¥¶¥¯¥·¥ç¥ó¤Ï¥Ç¡¼¥¿¥Ù¡¼¥¹Á´ÂÎ¤ò¥í¥Ã¥¯¤¹¤ë¤Î¤Ç¡¢Ä¹»þ´Ö¤Î¥È¥é¥ó
     ¥¶¥¯¥·¥ç¥ó¤ÏÊÂ¹Ô½èÍý¤Î¸úÎ¨¤òÄã²¼¤µ¤»¤Þ¤¹¡£

     ¥Ç¡¼¥¿Ëè¤Î¥È¥é¥ó¥¶¥¯¥·¥ç¥ó¤¬É¬Í×¤Ê¾ì¹ç¤Ï¡¢Pogo::atomic_call ¥á¥½¥Ã¥É¤ò
     »È¤¤¤Þ¤¹¡£

          $root->{key} = \@array;
          Pogo::atomic_call(\&sortarray, $root->{key});
          sub sortarray { my $aref = shift; @$aref = sort @$aref; }

     sortarray ¤¬¸Æ¤Ð¤ì¤Æ¤¤¤ë´Ö¡¢$root->{key}¤Ï¥í¥Ã¥¯¤µ¤ì¤Þ¤¹¡£½¾¤Ã¤ÆÂ¾¤Î¥Ç
     ¡¼¥¿¥Ù¡¼¥¹¥¯¥é¥¤¥¢¥ó¥È¤¬¥½¡¼¥È¤ò¼ÙËâ¤¹¤ë¤³¤È¤¬¤¢¤ê¤Þ¤»¤ó¤·¡¢¥½¡¼¥È¤¬Ãæ
     ÅÓÈ¾Ã¼¤Ë½ª¤ï¤ë¤È¤¤¤¦¤³¤È¤â¤¢¤ê¤Þ¤»¤ó¡£

     ¥Ç¡¼¥¿Ëè¤Î¥È¥é¥ó¥¶¥¯¥·¥ç¥ó¤Ë¤Ï¡¢¥æ¡¼¥¶¡¼¤Ë¤è¤ëÃæ»ß¤Îµ¡Ç½¤Ï¤¢¤ê¤Þ¤»¤ó¡£

¼õÆ°ÅªÆ°ºî
     ¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Î¥Ç¡¼¥¿¤ò´Æ»ë¤·¡¢Â¾¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¥¯¥é¥¤¥¢¥ó¥È¤Ë¤è¤Ã¤Æ¤½

     ¤Î¥Ç¡¼¥¿¤¬ÊÑ¹¹¤µ¤ì¤¿¤é²¿¤«¤Î½èÍý¤ò¤¹¤ë¡¢¤È¤¤¤¦¥¹¥¯¥ê¥×¥È¤¬É¬Í×¤Ê¾ì¹ç¤Ï¡¢
     Pogo::wait_modification ´Ø¿ô¤ò»È¤¤¤Þ¤¹¡£

          $result = Pogo::wait_modification($root->{key}, 5);

     ¤³¤ÎÊ¸¤¬¼Â¹Ô¤µ¤ì¤ë¤È¡¢$root->{key}¤¬Â¾¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¥¯¥é¥¤¥¢¥ó¥È¤Ë¤è¤Ã
     ¤ÆÊÑ¹¹¤µ¤ì¤ë¤«¡¢5ÉÃ·Ð¤Ä¤Þ¤Ç¡¢¼Â¹Ô¤Ï»ß¤Þ¤ê¤Þ¤¹¡£$result ¤Ï¡¢¥Ç¡¼¥¿¤¬ÊÑ
     ¹¹¤µ¤ì¤¿¾ì¹ç¤Ï1¡¢»þ´ÖÀÚ¤ì¤Î¾ì¹ç¤Ï0¤Ë¤Ê¤ê¤Þ¤¹¡£

     »þ´ÖÀÚ¤ì¤Þ¤Ç¤ÎÉÃ¿ô¤ò¾ÊÎ¬¤¹¤ë¤È¡¢±Ê±ó¤ËÂÔ¤ÁÂ³¤±¤Þ¤¹¡£

¥Ç¡¼¥¿¥Ù¡¼¥¹¥Ö¥é¥¦¥¶
--------------------

   Pogo ¤Ë¤Ï Pogo ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ÎÆâÍÆ¤òÇÁ¤¯¥¹¥¯¥ê¥×¥È browse ¤¬ÉÕÂ°¤·¤Æ¤¤
¤Þ¤¹¡£test.cfg ¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤òÇÁ¤¯¤Ë¤Ï¡¢¼¡¤Î¤è¤¦¤Ë¼Â¹Ô¤·¤Þ¤¹¡£

     browse test

   ¤¹¤ë¤È¡¢browse¤Ï¼¡¤Î¤è¤¦¤ËÉ½¼¨¤·¤Æ¡¢¥³¥Þ¥ó¥ÉÆþÎÏ¤òÂÔ¤Á¤Þ¤¹¡£

     test.cfg opened
     root=(HASH(Btree)(10000))>

   ¡Öls¡×¤ÈÆþÎÏ¤¹¤ë¤È¥ë¡¼¥È B ¥Ä¥ê¡¼¥Ï¥Ã¥·¥å¤ÎÆâÍÆ¤¬Îã¤¨¤Ð¼¡¤Î¤è¤¦¤Ë¸«¤é
¤ì¤Þ¤¹¡£Â¾¤Î¥Ç¡¼¥¿¤Ø¤Î»²¾È¤Ë¤Ä¤¤¤Æ¤Ï¥¯¥é¥¹Ì¾¡¢¥Ç¡¼¥¿¼ïÊÌ¡¢¥ª¥Ö¥¸¥§¥¯¥È ID
¤¬É½¼¨¤µ¤ì¤Þ¤¹¡£

     {aobj} = Aclass(HASH(Hash)(1012d))
     {index} = (HASH(Btree)(10282))
     {list} = (ARRAY(10036))
     {name} = "test"

   ¤³¤³¤Ç¡Öcd index¡×¤ÈÆþÎÏ¤¹¤ë¤È¡¢¸½ºß°ÌÃÖ¤¬ $root->{index}¤Ë¤Ê¤ê¡¢¥×¥í
¥ó¥×¥È¤Ï¼¡¤Î¤è¤¦¤ËÊÑ¤ï¤ê¤Þ¤¹¡£

     root{index}=(HASH(Btree))>

   ¡Öcd¡×¤ÈÆþÎÏ¤¹¤ë¤È¥ë¡¼¥È¤ËÌá¤ê¤Þ¤¹¡£¡Öcd ..¡×¤ÈÆþÎÏ¤¹¤ë¤È¿Æ¤ËÌá¤ê¤Þ¤¹¡£
¡Öexit¡×¤Ç½ªÎ»¤Ç¤¹¡£

¥á¥½¥Ã¥É
--------

   ¡Ö¥¯¥é¥¹¥á¥½¥Ã¥É¡×¤Èµ­¤µ¤ì¤¿¤â¤Î°Ê³°¤Ï¡¢¥ª¥Ö¥¸¥§¥¯¥È¥á¥½¥Ã¥É¤Ç¤¹¡£[]µ­
¹æ¤Ï¾ÊÎ¬²ÄÇ½¤Ê°ú¿ô¤ò°ÕÌ£¤·¤Þ¤¹¡£

$pogo = Pogo->new [config_filename]
     ¥¯¥é¥¹¥á¥½¥Ã¥É¡£Pogo ¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤Ã¤ÆÊÖ¤·¤Þ¤¹¡£config_filename ¤¬
     »ØÄê¤µ¤ì¤Æ¤¤¤ë¤È¡¢¤½¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤Ë½¾¤Ã¤ÆÆ°ºî¤·¤Æ¤¤¤ë GOODS ¥µ¡¼¥Ð¡¼
     ¤ËÀÜÂ³¤·¤Þ¤¹¡£ÂÐ±þ¤¹¤ë GOODS ¥µ¡¼¥Ð¡¼¤ÏÆ°ºîÃæ¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó¡£

$pogo->open config_filename
     ¤â¤· Pogo ¥ª¥Ö¥¸¥§¥¯¥È¤¬¤Þ¤À GOODS ¥µ¡¼¥Ð¡¼¤ËÀÜÂ³¤·¤Æ¤¤¤Ê¤±¤ì¤Ð¡¢¤³¤Î
     ¥á¥½¥Ã¥É¤ÇÀÜÂ³¤·¤Þ¤¹¡£

$pogo->close
     GOODS ¥µ¡¼¥Ð¡¼¤È¤ÎÀÜÂ³¤òÀÚ¤ê¤Þ¤¹¡£¤³¤Î¥á¥½¥Ã¥É¤ò»È¤¦É¬Í×¤Ï¤¢¤ê¤Þ¤»¤ó¡£
     Pogo ¥ª¥Ö¥¸¥§¥¯¥È¤¬ÇË´þ¤µ¤ì¤ë¤È¤­¤Ë¼«Æ°Åª¤Ë¼Â¹Ô¤µ¤ì¤Þ¤¹¡£

$pogo->root
     ¥ë¡¼¥ÈB¥Ä¥ê¡¼¤ËÂÐ±þ¤·¤¿Pogo::Btree¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤Ã¤ÆÊÖ¤·¤Þ¤¹¡£

$pogo->root_tie
     ¥ë¡¼¥È B ¥Ä¥ê¡¼¤ËÂÐ±þ¤·¤¿ Pogo::Btree ¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤ê¡¢¤½¤ì¤Ë tie
     ¤µ¤ì¤¿¥Ï¥Ã¥·¥å¤Ø¤Î»²¾È¤òÊÖ¤·¤Þ¤¹¡£

$pogo->begin_transaction
     ¥È¥é¥ó¥¶¥¯¥·¥ç¥ó¤ò³«»Ï¤·¤Þ¤¹¡£

$pogo->abort_transaction
     ¥È¥é¥ó¥¶¥¯¥·¥ç¥ó¤òÃæ»ß¤·¤Þ¤¹¡£

$pogo->end_transaction
     ¥È¥é¥ó¥¶¥¯¥·¥ç¥ó¤ò½ªÎ»¤·¤Þ¤¹¡£

$obj = Pogo::Scalar->new [pogoobj]
     ¥¯¥é¥¹¥á¥½¥Ã¥É¡£Pogo::Scalar ¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤Ã¤ÆÊÖ¤·¤Þ¤¹¡£Pogo ¥ª¥Ö¥¸
     ¥§¥¯¥È pogoobj ¤ò»ØÄê¤·¤¿¾ì¹ç¤Ï¡¢¤½¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë³ÊÇ¼¤µ¤ì¤Þ¤¹¡£

$scalarref = Pogo::Scalar->new_tie [pogoobj [,class]]
     ¥¯¥é¥¹¥á¥½¥Ã¥É¡£Pogo::Scalar ¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤ê¡¢¥¹¥«¥é¤ò¤½¤ì¤Ë tie
     ¤·¡¢ ¤½¤Î¥¹¥«¥é¤Î»²¾È¤òÊÖ¤·¤Þ¤¹¡£Pogo ¥ª¥Ö¥¸¥§¥¯¥È pogoobj
     ¤ò»ØÄê¤·¤¿¾ì¹ç¤Ï¡¢ ¤½¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë³ÊÇ¼¤µ¤ì¤Þ¤¹¡£¥¯¥é¥¹Ì¾ class
     ¤ò»ØÄê¤·¤¿¾ì¹ç¤Ï¡¢¤½¤Î ¥¯¥é¥¹Ì¾¤Ç bless ¤µ¤ì¤Þ¤¹¡£

$obj = Pogo::Array->new [size [,pogoobj]]
     ¥¯¥é¥¹¥á¥½¥Ã¥É¡£size ¤Ç»ØÄê¤µ¤ì¤¿¥µ¥¤¥º¤Î Pogo::Array ¥ª¥Ö¥¸¥§¥¯¥È¤òºî
     ¤Ã¤ÆÊÖ¤·¤Þ¤¹¡£size ¤¬¾ÊÎ¬¤µ¤ì¤ë¤È¡¢1¤Ë¤Ê¤ê¤Þ¤¹¡£Pogo ¥ª¥Ö¥¸¥§¥¯¥È
     pogoobj ¤ò»ØÄê¤·¤¿¾ì¹ç¤Ï¡¢¤½¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë³ÊÇ¼¤µ¤ì¤Þ¤¹¡£

$arrayref = Pogo::Array->new_tie [size [,pogoobj [,class]]]
     ¥¯¥é¥¹¥á¥½¥Ã¥É¡£size ¤Ç»ØÄê¤µ¤ì¤¿¥µ¥¤¥º¤Î Pogo::Array ¥ª¥Ö¥¸¥§¥¯¥È¤òºî
     ¤ê¡¢ÇÛÎó¤ò¤½¤ì¤Ë tie ¤·¡¢¤½¤ÎÇÛÎó¤Î»²¾È¤òÊÖ¤·¤Þ¤¹¡£ size ¤¬¾ÊÎ¬¤µ¤ì¤ë
     ¤È¡¢1¤Ë¤Ê¤ê¤Þ¤¹¡£Pogo ¥ª¥Ö¥¸¥§¥¯¥È pogoobj ¤ò»ØÄê¤·¤¿¾ì¹ç¤Ï¡¢¤½¤Î¥Ç¡¼
     ¥¿¥Ù¡¼¥¹¤Ë³ÊÇ¼¤µ¤ì¤Þ¤¹¡£¥¯¥é¥¹Ì¾ class ¤ò»ØÄê¤·¤¿¾ì¹ç¤Ï¡¢¤½¤Î¥¯¥é¥¹Ì¾
     ¤Ç bless ¤µ¤ì¤Þ¤¹¡£

$obj = Pogo::Hash->new [size [,pogoobj]]
     ¥¯¥é¥¹¥á¥½¥Ã¥É¡£size ¤Ç»ØÄê¤µ¤ì¤¿¥µ¥¤¥º¤Î¥Ï¥Ã¥·¥å¥¨¥ó¥È¥êÉ½¤Î Pogo::
     Hash ¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤Ã¤ÆÊÖ¤·¤Þ¤¹¡£size ¤¬¾ÊÎ¬¤µ¤ì¤ë¤È¡¢256
     ¤Ë¤Ê¤ê¤Þ¤¹¡£ Pogo ¥ª¥Ö¥¸¥§¥¯¥È pogoobj
     ¤ò»ØÄê¤·¤¿¾ì¹ç¤Ï¡¢¤½¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë³ÊÇ¼¤µ¤ì ¤Þ¤¹¡£

$hashref = Pogo::Hash->new_tie [size [,pogoobj [,class]]]
     ¥¯¥é¥¹¥á¥½¥Ã¥É¡£size ¤Ç»ØÄê¤µ¤ì¤¿¥µ¥¤¥º¤Î¥Ï¥Ã¥·¥å¥¨¥ó¥È¥êÉ½¤Î Pogo::
     Hash ¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤ê¡¢¥Ï¥Ã¥·¥å¤ò¤½¤ì¤Ë tie ¤·¡¢¤½¤Î¥Ï¥Ã¥·¥å¤Î»²¾È¤ò
     ÊÖ¤·¤Þ¤¹¡£size ¤¬¾ÊÎ¬¤µ¤ì¤ë¤È¡¢256 ¤Ë¤Ê¤ê¤Þ¤¹¡£Pogo ¥ª¥Ö¥¸¥§¥¯¥È
     pogoobj ¤ò»ØÄê¤·¤¿¾ì¹ç¤Ï¡¢¤½¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë³ÊÇ¼¤µ¤ì¤Þ¤¹¡£¥¯¥é¥¹Ì¾
     class ¤ò»ØÄê¤·¤¿¾ì¹ç¤Ï¡¢¤½¤Î¥¯¥é¥¹Ì¾¤Ç bless ¤µ¤ì¤Þ¤¹¡£

$obj = Pogo::Htree->new [size [,pogoobj]]
     ¥¯¥é¥¹¥á¥½¥Ã¥É¡£size ¤Ç»ØÄê¤µ¤ì¤¿¥µ¥¤¥º¤Î¥Ï¥Ã¥·¥å¥¨¥ó¥È¥êÉ½¤Î Pogo::
     Htree ¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤Ã¤ÆÊÖ¤·¤Þ¤¹¡£size ¤¬¾ÊÎ¬¤µ¤ì¤ë¤È¡¢ 65536 ¤Ë¤Ê¤ê
     ¤Þ¤¹¡£Pogo ¥ª¥Ö¥¸¥§¥¯¥È pogoobj ¤ò»ØÄê¤·¤¿¾ì¹ç¤Ï¡¢¤½¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë³Ê
     Ç¼¤µ¤ì¤Þ¤¹¡£

$hashref = Pogo::Htree->new_tie [size [,pogoobj [,class]]]
     ¥¯¥é¥¹¥á¥½¥Ã¥É¡£size ¤Ç»ØÄê¤µ¤ì¤¿¥µ¥¤¥º¤Î¥Ï¥Ã¥·¥å¥¨¥ó¥È¥êÉ½¤Î Pogo::
     Htree ¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤ê¡¢¥Ï¥Ã¥·¥å¤ò¤½¤ì¤Ë tie ¤·¡¢¤½¤Î¥Ï¥Ã¥·¥å¤Î»²¾È
     ¤òÊÖ¤·¤Þ¤¹¡£size ¤¬¾ÊÎ¬¤µ¤ì¤ë¤È¡¢ 65536 ¤Ë¤Ê¤ê¤Þ¤¹¡£Pogo ¥ª¥Ö¥¸¥§¥¯¥È
     pogoobj ¤ò»ØÄê¤·¤¿¾ì¹ç¤Ï¡¢¤½¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë³ÊÇ¼¤µ¤ì¤Þ¤¹¡£¥¯¥é¥¹Ì¾
     class ¤ò»ØÄê¤·¤¿¾ì¹ç¤Ï¡¢¤½¤Î¥¯¥é¥¹Ì¾¤Ç bless ¤µ¤ì¤Þ¤¹¡£

$obj = Pogo::Btree->new [pogoobj]
     ¥¯¥é¥¹¥á¥½¥Ã¥É¡£Pogo::Btree ¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤Ã¤ÆÊÖ¤·¤Þ¤¹¡£Pogo ¥ª¥Ö¥¸
     ¥§¥¯¥È pogoobj ¤ò»ØÄê¤·¤¿¾ì¹ç¤Ï¡¢¤½¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë³ÊÇ¼¤µ¤ì¤Þ¤¹¡£

$hashref = Pogo::Btree->new_tie [pogoobj [,class]]
     ¥¯¥é¥¹¥á¥½¥Ã¥É¡£Pogo::Btree ¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤ê¡¢¥Ï¥Ã¥·¥å¤ò¤½¤ì¤Ë tie
     ¤·¡¢¤½¤Î¥Ï¥Ã¥·¥å¤Î»²¾È¤òÊÖ¤·¤Þ¤¹¡£Pogo ¥ª¥Ö¥¸¥§¥¯¥È pogoobj ¤ò»ØÄê¤·¤¿
     ¾ì¹ç¤Ï¡¢¤½¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë³ÊÇ¼¤µ¤ì¤Þ¤¹¡£¥¯¥é¥¹Ì¾ class ¤ò»ØÄê¤·¤¿¾ì¹ç
     ¤Ï¡¢¤½¤Î¥¯¥é¥¹Ì¾¤Ç bless ¤µ¤ì¤Þ¤¹¡£

$obj = Pogo::Ntree->new [pogoobj]
     ¥¯¥é¥¹¥á¥½¥Ã¥É¡£Pogo::Ntree ¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤Ã¤ÆÊÖ¤·¤Þ¤¹¡£Pogo ¥ª¥Ö¥¸
     ¥§¥¯¥È pogoobj ¤ò»ØÄê¤·¤¿¾ì¹ç¤Ï¡¢¤½¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë³ÊÇ¼¤µ¤ì¤Þ¤¹¡£

$hashref = Pogo::Ntree->new_tie [pogoobj [,class]]
     ¥¯¥é¥¹¥á¥½¥Ã¥É¡£Pogo::Ntree ¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤ê¡¢¥Ï¥Ã¥·¥å¤ò¤½¤ì¤Ë tie
     ¤·¡¢¤½¤Î¥Ï¥Ã¥·¥å¤Î»²¾È¤òÊÖ¤·¤Þ¤¹¡£Pogo ¥ª¥Ö¥¸¥§¥¯¥È pogoobj ¤ò»ØÄê¤·¤¿
     ¾ì¹ç¤Ï¡¢¤½¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë³ÊÇ¼¤µ¤ì¤Þ¤¹¡£¥¯¥é¥¹Ì¾ class ¤ò»ØÄê¤·¤¿¾ì¹ç
     ¤Ï¡¢¤½¤Î¥¯¥é¥¹Ì¾¤Ç bless ¤µ¤ì¤Þ¤¹¡£

     ¥Î¡¼¥È¡§¤³¤ì¤é¤Î Pogo::*::new ¤ä Pogo::*::new_tie ¥á¥½¥Ã¥É¤Çºî¤é¤ì¤¿¥ª
     ¥Ö¥¸¥§¥¯¥È¤Ï¡¢°ú¿ô¤Ç Pogo ¥ª¥Ö¥¸¥§¥¯¥È¤¬»ØÄê¤µ¤ì¤Ê¤¤¸Â¤ê¡¢¥á¥â¥ê¾å¤Ë¤¢
     ¤ê¡¢¤Þ¤À±ÊÂ³Åª¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡£´ûÂ¸¤Î±ÊÂ³¥Ç¡¼¥¿¤ËÂåÆþ¤µ¤ì¤¿»þ¤Ë»Ï¤á¤Æ¡¢
     ±ÊÂ³¥Ç¡¼¥¿¤Ë¤Ê¤ê¤Þ¤¹¡£¤Þ¤¿¡¢°ú¿ô¤Ë Pogo ¥ª¥Ö¥¸¥§¥¯¥È¤ò»ØÄê¤¹¤ë¤È¡¢¤½¤Î
     ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë³ÊÇ¼¤µ¤ì¤Þ¤¹¤¬¡¢¤ä¤Ï¤ê´ûÂ¸¤Î±ÊÂ³¥Ç¡¼¥¿¤Ë»²¾È¤µ¤ì¤Æ»Ï¤á¤Æ
     ¿¿¤Ë±ÊÂ³¥Ç¡¼¥¿¤Ë¤Ê¤ê¤Þ¤¹¡£

¥æ¡¼¥Æ¥£¥ê¥Æ¥£¡¼´Ø¿ô
--------------------

Pogo::type_of
     »ØÄê¤µ¤ì¤¿Pogo¥Ç¡¼¥¿¤Î»²¾È¥¿¥¤¥×¡¢¥¯¥é¥¹Ì¾¡¢tie¥¯¥é¥¹Ì¾¤òÊÖ¤·¤Þ¤¹¡£

          ($reftype, $class, $tiedclass) = Pogo::type_of($root->{key});

     Îã¤¨¤Ð¼¡¤Î¤è¤¦¤ÊÃÍ¤¬ÆÀ¤é¤ì¤Þ¤¹¡£

          () : »²¾È¤Ç¤Ê¤¤
          ('ARRAY', '', 'Pogo::Array') : ÇÛÎó
          ('HASH', '', 'Pogo::Btree') : B¥Ä¥ê¡¼¥Ï¥Ã¥·¥å
          ('HASH', 'Aclass', 'Pogo::Hash') : Aclass¥ª¥Ö¥¸¥§¥¯¥È

Pogo::tied_object
     »ØÄê¤µ¤ì¤¿Pogo¥Ç¡¼¥¿¤Î»²¾ÈÀè¤¬tie¤µ¤ì¤¿Pogo::*¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤·¤Þ¤¹¡£

Pogo::equal
     Æó¤Ä¤Î Pogo ¥Ç¡¼¥¿¤ò°ú¿ô¤Ë¤È¤Ã¤Æ¡¢¤½¤ì¤¬Æ±¤¸¥Ç¡¼¥¿¥Ù¡¼¥¹¥ª¥Ö¥¸¥§¥¯¥È¤ò
     »Ø¤¹¤Ê¤é1¡¢°ã¤¦¤Ê¤é0¤òÊÖ¤·¤Þ¤¹¡£

Pogo::object_id
     »ØÄê¤µ¤ì¤¿Pogo¥Ç¡¼¥¿¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¥ª¥Ö¥¸¥§¥¯¥ÈID¤òÊÖ¤·¤Þ¤¹¡£

Pogo::atomic_call
     »ØÄê¤µ¤ì¤¿´Ø¿ô¤ò¡ÖÉÔ²ÄÊ¬¡×¤Ë¼Â¹Ô¤·¡¢¤½¤Î·ë²Ì¤òÊÖ¤·¤Þ¤¹¡£

          $result = Pogo::atomic_call(\&func, $data, @args);

     \&func ¤Ï¥µ¥Ö¥ë¡¼¥Á¥ó»²¾È¡¢$data ¤Ï Pogo ¥Ç¡¼¥¿¤Ç¤¹¡£$data ¤Ï¼Â¹ÔÃæ¥í
     ¥Ã¥¯¤µ¤ì¤Þ¤¹¡£¥í¥Ã¥¯¤¬¤ª¤³¤Ê¤ï¤ì¤ëÅÀ¤ò½ü¤±¤Ð¡¢¼¡¤ÈÆ±¤¸¤Ç¤¹¡£

          $result = func($data, @args);

     func¤Ï¥¹¥«¥é¥³¥ó¥Æ¥­¥¹¥È¤Ç¸Æ¤Ð¤ì¡¢ÊÖ¤êÃÍ¤ÏÀ°¿ô¤ËÊÑ´¹¤µ¤ì¤Þ¤¹¡£

Pogo::wait_modification
     »ØÄê¤µ¤ì¤¿¥Ç¡¼¥¿¤¬Â¾¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¥¯¥é¥¤¥¢¥ó¥È¤Ë¤è¤Ã¤ÆÊÑ¹¹¤µ¤ì¤ë¤«¡¢¤¢
     ¤ë¤¤¤Ï»ØÄê¤µ¤ì¤¿ÉÃ¿ô·Ð¤Ä¤Þ¤ÇÂÔ¤Á¤Þ¤¹¡£¥Ç¡¼¥¿¤¬ÊÑ¹¹¤µ¤ì¤¿¾ì¹ç¤Ï1¡¢»þ´Ö
     ÀÚ¤ì¤Î¾ì¹ç¤Ï0¤òÊÖ¤·¤Þ¤¹¡£

          $result = Pogo::wait_modification($data, $sec);

     »þ´ÖÀÚ¤ì¤Þ¤Ç¤ÎÉÃ¿ô¤¬¾ÊÎ¬¤µ¤ì¤ë¤È¡¢±Ê±ó¤ËÂÔ¤Á¤Þ¤¹¡£

Äã¥ì¥Ù¥ë¥á¥½¥Ã¥É
----------------

   °Ê²¼¤Î¥á¥½¥Ã¥É¤Ïtie¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹ÆâÉô¤Ç»È¤ï¤ì¤Æ¤¤¤ë¤â¤Î¤Ç¤¹¡£

Pogo::Var
     Pogo::Var ¤Ï¡¢°Ê²¼¤Î Pogo::*¥¯¥é¥¹·²¤¹¤Ù¤Æ¤ÎÃê¾Ý´ðËÜ¥¯¥é¥¹¤Ç¤¹¡£Pogo::
     Var ¥ª¥Ö¥¸¥§¥¯¥È¤Ï»È¤¨¤Þ¤»¤ó¡£

          Pogo::Var::get_class
          Pogo::Var::set_class
          Pogo::Var::begin_transaction
          Pogo::Var::abort_transaction
          Pogo::Var::end_transaction
          Pogo::Var::call
          Pogo::Var::equal
          Pogo::Var::wait_modification
          Pogo::Var::object_id

Pogo::Scalar
          Pogo::Scalar::get
          Pogo::Scalar::set

Pogo::Array
          Pogo::Array::get
          Pogo::Array::set
          Pogo::Array::get_size
          Pogo::Array::set_size
          Pogo::Array::clear
          Pogo::Array::push
          Pogo::Array::pop
          Pogo::Array::insert
          Pogo::Array::remove

Pogo::Hash
          Pogo::Hash::get
          Pogo::Hash::set
          Pogo::Hash::exists
          Pogo::Hash::remove
          Pogo::Hash::clear
          Pogo::Hash::first_key
          Pogo::Hash::next_key

Pogo::Htree
          Pogo::Htree::get
          Pogo::Htree::set
          Pogo::Htree::exists
          Pogo::Htree::remove
          Pogo::Htree::clear
          Pogo::Htree::first_key
          Pogo::Htree::next_key

Pogo::Btree
          Pogo::Btree::get
          Pogo::Btree::set
          Pogo::Btree::exists
          Pogo::Btree::remove
          Pogo::Btree::clear
          Pogo::Btree::first_key
          Pogo::Btree::last_key
          Pogo::Btree::next_key
          Pogo::Btree::prev_key
          Pogo::Btree::find_key

AUTHOR
======

   ÃæÅç Ì÷ <sey@jkc.co.jp>

SEE ALSO
========

   GOODS¤Îreadme.htm

Bidirectional relationship class for objects in a Pogo database
***************************************************************

NAME
====

   PogoLink - Bidirectional relationship class for objects in a Pogo
database

SYNOPSIS
========

     use PogoLink;
     # Define relationships
     package Person;
     sub new {
         my($class, $pogo, $name) = @_;
         # Make a hash ref persistent by $pogo and blessed by $class
         my $self = new_tie Pogo::Hash 8, $pogo, $class;
         %$self = (
             NAME     => $name,
             FATHER   => new PogoLink::Scalar($self, 'Man',    'CHILDREN'),
             MOTHER   => new PogoLink::Scalar($self, 'Woman',  'CHILDREN'),
             FRIENDS  => new PogoLink::Btree ($self, 'Person', 'FRIENDS', 'NAME'),
         );
         $self;
     }
     package Man;
     @ISA = qw(Person);
     sub new {
         my($class, $pogo, $name) = @_;
         my $self = $class->SUPER::new($pogo, $name);
         $self->{CHILDREN} = new PogoLink::Array ($self, 'Person', 'FATHER');
         $self->{WIFE}     = new PogoLink::Scalar($self, 'Woman',  'HUS');
         $self;
     }
     package Woman;
     @ISA = qw(Person);
     sub new {
         my($class, $pogo, $name) = @_;
         my $self = $class->SUPER::new($pogo, $name);
         $self->{CHILDREN} = new PogoLink::Array ($self, 'Person', 'MOTHER');
         $self->{HUS}      = new PogoLink::Scalar($self, 'Man',    'WIFE');
         $self;
     }

     # Use relationships
     $Pogo = new Pogo 'sample.cfg';
     $Dad = new Man   $Pogo, 'Dad';
     $Mom = new Woman $Pogo, 'Mom';
     $Jr  = new Man   $Pogo, 'Jr';
     $Gal = new Woman $Pogo, 'Gal';
     # Marriage
     $Dad->{WIFE}->add($Mom);     # $Mom->{HUS} links to $Dad automatically
     # Birth
     $Dad->{CHILDREN}->add($Jr);  # $Jr->{FATHER} links to $Dad automatically
     $Mom->{CHILDREN}->add($Jr);  # $Jr->{MOTHER} links to $Mom automatically
     # Jr gets friend
     $Jr->{FRIENDS}->add($Gal);   # $Gal->{FRIENDS} links to $Jr automatically
     # Oops! Gal gets Dad
     $Gal->{HUS}->add($Dad);      # $Dad->{WIFE} links to $Gal automatically
                                  # $Mom->{HUS} unlinks to $Dad automatically

DESCRIPTION
===========

   PogoLink makes single-single or single-multi or multi-multi
bidirectional relationships between objects in a Pogo database. The
relationships are automatically maintained to link each other correctly.
You can choose one of Pogo::Array, Pogo::Hash, Pogo::Htree, Pogo::Btree
and Pogo::Ntree to make a multi end of link.

Classes
-------

PogoLink::Scalar
     This class makes a single end of link.

PogoLink::Array
     This class makes a multi end of link as an array. It uses Pogo::Array
     to have links.

PogoLink::Hash, PogoLink::Htree, PogoLink::Btree, PogoLink::Ntree
     These classes make a multi end of link as a hash. Each uses
     corresponding Pogo::* to have links.

Methods
-------

new PogoLink::* $selfobject, $linkclass, $invattr, $keyattr
     Constructor. Class method. $selfobject is a object in the database
     which possesses this link. It must be a object as a hash reference.
     $linkclass is a class name of linked object. If $linkclass defaults,
     any class object is allowed. $invattr is an attribute (i.e. hash key)
     name of the linked object which links inversely. $keyattr is only
     necessary for PogoLink::Hash, PogoLink::Htree, PogoLink::Btree,
     PogoLink::Ntree.  It specifies an attribute name of the linked object
     thats value is used as the key of this link hash.

     NOTE: You cannot use PogoLink::* constructors as follows in a class
     constructor.

          sub new {
              my($class) = @_;
              my $self = {};
              bless $self, $class;
              $self->{FOO} = new PogoLink::Scalar $self, 'Foo', 'BAR';
              $self;
          }

     Because the self-object which is passed to PogoLink::* constructors
     must be a object in the database. In the above sample, $self is on
     the memory yet.  The right way is as follows.

          sub new {
              my($class, $pogo) = @_;
              my $self = new_tie Pogo::Hash 8, $pogo, $class;
              $self->{FOO} = new PogoLink::Scalar $self, 'Foo', 'BAR';
              $self;
          }

     You can make a database-stored and blessed reference by using new_tie
     which takes a Pogo object and a class name as arguments.

get $idx_or_key
     Get the linked object. For PogoLink::Scalar, $idx_or_key is not
     necessary. For PogoLink::Array, $idx_or_key is an array index number.
     For other, $idx_or_key is a hash key string.

getlist
     Get the linked object list.

getkeylist
     Get the hash key list of linked objects. Only available for
     PogoLink::Hash, PogoLink::Htree, PogoLink::Btree, PogoLink::Ntree.

find $object
     Test the link if it links to $object.

clear
     Unlink to all objects in the link.

del $object
     Unlink to $object.

add $object
     Link to $object.

AUTHOR
======

   Sey Nakajima <sey@jkc.co.jp>

SEE ALSO
========

   Pogo(3).  sample/person.pl.

Ì¾¾Î
====

   PogoLink - Pogo¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Î¥ª¥Ö¥¸¥§¥¯¥È¤ÎÁÐÊý¸þ´Ø·¸¤ò¼Â¸½¤¹¤ë¥¯¥é¥¹

³µÍ×
====

     use PogoLink;
     # ´Ø·¸¤ÎÄêµÁ
     package Person;
     sub new {
         my($class, $pogo, $name) = @_;
         # Make a hash ref persistent by $pogo and blessed by $class
         my $self = new_tie Pogo::Hash 8, $pogo, $class;
         %$self = (
             NAME     => $name,
             FATHER   => new PogoLink::Scalar($self, 'Man',    'CHILDREN'),
             MOTHER   => new PogoLink::Scalar($self, 'Woman',  'CHILDREN'),
             FRIENDS  => new PogoLink::Btree ($self, 'Person', 'FRIENDS', 'NAME'),
         );
         $self;
     }
     package Man;
     @ISA = qw(Person);
     sub new {
         my($class, $pogo, $name) = @_;
         my $self = $class->SUPER::new($pogo, $name);
         $self->{CHILDREN} = new PogoLink::Array ($self, 'Person', 'FATHER');
         $self->{WIFE}     = new PogoLink::Scalar($self, 'Woman',  'HUS');
         $self;
     }
     package Woman;
     @ISA = qw(Person);
     sub new {
         my($class, $pogo, $name) = @_;
         my $self = $class->SUPER::new($pogo, $name);
         $self->{CHILDREN} = new PogoLink::Array ($self, 'Person', 'MOTHER');
         $self->{HUS}      = new PogoLink::Scalar($self, 'Man',    'WIFE');
         $self;
     }

     # ´Ø·¸¤Î»ÈÍÑ
     $Pogo = new Pogo 'sample.cfg';
     $Dad = new Man   $Pogo, 'Dad';
     $Mom = new Woman $Pogo, 'Mom';
     $Jr  = new Man   $Pogo, 'Jr';
     $Gal = new Woman $Pogo, 'Gal';
     # ·ëº§
     $Dad->{WIFE}->add($Mom);     # $Mom->{HUS} ¤Ï¼«Æ°Åª¤Ë $Dad ¤ò»Ø¤¹
     # ÃÂÀ¸
     $Dad->{CHILDREN}->add($Jr);  # $Jr->{FATHER} ¤Ï¼«Æ°Åª¤Ë $Dad ¤ò»Ø¤¹
     $Mom->{CHILDREN}->add($Jr);  # $Jr->{MOTHER} ¤Ï¼«Æ°Åª¤Ë $Mom ¤ò»Ø¤¹
     # Jr¤ËÍ§Ã£¤¬¤Ç¤­¤ë
     $Jr->{FRIENDS}->add($Gal);   # $Gal->{FRIENDS} ¤Ï¼«Æ°Åª¤Ë $Jr ¤ò»Ø¤¹
     # ¤ª¤Ã¤È¡¢Gal¤¬Dad¤ò¥²¥Ã¥È¤·¤Á¤ã¤Ã¤¿
     $Gal->{HUS}->add($Dad);      # $Dad->{WIFE} ¤Ï¼«Æ°Åª¤Ë $Gal ¤ò»Ø¤¹
                                  # $Mom->{HUS} ¤Ï¼«Æ°Åª¤Ë $Dad ¤ò»Ø¤µ¤Ê¤¯¤Ê¤ë

²òÀâ
====

   PogoLink ¤Ï¡¢°ìÂÐ°ì¡¢°ìÂÐÂ¿¡¢Â¿ÂÐÂ¿¤ÎÁÐÊý¸þ´Ø·¸¤ò¡¢Pogo ¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ
¤Î¥ª¥Ö¥¸¥§¥¯¥È´Ö¤Ëºî¤ê¤Þ¤¹¡£¤½¤Î´Ø·¸¤Ï¡¢¤ª¸ß¤¤¤òÀµ¤·¤¯»Ø¤¹¤è¤¦¤Ë¡¢¼«Æ°
Åª¤ËÊÝ¤¿¤ì¤Þ¤¹¡£´Ø·¸¤ÎÂ¿Ã¼¤òºî¤ë¤Î¤Ë¡¢Pogo::Array, Pogo::Hash, Pogo::
Htree, Pogo::Btree, Pogo::Ntree ¤Î¤É¤ì¤«¤òÁª¤Ù¤Þ¤¹¡£

¥¯¥é¥¹
------

PogoLink::Scalar
     °ìÂÐ°ì¤ä°ìÂÐÂ¿´Ø·¸¤Î°ìÃ¼¤òºî¤ê¤Þ¤¹¡£

PogoLink::Array
     °ìÂÐÂ¿¤äÂ¿ÂÐÂ¿´Ø·¸¤ÎÂ¿Ã¼¤ò¡¢ÇÛÎó¤È¤·¤Æºî¤ê¤Þ¤¹¡£Pogo::Array ¤¬»È¤ï¤ì¤Þ
     ¤¹¡£

PogoLink::Hash, PogoLink::Htree, PogoLink::Btree, PogoLink::Ntree
     ¤³¤ì¤é¤Î¥¯¥é¥¹¤Ï¡¢Â¿Ã¼¤ò¥Ï¥Ã¥·¥å¤È¤·¤Æºî¤ê¤Þ¤¹¡£¤½¤ì¤¾¤ìÂÐ±þ¤·¤¿ Pogo:
     :*¤¬»È¤ï¤ì¤Þ¤¹¡£

¥á¥½¥Ã¥É
--------

new PogoLink::* $selfobject, $linkclass, $invattr, $keyattr
     ¥³¥ó¥¹¥È¥é¥¯¥¿¡£¥¯¥é¥¹¥á¥½¥Ã¥É¡£$selfobject ¤Ï¤³¤Î´Ø·¸¤ò»ý¤Ä¥Ç¡¼¥¿¥Ù¡¼
     ¥¹Ãæ¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¹¡£¥Ï¥Ã¥·¥å»²¾È¤È¤·¤Æ¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê
     ¤Þ¤»¤ó¡£$linkclass ¤Ï¤³¤Î´Ø·¸¤¬»Ø¤¹Áê¼ê¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¯¥é¥¹Ì¾¤Ç¤¹¡£¾Ê
     Î¬¤¹¤ë¤È¡¢¤É¤ó¤Ê¥¯¥é¥¹¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤âµö¤µ¤ì¤Þ¤¹¡£$invattr ¤Ï¤³¤Î´Ø
     ·¸¤ÎÁê¼ê¥ª¥Ö¥¸¥§¥¯¥È¤ÎÂ°À­Ì¾¡Ê¥Ï¥Ã¥·¥å¥­¡¼¡Ë¤Ç¡¢¤½¤ÎÂ°À­¤¬µÕ¤ËÁê¼ê¤«¤é
     ¤³¤Á¤é¤ò»Ø¤¹¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡£$keyattr ¤Ï¡¢PogoLink::Hash, PogoLink::
     Htree, PogoLink::Btree, PogoLink::Ntree ¤Ë¤Ä¤¤¤Æ¤À¤±É¬Í×¤Ç¡¢¤³¤Î´Ø·¸¤Î
     Áê¼ê¥ª¥Ö¥¸¥§¥¯¥È¤ÎÂ°À­Ì¾¡Ê¥Ï¥Ã¥·¥å¥­¡¼¡Ë¤Ç¡¢¤½¤ÎÂ°À­ÃÍ¤¬¥Ï¥Ã¥·¥å¥­¡¼¤È
     ¤·¤Æ»È¤ï¤ì¤Þ¤¹¡£

     Ãí°Õ¡§PogoLink::*¥³¥ó¥¹¥È¥é¥¯¥¿¤ò¡¢¥¯¥é¥¹¤Î¥³¥ó¥¹¥È¥é¥¯¥¿¤ÎÃæ¤Ç¼¡¤Î¤è
     ¤¦¤Ë»È¤¦¤³¤È¤Ï¤Ç¤­¤Þ¤»¤ó¡£

          sub new {
              my($class) = @_;
              my $self = {};
              bless $self, $class;
              $self->{FOO} = new PogoLink::Scalar $self, 'Foo', 'BAR';
              $self;
          }

     ¤Ê¤¼¤Ê¤é¡¢PogoLink::*¥³¥ó¥¹¥È¥é¥¯¥¿¤Î°ú¿ô¤È¤Ê¤ë¤½¤Î¥ª¥Ö¥¸¥§¥¯¥È¼«¿È¤Ï¡¢
     ¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¤«¤é¤Ç¤¹¡£¤³¤ÎÎã¤Ç¤Ï¡¢
     $self ¤Ï¤Þ¤À¥á¥â¥ê¾å¤Ë¤¢¤ë¤À¤±¤Ç¤¹¡£Àµ¤·¤¯¤Ï¼¡¤Î¤è¤¦¤Ë¤·¤Þ¤¹¡£

          sub new {
              my($class, $pogo) = @_;
              my $self = new_tie Pogo::Hash 8, $pogo, $class;
              $self->{FOO} = new PogoLink::Scalar $self, 'Foo', 'BAR';
              $self;
          }

     Pogo ¥ª¥Ö¥¸¥§¥¯¥È¤È¥¯¥é¥¹Ì¾¤ò°ú¿ô¤È¤·¤¿ new_tie ¤ò»È¤¨¤Ð¡¢¥Ç¡¼¥¿¥Ù¡¼¥¹
     ¤Ë³ÊÇ¼¤µ¤ì¡¢bless ¤µ¤ì¤¿»²¾È¤¬ÆÀ¤é¤ì¤ë¤Î¤Ç¤¹¡£

get $idx_or_key
     ´Ø·¸¤ÎÁê¼ê¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤·¤Þ¤¹¡£PogoLink::Scalar ¤Ç¤Ï $idx_or_key ¤Ï
     ÉÔÍ×¤Ç¤¹¡£PogoLink::Array ¤Ç¤Ï¡¢$idx_or_key ¤ÏÇÛÎó¤ÎÅº»úÈÖ¹æ¤Ç¤¹¡£¤½¤Î
     Â¾¤Î¾ì¹ç¤Ï¡¢$idx_or_key ¤Ï¥Ï¥Ã¥·¥å¥­¡¼¤Ç¤¹¡£

getlist
     ´Ø·¸¤ÎÁê¼ê¥ª¥Ö¥¸¥§¥¯¥È¤Î¥ê¥¹¥È¤òÊÖ¤·¤Þ¤¹¡£

getkeylist
     ´Ø·¸¤ÎÁê¼ê¤Î¥ê¥¹¥È¤ò¡¢¥Ï¥Ã¥·¥å¤Î¥­¡¼¤Î¥ê¥¹¥È¤È¤·¤ÆÊÖ¤·¤Þ¤¹¡£PogoLink::
     Hash, PogoLink::Htree, PogoLink::Btree, PogoLink::Ntree ¤Ë¤Ä¤¤¤Æ¤À¤±Í­
     ¸ú¤Ê¥á¥½¥Ã¥É¤Ç¤¹¡£

find $object
     ´Ø·¸¤ÎÁê¼ê¤Ë$object¤¬¤¢¤ë¤«Ä´¤Ù¤Þ¤¹¡£¤¢¤ì¤Ð¿¿¤òÊÖ¤·¤Þ¤¹¡£

clear
     ´Ø·¸¤ÎÁ´¤Æ¤ÎÁê¼ê¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î´Ø·¸¤òÃÇ¤Á¤Þ¤¹¡£

del $object
     $object¤Ø¤Î´Ø·¸¤òÃÇ¤Á¤Þ¤¹¡£

add $object
     $object¤Ø¤Î´Ø·¸¤òÄÉ²Ã¤·¤Þ¤¹¡£

ºî¼Ô
====

   ÃæÅç¡¡Ì÷ <sey@jkc.co.jp>

»²¾È
====

   Pogo(3).  sample/person.pl.

Squeeze a text file into multiple columns.
******************************************

NAME
====

   PostScript::Columns - Squeeze a text file into multiple columns.

SYNOPSIS
========

     use PostScript::ColDoc;

     $psdoc= pscolumns(
       -margins => [30,15], # NS,EW or N,E,W,S
       -headfont => 'NimbusMonL-Bold',
       -headsize => 12,
       -head => $head,
       -font => 'NimbusMonL-Regu',
       -size => 10,
       -text => $text,
         # default font/size for foot:
       -foot => "Page \$p of \$pp", # will interpolate later :)
     );

     # use all defaults, no footer
     $doc= pscolumns(
       -size => 5,
       -head => "Left\nLeft Also\tTest Document\tRight",
       -text => $text,
       -foot => scalar(localtime)."\tFoot\tPage \$p of \$pp",
     );

DESCRIPTION
===========

   Creates a PostScript document with a user-defined header and footer,
then attempts to squeeze the data into as many columns as possible.

AVAILABLE FONTS
===============

   Only the monospace PostScript fonts are available:

`NimbusMonL-Regu'
`NimbusMonL-Bold'
`NimbusMonL-ReguObli'
`NimbusMonL-BoldObli'
OPTIONS
=======

-margins
     Array ref that specifies page margins, in points (1/72 of an inch).
     North, East, West South are expressed as four elements: [ N, E, S, W
     ] or two elements [ N_S, E_W ].  (This is the same order that CSS
     uses.)

     Note: Different printers may require drastically different margins.
     You'll have to experiment each time you use this module with a new
     printer.

-headfont
     Name of the font to use for the header (see `"AVAILABLE FONTS"' in
     this node).

-headsize
     Size of the font to use for the header (in points).

-head
     String to use as header.  Upper-right, centered, and upper-left
     fields are tab-separated.  In the string, $p will be replaced by the
     current page number, and `$pp' with the total number of pages.

-font
     Name of the font to use for the text (see `"AVAILABLE FONTS"' in this
     node).

-size
     Size of the font to use for the text (in points).

-text
     Columnar text.

-footfont
     Name of the font to use for the footer (see `"AVAILABLE FONTS"' in
     this node).

-footsize
     Size of the font to use for the footer (in points).

-foot
     String to use as footer.  Lower-right, centered, and lower-left
     fields are tab-separated.  In the string, $p will be replaced by the
     current page number, and `$pp' with the total number of pages.

AUTHOR
======

   v, <five@rant.scriptmania.com>

SEE ALSO
========

   perl(1).

Generate PostScript code for circles, boxes, lines
**************************************************

NAME
====

   PostScript::Elements - Generate PostScript code for circles, boxes,
lines

DESCRIPTION
===========

   An object for representing lines, circles, boxes, and images such that
they can be easily output as PostScript code.

SYNOPSIS
========

AUTHOR
======

module to fetch data from PostScript fonts
******************************************

NAME
====

   PostScript::Font - module to fetch data from PostScript fonts

SYNOPSIS
========

     my $info = new PostScript::Font (filename, options);
     print STDOUT ("Name = ", $info->FontName, "\n");

DESCRIPTION
===========

   This package reads PostScript font files and stores the information in
memory.

   Most font file formats that are in use are recognised, especially the
Type 1 and Type 42 font formats. Other formats that usually parse okay are
Type 5 and Type 3, although Type 3 can sometimes fail depending on how
weird the font information is stored.

   The input font file can be encoded in ASCII (so-called `.pfa' format),
or binary (so-called `.pfb' format).

   True Type fonts are understood as well, they are converted internally
to Type 42 format. Currently this requires an external program,
*ttftot42*. This program will be used automatically if it can be located
in the execution PATH. Alternatively, you can set the variable
`$PostScript::Font::ttftot42' (or `$PostScript::FontMetrics::ttftot42') to
the name of the actual program. See also `EXTERNAL PROGRAMS' in this node.

CONSTRUCTOR
===========

new ( FILENAME [ , OPTIONS ] )
     The constructor will read the file and parse its contents.

OPTIONS
=======

error => [ 'die' | 'warn' | 'ignore' ]
     How errors must be handled. Default is to call die().  In any case,
     new() returns a undefined result.

format => [ 'ascii' | 'pfa' | 'binary' | 'pfb' ]
     The format in which the font data is stored.  Default is `'ascii'',
     suitable to be downloaded to a PostScript printer.

verbose => value
     Prints verbose info if value is true.

trace => value
     Prints tracing info if value is true.

debug => value
     Prints debugging info if value is true.  Implies 'trace' and
     'verbose'.

INSTANCE METHODS
================

   Each of these methods can return undef if the corresponding information
could not be found in the file.

FileName
     The name of the file, e.g. 'tir_____.pfb'.

FontName
     The name of the font, e.g. 'Times-Roman'.

FamilyName
     The family name of the font, e.g. 'Times'.

Version
     The version of the font, e.g. '001.007'.

ItalicAngle
     The italicity of the font, e.g. 0 (normal upright fonts) or -16
     (italic font).

isFixedPitch
     Indicates if this font has fixed pitch.

Weight
     This font weight.

FontType
     The font type, e.g. '1' for a Type 1 PostScript font, or 't' for a
     True Type font.

     True Type fonts will be converted to Type 42 internally, but still
     have 't' as FontType.

FontMatrix
     The font matrix as a reference to an anonymous array with the 6
     values.  To find the font scale, use

          int(1/$font->FontMatrix->[0])

FontBBox
     The font bounding box as a reference to an anonymous array with the 4
     values.

DataFormat
     The format in which the data is kept internally. See the format
     option.

FontData
     The complete contents of the file, normalised to Unix-style line
     endings.  It is in the format as returned by the DataFormat method.

Encoding
     This is either one of the strings `'StandardEncoding'' or
     `'ISOLatin1Encoding'', or a reference to an array that holds the
     encoding. In this case, the array will contain a glyph name (a string)
     for each element that is encoded.

     NOTE: Getting the encoding information can fail if the way it was
     stored in the font is not recognized by the parser. This is most
     likely to happen with manually constructed fonts.

EncodingVector
     Like encoding, but always returns a reference to the encoding array.
     In other words, the standard encodings are returned as arrays as well.

FontGlyphs
     This returns a reference to an array holding all the names of the
     glyphs this font defines, in the order the definitions occur in the
     font data.

     NOTE: Getting the glyphs information can fail if the way it was
     stored in the font is not recognized by the parser. This is most
     likely to happen with manually constructed fonts.

     Extracting the glyphs can be slow. It can be speeded up by using the
     external program *t1disasm*. This program will be used automatically,
     if it can be found in the execution PATH. Alternatively, you can set
     the variable `$PostScript::Font::t1disasm' to point to the *t1disasm*
     program. This does not apply to type 42 fonts, since these fonts do
     not require disassembly to get at the glyph list.

CLASS METHODS
=============

StandardEncoding
     Returns a reference to an array that contains all the glyphs names for
     Adobe's Standard Encoding.

ISOLatin1Encoding
     Returns a reference to an array that contains all the glyphs names for
     ISO-8859-1 (ISO Latin-1) encoding.

EXTERNAL PROGRAMS
=================

   Two external programs can be used by this package.

   *ttftot42* is required when True Type fonts must be handled. It is
called as follows:

     ttftot42 -fc filename

   This invocation will write the Type 42 version of the True Type font to
standard output.

   *ttftot42* can be found on http://ftp.giga.or.at/pub/nih/ttftot42

   An alternative, but not encouraged, way to handle True Type fonts is by
converting them to Type 1 fonts. An excellent converter, *ttf2pt1*, can be
used for this. To use this program, create a fake *ttftot42* script and
set variable $PostScript::Font::ttftot42 to the name of this script. The
script should contain something like this:

     $!/bin/sh
     shift	# get rid of '-fc' argument
     exec ttf2pt1 -ef "$@" - 2>/dev/null

   The redirection of error output to /dev/null is necessary. since the
program is quite verbose. Unfortunately, error messages will disappear as
well.

   *ttf2pt1* can be found on http://www.netspace.net.au/~mark/ttf2pt1

   Note: the resultant Type1 font is not a real conversion, but a (very
similar) imitation of the original True Type font. Small differences may
be noticable depending on the font quality.

   *t1disasm* can be used to speed up the fetching of the list of font
glyphs from Type 1 fonts. It is called as follows:

     t1disasm filename

   This invocation will write the disassembled version of the Type 1 font
to standard output. *t1disasm* is part of the *t1utils* package that can
be found at http://www.lcdf.org/~eddietwo/type/ and several other places.

KNOWN BUGS
==========

   Invoking external programs (*t1disasm*, *ttftot42*) is guaranteed to
work on Unix only.

SEE ALSO
========

http://www.adobe.com/supportservice/devrelations/PDFS/TN/T1_SPEC.PDF
     The specification of the Type 1 font format.

http://www.adobe.com/supportservice/devrelations/PDFS/TN/5012.Type42_Spec.pdf
     The specification of the Type 42 font format.

http://fonts.apple.com/TTRefMan/index.html
     The True Type reference manual.

http://www.adobe.com/supportservice/devrelations/PDFS/TN/5004.AFM_Spec.pdf
     The specification of the Adobe font metrics file format.

AUTHOR
======

   Johan Vromans, Squirrel Consultancy <jvromans@squirrel.nl>

COPYRIGHT and DISCLAIMER
========================

   This program is Copyright 2000,1998 by Squirrel Consultancy. All rights
reserved.

   This program is free software; you can redistribute it and/or modify it
under the terms of either: a) the GNU General Public License as published
by the Free Software Foundation; either version 1, or (at your option) any
later version, or b) the "Artistic License" which comes with Perl.

   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 either the GNU General Public
License or the Artistic License for more details.

module to fetch data from PostScript font `.inf' files
******************************************************

NAME
====

   PostScript::FontInfo - module to fetch data from PostScript font `.inf'
files

SYNOPSIS
========

     my $info = new PostScript::FontInfo (filename, options);
     print STDOUT ("Name = ", $info->name, "\n");

DESCRIPTION
===========

   This package allows font info files, so called `.inf' files, to be read
and (partly) parsed.

CONSTRUCTOR
===========

new ( FILENAME [ , OPTIONS ] )
     The constructor will read the file and parse its contents.

OPTIONS
=======

error => [ 'die' | 'warn' | 'ignore' ]
     How errors must be handled. Default is to call die().  In any case,
     new() returns a undefined result.

verbose => value
     Prints verbose info if value is true.

trace => value
     Prints tracing info if value is true.

debug => value
     Prints debugging info if value is true.  Implies 'trace' and
     'verbose'.

INSTANCE METHODS
================

   Each of these methods can return undef if the corresponding information
could not be found in the file.

FileName
     The name of the file, e.g. 'tir_____.afm'.

FontName
     The name of the font, e.g. 'Times-Roman'.

FamilyName
     The family name of the font, e.g. 'Times'.

Version
     The version of the font, e.g. '001.007'.

PCFileNamePrefix
     The prefix used to form MS-DOS compliant file names, e.g. 'tir__'.

InfoData
     The complete contents of the file, normalised to Unix-style line
     endings.

AUTHOR
======

   Johan Vromans, Squirrel Consultancy <jvromans@squirrel.nl>

COPYRIGHT and DISCLAIMER
========================

   This program is Copyright 2000,1998 by Squirrel Consultancy. All rights
reserved.

   This program is free software; you can redistribute it and/or modify it
under the terms of either: a) the GNU General Public License as published
by the Free Software Foundation; either version 1, or (at your option) any
later version, or b) the "Artistic License" which comes with Perl.

   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 either the GNU General Public
License or the Artistic License for more details.

module to fetch data from Adobe Font Metrics file
*************************************************

NAME
====

   PostScript::FontMetrics - module to fetch data from Adobe Font Metrics
file

SYNOPSIS
========

     my $info = new PostScript::FontMetrics (filename, options);
     print STDOUT ("Name = ", $info->FontName, "\n");
     print STDOUT ("Width of LAV = ", $info->kstringwidth("LAV", 10), "\n");

DESCRIPTION
===========

   This package allows Adobe standard font metric files, so called `.afm'
files, to be read and (partly) parsed.

   True Type fonts are understood as well, their metrics are extracted.
Currently this requires an external program, *ttftot42*. This program will
be used automatically if it can be located in the execution PATH.
Alternatively, you can set the variable
`$PostScript::FontMetrics::ttftot42' (or `$PostScript::Font::ttftot42') to
the name of the actual program. See also `EXTERNAL PROGRAMS' in this node.

CONSTRUCTOR
===========

new ( FILENAME [ , OPTIONS ])
     The constructor will read the file and parse its contents.

OPTIONS
=======

error => [ 'die' | 'warn' | 'ignore' ]
     How errors must be handled. Default is to call die().  In any case,
     new() returns a undefined result.

verbose => value
     Prints verbose info if value is true.

trace => value
     Prints tracing info if value is true.

debug => value
     Prints debugging info if value is true.  Implies 'trace' and
     'verbose'.

INSTANCE METHODS
================

   Note: Most of the info from the AFM file can be obtained by calling a
method of the same name, e.g. FontName and `IsFixedPitch'.

   Each of these methods can return undef if the corresponding information
could not be found in the file.

FileName
     The name of the file, e.g. 'tir_____.afm'.  This is not derived from
     the metrics data, but the name of the file as passed to the new
     method.

MetricsData
     The complete contents of the file, normalised to Unix-style line
     endings.

CharWidthData
     Returns a reference to a hash with the character widths for each
     glyph.

EncodingVector
     Returns a reference to an array with the glyph names for each encoded
     character.

CharBBoxData
     Returns a reference to a hash with the bounding boxes (a 4-element
     array) for each glyph.

KernData
     Returns a reference to a hash with the kerning data for glyph pairs.
     It is indexed by two glyph names (two strings separated by a comma,
     e.g. $kd->{"A","B"}).

stringwidth ( string [ , pointsize ] )
     Returns the width of the string, in character space units.

     Deprecated: When a pointsize argument is supplied, the resultant width
     is scaled to user space units. This assumes that the font maps 1000
     character space units to one user space unit (which is generally the
     case).

kstringwidth ( string [ , pointsize ] )
     Returns the width of the string in character space units, taking
     kerning information into account.

     Deprecated: When a pointsize argument is supplied, the resultant width
     is scaled to user space units. This assumes that the font maps 1000
     character space units to one user space unit (which is generally the
     case).

kstring ( string [ , extent ] )
     Returns an array reference (in scalar context) or an array (in array
     context) with substrings of the given string, interspersed with
     kerning info. The kerning info is the amount of movement needed for
     the correct kerning, in character space (which is usually 1000 times a
     PostScript point). The substrings are ready for printing: non-ASCII
     characters have been encoded and parentheses are put around them.

     If the extend argument is supplied, this amount of displacement is
     added to each space in the string.

     For example, for a given font, the following call:

          $typesetinfo = $metrics->kstring ("ILVATAB");

     could return in $typesetinfo:

          [ "(IL)", -97, "(V)", -121, "(A)", -92, "(T)", -80, "(AB)" ]

     There are several straightforward ways to process this.

     By translating to a series of 'show' and 'rmoveto' operations:

          foreach ( @$typesetinfo ) {
          	if ( /^\(/ ) {
          	    print STDOUT ($_, " show\n");
          	}
          	else {
          	    printf STDOUT ("%.3f 0 rmoveto\n", ($_*$fontsize)/$fontscale);
          	}
          }

     Or, assuming the following definition in the PostScript preamble (48
     is the font size):

          /Fpt 48 1000 div def
          /TJ {{ dup type /stringtype eq
            { show }
            { Fpt mul 0 rmoveto }
            ifelse } forall } bind def

     the following Perl code would suffice:

          print PS ("[ @$typesetinfo ] TJ\n");

EXTERNAL PROGRAMS
=================

   *ttftot42* is required when True Type fonts must be handled. It is
called as follows:

     ttftot42 -ac filename

   This invocation will write the metrics for the True Type font to
standard output.

   *ttftot42* can be found on http://ftp.giga.or.at/pub/nih/ttftot42

SEE ALSO
========

http://www.adobe.com/supportservice/devrelations/PDFS/TN/5004.AFM_Spec.pdf
     The specification of the Adobe font metrics file format.

AUTHOR
======

   Johan Vromans, Squirrel Consultancy <jvromans@squirrel.nl>

COPYRIGHT and DISCLAIMER
========================

   This program is Copyright 2000,1998 by Squirrel Consultancy. All rights
reserved.

   This program is free software; you can redistribute it and/or modify it
under the terms of either: a) the GNU General Public License as published
by the Free Software Foundation; either version 1, or (at your option) any
later version, or b) the "Artistic License" which comes with Perl.

   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 either the GNU General Public
License or the Artistic License for more details.

Modules for creating PostScript(tm) files of mailing address labels.
********************************************************************

NAME
====

   PostScript::MailLabels - Modules for creating PostScript(tm) files of
mailing address labels.

SYNOPSIS
========

   Modules for creating PostScript(tm) files of mailing address labels, to
be printed on standard adhesive-backed mailing label stock.  Flexible
enough to tackle other printing tasks, basically anything requiring a set
fields be printed on a regular grid.  Also creates PostScript(tm) code for
calibrating and testing mailing label printing.

DESCRIPTION
===========

   The module has three distinct output modes. In my experience, printing
mailing labels is a matter of tweaking parameters to get them all to fit
properly on the page. This module is designed with this in mind.

   The first output is the calibration sheet. This is a pair of annotated
axes, either in inches or centimeters, centered on the page and covering
the whole page in X and Y directions. The intent is for you to output this
page first, and simply read off the relevant page dimensions directly.

   The second output is the label test. This output is a series of boxes
drawn on the page, meant to outline the edges of all the mailing labels.
Take this sheet and line it up with a sheet of labels to see if they
actually match perfectly. If not, tweak the parameters until they do. Note
that sometimes you will get a message at the bottom of the sheet saying
"Bottom gap too large, last row cannot be printed". This means that the
printable area of your printer is too small to utilize the last row of
labels. I have this problem. But I handle it for you. Note also the arrows
on the test sheet. As you hold the test sheet over a sheet of labels, hold
it up to the light and slide the test sheet so that the boxes match the
edges of the labels. If you slide in the arrow direction, that is a
positive adjustment. The other direction is negative. If the edges of some
boxes come out dashed, that means that the non-printing border cuts off
the end of the label, so I will adjust the printing area appropriately.
Don't try to line up the dashed lines with label edges - it won't work.
Just line up the solid lines.

   The third output is the labels themselves. By default, I have set up a
US-centric address definition :

     firstname, lastname, street address, city, state, zipcode

   But with version 2.0, you can now create your own definition. You can
define new fields, and you can define how those fields land on a label.
You can also control the fonts on a per-field basis. Not the size, yet -
later pilgrim.

   Parameters you can set :

   Paper size, borders on the printable area (many printers will not print
right up to the edge of the paper), where the labels live on the page and
how big they are, overall x-y shift of page, whether or not to print
PostNET barcode, font, fontsize, units (english or metric), which
Avery(tm) product code to use, and where the first label starts.

   This last needs explanation. If you have a partially used sheet of
labels, you might want to use it up. So you count the missing labels,
starting at the upper left, and counting across, and then down. For
example, if I have 3 columns of labels, label five is the second label in
the second row.

   The Avery(tm) label codes are woefully incomplete. I can't find the
Avery(tm) specs anywhere, so the ones that are in there are for products I
personally own.  I e-mailed Avery(tm) and they gave me a long distance
phone number to call.

   If you have an Avery(tm) product that I haven't defined, send me the
specs and I'll add it.

   Also, if there is another brand of labels that you use, send me the
relevant data and I'll add that as well. I suspect that there must be some
other vendor in Europe, but I don't know who that would be.

   When setting up the addresses, I check to see if they will fit on the
label.  If not, I try to shorten them semi-intelligently until they fit.
This part could use quite a bit more work, if done right it probably
merits a module all it's own.

   Briefly, for the name line, I start trimming the ends off the first
name, and leave the last name alone.

   For the street, I look for things like Road or Avenue and nuke those
first, then I trim the street name from the right.

   For the last line, I trim the city and leave the state and zip alone.

   The barcode will be either a 5-digit zip or 9 digit zip-plus code. I
could also create the delivery point code, but since my mailing labels are
not even wide enough for the 9 digit zip-plus, I haven't bothered. I have
read the USPS spec on the barcode, and so far as I can tell, I meet the
spec.

   labelsetup :

   All the distances are in units of inches or centimeters, depending on
the Units flag.  A hash of the label definition will be returned.

   my $setup = $labels -> labelsetup(

     #    paper size

     PaperSize        => 'Letter',
     options are :
                 Letter Legal Ledger Tabloid A0 A1 A2 A3 A4 A5 A6 A7 A8
                 A9 B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 Envelope10 EnvelopeC5
                 EnvelopeDL Folio Executive

     #   printable area on physical page - these numbers represent border widths
     #    typical values might be 0.25 inches

     Printable_Left   => 0.0,
     Printable_Right  => 0.0,
     Printable_Top    => 0.0,
     Printable_Bot    => 0.0,

     #    define where the labels live (ideally)

     Output_Top     => 1.0, where does the top of the first label sit?
     Output_Left    => 0.5, where is the left edge of the first label?
     Output_Width   => 3.0, how wide are the labels?
     Output_Height  => 2.0, how tall are the labels?
     X_Gap          => 0.1, what is the vertical gap between labels?
     Y_Gap          => 0.0, what is the horizontal gap between labels?
     Number         => 30,  how many labels per page?
     Columns        => 3,   how many columns per page? (optional)

     if the number of columns are given, I'll check your math to see if the page
     width approximately equals the sum of the label widths plus gaps etc.

     #    Adjustments for printer idiosyncracies

     X_Adjust       => 0.0, shift the whole thing over by this amount.
     Y_Adjust       => 0.0  shift the whole thing down by this amount.

     #    Other controls

     Postnet    => 'yes',  barcodes? yes or no
     Font       => 'Helvetica', which default font? see below for generating a list
     FontSize   => 12, how big are they?
     Units      => 'english', english or metric
     FirstLabel => 1, where is the first label (begins at 1).

     # set equal to the Avery(tm) product code, and the label description
     # will be updated from the database.
     Avery        => undef,
     );

     generate a PostScript(tm) file with rulers on it for making measurements
         $output = $labels->labelcalibration ;
     generate a PostScript(tm) file with boxes showing where the text will land
         $output = $labels->labeltest ;
     the main event - make me a label file
         $output = $labels->makelabels(\@addrs) ;

     translate an Avery(tm) product code into a template code.
         $templatecode = $labels->averycode($product_code) ;
     retrieve an array of the paper width, height (in points)
         @width_height = @{ $labels->papersize } ;
     get the length of a string in points using the current font
         $stringwidth = $labels->stringwidth("This is a string") ;
     get a list of the available fonts
         @fontname = $labels->ListFonts;

     Components:

     Each component has a name, and four attributes. The attributes are :
         type : must be name, road, place, or bar. This defines the trimming
                strategy.
         adj : yes or no. Is trimming allowed?
         font : what font to use
         index : which entry in the input array will contain this component?

     Default components :
         #    first name
         fname    => { type => 'name', adj => 'yes', font => 'Helvetica', 'index' => 0 },
         #    last name
         lname    => { type => 'name', adj => 'yes', font => 'Helvetica', 'index' => 1 },
         #    street address and street
         street    => { type => 'road', adj => 'yes', font => 'Helvetica', 'index' => 2 },
         #    city
         city    => { type => 'place', adj => 'yes', font => 'Helvetica', 'index' => 3 },
         #    state
         state    => { type => 'place', adj => 'no', font => 'Helvetica', 'index' => 4 },
         #    country
         country    => { type => 'place', adj => 'no', font => 'Helvetica', 'index' => 6 },
         #    zip
         zip    => { type => 'place', adj => 'no', font => 'Helvetica', 'index' => 5 },
         #    postnet (bar code)
         postnet    => { type => 'bar', adj => 'no', font => 'PostNetJHC', 'index' => 5 },

     Editing components : with editcomponent

     #    What address components are available?
     print "components : ",join(' : ',@{$labels->editcomponent()}),"\n";

     #    Lets make the lname (lastname) bold-faced
     $labels->editcomponent('lname', 'name', 'no', 1, 'Times-Bold' );

     #    Lets create a new component
     $labels->editcomponent('company_name', 'name', 'yes', 7, 'Times-Bold');

     Label definition

     We define the label layout line by line, by describing for each line which
     components we want printed, and in what order.

     #    Default label definition
         #    line 1
         [ 'fname', 'lname' ],
         #    line 2
         [ 'street', ],
         #    line 3
         [ 'city', 'state', 'zip' ],
         #    line 4
         [ 'postnet', ],

     edit the label definition with definelabel :

     definelabel(line number, component, component, ...)

     #    first clear the old (default) definition
     $labels->definelabel('clear');
     #                   line number, component list
     $labels->definelabel(0,'pgm_name','version');
     $labels->definelabel(1,'blank',);
     $labels->definelabel(2,'author',);
     $labels->definelabel(3,'blank',);
     $labels->definelabel(4,'comments-1',);
     $labels->definelabel(5,'comments-2',);
     $labels->definelabel(6,'comments-3',);

EXAMPLE
=======

     #!/usr/bin/perl -w

     #        This shows the capabilities of the program...

     use PostScript::MailLabels 2.0;

     $labels = PostScript::MailLabels->new;

     #####################################################################`
     #    Dumping information from the modules
     #####################################################################`

     #    What address components are available?
     print "\n****** components ******\n";
     print join(' : ',@{$labels->editcomponent()}),"\n";

     #    What is the current label layout?
     print "\n****** layout ******\n";
     my @layout = @{$labels->definelabel()};
     foreach (@layout) {
         print join(' : ',@{$_}),"\n";
     }

     #    Here is how to list the available fonts
     print "\n****** fonts ******\n";
     @fonts = $labels->ListFonts;
     foreach (@fonts) {
         print "$_\n";
     }

     #    Here is how to list the available papers
     print "\n****** papers ******\n";
     print join(' : ',@{$labels->papers}),"\n";

     #    Here is how to list all th Avery data
      # layout=>[paper-size,[list of product codes], description,
      #          number per sheet, left-offset, top-offset, width, height]
      #            distances measured in points

     my %avery = %{$labels->averydata};
     print "\n****** Avery(tm) data ******\n";
     foreach (keys %avery) {
         print "$_ : $avery{$_}->[0] : ",
                join(', ',@{$avery{$_}->[1]})," : ",
                join(' : ',@{$avery{$_}}[2-7]),"\n";
     }

     #    Here are some more utilities

     print "\nString width of 'this is a test' = ",
             $labels->stringwidth("this is a test",)/72," inches\n";

     my $setup = $labels -> labelsetup( Font => 'PostNetJHC');

     print "\nzip code tests, 6,9, and 12 digit lengths barcodes:  ",
             $labels->stringwidth("123456",)/72," : ",
             $labels->stringwidth("123456789",)/72," : ",
             $labels->stringwidth("123456789012",)/72,
             " inches\n";

     print "\nPaper size Letter = ",($labels->papersize)->[0]," x ",
                                  ($labels->papersize)->[1]," in points\n";

     print "\nAvery(t) code for 8460 is >",$labels->averycode(8460),"<\n";

     #    Simple setup using predefined Avery label
     $labels -> labelsetup(
                 Avery       => $labels->averycode(8460),
                 PaperSize   => 'letter',
                 Font        => 'Times-Roman',
                 );

     print "\n                 num, left, top, width, height\n";
     print "label description : ", $setup->{number}, " : ",
                                   $setup->{output_left}, " : ",
                                   $setup->{output_top}, " : ",
                                   $setup->{output_width}, " : ",
                                   $setup->{output_height}, "\n";

     #    More hands-on setup defining everything. Note that Columns is optional
     $labels->labelsetup(
                         Units           => 'English',
                         PaperSize       => 'A4',

     Printable_Left  => 0.25,
     Printable_Right => 0.25,
     Printable_Top   => 0.0,
     Printable_Bot   => 0.55,

     Output_Top      => 0.5,
     Output_Left     => 0.0,
     Output_Width    => 2.625,
     Output_Height   => 1.0,
     X_Gap           => 0.16,
     Y_Gap           => 0.0,
     Number          => 30,
     Columns         => 3,

     #    Adjustments for printer idiosyncracies

     X_Adjust   => 0.05,
     Y_Adjust   => 0.05,

     PostNet    => 'yes',
     Font       => 'Helvetica',
     FontSize   => 12,
     FirstLabel => 1,
                            );

     #    We can fiddle the components...

     #    Lets make the lname (lastname) bold-faced
     print "\n******* make the lname field boldfaced *******\n";
     print "lname : ",join(' : ',@{$labels->editcomponent('lname')}),"\n";
     $labels->editcomponent('lname', 'name', 'no', 1, 'Times-Bold' );
     print "lname : ",join(' : ',@{$labels->editcomponent('lname')}),"\n";

     #    Lets switch the default ordering on the label from first-last to last-first
     print "\n******* swap order from first-last to last-first *******\n";
     print "Line 1 : ",join(' : ',@{$labels->definelabel(0)}),"\n";
     $labels->definelabel(0,'lname','fname');
     print "Line 1 : ",join(' : ',@{$labels->definelabel(0)}),"\n";

     #        print calibration sheet, in metric

     $labels->labelsetup( Units =>'metric');
     my $output = $labels->labelcalibration;
     open (FILE,"> calibration.ps") || warn "Can't open calibration.ps, $!\n";
     print FILE $output;
     close FILE;
     print "\n******* metric Letter sized calibration sheet in calibration.ps *******\n";

     #        adjust printable area and draw test boxes

     $output = $labels->labeltest;
     open (FILE,"> boxes.ps") || warn "Can't open boxes.ps, $!\n";
     print FILE $output;
     close FILE;
     print "\n******* Letter sized test boxes sheet in boxes.ps *******\n";

     #########################################################################
     #    Build a test address array
     # address array elements are : first,last,street_addr,city,state,zip
     my @addrs;
     my @address;
     my $indx = 0;
     foreach (<DATA>) {
         chomp;
         if ($indx%4 == 0) {
             @address = (split(':',$_));
         }
         elsif ($indx%4 == 1) {
             push @address,$_;
         }
         elsif ($indx%4 == 2) {
             push @address,(split(':',$_));
         }
         elsif ($indx%4 == 3) {
             push @addrs,[@address];
         }
         $indx++;
     }

     foreach (@addrs) {
         print "Address : $_->[0] $_->[1] $_->[2] $_->[3] $_->[4] $_->[5]\n";
     }

     #    Set up a few things...

     $setup = $labels -> labelsetup( Font         => 'Helvetica');
     $setup = $labels -> labelsetup( FirstLabel   => 25);
     $setup = $labels -> labelsetup( Output_Width => 2.625),
     $setup = $labels -> labelsetup( Columns      => 3),

     $output = $labels->makelabels(\@addrs);
     open (OUT,">labeltest.ps") || die "Can't open labeltest.ps, $!\n";
     print OUT $output;
     close OUT;
     print "\n******* label output in  labeltest.ps *******\n";

     1;

     __DATA__
     John and Jane:Doe
     1234 Robins Nest Sitting In a Tree Ave
     Katy:Tx:77453

     William:Clinton
     1300 Pennsylvania Ave.
     Washington:DC:10000

     Shirley:Temple
     98765 Birch Point Drive
     Houston:TX:78450

     Fred & June:Cleaver
     11221 Beaver Rd
     Columbus:OH:07873-6305

     Ernest and Julio:Gallo
     1987 Chardonnay
     San Jose:CA:80880

     Orville and Wilbur:Wright
     7715 Kitty Hawk Dr
     Kitty Hawk:NC:87220

     Ulysses:Grant
     1856 Tomb Park Rd
     Washington:DC:10012

BUGS AND TODO LIST
==================

   No bugs, that I am aware of.

   To do list :

+
     Need to be able to get the length of a string in ISOLatin1

+
     Add fontsize to each component

+
     Account for label height - currently will run off bottom

+
     Separate module for address compression/abbreviation

+
     Add bitmaps or images?

REVISION HISTORY
================

     Version 2.01 - January 2001
     Added y_gap tp Avery(tm) labels
     Updated calibration plot in BasicData to arbitrary paper size
     Minor repairs to test routine

     Version 2.0 - December 2000
     Major revision. Added all of the component and label definition stuff.
     Thanks to "Andrew Smith" <asmith at wpequity.com> for suggesting
     additional fields and inspiring the generalization.
     Thanks to Nuno Faria for assisting with the "Europeanization" of
     the code - it now works for Portuguese, and hopefully for other
     alphabets as well.
     Added pagesize so that various paper sizes are actually handled correctly.

     Version 1.0.1 - December 2000
     Bug reported by John Summerfield <summer at OS2.ami.com.au>
     Lowercase all SETUP parameters to avoid problems with mis-spellings.
     Do real parameter checks to check simple spelling errors.

     Bug reported by Nuno Faria <nfaria at fe.up.pt>
     Boxes plot did not work. Frankly I can't figure out how it ever did. Anyway
     it breaks on more modern versions of ghostscript, so I fixed it. Basically
     rewrote part of the PostScript(tm) code.

AUTHOR
======

     Alan Jackson
     October 1999
     alan@ajackson.org

     The PostNET font was gotten (under Gnu copyleft) from
     James H. Cloos, Jr. <cloos@jhcloos.com>

     The font metrics and paper sizes were pulled from the
     PostScript::Metrics module written by Shawn Wallace

Basic data that is used by the MailLabels                                     module.
*************************************************************************************

NAME
====

   PostScript::MailLabels::BasicData - Basic data that is used by the
MailLabels                                     module.

SYNOPSIS
========

     Loads up a few basic data items :

     Font metrics

     PS code for generating a calibration page

     PS code for generating a test page

     PS code for PostNET font

     Standard paper sizes

     Specs for Avery (tm) forms (incomplete)

DESCRIPTION
===========

     All this does is initialize a bunch of data items. Not intended to be
     used by normal people. It just makes the MailLabel.pm code more
     compact. The documentation is probably not too complete.

     Note that the font metrics camne from PostScript::Metrics by Shawn Wallace.
     The PostNET barcode font came from James H. Cloos, Jr.

EXAMPLE
=======

     require PostScript::MailLabels::BasicData;

     $data = new PostScript::MailLabels::BasicData;

     $code = '8460';
       @layout = @{$data{AVERY}{$code}};

     # layout=>[paper-size,[list of product codes], description,
     #          number per sheet, left-offset, top-offset, width, height]
     #			distances measured in points

     $testpage = $data{TESTPAGE};

REVISION HISTORY
================

     Version 1.02 - January 2001
     Fixed calibration axis labels to work for arbitrary paper size
     Added y_gap to Avery data
     Version 1.01 - December 2000
     Added pagesize parameter to handle paper other than Letter.
     Added more axis labels so that A4 calibration plot would work.

AUTHOR
======

     Alan Jackson
     October 1999
     alan@ajackson.org

SEE ALSO
========

helper module for PostScript::TextBlock
***************************************

NAME
====

   PostScript::Metrics - helper module for PostScript::TextBlock

SYNOPSIS
========

   Fix me.

DESCRIPTION
===========

   Fix me.

AUTHOR
======

   Shawn Wallace (shawn@as220.org)

SEE ALSO
========

   PostScript::TextBlock, PostScript::Element, PostScript::Document

module to fetch data from Unix PostScript Resource '`.upr'' files
*****************************************************************

NAME
====

   PostScript::FontResources - module to fetch data from Unix PostScript
Resource '`.upr'' files

SYNOPSIS
========

     my $rsc = new PostScript::FontResources (options);
     print STDOUT $rsc->FontAFM ("Times-Roman"), "\n";

DESCRIPTION
===========

   This package allows Unix font resource files, so called '`.upr'' files,
to be read and parsed.

CONSTRUCTOR
===========

new ( OPTIONS )
     The constructor will initialise the PostScript resource context by
     loading all resource files.

OPTIONS
=======

path => path
     path is a colon-separated list of locations where resource files are
     kept. It defaults to the value of the environment variable
     PSRESOURCEPATH, which defaults to '`::''.

     Two adjacent colons in the path represent the list of default places
     in which a component looks for resources. This is also the default
     value for users who have not installed private resources. Users with
     private resources should end the path with a double colon if they want
     their resources to override the system defaults, or begin it with a
     double colon if they don't want to override system defaults.

     On Unix systems, resource files end with the suffix '`.upr'' (for
     Unix PostScript resources). The principal resource file in a directory
     is named '`PSres.upr''.

     If the first line of a principal resource file is
     '`PS-Resources-Exclusive-1.0'', only this file will be loaded and
     processing continues with the next entry from the path.

     If, however, the first line of the principal resource file is
     '`PS-Resources-1.0'', or if there is no such file, all files in the
     directory with the suffix '`.upr'' will be loaded.

stdpath => path
     The standard locations for resource files.

error => [ 'die' | 'warn' | 'ignore' ]
     How errors must be handled.

     Invalid entries in the file are always reported unless the error
     handling strategy is set to 'ignore'.

verbose => value
     Prints verbose info if value is true.

trace => value
     Prints tracing info if value is true.  trace' and 'Implies 'verbose'.

debug => value
     Prints debugging info if value is true.  Implies 'trace' and
     'verbose'.

INSTANCE METHODS
================

   Each of these methods can return undef if the corresponding information
could not be found in the file.

FontAFM ( FONTNAME )
     The name of the Adobe Font Metrics (.afm) file for the named font.

FontOutline ( FONTNAME )
     The name of the PostScript Font program for the named font.

ENVIRONMENT VARIABLES
=====================

PSRESOURCEPATH
     The list of directories where resource files are kept. Semantics are
     as defined in appendix A of *Display PostScript Toolkit for X*, Adobe
     Technical Note `DPS.refmanuals.TK.pdf'.

KNOWN BUGS AND LIMITATIONS
==========================

   Only FontAFM and FontOutline resources are implemented. All other
resource sections are ignored.

   All info is loaded in memory structures. This is okay for small files
or if several lookups are done on the same file.

   Backslash escape processing is not yet implemented, except for the
handling of line continuation.

   This module is intended to be used on Unix systems only.  Your mileage
on other platforms may vary.

SEE ALSO
========

http://www.adobe.com/supportservice/devrelations/PDFS/TN/DPS.refmanuals.TK.pdf
     The specification of the Adobe Display PostScript Toolkit for X. The
     format of the font resources file is described in appendix A of this
     document.

AUTHOR
======

   Johan Vromans, Squirrel Consultancy <jvromans@squirrel.nl>

COPYRIGHT and DISCLAIMER
========================

   This program is Copyright 2000,1999 by Squirrel Consultancy. All rights
reserved.

   This program is free software; you can redistribute it and/or modify it
under the terms of either: a) the GNU General Public License as published
by the Free Software Foundation; either version 1, or (at your option) any
later version, or b) the "Artistic License" which comes with Perl.

   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 either the GNU General Public
License or the Artistic License for more details.

An object that may be used to construct a block of                 text in PostScript.
**************************************************************************************

NAME
====

   PostScript::TextBlock - An object that may be used to construct a block
of                 text in PostScript.

SYNOPSIS
========

     use PostScript::TextBlock;
     my $tb = new PostScript::TextBlock;
     $tb->addText( text => "Hullaballo in Hoosick Falls.\n",
                   font => 'CenturySchL-Ital',
                   size => 24,
                   leading => 26
                  );
     $tb->addText( text => "by Charba Gaspee.\n",
                   font => 'URWGothicL-Demi',
                   size => 12,
                   leading => 14
                  );
     print 'There are '.$tb->numElements.' elements in this object.';
     open OUT, '>psoutput.ps';
     my ($code, $remainder) = $tb->Write(572, 752, 20, 772);
     print OUT $code;

DESCRIPTION
===========

   The PostScript::TextBlock module implements four methods:

new() - Create a New PostScript::TextBlock object
     This method instantiates a new object of class PostScript::TextBlock.

addText( text=>$text,                [ font=>$font ],                [ size=>$size ],                [ leading=>$leading ] )
     The addText() method will add a new 'text element' to the TextBlock
     object. A 'text element' can be thought of as a section of text that
     has the same characteristics, i.e. all the characters are the same
     font, size and leading.  this representation allows you to include
     text rendered in multiple fonts at multiple sizes within the same
     text block by including them as separate elements.

     This method takes up to four attributes (note that the '[]' brackets
     above indicate that a parameter is optional, not an array reference):

     text The text attribute is required, though nothing bad will happen
     if you leave it out. This is simply the text to be rendered in the
     text block. Line breaks may be inserted by including a newline "\n".

     font The font attribute is a string indicating the name of the font
     to be used to render this element. The PS package uses an internal
     description of the Font Metrics of various fonts that is contained in
     the PostScript::Metrics module. As of this writing, the
     PostScript::Metrics module supports the following fonts (basically,
     the default GhostScript fonts that have AFM files):

     NimbusSanL-ReguCond	  URWGothicL-Book CenturySchL-Bold
     CharterBT-Italic URWBookmanL-Ligh          CharterBT-BoldItalic
     NimbusRomNo9L-ReguItal    URWBookmanL-DemiBoldItal CharterBT-Roman
           NimbusMonL-ReguObli NimbusSanL-ReguCondItal   CenturySchL-Ital
     CenturySchL-BoldItal      URWPalladioL-Roma URWBookmanL-LighItal
     CharterBT-Bold NimbusSanL-BoldCond       NimbusMonL-BoldObli
     NimbusSanL-BoldCondItal   URWGothicL-DemiObli NimbusSanL-Regu
      URWPalladioL-Bold NimbusMonL-Regu           NimbusSanL-ReguItal
     URWGothicL-BookObli       URWPalladioL-Ital

     You can get a list of the currently supported fonts with the
     following:

          use PostScript::Metrics;
          @okfonts = PostScript::Metrics->listFonts();

     NOTE: The font must be available to the PostScript interpreter that
     is used to render the page described by the program. If the
     interpreter cannot load the font, it will ususally attempt to
     substitute a similar font. If a font is substituted with a font with
     different metrics, lines of text may overrun the right margin of the
     text block. You have been warned.

     It is very easy to create stylesheets for a document:

          # Define the styles
          #
          %body = ( font => 'URWGothicL-DemiObli', size => 12, leading => 16 );
          %head1 = ( font => 'NimbusSanL-BoldCond', size => 24, leading => 36 );
          %head2 = ( font => 'NimbusSanL-BoldCond', size => 18, leading => 30 );

          # Use them where appropriate
          #
          $tb->addText(text => "Chapter 10\n", %head1);
          $tb->addText(text => "Spokane Sam and His Spongepants\n", %head2);
          $tb->addText(text => "It was a dark and stormy night and Spokane Sam\'s
          Spongepants were thirsty...", %body);

    numElements()
          Returns the number of elements in the text block object. An
          'element' is created each time the addText() method is called.

    Write( $width, $height, $xoffset, $yoffset )
          The Write() method will generate the PostScript code that will
          render the text on a page when passed to a PostScript
          interpreter such as Ghostscript. The four parameters are
          expressed in points (1/72 inch) and indicate the width and
          height of the box within which the text should be printed, and
          the x and y offset of the upper left corner of this box.

          Important: PostScript defines the orgin (0,0) as the lower left
          corner of the page! This *will* mess you up.

          Standard page sizes in points are:

               Paper Size                      Width, Height (in points)
               .........................       .........................
               Letter                          612, 792
               Legal                           612, 1008
               Ledger                          1224, 792
               Tabloid                         792, 1224
               A0                              2384, 3370
               A1                              1684, 2384
               A2                              1191, 1684
               A3                              842, 1191
               A4                              595, 842
               A5                              420, 595
               A6                              297, 420
               A7                              210, 297
               A8                              148, 210
               A9                              105, 148
               B0                              2920, 4127
               B1                              2064, 2920
               B2                              1460, 2064
               B3                              1032, 1460
               B4                              729, 1032
               B5                              516, 729
               B6                              363, 516
               B7                              258, 363
               B8                              181, 258
               B9                              127, 181
               B10                             91, 127
               #10 Envelope                    297, 684
               C5 Envelope                     461, 648
               DL Envelope                     312, 624
               Folio                           595, 935
               Executive                       522, 756

          The write() method returns two values: a string consisting of
          the PostScript code (suitable for printing to a file), and a
          TextBlock object containing the elements (and partial elements)
          that did not fit within the specified area, if any. If the
          entire text block fits with the area, the remainder will be
          undef. The remainder can be used to layout multiple pages and
          columns, etc. in a similar manner to most modern desktop
          publishing programs. In general, the write() method should be
          called as in the following, which writes the PostScript code to
          a file called 'psoutput.ps':

               open OUT, '>psoutput.ps';
               my ($code, $remainder) = $tb->Write(572, 752, 20, 772);
               print OUT $code;

          To print an entire text block that spans multiple pages, you
          could do something like this:

          (add enough text to the text block first..)

               open OUT, '>psoutput.ps';
               my $pages = 1;

               # Create the first page
               #
               my ($code, $remainder) = $tb->Write(572, 752, 20, 772);
               print OUT "%%Page:$pages\n";      # this is required by the Adobe
                                                 # Document Structuring Conventions
               print OUT $code;
               print OUT "showpage\n";

               # Print the rest of the pages, if any
               #
               while ($remainder->numElements) {
                   $pages++;
                   print OUT "%%Page:$pages\n";
                   ($code, $remainder) = $remainder->Write(572, 752, 20, 772);
                   print OUT $code;
                   print OUT "showpage\n";
               }

          However, if you use the PostScript::Document module to construct
          generic multi-page PostScript documents, you don't have to worry
          about this.

A NOTE ABOUT FONT METRICS
=========================

   The write() method uses the module PostScript::Metrics to determine the
width of each character; widths vary from font to font and character to
character.  If you were writing a stright PostScript program, you would
let the PostScript interpreter do this for you, but in the case of this
program, we need to know the width of each character in a font within the
Perl script. The PostScript::Metrics module contains the font metrics
(i.e., a list containing the width of each character in the font) for a
bunch of fonts that are listed above under the description of the
addText() method. This set started with the metrics for all of the default
fonts with AFM files that came with GhostScript. It is slowly growing as
more fonts are mapped. To add support for a new font, you must create the
array with the metrics for that font and add it to the PostScript::Metrics
module. For a font with an AFM file, the AFM file can be parsed with Gisle
Aas' Font::AFM module, available on CPAN.

   Please send all PostScript::Metrics patches to the author at
shawn@as220.org.

TODO
====

   * better compliance with Adobe's Document Structuring Conventions *
more font metrics descriptions * make font loading code smarter and more
efficient for the interpreter * support a larger character set * it would
be nice to add more functions, e.g. Clone() * how about settable defaults?

AUTHOR
======

   Copyright 1998, 1999 Shawn Wallace. All rights reserved.

   Contact the author: shawn@as220.org http://www.as220.org/shawn

   Portions of code contributed by Dan Smeltz.

   This is free software. You may use, modify, and redistribute this
package under the same terms as Perl itself.

   PostScript is a trademark of Adobe Systems.

Perl interface to the Postgres95 SQL database engine
****************************************************

NAME
====

   Postgres - Perl interface to the Postgres95 SQL database engine

SYNOPSIS
========

     use Postgres;

     $conn = db_connect($database,$host,$port)
       or die "could not connect -- $Postgres::error";

     The parameters $host and $port are optional (or may be undef).
     This will use the default Postgres95 values for them.

     print "Connected Database: ", $conn->db();
     print "Connected Host: ", $conn->host();
     print "Connection Options: ", $conn->options();
     print "Connected Port: ", $conn->port();
     print "Connected tty: ", $conn->tty();
     print "Connection Error Message: ", $conn->errorMessage();

   This method is identical to PQreset(conn)

     $conn->reset();

   This method executes an SQL statement or query.

     $query = $conn->execute($sql_statement)
       or die "Error -- $Postgres::error";

   Retrieve the values from a SELECT query.

     @array = $query->fetchrow();

   Get information from the results of the last query.

     $val = $query->cmdStatus();
     $val = $query->oidStatus();

   Calling the following functions on a result handle that is not from a
SELECT is undefined.

     $val = $query->ntuples();
     $val = $query->nfields();
     $val = $query->fname($column_index);
     $val = $query->fnumber($column_name);
     $val = $query->ftype($column_index);
     $val = $query->fsize($column_index);

   These functions are provided for completeness but are not intended to be
used.  The fetchrow() method will return undef for a field which is null.

     $val = $query->getvalue($tuple_index,$column_index);
     $val = $query->getlength($tuple_index,$column_index);
     $val = $query->getisnull($tuple_index,$column_index);

   The putline() and getline() functions are called as follows:

     $query->putline($string);
     $value = $query->getline();
     $query->endcopy();

DESCRIPTION
===========

   This package is designed as close as possible to its C API counterpart,
but be more like Perl in how you interact with the API.  The C Programmer
Guide that comes with Postgres describes most things you need.

   The following functions are currently not implemented: PQtrace(),
PQendtrace(), and the asynchronous notification.  I do not believe that
binary cursors will work, either.

   Once you db_connect() to a database, you can then issue commands to the
execute() method.  If either of them returns an error from the underlying
API, the value returned will be undef and the variable `$Postgres::error'
will contain the error message from the database.  The $port parameter to
db_connect() is optional and will use the default port if not specified.
All environment variables used by the PQsetdb() function are honored.

   The method fetchrow() returns an array of the values from the next row
fetched from the server.  It returns an empty list when there is no more
data available.  Fields which have a NULL value return undef as their
value in the array.  Calling fetchrow() or the other tuple-related
functions on a statement handle which is not from a SELECT statement has
undefined behavior, and may well crash your program.  Other functions work
identically to their similarly-named C API functions.

No finish or clear statements
-----------------------------

   Whenever the scalar that holds the statement or connection handle loses
its value, the underlying data structures will be freed and appropriate
connections closed.  This can be accomplished by performing one of these
actions:

undef the handle
use the handle for another purpose
let the handle run out of scope
exit the program.
Error messages
--------------

   A global variable `$Postgres::error' always holds the last error
message.  It is never reset except on the next error.  The only time it
holds a valid message is after execute() or db_connect() returns undef.

PREREQUISITES
=============

   You need to have the Postgres95 database server installed and
configured on your system to use this module.

   Be sure to set the proper directory locations in the Makefile.PL file
for your installation.

AUTHOR
======

   Vivek Khera (`vivek@khera.org').  Many ideas were taken from the
MsqlPerl module.  I am no longer maintaining this module.  If you would
like to take over, please let me know.

a UNIX print quota module
*************************

NAME
====

   Pquota - a UNIX print quota module

SYNOPSIS
========

     use Pquota;

     # object creator and destructor
     $pquota = Pquota->new ("/path/to/quota/directory"[, $opts]);
     $pquota->close ();

     # printers database commands
     $pquota->printer_add ($printer, $page_cost, $user_db);
     $pquota->printer_rm ($printer);
     $pquota->printer_set_cost ($printer, $cost);
     $pquota->printer_get_cost ($printer);
     $pquota->printer_get_cost_list ();
     $pquota->printer_set_user_database ($printer, $user_db);
     $pquota->printer_get_user_database ($printer);
     $pquota->printer_get_user_database_list ();
     $pquota->printer_set_field ($printer, $key, $value);
     $pquota->printer_get_field ($printer, $key);

     # user database commands
     $pquota->user_add ($user, $user_db, $periodic_quota);
     $pquota->user_rm ($user, $user_db);
     $pquota->user_print_pages ($user, $printer, $num_pages);
     $pquota->user_add_to_current ($user, $user_db, $amount);
     $pquota->user_set_current ($user, $user_db, $periodic_quota);
     $pquota->user_get_current_by_dbm ($user, $user_db);
     $pquota->user_get_current_by_printer ($user, $printer);
     $pquota->user_reset_current ($user, $user_db);
     $pquota->user_add_to_periodic ($user, $user_db, $amount);
     $pquota->user_set_periodic ($user, $user_db, $amount);
     $pquota->user_get_periodic ($user, $user_db);
     $pquota->user_reset_total ($user, $user_db);
     $pquota->user_set_field ($user, $user_db, $key, $value);
     $pquota->user_get_field ($user, $user_db, $key);

DESCRIPTION
===========

   This module is an attempt to provide an easy interface to a group of
DBM files used to store print quota information on a UNIX system.  It
makes writing printer interface scripts a lot easier.  Pquota requires the
MLDBM module.

   As we've said, Pquota is a wrapper module for handling DBM files.  We've
structured it so that there is one database that contains information about
the different printers on your system, and any number of user databases.
The printers database, which we've named _printers to (hopefully) avoid any
namespace clashes.  An entry in the _printers database looks something like
this:

     $printer_entry = {'cost'        =>      5,
                       'dbm'         =>      'students'};

   Every printer has a cost per page, and an associated user database.
Multiple printers can point to the same user database, but you can't have
multiple databases for the same printer.

   Pquota is designed with a periodic allotment of quota in mind.  On our
systems, students get a couple dollars worth every week.  So every entry
in a user database looks like this:

     $user_entry = {'periodic'       =>      300,
                    'current'        =>      273,
                    'total'          =>      27      };

   And once a week, we run a cron job to reset all the current values to
be equal to the periodic values.

   Pquota also has pessimistic file locking internal to its DBM accesses,
so there won't be any problems with corrupt DBM files.  However, we
decided not to register any signal handlers to deal with signals when the
files are locked, because we didn't want to be overriding any handlers in
the enclosing program.  Just in case, all of the lock files are named
dbm.lock, where dbm is the name of the DBM that is locked.  They reside in
the same directory as the DBMs themselves.

MLDBM Notes
-----------

   MLDBM by default uses Data::Dumper to translate Perl data structures
into strings, and SDBM_File to store them to disk.  This is because
SDBM_File comes with all UNIX installs of Perl, and Data::Dumper was
originally the only module which could serialize Perl's data structures.
However, it also has the option of using any of the other DBM modules for
storage, and either Storable or FreezeThaw to serialize the structures.
As such, we've added the $opts option to the new method.  Just give it a
hash reference, with the keys 'UseDB' or 'Serializer', to set either the
DBM module or the serializing module, respectively.  For example,

     $pquota = Pquota->new ("/var/spool/pquota", {'UseDB' => 'DB_File'});

   would tell MLDBM to use the DB_File module to store the structures to
disk.

   Also, to avoid unnecessary locking, we've added an option to open the
databases in read-only mode, so that scripts that won't be writing to the
databases don't lock it.  Simply set the 'RO' option to 'true' in order to
open the databases in read-only mode.

     $pquota = Pquota->new ("/var/spool/pquota", {'RO' => 'true'});

Method Notes
------------

   All methods return either the requested information or 1 in case of
success, and undef in case of failure.

Object Methods
--------------

Pquota::new ($quotadir[, $opts])
     Standard object constructor.  $quotadir should contain the path to a
     directory to store the DBMs.  The optional $opts should be a
     reference to a hash, as described in MLDBM Notes.

Pquota::close ()
     Closes all open databases.  The database methods will open the DBMs
     as needed, but you must call Pquota::close() before exiting your
     program in order to make sure the DBMs are properly closed.

Printer Database Methods
------------------------

Pquota::printer_add ($printer, $page_cost, $user_db)
     Adds a printer to the printers DBM, with the associated per-page cost
     and user database.

Pquota::printer_rm ($printer)
     Removes a printer from the printers DBM.

Pquota::printer_set_cost ($printer, $cost)
     Sets the per-page cost for the printer.

Pquota::printer_get_cost ($printer)
     Returns the per-page cost for the printer.

Pquota::printer_get_cost_list ()
     Returns a reference to a hash, with printer names as keys, and their
     per-page costs as the values.

Pquota::printer_set_user_database ($printer, $user_db)
     Sets the printer's associated user database.

Pquota::printer_get_user_database ($printer)
     Returns the name of the printer's associated user database.

Pquota::printer_get_user_database_list ()
     Returns a reference to a hash, with printer names as keys, and their
     per-page costs as the values.

Pquota::printer_set_field ($printer, $key, $value)
     Sets an arbitrary field in the printer's record.  This is in case you
     want to store more information about your printers than Pquota
     supports natively.

Pquota::printer_get_field ($printer, $key);
     Returns the value store in an arbitrary field in the printer's record.

User Database Methods
---------------------

Pquota::user_add ($user, $user_db, $periodic_quota)
     Adds an entry to a user database, with the indicated periodic quouta.

Pquota::user_rm ($user, $user_db)
     Removes a user from the specified user database.

Pquota::user_print_pages ($user, $printer, $num_pages)
     Modifies the user database to reflect the fact that the user has
     printed the indicated number of pages on the specified printer.

Pquota::user_add_to_current ($user, $user_db, $amount)
     Adds the specified amount to the user's current remaining quota.

Pquota::user_set_current ($user, $user_db. $amount)
     Sets the user's current remaining quota.

Pquota::user_get_current_by_dbm ($user, $user_db)
     Returns the user's current remaining quota.

Pquota::user_get_current_by_printer ($user, $printer)
     Returns the user's current remaining quota in the user database
     associated with that printer.

Pquota::user_reset_current ($user, $user_db)
     Resets the user's current remaining quota to his periodic quota value.

Pquota::user_add_to_periodic ($user, $user_db, $amount)
     Adds the specified amount to the user's periodic quota allotment.

Pquota::user_set_periodic ($user, $user_db, $amount)
     Sets the user's periodic quota allotment.

Pquota::user_get_periodic ($user, $user_db)
     Returns the user's periodic quota allotment.

Pquota::user_reset_total
     Sets the user's total quota used to 0.

Pquota::user_set_field ($user, $user_db, $key, $value)
     Sets an arbitrary field in the user's record.

Pquota::user_get_field ($user, $user_db, $key)
     Returns the value stored in an arbitrary field in the user's record.

TO DO
=====

   * Come up with more functionality.  Pquota currently does everything we
     need, but we're sure there must be features it lacks.

BUGS
====

   None that we know of.  Please feel free to mail us with any bugs,
patches, suggestions, comments, flames, death threats, etc.

AUTHORS
=======

   David Bonner <`dbonner@cs.bu.edu'> and Scott Savarese
<`savarese@cs.bu.edu'>

VERSION
=======

   Version 1.00  April 30, 1999

COPYRIGHT
=========

   Copyright (c) 1998, 1999 by David Bonner and Scott Savarese.  All rights
reserved. This program is free software; you can redistribute and/or modify
it under the same terms as Perl itself.

Adds pragmata to Exporter
*************************

NAME
====

   Pragmatic - Adds pragmata to Exporter

SYNOPSIS
========

   In module MyModule.pm:

     package MyModule;
     require Pragmatic;
     @ISA = qw (Pragmatic);

     %PRAGMATA = (mypragma => sub {...});

   In other files which wish to use MyModule:

     use MyModule qw (-mypragma); # Execute pragma at import time
     use MyModule qw (-mypragma=1,2,3); # Pass pragma argument list

DESCRIPTION
===========

   Pragmatic implements a default import method for processing pragmata
before passing the rest of the import to Exporter.

   Perl automatically calls the import method when processing a use
statement for a module. Modules and use are documented in Perlfunc (perl.info),
and Perlmod (perl.info).

   (Do not confuse Pragmatic with *pragmatic modules*, such as less,
strict and the like.  They are standalone pragmata, and are not associated
with any other module.)

Using Pragmatic Modules
-----------------------

   Using Pragmatic modules is very simple.  To invoke any particular
pragma for a given module, include it in the argument list to use preceded
by a hyphen:

     use MyModule qw (-mypragma);

   `Pragmatic::import' will filter out these arguments, and pass the
remainder of the argument list from the use statement to
`Exporter::import' (actually, to `Exporter::export_to_level' so that
Pragmatic is transparent).

   If you want to pass the pragma arguments, use syntax similar to that of
the -M switch to *perl* (see Perlrun (perl.info)):

     use MyModule qw (-mypragma=abc,1,2,3);

   If there are any warnings or fatal errors, they will appear to come
from the use statement, not from `Pragmatic::import'.

Writing Pragmatic Modules
-------------------------

   Writing Pragmatic modules with Pragmatic is straight-forward.  First,
`require Pragmatic' (you could use it instead, but it exports nothing, so
there is little to gain thereby).  Declare a package global `%PRAGMATA',
the keys of which are the names of the pragmata and their corresponding
values the code references to invoke.  Like this:

     package MyPackage;

     require Pragmatic;

     use strict;
     use vars qw (%PRAGMATA);

     sub something_else { 1; }

     %PRAGMATA =
       (first => sub { print "@_: first\n"; },
        second => sub { $SOME_GLOBAL = 1; },
        third => \&something_else,
        fourth => 'name_of_sub');

   When a pragma is given in a use statement, the leading hyphen is
removed, and the code reference corresponding to that key in `%PRAGMATA',
or a subroutine with the value's name, is invoked with the name of the
package as the first member of the argument list (this is the same as what
happens with import).  Additionally, any arguments given by the caller are
included (see `Using Pragmatic Modules' in this node, above).

EXAMPLES
========

Using Pragmatic Modules
-----------------------

  1. Simple use:
          use MyModule; # no pragmas

          use MyModule qw (-abc); # invoke C<abc>

          use MyModule qw (-p1 -p2); # invoke C<p1>, then C<p2>

  2. Using an argument list:
          use MyModule qw (-abc=1,2,3); # invoke C<abc> with (1, 2, 3)

          use MyModule qw (-p1 -p2=here); # invoke C<p1>, then C<p2>
                                          # with (1, 2, 3)

  3. Mixing with arguments for Exporter: (Please see Exporter,
     for a further explanatation.)

          use MyModule ( ); # no pragmas, no exports

          use MyModule qw (fun1 -abc fun2); # import C<fun1>, invoke C<abc>,
                                            # then import C<fun2>

          use MyModule qw (:set1 -abc=3); # import set C<set1>, invoke C<abc>
                                          # with (3)

Writing Pragmatic Modules
-------------------------

  1. Setting a package global:
          %PRAGMATA = (debug => sub { $DEBUG = 1; });

  2. Selecting a method:
          my $fred = sub { 'fred'; };
          my $barney = sub { 'barney'; };

          %PRAGMATA =
            (fred => sub {
               local $^W = 0;
               *flintstone = $fred;
             },

          barney => sub {
            local $^W = 0;
            *flintstone = $barney;
          });

  3. Changing inheritance:
          %PRAGMATA = (super => sub { shift; push @ISA, @_; });

  4. Inheriting pragmata:
          package X;
          @ISA = qw(Pragmatic);
          %PRAGMATA = (debug => 'debug');
          $DEBUG = 0;

          sub debug { ${"$_[0]::DEBUG"} = 1; }

          package Y:
          @ISA = qw(X);
          %PRAGMATA = (debug => 'debug');
          $DEBUG = 0;

SEE ALSO
========

   See Exporter,

   Exporter does all the heavy-lifting (and is a very interesting module
to study) after Pragmatic has stripped out the pragmata from the use.

DIAGNOSTICS
===========

   The following are the diagnostics generated by Pragmatic.  Items marked
"(W)" are non-fatal (invoke `Carp::carp'); those marked "(F)" are fatal
(invoke `Carp::croak').

No such pragma '%s'
     (F) The caller tried something like "use MyModule (-xxx)" where there
     was no pragma *xxx* defined for MyModule.

Invalid pragma '%s'
     (F) The writer of the called package tried something like "%PRAGMATA =
     (xxx => not_a_sub)" and either assigned *xxx* a non-code reference,
     or *xxx* is not a method in that package.

Pragma '%s' failed
     (W) The pramga returned a false value.  The module is possibly in an
     inconsisten state after this.  Proceed with caution.

AUTHORS
=======

   B. K. Oxley (binkley) at Home <binkley@bigfoot.com>

COPYRIGHT
=========

     Copyright 1999, B. K. Oxley.

   This library is free software; you may redistribute it and/or modify it
under the same terms as Perl itself.

base class for all applications
*******************************

NAME
====

   Proc::Application - base class for all applications

SYNOPSIS
========

     package Program;
     @Program::ISA = qw(Proc::Application);
     sub main { print "Done\n"; }
     package main;
     Program->new->run();

DESCRIPTION
===========

   This is a application code base

new
---

main
----

run
---

DESTROY
-------

processCommandOptions
---------------------

   Process options from command line by Getopt::Long && Getopt::ArgvFile

log
---

   Create and return log object ( the Log::Dispatch )

options
-------

description
-----------

usage
-----

_processFileLog
---------------

_processSysLog
--------------

_processScreenLog
-----------------

_processFileLock
----------------

stFormatLogLine
---------------

detach
------

chroot
------

changeUser
----------

changeGroup
-----------

pidfile
-------

daemon class based on Proc::Application;
****************************************

NAME
====

   Proc::Application::Daemon - daemon class based on Proc::Application;

SYNOPSIS
========

     package Program;
     use Proc::Application::Daemon;
     use base qw(Proc::Application::Daemon);
     sub handler
     {
         my ( $his, $clientSocket ) = @_;
         $this->socket->print ( 'Done' );
         $this->log->warning ( 'warning' );
         die "Error";
     }
     package main;
     Program->new->run();

DESCRIPTION
===========

   daemon class based on Proc::Application;

new
---

   A construtror, setup childs and childCount

options
-------

   Add mode (fork|single|prefork=[count]) and socket
(domain=unix|inet|ssl:all_io::socket:: parameter) options

processSocketCreate
-------------------

   Handler for socket option. Create new socket and store it to
$object->{socket}

processModeParameter
--------------------

   Child for 'prefork=count' mode and setup preforkCount option

socket
------

   Return a client socket from $object->{socket}

mainSocket
----------

   Return a main daemon socket from $object->{socket}

done
----

   You must return 'true' for end main loop

mainHandler
-----------

   Call handler() method with $cliendSocket atrument, log the errors of
execution and close client socket at exit

handler
-------

   Real work method, get $this and $clientSocket argumentds.

childs
------

   Return a hash reference of childs with keys with pids

processSigChild
---------------

   SIGCHLD processor. Get a child pid by waitpid() and delete it from
childs()

forkFunction
------------

   Get three code refs ( for run at parent, child and error fork
sitiations ), fork process and execute parameters functions. Store pid of
new process at childs(), exit(0) at child after execute of child function,
log fork error and sleep(1) after fork error.  funtions

threadFunction
--------------

realMain
--------

   Main loop. accept() the new connection, and fork (if fork more) and
pass execution to mainHandler

main
----

   Prefork processes if prefork mode, loop up for preforked childs count
and call realMain()

DESTROY
-------

   Send TERM signal to all childs and call parent DESTROY()

Log Debug Error Fatal Run Options
---------------------------------

   for compatibility with Net::Daemon

Generic interface to Unix and Win32 background process management
*****************************************************************

NAME
====

   Proc::Background - Generic interface to Unix and Win32 background
process management

SYNOPSIS
========

     use Proc::Background;
     timeout_system($seconds, $command, $arg1);
     timeout_system($seconds, "$command $arg1");
     my $proc1 = Proc::Background->new($command, $arg1, $arg2);
     my $proc2 = Proc::Background->new("$command $arg1 1>&2");
     $proc1->alive;
     $proc1->die;
     $proc1->wait;
     my $time1 = $proc1->start_time;
     my $time2 = $proc1->end_time;

DESCRIPTION
===========

   This is a generic interface for placing processes in background on both
Unix and Win32 platforms.  This module lets you start, kill, wait on,
retrieve exit values, and see if background processes still exist.

METHODS
=======

new command, [*arg*, [*arg*, ...]]
new 'command [*arg* [*arg* ...]]'
     This creates a new background process.  As exec() or system() may be
     passed an array with a single single string element containing a
     command to be passed to the shell or an array with more than one
     element to be run without calling the shell, new has the same
     behavior.

     In certain cases new will attempt to find command on the system and
     fail if it cannot be found.

     For Win32 operating systems:

          The Win32::Process module is always used to spawn background
          processes on the Win32 platform.  This module always takes a
          single string argument containing the executable's name and
          any option arguments.  In addition, it requires that the
          absolute path to the executable is also passed to it.  If
          only a single argument is passed to new, then it is split on
          whitespace into an array and the first element of the split
          array is used at the executable's name.  If multiple
          arguments are passed to new, then the first element is used
          as the executable's name.

          If the executable's name is an absolute path, then new
          checks to see if the executable exists in the given location
          or fails otherwise.  If the executable's name is not
          absolute, then the executable is searched for using the PATH
          environmental variable.  The input executable name is always
          replaced with the absolute path determined by this process.

          In addition, when searching for the executable, the
          executable is searched for using the unchanged executable
          name and if that is not found, then it is checked by
          appending `.exe' to the name in case the name was passed
          without the `.exe' suffix.

          Finally, the argument array is placed back into a single
          string and passed to Win32::Process::Create.

     For non-Win32 operating systems, such as Unix:

          If more than one argument is passed to new, then new
          assumes that the command will not be passed through the
          shell and the first argument is the executable's relative
          or absolute path.  If the first argument is an absolute
          path, then it is checked to see if it exists and can be
          run, otherwise new fails.  If the path is not absolute,
          then the PATH environmental variable is checked to see if
          the executable can be found.  If the executable cannot be
          found, then new fails.  These steps are taking to prevent
          exec() from failing after an fork() without the caller of
          new knowing that something failed.

     If anything fails, then new returns an empty list in a list context,
     an undefined value in a scalar context, or nothing in a void context.

pid
     Returns the process ID of the created process.  This value is saved
     even if the process has already finished.

alive
     Return 1 if the process is still active, 0 otherwise.

die
     Reliably try to kill the process.  Returns 1 if the process no longer
     exists once die has completed, 0 otherwise.  This will also return 1
     if the process has already died.  On Unix, the following signals are
     sent to the process in one second intervals until the process dies:
     HUP, QUIT, INT, KILL.

wait
     Wait for the process to exit.  Return the exit status of the command
     as returned by wait() on the system.  To get the actual exit value,
     divide by 256 or right bit shift by 8, regardless of the operating
     system being used.  If the process never existed, then return an empty
     list in a list context, an undefined value in a scalar context, or
     nothing in a void context.  This function may be called multiple times
     even after the process has exited and it will return the same exit
     status.

start_time
     Return the value that the Perl function time() returned when the
     process was started.

end_time
     Return the value that the Perl function time() returned when the exit
     status was obtained from the process.

FUNCTIONS
=========

timeout_system timeout, command, [*arg*, [*arg*...]]
timeout_system 'timeout command [*arg* [*arg*...]]'
     Run a command for timeout seconds and if the process did not exit,
     then kill it.  While the timeout is implemented using sleep(), this
     function makes sure that the full timeout is reached before killing
     the process.  timeout_system does not wait for the complete timeout
     number of seconds before checking if the process has exited.  Rather,
     it sleeps repeatidly for 1 second and checks to see if the process
     still exists.

     In a scalar context, timeout_system returns the exit status from the
     process.  In an array context, timeout_system returns a two element
     array, where the first element is the exist status from the process
     and the second is set to 1 if the process was killed by
     timeout_system or 0 if the process exited by itself.

     The exit status is the value returned from the wait() call.  If the
     process was killed, then the return value will include the killing of
     it.  To get the actual exit value, divide by 256.

     If something failed in the creation of the process, the subroutine
     returns an empty list in a list context, an undefined value in a
     scalar context, or nothing in a void context.

IMPLEMENTATION
==============

   *Proc::Background* comes with two modules, *Proc::Background::Unix* and
*Proc::Background::Win32*.  Currently, on the Unix platform
*Proc::Background* it uses the *Proc::Background::Unix* class and on the
Win32 platform *Proc::Win32*, which makes use of *Win32::Process*, is used.

   The *Proc::Background* assigns to @ISA either *Proc::Unix* or
*Proc::Win32*, which does the OS dependent work.  The OS independent work
is done in *Proc::Background*.

   Proc::Background uses two variables to keep track of the process.
$self->{_os_obj} contains the operating system object to reference the
process.  On a Unix systems this is the process id (pid).  On Win32, it is
an object returned from the *Win32::Process* class.  When $self->{_os_obj}
exists, then the process is running.  When the process dies, this is
recorded by deleting $self->{_os_obj} and saving the exit value
$self->{_exit_value}.

   Anytime alive is called, a waitpid() is called on the process and the
return status, if any, is gathered and saved for a call to wait.  This
module does not install a signal handler for SIGCHLD.  If for some reason,
the user has installed a signal handler for SIGCHLD, then, then when this
module calls waitpid(), the failure will be noticed and taken as the
exited child, but it won't be able to gather the exit status.  In this
case, the exit status will be set to 0.

SEE ALSO
========

   See also the Proc/Background/Unix, and
Proc/Background/Win32, manual pages.

AUTHOR
======

   Blair Zajac <blair@gps.caltech.edu>

COPYRIGHT
=========

   Copyright (C) 1998-2001 Blair Zajac.  All rights reserved.  This
package is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Unix interface to process mangement
***********************************

NAME
====

   Proc::Background::Unix - Unix interface to process mangement

SYNOPSIS
========

   Do not use this module directly.

DESCRIPTION
===========

   This is a process management class designed specifically for Unix
operating systems.  It is not meant used except through the
*Proc::Background* class.  See Proc/Background, for
more information.

AUTHOR
======

   Blair Zajac <blair@gps.caltech.edu>

COPYRIGHT
=========

   Copyright (C) 1998-2001 Blair Zajac.  All rights reserved.  This
package is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Interface to process mangement on Win32 systems
***********************************************

NAME
====

   Proc::Background::Win32 - Interface to process mangement on Win32
systems

SYNOPSIS
========

   Do not use this module directly.

DESCRIPTION
===========

   This is a process management class designed specifically for Win32
operating systems.  It is not meant used except through the
*Proc::Background* class.  See Proc/Background, for
more information.

IMPLEMENTATION
==============

   This package uses the Win32::Process class to manage the objects.

AUTHOR
======

   Blair Zajac <blair@gps.caltech.edu>

COPYRIGHT
=========

   Copyright (C) 1998-2001 Blair Zajac.  All rights reserved.  This
package is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Run Perl program as a daemon process
************************************

NAME
====

   Proc::Daemon - Run Perl program as a daemon process

SYNOPSIS
========

     use Proc::Daemon;
     Proc::Daemon::Init;

DESCRIPTION
===========

   This module contains the routine Init which can be called by a perl
program to initialize itself as a daemon.  A daemon is a process that runs
in the background with no controlling terminal.  Generally servers (like
FTP and HTTP servers) run as daemon processes.  However, do not make the
mistake that a daemon == server.

   The *Proc::Daemon::Init* function does the following:

  1. Forks a child and exits the parent process.

  2. Becomes a session leader (which detaches the program from the
     controlling terminal).

  3. Forks another child process and exits first child.  This prevents the
     potential of acquiring a controlling terminal.

  4. Changes the current working directory to "/".

  5. Clears the file creation mask.

  6. Closes all open file descriptors.

        You will notice that no logging facility, or other functionality
is performed.  *Proc::Daemon::Init* just performs the main steps to
initialize a program as daemon.  Since other funtionality can vary
depending on the nature of the program, *Proc::Daemon* leaves the
implementation of other desired functionality to the caller, or other
module/library (like Sys::Syslog).

   There is no meaningful return value *Proc::Daemon::Init*.  If an error
occurs in Init so it cannot perform the above steps, than it croaks with
an error message.  One can prevent program termination by using eval.

OTHER FUNCTIONS
===============

   *Proc::Daemon* also defines some other functions.  These functions can
be imported into the callers name space if the function names are
specified during the use declaration:

Fork
----

   Fork is like the built-in fork, but will try to fork if at all
possible, retrying if necessary.  If not possible, Fork will croak.

OpenMax
-------

   OpenMax returns the maximum file descriptor number.  If undetermined,
64 will be returned.

NOTES
=====

   * *Proc::Daemon::init* is still available for backwards capatibilty.
     However, it will not perform the double fork, and will return the
     session ID.

AUTHOR
======

   Earl Hood, earlhood@usa.net

   http://www.oac.uci.edu/indiv/ehood/

CREDITS
=======

   Implementation of *Proc::Daemon* derived from the following sources:

   * *Advanced Programming in the UNIX Environment*, by W. Richard Stevens.
     Addison-Wesley, Copyright 1992.

   * *UNIX Network Progamming*, Vol 1, by W. Richard Stevens.
     Prentice-Hall PTR, Copyright 1998.

DEPENDENCIES
============

   *Proc::Daemon* depends on the following modules: Carp, POSIX.

SEE ALSO
========

   See POSIX, Sys/Syslog,

fork off a function
*******************

NAME
====

   Proc::Forkfunk - fork off a function

SYNOPSIS
========

     use Proc::Forkfunc;

     forkfunc(\&child_func,@child_args);

DESCRIPTION
===========

   Fork off a process.  Call a function on the child process the function
should be passed in as a reference.  The child function should not return.

   Logic copied from somewhere, probably Larry Wall.

AUTHOR
======

   David Muir Sharnoff <muir@idiom.com>

Kill all instances of a process by pattern matching the command-line
********************************************************************

NAME
====

   killall - Kill all instances of a process by pattern matching the
command-line

SYNOPSIS
========

     use Proc::Killall;

     killall('HUP', 'xterm'); # SIGHUP all xterms
     killall('KILL', '^netscape$'); # SIGKILL to "netscape"

DESCRIPTION
===========

   This module provides one function, `killall()', which takes two
parameters: a signal name or number (see kill()) and a process pattern.
This pattern is matched against the process' command-line as the `ps'
command would show it (`ps' is not used internally, instead a package
called `Proc::ProcessTable' is used).

   `killall' searches the process table and sends that signal to all
processes which match the pattern. The return value is the number of
processes that were succesfully signaled. If any kills failed, the $!
variable will be set based on that last one that failed (even if a
successful kill happened afterward).

AUTHOR
======

   Written in 2000 by Aaron Sherman <ajs@ajs.com>

   `Proc::Killall' is copyright 2000 by Aaron Sherman, and may be
distributed under the same terms as Perl itself.

PREREQUISITES
=============

   `Proc::ProcessTable' is required for `Proc::Killall' to function.

SEE ALSO
========

   See Perl (perl.info), Perlfunc (perl.info),
Perlvar (perl.info), Proc/ProcessTable,

kill a list of pids, and all their sub-children
***********************************************

NAME
====

   Proc::Killfam - kill a list of pids, and all their sub-children

SYNOPSIS
========

     use Proc::Kilfam;
     killfam $signal, @pids;

DESCRIPTION
===========

   *killfam* accepts the same arguments as the Perl builtin kill command,
but, additionally, recursively searches the process table for children and
kills them as well.

EXAMPLE
=======

   *killfam 'TERM', ($pid1, $pid2, @more_pids)*;

KEYWORDS
========

   kill, signal

lock interface module
*********************

NAME
====

   Proc::Lock - lock interface module

SYNOPSIS
========

     use Proc::Lock;
     my $lock = new Proc::Lock ( ... );
     $lock->set ();
     die "locked" if $lock->isSet ();
     $lock->unset ();

DESCRIPTION
===========

     Generic lock module. You must subclass this class and overwrite set, unset, isSet and new (possible) for do your work

new
---

   Construct new lock object. You can setup parameters:

   ProcessName => $name of process for make lock file name Pid         =>
$ pid of process for make lock file name HostName    => $ name of host for
make lock file name Wait        => wait for lock is clean and continue
Timeout     => limit of time of wait of lock clean NoUnset     => not
unset lock at unset operation

     my $lock = new Proc::Lock... ( ProcessName => $0,
                                    Pid         => $$,
                                    Hostname    => gethostname(),
                                    Wait        => 1,
     				NoUnset     => 1,
                                    Timeout     => 30 );

     $lock->set || die "already runned";

set
---

   setup lock. Return true if success

unset
-----

   unset lock, return true if success

isSet
-----

   return true if lock is up

DESTROY
-------

   destroy lock object

log
---

   Return log object

_set _unset _isSet
------------------

   private methods, You must put your functionality to this methods.  The
real methods ( set, unset, isSet ) call this method.

lock interface module
*********************

NAME
====

   Proc::Lock::File - lock interface module

SYNOPSIS
========

     use Proc::Lock::File;
     my $lock = new Proc::Lock::File ( Directory => '/var/locks',
     				   ProcessName => 'locker' );
     $lock->set () || die "already locked";
     die "locked" if $lock->isSet ();
     $lock->unset ();

DESCRIPTION
===========

     Generic lock module. You must subclass this class and overwrite set, clear, isSet and new (possible) for do your work

new
---

   Construct new file lock object. Add Directory parameter to parent
constructor.

check whether a self process is already running
***********************************************

NAME
====

   Proc::PID_File - check whether a self process is already running

SYNOPSIS
========

     use Proc::PID_File;

     $Pid_File = Proc::PID_File->new(path=>"/var/run/mydaemon.pid");
     if (!$Pid_File->init)  { die "Can't open/create pid file: $!" }
     if ($Pid_File->active) { die "mydaemon is already running" }

     # go ahead, daemonize...

DESCRIPTION
===========

   A pid file is a file that contain, guess what, pid. Pids are written
down to files so that:

   * a program can know whether an instance of itself is currently running

   * other processes can know the pid of a running program

   This module can be used so that your script can do the former.

   If a pid file is created by the init() method, it will be automatically
deleted when the object is destroyed.

AUTHOR
======

   Copyright (C) 2000, Steven Haryanto <steven@haryan.to>. All rights
reserved.

   This module is free software; you may redistribute it and/or modify it
under the same terms as Perl itself.

HISTORY
=======

   000731 - first hack

Perl extension to access the unix process table
***********************************************

NAME
====

   Proc::ProcessTable - Perl extension to access the unix process table

SYNOPSIS
========

     use ProcessTable;

     $p = new Proc::ProcessTable( 'cache_ttys' => 1 );
     @fields = $p->fields;
     $ref = $p->table;

DESCRIPTION
===========

   Perl interface to the unix process table.

METHODS
=======

new
     Creates a new ProcessTable object. The constructor can take one flag:

     cache_ttys - causes the constructor to look for and use a file that
     caches a mapping of tty names to device numbers, and to create the
     file if it doesn't exist (this file is /tmp/TTYDEVS by default). This
     feature requires the Storable module.

fields
     Returns a list of the field names supported by the module on the
     current architecture.

table
     Reads the process table and returns a reference to an array of
     Proc::ProcessTable::Process objects. Attributes of a process object
     are returned by accessors named for the attribute; for example, to get
     the uid of a process just do:

     $process->uid

     The priority and pgrp methods also allow values to be set, since these
     are supported directly by internal perl functions.

EXAMPLES
========

     # A cheap and sleazy version of ps
     use Proc::ProcessTable;

     $FORMAT = "%-6s %-10s %-8s %-24s %s\n";
     $t = new Proc::ProcessTable;
     printf($FORMAT, "PID", "TTY", "STAT", "START", "COMMAND");
     foreach $p ( @{$t->table} ){
       printf($FORMAT,
              $p->pid,
              $p->ttydev,
              $p->state,
              scalar(localtime($p->start)),
              $p->cmndline);
     }

     # Dump all the information in the current process table
     use Proc::ProcessTable;

     $t = new Proc::ProcessTable;

     foreach $p (@{$t->table}) {
      print "--------------------------------\n";
      foreach $f ($t->fields){
        print $f, ":  ", $p->{$f}, "\n";
      }
     }

CAVEATS
=======

   Please see the file README in the distribution for a list of supported
operating systems. Please see the file PORTING for information on how to
help make this work on your OS.

AUTHOR
======

   D. Urist, durist@world.std.com

SEE ALSO
========

   Proc::ProcessTable::Process.pm, perl(1).

Perl process objects
********************

NAME
====

   Proc::ProcessTable::Process - Perl process objects

SYNOPSIS
========

     $process->kill(9);
     $process->priority(19);
     $process->pgrp(500);
     $uid = $process->uid;
     ...

DESCRIPTION
===========

   This is a stub module to provide OO process attribute access for
Proc::ProcessTable. Proc::ProcessTable::Process objects are constructed
directly by Proc::ProcessTable; there is no constructor method, only
accessors.

METHODS
=======

kill
     Sends a signal to the process; just an aesthetic wrapper for perl's
     kill. Takes the signal (name or number) as an argument. Returns number
     of processes signalled.

priority
     Get/set accessor; if called with a numeric argument, attempts to reset
     the process's priority to that number using perl's <B>setpriority
     function. Returns the process priority.

pgrp
     Same as above for the process group.

all other methods...
     are simple accessors that retrieve the process attributes for which
     they are named. Currently supported are:

          uid         UID of process
          gid         GID of process
          euid        effective UID of process           (Solaris only)
          egid        effective GID of process           (Solaris only)
          pid         process ID
          ppid        parent process ID
          spid        sprod ID                           (IRIX only)
          pgrp        process group
          sess        session ID
          cpuid       CPU ID of processor running on     (IRIX only)
          priority    priority of process
          ttynum      tty number of process
          flags       flags of process
          minflt      minor page faults                  (Linux only)
          cminflt     child minor page faults            (Linux only)
          majflt      major page faults                  (Linux only)
          cmajflt     child major page faults            (Linux only)
          utime       user mode time (1/100s of seconds) (Linux only)
          stime       kernel mode time                   (Linux only)
          cutime      child utime                        (Linux only)
          cstime      child stime                        (Linux only)
          time        user + system time
          ctime       child user + system time
          timensec    user + system nanoseconds part	 (Solaris only)
          ctimensec   child user + system nanoseconds    (Solaris only)
          qtime       cumulative cpu time                (IRIX only)
          size        virtual memory size (bytes)
          rss         resident set size (bytes)
          wchan       address of current system call
          fname       file name
          start       start time (seconds since the epoch)
          pctcpu      percent cpu used since process started
          state       state of process
          pctmem      percent memory
          cmndline    full command line of process
          ttydev      path of process's tty
          clname      scheduling class name              (IRIX only)

     See the "README.osname" files in the distribution for more up-to-date
     information.

AUTHOR
======

   D. Urist, durist@world.std.com

SEE ALSO
========

   Proc::ProcessTable.pm, perl(1).

popen() and " without calling the shell
***************************************

NAME
====

   Proc::SafePipe - popen() and " without calling the shell

SYNOPSIS
========

     $fh		= popen_noshell 'r', 'decrypt', $input;
     ($fh, $pid)	= popen_noshell 'w', 'ssh', $host, "cat >$output";

     $all_output	= backtick_noshell 'decrypt', $input;
     @lines	= backtick_noshell $cmd, @arg;

DESCRIPTION
===========

   These functions provide a simple way to read from or write to commands
which are run without being interpreted by the shell.  They croak if
there's a system failure, such as a failed fork.

popen_noshell mode command [*arg*]...
     This function is similar to popen() except that the command and its
     related *arg*s are never interpreted by a shell, they are passed to
     exec() as-is.  The mode argument must be `'r'' or 'w'.

     If called in an array context the return value is a list consisting of
     the filehandle and the PID of the child.  In a scalar context only the
     filehandle is returned.

backtick_noshell command [*arg*]...
     This function runs the given command with the given *arg*s and
     returns the output, like ```' does.  The difference is that the
     arguments are not filtered through a shell, they are exec()ed
     directly.

     The return value is either all the output from the command (if in a
     scalar context) or a list of the lines gathered from the command (in
     an array context).  The exit status of the command is in $?.

AUTHOR
======

   Roderick Schertler <`roderick@argon.org'>

interface scoreboard class
**************************

NAME
====

   Proc::Scoreboard - interface scoreboard class

SYNOPSIS
========

     use Proc::Scoreboard;
     my $scoreboard = new Proc::Scoreboard ( ... );
     my @idList = $scoreboard->list ();
     $scoreboard->add    ( $id );
     $scoreboard->delete ( $id );
     $scoreboard->modify ( $id, %hash );

DESCRIPTION
===========

   Intertface class for scoreboard.

new
---

   The constructor

add
---

     $sb->add ( $id );

   add new board with id $id to scoreboard

delete
------

     $sb->delete ( $id );

   delete board with id $id from scoreboard

modify
------

     $db->modify ( $id, %hash );

   modify board with id $id by passed parameters

list
----

   return list of all known scoreboards id's

interface scoreboard class
**************************

NAME
====

   Proc::Scoreboard - interface scoreboard class

SYNOPSIS
========

     use Proc::Scoreboard::Dir;
     my $scoreboard = new Proc::Scoreboard ( Directory => '/var/scoreboard' );
     my @idList = $scoreboard->list ();
     $scoreboard->add    ( $pid );
     $scoreboard->delete ( $pid );
     $scoreboard->modify ( $pid, %hash );

DESCRIPTION
===========

   Intertface class for scoreboard.

new
---

   The constructor

add
---

     $sb->add ( $id );

   add new board with id $id to scoreboard

delete
------

     $sb->delete ( $id );

   delete board with id $id from scoreboard

modify
------

     $db->modify ( $id, %hash );

   modify board with id $id by passed parameters

list
----

   return list of all known scoreboards id's

return short system calls with options
**************************************

NAME
====

   Proc::Short - return short system calls with options

SYNOPSIS
========

     use Proc::Short;

     $myproc = Proc::Short->new();  # create a new process object

     # settings below represent defaults
     $myproc->maxtime(300);         # set final timeout after 5 minutes
     $myproc->num_tries(5);         # try 5 times at most
     $myproc->time_per_try(30);     # time per try 30 sec
     $myproc->time_btw_tries(5);    # time between tries 5 sec

     # additional options
     $myproc->accept_no_error();    # Re-try if any STDERR output
     $myproc->pattern_stdout($pat); # require STDOUT to match regex $pat
     $myproc->pattern_stderr($pat); # require STDERR to match regex $pat
     $myproc->allow_shell(0);       # never use shell for operation
     $myproc->allow_shell(1);       # allowed to use shell for op

     $myproc->run("shell-command-line"); # Launch a shell process
     $myproc->run(sub { ... });          # Launch a perl subroutine
     $myproc->run(\&subroutine);         # Launch a perl subroutine

     Proc::Short::debug($level);         # Turn debug on

DESCRIPTION
===========

   The Proc::Short is intended to be an extension of the backticks
operator in PERL which incorporates a number of options, including
collecting STDOUT and STDERR separately - plus timeout and automatic
retries.  A new process object is created by

     $myproc = Proc::Short->new();

   The default will timeout after 30 seconds (timeout) for each attempt,
will try a process up to 10 times, with 5 seconds between each try.
Either shell-like command lines or references to perl subroutines can be
specified for launching a process in background.  A simple list process,
for example, can be started via the shell as

     ($out, $in) = $myproc->run("ls");

   or, as a perl subroutine, with

     $myproc->run(sub { return <*>; });

   The run Method will try to run the named process.  If the process times
out (after time_per_try seconds) or has a error defined as unacceptable,
it will wait (for time_btw_tries seconds) and try again.  This can repeat
until *maxtime* seconds or num_tries tries of the process to be run.

   The user can specify what constitutes an unacceptable error of STDOUT
or STDERR output - i.e. demanding a retry.  One common shorthand is to
have the run method retry if there is any return from STDERR.

     $myproc->accept_no_error();    # Re-try if any STDERR
     $myproc->pattern_stdout($pat); # require STDOUT to match regex $pat
     $myproc->pattern_stderr($pat); # require STDERR to match regex $pat

METHODS
=======

   The following methods are available:

new (Constructor)
     Create a new instance of this class by writing either

          $proc = new Proc::Short;   or   $proc = Proc::Short->new();

     The new method takes no arguments.

findexec
     Find where the named executables are in the path, or die if any are
     not found.

          ($fullpath) = $proc->needexec("ssh");

     The *needexec* method ...

unixhelp
     Try various ways to get help on a given executable.

          ($helpmsg) = $proc->unixhelp("ssh");

unixversion
     Try various ways to get version number on a given executable.

          ($helpmsg) = $proc->unixhelp("ssh");

run
     Run a new process and collect the standard output and standard error
     via separate pipes.  By default, it forks off another process and
     collects the output when it is done.  There is a time limit of

          ($out, $err, $status) = $proc->run("program-name");

     There are a number of options.  You can start execution of an
     independent Perl function (like "eval" except with timeout, retries,
     etc.).  Simply provide the function reference like

          ($out, $err, $status) = $proc->run(\&perl_function);

     or supply an unnamed subroutine:

          ($out, $err, $status) = $proc->run( sub { sleep(1) } );

     The run Method returns after the the function finishes, one way or
     another.

num_tries Return or set the maximum number of tries the run method will  attempt an operation if there are unallowed errors.  Default is 5.  =cut
time_per_try Return or set the maximum time in seconds for each attempt which  run makes of an operation.  Multiple tries in case of error  can go longer than this.  Default is 30 seconds.  =cut
time_btw_tries Return or set the time in seconds between attempted operations  in case of unacceptable error.  Default is 5 seconds.   =cut
     sub AUTOLOAD {     my $self= shift;     my $type= ref($self) or
     croak("$self is not an object");     my $name= $AUTOLOAD;     $name
     =~ s/.*://; # strip qualified call, i.e. Geometry::that     unless
     (exists $self->{$name}) { 	croak("Can't access `$name' field
     in object of class $type");     }     if (@_) { 	my $val= @_; 	if
     (defined($intdefaults{$name}) and not ($val =~ /\d+/)) {
     croak "Invalid $name initializer $val"; 	} 	$self->{$name}=
     $val;     }     return $self->{$name}; }

     ######################################################################
     # Internal debug print function
     ######################################################################
     sub _dprt {     return unless $Debug;     if (ref($_[0])) {
     warn ref(shift()), "> @_\n";     } else { 	warn "> @_\n";     }
     }

     ######################################################################
     # This is for getting the WNOHANG constant of the system: a magic #
     flag for the "waitpid" command which guards against certain errors #
     which could hang the system.  # # Since the waitpid(-1, &WNOHANG)
     command isn't supported on all Unix # systems, and we still want
     Proc::Short to run on every system, we # have to quietly perform some
     tests to figure out if - or if not.  # The function returns the
     constant, or undef if it's not available.
     ######################################################################
     sub _get_system_nohang {     my $nohang;     open(SAVEERR,
     ">&STDERR");     # If the system doesn't even know /dev/null, forget
     about it.      open(STDERR, ">/dev/null") || return undef;     #
     Close stderr, since some weirdo POSIX modules write nasty     # error
     messages     close(STDERR);     # Check for the constant     eval
     'use POSIX ":sys_wait_h"; $nohang = &WNOHANG;';     # Re-open STDERR
       open(STDERR, ">&SAVEERR");     close(SAVEERR);     # If there was
     an error, return undef     return undef if $@;     return $nohang; }

     1;

     __END__

NOTE
====

   This is an attempt to duplicate the ease of use of backticks (") while
allowing additional options like timeout or re-tries in case of error.

Requirements
============

   I'd recommend using at least perl 5.003 - if you don't have it, this is
the time to upgrade! Get 5.005_02 or better.

AUTHORS
=======

   John Hanju Kim <jhkim@fnal.gov>

launch and control background processes
***************************************

NAME
====

   Proc::Simple - launch and control background processes

SYNOPSIS
========

     use Proc::Simple;

     $myproc = Proc::Simple->new();        # Create a new process object

     $myproc->start("shell-command-line"); # Launch a shell process
     $myproc->start(sub { ... });          # Launch a perl subroutine
     $myproc->start(\&subroutine);         # Launch a perl subroutine

     $running = $myproc->poll();           # Poll Running Process

     $proc->kill_on_destroy(1);            # Set kill on destroy
     $proc->signal_on_destroy("KILL");     # Specify signal to be sent
                                           # on destroy

     $myproc->kill();                      # Kill Process (SIGTERM)

     $myproc->kill("SIGUSR1");             # Send specified signal

     $myproc->exit_status();               # Return exit status of process

     Proc::Simple::debug($level);          # Turn debug on

DESCRIPTION
===========

   The Proc::Simple package provides objects that model real-life
processes from a user's point of view. A new process object is created by

     $myproc = Proc::Simple->new();

   Either shell-like command lines or references to perl subroutines can
be specified for launching a process in background.  A 10-second sleep
process, for example, can be started via the shell as

     $myproc->start("sleep 10");

   or, as a perl subroutine, with

     $myproc->start(sub { sleep(10); });

   The start Method returns immediately after starting the specified
process in background, i.e. non-blocking mode.  It returns 1 if the
process has been launched sucessfully and 0 if not.

   The poll method checks if the process is still running

     $running = $myproc->poll();

   and returns 1 if it is, 0 if it's not. Finally,

     $myproc->kill();

   terminates the process by sending it the SIGTERM signal. As an option,
another signal can be specified.

     $myproc->kill("SIGUSR1");

   sends the SIGUSR1 signal to the running process. kill returns 1 if it
succeeds in sending the signal, 0 if it doesn't.

   The methods are discussed in more detail in the next section.

   A destructor is provided so that the forked processes can be sent a
signal automatically should the perl object be destroyed or if the perl
process exits. By default this behaviour is turned off (see the
kill_on_destroy and signal_on_destroy methods).

METHODS
=======

   The following methods are available:

new (Constructor)
     Create a new instance of this class by writing

          $proc = new Proc::Simple;

     or

          $proc = Proc::Simple->new();

     It takes no arguments.

start
     Launch a new process. For an external program to be started like from
     the shell, call

          $status = $proc->start("program-name");

     If, on the other hand, you want to start execution of a Perl function
     in the background, simply provide the function reference like

          $status = $proc->start(\&perl_function);

     or supply an unnamed subroutine:

          $status = $proc->start( sub { sleep(1) } );

     The start Method returns immediately after starting the specified
     process in background, i.e. non-blocking mode.  It returns 1 if the
     process has been launched sucessfully and 0 if not.

poll
     The poll method checks if the process is still running

          $running = $myproc->poll();

     and returns 1 if it is, 0 if it's not.

kill
     The kill() method:

          $myproc->kill();

     terminates the process by sending it the SIGTERM signal. As an
     option, another signal can be specified.

          $myproc->kill("SIGUSR1");

     sends the SIGUSR1 signal to the running process. kill returns 1 if it
     succeeds in sending the signal, 0 if it doesn't.

kill_on_destroy
     Set a flag to determine whether the process attached to this object
     should be killed when the object is destroyed. By default, this flag
     is set to false.  The current value is returned.

          $current = $proc->kill_on_destroy;
          $proc->kill_on_destroy(1); # Set flag to true
          $proc->kill_on_destroy(0); # Set flag to false

signal_on_destroy
     Method to set the signal that will be sent to the process when the
     object is destroyed (Assuming kill_on_destroy is true). Returns the
     current setting.

          $current = $proc->signal_on_destroy;
          $proc->signal_on_destroy("KILL");

pid
     Returns the pid of the forked process associated with this object

          $pid = $proc->pid;

DESTROY (Destructor)
     Object destructor. This method is called when the object is destroyed
     (eg with "undef" or on exiting perl). If kill_on_destroy is true the
     process associated with the object is sent the signal_on_destroy
     signal (SIGTERM if undefined).

exit_status
     Returns the exit status of the process as the $! variable indicates.
     If the process is still running, undef is returned.

debug
     Switches debug messages on and off - Proc::Simple::debug(1) switches
     them on, Proc::Simple::debug(0) keeps Proc::Simple quiet.

NOTE
====

   Please keep in mind that there is no guarantee that the SIGTERM signal
really terminates a process. Processes can have signal handlers defined
that avoid the shutdown.  If in doubt, whether a process still exists,
check it repeatedly with the poll routine after sending the signal.

Requirements
============

   I'd recommend using perl 5.6.0 although it might also run with 5.003
also - if you don't have it, this is the time to upgrade!

AUTHORS
=======

   Michael Schilli <michael@perlmeister.com>

   Tim Jenness  <t.jenness@jach.hawaii.edu>    did
kill_on_destroy/signal_on_destroy/pid

   Mark R. Southern <mark_southern@merck.com>    worked on EXIT_STATUS
tracking

Spawn processes but report exec() errors
****************************************

NAME
====

   Proc::SyncExec - Spawn processes but report exec() errors

SYNOPSIS
========

     # Normal-looking piped opens which properly report exec() errors in $!:
     sync_open WRITER_FH, "|command -with args" or die $!;
     sync_open READER_FH, "command -with args|" or die $!;

     # Synchronized fork/exec which reports exec errors in $!:
     $pid = sync_exec $command, @arg;
     $pid = sync_exec $code_ref, @command;	# run code after fork in kid

     # fork() which retries if it fails, then croaks() if it still fails.
     $pid = fork_retry;
     $pid = fork_retry 100;		# retry 100 times rather than 5
     $pid = fork_retry 100, 2;		# sleep 2 rather than 5 seconds between

     # A couple of interfaces similar to sync_open() but which let you
     # avoid the shell:
     $pid = sync_fhpopen_noshell READERFH, 'r', @command;
     $pid = sync_fhpopen_noshell WRITERFH, 'w', @command;
     $fh = sync_popen_noshell 'r', @command_which_outputs;
     $fh = sync_popen_noshell 'w', @command_which_inputs;
     ($fh, $pid) = sync_popen_noshell 'r', @command_which_outputs;
     ($fh , $pid)= sync_popen_noshell 'w', @command_which_inputs;

DESCRIPTION
===========

   This module contains functions for synchronized process spawning with
full error return.  If the child's exec() call fails the reason for the
failure is reported back to the parent.

   These functions will croak() if they encounter an unexpected system
error, such as a pipe() failure or a repeated fork() failure.

   Nothing is exported by default.

fork_retry [*max-retries* [*sleep-between*]]
     This function runs fork() until it succeeds or until *max-retries*
     (default 5) attempts have been made, sleeping *sleep-between* seconds
     (default 5) between attempts.  If the last fork() fails fork_retry
     croak()s.

sync_exec [code] command...
     This function is similar to a fork()/exec() sequence but with a few
     twists.

     sync_exec does not return until after the fork()ed child has already
     performed its exec().  The synchronization this provides is useful in
     some unusual circumstances.

     Normally the pid of the child process is returned.  However, if the
     child fails its exec() sync_exec returns undef and sets $! to the
     reason for the child's exec() failure.

     Since the @cmd array is passed directly to Perl's exec() Perl might
     choose to invoke the command via the shell if @cmd contains only one
     element and it looks like it needs a shell to interpret it.  If this
     happens the return value of sync_exec only indicates whether the
     exec() of the shell worked.

     The optional initial code argument must be a code reference.  If it
     is present it is run in the child just before exec() is called.  You
     can use this to set up redirections or whatever.  If code returns
     false no exec is performed, instead a failure is returned using the
     current $!  value (or EINTR if $! is 0).

     If the fork() fails or if there is some other unexpected system error
     sync_exec croak()s rather than returning.

sync_fhpopen_noshell fh type cmd [*arg*]...
     This is a popen() but it never invokes the shell and it uses
     sync_exec() under the covers.  See `' in this node.

     The type is either `'r'' to read from the process or 'w' to write to
     it.

     The return value is the pid of the forked process.

sync_popen_noshell type cmd *arg*...
     This is like sync_fhpopen_noshell, but you don't have to supply the
     filehandle.

     If called in an array context the return value is a list consisting of
     the filehandle and the PID of the child.  In a scalar context only the
     filehandle is returned.

sync_open fh [*open-spec*]
     This is like a Perl open() except that if a pipe is involved and the
     implied exec() fails sync_open() fails with $! set appropriately.  See
     `' in this node.

     Like sync_exec, sync_open croak()s if there is an unexpected system
     error (such as a failed pipe()).

     Also like sync_exec, if you use a command which Perl needs to use the
     shell to interpret you'll only know if the exec of the shell worked.
     Use sync_fhpopen_noshell or sync_exec to be sure that this doesn't
     happen.

AUTHOR
======

   Roderick Schertler <`roderick@argon.org'>

SEE ALSO
========

   perl(1).

Interpret and act on wait() status values
*****************************************

NAME
====

   Proc::WaitStat - Interpret and act on wait() status values

SYNOPSIS
========

     $description = waitstat $?;
     exit waitstat_reuse $?;
     waitstat_die $?, 'program-name';
     close_die COMMAND, 'program-name';

DESCRIPTION
===========

   This module contains functions for interpreting and acting on wait
status values.

   Nothing is exported by default.

waitstat *wait-status*
     Returns a string representation of wait() status value *wait-status*.
     Values returned are like `"0"' and `"64"' and `"killed (SIGHUP)"'.

     This function is prototyped to take a single scalar argument.

waitstat_reuse *wait-status*
     Turn *wait-status* into a value which can be passed to exit, converted
     in the same manner the shell uses.  If *wait-status* indicates a
     normal exit, return the exit value.  If *wait-status* instead
     indicates death by signal, return 128 plus the signal number.

     This function is prototyped to take a single scalar argument.

waitstat_die *wait-status* *program-name*
     die() if *wait-status* is non-zero (mentioning *program-name* as the
     source of the error).

     This function is prototyped to take two scalar arguments.

close_die filehandle name
     Close filehandle, if that fails die() with an appropriate message
     which refers to name.  This handles failed closings of both programs
     and files properly.

     This function is prototyped to take a filehandle (actually, a glob
     ref) and a scalar.

EXAMPLES
========

     close SENDMAIL;
     exit if $? == 0;
     log "sendmail failure: ", waitstat $?;
     exit EX_TEMPFAIL;

     $pid == waitpid $pid, 0 or croak "Failed to reap $pid: $!";
     exit waitstat_reuse $?;

     $output = `some-program -with args`;
     waitstat_die $?, 'some-program';
     print "Output from some-process:\n", $output;

     open PROGRAM, '| post-processor' or die "Can't fork: $!";
     while (<IN>) {
     	print PROGRAM pre_process $_
     	    or die "Error writing to post-processor: $!";
     }
     # This handles both flush failures at close time and a non-zero exit
     # from the subprocess.
     close_die PROGRAM, 'post-processor';

AUTHOR
======

   Roderick Schertler <`roderick@argon.org'>

SEE ALSO
========

   perl(1), IPC::Signal(3pm).

graphical filesystem / project tree for software developers and webmasters
**************************************************************************

NAME
====

   Project::Tree - graphical filesystem / project tree for software
developers and webmasters

SYNOPSIS
========

     use Project::Tree;
     gui;

     or

     shell# perl -MProject::Tree -e gui

     or

     shell# ptree

INSTALLATION
============

   First you have to install Kenneth Albanowski's Gtk module (Version
0.500 or newer) and Gurusamy Sarathy's Data::Dumper.  The rest is business
as usual...

     perl Makefile.PL
     make
     make test
     make install

DESCRIPTION
===========

   This module is for software developers who have to maintain a lot of
files in a software project, e.g. a website with many HTML and/or perl
embedded dynamic pages and CGI scripts.

   Project::Tree is Gtk (Gimp/GNU Toolkit) based and creates a tree view
of your software projects, scanning recursevely their top level
directories using user configurable regex filters to include/exclude files
and subdirectories. The actions for the file items (e.g. start an editor
by double click) are configurable in the same way.

   The module additionally mantains a list of files for quick access.
Those files are shown in an extra alphabetically ordered list. A single
click on the list item triggers the file action.

   Each project is represented by a simple identifier which will be the
top node of the tree view for this project.

CONFIGURATION
=============

   This version of Project::Tree requires a configuration directory in the
home directory of the user. This is the structure of the directory:

     $HOME/.ptree/open_projects	list of currently open projects
     $HOME/.ptree/quickaccess	list of files for quick access
     $HOME/.ptree/projects/$PROJECT	configuration for each project

   Part of this distribution is a directory called 'example-configuration'.
You will find all these files there as a starting point for your private
configuration.

   All configuration files are in Data::Dumper format, so they are even
machine and human readable (Data::Dumper is a great tool for this purpose).

   This release of Project::Tree has no GUI for editing its configuration
files. So you have to set them up by hand (this will change in future
releases). Only the quickaccess file is actually generated by the program,
but this version has no GUI function to remove items from the quickaccess
list, so you have to do this by hand (or add this functionality and send me
the patch ;)

open_projects
-------------

   This file contains the following definition of currently open projects.

     $PTREE_OPEN_PROJECTS_LREF = [
     	'project1', .., 'projectN'
     ];

   This is a simple list of the project identifiers.

quickaccess
-----------

   This file lists the items of the quick access list.

     $PTREE_QUICK_ACCESS_LREF = [
       {
         'name'  => '/full/filename',	# path to file
         'exec'  => 'nc -noask %s',		# file action
         'color' => 'black'			# item color
       },
       ...
     ];

projects/$PROJECT
-----------------

   This is for project specific configuration. The file has the same name
as the project and must be present for each open project.

     $PTREE_PROJECT_DEFINITION_HREF = {

     desc => 'CGI Perl Preprocessor',		# description
     root_dir => '/home/joern/projects/CIPP',	# root path

     dir_include => [	# list of regexs for dir inclusion
     	        undef		# undef means "include all"
     	    ],

     dir_exclude => [	# list of regexs for dir exclusion
         'CVS$',		# undef means "exclude nothing"
     		...
     ],

     file_include => [
         {
             re => '\\.(cipp|pl|pm)$',	# regex for file incl.
             color => 'red',		# color of this files
             exec => 'nc'		# action of this files
     		    				# (defined below)
         },
         {
             re => undef,		# undef = all files
             color => 'black',		# color
             exec => 'nc'		# action (defined below)
         },
     		...

     ],

     file_exclude => [
         '.bck$',		# regex for file exclusion
         '.pdf$',
     		...
     ],

     exec => {			# definition of file actions
         nc => 'nc -noask %s'	# system call for actions 'nc'
     }
     	};

   The include regexes are computed before the exclude regexes. So the set
of included objects will be reduced by the exclude filters.

BUGS / TODO
===========

   This version of the module is based on my first Gtk hack. So the design
is slightly messed up (e.g. use of  global variables at some points). I
want to clean up this in future releases. My main concern is to realize a
pure object oriented interface which lets you inherit from this class to
add extra funtionality easily.

   I release this software at this time to evaluate if such a thing is of
interest for the public. For me this tool is very interesting, because I
want to pick up my files in a second instead of crawling by hand through
my filesystems for hours.

   So I'm very happy about every response of everyone who either
downloaded or even use this module. Don't hesitate to send me an email!

THANKS TO
=========

   Kenneth Albanowski for his great job: the Gtk module!

AUTHOR
======

   Joern Reder, joern@dimedis.de

COPYRIGHT
=========

   Copyright 1999 Joern Reder, All Rights Reserved

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1), Gtk (3pm).

package for Psh builtins, possibly loading them as needed
*********************************************************

NAME
====

   Psh::Builtins - package for Psh builtins, possibly loading them as
needed

SYNOPSIS
========

     use Psh::Builtins;

DESCRIPTION
===========

   Psh::Builtins currently contains only the hardcoded builtins of Perl
Shell, but may later on be extended to load them on the fly from separate
modules.

Builtins
--------

   * `setenv NAME [=] VALUE'

     Sets the environment variable NAME to VALUE.

   * `delenv NAME [NAME2 NAME3 ...]'

     Deletes the names environment variables.

   * `export VAR [=VALUE]'

     Just like setenv, below, except that it also ties the variable (in the
     Perl sense) so that subsequent changes to the variable automatically
     affect the environment. Variables who are lists and appear in
     `%Psh::array_exports' will also by tied to the array of the same name.
     Note that the variable must be specified without any Perl specifier
     like `$' or `@'.

   * `cd DIR'

     Change the working directory to DIR or home if DIR is not specified.
     The special DIR "-" is interpreted as "return to the previous
     directory".

   * `alias [NAME [=] REPLACEMENT]'

     Add `*NAME*' as a built-in so that NAME <REST_OF_LINE> will execute
     exactly as if REPLACEMENT <REST_OF_LINE> had been entered. For
     example, one can execute `alias ls ls -F' to always supply the -F
     option to "ls". Note the built-in is defined to avoid recursion here.

     With no arguments, prints out a list of the current aliases.  With
     only the `*NAME*' argument, prints out a definition of the alias with
     that name.

   * `unalias NAME | -a | all]'

     Removes the alias with name <`*NAME*' or all aliases if either <`*-a*'
     (for bash compatibility) or <`*all*' is specified.

AUTHOR
======

   the Psh team

SEE ALSO
========

   `psh' in this node

containing the completion routines of psh. Currently works with Term::ReadLine::Gnu and Term::ReadLine::Perl.
*************************************************************************************************************

NAME
====

   Psh::Completion - containing the completion routines of psh.  Currently
works with Term::ReadLine::Gnu and Term::ReadLine::Perl.

SYNOPSIS
========

DESCRIPTION
===========

AUTHOR
======

   Markus Peter, warp@spin.de Hiroo Hayashi, hiroo.hayashi@computer.org

SEE ALSO
========

Data structure representing a shell job
***************************************

NAME
====

   Psh::Job - Data structure representing a shell job

SYNOPSIS
========

     use Psh::Job;

     $joblist= new Psh::Joblist();

     $job= $joblist->create_job($pid, $command);

     $job->continue; # send SIGCONT to the job

     $job->{pid}; # to access the PID of the job
     $job->{call}; # to access the (command) name of the job
     $job->{running}; # to check wether the job is running

DESCRIPTION
===========

   This class is to be used in conjunction with Psh::Joblist

AUTHOR
======

   Markus Peter, warp@spin.de

SEE ALSO
========

   Psh::Joblist(3).

A data structure suitable for handling job lists like bash's
************************************************************

NAME
====

   Psh::Joblist - A data structure suitable for handling job lists like
bash's

SYNOPSIS
========

     use Psh::Joblist;

     $joblist= new Psh::Joblist();

     $job = $joblist->create_job($pid,$displayed_command);

     $joblist->delete_job($pid);

     $job = $joblist->get_job($pid);

     $flag = $joblist->job_exists($pid);

     $index = $joblist->get_job_number($pid);

     $job = $joblist->find_job();
     $job = $joblist->find_job($index);

     $joblist->enumerate();
     while( $job=$joblist->each()) { ... }

DESCRIPTION
===========

   Read the source ;-)

AUTHOR
======

   Markus Peter (warp@spin.de)

SEE ALSO
========

   Psh::Job(3)

containing base code for I18N
*****************************

NAME
====

   Psh::Locale::Base - containing base code for I18N

SYNOPSIS
========

DESCRIPTION
===========

AUTHOR
======

   Markus Peter, warp@spin.de

SEE ALSO
========

containing translations for default locale
******************************************

NAME
====

   Psh::Locale::Default - containing translations for default locale

SYNOPSIS
========

     use Psh::Locale::Default;

DESCRIPTION
===========

   This module contains defaults for all of the internationalized strings
in the Perl Shell.

Translating Signal Names
------------------------

   The text below can be used with Babelfish to generate the signal
descriptions for translations.

     tty output

     tty input

     killed

     floating point exception

     segmentation fault

     broken pipe

     bus error

     aborted

     illegal instruction

     stop typed at TTY

     interrupt character typed

     =head2 Translating Messages

     The text below was used with Babelfish to generate the messages
     for translations.

     done.

     terminated.

     stopped.

     restart.

     foreground.

     Error: "Foo" failed.

     Simulating option "W" and "strict".

     Permission denied.

     No such directory.

     No such builtin.

     Interrupted!

     "Readline" did not start up properly.

     No "Readline" module available. Please install "Term::ReadLine::Perl".

     "%1" is not an alias.

     Using "Readline": "%1", with features "X" and "Y".

     Your system does not support job control.

     "psh" supports the following built-in commands.

     Sorry, help for builtin %1 is not available.

     Warning: Expansion of "%1" in prompting message
     yielded text containing "%2" .
     Removing escape sequence from substitution.

     Warning: "Foo" contains unknown escape sequence.

     "libwin32" required (available as "CPAN" bundle or with "ActivePerl" distribution.

AUTHOR
======

   Markus Peter, warp@spin.de

SEE ALSO
========

   Psh::Locale::*

containing translations for French locale
*****************************************

NAME
====

   Psh::Locale::French - containing translations for French locale

SYNOPSIS
========

DESCRIPTION
===========

AUTHOR
======

   Gregor N. Purdy, gregor@focusresearch.com

SEE ALSO
========

containing translations for German locales
******************************************

NAME
====

   Psh::Locale::German - containing translations for German locales

SYNOPSIS
========

DESCRIPTION
===========

AUTHOR
======

   Markus Peter, warp@spin.de

SEE ALSO
========

containing translations for Italian locale
******************************************

NAME
====

   Psh::Locale::Italian - containing translations for Italian locale

SYNOPSIS
========

DESCRIPTION
===========

AUTHOR
======

   Gregor N. Purdy, gregor@focusresearch.com

SEE ALSO
========

containing translations for Portuguese locale
*********************************************

NAME
====

   Psh::Locale::Portuguese - containing translations for Portuguese locale

SYNOPSIS
========

DESCRIPTION
===========

AUTHOR
======

   Gregor N. Purdy, gregor@focusresearch.om

SEE ALSO
========

containing translations for Spanish locale
******************************************

NAME
====

   Psh::Locale::Spanish - containing translations for Spanish locale

SYNOPSIS
========

DESCRIPTION
===========

AUTHOR
======

   Gregor N. Purdy, gregor@focusresearch.com

SEE ALSO
========

Wrapper class for OS dependant stuff
************************************

NAME
====

   Psh::OS - Wrapper class for OS dependant stuff

SYNOPSIS
========

     use Psh::OS;

DESCRIPTION
===========

   TBD

AUTHOR
======

   Markus Peter, warp@spin.de

SEE ALSO
========

Contains Mac specific code
**************************

NAME
====

   Psh::OS::Mac - Contains Mac specific code

SYNOPSIS
========

     use Psh::OS;

DESCRIPTION
===========

   TBD

AUTHOR
======

   blaaa

SEE ALSO
========

contains Unix specific code
***************************

NAME
====

   Psh::OS::Unix - contains Unix specific code

SYNOPSIS
========

     use Psh::OS::Unix;

DESCRIPTION
===========

   Implements the Unix specific parts of Psh::OS

AUTHOR
======

   various

Contains Windows specific code
******************************

NAME
====

   Psh::OS::Win - Contains Windows specific code

SYNOPSIS
========

     use Psh::OS::Win32;

DESCRIPTION
===========

   An implementation of Psh::OS for Win32 systems. This module requires
libwin32.

AUTHOR
======

   Markus Peter, warp@spin.de Omer Shenker, oshenker@iname.com

SEE ALSO
========

containing the programmable completion routines of psh.
*******************************************************

NAME
====

   Psh::PCompletion - containing the programmable completion routines of
psh.

SYNOPSIS
========

DESCRIPTION
===========

   This module provides the programmable completion function almost
compatible with one of bash-2.04 and/or later.  The following document is
based on the texinfo file of bash-2.04-beta5.

Programmable Completion =======================
-----------------------------------------------

   When word completion is attempted for an argument to a command for
which a completion specification (a COMPSPEC) has been defined using the
complete builtin (See `Programmable Completion Builtins' in this node.),
the programmable completion facilities are invoked.

   First, the command name is identified.  If a compspec has been defined
for that command, the compspec is used to generate the list of possible
completions for the word.  If the command word is a full pathname, a
compspec for the full pathname is searched for first.  If no compspec is
found for the full pathname, an attempt is made to find a compspec for the
portion following the final slash.

   Once a compspec has been found, it is used to generate the list of
matching words.  If a compspec is not found, the default Psh completion
described above (Where is it described?) is performed.

   First, the actions specified by the compspec are used.  Only matches
which are prefixed by the word being completed are returned.  When the -f
or -d option is used for filename or directory name completion, the shell
variable *FIGNORE* is used to filter the matches.  See `ENVIRONMENT
VARIABLES' in this node for a description of *FIGNORE*.

   Any completions specified by a filename expansion pattern to the -G
option are generated next.  The words generated by the pattern need not
match the word being completed.  The *GLOBIGNORE* shell variable is not
used to filter the matches, but the *FIGNORE* shell variable is used.

   Next, the string specified as the argument to the -W option is
considered.  The string is first split using the characters in the *IFS*
special variable as delimiters.  Shell quoting is honored.  Each word is
then expanded using brace expansion, tilde expansion, parameter and
variable expansion, command substitution, arithmetic expansion, and
pathname expansion, as described above (Where is it described?).  The
results are split using the rules described above (Where is it
described?).  No filtering against the word being completed is performed.

   After these matches have been generated, any shell function or command
specified with the -F and -C options is invoked.  When the function or
command is invoked, the first argument is the word being completed, the
second argument is the current command line, the third argument is the
index of the current cursor position relative to the beginning of the
current command line, and the fourth argument is the name of the command
whose arguments are being completed.  If the current cursor position is at
the end of the current command, the value of the third argument is equal
to the length of the second argument string.

   No filtering of the generated completions against the word being
completed is performed; the function or command has complete freedom in
generating the matches.

   Any function specified with -F is invoked first.  The function may use
any of the shell facilities, including the compgen builtin described below
(See `Programmable Completion Builtins' in this node.), to generate the
matches.  It returns a array including the possible completions.  For
example;

     sub _foo_func {
         my ($cur, $line, $start, $cmd) = @_;
         ...
         return @possible_completions;
     }
     complete -F _foo_func bar

   Next, any command specified with the -C option is invoked in an
environment equivalent to command substitution.  It should print a list of
completions, one per line, to the standard output.  Backslash may be used
to escape a newline, if necessary.

   After all of the possible completions are generated, any filter
specified with the -X option is applied to the list.  The filter is a
pattern as used for pathname expansion; a & in the pattern is replaced
with the text of the word being completed.  A literal & may be escaped
with a backslash; the backslash is removed before attempting a match.  Any
completion that matches the pattern will be removed from the list.  A
leading ! negates the pattern; in this case any completion not matching
the pattern will be removed.

   Finally, any prefix and suffix specified with the -P and -S options are
added to each member of the completion list, and the result is returned to
the Readline completion code as the list of possible completions.

   If a compspec is found, whatever it generates is returned to the
completion code as the full set of possible completions.  The default Bash
completions are not attempted, and the Readline default of filename
completion is disabled.

Programmable Completion Builtins ================================
-----------------------------------------------------------------

   A builtin commands complete and a builtin Perl function compgen are
available to manipulate the programmable completion facilities.

compgen
          compgen [OPTION] [WORD]

     Generate possible completion matches for *WORD* according to the
     OPTIONs, which may be any option accepted by the complete builtin
     with the exception of -p and -r, and write the matches to the
     standard output.  When using the -F or -C options, the various shell
     variables set by the programmable completion facilities, while
     available, will not have useful values.

     The matches will be generated in the same way as if the programmable
     completion code had generated them directly from a completion
     specification with the same flags.  If *WORD* is specified, only
     those completions matching *WORD* will be displayed.

     The return value is true unless an invalid option is supplied, or no
     matches were generated.

complete
          complete [-abcdefjkvu] [-A ACTION] [-G GLOBPAT] [-W WORDLIST]
          	 [-P PREFIX] [-S SUFFIX] [-X FILTERPAT] [-x FILTERPAT]
          	 [-F FUNCTION] [-C COMMAND] NAME [NAME ...]
          complete -pr [NAME ...]

     Specify how arguments to each NAME should be completed.  If the -p
     option is supplied, or if no options are supplied, existing
     completion specifications are printed in a way that allows them to be
     reused as input.  The -r option removes a completion specification
     for each NAME, or, if no NAMEs are supplied, all completion
     specifications.

     The process of applying these completion specifications when word
     completion is attempted is described above (See `Programmable
     Completion' in this node.).

     Other options, if specified, have the following meanings.  The
     arguments to the -G, -W, and -X options (and, if necessary, the -P
     and -S options) should be quoted to protect them from expansion
     before the complete builtin is invoked.

    -A ACTION
          The ACTION may be one of the following to generate a list of
          possible completions:

         alias
               Alias names.  May also be specified as -a.

         arrayvar
               Names of Perl array variable names.

         binding
               Readline key binding names.

         builtin
               Names of shell builtin commands.  May also be specified as
               -b.

         command
               Command names.  May also be specified as -c.

         directory
               Directory names.  May also be specified as -d.

         disabled
               Names of disabled shell builtins (not implemented yet.).

         enabled
               Names of enabled shell builtins (not implemented yet.).

         export
               Names of exported shell variables.  May also be specified
               as -e.

         file
               File names.  May also be specified as -f.

         function
               Names of Perl functions.

         hashvar
               Names of Perl hash variable names.

         helptopic
               Help topics as accepted by the `help' builtin.

         hostname
               Hostnames.

         job
               Job names, if job control is active.  May also be specified
               as -j.

         keyword
               Shell reserved words.  May also be specified as -k.

         running
               Names of running jobs, if job control is active.

         setopt
               Valid arguments for the -o option to the set builtin (not
               implemented yet.).

         shopt
               Shell option names as accepted by the shopt builtin (not
               implemented yet.).

         signal
               Signal names.

         stopped
               Names of stopped jobs, if job control is active.

         user
               User names.  May also be specified as -u.

         variable
               Names of all Perl variables.  May also be specified as -v.

    -G *GLOBPAT*
          The filename expansion pattern *GLOBPAT* is expanded to generate
          the possible completions.

    -W *WORDLIST*
          The *WORDLIST* is split using the characters in the *IFS* special
          variable as delimiters, and each resultant word is expanded.  The
          possible completions are the resultant list.

    -C *COMMAND*
          *COMMAND* is executed in a subshell environment, and its output
          is used as the possible completions.

    -F FUNCTION
          The shell function FUNCTION is executed in the current Perl shell
          environment.  When it finishes, the possible completions are
          retrieved from the array which the function returns.

    -X *FILTERPAT*
          *FILTERPAT* is a pattern as used for filename expansion.  It is
          applied to the list of possible completions generated by the
          preceding options and arguments, and each completion matching
          *FILTERPAT* is removed from the list.  A leading ! in
          *FILTERPAT* negates the pattern; in this case, any completion
          not matching *FILTERPAT* is removed.

    -x *FILTERPAT*
          Similar to the -X option above, except it is applied to only
          filenames not to directory names etc.

    -P PREFIX
          PREFIX is added at the beginning of each possible completion
          after all other options have been applied.

    -S *SUFFIX*
          *SUFFIX* is appended to each possible completion after all other
          options have been applied.

     The return value is true unless an invalid option is supplied, an
     option other than -p or -r is supplied without a NAME argument, an
     attempt is made to remove a completion specification for a NAME for
     which no specification exists, or an error occurs adding a completion
     specification.

AUTHOR
======

   Hiroo Hayashi, hiroo.hayashi@computer.org

SEE ALSO
========

   info manual of bash-2.04 and/or later

EXAMPLE
=======

   `complete_example' in the Psh distribution shows you many examples of
the usage of programmable completion.

     source complete-examples

bla
***

NAME
====

   Psh::Parser - bla

SYNOPSIS
========

DESCRIPTION
===========

AUTHOR
======

SEE ALSO
========

package containing perl evaluation codes
****************************************

NAME
====

   Psh::PerlEval - package containing perl evaluation codes

SYNOPSIS
========

     use Psh::PerlEval;

DESCRIPTION
===========

   TBD

AUTHOR
======

   Glen Whitney I think..

SEE ALSO
========

Containing certain Psh utility functions
****************************************

NAME
====

   Psh::Utils - Containing certain Psh utility functions

SYNOPSIS
========

     use Psh::Utils (:all);

DESCRIPTION
===========

   TBD

AUTHOR
======

   blaaa

SEE ALSO
========

class for searching National Library of Medicine
************************************************

NAME
====

   WWW::Search::PubMed - class for searching National Library of Medicine

SYNOPSIS
========

   use WWW::Search;

   $query = "lung cancer treatment"; $search = new WWW::Search('PubMed');
$search->native_query(WWW::Search::escape_query($query));
$search->maximum_to_retrieve(100); while (my $result =
$search->next_result()) {

   $url = $result->url; $title = $result->title; $desc =
$result->description;

   print <a href=$url>$title<br>$desc<p>\n"; }

DESCRIPTION
===========

   WWW::Search class for searching National Library of Medicine (PubMed).
If you never heard of PubMed, Medline or don't know the difference between
a Abstract and Citation - you then can live without this backend.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

AUTHOR
======

   `WWW::Search::PubMed' is written and maintained by Jim Smyser
<jsmyser@bigfoot.com>.

COPYRIGHT
=========

   WWW::Search Copyright (c) 1996-1998 University of Southern California.
All rights reserved. PubMed.pm by Jim Smyser.

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

Common base class for lab development tools
*******************************************

NAME
====

   Puppet::Any - Common base class for lab development tools

SYNOPSIS
========

     use Puppet::Any ;

     package myClass ;

     @myClass::ISA=('Puppet::Any') ;

     package main ;
     my $file = 'test.db';
     my %dbhash;
     tie %dbhash,  'MLDBM',    $file , O_CREAT|O_RDWR, 0640 or die $! ;

     my $test = new myClass (name => 'test',
                               dbHash => \%dbhash,
                               keyRoot => 'key root'
                              );

     $test->display;
     $test->setDbInfo(toto => 'toto val',
                     'titi' => 'titi val',
                    dummy => 'null') ;

     $test->deleteDbInfo('dummy');

     MainLoop ; # Tk's

     untie %dbhash ;

DESCRIPTION
===========

   Puppet::* classes are designed to provide an access to the "puppeted"
object using a GUI based on Tk.

   The basic idea is when you construct a Puppet::* object, you have all
the functionnality of the object without the GUI. Then, when the need
arises, you may (or the class may decide to) open the GUI of the object
and then the user may perform any interactive he wishes.

   On the other hand, if the need does not arise, you may instanciate a
lot of objects without cluttering your display.

   For instance, if you have an object (say a ProcessGroup) controlling a
set of processes (Process objects). The user may start the ProcessGroup
through its GUI. Then all processes are run. If one of them fails, it will
raise its own GUI to display the cause of the problem and let the user
decide what to do.

   This class named Puppet::Any is the base class inherited by all other
Puppet classes. In this example, Process and Process group both will
inherit Puppet::Any.

   The base class features : - A Tk::Multi::Manager to show or hide the
different display of the base class   (or of the derived class) - A menu
bar - An event log display so derived object may log their activity - A
Debug log display so derived object may log their "accidental"   activities
- An Object Scanner to display the attribute of the derived object - A set
of functions to managed "has-a" relationship between Puppet objects.
The menu bar feature a "content" bar which enabled the user to open the
display of all "contained" objects.  - a facility to store data on a
database file tied to a hash.

   The class is designed to store its data in a SINGLE entry of the
database file. (For this you should use MLDBM if you want to store more
than a scalar in the database). The key for this entry is
"$keyRoot;$name". keyRoot and name being passed to the constructor of the
object. Needless to say, it's a bad idea to create two instances of
Puppet::WithDb with the same keyRoot and name.

default bindings
================

   <Meta-d> is bound to pop-up a Tk object scanner widget. This will be
handy to debug the child class you're going to develop.

DEFAULT WINDOWS
===============

debug log window
----------------

   This log window (see Puppet::Log(3)) will get all debug information for
this instance of the object. More or less reserved for developers of
children of Puppet::Any.

   Users object inheriting from Puppet::Any must use the printDebug()
method to log debug info in this window.

event log window
----------------

   This log window (see Puppet::Log(3)) will get all event information for
this instance of the object.

   Users object inheriting from Puppet::Any must use the printEvent()
method to log debug info in this window.  =head1 Object attributes

name
----

   name of the instance. No treatment or special signification to it
except that it can be handy for the debug.

content
-------

   Hash containing the reference of all acquired objects ('name' => ref).

topTk
-----

   Reference of the Tk main window.

log
---

   hash array which contains 'event' and 'debug' Puppet::Log objects.  Do
not squash it.

tk
--

   Hash containing the following keys :

     - toplevel: toplevel window ref of this object.
     - menubar: Frame containing the menu buttons. (you may call MenuButton on it)
     - contentMnb: ref to the menu managing content (private)
     - menu: hash containing menu widgets. ('File' for instance)
      ( you may call command on
       $self->{tk}{menu}{'File'} to define a new command in the menu for instance)
     - multiMgr Tk::Multi::Manager buddy ref.

   When the closeDisplay method is called, it will destroy
$self->{tk}{toplevel}, thus it will destroy all Tk widgets and then it
will delete the $self->{tk}  hash, thus it will delete all internal
reference to the destroyed widgets.  So you can also test whether your
widget has a display by testing if $self->{tk} is defined.

   The sub-class MUST abide to this rule if the closeDisplay is to work
properly.

dbHash
------

   Tied hash to the database.

keyRoot
-------

   First part of the key to access the database

myDbKey
-------

   The key to access the database

Methods
=======

new( ... )
----------

   Creates new Puppet object.

   parameters are :  - name  - topTk (optionnal, will create a MainWindow
if ommitted)  - keyRoot  - dbHash: ref of the tied hash

   Note that all other arguments are passed to the Puppet::Log
constructors.  I.e. you can also specify arguments specific to
Puppet::Log->new() through Puppet::Any->new() function.

acquire(a_name, a_ref)
----------------------

   Acquire the object ref as a child. a_ref must be an object derived of
Puppet::Any.

   Each acquired object must have different names.

drop('name')
------------

   Destroy child 'name'.

display()
---------

   defines a top level display for each object, contains a MultiText ,a
manager and a objScanner.

   <Meta-d> will create an object scanner to scan this object.

   A debug and an events log objects (Puppet::Log) are created for use by
the child class

   Return 1 if a display is actually created. 0 otherwise (i.e is the
display already exists).

   When overloading display, you may write you function like this :

     sub display
      {
        my $self = shift ;
        return unless $self->SUPER::display(@_ );

     ...
     }

   So the display instruction you add will be run only when creating the
display.

closeDisplay
------------

   Close the display. Note that the display can be re-invoked later.

printDebug(text)
----------------

   Will log the passed text into the debug log object.

printEvent(text)
----------------

   Will log the passed text into the events log object.

showEvent(text)
---------------

   Will display the 'event' log window.

storeDbInfo( key => value, ...)
-------------------------------

   Store the passed hash in the database. You may also pass a hash ref as
single argument.

deleteDbInfo( key, ...)
-----------------------

   delete the "key" entries from the database.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998 Dominique Dumont. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   perl(1), Tk(3), Puppet::Log(3)

Utility class to handle has-a relations and logs
************************************************

NAME
====

   Puppet::Body - Utility class to handle has-a relations and logs

SYNOPSIS
========

     use Puppet::Body ;

     package myClass ;
     sub new
      {
        my $type = shift ;
        my $self = {};
        $self->{body} = new Puppet::Body(cloth => $self, @_) ;
        bless $self,$type ;
      }

     sub body { return shift->{body} ;}

     package main ;

     # create a class with no persistent data
     my $foo = new myClass (Name => 'foo') ;

     # foo now has baz and buz
     $foo->body->acquire(body => $baz);
     $foo->body->acquire(body => $buz);

     # foo no longer has $baz
     $foo->body->drop($baz);

DESCRIPTION
===========

   Puppet::Body is a utility class that is used (and not inherited like
the deprecated Puppet::Any) to manage dynamic has-a relations between
objects.

   This class provides the following features :

   * An event log display so user object may log their activity (with
     Puppet/LogBody)

   * A Debug log display so user object may log their "accidental"
     activities(with Puppet/LogBody)

   * A set of functions to managed "has-a" relationship between Puppet
     objects.

Constructor
===========

new(...)
--------

   Creates new Puppet object. New() parameters are:

name
     The name of your object (defaults to "anonymous1" or "anonymous2" ...)

cloth
     The ref of your object

how
     Specify how logs are to be handled. See `"Constructor"', see
     Puppet/LogBody,

Generic methods
===============

getName()
---------

   Returns the name of this object.

HAS-A relations management methods
==================================

acquire(...)
------------

   Acquire the object ref as a child. Parameters are:

body
     Reference of the Puppet::Body object that is to be acquired.

name
     Name to refer to the acquired Puppet::Body. Defaults to the name of
     the acquired Puppet::Body object.

   For instance if object foo acquires object bar, bar becomes part of
foo's content and foo is one of the container of bar.

drop('name')
------------

   Does the opposite of acquire(), i.e. drop the object named 'name'.

getContent('name',...)
----------------------

   In scalar context, it returns the Puppet::Body ref of the object 'name'.
Returns undef if 'name' is not part of the content (i.e if it has not been
'acquired' before)

   In array context, it returns an array of all Puppet::Body references of
all passed names. Returns () if the object has no content.

getContainer('name',...)
------------------------

   Same as getContent for the container.

contentNames()
--------------

   Returns all names of the content, i.e. of all 'acquired' objects.

containerNames()
----------------

   Returns all names of the containers, i.e. of all objects that
'acquired' this object

Log management.
===============

printDebug(text)
----------------

   Will log the passed text into the debug and events log object.

printEvent(text)
----------------

   Will log the passed text into the events log object.

About Puppet framework
======================

   Puppet framework is made of a set of utility classes. I currently use
this framework for a major application Tk application.

   If you use directly the Puppet::Body class, you get the plain
functionnality.  And if you use the Puppet::Show class, you can get the
same functionnality and a Tk Gui to manage it.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998-1999 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   See Perl (perl.info), Puppet/Log,
Puppet/Storage, Puppet/Show,

Log facility with an optional Tk display
****************************************

NAME
====

   Puppet::Log - Log facility with an optional Tk display

SYNOPSIS
========

     use Puppet::Log ;

     my $log = new Puppet::Log('title' =>'log test') ;
     $log -> log("Some text") ;

     # $wmgr can be a toplevel Tk main window or a Tk::Multi::Manager
     $log ->display($wmgr, 1) ;

DESCRIPTION
===========

   This class implements a log facility with an optional Tk display.

   I.e once the class is created, you can log messages in it, but the Tk
display does no need to be created at the same time. You may invoke later
only when you need it.

   When the Tk display is not invoked, the log can be either printed on
STDOUT or warned on STDERR (or stay hidden). But in any case, the log
message will be stored in the class so that all log messages can be
retrieved later by the user or by the Tk display when invoked.

   Once the Tk display is invoked, it will be updated by new logs.

Constructor
===========

new([title => 'name'], ['how' => 'print' | 'warn' ])
----------------------------------------------------

   Creates the log object.

   The constructor parameters are :

   * title: Title of the Tk log display (optional)

   * name: Name of the log used when printing on STDOUT or STDERR
     (optional)

   * how: Specifies what to do when a log is sent to the object (either
     print on STDOUT, warn on STDERR). By default the logs will not be
     printed or warned. (optional)

   * help The argument may be a string or a sub reference.  When the help
     menu is invoked, either the help string will be displayed in a
     Tk::Dialog box or the sub will be run. In this case it is the user's
     responsability to provide a readable help from the sub.  (See
     `"help"', see Tk/Multi/Manager, for further
     details)

Methods
=======

log(text,...)
-------------

   Will log the passed text

   Optional parameters are:

   * how: will supersede the 'how' parameter passed to the constructor. If
     'how' is set to undef, the log will not be printed or warned.

clear()
-------

   Clear all stored logs.

getAll()
--------

   Return an array made of all stored logs.

display(toplevel_ref | multi_manager_reference, [hidden] )
----------------------------------------------------------

   Will create the log display. The log display is in fact a
Tk::Multi::Text window which can managed by a Tk::Multi::Manager object.

toplevel_ref
     The parent window object.

multi_manager_reference
     The Tk::Multi::Manager reference

hidden
     When hidden is 1, the log will not displayed on start-up. (default is
     to show the log window)

   If you don't provide a multi_manager reference, Puppet::Log will
consider that you want the Log to appear in its own TopLevel window.

   In this case Puppet::Log will create a new Toplevel window and create a
Tk::Multi::Manager in it. In this case, it will feature a File->close menu
entry to destroy the Log window.

   Once the Log window is destroyed, the display method can then be called
later to recreate it.

   In any case display() returns the manager reference. You may reuse this
reference to add another Log display in the Toplevel window that Log just
created. So that both log windows are displayed in the same Tk window.
(See the `t/top_log.t' example to see what I mean)

show()
------

   Will raise the log window. Note that this function is ignored if its
called before display().

About Puppet::* classes
=======================

   Puppet classes are a set of utility classes which can be used by any
object.  If you use directly the Puppet::*Body class, you get the plain
functionnality.  And if you use the Puppet::* class, you can get the same
functionnality and a Tk Gui to manage it.

   The basic idea is when you construct a Puppet::* object, you have all
the functionnality of the object without the GUI. Then, when the need
arises, you may (or the class may decide to) open the GUI of the object.
On the other hand, if the need does not arise, you may create a lot of
objects without cluttering your display.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998-1999 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1), Puppet::LogBody(3), Tk(3), Tk::Multi::Text(3),
Tk::Multi::Manager(3)

Log facility
************

NAME
====

   Puppet::LogBody - Log facility

SYNOPSIS
========

     use Puppet::LogBody ;

     my $log = new Puppet::LogBody
      (
       name => 'log test',
       'how' => 'print'
      ) ;

     $log -> log("hello")  ;                 # printed on STDOUT
     $log -> log("world",'how' => 'warn')  ; # printed on STDERR

     my @a = $log-> getAll() ; # @a contains ['hello','world']

DESCRIPTION
===========

   This class implements a log facility which can either print on STDOUT
or warn on STDERR (or hide) the log message. But in any case, the log
message will be stored in the class so that all log messages can be
retrieved later by the user.

Constructor
===========

new (...)
---------

   Creates the log object.

   Parameters are

   * name: is the log name that will be printed on STDERR or STDOUT at each
     log. (optional)

   * how: specifies what  to do when a log   is sent to the  object (either
     print  on STDOUT, warn  on  STDERR). By default  the logs  will not be
     printed or warned.

   For instance if name is set to 'foo' a call to log('hello') will print:

     foo:
           hello

Methods
=======

   As Puppet::LogBody inherits from Puppet::Log, all the parent methods are
available.

log(text,...)
-------------

   Will log the passed text

   Optional parameters are:

   * how: will supersede the 'how' parameter passed to the constructor. If
     'how' is set to undef, the log will not be printed or warned.

clear()
-------

   Clear all stored logs

getAll()
--------

   Return an array made of all stored logs.

About Puppet body classes
=========================

   Puppet classes are a set of utility classes which can be used by any
object.  If you use directly the Puppet::*Body class, you get the plain
functionnality.  And if you use the Puppet::* class, you can get the same
functionnality and a Tk Gui to manage it.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998-1999 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1), Puppet::Log(3)

Optional Tk Gui for Puppet::Body
********************************

NAME
====

   Puppet::Show - Optional Tk Gui for Puppet::Body

SYNOPSIS
========

     use Puppet::Show ;

     package myClass ;

     sub new
      {
        my $type = shift ;
        my $self = {};

        # no inheritance, your class contains the Puppet::Show class
        $self->{body} = new Puppet::Show(cloth => $self, @_) ;

     bless $self,$type ;
       }

     package main;

     my $mw = MainWindow-> new ;

     # these 2 parameters are passed to Puppet::Show constructor
     my $test = new MyTest( name => 'foo', 'topTk' => $mw) ;

     $test->display;

     MainLoop ; # Tk's

DESCRIPTION
===========

   Puppet::Show is a utility class that is used (and not inherited like
the deprecated Puppet::Any) to manage a Puppet/Body,
class through an optional GUI.

   So when you construct a Puppet::Show object, you have all the
functionnality of this object without the GUI. Then, when the need arises,
you may (or the user class may decide to) open the GUI of Puppet::Show so
the user may perform any interactive action.

   On the other hand, if the need does not arise, you may instanciate a
lot of objects (which uses Puppet::Show) without cluttering your display.

   The user class may use the Puppet::Show Tk widget (actually a
Tk::Multi::Toplevel widget) and add its own widget to customize the GUI to
its needs.

   This class features :

   * A Tk/Multi/Toplevel, to show or hide the
     different display of the Show class (or of the user class)

   * A menu bar (part of Tk/Multi/Toplevel)

   * An online help (part of Tk/Multi/Toplevel)

   * An event log display so user object may log their activity (See
     Puppet/Log)

   * A Debug log display so user objects may log their "accidental"
     activities (See Puppet/Log)

   * An Object Scanner (See Tk/ObjScanner) to
     display the attributes of the user object

   * A set of functions to manage "has-a" relationship between Puppet
     objects.  (See Puppet/Body).  The menu bar
     feature a "content" bar which enabled the user to open the display of
     all "contained" objects.

   * A facility to store data on a database file tied to a hash. (part of
     Puppet/Body)

DEFAULT WINDOWS
===============

debug log window
----------------

   This log window (see Puppet/Log) will get all debug
information for this instance of the object. More or less reserved for
developers of classes using Puppet::Show.

   Note that log sent to the 'event' window will also be displayed in the
debug window for better clarity.

event log window
----------------

   This log window (see Puppet/Log) will get all event
information for this instance of the object.

Constructor
===========

new( ... )
----------

   Creates new Puppet::Show object.  The constructor uses all
`"Constructor"', see Puppet/Body, parameters plus:

topTk
     The ref of the main Tk window

podName
     The name of the pod file that will be used for the online help.  (See
     Tk/Pod)

podSection
     The name of the pod section that will be used for the online help

Methods
=======

acquire(...)
------------

   Acquire the object ref as a child. Parameters are:

   * body: Reference of the Puppet::Body object that is to be acquired.

   * raise: Sub reference or method to call on the user object when the
     object is raised (generally through the 'content' menu).  (Default to
     call display on the user object)

   * myRaise: Sub reference or method to call when this object is raised
     (generally through the 'container' menu).  (Default to call
     $self->display())

   For instance if object foo acquires object bar, bar becomes part of
foo's content and foo is one of the container of bar.

display(...)
------------

   Creates a top level display for the user object.

   Parameters are:

   * master: Optional. You can set it to 1 if this object will be the
     master object of your application. In this case, destroying its
     display (with the File->close menu for instance) will make the
     application exit.

   * onDestroy: sub ref to call back when the display is destroyed.

   Return the Tk/Multi/Toplevel, object if a
display is actually created, undef otherwise (i.e is the display already
exists).

myDisplay()
-----------

   Return the Tk/Multi/Toplevel, object created
by the display method.

closeDisplay()
--------------

   Close the display. Note that the display can be re-created later.

About Puppet body classes
=========================

   Puppet classes are a set of utility classes which can be used by any
object.  If you use directly the Puppet::*Body class, you get the plain
functionnality.  And if you use the Puppet::* class, you can get the same
functionnality and a Tk Gui to manage it.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998-1999 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   Tk(3), Puppet::Log(3), Puppet::LogBody(3), Puppet::Body(3),
Tk::Multi::Toplevel(3), Tk::Multi::Manager(3)

Utility class to handle permanent data
**************************************

NAME
====

   Puppet::Storage - Utility class to handle permanent data

SYNOPSIS
========

     use Puppet::Storage ;

     my $file = 'test.db';
     my %db;

     # you manage the DB file
     tie %db, 'MLDBM', $file , O_CREAT|O_RDWR, 0640 or die $! ;

     # translucent attributes
     Puppet::Storage->dbHash(\%db);
     Puppet::Storage->keyRoot('key root');

     my $foo = new Puppet::Storage (name => 'foo');
     my $bar = new Puppet::Storage (name => 'bar');

     # store some data in permanent storage
     $foo->storeDbInfo(toto => 'toto val', dummy => 'null') ;

     # remove some data from permanent storage
     $bar->deleteDbInfo('dummy');

     # at the end of your program, just to be on the safe side
     untie %dbhash ;

DESCRIPTION
===========

   Puppet::Storage is a utility class which provides a facility to store
data on a database file tied to a hash.(with MLDBM)

Class data
==========

   These items are translucent attributes (See Perltootc (perl.info),
by Tom Christiansen).

   Using the following method, you may set or query the value for the data
class. And these parameters may be overridden with the constructor or by
invoking this method by the object rather than by the class.

keyRoot
     See `"Database management"' in this node.

dbHash
     ref of the tied hash. See `"Database management"' in this node.

Constructor
===========

new(...)
--------

   Creates new Puppet::Storage object. New() parameters are:

name
     The name of your object (no defaults)

spawn(...)
----------

   Spawn a new Puppet::Storage object re-using the translucent attribute
of the spawner object.

   parameters are:

name
     The name of your object (no defaults)

child(...)
----------

   Spawn a new Puppet::Storage object re-using the translucent attribute
of the spawner object. On top of that a new keyRoot attribute is defined
as '<parent_keyroot child_name';

   E.g. if the parent keyroot is 'foo', the parent name is 'bar', the
child name is 'calvin', then the new keyRoot of the child is set to 'foo
bar'. So for instance a 'toto' data will be stored in the child with this
key: 'foo bar;calvin#toto'. That's pretty complex, fortunately, you
shouldn't have to worry about the key managment.

   parameters are:

name
     The name of your object (no defaults)

Database management
===================

   The class is designed to store its data in a database file. (For this
you should use MLDBM if you want to store more than a scalar in the
database). The key for this entry is "$keyRoot;$name# $key". keyRoot and
name being passed to the constructor of the object and 'key' is the name
of the value you want to store (This may remind perl old timers of a trick
to emulate multi-dimensional hashes in perl4)

   Needless to say, creating two instances of Puppet::Storage with the
same dbHash, keyRoot and name is a *bad* idea because you may mix up data
from one object to another.

storeDbInfo(%hash)
------------------

   Store the passed hash in the database. You may also pass a hash ref as
single argument.

deleteDbInfo(key,...)
---------------------

   delete the "key" entries from the database.

getDbInfo(key,...)
------------------

   If one key is specified, getDbInfo will return the value of the "key"
entry from the database.

   If more than one key is passed, getDbInfo will return a hash ref
containing a copy of the key,value pairs from the database.

dumpDbInfo()
------------

   dumpDbInfo will return a hash ref containing a copy of all the
permanent data of this object.

   Using this method should only be used for debug purpose as it will
iterate over all the other values of the DB_File to get the data of this
object.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1999 Dominique Dumont. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   See Perl (perl.info), Puppet/Body,

Tk GUI for VCS file management
******************************

NAME
====

   Puppet::VcsTools::File - Tk GUI for VCS file management

SYNOPSIS
========

     use Tk ;
     use Puppet::VcsTools::File;
     use Puppet::VcsTools::HistEdit;
     use VcsTools::LogParser ;
     use VcsTools::DataSpec::HpTnd qw($description readHook);
     use Fcntl ;
     use MLDBM qw(DB_File);

     my %dbhash;
     tie %dbhash,  'MLDBM',    $file , O_CREAT|O_RDWR, 0640 or die $! ;

     my $ds = new VcsTools::LogParser
      (
       description => $description,
       readHook => \&readHook
      ) ;

     my $mw = MainWindow-> new ;
     $mw->withdraw ;

     my $he = $mw->LogEditor( 'format' => $ds) ;

     my $fileO = new Puppet::VcsTools::File
      (
       dbHash => \%dbhash,
       keyRoot => 'root',
       vcsClass => 'VcsTools::HmsAgent',
       vcsArgs =>
       {
        hmsHost => 'hptnofs',
        hmsBase => 'test_integ'
        },
       name => $tfile,
       workDir => $ENV{'PWD'},
       dataScanner => $ds,
       logEditor => $he,
       'topTk' => $mw
      );

     $fileO -> display( master => 1);

     MainLoop ;

DESCRIPTION
===========

   This class provides a GUI to the VcsTools/File,
class.

   The widget provides all the functionnalities to edit, archive, lock,
unlock, change the mode of a file.

   The widget also provide an 'open history' menu to call the
Puppet/VcsTools/History, widget which will let
you work on the history of a file. Moreover, this widget will let you edit
the log a each version of a file, if you want to modify it.

CAVEATS
=======

   The file must contain the `$Revision: 1.3 $' VCS keyword.

WIDGET USAGE
============

   The File widget contains a sub-window featuring:

   * A revision label to indicate the revision of the current file.

   * A 'writable' check button, which indicated the status of the file and
     is able to change its mode.

   * A 'locked'check button, which indicated the lock status of the file
     and is able to change its lock.

   By default, all these menus and buttons are disabled until the user
performs a File->check through the menu.

   The File menu contains several commands :

   * open history: Will open the history menu.

   * check: to get the revision, mode, and lock status of the current file.

   * archive: to archive the file (Enabled only if the file is writable).

   * create archive: to create an archive of the file (Enabled only if the
     file is writable and the archive does not exist).

   * edit: to edit the file (Enabled only if the file is writable or if
     the file does not yet exist).

   The File object will add some functionnalities to the History object
while opening it :

   * A 'merge' global menu: To perform a merge on 2 selected revision.

   * A 'show diff' global menu: To show a diff between 2 selected revision.

   * Button 2 is bound to arrows to show the diff between the 2 revisions
     next to the arrow.

   * A 'show diff' command is also added to the arrow popup menu.

   * Button 2 is bound to nodes to show the content of this revision.

   * An 'edit log' entry is added to the popup menu of the nodes and
     arrows.

Constructor
===========

new(...)
--------

   Will create a new File object.

   Parameters are those of `"new(...)"', see VcsTools/File.
plus :

   * topTk : Tk top window reference.

Generic methods
===============

   See `"check()"', see VcsTools/File,

display()
---------

   Will launch a widget for this object.

archiveFile(...)
----------------

   See `"archiveFile(...)"', see VcsTools/File.

   Feature one more parameter : The user may pass a 'auto' parameter set
to 1 if an interactive archive is not desired. (default 0)

History handling methods
========================

   See `"createHistory()"', see VcsTools/File,
`"edit()"', see VcsTools/File, `"getRevision()"', see
VcsTools/File, `"checkWritable()"', see VcsTools/File,
`"chmodFile(...)"', see VcsTools/File,
`"writeFile(...)"', see VcsTools/File,

openHistory()
-------------

   Will create a Puppet/VcsTools/History,
object for this file and open its display.

Handling the real file
======================

   See `"createLocalAgent()"', see VcsTools/File,
`"edit()"', see VcsTools/File, `"getRevision()"', see
VcsTools/File, `"checkWritable()"', see VcsTools/File,
`"chmodFile(...)"', see VcsTools/File,
`"writeFile(...)"', see VcsTools/File,

Handling the VCS part
=====================

   See `"createVcsAgent()"', see VcsTools/File,
`"checkArchive()"', see VcsTools/File,
`"changeLock(...)"', see VcsTools/File,
`"checkOut(...)"', see VcsTools/File,
`"getContent(...)"', see VcsTools/File,
`"archiveLog(...)"', see VcsTools/File,
`"getHistory()"', see VcsTools/File, `"showDiff(...)"',
see VcsTools/File, `"checkIn(...)"', see
VcsTools/File,

merge(...)
----------

   Will open a GUI to merge the 2 revisions. Will use xemacs ediff merge
to perform the actual merge.

   Parameters are :

   * rev1 : one of the revisions to merge.

   * rev2: the other.

   The ancestor of rev1 and rev2 will be computed by the
VcsTools/History, object.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998 Dominique Dumont. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   perl(1), Tk(3), Puppet::Any(3), VcsTools::DataSpec::HpTnd(3),
VcsTools::Version(3), VcsTools::File(3)

TreeGraph and node list widget
******************************

NAME
====

   Puppet::VcsTools::GraphWidget - TreeGraph and node list widget

SYNOPSIS
========

     use Tk::Multi::Manager;

     use Puppet::VcsTools::GraphWidget;

     my $wmgr = $mw -> MultiManager
      (
       'title' => 'log test' ,
       'menu' => $w_menu
      ) -> pack ();

     $toto = $wmgr -> newSlave
      (
       'type'=>'MultiVcsGraph',
       title => 'graph try',
       'list' => [1 .. 5 ]
      ) ;

     my $ref = [1000..1005];
     my ($ox,$oy) = (100,100);

     $tg -> addNode
       (
        nodeId => '1.0',
        text => $ref,
        xref => \$ox,
        yref => \$oy
       ) ;

DESCRIPTION
===========

   This composite widget is intented to provide a canvas to draw a VCS
revision tree associated with a listbox containing a list of all the
revisions of the VCS file.

   This widget features :

   * A scrollable Canvas. (See Tk/TreeGraph)

   * A print button (The shell print command may be modified by setting
     $printCmd to the appropriate shell command. By default, it is set to
     'lp -opostscript')

   * A clear button

   * A list box

   This widget will forward all unrecognized commands to the TreeGraph
object.

   Note that this widget should be created only by Tk/Multi/Manager.

WIDGET-SPECIFIC OPTIONS
=======================

title
-----

   Some text which will be displayed above the test window.

menu_button
-----------

   The log window feature a set of menu items which must be added in a
menu.  This menu ref must be passed with the menu_button prameter to the
object during its instanciation

list
----

   A reference to a list that will be inserted in the Listbox. (optional)

ADVERTISED WIDGET
=================

   * graph

   * list

   * menu

WIDGET-SPECIFIC METHODS
=======================

addRev( revision ,.. )
----------------------

   Add the passed revision in the revision listbox

print()
-------

   Will raise a popup window with an Entry to modify the actual print
command, a print button, a default button (to restore the default print
command), and a cancel button.

doPrint()
---------

   Print the label and the content of the text window. The print is invoked
by dumping the text content into a piped command.

   You may want to set up a new command to print correctly on your machine.
You may do it by using the setPrintCmd method or by invoking the 'print'
method.

setPrintCmd('print command')
----------------------------

   Will set the $printCmd class variable to the passed string. You may use
this method to set the appropriate print command on your machine. Note that
using this method will affect all other Tk::Multi::Canvas object since the
modified variable is not an instance variable but a class variable.

clear()
-------

   Is just a delete('1.0','end') .

Delegated methods
=================

   By default all widget method are delegated to the Text widget. Excepted
:

command(...)
------------

   Parameters are :

   * on: either 'menu', 'node' or 'arrow'

   * label: Label of the Popup menu entry

   * command: sub ref to run when the menu is invoked

   If the 'on' parameter is set to 'menu', the command will be delegated
to the menu entry managed by the Tk/Multi/Manager.
This will add a new command to the aforementionned menu.

   Otherwise, the command will be delegated to the TreeGraph widget.  See
`"command(...)"', see Tk/TreeGraph,

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998-1999 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1), Tk(3), Tk::Multi::Manager(3), Tk::TreeGraph(3)

TK GUI for VcsTools::History
****************************

NAME
====

   Puppet::VcsTools::History - TK GUI for VcsTools::History

SYNOPSIS
========

     require VcsTools::DataSpec::HpTnd ; # for instance
     # could be VcsTools::DataSpec::Rcs

     my $ds = new VcsTools::DataSpec::HpTnd ; # ditto

     my $hist = new Puppet::VcsTools::History
      (
       dbHash => \%dbhash,         # for permanent data storage
       keyRoot => 'history root',  # key for permanent data storage
       'topTk' => $mw,
       name => 'Foo history',
       dataScanner => $ds          # log analyser
      );

DESCRIPTION
===========

   This class provides a GUI to the VcsTools/History,
class.

   It contains a GraphWidget to draw the history tree and some key
bindings to read the log informations from the tree drawing .

WIDGET USAGE
============

   The display of the history object is made of :

   * A canvas to draw a revision tree.

   * A revision list. If you double click on a revision of this list,
     History will draw the revision tree starting from this revision.

   * A text window to display informations related to the revision tree.

Nodes
-----

   Each rectangle in the tree represent a revision (aka a node).  The text
in the rectangle is bound to some keys :

   * button-1 selects the node for further operation (See below)

   * button-3 pops-up a menu

   * double button-1 redraws the tree from this revision

   The node popup menu features :

   * draw from here: Re-draws the tree from this revision

   * open version object: Opens the display of the
     Puppet/VcsTools/Version, object.

Arrows
------

   Each arrow is bound to some keys :

   * button-1 shows the log of this revision

   * button-3 pops up a menu

   The arrow popup menu features :

   * show log: shows the log of this revision

   * show full log: shows the full log of this revision with all fields.

global features
---------------

   The graph widget features a global menu invoked on the title of the
graph widget. It features :

   * unselect all: unselect all nodes.

   * reload from archive: Reloads information from the VCS archive. This
     will also update your local information data base. Use this menu when
     other people have worked on your VCS files.

   * show cumulated log: Will show a concatenation of logs between 2
     selected revisions. One of this revision must be the ancestor of the
     other.

   The VcsTools::File(3) object have also some bindings (See `"WIDGET
USAGE"', see VcsTools/File)

Constructor
===========

new(...)
--------

   Will create a new history object.

   Parameters are:

   * All parameter of `"Constructor"', see Puppet/Body,

   * dataScanner : VcsTools::DataSpec::HpTnd (or equivalent) object
     reference

   * topTk: the ref of the Tk main window

Methods
=======

   All `"Methods"', see VcsTools/History, plus these
ones:

addNewVersion(...)
------------------

   The call will be delegated to `"addNewVersion(...)"', see
VcsTools/History, then the drawing will be updated with
it.

display()
---------

   Will launch a widget for this object.

closeDisplay()
--------------

   Delegated to the `"closeDisplay"', see Puppet/Body,
method.

drawTree(...)
-------------

   Parameters are:

   * revision: The tree will start from this revision number. Optional. If
     not passed the tree will be re-drawn from the revision that was
     passed the previous time this funcion was called.

   * nodeId: same as revision.

getTreeGraph()
--------------

   Returns the Tk/TreeGraph, ref embedded in History
display or undef if the display was not opened.

getInfoWidget()
---------------

   Returns the Tk/ROText, ref embedded in History display
or undef if the display was not opened.

TODO
====

   Trigger a history update if the database time stamp is younger than the
time of the last history analysis

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998-1999 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1), Tk(3), Puppet::Show(3), VcsTools::DataSpec::HpTnd(3),
Puppet::VcsTools::Version(3), Puppet::VcsTools::File(3)

Tk composite widget to edit a Vcs Log
*************************************

NAME
====

   Puppet::VcsTools::LogEdit - Tk composite widget to edit a Vcs Log

SYNOPSIS
========

     my $eh = $widget->LogEditor( name => 'dummy',
                                revision=> '1.1',
                                'format' => $logDataFormat) ;

     $eh->Show(info => Storage_object_of_a_VcsTools_Version_object) ;

DESCRIPTION
===========

   This composite Tk Widget is used to edit the log information of a
version of a Vcs file. A version of a Vcs file is implemented in the
VcsTools/Version, object. And the log information is
stored in its associated Puppet/Storage, class. This
class must be passed to the Show method so that the editor can modify the
log informations.

   The fields of the editor are set according to the 'format' parameter
passed during the widget creation.

   Each field feature a 'recall' button which will recall the last archived
value of the field. You may click several times on the 'recall' button to
get older values.

Constructor
===========

LogEditor()
-----------

   Parameters are :

   * format : data format array reference. The LogEditor widget content
     will match the content of this data structure

METHODS
=======

Show()
------

   This method displays the dialog, waits for the user to click either
'archive' or 'cancel'. If the user cancels the edition, Show returns 0.

   If the user clicked 'archive', Show will store the edited data in the
passed 'info' reference and returns 1.

   Parameters are :

   * name: name of the VCS file

   * revision : revision number of the log version to edit

   * info: hash ref or Puppet::Storage object which contains the log to
     edit. If a hash ref is passed, its content will be modified, if a
     Puppet::Storage object is passed, its permanent data will be modified.

   * grab: If global is specified a global (rather than local) grab is
     performed.

DESCRIPTION FORMAT
==================

   See `"DESCRIPTION FORMAT"', see VcsTools/LogParser,

   Each item of the description must have a type. According to the type,
the LogEditor will create a widget for this type:

   * line: The editor uses an Entry widget to edit this type.

   * enum:  The editor uses a RadioButton widget to edit this type. The
     possible values of the Buttons are set by the 'values' parameter of
     the data format.

   * array: The editor uses an Entry widget to edit this type. Array
     element will be separated by a comma or a white space.

   * text: The  editor uses an Text widget to edit this type.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998-1999 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1), Tk(3), VcsTools::DataSpec::HpTnd(3)

Tk GUI to manage a VcsTools::Version object
*******************************************

NAME
====

   Puppet::VcsTools::Version - Tk GUI to manage a VcsTools::Version object

SYNOPSIS
========

   No synopsis given. This object is better used with the
Puppet/VcsTools/History, module.

DESCRIPTION
===========

   This class represents one version of a VCS file. It holds all the
information relevant to this version including the log of this version,
the parent revision, child revision and so on.

   Its main function is to deal with the History object and its TreeGraph
object to draw the history revision tree. The Version object will perform
all necessary calls to the drawing methods of TreeGraph to get the correct
drawing.

   The information structure stored in each Version object are described
in the dataFormat HASH reference passed to the constructor (See
VcsTools/DataSpec/Rcs, or
VcsTools/DataSpec/HpTnd, for more details).

   This Object heavily uses Puppet/Show,
Puppet/Body, and Puppet/Storage.

WIDGET USAGE
============

   Well, By itself, the Version widget cannot do much.

   Future version may be better depending on user inputs.

   The only function available is to edit the history through the
"File->edit log" menu if the 'edit' parameter was specified to the
constructor.

Constructor
===========

new(...)
--------

   Parameters are those of `"new()"', see VcsTools/Version,
plus:

   * editor : LogEditor ref. If specified, the history of this version can
     be edited by calling the Show() method of the LogEditor. See
     `"Show()"', see Puppet/VcsTools/LogEdit.
     (optional)

Methods
=======

   All `"Methods"', see VcsTools/Version, plus these
ones:

display(...)
------------

   Will launch a widget for this object. All parameters are passed to
`"display(...)"', see Puppet/Show,

closeDisplay()
--------------

   Delegated to the `"closeDisplay"', see Puppet/Body,
method.

editLog()
---------

   Will run the log editor for this version.

archiveLog()
------------

   Will delegate the call to the history manager. Used to update the VCS
base from the log stored in the Version object. Used generally after an
editLog.

drawTree(tree_graph)
--------------------

   Will start drawing a tree (from the revision of this Version object)
calling History object's graph.

Internal Methods
================

   Not for faint hearted people.

drawSubTree(tree_graph, x, y, width_reference)
----------------------------------------------

   Called recursively to draw all nodes, internal method.

   x,y are the coordinates of the root of the sub-tree. The width will be
changed to the actual width (in pixels) of the sub-tree. Note that the
width of the sub-tree depends on the number of branches.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998-1999 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1), Tk(3), Puppet::Show(3), VcsTools::Version(3),
VcsTools::History(3)

Interface to the Qt QAccel class
********************************

NAME
====

   QAccel - Interface to the Qt QAccel class

SYNOPSIS
========

   `use QAccel;'

   Inherits QObject.

Member functions
----------------

   new, clear, connectItem, count, disconnectItem, findKey, insertItem,
isEnabled, isItemEnabled, key, removeItem, setEnabled, setItemEnabled

DESCRIPTION
===========

   The complete class is implemented. Do not try to use SIGNAL() or SLOT().

EXPORTED
========

   The `%Key' hash is exported into the caller's namespace, the elements
represent the values of the Key_* macros in C++ Qt. For example, the
`Key_Space' value in C++ would be accessible as `$Key{Space}' in Perl, the
`Key_Q' value would be accessible with `$Key{Q}', and so on.

   The scalar values $SHIFT, $CTRL, $ALT, and $ASCII_ACCEL are also
exported, and have the same value and function as their C++ counterparts.

SEE ALSO
========

   QAccel(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QApplication class
**************************************

NAME
====

   QApplication - Interface to the Qt QApplication class

SYNOPSIS
========

   `use QApplication;'

   Inherits QObject.

   Requires QClipboard, QCursor, QEvent, QFont, QFontMetrics, QPalette,
QPoint, and QWidget.

   A QApplication is automatically created when you `use Qt;' and will be
automatically exported into your namespace as $qApp.

Member functions
----------------

   new, beep, clipboard, closingDown, colorMode, desktop, enter_loop, exec,
exit, exit_loop, flushX, focusWidget, font, fontMetrics, mainWidget,
notify, overrideCursor, palette, postEvent, processEvents, quit,
restoreOverrideCursor, sendEvent, setColorMode, setFont, setMainWidget,
setOverrideCursor, setPalette, setStyle, startingUp, style, syncX, widgetAt

DESCRIPTION
===========

   What you see is what you get.

SEE ALSO
========

   QApplication(3qt) QObject(3qt) QObject(3) QGlobal(3)

NOTES
=====

   The Qt class automatically creates and exports a QApplication. None of
the other classes in Qt actually uses the Qt class, so if a user's
application doesn't 'use Qt;', no QApplication will be created. This is
meant to allow sub-classing QApplication or allowing a different interface
to use the PerlQt classes, like 'use KDE;'. The QGlobal class is included
in all PerlQt classes, instead of Qt.

BUGS
====

   setColorMode() is interfaced, but I don't think it works.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QBitmap class
*********************************

NAME
====

   QBitmap - Interface to the Qt QBitmap class

SYNOPSIS
========

   `use QBitmap;'

   Inherits QPixmap.

   Requires QSize and QWMatrix.

Member functions
----------------

   new, xForm

DESCRIPTION
===========

   What you see is what you get.

SEE ALSO
========

   QBitmap(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QBrush class
********************************

NAME
====

   QBrush - Interface to the Qt QBrush class

SYNOPSIS
========

   `use QBrush;'

   Requires QColor and QPixmap.

Member functions
----------------

   new, color, pixmap, setColor, setPixmap, setStyle, style

DESCRIPTION
===========

   As direct an interface as humanly possible.

EXPORTED
========

   The `%BrushStyle' hash is exported into the user's namespace. Since
there is no chance for namespace pollution, all `%BrushStyle' elements
ending in Pattern have been truncated so as to remove the Pattern.

SEE ALSO
========

   QBrush(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QButton class
*********************************

NAME
====

   QButton - Interface to the Qt QButton class

SYNOPSIS
========

   `use QButton;'

   Inherits QWidget.

   Requires QPixmap.

Member functions
----------------

   new

DESCRIPTION
===========

$button = QButton->new(parent = undef, name = undef)
     Direct interface.

SEE ALSO
========

   QButton(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QButtonGroup class
**************************************

NAME
====

   QButtonGroup - Interface to the Qt QButtonGroup class

SYNOPSIS
========

   `use QButtonGroup;'

   Inherits QGroupBox.

   Requires QButton.

Member functions
----------------

   new, find, insert, isExclusive, remove, setExclusive

DESCRIPTION
===========

   What you see is what you get.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QCheckBox class
***********************************

NAME
====

   QCheckBox - Interface to the Qt QCheckBox class

SYNOPSIS
========

   `use QCheckBox;'

   Inherits QButton.

Member functions
----------------

   new, isChecked, setChecked

DESCRIPTION
===========

   What you see is what you get.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QClipboard class
************************************

NAME
====

   QClipboard - Interface to the Qt QClipboard class

SYNOPSIS
========

   `use QClipboard;'

   Inherits QObject.

   Requires QPixmap.

Member functions
----------------

   clear, pixmap, setPixmap, setText, text

DESCRIPTION
===========

   What you see is what you get.

SEE ALSO
========

   QClipboard(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QColor class
********************************

NAME
====

   QColor - Interface to the Qt QColor class

SYNOPSIS
========

   `use QColor;'

Member functions
----------------

   new, alloc, blue, dark, green, hsv, isDirty, isValid, light, pixel, red,
rgb, setHsv, setNamedColor, setRgb

Static functions
----------------

   cleanup, currentAllocContext, destroyAllocContext, enterAllocContext,
initialize, lazyAlloc, leaveAllocContext, maxColors, numBitPlanes,
setLazyAlloc

Related functions
-----------------

   qBlue, qGray, qGreen, qRed, qRgb

DESCRIPTION
===========

   Every member of QColor, except the operators, has been interfaced
through this class.

EXPORTED
========

   The following QColor objects are exported into the user's namespace:

   $color0 $color1 $black $white $darkGray $gray $lightGray $red $green
$blue $cyan $magenta $yellow $darkRed $darkGreen $darkBlue $darkCyan
$darkMagenta $darkYellow

   The following functions are exported into the user's namespace:

   `&qBlue', `&qGray', `&qGreen', `&qRed', `&qRgb'

SEE ALSO
========

   QColor(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QComboBox class
***********************************

NAME
====

   QComboBox - Interface to the Qt QComboBox class

SYNOPSIS
========

   `use QComboBox;'

   Inherits QWidget.

   Requires QPixmap.

Member functions
----------------

   new, autoResize, changeItem, count, currentItem, insertionPolicy,
insertItem, insertStrList, maxCount, pixmap, removeItem, setAutoResize,
setCurrentItem, setInsertionPolicy, setMaxCount, setSizeLimit, sizeLimit,
text

DESCRIPTION
===========

   The only significant change is insertStrList(). For obvious reasons,
this function cannot be directly converted to Perl because of it's list
argument.  Perl simplifies the matter greatly by allowing a simple
argument-list change to `insertStrList(index, str1, ..., strN)'. Just set
the index argument to -1 of you want it the items to be appended.

EXPORTED
========

   The `%Policy' hash is exported into the user's namespace. It contains
all the constants that were referenced through QComboBox:: in C++.

CAVEATS
=======

   If there is sufficient demand, I'm more than willing to change the
insertStrList() arguments to make index the last argument and defaulted to
-1. This would break scripts, so be warned.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QCursor class
*********************************

NAME
====

   QCursor - Interface to the Qt QCursor class

SYNOPSIS
========

   `use QCursor;'

   Require QBitmap and QPoint.

Member functions
----------------

   new, bitmap, hotSpot, mask, pos, setPos

DESCRIPTION
===========

   What you see is what you get

EXPORTED
========

   The `%Cursor' hash is exported into the user's namespace. It contains
all of the global cursors (`arrowCursor', `crossCursor', etc..) without
the Cursor suffix (`$Cursor{arrow}', `$Cursor{cross}', etc...)

SEE ALSO
========

   QCursor(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QDialog class
*********************************

NAME
====

   QDialog - Interface to the Qt QDialog class

SYNOPSIS
========

   `use QDialog;'

   Inherits QWidget.

Member functions
----------------

   new, exec, result

DESCRIPTION
===========

   What you see is what you get.

EXPORTED
========

   The `%DialogCode' hash is exported into the user's namespace. It just
has `Accepted' and `Rejected'.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QEvent, QMouseEvent, QPaintEvent, QResizeEvent, and QTimerEvent classes
*******************************************************************************************

NAME
====

   QEvent - Interface to the Qt QEvent, QMouseEvent, QPaintEvent,
QResizeEvent, and QTimerEvent classes

SYNOPSIS
========

   `use QEvent;'

QEvent
------

Member functions
----------------

   new, type

QCloseEvent
-----------

   Inherits QEvent.

Member functions
----------------

   new, accept, ignore, isAccepted

QFocusEvent
-----------

   Inherits QEvent.

Member functions
----------------

   new, gotFocus, lostFocus

QKeyEvent
---------

   Inherits QEvent.

Member functions
----------------

   new, accept, ascii, ignore, isAccepted, key, state

QMouseEvent
-----------

   Inherits QEvent.

   Requires QPoint.

Member functions
----------------

   new, button, pos, state

QMoveEvent
----------

   Inherits QEvent.

Member functions
----------------

   new, oldPos, pos

QPaintEvent
-----------

   Inherits QEvent.

   Requires QRect.

Member functions
----------------

   new, rect

QResizeEvent
------------

   Inherits QEvent.

   Requires QSize.

Member functions
----------------

   new, oldSize, size

QTimerEvent
-----------

   Inherits QEvent

Member functions
----------------

   new, timerId

DESCRIPTION
===========

   All QEvent* classes have been completely interfaced except QCustomEvent.
It will take a bit of creativity to figure out how to make that work.

EXPORTED
========

   The following scalars are exported into the user's namespace on behalf
of QMouseEvent.

   $NoButton $LeftButton $RightButton $MidButton $MouseButtonMask
$ShiftButton $ControlButton $AltButton $KeyButtonMask

   The `%Event' hash is exported into the user's namespace, and represents
the `Event_*' constants. All `%Event' elements have had their prepending
`Event_' removed because of the lack of namespace problems.

CAVEATS
=======

   The exported names are very tempting to stuff into %Button.

SEE ALSO
========

   QEvent(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QFileDialog class
*************************************

NAME
====

   QFileDialog - Interface to the Qt QFileDialog class

SYNOPSIS
========

   `use QFileDialog;'

   Inherits QDialog.

Member functions
----------------

   new, dirPath, getOpenFileName, getSaveFileName, rereadDir, selectedFile,
setDir

DESCRIPTION
===========

   What you see is what you get.

CAVEATS
=======

   Implementing QDir is not on my todo list. I may provide a dir-name stub,
but nothing good is likely before PerlQt-1.00. Get used to it.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QFont class
*******************************

NAME
====

   QFont - Interface to the Qt QFont class

SYNOPSIS
========

   `use QFont;'

Member functions
----------------

   new, bold, charSet, defaultFont, exactMatch, family, fixedPitch,
insertSubstitution, italic, pointSize, rawMode, removeSubstitution,
setBold, setCharSet, setDefaultFont, setFamily, setFixedPitch, setItalic,
setPointSize, setRawMode, setStrikeOut, setStyleHint, setUnderline,
setWeight, strikeOut, styleHint, substitute, underline, weight

DESCRIPTION
===========

   What you see is what you get.

EXPORTED
========

   Three hashes, `%StyleHint', `%Weight', and `%CharSet', are exported into
the user's namespace. They correspond to the three enums in the QFont
class, and, if combined, contain all the constant values that were
accessed through QFont:: in C++.

   To refresh your memory without requiring you to read `qfont.h',
`%StyleHint' elements are font-names (Helvetica, Times, etc), `%Weight'
elements are the character's darkness (Light, Bold, etc), `%CharSet'
should be obvious enough to anyone who needs it.

SEE ALSO
========

   QFont(3pl)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QFontInfo class
***********************************

NAME
====

   QFontInfo - Interface to the Qt QFontInfo class

SYNOPSIS
========

   `use QFontInfo;'

   Requires QFont.

Member functions
----------------

   bold, charSet, exactMatch, family, fixedPitch, font, italic, pointSize,
rawMode, strikeOut, styleHint, underline, weight

DESCRIPTION
===========

   This class is fully interfaced. WYSIWYG

SEE ALSO
========

   QFontInfo(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QFontMetrics class
**************************************

NAME
====

   QFontMetrics - Interface to the Qt QFontMetrics class

SYNOPSIS
========

   `use QFontMetrics;'

   Requires QFont and QRect.

Member functions
----------------

   ascent, boundingRect, descent, font, height, leading, lineSpacing,
lineWidth, maxWidth, strikeOutPos, underlinePos, width

DESCRIPTION
===========

   Fully implemented. Very good.

SEE ALSO
========

   QFontMetrics(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QFrame class
********************************

NAME
====

   QFrame - Interface to the Qt QFrame class

SYNOPSIS
========

   `use QFrame;'

   Inherits QWidget.

   Requires QRect.

Member functions
----------------

   new, contentsRect, frameRect, frameShadow, frameShape, frameStyle,
frameWidth, lineShapesOk, lineWidth, midLineWidth, setFrameStyle,
setLineWidth, setMidLineWidth

DESCRIPTION
===========

   As direct an interface as humanly possible.

EXPORTED
========

   Exports `%QFrame' into the user's namespace. It contains all the
constants accessed through QFrame:: in C++

CAVEATS
=======

   I don't like `%QFrame', and it wouldn't take much for me to move them
all into the QFrame namespace and be done with it.

SEE ALSO
========

   QFrame(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Internal PerlQt class, required by all other classes
****************************************************

NAME
====

   QGlobal - Internal PerlQt class, required by all other classes

SYNOPSIS
========

   `require QGlobal;'

   `use QGlobal qw(...);'

   $object = new QClass->setImmortal

DESCRIPTION
===========

   The only relevant function in QGlobal (so far) is setImmortal(). It
removes the tendency of Perl to free the memory used by an object when it
goes out of scope. If you create say... a button that can live a life of
it's own while within a subroutine, that button will be killed at the end
of the subroutine without setImmortal().

   Reading beyond this point implies that you care about the internals.
Everything in here is subject to change at my whim (and probably already
has).

Object internals
----------------

   QGlobal is a repository for constansts requires by more than one
independant class, and contains Qt::Hash which is inherited by all Qt
classes.  The name Qt::Hash is a remnant from when all Qt objects were
blessed references to tied hashes. It is no-longer relevant because I
sacrificed safety and a bit of convienience in exchange for speed. Every
Qt object has two vital elements, THIS and DESTROY. The THIS element holds
the actual pointer to the C++ object represented in ram. PerlQt
sub-classes all classes for convienience, access to protected members, and
garbage-collection.

   Internally, there are two types of sub-class types, the PClass, and the
pClass. The pClass is availble only for classes which have protected
members which are accessible via Perl. There is a macro, `pQtTHIS(type)',
in `virtual.h' from libperlqt, which automatically typecasts PClass objects
into pClass objects. The PClass is the main sub-class type. Every class has
a P version, and when a PClass is returned from an XS function, the
DESTROY key is created and set to true. Only the existance of DESTROY is
necessary to delete the object on destruction. PClass objects are returned
from all constructors, and from all classes returning QClass &.

Object access
-------------

   There are two functions that are universally useful and likely to be
permanent. They are declared in `pqt.h', and every class requires that
header.

SV *objectify_ptr(void *ptr, char *clname, int delete_on_destroy = 0)
     This function is used when you want to convert a class pointer to an
     object.  *NEVER, EVER, EVER* try to convert a pointer to an SV
     manually!!! The internals are subject to change daily. And believe
     me, I've done it.  This function is automatically used in the typemap.

     The ptr argument is the object to be accessable in Perl. The clname
     argument is the name of the class. It is automatically modified so as
     to strip off any trailing garbage like spaces or *'s. That means
     macro conversions of pointer-types to strings are acceptable. In
     fact, that's how the typemap does it. The delete_on_destroy argument
     is pretty obvious. Just set it to a true value if you want the object
     to be deleted when it is destroyed.

void *extract_ptr(SV *obj, char *clname)
     This does the opposite conversion from objectify_ptr. It *will* cause
     the program to croak if passed what it considers an invalid object.

Virtual functions
-----------------

   The way in which virtual function-calls from C++ to Perl are achieved
is pretty simple at the moment. For every virtual function to be
overridden, a function named QClass_virtualFunction is created in the
virtualize class. The virtualize class, in turn, is inherited by all
classes which have virtual functions that can be overridden in Perl.

   Since the PClasses don't inherit each other, the same virtual function
must be overridden in all the sub-classes of the class with the virtual
function as well, if you want people to sub-class those classes. Since
every PClass which implements virtual classes inherits virtualize, all
that is needed in the virtual override function is a stub which calls
QClass_virtualFunction.

   The QClass_virtualFunction itself just does a method-call to a perl
object which was automatically saved when the object was created.

Signals and slots
-----------------

   Once they are setup, signals and slots are pretty fast and efficient in
Perl. The process of getting there is not.

   The signals and slots for a class are accesible through
`%$signals::signals{QClass}' and `%$slots::slots{QClass}'. These are
filled in with `use signals' and `use slots'.

   For every conection to a Perl QObject slot, a dummy pQtSigSlot object is
created. It is given the object it is to be an interface to, and the
slot-name it is supposed to call. The pQtSigSlot class holds all the stub
functions to be used to call Perl methods. Mostly, those stub function
just call the main functions, `slot1(SV*)', `slot2(SV*,SV*)', etc, with
their arguments converted to their scalar values.

   For every perl signal, a single dummy XS function is just given a new
name.  Since the `CV*' of a function is always passed to an XS function, it
just sees which function-name it was called as, checks the `%signals'
table for the signal to emit, and calls the relevant internal activate*()
function.

   All of the actual code for this is in `QObject.xs' from the main
source-tree and `sigslot.xs' from libperlqt.

EXPORTED
========

   Exports &qRound. EXPORT_OK's a bunch of useful enum values. See
`QGlobal.pm' for a list of those.

CAVEATS
=======

   Everything will change.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QGroupBox class
***********************************

NAME
====

   QGroupBox - Interface to the Qt QGroupBox class

SYNOPSIS
========

   `use QGroupBox;'

   Inherits QFrame.

Member functions
----------------

   new, alignment, setAlignment, setTitle, title

DESCRIPTION
===========

   What you see is what you get.

EXPORTED
========

   The following variables are exported into the user's namespace:

   %Align $SingleLine $DontClip $ExpandTabs $ShowPrefix $WordBreak
$GrayText $DontPrint

   See `QPainter(3)' in this node for info

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QImage class
********************************

NAME
====

   QImage - Interface to the Qt QImage class

SYNOPSIS
========

   `use QImage;'

Member functions
----------------

DESCRIPTION
===========

   What you see is what you get.

SEE ALSO
========

   QImage(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QLCDNumber class
************************************

NAME
====

   QLCDNumber - Interface to the Qt QLCDNumber class

SYNOPSIS
========

   `use QLCDNumber;'

   Inherits QFrame.

Member functions
----------------

   new, checkOverflow, display, intValue, mode, numDigits, setBinMode,
setDecMode, setHexMode, setMode, setNumDigits, setOctMode,
setSmallDecimalPoint, smallDecimalPoint, value

DESCRIPTION
===========

   What you see is what you get.

SEE ALSO
========

   QLCDNumber(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QLabel class
********************************

NAME
====

   QLabel - Interface to the Qt QLabel class

SYNOPSIS
========

   `use QLabel;'

   Inherits QFrame.

   Requires QPixmap and QSize.

Member functions
----------------

   new, alignment, autoResize, buddy, margin, pixmap, setAlignment,
setAutoResize, setBuddy, setMargin, setNum, setText, setPixmap, text

DESCRIPTION
===========

   QLabel has been completely interfaced.

EXPORTED
========

   The following variables are exported into the user's namespace:

   %Align $SingleLine $DontClip $ExpandTabs $ShowPrefix $WordBreak
$GrayText $DontPrint

   The `%Align' hash contains all the Align* constants without the Align.
All of these constants are defined in `qwindefs.h'.

CAVEATS
=======

   I might create `%Align' for the hell of it. You never know.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QLayout, QBoxLayout and QGridLayout classes
***************************************************************

NAME
====

   QLayout - Interface to the Qt QLayout, QBoxLayout and QGridLayout
classes

SYNOPSIS
========

QLayout
-------

   `use QLayout;'

   Inherits QObject.

   Requires QMenuBar.

Member functions
----------------

   activate, defaultBorder, freeze, setMenuBar

QBoxLayout
----------

   Inherits QLayout.

Member functions
----------------

   new, addLayout, addSpacing, addStretch, addStrut, addWidget, direction

QGridLayout
-----------

   Inherits QLayout.

Member functions
----------------

   new, addLayout, addMultiCellWidget, addWidget, setColStretch,
setRowStretch

DESCRIPTION
===========

   What you see is what you get.

EXPORTED
========

   The `%Direction' hash is exported on behalf of QBoxLayout. It contains
all of the constants within QBoxLayout.

   The %Align $SingleLine $DontClip $ExpandTabs $ShowPrefix $WordBreak
$GrayText $DontPrint constants are exported. See `QPainter(3)' in this node
for info.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QLineEdit class
***********************************

NAME
====

   QLineEdit - Interface to the Qt QLineEdit class

SYNOPSIS
========

   `use QLineEdit;'

   Inherits QWidget.

Member functions
----------------

   new, deselect, maxLength, selectAll, setMaxLength, setText, text

DESCRIPTION
===========

   What you see is what you get.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QListBox, QListBoxItem, QListBoxPixmap and QListBoxText classes
***********************************************************************************

NAME
====

   QListBox - Interface to the Qt QListBox, QListBoxItem, QListBoxPixmap
and QListBoxText classes

SYNOPSIS
========

QListBox
--------

   `use QListBox;'

   Inherits QTableView.

Member functions
----------------

   new, autoBottomScrollBar, autoScroll, autoScrollBar, autoUpdate,
bottomScrollBar, centerCurrentItem, changeItem, clear, count, currentItem,
dragSelect, insertItem, insertStrList, inSort, itemHeight, maxItemWidth,
numItemsVisible, pixmap, removeItem, scrollBar, setAutoBottomScrollBar,
setAutoScroll, setAutoScrollBar, setAutoUpdate, setBottomScrollBar,
setCurrentItem, setDragSelect, setScrollBar, setSmoothScrolling,
setTopItem, smoothScrolling, text, topItem

QListBoxItem
------------

   Requires QPixmap.

Member functions
----------------

   height, pixmap, text, width

QListBoxPixmap
--------------

   Inherits QListBoxItem

Member functions
----------------

   new

QListBoxText
------------

   Inherits QListBoxItem

Member functions
----------------

   new

DESCRIPTION
===========

   What you see is what you get.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QMenuBar class
**********************************

NAME
====

   QMenuBar - Interface to the Qt QMenuBar class

SYNOPSIS
========

   `use QMenuBar;'

   Inherits QFrame and QMenuData.

Member functions
----------------

   new

DESCRIPTION
===========

   What you see is what you get.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QMenuData class
***********************************

NAME
====

   QMenuData - Interface to the Qt QMenuData class

SYNOPSIS
========

   `use QMenuData;'

   Requires QObject, QPixmap and QPopupMenu.

Member functions
----------------

   new, accel, changeItem, clear, connectItem, count, disconnectItem, idAt,
indexOf, insertItem, insertSeparator, isItemChecked, isItemEnabled, pixmap,
removeItem, removeItemAt, setAccel, setId, setItemChecked, setItemEnabled,
text, updateItem

DESCRIPTION
===========

   What you see is what you get.

NOTES
=====

   findItem() is not, and will not be, interfaced. The 'member' argument of
insertItem() should not have a SLOT() or SIGNAL() around it. That's a
PerlQt no-no. Be sure to see `QObject(3)' in this node for info.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QMessageBox class
*************************************

NAME
====

   QMessageBox - Interface to the Qt QMessageBox class

SYNOPSIS
========

   `use QMessageBox;'

   Inherits QDialog.

Member functions
----------------

   new, adjustSize, buttonText, message, query, setButtonText, setText,
text

DESCRIPTION
===========

   What you see is what you get.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QMultiLineEdit class
****************************************

NAME
====

   QMultiLineEdit - Interface to the Qt QMultiLineEdit class

SYNOPSIS
========

   `use QMultiLineEdit;'

   Inherits QTableView.

   Requires QFont.

Member functions
----------------

   new, append, atBeginning, atEnd, autoUpdate, clear, copyText, cut,
deselect, getCursorPosition, insertAt, insertLine, isOverwriteMode,
isReadOnly, numLines, paste, removeLine, selectAll, setAutoUpdate,
setCursorPosition, setOverwriteMode, setReadOnly, setText, text, textLine

DESCRIPTION
===========

   What you see is what you get.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QObject class
*********************************

NAME
====

   QObject - Interface to the Qt QObject class

SYNOPSIS
========

   `use QObject;'

   `use signals 'sig1()', ..., 'sigx(int)';'

   `use slots 'slot1()', ..., 'sigx(int,int)';'

Member functions
----------------

   new, blockSignals, className, connect, disconnect, dumpObjectInfo,
dumpObjectTree, event, eventFilter, highPriority, inherits, insertChild,
installEventFilter, isA, isWidgetType, killTimer, killTimers, name,
removeChild, removeEventFilter, setName, signalsBlocked, startTimer

Virtual functions
-----------------

   timerEvent

DESCRIPTION
===========

   Except for children() and queryList(), every public QObject
member-function is fully-implemented. Unless noted below, all of those
functions are completely direct interfaces.

$connected = $reciever->connect(sender, signal, member)
     Do *NOT* attempt to use SIGNAL() or SLOT() on the signal and member
     arguments. They are not needed by PerlQt, because the connect()
     function can automatically determine whether the member argument is a
     signal or a slot, and the signal will always be a signal. The signal
     and member arguments must be strings. And at the moment, there isn't
     much room for error.

$connected = QObject::connect(sender, signal, reciever, member)
     Same as above listing, just as a normal function with a different
     argument-list.

$disconnected = $sender->disconnect(signal = undef, reciever = undef, member = undef)
     Remember *NOT* to use SIGNAL() and SLOT() with disconnect(). This
     function takes over for both the static disconnect() and the 3-arg
     member disconnect() in Qt.

$disconnected = $sender->disconnect(reciever, member = undef)
     Same warning about SIGNAL() and SLOT() as above.

timerEvent(event)
     This is a virtual function, meant to be reimplemented in your own
     classes. It is currently available through QObject and QWidget.

Signals and slots
-----------------

   Signals and slots are implemented in a limited way at the moment. You
may use no-arg signals and slots freely, as well as 1 and 2 integer
argument signals and slots.

   The declaration of signals and slots is done through the usage of 'use
signals' and 'use slots'. Any classes which have QObject in their
inheritance tree are free to use signals/slots after their superclass has
been included via require/use.

use signals 'sig1()', ..., 'sigx(int,int)'
     The arguments to `use signals' must be strings representing the signal
     prototypes *excluding* the object parameter. You may use `qw()' to
     quote the function prototypes, but it warns about commas when -w is
     in use.

     Add spaces at your own risk. Misspell at your own risk. PerlQt doesn't
     do any error-checking yet. All error-checking that is done is done by
     Qt. You may run `use signals' as many times as you want. I'm pretty
     sure that if you define the same signal-name twice, the latter
     prototype is used. But you should get a redefined function warning.
     Also, the argument-types are not checked yet.

     Running `use signals' exports a function named `emit' into your
     namespace.  It does nothing, and is just there for clarity and
     consistency with Qt where the emit keyword is just as void. When you
     emit a signal, you must call it as a method-call `$self->signal()',
     and not as `'signal()'' or `signal()' because it is not a string and
     it is not a normal function.

use slots 'slot1()', ..., 'slotx(int)'
     The arguments to `use slots' must be strings representing the
     prototypes of the slots you want to declare *excluding* the object
     parameter. The slot functions aren't cached by PerlQt, and are always
     called as full method-calls.

     Once you declare a function as being a slot, you may use connect() to
     connect any signal, Perl or C++, to it.

BUGS
====

   Signals and slots are seriously crippled. They do not check their
arguments, they only allow a couple of *integer only* arguments, and
there's a serious memory-leak which I can only attribute to signals and
slots or to virtual member-function overrides. At the moment, PerlQt
signals and slots are little more than proof-of-concept and it will take
significant effort to get it working right. Any suggestions are welcome.

SEE ALSO
========

   QObject(3qt), QGlobal(3)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QPaintDevice class
**************************************

NAME
====

   QPaintDevice - Interface to the Qt QPaintDevice class

SYNOPSIS
========

   `use QPaintDevice;'

Member functions
----------------

   devType, isExtDev, paintingActive

DESCRIPTION
===========

   A very strange class.

EXPORTED
========

   The `%PDT' and `%PDF' hashes are exported into the user's namespace.
They contain the values of the PD[FT]_* constants.

   bitBlt() is also exported, but in a strange twist of Perlian fate, it
can be called as a member-function.

     $widget->bitBlt(dx, dy, pixmap, sx, sy, sw, sh);

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QPainter class
**********************************

NAME
====

   QPainter - Interface to the Qt QPainter class

SYNOPSIS
========

   `use QPainter;'

   Requires QColor, QBrush, QFont, QFontInfo, QFontMetrics, QPaintDevice,
QPen, QPicture, QPixmap, QPoint, QPointArray, QRect, QRegion, QWMatrix

Member functions
----------------

   new, backgroundColor, backgroundMode, begin, boundingRect, brushOrigin,
clipRegion, device, drawArc, drawChord, drawEllipse, drawLine,
drawLineSegments, drawPie, drawPixmap, drawPoint, drawPolygon,
drawPolyline, drawQuadBezier, drawRect, drawRoundRect, drawText,
drawWinFocusRect, end, eraseRect, fillRect, font, fontInfo, fontMetrics,
hasClipping, hasViewXForm, hasWorldXForm, isActive, lineTo, moveTo, pen,
rasterOp, resetXForm, restore, rotate, save, scale, setBackgroundColor,
setBackgroundMode, setBrush, setBrushOrigin, setClipping, setClipRect,
setClipRegion, setFont, setPen, setRasterOp, setViewXForm, setViewport,
setWindow, setWorldMatrix, setWorldXForm, shear, translate, viewport,
window, worldMatrix, xForm, xFormDev

DESCRIPTION
===========

   All functions listed have every prototype version supported, mostly.
Any internal arguments are unavailable to PerlQt programmers.

EXPORTED
========

   The following variables are exported into the user's namespace on
behalf of `QPainter::drawText()' from `qwindefs.h'

   %Align $SingleLine $DontClip $ExpandTabs $ShowPrefix $WordBreak
$GrayText $DontPrint

   The `%BGMode' and `%RasterOp' hashes are also exported. `%BGMode'
contains the values in the BGMode enum in `qpainter.h' without the
trailing Mode, and `%RasterOp' contains the values in the RasterOp enum in
`qwindefs.h' without the trailing ROP.

SEE ALSO
========

   qpainter(3qt), QColor(3), QBrush(3), QFont(3), QPen(3)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QPalette and QColorGroup classes
****************************************************

NAME
====

   QPalette - Interface to the Qt QPalette and QColorGroup classes

SYNOPSIS
========

   `use QPalette;'

QColorGroup
-----------

   Requires QColor.

Member functions
----------------

   new, background, base, dark, foreground, light, mid, text

QPalette
--------

Member functions
----------------

   new, active, copy, disabled, normal, setActive, setDisabled, setNormal,
serialNumber

DESCRIPTION
===========

   What you see is what you get.

SEE ALSO
========

   QPalette(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QPen class
******************************

NAME
====

   QPen - Interface to the Qt QPen class

SYNOPSIS
========

   `use QPen;'

   Requires QColor.

Member functions
----------------

   new, color, setColor, setStyle, setWidth, style, width

DESCRIPTION
===========

   Except for the operators, this class is fully implemented.

EXPORTED
========

   The `%PenStyle' hash is exported into the user's namespace, and contains
all of the elements from the PenStyle enum defined in `qpen.h'.

SEE ALSO
========

   QPen(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QPicture class
**********************************

NAME
====

   QPicture - Interface to the Qt QPicture class

SYNOPSIS
========

   `use QPicture;'

   Inherits QPaintDevice.

Member functions
----------------

DESCRIPTION
===========

   What you see is what you get.

SEE ALSO
========

   QPicture(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QPixmap class
*********************************

NAME
====

   QPixmap - Interface to the Qt QPixmap class

SYNOPSIS
========

   `use QPixmap;'

   Inherits QPaintDevice.

   Requires QBitmap, QColor, QImage, and QWMatrix.

Member functions
----------------

   new, defaultDepth, depth, detach, fill, height, imageFormat,
isOptimized, isQBitmap, load, loadFromData, isGloballyOptimized, isNull,
optimize, optimizeGlobally, rect, resize, save, size, trueMatrix, width,
xForm

DESCRIPTION
===========

   Whatever has been interfaced is fully interfaced.

   The loadFromData function does not take a 'len' argument. All the other
arguments are normal and in the original order.

EXPORTED
========

   The `%ColorMode' hash is exported into the user's namespace. The
elements of `%ColorMode' contain all the constants in QPainter, which come
from the QPainter::ColorMode enum.

SEE ALSO
========

   QPixmap(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QPoint class
********************************

NAME
====

   QPoint - Interface to the Qt QPoint class

SYNOPSIS
========

   `use QPoint;'

Member functions
----------------

   new, setX, setY, x, y

DESCRIPTION
===========

   Most of QPoint is operators, and I haven't interfaced the operators yet.
Everything else, what little there is of it, is interfaced.

RESTRICTIONS
============

   The functions rx() and ry() will not be interfaced to PerlQt unless
there is sufficient demand for it, or lvalue Perl XSUBs become a reality.

SEE ALSO
========

   QPoint(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QPointArray class
*************************************

NAME
====

   QPointArray - Interface to the Qt QPointArray class

SYNOPSIS
========

   `use QPointArray;'

Member functions
----------------

   new, at, boundingRect, copy, fill, makeArc, makeEllipse, point,
putPoints, quadBezier, setPoint, setPoints, translate

DESCRIPTION
===========

   Many of the functions in the original QPointArray used nPoints to
specify the number of arguments or elements in *points. Perl is fortunatly
better than that, so just ditch nPoints and arrays of QCOORD's. Just type
the arguments in a list starting from where the nPoints would be.

SEE ALSO
========

   QPointArray(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QPopupMenu class
************************************

NAME
====

   QPopupMenu - Interface to the Qt QPopupMenu class

SYNOPSIS
========

   `use QPopupMenu;'

   Inherits QTableView and QMenuData.

   Requires QPoint.

Member functions
----------------

   new, popup

DESCRIPTION
===========

   What you see is what you get.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QPrinter class
**********************************

NAME
====

   QPrinter - Interface to the Qt QPrinter class

SYNOPSIS
========

   `use QPrinter;'

Member functions
----------------

   new, abort, aborted, creator, docName, fromPage, maxPage, minPage,
numCopies, newPage, orientation, outputFileName, outputToFile, pageSize,
printerName, printProgram, setup, setCreator, setDocName, setFromTo,
setMinMax, setNumCopies, setOrientation, setOutputFileName,
setOutputToFile, setPageSize, setPrinterName, setPrintProgram, toPage

DESCRIPTION
===========

   What you see is what you get.

EXPORTED
========

   The `%Orientation' and `%PageSize' hashes are exported to the user's
namespace. Their keys correspond to the matching enums in QPainter.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QPushButton class
*************************************

NAME
====

   QPushButton - Interface to the Qt QPushButton class

SYNOPSIS
========

   `use QPushButton;'

   Inherits QButton.

Member functions
----------------

   new, autoDefault, isDefault, setAutoDefault, setDefault

DESCRIPTION
===========

   Fully interfaced.

SEE ALSO
========

   QPushButton(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QRadioButton class
**************************************

NAME
====

   QRadioButton - Interface to the Qt QRadioButton class

SYNOPSIS
========

   `use QRadioButton;'

   Inherits QButton.

Member functions
----------------

   new, isChecked, setChecked

DESCRIPTION
===========

   What you see is what you get.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QRangeControl class
***************************************

NAME
====

   QRangeControl - Interface to the Qt QRangeControl class

SYNOPSIS
========

   `use QRangeControl;'

Member functions
----------------

   new, addLine, addPage, lineStep, maxValue, minValue, pageStep, setRange,
setSteps, setValue, subtractLine, subtractPage, value

DESCRIPTION
===========

   What you see is what you get

SEE ALSO
========

   qrangecontrol(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QRect class
*******************************

NAME
====

   QRect - Interface to the Qt QRect class

SYNOPSIS
========

   `use QRect;'

   Requires QPoint and QSize.

Member functions
----------------

   new, bottom, bottomLeft, bottomRight, center, contains, coords, height,
intersect, intersects, isEmpty, isNull, isValid, left, moveBottomLeft,
moveBottomRight, moveBy, moveCenter, moveTopLeft, moveTopRight, normalize,
rect, right, setBottom, setCoords, setHeight, setLeft, setRect, setRight,
setSize, setTop, setWidth, setX, setY, size, top, topLeft, topRight, unite,
width, x, y

DESCRIPTION
===========

   Everything but the operators is fully interfaced.

SEE ALSO
========

   QRect(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QRegion class
*********************************

NAME
====

   QRegion - Interface to the Qt QRegion class

SYNOPSIS
========

   `use QRegion;'

   Requires QPoint, QPointArray, and QRect.

Member functions
----------------

   new, contains, intersect, isEmpty, isNull, subtract, translate, unite,
xor

DESCRIPTION
===========

   Everything but the operators has been successfully interfaced.

SEE ALSO
========

   QRegion(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QScrollBar class
************************************

NAME
====

   QScrollBar - Interface to the Qt QScrollBar class

SYNOPSIS
========

   `use QScrollBar;'

   Inherits QWidget and QRangeControl.

Member functions
----------------

   new, orientation, setOrientation, setRange, setTracking, setValue,
tracking

DESCRIPTION
===========

   Nothing unusual, everything listed is interfaced.

EXPORTED
========

   The `%Orientation' hash is exported into the user's namespace. The
elements of `%Orientation' are `Horizontal' and `Vertical', and they
represent the possible orientations of the scrollbar.

SEE ALSO
========

   QScrollBar(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QSize class
*******************************

NAME
====

   QSize - Interface to the Qt QSize class

SYNOPSIS
========

   Requires QPoint.

Member functions
----------------

   new, height, isEmpty, isNull, isValid, setHeight, setWidth, width

DESCRIPTION
===========

   Rumors about the lack of operators in PerlQt's QSize are true!

SEE ALSO
========

   QSize(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QSlider class
*********************************

NAME
====

   QSlider - Interface to the Qt QSlider class

SYNOPSIS
========

   `use QSlider;'

   Inherits QWidget and QRangeControl.

Member functions
----------------

   new, addStep, orientation, setOrientation, setTickmarks, setTracking,
setValue, sliderRect, subtractSteps, tickInterval, tickmarks, tracking

DESCRIPTION
===========

   What you see is what you get.

EXPORTED
========

   The `%Orientation' and `%TickSetting' hashes are exported into the
user's namespace. The elements of `%Orientation' are `Horizontal' and
`Vertical', and they represent the possible orientations of the slider. The
`%TickSetting' hash has all the tick setting constants.

SEE ALSO
========

   qslider(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QTabBar class
*********************************

NAME
====

   QTabBar - Interface to the Qt QTabBar class

SYNOPSIS
========

   `use QTabBar;'

   Inherits QWidget.

Member functions
----------------

   new, addTab, isTabEnabled, setTabEnabled

QTab
----

     $tab = new QTab;
     $$tab{label} = "Hello World";
     $$tab{r} = new QRect(1, 2, 3, 4);
     $$tab{enabled} = 1;
     $$tab{id} = 10;

DESCRIPTION
===========

   What you see is what you get.

NOTES
=====

   QTab is a tied hash reference which accesses a real QTab.  keys() does
not work on a QTab.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QTabDialog class
************************************

NAME
====

   QTabDialog - Interface to the Qt QTabDialog class

SYNOPSIS
========

   `use QTabDialog;'

   Inherits QDialog.

Member functions
----------------

   new, addTab, hasApplyButton, hasCancelButton, hasDefaultButton,
isTabEnabled, setApplyButton, setCancelButton, setDefaultButton,
setTabEnabled

DESCRIPTION
===========

   What you see is what you get.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QTableView class
************************************

NAME
====

   QTableView - Interface to the Qt QTableView class

SYNOPSIS
========

   `use QTableView;'

   Inherits QFrame.

DESCRIPTION
===========

   Empty.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QTimer class
********************************

NAME
====

   QTimer - Interface to the Qt QTimer class

SYNOPSIS
========

   `use QTimer;'

   Inherits QObject.

Member functions
----------------

   new, changeInterval, isActive, singleShot, start, stop

DESCRIPTION
===========

   What you see is what you get.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QToolTip and QToolTipGroup classes
******************************************************

NAME
====

   QToolTip - Interface to the Qt QToolTip and QToolTipGroup classes

Member functions
----------------

SYNOPSIS
========

   `use QToolTip;'

DESCRIPTION
===========

   What you see is what you get.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QWMatrix class
**********************************

NAME
====

   QWMatrix - Interface to the Qt QWMatrix class

SYNOPSIS
========

   `use QWMatrix;'

   Requires QPoint, QPointArray, and QRect.

Member functions
----------------

   new, dx, dy, invert, m11, m12, m21, m22, map, reset, rotate, scale,
shear, setMatrix, translate

DESCRIPTION
===========

   Except for the operators, fully interfaced.

SEE ALSO
========

   QWMatrix(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QWidget class
*********************************

NAME
====

   QWidget - Interface to the Qt QWidget class

SYNOPSIS
========

   `use QWidget;'

   Inherits QObject and QPaintDevice.

   Requires QEvent, QFont, QPixmap, QPoint, QRect, and QSize.

Member functions
----------------

   new, adjustSize, backgroundColor, backgroundPixmap, caption,
childrenRect, clearFocus, close, drawText, erase, focusPolicy, font,
foregroundColor, frameGeometry, geometry, grabKeyboard, grabMouse,
hasFocus, hasMouseTracking, height, hide, icon, iconText, iconify,
isActiveWindow, isDesktop, isEnabled, isFocusEnabled, isModal, isPopup,
isTopLevel, isUpdatesEnabled, isVisible, keyboardGrabber, lower,
mapFromGlobal, mapFromParent, mapToGlobal, mapToParent, maximumSize,
minimumSize, mouseGrabber, move, pos, raise, recreate, rect,
releaseKeyboard, releaseMouse, repaint, resize, scroll, setActiveWindow,
setBackgroundColor, setBackgroundPixmap, setCaption, setEnabled,
setFixedSize, setFocus, setFocusPolicy, setFont, setGeometry, setIcon,
setIconText, setMaximumSize, setMinimumSize, setMouseTracking,
setSizeIncrement, setStyle, setUpdatesEnabled, show, size, sizeHint,
sizeIncrement, style, topLevelWidget, update, width, winId, x, y

Virtual functions
-----------------

   mouseMoveEvent, mousePressEvent, mouseReleaseEvent, paintEvent,
resizeEvent

DESCRIPTION
===========

   Every function made available to Perl is meant to be interfaced
identically to C++ Qt.

EXPORTED
========

   The `%FocusPolicy' and `%WFlags' hashes are exported into the user's
namespace.

   `%FocusPolicy' contains all of the constants in QWidget that end in
Focus.  That trailing *Focus* is removed from the end of the keys for
brevity.

   The `%WFlags' hash is much more involved. It contains all of the
`WState_*', `WType_*', and `WStyle_*' flags, as well as quite a few others
that begin with W. You can get a full list of them from `qwindefs.h'.

   But you won't find these constants exactly as they're spelled out in
there.  I've stripped all the leading W's, for example. And all of the
constants which have an underscore in them have been split up into two
components based on the underscore. I think a few examples are in order.

     Was: WStyle_NormalBorder
     Now: $WFlags{Style}{NormalBorder}
     Was: WState_TrackMouse
     Now: $WFlags{State}{TrackMouse}
     Was: WPaintDesktop
     Now: $WFlags{PaintDesktop}

   You can hopefully figure out the rest yourself.

SEE ALSO
========

   QWidget(3qt)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

Interface to the Qt QWindow class
*********************************

NAME
====

   QWindow - Interface to the Qt QWindow class

SYNOPSIS
========

   `use QWindow;'

   Inherits QWidget.

Member functions
----------------

   new

DESCRIPTION
===========

   Not much here.

AUTHOR
======

   Ashley Winters <jql@accessone.com>

A Perl module interface to Qt
*****************************

NAME
====

   Qt - A Perl module interface to Qt

SYNOPSIS
========

   `use Qt;'

   Requires QApplication and QGlobal.

DESCRIPTION
===========

   The Qt module itself only creates a $qApp and exports some QGlobal
imports.

   This module is not the whole of the Qt interface, though. Each header in
Qt which holds a class is represented by a module with the name of that
class. Classes like QWidget and QApplication are represented by modules of
the same name. QResizeEvent is not a module, but rather is part of the
QEvent module, just as the QResizeEvent class is a part of `qevent.h'.

   Each class header that has been interfaced to Perl has a pod attached
which describes the function interface from Qt.

EXPORTED
========

   The Qt module exports $qApp and `&qRound'.

SEE ALSO
========

   QApplication(3qt), QApplication(3), QGlobal(3)

AUTHOR
======

   Ashley Winters <jql@accessone.com>

A Simpler Syntax for Perl-Tk GUI Building
*****************************************

NAME
====

   Qtk::QuickTk - A Simpler Syntax for Perl-Tk GUI Building

SYNOPSIS
========

     use Tk;
     use Qtk::QuickTk

     # need to set $filename, e.g.:  my $filename='miniapp.qtk';

     my $app=Qtk::Quicktk->new($filename);
     die "QuickTk constructor unable to read GUI spec: $filename\n"
       unless defined $app;

     MainLoop;die "QuickTk fell through past MainLoop\n";

   or, alternatively, make a QuickTk script directly executable, with the
following first line (see full demo script in EXAMPLES, below:

     exec /usr/bin/perl -M'Qtk::QuickTk=app' -e app $0;exit

REQUIRES
========

   *QuickTk* uses modules:   *Text::TreeFile* (optionally), Tk,
FileHandle, Carp, English, Exporter and *Autoloader*.

DESCRIPTION
===========

   *QuickTk* supports a simplified syntax for specifying GUI-based
applications using *perl-tk* (module `Tk.pm' and friends).  A companion
module, `Text::TreeFile', supports comments, include files, continuation
lines and special interpretation of a strict indentation convention to
indicate tree-like hierarchical nesting.  Each node of a QuickTk GUI
specification is a character string which succinctly and clearly specifies
the properties of a GUI widget or event binding.  Such specification
documents are quick and easy to write, read and maintain.

OPTIONS
=======

   The GUI specification can be provided to *QuickTk* in any of several
forms, the generated code can be logged to a file, and execution of the
code can be avoided, to allow code-generation only.

EXAMPLE
=======

     -------------- executable as a shell script -------------------------------
     exec /usr/bin/perl -M'Qtk::QuickTk=app' -e app $0;exit
     #   file:  miniapp

     m MainWindow      title:'QuickTk Minimal Demo'
       mb Frame        side:top fill:x :
         f Menubutton  side:left       : text:File
           o c         label:Open sub:my($wid)=@_;
                         ...my $out=$$w{mts};my $tf=$$w{tf};
                         ...$$gl{efile}=$tf->Show;$$gl{eww}=0;
                         ...my $fh=new FileHandle "<$$gl{efile}";
                         ...while(<$fh>) { $out->insert('end',$_); }
                         ...close $fh;$out->yview('1.0');print "ok 2\n";
           q c         label:Quit sub:print "ok 8\n";exit;
         t Menubutton  side:left       : text:Tool
           d c         label:'Directory Listing'
                         ... sub:$$gl{widgets}{mts}->insert('end',
                         ...  `pwd`);$$gl{widgets}{mts}->insert('end',
                         ...  `ls -alF`);print "ok 3\n";
           s c         label:Satisfaction sub:print "ok 4\n";
         h Menubutton  side:right      : text:Help
           a c         label:About sub:$$gl{widgets}{mts}->insert('end',
                         ... 'this is a demo of perl module Qtk::QuickTk');
                         ... print "ok 5\n";
       tb Frame        side:top fill:x :
         d Button      side:left       : text:Dir
                         ... sub:$$w{mts}->insert('end',`ls -alF`);
                         ... print "ok 6\n";
         q Button      side:left       : text:Geom sub:$$w{mts}->insert('end',
                         ... "geom: ".$$w{m}->geometry."\n");
                         ... print "ok 7\n";
       ts Scrolled     side:top fill:both expand:1 : Text: scrollbars:osoe
       tf FileSelect   nopack                           : directory:.
     -------------- end of executable shell script example ---------------------

FILE FORMAT
===========

   By default, `Qtk::QuickTk' uses the `Text::TreeFile' module to read a
file containing a GUI specification, in the *QuickTk* mini-language.  The
low-level format of this file is as follows.  Each widget is specified in
a node of the tree in such a file.  The language for widget specifications
is described further below.

   The file format supported relies upon indentation of text strings, to
indicate hierarchical nesting for the tree structure.  Strict indentation
(of two space characters per nesting level) is used to represent
parent-child structure.

Comments
--------

   A line consisting exclusively of whitespace, or a line beginning with
either the pound-sign ("#"), the semicolon (";"), or the forward slash
("/") character will be ignored as a comment.    In the very first line of
a file, the initial characters, "exec ", will indicate a comment line.

Continuation Lines
------------------

   A line beginning with whitespace followed by three period (".")
characters, will be concatenated to the previous line, as a continuation.
The preceding end-of-line, the initial whitespace and the ellipsis ("...")
will be removed and otherwise ignored, to allow long strings to be
represented within line-length constraints.

Include Files
-------------

   In addition, any line consisting of indentation followed by "include"
will be interpreted as a file-include request.  In this case, succeeding
whitespace followed by a file specification will cause the contents of the
named file to be substituted at that point in the tree.  The included file
will be sought in the same directory as the file including it.

WIDGET SPECIFICATIONS
=====================

   The basic format for GUI widget specifications is a text string that
has two parts.  The first is an ID section which identifies the widget,
and the second is an arguments section which provides the specifics of how
the widget is to be configured.

Widget ID
---------

   There are four kinds of specifications, each with a variation in the
details of these two parts.  In the most common case (that for *MainWindow*
and most other widgets), the ID section is made of two subparts.  First is
the name your script can use to reference the widget later, and second is
the widget type name, chosen from the many available in the Tk widget
library (e.g. Button, *MainWindow*, Menubutton).  In the special case of a
menu item, the second part of the ID section can be a single letter
identifying one of five types of available menu items, for short, or the
name of the type itself.  The name subpart must be unique only within the
same level of indentation under a parent widget, because the name you will
use to refer to the widget will usually (automatically) be the
concatenation of its name with all its ancestors' names.

     For specifications of bindings of events to actions, the ID part is a
     single event identifier enclosed in angle brackets ("Less_Than_Special_Sequence" and "Greater_Than_Special_Sequence").

   See `"EXAMPLES"' in this node, or `Qtk::QuickTk::scripts(3pm)' in this
node, for clarification.

   Here are samples of each of the four kinds of specifications:

     m    MainWindow                title:'QuickTk Demo'
     f    Menubutton    side:left : text:File
     o    c                         label:Open sub:exit;
     <CR>                           sub:$$gl{command}=$$gl{inputline};

Widget Arguments
----------------

   Each of the four kinds of specifications can have arguments provided.
There are two categories of arguments, and these are separated by a colon
(":") character which, itself, is surrounded by spaces.  The first type of
arguments is the "packing options" and the second is the "configuration
options".  The packing options (and the colon delimiter) are not specified
for three of the four kinds of specifications.  These are the MainWindow,
the menu items, and the event bindings.  The packing options are used for
the most common widget specifications - the ones for generic widgets - so
these specifications will always have the space-surrounded colon delimiter
unless no configuration option arguments need to be specified.

   To write these specifications you must be acquainted with the perl-tk
(module `Tk.pm') library of widgets and how to use it.  The QuickTk module
provides a good many simplifications of syntax, though, and details of
these are described in `Qtk::QuickTk::details(3pm)' in this node, see
Qtk/QuickTk/scripts, and demonstrated in the example
scripts.

CAVEATS
=======

   *QuickTk* provides none of the GUI-building widgets, functions or other
facilities.  It provides only for simplified syntax for accessing the
capabilities and features of `perl-tk' (the perl module, *Tk(3pm)* and
friends), so familiarity with those materials is prerequisite to using
*QuickTk*.

AUTHOR
======

   John Kirk <`johnkirk@dystanhays.com'>

COPYRIGHT
=========

   Copyright (c) 2000 John Kirk. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `Text::TreeFile(3pm)' in this node - for the low-level file format it
supports,

   `Qtk::QuickTk::scripts(3pm)' in this node - for exhaustive description
of the syntax,

   `Qtk::QuickTk::details(3pm)' in this node - for precise definition of
usage details,

   `Qtk::QuickTk::internals(3pm)' in this node - for implementation
details,

   `Tk::UserGuide(3pm)' in this node - for an introduction to perl-tk,

   `widget(1)' in this node - for examples of most of the perl-tk widgets,
etc.,

   and `http://perl.dystanhays.com/jnk' - for related material on this
module.

BUGS
====

   Uses (deprecated for libraries) `English(3pm)', which should be removed.

   Also, exceptions are handled poorly, inconsistently and unclearly.  The
`Carp(3pm)' module should be used, the behavior should be made more clear,
and the exceptions should be handled in a consistent manner.

   Documentation is incomplete (although the module code is very short,
thus somewhat accessible) and examples are not very thorough.

   The code is ready for an overhaul to reduce near-duplication and improve
modularity.

precise definition of usage details
***********************************

NAME
====

   Qtk::QuickTk::details - precise definition of usage details

SYNOPSIS
========

     use Tk;
     use Qtk::QuickTk

     # need to set $filename, e.g.:  my $filename='miniapp.qtk';

     my $app=Qtk::Quicktk->new($filename);
     die "QuickTk constructor unable to read GUI spec: $filename\n"
       unless defined $app;

     MainLoop;die "QuickTk fell through past MainLoop\n";

   or, alternatively, make a QuickTk script directly executable, with the
following first line (see full demo script in EXAMPLES, below:

     exec /usr/bin/perl -M'Qtk::QuickTk=app' -e app $0;exit

DESCRIPTION
===========

   (Introduction not written yet.)

FUNCTION: new [ spec, [ *codeout*, [ *genonly* ] ] ]
====================================================

   The constructor (function "new") for module *Qtk::QuickTk* can be
invoked with zero, one, two or three parameters.  The first is a GUI
specification, which can take several forms, as below, under `"spec"' in
this node; the second, a filename for logging generated code; and the
third, a generate-only flag.  If no parameters are specified, an object (a
blessed reference to a hash) will be returned with only the prototype
entries present.  In this case one might create a GUI spec by other
external means and put it into the hash.

Parameter: spec
---------------

   If at least one parameter is specified, the first will be taken to be
the specification for a GUI based application.  This spec may be in one of
three forms:  (1) a filename, (2) a reference blessed into the
*Text::TreeFile* class, or (3) a reference to a tree of text strings.

spec parameter: as filename
     If the spec parameter is a scalar, but not a reference, it will be
     interpreted as a filename and passed to module *Text::TreeFile* to
     create a tree of strings.  This tree will be used as the GUI
     specification for further processing.

spec parameter: as *Text:TreeFile* ref
     If the spec parameter is a reference that has been blessed into the
     *Text::TreeFile* class, the resulting tree of strings will be used as
     the GUI specification for further processing.

spec parameter: as tree of strings
     If the spec parameter is a reference to an array of the correct form
     to be a string tree node, it will be interpreted as the GUI
     specification for further processing.

Parameter: *codeout*
--------------------

   If at least two parameters are specified in the call to new(), the
second will be interpreted as a filename for output logging of the
generated *perl-tk* code.  If the undef value is specified, then logging
will not occur.  If this parameter is not specified, the default is not to
log generated code to a file at all.

Parameter: *genonly*
--------------------

   If three parameters are specified in the call to new(), the third will
be interpreted as a flag indicating whether to execute the *perl-tk* code
generated.  If the undef value is specified or this parameter is not
specified, the default is to execute the code generated.  If a value is
specified, then no generated *perl-tk* code will be executed.

FUNCTION: app [ [ *genonly* ] *gfilename* ]
===========================================

   *app()* will expect the first argument to contain the name of the
*QuickTk* script to execute (often, the script that invoked it).

FUNCTION: *createwidget* args *specname*
========================================

   *createwidget()* will expect the first argument to be a reference to an
array containing values to which the *QuickTk* script widget spec refers
by names $0, $1, ..., and the second argument to be a string which is the
name of the widget specified in the script with the 'nocreate' packing
option set.  This would normally be called by a callback specified
somewhere in the script.

FUNCTION: *showglobals*
=======================

   (Not written yet.)

FUNCTION: *logit*
=================

   (Not written yet.)

FUNCTION: logg
==============

   (Not written yet.)

TEST SCRIPT: test.pl
====================

   (Not written yet.)

EXPORTS
=======

   Nothing is exported by default.  Functions *app()*, *createwidget()*,
*showglobals()*, *logit()*, and *logg()* may be imported on request.  The
module's new() function returns a blessed reference to a hash which
contains a number of data items. (Refer to Qtk/QuickTk/internals,
for details, if you want them.)  This hash acts as
a global repository for variables accessible to the application.  See
Qtk/QuickTk/scripts, for instruction and sample
uses of this facility.

EXCEPTIONS
==========

   (Not written yet.)

BUGS
====

   (Not written yet.)

implementation details
**********************

NAME
====

   Qtk::QuickTk::internals - implementation details

SYNOPSIS
========

     use Qtk::QuickTk;

     sub _loadwidget;
     sub _loadmenitm;
     sub _bindevent;
     sub _getargs;
     sub _gettitle;
     sub _getcommand;
     sub _getsub;
     sub _getini;

DESCRIPTION
===========

     (Nothing written, yet.)

exhaustive description of the syntax
************************************

NAME
====

   Qtk::QuickTk::scripts - exhaustive description of the syntax

SYNOPSIS
========

   (example script, actually)

     exec /usr/bin/perl -M'Qtk::QuickTk=app' -e app $0;exit
     m MainWindow         title:'QuickTk Minimal Demo'
       mb Frame           side:top fill:x :
         f Menubutton     side:left       : text:File
           o command      label:Open sub:my($wid)=@_;
                            ...my $out=$$w{mts};my $tf=$$w{tf};
                            ...$$gl{efile}=$tf->Show;$$gl{eww}=0;
                            ...my $fh=new FileHandle "<$$gl{efile}";
                            ...while(<$fh>) { $out->insert('end',$_); }
                            ...close $fh;$out->yview('1.0');print "ok 2\n";
           q command      label:Quit sub:print "ok 8\n";exit;
         t Menubutton     side:left       : text:Tool
           d command      label:'Directory Listing'
                            ... sub:$$gl{widgets}{mts}->insert('end',
                            ...  `pwd`);$$gl{widgets}{mts}->insert('end',
                            ...  `ls -alF`);print "ok 3\n";
           s command      label: Satisfaction sub:print "ok 4\n";
         h Menubutton     side:right      : text:Help
           a command      label:About sub:$$gl{widgets}{mts}->insert('end',
                            ... 'this is a demo of perl module Qtk::QuickTk');
                            ... print "ok 5\n";
       tb Frame           side:top fill:x :
         d Button         side:left       : text:Dir
                          ... sub:$$w{mts}->insert('end',`ls -alF`);
                          ... print "ok 6\n";
         q Button         side:left       : text:Geom sub:$$w{mts}->insert('end',
                          ... "geom: ".$$w{m}->geometry."\n");
                          ... print "ok 7\n";
       ts Scrolled        side:top fill:both expand:1 : Text: scrollbars:osoe
       tf FileSelect      nopack                      : directory:.

DESCRIPTION
===========

   This document attempts to completely specify the *QuickTk*
mini-language.  Everything you need to know to write GUI applications with
this module should appear here, assuming you are familiar with the
*perl-tk* (the `Tk.pm' module, and friends) library to which *QuickTk*
provides simpler access.

   See 1,
of course, to look at examples.  Several of them are provided, chosen to
be representative of a wide range of features exercised.  A plan is afoot
to reference them directly in documentation, where features are described
and, perhaps, vice-versa.

   See 2,
without identifying them as non-portable.
(witness the next couple of paragraphs, for instance) *QuickTk* works well
in other contexts, but we've been slow about properly flagging the
caveats.  The plan is to correct the documentation soon.

   The most common way to use *QuickTk* is to make a script in a file whose
first line is the following (Make sure the absolute path reference to your
perl binary executable is correct, though.):

     exec /usr/bin/perl -M'Qtk::QuickTk=app' -e app $0;exit

   When the script is executed by your shell, this should cause perl to be
started (without creating a new process), bringing in the *QuickTk* module
and asking it to import the *app()* function into the *main::* namespace.
Then it executes *app()* and makes the name of your script ($0, above) the
first (the only) command-line argument to the executing perl program.  The
*app()* function will request module *Text::TreeFile* to come back and
read your script into a tree-of-text-strings data structure (respecting
comments, continuation lines, include-file requests, and strict
two-space-per-level indentation to indicate parent-child nesting of tree
nodes) which will then be interpreted and executed by *QuickTk* as a GUI
application specification, where each text string is taken to specify a
widget or event binding.  See `Text::TreeFile(3pm)' in this node for more
details of that format, and `Tk(3pm)' in this node and manpages for the
other `Tk::*(3pm)' modules, for information about the functionality
available to your application.

APPLICATION VARIABLES
=====================

   *QuickTk* provides a hash, returned by the new() constructor, which is
blessed into the *Qtk::QuickTk* class as a namespace for variables which
are "global" to the application.  Perl code included in the script will be
evaluated in a context which provides both a reference to this hash (as
variable, `$gl'), and a reference to another hash within it (as variable,
`$w', which is short for, and synonymous with, `$$gl{widgets}') for
convenience.

   The upshot of this is that the following conventions are enabled, for
referring to variables (objects) in *QuickTk*.  First, to use a global
variable named "var", you specify the syntax, `"$$gl{var}"'.  Second, to
indicate a variable by reference (used in "-textvariable" options, for
instance) you specify the syntax, `"\$$gl{var}"', for the example variable
mentioned above.  Third, to refer to a widget previously created, you use
the name you specified as the very first field in the spec for that widget
("m", in the first example line, below) as the key to either the
`"$gl->{widgets}"' hash (e.g. `$$gl{widgets}{m}', or
`$gl->{widgets}->{m}') or for short, to the `"$w"' hash (e.g.  `$$w{m}',
or `$w->{m}'), for the *MainWindow* widget specified in the first example
line, below.  This is commonly done for the purpose of accessing object
methods of a widget.

   Here are several examples of using application variables:

Example of referencing an already-created widget
------------------------------------------------

   First, a *QuickTk* spec makes a main window, with a title:

     m MainWindow title:'QuickTk Demonstration Application'

   then, later, some code (in a callback, perhaps) gets executed:

     $$w{m}->configure(-title=>'QuickTk (updated) Demo App');
     print "The MainWindow title is now: ",
           $$gl{widgets}{m}->cget(-title),"\n";

   Note that, above, the "m" in `$$w{m}' and in `$$gl{widgets}{m}' is a
direct reference to the "m" which is the first field in the *QuickTk*
widget spec shown just previously.

   Also note that the *MainWindow* is referred-to both via the short
`$$w{m}' form and the longer, more explicit, `$$gl{widgets}{m}' form, in
different places.

   The name by which you refer to a widget in your code ("m", in the
example above) will be the concatenation of all the ancestors' names, and
the one for the current widget, as specified in the name field of your
script's widget spec.  Thus, note in the example in `"SYNOPSIS"' in this
node, a widget is accessed using the name, *"mts"*, as:
`"$$gl{widgets}{mts}"' while the widget is identified with only *"ts"* in
the script.  This is because the *"ts"* widget is a child of parent *"m"*,
yielding *"mts"* as the fully qualified, complete name.

Example of keeping a label updated, directly from an entry field
----------------------------------------------------------------

   These two *QuickTk* widget specs may occur in widely separated parts of
the user interface for an application:

     mce Entry pack:left : textvariable:\$$gl{inp}
     mcp Label pack:left : textvariable:\$$gl{inp}

   As text is typed into the Entry widget, it will show immediately
(simultaneously) in the Label widget.

Example of updating a label on demand, from an entry field
----------------------------------------------------------

   Text entered into the Entry widget will be kept in the variable named
"input", and the Label widget will show text from the variable named
"display".  Only when the Button is pressed will the text in the variable
named "input" get copied into the variable named "display" and, thus, be
displayed by the Label.

     mce Entry pack:left : textvariable:\$$gl{input}
     mcp Label pack:left : textvariable:\$$gl{display}
     mcb Button pack:left : text:Update sub:$$gl{display}=$$gl{input};

SCRIPT SYNTAX
=============

   The remainder of this document is devoted to enumerating and describing
use of the (mostly syntactic) features that the *QuickTk* language
provides.  We will call each node of the tree representing your GUI
specification either a "node", a "widget spec", or a "spec" (for short).
There are some commonalities among all specs, but differences are
important among the formats of the four basic spec types:

(1) the 'toplevel' spec type
----------------------------

   Either a *MainWindow* or a *TopLevel* widget spec.

(2) the 'menu item' spec type
-----------------------------

   This type refers to widgets that are children of a Menubutton or Menu
widget.  The Tk library provides five of these, as described subsequently
in this document.

(3) the 'event binding' spec type
---------------------------------

   This is sometimes referred to as an event or binding, for short.  This
type is a spec that's not a widget but, rather, a binding of an action to
a particular event that may occur in the parent widget's window.

(4) the 'generic widget' spec type
----------------------------------

   This type of spec is sometimes called just widget, for short.  This is
the most common spec, referring to any other widget in the Tk library's
repertoire not mentioned in the first three categories.

Spec Forms
----------

   All specs are of the form:

     <ID section> <arguments section>

   and the arguments section can have either or both of:

     <packing options> : <configuration options>

   although the composition of each (ID or arguments) section will be
somewhat different among the four main spec types.  Options are all
specified as:

     <option name>:<option value>

   but note that the colon (":") character, above, *must not* have any
surrounding spaces while the one separating the configuration options from
the packing options (shown previously) must be surrounded by spaces.

   Looking at the examples provided will give the best introduction to
writing specifications, but this document offers precise definition of the
conventions for reference use.  Of course, the module code is relatively
brief, so reading that can be a practical arbiter in case of failure to
communicate on the part of this document.

   We'll describe the differences among the four main spec types first for
the ID section, and next for the arguments section.  Then, we will
enumerate the details (held in common among all the spec types) of
specifying option arguments.

ID SECTION
==========

   The ID section always follows the indentation and is delimited from any
following arguments by spaces.  The differences, for each main spec type
are as follows:

Toplevel and Generic Widget Specs
---------------------------------

   The ID section for these specs has two parts, delimited by spaces.  The
first part is a name that will be used as a hash key to allow the
application to refer directly to the widget subsequently to its creation.
The second part is the name of the widget type (chosen from the *perl-tk*
library documentation) for the widget to be created.  e.g.  Button,
Menubutton, *MainWindow*, or *TopLevel*.

Menu Item Widget Specs
----------------------

   The ID section for these specs has two parts, delimited by spaces.  The
first part is a name that will be used to construct a hash key to allow
the application to refer directly to the widget subsequently to its
creation.  The second part can be either a single character indicating one
of the five widget types provided by Tk, or the name that Tk uses, itself,
as shown in the chart below.  The widget types allowed are:

     letter  Tk name         description of effect when menu item is chosen
     ------  -----------     -----------------------------------------------
         c   command      -- an action to perform

     m   cascade      -- a submenu to post

     -   separator    -- no action (separates groups of menu items)

     k   checkbutton  -- sets values of any of several boolean variables

     r   radiobutton  -- sets one of several values for a variable

Event Binding Specs
-------------------

   The ID section for these specs has only a single part, recognized by
surrounding angle brackets ("<" and ">").  This part identifies the event
(which may occur in the parent widget's window) that is to be bound to the
action specified in the arguments section.  Examples of events are:
"<Tab>", "<CR>", "<Button>", "<Double-Click>", "<Right-Click>", "<A>" and
"<Ctrl-A>".

ARGUMENTS SECTION
=================

   The ID section always follows the indentation and is delimited from any
following arguments by spaces.  The differences, for each main spec type
are as follows:

Generic Widget Specs
--------------------

   There are three formats, depending on whether you have options in both,
or just one category:

     <packing options> : <configuration options>
     : <configuration options>
     <packing options>

Toplevel and Menu Item Widget Specs
-----------------------------------

   These widget types take no <packing options>, so the format is simple:

     <configuration options>

Event Binding Specs
-------------------

   This kind of spec only needs the action to be bound to the event:

     <action bound to event>

OPTION SPECS
============

   There are six variations of the form of a single item in the list of
<packing options> or <configuration options> in the <arguments section>,
as follows.  The <option name> and <option value>, except where noted as
otherwise, are always chosen from available possibilities documented in
the *perl-tk* documentation.  The six syntax variations are:

(1) The generic case, for an option spec
----------------------------------------

   The most generic case, if none of the other cases applies, has an
<option name> and an <option value>, neither of which contains embedded
space characters.  These are separated by a colon (":") character which
has no space characters adjacent to it.  The format is:

     <option name>:<option value>

(2) The option value contains embedded spaces
---------------------------------------------

   The <option value> may be single-quoted, to allow embedded space
characters within it.  The format is:

     <option name>:'<option value>'

   <option value> may be null or not.  This is handled differently,
depending on whether it occurs as a packing or configuration option.

(3) The option value is absent, but the colon is specified
----------------------------------------------------------

   The <option value> may be absent.  This is used for lone (not of the
<name>=><value> form) leading arguments to the configuration or geometry
manager functions in *perl-tk*.  The format is:

     <option name>:

   This is handled differently, depending on whether it occurs as a
packing or configuration option.

(4) The option value is absent, and the colon is omitted
--------------------------------------------------------

   The <option value> may be absent, and the colon delimiter omitted, in
certain cases (for the ones not specially introduced by *QuickTk*).  The
format for these option items is, simply:

     <option name>

   This applies to any option name that's not a <special option>

(5) Special options; there is no colon, nor an option value
-----------------------------------------------------------

   *QuickTk* introduces some special-function <option name> choices, to
enable a way for a script to invoke functionality the generic form of the
syntax doesn't provide.  These occur only in a list of <packing options>.
The format for these option items is, simply:

     <special option>

   There are five of these special-function <option name> choices.  Their
names and meanings are:

(1) 'nocreate'
     This widget spec should be remembered for use later, but should not
     be created on startup.  A callback specified as the action for some
     widget or event may call the *createwidget* function to create
     instances of this widget when it is needed.

(2) 'nopack'
     This widget should be created, but not mapped to the screen to become
     visible on startup.  It may be made visible on demand, later.

(3) 'pack'
     This is the default case, and is usually omitted.  The possibility
     for specifying it explicitly is included only for consistency.

(4) 'place'
     The *place()* geometry management function should be used instead of
     pack().  The other <packing options> are passed to the placer, rather
     than the packer.

(5) 'grid'
     The *grid()* geometry management function should be used instead of
     pack().  The other <packing options> are passed to the gridder,
     rather than the packer.

(6) Special 'last' options; simplify syntax for longer values
-------------------------------------------------------------

   *QuickTk* introduces a some additional special-function <option name>
choices, that may occur *only* as the very last option in a spec node.
These, thus, allow embedded spaces, and are processed specially for extra
convenience.  As it turns out, these occur only in the <configuration
options> list of the <arguments section>.  The format is:

     <last option>:<everything to the end of the spec>

   There are four of these special <option name> choices, each of which
applies only to certain widget types, as indicated:

'ini' (MainWindow widget)
     The entire string after the colon will be executed as perl code,
     immediately.  This allows a script to initialize variables, etc.

'ttl' (MainWindow or TopLevel widget)
     The entire string after the colon will become the "-title"
     configuration option for the widget.  This allows long titles to
     contain embedded space characters, without having to be explicitly
     quoted.

'cmd' (generic or menuitem widget)
     The entire string after the colon will be parsed as of either of the
     following forms:

          <function> ( <args> )
            or:   <function>

     where <function> must not contain embedded space or parenthesis ("(")
     characters and may be followed by space characters, and a character
     string surrounded by parentheses ("(" and ")") may optionally be
     present.  This will be reformatted to become a "-command"
     configuration option to the widget which specifies a callback in the
     form:

          "-command"=>[main::<function>,$gl,<args>]

     This makes the callback refer to a function defined in the *main::*
     namespace, which is called with an implicit reference to the
     *QuickTk* blessed hash as its first argument (somewhat like an object
     method), to allow the function code to access effectively "global"
     variables for the application.  (See `"APPLICATION VARIABLES"' in
     this node, above.)

'sub' (generic or menuitem widget)
     The entire string after the colon will be surrounded with "sub { "
     and " }", and thus evaluated as an anonymous function callback as the
     value of a "-command=>" configuration option to the widget.

GENERATED CODE
==============

   The generated *perl-tk* code, for arguments to the widget configuration
function or the geometry management function will be as:

option name usually gets initial hyphen, and is quoted
------------------------------------------------------

   <option name> becomes "-<option name>"=> if it has a value specified.
Otherwise, it (a stand-alone option) is simply surrounded by double-quote
characters.

packing option values are quoted
--------------------------------

   All values specified for packing options are surrounded with
double-quote characters.

most configuration option values get quoted
-------------------------------------------

   Generally, values for configuration options will be surrounded with
double-quote characters.  The exceptions are:

values starting with a dollar-sign character
     A value which has "$" as its first character is taken to indicate a
     variable in *QuickTk*'s hash whose key is what follows the "$", so it
     is modified to: $$gl{<option value without "$">}.

values starting with the back-slant character
     A value which has "\" as its first character is taken to indicate a
     variable in *QuickTk*'s hash whose key is what follows the "\", so it
     is modified to: \$$gl{<option value without "\">}.

values surrounded with square brackets
     A value which is surrounded with "[" and "]" is taken to be a
     reference to an anonymous array specifying a callback and its
     arguments, and is used as-is.

a null string value specified with single-quotes
     A value which is a null string specified as """ will be used as-is.
     This is a way of making sure the option name is not interpreted
     specially as a lone option even when the value should be empty.

QM entanglement of variables in perl
************************************

NAME
====

   Quantum::Entanglement - QM entanglement of variables in perl

SYNOPSIS
========

     use Quantum::Entanglement qw(:DEFAULT :complex :QFT);

     my $c = entangle(1,0,i,1);    # $c = |0> + i|1>
     my $d = entangle(1,0,1,1);    # $d = |0> + |1>

     $e = $c * $d; # $e now |0*0> + i|0*1> + |1*0> + i|1*1>, connected to $c, $d

     if ($e == 1) { # observe, probabilistically chose an outcome
       # if we are here, ($c,$d) = i|(1,1)>
       print "* \$e == 1\n";
     }
     else { # one of the not 1 versions of $e chosen
       # if we are here, ($c,$d) = |(0,0)> + i|(1,0)> + |(0,1)>
       print "* \$e != 1\n";
     }

BACKGROUND
==========

     "Quantum Mechanics - the dreams that stuff is made of."

   Quantum mechanics is one of the stranger things to have emerged from
science over the last hundred years.  It has led the way to new
understanding of a diverse range of fundamental physical phenomena and,
should recent developments prove fruitful, could also lead to an entirely
new mode of computation where previously intractable problems find
themselves open to easy solution.

   While the detailed results of quantum theory are hard to prove, and
even harder to understand, there are a handful of concepts from the theory
which are more easily understood.  Hopefully this module will shed some
light on a few of these and their consequences.

   One of the more popular interpretations of quantum mechanics holds that
instead of particles always being in a single, well defined, state they
instead exist as an almost ghostly overlay of many different states (or
values) at the same time.  Of course, it is our experience that when we
look at something, we only ever find it in one single state.  This is
explained by the many states of the particle collapsing to a single state
and highlights the importance of observation.

   In quantum mechanics, the state of a system can be described by a set
of numbers which have a probability amplitude associated with them.  This
probability amplitude is similar to the normal idea of probability except
for two differences.  It can be a complex number, which leads to
interference between states, and the probability with which we might
observe a system in a particular state is given by the modulus squared of
this amplitude.

   Consider the simple system, often called a *qubit*, which can take the
value of 0 or 1.  If we prepare it in the following superposition of
states (a fancy way of saying that we want it to have many possible values
at once):

     particle = 1 * (being equal to 1) + (1-i) * (being equal to 0)

   we can then measure (observe) the value of the particle.  If we do
this, we find that it will be equal to 1 with a probability of

     1**2 / (1**2 + (1-i)(1+i) )

   and equal to zero with a probability of

     (1+i)(1-i) / (1**2 + (1-i)(1+i) )

   the factors on the bottom of each equation being necessary so that the
chance of the particle ending up in any state at all is equal to one.

   Observing a particle in this way is said to collapse the wave-function,
or superposition of values, into a single value, which it will retain from
then onwards.  A simpler way of writing the equation above is to say that

     particle = 1 |1> + (1-i) |0>

   where the probability amplitude for a state is given as a 'multiplier'
of the value of the state, which appears inside the `< | ' >> pattern (this
is called a *ket*, as sometimes the *bra* or `< <  | '>, pattern appears
to the left of the probability amplitudes in these equations).

   Much of the power of quantum computation comes from collapsing states
and modifying the probability with which a state might collapse to a
particular value as this can be done to each possible state at the same
time, allowing for fantastic degrees of parallelism.

   Things also get interesting when you have multiple particles together
in the same system.  It turns out that if two particles which exist in
many states at once interact, then after doing so, they will be linked to
one another so that when you measure the value of one you also affect the
possible values that the other can take.  This is called entanglement and
is important in many quantum algorithms.

DESCRIPTION
===========

   Essentially, this allows you to put variables into a superposition of
states, have them interact with each other (so that all states interact)
and then observe them (testing to see if they satisfy some comparison
operator, printing them) which will collapse the entire system so that it
is consistent with your knowledge.

   As in quantum physics, the outcome of an observation will be the result
of selecting one of the states of the system at random.  This might affect
variables other than the ones observed, as they are able to remember their
history.

   For instance, you can say:

     $foo = entangle(1,0,1,1); # foo = |0> + |1>
     $bar = entangle(1,0,1,1); # bar = |0> + |1>

   if at this point we look at the values of $foo or $bar, we will see
them collapse to zero half of the time and one the other half of the time.
We will also find that us looking at $foo will have no effect on the
possible values, or chance of getting any one of those values, of $bar.

   If we restrain ourselves a little and leave $foo and $bar unobserved we
can instead play some games with them.  We can use our entangled variables
just as we would any other variable in perl, for instance,

     $c = $foo * $bar;

   will cause $c to exist in a superposition of all the possible outcomes
of multiplying each state of $foo with each state in $bar.  If we now
measure the value of $c, we will find that one quarter of the time it will
be equal to one, and three quarters of the time it will be equal to zero.

   Lets say we do this, and $c turns out to be equal to zero this time,
what does that leave $foo and $bar as?  Clearly we cannot have both $foo
and $bar both equal to one, as then $c would have been equal to one, but
all the other possible values of $foo and $bar can still occur.  We say
that the state of $foo is now entangled to the state of $bar so that

     ($foo, $bar ) = |0,0> + |0,1> + |1,0>.

   If we now measure $foo, one third of the time it will be equal to one
and two thirds of the time, it will come out as zero.  If we do this and
get one, this means that should we observe $bar it will be equal to zero so
that our earlier measurement of $c still makes sense.

Use of this module
==================

   To use this module in your programs, simply add a

     use Quantum::Entanglement;

   line to the top of your code,  if you want to use complex probability
amplitudes, you should instead say:

     use Quantum::Entanglement qw(:complex :DEFAULT);

   which will import the `Math::Complex i Re Im rho theta arg cplx cplxe'
functions / constants into your package.

   You can also import a Quantum Fourier transform, which acts on the
probability amplitudes of a state (see below) by addind a `:QFT' tag.

   This module adds an entangle function to perl, this puts a variable
into multiple states simultaneously.  You can then cause this variable to
interact with other entangled, or normal, values the result of which will
also be in many states at once.

   The different states which a variable can take each have an associated
complex probability amplitude, this can lead to interesting behaviour, for
instance, a root-not logic gate (see q_logic, below).

entangle
--------

   This sets up a new entangled variable:

     $foo = entangle(prob1, val1, prob2, val2, ...);

   The probability values are strictly speaking probability amplitudes,
and can be complex numbers (corresponding to a phase or wave-ish nature
(this is stretching things slightly...)).  To use straight numbers, just
use them, to use complex values, supply a Math::Complex number.

   Thus

     $foo = entangle(1, 0, 1+4*i, 1);

   corresponds to:

     foo = 1|0> + (1 + 4i)|1>

   The probabilities do not need to be normalized, this is done by the
module whenever required (ie. when observing variables).

Non-observational operations
----------------------------

   We can now use our entangled variable just as we would any normal
variable in perl.  Much of the time we will be making it do things where
we do not find anything out about the value of our variable, if this is
the case, then the variable does not collapse, although any result of its
interactions will be entangled with itself.

Observational Operators
-----------------------

   Whenever you perform an operation on an entangled variable which should
increase your level of knowledge about the value of the variable you will
cause it to collapse into a single state or set of states.  All logical
comparison (`==', gt ....) operators, as well as string and num -ifying
and boolean observation will cause collapse.

   When an entangled variable is observed in this way, sets of states which
would satisfy the operator are produced (ie. for $a < 2, all states <2 and
all >= 2).  One of these sets of states is then selected randomly, using
the probability amplitudes associated with the states.  The result of
operating on this state is then returned.  Any other states are then
destroyed.

   For instance, if

     $foo = entangle(1,2,1,3,1,5,1,7);
            # |2> +|3> + |5> +|7>
     then saying

     print '$foo is greater than four' if ($foo > 4);

   will cause $foo to be either `< |2' + |3> >> or `< |5' +7> >>.

   Of course, if you had said instead:

     $foo = entangle(-1,2,1,3,1,5,1,7);
              # -1|2> + |3> + |5> +|7>

   then if `$foo' was measured here, it would come out as any one of
2,3,5,7 with equal likelyhood (remember, amplitude squared).  But saying

     print '$foo is greater than four' if ($foo > 4);

   will cause foo to be `< |2' or 3> >> with a probability of `(-1 + 1) ==
0' or `< |5 or 7' >> with probability of `(1 + 1)/2 == 1'.  Thus `< $foo '
4 >> will always be true.

   It is possible to perform operations like these on an entangled
variable without causing collapse by using p_op (below).

   When performing an observation, the module can do two things to the
states which can no longer be valid (those to which it did not collapse,
|2 or 3> in the example above).  It can either internally set the
probability of them collapsing to be zero or it can delete them entirely.
This could have consequences if you are writing parallel functions that
rely on there being a certain number of states in a variable, even after
collapse.

   The default is for collapsed states to be destroyed, to alter this
behaviour, set the `$Quantum::Entanglement::destroy' variable to a false
value.  In general though, you can leave this alone.

Breaking this behaviour
-----------------------

   Although not the default, it is possible to cause observation (for
boolean context or with comparison operators only) to act in a more
purposeful manner.  If the variable:

     $Quantum::Entanglement::conform

   has a true value, then the overloaded operations provided by this
module will try their very best to return "truth" instead of selecting
randomly from both "true" and "false" outcomes.

   For example:

     $foo = entangle(1,0,1,1,1,3); # foo = |0> + |1> + |3>
     $Quantum::Entanglement::conform = 1;
     print "\$foo > 0\n" if $foo > 0;
                                   # foo now = |1> + |3>
     print "\$foo == 3\n" if $foo == 3;
                                   # foo now = |3>

   will always output:

     $foo > 0
     $foo == 3

   Of course, setting this variable somewhat defeats the point of the
module, but it could lead to some interesting pre-calculating algorithms
which are fed with entangled input, which is then later defined (by
testing ==, say )with the answer of the calculation appearing, as if by
magic, in some other variable.  See also the section `save_state' in this
node.

p_op
----

   This lets you perform conditional operations on variables in a
superposition of states *without actually looking at them*.  This returns
a new superposed variable, with states given by the outcome of the p_op.
You cannot, of course, gain any information about the variables involved
in the p_op by doing this.

     $rt = p_op(var1, op, var2, code if true, code if false).

   op should be a string representing the operation to be performed (eg.
`"=="').  The two code arguments should be references to subs the return
values of which will be used as the value of the corresponding state
should the expression be true or false.

   If no code is provided, the return value of the operator itself is
evaluated in boolean context, if true, 1 or if false, 0 is used as the
corresponding state of the returned variable.  Only one of var1 and var2
need to be entangled states.  The values of the states being tested are
placed into the $QE::arg1 and $QE::arg2 variables should the subroutines
want to play with them (these are localized aliases to the actual values,
so modify at your peril (or pleasure)).

   The semantics are best shown by example:

     $gas = entangle(1, 'bottled', 1, 'released');
       # gas now in states |bottled> + |released>

     $cat_health = p_op($gas, 'eq', 'released',
                             sub {'Dead'},
                             sub {'Alive'});
       # cat,gas now in states |Alive, bottled> + |Dead, released>

   This is similar to parallel execution of the following psuedo code:

     if (gas is in bottle) { # not probabilistic, as we don't look
       cat is still alive
     }
     else {
       cat is dead
     }

   The cat can now be observed (with a conditional test say) and doing so
will collapse both the cat and the gas:

     if ($cat_health eq 'Dead') {# again, outcome is probabilistic
       # thus gas = |released>
     }
     else {
       # thus gas = |bottled>
     }

   This also lets you use some other 'binary' operators on a superposition
of states by immediatly observing the return value of the parallel op.

     $string = entangle(1,'aa', 1, 'bb', 1, 'ab', 1, 'ba');
     $regex = qr/(.)\1/;

     if (q_op($string, '=~', $regex)) { # again, probabilistic
       # if here, string = |aa> + |bb>
     }
     else {
       # if here, string = |ab> + |ba>
     }

p_func
------

   This lets you perform core functions and subs through the states of a
superposition without observing and produce a new variable corresponding
to a superposition of the results of the function.

     <p_func("func" ,entangled var,[more vars,] [optional args])

   Any number of entangled variables can be passed to the function,
optional args begin with the first non-entangled var.

   The optional args will be passed to the subroutine or function
unmodified.

   eg. `p_func('substr', $foo, 1,1)' will perform `substr($state, 1,1)' on
each state in $foo.  Saying `p_func('substr', $foo,$bar,1)' will evaluate
`substr($s_foo, $s_bar,1)' for each state in $foo and $bar.

   You can also specify a subroutine, either in the same package that
p_func is called from, or with a fully qualified name.

     sub foo {my $state = $_[0]; return ${$_[1]}[$state]}
     @foo = qw(one two three);
     $foo = entangle(1,1,1,2,1,3); # |1> + |2> + |3>
     $bar = p_func('foo', $foo, \@foo);

     # bar now |one> + |two> + |three>

   You can also pass a code reference as first arg (cleaner)...

     $bar = p_func(\&foo, $foo, \@foo);

q_logic
-------

   This allows you to create new states, increasing the amount of global
state as you do so.  This lets you apply weird quantum logic gates to your
variables, amongst other things.

     q_logic(code ref, entangled var [,more vars] );

   The code ref is passed a list of probabilities and values corresponding
to the state currently being examined. (prob, val, [prob, val..])  code
ref must return a list of the following format:

     (prob, val, prob, val ...) # as entangle basically

   For instance, this is a root-not gate:

     sub root_not {
       my ($prob, $val) = @_;
       return( $prob * (i* (1/sqrt(2))), $val,
     	   $prob * (1/sqrt(2)), !$val ? 1 : 0);
     }

     $foo = entangle(1,0);
     $foo = q_logic(\&root_not, $foo);

     # if $foo is observed here, it will collapse to both 0 and 1, at random

     $foo = q_logic(\&root_not, $foo);

     print "\$foo is 1\n" if $foo; # always works, $foo is now 1.

   This corresponds to the following:

     foo = |0>

     root_not( foo )

     foo is now in state: sqrt(2)i |0> + sqrt(2) |1>

     root_not (foo)

     foo in state: (0.5 - 0.5) |0> + (0.5i + 0.5i) |1>

     which if observed gives

     foo = 0|0> + i|1> which must collapse to 1.

   Neat, huh?

save_state
----------

   Having set up a load of entangled variables, you might wish to store
their superposed state for later restoration.  This is acheived using the
save_state function:

     $state = save_state( [list of entangled variables] );

   To restore the states of the entangled variables, simply call the
`restore_state' method on the $state:

     ($foo, $bar) = $state->restore_state;

   Once a state is restored, all other entangled variables will loose
their values, so make sure that your save_state with everything you might
want to use later.

   Multiple different states can be saved and restored independently, but
only one set of global states can be active at once, if a little caution
is applied, this should not cause any problems.

   See the demo calc_cache for an example of use.

QFT
---

   This provides a quantum fourier transform which acts on the probability
amplitudes of a state, creating a new state with the same values as the
initial state but with new probability amplitudes.  FTs like this are used
in many quantum algorithms where it is important to find the periodicity
of some function (for instance, Shor).

   This will only work if you have carefully populated your states,
essentially if only one call has been made to the entangle function (you
can have many 'result' variables lying around, but only one 'seed' state).
This sort of breaks encapsulation, so this might change in the future!

   See `~/demo/shor.pl' for an example of the use of this function.

Quantum::Entanglement::show_states
----------------------------------

   This allows you to find out the states that your variables are in, it
does not count as observation.

   If called without arguments, this shows all the possible arrangements
of values which the system can exist in, for instance, if you had two
entangled variables:

     $foo = entangle(1,0,1,1);
     $bar = entangle(1,0,1,1);

     print Quantum::Entanglement::show_states;

   outputs:

     1|0>   1|0>
     1|1>   1|0>
     1|0>   1|1>
     1|1>   0|1>

   If called as a method (or with a list of entangled vars) it will only
return the states available to that variable, thus:

     $foo = entangle(1,0,1,1);
     print $foo->show_states;

   outputs:

     1|0> + 1|1>

   The ordering of the output of this function may change in later versions
of this module.

EXPORT
======

   This module exports quite a bit, entangle, save_state, p_op, p_func and
q_logic.  If used with qw(:complex) it will also export the following
functions / constants from the Math::Complex module: `i Re Im rho theta
arg cplx cplxe'.

AUTHOR
======

   Alex Gough (`alex@rcon.org').  Any comments, suggestions or bug reports
are warmly welcomed.

SEE ALSO
========

   perl(1).  See Quantum/Superpositions. See
Math/Complex.  `http:' in this node  - 1985 Paper by David
Deutsch.  `http:' in this node  - Machines, Logic and Quantum Physics,
 David Deutsch, Artur Ekert, Rossella Lupacchini.

   Various examples are provided in the `~/demo/' directory of the
distribution.

BUGS
====

   This is slow(ish) but fun, so hey!

Shortcomings
------------

   This module does fall short of physical reality in a few important
areas, some of which are listed below:

No eigenfunction like behaviour
     All operators share the same set of eigenfunctions, in real QM this
     is sometimes not the case, so observing one thing would cause some
     other thing (even if already observed) to fall into a superposition
     of states again.

Certain observables cannot simultaneously have precisely defined values.
     This follows from the point above.  The famous uncertainty principle
     follows from the fact that position and momentum have different sets
     of eigenfunctions.  In this module, it is always possible to collapse
     the system so that a value is known for every entangled variable.

Perl is not a quantum computing device
     Perl, alas, is currently only implemented on classical computers, this
     has the disadvantage that any quantum algorithm will not run in
     constant time but will quite likely run in exponential time.  This
     might be remedied in future releases of perl.  Just not anytime soon.

Quantum information cannot be copied with perfect fidelity
     It is impossible to perfectly clone a real entangled state without
     'damaging' in some way either the original or the copy.  In this
     module, it is possible for this to happen as we have special access
     to the states of our variables.

Cannot generate perfectly random numbers
     It is well known that classical computers cannot produce a perfectly
     random sequence of numbers, as this module runs on one of these, it
     also suffers the same fate.  It is possible to give a classical
     computer access to a perfect random number generator though
     (essentially by linking it to a suitable physical system) in which
     case this is no longer a problem.

COPYRIGHT
=========

   This code is copyright (c) Alex Gough, 2001.  All Rights Reserved.
This module is free software.  It may be used, redistributed and/or
modified under the same terms as perl itself.

QM-like superpositions in Perl
******************************

NAME
====

   Quantum::Superpositions - QM-like superpositions in Perl

VERSION
=======

   This document describes version 1.03 of Quantum::Superpositions,
released August 11, 2000.

SYNOPSIS
========

     use Quantum::Superpositions;

     if ($x == any($a, $b, $c)) { ...  }

     while ($nextval < all(@thresholds)) { ... }

     $max = any(@value) < all(@values);

     use Quantum::Superpositions BINARY => [ CORE::index ];

     print index( any("opts","tops","spot"), "o" );
     print index( "stop", any("p","s") );

BACKGROUND
==========

   Under the standard interpretation of quantum mechanics, until they are
observed, particles exist only as a discontinuous probability function.
Under the Cophenhagen Interpretation, this situation is often visualized
by imagining the state of an unobserved particle to be a ghostly overlay
of all its possible observable states simultaneously. For example, a
particle that might be observed in state A, B, or C may be considered to
be in a pseudo-state where it is simultaneously in states A, B, and C.
Such a particle is said to be in a superposition of states.

   Research into applying particle superposition in construction of
computer hardware is already well advanced. The aim of such research is to
develop reliable quantum memories, in which an individual bit is stored as
some measurable property of a quantised particle (a qubit). Because the
particle can be physically coerced into a superposition of states, it can
store bits that are simultaneously 1 and 0.

   Specific processes based on the interactions of one or more qubits
(such as interference, entanglement, or additional superposition) are then
be used to construct quantum logic gates. Such gates can in turn be
employed to perform logical operations on qubits, allowing logical and
mathematical operations to be executed in parallel.

   Unfortunately, the math required to design and use quantum algorithms
on quantum computers is painfully hard. The Quantum::Superpositions module
offers another approach, based on the superposition of entire scalar
values (rather than individual qubits).

DESCRIPTION
===========

   The Quantum::Superpositions module adds two new operators to Perl: any
and all.

   Each of these operators takes a list of values (states) and
superimposes them into a single scalar value (a superposition), which can
then be stored in a standard scalar variable.

   The any and all operators produce two distinct kinds of superposition.
The any operator produces a disjunctive superposition, which may
(notionally) be in any one of its states at any time, according to the
needs of the algorithm that uses it.

   In contrast, the all operator creates a conjunctive superposition,
which is always in every one of its states simultaneously.

   Superpositions are scalar values and hence can participate in
arithmetic and logical operations just like any other type of scalar.
However, when an operation is applied to a superposition, it is applied
(notionally) in parallel to each of the states in that superposition.

   For example, if a superposition of states 1, 2, and 3 is multiplied by
2:

     $result = any(1,2,3) * 2;

   the result is a superposition of states 2, 4, and 6. If that result is
then compared with the value 4:

     if ($result == 4) { print "fore!" }

   then the comparison also returns a superposition: one that is both true
and false (since the equality is true for one of the states of $result and
false for the other two).

   Of course, a value that is both true and false is of no use in an if
statement, so some mechanism is needed to decide which superimposed
boolean state should take precedence.

   This mechanism is provided by the two types of superposition available.
A disjunctive superposition is true if any of its states is true, whereas
a conjunctive superposition is true only if all of its states are true.

   Thus the previous example does print "fore!", since the if condition is
equivalent to:

     if (any(2,4,6) == 4)...

     It suffices that any one of 2, 4, or 6 is equal to 4, so the condition
     is true and the C<if> block executes.

   On the other hand, had the control statement been:

     if (all(2,4,6) == 4)...

   the condition would fail, since it is not true that all of 2, 4, and 6
are equal to 4.

   Operations are also possible between two superpositions:

     if (all(1,2,3)*any(5,6) < 21)
             { print "no alcohol"; }

     if (all(1,2,3)*any(5,6) < 18)
             { print "no entry"; }

     if (any(1,2,3)*all(5,6) < 18)
             { print "under-age" }

     In this example, the string "no alcohol" is printed because the
     superposition produced by the multiplication is the Cartesian product of
     the respective states of the two operands: C<all(5,6,10,12,15,18)>.
     Since all of these resultant states are less that 21, the condition is
     true. In contrast, the string "no entry" is not printed, because not all
     the product's states are less than 18.

   Note that the type of the first operand determines the type of the
result of an operation.  Hence the third string - "underage" - is printed,
because multiplying a disjunctive superposition by a conjunctive
superposition produces a result that is disjunctive:
`any(5,6,10,12,15,18)'. The condition of the if statement asks whether any
of these values is less than 18, which is true.

Composite Superpositions
------------------------

   The states of a superposition may be any kind of scalar value - a
number, a string, or a reference:

     $wanted = any("Mr","Ms").any(@names);
     if ($name eq $wanted) { print "Reward!"; }

     $okay = all(\&check1,\&check2);
     die unless $okay->();

     my $large =
             all(    BigNum->new($centillion),
                     BigNum->new($googol),
                     BigNum->new($SkewesNum)
             );
     @huge =  grep {$_ > $large} @nums;

   More interestingly, since the individual states of a superposition are
scalar values and a superposition is itself a scalar value, a
superposition may have states that are themselves superpositions:

     $ideal = any( all("tall", "rich", "handsome"),
                   all("rich", "old"),
                   all("smart","Australian","rich")
                 );

   Operations involving such a composite superposition operate recursively
and in parallel on each its states individually and then recompose the
result. For example:

     while (@features = get_description) {
             if (any(@features) eq $ideal) {
                     print "True love";
             }
     }

   The `any(@features) eq $ideal' equality is true if the input
characteristics collectively match any of the three superimposed
conjunctive superpositions. That is, if the characteristics collectively
equate to each of "tall" and "rich" and "handsome", or to both "rich" and
"old", or to all three of "smart" and "Australian" and "rich".

Eigenstates
-----------

   It is useful to be able to determine the list of states that a given
superposition represents.  In fact, it is not the *states* per se, but the
values to which the states may collapse - the *eigenstates* that are
useful.

   In programming terms this is the set of values `@ev' for a given
superposition $s such that `any(@ev) == $s' or `any(@ev) eq $s'.

   This list is provided by the `eigenstates' operator, which may be
called on any superposition:

     print "The factor was: ",
           eigenstates($factor);

     print "Don't use any of:",
           eigenstates($badpasswds);

Boolean evaluation of superpositions
------------------------------------

   The examples shown above assume the same meta-semantics for both
arithmetic and boolean operations, namely that a binary operator is
applied to the Cartesian product of the states of its two operands,
regardless of whether the operation is arithmetic or logical. Thus the
comparison of two superpositions produces a superposition of 1's and 0's,
representing any (or all) possible comparisons between the individual
states of the two operands.

   The drawback of applying arithmetic metasemantics to logical operations
is that it causes useful information to be lost. Specifically, which
states were responsible for the success of the comparison. For example, it
is possible to determine if any number in the array `@newnums' is less
than all those in the array `@oldnums' with:

     if (any(@newnums) < @all(oldnums)) {
       print "New minimum detected";
     }

   But this is almost certainly unsatisfactory, because it does not reveal
which element(s) of `@newnum' caused the condition to be true.

   It is, however, possible to define a different meta-semantics for
logical operations between superpositions; one that preserves the
intuitive logic of comparisons but also gives limited access to the states
that cause those comparsions to succeed.

   The key is to deviate from the arithmetic view of superpositional
comparison (namely, that a compared superposition yields a superposition
of compared state combinations).  Instead, the various comparison
operators are redefined so that they form a superposition of those
eigenstates of the left operand that cause the operation to be true. In
other words, the old meta-semantics superimposed the result of each
parallel comparison, whilst the new meta-semantics superimposes the left
operands of each parallel comparison that succeeds.

   For example, under the original semantics, the comparisons:

     all(7,8,9) <= any(5,6,7)        #A
     all(5,6,7) <= any(7,8,9)        #B
     any(6,7,8) <= all(7,8,9)        #C

   would yield:

     all(0,0,1,0,0,0,0,0,0)          #A (false)
     all(1,1,1,1,1,1,1,1,1)          #B (true)
     any(1,1,1,1,1,1,0,1,1)          #C (true)

   Under the new semantics they would yield:

     all(7)                          #A (false)
     all(5,6,7)                      #B (true)
     any(6,7)                        #C (true)

   The success of the comparison (the truth of the result) is no longer
determined by the values of the resulting states, but by the number of
states in the resulting superposition.

   The Quantum::Superpositions module treats logical operations and
boolean conversions in exactly this way.  Under these meta-semantics, it
is possible to check a comparison and also determine which eigenstates of
the left operand were responsible for its success:

     $newmins = any(@newnums) < all(@oldnums);

     if ($newmins) {
             print "New minima found:", eigenstates($newmins);
     }

   Thus, these semantics provide a mechanism to conduct parallel searches
for minima and maxima :

     sub min {
       eigenstates( any(@_) <= all(@_) )
     }

     sub max {
       eigenstates( any(@_) >= all(@_) )
     }

   These definitions are also quite intuitive, almost declarative: the
minimum is any value that is less-than-or-equal-to all of the other
values; the maximum is any value that is greater-than-or-equal to all of
them.

String evaluation of superpositions
-----------------------------------

   Converting a superposition to a string produces a string that encode
the simplest set of eigenstates equivalent to the original superposition.

   If there is only one eigenstate, the stringification of that state is
the string representation.  This eliminates the need to explicitly apply
the `eigenstates' operator when only a single resultant state is possible.
For example:

     print "lexicographically first: ",
           any(@words) le all(@words);

   In all other cases, superpositions are stringified in the format:
`"all(*eigenstates*)"' or `"any(*eigenstates*)"'.

Numerical evaluation of superpositions
--------------------------------------

   Providing an implicit conversion to numeric (for situations where
superpositions are used as operands to an arithmetic operation, or as
array indices) is more challenging than stringification, since there is no
mechanism to capture the entire state of a superposition in a single
non-superimposed number.

   Again, if the superposition has a single eigenstate, the conversion is
just the standard conversion for that value. For instance, to output the
value in an array element with the smallest index in the set of indices @i:

     print "The smallest element is: ",
           $array[any(@i)<=all(@i)];

   If the superposition has no eigenstates, there is no numerical value to
which it could collapse, so the result is undef.

   If a disjunctive superposition has more than one eigenstate, that
superposition could collapse to any of those values. And it is convenient
to allow it to do exactly that - collapse (pseudo-)randomly to one of its
eigenstates.  Indeed, doing so provides a useful notation for random
selection from a list:

     print "And the winner is...",
           $entrant[any(0..$#entrant)];

Superpositions as subroutine arguments
--------------------------------------

   When a superposition is used as a subroutine argument, that subroutine
is applied in parallel to each state of the superposition and the results
re-superimposed to form the same type of superposition. For example, given:

     $n1 = any(1,4,9);
     $r1 = sqrt($n1);

     $n2 = all(1,4,9);
     $r2 = pow($n2,3);

     $r3 = pow($n1,$r1);

   then $r1 contains the disjunctive superposition `any(1,2,3)', `$r2'
contains the conjunctive superposition `all(1,64,729)', and <$r3 >
contains the conjunctive superposition `any(1,4,9,16,64,81,729)'.

   Because the built-in sqrt and pow functions don't know about
superpositions, the module provides a mechanism for informing them that
their arguments may be superimposed.

   If the call to `use Quantum::Superpositions' is given an argument list,
that list specifies which functions should be rewritten to handle
superpositions. Unary functions and subroutine can be "quantized" like  so:

     sub incr    { $_[0]+1 }
     sub numeric { $_[0]+0 eq $_[0] }

     use Quantum::Superpositions
             UNARY         => ["CORE::int", "main::incr"],
             UNARY_LOGICAL => ["main::numeric"];

   For binary functions and subroutines use:

     sub max  { $_[0] < $_[1] ? $_[1] : $_[0] }

     sub same { my $failed; $IG{__WARN__}=sub{$failed=1};
                return $_[0] eq $_[1] || $_[0]==$_[1] && !$failed;
              }

     use Quantum::Superpositions
             BINARY         => ['main::max', 'CORE::index'],
             BINARY_LOGICAL => ['main::same'];

EXAMPLES
========

Primality testing
-----------------

   The power of programming with scalar superpositions is perhaps best seen
by returning the quantum computing's favourite adversary: prime numbers.
Here, for example is an O(1) prime-number tester, based on naive trial
division:

     sub is_prime {
       my ($n) = @_;
       return $n % all(2..sqrt($n)+1) != 0
     }

   The subroutine takes a single argument ($n) and computes (in parallel)
its modulus with respect to every integer between 2 and `sqrt($n)'.  This
produces a conjunctive superposition of moduli, which is then compared
with zero.  That comparison will only be true if all the moduli are not
zero, which is precisely the requirement for an integer to be prime.

   Because `is_prime' takes a single scalar argument, it can also be
passed a superposition.  For example, here is a constant-time filter for
detecting whether a number is part of a pair of twin primes:

     sub has_twin {
             my ($n) = @_;
             return is_prime($n) && is_prime($n+any(+2,-2);
     }

Set membership and intersection
-------------------------------

   Set operations are particularly easy to perform using superimposable
scalars.  For example, given an array of values `@elems', representing the
elements of a set, the value `$v' is an element of that set if:

     $v == any(@elems)

   Note that this is equivalent to the definition of an eigenstate. That
equivalence can be used to compute set intersections. Given two
disjunctive superpositions, `$s1=any(@elems1)' and `$s2=any(@elems2)',
representing two sets, the values that constitute the intersection of
those sets must be eigenstates of both <$s1> and `$s2'. Hence:

     @intersection = eigenstates(all($s1, $s2));

   This result can be extended to extract the common elements from an
arbitrary number of arrays in parallel:

     @common = eigenstates( all(     any(@list1),
                                     any(@list2),
                                     any(@list3),
                                     any(@list4),
                               )
                  );

Factoring
---------

   Factoring numbers is also trivial using superpositions.  The factors of
an integer N are all the quotients q of N/n (for all positive integers n <
N) that are also integral. A positive number q is integral if floor(q)==q.
Hence the factors of a given number are computed by:

     sub factors {
       my ($n) = @_;
       my $q = $n / any(2..$n-1);
       return eigenstates(floor($q)==$q);
     }

Query processing
----------------

   Superpositions can also be used to perform text searches.  For example,
to determine whether a given string ($target) appears in a collection of
strings (@db):

     use Quantum::Superpositions BINARY => ["CORE::index"];

     $found = index(any(@db), $target) >= 0;

   To determine which of the database strings contain the target:

     sub contains_str {
             if (index($dbstr, $target) >= 0) {
                     return $dbstr;
             }
     }

     $found = contains_str(any(@db), $target);
     @matches = eigenstates $found;

   It is also possible to superimpose the target string, rather than the
database, so as to search a single string for any of a set of targets:

     sub contains_targ {
             if (index($dbstr, $target) >= 0) {
                     return $target;
             }
     }

     $found = contains_targ($string, any(@targets));
     @matches = eigenstates $found;

   or in every target simultaneously:

     $found = contains_targ($string, all(@targets));
     @matches = eigenstates $found;

AUTHOR
======

   Damian Conway (damian@conway.org)

BUGS
====

   There are undoubtedly serious bugs lurking somewhere in code this funky
:-) Bug reports and other feedback are most welcome.

COPYRIGHT
=========

   Copyright (c) 1998-2000, Damian Conway. All Rights Reserved.  This
module is free software. It may be used, redistributed and/or modified
under the terms of the Perl Artistic License   (see
http://www.perl.com/perl/misc/Artistic.html)

extension for creating quines
*****************************

NAME
====

   Quine - extension for creating quines

SYNOPSIS
========

     #!/usr/bin/perl -w

     use Quine;

     # rest of code here

DESCRIPTION
===========

   This module simply prints the content of the program using the module.
This type of program is called a "quine".

AUTHOR
======

     Jeff "japhy" Pinyan
     CPAN ID: PINYAN
     japhy@pobox.com
     http://www.pobox.com/~japhy/

Perl interface to file system quotas
************************************

NAME
====

   Quota - Perl interface to file system quotas

SYNOPSIS
========

     use Quota;

     ($block_curr, $block_soft, $block_hard, $block_timelimit,
      $inode_curr, $inode_soft, $inode_hard, $inode_timelimit) =
     Quota::query($dev [,$uid]);

     ($block_curr, $block_soft, $block_hard, $block_timelimit,
      $inode_curr, $inode_soft, $inode_hard, $inode_timelimit) =
     Quota::rpcquery($host, $path [,$uid]);

     Quota::setqlim($dev, $uid, $block_soft, $block_hard,
     		   $inode_soft, $inode_hard [,$tlo]);

     Quota::sync([$dev]);

     $arg = Quota::getqcarg([$path]);

     Quota::setmntent();
     ($dev, $path, $type, $opts) = Quota::getmntent();
     Quota::endmntent();

DESCRIPTION
===========

   The Quota module provides access to file system quotas.  The quotactl
system call or ioctl is used to query or set quotas on the local host, or
queries are submitted via RPC to a remote host.  Mount tables can be
parsed with *getmntent* and paths can be translated to device files (or
whatever the actual *quotactl* implementations needs as argument) of the
according file system.

Functions
---------

*($bc,$bs,$bh,$bt, $ic,$is,$ih,$it) = Quota::query($dev, $uid, $isgrp)*
     Get current usage and quota limits for a given file system and user.
     The user is specified by its numeric uid; defaults to the process'
     real uid.

     The type of $dev varies from system to system. It's the argument
     which is used by the *quotactl* implementation to address a specific
     file system. It may be the path of a device file (e.g. */dev/sd0a*)
     or the path of the mount point or the quotas file at the top of the
     file system (e.g. */home.stand/quotas*). However you do not have to
     worry about that; use *Quota::getqcarg* to automatically translate
     any path inside a file system to the required $dev argument.

     $dev may also be in the form of *hostname:path*, which has the module
     transparently query the given host via a remote procedure call (RPC).
     In case you have *NFS* (or similar network mounts), this type of
     argument may also be produced by *Quota::getqcarg*. Note: RPC queries
     require *rquotad(1m)* to be running on the target system. If the
     daemon or host are down, the timeout is 12 seconds.

     In *$bc* and *$ic* the current usage in blocks and inodes is returned.
     *$bs* and *$is* are the soft limits, *$bh* and *$ih* hard limits. If
     the soft limit is exceeded, writes by this user will fail for blocks
     or inodes after *$bt* or $it is reached. These times are expressed as
     usual, i.e. in elapsed seconds since 00:00 1/Jan/1970 GMT.

     Note: When the quota limits are not exceeded, the timestamps are
     meaningless and should be ignored. When hard and soft limits are
     zero, there is no limit for that user. On most systems Quota::query
     will return undef in that case and errno will be set to ESRCH.

     When *$isgrp* is given and set to 1, *$uid* is taken as gid and group
     quotas are queried. This is not supported across RPC and even locally
     only on a few architectures (e.g. Linux and other BSD based Unix
     variants, OSF/1 and  AIX - check the quotactl(2) man page on your
     systems). If unsupported, this flag is ignored.

*Quota::setqlim($dev, $uid, $bs,$bh, $is,$ih, $tlo, $isgrp)*
     Sets quota limits for the given user. Meanings of $dev, *$uid*,
     *$bs*, *$bh*, *$is* and *$ih* are the same as in *Quota::query*.

     *$tlo* decides how the time limits are initialized: 0: The time
     limits are set to *NOT STARTED*, i.e. the time limits are not
     initialized until the first write attempt by this user.  This is the
     default.  1: The time limits are set to *7.0 days*.  More
     alternatives (i.e. setting a specific time) aren't available in most
     implementations.

     When *$isgrp* is given and set to 1, *$uid* is taken as gid and group
     quota limits are set. This is supported only on a few architectures
     (see above). If unsupported, this flag is ignored.

     Note: if you want to set the quota of a particular user to zero, i.e.
     no write permission, you must not set all limits to zero, since that
     is equivalent to unlimited access. Instead set only the hard limit to
     0 and the soft limit for example to 1.

     Note that you cannot set quotas via RPC.

Quota::sync($dev)
     Have the kernel update the quota file on disk or all quota files if
     no argument given (the latter doesn't work on all systems, in
     particular on *HP-UX 10.10*).

     The main purpose of this function is to check if quota is enabled in
     the kernel and for a particular file system. Read the *quotaon(1m)*
     man page on how to enable quotas on a file system.

*($bc,$bs,$bh,$bt, $ic,$is,$ih,$it) =*
     *Quota::rpcquery($host,$path,$uid)*

     This is equivalent to *Quota::query("$host:$path",$uid)*, i.e.  query
     quota for a given user on a given remote host via RPC.  $path is the
     path of any file or directory inside the wanted file system on the
     remote host.

*$arg = Quota::getqcarg($path)*
     Get the required $dev argument for *Quota::query* and *Quota::setqlim*
     for the file system you want to operate on. $path is any path of an
     existing file or directory inside that file system. The path argument
     is optional and defaults to the current working directory.

     The type of $dev varies between operating systems, i.e. different
     implementations of the quotactl functionality. Hence it's important
     for compatibility to always use this module function and not really
     pass a device file to *Quota::query* (as returned by *Quota::getdev*).
     See also above at *Quota::query*

*$dev = Quota::getdev($path)*
     Returns the device entry in the mount table for a particular file
     system, specified by any path of an existing file or directory inside
     it. $path defaults to the working directory. This device entry need
     not really be a device. For example on network mounts (*NFS*) it's
     *"host:mountpath"*, with *amd(1m)* it may be something completely
     different.

     *NEVER* use this to produce a $dev argument for other functions of
     this module, since it's not compatible. On some systems *quotactl*
     does not work on devices but on the quotas file or some other kind of
     argument. Always use *Quota::getqcarg*.

Quota::setmntent()
     Opens or resets the mount table. This is required before the first
     invocation of *Quota::getmntent*.

     Note: on some systems there is no equivalent function in the C
     library.  But you still have to call this module procedure for
     initialization of module-internal variables.

*($dev, $path, $type, $opts) = Quota::getmntent()*
     Returns the next entry in the system mount table. This table contains
     information about all currently mounted (local or remote) file
     systems.  The format and location of this table (e.g. */etc/mtab*)
     vary from system to system. This function is provided as a compatible
     way to parse it. (On some systems, like *OSF/1*, this table isn't
     accessible as a file at all, i.e. only via *Quota::getmntent*).

Quota::endmntent()
     Close the mount table. Should be called after the last use of
     *Quota::getmntent* to free possibly allocated file handles and memory.
     Always returns undef.

Quota::strerr()
     Translates $! to a quota-specific error text. You should always use
     this function to output error messages, since the normal messages
     don't always make sense for quota errors (e.g. *ESRCH*: *No such
     process*, here: *No quota for this user*)

RETURN VALUES
=============

   Functions that are supposed return lists or scalars, return undef upon
errors. As usual $! contains the error code (see *Quota::strerr*).

   *Quota::endmntent* always returns undef. All other functions return
undef only upon errors.

EXAMPLES
========

   An example for each function can be found in the test script test.pl.
See also the contrib directory, which contains some longer scripts, kindly
donated by users of the module.

BUGS
====

   With remote quotas we have to rely on the remote system to state
correctly which block size the quota values are referring to.
Unfortunately on Linux the rpc.rquotad reports a block size of 4
kilobytes, which is wildly incorrect. So you either need to fix your Linux
rquotad or keep *#define LINUX_RQUOTAD_BUG* defined, which will
Quota::query always let assume all remote partners in reality report 1kB
blocks. Of course that'll break with mixed systems, so better fix your
rquotad. For more info on other Linux bugs please see INSTALL.

AUTHORS
=======

   This module was created 1995 by Tom Zoerner (tomzo@nefkom.net) and
since then continually improved and ported to many operating- and
file-systems. Numerous people have contributed to this process; for a
complete list of names please see the CHANGES document.

SEE ALSO
========

   perl(1), edquota(1m), quotactl(2) or quotactl(7I), mount(1m), mtab(4)
or mnttab(4), quotaon(1m), setmntent(3), getmntent(3) or getmntinfo(3),
endmntent(3), rpc(3), rquotad(1m).

Perl object oriented client interface to SAP R/3 using RFCSDK
*************************************************************

NAME
====

   R3.pm - Perl object oriented client interface to SAP R/3 using RFCSDK

SYNOPSIS
========

     use R3;
     $conn = new R3::conn (host=>$host, sysnr=>$sysnr, client=>$client,
     user=>$usr, passwd=>$passwd);
     $itab = new R3::itab ($conn, $table_name);
     $func = new R3::func ($conn, $func_name);
     ...

DESCRIPTION
===========

   R3.pm provides an object oriented interface to SAP's RFCSDK for
connection to an R/3 system. R3::conn is the object interface to R/3
connections. R3::itab is the object interface to ABAP internal tables.
R3::func is the object interface to ABAP RFC enabled functions.

AUTHOR
======

   Johan Schoen, johan.schon@capgemini.se

SEE ALSO
========

   perl(1), R3::conn(3), R3::func(3), R3::itab(3) and R3::rfcapi(3).

Perl extension for handling connection to a SAP R/3 system
**********************************************************

NAME
====

   R3::conn - Perl extension for handling connection to a SAP R/3 system

SYNOPSIS
========

     use R3::conn;

     $conn = new R3::conn (client=>"100", user=>"SAP*",
       password=>"pass", hostname=>"apollo", sysnr=>0);

     undef $conn;

DESCRIPTION
===========

   R3::conn::new creates a new connection to a R/3 system. It takes the
following named parameters:   client => R/3 client   user => user ID
password => user's password   passwd => alias for password   language =>
logon language, defaults to 'E'   lang => alias for language   hostname =>
application server's hosname   host => alias for hostname   systemnr =>
system number   sysnr => alias for systemnr   gwhost => gateway host,
defaults to host   gwservice => gateway service, defaults to service
"sapgw##" with ## = 'sysnr'   trace => rfc trace on if set to 1, defaults
to 0 (off)   pre4 => should be set to true value if target host has R/3
release < 40A

AUTHOR
======

   Johan Schoen, johan.schon@capgemini.se

SEE ALSO
========

   perl(1), R3(3), R3::func(3), R3::itab(3) and R3::rfcapi(3).

Perl extension for calling remote functions in a R/3 system
***********************************************************

NAME
====

   R3::func - Perl extension for calling remote functions in a R/3 system

SYNOPSIS
========

     use R3::func;
     $func = new R3::func ($conn, $func_name);
     call $func (\@export, \@tables, $field_1, $value_1, $field_2, $value_2,
     $field_3, $value_3, ... $field_n, $value_n);
     undef $func;

DESCRIPTION
===========

   R3::func::new enables a R/3 function to be called from perl. The
function interface is retrieved from the R/3 system. R3::func::new takes
two parameters, first parameter is a R3::conn, second is the name of the
ABAP function.

   R3::func::call calls the ABAP function specified in R3::func::new.
R3::func::call takes two or more parameters. First parameter is a reference
to an array of export variable and export value pairs. Second parameter is
a reference to an array of table name and table handle pairs. Third and
further parameters are import variable name and import variable pairs. Use
references to empty arrays, [], if there is no export variables and/or
tables in the function interface.

   Example:   ...    $func=new R3::func ($conn, "RFC_GET_TABLE_ENTRIES");
$itab=new R3::itab ($conn, "TAB512");   call $func ([TABLE_NAME=>'TVKO',
GEN_KEY=>'2'],     [ENTRIES=>$itab], NUMBER_OF_ENTRIES=>$e);   ...

AUTHOR
======

   Johan Schoen, johan.schon@capgemini.se

SEE ALSO
========

   perl(1), R3(3), R3::conn(3), R3::itab(3) and R3::rfcapi(3).

Perl extension for handling ABAP internal tables
************************************************

NAME
====

   R3::itab - Perl extension for handling ABAP internal tables

SYNOPSIS
========

     use R3::itab;
     $itab = new R3::itab ($conn, "MARA");

     $itab->get_records();
     %h = $itab->get_record($i);
     $itab->set_record($i, %h);
     $itab->ins_record($i, %h);
     $itab->add_record(%h);
     $itab->del_record($i);

     $itab->get_lines();
     $s = $itab->get_line($i);
     $itab->set_line($i, $s);
     $itab->ins_line($i, $s);
     $itab->add_line($s);
     $itab->del_line($i);

     $itab->trunc();

     %h = $itab->line2record($s);
     $s = $itab->record2line(%h);

DESCRIPTION
===========

   First record in a R3::itab is 1. This is the same as in ABAP.

   $itab->get_records() returns the number of records in $itab

   $itab->get_record($i) returns an array of field name, value pairs for
the $i:th record in $itab

   $itab->set_record($i, %h) replaces the values of the $i:th record in
$itab with the values in the field name, value pairs following the first
parameter

   $itab->ins_record($i, %h) inserts a record at the $i:th position in
$itab and sets the values to the value in the field name, value pairs
following the first parameter

   $itab->add_record(%h) appends a new record to the end of $itab and sets
the values to the value in the field name, value pairs in %h

   $itab->del_record($i) deletes the $i:th record from $itab

   $itab->get_lines() returns the number of records in $itab; should be the
same amount as $itab->get_records() returns

   $itab->get_line($i) returns an unpacked hex string with the values of
the $i:th record in $itab

   $itab->set_line($i, $s) replace the values of the $i:th record with the
content in the unpacked hex string in $s

   $itab->ins_line($i, $s) inserts a new record at the $i:th position in
$itab and sets the values to the content in the unpacked hex string $s

   $itab->add_line($s) adds a new record to the end of $itab and sets the
values to the content in the unpacked hex string $s

   $itab->del_line($i) deletes the $i:th record from $itab

   $itab->trunc() deletes all records from $itab

   $itab->line2record($s) returns the unpacked hex string as an array of
field name, value pairs

   $itab->record2line(%h) returns an unpacked hex string corresponding to
the array of field name, value pairs

AUTHOR
======

   Johan Schoen, johan.schon@capgemini.se

SEE ALSO
========

   perl(1), R3(3), R3::conn(3), R3::func(3) and R3::rfcapi(3).

RADIUS dictionary parser
************************

NAME
====

   RADIUS::Dictionary - RADIUS dictionary parser

SYNOPSIS
========

     use RADIUS::Dictionary;

     my $dict = new RADIUS::Dictionary "/etc/radius/dictionary";
     $dict->readdict("/some/other/file");
     my $num = $dict->attr_num('User-Name');
     my $name = $dict->attr_name(1);

DESCRIPTION
===========

   This is a simple module that reads a RADIUS dictionary file and parses
it, allowing conversion between dictionary names and numbers.

METHODS
-------

   new

   Returns a new instance of a RADIUS::Dictionary object.  If given an
(optional) filename, it calls *readdict* for you.

   ->*readdict*

   Parses a dictionary file and learns the name<->number mappings.

   ->*attr_num*($attrname)

   Returns the number of the named attribute.

   ->*attr_type*($attrname)

   Returns the type (string, integer, *ipaddr*, or time) of the named
attribute.

   ->*attr_name*($attrnum)

   Returns the name of the attribute with the given number.

   ->*attr_numtype*($attrnum)

   Returns the type of the attribute with the given number.

   ->*attr_has_val*($attrnum)

   Returns a true or false value, depending on whether or not the numbered
attribute has any known value constants.

   ->*val_has_name*($attrnum)

   Alternate (bad) name for *attr_has_val*.

   ->*val_num*($attrnum, $valname)

   Returns the number of the named value for the attribute number supplied.

   ->*val_name*

   Returns the name of the numbered value for the attribute number
supplied.

CAVEATS
=======

   This module is mostly for the internal use of RADIUS::Packet, and may
otherwise cause insanity and/or blindness if studied.

AUTHOR
======

   Christopher Masto, chris@netmonger.net

SEE ALSO
========

   RADIUS::Packet

Object-oriented Perl interface to RADIUS packets
************************************************

NAME
====

   RADIUS::Packet - Object-oriented Perl interface to RADIUS packets

SYNOPSIS
========

     use RADIUS::Packet;
     use RADIUS::Dictionary;

     my $d = new RADIUS::Dictionary "/etc/radius/dictionary";

     my $p = new RADIUS::Packet $d, $data;
     $p->dump;

     if ($p->attr('User-Name' eq "lwall") {
       my $resp = new RADIUS::Packet $d;
       $resp->set_code('Access-Accept');
       $resp->set_identifier($p->identifier);
       $resp->set_authenticator($p->authenticator);
       $resp->set_attr('Reply-Message') = "Welcome, Larry!\r\n";
       my $respdat = auth_resp($resp->pack, "mysecret");
       ...

DESCRIPTION
===========

   RADIUS (RFC2138) specifies a binary packet format which contains
various values and attributes.  RADIUS::Packet provides an interface to
turn RADIUS packets into Perl data structures and vice-versa.

   RADIUS::Packet does not provide functions for obtaining RADIUS packets
from the network.  A simple network RADIUS server is provided as an
example at the end of this document.  Also, a RADIUS::Server module is
under development which will simplify the interface.

PACKAGE METHODS
---------------

new RADIUS::Packet $dictionary, $data
     Returns a new RADIUS::Packet object.  $dictionary is an optional
     reference to a RADIUS::Dictionary object.  If not supplied, you must
     call *set_dict*.  If $data is supplied, unpack will be called for you
     to initialize the object.

OBJECT METHODS
--------------

->*set_dict*($dictionary)
     RADIUS::Packet needs access to a RADIUS::Dictionary object to do
     packing and unpacking.  set_dict must be called with an appropriate
     dictionary reference (see RADIUS/Dictionary)
     before you can use ->pack or ->unpack.

->unpack($data)
     Given a raw RADIUS packet $data, unpacks its contents so that they
     can be retrieved with the other methods (code, attr, etc.).

->pack
     Returns a raw RADIUS packet suitable for sending to a RADIUS client
     or server.

->code
     Returns the Code field as a string.  As of this writing, the following
     codes are defined:

          Access-Request          Access-Accept
          Access-Reject           Accounting-Request
          Accounting-Response     Access-Challenge
          Status-Server           Status-Client

-><set_code>($code)
     Sets the Code field to the string supplied.

->identifier
     Returns the one-byte Identifier used to match requests with responses,
     as a character value.

->*set_identifier*
     Sets the Identifier byte to the character supplied.

->*authenticator*
     Returns the 16-byte Authenticator field as a character string.

->*set_authenticator*
     Sets the Authenticator field to the character string supplied.

->attr($name)
     Retrieves the value of the named Attribute.  Attributes will be
     converted automatically based on their dictionary type:

          STRING     Returned as a string.
          INTEGER    Returned as a Perl integer.
          IPADDR     Returned as a string (a.b.c.d)
          TIME       Returned as an integer

->*set_attr*($name, $val)
     Sets the named Attribute to the given value.  Values should be
     supplied as they would be returned from the attr method.

->password($secret)
     The RADIUS Password attribute is encoded with a shared secret.  Use
     this method to return the decoded version.

->dump
     Prints the packet's contents to STDOUT.

EXPORTED SUBROUTINES
--------------------

*auth_resp*($packed_packet, $secret)
     Given a (packed) RADIUS packet and a shared secret, returns a new
     packet with the Authenticator field changed in accordace with RADIUS
     protocol requirements.

NOTES
=====

   This document is (not yet) intended to be a complete description of how
to implement a RADIUS server.  Please see the RFCs (at
ftp://ftp.livingston.com/pub/radius/) for that.  The following is a brief
description of the procedure:

     1. Recieve a RADIUS request from the network.
     2. Unpack it using this package.
     3. Examine the attributes to determine the appropriate response.
     4. Construct a response packet using this package.
        Copy the Identifier and Authenticator fields from the request,
        set the Code as appropriate, and fill in whatever Attributes
        you wish to convey in to the server.
     5. Call the pack method and use the auth_resp function to
        authenticate it with your shared secret.
     6. Send the response back over the network.
     7. Lather, rinse, repeat.

EXAMPLE
=======

     #!/usr/local/bin/perl -w

     use RADIUS::Dictionary;
     use RADIUS::Packet;
     use Net::Inet;
     use Net::UDP;
     use Fcntl;
     use strict;

     # This is a VERY simple RADIUS authentication server which responds
     # to Access-Request packets with Access-Accept.  This allows anyone
     # to log in.

     my $secret = "mysecret";  # Shared secret on the term server

     # Parse the RADIUS dictionary file (must have dictionary in current dir)
     my $dict = new RADIUS::Dictionary "dictionary"
       or die "Couldn't read dictionary: $!";

     # Set up the network socket (must have radius in /etc/services)
     my $s = new Net::UDP { thisservice => "radius" } or die $!;
     $s->bind or die "Couldn't bind: $!";
     $s->fcntl(F_SETFL, $s->fcntl(F_GETFL,0) | O_NONBLOCK)
       or die "Couldn't make socket non-blocking: $!";

     # Loop forever, recieving packets and replying to them
     while (1) {
       my ($rec, $whence);
       # Wait for a packet
       my $nfound = $s->select(1, 0, 1, undef);
       if ($nfound > 0) {
     	# Get the data
     	$rec = $s->recv(undef, undef, $whence);
     	# Unpack it
     	my $p = new RADIUS::Packet $dict, $rec;
     	if ($p->code eq 'Access-Request') {
     	  # Print some details about the incoming request (try ->dump here)
     	  print $p->attr('User-Name'), " logging in with password ",
     		$p->password($secret), "\n";
     	  # Create a response packet
     	  my $rp = new RADIUS::Packet $dict;
     	  $rp->set_code('Access-Accept');
     	  $rp->set_identifier($p->identifier);
     	  $rp->set_authenticator($p->authenticator);
     	  # (No attributes are needed.. but you could set IP addr, etc. here)
     	  # Authenticate with the secret and send to the server.
     	  $s->sendto(auth_resp($rp->pack, $secret), $whence);
     	}
     	else {
     	  # It's not an Access-Request
     	  print "Unexpected packet type recieved.";
     	  $p->dump;
     	}
       }
     }

AUTHOR
======

   Christopher Masto, chris@netmonger.net

SEE ALSO
========

   RADIUS::Dictionary

Perl extension for manipulating a RADIUS users file.
****************************************************

NAME
====

   RADIUS::UserFile - Perl extension for manipulating a RADIUS users file.

SYNOPSIS
========

     use RADIUS::UserFile;

     my $users = new RADIUS::UserFile File => '/etc/raddb/users';
     $users->load('/usr/local/etc/radius/users');

     $users->add(Who        => 'joeuser',
                 Attributes => { key1 => 'val1', key2 => 'val2' },
                 Comment    => 'Created on '. scalar localtime);

     $users->update(File => '/etc/raddb/users',
                    Who => qw(joeuser janeuser));

     print $users->format('joeuser');

REQUIRES
========

   Perl5.004, Fcntl, File::Copy, Tie::IxHash

EXPORTS
=======

   Nothing

DESCRIPTION
===========

   This module provides methods for reading information from a RADIUS
users database.

PACKAGE METHODS
---------------

new RADIUS::UserFile
new RADIUS::UserFile(File => *$USERS_FILE*, Who => *$USER*)
new RADIUS::UserFile(File => *$USERS_FILE*, Who => *\@USERS*)
     Creates and returns a new `RADIUS::UserFile' object.

     File specifies the RADIUS users file to load (e.g.
     "/etc/raddb/users").  If no file is specified, one isn't loaded; in
     this case, the load() method can be used to retrieve any user data.
     If an error occurred while reading File, 0 is returned instead.

     Who limits the retrieval of user information to the list of users
     specified.  A single user can be named using a string, or a set of
     users can be passed as a reference to an array.  If Who is left
     undefined, all users will be loaded.

OBJECT METHODS
--------------

->add(Who => *$USER*, Attributes => *\%ATTRS*, Comment => *$TEXT*)
     Adds information about the named user.  This information will
     henceforth be available through users, attributes, comment, etc.  Any
     comments are automatically prefixed with "# ".  Attributes should be
     specified as a reference to a hash; each value should either be an
     array ref or a string.  On success, 1 is returned.  On error, 0 is
     returned and STDERR gets an appropriate message.

->attributes(*$USER*)
     Returns a list of defined attributes for the specified user.  If the
     user doesn't exist, undef is returned.

->comment(*$USER*)
     Returns a string representing the comments that would prefix the given
     user's entry in the users file.  If the user doesn't exist, undef is
     returned.

->dump(*$USER*)
     Prints out the attributes of the named user, in alphabetical order.
     $self is returned.

->files
     Returns a list of files from which we have read user attributes.  The
     list is sorted according to the order in which the files were read.
     If no files have yet been read successfully, an empty array is
     returned.

->format(*$USER*)
     Returns a string containing the attributes of the named user,
     prefixed by any comments, according to the format required for the
     RADIUS users file.  If the user doesn't exist, an empty string is
     returned.

->load(File => *$USERS_FILE*, Who => *$USER*)
->load(File => *$USERS_FILE*, Who => *\@USERS*)
     Loads the contents of the specified RADIUS users file.  The name of
     the file is stored in a first-in, last-out stack enumerating which
     "databases" have been loaded (see files()).  The `RADIUS::UserFile'
     object is returned.  The options are the same as described in new().
     If a user already exists and further info is read about that user
     from the specified file, the new information is just added to what is
     already known.  On success, 1 is returned; on failure, 0 is returned
     and an appropriate message is sent to STDERR.

->read_users(*$USERS_FILE*, *$USER*)
->read_users(*$USERS_FILE*, *\@USERS*)
     Reads in the contents of the specified RADIUS users file, and returns
     a pair of hashes:  one index by user name, with each element
     containing a hash of (attribute name => [ values ]) pairs; and
     another also indexed by user name, containing the comments that
     immediately preceded that user's file entry.  The options are the
     same as in new().  Each comment value is a string.  Each user
     attribute value is a ref to an array of strings.  This is mainly
     designed as a utility function to be used by new() and load(), and
     doesn't affect the calling object.  On failure, 0 is returned.

->remove(*$USER* ...)
     Deletes the specified users from the object.  The list of users
     successfully deleted is returned.

->removed()
     Returns a list of users that have been removed from the object.

->update(File => *$USERS_FILE*, Who => *\@USERS*)
     Updates user attributes in a RADIUS users file.  If the file is
     specified, its contents are updated; otherwise, the last file read is
     modified.  If a list of users is provided, only their entries are
     updated; otherwise, all known users are.  All users to be "updated"
     are printed using the results of format.  Other users are printed as
     found.  It should be noted that some extra newlines can be left in a
     file with this method:  if an empty line follows a given record that
     has been remove()d, then it will still be there in the file being
     updated.  On success, non-zero is returned.  On failure, 0 is
     returned and STDERR gets an appropriate message.

->user(*$USER*)
     Returns a ref to a hash representing the attributes of the named user.
     If the user doesn't exist, undef is returned.

->usernames
     Returns a ref to an anonymous array of strings representing the users
     about which we have attributes defined.  If no users are defined, a
     ref to an empty anonymous array is returned.

->users
     Returns a ref to a hash of user hashes, where each user hash is a set
     of (attribute name => value) pairs.  This is the actual data stored
     in the object, so use with caution.

->values(*$USER*, *$ATTRIBUTE*)
     Returns an array of strings representing the values for the named
     attribute of the given user.  If the user or attribute doesn't exist,
     undef is returned.

AUTHOR
======

   Copyright (c) 2000 O'Shaughnessy Evans <oevans@acm.org>.  All rights
reserved.  This version is distributed under the same terms as Perl itself
(i.e. it's free), so enjoy.

SEE ALSO
========

   See RADIUS/Packet, RADIUS/Dictionary,
`Authen::Radius' in this node.

PERL Interface to Cisco AS5200 Access Router
********************************************

NAME
====

   RAS::AS5200.pm - PERL Interface to Cisco AS5200 Access Router

   Version 1.04, June 9, 2000

SYNOPSIS
========

   *RAS::AS5200* is a PERL 5 module for interfacing with a Cisco AS5200
access router. Using this module, one can very easily construct programs
to find a particular user in a bank of AS5200s, disconnect users, get
usage statistics, or execute arbitrary commands on a AS5200.

PREREQUISITES AND INSTALLATION
==============================

   This module uses Jay Rogers' *Net::Telnet module*. If you don't have
*Net::Telnet*, get it from CPAN or this module won't do much for you.

   Installation is easy, thanks to MakeMaker:

  1. "perl Makefile.PL && make"

  2. "make test" to run the test suite. Check the test output. It should
     seem correct. If there are errors, check the hostname and passwords
     and try again.

  3. If all is good, do a "make install"

  4. Check out the examples in this documentation. Also, some programs
     based on the RAS:: series of modules will be made available on CPAN
     at the same place as this module.

DESCRIPTION
===========

   At this time, the following methods are implemented:

creating an object with new
     Use the new() method to create a new object.

          Example:
             use RAS::AS5200;
             $foo = new RAS::AS5200(
                hostname => 'dialup1.example.com',
                login => '!root',
                password => 'mysecret',
                truncateusernames => 'true'
             );

     The following variables are useful:    hostname - The hostname of the
     router to connect to    login - The login name to get a command-line
     on the router    password - The password to the login name supplied
     enablepassword - The enable password to the router
     truncateusernames - See below    prompt - See below

     Since there's no point in dynamically changing the hostname, login,
     etc. these settings are static and must be supplied to the
     constructor. No error will be returned if these settings are not
     specified (except for the hostname, which is required), but your
     program will likely not get very far without at least a hostname and
     a correct password. Some older IOS versions such as Version 11.2(15a)
     only require a password and not a login name - if a login name is
     supplied, it is assumed that your router is not one of these and a
     full login-and-password script will be used; if a login name is not
     supplied, it is assumed that your router only requires a password to
     log in.

     The enablepassword is only required if you'll be using commands that
     require enable status on the router. This includes the userkill() and
     killexcessoutoctets() methods and would also include, for example,
     run_command('reload').

     If the "truncateusernames" option is set to non-null, then usernames
     supplied to user-seeking functions such as userkill() and usergrep()
     will be internally truncated to 10 characters. This is to work around
     a "feature" of the AS5200 that only the first 10 characters of a
     login name are displayed, which would cause usergrep('johnjjschmidt')
     to never work, as the AS5200 displays the login name as 'johnjjschm'.
     See the TRUNCATING USER NAMES section for more discussion on this.

     Prompt handling has been vastly improved. If a prompt is not
     specified, a reasonable default is assumed that should work just
     fine. If you want to specify a prompt, supply a regular expression
     without delimiters or anchors that represents your router's prompt,
     e.g. prompt => 'as5200[>#]' If you get errors about a bad match
     operator or a bad delimiter, you likely specified anchros and/or
     delimiters.

printenv
     This is for debugging. It prints to STDERR a list of its
     configuration hash, e.g. the hostname, login, and password. The
     printenv method does not return a value.

          Example:
             $foo->printenv;

run_command
     This takes a list of commands to be executed on the AS5200, executes
     the commands, and returns a list of references to arrays containg the
     text of each command's output. Repeat: It doesn't return an array, it
     returns an array of references to arrays. Each array contains the
     text output of each command. Think of it as an array-enhanced version
     of PERL's `backtick` operator.

     Some router functions (e.g. rebooting) ask for confirmation -
     confirmation will be automatically supplied by the module's interface
     routine.

          Example:
             # Execute a command and print the output
             $command = 'show modems';
             ($x) = $foo->run_command($command);
             print "Output of command \'$command\':\n", @$x ;

          Example:
             # Execute a string of commands
             # and show the output from one of them
             (@output) = $foo->run_command('show isdn status','show modems');
             print "Modems:\n@$output[0]\n\n";;
             print "Current connections:\n@$output[1]\n\n";;

     In Cisco-land, some functions are only available in enabled mode. To
     specify that a command should be run in enabled mode, prefix the
     command with "ENABLE " - that's all caps and a single space between
     the ENABLE and the rest of the command.

          Example:
             # Reboot the router
             $foo->run_command('ENABLE reload');

usergrep
     Supply a username as an argument, and usergrep will return an array
     of ports on which that user was found (thus, an empty list if they
     weren't found). An undefined value is returned if no username was
     supplied. Internally, this does a run_command('show users') and
     processes the output.

          Example:
             @ports = $foo->usergrep('gregor');
             print "User gregor was found on ports @ports\n";

userkill
     This does a usergrep, but with a twist: it disconnects the user by
     resetting the modem on which they're connected. Like usergrep, it
     returns an array of ports to which the user was connected before they
     were reset (or an empty list if they weren't found). The undefined
     value is returned if no username is supplied.

          Examples:
             @foo = $foo->userkill('gregor');
             print "Gregor was on ports @foo - HA HA!\n" if @ports ;

          @duh = $foo->userkill('-');
          print "There were ", scalar(@duh), " ports open.\n";

portusage
     This returns an array: The 1st element is the number of ports. The
     rest is a list of users who are currently online.

          Examples:
             ($ports,@people) = $foo->portusage;
             print "There are $ports total ports.\n";
             print "There are ", scalar(@people), "people online.\n";
             print "They are: @people\n";

          ($ports,@people) = $foo->portusage;
          print "Ports free: ", $ports - scalar(@people), "\n";
          print "Ports used: ", scalar(@people), "\n";
          print "Ports total: ", $ports, "\n";

userports
     This returns a hash with the key of each item being a username. The
     value of each item is an array of the ports that that username is
     currently using. This provides some information that a simple
     usergrep() lacks.

          Example:
             %userports = $foo->userports;
             foreach $user (keys(%userports)) {
               foreach $port (@{$userports{$user}}) {
                    print "User: $user is on $port\n";
                }
             }

killexcessoutoctets
     Takes a bytelimit as an argument and then checks each port's
     out-octets count. If the out octet count is higher than the
     bytelimit, the interface and its counters are reset. This is useful
     to stop RADIUS counters from wrapping, since a 32-bit signed integer
     wraps into negative at about 2 gig.

          Example:
             # kills users with outoctets of over about 2 gig
             $foo->killexcessoutoctets(2100000000);

EXAMPLE PROGRAMS
================

   These are some examples of how you could use this module. Full-fledged
applications based on the RAS:: family of modules will be made available
at CPAN at the same place as this module. Also, check out the test.pl file
included in this distribution for some sample code.

   ###

     portusage.pl - Prints a summary of port usage on a bank of modems

     use RAS::AS5200;
     $used = $total = 0;
     foreach ('dialup1.example.com','dialup2.example.com') {
        $foo = new RAS::AS5200(
           hostname => $_,
           login => '!root',
           password => 'mysecret'
        );

     local($ports,@ports) = $foo->portusage;
     $total += $ports;
     $used += scalar(@ports);
        }
        print "$used out of $total ports are in use.\n";

   ###

     usergrep.pl - Finds a user on a bank of modems

     ($username) = @ARGV;
     die "Usage: $0 <username>\nFinds the specified user.\n" unless $username ;

     use RAS::AS5200;
     foreach ('dialup1.example.com','dialup2.example.com') {
        $foo = new RAS::AS5200(
           hostname => $_,
           login => '!root',
           password => 'mysecret'
        );

     @ports = $foo->usergrep($username);
     (@ports) && print "Found user $username on $_ ports @ports\n";
        }

   ###

     userkill.pl - Kick a user off a bank of modems. Makes a great cron job. ;)

     ($username) = @ARGV;
     die "Usage: $0 <username>\nDisconnects the specified user.\n" unless $username ;

     use RAS::AS5200;
     foreach ('dialup1.example.com','dialup2.example.com') {
        $foo = new RAS::AS5200(
           hostname => $_,
           login => '!root',
           password => 'mysecret'
        );

     @ports = $foo->userkill($username);
     (@ports) && print "$_ : Killed ports @ports\n";
        }

TRUNCATING USER NAMES
=====================

   A "feature" of the Cisco AS5200 is that only the first 10 characters of
login names are displayed. As such, doing a usergrep('johnjjschmidt')
would never find the fellow, as the AS5200 truncates the username to
'johnjjschm'.

   To work around this, you may set the "truncateusernames" flag in your
constructor (see above). This will cause user-matching functions such as
usergrep and userkill to internally truncate usernames to 10 characters
for matching purposes. This means that usergrep('johnjjschmidt') would
internally be treated as usergrep('johnjjschm') so that it would match.

   So, you have your choice of two evils. If you don't enable username
truncation, you'll miss users with login names over 10 characters in
length. If you enable it, you could accidentally userkill user
'johnjjschm' when you meant to kill 'johnjjschmidt'. Sorry - Cisco screwed
up and we get to suffer for it.

BUGS
====

   The set of functions supplied is a bit bare but is growing. If you
write a useful function, or if you need a specific function added, please
let me know and I'd be glad to check it out on an in-my-free-time basis.

   There are no known bugs. There are likely a lot of unexpected features,
though. If you find any, PLEASE let me know.

   This module has been tested with an AS5300 with some degree of success.
Last I heard, the userports() function didn't work properly on the AS5300.

CHANGES IN THIS VERSION
=======================

   1.04     Fixed some small typos.

   1.03     Added the userports() and killexcessoutoctets() methods. Added
better prompt support (YAY!). Made error messages more useful. Made the
module work with or without a login prompt, as older IOS (11.2
specifically) doesn't require a login name, only a password.

   1.02     Cleaned up the code substantially. Fixed a "bug" that
truncated usernames at 8 characters. Added the "truncateusernames" option.
Tested the userkill() function on ISDN clients - works.

   1.01     Improved the error handling a tad. Touched up the docs.

   1.00     First released version of RAS::AS5200.

AUTHORS, MAINTAINERS, AND CONTACT INFO
======================================

   RAS::AS5200 uses the Net::Telnet module by Jay Rogers <jay@rgrs.com> -
thank you, Jay!

   Gregor Mosheh <stigmata@blackangel.net> wrote RAS::AS5200 and left some
significant problems in it, especially the prompt handling.

   Luke Robins <luker@vicnet.net.au> worked on the prompt handling and
apprised me that later IOSes need different login/password procedures, and
he also wrote the userports() and killexcessoutoctets() methods.

   Todd Caine <todd_caine@eli.net> helped out substantially with the
prompt handling, as well.

   Thank you very much, Luke and Robin, for fixing the most annoying bugs
in RAS::AS5200!

   The maintainer of RAS::AS5200 is Gregor Mosheh, at the address above.

LICENSE AND WARRANTY
====================

   Where would we be if Larry Wall were tight-fisted with PERL itself? For
God's sake, it's PERL code. It's free!

   This software is hereby released into the Public Domain, where it may
be freely distributed, modified, plagiarized, used, abused, and deleted
without regard for the original author.

   Bug reports and feature requests will be handled ASAP, but without
guarantee. The warranty is the same as for most freeware:    It Works For
Me, Your Mileage May Vary.

PERL Interface to 3Com/USR Total Control HiPerARC
*************************************************

NAME
====

   RAS::HiPerARC.pm - PERL Interface to 3Com/USR Total Control HiPerARC

   Version 1.03, June 9, 2000

SYNOPSIS
========

   *RAS::HiPerARC* is a PERL 5 module for interfacing with a 3Com/USR
Total Control HiPerARC remote access server. Using this module, one can
very easily construct programs to find a particular user in a bank of
ARCs, disconnect users, get usage statistics, or execute arbitrary
commands on a ARC.

PREREQUISITES AND INSTALLATION
==============================

   This module uses Jay Rogers' *Net::Telnet module*. If you don't have
*Net::Telnet*, get it from CPAN or this module won't do much for you.

   Installation is easy, thanks to MakeMaker:

  1. "perl Makefile.PL && make && make test"

  2. If the tests worked all right, "make install"

  3. Check out the examples in this documentation.

DESCRIPTION
===========

   At this time, the following methods are implemented:

creating an object with new
     Use the new() method to create a new object.

          Example:
             use RAS::HiPerARC;
             $foo = new RAS::HiPerARC(
                hostname => 'dialup1.example.com',
                login => '!root',
                password => 'mysecret',
             );

     The following variables are useful:    hostname - The hostname of the
     router to connect to    login - The login name to get a command-line
     on the router    password - The password to the login name supplied
     prompt - See below

     Since there's no point in dynamically changing the hostname, login,
     etc. these settings are static and must be supplied to the
     constructor. No error will be returned if these settings are not
     specified (except for the hostname, which is required), but your
     program will likely not get very far without at least a hostname and
     a correct password.

     Prompt handling has been vastly improved. If a prompt is not
     specified, a reasonable default is assumed that should work just
     fine. If you want to specify a prompt, supply a regular expression
     without delimiters or anchors that represents your router's prompt,
     e.g. prompt => 'hiper>' If you get errors about a bad match operator
     or a bad delimiter, you likely have a bad prompt string.

printenv
     This is for debugging only. It prints to STDOUT a list of its
     configuration hash, e.g. the hostname, login, and password. The
     printenv method does not return a value.

          Example:
             $foo->printenv;

run_command
     This takes a list of commands to be executed on the ARC, executes the
     commands, and returns a list of references to arrays containg the
     text of each command's output.

     Repeat: It doesn't return an array, it returns an array of references
     to arrays. Each array contains the text output of each command. Think
     of it as an array-enhanced version of PERL's `backtick` operator.

          Example:
             # Execute a command and print the output
             $command = 'list conn';
             ($x) = $foo->run_command($command);
             print "Output of command \'$command\':\n", @$x ;

          Example:
             # Execute a string of commands
             # and show the output from one of them
             (@output) = $foo->run_command('list interface','list con');
             print "Modems:\n@$output[0]\n\n";;
             print "Current connections:\n@$output[1]\n\n";;

usergrep
     Supply a username as an argument, and usergrep will return an array
     of ports on which that user was found (or an empty array, if they're
     not found). If no username is supplied, returns undefined.
     Internally, this does a run_command('list connections') and parses
     the output.

          Example:
             @ports = $foo->usergrep('gregor');
             print "User gregor was found on ports @ports\n";

userkill
     This does a usergrep, but with a twist: it disconnects the user by
     resetting the modem on which they're connected. Like usergrep, it
     returns an array of ports to which the user was connected before they
     were reset or an empty array if they weren't found. An undef is
     returned if no username was supplied.

          Examples:
             @foo = $foo->userkill('gregor');
             print "Gregor was on ports @foo - HA HA!\n" if @ports ;

          @duh = $foo->userkill('-');
          print "There were ", scalar(@duh), " ports open.\n";

portusage
     This returns an array consisting of 2 items: The 1st element is the
     number of ports. The rest is a list of users who are currently online.

          Examples:
             ($ports,@people) = $foo->portusage;
             print "There are $ports total ports.\n";
             print "There are ", scalar(@people), "people online.\n";
             print "They are: @people\n";

          ($ports,@people) = $foo->portusage;
          print "Ports free: ", $ports - scalar(@people), "\n";
          print "Ports used: ", scalar(@people), "\n";
          print "Ports total: ", $ports, "\n";

userports
     This returns a hash with the key of each item being a username. The
     value of each item is an array of the ports that that username is
     currently using. This provides some information that a simple
     usergrep() lacks.

          Example:
             %userports = $foo->userports;
             foreach $user (keys(%userports)) {
               foreach $port (@{$userports{$user}}) {
                    print "User: $user is on $port\n";
                }
             }

EXAMPLE PROGRAMS
================

   portusage.pl - Prints a summary of port usage on a bank of modems

   use RAS::HiPerARC; $used = $total = 0; foreach
('arc1.example.com','arc2.example.com','arc3.example.com') {    $foo = new
RAS::HiPerARC(       hostname => $_,       login => '!root',
password => 'mysecret'    );

     local($ports,@ports) = $foo->portusage;
     $total += $ports;
     $used += scalar(@ports);
     }

   print "$used out of $total ports are in use.\n";

   ###

   usergrep.pl - Finds a user on a bank of modems

   ($username) = @ARGV; die "Usage: $0 <username>\nFinds the specified
user.\n" unless $username ;

   use RAS::HiPerARC; foreach
('arc1.example.com','arc2.example.com','arc3.example.com') {    $foo = new
RAS::HiPerARC(       hostname => $_,       login => '!root',
password => 'mysecret'    );

     @ports = $foo->usergrep($username);
     (@ports) && print "Found user $username on $_ ports @ports\n";
     }

   ###

   userkill.pl - Kick a user off a bank of modems. Makes a great cron job.
;)

   ($username) = @ARGV; die "Usage: $0 <username>\nDisconnects the
specified user.\n" unless $username ;

   use RAS::HiPerARC; foreach
('arc1.example.com','arc2.example.com','arc3.example.com') {    $foo = new
RAS::HiPerARC(       hostname => $_,       login => '!root',
password => 'mysecret'    );

     @ports = $foo->userkill($username);
     (@ports) && print "$_ : Killed ports @ports\n";
     }

CHANGES IN THIS VERSION
=======================

   1.03     Added userports() method. Added better prompt support (YAY!).
Made error messages more useful.

   1.02     Fixed portusage() to only count Up interfaces. The ARC
remembers modems even when they've been removed, and this accounts for
that oddity. Cleaned up the code substantially. Fixed the prompt-matching
code so that a prompt mismatch will cause run_command() to return instead
of hanging in a loop.

   1.01     Added a test suite. Corrected some errors in the
documentation. Improved error handling a bit.

AUTHORS, MAINTAINERS, AND CONTACT INFO
======================================

   RAS::HiPerARC uses the Net::Telnet module by Jay Rogers <jay@rgrs.com>
- thank you, Jay!

   Gregor Mosheh <stigmata@blackangel.net> wrote RAS::HiPerARC originally,
but the prompt handling needed some help in case people cuztomized their
prompts.

   Luke Robins <luker@vicnet.net.au> and Todd Caine <todd_caine@eli.net>
helped out substantially with the prompt handling with RAS::AS5200 and the
changes were carried over into RAS::HiPerARC. Thank you, Luke and Todd!

   The maintainer of RAS::HiPerARC is Gregor Mosheh, at the address above.

BUGS
====

   Since we use this for port usage monitoring, new functions will be
added slowly on an as-needed basis. If you need some specific
functionality let me know and I'll see what I can do. If you write an
addition for this, please send it in and I'll incororate it and give
credit.

LICENSE AND WARRANTY
====================

   Where would we be if Larry Wall were tight-fisted with PERL itself? For
God's sake, it's PERL code. It's free!

   This software is hereby released into the Public Domain, where it may
be freely distributed, modified, plagiarized, used, abused, and deleted
without regard for the original author.

   Bug reports and feature requests will be handled ASAP, but without
guarantee. The warranty is the same as for most freeware:    It Works For
Me, Your Mileage May Vary.

PERL Interface to Livingston PortMaster 2
*****************************************

NAME
====

   RAS::PortMaster.pm - PERL Interface to Livingston PortMaster 2

   Version 1.15, January 17, 2000

   Gregor Mosheh (stigmata@blackangel.net)

SYNOPSIS
========

   *RAS::PortMaster* is a PERL 5 module for interfacing with a Livingston
PortMaster remote access server. Using this module, one can very easily
construct programs to find a particular user in a bank of PMs, disconnect
users, get usage statistics, or execute arbitrary commands on a PM.

PREREQUISITES AND INSTALLATION
==============================

   This module uses Jay Rogers' *Net::Telnet module*. If you don't have
*Net::Telnet*, get it from CPAN or this module won't do much for you.

   Installation is easy, thanks to MakeMaker:

  1. "perl Makefile.PL && make && make test"

  2. If the tests went well, do a "make install"

  3. Check out the EXAMPLES section of this document for examples on how
     you'd want to use this module.

DESCRIPTION
===========

   At this time, the following methods are implemented:

creating an object with new
     Call the new method while supplying the  "hostname", "login", and
     "password" hash, and you'll get an object reference returned.

          Example:
             use RAS::PortMaster;
             $foo = new RAS::PortMaster(
                hostname => 'dialup1.example.com',
                login => '!root',
                password => 'mysecret'
             );

     Since there's no sense in dynamically changing the hostname,
     password, etc. no methods are supplied for modifying them and they
     must be supplied statically to the constructor. No error will be
     generated if anything is left out, though it's likely that your
     program won't get far without supplying a proper hostname and
     password...

printenv
     This is for debugging only. It prints to STDOUT a list of its
     configuration hash, e.g. the hostname, login, and password. The
     printenv method does not return a value.

          Example:
             $foo->printenv;

run_command
     This takes a list of commands to be executed on the PortMaster,
     executes the commands, and returns a list of references to arrays
     containg the text of each command's output.

     Repeat: It doesn't return an array, it returns an array of references
     to arrays. Each array contains the text output of each command. Think
     of it as an array-enhanced version of PERL's `backtick` operator.

          Example:
             # Execute a command and print the output
             $command = 'sho ses';
             ($x) = $foo->run_command($command);
             print "Output of command \'$command\':\n", @$x ;

          Example:
             # Execute a string of commands
             # and show the output from one of them
             (@output) = $foo->run_command('reset S15','sho ses');
             print @$output[1] ;

usergrep
     Supply a username as an argument, and usergrep will return an array
     of ports on which that user was found (or an empty array if they
     weren't found). A undefined value is returned if no username was
     supplied. Internally, this does a run_command("sho ses") and parses
     the output.

          Example:
             @ports = $foo->usergrep('gregor');
             print "User gregor was found on ports @ports\n";

userkill
     This does a usergrep, but with a twist: it disconnects the user by
     resetting the modem on which they're connected. Like usergrep, it
     returns an array of ports to which the user was connected before they
     were reset (or an empty array if they weren't found). An undefined
     value is returned if no username was supplied.

     Because the PortMaster shows even ports that are not in use and shows
     the username as '-', you can userkill a username of "-" to reset all
     idle modems.

          Examples:
             @foo = $foo->userkill('gregor');
             print "Gregor was on ports @foo - HA HA!\n" if @ports ;

          @duh = $foo->userkill('-');
          print "There were ", scalar(@duh), " ports open.\n";

portusage
     This returns an array consisting of 2 parts: The 1st element is the
     number of ports. The rest is a list of users who are currently online.

          Examples:
             @people = $foo->portusage;
             print "There are ", shift(@people), " total ports.\n";
             print "There are ", scalar(@people), "people online.\n";
             print "They are: @people\n";

          ($ports,@people) = $foo->portusage;
          print "Ports free: ", $ports - scalar(@people), "\n";
          print "Ports used: ", scalar(@people), "\n";
          print "Ports total: ", $ports, "\n";

EXAMPLE PROGRAMS
================

   portusage.pl - Summarizes port usage on a bank of PMs

   use RAS::PortMaster; $used = $total = 0; foreach
('pm1.example.com','pm2.example.com','pm3.example.com') {    $foo = new
RAS::PortMaster(       hostname => $_,       login => '!root',
password => 'mysecret'    );

     local(@ports,$ports);
     ($ports,@ports) = $foo->portusage;
     $total += $ports;
     $used += scalar(@ports);
     }

   print "$used out of $total ports are in use.\n";

   #####

   usergrep.pl - Locate a user on a bank of PMs

   ($username) = @ARGV; die "Usage: $0 <username>\nFinds the specified
user.\n" unless $username ;

   use RAS::PortMaster;

   foreach ('pm1.example.com','pm2.example.com','pm3.example.com') {
$foo = new RAS::PortMaster(       hostname => $_,       login => '!root',
    password => 'mysecret'    );

     @ports = $foo->usergrep($username);
     (@ports) && print "Found user $username on $_ ports @ports\n";
     }

   #####

   userkill.pl - Kick a user off a bank of PMs

   ($username) = @ARGV; die "Usage: $0 <username>\nDisconnects the
specified user.\n" unless $username ;

   use RAS::PortMaster;

   foreach ('pm1.example.com','pm2.example.com','pm3.example.com') {
$foo = new RAS::PortMaster(       hostname => $_,       login => '!root',
    password => 'mysecret'    );

     @ports = $foo->userkill($username);
     (@ports) && print "$_ : Killed ports @ports\n";
     }

CHANGES IN THIS VERSION
=======================

   1.15     Cleaned up the code significantly. Fixed the prompt code to
avoid infinite loops in the case of a prompt mismatch - it now times out
appropriately.

   1.14     Fixed a leak in run_command. I swear I test this stuff before
I upload it, really!

   1.13     Added a test suite. Fixed some documentation errors. Added
some error handling.

   1.12     Bug fixes. Optimized userkill() for better performance.

   1.11     The package name got mangled when I zipped everything up, and
was thus useless. This has been fixed. Sorry. Also moved the example
programs into this document for easy availability. Also fixed an
intermittent problem with PERL not liking my use of shift() on a routine
call.

   1.00     First release, November 1999.

BUGS
====

   The set of supplied functions is a bit bare. Since we use this for port
usage monitoring, new functions will be added slowly on an as-needed
basis. If you need some specific functionality let me know and I'll see
what I can do. If you write an addition for this, please send it in and
I'll incororate it and give credit.

   I make some assumptions about router prompts based on what I have on
hand for experimentation. If I make an assumption that doesn't apply to
you (e.g. all prompts are /^\w+\>\s+/) then you could get "pattern match
timeout" errors. If this happens, you may be using the wrong RAS module to
connect the the router (e.g. don't use RAS::PortMaster to connect to a
Cisco AS5200). Otherwise, check the regexps in the loop within
run_command, and make sure your prompt fits this regex. If not, either fix
the regex and/or (even better) PLEASE send me some details on your prompt
and what commands you used to set your prompt.

LICENSE AND WARRANTY
====================

   Where would we be if Larry Wall were tight-fisted with PERL itself? For
God's sake, it's PERL code. It's free!

   This software is hereby released into the Public Domain, where it may
be freely distributed, modified, plagiarized, used, abused, and deleted
without regard for the original author.

   Bug reports and feature requests will be handled ASAP, but without
guarantee. The warranty is the same as for most freeware:    It Works For
Me, Your Mileage May Vary.

Remote CGI distributed processing
*********************************

NAME
====

   RCGI - Remote CGI distributed processing

SYNOPSIS
========

     use RCGI;
     @result = Invoke('jobone',@arguments);
     $result = Invoke('jobtwo',@arguments);

     $remote_subroutine = new RCGI($base_url,$library_path,$module,$subroutine);
     @my_result = $remote_subroutine->Call(@arguments);
     if ($remote_subroutine->Success()) {
          print @my_result,'';
     } else {
          print STDERR "Call to " . $remote_subroutine->Base_URL() .
     	   " failed with status: " . $remote_subroutine->Status() .
     	          ' ' . $remote_subroutine->Error_Message() . "\n";
     }
     $remote_subroutine->Async(1);
     $remote_subroutine->Wantarray(1);
     $remote_subroutine->Call(@arguments);
     while(! $remote_subroutine->Done()) {
         # This should really be something usefull--like calls to other servers!
         sleep 1;
     }
     @my_result = $remote_subroutine->Read();
     if ($remote_subroutine->Success()) {
          print @my_result,'';
     } else {
          print STDERR "Call to " . $remote_subroutine->Base_URL() .
     	   " failed with status: " . $remote_subroutine->Status() .
     	          ' ' . $remote_subroutine->Error_Message() . "\n";
     }

     $result = RCGI::run_cgi_command($base_url, \%cgi_form,
     	                            method => $method,
                                     username => $username,
                                     password => $password,
                                     timeout => $timeout,
                                     user_agent => $user_agent,
                                     nph => $bool_nph);

     # In a CGI script
     ($cgi_form, %options) = RCGI::Process_Parameters( new CGI );
     $result = RCGI::run_cgi_command($base_url, $cgi_form, %options);

ABSTRACT
========

   This perl library provides remote execution using CGI on remote web
servers.

INSTALLATION:
=============

Installation overview
---------------------

   The installation of RCGI for full functionality consists of the
following steps:

   1) Edit RCGI/Config.pm to change the location of the configuration
directory to an appropriate place.

   2) Install the RCGI library itself by doing:         perl Makefile.PL
     make         make test         make install

   3) Put the *perlcall.cgi* CGI script and the *SAR.pm* module on every
computer which will be running remote subroutines in the computer's
webserver's cgi-bin directory.

   4) Create sard.conf, server.conf, and jobs.conf files in the
*/usr/rcgi* directory.

   5) Start the *sard* daemon running on a computer which has read and
write access to the */usr/rcgi* directory.

   6) (Optional) Edit the line in sardcheck ($sard_user = 'sard_user'), to
be the user which ran the the *sard* daemon in step five.  As the same use
as step five, add a crontab entry which looks similar to:

   30 * * * * /usr/local/bin/perl /path_to_sardcheck/sardcheck

   Steps 2 and 3 are the only steps necessary if the load balancing calls:
*Invoke*, *Async_Invoke*, or *new_job RCGI* will not be used.  Step 3 may
be neglected if only *RCGI::run_cgi_command* will be used.

The /usr/rcgi directory
-----------------------

   If you wish to change the location of the configuration directory from
the default value of */usr/rcgi*, edit *RCGI/Config.pm*.  The
configuration must then be made, *mkdir /usr/rcgi* and set to the correct
permissions: *chgrp rcgi /usr/rcgi ; chmod g+rw /usr/rcgi*.  The DBM
files: *load.dir* and *load.pag* are created in this directory and must be
writable by any user process attempting to *Invoke* remote subroutines.

   The sard.conf, server.conf, and jobs.conf files need to then be created
in the */usr/rcgi* directory.  Following is the format for those files:

sard.conf
---------

     # machine URL_of_perlcall.cgi path_to_SAR.pm_module
     # Items on a line must be seperated by a single tab
     machine_name	http://www.webserver.url/cgi-bin/perlcall.cgi	path_to_SAR.pm_module

sard daemon
-----------

   Usage is: sard /usr/rcgi/sard.conf /usr/rcgi/sar
[timeperiod_in_seconds] [bool_verbose]

   The sard (System Activity Report Daemon) runs in the background to
collect usage from the machines configured in the sard.conf file.  It uses
the RCGI library to call (via perlcall.cgi) the SAR.pm module which, on
Unix, uses the sar program to collect system activity over, by default, 10
minute periods.  This information is stored in the DBM *sar* file located
in the */usr/rcgi* directory.

   This system activity information is used by the RCGI library to
implement load balancing of job requests.

server.conf
-----------

     # machine number_of_processors processes_per_processor reserve_idle(in percent)
     # the high reserve_idle should prevent those machines from being used
     # Items on a line must be seperated by a single tab
     medium	4	2	10
     shared	4	1	50
     dud	1	2	100000
     mine	1	1	100000
     super	12	1	10

jobs.conf
---------

     # job_type server task_url library_path module subroutine option option_value
     # where option can be: timeout, username, password, user_agent
     # Items on a line must be seperated by a single tab
     jobone	machine1	http://webserver1/cgi-bin/perlcall.cgi	module_path	Module	subroutine	option_name	option_value
     jobone	machine2	http://webserver2/cgi-bin/perlcall.cgi	module_path	Module	subroutine	option_name	option_value
     jobtwo	machine2	http://webserver2/cgi-bin/perlcall.cgi	module_path	Module	subroutine	option_name	option_value
     jobtwo	machine3	http://webserver3/cgi-bin/perlcall.cgi	module_path	Module	subroutine	option_name	option_value

perlcall.cgi and SAR.pm and other user modules installation
-----------------------------------------------------------

   The *perlcall.cgi* perl CGI script and the *SAR.pm* module will need to
be installed in a *cgi-bin* directory of the web server of every computer
which will be set up to allow jobs to be *Invoke*'ed or Call'ed.  The
*SAR.pm* module can alternatively be installed anywhere in the standard
perl *@INC* path.

   Perl modules to call must be in the standard perl *@INC* path or in the
library path given in the calls or in jobs.conf.

RCGI libraries installation
---------------------------

   To install this package, just change to the directory in which this
file is found and type the following:

     perl Makefile.PL
     make
     make test
     make install

   In order for a job to be invoked, the sard daemon must be running to
collect computer processor loads.  The *perlcall.cgi* CGI script and the
*SAR.pm* module must be installed properly on each computer.

DESCRIPTION
===========

   The RCGI library allows calling Perl subroutines in modules on remote
computers with load balancing.

Load balancing using RCGI
-------------------------

   RCGI calculates which machine to invoke a job on by using the machine
which has the maximum idle time as determined by:

   1) Take the measured idle time for each machine if it is newer than the
last calculated idle time for the machine.

   2) Subtract the reserve_idle for each machine.

   3) If two machines have similar resulting idle times, use the machine
with the most increase in measured idle time.

   The resulting idle time then has a process usage amount subtracted from
it and which is then stored in the DBM load file stored in the */usr/rcgi*
directory for subsequent usage for other job requests.

   The process usage for a machine is calculated according to the
following formula:

     process_usage = (100 / (machine_processors * processes_per_processor));

Usage of RCGI
-------------

   A perl program which is written as:

     use lib 'module_path';
     use Module;
     $result = Module::subroutine(@arguments); # or
     @result = Module::subroutine(@arguments);

   can be converted to use a job, jobone:

   jobs.conf entry:

     jobone	machine1	http://webserver1/cgi-bin/perlcall.cgi	module_path	Module	subroutine
     jobone	machine2	http://webserver2/cgi-bin/perlcall.cgi	module_path	Module	subroutine

   by being rewritten as:

     use RCGI;
     $remote_subroutine = new_job RCGI('jobone');
     $result = $remote_subroutine->Call(@arguments); # or
     @result = $remote_subroutine->Call(@arguments);

   or

     use RCGI;
     $result = Invoke('jobone',@arguments); # or
     @result = Invoke('jobone',@arguments);

   or can be rewritten to directly call a specific machine, machine1, as:

     use RCGI;
     $remote_subroutine = new RCGI('http://webserver1/cgi-bin/perlcall.cgi',
     				  'module_path',
     				  'Module',
     				  'subroutine');
     $result = $remote_subroutine->Call(@arguments); # or
     @result = $remote_subroutine->Call(@arguments);

   with the error checking for failure of the remote call by:

     if ($remote_subroutine->Success()) {
     	print $result;
     } else {
     	print "Call to " . $remote_subroutine->Base_URL() .
     	    " failed with status: " . $remote_subroutine->Status() .
     		' ' . $remote_subroutine->Error_Message() . "\n";
     }

RCGI Structure
--------------

   There are four possible uses or layers for RCGI:

     1. Invoking a module subroutine as a job via perlcall.cgi on the least busy computer defined for that job type.  This may be either synchronous or asynchronous.

     2. Getting a RCGI remote subroutine object for the least busy computer defined for that job type.

     3. Calling a module subroutine via perlcall.cgi on a particular computer.  This may be either synchronous or asynchronous.

     4. Retrieving HTML pages from static HTML pages or CGI scripts using RCGI::run_cgi_command.

RCGI Structure Diagram
----------------------

   The arrows, '# ==>', show the usable API of RCGI.

     sard.conf
                                                                   /
                                                                  L
                                                              sard
                                                              |
        1 ==> Invoke or Async_Invoke                          V
                        |             jobs.conf, server,conf, DBM file sar
                        |            /
                        V           L
        2 ==>           new_job RCGI <-----> DBM file load
                             |
                             |
                             V
        3 ==>             new RCGI
                             |
                             |
                             V
                        $remote_subroutine->Call ==> http://www/cgi-bin/perlcall.cgi
                        |                     /|         A
                        |                     /|         |
                        |                    / |         V
                        V                   /  |     return( eval '
        4 ==> RCGI::run_cgi_command        /   |     use lib 'library_path';
                                          /    |     use Module;
                                         /     |     Module::subroutine(@arguments);
                                        L      |     ' );
                        $result or @result     V
               $remote_subroutine->Success     $remote_subroutine->Done
         $remote_subroutine->Error_Message            |
                                                      |
                                                      V
                                               $remote_subroutine->Read
                                                      |
                                                      |
                                                      V
                                                    result
                                              $remote_subroutine->Sucess
                                              $remote_subroutine->Error_Message

Functions and Methods
=====================

Invoke a job request
--------------------

     @my_result = Invoke('job_name',@arguments);

   Invoke a job to synchronously call a remote subroutine.

   Where @arguments is the normal list of arguments for the remote
subroutine.

Async_Invoke a job request
--------------------------

     $remote_subroutine = Async_Invoke('job_name',@arguments);

   Invoke a job to asynchronously call a remote subroutine.

   Where @arguments is the normal list of arguments for the remote
subroutine.

Get a new RCGI object using a job type
--------------------------------------

     $remote_subroutine = new_job RCGI('job_name');

     OR

     $remote_subroutine = new_job RCGI('job_name',$minimum_load);

   This will create a new object which will allow a remote subroutine call
for a particular job type.  *$minimum_load* is the minimum percentage of
idle to leave when assigning jobs.

Creating a new RCGI object:
---------------------------

     $remote_subroutine = new RCGI($base_url,$library_path,$module,$subroutine)

     OR

     $remote_subroutine = new RCGI($base_url,$library_path,$module,$subroutine,
     				  -option => value)

   The arguments are:

   *$base_url* - the base URL for the remote subroutine call.  This is the
URL for perlcall.cgi on the remote web server.

   *$library_path* - the location of the module which contains the
subroutine for the remote subroutine call.  This is optional-undef may be
passed instead if the module is located relative to the perl *@INC* path.
A '.' may be passed to specify the cgi-bin directory on the remote web
server.

   *$module* - the module which contains the subroutine for the remote
subroutine call.

   *$subroutine* - the name of the subroutine to call for the remote
subroutine call.  This subroutine must be callable in the form
*Module_Name::subroutine();*.  Please remember that no executation state
is maintained by default on the remote computer.

   Options are passed as: -option => value, where -option is one of:

     -async          Do an asynchronous call.
     -wantarray      Force array or scalar result (useful for using with async).
     -username       Username to login to remote web server, if any.
     -password       Password to login to remote web server, if any.
     -user_agent     User_agent to use for remote web server.
     -timeout        Timeout in seconds for web connection (default is 180).

   This will create a new object which allows remote subroutine calls.

Calling the remote subroutine with Call
---------------------------------------

   Synchronous Call

     @my_result = $remote_subroutine->Call(@arguments);

     OR

     $my_result = $remote_subroutine->Call(@arguments);

   Where @arguments is the normal list of arguments for the remote
subroutine.

   Asynchronous Call

     $remote_subroutine->Call(@arguments);

     while(! $remote_subroutine->Done()) {
     	# This should really be something useful
     	sleep 1;
     }
     @my_result = $remote_subroutine->Read();

     OR

     $my_result = $remote_subroutine->Read();

   Where @arguments is the normal list of arguments for the remote
subroutine.

Check to see if an asynchronous call is Done
--------------------------------------------

     $remote_subroutine->Done();

   Return true when the asynchronous call has completed.

Read the results from an asynchronous call
------------------------------------------

     @my_result = $remote_subroutine->Read();

     OR

     $my_result = $remote_subroutine->Read();

   Fetch the result from an asynchronous call.

Success or failure of the remote subroutine call
------------------------------------------------

     $remote_subroutine->Success()

   This returns true if the remote subroutine call was completed with no
errors.

The return Status of rhte remote subroutine call
------------------------------------------------

     $remote_subroutine->Status()

   This returns the status code from the remote subroutine call.  Possible
values are:

     -30 -- Machines are busy, the load is less than the load minimum (default is zero idle)

     -27 -- Missing task_url, module, or subroutine for job type definition for assigned machine

     -26 -- Missing job type definition for assigned machine

     -25 -- Missing sar measurement for assigned machine

     -24 -- Unable to assign machine

     -20 -- No job types defined match asked for job type

     -13 -- Unable to open load file

     -12 -- Unable to open sar file

     -11 -- Unable to open server.conf file

     -10 -- Unable to open jobs.conf file

     -1 -- The base URL, the module, or the subroutine were not given.

     -2 -- Unable to fork background process for asynchronous call.

     200 -- Successful call.

     >200 -- Error code from remote web server or CGI script

Error_Message
-------------

     $remote_subroutine->Error_Message()

   This returns the associated error message, if any, from an unsuccessful
remote subroutine call.  If the Status is greater than 200, then the error
message is from the remote web server.

Base_URL
--------

     $base_url = $remote_subroutine->Base_URL();

     OR

     $remote_subroutine->Base_URL($base_url);

   Get or set the base URL for the remote subroutine call.  This is the
URL for *perlcall.cgi* on the remote web server.

Library_Path
------------

     $library_path = $remote_subroutine->Library_Path();

     OR

     $remote_subroutine->Library_Path($library_path);

   Get or set the location of the module which contains the subroutine for
the remote subroutine call.  This is optional-undef may be passed instead
if the module is located relative to the perl *@INC* path.  A '.' may be
passed to specify the cgi-bin directory on the remote web server.

Module
------

     $module = $remote_subroutine->Module();

     OR

     $remote_subroutine->Module($module);

   Get or set the module which contains the subroutine for the remote
subroutine call.

Subroutine
----------

     $subroutine = $remote_subroutine->Subroutine();

     OR

     $remote_subroutine->Subroutine($subroutine);

   Get or set the name of the subroutine to call for the remote subroutine
call.  This subroutine must be callable in the form
*Module_Name::subroutine();*.  Please remember that no executation state
is maintained by default on the remote computer.

Async
-----

     $async = $remote_subroutine->Async();

     OR

     $remote_subroutine->Async($async);

   Get or set whether the call is asynchronous.

Wantarray
---------

     $wantarray = $remote_subroutine->Wantarray();

     OR

     $remote_subroutine->Wantarray($wantarray);

   Get or set whether the call returns a scalar or an array (or
associative array).

Username
--------

     $username = $remote_subroutine->Username();

     OR

     $remote_subroutine->Username($username);

   Get or set the username, if any, used to login to the remote server.

Password
--------

     $password = $remote_subroutine->Password();

     OR

     $remote_subroutine->Password($password);

   Get or set the password, if any, used to login to the remote server.

User_Agent
----------

     $user_agent = $remote_subroutine->User_Agent();

     OR

     $remote_subroutine->User_Agent($user_agent);

   Get or set the user_agent used to when connecting to the remote server.

Timeout
-------

     $timeout = $remote_subroutine->Timeout();

     OR

     $remote_subroutine->Timeout($timeout);

   Get or set the timeout in seconds used in the connection to the remote
server.  Default is 180 seconds.

Process_Parameters
------------------

     ($cgi_form, %options) = RCGI::Process_Parameters( new CGI , \%TRANSLATE, \%IGNORE );

   This processes the CGI parameters, using the passed CGI object
reference.  The optional %TRANSLATE associative array allows passing CGI
parameters with a different parameter field name (i.e., translate paramter
foo=1 to bar=1).  The optional %IGNORE associative array specifies CGI
parameters which should not be passed on.

   Returned are *$cgi_form* which is a reference to an associative array
which contains the CGI parameters in a form ready to pass to
*RCGI::run_cgi_command()* and the %options associative array of options to
pass to *RCGI::run_cgi_command()*.

run_cgi_command
---------------

     $result = RCGI::run_cgi_command($base_url, \%cgi_form, %options);

   This fetches an HTML page from either a static HTML page or a CGI
script.

   *$base_url* is the URL of the page to get.  \%cgi_form is an associate
array whose index is CGI parameters to pass and whose values are the CGI
parameter values to pass to the remote CGI script.  If a parameter's name
has 'upload:' prepended to it, then the values will be passed using the
multipart/form-data file upload method.  (Example $cgi_form = {
'upload:seq_file' => "> sequence\nAAAAA\n" }.)

   Options are passed as: -option => value, where -option is one of:

     -method         CGI method to use (GET is default).
                     Values are 0 or undef for GET and 1 for POST
     -nph            Use 1 to treat the remote CGI script as NPH.
     -username       Username to login to remote web server, if any.
     -password       Password to login to remote web server, if any.
     -user_agent     User_agent to use for remote web server.
     -timeout        Timeout in seconds for web connection (default is 180).

Example Job Invoke Script
=========================

     #!/usr/local/bin/perl

     use RCGI;
     @result = Invoke('jobtest1','one');
     print @result;

     $result = Invoke('jobtest2','two');
     print $result;
     exit;

     $remote = new_job RCGI('jobtest1');
     @out = $remote->Call('one');
     if ( $remote->Success() == 0) {
     	print " Failed with error: " .
     	    $remote->Error_Message() . "\n";
     	undef @out;
     }

Example Remote Subroutine Call Script
=====================================

     #!/usr/local/bin/perl
     #
     #

     use RCGI;

     $base_url = 'http://www.sandrock.edu/cgi-bin/perlcall.cgi';
     $library_path = '/my/module/directory';
     $module = 'MyModule';
     $subroutine = 'my_subroutine';
     $remote_subroutine = new RCGI($base_url,$library_path,$module,$subroutine);

     @my_result = $remote_subroutine->Call(0, 'a', 'b');
     $, = "\n";
     if ($remote_subroutine->Success()) {
         print @my_result,'';
     } else {
         print STDERR "Call to " . $remote_subroutine->Base_URL() .
     	" failed with status: " . $remote_subroutine->Status() .
     	    ' ' . $remote_subroutine->Error_Message() . "\n";
     }

     $my_result = $remote_subroutine->Call(0, 'a', 'b', 'c');
     if ($remote_subroutine->Success()) {
         print $my_result,'';
     } else {
         print STDERR "Call to " . $remote_subroutine->Base_URL() .
     	" failed with status: " . $remote_subroutine->Status() .
     	    ' ' . $remote_subroutine->Error_Message() . "\n";
     }

     $remote_subroutine->Async(1);
     $remote_subroutine->Wantarray(1);
     $remote_subroutine->Call(5, 'async', 'hronous');
     $| = 1;
     while(! $remote_subroutine->Done()) {
         # This should really be something usefull--like calls to other servers!
         sleep 1;
         print ".";
     }
     @my_result = $remote_subroutine->Read();
     $, = "\n";
     if ($remote_subroutine->Success()) {
         print @my_result,'';
     } else {
         print STDERR "Call to " . $remote_subroutine->Base_URL() .
     	" failed with status: " . $remote_subroutine->Status() .
     	    ' ' . $remote_subroutine->Error_Message() . "\n";
     }

REPORTING BUGS
==============

   When reporting bugs/problems please include as much information as
possible.

   A small script which yields the problem will probably be of help.  If
you cannot include a small script then please include a Debug trace from a
run of your program which does yield the problem.

AUTHOR INFORMATION
==================

   Brian H. Dunford-Shore   brian@ibc.wustl.edu David J. States
states@ibc.wustl.edu

   Copyright 1998, Washington University School of Medicine, Institute for
Biomedical Computing.  All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Address bug reports and comments to: www@ibc.wustl.edu

TODO
====

Save the result dump in a file for batch mode
Save the arguments in a file for queued batch mode
SEE ALSO
========

CREDITS
=======

BUGS
====

   You really mean 'extra' features ;).  None known.

COPYRIGHT
=========

   Copyright (c) 1997 Washington University, St. Louis, Missouri. All
rights reserved.  This program is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

Remote Control Unit Interface
*****************************

NAME
====

   RCU - Remote Control Unit Interface

SYNOPSIS
========

     use RCU;

DESCRIPTION
===========

   This module provides a generic interface to remote control units (only
receivers at the moment, as I cannot test more). It only provides an
abstract management interface, other modules are required for the hardware
access (RCU::Irman and RCU::Lirc are included, however).

GETTING STARTED
---------------

   Please read RCU/Receipts, to get some idea on how
to proceed after you installed the module (testing & standard techniques).

THE RCU CLASS
=============

   The RCU class provides a general interface to anything you might want to
do to, it represents your application.

$rcu = new RCU "interface-spec"
     Creates a new RCU application. interface must be an interface
     specification similar to DBI's DSN:

          RCU:ifname:arg:arg...

     Examples: low-level interface (without `RCU::' prefix) or an arrayref
     containing name and constructor arguments. If the interface name has
     a `::' prefix it will be used as-is (without that prefix, of course).

     For a much better interface, see RCU/Event.

$rcu->interface
     Return the RCU::Interface object used by this RCU object.

($keycode, $repeat) = $rcu->get
($keycode, $repeat) = $rcu->poll
     Simplified interface to the RCU (See also RCU/Event),
     return a cooked keycode and a repeat count (initial
     keypress = 0, increasing while the key is pressed). If get is called
     in scalar context it only returns unrepeated keycodes.

     This interface is problematic: no key-up events are generated, and
     the repeat events occur pseudo-randomly and have no time relation
     between each other, so better use the event-based interface provided
     by `RCU::Event|RCU::Event' in this node.

THE RCU::Key CLASS
==================

   This class collects information about rcu keys.

THE RCU::Interface CLASS
========================

   `RCU::Interface' provides the base class for all rcu interfaces, it is
rarely used directly.

fd
     Return a unix filehandle that can be polled, or -1 if this is not
     possible.

($time, $raw, $cooked) = $if->get
($time, $raw, $cooked) = $if->poll
     Wait until a RCU event happens and return it. If the device can
     translate raw keys events (e.g. hex key codes) into meaningful names
     ("cooked" keys) it will return the cooked name as second value,
     otherwise both return values are identical.

     get always returns an event, waiting if neccessary, while poll only
     checks for an event: If one is pending it is returned, otherwise poll
     returns nothing.

SEE ALSO
========

   See RCU/Irman, RCU/Lirc.

AUTHOR
======

   This perl extension was written by Marc Lehmann <pcg@goof.com>.

BUGS
====

   No send interface.

Remote Control Unit Interface
*****************************

NAME
====

   RCU::Context - Remote Control Unit Interface

SYNOPSIS
========

     use RCU::Context;

DESCRIPTION
===========

$ctx = new RCU::Context;
     Create a new key context.

$ctx->bind(event, action)
     Bind the given action to an event (see EVENT SYNTAX, below, for an
     explanation of this string).

     action must be one of the following:

          A code-reference
            This code reference will be called with the event name, generating rcu,
            timestamp and any additional arguments (usually none) fiven to the
            inject method.

          "enter", $context
          "enter*", $context
            Enter the given context object. The forms with an appended star "re-exec"
            the event in the new context.

          "leave"
          "leave*"
            leave the current context (restoring the context active before it was
            "enter"'ed)

          "switch", $context
          "switch*", $context
            switch to the given context object

     For every keypress, *only the first* (in order of their definition)
     matching event handler is being executed.

$ctx->inject(event, time, rcu, args...)
     Simulate the given event (see "EVENT SYNTAX", below).

$ctx->enter($rcu)
$ctx->leave($rcu)
     "Enter" ("Leave") the context (and create an <enter> (<leave>")
     event). Not usually called by application code.

EVENT SYNTAX
============

   The simplest way to specify events is using the (cooked) keyname, e.g.
the event `cd-shuffle' occurs when the key named "cd-shuffle" was pressed
down.

   Since events are regular expressions, you have to quote any special
characters (like . or *, where ^, `$' and . stop at keys boundaries) if
you want to use them. On the other hand, regexes give you great freedom,
if you specify the event:

     rcu-key-(\d+)

   ... you can then use "$1" in your callback to find out which digit was
pressed.

   You can prefix a keyname with a "~" which means the key was released
(deactivates, switched off) instead of being pressed. If you want to force
interpretation as a key-down event you can prefix the keyname with an "="
character.

   Every key will always generate two events: one key-down (activate) event
when it is pressed and one "~" (key-up) event when it is released again.
It is not possible that two keys are active at the same time.

   To make matters slightly more complicated, you can also prepend a
"history" of key names (all seperated by ":") before the current event.
This means that the event depends on previous key-presses (no prefix
characters are there).

   Examples (all key names are, of course, hypothetical):

     <enter>          enter the current context
     key-ff           the fast forward key was pressed down
     =key-ff          same as above
     ~key-rev         the "rev"-key was released
     key-tuner:key-4  first the tuner key was pressed (and released), then "4"
     key-tuner:~key-4 first the tuner key was pressed, then "4" was released
     k1:k2:k3         the keys "1", "2" were pressed and released, then
                      "3" was pressed.

   EBNF-Grammar

   For those of you who need it...

     event     := history prefix eventname
     history   := <empty> | keyname ":" history
     prefix    := <empty> | "=" | "~"
     eventname := keyname | "<enter>" | "<leave>"
     keyname   := any string consisting of printable, non-whitespace
                  characters without ":"

SEE ALSO
========

   See RCU.

AUTHOR
======

   This perl extension was written by Marc Lehmann <pcg@goof.com>.

Event-based RCU operation
*************************

NAME
====

   RCU::Event - Event-based RCU operation

SYNOPSIS
========

     use RCU::Event;

     $rcu = connect RCU::Event "interfac-spec", [initial-context]

DESCRIPTION
===========

   This module provides a superset of the standard `RCU' interface by
adding an event-based interface. Basically, you create one or more
*contexts* (See `RCU::Context') and bind it to a RCU::Event object. All
key events will then be directed to the current context.

$ctx = connect RCU::Event "interface-desc";
     Create a new RCU interface. The functionality is the same as
     `RCU|RCU' in this node, with the functions added below.

$rcu->inject(key)
     Act as if key key was pressed (key starts with "=") or released (when
     key starts with `~').  This is rarely used but is useful to
     "simulate" key presses.

$rcu->set_context(new_context)
     Leave the current context (if any) and enter the `new_context', to
     which all new events are directed to.

$rcu->push_context(new_context)
     Enter the given `new_context' without leaving the current one.

$rcu->pop_context
     Leave the current context and restore the previous context that was
     saved in `push_context'.

SEE ALSO
========

   See RCU.

AUTHOR
======

   This perl extension was written by Marc Lehmann <pcg@goof.com>.

RCU interface to libirman.
**************************

NAME
====

   RCU::Irman - RCU interface to libirman.

SYNOPSIS
========

     use RCU::Irman;

DESCRIPTION
===========

   See RCU.

new <path>
     Create an interface to the RCU receiver at serial port <path> (default
     from in irman.conf used if omitted).

AUTHOR
======

   This perl extension was written by Marc Lehmann <pcg@goof.com>.

RCU interface to linux-infrared-remote-control
**********************************************

NAME
====

   RCU::Lirc - RCU interface to linux-infrared-remote-control

SYNOPSIS
========

     use RCU::Lirc;

DESCRIPTION
===========

   See RCU.

new progname
     Create an interface to lircd using the configuration for program
     "progname".

AUTHOR
======

   This perl extension was written by Marc Lehmann <pcg@goof.com>.

RCU::Receipts
=============

   This manpage contains some examples that should help you getting started
with the module and solving common problems.

THE BASICS
----------

Debugging The Connection
     To find out wether the connection actually works, you can try this
     very simple program:

          use RCU;

          $rcu = new RCU "RCU:Lirc";

          # endless loop
          while () {
             my ($key, $repeat) = $rcu->get;
             print "EVENT $key (= $repeat)\n";
          }

     If you do not use the lirc interface you would have to specify another
     one on the call to new, like `RCU:Irman' for your irman (very nice)
     or `RCU:Irman:/dev/ttyS1' if you know that your irman is connected to
     `/dev/ttyS1'.

     Here is some example output:

          EVENT sony-cd-next (= 0)
          EVENT sony-cd-next (= 1)
          EVENT sony-cd-next (= 0)
          EVENT sony-cd-next (= 1)
          EVENT sony-cd-next (= 2)
          EVENT sony-cd-fwd (= 0)
          EVENT sony-cd-fwd (= 1)
          EVENT sony-cd-4 (= 0)
          EVENT sony-cd-4 (= 1)

     ... correspong to two times "sony-cd-next", and one press for
     "sony-cd-fwd" and "sony-cd-4".

Using Event
     If you don't know how the Event module works you should read about
     that one first and come back.

     In general, the Event-API is easy to use. The only (seeming)
     complication is that you have to think a bit about your setup. The
     reason you should use this API is that using repeated keypresses has
     one major drawback: It does not let you know when the user stopped
     pressing the key (the events just do not occur) and different remotes
     repeat their pulses with different frequency. The only thing that you
     should use to measure the duration of a keypress is therefore
     wallclock time.

     This is what the Event-API does: It translates normal key-events into
     key-down/key-up pairs, on which you can bind any action you want (See
     RCU/Context). Since keypresses usually do not
     happen in some informational void but depend on previous keys and
     e.g. the mode of the application, you have to put all your events
     into some context (actually, into some RCU/Context,
     -object), like this:

          use Event;
          use RCU::Event;
          use RCU::Context;

          # create a new context
          $ctx = new RCU::Context;

          # and bind some actions to some events
          $ctx->bind(
                "sony-cd-stop" => sub { print "T$_[1]: STOP pressed\n" },
                "~sony-cd-1"   => sub { print "T$_[1]: 'one' key released\n" },
                "=.*"          => sub { print "T$_[1]: unknown event '$_[0]'\n" },
          );

          # connect to the RCU
          $rcu = new RCU::Event "RCU:Irman";
          $rcu->set_context($ctx);

          # jump into the main event loop
          Event::loop;

     Here is some sample output:

          T965403699.132146: STOP pressed
          T965403703.059969: unknown event 'sony-cd-stop:=sony-cd-1'
          T965403703.621847: 'one' key released

     As you can see, I first pressed the STOP button, followed by a press
     of the "1" button, for which the default handler was used, since we
     haven't bound "STOP followed by 1" to any event, followed by the
     button-release event.

RECEIPTS
--------

   ... not written yet ...

A Volume Slider
Digit Input
AUTHOR
======

   This document was wirtten by Marc Lehmann <pcg@goof.com>

Relational DataBase Abstraction Layer class (ReDBALl)
*****************************************************

NAME
====

   RDBAL - Relational DataBase Abstraction Layer class (ReDBALl)

SYNOPSIS
========

     use RDBAL;

     $connection = RDBAL::Connect('username', 'password', 'server');

     $connection->Query("SQL query"); #	Execute an SQL select and return the results in an array

     $connection->Sql("SQL command(s)"); #	Execute an arbitrary SQL command

     $connection->PrintTable(); #	print the results of the most recent select

     $connection->PrintTables(); #	print the results of one or more selects

     $connection->ColumnNames(); #	get column names for results table

     $connection->ColumnTypes(); #	get column data types for results table

     $connection->ColumnLengths(); #	get column lengths for results table

DESCRIPTION
===========

   RDBAL is a perl module to work with a SQL Relational database.  A
middle layer driver may be written for any database connection layer.  It
is also possible to write middle layer drivers which would parse SQL
statements and implement them in some arbitrary fashion.

   Currently available are: Pg (PostgreSQL), Apache::Sybase::DBlib,
Sybase::DBlib, ODBC middle layer drivers, and dbi:Sybase.

   The presence of a given middle layer driver may be checked by checking
to see if: $RDBAL::Layer{'Pg'}, $RDBAL::Layer{'ApacheSybaseDBlib'},
$RDBAL::Layer{'SybaseDBlib'}, $RDBAL::Layer{'ODBC'}, or
$RDBAL::Layer{'dbi:Sybase'} is defined.

FUNCTIONS
=========

$connection = RDBAL::Connect('username', 'password', 'server', ['preferred_layer']);
------------------------------------------------------------------------------------

   Create/get a connection to a database (server).

   Username and password are mandatory for database servers which require
logins.  For Win32::ODBC, server is the name of an existing DSN.

   Possible values for preferred_layer are (in the order of default
preference):

Pg
ApacheSybaseDBlib
SybaseDBlib
ODBC
dbi:Sybase
dbi:Oracle
$connection->Query("SQL query")
-------------------------------

   Execute an SQL select and return the results in an array.

$connection->Sql("SQL command(s)")
----------------------------------

   execute an arbitrary SQL command.

$connection->RowCount()
-----------------------

   Fetch the number of rows that were affected by the previous SQL command.

@row = $connection->NextRow();
------------------------------

   fetch the next row from a result set

$bool_regular_row = $connection->Regular_Row();
-----------------------------------------------

   see if the row just fetched is a regular data set row

$bool_no_more_result_sets = $connection->More_Results();
--------------------------------------------------------

   see if there are any more result sets

$connection->PrintTable()
-------------------------

   Print the results of the most recent select.

$connection->PrintTables()
--------------------------

   Print the results of one or more selects.

$connection->ColumnNames()
--------------------------

   Get column names for results table.

$connection->ColumnTypes()
--------------------------

   Get column data types for results table.

$connection->ColumnLengths()
----------------------------

   Get column lengths for results table.

REPORTING BUGS
==============

   When reporting bugs/problems please include as much information as
possible.

   A small script which yields the problem will probably be of help.  If
you cannot include a small script then please include a Debug trace from a
run of your program which does yield the problem.

AUTHOR INFORMATION
==================

   Brian H. Dunford-Shore   brian@ibc.wustl.edu

   Copyright 1998, Washington University School of Medicine, Institute for
Biomedical Computing.  All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Address bug reports and comments to: www@ibc.wustl.edu

TODO
====

   These are features that would be nice to have and might even happen
someday (especially if YOU write it).

Other types of database servers:
     (mSQL, mySQL, etc.).

SEE ALSO
========

   *Sybase::DBlib* - http://www.ibc.wustl.edu/perl5/other/sybperl.html

   *Win32::odbc* - http://www.ibc.wustl.edu/perl5/other/Win32/odbc.html

CREDITS
=======

   Thanks very much to:

   *David J. States* (states@ibc.wustl.edu)

   and

   *Fyodor Krasnov* (fyodor@bws.aha.ru)

     for suggestions and bug fixes.

BUGS
====

   You really mean 'extra' features ;).  None known.

COPYRIGHT
=========

   Copyright (c) 1997, 1998, 1999 Washington University, St. Louis,
Missouri. All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

RDBAL Schema information object
*******************************

NAME
====

   RDBAL::Schema - RDBAL Schema information object

SYNOPSIS
========

     use RDBAL;
     use RDBAL::Schema;
     $X = RDBAL::Connect('username', 'password', 'server');
     $schema = new($X,$database);
     $database = $schema->Database();
     @user_tables = $schema->User_Tables();
     @views = $schema->Views();
     @procedures = $schema->Procedures();
     @system_tables = $schema->System_Tables();
     @fields = $schema->Table_Fields($table);
     @fields = $schema->System_Table_Fields($table);
     @fields = $schema->View_Fields($view);
     @fields = $schema->Procedure_Parameters($procedure);
     @fields = $schema->Fields($object,$object_type);
     $field_info = $schema->Field_Info($object,$field,$object_type,$info_type);
     $primary_key_number = $schema->Primary_Key($object,$field,$object_type);
     $field_type = $schema->Field_Type($object,$field,$object_type);
     $field_length = $schema->Field_Length($object,$field,$object_type);
     $field_width = $schema->Field_Width($object,$field,$object_type);
     $field_precision = $schema->Field_Precision($object,$field,$object_type);
     $field_scale = $schema->Field_Scale($object,$field,$object_type);
     $field_identity = $schema->Field_Identity($object,$field,$object_type);
     $field_null = $schema->Field_Null($object,$field,$object_type);
     @indexes = $schema->Indexes($table,$object_type);
     @primary_keys = $schema->Primary_Keys($table,$object_type);
     @keys = $schema->Keys($table,$object_type);
     @children_tables = $schema->Children($table);
     @parent_tables = $schema->Parents($table);
     @field_equivalences = $schema->Relation($parent,$child);
     # Get comments (views' and procedures' definitions)
     $comments = $schema->Comments($object,$object_type)
     # Get view's tables
     @tables = $schema->View_Tables($view)

ABSTRACT
========

   This perl library uses perl5 objects to make it easy to retrieve
information about a particular PostgreSQL, Sybase, MS SQL, or Oracle
databases's schema.

INSTALLATION:
=============

   If you wish to change the location of the schema cache directory from
the default value of '/usr/local/schema_cache', edit Config.pm.

   To install this package, just change to the directory in which this
file is found and type the following:

     perl Makefile.PL
     make
     make test
     make install

   and to create the schema cache directory:

     make schema_cache

Installation of pg_schema.pl
----------------------------

   An example script for converting a DDL in Transact SQL format to
PostgreSQL format with foreign key relational integrity enforced and
remembered by PostgreSQL rules is included and must be manually installed
(change the first line from #!/usr/local/bin/perl if your perl lives
elsewhere).  See pg_schema.pl below for more.

DESCRIPTION
===========

   The schema information available includes:

Objects:     tables, views, and procedures
Objects' fields (or parameters)
Objects' fields' properties:           type, length, precision, scale, identity column, nullable
Tables' indexes and primary keys
Parent => child relations between tables including primary key/foreign key equivalences.
Views' and Procedures' definitions (Comments).
A view's underlying tables.
   The database connection is cached in the schema object.  Objects and
their fields properties and index information are retrieved when the
schema object is created.  Table relationship information is retrieved for
all tables when the first relationship information is requested.

pg_schema.pl
------------

   The rules this script creates are necessary for RDBAL to have foreign
key relation information.  It translates a foreign key reference into
PostgreSQL rules:

   FROM:

     alter table table2
         add foreign key  (field1, field2)
            references table1 (field1, field2)
     go

   TO:

   Insert RI:

     create rule fk_table2_insert as on insert to table2
     where new.field1 <> table1.field1 and new.field2 <> table1.field1
             do instead nothing;

   Update RI:

     create rule fk_table2_update as on update to table2
     where new.field1 <> table1.field1 and new.field2 <> table1.field2
             do instead nothing;

     create rule pk_table1_update as on update to table1
     where old.field1 = table2.field1 and old.field2 = table2.field2
             do instead nothing;

   NOTE: the pk_update rule must list all children!

   Delete RI:

     create rule pk_table1_delete as on delete to table1
     where old.field1 = table2.field1 and old.field2 = table2.field2
             do instead nothing;

   NOTE: the delete rule must list all children!

   This script also maps datatypes:

smalldatetime to datetime
tinyint to int

float4 or float8 to float
   pg_schema.pl reads the input DDL on standard input and writes the
output DDL to standard output.

CREATING A NEW RDBAL::Schema OBJECT:
------------------------------------

     $query = new RDBAL::Schema($connection,$database);

     OR

     $query = new RDBAL::Schema($connection,$database, -option => value);

   Options are passed as: -option => value, where -option is one of:

     -server         Database server name.  This is used to differentiate
                     between databases when caching.
     -server_type    Database server type.  This is used to differentiate
                     how to retrieve the schema.  The default is Transact-SQL
                     or a hand-crafted schema cache file.  Currently, the
                     only correct values for this are I<undef>, I<pg>,
                     I<oracle>, I<dbi:Sybase>, or I<dbi:Oracle>.
     -get_system     1 or undef.  A true value for this option causes retrieval
                     (and caching) of schema for system tables.
     -nocache        1 or undef.  A true value causes the cached schema to not
                     be used and a new cache to be written.
     -username       Database username.  This is used to differentiate
                     between different users views of a database when caching.

   This will create a new schema object for the database.  This must be
given an open connection to a RDBAL database server object:

     use RDBAL;
     $connection = RDBAL::Connect('username', 'password', 'server');

Fetching the database from the schema object:
---------------------------------------------

     $database = $schema->Database();

   The database may be retrieved from the database schema object.

Fetching the user tables from the schema:
-----------------------------------------

     @user_tables = $schema->User_Tables();

   The user tables may be retrieved from the database schema.

Fetching the views from the schema:
-----------------------------------

     @views = $schema->Views();

   The views may be retrieved from the database schema.

Fetching the procedures from the schema:
----------------------------------------

     @procedures = $schema->Procedures();

   The procedures may be retrieved from the database schema.

Fetching the system tables from the schema:
-------------------------------------------

     @system_tables = $schema->System_Tables();

   The system tables may be retrieved from the database schema if the
-get_system option was given when the schema object (or its cache) was
created.

Fetching the fields from the schema for a user table:
-----------------------------------------------------

     @fields = $schema->Table_Fields($table);

   A user table's fields may be retrieved from the database schema.

Fetching the fields from the schema for a system table:
-------------------------------------------------------

     @fields = $schema->System_Table_Fields($table);

   A system table's fields may be retrieved from the database schema if
the -get_system option was given when the schema object (or its cache) was
created.

Fetching the fields from the schema for a view:
-----------------------------------------------

     @fields = $schema->View_Fields($view);

   A view's fields may be retrieved from the database schema.

Fetching the parameters from the schema for a procedure:
--------------------------------------------------------

     @parameters = $schema->Procedure_Parameters($procedure);

   A procedure's parameters may be retrieved from the database schema.

Fetching the fields from the schema:
------------------------------------

     @fields = $schema->Fields($object,$object_type);

   *$object_type* is optional and defaults to *'User Table'*.

   The fields may be retrieved from the database schema for
*$object_type*'s of:

'User Table'
'System Table'
'View'
'Procedure'
Fetching the primary key number from the schema for a field:
------------------------------------------------------------

     $primary_key_number = $schema->Primary_Key($object,$field,$object_type);

   *$object_type* is optional and defaults to *'User Table'*.

   The primary key number may be retrieved from the database schema for a
field.  undef is returned if the field is not a primary key.

Fetching the field type from the schema:
----------------------------------------

     $field_type = $schema->Field_Type($object,$field,$object_type);

   *$object_type* is optional and defaults to *'User Table'*.

   The field type may be retrieved from the database schema.

Fetching the field length from the schema:
------------------------------------------

     $field_length = $schema->Field_Length($object,$field,$object_type);

   *$object_type* is optional and defaults to *'User Table'*.

   The field length may be retrieved from the database schema.

Fetching the field width from the schema:
-----------------------------------------

     $field_width = $schema->Field_Width($object,$field,$object_type);

   *$object_type* is optional and defaults to *'User Table'*.

   A value for the character string width of a field may be retrieved from
the database schema.

Fetching the field precision from the schema:
---------------------------------------------

     $field_precision = $schema->Field_Precision($object,$field,$object_type);

   *$object_type* is optional and defaults to *'User Table'*.

   The field precision may be retrieved from the database schema.

Fetching the field scale from the schema:
-----------------------------------------

     $field_scale = $schema->Field_Scale($object,$field,$object_type);

   *$object_type* is optional and defaults to *'User Table'*.

   The field scale may be retrieved from the database schema.  If the
field datatype does not have a scale, the value is undef.

Fetching the field's identity column status from the schema:
------------------------------------------------------------

     $field_identity = $schema->Field_Identity($object,$field,$object_type);

   *$object_type* is optional and defaults to *'User Table'*.

   The field's identity column status may be retrieved from the database
schema.  Nonzero implies the field is an identity column.

Fetching the field nullable from the schema:
--------------------------------------------

     $field_null = $schema->Field_Null($object,$field,$object_type);

   *$object_type* is optional and defaults to *'User Table'*.

   Whether a field is nullable may be retrieved from the database schema.
It is a 1 if the field is nullable.

Fetching a field's (or parameter's) information from the schema:
----------------------------------------------------------------

     $field_info = $schema->Field_Info($object,$field,$object_type,$info_type);

   *$object_type* is optional and defaults to *'User Table'*.
*$info_type* is optional and defaults to 'Type'.

   A field's information may be retrieved from the database schema for
*$object_type*'s of:

'User Table'
'System Table'
'View'
'Procedure'
   and *$info_type*'s of:

'Primary_Key'
'Type'
'Length'
'Precision'
'Scale'
'Identity'
'Null'

The primary key number may be retrieved from the database schema for a field.      undef is returned if the field is not a primary key.
The field type may be retrieved from the database schema.
The field length may be retrieved from the database schema.
The field precision may be retrieved from the database schema.
The field scale may be retrieved from the database schema.
The field's identity column status may be retrieved from the database schema.      Nonzero implies the field is an identity column.
Whether a field is nullable may be retrieved from the database schema.      It is a 1 if the field is nullable.
Fetching the indexes from the schema:
-------------------------------------

     @indexes = $schema->Indexes($table,$object_type);

   *$object_type* is optional and defaults to *'User Table'*.

   The indexes may be retrieved from the database schema.  Each index is
reported as (each item seperated by tabs):

     index_name	index_description	comma_seperated_index_field_list

   Example:

     PK_STS	clustered, unique located on default	chromosome, arm, id_number

Fetching the primary key fields from the schema:
------------------------------------------------

     @primary_keys = $schema->Primary_Keys($table,$object_type);

   *$object_type* is optional and defaults to *'User Table'*.

   The primary key fields may be retrieved from the database schema.

Fetching all index keys from the schema:
----------------------------------------

     @keys = $schema->Keys($table,$object_type);

   *$object_type* is optional and defaults to *'User Table'*.

   All of the index keys may be retrieved from the database schema.  Each
array element is a comma delimited list of the index's keys.

Fetching the children tables from the schema:
---------------------------------------------

     @children_tables = $schema->Children($table);

   A table's children tables may be retrieved from the database schema.

Fetching the parent tables from the schema:
-------------------------------------------

     @parent_tables = $schema->Parents($table);

   A table's parent tables may be retrieved from the database schema.

Fetching the field equivalences from the schema:
------------------------------------------------

     @field_equivalences = $schema->Relation($parent,$child);

   The key field equivalences may be retrieved from the database schema.
Each key field equivalence array element is given as:
parent_key_field=child_key_field

Fetching the comments (views' and procedures' definitions) from the schema:
---------------------------------------------------------------------------

     $comments = $schema->Comments($object,$object_type)

   *$object_type* is optional and defaults to 'Procedure'.

   The comments (views' and procedures' definitions) may be retrieved from
the database schema.

Getting a view's underlying tables from the schema:
---------------------------------------------------

     @tables = $schema->View_Tables($view)

   A view's underlying tables may be retrieved from the database schema.

Quote a field's value if necessary
----------------------------------

     $quoted_field = $schema->Quote_Field($object,$field,$value,$object_type);

   Appropriately put quote marks around a field's value.  Single quote
marks get doubled, example: dont't  ==> "don"t".

Schema Cache File Format
========================

   The schema cache file contains individual lines which describe some
part of a schema (a descriptor).  Each descriptor is a tab delimited line
with the first element on the line specifying what is being described (the
type).  Carriage returns (not newlines) may be embedded in the comment
(definition) descriptor elements.  Blank lines follow each group of index
descriptors for a table.  Line feeds seperate different types of
descriptors.

Object Descriptor
-----------------

   An object descriptor describes the fields or parameters of a system or
user table, a view, or a procedure.  It contains the following (tab
delimited) elements:

Type = 'O'
Object = owner.object (owner defaults to 'dbo')
Object type:
          S => 'System Table'
          U => 'User Table'
          V => 'View'
          P => 'Procedure'
          TABLE => 'User Table'
          VIEW => 'View'
          PROCEDURE => 'Procedure'

Field name
Field type
Field length
Field precision
Field scale
Identity field (1 if true)
Nullable field (1 if true)
Primary Key Descriptor
----------------------

   A primary key descriptor lists the primary key for a table and the
fields which comprise the primary key.  It contains the following (tab
delimited) elements:

Type = 'PK'
Name of object having primary key
Object type ('User Table' or 'System Table')
Database
Owner (default is 'dbo')
Object (table)
Primary Key field
Position in primary key
Primary Key name (optional)
Foreign Key Descriptor
----------------------

   A foreign key descriptor lists the foreign key relationships for a
table.  Each descriptor pairs a primary key field name of one table with
the corresponding foreign key field name of another table.  It also gives
the position each of those fields within the primary and foreign key
tuples.  It contains the following (tab delimited) elements:

Type = 'FK'
Object type ('User Table' or 'System Table')
Database
Owner (default is 'dbo')
Primary Key Object (table)
Primary Key field
Database
Owner (default is 'dbo')
Foreign Key Object (table)
Foreign Key field
Foreign key field position in tuple
Update rule number - always 1, if present
Delete rule number - always 1, if present
Foreign Key name (Optional)
Primary Key name (Optional)
Index Descriptors
-----------------

   An index descriptor lists the indexes for a table and the fields which
comprise that index.  It contains the following (tab delimited) elements
(blank lines follow each set of indexes for a table):

Type = 'I'
Index Object (table)
Index Object type ('User Table' or 'System Table')
Index Name
Index description
Comma seperated, ordered index field list
Comments (and stored procedure definitions) Descriptors
-------------------------------------------------------

   A comment (or definition) descriptor contains the following (tab
delimited) elements:

Type = 'C'
Object
Object Type is one of: 'User Table', 'System Table', 'View', 'Procedure'
Comment or definition (carriage returns replace newlines and tabs are replaced by five spaces
Example Script
==============

     #!/usr/local/bin/perl

     use RDBAL
     use RDBAL::Schema;

     $server   = shift;
     $database = shift;
     $username = shift;
     $password = shift;

     # Check to see if we want to use a different name for the server
     if ($RDBAL::Layer{'SybaseDBlib'} || $RDBAL::Layer{'ApacheSybaseDBlib'}) {
         $server = 'sybase_sql';
     } else {
         $server = 'odbc_sql';
     }
     if (!defined($server) ||
         !defined($database) ||
         !defined($username) ||
         !defined($password)) {
         die "Usage is: get_schema.pl server database username password\n";
     }

     # Get connnection to database server
     ( $X = RDBAL::Connect($username,$password,$server)
      or (die "Failed to connect to $server $username"));

     $schema = new RDBAL::Schema($X,$database, -get_system => 1);

     $, = "\t";
     print "Info for database: " . $schema->Database() . "\n";
     print "User Tables:\n";
     map {
         $table = $_;
         print "\tTable: $table\n";
         map {
     	print "\t\t". $_ . (($schema->Primary_Key($table,$_)) ? '*' : ''),
     	$schema->Field_Type($table,$_),
     	$schema->Field_Length($table,$_),
     	$schema->Field_Precision($table,$_),
     	$schema->Field_Scale($table,$_),
     	(($schema->Field_Identity($table,$_)) ? 'Identity' : ''),
     	(($schema->Field_Null($table,$_)) ? 'NULL' : 'NONNULL')
     	  . "\n";
         } $schema->Table_Fields($table);
         print "\t\tPrimary keys:", $schema->Primary_Keys($table,'User Table'),"\n";
         map {
     	@keys = split(',',$_);
     	print "\t\tIndex keys:", @keys ,"\n";
         } $schema->Keys($table,'User Table');
         map {
     	($index_name, $index_description, $keys) = split("\t",$_);
     	print "\t\tIndexes:\t$index_name\t$keys\t$index_description\n";
         } $schema->Indexes($table,'User Table');
         print "\t\tComments:", $schema->Comments($table,'User Table'), "\n";
         map {
     	print "\t\tParents: $_ (Reverse)", $schema->Relation($_,$table),"\n";
         } $schema->Parents($table);
         map {
     	print "\t\tChildren: $_", $schema->Relation($table,$_),"\n";
         } $schema->Children($table);
     } $schema->User_Tables();

     print "System Tables:\n";
     map {
         $table = $_;
         print "\tTable: $table\n";
         map {
     	print "\t\t". $_ . (($schema->Primary_Key($table,$_,'System Table')) ? '*' : ''),
     	$schema->Field_Type($table,$_,'System Table'),
     	$schema->Field_Length($table,$_,'System Table'),
     	$schema->Field_Precision($table,$_,'System Table'),
     	$schema->Field_Scale($table,$_,'System Table'),
     	(($schema->Field_Identity($table,$_,'System Table')) ? 'Identity' : ''),
     	(($schema->Field_Null($table,$_,'System Table')) ? 'NULL' : 'NONNULL')
     	    . "\n";
         } $schema->System_Table_Fields($table);
         print "\t\tComments:", $schema->Comments($table,'System Table'), "\n";
     } $schema->System_Tables();

     print "Views:\n";
     map {
         $table = $_;
         print "\tView: $table (Tables:", $schema->View_Tables($_), ")\n";
         map {
     	print "\t\t". $_,
     	$schema->Field_Type($table,$_,'View'),
     	$schema->Field_Length($table,$_,'View'),
     	$schema->Field_Precision($table,$_,'View'),
     	$schema->Field_Scale($table,$_,'View'),
     	(($schema->Field_Null($table,$_,'View')) ? 'NULL' : 'NONNULL')
     	  . "\n";
         } $schema->View_Fields($table);
         print "\tComments:", $schema->Comments($table,'View'), "\n";
     } $schema->Views();

     print "Procedures:\n";
     map {
         $table = $_;
         print "\tProcedure: $table\n";
         map {
     	print "\t\t". $_,
     	$schema->Field_Type($table,$_,'Procedure'),
     	$schema->Field_Length($table,$_,'Procedure'),
     	$schema->Field_Precision($table,$_,'Procedure'),
     	$schema->Field_Scale($table,$_,'Procedure'),
     	(($schema->Field_Null($table,$_,'Procedure')) ? 'NULL' : 'NONNULL')
     	 . "\n";
         } $schema->Procedure_Parameters($table);
         print "\tComments:", $schema->Comments($table,'Procedure'), "\n";
     } $schema->Procedures();

REPORTING BUGS
==============

   When reporting bugs/problems please include as much information as
possible.

   A small script which yields the problem will probably be of help.  If
you cannot include a small script then please include a Debug trace from a
run of your program which does yield the problem.

AUTHOR INFORMATION
==================

   Brian H. Dunford-Shore   brian@ibc.wustl.edu

   Copyright 1998, Washington University School of Medicine, Institute for
Biomedical Computing.  All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Address bug reports and comments to: www@ibc.wustl.edu

TODO
====

   These are features that would be nice to have and might even happen
someday (especially if YOU write it).

Other types of database servers:
     (mSQL, mySQL, etc.).

SEE ALSO
========

   *RDBAL* - http://www.ibc.wustl.edu/perl5/other/RDBAL.html

   *Sybase::DBlib* - http://www.ibc.wustl.edu/perl5/other/sybperl.html

   *Win32::odbc* - http://www.ibc.wustl.edu/perl5/other/Win32/odbc.html

CREDITS
=======

   Thanks very much to:

   *David J. States* (states@ibc.wustl.edu)

     for suggestions and bug fixes.

BUGS
====

   You really mean 'extra' features ;).  None known.

COPYRIGHT
=========

   Copyright (c) 1997, 1998, 1999 Washington University, St. Louis,
Missouri. All rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

This is a set of Perl modules that implement an object-oriented API to manipulate RDF models
********************************************************************************************

NAME
====

   RDFStore - This is a set of Perl modules that implement an
object-oriented API to manipulate RDF models

SYNOPSIS
========

     use RDFStore;

DESCRIPTION
===========

   RDFStore is a set of Perl modules to manage Resource Description
Framework (RDF) model databases in a easy and straightforward way. It is a
pure Perl implementation of the Draft Java API (see
http://www-db.stanford.edu/~melnik/rdf/api.html) from the Stanford
University DataBase Group by Sergey Melnik. Together with its companions
RDFStore::Parser::SiRPAC(3) and Data::MagicTie(3) modules RDFStore suite
allow a user to fetch, parse, process, store and query RDF models.

   Modules like RDFStore::Stanford::RDFNode, RDFStore::Stanford::Literal,
RDFStore::Stanford::Model and so on define a set of "O-O interfaces" to be
implemented by concrete counterparts such as RDFStore::RDFNode,
RDFStore::Model and others. The modules defined by RDFStore correspond to
the Java org.w3c.rdf.model, org.w3c.rdf.util,
org.w3c.rdf.implementation.model, org.w3c.tools.crypt,
edu.stanford.db.rdf.schema, edu.stanford.db.rdf.vocabulary,
org.w3c.rdf.vocabulary.rdf_syntax_19990222,
org.w3c.rdf.vocabulary.rdf_schema_19990303,
org.w3c.rdf.vocabulary.dublin_core_1999070 packages defined by Sergey
Melnik; the Perl code has been structured as follow:

     Perl packages 		   Java classes
     --------------------------------------------------------------
     RDFStore::Stanford::*				org.w3c.rdf.model
     --------------------------------------------------------------
     RDFStore::Stanford::Model			org.w3c.rdf.model.Model
     RDFStore::Stanford::Literal 			org.w3c.rdf.model.Literal
     RDFStore::Stanford::RDFNode 			org.w3c.rdf.model.RDFNode
     RDFStore::Stanford::Resource 			org.w3c.rdf.model.Resource
     RDFStore::Stanford::Statement 			org.w3c.rdf.model.Statement
     RDFStore::Stanford::NodeFactory 		org.w3c.rdf.model.NodeFactory
     RDFStore::Stanford::VirtualModel		org.w3c.rdf.model.VirtualModel
     RDFStore::Stanford::SetModel 			org.w3c.rdf.model.SetModel

   RDFStore::Stanford::Digest::*				org.w3c.rdf.util,org.w3c.tools.crypt
---------------------------------------------------------------------------
RDFStore::Stanford::Digest				org.w3c.rdf.tools.crypt.Digest
RDFStore::Stanford::Digest::Util			org.w3c.rdf.util.DigestUtil
RDFStore::Stanford::Digest::AbstractDigest	org.w3c.rdf.util.DigestUtil
RDFStore::Stanford::Digest::GenericDigest	org.w3c.rdf.util.DigestUtil
RDFStore::Stanford::Digest::MD5			org.w3c.rdf.util.DigestUtil
RDFStore::Stanford::Digest::SHA1			org.w3c.rdf.util.DigestUtil

RDFStore::*				org.w3c.rdf.implementation.model,edu.stanford.db.rdf.schema
--------------------------------------------------------------------------------------------------
RDFStore::Model			org.w3c.rdf.implementation.model.Model
RDFStore::Literal			org.w3c.rdf.implementation.model.Literal
RDFStore::RDFNode			org.w3c.rdf.implementation.model.RDFNode
RDFStore::Resource		org.w3c.rdf.implementation.model.Resource
RDFStore::Statement		org.w3c.rdf.implementation.model.Statement
RDFStore::NodeFactory		org.w3c.rdf.implementation.model.NodeFactory
RDFStore::VirtualModel		org.w3c.rdf.implementation.model.VirtualModel
RDFStore::SetModel		org.w3c.rdf.implementation.model.SetModel
RDFStore::SchemaModel		edu.stanford.db.rdf.schema.RDFSchemaModel

   RDFStore::Stanford::Vocabulary::*				edu.stanford.db.rdf.vocabulary
------------------------------------------------------------------------------------------
RDFStore::Stanford::Vocabulary::Generator		edu.stanford.db.rdf.vocabulary.Generator

RDFStore::Stanford::Vocabulary::RDF			org.w3c.rdf.vocabulary.rdf_syntax_19990222.RDF
RDFStore::Stanford::Vocabulary::RDFS			org.w3c.rdf.vocabulary.rdf_schema_19990303.RDFS
RDFStore::Stanford::Vocabulary::DC				org.w3c.rdf.vocabulary.dublin_core_19990702.DC

   The Perl RDF API implementation is almost aligned with the Java one
(some feauture were left out because for it difficulty or impossibility in
the implementation). E.g. Perl do not have Exceptions as built in
construcut, and altough they could be easily implemented with eval() and
$@ checking, RDFStore just uses the Carp module to warn, croak or confess
on errors. In the RDFStore branch the modules code has been extended and
modified to use the Data::MagicTie(3) interface and a different indexing
mechanism in RDFStore::FindIndex(3). Similarly the
RDFStore::Stanford::Vocabulary::Generator(3) now generates valid Perl5
modules containing constants definitions of input RDF Schema.

   For the whole API documentation you can temporarly refer to the JavaDoc
version at http://www-db.stanford.edu/~melnik/rdf/api-doc/

   In addition I invite you to look at the samples and utils directory
coming with the RDFStore distribution for a fruitful set of examples to
play with :-)

BUGS
====

   This module implements most of the classes and packages as its Java
counterpart from the Stanford University Database Group by Sergey Melnik
(see http://www-db.stanford.edu/~melnik/rdf/api.html), but some feature
have been missied on purposed or just forgotten ;-) This RDFsotre version
is up-to-date with the latest changes from current revision: 2000-12-05 of
Stanford Java API.

   Not supported:

     * NodeFactory::createOrdinal()
     * order/backorder experimental from Sergey Melnik

SEE ALSO
========

   RDFStore::Parser::SiRPAC(3), DBMS(3) and XML::Parser(3)
XML::Parser::Expat(3) RDFStore::Stanford::Model(3) RDFStore::NodeFactory(3)
Summary of Recent Discussions about an Application Programming Interface
for RDF - http://nestroy.wi-inf.uni-essen.de/rdf/sum_rdf_api/

   RDF Model and Syntax Specification - http://www.w3.org/TR/REC-rdf-syntax
RDF Schema Specification 1.0 -
http://www.w3.org/TR/2000/CR-rdf-schema-20000327 Statements/Statings -
http://ilrt.org/discovery/2000/11/statements/

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

     Sergey Melnik <melnik@db.stanford.edu> is the original author of the Java RDF API - txs Sergey!

implementation of the FindIndex RDF API
***************************************

NAME
====

   RDFStore::FindIndex - implementation of the FindIndex RDF API

SYNOPSIS
========

     use RDFStore::FindIndex;
     my $myindex = new RDFStore::FindIndex({});

     use Data::MagicTie;
     tie %index,"Data::MagicTie",'index';
     my $mypresistentindex = new RDFStore::FindIndex(\%index);

DESCRIPTION
===========

   This modules implement a very simple and dirty indexing for
RDFStore::Stanford::Statement(s) using three hashes one indexing by
subject, one by predicate one by object. Each hash contain a copy of the
statement actually containing such a subject, predicate or object. It is
not really efficient due the fact that it requires to keep as value in
hashes a copy of the BLOBed statement - see Data::MagicTie(3)

   An instance of RDFStore::FindIndex can be passed to RDFStore::Model to
help it searching the RDF triplets store.

SEE ALSO
========

   Data::MagicTie(3) RDFStore::Model(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

An implementation of the Literal RDF API
****************************************

NAME
====

   RDFStore::Literal - An implementation of the Literal RDF API

SYNOPSIS
========

     use RDFStore::Literal;
     my $literal = new RDFStore::Literal("Ciao neh!!");

DESCRIPTION
===========

   An RDFStore::Stanford::Literal implementation using Digested URIs.

SEE ALSO
========

   Digest(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

An implementation of the Model RDF API
**************************************

NAME
====

   RDFStore::Model - An implementation of the Model RDF API

SYNOPSIS
========

     use RDFStore::Model;
     use RDFStore::NodeFactory;
     use RDFStore::FindIndex;
     use Data::MagicTie;

     my $factory= new RDFStore::NodeFactory();
     my $statement = $factory->createStatement(
                             	$factory->createResource('http://perl.org'),
                             	$factory->createResource('http://iscool.org/schema/1.0/#label'),
                             	$factory->createLiteral('Cool Web site')
                                     );
     my $statement1 = $factory->createStatement(
     			$factory->createResource("http://www.altavista.com"),
     			$factory->createResource("http://pen.jrc.it/schema/1.0/#author"),
     			$factory->createLiteral("Who? :-)")
     			);

     my $statement2 = $factory->createStatement(
     			$factory->createUniqueResource(),
     			$factory->createUniqueResource(),
     			$factory->createLiteral("")
     			);

     my $index_db={};
     tie %{$index_db},"Data::MagicTie",'index/triples',(Q => 20);
     my $index=new RDFStore::FindIndex($index_db);
     my $model = new RDFStore::Model($factory,undef,$index,undef);

     $model->add($statement);
     $model->add($statement1);
     $model->add($statement2);
     my $model1 = $model->duplicate();

     print $model1->getDigest->equals( $model1->getDigest );
     print $model1->getDigest->hashCode;

     my $found = $model->find($statement2->subject,undef,undef);
     foreach (keys %{$found->elements}) {
             	print $found->elements->{$_}->getLabel(),"\n";
     };

DESCRIPTION
===========

   An RDFStore::Stanford::Model implementation using Digested URIs and
Perl hashes to store triplets. The actual store could be tied to a
Data::MagicTie(3) hash/array and the RDFStore::FindIndex(3) module.

SEE ALSO
========

   Data::MagicTie(3) Digest(3) RDFStore::Stanford::Digest(3)
RDFStore::RDFNode RDFStore::Resource RDFStore::FindIndex(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

implementation of the NodeFactory RDF API
*****************************************

NAME
====

   RDFStore::NodeFactory - implementation of the NodeFactory RDF API

SYNOPSIS
========

     use RDFStore::NodeFactory;
     my $factory = new RDFStore::NodeFactory();
     my $statement = $factory->createStatement(
     			$factory->createResource("http://pen.jrc.it"),
       				$factory->createResource("http://purl.org/schema/1.0#author"),
       				$factory->createLiteral("Alberto Reggiori")
     			);

DESCRIPTION
===========

   An RDFStore::Stanford::NodeFactory implementation using
RDFStore::RDFNode, RDFStore::Resource and RDFStore::Literal

SEE ALSO
========

   RDFStore::RDFNode(3) RDFStore::Resource(3) RDFStore::Literal(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

This module implements an RDF strawman parser for the syntax proposed by Jonathan Borden at http://www.openhealth.org/RDF/rdf_Syntax_and_Names.htm
**************************************************************************************************************************************************

NAME
====

   RDFStore::Parser::OpenHealth - This module implements an RDF strawman
parser for the syntax proposed by Jonathan Borden at
http://www.openhealth.org/RDF/rdf_Syntax_and_Names.htm

SYNOPSIS
========

     use RDFStore::Parser::OpenHealth;
             use RDFStore::NodeFactory;
             my $p=new RDFStore::Parser::OpenHealth(
     	ErrorContext => 2,
                     Handlers        => {
                             Init    => sub { print "INIT\n"; },
                             Final   => sub { print "FINAL\n"; },
                             Assert  => sub { print "STATEMENT - @_\n"; }
                     },
                     NodeFactory     => new RDFStore::NodeFactory() );

     $p->parsefile('http://www.openhealth.org/RDF/mns-fig13-result.xml');
             $p->parsefile('/some/where/my.xml');
             $p->parsefile('file:/some/where/my.xml');
     $p->parse(*STDIN);

     use RDFStore;
     my $pstore=new RDFStore::Parser::OpenHealth(
                     ErrorContext 	=> 2,
                     Style 		=> 'RDFStore::Parser::SiRPAC::RDFStore',
                     NodeFactory     => new RDFStore::NodeFactory(),
                     store   =>      {
                                     	persistent      =>      1,
                                     	directory       =>      '/tmp/',
                                     	seevalues       =>      1,
                                     	options         =>      { style => 'BerkeleyDB', Q => 20 }
                                     }
             );
     $pstore->parsefile('http://www.openhealth.org/RDF/mns-sect7.2-result.xml');

DESCRIPTION
===========

   This module implements a Resource Description Framework (RDF) strawman
parser compliant to the syntax proposed by Jonathan Borden at
http://www.openhealth.org/RDF/rdf_Syntax_and_Names.htm using the XSLT
style sheet at http://www.openhealth.org/RDF/extract/rdfExtractity.xsl.
Such a syntax is yet another extension/refinement of the original syntax
proposed by Dan Connoly at http://www.w3.org/XML/2000/04rdf-parse/rdfp.xsl
and already extended by Jason Diamond's at
http://www.injektilo.org/rdf/rdf.xsl. The parser has been completely
written in Perl using the XML::Parser::Expat(3) module. For the actual
explaination see the RDFStore::Parser::SiRPAC(3) man page.

METHODS
=======

   RDFStore::Parser::OpenHealth supports all the RDFStore::Parser::SiRPAC
options *but* Source. See the manual page for RDFStore::Parser::SiRPAC(3)

BUGS
====

   Although the syntax proposed by Jonathan Borden is quite complete, the
style-sheet is not unfortunately compatible with the Sablotron(3) great
XSLT engine, that does not support 'exclude-result-prefixes' and functions
overriding. A modified version working for Sablotron is available in the
samples directory in the file xml2rdf.xsl.

SEE ALSO
========

   RDFStore::Parser::SiRPAC(3), Sablotron(3) RDFStore::NodeFactory(3)

     Mapping namespace qualified element names to URIs -
     http://www.openhealth.org/RDF/QNameToURI.htm

     Jason Diamond's http://injektilo.org/rdf/examples.html

     Dan Connoly strawman sytax - http://www.w3.org/XML/2000/04rdf-parse/

     TimBL's semantic web toolbox - http://www.w3.org/DesignIssues/Toolbox

     RDF Model and Syntax Specification -
     http://www.w3.org/TR/REC-rdf-syntax

     RDF Schema Specification 1.0 -
     http://www.w3.org/TR/2000/CR-rdf-schema-20000327

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>
     Clark Cooper is the author of the XML::Parser(3) module together with Larry wall

This module implements a streaming RDF Parser as a direct implementation of XML::Parser::Expat(3)
*************************************************************************************************

NAME
====

   RDFStore::Parser::SiRPAC - This module implements a streaming RDF
Parser as a direct implementation of XML::Parser::Expat(3)

SYNOPSIS
========

     use RDFStore::Parser::SiRPAC;
             use RDFStore::NodeFactory;
             my $p=new RDFStore::Parser::SiRPAC(
     	ErrorContext => 2,
                     Handlers        => {
                             Init    => sub { print "INIT\n"; },
                             Final   => sub { print "FINAL\n"; },
                             Assert  => sub { print "STATEMENT - @_\n"; }
                     },
                     NodeFactory     => new RDFStore::NodeFactory() );

     $p->parsefile('http://www.gils.net/bsr-gils.rdfs');
             $p->parsefile('http://www.gils.net/rdf/bsr-gils.rdfs');
             $p->parsefile('/some/where/my.rdf');
             $p->parsefile('file:/some/where/my.rdf');
     $p->parse(*STDIN);

     use RDFStore;
     my $pstore=new RDFStore::Parser::SiRPAC(
                     ErrorContext 	=> 2,
                     Style 		=> 'RDFStore::Parser::SiRPAC::RDFStore',
                     NodeFactory     => new RDFStore::NodeFactory(),
                     Source  	=> 'http://www.gils.net/bsr-gils.rdfs',
                     store   =>      {
                                     	persistent      =>      1,
                                     	directory       =>      '/tmp/',
                                     	seevalues       =>      1,
                                     	options         =>      { style => 'BerkeleyDB', Q => 20 }
                                     }
             );
     $pstore->parsefile('http://www.gils.net/bsr-gils.rdfs');

     #using the Expat no-blocking feature
     my $nbpstore = $pstore->parse_start();
     while (<STDIN>) {
     	$nbpstore->parse_more($_);
     };
     $nbpstore->parse_done();

DESCRIPTION
===========

   This module implements a Resource Description Framework (RDF)
*streaming* parser completely in Perl using the XML::Parser::Expat(3)
module. The actual RDF parsing happens using an instance of
XML::Parser::Expat with Namespaces option enabled and start/stop and char
handlers set.  The RDF specific code is based on the modified version of
SiRPAC of Sergey Melnik in Java; a lot of changes and adaptations have
been done to actually run it under Perl.  Expat options may be provided
when the RDFStore::Parser::SiRPAC object is created. These options are
then passed on to the Expat object on each parse call.

   Exactly like XML::Parser(3) the behavior of the parser is controlled
either by the Style entry elsewhere in this document and/or the Handlers
entry elsewhere in this document options, or by the setHandlers entry
elsewhere in this document method. These all provide mechanisms for
RDFStore::Parser::SiRPAC to set the handlers needed by Expat.  If neither
Style nor Handlers are specified, then parsing just checks the RDF
document syntax against the W3C RDF Raccomandation . When underlying
handlers get called, they receive as their first parameter the Expat
object, not the Parser object.

   To see some examples about how to use it look at the sections below and
in the samples and utils directory coming with this software distribution.

   E.g.  	With RDFStore::Parser::SiRPAC you can easily write an
rdfingest.pl script to do something like this:

     fetch -o - -q http://dmoz.org/rdf/content.rdf.u8.gz | \
     	gunzip - | \
     	sed -f dmoz.content.sed | rdfingest.pl -

METHODS
=======

new
     This is a class method, the constructor for RDFStore::Parser::SiRPAC.
     Options are passed as keyword value pairs. Recognized options are:

        * NodeFactory

          This option is *mandatory* to run the RDFStore::Parser::SiRPAC
          parser correctly and must contain a reference to an object of
          type RDFStore::Stanford::NodeFactory(3). Such a reference is
          used during the RDF parsing to create resources, literal and
          statements to be passed to the registered handlers. A sample
          implementation is RDFStore::NodeFactory that is provided with
          the RDFStore package.

        * Source

          This option can be specified by the user to set a base URI to
          use for the generation of resource URIs during parsing. If this
          option is omitted the parser will try to generate a prefix for
          generated resources using the input filename or URL actually
          containing the input RDF. In a near future such an option could
          be obsoleted by use of XMLBase W3C raccomandation.

        * Style

          This option provides an easy way to set a given style of parser.
          There is one sample Sylte module provided with the
          RDFStore::Parser::SiRPAC distribution called
          RDFStore::Parser::SiRPAC::RDFStore. Such a module uses the
          RDFStore(3) modules together with the Data::MagicTie(3) to
          implement a simple RDF storage.  Custom styles can be provided
          by giving a full package name containing at least one '::'. This
          package should then have subs defined for each handler it wishes
          to have installed. See `"WRITE YOUR OWN PARSER"' in this node
          below for a discussion on how to build one.

        * Handlers

          When provided, this option should be an anonymous hash
          containing as keys the type of handler and as values a sub
          reference to handle that type of event. All the handlers get
          passed as their 1st parameter the instance of Expat that is
          parsing the document. Further details on handlers can be found
          in `"HANDLERS"' in this node. Any handler set here overrides the
          corresponding handler set with the Style option.

        * ErrorContext

          This is an XML::Parser option. When this option is defined,
          errors are reported in context. The value should be the number
          of lines to show on either side of the line in which the error
          occurred.

     All the other XML::Parser and XML::Parser::Expat options should work
     freely with RDFStore::Parser::SiRPAC see XML::Parser(3) and
     XML::Parser::Expat(3).

setHandlers(TYPE, HANDLER [, TYPE, HANDLER [...]])
     This method registers handlers for various parser events. It
     overrides any previous handlers registered through the Style or
     Handler options or through earlier calls to setHandlers. By providing
     a false or undefined value as the handler, the existing handler can
     be unset.

     This method returns a list of type, handler pairs corresponding to the
     input. The handlers returned are the ones that were in effect prior to
     the call.

     See a description of the handler types in `"HANDLERS"' in this node.

parse(SOURCE, URIBASE [, OPT => OPT_VALUE [...]])
     The SOURCE parameter should either be a string containing the whole
     RDF document, or it should be an open IO::Handle.  The URIBASE can be
     specified by the user to set a base URI to use for the generation of
     resource URIs during parsing. If this option is omitted the parser
     will try to generate a prefix for generated resources using either
     the `Source' in this node option of the constructor, the input
     filename or URL actually containing the input RDF. In a near future
     such an option could be obsoleted by use of XMLBase W3C
     raccomandation.  Constructor options to XML::Parser::Expat given as
     keyword-value pairs may follow the URIBASE parameter. These override,
     for this call, any options or attributes passed through from the
     RDFStore::Parser::SiRPAC instance.

     A die call is thrown if a parse error occurs. Otherwise it will
     return 1 or whatever is returned from the Final handler, if one is
     installed.  In other words, what parse may return depends on the
     style.

     e.g. the RDFStore::Parser::SiRPAC::RDFStore Style module returns an
     instance of RDFStore::Stanford::Model

parsestring(STRING, URIBASE [, OPT => OPT_VALUE [...]])
     This is just an alias for parse for backwards compatibility.

parsefile(URL_OR_FILE [, OPT => OPT_VALUE [...]])
     Open URL_OR_FILE for reading, then call parse with the open handle.
     If URL_OR_FILE is a full qualified URL this module uses Socket(3) to
     actually fetch the content.  The URIBASE `parse()' in this node
     parameter is set to URL_OR_FILE.

HANDLERS
========

   As Expat, SiRPAC is an event based parser. As the parser recognizes
parts of the RDF document then any handlers registered for that type of an
event are called with suitable parameters.  All handlers receive an
instance of XML::Parser::Expat as their first argument. See `"METHODS"',
see XML/Parser/Expat, for a discussion of the methods
that can be called on this object.

Init             (Expat)
------------------------

   This is called just before the parsing of the document starts.

Final            (Expat)
------------------------

   This is called just after parsing has finished, but only if no errors
occurred during the parse. Parse returns what this returns.

Assert            (Expat, Statement)
------------------------------------

   This event is generated when a new RDF statement has been generated by
the parseer.start tag is recognized. Statement is of type
RDFStore::Stanford::Statement(3) as generated by the
RDFStore::Stanford::NodeFactory(3) passed as argument to the
RDFStore::Parser::SiRPAC constructor.

Start_XML_Literal            (Expat, Element [, Attr, Val [,...]])
------------------------------------------------------------------

   This event is generated when an XML start tag is recognized within an
RDF property with parseType="Literal". Element is the name of the XML
element type that is opened with the start tag. The Attr & Val pairs are
generated for each attribute in the start tag.

   This handler should return a string containing either the original XML
chunck or one f its transformations, perhaps using XSLT.

Stop_XML_Literal              (Expat, Element)
----------------------------------------------

   This event is generated when an XML end tag is recognized within an RDF
property with parseType="Literal". Note that an XML empty tag (<foo/>)
generates both a Start_XML_Literal and an Stop_XML_Literal event.

Char_XML_Literal             (Expat, String)
--------------------------------------------

   This event is generated when non-markup is recognized within an RDF
property with parseType="Literal". The non-markup sequence of characters
is in String. A single non-markup sequence of encoding of the string in
the original document, this is given to the handler in UTF-8.

   This handler should return the processed text as a string.

WRITE YOUR OWN PARSER
=====================

   Write an extension module for you needs it is as easy as write one for
XML::Parser :) Have a look at
http://www.xml.com/xml/pub/98/09/xml-perl.html and
http://wwwx.netheaven.com/~coopercc/xmlparser/intro.html.

   You can either make you Perl script a parser self by embedding the
needed function hooks or write a custom Style module for
RDFStore::Parser::SiRPAC.

*.pl scripts
------------

     use RDFStore::Parser::SiRPAC;
     use RDFStore::NodeFactory;
     my $p=new RDFStore::Parser::SiRPAC(
     	Handlers        => {
     		Init    => sub { print "INIT\n"; },
     		Final   => sub { print "FINAL\n"; },
     		Assert  => sub { print "STATEMENT - @_\n"; }
     	},
     	NodeFactory     => new RDFStore::NodeFactory() );

   or something like:

     use RDFStore::Parser::SiRPAC;
             use RDFStore::NodeFactory;
     my $p=new RDFStore::Parser::SiRPAC( NodeFactory     => new RDFStore::NodeFactory() );
     $p->setHandlers(        Init    => sub { print "INIT\n"; },
                             	Final   => sub { print "FINAL\n"; },
                             	Assert  => sub { print join(",",@_),"\n"; }     );

Style modules
-------------

   A more sophisticated solution is to write a complete Perl5 Sytle module
for RDFStore::Parser::SiRPAC that can be easily reused in your code. E.g.
a perl script could use this piece of code:

     use RDFStore::Parser::SiRPAC;
     use RDFStore::Parser::SiRPAC::MyStyle;
     use RDFStore::NodeFactory;

     my $p=new RDFStore::Parser::SiRPAC(	Style => 'RDFStore::Parser::SiRPAC::MyStyle',
                     			NodeFactory     => new RDFStore::NodeFactory() );
     $p->parsefile('http://www.gils.net/bsr-gils.rdfs');

   The Style module self could stored into a file like MyStyle.pm like
this:

     package RDFStore::Parser::SiRPAC::MyStyle;

     sub Init { print "INIT\n"; };
     sub Final { print "FINAL\n"; };
     sub Assert {
                     print "ASSERT: ",
                                     $_[1]->subject()->toString(),
                                     $_[1]->predicate()->toString(),
                                     $_[1]->object()->toString(), "\n";
     };
     sub Start_XML_Literal { print "STARTAG: ",$_[1],"\n"; };
     sub Stop_XML_Literal { print "ENDTAG: ",$_[1],"\n"; };
     sub Char_XML_Literal { print "UTF8 chrs: ",$_[1],"\n"; };

     1;

   For a more complete and useful example see
RDFStore::Parser::SiRPAC::RDFStore(3).

BUGS
====

   This module implements most of the W3C RDF Raccomandation as its Java
counterpart SiRPAC from the Stanford University Database Group by Sergey
Melnik (see http://www-db.stanford.edu/~melnik/rdf/api.html) This version
is conformant to the latest RDF API Draft on 2000-11-13. It does not
support yet:

     * aboutEach and aboutEachPrefix

SEE ALSO
========

   RDFStore::Parser::SiRPAC(3), DBMS(3) and XML::Parser(3)
XML::Parser::Expat(3) RDFStore::Stanford::Model(3) RDFStore::NodeFactory(3)

     RDF Model and Syntax Specification - http://www.w3.org/TR/REC-rdf-syntax
     RDF Schema Specification 1.0 - http://www.w3.org/TR/2000/CR-rdf-schema-20000327
     Benchmarking XML Parsers by Clark Cooper - http://www.xml.com/pub/Benchmark/article.html
     See also http://www.w3.org/RDF/Implementations/SiRPAC/SiRPAC-defects.html
     RDF::Parser(3) from http://www.pro-solutions.com

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

     Sergey Melnik <melnik@db.stanford.edu> is the original author of the streaming version of SiRPAC in Java
     Clark Cooper is the author of the XML::Parser(3) module together with Larry Wall

This module is an extension of RDFStore::Parser::SiRPAC(3) that actually use the RDFStore API modules to ingest records into an RDFStore database.
**************************************************************************************************************************************************

NAME
====

   RDFStore::Parser::Styles::MagicTie - This module is an extension of
RDFStore::Parser::SiRPAC(3) that actually use the RDFStore API modules to
ingest records into an RDFStore database.

SYNOPSIS
========

     use RDFStore::Parser::SiRPAC;
     use RDFStore::Parser::Styles::MagicTie;
     use RDFStore::NodeFactory;
     my $p=new RDFStore::Parser::SiRPAC(	ErrorContext => 2,
                                     Style => 'RDFStore::Parser::Styles::MagicTie',
                                     NodeFactory     => new RDFStore::DBMS::NodeFactory()
                                     );

   if(defined $ENV{GATEWAY_INTERFACE}) {         print "Content-type:
text/html

   ";         $p->parsefile($ENV{QUERY_STRING}); } else {         my
$input = shift;         if($input =~ /^-/) {
$p->parse(*STDIN);         } else {                 $p->parsefile($input);
       }; };

DESCRIPTION
===========

   In the samples directory of the distribution you can find a set of a
sample scripts to play with :)

METHODS
=======

new
     This is a class method, the constructor for RDFStore::Parser::SiRPAC.
     Options are passed as key/value pairs.
     RDFStore::Parser::Styles::MagicTie supports all the
     RDFStore::Parser::SiRPAC options plus the following:

        * store

          This option if present must point to an HASH reference.
          Recognized options are:

        * persistent

          This option specify if the RDFStore::Stanford::Statement objects
          generated during parsing must be stored in some kind of
          RDFStore. It is a SCALAR with possible values of 0 or 1.

        * seevalues

          This options is a SCALAR with possible values of 0/1 and flags
          whether the parsing is verbose or not (print triples)

        * directory

          This option specify the output directory where the actual DB
          files are generated when the *persistent* option is set.

        * options

          This option if present must point to an HASH reference and helps
          the user to specify the Data::MagicTie options about storage of
          the RDFStore::Stanford::Statement statements when the
          *persistent* option is set. See Data::MagicTie(3)

BUGS
====

   None known yet

SEE ALSO
========

   RDFStore::Parser::SiRPAC(3), Data::MagicTie(3) RDFStore(3) DBMS(3)

AUTHOR
======

   Alberto Reggiori <alberto.reggiori@jrc.it>

implementation of the RDFNode RDF API
*************************************

NAME
====

   RDFStore::RDFNode - implementation of the RDFNode RDF API

SYNOPSIS
========

     use RDFStore::RDFNode;
     my $node = new RDFStore::RDFNode();

DESCRIPTION
===========

   An RDFStore::Stanford::RDFNode implementation using Digested URIs.

SEE ALSO
========

   RDFStore::Stanford::RDFNode(3) Digest(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

implementation of the Resource RDF API
**************************************

NAME
====

   RDFStore::Resource - implementation of the Resource RDF API

SYNOPSIS
========

     use RDFStore::Resource;
     my $resource = new RDFStore::Resource("http://pen.jrc.it/idex.html");

DESCRIPTION
===========

   An RDFStore::Stanford::Resource implementation using Digested URIs.

SEE ALSO
========

   RDFStore::Stanford::Resource(3) Digest(3) RDFStore::RDFNode(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

implementation of the SchemaModel RDF API
*****************************************

NAME
====

   RDFStore::SchemaModel - implementation of the SchemaModel RDF API

SYNOPSIS
========

     use RDFStore::SchemaModel;
     my $schema_validator = new RDFStore::SchemaModel();
     my $valid = $schema_validator->validateRawSchema($m,$rawSchema);

DESCRIPTION
===========

   This is an incomplete package and it provides basic RDF Schema support
accordingly to the Draft API of Sergey Melnik at
http://www-db.stanford.edu/~melnik/rdf/api.html.  Please use it as a
prototype and/or just to get the idea. It provide basic 'closure' support
and validation of a given RDF instance against an RDF Schema.

SEE ALSO
========

   RDFStore::Model(3) RDFStore::VirtualModel(3) RDF Schema Specification
1.0 - http://www.w3.org/TR/2000/CR-rdf-schema-20000327 DARPA Agent Markup
Language (DAML) - http://www.daml.org/

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

implementation of the SetModel RDF API
**************************************

NAME
====

   RDFStore::SetModel - implementation of the SetModel RDF API

SYNOPSIS
========

     use RDFStore::SetModel;
             use RDFStore::NodeFactory;
             use RDFStore::FindIndex;
             use Data::MagicTie;

     my $factory= new RDFStore::NodeFactory();
     my $index_db={};
     tie %{$index_db},"Data::MagicTie",'index/triples',(Q => 20);
     my $index=new RDFStore::FindIndex($index_db);
     	my $set = new RDFStore::SetModel($factory,undef,$index,undef);

DESCRIPTION
===========

   An RDFStore::Stanford::SetModel implementation using RDFStore::Model
and Digested URIs.

SEE ALSO
========

   RDFStore::Stanford::SetModel(3) RDFStore::Model(3) Digest(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

implementation of the Digest RDF API
************************************

NAME
====

   RDFStore::Stanford::Digest - implementation of the Digest RDF API

SYNOPSIS
========

DESCRIPTION
===========

SEE ALSO
========

   Digest(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

implementation of the AbstractDigest RDF API
********************************************

NAME
====

   RDFStore::Stanford::Digest::Abstract - implementation of the
AbstractDigest RDF API

SYNOPSIS
========

DESCRIPTION
===========

SEE ALSO
========

   Digest(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

implementation of the GenericDigest RDF API
*******************************************

NAME
====

   RDFStore::Stanford::Digest::Generic - implementation of the
GenericDigest RDF API

SYNOPSIS
========

DESCRIPTION
===========

SEE ALSO
========

   Digest(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

implementation of the MD5Digest RDF API
***************************************

NAME
====

   RDFStore::Stanford::Digest::MD5 - implementation of the MD5Digest RDF
API

SYNOPSIS
========

DESCRIPTION
===========

SEE ALSO
========

   Digest(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

implementation of the SHA1Digest RDF API
****************************************

NAME
====

   RDFStore::Stanford::Digest::SHA1 - implementation of the SHA1Digest RDF
API

SYNOPSIS
========

DESCRIPTION
===========

SEE ALSO
========

   Digest(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

implementation of the DigestUtil RDF API
****************************************

NAME
====

   RDFStore::Stanford::Digest::Util - implementation of the DigestUtil RDF
API

SYNOPSIS
========

DESCRIPTION
===========

SEE ALSO
========

   Digest(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

definiton of the Literal RDF API
********************************

NAME
====

   RDFStore::Stanford::Literal - definiton of the Literal RDF API

SYNOPSIS
========

     use RDFStore::Stanford::Literal;
     my $literal = new RDFStore::Stanford::Literal("Ciao neh!!");

DESCRIPTION
===========

   This is just the interface definition. If you are more interested to an
example implementation see RDFStore::Literal(3)

SEE ALSO
========

   RDFStore::Literal(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

definiton of the Model RDF API
******************************

NAME
====

   RDFStore::Stanford::Model - definiton of the Model RDF API

SYNOPSIS
========

     use RDFStore::Stanford::Model;
     use RDFStore::Stanford::Literal;
     use RDFStore::Stanford::Resource;
     use RDFStore::Stanford::Statement;
     my $model = new RDFStore::Stanford::Model();
     my $obj = new RDFStore::Stanford::Literal("foo");
     my $subj = new RDFStore::Stanford::Literal("http://www.foo.com");
     my $pred = new RDFStore::Stanford::Literal("http://rdf.dev.oclc.org/eor/2000/02/26-dcv#","creator");
     my $fact= new RDFStore::Stanford::Statement($subj, $pred, $obj);
     $model->add($fact);
     my $result_model = $model->find($fact);

DESCRIPTION
===========

   This is just the interface definition. If you are more interested to an
example implementation see RDFStore::Model(3)

SEE ALSO
========

   RDFStore::Model(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

definiton of the NodeFactory RDF API
************************************

NAME
====

   RDFStore::Stanford::NodeFactory - definiton of the NodeFactory RDF API

SYNOPSIS
========

     use RDFStore::Stanford::NodeFactory;
     my $factory = new RDFStore::Stanford::NodeFactory();
     my $statement = $factory->createStatement(
     				$factory->createResource("http://pen.jrc.it/idex.html"),
     				$factory->createResource("http://rdf.dev.oclc.org/eor/2000/02/26-dcv#","creator"),
     				$factory->createLiteral("Alberto Reggiori")
     				);

DESCRIPTION
===========

   This is just the interface definition. If you are more interested to an
example implementation see RDFStore::NodeFactory(3)

SEE ALSO
========

   RDFStore::NodeFactory(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

definiton of the RDFNode RDF API
********************************

NAME
====

   RDFStore::Stanford::RDFNode - definiton of the RDFNode RDF API

SYNOPSIS
========

     use RDFStore::Stanford::RDFNode
     my $node = new RDFStore::Stanford::RDFNode();

DESCRIPTION
===========

   This is just the interface definition. If you are more interested to an
example implementation see RDFStore::RDFNode(3)

SEE ALSO
========

   RDFStore::RDFNode(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

definiton of the Resource RDF API
*********************************

NAME
====

   RDFStore::Stanford::Resource - definiton of the Resource RDF API

SYNOPSIS
========

     use RDFStore::Stanford::Resource
     my $resource = new RDFStore::Stanford::Resource("http://pen.jrc.it/index.html");
     my $resource1 = new RDFStore::Stanford::Resource("http://pen.jrc.it","/index.html");

DESCRIPTION
===========

   This is just the interface definition. If you are more interested to an
example implementation see RDFStore::Resource(3)

   An RDF resource. Every RDF resource must have a URI.  Many RDF
resources are pieces of vocabulary. They typically have a namespace and a
local name. In this case, a URI is composed as a concatenation of the
namespace and the local name. For other kinds of identifiers (e.g.
autogenerated UUIDs), the namespace is undef.

SEE ALSO
========

   RDFStore::Resource(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

definiton of the SetModel RDF API
*********************************

NAME
====

   RDFStore::Stanford::SetModel - definiton of the SetModel RDF API

SYNOPSIS
========

     use RDFStore::Stanford::SetModel;
             use RDFStore::Stanford::Literal;
             use RDFStore::Stanford::Resource;
             use RDFStore::Stanford::Statement;
             my $set = new RDFStore::Stanford::Model();
             my $obj = new RDFStore::Stanford::Literal("foo");
             my $subj = new RDFStore::Stanford::Literal("http://www.foo.com");
             my $subj1 = new RDFStore::Stanford::Literal("http://www.bar.com");
             my $pred = new RDFStore::Stanford::Literal("http://rdf.dev.oclc.org/eor/2000/02/26-dcv#","creator");
             my $fact= new RDFStore::Stanford::Statement($subj, $pred, $obj);
             my $fact1= new RDFStore::Stanford::Statement($subj1, $pred, $obj);
             $set->add($fact);
             my $result_model = $set->find($fact);
     $set->subtract($fact1);

DESCRIPTION
===========

   This is just the interface definition. If you are more interested to an
example implementation see RDFStore::SetModel(3)

SEE ALSO
========

   RDFStore::SetModel(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

definiton of the Statement RDF API
**********************************

NAME
====

   RDFStore::Stanford::Statement - definiton of the Statement RDF API

SYNOPSIS
========

     use RDFStore::Stanford::Statement;
     use RDFStore::Stanford::Literal;
     use RDFStore::Stanford::Resource;
     my $statement = new RDFStore::Stanford::Statement(
     				new RDFStore::Stanford::Resource("http://pen.jrc.it/idex.html"),
     				new RDFStore::Stanford::Resource("http://rdf.dev.oclc.org/eor/2000/02/26-dcv#","creator"),
     				new RDFStore::Stanford::Literal("Alberto Reggiori")
     				);

DESCRIPTION
===========

   This is just the interface definition. If you are more interested to an
example implementation see RDFStore::Statement(3)

SEE ALSO
========

   RDFStore::Statement(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

definiton of the VirtualModel RDF API
*************************************

NAME
====

   RDFStore::Stanford::VirtualModel - definiton of the VirtualModel RDF API

SYNOPSIS
========

     use RDFStore::Stanford::VirtualModel;
     my $virtual = new RDFStore::Stanford::VirtualModel();

DESCRIPTION
===========

   This is just the interface definition. If you are more interested to an
example implementation see RDFStore::VirtualModel(3) or
RDFStore::SchemaModel(3)

SEE ALSO
========

   RDFStore::VirtualModel(3) RDFStore::SchemaModel(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

implementation of the Vocabulary Generator RDF API
**************************************************

NAME
====

   RDFStore::Stanford::Vocabulary::Generator - implementation of the
Vocabulary Generator RDF API

SYNOPSIS
========

     use RDFStore::Stanford::Vocabulary::Generator;
     my $generator = new RDFStore::Stanford::Vocabulary::Generator();
     # see vocabulary-generator.pl
     $generator->createVocabulary($packageClass, $all, $namespace, $outputDirectory, $factoryStr);

DESCRIPTION
===========

   Generate Perl packages with constants for resources defined in an RDF
(Schema).

SEE ALSO
========

   RDFStore::Vocabulary::RDF(3) RDFStore::Vocabulary::RDFS(3)
RDFStore::Vocabulary::DC(3) RDFStore::Vocabulary::DAML(3)
RDFStore::SchemaModel(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

implementation of the Statement RDF API from Sergey Melnik (see http://www-db.stanford.edu/~melnik/rdf/api.html)
****************************************************************************************************************

NAME
====

   RDFStore::Statement - implementation of the Statement RDF API from
Sergey Melnik (see http://www-db.stanford.edu/~melnik/rdf/api.html)

SYNOPSIS
========

     use RDFStore::Statement;
     use RDFStore::Literal;
     use RDFStore::Resource;
     my $statement = new RDFStore::Statement(
     				new RDFStore::Resource("http://pen.jrc.it/idex.html"),
     				new RDFStore::Resource("author","http://purl.org/schema/1.0#"),
     				new RDFStore::Literal("Alberto Reggiori")
     				);

DESCRIPTION
===========

   An RDFStore::Stanford::Statement implementation using Digested URIs.

SEE ALSO
========

   RDFStore::Stanford::Statement(3) Digest(3) RDFStore::RDFNode(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

implementation of the VirtualModel RDF API
******************************************

NAME
====

   RDFStore::VirtualModel - implementation of the VirtualModel RDF API

SYNOPSIS
========

     use RDFStore::VirtualModel;
             use RDFStore::NodeFactory;
             use RDFStore::FindIndex;
             use Data::MagicTie;

     my $factory= new RDFStore::NodeFactory();
     my $index_db={};
     tie %{$index_db},"Data::MagicTie",'index/triples',(Q => 20);
     my $index=new RDFStore::FindIndex($index_db);
     my $virtual = new RDFStore::VirtualModel($factory,undef,$index,undef);

DESCRIPTION
===========

   An RDFStore::Stanford::VirtualModel implementation using
RDFStore::Model and Digested URIs.

SEE ALSO
========

   RDFStore::Stanford::VirtualModel(3) RDFStore::Model(3) Digest(3) and
RDFStore::SchemaModel(3)

AUTHOR
======

     Alberto Reggiori <alberto.reggiori@jrc.it>

=head1 SYNOPSIS
***************

NAME  	RDFStore::Vocabulary::DC
===============================

SYNOPSIS
========

     use RDFStore::Vocabulary::DC;
     print $DC::Title->toString;

DESCRIPTION
===========

SEE ALSO
========

AUTHOR
======

   Alberto Reggiori <alberto.reggiori@jrc.it>

=head1 SYNOPSIS
***************

NAME         RDFStore::Vocabulary::RDF
======================================

SYNOPSIS
========

     use RDFStore::Vocabulary::RDF;
     print $RDF::type->toString;

DESCRIPTION
===========

SEE ALSO
========

AUTHOR
======

   Alberto Reggiori <alberto.reggiori@jrc.it>

=head1 SYNOPSIS
***************

NAME         RDFStore::Vocabulary::RDFS
=======================================

SYNOPSIS
========

     use RDFStore::Vocabulary::RDFS;
     print $RDFS::Class->toString;

DESCRIPTION
===========

SEE ALSO
========

AUTHOR
======

   Alberto Reggiori <alberto.reggiori@jrc.it>

RFC 822 style address validation.
*********************************

NAME
====

   RFC::RFC822::Address  -  RFC 822 style address validation.

SYNOPSIS
========

     use RFC::RFC822::Address qw /valid/;

     print "Valid\n" if valid 'abigail@example.com';

DESCRIPTION
===========

   This module checks strings to see whether they are have the valid
syntax, as defined in RFC 822 [1]. One subroutine, valid, can be imported,
which takes a single string as argument. If the string is valid according
to RFC 822, a true value is returned, else a false value is returned.

REFERENCES
==========

[1]
     David H. Crocker (revisor): "STANDARD FOR THE FORMAT OF ARPA INTERNET
     TEXT MESSAGES". RFC 822. 13 August 1982.

CAVEATS and BUGS
================

   This module sets the variable `$Parse::RecDescent::skip'. This will
influence all other Parse::RecDescent parsers. And this parser will break
if you set `$Parse::RecDescent::skip' to another value. It doesn't look
that it is possible to set an alternative skip value for each parser,
other than setting the skip value on each production.

   Example A.1.5 in RFC 822 is wrong. It should use
*"Galloping Gourmet"@ANT.Down-Under*.

   This module should have been named `RFC::822::Address'. However, perl
5.004 doesn't like the `822' part, and at the time of this writing MacPerl
is still at 5.004.

   This module is slow.

REVISION HISTORY
================

     $Log: Address.pm,v $
     Revision 1.5  2000/08/29 22:15:01  abigail
     Changed group rule to make <leftop> part greedy.
       (Damian Conway/Douglas Wilson)
     Added a test; removed $DEBUG part, now prints message on failures.
     Changed wording of license (using BSD/X style).

     Revision 1.4  1999/10/04 09:12:58  abigail
     Fixed typo in pod.

     Revision 1.3  1999/10/04 09:07:23  abigail
     Parsing of comments.
     Completed (?) test suite. Added --debug option to test.pl, to print
        what was being matched, and what the result of validation was.
     Changed package name to RFC::RFC822::Address, to cope for 5.004 users;
        MacPerl is still on 5.004.

     Revision 1.2  1999/10/02 10:08:48  abigail
     Grammar is now aware of the whitespace rules.
     Comment rules still have to be implemented.
     used h2xs.
     Created initial test.pl file.

     Revision 1.1  1999/10/01 08:50:13  abigail
     Initial revision

AUTHOR
======

   This package was written by Abigail, abigail@foad.org.

COPYRIGHT and LICENSE
=====================

   This program is copyright 1999, 2000 by Abigail.

   Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Perl extension for the RIPEMD-160 Hash function
***********************************************

NAME
====

   RIPEMD160 - Perl extension for the RIPEMD-160 Hash function

SYNOPSIS
========

     use RIPEMD160;

     $context = new RIPEMD160;
     $context->reset();

     $context->add(LIST);
     $context->addfile(HANDLE);

     $digest = $context->digest();
     $string = $context->hexdigest();

     $digest = RIPEMD160->hash(SCALAR);
     $string = RIPEMD160->hexhash(SCALAR);

DESCRIPTION
===========

   The *RIPEMD160* module allows you to use the RIPEMD160 Message Digest
algorithm from within Perl programs.

   This is a BETA Version. In the future it will be located in
Crypt::RIPEMD160 and not in RIPEMD160.

   The module is based on the implementation from Antoon Bosselaers from
Katholieke Universiteit Leuven.

   A new RIPEMD160 context object is created with the new operation.
Multiple simultaneous digest contexts can be maintained, if desired.  The
context is updated with the add operation which adds the strings contained
in the LIST parameter. Note, however, that `add('foo', 'bar')',
`add('foo')' followed by `add('bar')' and `add('foobar')' should all give
the same result.

   The final message digest value is returned by the digest operation as a
20-byte binary string. This operation delivers the result of add
operations since the last new or reset operation. Note that the digest
operation is effectively a destructive, read-once operation. Once it has
been performed, the context must be reset before being used to calculate
another digest value.

   Several convenience functions are also provided. The *addfile*
operation takes an open file-handle and reads it until end-of file in 8192
byte blocks adding the contents to the context. The file-handle can either
be specified by name or passed as a type-glob reference, as shown in the
examples below. The *hexdigest* operation calls digest and returns the
result as a printable string of hexdecimal digits. This is exactly the
same operation as performed by the unpack operation in the examples below.

   The hash operation can act as either a static member function (ie you
invoke it on the RIPEMD160 class as in the synopsis above) or as a normal
virtual function. In both cases it performs the complete RIPEMD160 cycle
(reset, add, digest) on the supplied scalar value. This is convenient for
handling small quantities of data. When invoked on the class a temporary
context is created. When invoked through an already created context
object, this context is used. The latter form is slightly more efficient.
The *hexhash* operation is analogous to *hexdigest*.

EXAMPLES
========

     use RIPEMD160;

     $ripemd160 = new RIPEMD160;
     $ripemd160->add('foo', 'bar');
     $ripemd160->add('baz');
     $digest = $ripemd160->digest();

     print("Digest is " . unpack("H*", $digest) . "\n");

   The above example would print out the message

     Digest is f137cb536c05ec2bc97e73327937b6e81d3a4cc9

   provided that the implementation is working correctly.

   Remembering the Perl motto ("There's more than one way to do it"), the
following should all give the same result:

     use RIPEMD160;
     $ripemd160 = new RIPEMD160;

     die "Can't open /etc/passwd ($!)\n" unless open(P, "/etc/passwd");

     seek(P, 0, 0);
     $ripemd160->reset;
     $ripemd160->addfile(P);
     $d = $ripemd160->hexdigest;
     print "addfile (handle name) = $d\n";

     seek(P, 0, 0);
     $ripemd160->reset;
     $ripemd160->addfile(\*P);
     $d = $ripemd160->hexdigest;
     print "addfile (type-glob reference) = $d\n";

     seek(P, 0, 0);
     $ripemd160->reset;
     while (<P>)
     {
         $ripemd160->add($_);
     }
     $d = $ripemd160->hexdigest;
     print "Line at a time = $d\n";

     seek(P, 0, 0);
     $ripemd160->reset;
     $ripemd160->add(<P>);
     $d = $ripemd160->hexdigest;
     print "All lines at once = $d\n";

     seek(P, 0, 0);
     $ripemd160->reset;
     while (read(P, $data, (rand % 128) + 1))
     {
         $ripemd160->add($data);
     }
     $d = $ripemd160->hexdigest;
     print "Random chunks = $d\n";

     seek(P, 0, 0);
     $ripemd160->reset;
     undef $/;
     $data = <P>;
     $d = $ripemd160->hexhash($data);
     print "Single string = $d\n";

     close(P);

NOTE
====

   The RIPEMD160 extension may be redistributed under the same terms as
Perl.  The RIPEMD160 algorithm is published in "Fast Software Encryption,
LNCS 1039, D. Gollmann (Ed.), pp.71-82".

   The basic C code implementing the algorithm is covered by the following
copyright:

   ` /********************************************************************\
*  *      FILE:     rmd160.c  *  *      CONTENTS: A sample
C-implementation of the RIPEMD-160  *                hash-function.   *
 TARGET:   any computer with an ANSI C compiler  *  *      AUTHOR:
Antoon Bosselaers, ESAT-COSIC  *      DATE:     1 March 1996  *
VERSION:  1.0  *  *      Copyright (c) Katholieke Universiteit Leuven  *
  1996, All Rights Reserved  *
\********************************************************************/ '

RIPEMD-160 test suite results (ASCII):
======================================

   ` * message: "" (empty string)   hashcode:
9c1185a5c5e9fc54612808977ee8f548b2258d31 * message: "a"   hashcode:
0bdc9d2d256b3ee9daae347be6f4dc835a467ffe * message: "abc"   hashcode:
8eb208f7e05d987a9b044a8e98c6b087f15a0bfc * message: "message digest"
hashcode: 5d0689ef49d2fae572b881b123a85ffa21595f36 * message:
"abcdefghijklmnopqrstuvwxyz"   hashcode:
f71c27109c692c1b56bbdceb5b9d2865b3708dbc * message:
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"   hashcode:
12a053384a9c0c88e405a06c27dcf49ada62eb2b * message: "A...Za...z0...9"
hashcode: b0e20b6e3116640286ed3a87a5713079b21f5189 * message: 8 times
"1234567890"   hashcode: 9b752e45573d4b39f4dbd3323cab82bf63326bfb *
message: 1 million times "a"   hashcode:
52783243c1697bdbe16d37f97f68f08325dc1528 '

   This copyright does not prohibit distribution of any version of Perl
containing this extension under the terms of the GNU or Artistic licences.

AUTHOR
======

   The RIPEMD-160 interface was written by Christian H. Geuer
(`christian.geuer@crypto.gun.de').

SEE ALSO
========

   MD5(3pm) and SHA(1).

Perl extension for RIPEMD-160 MAC function
******************************************

NAME
====

   RIPEMD160::MAC - Perl extension for RIPEMD-160 MAC function

SYNOPSIS
========

     use RIPEMD160::MAC;

     $key = "This is the secret key";

     $mac = new RIPEMD160::MAC($key);

     $mac->reset();

     $mac->add(LIST);
     $mac->addfile(HANDLE);

     $digest = $mac->mac();
     $string = $mac->hexmac();

DESCRIPTION
===========

   The *RIPEMD160* module allows you to use the RIPEMD160 Message Digest
algorithm from within Perl programs.

EXAMPLES
========

     use RIPEMD160;

     $ripemd160 = new RIPEMD160;
     $ripemd160->add('foo', 'bar');
     $ripemd160->add('baz');
     $digest = $ripemd160->digest();

     print("Digest is " . unpack("H*", $digest) . "\n");

   The above example would print out the message

     Digest is f137cb536c05ec2bc97e73327937b6e81d3a4cc9

   provided that the implementation is working correctly.

AUTHOR
======

   The RIPEMD-160 interface was written by Christian H. Geuer
(`christian.geuer@crypto.gun.de').

SEE ALSO
========

   MD5(3pm) and SHA(1).

Perl interface to ONC RPC
*************************

NAME
====

   RPC::ONC - Perl interface to ONC RPC

SYNOPSIS
========

     use RPC::ONC;

     # Create a client of the NFS service.

     $clnt = &RPC::ONC::Client::clnt_create('foo.bar.com',
     				      NFS_PROGRAM, NFS_VERSION,
     				      'netpath');

     # Set the timeout to 3 seconds.
     $clnt->clnt_control(CLSET_TIMEOUT, pack('LL', 3, 0));

DESCRIPTION
===========

   The RPC::ONC module provides access to some of the ONC RPC routines for
making and receiving remote procedure calls, as well as functions to
access members of RPC-related structures. It's intended to be used with
'perlrpcgen', which generates Perl XS stubs for RPC clients and servers.

   Most of these routines work the same as their C equivalents and are
thus not described in detail.

CAVEAT
======

   Not all of the ONC RPC calls are provided in this alpha version-I've
been filling them in more or less as needed. Let me know if there's one
you really need.

GLOBALS
=======

RPC::ONC::errno
     Number of the error that just occurred.

RPC::ONC::errstr
     Message corresponding to error that just occurred.

CLASSES
=======

RPC::ONC::Client
----------------

   RPC::ONC::Client wraps CLIENT *.

clnt_create(host, prognum, versnum, nettype)
     If the call fails, clnt_create will set RPC::ONC::errno and
     RPC::ONC::errstr and croak.

clnt_control(clnt, req, info)
     The info argument should be packed as an appropriate structure for the
     operation.

clnt_destroy(clnt)
set_cl_auth(clnt, auth)
     Takes an RPC::ONC::Client object and an RPC::ONC::Auth object and
     assigns the cl_auth field of the first to the second.

RPC::ONC::Auth
--------------

   RPC::ONC::Auth wraps AUTH *.

authnone_create
authsys_create_default
auth_destroy(auth)
RPC::ONC::svc_req
-----------------

   RPC::ONC::svc_req wraps struct svc_req *.

rq_prog(svc_req)
     Returns the rq_prog field.

rq_vers(svc_req)
     Returns the rq_vers field.

rq_proc(svc_req)
     Returns the rq_proc field.

rq_cred(svc_req)
     Returns the rq_cred field as an RPC::ONC::opaque_auth object.

authsys_parms(svc_req)
     Returns the rq_clntcred field as an RPC::ONC::authsys_parms object.
     Will croak if the credentials are not the right flavor.

authdes_cred(svc_req)
     Returns the rq_clntcred field as an RPC::ONC::authdes_cred object.
     Will croak if the credentials are not the right flavor.

RPC::ONC::opaque_auth
---------------------

oa_flavor(opaque_auth)
     Returns the oa_flavor field.

RPC::ONC::authsys_parms
-----------------------

aup_time(authsys_parms)
     Returns the aup_time field.

aup_machname(authsys_parms)
     Returns the aup_machname field.

aup_uid(authsys_parms)
     Returns the aup_uid field.

aup_gid(authsys_parms)
     Returns the aup_gid field.

aup_gids(authsys_parms)
     Returns the aup_gids field as an array.

RPC::ONC::Svcxprt
-----------------

   RPC::ONC::Svcxprt wraps struct svcxprt *.

svc_getcaller(transp)
     Returns a sockaddr_in * which you can unpack to get the IP address of
     the caller.

SEE ALSO
========

   `perlrpcgen(1)' in this node

AUTHOR
======

   Jake Donham <jake@organic.com>

THANKS
======

   Thanks to Organic Online <http://www.organic.com/> for letting me hack
at work.

Perl extension for writing PlRPC clients
****************************************

NAME
====

   RPC::PlClient - Perl extension for writing PlRPC clients

SYNOPSIS
========

     require RPC::PlClient;

     # Create a client object and connect it to the server
     my $client = RPC::PlClient->new('peeraddr' => 'joes.host.de',
     				  'peerport' => 2570,
     				  'application' => 'My App',
     				  'version' => '1.0',
     				  'user' => 'joe',
     				  'password' => 'hello!');

     # Create an instance of $class on the server by calling $class->new()
     # and an associated instance on the client.
     my $object = $client->Call('NewHandle', $class, 'new', @args);

     # Call a method on $object, effectively calling the same method
     # on the associated server instance.
     my $result = $object->do_method(@args);

DESCRIPTION
===========

   PlRPC (Perl RPC) is a package that simplifies the writing of Perl based
client/server applications. RPC::PlServer is the package used on the
server side, and you guess what RPC::PlClient is for. See
`RPC::PlServer(3)' in this node for this part.

   PlRPC works by defining a set of methods that may be executed by the
client.  For example, the server might offer a method "multiply" to the
client. Now a function call

     @result = $client->Call('multiply', $a, $b);

   on the client will be mapped to a corresponding call

     $server->multiply($a, $b);

   on the server. The function calls result will be transferred to the
client and returned as result of the clients method. Simple, eh? :-)

Client methods
--------------

$client = new(%attr);
     (Class method) The client constructor. Returns a client object,
     connected to the server. A Perl exception is thrown in case of
     errors, thus you typically use it like this:

          $client = eval { RPC::PlClient->new ( ... ) };
          if ($@) {
          	print STDERR "Cannot create client object: $@\n";
          	exit 0;
          }

     The method accepts a list of key/value pairs as arguments. Known
     arguments are:

    peeraddr
    peerport
    socket_proto
    socket_type
    timeout
          These correspond to the attributes *PeerAddr*, *PeerPort*, Proto,
          Type and Timeout of IO::Socket::INET. The server connection will
          be established by passing them to IO::Socket::INET->new().

    socket
          After a connection was established, the IO::Socket instance will
          be stored in this attribute. If you prefer establishing the
          connection on your own, you may as well create an own instance
          of IO::Socket and pass it as attribute socket to the new method.
          The above attributes will be ignored in that case.

    application
    version
    user
    password
          it is part of the PlRPC authorization process, that the client
          must obeye a login procedure where he will pass an application
          name, a protocol version and optionally a user name and password.
          These arguments are handled by the servers Application, Version
          and User methods.

    compression
          Set this to off (default, no compression) or gzip (requires the
          Compress::Zlib module).

    cipher
          This attribute can be used to add encryption quite easily. PlRPC
          is not bound to a certain encryption method, but to a block
          encryption API. The attribute is an object supporting the
          methods blocksize, encrypt and decrypt. For example, the modules
          Crypt::DES and Crypt::IDEA support such an interface.

          Note that you can set or remove encryption on the fly (putting
          undef as attribute value will stop encryption), but you have to
          be sure, that both sides change the encryption mode.

          Example:

               use Crypt::DES;
               $cipher = Crypt::DES->new(pack("H*", "0123456789abcdef"));
               $client = RPC::PlClient->new('cipher' => $cipher,
               				...);

    maxmessage
          The size of messages exchanged between client and server is
          restricted, in order to omit denial of service attacks. By
          default the limit is 65536 bytes.

    debug
          Enhances logging level by emitting debugging messages.

    logfile
          By default the client is logging to syslog (Unix) or the event
          log (Windows).  If neither is available or you pass a TRUE value
          as logfile, then logging will happen to the given file handle,
          an instance of IO::Handle. If the value is scalar, then logging
          will occur to stderr.

          Examples:

               # Logging to stderr:
               my $client = RPC::PlClient->new('logfile' => 1, ...);

               # Logging to 'my.log':
               my $file = IO::File->new('my.log', 'a')
                   || die "Cannot create log file 'my.log': $!";
               my $client = RPC::PlClient->new('logfile' => $file, ...);

@result = $client->Call($method, @args);
     (Instance method) Calls a method on the server; the arguments are a
     method name of the server class and the method call arguments. It
     returns the method results, if successfull, otherwise a Perl
     exception is thrown.

     Example:

          @results = eval { $client->Call($method, @args };
          if ($@) {
              print STDERR "An error occurred while executing $method: $@\n";
              exit 0;
          }

$cobj = $client->ClientObject($class, $method, @args)
     (Instance method) A set of predefined methods is available that make
     dealing with client side objects incredibly easy: In short the client
     creates a representation of the server object for you. Say we have an
     object $sobj on the server and an associated object $cobj on the
     client: Then a call

          @results = $cobj->my_method(@args);

     will be immediately mapped to a call

          @results = $sobj->my_method(@args);

     on the server and the results returned to you without any additional
     programming. Here's how you create $cobj, an instance of
     *RPC::PlClient::Object*:

          my $cobj = $client->ClientObject($class, 'new', @args);

     This will trigger a call

          my $sobj = $class->new(@args);

     on the server for you. Note that the server has the ability to
     restrict access to both certain classes and methods by setting
     $server->{'methods'} appropriately.

EXAMPLE
=======

   We'll create a simple example application, an MD5 client. The server
will have installed the MD5 module and create digests for us. We present
the client part only, the server example is part of the RPC::PlServer man
page. See `RPC::PlServer(3)' in this node.

     #!/usr/local/bin/perl

     use strict;               # Always a good choice.

     require RPC::PlClient;

     # Constants
     my $MY_APPLICATION = "MD5_Server";
     my $MY_VERSION = 1.0;
     my $MY_USER = "";		# The server doesn't require user
     my $MY_PASSWORD = "";	# authentication.

     my $hexdigest = eval {
         RPC::PlClient->new('peeraddr'    => 'joes.host.de',
     			   'peerport'    => 5000,
     			   'application' => $MY_APPLICATION,
     			   'version'     => $MY_VERSION,
     			   'user'        => $MY_USER,
     			   'password'    => $MY_PASSWORD);

     # Create an MD5 object on the server and an associated
     # client object. Executes a
     #     $context = MD5->new()
     # on the server.
     my $context = $client->ClientObject('MD5', 'new');

     # Let the server calculate a digest for us. Executes a
     #     $context->add("This is a silly string!");
     #     $context->hexdigest();
     # on the server.
     	$context->add("This is a silly string!");
     	$context->hexdigest();
         };
         if ($@) {
     die "An error occurred: $@";
         }

     print "Got digest $hexdigest\n";

AUTHOR AND COPYRIGHT
====================

   The PlRPC-modules are

     Copyright (C) 1998, Jochen Wiedmann
                         Am Eisteich 9
                         72555 Metzingen
                         Germany

     Phone: +49 7123 14887
     Email: joe@ispsoft.de

     All rights reserved.

   You may distribute this package under the terms of either the GNU
General Public License or the Artistic License, as specified in the Perl
README file.

SEE ALSO
========

   `PlRPC::Server(3)' in this node, `Net::Daemon(3)' in this node,
`Storable(3)' in this node, `Sys::Syslog(3)' in this node, see
Win32/EventLog,

   An example application is the DBI Proxy client:

   `DBD::Proxy(3)' in this node.

Perl extension for writing PlRPC servers
****************************************

NAME
====

   RPC::PlServer - Perl extension for writing PlRPC servers

SYNOPSIS
========

     # Create a subclass of RPC::PlServer
     use RPC::PlServer;

     package MyServer;
     $MyServer::VERSION = '0.01';
     @MyServer::ISA = qw(RPC::PlServer);

     # Overwrite the Run() method to handle a single connection
     sub Run {
         my $self = shift;
         my $socket = $self->{'socket'};
     }

     # Create an instance of the MyServer class
     package main;
     my $server = MyServer->new({'localport' => '1234'}, \@ARGV);

     # Bind the server to its port to make it actually running
     $server->Bind();

DESCRIPTION
===========

   PlRPC (Perl RPC) is a package for implementing servers and clients that
are written in Perl entirely. The name is borrowed from Sun's RPC (Remote
Procedure Call), but it could as well be RMI like Java's "Remote Method
Interface), because PlRPC gives you the complete power of Perl's OO
framework in a very simple manner.

   RPC::PlServer is the package used on the server side, and you guess what
RPC::PlClient is for. Both share the package RPC::PlServer::Comm for
communication purposes. See `PlRPC::Client(3)' in this node and
`RPC::PlServer::Comm' in this node for these parts.

   PlRPC works by defining a set of methods that may be executed by the
client.  For example, the server might offer a method "multiply" to the
client. Now the clients method call

     @result = $client->multiply($a, $b);

   will be immediately mapped to a method call

     @result = $server->multiply($a, $b);

   on the server. The arguments and results will be transferred to or from
the server automagically. (This magic has a name in Perl: It's the
Storable module, my thanks to Raphael Manfredi for this excellent
package.) Simple, eh? :-)

   The RPC::PlServer and RPC::PlClient are abstract servers and clients:
You have to derive your own classes from it.

Additional options
------------------

   The RPC::PlServer inherits all of Net::Daemon's options and attributes
and adds the following:

cipher
     The attribute value is an instance of Crypt::DES, Crypt::IDEA or any
     other class with the same API for block encryption. If you supply
     such an attribute, the traffic between client and server will be
     encrypted using this option.

maxmessage (*-maxmessage=size*)
     The size of messages exchanged between client and server is
     restricted, in order to omit denial of service attacks. By default
     the limit is 65536 bytes.

users
     This is an attribute of the client object used for Permit/Deny rules
     in the config file. It's value is an array ref of user names that are
     allowed to connect from the given client. See the example config file
     below. `CONFIGURATION FILE' in this node.

Error Handling
--------------

   Error handling is simple with the RPC package, because it is based on
Perl exceptions completely. Thus your typical code looks like this:

     eval {
         # Do something here. Don't care for errors.
         ...
     };
     if ($@) {
         # An error occurred.
         ...
     }

Server Constructors
-------------------

     my $server = RPC::PlServer(\%options, \@args);

   (Class method) This constructor is immediately inherited from the
Net::Daemon package. See `Net::Daemon(3)' in this node for details.

Access Control
--------------

     $ok = $self->AcceptApplication($app);
     $ok = $self->AcceptVersion($version);
     $ok = $self->AcceptUser($user, $password);

   The RPC::PlServer package has a very detailed access control scheme:
First of all it inherits Net::Daemon's host based access control. It adds
version control and user authorization. To achieve that, the method Accept
from Net::Daemon is split into three methods, *AcceptApplication*,
*AcceptVersion* and *AcceptUser*, each of them returning TRUE or FALSE.
The client receives the arguments as the attributes application, version,
user and password. A client is accepted only if all of the above methods
are returning TRUE.

   The default implementations are as follows: The AcceptApplication method
returns TRUE, if *$self* is a subclass of *$app*. The AcceptVersion method
returns TRUE, if the requested version is less or equal to
*${$class}::VERSION*, $self being an instance of $class. Whether a user is
permitted to connect depends on the client configuration. See
`CONFIGURATION FILE' in this node below for examples.

Method based access control
---------------------------

   Giving a client the ability to invoke arbitrary methods can be a
terrible security hole. Thus the server has a methods attribute. This is a
hash ref of class names as keys, the values being hash refs again with
method names as the keys. That is, if your hash looks as follows:

     $self->{'methods'} = {
         'CalcServer' => {
             'NewHandle' => 1,
             'CallMethod' => 1 },
         'Calculator' => {
             'new' => 1,
             'multiply' => 1,
             'add' => 1,
             'divide' => 1,
             'subtract' => 1 }
         };

   then the client may use the CalcServer's NewHandle method to create
objects, but only via the permitted constructor Calculator->new. Once a
Calculator object is created, the server may invoke the methods multiply,
add, divide and subtract.

CONFIGURATION FILE
==================

   The server config file is inherited from Net::Daemon. It adds the users
and cipher attribute to the client list. Thus a typical config file might
look as follows:

     # Load external modules; this is not required unless you use
     # the chroot() option.
     #require DBD::mysql;
     #require DBD::CSV;

     # Create keys
     my $myhost_key = Crypt::IDEA->new('83fbd23390ade239');
     my $bob_key    = Crypt::IDEA->new('be39893df23f98a2');

     {
         # 'chroot' => '/var/dbiproxy',
         'facility' => 'daemon',
         'pidfile' => '/var/dbiproxy/dbiproxy.pid',
         'user' => 'nobody',
         'group' => 'nobody',
         'localport' => '1003',
         'mode' => 'fork',

     # Access control
     'clients' => [
         # Accept the local LAN (192.168.1.*)
         {
             'mask' => '^192\.168\.1\.\d+$',
             'accept' => 1,
             'users' => [ 'bob', 'jim' ],
             'cipher' => $myhost_key
         },
         # Accept myhost.company.com
         {
             'mask' => '^myhost\.company\.com$',
             'accept' => 1,
             'users' => [ {
                 'name' => 'bob',
                 'cipher' => $bob_key
                 } ]
         },
         # Deny everything else
         {
             'mask' => '.*',
             'accept' => 0
         }
     ]
         }

   Things you should note: The user list of 192.168.1.* contains scalar
values, but the user list of myhost.company.com contains hash refs: This
is required, because the user configuration is more specific for user
based encryption.

EXAMPLE
=======

   Enough wasted time, spread the example, not the word. :-) Let's write a
simple server, say a server for MD5 digests. The server uses the external
package MD5, but the client doesn't need to install the package. `MD5(3)'
in this node. We present the server source here, the client is part of the
RPC::PlClient man page. See `RPC::PlClient(3)' in this node.

     #!/usr/bin/perl -wT
     # Note the -T switch! This is always recommended for Perl servers.

     use strict;               # Always a good choice.

     require RPC::PlServer;
     require MD5;

     package MD5_Server;  # Clients need to request application
                          # "MD5_Server"

     $MD5_Server::VERSION = '1.0'; # Clients will be refused, if they
                                   # request version 1.1
     @MD5_Server::ISA = qw(RPC::PlServer);

     eval {
         # Server options below can be overwritten in the config file or
         # on the command line.
         my $server = MD5_Server->new({
     	    'pidfile'    => '/var/run/md5serv.pid',
     	    'configfile' => '/etc/md5serv.conf',
     	    'facility'   => 'daemon', # Default
     	    'user'       => 'nobody',
     	    'group'      => 'nobody',
     	    'localport'  => 2000,
     	    'logfile'    => 0,        # Use syslog
             'mode'       => 'fork',   # Recommended for Unix
             'methods'    => {
     	        'MD5_Server' => {
     		    'ClientObject' => 1,
     		    'CallMethod' => 1,
     		    'NewHandle' => 1
     		    },
     	        'MD5' => {
     		    'new' => 1,
     		    'add' => 1,
     		    'hexdigest' => 1
     		    },
     	        }
         });
         $server->Bind();
     };

SECURITY
========

   It has to be said: PlRPC based servers are a potential security problem!
I did my best to avoid security problems, but it is more than likely, that
I missed something. Security was a design goal, but not *the* design goal.
(A well known problem ...)

   I highly recommend the following design principles:

Protection against "trusted" users
----------------------------------

perlsec
     Read the perl security FAQ (`perldoc perlsec') and use the -T switch.

taintperl
     Use the -T switch. I mean it!

Verify data
     Never untaint strings withouth verification, better verify twice.
     For example the CallMethod function first checks, whether an object
     handle is valid before coercing a method on it.

Be restrictive
     Think twice, before you give a client access to a method.

perlsec
     And just in case I forgot it: Read the perlsec man page. :-)

Protection against untrusted users
----------------------------------

Host based authorization
     PlRPC has a builtin host based authorization scheme; use it!  See `'
     in this node.

User based authorization
     PlRPC has a builtin user based authorization scheme; use it!  See `'
     in this node.

Encryption
     Using encryption with PlRPC is extremely easy. There is absolutely no
     reason for communicating unencrypted with the clients. Even more: I
     recommend two phase encryption: The first phase is the login phase,
     where to use a host based key. As soon as the user has authorized,
     you should switch to a user based key. See the DBI::ProxyServer for
     an example.

AUTHOR AND COPYRIGHT
====================

   The PlRPC-modules are

     Copyright (C) 1998, Jochen Wiedmann
                         Am Eisteich 9
                         72555 Metzingen
                         Germany

     Phone: +49 7123 14887
     Email: joe@ispsoft.de

     All rights reserved.

   You may distribute this package under the terms of either the GNU
General Public License or the Artistic License, as specified in the Perl
README file.

SEE ALSO
========

   `RPC::PlClient(3)' in this node, `RPC::PlServer::Comm(3)' in this node,
`Net::Daemon(3)' in this node, `Net::Daemon::Log(3)' in this node,
`Storable(3)' in this node, `Sys::Syslog(3)' in this node,
`Win32::EventLog(3)' in this node

   See `DBI::ProxyServer(3)' in this node for an example application.

Perl classes to handle SRPC calls with call-back
************************************************

NAME
====

   RPC::Simple - Perl classes to handle SRPC calls with call-back

SYNOPSIS
========

     use RPC::Simple;

     #see test.pl file

DESCRIPTION
===========

   Dummy class which loads RPC::Simple::AnyLocal and
RPC::Simple::AnyRemote ;

   This module deals with remote procedure call. I've tried to keep things
simple.

   So this module should be :  - quite simple to use (thanks to autoload
mechanisms)  - lightweight

   It sure is not :  - DCE  - CORBA  - bulletproof  - securityproof  -
foolproof

   But it works. (Although I'm opened to suggestion regarging the
"un-proof" areas)

   The module is made of the following sub-classes :

     RPC::Simple::Agent - Perl extension for an agent object
     RPC::Simple::AnyLocal - Perl extension defining a virtual RPC client class

     RPC::Simple::AnyRemote - Perl base class for a remote object
     RPC::Simple::CallHandler - Perl class to handle RPC::Simple calls with call-back
     RPC::Simple::Factory - Perl extension for creating client
     RPC::Simple::ObjectHandler - Perl class to handle a remote object
     RPC::Simple::Server - Perl class to use in the RPC::Simple server script.
     RPC::Simple::AnyWhere - Common parts for AnyLocal and AnyRemote

   Anyway, the casual user should worry only about inheriting the
RPC::Simple::AnyLocal class and creating a RPC::Simple::Factory on the
local side.

   On the remote side, the user will only have to inherit
RPC::Simple::AnyRemote and run the mainLoop method of RPC::Simple::Server.

   In each side you must declare all methods available on the other side
in a global array of your class.

   How it works ? The user (i.e. you) must write a local class which
inherit from AnyLocal. AnyLocal is designed to handle Agent and Factory.

     AnyLocal --1---<>---1-- Agent --*--<>---Factory----<>--LAN
         |
        /\____
             |
             |
         LocalClass

   First, the user script will have to :  - instantiate one Factory.   -
Create its instance of LocalClass  - LocalClass::new will call
$self->createRemote, this will create the Agent class.

     - Now any call to an undefined method (BUT declared in @RPC_SUB)
     of LocalClass will be forwarded to the Remote class.
     If this call has a code reference as first parameter, Agent
     will call this code when the remote call is over. I.e. all remote
     procedure call must be designed in asynchronous mode.

   Note that undefined method not declared in @RPC_SUB will be autoloaded
(or at least, I'll try to autoload them).

   Note that Factory and Agent actually use Tk to manage the socket
connection.

   On the remote side, the user will write its RemoteClass which will
inherit from AnyRemote.

     LAN --1--<>--*-- Server --1--<>--*--ObjectHandler--1--<>--*--CallHandler
                                               |                        |
                                               1                        *
                                               |                        |
                                               --<>--1--AnyRemote--1-<>--
                                                            |
                                                           /\____
                                                                |
                                                                |
                                                           RemoteClass

   RemoteClass will be called with the method name that was invoked for
LocalClass. RemtoeClass may call a function from local class using the
same mechanism but it may NOT expect a call-back from this call to the
local side.

   Note that the remote class may call directly method from the Local
class.  (Provided the local method is declared in the @RPC_SUB array of
the remote class)

   Note that the instance variable of the local class or remote class are
not shared or updated or replicated magically. If you must pass data from
one side to the other, you have to do it explicitely. In most case you'll
pass the variable value as a method parameter.

CAVEATS
=======

   Well, this stuff is supposed to be pretty simple, the code to handle the
RPC and callback is not much complicated, but I sure have a lot of problem
to write a doc which make using this module simple. Future version may get
better depending on your comments or questions.

AUTHOR
======

   Dominique_Dumont@grenoble.hp.com

SEE ALSO
========

   perl(1), RPC::Simple::AnyLocal(3), RPC::Simple::AnyRemote(3) .

Perl extension for an agent object for RPC
******************************************

NAME
====

   RPC::Simple::Agent - Perl extension for an agent object for RPC

SYNOPSIS
========

     use RPC::Simple::Agent ;

DESCRIPTION
===========

   This class is an agent for client class inheriting PRC::AnyLocal. This
class will handle all the boring stuff to create, access store call-back
when dealing with the remote object.

   Casual user should not worry about this class. RPC::Simple::AnyLocal
will deal with it.

Methods
=======

new( $factory_ref, client_ref, index, remote_class, ... .)
----------------------------------------------------------

   Create the agent.

   factory_ref is the SPRC::Factory object.

   client_ref is the client object itself.

   index is an index handled by the Factory.

   remote_class if the name of the class created on the remote side. By
default, it is set to the client's class name with a 'Real' prepended to
the name.

   I.e if the client is Foo::Bar, the remote will be Foo::RealBar.

   The remaining parameters will forwarded to the constructor of the remote
class.

getRemoteHostName
-----------------

   returns the remote host name

delegate( method_name , [code_ref ],                 parameters ,... )
----------------------------------------------------------------------

   Call a method of the remote object. If code_ref is specified, the code
will be executed with whatever parameters the remote functions passed in
its reply.

   The remaining optionnal parameters are passed as is to the remote
method.

   Note that ref are copied. You can't expect the remote to be able to
modify a client's variable because you passed it's ref to the remote.

callMethod( method_name, argument_array_ref )
---------------------------------------------

   Function used to call the owner of the agent. All arguments of the
function to be called back are passed in the array ref.

CALLBACKS
=========

remoteCreated(result, string)
-----------------------------

   Called when the remote object is created. 'result' will be true or false
depending on whether the remote object was created or not.

   'string' contains the error message in case of a failure.

treatCallBack ( request_id, argument_array_ref)
-----------------------------------------------

   Function used to call-back the owner of the agent. All arguments of the
function to be called back are passed in the array ref.

   'request_id' is used to know what object and methos are to be called
back.  These info were stored by the delegate function.

AUTHOR
======

   Dominique_Dumont@grenoble.hp.com

SEE ALSO
========

   perl(1), RPC::Simple::AnyLocal(3).

Perl extension defining a virtual SRPC client class
***************************************************

NAME
====

   RPC::Simple::AnyLocal - Perl extension defining a virtual SRPC client
class

SYNOPSIS
========

     package MyLocal ;

     use RPC::Simple::AnyLocal;
     use vars qw($VERSION @ISA @RPC_SUB) ;
     @ISA = qw(RPC::Simple::AnyLocal [other_class] );
     @RPC_SUB = qw(remoteHello remoteAsk);

     sub new
      {
        my $type = shift ;

     my $self = {} ;
     my $remote =  shift ;
     bless $self,$type ;

     $self->createRemote($remote,'your_class_name') ;
     return $self ;
       }

     # Note that the 'remoteHello' method is not part of MyLocal

     package main;

     use Tk ;
     use RPC::Simple::Server ;
     use RPC::Simple::Factory ;

     my $pid = &spawn ; # spawn server if needed

     # client part
     my $mw = MainWindow-> new ;
     my $verbose = 1 ;

     # create factory
     my $factory = new RPC::Simple::Factory($mw,\$verbose) ;
     my $local = new MyLocal($factory) ;
     $mw -> Button (text => 'quit', command => sub {exit;} ) -> pack ;
     $mw -> Button (text => 'remoteAct',
       command => sub {$local->remoteHello();} ) -> pack ;

     MainLoop ; # Tk's

DESCRIPTION
===========

   This class must be inherited by a sub-class so this one can use the RPC
facility.

   Note that this class (and the Factory class) was designed to use Tk's
fileevent facilities.

   The child object must declare in the @RPC_SUB array the name of the
methods available on the remote side.

Methods
=======

createRemote(factory_object_ref, [remote_class_name], ... )
-----------------------------------------------------------

   This method should be called by the child object during start-up. It
will ask the SRPC factory to create a ClientAgent class dedicated to this
new object.

   The server on the other side of the socket will load the code necessary
for the remote class. By default the remote class name will be
...::Real<LocalClass>. I.e if your local class is Test::Foo the remote
class name will be Test::RealFoo.

   If the remote class name has no prefix, '.pm' will be appended to get
the file name to load

   The remaining parameters will passed to the remote object's new method
during its creation.

   returns self.

destroy()
---------

   Objects derived from AnyLocal must be explicitely destroy. If you just
undef the object reference, you will not release the memory and the remote
object will not be destroyed.

AUTOLOAD()
----------

   When this method is called (generally through perl mechanism), the call
will be forwarded with all parameter to the remote object. If the first
parameters is  : \&one_callback

   the function &one_callback will be called when the remote side has
finished its function.

   If you want to call-back an object method, use a closure. Such as

     $self->remote_method(sub {$self-> finished(@_)})

   Note that if the remote method name is not declared in the @RPC_SUB
array, AnyLocal will try to autoload this method.

   returns self.

instance variable
=================

   AnyLocal will create the following instance variables:

_twinHandle
-----------

   Will contains the ref of the RPC::Simple::Agent object.

remoteHostName
--------------

   Will contains the name of the remote host.

Inheritance and Autoload
========================

   Since RPC::Simple uses the AUTOLOAD subroutine to delegate unknown
calls to the remote class, you must pay attention if you use or inherit
classes which use the AutoLoader mechanism.

   The AUTOLOAD defined in this class will first check if the called
function is declared in the @RPC_SUB arrays of all inherited classes. If
yes it will call the remote function. If not it will forward the call to
the AutoLoader::AUTOLOAD routine. In this case you fall back on the usual
AutoLoad mechanism.

   For this scheme to work, it is important that RPC::Simple::AUTOLOAD is
run BEFORE the AutoLoader::AUTOLOAD routine.

   So when inheriting from RPC::Simple and another class (say Foo::Bar),
you must put RPC::Simple::AnyLocal BEFORE your class in the @ISA array.

   For instance, you must declare :  @ISA = qw(RPC::Simple::AnyLocal
Foo::Bar);

   BTW, if you are mixing autoloading, remote calls and inheritance, which
is a recipe for a good headache, you really (I mean it) should use
subroutine stubs for the auloaded functions. (It does really work better).
See AutoLoad(3).

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

SEE ALSO
========

   perl(1), RPC::Simple::Factory(3), RPC::Simple::AnyRemote(3)

Perl base class for a remote object accessible by RPC
*****************************************************

NAME
====

   RPC::Simple::AnyRemote - Perl base class for a remote object accessible
by RPC

SYNOPSIS
========

     package myClass ;
     use vars qw(@ISA @RPC_SUB);
     use RPC::Simple::AnyRemote;

     @ISA=('RPC::Simple::AnyRemote') ;
     @RPC_SUB = qw(localMethod);

DESCRIPTION
===========

   This class must be inherited by the user's class actually performing the
remote functions.

   Note that any user defined method which can be called by the local
object must be able to handle the following optionnal parameters :

   'callback' => code_reference

   Usually, the methods will be like :

     sub remoteMethod
     {
       my $self = shift ;
       my $param = shift ;
       my $callback ;

     if ($param eq 'callback')
       {
         # callback required
         $callback = shift
       }

     # user code

     # can call a method from local object
     $self->localMethod("Hey, remoteMethod was called !!");

     # when the user code is over
     return unless defined $callback ;

     &$callback("Hello local object" ) ;
      }

Methods
=======

new('controller_ref')
---------------------

   controller_ref is the RPC::Simple::ObjectHandler object actually
controlling this instance.

   If you overload 'new', don't forget to call also the inherited 'new'
method.

AUTOLOAD()
----------

   When this method is called (generally through perl mechanism), the call
will be forwarded with all parameter to the local object.  Note that if
the remote method name is not declated in the @RPC_SUB array, AnyLocal
will try to autoload this mehtod.

   Note that this method is not able to handle sub_reference and call back
mechanism is not possible fromthis side.

   returns self.

instance variable
=================

   AnyRemote will create the following instance variables:

_twinHandle
-----------

   RPC::Simple::ObjectHandler object reference

origDir
-------

   Store the pwd of the object during its creation.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

SEE ALSO
========

   perl(1), RPC::Simple::AnyLocal(3)

extension defining a virtual SRPC client or server class
********************************************************

NAME
====

   RPC::Simple::AnyWhere - extension defining a virtual SRPC client or
server class

SYNOPSIS
========

     package MyLocal ;

     use RPC::Simple::AnyLocal; # or AnyRemote BUT NOT THIS CLASS

DESCRIPTION
===========

   This class is intented to be inherited only by AnyLocal or AnyRemote.
Don't use it yourself.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

SEE ALSO
========

   perl(1), RPC::Simple::Factory(3), RPC::Simple::AnyRemote(3)

Perl class to handle RPC calls with call-back
*********************************************

NAME
====

   RPC::Simple::CallHandler - Perl class to handle RPC calls with call-back

SYNOPSIS
========

     use RPC::Simple::CallHandler;

DESCRIPTION
===========

   This class is intanciated on the remote side each time a function is
called with a call-back ref. This class will hold the relevant information
so that the call-back will be passed to the local object which issued the
call.

   Used only for asynchronous functions calls. I.e the called function
cannot pass a result immediately, it will have to call-back this handler.

new (handler_ref, remote_object, request_id, method, argument_ref)
==================================================================

   Call the remote_object methods with a call-back parameter and the passed
arguments, store the handler ref.

   Note that the called method must be able to handle a sub ref  parameter.
This sub must be called when the function is over.

   Usually the call-back function will be a closure.

methods
=======

done ($result, ...)
-------------------

   call-back method.

AUTHOR
======

   Dominique_Dumont@hp.com

SEE ALSO
========

   perl(1).

Perl extension for creating RPC client
**************************************

NAME
====

   RPC::Simple::Factory - Perl extension for creating RPC client

SYNOPSIS
========

     use Tk;
     use RPC::Simple::Factory;

     my $mw = MainWindow-> new ;
     my $verbose = 1 ; # up to you

     # create factory
     my $factory = new RPC::Simple::Factory($mw,\$verbose) ;

DESCRIPTION
===========

   This class handles all the tricky stuff involving socket handling.
Note that this was written to be used with Tk.

Methods
=======

new($tkTop, [ $verboseRef ], [remote_host], [port] )
----------------------------------------------------

   create the factory. One factory must be created for each remote host..

   tkTop is the ref of Tk's main window.

   $verboseRef is the ref of a variable. When set to 1 at any time, the
object will become verbose i.e. it will print on STDOUT a lot of messages
related to the RPC processing. Then you may use $verboseRef as a text
variable on a check button to control whether you want to trace RPC
messages or not.  If not provided, the object will not be verbose.

   By default, remote_host is set to 'localhost', port is set to 7810.

logmsg (...)
------------

   print arguments if verbose mode.

newRemoteObject( $owner_ref, [ remote_class_name ] ... )
--------------------------------------------------------

   Will create a remote (the remote_class_name) object tied to the owner.

   Additional parameters will be passed as is to the remote 'new' method.

getRemoteHostName
-----------------

   return the remote host name

writeSockBuffer ( agent_index, remote_method, request_id, parameter, [object_name])
-----------------------------------------------------------------------------------

   Encode the method, object, parameter and send it to the remote object.

   agent_index and request_id are used later for the call-back mechanism.

readSock
--------

   read pending data on the socket. Do an eval on the read data to
call-back the relevent Agents.

   Note that there's no security implemented (yet).

Static functions
================

spawn([port],[verbose])
-----------------------

   Will spawn a RPC::Simple server on your machine. Don't call this
function if you need to do RPC on a remote machine.

   Return the server pid or null (just like fork)

ON EXIT
=======

   When the object is destroyed, the 'END' routine will be called. This
will kill the server if it was created by spawn.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

SEE ALSO
========

   perl(1), RPC::Simple::Agent(3), RPC::Simple::AnyLocal(3).

Perl class to handle a remote object
************************************

NAME
====

   RPC::Simple::ObjectHandler - Perl class to handle a remote object

SYNOPSIS
========

     use RPC::Simple::ObjectHandler;

DESCRIPTION
===========

   This class is instanciated by RPS::Simple::Server each time a remote
object is created. All is handled by the server, the user need not to
worry about it.

new (server_ref, object_name, agent_id, argument_array_ref, req_id)
===================================================================

   Creates a new object controller. Also creates a new object_name which
is remotely controlled by the agent referenced by agent_id. If object name
has no suffix, new will 'require' object_name.pm

   The new method of the slave object will be passed the argument stored
in argument_array_ref.

   req_id is used for calling back the agent once the object is created
(either with success ot not)

   The connection server is passed with server_ref

METHODS
=======

remoteCall( request_id | undef , method_name, arguments )
---------------------------------------------------------

   Will call the slave object with method method_name and the arguments.

   If request_id is defined, it means that a call-back is expected. In
this case, the argument passed should contains a sub reference.

close
-----

   Cancel all pending requests and delete itself.

delegate(method_name, ... )
---------------------------

   Used to call the local object with passed method and arguments.

callbackDone($reqId,$result)
----------------------------

   Called by the callHandler when a function performed by the remote object
is over. $result being the result of this function.

AUTHOR
======

   Dominique_Dumont@hp.com

SEE ALSO
========

   perl(1)

Perl class to use in the RPC server script.
*******************************************

NAME
====

   RPC::Simple::Server - Perl class to use in the RPC server script.

SYNOPSIS
========

     use RPC::Simple::Server;

     my $server_pid = &spawn ;

DESCRIPTION
===========

   Generic server class. The mainLoop function will instantiate one server
object for each connection request.

   Server also provides functions (childDeath) to monitor children
processes.

Exported static functions
=========================

mainLoop
--------

   To be called at the end of the main program.  This function will
perform the select loop, and call relevant server objects.

goodGuy([ipaddress|host_name])
------------------------------

   Declare the IP address or the host name as a buddy. Connection from
buddies will be accepted. localhost is always considered as a good guy.

registerChild($object_ref, $pid)
--------------------------------

   Register process $pid as a process to be monitored by server.
$object_ref is the process manager of this child.
$object_ref::process_over will be called back when (or shortly after) the
child dies.

unregisterChild($pid)
---------------------

   unregister process $pid. Does not call-back the process manager.

childDeath
----------

   Static function called when a child dies. $SIG{CHLD} must be set to
\&childDeath by the user.

CONSTRUCTOR
===========

   Called by mainloop. Construct a server. Currently only one server is
supported.

METHODS
=======

acceptSocket
------------

   called by new. By default, accepts only connection from localhost
(127.0.0.1).

writeSock(index_of_agent, method, reqId, param, [objectName ])
--------------------------------------------------------------

   Called by Object handler to send data back to Agent.

   param: array_ref of parameters passed to the call-back function.

readClient
----------

   Read the client's socket. Execute the code passed through the socket and
call the relevant object handlers.

   returns 0 if the socket is closed.

close
-----

   Close the connection.

setMask(object,method, file_number)
-----------------------------------

   Function used by any object controlling a child process. Register the
object and the method to call back when reading from the passed file
descriptor.

   file_number is as given by fileno

resetMask
---------

   To be called when the child process is dead.

getFileno
---------

   Returns the fileno of the client's socket.

CAVEATS
=======

   Some function are provided to handle remote processes. These functions
are not yet tested. They may not stay in this class either.

AUTHOR
======

   Dominique_Dumont@hp.com

SEE ALSO
========

   perl(1).

Perl extension for writing pRPC clients
***************************************

NAME
====

   RPC::pClient - Perl extension for writing pRPC clients

SYNOPSIS
========

     use RPC::pClient;

     $sock = IO::Socket::INET->new('PeerAddr' => 'joes.host.de',
     				'PeerPort' => 2570,
     				'Proto' => 'tcp');

     $connection = new RPC::pClient('sock' => $sock,
                                    'application' => 'My App',
     				 'version' => '1.0',
     				 'user' => 'joe',
     				 'password' => 'hello!');

DESCRIPTION
===========

   pRPC (Perl RPC) is a package that simplifies the writing of Perl based
client/server applications. RPC::pServer is the package used on the server
side, and you guess what RPC::pClient is for. See `RPC::pClient(3)' in
this node for this part.

   pRPC works by defining a set of of functions that may be executed by
the client. For example, the server might offer a function "multiply" to
the client. Now a function call

     @result = $con->Call('multiply', $a, $b);

   on the client will be mapped to a corresponding call

     multiply($con, $data, $a, $b);

   on the server. (See the funcTable description below for $data.) The
function calls result will be returned to the client and stored in the
array @result. Simple, eh? :-)

Client methods
--------------

new
     The client constructor. Returns a client object or an error string,
     thus you typically use it like this:

          $client = RPC::pClient->new ( ... );
          if (!ref($client)) {
              print STDERR "Error while creating client object: $client\n";
          } else {
              # Do real stuff
              ...
          }

Call
     calls a function on the server; the arguments are a function name,
     followed by function arguments. It returns the function results, if
     successfull. After executing Call() you should always check the error
     attribute: An empty string indicates success. Thus the equivalent to

          $c = Add($a, $b)
          # Use $c
          ...

     is

          $c = $client->Call("Add", $a, $b);
          if ($client->error) {
              # Do something in case of error
              ...
          } else {
              # Use $c
              ...
          }

CallInt
     Similar to and internally used by Call. Receives the same arguments,
     but the result is prepended by a status value: If this status value
     is TRUE, then all went fine and the following result array is valid.
     Otherwise an error occurred and the error message follows immediately
     after the status code. Example:

          my($status, @result) = $client->CallInt("Add", $a, $b);
          if (!$status) {
              #  Do something in case of error
              my $errmsg = shift @result  ||  "Unknown error";
              ...
          } else {
              ...
          }

Encrypt
     This method can be used to get or set the cipher attribute, thus the
     encryption mode. If the method is passed an argument, the argument
     will be used as the new encryption mode. ('undef' for no encryption.)
     In either case the current encryption mode will be returned. Example:

          # Get the current encryption mode
          $mode = $server->Encrypt();

          # Currently disable encryption
          $server->Encrypt(undef);

          # Switch back to the old mode
          $server->Encrypt($mode);

Client attributes
-----------------

   Client attributes will typically be supplied with the new constructor.

sock
     An object of type IO::Socket, which should be connected to the server.

cipher
     This attribute can be used to add encryption quite easily. pRPC is not
     bound to a certain encryption method, but to a block encryption API.
     The attribute is an object supporting the methods blocksize, encrypt
     and decrypt. For example, the modules Crypt::DES and Crypt::IDEA
     support such an interface.

     Note that you can set or remove encryption on the fly (putting undef
     as attribute value will stop encryption), but you have to be sure,
     that both sides change the encryption mode.

     Do not modify this attribute directly, use the encrypt method
     instead! However, it is legal to pass the attribute to the
     constructor.

     Example:

          use Crypt::DES;
          $crypt = DES->new(pack("H*", "0123456789abcdef"));
          $client->Encrypt($crypt);

          # or, to stop encryption
          $client->Encrypt(undef);

application
version
user
password
     it is part of the pRPC authorization process, that the client must
     obeye a login procedure where he will pass an application name, a
     protocol version and optionally a user name and password.  You do not
     care for that (except passing the right values, of course :-), this
     is done within the client constructor.

io
     this attribute is the Storable object created for communication with
     the server. You may use this, for example, when you want to change
     the encryption mode with Storable::Encrypt(). See `Storable(3)' in
     this node.

EXAMPLE
=======

     #!/usr/local/bin/perl -T
     use 5.0004;               # Yes, this really *is* required.
     use strict;               # Always a good choice.

     use IO::Socket();
     use RPC::pClient;

     # Constants
     my $MY_APPLICATION = "Test Application";
     my $MY_VERSION = 1.0;
     my $MY_USER = "foo";
     my $MY_PASSWORD = "bar";

     # Connect to the server
     my $sock = IO::Socket::INET->new('PeerAddr' => 'joes.host.de',
                                      'PeerPort' => 5000,
                                      'Proto' => 'tcp');
     if (!defined($sock)) {
         die "Cannot connect: $!\n";
     }

     # Login procedure
     my $client = RPC::pClient->new('sock' => $sock,
                                    'application' => $MY_APPLICATION,
                                    'version' => $MY_VERSION,
                                    'user' => $MY_USER,
                                    'password' => $MY_PASSWORD);
     if (!ref($client)) {
         die "Cannot create client: $client\n";
     }

     # Call multiply function
     my $a = $client->Call("multiply", 3, 4);
     if ($client->error) {
         die "An error occurred while multiplying: $a\n";
     }

AUTHOR
======

   Jochen Wiedmann, wiedmann@neckar-alb.de

SEE ALSO
========

   `pRPC::Server(3)' in this node, `Storable(3)' in this node,
`Sys::Syslog(3)' in this node

   For an example application, see `DBD::pNET(3)' in this node.

Perl extension for writing pRPC servers
***************************************

NAME
====

   RPC::pServer - Perl extension for writing pRPC servers

SYNOPSIS
========

     use RPC::pServer;

     $sock = IO::Socket::INET->new('LocalPort' => 9000,
     				'Proto' => 'tcp',
     				'Listen' = 5,
     				'Reuse' => 1);

     $connection = new RPC::pServer('sock' => $sock,
     				      'configFile' => $file,
     				      'funcTable' => $funcTableRef,
     				      # other attributes #
     				     );

     while ($running) {
         $connection->Loop();
         if ($connection->error) {
     	  # Do something
         }
     }

DESCRIPTION
===========

   pRPC (Perl RPC) is a package that simplifies the writing of Perl based
client/server applications. RPC::pServer is the package used on the server
side, and you guess what Net::pRPC::Client is for. See
`Net::pRPC::Client(3)' in this node for this part.

   pRPC works by defining a set of of functions that may be executed by
the client. For example, the server might offer a function "multiply" to
the client. Now a function call

     @result = $con->Call('multiply', $a, $b);

   on the client will be mapped to a corresponding call

     multiply($con, $data, $a, $b);

   on the server. (See the funcTable description below for $data.) The
function call's result will be returned to the client and stored in the
array @result. Simple, eh? :-)

Server methods
--------------

new
     The server constructor. Unlike the usual constructors, this one will
     in general not return immediately, at least not for a server running
     as a daemon. Instead it will return if a connection is established
     with a connection object as result.  The result will be an error
     string or the connection object, thus you will typically do a

          $con = RPC::pServer->new ( ...);
          if (!ref($con)) {
              print "Error $con.\n";
          } else {
              # Accept connection
              ...
          }

Accept
Deny
     After a connection is established, the server should call either of
     these methods. If he calls Accept(), he should continue with calling
     the Loop() method for processing the clients requests.

Loop
     When a connection is established, the Loop method must be called. It
     will process the client's requests. If Loop() returns FALSE, an error
     occurred. It is the main programs task to decide what to do in that
     case.

Encrypt
     This method can be used to get or set the cipher attribute, thus the
     encryption mode. If the method is passed an argument, the argument
     will be used as the new encryption mode. ('undef' for no encryption.)
     In either case the current encryption mode will be returned. Example:

          # Get the current encryption mode
          $mode = $server->Encrypt();

          # Currently disable encryption
          $server->Encrypt(undef);

          # Switch back to the old mode
          $server->Encrypt($mode);

Server attributes
-----------------

   Server attributes will typically be supplied with the new constructor.

configFile
     RPC::pServer has a builtin authorization mechanism based on a
     configuration file. If you want to use this mechanism, just supply
     the name of a configuration file with the attribute configFile and
     the server will accept or deny connections based on the configuration
     file.

     The authorization scheme is host based, but you may add user based
     functionality with the user and password attributes. See `' in this
     node below.

client
     This attribute is useful in conjunction with the configFile.  If the
     server has authorized a client by using the config file, he will
     create a hash ref with all the client attributes and store a
     reference to this hash under the key client.  Thus you can easily
     extend the configuration file for your own purposes, at least as long
     as host based configuration is sufficient for you.

sock
     An object of type IO::Socket, if this program is running as a daemon.
     An accept() call will be executed on this socket in order to wait for
     connections. See `IO::Socket(3)' in this node.

     An inetd based server should leave this attribute empty: The method
     will use STDIN and STDOUT instead.

     Note: The latter is not yet functionable, I first need to work out
     how to create an object of type IO::socket for an inetd based
     server's STDIN and STDOUT. It seems this is currently not supported
     by IO::Socket.

cipher
     This attribute can be used to add encryption quite easily. pRPC is not
     bound to a certain encryption method, but to a block encryption API.
     The attribute is an object supporting the methods blocksize, encrypt
     and decrypt. For example, the modules Crypt::DES and Crypt::IDEA
     support such an interface.

     Do not modify this attribute directly, use the encrypt method
     instead!  However, it is legal to pass the attribute to the
     constructor.

     Example:

          use Crypt::DES;
          $crypt = DES->new(pack("H*", "0123456789abcdef"));
          $client->Encrypt($crypt);

          # or, to stop encryption
          $client->Encrypt(undef);

     You might prefer encryption being client dependent, so there is the
     additional possibility to setup encryption in the server configuration
     file. See `' in this node. Client encryption definitions take
     precedence over the cipher attribute.

     However, you can set or remove encryption on the fly (putting undef
     as attribute value will stop encryption), but you have to be sure,
     that both sides change the encryption mode.

funcTable
     This attribute is a hash reference. The hash keys are the names of
     methods, that the client may execute on the server.  The hash values
     are hash references (again). The RPC::pServer module will use the key
     'code' only: It contains a code reference to the function performing
     the clients function call. The first argument of the function call
     will be the connection object itself, the second will be the
     'funcTable' value. You are free to use this hash reference in any way
     you want, the exception being the 'code' key. The function must
     return a list: In case of errors the results will be the values 0,
     followed by a textual error message. In case of success, it ought to
     return nonzero, followed by the result list being sent to the client.

stderr
     a value of TRUE will enable logging messages to STDERR, the default
     is using syslog(); if the stderr attribute is FALSE, you might call
     openlog() to configure the application name and facility. See
     `Sys::Syslog(3)' in this node.

debug
     this will cause the server to log debugging information about client
     requests using the Log method. A value of 0 disables debugging.

application
version
user
password
     it is part of the pRPC authorization process, that the client must
     obeye a login procedure where he will pass an application name, a
     protocol version and optionally a user name and password.  These are
     not used by pRPC, but when the new method returns with a connection
     object, the main program may use these for additional authorization.

     These attributes are read-only.

io
     this attribute is a Storable object created for communication with
     the client. You may use this, for example, when you want to change
     the encryption mode with Storable::Encrypt(). See `Storable(3)' in
     this node.

CONFIGURATION FILE
==================

   The server configuration file is currently not much more than a
collection of client names or ip numbers that should be permitted or
denied to connect to the server. Any client is represented by a definition
like the following:

     accept .*\.neckar-alb\.de
         encryption    DES
         key           063fde7982defabc
         encryptModule Crypt::DES

     deny .*

   In other words a client definition begins with either `accept pattern'
or `deny pattern', followed by some client attributes, each of the
attributes being on a separate line, followed by the attribute value.  The
pattern is a perl regular expression matching either the clients host name
or IP number. In particular this means that you have to escape dots, for
example a client with IP number 194.77.118.1 is represented by the pattern
`194\.77\.118\.1'.

   Currently known attributes are:

encryption
key
encryptionModule
     These will be used for creating an encryption object which is used
     for communication with the client, see `Storable(3)' in this node for
     details. The object is created with a sequence like

          use $encryptionModule;
          $cipher = $encryption->new(pack("H*", $key));

     encryptionModule defaults to encryption, the reason why we need both
     is the brain damaged design of the Crypt/IDEA, and
     Crypt/DES, modules, which use different module and
     package names without any obvious reason.

   You may add any other attribute you want, thus extending your
authorization file. The RPC::pServer module will simply ignore them, but
your main program will find them in the client attribute of the
RPC::pServer object. This can be used for additional client dependent
configuration.

PREDEFINED FUNCTIONS
====================

   RPC::pServer offers some predefined methods which are designed for ease
in work with objects. In short they allow creation of objects on the
server, passing handles to the client and working with these handles in a
fashion similar to the use of the true objects.

   The handle functions need to share some common data, namely a hash
array of object handles (keys) and objects (values). The problem is, how
to allocate these variables. By keeping a multithreaded environment in
mind, we suggest to store the hash on the stack of the server's main loop.

   The handle functions get access to this loop, by looking into the
'handles' attribute of the respective entry in the 'funcTables' hash. See
above for a description of the 'funcTables' hash.

   See below for an example of using the handle functions.

NewHandle
     This method can be inserted into the servers function table. The
     client may call this function to create objects and receive handles
     to the objects. The corresponding entry in the function table must
     have a key classes: This is a list reference with class names. The
     client is restricted to create objects of these classes only.

     The NewHandle function expects, that the constructor returns an
     object in case of success or 'undef' otherwise. Note, that this isn't
     true in all cases, for example the RPC::pServer and Net::pRPC::Client
     classes behave different. In that cases you have to write your own
     constructor with a special error handling. The StoreHandle method
     below will help you.  Constructors with a different name than new are
     another example when you need StoreHandle directly.

StoreHandle
     After you have created an object on behave of the clients request,
     you'd like to store it for later use. This is what StoreHandle does
     for you. It returns an object handle which may be passed back to the
     client. The client can pass the objects back to the server for use in
     CallMethod or UseHandle.

NewHandle
     The NewHandle is mainly a wrapper for StoreHandle. It creates an
     object of the given class, passes it to StoreHandle and returns the
     result. The NewHandle method is designed for direct use within the
     servers function table.

UseHandle
     This is the counterpart of StoreHandle: It gets an object handle,
     passed by the client, as argument and returns the corresponding
     object, if any. An 'undef' value will be returned for an invalid
     handle.

CallMethod
     This function receives an object handle as argument and the name of a
     method being executed. The method will be invoked on the
     corresponding object and the result will be returned.

     A special method is 'DESTROY', valid for any object handle. It
     disposes the object, the handle becomes invalid.

   All handle functions are demonstrated in the following example.

EXAMPLE
=======

   Enough wasted time, spread the example, not the word. :-) Let's write a
simple server, say a spreadsheet server. Of course we are not interested
in the details of the spreadsheet part (which could well be implemented in
a separate program), the spreadsheet example is choosen, because it is
obvious, that such a server is dealing with complex data structures. For
example, a "sum" method should be able to add over complete rows, columns
or even rectangular regions of the spreadsheet. And another thing,
obviously a spread- sheet could easily be represented by perl data
structures: The spreadsheet itself could be a list of lists, the elements
of the latter lists being hash references, each describing one column. You
see, such a spreadsheet is an ideal object for the `Storable(3)' in this
node class. But now, for something completely different:

     #!/usr/local/bin/perl -wT # Note the -T switch! I mean it!
     use 5.0004;               # Yes, this really *is* required.
     use strict;               # Always a good choice.

     use IO::Socket();
     use RPC::pServer;

     # Constants
     $MY_APPLICATION = "Test Application";
     $MY_VERSION = 1.0;

     # Functions that the clients may execute; for simplicity
     # these aren't designed in an object oriented manner.

     # Function returning a simple scalar
     sub sum ($$$$$) {
     	my($con, $data, $spreadsheet, $from, $to) = @_;
         # Example: $from = A3, $to = B5
     	my($sum) = SpreadSheet::Sum($spreadsheet, $from, $to);
     	return (1, $sum);
     }

     # Function returning another spreadsheet, thus a complex object
     sub double ($$$$$) {
         my($con, $data, $spreadsheet, $from, $to);
         # Doubles the region given by $from and $to, returns
         # a spreadsheet
     	my($newSheet) = SpreadSheet::Double($spreadsheet, $from, $to);
     	(1, $newSheet);
     }

     # Quit function; showing the use of $data
     sub quit ($$) {
     	my($con, $data) = @_;
     	$$data = 0;   # Tell the server's Loop() method, that we
                       # are done.
         (1, "Bye!");
     }

     # Now we give the handle functions a try. First of all, a
     # spreadsheet constructor:
     sub spreadsheet ($$$$) {
     	my ($con, $data, $rows, $cols) = @_;
     	my ($sheet, $handle);
     	if (!defined($sheet = SpreadSheet::Empty($rows, $cols))) {
     	    $con->error = "Cannot create spreadsheet";
     	    return (0, $con->error);
     	}
     	if (!defined($handle = StoreHandle($con, $data, $sheet))) {
     	    return (0, $con->error); # StoreHandle stored error message
     	}
     	(1, $handle);
     }

     # Now a similar function to "double", except that a spreadsheet
     # is doubled, which is stored locally on the server and not
     # remotely on the client
     sub rdouble ($$$$$) {
         my($con, $data, $sHandle, $from, $to);
     	my($spreadsheet) = UseHandle($con, $data, $sHandle);
     	if (!defined($spreadsheet)) {
     	    return (0, $con->error); # UseHandle stored an error message
     	}
         # Doubles the region given by $from and $to, returns
         # a spreadsheet
     	my($newSheet) = SpreadSheet::Double($spreadsheet, $from, $to);
     	my($handle);
     	if (!defined($handle = StoreHandle($con, $data, $newSheet))) {
     	    return (0, $con->error); # StoreHandle stored error message
     	}
     	(1, $newSheet);
     }

     # This function is called for any valid connection to a client
     # In a loop it processes the clients requests.
     #
     # Note, that we are using local data only, thus we should be
     # safe in a multithreaded environment. (Of course, noone knows
     # about the spreadsheet functions ... ;-)
     sub Server ($) {
         my($con) = shift;
         my($con, $configFile, %funcTable);
         my($running) = 1;
     	my(%handles) = (); # Note: handle hash is on the local stack

     # First, create the servers function table. Note the
     # references to the handle hash in entries that access
     # the handle functions.
             %funcTable = {
         'sum'         => { 'code' => &sum },
         'double'      => { 'code' => &list },
         'quit'        => { 'code' => &quit,
     		       'data' = \$running }
         'spreadsheet' => { 'code' => \&spreadsheet,
     		       'handles' => \%handles },
         'rdouble'     => { 'code' => \&rdouble,
     		       'handles' = \%handles },

     # An alternative to the 'spreadsheet' entry above;
     'NewHandle'   => { 'code' => \&RPC::pServer::NewHandle,
     			       'handles' => \%handles,
     			       'classes' => [ 'Spreadsheet' ] },

     # Give client access to *all* (!) spreadsheet methods
     'CallMethod'  => { 'code' => \&RPC::pServer::CallMethod,
     			       'handles' => \%handles }
     	};

     $con->{'funcTable'} = \%funcTable;

     while($running) {
     	    if (!$con->Loop()) {
     		$con->Log('err', "Exiting.\n"); # Error already logged
     		exit 10;
     	    }
     }
     	$con->Log('notice', "Client quits.\n");
     	exit 0;
         }

     # Avoid Zombie ball ...
     sub childGone { my $pid = wait; $SIG{CHLD} = \&childGone; }

     # Now for main
     {
         my ($iAmDaemon, $sock);

     # Process command line arguments ...
             ...

     # If running as daemon: Create a socket object.
     	if ($iAmDaemon) {
     	    $sock = IO::Socket->new('Proto' => 'tcp',
     				    'Listen' => SOMAXCONN,
     				    'LocalPort' => 'wellKnownPort(42)',
     				    'LocalAddr' => Socket::INADDR_ANY
     				   );
     	} else {
     	    $sock = undef; # Let RPC::pServer create a sock object
     	}

     while (1) {
     	    # Wait for a client establishing a connection
     	    my $con = RPC::pServer('sock' => $sock,
     				   'configFile' => 'testapp.conf');
         if (!ref($con)) {
     		print STDERR "Cannot create server: $con\n";
     	    } else {
     		if ($con->{'application'} ne $MY_APPLICATION) {
     		    # Whatever this client wants to connect to:
     		    # It's not us :-)
     		    $con->Deny("This is a $MY_APPLICATION server. Go away");
     		} elsif ($con->{'version'} > $MY_VERSION) {
     		    # We are running an old version of the protocol :-(
     		    $con->Deny("Sorry, but this is version $MY_VERSION");
     		} elsif (!IsAuthorizedUser($con->{'user'},
     					   $con->{'password'})) {
     		    $con->Deny("Access denied");
     		} else {
     		    # Ok, we accept the client. Spawn a child and let
     		    # the child do anything else.
     		    my $pid = fork();
     		    if (!defined($pid)) {
     			$con->Deny("Cannot fork: $!");
     		    } elsif ($pid == 0) {
     			# I am the child
     			$con->Accept("Welcome to the pleasure dome ...");
     			Server();
     		    }
     		}
     	    }
     	}
         }

SECURITY
========

   It has to be said: pRPC based servers are a potential security problem!
I did my best to avoid security problems, but it is more than likely, that
I missed something. Security was a design goal, but not *the* design goal.
(A well known problem ...)

   I highly recommend the following design principles:

Protection against "trusted" users
----------------------------------

perlsec
     Read the perl security FAQ (`perldoc perlsec') and use the -T switch.

taintperl
     Use the -T switch. I mean it!

Verify data
     Never untaint strings withouth verification, better verify twice.
     For example the CallMethod function first checks, whether an object
     handle is in a a proper format (currently integer numbers, but don't
     rely on that, it could change). If it is, then it will still be
     verified, that an object with the given handle exists.

Be restrictive
     Think twice, before you give a client access to a function. In
     particular, think twice, before you give a client access to objects
     via the handle methods: If a client can coerce CallMethod() on an
     object, he has access to *all* methods of that object!

perlsec
     And just in case I forgot it: Read the perlsec man page. :-)

Protection against untrusted users
----------------------------------

Host based authorization
     pRPC has a builtin host based authorization scheme; use it!  See `'
     in this node.

User based authorization
     pRPC has no builtin user based authorization scheme; that doesn't
     mean, that you should not implement one.

Encryption
     Using encryption with pRPC is extremely easy. There is absolutely no
     reason for communicating unencrypted with the clients. Even more: I
     recommend two phase encryption: The first phase is the login phase,
     where to use a host based key. As soon as the user has authorized,
     you should switch to a user based key. See the DBD::pNET agent for an
     example.

AUTHOR
======

   Jochen Wiedmann, wiedmann@neckar-alb.de

SEE ALSO
========

   `Net::pRPC::Client(3)' in this node, `Storable(3)' in this node,
`Sys::Syslog(3)' in this node

   See `DBD::pNET(3)' in this node for an example application.

Perl extension for generating Rich Text (RTF) Files
***************************************************

NAME
====

   RTF::Document - Perl extension for generating Rich Text (RTF) Files

DESCRIPTION
===========

   RTF::Document is a module for generating Rich Text Format (RTF)
documents that can be used by most text converters and word processors.

   For a listing of properties, consult the %DOCINFO and %PROPERTIES hashes
in the source code.

REQUIRED MODULES
================

     Carp
     POSIX
     Convert::Units::Type 0.33

EXAMPLE
=======

     use RTF::Document;

     # Document properties

     $rtf = new RTF::Document(
       {
         doc_page_width => '8.5in',
         doc_page_height => '11in'
       }
     );

     # Font definitions

     $fAvantGarde = $rtf->add_font ("AvantGarde",
        { family=>swiss,
          default=>1
        } );
     $fCourier = $rtf->add_font ("Courier",
       { family=>monospace, pitch=>fixed,
         alternates=>["Courier New", "American Typewriter"]
       } );

     # Color definitions

     $cRed   = $rtf->add_color ( { red=>255 } );
     $cGreen = $rtf->add_color ( { green=>128 } );
     $cCustm = $rtf->add_color ( { red=>0x66, blue=>0x33, green=>0x33 } );

     $cBlack = $rtf->add_color ( { name=>'black' } );
     $cWhite = $rtf->add_color ( { gray=>'100%' } );

     $cNavy = $rtf->add_color ( { blue=>'100%', gray=>'50%' } );

     # style definitions

     $sNormal = $rtf->add_style( "Normal",
       { font=>$fAvantGarde, font_size=>'12pt',
         color_foreground=>$cBlack },
       { type=>paragraph, default=>1 }
     );

     $sGreen = $rtf->add_style( "Green",
       { color_foreground=>$cGreen },
       { type=>character, additive=>1 }
     );

     # Mix any combo of properties and text...

     $rtf->add_text( $rtf->root(),
        "Default text\n\n",

     { bold=>1, underline=>continuous },
     "Bold/Underlined Text\n\n",

     { font_size=>'20pt', font=>$fCourier,
       color_foreground=>$cRed },
     "Bigger, Red and Monospaced.\n\n",

     { style_default=>paragraph },
     { style_default=>character },

     "This is ",
     [ { style=>$sGreen }, "green" ],
     " styled.\n\n"

     );

     open FILE, ">MyFile.rtf";
     binmode FILE;
     print FILE $rtf->rtf();
     close FILE;

DOCUMENT STRUCTURE
==================

   For purposes of using this module, a Rich Text (RTF) Document can be
subdivided into groups. Groups can be considered containers for text and
*controls* (controlling document and text properties).

   For all intents and purposes, a group limits the scope of controls. So
if we set the "bold" character property within a group, the text will be
bold only within that group (until it is turned off within that group).

   When generating a RTF document using this module, we are only concerned
with the root group (also called the "Document Area"). (The "Header"
groups are taken care of automatically by this module.)

   The Document Area is subdivided into *sections*. Each section is
subdivided into paragraphs.

METHODS
=======

   Some of the methods are documented below. (Methods not documented here
may be changed in future versions.)

new
---

     $rtf = new RTF::Document( \%DocumentProperties );

   Creates a new RTF document object.

root
----

     $gRoot = $rtf->root();

   Returns the "root" group in the RTF document.

new_group
---------

     $gMyGroup = $rtf->new_group();

   Creates a new group (not inside of the RTF document).

add_group
---------

     $gChildOfRoot = $rtf->add_group();
     $gChildOfChild = $rtf->add_group( $gChild );

   Adds a child group to the specfied group. If no group is specified, the
"root" group is assumed.

     $rtf->add_group( $rtf->root(), $gMyGroup );

   Adds a group to the specified parent group (in this case, the root
group).

add_raw
-------

     $rtf->add_raw( $group, '\par', "Some Text" );

   Adds raw controls and text to the group. This method is intended for
internal use only.

add_text
--------

     $rtf->add_text( $group, "Some text ", { bold=>1 }, "more text" );

   Adds text and controls to a group. Text is escaped.

add_font
--------

add_color
---------

add_style
---------

PROPERTIES
==========

Document Properties
-------------------

Section Properties
------------------

Paragraph Properties
--------------------

Character Properties
--------------------

KNOWN ISSUES
============

   This module should be considered in the "alpha" stage. Use at your own
risk.

   There are no default document or style properties produced by this
module, with the exception of the character set. If you want to make sure
that a *specific* font, color, or style is used, you must specify it.
Otherwise you rely on the assumptions of whatever RTF reader someone is
using.

   This module does not insert newlines anywhere in the text, even though
some RTF writers break lines before they exceed 225 characters.  This may
or may not be an issue with some reader software.

   Unknown font or style properties will generally be ignored without
warning.

   This module supports some newer RTF controls (used in Word 95/Word 97)
that may are not understood by older RTF readers.

   Once a Font, Color or Style is added, it cannot be changed. No checking
for redundant entries is done.

   Generally, it is not possible to reference a not-yet-created Style with
the next or basedon attributes. However, you can use the constances "last",
"self" or "next" to reference the last style added, the current style
being added, or the next style that will be added, respectively.

   Specifying properties in a particular order within a group does not
guarantee that they will be emitted in that order. If order matters,
specify them separetly. For instance,

     $rtf->add_text($rtf->root, { style_default=>character, bold=>1 } );

   should be (if you want to ensure character styles are reset before
setting bold text):

     $rtf->add_text($rtf->root, { style_default=>character }, { bold=>1 } );

   Also note that duplicate properties within the same group won't work.
i.e., If you want to set "style_default" for both paragraphs and
characters, you must do so in separate groups.

   This isn't so much as a bug as the way Perl handles hashes.

Unimplemented Features
----------------------

   A rather large number of features and control words are not handled in
this version. Among the major features:

Annotations and Comments
Bookmarks
Bullets and Paragraph Numbering
     Some support has been added. The backwards-compatability controls for
     numbered paragraphs used by older readers has not been added because
     it is not properly handled by newer readers.

Character Sets and Internationalization
     Non-"ANSI" character sets (i.e., Macintosh) and Unicode character
     sets are not supported (at least not intentionally). There is no
     support for Asian character sets in this version of the module.

     Unicode character escapes are not implemented.

     Language codes (defining a default language, or a language for a
     group of characters) are not implemented.

     Bi-directional and text-flow controls are not implemented.

Embedded Images and OLE Objects
File Tables
Footnotes and Endnotes
Forms
Headers and Footers
Hyphenation Control
     Some minimal controls have been added.

Lists and List Tables
     Not implemented: List Tables are really a kind of style sheet for
     lists.  Priority will be given to support generic bullets and
     paragraph numbering.

Page Numbering
     Minimal definition, untested.

Printer Bin Controls
Revision Tables
Special Characters and Document Variables
     Most special characters not not implemented, with the exception of
     tabs. Double newline characters are converted to a new paragraph
     control, and single newlines are converted to a new line control.

Tabs
Tables and Frames
SEE ALSO
========

   Microsoft Technical Support and Application Note, "Rich Text Format
(RTF) Specification and Sample Reader Program", Version 1.5.

   *Convert::Units::Type*.

AUTHOR
======

   Robert Rothenberg <wlkngowl@unix.asb.com>

LICENSE
=======

   Copyright (c) 1999-2000 Robert Rothenberg. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Perl extension for randomizing things.
**************************************

NAME
====

   Randomize - Perl extension for randomizing things.

SYNOPSIS
========

     use Randomize;
     my $randomizer = Randomize->new(\@rules);
     while (1) {
       my $random_hash = $randomizer->generate();
     }

DESCRIPTION
===========

   This packages takes a set of randomization rules in the form of an
array reference, and creates random hashes on request based on the rules
given.

   I know that doesn't make sense, so here's an example.

     my @randomizer_rules =
       [ {Field  => 'Street',
          Values => [{Data   => ['Preston', 'Hillcrest'],
                      Weight => 1},
                     {Data   => ['Coit'],
                      Weight => 2}]},
         {Field  => 'Number',
          Values => [18100..18299]}
       };

     my $randomizer = Randomize->new(\@randomizer_rules);
     while (1)
       my $hashref = $randomizer->generate();
     }

   The key is @randomizer_rules.  What this list tells Randomizer is that,
every time you invoke the generate() method, you want to get back a
reference to a hash that looks like:

     $hashref = { Street => 'Preston',
                  Number => 18111 };

   where the Number is between 18100 and 18299 and the Street is either
Preston, Hillcrest, or Coit.  Further, you want the numbers to be evenly
distributed, but you want the street to be Coit half the time, and evenly
distributed between Preston and Hillcrest the rest of the time.

   So, if you called $randomizer->generate() 1000 times, you'd get roughly
500 addresses on Coit and 250 addresses each on Preston and Hillcrest.

   Let's look at a more complicated @randomizer_rules now.

     my @randomizer_rules =
       ( {Field  => 'Street',
          Values => [{Data   => ['Preston', 'Hillcrest'],
                      Weight => 1},
                     {Data   => ['Coit'],
                      Weight => 2}]},
         {Field  => 'Number',
          Values => [{Precondition => "<<Street>> eq 'Preston'",
                      Alternatives => [{Data => [18100..18199],
                                        Weight => 1},
                                       {Data => [18200..18299],
                                        Weight => 9}]},
                     {Precondition    => 'DEFAULT',
                      Alternatives => [{Data => [18100..18299],
                                        Weight => 1}]}]}
       );

   Given this, the generate() method will still return a hash reference in
the form

     $hashref = { Street => 'Preston',
                  Number => 18111 };

   with the same streets and address ranges.  However, if the street
picked happens to be Preston, 90% of the addresses generated will be in
the range 18200 to 18299.

   In final example, note the Retry_If clause:

     my @randomizer_rules =
       ( {Field  => 'Street',
          Values => [{Data   => ['Preston', 'Hillcrest'],
                      Weight => 1},
                     {Data   => ['Coit'],
                      Weight => 2}]},
         {Field  => 'Number',
          Values => [{Precondition => "<<Street>> eq 'Preston'",
                      Alternatives => [{Data => [18100..18199],
                                        Weight => 1},
                                       {Data => [18200..18299],
                                        Weight => 9}],
                      Retry_If     => ['defined $main::addr1 && <<Number>> == $main::addr1->{Number}']},
                     {Precondition    => 'DEFAULT',
                      Alternatives => [{Data => [18100..18299],
                                        Weight => 1}]}]}
       );

     my $randomizer = Randomize->new(\@randomizer_rules);
     while (1)
       $main::addr1 = $main::addr2 = undef;
       $main::addr1 = $randomizer->generate();
       $main::addr2 = $randomizer->generate();
     }

   In this example, we're generating pairs of addresses.  The Retry_If
clause ensures that we never get a pair of identical addresses on Preston.
It's still possible to get identical addresses on Coit or Hillcrest,
however.

   Retry_If clauses may also appear at the same level as Field and Values,
like so:

     my @randomizer_rules =
       ( {Field  => 'Street',
          Values => ['Preston', 'Hillcrest', 'Coit']},
         {Field  => 'Number',
          Values => [18100..18299],
          Retry_If => ['<<Street>> eq 'Coit' && <<Number>> eq 18200']}
       );

   This ruleset tells Randomize to try again if the address generated is
18200 Coit.

   There is also one special rule that Randomize looks for:  "DEBUG".  A
"DEBUG ON" rule turns debugging messages on so you can see what's
happening when you call generate().  It also attempts to print the code it
generates to a file.  You can optionally pass the filename in, like "DEBUG
ON myfile.code", or if you don't specify a file, the default output file
is "Randomize.code".  If the file can't be opened for writing, a warning
is sent to standard error, but execution of your program is otherwise
unaffected.

   Correspondingly, a "DEBUG OFF" rule turns debugging off, although the
code is still printed.  Placement of "DEBUG ON" and "DEBUG OFF" statements
determines which fields debugging information is printed for.  For
example, take a look at the following ruleset:

     my @randomizer_rules =
       ( 'DEBUG ON',
         {Field  => 'Street',
          Values => ['Preston', 'Hillcrest', 'Coit']},
         'DEBUG OFF',
         {Field  => 'Number',
          Values => [18100..18299],
          Retry_If => ['<<Street>> eq 'Coit' && <<Number>> eq 18200']},
       );

   This ruleset results in debugging information being printed for
generation of the "Street" field, but not for the "Number" field, and code
will be printed to the file "Randomize.code".

   NOTE:  Randomize cannot currently generate anything other than simple
hashes.  If you want a complex data structure, you'll have to either build
it yourself by moving items around in the returned hash, or by using
multiple randomize objects.

EXPORT
------

   None.

AUTHOR
======

   Brand Hilton

PUBLIC METHODS
==============

new
===

Description
-----------

   This is the constructor for Randomize objects.  It takes one parameter:
a reference to an array containing randomizer rules.  From these rules,
the generate() method is created.  If an error is detected in the rules,
the package variable $Randomize::errmsg will contain the error message and
new() will return undef.

Syntax
------

     $randomizer = Randomize->new(\@rules);

     $randomizer  - On success, a Randomize object.

     \@rules      - A reference to an array containing
                    Randomize rules, as described in the
                    DESCRIPTION section.

generate
========

Description
-----------

   This method returns a reference to a hash.  The hash contains the fields
you specified in your randomizer rules.  Each call to generate() gives you
a new hash, with a new set of randomized values.

   NOTE:  If you wish to specify a value for one or more fields of the
hash, you can pass in the field and its value.

Syntax
------

     $hashref = $randomizer->generate( [ $fieldname, $value, ... ] );

     $hashref    - A hash reference returned by generate().

     $randomizer - A Randomize object.

     $fieldname  - The name of a field in the hash.

     $value      - The value you wish that field to take
                   this time through.

parser and backends for 'rc' shell
**********************************

NAME
====

   Rc - parser and backends for 'rc' shell

SYNOPSIS
========

   If you need a synposis, you should start with an easier project.

DESCRIPTION
===========

   The design of this module is similar to the design of B, the
perl compiler backend.

WHY RC?
=======

   'rc' has a cleaner syntax in comparison to sh or csh.  If your going to
go through the unpleasantness of learning to program in a shell, it might
as well be 'rc'.

SUPPORT
=======

   Send any questions or comments to envy@listbox.com!

   If you'd like to subscribe to this mailing list send email to
majordomo@listbox.com.  Thanks!

AUTHOR
======

   Copyright © 1998 Joshua Nathaniel Pritikin.  All rights reserved.

   This package is free software and is provided "as is" without express
or implied warranty.  It may be used, redistributed and/or modified under
the terms of the Perl Artistic License (see
http://www.perl.com/perl/misc/Artistic.html)

   Portions of this sortware include source code from the 'rc' shell.
These portions are Copyright © 1991 Byron Rakitzis.  'rc' is free,
open-source package and is available at most ftp sites that distribute GNU
software.

Perl Object Class for Revision Control System (RCS).
****************************************************

NAME
====

   Rcs - Perl Object Class for Revision Control System (RCS).

SYNOPSIS
========

     use Rcs;

DESCRIPTION
===========

   This Perl module provides an object oriented interface to access
*Revision Control System (RCS)* utilities.  RCS must be installed on the
system prior to using this module.  This module should simplify the
creation of an RCS front-end.

OBJECT CONSTRUCTOR
------------------

   The new method may be used as either a class method or an object method
to create a new object.

     # called as class method
     $obj = Rcs->new;

     # called as object method
     $newobj = $obj->new;

CLASS METHODS
-------------

   Besides the object constructor, there are three class methods provided
which effect any newly created objects.

   The *arcext* method sets the RCS archive extension, which is ',v' by
default.

     # set/unset RCS archive extension
     Rcs->arcext('');            # set no archive extension
     Rcs->arcext(',v');          # set archive extension to ',v'
     $arc_ext = Rcs->arcext();   # get current archive extension

   The *bindir* method sets the directory path where the RCS executables
(i.e. rcs, ci, co) are located.  The default location is '/usr/local/bin'.

     # set RCS bin directory
     Rcs->bindir('/usr/bin');

     # access RCS bin directory
     $bin_dir = Rcs->bindir;

   The quiet method sets/unsets the quiet mode for the RCS executables.
Quiet mode is set by default.

     # set/unset RCS quiet mode
     Rcs->quiet(0);      # unset quiet mode
     Rcs->quiet(1);      # set quiet mode

     # access RCS quiet mode
     $quiet_mode = Rcs->quiet;

   These methods may also be called as object methods.

     $obj->arcext('');
     $obj->bindir('/usr/bin');
     $obj->quiet(0);

OBJECT ATTRIBUTE METHODS
------------------------

   These methods set the attributes of the RCS object.

   The file method is used to set the name of the RCS working file.  The
filename must be set before invoking any access of modifier methods on the
object.

     $obj->file('mr_anderson.pl');

   The *arcfile* method is used to set the name of the RCS archive file.
Using this method is optional, as the other methods will assume the archive
filename is the same as the working file unless specified otherwise.  The
RCS archive extension (default ',v') is automatically added to the
filename.

     $obj->arcfile('principle_mcvicker.pl');

   The *workdir* methods set the path of the RCS working directory.  If not
specified, default path is '.' (current working directory).

     $obj->workdir('/usr/local/source');

   The *rcsdir* methods set the path of the RCS archive directory.  If not
specified, default path is './RCS'.

     $obj->rcsdir('/usr/local/archive');

RCS PARSE METHODS
-----------------

   This class provides methods to directly parse the RCS archive file.

   The access method returns a list of all user on the access list.

     @access_list = $obj->access;

   The author method returns the author of the revision.  The head revision
is used if no revision argument is passed to method.

     # returns the author of revision '1.3'
     $author = $obj->author('1.3');

     # returns the authos of the head revision
     $author = $obj->author;

   The head method returns the head revision.

     $head = $obj->head;

   The lock method returns the locker of the revision.  The method returns
null if the revision is unlocked.  The head revision is used if no revision
argument is passed to method.

     # returns locker of revision '1.3'
     $locker = $obj->lock('1.3');

     # returns locker of head revision
     $locker = $obj->lock;

   The *revisions* method returns a list of all revisions of archive file.

     @revisions = $obj->revisions;

   The state method returns the state of the revision. The head revision
is used if no revision argument is passed to method.

     # returns state of revision '1.3'
     $state = $obj->state('1.3');

     # returns state of head revision
     $state = $obj->state;

   The symbol method returns the symbol(s) associated with a revision.  If
called in list context, method returns all symbols associated with
revision.  If called in scalar context, method returns last symbol
assciated with a revision.  The head revision is used if no revision
argument is passed to method.

     # list context, returns all symbols associated with revision 1.3
     @symbols = $obj->symbol('1.3');

     # list context, returns all symbols associated with head revision
     @symbols = $obj->symbol;

     # scalar context, returns last symbol associated with revision 1.3
     $symbol = $obj->symbol('1.3');

     # scalar context, returns last symbol associated with head revision
     $symbol = $obj->symbol;

   The symbols method returns a hash, keyed by symbol, of all of the
revisions associated with the file.

     %symbols = $obj->symbols;
     foreach $sym (keys %symbols) {
         $rev = $symbols{$sym};
     }

   The *revdate* method returns the date of a revision.  The returned date
format is the same as the localtime format.  When called as a scalar, it
returns the system date number.  If called is list context, the list
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) is returned.

     # scalar mode
     $scalar_date = $obj->revdate;
     print "Scalar date number = $scalar_date\n";
     $date_str = localtime($scalar_date);
     print "Scalar date string = $date_str\n";

     # list mode
     @list_date = $obj->revdate;
     print "List date = @list_date\n";

   The *dates* method returns a hash of revision dates, keyed on revision.
The hash values are system date numbers.  When called in scalar mode, the
method returns the most recent revision date.

     # list mode
     %DatesHash = obj->dates;
     @dates_list = sort {$b<=>$a} values %DatesHash;
     $MostRecent = $dates_list[0];

     # scalar mode
     $most_recent = $obj->dates;
     print "Most recent date = $most_recent\n";
     $most_recent_str = localtime($most_recent);
     print "Most recent date string = $most_recent_str\n";

   The *symrev* method returns the revision against which a specified
symbol was defined. If the symbol was not defined against any version of
this file, 0 is returned.

     # gets revision that has 'MY_SYMBOL' defined against it
     $rev = $obj->symrev('MY_SYMBOL');

   The *daterev* method returns revisions which were created before a
specified date.  Method may take one or six arguments.  If one arguments
is passed, then the argument is a date number.  If six arguments are
passed, then they represent a date string.

     # one argument, date number
     # gets revisions created before Sun Sep  6 22:23:47 1998
     @revs = $obj->daterev(841436420);

     # six argument
     # gets revisions created before 25th June 1998 16:45:30
     @revs = $obj->daterev(1998, 6, 25, 16, 45, 30);

   The comments method returns a hash of revision comments, keyed on
revision.  A key value of 0 returns the description.

     %comments = $obj->comments;
     $description = $comments{0};
     $comment_1_3 = $comments{'1.3'};

RCS SYSTEM METHODS
------------------

   These methods invoke the RCS system utilities.

   The ci method calls the RCS ci program.

     # check in, and then check out in unlocked state
     $obj->ci('-u');

   The co method calls the RCS co program.

     # check out in locked state
     $obj->co('-l');

   The *rcs* method calls the RCS rcs program.

     # lock file
     $obj->rcs('-l');

   The *rcsdiff* method calls the RCS rcsdiff program.  When called in
list context, this method returns the outpout of the rcsdiff program.
When called in scalar context, this method returns the return status of
the rcsdiff program.  The return status is 0 for the same, 1 for some
differences, and 2 for error condition.

   When called without parameters, rcsdiff does a diff between the current
working file, and the last revision checked in.

     # call in list context
     @diff_output = $obj->rcsdiff;

     # call in scalar context
     $changed = $obj->rcsdiff;
     if ($changed) {
         print "Working file has changed\n";
     }

   Call rcsdiff with parameters to do a diff between any two revisions.

     @diff_output = $obj->rcsdiff('-r1.2', '-r1.1');

   The *rlog* method calls the RCS rlog program.  This method returns the
output of the rlog program.

     # get complete log output
     @rlog_complete = $obj->rlog;

     # called with '-h' switch outputs only header information
     @rlog_header = $obj->rlog('-h');
     print @rlog_header;

   The *rcsclean* method calls the RCS rcsclean program.

     # remove working file
     $obj->rcsclean;

EXAMPLES
========

CREATE ACCESS LIST
------------------

   Using method *rcs* with the -a switch allows you to add users to the
access list of an RCS archive file.

     use Rcs;
     $obj = Rcs->new;

     $obj->rcsdir("./project_tree/archive");
     $obj->workdir("./project_tree/src");
     $obj->file("cornholio.pl");

   Methos *rcs* invokes the RCS utility rcs with the same parameters.

     @users = qw(beavis butthead);
     $obj->rcs("-a@users");

   Calling method access returns list of users on access list.

     $filename = $obj->file;
     @access_list = $obj->access;
     print "Users @access_list are on the access list of $filename\n";

PARSE RCS ARCHIVE FILE
----------------------

   Set class variables and create 'RCS' object.  Set bin directory where
RCS programs (e.g. rcs, ci, co) reside.  The default is '/usr/local/bin'.
This sets the bin directory for all objects.

     use Rcs;
     Rcs->bindir('/usr/bin');
     $obj = Rcs->new;

   Set information regarding RCS object.  This information includes name
of the working file, directory of working file ('.' by default), and RCS
archive directory ('./RCS' by default).

     $obj->rcsdir("./project_tree/archive");
     $obj->workdir("./project_tree/src");
     $obj->file("cornholio.pl");

     $head_rev = $obj->head;
     $locker = $obj->lock;
     $author = $obj->author;
     @access = $obj->access;
     @revisions = $obj->revisions;

     $filename = $obj->file;

     if ($locker) {
         print "Head revision $head_rev is locked by $locker\n";
     }
     else {
         print "Head revision $head_rev is unlocked\n";
     }

     if (@access) {
         print "\nThe following users are on the access list of file $filename\n";
         map { print "User: $_\n"} @access;
     }

     print "\nList of all revisions of $filename\n";
     foreach $rev (@revisions) {
         print "Revision: $rev\n";
     }

CHECK-IN FILE
-------------

   Set class variables and create 'RCS' object.  Set bin directory where
RCS programs (e.g. rcs, ci, co) reside.  The default is '/usr/local/bin'.
This sets the bin directory for all objects.

     use Rcs;
     Rcs->bindir('/usr/bin');
     Rcs->quiet(0);      # turn off quiet mode
     $obj = Rcs->new;

   Set information regarding RCS object.  This information includes name of
working file, directory of working file ('.' by default), and RCS archive
directory ('./RCS' by default).

     $obj->file('cornholio.pl');

     # Set RCS archive directory, is './RCS' by default
     $obj->rcsdir("./project_tree/archive");

     # Set working directory, is '.' by default
     $obj->workdir("./project_tree/src");

   Check in file using -u switch.  This will check in the file, and will
then check out the file in an unlocked state.  The -m switch is used to
set the revision comment.

   Command:

     $obj->ci('-u', '-mRevision Comment');

   is equivalent to commands:

     $obj->ci('-mRevision Comment');
     $obj->co;

CHECK-OUT FILE
--------------

   Set class variables and create 'RCS' object.  Set bin directory where
RCS programs (e.g. rcs, ci, co) reside.  The default is '/usr/local/bin'.
This sets the bin directory for all objects.

     use Rcs;
     Rcs->bindir('/usr/bin');
     Rcs->quiet(0);      # turn off quiet mode
     $obj = Rcs->new;

   Set information regarding RCS object.  This information includes name of
working file, directory of working file ('.' by default), and RCS archive
directory ('./RCS' by default).

     $obj->file('cornholio.pl');

     # Set RCS archive directory, is './RCS' by default
     $obj->rcsdir("./project_tree/archive");

     # Set working directory, is '.' by default
     $obj->workdir("./project_tree/src");

   Check out file read-only:

     $obj->co;

   or check out and lock file:

     $obj->co('-l');

RCSDIFF
-------

   Method *rcsdiff* does an diff between revisions.

     $obj = Rcs->new;
     $obj->bindir('/usr/bin');

     $obj->rcsdir("./project_tree/archive");
     $obj->workdir("./project_tree/src");
     $obj->file("cornholio.pl");

     print "Diff of current working file\n";
     if ($obj->rcsdiff) {       # scalar context
         print $obj->rcsdiff;   # list context
     }
     else {
        print "Versions are Equal\n";
     }

     print "\n\nDiff of revisions 1.2 and 1.1\n";
     print $obj->rcsdiff('-r1.2', '-r1.1');

RCSCLEAN
--------

   Method *rcsclean* will remove an unlocked working file.

     use Rcs;
     Rcs->bindir('/usr/bin');
     Rcs->quiet(0);      # turn off quiet mode
     $obj = Rcs->new;

     $obj->rcsdir("./project_tree/archive");
     $obj->workdir("./project_tree/src");
     $obj->file("cornholio.pl");

     print "Quiet mode NOT set\n" unless Rcs->quiet;

     $obj->rcsclean;

AUTHOR
======

   Craig Freter, <`craig@freter.com'>

CONTRIBUTORS
============

   David Green, <`greendjf@cvhp152.gpt.co.uk'>

   Jamie O'Shaughnessy, <`jamie@thanatar.demon.co.uk'>

COPYRIGHT
=========

   Copyright (C) 1997,1998 Craig Freter.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

create regular expressions from word lists
******************************************

NAME
====

   Regex::PreSuf - create regular expressions from word lists

SYNOPSIS
========

     use Regex::PreSuf;

     my $re = presuf(qw(foobar fooxar foozap));

     # $re should be now 'foo(?:zap|[bx]ar)'

DESCRIPTION
===========

   The *presuf()* subroutine builds regular expressions out of 'word
lists', lists of strings.  The regular expression matches the same words
as the word list.  These regular expressions normally run faster than a
simple-minded '|'-concatenation of the words.

   Examples:

   *      'foobar fooxar' => 'foo[bx]ar'

   *      'foobar foozap' => 'foo(?:bar|zap)'

   *      'foobar fooar'  => 'foob?ar'

   The downsides:

   * The original order of the words is not necessarily respected, for
     example because the character class matches are collected together,
     separate from the '|' alternations.

   * The module blithely ignores any specialness of any regular expression
     metacharacters such as the `.*?+{}[]^$', they are just plain ordinary
     boring characters.

   For the second downside there is an exception.  The module has some
rudimentary grasp of how to use the 'any character' metacharacter.  If you
call *presuf()* like this:

     my $re = presuf({ anychar=>1 }, qw(foobar foo.ar fooxar));

     # $re should be now 'foo.ar'

   The module finds out the common prefixes and suffixes of the words and
then recursively looks at the remaining differences.  However, by default
only common prefixes are used because for many languages (natural or
artificial) this seems to produce the fastest matchers.  To allow also for
suffixes use

     my $re = presuf({ suffixes=>1 }, ...);

   To use *only* suffixes use

     my $re = presuf({ prefixes=>0 }, ...);

   (this implicitly enables suffixes)

Debugging
---------

   In case you want to flood your session without debug messages you can
turn on debugging by saying

     Regex::PreSuf::debug(1);

   How to turn them off again is left as an exercise for the kind reader.

COPYRIGHT
=========

   Jarkko Hietaniemi

   This code is distributed under the same copyright terms as Perl itself.

Object Oriented interface to perl's regular expression code
***********************************************************

NAME
====

   Regexp - Object Oriented interface to perl's regular expression code

SYNOPSIS
========

     use Regexp;

     my $re = new Regexp q/Some Pattern/;

     if (match $re "Some String") { ... }

     $re->prematch

     $re->postmatch

     $re->pattern

     my @info  = $re->backref
     my $count = $re->backref

DESCRIPTION
===========

CONSTRUCTORS
============

new ( PATTERN [, FLAGS ] )
     new compiles the given PATTERN into a new Regexp object.  See
     Perlre (perl.info), for a description of PATTERN

     A second optional parameter, FLAGS, can be used to control how the
     pattern is compiled. FLAGS is a numeric value which can be
     constructed by or-ing together constants which Regexp conditionally
     exports. The constants are :

    FOLD
          Perform case-insensitive matches. See `/i' in Perlre (perl.info),

    NOCASE
          A synonym for FOLD

    MULTILINE
          Treat strings as multiple lines, See `/m' in Perlre (perl.info),

    SINGLELINE
          Treat strings as single lines, See `/s' in Perlre (perl.info),

    EXTENDED
          Use extended patter formats to increase legibility, See `/x' in
          Perlre (perl.info),

current
     Returns an object which represents the current (last) pattern.

METHODS
=======

minlength
     Returns the minimum length that a string has to be before it will
     match the regular expression

pattern
     Returns the pattern text

match ( STRING [, OFFSET [, FLAGS]] )
     match is like the `=~' operator in perl. STRING is the string which
     the regexp is to be applied. `OFFEST' and FLAGS are both optional.

     In a scalar context match returns a true or false value depending on
     whether the match was sucessful. In an array context match returns an
     array of the contents of all the backreferences, or an empty array.

     `OFFSET', if given, directs the regexp code to start trying to match
     the regexp at the given offset from the start of STRING

     FLAGS is a numeric value which can be constructed by or-ing together
     constants which Regexp conditionally exports. The constants are :

    GLOBAL
          Match as many times as possible, starting each time where the
          previous match ended. See `/g' option in Perlre (perl.info).

          If match is called in an array context and the GLOBAL flag is
          set then the result will be an array of all the backreferences
          from all the matches.

nparens
     Returns the number of parentheses in the expression

lastparen
     Returns the number of the last parentheses that matched.

backref ( [INDEX] )
     The result of backref is sensetive to how it is called.

     If called with a single argument then backref returns the text for
     the given backreference in the pattern. Backreferences are numbered
     from 1 as with `$1..$9'.

     If called with a single argument of zero, then backref will return
     the text of the last match. (Same as lastmatch)

     If called without any arguments, and in a scalar context, then
     backref will return the number of backreferences that there are in
     the Regexp object. (Same as nparens)

     If called without any arguments, and in aN array context, then
     backref will return a list of all the backreference values from the
     last match.

prematch
     Returns the text preceeding the text of the last match

lastmatch
     Returns the text of the last match

postmatch
     Returns the text following the text of the last match

startpos
     Returns the offset into the original string to the start of the text
     in the last match.

length
     Returns the length of the text in the last match

endpos
     Returns the offset into the original string to the end of the text in
     the last match.

AUTHORS
=======

   Regexp is a combination of work by Nick Ing-Simmons
<`nick@ni-s.u-net.com'> and Ilya Zakharevich <`ilya@math.ohio-state.edu'>
brought together and improved by Graham Barr <`bodg@tiuk.ti.com'>

Provide commonly requested regular expressions
**********************************************

NAME
====

   Regexp::Common - Provide commonly requested regular expressions

SYNOPSIS
========

     # STANDARD USAGE

     use Regexp::Common;

     while (<>) {
     	/$RE{num}{real}/ 		and print q{a number\n};
     	/$RE{quoted}			and print q{a ['"`] quoted string\n};
     	/$RE{delimited}{-delim=>'/'}/	and print q{a /.../ sequence\n};
     	/$RE{balanced}{-parens=>'()'}/	and print q{balanced parentheses\n};
     	/$RE{profanity}/ 		and print q{a #*@%-ing word\n};
     }

     # SUBROUTINE-BASED INTERFACE

     use Regexp::Common 'RE';

     while (<>) {
     	$_ =~ RE_num_real() 		 and print q{a number\n};
     	$_ =~ RE_quoted()		 and print q{a ['"`] quoted string\n};
     	$_ =~ RE_delimited(-delim=>'/')	 and print q{a /.../ sequence\n};
     	$_ =~ RE_balanced(-parens=>'()'} and print q{balanced parentheses\n};
     	$_ =~ RE_profanity() 		 and print q{a #*@%-ing word\n};
     }

     # IN-LINE MATCHING...

     if ( $RE{num}{int}->matches($text} ) {...}

     # ...AND SUBSTITUTION

     my $cropped = $RE{ws}{crop}->subs($uncropped);

     # ROLL-YOUR-OWN PATTERNS

     use Regexp::Common 'pattern';

     pattern name   => ['name', 'mine'],
     	 create => '(?i:J[.]?\s+A[.]?\s+Perl-Hacker)',
     	 ;

     my $name_matcher = $RE{name}{mine};

     pattern name    => [ 'lineof', '-char=_' ],
     	 create  => sub {
     			my $flags = shift;
     			my $char = quotemeta $flags->{-char};
     			return '(?:^$char+$)';
     		    },
     	 matches => sub {
        			my ($self, $str) = @_;
        			return $str !~ /[^$self->{flags}{-char}]/;
     		    },
     	 subs   => sub {
     			my ($self, $str, $replacement) = @_;
     			$_[1] =~ s/^$self->{flags}{-char}+$//g;
     		   },
     	 ;

     my $asterisks = $RE{lineof}{-char=>'*'};

DESCRIPTION
===========

   By default, this module exports a single hash (`%RE') that stores or
generates commonly needed regular expressions (see `"List of available
patterns"' in this node).

   There is an alternative, subroutine-based syntax described in
`"Subroutine-based interface"' in this node.

General syntax for requesting patterns
--------------------------------------

   To access a particular pattern, `%RE' is treated as a hierarchical hash
of hashes (of hashes...), with each successive key being an identifier. For
example, to access the pattern that matches real numbers, you specify:

     $RE{num}{real}

     and to access the pattern that matches integers:

     $RE{num}{int}

   Deeper layers of the hash are used to specify flags: arguments that
modify the resulting pattern in some way. The keys used to access these
layers are prefixed with a minus sign and may include a value that is
introduced by an equality sign. For example, to access the pattern that
matches base-2 real numbers with embedded commas separating groups of
three digits (e.g. 10,101,110.110101101):

     $RE{num}{real}{'-base=2'}{'-sep=,'}{'-group=3'}

   Through the magic of Perl, these flag layers may be specified in any
order (and even interspersed through the identifier keys!)  so you could
get the same pattern with:

     $RE{num}{real}{'-sep=,'}{'-group=3'}{'-base=2'}

   or:

     $RE{num}{'-base=2'}{real}{'-group=3'}{'-sep=,'}

   or even:

     $RE{'-base=2'}{'-group=3'}{'-sep=,'}{num}{real}

   etc.

   Note, however, that the relative order of amongst the identifier keys
*is* significant. That is:

     $RE{list}{set}

   would not be the same as:

     $RE{set}{list}

Alternative flag syntax
-----------------------

   As the examples in the previous section indicate, the syntax for
specifying flags is somewhat cumbersome, because of the need to quote the
entire (non-identifier) key-plus-value. To make such specifications less
ugly, Regexp::Common permanently changes the value of the magical $;
variable (setting it to the character `'=''), so that flags can also be
specified like so:

     $RE{num}{real}{-base=>2}{-group=>3}{-sep=>','}

   This syntax is preferred, and is used throughout the rest of this
document.

   In the unlikely case that the non-standard value of $; breaks your
program, this behaviour can be disabled by importing the module as:

     use Regexp::Common 'clean';

Universal flags
---------------

   Normally, flags are specific to a single pattern.  However, there is
one flag that all patterns may specify.

   By default, the patterns provided by `%RE' contain no capturing
parentheses. However, if the `-keep' flag is specified (it requires no
value) then any significant substrings that the pattern matches are
captured. For example:

     if ($str =~ $RE{num}{real}{-keep}) {
             $number   = $1;
             $whole    = $3;
             $decimals = $5;
     }

   Special care is needed if a "kept" pattern is interpolated into a
larger regular expression, as the presence of other capturing parentheses
is likely to change the "number variables" into which significant
substrings are saved.

   See also `"Adding new regular expressions"' in this node, which
describes how to create new patterns with "optional" capturing brackets
that respond to `-keep'.

OO interface and inline matching/substitution
---------------------------------------------

   The patterns returned from `%RE' are objects, so rather than writing:

     if ($str =~ /$RE{some}{pattern}/ ) {...}

   you can write:

     if ( $RE{some}{pattern}->matches($str) ) {...}

   For matching this would seem to have no great advantage apart from
readability (but see below).

   For substitutions, it has other significant benefits. Frequently you
want to perform a substitution on a string without changing the original.
Most people use this:

     $changed = $original;
     $changed =~ s/$RE{some}{pattern}/$replacement/;

   The more adept use:

     ($changed = $original) =~ s/$RE{some}{pattern}/$replacement/;

   Regexp::Common allows you do write this:

     $changed = $RE{some}{pattern}->subs($original=>$replacement);

   Apart from reducing precedence-angst, this approach has the daded
advantages that the substitution behaviour can be optimized fro the
regular expression, and the replacement string can be provided by default
(see `"Adding new regular expressions"' in this node).

   For example, in the implementation of this substitution:

     $cropped = $RE{ws}{crop}->subs($uncropped);

   the default empty string is provided automatically, and the
substitution is optimized to use:

     $uncropped =~ s/^\s+//;
     $uncropped =~ s/\s+$//;

   rather than:

     $uncropped =~ s/^\s+|\s+$//g;

Subroutine-based interface
--------------------------

   The hash-based interface was chosen because it allows regexes to be
effortlessly interpolated, and because it also allows them to be
"curried". For example:

     my $num = $RE{num}{int};

     my $comma'd    = $num->{-sep=>','}{-group=>3};
     my $duodecimal = $num->{-base=>12};

   However, the use of tied hashes does make the access to Regexp::Common
patterns slower than it might otherwise be. In contexts where impatience
overrules laziness, Regexp::Common provides an additional subroutine-based
interface.

   For each (sub-)entry in the `%RE' hash (`$RE{key1}{key2}{etc}'), there
is a corresponding exportable subroutine: `RE_key1_key2_etc()'. The name of
each subroutine is the underscore-separated concatenation of the *non-flag*
keys that locate the same pattern in `%RE'. Flags are passed to the
subroutine in its argument list. Thus:

     use Regexp::Common qw( RE_ws_crop RE_num_real RE_profanity );

     $str =~ RE_ws_crop() and die "Surrounded by whitespace";

     $str =~ RE_num_real(-base=>8, -sep=>" ") or next;

     $offensive = RE_profanity(-keep);
     $str =~ s/$offensive/$bad{$1}++; "<expletive deleted>"/ge;

   Note that, unlike the hash-based interface (which returns objects),
these subroutines return ordinary qr'd regular expressions. Hence they do
not curry, nor do they provide the OO match and substitution inlining
described in the previous section.

   It is also possible to export subroutines for all available patterns
like so:

     use Regexp::Common 'RE_ALL';

Adding new regular expressions
------------------------------

   You can add your own regular expressions to the `%RE' hash at run-time,
using the exportable pattern subroutine. It expects a hash-like list of
key/value pairs that specify the behaviour of the pattern. The various
possible argument pairs are:

`name => [ @list ]'
     A required argument that specifies the name of the pattern, and any
     flags it may take, via a reference to a list of strings. For example:

          pattern name => [qw( line of -char )],
                  # other args here
                  ;

     This specifies an entry `$RE{line}{of}', which may take a `-char'
     flag.

     Flags may also be specified with a default value, which is then used
     whenever the flag is omitted, or specified without an explicit value.
     For example:

          pattern name => [qw( line of -char=_ )],
                  # default char is '_'
                  # other args here
                  ;

`create => $sub_ref_or_string'
     A required argument that specifies either a string that is to be
     returned as the pattern:

          pattern name    => [qw( line of underscores )],
                  create  => q/(?:^_+$)/
                  ;

     or a reference to a subroutine that will be called to create the
     pattern:

          pattern name    => [qw( line of -char=_ )],
                  create  => sub {
                                  my ($self, $flags) = @_;
                                  my $char = quotemeta $flags->{-char};
                                  return '(?:^$char+$)';
                              },
                  ;

     If the subroutine version is used, the subroutine will be called with
     three arguments: a reference to the pattern object itself, a reference
     to a hash containing the flags and their values, and a reference to
     an array containing the non-flag keys.

     Whatever the subroutine returns is stringified as the pattern.

     No matter how the pattern is created, it is immediately postprocessed
     to include or exclude capturing parentheses (according to the value
     of the `-keep' flag). To specify such "optional" capturing
     parentheses within the regular expression associated with create, use
     the notation `(?k:...)'. Any parentheses of this type will be
     converted to `(...)'  when the `-keep' flag is specified, or
     `(?:...)' when it is not.  It is a Regexp::Common convention that the
     outermost capturing parentheses always capture the entire pattern,
     but this is not enforced.

`matches => $sub_ref'
     An optional argument that specifies a subroutine that is to be called
     when the `$RE{...}->matches(...)' method of this pattern is invoked.

     The subroutine should expect two arguments: a reference to the
     pattern object itself, and the string to be matched against.

     It should return the same types of values as a `m/.../' does.

          pattern name    => [qw( line of -char )],
                  create  => sub {...},
                  matches => sub {
                                  my ($self, $str) = @_;
                                  return $str !~ /[^$self->{flags}{-char}]/;
                             },
                  ;

`subs => $sub_ref'
     An optional argument that specifies a subroutine that is to be called
     when the `$RE{...}->subs(...)' method of this pattern is invoked.

     The subroutine should expect three arguments: a reference to the
     pattern object itself, the string to be changed, and the value to be
     substituted into it.  The third argument may be undef, indicating the
     default substitution is required.

     The subroutine should return the same types of values as an
     `s/.../.../' does.

     For example:

          pattern name    => [ 'lineof', '-char=_' ],
                  create  => sub {...},
                  subs   => sub {
                                  my ($self, $str, $ignore_replacement) = @_;
                                  $_[1] =~ s/^$self->{flags}{-char}+$//g;
                            },
                   ;

     Note that such a subroutine will almost always need to modify `$_[1]'
     directly.

`version => $minimum_perl_version'
     If this argument is given, it specifies the minimum version of perl
     required to use the new pattern. Attempts to use the pattern with
     earlier versions of perl will generate a fatal diagnostic.

List of available patterns
--------------------------

   The following patterns are currently available:

`$RE{balanced}{-parens}'
     Returns a pattern that matches a string that starts with the nominated
     opening parenthesis or bracket, contains characters and properly
     nested parenthesized subsequences, and ends in the matching
     parenthesis.

     More than one type of parenthesis can be specified:

          $RE{balanced}{-parens=>'(){}'}

     in which case all specified parenthesis types must be correctly
     balanced within the string.

     Under `-keep':

    $1
          captures the entire expression

`$RE{num}{int}{-sep}{-group}'
     Returns a pattern that matches a decimal integer.

     If `-sep=*P*' is specified, the pattern P is required as a grouping
     marker within the number.

     If `-group=*N*' is specified, digits between grouping markers must be
     grouped in sequences of exactly N characters. The default value of N
     is 3.

     For example:

          $RE{num}{int}                            # match 1234567
          $RE{num}{int}{-sep=>','}                 # match 1,234,567
          $RE{num}{int}{-sep=>',?'}                # match 1234567 or 1,234,567
          $RE{num}{int}{-sep=>'.'}{-group=>4}      # match 1.2345.6789

     Under `-keep':

    $1
          captures the entire number

    $2
          captures the optional sign number

    $3
          captures the complete set of digits

`$RE{num}{real}{-base}{-radix}{-places}{-sep}{-group}{-expon}'
     Returns a pattern that matches a floating-point number.

     If `-base=*N*' is specified, the number is assumed to be in that base
     (with A..Z representing the digits for 11..36). By default, the base
     is 10.

     If `-radix=*P*' is specified, the pattern P is used as the radix
     point for the number (i.e. the "decimal point" in base 10). The
     default is `qr/[.]/'.

     If `-places=*N*' is specified, the number is assumed to have exactly
     N places after the radix point.  If `-places=*M,N*' is specified, the
     number is assumed to have between M and N places after the radix
     point.  By default, the number of places is unrestricted.

     If `-sep=*P*' specified, the pattern P is required as a grouping
     marker within the pre-radix section of the number. By default, no
     separator is allowed.

     If `-group=*N*' is specified, digits between grouping separators must
     be grouped in sequences of exactly N characters. The default value of
     N is 3.

     If `-expon=*P*' is specified, the pattern P is used as the exponential
     marker.  The default value of P is C<qr/[Ee]/.

     For example:

          $RE{num}{real}                  # matches 123.456 or -0.1234567
          $RE{num}{real}{-places=2}       # matches 123.45 or -0.12
          $RE{num}{real}{-places='0,3'}   # matches 123.456 or 0 or 9.8
          $RE{num}{real}{-sep=>'[,.]?'}   # matches 123,456 or 123.456
          $RE{num}{real}{-base=>3'}       # matches 121.102

     Under `-keep':

    $1
          captures the entire match

    $2
          captures the optional sign

    $3
          captures the complete mantissa

    $4
          captures the whole number portion of the mantissa

    $5
          captures the radix point

    $6
          captures the fractional portion of the mantissa

    $7
          captures the optional exponent marker

    $8
          captures the entire exponent value

    $9
          captures the optional sign of the exponent

    $10
          captures the digits of the exponent

`$RE{num}{dec}{-radix}{-places}{-sep}{-group}{-expon}'
     A synonym for `$RE{num}{real}{-base='10}{...}>

`$RE{num}{oct}{-radix}{-places}{-sep}{-group}{-expon}'
     A synonym for `$RE{num}{real}{-base='8}{...}>

`$RE{num}{bin}{-radix}{-places}{-sep}{-group}{-expon}'
     A synonym for `$RE{num}{real}{-base='2}{...}>

`$RE{num}{hex}{-radix}{-places}{-sep}{-group}{-expon}'
     A synonym for `$RE{num}{real}{-base='16}{...}>

`$RE{comment}{*language*}'
     A comment string in the nominated language.

     Available languages are:

          $RE{comment}{C}
          $RE{comment}{C++}
          $RE{comment}{shell}
          $RE{comment}{Perl}

     Under `-keep':

    $1
          captures the entire match

    $2
          captures the opening comment marker (except for
          `$RE{comment}{C++}')

    $3
          captures the contents of the comment (except for
          `$RE{comment}{C++}')

    $4
          captures the  closing comment marker (except for
          `$RE{comment}{C++}')

$RE{profanity}
     Returns a pattern matching words - such as Carlin's "big seven" - that
     are most likely to give offense. Note that correct anatomical terms
     are deliberately not included in the list.

     Under `-keep':

    $1
          captures the entire word

`$RE{profanity}{contextual}'
     Returns a pattern matching words that are likely to give offense when
     used in specific contexts, but which also have genuinely
     non-offensive meanings.

     Under `-keep':

    $1
          captures the entire word

`$RE{ws}{crop}'
     Returns a pattern that identifies leading or trailing whitespace.

     For example:

          $str =~ s/$RE{ws}{crop}//g;     # Delete surrounding whitespace

     The call:

          $RE{ws}{crop}->subs($str);

     is optimized (but probably still slower than doing the s///g
     explicitly).

     This pattern does not capture under `-keep'.

`$RE{delimited}{-delim}{-esc}'
     Returns a pattern that matches a single-character-delimited substring,
     with optional internal escaping of the delimiter.

     When `-delim=*S*' is specified, each character in the sequence S is a
     possible delimiter. There is no default delimiter, so this flag must
     always be specified.

     If `-esc=*S*' is specified, each character in the sequence S is the
     delimiter for the corresponding character in the `-delim=*S*' list.
     The default escape is backslash.

     For example:

          $RE{delimited}{-delim=>'"'}             # match "a \" delimited string"
          $RE{delimited}{-delim=>'"'}{-esc=>'"'}  # match "a "" delimited string"
          $RE{delimited}{-delim=>'/'}             # match /a \/ delimited string/
          $RE{delimited}{-delim=>q{'"}}           # match "string" or 'string'

     Under `-keep':

    $1
          captures the entire match

    $2
          captures the opening delimiter (provided only one delimiter was
          specified)

    $3
          captures delimited portion of the string (provided only one
          delimiter was specified)

    $4
          captures the closing delimiter (provided only one delimiter was
          specified)

$RE{quoted}{-esc}
     A synonym for `$RE{delimited}{q{-delim='"`}{...}}'

`$RE{list}{-pat}{-sep}{-lastsep}'
     Returns a pattern matching a list of (at least two) substrings.

     If `-pat=*P*' is specified, it defines the pattern for each substring
     in the list. By default, P is `qr/.*?/'.

     If `-sep=*P*' is specified, it defines the pattern P to be used as a
     separator between each pair of substrings in the list, except the
     final two.  By default P is `qr/\s*,\s*/'.

     If `-lastsep=*P*' is specified, it defines the pattern P to be used as
     a separator between the final two substrings in the list.  By default
     P is the same as the pattern specified by the `-sep' flag.

     For example:

          $RE{list}{-pat=>'\w+'}                # match a list of word chars
          $RE{list}{-pat=>$RE{num}{real}}       # match a list of numbers
          $RE{list}{-sep=>"\t"}                 # match a tab-separated list
          $RE{list}{-lastsep=>',\s+and\s+'}     # match a proper English list

     Under `-keep':

    $1
          captures the entire list

    $2
          captures the last separator

`$RE{list}{conj}{-word=*PATTERN*}'
     An alias for `$RE{list}{-lastsep=''\s*,?\s*PATTERN\s*'}>

     If `-word' is not specified, the default pattern is `qr/and|or/'.

     For example:

          $RE{list}{conj}{-word=>'et'}             # match Jean, Paul, et Satre
          $RE{list}{conj}{-word=>'oder'}           # match Bonn, Koln oder Hamburg

`$RE{list}{and}'
     An alias for `$RE{list}{conj}{-word=''and'}>

`$RE{list}{or}'
     An alias for `$RE{list}{conj}{-word=''or'}>

`$RE{net}{IPv4}'
     Returns a pattern that matches a valid IP address in "dotted decimal"

     For this pattern and the next four, under `-keep':

    $1
          captures the entire match

    $2
          captures the first component of the address

    $3
          captures the second component of the address

    $4
          captures the third component of the address

    $5
          captures the final component of the address

`$RE{net}{IPv4}{dec}{-sep}'
     Returns a pattern that matches a valid IP address in "dotted decimal"

     If `-sep=*P*' is specified the pattern P is used as the separator.
     By default P is `qr/[.]/'.

`$RE{net}{IPv4}{hex}{-sep}'
     Returns a pattern that matches a valid IP address in "dotted
     hexadecimal"

     If `-sep=*P*' is specified the pattern P is used as the separator.
     By default P is `qr/[.]/'. `-sep='""> and `-sep='" "> are useful
     alternatives.

`$RE{net}{IPv4}{oct}{-sep}'
     Returns a pattern that matches a valid IP address in "dotted octal"

     If `-sep=*P*' is specified the pattern P is used as the separator.
     By default P is `qr/[.]/'.

`$RE{net}{IPv4}{bin}{-sep}'
     Returns a pattern that matches a valid IP address in "dotted binary"

     If `-sep=*P*' is specified the pattern P is used as the separator.
     By default P is `qr/[.]/'.

Forthcoming patterns and features
---------------------------------

   Future releases of the module will also provide patterns for the
following:

     * email addresses
     * HTML/XML tags
     * more numerical matchers,
     * mail headers (including multiline ones),
     * URLS (various genres)
     * telephone numbers of various countries
     * currency (universal 3 letter format, Latin-1, currency names)
     * dates
     * binary formats (e.g. UUencoded, MIMEd)

   If you have other patterns or pattern generators that you think would be
generally useful, please send them to the author - preferably as source
code using the pattern subroutine. Submissions that include a set of
tests, will be especially welcome.

DIAGNOSTICS
===========

`Can't export unknown subroutine %s'
     The subroutine-based interface didn't recognize the requested
     subroutine.  Often caused by a spelling mistake or an incompletely
     specified name.

          =item C<Can't create unknown regex: $RE{...}>

     Regexp::Common doesn't have a generator for the requested pattern.
     Often indicates a mispelt or missing parameter.

`Perl %f does not support the pattern $RE{...}. You need Perl %f or later'
     The requested pattern requires advanced regex features (e.g.
     recursion) that not available in your version of Perl. Time to
     upgrade.

`pattern() requires argument: name =' [ @list ]>
     Every user-defined pattern specification must have a name.

`pattern() requires argument: create =' $sub_ref_or_string>
     Every user-defined pattern specification must provide a pattern
     creation mechanism: either a pattern string or a reference to a
     subroutine that returns the pattern string.

`Base must be between 1 and 36'
     The `$RE{num}{real}{-base=''N'}> pattern uses the characters [0-9A-Z]
     to represent the digits of various bases. Hence it only produces
     regular expressions for bases up to hexatricensimal.

`Must specify delimiter in $RE{delimited}'
     The pattern has no default delimiter.  You need to write:
     `$RE{delimited}{-delim='X'}> for some character X

ACKNOWLEDGEMENTS
================

   Deepest thanks to the many people who have encouraged and contributed
to this project, especially: Elijah, Jarkko, Tom, Nat, Ed, and Vivek.

AUTHOR
======

   Damian Conway (damian@conway.org)

BUGS AND IRRITATIONS
====================

   Bound to be plenty.

   For a start, there are many common regexes missing.  Send them in!

COPYRIGHT
=========

     Copyright (c) 2001, Damian Conway. All Rights Reserved.
            This module is free software. It may be used, redistributed
           and/or modified under the terms of the Perl Artistic License
        (see http://www.perl.com/perl/misc/Artistic.html)

Shell-like regular expressions
******************************

NAME
====

   Regexp::Shellish - Shell-like regular expressions

SYNOPSIS
========

     use Regexp::Shellish qw( :all ) ;

     $re = compile_shellish( 'a/c*d' ) ;

     ## This next one's like 'a*d' except that it'll
     ## match 'a/d'.
     $re = compile_shellish( 'a**d' ) ;

     ## And here '**' won't match 'a/d', but behaves
     ## like 'a*d', except for the possibility of high
     ## cpu time consumption.
     $re = compile_shellish( 'a**d', { star_star => 0 } ) ;

     ## The next two result in identical $re1 and $re2.
     ## The second is a noop so that Regexp references can
     ## be easily accomodated.
     $re1 = compile_shellish( 'a{b,c}d' ) ;
     $re2 = compile_shellish( qr/\A(?:a(?:b|c)d)\Z/ ) ;

     @matches = shellish_glob( $re, @possibilities ) ;

DESCRIPTION
===========

   Provides shell-like regular expressions.  The wildcards provided are
'?', '*' and '**', where '**' is like '*' but matches '/'.  See `' in this
node for details.

   Case sensitivity and treatment of conreucts like '**', '(a*b)', and
'{a,b,c}' can be controlled.

compile_shellish
     Compiles a string containing a shellish regular expression a,
     returning a Regexp reference.  Regexp references passed in are passed
     through unmolested.

     Here are the transformation rules:

          '*'  => '[^/]*'
          '?'  => '.'
          '**' => '.*'               ## unless { star_star => 0 }

          '('  => '('                ## unless { parens => 0 }
          ')'  => ')'                ## unless { parens => 0 }

          '{a,b,c}' => '(?:a|b|c)'   ## unless { braces => 0 }

          '\a' => 'a'                ## These are de-escaped and
          '\*' => '\*'               ## passed to quotemeta()

     The wildcards treat newlines as normal characters.

     Parens group in to $1..$n, since they are passed through unmolested
     (unless option parens => 0 is passed).  This is useless when using
     glob_shellish(), though.

     The final parameter can be a hash reference containing options:

          compile_shellish(
             '**',
             {
                anchors        => 0,   ## Doesn't put ^ and $ around the
          	                        ## resulting regexp
                case_sensitive => 0,   ## Make case insensitive
                star_star      => 0,   ## '**' is now two '*' wildcards
          	 parens         => 0,   ## '(', ')' are now regular chars
          	 braces         => 0,   ## '{', '}' are now regular chars
             }
          ) ;

     No option affects Regexps passed through.

shellish_glob
     Pass a regular expression and a list of possible values, get back a
     list of matching values.

          my @matches = shellish_glob( '*/*', @possibilities ) ;
          my @matches = shellish_glob( '*/*', @possibilities, %options ) ;

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

simple implementation of the Win32 registry in Unix
***************************************************

NAME
====

   Register - simple implementation of the Win32 registry in Unix

SYNOPSIS
========

     use Register;

DESCRIPTION
===========

   Register is simply the main package to run registry option you can see :

     * Register::System

AUTHOR
======

     Vecchio Fabrizio <jacote@tiscalinet.in>

SEE ALSO
========

   See Register/System,DBD/CSV,`DBI'
in this node

Implementation of the windows ini like structure
************************************************

NAME
====

   Register::Generic - Implementation of the windows ini like structure

SYNOPSIS
========

     use Register;

     $genreg=new Register::Generic (
     		'regpath' => "/home/myprog",
     		'regname' => "INITFILE"
     	);

     $genreg->savesettings("SECTION","KEY","VALUE");
     $value=$genreg->getsettings("SECTION","KEY");
     $sections=$genreg->getsections;
     $genreg->deletesettings(,"SECTION","KEY");
     $genreg->deletesection("SECTION");

DESCRIPTION
===========

   The Register::Generic module permit to create an ini file like Windows
for save generic information about your program.  With the use of CSV dbd
, the file created is readable by DBI without problem.  Here CSV table
specifics:

     FIELD_NAME		FIELD_TYPE
     ----------------------------------
     R_SECTION		CHAR
     R_KEY			CHAR
     R_VALUE			CHAR

FUNCTIONS
=========

Function <new>
--------------

   The <new> statament create the Register::Generic object and return the
reference to him.

     $genreg=new Register::System (
     		'regpath' => "/home/myprog",
     		'regname' => "INIFILE"
     	);

   Parameter :

     regpath		specify the path where new statament search for
     		file.

     regname		specify the name of the file to use.

   Finaly if regpath don't exist the program return an error message at
compile time, if the register don't exist it is maked.

Function <savesettings>
-----------------------

   The savesettings function , save the value argument in the key of the
section of the program.

     $genreg->savesettings("SECTION","KEY","VALUE");

   If the key don't exist it make (it make also section without specify
befor), else if key already exist and value is different from previous it
update value.

Function <getsettings>
----------------------

   The getsettings function retrieve the value of the specified key.

     $value=$genreg->getsettings("SECTION","KEY");

Function <getsections>
----------------------

   The getsections function retrieve the section in the ini file and
return an array.

     @sections=$genreg->getsections;

Function <deletesettings>
-------------------------

   The deletesettings function delete the entry key specified.

     $genreg->deletesettings("SECTION","KEY");

Function <deletesection>
------------------------

   The deletesection function delete the entry section specified.

     $genreg->deletesection("SECTION");

AUTHOR
======

     Vecchio Fabrizio <jacote@tiscalinet.in>

SEE ALSO
========

   See Register,DBD/CSV,`DBI' in this node

Implementation of the Win32 registry in Unix
********************************************

NAME
====

   Register::System - Implementation of the Win32 registry in Unix

SYNOPSIS
========

     use Register;

     $sysreg=new Register::System (
     		'regpath' => "/etc",
     		'regname' => "SYSREG"
     	);

     $sysreg->savesettings("APPLICATION","SECTION","KEY","VALUE");
     $value=$sysreg->getsettings("APPLICATION","SECTION","KEY");
     $sysreg->deletesettings("APPLICATION","SECTION","KEY");
     $sysreg->deletesection("APPLICATION","SECTION");

DESCRIPTION
===========

   The Register::System module permit to create a registry file like
Windows for save global information about your program.  With the use of
CSV dbd , the file created is readable by DBI without problem.  Here CSV
table specifics:

     FIELD_NAME		FIELD_TYPE
     ----------------------------------
     R_APPLICATION		CHAR
     R_SECTION		CHAR
     R_KEY			CHAR
     R_VALUE			CHAR

FUNCTIONS
=========

Function <new>
--------------

   The <new> statament create the Register::System object and return the
reference to him.

     $sysreg=new Register::System (
     		'regpath' => "/etc",
     		'regname' => "SYSREG"
     	);

   Parameter :

     regpath		specify the path where new statament search for
     		registers.

     regname		specify the name of the register to use.

   Finaly if regpath don't exist the program return an error message at
compile time, if the register don't exist it is maked.

Function <savesettings>
-----------------------

   The savesettings function , save the value argument in the key of the
section of the program.

     $sysreg->savesettings("APPLICATION","SECTION","KEY","VALUE");

   If the key don't exist it make (it make also application and section
without specify befor), else if key already exist and value is different
from previous it update value.

Function <getsettings>
----------------------

   The getsettings function retrieve the value of the specified key.

     $value=$sysreg->getsettings("APPLICATION","SECTION","KEY");

Function <deletesettings>
-------------------------

   The deletesettings function delete the entry key specified.

     $sysreg->deletesettings("APPLICATION","SECTION","KEY");

Function <deletesection>
------------------------

   The deletesection function delete the entry section specified.

     $sysreg->deletesection("APPLICATION","SECTION");

AUTHOR
======

     Vecchio Fabrizio <jacote@tiscalinet.in>

SEE ALSO
========

   See Register,DBD/CSV,`DBI' in this node

Generate tracebacks and create and install die() and  warn() handlers.
**********************************************************************

NAME
====

   Religion - Generate tracebacks and create and install die() and  warn()
handlers.

DESCRIPTION
===========

   This is a second go at a module to simplify installing die() and warn()
handlers, and to make such handlers easier to write and control.

   For most people, this just means that if use `use Religion;' then you'll
get noticably better error reporting from warn() and die(). This is
especially useful if you are using eval().

   Religion provides four classes, WarnHandler, DieHandler,
WarnPreHandler, and DiePreHandler, that when you construct them return
closures that can be stored in variables that in turn get invoked by
$SIG{__DIE__} and $SIG{__WARN__}. Note that if Religion is in use, you
should not modify $SIG{__DIE__} or $SIG{__WARN__}, unless you are careful
about invoking chaining to the old handler.

   Religion also provides a TraceBack function, which is used by a
DieHandler after you `die()' to give a better handle on the current scope
of your situation, and provide information about where you were, which
might influence where you want to go next, either returning back to where
you were, or going on to the very last. [Sorry - Ed.]

   See below for usage and examples.

USAGE
=====

DieHandler SUB
     Invoke like this:

          $Die::Handler = new DieHandler sub {
          	#...
          };

     where `#...' contains your handler code. Your handler will receive the
     following arguments:

          $message, $full_message, $level, $eval,
          		    $iline, $ifile, $oline, $ofile, $oscope

     `$message' is the message provided to die(). Note that the default
     addition of " at FILE line LINE.\n" will have been stripped off if it
     was present.  If you want to add such a message back on, feel free to
     do so with $iline and $ifile.

     `$full_message) is the message with a scope message added on if there
     was no newline at the end of C<$message'. Currently, this is not the
     original message that die() tacked on, but something along the lines
     of " at line 3 of the eval at line 4 of Foo.pl\n".

     `$eval' is non-zero if the die() was invoked inside an eval.

     The rest of the arguments are explained in the source for
     Religion::TraceBack. Yes, I need to document these, but not just now,
     for they are a pain to explain.

     Whenever you install a DieHandler, it will automatically store the
     current value of $Die::Handler so it can chain to it. If you want to
     install a handler only temporarily, use local().

     If your handler returns data using return or by falling off the end,
     then the items returns will be used to fill back in the argument
     list, and the next handler in the chain, if any, will be invoked.
     *Don't fall off the end if you don't want to change the error
     message.*

     If your handler exits using last, then no further handlers will be
     invoked, and the program will die immediatly.

     If your handler exits using next, then the next handler in the chain
     will be invoked directly, without giving you a chance to change its
     arguments as you could if you used return.

     If your handler invokes die(), then die() will proceed as if no
     handlers were installed. If you are inside an eval, then it will exit
     to the scope enclosing the eval, otherwise it will exit the program.

WarnHandler SUB
     Invoke like this:

          $Warn::Handler = new WarnHandler sub {
          	#...
          };

          For the rest of its explanation, see DieHandler, and subsitute warn() for
          die(). Note that once the last DieHandler completes (or C<last> is invoked)
          then execution will return to the code that invoked warn().

DiePreHandler SUB
     Invoke like this:

          $Die::PreHandler = new DiePreHandler sub {
          	#...
          };

          This works identically to $Die::Handler, except that it forms a separate chain
          that is invoked I<before> the DieHandler chain. Since you can use C<last> to
          abort all the handlers and die immediately, or change the messages or scope
          details, this can be useful for modifying data that all future handlers will
          see, or to dispose of some messages from further handling.

     This is even more useful in $Warn::PreHandler, since you can just
     throw away warnings that you *know* aren't needed.

WarnPreHandler SUB
     Invoke like this:

          $Warn::PreHandler = new WarnPreHandler sub {
          	#...
          };

          This works identically to $Warn::Handler, except that it forms a separate
          chain that is invoked I<before> the WarnHandler chain. Since you can use
          C<last> to abort all the handlers and return to the program, or change
          the messages or scope details, this can be useful for modifying data that
          all future handlers will see, or to dispose of some messages.

     This is very useful, since you can just throw away warnings that you
     *know* aren't needed.

EXAMPLES
========

A dialog error message:
          $Die::Handler = new DieHandler sub {
             my($msg,$fmsg,$level,$eval) = @_;
             if($eval) {
          		# if we are in an eval, skip to the next handler
          		next;
          	} else {
          		# show a message box describing the error.
          	 	print "ShowMessageBox $fmsg";

          	 	# force the program to exit
          	 	exit 0;
          	 	next;
          	}
          };

A handler that changes die() messages back to the original format
          local($Die::Handler) = new DieHandler sub {
             my($msg,$fmsg,$level,@trace) = @_;

          $fmsg = $msg . ((substr($msg,-1,1) ne "\n") ?
          			 " at $trace[2] line $trace[1].\n"
          			 : "");
          return ($msg,$fmsg);
           };

A warn handler that does nothing.
          $Warn::Handler = new WarnHandler sub {next;};

A warn prehandler that throws away a warning.
          $Warn::PreHandler = new WarnPreHandler sub {
          	my($msg,$fmsg,$level,$eval) = @_;
          	if($msg =~ /Use of uninitialized/) {
          		last;
          	}
          	next;
          };

Interface to Remedy's Action Request (Version 1.2)
**************************************************

NAME
====

   Remedy::Ar - Interface to Remedy's Action Request (Version 1.2)

DESCRIPTION
===========

Terminology
-----------

   Action Request uses terminology which may not be familiar to some
people.  Action Request can be viewed as graphical interface to a RDB
(although flat files can also be used at the backend).  A schema is
roughly equivalent to a table in other database terminology.  In the
graphical interface only fields from one schema can be present (although
it is possible to fill some fields from other schema.  An entry is
equivalent to a record.

Data structures
---------------

$control
     This is a private tag which is used to keep track of multiple
     connections.  The newcontrol() returns a new $control tag, which can
     then be used for all other operations.

$schema
     The name of a schema to operate on.

$server
     The name of a server to connect to.

$entryId
     A unique string representing an individual entry.  Once you have an
     $entryId, you can use it with GetEntry to retrieve detailed
     information about the record.

$fieldList
     A $fieldList is a reference to an associative array containing field
     name/contents pairs.  The field name used is the label displayed for
     the schema, using the default display tag.

Entry Operations
----------------

$entryId = CreateEntry($control, $schema, $fieldList)
     Adds a new entry to the specified schema.

     (Not Yet Implemented)

DeleteEntry($control, $schema, $entryId)
     Removes an entry from the specified schema.  This action requires
     administrator access.

     (Not Yet Implemented)

$fieldList = GetEntry($control, $schema, $entryId)
     Returns all fields from the entry associated with $entryId in $schema.

SetEntry
     (Not Yet Implemented)

GetListEntry($control, $schema, $qualifier, $maxRetrieve)
MergeEntry
     (Not Yet Implemented)

Schema Operations
-----------------

CreateSchema
     (Not Yet Implemented)

DeleteSchema
     (Not Yet Implemented)

GetSchema(control, schema)
SetSchema
     (Not Yet Implemented)

GetListSchema(control, changedSince)
Field Operations
----------------

CreateField
     (Not Yet Implemented)

DeleteField
     (Not Yet Implemented)

GetField(control, schema, fieldId)
SetField
     (Not Yet Implemented)

GetListField(control, schema, changedSince)
Menu Operations
---------------

CreateCharMenu
     (Not Yet Implemented)

DeleteCharMenu
     (Not Yet Implemented)

ExpandCharMenu
     (Not Yet Implemented)

GetCharMenu
     (Not Yet Implemented)

SetCharMenu
     (Not Yet Implemented)

GetListCharMenu
     (Not Yet Implemented)

Filter Operations
-----------------

CreateFilter
     (Not Yet Implemented)

DeleteFilter
     (Not Yet Implemented)

GetFilter
     (Not Yet Implemented)

SetFilter
     (Not Yet Implemented)

GetListFilter
     (Not Yet Implemented)

Active Link Operations
----------------------

CreateActiveLink
     (Not Yet Implemented)

DeleteActiveLink
     (Not Yet Implemented)

GetActiveLink
     (Not Yet Implemented)

SetActiveLink
     (Not Yet Implemented)

GetListActiveLink
     (Not Yet Implemented)

AdminExt Operations
-------------------

CreateAdminExt
     (Not Yet Implemented)

DeleteAdminExt
     (Not Yet Implemented)

GetAdminExt
     (Not Yet Implemented)

SetAdminExt
     (Not Yet Implemented)

GetListAdminExt
     (Not Yet Implemented)

ExecuteAdminExt
     (Not Yet Implemented)

Miscellaneous Operations
------------------------

VerifyUser(control)
GetListServer()
Export
     (Not Yet Implemented)

Import
     (Not Yet Implemented)

GetListGroup(control)
GetServerInfo
     (Not Yet Implemented)

SetServerInfo
     (Not Yet Implemented)

DecodeStatusHistory
     (Not Yet Implemented)

DecodeDiary
     (Not Yet Implemented)

LoadARQualifierStruct(control, schema, qualString)
Miscellaneous Support Functions (Not part of the AR API)
--------------------------------------------------------

newcontrol()
printcontrol(control)
setuser(control, user, password)
setlanguage(control, language)
setserver(control, server)
AUTHOR
======

   Copyright (c) 1995 Rik Harris (*rik.harris@fulcrum.com.au*). All rights
reserved.  This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

   The Ar perl extension, and this documentation were derived from the
information found in the Action Request include files, and the Action
Request System Programmer's Guide (Remedy Part Number: AXA-120-DA4-01).

   Action Request System and AR System are tracemarks of Remedy
Corporation.

A RenderMan binding as a Perl 5.6 module
****************************************

NAME
====

   RenderMan - A RenderMan binding as a Perl 5.6 module

SYNOPSIS
========

     use RenderMan;

DESCRIPTION
===========

   This RenderMan module implements a Perl 5.6 binding for the BMRT client
library (libribout).  It fully supports the client library.  Therefore,
this module has the following limitations: Error Handling callbacks are
not implemented, Filter function callbacks are not implemented, and the
TransformPoints function does nothing.  Also, Blobby is not yet supported
by BMRT 2.5.0.8.

   The full RenderMan specification is way beyond the scope of this man
page.  Please refer to the documents below for more information about
RenderMan.  The Perl binding is identical to the C binding except a few
minor points: All "parameterlist"s are passed as a reference to a hash
(i.e. \%params).  Anywhere that a function's arguments can be terminated
by RI_NULL, you can simply choose to not include that RI_NULL argument,
which is incredibly nice.

   All array, matrix, and basis types are single-dimension arrays of
doubles in this Perl binding.  The order for 2-dimension types is
first-row followed by second-row, etc.

   You will typically want to run your RenderMan Perl script and pipe the
results into any RenderMan-compliant renderer, such as "rgl", "rendribv",
or "rendrib", which all come with the excellent BMRT backage by Larry
Gritz.

   If using the WinNT version of BMRT, you can specify a filename, "rgl"
or "rendrib" as the argument to Begin(); and the output will be sent to a
file or automatically piped to "rgl" or "rendrib" since the piping
mechanism (and general functionality) of WinNT's command line parser is,
uh, limited.

AUTHOR
======

   Glenn M. Lewis, mailto:glenn@gmlewis.com, http://www.gmlewis.com/

SEE ALSO
========

   Blue Moon Rendering Toolkit (BMRT) by Larry Gritz.  http://www.bmrt.org/

   The RenderMan Companion: A Programmer's Guide to Realistic Computer
Graphics by Steve Upstill, published by Addison Wesley.  ISBN
0-201-50868-0.

   Advanced RenderMan: Creating CGI for Motion Pictures by Anthony A.
Apodaca and Larry Gritz, published by Morgan Kaufmann Publishers ISBN
1-55860-618-1

   The RenderMan Interface Specification, Version 3.2, July 2000, Pixar.
http://www.pixar.com/products/rendermandocs/toolkit/Toolkit/

   RenderMan is a registered trademark of Pixar.  http://www.pixar.com/

handling application defaults in Perl.
**************************************

NAME
====

   Resources - handling application defaults in Perl.

SYNOPSIS
========

     use Resources;

     $res = new Resources;
     $res = new Resources "resfile";

DESCRIPTION
===========

   Resources are a way to specify information of interest to program or
packages.

   Applications use resource files to specify and document the values of
quantities or attributes of interest.

   Resources can be loaded from or saved to resource files. Methods are
provided to search, modify and create resources.

   Packages use resources to hardwire in their code the default values for
their attributes, along with documentation for the attibutes themselves.

   Packages inherit resources when subclassed, and the resource names are
updated dynamically to reflect a class hierarchy.

   Methods are provided for interactive resource inspection and editing.

1. Resource inheritance
-----------------------

   Package attributes are inherited from base and member classes, their
names are dynamically updated to reflect the inheritance, and values
specified in derived/container classes override those inherited from
base/member classes.

   More precisely, there a few rules governing the inheritance of resource
names and values, and they will be explained by way of examples.

   As far as resource names, the rules are:

Base class
     If Vehicle has a "speed" property, then it can use a resource named
     "vehicle.speed" to specify its default value.

Derived class
     If Car *is a* Vehicle, then Car has a "car.speed" resource
     automagically defined by inheritance from the base class.

Container class
     If Car *has a* member object called Tire, and Tire has a
     "tire.pressure" resource, then Car inherits a "car.tire.pressure"
     resource from the member class.

Application class
     All resources of Car objects used by a program named "race" have the
     prefix "race." prepended to their names, e.g. "race.car.speed",
     "race.car.tire.pressure", etc.

   With regard to assigning values to resources, the rules are:

Specification in a file
     Resources specified in a resource file always override hardcoded
     resources (with the exception of "hidden" resources, see below).

Inheritance
     Resources defined in a derived class (like Car) override those
     specified in a base class. Likewise, resources defined in a container
     class override those specified in the members.

     In the above example, a default value for "car.speed" in Car
     overrides the value of "vehicle.speed" in any Car object, otherwise
     "car.speed" assumes the value of "vehicle.speed".  Same for
     "car.tire.pressure".

2. Resource Files.
------------------

   A resource specification in a (text) resource file is a line of the
form:

     sequence: value

   There may be any number of whitespaces between the name and the colon
character, and between the colon and the value.

sequence can have four forms:
          (1) word

     A word not containing whitespaces, colons (':'), dots ('.') or
     asterisks ('*'), nor starting with an underscore ('_').

     Or, recursively:

          (2) word.sequence
          (3) word*sequence
          (4) *sequence

     The asterisks in a resource name act as wildcards, matching any
     sequence of characters.

     For cases (3) or (4) the word must be or match the current application
     class, otherwise the resource specification is silently ignored (this
     means that an applications loads from a file only its own resources,
     and those whose application class is a wildcard).

     No distinction is made between uppercase and lowercase letters.

value can be:
     An unadorned word or a quoted sequence of whitespace-separated words.
     Both single (' ') and double quotes quotes (" ") are allowed, and
     they must be paired.

     Any constant scalar constructor in Perl, including anon references to
     constant arrays or hashes.

     The special words *yes*, *true*, no, false (case insensitive) are
     treated as boolean resources and converted 1 and 0, unless they are
     quoted.

   Examples of valid resource specifications:

     car*brand       : Ferrari    # A word.
     car.price       : 200K       # Another word
     car.name        : '312 BB'   # A quoted sentence
     car*runs*alot   : yes        # A boolean, converted to 1.
     car*noise*lotsa : 'yes'      # yes, taken verbatim
     car.size        : [1, [2, 3]]           # An anon array.
     car.lett        : {"P"=>1, "Q"=>[2, 3]} # An anon hash.

   Examples of illegal resource names:

     car pedal    # Whitespace in the name.
     .carpedal    # Leading dot in name.
     car._pedal   # Leading underscore in _dog.
     carpedal*    # Trailing asterisk.
     carpedal.    # Trailing dot.

   A resource file may contain comments: anything from a hash ('#')
character to the end of a line is ignored, unless the hash character
appears inside a quoted value string.

   Resource specifications may be split across successive lines, by
terminating the split lines with a backslash, as per cpp(1).

3. The Resources hash
---------------------

   A non-my hash named %Resources can be used to specify the default
values for the attributes of a package in its source code, along with
documentation for the attributes themselves. The documentation itself is
"dynamical" (as opposed to the static, pod-like variety) in that it
follows a class hyerarchy and is suitable for interactive display and
editing.

   The %Resources hash is just a hash of

     $Name => [$Value, $Doc]

   things. Each hash key *$Name* is a resource name in the above sequence
form. Each hash value is a reference to an anon array *[$Value, $Doc]*,
with *$Doc* being an optional resource documentation.

   The resource $Name *cannot* contain wildcard ('*') or colon (':')
characters, nor start or end with a dot ('.'). Also, it must not be
prefixed with the package name (since this is automatically prepended by
the merge method, see below). Names starting with an underscore ('_')
character are special in that they define "hidden" resources. These may
not be specified in resource files, nor dynamically viewed/edited: they
come handy to specify global parameters when you do not want to use global
application-wide variables, and/or want to take advantage of the
inheritance mechanism.

   The resource $Value can be any constant scalar Perl constructor,
including references to arrays and/or hashes of constants (or references
thereof). Boolean values must be specified as 1 or 0.

   The resource documentation is a just string of any length: it will be
appropriately broken into lines for visualization purposes. It can also be
missing, in which case an inherited documentation is used (if any exists,
see the merge method below).

   The content of a resource hash is registered in a global Resource
object using the merge method.

   Here is an example of deafults specification for a package.

     package Car;
     @ISA = qw( Vehicle );
     use vars qw( %Resources );

     %Resources = (
         brand    => ["FIAT", "The carmaker"],
         noise    => ["Ashtmatic", "Auditory feeling"],
         sucks    => [1, "Is it any good?"],
     	 nuts     => [ { on => 2, off => [3, 5] }, "Spares"],
     	 '_ghost' => [0, "Hidden. Mr. Invisible"]
     	 'tire.flat' => [0],
     );

   The last line overrides a default in member class Tire. The
corresponding doc string is supposedly in the source of that class. The
last two hash keys are quoted because of the non alphanumeric characters
in them.

4. Objects and resources
------------------------

   The recommended way to use resources with Perl objects is to pass a
Resource object to the "new" method of a package.  The method itself will
merge the passed resources with the package defaults, and the passed
resource will override the defaults where needed.

   Resource inheritance via subclassing is then easily achieved via the
merge method, as shown in the EXAMPLES section.

5. Methods in class Resources
-----------------------------

5.1. Creation and initialization
--------------------------------

*new Resources ($resfile);*
     Creates a new resource database, initialized with the defaults for
     class Resources (see below for a list of them).

     If a nonempty file name is specified in $resfile, it initializes the
     object with the content of the so named resource file. For safe (non
     overwriting) loading, see the load method below.

     If the special file name "_RES_NODEFAULTS" is specified, the object
     is created completely empty, with not even the Resources class
     defaults in it.

     Returns the new object, or undef in case of error.

*load($resfile, $nonew);*
     Loads resources from a file named $resfile into a resource database.

     The $nonew argument controls whether loading of non already defined
     resurces is allowed. If it is true, safe loading is performed:
     attempting to load non-wildcarded resource names that do not match
     those already present in the database causes an error. This can be
     useful if you want to make sure that only pre-defined resources (for
     which you presumably have hardwired defaults) are loaded. It can be a
     safety net against typos in a resource file.

     Use is made of *Safe::reval* to parse values specified through Perl
     constructors (only constants, anon hashes and anon arrays are
     allowed).

     Returns 1 if ok, 0 if error.

*merge($class, @memberclasses);*
     Merges the %Resources hash of the package defining $class with those
     of its @memberclasses, writing the result in the resource database.

     The merging reflects the resource inheritance explained above: the
     %Resources of all base classes and member classes of $class are
     inherited along the way. Eventually all these resources have their
     names prefixed with the name of the package in which $class is
     defined (lowercased and stripped of all foo::bar:: prefixes), and
     with the application class as well.

     In the above example, the defaults of a Car object will be renamed,
     after merging as:

          car.brand, car.noise, ...,
          car.tire.flat

     and for a Civic object, where Civic is a (i.e. ISA) Car, they will be
     translated instead as

          civic.brand, civic.noise, ...,
          civic.tire.flat

     Finally, the application name ($0, a.k.a $PROGRAM_NAME in English) is
     prepended to all resource names, so, if the above Civic package is
     used by a Perl script named "ilove.pl", the final names after merging
     are

          ilove.civic.brand, ilove.civic.noise, ...,
          ilove.civic.tire.flat

     The new names are the ones to use when accessing these resources by
     name.

     The resource values are inherited accoring to the rules previously
     indicated, hence with resource files having priority over hardcoded
     defaults, nnd derived or container classes over base or member
     classes.

     Returns 1 if for success, otherwise 0.

5.2. Looking up resources
-------------------------

   The values and documentation strings stored in a Resource object can be
accessed by specifying their names in three basic ways:

directly ("byname" methods)
     As in "my.nice.cosy.couch" .

by a pattern ("bypattern" methods)
     As in "m??nice.*" .

hierarchically ("byclass" methods)
     If class Nice *is a* Cosy, then asking for "couch" in package Cosy
     gets you the value/doc of "my.couch". If, instead, Nice *has a* Cosy
     member, that the method gets you "my.nice.cosy.couch". This behaviour
     is essential for the proper initialization of subclassed and member
     packages, as explained in detail below.

   It is also possible to retrieve the whole content of a resource database
("names" and "each" methods)

   Note that all the resource lookup methods return named (non
"wildcarded") resources only. Wildcarded resources (i.e. those specified
in resource files, and whose names contain one or more '*') are best
thought as placeholders, to be used when the value of an actual named
resource is set.

   For example, a line in a resource file like

     *background : yellow

   fixes to yellow the color of all resources whose name ends with
"background".  However, your actual packages will never worry about unless
they really need a background. In this case they either have a
"background" resource in their defaults hash, or subclass a package that
has one.

valbyname($name);
     Retrieves the value of a named resource from a Resource database. The
     $name argument is a string containing a resource name with no
     wildcards.

     Returns the undefined value if no such resource is defined.

docbyname($name);
     Retrieves the documentation string of a named resource from a Resource
     database. The $name argument is a string containing a resource name
     with no wildcards.

     Returns the undefined value if no such resource is defined.

bypattern($pattern);
     Retrieves the full names, values and documentation strings of all the
     named (non wildcarded) resources whose name matches the given
     $pattern. The pattern itself is string containing a Perl regular
     expression, not enclosed in slashes.

     Returns a new Resource object containing only the matching resources,
     or the undefined value if no matches are found.

valbypattern($pattern);
     Retrieves the full names and values of all named (non wildcarded)
     resources whose name matches the given pattern.

     Returns a new Resource object containing only names and values of the
     matching resources (i.e. with undefined doc strings), or the
     undefined value if no matches are found.

docbypattern($pattern);
     Retrieves the full names and documentation strings of all named (non
     wildcarded) resources whose name matches the given pattern.

     Returns a new Resource object containing only names and docs of the
     matching resources (i.e. with undefined resource values), or the
     undefined value if no matches are found.

*byclass($object, $suffix);*
     To properly initialize the attributes of a package via resources we
     need a way to know whether the package defaults (contained in its
     %Resources hash) have been overridden by a derived or container
     class.  For example, to set a field like $dog->{Weight} in a Dog
     object, we must know if this $dog is being subclassed by Poodle or
     Bulldog, or if it is a member of Family, since all these other
     classes might override whatever "weight" default is defined in the
     %Resources hash of Dog.pm.

     This information must of course be gathered at runtime: if you tried
     to name explicitly a resource like "family.dog.weight" inside Dog.pm
     all the OOP crowd would start booing at you. Your object would not be
     reusable anymore, being explicitly tied to a particular container
     class. After all we do use objects mainly because we want to easily
     reuse code...

     Enter the "by class" resource lookup methods: *byclass*, *valbyclass*
     and *docbyclass*.

     Given an $object and a resource $suffix (i.e. a resource name
     stripped of all container and derived class prefixes), the *byclass*
     method returns a 3 element list containing the name/value/doc of that
     resource in $object. The returned name will be fully qualified with
     all derived/container classes, up to the application class.

     For example, in a program called "bark", the statements

          $dog = new Dog ($res); # $res is a Resources database
          ($name,$value,$doc) = $res->byclass($dog, "weight");

     will set $name, $value and $doc equal to those of the
     "bark.poodle.weight" resource, if this Dog is subclassed by Poodle,
     and to those of "bark.family.dog.weight", if it is a member of Family
     instead.

     The passed name suffix must not contain wildcards nor dots.

     Be careful not to confuse the "byclass" with the "byname" and
     "bypattern" retrieval methods: they are used for two radically
     different goals. See the EXAMPLES section for more.

     Returns the empty list if no resources are found for the given suffix,
     or if the suffix is incorrect.

*namebyclass($obj, $suffix);*
     As the *byclass* method above, but returns just the resource name
     (i.e. the suffix with all the subclasses prepended).

*valbyclass($obj, $suffix);*
     As the *byclass* method above, but returns just the resource value.

docbyclass($suffix);
     As the *byclass* method above, but returns just the resource
     documentation.

each;
     Returns the next name/[value,doc] pair of the named (non wildcarded)
     resources in a resource database, exactly as the each Perl routine.

names;
     Returns a list of the names of all named (non-wildcarded) resources
     in a resource database, or undef if the databasee is empty.

5.3. Assigning and removing Resources
-------------------------------------

*put($name, $value, $doc);*
     Writes the value and doc of a resource in the database.  It is
     possible to specify an empty documentation string, but name and value
     must be defined.

     Wildcards ('*' characters) are allowed in the $name, but the $doc is
     ignored in this case (documentation is intended for single resources,
     not for sets of them).

     The value is written unchanged unless the resource database already
     contains a wildcarded resource whose name includes $name (foo*bar
     includes foo.bar, foo.baz.bar, etc.). In this case the value of the
     wildcarded resource overrides the passed $value.

     Returns 1 if ok, 0 if error.

removebyname($name);
     Removes the named (non wildcarded) resources from the database.

     Returns 1 if OK, 0 if the resource is not found in the database.

removebypattern($name);
     Removes from the database all resources (both named and wildcarded)
     whose name mathes $pattern. An exactly matching name must be
     specified for wildcarded resources (foo*bar to remove foo*bar).

     Returns the number of removed resources.

5.6. Viewing and editing resources.
-----------------------------------

view;
     Outputs the current content of a Resource object by piping to a pager
     program.

     The environment variable $ENV{RESPAGER}, the resource
     "resources.pager" and the environment variable $ENV{PAGER} are looked
     up, in this very order, to find the pager program. Defaults to
     */bin/more* if none of them is found.

     The output format is the same of a resource file, with the resource
     names alphabetically ordered, and the resource documentation strings
     written as comments.

     Returns 1 if ok, 0 if error.

edit($nonew);
     Provides dynamical resource editing of a Resource object via an
     external editor program. Only resource names and values can be edited
     (anyway, what is the point of editing a resource comment on the fly?).

     The environment variables $ENV{RESEDITOR} and the resource
     "resouces.editor", are looked up, in this very order, to find the
     editor program. Defaults to */bin/vi* if none is found.

     The editor buffer is initialized in the same format of a resource
     file, with the resource names alphabetically ordered, and the
     resource documentation strings written as comments. The temporary
     file specified by the "resources.tmpfil" resource is used to
     initialize the editor, or '/tmp/resedit<pid>' if that resource is
     undefined.

     When the editor is exited (after saving the buffer) the method
     attempts to reload the edited resources. If an error is found the
     initial object is left unchanged, a warning with the first offending
     line in the file is printed, and the method returns with undef.
     Controlled resource loading is obtained by specifying a true value
     for the $nonew argument (see load).

     If the loading is successful, a new (edited) resource object is
     returned, which can be assigned to the old one for replacement.

     After a successful edit, the value of the resource
     "resources.updates" (which is always defined to 0 whenever a new
     resource is created) is increased by one. This is meant to notify
     program the and/or packages of the resource change, so they can
     proceed accordingly if they wish.

5.5. Miscellaneous methods
--------------------------

write($filename);
     Outputs all resources of a resource database into a resource file
     (overwriting it).

     The resource documentation strings are normally written as comments,
     so the file itself is immediately available for resource loading.
     However, if the boolean resource "resources.writepod" is true, then
     the (non wildcarded) resources are output in POD format for your
     documentational pleasure.

     As usual in Perl, the filename can allo be of the form "|command", in
     which case the output is piped into "comma1nd".

     For resources whose value is a reference to an anon array or hash, it
     produces the appropriate constant Perl contructor by reverse parsing.
     The parser itself is available as a separate method named _parse (see
     package source for documentation).

     Returns 1 if ok, 0 if error.

5. Resources of Resources
-------------------------

   As you may have guessed at this point, the default configuration of this
package itself is defined by resources. The resource class is, of course,
"resources" (meaning that all the names have a leading "resources.").

   To prevent chaos, however, these resources cannot be subclassed. This
should not be a problem in normal applications, since the Resource package
itself is not meant to be subclassed, but to help building a hierarchy of
classes instead.

   The currently recognized resources, and their default values, are:

resources.appclass : "$PROGRAM_NAME"
     The application name of this Resource object.

resources.editor : /bin/vi
     Resource editor.

resources.mergeclass : true
     Boolean. True to merge with class inheritance.

resources.pager : /bin/more
     Resource pager.

resources.separator : ':'
     Pattern separating names from values in resource files.

resources.tmpfil : "
     Editor temporary file.

resources.updates : 0
     Number of resource updates.

resources.verbosity : 1
     True to print warnings.

resources.viewcols : 78
     Width of view/edit window.

resources.writepod : false
     Boolean. True if the write method should output in POD format.

EXAMPLES
========

   Here is an example of resource inheritance.  HotDog is a subclass of
Food, and has a member Wiener whichi happens to be a Food as well.

   The subclass has defaults for two resources defined by the base classes
("edible" and "wiener.mustard"), and their values will override the base
class defaults.

   Remember that after merging all resources names are prefixed with the
current class name.

     use Resources;
     package Food;
     %Resources = (
       edible => [1, "Can it be eaten."],
       tasty  => ["sort_of",  "D'ya like it?"],
     );

     sub new {
        my ($type, $res) = @_;
        $res || $res =  new Resources || (return undef);
        $res->merge($type) || die ("can't merge defaults");

        my $food= bless({}, type);
        $food->{Edible} = $res->valbyclass("edible");
        $food->{Tasty}  = $res->valbyclass("tasty");
        # Use valbyclass so a subclass like HotDog can change this by its
        # defaults.
     }

     # A Food method to say if it can be eaten.
     sub eatok {
        my $food=shift;
        return $food->{Edible};
     }

     package Wiener;
     @ISA = qw( Food );
     %Resources = (
          tasty => ["very"], # this overrides a base class default
          mustard => ["plenty", "How much yellow stuff?"],
     );
     # Nothing else: all methods are inherited from the base class.

     package HotDog;
     @ISA = qw( Food );

     %Resources = (
         edible    => [0],
         tasty     => ["yuck!"],
         'wiener.mustard' => ["none"], # To override member class default.
     );

     sub new {
        my ($type, $res) = @_;

        $res || $res =  new Resources || (return undef);
        $res->merge($type) || die ("can't merge defaults");

        my $hd = bless(new Food ($res), $type);
        $hd->{Wien} = new Wiener ($res);
        return $hd;
     }

     # All tastes of hotdog
     sub tastes {
        my $hd = shift;
        return ($hd->{Tasty}, $hd->{Wien}->{Tasty});
     }

     package main;
     # Whatever
     #
     $res = new Resources("AppDefltFile") || die;
     $snack = new HotDog($res);
     $gnam = $snack->eat();  # hotdog.edible overridees food.edible,
                             # so here $gnam equals 0

     @slurp = $snack->tastes()    # @slurp equals ("yuck!", "very")
                                  # the resources were overridden
                                  # by a subclass of HotDog , or
                                  # differently specified in
                                  # "AppDefltFile"

SEE ALSO
========

   Safe(3).

BUGS
====

   The underlying idea is to use a centralized resource database for the
whole application. This ensures uniformity of behaviour across kin
objects, but allow special characterizations only at the cost of
subclassing.

AUTHOR
======

     Francesco Callari <franco@cim.mcgill.ca>
     Artifical Perception Laboratory,
     Center for Intelligent Machines,
     McGill University.

     WWW: http://www.cim.mcgill.ca/~franco/Home.html

COPYRIGHT
=========

   Copyright 1996 Francesco Callari, McGill University

   Permission to use, copy, modify, and distribute this software and its
documentation for any purpose without fee 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 McGill not be used in advertising or
publicity pertaining to distribution of the software without specific,
written prior permission.  McGill makes no representations about the
suitability of this software for any purpose.  It is provided "as is"
without express or implied warranty.

   MCGILL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL
MCGILL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

A subclass of XML::Doctype
**************************

NAME
====

   RevML::Doctype - A subclass of XML::Doctype

SYNOPSIS
========

     use RevML::Doctype ;

     ## To use the highest RevML::Doctype module (e.g. RevML::Doctype::v0_22)
     $rmldt = RevML::Doctype->new ;

     ## To parse a .dtd file:
     $rmldt = RevML::Doctype->new( 'revml.dtd' );
     $rmldt = RevML::Doctype->new( DTD_FILE => 'revml.dtd' );

     ## To load a preparsed .pm file
     $rmldt = RevML::Doctype->new( 1.1 ) ;
     $rmldt = RevML::Doctype->new( VERSION => 1.1 ) ;

DESCRIPTION
===========

METHODS
=======

new
     Creates an instance.

save_as_pm
          $doctype->save_as_pm ;
          $doctype->save_as_pm( $out_spec ) ;

     Outspec is a module name.  'RevML::Doctype::vNNN' is assumed if no
     outspec is provided.  Use '-' to emit to STDOUT.

     Saves the Doctype object in a perl module.  Tries to save in
     lib/RevML/Doctype/ if that directory exists, then in ./ if not.

import
use
          ## To extablish a default RevML::Doctype for the current package:
          use RevML::Doctype 'DEFAULT' ;
          use RevML::Doctype DTD_FILE => 'revml.dtd' ;

SUBCLASSING
===========

   This class uses the fields pragma, so you'll need to use base and
possibly fields in any subclasses.

COPYRIGHT
=========

   Copyright 2000, Perforce Software, Inc.  All Rights Reserved.

   This will be licensed under a suitable license at a future date.  Until
then, you may only use this for evaluation purposes.  Besides which, it's
in an early alpha state, so you shouldn't depend on it anyway.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

Write RevML files using the RevML DTD
*************************************

NAME
====

   RevML::Writer - Write RevML files using the RevML DTD

SYNOPSIS
========

     use RevML::Doctype::v1_1 ;
     use RevML::Writer ;

DESCRIPTION
===========

   This class provides facilities to write out the tags and content of
RevML documents.  See XML::AutoWriter for all the details on this writer's
API.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

COPYRIGHT
=========

   This module is Copyright 2000, Perforce Software, Inc.  All rights
reserved.

   This will be licensed under a suitable license at a future date.  Until
then, you may only use this for evaluation purposes.  Besides which, it's
in an early alpha state, so you shouldn't depend on it anyway.

Perl extension for to start programs in background
**************************************************

NAME
====

   Run - Perl extension for to start programs in background

SYNOPSIS
========

     use Run;
     $pid = spawn 'long_running_task', 'arg1', 'arg2' or die "spawn: $!";
     do_something_else();
     waitpid($pid,0);

DESCRIPTION
===========

   The subroutine spawn is equivalent to the builtin system (see `system
LIST', see Perlfunc (perl.info)) with the exceptions that the
program is started in background, and the return the pid of the kid.

   Returns 0 on failure, $! should contain the reason for the failure.

EXPORT
======

   Exports spawn by default.

AUTHOR
======

   Ilya Zakharevich <ilya@math.ohio-state.edu

TODO
====

   What to do with `errs' in or?  Should they be cleared?

ENVIRONMENT
===========

   `PERL_RUN_DEBUG' is used to set debugging flag.

NOTES
=====

   `open FH, ">&=FH1"' creates a "naughty" copy of `FH1'.  Closing FH will
invalidate `FH1'.

SEE ALSO
========

   perl(1).

Tied access to sdbm files
*************************

NAME
====

   SDBM_File - Tied access to sdbm files

SYNOPSIS
========

     use SDBM_File;

     tie(%h, 'SDBM_File', 'Op.dbmx', O_RDWR|O_CREAT, 0640);

     untie %h;

DESCRIPTION
===========

   See `tie', see Perlfunc (perl.info), `tie', see
Perldbmfilter (perl.info),

a SDL perl extension
********************

NAME
====

   SDL::App - a SDL perl extension

SYNOPSIS
========

     $app = new SDL::App ( -title => 'FunkMeister 2000',
     			-icon_title => 'FM2000',
     			-icon => 'funkmeister.png',
     			-width => 400,
     			-height => 400 );

DESCRIPTION
===========

   This Object is a composite made up of a few surfaces, and strings.
This object does the setup for the SDL library, and greates the base
application window.

   The options that the constructor takes are:

   -title =>	the title bar of the window -icon_title =>	the
title bar of the icon -icon =>	the icon image file -flags =>	the
SDL_* surface flags for the	default window -width =>	of the
app window -height =>	of the app window -depth =>	the bit depth of the window

Additional Methods
------------------

     In addition to initilizing the SDL library, the app class
     provides access to a couple miscellaneous functions that all programs
     may need:

     $app->delay(milliseconds);

   Delay will cause a delay of roughly the specified milliseconds. Since
this only runs in multi-tasking environments, the exact number is not
assured.

     $app->ticks();

   Ticks returns the number of clock ticks since the program was started.

     $app->error();

   Error returns any pending SDL related error messages.  It returns an
empty string if no errors are pending, making it print friendly.

     $app->warp(x,y);

   Will move the cursor to the location x,y.

AUTHOR
======

   David J. Goehrig

SEE ALSO
========

   perl(1) SDL::Surface(3) SDL::Mixer(3) SDL::Event(3) SDL::Cdrom(3).

a SDL perl extension
********************

NAME
====

   SDL::Cdrom - a SDL perl extension

SYNOPSIS
========

     $cdrom = new SDL::Cdrom 0;

DESCRIPTION
===========

     Cdrom.pm provides software control for CD music.  To open a
     CD for playing, ejecting, etc. create a new instance of the Cdrom object,
     passing it the number of the drive starting with 0 .. CD_NUM_DRIVES - 1:

     $cdrom = new SDL::Cdrom 0;

   The function CD_NUM_DRIVES will return the number of accessible drives
your system currently has.  Once open, you can get the device name of the
drive using the method name:

     $name = $cdrom->name();

Polling Status
--------------

     The method $cdrom->status() differs from the SDL function SDL_CDStatus
     in that it returns a string describing the status.  This method returns
     the following values:

     playing
     stopped
     paused
     empty
     error

   This was done simply to make it easier to present this information to
the end user, in particular programmers debugging their scripts, with
little loss of speed.

Using the CD
------------

     $cdrom->play(track,number_of_tracks,[frame],[number_of_frames]);
     $cdrom->pause();
     $cdrom->resume();
     $cdrom->stop();
     $cdrom->eject();

   The only tricky thing here is that those familiar with the function
SDL_CDPlayTracks should be aware that ntracks and start_frame have been
swapped to make it easier to use, with the frame oriented parameters being
optional.

Track Data
----------

     To get information on a particular track the method:

     $cdrom->track(index);

   will return a hash containing: -id, the track number as one would see
on their cd player, -type, the type of data, -length, size of track in
frames, -offset, the posistion on the CD.

     $cdrom->current();

   returns the hash for the current track, and $cdrom->current_frame will
give you the current frame within that track.

     $cdrom->num_tracks();

   logically, returns the number of tracks on the cd, and

   	$cdrom->id();

   returns the id of the cdrom.

AUTHOR
======

   David J. Goehrig

SEE ALSO
========

   perl(1) SDL::Mixer(3) SDL::App(3).

a SDL perl extension
********************

NAME
====

   SDL::Cursor - a SDL perl extension

SYNOPSIS
========

     $cursor = new SDL::Cursor 	-data => new SDL::Surface "cursor.png",
     				-mask => new SDL::Surface "mask.png",
     				-x => 0, -y => 0;

DESCRIPTION
===========

     To create a new cursor, create a new instance of the Cursor
     class passing it two surfaces as shown in the example.  The x and
     y values indicate the position of the hot-spot for clicking.

   To move the cursor to a position on the screen use the warp method
passing the values of x and y.  The warp function does not require an
instance to have been created, and can be safely used directly.

     SDL::Cursor::warp(x,y);
     $cursor->warp(200,200);

   Similary, to toggle the visible status of the cursor use the show
method:

     SDL::Cursor::show(0);	# this hides the cursor
     $cursor->show(1);	# make the cursor visible

   If you have created a new Cursor, to set it as the active cursor use
the method 'use':

     $cursor->use();

   Finally, if you are using more than one instance of a SDL_Cursor *, you
may find the get method useful for finding out the current cursor.

     SDL::Cursor::get();
     $cursor->get();

   NB: This will not return the value of that instance, but rather the
instance currently in use;

AUTHOR
======

   David J. Goehrig

SEE ALSO
========

   perl(1) SDL::Surface(3).

a SDL perl extension
********************

NAME
====

   SDL::Event - a SDL perl extension

SYNOPSIS
========

     $event = new SDL::Event;

DESCRIPTION
===========

     SDL::Event->new(); creates a SDL_Event structure, into
     which events may be stored.

   $event->type()

     This function returns the event type which will be one of
     the values: SDL_ACTIVEEVENT, SDL_KEYDOWN, SDL_KEYUP, SDL_MOUSEMOTION,
     SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONUP, SDL_QUIT,SDL_SYSWMEVENT.

Gathering Events
----------------

     $event->poll();
     $event->pump();
     $event->wait();

   These three methods can be used to gather new events.  Poll and pump
should be used together.  Pump will collect events, and poll will read
events from the stack, returning 0 if no events were found.  Similarly
wait will wait for an event to occur, and then return.

Active Events
-------------

   These events indicate a change in the state of the application. The
methods which access the event's properties are:

     $event->gain();
     $event->state();

   The possible states that an event may return are: SDL_APPMOUSEFOCUS,
SDL_APPINPUTFOCUS, and SDL_APPACTIVE.

Key Events
----------

   Everytime a key is pressed or release, while the app has input focus, a
key event will be generated.  The following methods provide access to the
event's fileds:

     $event->key_state();
     $event->key_name();
     $event->key_sym();
     $event->key_mod();
     $event->key_unicode();
     $event->key_scancode();

   Key_state will return either SDL_PRESSED or SDL_RELEASED.  Key_name
will return a string giving the name of the key.  Sym will return the SDL
key symbol code, which can be checked against the SDLK_* entries as
specified in the SDL documentation. (ie sym 27 is SDLK_ESCAPE).  Likewise,
key_mod will return the current modifier state of the key and can be or'ed
against the KMOD_* masks as per the SDL documentation.

   To enable unicode support, one must first call

     $event->set_unicode(1);

   there after each event will fill out the unicode field.  The key_unicode
function returns the integer of the unicode key.  Similarly, key_scancode
will return the raw scancode from the key event.

Mouse Events
------------

   There are two types of mouse related events, motion and button.  The
exact type is important as there are separate methodss for reading from
each.  For motion events one should use:

     $event->motion_state();
     $event->motion_x();
     $event->motion_y();
     $event->motion_xrel();
     $event->motion_yrel();

   For button events the following are applicable:

   	$event->button_state(); 	$event->button_x(); 	$event->button_y();
$event->button();

   Button_state will either be SDL_PRESSED or SDL_RELEASED, while button
will contain the number of the button pressed, 1, 2, 3, etc.

Other things
------------

   Additionally, you can use the method 'set' to make the SDL ignore or
re-enable event types.  For example, you can ignore all SDL_SYSWMEVENT
events with the command:

     $event->set(SDL_SYSWMEVENT,SDL_IGNORE);

   This is highly recommended as you will have to process fewer events
this way.  You can also enable key repeats using the method:

     $event->set_key_repeat(delay,interval);

   It should be noted that there is currently no support for the SYSWMEVENT
events in this structure, as these are really best dealt with C level
code.  This may change in the future.

AUTHOR
======

   David J. Goehrig

SEE ALSO
========

   perl(1) SDL::App(3).

a SDL perl extension
********************

NAME
====

   SDL::Font - a SDL perl extension

SYNOPSIS
========

     $font = new Font "Font.png";
     $font->use();

DESCRIPTION
===========

     SDL::Font provides a mechanism for loading and using SFont style
     fonts.  To create a new font, simply create a new instance of the class
     Font, passing it the name of the image file that contains the SFont.

     To use the font, call the use method of the font instance as
     shown above.  Perl will automagically deallocate all of the buffers.
     You must create and use a font prior to printing on any surface.
     For further details see the file SFont-README in this distribution.

AUTHOR
======

   David J. Goehrig

SEE ALSO
========

   perl(1) SDL::Surface(3)

a SDL perl extension
********************

NAME
====

   SDL::Mixer - a SDL perl extension

SYNOPSIS
========

     $mixer = new SDL::Mixer 	-frequency => MIX_DEFAULT_FREQUENCY,
     				-format => MIX_DEFAULT_FORMAT,
     				-channels => MIX_DEFAULT_CHANNELS,
     				-size => 4096;

DESCRIPTION
===========

     This module provides a pseudo object ( it contains no data ),
     that handles all of the digital audio for the system.  It is simply an
     interface for SDL_mixer.  In general, there is no need to pass any flags
     to the constructor.  The default, shown above, provides 8 channels of
     16 bit audio at 22050 Hz. and a single channel of music.

     The flags passable are -frequency ( or for the impatient -rate ),
     -format, -channels, -size, which specify the sample frequency, byte
     format, number of channels, and sample size respectively.  Frequency
     can range from 11025 to 44100.  Format is one of the following:
     AUDIO_U8, AUDIO_S8, AUDIO_U16, AUDIO_S16.  For those with big endian
     machines use AUDIO_U16MSB and AUDIO_S16MSB.  Channels default to 8,
     while size goes to 4096, and can range from 512 to 8096.  Given you
     are using perl, a higher latency is probably more realistic.

     There are two subordinate modules, Sound.pm and Music.pm
     which handle the actual file access and memory cleanup.  Sound objects
     also have a per file volume control above and beyond the channel's
     volume setting.  It can be set to half volume as follows:

     my $wavfile = new SDL::Sound "funk.wav";
     $wavfile.volume(64);

     Sound objects can only load .wav files.  Music files, however,
     can load MIDI files such as .mod .s3m .it .xm.  Music files, more importantly,
     through use of Lokisoft's smpeg library, can play MP3 files.  This is,
     of course, the music format of choice.  If you need normal CD audio, please
     use the Cdrom.pm module.

Functions
---------

     $hashref = $mixer->query_spec();

   Query_spec returns a has containing the keys -status, -frequency,
-format, and -channels.  These are the values that are being used by the
mixer.  If you are adventurous, the SDL::sdlpl::sdl_*_audio_* functions
provide low level access the the SDL Audio features.  Without C level
callback functions these routines are useless though.

     $mixer->reserve_channels(n);

   This calls Mix_ReserveChannels and saves n channels for the app.

     $mixer->allocate_channels(n);

   If given a number greater than the current number of channels, it will
grow the collection of channels to n.  If n is lower, then it will free
those channels, and remove them.

     $mixer->group_channel(channel,group)

   This will add channel to group, which channel and group are both
integers.  Similarly,

     $mixer->group_channels(from,to,group)

   will add channels from 'from' to 'to' to group 'group'.

     $mixer->group_available(group)

   will return the next available channel in a group.

     $mixer->group_count(group)

   will return the number of channels in a group, and if group = -1 will
return the total number of channels.

     $mixer->group_oldest(group)

   will return the longest playing sample in the group.

     $mixer->group_newer(group)

   will return the most recently played sample of a playing group.

     $mixer->play_channel(channel,Sound,loops,[ticks]);
     $mixer->fade_in_channel(channel,Sound,loops,ms,[ticks]);
     $mixer->fade_out_channel(channel,ms);
     $mixer->fade_out_group(group,ms);
     $mixer->channel_expire(channel,ms);
     $mixer->halt(channel);
     $mixer->halt_group(group);
     $mixer->pause(channel);
     $mixer->resume(channel);

     $mixer->fading_channel(channel);
     $mixer->playing(channel);
     $mixer->paused(channel);

   Play_channel will play a Sound object 'Sound', on channel 'channel', and
loop 'loops' times, for optionally at most 'ticks' ticks.  Fade_in_channel
works the same, but fades the sample in over ms milliseconds.
Fade_out_channel will fade a channel out for ms milliseconds, where as
channel_expire will kill it after ms milliseconds. Halt will kill a
channel immediately, and halt_group works on an entire group.  Pause and
resume works as a pair to pause and resume playback of a channel.
Fadding_channel, playing, and paused, all return a value if the channel is
in that state.

   There are a number of similar methods for music.  They work basically
the same way, but as there is only a single music channel, do not require
as many args. They are as follows:

     $mixer->play_music(Music,loops);
     $mixer->fade_in_music(Music,loops,ms);
     $mixer->fade_out_music(ms);
     $mixer->halt_music();
     $mixer->pause_music();
     $mixer->resume_music();

     $mixer->music_paused();
     $mixer->playing_music();
     $mixer->fading_music();

   In addition to those, music also has two additional commands:

   	$mixer->rewind_music(); 	$mixer->set_music_command("string");

Volume Control
--------------

     The MIX_MAX_VOLUME is 128.  To set the volume of the music use
     the method:

     $mixer->music_volume(vol);

   Similarly the volume of each channel can be set using:

     $mixer->channel_volume(channel,vol);

   For .wav files, the volume of the sample itself can be adjusted as
mentioned above using the 'volume' method of the Sound object.  The mixer
will automagically handle all of the mixing for you.

AUTHOR
======

   David J. Goehrig

SEE ALSO
========

   perl(1) SDL::Cdrom(3)

a SDL perl extension
********************

NAME
====

   SDL::OpenGL - a SDL perl extension

SYNOPSIS
========

   Provides OpenGL bits to SDL-Perl, please look at the examples.

DESCRIPTION
===========

Additional Methods
------------------

AUTHOR
======

   Wayne Keenan

SEE ALSO
========

   perl(1) SDL::Surface(3) SDL::Mixer(3) SDL::Event(3) SDL::Cdrom(3).

Glut like wrapper for SDL OpenGL apps
*************************************

NAME
====

   SDL::OpenGL::App  - Glut like wrapper for SDL OpenGL apps

SYNOPSIS
========

     use SDL::OpenGL::App;

      my $app=new SDL::OpenGL::App;

     $app->app_name("Gears");

     $app->register_handler(init    => \&init,
     			draw    => \&draw,
     			events  => \&events,
     			idle    => \&idle,
     			reshape => \&reshape,
     		       );

     $app->run();

DESCRIPTION
===========

METHODS
=======

     new
     add_startup_parameter
     add_runtime_help
     register_handler
     pointer_show
     run
     pump
     screendump

     app_name
     screen_width
     screen_height
     fullscreen
     fps
     glinfo

     red_size
     green_size
     blue_size
     depth_size
     doublebufer

     Package utility methods:

     read_texture
     rle_enc
     rle_dec
     =head1 EXAMPLES

QUICK DEMO/TEST
---------------

   Running the in-built demo/test:

   run perl with the 'e' flag to execute these one liners:

   'use SDL::OpenGL::App; new SDL::OpenGL::App->run'

   same, but in fullscreen mode:

   'use SDL::OpenGL::App; $g=new SDL::OpenGL::App; $g->fullscreen(1);
$g->run'

PUMPING
-------

   'Pumping' the SDL::OpenGL::App processing loop, step by step:

   Make use of the 'pump' function, say, when called from a Gtk Idle loop
for instance:

   my $gl_app=new SDL::OpenGL::App ;

   #register handlers/help as normal

   my $stay_alive=1; while ($stay_alive)   {    my $gl_rc=$gl_app->pump();
#returns FALSE when 'reasons to leave' detected

     $stay_alive=0 unless $gl_rc;
       }

MAKE A MOVIE!
-------------

     NOTE:: currently (as from V1.06) only RAW PPM files are generated, but
     then SDL::OpenGL::App can only read ASCII/RAW PPM file anyway, for now.

     To create a series of screenshots to build a movie, e.g. to build
     OpenGL looking graphics for a 'flatter' application(s) (game/web/etc..):

     #do things as usual, then

     my $frame=0;
     my $frame_ext_format="%d"; #you may want leading 8 zeros hex, e.g, : "%08x"
     sub idle
       {

        #..do your 'Idle' stuff..

        $gl_app->screendump(FILE_NAME=>"movie/gear.".sprintf($frame_ext_format,$frame++));
       }

   to playback the movie, one quick way is to use the 'animate' program
from ImageMagick:

   $ animate movie/gear.*

   Furthermore, you could then use 'read_texture' to read them all/it back
in, to be used as a (possibly animated) bill board, or drop OpenGL mode
and then use them in 2D SDL Surfaces, you choose.

   For more examples please have a look inside the directory:
'examples/openGL/Glut'

TODO
====

BUGS
====

AUTHOR
======

     Wayne Keenan               wayne@metaverse.fsnet.co.uk

     Copyright (c) 2000 Wayne Keenan. All rights reserved.
     This program is free software; you can redistribute it
     and/or modify it under the same terms as Perl itself.

VERSION
=======

     Version 0.02     (05 Aug 2000)

SEE ALSO
========

     perl(1) SDL::App SDL::OpenGL

a SDL perl extension
********************

NAME
====

   SDL::Rect - a SDL perl extension

SYNOPSIS
========

     $rect = new SDL::Rect ( -height => 4, -width => 40 );

DESCRIPTION
===========

     SDL::Rect->new(...); creates a SDL_Rect structure which is
     used for specifying regions for filling, blitting, and updating.
     These objects make it easy to cut and backfill.

   By default, x, y = 0, and h, w default to 0. (the default scratch
sizes);

Rect fields
-----------

     The four fields of a rectangle can be set simply
     by passing a value to the applicable method.  These are:

     $rect->x(4);		# sets x to 4
     $rect->y();		# reads y
     $rect->width(49);	# sets width to 49
     $rect->height();	# reads height

AUTHOR
======

   David J. Goehrig

SEE ALSO
========

   perl(1) SDL::Surface(3)

a SDL perl extension
********************

NAME
====

   SDL::Surface - a SDL perl extension

SYNOPSIS
========

     use SDL::Surface;
     $image = new SDL::Surface(-name=>"yomama.jpg");

DESCRIPTION
===========

     SDL::Surface->new(-name=>"yomama.jpg"); will load an image named
     yomama.jpg, which works equally well with images of type bmp, ppm, pcx,
     gif, jpeg, and png. Optionally, if you would like a scratch surface
     to work with, you can createit using this function using the following
     syntax:

SDL::Surface->new(-flags=>SDL_SWSURFACE,-width=>666,-height=>666,-depth=>8);

   which will produce a software suface, at 666x666x256 colors.  To create
an image using the default depth and flag state simply use:

   SDL::Surface->new(-width=>$my_w,-height=>$my_h);

   If you are on a big endian machine, or some really funky hardware you
can set the RGBA bitmasks with the keys -Rmask, -Gmask, -Bmask, -Amask.
For example to create a scratch surface on a big endian machine one would
use: 	SDL::Surface->new(-width=>200,-height=>100,
-Rmask=>0xff000000,-Gmask=>0x00ff0000,
-Bmask=>0x0000ff00,-Amask=>0x000000ff);

DESTROY
-------

     When a surface is destroyed, perl will call SDL_FreeSurface() on
     it. Hence don't worry about freeing it yourself.  If you must, then
     invoke the function SDL::sdlpl::sdl_free_surface($your_surface);

Read-only Surface fields
------------------------

     The SDL_Surface structure has many subfields.  Most of these
     fields are accessible in read-only form.  Most of these fields are
     useless to a perl hacker anyways, and are provided for a sense
     of completeness.

   $surface->flags()

   	This field returns the flags which are applicable to the current
surface.  The possible values for the flags are:

     SDL_ANYFORMAT
     SDL_SWSURFACE
     SDL_HWSURFACE
     SDL_HWPALETTE
     SDL_DOUBLEBUF
     SDL_FULLSCREEN

   $surface->palette()

   	This field returns a pointer to the SDL_Palette structure for this
image if it is an 8 bit image, or NULL if the image is 16, 24, or 32 bit.
cf. Palette.pm NB: this should not be passed to any Palette method.  what
you need there is to create a new Palette object, passing it the image as
in:

     my $pal = new SDL::Palette $image;

   cf Palette.pm for details.

   $surface->bpp()

     This field returns the bits per pixel, aka depth,
     of the surface.

   $surface->bytes_per_pixel()

     This field returns the bytes per pixel, this should
     in all cases be the same as bpp/8.  Technically, it reads
     that field of the SDL_PixelFormat structure for the surface.

   $surface->Rshift(); $surface->Gshift(); ...

     These functions return the Rshift, Gshift, Bshift, and
     Ashift respectively for the surface.  To be perfectly honest,
     these are not all that useful from perl, but are provided
     for future expansion.

   $surface->Rmask(), $surface->Gmask() ...

     Like Rshift & friends, Rmask, Gmask, Bmask, and Amask
     return the current byte masks for each component of RGBA
     surfaces.  They are provided for future expansion.

   $surface->color_key();

     This returns the pixel value which was set using
     $surface->set_color_key(flag,pixel);  This is the transparent
     color for the image.

   $surface->alpha();

     This returns the alpha value of the surface, usually
     set by $surface->set_alpha(flag,alpha);  Alpha values are
     not applicable to palettized images.

   $surface->width();

     This returns the width of the surface.

   $surface->height();

     This returns the height of the surface.

   $surface->clip_minx ... clip_miny ... clip_maxx ... clip_maxy

     clip_minx, clip_miny, clip_maxx, and clip_maxy return
     the current clipping values for the surface.

   $surface->pitch();

     This returns the pitch of the image, aka the width
     of a single row of pixels in bytes.  This should be the same
     as $surface->width()*$surface->bytes_per_pixel().
     It is provided for future expansion.

Poking Pixels
-------------

     The swiss-army-chainsaw of pixel manipulation, the method
     $surface->pixel(x,y,color); can be used to read or set the value
     of a pixel at the point (x,y).  If no color value is passed, it
     will simply read the value at that point.  If a color is passed, it
     will set the point to that value and then return the value to which
     it  was actually set.

     For the speed conscious, this function is SLOW.  It is not
     designed for line drawing or other large-scale projects.  It is my
     intention to provide a generic drawing system in the future,
     and additional low level memory tools, but in the mean time, if you
     must this cudgel.

   So just to reiterate:

   	$surface->pixel(12,13);	# returns the pixel at (12,13)
$surface->pixel(12,13,0xffff); # sets that pixel to 0xffff

Filling areas
-------------

     To fill a larger volume than a single pixel the method:

     $surface->fill($rect,color);

   will fill a rectangle with the value of color.  With intelligent use of
Rect objects one can draw buttons and the like.  It is also useful in
clearing the screen.

Locking, Unlocking, and the like...
-----------------------------------

     When writing to certain surfaces, notably some SDL_HWSURFACE
     flaged surfaces, it is necessary to lock the surface before twiddling
     its bits.  To tell if you must do so it is wise to call the function:

     $suface->lockp();

   If it returns non-zero you should then call:

     $surface->lock();

   and after your write call:

     $surface->unlock();

   and everything will be well.  Locking and unlocking a surface which
doesn't require locking only wastes time, so if you have time to spare,
you could just do so by default.

Bliting & Updating
------------------

     To copy image data from one surface to another, the SDL
     provides a collection of functions.

     $surface->update(rect,...);

   will update any number of Rects of the screen, where as:

     $surface->flip();

   will update the entire screen.

     $surface->blit($srect,$dest,$drect);

   will copy the contents contained by $srect of the surface $surface into
area specified bye $drect of the surface $dest.  Please see the documents
for Rect.pm for the creation of $srect and $drect.

So may Colors in the world ...
------------------------------

     To set the colors in a palettized image, the method:

     $surface->set_colors($start,...)

   is provided.  It takes 1 or more Color objects, and sets the
consecutive palette entries starting at entry $start.  Hence to set the
first ten palette entires one would use:

     $my_surface->set_colors(0,$color1,$color2,...$color10);

   where $color1 ... $color10 were created with Color->new(r,g,b); see
Color.pm for details.

     Transperancy and alpha levels for an image can also be set
     using the methods:

     $surface->set_color_key(flag,pixel);

     and
     		$surface->set_alpha(flag,alpha);

   where the flags for set_color_key are: SDL_SRCCOLORKEY and SDL_RLEACCEL,
and the flags for set_alpha are: SDL_SRCALPHA and SDL_MULACCEL.

Clipping
--------

     To set the clipping rectangle for a source surface the
     method $surface->clip(top,left,bottom,right); will prevent
     accidental bliting of material outside of this rectangle.

Format Conversion
-----------------

     Occasionally it will be necessary to manipulate images in
     a format other than that used by the display, to manage the conversion
     the method: $surface->display_format(); will produce a new surface
     in the format used for display.

Fonts & Printing
----------------

     As of version 1.01, SDLpl now supports SFont style
     fonts.  Before printing, one must create and use a new font
     as specified in SDL::Font.  For example to load a font stored
     in Ionic.png one would use:

     $font = new Font "Ionic.png";
     $font->use;

     Then to print a string to (10,13) on a surface one would use
     the print method of the surface:

     $surface->print(10,13,"Hello World");

AUTHOR
======

   David J. Goehrig

SEE ALSO
========

   perl(1) SDL::Rect(3) SDL::Font(3).

Perl bindings for the SDL
*************************

NAME
====

   SDL::sdlpl - Perl bindings for the SDL

SYNOPSIS
========

     use SDL::sdlpl;

DESCRIPTION
===========

     sdlpl is a collection of bindings for functions in the
     Simple DirectMedia Layer, and an assortment of related utilities.
     The module sdlpl is not indended for direct use, but rather serves
     as the backbone of a collection of Object-Oriented modules which
     provide access to the SDL library.

     The associated modules are App.pm, Surface.pm, Event.pm, Rect.pm,
     Palette.pm, Mixer.pm, Cdrom.pm and OpenGL.pm.

AUTHOR
======

   David J. Goehrig Wayne Keenan

SEE ALSO
========

   perl(1) App(3) Surface(3) Event(3) Rect(3) Palette(3) Mixer(3) Cdrom(3)
OpenGL(3) OpenGL::App(3)

gather local and remote SETI@home stats and manipulate them
***********************************************************

NAME
====

   SETI::Stats - gather local and remote SETI@home stats and manipulate
them

SYNOPSIS
========

     use SETI::Stats;

     $s = new SETI::Stats ( rsh => "/semi-free/bin/ssh -l ernie",
                            host => "bert",
                            dir => "/seti" );
     $s->visit;
     print $s->user_info("email_addr");
     print $s->bar . "\n";

     $t = new SETI::Stats ( dir => "/martin/seti", save => "p" );
     while (1) {
       $t->visit;
       print $t->dump . "\n\n";
       sleep(60);
     }

DESCRIPTION
===========

   This Perl class provides an object oriented API which lets you gather
SETI@home stats from one or more machines and gives you a programmatic way
of getting access to them.  It can cope with multiple SETI@home clients
which share a directory hierarchy accessible to the machine it is run on,
clients which each have their own private filespace (using rsh, ssh or
equivalent) and even works for boxes running Windows NT.

   SETI::Stats borrows from Jan Rocho's *perlseti.pl*, but differs in
several ways - this is a module devoted to stats gathering rather than a
general purpose control program, it can be used to monitor remote machines
without even requiring Perl to be installed on them, and it provides a
generic framework for access to (both local and remote) SETI@home client
stats.  It could also be extended to cover stats gathering from the
SETI@home WWW server, though this may be better done in a separate module
to avoid code bloat.

METHODS
=======

   Each *SETI::Stats* object supports the following methods:

new
     Create a new *SETI::Stats* object.  The following parameters are
     supported:

    dir
          This is the (local or remote) directory where *SETI::Stats* will
          look for the SETI@home client's stats files.  It defaults to
          */home/seti*.

    host
          When gathering stats remotely, this is the name of the host to
          contact.  It will also be used as part of the name of
          *SETI::Stats*' own state file - see below for more info on this.

    rsh
          The command (rsh or equivalent) which will be used to contact the
          remote host when gathering stats over the Internet.  If you need
          to specify a user name or other parameters, you can add them
          here, e.g.

               rsh => "/semi-free/bin/ssh -l ernie"

          This defaults to ssh.

    save
          The filename (absolute or relative) prefix of the local file to
          store *SETI::Stats*' state info in.  This defaults to
          perlseti_data.  See below for more information on state file
          naming.

    source
          The radio telescope data source for the SETI@home client.  By
          default this is set to the *Arecibo Radio Observatory*, which is
          currently the only source of data for the SETI@home experiment.

     Note that none of these parameters is mandatory.  In particular, you
     don't have to store state info between polling clients - unless you
     want to use the dump method.  The visit method will store it for you,
     however!

poll
     This method polls the SETI@home client being monitored by this
     *SETI::Stats* object for a given section of its stats.  It takes the
     following parameters:

    checkpoint
          This indicates that the poll invocation is of the local
          checkpoint file maintained by *SETI::Stats* rather than a
          (possibly remote) state file maintained by the SETI@home client
          itself.  It's set automatically by the visit method when
          updating the local checkpoint file.

    section
          This is the section name to poll for, corresponding to the file
          section.txt in the SETI@home working directory on the client
          machine.

     This method is normally used internally by the visit method.

populate
     This method populates the internal data structures used by
     *SETI::Stats* for this section of the stats.  It takes the following
     parameters:

    results
          An array of results, in the format *attribute*=value, with one
          attribute/value pair per entry - e.g. *prog=0.487688*

    section
          The section name of the stats to populate, e.g. work_unit.

     This method is normally used internally by the visit method.

checkpoint
     This method saves *SETI::Stats*' current state info to a file on the
     local machine (even when monitoring a remote one).  The file name is
     determined by the values of the dir and save parameters when the
     object was created, e.g. with a dir of */seti* and a save of
     *perlseti_state*, the file created would be */seti/perlseti_state.txt*
     when the local host was being monitored.

     In the case of a remote client being monitored, the host name is
     appended to dir and save, prefixed by an underscore, e.g. for the
     client machine *bert*, the file would be
     */seti/perlseti_state_bert.txt*.  Note that the value of save no
     longer needs to contain the string *perlseti* (as was the case in
     *SETI::Stats* 1.00 and 1.01) for this feature to work properly.

     You don't have to checkpoint, but be aware that this info is used by
     the dump method.

     This method is normally used internally by the visit method.

visit
     This method is the one you would normally call when polling a given
     SETI@home client for its stats.  It in turn calls the poll method for
     each of the result_header, state, user_info, version and work_unit
     stats files and populates the *SETI::Stats* object's internal data
     structures with the contents of these files.

     These are then accessible through the result_header, state,
     user_info, version and work_unit methods.

     visit also calls the checkpoint and poll methods, which store
     *SETI::Stats*' state information and populates the internal data
     structure used by the perlseti_data method.

   Access methods:

bar
     Returns a progress bar of '#' characters, representing the percentage
     of the work unit which has been analysed so far - on a scale of 0 to
     80 characters, where 80 indicates that the work unit is complete.

dump
     Returns a SETI stats info 'screen' in the style of *perlseti.pl*,
     based on the last polled values for this SET@home client.

perlseti_data
     The method returns the value of the nominated parameter in the
     perlseti_data section of the client's stats.  This section is unusual
     in that it is collected by *SETI::Stats* rather than the SETI@home
     client itself.

result_header
     This method returns the value of the nominated parameter in the
     result_header section of the client's stats.

state
     This method returns the value of the nominated parameter in the state
     section of the client's stats.

user_info
     This method returns the value of the nominated parameter in the
     user_info section of the client's stats.

version
     This method returns the value of the nominated parameter in the
     version section of the client's stats.

work_unit
     This method returns the value of the nominated parameter in the
     work_unit section of the client's stats.

   Examples of the access methods in use can be found above in the SYNOPSIS
section of this manpage.

BUGS
====

   This is still fairly new stuff, so probably contains much which is
apocryphal, or just plain wrong :-)

   If the object existed already we should probably take care to overwrite
or remove old stats in a section when doing an update, or we could end up
with the situation that some stats are current but others aren't.

   Return codes should be documented.

   There should be a test module.

   Debugging options would be useful!

COPYRIGHT
=========

   Copyright (c) 1999, Martin Hamilton <martinh@gnu.org>.  All rights
reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Martin Hamilton <martinh@gnu.org>

Perl interface to SGI/Irix File Access Monitor
**********************************************

NAME
====

   *SGI::FAM* - Perl interface to SGI/Irix File Access Monitor

SYNOPSIS
========

     use SGI::FAM;
     my $fam=new SGI::FAM;
     $fam->monitor('/foo');
     $fam->monitor('/foo/bar.txt');
     while (1) {
       my $event=$fam->next_event;	# Blocks
       print "Pathname: ", $event->filename,
         " Event: ", $event->type, "\n";
     }

   Asynchronous mode:

     while ($fam->pending) {
       my $event=$fam->next_event; # Immediate
       ...
     }
     # Do something else

DESCRIPTION
===========

   Provides a somewhat higher-level and friendlier interface to the
SGI/Irix File Access Monitor API. This allows one to monitor both local
and remote (NFS-mounted) files and directories for common filesystem
events. To do so, you must register "monitors" on specified pathnames and
wait for events to arrive pertaining to them. To get a full description of
the API, you should see `fam(3x)' in this node.

   Since FAM only deals with absolute pathnames, all paths are
canonicalized internally and monitors are held on canonical paths.
Whenever a path is returned from this module, howvever, via which or
*monitored* with no arguments, the originally specified path is given for
convenience.

MAIN METHODS
============

new [ *appname* ]
-----------------

   Create a new FAM connection. An application name may be given.

pending
-------

   True if there is an event waiting. Returns immediately.

*debug_level* [ level ]
-----------------------

   Set or query debug level. Values are *FAM_DEBUG_OFF*, *FAM_DEBUG_ON*,
and *FAM_DEBUG_VERBOSE* (you should ask to import these).

next_event
----------

   Returns next event in queue, as an event object. Blocks if necessary
until one is available.

*monitor* path [ unique [ type [ depth mask ] ] ]
-------------------------------------------------

   Monitor the specified file or directory. Expect a slew of events
immediately (*exist* and *end_exist*) which may not interest you.

   unique, if specified and true, will produce a warning if the monitored
path is not unique among those already being monitored. This can be
helpful for debugging, but normally this is harmless.

   type may be file, dir or *coll*; it defaults to file or dir according
to an *existing* filesystem entry. If you specify *coll* (collection), pass
additional depth and mask arguments, if you ever figure out what that does
(SGI does not say).

*cancel* path
-------------

   Stop monitoring this path.

*monitored* [ path ]
--------------------

   List all currently monitored paths, or check if a specific one is being
monitored. Does not check if a monitor is suspended.

*suspended* path
----------------

   True if the specified monitor is suspended.

*suspend* [ path ]
------------------

   Suspend monitoring of a path, or all paths if unspecified.

resume [ path ]
---------------

   Resume monitoring of a path, or all paths if unspecified.

which event
-----------

   Gives the pathname for the monitor generating this event. Often this
will be the same as `$event->filename', but will differ in some cases,
e.g. in create events where filename will yield the basename of the new
file while the which method must be invoked to determine the directory of
creation, if more than one is being monitored.

EVENT METHODS
=============

hostname
--------

   Host of event. Does not seem to work, actually.

filename
--------

   Path of event, according to FAM.

type
----

   Type of event; one of the following strings: change, delete,
*start_exec*, *stop_exec*, create, move, ack, *exist*, *end_exist*.

BUGS
====

   Most of these can be observed with `monitor'.

Hostnames
     Do not seem to be supplied at all.

Timing
     Is somewhat erratic. For example, creating a file that had been
     monitored and deleted will signal a create event on it, after about a
     second pause.

Execute Events
     Are not sent, as far as the author can determine.

SEE ALSO
========

   For the raw SGI interface (rather poorly documented), see `fam(3x)' in
this node.

AUTHORS
=======

   J. Glick *jglick@sig.bsh.com*.

REVISION
========

   X<$Format: "`$Source$' last modified $Date$ release $ProjectRelease$.
$Copyright$"$> `lib/SGI/FAM.pm' last modified Thu, 25 Sep 1997 22:56:42
-0400 release 1.002. Copyright (c) 1997 Strategic Interactive Group. All
rights reserved. This program is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

an element of an SGML, XML, or HTML document
********************************************

NAME
====

   SGML::Element - an element of an SGML, XML, or HTML document

SYNOPSIS
========

     $element->gi;
     $element->name;
     $element->attr ($attr[, $value]);
     $element->attr_as_string ($attr[, $context, ...]);
     $element->attributes [($attributes)];
     $element->contents [($contents)];

     $element->as_string([$context, ...]);

     $element->iter;

     $element->accept($visitor, ...);
     $element->accept_gi($visitor, ...);
     $element->children_accept($visitor, ...);
     $element->children_accept_gi($visitor, ...);

DESCRIPTION
===========

   An `SGML::Element' represents an element in an SGML or XML document.
An Element contains a generic identifier, or name, for the element, the
elements attributes and the ordered contents of the element.

   `$element->gi' and `$element->name' are synonyms, they return the
generic identifier of the element.

   `$element->attr' returns the value of an attribute, if a second
argument is given then that value is assigned to the attribute and
returned.  The value of an attribute may be an array of scalar or
`SGML::SData' objects, an `SGML::Notation', or an array of `SGML::Entity'
or `SGML::ExtEntity' objects.  attr returns undef for implied attributes.

   `$element->attr_as_string' returns the value of an attribute as a
string, possibly modified by `$context'. (XXX undefined results if the
attribute is not cdata/sdata.)

   `$element->attributes' returns a reference to a hash containing the
attributes of the element, or undef if there are no attributes defined for
for this element.  The keys of the hash are the attribute names and the
values are as defined above.  `$element->attributes($attributes)' assigns
the attributes from the hash `$attributes'.  No hash entries are made for
implied attributes.

   `$element->contents' returns a reference to an array containing the
children of the element.  The contents of the element may contain other
elements, scalars, `SGML::SData', `SGML::PI', `SGML::Entity',
`SGML::ExtEntity', or `SGML::SubDocEntity' objects.
`$element->contents($contents)' assigns the contents from the array
$contents.

   `$element->as_string' returns the entire hierarchy of this element as a
string, possibly modified by `$context'.  See SGML/SData,
and SGML/PI, for more detail.  (XXX does not
expand entities.)

   `$element->iter' returns an iterator for the element, see
`Class::Visitor' for details.

   `$element->accept($visitor[, ...])' issues a call back to
`$visitor->visit_SGML_Element($element[, ...])'.  See examples
`visitor.pl' and `simple-dump.pl' for more information.

   `$element->accept_gi($visitor[, ...])' issues a call back to
`$visitor->visit_gi_*GI*($element[, ...])' where *GI* is the generic
identifier of this element.  `accept_gi' maps strange characters in the GI
to underscore (`_') [XXX more specific].

   `children_accept' and `children_accept_gi' call accept and `accept_gi',
respectively, on each object in the element's content.

   Element handles scalars internally for as_string, `children_accept',
and `children_accept_gi'.  For `children_accept' and `children_accept_gi'
(both), Element calls back with `$visitor->visit_scalar($scalar[, ...])'.

   For as_string, Element will use the string unless
`$context->{cdata_mapper}' is defined, in which case it returns the result
of calling the `cdata_mapper' subroutine with the scalar and the remaining
arguments.  The actual implementation is:

     &{$context->{cdata_mapper}} ($scalar, @_);

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), SGML::Grove(3), Text::EntityMap(3), SGML::SData(3),
SGML::PI(3), Class::Visitor(3).

an entity defined in an SGML or XML document
********************************************

NAME
====

   SGML::Entity - an entity defined in an SGML or XML document

SYNOPSIS
========

     $name = $entity->name;
     $data = $entity->data;

     $entity->iter;

     $entity->accept($visitor, ...);

     The following are defined for type compatibilty:

     $entity->as_string([$context, ...]);
     $entity->accept_gi($visitor, ...);
     $entity->children_accept($visitor, ...);
     $entity->children_accept_gi($visitor, ...);

DESCRIPTION
===========

   An `SGML::Entity' contains an entity defined in a document instance.
Within a grove, any entity with the same name refers to the same
`SGML::Entity' object.

   `SGML::Entity' objects occur in a value of an element attribute or as
children of entities.

   `$entity->name' returns the name of the Entity object.

   `$entity->data' returns the data of the Entity object.

   `$entity->accept($visitor[, ...])' issues a call back to
`$visitor->visit_SGML_Entity($entity[, ...])'.  See examples `visitor.pl'
and `simple-dump.pl' for more information.

   `$entity->as_string' returns an empty string.

   `$entity->accept_gi($visitor[, ...])' is implemented as a synonym for
accept.

   `children_accept' and `children_accept_gi' do nothing.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), SGML::Grove(3), Text::EntityMap(3), SGML::Element(3),
SGML::PI(3).

an external entity defined in an SGML or XML document
*****************************************************

NAME
====

   SGML::ExtEntity - an external entity defined in an SGML or XML document

SYNOPSIS
========

     $name = $ext_entity->name;
     $data = $ext_entity->data;
     $type = $ext_entity->type;
     $system_id = $ext_entity->system_id;
     $public_id = $ext_entity->public_id;
     $generated_id = $ext_entity->generated_id;
     $attributes = $ext_entity->attributes;
     $notation = $ext_entity->notation;

     $ext_entity->iter;

     $ext_entity->accept($visitor, ...);

     The following are defined for type compatibilty:

     $ext_entity->as_string([$context, ...]);
     $ext_entity->accept_gi($visitor, ...);
     $ext_entity->children_accept($visitor, ...);
     $ext_entity->children_accept_gi($visitor, ...);

DESCRIPTION
===========

   An `SGML::ExtEntity' contains an external entity defined in a document
instance.  Within a grove, any entity with the same name refers to the
same `SGML::ExtEntity' object.

   `$ext_entity->name' returns the name of the external entity object.

   `$ext_entity->data' returns the data of the entity if it has been
loaded (XXX but that's not been defined yet).

   `$ext_entity->accept($visitor[, ...])' issues a call back to
`$visitor->visit_SGML_ExtEntity($ext_entity[, ...])'.  See examples
`visitor.pl' and `simple-dump.pl' for more information.

   `$ext_entity->as_string' returns an empty string.

   `$ext_entity->accept_gi($visitor[, ...])' is implemented as a synonym
for accept.

   `children_accept' and `children_accept_gi' do nothing.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), SGML::Grove(3), Text::EntityMap(3), SGML::Element(3),
SGML::PI(3).

an SGML, XML, or HTML document
******************************

NAME
====

   SGML::Grove - an SGML, XML, or HTML document

SYNOPSIS
========

     use SGML::Grove;
     $grove = A::GroveBuilder->new ($sysid);
     $root = $grove->root;
     $errors = $grove->errors;
     $entities = $grove->entities;
     $notations = $grove->notations;

     $grove->as_string([$context, ...]);

     $grove->iter;

     $grove->accept($visitor, ...);
     $grove->accept_gi($visitor, ...);
     $grove->children_accept($visitor, ...);
     $grove->children_accept_gi($visitor, ...);

DESCRIPTION
===========

   `SGML::Grove' represents a loaded document instance returned from a
grove building or parsing module, i.e. for SGML documents this may be
SGML::SPGroveBuilder.  The returned grove contains the root, or top,
element of the document and an array of any warnings or errors that may
have been generated while parsing the document.

   `$grove->root' returns the `SGML::Element' of the outermost element of
the document.

   `$grove->errors' returns a reference to an array containing any errors
generated while parsing the document.

   `$grove->entities' returns a reference to a hash containing any
entities referenced in this grove (as opposed to entities that may have
been declared but not used).

   `$grove->notations' returns a reference to an array containing any
notations referenced in this grove.

   `$grove->as_string' returns the entire grove as a string, possibly
modified by `$context'.  See SGML/SData, and
SGML/PI, for more detail.

   `$grove-'iter> returns an iterator for the grove object, see
`Class::Visitor' for details.

   `$grove->accept($visitor[, ...])' issues a call back to
`$visitor->visit_SGML_Grove($element[, ...])'.  See examples `visitor.pl'
and `simple-dump.pl' for more information.

   `$grove->accept_gi($visitor[, ...])' is implemented as a synonym for
accept.

   `children_accept' and `children_accept_gi' call accept and `accept_gi',
respectively, on the root element.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), Text::EntityMap(3), SGML::Element(3), SGML::SData(3),
SGML::PI(3), Class::Visitor(3).  <http://www.jclark.com/>

an data type defined in SGML or XML
***********************************

NAME
====

   SGML::Notation - an data type defined in SGML or XML

SYNOPSIS
========

     $name = $notation->name;
     $system_id = $notation->system_id;
     $public_id = $notation->public_id;
     $generated_id = $notation->generated_id;

     $notation->iter;

     $notation->accept($visitor, ...);

     The following are defined for type compatibilty:

     $notation->as_string([$context, ...]);
     $notation->accept_gi($visitor, ...);
     $notation->children_accept($visitor, ...);
     $notation->children_accept_gi($visitor, ...);

DESCRIPTION
===========

   An `SGML::Notation' contains the type definition defined in a document
instance, with the possible `generated_id' generated by the parser.
Within a grove, any notation with the same name refers to the same
`SGML::Notation' object.

   `SGML::Notation' objects occur as the value of element attributes or as
a member of external entities.

   `$notation->name' returns the name of the notation.

   `$notation->accept($visitor[, ...])' issues a call back to
`$visitor->visit_SGML_Notation($notation[, ...])'.  Note that
`SGML::Notation' objects are never primary children of an `SGML::Element'
object and will not ordinarily occur while simply visiting a grove.

   `$notation->as_string' returns an empty string.

   `$notation->accept_gi($visitor[, ...])' is implemented as a synonym for
accept.

   `children_accept' and `children_accept_gi' do nothing.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), SGML::Grove(3), Text::EntityMap(3), SGML::Element(3),
SGML::PI(3).

an SGML, XML, or HTML document processing instruction
*****************************************************

NAME
====

   SGML::PI - an SGML, XML, or HTML document processing instruction

SYNOPSIS
========

     $data = $pi->data;

     $pi->as_string([$context, ...]);

     $pi->iter;

     $pi->accept($visitor, ...);
     $pi->accept_gi($visitor, ...);
     $pi->children_accept($visitor, ...);
     $pi->children_accept_gi($visitor, ...);

DESCRIPTION
===========

   An `SGML::PI' contains the data in a Processing Instruction (PI).

   `$pi->data' returns the data of the PI object.

   `$pi->as_string' returns an empty string.

   `$pi->iter' returns an iterator for the PI object, see `Class::Visitor'
for details.

   `$pi->accept($visitor[, ...])' issues a call back to
`$visitor->visit_SGML_PI($sdata[, ...])'.  See examples `visitor.pl' and
`simple-dump.pl' for more information.

   `$pi->accept_gi($visitor[, ...])' is implemented as a synonym for
accept.

   `children_accept' and `children_accept_gi' do nothing.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), SGML::Grove(3), Text::EntityMap(3), SGML::Element(3),
SGML::SData(3), Class::Visitor(3).

an SGML, XML, or HTML document SData replacement
************************************************

NAME
====

   SGML::SData - an SGML, XML, or HTML document SData replacement

SYNOPSIS
========

     $sdata = SGML::SData->new ($replacement[, $entity_name]);

     $name = $sdata->name;
     $data = $sdata->data;

     $sdata->as_string([$context, ...]);

     $sdata->iter;

     $sdata->accept($visitor, ...);
     $sdata->accept_gi($visitor, ...);
     $sdata->children_accept($visitor, ...);
     $sdata->children_accept_gi($visitor, ...);

DESCRIPTION
===========

   An `SGML::SData' contains the entity name and replacement value of a
character entity reference.

   `$sdata->name' returns the entity name of the SData object.

   `$sdata->data' returns the data of the SData object.

   The Perl module `Text::EntityMap' can be used to map commonly used
character entity sets to common output formats.

   `$sdata->as_string([$context, ...])' returns data surrounded by
brackets (`[ ... ]') unless `$context->{sdata_mapper}' is defined, in
which case it returns the result of calling the `sdata_mapper' subroutine
with data and the remaining arguments.  The actual implementation is:

     &{$context->{sdata_mapper}} ($self->data, @_);

   `$sdata->iter' returns an iterator for the sdata object, see
`Class::Visitor' for details.

   `$sdata->accept($visitor[, ...])' issues a call back to
`$visitor->visit_SGML_SData($sdata[, ...])'.  See examples `visitor.pl'
and `simple-dump.pl' for more information.

   `$sdata->accept_gi($visitor[, ...])' is implemented as a synonym for
accept.

   `children_accept' and `children_accept_gi' do nothing.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), SGML::Grove(3), Text::EntityMap(3), SGML::Element(3),
SGML::PI(3), Class::Visitor(3).

load an SGML, XML, or HTML document
***********************************

NAME
====

   SGML::SPGrove - load an SGML, XML, or HTML document

SYNOPSIS
========

     use SGML::SPGroveBuilder;
     $grove = SGML::SPGroveBuilder->new ($sysid);
     $root = $grove->root;
     $errors = $grove->errors;
     $entities = $grove->entities;
     $notations = $grove->notations;

     Other grove methods defined by SGML::Grove:

     $grove->as_string([$context, ...]);

     $grove->iter;

     $grove->accept($visitor, ...);
     $grove->accept_gi($visitor, ...);
     $grove->children_accept($visitor, ...);
     $grove->children_accept_gi($visitor, ...);

DESCRIPTION
===========

   new loads an SGML, XML, or HTML document instance from `$sysid' using
James Clark's SGML Parser (SP), returning a "grove" that contains the
root, or top, element of the document, an array of any warnings or errors
that may have been generated while parsing the document, and arrays of
notations and entities used within the document.

   `$sysid' is most often the file name of the SGML instance to be parsed,
but can be any of the ids described in "System Identifiers" in SP's
documentation.  For example, `$sysid' can also be a URL, `-' for standard
input, a literal string ("`<LITERAL>$scalar'"), or a formal system
identifier.

   `$grove->root' returns the `SGML::Element' of the outermost element of
the document.

   `$grove->errors' returns a reference to an array containing any errors
generated by SP or SGML::SPGroveBuilder while parsing the document or
building the grove.

   `$grove->entities' returns a reference to a hash containing any
entities referenced in this grove (as opposed to entities that may have
been declared but not used).

   `$grove->notations' returns a reference to an array containing any
notations referenced in this grove.

   Refer to SGML::Grove for details of as_string, `iter', accept,
`accept_gi', `children_accept', `children_accept_gi'.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), SGML::Grove(3) <http://www.jclark.com/sp/>
<http://www.jclark.com/sp/sysid.htm>

build a simple transformation package
*************************************

NAME
====

   SGML::Simple::BuilderBuilder - build a simple transformation package

SYNOPSIS
========

     use SGML::SPGroveBuilder;
     use SGML::Grove;
     use SGML::Simple::Spec;
     use SGML::Simple::SpecBuilder;
     use SGML::Simple::BuilderBuilder;

     $spec_grove = SGML::SPGroveBuilder->new ($spec_sysid);
     $spec = SGML::Simple::Spec->new;
     $spec_grove->accept (SGML::Simple::SpecBuilder->new, $spec);
     $builder = SGML::Simple::BuilderBuilder->new (spec => $spec
     						  [, eval_output => $fh]);

     $grove = SGML::SPGroveBuilder->new ($sysid);
     $object_tree_root = My::Object->new();
     $grove->accept ($builder->new, $object_tree_root);

DESCRIPTION
===========

   `BuilderBuilder' returns the package name of a package built using a
specification read from a specification file.  The key `spec' contains the
specification.  The key ``eval_output'' is either a file handle or a
scalar reference, instead of evaluating generated code `BuilderBuilder'
will print to or append to ``eval_output'', respectively.

   Passing a new "builder" to `accept_gi' of a grove will cause an output
object tree to be generated under `$object_tree_root' using the builder.

   `Builder' packages are all singletons, calling new always returns the
same object.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

     perl(1), SGML::Grove(3), SGML::Simple::Spec(3),
     SGML::Simple::SpecBuilder(3)

a simple transformation specification
*************************************

NAME
====

   SGML::Simple::Spec - a simple transformation specification

SYNOPSIS
========

     use SGML::SPGroveBuilder;
     use SGML::Simple::Spec;
     use SGML::Simple::SpecBuilder;
     use SGML::Simple::BuilderBuilder;

     $spec_grove = SGML::SPGroveBuilder->new ($spec_sysid);
     $spec = SGML::Simple::Spec->new;
     $spec_grove->accept (SGML::Simple::SpecBuilder->new, $spec);
     $builder = SGML::Simple::BuilderBuilder->new (spec => $spec);

DESCRIPTION
===========

   A `SGML::Simple::Spec' object containing `SGML::Simple::Spec::Rule'
objects is built by the `SpecBuilder' module from a grove of a simple
specification file.

   `SGML::Simple::Spec' and `SGML::Simple::Spec::Rule' inherit all methods
from `Class::Visitor' and `Class::Template'.  Fields are defined below.

   `Spec' objects are passed to `SGML::Simple::BuilderBuilder' to build a
Perl package for transforming other SGML groves.

`SGML::Simple::Spec'
--------------------

   `SGML::Simple::Spec' contains the following fields:

     default_prefix, default_object

   `default_prefix' defines the default package prefix to be used for
objects being created during a transform.  `default_object' defines an
object to be created when a make field is undefined in a rule.

     rules  --  an array

   rules contains the global set of rules for this transformation.

     stuff

   `stuff' contains extra Perl code to be added as part of the new package.

`SGML::Simple::Spec::Rule'
--------------------------

   `SGML::Simple::Spec::Rule' defines a single transformation rule and
contains the following fields:

     query

   A space seperated list of generic identifiers that this rule applies to.

     holder

   A flag indicating that this element merely contains other elements.  No
objects are created during the transformation.

     ignore

   A flag indicating that this element should be ignored.  No objects are
created during the transformation and no elements contained in this
element are processed.

     make

   The package name of an object to be created for this rule.  An object
in the `make' package is created to hold any elements contained in this
element.

     port

   A field name in the parent object to append this object to.  If not
defined, this object is added to the parent's `contents' field.

     rules  --  an array

   Rules that apply only within the current element.

     code

   If code is defined it is used in place of any code that would have been
generated by `BuilderBuilder', all other fields are ignored.  Code for a
holder element looks like this:

     my $self = shift; my $element = shift; my $parent = shift;
     $element->children_accept_gi ($self, $parent, @_);

   Code for creating a new object looks like this:

     my $self = shift; my $element = shift; my $parent = shift;
     my $obj = My::Object->new;
     $parent->push ($obj);
     $element->children_accept_gi ($self, $obj, @_);

   Code for switching a set of rules (the current "builder") looks like
this:

     my $self = shift; my $element = shift; my $parent = shift;
     $new_builder = Another::Builder->new;
     $element->children_accept_gi ($new_builder, $obj, @_);

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

     perl(1), SGML::Grove(3), SGML::Simple::SpecBuilder(3),
     SGML::Simple::BuilderBuilder(3), Class::Visitor(3),
     Class::Template(3)

build a SGML::Spec object
*************************

NAME
====

   SGML::Simple::SpecBuilder - build a SGML::Spec object

SYNOPSIS
========

     use SGML::SPGroveBuilder;
     use SGML::Grove;
     use SGML::Simple::Spec;
     use SGML::Simple::SpecBuilder;
     use SGML::Simple::BuilderBuilder;

     $spec_grove = SGML::SPGroveBuilder->new ($spec_sysid);
     $spec = SGML::Simple::Spec->new;
     $spec_grove->accept (SGML::Simple::SpecBuilder->new, $spec);
     $builder = SGML::Simple::BuilderBuilder->new (spec => $spec);

DESCRIPTION
===========

   `SpecBuilder' builds a new SGML::Spec object from a grove conforming to
the "Grove Simple Spec" DTD.

   The SGML::Spec object can be passed to `SGML::Simple::BuilderBuilder'
to create a new package for transforming other groves.

   See `SGML::Simple::Spec' for more details about the `Spec' object.

   `SpecBuilder' is a singleton, calling new always returns the same
object.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

     perl(1), SGML::Grove(3), SGML::Simple::Spec(3),
     SGML::Simple::BuilderBuilder(3)

a SubDoc entity defined in an SGML or XML document
**************************************************

NAME
====

   SGML::SubDocEntity - a SubDoc entity defined in an SGML or XML document

SYNOPSIS
========

     $name = $subdoc_entity->name;
     $data = $subdoc_entity->data;
     $system_id = $subdoc_entity->system_id;
     $public_id = $subdoc_entity->public_id;
     $generated_id = $subdoc_entity->generated_id;
     $attributes = $subdoc_entity->attributes;
     $notation = $subdoc_entity->notation;

     $subdoc_entity->iter;

     $subdoc_entity->accept($visitor, ...);

     The following are defined for type compatibilty:

     $subdoc_entity->as_string([$context, ...]);
     $subdoc_entity->accept_gi($visitor, ...);
     $subdoc_entity->children_accept($visitor, ...);
     $subdoc_entity->children_accept_gi($visitor, ...);

DESCRIPTION
===========

   An `SGML::SubDocEntity' contains a subdoc entity defined in a document
instance.  Within a grove, any entity with the same name refers to the
same `SGML::SubDocEntity' object.

   `$subdoc_entity->name' returns the entity name of the subdoc entity
object.

   `$subdoc_entity->data' returns the grove object of the subdoc if it has
been loaded (XXX but that's not been defined yet).

   `$subdoc_entity->accept($visitor[, ...])' issues a call back to
`$visitor->visit_SGML_SubDocEntity($subdoc_entity[, ...])'.  See examples
`visitor.pl' and `simple-dump.pl' for more information.

   `$subdoc_entity->as_string' returns an empty string.

   `$subdoc_entity->accept_gi($visitor[, ...])' is implemented as a
synonym for accept.

   `children_accept' and `children_accept_gi' do nothing.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), SGML::Grove(3), Text::EntityMap(3), SGML::Element(3),
SGML::PI(3).

write an SGML or XML grove
**************************

NAME
====

   SGML::Writer - write an SGML or XML grove

SYNOPSIS
========

     $writer = $SGML::Writer->new ([file_handle => $fh]
     				[, depth => $depth ]);
     $grove->accept ($writer);

DESCRIPTION
===========

   `SGML::Writer' writes a limited representation of a grove.
*file_handle* can be a file handle or a scalar reference, if it is a
scalar reference Writer will append to it.  Writer writes to standard
output if *file_handle* is not specified.

   XXX this code could do more, see `sgmlnorm(1)' in this node.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), SGML::Grove(3), sgmlnorm(1)

Perl interface to the NIST Secure Hash Algorithm
************************************************

NAME
====

   SHA - Perl interface to the NIST Secure Hash Algorithm

SYNOPSIS
========

     use SHA;

     $version = &SHA::sha_version;

     $context = new SHA;
     $context->reset();

     $context->add(LIST);
     $context->addfile(HANDLE);

     $digest = $context->digest();
     $string = $context->hexdigest();

     $digest = $context->hash($string);
     $string = $context->hexhash($string);

DESCRIPTION
===========

   The `SHA' module is *depreciated*.  Use `Digest::SHA1' instead.

   The current `SHA' module is just a wrapper around the `Digest::SHA1'
module.  It is provided so that legacy code that rely on the old interface
still work.  This wrapper does not support the old (and buggy) SHA-0
algorithm.

   In addition to the methods provided by `Digest::SHA1' this module
provide the class methods SHA->hash() and SHA->hexhash() that basically do
the same as the sha1() and sha1_hex() functions provided `Digest::SHA1'.

   The SHA->hex* methods will insert spaces between groups of 8 hex
characters, while the Digest::SHA1 version of the same methods will not do
this.

SEE ALSO
========

   See Digest/SHA1,

a MIB Compiler supporting SMIv1 and SMIv2
*****************************************

NAME
====

   SNMP::MIB::Compiler - a MIB Compiler supporting SMIv1 and SMIv2

SYNOPSIS
========

     use SNMP::MIB::Compiler;

     my $mib = new SNMP::MIB::Compiler;

     # search MIBs there...
     $mib->add_path('./mibs', '/foo/bar/mibs');

     # possibly using these extensions...
     $mib->add_extension('', '.mib', '.my');

     # store the compiled MIBs there..
     $mib->repository('./out');

     # only accept SMIv2 MIBs
     $mib->{'accept_smiv1'} = 0;
     $mib->{'accept_smiv2'} = 1;

     # no debug
     $mib->{'debug_lexer'}     = 0;
     $mib->{'debug_recursive'} = 0;

     # store compiled MIBs into files
     $mib->{'make_dump'}  = 1;
     # read compiled MIBs
     $mib->{'use_dump'}   = 1;
     # follow IMPORTS clause while compiling
     $mib->{'do_imports'} = 1;

     # load a precompiled MIB
     $mib->load('SNMPv2-MIB');

     # compile a new MIB
     $mib->compile('IF-MIB');

     print $mib->resolve_oid('ifInOctets'), "\n";
     print $mib->convert_oid('1.3.6.1.2.1.31.1.1.1.10'), "\n";
     print $mib->tree('ifMIB');

DESCRIPTION
===========

     SNMP::MIB::Compiler is a MIB compiler that fully supports
     both SMI(v1) and SMIv2. This module can be use to compile
     MIBs (recursively or not) or load already compiled MIBs for
     later use.
     Some tasks can be performed by the resulting object such as :

     - resolution of object names into object identifiers (OIDs).
       e.g. ifInOctets => 1.3.6.1.2.1.2.2.1.10

     - convertion of OIDs.
       e.g. 1.3.6.1.2.1.2.1 =>
              iso.org.dod.internet.mgmt.mib-2.interfaces.ifNumber

     - drawing MIB trees.
       e.g. ifTestTable => ifTestTable
                               |
                               +-- --- ifTestEntry(1)
                                   |
                                   +-- -rw Integer  ifTestId(1)
                                   +-- -rw Integer  ifTestStatus(2)
                                   +-- -rw ObjectID ifTestType(3)
                                   +-- -r- Integer  ifTestResult(4)
                                   +-- -r- ObjectID ifTestCode(5)
                                   +-- -rw String   ifTestOwner(6)

     The MIB to be compiled requires no modification. Everything legal
     according to SMIs is accepted, including MACRO definitions (which
     are parsed but ignored).

     This module is shipped with the basic MIBs usually needed by IMPORTS
     clauses. A lot of IETF MIBs has been successfully tested as well as
     some private ones.

Methods
=======

new
     `SNMP::MIB::Compiler::new()' *class method*

     To create a new MIB, send a new() message to the SNMP::MIB::Compiler
     class.  For example:

          my $mib = new SNMP::MIB::Compiler;

     This will create an empty MIB ready to accept both SMIv1 and SMIv2
     MIBs. A lot of attributes can be (des)activated to obtain a more or
     less strict and verbose compiler.  The created object is returned.

`add_path'
     `SNMP::MIB::Compiler::add_path(p1[,p2[,p3]])' *object method*

     Add one or more directories to the search path. This path is used to
     locate a MIB file when the 'compile' method is invoqued.  The current
     list of paths is returned.

     Example:

          # search MIBs in the "mibs" directory (relative
          # to cwd) and in "/foo/bar/mibs" (absolute path)
          $mib->add_path('./mibs', '/foo/bar/mibs');

`add_extension'
     `SNMP::MIB::Compiler::add_extension(e1[,e2[,e3]])' *object method*

     Add one or more extensions to the extension list. These extensions are
     used to locate a MIB file when the 'compile' method is invoqued. All
     extensions are tested for each directory specified by the add_path()
     method until one match.  The current list of extensions is returned.

     Example:

          $mib->add_path('./mibs', '/foo/bar/mibs');
          $mib->add_extension('', '.mib');
          $mib->compile('FOO');

          The order is "./mibs/FOO", "./mibs/FOO.mib", "/foo/bar/mibs/FOO"
          and "/foo/bar/mibs/FOO.mib".

`repository'
     `SNMP::MIB::Compiler::repository([dir])' *object method*

     If 'dir' is defined, set the directory where compiled MIBs will be
     stored (using the compile() method) or loaded (using the load()
     method).  The repository MUST be initialized before a MIB can be
     compiled or loaded.  The current repository is returned.

     Example:

          $mib->repository('./out');
          print "Current repository is ", $mib->repository, "\n";

compile
     `SNMP::MIB::Compiler::compile(mib)' *object method*

     Compile a MIB given its name. All information contained in this MIB
     is inserted into the current object and is stored into a file in the
     repository (see the 'make_dump' attribute).  The choosen name is the
     same as the real MIB name (defined in the MIB itself). If a
     precompiled MIB already exists in the repository and is newer than
     the given file, it is used instead of a real compilation (see the
     'use_dump' attribute).  The compiler can be recursive if IMPORTS
     clauses are followed (see the 'do_imports' attribute) and in that
     case, uncompiled MIB names must be explict according to paths and
     extensions critaeria (see add_path() and add_extensions() methods).
     The current object is returned.

load
     `SNMP::MIB::Compiler::load(mib)' *object method*

     Load a precompiled MIB given its name. All information contained in
     this MIB is inserted into the current object. The file is searched in
     the repository which MUST be initialized. In case of success, returns
     1 else returns 0.

     Example:

          $mib->load('SNMPv2-SMI');
          $mib->load('SNMPv2-MIB');

`resolve_oid'
     `SNMP::MIB::Compiler::resolve_oid(node)' *object method*

     Example:

          print $mib->resolve_oid('ifInOctets'), "\n";

`convert_oid'
     `SNMP::MIB::Compiler::convert_oid(oid)' *object method*

     Example:

          print $mib->convert_oid('1.3.6.1.2.1.31.1.1.1.10'), "\n";

`tree'
     `SNMP::MIB::Compiler::tree(node)' *object method*

     Example:

          print $mib->tree('ifMIB');

Attributes
==========

`do_imports'

`accept_smiv1'

`accept_smiv2'
`allow_underscore'
`allow_lowcase_hstrings'
`allow_lowcase_bstrings'
`make_dump'
`dumpext'
`use_dump'
`debug_lexer'
`debug_recursive'
BUGS
====

   Currently, it is more a TODO list than a bug list.

   - not enough documentation

   - not enough methods

   - not enough test scripts

   - find a better name for compiled MIBs than 'dump's.. even if they are
no more than dumps.

   If your MIBs can't be compiled by this module, please, double check
their syntax. If you really think that they are correct, send them to me
including their "uncommon" dependencies.

AUTHOR
======

   Fabien Tassin (fta@oleane.net)

COPYRIGHT
=========

   Copyright 1998, 1999, Fabien Tassin. All rights reserved.  It may be
used and modified freely, but I do request that this copyright notice
remain attached to the file. You may modify this module as you wish, but
if you redistribute a modified version, please attach a note listing the
modifications you have made.

Snmp modules to perform snmp set,get,walk,next,walk_hash etc.
*************************************************************

NAME
====

   SNMP::Util - Snmp modules to perform snmp set,get,walk,next,walk_hash
etc.

SYNOPSIS
========

   `use SNMP::Util;'

   ## Documentation (POD) =head1 NAME

     Perl SNMP utilities - SNMP::Util - Version 1.8

DESCRIPTION
===========

   This Perl library is a set of utilities for configuring and monitoring
SNMP based devices.  This library requires the UCD port of SNMP and the
SNMP.pm module writted by Joe Marzot.

Version          1.0 Initial Release     1.1 Fixed Manifest File     1.2 Added get_hash / walk_hash now calls walk / Modified output in poll_value     1.3 Added use strict to library and fixed some bugs with my vars     1.4 Fixed code to elminate perl warning     1.5 Changed all mapInt functions to mapEnum - (support for mapInt not in          Joe Marzot's version 1.8).     1.6 Updated docs html and text     1.7 Includes patches from Charles Anderson      1.8 Includes patches from  tyoshida
===============================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================

Software requirements
=====================

   The following applications need to be built and installed before
running the SNMP::Util application.

     ucd-snmp-3.5 - ftp:://ftp.ece.ucdavis.edu:/pub/snmp/ucd-snmp.tar.gz
     SNMP-1.8 - www.perl.com/CPAN

Summary of functions
====================

     get - snmpget and return formatted array
     get_hash - snmpget and return hash
     get_set_restore - get value, set new range of values and restore value
     next - snmpnext and return formatted array
     ping_check - get uptime and return 1 if reachable
     ping_check_exit - get uptime and exit if not reachable
     poll_device - poll a device until it becomes reachable
     poll_devices - poll several devices until they becomes reachable
     poll_value - snmpget in a loop until variable reaches desired state
     set - snmpset and return
     set_get - snmpset followed by get and check
     walk - snmpwalk and return formatted array
     walk_hash - snmpwalk and return hash ($hash->{mibname}{index} = value)

Creation on the SNMP::Util object
=================================

   You must first do a use statement to pull in the library. Then the snmp
object can be created.

     #!/usr/local/lib/perl
     use lib "put lib path here"
     use SNMP::Util;

     The SNMP::Util object is created as follows:

     $snmp = new SNMP::Util(-device => $IP,
                           -community => $community,
                           -timeout => 5,
                           -retry => 0,
                           -poll => 'on',
                           -poll_timeout => 5,
                           -verbose => 'off',
     	 	       -errmode => 'return',
                           -delimiter => ' ',
     		      )

     community = snmp community string
     timeout = snmp timeout in seconds (You may also use sub second values ie 0.5)
     retry = number of snmp retries on timeouts
     poll = poll the unreachable device after number of retries reached and then retry again
     poll timeout = poll timeout in minutes default = 5 minutes
     verbose = controls the output of the snmp low level library
     errmode = error mode ('return' on error or 'die' on error) default = return
     delimeter = specifies the character to use between octets when getting octet-strings

     Note: Delimiter can also be set by using the setting the Global variable as follows:
           $SNMP::Util::Delimiter = '-'

Creating and using multiple objects
-----------------------------------

   First populate an array of IP addresses:

     @IP_array = ('1.1.1.1','1.1.1.2','1.1.1.3','1.1.1.4')

     foreach $IP (@IP_array){

     $snmp->{$IP} = new SNMP::Util(-device => $IP,
                       -community => $community,
     		      -timeout => 5,
     		      -retry => 0,
     		      -poll => 'on',
     		      -delimiter => ' ',
     		      )
      }

     #Now get the uptime for each switch
     foreach $IP (@IP_array){
         $uptime = $snmp->{$IP}->get('v','sysUpTime.0')
         print "Uptime for $IP = $uptime\n"
     }

How to use the object for a simple snmpget
==========================================

     $uptime = $snmp->get('v','sysUpTime.0')
               where 'v', is the format of the output (v = value)
               and $uptime contains the system uptime in 10ths of seconds

MIB Loading
===========

   The SNMP::Util module loads the mib using the SNMP::Util_env.pm module
by using the following statements.

     use SNMP::Util_env
     # Initialize mib
     &SNMP::initMib()

     You must update the SNMP::Util_env.pm file or simply set up these environment
     variables and the SNMP::Util_env.pm file will not override them.

     The environment variables are as follows:

     $ENV{'MIBDIRS'} = '/usr/local/lib/snmp/mibs'
     $ENV{'MIBFILES'} = '/ats/data/mibs/rfc1850.mib:
     /ats/data/mibs/rfc1406.mib:/ats/data/mibs/rfc1407.mib:
     /ats/data/mibs/rfc1595.mib:/ats/data/mibs/rfc1724.mib'

     You can specify whatever MIBS you would like to load.

Error Handling method
=====================

   All error handling is done through the error handling method (error).
The error message can be obtained by using the method (errmsg) The
detailed error message can be obtained by using the method (errmsg_detail)

   This error method returns a boolean result to indicate if an error
ocurred

     example:

     if ($snmp->error){
     	$error = $snmp->errmsg;
     	$error_detail = $snmp->errmsg_detail;
     	print "snmp error = $error\n";
     	print "snmp error detail = $error_detail\n";
     }

Print Output Logging
====================

   The printing of output is controlled by the logging routine.  the
amount of output is configured by setting the MAX_LOG_LEVEL environment
variable.  There are four levels of output logging:
(none,status,fail,debug).  You may also set the logging using the global
variable Max_log_level.

     none = print  no output (use errmsg only for errors)
     status = print general status information
     fail = print general status and failures
     debug = print general status, failures, and debug information

     You can set the environment variable in your environment or inside the
     program using the following format:

        $env{'MAX_LOG_LEVEL'} = 'debug'

     or using the global
     $SNMP::Util::Max_log_level = 'debug'

     Example Output from Logging:

     get (noSuchName) There is no such variable name in this MIB.
     snmpget 100.100.100.1 public 1.3.6.1.2.1.2.2.1.1.1 1.3.6.1.2.1.2.2.1.7.1
     snmpget 100.100.100.1 public ifIndex.1 ifAdminStatus.1
     snmp error index = 1

     Note: error index = the index of the var bind that failed

Formatting SNMP output (get, next, walk)
========================================

   The SNMP utilities have a formatting function which will format the
return values which are most cases an array.

     The format options are specified as strings as follows:

     print " format string = oOnNtvei\n"
     print " o = oid with index\n"
     print " O = oid without index\n"
     print " n = name with index\n"
     print " N = name without index\n"
     print " t = type\n"
     print " v = value\n"
     print " e = enumeration\n"
     print " i = instance of the mib variable\n\n"

     Note: enumerations apply to integers and timeticks.  It will convert integer values
     to enumerations and it will convert timeticks to days,hours,minutes,seconds.

     example usage:

     @result = $snmp->get('nve','sysUptime.0')
     $result[0] = sysUptime.0
     $result[1] = 13392330
     $result[2] = 1 days, 13:12:03

     Note: Any format can be used for the (get,walk,next routines)
           Only 'e' or 'v' is needed in the walk_hash routine.

   This formatting was designed to allow the user to format the output in
whatever format they need for there application.  You may want to use the
'v' option when comparing timetick values, but you may want to use the 'e'
option for the human readable display.

   The snmpget routine may be equated to an array if the formatting has
more than one value or it may be equated to a scalar value if the
formatting has only one value.  It must be equated to an array if the
snmpget is a multi var bind.

Input Formatting
================

   The input supplied to the SNMP functions is designed to be very
flexible and allows the user to use shortcuts to apply instances to
variables.

Input formatting options for the get,next,walk
----------------------------------------------

   *Simple format name.instance or oid.instance*

     $snmp->get('e','ifIndex.1','ifAdminStatus.1','ifOperStatus.1')
     $snmp->get('e','1.3.6.1.2.1.2.2.1.1.1','1.3.6.1.2.1.2.2.1.7.1','1.3.6.1.2.1.2.2.1.8.1')

   *Shortcut format instance up front (no instance in mib name or oid*

     $snmp->get('e',1,'ifIndex','ifAdminStatus','ifOperStatus')
     $snmp->get('e',1,'1.3.6.1.2.1.2.2.1.1','1.3.6.1.2.1.2.2.1.7','1.3.6.1.2.1.2.2.1.8')

   *Long format name,instance,name,instance etc of
oid,instance,oid,instance etc*

     $snmp->get('e','ifIndex',1,'ifAdminStatus',1,'ifOperStatus',1)
     $snmp->get('e','1.3.6.1.2.1.2.2.1.1',1,'1.3.6.1.2.1.2.2.1.7',1,'1.3.6.1.2.1.2.2.1.8',1)

   You may also set up an array for any of the above formats and pass the
array into the get function as follows:

     @oids = ('ifIndex.1','ifAdminStatus.1','ifOperStatus.1')
     $snmp->get('e',@oids)

   *Hash like format* name => instance or oid => instance

     $interface = 1
     $snmp->get(
     	   'e',
     	   ifIndex => $interface,
     	   ifAdminStatus => $interface,
     	   ifOperStatus => $interface,
     	   ifSpeed => $interface,
     	   )
     or

     $snmp->get(
     	   index => $interface,
     	   ifIndex,
     	   ifAdminStatus,
     	   ifOperStatus,
     	   ifSpeed,
     	   )

   *Calling get with dashed options*

     @result = $snmp->get(
                         -format => 'ne',
                         -oids => [
                                   ifIndex => $interface,
                                   ifAdminStatus => $interface,
                                   ifOperStatus => $interface,
                                   ifSpeed => $interface,
                                   ],
                        )
     or
     @oids = ('ifIndex.1','ifAdminStatus.1','ifOperStatus.1')
     @result = $snmp->get(
                         -format => 'ne',
                         -oids => \@oids,
     		     )

     Note: When using the dashed option format, you must pass the array by reference as shown
     above.

     =head2 Input formats for the set routine

   *Simple format name.instance,value or oid.instance,value*

     $snmp->set('ifAdminStatus.1','up')
     $snmp->set('1.3.6.1.2.1.2.2.1.7.1','up')

   *Shortcut format instance up front (no instance in mib name or oid*

     $snmp->set(1,'ifAdminStatus','up')
     $snmp->set(1,'1.3.6.1.2.1.2.2.1.7','up')

   *Long format name,instance,value or oid,instance,value*

     $snmp->set('ifAdminStatus',1,'up')
     $snmp->set('1.3.6.1.2.1.2.2.1.7',1,'up')

     You may also set up an array for any of the above formats and pass the array into the
     get method as follows:

     @oids = ('ifAdminStatus.1','up')
     $snmp->set(@oids)

   *Hash like format*

     $snmp->set(
     	   "ifAdminStatus.$interface" => 'up',
     	   )
     or

     $snmp->set(
     	   index => $interface,
     	   "ifAdminStatus" => 'up',
     	   )

     =head1 SNMP Method summary

get
---

   The get will do a snmpget and return an array specified by the format
statement.

     Usage: @result = $snmp->get('ne','ifAdminStatus.1')
            $result[0] = ifAdminStatus.1
     	$result[1] = 'up'

     $result = $snmp->get('e','ifAdminStatus.1')
             Note: As shown above, the result is a scalar if only one value is returned

get_hash
--------

   This method will do an snmpget and return a hash.   The format for the
hash is (value = $hash->{mibname}{index}).

     example: $hash = $snmp->get_hash('ne','ifIndex.1','ifIndex.2',
     				  'ifOperStatus.1','ifOperStatus.2');

     $hash->{ifIndex}{1} = 1
     $hash->{ifIndex}{2} = 2
     $hash->{ifOperStatus}{1} = up
     $hash->{ifOperStatus}{2} = up

     Note: Valid format statements for get_hash are 'ne' or 'nv'

     =head2 get_set_restore

   The get_set_restore will get the variable, set it to a range and
restore the value

     Usage:  @result = $snmp->get_set_restore('1..10','ifAdminStatus.1');
             where the value '1..10' is the range of values

     Note: The range is specified using .. for ranges and , for individual values.

next
----

   The next will do a snmpnext and return an array specified by the format
statement.

     Usage:  @result = $snmp->next('ne','ifAdminStatus.1')
     	$result[0] = ifAdminStatus.2
     	$result[1] = 'up'

     $result = $snmp->next('e','ifAdminStatus.1')
             Note: As shown above, the result is a scalar if only one value is returned

     =head2 ping_check

   The ping_check will do a snmpget of uptime and return 1 if device is
alive

ping_check_exit
---------------

   The ping_check will do a snmpget of uptime and exit if not alive

poll_device
-----------

   The poll_device will loop on the snmpget of uptime command until the
device is reachable.  The loop will exit once the poll_timeout time is
reached (default = 5 minutes).

poll_devices
------------

   The poll_devices will do a snmpget of uptime on several devices until
the device are reachable.  The loop will exit once the poll_timeout time
is reached (default = 5 minutes).

     $snmp->poll_devices(@IP_array);
     where @IP_array = array of IP addresses

poll_value
----------

   The poll value method will poll a mib variable until it reaches that
state and returns the amount of time it took to reach that state

     Usage: $snmp->poll_value(-oid => "ifAdminStatus.$interface",
     			 -state => 'up',
     			 -timeout => 120,
     			 -montime => 5,
     			 -delay   => 1)

     or

     $snmp->poll_value(-oid     => "1.3.6.1.2.1.2.2.1.8",
                      -instance => $interface,
                      -state => 'up',
                      -timeout => 120,
                      -montime => 5,
                      -delay   => 1)

   or

     use a array ref if you want the polling to stop when the result
     matches more than one value

     $snmp->poll_value(-oid     => "1.3.6.1.2.1.2.2.1.8",
                      -instance => $interface,
                      -state => ['up','down']
                      -timeout => 120,
                      -montime => 5,
                      -delay   => 1)

     Note: You must use the instance when using oids.

set
---

   The set will set a group of variables and return 1 if passed

     Usage:  @result = $snmp->set(
     			     index => 1,
     			     ifAdminStatus => 'up',
     			     )

set_get
-------

   The set_get will set a group of variables,get,check and return 1 if
passed

     Usage:  @result = $snmp->set(
     			     index => 1,
     			     ifAdminStatus => 'up',
     			     )

walk
----

   The walk will do a snmpwalk and return an array specified by the format
statement. It also has a special print option to print out each loop in the
walk. This method is capable of doing multivarbind walks.

     Usage: @result = $snmp->walk(-format => 'ne',
     			       -oids =>['ifAdminStatus'],
     			       -print => 'on');

     		  where print = 'on' or 'off'

     or use the shortcut format (Note: print will be disabled by default

     @result = $snmp->walk('ne','ifAdminStatus');

     $result[0] = ifAdminStatus.1
     $result[1] = 'up'
             $result[2] = ifAdminStatus.2
     $result[3] = 'up'
             ...

walk_hash
---------

   The walk_hash will do a snmpwalk and return a hash with the value
specified by the format.  This method is capable of doing multivarbind
walks.

     Usage: $result = $snmp->walk_hash('e','ifIndex','ifAdminStatus','ifOperStatus')
            $result->{ifIndex}{1} = 1
     	$result->{ifAdminStatus}{1} = 'up'
            $result->{ifOperStatus}{1} = 'up'
     	$result->{ifIndex}{2} = 2
     	$result->{ifAdminStatus}{2} = 'up'
            $result->{ifOperStatus}{2} = 'up'

     or
     Usage: $result = $snmp->walk_hash('v','ifIndex','ifAdminStatus','ifOperStatus')
            $result->{ifIndex}{1} = 1
     	$result->{ifAdminStatus}{1} = 1
            $result->{ifOperStatus}{1} = 1
     	$result->{ifIndex}{2} = 2
     	$result->{ifAdminStatus}{2} = 1
            $result->{ifOperStatus}{2} = 1

Library for SOAP clients and servers in Perl
********************************************

NAME
====

   SOAP - Library for SOAP clients and servers in Perl

SYNOPSIS
========

     use SOAP;
     print "This is SOAP/Perl-$SOAP::VERSION\n";

DESCRIPTION
===========

   SOAP/Perl is a collection of Perl modules which provides a simple and
consistent application programming interface (API) to the Simple Object
Access Protocl (SOAP).

   To learn more about SOAP, see the W3C note at
<URL:http://www.w3.org/TR/SOAP>

   This library provides tools for you to build SOAP clients and servers.

   The library contains modules for high-level use of SOAP, but also
modules for lower-level use in case you need something a bit more
customized.

   SOAP/Perl uses Perl's object oriented features exclusively. There are
no subroutines exported directly by these modules.

   This version of SOAP/Perl supports the SOAP 1.0 specification, which is
an IETF internet draft. See <URL:http://www.ietf.org> for details.

   The main features of the library are:

   * Contains various reusable components (modules) that can be used
     separately or together.

   * Provides an object oriented model for serializing/deserializing and
     sending/receiving SOAP packets (lovingly referred to in some circles
     as SOAP bars). Within this framework we currently support access to
     SOAP over HTTP, but we're open to expanding support for SOAP over
     SMTP and other transports in the future.

   * Provides a fully object oriented interface.

   * Supports SOAP 1.1 spec. The current version does not yet handle
     arrays.

   * Supports serializing/deserializing of sophisticated object graphs
     which may have cycles (a circular queue would serialize just fine,
     for instance).

   * Provides full namespace support for SOAP 1.1, which is recommended by
     the spec.

   * Implements full support for SOAP 1.1 references, including correctly
     dealing with shared references between header and body elements.

   * Experimental support for extensibility of the
     serialization/deserialization architecture has been included; see
     SOAP::TypeMapper for details, and SOAP::Struct and
     SOAP::StructSerializer for a specific example.

   * Supports servers using CGI or Apache+mod_perl. Tested with Apache on
     Linux as well as IIS on Windows 2000.

The EnvelopeMaker Object
------------------------

   SOAP::EnvelopeMaker takes as input an array of header objects and a
single body object (currently these "objects" are either Perl hashes, or
instances of SOAP::Struct), and produces as output an XML stream.

The Parser Object
-----------------

   SOAP::Parser takes as input a string (or a file/file handle) and parses
the content as a SOAP envelope. This results in an array of header objects
and a single body element.

   To avoid coupling the SOAP serialization/deserialization code to HTTP,
a set of loadable transports is also provided. See the following modules
for documentation of the transport architecture:

     SOAP::Transport::HTTP::Client
     SOAP::Transport::HTTP::Server
     SOAP::Transport::HTTP::Apache
     SOAP::Transport::HTTP::CGI

Where to Find Examples
----------------------

   See SOAP::EnvelopeMaker for a client-side example that shows the
serialization of a SOAP request, sending it over HTTP and receiving a
response, and the deserialization of the response.

   See SOAP::Transport::HTTP::Apache for a server-side example that shows
how to map incoming HTTP requests to method calls on your own Perl classes.

OVERVIEW OF CLASSES AND PACKAGES
================================

   This table should give you a quick overview of the classes provided by
the library.

   - High-level classes you should begin with -  SOAP::Struct          -
Ordered collection often used to                           hold SOAP
requests and responses  SOAP::TypedPrimitive  - Adds an explicit xsi:type
to stream  SOAP::EnvelopeMaker   - Serializes objects into SOAP bars
SOAP::Parser          - Deserializes SOAP bars into objects
SOAP::Transport       - Description of transport architecture
SOAP::Transport::HTTP - Description of HTTP transport
SOAP::Transport::HTTP::Client - Client side support for HTTP,
                    using libwww-perl  SOAP::Transport::HTTP::Server -
Server side support for HTTP,                                   decoupled
from web server APIs  SOAP::Transport::HTTP::Apache - Apache/mod_perl
support  SOAP::Transport::HTTP::CGI    - Vanilla CGI support

   - Serialization architecture -

     SOAP::Envelope      -- Low level access to SOAP serialization
     SOAP::OutputStream  -- used in conjunction with SOAP::Envelope for
                            Low level access to SOAP serialization
     SOAP::Packager      -- Helps to implement SOAP 1.0 packages,
                            used by SOAP::Envelope and SOAP::OutputStream
     SOAP::GenericHashSerializer    -- Generic serializer for Perl hash references
     SOAP::GenericScalarSerializer  -- Generic serializer for Perl scalars
     SOAP::TypedPrimitiveSerializer -- Specialized serializer
     SOAP::StructSerializer         -- Specialized serializer

   - Deserialization architecture -

     SOAP::GenericInputStream.pm   -- Look here if you are interested in
                                      extending the deserialization framework
                                      to be able to deserialize your own objects
     -- Miscellaneous --

     SOAP::TypeMapper    -- An experimental extensibility point for the
                            serialization architecture
     SOAP::Defs          -- Constants used by the other modules

MORE DOCUMENTATION
==================

   All modules contain detailed information on the interfaces they provide.

BUGS AND LIMITATIONS
====================

   The serialization framework does not yet handle arrays, and the HTTP
transport does not handle M-POST.

ACKNOWLEDGEMENTS
================

   Keith Brown is the original and current author of this work, but he
worked very closely with Don Box in developing a common design and
implementation architecture (Don was building a Java implementation
side-by-side, and Keith and Don worked together in a kind of XP style of
programming - it was fun). GopalK at Microsoft was tremendously helpful in
ferreting out issues in the SOAP spec. Mike Abercrombie at DevelopMentor
(where Keith and Don work) was very supportive of the effort as well.
Thanks Mike!

COPYRIGHT
=========

     Copyright 1999-2000, DevelopMentor. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AVAILABILITY
============

   The latest version of this library is normally available from CPAN as
well as:

     http://soapl.develop.com/soap_perl_current

   The best place to discuss this code is on the SOAP mailing list at:

     http://discuss.develop.com/soap.html

Spec-defined constants
**********************

NAME
====

   SOAP::Defs - Spec-defined constants

SYNOPSIS
========

     use SOAP::Defs;

DESCRIPTION
===========

   This is an internal class that exports global symbols needed by various
SOAP/Perl classes. You don't need to import this module directly unless
you happen to be building SOAP plumbing (as opposed to simply writing a
SOAP client or server).

AUTHOR
======

   Keith Brown

Creates SOAP streams
********************

NAME
====

   SOAP::Envelope - Creates SOAP streams

SYNOPSIS
========

     use SOAP::Envelope;

     sub output_fcn {
         my $string = shift;
         print $string;
     }

     my $namespaces_to_preload = ["urn:foo", "urn:bar"];
     my $env = SOAP::Envelope->new(\&output_fcn,
                                   $namespaces_to_preload);
     my $header = $env->header("urn:a", "MyHeaderA",
                               undef, undef,
                               0, 0);
     ...
     $header->term();

     $header = $env->header("urn:b", "MyHeaderB",
                            undef, undef,
                            0, 0);
     ...
     $header->term();

     my $body = $env->body("urn:c", "MyCall",
                           undef, undef);
     ...
     $body->term();

     $env->term();

DESCRIPTION
===========

   This class bootstraps and manages the serialization of an object graph
into a SOAP stream. It is used by the SOAP::Transport classes, but may be
used directly as well.

The new function
----------------

   Creates a new envelope. If you know you'll be using certain namespaces
a lot, you can save some space by preloading those namespaces (pass the
set of URI strings as an array when creating a new envelope, as in the
example above).

The header function
-------------------

   Creates a new header in the specified namespace URI (which is required).
You can call this function multiple times to create several different
headers, but don't call the body function until you've created all the
headers.  If omitted, the typename and typeuri will be taken from the
accessor name and accessor uri, but the accessor name and uri are required.
Be sure to term() the current header before creating a new one.  For a
discussion of the $object optional parameter, please see body(), below.

The body function
-----------------

   Creates the body. You can only call this function once per envelope,
and you must call it after you're done creating all the headers you need
to create. If omitted, the typename and typeuri will be taken from the
accessor name and accessor uri, but the accessor name is required.  The
$object parameter is optional, but must be passed if headers (or
subelements in the body) may point to the body itself. SOAP::Envelope adds
this object reference into its identity dictionary to correctly deal with
these cases (a doubly-linked list is a simple example of this case).  If
you pass $object, you have to be prepared for body() to return undef,
which indicates that the object was already marshaled into the header area
(because it was referred to by a header element). In this case, the body
element will simply be a reference to the previously marshaled body.  If
body() returns a value, don't forget to call term() through it when you're
done serializing the body, because this forces the output of any
outstanding multi-ref items.

The term function
-----------------

   This writes an end tag, terminating the SOAP envelope.

DEPENDENCIES
============

   SOAP::OutputStream SOAP::Packager SOAP::Defs

AUTHOR
======

   Keith Brown

SEE ALSO
========

   SOAP::OutputStream SOAP::Transport::HTTP

Creates SOAP envelopes
**********************

NAME
====

   SOAP::EnvelopeMaker - Creates SOAP envelopes

SYNOPSIS
========

   use SOAP::EnvelopeMaker;

   my $soap_request = "; my $output_fcn = sub {     $soap_request .= shift;
}; my $em = SOAP::EnvelopeMaker->new($output_fcn);

   my $body = SOAP::Struct->new(     origin => { x => 10,  y => 20  },
corner => { x => 100, y => 200 }, );

   $em->set_body("urn:com-develop-geometry", "calculateArea", 0, $body);

   my $host        = "soapl.develop.com"; my $port        = 80; my
$endpoint    = "/soap?class=Geometry"; my $method_uri  =
"urn:com-develop-geometry"; my $method_name = "calculateArea";

   use SOAP::Transport::HTTP::Client;

   my $soap_on_http = SOAP::Transport::HTTP::Client->new();

   my $soap_response = $soap_on_http->send_receive($host, $port, $endpoint,
                                               $method_uri,
                                 $method_name,
                    $soap_request); use SOAP::Parser; my $soap_parser =
SOAP::Parser->new(); $soap_parser->parsestring($soap_response);

   my $area = $soap_parser->get_body()->{result};

   print "The area is: $area\n";

DESCRIPTION
===========

   The overall usage pattern of SOAP::EnvelopeMaker is as follows:

   1) Determine what you want to do with the resulting SOAP packet    and
create an output function that implements this policy.

   2) Create an instance of SOAP::EnvelopeMaker, passing a reference    to
your output function, or to a string if you were just planning    on
buffering the output anyway (in this case, you'll get an output
function that looks like this: sub {$$r .= shift}

   (note that somebody may already have done these first two steps  on
your behalf and simply passed you a reference to a pre-initialized
EnvelopeMaker - see SOAP::Transport::HTTP::Server for an example)

   3) (optional) Call add_header one or more times to specify headers.

   4) (required) Call set_body to specify the body.

   5) Throw away the EnvelopeMaker and do something with the envelope
that you've collected via your output function (assuming you've    not
simply been piping the output somewhere as it's given to you).

   EnvelopeMaker expects that you'll add *all* your headers *before*
setting the body - if you mess this up, the results are undefined.

   By the time set_body returns, a complete SOAP envelope will have been
sent to your output function (in one or more chunks). You can

new(OutputFcn)
--------------

   OutputFcn should accept a single scalar parameter, and will be called
multiple times with chunks of the SOAP envelope as it is constructed.  You
can either append these chunks into a big string, waiting until the entire
envelope is constructed before you do something with it (like calculate
the content-length, for instance), or you can simply pipe each chunk
directly to somebody else.

   As of version 0.25, you can now pass a string reference for OutputFcn
and the EnvelopeMaker will provide a very simple buffering output function
(one that we all ended up writing anyway during testing): sub {$$r .=
shift}

add_header(AccessorUri, AccessorName, MustUnderstand, IsPackage, Object)
------------------------------------------------------------------------

   The first two parameters allow you to specify a QName (qualified name)
for your header. Note that in SOAP, all headers MUST be namespace
qualified. MustUnderstand and IsPackage turn on SOAP features that are
explained in the SOAP spec; if you haven't yet grok'd SOAP packages, just
pass 0 for IsPackage. Finally, Object is whatever you'd like to serialize
into the header (see set_body for notes on what can go here; headers can
contain the same stuff as the body).

set_body(AccessorUri, AccessorName, IsPackage, Object)
------------------------------------------------------

   The first two parameters allow you to specify a QName (qualified name)
for the body. The name of the accessor is the name of the SOAP method call
you're making. IsPackage says that the body will be a SOAP package; just
pass 0 if you're not sure what this means. Object is whatever you'd like
to serialize. This can be one of the following things:

   1) a scalar - the body will contain the scalar content.

   2) a hash reference - the body will contain a SOAP serialized version
                   of the contents of the hash.

   3) a SOAP::Struct reference - the body will contain a SOAP serialized
                           version of the struct, where the serialized
                          contents of the struct will be in the same
                        order in the SOAP bar as they appeared
                  in the SOAP::Struct constructor.

   Note that the SOAP/Perl serialization architecture deals with references
very carefully, so it is possible to pass arbitrary object graphs (although
each "object reference" must currently be a non-blessed scalar or hash
reference).

   In the future, expect to see support for passing blessed object
references (if you want to do this today, see the experimental
SOAP::TypeMapper).  SOAP::Struct is an example of this.

   One interesting thing SOAP (and SOAP/Perl) support is that the headers
and body can share references. They can point to the same stuff. Also,
cycle detection is a natural part of SOAP/Perl's serialization
architecture, so you can pass linked lists, circular queues, etc. and they
will be rehydrated correctly.

DEPENDENCIES
============

   SOAP::Envelope

AUTHOR
======

   Keith Brown

SEE ALSO
========

   SOAP::Envelope

Generic serializer for Perl hashes
**********************************

NAME
====

   SOAP::GenericHashSerializer - Generic serializer for Perl hashes

SYNOPSIS
========

DESCRIPTION
===========

   Serializes a vanilla Perl hash to a SOAP::OutputStream.  Note that Perl
hashes are unordered, so the serialization order is not guaranteed. Use
SOAP::Struct as opposed to a hash if you need to preserve order (this is
actually a requirement of the SOAP spec).

DEPENDENCIES
============

   SOAP::Serializer

AUTHOR
======

   Keith Brown

Default handler for SOAP::Parser output
***************************************

NAME
====

   SOAP::GenericInputStream - Default handler for SOAP::Parser output

SYNOPSIS
========

     use SOAP::Parser;

     my $parser = SOAP::Parser->new();

     $parser->parsefile('soap.xml');

     my $headers = $parser->get_headers();
     my $body    = $parser->get_body();

DESCRIPTION
===========

   As you can see from the synopsis, you won't use SOAP::GenericInputStream
directly, but rather the SOAP::Parser will create instances of it when
necessary to unmarshal SOAP documents.

   The main reason for this documentation is to describe the interface
exposed from SOAP::GenericInputStream because you need to implement this
interface if you'd like to have the parser create something more exotic
than what SOAP::GenericInputStream produces.

new(TypeUri, TypeName, Resolver)
--------------------------------

   TypeUri and TypeName are strings that indicate the type of object being
unmarshaled. Resolver is a function pointer takes a single argument, the
resulting object, and you should call through this pointer in your
implementation of term (which means you need to store it until term is
called). Here's an example of a minimal implementation, assuming you've
stored the object reference in $self->{object}:

     sub new {
         my ($class, $typeuri, $typename, $resolver) = @_;
         return bless { resolver => $resolver }, $class;
     }

     sub term {
         my ($self) = @_;
         $self->{resolver}->($self->{object});
     }

simple_accessor(AccessorUri, AccessorName, TypeUri, TypeName, Content)
----------------------------------------------------------------------

   SOAP::Parser calls this function when it encounters a simple (scalar)
accessor.  You are told the uri and name of both the accessor and any
xsi:type attribute.  If the packet being unmarshaled doesn't use
namespaces (this is possible but isn't recommended by the SOAP spec),
AccessorUri will be undefined. Unless there is an explicit xsi:type,
TypeUri and TypeName will also be undefined. So the only two parameters
that are guaranteed to be defined are AccessorName and Content.

   AccessorUri and AccessorName gives the namespace and name of the
element, and Content contains the scalar content (always a string).

compound_accessor(AccessorUri, AccessorName, TypeUri, TypeName, IsPackage, Resolver)
------------------------------------------------------------------------------------

   SOAP::Parser calls this function when it encounters a compound accessor
(e.g., a structured type whose value is inlined under the accessor). The
first four parameters here are as described in simple_accessor above.
IsPackage is a hint that tells you that this node is a package (generally
you can ignore this; SOAP::Parser does all the work to deal with
packages). Resolver may or may not be defined, and I'll discuss how it
works shortly.

   NOTE NOTE NOTE: The SOAP "package" attribute was dropped when the SOAP
spec                 went from version 1.0 to version 1.1. Use
package-related                 functionality at your own risk - you may
not interoperate                 with other servers if you rely on it.
I'll eventually remove                 this feature if it doesn't reappear
in the spec soon.

   This function must return a blessed object reference that implements the
same interface (nothing prohibits you from simply returning $self, but
since SOAP::Parser keeps track of these object references on a per-node
basis, it's usually easier just to create a new instance of your class and
have each instance know how to unmarshal a single object).

   If Resolver is defined, you'll need to call it when the new stream is
term'd to communicate the resulting object reference to the Parser, so be
sure to propagate this reference to the new stream you create to do the
unmarshaling. Since you probably also need to be notified when the new
object is created, you'll not normally hand Resolver directly to the new
stream, but rather you'll provide your own implementation of Resolver that
does something with the object and then chains to the Resolver passed in
from the parser:

     sub compound_accessor {
         my ($self, $accessor_uri, $accessor_name, $typeuri, $typename, $is_package, $resolver) = @_;

     my $object = $self->{object};

     # create a closure to pass to the new input stream
     my $my_resolver = sub {
         my ($newly_unmarshaled_object) = @_;

     # do something with the object yourself
     $object->{$accessor_name} = $newly_unmarshaled_object;

     # chain to the Parser's resolver if it's defined
     $resolver->($child_object) if $resolver;
             };

     return $self->{type_mapper}->get_deserializer($typeuri, $typename, $my_resolver);
         }

reference_accessor(AccessorUri, AccessorName, Object)
-----------------------------------------------------

   SOAP::Parser calls this function when it encounters a reference to an
object that it's already unmarshaled. AccessorUri and AccessorName are the
same as in simple_accessor, and Object is a reference to a thingy; it's
basically whatever was resolved when another stream (perhaps one that you
implemented) unmarshaled the thingy. This could be a blessed object
reference, or simply a reference to a scalar (in SOAP it is possible to
communicate pointers to multiref scalars). In any case, you should add
this new reference to the object graph. Here's a simple example:

     sub reference_accessor {
         my ($self, $accessor_uri, $accessor_name, $object) = @_;

     $self->{object}{$accessor_name} = $object;
         }

forward_reference_accessor(AccessorUri, AccessorName)
-----------------------------------------------------

   SOAP::Parser calls this function when it encounters a reference to an
object that has not yet been unmarshaled (a forward reference). You should
return a function pointer that expects a single argument (the unmarshaled
object). This can be as simple as creating a closure that simply delays a
call to reference_accessor on yourself:

     sub forward_reference_accessor {
         my ($self, $accessor_uri, $accessor_name) = @_;

     # return a closure to complete the transaction at a later date
     return sub {
         my ($object) = @_;
         $self->reference_accessor($accessor_uri, $accessor_name, $object);
     };
         }

term()
------

   SOAP::Parser calls this function when there are no more accessors for
the given node.  You are expected to call the Resolver you were passed at
construction time at this point to pass the unmarshaled object reference
to your parent. Note that due to forward references, the object may not be
complete yet (it may have oustanding forward references that haven't yet
been resolved). This isn't a problem, because the parse isn't finished
yet, and as long as you've provided a resolver that fixes up these object
references from your implementation of forward_reference_accessor, by the
time the parse is complete, your object have all its references resolved
by the parser.

   See the description of new() for an example implementation of this
function.

DEPENDENCIES
============

   SOAP::TypeMapper

AUTHOR
======

   Keith Brown

SEE ALSO
========

   perl(1).

Generic serializer for Perl scalar references
*********************************************

NAME
====

   SOAP::GenericScalarSerializer - Generic serializer for Perl scalar
references

SYNOPSIS
========

   Forthcoming

DESCRIPTION
===========

   Forthcoming

AUTHOR
======

   Keith Brown

Client and server side SOAP implementation
******************************************

NAME
====

   SOAP::Lite - Client and server side SOAP implementation

SYNOPSIS
========

     use SOAP::Lite;
     print SOAP::Lite
       -> uri('http://simon.fell.com/calc')
       -> proxy('http://www.razorsoft.net/ssss4c/soap.asp')
       -> doubler([10,20,30,50,100])
       -> result ->[1];

     The same code with autodispatch:

     use SOAP::Lite +autodispatch =>
       uri => 'http://simon.fell.com/calc',
       proxy => 'http://www.razorsoft.net/ssss4c/soap.asp'
     ;
     print doubler([10,20,30,50,100])->[1];

   Code with service description

     use SOAP::Lite;
     print SOAP::Lite
       -> service('http://www.xmethods.net/sd/StockQuoteService.wsdl')
       -> getQuote('MSFT');

   Code for SOAP server (CGI):

     use SOAP::Transport::HTTP;
     SOAP::Transport::HTTP::CGI
       -> dispatch_to('/Your/Path/To/Deployed/Modules', 'Module::Name', 'Module::method')
       -> handle;

DESCRIPTION
===========

   SOAP::Lite is a collection of Perl modules which provides a simple and
lightweight interface to the Simple Object Access Protocol (SOAP) both on
client and server side.

   This version of SOAP::Lite supports the SOAP 1.1 specification (
http://www.w3.org/TR/SOAP ).

   The main features of the library are:

   * Supports SOAP 1.1 spec.

   * Provides full namespace support for SOAP 1.1.

   * Supports XML entity encoding.

   * Supports header attributes.

   * Supports HTTPS protocol.

   * Supports SMTP protocol.

   * Provides POP3 server implementation.

   * Supports Basic/Digest server authentication.

   * Provides COM interface.

   * Supports blessed object references.

   * Contains various reusable components (modules) that can be used
     independently, as, for instance, SOAP::Serializer and
     SOAP::Deserializer.

   * Provides an object oriented interface for serializing/deserializing
     and sending/receiving SOAP packets. Support for extensibility of the
     serialization/deserialization architecture has been included; see
     SOAP::Data for details.

   * Supports serialization/deserialization of sophisticated object graphs
     which may have cycles (a circular queue would serialize just fine, as
     well as $a=\$a. See tests and documentation for more examples).

   * Supports arrays (both serialization and deserialization with
     autotyping).

   * Custom/user-defined types (see SOAP::Data::as_ordered_hash for
     example).  Supports ordered hashes (as working example of
     user-defined data types).

   * Customizable auto type definitions.

   * Has more than 40 tests that access public test servers with different
     implementations: Apache SOAP, Frontier, Perl, XSLT, COM and VB6.

   * Has (limited) schema support (WSDL) with dynamic and stub access.

   * Supports Base64 encoding.

   * Supports out parameters binding.

   * Supports transparent SOAP calls with autodispatch feature.

   * Supports dynamic/static class/method binding.

   * Provides CGI/daemon server implementation.

   * Provides interactive shell for SOAP sessions (bin/SOAPsh.pl).

   * Easy services deployment. Put module in specified directory and it'll
     be accessible.

   * Has enough examples and documentation to be up and running in no time.

WHERE TO FIND EXAMPLES
----------------------

   See `t/*.t', `examples/*.pl' and the module documentation for a
client-side examples that demonstrate the serialization of a SOAP request,
sending it via HTTP to the server and receiving the response, and the
deserialization of the response. See `examples/server/*' for server-side
implementations.

OVERVIEW OF CLASSES AND PACKAGES
================================

   This table should give you a quick overview of the classes provided by
the library.

     SOAP::Lite.pm
     -- SOAP::Lite           -- Main class provides all logic
     -- SOAP::Transport      -- Supports transport architecture
     -- SOAP::Data           -- Provides extensions for serialization architecture
     -- SOAP::Header         -- Provides extensions for header serialization
     -- SOAP::Parser         -- Parses XML file into object tree
     -- SOAP::Serializer     -- Serializes data structures to SOAP package
     -- SOAP::Deserializer   -- Deserializes results of SOAP::Parser into objects
     -- SOAP::SOM            -- Provides access to deserialized object tree
     -- SOAP::Constants      -- Provides access to common constants
     -- SOAP::Trace          -- Provides tracing facilities
     -- SOAP::Schema         -- Provides access and stub(s) for schema(s)
     -- SOAP::Schema::WSDL   -- WSDL implementation for SOAP::Schema
     -- SOAP::Server         -- Handles requests on server side
     -- SOAP::Server::Object -- Handles objects-by-reference

     SOAP::Transport::HTTP.pm
     -- SOAP::Transport::HTTP::Client  -- Client interface to HTTP transport
     -- SOAP::Transport::HTTP::Server  -- Server interface to HTTP transport
     -- SOAP::Transport::HTTP::CGI     -- CGI implementation of server interface
     -- SOAP::Transport::HTTP::Daemon  -- Daemon implementation of server interface
     -- SOAP::Transport::HTTP::Apache  -- mod_perl implementation of server interface

     SOAP::Transport::POP3.pm
     -- SOAP::Transport::POP3::Server  -- Server interface to POP3 protocol

     SOAP::Transport::MAILTO.pm
     -- SOAP::Transport::MAILTO::Client -- Client interface to SMTP/sendmail

     SOAP::Transport::LOCAL.pm
     -- SOAP::Transport::LOCAL::Client -- Client interface to local transport

     SOAP::Transport::TCP.pm
     -- SOAP::Transport::TCP::Server -- Server interface to TCP protocol
     -- SOAP::Transport::TCP::Client -- Client interface to TCP protocol

SOAP::Lite
----------

   All methods that SOAP::Lite provides can be used for both setting and
retrieving values. If you provide no parameters, you will get current
value, and if parameters are provided, a new value will be assigned to the
object and the method in question will return the current object (if not
stated otherwise). This is suitable for stacking these calls like:

     $lite = SOAP::Lite
       -> uri('http://simon.fell.com/calc')
       -> proxy('http://www.razorsoft.net/ssss4c/soap.asp')
     ;

   The order is insignificant and you may call the new() method first. If
you don't do it, SOAP::Lite will do it for you. However, the new() method
gives you additional syntax:

     $lite = new SOAP::Lite
       uri => 'http://simon.fell.com/calc',
       proxy => 'http://www.razorsoft.net/ssss4c/soap.asp'
     ;

new()
     new() accepts a hash with method names as keys. It will call the
     appropriate methods together with the passed values. Since new() is
     optional it won't be mentioned anymore.

transport()
     Provides access to the `' in this node object. The object will be
     created for you. You can reassign it (but generally you should not).

serializer()
     Provides access to the `' in this node object. The object will be
     created for you. You can reassign it (but generally you should not).

proxy()
     Shortcut for `< transport-'proxy() >>. This lets you specify an
     endpoint (service address) and also loads the required module at the
     same time. It is required for dispatching SOAP calls. The name of the
     module will be defined depending on the protocol specific for the
     endpoint. The prefix `SOAP::Transport' will be prepended, the module
     will be loaded and object of class (with appended `::Client') will be
     created.

     For example, for `http://localhost/', the class for creating objects
     will look for `SOAP::Transport:HTTP::Client';

     In addition to endpoint parameter, proxy() can accept any transport
     specific parameters that could be passed as name => value pairs. For
     example, to specify proxy settings for HTTP protocol you may do:

          $soap->proxy('http://endpoint.server',
                       proxy => ['http' => 'http://my.proxy.server']);

     Notice that since proxy (second one) expects to get more than one
     parameter you should wrap them in array.

     Another useful example can be the client that is sensitive to
     cookie-based authentication. You can provide this with:

          $soap->proxy('http://localhost',
                       cookie_jar => HTTP::Cookies->new(ignore_discard => 1));

endpoint()
     Lets you specify an endpoint *without* changing/loading the protocol
     module.  This is useful for switching endpoints without switching
     protocols. You should call proxy() first. No checks for protocol
     equivalence will be made.

outputxml()
     Lets you specify the kind of output from all method calls. If `true',
     all methods will return unprocessed, raw XML code. You can parse it
     with XML::Parser, SOAP::Deserializer or any other appropriate module.

autotype()
     Shortcut for `< serializer-'autotype() >>. This lets you specify
     whether the serializer will try to make autotyping for you or not.
     Default setting is `true'.

readable()
     Shortcut for `< serializer-'readable() >>. This lets you specify the
     format for the generated XML code. Carriage returns <CR> and
     indentation will be added for readability. Useful in the case you
     want to see the generated code in a debugger. By default, there are
     no additional characters in generated XML code.

namespace()
     Shortcut for `< serializer-'namespace() >>. This lets you specify the
     default namespace for generated envelopes (`'SOAP-ENV'' by default).

encodingspace()
     Shortcut for `< serializer-'encodingspace() >>. This lets you specify
     the default encoding namespace for generated envelopes (`'SOAP-ENC''
     by default).

encoding()
     Shortcut for `< serializer-'encoding() >>. This lets you specify the
     encoding for generated envelopes. For now it will not actually change
     envelope encoding, it will just modify the XML header (`'UTF-8'' by
     default).

typelookup()
     Shortcut for `< serializer-'typelookup() >>. This gives you access to
     the `typelookup' table that is used for autotyping. For more
     information see `' in this node.

uri()
     Shortcut for `< serializer-'uri() >>. This lets you specify the uri
     for SOAP methods. Nothing is specified by default and your call will
     definitely fail if you don't specify the required uri.

     WARNING: URIs are just identifiers. They may *look like URLs*, but
     they are not guaranteed to point to anywhere and shouldn't be used as
     such pointers.  URIs assume to be unique within the space of all XML
     documents, so consider them as unique identifiers and nothing else.

multirefinplace()
     Shortcut for `< serializer-'multirefinplace() >>. If true, the
     serializer will put values for multireferences in the first
     occurrence of the reference.  Otherwise it will be encoded as top
     independent element, right after method element inside Body. Default
     value is false.

header()
     *DEPRECATED*: Use SOAP::Header instead.

     Shortcut for `< serializer-'header() >>. This lets you specify the
     header for generated envelopes. You can specify root,
     `mustUnderstand' or any other header using `' in this node class:

          $serializer = SOAP::Serializer->envelope('method' => 'mymethod', 1,
            SOAP::Header->name(t1 => 5)->attr({'~V:mustUnderstand' => 1}),
            SOAP::Header->name(t2 => 7)->mustUnderstand(2),
          );

     will be serialized into:

          <SOAP-ENV:Envelope ...attributes skipped>
            <SOAP-ENV:Header>
              <t1 xsi:type="xsd:int" SOAP-ENV:mustUnderstand="1">5</t1>
              <t2 xsi:type="xsd:int" SOAP-ENV:mustUnderstand="1">7</t2>
            </SOAP-ENV:Header>
            <SOAP-ENV:Body>
              <namesp1:mymethod xmlns:namesp1="urn:SOAP__Serializer">
                <c-gensym6 xsi:type="xsd:int">1</c-gensym6>
              </namesp1:mymethod>
            </SOAP-ENV:Body>
          </SOAP-ENV:Envelope>

     You can mix `SOAP::Header' parameters with other parameters and you
     can also return `SOAP::Header' parameters as a result of a remote
     call. They will be placed into the header. See
     `My::Parameters::addheader' as an example.

on_action()
     This lets you specify a handler for `on_action event'. It is
     triggered when creating SOAPAction. The default handler will set
     SOAPAction to `"uri#method"'. You can change this behavior globally
     (see `' in this node) or locally, for a particular object.

on_fault()
     This lets you specify a handler for `on_fault' event. The default
     behavior is to die on an transport error and to *do nothing* on other
     error conditions. You may change this behavior globally (see `' in
     this node) or locally, for a particular object.

on_debug()
     This lets you specify a handler for `on_debug event'. Default
     behavior is to do nothing. Use `+trace/+debug' option for SOAP::Lite
     instead. If you use if be warned that since this method is just
     interface to `+trace/+debug' it has global effect, so if you install
     it for one object it'll be in effect for all subsequent calls (even
     for other objects).

on_nonserialized()
     This lets you specify a handler for `on_nonserialized event'. The
     default behavior is to produce a warning if warnings are on for
     everything that cannot be properly serialized (like CODE references
     or GLOBs).

call()
     Provides alternative interface for remote method calls. You can always
     run `< SOAP::Lite-'new(...)->method(@parameters) >>, but call() gives
     you several additional options:

    prefixed method
          If you want to specify prefix for generated method's element one
          of the available options is do it with call() interface:

               print SOAP::Lite
                 -> new(....)
                 -> call('myprefix:method' => @parameters)
                 -> result;

          This example will work on client side only. If you want to
          change prefix on server side you should override default
          serializer. See `examples/server/soap.*' for examples.

    access to any method
          If for some reason you want to get access to remote procedures
          that have the same name as methods of SOAP::Lite object these
          calls (obviously) won't be dispatched. In that case you can
          originate your call trough call():

               print SOAP::Lite
                 -> new(....)
                                # don't forget to specify CLASS name as the first parameter
                 -> call(new => @parameters)
                 -> result;

    implementation of OO interface
          With `autodispatch|' in this node you can make CLASS/OBJECT
          calls like:

               my $obj = CLASS->new(@parameters);
               print $obj->method;

          However, because of side effects `autodispatch|' in this node
          has, it's not always possible to use this syntax. call()
          provides you alternative:

               # you should specify uri()
               my $soap = SOAP::Lite
                 -> uri('http://my.own.site/CLASS') # <<< CLASS goes here
                 # ..... other parameters
               ;

               my $obj = $soap->call(new => @parameters)->result;
               print $soap->call(method => $obj)->result;
               # $obj object will be updated here if necessary,
               # as if you call $obj->method() and method() updates $obj

               # Update of modified object MAY not work if server on another side
               # is not SOAP::Lite

    ability to set method's attributes
          Additionally this syntax lets you specify attributes for method
          element:

               print SOAP::Lite
                 -> new(....)
                 -> call(SOAP::Data->name('method')->attr({xmlns => 'mynamespace'})
                         => @parameters)
                 -> result;

          You can specify any attibutes and name of SOAP::Data element
          becomes name of method. Everything else except attributes is
          ignored and parameters should be provided as usual.

          Be warned, that though you have more control using this method,
          you should specify namespace attribute for method explicitely,
          even if you made uri() call earlier. So, if you have to have
          namespace on method element, instead of:

               print SOAP::Lite
                 -> new(....)
                 -> uri('mynamespace') # will be ignored
                 -> call(SOAP::Data->name('method') => @parameters)
                 -> result;

          do

               print SOAP::Lite
                 -> new(....)
                 -> call(SOAP::Data->name('method')->attr({xmlns => 'mynamespace'})
                         => @parameters)
                 -> result;

          because in the former call uri() will be ignored and namespace
          won't be specified. If you run script with -w option (as
          recommended) SOAP::Lite gives you a warning:

               URI is not provided as attribute for method (method)

          Moreover, it'll become fatal error if you try to call it with
          prefixed name:

               print SOAP::Lite
                 -> new(....)
                 -> uri('mynamespace') # will be ignored
                 -> call(SOAP::Data->name('a:method') => @parameters)
                 -> result;

          gives you:

               Can't find namespace for method (a:method)

          because nothing is associated with prefix 'a'.

     One more comment. One case when SOAP::Lite will change something that
     you specified is when you specified prefixed name and empty namespace
     name:

          print SOAP::Lite
            -> new(....)
            -> uri('')
            -> call('a:method' => @parameters)
            -> result;

     This code will generate:

          <method xmlns="">....</method>

     instead of

          <a:method xmlns:a="">....</method>

     because later is not allowed according to XML Namespace specification.

     In all other aspects `< -'call(mymethod => @parameters) >> is just a
     synonim for `< -'mymethod(@parameters) >>.

self()
     Returns object reference to global defaul object specified with `use
     SOAP::Lite ...' interface. Both class method and object method return
     reference to global object, so:

          use SOAP::Lite
            proxy => 'http://my.global.server'
          ;

          my $soap = SOAP::Lite->proxy('http://my.local.server');

          print $soap->self->proxy;

     prints `'http://my.global.server'' (the same as `<
     SOAP::Lite-'self->proxy >>).  See `' in this node for more
     information.

SOAP::Data
----------

   You can use this class if you want to specify a value, a name, atype, a
uri or attributes for SOAP elements (use value(), name(), type(), uri()
and attr() methods correspondingly).  For example, `<
SOAP::Data-'name('abc')->value(123) >> will be serialized into `<
<abc'123</abc> >>, as well as will `< SOAP::Data-'name(abc => 123) >>.
Each of them (except the value() method) can accept a value as the second
parameter. All methods return the current value if you call them without
parameters. The return the object otherwise, so you can stack them. See
tests for more examples. You can import these methods with:

   SOAP::Data->import('name');

   or

     import SOAP::Data 'name';

   and then use `< name(abc =' 123) >> for brevity.

   An interface for specific attributes is also provided. You can use the
`actor()', `mustUnderstand()', `encodingStyle()' and root() methods to
set/get values of the correspondent attributes.

     SOAP::Data
       ->name(c => 3)
       ->encodingStyle('http://xml.apache.org/xml-soap/literalxml')

   will be serialized into:

     <c SOAP-ENV:encodingStyle="http://xml.apache.org/xml-soap/literalxml"
        xsi:type="xsd:int">3</c>

SOAP::Serializer
----------------

   Usually you don't need to interact directly with this module. The only
case when you need it, it when using autotyping. This feature lets you
specify types for your data according to your needs as well as to
introduce new data types (like ordered hash for example).

   You can specify a type with `< SOAP::Data-'type(float => 123) >>. During
the serialization stage the module will try to serialize your data with the
`as_float' method. It then calls the `typecast' method (you can override it
or inherit your own class from `' in this node) and only then it will try
to serialize it according to data type (SCALAR, ARRAY or HASH). For
example:

     SOAP::Data->type('ordered_hash' => [a => 1, b => 2])

   will be serialized as an ordered hash, using the `as_ordered_hash'
method.

   If you do not specify a type directly, the serialization module will try
to autodefine the type for you according to the `typelookup' hash. It
contains the type name as key and the following 3-element array as value:

     priority,
     check_function (CODE reference),
     typecast function (METHOD name or CODE reference)

   For example, if you want to add `uriReference' to autodefined types,
you should add something like this:

     $s->typelookup({
       %{$s->typelookup},
       uriReference => [11, sub { shift =~ m!^http://! }, 'as_uriReference']
     });

   and add the `as_uriReference' method to the `' in this node class:

     sub SOAP::Serializer::as_uriReference {
       my $self = shift;
       my($value, $name, $type, $attr) = @_;
       return [$name, {%{$attr || {}}, 'xsi:type' => 'xsd:uriReference'}, $value];
     }

   The specified methods will work for both autotyping and direct typing,
so you can use either

     SOAP::Data->type(uriReference => 'http://yahoo.com')>

   or just

     'http://yahoo.com'

   and it will be serialized into the same type. For more examples see as_*
methods in `' in this node.

   The SOAP::Serializer provides you with autotype(), readable(),
namespace(), encodingspace(), encoding(), typelookup(), uri(),
multirefinplace() and envelope() methods. All methods (except envelope())
are described in the `' in this node section.

envelope()
     This method allows you to build three kind of envelopes depending on
     the first parameter:

    method
               envelope(method => 'methodname', @parameters);

          or

               method('methodname', @parameters);

          Lets you build a request/response envelope.

    fault
               envelope(fault => 'faultcode', 'faultstring', $details);

          or

          fault('faultcode', 'faultstring', $details);

          Lets you build a fault envelope. Faultcode will be properly
          qualified and details could be string or object.

    freeform
               envelope(freeform => 'something that I want to serialize');

          or

               freeform('something that I want to serialize');

               Reserved for nonRPC calls. Lets you build your own payload inside a SOAP
               envelope. All SOAP 1.1 specification rules are enforced, except method
               specific ones. See UDDI::Lite as example.

   For more examples see tests and SOAP::Transport::HTTP.pm

SOAP::SOM
---------

   All calls you are making through object oriented interface will return
SOAP::SOM object, and you can access actual values with it.  Next example
gives you brief overview of the class:

     my $soap = SOAP::Lite .....;
     my $som = $soap->method(@parameters);

     if ($som->fault) { # will be defined if Fault element is in the message
       print $som->faultdetail; # returns value of 'detail' element as
                                # string or object
       $som->faultcode;   #
       $som->faultstring; # also available
       $som->faultactor;  #
     } else {
       $som->result; # gives you access to result of call
                     # it could be any data structure, for example reference
                     # to array if server didi something like: return [1,2];

       $som->paramsout; # gives you access to out parameters if any
                        # for example, you'll get array (1,2) if
                        # server returns ([1,2], 1, 2);
                        # [1,2] will be returned as $som->result
                        # and $som->paramsall will return ([1,2], 1, 2)
                        # see section IN/OUT, OUT PARAMETERS AND AUTOBINDING
                        # for more information

     $som->paramsall; # gives access to result AND out parameters (if any)
                      # and returns them as one array

     $som->valueof('//myelement'); # returns value(s) (as perl data) of
                                   # 'myelement' if any. All elements in array
                                   # context and only first one in scalar

     $h = $som->headerof('//myheader'); # returns element as SOAP::Header, so
                                        # you can access attributes and values
                                        # with $h->mustUnderstand, $h->actor
                                        # or $h->attr (for all attributes)
       }

     SOAP::SOM object gives you access to the deserialized envelope via several
     methods. All methods accept a node path (similar to XPath notations).
     SOM interprets '/' as the root node, '//' as relative location path
     ('//Body' will find all bodies in document, as well as
     '/Envelope//nums' will find all 'nums' nodes under Envelope node),
     '[num]' as node number and '[op num]' with C<op> being a comparison
     operator ('<', '>', '<=', '>=', '!', '=').

   All nodes in nodeset will be returned in document order.

match()
     Accepts a path to a node and returns true/false in a boolean context
     and a SOM object otherwise. valueof() and dataof() can be used to get
     value(s) of matched node(s).

valueof()
     Returns the value of a (previously) matched node. It accepts a node
     path.  In this case, it returns the value of matched node, but does
     not change the current node. Suitable when you want to match a  node
     and then navigate through node children:

          $som->match('/Envelope/Body/[1]'); # match method
          $som->valueof('[1]');              # result
          $som->valueof('[2]');              # first out parameter (if present)

     The returned value depends on the context. In a scalar context it
     will return the first element from matched nodeset. In an array
     context it will return all matched elements.

dataof()
     Same as valueof(), but it returns a `' in this node object, so you
     can get access to the name, the type and attributes of an element.

headerof()
     Same as dataof(), but it returns `' in this node object, so you can
     get access to the name, the type and attributes of an element. Can be
     used for modifying headers (if you want to see updated header inside
     Header element, it's better to use this method instead of dataof()
     method).

namespaceuriof()
     Returns the uri associated with the matched element. This uri can
     also be inherited, for example, if you have

          <a xmlns='http://my.namespace'>
            <b>
               value
            </b>
          </a>

     this method will return same value for 'b' element as for 'a'.

   SOAP::SOM also provides  methods for direct access to the envelope, the
body, methods and parameters (both in and out). All these methods return
real values (in most cases it will be a hash reference), if called as
object method. Returned values also depend on context: in an array context
it will return an array of values and in scalar context it will return the
first element. So, if you want to access the first output parameter, you
can call `< $param = $som-'paramsout >>; and you will get it regardless of
the actual number of output parameters.  If you call it as class function
(for example, SOAP::SOM::method) it returns an XPath string that matches
the current element ('/Envelope/Body/[1]' in case of 'method'). The method
will return undef if not present OR if you try to access an element that
has an `xsi:null="1"' attribute. To distinguish between these two cases
you can first access the match() method that will return true/false in a
boolean context and then get the real value:

     if ($som->match('//myparameter')) {
       $value = $som->valueof; # can be undef too
     } else {
       # doesn't exist
     }

root()
     Returns the value (as hash) of the root element. Do exactly the same
     as `< $som-'valueof('/') >> does.

envelope()
     Returns the value (as hash) of the Envelope element. Keys in this
     hash will be 'Header' (if present), 'Body' and any other (optional)
     elements. Values will be the deserialized header, body, and elements,
     respectively.  If called as function (`SOAP::SOM::envelope') it will
     return a Xpath string that matches the envelope content. Useful when
     you want just match it and then iterate over the content by yourself.
     Example:

          if ($som->match(SOAP::SOM::envelope)) {
            $som->valueof('Header'); # should give access to header if present
            $som->valueof('Body');   # should give access to body
          } else {
            # hm, are we doing SOAP or what?
          }

header()
     Returns the value (as hash) of the Header element. If you want to
     access all attributes in the header use:

          # get element as SOAP::Data object
          $transaction = $som->match(join '/', SOAP::SOM::header, 'transaction')->dataof;
          # then you can access all attributes of 'transaction' element
          $transaction->attr;

headers()
     Returns a node set of values with deserialized headers. The
     difference between the header() and headers() methods is that the
     first gives you access to the whole header and second to the headers
     inside the 'Header' tag:

          $som->headerof(join '/', SOAP::SOM::header, '[1]');
          # gives you first header as SOAP::Header object

          ($som->headers)[0];
          # gives you value of the first header, same as
          $som->valueof(join '/', SOAP::SOM::header, '[1]');

          $som->header->{name_of_your_header_here}
          # gives you value of name_of_your_header_here

body()
     Returns the value (as hash) of the Body element.

fault()
     Returns the value (as hash) of `Fault' element: `faultcode',
     `faultstring' and detail. If `Fault' element is present, result(),
     paramsin(), paramsout() and method() will return an undef.

faultcode()
     Returns the value of the `faultcode' element if present and undef
     otherwise.

faultstring()
     Returns the value of the `faultstring' element if present and undef
     otherwise.

faultactor()
     Returns the value of the `faultactor' element if present and undef
     otherwise.

faultdetail()
     Returns the value of the detail element if present and undef
     otherwise.

method()
     Returns the value of the method element (all input parameters if you
     call it on a deserialized request envelope, and result/output
     parameters if you call it on a deserialized response envelope).
     Returns undef if the 'Fault' element is present.

result()
     Returns the value of the result of the method call. In fact, it will
     return the first child element (in document order) of the method
     element.

paramsin()
     Returns the value(s) of all passed parameters.

paramsout()
     Returns value(s) of the output parameters.

paramsall()
     Returns value(s) of the result AND output parameters as one array.

SOAP::Schema
------------

   SOAP::Schema gives you ability to load schemas and create stubs
according to these schemas. Different syntaxes are provided:

   *      use SOAP::Lite
            service => 'http://www.xmethods.net/sd/StockQuoteService.wsdl',
            # service => 'file:/your/local/path/StockQuoteService.wsdl',
            # service => 'file:./StockQuoteService.wsdl',
          ;
          print getQuote('MSFT'), "\n";

   *      use SOAP::Lite;
          print SOAP::Lite
            -> service('http://www.xmethods.net/sd/StockQuoteService.wsdl')
            -> getQuote('MSFT'), "\n";

   *      use SOAP::Lite;
          my $service = SOAP::Lite
            -> service('http://www.xmethods.net/sd/StockQuoteService.wsdl');
          print $service->getQuote('MSFT'), "\n";

   You can create stub with *stubmaker* script:

     perl stubmaker.pl http://www.xmethods.net/sd/StockQuoteService.wsdl

   and you'll be able to access SOAP services in one line:

     perl "-MStockQuoteService qw(:all)" -le "print getQuote('MSFT')"

   or dynamically:

     perl "-MSOAP::Lite service=>'file:./quote.wsdl'" -le "print getQuote('MSFT')"

   Other supported syntaxes with stub(s) are:

   *      use StockQuoteService ':all';
          print getQuote('MSFT'), "\n";

   *      use StockQuoteService;
          print StockQuoteService->getQuote('MSFT'), "\n";

   *      use StockQuoteService;
          my $service = StockQuoteService->new;
          print $service->getQuote('MSFT'), "\n";

   Support for schemas is limited for now. Though module was tested with
dozen different schemas it won't understand complex objects and will work
only with WSDL.

SOAP::Trace
-----------

   SOAP::Trace provides you with a trace/debug facility for the SOAP::Lite
library. To activate it you need to specify a list of traceable
events/parts of SOAP::Lite:

     use SOAP::Lite +trace =>
       qw(list of available traces here);

   Available events are:

     transport  -- (client) access to request/response for transport layer
     dispatch   -- (server) shows full name of dispatched call
     result     -- (server) result of method call
     parameters -- (server) parameters for method call
     headers    -- (server) headers of received message
     objects    -- (both)   new/DESTROY calls
     method     -- (both)   parameters for '->envelope(method =>' call
     fault      -- (both)   parameters for '->envelope(fault =>' call
     freeform   -- (both)   parameters for '->envelope(freeform =>' call
     trace      -- (both)   trace enters into some important functions
     debug      -- (both)   details about transport

   For example:

     use SOAP::Lite +trace =>
       qw(method fault);

   lets you output the parameter values for all your fault/normal
envelopes onto STDERR.  If you want to log it you can either redirect
STDERR to some file

     BEGIN { open(STDERR, '>>....'); }

   or (preferably) define your own function for a particular event:

     use SOAP::Lite +trace =>
       method => sub {'log messages here'}, fault => \&log_faults;

   You can share the same function for several events:

     use SOAP::Lite +trace =>
       method, fault => \&log_methods_and_faults;

   Also you can use 'all' to get all available tracing and use '-' in
front of an event to disable particular event:

     use SOAP::Lite +trace =>
       all, -transport; # to get all logging without transport messages

   Finally,

     use SOAP::Lite +trace;

   will switch all debugging on.

   You can use 'debug' instead of 'trace'. I prefer 'trace', others
'debug'.  Also `on_debug' is available for backward compatibility, as in

     use SOAP::Lite;

     my $s = SOAP::Lite
       -> uri('http://tempuri.org/')
       -> proxy('http://beta.search.microsoft.com/search/MSComSearchService.asmx')
       -> on_debug(sub{print@_}) # show you request/response with headers
     ;
     print $s->GetVocabulary(SOAP::Data->name('~:Query' => 'something'))
             ->valueof('//FOUND');

   or switch it on individually, with

     use SOAP::Lite +trace => debug;

   or

   use SOAP::Lite +trace => debug => sub {'do_what_I_want_here'};

   Compare this with:

     use SOAP::Lite +trace => transport;

     which gives you access to B<actual> request/response objects, so you can even
     set/read cookies or do whatever you want there.

   The difference between debug and `transport' is that `transport' will
get a HTTP::Request/HTTP::Response object and debug will get a stringified
request (NOT OBJECT!). It can also be called in other places too.

FEATURES AND OPTIONS
====================

DEFAULT SETTINGS
----------------

   Though this feature looks similar to `autodispatch|' in this node they
have (almost) nothing in common. It lets you create default object and all
objects created after that will be cloned from default object and hence
get its properties. If you want to provide common proxy() or uri()
settings for all SOAP::Lite objects in your application you may do:

     use SOAP::Lite
       proxy => 'http://localhost/cgi-bin/soap.cgi',
       uri => 'http://my.own.com/My/Examples'
     ;

     my $soap1 = new SOAP::Lite; # will get the same proxy()/uri() as above
     print $soap1->getStateName(1)->result;

     my $soap2 = SOAP::Lite->new; # same thing as above
     print $soap2->getStateName(2)->result;

     # or you may override any settings you want
     my $soap3 = SOAP::Lite->proxy('http://localhost/');
     print $soap3->getStateName(1)->result;

   Any SOAP::Lite properties can be propagated this way. Changes in object
copies will not affect global settings and you may still change global
settings with `< SOAP::Lite-'self >> call which returns reference to
global object. Provided parameter will update this object and you can even
set it to undef:

     SOAP::Lite->self(undef);

   The `use SOAP::Lite' syntax also lets you specify default event handlers
for your code. If you have different SOAP objects and want to share the
same on_action() (or on_fault() for that matter) handler. You can specify
on_action() during initialization for every object, but you may also do:

     use SOAP::Lite
       on_action => sub {sprintf '%s#%s', @_}
     ;

   and this handler will be the default handler for all your SOAP objects.
You can override it if you specify a handler for a particular object.  See
`t/*.t' for example of on_fault() handler.

   Be warned, that since `use ...' is executed at compile time all use
statements will be executed before script execution that can make
unexpected results. Consider code:

     use SOAP::Lite proxy => 'http://localhost/';

     print SOAP::Lite->getStateName(1)->result;

     use SOAP::Lite proxy => 'http://localhost/cgi-bin/soap.cgi';

     print SOAP::Lite->getStateName(1)->result;

   *BOTH* SOAP calls will go to `'http://localhost/cgi-bin/soap.cgi''. If
you want to execute use at run-time, put it in eval:

     eval "use SOAP::Lite proxy => 'http://localhost/cgi-bin/soap.cgi'; 1" or die;

   or use

     SOAP::Lite->self->proxy('http://localhost/cgi-bin/soap.cgi');

IN/OUT, OUT PARAMETERS AND AUTOBINDING
--------------------------------------

   SOAP::Lite gives you access to all parameters (both in/out and out) and
also does some additional work for you. Lets consider following example:

     <mehodResponse>
       <res1>name1</res1>
       <res2>name2</res2>
       <res3>name3</res3>
     </mehodResponse>

   In that case:

     $result = $r->result; # gives you 'name1'
     $paramout1 = $r->paramsout;      # gives you 'name2', because of scalar context
     $paramout1 = ($r->paramsout)[0]; # gives you 'name2' also
     $paramout2 = ($r->paramsout)[1]; # gives you 'name3'

   or

     @paramsout = $r->paramsout; # gives you ARRAY of out parameters
     $paramout1 = $paramsout[0]; # gives you 'res2', same as ($r->paramsout)[0]
     $paramout2 = $paramsout[1]; # gives you 'res3', same as ($r->paramsout)[1]

   Generally, if server returns `return (1,2,3)' you will get 1 as the
result and 2 and 3 as out parameters.

   If the server returns `return [1,2,3]' you will get an ARRAY from
result() and undef from paramsout() .  Results can be arbitrary complex:
they can be an array of something, they can be objects, they can be
anything and still be returned by result() . If only one parameter is
returned, paramsout() will return undef.

   But there is more.  If you have in your output parameters a parameter
with the same signature (name+type) as in the input parameters this
parameter will be mapped into your input automatically. Example:

   server:

     sub mymethod {
       shift; # object/class reference
       my $param1 = shift;
       my $param2 = SOAP::Data->name('myparam' => shift() * 2);
       return $param1, $param2;
     }

   client:

     $a = 10;
     $b = SOAP::Data->name('myparam' => 12);
     $result = $soap->mymethod($a, $b);

   After that, `< $result == 10 and $b-'value == 24 >>! Magic? Sort of.
Autobinding gives it to you. That will work with objects also with one
difference: you do not need to worry about the name and the type of object
parameter. Consider the `PingPong' example (`examples/My/PingPong.pm' and
`examples/pingpong.pl'):

   server:

     package My::PingPong;

     sub new {
       my $self = shift;
       my $class = ref($self) || $self;
       bless {_num=>shift} => $class;
     }

     sub next {
       my $self = shift;
       $self->{_num}++;
     }

   client:

     use SOAP::Lite +autodispatch =>
       uri => 'urn:',
       proxy => 'http://localhost/'
     ;

     my $p = My::PingPong->new(10); # $p->{_num} is 10 now, real object returned
     print $p->next, "\n";          # $p->{_num} is 11 now!, object autobinded

AUTODISPATCHING AND SOAP:: PREFIX
---------------------------------

   WARNING: `autodispatch' feature can have side effects for your
application and can affect functionality of other modules/libraries
because of overloading UNIVERSAL::AUTOLOAD. All unresolved calls will be
dispatched as SOAP calls, however it could be not what you want in some
cases. If so, consider using object interface (see `implementation of OO
interface').

   SOAP::Lite provides an autodispatching feature that lets you create
code which looks the same for local and remote access.

   For example:

   use SOAP::Lite +autodispatch =>     uri => 'urn:/My/Examples',
proxy => 'http://localhost/'   ;

   tells SOAP to 'autodispatch' all calls to the 'http://localhost/'
endpoint with the 'urn:/My/Examples' uri. All consequent method calls can
look like:

     print getStateName(1), "\n";
     print getStateNames(12,24,26,13), "\n";
     print getStateList([11,12,13,42])->[0], "\n";
     print getStateStruct({item1 => 10, item2 => 4})->{item2}, "\n";

   As you can see, there is no SOAP specific coding at all.

   The same logic will work for objects as well:

     print "Session iterator\n";
     my $p = My::SessionIterator->new(10);
     print $p->next, "\n";
     print $p->next, "\n";

   This will access the remote My::SessionIterator module, gets an object,
and then calls remote methods again. The object will be transferred to the
server, the method is executed there and the result (and the modified
object!) will be transferred back to the client.

   Autodispatch will work *only* if you do not have the same method in your
code. For example, if you have `use My::SessionIterator' somewhere in your
code of our previous example, all methods will be resolved locally  and no
SOAP calls will be done. If you want to get access to remote
objects/methods even in that case, use `SOAP::' prefix to your methods,
like:

     print $p->SOAP::next, "\n";

   See `pingpong.pl' for example of a script, that works with the same
object locally and remotely.

   `SOAP::' prefix also gives you ability to access methods that have the
same name as methods of SOAP::Lite itself. For example, you want to call
method new() for your class `My::PingPong' through OO interface.  First
attempt could be:

     my $s = SOAP::Lite
       -> uri('http://www.soaplite.com/My/PingPong')
       -> proxy('http://localhost/cgi-bin/soap.cgi')
     ;
     my $obj = $s->new(10);

   but it won't work, because SOAP::Lite has method new() itself. To
provide a hint, you should use `SOAP::' prefix and call will be dispatched
remotely:

     my $obj = $s->SOAP::new(10);

   You can mix autodispatch and usual SOAP calls in the same code if you
need it. Keep in mind, that calls with SOAP:: prefix should always be a
method call, so if you want to call functions, use `< SOAP-'myfunction() >>
instead of `SOAP::myfunction()'.

   Be warned though Perl has very flexible syntax some versions will
complain

     Bareword "autodispatch" not allowed while "strict subs" in use ...

   if you try to put 'autodispatch' and '=>' on separate lines. So, keep
them on the same line, or put 'autodispatch' in quotes:

     use SOAP::Lite 'autodispatch' # DON'T use plus in this case
       => ....
     ;

ACCESSING HEADERS AND ENVELOPE ON SERVER SIDE
---------------------------------------------

   SOAP::Lite gives you direct access to all headers and the whole
envelope on the server side. Consider the following code from
My::Parameters.pm:

     sub byname {
       my($a, $b, $c) = @{pop->method}{qw(a b c)};
       return "a=$a, b=$b, c=$c";
     }

   You will get this functionality ONLY if you inherit your class from the
SOAP::Server::Parameters class. This should keep existing code working and
provides this feature only when you need it.

   Every method on server side will be called as class/object method, so
it will get an *object reference* or a *class name* as the first
parameter, then the method parameters, and then an envelope as SOAP::SOM
object. Shortly:

     $self [, @parameters] , $envelope

   If you have a fixed number of parameters, you can simple do:

     my $self = shift;
     my($param1, $param2) = @_;

   and ignore the envelope. If you need access to the envelope you can do:

     my $envelope = pop;

   since the envelope is always the last element in the parameters list.
The `byname()' method `< pop-'method >> will return a hash with parameter
names as hash keys and parameter values as hash values:

     my($a, $b, $c) = @{pop->method}{qw(a b c)};

   gives you by-name access to your parameters.

SERVICE DEPLOYMENT. STATIC AND DYNAMIC
--------------------------------------

   Let us scrutinize the deployment process. When designing your SOAP
server you can consider two kind of deployment: static and dynamic.  For
both, static and dynamic,  you should specify MODULE, `MODULE::method',
method or `PATH/' when creating useing the SOAP::Lite module. The
difference between static and dynamic deployment is that in case of
'dynamic', any module which is not present will be loaded on demand. See
the `' in this node section for detailed description.

   Example for static deployment:

     use SOAP::Transport::HTTP;
     use My::Examples;           # module is preloaded

     SOAP::Transport::HTTP::CGI
       # deployed module should be present here or client will get 'access denied'
       -> dispatch_to('My::Examples')
       -> handle;

   Example for dynamic deployment:

     use SOAP::Transport::HTTP;
     # name is unknown, module will be loaded on demand

     SOAP::Transport::HTTP::CGI
       # deployed module should be present here or client will get 'access denied'
       -> dispatch_to('/Your/Path/To/Deployed/Modules', 'My::Examples')
       -> handle;

   For static deployment you should specify the MODULE name directly.  For
dynamic deployment you can specify the name either directly (in that case
it will be required without any restriction) or indirectly, with a PATH In
that case, the ONLY path that will be available will be the PATH given to
the dispatch_to() method). For information how to handle this situation
see `' in this node section.

   You should also use static binding when you have several different
classes in one file and want to make them available for SOAP calls.

   SUMMARY:

     dispatch_to(
       # dynamic dispatch that allows access to ALL modules in specified directory
       PATH/TO/MODULES
       # 1. specifies directory
       # -- AND --
       # 2. gives access to ALL modules in this directory without limits

     # static dispatch that allows access to ALL methods in particular MODULE
     MODULE
     #  1. gives access to particular module (all available methods)
     #  PREREQUISITES:
     #    module should be loaded manually (for example with 'use ...')
     #    -- OR --
     #    you can still specify it in PATH/TO/MODULES

     # static dispatch that allows access to particular method ONLY
     MODULE::method
     # same as MODULE, but gives access to ONLY particular method,
     # so there is not much sense to use both MODULE and MODULE::method
     # for the same MODULE
       )

SECURITY
--------

   Due to security reasons, the current path for perl modules (`@INC')
will be disabled once you have chosen dynamic deployment and specified
your own `PATH/'.  If you want to access other modules in your included
package you have several options:

  1. Switch to static linking:

          use MODULE;
          $server->dispatch_to('MODULE');

     It can be useful also when you want to import something specific from
     the deployed modules:

          use MODULE qw(import_list);

  2. Change use to require. The path is unavailable only during the
     initialization part, and it is available again during execution.  So,
     if you do require somewhere in your package, it will work.

  3. Same thing, but you can do:

          eval 'use MODULE qw(import_list)'; die if $@;

  4. Assign a `@INC' directory in your package and then make use.  Don't
     forget to put `@INC' in `BEGIN{}' block or it won't work:

          BEGIN { @INC = qw(my_directory); use MODULE }

COMPRESSION
-----------

   SOAP::Lite provides you option for enabling compression on wire (for
HTTP transport only). Both server and client should support this
capability, but this logic should be absolutely transparent for your
application.

   It could be enabled by specifying threshold for compression on client or
server side:

Client
          print SOAP::Lite
            -> uri('http://localhost/My/Parameters')
            -> proxy('http://localhost/', options => {compress_threshold => 10000})
            -> echo(1 x 10000)
            -> result
          ;

Server
          my $server = SOAP::Transport::HTTP::CGI
            -> dispatch_to('My::Parameters')
            -> options({compress_threshold => 10000})
            -> handle;

   For more information see `COMPRESSION section|SOAP::Transport::HTTP' in
this node in HTTP transport documentation.

OBJECTS-BY-REFERENCE
--------------------

   SOAP::Lite implements an experimental (yet functional) support for
objects-by-reference. You should not see any difference on the client side
when using this. On the server side you should specify the names of the
classes you want to be returned by reference (instead of by value) in the
`objects_by_reference()' method for your server implementation (see
soap.pop3, soap.daemon and Apache.pm).

   Garbage collection is done on the server side (not earlier than after
600 seconds of inactivity time), and you can overload the default behavior
with specific functions for any particular class.

   Binding does not have any special syntax and is implemented on server
side (see the differences between My::SessionIterator and
My::PersistentIterator).  On the client side, objects will have same
type/class as before (`< My::SessionIterator-'new() >> will return an
object of class My::SessionIterator). However, this object is just a stub
with an object ID inside.

INTEROPERABILITY
----------------

Microsoft's .NET
     To use .NET client and SOAP::Lite server

    qualify all elements
          use fully qualified names for your return values, e.g.:

               return SOAP::Data->name('~:myname')->type('string')->value($output);

          In addition see comment about default incoding in .NET Web
          Services below.

     To use SOAP::Lite client and .NET server

    declare proper soapAction (uri/method) in your call
          For example, use `on_action(sub{join '', @_})'.

    qualify all elements
          Any of following actions should work:

         use fully qualified name for method parameters
               Use `< SOAP::Data-'name('~:Query'  => 'biztalk') >> instead
               of `< SOAP::Data-'name('Query'  => 'biztalk') >>.

               Example of SOAPsh call (all parameters should be in one
               line):

                    > perl SOAPsh.pl
                      "http://beta.search.microsoft.com/search/mscomsearchservice.asmx"
                      "http://tempuri.org/"
                      "on_action(sub{join '', @_})"
                      "GetVocabulary(SOAP::Data->name('~:Query'  => 'biztalk'))"

         make method in default namespace
               instead of

                    my @rc = $soap->call(add => @parms)->result;
                    # -- OR --
                    my @rc = $soap->add(@parms)->result;

               use

                    my $method = SOAP::Data->name('add')
                                           ->attr({xmlns => 'http://tempuri.org/'});
                    my @rc = $soap->call($method => @parms)->result;

         modify .NET server if you are in charge for that
               Stefan Pharies <stefanph@microsoft.com>:

               SOAP::Lite uses the SOAP encoding (section 5 of the soap
               1.1 spec), and the default for .NET Web Services is to use
               a literal encoding. So elements in the request are
               unqualified, but your service expects them to be qualified.
               .Net Web Services has a way for you to change the expected
               message format, which should allow you to get your interop
               working.  At the top of your class in the asmx, add this
               attribute:

                    [SoapService(Style=SoapServiceStyle.RPC)]

               Full Web Service text may look like (as far as I understand
               the syntax):

                    <%@ WebService Language="C#" Class="Test" %>
                    using System.Web.Services;

                    [SoapService(Style=SoapServiceStyle.RPC)]
                    public class Test : WebService {
                      [WebMethod]
                      public int add(int a, int b) {
                        return a + b;
                      }
                    }

     Thanks to   Petr Janata <petr.janata@i.cz>,   Stefan Pharies
     <stefanph@microsoft.com>, and   Brian Jepson <bjepson@jepstone.net>
     for description and examples.

TROUBLESHOOTING
---------------

HTTP transport
     See `TROUBLESHOOTING|SOAP::Transport::HTTP' in this node section in
     documentation for HTTP transport.

COM interface

    Can't call method "server" on undefined value
          Probably you didn't register Lite.dll with 'regsvr32 Lite.dll'

    Failed to load PerlCtrl runtime
          Probably you have two Perl installations in different places and
          ActiveState's Perl isn't the first Perl specified in PATH.
          Rename the directory with another Perl (at least during the
          DLL's startup) or put ActiveState's Perl on the first place in
          PATH.

PERFORMANCE
-----------

Processing of XML encoded fragments
     SOAP::Lite is based on XML::Parser which is basically wrapper around
     James Clark's expat parser. Expat's behavior for parsing XML encoded
     string can affect processing messages that have lot of encoded
     entities, like XML fragments, encoded as strings. Providing low-level
     details, parser will call char() callback for every portion of
     processed stream, but individually for every processed entity or
     newline. It can lead to lot of calls and additional memory manager
     expenses even for small messages. By contrast, XML messages which are
     encoded as base64, don't have this problem and difference in
     processing time can be significant. For XML encoded string that has
     about 20 lines and 30 tags, number of call could be about 100 instead
     of one for the same string encoded as base64.

     Since it is parser's feature there is NO fix for this behavior (let
     me know if you find one), especially because you need to parse
     message you already got (and you cannot control content of this
     message), however, if your are in charge for both ends of processing
     you can switch encoding to base64 on sender's side. It will
     definitely work with SOAP::Lite and it may work with other
     toolkits/implementations also, but obviously I cannot guarantee that.

     If you want to encode specific string as base64, just do `<
     SOAP::Data-'type(base64 => $string) >> either on client or on server
     side. If you want change behavior for specific instance of
     SOAP::Lite, you may subclass SOAP::Serializer, override as_string()
     method that is responsible for string encoding (take a look into
     `as_base64()') and specify new serializer class for your SOAP::Lite
     object with:

          my $soap = new SOAP::Lite
            serializer => My::Serializer->new,
            ..... other parameters

     or on server side:

          my $server = new SOAP::Transport::HTTP::Daemon # or any other server
            serializer => My::Serializer->new,
            ..... other parameters

     If you want to change this behavior for all instances of SOAP::Lite,
     just substitute as_string() method with `as_base64()' somewhere in
     your code after `use SOAP::Lite' and before actual processing/sending:

          *SOAP::Serializer::as_string = \&SOAP::Serializer::as_base64;

     Be warned that last two methods will affect all strings and convert
     them into base64 encoded. It doesn't make any difference for
     SOAP::Lite, but it may make a difference for other toolkits.

WEBHOSTING INSTALLATION
-----------------------

   As soon as you have telnet access to the box and XML::Parser is already
installed there you may install you own copy of SOAP::Lite even if hosting
provider doesn't want to do it himself.

   Login and setup PERL5LIB variable in your .profile (or .bash_profile):

     PERL5LIB=/you/home/directory/lib; export PERL5LIB

   'lib' here is the name of directory where all libraries will be
installed under your home directory.

   Run CPAN module with

     perl -MCPAN -e shell

   and run three commands

     o conf make_arg -I~/lib
     o conf make_install_arg -I~/lib
     o conf makepl_arg LIB=~/lib PREFIX=~ INSTALLMAN1DIR=~/man/man1 INSTALLMAN3DIR=~/man/man3

   LIB will specify directory where all libraries will reside.

   PREFIX will specify prefix for all directoies (like lib, bin, man, but
it doesn't work for all cases for some reason).

   INSTALLMAN1DIR and INSTALLMAN3DIR specify directories for man (if you
don't specify it, install will fail because it'll try to setup it in
default directory and you don't have permissions for that).

   Now you may run:

     install SOAP::Lite

   Later, in your scripts you'll need to add:

     use lib '/your/home/directory/lib';

   somewhere before `'use SOAP::Lite;'' and you're done

BUGS AND LIMITATIONS
====================

   * No support for multidimensional, partially transmitted and sparse
     arrays (however arrays of arrays are supported, as well as any other
     data structures, and you can add your own implementation with `' in
     this node).

   * Limited support for WSDL schemas.

PLATFORMS
=========

MacOS
     Information about XML::Parser for MacPerl could be found here:
     http://bumppo.net/lists/macperl-modules/1999/07/msg00047.html

     Compiled XML::Parser for MacOS could be found here:

     http://www.perl.com/CPAN-local/authors/id/A/AS/ASANDSTRM/XML-Parser-2.27-bin-1-MacOS.tgz

AVAILABILITY
============

   You can download the latest version SOAP::Lite for Unix or SOAP::Lite
for Win32 from http://soaplite.com/ .  SOAP::Lite is available also from
CPAN ( http://search.cpan.org/search?dist=SOAP-Lite ).  You are very
welcome to write mail to the author (paulclinger@yahoo.com) with your
comments, suggestions, bug reports and complaints.

SEE ALSO
========

   See SOAP, SOAP/Perl library from Keith Brown (
http://www.develop.com/soap/ ) or (
http://search.cpan.org/search?dist=SOAP )

ACKNOWLEDGMENTS
===============

   Lot of thanks to   Tony Hong <thong@xmethods.net>,   Petr Janata
<petr.janata@i.cz>,   Murray Nesbitt <murray@ActiveState.com>,   Robert
Barta <rho@bigpond.net.au>,   Gisle Aas <gisle@ActiveState.com>,   Carl K.
Cunningham <cc@roberts.de>,   Graham Glass <graham-glass@mindspring.com>,
Chris Radcliff <chris@velocigen.com>, and   many others for provided
help, feedback, support, patches and comments.

COPYRIGHT
=========

   Copyright (C) 2000-2001 Paul Kulchenko. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Paul Kulchenko (paulclinger@yahoo.com)

Writes SOAP fragments
*********************

NAME
====

   SOAP::OutputStream - Writes SOAP fragments

SYNOPSIS
========

     # note that we need SOAP::Envelope to bootstrap
     use SOAP::Envelope;

     sub output_fcn {
         my $string = shift;
         print $string;
     }

     my $namespaces_to_preload = ["urn:foo", "urn:bar"];
     my $env = SOAP::Envelope->new(\&output_fcn,
                                   $namespaces_to_preload);
     my $body = $env->body();

     # here is where we actually use SOAP::OutputStream
     my $child = $body->compound_accessor("urn:quux", "reverse_string", undef, undef, 0);

     $child->simple_accessor(undef, "s", undef, undef, "dlrow olleH");

     $child->term();
     $body->term();
     $env->term();

   This creates the following XML:

   <s:Envelope xmlns:s="urn:schemas-xmlsoap-org:soap.v1"
xmlns:xsd="http://www.w3.org/1999/XMLSchema"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:n1="urn:foo"             xmlns:n2="urn:bar">   <s:Body>
<n3:reverse_string xmlns:n3="urn:quux">       <s>dlrow olleH</s>
</n3:reverse_string>   </s:Body> </s:Envelope>

DESCRIPTION
===========

   SOAP::OutputStream encapsulates the details of writing SOAP packets
into a few easy to use functions. In order to bootstrap a SOAP stream (and
get your first SOAP::OutputStream reference), you'll need to use
SOAP::Envelope, as shown in the example above.

The simple_accessor function
----------------------------

   This function writes a simple accessor (e.g., a string or number, as
opposed to a compound type). It takes two sets of URI/typenames, one for
the accessor and one for the optional xsi:type attribute. At a minimum,
you must specify the accessor_name and content.

The compound_accessor function
------------------------------

   This function opens a new compound accessor (by writing an open XML
tag), and returns a new SOAP::OutputStream that you should use to write
the contents of that accessor. This function always creates nested
elements. If you want to create an independent element, call
reference_accessor instead. The is_package parameter allows you to open a
new package at this node; the OutputStream will write all further
independent elements at this level in the XML document, creating a
standalone XML fragment within the SOAP envelope. The OutputStream will
complain if all references within the package cannot be resolved when this
node is closed.  See the SOAP spec for details on packages.

   NOTE NOTE NOTE: The SOAP "package" attribute was dropped when the SOAP
spec                 went from version 1.0 to version 1.1. Use
package-related                 functionality at your own risk - you may
not interoperate                 with other servers if you rely on it.
I'll eventually remove                 this feature if it doesn't reappear
in the spec soon.

The reference_accessor function
-------------------------------

   This function creates a reference (SOAP:href) node, and stores the
specified object until the current package is closed, at which time a
serializer is obtained for the object (based on its type) and is asked to
serialize itself to a new stream at the level of the package. Note that if
you're not using packages explicitly, then the system will perform this
resolution and serialization when you switch from creating Headers to
creating the Body, and once again when the Body is terminated. The object
referenced is guaranteed to only be serialized once (assuming you've
obeyed the SOAP rules for packages and Header/Body object reference
sharing).

The term function
-----------------

   Call this function when you want to close the node you're working with.
This does several things - it seals the package if the node you're using
was created as a package, and it writes an end tag (along with doing some
other internal bookeeping that's pretty important). Don't forget to call
this function before opening a new sibling node.

DEPENDENCIES
============

   SOAP::Defs

AUTHOR
======

   Keith Brown

SEE ALSO
========

   SOAP::Envelope

SOAP internal helper class
**************************

NAME
====

   SOAP::Packager - SOAP internal helper class

SYNOPSIS
========

     use SOAP::Packager;
     my $packager = SOAP::Packager->new('s:', 1, sub { print shift } );

     # some object used as a reference
     my $object = SOAP::Object->new();

     # on a given packager, register() always returns the same id for a given object
     my $id = $packager->register($env, $object);
     unless($id == $packager->register($env, $object)) { die "internal error" }

     # this serializes objectA
     $packager->seal($envelope);

     # note that the package is still valid
     unless($id == $packager->register($env, $object)) { die "internal error" }

     my $objectB = SOAP::Object->new();
     my $idB = $packager->register($env, $objectB);
     unless($idB == $packager->register($env, $objectB)) { die "internal error" }

     # this just serializes objectB - objectA was already serialized before
     $packager->seal($env);

     # this does nothing except waste some cycles enumerating a hash table
     $packager->seal($env=);

     # hash tables shut down at destruction of packager, releasing object references
     $packager = undef;

DESCRIPTION
===========

   This is an internal class used by the SOAP/Perl implementation. It is
designed to manage a table of object references and XML ids used for
serializing object graphs that may contain multiref data (and perhaps even
cycles). If you are extending SOAP/Perl, the above synopsis will probably
be all you need if you want to reuse this class. Whatever you pass for the
$env reference should implement a function called _alloc_id that returns a
unique string each time it is called. This is normally implemented by
SOAP::Envelope, so you can see a sample implementation there.

   NOTE NOTE NOTE: The SOAP "package" attribute was dropped when the SOAP
spec                 went from version 1.0 to version 1.1. Use
package-related                 functionality at your own risk - you may
not interoperate                 with other servers if you rely on it.
I'll eventually remove                 this feature if it doesn't reappear
in the spec soon.

AUTHOR
======

   Keith Brown

SEE ALSO
========

   SOAP::Envelope SOAP::OutputStream

Parses SOAP documents
*********************

NAME
====

   SOAP::Parser - Parses SOAP documents

SYNOPSIS
========

     use SOAP::Parser;

     my $parser = SOAP::Parser->new();

     $parser->parsefile('soap.xml');

     my $headers = $parser->get_headers();
     my $body    = $parser->get_body();

DESCRIPTION
===========

   SOAP::Parser has all the logic for traversing a SOAP packet, including
Envelope, Header, and Body, dealing with namespaces and tracking down
references. It is basically an extension of a SAX-like parser, which means
that it exposes an event-driven interface that you can implement to get
the results of the parse. By default, SOAP/Perl provides
SOAP::GenericInputStream to handle these events, which simply produces an
object graph of hash references. If you want something different, on a per
type URI basis, you can register alternate handlers so you can produce
different output. See SOAP::TypeMapper for details.

   The handler needs to implement a set of methods, and these are outlined
in SOAP::GenericInputStream along with descriptions of what the default
behavior is (in other words, what SOAP::GenericInputStream does for each
of these methods).

   The benefit of this design is that it avoids using a DOM to parse SOAP
packets; rather, the packet is unmarshaled directly into whatever final
form you need. This is more efficient in space and time than first
unmarshaling into a DOM and then traversing the DOM to create an object
graph that is meaningful to your program. To get the full benefit of this,
you may need to implement a handler that creates your custom object graph
from the SOAP packet (see SOAP::GenericInputStream for details). Since
SOAP::Parser does all the hard work, implementing a handler (or set of
handlers) is really pretty painless.

new(TypeMapper)
---------------

   Creates a new parser. Be sure *not* to reuse a parser for multiple SOAP
packets - create one, use it, and then throw it away and get a new one if
you need to parse a second SOAP packet.

   TypeMapper is an optional parameter that points to an instance of
SOAP::TypeMapper that allows you to register alternate serializers and
deserializers for different classes of objects. See the docs for that
class for more details. If you don't pass this parameter, the system uses
a default TypeMapper object.

parsestring(String)
-------------------

   Parses the given string.

parsefile(Filename)
-------------------

   Parses the given file.

get_headers()
-------------

   After parsing, this function returns the array of headers in the SOAP
envelope.

   Specifically, this function returns an array reference that contains
zero or more hash references, each of which always take the following form:

     {
       soap_typeuri  => 'namespace qualification of header',
       soap_typename => 'unqualified name of header',
       content       => <header object>
     }

   For instance, the following header:

     <f:MyHeader xmlns:f="urn:foo">42 </f:MyHeader>

   would be deserialized in this form:

     {
       soap_typeuri  => 'urn:foo',
       soap_typename => 'MyHeader',
       content       => 42,
     }

     while this header:

     <f:MyHeader xmlns:f="urn:foo">
      <m1>something</m1>
      <m2>something else</m2>
     </f:MyHeader>

   would be deserialized (by default) in this form:

     {
       soap_typeuri  => 'urn:foo',
       soap_typename => 'MyHeader',
       content       => {
           soap_typeuri  => 'urn:foo',
           soap_typename => 'MyHeader',
           m1 => 'something',
           m2 => 'something else',
       },
     }

   Note the redundancy of the soap_typeuri and soap_typename isn't
strictly necessary in this case because this information is embedded in
the content itself. However, because of the potential (and common need)
for sending scalars as the entirety of the header content, we need some
way of communicating the namespace and typename of the header. Thus the
content, for consistency, is always packaged in a hash along with explicit
type information.

get_body()
----------

   After parsing, this function retrieves the body of the SOAP envelope.

   Since it doesn't make sense to send just a scalar as the body of a SOAP
request, we don't need the redundancy of packaging the content inside of a
hash along with its type and namespace (as was done above with headers).
For instance:

     <f:MyBody xmlns:f="urn:foo">
      <m1>something</m1>
      <m2>something else</m2>
     </f:MyBody>

   would be deserialized (by default) as the following:

     {
       soap_typeuri  => 'urn:foo',
       soap_typename => 'MyBody',
       m1 => 'something',
       m2 => 'something else',
     }

DEPENDENCIES
============

   XML::Parser::Expat SOAP::GenericInputStream SOAP::Defs

AUTHOR
======

   Keith Brown

SEE ALSO
========

   SOAP::GenericInputStream

serialization utilities
***********************

NAME
====

   SOAP::Serializer - serialization utilities

SYNOPSIS
========

   Used internally by SOAP/Perl

DESCRIPTION
===========

   Used internally by SOAP/Perl

AUTHOR
======

   Keith Brown

deprecated
**********

NAME
====

   SOAP::SimpleTypeWrapper - deprecated

SYNOPSIS
========

   deprecated

DESCRIPTION
===========

   Introduced in SOAP/Perl 0.24 Deprecated in SOAP/Perl 0.25

AUTHOR
======

   Keith Brown

support for ordered hashes
**************************

NAME
====

   SOAP::Struct - support for ordered hashes

SYNOPSIS
========

   use SOAP::EnvelopeMaker;

   # produce a body that will retain the order of params # when serialized
to a SOAP envelope my $body = SOAP::Struct->new(     a => 3,     b => 4, );

   # same as above, but explicit xsi:type attrs will also # be included
for accessor 'b' my $body = SOAP::Struct->new_typed(     a => 3,     undef,
   b => 4,     'float', );

DESCRIPTION
===========

   The SOAP spec explicitly mandates that it should be possible to
serialize structures and control both the names of the accessors and the
order that they appear in the serialized stream.  (SOAP 1.1, section 7.1,
bullet 3) Prior to SOAP/Perl 0.25, this was impossible, as the only way to
serialize a "struct" was to use a hash, which is unordered in Perl. This
class allows you to specify a structure where the order of the accessors
is preserved. This is important when making SOAP calls to many traditional
RPC-style servers that expect parameters to arrive in a certain order (and
could generally care less about the names of those parameters).

new(accessor_1_name => accessor_1_value, ...)
---------------------------------------------

   This constructor feels the same as constructing a hash, but the order
of the accessors will be maintained when this "super-hash" is serialized.

new_typed(accessor_1_name => accessor_1_value, accessor_1_type, ...)
--------------------------------------------------------------------

   This constructor is for convenience - if you pass something other than
undef for accessor_n_type, then accessor_n_value will be wrapped with a
TypedPrimitive class with the specified type. This way you can force
explicit type names to be used for each element in the structure.  See
SOAP::TypedPrimitive for a discussion of why this can be important.

DEPENDENCIES
============

   SOAP::TypedPrimitive

AUTHOR
======

   Keith Brown

SEE ALSO
========

   SOAP::TypedPrimitive

(internal) serializer for SOAP structs
**************************************

NAME
====

   SOAP::StructSerializer - (internal) serializer for SOAP structs

DEPENDENCIES
============

   SOAP::Struct SOAP::Serializer

AUTHOR
======

   Keith Brown

SEE ALSO
========

   SOAP::Struct

Test framework for SOAP::Lite
*****************************

NAME
====

   SOAP::Test - Test framework for SOAP::Lite

SYNOPSIS
========

     use SOAP::Test;

     SOAP::Test::Server::run_for('http://localhost/cgi-bin/soap.cgi');

DESCRIPTION
===========

   SOAP::Test provides simple framework for testing server implementations.
Specify your address (endpoint) and run provided tests against your server.
See t/1*.t for examples.

COPYRIGHT
=========

   Copyright (C) 2000-2001 Paul Kulchenko. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Paul Kulchenko (paulclinger@yahoo.com)

Server/Client side ActiveWorks support for SOAP::Lite for Perl
**************************************************************

NAME
====

     SOAP::Transport::ACTIVEWORKS - Server/Client side ActiveWorks support for SOAP::Lite for Perl

SYNOPSIS
========

     use SOAP::Lite +autodispatch =>
       uri      => 'activeworks://myBroker:clientGroup@my.active.host:7449',
       proxy    => 'http://my.http.host/aw-soap/',
       on_fault => sub { my($soap, $res) = @_;
         die ref $res ? $res->faultdetail : $soap->transport->status, "\n";
       }
     ;

     print "Remote Time is ", ${ AdapterDevKit::timeRequest->SOAP::publish }{time}, "\n";

DESCRIPTION
===========

   The SOAP::Transport::ACTIVEWORKS class provides support for ActiveWorks
URIs to access ActiveWorks brokers through an HTTP proxy server with SOAP
structured requests.  The package also allows an ActiveWorks adapter to be
used as a SOAP server to either invoke arbitrary Perl classes or to
publish and return ActiveWorks events specified in a SOAP structure.

   This class mirrors the interface of the SOAP::Transport::HTML class
which should be referred to for general documentation.  The URI differences
will be discussed here with example usage.

ACTIVEWORKS URI COMPONENTS
--------------------------

   The general schema of an ActiveWorks URI is as follows:

     activeworks://<broker>:<client group>@<host>:<port>

   All parameters are optional and defaults can be set within the BEGIN
section of the SOAP::Transport::ActiveWorks package.  The assumed client
group is always 'SOAP' and SOAP requests are forwarded to a SOAP adapter
(*server/soap_adapter.pl* is provided) assumed to be running on the
default broker.

   If an alternative client group is specified the SOAP request is assumed
to contain fields corresponding to a named ActiveWorks event available on
the broker.  See section `PSEUDO EVENTS' for details.

HTTP PROXY SETTINGS
-------------------

   When using an HTTP server to proxy publish AW events the 'proxy'
autodispatcher parameter should be set to your SOAP server URI as you
would with a normal SOAP request.

     use SOAP::Lite +autodispatch =>
       uri      => 'urn:', # use default broker, client group, etc.
       proxy    => 'http://my.http.host/aw-soap/',
       on_fault => sub { my($soap, $res) = @_;
         die ref $res ? $res->faultdetail : $soap->transport->status, "\n";
       }
     ;

   Note that the SOAP server, 'aw-soap' in this case, must be enabled to
dispatch requests to an ActiveWorks handler.  The provided Apache::AwSOAP
module demonstrates this:

     package Apache::AwSOAP;

     use strict;
     use Apache;
     use SOAP::Transport::ACTIVEWORKS;

     my $server = SOAP::Transport::ACTIVEWORKS::Apache
        -> dispatch_to( '' );

     sub handler { $server->handler(@_); }

     1;

   The *client/http-aw-soap-aw-calculator.pl* script demonstrates relaying
a SOAP envelope from an http server to an ActiveWorks adapter for
processing.

   To work with your normal soap server, the AwGateway module may be used
to relay an ordinary SOAP request as an ActiveWorks event to a broker
specified in the autodispatcher 'uri' parameter.  See section AwGateway.

USING AN ACTIVEWORKS BROKER AS A SOAP SERVER
--------------------------------------------

   The ACTIVEWORKS module along with the *soap-lite-adapter.pl* allows you
to use an ActiveWorks broker as a SOAP server.  Like a normal http server
the SOAP adapter will instantiate and invoke the class and method specified
in a SOAP request.  In addition, classes may be mapped onto ActiveWorks
events (see section PSEUDO CLASSES), mapped onto an adapter subroutine for
special handling (see *http-callback-aw-aw-time.pl* for a demonstration)
and even relayed to an http SOAP server specified in the method URI (see
*aw-soap-aw-http-calculator.pl* for example usage).

   The *soap-lite-adapter.pl* allows an  ActiveWorks client to send and
receive requests to a broker with a SOAP envelope to take advantage of the
SOAP protocol in a purely ActiveWorks environment.

PSEUDO CLASSES
--------------

   ActiveWorks events may be instantiated and published much like remote
classes.  With a 'pseudo class' we treat the remote event as if it were
just another SOAP class that we want to access remotely.

   The difference will be that we can only send a hash reference as an
argument and always get a hash type in return (which is in keeping with
the Aw package treatment of events as hashes).  Also we publish the event
with the dummy method '->publish'.

     use SOAP::Lite +autodispatch =>
       uri      => 'activeworks://myBroker:clientGroup@my.active.host:7449',
       proxy    => 'http://my.http.host/aw-soap/',
       on_fault => sub { my($soap, $res) = @_;
         die ref $res ? $res->faultdetail : $soap->transport->status, "\n";
       }
     ;

     #
     # Hash are used to transport ActiveWorks request event data:
     #
     my %request = ();

     #
     # Populate the event fields:
     #
     $request{numbers} = \@Numbers;

     #
     # Reset default publish timeout from 20 seconds:
     #
     $request{_event_timeout} = 40000;

     #
     # Publish event and force returned SOAPStruct type into a hash:
     #
     my %results = %{ AdapterDevKit::calcRequest->SOAP::publish ( \%request ) };

   The client script *http-pseudo-aw-aw-calculator.pl* and
*http-pseudo-aw-aw-time.pl* demonstrate pseudo class usage.

AwGateway
---------

   The AwGateway module is a normal SOAP module that you would keep in your
"Deployed Modules" directory.  With AwGateway you access an ActiveWorks
broker through your usual SOAP server and bi-pass the ACTIVEWORKS module
altogether.

   See the AwGateway full documentation and the accompanying client script
*http-gateway-aw-aw-calculator.pl* demonstration use.

DEPENDENCIES
============

     The Aw package for Perl interfaces to ActiveWorks libraries.
     The SOAP-Lite package.

SEE ALSO
========

     See SOAP::Transport::HTTP

COPYRIGHT
=========

   Copyright (C) 2000 Paul Kulchenko. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   The SOAP::Transport::ACTIVEWORKS module was developed by Daniel Yacob
and is derived directly from SOAP::Transport::HTTP by Paul Kulchenko.

     Daniel Yacob,  L<yacob@rcn.com|mailto:yacob@rcn.com>
     Paul Kulchenko,  L<paulclinger@yahoo.com|mailto:paulclinger@yahoo.com>

Automarshall methods for Perl SOAP
**********************************

NAME
====

   SOAP::Transport::ActiveWorks::AutoInvoke::Client - Automarshall methods
for Perl SOAP

SYNOPSIS
========

     #!/usr/bin/perl -w

     #
     #  Client example that goes with server example
     #  in SOAP::Transport::ActiveWorks::AutoInvoke::Client
     #
     use strict;

     package Calculator;
     use base qw( SOAP::Transport::ActiveWorks::AutoInvoke::Client );

     package main;

     my $calc = new Calculator;

     print "sum = ", $calc->add ( 1, 2, 3 ), "\n";

DESCRIPTION
===========

   The intention of the AutoInvoke package is to allow a SOAP client to
use a remote class as if it were local.  The remote package is treated as
local with a declaration like:

     package MyClass;
     use base qw( SOAP::Transport::ActiveWorks::AutoInvoke::Client );

   The SOAP::AutoInvoke base class will "Autoload" methods called from an
instance of "MyClass", send it to the server side, and return the results
to the caller's space.

Provided Methods
----------------

new:
     * * The 'new' method may be called with option arguments to reset
     variables from the defaults.

          my $class = new MyClass (
                          _soap_host       => 'anywhere.com',
                          _soap_port       => 8849,
                          _soap_client_group   => 'NotSOAP',
                          _soap_method_uri => 'urn:com-name-your'
                      );

     It is advisable to set the package defaults at installation time in
     the SOAP/Transport/ActiveWorks/AutoInvoke/Client.pm (this) file.  The
     variables may also be reset after instantiation with the 'set'
     methods.

     The '_soap_' variable is relevant only to the local instantiation of
     "MyClass".  The remote instantiation will call "new" with any
     arguments you have passed to the local instantiation that did not
     begin with '_soap_':

          my $class = new MyClass (
                          _soap_host => 'anywhere.com',
                          arg1,
                          arg2,
                          @arg3,
                          arg4   => $value,
                          :
                      );

     This works so long as the data types being passed are something the
     SOAP package can serialize.  SOAP::AutoInvoke can send and receive
     simple arrays.

     To reset the name of the "new" to be called remotely:

          my $class = new MyClass (
                          :
                          _soap_new_method => 'create',
                          :
                      );

     To not call any new method remotely:

          my $class = new MyClass (
                          :
                          _soap_new_method => undef,
                          :
                      );

    *_soap_get_post*:
          returns the contents of $class->{_soap_host}.

    *_soap_set_post*:
          sets the contents of $class->{_soap_host}.

    *_soap_get_port*:
          returns the contents of $class->{_soap_port}.

    *_soap_set_port*:
          sets the contents of $class->{_soap_port}.

    *_soap_get_broker*:
          returns the contents of $class->{_soap_broker}.

    *_soap_set_broker*:
          sets the contents of $class->{_soap_broker}.

    *_soap_get_client_group*:
          returns the contents of $class->{_soap_client_group}.

    *_soap_set_client_group*:
          sets the contents of $class->{_soap_client_group}.

    *_soap_get_method_uri*:
          returns the contents of $class->{_soap_method_uri}.

    *_soap_set_method_uri*:
          sets the contents of $class->{_soap_method_uri}.

    *_soap_get_new_args*:
          returns the contents of $class->{_soap_new_args}.

    *_soap_set_new_args*:
          sets the contents of $class->{_soap_new_args}.

    *_soap_get_new_method*:
          returns the contents of $class->{_soap_new_method}.

    *_soap_set_new_method*:
          sets the contents of $class->{_soap_new_method}.  The default is
          "new".

DEPENDENCIES
============

   SOAP-0.28 SOAP::Transport::ActiveWorks Data::Dumper

AUTHOR
======

   Daniel Yacob, `yacob@rcn.com|mailto:yacob@rcn.com' in this node

SEE ALSO
========

   perl(1). SOAP(3). SOAP::Transport::ActiveWorks::AutoInvoke::Server(3).

Automarshall methods for Perl SOAP
**********************************

NAME
====

   SOAP::Transport::ActiveWorks::AutoInvoke::Server - Automarshall methods
for Perl SOAP

SYNOPSIS
========

   require SOAP::Transport::ActiveWorks::Server; use
SOAP::Transport::ActiveWorks::AutoInvoke::Server;

   my $safe_classes ={       Calculator => \&auto_invoke,       Time
=> \&handle_time_request, };

DESCRIPTION
===========

   SOAP::Transport::ActiveWorks::AutoInvoke::Server provides the dispatch
subroutine "auto_invoke" to handle class instantiation and method
invocation that were called with a client created with
SOAP::Transport::ActiveWorks::AutoInvoke::Client.

   Intended use is with SOAP adapters.

DEPENDENCIES
============

   SOAP-0.28 SOAP::Transport::ActiveWorks
SOAP::Transport::ActiveWorks::AutoInvoke::Client Data::Dumper

AUTHOR
======

   Daniel Yacob, `yacob@rcn.com|mailto:yacob@rcn.com' in this node

SEE ALSO
========

   perl(1). SOAP(3). SOAP::Transport::ActiveWorks::AutoInvoke::Client(3).

Client side ActiveWorks support for SOAP/Perl
*********************************************

NAME
====

   SOAP::Transport::ActiveWorks::Client - Client side ActiveWorks support
for SOAP/Perl

SYNOPSIS
========

     use SOAP::Transport::ActiveWorks::Client;

     my $soap_on_aw = SOAP::Transport::ActiveWorks::Client->new();

     my $soap_response = $soap_on_aw->send_receive (
                         $self->{_soap_host},
                         $self->{_soap_port},
                         $self->{_soap_broker},
                         $self->{_soap_client_group},
     			$self->{_soap_class},
                         $self->{_soap_method_uri},
                         $method_name,
                         $soap_request
     );

DESCRIPTION
===========

   SOAP::Transport::ActiveWorks::Client provides a client class with the
single method "send_receive" to deliver a SOAP formatted request to a SOAP
adapter connected to an ActiveWorks broker.

   The ActiveWorks SOAP client is the direct analog to the HTTP Client.
The primary difference is that the "endpoint" is split into fields
specifying the "broker" and "client_group" to connect to.  These
attributes may be set when the client object is instantiated or at any
time afterwards.  Not specifiying a values defaults to the settings in
SOAP::Transport::ActiveWorks::Defs.

DEPENDENCIES
============

     Aw::Client
     SOAP-0.28
     SOAP::Defs
     SOAP::Transport::ActiveWorks::Defs;

AUTHOR
======

   Daniel Yacob, `yacob@rcn.com|mailto:yacob@rcn.com' in this node

SEE ALSO
========

   perl(1). SOAP(3). SOAP::Transport::ActiveWorks::Server(3).

Spec-defined constants
**********************

NAME
====

   SOAP::Transport::ActiveWorks::Defs - Spec-defined constants

SYNOPSIS
========

     use SOAP::Transport::ActiveWorks::Defs;

DESCRIPTION
===========

   This is an internal class that exports global symbols needed by various
SOAP/ActiveWorks/Perl classes. You don't need to import this module
directly unless you happen to be building SOAP plumbing (as opposed to
simply writing a SOAP client or server).

AUTHOR
======

   Daniel Yacob, `yacob@rcn.com|mailto:yacob@rcn.com' in this node

SEE ALSO
========

   perl(1). SOAP(3). SOAP::Transport::ActiveWorks::Server(3).

Forward SOAP requests from Apache to an ActiveWorks broker
**********************************************************

NAME
====

   SOAP::Transport::ActiveWorks::HTTP::Apache - Forward SOAP requests from
Apache to an ActiveWorks broker

SYNOPSIS
========

     package Apache::SOAPServer;
     use strict;
     use Apache;
     use SOAP::Transport::HTTP::Apache;
     use SOAP::Transport::ActiveWorks::HTTP::Apache;

     sub handler {

     my $http_safe_classes = {
         ClassA => undef,
         ClassB => undef,
     };

     my $aw_safe_classes = {
         ClassC     => undef,
         Calculator => undef,
     };

     my $r = Apache->request();

     my %args = $r->args();

     if ( $http_safe_classes->{$args{class}} ) {
          #
          #  Handle requests here and now.
          #
          SOAP::Transport::HTTP::Apache->handler($http_safe_classes);
     }
     else {
          #
          #  Forward to an adapter for handling.
          #
          SOAP::Transport::ActiveWorks::HTTP::Apache->handler($aw_safe_classes);
     }

     }

DESCRIPTION
===========

   This package is a minor rewrite of the SOAP::Transport::HTTP::Apache.
The difference is that it uses a proxy handler to forward requests to an
ActiveWorks broker instead the HTTP server handler.

DEPENDENCIES
============

   SOAP::Transport::HTTP::Server;

AUTHOR
======

   Daniel Yacob, `yacob@rcn.com|mailto:yacob@rcn.com' in this node

SEE ALSO
========

   perl(1). SOAP(3). SOAP::Transport::ActiveWorks::HTTP::Proxy(3).

Forward SOAP requests from an HTTP server to an ActiveWorks broker
******************************************************************

NAME
====

   SOAP::Transport::ActiveWorks::HTTP::Proxy - Forward SOAP requests from
an HTTP server to an ActiveWorks broker

SYNOPSIS
========

     require SOAP::Transport::HTTP::Proxy;

     my $s = SOAP::Transport::ActiveWorks::HTTP::Proxy->new();

     $s->handle_request($http_method, $request_class,
     			   $request_header_reader,
     			   $request_content_reader,
     			   $response_header_writer,
     			   $response_content_writer,
     			   $optional_dispatcher);

DESCRIPTION
===========

   SOAP::Transport::ActiveWorks::HTTP::Proxy provides a handler for use by
SOAP::Transport::ActiveWorks::HTTP::Apache for forwarding requests to an
ActiveWorks broker received via Apache or other HTTP server.  The
relationship between packages is identical to that of
SOAP::Transport::::HTTP::Apache/Server.

   See SOAP::Transport::ActiveWorks::HTTP::Apache for intended usage.  The
package also provides a subroutine for optional usage as dispatcher.

http_proxy
----------

   * * The subroutine http_proxy may be imported from the package to use
with SOAP::Transport::HTTP::Apache directly as an optional_dispatcher.
Optional dispatcher usage as shown below is valid with the version of
SOAP::Transport::HTTP::Apache that comes with the SOAP-AutoInvoke package:

     package Apache::SOAPServer;
     use strict;
     use Apache;
     use SOAP::Transport::HTTP::Apache;
     use SOAP::Transport::ActiveWorks::HTTP::Proxy qw( http_proxy );

     sub handler {

     my $safe_classes ={
         ClassA       => undef,
         ClassB       => undef,
         Calculator   => \&http_proxy,
     };

     SOAP::Transport::HTTP::Apache->handler($safe_classes);

   }

DEPENDENCIES
============

     SOAP::Defs
     SOAP::Parser
     SOAP::EnvelopeMaker
     SOAP::Transport::ActiveWorks::Defs

AUTHOR
======

   Daniel Yacob, `yacob@rcn.com|mailto:yacob@rcn.com' in this node

SEE ALSO
========

   perl(1). SOAP(3). SOAP::Transport::ActiveWorks::HTTP::Apache(3).

Server side ActiveWorks support for SOAP/Perl
*********************************************

NAME
====

   SOAP::Transport::ActiveWorks::Server - Server side ActiveWorks support
for SOAP/Perl

SYNOPSIS
========

     require SOAP::Transport::ActiveWorks::Server;

     my $s = new SOAP::Transport::ActiveWorks::Server;

     $s->handle_request (
         $request_type,
         $request_class,
         $request_header_reader,
         $request_content_reader,
         $response_header_writer,
         $response_content_writer,
         $optional_dispatcher
     );

DESCRIPTION
===========

   This package is a minimalist wrapper around
SOAP::Transport::HTTP::Server which may be substituted for this package
with no loss of functionality.  This is not guaranteed to be the case in
the future.

DEPENDENCIES
============

   SOAP::Transport::HTTP::Server;

AUTHOR
======

   Daniel Yacob, `yacob@rcn.com|mailto:yacob@rcn.com' in this node

SEE ALSO
========

   perl(1). SOAP(3). SOAP::Transport::ActiveWorks::Client(3).

Client side FTP support for SOAP::Lite
**************************************

NAME
====

   SOAP::Transport::FTP - Client side FTP support for SOAP::Lite

SYNOPSIS
========

     use SOAP::Lite
       uri => 'http://my.own.site.com/My/Examples',
       proxy => 'ftp://login:password@ftp.somewhere.com/relative/path/to/file.xml', # ftp server
       # proxy => 'ftp://login:password@ftp.somewhere.com//absolute/path/to/file.xml', # ftp server
     ;

     print getStateName(1);

DESCRIPTION
===========

COPYRIGHT
=========

   Copyright (C) 2000-2001 Paul Kulchenko. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Paul Kulchenko (paulclinger@yahoo.com)

Server/Client side HTTP support for SOAP::Lite
**********************************************

NAME
====

   SOAP::Transport::HTTP - Server/Client side HTTP support for SOAP::Lite

SYNOPSIS
========

Client
          use SOAP::Lite
            uri => 'http://my.own.site.com/My/Examples',
            proxy => 'http://localhost/',
          # proxy => 'http://localhost/cgi-bin/soap.cgi', # local CGI server
          # proxy => 'http://localhost/',                 # local daemon server
          # proxy => 'http://localhost/soap',             # local mod_perl server
          # proxy => 'https://localhost/soap',            # local mod_perl SECURE server
          # proxy => 'http://login:password@localhost/cgi-bin/soap.cgi', # local CGI server with authentication
          ;

          print getStateName(1);

CGI server
          use SOAP::Transport::HTTP;

          SOAP::Transport::HTTP::CGI
            # specify path to My/Examples.pm here
            -> dispatch_to('/Your/Path/To/Deployed/Modules', 'Module::Name', 'Module::method')
            -> handle
          ;

Daemon server
          use SOAP::Transport::HTTP;

          # change LocalPort to 81 if you want to test it with soapmark.pl

          my $daemon = SOAP::Transport::HTTP::Daemon
            -> new (LocalAddr => 'localhost', LocalPort => 80)
            # specify list of objects-by-reference here
            -> objects_by_reference(qw(My::PersistentIterator My::SessionIterator My::Chat))
            # specify path to My/Examples.pm here
            -> dispatch_to('/Your/Path/To/Deployed/Modules', 'Module::Name', 'Module::method')
          ;
          print "Contact to SOAP server at ", $daemon->url, "\n";
          $daemon->handle;

Apache mod_perl server
     See `examples/server/Apache.pm' and `' in this node section for more
     information.

mod_soap server (.htaccess, directory-based access)
          SetHandler perl-script
          PerlHandler Apache::SOAP
          PerlSetVar dispatch_to "/Your/Path/To/Deployed/Modules, Module::Name, Module::method"
          PerlSetVar options "compress_threshold => 10000"

     See Apache/SOAP, for more information.

DESCRIPTION
===========

   This class encapsulates all HTTP related logic for a SOAP server,
independent of what web server it's attached to.  If you want to use this
class you should follow simple guideline mentioned above.

   Following methods are available:

on_action()
     on_action method lets you specify SOAPAction understanding. It accepts
     reference to subroutine that takes three parameters:

          SOAPAction, method_uri and method_name.

     `SOAPAction' is taken from HTTP header and method_uri and method_name
     are extracted from request's body. Default behavior is match
     `SOAPAction' if present and ignore it otherwise. You can specify you
     own, for example die if `SOAPAction' doesn't match with following
     code:

          $server->on_action(sub {
            (my $action = shift) =~ s/^("?)(.+)\1$/$2/;
            die "SOAPAction shall match 'uri#method'\n" if $action ne join '#', @_;
          });

dispatch_to()
     dispatch_to lets you specify where you want to dispatch your services
     to. More precisely, you can specify PATH, MODULE, method or
     combination `MODULE::method'. Example:

          dispatch_to(
            'PATH/',          # dynamic: load anything from there, any module, any method
            'MODULE',         # static: any method from this module
            'MODULE::method', # static: specified method from this module
            'method',         # static: specified method from main::
          );

     If you specify `PATH/' name of module/classes will be taken from uri
     as path component and converted to Perl module name with substitution
     '::' for '/'. Example:

          urn:My/Examples              => My::Examples
          urn://localhost/My/Examples  => My::Examples
          http://localhost/My/Examples => My::Examples

     For consistency first '/' in the path will be ignored.

     According to this scheme to deploy new class you should put this
     class in one of the specified directories and enjoy its services.
     Easy, eh?

handle()
     handle method will handle your request. You should provide parameters
     with request() method, call handle() and get it back with response() .

request()
     request method gives you access to HTTP::Request object which you can
     provide for Server component to handle request.

response()
     response method gives you access to HTTP::Response object which you
     can access to get results from Server component after request was
     handled.

PROXY SETTINGS
--------------

   You can use any proxy setting you use with LWP::UserAgent modules:

     SOAP::Lite->proxy('http://endpoint.server',
                       proxy => ['http' => 'http://my.proxy.server']);

   or

     $soap->transport->proxy('http' => 'http://my.proxy.server');

   should specify proxy server for you. And if you use `HTTP_proxy_user'
and `HTTP_proxy_pass' for proxy authorization SOAP::Lite should know how
to handle it properly.

COOKIE-BASED AUTHENTICATION
---------------------------

     use HTTP::Cookies;

     my $cookies = HTTP::Cookies->new(ignore_discard => 1);
       # you may also add 'file' if you want to keep them between sessions

     my $soap = SOAP::Lite->proxy('http://localhost');
     $soap->transport->cookie_jar($cookies);

   Cookies will be taken from response and provided for request. You may
always add another cookie (or extract what you need after response) with
HTTP::Cookies interface.

   You may also do it in one line:

     $soap->proxy('http://localhost',
                  cookie_jar => HTTP::Cookies->new(ignore_discard => 1));

COMPRESSION
-----------

   SOAP::Lite provides you option for enabling compression on wire (for
HTTP transport only). Both server and client should support this
capability, but this logic should be absolutely transparent for your
application.  Server will respond with encoded message only if client can
accept it (client sends Accept-Encoding with 'compress' or '*' values) and
client has fallback logic, so if server doesn't understand specified
encoding (Content-Encoding: compress) and returns proper error code (406
NOT ACCEPTABLE) client will repeat the same request not encoded and will
store this server in per-session cache, so all other requests will go
there without encoding.

   Having options on client and server side that let you specify threshold
for compression you can safely enable this feature on both client and
server side.

Client
          print SOAP::Lite
            -> uri('http://localhost/My/Parameters')
            -> proxy('http://localhost/', options => {compress_threshold => 10000})
            -> echo(1 x 10000)
            -> result
          ;

Server
          my $server = SOAP::Transport::HTTP::CGI
            -> dispatch_to('My::Parameters')
            -> options({compress_threshold => 10000})
            -> handle;

   Compression will be enabled on client side IF: threshold is specified
AND size of current message is bigger than threshold AND module
Compress::Zlib is available. Client will send header 'Accept-Encoding'
with value 'compress' if threshold is specified AND module Compress::Zlib
is available.

   Server will accept compressed message if module Compress::Zlib is
available, and will respond with compressed message ONLY IF: threshold is
specified AND size of current message is bigger than threshold AND module
Compress::Zlib is available AND header 'Accept-Encoding' is presented in
request.

EXAMPLES
========

   Consider following examples of SOAP servers:

CGI:
          use SOAP::Transport::HTTP;

          SOAP::Transport::HTTP::CGI
            -> dispatch_to('/Your/Path/To/Deployed/Modules', 'Module::Name', 'Module::method')
            -> handle
          ;

daemon:
          use SOAP::Transport::HTTP;

          my $daemon = SOAP::Transport::HTTP::Daemon
            -> new (LocalAddr => 'localhost', LocalPort => 80)
            -> dispatch_to('/Your/Path/To/Deployed/Modules', 'Module::Name', 'Module::method')
          ;
          print "Contact to SOAP server at ", $daemon->url, "\n";
          $daemon->handle;

mod_perl:
     httpd.conf:

          <Location /soap>
            SetHandler perl-script
            PerlHandler SOAP::Apache
          </Location>

     Apache.pm:

          package SOAP::Apache;

          use SOAP::Transport::HTTP;

          my $server = SOAP::Transport::HTTP::Apache
            -> dispatch_to('/Your/Path/To/Deployed/Modules', 'Module::Name', 'Module::method');

          sub handler { $server->handler(@_) }

          1;

Apache::Registry:
     httpd.conf:

          Alias /mod_perl/ "/Apache/mod_perl/"
          <Location /mod_perl>
            SetHandler perl-script
            PerlHandler Apache::Registry
            PerlSendHeader On
            Options +ExecCGI
          </Location>

     soap.mod_cgi (put it in /Apache/mod_perl/ directory mentioned above)

          use SOAP::Transport::HTTP;

          SOAP::Transport::HTTP::CGI
            -> dispatch_to('/Your/Path/To/Deployed/Modules', 'Module::Name', 'Module::method')
            -> handle
          ;

   WARNING: dynamic deployment with Apache::Registry will fail, because
module will be loaded dynamically only for the first time. After that it
is already in the memory, that will bypass dynamic deployment and produces
error about denied access. Specify both PATH/ and MODULE name in
dispatch_to() and module will be loaded dynamically and then will work as
under static deployment. See examples/server/soap.mod_cgi for example.

TROUBLESHOOTING
===============

Dynamic libraries are not found
     If you see in webserver's log file something like this:

     Can't load
     '/usr/local/lib/perl5/site_perl/.../XML/Parser/Expat/Expat.so' for
     module XML::Parser::Expat: dynamic linker: /usr/local/bin/perl:
     libexpat.so.0 is NEEDED, but object does not exist at
     /usr/local/lib/perl5/.../DynaLoader.pm line 200.

     and you are using Apache web server, try to put into your httpd.conf

          <IfModule mod_env.c>
              PassEnv LD_LIBRARY_PATH
          </IfModule>

Apache is crashing with segfaults
     If using SOAP::Lite (or XML::Parser::Expat) in combination with
     mod_perl causes random segmentation faults in httpd processes try to
     configure Apache with:

          RULE_EXPAT=no

     See http://archive.covalent.net/modperl/2000/04/0185.xml for more
     details and lot of thanks to Robert Barta (rho@bigpond.net.au) for
     explaining this weird behavior.

CGI scripts are not running under Microsoft Internet Information Server (IIS)
     CGI scripts may not work under IIS unless scripts are .pl, not .cgi.

DEPENDENCIES
============

     Crypt::SSLeay             for HTTPS/SSL
     SOAP::Lite, URI           for SOAP::Transport::HTTP::Server
     LWP::UserAgent, URI       for SOAP::Transport::HTTP::Client
     HTTP::Daemon              for SOAP::Transport::HTTP::Daemon
     Apache, Apache::Constants for SOAP::Transport::HTTP::Apache

SEE ALSO
========

     See ::CGI, ::Daemon and ::Apache for implementation details.
     See examples/server/soap.cgi as SOAP::Transport::HTTP::CGI example.
     See examples/server/soap.daemon as SOAP::Transport::HTTP::Daemon example.
     See examples/My/Apache.pm as SOAP::Transport::HTTP::Apache example.

COPYRIGHT
=========

   Copyright (C) 2000-2001 Paul Kulchenko. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Paul Kulchenko (paulclinger@yahoo.com)

SOAP mod_perl handler
*********************

NAME
====

   SOAP::Transport::HTTP::Apache - SOAP mod_perl handler

SYNOPSIS
========

   Use this class to expose SOAP endpoints using Apache and mod_perl.
Here's an example of a class that would like to receive SOAP packets. Note
that it implements a single interesting function, handle_request, that
takes there arguments: an array of headers, a body, and an EnvelopeMaker
for creating the response:

     package Calculator;
     use strict;

     sub new {
         bless {}, shift;
     }

     sub handle_request {
         my ($self, $headers, $body, $envelopeMaker) = @_;

     $body->{extra_stuff} = "heres some extra stuff";

     foreach my $header (@$headers) {
         $header->{extra_stuff} = "heres some more extra stuff";
     	    $envelopeMaker->add_header(undef, undef, 0, 0, $header);
     	}
     	$envelopeMaker->set_body(undef, 'myresponse', 0, $body);
         }

     1;

   In order to translate HTTP requests into calls on your Calculator class
above, you'll need to write an Apache handler. This is where you'll use
the SOAP::Transport::HTTP::Apache class:

     package ServerDemo;
     use strict;
     use SOAP::Transport::HTTP::Apache;

     sub handler {
     	my $safe_classes = {
     	    Calculator => undef,
     	};
       SOAP::Transport::HTTP::Apache->handler($safe_classes);
     }

   1;

   As you can see, this class basically does it all - parses the HTTP
headers, reads the request, and sends a response. All you have to do is
specify the names of classes that are safe to dispatch to.

   Of course, in order to tell Apache about your handler class above,
you'll need to modify httpd.conf. Here's a simple example that shows how
to set up an endpoint called "/soap" that maps to your ServerDemo handler
above:

     <Location /soap>
         SetHandler perl-script
         PerlHandler ServerDemo
     </Location>

   (I leave it up to you to make sure ServerDemo is in Perl's @INC path -
see Writing Apache Modules with Perl and C by O'Reilly for help with
mod_perl, or just man mod_perl)

DESCRIPTION
===========

   This class encapsulates the details of hooking up to mod_perl, and then
calls SOAP::Transport::HTTP::Server to do the SOAP-specific stuff. This
way the Server class can be reused with any web server configuration
(including CGI), by simply composing it with a different front-end (for
instance, SOAP::Transport::HTTP::CGI).

handler(SafeClassHash, OptionalDispatcher)
------------------------------------------

   This is the only method on the class, and you must pass a hash
reference whose keys contain the collection of classes that may be invoked
at this endpoint. If you specify class FooBar in this list, for instance,
and a client sends a SOAP request to http://yourserver/soap?class=FooBar,
then the SOAP::Transport::HTTP::Server class will eventually attempt to
load FooBar.pm, instatiate a FooBar, and call its handle_request function
(see SOAP::Transport::HTTP::Server for more detail). If you don't include
a class in this hash, SOAP/Perl won't run it. I promise.

   By the way, only the keys in this hash are important, the values are
ignored.

   Also, nothing is stopping you from messing around with the request
object yourself if you'd like to add some headers or whatever; you can
always call Apache->request() to get the request object inside your
handle_request function. Just make sure you finish what you're doing
before you return to SOAP::Transport::HTTP::Server, because at that point
the response is marshaled and sent back.

   See SOAP::Transport::HTTP::Server for a description of the
OptionalDispatcher argument.

DEPENDENCIES
============

   SOAP::Transport::HTTP::Server

AUTHOR
======

   Keith Brown

Automarshall methods for Perl SOAP
**********************************

NAME
====

   SOAP::AutoInvoke - Automarshall methods for Perl SOAP

SYNOPSIS
========

     #!/usr/bin/perl -w

     #
     #  Client example that goes with server example
     #  in SOAP::Transport::HTTP::AutoInvoke
     #
     use strict;

     package Calculator;
     use base qw( SOAP::AutoInvoke );

     package main;

     my $calc = new Calculator;

     print "sum = ", $calc->add ( 1, 2, 3 ), "\n";

DESCRIPTION
===========

   The intention of SOAP::AutoInvoke is to allow a SOAP client to use a
remote class as if it were local.  The remote package is treated as local
with a declaration like:

     package MyClass;
     use base qw( SOAP::AutoInvoke );

   The SOAP::AutoInvoke base class will "Autoload" methods called from an
instance of "MyClass", send it to the server side, and return the results
to the caller's space.

Provided Methods
----------------

new:
     * * The 'new' method may be called with option arguments to reset
     variables from the defaults.

          my $class = new MyClass (
                          _soap_host       => 'anywhere.com',
                          _soap_port       => 80,
                          _soap_endpoint   => 'soapx?class=OtherClass',
                          _soap_method_uri => 'urn:com-name-your'
                      );

     It is advisable to set the package defaults at installation time in
     the SOAP/Transport/HTTP/AutoInvoke/Client.pm (this) file.  The
     variables may also be reset after instantiation with the 'set'
     methods.

     The '_soap_' variable is relevant only to the local instantiation of
     "MyClass".  The remote instantiation will call "new" with any
     arguments you have passed to the local instantiation that did not
     begin with '_soap_':

          my $class = new MyClass (
                          _soap_host => 'anywhere.com',
                          arg1,
                          arg2,
                          @arg3,
                          arg4   => $value,
                          :
                      );

     This works so long as the data types being passed are something the
     SOAP package can serialize.  SOAP::AutoInvoke can send and receive
     simple arrays.

     To reset the name of the "new" to be called remotely:

          my $class = new MyClass (
                          :
                          _soap_new_method => 'create',
                          :
                      );

     To not call any new method remotely:

          my $class = new MyClass (
                          :
                          _soap_new_method => undef,
                          :
                      );

    *_soap_get_host*:
          returns the contents of $class->{_soap_host}.

    *_soap_set_host*:
          sets the contents of $class->{_soap_host}.

    *_soap_get_port*:
          returns the contents of $class->{_soap_port}.

    *_soap_set_port*:
          sets the contents of $class->{_soap_port}.

    *_soap_get_endpoint*:
          returns the contents of $class->{_soap_endpoint}.

    *_soap_set_endpoint*:
          sets the contents of $class->{_soap_endpoint}.

    *_soap_get_method_uri*:
          returns the contents of $class->{_soap_method_uri}.

    *_soap_set_method_uri*:
          sets the contents of $class->{_soap_method_uri}.

    *_soap_get_new_args*:
          returns the contents of $class->{_soap_new_args}.

    *_soap_set_new_args*:
          sets the contents of $class->{_soap_new_args}.

    *_soap_get_new_method*:
          returns the contents of $class->{_soap_new_method}.

    *_soap_set_new_method*:
          sets the contents of $class->{_soap_new_method}.  The default is
          "new".

DEPENDENCIES
============

   SOAP-0.28 Data::Dumper

AUTHOR
======

   Daniel Yacob, `yacob@rcn.com|mailto:yacob@rcn.com' in this node

SEE ALSO
========

   perl(1). SOAP(3). SOAP::Transport::HTTP::AutoInvoke(3).

Automarshall methods for Perl SOAP
**********************************

NAME
====

   SOAP::Transport::HTTP::AutoInvoke - Automarshall methods for Perl SOAP

SYNOPSIS
========

     package Apache::SoapServer;
     use strict;
     use SOAP::Transport::HTTP::Apache;      # must be the provided Apache.pm!
     use SOAP::Transport::HTTP::AutoInvoke;  # import "auto_invoke" dispatcher

     sub handler {
            my $safe_classes   ={
                    ClassA     => undef,          # uses default   dispatcher
                    ClassB     => undef,          # uses default   dispatcher
                    Calculator => \&auto_invoke,  # uses specified dispatcher
                    ClassC     => undef,          # uses default   dispatcher
                    ClassD     => \&myDispatcher, # uses specified dispatcher
            };
            SOAP::Transport::HTTP::Apache->handler($safe_classes);
     }

     1;

DESCRIPTION
===========

   SOAP::Transport::HTTP::AutoInvoke provides the dispatch subroutine
"auto_invoke" to handle class instantiation and method invocation that
were called with a client created with
SOAP::Transport::ActiveWorks::AutoInvoke::Client.

DEPENDENCIES
============

   SOAP-0.28 SOAP::AutoInvoke Data::Dumper

AUTHOR
======

   Daniel Yacob, `yacob@rcn.com|mailto:yacob@rcn.com' in this node

SEE ALSO
========

   perl(1). SOAP(3). SOAP::AutoInvoke(3).

Generic SOAP CGI handler
************************

NAME
====

   SOAP::Transport::HTTP::CGI - Generic SOAP CGI handler

SYNOPSIS
========

   Use this class to expose SOAP endpoints using vanilla CGI.  Here's an
example SOAP endpoint exposed using this class:

     package ServerDemo;
     use strict;
     use SOAP::Transport::HTTP::CGI;

     sub handler {
     	my $safe_classes = {
     	    Calculator => undef,
     	};
       SOAP::Transport::HTTP::CGI->handler($safe_classes);
     }

     1;

   (I leave it up to you to figure out how to get Perl scripts to run as
CGI scripts - please see your Perl docs for details)

DESCRIPTION
===========

   This class encapsulates the details of hooking up to CGI, and then
calls SOAP::Transport::HTTP::Server to do the SOAP-specific stuff. This
way the Server class can be reused with any web server configuration
(including mod_perl), by simply composing it with a different front-end
(for instance, SOAP::Transport::HTTP::Apache, for instance.

handler(SafeClassHash, OptionalDispatcher)
------------------------------------------

   This is the only method on the class, and you must pass a hash
reference whose keys contain the collection of classes that may be invoked
at this endpoint. If you specify class FooBar in this list, for instance,
and a client sends a SOAP request to http://yourserver/soap?class=FooBar,
then the SOAP::Transport::HTTP::Server class will eventually attempt to
load FooBar.pm, instatiate a FooBar, and call its handle_request function
(see SOAP::Transport::HTTP::Server for more detail). If you don't include
a class in this hash, SOAP/Perl won't run it. I promise.

   By the way, only the keys in this hash are important, the values are
ignored.

   Also, nothing is stopping you from messing around with the response
yourself if you'd like to add some headers or whatever; you can always
call print() dump more headers to STDOUT.  Just make sure you finish what
you're doing before you return to SOAP::Transport::HTTP::Server, because
at that point the response is marshaled and sent back.

   See SOAP::Transport::HTTP::Server for details on the OptionalDispatcher
parameter.

DEPENDENCIES
============

   SOAP::Transport::HTTP::Server

AUTHOR
======

   Keith Brown

Client side HTTP support for SOAP/Perl
**************************************

NAME
====

   SOAP::Transport::HTTP::Client - Client side HTTP support for SOAP/Perl

SYNOPSIS
========

     use SOAP::Transport::HTTP::Client;

DESCRIPTION
===========

   Forthcoming...

DEPENDENCIES
============

   LWP::UserAgent SOAP::Defs

AUTHOR
======

   Keith Brown

SEE ALSO
========

Server side HTTP support for SOAP/Perl
**************************************

NAME
====

   SOAP::Transport::HTTP::Server - Server side HTTP support for SOAP/Perl

SYNOPSIS
========

     use SOAP::Transport::HTTP::Server;

DESCRIPTION
===========

   This class provides all the HTTP related smarts for a SOAP server,
independent of what web server it's attached to. It exposes a single
function (that you'll never call, unless you're adapting SOAP/Perl to a
new web server environment) that provides a set of function pointers for
doing various things, like getting information about the request and
sending response headers and content.

   What *is* important to know about this class is what it expects of you
if you want to handle SOAP requests. You must implement your class such
that it can be created via new() with no arguments, and you must implement
a single function:

handle_request(HeaderArray, Body, EnvelopeMaker)
------------------------------------------------

   The first two arguments are the input, an array of header objects
(which may be empty if no headers were sent), a single Body object, and a
third object to allow you to send a response.

   See EnvelopeMaker to learn how to send a response (this is the same
class used by a client to send the request, so if you know how to do that,
you're cooking with gas).

   HeaderArray and Body are today simply hash references, but in the
future, they may be blessed object references.

   If you want to customize this call-dispatching mechanism, you may pass
a code reference for the OptionalDispatcher argument.

   The OptionalDispatcher argument allows you to override the default
dispatching behavior with your own code. This should reference a
subroutine with the following signature:

custom_dispatcher(RequestedClass, HeaderArray, Body, EnvelopeMaker)
-------------------------------------------------------------------

   sub my_dispatcher {     my ($requested_class, $headers, $body, $em) =
@_;

     # here's a simple example that converts the request
     # into a method call (it doesn't deal with headers though)
     my $method_name = $body->{soap_typename};
     require $requested_class . '.pm';
     my $retval = $requested_class->$method_name(%$body);
     $em->set_body($body->{soap_typeuri}, $method_name . 'Response',
     		  0, {return => $retval});
     }

   The above example handles each request by invoking a class-level method
on the requested class.

DEPENDENCIES
============

   SOAP::Defs SOAP::Parser SOAP::EnvelopeMaker

AUTHOR
======

   Keith Brown

SEE ALSO
========

   SOAP::Transport::HTTP::EnvelopeMaker SOAP::Transport::HTTP::Apache

Server/Client side HTTP Smart Proxy for SOAP::Lite
**************************************************

NAME
====

   SOAP::Transport::HTTPX - Server/Client side HTTP Smart Proxy for
SOAP::Lite

SYNOPSIS
========

     use SOAP::Lite +autodispatch =>
        uri      => 'urn:',
        proxy    => 'httpx://my.smart.server/soap',
        on_fault => sub { my($soap, $res) = @_;
           die ref $res ? $res->faultdetail : $soap->transport->status, "\n";
        }
     ;

     print Hello->SOAP::echo ( 'Paul' ), "\n";

DESCRIPTION
===========

   The SmartProxy package is intended for use in a multi-server setting
where one or more servers may not be directly accessible to client side
scripts.  The SmartProxy package makes request redirection and forwarding
on a per class basis easy.  Client scripts need not know which server is
appropriate for a specific request and may make all requests from a single
master server which can be relied upon to redirect clients to the server
currently fulfilling a given request.  The relieves a maintenance burden
on the client side.  The server may also redirect clients to a new class
name or fully qualified action URI (methods and arguments are assumed to
remain constant however).

DEPENDENCIES
============

     The SOAP-Lite package.

SEE ALSO
========

     See SOAP::Transport::HTTP

COPYRIGHT
=========

   Copyright (C) 2000-2001 Paul Kulchenko. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

     Daniel Yacob (yacob@rcn.com)
     Paul Kulchenko (paulclinger@yahoo.com)

Server side IO support for SOAP::Lite
*************************************

NAME
====

   SOAP::Transport::IO - Server side IO support for SOAP::Lite

SYNOPSIS
========

     use SOAP::Transport::IO;

     SOAP::Transport::IO::Server

     # you may specify as parameters for new():
     # -> new( in => 'in_file_name' [, out => 'out_file_name'] )
     # -> new( in => IN_HANDLE      [, out => OUT_HANDLE] )
     # -> new( in => *IN_HANDLE     [, out => *OUT_HANDLE] )
     # -> new( in => \*IN_HANDLE    [, out => \*OUT_HANDLE] )

     # -- OR --
     # any combinations
     # -> new( in => *STDIN, out => 'out_file_name' )
     # -> new( in => 'in_file_name', => \*OUT_HANDLE )

     # -- OR --
     # use in() and/or out() methods
     # -> in( *STDIN ) -> out( *STDOUT )

     # -- OR --
     # use default (when nothing specified):
     #      in => *STDIN, out => *STDOUT

     # don't forget, if you want to accept parameters from command line
     # \*HANDLER will be understood literally, so this syntax won't work
     # and server will complain

     -> new(@ARGV)

     # specify path to My/Examples.pm here
     -> dispatch_to('/Your/Path/To/Deployed/Modules', 'Module::Name', 'Module::method')
     -> handle
       ;

DESCRIPTION
===========

COPYRIGHT
=========

   Copyright (C) 2000-2001 Paul Kulchenko. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Paul Kulchenko (paulclinger@yahoo.com)

Client side no-transport support for SOAP::Lite
***********************************************

NAME
====

   SOAP::Transport::LOCAL - Client side no-transport support for SOAP::Lite

SYNOPSIS
========

DESCRIPTION
===========

COPYRIGHT
=========

   Copyright (C) 2000-2001 Paul Kulchenko. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Paul Kulchenko (paulclinger@yahoo.com)

Client side SMTP/sendmail support for SOAP::Lite
************************************************

NAME
====

   SOAP::Transport::MAILTO - Client side SMTP/sendmail support for
SOAP::Lite

SYNOPSIS
========

     use SOAP::Lite;

     SOAP::Lite
       -> uri('http://soaplite.com/My/Examples')
       -> proxy('mailto:destination.email@address', smtp => 'smtp.server', From => 'your.email', Subject => 'SOAP message')

     # or
     # -> proxy('mailto:destination.email@address?From=your.email&Subject=SOAP%20message', smtp => 'smtp.server')

     # or if you want to send with sendmail
     # -> proxy('mailto:destination.email@address?From=your.email&Subject=SOAP%20message')

     # or if your sendmail is in undiscoverable place
     # -> proxy('mailto:destination.email@address?From=your.email&Subject=SOAP%20message', sendmail => 'command to run your sendmail')

     -> getStateName(12)
       ;

DESCRIPTION
===========

COPYRIGHT
=========

   Copyright (C) 2000-2001 Paul Kulchenko. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Paul Kulchenko (paulclinger@yahoo.com)

Server side POP3 support for SOAP::Lite
***************************************

NAME
====

   SOAP::Transport::POP3 - Server side POP3 support for SOAP::Lite

SYNOPSIS
========

     use SOAP::Transport::POP3;

     my $server = SOAP::Transport::POP3::Server
       -> new('pop.mail.server')
       # if you want to have all in one place
       # -> new('user:password@pop.mail.server')
       # specify list of objects-by-reference here
       -> objects_by_reference(qw(My::PersistentIterator My::SessionIterator My::Chat))
       # specify path to My/Examples.pm here
       -> dispatch_to('/Your/Path/To/Deployed/Modules', 'Module::Name', 'Module::method')
     ;
     # you don't need to use next line if you specified your password in new()
     $server->login('user' => 'password') or die "Can't authenticate to SMTP server\n";

     # handle will return number of processed mails
     # you can organize loop if you want
     $server->handle while sleep 10;

DESCRIPTION
===========

COPYRIGHT
=========

   Copyright (C) 2000-2001 Paul Kulchenko. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Paul Kulchenko (paulclinger@yahoo.com)

Server/Client side TCP support for SOAP::Lite
*********************************************

NAME
====

   SOAP::Transport::TCP - Server/Client side TCP support for SOAP::Lite

SYNOPSIS
========

     use SOAP::Transport::TCP;

     my $daemon = SOAP::Transport::TCP::Server
       -> new (LocalAddr => 'localhost', LocalPort => 82, Listen => 5, Reuse => 1)
       -> objects_by_reference(qw(My::PersistentIterator My::SessionIterator My::Chat))
       -> dispatch_to('/Your/Path/To/Deployed/Modules', 'Module::Name', 'Module::method')
     ;
     print "Contact to SOAP server at ", join(':', $daemon->sockhost, $daemon->sockport), "\n";
     $daemon->handle;

DESCRIPTION
===========

COPYRIGHT
=========

   Copyright (C) 2000-2001 Paul Kulchenko. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Paul Kulchenko (paulclinger@yahoo.com)

Maps Perl types to their serializer/deserializer classes
********************************************************

NAME
====

   SOAP::TypeMapper - Maps Perl types to their serializer/deserializer
classes

SYNOPSIS
========

   This is an extensibility point built in to SOAP/Perl to allow for
future expansion, especially with regards to the eventual development of
an XML Schema-based metadata format. In the short term, you can use this
extensibility point to add support for marshaling blessed object
references.

   This is currently an experimental feature and will be documented in
more detail once we have a bit more implementation experience. Feel free
to peruse the sources and use this class if you like, and send feedback.

DESCRIPTION
===========

   Forthcoming...

AUTHOR
======

   Keith Brown

Wrapper for xsd primitives that need explicit SOAP type attributes
******************************************************************

NAME
====

   SOAP::TypedPrimitive - Wrapper for xsd primitives that need explicit
SOAP type attributes

SYNOPSIS
========

   use SOAP::TypedPrimitive;

   my $body = {     a => SOAP::TypedPrimitive->new(3, 'float'),     b =>
SOAP::TypedPrimitive->new(4, 'float'), };

DESCRIPTION
===========

   In some cases it is desirable to provide explicit types for parameters
being passed to SOAP methods. One legitimate case is when you need to
disambiguate a call to a method that is one of many with the same name
that only differ by the parameter types (i.e., an 'overloaded' method).

new(value, typeString)
----------------------

   Returns a blessed object reference that has a custom serializer that
will emit explicit xsi:type attributes. For instance, the above example
produces the following SOAP representation for 'a':

   <a xsi:type='xsd:float'>3</a>

   Note that this class only supports primitive types defined in the xsd
namespace (see XML Schema Part 2: Datatypes)

DEPENDENCIES
============

   SOAP::Defs SOAP::TypedPrimitiveSerializer

AUTHOR
======

   Keith Brown

SEE ALSO
========

   SOAP::EnvelopeMaker

serializer for xsd scalars
**************************

NAME
====

   SOAP::TypedPrimitiveSerializer - serializer for xsd scalars

DEPENDENCIES
============

   SOAP::TypedPrimitive

AUTHOR
======

   Keith Brown

SEE ALSO
========

   SOAP::TypedPrimitive

Perl extension for access to SOM and DSOM objects.
**************************************************

NAME
====

   SOM - Perl extension for access to SOM and DSOM objects.

SYNOPSIS
========

     use SOM;
     blah blah blah

DESCRIPTION
===========

Supported types
---------------

   (exported with the tag `:types'):

     tk_short
     tk_ushort
     tk_long
     tk_ulong
     tk_float
     tk_double
     tk_char
     tk_boolean
     tk_octet
     tk_enum
     tk_string
     tk_pointer		# Not yet?
     tk_void		# Output only

Supported services
------------------

     $class = Find_Class($classname, $major, $minor)

   Returns SOM Class object.  Use `$major = $minor = 0' if you do not need
a version check.

     $obj = $class->NewObject()

   Creates a new instance of an object of the given class.

     $repo = RepositoryNew()

   Returns an object for access to Repository.

     SOMClass()

   Returns the SOM (meta)class `SOMClass'.

     SOMObject()

   Returns the SOM class `SOMObject'.

     SOMClassMgr()

   Returns the SOM class `SOMClassMgr'.

     SOMClassMgrObject()

   Returns the standard `SOMClassMgrObject' object.

     $obj->Dispatch0($method_name)

   Dispatches a method with void return and no arguments (not supported,
fatal error if $method_name cannot be resolved).

     $obj->Dispatch_templ($method_name, $template, ...)

   Dispatches a method with return type and arguments described by a
$template.  See `t/animal.t' how to build a template.

     $obj->GetClass()

   Return the class of the object (as a SOM object).

Primitive classes
=================

   Some SOM methods are hardwired into the module, they operate on Perl
objects with names ending on `Ptr'.  (Other SOM methods are currently
supported with Dispatch_templ() method only.)

   Note that support of Repository classes is much more complete than for
other classes, since support on auto-import of methods is impossible
without this.

   DSOM-related primitive classes are listed in `Working with DSOM' in
this node.

SOMObjectPtr
------------

`GetClass'
     Returns the class object.

`GetClassName'
     Returns the class name.

   Additionally, two non-SOM methods are made available: Dispatch0() and
Dispatch_templ().

SOMClassPtr
-----------

`NewObject'
     Returns a new object of the given class.

ContainedPtr
------------

   All the methods take environment as an argument:

     $name = $obj->name($env)

name
     String name of the element (unique inside the immediate parent).

id
     String id of the element (unique in the repository).

`defined_in'
     String id of the immediate parent.

`within'
     Returns a list of containers with definitions of this object.

describe
     Returns information defined in the IDL specification of this object.
     *Memory management for this???*.  Return type is
     AttributeDescriptionPtr.

ContainerPtr
------------

`lookup_name'
     Returns a list of objects with the given name within a specified
     Container object, or within objects contained in the Container object.

          $obj->lookup_name($env, $name, $levels, $type, $noinherited)

     $levels should be -1 to search all the kids-containers as well,
     otherwise should be 1. $type should be one of

          AttributeDef ConstantDef ExceptionDef InterfaceDef
          ModuleDef ParameterDef OperationDef TypeDef all

     If $noinherited, any inherited objects will not be returned.

`contents'
     Returns the list of contained elements.

          $obj->contents($env, $type, $noinherited)

     Parameters have the same sense as for the `lookup_name' method.

AttributeDescriptionPtr
-----------------------

   *Should be scraped: AttributeDescriptionPtr should be substituted by
proper subclass of Contained!*

   The methods do not take environment as an argument:

     $typecode = $attr->type()

   In addition to methods name(), id(), defined_in() similar to ones in
`Contained', has two additional methods:

type
     `TypeCodePtr' object which describes the type of the attribute.

readonly
     whether the attribute is readonly.

   Currently there is no value() method.

OperationPtr
------------

   All the methods take environment as an argument:

     $name = $op->result($env)

result
     TypeCode of the return value.

ParameterPtr
------------

   All the methods take environment as an argument:

     $name = $argN->type($env)

type
     TypeCode of this argument.

mode
     One of the strings `INOUT', `OUT', IN.

TypeCode
--------

   All the methods take environment as an argument:

     $kind = $tc->kind($env)

`kind'
     Returns the type of the TypeCode.  Types are the same as `Supported
     types' in this node.

`param_count'
     Returns the number of parameters encoded in the TypeCode.

parameter
     Returns the nth parameter encoded in the TypeCode as any.  n changes
     from 0 to *param_count*` - 1'.

          $p = $tc->parameter($env, 2);

any
---

   All the methods take environment as an argument:

     $type = $any->type($env)

type
     Returns the TypeCode of the value stored in the any.

value
     Returns the value stored in the any.  Only elementary types are
     supported now.

Repository
==========

   Since Container/`Contained' are completely supported by primitive
classes, one can walk the Repository tree any way one is pleased.  We use
only the following subtree of the Repository: inside toplevel we find
`InterfaceDef' elements (which carry information about SOM classes),
inside an `InterfaceDef' we look for `OperationDef' elements (which
correspond to methods in the class), and inside an `OperationDef' we look
for `ParameterDef' elements (which correspond to arguments of a method).

BUGS
----

   We consider `ContainedContainerPtr' as being both a ContainerPtr and
ContainedPtr.  But not all of them are.  This is bad, since calling C SOM
bindings on an object of unappropriate type is not catchable.

Working with DSOM
=================

   After any call which includes $ev, one should `$ev-'Clear> to avoid
memory leaks.  Before this call $ev can be expected for error info.
Package SOM contains following *major codes* of exceptions:
SYSTEM_EXCEPTION, USER_EXCEPTION, NO_EXCEPTION (exportable with tag
`:environment').

   This API is very experimental.  Read DSOM reference to know what these
calls are doing.

Starting/stopping servers
-------------------------

   DSOM to WPS requires two servers: one is a SOMD server (a separate
process), another is WPSD server (extra thread(s) in WPS shell process).
To check existence: SOM::IsSOMDDReady(), SOM::IsWPDServerReady().

   To create: `SOM::RestartSOMDD(1)', `SOM::RestartWPDServer(1)'.

   To stop: `SOM::RestartSOMDD(0)', `SOM::RestartWPDServer(0)'.

   Keep in mind that servers are not refcounted, so it maybe not a very
good idea to shut them down even if did not run when you started (since
somebody else could have started to use them in between).

   Additionally, stopping servers when they did not completely started
could lead to problems.

   A convenience function `SOM::Ensure_Servers($shutdown_dsom,
$shutdown_wpsd)' is provided.  If the arguments are given, servers will be
shutdown at end of run if they were not running when this function was
called.  (Exportable with `:dsom')

Class `EnvironmentPtr'
----------------------

   To create:

     $ev = SOM::CreateLocalEnvironment();

   (exportable with tag `:environment').

   Methods:

     $major = $ev->major;
     $stringID = $ev->id;
     $minor = $ev->id;		# 0 if $ev->major != SYSTEM_EXCEPTION
     $state = $ev->completed;	# undef if $ev->major != SYSTEM_EXCEPTION
     				# or state is not YES or NO, otherwise 0 or 1
     $ev->Clear;			# Free() data if $ev->major == SYSTEM_EXCEPTION

   A simpleminded error reporter is made available as method Check:

     $err = $ev->Check and warn "Got exception $err";

   $err is formatted as `MAJOR=2 ID='OPSYS' MINOR=343 COMPLETED=NO'.

Package `SOM::SOMDeamon'
------------------------

   Functions:

     Init($ev);
     Uninit($ev);
     ClassMgrObject();		# Default SOMD class manager
     ObjectMgr();			# Default SOMD object manager
     WPClassManagerNew();		# One can Merge the result with ObjectMgr()

Class `SOMClassManagerPtr'
--------------------------

   Methods:

     $oldmgr->MergeInto($newmgr);

Class `ObjectMgrPtr'
--------------------

   Methods:

     $mgr->ReleaseObject($ev, $servername);

Class `SOMDObjectMgrPtr'
------------------------

   ISA `ObjectMgrPtr'.

   Methods:

     $server = $mgr->FindServerByName($ev, $servername);

Class `SOMDServerPtr'
---------------------

   Methods:

     $server->GetClassObj($ev, $classname);

Example
-------

   Initialize:

     use SOM ':class', ':dsom', ':environment';
     Ensure_Servers();
     $ev = SOM::CreateLocalEnvironment();

     sub EnvironmentPtr::CheckAndWarn {
       my $err; $err = $ev->Check and warn "Got exception $err";
     }

   Start class dispatchers:

     SOM::SOMDeamon::Init($ev);
     $ev->CheckAndWarn;
     $SOM_ClassMgr = SOM::SOMDeamon::ClassMgrObject or die;
     $WPS_ClassMgr = SOM::SOMDeamon::WPClassManagerNew or die;
     $SOM_ClassMgr->MergeInto($WPS_ClassMgr); # In fact MergeFrom

     Init_WP_Classes();	# Otherwise cannot GetClassObj('WPFolder')

     $server = SOM::SOMDeamon::ObjectMgr->FindServerByName($ev, "wpdServer")
       or die;
     $ev->CheckAndWarn;

   Get a class object of requested type:

     $classFolder = $server->GetClassObj($ev, "WPFolder") or die;
     $ev->CheckAndWarn;
     ## ... Do some work with $folderClass

   Shut down dispatchers:

     SOM::SOMDeamon::ObjectMgr->ReleaseObject($ev, $server);
     $ev->CheckAndWarn;
     SOM::SOMDeamon::Uninit($ev);
     $ev->CheckAndWarn;

EXPORT
======

   None by default.  Tags `:types', `:class'.

AUTHOR
======

   A. U. Thor, a.u.thor@a.galaxy.far.far.away

BUGS
====

   Only primitive types of parameters and return value are supported.

   Only in-parameters are supported.

   No memory management is done at all.

   Exception is not analysed.

   SOM Objects have type SOMObjectPtr, SOM Classes have type SOMClassPtr
etc.

   Methods may be dispatched only when a signature is explicitely
described.

SEE ALSO
========

   perl(1).

Simple Perl Object Persistence with Security
********************************************

NAME
====

   SPOPS - Simple Perl Object Persistence with Security

SYNOPSIS
========

     # Define an object completely in a configuration file
     my $spops = {
       myobject => {
        class => 'MySPOPS::Object',
        isa => qw( SPOPS::DBI ),
        ...
       }, ...
     };

     # Process the configuration:
     SPOPS::Configure->process_config( { config => $spops } );

     # Initialize the class
     MySPOPS::Object->class_initialize;

     # create the object
     my $object = MySPOPS::Object->new;

     # Set some parameters
     $object->{ $param1 } = $value1;
     $object->{ $param2 } = $value2;

     # Store the object in an inherited persistence mechanism
     eval { $object->save };
     if ( $@ ) {
       my $err_info = SPOPS::Error->get;
       die "Error trying to save object:\n",
           "$err_info->{user_msg}\n",
           "$err_info->{system_msg}\n";
     }

OVERVIEW
========

   SPOPS - or Simple Perl Object Persistence with Security - allows you to
easily define how an object is composed and save, retrieve or remove it
any time thereafter. It is intended for SQL databases (using the DBI), but
you should be able to adapt it to use any storage mechanism for
accomplishing these tasks.  (An early version of this used GDBM, although
it was not pretty.)

   The goals of this package are fairly simple:

   * Make it easy to define the parameters of an object

   * Make it easy to do common operations (fetch, save, remove)

   * Get rid of as much SQL (or other domain-specific language) as
     possible, but...

   * ... do not impose a huge cumbersome framework on the developer

   * Make applications easily portable from one database to another

   * Allow people to model objects to existing data without modifying the
     data

   * Include flexibility to allow extensions

   * Let people simply issue SQL statements and work with normal datasets
     if they want

   So this is a class from which you can derive several useful methods.
You can also abstract yourself from a datasource and easily create new
objects.

   The subclass is responsible for serializing the individual objects, or
making them persistent via on-disk storage, usually in some sort of
database. See "Object Oriented Perl" by Conway, Chapter 14 for much more
information.

   The individual objects or the classes should not care how the objects
are being stored, they should just know that when they call fetch() with a
unique ID that the object magically appears. Similarly, all the object
should know is that it calls save() on itself and can reappear at any
later date with the proper invocation.

Tie Interface
-------------

   This version of SPOPS supports using a `tie' in this node interface to
get and set the individual data values. You can also use the more
traditional OO get and set operators, but most people will likely find the
hashref interface easier to deal with. (It also means you can interpolate
data into strings: bonus!) Examples are given below.

   The tie interface allows the most common operations - fetch data and
put it into a data structure for later use - to be done very easily. It
also hides much of the complexity behind the object for you so that most
of the time you are dealing with a simple hashref.

Serialization
-------------

   Since the main SPOPS class from which all SPOPS objects derive has
Storable, as a parent, you can call any of its methods
from any SPOPS object and have a serialized version of your object. You can
send it over the network, save it for later - whatever you like.

   Note that this feature appeared starting version 0.39, so if you have
any issues with it please e-mail the author. There are some issues to be
worked out with configuration and the like, but it basically just works.

What do the objects look like?
------------------------------

   Here is an example getting values from CGI.pm and saving an object:

     my $q = new CGI;
     my $obj = MyUserClass->new();
     foreach my $field ( qw( f_name l_name birthdate ) ) {
       $obj->{ $field } = $q->param( $field );
     }
     my $object_id = eval { $obj->save };
     if ( $@ ) {
      ... report error information ...
     }
     else {
       warn " Object saved with ID: $obj->{object_id}\n";
     }

   You can now retrieve it later using the object_id:

     my $obj = MyUserClass->fetch( $object_id );
     print "First Name: $obj->{f_name}\n",
           "Last Name:  $obj->{l_name}\n",
           "Birthday:   $obj->{birthdate}\n";

   You can also associate objects to other objects:

     my $primary_group = $user->group;
     print "Group Name: $primary_group->{name}\n";

   And you can fetch batches of objects at once:

     my $user_list = MyUserClass->fetch_group( { where => 'l_name LIKE ?',
                                                 value => [ 'w%' ],
                                                 order => 'birthdate' } );
     foreach my $user ( @{ $user_list } ) {
       print " $user->{f_name} $user->{l_name} -- $user->{birthdate}\n";
     }

EXAMPLES
========

     # Retrieve all themes and print a description
     my $themes = eval { $theme_class->fetch_group( { order => 'title' } ) };
     if ( $@ ) { ... report error ... }
     else {
       foreach my $thm ( @{ $themes } ) {
         print "Theme: $thm->{title}\n",
               "Description: $thm->{description}\n";
       }
     }

     # Create a new user, set some values and save
     my $user = $user_class->new;
     $user->{email} = 'mymail@user.com';
     $user->{first_name} = 'My';
     $user->{last_name}  = 'User';
     my $user_id = eval { $user->save };
     if ( $@ ) {
       print "There was an error: ", $R->error->report(), "\n";
     }

     # Retrieve that same user from the database
     my $user_id = $cgi->param( 'user_id' );
     my $user = eval { $user_class->fetch( $user_id ) };
     if ( $@ ) { ... report error ... }
     else {
       print "The user's first name is: $user->{first_name}\n";
     }

     my $data = MyClass->new( { field1 => 'value1', field2 => 'value2' } );

     # Retrieve values using the hashref
     print "The value for field2 is: $data->{field2}\n";

     # Set values using the hashref
     $data->{field3} = 'value3';

     # Save the current data state
     eval { $data->save };
     if ( $@ ) { ... report error ... }

     # Remove the object permanently
     eval { $data->remove };
     if ( $@ ) { ... report error ... }

     # Call arbitrary object methods to get other objects
     my $other_obj = eval { $data->call_to_get_other_object() };
     if ( $@ ) { ... report error ... }

     # Clone the object with an overridden value and save
     my $new_data = $data->clone( { field1 => 'new value' } );
     eval { $new_data->save };
     if ( $@ ) { ... report error ... }

     # $new_data is now its own hashref of data --
     # explore the fields/values in it
     while ( my ( $k, $v ) = each %{ $new_data } ) {
       print "$k == $v\n";
     }

     # Retrieve saved data
     my $saved_data = eval { MyClass->fetch( $id ) };
     if ( $@ ) { ... report error ... }
     else {
       while ( my ( $k, $v ) = each %{ $saved_data } ) {
         print "Value for $k with ID $id is $v\n";
       }
     }

     # Retrieve lots of objects, display a value and call a
     # method on each
     my $data_list = eval { MyClass->fetch_group( where => "last_name like 'winter%'" ) };
     if ( $@ ) { ... report error ... }
     else {
       foreach my $obj ( @{ $data_list } ) {
         print "Username: $obj->{username}\n";
         $obj->increment_login();
       }
     }

DESCRIPTION
===========

   This module is meant to be overridden by a class that will implement
persistence for the SPOPS objects. This persistence can come by way of
flat text files, LDAP directories, GDBM entries, DBI database tables -
whatever. The API should remain the same.

Class Hierarchy
---------------

   SPOPS (Simple Perl Object Persistence with Security) provides a
framework to make your application objects persistent (meaning, you can
store them somewhere, e.g., in a relational database), and to control
access to them (the usual user/group access rights stuff). You will
usually just configure SPOPS by means of configuration files, and SPOPS
will create the necessary classes and objects for your application on the
fly. You can of course have your own code implement your objects -
extending the default SPOPS object behavior with your methods. However, if
SPOPS shall know about your classes and objects, you will have to tell it
- by configuring it.

   The typical class hierarchy for an SPOPS object looks like this:

     --------------------------
         |SPOPS                     |
     --------------------------
                ^
                |
     --------------------------
         |SPOPS::MyStorageTechnology|
     --------------------------
                ^
                |
     --------------------------
         |SPOPS::MyApplicationClass |
     --------------------------

   * SPOPS

     Abstract base class, provides persistency and security framework
     (fetch, save, remove)

     Example: You are reading it now!

   * SPOPS::MyStorageTechnology

     Concrete base class, provides technical implementation of framework
     for a particular storage technology (e.g., Filesystem, RDBMS, LDAP,
     ... )

     Example: SPOPS::DBI, SPOPS::GDBM, ...

   * SPOPS::MyApplicationClass

     User class, provides semantic implementation of framework
     (configuration of parent class, e.g., database connection strings,
     field mappings, ... )

     Example: MyApplication::User, MyApplication::Document, ...

SPOPS Object States
-------------------

   Basically, each SPOPS object is always in one of two states:

   * Runtime State

   * Persistency State

   In Runtime State, the object representation is based on a hash of
attributes. The object gets notified about any changes to it through the
tie(3) mechanism.

   In Persistency State, the object exists in some persistent form, that
is, it is stored in a database, or written out to a file.

   You can control what happens to the object when it gets written to its
persistent form, or when it is deleted, or fetched from its storage form,
by implementing a simple API: fetch(), save(), remove().

     -------------         save, remove         -----------------
         |Runtime State|     ------------------->   |Persistency State|
     -------------      <------------------     -----------------
                              fetch

   Around the fetch(), save(), and remove() calls, you can execute helper
functions (pre_fetch(), post_fetch(), pre_save(), post_save(),
pre_remove(), post_remove()), in case you need to prepare anything or
clean up something, according to needs of your storage technology.  These
are pushed on a queue based on a search of @ISA, and executed front to end
of the queue. If any of the calls in a given queue returns a false value,
the whole action (save, remove, fetch) is short-circuited (that is, a
failing method bombs out of the action). More information on this is in
`Data Manipulation Callbacks: Rulesets' in this node below.

API
===

   The following includes methods within SPOPS and those that need to be
defined by subclasses.

   In the discussion below, the following holds:

   * When we say *base class*, think *SPOPS*

   * When we say *subclass*, think of *SPOPS::DBI* for example

   Onward!

   Also see the `ERROR HANDLING' in this node section below on how we use
die() to indicate an error and where to get more detailed infromation.

   *new( [ \%initialize_data ] )*

   Implemented by base class.

   This method creates a new SPOPS object. If you pass it key/value pairs
the object will initialize itself with the data (see initialize() for
notes on this).

   Note that you can use the key 'id' to substitute for the actual
parameter name specifying an object ID. For instance:

     my $uid = $user->id;
     if ( eval { $user->remove } ) {
       my $new_user = MyUser->new( { id => $uid, fname = 'BillyBob' ... } );
       ...
     }

   In this case, we do not need to know the name of the ID field used by
the MyUser class.

   Returns on success: a tied hashref object with any passed data already
assigned.

   Returns on failure: undef.

   Examples:

     # Simplest form...
     my $data = MyClass->new();

     # ...with initialization
     my $data = MyClass->new( { balance => 10532,
                                account => '8917-918234' } );

   *clone( \%params )*

   Returns a new object from the data of the first. You can override the
original data with that in the \%params passed in.

   Examples:

     # Create a new user bozo
     my $bozo = $user_class->new;
     $bozo->{first_name} = 'Bozo';
     $bozo->{last_name}  = 'the Clown';
     $bozo->{login_name} = 'bozosenior';
     eval { $bozo->save };
     if ( $@ ) { ... report error .... }

     # Clone bozo; first_name is 'Bozo' and last_name is 'the Clown',
     # as in the $bozo object, but login_name is 'bozojunior'
     my $bozo_jr = $bozo->clone( { login_name => 'bozojunior' } );
     eval { $bozo_jr->save };
     if ( $@ ) { ... report error ... }

   initialize()

   Implemented by base class, although it is often overridden.

   Cycle through the parameters and set any data necessary. This allows
you to construct the object with existing data. Note that the tied hash
implementation ensures that you cannot set infomration as a parameter
unless it is in the field list for your class. For instance, passing the
information:

     firt_name => 'Chris'

   should likely not set the data, since 'firt_name' is the misspelled
version of the defined field 'first_name'.

   *fetch( $oid, [ \%params ] )*

   Implemented by subclass.

   This method should be called from either a class or another object with
a named parameter of 'id'.

   Returns on success: a SPOPS object.

   Returns on failure: undef; if the action failed (incorrect fieldname in
the object specification, database not online, database user cannot
select, etc.) a die() will be used to raise an error.

   The \%params parameter can contain a number of items - all are optional.

   Parameters:

     <datasource>
       For most SPOPS implementations, you can pass the data source (a DBI
       database handle, a GDBM tied hashref, etc.) into the routine.

     data
       You can use fetch() not just to retrieve data, but also to do the
       other checks it normally performs (security, caching, rulesets,
       etc.). If you already know the data to use, just pass it in using
       this hashref. The other checks will be done but not the actual data
       retrieval. (See the C<fetch_group> routine in L<SPOPS::DBI> for an
       example.)

     skip_security
       A true value skips security checks.

     skip_cache
       A true value skips any use of the cache.

   In addition, specific implementations may allow you to pass in other
parameters. (For example, you can pass in 'field_alter' to the
SPOPS/DBI, implementation so you can format the returned data.)

   Example:

     my $id = 90192;
     my $data = eval { MyClass->fetch( $id ) };

     # Read in a data file and retrieve all objects matching IDs
     my @object_list = ();
     while ( <DATA> ) {
       chomp;
       next if ( /\D/ );
       my $obj = eval { ObjectClass->fetch( $_ ) };
       if ( $@ ) { ... report error ... }
       else      { push @object_list, $obj  if ( $obj ) }
     }

   *save( [ \%params ] )*

   Implemented by subclass.

   This method should save the object state in whatever medium the module
works with. Note that the method may need to distinguish whether the
object has been previously saved or not - whether to do an add versus an
update. See the section `TRACKING CHANGES' in this node for how to do
this. The application should not care whether the object is new or
pre-owned.

   Returns on success: the ID of the object if applicable, otherwise a
true value;

   Returns on failure: undef, and a die() to indicate that the action
failed.

   Example:

     my $rv = eval { $obj->save };
     if ( $@ ) {
       warn "Save of ", ref $obj, " did not work properly!";
     }

   Parameters:

     <datasource>
       For most SPOPS implementations, you can pass the data source (a DBI
       database handle, a GDBM tied hashref, etc.) into the routine.

     is_add
       A true value forces this to be treated as a new record.

     skip_security
       A true value skips the security check.

     skip_cache
       A true value skips any caching.

     skip_log
       A true value skips the call to 'log_action'

   remove()

   Implemented by subclass.

   Permanently removes the object, or if called from a class removes the
object having an id matching the named parameter of 'id'.

   Returns: status code based on success (undef == failure).

   Parameters:

     <datasource>
       For most SPOPS implementations, you can pass the data source (a DBI
       database handle, a GDBM tied hashref, etc.) into the routine.

   Examples:

     # First fetch then remove
     my $obj = MyClass->fetch( $id );
     my $rv = $obj->remove();

TRACKING CHANGES
================

   The object tracks whether any changes have been made since it was
instantiated and keeps an internal toggle switch. You can query the toggle
or set it manually.

     $obj->changed();

   Returns 1 if there has been change, undef if not.

     $obj->has_change();

   Sets the toggle to true.

     $obj->clear_change();

   Sets the toggle to false.

   Example:

     if ( $obj->changed() ) {
       my $rv = $obj->save();
     }

   Note that this can (and should) be implemented within the subclass, so
you as a user can simply call:

     $obj->save();

   And not worry about whether it has been changed or not. If there has
been any modification, the system will save it, otherwise it will not.

   *Automatically Created Accessors*

   In addition to getting the data for an object through the hashref
method, you can also get to the data with accessors named after the fields.

   For example, given the fields:

     $user->{f_name}
     $user->{l_name}
     $user->{birthday}

   You can call to retrieve the data:

     $user->f_name();
     $user->l_name();
     $user->birthday();

   Note that this is only to read the data, not to change it. The system
does this using AUTOLOAD, and after the first call it automatically
creates a subroutine in the namespace of your class which handles future
calls so there is no need for AUTOLOAD on the second or future calls.

DATA ACCESS METHODS
===================

   Most of this information can be accessed through the CONFIG hashref,
but we also need to create some hooks for subclasses to override if they
wish. For instance, language-specific objects may need to be able to
modify information based on the language abbreviation.

   We have simple methods here just returning the basic CONFIG
information. The following are defined:

   * lang ( $ )

     Returns a language code (e.g., 'de' for German; 'en' for English).
     This only works if defined by your class.

   * no_cache ( bool )

     Returns a boolean based on whether this object can be cached or not.
     This does not mean that it *will* be cached, just whether the class
     allows its objects to be cached.

   * field( \% )

     Returns a hashref (which you can sort by the values if you wish) of
     fieldnames used by this class.

   * field_list( \@ )

     Returns an arrayref of fieldnames used by this class.

   * timestamp_field ( $ )

     Returns a fieldname used for the timestamp. Having a blank or
     undefined value for this is ok. But if you do define it, your UPDATEs
     will be checked to ensure that the timestamp values match up. If not,
     the system will throw an error. (Note, this is not yet implemented.)

   Subclasses can define their own where appropriate.

"GLOBALS"
=========

   These objects are tied together by just a few things:

   *global_config*

   A few items sprinkled throughout the SPOPS hierarchy need information
provided in a configuration file. See SPOPS/Configure,
for more information about what should be in it, what
form it should take and some of the nifty tricks you can do with it.

   Returns: a hashref of configuration information.

   *global_cache*

   A caching object. If you have

     {cache}->{SPOPS}->{use}

   in your configuration set to '0', then you do not need to worry about
this. Otherwise, the caching module should implement:

   The method get(), which returns the property values for a particular
object.

     $cache->get( { class => 'SPOPS-class', id => 'id' } )

   The method set(), which saves the property values for an object into
the cache.

     $cache->set( { data => $spops_object } );

   This is a fairly simple interface which leaves implementation pretty
much wide open.

   Note that subclasses may also have items that must be accessible to all
children - see SPOPS/DBI, and the `global_db_handle'
method.

DATA MANIPULATION CALLBACKS: RULESETS
=====================================

   When a SPOPS object calls fetch/save/remove, the base class takes care
of most of the details for retrieving and constructing the object.
However, sometimes you want to do something more complex or different.
Each data manipulation method allows you to define two methods to
accomplish these things. One is called before the action is taken (usually
at the very beginning of the action) and the other after the action has
been successfully completed.

   What kind of actions might you want to accomplish? Cascading deletes
(when you delete one object, delete a number of other dependent objects as
well); dependent fetches (when you fetch one object, fetch all its
component objects as well); implement a consistent data layer (such as
full-text searching) by sending all inserts and updates to a separate
module or daemon. Whatever.

   Each of these actions is a rule, and together they are rulesets. There
are some fairly simple guidelines to rules:

  1. Each rule is independent of every other rule. Why? Rules for a
     particular action may be executed in an arbitrary order. You cannot
     guarantee that the rule from one class will execute before the rule
     from a separate class.

  2. A rule should not change the data of the object on which it operates.
     Each rule should be operating on the same data. And since guideline 1
     states the rules can be executed in any order, changing data for use
     in a separate rule would create a dependency between them.

  3. If a rule fails, then the action is aborted. This is central to how
     the ruleset operates, since it allows inherited behaviors to have a
     say on whether a particular object is fetched, saved or removed.

        For example, you may want to implement a 'layer' over certain
classes of data. Perhaps you want to collect how many times users from
various groups visit a set of objects on your website. You can create a
fairly simple class that puts a rule into the ruleset of its children that
creates a log entry every time a particular object is fetch()ed. The class
could also contain methods for dealing with this information.

   This rule is entirely separate and independent from other rules, and
does not interfere with the normal operation except to add information to
a separate area of the database as the actions are happening. In this
manner, you can think of them as a trigger as implemented in a relational
database. However, triggers can (and often do) modify the data of the row
that is being manipulated, whereas a rule should not.

   *pre_fetch_action( { id => $ } )*

   Called before a fetch is done, although if an object is retrieved from
the cache this action is skipped. The only argument is the ID of the
object you are trying to fetch.

   *post_fetch_action( \% )*

   Called after a fetch has been successfully completed, including after a
positive cache hit.

   *pre_save_action( { is_add =>; bool } )*

   Called before a save has been attempted. If this is an add operation
(versus an update), we pass in a true value for the 'is_add' parameter.

   *post_save_action( { is_add => bool } )*

   Called after a save has been successfully completed. If this object was
just added to the data store, we pass in a true value for the 'is_add'
parameter.

   *pre_remove_action( \% )*

   Called before a remove has been attempted.

   *post_remove_action( \% )*

   Called after a remove has been successfully completed.

FAILED ACTIONS
==============

   If an action fails, the 'fail' method associated with that action is
triggered. This can be a notification to an administrator, or saving the
data in the filesystem after a failed save.

   *fail_fetch()*

   Called after a fetch has been unsuccessful.

   *fail_save()*

   Called after a save has been unsuccessful.

   *fail_remove()*

   Called after a remove has been unsuccessful.

CACHING
=======

   SPOPS has object caching built-in. As mentioned above, you will need to
define a *global_cache* either in your SPOPS object class one of its
parents. Typically, you will put the *stash class* in the @ISA of your
SPOPS object.

   *pre_cache_fetch()*

   Called before an item is fetched from the cache; if this is called, we
know that the object is in the cache, we just have not retrieved it yet.

   *post_cache_fetch()*

   Called after an item is successfully retrieved from the cache.

   *pre_cache_save()*

   Called before an object has been cached.

   *post_cache_save()*

   Called after an object has been cached.

   *pre_cache_remove()*

   Called before an object is removed from the cache.

   *post_cache_remove()*

   Called after an object is successfully removed from the cache.

OTHER INDIVIDUAL OBJECT METHODS
===============================

   *get( $param_name )*

   Returns the currently stored information within the object for $param.

     my $value = $obj->get( 'username' );
     print "Username is $value";

   It might be easier to use the hashref interface to the same data, since
you can inline it in a string:

     print "Username is $obj->{username}";

   You may also use a shortcut of the parameter name as a method call for
the first instance:

     my $value = $obj->username();
     print "Username is $value";

   *set( $param_name, $value )*

   Sets the value of $param to $value. If value is empty, $param is set to
undef.

     $obj->set( 'username', 'ding-dong' );

   Again, you can also use the hashref interface to do the same thing:

     $obj->{username} = 'ding-dong';

   Note that unlike get, You *cannot* use the shortcut of using the
parameter name as a method. So a call like:

     my $username = $obj->username( 'new_username' );

   Will silently ignore any parameters that are passed and simply return
the information as get() would.

   id()

   Returns the ID for this object. Checks in its config variable for the
ID field and looks at the data there.  If nothing is currently stored, you
will get nothing back.

   Note that we also create a subroutine in the namespace of the calling
class so that future calls take place more quickly.

   *changed()*

   Retuns the current status of the data in this object, whether it has
been changed or not.

   *has_change()*

   Sets the *changed* flag of this object to true.

   *clear_change()*

   Sets the *changed* flag of this object to false.

   *is_checking_fields()*

   Returns 1 if this object (and class) check to ensure that you use only
the right fieldnames for an object, 0 if not.

   *timestamp()*

   Returns the value of the timestamp_field for this object, undef if the
timestamp_field is not defined.

   *timestamp_compare( $ts_check )*

   Returns true if $ts_check matches what is in the object, false
otherwise.

   *object_description()*

   Returns a hashref with three keys of information about a particular
object:

     url
       URL that will display this object

     name
       Name of this general class of object (e.g., 'News')

     title
       Title of this particular object (e.g., 'Man bites dog, film at 11')

ERROR HANDLING
==============

   (See SPOPS/Error, for now - more later!)

NOTES
=====

   There is an issue using these modules with Apache::StatINC along with
the startup methodology that calls the *class_initialize* method of each
class when a httpd child is first initialized. If you modify a module
without stopping the webserver, the configuration variable in the class
will not be initialized and you will inevitably get errors.

   We might be able to get around this by having most of the configuration
information as static class lexicals. But anything that depends on any
information from the CONFIG variable in request (which is generally passed
into the *class_initialize* call for each SPOPS implementation) will get
hosed.

TO DO
=====

   *Allow call to pass information to rulesets*

   Modify all calls to `pre_fetch_action' (etc.) to take a hashref of
information that can be used by the ruleset. For instance, if I do not
want an object indexed by the full-text ruleset (even though the class
uses it), I could do:

     eval { $obj->save( { full_text_skip => 1 } ) };

   *Objects composed of many records*

   An idea: Make this data item framework much like the one Brian Jepson
discusses in Web Techniques:

     http://www.webtechniques.com/archives/2000/03/jepson/

   At least in terms of making each object unique (having an OID).  Each
object could then be simply a collection of table name plus ID name in the
object table:

     CREATE TABLE objects (
       oid        int not null,
       table_name varchar(30) not null,
       id         int not null,
       primary key( oid, table_name, id )
     )

   Then when you did:

     my $oid  = 56712;
     my $user = User->fetch( $oid );

   It would first get the object composition information:

     oid    table        id
     ===    =====        ==
     56712  user         1625
     56712  user_prefs   8172
     56712  user_history 9102

   And create the User object with information from all three tables.

   Something to think about, anyway.

BUGS
====

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

MORE INFORMATION
================

   Find out more about SPOPS - current versions, updates, rants, ideas -
at:

     http://www.openinteract.org/SPOPS/

   CVS access and mailing lists (currently supported by the
openinteract-dev list) are at:

   http://sourceforge.net/projects/openinteract/

AUTHORS
=======

   Chris Winters <chris@cwinters.com>

   Christian Lemburg <clemburg@online-club.de> contributed some
documentation and far too many good ideas to implement.

   Rusty Foster <rusty@kuro5hin.org> was also influential in the early
days of this library.

   The following people have offered patches to SPOPS:

   * Rick Myers <rik@sumthin.nu>

read in configuration information for collections and create/configure
**********************************************************************

NAME
====

   SPOPS::Configure - read in configuration information for collections
and create/configure

SYNOPSIS
========

     use Ad::This;
     use Ad::That;

     use SPOPS::Configure;

     my $classes = [];
     $classes = SPOPS::Configure->parse_config( $conf );

DESCRIPTION
===========

   This class only has one method: parse_config. It takes a hashref of
collection information and configures existing classes with any
information necessary (including the @ISA for each) and also whips up
collection classes on the fly based on the data found in the hashref
passed in.

   Note that this class is *not required* to use SPOPS. You can happily
just define the configuration information right in your class and never
have a need to

METHODS
=======

   *process_config( \%params )*

   Parameters:

     config (\%)
       A hashref of configuration information for one or more SPOPS
       objects. The key is the SPOPS object alias, the value is a hashref
       of configuration information corresponding to that alias.

     In the absence of an 'alias_list', each of the SPOPS objects
     specified in the configuration will be processed.

     alias_list (\@) (optional)
       List of aliases to process from the 'config'. Use this if for some
       reason you do not want to process all the aliases.

     meta (\%) (optional)
       Can also be in the 'config' hashref -- see information under
       'parse_config()' below.

   *create_spops_class( \%config, \%spops_config )*

   Takes configuration information for a single SPOPS class, creates it
on-the-fly and reads in any external code when specified.

   Note that you can pass a true value for the key 'require_isa' in the
\%config parameter. The routine will then try to 'require' every class in
the 'isa' field of your SPOPS class configuration.

   Returns: the class name if successful.

   *parse_config( \%config, \%spops_config )*

   Takes a hashref of configuration information and returns the classes
created/configured properly.

   One of the keys in the configuration is special. You can pass it in
directly as a parameter (using the 'meta' key) or put it in the
configuration (using the '_meta' key). If you do neither, the system will
use a default (currently consisting of parsing the fields 'field',
'no_insert', 'no_update' and 'skip_undef' from an arrayref into a hashref.)

   This 'meta' information allows you to manipulate the information in the
configuration. Generally this is only for easier input: who wants to type
out an entire hashref when all you want is to list some fields that get
used later as lookups?

   The 'meta' information is a hashref. Currently the only supported key
is 'parse_into_hash', which takes a listref and makes it into a hashref to
facilitate individual lookups. (No 'grep in a void context' for us!)

   So we read in the \%spops_config information, massage it if necessary
and assign the information to the SPOPS class configuration. After this
class is run you should be able to call:

     my \%class_config = $object_class->CONFIG;

   And get back a hashref of configuration information for the class.

   Returns: the class name if successful.

   *create_relationship*

   Currently this creates the 'has_a' relationship and installs the
ruleset information in each class that asks for it.

   See the writeup below under `Relationship Fields' in this node.

   Returns: the class name if successful.

   *_read_code_class*

   Used internally to emulate some of what 'require' does to find a file
with code and then reads the subroutines into another package.

   Returns: arrayref of filenames that whose subroutines were read into
the SPOPS object class.

CONFIGURATION FIELDS EXPLAINED
==============================

   The configuration for a SPOPS class can be elaborate or minimal,
depending on your needs.

Required Fields
---------------

   class ($)

   Name the class you want to create.

   field (\@) (parsed into \%)

   List the properties of the object. If you try to assign to a property
that is not in the list, see SPOPS/Tie, will warn you and the
assignment will be discarded. For instance:

     # configuration
     class => 'My::HipHop',
     field => [ qw/ hip hop hooray / ],
     ...

     # code
     my $obj = My::HipHop->new;
     $obj->{'boo-yah'} = "and he said";

   will result in a warning.

   isa (\@)

   List the classes that your class inherits from. This can be a
combination of SPOPS and other classes - for instance, you might use
SPOPS/DBI, for serialization functinality but another class
(`My::FullTextIndex') to implement a ruleset for full-text indexing. (See
SPOPS, for more information on rulesets.)

   *id_field* ($)

   Name the field that will be used to uniquely identify an object. The
type of field does not matter, but the fact that each value is unique
does. You also cannot use an empty string (or undef, or 'NULL') as an
identifier.

   SPOPS does not currently deal with objects that use multiple fields to
identify a record. (In database parlance, this is a "multiple field
primary key".) To get around the restriction, you can simply add another
field to the record and use it as a primary key. Instead of using the
'fetch' method to retrieve records, you can create a simple
'fetch_by_blah' that takes two fields instead of one. (Note: on the TO DO
list for SPOPS is the ability to create a 'fetch_by_blah' method
on-the-fly from configuration information.

Optional Fields
---------------

   *code_class* ($ or \@)

   Note: This is not optional if you wish to draw code from a class
separate from the one you are creating.

   When this class finds a 'code_class' value, it tries to find the class
somewhere in @ISA. If it can find the class, it reads the file in and puts
the subroutines into the class you are creating. For instance:

     ...
     class      => 'My::Tofu',
     code_class => 'Food::Tofu',
     ...

   Will read the routines from 'Food::Tofu' and put them into the
'My::Tofu' namespace. (It will also currently put any lexical variables
from the code class into your class, so be careful.)

   You can also bring in routines from multiple files:

     ...
     class      => 'My::Tofu',
     code_class => [ 'Food::Tofu', 'Food::Soybean', 'Food::Vegan' ],
     ...

   However, you should be careful with this. Possibilities abound for
different classes defining the same subroutine and similar actions which
are quite difficult to debug.

   *no_security* ($)

   Set this to a true value if you do not want this class to use security.
This overrides all other values - even if you have SPOPS/Secure,
in the 'isa' of your class, security will not be checked if
this value is true. Be careful!

   *no_insert* (\@) (parsed into (\%)

   Specify fields that should not be included when we first create a
record.

   *no_update* (\@) (parsed into (\%)

   Specify fields whose values should never be changed when we update a
record.

   skip_undef (\@) (parsed into (\%)

   Specify fields that are not included on either a create or update if
they are not defined. (Note that 'undef' is a bit of a misnomer - we do a
simple perl 'truth' test to see if the field exists or not.)

   alias (\@)

   What other aliases do you want this class to be known under? SPOPS does
not currently do anything with this, but implementations can.

   display (\%)

   How should this object be displayed? Currently, the hashref it points
to must have at least one key 'url', to which SPOPS appends a query string
to identify this object.

   The query string it appends is very simple, something like:

     url . ? . $class->CONFIG->{id_field} . = . $object->id()

   name (\&)

   How can we find the name of an individual object? For instance, in a
contact database, the name of a person object is the full name of the
person.

   Here we expect either a code reference or a scalar. Most often you will
use a scalar, which just names the field within an object to use, such as:

     name => 'title'

   The code reference can do anything complicated you like, but more often
than not it is just something like:

     name => sub { return join( ', ', $_[0]->{field1}, $_[0]->{field2} ) }

   *object_name* ($)

   What is the generic name for an object? For instance, 'Document',
'Link', 'Page', 'Food'.

   *as_string_order* (\@) *as_string_label* (\%)

   Every SPOPS object has a method 'as_string' as defined in SPOPS.
However, this is a very blunt instrument as it basically just
dumps out the properties of the object into a string without any nice
labelling or control over order. The 'as_string_order' field allows you to
list the fields you want included in the 'as_string' output along with
their order, and 'as_string_label' allows you to assign a label to these
fields.

   *creation_security* (\%) (used by SPOPS::Secure)

   See SPOPS/Secure, for more information how this is
used.

   *base_table* ($) (used by SPOPS::DBI)

   Table name for data to be stored.

   *sql_defaults* (\@) (used by SPOPS::DBI)

   List of fields that have defaults defined in the SQL table. For
instance:

     active   CHAR(3) NOT NULL DEFAULT 'yes',

   After SPOPS/DBI, fetches a record, it then checks to
see if there are any defaults for the record and if so it refetches the
object to ensure that the data in the object and the data in the database
are synced.

   *field_alter* (\%) (used by SPOPS::DBI)

   Allows you to define different formatting behaviors for retrieving
fields. For instance, if you want dates formatted in a certain manner in
MySQL, you can do something like:

     field_alter => { posted_on => q/DATE_FORMAT( posted_on, '%M %e, %Y (%h:%i %p)' )/ }

   Which instead of the default time format:

     2000-09-26 10:29:00

   will return something like:

     September 26, 2000 (10:29 AM)

   These are typically database-specific.

Relationship Fields
-------------------

   *has_a* (\%)

   Define a one-to-one relationship from one object to another. Currently,
this means that an object has one or more fields that contain the ID value
of another object. The 'has_a' field of a configuration tells this class
what these relationships are, and this class automatically builds the
subroutines to make this happen.

   Here is a simple example that many people are familiar with in which a
user can belong to a single group.

     my $spops = {
       user => {
         field    => [ 'user_id', 'group_id', 'email' ],
         id_field => 'user_id',
         class    => 'My::User',
         has_a    => { 'My::Group' => [ 'group_id' ] },
         ...
       },
       group => {
         field    => [ 'group_id', 'name' ],
         id_field => 'group_id',
         class    => 'My::Group',
         ...
       },

     };

   Here are the steps this class goes through to create a subroutine you
can call from one object to retrieve its associated object. (Using the
above example, to retrieve a `My::Group' object given a `My::User' object.)

  1. Find the SPOPS configuration information matching the SPOPS class
     given as the key. ('My::Group' under {user}->{has_a} in the example
     above.) We will call this the SPOPS-Has below.

  2. Compare the 'id_field' in the SPOPS-Has information ('group_id' under
     {group}->{id_field} in the example) to the field given as the key in
     the original link ('group_id' under {user}->{has_a}->{'My::Group'} in
     the example).

  3. If the 'id_field' and the linking field are the same, create a
     subroutine of the same name as the SPOPS-Has tag. This is true in the
     above example, so we can do:

          # Retrieve a My::User object
          my $user = My::User->fetch( 13 );

          # Retrieve the My::Group object related to this My::User object
          my $group = $user->group();

     since the field specified in the user 'has_a' clause matches the
     id_field specified in the class it is linking to.

  4. If the 'id_field' and the linking field are not the same we either
     create a subroutine automatically or allow the configuration to
     specify one for us. We will deal with both possibilities below.

     First, the automatic creation. For this example, replace the above
     definition for 'user' with:

          user => {
            field    => [ 'user_id', 'group_id', 'subgroup_id', 'email' ],
            id_field => 'user_id',
            class    => 'My::User',
            has_a    => { 'My::Group' => [ 'group_id', 'subgroup_id' ] },
            ...
          },

     Now we have two relationships: the user belongs to both a group and a
     subgroup. Both the group and subgroup are instances of the same class,
     so we cannot refer to both of them using the 'group' alias as we did
     in the previous example.

     Once the above configuration is processed, we can do:

          # Retrieve a My::User object
          my $user = My::User->fetch( 13 );

          # Retrieve the My::Group object related to this My::User object by
          # the 'group_id' field
          my $group = $user->group();

          # Retrieve the My::Group object related to this My::User object by
          # the 'subgroup_id' field
          my $subgroup = $user->subgroup_id_group();

     So we create a subroutine with the name:

          my $subroutine_name = join( '_', $id_field, $link_alias );

     In this case, $id_field is 'subgroup_id' and $alias is 'group'.

     You can sometimes use this to your advantage but it makes for some
     awkward naming schemes. However, you can use another means of naming.
     The custom means allows you to do something like this:

          user => {
            field    => [ 'user_id', 'group_id', 'subgroup_id', 'email' ],
            id_field => 'user_id',
            class    => 'My::User',
            has_a    => { 'My::Group' => [ 'group_id',
                                           { subgroup_id => 'subgroup' } ] },
            ...
          },

     Now you can do the following:

          # Retrieve a My::User object
          my $user = My::User->fetch( 13 );

          # Retrieve the My::Group object related to this My::User object by
          # the 'group_id' field
          my $group = $user->group();

          # Retrieve the My::Group object related to this My::User object by
          # the 'subgroup_id' field
          my $subgroup = $user->subgroup();

     Here, instead of relying on SPOPS to name the subroutine for us that
     maps to the $id_field 'subgroup_id', we named it ouselves. The only
     warning here is to ensure that you do not create a subroutine of the
     same name in a 'code_class', otherwise the 'code_class' routine will
     get overwritten.

     *fetch_by* (\@)

     Create a 'fetch_by_{fieldname}' routine that simply returns an
     arrayref of objects that match the value of a particular field.

     Example:

          my $spops = {
            user => {
              field    => [ 'user_id', 'group_id', 'subgroup_id', 'email' ],
              id_field => 'user_id',
              class    => 'My::User',
              fetch_by => [ 'email' ],
              ...
            },
          };

     Allows us to do:

          my $user_list = My::User->fetch_by_email( 'allyour@base.ours.com' );
          foreach my $user ( @{ $user_list } ) {
            send_email( $user->{email}, "This is an invalid address" );
          }

     *links_to* (\@)

     (See SPOPS/Configure/DBI, for information.)

TO DO
=====

   *Creating a file of code*

   Instead of always reading the code into memory we might want to create
a file with the new package if it is not found the first time or if it is
modified in the process here. This would allow offline tools to modify a
SPOPS configuration and generate a class with subroutines from more than
one class...

   *Make 'code_class' more flexible*

   Instead of making 'code_class' read in just packages, maybe we want to
have a file of just subroutines that gets included to the class.

BUGS
====

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters  <chris@cwinters.com>

Define additional configuration methods
***************************************

NAME
====

   SPOPS::Configure::DBI - Define additional configuration methods

SYNOPSIS
========

     my $init_classes = SPOPS::Configure::DBI->parse_config( { config => $CONFIG->{SPOPS} } );

DESCRIPTION
===========

   We override the method *additional_work()* from SPOPS/Configure,
so we can create subroutines in the classes that want to
*link_to* other objects, among other things.

   It is possible - and perhaps desirable for the sake of clarity - to
create a method within *SPOPS::DBI* that does all the work for us, then we
would only need to create a subroutine that calls that subroutine.

   However, creating routines with the values embedded directly in them
should be quicker and more efficient. So we will try it this way.

METHODS
=======

   *create_relationship( $spops_config )*

   Get the config and plow through the SPOPS classes, seeing if any of
them have the *links_to* key defined. If so, we create three subroutines
with the proper info.

   The first is named '${links_to}' and simply returns an arrayref of
objects that the main object links to. For instance:

   Example:

     # $links_to = 'group'
     # Retrieve all groups that this user is a member of
     my $group_list = eval { $user->group };

   The second is named '${links_to}_add' and links the object to any
number of other objects. The return value is the number of successful
links.

   The third is named '${links_to}_remove' and removes links from the
object to any number of other objects. The return value is the number of
successful removals.

   Examples:

     # $links_to = 'group'
     # First retrieve all groups
     my $group_list = eval { $user->group };
     print "Group list: ", join( ' // ', map { $_->{group_id} } @{ $group_list } );
     >> 2 // 3 // 5

     # Now add some more, making the user a member of these new groups
     my $added = eval { $user->group_add( [ 7, 9, 21, 23 ] ) };
     print "Group list: ", join( ' // ', map { $_->{group_id} } @{ $group_list } );
     >> 2 // 3 // 5 // 7 // 9 // 21 // 23

     # Now remove two of them
     my $removed = eval { $user->group_remove( [ 2, 21 ] ) };
     print "Group list: ", join( ' // ', map { $_->{group_id} } @{ $group_list } );
     >> 3 // 5 // 7 // 9 // 23

CONFIGURATION FIELDS EXPLAINED
==============================

   *links_to* (\%)

   The 'links_to' field allows you to specify a SPOPS alias and specify
which table is used to link the objects:

     {
        'SPOPS-tag' => 'table_name',
     }

   Note that this relationship assumes a link table that joins two
separate tables. When you sever a link between two objects, you are only
deleting the link rather than deleting an object. See `TO DO' in this node
for another proposal.

   We are also considering making 'SPOPS-tag' into 'SPOPS-class' to make
this more versatile. See SPOPS/Configure, for more
info.

TO DO
=====

   *Make 'links_to' more flexible*

   We need to account for different types of linking; this may require an
additional field beyond 'links_to' that has a similar effect but works
differently.

   For instance, Table-B might have a 'has_a' relationship with Table-A,
but Table-A might have a 'links_to' relationship with Table-B. (Themes in
OpenInteract work like this.) We need to be able to specify that when
Table-A severs its relationship with one or more objects from Table-B, the
actual object is removed rather than just a link between them.

BUGS
====

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters  <chris@cwinters.com>

Install variables, subroutines and process inherited rulesets per class
***********************************************************************

NAME
====

   SPOPS::Configure::Ruleset - Install variables, subroutines and process
inherited rulesets per class

SYNOPSIS
========

     # Note that this is almost (entirely?) exclusively done
     # from SPOPS::Configure

     SPOPS::Configure::Ruleset->create_relationship( $spops_config );

DESCRIPTION
===========

   This class only has one method: create_relationship. It is almost
always called from the SPOPS/Configure, class after
doing intitial processing of classes. The method takes configuration
information for a SPOPS class.

   For this class, we install a package variable \%RULESET and a method
RULESET which returns that hashref. The variable \%RULESET holds all of
the applicable rules for that particular class, and after creating the
variable and subroutine we find all of the rules inherited by the class
and install them in the class. This is a performance win, since we do not
need to dynamically search them out everytime the rules for a particular
action need to be executed.

   See SPOPS, for more information about what a ruleset is
and how it is executed.

METHODS
=======

   *create_relationship( \%spops_config )*

   Install the package variable \%RULESET and the method RULESET to access
it. Also find all the rules that apply to a particular class (inherited
from parents) and install to the class.

TO DO
=====

BUGS
====

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters  <chris@cwinters.com>

Implement SPOPS class, serializing into a DBI database
******************************************************

NAME
====

   SPOPS::DBI - Implement SPOPS class, serializing into a DBI database

SYNOPSIS
========

     use SPOPS::DBI;
     @ISA = qw( SPOPS::DBI );
     ...

DESCRIPTION
===========

   This SPOPS class is not meant to be used directly.  Instead, you
inherit certain methods from it while implementing your own. Your module
should implement:

   * (optional) Methods to sort member objects or perform operations on
     groups of them at once.

   * (optional) Methods to relate an object of this class to objects of
     other classes - for instance, to find all users within a group.

   * (optional) The initialization method (*_class_initialize()*), which
     should create a config() object stored in the package variable and
     initialize it with configuration information relevant to the class.

   * (optional) Methods to accomplish actions before/after many of the
     actions implemented here: fetch/save/remove.

   * (optional) Methods to accomplish actions before/after saving or
     removing an object from the cache.

   Of course, these methods can also do anything else you like. :)

   As you can see, all the methods are optional. Along with
SPOPS/Configure, and SPOPS/Configure/DBI,
you can create an entirely virtual class consisting
only of configuration information. So you can actually create the
implementation for a new object in two steps:

  1. Create the configuration file (or add to the existing one)

  2. Create the database table the class depends on.

        Complete!

DATA ACCESS METHODS
===================

   The following methods access configuration information about the class
but are specific to the DBI subclass.

   * base_table ($): Just the table name, no owners or db names prepended.

   * table_name ($): Fully-qualified table name

   * field (\%): Hashref of fields/properties (field is key, value is true)

   * field_list (\@): Arrayref of fields/propreties

   * no_insert (\%): Hashref of fields not to insert (field is key, value
     is true)

   * no_update (\%): Hashref of fields not to update (field is key, value
     is true)

   * skip_undef (\%): Hashref of fields to skip update/insert if they are
     undefined (field is key, value is true)

   * field_alter (\%): Hashref of data-formatting instructions (field is
     key, instruction is value)

OBJECT METHODS
==============

   *id_clause( [ $id, [ $opt, \%params ] )*

   Returns a snippet of SQL suitable for identifying this object in the
database.

   This can be called either from the class or from a particular object.
If called from a class, the $id value must be passed in. Examples:

     my $id = 35;
     my $sql = qq/
       DELETE FROM $table
        WHERE @{[ $class->id_clause( $id ) ]}
     /;
     print "SQL: $sql";

     >> SQL:
          DELETE FROM this_table
           WHERE this_table.this_id = 35

     $class->db_select( ... where => $class->id_clause( 15 ), ... )

   If the system cannot determine the data type of the id field, it makes
a best guess based on the package variable GUESS_ID_FIELD_TYPE. It
defaults to SQL_INTEGER (as set by DBI), but you can set it dynamically as
well:

     $SPOPS::DBI::GUESS_ID_FIELD_TYPE = SQL_VARCHAR;

   Note that the default behavior is to create a fully-qualified ID field.
If you do not wish to do this (for instance, if you need to use the ID
field for a lookup into a link table), just pass 'noqualify' as the second
argument. To use the example from above:

     my $id = 35;
     my $sql = qq/
       DELETE FROM $table
        WHERE @{[ $class->id_clause( $id, 'noqualify' ) ]}
     /;
     print "SQL: $sql";

     >> SQL:
          DELETE FROM this_table
           WHERE this_id = 35

   *fetch( $id, \%params )*

   Fetches the information for an object of type class from the data
store, creates an object with the data and returns the object. Any
failures trigger a die with pertinent information as described in `ERROR
HANDLING' in this node.

   If you have security turned on for the object class, the system will
first check if the currently-configured user is allowed to fetch the
object. If the user has less that SEC_LEVEL_READ access, the fetch is
denied and a die() triggered.

   Note that if the fetch is successful we store the access level of this
object within the object itself. Check the temporary property
{tmp_security_level} of any object and you will find it.

   Parameters:

     field_alter - (\%) fields are keys, values are database-dependent
      formatting strings. You can accomplish different types of
      date-formatting or other manipulation tricks.

   You can also pass a DEBUG value to get debugging information for that
particular statement dumped into the error log:

     my $obj = eval { $class->fetch( $id, { DEBUG => 1 } ); };

   *fetch_group( \%params )*

   Returns an arrayref of objects that meet the criteria you specify.

   Parameters:

     where - a WHERE clause; leave this blank and you will get all entries

     order - an ORDER BY clause; leave this blank and the order is
      arbitrary

     other parameters get passed onto the fetch() statement when the
     records are being retrieved.

   This is actually fairly powerful. Examples:

     # Get all the user objects and put them in a hash
     # indexed by the id
     my %uid = map { $_->id => $_ } @{ $R->user->fetch_group( { order => 'last_name' } ) };

     # Get only those user objects for people who have
     # logged in today
     my $users = $R->user->fetch_group( {
                   where => 'datediff( dd, last_login, get_date() ) = 0',
                   order => 'last_name'
                 } );
     foreach my $user ( @{ $users } ) {
       print "User: $user->{login_name} logged in today.\n";
     }

   Note that you can also return objects that match the results of a join
query:

     my $list = eval { $class->fetch_group( { order => 'item.this, item.that',
                                              from => [ 'item', 'modifier' ],
                                              where => 'modifier.property = ? AND ' .
                                                       'item.item_id = modifier.item_id',
                                              value => [ 'property value' ], } ); };

   *save( [ \%params ] )*

   Object method that saves this object to the data store.  Returns the
new ID of the object if it is an add; returns the object ID if it is an
update. As with other methods, any failures trigger a die().

   Example:

     my $obj = $class->new;
     $obj->{param1} = $value1;
     $obj->{param2} = $value2;
     my $new_id = eval { $obj->save };
     if ( $@ ) {
       print "Error inserting object: $@->{error}\n";
     }
     else {
       print "New object created with ID: $new_id\n";
     }

   The object can generally tell whether it should be created in the data
store or whether it should update the data store values. Currently it
determines this by the presence of an ID value. If an ID value exists,
this is probably an update; if it does not exist, it is probably a save.

   You can give SPOPS hints otherwise. If you are controlling ID values
yourself and an ID value exists in your object, you can do:

     $obj->save({ is_add => 1 });

   to tell SPOPS to treat the request as a creation rather than an update.

   One other thing to note if you are using SPOPS/Secure,
for security: SPOPS assumes that your application determines
whether a user can create an object. That is, all requests to create an
object are automatically approved. Once the object is created, the initial
security logic kicks in and any further actions (fetch/save/remove) are
controlled by `SPOPS::Secure'.

   Note that if your database schema includes something like:

     CREATE TABLE my_table (
      my_id      int,
      created_on datetime default today(),
      table_legs tinyint default 4
     )

   and your object had the following values:

     my_id      => 10,
     created_on => undef,
     table_legs => undef

   The only thing your object would reflect after inserting is the ID,
since the other values are filled in by the database. The save() method
tries to take this into account and syncs the object up with what is in
the database once the record has been successfully inserted. If you want
to skip this step, either pass a positive value for the 'no_sync' key or
set 'no_save_sync' to a positive value in the CONFIG of the implementing
class.

   *remove( [ \%params ] )*

   Note that you can only remove a saved object (duh). Also tries to
remove the object from the cache. The object will not actually be
destroyed until it goes out of scope, so do not count on its DESTROY
method being called exactly when this happens.

   Returns 1 on success, die() with hashref on failure. Example:

     eval { $obj->remove };
     if ( $@ ) {
       print "Object not removed. Error: $@->{error}";
     }
     else {
       print "Object removed properly.";
     }

   *log_action( $action, $id )*

   Implemented by subclass.

   This method is passed the action performed upon an object ('create',
'update', 'remove') and the ID. SPOPS::DBI comes with an empty method, but
you can subclass it and do what you wish

ERROR HANDLING
==============

   Like all SPOPS classes, any errors encountered will be tossed up to the
application using a die() and a simple string as a message. We also set
more detailed information in a number of SPOPS/Error,
package variables; see that module for more details.

TO DO
=====

BUGS
====

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters  <chris@cwinters.com>

   The following people added to this module with patches and/or advice:

   * Christian Lemburg <clemburg@aixonix.de>

Retrieves ID field information from a pool
******************************************

NAME
====

   SPOPS::DBI::Keypool - Retrieves ID field information from a pool

SYNOPSIS
========

     package MySPOPS;

     @MySPOPS::ISA = qw( SPOPS::DBI::Keypool SPOPS::DBI );

DESCRIPTION
===========

   This module retrieves a value from a pool of key values matched up to
tables. It is not as fast as IDENTITY fields, auto_incrementing values or
sequences, but it is portable among databases and, most importantly, works
in a replicated environment. It also has the benefit of being fairly simple
to understand.

   Currently, the key fetching procedure is implemented via a stored
procedure for portability among tools in different languages, but it does
not have to remain this way. It is perfectly feasible to program the
entire procedure in perl.

BUGS
====

   *Put this class before others in ISA*

   Not really a bug, but you must put this class before any
database-specific ones in your @ISA, otherwise you will not see the
results of this class and likely get very confused.

TO DO
=====

   *Make option for perl implementation*

   Allow authors to use a perl implementation of a key pool rather than
relying on a stored procedure (particularly for those databases without
stored procedures...).

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters  <chris@cwinters.com>

MySQL-specific code for DBI collections
***************************************

NAME
====

   SPOPS::DBI::MySQL - MySQL-specific code for DBI collections

SYNOPSIS
========

     package MySPOPS;

     @MySPOPS::ISA = qw( SPOPS::DBI::MySQL SPOPS::DBI );

DESCRIPTION
===========

   This just implements some MySQL-specific routines so we can abstract
them out.

   One of these items is to return the just-inserted ID. Only works for
tables that have at least one auto-increment field:

     CREATE TABLE my_table (
       id  int not null auto_increment,
       ...
     )

BUGS
====

TO DO
=====

SEE ALSO
========

   See DBD/mysql, `DBI' in this node

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters  <chris@cwinters.com>

Creates a random code for the ID field
**************************************

NAME
====

   SPOPS::DBI::RandomCode - Creates a random code for the ID field

SYNOPSIS
========

     package MySPOPS;

     @MySPOPS::ISA = qw( SPOPS::DBI::RandomCode SPOPS::DBI );

DESCRIPTION
===========

   Very, very simple. We just use the *generate_random_code()* method in
all SPOPS  classes to generate an n character code. The width of the code
is determined by the field {id_width} in the CONFIG of the SPOPS
implementation.

BUGS
====

   *Getting a 'random' value*

   If you are using this under mod_perl, you might have the problem of
colliding ID fields. This seems to happen because the httpd children all
have the same random seed, since they are all forked off from the same
parent.

   The solution is to put a 'srand()' in the PerlChildInitHandler,
although mod_perl versions from 1.25 on might take care of this for you.

TO DO
=====

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters  <chris@cwinters.com>

Sybase-specific routines for the SPOPS::DBI
*******************************************

NAME
====

   SPOPS::DBI::Sybase - Sybase-specific routines for the SPOPS::DBI

SYNOPSIS
========

     # In your configuration:

     'myspops' => {
         'isa' => [ qw/ SPOPS::DBI::Sybase SPOPS::DBI / ],

     # If you have an IDENTITY field, set syb_identity to true
     'syb_identity' => 1,
     ...
      },

DESCRIPTION
===========

   This just implements some Sybase-specific routines so we can abstract
them out.

   One of them optionally returns the IDENTITY value returned by the last
insert. Of course, this only works if you have an IDENTITY field in your
table:

     CREATE TABLE my_table (
       id  numeric( 8, 0 ) IDENTITY not null,
       ...
     )

   NOTE: You also need to let this module know if you are using this
IDENTITY option by setting in your class configuration the key
'syb_identity' to a true value.

METHODS
=======

   *sql_quote*

   `DBD::Sybase' depends on the type of a field if you are quoting values
to put into a statement, so we override the default 'sql_quote' from
`SPOPS::SQLInterface' to ensure the type of the field is used in the
DBI->quote call.

BUGS
====

TO DO
=====

SEE ALSO
========

   See SPOPS/Key/DBI/Identity, `DBD::Sybase' in
this node, `DBI' in this node

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters  <chris@cwinters.com>

Centralized error messages from all SPOPS objects.
**************************************************

NAME
====

   SPOPS::Error - Centralized error messages from all SPOPS objects.

SYNOPSIS
========

     # Using SPOPS in your application
     my $obj_list = eval { $obj->fetch_group( { where => 'this = that' } ) };
     if ( $@ ) {
       warn "Error found! Error: $@\n",
            "Error type: $SPOPS::Error::type\n",
            "More specific: $SPOPS::Error::system_msg\n",
            "Extra stuff:\n",
            "--$SPOPS::Error::extra->{sql}\n",
            "--$SPOPS::Error::extra->{valuesb}\n";
     }

DESCRIPTION
===========

   This class provides a central location for error messages from all
SPOPS modules. The error information collected in these variables is
guaranteed to result from the most recent error generated by SPOPS.

VARIABLES
=========

   All of these variables are package variables, so you refer to them like
this:

     $SPOPS::Error::<variable_name>
     $SPOPS::Error::system_msg

   See the `NOTES' in this node section below for hints on making the
error variables shorter.

     *user_msg* ($)

     A generic message that is suitable for showing a user. When telling a
     user something went wrong, you do not want to tell them:

          execute called with 2 bind variables when 1 are needed

     instead, you want to tell them:

          Database query failed to execute

     This variable is identical to the value thrown by the *die()*
     command, so you do not normally need to refer to it.

     *system_msg* ($)

     Even though you do not want to show your users details of the error,
     you still need to know them! The variable *system_msg* gives you
     details regarding the error.

     type ($)

     SPOPS knows about a few types of errors. Some depend on your SPOPS
     implementation (e.g., DBI, dbm, LDAP, etc.). Others can be:

          -security: There is a security violation and the action could not be
                     completed

     package ($)

     Set to the package from where the error was thrown.

     method ($)

     Set to the method from where the error was thrown.

     filename ($)

     Set to the filename from where the error was thrown.

     line ($)

     Set to the line number from where the error was thrown.

     *extra* (\%)

     Different SPOPS classes have different information related to the
     current request. For instance, DBI errors will typically fill the
     'sql' and 'values' keys. Other SPOPS implementations may use different
     keys; see their documentation for details.

METHODS
=======

   clear

   Clears the current error saved in the class. Classes outside the
*SPOPS::* hierarchy should never need to call this.

   No return value.

   get()

   Returns a hashref with all the currently set error values.

   *set( \% )*

   First clears the variables then sets them all in one fell swoop. The
variables that are set are passed in the first argument, a hashref. Also
sets both the package and method variables for you, although you can
override by setting manually.

   No return value;

NOTES
=====

   Some people might find it easier to alias a local package variable to a
SPOPS error variable. For instance, you can do:

     *err_user_msg   = \$SPOPS::Error::user_msg;
     *err_system_msg = \$SPOPS::Error::system_msg;
     *err_type       = \$SPOPS::Error::type;
     *err_extra      = \%SPOPS::Error::extra;

   And then refer to the alias in your local package:

     my $obj_list = eval { $obj->fetch_group( { where => 'this = that' } ) };
     if ( $@ ) {
       warn "Error found! Error: $@\n",
            "Error type: $err_type\n",
            "More specific: $err_system_msg\n",
            "Extra stuff:\n",
            "--$err_extra{sql}\n",
            "--$err_extra{values}\n";
     }

   Whatever floats your boat.

TO DO
=====

BUGS
====

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters  <chris@cwinters.com>

Store SPOPS objects in a GDBM database
**************************************

NAME
====

   SPOPS::GDBM - Store SPOPS objects in a GDBM database

SYNOPSIS
========

     my $obj = Object::Class->new;
     $obj->{parameter1} = 'this';
     $obj->{parameter2} = 'that';
     my $id = $obj->save;

DESCRIPTION
===========

   Implements SPOPS persistence in a GDBM database. Currently the
interface is not as robust or powerful as the `SPOPS::DBI' implementation,
but if you want more robust data storage, retrieval and searching needs
you should probably be using a SQL database anyway.

   This is also a little different than the `SPOPS::DBI' module in that
you have a little more flexibility as to how you refer to the actual GDBM
file required. Instead of defining one database throughout the operation,
you can change in midstream. (To be fair, you can also do this with the
`SPOPS::DBI' module, it is just a little more difficult.) For example:

     # Read objects from one database, save to another
     my @objects = Object::Class->fetch_group( { filename => '/tmp/object_old.gdbm' } );
     foreach my $obj ( @objects ) {
       $obj->save( { is_add => 1, gdbm_filename => '/tmp/object_new.gdbm' } );
     }

METHODS
=======

   *id_field*

   If you want to define an ID field for your class, override this. Can be
a class or object method.

   *class_initialize*

   Much the same as in DBI. (Nothing interesting.)

   *initialize( \%params )*

   Much the same as in DBI, although you are able to initialize an object
to use a particular filename by passing a value for the 'GDBM_FILENAME'
key in the hashref for parameters when you create a new object:

     my $obj = Object::Class->new( { GDBM_FILENAME = '/tmp/mydata.gdbm' } );

   *global_gdbm_tie( \%params )*

   Returns a tied hashref if successful.

   There are many different ways of creating a filename used for GDBM. You
can define a default filename in your package configuration; you can pass
it in with every request (using the parameter 'filename'); you can define
a file fragment (non-specific directory name plus a filename, like
'conf/package.gdbm') and then pass a directory to anchor the filename with
every request.

   Parameters:

     perm ($ (default 'read')
       Defines the permissions to open the GDBM file. GDBM recognizes
       three permissions: 'GDBM_READER', 'GDBM_WRITER', 'GDBM_WRCREAT'
       (for creating and having write access to the file). You only need
       to pass 'read', 'write', or 'create' instead of these constants.

     If you pass nothing, C<SPOPS::GDBM> will assume 'read'. Also note
     that on some GDBM implementations, specifying 'write' permission to
     a file that has not yet been created still creates it, so 'create'
     might be redundant on your system.

     filename ($) (optional)
       Filename to use. If it is not passed, we look into the
       'tmp_gdbm_filename' field of the object, and then the 'filename'
       key of the 'gdbm_info' key of the class config, and then the
       'filename' key of the 'gdbm_info' key of the global configuration.

     directory ($) (optional)
       Used if you have defined 'file_fragment' within your package
       configuration; we join the directory and filename with a '/' to
       create the gdbm filename.

   id

   If you have defined a routine that returns the 'id_field' of an object,
it returns the value of that for a particular object. Otherwise it
executes the coderef found in the 'create_id' key of the class
configuration for the object. Usually this is something quite simple:

     ...
     'create_id' => sub { return join( '--', $_[0]->{name}, $_[0]->{version} ) }
     ...

   In the config file just joins the 'name' and 'version' parameters of an
object and returns the result.

   *object_key*

   Creates a key to store the object in GDBM. The default is to prepend
the class to the value returned by id() to prevent ID collisions between
objects in different classes. But you can make it anything you want.

   *fetch( $id, \%params *

   Retrieve a object from a GDBM database. Note that $id corresponds not
to the object key, or the value used to store the data. Instead it is a
unique identifier for objects within this class.

   You can pass normal db parameters.

   *fetch_group( \%params )*

   Retrieve all objects from a GDBM database from a particular class. If
you modify the 'object_key' method, you will probably want to modify this
as well.

   You can pass normal db parameters.

   *save( \%params )*

   Save (either insert or update) an object in a GDBM database.

   You can pass normal db parameters.

   *remove( \%params )*

   Remove an object from a GDBM database.

   You can pass normal db parameters.

Private Methods
---------------

   *_return_structure_for_key( \%params )*

   Returns the data structure in the GDBM database corresponding to a
particular key. This data structure is not blessed yet, it is likely just
a hashref of data (depending on how you implement your objects, although
the default method for SPOPS objects is a tied hashref).

   This is an internal method, so do not use it.

   You can pass normal db parameters.

TO DO
=====

BUGS
====

SEE ALSO
========

   GDBM software:

   http://www.fsf.org/gnulist/production/gdbm.html

   GDBM on Perl/Win32:

   http://www.roth.net/perl/GDBM/

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters  <chris@cwinters.com>

Implement as objects files containing perl hashrefs dumped to text
******************************************************************

NAME
====

   SPOPS::HashFile - Implement as objects files containing perl hashrefs
dumped to text

SYNOPSIS
========

     my $config = SPOPS::HashFile->new( { filename => '/home/httpd/myapp/server.perl',
                                          perm => 'read' } );
     print "My SMTP host is $config->{smtp_host}";

     # Setting a different value is ok...
     $config->{smtp_host} = 'smtp.microsoft.com';

     # ...but this will 'die' with an error, since you set the permission
     # to read-only 'read' in the 'new' call
     $config->save;

DESCRIPTION
===========

   Implement a simple interface that allows you to use a perl data
structure dumped to disk as an object. This is often used for
configuration files, since the key/value, and the flexibility of the
'value' part of the equation, maps well to varied configuration directives.

METHODS
=======

   *new( { filename => $, [ perm => $ ] } )*

   Create a new `SPOPS::HashFile' object that uses the given filename and,
optionally, the given permission. The permission can be one of three
values: 'read', 'write' or 'new'. If you try to create a new object
without passing the 'new' permission, the action will die because it
cannot find a filename to open. Any value passed in that is not 'read',
'write' or 'new' will get changed to 'read', and if no value is passed in
it will also be 'read'.

   Note that the 'new' permission does not mean that a new file will
overwrite an existing file automatically. It simply means that a new file
will be created if one does not already exist; if one does exist, it will
be used.

   The 'read' permission only forbids you from saving the object or
removing it entirely. You can still make modifications to the data in the
object.

   This overrides the new() method from SPOPS.

   *fetch( $filename, [ { perm => $ } ] )*

   Retrieve an existing config object (just a perl hashref data structure)
from a file. The action will result in a 'die' if you do not pass a
filename, if the file does not exist or for any reason you cannot open it.

   save

   Saves the object to the file you read it from.

   remove

   Deletes the file you read the object from, and blanks out all data in
the object.

   *clone( { filename => $, [ perm => $ ] } )*

   Create a new object from the old, but you can change the filename and
permission at the same time. Example:

     my $config = SPOPS::HashFile->new( { filename => '~/myapp/spops.perl' } );
     my $new_config = $config->clone( { filename => '~/otherapp/spops.perl',
                                        perm => 'write' } );
     $new_config->{base_dir} = '~/otherapp/spops.perl';
     $new_config->save;

   This overrides the clone() method from SPOPS.

NOTES
=====

   *No use of SPOPS::Tie*

TO DO
=====

   *Use SPOPS::Tie*

   This is one of the few SPOPS implementations that will never use the
`SPOPS::Tie' class to implement its data holding. We still use a tied
hash, but it is much simpler - no field checking, no ensuring that the
keys match in case, etc. This just stores some information about the
object (filename, permission, and data) and lets you go on your merry way.

   However, since we recently changed SPOPS/Tie, to make
field-checking optional we might be able to use it.

BUGS
====

SEE ALSO
========

   See SPOPS, Data/Dumper,

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters  <chris@cwinters.com>

Implement a security object and basic operations
************************************************

NAME
====

   SPOPS::Impl::Security - Implement a security object and basic operations

SYNOPSIS
========

     use SPOPS::Secure qw( :all );
     my $sec_class = 'SPOPS::Impl::Security';

     # Create a security object with level WRITE
     # for user $user on object $obj
     my $sec = $sec_class->new();
     $sec->{class}    = ref $obj;
     $sec->{oid}      = $obj->id;
     $sec->{scope}    = SEC_SCOPE_USER;
     $sec->{scope_id} = $user->id;
     $sec->{level}    = SEC_LEVEL_WRITE;
     $sec->save;

     # Clone that object and change its scope to
     # GROUP and level to READ
     my $secg = $sec->clone( scope => SEC_SCOPE_GROUP,
                             scope_id => $group->id,
                             level => SEC_LEVEL_READ );
     $secg->save;

DESCRIPTION
===========

   This class works a little behind-the-scenes, so you probably will not
deal directly with it very much. Instead, check out SPOPS/Secure,
for module developer (and other) information.

   Each security setting to an object is itself an object. In this manner
we can use the SPOPS framework to create/edit/remove security settings.
(Note that if you modify the 'SPOPS::Impl::SecurityObj' class to use
'SPOPS::Secure' in its @ISA, you will probably collapse the Earth - or at
least your system - in a self-referential object definition cycle. Do not
do that.)

METHODS
=======

   *fetch_match( $obj, scope =* SCOPE, scope_id => $ );

   Returns a security object matching the $obj for the scope and scope_id
passed in, undef if none found.

   Examples:

     my $sec_class = 'SPOPS::Impl::SecurityObj';

     # Returns security object matching $obj with a scope of WORLD
     my $secw = $sec_class->fetch_match( $obj, scope => SEC_SCOPE_WORLD );

     # Returns security object matching $obj with a scope of GROUP
     # matching the ID from $group
     my $secg = $sec_class->fetch_match( $obj, scope => SEC_SCOPE_GROUP,
                                         scope_id => $group->id );

     # Returns security object matching $obj with a scope of USER
     # matching the ID from $user
     my $secg = $sec_class->fetch_match( $obj, scope => SEC_SCOPE_USER,
                                         scope_id => $user->id );

   *fetch_by_object( $obj, { user =* \@, group => \@ ... } )>

   Returns a hashref with security information for a particular object.
The keys of the hashref are SEC_SCOPE_WORLD, SEC_SCOPE_USER, and
SEC_SCOPE_GROUP as exported by SPOPS::Secure.

   You can restrict the security returned for USER and/or GROUP by passing
a hashref of objects or ID values under the 'user' or 'group' keys.

   You can also pass in a 'class' and 'oid' value to use that for the
object identifier for the lookup.

   Examples:

     my \%info = $sec->fetch_by_object( $obj );

   Returns all security information for $obj.

     my \%info = $sec->fetch_by_object( $obj, { user => [ 1, 2, 3 ] } );

   Returns $obj security information for WORLD, all GROUPs but only USERs
with ID 1, 2 or 3.

     my \%info = $sec->fetch_by_object( $obj, { user => [ 1, 2, 3 ],
                                                group => [ 817, 901, 716 ] } );

   Returns $obj security information for WORLD, USERs 1, 2 and 3 and
GROUPs 817, 901, 716.

TO DO
=====

BUGS
====

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters <chris@cwinters.com>

Create and manipulate users.
****************************

NAME
====

   SPOPS::User - Create and manipulate users.

SYNOPSIS
========

     use SPOPS::User;
     $user = SPOPS::User->new();

     # Increment the user's login total
     $user->increment_login();
     print "Username: $user->{username}\n";

DESCRIPTION
===========

METHODS
=======

   *fetch_by_username( $username, \%params )*

   Class method. Retrieves a user object based on a $username rather than
a user_id. Returns undef if no user found by that name.

   *full_name()*

   Returns the full name - it is accessed often enough that we just made
an alias for concatenating the first and last names.

   *make_public()*

   Make this user part of the public group.

   *check_password( $pw )*

   Return a 1 if the password matches what is in the database, a 0 if not.

TO DO
=====

BUGS
====

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters  <chris@cwinters.com>

Retrieve IDENTITY values from a supported DBI database
******************************************************

NAME
====

   SPOPS::Key::DBI::Identity - Retrieve IDENTITY values from a supported
DBI database

SYNOPSIS
========

     # Using a class-only defintion
     package MySPOPS;
     @MySPOPS::ISA = qw( SPOPS::Key::DBI::Identity  SPOPS::DBI );

     # Using a config-only definition
     'myspops' => {
         'isa' => [ qw/ SPOPS::Key::DBI::Identity  SPOPS::DBI / ],
         ...
     },

DESCRIPTION
===========

   This class enables a just-created object to the IDENTITY value returned
by its last insert. Of course, this only works if you have an IDENTITY
field in your table, such as:

     CREATE TABLE my_table (
       id    numeric( 8, 0 ) IDENTITY not null,
       ...
     )

   This method is typically used in Sybase and Microsoft SQL Server
databases. The client library (Open Client, FreeTDS, ODBC) should not make
a difference to this module.

METHODS
=======

   *pre_fetch_id()*

   Ensure we only get the ID after the data are inserted.

   *post_fetch_id()*

   Retrieve the IDENTITY value after inserting a row.

BUGS
====

   None.

TO DO
=====

SEE ALSO
========

   `DBD::Sybase' in this node, `DBI' in this node

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters  <chris@cwinters.com>

Retrieves ID field information from a pool
******************************************

NAME
====

   SPOPS::Key::DBI::Pool - Retrieves ID field information from a pool

SYNOPSIS
========

     # In your configuration file

     # Bind the value 'unique_value' to the field 'table'

     my $spops = {
       isa => [ qw/ SPOPS::Key::DBI::Pool SPOPS::DBI / ],
       pool_sql   => 'select my_key from key_pool where table = ?',
       pool_value => [ 'unique_value' ],
       ...
     };

     # Use the values 'unique_value' and 'my_location' but use quoting
     # rather than binding (some DBDs don't let you use bound values with
     # stored procedures)

     my $spops = {
       isa => [ qw/ SPOPS::Key::DBI::Pool SPOPS::DBI / ],
       pool_sql   => 'exec new_key %s, %s',
       pool_value => [ 'unique_value', 'my_location' ],
       pool_quote => 1,
       ...
     };

DESCRIPTION
===========

   This module retrieves a value from a pool of key values matched up to
tables. It is not as fast as IDENTITY fields (see
SPOPS/Key/DBI/Identity, auto_incrementing values
or sequences, but can be portable among databases and, most importantly,
works in a replicated environment. It also has the benefit of being fairly
simple to understand.

   Currently, the key fetching procedure is implemented via a stored
procedure for portability among tools in different languages, but it does
not have to remain this way. It is perfectly feasible to program the
entire procedure in perl.

BUGS
====

   *Put this class before others in ISA*

   Not really a bug, but you must put this class before any
database-specific ones (like 'SPOPS::DBI::Sybase' or whatnot) in your
@ISA, otherwise this class will not be able to do its work.

TO DO
=====

   It might be a good idea to subclass this with a pure Perl solution.

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters  <chris@cwinters.com>

Creates a random alphanumeric code for the ID field
***************************************************

NAME
====

   SPOPS::Key::Random - Creates a random alphanumeric code for the ID field

SYNOPSIS
========

     package MySPOPS;

     @MySPOPS::ISA = qw( SPOPS::Key::Random SPOPS::DBI );

DESCRIPTION
===========

   Very, very simple. We just use the *generate_random_code()* method in
all SPOPS  classes to generate an n character code. The width of the code
is determined by the field {id_width} in the CONFIG of the SPOPS
implementation.

BUGS
====

   *Getting a 'random' value*

   If you are using this under mod_perl, you might have the problem of
colliding ID fields. This seems to happen because the httpd children all
have the same random seed, since they are all forked off from the same
parent.

   The solution is to put a 'srand()' in the PerlChildInitHandler,
although mod_perl versions from 1.25 on might take care of this for you.

TO DO
=====

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters  <chris@cwinters.com>

Generic routines for DBI database interaction
*********************************************

NAME
====

   SPOPS::SQLInterface - Generic routines for DBI database interaction

SYNOPSIS
========

     # Make this class a parent of my class
     package My::DBIStuff;
     use SPOPS::SQLInterface;
     @My::DBIStuff::ISA = qw( SPOPS::SQLInterface );

     # You should also be able to use it directly, but you
     # need to pass in a database handler with every request
     use SPOPS::SQLInterface;
     my $dbc = 'SPOPS::SQLInterface';
     my $db = DBI->connect( ... ) || die $DBI::errstr;
     my $rows = $dbc->db_select( { select => [ qw/ uid first_name last_name / ],
                                   from   => [ 'users' ],
                                   where  => 'first_name = ? or last_name = ?',
                                   value  => [ 'fozzie', "th' bear" ],
                                   db     => $db } );
     foreach my $row ( @{ $results } ) {
       print "User ID $row->[0] is $row->[1] $row->[2]\n";
     }

DESCRIPTION
===========

   You are meant to inherit from this class, although you can use it as a
standalone SQL abstraction tool as well, as long as you pass the database
handle into every routine you call.

DATABASE METHODS
================

   Relatively simple (!) methods to do the select, update, delete and
insert statements, with the right values and table names being passed in.

   All parameters are passed in via named values, such as:

     $t->db_select( { select => [ 'this', 'that' ],
                      from => [ 'mytable' ] } );

   *VERY IMPORTANT*

   The subclass that uses these methods must either pass in a DBI database
handle via a named parameter (db) or make it available through a method of
the class called 'global_db_handle'.

METHODS
=======

   There are very few methods in this class, but each one can do quite a
bit.

db_select
---------

   Executes a SELECT. Return value depends on what you ask for.

   Parameters:

   select (\@)

   Fields to select

   *select_modifier* ($)

   Clause to insert between 'SELECT' and fields (e.g., DISTINCT)

   from (\@)

   List of tables to select from

   order ($)

   Clause to order results by; if not given, the order depends entirely on
the database.

   where ($)

   Clause to limit results. Note that you can use '?' for field values but
they will get quoted as if they were a SQL_VARCHAR type of value.

   return ($)

   list: returns an arrayref of arrayrefs (default)

   single: returns a single arrayref

   hash: returns an arrayref of hashrefs

   *single-list*: returns an arrayref with the first value of each record
as the element.

   value (\@)

   List of values to bind, all as SQL_VARCHAR; they must match order of
'?' in the where clause either passed in or within the SQL statement
passed in.

   sql ($)

   Full statement to execute, although you may put '?' in the where clause
and pass values for substitution. (No quoting hassles...)

   Examples:

   Perl statement:

     $t->db_select( { select => [ qw/ first_name last_name /],
                      from => [ 'users' ],
                      where => 'last_name LIKE ?',
                      value => 'moo%' } );

   SQL statement:

     SELECT first_name, last_name
       FROM users
      WHERE last_name LIKE 'moo%'

   Returns:

     [ [ 'stephen', 'moore' ],
       [ 'charles', 'mooron' ],
       [ 'stacy', 'moonshine' ] ]

   Perl statement:

     $t->db_select( { select => [ qw/ u.username l.login_date / ],
                      from => [ 'users u', 'logins l' ],
                      where => "l.login_date > '2000-04-18' and u.uid = l.uid"
                      return => 'hash' } );

   SQL statement:

     SELECT u.username, l.login_date
       FROM users u, logins l
      WHERE l.login_date > '2000-04-18' and u.uid = l.uid

   Returns:

     [ { username => 'smoore',
         login_date => '2000-05-01' },
       { username => 'cmooron',
         login_date => '2000-04-19' },
       { username => 'smoonshine',
         login_date => '2000-05-02' } ]

   Perl statement:

     $t->db_select( { select => [ qw/ login_name first_name last_name /],
                      from => [ 'users' ],
                      where => 'last_name LIKE ?',
                      value => 'moo%',
                      return => 'single-list' } );

   SQL statement:

     SELECT login_name, first_name, last_name
       FROM users
      WHERE last_name LIKE 'moo%'

   Returns:

     [ 'smoore',
       'cmooron',
       'smoonshine' ]

db_insert
---------

   Create and execute an INSERT statement given the parameters passed in.

   Parameters:

   table ($)

   Name of table to insert into

   field (\@)

   List of fieldnames to insert

   value (\@)

   List of values, matching up with order of field list.

   *no_quote* (\%)

   Fields that we should not quote

   sql ($)

   Full SQL statement to run; you can still pass in values to quote/bind
if you use '?' in the statement.

   *return_sth* ($)

   If true, return the statement handle rather than a status.

   Examples:

   Perl statement:

     $t->db_insert( { table => 'users',
                      field => [ qw/ username first_name last_name password / ],
                      value => [ 'cmw817', "Chris O'Winters" ] } );

   SQL statement:

     INSERT INTO users
     ( username, first_name, last_name, password )
     VALUES
     ( 'cmw817', 'Chris', 'O''Winters', NULL )

   Perl statement:

     my $sql = qq/
       INSERT INTO users ( username ) VALUES ( ? )
     /;

     foreach my $username ( qw/ chuck stinky jackson / ) {
       $t->db_insert( { sql => $sql, value => [ $username ] } );
     }

   SQL statements:

     INSERT INTO users ( username ) VALUES ( 'chuck' )
     INSERT INTO users ( username ) VALUES ( 'stinky' )
     INSERT INTO users ( username ) VALUES ( 'jackson' )

db_update
---------

   Create and execute an UPDATE statement given the parameters passed in.

   Parameters:

   field (\@)

   List of fieldnames we are updating

   value (\@)

   List of values corresponding to the fields we are updating.

   table ($)

   Name of table we are updating

   where ($)

   Clause that specifies the rows we are updating

   *no_quote* (\%)

   Specify fields not to quote

   sql ($)

   Full SQL statement to run; note that you can use '?' for values and
pass in the raw values via the 'value' parameter, and they will be quoted
as necessary.

   Examples:

   Perl statement:

     $t->db_update( { field => [ qw/ first_name last_name / ],
                      value => [ 'Chris', "O'Donohue" ],
                      table => 'users',
                      where => 'user_id = 98172' } );

   SQL statement:

     UPDATE users
        SET first_name = 'Chris',
            last_name = 'O''Donohue',
      WHERE user_id = 98172

db_delete
---------

   Removes the record indicated by %params from the database.

   Parameters:

   table ($)

   Name of table from which we are removing records.

   where ($)

   Specify the records we are removing

   value (\@)

   List of values to bind to '?' that may be found either in the where
clause passed in or in the where clause found in the SQL statement.

   sql ($)

   Full SQL statement to execute directly, although you can use '?' for
values and pass the actual values in via the 'value' parameter.

   Be careful: if you pass in the table but not the criteria, you will
clear out your table! (Just like real SQL...)

   Examples:

   Perl statement:

     $t->db_delete( { table => 'users', where => 'user_id = 98172' } );

   SQL statement:

     DELETE FROM users
      WHERE user_id = 98172

   Perl statement:

     $t->db_delete( { table => 'users', where => 'last_name LIKE ?',
                      value => [ 'moo%' ] } );

   SQL statement:

     DELETE FROM users
      WHERE last_name LIKE 'moo%'

   Perl statement:

     $t->db_delete( { table => 'users' } );

   SQL statement:

     DELETE FROM users

   Oops, just cleared out the 'users' table. Be careful!

db_discover_types
-----------------

   Basically issue a dummy query to a particular table to get its schema.
We save the DBI type information in the %TYPE_INFO lexical that all
routines here can access.

   If a DBD driver does not support the {TYPE} attribute of the statement
handle, you have to specify some simple types in your class configuration
or provide them somehow. This is still slightly tied to SPOPS
implementations in OpenInteract, but only slightly.

   Return a hashref of fieldnames as keys and DBI types as values.

   Parameters:

   table ($)

   The name of a particular table. Note that this routine is not smart
enough to distinguish between: users and *dbo.users* even though they
might be the same table in the database. It is not particularly harmful if
you use the same name twice in this manner, the module just has to do a
little extra work.

ERROR HANDLING
==============

   Like other classes in SPOPS, all errors encountered will result in the
error information saved in SPOPS/Error, and a die()
being thrown. (More later.)

TO DO
=====

   *DBI binding conventions*

   One of the things the DBI allows you to do is prepare a statement once
and then execute it many times. It would be nice to allow that somehow.

BUGS
====

SEE ALSO
========

   `DBI' in this node

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters <chris@cwinters.com>

   Rusty Foster <rusty@kuro5hin.org> was influential in the early days of
this library.

Implement security across one or more classes of SPOPS objects
**************************************************************

NAME
====

   SPOPS::Secure - Implement security across one or more classes of SPOPS
objects

SYNOPSIS
========

     package MySPOPS::Class;

     use SPOPS::Secure qw( :all ); # import the security constants

     @MySPOPS::Class::ISA = qw( SPOPS::Secure SPOPS::DBI );

DESCRIPTION
===========

   By adding this module into the @ISA variable for your SPOPS class, you
implement a mostly transparent per-object security system. This security
system relies on a few things being implemented:

   * A SPOPS class implementing users

   * A SPOPS class implementing groups

   * A SPOPS class implementing security objects

   Easy, eh? Fortunately, SPOPS comes with all three, although you are
free to modify them as you see fit.

Overview of Security
--------------------

   Security is implemented with a number of methods that are called within
the SPOPS implementation module. For instance, every time you call fetch()
on an object, the system first determines whether you have rights to do
so. Similar callbacks are located in save() and remove(). If you do not
either define the method in your SPOPS implementation or use this module,
the action will always be allowed.

   We use the Unix-style of permission scheme, separating the scope into:
USER, GROUP and WORLD from most- to least-specific. (This is abbreviated
as U/G/W.) When we check permissions, we check whether a security level is
defined for the most-specific item first, then work our way up to the
least_specific. (We use the term 'scope' frequently in the module and
documentation - a 'specific scope' is a particular user or group, or the
world.)

   Even though we use the U/G/W scheme from Unix, we are not constrained
by its history. There is no strict 'ownership' assigned to an object as
there is to a Unix file. Instead, an object can have assigned to it
permissions from any number of users, and any number of groups.

   There are three settings for any object combined with a specific scope:

     NONE:  The scope is barred from even seeing the object.
     READ:  The scope can read the object but not save it.
     WRITE: The scope can read, write and delete the object.

   (To be explicit: WRITE permission implies READ permission as well; if a
scope has WRITE permission for an object, it can do anything with it,
including remove it.)

Security Rules
--------------

   With security, there are some important assumptions. These rules are
laid out here.

   * *The most specific security wins.* This means that you might have set
     permissions on an object to be SEC_LEVEL_WRITE for SEC_LEVEL_WORLD,
     but if the user who is logged in has SEC_LEVEL_NONE, permission will
     be denied.

   * *All objects must have a WORLD permission.* Configuration for your
     SPOPS object must include the *initial_security* hash. The only
     required field is 'WORLD', which defines the default WORLD permission
     for newly-created objects. If you do not include this, the system will
     automatically set the WORLD permission to SEC_LEVEL_NONE, which is
     probably not what you want.

   For instance, look at an object that represents a news notice posted:

     Object Class: MyApp::News
     Object ID:    1625

     ------------------------------------------------
     | SCOPE | SCOPE_ID |  NONE  |  READ  |  WRITE  |
     ------------------------------------------------
     | USER  | 71827    |        |   X    |         |
     | USER  | 6351     |   X    |        |         |
     | USER  | 9182     |        |        |    X    |
     | GROUP | 762      |        |   X    |         |
     | GROUP | 938      |        |        |    X    |
     | WORLD |          |        |   X    |         |
     ------------------------------------------------

   >From this, we can say:

   * User 6351 can never view this notice. Even though the user might be a
     part of a group that can; even though WORLD has READ permission.
     Since the user is explicitly forbidden from viewing the notice,
     nothing else matters.

   * If a different User (say, 21092) who belongs to both Group 762 and
     Group 938 tries to determine permission for this object, that User
     will have WRITE permission since the system returns the highest
     permission granted by all Group memberships.

   * Any user who is not specified here and who does not belong to either
     Group 762 or Group 938 will get READ permission to the object,
     reverting to the permission for the scope WORLD.

Setting Security for Created Objects
------------------------------------

   The Unix paradigm of file permissions assumes several things.

User and Group Objects
----------------------

   It is a fundamental tenet of this persistence framework that it should
have no idea what your application looks like.  However, since we deal
with user and group objects, it is necessary to enforce some standards.

   * Must be able to retrieve the ID of the object with the method call
     'id'. The ID value can be numeric or it can be a string, but it must
     have 16 or fewer characters.

   * Must be able to get an arrayref of members. With a group object, you
     must implement a method that returns users called 'user'. Similarly,
     your user object must implement a method that returns the groups that
     user belongs to via the method 'group':

          # Note that 'login_name' is not required as a
          # parameter; this is just an example
          my $user_members = eval { $group->user };
          foreach my $user ( @{ $user_members } ) {
            print "Username is $user->{login_name}\n";
          }

          # Note that 'name' is not required as a
          # parameter; this is just an example
          my $groups = eval { $user->group };
          foreach my $group ( @{ $groups } ) {
            print "Group name is $group->{name}\n";
          }

   * Must be able to retrieve the logged-in user (and, by the rule stated
     above, the groups that user belongs to).  This is done via the
     *global_user_current* method call. The SPOPS object or other class
     must be able to fulfill this method and return a user object.

METHODS
=======

   The methods that this class implements can be used by any SPOPS class.
The variable $item below refers to the fact that you can either do an
object method call or a class method call. If you do a class method call,
you must pass in the ID of the object for which you want to get or set
security.

   However, you may also implement security on the class level as well.
For instance, if your application uses classes to implement modules within
an application, you might wish to restrict the module by security very
similar to the security implemented for individual objects. In this case,
you would have a class name and no object ID (oid) value.

   To do so, simply make the class a subclass of SPOPS::Secure.  All the
methods remain exactly the same.

check_security( [ \%params ] )
------------------------------

   The method get_security() returns a code corresponding to the LEVEL
constants exported from this package. This code tells you what permissions
the logged in user has. You can also pass user and group parameters to
check security for other items as well.

   Note that you can check security for multiple groups but only one user
at a time. Passing an arrayref of user objects for the 'user' parameter
will result in the first user object being checked and the remainder
discarded. This is unlikely to be what you need.

   Examples:

     # Find the permission for the currently logged-in user for $item
     $item->check_security();

     # Get the security for this $item for a particuar
     # user; note that this *does* find the groups this
     # user belongs to and checks those as well
     $item->check_security( user => $user );

     # Find the security for this item for either of the
     # groups specified
     $item->check_security( group => [ $group, $group ] );

get_security( [ \%params ] )
----------------------------

   Returns a hashref of security information about the particular class or
object. The keys of the hashref are the constants, SEC_SCOPE_WORLD,
SEC_SCOPE_GROUP and SEC_SCOPE_USER. The value corresponding to the
SEC_SCOPE_WORLD key is simply the WORLD permission for the object or
class. Similarly, the value of SEC_SCOPE_USER is the permission for the
user specified. The SEC_SCOPE_GROUP key has as its value a hashref with
the IDs of the group as keys. (Examples below)

   Note that if the user specified does not have permissions for the
class/object, then its entry is blank.

   The parameters correspond to check_security. The default is to retrieve
the security for the currently logged-in user and groups (plus WORLD), but
you can restrict the output if necessary.

   Note that the WORLD key is always set, no matter how much you restrict
the user/groups.

   Finally: this will not be on the test, since you will probably not need
to use this very often. The *check_security()* and *set_security()*
methods are likely the only interfaces you need with security whether it
be object or class-based. The *get_security()* method is used primarily
for internal purposes, but you might also need it if you are writing
security administration tools.

   Examples:

     # Return a hashref using the currently logged-in
     # user and the groups the user belongs to
     #
     # Sample of what $perm looks like:
     # $perm = { 'u' => 4, 'w' => 1, 'g' => { 5162 => 4, 7182 => 8 } };
     #
     # Which means that the user has a permission of SEC_LEVEL_READ,
     # the user belongs to two groups with IDs 5162 and 7182 which have
     # permissions of READ and WRITE, respectively, and the WORLD
     # permission is NONE.
     my $perm = $item->get_security();

     # Find the security for a particular user object and its groups
     my $perm = $item->get_security( user => $that_user );

     # Find the security for two groups, no user objects.
     my $perm = $item->get_security( group => [ $group1, $group2 ] );

get_security_scopes( \%params )
-------------------------------

   Called by *get_security()* to determine which scopes to use to check
security on an object.

set_security( \%params )
------------------------

   The method set_security() returns a status as to whether the permission
has been set to what you requested.

   The default is to operate on one item at a time, but you can specify
many items at once with the 'multiple' parameter.

   Examples:

     # Set $item security for WORLD to READ

     my $wrv =  $item->set_security( scope => SEC_SCOPE_WORLD,
                                     level => SEC_LEVEL_READ );
     unless ( $wrv ) {
       # error! security not set properly
     }

     # Set $item security for GROUP $group to WRITE

     my $grv =  $item->set_security( scope => SEC_SCOPE_GROUP,
                                     scope_id => $group->id,
                                     level => SEC_LEVEL_WRITE );
     unless ( $grv ) {
       # error! security not set properly
     }

     # Set $item security for USER objects whose IDs are the keys in the
     # hash %multiple and whose values are the levels corresponding to the
     # ID.
     #
     # (Note that this is a contrived example for setting up the %multiple
     # hash - you should always do some sort of validation/checking before
     # passing user-specified information to a method.)

     my %multiple = (
      $user1->id => $cgi->param( 'level_' . $user1->id ),
      $user2->id => $cgi->param( 'level_' . $user2->id )
     );
     my $rv = $item->set_security( scope => SEC_SCOPE_USER,
                                   level => \%multiple );
     if ( $rv != scalar( keys %multiple ) ) {
       # error! security not set properly for all items
     }

     # Set $item security for multiple scopes whose values
     # are in the hash %multiple; note that the hash %multiple
     # has a separate layer now since we're specifying multiple
     # scopes within it.

     my %multiple = (
      SEC_SCOPE_USER() => {
         $user1->id => $cgi->param( 'level_' . $user1->id ),
         $user2->id => $cgi->param( 'level_' . $user2->id ),
      },
      SEC_SCOPE_GROUP() => {
         $group1->id  => $cgi->param( 'level_group_' . $group1->id ),
      },
     );
     my $rv = $item->set_security( scope => [ SEC_SCOPE_USER, SEC_SCOPE_GROUP ],
                                   level => \%multiple );

create_initial_security( \%params )
-----------------------------------

   Creates the initial security for an object. This can be simple, or this
can be complicated :) It is designed to be flexible enough for us to
easily plug-in security policy modules whenever we write them, but simple
enough to be used just from the object configuration.

   Object security configuration information is specified in the
'creation_security' hashref in the object configuration. A typical setup
might look like:

     creation_security => {
        u   => undef,
        g   => { level => { 3 => 'WRITE' } },
        w   => { level => 'READ'},
     },

   Each of the keys maps to a (hopefully intuitive) scope:

     u = SEC_SCOPE_USER
     g = SEC_SCOPE_GROUP
     w = SEC_SCOPE_WORLD

   For each scope you can either name security specifically or you can
defer the decision-making process to a subroutine. The former is called
'exact specification' and the latter 'code specification'. Both are
described below.

   Note that the 'level' values used ('WRITE' or 'READ' above) do not
match up to the SEC_LEVEL_* values exported from this module. Instead they
are just handy mnemonics to use - just lop off the 'SEC_LEVEL_' from the
exported variable:

     SEC_LEVEL_NONE  = 'NONE'
     SEC_LEVEL_READ  = 'READ'
     SEC_LEVEL_WRITE = 'WRITE'

   *Exact specification*

   'Exact specification' does exactly that - you specify the ID and
security level of the users and/or groups, along with one for the 'world'
scope if you like. This is handy for smaller sites where you might have a
small number of groups.

   The exact format is:

     SCOPE => { level => { ID => LEVEL,
                           ID => LEVEL, ... } }

   Where 'SCOPE' is 'u' or 'g', 'ID' is the ID of the group/user and
'LEVEL' is the level you want to assign to that group/user. So using our
example above:

     g   => { level => { 3 => 'WRITE' } },

   We assign the security level 'SEC_LEVEL_WRITE' to the group with ID 3.

   You can also use shortcuts.

   For the SEC_SCOPE_USER scope, if you specify a level:

     u    => { level => 'READ' }

   Then that security level is assigned for the user who created the
object.

   For the SEC_SCOPE_GROUP scope, if you specify a level:

     g    => { level => 'READ' }

   Then that security level is assigned for all of the groups to which the
user who created the object belongs.

   If you specify anything other than a level for the SEC_SCOPE_WORLD
scope, the system will discard the entry.

   *Code specificiation*

   You can also assign the entire process off to a separate routine:

     creation_security => {
        code => [ 'My::Package' => 'security_set' ]
     },

   This code should return a hashref formatted like this

     {
       u => SEC_LEVEL_*,
       g => { gid => SEC_LEVEL_* },
       w => SEC_LEVEL_*
     }

   If you do not include a scope in the hashref, no security information
for that scope will be entered.

   Parameters:

     class
       Specify the class you want to use to create the initial security.

     oid
       Specify the object ID you want to use to create the initial
       security.

TAGS FOR SCOPE/LEVEL
====================

   This module exports nothing by default. You can import specific tags
that refer to the scope and level, or you can import groups of them.

   Note that you should always use these tags. They may seem unwieldly,
but they make your program easier to read and allow us to modify the
values for these behind the scenes without you modifying any of your code.
If you use the values directly, you will get what is coming to you.

   You can import individual tags like this:

     use SPOPS::Secure qw( SEC_SCOPE_WORLD );

   Or you can import the tags in groups like this:

     use SPOPS::Secure qw( :scope );

   *Scope Tags*

   * SEC_SCOPE_WORLD

   * SEC_SCOPE_GROUP

   * SEC_SCOPE_USER

   *Level Tags*

   * SEC_LEVEL_NONE

   * SEC_LEVEL_READ

   * SEC_LEVEL_WRITE

   *Verbose Level Tags*

   These tags return a text value for the different security levels.

   * SEC_LEVEL_VERBOSE_NONE (returns 'NONE')

   * SEC_LEVEL_VERBOSE_READ (returns 'READ')

   * SEC_LEVEL_VERBOSE_WRITE (returns 'WRITE')

   *Groups of Tags*

   * scope: brings in all SEC_SCOPE tags

   * level: brings in all SEC_LEVEL tags

   * verbose: brings in all SEC_LEVEL_*_VERBOSE tags

   * all: brings in all tags

TO DO
=====

   *Sort out the different set_* methods*

   The different set_* methods are currently quite confusing.

   *Add SUMMARY level*

   Think about adding a SUMMARY level of security. This would allow, for
instance, search results to bring up an object and display a title and
perhaps more (controlled by the object), but forbid actually viewing the
entire object.

   *Add caching*

   Gotta gotta gotta get a caching interface done, where we simply say:

     $object->cache_security_level( $user );

   And cache the security level for that object for that user. **Any**
security modifications to that object wipe out the cache for that object.

BUGS
====

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters  <chris@cwinters.com>

Define hierarchical security
****************************

NAME
====

   SPOPS::Secure::Hierarchy - Define hierarchical security

SYNOPSIS
========

     # In your SPOPS configuration
     'myobj' => {
        'class' => 'My::FileObject',
        'isa' => [ qw/ ... SPOPS::Secure::Hierarchy  ... / ],
        'hierarchy_separator' => '/',
        'hierarchy_field'     => 'myobj_id',
        ...
     },

     # Every normal SPOPS security check will now go through a hierarchy
     # check using '/' as a separator on the value of the object parameter
     # 'myobj_id'

     my $file_object = eval { My::FileObject->fetch(
                                  '/docs/release/devel-only/v1.3/mydoc.html'
                       ) };

     # You can also use it as a standalone service. Note that the 'class'
     # in this example is controlled by you and used as an identifier
     # only.

     my $level = eval { SPOPS::Secure::Hierarchy->check_security({
                               class => 'My::Nonexistent::File::Class',
                               user => $my_user, group => $my_group_list,
                               security_object_class => 'My::SecurityObject',
                               oid   => '/docs/release/devel-only/v1.3/mydoc.html',
                               hierarchy_separator => '/',
                        })
                 };

DESCRIPTION
===========

   The existing SPOPS security framework relies on a one-to-one mapping of
security value to object. Sometimes you need security to filter down from
a parent to any number of children, such as in a pseudo-filesystem of
objects.

   To accomplish this, every record needs to have an identifier that can
be manipulated into a parent identifier. With filesystems (or URLs) this
is simple. Given the pseudo-file:

     /docs/release/devel-only/v1.3/mydoc.html

   You have the following parents:

     /docs/release/devel-only/v1.3
     /docs/release/devel-only
     /docs/release/
     /docs/
     <ROOT OBJECT> (explained below)

   What this module does is check the security of each parent in the
hierarchy. If no security settings are found for an item, the module tries
to find security of its parent. This continues until either the parent
hierarchy is exhausted or one of the parents has a security setting.

   If the security were defined like this:

   (Note: this is pseudo-code, and not necessarily the internal
representation):

     <ROOT OBJECT> =>
          { world => SEC_LEVEL_READ,
            group => { admin => SEC_LEVEL_WRITE } }

     /docs/release/devel-only =>

     { world => SEC_LEVEL_NONE,
       group => { devel => SEC_LEVEL_WRITE } }

   And our sample file is:

     /docs/release/devel-only/v1.3/mydoc.html

   And our users are:

   * *racerx* is a member of groups 'public', 'devel' and
     'mysteriouscharacters'

   * *chimchim* is a member of groups 'public', 'sidekicks'

   * *speed* is a member of groups 'public' and 'devel'

   Then both the users racerx and speed would have SEC_LEVEL_WRITE access
to the file while chimchim would have no access at all.

   For the file:

     /docs/release/public/v1.2/mydoc.html

   All three users would have SEC_LEVEL_READ access since the permissions
inherit from the <ROOT OBJECT>.

What is the ROOT OBJECT?
------------------------

   If you have a hierarchy of security, you are going to need one object
from which all security flows. No matter what kind of identifiers,
separators, etc. that you're using, the root object always has the same
object ID (For the curious, this object ID is available as the exported
scalar `$ROOT_OBJECT_NAME' from this module).

   If you do not create security for the root object manually,
`SPOPS::Secure::Hierarchy' will do so for you. However, you should be
aware that it will create the most stringent permissions for such an
object and that you might have a difficult time creating/updating objects
once this happens.

   Here is how to create such security:

     $class->create_root_object_security({
              scope => [ SEC_SCOPE_WORLD, SEC_SCOPE_GROUP ],
              level => { SEC_SCOPE_WORLD() => SEC_LEVEL_READ,
                       , SEC_SCOPE_GROUP() => { 3 => SEC_LEVEL_WRITE } }
     });

   Now, every object created in your class will default to having READ
permissions for WORLD and WRITE permissions for group ID 3.

METHODS
=======

   Most of the functionality in this class is found in SPOPS/Secure.
We override one of its methods and add one specific to the
functionality of this module.

   *get_hierarchy_levels( \%params )*

   Retrieve security for each level of the hierarchy. Returns a list - the
first element is a hashref with the keys as hierarchy elements and the
values as the security settings for that element (like what you would get
back if you checked only one item). The second element is a scalar with
the key of the first item encountered which actually had security.

   Example:

   my ( $all_levels, $first ) = $obj->get_hierarchy_levels();  print
"Level Info:\n", Data::Dumper::Dumper( $all_levels );

     >Level Info:
     > $VAR1 = {
     >  '/docs/release/devel-only/v1.3/mydoc.html' => undef,
     >  '/docs/release/devel-only/v1.3' => undef,
     >  '/docs/release/devel-only' => { u => 4, g => undef, w => 8 },
     >  '/docs/release/' => undef,
     >  '/docs/' => undef,
     >  'ROOT_OBJECT' => { u => undef, g => undef, w => 4 }
     >};

     print "First Level: ", $first;

     > First Level: /docs/release/devel-only

   *get_security( \%params )*

   Returns: hashref of security information indexed by the scopes.

   Parameters:

     class ($) (not required if calling from object)
       Class (or generic identifier) for which we would like to check
       security

     oid ($) (not required if calling from object)
       Unique identifier for the object (or generic thing) needing to be
       checked.

     hierarchy_field ($) (only required if calling from object with no
     configuration)
       Field to be used for the hierarchy check. Most (all?) of the time
       this will be the same as your configured 'id_field' in your SPOPS
       configuration.

     hierarchy_separator ($) (not required if calling from object with
     configuration)
       Character or characters used to split the hierarchy value into
       pieces.

     hierarchy_manip (optional)
       Code reference that, given the value to be broken into chunks, will
       return a hashref of information that describe the ways the
       hierarchy information can be used.

   *create_root_object_security( \%params )*

   If you're trying to retrofit this security system into a class with
already existing objects, you will need a way to bootstrap it so that you
can perform the actions you like. This method will create initial security
for you.

   Parameters:

     scope (\@ or $)
       One or more SPOPS::Secure SCOPE constants that define the scopes
       that you are defining security for.

     level (\% or $)
       If you have specified more than one item in the 'scope' parameter,
       this is a hashref, the keys of which are the scopes defined. The
       value may be a SPOPS::Secure LEVEL constant if the matching scope
       is WORLD, or a hashref of object-id - LEVEL pairs if the matching
       scope is USER or GROUP. (See L<What is the ROOT OBJECT?> above.)

BUGS
====

TO DO
=====

   *Revisit when hierarchy field != primary key*

   the _get_hierarchy_parameters has an assumption that the object ID will
always be the hierarchy value. Fix this. (Putting off because this is
unlikely.)

NOTES
=====

   *Security for Each Parent not Required*

   Note that each parent as we go up the hierarchy does not have to exist
in terms of security. That is, since an object can be both a child and a
parent, and a child can inherit from a parent, then the inheritance needs
to be able to flow through more than one generation.

SEE ALSO
========

   `SPOPS::Security' in this node

AUTHORS
=======

   Chris Winters <chris@cwinters.com>

   Christian Lemburg <lemburg@aixonix.de>

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Simple class implementing tied hash with some goodies
*****************************************************

NAME
====

   SPOPS::Tie - Simple class implementing tied hash with some goodies

SYNOPSIS
========

     # Create the tied hash
     use SPOPS::Tie;
     my ( %data );
     my @fields = qw( first_name last_name login birth_date );
     tie %data, 'SPOPS::Tie', $class, \@fields;

     # Store some simple properties
     $data{first_name} = 'Charles';
     $data{last_name}  = 'Barkley';
     $data{login}      = 'cb';
     $data{birth_date} = '1957-01-19';

     # Store a temporary property
     $data{tmp_rebound_avg} = 11.3;

     while ( my ( $prop, $val ) = each %data ) {
      printf( "%-15s: %s\n", $prop, $val );
     }

     # Note that output does not include 'tmp_rebound_avg'
     >first_name     : Charles
     >login          : cb
     >last_name      : Barkley
     >birth_date     : 1957-01-19

DESCRIPTION
===========

   Stores data for a SPOPS object, and also some accompanying materials
such as whether the object has been changed and any temporary variables.

Checking Changed State
----------------------

   You can check whether the data have changed since the last fetch by
either calling the method of the SPOPS object (recommended) or asking for
the '_changed' key:

     # See if this object has changed
     if ( $obj->{_changed} ) {
      ...do stuff...
     }

     # Tell the object that it has changed (force)
     $obj->{_changed} = 1;

   Note that this state is automatically tracked based on whether you set
any property of the object, so you should never need to do this. See
SPOPS, for more information about the *changed* methods.

Tracking Temporary Variables
----------------------------

   Note that this section only holds true if you have field-checking
turned on (by passing an arrayref of fields in the 'field' key of the
hashref passed as the second parameter in the tie call).

   At times you might wish to keep information with the object that is
only temporary and not supposed to be serialized with the object. However,
the 'valid property' nature of the tied hash prevents you from storing
information in properties with names other than those you pass into the
initial call to tie(). What to do?

   Have no fear! Simply prefix the property with 'tmp_' (or something
else, see below) and SPOPS::Tie will keep the information at the ready for
you:

     my ( %data );
     my $class = 'SPOPS::User';
     tie %data, 'SPOPS::Tie', $class, [ qw/ first_name last_name login / ];
     $data{first_name} = 'Chucky';
     $data{last_name}  = 'Gordon';
     $data{login}      = 'chuckg';
     $data{tmp_inoculation} = 'Jan 16, 1981';

   For as long as the hash %data is in scope, you can reference the
property 'tmp_inoculation'. However, you can only reference it directly.
You will not see the property if you iterate through hash using keys or
each.

Storing Information for Internal Use
------------------------------------

   The final kind of information that can be stored in a SPOPS object is
'internal' information. This is similar to temporary variables, but is
typically only used in the internal SPOPS mechanisms - temporary variables
are often used to store computed results or other information for display
rather than internal use.

   For example, the SPOPS/DBI, module allows you to
create validating subroutines to ensure that your data conform to some
sort of specification:

     push @{ $obj->{_internal_validate} }, \&ensure_consistent_date;

   Most of the time you will not need to deal with this, but check the
documentation for the object you are using.

METHODS
=======

   See Tie/Hash, or Perltie (perl.info), for
details of what the different methods do.

TO DO
=====

   *Benchmarking*

   We should probably benchmark this thing to see what it can do

BUGS
====

SEE ALSO
========

   See Perltie (perl.info),

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters  <chris@cwinters.com>

Enable field checking for SPOPS objects
***************************************

NAME
====

   SPOPS::Tie::StrictField - Enable field checking for SPOPS objects

SYNOPSIS
========

     use SPOPS::Tie::StrictField;
     my ( %data );
     my @fields = qw( first_name last_name login birth_date );
     tie %data, 'SPOPS::Tie::StrictField', $class, \@fields;

     # Trigger warnings by trying to store a misspelled
     # or unknown property

     # 'login' is the correct field
     $data{login_name}  = 'cb';

     # not in @fields list
     $data{middle_name} = 'Amadeus';

DESCRIPTION
===========

   This class subclasses SPOPS/Tie, adding field-checking
functionality. When you tie the hash, you also pass it a hashref of extra
information, one key of which should be 'field'. The 'field' parameter
specifies what keys may be used to access data in the hash. This is to
ensure that when you set or retrieve a property it is properly spelled.

   If you do not specify the 'field' parameter properly, you will get
normal SPOPS/Tie, functionality, which might throw a
monkey wrench into your application since you and any users will expect
the system to not silently accept misspelled object keys.

   For instance:

     my ( %data );
     my $class = 'SPOPS::User';
     tie %data, 'SPOPS::Tie::StrictField', $class, [ qw/ first_name last_name login / ];
     $data{firstname} = 'Chucky';

   would result in a message to STDERR, something like:

     Error setting value for field (firstname): it is not a valid field
     at my_tie.pl line 9

   since you have misspelled the property, which should be 'first_name'.

SEE ALSO
========

   See SPOPS/Tie, Perltie (perl.info),

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS
=======

   Chris Winters  <chris@cwinters.com>

Utility methods for SPOPS objects
*********************************

NAME
====

   SPOPS::Utility - Utility methods for SPOPS objects

SYNOPSIS
========

     # In configuration file
      'isa' => [ qw/ SPOPS::Utility SPOPS::DBI / ],

     # Create an object and run a utility
     my $user = MyApp::User->fetch( $id );
     $user->{crypted_password} = $user->crypt_it( $new_password );

     # Also use them separately
     use SPOPS::Utility qw();

     my $now = SPOPS::Utility->now;
     my $random = SPOPS::Utility->generate_random_code( 16 );

DESCRIPTION
===========

   This class has a number of utility methods that can be used from SPOPS
objects or from the SPOPS classes. They were previously in the main SPOPS
module but were removed to make the classes more consistent and focused.

   The different methods are fairly unrelated.

METHODS
=======

   *generate_random_code( $length )*

   Generates a random code of $length length consisting of upper-case
characters in the english alphabet.

   *crypt_it( $text )*

   Returns a crypt()ed version of $text. If $text not passed in, returns
undef.

   *now( \% )*

   Return the current time, formatted: yyyy-mm-dd hh:mm:ss. Since we use
the Date/Format, module (which in turn uses standard
strftime formatting strings), you can pass in a format for the date/time
to fit your needs.

   Parameters:

     format
       strftime format

     time
       return of time command (or manipulation thereof); see 'perldoc -f time'

   *today()*

   Return a date (yyyy-mm-dd) for today.

   *now_between_dates( { begin =* $dateinfo, end => $dateinfo } );

   Where $dateinfo is either a simple scalar ('yyyy-mm-dd') or an arrayref
([yyyy,mm,dd]).

   Note that you can also just pass one of the dates and the check will
still perform ok.

   Returns 1 if 'now' is between the two dates (inclusive), undef
otherwise.

   Examples:

   # Today is '2000-10-31' in all examples

     SPOPS::Utility->now_between_days( { begin => '2000-11-01' } );
     ( returns 'undef' )

     SPOPS::Utility->now_between_days( { end => '1999-10-31' } );
     ( returns 'undef' )

     SPOPS::Utility->now_between_days( { begin => [2000, 10, 1 ] } );
     ( returns 1 )

     SPOPS::Utility->now_between_days( { begin => '2000-10-01',
                                         end   => '2001-10-01' } );
     ( returns 1 )

   *list_process( \@existing, \@new )*

   Returns: hashref with three keys, each with an arrayref as the value:

     keep:   items found in both \@existing and \@new
     add:    items found in \@new but not \@existing
     remove: items found in \@existing but not \@new

   Mainly used for determining one-to-many relationship changes, but you
can probably think of other applications.

COPYRIGHT
=========

   Copyright (c) 2001 intes.net, inc.. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

MORE INFORMATION
================

   See the website:

     http://www.openinteract.org/SPOPS/

AUTHORS
=======

   Chris Winters <chris@cwinters.com>

   Christian Lemburg <lemburg@aixonix.de> successfully argued that these
methods should be removed from SPOPS.pm

add anchors ('^', '$') to SQL wildcards
***************************************

NAME
====

   SQL::AnchoredWildcards - add anchors ('^', '$') to SQL wildcards

SYNOPSIS
========

     use SQL::AnchoredWildcards;
     $pattern = sql_anchor_wildcards($pattern);

DESCRIPTION
===========

   SQL::AnchorWildcards enhances the default SQL SELECT..LIKE wildcard
processing by adding support for the '^' and '$' anchor metacharacters.
When using sql_anchor_wildcards(), if the pattern does not contain '^'
('$'), the search pattern is unanchored at the beginning (end).  Escaping
of '^' and '$' is done with '\'.

   Please also note that '$' is properly escaped for Perl's benefit.

EXAMPLES
========

   Let's take an SQL SELECT...LIKE Perl statement as in:

     my $query = new CGI;
     $query->import_names('Q');
     my $SQL =<<endSQL;
       SELECT
        GROUPNAME,
        GROUPID
       FROM
        TSR_GROUPS
       WHERE
        GROUPNAME LIKE '$Q::search';
     endSQL

   which will yield the SQL statement:

     SELECT
      GROUPNAME,
      GROUPID
     FROM
      TSR_GROUPS
     WHERE
      GROUPNAME LIKE 'HDTV';

   when the user has typed 'HDTV' into the text box named 'search' on the
CGI input form.  If 'HDTV' is the search term, then SQL SELECT..LIKE will
only find groups whose name matches /^HDTV$/.  If the CGI uses:

     $Q::search = sql_anchor_wildcards($Q::search);

   the SQL statement becomes:

     SELECT
      GROUPNAME,
      GROUPID
     FROM
      TSR_GROUPS
     WHERE
      GROUPNAME LIKE '%HDTV%';

   which will find all groups that have 'HDTV' as part of the group's
name.  I think that most people that use a Web-based search engine would
expect that typing 'HDTV' into a search box would make the search engine
find all groups that have 'HDTV' as part of the group's name.

   But what if you only want to find groups whose name starts with 'HDTV' -
say, all HDTV engineering groups like 'HDTV Power Supply Design' where
other, non-engineering groups would have 'HDTV' later in their names, like
'Marketing & Sales - HDTV Direct View'?  In that case with
SQL::AnchoredWildcards, you would type '^HDTV' into the CGI search box,
with:

     SELECT
      GROUPNAME,
      GROUPID
     FROM
      TSR_GROUPS
     WHERE
      GROUPNAME LIKE 'HDTV%';

   as the resulting SQL.  As you would expect, this SQL SELECT..LIKE
statement would find groups whose name starts with 'HDTV'.

   Similarly, if you know that the groups you want are those that have
'HDTV' as the last component of their names, like 'Marketing & Sales -
Direct View HDTV', you would type 'HDTV$' into the CGI search box, with:

     SELECT
      GROUPNAME,
      GROUPID
     FROM
      TSR_GROUPS
     WHERE
      GROUPNAME LIKE '%HDTV';

   as the resulting SQL.

   If you are looking for an embedded '$', as in:

     DCL LOGICAL $SYS_INFO

   you would type 'DCL LOGICAL \$SYS_INFO' into the CGI search box, with:

     SELECT
      GROUPNAME,
      GROUPID
     FROM
      TSR_GROUPS
     WHERE
      GROUPNAME LIKE 'DCL LOGICAL $SYS_INFO';

   as the resulting SQL.

AUTHOR
======

   Mark Leighton Fisher, fisherm@tce.com

SEE ALSO
========

   perl(1).

Base for deriving evalution objects for SQL::Statement
******************************************************

NAME
====

   SQL::Eval - Base for deriving evalution objects for SQL::Statement

SYNOPSIS
========

     require SQL::Statement;
     require SQL::Eval;

     # Create an SQL statement; use a concrete subclass of
     # SQL::Statement
     my $stmt = MyStatement->new("SELECT * FROM foo, bar",
     			        SQL::Parser->new('Ansi'));

     # Get an eval object by calling open_tables; this
     # will call MyStatement::open_table
     my $eval = $stmt->open_tables($data);

     # Set parameter 0 to 'Van Gogh'
     $eval->param(0, 'Van Gogh');
     # Get parameter 2
     my $param = $eval->param(2);

     # Get the SQL::Eval::Table object referring the 'foo' table
     my $fooTable = $eval->table('foo');

DESCRIPTION
===========

   This module implements two classes that can be used for deriving
concrete subclasses to evaluate SQL::Statement objects. The SQL::Eval
object can be thought as an abstract state engine for executing SQL
queries, the SQL::Eval::Table object can be considered a *very* table
abstraction. It implements method for fetching or storing rows, retrieving
column names and numbers and so on.  See the test.pl script as an example
for implementing a concrete subclass.

   While reading on, keep in mind that these are abstract classes, you
*must* implement at least some of the methods describe below.  Even more,
you need not derive from SQL::Eval or SQL::Eval::Table, you just need to
implement the method interface.

   All methods just throw a Perl exception in case of errors.

Method interface of SQL::Eval
-----------------------------

new
     Constructor; use it like this:

          $eval = SQL::Eval->new(\%attr);

     Blesses the hash ref \%attr into the SQL::Eval class (or a subclass).

param
     Used for getting or setting input parameters, as in the SQL query

          INSERT INTO foo VALUES (?, ?);

     Example:

          $eval->param(0, $val);        # Set parameter 0
          $eval->param(0);              # Get parameter 0

params
     Likewise used for getting or setting the complete array of input
     parameters. Example:

          $eval->params($params);       # Set the array
          $eval->params();              # Get the array

table
     Returns or sets a table object. Example:

          $eval->table('foo', $fooTable);  # Set the 'foo' table object
          $eval->table('foo');             # Return the 'foo' table object

column
     Return the value of a column with a given name; example:

          $col = $eval->column('foo', 'id');  # Return the 'id' column of
                                              # the current row in the
                                              # 'foo' table

     This is equivalent and just a shorthand for

          $col = $eval->table('foo')->column('id');

Method interface of SQL::Eval::Table
------------------------------------

new
     Constructor; use it like this:

          $eval = SQL::Eval::Table->new(\%attr);

     Blesses the hash ref \%attr into the SQL::Eval::Table class (or a
     subclass).

row
     Used to get the current row as an array ref. Do not mismatch getting
     the current row with the fetch_row method! In fact this method is
     valid only after a successfull `$table->fetchrow()'.  Example:

          $row = $table->row();

column
     Get the column with a given name in the current row. Valid only after
     a successfull `$table->fetchrow()'. Example:

          $col = $table->column($colName);

column_num
     Return the number of the given column name. Column numbers start with
     0. Returns undef, if a column name is not defined, so that you can
     well use this for verifying valid column names. Example:

          $colNum = $table->column_num($colNum);

column_names
     Returns an array ref of column names.

   The above methods are implemented by SQL::Eval::Table. The following
methods aren't, so that they *must* be implemented by concrete subclassed.
See the test.pl script for example.

fetch_row
     Fetches the next row from the table. Returns undef, if the last row
     was already fetched. The argument $data is for private use of the
     concrete subclass. Example:

          $row = $table->fetch_row($data);

     Note, that you may use

          $row = $table->row();

     for retrieving the same row again, until the next call of fetch_row.

push_row
     Likewise for storing rows. Example:

          $table->push_row($data, $row);

push_names
     Used by the *CREATE TABLE* statement to set the column names of the
     new table. Receives an array ref of names. Example:

          $table->push_names($data, $names);

seek
     Similar to the seek method of a filehandle; used for setting the
     number of the next row being written. Example:

          $table->seek($data, $whence, $rowNum);

     Actually the current implementation is using only `seek($data, 0,0)'
     (first row) and `seek($data, 2,0)' (last row, end of file).

truncate
     Truncates a table after the current row. Example:

          $table->truncate($data);

INTERNALS
=========

   The current implementation is quite simple: An SQL::Eval object is an
hash ref with only two attributes. The params attribute is an array ref of
parameters. The tables attribute is an hash ref of table names (keys) and
table objects (values).

   SQL::Eval::Table instances are implemented as hash refs. Used attributes
are row (the array ref of the current row), `col_nums' (an hash ref of
column names as keys and column numbers as values) and col_names, an array
ref of column names with the column numbers as indexes.

MULTITHREADING
==============

   All methods are working with instance-local data only, thus the module
is reentrant and thread safe, if you either don't share handles between
threads or grant serialized use.

AUTHOR AND COPYRIGHT
====================

   This module is Copyright (C) 1998 by

     Jochen Wiedmann
     Am Eisteich 9
     72555 Metzingen
     Germany

     Email: joe@ispsoft.de
     Phone: +49 7123 14887

   All rights reserved.

   You may distribute this module under the terms of either the GNU
General Public License or the Artistic License, as specified in the Perl
README file.

SEE ALSO
========

   `SQL::Statement(3)' in this node

Convert a data dictionary into SQL statements
*********************************************

NAME
====

   SQL::Schema - Convert a data dictionary into SQL statements

SYNOPSIS
========

     use DBI;

     my $dbh = DBI->connect(...);

     use SQL::Schema;

     my $schema = SQL::Schema->new($dbh);

     my $sql = $schema->string;
     print $sql;

     print "$schema";

WARNING
=======

   This is alpha software.  It currently works with Oracle databases only.
The name of the module might be changed in future releases as well as its
interface.

   If somebody is modifying the datase schema during the life time of an
`SQL::Schema' object, the object will probably fail and / or produce wrong
information.

DESCRIPTION
===========

   `SQL::Schema' is a class for objects representing a database schema.
The methods of an instanciated object do allow to access the information
within a database's data dictionary and to represent them as SQL create
statements and the like using the proper SQL dialect.

Constructor
-----------

     $schema = SQL::Schema->new($dbh);

   The new method instanciates a schema object. The only argument required
is a database handle, which has to offer the same API as described within
`DBI(3)' in this node.

Methods
-------

     $sql = $schema->string;

   Returns an SQL string containing several statements at once.  This
string contains all the SQL statements to create the database schema.

   This method is overloaded with the string operator. So the following
two lines are equivalent:

     $sql = $schema->string;
     $sql = "$schema";

AUTHOR AND COPYRIGHT
====================

     SQL::Schema is Copyright (C) 2000, Torsten Hentschel
                                        Windmuehlenweg 47
                                        44141 Dortmund
                                        Germany

     Email: todd@bayleys.ping.de

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `export_schema(1)' in this node, `DBI(3)' in this node,
`SQL::Schema::Procedure(3)' in this node, `SQL::Schema::Sequence(3)' in
this node, `SQL::Schema::Table(3)' in this node, `SQL::Schema::Trigger(3)'
in this node, `SQL::Schema::View(3)' in this node

A constraint of a database table
********************************

NAME
====

   SQL::Schema::Constraint - A constraint of a database table

SYNOPSIS
========

     my $constraint = SQL::Schema::Constraint->new(%attr);

     my $sql = $constraint->constraint_clause;
     print $sql;

     print "$constraint";

DESCRIPTION
===========

   `SQL::Schema::Constraint' is a class for objects representing a database
table's constraint. The methods of an instanciated object do allow to
access the information within a database's data dictionary and to
represent them as SQL create statements and the like using the proper SQL
dialect.

Constructors
------------

     $constraint = SQL::Schema::Constraint->new(%attr);

   The new method instanciates a constraint object. The object is an in
memory representation of a (possible) database table's constraint.  The
attributes are given as key value pairs by the hash %attr.  Possible keys
are:

     key                required?   value description

     constraint_name    yes         the constraint's name
     constraint_type    yes         one of
                                      C for check
                                      P for primary key
                                      U for unique key
                                      R for referential integrity
     search_condition   no          text of search condition for
                                    table check
     delete_rule        (*)         either `cascade' or `no action'
                                    default: `no action'
     status             no          either `enabled' or `disabled'
                                    default: `enabled'
     deferrable         no          either `deferrable' or `not deferrable'
                                    default: `not deferrable'
     deferred           no          either `immediate' or `deferred'
                                    default: `immediate'
     generated          no          either `generated name' or `user name'
                                    default: `user name'
     validated          no          either `validated' or `not validated'
                                    default: `validated'

   These keys (except columns) and their possible values correspond
exactly to the data dictionary view `user_constraints' and are described
within Oracle's Server Reference.

   Additionally the following keys are possible/required. They do not
relate to columns within the view `user_constraints'.

     key                required?   value description

     columns            no          a reference to a list with
                                    column objects
     r_schema           (*)         the referenced table's schema
     r_table_name       (*)         the referenced table's name
     r_columns          (*)         a reference to a list containing
                                    column objects representing the
                                    referenced columns

     (*) means: required for referential constrains otherwise not
                allowed

     @columns = SQL::Schema::Constraint->select_columns($dbh,$schema,$name);

   Returns a list of columns in the correct sequence. All the columns
belonging to the constraint with the name `$schema.$name' are selected
from the database and returned. All the elements of the returned list are
objects of the class `SQL::Schema::Table::Column'.

   The method's arguments are as follows:

$dbh
     A database handle as defined by `DBI(3)' in this node.

$schema
     The name of the constraint's schema.

$name
     The constraint's name.

     $constraint = SQL::Schema::Constraint->select($dbh,$constraint_name);

   The select method fetches the attributes required by new from the
database and returns the constraint object. (It calls new internally.)

   If the constraint could not be found within the database, the method
returns undef.

   The method's arguments are as follows:

$dbh
     A database handle as defined by `DBI(3)' in this node.

`$constraint_name'
     The name of the constraint.

Methods
-------

   The following attribute methods do return the current value of the
attributes (as handed over to the new method):

     $constraint_name   = $constraint->name;
     $constraint_type   = $constraint->type;
     $search_condition  = $constraint->search_condition;
     $delete_rule       = $constraint->delet_rule;
     $status            = $constraint->status;
     $deferrable        = $constraint->deferrable;
     $deferred          = $constraint->deferred;
     $generated         = $constraint->generated;
     $validated         = $constraint->validated;
     @columns           = $constraint->columns;
     $r_schema          = $constraint->r_schema;
     $r_table_name      = $constraint->r_table_name;
     @r_columns         = $constraint->r_columns;

   The return value of many of the above extra values is text with just
two possible values. Sometimes it is more comfortable for programmers to
have methods returning boolean values. The table below names extra methods
based on the methods above. They return 1 if the base method returns the
value shown within the 3rd column. Otherwise the return 0.

     extra method     base method    1 if eq          0 if eq

     cascade          delete_rule   cascade          no action
     enabled          status        enabled          disabled
     deferrable_b     deferrable    deferrable       not deferrable
     deferred_b       deferred      deferred         immediate
     generated_b      generated     generated name   user name
     validated_b      validated     validated        not validated

   Examples:

     $bool = $constraint->cascade;
     $bool = $constraint->enabled;
     $bool = $constraint->deferrable_b;
     $bool = $constraint->deferred_b;
     $bool = $constraint->generated_b;
     $bool = $constraint->validated_b;

     $sql = $constraint->constraint_clause;
     $sql = "$constraint";

   Returns a string containing the constraint clause which could be used
as part of an SQL statements for creation of the corresponding constraint.
This method is overloaded with the string operator. So the two examples
above are equivalent.

AUTHOR AND COPYRIGHT
====================

     SQL::Schema::Constraint is Copyright (C) 2000,
       Torsten Hentschel
       Windmuehlenweg 47
       44141 Dortmund
       Germany

     Email: todd@bayleys.ping.de

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `DBI(3)' in this node, `SQL::Schema(3)' in this node,
`SQL::Schema::Table(3)' in this node

A function stored within the database
*************************************

NAME
====

   SQL::Schema::Function - A function stored within the database

SYNOPSIS
========

     my $function = SQL::Schema::Function->new(%attr);

     my $sql = $function->create_statement;
     print $sql;

     print "$function";

DESCRIPTION
===========

   `SQL::Schema::Function' is a class for objects representing a function
stored within the database.  The methods of an instanciated object do
allow to access the information within a database's data dictionary and to
represent them as SQL create statements and the like using the proper SQL
dialect.

Constructors
------------

     $function = SQL::Schema::Function->new(%attr);

   The new method instanciates a function object. The object is an in
memory representation of a (possible) database function.  The attributes
are given as key value pairs by the hash %attr.  Possible keys are:

     key               required?   value description

     name              yes         the name of the function
                                   without preceeding schema name

     text              yes         the concatenation of all the text lines
                                   forming the function's source code

   As a function is basically a piece of source stored within the
database, this class inherits all methods from `SQL::Schema::Source'.  So
please have a look at the new method describet at `SQL::Schema::Source(3)'
in this node. Though the new method here overwrites the new method there,
it calls the super class's new method with just the key value pair for the
source's type added.

     $function = SQL::Schema::Function->select($dbh,$name);

   The select method fetches the attributes required by new from the
database and returns the function object. (It calls new internally.)

   If the function with the name $name could not be found within the
database, the method returns undef.

   The method's arguments are as follows:

$dbh
     A database handle as defined by `DBI(3)' in this node.

$name
     The name of the function without preceeding schema name.

Methods
-------

   The following attribute methods do exist:

     $type = $function->type;

   The method type always returns the string "function".  This package
inherits all the other methods from SQL::Schema::Source as a database
function basically is a special kind of source within the database. For
more information, please have a look at `SQL::Schema::Source(3)' in this
node.

AUTHOR AND COPYRIGHT
====================

     SQL::Schema::Function is Copyright (C) 2000,
       Torsten Hentschel
       Windmuehlenweg 47
       44141 Dortmund
       Germany

     Email: todd@bayleys.ping.de

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `DBI(3)' in this node, `SQL::Schema(3)' in this node,
`SQL::Schema::Source(3)' in this node

A package stored within the database
************************************

NAME
====

   SQL::Schema::Package - A package stored within the database

SYNOPSIS
========

     my $package = SQL::Schema::Package->new(%attr);

     my $sql = $package->create_statement;
     print $sql;

     print "$package";

DESCRIPTION
===========

   `SQL::Schema::Package' is a class for objects representing a package
stored within the database.  The methods of an instanciated object do
allow to access the information within a database's data dictionary and to
represent them as SQL create statements and the like using the proper SQL
dialect.

Constructors
------------

     $package = SQL::Schema::Package->new(%attr);

   The new method instanciates a package object. The object is an in
memory representation of a (possible) database package.  The attributes
are given as key value pairs by the hash %attr.  Possible keys are:

     key               required?   value description

     name              yes         the name of the package
                                   without preceeding schema name

     text              yes         the concatenation of all the text lines
                                   forming the package's source code

   As a package is basically a piece of source stored within the database,
this class inherits all methods from `SQL::Schema::Source'.  So please
have a look at the new method describet at `SQL::Schema::Source(3)' in
this node. Though the new method here overwrites the new method there, it
calls the super class's new method with just the key value pair for the
source's type added.

     $package = SQL::Schema::Package->select($dbh,$name);

   The select method fetches the attributes required by new from the
database and returns the package object. (It calls new internally.)

   If the package with the name $name could not be found within the
database, the method returns undef.

   The method's arguments are as follows:

$dbh
     A database handle as defined by `DBI(3)' in this node.

$name
     The name of the package without preceeding schema name.

Methods
-------

   The following attribute methods do exist:

     $type = $package->type;

   The method type always returns the string "package".  This package
inherits all the other methods from SQL::Schema::Source as a database
package basically is a special kind of source within the database. For
more information, please have a look at `SQL::Schema::Source(3)' in this
node.

AUTHOR AND COPYRIGHT
====================

     SQL::Schema::Package is Copyright (C) 2000,
       Torsten Hentschel
       Windmuehlenweg 47
       44141 Dortmund
       Germany

     Email: todd@bayleys.ping.de

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `DBI(3)' in this node, `SQL::Schema(3)' in this node,
`SQL::Schema::Source(3)' in this node

A package's body stored within the database
*******************************************

NAME
====

   SQL::Schema::Package::Body - A package's body stored within the database

SYNOPSIS
========

     my $body = SQL::Schema::Package::Body->new(%attr);

     my $sql = $body->create_statement;
     print $sql;

     print "$body";

DESCRIPTION
===========

   `SQL::Schema::Package::Body' is a class for objects representing a
package's body stored within the database.  The methods of an instanciated
object do allow to access the information within a database's data
dictionary and to represent them as SQL create statements and the like
using the proper SQL dialect.

Constructors
------------

     $body = SQL::Schema::Package::Body->new(%attr);

   The new method instanciates a package body object. The object is an in
memory representation of a (possible) database package body.  The
attributes are given as key value pairs by the hash %attr.  Possible keys
are:

     key               required?   value description

     name              yes         the name of the package
                                   without preceeding schema name

     text              yes         the concatenation of all the text lines
                                   forming the packag body's source code

   As a package body is basically a piece of source stored within the
database, this class inherits all methods from `SQL::Schema::Source'.  So
please have a look at the new method describet at `SQL::Schema::Source(3)'
in this node. Though the new method here overwrites the new method there,
it calls the super class's new method with just the key value pair for the
source's type added.

     $body = SQL::Schema::Package::Body->select($dbh,$name);

   The select method fetches the attributes required by new from the
database and returns the package body object. (It calls new internally.)

   If the package body with the name $name could not be found within the
database, the method returns undef.

   The method's arguments are as follows:

$dbh
     A database handle as defined by `DBI(3)' in this node.

$name
     The name of the package without preceeding schema name.

Methods
-------

   The following attribute methods do exist:

     $type = $body->type;

   The method type always returns the string "`package body'".  This
package inherits all the other methods from SQL::Schema::Source as a
database package body basically is a special kind of source within the
database. For more information, please have a look at
`SQL::Schema::Source(3)' in this node.

AUTHOR AND COPYRIGHT
====================

     SQL::Schema::Package::Body is Copyright (C) 2000,
       Torsten Hentschel
       Windmuehlenweg 47
       44141 Dortmund
       Germany

     Email: todd@bayleys.ping.de

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `DBI(3)' in this node, `SQL::Schema(3)' in this node,
`SQL::Schema::Source(3)' in this node

A procedure stored within the database
**************************************

NAME
====

   SQL::Schema::Procedure - A procedure stored within the database

SYNOPSIS
========

     my $procedure = SQL::Schema::Procedure->new(%attr);

     my $sql = $procedure->create_statement;
     print $sql;

     print "$procedure";

DESCRIPTION
===========

   `SQL::Schema::Procedure' is a class for objects representing a procedure
stored within the database.  The methods of an instanciated object do
allow to access the information within a database's data dictionary and to
represent them as SQL create statements and the like using the proper SQL
dialect.

Constructors
------------

     $procedure = SQL::Schema::Procedure->new(%attr);

   The new method instanciates a procedure object. The object is an in
memory representation of a (possible) database procedure.  The attributes
are given as key value pairs by the hash %attr.  Possible keys are:

     key               required?   value description

     name              yes         the name of the procedure
                                   without preceeding schema name

     text              yes         the concatenation of all the text lines
                                   forming the procedure's source code

   As a procedure is basically a piece of source stored within the
database, this class inherits all methods from `SQL::Schema::Source'.  So
please have a look at the new method describet at `SQL::Schema::Source(3)'
in this node. Though the new method here overwrites the new method there,
it calls the super class's new method with just the key value pair for the
source's type added.

     $procedure = SQL::Schema::Procedure->select($dbh,$name);

   The select method fetches the attributes required by new from the
database and returns the procedure object. (It calls new internally.)

   If the procedure with the name $name could not be found within the
database, the method returns undef.

   The method's arguments are as follows:

$dbh
     A database handle as defined by `DBI(3)' in this node.

$name
     The name of the procedure without preceeding schema name.

Methods
-------

   The following attribute methods do exist:

     $type = $procedure->type;

   The method type always returns the string "`procedure'".  This package
inherits all the other methods from SQL::Schema::Source as a database
procedure basically is a special kind of source within the database. For
more information, please have a look at `SQL::Schema::Source(3)' in this
node.

AUTHOR AND COPYRIGHT
====================

     SQL::Schema::Procedure is Copyright (C) 2000,
       Torsten Hentschel
       Windmuehlenweg 47
       44141 Dortmund
       Germany

     Email: todd@bayleys.ping.de

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `DBI(3)' in this node, `SQL::Schema(3)' in this node,
`SQL::Schema::Source(3)' in this node

An Oracle sequence
******************

NAME
====

   SQL::Schema::Sequence - An Oracle sequence

SYNOPSIS
========

     my $sequence = SQL::Schema::Sequence->new(%attr);

     my $sql = $sequence->create_statement;
     print $sql;

     print "$sequence";

DESCRIPTION
===========

   `SQL::Schema::Sequence' is a class for objects representing an Oracle
sequence. The methods of an instanciated object do allow to access the
information within a database's data dictionary and to represent them as
SQL create statements and the like using the proper SQL dialect.

Constructors
------------

     $sequence = SQL::Schema::Sequence->new(%attr);

   The new method instanciates a sequence object. The object is an in
memory representation of a (possible) oracle sequence.  The attributes are
given as key value pairs by the hash %attr.  Possible keys are:

     key            required?   value description

     schema_name    no          The name of the schema for

     sequence_name  yes         The name of the sequence (without a
                                preceeding schema name).

     min_value      no          number
     max_value      no          number
     increment_by   yes         number
     cycle_flag     no          either `Y' or `N'; default: `N'
     order_flag     no          either `Y' or `N'; default: `N'
     cache_size     yes         number
     start_with     yes         number

   These keys (except `schema_name' and `start_with') and their possible
values correspond exactly to the data dictionary view `user_sequences' and
are described within Oracle's Server Reference.

   The value for `start_with' is the number the sequence should start with.

     $sequence = SQL::Schema::Sequence->select($dbh,$name);
     $sequence = SQL::Schema::Sequence->select($dbh,$name,$schema_name);

   The select method fetches the attributes required by new from the
database and returns the sequence object. (It calls new internally.) It
takes the following arguments:

   If the sequence with the name $name could not be found within the
database, the method returns undef.

   The method's arguments are as follows:

$dbh
     A database handle as defined by `DBI(3)' in this node.

$name
     The name of the sequence without preceeding schema name.

`$schema_name'
     Optionally the name of the database schema.

     Warning: The method introduces a bug. The value for `start_with'
     required by the new method is selecte as `last_number + increment_by'.
     If the resulting value is outside the inverval given by `min_value'
     and `max_value' this is not checked. This means: In extreme cases it
     might happen, that the statement produced by the *create_statement*
     method can not really be executed on by a database.

Methods
-------

   The following attribute methods do return the current value of the
attributes (as handed over to the new method):

     $schema_name = $sequence->schema_name;
     $name = $sequence->name;
     $min_value = $sequence->min_value;
     $max_value = $sequence->max_value;
     $increment_by = $sequence->increment_by;
     $cycle_flages = $sequence->cycle_flags;
     $order_flags = $sequence->order_flags;
     $cache_size = $sequence->cache_size;
     $start_with = $sequence->start_with;

   The return value of *cycle_flag* resp. *order_flag* is either Y or N.
This is somewhat uncomfortable for perl programmers. You might want to use
the following two methods instead:

     $cycle_flag = $sequence->cycle;
     $order_flag = $sequence->order;

   They do return 1 resp. 0 where their corresponding attribute method
returns Y resp. N.

     my $qname = $sequence->qualified_name;

   Returns the qualified name of the sequence which is the concatenation
of `schema_name' and `sequence_name' with a in between if `schema_name'
has been set. Otherwise only `sequence_name' is returned.

     $sql = $sequence->create_statement;
     $sql = "$sequence";

   Returns a string containing an SQL statements for creation of a
sequence. This method is overloaded with the string operator.  So the two
examples above are equivalent.

     $sql = $sequence->drop_statement;

   Returns a string containing an SQL statement that would drop this
sequence.

BUGS
====

   The select method introduces a bug. This occurs if the value selected
from the database for `start_with' is not valid. For more information see
warning at select.

AUTHOR AND COPYRIGHT
====================

     SQL::Schema::Sequence is Copyright (C) 2000,
       Torsten Hentschel
       Windmuehlenweg 47
       44141 Dortmund
       Germany

     Email: todd@bayleys.ping.de

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `DBI(3)' in this node, `SQL::Schema(3)' in this node

A source stored within the database
***********************************

NAME
====

   SQL::Schema::Source - A source stored within the database

SYNOPSIS
========

     my $source = SQL::Schema::Source->new(%attr);

     my $sql = $source->create_statement;
     print $sql;

     print "$source";

DESCRIPTION
===========

   `SQL::Schema::Source' is a class for objects representing the source of
a package, function, procedure etc. stored within the database.  The
methods of an instanciated object do allow to access the information
within a database's data dictionary and to represent them as SQL create
statements and the like using the proper SQL dialect.

Constructors
------------

     $source = SQL::Schema::Source->new(%attr);

   The new method instanciates a source object. The object is an in memory
representation of a (possible) database source.  The attributes are given
as key value pairs by the hash %attr.  Possible keys are:

     key               required?   value description

     name              yes         the name of the package, procedure,
                                   function, ... without preceeding
                                   schema name

     type              yes         the type of the source; e.g.
                                     `procedure', `function',
                                     `package', `package body', ...

     text              yes         the concatenation of all the text lines
                                   forming the source code

   All the keys correspond to the columns with the same name from Oracle's
data dictionary view `user_sources'. Only text is somewhat special: It has
to be a concatenation of the source lines.

     $source = SQL::Schema::Source->select($dbh,$name,$type);

   The select method fetches the attributes required by new from the
database and returns the source object. (It calls new internally.)

   If the source with the name $name could not be found within the
database, the method returns undef.

   The method's arguments are as follows:

$dbh
     A database handle as defined by `DBI(3)' in this node.

$name
     The name of the source without preceeding schema name.

$type
     The type of the source.

Methods
-------

   The following attribute methods do return the current value of the
attributes (as handed over to the new method):

     $name = $source->name;
     $type = $source->type;
     $text = $source->text;

     $sql = $source->create_statement;
     $sql = "$source";

   Returns a string containing an SQL statements for creation of this
source. This method is overloaded with the string operator.  So the two
examples above are equivalent.

     $sql = $trigger->drop_statement;

   Returns a string containing an SQL statement that would drop this
trigger.

AUTHOR AND COPYRIGHT
====================

     SQL::Schema::Source is Copyright (C) 2000,
       Torsten Hentschel
       Windmuehlenweg 47
       44141 Dortmund
       Germany

     Email: todd@bayleys.ping.de

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `DBI(3)' in this node, `SQL::Schema(3)' in this node,

A database table
****************

NAME
====

   SQL::Schema::Table - A database table

SYNOPSIS
========

     my $table = SQL::Schema::Table->new(%attr);

     my $sql = $table->create_statement;
     print $sql;

     print "$table";

DESCRIPTION
===========

   `SQL::Schema::Table' is a class for objects representing a database
table. The methods of an instanciated object do allow to access the
information within a database's data dictionary and to represent them as
SQL create statements and the like using the proper SQL dialect.

Constructors
------------

     $table = SQL::Schema::Table->new(%attr);

   The new method instanciates a table object. The object is an in memory
representation of a (possible) database table.  The attributes are given
as key value pairs by the hash %attr.  Possible keys are:

     key              required?   value description

     schema_name      no          The name of the schema for

     table_name       yes         The name of the table (without a
                                  preceeding schema name).

     columns          yes         a reference to a list of
                                  column objects

     pct_free         no          number
     pct_used         no          number
     ini_trans        no          number

   These keys (except `schema_name' and columns) and their possible values
correspond exactly to the data dictionary view `user_tables' and are
described within Oracle's Server Reference.

   Optionally the following keys and values which do have no counter part
within the view `user_tables' are allowed for the attribute hash:

     key           value description

     constraints   a reference to a list of constraint objects
                   (objects of type SQL::Schema::Constraint for instance)

     $table = SQL::Schema::Table->select($dbh,$name,$schema_name);

   The select method fetches the attributes required by new from the
database and returns the table object. (It calls new internally.)

   If the table with the name $name could not be found within the
database, the method returns undef.

   The method's arguments are as follows:

$dbh
     A database handle as defined by `DBI(3)' in this node.

$name
     The name of the table without preceeding schema name.

`$schema_name'
     The name of the database schema.

Methods
-------

   The following attribute methods do return the current value of the
attributes (as handed over to the new method):

     $schema_name = $table->schema_name;
     $name = $table->name;
     @columns = $table->columns;
     $pct_free = $table->pct_free;
     $pct_used = $table->pct_used;
     $ini_trans = $table->ini_trans;
     @constraints = $table->constraints;

     my $qname = $table->qualified_name;

   Returns the qualified name of the table which is the concatenation of
`schema_name' and table_name with a in between if `schema_name' has been
set. Otherwise only table_name is returned.

     $sql = $table->create_statement;
     $sql = "$table";

   Returns a string containing an SQL statements for creation of this
table. This method is overloaded with the string operator.  So the two
examples above are equivalent.

     $sql = $table->drop_statement;

   Returns a string containing an SQL statement that would drop this table.

AUTHOR AND COPYRIGHT
====================

     SQL::Schema::Table is Copyright (C) 2000,
       Torsten Hentschel
       Windmuehlenweg 47
       44141 Dortmund
       Germany

     Email: todd@bayleys.ping.de

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `DBI(3)' in this node, `SQL::Schema(3)' in this node,
`SQL::Schema::Table::Column(3)' in this node, `SQL::Schema::Constraint(3)'
in this node

A column of a database table
****************************

NAME
====

   SQL::Schema::Table::Column - A column of a database table

SYNOPSIS
========

     my $column = SQL::Schema::Table::Column->new(%attr);

     my $sql = $column->column_definition;
     print $sql;

     print "$column";

DESCRIPTION
===========

   `SQL::Schema::Table::Column' is a class for objects representing a
database table's column. The methods of an instanciated object do allow to
access the information within a database's data dictionary and to
represent them as SQL create statements and the like using the proper SQL
dialect.

Constructors
------------

     $column = SQL::Schema::Table::Column->new(%attr);

   The new method instanciates a column object. The object is an in memory
representation of a (possible) database table's column.  The attributes
are given as key value pairs by the hash %attr.  Possible keys are:

     key              required?   value description

     column_name      yes         The name of the table's column.

     data_type        yes         number
     data_length      no          number
     data_precision   no          number
     data_scale       no          number
     nullable         no          either `Y' o `N'; default: `Y'
     data_default     no          a character string approbriate as
                                  expression after the `default' keyword
                                  (might include quotes)

   These keys and their possible values correspond exactly to the data
dictionary view `all_tab_columns' and are described within Oracle's Server
Reference.

     $column = SQL::Schema::Table::Column->select($dbh,$table_name,$column_name);

   The select method fetches the attributes required by new from the
database and returns the column object. (It calls new internally.)

   If the column could not be found within the database, the method
returns undef.

   The method's arguments are as follows:

$dbh
     A database handle as defined by `DBI(3)' in this node.

`$table_name'
     The name of the table without preceeding schema name.

`$column_name'
     The name of the column.

Methods
-------

   The following attribute methods do return the current value of the
attributes (as handed over to the new method):

     $column_name = $column->name;
     $data_type = $column->data_type;
     $data_length = $column->data_length;
     $data_precision = $column->data_precision;
     $data_scale = $column->data_scale;
     $nullable = $column->nullable;
     $data_default = $column->data_default;

   There does exist a speciallity for the `data_default' method: If the
attribute `data_default' the method `data_default' returns the content of
the attribute with eleminated trailing new line.

   The return value of *nullable* is either Y or N.  This is somewhat
uncomfortable for perl programmers.  You might want to use the following
method instead:

     $nullable = $sequence->nullable_bool;

   It does return 1 resp. 0 where its corresponding attribute method
returns Y resp. N.

     $sql = $column->column_definition;
     $sql = "$column";

   Returns a string containing the column definition which could be used
as part of an SQL statements for creation of the corresponding column.
This method is overloaded with the string operator. So the two examples
above are equivalent.

AUTHOR AND COPYRIGHT
====================

     SQL::Schema::Table::Column is Copyright (C) 2000,
       Torsten Hentschel
       Windmuehlenweg 47
       44141 Dortmund
       Germany

     Email: todd@bayleys.ping.de

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `DBI(3)' in this node, `SQL::Schema::Table(3)' in this node

A database trigger
******************

NAME
====

   SQL::Schema::Trigger - A database trigger

SYNOPSIS
========

     my $trigger = SQL::Schema::Trigger->new(%attr);

     my $sql = $trigger->create_statement;
     print $sql;

     print "$trigger";

DESCRIPTION
===========

   `SQL::Schema::Trigger' is a class for objects representing a database
trigger. The methods of an instanciated object do allow to access the
information within a database's data dictionary and to represent them as
SQL create statements and the like using the proper SQL dialect.

Constructors
------------

     $trigger = SQL::Schema::Trigger->new(%attr);

   The new method instanciates a trigger object. The object is an in
memory representation of a (possible) database trigger.  The attributes
are given as key value pairs by the hash %attr.  Possible keys are:

     key               required?   value description

     trigger_name      yes         the name of the trigger (without a
                                   preceeding schema name)

     description       yes         the "head" of the trigger's create statement
                                   excluding `create trigger ' resp.
                                   `create or replace trigger ' but including
                                   everything from the trigger's name on up to
                                   (but not including) the when_clause

     when_clause       no          the when clause of the trigger everything
                                   from `when' until the start of the
                                   PL/SQL block (remember: the PL/SQL block
                                   starts with `declare' or `begin')

     trigger_body      yes         the PL/SQL block of the trigger including
                                   `declare', `begin' and `end;'

   All the keys correspond to the columns with the same name from Oracle's
data dictionary view `user_triggers'.

     $trigger = SQL::Schema::Trigger->select($dbh,$name);

   The select method fetches the attributes required by new from the
database and returns the trigger object. (It calls new internally.)

   If the trigger with the name $name could not be found within the
database, the method returns undef.

   The method's arguments are as follows:

$dbh
     A database handle as defined by `DBI(3)' in this node.

$name
     The name of the trigger without preceeding schema name.

Methods
-------

   The following attribute methods do return the current value of the
attributes (as handed over to the new method):

     $name = $trigger->name;
     $description = $trigger->description;
     $when_clause = $trigger->when_clause;
     $trigger_body = $trigger->trigger_body;

     $sql = $trigger->create_statement;
     $sql = "$trigger";

   Returns a string containing an SQL statements for creation of this
trigger. This method is overloaded with the string operator.  So the two
examples above are equivalent.

     $sql = $trigger->drop_statement;

   Returns a string containing an SQL statement that would drop this
trigger.

AUTHOR AND COPYRIGHT
====================

     SQL::Schema::Trigger is Copyright (C) 2000,
       Torsten Hentschel
       Windmuehlenweg 47
       44141 Dortmund
       Germany

     Email: todd@bayleys.ping.de

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `DBI(3)' in this node, `SQL::Schema(3)' in this node,

A database view
***************

NAME
====

   SQL::Schema::View - A database view

SYNOPSIS
========

     my $view = SQL::Schema::View->new(%attr);

     my $sql = $view->create_statement;
     print $sql;

     print "$view";

DESCRIPTION
===========

   `SQL::Schema::View' is a class for objects representing a database
view. The methods of an instanciated object do allow to access the
information within a database's data dictionary and to represent them as
SQL create statements and the like using the proper SQL dialect.

Constructors
------------

     $view = SQL::Schema::View->new(%attr);

   The new method instanciates a view object. The object is an in memory
representation of a (possible) database view.  The attributes are given as
key value pairs by the hash %attr.  Possible keys are:

     key              required?   value description

     view_name        yes         the name of the view (without a
                                  preceeding schema name)

     aliases          no          a reference to a list of names
                                  for the columns returned by the view

     subquery         yes         the SQL text of the subquery

     constraint_name  no          the name of the constraint for the
                                  "with check option"; WARNING: The
                                  subquery has to end with the text
                                  'with check option ' to make this work
                                  correctly

     $view = SQL::Schema::View->select($dbh,$name);

   The select method fetches the attributes required by new from the
database and returns the view object. (It calls new internally.)

   If the view with the name $name could not be found within the database,
the method returns undef.

   The method's arguments are as follows:

$dbh
     A database handle as defined by `DBI(3)' in this node.

$name
     The name of the view without preceeding schema name.

Methods
-------

   The following attribute methods do return the current value of the
attributes (as handed over to the new method):

     $name = $view->name;
     @aliases = $view->alisaes;
     $subquery = $view->subquery;
     $constraint_name = $view->constraint_name;

     $sql = $view->create_statement;
     $sql = "$view";

   Returns a string containing an SQL statements for creation of this
view. This method is overloaded with the string operator.  So the two
examples above are equivalent.

     $sql = $view->drop_statement;

   Returns a string containing an SQL statement that would drop this view.

AUTHOR AND COPYRIGHT
====================

     SQL::Schema::View is Copyright (C) 2000,
       Torsten Hentschel
       Windmuehlenweg 47
       44141 Dortmund
       Germany

     Email: todd@bayleys.ping.de

     All rights reserved.

     You may distribute this package under the terms of either the GNU
     General Public License or the Artistic License, as specified in the
     Perl README file.

SEE ALSO
========

   `DBI(3)' in this node, `SQL::Schema(3)' in this node,

SQL parsing and processing engine
*********************************

NAME
====

   SQL::Statement - SQL parsing and processing engine

SYNOPSIS
========

     require SQL::Statement;

     # Create a parser
     my($parser) = SQL::Statement->new('Ansi');

     # Parse an SQL statement
     $@ = '';
     my ($stmt) = eval {
         SQL::Statement->new("SELECT id, name FROM foo WHERE id > 1",
     			    $parser);
     };
     if ($@) {
     	die "Cannot parse statement: $@";
     }

     # Query the list of result columns;
     my $numColums = $stmt->columns();  # Scalar context
     my @columns = $stmt->columns();    # Array context
     # @columns now contains SQL::Statement::Column instances

     # Likewise, query the tables being used in the statement:
     my $numTables = $stmt->tables();   # Scalar context
     my @tables = $stmt->tables();      # Array context
     # @tables now contains SQL::Statement::Table instances

     # Query the WHERE clause; this will retrieve an
     # SQL::Statement::Op instance
     my $where = $stmt->where();

     # Evaluate the WHERE clause with concrete data, represented
     # by an SQL::Eval object
     my $result = $stmt->eval_where($eval);

     # Execute a statement:
     $stmt->execute($data, $params);

DESCRIPTION
===========

   For installing the module, see `"INSTALLATION"' in this node below.

   The SQL::Statement module implements a small, abstract SQL engine. This
module is not usefull itself, but as a base class for deriving concrete
SQL engines. The implementation is designed to work fine with the DBI
driver DBD::CSV, thus probably not so well suited for a larger
environment, but I'd hope it is extendable without too much problems.

   By parsing an SQL query you create an SQL::Statement instance. This
instance offers methods for retrieving syntax, for WHERE clause and
statement evaluation.

Creating a parser object
------------------------

   What's accepted as valid SQL, depends on the parser object. There is a
set of so-called features that the parsers may have or not. Usually you
start with a builtin parser:

     my $parser = SQL::Parser->new($name, [ \%attr ]);

   Currently two parsers are builtin: The *Ansi* parser implements a proper
subset of ANSI SQL. (At least I hope so. :-) The SQL::Statement parser is
used by the DBD:CSV driver.

   You can query or set individual features. Currently available are:

create.type_blob
create.type_real
create.type_text
     These enable the respective column types in a *CREATE TABLE* clause.
     They are all disabled in the *Ansi* parser, but enabled in the
     SQL::Statement parser. Example:

select.join
     This enables the use of multiple tables in a SELECT statement, for
     example

          SELECT a.id, b.name FROM a, b WHERE a.id = b.id AND a.id = 2

   To enable or disable a feature, for example select.join, use the
following:

     # Enable feature
     $parser->feature("select", "join", 1);
     # Disable feature
     $parser->feature("select", "join", 0);

   Of course you can query features:

     # Query feature
     my $haveSelectJoin = $parser->feature("select", "join");

   The new method allows a shorthand for setting features. For example,
the following is equivalent to the SQL::Statement parser:

     $parser = SQL::Statement->new('Ansi',
     				{ 'create' => { 'type_text' => 1,
     						'type_real' => 1,
     						'type_blob' => 1 },
     				  'select' => { 'join' => 0 }});

Parsing a query
---------------

   A statement can be parsed with

     my $stmt = SQL::Statement->new($query, $parser);

   In case of syntax errors or other problems, the method throws a Perl
exception. Thus, if you want to catch exceptions, the above becomes

     $@ = '';
     my $stmt = eval { SQL::Statement->new($query, $parser) };
     if ($@) { print "An error occurred: $@"; }

   The accepted SQL syntax is restricted, though easily extendable. See
`SQL syntax' in this node below. See `Creating a parser object' in this
node above.

Retrieving query information
----------------------------

   The following methods can be used to obtain information about a query:

command
     Returns the SQL command, currently one of SELECT, INSERT, UPDATE,
     DELETE, CREATE or DROP, the last two referring to *CREATE TABLE* and
     *DROP TABLE*. See `SQL syntax' in this node below. Example:

          my $command = $stmt->command();

columns
          my $numColumns = $stmt->columns();  # Scalar context
          my @columnList = $stmt->columns();  # Array context
          my($col1, $col2) = ($stmt->columns(0), $stmt->columns(1));

     This method is used to retrieve column lists. The meaning depends on
     the query command:

          SELECT $col1, $col2, ... $colN FROM $table WHERE ...
          UPDATE $table SET $col1 = $val1, $col2 = $val2, ...
              $colN = $valN WHERE ...
          INSERT INTO $table ($col1, $col2, ..., $colN) VALUES (...)

     When used without arguments, the method returns a list of the columns
     $col1, $col2, ..., $colN, you may alternatively use a column number
     as argument. Note that the column list may be empty, like in

          INSERT INTO $table VALUES (...)

     and in CREATE or DROP statements.

     But what does "returning a column" mean? It is returning an
     SQL::Statement::Column instance, a class that implements the methods
     table and name, both returning the respective scalar. For example,
     consider the following statements:

          INSERT INTO foo (bar) VALUES (1)
          SELECT bar FROM foo WHERE ...
          SELECT foo.bar FROM foo WHERE ...

     In all these cases exactly one column instance would be returned with

          $col->name() eq 'bar'
          $col->table() eq 'foo'

tables
          my $tableNum = $stmt->tables();  # Scalar context
          my @tables = $stmt->tables();    # Array context
          my($table1, $table2) = ($stmt->tables(0), $stmt->tables(1));

     Similar to columns, this method returns instances of
     `SQL::Statement::Table'.  For UPDATE, DELETE, INSERT, CREATE and
     DROP, a single table will always be returned.  SELECT statements can
     return more than one table, in case of joins. Table objects offer a
     single method, name which returns the table name.

params
          my $paramNum = $stmt->params();  # Scalar context
          my @params = $stmt->params();    # Array context
          my($p1, $p2) = ($stmt->params(0), $stmt->params(1));

     The params method returns information about the input parameters used
     in a statement. For example, consider the following:

          INSERT INTO foo VALUES (?, ?)

     This would return two instances of SQL::Statement::Param. Param
     objects implement a single method, `$param-'num()>, which retrieves
     the parameter number. (0 and 1, in the above example). As of now, not
     very usefull ... :-)

row_values
          my $rowValueNum = $stmt->row_values(); # Scalar context
          my @rowValues = $stmt->row_values();   # Array context
          my($rval1, $rval2) = ($stmt->row_values(0),
          			  $stmt->row_values(1));

     This method is used for statements like

          UPDATE $table SET $col1 = $val1, $col2 = $val2, ...
              $colN = $valN WHERE ...
          INSERT INTO $table (...) VALUES ($val1, $val2, ..., $valN)

     to read the values $val1, $val2, ... $valN. It returns scalar values
     or SQL::Statement::Param instances.

Order
          my $orderNum = $stmt->order();   # Scalar context
          my @order = $stmt->order();      # Array context
          my($o1, $o2) = ($stmt->order(0), $stmt->order(1));

     In SELECT statements you can use this for looking at the ORDER
     clause. Example:

          SELECT * FROM FOO ORDER BY id DESC, name

     In this case, order could return 2 instances of SQL::Statement::Order.
     You can use the methods `$o->table()', `$o->column()' and
     `$o->desc()' to examine the order object.

where
          my $where = $stmt->where();

     This method is used to examine the syntax tree of the WHERE clause.
     It returns undef (if no WHERE clause was used) or an instance of
     SQL::Statement::Op. The Op instance offers 4 methods:

    op
          returns the operator, one of AND, `OR', =, `<>', `>=', `>',
          `<=', `<', `LIKE', `CLIKE' or `IS'.

    arg1

    arg2
          returns the left-hand and right-hand sides of the operator. This
          can be a scalar value, an SQL::Statement::Param object or yet
          another SQL::Statement::Op instance.

    neg
          returns a TRUE value, if the operation result must be negated
          after evalution.

     To evaluate the WHERE clause, fetch the topmost Op instance with the
     where method. Then evaluate the left-hand and right-hand side of the
     operation, perhaps recursively. Once that is done, apply the operator
     and finally negate the result, if required.

   To illustrate the above, consider the following WHERE clause:

     WHERE NOT (id > 2 AND name = 'joe') OR name IS NULL

   We can represent this clause by the following tree:

     (id > 2)   (name = 'joe')
            \   /
               NOT         AND
                \      (name IS NULL)
                 \    /
                   OR

   Thus the WHERE clause would return an SQL::Statement::Op instance with
the op() field set to 'OR'. The arg2() field would return another
SQL::Statement::Op instance with arg1() being the SQL::Statement::Column
instance representing id, the arg2() field containing the value undef
(NULL) and the op() field being 'IS'.

   The arg1() field of the topmost Op instance would return an Op instance
with op() eq 'AND' and neg() returning TRUE. The arg1() and arg2() fields
would be Op's representing "id > 2" and "name = 'joe'".

   Of course there's a ready-for-use method for WHERE clause evaluation:

Evaluating a WHERE clause
-------------------------

   The WHERE clause evaluation depends on an object being used for
fetching parameter and column values. Usually this can be an SQL::Eval
object, but in fact it can be any object that supplies the methods

     $val = $eval->param($paramNum);
     $val = $eval->column($table, $column);

   See SQL/Eval, for a detailed description of these
methods.  Once you have such an object, you can call a

     $match = $stmt->eval_where($eval);

Evaluating queries
------------------

   So far all methods have been concrete. However, the interface for
executing and evaluating queries is abstract. That means, for using them
you have to derive a subclass from SQL::Statement that implements at least
certain missing methods and/or overwrites others. See the test.pl script
for an example subclass.

   Something that all methods have in common is that they simply throw a
Perl exception in case of errors.

execute
     After creating a statement, you must execute it by calling the execute
     method. Usually you put an eval statement around this call:

          $@ = '';
          my $rows = eval { $self->execute($data); };
          if ($@) { die "An error occurred!"; }

     In case of success the method returns the number of affected rows or
     -1, if unknown. Additionally it sets the attributes

          $self->{'NUM_OF_FIELDS'}
          $self->{'NUM_OF_ROWS'}
          $self->{'data'}

     the latter being an array ref of result rows. The argument $data is
     for private use by concrete subclasses and will be passed through to
     all methods. (It is intentionally not implemented as attribute:
     Otherwise we might well become self referencing data structures which
     could prevent garbage collection.)

CREATE
DROP
INSERT
UPDATE
DELETE
SELECT
     Called by execute for doing the real work. Usually they create an
     SQL::Eval object by calling `$self->open_tables()', call
     `$self->verify_columns()' and then do their job. Finally they return
     the triple

          ($self->{'NUM_OF_ROWS'}, $self->{'NUM_OF_FIELDS'},
           $self->{'data'})

     so that execute can setup these attributes. Example:

          ($self->{'NUM_OF_ROWS'}, $self->{'NUM_OF_FIELDS'},
           $self->{'data'}) = $self->SELECT($data);

verify_columns
     Called for verifying the row names that are used in the statement.
     Example:

          $self->verify_columns($eval, $data);

open_tables
     Called for creating an SQL::Eval object. In fact what it returns
     doesn't need to be derived from SQL::Eval, it's completely sufficient
     to implement the same interface of methods. See SQL/Eval,
     for details. The arguments $data, `$createMode' and
     `$lockMode' are corresponding to those of
     SQL::Eval::Table::open_table and usually passed through. Example:

          my $eval = $self->open_tables($data, $createMode, $lockMode);

     The eval object can be used for calling `$self-'verify_columns> or
     `$self-'eval_where>.

open_table
     This method is completely abstract and *must* be implemented by
     subclasses.  The default implementation of `$self-'open_tables> calls
     this method for any table used by the statement. See the test.pl
     script for an example of imlplementing a subclass.

SQL syntax
==========

   The SQL::Statement module is far away from ANSI SQL or something
similar, it is designed for implementing the DBD::CSV module. See
`DBD::CSV(3)' in this node.

   I do not want to give a formal grammar here, more an informal
description: Read the statement definition in sql_yacc.y, if you need
something precise.

   The main lexical elements of the grammar are:

Integers
Reals
     Syntax obvious

Strings
     Surrounded by either single or double quotes; some characters need to
     be escaped with a backslash, in particular the backslash itself (\\),
     the NUL byte (\0), Line feeds (\n), Carriage return (\r), and the
     quotes (\' or \").

Parameters
     Parameters represent scalar values, like Integers, Reals and Strings
     do. However, their values are read inside Execute() and not inside
     Prepare(). Parameters are represented by question marks (?).

Identifiers
     Identifiers are table or column names. Syntactically they consist of
     alphabetic characters, followed by an arbitrary number of alphanumeric
     characters. Identifiers like SELECT, INSERT, INTO, ORDER, BY, WHERE,
     ... are forbidden and reserved for other tokens.

   What it offers is the following:

CREATE
------

   This is the CREATE TABLE command:

     CREATE TABLE $table ( $col1 $type1, ..., $colN $typeN,
                           [ PRIMARY KEY ($col1, ... $colM) ] )

   The column names are $col1, ... $colN. The column types can be INTEGER,
`CHAR(n)', `VARCHAR(n)', REAL or `BLOB'. These types are currently
completely ignored. So is the (optional) `PRIMARY KEY' clause.

DROP
----

   Very simple:

     DROP TABLE $table

INSERT
------

   This can be

     INSERT INTO $table [ ( $col1, ..., $colN ) ]
         VALUES ( $val1, ... $valN )

DELETE
------

     DELETE FROM $table [ WHERE $where_clause ]

   See `SELECT' in this node below for a decsription of $where_clause

UPDATE
------

     UPDATE $table SET $col1 = $val1, ... $colN = $valN
         [ WHERE $where_clause ]

   See `SELECT' in this node below for a decsription of $where_clause

SELECT
------

     SELECT [DISTINCT] $col1, ... $colN FROM $table
         [ WHERE $where_clause ] [ ORDER BY $ocol1, ... $ocolM ]

   The $where_clause is based on boolean expressions of the form $val1 $op
$val2, with $op being one of '=', '<>', '>', '<', '>=', '<=', 'LIKE',
'CLIKE' or IS. You may use OR, AND and brackets to combine such boolean
expressions or NOT to negate them.

INSTALLATION
============

   Like most other Perl modules, you simply do a

     perl Makefile.PL
     make		(nmake or dmake, if you are using Win32)
     make test		(Let me know, if any tests fail)
     make install

   Known problems are:

   * Some flavours of SCO Unix don't seem to have alloca() or something
     similar.  I recommend using gcc or egcs for compiling Perl and the
     SQL::Statement module: Both compilers have a builtin alloca().

     Another option could be to use external alloca.c, for example

          http://www.pu.informatik.th-darmstadt.de/FTP/pub/pu/alloca.c
          http://www.cs.purdue.edu/homes/young/src2www-example/alloca.c.html

     I did test neither of them and cannot give detailed instructions for
     including them into the SQL::Statement module. However, it should be
     sufficient to compile alloca.c with the same instructions than, for
     example, sql_yacc.c and finally repeat the linker command by
     inserting alloca.o after sql_yacc.o.

     Note that I cannot modify the sources to work without alloca(), as it
     is the bison parser that's using alloca() and I don't have the bison
     generated code in my hands.

     My thanks to Theo Petersen, <theo@acsp.com>, for pointing out this
     problem and the possible workarounds.

INTERNALS
=========

   Internally the module is splitted into three parts:

Perl-independent C part
-----------------------

   This part, contained in the files `sql_yacc.y', `sql_data.h',
`sql_data.c' and `sql_op.c', is completely independent from Perl.  It
might well be used from within another script language, Tcl say, or from a
true C application.

   You probably ask, why Perl independence? Well, first of all, I think
this is a valuable target in itself. But the main reason was the
impossibility to use the Perl headers inside bison generated code. The
Perl headers export almost the complete Yacc interface to XS, for whatever
reason, thus redefining constants and structures created by your own bison
code. :-(

Perl-dependent C part
---------------------

   This is contained in `Statement.xs'. The both C parts communicate via a
C structure sql_stmt_t. In fact, an SQL::Statement object is nothing else
than a pointer to such a structure. The XS calls columns(), Table(),
where(), ... do nothing more than fetching data from this structure and
converting it to Perl objects. See `The sql_stmt_t structure' in this node
below for details on the structure.

Perl part
---------

   Besides some stub functions for retrieving statement data, this is
mainly the query processing with the exception of WHERE clause evaluation.

The sql_stmt_t structure
------------------------

   This structure is designed for optimal performance. A typical query
will be parsed with only 4 or 5 malloc() calls; in particular no memory
will be aquired for storing strings; only pointers into the query string
are used.

   The statement stores its tokens in the values array. The array elements
are of type sql_val_t, a union, that can represent the most interesting
tokens; for example integers and reals are stored in the data.i and data.d
parts of the union, strings are stored in the data.str part, columns in
the data.col part and so on. Arrays are allocated in chunks of 64
elements, thus a single malloc() will be usually sufficient for allocating
the complete array. Some types use pointers into the values array: For
example, operations are stored in an sql_op_t structure that containes
elements arg1 and arg2 which are pointers into the value table, pointing
to other operations or scalars. These pointers are stored as indices, so
that the array can be extended using realloc().

   The sql_stmt_t structure contains other arrays: columns, tables,
rowvals, order, ... representing the data returned by the columns(),
tables(), row_values() and order() methods. All of these contain pointers
into the values array, again stored as integers.

   Arrays are initialized with the _InitArray call in SQL_Statement_Prepare
and deallocated with _DestroyArray in SQL_Statement_Destroy. Array
elements are obtained by calling _AllocData, which returns an index.  The
number -1 is used for errors or as a NULL value.

The WHERE clause evaluation
---------------------------

   A WHERE clause is evaluated by calling SQL_Statement_EvalWhere(). This
function is in the Perl independent part, but it needs the possibility to
retrieve data from the Perl part, for example column or parameter values.
These values are retrieved via callbacks, stored in the sql_eval_t
structure. The field stmt->evalData points to such a structure. Of course
the calling method can extend the sql_eval_t structure (like eval_where in
Statement.xs does) to include private data not used by
SQL_Statement_EvalWhere.

Features
--------

   Different parsers are implemented via the sql_parser_t structure. This
is mainly a set of yes/no flags. If you'd like to add features, do the
following:

   First of all, extend the sql_parser_t structure. If your feature is
part of a certain statement, place it into the statements section, for
example "select.join". Otherwise choose a section like "misc" or
"general". (There's no particular for the section design, but structure
never hurts.)

   Second, add your feature to sql_yacc.y. If your feature needs to extend
the lexer, do it like this:

     if (FEATURE(misc, myfeature) {
     	/*  Scan your new symbols  */
     	...
     }

   See the *BOOL* symbol as an example.

   If you need to extend the parser, do it like this:

     my_new_rule:
     	/*  NULL, old behaviour, doesn't use my feature  */
         | my_feature
             { YFEATURE(misc, myfeature); }
     ;

   Thus all parsers not having FEATURE(misc, myfeature) set will produce a
parse error here. Again, see the BOOL symbol for an example.

   Third thing is to extend the builtin parsers. If they support your
feature, add a 1, otherwise a 0. Currently there are two builtin parsers:
The *ansiParser* in sql_yacc.y and the sqlEvalParser in Statement.xs.

   Finally add support for your feature to the `feature' method in
Statement.xs. That's it!

MULTITHREADING
==============

   The complete module code is reentrant. In particular the parser is
created with `%pure_parser'. See `bison(1)' in this node for details on
reentrant parsers. That means, the module is ready for multithreading, as
long as you don't share handles between threads. Read-only handles, for
example parsers, can even be shared.

   Statement handles cannot be shared among threads, at least not, if you
don't grant serialized access. Per-thread handles are always safe.

AUTHOR AND COPYRIGHT
====================

   This module is Copyright (C) 1998 by

     Jochen Wiedmann
     Am Eisteich 9
     72555 Metzingen
     Germany

     Email: joe@ispsoft.de
     Phone: +49 7123 14887

   All rights reserved.

   You may distribute this module under the terms of either the GNU
General Public License or the Artistic License, as specified in the Perl
README file.

SEE ALSO
========

   `DBI(3)' in this node, `DBD::CSV(3)' in this node

Perl interface to the SWISH-E search engine.
********************************************

NAME
====

   SWISH - Perl interface to the SWISH-E search engine.

SYNOPSIS
========

     use SWISH;

     $sh = SWISH->connect('Fork',
         prog     => '/usr/local/bin/swish-e',
         indexes  => 'index.swish-e',
         results  => sub { print $_[1]->as_string,"\n" },
     );

     die $SWISH::errstr unless $sh;

     $hits = $sh->query('metaname=(foo or bar)');

     print $hits ? "Returned $hits documents\n" : 'failed query:' . $sh->errstr . "\n";

     # Variations

     $sh = SWISH->connect('Fork',
         prog     => '/usr/local/bin/swish-e',
         indexes  => \@indexes,
         results  => \&results,      # callback
         headers  => \&headers,
         maxhits  => 200,
         timeout  => 20,
         -e       => undef,      # add just a switch
     );

     $sh = SWISH->connect('Library', %parameters );
     $sh = SWISH->connect('Library', \%parameters );

     $sh = SWISH->connect('Server',
         port     => $port_number,
         host     => $host_name,
         %parameters,
     );

     $hits = $sh->query( $query_string );
     $hits = $sh->query( query => $query_string );

     $hits = $sh->query(
         query       => $query_string,
         results     => \&results,
         headers     => \&headers,
         properties  => [qw/title subject/],
         sortorder   => 'subject',
         startnum    => 100,
         maxhits     => 1000,
     );

     $error_msg = $sh->error unless $hits;

     # Unusual, but might want to use in your headers() callback.
     $sh->abort_query;

     @raw_results = $sh->raw_query( \%query_settings );

     $r = $sh->index( '/path/to/config' );
     $r = $sh->index( \%indexing_settings );

     # If all config settings were stored in the index header
     $r = $sh->reindex;

     $header_array_ref = $sh->indexheaders;

     # returns words as swish sees them for indexing
     $search_words = $sh->swish_words( \$doc );

     $stemmed = $sh->stem_word( $word );

     $sh->disconnect;
     # or an alias:
     $sh->close;

DESCRIPTION
===========

   NOTE: This is alpha code and is not to be used in a production
environment.  Testing and feedback on using this module is *gratefully
appreciated*.

   This module provides a standard interface to the SWISH-E search engine.
With this interface your program can use SWISH-E in the standard
forking/exec method, or with the SWISH-E C library routines, and, if ever
developed, the SWISH-E server with only a small change.

   The idea is that you can change the way your program accesses a SWISH-E
index without having to change your code.  Much, that is.

METHODS
=======

   Most methods will take either a hash, or a reference to a hash as a
named parameter list.  Parameters set in the connect() method will be
defaults, with parameters in other methods overriding the defaults.

connect
     `$sh = SWISH->connect( $access_method, \%params );'

     The connect method uses the `$access_method' to initiate a connection
     with SWISH-E.  What that means depends on the access method.  The
     return value is an object used to access methods below, or undefined
     if failed.  Errors may be retrieved with the package variable
     $SWISH::errstr.

     The SWISH module will load the driver for the type of access
     specified in the access method, if available, by loading the
     `SWISH::$access_method module'.

     Parameters are described below in PARAMETERS, but must include the
     path to the swish binary program if using the File access_method and
     index file(s).  (index files?)

query
     `$hits = $sh->query( query => $query, \%parameters );'

     The query method executes a query and returns the number of hits
     found.  `$hits' is undefined if there is an error.  The last error
     may be retrieved with `$sh->error'.

     query can be passed a single scalar as the search string, a hash, or
     a reference to a hash.  Parameters passed override the defaults
     specified in the connect method.

          Examples:
              $hits = $sh->query( 'foo or bar' );
              $hits = $sh->query( 'subject=(foo or bar)' );
              $hits = $sh->query( query => 'foo or bar' );
              $hits = $sh->query( %parameters );
              $hits = $sh->query( \%parameters );

     It is recommended to use a callback function to receive the search
     results.  See headers below.

raw_query
     A raw_query returns a list containing every output line from the
     query, including index header lines.  This can generate a large list,
     so using query with a callback function is recommended.

          Example:
              @results = $sh->raw_query('foo');

indexheaders
     The indexheaders method accesses the headers from the last query
     call.  Since SWISH may return more than one set of headers (e.g. when
     searching multiple indexes), this method returns a reference to an
     array of hashes.

          Example:
              foreach my $header_set ( @{$sh->indexheaders} ) {
                  print "\nHeaders:\n";
                  print "$_:$header_set->{$_}\n" for sort keys %$header_set;
              }

abort_query
     Calling $sh->abort_query within your callback handlers (results and
     headers) will terminate the current request.  You could also probably
     just die() and get the same results.

index
     ** To Be Implemented **

     The index method creates a swish index file.  You may pass index
     either a path to a SWISH-E configuration file, or reference to a hash
     with the index parameters stored in name => value pairs.

     The parameters in the hash will be written to a temporary file before
     indexing in with the Fork method.  If passing a reference to a hash,
     you may include a key tempfile that specifies the location of the
     temporary file.  Otherwise, /tmp will be assumed.

     If a parameter is not passed it will look in the object for an
     attribute named *indexparam*

reindex
     ** To Be Implemented? **

     This is a wish list method.  The idea is all the indexing parameters
     would be stored in the header on an index so to all one would need to
     do to reindex is call swish with the name of the index file.

stem_word
     ** To Be Implemented **

     stem_word returns the stem of the word passed.  This may be left to a
     separate module, but could be require()d on the fly.  The swish
     stemming routine is needed to highlight search terms when the index
     contains stemmed words.

swish_words
     ** To Be Implemented? **

     swish_words takes a scalar or a reference to a scalar and tokenizes
     the words as swish would do during indexing. The return value is a
     reference to an array where each element is a token.  Each token is
     also a reference to an array where the first element is the word, and
     the second element is a flag indicating if this is an indexable word.
     Confused?

     This requires HTML::Parser (HTML::TokeParser?) to be installed.

     The point of this is for enable phrase highlighting.  You can read
     your source and, if lucky, highlight phrase found in searches.

          Example:
              $words = $sh->swish_words( 'This is a phrase of words' );
                                            0 1 2345   6  7 89  10

          $words->[0][0] is 'This'
          $words->[0][1] is 1 indicating that swish would have this indexed
          $words->[0][2] is 0 this is swish word zero
          $words->[0][3] is the stemmed version of 'This', if using stemming.

          $words->[1][0] is ' '
          $words->[1][1] is 0 indicating that swish would not index
          $words->[1][2] is undef (not a word)

          $words->[2][0] is 'is'
          $words->[2][1] is 0 indicating that swish would not index (stop word)
          $words->[2][2] is undef (not a word)

          $words->[6][0] is 'phrase'
          $words->[6][1] is 1 indicating that it is a swish word
          $words->[6][2] is 2 this is the second swish word
                            ('is' and 'a' are stop words)

ACCESS METHODS
==============

   Two access methods are available:  `Fork' and `Library'.

   The Fork method requires a prog parameter passed to the connect class
method.  This parameter specifies the location of the swish-e executable
program

   The *Library* method does not require any special parameters, but does
require that the SWISH::Library module is installed and can be found
within @INC.

   The Server method is a proposed method to access a SWISH-E server.
Required parameters may include port, host, user, and password to gain
access to the SWISH-E server.

PARAMETERS
==========

   Parameters can be specified when starting a swish connection.  The
parameters are stored as defaults within the object and will be used on
each query, unless other overriding parameters are specified in an
individual method call.

   Most parameters have been given longer names (below).  But, any valid
parameter may be specified by using the standard dash followed by a
letter.  That is:

     maxhits => 100,

   is the same as

     -m      => 100,

   And to add just a switch without a parameter:     -e      => undef,

   Keep in mind that not all switches may work with all access methods.
The swish binary may have different options than the swish library.

prog
     prog defines the path to the swish executable.  This is only used in
     the Fork access method.

          Example:
              $parameters{ path } = '/usr/local/bin/swish-e';

indexes
     indexes defines the index files used in the next query or raw_query
     operation.

          Examples:
              $parameters{ indexes } = '/path/to/index.swish-e';
              $parameters{ indexes } = ['/path/to/index.swish-e', '/another/index'];

query
     query defines the search words (-w switch for SWISH-E)

          Example:
              $parameters{ query } = 'keywords=(apples or oranges) and subject=(trees)';

tags or context
     tags (or the alias context) is a string that defines where to look in
     a HTML document (-t switch)

properties
     properties defines which properties to return in the search results.
     Properties must be defined during indexing.  You must pass an array
     reference if using more than one property.

          Examples:
              $sh = query( query => 'foo', properties => 'title' );
              $sh = query( query => 'foo', properties => [qw/title subject/] );

maxhits
     Define the maximum number of results to return.  Currently, If you
     specify more than one index file maxhits is *per index file*.

startnum
     Defines the starting number in the results.  This is used for
     generating paged results.  Should there be pagesize and pagenum
     parameters?

sortorder
     Sorts the results based on properties listed.  Properties must be
     defined during indexing.  You may specify ascending or descending
     sorts in future version of swish.

          Example:
              $parameters{ sortorder } = 'subject';

          # under developement
          $parameters{ sortorder } = [qw/subject category/];
          $parameters{ sortorder } = [qw/subject asc category desc/];

start_date
     ** Not implemented **

     Specify a starting dates in unix seconds.  Only results after this
     date will be returned.

end_date
     ** Not implemented **

     Ending date in unix seconds.

results
     results defines a callback subroutine.  This routine is called for
     each result returned by a query.

          Example:
              $parameters{ results } = \&display_results
              $parameters{ results } = sub { print $_[1]->file, "\n" };

     Two paramaters are passed: the current search object (created by
     connect) and an object blessed into the SWISH::Results class.

          Example:

          sub display_results {
              my ($sh, $hit) = @_;

          # SWISH::Results attributes
          my @show = qw/score file title size position total_hits/;

          my %results = map { ($_, $hit->$_) } @show;
          my @properties = @{$hit->{properties}} if $hit->{properties};
          print join( ':', @results{ @show }, @properties ), "\n";
                  }

     The callback routines (results and headers) are called while inside
     an eval block.  If you die within your handlers the program will NOT
     exit, but any message you pass to die() will be available in
     $sh->errstr.  In general, do as little as possible with your callback
     routines.

     The SWISH::Results class is currently within the SWISH module.  This
     may change.

headers
     headers defines a callback subroutine.  This routine is called for
     each result returned by a query.

          Example:
              $parameters{ headers } = \&headers;

     Your subroutine is called with three parameters: the current object,
     and the header and value.

          sub headers {
              my ( $sh, $header, $value ) = @_;
              print "$header: $value\n";
          }

     In general, it will be better to call the headers method.

timeout
     timeout is the number of seconds to wait before aborting a query
     request.  Don't spend too much time in your results callback routine
     if you are using a timeout.  Timeout is emplemented as a $SIG{ALRM}
     handler and funny things happen with perl's signal handlers.

TO DO
=====

   How to detect a new index if library holds the file open?

   Is it ok to change index files on the same object?  Does the library
keep the index file open between requests?

   Interface for Windows platform?

SEE ALSO
========

   http://sunsite.berkeley.edu/SWISH-E/

AUTHOR
======

   Bill Moseley <moseley@hank.org>

Perl extension for accessing the SWISH-E search engine via a fork/exec.
***********************************************************************

NAME
====

   SWISH::Fork - Perl extension for accessing the SWISH-E search engine
via a fork/exec.

SYNOPSIS
========

     use SWISH;

     $sh = SWISH->connect('Fork',
        prog     => '/usr/local/bin/swish-e',
        indexes  => 'index.swish-e',
        results  => sub { print $_[1]->as_string,"\n" },
     );

DESCRIPTION
===========

   This module is a driver for the SWISH search engine using the forked
access method.  Please see SWISH, for usage instructions.

REQUIRED MODULES
----------------

   SWISH - the front-end for module for accessing the SWISH search engine.

   Sys::Signal - Use instead of `local $SIG{ALRM}' to restore signal
handlers.  Should be fixed in Perl 5.6.1

   Symbol - localized file handles (standard module)

AUTHOR
======

   Bill Moseley - moseley@hank.org

SEE ALSO
========

   See SWISH,

Perl extension for stemming words using a modified version of the  Stem routine from the SWISH search engine.  (http://sunsite.berkeley.edu/SWISH-E/)
*****************************************************************************************************************************************************

NAME
====

   Stemmer - Perl extension for stemming words using a modified version of
the Stem routine from the SWISH search engine.
(http://sunsite.berkeley.edu/SWISH-E/)

SYNOPSIS
========

     use SWISH::Stemmer;
     $stemmed_word = SwishStem( $word );

DESCRIPTION
===========

   This module provides access to the Stem() function used in SWISH-E to
stem words.  This module is needed if you wish to highlight words in
source documents.

   Not that this module includes the stemmer.c function from the SWISH-E
distribution.  You should make sure that the stemmer.c file contained here
is closely matched to the stemmer.c module in the SWISH-E distribution.

   Also, there is a SWISH-E library that will contain the Stem() and
SwishStem() functions.  So you may be able to access that library instead
of using this module.  Check the SWISH-E discussion list for more info.

     Purpose:    Implementation of the Porter stemming algorithm documented
                 in: Porter, M.F., "An Algorithm For Suffix Stripping,"
                 Program 14 (3), July 1980, pp. 130-137.

     Provenance: Written by B. Frakes and C. Cox, 1986.
                 Changed by C. Fox, 1990.
                    - made measure function a DFA
                    - restructured structs
                    - renamed functions and variables
                    - restricted function and variable scopes
                 Changed by C. Fox, July, 1991.
                    - added ANSI C declarations
                    - branch tested to 90% coverage

     Notes:      This code will make little sense without the the Porter
                 article.  The stemming function converts its input to
                 lower case.

AUTHOR
======

   Bill Moseley used the stemmer.c from the Swish-e distribution for this
module.

SEE ALSO
========

   perl(1)

Compile and execute code in restricted compartments
***************************************************

NAME
====

   Safe - Compile and execute code in restricted compartments

SYNOPSIS
========

     use Safe;

     $compartment = new Safe;

     $compartment->permit(qw(time sort :browse));

     $result = $compartment->reval($unsafe_code);

DESCRIPTION
===========

   The Safe extension module allows the creation of compartments in which
perl code can be evaluated. Each compartment has

a new namespace
     The "root" of the namespace (i.e. "main::") is changed to a different
     package and code evaluated in the compartment cannot refer to
     variables outside this namespace, even with run-time glob lookups and
     other tricks.

     Code which is compiled outside the compartment can choose to place
     variables into (or share variables with) the compartment's namespace
     and only that data will be visible to code evaluated in the
     compartment.

     By default, the only variables shared with compartments are the
     "underscore" variables $_ and @_ (and, technically, the less
     frequently used %_, the _ filehandle and so on). This is because
     otherwise perl operators which default to $_ will not work and
     neither will the assignment of arguments to @_ on subroutine entry.

an operator mask
     Each compartment has an associated "operator mask". Recall that perl
     code is compiled into an internal format before execution.
     Evaluating perl code (e.g. via "eval" or "do 'file'") causes the code
     to be compiled into an internal format and then, provided there was
     no error in the compilation, executed.  Code evaluated in a
     compartment compiles subject to the compartment's operator mask.
     Attempting to evaluate code in a compartment which contains a masked
     operator will cause the compilation to fail with an error. The code
     will not be executed.

     The default operator mask for a newly created compartment is the
     ':default' optag.

     It is important that you read the Opcode(3) module documentation for
     more information, especially for detailed definitions of opnames,
     optags and opsets.

     Since it is only at the compilation stage that the operator mask
     applies, controlled access to potentially unsafe operations can be
     achieved by having a handle to a wrapper subroutine (written outside
     the compartment) placed into the compartment. For example,

          $cpt = new Safe;
          sub wrapper {
              # vet arguments and perform potentially unsafe operations
          }
          $cpt->share('&wrapper');

WARNING
=======

   The authors make *no warranty*, implied or otherwise, about the
suitability of this software for safety or security purposes.

   The authors shall not in any case be liable for special, incidental,
consequential, indirect or other similar damages arising from the use of
this software.

   Your mileage will vary. If in any doubt *do not use it*.

RECENT CHANGES
--------------

   The interface to the Safe module has changed quite dramatically since
version 1 (as supplied with Perl5.002). Study these pages carefully if you
have code written to use Safe version 1 because you will need to makes
changes.

Methods in class Safe
---------------------

   To create a new compartment, use

     $cpt = new Safe;

   Optional argument is (NAMESPACE), where NAMESPACE is the root namespace
to use for the compartment (defaults to "Safe::Root0", incremented for
each new compartment).

   Note that version 1.00 of the Safe module supported a second optional
parameter, MASK.  That functionality has been withdrawn pending deeper
consideration. Use the permit and deny methods described below.

   The following methods can then be used on the compartment object
returned by the above constructor. The object argument is implicit in each
case.

permit (OP, ...)
     Permit the listed operators to be used when compiling code in the
     compartment (in *addition* to any operators already permitted).

permit_only (OP, ...)
     Permit *only* the listed operators to be used when compiling code in
     the compartment (no other operators are permitted).

deny (OP, ...)
     Deny the listed operators from being used when compiling code in the
     compartment (other operators may still be permitted).

deny_only (OP, ...)
     Deny *only* the listed operators from being used when compiling code
     in the compartment (all other operators will be permitted).

trap (OP, ...)
untrap (OP, ...)
     The trap and untrap methods are synonyms for deny and permit
     respectfully.

share (NAME, ...)
     This shares the variable(s) in the argument list with the compartment.
     This is almost identical to exporting variables using the
     `Exporter(3)' in this node module.

     Each NAME must be the name of a variable, typically with the leading
     type identifier included. A bareword is treated as a function name.

     Examples of legal names are '$foo' for a scalar, '@foo' for an array,
     '%foo' for a hash, '&foo' or 'foo' for a subroutine and '*foo' for a
     glob (i.e.  all symbol table entries associated with "foo", including
     scalar, array, hash, sub and filehandle).

     Each NAME is assumed to be in the calling package. See share_from for
     an alternative method (which share uses).

share_from (PACKAGE, ARRAYREF)
     This method is similar to share() but allows you to explicitly name
     the package that symbols should be shared from. The symbol names
     (including type characters) are supplied as an array reference.

          $safe->share_from('main', [ '$foo', '%bar', 'func' ]);

varglob (VARNAME)
     This returns a glob reference for the symbol table entry of VARNAME in
     the package of the compartment. VARNAME must be the name of a
     variable without any leading type marker. For example,

          $cpt = new Safe 'Root';
          $Root::foo = "Hello world";
          # Equivalent version which doesn't need to know $cpt's package name:
          ${$cpt->varglob('foo')} = "Hello world";

reval (STRING)
     This evaluates STRING as perl code inside the compartment.

     The code can only see the compartment's namespace (as returned by the
     root method). The compartment's root package appears to be the
     `main::' package to the code inside the compartment.

     Any attempt by the code in STRING to use an operator which is not
     permitted by the compartment will cause an error (at run-time of the
     main program but at compile-time for the code in STRING).  The error
     is of the form "%s trapped by operation mask operation...".

     If an operation is trapped in this way, then the code in STRING will
     not be executed. If such a trapped operation occurs or any other
     compile-time or return error, then $@ is set to the error message,
     just as with an eval().

     If there is no error, then the method returns the value of the last
     expression evaluated, or a return statement may be used, just as with
     subroutines and *eval()*. The context (list or scalar) is determined
     by the caller as usual.

     This behaviour differs from the beta distribution of the Safe
     extension where earlier versions of perl made it hard to mimic the
     return behaviour of the eval() command and the context was always
     scalar.

     Some points to note:

     If the entereval op is permitted then the code can use eval "..." to
     'hide' code which might use denied ops. This is not a major problem
     since when the code tries to execute the eval it will fail because the
     opmask is still in effect. However this technique would allow clever,
     and possibly harmful, code to 'probe' the boundaries of what is
     possible.

     Any string eval which is executed by code executing in a compartment,
     or by code called from code executing in a compartment, will be eval'd
     in the namespace of the compartment. This is potentially a serious
     problem.

     Consider a function foo() in package pkg compiled outside a
     compartment but shared with it. Assume the compartment has a root
     package called 'Root'. If foo() contains an eval statement like eval
     '$foo = 1' then, normally, $pkg::foo will be set to 1.  If foo() is
     called from the compartment (by whatever means) then instead of
     setting $pkg::foo, the eval will actually set $Root::pkg::foo.

     This can easily be demonstrated by using a module, such as the Socket
     module, which uses eval "..." as part of an AUTOLOAD function. You can
     'use' the module outside the compartment and share an (autoloaded)
     function with the compartment. If an autoload is triggered by code in
     the compartment, or by any code anywhere that is called by any means
     from the compartment, then the eval in the Socket module's AUTOLOAD
     function happens in the namespace of the compartment. Any variables
     created or used by the eval'd code are now under the control of the
     code in the compartment.

     A similar effect applies to all runtime symbol lookups in code called
     from a compartment but not compiled within it.

rdo (FILENAME)
     This evaluates the contents of file FILENAME inside the compartment.
     See above documentation on the reval method for further details.

root (NAMESPACE)
     This method returns the name of the package that is the root of the
     compartment's namespace.

     Note that this behaviour differs from version 1.00 of the Safe module
     where the root module could be used to change the namespace. That
     functionality has been withdrawn pending deeper consideration.

mask (MASK)
     This is a get-or-set method for the compartment's operator mask.

     With no MASK argument present, it returns the current operator mask of
     the compartment.

     With the MASK argument present, it sets the operator mask for the
     compartment (equivalent to calling the deny_only method).

Some Safety Issues
------------------

   This section is currently just an outline of some of the things code in
a compartment might do (intentionally or unintentionally) which can have
an effect outside the compartment.

Memory
     Consuming all (or nearly all) available memory.

CPU
     Causing infinite loops etc.

Snooping
     Copying private information out of your system. Even something as
     simple as your user name is of value to others. Much useful
     information could be gleaned from your environment variables for
     example.

Signals
     Causing signals (especially SIGFPE and SIGALARM) to affect your
     process.

     Setting up a signal handler will need to be carefully considered and
     controlled.  What mask is in effect when a signal handler gets
     called?  If a user can get an imported function to get an exception
     and call the user's signal handler, does that user's restricted mask
     get re-instated before the handler is called?  Does an imported
     handler get called with its original mask or the user's one?

State Changes
     Ops such as chdir obviously effect the process as a whole and not just
     the code in the compartment. Ops such as rand and srand have a similar
     but more subtle effect.

AUTHOR
------

   Originally designed and implemented by Malcolm Beattie,
mbeattie@sable.ox.ac.uk.

   Reworked to use the Opcode module and other changes added by Tim Bunce
<`Tim.Bunce@ig.co.uk'>.

make a hole to the original main compartment in the Safe compartment
********************************************************************

NAME
====

   Safe::Hole - make a hole to the original main compartment in the Safe
compartment

SYNOPSIS
========

     use Safe;
     use Safe::Hole;
     $cpt = new Safe;
     $hole = new Safe::Hole;
     sub test { Test->test; }
     $Testobj = new Test;
     # $cpt->share('&test');  # alternate as next line
     $hole->wrap(\&test, $cpt, '&test');
     # ${$cpt->varglob('Testobj')} = $Testobj;  # alternate as next line
     $hole->wrap($Testobj, $cpt, '$Testobj');
     $cpt->reval('test; $Testobj->test;');
     print $@ if $@;
     package Test;
     sub new { bless {},shift(); }
     sub test { my $self = shift; $self->test2; }
     sub test2 { print "Test->test2 called\n"; }

DESCRIPTION
===========

     We can call outside defined subroutines from the Safe compartment
     using share(), or can call methods through the object that is copied into
     the Safe compartment using varglob(). But that subroutines or methods
     are executed in the Safe compartment too, so they cannot call another
     subroutines that are dinamically qualified with the package name such as
     class methods.
     Through Safe::Hole, we can execute outside defined subroutines in the
     original main compartment from the Safe compartment.

Methods
-------

new [NAMESPACE]
     Class method. Constructor.    NAMESPACE is the alternate root
     namespace that makes the compartment in which call() method execute
     the subroutine.  Default of NAMESPACE means 'main'. We use the
     default usually.

call $coderef [,@args]
     Object method.    Call the subroutine refered by $coderef in the
     compartment that is specified with constructor new. @args are passed
     to called $coderef.

wrap $ref [,$cpt ,$name]
     Object method.    If $ref is a code reference, this method returns
     the anonymous subroutine reference that calls $ref using call()
     method of Safe::Hole (see above).    If $ref is a class object, this
     method makes a wrapper class of that object and returns a new object
     of the wrapper class. Through the wrapper class, all original class
     methods called using call() method of Safe::Hole.    If $cpt as Safe
     object and $name as subroutine or scalar name specified, this method
     works like share() method of Safe. When $ref is a code reference
     $name must like '&subroutine'. When $ref is a object $name must like
     '$var'.    Name $name may not be same as referent of $ref. For
     example:   $hole->wrap(\&foo, $cpt, '&bar');   $hole->wrap(sub{...},
     $cpt, '&foo');   $hole->wrap($objfoo, $cpt, '$objbar');

root
     Object method.    Return the namespace that is specified with
     constructor new.

Warning
-------

   You MUST NOT share the Safe::Hole object with the Safe compartment. If
you do it the Safe compartment is NOT safe.

AUTHOR
======

   Sey Nakajima <sey@jkc.co.jp>

SEE ALSO
========

   Safe(3).

produces an array from a scalar value or array ref.
***************************************************

NAME
====

   Scalar::Listify - produces an array from a scalar value or array ref.

SYNOPSIS
========

     use Scalar::Listify;

     $text_scalar = 'text';
     $aref_scalar = [ 1.. 5 ];

     print join ':', listify $text_scalar; # => text
     print join ':', listify $aref_scalar; # => 1:2:3:4:5

DESCRIPTION
===========

   A lot of Perl code ends up with scalars having either a single scalar
value or a reference to an array of scalar values. In order to handle the
two conditions, one must check for what is in the scalar value before
getting on with one's task. Ie:

     $text_scalar = 'text';
     $aref_scalar = [ 1.. 5 ];

     print ref($text_scalar) ? (join ':', @$text_scalar) : $text_scalar;

   And this module is designed to address just that!

EXPORT
------

   listify() - listify takes a scalar as an argument and returns the value
of the scalar in a format useable in list contexts.

AUTHOR
======

   T. M. Brannon, <tbone@CPAN.org>

SEE ALSO
========

   perl(1).

A selection of general-utility scalar subroutines
*************************************************

NAME
====

   Scalar::Util - A selection of general-utility scalar subroutines

SYNOPSIS
========

     use Scalar::Util qw(blessed dualvar reftype weaken isweak);

DESCRIPTION
===========

   `Scalar::Util' contains a selection of subroutines that people have
expressed would be nice to have in the perl core, but the usage would not
really be high enough to warrant the use of a keyword, and the size so
small such that being individual extensions would be wasteful.

   By default `Scalar::Util' does not export any subroutines. The
subroutines defined are

blessed EXPR
     If EXPR evaluates to a blessed reference the name of the package that
     it is blessed into is returned. Otherwise undef is returned.

dualvar NUM, STRING
     Returns a scalar that has the value NUM in a numeric context and the
     value STRING in a string context.

          $foo = dualvar 10, "Hello";
          $num = $foo + 2;			# 12
          $str = $foo . " world";		# Hello world

isweak EXPR
     If EXPR is a scalar which is a weak reference the result is true.

reftype EXPR
     If EXPR evaluates to a reference the type of the variable referenced
     is returned. Otherwise undef is returned.

weaken REF
     REF will be turned into a weak reference. This means that it will not
     hold a reference count on the object it references. Also when the
     reference count on that object reaches zero, REF will be set to undef.

     This is useful for keeping copies of references , but you don't want
     to prevent the object being DESTROY-ed at it's usual time.

COPYRIGHT
=========

   Copyright (c) 1997-2000 Graham Barr <gbarr@pobox.com>. All rights
reserved.  This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

   except weaken and isweak which are

   Copyright (c) 1999 Tuomas J. Lukka <lukka@iki.fi>. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as perl itself.

BLATANT PLUG
============

   The weaken and isweak subroutines in this module and the patch to the
core Perl were written in connection  with the APress book `Tuomas J.
Lukka's Definitive Guide to Object-Oriented Programming in Perl', to avoid
explaining why certain things would have to be done in cumbersome ways.

OS independent interface to the Unix 'at' command
*************************************************

NAME
====

   Schedule::At - OS independent interface to the Unix 'at' command

SYNOPSIS
========

     require Schedule::At;

     Schedule::At::add(TIME => $string, COMMAND =>$string [, TAG =>$string]);
     Schedule::At::add(TIME => $string, FILE => $string [, TAG => $string])

     Schedule::At::remove(JOBID => $string);
     Schedule::At::remove(TAG => $string);

     %jobs = Schedule::At::getJobs();

DESCRIPTION
===========

   This modules provides an OS independent interface to 'at', the Unix
command that allows you to execute commands at a specified time.

Schedule::At::add
     Adds a new job to the at queue.

     You have to specify a TIME and a command to execute. The TIME has a
     common format: YYYYMMDDHHmm. Where *YYYY* is the year (4 digits), *MM*
     the month (01-12), *DD* is the day (01-31), *HH* the hour (00-23) and
     mm the minutes.

     The command is passed with the *COMMAND* or the FILE parameter.
     *COMMAND* can be used to pass the command as an string, and FILE to
     read the commands from a file.

     The optional parameter TAG serves as an application specific way to
     identify a job or a set of jobs.

     Returns 0 on success or a value != 0 if an error occurred.

Schedule::At::remove
     Remove an at job.

     You identify the job to be deleted using the *JOBID* parameter (an
     opaque string returned by the getJobs subroutine). You can also
     specify a job or a set of jobs to delete with the TAG parameter,
     removing all the jobs that have the same tag (as specified with the
     add subroutine).

     Returns 0 on success or a value != 0 if an error occurred.

Schedule::At::getJobs
     Returns a hash with all the current jobs or undef if an error
     occurred.  For each job the key is a JOBID (an OS dependent string
     that shouldn't be interpreted), and the value is a hash reference.

     This hash reference points to a hash with the keys:

    TIME
          An OS dependent string specifying the time to execute the command

    TAG
          The tag specified in the Schedule::At::add subroutine

EXAMPLES
========

     use Schedule::At;

     # 1
     Schedule::At::add (TIME => '199801181530', COMMAND => 'ls',
     	TAG => 'ScheduleAt');
     # 2
     Schedule::At::add (TIME => '199801181630', COMMAND => 'ls',
     	TAG => 'ScheduleAt');
     # 3
     Schedule::At::add (TIME => '199801181730', COMMAND => 'ls');

     # This will remove #1 and #2 but no #3
     Schedule::At::remove (TAG => 'ScheduleAt');

     my %atJobs = Schedule::At::getJobs();
     foreach my $job (values %atJobs) {
     	print "\t", $job->{JOBID}, "\t", $job->{TIME}, ' ',
     		($job->{TAG} || ''), "\n";
     }

AUTHOR
======

   Jose A. Rodriguez (josear@ac.upc.es)

cron-like scheduler for Perl subroutines
****************************************

NAME
====

   Cron - cron-like scheduler for Perl subroutines

SYNOPSIS
========

     use Schedule::Cron;

     # Subroutines to be called
     sub dispatcher {
       print "ID:   ",shift,"\n";
       print "Args: ","@_","\n";
     }

     sub check_links {
       # do something...
     }

     # Create new object with default dispatcher
     my $cron = new Schedule::Cron(\&dispatcher);

     # Load a crontab file
     $cron->load_crontab("/var/spool/cron/perl");

     # Add dynamically  crontab entries
     $cron->add_entry("3 4  * * *",ROTATE => "apache","sendmail");
     $cron->add_entry("0 11 * * Mon-Fri",\&check_links);

     # Run scheduler
     $cron->run(detach=>1);

DESCRIPTION
===========

   This  module provides  a simple  but complete  cron like scheduler.
I.e   this  modules   can   be  used   for periodically executing Perl
subroutines.  The dates and parameters  for   the  subroutines  to   be
called  are specified   with  a  format   known  as   crontab  entry
(`"METHODS"' in this node, `add_entry()' and `crontab(5)' in this node)

   The  philosophy  behind  `Schedule::Cron'  is  to  call subroutines
periodically from  within  one single  Perl program  instead  of  letting
`cron'  trigger  several (possibly different) perl  scripts. Everything
under one roof.  Furthermore  `Schedule::Cron' provides mechanism to
create crontab  entries dynamically, which isn't that easy with `cron'.

   `Schedule::Cron' knows  about all extensions  (well, at least all
extensions  I'm aware of, i.e those  of the so called  "Vixie" cron)  for
crontab  entries  like ranges including  'steps', specification of  month
and  days of the week by  name or coexistence of lists  and ranges in the
same  field.  And  even a bit  more (like  lists and ranges with symbolic
names).

METHODS
=======

$cron = new Schedule::Cron($dispatcher,[extra args])
     Creates  a new  `Cron' object.   `$dispatcher' is  a reference  to a
     subroutine, which  will be called by default.   `$dispatcher' will be
     invoked with the arguments parameter  provided in the crontab entry if
     no other subroutine is specified. This can be either a single argument
     containing  the  argument  parameter  literally  has  string  (default
     behavior)  or a  list  of  arguments when  using  the eval  option
     described below.

     The date  specifications must  be either provided  via a  crontab like
     file or added explicitly with `add_entry()' (`"add_entry"' in this
     node).

     extra_args  can  be  a   hash  or  hash  reference  for  additional
     arguments.  The following parameters are recognized:

          file => <crontab>  Load the crontab entries from <crontab>

          eval =>  1         Eval  the argument  parameter in  a crontab
                             entry   before   calling   the   subroutine
                             (instead    of   literally    calling   the
                             dispatcher  with the argument  parameter as
                             string

$cron->load_crontab($file)

$cron->load_crontab(file=>$file,[eval=>1])
     Loads and parses the crontab  file $file. The entries found in this
     file   will   be   added   to   the   current   time   table   with
     `$cron->add_entry'.

     The format of  the file consists of cron  commands containing of lines
     with at least 5 columns, whereas the first 5 columns specify the date.
     The rest of the line (i.e columns 6 and greater) contains the argument
     with which the dispatcher subroutine  will be called.  By default, the
     dispatcher will  be called with one single  string argument containing
     the  rest of  the line  literally.   Alternatively, if  you call  this
     method with  the optional argument  `eval=>1' (you must  then use the
     second  format shown above), the  rest of the line  will be evaled
     before used as argument for the dispatcher.

     For the format of the first 5 columns, please see `"add_entry"' in
     this node.

     Blank lines and lines starting with a `#' will be ignored.

     There's  no  way to  specify  another  subroutine  within the  crontab
     file.  All  calls   will  be  made  to  the   dispatcher  provided  at
     construction time.

     If    you   want    to    start   up    fresh,    you   should    call
     `$cron->clean_timetable()' before.

     Example of a crontab fiqw(le:)

          # The following line runs on every Monday at 2:34 am
          34 2 * * Mon  "make_stats"
          # The next line should be best read in with an eval=>1 argument
          *  * 1 1 *    { NEW_YEAR => '1',HEADACHE => 'on' }

$cron->add_entry($timespec,[arguments])
     Adds a new entry to the list of scheduled cron jobs.

     *Time and Date specification*

     `$timespec' is the  specification of the scheduled time in  crontab
     format  (`crontab(5)' in this node) which  contains five time and
     date fields. `$timespec' can be either a plain string, which
     contains a whitespace  separated time and date specification.
     Alternatively, `$timespec' can be a reference to an array containing
     the five elements for the date fields.

     The time and date  fields are (cited from `crontab(5)' in this node,
     "Vixie" cron):

          field          values
          =====          ======
          minute         0-59
          hour           0-23
          day of month   1-31
          month          1-12 (or as names)
          day of week    0-7 (0 or 7 is Sunday, or as names )

          A field may be an asterisk (*), which always stands for
          ``first-last''.

          Ranges of numbers are  allowed.  Ranges are two numbers
          separated  with  a  hyphen.   The  specified  range  is
          inclusive.   For example, 8-11  for an  ``hours'' entry
          specifies execution at hours 8, 9, 10 and 11.

          Lists  are allowed.   A list  is a  set of  numbers (or
          ranges)  separated by  commas.   Examples: ``1,2,5,9'',
          ``0-4,8-12''.

          Step  values can  be used  in conjunction  with ranges.
          Following a range with ``/<number>'' specifies skips of
          the  numbers value  through the  range.   For example,
          ``0-23/2'' can  be used in  the hours field  to specify
          command execution every  other hour (the alternative in
          the V7 standard is ``0,2,4,6,8,10,12,14,16,18,20,22'').
          Steps are  also permitted after an asterisk,  so if you
          want to say ``every two hours'', just use ``*/2''.

          Names can also  be used for the ``month''  and ``day of
          week''  fields.  Use  the  first three  letters of  the
          particular day or month (case doesn't matter).

          Note: The day of a command's execution can be specified
                by two fields  -- day of month, and  day of week.
                If both fields are restricted (ie, aren't *), the
                command will be run when either field matches the
                current  time.  For  example, ``30  4 1,15  * 5''
                would cause a command to be run at 4:30 am on the
                1st and 15th of each month, plus every Friday

     In addition, ranges or lists of names are allowed.

     Examples:

          "8  0 * * *"       ==> 8 minutes after midnight, every day
          "5 11 * * Sat,Sun" ==> at 11:05 on each Saturday and Sunday
          "0-59/5 * * * *"   ==> every five minutes
          "42 12 3 Feb Sat"  ==> at 12:42 on 3rd of February and on
                                 each Saturday in February

     *Command specification*

     The subroutine to be  executed when the the `$timespec' matches can
     be specified in several ways.

     First,  if the  optional `arguments'  are  lacking, the default
     dispatching  subroutine provided at construction time will be called
     without arguments.

     If the second parameter to this method is a reference to a
     subroutine,  this subroutine  will be used  instead of the dispatcher.

     Any additional parameters will  be given as arguments to the
     subroutine  to be executed.  You can also  specify a reference to an
     array instead of a list of parameters.

     You can also  use a named parameter list  provided as an hashref.
     The named parameters recognized are:

          subroutine      reference to subroutine to be executed
          sub

          arguments       reference to array containing arguments
          args            to be use when calling the subroutine

          eval            if  set, provide the  subroutine with
                          the  evaled string provided  with the
                          'arguments'      parameter.       The
                          evaluation     will     take    place
                          immediately (not  when the subroutine
                          is to be called)

     Examples:

          $cron->add_entry("* * * * *");
          $cron->add_entry("* * * * *","doit");
          $cron->add_entry("* * * * *",\&dispatch,"first",2,"third");
          $cron->add_entry("* * * * *",{'subroutine' => \&dispatch,
          				 'arguments'  => [ "first",2,"third" ]});
          $cron->add_entry("* * * * *",{'subroutine' => \&dispatch,
          				 'arguments'  => '[ "first",2,"third" ]',
          				 'eval'       => 1});

$cron->run([options])
     This method starts the scheduler.

     When  called  without options,  this  method will  never return  and
     executes the  scheduled subroutine  calls as needed.

     Alternatively,  you can detach  the main  scheduler loop from the
     current process  (daemon mode). In  this case, the  pid  of  the
     forked  scheduler  process  will  be returned.

     The options  parameter specifies the  running mode of
     `Schedule::Cron'.  It can be  either a plain list which will be
     interpreted  as a hash or it  can be a reference to  hash. The
     following named  parameters (keys  of the provided hash) are
     recognized:

          detach    if set to one, detach the scheduler process
                    from the current process

          pid_file  if  running   in  daemon  mode,   name  the
                    optional file,  in which the  process id of
                    the scheduler process should be written. By
                    default, no PID File will be created.

     Examples:

          # Start  scheduler, detach  from current  process and
          # write  the  PID  of  the forked  scheduler  to  the
          # specified file
          $cron->run(detach=>1,pid_file=>"/var/run/scheduler.pid");

          # Start scheduler and wait forever.
          $cron->run();

$cron->clean_timetable()
     Remove all scheduled entries

$cron->check_entry($id)
     Check, whether the given ID is already registered in the timetable.
     A ID is the first argument in the argument parameter of the a crontab
     entry.

     Returns (one of) the index in the  timetable (can be 0, too) if the ID
     could be found or undef otherwise.

     Example:

          $cron->add_entry("* * * * *","ROTATE");
          .
          .
          defined($cron->check_entry("ROTATE")) || die "No ROTATE entry !"

$cron->get_next_execution_time($cron_entry,[$ref_time])
     Well, this is mostly an internal method, but it might be useful on
     its own.

     The purpose of this method is to calculate the next execution time
     from a specified crontab entry

     Parameters:

          $cron_entry  The crontab entry as specified in L<"add_entry">
          $ref_time    the reference time for which the next time should be
                       searched which matches $cron_entry. By default, take
                       the current time

     This method returns the number of epoch-seconds of the next matched
     date for `$cron_entry'.

     Since I suspect, that this calculation of the next execution time
     might fail in some circumstances (bugs are lurking everywhere ;-) an
     additional interactive method `bug()' is provided for checking
     crontab entries against your expected output. Refer to the top-level
     README for additional usage information for this method.

TODO
====

   * Provide a `reload()' method for reexaming the crontab file

   * Clean up `get_next_execution_time()' and give it at least some
     rational grounding ;-)

   * Provide support for systems without fork() via `OS::Process'

   * Add logging

COPYRIGHT
=========

   Copyright 1999,2000 Roland Huss.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

     ...roland

Load distribution and status across multiple host machines
**********************************************************

NAME
====

   Schedule::Load - Load distribution and status across multiple host
machines

SYNOPSIS
========

     # Get per-host or per top process information
     use Schedule::Load::Hosts;
     foreach my $host ($hosts->hosts) {
         printf $host->hostname " is on our network\n";
     }

     # Choose hosts
     use Schedule::Load::Schedule;
     my $scheduler = Schedule::Load::Schedule->fetch();
     print "Best host for a new job: ", $scheduler->best();

     # user access
     rtop
     rschedule reserve <hostname>

DESCRIPTION
===========

   This package provides useful utilities for load distribution and status
across multiple machines in a network.  To just see what is up in the
network, see the rschedule or `rtop', `rloads' or `rhosts' commands.

   The system is composed of four unix programs (each also with a
underlying Perl module):

slreportd
     slreportd is run on every host in the network, usually started with a
     init.d script.  It reports itself to the slchoosed daemon
     periodically, and is responsible for checking loading and top
     processes specific to the host that it runs on.

     slreportd may also be invoked with some variables set.  This allows
     static host information, such as class settings to be passed to
     applications.

slchoosed
     slchoosed is run on one host in the network.  It collects connections
     from the slreportd reporters, and maintains a internal database of the
     entire network.  User clients also connect to the chooser, which then
     gets updated information from the reporters, and returns the
     information to the user client.  As the chooser has the entire
     network state, it can also choose the best host across all CPUs in
     the network.

rschedule
     rschedule is a command line interface to this package.  It and the
     aliases `rtop', `rhosts', and `rloads' report the current state of the
     network including hosts and top loading.  rschedule also allows
     reserving hosts and setting the classes of the machines, as described
     later.

slpolice
     slpolice is a optional client daemon which is run as a `cron' job.
     When a user process has over a hour of CPU time, it nices that process
     and sends mail to the user.  It is intended as a example which can be
     used directly or changed to suit the system manager preferences.

MODULES
=======

Schedule::Load::Hosts
     Schedule::Load::Hosts provides the connectivity to the slchoosed
     daemon, and accessors to load and modify that information.

Schedule::Load::Schedule
     Schedule::Load::Schedule provides functions to choose the best host
     for a new job, reserving hosts, and for setting what hosts specific
     classes of jobs can run on.

Schedule::Load::Reporter
     Schedule::Load::Reporter implements the internals of slreportd.

Schedule::Load::Chooser
     Schedule::Load::Chooser implements the internals of slchoosed.

RESERVATIONS
============

   Occasionally clusters have members that are only to be used by specific
people, and not for general use.  A host may be reserved with `rschedule
reserve'.  This will place a special comment on the machine that
`rschedule hosts' will show.  Reservations also prevent the
Schedule::Load::Schedule package from picking that host as the best host.

   To be able to reserve a host, the reservable variable must be set on
that host.  This is generally done when slreportd is invoked on the
reservable host by using `slreportd reservable=1'.

CLASSES
=======

   Different hosts often have different properties, and jobs need to be
able select a host with certain properties, such as hardware or licensing
requirements.  Classes are generally just boolean variables which start
with class_.  Classes can be specified when slreportd is invoked on the
`slreportd class_foo=1'.  The class setting may be seen with `rschedule
classes' or may be read (as may any other variable) as a accessor from a
`Schedule::Load::Hosts::Host' object.

   Once a class is defined, a scheduling call can include it the classes
array that is passed when the best host is requested.  Only machines which
match one of those classes will be selected.

COMMAND COMMENTS
================

   `rschedule loads' or `rloads' show the command that is being run.  By
default this is the basename of the command invoked, as reported by the
operating system.  Often this is of little use, especially when the same
program is used by many people.  The `rschedule cmnd_comment' command or
`Schedule::Load::Schedule::cmnd_comment' function will assign a more
verbose command to that process id.  For example, we use dc_shell, and put
the name of the module being compiled into the comment, so rather then
several copies of the generic "dc_shell" we see "dc module", "dc module2",
etc.

HOLD KEYS
=========

   When a best host is picked for a new job, there is often a lag before a
process actually starts up on the selected host, and enough CPU time
elapses for that new process to claim CPU time.  To prevent another job
from scheduling onto that host during this lag, scheduling calls may
specify a hold key.  For a limited time, the load on the host will be
incremented.  When the job begins and a little CPU time has elapsed a
hold_release call may be made, (or the timer expires), which releases the
hold.  This will cause the load reported by `rschedule hosts' to
occasionally be higher then the number of jobs on that host.

FIXED LOADS
===========

   Some jobs have CPU usage patterns which contain long periods of low CPU
activity, such as when doing disk IO.  make is a typical example; the
parent make process uses little CPU time, but the children of the make pop
in and out of the cpu run list.

   When scheduling, it is useful to have such jobs always count as one (or
more) job, so that the idle time is not misinterpreted and another job
scheduled onto that machine.  Fixed loading allows all children of a given
parent to count as a given fixed CPU load.  Using make again, if the
parent make process is set as a fixed_load of one, the make and all
children will always count as one load, even if not consuming CPU
resources.  The `rschedule loads' or `rloads' command includes not only
top cpu users, but also all fixed loads.  If a child process is using CPU
time, that is what is displayed.  If no children are using appreciable CPU
time (~2%), the parent is the one shown in the loads list.

DISTRIBUTION
============

   The latest version is available from CPAN.

SEE ALSO
========

   User program for viewing loading, etc:

   rschedule

   Daemons:

   slreportd, slchoosed, slpolice

   Perl modules:

   Schedule::Load::Chooser, `Schedule::Load::Hosts::Host',
`Schedule::Load::Hosts::Proc', Schedule::Load::Hosts,
Schedule::Load::Reporter, Schedule::Load::Schedule

AUTHORS
=======

   Wilson Snyder <wsnyder@wsnyder.org>

Distributed load choosing daemon
********************************

NAME
====

   Schedule::Load::Chooser - Distributed load choosing daemon

SYNOPSIS
========

     use Schedule::Load::Chooser;

     Schedule::Load::Chooser->start(port=>1234,);

DESCRIPTION
===========

   Schedule::Load::Chooser on startup creates a daemon that clients can
connect to using the Schedule::Load package.

start ([parameter=>value ...]);
     Starts the chooser daemon.  Does not return.

PARAMETERS
==========

port
     The port number of slchoosed.  Defaults to 'slchoosed' looked up via
     /etc/services, else 1752.

dead_time
SEE ALSO
========

   `Schedule::Load', slchoosed

DISTRIBUTION
============

   This package is distributed via CPAN.

AUTHORS
=======

   Wilson Snyder <wsnyder@wsnyder.org>

Return host loading information across a network
************************************************

NAME
====

   Schedule::Load::Hosts - Return host loading information across a network

SYNOPSIS
========

     use Schedule::Load::Hosts;

     my $hosts = Schedule::Load::Hosts->fetch();
     $hosts->print_machines();
     $hosts->print_top();

     # Overall machine status
     my $hosts = Schedule::Load::Hosts->fetch();
     (my $FORMAT =    "%-12s    %4s     %4s   %6s%%       %5s    %s\n") =~ s/\s\s+/ /g;
     printf ($FORMAT, "HOST", "CPUs", "FREQ", "TotCPU", "LOAD", "ARCH/OS");
     foreach my $host ($hosts->hosts) {
     	printf STDOUT ($FORMAT,
     		       $host->hostname,
     		       $host->cpus,
     		       $host->max_clock,
     		       sprintf("%3.1f", $host->total_pctcpu),
     		       $host->adj_load,
     		       $host->archname ." ". $host->osvers,
     		       );
     }

     # Top processes
     (my $FORMAT =    "%-12s   %6s    %-8s      %-5s    %6s     %5s%%    %s\n") =~ s/\s\s+/ /g;
     printf ($FORMAT, "HOST", "PID", "USER",  "STATE", "RUNTM", "CPU","COMMAND");
     foreach my $host ($hosts->hosts) {
     	foreach $p ($host->top_processes) {
     	    printf($FORMAT,
     		   $host->hostname,
     		   $p->pid, 		$p->uname,
     		   $p->state, 		$p->time_hhmm,
     		   $p->pctcpu,		$p->fname);
     	}
     }

DESCRIPTION
===========

   This package provides information about host loading and top processes
from many machines across a entire network.

fetch ()
     Fetch the data structures from across the network.  This also creates
     a new object.  Accepts the port and host parameters.

restart ()
     Restart all daemons, loading their code from the executables again.
     Use sparingly.  chooser parameter if true (default) restarts chooser,
     reporter parameter if true (default) restarts reporter.

hosts ()
     Returns the host objects, accessable with
     `Schedule::Load::Hosts::Host'.  In an array context, returns a list;
     In a a scalar context, returns a reference to a list.

get_host ($hostname)
     Returns a reference to a host object with the specified hostname, or
     undef if not found.

classes ()
     Returns all class_ variables under all hosts.  In an array context,
     returns a list; In a a scalar context, returns a reference to a list.

print_classes
     Returns a string with the list of machines and classes that may run
     on them in a printable format.

print_hosts
     Returns a string with the list of host machines and loading in a
     printable format.

print_top
     Returns a string with the top jobs on all machines in a printable
     format, ala the top program.

print_loads
     Returns a string with the top jobs command lines, including any jobs
     with a fixed loading.

PARAMETERS
==========

dhost
     List of daemon hosts that may be running the slchoosed server.  The
     second host is only used if the first is down, and so on down the
     list.

port
     The port number of slchoosed.  Defaults to 'slchoosed' looked up via
     /etc/services, else 1752.

SEE ALSO
========

   `Schedule::Load::Hosts::Host', `Schedule::Load::Hosts::Proc'

   `Schedule::Load', rschedule

DISTRIBUTION
============

   The latest version is available from CPAN.

AUTHORS
=======

   Wilson Snyder <wsnyder@wsnyder.org>

Return information about a host
*******************************

NAME
====

   Schedule::Load::Hosts::Host - Return information about a host

SYNOPSIS
========

     See Schedule::Load::Hosts

DESCRIPTION
===========

   This package provides accessors for information about a specific host
obtained via the Schedule::Load::Host package.

fields
     Returns all information fields for this host.

exists (key)
     Returns if a specific field exists for this host.

get (key)
     Returns the value of a specific field for this host.

ACCESSORS
=========

   A accessor exists for each field returned by the fields() call.
Typical elements are described below.

top_processes
     Returns a reference to a list of top process objects,
     `Schedule::Load::Hosts::Proc' to access the information for each
     process.  In an array context, returns a list; In a a scalar context,
     returns a reference to a list.

archname
     Architecture name from Perl build.

cpus
     Number of CPUs.

hostname
     Name of the host.

max_clock
     Maximum clock frequency.

load_limit
     Limit on the loading that a machine can bear, often set to the number
     of CPUs to not allow overloading of a machine.  Undefined if no limit.

osname
     Operating system name from Perl build.

reservable
     If true, this host may be reserved for exclusive use by a user.

reserved
     If true, this host is reserved, and this field contains a username and
     start time comment.

systype
     System type from Perl build.

total_load
     Total number of processes in run or on processor state.

adj_load
     Total number of processes in run or on processor state, adjusted for
     any jobs that have a specific fixed_load or hold time.  This is the
     load used for picking hosts.

total_pctcpu
     Total CPU percentage used by all processes.

SEE ALSO
========

   `Schedule::Load', Schedule::Load::Hosts, `Schedule::Load::Hosts::Proc'

DISTRIBUTION
============

   The latest version is available from CPAN.

AUTHORS
=======

   Wilson Snyder <wsnyder@wsnyder.org>

Return process information
**************************

NAME
====

   Schedule::Load::Hosts::Proc - Return process information

SYNOPSIS
========

     See Schedule::Load::Hosts

DESCRIPTION
===========

   This package provides accessors for information about a specific
process obtained via the Schedule::Load::Hosts package.

fields
     Returns all information fields for this process.

exists (key)
     Returns true if a specific field exists for this process.

get (key)
     Returns the value of a specific field for this process.

ACCESSORS
=========

   A accessor exists for each field returned by the fields() call.  Typical
elements are described below.  All fields that `Proc::ProcessTable'
supports are also included here.

nice0
     Nice value with 0 being normal and 19 maximum nice.

time_hhmm
     Returns the runtime of the process in mmm:ss or hh.hH format,
     whichever is appropriate.

username
     Texual user name running this process.

SEE ALSO
========

   `Schedule::Load', Schedule::Load::Hosts, `Schedule::Load::Hosts::Host'

DISTRIBUTION
============

   The latest version is available from CPAN.

AUTHORS
=======

   Wilson Snyder <wsnyder@wsnyder.org>

Distributed load reporting daemon
*********************************

NAME
====

   Schedule::Load::Reporter - Distributed load reporting daemon

SYNOPSIS
========

     use Schedule::Load::Reporter;

     Schedule::Load::Reporter->start(dhost=>('host1', 'host2'),
     				  port=>1234,);

DESCRIPTION
===========

   Schedule::Load::Reporter on startup connects to the requested server
host and port.  The server connected to can then poll this host for
information about system configuration and current loading conditions.

start ([parameter=>value ...]);
     Starts the reporter.  Does not return.

PARAMETERS
==========

dhost
     List of daemon hosts that may be running the slchoosed server.  The
     second host is only used if the first is down, and so on down the
     list.

port
     The port number of slchoosed.  Defaults to 'slchoosed' looked up via
     /etc/services, else 1752.

min_pctcpu
     The minimum percentage of the CPU that a job must have to be included
     in the list of top processes sent to the client.  Defaults to 3.
     Setting to 0 will consume a lot of bandwidth.

stored_filename
     The filename to store persistant items in, such as if this host is
     reserved.  Must be either local-per-machine, or have the hostname in
     it.  Defaults to /usr/local/lib/rschedule/slreportd_{hostname}_store.
     Set to undef to disable persistance (thus if the machine reboots the
     reservation is lost.)

SEE ALSO
========

   `Schedule::Load', slreportd

DISTRIBUTION
============

   This package is distributed via CPAN.

AUTHORS
=======

   Wilson Snyder <wsnyder@wsnyder.org>

Functions for choosing a host among many
****************************************

NAME
====

   Schedule::Load::Schedule - Functions for choosing a host among many

SYNOPSIS
========

     use Schedule::Load::Schedule;

     my $scheduler = Schedule::Load::Schedule->fetch();
     print "Best host for a new job: ", $scheduler->best();

DESCRIPTION
===========

   This package will allow the most lightly loaded host to be choosen for
new jobs across many machines across a entire network.

   It is also a superclass of Schedule::Load::Hosts, so any functions that
work for that module also work here.

best (...)
     Returns the hostname of the best host in the network for a new job.

    allow_none
          If allow_none is true, if there is less then a free CPU across
          the entire network, then no cpu will be choosen.  This is useful
          for programs that can dynamically adjust their outstanding job
          count.  (Presumably you would only set allow_none if you already
          have one job running, or you can get livelocked out of getting
          anything!)

    classes
          An array reference of which classes the host must support to
          allow this job to be run on that host.  Defaults to [], which
          allows any host.

    favor_host
          The hostname to try and choose if all is equal, under the
          presumption that there are disk access time benefits to doing
          so.  Defaults to the current host.

    hold_key
          A hold key will reserve a job slot on the choosen CPU until a
          release_hold function is called.  This prevents overscheduling a
          host due to the delay between choosing a host with a light load
          and starting the job on it which rases the CPU load of that
          choosen host.

    hold_time
          Number of seconds to allow the hold to remain before being
          removed automatically.

fixed_load (load=>load_value, [pid=>$$], [host=>localhost])
     Sets the current process and all children as always having at least
     the load value specified.  This prevents undercounting CPU
     utilization when a large batch job is running which is just paused in
     the short term to do disk IO or sleep.

hold_release (hold_key=>key)
     Releases the temporary hold placed with the best function.

hosts_of_class (class=>name)
     Returns `Schedule::Load::Hosts::Host' objects for every host that
     matches the given class.

jobs (...)
     Returns the maximum number of jobs suggested for the given scheduling
     parameters.  Presumably this will be used to spawn parallel jobs for
     one given user, such as the `make -j' command.  Jobs() takes the same
     arguments as best(), in addition to:

    max_jobs
          Maximum number of jobs that jobs() can return.  Defaults to 6
          jobs during the day, unlimited at night.

release (host=>hostname)
     Releases the machine from exclusive use of any user.  The user doing
     the release does not have to be the same user that reserved the host.

reserve (host=>hostname, [comment=>comment])
     Reserves the machine for exclusive use of the current user.  The host
     choosen must have the reservable flag set.  `rschedule hosts' will
     show the host as reserved, along with the provided comment.

PARAMETERS
==========

   Parameters for the new and fetch calls are shown in
Schedule::Load::Hosts.

night_hours_cb
     Reference to Function for determining if this is night time, defaults
     to M-F 6am-10pm.  When it is nighttime hours, every class passed to
     the best option has a new class with _night appended.

SEE ALSO
========

   `Schedule::Load', Schedule::Load::Hosts, rschedule

DISTRIBUTION
============

   The latest version is available from CPAN.

AUTHORS
=======

   Wilson Snyder <wsnyder@wsnyder.org>

Handles and detects clash between pattern-based schedules
*********************************************************

NAME
====

     Schedule::Match - Handles and detects clash between pattern-based schedules

SYNOPSIS
========

     use Schedule::Match qw(scheck rcheck isleap uthash expand localtime);

     # hash structure of handled schedule
     $this = {
       life => 3600, # how long each execution of schedule lasts (in second)
       t_mh => '*',  # minute of the hour      - in crontab(5) format
       t_hd => '*',  # hour of the day         - in crontab(5) format
       t_dw => '*',  # day of the week         - in crontab(5) format
       t_dm => '*',  # date of the month       - in crontab(5) format
       t_wm => '*',  # week of the month       - in crontab(5) format
       t_my => '*',  # month of the year       - in crontab(5) format
       t_yt => '*',  # year (of the time)      - in crontab(5) format
       t_om => '*',  # occurrence in the month - in crontab(5) format
     };

     # create hash structure from given time
     $that = uthash($time, $life);

     @when = scheck($this, $that, ...); # list clash (duration not considered)
     @when = rcheck($this, $that, ...); # list clash (duration     considered)

     $bool = isleap($year);         # check for leap year
     @list = expand($expr, \@fill); # expand each crontab(5) expression

     @time = localtime($time);      # feature enhanced localtime(3)

DESCRIPTION
===========

   This library allows you to manage schedule which has structure similar
to crontab(5) format. It offers methods to detect clash between schedules
(with or without duration considered), and can also tell when, and how
often they clash.

   From the viewpoint of data structure, one major difference compared to
crontab(5) is a concept of duration. Each schedule has its own duration,
and clash detection can be done upon that.  For more information on data
structure, please consult SCHEDULE STRUCTURE section below.

   All schedules are assumed to be in the same timezone. You will have to
align them beforehand if not.

   Currently available methods are as follows:

@when = lcheck($this, $deep, $keep, $init, $last);
     Returns list of UNIX times which is a time given schedule gets
     invoked.

@when = scheck($this, $that, $deep, $keep, $init, $last);
     Detects clash between given schedules _without_ considering duration.
     Returns the list of clash time (empty if not).  It is safe to assume
     the list is sorted.

     Options are:

    - $deep
          Sets the "depth" of clash detection. If set to false, it will
          report only one clash (first one) per day.

    - $keep
          Sets the maximum number of clashes to detect. Defaults to 1.

    - $init
          Set the starting time of timespan to do the detection.  Defaults
          to the moment this method is called.

    - $done
          Set the closing time of timespan to do the detection.  Defaults
          to 3 years after $init.

$list = rcheck($exp0, $exp1, $deep, $keep, $init, $done);
     Detects clash between given schedules _with_ duration considered.

     This is almost compatible with *scheck* except that $deep and $keep
     option does not work as expected (for current implementation). For
     $deep, it is always set to 1, and for $keep, you would need to
     specify much larger value (I cannot give the exact number since it
     depends on how often two schedules clash).

$bool = isleap($year);
     Returns wheather given year is leap year or not. Returns true if it
     is, false otherwise.

$hash = uthash($time[, $life]);
     Create schedule structure from given UNIX time. Optionally, you can
     also set the duration of created schedule (which defaults to 0).

@time = localtime($time);
     Converts a time as returned by the time function to a 11-element
     array with the time analyzed for the local time zone.

     Except for appended 10th and 11th element, this is compatible with
     built-in localtime.

     Appended 2 elements (10th and 11th) are "week of the month" and
     "occurence in the month", both in 1-indexed style.

@list = expand($expr, \@fill);
     Function to expand given crontab(5)-like expression to the list of
     matching values. \@fill is used to expand wildcard.

SCHEDULE STRUCTURE
==================

   Below is a structure of schedule used in this library:

     life => duration of the schedule (in second)
     t_mh => minute of the hour
     t_hd => hour of the day
     t_dm => day of the month
     t_my => month of the year
     t_yt => year (of the time)
     t_dw => day of the week
     t_wm => week of the month
     t_om => occurrence in the month

   As you can see, this is a simple hashtable. And for all t_* entries,
crontab(5)-like notation is supported. For this notation, please consult
crontab(5) manpage.

   Next goes some examples. To make description short, I stripped the text
"Schedule lasting for an hour, starting from midnight" off from each
description. Please assume that when reading.

  1. on every Jan. 1.
          $schedule = {
              life => 3600,
              t_mh => '0',
              t_hd => '0',
              t_dm => '1',
              t_my => '0',
              t_yt => '*',
              t_dw => '*',
              t_wm => '*',
              t_om => '*',
          }

  2. on every 3rd Sunday.
          $schedule = {
              life => 3600,
              t_mh => '0',
              t_hd => '0',
              t_dm => '*',
              t_my => '*',
              t_yt => '*',
              t_dw => '0',
              t_wm => '*',
              t_om => '3',
          }

  3. on Monday of every 3rd week.
          $schedule = {
              life => 3600,
              t_mh => '0',
              t_hd => '0',
              t_dm => '*',
              t_my => '*',
              t_yt => '*',
              t_dw => '1',
              t_wm => '3',
              t_om => '*',
          }

  4. on every other day.
          $schedule = {
              life => 3600,
              t_mh => '0',
              t_hd => '0',
              t_dm => '*/1',
              t_my => '*',
              t_yt => '*',
              t_dw => '*',
              t_wm => '*',
              t_om => '*',
          }

  5. on every other 2 days, from January to May.
          $schedule = {
              life => 3600,
              t_mh => '0',
              t_hd => '0',
              t_dm => '*/2',
              t_my => '0-4',
              t_yt => '*',
              t_dw => '*',
              t_wm => '*',
              t_om => '*',
          }

  6. on the day which is Sunday _and_ the 1st day of the month.
          $schedule = {
              life => 3600,
              t_mh => '0',
              t_hd => '0',
              t_dm => '1',
              t_my => '*',
              t_yt => '*',
              t_dw => '0',
              t_wm => '*',
              t_om => '*',
          }

  7. on Jan. 1, 1999
          $schedule = {
              life => 3600,
              t_mh => '0',
              t_hd => '0',
              t_dm => '1',
              t_my => '0',
              t_yt => '1999',
              t_dw => '*',
              t_wm => '*',
              t_om => '*',
          }

     Got the idea? You need to be careful on how you specify pattern,
     since it is possible to create pattern which never happens (Say,
     every Monday of 1st week which is 3rd Monday of the month).

     Other key-value pair can be in the hash, but there is no gurantee for
     those entries. It might clash with future enhancements to the
     strcuture, or it might even be dropped when the internal copy of the
     structure is made.

BUGS
====

   Two potential bugs are currently known:

UNIX-Y2K++ bug
     Due to a feature of localtime(3), this cannot cannot handle year
     beyond 2038. Since clash-detection code checks for the date in the
     future, this library is likely to break before that (around 2030?).

Clash detection bug
     When schedule(s) in question repeat in very short time (like every
     minute), method rcheck might not be able to check through timespan
     that is long enough.

     This can be avoided if you specify HUGE value for $keep, but then
     things will be so slow, I believe it is not practical.

COPYRIGHT
=========

   Copyright 1999, Taisuke Yamada <tai@imasy.or.jp>.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

(Win32) system administrator`s library - for login and application startup scripts, etc
***************************************************************************************

NAME
====

   Script - (Win32) system administrator`s library - for login and
application startup scripts, etc

SYNOPSIS
========

     use Script;                      # or use Script ':DEFAULT'
     $a =FileRead('c:\\autoexec.bat');
     FileDelete('-r','c:\\tmp\\*');
     FileEdit('c:\\autoexec.bat',sub{s/(SET *TMP *= *)/${1}c:\\tmp/i});
     use Script ':ALL';               # import from @EXPORT and @EXPORT_OK
     Print('Using','all','functions','from','@EXPORT','and','@EXPORT_OK');
     use Script ':ALL',':OVER';       # silently overwrite with imported

DESCRIPTION
===========

   At primary this module was written for system administrator needs in
centralised administration of Win32 clients: logon and application startup
scripts, etc. Later some functions useful in Windows NT server scripts was
added. Now many functions may run on UNIX or may be developed for it. But
area of Win32 servers and clients is very specific.

   This module was made for several reasons:

   - for useful functions does not (yet?) implemented as core perl
functions.

   - for more flexible and powerful functional style programming
functions, than exists.

   - to load used perl modules when required, with "eval('use ...')".

   - to support scripting modes: printing of commands executed, die on
errors.

   This module calls for it`s functions many other modules from standard
and site perl libraries and OS commands, and depends on their
implementations and limitations. GUI functions implemented with Perl Tk.

   Currently this module is implemented and tested on Win32 platform.

VARIABLES
=========

     use vars qw($Interact $GUI $Echo $ErrorDie $Error $FileLog $Print);

     # example usage: $Script::Interact=0

     $Interact   =1;   # interact with user in functions as Prompt, Die, GUIMsg
     $GUI        =1;   # use GUI interaction instead of terminal in functions
                       # as Die, GUIMsg
     $Echo       =1;   # print commands as 'set echo on' in DOS
     $ErrorDie   =0;   # die on error if 1, 2 inside Try
     $@ = $Error ='';  # last error occurred
     $FileLog    ='';  # log file name (LOG handle) for Echo, Print, errors...
     $Print      ='';  # external print routine reference

   NOTE:

   Some functions have not printout, and are not controlled by $Echo. Some
functions are not controlled by $Echo due to used components.

RESULTS of FUNCTIONS
====================

   Some (boolean) functions returns TRUE to show success, or FALSE (0, ").

   Returning values functions returns on error empty value: 0 or " or ().

   Undefined and negative results are escaped as possible for better
functional programming style support.  Values '0E0' or '0 but true'
(numeric 0 and logical true) are not used.

   Variable $@ or $Error may be used to distinguish erroneous empty values
from normal.

CLASSES of FUNCTIONS
====================

   (see Exporter)

   @EXPORT = qw(CPTranslate Die Echo FileACL FileCompare FileCopy FileCRC
FileCwd FileDelete FileEdit FileFind FileGlob FileHandle FileIni FileLnk
FileMkDir FileNameMax FileNameMin FileRead FileSize FileSpace FileTrack
FileWrite FTPCmd GUIMsg NetUse Pause Platform Print Registry Run RunInf
RunKbd SMTPSend StrTime UserEnvInit UserPath);

   @EXPORT_OK = qw(FileLog TrAnsi2Oem TrOem2Ansi Try(@) TryHdr);

   %EXPORT_TAGS = ('ALL'=>[@EXPORT,@EXPORT_OK], 'OVER'=>[]);

Error processing functions
     Try, TryHdr

File functions
     FileACL, FileCompare, FileCopy, FileCRC, FileCwd, FileDelete,
     FileEdit, FileFind, FileGlob, FileHandle, FileIni, FileLnk, FileLog,
     FileMkDir, FileNameMax, FileNameMin, FileRead, FileSize, FileSpace,
     FileTrack, FileWrite

FTP functions
     FTPCmd

Registry functions
     Registry

Run & Misc functions
     Run, RunInf, RunKbd, NetUse, Platform, UserEnvInit, UserPath

Mail functions
     SMTPSend

String functions
     CPTranslate, TrAnsi2Oem, TrOem2Ansi, StrTime

Interactive functions
     Die, GUIMsg, Pause, Print, Echo

Obsolete functions
     TrAnsi2Oem, TrOem2Ansi

FUNCTIONS
=========

CPTranslate ( fromCP, toCP, string,... ) -> $translatedString

TrAnsi2Oem ( ansiString ) -> oemString - obsolete, not recommended

TrOem2Ansi ( oemString ) -> ansiString - obsolete, not recommended
     Translates strings from codepage fromCP to codepage toCP, returns
     translated string or list of strings.  Codepages may be 'oem',
     '866','ansi', '1251','koi' prone of koi8, '8859-5' prone of ISO
     8859-5.

Die ( ?string,... )
     Displays blank delimited strings to user and dies with error code 1.
     As a default message $@ is used.  For GUI uses GUIMsg with text
     translated from 'oem' to 'ansi'.  If $Interact == 0, does not waits
     for user response.

Echo ( text,... ) -> success
     Prints given text list delimited with blanks and terminated with
     "\n". May be switched off with $Echo or redefined with $Print.

FileACL ( ?'-r+', fileMask, ?sub(...), user => access,... ) -> success
     Sets access control list for directories and files matching fileMask
     and sub.  Without given access control list, prints current, this
     behaviour may be changed.  Uses FileFind, `Win32::FileSecurity|Win32'
     in this node.

     Options: 'r'ecurse subdirectories, '+' - add ACL entries instead of
     replacing them.

     Sub parameters are like in FileFind.

     Access: 'add' (not implemented), 'add&read', 'add&list' (not
     implemented), 'read', 'change', 'full', reference to array of array
     references [[directory low level rights],[file low level rights]].

FileCompare ( file1, file2 ) -> differs
     Compares two files and returns 0 for identical files, 1 for unequal
     files, -1 when error.  Uses `File::Compare|File' in this node

FileCopy ( ?'-rdfi', fromFileMask, toPath ) -> success
     Copies fromFileMask to toPath. On 'MSWin32' uses `xcopy' with
     switches H, R, K, E, Q, Z.

     Options: 'r'ecurse subdirectories, 'd'irectory target hint, 'f'ile
     target hint, 'i'gnore errors - continue copying.

FileCRC (?'-adler', file) -> CRC
     Calculates CRC of file or 0 if error. Uses `Compress::Zlib|Compress'
     in this node.

     Options: 'adler' or 'adler32' or '-a adler', 'crc32' (default).

FileDelete ( ?'-r', fileMask,... ) -> success
     Deletes files and directories fileMask. Uses FileGlob.

     Options: 'r'ecurse subdirectories.

FileCwd () -> cwd
     eval('use Cwd; getcwd()')

FileEdit ( ?'-im', file, ?fileTo, sub(section, @variables)) -> success
FileEdit ( file, ?'-im', sub ) - obsolete, not recommended
     Edits given file with given sub using local variable $_ for text to
     edit.  Uses FileRead, FileWrite, `File::Copy|File' in this node.

     Options: 'i'nplace edit in memory (default), 'i ext' - use temporary
     file with given extension, 'm'ultiline edit instead of evaluation sub
     for each row of file.

     Parameters of sub: $_, $_[0] - section name (determined with '[' sign
     in row beginning),  @_(1...) - temporary variables with lifetime of
     FileEdit execution.

FileFind ( ?'-i!dlmrs', fileMask,..., sub(\@stat,path,name)...) -> num_matches
FileFind ( ?'-i!dlmrs', fileMask,..., sub(\@stat,,,result)...) -> result
FileFind ( ?'-i!dlmrs', sub(\@stat), fileMask...) - obsolete, not recommended
     Finds files and directories with given mask and evaluates sub,
     locally setting $_ to filename. Returns number of sub agrees, or
     result if defined, or 0 on errors. There may be several subs and
     several filemasks for each sub, and they will be executed within one
     transaction of FileFind call.  Uses FileGlob

     Options: 'i'gnore stat errors, '!' - not, 'd'irectories, 'l'ow before
     deep scan, 'm'ountpoints, 'r'ecurse directories, 's'ymlinks.

     Parameters of sub are local $_ with full current filename, $_[0] with
     reference to @stat array, $_[1] with path, $_[2] with filename, $_[3]
     as optional result storage (initially undefined).  Sub can return
     undefined value in $_ to signal stop, determine directories with
     $_[0]->[2] & 0040000, prevent recursing by assigning $_[0]->[2] =0.

     Options for FileFind and based on it functions as FileACL, FileSize
     should and should not be the same. FileFind defaulty recurses, other
     commands traditionally not. Set of FileFind options may be extended
     in future, but existing programs should be preserved, and so FileFind
     options should be negative instead of traditionally positive options
     of other commands.  Based on FileFind functions are restricted, not
     using all possible FileFind features. All functions may be called
     from comprehensive FileFind to get all features.

FileGlob ( mask ) -> filelist
     Globs filenames with mask and returns list of them such as standard
     function glob. On error returns empty list?  When $^O eq 'MSWin32'
     own implementation with fragments from `File::DosGlob|File' in this
     node is used, else glob is called.

     Standard glob is not well on Win32 platforms, when working with
     filenames in foreign languages and calling external executable
     dosglob.exe should be placed in path.

     `File::DosGlob|File' in this node has some problems with non-english
     letters in filenames and long filenames.

FileHandle ( \*filehandle, sub(oldhandle) ) -> result
FileHandle ( filename, sub(oldhandle) ) -> result
     Selects given filehandle, evals sub, selects previously selected
     handle.  For filename, temporarily opens file with handle 'HANDLE',
     selects this handle, evals sub...  Returns result of sub, or empty
     (") if error.

FileIni ( ?'-', file, item,... ) -> success
FileIni ( ?'-', file) -> hash of items
     Edits ini-file in Windows format with given items.  Without items
     returns a hash structure $hash{section}->{name}=value.  Uses
     FileRead, FileWrite.

     Options: reserved for future use.

     Format of items: '[sectionName]', ';comment', [name => value];
     ['[sectionName]', op], [';comment', op], [name, value, op]

     Operations: '+' - set (default), '-' -delete, 'i'nitial value,
     'o'ptional value.

FileLnk (?'-mda', ?filename) -> Win32::Shortcut object
FileLnk (?'-mdac', filename, path, args, dir, description, show, hotkey, iconlocation, iconnumber ) -> Success
FileLnk (?'-mdac', filename, {-path=>path, -arg=>args, -dir=>dir, -desc=>description, -show=>show, -hot=>hotkey, -il=>iconlocation, -in=>iconnumber}) -> Success
     Returns `Win32::Shortcut|Win32' in this node object or creates Win32
     shortcut file.  Uses `Win32::Shortcut|Win32' in this node.  Filename
     may be absolute or relative to 'm'enu or 'd'esktop according to this
     options.  Default filename extension is '.lnk'.  Names of parameters
     for shortcut may be given above or may be names of properties of
     `Win32::Shortcut|Win32' in this node object.

     Options: 'm'enu relative filename, 'd'esktop relative filename, 'a'll
     users profile use instead of current user profile, 'c'reate shortcut
     file instead of update.

FileLog (logfile) -> success
FileLog () -> filename
FileLog (undef)
     Sets or requests log file name, opens log file with LOG handle for
     errors, warnings, Echo, Print.

FileMkDir ( dir, ?mask) -> success
     Executes standard `mkdir|perlfunc' in this node call, uses optional
     access mask (0777 default).

FileNameMax ( fileMask, ?sub(fullName, $_=fileName, digits)) -> max || (name, max)
     Finds filename with maximal number in it. Returns this number or list
     of full filename and number in list context.  Numeric comparing is
     used.  Sub may be used to translate filename to comparable value or
     ignore values.  Uses FileGlob

FileNameMin ( fileMask, ?sub(fullName, $_=fileName, digits)) -> name || (name, min)
     Finds filename with minimal number in it. Returns full name of this
     file or list of full filename and number in list context.  Numeric
     comparing is used.  Sub may be used to translate filename to
     comparable value or ignore values.  Uses FileGlob

FileRead ( ?'-asb', file, ?sub ) -> list of rows || data
     Reads given file into memory as array or list ('-a'), text scalar
     ('-s'), binary scalar ('-b'). Default, '-a' or '-b', is determined
     with `wantarray|perlfunc' in this node.

     If sub is defined, it is evaluated for each row read into local $_,
     and with '-a' option results of each evaluation are returned as a
     list, true is returned otherwise.

     On error returns empty list or scalar, according to option
     '-a','-s','-b'.

FileSize ( ?opt, fileMask, ?sub ) -> size in bytes
     Returns total size in bytes for directories and files matching
     fileMask and sub.  Uses FileFind with given options (-i default),
     parameters of sub are the same.

FileSpace ( ?filesystem ) -> free disk space in bytes
     Returns free disk space in bytes for specified dir.  Uses
     `\%COMSPEC\% /c dir $dir`.

FileTrack ( ?'-it!cdrt', sourceDir, destDir, ?sub(\@stat,path,name)) -> arcDir
     Tracks changed files matched 'sub' in 'sourceDir' into 'destDir'.
     Returns path to new archive directory inside 'destDir' or empty
     string if none archived.  'Sub' gets current filename in $_ and
     returns 'true' if match.  Code and interface are like FileFind.  Uses
     FileCopy, FileCRC, FileGlob.

     Options: 'i'gnore errors, 't'est and track CRC, '!' - not, 'c'opy
     changed files, 'd'irectories, 'r'ecurse directories, 't'ime check.

FileWrite ( ?'-b', file, data,...) -> success
     Writes given data into given file. Option '-b' chooses binary mode and
     binary write. Without '-b', each element of data list is printed with
     trailing "\n" added.

FTPCmd ( host, user, passwd, ?command, command, ?arguments) -> success
FTPCmd ( {-host=>host, -user=>user, -passwd=>passwd}, ?command, command, ?arguments) -> success
FTPCmd ( {-s=>host, -u=>user, -p=>passwd}, ?command, command, ?arguments) -> success
     Executes FTP command. First command may be
     'ascii','binary','ebcdic','byte'.  Second command may be 'dir', 'ls',
     'get', 'put', sub($ftp).  Returns result of command executed, for
     'dir' and 'ls' - list of values.  Uses `Net::FTP|Net' in this node.

GUIMsg ( title, string,...)
GUIMsg ( text )
     Popups given message to user.  Uses `Tk|Tk' in this node.

NetUse ( disk, resource ) -> success
     Executes Windows commands 'net use disk /d' and 'net use disk
     resource'.  Uses Run

Pause ( ?text,... ) -> response
     Prints given text list delimited with blanks and terminated with "\n",
     reads row from STDIN and returns it.

Platform ( parameter ) -> value
     Determine value of parameter: 'os', 'osname', 'win32', 'ver',
     'patch', 'lang', 'prodid', 'windir', 'name', 'domain', 'host',
     'hostdomain', 'user','userdomain'...  Uses available environment
     variables, perl functions, OS commands, stored in registry values.
     'windir' parameter may be used when Win32 'windir' environment
     variable is not available.

Print ( text,... ) -> success
     Prints given text list delimited with blanks and terminated with
     "\n". May be redefined with $Print.

Registry (?'-\\|/', key) -> value
Registry (?'-\\|/', key, ?type, value) -> success
Registry (?'-\\|/', key, value, ?type) - possible, but not recommended
     Works with values in Windows registry: returns value for given key
     and name, sets given value, deletes if undefined value given.  Uses
     `Win32::TieRegistry|Win32' in this node, error processing is
     unsupported.

     Option defines delimiter for key parts: '\\' (default), '|' or '/'.

     Value name may be delimited with double delimiter ('key\\\\name') as
     recommended `Win32::TieRegistry|Win32' in this node, or single
     delimiter ('key\\name') as also supported.

     Last parts of key not present in registry are automatically created,
     that improves behaviour of `Win32::TieRegistry|Win32' in this node.

     Type may be 'REG_SZ' (default), 'REG_EXPAND_SZ', 'REG_BINARY',
     'REG_MULTI_SZ', 'REG_DWORD'.

Run (command, ?arguments) -> success
     Runs specified command with `system|perlfunc' in this node call,
     returns !($? || $!).  Shell is used as in `system|perlfunc' in this
     node call - if command and arguments are in the same string.  Last
     argument may be sub to print to program called.

RunInf (filename, ?section, ?reboot mode) -> run string
     Generates command to run to install given inf-file on Windows.
     Default section name is 'DefaultInstall'.  Default reboot mode is
     128, not 132 as in Windows file association.

RunKbd (?timeout, title mask) -> window handle
RunKbd (?timeout, title mask, ?timeout, keyboard string) -> success
RunKbd (?timeout, title mask, ") -> success
     Finds window with title mask (regexp) given and types keyboard string
     into it.  Without keyboard string returns handle of window found.
     With empty keyboard string waits window to disappear.  Find operation
     retries to be sucessful within timeout.  Keyboard typing is delayed
     with timeout.  Uses `Win32::GuiTest|Win32' in this node.  Special
     symbols in keyboard string: '~' -ENTER, '+' -SHIFT, '^' -CONTROL, '%'
     -ALT; () - grouping, {} - quote special characters; {BACKSPACE},
     {BS}, {BKSP} - backkspace; {BREAK}, {CAPS}, {DELETE}, {DOWN}, {END},
     {ENTER}, {ESCAPE}, {HELP}, {HOME}, {INSERT}, {LEFT}, {NUMLOCK},
     {PGDN}, {PGUP}, {PRTSCR}, {RIGHT}, {SCROLL}, {PAUSE}; {F1} .. {F24}.

SMTPSend ( host, ?from, ?\@to, row,... ) - > success
     Sends MIME message to SMTP host, catenating rows via "\n". If 'from'
     or 'to' argument undefined, values are searched within rows of message
     as 'From:', 'Sender:', 'To:'. If array reference 'to' occurs in place
     of of message row, it will be converted to 'To:' MIME string.  Uses
     `Net::SMTP|Net' in this node.

StrTime ( ?mask, ?@time ) -> string
     Converts given date-time array into string using given mask.  Default
     mask is 'dd.mm.yy hh:mm:ss', constructs are 'yyyy', 'yy', 'mm', 'dd',
     'hh', 'ss'.  Default time is 'localtime(time)'.

Try ( eval {...}, default ) -> result
Try ( eval {...}, \&catch ) -> result
Try ( sub  {...}, ... ) -> result
     Try-Catch construction.  Function Try returns result of eval on
     success.  If error occurred (determined by $@), it returns default
     value or result of catch evaluation.

TryHdr (subject, stage)
TryHdr (undef, stage)
     Declare title and/or stage name of transaction to insert into $@
     inside Try.  May be used only inside Try(sub{},...).

UserEnvInit ( ?'-nhy' )
     Initiates user`s environment on Win32.  Uses
     `Win32::TieRegistry|Win32' in this node, `cacls', reskit utilities
     `winset', `setx'.

     Default options are '-nhy', option '-y' redefines environment
     variables when they defined, options may be '-n', '-ny', '-h'.

     Option 'n' sets on Win95 environment variables used on WinNT: 'OS',
     'COMPUTERNAME', 'USERNAME'.

     Option 'h' works if 'c:/Home' directory exists. It creates directory
     'c:/Home/Username' if it not exists (WinNT ACL setting applied), sets
     it to 'HOME' environment variable, sets value for

     $$Registry{'CUser\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User
     Shell Folders\\\\Personal'} to 'c:/Home/Username' or 'c:/Home/Work'
     (for systems with single user profile).

UserPath (user) -> home dir
UserPath (user, subdir) -> home subdir
     Returns path to user profile directory or subdirectory on Win32 or
     path to user home directory ($ENV{HOME}) or subdirectory on other
     platforms.  User may be 'all' users, 'default', " - current.  Subdir
     on Win32 may be 'Desktop', 'Personal','Programs','Start
     Menu','Startup', and other Win32 registry names under 'Explorer /
     Shell Folders'.  If Win32 subdir is not found for user, 'all users'
     profile' is used, and vice versa.

VERSION
=======

25/09-27/10/2000
----------------

Changed
     Echo, Print - are exported by default (moved from @EXPORT_OK to
     @EXPORT).

     FileACL - processed files are printed, not echoed; uses 'cacls.exe'
     when possible.

     FileCopy - '-d' removed from 'cp'.

     FileCopy - uses Run(...sub{}).

     FileGlob - support for filenames with '()'.

     FileLog - $SIG{__DIE__} dies if !defined($^S) too.

     FileSpace - digit grouping symbol may be ','.

     FileTrack - internal filehandle renamed from 'LOG' to 'TRACK'.

     NetUse - invokes 'net use ... /Yes' on Win95.

     Registry - supports unnamed registry values.

     Run - last argument may be sub to print to program called.

     UserPath - excludes blanks at the end of path as may be on WinNT.

31/07-15/09/2000
----------------

New
     FileCwd

     FileLnk

     RunKbd

     RunInf

     UserPath

Changed
     `$ErrorDie' - value 2 introduced and used inside Try because of $^S
     may be incorrect inside eval('string') or do(script).

     FileCopy - used pipe to answer to xcopy before system call because of
     codepage translation problem in open(commandline) on Win32 and
     incorrect $? of wait of `IPC::Open3|IPC' in this node on Win95.

     FileEdit - restored sub's parameter $_[0] with with section name,
     removed 28/02/2000.

     FileFind, FileTrack - filenames with '?' are ignored only when $^O eq
     'MSWin32'.

     FileFind - options added: !'l'ow before deep scan, 'm'ountpoints,
     's'ymlinks.

     FileGlob - created own implementation for 'MSWin32' supporting
     non-english letters and long filenames instead of
     `File::DosGlob|File' in this node.

     FileHandle - uses caller's namespace for HANDLE.

     FileTrack - added '!t' option to disable mtime checking.

     FTPCmd - first parameter may be hash ref with host, username and
     password.

     Pause - returns string entered as documented, instead of chomp result.

     Platform - new parameter 'windir'.

16-17/06/2000, 03-05/07/2000, FileTrack and some corrections
------------------------------------------------------------

New
     FileTrack

Changed
     FileCopy - translates '/' into '\' under Win32.  FileFind - corrected
     regular expressions for options.  Pause    - chomp used.

08/05/2000, Log writing and some corrections
--------------------------------------------

New
     FileLog

Changed
     FileFind - filepath and filename inserted into sub args after stat
     reference; FileMkDir - new default mode is 0777; StrTime - always
     4-digit years after 2000

24/03/2000, Improved error processing
-------------------------------------

   Module Carp used, croak should be called instead of `TryErr' or die.

Removed
     `TryErr', `TryEnd'

New
     TryHdr

12/02/2000 - 28/02/2000, Error processing and UNIX compatibility
----------------------------------------------------------------

   Error processing made with eval{} and $@, see Try.  Variable $Error is
syncronised with $@ and becomes optional.

   $^O (osname) introduced into some functions.

New
     Echo, Try, `TryEnd', `TryErr', $@

Changed
     Die, FileCopy ('cp -dpRf' for unix compatibility), FileEdit (removed
     parameter with section name), FileFind (backslash replaced with slash
     for unix compatibility, -i introduced), FileGlob (glob for unix
     compatibility), FileSize (options, -i FileFind option), FileSpace
     ('df -k' used for unix), Platform ($^O (osname) and getlogin), Print
     ($Echo dependence moved into Echo), SMTPSend

Removed
     `PrintErr' and $PrintErr (use warn and $SIG{__WARN__} instead)

Problems
     FileACL (failure `Win32::FileSecurity|Win32' in this node on
     non-local users and groups), FileFind (failure stat on non-standard
     filenames, f.e. with '?')

ToDo
     FileFind - review options and arguments.  It should accept violating
     needs when deleting and creating.  When creating, sub should see
     directories first, when deleting - contents first.

     FTPCmd, Platform, SMTPSend, - approve and test.

Analysis of functions:
          p - 5 - platform (windows specific) realisation only, 2 - unix+win
          w - 3 - windows specific
          e -   - no error handling
             31 - total number of functions

          pwe
           CPTranslate           e
           Die                   e
           Echo                  e
           FileACL             p
           FileCompare
           FileCopy            2
           FileCRC
           FileDelete
           FileEdit
           FileFind
           FileGlob              e
           FileHandle
           FileIni
           FileMkDir
           FileNameMax
           FileNameMin
           FileRead
           FileSize
           FileSpace           p
           FileWrite
           FTPCmd
           GUIMsg
           NetUse              pw
           Pause
           Platform            ?
           Print                 e
           Registry            pw
           Run
           SMTPSend
           StrTime               e
           UserEnvInit         pw

19/10 - 08/11/99, First documented release
------------------------------------------

Source changing
     Functions sorted alphabetically.

New variables:
     $Interact, $GUI, $Echo

Removed variables:
     $noInteract (replaced with $Interact)

New functions:
     CPTranslate, FileACL, FileHandle, FileMkDir, FileSize, FileSpace,
     Platform, SMTPSend

Changed functions:
     FileCopy, FileFind, FileGlob, FileNameMax, FileNameMin, Registry

ToDo:
     RetCodes - '0E0' for successful empty?

     FileACL - debug and develop.

     FileFind - corrected stat bug for filenames with sign '?'.

     FileFind - review options and arguments.

     FileFind - should accept violating needs when deleting and creating.
     When creating, sub should see directories first, when deleting -
     contents first.

     FTPCmd - approve and test.

     Platform - approve and test.

     Print and `PrintErr' - should this functions be exported by default?

     UserEnvInit - approve and test, especially for russian WinNT.

24/02/99 - 02/07/99, Corrections and Developments
-------------------------------------------------

   Corrections and developments was made 02/07/99, 28/06/99, 23/06/99,
15/06/99, 01/04/99, 25/03/99, 23/03/99, 20/03/99, 19/03/99, 17/03/99,
15/03/99, 13/03/99, 12/03/99, 09/03/99, 06/03/99, 03/03/99, 02/03/99,
01/03/99, 27/02/99, 24/02/99

18/02/99 13:04, First release
-----------------------------

   A small module with a few functions was created and turned onto
exploitation.

AUTHOR
======

   Andrew V Makarow <makarow@mail.com>, Denis E Medvedyuk <demed@mail.com>

generic binary search
*********************

NAME
====

   Search::Binary - generic binary search

SYNOPSIS
========

     use Seach::Binary;
     $pos = binary_search($min, $max, $val, $read, $handle, [$size]);

DESCRIPTION
===========

   `binary_search' implements a generic binary search algorithm returning
the position of the first record whose *index value* is greater than or
equal to $val. The search routine does not define any of the terms
position, record or *index value*, but leaves their interpretation and
implementation to the user supplied function `&$read()'. The only
restriction is that positions must be integer scalars.

   During the search the read function will be called with three arguments:
the input parameters $handle and $val, and a position.  If the position is
not undef, the read function should read the first whole record starting
at or after the position; otherwise, the read function should read the
record immediately following the last record it read.  The search
algorithm will guarantee that the first call to the read function will not
be with a position of undef.  The read function needs to return a two
element array consisting of the result of comparing $val with the index
value of the read record and the position of the read record. The
comparison value must be positive if $val is strictly greater than the
index value of the read record, 0 if equal, and negative if strictly less.
Furthermore, the returned position value must be greater than or equal to
the position the read function was called with.

   The input parameters `$min' and `$max' are positions and represents the
extent of the search. Only records which begin at positions within this
range (inclusive) will be searched. Moreover, `$min' must be the starting
position of a record. If present $size is a difference between positions
and determines when the algorithms switches to a sequential search. $val is
an index value. The value of $handle is of no consequence to the binary
search algorithm; it is merely passed as a convenience to the read
function.

COPYRIGHT
=========

     Copyright 1998, Erik Rantapaa

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

search for key in dictionary file
*********************************

NAME
====

   Search::Dict, look - search for key in dictionary file

SYNOPSIS
========

     use Search::Dict;
     look *FILEHANDLE, $key, $dict, $fold;

DESCRIPTION
===========

   Sets file position in FILEHANDLE to be first line greater than or equal
(stringwise) to $key.  Returns the new file position, or -1 if an error
occurs.

   The flags specify dictionary order and case folding:

   If *$dict* is true, search by dictionary order (ignore anything but word
characters and whitespace).

   If *$fold* is true, ignore case.

A manager for inverted index maps
*********************************

NAME
====

   Search::InvertedIndex - A manager for inverted index maps

SYNOPSIS
========

     use Search::InvertedIndex;

     my $database = Search::InvertedIndex::DB::DB_File_SplitHash->new({
                -map_name => '/www/search-engine/databases/test-maps/test',
     				-multi => 4,
               -file_mode => 0644,
               -lock_mode => 'EX',
            -lock_timeout => 30,
          -blocking_locks => 0,
               -cachesize => 1000000,
           -write_through => 0,
         -read_write_mode => 'RDWR';
           });

     my $inv_map = Search::Inverted->new({ -database => $database });

   ########################################################## # Example
Update ##########################################################

     my $index_data = "Some scalar - complex structure refs are ok";

     my $update = Search::InvertedIndex::Update->new({
                                  -group => 'keywords',
                                  -index => 'http://www.nihongo.org/',
                                   -data => $index_data,
                                   -keys => {
                                               'some' => 10,
                                             'scalar' => 20,
                                            'complex' => 15,
                                          'structure' => 15,
                                               'refs' => 15,
                                                'are' => 15,
                                                 'ok' => 15,
                                            },
                                            });
     my $result = $inv_map->update({ -update => $update });

   ########################################################## # Example
Query # '-nodes' is an anon list of Search::InvertedIndex::Query # objects
(this allows constructing complex booleans by # nesting).  # # '-leafs' is
an anon list of Search::InvertedIndex::Query::Leaf # objects (used for
individual search terms).  #
##########################################################

     my $query_leaf1 = Search::InvertedIndex::Query::Leaf->new({
                                             -key => 'complex',
                                           -group => 'keywords',
                                          -weight => 1,
                                          });

     my $query_leaf2 = Search::InvertedIndex::Query::Leaf->new({
                                             -key => 'structure',
                                           -group => 'keywords',
                                          -weight => 1,
                                          });
     my $query_leaf3 = Search::InvertedIndex::Query::Leaf->new({
                                             -key => 'gold',
                                           -group => 'keywords',
                                          -weight => 1,
                                          });
     my $query1 = Search::InvertedIndex::Query->new({
                        -logic => 'and',
                       -weight => 1,
                        -nodes => [],
                        -leafs => [$query_leaf1,$query_leaf2],
                     });
     my $query2 = Search::InvertedIndex::Query->new({
                        -logic => 'or',
                       -weight => 1,
                        -nodes => [$query1],
                        -leafs => [$query_leaf3],
                     });

     my $result = $inv_map->search({ -query => $query2 });

   ##########################################################

     $inv_map->close;

DESCRIPTION
===========

   Provides the core of an inverted map based search engine. By mapping
'keys' to 'indexes' it provides ultra-fast look ups of all 'indexes'
containing specific 'keys'. This produces highly scalable behavior where
thousands, or even millions of records can be searched extremely quickly.

   Available database drivers are:

     Search::InvertedIndex::DB::DB_File_SplitHash
     Search::InvertedIndex::DB::Mysql

   Check the POD documentation for each database driver to determine
initialization requirements.

CHANGES
=======

     1.00 1999.06.16 - Initial release

     1.01 1999.06.17 - Documentation fixes and fix to 'close' method in
                       Search::InvertedIndex::DB::DB_File_SplitHash

     1.02 1999.06.18 - Major bugfix to locking system.
                       Performance tweaking. Roughly 3x improvement.

     1.03 1999.06.30 - Documentation fixes.

     1.04 1999.07.01 - Documentation fixes and caching system bugfixes.

     1.05 1999.10.20 - Altered ranking computation on search results

     1.06 1999.10.20 - Removed 'use attrs' usage to improve portability

     1.07 1999.11.09 - "Cosmetic" changes to avoid warnings in Perl 5.004

     1.08 2000.01.25 - Bugfix to 'Search::InvertedIndex::DB:DB_File_SplitHash' submodule
                       and documentation additions/fixes

     1.09 2000.03.23 - Bugfix to 'Search::InvertedIndex::DB:DB_File_SplitHash' submodule
                       to manage case where 'open' is not performed before close is called.

     1.10 2000.07.05 - Delayed loading of serializer and added option to select
                       which serializer (Storable or Data::Dumper) to use at instance 'new' time.
                       This should allow module to be loaded by mod_perl via the 'PerlModule'
                       conf directive and enable use on platforms that do not support
                       'Storable' (such as Macintosh).

     1.11 2000.11.29 - Added 'Search::InvertedIndex::DB::Mysql' (authored by
                       Michael Cramer <cramer@webkist.com>) database driver
                       to package.

Public API
----------

`new($parm_ref);'
     Provides the interface for obtaining a new Search::InvertedIndex
     object for manipulating a inverted database.

     Example 1:

          my $database = Search::InvertedIndex::DB::DB_File_SplitHash->new({
                      -map_name =>
          			             '/www/search-engine/databases/test-map_names/test',
          				-multi => 4,
                     -file_mode => 0644,
                     -lock_mode => 'EX',
                  -lock_timeout => 30,
                -blocking_locks => 0,
                     -cachesize => 1000000,
                 -write_through => 0,
               -read_write_mode => 'RDONLY',
                   -stringifier => ['Storable','Data::Dumper'],
                 });

          my $inv_map = Search::InvertedIndex->new({
                         '-database' => $database,
                '-search_cache_size' => 1000,
                 '-search_cache_dir' => '/var/tmp/search_cache',
              });

     The -database parameter is required and must be a
     'Search::InvertedIndex::DB::...'  type database object. The other two
     parameters are optional and define the location and size of the
     search cache. If omitted, no search caching will be done.

     The optional '-stringifier' parameter can be used to override the
     default use of 'Storable' (with fallback to 'Data::Dumper') as the
     stringifier used for storing data by the module. Specifiying
     -stringifier => 'Data::Dumper' would specify using 'Data::Dumper'
     (only) as the stringifier while specifiying -stringifier =>
     ['Data::Dumper','Storable'] would specify to use Data::Dumper by
     preference (but to fall back to 'Storable' if Data::Dumper was not
     available). If a database was created using a particular serializer,
     it will automatically detect it and attempt to use the correct one.

`lock($parm_ref);'
     Changes a lock on the underlaying database.

     Forces 'sync' if the stat is changed from 'EX' to a lower lock state
     (i.e. 'SH' or 'UN'). Croaks on errors.

     Example:

          $inv->lock({ -lock_mode => 'EX' [, -lock_timeout => 30] [, -blocking_locks => 0],
                });

     The only _required_ parameter is the -lock_mode. The other parameters
     can be inherited from the object state. If the other parameters are
     used, they change the object state to match the new settings.

`status($parm_ref);'
     Returns the requested status line for the database. Allowed requests
     are '-open', and '-lock'.

     Example 1:  my $status = $inv_map->status(-open); # Returns either
     '1' or '0'

     Example 2:  my $status = $inv_map->status(-lock_mode); # Returns
     'UN', 'SH' or 'EX'

`update($parm_ref);'
     Performs an update on the map. This is designed for
     adding/changing/deleting a bunch of related information in a single
     block update.  It takes a Search::InvertedIndex::Update object as
     input. It assumes that you wish to remove all references to the
     specified index and replace them with a new list of references. It
     can also will update the -data for the -index. If -data is passed and
     the -index does not already exist, a new index record will be
     created. It is a fatal error to pass a non-existant index without a
     -data parm to initialize it. It is also a fatal error to pass an
     update for a non-existant -group.

     Passing an empty -keys has the effect of deleting the index from
     group (but not from the system).

     Example:

          my $update = Search::InvertedIndex::Update->new(...);
          $inv_map->update({ -update => $update });

     It is much faster to update a index using the update method than the
     add_entry_to_group method in most cases because the batching of
     changes allows for efficiency optimizations when there is more than
     one key.

`preload_update($parm_ref);'
     'preload_update' places the passed 'update' object data into a pending
     queue which is not reflected in the searchable database until the
     'update_group' method has been called. This allows the loading
     process to be streamlined for maximum performance on large full
     updates. This method is not appropriate to incremental updates as the
     'update_group' method destroys the previous searchable data set on
     execution.

     It also places the database effectively offline during the update, so
     this is not a suitable method for updating a 'online' database.
     Updates should happen on an 'offline' copy that is then swapped into
     place with the 'online' database.

     Example:

          my $update = Search::InvertedIndex::Update->new(...);
          $inv_map->preload_update({ -update => $update });
                 .
          		.
          		.
          $inv_map->update_group({ -group => 'test' });

`clear_preload_update_for_group($parm_ref);'
     This clears all the data from the preload area for the specified
     group.

`update_group($parm_ref);'
     This clears the specifed group and loads all preloaded data (updates
     batch loaded through the 'preload_update' method pending finalization.

     This is by far the fastest way to load a large set of data into the
     search system - but it is an 'all or nothing' approach. No
     'incremental' updating is possible via this interface - the
     update_group completely erases all previously searchable data from
     the group and replaces it with the pending 'preload'ed data.

     Examples:

          $inv_map->update_group({ -group => 'test' });

          $inv_map->update_group({ -group => 'test', -block_size => 65536 });

     -block_size determines the 'chunking factor' used to limit the amount
     of memory the update uses (it corresponds roughly to the number of
     line entry items to be processed in memory at one time). Higher
     '-block_size's will improve performance until you run out of real
     memory. The default is 65536.

     Since an exclusive lock should be held during the entire process, the
     database is essentially inaccessible until the update is complete. It
     is probably inadvisable to use this method of updating without
     keeping an 'online' and a seperate 'offline' database and copy over
     the 'offline' to 'online' after completion of the mass update on the
     'offline' database.

`search($parm_ref);'
     Performs a query on the map and returns the results as a
     Search::InvertedIndex::Result object containing the keys and rankings.

     Example:

          my $query = Search::InvertedIndex::Query->new(...);
          my $result = $inv_map->search({ -query => $query });

     Performs a complex multi-key match search with boolean logic and
     optional search term weighting.

     The search request is formatted as follows:

     my $result = $inv_map->search({ -query => $query });

     where '$query' is a Search::InvertedIndex::Query object.

     Each node can either be a specific search term with an optional
     weighting term (a Search::InvertedIndex::Query::Leaf object) or a
     logic term with its own sub-branches (a Search::Inverted::Query
     object).

     The weightings are applied to the returned matches for each search
     term by multiplication of their base ranking before combination with
     the other logic terms.

     This allows recursive use of search to resolve arbitrarily complex
     boolean searches and weight different search terms.

`data_for_index($parm_ref);'
     Returns the data record for the passed -index. Returns undef if no
     matching -index is in the system.

     Example:   my $data = $self->data_for_index({ -index => $index });

`clear_all;'
     Completely clears the contents of the database and the search cache.

`clear_cache;'
     Completely clears the contents of the search cache.

`close;'
     Closes the currently open -map and flushes all associated buffers.

`DESTROY;'
     Closes the currently open -map and flushes all associated buffers.

`number_of_groups;'
     Returns the raw number of groups in the system.

     Example: my $n = $inv_map->number_of_groups;

`number_of_indexes;'
     Returns the raw number of indexes in the system.

     Example: my $n = $inv_map->number_of_indexes;

`number_of_keys;'
     Returns the raw number of keys in the system.

     Example: my $n = $inv_map->number_of_keys;

`number_of_indexes_in_group($parm_ref);'
     Returns the raw number of indexes in a specific group.

     Example: my $n = $inv_map->number_of_indexes_in_group({ -group =>
     $group });

`number_of_keys_in_group($parm_ref);'
     Returns the raw number of keys in a specific group.

     Example: my $n = $inv_map->number_of_keys_in_group({ -group => $group
     });

`add_group($parm_ref);'
     Adds a new '-group' to the map. There is normally no need to call
     this method from outside the module. The addition of new -groups is
     done automatically when adding new entries.

     Example: $inv_map->add_group({ -group => $group });

     croaks if unable to successfuly create the group for some reason.

     It silently eats attempts to create an existing group.

`add_index($parm_ref);'
     Adds a index entry to the system.

     Example: $inv_map->add_index({ -index => $index, -data => $data });

     If the 'index' is the same as an existing index, the '-data' for that
     index will be updated.

     -data can be pretty much any scalar. strings/object/hash/array
     references are ok.  They will be transparently serialized using
     Storable (preferred) or Data::Dumper.

     This method should be called to set the '-data' record returned by
     searches to something useful. If you do not, you will have to
     maintain the information you want to show to users seperately from
     the main search engine core.

     The method returns the index_enum of the index.

`add_index_to_group($parm_ref);'
     Adds an index entry to a group. If the index does not already exist
     in the system, adds it to the system as well.

     Example: $inv_map->add_index_to_group({ -group => $group, '-index' =>
     $index[, -data => $data]});

     Returns the 'index_enum' for the index record.

     If the 'index' is the same as an existing key, the 'index_enum' of the
     existing index will be returned.

     There is normally no need to call this method directly. Addition of
     index to groups is handled automatically during addition of new
     entries.

     It cannot be used to add index to non-existant groups. This is a
     feature not a bug.

`add_key_to_group($parm_ref);'
     Adds a key entry to a group.

     Example: $inv_map->_add_key({ -group => $group, -key => $key });

     Returns the 'key_enum' for the key record.

     If the 'key' is the same as an existing key, the 'key_enum' of the
     existing key will be returned.

     There is normally no need to call this method directly. Addition of
     keys to groups is handled automatically during addition of new
     entries.

     It cannot be used to add keys to non-existant groups. This is a
     feature not a bug.

`add_entry_to_group($parm_ref);'
     Adds a reference to a particular index for a key with a ranking to a
     specific group.

     Example: $inv_map->add_entry_to_group({ -group => $group, -key =>
     $key, -index => $index, -ranking => $ranking });

     This method cannot be used to create new -indexes or -groups. This is
     a feature, not a bug.  It *will* create new -keys as needed.

`remove_group($parm_ref);'
     Remove all entries for a group from the map.

     Example: $inv_map->remove_group({ -group => $group });

     This removes all key and key/index entries for the group and all
     other group specific data from the map.

     Use this method when you wish to completely delete a searchable
     'group' from the map without disturbing other existing groups.

`remove_entry_from_group($parm_ref);'
     Remove a specific key<->index entry from the map for a group.

     Example: $inv_map->remove_entry_from_group({ -group => $group, -key
     => $key, -index => $index });

     Does not remove the -key or -index from the database or the group -
     only the entries mapping the two to each other.

`remove_index_from_group ($parm_ref);'
     Remove all references to a specific index for all keys for a group.

     Example: $inv_map->_remove_index_from_group({ -group => $group,
     -index => $index });

     Note: This *does not* remove the index from the _system_ - just a
     specific       group.

     It is a null operation to remove an undeclared index or to remove a
     declared index from a group where it is not used.

`remove_index_from_all ($parm_ref);'
     Remove all references to a specific index from the system.

     Example: $inv_map->_remove_index_from_all({ -index => $index });

     This *completely* removes it from all groups and the master system
     entries.

     It is a null operation to remove an undefined index.

`remove_key_from_group($parm_ref);'
     Remove all references to a specific key for all indexes for a group.

     Example: $inv_map->remove({ -group => $group, -key => $key });

     Returns undef if the key speced was not even in database.  Returns
     '1' if the key speced was in the database, and has             been
     successfully deleted.

     croaks on errors.

`list_all_keys_in_group($parm_ref);'
     Returns an anonymous array containing a list of all defined keys in
     the specified group.

     Example:  $keys = $inv_map->list_all_keys_in_group({ -group => $group
     });

     Note: This can result in *HUGE* returned lists. If you have a lot of
     records in the group, you are better off using the iteration support
     ('first_key_in_group', 'next_key_in_group').

`first_key_in_group($parm_ref);'
     Returns the 'first' key in the -group based on hash ordering.

     Returns 'undef' if there are no keys in the group.

     Example: my $first_key = $inv_map->first_key_in_group({-group =>
     $group});

`next_key_in_group($parm_ref);'
     Returns the 'next' key in the group based on hash ordering.

     Returns 'undef' when there are no more keys in the group or if the
     passed -key is not in the group map.

     Example: my $next_key = $inv_map->next_key_in_group({ -group =>
     $group, -key => $key });

`list_all_indexes_in_group($parm_ref);'
     Returns an anonymous array containing a list of all defined indexes
     in the group

     Example: $indexes = $inv_map->list_all_indexes_in_group({ -group =>
     $group });

     Note: This can result in *HUGE* returned lists. If you have a lot of
     records in the group, you are better off using the iteration support
     (first_index_in_group(), next_index_in_group())

`first_index_in_group;'
     Returns the 'first' index in the -group based on hash ordering.
     Returns 'undef' if there are no indexes in the group.

     Example: my $first_index = $inv_map->first_index_in_group({ -group =>
     $group });

`next_index_in_group({-group =' $group, -index => $index});>
     Returns the 'next' index in the -group based on hash ordering.
     Returns 'undef' if there are no more indexes.

     Example: my $next_index = $inv_map->next_index_in_group({-group =>
     group, -index => $index});

`list_all_indexes;'
     Returns an anonymous array containing a list of all defined indexes
     in the map.

     Example: $indexes = $inv_map->list_all_indexes;

     Note: This can result in *HUGE* returned lists. If you have a lot of
     records in the map or do not have a lot memory, you are better off
     using the iteration support ('first_index', 'next_index')

`first_index;'
     Returns the 'first' index in the system based on hash ordering.
     Returns 'undef' if there are no indexes.

     Example: my $first_index = $inv_map->first_index;

`next_index({-index =' $index});>
     Returns the 'next' index in the system based on hash ordering.
     Returns 'undef' if there are no more indexes.

     Example: my $next_index = $inv_map->next_index({-index => $index});

`list_all_groups;'
     Returns an anonymous array containing a list of all defined groups in
     the map.

     Example: $groups = $inv_map->list_all_groups;

     If you have a lot of groups in the map or do not have a lot of memory,
     you are better off using the iteration support ('first_group',
     'next_group')

`first_group;'
     Returns the 'first' group in the system based on hash ordering.
     Returns 'undef' if there are no groups.

     Example: my $first_group = $inv_map->first_group;

`next_group ({-group =' $group });>
     Returns the 'next' group in the system based on hash ordering.
     Returns 'undef' if there are no more groups.

     Example: my $next_group = $inv_map->next_group({-group => $group});

Internals
---------

   The routines after this point are _internal_ to the object.  Do not
access them from outside the object.

   They are documented in the POD for code maintainence reasons only.

   You Have Been Warned. ;)

`_bare_search($parm_ref);'
     Performs a query on the map and returns the results as a an anonymous
     array containing the keys and rankings.

     Example:

          my $query = Search::InvertedIndex::Query->new(...);
          my $result = $inv_map->search({ -query => $query });

     Performs a complex multi-key match search with boolean logic and
     optional search term weighting.

     The search request is formatted as follows:

     my $result = $inv_map->search({ -query => $query });

     where '$query' is a Search::InvertedIndex::Query object.

     Each node can either be a specific search term with an optional
     weighting term (a Search::InvertedIndex::Query::Leaf object) or a
     logic term with its own sub-branches (a Search::Inverted::Query
     object).

     The weightings are applied to the returned matches for each search
     term by multiplication of their base ranking before combination with
     the other logic terms.

     This allows recursive use of search to resolve arbitrarily complex
     boolean searches and weight different search terms.

     Returns a reference to a hash of indexes and their rankings.

`_get_data_for_index_enum($parm_ref);'
     Returns the data record for the passed -index_enum.

     Returns undef if no data record exists for the requested -index_enum.

     Example:   my $data = $self->_get_data_for_index_enum({ -index_enum
     => $index_enum });

`_and($terms);'
     Takes the passed list of search data results and merges them via
     logical _and. Merged ranking is the sum of the individual rankings.

`_nand($terms);'
     Takes the passed list of search data results and merges them via
     logical NAND (Not And). Merged ranking is the sum of the individual
     rankings.

`_or($terms);'
     Takes the passed list of search data results and merges them via
     logical OR. Merged ranking is the sum of the individual rankings.

`_pack_list($hash_ref);'
     Internal method. Not for access outside of the module.

     Packs the passed hash ref of enum keys and signed 16 bit int values
     into a dense binary structure. There is an endian dependancy here.

`_unpack_list($packed_list);'
     Internal method. Not for access outside of the module.

     Unpacks the passed dense binary structure into an anonymous hash of
     enum keys and signed 16 bit int values.  There is an endian
     dependancy here.

`_increment_enum($enum_value);'
     Internal method. Not for access outside of the module.

     Increments an 'enum' (internally a 12 digit hexadecimal number) by 1.

`_untaint($string);'
     Untaints the passed string. Use with care.

DATABASE STRUCTURES
===================

   The inverted database uses a complex overlay built on a generic
key/value accessible database (it really is fairly 'database agnostic').

   It is organized into sub-sets of information by database key name space:

     ; Counter. Incremented for new groups, decremented for deleted groups.
     number_of_groups        -> # (decimal integer)

     ; Counter. Incremented for new indexes, decremented for deleted indexes.
     number_of_indexes       -> # (decimal integer)

     ; Counter. Incremented for new keys, decremented for deleted keys.
     number_of_keys          -> # (decimal integer)

     ; The 'high water' mark used in assigning new index_enum keys
     index_enum_counter      -> # (12 digit hex number)

     ; Maps an index ("file") to its assigned index enumeration key
     $INDEX<index>               -> index_enum

     ; Maps the assigned index enumeration back to the index ("file") and
     ; provides pointers to the 'next' and 'prev' index_enums in the system
     $INDEX_ENUM<index_enum>         -> _next_index_enum_ _prev_index_enum_ index

     ; Maps the 'first' 'index_enum' for the system
     ${INDEX_ENUM}first_index_enum     -> index_enum of 'first' index_enum for the system

     ; Data record for the index ("File"). Wrapped using 'Storable' or 'Data::Dumper'
     $INDEX_ENUM_DATA<index_enum>_data   -> data

     ; The 'high water' mark used in assigning new group_enum keys
     group_enum_counter      -> # (12 digit hex number)

     ; Maps a group's name to its assigned group enumeration key
     $GROUP<groupname>           -> group_enum

     ; Maps the assigned group enumeration key to a group and provides
     ; pointers to the 'next' and 'previous' groups in the system.
     $GROUP_ENUM<group_enum>         -> _prev_group_enum_ _next_group_enum_ $group

     ; Maps the 'first' 'group_enum' for the system
     ${GROUP_ENUM}first_group_enum     -> group_enum of 'first' group_enum for the system

     ; Counter. Incremented for new keys, decremented for deleted keys.
     $GROUP_ENUM_DATA<group_enum>_number_of_keys     -> # (decimal integer)

     ; Counter. Incremented for new indexes, decremented for deleted indexes.
     $GROUP_ENUM_DATA<group_enum>_number_of_indexes  -> #  (decimal integer)

     ; 'High water' mark used in assigning new key_enum values for keys
     $GROUP_ENUM_DATA<group_enum>_key_enum_counter   -> # (12 digit hex number)

     ; Maps the 'first' 'key_enum' for the group
     $GROUP_ENUM_DATA<group_enum>_first_key_enum         -> key_enum of 'first' key_enum

     ; Maps the 'first' 'index_enum' for the group
     $GROUP_ENUM_DATA<group_enum>_first_index_enum       -> index_enum of 'first' index_enum for the group

     ; network order packed list of (6 byte) key_enums and
     ; (16 bit signed) relevance rankings for the specified group_enum
     ; and index_enum
     $GROUP_ENUM_DATA<group_enum>$INDEXED_KEY_LIST<index_enum>           -> key_list

     ; Pointers to the 'next' and 'previous' index_enums for this group.
     $GROUP_ENUM_DATA<group_enum>$INDEX_ENUM_GROUP_CHAIN<index_enum>           -> _prev_index_enum_ _next_index_enum_

     ; network order packed list of (6 byte) index_enums
     ; and (16 bit signed) relevance rankings for the specified group_enum
     ; and key_enum
     $GROUP_ENUM_DATA<group_enum>$KEYED_INDEX_LIST<key_enum>             -> index_list

     ; Maps 'key's to 'key_enum's
     $GROUP_ENUM_DATA<group_enum>$KEY_TO_KEY_ENUM<key>                  -> key_enum

     ; Maps 'key_enum's to 'key's and provides pointers to the
     ; 'next' and 'previous' keys for the group
     $GROUP_ENUM_DATA<group_enum>$KEY_ENUM_TO_KEY_AND_CHAIN<key_enum>             -> _prev_key_enum_ _next_key_enum_ key

VERSION
=======

   1.11

COPYRIGHT
=========

   Copyright 1999, Benjamin Franz (<URL:http://www.nihongo.org/snowhare/>)
and FreeRun Technologies, Inc. (<URL:http://www.freeruntech.com/>). All
Rights Reserved.  This software may be copied or redistributed under the
same terms as Perl itelf.

AUTHOR
======

   Benjamin Franz

TODO
====

   Everything.

   Concept item for evaluation: By storing a dense list of all indexed
keywords, you would be able to use a regular expression or other fuzzy
search matching scheme comparatively efficiently, locate possible words
via a grep and then search on the possibilities. Seems to make sense to
implement that as _another_ module that uses this module as a backend.
'Search::InvertedIndex::Fuzzy' perhaps.

SEE ALSO
========

     Search::InvertedIndex::Query  Search::InvertedIndex::Query::Leaf
     Search::InvertedIndex::Result Search::InvertedIndex::Update
     Search::InvertedIndex::DB::DB_File_SplitHash
     Search::InvertedIndex::DB::Mysql

A manager for autoloading Search::InvertedIndex modules
*******************************************************

NAME
====

   Search::InvertedIndex::AutoLoader - A manager for autoloading
Search::InvertedIndex modules

SYNOPSIS
========

   use Search::InvertedIndex::AutoLoader;

DESCRIPTION
===========

   Sets up the autoloader to load the modules in the Search::InvertedIndex
system on demand.

CHANGES
=======

   1.01 Added Search::InvertedIndex::DB::Mysql to the list of autoloaded
modules

COPYRIGHT
=========

   Copyright 1999, Benjamin Franz (<URL:http://www.nihongo.org/snowhare/>)
and FreeRun Technologies, Inc. (<URL:http://www.freeruntech.com/>). All
Rights Reserved.  This software may be copied or redistributed under the
same terms as Perl itelf.

AUTHOR
======

   Benjamin Franz

TODO
====

   Nothing.

A Berkeley database interface object for Search::InvertedIndex
**************************************************************

NAME
====

   Search::InvertedIndex::DB::DB_File_SplitHash - A Berkeley database
interface object for Search::InvertedIndex

SYNOPSIS
========

     use Search::InvertedIndex::DB::DB_File_SplitHash;

     my $db = Search::InvertedIndex::DB::DB_File_SplitHash->new({
                -map_name => '/www/search-engine/databases/test-map_names/test',
                   -multi => 4,
               -file_mode => 0644,
               -lock_mode => 'EX',
            -lock_timeout => 30,
          -blocking_locks => 0,
               -cachesize => 1000000,
           -write_through => 0,
         -read_write_mode => 'RDONLY';
           });

     my $inv_map = Search::InvertedIndex->new({ -database => $db });

     my $query = Search::InvertedIndex::Query->new(...);
     my $result = $inv_map->search({ -query => $query });

     my $update = Search::InvertedIndex::Update->new(...);
     my $result = $inv_map->update({ -update => $update });

     $inv_map->close;

DESCRIPTION
===========

   Provides a standard interface to an underlaying database - in this case
Berkeley DB as extended by the Tie::DB_File::SplitHash package.

   There are twelve standard API calls required of any database interface
used by the Search::InvertedIndex module:

     new     - Takes all parameters required for initialization.
               Free form parameters as required by the underlaying
               database.
     open    - Actually opens the database. No parameters.
     close   - Closes the database. No parameters.
     lock    - Sets a lock state of (UN, SH or EX) and optionally allows setting/
               changing the 'blocking/non-blocking' and timeouts for locking.
     get     - Fetches a string -value for a -key. Returns 'undef' if no -key matches in the database.
     put     - Stores a string -value for a -key. Returns true on success, false on failure.
     exists  - Returns true if the -key is defined in the database, false otherwise.
     delete  - Removes a -key and associated -value from database. Returns true on success, false on failure.
     clear   - Clears all keys/values from the database
     status  - Returns open and lock status messages.

     DESTROY - Used to dispose of the database object

CHANGES
=======

     1.00 1999.06.16 - Initial release.

     1.01 1999.06.17 - Bug fix to 'close' method. Failed to clear the filehandle used for locking.

     1.02 1999.06.18 - Major bugfix to locking system and performance tweaking

     1.03 1999.07.01 - Documentation corrections.

     1.04 1999.10.20 - Removed use of 'use attr' for portability improvement

     1.06 2000.01.25 - Bugfix (added 'use Tie::DB_File::SplitHash;' to initialization)

     1.07 2000.03.23 - Bugfix for disposal when database was never actually opened

Public API
----------

`new($parm_ref);'
     Provides the interface for obtaining a new Search::InvertedIndex
     object for manipulating a inverted database.

     Example 1: my $inv_map = Search::InvertedIndex->new;

     Example 2: my $inv_map = Search::InvertedIndex->new({
         -map_name => '/tmp/imap', # file path to map
        -multi => 4,           # multiple DB file factor. Defaults to 4
                      -file_mode => 0644,        # File permissions to
     open with. Defaults to 0666.                      -cachesize =>
     1000000,     # DB cache size. Defaults to 1000000
     -lock_mode => 'EX',        # DB lock mode. Defaults to EX
         -lock_timeout => 30,          # Seconds to try and get locks.
     Defaults to 30                 -write_through => 0,           # Write
     through on cache? Defaults to 0 (no)                -blocking_locks
     => 0,           # Locks should block? Defaults to 0 (no)
     -read_write_mode => 'RDWR',      # RDONLY or RDWR? Defaults to 'RDWR'
                 });

`open;'
     Actually open the database for use.

     Example 1: $inv_map->open;

`status($parm_ref);'
     Returns the requested status line for the database. Allowed requests
     are '-open', and '-lock'.

     Example 1:  my $status = $db->status(-open); # Returns either '1' or
     '0'

     Example 2:  my $status = $db->status(-lock_mode); # Returns 'UN',
     'SH' or 'EX'

`lock($parm_ref);'
     Sets or changes a filesystem lock on the underlaying database files.
     Forces 'sync' if the stat is changed from 'EX' to a lower lock state
     (i.e. 'SH' or 'UN'). Croaks on errors.

     Example:

          $inv->lock({ -lock_mode => 'EX',
                    -lock_timeout => 30,
                  -blocking_locks => 0,
                });

     The only _required_ parameter is the -lock_mode. The other parameters
     can be inherited from the object state. If the other parameters are
     used, they change the object state to match the new settings.

`close;'
     Closes the currently open -map_name and flushes all associated
     buffers.

`DESTROY;'
     Closes the currently open -map_name and flushes all associated
     buffers.

`put({ -key =' $key, -value => $value });>
     Stores the -value at the -key location in the database. No
     serialization is performed - this is a pure 'store a string' method.
     Returns '1' on success, '0' on failure.

`get({ -key =' $key });>
     Returns the -value at the -key location in the database. No
     deserialization is performed - this is a pure 'fetch a string'
     method. It returns 'undef' if no such key exists in the database.

     Example:

          my ($value) = $db->get({ -key => $key });

`delete({ -key =' $key });>
     Deletes the -value at the -key location in the database.

`exists{-key =' $key});>
     Returns true if the -key exists in the database.  Returns false if
     the -key does not exist in the database.

`clear;'
     Internal method. Not for access outside of the module.

     Completely clears the map database.

`_open_multi_map;'
     Internal method. Not for access outside of the module.

     Actually open the map for use using either DB_File or
     Tie::DB_File_SplitHash as appropriate.

     Example 1: $self->_open_multi_map;

COPYRIGHT
=========

   Copyright 1999, Benjamin Franz (<URL:http://www.nihongo.org/snowhare/>)
and FreeRun Technologies, Inc. (<URL:http://www.freeruntech.com/>). All
Rights Reserved.  This software may be copied or redistributed under the
same terms as Perl itelf.

AUTHOR
======

   Benjamin Franz

TODO
====

   Everything.

A MySQL database interface object for Search::InvertedIndex
***********************************************************

NAME
====

   Search::InvertedIndex::DB::Mysql - A MySQL database interface object
for Search::InvertedIndex

SYNOPSIS
========

     use Search::InvertedIndex::DB::Mysql;

     my $db = Search::InvertedIndex::DB::Mysql->new({
                 -db_name => 'searchdb',
                -hostname => 'db.domain.com',
                -username => 'dbuser',
                -password => 'dbuserpw',
              -table_name => 'indextablename',
               -lock_mode => 'EX' });

     my $inv_map = Search::InvertedIndex->new({ -database => $db });

     my $query = Search::InvertedIndex::Query->new(...);
     my $result = $inv_map->search({ -query => $query });

     my $update = Search::InvertedIndex::Update->new(...);
     my $result = $inv_map->update({ -update => $update });

     $inv_map->close;

DESCRIPTION
===========

   An interface allowing Search::InvertedIndex to store and retrieve data
from Mysql database tables. All of the data is stored in a single table,
which will be created automatically if it does not exist when the new
method is called.

   The new method takes up to six parameters, two of which are required.

`-db_name'
     Mysql database name. Required.

`-table_name'
     Table within the database to use. *CAUTION* If this table exists, the
     clear method will erase the contents WITHOUT verifying that the table
     contains data the module understands. If you point the module to an
     existing table you do so at your own risk! Required.

`-hostname'
     Mysql database host. Default: database server is on the local machine.

`-username'
     User for connecting to the Mysql server. The user must have
     appropriate authority for the operations you are performing or Mysql
     may complain.  Default: none.

`-password'
     Password for the User. Default: none.

`-lock_mode'
     Locking status for the database table. EX, SH, or UN. EX will attempt
     to obtain a WRITE lock on the table, SH a READ lock, and UN will not
     request one at all. Tables may be created and modified in any mode,
     but EX is obviously recommended.

CHANGES
=======

     1.00 2000.11.28 - First version.

COPYRIGHT
=========

   This software may be copied or redistributed under the same terms as
Perl itelf.

AUTHOR
======

   Michael Cramer <cramer@webkist.com>, based on
Search::InvertedIndex::DB::DB_File_SplitHash by Benjamin Franz.

NOTES
=====

   This module is not tested during installation due to its need for MySQL
support in Perl and associated access permissions and so on.

   You *MUST* have the DBI and DBD::mysql modules installed to be able to
use this module.

   Theoretically, someone could use this module as a starting point for
creating support for all kinds of DBI supported databases.

SEE ALSO
========

   Search::InvertedIndex Search::InvertedIndex::DB::DB_File_SplitHash DBI
DBD::mysql

A query for an inverted index search.
*************************************

NAME
====

   Search::InvertedIndex::Query - A query for an inverted index search.

SYNOPSIS
========

DESCRIPTION
===========

   Provides methods for setting up a search query to be performed by the
search engine.

CHANGES
=======

     1.01 1999.06.30 - Documentation updates

Public API
----------

   Inherits 'get','set','clear' and 'exists' methods from Class::NamedParms

Initialization
--------------

`new($parm_ref);'
     Returns and optionally initializes a new Search::InvertedIndex::Query
     object.

     Examples:

          my $query = Search::InvertedIndex::Query->new;

          my $query = Search::InvertedIndex::Query->new({ -logic => 'or',
                                                         -weight => 0.5,
                                                          -nodes => \@query_nodes,
                                                          -leafs => \@leaf_nodes,
                                                         });

     -nodes must be 'Search::InvertedIndex::Query' objects.  -leafs must
     be 'Search::InvertedIndex::Query::Leaf' objects.  -logic applies to
     both -nodes (after search resolution) and -leafs.         If omitted,
     -logic is defaults to 'and'. Allowed logic values 	   are 'and', 'or'
     and  'nand'.  -weight is applied to the _result_ of a search of the
     Query object and         is optional (defaulted to '1' if omitted).

     Inherits 'get/set' methods from Class::NamedParms - thus to 'append'
     use the 'get' method on '-nodes' or '-leafs',  'push' the new thing
     on the end of the anon array return, and use the 'set' method to save
     the updated anon array.

COPYRIGHT
=========

   Copyright 1999, Benjamin Franz (<URL:http://www.nihongo.org/snowhare/>)
and FreeRun Technologies, Inc. (<URL:http://www.freeruntech.com/>). All
Rights Reserved.  This software may be copied or redistributed under the
same terms as Perl itelf.

AUTHOR
======

   Benjamin Franz

TODO
====

   Everything.

A query leaf item for an inverted index search.
***********************************************

NAME
====

   Search::InvertedIndex::Query::Leaf - A query leaf item for an inverted
index search.

SYNOPSIS
========

DESCRIPTION
===========

   Provides an object for holding the specifics of a search term item.

`new($parm_ref);'
     Creates and initializes a Search::InvertedIndex::Query::Leaf object:

          Example:
           my $leaf = Search::InvertedIndex::Query::Leaf->new({
                                                      -key => 'sterling',
                                                    -group => 'wineries',
                                                   -weight => 1,
                                                    });

          -group and -key are required, -weight is optional.

     Inherits 'get','set','clear','exists' methods from Class::NamedParms

COPYRIGHT
=========

   Copyright 1999, Benjamin Franz (<URL:http://www.nihongo.org/snowhare/>)
and FreeRun Technologies, Inc. (<URL:http://www.freeruntech.com/>). All
Rights Reserved.  This software may be copied or redistributed under the
same terms as Perl itelf.

AUTHOR
======

   Benjamin Franz

TODO
====

   Document.

A list of result entries from a inverted index search.
******************************************************

NAME
====

   Search::InvertedIndex::Result - A list of result entries from a
inverted index search.

SYNOPSIS
========

DESCRIPTION
===========

   Contains zero or more result entries from a search. Provides access
methods to information in/from/about the entries.

CHANGES
=======

     1.00 1999.6.16 - Initial release

     1.01 1999.6.17 - Documentation fixes

Public API
----------

Initialization
--------------

`new($parm_ref);'

`number_of_index_entries;'
     Returns the number of index entries in the result.

`entry($parm_ref);'
     In an array context, returns the index, data and ranking for the
     requested entry.

     In a scalar context returns only the index.

     Examples:

          my $index = $result->entry({ -number => 10 };

          my ($index,$data,$ranking) = $result->entry({ -number => 10 });

COPYRIGHT
=========

   Copyright 1999, Benjamin Franz (<URL:http://www.nihongo.org/snowhare/>)
and FreeRun Technologies, Inc. (<URL:http://www.freeruntech.com/>). All
Rights Reserved.  This software may be copied or redistributed under the
same terms as Perl itelf.

AUTHOR
======

   Benjamin Franz

TODO
====

   Everything.

A container for a mass data update for a -group/-index.
*******************************************************

NAME
====

   Search::InvertedIndex::Update - A container for a mass data update for
a -group/-index.

SYNOPSIS
========

DESCRIPTION
===========

   Provides a container for the information to perform an update for a
-group/-index tuple.

Public API
----------

   Inherits 'get','set','clear' and 'exists' methods from Class::NamedParms

Initialization
--------------

`new($parm_ref);'
     Returns and optionally initializes a new Search::InvertedIndex::Update
     object.

     Examples:

          my $update = Search::InvertedIndex::Update->new;

          my $update = Search::InvertedIndex::Update->new({ -group => $group,
                                                            -index => $index,
                                                             -data => $index_data,
                                                             -keys => {
          												               $key0 => 10,
          															   $key1 => 20,
          															   $key2 => 15,
          													         },
          												 });

     Inherits 'get/set' methods from Class::NamedParms

     The -keys parameter is a reference to a hash containing all the keys
     for this index and their assigned rankings. Rankings are allowed to
     be integer values between -32768 and +32767 inclusive.

     The -group and -index are required, the -keys are optional. The
     Update object is used for update by replacement of all -keys for the
     specified -group and -index.  All existing keys are deleted and the
     passed -keys is used to insert a completely new set of keys for the
     specified index/group.

     The -data parameter is optional, but if passed will replace the
     existing -data record for the -index.

COPYRIGHT
=========

   Copyright 1999, Benjamin Franz (<URL:http://www.nihongo.org/snowhare/>)
and FreeRun Technologies, Inc. (<URL:http://www.freeruntech.com/>). All
Rights Reserved.  This software may be copied or redistributed under the
same terms as Perl itelf.

AUTHOR
======

   Benjamin Franz

TODO
====

   Everything.

Perl extension to use the ACE/Server Administration Toolkit API
***************************************************************

NAME
====

   SecurID::ACEdb - Perl extension to use the ACE/Server Administration
Toolkit API

SYNOPSIS
========

     use SecurID::ACEdb qw(:basic func1 func2 ...)
     use SecurID::ACEdb qw(:all);
     ApiInit();
     ...
     ApiEnd();

DESCRIPTION
===========

   The ACE/Server Administration Toolkit API is used to create custom
administration applications for ACE/Server, specifically functions that
can read and modify the ACE/Server databases.

FUNCTIONS
=========

   All functions must be explicitly imported into the namespace. The import
tag *basic* imports ApiInit, ApiEnd, and Result. The import tag all
imports all functions.

   Unless otherwise documented, all function calls return 1 if the function
succeeded, 0 otherwise.

Result
------

     $result = Result();

   Returns the result of the last operation as a string. This should be
called whenever any function fails to determine the cause of the failure.

ApiInit
-------

     ApiInit([commitFlag => v]);

   Initializes and connects to the ACE/Server databases. This is required
before subsequent `SecurID::ACEdb' functions can be called. The
`commitFlag' should be set to true to automatically commit database
changes. If not set, then the Commit and Rollback functions can be used to
define transactions. *This function can only be called once in any
program. It cannot even be called a second time after calling ApiEnd*.
Don't blame me; blame Security Dynamics.

Commit
------

     Commit();

   Commits all API function calls to the database since the last commit or
rollback. Only needed if ApiInit was not called with a `commitFlag' of
true.

Rollback
--------

     Rollback();

   Rolls back all API function calls since the last commit or rollback.
Only needed if ApiInit was not called with a `commitFlag' of true.

ApiEnd
------

     ApiEnd();

   Finishes the API session. Once this function is called, no subsequent
API functions can be called, *including ApiInit*.

ApiRev
------

     $rev = ApiRev()

   Returns the revision number of the API, as a string.

AssignToken
-----------

     AssignToken($lastname, $firstname, $login, $shell, $serial);

   Adds a user to the database and assigns the token specified by
`$serial'. The token is enabled, the PIN is cleared, and both
BadTokenCodes and BadPINs are set to zero.

SetUser
-------

     SetUser($lastname, $firstname, $login, $shell, $serial);

   Sets an existing user's information as specified by the parameters.
The token serial number is used to locate the user in the database, so
this function cannot be used to change a user's token.

ListUserInfo
------------

     $userinfo = ListUserInfo($serial);

   Returns user information for a user who owns the specified token. The
user information is returned in a hashref which contains the keys
*userNum*, *lastName*, *firstName*, *defaultLogin*, *createPIN*,
*mustCreatePIN*, *defaultShell*, *tempUser*, *dateStart*, *todStart*,
*dateEnd*, and *todEnd*. Returns undef if there was an error.

UnassignToken
-------------

     UnassignToken($serial)

   Unassigns the token and deletes the user from the database. The user
must be removed from all groups and not be enabled on any clients before
calling this function.

SetCreatePin
------------

     SetCreatePin($state, $serial);

   Sets the createPIN modes for the user related to `$serial'. $state
should be a string containing one of the values USER, SYSTEM, or *EITHER*.

AddUserExtension
----------------

     AddUserExtension($key, $data, $serial);

   Adds a user extension record for the user related to `$serial'. The
data field can be no more than 80 characters, while the key field must be
no more than 48 characters.

DelUserExtension
----------------

     DelUserExtension($key, $serial);

   Deletes a user extension record for the user related to `$serial'.

ListUserExtension
-----------------

     $ext = ListUserExtension($key, $serial);

   Returns the user extension data for the specified key of the user
related to `$serial'. Returns undef if there was an error.

SetUserExtension
----------------

     SetUserExtension($key, $data, $serial);

   Sets data in an existing extension field for the user related to
`$serial'.

DisableToken
------------

     DisableToken($serial);

   Disables the token so that the related user cannot authenticate.

EnableToken
-----------

     EnableToken($serial);

   Enables the token so that the related user can authenticate.

ListTokens
----------

     @list = ListTokens();

   Returns a list of all tokens in the database, or an empty list if there
was an error. Note that the underlying C API requires this function to be
called multiple times to get the entire list; the Perl version does not
require this. If a call to the function other than the first results in an
error, ListTokens will return a partial list, and will not notify the
caller of any error condition. The caller should examine the value of
`Result()'; if it is not *Done*, then the entire list was not returned.

ListTokenInfo
-------------

     $info = ListTokenInfo($serial);

   Returns a hashref containing token information, or undef if there was
an error. The hashref contains the keys *serialNum*, *pinClear*,
*numDigits*, interval, *dateBirth*, *todBirth*, *dateDeath*, *todDeath*,
*dateLastLogin*, *todLastLogin*, type, hex, enabled, *newPINMode*,
*userNum*, *nextTCodeStatus*, *badTokenCodes*, *badPINs*, *datePIN*,
*todPIN*, *dateEnabled*, *todEnabled*, *dateCountsLastModified*, and
*todCountsLastModified*.

ResetToken
----------

     ResetToken($serial);

   Resets the token to a known state, so that the token is enabled, next
token code mode is off, bad token codes is zero, and bad PINs is zero.
This should be done before assigning the token to a user or to remedy
token problems.

NewPin
------

     NewPin($serial)

   Puts the token into new PIN mode.

AddLoginToGroup
---------------

     AddLoginToGroup($login, $group, $shell, $serial);

   Adds the user login to a group in the database. The group must exist
and the login must be unique to the group. The shell can be an empty
string.

DelLoginFromGroup
-----------------

     DelLoginFromGroup($login, $group);

   Deletes the login name from a group.

ListGroupMembership
-------------------

     $groups = ListGroupMembership($serial);

   Lists the groups that a token has been assigned to. Returns a listref
or undef if there was a problem. Each element of the list is a hashref
containing the keys *userName*, *shell*, and group.

ListGroups
----------

     $groups = ListGroups();

   Lists the groups in the ACE/Server database. Returns a listref or undef
if there was a problem. Each element of the list is a hashref containing
the keys group and *siteName*.

EnableLoginOnClient
-------------------

     EnableLoginOnClient($login, $client, $shell, $serial);

   Enables a user login on a client. The client must exist and the login
must be unique to the client. The shell can be an empty string.

DelLoginFromClient
------------------

     DelLoginFromClient($login, $client);

   Disables a user login from a client.

ListClientActivations
---------------------

     $list = ListClientActivations($serial);

   Lists the clients that a token is activated on. Returns a listref or
undef if there was an error. Each element of the list is a hashref
containing the keys login, *shell*, *clientName*, and *siteName*.

ListClientsForGroup
-------------------

     $list = ListClientsForGroup($group);

   Lists the clients associated with a group. Returns a listref or undef
if there was a problem. Each element of the list is a hashref containing
the keys *clientName* and *siteName*.

ListClients
-----------

     $list = ListClients();

   Returns a list of all clients in the database. Returns a listref or
undef if there was a problem. Each element of the list is a hashref
containing the keys *clientName* and *siteName*.

ListSerialByLogin
-----------------

     @serial = ListSerialByLogin($login, [$count]);

   Looks up the token serial number belonging to the user with login name
`$login'. $count specifies which instance of `$login' to use if there are
multiple instances, and defaults to 1. Returns a listref to the serial
numbers assigned to `$login'. Returns an empty listref if the user does
not exist, or if the count was too high, and returns undef if there was
another error.

ListHistory
-----------

     $hist = ListHistory($days, $serial, [$filter]);

   Lists the events in the activity log affecting token `$serial'.
`$days' specifies the number of days prior to the present date to list the
history for. If `$filter' is true, events performed by an administrator
will be filtered from the list, making it easier to view authentication
events. Returns a listref or undef if there was a problem. Each element of
the list is a hashref containing the keys *msgString*, *localDate*,
*localTOD*, login, *affectedUserName*, *groupName*, *clientName*,
*siteName*, *serverName*, and *messageNum*.

MonitorHistory
--------------

     MonitorHistory([$filename, [$close]]);

   Docs tbd.

DumpHistory
-----------

     DumpHistory($month, $day, $year, [$days, [$filename, [$truncate]]]);

   Dumps the affected events in the log. If $filename is provided,
specifies a filename to dump the log to. $filename can also be the empty
string. The affected events start at the beginning of the log and end one
day prior to the date specified by the $month, $day, and $year parameters.
$year should be a 4-digit number. If the `$days' parameter is non-zero,
then the first three parameters are ignored, and the `$days' parameters
specifies the number of days prior to today's date that are not affected.
If the `$truncate' option is set, the entries will be removed from the log.

AUTHOR
======

   Dave Carrigan <Dave.Carrigan@cnpl.enbridge.com>

SEE ALSO
========

   perl(1).

A module to open or create files within suid/sgid files
*******************************************************

NAME
====

   `Secure::File' - A module to open or create files within suid/sgid files

SYNOPSIS
========

     use Secure::File;
     my $SF = new Secure::File;
     $SF->open();

     my $NF = new Secure::File, 'myfile';

DESCRIPTION
===========

   open  This checks that both the effective and real  user / group ids
have sufficient permissions to use the specified file.  (Standard open
calls only check the effective ids).  `Secure::File' also checks that the
file we open, really is the same file we checked ids on.

   If the file already exists, open will fail.

WARNING <==============================================================>
========================================================================

   E<DO NOT TRUST THIS MODULE>.  Every effort has been made to make this
module useful, but it can not make a secure system out of an insecure one.
It can not read the programers mind.

Author
======

   Randall Maas (`mailto:randym@acm.org' in this node, `http:' in this
node)

save and restore selected file handle
*************************************

NAME
====

   SelectSaver - save and restore selected file handle

SYNOPSIS
========

     use SelectSaver;

     {
        my $saver = new SelectSaver(FILEHANDLE);
        # FILEHANDLE is selected
     }
     # previous handle is selected

     {
        my $saver = new SelectSaver;
        # new handle may be selected, or not
     }
     # previous handle is selected

DESCRIPTION
===========

   A SelectSaver object contains a reference to the file handle that was
selected when it was created.  If its new method gets an extra parameter,
then that parameter is selected; otherwise, the selected file handle
remains unchanged.

   When a SelectSaver is destroyed, it re-selects the file handle that was
selected when it was created.

load functions only on demand
*****************************

NAME
====

   SelfLoader - load functions only on demand

SYNOPSIS
========

     package FOOBAR;
     use SelfLoader;

     ... (initializing code)

     __DATA__
     sub {....

DESCRIPTION
===========

   This module tells its users that functions in the FOOBAR package are to
be autoloaded from after the `__DATA__' token.  See also `"Autoloading"',
see Perlsub (perl.info).

The __DATA__ token
------------------

   The `__DATA__' token tells the perl compiler that the perl code for
compilation is finished. Everything after the `__DATA__' token is
available for reading via the filehandle FOOBAR::DATA, where FOOBAR is the
name of the current package when the `__DATA__' token is reached. This
works just the same as `__END__' does in package 'main', but for other
modules data after `__END__' is not automatically retrievable, whereas
data after `__DATA__' is.  The `__DATA__' token is not recognized in
versions of perl prior to 5.001m.

   Note that it is possible to have `__DATA__' tokens in the same package
in multiple files, and that the last `__DATA__' token in a given package
that is encountered by the compiler is the one accessible by the
filehandle. This also applies to `__END__' and main, i.e. if the 'main'
program has an `__END__', but a module 'require'd (_not_ 'use'd) by that
program has a 'package main;' declaration followed by an '`__DATA__'',
then the DATA filehandle is set to access the data after the `__DATA__' in
the module, _not_ the data after the `__END__' token in the 'main'
program, since the compiler encounters the 'require'd file later.

SelfLoader autoloading
----------------------

   The SelfLoader works by the user placing the `__DATA__' token after
perl code which needs to be compiled and run at 'require' time, but before
subroutine declarations that can be loaded in later - usually because they
may never be called.

   The SelfLoader will read from the FOOBAR::DATA filehandle to load in
the data after `__DATA__', and load in any subroutine when it is called.
The costs are the one-time parsing of the data after `__DATA__', and a
load delay for the _first_ call of any autoloaded function. The benefits
(hopefully) are a speeded up compilation phase, with no need to load
functions which are never used.

   The SelfLoader will stop reading from `__DATA__' if it encounters the
`__END__' token - just as you would expect.  If the `__END__' token is
present, and is followed by the token DATA, then the SelfLoader leaves the
FOOBAR::DATA filehandle open on the line after that token.

   The SelfLoader exports the AUTOLOAD subroutine to the package using the
SelfLoader, and this loads the called subroutine when it is first called.

   There is no advantage to putting subroutines which will _always_ be
called after the `__DATA__' token.

Autoloading and package lexicals
--------------------------------

   A 'my $pack_lexical' statement makes the variable $pack_lexical local
_only_ to the file up to the `__DATA__' token. Subroutines declared
elsewhere _cannot_ see these types of variables, just as if you declared
subroutines in the package but in another file, they cannot see these
variables.

   So specifically, autoloaded functions cannot see package lexicals (this
applies to both the SelfLoader and the Autoloader).  The vars pragma
provides an alternative to defining package-level globals that will be
visible to autoloaded routines. See the documentation on vars in the
pragma section of Perlmod (perl.info).

SelfLoader and AutoLoader
-------------------------

   The SelfLoader can replace the AutoLoader - just change 'use AutoLoader'
to 'use SelfLoader' (though note that the SelfLoader exports the AUTOLOAD
function - but if you have your own AUTOLOAD and are using the AutoLoader
too, you probably know what you're doing), and the `__END__' token to
`__DATA__'. You will need perl version 5.001m or later to use this
(version 5.001 with all patches up to patch m).

   There is no need to inherit from the SelfLoader.

   The SelfLoader works similarly to the AutoLoader, but picks up the subs
from after the `__DATA__' instead of in the 'lib/auto' directory.  There
is a maintenance gain in not needing to run AutoSplit on the module at
installation, and a runtime gain in not needing to keep opening and
closing files to load subs. There is a runtime loss in needing to parse
the code after the `__DATA__'. Details of the AutoLoader and another view
of these distinctions can be found in that module's documentation.

__DATA__, __END__, and the FOOBAR::DATA filehandle.
---------------------------------------------------

   This section is only relevant if you want to use the `FOOBAR::DATA'
together with the SelfLoader.

   Data after the `__DATA__' token in a module is read using the
FOOBAR::DATA filehandle. `__END__' can still be used to denote the end of
the `__DATA__' section if followed by the token DATA - this is supported
by the SelfLoader. The `FOOBAR::DATA' filehandle is left open if an
`__END__' followed by a DATA is found, with the filehandle positioned at
the start of the line after the `__END__' token. If no `__END__' token is
present, or an `__END__' token with no DATA token on the same line, then
the filehandle is closed.

   The SelfLoader reads from wherever the current position of the
`FOOBAR::DATA' filehandle is, until the EOF or `__END__'. This means that
if you want to use that filehandle (and ONLY if you want to), you should
either

   1. Put all your subroutine declarations immediately after the
`__DATA__' token and put your own data after those declarations, using the
`__END__' token to mark the end of subroutine declarations. You must also
ensure that the SelfLoader reads first by  calling
'SelfLoader->load_stubs();', or by using a function which is selfloaded;

   or

   2. You should read the `FOOBAR::DATA' filehandle first, leaving the
handle open and positioned at the first line of subroutine declarations.

   You could conceivably do both.

Classes and inherited methods.
------------------------------

   For modules which are not classes, this section is not relevant.  This
section is only relevant if you have methods which could be inherited.

   A subroutine stub (or forward declaration) looks like

     sub stub;

   i.e. it is a subroutine declaration without the body of the subroutine.
For modules which are not classes, there is no real need for stubs as far
as autoloading is concerned.

   For modules which ARE classes, and need to handle inherited methods,
stubs are needed to ensure that the method inheritance mechanism works
properly. You can load the stubs into the module at 'require' time, by
adding the statement 'SelfLoader->load_stubs();' to the module to do this.

   The alternative is to put the stubs in before the `__DATA__' token
BEFORE releasing the module, and for this purpose the Devel::SelfStubber
module is available.  However this does require the extra step of ensuring
that the stubs are in the module. If this is done I strongly recommend
that this is done BEFORE releasing the module - it should NOT be done at
install time in general.

Multiple packages and fully qualified subroutine names
======================================================

   Subroutines in multiple packages within the same file are supported -
but you should note that this requires exporting the
`SelfLoader::AUTOLOAD' to every package which requires it. This is done
automatically by the SelfLoader when it first loads the subs into the
cache, but you should really specify it in the initialization before the
`__DATA__' by putting a 'use SelfLoader' statement in each package.

   Fully qualified subroutine names are also supported. For example,

     __DATA__
     sub foo::bar {23}
     package baz;
     sub dob {32}

   will all be loaded correctly by the SelfLoader, and the SelfLoader will
ensure that the packages 'foo' and 'baz' correctly have the SelfLoader
AUTOLOAD method when the data after `__DATA__' is first parsed.

writing perl code with the word 'Peterbilt' as statement terminator, rather than a semicolon.
*********************************************************************************************

NAME
====

   Semi::Semicolons - writing perl code with the word 'Peterbilt' as
statement terminator, rather than a semicolon.

SYNOPSIS
========

     use Semi::Semicolons;
     print "Why????"Peterbilt
     print "Because of the mouche"Peterbilt

DESCRIPTION
===========

   This is perhaps the stupidest piece of perl code ever written (for its
size, anyway...)

   What this does is allow you to write code using the word Peterbilt as
your statement terminator, rather than the usual semicolon.

   For the adventurous, Semi::Semicolons allows you to customize your
statement terminator:

     use Semi::Semicolons qw(Mack);
     print "What's your twenty, Snowman?"Mack

AUTHOR
======

   David H. Adler <dha@panix.com> and Michael G Schwern <schwern@pobox.com>
(from an idea by Adam Turoff)

SEE ALSO
========

   perl(1)

   "Beneath the Valley of the Ultravixens" (Russ Meyer)

   "Convoy" (C. W. McCall)

   "Smokey and the Bandit", et. al. (Burt Reynolds)

   "The Golden Age of Colonic Irrigation" (Monty Python's Flying Circus)

Add client-server behavior to scripts.
**************************************

NAME
====

   Server::FastPL - Add client-server behavior to scripts.

VERSION
=======

   This document refers to version 1.00 of Server::FastPL, released April
10, 2000

SYNOPSIS
========

   -- server --

   use Server::FastPL;

   my $fps = new Server::FastPL(TYPE=>"SERVER",NAME=>"Test");

   while ($client = $fps->receive_connect()) {    ...  }

   -- client --

   use Server::FastPL;

   my $server = new Server::FastPL(TYPE=>"CLIENT",SERVER=>"/tmp/Test");

   ...

DESCRIPTION
===========

Overview
--------

   This module is just a convenience wrapper for Server::FastPL::Server and
Server::FastPL::Client. You might prefer to use these modules instead of
this one.

   See Server::FastPL::Server and Server::FastPL::Client for instructions.

SEE ALSO
========

   Server::FastPL::Server; Server::FastPL::Client;

COPYRIGHT
=========

   Copyright (c) 2000, Daniel Ruoso. All Rights Reserved.  This module is
free software. It may be used, redistributed and/or modified under the
same terms of Perl itself

A Client to the Server::FastPL::Server module.
**********************************************

NAME
====

   Server::FastPL::Client - A Client to the Server::FastPL::Server module.

VERSION
=======

   This document refers to version 1.00 of Server::FastPL::Client,
released April 10, 2000.

SYNOPSIS
========

     use Server::FastPL::Client;

     $server = new Server::FastPL::Client(SERVER => "/tmp/Test");

     ...

DESCRIPTION
===========

Overview
--------

   This module connect to a Unix Socket Server, waits for a one line reply
that indicate a new Socket to connect, and then returns the Socket
FileHandle to the definitive server.

Constructor and Initialization
------------------------------

   $server = new Server::FastPL::Client(SERVER=>"/tmp/Teste");

   There is only one parameter, SERVER. This indicates the primary socket
that the module will connect, this function returns the socket filehandle
of the definitive server.

SEE ALSO
========

   Any Information about how it works is on Server::FastPL::Server

AUTHOR
======

   Daniel Ruoso (daniel@ruoso.com)

COPYRIGHT
=========

   Copyright (c) 2000, Daniel Ruoso. All Rights Reserved.  This modules is
free software. It may be userd, redistributed and/or modified under the
same terms of Perl itself.

Eliminate the compile-time of big scripts
*****************************************

NAME
====

   Server::FastPL::Server - Eliminate the compile-time of big scripts

VERSION
=======

   This document refers to version 1.00 of Server::FastPL::Server,
released April 10, 2000.

SYNOPSIS
========

   use Server::FastPL::Server

   my $fps = new
Server::FastPL::Server(NAME=>"Test",MAX_CHILDS=>5,DEBUG=>1);

   while ($client = $fps->receive_connect()) {   ...  }

DESCRIPTION
===========

Overview
--------

   This module was created to avoid the compile time of big scripts that
runs a lot of times. It works forking your script into MAX_CHILDS childs,
and using Unix Sockets to run your code. Just like CGI::Fast. Combining
whith Server::FastPL::Client, you can easily do a client-server program.

Contructor and initialization
-----------------------------

   $fps = new Server::FastPL::Server(  # REQUIRED: This is the name of the
socket file  NAME => "Test",  # Socket files dir. "/tmp/" as default.
SOCKET_DIR => "/tmp/",  # Number of childs to fork, 5 as default.
MAX_CHILDS => 5,  # Debug about the childs. 0 as default.   DEBUG => 0 )
|| die $!;

Class and object methods
------------------------

   $client = $fps->receive_connect();

   This method waits for a connection, and return a FileHandle (a Socket)
to input/output of the server.

ENVIRONMENT
===========

   Signals:

   This module uses two signals: USR1 and CHLD, don\'t use it in your
script, it will cause the server not to work.

   %ENV:

   The environment hash is not passed from the client to the server. You
must do it by your own way.

DIAGNOSTICS
===========

   All error messages are passed to $!. Use it in your script to detect
errors.

BUGS
====

   No known bugs at this moment.

FILES
=====

   The module creates the folowing files in directory SOCKET_DIR:

NAME The main socket
NAME.x A socket for each child
NAME.fifo Comunication beetwen mother and children
SEE ALSO
========

   Server::FastPL::Client IO::Socket

AUTHOR
======

   Daniel Ruoso (daniel@ruoso.com)

COPYRIGHT
=========

   Copyright (c) 2000, Daniel Ruoso. All Rights Reserved.  This module is
free software. It may be used, redistributed and/or modified under the
same terms of Perl itself

Perl Extension for writing modules
**********************************

NAME
====

   Seshat - Perl Extension for writing modules

   "Seshat, her who writes..."

SYNOPSIS
========

     use Seshat;

     my $lh = Seshat->new($log_filename[, PARAM => VALUE [, ...]]);

     $res = $lh->write($string,$nl_bool);

DESCRIPTION
===========

     Seshat is a module designed to handle more than one log, and log files shared by two or more processes.
     It is a concurrency safe system, and implements extra information about the script that is writing the log.

METHODS
=======

$lh = Seshat->new($log_filename [, PARAM => VALUE [, ...]])
     Creates a new object that uses th $log_filename as the log file

     Parameter description:

     DATE_FORMAT => $string

     Defines the format of the date that is written to the log file

          Types:

          %a -> short day
          %A -> long day
          %b -> short month
          %B -> long month
          %d -> month day
          %g -> last 2 dig of year
          %G -> year
          %c -> long date
          %D -> short date
          %F -> short date (inverted)
          %H -> hour
          %M -> minutes
          %S -> seconds

          ex: "%a %b %G - %H:%M:%S"
               Tue Oct 2000 - 13:59:41

     LOG_LEVEL => [0..5]

          Defines the amount of information about the caller script that is written to the log file

$res = $lh->write($string,$nl_bool);
     Writes the $string to the log file , and terminates the line or not
     ($nl_bool)

TODO
====

   Sugestions accepted

AUTHOR
======

   Bruno Tavares (bat@isp.novis.pt)

SEE ALSO
========

   perl(1), Seshat::Parallel(1)

Perl extension for Seshat
*************************

NAME
====

   Seshat::Parallel - Perl extension for Seshat

SYNOPSIS
========

     use Seshat::Parallel;

     my $plh = Seshat::Parallel->new("filename1"[,"filename2",...]);

     $plh->write($string, $bol_flag);

     my $res = $plh->registar("filename3");

     my $res = $plh->register("filename1");

DESCRIPTION
===========

   This is an extension for Seshat, it introduces multiple , simultaneous,
log writing.  The module uses a list of filenames given by the user and,
every time its required, the modulo writes the string to all the filenames
specified.

AUTHOR
======

   Bruno Tavares (bruno.tav@clix.pt)

SEE ALSO
========

   perl(1).

bag (multiset) class
********************

NAME
====

     Set::Bag - bag (multiset) class

SYNOPSIS
========

     use Set::Bag;

     my $bag_a = Set::Bag->new(apples => 3, oranges => 4);
     my $bag_b = Set::Bag->new(mangos => 3);
     my $bag_c = Set::Bag->new(apples => 1);
     my $bag_d = ...;

     # Methods

     $bag_b->insert(apples => 1);
     $bag_b->delete(mangos => 1);

     $bag_b->insert(cherries => 1, $bag_c);

     my @b_elements = $bag_b->elements;	# ('apples','cherries','mangos')
     my @b_grab_app = $bag_b->grab('apples', 'cherries'); # (3, 1)
     my @a_grab_all = $bag_a->grab;	# (apples => 3, oranges => 4)

     print "bag_a     sum      bag_b = ", $bag_b->sum($bag_b),          "\n";
     print "bag_a  difference  bag_b = ", $bag_b->difference($bag_b),   "\n";

     print "bag_a    union     bag_b = ", $bag_a->union($bag_b),        "\n";
     print "bag_a intersection bag_b = ", $bag_a->intersection($bag_b), "\n";

     print "bag_b complement = ", $bag_b->complement, "\n";

     # Operator Overloads

     print "bag_a = $bag_a\n";		# (apples => 3, oranges => 4)

     $bag_b += $bag_c;					# Insert
     $bag_b -= $bag_d;					# Delete

     print "bag_b = $bag_b\n";

     print "bag_a + bag_b = ", $bag_b + $bag_b, "\n";	# Sum
     print "bag_a - bag_b = ", $bag_b - $bag_b, "\n";	# Difference

     print "bag_a | bag_b = ", $bag_a | $bag_b, "\n";	# Union
     print "bag_a & bag_b = ", $bag_a & $bag_b, "\n";	# Intersection

     $bag_b |= $bag_c;					# Maximize
     $bag_b &= $bag_d;					# Minimize

     print "good\n" if     $bag_a eq "(apples => 3, oranges => 4)";	# Eq
     print "bad\n"  unless $bag_a ne "(apples => 3, oranges => 4)";	# Ne

     print "-bag_b = ", -$bag_b"\n";			# Complement

     $bag_c->delete(apples => 5);			# Would abort.
     print "Can",					# Cannot ...
           $bag_c->over_delete() ? "" : "not",
           " over delete from bag_c\n";
     $bag_c->over_delete(1);
     print "Can",					# Can ...
           $bag_c->over_delete() ? "" : "not",
           " over delete from bag_c\n";
     $bag_c->delete(apples => 5);			# Would succeed.
     print $bag_c, "\n";					# ()

DESCRIPTION
===========

   This module implements a simple bag (multiset) class.

   A bag may contain one or more instances of elements.  One may add and
delete one or more instances at a time.

   If one attempts to delete more instances than there are to delete from,
the default behavious of delete is to raise an exception.  The
*over_delete* method can be used to control this behaviour.

   Inserting or removing negative number of instances translates into
removing or inserting positive number of instances, respectively.

   The sum is also known as the *additive union*.  It leaves in the result
bag the sum of all the instances of all bags.

   Before using the *difference* you very often will need the
*over_delete*.

   The union is also known as the *maximal union*.  It leaves in the
result bag the maximal number of instances in all bags.

   The intersection leaves in the result bag only the elements that have
instances in all bags and of those the minimal number of instances.

   The *complement* will leave in the result bag the maximal number of
instances *ever* seen (via new, insert, sum, or *maximize*) in the bag
minus the current number of instances in the bag.

   The *grab* method returns the contents of a bag.  If used with
parameters the parameters are the elements and their number of instances
in the bag are returned.  If an element that does not exist in the bag is
grabbed for, the number of instances returned for that element will be
undef.  If used without parameters the elements are returned in
pseudorandom order.

NOTES
=====

   Beware the low precedence of | and & compared with eq and ne.

AUTHOR
======

   Jarkko Hietaniemi <jhi@iki.fi>

COPYRIGHT
=========

   O'Reilly and Associates.  This module can be distributed under the same
terms as Perl itself.

Expand crontab(5)-style integer lists
*************************************

NAME
====

   Set::Crontab - Expand crontab(5)-style integer lists

SYNOPSIS
========

   $s = Set::Crontab->new("1-9/3,>15,>30,!23", [0..30]);

   if ($s->contains(3)) { ... }

DESCRIPTION
===========

   Set::Crontab parses crontab-style lists of integers and defines some
utility functions to make it easier to deal with them.

Syntax
------

   Numbers, ranges, *, and step values all work exactly as described in
`crontab(5)' in this node. A few extensions to the standard syntax are
described below.

< and >
     <N selects the elements smaller than N from the entire range, and adds
     them to the set. >N does likewise for elements larger than N.

!
     !N excludes N from the set. It applies to the other specified range;
     otherwise it applies to the specified ranges (i.e. "!3" with a range
     of "1-10" corresponds to "1-2,4-10", but ">3,!7" in the same range
     means "4-6,8-10").

Functions
---------

new($spec, [@range])
     Creates a new Set::Crontab and returns a reference to it.

contains($num)
     Returns true if $num exists in the set.

list()
     Returns the expanded list corresponding to the set.

   The functions described above croak if they are called with incorrect
arguments.

SEE ALSO
========

   `crontab(5)' in this node

AUTHOR
======

   Abhijit Menon-Sen <ams@wiw.org>

   Copyright 2001 Abhijit Menon-Sen. All Rights Reserved.

   This is free software; you may redistribute and/or modify it under the
same terms as Perl itself.

Sets of Integers
****************

NAME
====

   Set::IntRange - Sets of Integers

   Easy manipulation of sets of integers (arbitrary intervals)

SYNOPSIS
========

METHODS
-------

     Version
         $version = $Set::IntRange::VERSION;

     new
         $set = Set::IntRange->new($lower,$upper);
         $set = $any_set->new($lower,$upper);

     Resize
         $set->Resize($lower,$upper);

     Size
         ($lower,$upper) = $set->Size();

     Empty
         $set->Empty();

     Fill
         $set->Fill();

     Flip
         $set->Flip();

     Interval_Empty
         $set->Interval_Empty($lower,$upper);
         $set->Empty_Interval($lower,$upper); # (deprecated)

     Interval_Fill
         $set->Interval_Fill($lower,$upper);
         $set->Fill_Interval($lower,$upper);  # (deprecated)

     Interval_Flip
         $set->Interval_Flip($lower,$upper);
         $set->Flip_Interval($lower,$upper);  # (deprecated)

     Interval_Scan_inc
         while (($min,$max) = $set->Interval_Scan_inc($start))

     Interval_Scan_dec
         while (($min,$max) = $set->Interval_Scan_dec($start))

     Bit_Off
         $set->Bit_Off($index);
         $set->Delete($index);                # (deprecated)

     Bit_On
         $set->Bit_On($index);
         $set->Insert($index);                # (deprecated)

     bit_flip
         $bit = $set->bit_flip($index);
         if ($set->bit_flip($index))
         $bit = $set->flip($index);           # (deprecated)
         if ($set->flip($index))              # (deprecated)

     bit_test
         $bit = $set->bit_test($index);
         if ($set->bit_test($index))
         $bit = $set->contains($index);
         if ($set->contains($index))
         $bit = $set->in($index);             # (deprecated)
         if ($set->in($index))                # (deprecated)

     Norm
         $norm = $set->Norm();

     Min
         $min = $set->Min();

     Max
         $max = $set->Max();

     Union
         $set1->Union($set2,$set3);           # in-place is possible!

     Intersection
         $set1->Intersection($set2,$set3);    # in-place is possible!

     Difference
         $set1->Difference($set2,$set3);      # in-place is possible!

     ExclusiveOr
         $set1->ExclusiveOr($set2,$set3);     # in-place is possible!

     Complement
         $set1->Complement($set2);            # in-place is possible!

     is_empty
         if ($set->is_empty())

     is_full
         if ($set->is_full())

     equal
         if ($set1->equal($set2))

     subset
         if ($set1->subset($set2))
         if ($set1->inclusion($set2))         # (deprecated)

     Lexicompare
         $cmp = $set1->Lexicompare($set2);    # unsigned

     Compare
         $cmp = $set1->Compare($set2);        # signed

     Copy
         $set1->Copy($set2);

     Shadow
         $other_set = $some_set->Shadow();

     Clone
         $twin_set = $some_set->Clone();

     to_Enum
         $string = $set->to_Enum();           # e.g., "-8..-5,-1..2,4,6..9"

     from_Enum
         eval { $set->from_Enum($string); };

     to_Hex
         $string = $set->to_Hex();            # e.g., "0007AF1E"

     from_Hex
         eval { $set->from_Hex($string); };

     BitVector
         $set->BitVector->any_Bit_Vector_method();

OVERLOADED OPERATORS
--------------------

     # "$index" is a number or a Perl scalar variable containing a
     # number which represents the set containing only that element:

     Emptyness
         if ($set) # if not empty
         if (! $set) # if empty
         unless ($set) # if empty

     Equality
         if ($set1 == $set2)
         if ($set1 != $set2)
         if ($set == $index)
         if ($set != $index)

     Lexical Comparison
         $cmp = $set1 cmp $set2;
         if ($set1 lt $set2)
         if ($set1 le $set2)
         if ($set1 gt $set2)
         if ($set1 ge $set2)
         if ($set1 eq $set2)
         if ($set1 ne $set2)
         $cmp = $set cmp $index;
         if ($set lt $index)
         if ($set le $index)
         if ($set gt $index)
         if ($set ge $index)
         if ($set eq $index)
         if ($set ne $index)

     String Conversion
         $string = "$set";
         print "\$set = '$set'\n";

     Union
         $set1 = $set2 + $set3;
         $set1 += $set2;
         $set1 = $set2 | $set3;
         $set1 |= $set2;
         $set1 = $set2 + $index;
         $set += $index;
         $set1 = $set2 | $index;
         $set |= $index;

     Intersection
         $set1 = $set2 * $set3;
         $set1 *= $set2;
         $set1 = $set2 & $set3;
         $set1 &= $set2;
         $set1 = $set2 * $index;
         $set *= $index;
         $set1 = $set2 & $index;
         $set &= $index;

     Difference
         $set1 = $set2 - $set3;
         $set1 -= $set2;
         $set1 = $set2 - $set1;
         $set1 = $set2 - $index;
         $set1 = $index - $set2;
         $set -= $index;

     ExclusiveOr
         $set1 = $set2 ^ $set3;
         $set1 ^= $set2;
         $set1 = $set2 ^ $index;
         $set ^= $index;

     Complement
         $set1 = -$set2;
         $set1 = ~$set2;
         $set = -$set;
         $set = ~$set;

     Subset Relationship
         if ($set1 <= $set2)

     True Subset Relationship
         if ($set1 < $set2)

     Superset Relationship
         if ($set1 >= $set2)

     True Superset Relationship
         if ($set1 > $set2)

     Norm
         $norm = abs($set);

DESCRIPTION
===========

   This class lets you dynamically create sets of arbitrary intervals of
integers and perform all the basic operations for sets on them (for a list
of available methods and operators, see above).

   See `Bit::Vector(3)' in this node for more details!

SEE ALSO
========

   Bit::Vector(3), Set::IntegerFast(3), Math::MatrixBool(3),
Math::MatrixReal(3), DFA::Kleene(3), Math::Kleene(3), Graph::Kruskal(3).

VERSION
=======

   This man page documents "Set::IntRange" version 5.0.

AUTHOR
======

   Steffen Beyer <sb@sdm.de>.

COPYRIGHT
=========

   Copyright (c) 1996, 1997 by Steffen Beyer. All rights reserved.

LICENSE
=======

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Manages sets of integers
************************

NAME
====

   Set::IntSpan - Manages sets of integers

SYNOPSIS
========

     use Set::IntSpan qw(grep_set map_set);

     $Set::IntSpan::Empty_String = $string;

     $set    = new   Set::IntSpan $set_spec;
     $valid  = valid Set::IntSpan $run_list;
     $set    = copy  $set $set_spec;

     $run_list = run_list $set;
     @elements = elements $set;

     $u_set = union      $set $set_spec;
     $i_set = intersect  $set $set_spec;
     $x_set = xor        $set $set_spec;
     $d_set = diff       $set $set_spec;
     $c_set = complement $set;

     equal      $set $set_spec;
     equivalent $set $set_spec;
     superset   $set $set_spec;
     subset     $set $set_spec;

     $n = cardinality $set;

     empty      $set;
     finite     $set;
     neg_inf    $set;
     pos_inf    $set;
     infinite   $set;
     universal  $set;

     member     $set $n;
     insert     $set $n;
     remove     $set $n;

     $min = min $set;
     $max = max $set;

     $subset = grep_set { ... } $set;
     $mapset = map_set  { ... } $set;

     for ($element=$set->first; defined $element; $element=$set->next) { ... }
     for ($element=$set->last ; defined $element; $element=$set->prev) { ... }

     $element = $set->start($n);
     $element = $set->current;

REQUIRES
========

   Perl 5.004, Exporter

EXPORTS
=======

`@EXPORT'
---------

   Nothing

`@EXPORT_OK'
------------

   `grep_set', `map_set'

DESCRIPTION
===========

   `Set::IntSpan' manages sets of integers.  It is optimized for sets that
have long runs of consecutive integers.  These arise, for example, in
.newsrc files, which maintain lists of articles:

     alt.foo: 1-21,28,31
     alt.bar: 1-14192,14194,14196-14221

   Sets are stored internally in a run-length coded form.  This provides
for both compact storage and efficient computation.  In particular, set
operations can be performed directly on the encoded representation.

   `Set::IntSpan' is designed to manage finite sets.  However, it can also
represent some simple infinite sets, such as {x | x>n}.  This allows
operations involving complements to be carried out consistently, without
having to worry about the actual value of INT_MAX on your machine.

SET SPECIFICATIONS
==================

   Many of the methods take a *set specification*.  There are four kinds
of set specifications.

Empty
-----

   If a set specification is omitted, then the empty set is assumed.  Thus,

     $set = new Set::IntSpan;

   creates a new, empty set.  Similarly,

     copy $set;

   removes all elements from $set.

Object reference
----------------

   If an object reference is given, it is taken to be a `Set::IntSpan'
object.

Array reference
---------------

   If an array reference is given, then the elements of the array are
taken to be the elements of the set.  The array may contain duplicate
elements.  The elements of the array may be in any order.

Run list
--------

   If a string is given, it is taken to be a *run list*.  A run list
specifies a set using a syntax similar to that in newsrc files.

   A run list is a comma-separated list of *runs*.  Each run specifies a
set of consecutive integers.  The set is the union of all the runs.

   Runs may be written in any of several forms.

Finite forms
------------

n
     { n }

a-b
     {x | a<=x && x<=b}

Infinite forms
--------------

(-n
     {x | x<=n}

n-)
     {x | x>=n}

(-)
     The set of all integers

Empty forms
-----------

   The empty set is consistently written as " (the null string).  It is
also denoted by the special form '-' (a single dash).

Restrictions
------------

   The runs in a run list must be disjoint, and must be listed in
increasing order.

   Valid characters in a run list are 0-9, '(', ')', '-' and ','.  White
space and underscore (_) are ignored.  Other characters are not allowed.

Examples
--------

 -
     { }

 1
     { 1 }

 1-2
     { 1, 2 }

 -5-1
     { -5, -4, -3, -2, -1 }

 (-)
     the integers

 (-1
     the negative integers

 1-3, 4, 18-21
     { 1, 2, 3, 4, 18, 19, 20, 21 }

ITERATORS
=========

   Each set has a single *iterator*, which is shared by all calls to
first, last, start, next, prev, and current.  At all times, the iterator
is either an element of the set, or undef.

   first, last, and start set the iterator; next, and prev move it; and
current returns it.  Calls to these methods may be freely intermixed.

   Using next and prev, a single loop can move both forwards and backwards
through a set.  Using start, a loop can iterate over portions of an
infinite set.

METHODS
=======

Creation
--------

$set = new `Set::IntSpan' *$set_spec*
     Creates and returns a `Set::IntSpan' object.  The initial contents of
     the set are given by *$set_spec*.

$ok = valid `Set::IntSpan' $run_list
     Returns true if $run_list is a valid run list.  Otherwise, returns
     false and leaves an error message in $@.

$set = copy $set *$set_spec*
     Copies *$set_spec* into $set.  The previous contents of $set are lost.
     For convenience, copy returns $set.

$run_list = `run_list' $set
     Returns a run list that represents $set.  The run list will not
     contain white space.  $set is not affected.

     By default, the empty set is formatted as '-'; a different string may
     be specified in `$Set::IntSpan::Empty_String'.

*@elements* = elements $set
     Returns an array containing the elements of $set.  The elements will
     be sorted in numerical order.  In scalar context, returns an array
     reference.  $set is not affected.

Set operations
--------------

$u_set = union $set *$set_spec*
     Returns the set of integers in either $set or *$set_spec*.

$i_set = `intersect' $set *$set_spec*
     Returns the set of integers in both $set and *$set_spec*.

$x_set = xor $set *$set_spec*
     Returns the set of integers in $set or *$set_spec*, but not both.

$d_set = diff $set *$set_spec*
     Returns the set of integers in $set but not in *$set_spec*.

$c_set = `complement' $set
     Returns the set of integers that are not in $set.

   For all set operations, a new `Set::IntSpan' object is created and
returned.  The operands are not affected.

Comparison
----------

`equal' $set *$set_spec*
     Returns true iff $set and *$set_spec* contain the same elements.

`equivalent' $set *$set_spec*
     Returns true iff $set and *$set_spec* contain the same number of
     elements.  All infinite sets are equivalent.

`superset' $set *$set_spec*
     Returns true iff $set is a superset of *$set_spec*.

`subset' $set *$set_spec*
     Returns true iff $set is a subset of *$set_spec*.

Cardinality
-----------

$n = `cardinality' $set
     Returns the number of elements in $set.  Returns -1 for infinite sets.

empty $set
     Returns true iff $set is empty.

`finite' $set
     Returns true iff $set is finite.

`neg_inf' $set
     Returns true iff $set contains {x | x<n} for some n.

`pos_inf' $set
     Returns true iff $set contains {x | x>n} for some n.

`infinite' $set
     Returns true iff $set is infinite.

universal $set
     Returns true iff $set contains all integers.

Membership
----------

member $set $n
     Returns true iff the integer $n is a member of $set.

insert $set $n
     Inserts the integer $n into $set.  Does nothing if $n is already a
     member of $set.

remove $set $n
     Removes the integer $n from $set.  Does nothing if $n is not a member
     of $set.

Extrema
-------

min $set
     Returns the smallest element of $set, or undef if there is none.

max $set
     Returns the largest element of $set, or undef if there is none.

Iterators
---------

$set->first
     Sets the iterator for $set to the smallest element of $set.  If there
     is no smallest element, sets the iterator to undef.  Returns the
     iterator.

$set->last
     Sets the iterator for $set to the largest element of $set.  If there
     is no largest element, sets the iterator to undef.  Returns the
     iterator.

$set->start($n)
     Sets the iterator for $set to $n.  If $n is not an element of $set,
     sets the iterator to undef.  Returns the iterator.

$set->next
     Sets the iterator for $set to the next element of $set.  If there is
     no next element, sets the iterator to undef.  Returns the iterator.

     next will return undef only once; the next call to next will reset
     the iterator to the smallest element of $set.

$set->prev
     Sets the iterator for $set to the previous element of $set.  If there
     is no previous element, sets the iterator to undef.  Returns the
     iterator.

     prev will return undef only once; the next call to prev will reset
     the iterator to the largest element of $set.

$set->current
     Returns the iterator for $set.

FUNCTIONS
=========

$sub_set = `grep_set' { ... } $set
     Evaluates the BLOCK for each integer in $set (locally setting $_ to
     each integer) and returns a `Set::IntSpan' object containing those
     integers for which the BLOCK returns TRUE.

     Returns undef if $set is infinite.

$map_set = `map_set' { ... } $set
     Evaluates the BLOCK for each integer in $set (locally setting $_ to
     each integer) and returns a `Set::IntSpan' object containg all the
     integers returned as results of all those evaluations.

     Evaluates the BLOCK in list context, so each element of $set may
     produce zero, one, or more elements in the returned set.

     Returns undef if $set is infinite.

CLASS VARIABLES
===============

`$Set::IntSpan::Empty_String'
     `$Set::IntSpan::Empty_String' contains the string that is returned
     when `run_list' is called on the empty set.  `$Empty_String' is
     initially '-'; alternatively, it may be set to ".  Other values
     should be avoided, to ensure that `run_list' always returns a valid
     run list.

     `run_list' accesses `$Empty_String' through a reference stored in
     $set->{`empty_string'}.  Subclasses that wish to override the value
     of `$Empty_String' can reassign this reference.

DIAGNOSTICS
===========

   Any method (except valid) will die if it is passed an invalid run list.

`Set::IntSpan::_copy_run_list: Bad syntax:' *$runList*
     (F) $run_list has bad syntax

`Set::IntSpan::_copy_run_list: Bad order:' *$runList*
     (F) $run_list has overlapping runs or runs that are out of order.

`Set::IntSpan::elements: infinite set'
     (F) An infinte set was passed to elements.

Out of memory!
     (X) elements $set can generate an "Out of memory!"  message on
     sufficiently large finite sets.

NOTES
=====

Traps
-----

   Beware of forms like

     union $set [1..5];

   This passes an element of @set to union, which is probably not what you
want.  To force interpretation of $set and [1..5] as separate arguments,
use forms like

     union $set +[1..5];

   or

     $set->union([1..5]);

Cardinality
-----------

   You cannot use the obvious comparison routine

     { $a->cardinality <=> $b->cardinality }

   to sort sets by size, because `cardinality' returns -1 for infinte sets.
(All the non-negative integers were taken. Sorry.)

   Instead, you have to write something like

     {  my $a_card = $a->cardinality;
        my $b_card = $b->cardinality;

        $a_card == $b_card and return  0;
        $a_card <  0       and return  1;
        $b_card <  0       and return -1;
        $a_card <=> $b_card                }

grep_set and map_set
--------------------

   `grep_set' and `map_set' make it easy to construct sets for which the
internal representation used by `Set::IntSpan' is not small. Consider:

     $billion = new Set::IntSpan '0-1_000_000_000';   # OK
     $odd     = grep_set { $_ & 1 } $billion;         # trouble
     $even    = map_set  { $_ * 2 } $billion;         # double trouble

Error handling
--------------

   There are two common approaches to error handling: exceptions and
return codes.  There seems to be some religion on the topic, so
`Set::IntSpan' provides support for both.

   To catch exceptions, protect method calls with an eval:

     $run_list = <STDIN>;
     eval { $set = new Set::IntSpan $run_list };
     $@ and print "$@: try again\n";

   To check return codes, use an appropriate method call to validate
arguments:

     $run_list = <STDIN>;
     if (valid Set::IntSpan $run_list)
        { $set = new Set::IntSpan $run_list }
     else
        { print "$@ try again\n" }

   Similarly, use `finite' to protect calls to elements:

     finite $set and @elements = elements $set;

   Calling elements on a large, finite set can generate an "Out of
memory!" message, which cannot (easily) be trapped.  Applications that
must retain control after an error can use `intersect' to protect calls to
elements:

     @elements = elements { intersect $set "-1_000_000 - 1_000_000" };

   or check the size of $set first:

     finite $set and cardinality $set < 2_000_000 and @elements = elements $set;

Limitations
-----------

   Although `Set::IntSpan' can represent some infinite sets, it does not
perform infinite-precision arithmetic.  Therefore, finite elements are
restricted to the range of integers on your machine.

Roots
-----

   The sets implemented here are based on a Macintosh data structure called
a region.  See Inside Macintosh for more information.

AUTHOR
======

   Steven McDougall, swmcd@world.std.com

COPYRIGHT
=========

   Copyright 1996-1998 by Steven McDougall. This module is free software;
you can redistribute it and/or modify it under the same terms as Perl
itself.

grouped data eg ACL's, city/state/country etc
*********************************************

NAME
====

   Set::NestedGroups - grouped data eg ACL's, city/state/country etc

SYNOPSIS
========

     use Set::NestedGroups;
     $nested = new Set::NestedGroups;
     $nested->add('user','group');
     $nested->add('group','parentgroup');
     do_something() if($nested->member('user','parentgroup'));

DESCRIPTION
===========

   Set::NestedGroups gives an implementation of nested groups, access
control lists (ACLs) would be one example of nested groups.

   For example, if Joe is a Manager, and Managers have access to payroll,
you can create an ACL which implements these rules, then ask the ACL if
Joe has access to payroll.

   Another example, you may wish to track which city, state and country
people are in, by adding people to cities, cities to states, and states to
countries.

CONSTRUTORS
===========

new()
     creates a new Set::NestedGroups object.

new( fh )
     creates a new Set::NestedGroups object, the object will be
     initialized using data read from this handle. For details on the
     format, see the save() method

new( $sth )
     creates a new Set::NestedGroups object, the object will be initialized
     using data read using this this DBI statement handle.  For details on
     the format, see the save() method

METHODS
=======

add ( $member, $group)
     adds a member to a group. The group will be created if it doesn't
     already exist.

remove ( $member, $group )
     removes a member from a group. If this was the last member in this
     group, then the group will be deleted. If the member was only in this
     group, then the member will be deleted.

save(FILEHANDLE)
     Outputs the object to the given filehandle, which must be already open
     in write mode.

     The format is compatable with the format used by CGI, and can be used
     with new to initialize a new object;

     Returns true if successfully wrote the data, or false if something
     went wrong (usually that meant that the handle wasn't already open in
     write mode).

save($sth)
     Saves the object to a DBI database. This can be used with new to
     initialize a new object. The $sth should be expecting 2 values, in
     this fashion:

          $sth = $dbh->prepare('insert into acl values (?,?)')
          $acl->save($dbh);
          $sth->finish();

          $sth = $dbh->prepare('select * from acl');
          $newacl=new ACL($sth);

     Returns true if successfully wrote the data, or false if something
     went wrong.

member ( $member, $group )
     Returns true if $member is a member of $group.

member ( $member )
     returns true if $member exists in any group.

group ( $group )
     returns true if $group exists

groups ( $member, %options )
     Returns the groups that $member belongs to. Options are explained
     below.

members ( $group , %options )
     Returns the members of $group. Keep on reading for the options

list(%options)
     Returns a Set::NestedGroups::Member object that will output an list
     of the members & groups. This could be considered a calling of
     groups() on each member, except this is more efficent.

     The object can be used as follows.

          $list=$nested->list();
          for(my $i=0;$i<$list->rows();$i++){
            my ($member,$group)=$list->next();
            print "$member=$group\n";
          }

options
-------

   By default, the above methods give every valid combination. However you
might not always want that. Therefore there are options which can prevent
return of certain values.

   All of these examples presume that 'joe' is a member of 'managers', and
'managers' is a member of payroll, and that you are using only one of
these options. You can use all 3, but that gets complicated to explain.

   -norecurse=>1

   No Recursion is performed, method would ignore payroll, and return only
managers.

   -nomiddles=>1

   Doesn't returns groups 'in the middle', method would ignore mangers,
and return only payroll.

   -nogroups=>1

   Doesn't return members that are groups. This only applies to the list()
method, in which case it acts like nomiddles, except on the member instead
of the group. list would ignore managers and return joe => managers , joe
=> payroll.

   This sounds a lot more confusing than it actually is, once you try it
once or twice you'll get the idea.

AUTHOR
======

   Alan R. Barclay, gorilla@elaine.drink.com

SEE ALSO
========

   perl(1), CGI, DBI.

Set of nested groups
********************

NAME
====

   Set::NestedGroup::Member - Set of nested groups

SYNOPSIS
========

     use Set::NestedGroup;
     $acl = new Set::NestedGroup;
     $acl->add('user','group');
     $acl->add('group','parentgroup');
     $list=$acl->list();
     for(my $i=0;$i<$list->rows();$i++){
       my ($member,$group)=$list->next();
       print "$member=$group\n";
     }

DESCRIPTION
===========

   Set::NestedGroup::Member objects are returns from a Set::NestedGroup
object's list() method.

METHODS
=======

rows ()
     Returns the number of rows this has. May be used to construct a loop
     to extract all the data.

next ()
     Returns a list comprising of the next member & group. Returns undef
     when the list is exhausted.

AUTHOR
======

   Alan R. Barclay, gorilla@elaine.drink.com

SEE ALSO
========

   perl(1), Set::NestedGroup

set of objects
**************

NAME
====

   Set::Object - set of objects

SYNOPSIS
========

     use Set::Object;
     $set = Set::Object->new();

DESCRIPTION
===========

   This modules implements a set of objects, that is, an unordered
collection of objects without duplication.

CLASS METHODS
=============

new( [list] )
-------------

   Return a new `Set::Object' containing the elements passed in list.  The
elements must be objects.

INSTANCE METHODS
================

insert( [list] )
----------------

   Add objects to the `Set::Object'.  Adding the same object several times
is not an error, but any `Set::Object' will contain at most one occurence
of the same object.  Returns the number of elements that were actually
added.

includes( [list] )
------------------

   Return `true' if all the objects in list are members of the
`Set::Object'.  list may be empty, in which case `true' is returned.

members
-------

   Return the objects contained in the `Set::Object'.

size
----

   Return the number of elements in the `Set::Object'.

remove( [list] )
----------------

   Remove objects from a `Set::Object'.  Removing the same object more
than once, or removing an object absent from the `Set::Object' is not an
error.  Returns the number of elements that were actually removed.

clear
-----

   Empty this `Set::Object'.

as_string
---------

   Return a textual Smalltalk-ish representation of the `Set::Object'.
Also available as overloaded operator "".

intersection( [list] )
----------------------

   Return a new `Set::Object' containing the intersection of the
`Set::Object's passed as arguments.  Also available as overloaded operator
*.

union( [list] )
---------------

   Return a new `Set::Object' containing the union of the `Set::Object's
passed as arguments.  Also available as overloaded operator +.

subset( set )
-------------

   Return `true' if this `Set::Object' is a subset of set.  Also available
as operator <=.

proper_subset( set )
--------------------

   Return `true' if this `Set::Object' is a proper subset of set Also
available as operator <.

superset( set )
---------------

   Return `true' if this `Set::Object' is a superset of set.  Also
available as operator >=.

proper_superset( set )
----------------------

   Return `true' if this `Set::Object' is a proper superset of set Also
available as operator >.

INSTALLATION
============

   This module is partly written in C, so you'll need a C compiler to
install it.  Use the familiar sequence:

     perl Makefile.PL
     make
     make test
     make install

   This module was developed on Windows NT 4.0, using the Visual C++
compiler with Service Pack 2. It was also tested on AIX using IBM's xlc
compiler.

PERFORMANCE
===========

   The following benchmark compares `Set::Object' with using a hash to
emulate a set-like collection:

     use Set::Object;

     package Obj;
     sub new { bless { } }

     @els = map { Obj->new() } 1..1000;

     require Benchmark;

     Benchmark::timethese(100, {
        'Control' => sub { },
        'H insert' => sub { my %h = (); @h{@els} = @els; },
        'S insert' => sub { my $s = Set::Object->new(); $s->insert(@els) },
        } );

     %gh = ();
     @gh{@els} = @els;

     $gs = Set::Object->new(@els);
     $el = $els[33];

     Benchmark::timethese(100_000, {
     	   'H lookup' => sub { exists $gh{33} },
     	   'S lookup' => sub { $gs->includes($el) }
        } );

   On my computer the results are:

     Benchmark: timing 100 iterations of Control, H insert, S insert...
        Control:  0 secs ( 0.01 usr  0.00 sys =  0.01 cpu)
                 (warning: too few iterations for a reliable count)
       H insert: 68 secs (67.81 usr  0.00 sys = 67.81 cpu)
       S insert:  9 secs ( 8.81 usr  0.00 sys =  8.81 cpu)
     Benchmark: timing 100000 iterations of H lookup, S lookup...
       H lookup:  7 secs ( 7.14 usr  0.00 sys =  7.14 cpu)
       S lookup:  6 secs ( 5.94 usr  0.00 sys =  5.94 cpu)

AUTHOR
======

   Jean-Louis Leroy, jll@skynet.be

LICENCE
=======

   Copyright (c) 1998-1999, Jean-Louis Leroy. All Rights Reserved.  This
module is free software. It may be used, redistributed and/or modified
under the terms of the Perl Artistic License

SEE ALSO
========

   perl(1).  overload.pm

basic set operations
********************

NAME
====

   Set::Scalar - basic set operations

SYNOPSIS
========

     use Set::Scalar;
     $s = Set::Scalar->new;
     $s->insert('a', 'b');
     $s->delete('b');
     $t = Set::Scalar->new('x', 'y', $z);

DESCRIPTION
===========

Creating
--------

     $s = Set::Scalar->new;
     $s = Set::Scalar->new(@members);

     $t = $s->clone;

Modifying
---------

     $s->insert(@members);
     $s->delete(@members);
     $s->invert(@members); # insert if hasn't, delete if has

Displaying
----------

     print $s, "\n";

   The display format of a set is the members of the set separated by
spaces and enclosed in parentheses ().

   You can even display recursive sets.

Querying
--------

     @members  = $s->members;
     @elements = $s->elements; # alias for members

     $size = $s->size;

     if ($s->member($member)) { ...

     $s->element  # alias for member
     $s->has      # alias for member
     $s->contains # alias for member

     $s->is_null
     $s->is_universal

     $s->null	 # the null set
     $s->universe # the universe of the set

Deriving
--------

     $u = $s->union($t);
     $i = $s->intersection($t);
     $d = $s->difference($t);
     $e = $s->symmetric_difference($t);
     $v = $s->unique($t);
     $c = $s->complement;

   These methods have operator overloads:

     $u = $s + $t; # union
     $i = $s * $t; # intersection
     $d = $s - $t; # difference
     $e = $s % $t; # symmetric_difference
     $v = $s / $t; # unique
     $c = -$s;     # complement

   Both the `symmetric_difference' and unique are symmetric on all their
arguments.  For two sets they are identical but for more than two sets
beware: `symmetric_difference' returns true for elements that are in an
odd number (1, 3, 5, ...) of sets, unique returns true for elements that
are in one set.

   Some examples of the various set differences:

     set or difference                   value

     $a                                  (a b c d e)
     $b                                  (c d e f g)
     $c                                  (e f g h i)

     $a->difference($b)                  (a b)
     $a->symmetric_difference($b)        (a b f g)
     $a->unique($b)                      (a b f g)

     $b->difference($a)                  (f g)
     $b->symmetric_difference($a)        (a b f g)
     $b->unique($a)                      (a b f g)

     $a->difference($b, $c)              (a b)
     $a->symmetric_difference($b, $c)    (a b e h i)
     $a->unique($b, $c)                  (a b h i)

Comparing
---------

     $eq = $s->is_equal($t);
     $dj = $s->is_disjoint($t);
     $pi = $s->is_properly_intersecting($t);
     $ps = $s->is_proper_subset($t);
     $pS = $s->is_proper_superset($t);
     $is = $s->is_subset($t);
     $iS = $s->is_superset($t);

     $cmp = $s->compare($t);

   The compare method returns a string from the following list: "equal",
"disjoint", "proper subset", "proper superset", "proper intersect", and in
future (once I get around implementing it), "disjoint universes".

   These methods have operator overloads:

     $eq = $s == $t; # is_equal
     $dj = $s != $t; # is_disjoint
     # No operator overload for is_properly_intersecting.
     $ps = $s < $t;  # is_proper_subset
     $pS = $s > $t;  # is_proper_superset
     $is = $s <= $t; # is_subset
     $iS = $s >= $t; # is_superset

     $cmp = $s <=> $t;

AUTHOR
======

   Jarkko Hietaniemi <jhi@iki.fi>

base class for Set::Scalar
**************************

NAME
====

   Set::Scalar::Base - base class for Set::Scalar

SYNOPSIS
========

   *Internal use only*.

DESCRIPTION
===========

   See the Set::Scalar documentation.

AUTHOR
======

   Jarkko Hietaniemi <jhi@iki.fi>

internal class for Set::Scalar
******************************

NAME
====

   Set::Scalar::Null - internal class for Set::Scalar

SYNOPSIS
========

   *Internal use only*.

DESCRIPTION
===========

   *This is not the module you are looking for.* If you want documentation
see Set/Scalar.

AUTHOR
======

   Jarkko Hietaniemi <jhi@iki.fi>

internal class for Set::Scalar
******************************

NAME
====

   Set::Scalar::Real - internal class for Set::Scalar

SYNOPSIS
========

   *Internal use only*.

DESCRIPTION
===========

   *This is not the module you are looking for.* If you want documentation
see Set/Scalar.

AUTHOR
======

   Jarkko Hietaniemi <jhi@iki.fi>

universes for set members
*************************

NAME
====

   Set::Scalar::Universe - universes for set members

SYNOPSIS
========

   *Do not use directly.*

DESCRIPTION
===========

   There are only two guaranteed interfaces, both sort of indirect.

   The first one is accessing the universe of a set:

     $set->universe

   This contains the members of the universe

     $set->universe->members

   of the $set.

   The second supported interface is displaying set universes.

     print $set->universe, "\n";

   This will display the members of the set inside square brackets: [], as
opposed to sets,  which have their members shown inside parentheses: ().

AUTHOR
======

   Jarkko Hietaniemi <jhi@iki.fi>

valued sets
***********

NAME
====

   Set::Scalar::Valued - valued sets

SYNOPSIS
========

     use Set::Scalar::Valued;
     $s = Set::Scalar::Valued->new;
     $s->insert(a => 12, 'b c' => $d);
     $s->delete('b c' => $d);
     $t = Set::Scalar->new(x => $y, y => $z);

DESCRIPTION
===========

   Valued sets are an extension of the traditional set concept.  In
addition to a member just existing in the set, the member also has a
distinct value.  You can think of this a combination of a traditional set
and a Perl hash.

   The used methods are as for the traditional of Set::Scalar, with the
difference that when creating (new()) or modifying (insert(), delete(),
invert()), you must supply twice the number of arguments: the member-value
pairs, instead of just the members.  Note, though, that in the current
implementation of delete() the value half is unused, the deletion is by
the member.  In future implementation this behavior may change so that
also the value matters.

   There are a couple of additional methods:

     %ve = $s->valued_members;

   which returns the member-value pairs, and

     @v  = $s->values;

   which returns just the values (in the same order as the members()
method would return the members), and

     $v  = $s->value($member);

   which returns the value of the member.

   The display format of a valued set is the member-value pairs separated
by " => ", the pairs separated by ", " and enclosed in curly brackets {}.

AUTHOR
======

   Jarkko Hietaniemi <jhi@iki.fi>

universes for valued set members
********************************

NAME
====

   Set::Scalar::ValuedUniverse - universes for valued set members

SYNOPSIS
========

   *Do not use directly.*

DESCRIPTION
===========

   There are only two guaranteed interfaces, both sort of indirect.

   The first one is accessing the universe of a valued set:

     $valued_set->universe

   This contains the members of the universe

     $valued_set->universe->members

   of the `$valued_set'.

   The second supported interface is displaying universes of valued sets.

     print $valued_set->universe, "\n";

   This will display the members of the valued set inside square brackets:
[], as opposed to valued sets, which have their members shown inside
parentheses: ().

AUTHOR
======

   Jarkko Hietaniemi <jhi@iki.fi>

internal class for Set::Scalar
******************************

NAME
====

   Set::Scalar::Virtual - internal class for Set::Scalar

SYNOPSIS
========

   *Internal use only*.

DESCRIPTION
===========

   *This is not the module you are looking for.* If you want documentation
see Set/Scalar.

AUTHOR
======

   Jarkko Hietaniemi <jhi@iki.fi>

Manages an interval on the integer line
***************************************

NAME
====

   Set::Window - Manages an interval on the integer line

SYNOPSIS
========

     use Set::Window;

     $window  = new_lr Set::Window $left, $right;
     $window  = new_ll Set::Window $left, $length;
     $window  = empty  Set::Window;

     $left     = $window->left;
     $right    = $window->right;
     $size     = $window->size;
     @bounds   = $window->bounds;
     @elements = $window->elements;

     empty     $window;
     eqivalent $window1 $window2;
     equal     $window1 $window2;

     $window = copy        $window
     $window = offset      $window $offset
     $window = inset       $window $inset
     $window = cover       $window @windows
     $window = intersect   $window @windows

     @windows = $window->series($length);

REQUIRES
========

   Perl 5.003, Exporter

EXPORTS
=======

   Nothing

DESCRIPTION
===========

   A `Set::Window' object represents a window on the integer line; that is,
a finite set of consecutive integers.

   Methods are provided for creating and modifying windows, for obtaining
information about windows, and for performing some simple set operations
on windows.

The empty window
----------------

   The empty window represents the empty set.  Like the empty set, the
empty window is unique.

METHODS
=======

Creation
--------

`new_lr Set::Window' $left`,' $right
     Creates and returns a new `Set::Window' object.  $left and $right
     specify the first and last integers in the window.

     If $right is less than $left, returns the empty window.

`new_ll Set::Window' $left`,' $length
     Creates and returns a new Set::Window object.  $left is the first
     integer in the interval, and $length is the number of integers in the
     interval

     If $length is less than one, returns the empty window.

`empty Set::Window'
     Creates and returns an empty `Set::Window' object.

Access
------

*$window*`->left'
     Returns the first integer in the window, or undef if *$window* is
     empty.

*$window*`->right'
     Returns the last integer in the window, or undef if *$window* is
     empty.

*$window*`->size'
     Returns the number of integers in the window.

     The identity *$window*`->size == '*$window*`->right -
     '*$window*`->left + 1' holds for all non-empty windows.

*$window*`->bounds'
     Returns a list of the first and last integers in *$window*, or undef
     if *$window* is empty.  In scalar context, returns an array reference.

*$window*`->elements'
     Returns a list of the integers in *$window*, in order.  In scalar
     context, returns an array reference.

Predicates
----------

empty *$window*
     Returns true iff *$window* is empty.

`equal' *$window1* *$window2*
     Returns true iff *$window1* and *$window2* are the same.

     All empty windows are `equal'.

`equivalent' *$window1* *$window2*
     Returns true iff *$window1* and *$window2* are the same size.

Modification
------------

   These methods implement copy semantics: modifications are made to a
copy of the original window.  The original window is unaltered, and the
new window is returned.

copy *$window*
     Creates and returns a (deep) copy of *$window*.

offset *$window* $offset
     Makes a copy of *$window*, and then shifts it by $offset.  Positive
     values of $offset move the window to the right; negative values move
     it to the left.  Returns the new window.

     If offset is called on the empty window, it returns the empty window.

`inset' *$window* *$inset*
     Makes a copy of *$window*, and then shrinks it by *$inset* at each
     end.  If *$inset* is negative, the window expands.  Returns the new
     window.

     If `inset' is called on the empty window, it returns the empty window.

`cover' *$window* *@windows*
     Creates and returns the smallest window that covers (i.e. contains)
     *$window* and all the *@windows*.

`intersect' *$window* *@windows*
     Creates and returns the largest window that is contained by *$window*
     and all the *@windows*.  This may be the empty window.

Utility
-------

*$window*`->series('$length)
     Returns a list of all the windows of $length that are contained in
     *$window*, ordered from left to right.  In scalar context, returns an
     array reference.

     If $length is greater than *$window*`->length', the list will be
     empty.  If $length is less than 1, returns undef.

DIAGNOSTICS
===========

   None.

NOTES
=====

Why?
----

   Belive it or not, I actually needed this structure in a program.  Maybe
someone else will need it, too.

Weight
------

   `Set::Window' objects are designed to be lightweight.  If you need more
functionality, consider using `Set::IntSpan'.

Error handling
--------------

   `Set::Window' does not issue any diganostics; in particular, none of
the methods can die.

   Calling elements on a large window can lead to an `out of memory!'
message, which cannot be trapped (as of perl 5.003).  Applications that
must retain control can protect calls to elements with an `intersect'

     $limit = new_lr Set::Window -1_000_000, 1_000_000;
     @elements = $window->intersect($limit)->elements;

   or check the size of *$window* first:

     length $window < 2_000_000 and @elements = elements $window;

   Operations involving the empty window are handled consistently.  They
return valid results if they make sense, and undef otherwise.  Thus:

     Set::Window->empty->elements

   returns an empty list, because the empty window has no elements, while

     Set::Windows->empty->bounds

   returns undef, because the empty window has no first or last element.

SEE ALSO
========

   perl(1), `Set::IntSpan'

AUTHOR
======

   Steven McDougall, swmcd@world.std.com

COPYRIGHT
=========

   Copyright (c) 1996, 1997 Steven McDougall.  All rights reserved.  This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Perl teaches the birds and the bees.
************************************

NAME
====

   Sex - Perl teaches the birds and the bees.

SYNOPSIS
========

     package Catholicism;
     use Sex qw(strict Religion);

     package Mormonism;
     use Sex qw(Catholicism Sex);

DESCRIPTION
===========

   Heterogeneous recombination of Perl packages.

   Given two (or more, I'm a liberal guy) packages, Sex.pm will recombine
their symbols at random recombining them into the new module thus
providing a cross-section of its functions and global variables.  It will
also push the parent classes onto the child's @ISA array.

   So you could do:

     package Net::SFTP;
     use Sex qw(Net::FTP Net::SSLeay);

   And get a secure FTP client!

   The recombination occurs in such a way to ensure that the child will
contain -all- the symbols of both parents.  Should two (or more) parents
wish to bestow the same symbol on its child one will be chosen at random.

   For example:

     package DejaNews;
     use Sex qw(LWP::Simple Net::NNTP);

   LWP::Simple and Net::NNTP both have a head() function and thus they try
to give head() to their child.  Sex.pm will suck the head() off either
LWP::Simple or Net::NNTP and stick it to DejaNews.  Afterwards, DejaNews
can procede to finally use its head().

   Here's another timely example for Sex in the 21st century:

     package URI::Bot9000;
     use Sex qw(URI LWP::RobotUA protected);

   Because of the dire consequences of having sex with URI, one should
make sure you're well protected.

BUGS
====

   There are many bugs you can get from having Sex used too often on your
computer.  Please be sure your programs are Safe before they have Sex.

     package Trojan;
     use Sex qw(Safe Sex);

AUTHOR
======

   Michael 'The Porn King of CMU' Schwern  <schwern@pobox.com>

SEE ALSO
========

   'Disco Dolls in Hot Skin'

   'Exhausted:  The John Holmes Story'

   'Deep Recursion' starring Ada Lovelace.

   'The Fly' (1953)

run shell commands transparently within perl
********************************************

NAME
====

   Shell - run shell commands transparently within perl

SYNOPSIS
========

   See below.

DESCRIPTION
===========

     Date: Thu, 22 Sep 94 16:18:16 -0700
     Message-Id: <9409222318.AA17072@scalpel.netlabs.com>
     To: perl5-porters@isu.edu
     From: Larry Wall <lwall@scalpel.netlabs.com>
     Subject: a new module I just wrote

   Here's one that'll whack your mind a little out.

     #!/usr/bin/perl

     use Shell;

     $foo = echo("howdy", "<funny>", "world");
     print $foo;

     $passwd = cat("</etc/passwd");
     print $passwd;

     sub ps;
     print ps -ww;

     cp("/etc/passwd", "/tmp/passwd");

   That's maybe too gonzo.  It actually exports an AUTOLOAD to the current
package (and uncovered a bug in Beta 3, by the way).  Maybe the usual
usage should be

     use Shell qw(echo cat ps cp);

   Larry

   If you set $Shell::capture_stderr to 1, the module will attempt to
capture the STDERR of the process as well.

   The module now should work on Win32.

     Jenda

AUTHOR
======

   Larry Wall

   Changes by Jenda@Krynicky.cz and Dave Cottle
<d.cottle@csc.canterbury.ac.nz>

Perl extension for doing maths with strings
*******************************************

NAME
====

   Silly::StringMaths - Perl extension for doing maths with strings

SYNOPSIS
========

     use Silly::StringMaths qw(add subtract multiply divide exponentiate);

     # Add two positive numbers - returns ABFOOR
     print add("FOO", "BAR");

     # Add a generally positive number and a negative number
     # - returns ot
     print add("FNoRD", "yncft");

     # Subtract several numbers from a rather large one
     # - returns accdeiiiiloopssu
     print subtract("Supercalifragilisticepsialidocious",
     					  "stupid", "made", "up", "word");

     # Multiply two negative numbers - returns AAACCCCCCEEELLLNNN
     print multiply("cancel", "out");

     # Divide two numbers - returns AAA
     print divide("EuropeanCommission", "France");

     # Confirm Pythagorus' theorum - returns nothing
     print subtract(exponentiate("FETLA", "PI"),
     					  exponentiate("TLA", "PI"),
     					  exponentiate("ETLA", "PI"));

DESCRIPTION
===========

   Silly::StringMaths provides support for basic integer mathematics, using
strings rather than numbers. Upper-case letters are positive, lower-case
letters are negative, so ABCDEF would be 6 (but WOMBAT would also be 6),
whereas positive would actually be -8. Mixed-case is also possible, so
Compaq is actually -5.  Most methods return a canonicalised version of the
string - e.g. `ampq' rather than `Compaq' (mixed case removed, the result
sorted alphabetically).

   The behaviour of other characters is as yet undefined, but be warned
that non-alphabetical characters may be reserved for floating point or
imaginary numbers.

   Actual numbers (i.e. the characters 0 to 9) will never be used by this
module.

BASIC METHODS
=============

add
---

   Takes an array of strings, returns the sum.

subtract
--------

   Takes a string, subtracts all other supplied strings from it and
returns the result.

multiply
--------

   Takes a string and multiplies it by all the other strings, returning
the resulting product.

divide
------

   Takes a string, and divides it by all the other strings, returning the
result. Results are rounded down.

exponentiate
------------

   Takes a number, raises it to the appropriate power, as specified by the
other arguments. Returns the result. (Note that some textual information
is lost here - the result will be either As or as).

USEFUL TOOLBOX METHODS
======================

normalise
---------

   Takes a string with, potentially, a mix of upper-case and lower-case
letters, and returns a sorted string that is unmistakeably either positive
or negative.

sign
----

   Returns the sign of a number as either 1, 0 or -1 (as a string,
obviously).

negative
--------

   Returns whether the supplied string is negative or not

invert
------

   Takes a reference to a number, inverts it.

AUTHOR
======

   Sam Kington, sam@illuminated.co.uk

SEE ALSO
========

   perl(1).

Meaningless gibberish generator
*******************************

NAME
====

   Werder - Meaningless gibberish generator

SYNOPSIS
========

     use Silly::Werder;

     my $foo = new Silly::Werder;

     # Set the min and max number of werds per line
     $foo->set_werds_num(5, 9);

     # Set the min and max # of syllables per werd
     $foo->set_syllables_num(3, 7);

     # Set the percentage of the time a werd will start with a consonant
     $foo->set_cons_weight(75);

     # Return a random sentence, question, or exclaimation
     $line = $foo->line;

     $sentence = $foo->sentence;
     $question = $foo->question;
     $question = $foo->exclaimation;

     # Generate a long random sentence calling as a class method
     Silly::Werder->set_werds_num(10,20);
     print Silly::Werder->line;

     # All of the above methods can be used as either class methods
     # or object methods.

DESCRIPTION
===========

   This module is used to create pronouncable yet completely meaningless
language.  It is good for sending to a text-to-speech program (ala
festival), generating passwords, annoying people on irc, and all kinds of
fun things.

BUGS
====

   The only bug I am aware of is the (intentional) spelling of 'werd'
throughout the souce and documentation =)

AUTHOR
======

   Werder was created and implemented by Dave Olszewski, aka cxreg.  You
can send comments, suggestions, flames, or love letters to
dave.olszewski@osdn.com

Perl-only Constant Database
***************************

NAME
====

   SimpleCDB - Perl-only Constant Database

SYNOPSIS
========

     use SimpleCDB;

     # writer
     # - tie blocks until DB is available (exclusive), or timeout
     tie %h, 'SimpleCDB', 'db', O_WRONLY
     	 or die "tie failed: $SimpleCDB::ERROR\n";
     $h{$k} = $v;
     die "store: $SimpleCDB::ERROR" if $SimpleCDB::ERROR;
     untie %h;	# release DB (exclusive) lock

     # reader
     # - tie blocks until DB is available (shared), or timeout
     tie %h, 'SimpleCDB', 'db', O_RDONLY
     	 or die "tie failed: $SimpleCDB::ERROR\n";
     $v = $h{$i};
     die "fetch: $SimpleCDB::ERROR" if $SimpleCDB::ERROR;
     untie %h;	# release DB (shared) lock

DESCRIPTION
===========

   This is a simple perl-only DB intended for constant DB applications. A
constant DB is one which, once created, is only ever read from (though
this implementation allows appending of new data). That is, this is an
"append-only DB" - records may only be added and/or extracted.

   Course-grained locking provided to allow multiple users, as per flock
semantics (i.e. write access requires an exclusive lock, read access needs
a shared lock (see notes below re. perl < 5.004)). As (exclusive) updates
may be take some time to complete, shared lock attempts will timeout after
a defined waiting period (returning $! == EWOULDBLOCK).  Concurrent update
attempts will behave similarly, but with a longer timeout.

   The DB files are simple flat files, with one record per line. Records
(both keys and values) may be arbitrary (binary) data. Records are
extracted from these files via a plain linear search. Unsurprisingly, this
search is a relatively inefficient operation. To improve extraction speed,
records are randomly distributed across N files, with the average search
space is reduced by 1/N compared to a single file. (See below for some
example performance times.) One advantage of this flat file based solution
is that the DB is human readable (assuming the data is), and with some
care can be edited with a plain ol' text editor.

   Finally, note that this DB does not support duplicate entries. In
practice, the first record found matching a given key is returned, any
duplicates will be ignored.

PURPOSE
-------

   I needed to extract single records from a 20k-40k record data set,
within at most 5 seconds on an old Sun 4/40, to feed to an interactive
voice response system. Fine, I thought, an easy job for any old DBM.

   Unfortunately, all of the standard "system" DBMs (NBDM, SDBM, ODBM) are
broken when it comes to "large" data sets (though I don't generally call
20,000 records "large") - at least on Solaris 2.5.1 and Solaris 2.6
machines. I found after inserting some 15k records: NDBM dies; SDBM and
ODBM silently "lose" data (you can't extract records which you know you
inserted). On an HPUX machine, it took nearer to 100,000 records to break
[NSO]DBM. All worked flawlessly on a Linux 2.2.16 machine. The program
examples/testdbm.pl can be used to exercise the various DBMs.

   BerkeleyDB (DB_File) and GDBM work well, but they don't come standard
with many boxes. Further, this package was originally written for an old
Solaris 2.5 box which lacked development tools (and the space and
management will to install such tools) to build a "real" DB.

   And besides, I hadn't played with perl's tie mechanism before...

EXPORTS / CONSTRUCTOR
=====================

   This modules uses the tie interface, as for DB_File.

   The default Fcntl exports are re-exported by default, primarily for the
LOCK_ constants.

CLASS METHODS / CLASS VARIABLES
===============================

   There are two public class variables:

     $SimpleCDB::DEBUG  turn on some debugging messages
     $SimpleCDB::ERROR  error message for last operation, empty if no error
                        has ocurred

METHODS
=======

   n/a

NOTES
=====

   It seems not all environments have POSIX::EWOULDBLOCK defined, in which
case this module defines it as a subroutine constant.

   This DB may use a significant number of file descriptors, you may want
to increase the user/system resource limits for better performance (e.g.
`ulimit -S -n 300' on a Solaris box). My test programs on Solaris don't
seem to want to open more than 256 files at a time, that is even with the
ulimit set to 300, I got EMFILE results as soon as I reached 256 open file
descriptors.  This means there is still some file closing/opening going
on... Interestingly, on the non-exhaustive, not-terribly-thorough testing
I did, I noticed that using a smaller number of files gave slightly better
performance wrt. creating the DB. e.g.  with ulimit set as above, over two
runs of each on an old Sparc:       nfiles = 256 : real,user,sys time =
3:20, 2:43, 0:01       nfiles =  16 : real,user,sys time = 3:00, 2:40, 0:00
Perhaps this is due to file caching?

   Speaking of performance, I used Devel::DProf to find that using crypt to
generate the digest is a real bottleneck (75% CPU time was in generating
the digest :-) Using MD5 reduces this to around 6% (only half of which is
in MD5)! My homebrew digest is not nearly as good as MD5 (both in CPU and
quality), but it more or less does the job when MD5 isn't available.

   Here's how it runs:  Records are between 0 and 100 bytes each. Times
are user/sys/real, as either minutes:seconds or just seconds. wr = create
the db with the stated number of records. rd = read one record (next to
last inserted, i.e.  should be about the worst case).

     Sun 4/40 (sun4c), Solaris 2.5
      40,000 records, nfiles =   1: wr =14:48/29/14:03  rd = 26/2.2/28
      40,000 records, nfiles =  16: wr =14:04/30/15:15  rd =  4/1.0/ 6
      40,000 records, nfiles = 256: wr =14:33/34/15:32  rd =  3/0.8/ 4
       i.e. sloooowwwww to build, good enough on extraction.

     Sun Ultra/1 (sun4u), Solaris 2.6 (SCSI disks)
      40,000 records, nfiles =   1: wr = 53/2.8/57  rd = 3.0/0.1/3.4
      40,000 records, nfiles =  16: wr = 53/2.4/57  rd = 0.5/0.0/0.6
      40,000 records, nfiles = 256: wr =196/19/240  rd = 0.3/0.0/0.4

     x86 C433/64MB, IDE ATA/66 disk, Linux 2.2.16
      40,000 records, nfiles =   1: wr = 18/0.7/19  rd = 1.3/0.0/1.4
      40,000 records, nfiles =  16: wr = 18/0.8/19  rd = 0.3/0.0/0.3
      40,000 records, nfiles = 256: wr = 18/0.8/20  rd = 0.2/0.0/0.2
     100,000 records, nfiles =   1: wr = 47/2.0/49  rd = 3.1/0.1/3.2
     100,000 records, nfiles =  16: wr = 47/2.0/49  rd = 0.4/0.0/0.4
     100,000 records, nfiles = 256: wr = 47/2.2/49  rd = 0.2/0.0/0.2
       i.e. I think the o/s is caching the whole bloody lot :-)

   Clearly, other overheads limit the benefit of the distributed file
hashing, however the result is useful for my purposes...

   The important thing is, it works (as opposed to NDBM and friends).
while (each %h) always shows as much data as you put in :-)

"BUGS"
======

   Possibly, though it works for me :-)

   I've noted that on a HP-UX B.10.20 box that ALRMs don't seem to trigger
when I expect they should. For example, in _lock, I set alarm for say 5s
and then call flock, which I expect to block until either the lock is
granted *or* the alarm goes off (as happens for Solaris and Linux).
However, it is as if the HP-UX box's ALRM signal is delayed until the flock
returns. HP-UX doesn't have a flock call, but does support lockf (which
can lock regions of a file), so perhaps this behaviour is an artefact of
perl's flock emulation...

COPYRIGHT
=========

   Copyright (c) 2000 Benjamin Low <b.d.low@ieee.org>.  All rights
reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   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 Artistic License for more
details.

AUTHORS
=======

   Written as a last resort, and as an excuse to write my first tied
module, by Benjamin Low <b.d.low@ieee.org>, July 2000.

SEE ALSO
========

   Dan Berstein has a nice constant DB implementation, written in C, at

   http://cr.yp.to/cdb.html

   If you've a C compiler handy I recommend this library over SimpleCDB.

   If you want a read+write DB, go for GDBM - it doesn't support
fine-grained locking but does actually work.

Simple configuration file parser
********************************

NAME
====

   SimpleConfig - Simple configuration file parser

SYNOPSIS
========

     use SimpleConfig;

     $config = SimpleConfig->new("configrc", [qw(Foo Bar Baz Quux)]);

     $config->parse();

DESCRIPTION
===========

     C<SimpleConfig> reads and parses simple configuration files.  It's
     designed to be smaller and simpler than the C<ConfigReader> module
     and is more suited to simple configuration files.

CONSTRUCTOR
===========

new ( FILENAME, DIRECTIVES )
     This is the constructor for a new SimpleConfig object.

     FILENAME tells the instance where to look for the configuration file.

     DIRECTIVES is a reference to an array.  Each member of the array
     should contain one valid directive.

     This does the actual work.  No parameters needed.

     Returns the parsed value for that directive.

LIMITATIONS/BUGS
================

   Directives are case-sensitive.

   If a directive is repeated, the first instance will silently be ignored.

   Always die()s on errors instead of reporting them.

   get() doesn't warn if used before parse().

   get() doesn't warn if you try to acces the value of an unknown
directive not know (ie: one that wasn't passed via new()).

   All these will be addressed in future releases.

AUTHOR
======

   Bek Oberin <gossamer@tertius.net.au>

COPYRIGHT
=========

   Copyright (c) 1998 Bek Oberin.  All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Database Session
****************

NAME
====

   DB_session.pm - Database Session

##################################################################################################################

DESCRIPTION
===========

   Gives a friendlier interface to the DBI module.

##################################################################################################################

SYNOPSIS
========

   Please see DESCRIPTION.

##################################################################################################################

REVISION
========

   $Revision: 1.2 $

   $Date: 2000/04/26 04:28:08 $

##################################################################################################################

AUTHOR
======

   Simran *simran@unsw.edu.au*

##################################################################################################################

BUGS
====

   No known bugs.

##################################################################################################################

PROPERTIES
==========

   DATABASE: the name of the database to connect to.

   HOST:     the name of the host computer for the session.

   PORT:     the port number to connect to the host.

   USERNAME: the user name to use for the connection.

   PASSWORD: the password to use for the connection.

   DSN:      the Data Source Name.

   PROTOCOL: the protocol to use for DBI. Defaults to "mysql"

   DATABASE_HANDLE: the database handle when the connection is made (used
to perform queries etc).

##################################################################################################################

METHODS
=======

##################################################################################################################

new
---

Description
     This is the create method for the DB_session class. The new method
     can be called with parameters, if it is, they ar passed to the set
     method (see below).

          $session = DB_session->new

          or

          $session = DB_session->new($parameters)

     eg.

          $session = DB_session->new("PROTOCOL=mysql;DATABASE=test;HOST=localhost;PORT=3306");

Input
          $parameters -  the parameters string is passed straight to the set method (see below).

Output
          New DB_session object created.

Return Value
          New DB_session object.

##################################################################################################################

set
---

Description
     This method takes strings (one or more) of the form
     "<property1>=<value1>; <property2>=<value2>" (i.e. each value in the
     same string must be separated by a semi colon). And sets the
     coressponding property in the object.

     Example: to set the DATABASE property
     $session->set("DATABASE=MyDataBase")

     set is case insensitive when working out which property to set (eg
     DATABASE or database) would work equally well.

          $session->set(@parameters); # list of parameter strings

          or

          $session->set($parameters); # single parameter string

Input
          @parameters (list of inputs $parameters below)

          $parameters (scalar, string) -  the parameters
          string (or list of strings is a set of paired <property>=<value>,
          with each pair being separated by a semi-colon.

          Note: Dont use semi-colons or equals (; or =) in the values

          eg: $parameters = "DATABASE=MyData;USER=Me;PASSWORD=secret";

Output
          Sets properties within the object

Return Value
          returns 1 if all parameters successfully set.

##################################################################################################################

build_dsn
---------

Description
     This internal method builds the DSN property (needed for the
     connection). There should be no need to call this manually as the
     DB_session object should invoke this method interanlly whenever it
     needs to connect to the DB

     A DSN looks like "DBI:<protocol>:database=<dbname>;host=<hostname>;
     port=portname". The host and the port are optional, but the protocol
     and the database are essential.

Syntax
          $session->set(@parameters); # list of parameter strings

          or

          $session->set($parameters); # single parameter string

Input
          None, uses object properties

Output
          Builds the DSN property

Return Value
          returns 1 if DSN is valid.

##################################################################################################################

connect
-------

Description
     This method connects to the database using the DBI connect method.
     Needs a valid DSN to succeed and invokes the internal "build_dsn"
     method.  This is mostly an internal method called when a conection
     becomes necessary.

Input
          None, uses object properties DSN, USERNAME, PASSWORD

Output
          creates DBI database handle and stores it in the
          DATABASE_HANDLE property.

Return Value
          returns 1 if connection succeeds.

##################################################################################################################

disconnect
----------

Description
     This method disconnects the database handle using the DBI disconnect
     method.  This can be called explicity, but will be called when the
     DB_session object is destroyed. ie. when the object is removed or
     deleted.

          $session->disconnect

Input
          None, uses object property DATABASE_HANDLE

Output
          Disconnects and removes the DATABASE_HANDLE

Return Value
          1 if the disconnection succeeds

##################################################################################################################

query_handle
------------

Description
     Returns a statement handle of a particular query (see DBI and DBD
     documentation for how to use the query handle. The query handle
     should be explictly closed ($handle->finish) to avoid warnings and
     errors.

     eg.

          $handle = $query_handle($query);

Input
          $query - the sql query to use

Output
          $handle - the statement handle

Return Value
          same as output

##################################################################################################################

quote
-----

Description
     Puts escape characters next to charaters for sql strings (queries
     etc).

     The following characters have an escape '\' put in front of them: ",
     ', \, !, \t, \r, \n, \0,

     In addition if a positive second parameter is sent (for stronger
     'literal' escaping) these characters are escaped: %, <, >, =

          $escaped_string = $session->escape($string); or

          $escaped_string = $session->escape($string, 1); (for literal)

Input
          $string - the string to 'quote'

          1 (optional) if positive, stronger escaping used.

Output
          $escaped_string

Return Value
          none

##################################################################################################################

all_values
----------

Description
     Similar to the 'Value' from db_routines.pl function, but returns the
     entire query.

     'all_values' does not keep the statement handle so once called, the
     query returns the results and then is gone.

          $array_ref = $session->all_values($query);

Input
          $query - the sql query to run

Output
          $array_ref - the result of a 'fetchall_arrayref'

Return Value
          output is the return value.

##################################################################################################################

rarh
----

Description
     Used for accessing the data from the database with a special
     output/return value

          $url_data = $dbObject->rarh("table", "id=$id and name='simran'")

Input
          $table - the table name we are to get data from
          	$where_clauses - any where clauses

Output
          $table_data - the output is a "reference to an array of references to hashes"
                        containing information for data associated with the query.
                        eg.
                          $table_data = [
                                         { row1field1 => row1value1, row1field2 => row1value2, ... }
                                         { row2field1 => row2value1, row2field2 => row2value2, ... }
                                        ]

          Note: All the field names will be in lower case.

Return Value
          Same as output.

##################################################################################################################

value
-----

Description
     Equivalent to the 'Value' from db_routines.pl function, but returns
     the entire query.

     'values' does not keep the statement handle so once called, the query
     returns the results and then is gone.

     eg.          @array = $session->value($query);

Input
          $query - the query string...

Output
          @array - the result of a 'fetchrow'

Return Value
          output is the return value.

##################################################################################################################

do
--

Description
     A fairly generic do command for the database. It connects if necessary
     and executes the command. It returns the number of row effected by the
     command.

     eg.         $rows = $session->do($mysql_command);

Input
          $mysql_command (scalar, string) a command to be executed using the
            DBI::do method.

Output
          $rows (scalar, integer) the number of rows affected. If do method
            fails rows will be 'undef' # if the method succeeds but the
            command effects no rows the return value will be 0.

Return Value
          same as output

##################################################################################################################

error
-----

Description
     If called in an array context, returns the complete history of error
     messages thus far. Else, returns the latest error message if set.

          $errmsg = $session->error();

          or

          foreach $_ ($session->error()) {
          	  print "Error: $_\n";
          }

Input
          none

Output
          In array context, returns an array containing all error message set thus far.
          Else, returns the latest error message if set.

Return Value
          same as output

##################################################################################################################

DESTROY
-------

Description
     The automatic destructor method for DB_session. Called automatically
     when a DB_session is destroyed.

Syntax
          not used. method called when object is destroyed

Input
          none

Output
          none

Return Value
          none

##################################################################################################################

Error Module
************

NAME
====

   Error.pm - Error Module

##################################################################################################################

DESCRIPTION
===========

   Gives a friendly interface for scripts and other modules to maintain
error states

##################################################################################################################

SYNOPSIS
========

   Please see DESCRIPTION.

##################################################################################################################

REVISION
========

   $Revision: 1.2 $

   $Date: 2000/04/26 04:28:08 $

##################################################################################################################

AUTHOR
======

   Simran *simran@unsw.edu.au*

##################################################################################################################

BUGS
====

   No known bugs.

##################################################################################################################

PROPERTIES
==========

   ERROR:    the error message - used internally

   CARP:     should be set to '1' if you want the error module to 'carp'
every time           an error is set.

   HISTORY:  a pointer to an array in which the full history of error
messages is kept.

##################################################################################################################

METHODS
=======

##################################################################################################################

new
---

Description
     This is the create method for the Error class. The new method can be
     called with a reference to a hash, if it is, the reference is used to
     set all properties contained in the hash.

          $error = Error->new();

          or

          $error = Error->new($parameters_ref)

     eg.

          $error = Error->new({CARP => 1});

Input
          $parameters_ref - a reference to a hash

Output
          New Error object created.

Return Value
          New Error object.

##################################################################################################################

clear
-----

Description
     This method resets the error message. It should be called at the
     start of any code that you want to set errors in.

Syntax
          $session->clear();

Input
          None, uses object properties

Output
          none

Return Value
          none

##################################################################################################################

set
---

Description
     Sets the error message to the supplied message.

     eg. $error->set("Could not open file : $!";

Input
          $string - the error message

Output
          none

Return Value
          none

##################################################################################################################

msg
---

Description
     Returns a error message(s) that would have been set earlier.

     eg.          $message = $error->msg();

          @messages = $error->msg();

Input
          None

Output
          In array context, returns all the error messages set thus far.
          In scalar context, returns the lasest set error message.

Return Value
          same as output

##################################################################################################################

Log Module
**********

NAME
====

   Log.pm - Log Module

##################################################################################################################

DESCRIPTION
===========

   Gives an interface for logging messages to a file

##################################################################################################################

SYNOPSIS
========

   Please see DESCRIPTION.

##################################################################################################################

REVISION
========

   $Revision: 1.2 $

   $Date: 2000/04/26 04:28:08 $

##################################################################################################################

AUTHOR
======

   Simran *simran@unsw.edu.au*

##################################################################################################################

BUGS
====

   No known bugs.

##################################################################################################################

PROPERTIES
==========

   LOGFILE:     the log file name

   FILE_HANDLE: the FileHandle for the file we are logging to

##################################################################################################################

METHODS
=======

##################################################################################################################

new
---

Description
     This is the create method for the Log class. The new method can be
     called with a reference to a hash, if it is, the reference is used to
     set all properties contained in the hash.

          $log = Log->new("/tmp/program.log");

Input
          $logfile = the logfile for writing to

Output
          New Log object created.

Return Value
          New Log object.

##################################################################################################################

open
----

Description
     This method is used internally from within the new method to open the
     file ready for writing to.

Input
          none - uses properties

Output
          none

Return Value
          none

##################################################################################################################

write
-----

Description
     Writes a message to the logfile

     eg. $log->write("Got data from remote host");

Input
          $string - the log message

Output
          none

Return Value
          none

##################################################################################################################

error
-----

Description
     If called in an array context, returns the complete history of error
     messages thus far. Else, returns the latest error message if set.

          $errmsg = $session->error();

          or

          foreach $_ ($session->error()) {
          	  print "Error: $_\n";
          }

Input
          none

Output
          In array context, returns an array containing all error message set thus far.
          Else, returns the latest error message if set.

Return Value
          same as output

Track information about the channels you're on
**********************************************

NAME
====

   Sirc::Chantrack - Track information about the channels you're on

SYNOPSIS
========

     $Channel{$chan}		# true if you're on $channel

     # These only work for channels you are on:
     $Chan_limit{$chan}		# channel limit, or non-existent
     $Chan_user{$chan}{$who}	# true if $who is on $channel
     $Chan_op{$chan}{$who}	# true if $who is an op on $channel
     $Chan_voice{$chan}{$who}	# true if $who has a voice op on $channel

     # These only work for nicks which are on at least one of
     # the channels you are on:
     $Nick{$nick}		# value is $nick, properly cased
     $User_chan{$nick}{$channel}	# true for all the channels you and
     	    	    	    	# $nick are both on

     # Overridden functions in main:
     main::userhost $user, $have, $have_not;
     main::userhost [@user_list], $have, $have_not;

     # Sirc::Util-style hooks:
     +op		gets ($channel, $nick), $who is originator
     -op		ditto
     +voice	gets ($channel, $nick), $who is originator
     -voice	ditto
     limit	gets ($channel, $old_limit, $new_limit), $who is originator

DESCRIPTION
===========

   This module tracks various data about the channels you are on, and the
nicks who are on them with you.  It also overrides main::userhost with an
enhanced version, and it provides hooks for when people gain and lose ops.

   Nothing is exported by default.

   Most of the data is available in a series of hashes.  These hashes are
tied to a package which downcases the keys.

   All of the hashes only track data about the channels you are on.

*$Channel{channel}*
     The keys of this hash are the names of the channels you're on.  Values
     are always 1.

*$Chan_user{channel}{nick}*
     This hash of hashes tracks the users on the channels you're on.  The
     values are always 1.

*$User_chan{nick}{channel}*
     This hash of hashes contains the same data as %Chan_user, but with the
     keys stacked in the opposite order.

*$Chan_op{channel}{nick}*
     This hash of hashes only contains elements for the operators of the
     given channels.  The values are always 1.

*$Chan_voice{channel}{nick}*
     This hash of hashes only contains elements for the people on the
     channel who have voices.  Due to the way /NAMES works, though, it can
     lack people who were +o when you showed up and got +v before you
     showed up (even if they subsequenty lose the +o).  (It syncs from
     `/names' and `/mode'.)  Note that ops can speak without voices.  The
     values are always 1.

*$Nick{nick}*
     This hash maps from any case of nick to the proper case.

*main::userhost *nick-or-array-ref*, *have-code* [, *havenot-code*]*
     This is an overridden version of *main::userhost*.  It uses the cached
     data to avoid going to the server for information.  Additionally, the
     first arg can be a reference to an array of nicks to check on.  If you
     query multiple users this way they're sent to the server in lots of 5.
     Lastly, the two code arguments can be either strings or code refs.
     The data will be in $::who, $::user and $::host when the code runs.

     Eg, here's how to run a command which uses userhost info for every
     user on a channel:

          userhost [keys %{ $Chan_user{$c} }], sub {
          	autoop_try $c, "$who!$user\@$host";
          };

*+op*, *-op*, *+voice*, and *-voice* hooks
     These are *Sirc::Util*-style hooks which are called when people gain
     and lose ops and voices.  They are only called for people who are
     still in the channel after the gain/loss.  That is, an operator
     leaving the channel does not trigger the *-op* hook.

     The hooks are called with the channel as the first arg and the nick as
     the second.  The originator is in $::who.  Eg, here's a trigger which
     activates when you are given ops:

          use Sirc::Util qw(add_hook ieq);

          add_hook '+op', sub {
          	my ($c, $n) = @_;
          	timer 10, qq{ main::cmd_autoop "\Q$c\E" }
          	    if ieq $n, $::nick;
          };

limit hook
     This is a Sirc::Util-style hook for channel limit changes.  It gets as
     args the channel name, the old limit, and the new limit.  $::who
     contains the originator.

AVAILABILITY
============

   Check CPAN or http://www.argon.org/~roderick/ for the latest version.

AUTHOR
======

   Roderick Schertler <`roderick@argon.org'>

SEE ALSO
========

   sirc(1), perl(1), Sirc::Util(3pm).

simple channel limit management
*******************************

NAME
====

   Sirc::LimitMan - simple channel limit management

SYNOPSIS
========

     /eval use Sirc::LimitMan

     /limitman			# toggles management on current channel
     /limitman #mychan		# toggles management on #mychan

DESCRIPTION
===========

   This module provides a command which will do simple channel limit
management.  When invoked for a channel you will occasionally modify the
channel's limit to keep it within a certain distance of the actual number
of users.  The channel can become full while limit management is in place.
This is intentional, if the limit were always upped in order to allow
somebody else to join, it would be pointless.

   This code tries to keep the noise down by limiting the number of +l
changes.  A client running it considers itself the master if it's the last
one who made a change to the limit.  Normally the clients try to schedule
themselves so that only the master keeps changing the limit, but somebody
else will step in if he falls down on the job.

Settable Options
================

   You can set these values with *sirc*'s /set command.  Most of them
should really be specifiable per-channel, but they aren't.  Sorry.

limitman *on*|*off*
     If disabled then no limit management is done.  The channels you want
     limit management for are still remembered, so if you enable it again
     later they'll kick in again.  The default is *on*.

limitman_debug *on*|*off*
     Turning this on causes the module to let you in on its cogitations.
     It defaults to *off*.

limitman_tween seconds
     This is the base number of seconds between checks to see if the limit
     should be adjusted.  The default is 60.

limitman_skew seconds
     Non-masters have an additional delay between checks.  Part of it is a
     random delay of up to limitman_skew seconds, default 30.

limitman_skew_offset seconds
     An additional part of the delay for non-masters is a constant
     limitman_skew_offset seconds, default 15.

limitman_low count
     The limit will raised if there are fewer than limitman_low free slots
     on the channel, default 2.

limitman_high count
     The limit will lowered if there are more than limitman_high free
     slots on the channel, default 5.

limitman_reset count
     When the limit is reset, it's set to the current number of users plus
     limitman_reset, default 4.

AVAILABILITY
============

   Check CPAN or http://www.argon.org/~roderick/ for the latest version.

AUTHOR
======

   Roderick Schertler <`roderick@argon.org'>

SEE ALSO
========

   sirc(1), perl(1), Sirc::Chantrack(3pm), Sirc::Util(3pm).

Utility sirc functions
**********************

NAME
====

   Sirc::Util - Utility sirc functions

SYNOPSIS
========

     # sirc functions
     use Sirc::Util ':sirc';
     # overrides:
     timer $delay, $code_string_or_ref, [$reference];

     # user messages
     arg_count_error $name, $want, [@arg];
     tell_error $msg;
     tell_question $msg;
     xtell $msg;

     # miscellaneous
     $pattern = ban_pattern $nick, $user, $host;
     $boolean = by_server [$who, $user, $host];
     eval_this $code, [@arg];
     eval_verbose $name, code$, [@arg];
     $boolean = have_ops $channel;
     $boolean = have_ops_q $channel;
     $boolean = ieq $a, $b;
     $re = mask_to_re $mask;
     $unused_timer = newtimer;
     optional_channel or return;
     $boolean = plausible_channel $channel;
     $boolean = plausible_nick $nick;
     $arg = xgetarg;
     $restricted = xrestrict;

     # /settables
     settable name, $var_ref, $validate_ref;
     settable_boolean $name, $var_ref;
     settable_int $name, $var_ref, [$validate_ref];

     # hooks
     add_hook_type $name;
     add_hook $name, $code;
     run_hook $name, [@arg];

DESCRIPTION
===========

   This module provides a bunch of utility functions for *sirc*.

   It also allows you to import from it all of the standard sirc API
functions, so that you can more simply write your script as a module.

   Nothing is exported by default.

STANDARD SIRC FUNCTIONS
=======================

   You can import the standard SIRC API functions individually or, using
the tag *:sirc*, as a group.  The available functions are:

     accept addcmd addhelp addhook addset connect deltimer describe
     docommand doset dosplat dostatus eq getarg getuserline getuserpass
     listen load me msg newfh notice print remhook remsel resolve say sl
     tell timer userhost yetonearg

   Some of these are actually enhanced versions of the routines that *sirc*
provides, see below for information about them.

STANDARD MESSAGE FORMS
======================

   These functions provide for a few standard message forms which are shown
to the user via main::tell().

arg_count_error name, *want*, [*arg*...]
     This prints an error appropriate to an incorrect number of arguments.
     name is the name of the invoking sub, *want* is how many arguments
     were desired and the remaining *arg* arguments are the arguments which
     were actually received.

tell_error msg
     This formats msg as an error message and passes it to main::tell.
     It's appropriate for errors caused by the system or an invalid
     invocation of your code.

tell_question msg
     This formats msg as an error message for something the user did
     wrong.  The message is passed to main::tell.

xtell msg
     This is just `main::tell "*** $msg"'.

MISCELLANEOUS FUNCTIONS
=======================

   These are some functions which don't fall nicely into groups like those
following do.

ban_pattern nick, user, host
     This returns a pattern suitable for banning the given nick, user and
     host.

     The current implementation is this:  Any nick is always matched.  If
     the user has a ~ at the start (that is, it didn't come from identd)
     all user names are matched, else just the one given matches.  If the
     host is an IP address, it bans a class C sized chunk of IP space,
     otherwise part of it is wildcarded (how much depends on how many
     parts it has).

     For example:

          qw(Nick  user 1.2.3.4)		*!user@1.2.3.*
          qw(Nick ~user 1.2.3.4)		*!*@1.2.3.*
          qw(Nick  user host.foo.com)		*!user@*.foo.com
          qw(Nick ~user host.foo.com)		*!*@*.foo.com
          qw(Nick  user foo.com)		*!user@*foo.com
          qw(Nick ~user foo.com)		*!*@*foo.com

by_server [who, user, host]
     If the given who, user, host corresponds to a server rather than a
     user, return the server name, else return undef.  If these aren't
     specified the global $::who, $::user, and $::host are used, which is
     what you usually want anyway.

eval_this code, [*arg*...]
     This evals code with *arg* as arguments.  The code can be either a
     code reference or a string.  In either case the *arg*s will be
     available in @_.  The return value is whatever the code returns.  $@
     will be set if an exception was raised.

eval_verbose name, code, [*arg*...]
     This is like eval_this except that if an exception is raised it is
     passed along to tell_error (with a message indicating it's from name).

have_ops channel
     This function returns true if you have ops on the specified channel.
     If you don\'t have ops it prints an error message and returns false.

have_ops_q channel
     This is like have_ops except that no message is printed, it just
     returns true or false depending on whether you have ops on the
     specified channel.

ieq $a, $b
     This sub returns true if its two args are eq, ignoring case.

mask_to_re glob
     Convert the given "mask" (an IRC-style glob pattern) to a regular
     expression.  The only special characters in IRC masks are * and ?
     (there's no way to escape one of these).  The returned pattern always
     matches case insensitively and is anchored at the front and back (as
     IRC does it).

optional_channel
     This sub examines $::args to see if the first word in it looks like a
     channel.  If it doesn't then $::talkchannel is inserted there.  If
     there was no channel present and you're not on a channel then an
     error message is printed and false is returned, otherwise true is
     returned.

     Here's a replacement for /names which runs /names for your current
     channel if you don't provide any args.

          sub main::cmd_names {
          	optional_channel or return;
          	docommand "/names $::args";
          }
          addcmd 'names';

newtimer
     Return an unused timer number.

plausible_channel channel
     This returns true if channel is syntactically valid as a channel name.

plausible_nick nick
     This returns true if nick is syntactically valid as a nick name.
     Originally I used the RFC 1459 definition here, but that turns out to
     be no longer valid.  I don't know what definition modern IRC servers
     are using.  This sub allows characters in the range [!-~].

timer @args
     This is an enhanced version of *sirc*'s timer().  It allows you to use
     a code reference as the code arg.

xgetarg
     This is like main::getarg, but it returns the new argument (in
     addition to setting $::newarg).

xrestrict
     This just returns $::restrict.

/SET COMMANDS
=============

   These commands provide a simplified interface to adding /set variables.

settable name, *var-ref*, *validate-ref*
     This sub adds a user-settable option.  name is its name, *var-ref* is
     a reference to the place it will be stored, and *validate-ref* is a
     reference to code to validate and save new values.  The code will be
     called as `$rvalidate-'($rvar, $name, $value)>.  $name will be in
     upper case.  The code needs to set both $$rvar and $::set{$name}.
     (The values in %set are user-visible.)

settable_boolean name, *var-ref*
     This adds a /settable boolean called name.  *var-ref* is a reference
     to the scalar which will store the value.

settable_int name, *var-ref*, [*validate-ref*]
     This function adds a /settable integer called name.  *var-ref* is a
     reference to the scalar which will store the value.

     *validate-ref*, if provided, will be called to validate the a new
     value is legal.  It will receive both the name and the new value as
     arguments.  Before it is called the new value will have been vetted
     for number-hood.  It should return a boolean to indicate whether the
     value is okay.

HOOKS
=====

   Sirc::Util provides functionality for creating, adding code to and
running hooks.

add_hook_type name
     This creates a new hook called name.

add_hook name, code
     Add code to the name hook.  The name must already have been created
     with add_hook_type().  The code can be either a string or a code
     reference.

run_hook name, [*arg*...]
     Run the name hook, passing the *arg*s to each hook member via @_.

AVAILABILITY
============

   Check CPAN or http://www.argon.org/~roderick/ for the latest version.

AUTHOR
======

   Roderick Schertler <`roderick@argon.org'>

SEE ALSO
========

   sirc(1), perl(1), Sirc::Chantrack(3pm).

An perl make engine using perl code for rules
*********************************************

NAME
====

   Slay::Maker - An perl make engine using perl code for rules

STATUS
======

   Beta. Pretty stable, though underdocumented.

DESCRIPTION
===========

   Slay::Maker is a make engine that uses perl declaration syntax for
rules, including regular expressions for targets and anonymous subs for
targets, dependancies, and actions.

   This allows you to tightly integrate a make engine in an application
and to excercise a large amount of control over the make process, taking
full advantage of Perl code at any point in the make cycle.

RULE SYNTAX
===========

   The rulebase syntax is:

     [ @targets1, ':', @dependancies1, '=', @actions1, { option => val } ],
     [ @targets2, ':', @dependancies2, '=', @actions2, { option => val } ],
     [ @targets3, ':', @dependancies3, '=', @actions3, { option => val } ],
     [ @targets4, ':', @dependancies4, '=', @actions4, { option => val } ],
     ...

   Each item in any of the three arrays may be a literal string or a
subroutine (CODE) reference.  A literal string is pretty much the same as
using a literal string in a regular makefile.  You may also use regular
expression ('Regexp') references (`qr/.../') in @targets and the $1, $2,
... variables inside strings in @dependancies:

     [ qr/(.*).pm/, ':', "$1.pm.in", '=', sub { ... } ],

   Subroutine references are evaluated as lazily as possible when the make
is being run, so any CODE refs in @targets will be called each time a make
is run, CODE refs in @dependancies will only be called if a target
matches, and CODE refs in @actions are only called if the rule is fired.

TARGET SUBS
-----------

   ** NOT IMPLEMENTED QUITE YET **.  It's simple to do, just haven't needed
it yet.

   Aside from strings and Regexps, you will be able to use CODE refs in
the target list.  These are called each time the rule is evaluated, which
will usually happen once per target or dependancy being checked when the
make is run.

   A target sub declaration might look like:

     sub {
        my ( $maker ) = @_ ;
        ...
        return @targets;
     },

   (if target subs were implemented already).

DEPENDANCIES
------------

   Dependancies may be strings or CODE references.  Plain strings have $1,
$2, ... interpolation done on them (remember to \ escape the $1, etc.).

   CODE refs will be called if the target matches and must return a
possibly empty list of strings containing the names of dependancies.
Variable interpolation will not be done on the returned strings.  That
would be obscene.

   A dependancy sub declaration might look like:

     sub {
        my ( $maker, $target, $matches ) = @_ ;
        ...
        return @dependancies ;
     },

   where

     $maker    refers to the Slay::Maker (or subclass) being run
     $target   is the target that matched (in the event of multiple targets)
     $matches  is an ARRAY of the values extracted from $1, $2, etc.

   .

ACTIONS
-------

   If an $action is a plain string, it's passed to "sh -c '$string'".  If
it's an ARRAY ref, it's run without interference from or benefit of a
shell (see `run', see IPC/Run, for details).  If it's a CODE
ref, it's called.

   An action sub declaration might look like:

     sub {
        my ( $maker, $target, $deps, $matches ) = @_ ;
        ...
        return @dependancies ;
     },

   where

     $maker    refers to the Slay::Maker (or subclass) being run
     $target   is the target that matched (in the event of multiple targets)
     $deps     is an ARRAY of the expanded dependancies.  There's no way
               of telling which are freshly rebuilt, but you can track that
     	     yourself in the action rules of the dependancies, if you
     	     like.
     $matches  is an ARRAY of the values extracted from $1, $2, etc.

TARGET BACKUPS
==============

   A target may be moved off to a backup location before it is rebuilt, so
that it may be restored if rebuilding fails.  This is also used for the
optional restoral of modification times described below.

   Restoral needs to be done manually by calling the `' in this node
method, and you can call the `' in this node method, too.

   The `' in this node method will be called automatically if modification
time restoral is enabled for a target.

MODIFICATION TIME RESTORAL
==========================

   One unusual option is that a target file's modification time can be
restored if it is unchanged after being updated.  This can be useful when
checking files out of a repository: the files' mod times won't be affected
if their contents haven't changed.

   This can be done by a (fast but possibly misleading) check for a change
in file size or by executing 'diff -brief' between a target's backup and
it's new version.  Other methods, such as hashing or block-by-block binary
comparison will be implemented in the future if needed.

   This is controled by the `' in this node option passed to the base
class constructor:

     my $self = $class->SUPER::new( ..., { detect_no_diffs => 1 } ) ;

   and can be passed as an option to any rule.

AN EXAMPLE
==========

   Here's a real example, which will have to stand in for documentation
until further notice.  If you need more, mail me (barries@slaysys.com) and
get me to do something productive for a change.

   This is a subclass that compiles a set of builtin rules at module
compilation time.  It declares a method for spawning the cvs command
first, then builds some rules.

     package Safari::Cvs::Make ;

     @ISA = qw( Slay::Maker ) ;

     use strict ;
     use IPC::Run ;

     sub cvs {
        my Safari::Cvs::Make $maker = shift ;

     my $stdout_to ;
     if ( $_[-1] =~ /^\s*>(.*)/ ) {
     	 $stdout_to = $1 ;
     	 pop ;
     }

     my $cvs_out ;
     run [ qw( cvs -q -l -z9 ), @_ ], \undef, \$cvs_out or die $! ;

     return $cvs_out ;
        }

     my $builtin_rules = Safari::Make->compile_rules(
        [  'meta/cvs_modules',
     	 '=', sub {   ## The action that occurs when the rule fires.
     	    ## We could just do the cvs co -c here, but many pservers don't
     	    ## have that implemented.  so, check out the modules file and
     	    ## parse it.
     	    my ( $maker, $target ) = @_ ;
     	    $maker->cvs( qw( checkout -p CVSROOT/modules ), ">$target" ) ;
     	 },
        ],
        [ 'update',
     	 ':' => sub {
     	    my ( $maker ) = @_ ;

     my $context = $maker->{CONTEXT} ;

     my @modules ;

     my %args = $context->request->args ;
     if ( defined $args{modules} ) {
        @modules = split( ',', $args{modules} ) ;
     }
     elsif ( defined $args{module} ) {
        @modules = $args{module} ;
     }
     else {
        eval {
           ## A recursive make
     		  $maker->make( 'meta/cvs_modules', { force => 1 } ) ;
        } ;
        if ( $@ ) {
     		  warn $@ ;
        }

     if ( ! open( F, "<meta/cvs_modules" ) ) {
     		  warn "$!: meta/cvs_modules, globbing" ;
     		  @modules = map {
     		     s{^meta/HEAD/}{}; $_
     		  } grep {
     		     -d $_
     		  } glob( 'meta/HEAD/*' ) ;
     }
     else {
     		  my $line ;
     		  my %modules ;
     		  while (<F>) {
     		     next if /^\s*#|^\s*$/ ;
     		     chomp ;
     		     $line .= $_ ;
     		     redo if $line =~ s{\\$}{} ;
     		     $modules{$1} = 1 if $line =~ m{^\s*(\S+)} ;
     		     $line = '' ;
     		  }
     		  close F ;
     		  @modules = sort keys %modules ;
     }
     	    }

     debug 'modules', \@modules ;
     die "No modules found\n" unless @modules ;
     return map { "source/HEAD/$_/CVS/" } @modules ;
     	 },
     	 '=' => sub {
     my ( $maker, $target, $deps ) = @_ ;

     my @dirs = map { s{/CVS/}{} ; $_ } @$deps ;

     ## We go ahead and update after creating modules for a couple of
     ## reasons:
     ## 1. It's rare that we've just checked out a module
     ## 2. It's simpler this way
     ## 3. If we just created a *big* module, then we might need to
     ## update anyway.

     ## We set $logs{$filename} = 1 if we must replace the current log file,
     ## or = 0 to just ensure that the log file is fetched.
     my %logs ;
     my $force_all ;

     my $cwd = cwd() ;
     for ( @dirs ) {
        chdir $_ or die "$!: $_" ;
        my $module = $_ ;
        $module =~ s{.*/}{} ;
        ## -P: Prune empty dirs
        ## -d: Add new dirs that we don't have
        for ( split /^/m, $maker->cvs( qw( update -d -P ) ) ) {
     		  chomp ;
     		  if ( /^[UP]\s+(.*)/ ) {
     		     $logs{"meta/HEAD/$module/$1.log"} = 1 ;
     		  }
     		  elsif ( /^\?\s+(.*)/ ) {
     		     my $log_file = "meta/HEAD/$module/$1.log" ;
     		     eval {
     			rmtree( [ $log_file ] ) ;
     		     } ;
     		     warn "Error removing ;$log_file'" if $@ ;
     		  }
     		  else {
     		     warn "Unexpected CVS file mode: $_" ;
     		  }
        }
        chdir $cwd or die "$!: $cwd" ;
     }

     for ( sort keys %logs ) {
        $maker->make(
     		  $_,
     		  {
     		     force => $force_all || $logs{$_}
     		  }
        ) ;
     }

     },
     {
        force => 1,   # Always remake this target
     }
           ],
        ) ;

METHODS
=======

new
     Constructor.

          my $rules = [
             # ...
          ] ;
          my $maker = Slay::Maker->new( $rules ) ;
          my $maker = Slay::Maker->new( $rules, { option => 1 } ) ;

     options (which can also be defined on a per-rule basis) are:

    auto_create_dirs
          Creates directories that targets will be created in before
          executing a target's actions.

    detect_no_diffs
          Copy the target before executing a rule, then restore the
          original modification and access times if the contents of the
          target are the same after the rule.

    detect_no_size_change
          Look for changes in the size of a file after executing a rule
          and restore the original modification and access times if it
          changes.

    force
          Always remake target, even if it does not appear to be out of
          date

     Warning: options are not checked for spelling errors.

     Options may be passed to new(), make(), build_queue(), and to rules
     themselves.  Options passed to make() or build_queue() take
     precedence over rules' options, and rules' options take precedence
     over those passed to new().

add_rules
     Add rules (compiled or not) to the rule base.

atime
     This returns the atime of a file, reading from the stat cache if
     possible.

build_queue
     Builds a new queue of rules to be exec()ed to make a target

builtin_rules
     Returns [] by default.  This is provided so that subclasses may
     overload it to provide sets of rules.  This is called by new() before
     adding any rules passed to new().

canonpath
     Cleans up the path, much like File::Spec::Unix::canonpath(), but also
     removes name/.. constructs.

chdir
     Calls sytem's chdir(), die()s on failure, and uses the parameter as
     the current directory.  The last is the main reason for this sub: if
     you chdir() to a symbolic link, then we want to know the symbolic
     directory, not the real one returned by cwd().

check_targets
     Checks targets and adds them to queue if need be.  Does not integrate
     Slay::Maker options: this is left to the caller (usually the original
     build_queue() call).

clear_caches
     Clears the stat cache, so the filesystem must be reexamined.  Only
     needed if Slay::Maker is being called repetetively.

clear_stat
     Clears the stat cache for a given path, so the next stat() on that
     path will read the filesystem.

compile_rules
     Returns a rulebase compiled from the arguments.  Rules that are
     already compiled are passed through unchanged.  This is a class
     method, so

          Slay::Maker->compile_rules(
             [ 'a', [qw( b c )], 'cat b c > a' ],
             ...
          ) ;

     can be used to compile a rulebase once at startup

backup
     Copies a file so that it can be restored later or checked for changes.

     If the target will only ever be replaced by the make, then it will
     not be altered in-place, and the move option may be passed:

          $maker->backup( $target, { move => 1 } ) ;

     If the target is an fiel which always changes size when it's changed,
     you may pass the `stat_only' option:

          $maker->backup( $target, { stat_only => 1 } ) ;

     The return value can be passed to restore(), target_unchanged(), and
     remove_backup().

cwd
     Returns the current working directory, from the cache if that's
     possible.

e
     Returns true if the file exists, but uses the stat_cache if possible.

exec_queue
     Executes the queued commands.

find_rule
     Given a target, finds a rule.

make
     Makes one or more target(s) if it's out of date.  Throws exceptions if
     the make fails.  May partially make targets.

make_level
     Returns 0 if make() has not been called (well, actually, if
     recurse_in() has not been called).  Returns number of recursive calls
     otherwise, so this is equal to 1 when making something but not
     recursing.

mtime
     This returns the mtime of a file, reading from the stat cache if
     possible.

options
     Sets / gets a reference to the options hash.

push
     Adds a ( target, rule ) tuple to the exec queue.  Will not add the
     same target twice.

recurse_in
     Sets up for a recursive make.  Called automatically by make() if
     make() is already running.

recurse_out
     Restored after a recursive make.  Called automatically by make() if
     make() is already running.

queue_size
     Number of rules that need to be made.

remove_backup
          my $backup = $maker->backup( $target ) ;
          ## ...
          $maker->remove_backup(
             $backup,
             {
          	 restore_if_unchanged => 1,
          	 deps                 => \@deps,
             }
          ) ;

     Removes a backup of the target created with backup_target().

replace_rules
     Replaces the rule for a target (or targets).  The targets passed in
     must exactly match those of the rule to be replaced.

restore
          my $backup = $maker->backup( $target, { move => 1 } ) ;
          ## Try to recreate target, setting $error on error
          $maker->restore( $backup )
             if $error ;
          $maker->restore( $backup, { deps => \@deps } )
             if ! $error && $maker->target_unchanged( $backup ) ;
          $maker->remove_backup( $backup ) ;

     Note that you only need this in case of an error.  You can pass the
     restore_if_unchanged => 1 and deps => \@deps options to
     remove_backup().

     When backup() has been called, it's return value can be passed to
     restore_target() to restore the original target, timestamps and all.

     NOTE: restoring a target that's not changed is likely to cuase it to
     be remade every time once a dependancy's timestamp becomes more
     recent.  The `deps' option allows the timestamps to be set to the
     newest of the original timestamps and the dependencies' timestamps.
     This should not be done if there was an error generating the file.

rules
     Gets or replaces the rules list

size
     This returns the size of a file, reading from the stat cache if
     possible.

stat
     Looks in the stat cache for the stat() results for a path.  If not
     found, fills the cache.  The cache is shared between all instances of
     this class, and may be cleared using clear_stat_cache().

target_unchanged
     Takes the result of backup_target() and checks to see if the target
     has been changed or removed.

back
TODO
====

   * Propogate effects of restored timestamps.

     If a target has it's timestamps restored as a result of detecting no
     change (see options detect_no_size_change and detect_no_diffs), then
     there may well be no need to actually execute later rules.

     One way to do this is to re-check the mtime dependencies when
     rebuilding.  Another is to subscribe later items in the queue to
     earlier items and have the earlier items set a flag that tells the
     later items to go ahead and execute.  Items could flag themselves to
     execute regardless, which we might want to do if a dependancy is not
     present when make is run.

   * Don't really call diff(1) for detect_no_diffs

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

LICENSE
=======

   Copyright 2000, R. Barrie Slaymaker, Jr., All Rights Reserved.

   That being said, do what you will with this code, it's completely free.

   Please let me know of any improvements so I can have the option of
folding them back in to the original.

a class for making things with dependancies
*******************************************

NAME
====

   Slay::MakerRule - a class for making things with dependancies

SYNOPSIS
========

     use strict ;

     use Slay::MakerRule ;

     $t1 = Slay::MakerRule->new(
        \@target,         ## Filenames made by \@actions
        \@dependencies,   ## Files or Slay::MakerRule objects
        \@actions,        ## Command lines or sub{}
     ) ;

   Any or all of the three parameters may be scalars if there is only one
thing to pass:

     $t1 = Slay::MakerRule->new(
        $target,
        $dependency,
        $action,
     ) ;

DESCRIPTION
===========

check
     Builds the queue of things to make if this target or it's
     dependencies are out of date.

exec
     Executes the action(s) associated with this rule.

targets
     returns either ( target1, target2, ... ) or "target1, target2, ..."
     depending on context.

matches
     Checks the target list to see if it matches the target passed in.

Perl extension remote presentation
**********************************

NAME
====

   SlideShow - Perl extension remote presentation

SYNOPSIS
========

     use SlideShow;
     new SlideShow
       (master_cgi  => "http://127.0.0.1/cgi-bin/master",
        start_title => "My SlideShow",
        url_list    => [qw(http://www.perl.com http://www.infobot.org)],
        )->run;

     perl -MSlideShow -e 'SlideShow->new()->run';
     perl -MSlideShow -e 'SlideShow->client()->run';

DESCRIPTION
===========

   SlideShow is a device for giving presentations over the Web.  It allows
one user (the master) to control the content that appears on other user
(client) browsers by using server pushes.

   For example, you could arrange a conference call or radio broadcast,
and then tell everyone to point their browsers at a client CGI, and then
give the talk with visual materials.

PREREQUISITES
=============

   LWP::UserAgent, HTTP::Request, HTML::Parser, CGI.pm, and web server
that will allow you to run CGIs.

RUNNING A SLIDESHOW
===================

   You will need a web server that will allow you to use CGI, but it is
otherwise a simple matter to run a SlideShow.

   First, have the session leader start a master session.  This is done by
creating a SlideShow object and passing it a few parameters, such as:

master_cgi The URL to the master CGI program, wherever you are utting it. [Required].
view_file Where to keep the currently-showing pages.
start_title The title that shows up on the master session at startup.
url_list A list of URLs to use as presets to start off the session with.
tmp_dir Where to keep the temporary files.  default is `/tmp'.
log_file Where to put the final log of all pages visited.
commentary A little message that goes on the master  startup page.  HTML can be included verbatim.
EXAMPLES
========

for the master session:
          use SlideShow;

          new SlideShow
            (master_cgi  => "http://127.0.0.1/cgi-bin/master",
             start_title => "My SlideShow",
             view_file   => "/tmp/viewfile.html",
             url_list    => [qw(http://www.perl.com http://www.infobot.org)],
             )->run;

for the clients/viewers:
          use SlideShow;

          SlideShow::client(view_file => "/tmp/viewfile.html");

NOTE: the push involved non-parsed headers (NPH) and many browsers require that a CGI be named with the  prefix 'nph-', such as 'nph-view', to work properly.
     See the included examples, *slideshow-master* and
     *nph-slideshow-viewer*.

BUGS
====

   Requires someone or something to lead the session.  Autonomous shows
should be added.

AUTHOR
======

   Kevin A. Lenzo <lenzo@cs.cmu.edu>

SEE ALSO
========

   perl(1), see LWP/UserAgent, HTTP/Request,
see HTML/Parser, CGI.

module to control the Slink-e product produced by Nirvis - visit Nirvis at http://www.nirvis.com
************************************************************************************************

NAME
====

   Slinke - module to control the Slink-e product produced by Nirvis -
visit Nirvis at http://www.nirvis.com

SYNOPSIS
========

     use Slinke;

     # Create a Slinke and read from the infrared port
     my $slinke = new Slinke;
     my $data = $slinke->requestInput();

     foreach my $i ( @$data ) {
        print "$i\n";
     }

DESCRIPTION
===========

   Slink-e is a product that can speak to many different Sony products over
the S-Link port.  Also, it can receive and transmit infrared signals over
8 different transmitters/receivers.

   For now, the bulk of this code deals with the transmission and reception
of these infrared signals.

   Note that this code borrows heavily from C++ code from Colby Boles.  In
fact, sometimes I just copied his code and comments verbatim.

METHODS
=======

EXPORT
------

   The different port names are exported.  These are the following:

     PORT_SL0 PORT_SL1 PORT_SL2 PORT_SL3 PORT_IR PORT_PAR PORT_SER PORT_SYS

$slinke = new Slinke( [ DEVICE => $device, SERIALPORT => $serialport ] );
-------------------------------------------------------------------------

   Returns a newly created `Slinke' object.

   `$device' is the name of the device that the Slink-e is connected to.

   If no device is provided, a search is made on the following devices:
/dev/ttyS0 /dev/ttyS1 /dev/ttyS2 /dev/ttyS3

   On windows, COM ports 1-8 are searched

   If you would rather provide a SerialPort object, you can do that by
setting the SERIALPORT argument

$slinke->requestInput();
------------------------

   This function returns any input from the S-Link ports, the IR ports or
the Parallel port

   The returned element is a hash reference.

   `PORT' is always set, and it will contain the port that returned the
data

   DATA is a reference to an array of values.

   TIME is set for data coming from the IR port and this lists the total
amount of time that was needed to produce the IR signal

   `IRPORT' is set for data coming from the IR port.  It tells which IR
receiver (1-8) the data was received on.  Note that you must have a
Slink-e of version 2.0 or higher for IRPORT to be greater than 0

$slinke->requestSerialNumber()
------------------------------

   This returns the 8 byte serial number of the Slink-e.

$slinke->requestBaud()
----------------------

   This returns the baud rate in bps of the Slink-e.

$slinke->setBaud()
------------------

   This sets the baud rate in bps of the Slink-e.

$slinke->requestFirmwareVersion()
---------------------------------

   This returns the firmware version of the Slink-e

$slinke->enablePort( $port )
----------------------------

   Enables reception on specified port.  If port == `PORT_SYS' *all ports
are not enabled*, instead each port is returned to its enabled/disabled
state previous to the global disablement.

$slinke->disablePort( $port )
-----------------------------

   Disables reception on specified port.  If port == `PORT_SYS', all ports
are disabled.  Disabling a port does not prevent the host from sending
messages out the port, only receiving them.

$slinke->requestIRSamplingPeriod()
----------------------------------

   This returns the infrared sampling period of the Slink-e.  Values can
range from 50 microseconds to 1 millisecond.

   The IR sampling period determines the maximum timing resolution which
can be achieved when decoding IR signals.  In general, the sampling period
should be at least 3 times shorter than the shortest pulse you wish to
detect.  Short sampling periods are necessary when acquiring timing
information about new remote signals, but are not necessarily need to
output known remote signals since the sampling period need only be the
least common multiple of the pulse widths in the signal.

   The IR sampling period is also used as a timebase for parallel port
output signals.

$slinke->setIRSamplingPeriod( $time )
-------------------------------------

   This sets the infrared sampling period of the Slink-e.  Values can
range from 50 microseconds to 1 millisecond in 1/5 microsecond steps.
Upon success, this function will return the sampling period.  On value, it
will return undef.

   The IR sampling period determines the maximum timing resolution which
can be achieved when decoding IR signals.  In general, the sampling period
should be at least 3 times shorter than the shortest pulse you wish to
detect.  Short sampling periods are necessary when acquiring timing
information about new remote signals, but are not necessarily need to
output known remote signals since the sampling period need only be the
least common multiple of the pulse widths in the signal.

   The IR sampling period is also used as a timebase for parallel port
output signals.

$slinke->requestIRCarrier()
---------------------------

   This returns the IR carrier frequency of the Slink-e.

$slinke->setIRCarrier( $frequency )
-----------------------------------

   This sets the IR carrier frequency of the Slink-e.  Note that because
of the way that the frequency gets set, it will be very unlikely that you
will be able to set the exact frequency that you want.  However, the
Slink-e should be able to handle your frequency within several hundred
hertz.

   Upon success, the frequency that the Slink-e is using will be returned.

   Upon failure, undef is returned.

$slinke->requestIRTimeoutPeriod()
---------------------------------

   This returns the IR timeout period of the Slink-e as measured in sample
periods.  The timeout period defines how ling the IR receiver module must
be inactive for the Slink-e to consider a message to be completed.

$slinke->setIRTimeoutPeriod( $sample_periods )
----------------------------------------------

   This returns the IR timeout period of the Slink-e as measured in sample
periods.  The timeout period defines how ling the IR receiver module must
be inactive for the Slink-e to consider a message to be completed.  Most
IR remotes repeat commands many times for one keypress.  If you want to
see each command as a separate message, set the timeout period to be less
than the off time between commands.  If you to see the keypress as one
long message with repeated commands, set the timeout period to be longer
than the off time between commands.  The latter mode is particularly
useful for initially determining the timing information for a new remote.

   On success, the new value of the timeout period will be returned.

   On failure, undef is returned.

$slinke->requestIRMinimumLength()
---------------------------------

   This returns the length of the shortest IR receive message in bytes
which will be considered a valid message.

$slinke->setIRMinimumLength( $bytes )
-------------------------------------

   This set the length of the shortest IR receive message in bytes which
will be considered a valid message.  IR receiver modules such as the one
on the Slink-e tend to be very sensitive to both optical and electrical
noise, causing them to occasionally generate false pulses when there is no
actual IR signal.  The false pulses are generally of short duration and do
not contain the large number of on/off alternations present in a true IR
remote signal.  By setting a minimum message length, false pulses will be
ignored and not reported to the host.  The minimum length can range from 0
to 15 bytes.

   Upon success, the new minimum message length is returned.

   Upon failure, undef is returned.

$slinke->requestIRTransmitPorts()
---------------------------------

   This returns the value of the ports that the Slink-e uses for IR
transmissions.  The bits represent the 8 IR ports, IR0 being the LSB, IR7
the MSB.  A "1" indicates the port will be used.

   *This command requires a firmware version of 2.0 and above*

$slinke->setIRTransmitPorts( $ports )
-------------------------------------

   This sets the ports that the Slink-e uses for IR transmissions.  The
bits represent the 8 IR ports, IR0 being the LSB, IR7 the MSB.  A "1"
indicates the port will be used.

   *This command requires a firmware version of 2.0 and above*

$slinke->requestIRPolarity()
----------------------------

   Reports the polarity sense of each of the IR ports. These settings will
also affect the IR routing system. The bits of the response represent the
8 IR ports, IR0 being the LSB, IR7 the MSB. A "1" bit indicates that the
input is active-low (when the  input goes to 0 Volts), a "0" bit indicates
that the input is active-high (when the input goes to 5 Volts). All ports
are active-low by default so that they will work correctly with the IR
receiver modules. If you have some other low-speed serial device which is
active-high (e.g. a Control-S input) that you would like to connect, you
will want to change the polarity on that port.  Be careful with this
option - if you set the wrong polarity for a port, the Slink-e will be
locked into a constant receive state and will become unresponsive.

   *This command requires a firmware version of 2.0 and above*

$slinke->setIRPolarity( $ports )
--------------------------------

   Sets the polarity sense of each of the IR ports. These settings will
also affect the IR routing system. The bits of $ports represent the 8 IR
ports, IR0 being the LSB, IR7 the MSB. A "1" bit indicates that the input
is active-low (when the input goes to 0 Volts), a "0" bit indicates that
the input is active-high (when the input goes to 5 Volts). All ports are
active-low by default so that they will work correctly with the IR
receiver modules. If you have some other low-speed serial device which is
active-high (e.g. a Control-S input) that you would like to connect, you
will want to change the polarity on that port. Be careful with this option
- if you set the wrong polarity for a port, the Slink-e will be locked
into a constant receive state and will become unresponsive.

   *This command requires a firmware version of 2.0 and above*

$slinke->requestIRReceivePorts()
--------------------------------

   This returns the value of the ports that the Slink-e uses for IR
reception.  The bits represent the 8 IR ports, IR0 being the LSB, IR7 the
MSB.  A "1" indicates the port will be used.

   *This command requires a firmware version of 2.0 and above*

$slinke->setIRReceivePorts( $ports )
------------------------------------

   This sets the ports that the Slink-e uses for IR reception.  The bits
represent the 8 IR ports, IR0 being the LSB, IR7 the MSB.  A "1" indicates
the port will be used.

   *This command requires a firmware version of 2.0 and above*

   Upon success, this returns the ports that the Slink-e is using for IR
reception.

   Upon failure, undef is returned.

$slinke->requestIRRoutingTable()
--------------------------------

   This response describes the IR routing table. The routelist byte for
each IRRX port specifies which IRTX ports the received signal will be
echoed to.  The format for this byte is the same as the Set IR transmit
ports command.  The carrier byte specifes the carrier frequency to be used
in the routed signals from a given IRRX port. This byte is equivalent to
the CC byte in the Set IR carrier command. To reduce data storage
requirements, no prescaler value can be specified and the prescaler is
defaulted to 0 instead. This means that 15.7khz is the lowest available
carrier frequency for IR routing.

   *This command requires a firmware version of 2.0 and above*

$slinke->setIRRoutingTable( @data )
-----------------------------------

   This command sets up the IR routing table. The routelist byte for each
IRRX port specifies which IRTX ports the received signal will be echoed to.
The format for this byte is the same as the Set IR transmit ports command.
The carrier byte specifes the carrier frequency to be used in the routed
signals from a given IRRX port. This byte is equivalent to the CC byte in
the Set IR carrier command. To reduce data storage requirements, no
prescaler value can be specified and the prescaler is defaulted to 0
instead. This means that 15.7khz is the lowest available carrier frequency
for IR routing.

   *This command requires a firmware version of 2.0 and above*

$slinke->requestHandshaking()
-----------------------------

   Reports the input and output handshaking mode for the Parallel Port.

   As a binary number, the output looks as follows: `[0 0 0 0 0 0 in out]'

   Only the bits in and out are used.

   in = 0 : Disable Input Handshaking (default at startup). Disable the use
of DISTB/DIO7 as a handshaking pin, in turn freeing it for general I/O use.
When input handshaking is enabled, rising edges on the DISTB input cause
the Parallel Port data to be sampled and sent to the host in the form of a
port receive message. When disabled, sampling of the Parallel Port only
occurs when a sample port message is issued.

   in = 1 : Enable Input Handshaking  Enables the use of DISTB/DIO7 as a
handshaking pin, in turn removing it from general I/O use. When input
handshaking is enabled, rising edges on the DISTB input cause the Parallel
Port data to be sampled and sent to the host in the form of a port receive
message. When disabled, sampling of the Parallel Port only occurs when a
sample port message is issued.

   out= 0 : Disable Output Handshaking (default at startup). Disable the
use of DOSTB/DIO6 as a handshaking pin, in turn freeing it for general I/O
use. When output handshaking is enabled, each data byte sent out the
Parallel Port using the port send command will be accompanied by a
positive DOSTB pulse lasting one IR sampling period.

   out = 1 : Enable Output Handshaking Enable the use of DOSTB/DIO6 as a
handshaking pin, in turn removing it from general I/O use. When output
handshaking is enabled, each data byte sent out the Parallel Port using
the port send command will be accompanied by a positive DOSTB pulse
lasting one IR sampling period.

$slinke->setHandshaking( $handshaking )
---------------------------------------

   Sets the input and output handshaking mode for the Parallel Port.

   As a binary number, `$handshaking' looks as follows: `[0 0 0 0 0 0 in
out]'

   Only the bits in and out are used.

   in = 0 : Disable Input Handshaking (default at startup). Disable the
use of DISTB/DIO7 as a handshaking pin, in turn freeing it for general I/O
use. When input handshaking is enabled, rising edges on the DISTB input
cause the Parallel Port data to be sampled and sent to the host in the
form of a port receive message.  When disabled, sampling of the Parallel
Port only occurs when a sample port message is issued.

   in = 1 : Enable Input Handshaking  Enables the use of DISTB/DIO7 as a
handshaking pin, in turn removing it from general I/O use. When input
handshaking is enabled, rising edges on the DISTB input cause the Parallel
Port data to be sampled and sent to the host in the form of a port receive
message. When disabled, sampling of the Parallel Port only occurs when a
sample port message is issued.

   out= 0 : Disable Output Handshaking (default at startup). Disable the
use of DOSTB/DIO6 as a handshaking pin, in turn freeing it for general I/O
use. When output handshaking is enabled, each data byte sent out the
Parallel Port using the port send command will be accompanied by a
positive DOSTB pulse lasting one IR sampling period.

   out = 1 : Enable Output Handshaking Enable the use of DOSTB/DIO6 as a
handshaking pin, in turn removing  it from general I/O use. When output
handshaking is enabled, each data byte sent out the Parallel Port using
the port send command will be accompanied by a positive DOSTB pulse
lasting one IR sampling period.

   Upon success, the new handshaking setting is returned

   Upon failure, undef is returned.

$slinke->requestDirection()
---------------------------

   Reports which parallel port lines are inputs or outputs. The bits d7:d0
in the output correspond 1 to 1 with the Parallel Port I/O lines DIO7:DIO0.
Setting a direction bit to 1 assigns the corresponding DIO line as an
input, while setting it to 0 make it an output. At startup, all DIO lines
are configured as inputs. The use of handshaking on lines DISTB/DIO7 and
DOSTB/DIO6 overrides the direction configuration for these lines while
enabled.

$slinke->setDirection( $direction )
-----------------------------------

   Configures the parallel port lines as inputs or outputs. The bits d7:d0
in the direction byte correspond 1 to 1 with the Parallel Port I/O lines
DIO7:DIO0. Setting a direction bit to 1 assigns the corresponding DIO line
as an input, while setting it to 0 make it an output. At startup, all DIO
lines are configured as inputs. The use of handshaking on lines DISTB/DIO7
and DOSTB/DIO6 overrides the direction configuration for these lines while
enabled. Slink-e will return a configuration direction equals response to
verify your command.

$slinke->sampleParPort()
------------------------

   Causes the Slink-e to sample the Parallel Port inputs just as if it had
seen a rising edge on DISTB when input handshaking is enabled. This command
works whether input handshaking is enabled or not. The Slink-e will
respond with a port receive message containing the Parallel Port data.

   Note that this function does not actually return the parallel port data.
To get that, you must call the `requestInput' function.

$slinke->sendIR( DATA => $data [, IRPORT => $ports ] )
------------------------------------------------------

   This function allows you to send IR signals.  The DATA element should be
an array reference of run length coded signals.  If you wish to send the
IR on specific ports, set the `IRPORT' element.

   This function will automatically mute the IR Receivers while data is
being sent so that the receiver will not capture what the transmitter is
sending.

$slinke->sendData( DATA => $data, PORT => $port )
-------------------------------------------------

   This allows data to be sent over a S-Link port or the parallel port.
The `PORT' element must be set to either `PORT_SL0', `PORT_SL1',
`PORT_SL2' or `PORT_PAR'.  The data element should be an array reference
of the data to be sent.

$slinke->reset()
----------------

   Warm-boots the Slink-e, resetting all defaults including the baud rate.
In version 2.0 or greater, these defaults are loaded from an EEPROM which
is user programmable.

$slinke->loadDefaults()
-----------------------

   Causes the Slink-e to load all of the current user settings from EEPROM
memory so that they are returned to their default values, Be wary of the
fact that the baud rate stored in EEPROM could be different than the
current baud rate. In this case communications will be lost until the host
detects the new baud rate. If successful, the Slink-e will send a defaults
loaded response.

   *This command requires a firmware version of 2.0 and above*

$slinke->saveDefaults()
-----------------------

   Causes the Slink-e to save all of the current user settings to EEPROM
memory so that they will become the defaults the next time the Slink-e is
reset or powered-up. If successful, the Slink-e will send a defaults saved
response.

   *This command requires a firmware version of 2.0 and above*

decodeIR( @data )
-----------------

   This will take the data returned by requestInput and attempt to convert
it to a bit string.  This function returns a hash reference.

   Elements of the hash reference

     HEAD => The wakeup call for the device.  These are typically the first two
             bytes in the data array.  This is an array reference.

     CODE => This is a bit string indicating the command that was sent.
             For Sony devices, a "P" is thrown in when a pause in the data array
             is detected.

     TAIL => The bytes that indicate the end of the data string.  These are
             typically the last five bytes of the data array.  This is an array
             reference.

     ENCODING => This is an array reference of two array references that describes
             how zeroes and ones are encoded.

TODO
====

   Add bin mode for S-Link ports

AUTHOR
======

   Brian Paulsen <Brian@ThePaulsens.com>

   Copyright 2000, Brian Paulsen.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Bug reports and comments to Brian@ThePaulsens.com.

   For further information about the Slink-e, visit http://www.nirvis.com

Perl extension for dynamic generation of SMIL files.
****************************************************

NAME
====

   Smil.pm - Perl extension for dynamic generation of SMIL files.

SYNOPSIS
========

     use Smil;
     (read on, good knight...)

DESCRIPTION
===========

   This module provides an object oriented interface to generation of SMIL
(Synchronized Multimedia Integration Language) files.  Creating a simple
SMIL file is as simple as this script:

     use Smil;
     $s = new Smil;
     print $s->header; # Remember MIME header if running as CGI
     $s->addMedia( "src" => "rtsp://videoserver.com/video.rm" );
     print $s->getAsString();

   This will create the following SMIL file with the correct header,
perfect for a CGI script coming off a web server:

     Content-type: application/smil

     <smil>
        <body>
            <par>
                <ref src="rtsp://videoserver.com/video.rm"/>
            </par>
        </body>
     </smil>

   Your first SMIL file!  Actually, this doesn't do much, but SMIL
beginners can't be choosers, right?

   As a new feature as of 0.70, you can now use Quicktime extensions.
Peruse the qt.pl file in the installation directory for a sampling of the
methods you can call for Quicktime extensions added to the <smil> element.
Otherwise, add the attributes and their values directly into SMIL when
you call addMedia.  Smil.pm will allow any namespace attributes to pass
through to the media element.  When you do add one of these attributes, or
call something like setQtAutoplay(), Smil.pm automatically adds the
xmlns:qt attribute with the proper unique identifier to the <smil>
element.  So, if you decide midway through creation of a SMIL file that
you want Quicktime extensions, call the proper method and Smil.pm will add
the proper code to add these extensions to your SMIL file.

   You can do more advanced things by adding regions to your SMIL files,
and playing media inside those regions.

     $s = new Smil( "height" => 300, "width" => 300 );
     $region_name = "first_region";
     $s->addRegion( "name" => $region_name,
     		   "top" => 20, "left" => 35,
     		   "height" => 100, "width" => 100 );
     $s->addMedia( "src" => "rtsp://videoserver.com/video.rm",
               "region" => $region_name );
     print $s->getAsString;

   This code results in the following output:

     <smil>
        <head>
            <layout>
                <root-layout width="300"
                             height="300"/>
                <region width="100"
                        height="100"
                        left="35"
                        top="20"
                        id="first_region"/>
            </layout>
        </head>
        <body>
            <par>
                <ref src="rtsp://videoserver.com/video.rm"
                     region="first_region"/>
            </par>
        </body>
     </smil>

   (Well, sort of, I had to reformat it so that it didn't stretch past the
end of the line, but functionally exactly the same)

   All of this would be somewhat trivial if this module didn't expose the
main differentiator between SMIL and HTML - the timeline!  With SMIL you
can synchronize and schedule your media over a timeline, all without nasty
proprietary scripting solutions.  This idea is built into SMIL and exposed
in this module.

     $s = new Smil( "height" => 300, "width" => 300 );
     $region1 = "first_region";
     $region2 = "second_region";
     $s->addRegion( "name" => $region1,
     		"top" => 20, "left" => 35,
     		"height" => 100, "width" => 100 );
     $s->addRegion( "name" => $region2,
     		"top" => 60, "left" => 55,
     		"height" => 120, "width" => 120 );
     $s->startSequence();
     $s->addMedia( "src" => "rtsp://videoserver.com/video1.rm",
     	       "region" => $region1 );
     $s->addMedia( "src" => "rtsp://videoserver.com/video2.rm",
     	       "region" => $region2 );
     $s->endSequence();
     print $s->getAsString;

   Results in this (again formatted to fit your screen...)

     <smil>
        <head>
            <layout>
                <root-layout width="300" height="300"/>
                <region width="100" height="100"
                        left="35" top="20"
                        id="first_region"/>
                <region width="120" height="120"
                        left="55" top="60"
                        id="second_region"/>
            </layout>
        </head>
        <body>
            <seq>
                <ref src="rtsp://videoserver.com/video1.rm"
                        region="first_region"/>
                <ref src="rtsp://videoserver.com/video2.rm"
                        region="second_region"/>
            </seq>
        </body>
     </smil>

   You can schedule media in two ways, by calling startSequence coupled
with endSequence or startParallel with endParallel, as you saw above, or
you can specify begin and end times within the media directly for an
absolute timeline.

     $s = new Smil( "height" => 300, "width" => 300 );
     $region1 = "first_region";
     $region2 = "second_region";
     $s->addRegion( "name" => $region1,
     		"top" => 20, "left" => 35,
     		"height" => 100, "width" => 100 );
     $s->addRegion( "name" => $region2,
     		"top" => 60, "left" => 55,
     		"height" => 120, "width" => 120 );
     $s->startParallel();
     $s->addMedia( "src" => "rtsp://videoserver.com/video1.rm",
     	       "region" => $region1 );
     $s->addMedia( "src" => "rtsp://videoserver.com/video1.rm",
     	       "region" => $region2,
     	       "begin" => "5s" );
     $s->endParallel();
     print $s->getAsString();

   Producing this:

     <smil>
        <head>
            <layout>
                <root-layout width="300" height="300"/>
                <region width="100" height="100"
                        left="35" top="20" id="first_region"/>
                <region width="120" height="120"
                        left="55" top="60" id="second_region"/>
            </layout>
        </head>
        <body>
            <par>
                <ref src="rtsp://videoserver.com/video1.rm"
                     region="first_region"/>
                <ref src="rtsp://videoserver.com/video1.rm"
                     region="second_region" begin="5s"/>
            </par>
        </body>
     </smil>

   Notice the "begin" parameter, this tells the media its absolute begin
time.  The above code will start the second clip 5 seconds after the first
even though they are playing in parallel

   You can add your own code using the addCode method

     $s->addCode( "<new_tag/>" );

   You can add comments by using the addComment method

     $s->addComment( "A comment is here" );

   PerlySMIL will add the necessary comment code around the comment, so you
get back

   <!-A comment is here->

   You as the author are responsible for formatting, so don't expect that
your arbitrary code will be indented like the rest of the SMIL.

   Like HTML, SMIL applications can have hyperlinks.  There are two types
in SMIL: normal hrefs, and anchors.  An href covers the entire media item,
whereas an anchor covers a rectangular portion of the media item.  To
create an href, add the "href" parameter when you add the media to the
SMIL object.

     $s->addMedia( "src" => "rtsp://videosource.com/video.rm",
                   "show" => "new",
                   "href" => "http://www.destinationlink.com/link.html" );

   Adding anchors is more complex, but much more versatile.  You can do
everything with anchors that you can do with hrefs, but with anchors you
add the capability to change the hyperlinks over time and specify only
portions of the media item for linking.  To create an anchor you need to
pass, brace yourself, a reference to an array of hash references.  Mimic
the code below if you don't want to know what that means.  The format is
like this:

   [ { hash_values }, { hash_values } ] where hash_values are key-value
pairs like "bob" => "sally"  (Perl gurus know that "=>" is a synonym for
comma...)

   Here's a code example to get you started.

     $smil->addMedia( 'src' => "video.rm",
     		     'anchors' =>
                         [
                           { 'href' => "http://websrv.com/index.html,
                               'coords' => '0,0,110,50',
     			      'show' => 'new',
     			      'begin' => 3 } ,
                           { 'href' => "another.smil",
     			      'coords' => '125,208,185,245',
     			      'begin' => 9 }
                         ] );

   Notice several things about the above example.  One, with an anchor, we
can specify where we want the hyperlink to persist over the media item.
This is done using a coordinate system with two points, the top, left
corner, and the bottom, right corner.  So, if we wanted to remove the href
tag completely, we could just specify the entire canvas of the media item
in the coordinate parameter and we would have the same thing as a href.
Also, in the above example, we started some hyperlinks at different times.
The first one begins a 3 seconds, and the second begins at 9 seconds.  We
could have also specified end times using the "end" parameter/attribute.
Finally, since a SMIL is not HTML we have to have a mechanism for dealing
with links to HTML files (or other media for that matter) and media that
can play back within our SMIL player.  So, if we want to send the result
of clicking on a link to a web browser, we need to use the "show" parameter
and give it a value of "new".  If we want our SMIL player to handle the
hyperlink itself (as would be the case for the second example since it is
another smil file), we can either leave the "show" parameter out and let
it default to the SMIL player, or explicitly add "show" => "replace" to
replace the current SMIL file with the new link.

   As a new feature of 0.7, you can now inline your media files directly
within a SMIL file.  When you add media to smil using the addMedia method
call, specify -inline => 1 and the module will attempt to download or read
from local disk any files which are added using this attribute.  Check out
the inline.pl file inside the installation directory, and also the slurp.pl
script which will slurp in simple SMIL files and inline all code if you
give it the proper parameter.

AUTHOR
======

   Chris Dawson (cdawson@webiphany.com) http://www.webiphany.com/perlysmil/

SEE ALSO
========

   perl(1). perldoc CGI

load the C socket.h defines and structure manipulators
******************************************************

NAME
====

   Socket, sockaddr_in, sockaddr_un, inet_aton, inet_ntoa - load the C
socket.h defines and structure manipulators

SYNOPSIS
========

     use Socket;

     $proto = getprotobyname('udp');
     socket(Socket_Handle, PF_INET, SOCK_DGRAM, $proto);
     $iaddr = gethostbyname('hishost.com');
     $port = getservbyname('time', 'udp');
     $sin = sockaddr_in($port, $iaddr);
     send(Socket_Handle, 0, 0, $sin);

     $proto = getprotobyname('tcp');
     socket(Socket_Handle, PF_INET, SOCK_STREAM, $proto);
     $port = getservbyname('smtp', 'tcp');
     $sin = sockaddr_in($port,inet_aton("127.1"));
     $sin = sockaddr_in(7,inet_aton("localhost"));
     $sin = sockaddr_in(7,INADDR_LOOPBACK);
     connect(Socket_Handle,$sin);

     ($port, $iaddr) = sockaddr_in(getpeername(Socket_Handle));
     $peer_host = gethostbyaddr($iaddr, AF_INET);
     $peer_addr = inet_ntoa($iaddr);

     $proto = getprotobyname('tcp');
     socket(Socket_Handle, PF_UNIX, SOCK_STREAM, $proto);
     unlink('/tmp/usock');
     $sun = sockaddr_un('/tmp/usock');
     connect(Socket_Handle,$sun);

DESCRIPTION
===========

   This module is just a translation of the C `socket.h' file.  Unlike the
old mechanism of requiring a translated `socket.ph' file, this uses the
h2xs program (see the Perl source distribution) and your native C
compiler.  This means that it has a far more likely chance of getting the
numbers right.  This includes all of the commonly used pound-defines like
AF_INET, SOCK_STREAM, etc.

   Also, some common socket "newline" constants are provided: the
constants `CR', `LF', and `CRLF', as well as `$CR', `$LF', and `$CRLF',
which map to `\015', `\012', and `\015\012'.  If you do not want to use
the literal characters in your programs, then use the constants provided
here.  They are not exported by default, but can be imported individually,
and with the `:crlf' export tag:

     use Socket qw(:DEFAULT :crlf);

   In addition, some structure manipulation functions are available:

inet_aton HOSTNAME
     Takes a string giving the name of a host, and translates that to the
     4-byte string (structure). Takes arguments of both the 'rtfm.mit.edu'
     type and '18.181.0.24'. If the host name cannot be resolved, returns
     undef. For multi-homed hosts (hosts with more than one address), the
     first address found is returned.

inet_ntoa IP_ADDRESS
     Takes a four byte ip address (as returned by inet_aton()) and
     translates it into a string of the form 'd.d.d.d' where the 'd's are
     numbers less than 256 (the normal readable four dotted number
     notation for internet addresses).

INADDR_ANY
     Note: does not return a number, but a packed string.

     Returns the 4-byte wildcard ip address which specifies any of the
     hosts ip addresses. (A particular machine can have more than one ip
     address, each address corresponding to a particular network
     interface. This wildcard address allows you to bind to all of them
     simultaneously.)  Normally equivalent to inet_aton('0.0.0.0').

INADDR_BROADCAST
     Note: does not return a number, but a packed string.

     Returns the 4-byte 'this-lan' ip broadcast address.  This can be
     useful for some protocols to solicit information from all servers on
     the same LAN cable.  Normally equivalent to
     inet_aton('255.255.255.255').

INADDR_LOOPBACK
     Note - does not return a number.

     Returns the 4-byte loopback address. Normally equivalent to
     inet_aton('localhost').

INADDR_NONE
     Note - does not return a number.

     Returns the 4-byte 'invalid' ip address. Normally equivalent to
     inet_aton('255.255.255.255').

sockaddr_in PORT, ADDRESS
sockaddr_in SOCKADDR_IN
     In an array context, unpacks its SOCKADDR_IN argument and returns an
     array consisting of (PORT, ADDRESS).  In a scalar context, packs its
     (PORT, ADDRESS) arguments as a SOCKADDR_IN and returns it.  If this
     is confusing, use pack_sockaddr_in() and unpack_sockaddr_in()
     explicitly.

pack_sockaddr_in PORT, IP_ADDRESS
     Takes two arguments, a port number and a 4 byte IP_ADDRESS (as
     returned by inet_aton()). Returns the sockaddr_in structure with
     those arguments packed in with AF_INET filled in.  For internet
     domain sockets, this structure is normally what you need for the
     arguments in bind(), connect(), and send(), and is also returned by
     getpeername(), getsockname() and recv().

unpack_sockaddr_in SOCKADDR_IN
     Takes a sockaddr_in structure (as returned by pack_sockaddr_in()) and
     returns an array of two elements: the port and the 4-byte ip-address.
     Will croak if the structure does not have AF_INET in the right place.

sockaddr_un PATHNAME
sockaddr_un SOCKADDR_UN
     In an array context, unpacks its SOCKADDR_UN argument and returns an
     array consisting of (PATHNAME).  In a scalar context, packs its
     PATHNAME arguments as a SOCKADDR_UN and returns it.  If this is
     confusing, use pack_sockaddr_un() and unpack_sockaddr_un() explicitly.
     These are only supported if your system has <`sys/un.h'>.

pack_sockaddr_un PATH
     Takes one argument, a pathname. Returns the sockaddr_un structure with
     that path packed in with AF_UNIX filled in. For unix domain sockets,
     this structure is normally what you need for the arguments in bind(),
     connect(), and send(), and is also returned by getpeername(),
     getsockname() and recv().

unpack_sockaddr_un SOCKADDR_UN
     Takes a sockaddr_un structure (as returned by pack_sockaddr_un()) and
     returns the pathname.  Will croak if the structure does not have
     AF_UNIX in the right place.

load IPv6 related part of the C socket.h defines and structure manipulators
***************************************************************************

NAME
====

   Socket6, sockaddr_in6, inet_pton, inet_ntop - load IPv6 related part of
the C socket.h defines and structure manipulators

SYNOPSIS
========

     use Socket;
     use Socket6;

     @res = getaddrinfo('hishost.com', 'daytime', AF_UNSPEC, SOCK_STREAM);
     $family = -1;
     while (scalar(@res) >= 5) {
     	($family, $socktype, $proto, $saddr, $canonname, @res) = @res;

     ($host, $port) = getnameinfo($saddr, NI_NUMERICHOST | NI_NUMERICSERV);
     print STDERR "Trying to connect to $host port port $port...\n";

     socket(Socket_Handle, $family, $socktype, $proto) || next;
             connect(Socket_Handle, $saddr) && last;

     close(Socket_Handle);
     $family = -1;
         }

     if ($family != -1) {
     	print STDERR "connected to $host port port $port\n";
     } else {
     	die "connect attempt failed\n";
     }

DESCRIPTION
===========

   This module supports getaddrinfo() and getnameinfo() to intend to
enable protocol independent programing.  If your environment supports
IPv6, IPv6 related defines such as AF_INET6 are included.

   If you use Socket6 module, be sure to specify "use Socket" as well as
"use Socket6".

   Functions supplied are:

inet_pton AF HOST
inet_ntop AF ADDR

pack_sockaddr_in6 PORT ADDR

pack_sockaddr_in6_all PORT FLOWINFO ADDR SCOPEID

unpack_sockaddr_in6 NAME

unpack_sockaddr_in6_all NAME

gethostbyname2 HOSTNAME, SERVNAME
getaddrinfo HOSTNAME, SERVNAME, FAMILY, SOCKTYPE, PROTOCOL, FLAGS
          Arguments from FAMILY to FLAGS are optional.

getnameinfo NAME, FLAGS
          FLAGS argument is optional.

SYNOPSIS
========

     use Socket::PassAccessRights;
     Socket::PassAccessRights::sendfd(fileno(SOCKET), fileno(SEND_ME)) or die;
     $fd = Socket::PassAccessRights::recvfd(fileno(SOCKET)) or die;
     open FD, ">&=$fd" or die "$!";  # convert int fd to file handle

DESCRIPTION
===========

   Implements passing access rights (i.e. file descritors) over Unix
domain sockets. Only one fd can be passed at one time and no other data
can be sent in the same operation (operation itself involves sending
exactly one byte of data to solve EOF detection anomaly).

   See test.pl and examples directory for usage examples.

PLATFORMS
=========

   This code has only been tested on

     * Linux-2.0.38 with glibc-2.0.7 (libc.so.6) and libc.so.5 (BSD4.4 style)
     * Linux-2.2.14 with glibc-2.0.7 (libc.so.6) (BSD4.4 style)
     * Solaris-2.6 using gcc (BSD4.3 style)

   Specifically, the code from [Stevens] did not work out of the box. I had
to rename msg.msg_accrights* to msg.control* and send at least one byte.
General impression from net is that file descripto passing code seems to
be buggy - not just in Linux, but on FreeBSD, too.

AUTHOR AND COPYRIGHT
====================

   Sampo Kellomaki <sampo@iki.fi>

   Copyright (c) 2000 by Sampo Kellomaki <sampo@iki.fi>, All Rights
Reserved.

   This module may be copied under the same terms as perl itself.

SEE ALSO
========

   Home page: http://www.bacus.pt/Net_SSLeay/modules.html perl(1)
recvmsg(2) sendmsg(2) Richard Stevens: Unix Network Programming, Prentice
Hall, 1990; chapter 6.10.  /usr/include/socketbits.h
/usr/include/sys/socket.h

Perl extension for blah blah blah
*********************************

NAME
====

   Softref - Perl extension for blah blah blah

SYNOPSIS
========

     use Softref;
     blah blah blah

DESCRIPTION
===========

   Stub documentation for Softref was created by h2xs. It looks like the
author of the extension was negligent enough to leave the stub unedited.

   Blah blah blah.

Exported functions
==================

     void sv_rvsoft(SV*);

AUTHOR
======

   A. U. Thor, a.u.thor@a.galaxy.far.far.away

SEE ALSO
========

   perl(1).

Read /var/sadm/install/contents file
************************************

NAME
====

   Solaris::Contents - Read /var/sadm/install/contents file

SYNOPSIS
========

   $c=Solaris::Contents::new();

DESCRIPTION
===========

   Solaris::Contents is an object oriented interface into the
/var/sadm/install/contents file which Solaris uses to keep track of all
the files installed on a system, and their corresponding packages.

CONSTRUCTOR METHOD
==================

   $c=Solaris::Contents::new();

   No arguements are required.  By default, the object always believes the
contents file is /var/sadm/install/contents.  The ability to change this
could change with a future release.

OBJECT METHODS
==============

entries()
     Returns an array of every file record in the contents file.  Very
     long.

entriesForPkg()
     Returns an array of every file record for a specified package.

entry($file)
     Returns a hash table of every element for a specified file.

ftype($file)
class($file)
major($file)
minor($file)
mode($file)
user($file)
group($file)
size($file)
cksum($file)
modified($file)
pkgs($file)
     Each of the above methods returns the specific data for a specified
     file entry from the contents file.  Not all entries will have data
     specific to every method.  Check the Solaris prototype man page for
     more information.  The pkgs() method returns an array of packages
     related to that specific file.

NOTES
=====

   The initialization time of Contents objects could take a few seconds
depending on the size of the contents file.

   I may add more methods to this class later on.  It would be kind of
neat to do more with the link entries.

AUTHOR
======

   Chris Josephes, chrisj@onvoy.com

Manages Solaris package information
***********************************

NAME
====

   Solaris::InstallDB - Manages Solaris package information

SYNOPSIS
========

   use Solaris::InstallDB $instdb=Solaris::InstallDB::new(-directory =>
$dir, -loadContents);

DESCRIPTION
===========

   The Solaris::InstallDB class manages a directory of Solaris packages. It
searches for all of the packages in a directory, and then records them in
a hash table by name and architecture.  It is also capable of spawning a
Solaris::Contents object.

   With this class, you can get a list of all packages available, and all
architectures it supports.  It can also report some basic system about the
hardware it is running on.

CONSTRUCTOR METHOD
==================

   $instdb=Solaris::InstallDB::new(-directory => $dir, -loadContents);

   The new method creates a Solaris::InstallDB object.  By default, it will
search for objects in the /var/sadm/pkg directory, but you can change that
by using the -directory parameter.

   If you want to create a Solaris::Contents object automatically, add the
-loadContents flag.

OBJECT METHODS
==============

release()
     Returns the operating system release number in uname format.  For
     example, if you were running a script on a Solaris 7 system, it would
     return 5.7.

releaseAlias()
     Returns the commercial name of the operating system.  For example, if
     you were running a script on an Intel system running Solaris 7, it
     would return 7_x86.

isa()
     Returns the Instruction Set Architecture of the hardware.

processor()
     Returns the processor type.

hardwareClass()
     Returns the hardware class.

arch()
     Returns a combination of the ISA and hardware class.

packages()
     Returns a list of the packages found in the specified directory

arches($pkg)
     Returns a list of architectures supported by a given package.

contents()
     Returns the Solaris::Contents object that was created when the object
     was initialized.

package(-name => $pkg, -arch => $arch, -debug)
     Returns a Solaris::Package object.

     If -arch isn't specified, the object will search the database for a
     suitable match based on the system the script is running on.

     If -debug is specified and the method fails to return a package
     object, an error message to STDOUT will explain why the method failed.

pkgFile(-name => $name, -arch => $arch)
     Returns the filename of a particular package for the specified
     architecture

directory()
     Returns the directory the object is looking for packages in

NOTES
=====

   This object only works on packages in the directory format, not the data
stream format.

   The code may seem a bit complex, but it's due to the fact that there are
different package directories for the same package, but with different
architectures.

   Since I have a lot of code that gives hardware information, I may work
on the idea of a Solaris::Hardware package during a later code revision.

AUTHOR
======

   Chris Josephes, chrisj@onvoy.com

Perl module to obtain basic Solaris Package Info
************************************************

NAME
====

   Solaris::Package - Perl module to obtain basic Solaris Package Info

SYNOPSIS
========

     use Solaris::Package;

     $x=Solaris::Package::new(-directory => "/tmp/install", -file => "SUNWm64.u");

DESCRIPTION
===========

   Solaris::Package is a class module that reads in the information from a
pkginfo file for a Solaris package.  It can be spawned from a
Solaris::InstallDB object, or it can be used as a standalone object.

CONSTRUCTOR METHOD
==================

$pkg=Solaris::Package::new(-directory => $dir, -file => $pkgDir);
     The -directory arguement specifies what package directory to search
     in, the -file directory points to the directory name the package is
     in.

     Optionally, you can specify a pointer to a Solaris::InstallDB object
     by using the -installDB arguement.

     Two points to clarify:

     This object only works on Solaris packages in the directory format,
     not the data stream format, so the -file arguement is really
     specifying a filesystem directory.

     The name of a package is not necessarily the same as the name of the
     file of the package.  The SUNWm64 example at the beginning of this
     documentation is an example of a package with a different directory
     name.

OBJECT METHODS
==============

pkg()
name()
desc()
pkVersion()
arch()
email()
hotline()
vendor()
basedir()
pstamp()
instdate()
patchList()
     Each of these methods returns their corresponding pkginfo parameter.
     Note that patchList() returns an array type, with each element
     listing a single patch. The pkVersion() method returns the package
     version, and should not be confused with the version() method.

pkgInfo()
     Returns a simplified output similar to the "pkginfo" command, but
     does not report filesystem contents.  That can be achieved by using
     the Solaris::Contents object.

paramDump()
     Returns a hash table with every parameter in the pkginfo file and
     every corresponding value

AUTHOR
======

   Chris Josephes, chrisj@onvoy.com

SEE ALSO
========

   The pkginfo(4) manpage.

Patchdiag class file
********************

NAME
====

   Solaris::Patchdiag - Patchdiag class file

SYNOPSIS
========

   use Solaris::Patchdiag; $pd=Solaris::Patchdiag::new(-file => $filename);

DESCRIPTION
===========

   Solaris::Patchdiag is a class for accessing the content of the
patchdiag.xref file, which is a file Sun puts out to list patches
available for the Solaris operating system.

   An instance method of the class reads in the file, and accessor methods
allow programs to obtain information about the patches, such as what OS
version the patch is for, and what packages the patch is applied to.

CONSTRUCTOR METHOD
==================

   $pd=Solaris::Patchdiag::new(-file => $filename);

   The new method can accept a file paramter to specify what
patchdiag.xref file it should read.  If no file is specified, the object
will look for a patchdiag.xref file in the current directory.

OBJECT METHODS
==============

rev($id)
releaseDate($id)
recommendedFlag($id)
securityFlag($id)
obsoleteFlag($id)

y2kFlag($id)
osRelease($id)
arch($id)
pkgs($id)
synopsis($id)
     Each of the above methods access fields within the file for a
     specified patch.  To find out what operating system release patch ID
     108832 is for, you would use

          $os=$pd->osRelease(108832);

file()
     Returns the name of the patchdiag.xref file being referenced

list()
     Returns a list of all patches in the patchdiag.xref file

entry($id)
     Returns a hash table with all of the data for a particular patch

recommendedList()
securityList()
obsoleteList()

y2kList()
     Each of the above methods returns an array list of patches with the
     appropriate flag set.  For example, to get a list of all of the
     security classified patches, use

          (@secpatches)=$pd->securityList();

patchesFor($pkg,$osRelease)
     Returns an array of all the patches that modify a package in a
     specific OS Release

NOTES
=====

   The patchdiag.xref file is a REALLY awkward file format, and the fact
that it isn't really documented doesn't help much.  I'm only interpreting
it based on the source code of the patchdiag.pl program and from
observation.

   The "arch" field apparantly lists architectures supported by the patch,
AND prerequisite patches that need to be installed beforehand.

   The "flag" fields contain a space when empty, which technically wastes
space.

   The "y2k" field can contain either a "Y" or a "B", and the original
patchdiag.pl program checks for the possibility of a "YB" value as well.
I have no idea what the differences are, so I just report the flag as set
if either character is present.

   The "osRelease" field specifies the Solaris OS release name, which
involves some munging, and it makes no sense at times.  Why report "7_x86"
in one field, when you already report the platform architecture in
another?  Maybe it's really a Solaris naming convention issue.

AUTHOR
======

   Chris Josephes, chrisj@onvoy.com

SEE ALSO
========

   The patchdiag(1m) manpage.

make sort functions for arbitrary sort orders
*********************************************

NAME
====

   Sort::ArbBiLex - make sort functions for arbitrary sort orders

SYNOPSIS
========

     use Sort::ArbBiLex (
       'fulani_sort',   # ask for a &fulani_sort to be defined
       "a A
        c C
        ch Ch CH
        ch' Ch' CH'
        e E
        l L
        lh Lh LH
        n N
        r R
        s S
        u U
        z Z
       "
     );
     @words = <>;
     @stuff = fulani_sort(@words);
     foreach (@stuff) { print "<$_>\n" }

CONCEPTS
========

   Writing systems for different languages usually have specific sort
orders for the glyphs (characters, or clusters of characters) that each
writing system uses.  For well-known national languages, these different
sort orders (or someone's idea of them) are formalized in the locale for
each such language, on operating system flavors that support locales.
However, there are problems with locales; cf. Perllocale (perl.info).
Chief among the problems relevant here are:

   * The basic concept of "locale" conflates language/dialect, writing
system, and character set - and country/region, to a certain extent.  This
may be inappropriate for the text you want to sort.  Notably, this assumes
standardization where none may exist (what's THE sort order for a language
that has five different Roman-letter-based writing systems in use?).

   * On many OS flavors, there is no locale support.

   * Even on many OS flavors that do suport locales, the user cannot
create his own locales as needed.

   * The "scope" of a locale may not be what the user wants - if you want,
in a single program, to sort the array @foo by one locale, and an array
@bar by another locale, this may prove difficult or impossible.

   In other words, locales (even if available) may not sort the way you
want, and are not portable in any case.

   This module is meant to provide an alternative to locale-based sorting.

   This module makes functions for you that implement bi-level
lexicographic sorting according to a sort order you specify.
"Lexicographic sorting" means comparing the letters (or properly,
"glyphs", as I'll call them here, when a single glyph can encompass
several letters, as with digraphs) in strings, starting from the start of
the string (so that "apple" comes after "apoplexy", say) - as opposed to,
say, sorting by numeric value.  "Lexicographic sorting" is sometimes used
to mean just "ASCIIbetical sorting", but I use it to mean the sort order
used by *lexicograph*ers, in dictionaries (at least for alphabetic
languages).

   Consider the words "resume" and "rE<eacute>sumE<eacute>" (the latter
should display on your POD viewer with acute accents on the e's).  If you
declare a sort order such that e-acute ("E<eacute>") is a letter after e
(no accent), then "rE<eacute>sumE<eacute>" (with accents) would sort after
every word starting with "re" (no accent) - so "rE<eacute>sumE<eacute>"
(with accents) would come after "reward".

   If, however, you treated e (no accent) and e-acute as the same letter,
the ordering of "resume" and "rE<eacute>sumE<eacute>" (with accents) would
be unpredictable, since they would count as the same thing - whereas
"resume" should always come before "rE<eacute>sumE<eacute>" (with accents)
in English dictionaries.

   What bi-level lexicographic sorting means is that you can stipulate
that two letters like e (no accent) and e-acute ("E<eacute>") generally
count as the same letter (so that they both sort before "reward"), but
that when there's a tie based on comparison that way (like the tie between
"resume" and "rE<eacute>sumE<eacute>" (with accents)), the tie is broken
by a stipulation that at a second level, e (no accent) does come before
e-acute ("E<eacute>").

   (Some systems of sort order description allow for any number of levels
in sort orders - but I can't imagine a case where this gets you anything
over a two-level sort.)

   Moreover, the units of sorting for a writing system may not be
characters exactly.  In some forms of Spanish, ch, while two characters,
counts as one glyph - a "letter" after c (at the first level, not just the
second, like the e in the paragraph above).  So "cuerno" comes before
"chile".  A character-based sort would not be able to see that "ch" should
count as anything but "c" and "h".  So this library doesn't assume that
the units of comparison are necessarily individual characters.

Limitations
-----------

   * The most notable limitation of this module is that its identification
of glyphs must be context-insensitive.  So you can't stipulate that, for
example, ":" normally counts as a letter after "h", but that it doesn't
count (or that it counts as a letter after "z", or whatever) in the
special case of appearing at the start of words.

   * You can't declare whitespace characters of any kind as sortable
glyphs using the single-string ("short form") declaration.  This is,
obviously, because in that declaration format, whitespace is reserved as
the delimiter for glyphs and families.  So if you want to have space, tab,
CR, and/or LF be sortable glyphs, you just have to declare that with the
long form (LoL-reference) format.  See the sections on these formats,
below.

   * When you have Sort::ArbBiLex generate a new bi-level sort function
based on a sort-order declaration, both levels of comparison obviously
have the same sort-order declaration - so you can't have Sort::ArbBiLex
make a function where at one level "ch" counts as one glyph, and at the
other, it counts as two; nor where it counts as a glyph in one position in
one level, and at another position in the other level.

   * When you declare a glyph as consisting of several characters, you're
saying that several letters should be considered as one unit.  However,
you can't go the other way: you can't say that a single letter should be
considered as a combination of glyphs.  But I've seen some descriptions of
German sort order that say that a-umlaut (etc) should be treated as if it
were a literal "ae" - i.e. an "a" glyph followed by an "e" glyph.  This
can't be done simply with Sort::ArbBiLex.

   * Note that ArbBiLex-generated sort routines always start sorting (at
both levels) with glyphs at the start of the string, and continue to the
end.  But some descriptions (like p138 of the *Unicode Standard Version
3.0*) of French sort order say that the the first level of sorting goes as
you'd expect, start to finish, but a later level, ties between different
accents are broken *starting from the end*, and working backwards.  This
can't be done simply with Sort::ArbBiLex.  (But it's my experience that
the difference is not significant, in the case of French data.)

   * Currently, you cannot declare more than 255 glyph-groups (i.e.,
glyphs that sort the same at the first level), and no glyph-group can
contain more that 255 glyphs each.  (This may change in the future.)
However, it's fine if the total number of glyphs in all glyph-groups sums
to greater than 255 (as in the case of a declaration for 30 glyph-groups
with 10 glyphs each).

   * I'm writing this module before all details of Perl's future handling
of text in Unicode are clear.  This may change how this module works,
although I'm hoping it will not introduce any incompatibilities.

   * This library makes no provision for overriding the builtin sort
function.  It's probably a bad idea to try to do so, anyway.

   * If all of the glyphs in a given sort order are one character long, the
resulting sorter function will be rather fast.  If any of them are longer
than that, it is rather slower.  (This is because one-character mode does
its work with lots of tr///'s, whereas "multi"-character mode (i.e., if
any glyphs are more than one character long) uses lots of s///'s and
hashes.  It's as fast as I can make it, but it's still necessarily much
slower than single-character mode.  So if you're sorting 10,000 dictionary
headwords, and you change your sort order from one that uses all
one-character glyphs, to one where there's even just one two-character
glyph, and you notice that it now takes 15 seconds instead of 3 before,
now you know why.

   * *Remember*, if this module produces a function that *almost* does
what you want, but doesn't exactly, because of the above limitations, then
you can be have it output the source (via `source_maker') of the function,
and try modifying that function on your own.

DESCRIPTION
===========

   This module provides two functions, `Sort::ArbBiLex::maker' and
`Sort::ArbBiLex::source_maker', and it also presents an interface that
accepts parameters in the `use Sort::ArbBiLex ( ... )' statement.

`use Sort::ArbBiLex;'
---------------------

   This merely loads the module at compile-time, just like any normal "use
*[modulename]*".  But with parameters, it's special:

`use Sort::ArbBiLex ( 'name', DECLARATION, ...  );'
---------------------------------------------------

   This compile-time directive, besides loading the module if it's not
already in memory, will interpret the parameters as a list of pairs, where
each pair is first the name of a sub to create and then the DECLARATION of
its sort order.  This calls `Sort::ArbBiLex::maker(DECLARATION)' to make a
such-named function, that sorts according to the sort order you specify.

   This is probably the only way most users will need to interact with
this module; they probably won't need to call
`Sort::ArbBiLex::maker(DECLARATION)' (much less
`Sort::ArbBiLex::source_maker(DECLARATION)'!) directly.

   Unless your sort-order declarations are variables, you can simply use
this `use Sort::ArbBiLex (...)' syntax.  Feel free to skip ahead to the
"Values for DECLARATION" section.

The function Sort::ArbBiLex::maker(DECLARATION)
-----------------------------------------------

   `maker' is called thus:

     Sort::ArbBiLex::maker(DECLARATION)

   This will make a sort function, based on the contents of DECLARATION.
The return value is an anonymous subroutine reference.  While you can
store this just like any another anonymous subroutine reference, you
probably want to associate it with name, like most functions.  To
associate it with the symbol `fulani_sort' in the current package, do this:

     *fulani_sort = Sort::ArbBiLex::maker($my_decl);

   Then you can call `fulani_sort(@whatever)' just like any other kind of
function, just as if you'd defined `fulani_sort' via:

     sub fulani_sort {
       ...blah blah blah...
     }

   As you might expect, you can specify a package, like so:

     *MySorts::fulani_sort = Sort::ArbBiLex::maker($my_decl);

   If you don't know what `*thing = EXPR' means or how it works, don't
worry, just use it - or duck the whole issue by using the "`use
Sort::ArbBiLex ('fulani_sort', DECL);'".

   Actually, there's a minor difference between the various ways of
declaring the subroutine `fulani_sort': if you declare it via a call to
this:

     *fulani_sort = Sort::ArbBiLex::maker($my_decl);

   then that happens at runtime, not compile time.  However, compile-time
is when Perl wants to know what subs will exist if you want to be able to
call them without parens.  I.e., this:

     @stuff = fulani_sort @whatever;  # no parens!

   will cause all sorts of angry error messages, which you can happily
avoid by simply adding a "forward declaration" at some early point in the
program, to express that you're goung to want to use "fulani_sort" as a
sub name:

     sub fulani_sort;  # yup, just that!
     ...later...
     *fulani_sort = Sort::ArbBiLex::maker($my_decl);
     ...later...
     @stuff = fulani_sort @whatever;  # no parens!

   And then all should be well.

   The short story is to use the "`use Sort::ArbBiLex ('fulani_sort',
...)'" syntax whenever possible (at which point you're free to omit
parens, since the "use" makes it happen at compile-time, not runtime).

   But when you can't use the "`use Sort::ArbBiLex ('fulani_sort', ...)'"
syntax, and you need to use a "`*foo = ...'" syntax instead (which *is*
usually necessary if your declaration is a variable, instead of a
literal), then either add a "`sub fulani_sort;'" line to your program; or
just be sure to use parens on every call to the `fulani_sort' function.

   See also: Perlsub (perl.info), for the whys and
wherefors of function protoptying, if you want all the scary details.

The function Sort::ArbBiLex::source_maker(DECLARATION)
------------------------------------------------------

   `Sort::ArbBiLex::source_maker' is just like `Sort::ArbBiLex::maker',
except that it returns a string containing the source of the function.
It's here if you want to, well, look at the source of the function, or
write it to a file and modify it.

Values for DECLARATION
======================

   DECLARATION is a specification of the sort order you want the new
function to sort according to.

   It can occur in two formats: short form (a single string), and long
form (a reference to a list of lists of glyphs).

Short-form DECLARATION values
-----------------------------

   A short-form specification consists of a string that consists of lines
containing glyphs.  The example in the SYNOPSIS section shows this format.

   Formally, lines in the short-form declaration string are separated by
carriage returns and/or linefeeds.  Each line consists of glyphs separated
by whitespace (other than CRs or LFs).  Lines that are empty (i.e., which
contain no glyphs) are ignored.  A declaration that contains no glyphs at
all is illegal, and causes a fatal error.  A "glyph" is any sequence of
non-whitespace characters.  No glyph can appear more that once in the
declaration, or it's a fatal error.

   A degenerate case of there being only one glyph-family with many glyphs
in it (i.e., a one-level sort instead of a bi-level), like this:

     Sort::ArbBiLex::maker('fulani_sort',
       "a A c C c' C' e E h H x X i I : l L n N r R s S u U z Z zh Zh ZH"
     );

   is actually treated as if it were that many glyph-families with only
one glyph in each.  This in an internal optimization.

   PLEASE NOTE that any characters that *are* in the data being sorted but
which *do not* appear in the sort order declaration (neither as
themselves, or as part of glyphs) are treated *as if they are not there*.
In other words, given the sort order in the above example, if you had
"David" as an item to sort, it would sort just as if it were "ai" - since
"D", "v", and "d" aren't in that declaration.  So think twice before
deciding that certain letters "are not part of the alphabet" of the
language in question.

   Note also that if, say, "ch" is in the sort order, but "h" isn't, then
an "h" not after a "c" (like in "helicopter" or "pushed") will not be
counted for sake of sorting.

Long-form DECLARATION values
----------------------------

   A long-form specification consists of a reference to a list of lists of
glyphs.  For example, the example from the SYNOPSIS section could just as
well be denoted with a long-form declaration like this:

     use Sort::ArbBiLex ( 'fulani_sort',
      [
        [ "a", "A" ],
        [ "c", "C" ],
        [ "ch", "Ch", "CH" ],
        [ "ch'", "Ch'", "CH'" ],
        [ "e", "E" ],
        [ "l", "L" ],
        [ "lh", "Lh", "LH" ],
        [ "n", "N" ],
        [ "r", "R" ],
        [ "s", "S" ],
        [ "u", "U" ],
        [ "z", "Z" ],
      ]
     );

   The main practical reason I provide this declaration is that, as
discussed in the Limitations section, the short form doesn't allow you to
declare whitespace characters of any kind as sortable glyphs using the
single-string ("short form") declaration, because in that declaration
format, whitespace is reserved as the delimiter for glyphs and families.
But you can do it in the long form.  In the above example, you'd just add
a line before the one for a/A, like this:

     use Sort::ArbBiLex ( 'fulani_sort',
       [
        [ " ", "\t", "\cm", "\cj" ],  # whitespace characters.
        [ "a", "A" ],
       ...etc...

   That'd make whitespace the first glyph family.  The effect of this
would be to make sorting sensitive to whitespace, such that "for", "for
sure", and "forest" would sort in that order.  It's my impression that
most modern English dictionaries sort without respect to whitespace (so
that that list, sorted, would be "for", "forest", "for sure"), but I also
realize that that's not the only way to do it.  In fact, sensitivity to
whitespace seems an inevitable part of conventional sort orders for some
languages.

   A thought: Presumably the only place you'd want to put the whitespace
family is at the start of the declaration.  It'd be really strange in the
middle or the end, I think.

   A word of caution: Note that, if you have whitespace as a glyph family,
"for sure" (with just the one space) and "for  sure" (with two spaces
inbetween) do not sort the same.  You may expect that the sorter would
magically collapse whitespace, seeing all sequences of whitespace as
equal.  Au contraire!  They're glyphs, just like any others, so sorting
"for sure" and "for  sure" (two spaces) is totally analogous to sorting
"ika" and "ikka".

GUTS
====

   * ArbBiLex stands for "arbitrary bi-level lexicographic".

   * The source to this module may tie your brain in knots.  That's what it
does to me, *and I wrote it*.  Code that writes code can be icky that way.

   If you want to figure out this module's workings, try using:

     print Sort::ArbBiLex::source_maker($decl);

   where you start out with $decl as something short.  Understand the code
that this module makes before you try to understand how it makes it.

   * The sorter functions this module makes are built around the
Schwartzian transform - i.e., the construct "map BLOCK sort BLOCK map
BLOCK List".  For a brief discussion of that, see Perlfaq4 (perl.info),
under the question "How do I sort an array by
(anything)?".  Or maybe I'll write a *Perl Journal* (www.tpj.com) article
about it some time.

   * If you look at, say,

     use Sort::ArbBiLex (fu => "a b c ch d i h s sh x");
     @x = fu( qw(chachi baba) );

   and if you wonder how the "ch" in "chachi" ends up as one glyph "ch"
(which is what happens), instead of as a glyph "c" and a glyph "h" (which
is not what happens), then consider that this

     print "<$1>" while 'chache' =~ /(ch|c|h|a|e)/g

   prints "<ch><a><ch><e>", not "<c><h><a><c><h><e>".

   * While you're at it, consider that this:

     print "<$1>" while "itlha" =~ /(tl|lh|l|h|i|a)/g

   prints "<i><tl><h><a>", never "<i><t><lh><a>".  Presumably this is
always The Right Thing.

   * Most modules that define an import method (either directly, or by
inheritating from the Exporter module), use it to just export pre-existing
subs from their own package into the calling package.  But
Sort::ArbBiLex's import is different - there's no pre-existing subs to
export, so it just makes new anonymous subs on demand, and sticks them
into the package that's current for the given "`use Sort::ArbBiLex'" line
(unless the given subname already has a package name on it, like
"MySorts::nornish").

COPYRIGHT
=========

   Copyright 1999, 2000, Sean M. Burke `sburke@cpan.org', all rights
reserved.  This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

AUTHOR
======

   Sean M. Burke `sburke@cpan.org'

Sort lines containing delimited fields
**************************************

NAME
====

   Sort::Fields - Sort lines containing delimited fields

SYNOPSIS
========

     use Sort::Fields;
     @sorted = fieldsort [3, '2n'], @lines;
     @sorted = fieldsort '\+', [-1, -3, 0], @lines;

     $sort_3_2n = make_fieldsort [3, '2n'], @lines;
     @sorted = $sort_3_2n->(@lines);

DESCRIPTION
===========

   Sort::Fields provides a general purpose technique for efficiently
sorting lists of lines that contain data separated into fields.

   Sort::Fields automatically imports two subroutines, `fieldsort' and
`make_fieldsort', and two variants, `stable_fieldsort' and
`make_stable_fieldsort'.  `make_fieldsort' generates a sorting subroutine
and returns a reference to it.  `fieldsort' is a wrapper for the
`make_fieldsort' subroutine.

   The first argument to make_fieldsort is a delimiter string, which is
used as a regular expression argument for a split operator.  The delimiter
string is optional.  If it is not supplied, make_fieldsort splits each
line using `/\s+/'.

   The second argument is an array reference containing one or more field
specifiers.  The specifiers indicate what fields in the strings will be
used to sort the data.  The specifier "1" indicates the first field, "2"
indicates the second, and so on.  A negative specifier like "-2" means to
sort on the second field in reverse (descending) order.  To indicate a
numeric rather than alphabetic comparison, append "n" to the specifier.  A
specifier of "0" means the entire string ("-0" means the entire string, in
reverse order).

   The order in which the specifiers appear is the order in which they
will be used to sort the data.  The primary key is first, the secondary
key is second, and so on.

   `fieldsort [1, 2], @data' is roughly equivalent to `make_fieldsort([1,
2])->(@data)'.  Avoid calling fieldsort repeatedly with the same sort
specifiers.  If you need to use a particular sort more than once, it is
more efficient to call `make_fieldsort' once and reuse the subroutine it
returns.

   `stable_fieldsort' and `make_stable_fieldsort' are like their
"unstable" counterparts, except that the items that compare the same are
maintained in their original order.

EXAMPLES
========

   Some sample data (in array `@data'):

     123   asd   1.22   asdd
     32    ewq   2.32   asdd
     43    rewq  2.12   ewet
     51    erwt  34.2   ewet
     23    erww  4.21   ewet
     91    fdgs  3.43   ewet
     123   refs  3.22   asdd
     123   refs  4.32   asdd

     # alpha sort on column 1
     print fieldsort [1], @data;

     123   asd   1.22   asdd
     123   refs  3.22   asdd
     123   refs  4.32   asdd
     23    erww  4.21   ewet
     32    ewq   2.32   asdd
     43    rewq  2.12   ewet
     51    erwt  34.2   ewet
     91    fdgs  3.43   ewet

     # numeric sort on column 1
     print fieldsort ['1n'], @data;

     23    erww  4.21   ewet
     32    ewq   2.32   asdd
     43    rewq  2.12   ewet
     51    erwt  34.2   ewet
     91    fdgs  3.43   ewet
     123   asd   1.22   asdd
     123   refs  3.22   asdd
     123   refs  4.32   asdd

     # reverse numeric sort on column 1
     print fieldsort ['-1n'], @data;

     123   asd   1.22   asdd
     123   refs  3.22   asdd
     123   refs  4.32   asdd
     91    fdgs  3.43   ewet
     51    erwt  34.2   ewet
     43    rewq  2.12   ewet
     32    ewq   2.32   asdd
     23    erww  4.21   ewet

     # alpha sort on column 2, then alpha on entire line
     print fieldsort [2, 0], @data;

     123   asd   1.22   asdd
     51    erwt  34.2   ewet
     23    erww  4.21   ewet
     32    ewq   2.32   asdd
     91    fdgs  3.43   ewet
     123   refs  3.22   asdd
     123   refs  4.32   asdd
     43    rewq  2.12   ewet

     # alpha sort on column 4, then numeric on column 1, then reverse
     # numeric on column 3
     print fieldsort [4, '1n', '-3n'], @data;

     32    ewq   2.32   asdd
     123   refs  4.32   asdd
     123   refs  3.22   asdd
     123   asd   1.22   asdd
     23    erww  4.21   ewet
     43    rewq  2.12   ewet
     51    erwt  34.2   ewet
     91    fdgs  3.43   ewet

     # now, splitting on either literal period or whitespace
     # sort numeric on column 4 (fractional part of decimals) then
     # numeric on column 3 (whole part of decimals)
     print fieldsort '(?:\.|\s+)', ['4n', '3n'], @data;

     51    erwt  34.2   ewet
     43    rewq  2.12   ewet
     23    erww  4.21   ewet
     123   asd   1.22   asdd
     123   refs  3.22   asdd
     32    ewq   2.32   asdd
     123   refs  4.32   asdd
     91    fdgs  3.43   ewet

     # alpha sort on column 4, then numeric on the entire line
     # NOTE: produces warnings under -w
     print fieldsort [4, '0n'], @data;

     32    ewq   2.32   asdd
     123   asd   1.22   asdd
     123   refs  3.22   asdd
     123   refs  4.32   asdd
     23    erww  4.21   ewet
     43    rewq  2.12   ewet
     51    erwt  34.2   ewet
     91    fdgs  3.43   ewet

     # stable alpha sort on column 4 (maintains original relative order
     # among items that compare the same)
     print stable_fieldsort [4], @data;

     123   asd   1.22   asdd
     32    ewq   2.32   asdd
     123   refs  3.22   asdd
     123   refs  4.32   asdd
     43    rewq  2.12   ewet
     51    erwt  34.2   ewet
     23    erww  4.21   ewet
     91    fdgs  3.43   ewet

BUGS
====

   Some rudimentary tests now.

   Perhaps something should be done to catch things like:

     fieldsort '.', [1, 2], @lines;

   `'.'' translates to `split /./' - probably not what you want.

   Passing blank lines and/or lines containing the wrong kind of data
(alphas instead of numbers) can result in copious warning messages under
-w.

   If the regexp contains memory parentheses (`(...)' rather than
`(?:...)'), split will function in "delimiter retention" mode, capturing
the contents of the parentheses as well as the stuff between the
delimiters.  I could imagine how this could be useful, but on the other
hand I could also imagine how it could be confusing if encountered
unexpectedly.  Caveat sortor.

   Not really a bug, but if you are planning to sort a large text file,
consider using sort(1).  Unless, of course, your operating system doesn't
have sort(1).

AUTHOR
======

   Joseph N. Hall, joseph@5sigma.com

SEE ALSO
========

   perl(1).

general rules-based sorting of lists
************************************

NAME
====

     Sort::PolySort -- general rules-based sorting of lists

SYNOPSIS
========

     use Sort::PolySort;
     $s=new Sort::PolySort;			# defaults to 'name'
     @people=('John Doe','Jane Doll','John Quasimodo Doe');
     print join(", ",$s->sort(@people),"\n";

     use Sort::PolySort;
     $s=new Sort::PolySort('dateus');	# sets internal
     @dates=$s->sort(@dates);		# uses internal
     $s->by('email');			# sets internal
     @names=$s->sortby('name',@names);	# overrides internal
     @emails=$s->sort(@emails);		# internal is still 'email'

DESCRIPTION
===========

   This module provides methods to sort a list of strings based on parsing
the strings according to a configurable set of specifications.

METHODS
-------

   The following methods are available:

new
     Creates a new polysort object. Takes optional arguement of initial
     named spec set (defaults to name).

by
     Configures for the named set of sorting specs. Arguement is name of
     spec set.

sort
     Sorts by the previously-set (by new or by) specs. Arguement is a list
     of items to sort. Returns the sorted list, leaving the original
     unchanged.

sortby
     Sorts by the given (named) set of specs. The specs are only changed
     for this particular sort, so future calls to sort will use whatever
     specs were in effect before the sortby call. First arguement is name
     of spec set, second arguement is a list of items to sort. Returns the
     sorted list, leaving the original unchanged.

get
     Returns an associative array of the current sort specs. See `' in
     this node.

set
     Sets the current sort specs to the given associative array. Specs not
     appearing in the passed array retain their previous values, so this
     method can be used along with get to keep state during a subroutine
     call or to alter particular specs to get new sorting results.
     Arguement is an associative array. See `' in this node.

Specs
-----

   The following specifications are local to each Sort::PolySort object:

`GLOBTOP'
     Lump last two levels together?

`LEVELS'
     Number of levels to consider (0=all)

`R2L'
     Count fields right to left?

`NUMERIC'
     Do numerical sort?

CASE
     Do case-sensitive sort?

`DELIM1'
     Primary element delimiter (must not be null).

`DELIM2'
     Secondary element delimiter (can be null).

Parsing Scheme
--------------

   The following order is followed to determine the keys used to sort the
given array:

  1. *DELIM2* (if given)

     Remove up to leftmost (rightmost if *R2L* is true) occurance of
     *DELIM2* (will be brought back later).

  2. *DELIM1*

     Split remainder at all occurances of *DELIM1*.

  3. *GLOBTOP* (if true)

     Rejoin left (right if *R2L* is true) 2 elements (always joined
     left-to-right, regardless of *R2L*).

  4. *R2L* (if true)

     Reverse list of elements.

  5. *LEVELS*

     Store first *LEVELS* (all if =0) elements (last 2 considered as a
     single element if *GLOBTOP* is true).

  6. *DELIM2* (if true)

     Store string from left of *DELIM2* as next element.

  7. *LEVELS* (unless 0)

     Rejoin remaining elements (in original order, regardless of *R2L*) and
     store as next element.

Named Specs
-----------

   The following (case-sensitive) names are used by new, by and sortby to
represent pre-defined sets of specs:

datebr
     by European (dd/mm/yy) date

dateus
     by US-style (mm/dd/yy) date

email
     by user for each machine (all parts of FQDN)

email2
     by user for each top-level domain (last 2 atoms)

emaild
     by user for each domain-name (next-to-last atom)

ip
     by numerical (aaa.bbb.ccc.ddd) ip address

name
     by last name/first name/middle name or initials

ERRORS
======

   The following errors may occur:

*No specname given*
     by or sortby wasn't passed a specname.

*Never heard of specname "foo"*
     new, by, or sortby was passed a name that was not in the list of
     known specnames.

NOTES
=====

   The whole parsing method is pretty perverse, but honestly was the first
thing that came to mind. It works, but is not very fast or extensible.
Enough interested folks mailed me that I wanted to get this out now, but
it's dyin' for a rewrite. So this is just a beta. The main interface will
remain the same, but the parser will be rewritten and the spec variables
changed. Accessor methods will change as a result (using `%s=$s-'get; ...
;$s->set(%s) will probably still work to save state, though). And accessor
methods wll be added so that new names spec sets can be added at runtime
or known ones modified. And new named spec sets will be added. And on and
on and on...

AUTHOR
======

   Daniel Macks <dmacks@netspace.org>

COPYRIGHT
=========

   Copyright (c) 1996 by Daniel Macks. All rights reserved.  This module
is free software; you may redistribute it and/or modify it under the same
terms as Perl itself.

a perl 5 module for sorting of revision-like numbers
****************************************************

NAME
====

   Sort::Versions - a perl 5 module for sorting of revision-like numbers

SYNOPSIS
========

     use Sort::Versions;
     @l = sort versions qw( 1.2 1.2.0 1.2a.0 1.2.a 1.a 02.a );

     ...

     use Sort::Versions;
     print "lower" if versioncmp("1.2","1.2a")==-1;

     ...

     use Sort::Versions;
     %h = (1 => "d", 2 => "c", 3 => "b", 4 => "a");
     @h = sort {versioncmp $h{$a}, $h{$b}} keys %h;

DESCRIPTION
===========

   Sort::Versions allows easy sorting of mixed non-numeric and numeric
strings, like the "version numbers" that many shared library systems and
revision control packages use. This is quite useful if you are trying to
deal with shared libraries. It can also be applied to applications that
intersperse variable-width numeric fields within text. Other applications
can undoubtedly be found.

   For an explanation of the algorithm, it's simplest to look at these
examples:

     1.1   <  1.2
     1.1a  <  1.2
     1.1   <  1.1.1
     1.1   <  1.1a
     1.1.a <  1.1a
     1     <  a
     a     <  b
     1     <  2
     1     <  0002
     1.5   <  1.06

   More precisely (but less comprehensibly), the two strings are treated as
subunits delimited by periods. Each subunit can contain any number of
groups of digits or non-digits. If digit groups are being compared on both
sides, a numeric comparison is used, otherwise a ASCII ordering is used. A
group or subgroup with more units will win if all comparisons are equal.

   One important thing to note is that if a numeric comparison is made,
then leading zeros are ignored. Thus 1.5 sorts before `1.06', since two
separate comparisons are being made: `1 == 1', and `5 < 6'. This is not
the same as `if(1.5 < 1.06) {...}'.

USAGE
=====

   Sort::Versions exports `versions' and `versioncmp'. The former is a
function suitable for handing directly to sort. The second function,
`versioncmp', takes two arguments and returns a cmp style comparison value.
This is handy in indirect comparisons, as shown above.

AUTHOR
======

   Kenneth J. Albanowski		kjahds@kjahds.com

   Copyright (c) 1996, Kenneth J. Albanowski. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

wrapper class for the Spectrum Command Line Interface
*****************************************************

NAME
====

   Spectrum::CLI - wrapper class for the Spectrum Command Line Interface

SYNOPSIS
========

     use Spectrum::CLI;

     see METHODS section below

DESCRIPTION
===========

   `Spectrum::CLI' is class which intends to provide a convenient way to
invoke the various CLI commands of Spectrum Enterprise Manager from within
perl scripts.

   In the author's estimation, the two primary benefits of `Spectrum::CLI'
are:

   * the parsing of "show" command results

     `Spectrum::CLI' intelligently parses of the output of CLI "show"
     commands.  That is, it will split apart the columnar values for you,
     and return them as an array of hashes, each element representing one
     line of output.

   * the elimination of "SpecHex" numbers in scripts

     Because of the aforementioned results parsing, it is now easy to
     mention spectrum data objects by name rather than by their hexadecimal
     Handle or Id.  For instance, the following one=liner will create a
     hash of models by model name:

          map { $Model{$_->{MName}} = $_ } Spectrum::CLI->new->show_models;

     This would subsequently enable one to refer to a model's handle like
     this:

          my $handle = $Model{Universe}{MHandle};

     In this way, scripts can be written which discover all SpecHex magic
     numbers, and are, therefore, more readable and potentially more
     portable/reusable amongst Spectrum installations.

METHODS
=======

new - create a new Spectrum::CLI object
          $obj = Spectrum::CLI->new([VNM_Name,]
                                    [SPECROOT,]
                                    [ {
                                       [verbose => 1,]
                                       [Verbose => 1,]
                                       [CLISESSID => $sessid,]
                                       [CLIMNAMEWIDTH => $width,]
                                       [VNMSHRCPATH => $path,]
                                       [localhostname => $localname,]
                                       [timeout => $seconds,]
                                    } ]);

          my $cli = new Spectrum::CLI;

     This is the class' constructor - it returns a `Spectrum::CLI' object
     upon success or undef on failure.  Its arguments are optional, and may
     occur in any order.  In general, it can be called with no arguments
     unless the SPECROOT environment variable is not set, or one wishes to
     connect to a SpectroSERVER on another host (i.e. the script is not
     running on the VNM host).

     The optional constructor arguments are:

    *VNM name*
          You may pass a string specifying the name of the VNM machine
          where the SpectroSERVER to which you'd like to connect resides.
          (This is passed to the as the first argument to the "connect"
          command.)

    *SPECROOT value*
          You may pass a string specifying the absolute path to the "vnmsh"
          directory.  It should point to a directory which contains the
          "vnmsh" sub-directory.  (It is not necessary to pass this
          argument if either the SPECROOT or SPEC_ROOT environment
          variables are set.)

    *options hashref*
          A hash reference may also be passed as an argument.  The hash
          can be used to specify a number of options.  These include:

         verbose
               Passing { verbose => 1 } will cause the package to report
               errors from the CLI commands to STDERR.  This feature can
               also be enabled by calling the "verbose" object method with
               a non-zero argument after the constructor returns
               successfully with that object.

         Verbose
               Primarily for use while debugging, passing { Verbose => 1 }
               will cause the package to report what it is doing, such as
               which CLI command it is about to execute.  This feature can
               also be enabled by calling the "Verbose" object method with
               a non-zero argument after the constructor returns
               successfully with that object.

         CLISESSID
               Passing { CLISESSID => value } will cause `Spectrum::CLI'
               to use that value as the session id.  Normally, in the
               absence of this option, the perl script's process id is
               used.  Use of this option is discouraged unless the default
               value is somehow problematic.

         CLIMNAMEWIDTH
               Passing { CLIMNAMEWIDTH => value } will cause
               `Spectrum::CLI' to use that value as the model name width
               for CLI "show" commands. Normally, in the absence of this
               option, the value 1024 is used.  Use of this option is
               discouraged unless the default value is somehow problematic.

         VNMSHRCPATH
               Passing { VNMSHRCPATH => value } will cause `Spectrum::CLI'
               to use that value as the full path to the configuration
               file for the CLI.  Normally, in the absence of this option,
               the value "$SPECROOT/vnmsh/.vnmshrc" is used.  Use of this
               option is discouraged unless the default value is somehow
               problematic.

         localhostname
               Passing { localhostname => value } will cause
               `Spectrum::CLI' to use that value as the IP address or
               resolvable hostname to determine whether or not the local
               VnmShd is running.  (If VnmShd is not running, the
               constructor will attempt to launch it.)  Normally, in the
               absence of this option, the return value from
               Sys::Hostname::hostname is used.  Use of this option is
               discouraged unless the default value is somehow
               problematic.  (That should probably never happen as
               currently VnmShd seems to bind(2) and listen(2) at the
               address associated with the system's hostname.)

         timeout
               Passing { timeout => value } will cause `Spectrum::CLI' to
               use that value as the number of seconds to sleep before
               attempting to connect to the VnmShd that it just launched.
               If the VnmShd is already running (when the constructor is
               called) this timeout is not used.  Perhaps in the future
               this timeout will be use for other things as well.
               Normally, in the absence of this option, the value of 5
               seconds will be used.  Use of this option is discouraged
               unless the default value is somehow problematic.

          # show_types:
          map { $Type{$_->{Name}} = $_ } $cli->show_types;

          # show_attributes:
          map {
             $UserAttr{$_->{Name}} = $_
          } $cli->show_attributes("mth=$Type{User}{Handle}");

          # ...

     These methods invoke the CLI "show" command.  They return an array of
     hashes where the hash keys are the column headings from the first line
     of output of the corresponding CLI command, and the values are the
     corresponding value in that column for the given row.

seek
          @results = $obj->seek("attr=attribute_id,val=value",
          			 [lh=landscape_handle]);

     This method invokes the CLI "seek" command.  It returns values in a
     like the "show" methods.

*destroy_**, etc.
          # create_model:
          $cli->create_model("mth=$Type{User}{Handle}",
                   "attr=$UserAttr{Model_Name}{Id},val=joe",
                   "attr=$UserAttr{User_Full_Name}{Id},val='Joe User'");

     ALL of the other CLI commands are available as methods.  The return
     value(s) of these methods differs markedly from that of the
     aforementioned show_* or seek methods.  This is because these methods
     do not normally produce columnar output, but instead produce messages
     which sometimes include some useful piece of information.  For
     instance, "create model" produces a message upon success, which
     indicates the model handle of the create model.  The caller will
     nearly always want to obtain that handle, which can be done by
     parsing the returned values.  (See the results method for a hint at
     how to do this.)

     In an array context these methods return an array in which the first
     element is the exit status (i.e. zero indication success) of the
     underlying CLI command.  The subsequent elements of the returned array
     are the standard output and standard error (if any) lines produced by
     the underlying CLI command.

     In a scalar context these methods return non-zero if the command
     succeeds, zero otherwise.

     Regardless of the context in which they are invoked, these methods
     cause the objects internal status and results to be set.  If it is
     more convenient, these values can be retrieved using the status and
     results methods rather than having to collect them as return values.

dir
          print $obj->dir;

     this method returns the absolute path to the directory containing the
     vnmsh commands.

verbose
          $obj->verbose(1);
          print $obj->verbose;

     This method returns a boolean value indicating whether or not verbose
     behavior is currently turned on.

     If a zero or non-zero argument is passed it will either clear or set
     this feature, respectively.

Verbose
          $obj->Verbose(1);
          print $obj->Verbose;

     This method returns a boolean value indicating whether or not "very
     verbose" behavior is currently turned on.

     If a zero or non-zero argument is passed it will either clear or set
     this feature, respectively.

results
          @results = $obj->results;

     This method returns an array containing the results (standard output
     and standard error) of the last vnmsh command that was executed.

     The results method is *extremely* useful to determine things such as
     the model handle of the model that was created by a call to
     *create_model*.  For instance:

          if ($obj->create_model("mth=$T{User}{Handle}",
                       "attr=$A{Model_Name}{Id},val=joe",
                       "attr=$A{User_Full_Name}{Id},val='Joe User'")) {
             printf "created model: %s\n", model_handle($obj->results)
          }

          sub model_handle {
             my $mh;
             grep { m/(0x[0-9A-Fa-f]+)$/ && ($mh = $&)} @_;
             return $mh
          }

status
          if (0 != ($status = $obj->status)) {
             printf("the previous vnmsh command failed: %d\n", $status)
          }

     This method returns the exit status of the last vnmsh command that was
     executed.

IMPLEMENTATION
==============

   Spectrum::CLI is a perl AutoLoader.  As such, there is no explicit
definition of each method that corresponds to a CLI command.  Instead,
this module "discovers" which commands are available in the vnmsh
directory, and invokes them based on the called method name as determined
at run time.

   Theoretically, this has at least two advantages:

   * If new CLI commands or options are ever introduced, they will
     magically appear as part of this API and perhaps even behave as
     expected.  This is especially likely if the output and return values
     are like those of the current commands.

   * This module is relatively terse.  It would have been much more work to
     create and maintain if a seperate method needed to be written for each
     and command and argument combination.

AUTHOR
======

   Dave Plonka <plonka@doit.wisc.edu>

   Copyright (C) 1999-2000  Dave Plonka.  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.

SEE ALSO
========

   perl(1).

Simple waveform abstraction for use with Audio::TTS
***************************************************

NAME
====

   Audio::FileWave - Simple waveform abstraction for use with Audio::TTS

SYNOPSIS
========

     $wave = new Audio::FileWave $type, $data;

     set_play_command Audio::FileWave $type $command;

     play $wave;

     free $wave;

DESCRIPTION
===========

   This is a simple class which represents a waveform. It is designed for
use by the `Festival::TTS|Festival::TTS' in this node module, if you want
to play waveforms some other way you need to supply another class which
implements this interface.

   This class maintains a table mapping file types to play commands. When
the command is called the string `*WAVE*' is replaced by the filename of
the data. If you don't set up a command for the waveform type
`Festival::TTS|Festival::TTS' in this node requests, the default command
`*na_play WAVE*' is used. The `na_play|na_play' in this node command is
part of the *Edinburgh Speech Tools* and so if you have festival you
should also have it.

set_play_command Festival::FileWave $type $command;
     Sets the play command to be used for files of the given type.

$wave = new Festival::FileWave $type, $data;
     Create a waveform from the given data which is of type $type. Actually
     saves it to a file.

free $wave;
     Free the resources used for the waveform. (unlinks the file).

play $wave;
     Play the waveform. Calls the command associated with the file type.

AUTHOR
======

   Richard Caley, R.Caley@ed.ac.uk

SEE ALSO
========

   `Festival::TTS' in this node, perl(1), festival(1), Festival
Documentation

Communicate with a festival server process.
*******************************************

NAME
====

   Speech::Festival - Communicate with a festival server process.

SYNOPSIS
========

     use Festival;
     $festival = new Festival -host => 'serverhost', -port => 1314;

     conn $festival;
     disconnect $festival;

     request $festival '(some scheme)';
     request $festival '(some scheme)', \&result_handler, $args, $for, $handler;

     if (result_waiting $festival) { # process it }
     wait_for_result $festival, $timeout;
     ($type, $data) = get_result $festival;

DESCRIPTION
===========

   This package provides a simple interface to an instance of the festival
speech synthesis system running as a server on some machine. If you want a
simple speech-ouput module using this interface see `Speech::Synthesis' in
this node.

   Since festival can return an unpredictable number of results from a
single request, and since it is useful to process them as they arrive,
something a little more complex than a simple remote-procedure-call
interface is needed.

   There are basicly three ways to organise your application's interaction
with festival. In the simplest cases you can pass a result handling
procedure along with your request. For more control you can process one
value at a time by using `result_waiting|' in this node to poll for
results or `wait for result|' in this node to block until a result is
available.

   In any case results consist of a type and some data. The types are

$Speech::Festival::SCHEME
     The data is a Scheme expression, for instance a number or a list.

$Speech::Festival::WAVE
     The data is a waveform. what format this is in willbe determined by
     what you have previously told festival.

$Speech::Festival::OK
     All the results for this request have been sent. No data.

$Speech::Festival::ERROR
     Festival has reported an error. No data. Unfortunatly festival doesn't
     sen any information about the error, so for details you will have to
     check the server's log.

   A single festival session (between calls to `conn|' in this node and
`disconnect|' in this node) talks to a single Scheme interpreter in
festival, and hence state will be remembered between requests.

$festival = new Festival 'serverhost', 1314;
     Create a new festival session which will connect to the given host and
     port. If ommitted these default to *localhost* and *1314*.

conn $festival;
     Connect to festival. Returns true if all is well, false otherwise. In
     the event of an error the variable *$speech_error* conatains a
     description of it.

disconnect $festival;
     Disconnect from festival. The connection mat be reopened later with
     `conn|' in this node, but any state will have been lost.

request $festival '(some scheme)';
     Send the given Scheme to festival. You should use `result_waiting|'
     in this node, `wait_for_result|' in this node and `get_result|' in
     this node to process the results of the request.

request $festival '(some scheme)', \&result_handler, $args, $for, $handler;
     Send the given Scheme to festival asking it to call *&result_handler*
     on each result returned. The handler is called as:

     result_handler($type, $data, $args, $for, $handler)

if (*result_waiting* $festival) { # process it }
     Look to see if there are any results waiting to be processed. This
     only guarantees that the start of the result has arrived, so a
     subsequent call to `get_result|' in this node may not return
     instantly, but should not block for an extended time.

wait_for_result $festival, $timeout;
     Blocks until festival sends a result. Timeout is in seconds, if can be
     omitted, in which case the call waits for an unbounded time. Returns
     false if he call timed out, true if there is a request waiting. Again,
     this only guarantees that a result has started to arrive.

($type, $data) = get_result $festival;
     Reads a single result.

EXAMPLES
========

   The code below does some arithmatic the hard way.

     use Speech::Festival;
     $festival = new Speech::Festival -host => 'festival-server.mynet';

     conn $festival
     	 || die "can't talk to festival - $speech_error";

     request $festival '(+ 123 456)',
     	    sub {
     		my ($type, $data) = @_;

     print "Scheme Result=$data"
     	if $type eq $Speech::Festival::SCHEME;
     print "ERROR!\n"
             if $type eq $Speech::Festival::ERROR;
     	    };

AUTHOR
======

   Richard Caley, R.Caley@ed.ac.uk

SEE ALSO
========

   `Speech::Synthesis' in this node, `Speech::Festival::Synthesis' in this
node, perl(1), festival(1), Festival Documentation

Simple text-to-speech using festival.
*************************************

NAME
====

   Speech::Festival::Synthesiser - Simple text-to-speech using festival.

SYNOPSIS
========

     use Speech::Speech::Festival::Synthesiser;
     $festival = new Speech::Festival::Synthesiser 'serverhost', 1314;

     start $festival;
     stop $festival;

     @voices = voice_list $festival;
     voice $festival "myvoice";
     voice_description $festival;

     synth_description $festival;
     speak $festival $text;

DESCRIPTION
===========

   `Speech::Festival::Synthesiser' in this node provides a simple way to
add speech to a perl application. It is a sub-class of `Speech::Festival'
in this node and so you can use any of the methods in that class to
manipulate festival if necessary.

   This package conform to the interface defined by `Speech::Synthesiser'
in this node and so provides a synthesiser for use throughthat interface.

   Actual sound output is provided by an auiliary class, by default
`Audio::FileWave' in this node which runs an external program to play
sound, but you can replace it with another class if you have a better way
of playing sounds (eg a perl extension providing sound output), see the
documentation for `Audio::FileWave' in this node for the interface an
alternative should provide should implement.

   If you do use `Audio::FileWave' in this node you may need to set up the
command it uses to play sounds, see the documentation for
`Audio::FileWave' in this node.

$festival = new Speech::Festival::Synthesiser -host => 'serverhost', -port => 1314, ...
     Create a new festival session which will connect to the given host and
     port. If ommitted these default to *localhost* and *1314*.

start $festival;
     Connect to festival and inistilise the session. Returns true if all is
     well, false otherwise. In the event of an error the variable
     *$festival_error* conatains a description of it.

stop $festival;
     Disconnect from festival. The connection may be reopened later with
     `' in this node, but any state will have been lost.

@voices = *voice_list* $festival;
     Return a list of the voices available from this server.

voice $festival "myvoice";
     Select a voice.

voice_description $festival;
     Returns the description of the current voice.

synth_description $festival;
     Synthesize the standard festival introductory text.

speak $festival $text;
     Speak the given text.

AUTHOR
======

   Richard Caley, R.Caley@ed.ac.uk

SEE ALSO
========

   `Speech::Synthesiser' in this node, `Speech::Festival' in this node,
`Audio::FileWave' in this node, perl(1), festival(1), Festival
Documentation

Generic speech syntheiser interface
***********************************

NAME
====

   Speech::Synthesiser - Generic speech syntheiser interface

SYNOPSIS
========

     use Speech::Synthesiser;
     $synth = new Speech::Synthesiser
     		-type => 'SynthName',
                   # other args
     		;

     start $synth;
     stop $synth;

     @voices = voice_list $synth;
     voice $synth "myvoice";

     intro $synth;
     speak $synth $text;

DESCRIPTION
===========

   `Speech::Synthesiser' in this node provides a simple way to add speech
to a perl application. It is a generic class which can be used to talk to
any speech synthesiser given a suitable interface module.

   Actual sound output is provided by an auiliary class, by default
`Audio::FileWave' in this node which runs an external program to play
sound, but you can replace it with another class if you have a better way
of playing sounds (eg a perl extension providing sound output), see the
documentation for `Speech::FileWave' in this node for the interface an
alternative should provide should implement.

   If you do use `Speech::FileWave' in this node you may need to set up
the command it uses to play sounds, see the documentation for
`Audio::FileWave' in this node.

$synth = new Speech::Synthesiser -type => 'SynthName', ARGS;
     Create a synthesiser of the named type. Looks for a package
     `Speech::SynthName::Synthesiser'. All arguments are passed to the
     creation function for that class.

     The following arguments have special meaning to the
     `Speech::Synthesiser' new method.

    -waveimp CLASS
          CLASS is the name of a perl package which implements wave
          playing. If not given it defaults to `Audio::FileWave'.

    -waveargs [ @ARGS ]
          @ARGS are passed to the new method of the wave class. For
          `Audio::FileWave' this defaults to `( "riff" )'.

start $synth;
     Do whatever is ncecessary to prepar ethe synthesiser fo work. Returns
     true if all is well, false otherwise. In the event of an error the
     variable *$synth_error* conatains a description of it.

stop $synth;
     Close down the synthesiser, releasing any resources it holds. The
     synthesiser may be restarted with `' in this node, but any state may
     have been lost.

@voices = *voice_list* $synth;
     Return a list of the voices available from this synthesiser.

voice $synth "myvoice";
     Select a voice.

voice_description $synth;
     Returns a description of the voice.

synth_description $synth;
     Synthesize a description of the synthesiser,

speak $synth $text;
     Speak the given text. Not much more to be said really:-).

EXAMPLE
=======

   The following should talk to you, all else being equal. Uses the
festival synthesiser, so you will need to run a festival server on the
named machine.

     use Speech::Synthesiser;

     $synth = new Speech::Synthesiser
     		-type => 'Festival',
     		-host => 'festival-server.mynet';

     start $synth
     	 || die "can't talk to festival - $synth_error";

     speak $synth "We are perl, prepare for assimilation.";

AUTHOR
======

   Richard Caley, R.Caley@ed.ac.uk

SEE ALSO
========

   `Speech::Festival' in this node, `Speech::Festival::Synthesiser' in
this node, `Audio::FileWave' in this node, perl(1), festival(1), Festival
Documentation

Perl extension for the Spread group communication system
********************************************************

NAME
====

   Spread - Perl extension for the Spread group communication system

SYNOPSIS
========

     use Spread;

     # Connect
     my($mailbox, $private_group) = Sread::connect(
     	spread_name => '4444@host.domain.com',
     	private_name => 'mrcool',
     	);

     # Join and leave groups
     my(@group_to_join) = ( 'GroupA', 'GroupB', 'GroupC' );
     my(@joined_groups) = grep( Spread::join($mbox, $_), @group_to_join );
     print "Spread::join -- $sperrorno"
     	unless (Spread::leave($mbox, 'GroupC'));

     # Multicast to group(s)
     Spread::multicast($mbox, AGREED_MESS, 'GroupB', 0, "Hey you!");
     Spread::multicast($mbox, SAFE_MESS, @joined_groups, 0, "Hey yall!");

     # Poll mailbox
     my($messsize) = Spread::poll($mbox);
     if(defined($messsize)) { print "Next message: $messsize bytes\n"; }
     else { print "Spread::poll $sperrno\n"; }

     # Receive messages (see spread's man pages for more description)
     my($sevice_type, $sender, $groups, $mess_type, $endian, $message) =
     	Spread::receive($mbox);
     my($sevice_type, $sender, $groups, $mess_type, $endian, $message) =
     	Spread::receive($mbox, 1.789);  # 1.789 second timeout on receive

     # Disconnect
     if(Spread::disconnect($mbox)) { print "Successful disconnect\n"; }
     else { print "Spread::disconnect -- $sperrorno\n"; }

DESCRIPTION
===========

   Understanding through practice ;)

   See man pages for SP_connect, SP_join, SP_multicast, SP_receive,
SP_poll, SP_error, SP_leave, SP_disconnect.

   $sperror holds either the integer spread error or a descriptive string
depending on the context in which $sperror is used.

Exported constants
==================

   The predefined groups of exports in the use statements are as follows:

   use Spread qw(:SP);

   Exports the Spread::connect, Spread::join, Spread::multicast,
Spread::receive, Spread::poll, Spread::error, Spread::leave, and
Spread::disconnect as SP_connect, SP_join, SP_multicast, SP_receive,
SP_poll, SP_error, SP_leave, and SP_disconnect, respectively.

   use Spread qw(:ERROR);

   Exports all of the error conditions.  Please refer to the SP_* C man
pages as the "RETURN VALUES" there have both identical spellings and
meanings.

   use Spread qw(:MESS);

   Exports all of the message types (this is returned as service type by
the Spread::receive function and is the request service type of the
Spread::multicast function).  The actual meaning of these orderings and
assurances are not simple to explain without a basic understanding of
group communication systems.  For more information on this topic, please
visit the Spread web site at http://www.spread.org/

   All constants in alphabetical order:

     ACCEPT_SESSION
     AGREED_MESS
     BUFFER_TOO_SHORT
     CAUSAL_MESS
     CAUSED_BY_DISCONNECT
     CAUSED_BY_JOIN
     CAUSED_BY_LEAVE
     CAUSED_BY_NETWORK
     CONNECTION_CLOSED
     COULD_NOT_CONNECT
     FIFO_MESS
     HIGH_PRIORITY
     ILLEGAL_GROUP
     ILLEGAL_MESSAGE
     ILLEGAL_SERVICE
     ILLEGAL_SESSION
     ILLEGAL_SPREAD
     LOW_PRIORITY
     MAX_SCATTER_ELEMENTS
     MEDIUM_PRIORITY
     MEMBERSHIP_MESS
     REGULAR_MESS
     REG_MEMB_MESS
     REJECT_ILLEGAL_NAME
     REJECT_NOT_UNIQUE
     REJECT_NO_NAME
     REJECT_QUOTA
     REJECT_VERSION
     RELIABLE_MESS
     SAFE_MESS
     SELF_DISCARD
     TRANSITION_MESS
     UNRELIABLE_MESS

AUTHOR
======

   Theo Schlossnagle <jesus@cnds.jhu.edu>

SEE ALSO
========

   Various spread documentation at http://www.spread.org/.

Abstract base class for Excel workbooks and worksheets.
*******************************************************

NAME
====

   BIFFwriter - Abstract base class for Excel workbooks and worksheets.

SYNOPSIS
========

   See the documentation for Spreadsheet::WriteExcel

DESCRIPTION
===========

   This module is used in conjuction with Spreadsheet::WriteExcel.

AUTHOR
======

   John McNamara jmcnamara@cpan.org

COPYRIGHT
=========

   Copyright (c) 2000, John McNamara. All Rights Reserved. This module is
free software. It may be used, redistributed and/or modified under the
same terms as Perl itself.

Class for defining Excel formatting.
************************************

NAME
====

   Format - Class for defining Excel formatting.

SYNOPSIS
========

   See the documentation for Spreadsheet::WriteExcel

DESCRIPTION
===========

   This module is used in conjuction with Spreadsheet::WriteExcel.

AUTHOR
======

   John McNamara jmcnamara@cpan.org

COPYRIGHT
=========

   Copyright (c) 2000, John McNamara. All Rights Reserved. This module is
free software. It may be used, redistributed and/or modified under the
same terms as Perl itself.

Writes BIFF data into a OLE compound storage file.
**************************************************

NAME
====

   OLEwriter - Writes BIFF data into a OLE compound storage file.

SYNOPSIS
========

   See the documentation for Spreadsheet::WriteExcel

DESCRIPTION
===========

   This module is used in conjuction with Spreadsheet::WriteExcel.

AUTHOR
======

   John McNamara jmcnamara@cpan.org

COPYRIGHT
=========

   Copyright (c) 2000, John McNamara. All Rights Reserved. This module is
free software. It may be used, redistributed and/or modified under the
same terms as Perl itself.

Get information from Excel file
*******************************

NAME
====

   Spreadsheet::ParseExcel - Get information from Excel file

SYNOPSIS
========

     use strict;
     use Spreadsheet::ParseExcel;
     my $oExcel = new Spreadsheet::ParseExcel;

     #1.1 Normal Excel97
     my $oBook = $oExcel->Parse('Excel/Test97.xls');
     my($iR, $iC, $oWkS, $oWkC);
     print "FILE  :", $oBook->{File} , "\n";
     print "COUNT :", $oBook->{SheetCount} , "\n";
     print "AUTHOR:", $oBook->{Author} , "\n";
     for(my $iSheet=0; $iSheet < $oBook->{SheetCount} ; $iSheet++) {
         $oWkS = $oBook->{Worksheet}[$iSheet];
         print "--------- SHEET:", $oWkS->{Name}, "\n";
         for(my $iR = $oWkS->{MinRow} ;
                 defined $oWkS->{MaxRow} && $iR <= $oWkS->{MaxRow} ; $iR++) {
             for(my $iC = $oWkS->{MinCol} ;
                             defined $oWkS->{MaxCol} && $iC <= $oWkS->{MaxCol} ; $iC++) {
                 $oWkC = $oWkS->{Cells}[$iR][$iC];
                 print "( $iR , $iC ) =>", $oWkC->Value, "\n" if($oWkC);
             }
         }
     }

DESCRIPTION
===========

   Spreadsheet::ParseExcel makes you to get information from Excel95,
Excel97, Excel2000 file.

Functions
---------

new
     *$oExcel* = new Spreadsheet::ParseExcel;

     Constructor.

Parse
     *$oWorkbook* = $oParse->Parse($sFileName [, $oFmt]);

     return `Workbook' in this node object.  if error occurs, returns
     undef.

    $sFileName
          name of the file to parse

          From 0.12 (with OLE::Storage_Lite v.0.06), scalar reference of
          file contents (ex. \$sBuff) or IO::Handle object (inclucdng
          IO::File etc.) are also available.

    $oFmt
          `Formatter Class' in this node to format the value of cells.

Workbook
--------

   *Spreadsheet::ParseExcel::Workbook*

   Workbook class has these properties :

File
     Name of the file

Author
     Author of the file

Flag1904
     If this flag is on, date of the file count from 1904.

Version
     Version of the file

SheetCount
     Numbers of `Worksheet' in this node s in that Workbook

Worksheet[SheetNo]
     Array of `Worksheet' in this nodes class

Worksheet
---------

   *Spreadsheet::ParseExcel::Worksheet*

   Worksheet class has these properties:

Name
     Name of that Worksheet

DefRowHeight
     Default height of rows

DefColWidth
     Default width of columns

RowHeight[Row]
     Array of row height

ColHeight[Col]
     Array of column width (undef means DefColWidth)

Cells[Row][Col]
     Array of `Cell' in this nodes infomation in the worksheet

Cell
----

   *Spreadsheet::ParseExcel::Cell*

   Cell class has these properties:

Value
     Method Formatted value of that cell

Val
     Original Value of that cell

Type
     Kind of that cell ('Text', 'Numeric', 'Date')

Code
     Character code of that cell (undef, 'ucs2', '_native_') undef tells
     that cell seems to be ascii.  '_native_' tells that cell seems to be
     'sjis' or something like that.

Formatter class
===============

   *Spreadsheet::ParseExcel::Fmt**

   Formatter class will convert cell data.

   Spreadsheet::ParseExcel includes 2 formatter classes: FmtDefault and
FmtJapanese.  You can create your own FmtClass as you like.

   Formatter class(Spreadsheet::ParseExcel::Fmt*) should provide these
functions:

ChkType($oSelf, $iNumeric, $iFmtIdx)
     tells type of the cell that has specified value.

    $oSelf
          Formatter itself

    $iNumeric
          If on, the value seems to be number

    $iFmtIdx
          Format index number of that cell

TextFmt($oSelf, $sText, $sCode)
     converts original text into applicatable for Value.

    $oSelf
          Formatter itself

    $sText
          Original text

    $sCode
          Character code of Original text

ValFmt($oSelf, $oCell, $oBook)
     converts original value into applicatable for Value.

    $oSelf
          Formatter itself

    $oCell
          Cell object

    $oBook
          Workbook object

AUTHOR
======

   Kawai Takanori (Hippo2000) kwitknr@cpan.org

     http://member.nifty.ne.jp/hippo2000/            (Japanese)
     http://member.nifty.ne.jp/hippo2000/index_e.htm (English)

SEE ALSO
========

   XLHTML, OLE::Storage, Spreadsheet::WriteExcel, OLE::Storage_Lite

   This module is based on herbert within OLE::Storage and XLHTML.

COPYRIGHT
=========

   The Spreadsheet::ParseExcel module is Copyright (c) 2000,2001 Kawai
Takanori. Japan.  All rights reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

ACKNOWLEDGEMENTS
================

   First of all, I would like to acknowledge valuable program and modules :
XHTML, OLE::Storage and Spreadsheet::WriteExcel.

   In no particular order: Yamaji Haruna, Simamoto Takesi, Noguchi Harumi,
Ikezawa Kazuhiro, Suwazono Shugo, Hirofumi Morisada, Michael Edwards, Kim
Namusk and many many people + Kawai Mikako.

Utility function for Spreadsheet::ParseExcel
********************************************

NAME
====

   Spreadsheet::ParseExcel::Utility - Utility function for
Spreadsheet::ParseExcel

SYNOPSIS
========

     use strict;
     #Declare
     use Spreadsheet::ParseExcel::Utility qw(ExcelFmt ExcelLocaltime LocaltimeExcel);

     #Convert localtime ->Excel Time
     my $iBirth = LocaltimeExcel(11, 10, 12, 23, 2, 64);
                                # = 1964-3-23 12:10:11
     print $iBirth, "\n";       # 23459.5070717593

     #Convert Excel Time -> localtime
     my @aBirth = ExcelLocaltime($iBirth, undef);
     print join(":", @aBirth), "\n";   # 11:10:12:23:2:64:1:0

     #Formatting
     print ExcelFmt('yyyy-mm-dd', $iBirth), "\n"; #1964-3-23
     print ExcelFmt('m-d-yy', $iBirth), "\n";     # 3-23-64
     print ExcelFmt('#,##0', $iBirth), "\n";      # 23,460
     print ExcelFmt('#,##0.00', $iBirth), "\n";   # 23,459.51
     print ExcelFmt('"My Birthday is (m/d):" m/d', $iBirth), "\n";
                                       # My Birthday is (m/d): 3/23

DESCRIPTION
===========

   Spreadsheet::ParseExcel::Utility exports utility functions concerned
with Excel format setting.

Functions
=========

   This module can export 3 functions: ExcelFmt, ExcelLocaltime and
LocaltimeExcel.

ExcelFmt
--------

   $sTxt = ExcelFmt($sFmt, $iData [, $i1904]);

   *$sFmt* is a format string for Excel. *$iData* is the target value.  If
*$flg1904* is true, this functions assumes that epoch is 1904.  *$sTxt* is
the result.

   For more detail and examples, please refer sample/chkFmt.pl in this
distribution.

   ex.

   =head2 ExcelLocaltime

   ($iSec, $iMin, $iHour, $iDay, $iMon, $iYear, $iwDay, $iMSec) =
  ExcelLocaltime($iExTime [, $flg1904]);

   *ExcelLocaltime* converts time information in Excel format into Perl
localtime format.  *$iExTime* is a time of Excel. If *$flg1904* is true,
this functions assumes that epoch is 1904.  *$iSec*, *$iMin*, *$iHour*,
*$iDay*, *$iMon*, *$iYear*, *$iwDay* are same as localtime.  *$iMSec*
means 1/1,000,000 seconds(ms).

LocaltimeExcel
--------------

   *$iExTime* = LocaltimeExcel($iSec, $iMin, $iHour, $iDay, $iMon, $iYear
[,$iMSec] [,$flg1904])

   LocaltimeExcel converts time information in Perl localtime format into
Excel format .  *$iSec*, *$iMin*, *$iHour*, *$iDay*, *$iMon*, *$iYear* are
same as localtime.

   If *$flg1904* is true, this functions assumes that epoch is 1904.
*$iExTime* is a time of Excel.

AUTHOR
------

   Kawai Takanori (Hippo2000) kwitknr@cpan.org

     http://member.nifty.ne.jp/hippo2000/            (Japanese)
     http://member.nifty.ne.jp/hippo2000/index_e.htm (English)

SEE ALSO
========

   Spreadsheet::ParseExcel, Spreadsheet::WriteExcel

COPYRIGHT
=========

   This module is part of the Spreadsheet::ParseExcel distribution.

A writer class for Excel Workbooks.
***********************************

NAME
====

   Workbook - A writer class for Excel Workbooks.

SYNOPSIS
========

   See the documentation for Spreadsheet::WriteExcel

DESCRIPTION
===========

   This module is used in conjuction with Spreadsheet::WriteExcel.

AUTHOR
======

   John McNamara jmcnamara@cpan.org

COPYRIGHT
=========

   Copyright (c) 2000, John McNamara. All Rights Reserved. This module is
free software. It may be used, redistributed and/or modified under the
same terms as Perl itself.

A writer class for Excel Worksheets.
************************************

NAME
====

   Worksheet - A writer class for Excel Worksheets.

SYNOPSIS
========

   See the documentation for Spreadsheet::WriteExcel

DESCRIPTION
===========

   This module is used in conjuction with Spreadsheet::WriteExcel.

AUTHOR
======

   John McNamara jmcnamara@cpan.org

COPYRIGHT
=========

   Copyright (c) 2000, John McNamara. All Rights Reserved. This module is
free software. It may be used, redistributed and/or modified under the
same terms as Perl itself.

Write to a cross-platform Excel binary file.
********************************************

NAME
====

   Spreadsheet::WriteExcel - Write to a cross-platform Excel binary file.

VERSION
=======

   This document refers to version 0.30 of Spreadsheet::WriteExcel,
released February 26, 2001.

SYNOPSIS
========

   To write a string, a formatted string, a number and a formula to the
first worksheet in an Excel workbook called perl.xls:

     use Spreadsheet::WriteExcel;

     # Create a new Excel workbook
     my $workbook = Spreadsheet::WriteExcel->new("perl.xls");
     $worksheet   = $workbook->addworksheet(); # Add a worksheet
     $format      = $workbook->addformat();    # Add a format

     # Define the format
     $format->set_bold();
     $format->set_color('red');
     $format->set_align('center');

     # Row and column are zero indexed
     $col = 0;
     $row = 0;

     $worksheet->write($row,  $col, "Hi Excel!");
     $worksheet->write(1,     $col, "Hi Excel!", $format);
     $worksheet->write(2,     $col, 1.2345);
     $worksheet->write(3,     $col, '=SIN(PI()/4)');

DESCRIPTION
===========

   The Spreadsheet::WriteExcel module can be used create a cross-platform
Excel binary file. Multiple worksheets can be added to a workbook and
formatting can be applied to cells. Text, numbers, formulas and hyperlinks
can be written to the cells.

   The Excel file produced by this module is compatible with Excel 5, 95,
97 and 2000.

   The module will work on the majority of Windows, UNIX and Macintosh
platforms. Generated files are also compatible with the Linux/UNIX
spreadsheet applications OpenOffice, Gnumeric and XESS. The generated
files are not compatible with MS Access.

WORKBOOK METHODS
================

   The Spreadsheet::WriteExcel module provides an object oriented
interface to a new Excel workbook. The following methods are available
through a new workbook.

   If you are unfamiliar with object oriented interfaces or the way that
they are implemented in Perl have a look at `perlobj' and `perltoot' in
the main Perl documentation.

new()
-----

   A new Excel workbook is created using the new() constructor as follows:

     my $workbook = Spreadsheet::WriteExcel->new("filename.xls");

   Although my is not specifically required it defines the scope of the
new workbook variable and, in the majority of cases, ensures that the
workbook is closed properly without explicitly calling the close() method.

   You can redirect the output to STDOUT using the special Perl filehandle
`"-"'. This can be useful for CGIs which have a Content-type of
`application/vnd.ms-excel', for example:

     #!/usr/bin/perl -w

     use strict;
     use Spreadsheet::WriteExcel;

     # Set the filename and send the content type and disposition
     my $filename ="cgitest.xls";

     print "Content-type: application/vnd.ms-excel\n";
     print "Content-Disposition: attachment; filename=$filename\n";
     print "\n";

     my $workbook  = Spreadsheet::WriteExcel->new("-");
     my $worksheet = $workbook->addworksheet();

     $workbook->write(0, 0, "Hi Excel!");

close()
-------

   The close() method can be called to explicitly close an Excel file.

     $workbook->close();

   An explicit close() is required if the file must be closed prior to
performing some external action on it such as copying or reading its size.

   In addition, close() may be required if the scope of the Workbook,
Worksheet or Format objects cannot be determined by perl. Situations where
this can occur are:

   * If my() was not used to declare the scope of a workbook variable
     created using new().

   * If the `addworksheet()' or addformat() methods are called in
     subroutines.

   The reason for this is that Spreadsheet::WriteExcel relies on Perl's
DESTROY subroutine to trigger destructor methods in a specific sequence.
This will not happen if the scope of the variables cannot be determined.

   In general, if you create a file with a size of 0 bytes you need to
call close().

addworksheet($sheetname)
------------------------

   At least one worksheet should be added to a new workbook:

     $worksheet1 = $workbook->addworksheet();          # Sheet1
     $worksheet2 = $workbook->addworksheet('Foglio2'); # Foglio2
     $worksheet3 = $workbook->addworksheet('Data');    # Data
     $worksheet4 = $workbook->addworksheet();          # Sheet4

   If `$sheetname' is not specified the default Excel convention will be
followed, i.e. Sheet1, Sheet2, etc.

addformat()
-----------

   The addformat() method can be used to create new Format objects which
are used to apply formatting to a cell:

     $format1 = $workbook->addformat();
     $format2 = $workbook->addformat();

   See the `FORMAT METHODS' in this node section for details.

worksheets()
------------

   The worksheets() method returns a reference to the array of worksheets
in a workbook. This can be useful if you want to repeat an operation on
each worksheet in a workbook or if you wish to refer to a worksheet by its
index:

     foreach $worksheet (@{$workbook->worksheets()}) {
        $worksheet->write(0, 0, "Hello");
     }

     # or:

     $worksheets = $workbook->worksheets();
     @$worksheets[0]->write(0, 0, "Hello");

   References are explained in detail in `perlref' and `perlreftut' in the
main Perl documentation.

set_1904()
----------

   Excel stores dates as real numbers where the integer part stores the
number of days since the epoch and the fractional part stores the
percentage of the day. The epoch can be either 1900 or 1904. Excel for
Windows uses 1900 and Excel for Macintosh uses 1904. However, Excel on
either platform will convert automatically between one system and the
other.

   Spreadsheet::WriteExcel stores dates in the 1900 format by default. If
you wish to change this you can call the set_1904() workbook method. You
can query the current value by calling the `get_1904()' workbook method.
This returns 0 for 1900 and 1 for 1904.

   In general you probably won't need to use set_1904().

WORKSHEET METHODS
=================

   The following methods are available through a new worksheet. A new
worksheet is created by calling the `addworksheet()' method from a
workbook object:

     $worksheet1 = $workbook->addworksheet();
     $worksheet2 = $workbook->addworksheet();

write($row, $column, $token, $format)
-------------------------------------

   The write() method is a general alias for one of several methods of
writing to a cell in Excel. write() calls one of the following methods
depending on the value of $token:

   `write_number()' if $token is a number based on the following regex:
`$token =~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/'.

   `write_blank()' if $token is a blank string: "" or ".

   `write_url()' if $token is a URL based on the following regex: `$token
=~ m|[fh]tt?p://|'.

   `write_formula()' if the first character of $token is =.

   `write_string()' if none of the previous conditions apply.

   Here are some examples:

     $worksheet->write(0, 0, "Hello"                 );  # write_string()
     $worksheet->write(1, 0, 'One'                   );  # write_string()
     $worksheet->write(2, 0,  2                      );  # write_number()
     $worksheet->write(3, 0,  3.00001                );  # write_number()
     $worksheet->write(4, 0,  ""                     );  # write_blank()
     $worksheet->write(5, 0,  ''                     );  # write_blank()
     $worksheet->write(6, 0,  'http://www.perl.com/' );  # write_url()
     $worksheet->write(7, 0,  'ftp://ftp.cpan.org/'  );  # write_url()
     $worksheet->write(8, 0,  '=A3 + 3*A4'           );  # write_formula()
     $worksheet->write(9, 0,  '=SIN(PI()/4)'         );  # write_formula()

   The `$format' argument is optional. It should be a valid Format object,
see `FORMAT METHODS' in this node:

     my $format = $workbook->addformat();
     $format->set_bold();
     $format->set_color('red');
     $format->set_align('center');

     $worksheet->write(4, 0, "Hello", $format ); # Formatted string

   It should be noted that `$row' and `$column' are zero indexed cell
locations for the write methods. Thus, Cell A1 is (0, 0) and Cell AD2000
is (1999, 29). Cells can be written to in any order but for forward
compatibility it is probably best to write them in row-column order when
possible.

   The write methods return:

     0 for success.
        -1 for insufficient number of arguments.
        -2 for row or column out of bounds.
        -3 for string too long.

write_number($row, $column, $number, $format)
---------------------------------------------

   Write an integer or a float to the cell specified by `$row' and
`$column':

     $worksheet->write_number(0, 0,  1     );
     $worksheet->write_number(1, 0,  2.3451);

   The `$format' argument is optional.

write_string($row, $column, $string, $format)
---------------------------------------------

   Write a string to the cell specified by `$row' and `$column':

     $worksheet->write_string(0, 0, "Your text here" );

   The maximum string size is 255 characters. The `$format' argument is
optional.

write_formula($row, $column, $formula, $format)
-----------------------------------------------

   Write a formula or function to the cell specified by `$row' and
`$column':

     $worksheet->write_formula(0, 0, '=$B$3 + B4'  );
     $worksheet->write_formula(1, 0, '=SIN(PI()/4)');
     $worksheet->write_formula(2, 0, '=SUM(B1:B5)');
     $worksheet->write_formula(3, 0, '=IF(A3>1,"Yes", "No")');
     $worksheet->write_formula(4, 0, '=AVERAGE(1, 2, 3, 4)');
     $worksheet->write_formula(5, 0, '=DATEVALUE("1-Jan-2001")');

   For more information about writing Excel formulas see `FORMULAS AND
FUNCTIONS IN EXCEL' in this node

write_blank($row, $column, $format)
-----------------------------------

   Write a blank cell specified by `$row' and `$column':

     $worksheet->write_blank(0, 0, $format);

   This method is useful for adding formatting to a cell which doesn't
contain a string or number value.

write_url($row, $col, $url, $string, $format)
---------------------------------------------

   Write a hyperlink to a URL in the cell specified by `$row' and
`$column'. The hyperlink is comprised of two elements: the visible label
and the invisible link. The visible label is the same as the link unless
an alternative string is specified. The alternative $string and the
`$format' are optional.

     $worksheet->write_url(0, 0, 'http://www.perl.com/'                 );
     $worksheet->write_url(1, 0, 'http://www.perl.com/', 'Perl home'    );
     $worksheet->write_url(2, 0, 'http://www.perl.com/', undef, $format );

   The label is written using the `write_string()' method. Therefore the
255 characters string limit applies to the label: the URL can be any
length. Use undef if you wish to specify a format without specifying an
alternative string.

   Note: Hyperlinks are not available in Excel 5. They will appear as a
string only.

activate()
----------

   The activate() method is used to specify which worksheet is initially
selected in a multi-sheet workbook:

     $worksheet1 = $workbook->addworksheet('To');
     $worksheet2 = $workbook->addworksheet('the');
     $worksheet3 = $workbook->addworksheet('wind');

     $worksheet3->activate();

   This is similar to the Excel VBA activate method. The default value is
the first worksheet.

set_first_sheet()
-----------------

   The activate() method determines which worksheet is initially selected.
However, if there are a large number of worksheets the selected worksheet
may not appear on the screen. To avoid this you can select which is the
leftmost visible worksheet using set_first_sheet():

     for (1..20) {
         $workbook->addworksheet;
     }

     $worksheet21 = $workbook->addworksheet();
     $worksheet22 = $workbook->addworksheet();

     $worksheet21->set_first_sheet();
     $worksheet22->activate();

   This method is not required very often. The default value is the first
worksheet.

set_selection($first_row, $first_col, $last_row, $last_col);
------------------------------------------------------------

   This method can be used to specify which cell or cells are selected in
a worksheet. The most common requirement is to select a single cell, in
which case `$last_row' and `$last_col' are not required. The active cell
within a selected range is determined by the order in which `$first' and
`$last' are specified:

     $worksheet1->set_selection(3, 3);       # Cell D4
     $worksheet2->set_selection(3, 3, 6, 6); # Cells D4 to G7
     $worksheet3->set_selection(6, 6, 3, 3); # Cells G7 to D4

   The default is cell (0, 0).

set_row($row, $height, $format);
--------------------------------

   This method can be used to specify the height of a row. The `$format'
argument is optional, for additional information, see `FORMAT METHODS' in
this node.

     $worksheet->set_row(0, 20); # Row 1 height set to 20

   If you wish to set the format without changing the height you can pass
undef as the height parameter:

     $worksheet->set_row(0, undef, $height);

set_column($first_col, $last_col, $width, $format);
---------------------------------------------------

   This method can be used to specify the width of a single column or a
range of columns. If the method is applied to a single column the value of
`$first_col' and `$last_col' should be the same:

     $worksheet->set_column(0, 0, 20); # Column A width set to 20
     $worksheet->set_column(1, 3, 30); # Columns B-D width set to 30

   The width corresponds to the column width value that is specified in
Excel. It is approximately equal to the length of a string in the default
font of Arial 10. The `$format' argument is optional, for additional
information, see `FORMAT METHODS' in this node.

   If you wish to set the format without changing the width you can pass
undef as the width parameter:

     $worksheet->set_column(0, 0, undef, $format);

FORMAT METHODS
==============

   This section describes the methods that are available through a Format
object. Format objects are created by calling the workbook addformat()
method as follows:

     my $heading1 = $workbook->addformat();
     my $heading2 = $workbook->addformat();

   The format object holds all the formatting properties that can be
applied to a cell, a row or a column. The following table shows the Excel
format categories, the formatting properties that can be applied and the
relevant object method to do so:

     Category        Property            Method Name
     --------        --------            -----------
     Font            Font type           set_font()
                     Font size           set_size()
                     Font color          set_color()
                     Bold                set_bold()
                     Italic              set_italic()
                     Underline           set_underline()
                     Strikeout           set_font_strikeout()
                     Super/Subscript     set_font_script()
                     Outline             set_font_outline()
                     Shadow              set_font_shadow()

     Number          Numeric format      set_num_format()

     Alignment       Horizontal align    set_align()
                     Vertical align      set_align()
                     Rotation            set_rotation()
                     Text wrap           set_text_wrap()
                     Justify last        set_text_justlast()
                     Merge               set_merge()

     Pattern         Cell pattern        set_pattern()
                     Background color    set_bg_color()
                     Foreground color    set_fg_color()

     Border          Cell border         set_border()
                     Bottom border       set_bottom()
                     Top border          set_top()
                     Left border         set_left()
                     Right border        set_right()
                     Border color        set_border_color()
                     Bottom color        set_bottom_color()
                     Top color           set_top_color()
                     Left color          set_left_color()
                     Right color         set_right_color()

   The default format is Arial 10 with all other properties off. In
general a method call without an argument will turn a property on, for
example:

     my $format1 = $workbook->addformat();
     $format1->set_bold();  # Turns bold on
     $format1->set_bold(1); # Also turns bold on
     $format1->set_bold(0); # Turns bold off

   More than one property can be applied to a format:

     my $format2 = $workbook->addformat();
     $format2->set_bold();
     $format2->set_italic();
     $format2->set_color('red');

   Once a Format object has been constructed it can be passed as an
argument to the worksheet write methods as follows:

     $worksheet->write(0, 0, "One", $format);
     $worksheet->write_string(1, 0, "Two", $format);
     $worksheet->write_number(2, 0, 3, $format);
     $worksheet->write_blank(3, 0, $format);

   Formats can also be passed to the worksheet `set_row()' and
`set_column()' methods to define the default property for a row or column.

     $worksheet->set_row(0, 15, $format);
     $worksheet->set_column(0, 0, 15, $format);

   However, the `set_row()' and `set_column()' methods will not set the
format for individual cells written by WriteExcel, they only have an
effect on cells written after the workbook is opened in Excel.

   It is important to understand that a Format is applied to a cell not in
its current state but in its final state. Consider the following example:

     my $format = $workbook->addformat();
     $format->set_bold();
     $format->set_color('red');
     $worksheet->write(0, 0, "Cell A1", $format);
     $format->set_color('green');
     $worksheet->write(0, 1, "Cell B1", $format);

   Cell A1 is assigned the Format `$format' which is initially set to the
colour red. However, the colour is subsequently set to green. When Excel
displays Cell A1 it will display the final state of the Format which in
this case will be the colour green.

   The Format object methods are described in more detail in the following
sections. In addition, there is a Perl program called `formats.pl' in the
examples directory of the WriteExcel distribution. This program creates an
Excel workbook called `formats.xls' which contains examples of almost all
the format types.

copy($format)
-------------

   This is the only method of a Format object that doesn't apply directly
to a property. It is used to copy all of the properties from one Format
object to another:

     my $lorry1 = $workbook->addformat();
     $lorry1->set_bold();
     $lorry1->set_italic();
     $lorry1->set_color('red');    # lorry1 is bold, italic and red

     my $lorry2 = $workbook->addformat();
     $lorry2->copy($lorry1);
     $lorry2->set_color('yellow'); # lorry2 is bold, italic and yellow

   This can be useful when you are setting up several complex but similar
formats. It is also useful if you want to use a format in more than one
workbook:

     # Create the workbooks
     my $workbook1   = Spreadsheet::WriteExcel->new("workbook1.xls");
     my $workbook2   = Spreadsheet::WriteExcel->new("workbook2.xls");
     my $worksheet1  = $workbook->addworksheet();
     my $worksheet2  = $workbook->addworksheet();
     my $format1     = $workbook->addformat();
     my $format2     = $workbook->addformat();

     # Create a global format object that isn't tied to a workbook
     my $global      = Spreadsheet::WriteExcel::Format->new();
     $global->set_color('blue');

     # Copy the global format properties to the worksheet formats
     $format1->copy($global);
     $format2->copy($global);

   Note: this is not a copy constructor, both objects must exist prior to
copying.

set_font($fontname)
-------------------

     Default state:      Font is Arial
     Default action:     None
     Valid args:         Any valid font name

   Specify the font used:

     $format->set_font('Times New Roman');

   Excel can only display fonts that are installed on the system that it
is running on. Therefore it is best to use the fonts that come as standard
such as 'Arial', 'Times New Roman' and 'Courier New'. See also the Fonts
worksheet created by formats.pl

set_size()
----------

     Default state:      Font size is 10
     Default action:     Set font size to 1
     Valid args:         Integer values from 1 to as big as your screen.

   Set the font size. Excel adjusts the height of a row to accommodate the
largest font size in the row. You can also explicitly specify the height
of a row using the set_row() worksheet method.

     my $format = $workbook->addformat();
     $format->set_size(30);

set_color()
-----------

     Default state:      Excels default color, usually black
     Default action:     Set the default color
     Valid args:         Integers form 8..63 or the following strings:
                         'aqua'
                         'black'
                         'blue'
                         'fuchsia'
                         'gray'
                         'green'
                         'lime'
                         'navy'
                         'orange'
                         'purple'
                         'red'
                         'silver'
                         'white'
                         'yellow'

   Set the font colour. The set_color() method is used as follows:

     my $format = $workbook->addformat();
     $format->set_color('red');
     $worksheet->write(0, 0, "wheelbarrow", $format);

   Note: The set_color() method is used to set the colour of the font in a
cell. To set the colour of a cell use the set_fg_color() and set_pattern()
methods.

   For additional examples see the 'Named colors' and 'Standard colors'
worksheets created by formats.pl

set_bold()
----------

     Default state:      bold is off
     Default action:     Turn bold on
     Valid args:         0, 1 [1]

   Set the bold property of the font:

     $format->set_bold();  # Turn bold on

   [1] Actually, values in the range 100..1000 are also valid. 400 is
normal, 700 is bold and 1000 is very bold indeed. It is probably best to
set the value to 1 and use normal bold.

set_italic()
------------

     Default state:      Italic is off
     Default action:     Turn italic on
     Valid args:         0, 1

   Set the italic property of the font.

set_underline()
---------------

     Default state:      Underline is off
     Default action:     Turn on single underline
     Valid args:         0  = No underline
                         1  = Single underline
                         2  = Double underline
                         33 = Single accounting underline
                         34 = Double accounting underline

   Set the underline property of the font.

set_strikeout()
---------------

     Default state:      Strikeout is off
     Default action:     Turn strikeout on
     Valid args:         0, 1

   Set the strikeout property of the font.

set_script()
------------

     Default state:      Super/Subscript is off
     Default action:     Turn Superscript on
     Valid args:         0  = Normal
                         1  = Superscript
                         2  = Subscript

   Set the superscript/subscript property of the font. This format is
currently not very useful.

set_outline()
-------------

     Default state:      Outline is off
     Default action:     Turn outline on
     Valid args:         0, 1

   Macintosh only.

set_shadow()
------------

     Default state:      Shadow is off
     Default action:     Turn shadow on
     Valid args:         0, 1

   Macintosh only.

set_num_format()
----------------

     Default state:      General format
     Default action:     Format index 1
     Valid args:         See the following table

   This method is used to define the numerical format of a number in
Excel. It controls whether a number is displayed as an integer, a floating
point number, a date, a currency value or some other user defined format.

   The numerical format of a cell can be specified by using a format
string or an index to one of Excel's built-in formats:

     my $format1 = $workbook->addformat();
     my $format2 = $workbook->addformat();
     $format1->set_num_format('d mmm yyyy'); # Format string
     $format2->set_num_format(0x0f);         # Format index

     $worksheet->write(0, 0, 36892.521, $format1);      # 1 Jan 2001
     $worksheet->write(0, 0, 36892.521, $format2);      # 1-Jan-01

   Using format strings you can define very sophisticated formatting of
numbers.

     $format01->set_num_format('0.000');
     $worksheet->write(0,  0, 3.1415926, $format01);    # 3.142

     $format02->set_num_format('#,##0');
     $worksheet->write(1,  0, 1234.56,   $format02);    # 1,235

     $format03->set_num_format('#,##0.00');
     $worksheet->write(2,  0, 1234.56,   $format03);    # 1,234.56

     $format04->set_num_format('$0.00');
     $worksheet->write(3,  0, 49.99,     $format04);    # $49.99

     $format05->set_num_format('£0.00');
     $worksheet->write(4,  0, 49.99,     $format05);    # £49.99

     $format06->set_num_format('¥0.00');
     $worksheet->write(5,  0, 49.99,     $format06);    # ¥49.99

     $format07->set_num_format('mm/dd/yy');
     $worksheet->write(6,  0, 36892.521, $format07);    # 01/01/01

     $format08->set_num_format('mmm d yyyy');
     $worksheet->write(7,  0, 36892.521, $format08);    # Jan 1 2001

     $format09->set_num_format('d mmmm yyyy');
     $worksheet->write(8,  0, 36892.521, $format09);    # 1 January 2001

     $format10->set_num_format('dd/mm/yyyy hh:mm AM/PM');
     $worksheet->write(9,  0, 36892.521, $format10);    # 01/01/2001 12:30 AM

     $format11->set_num_format('0 "dollar and" .00 "cents"');
     $worksheet->write(10, 0, 1.87,      $format11);    # 1 dollar and .87 cents

     # Conditional formatting
     $format12->set_num_format('[Green]General;[Red]-General;General');
     $worksheet->write(11, 0, 123,       $format12);    # > 0 Green
     $worksheet->write(12, 0, -45,       $format12);    # < 0 Red
     $worksheet->write(13, 0, 0,         $format12);    # = 0 Default colour

   The colour format should have one of the following values:

     [Black] [Blue] [Cyan] [Green] [Magenta] [Red] [White] [Yellow]

   Alternatively you can specify the colour based on a colour index as
follows: `[Color n]', where n is a standard Excel colour index - 7. See
the 'Standard colors' worksheet created by formats.pl.

   For more information refer to the documentation on formatting in the
doc directory of the Spreadsheet::WriteExcel distro, the Excel on-line
help or to the tutorial at:
http://support.microsoft.com/support/Excel/Content/Formats/default.asp and
http://support.microsoft.com/support/Excel/Content/Formats/codes.asp

   You should ensure that the format string is valid in Excel prior to
using it in WriteExcel.

   One of the most common uses of the set_num_format() is to format a
number as a date. Excel stores dates as a real number where the integer
part of the number stores the number of days since the epoch and the
fractional part stores the percentage of the day. The epoch can be either
1900 or 1904. Excel for Windows uses 1900 and Excel for Macintosh uses
1904. However, Excel on either platform will convert automatically between
one system and the other. For an example of how to convert between
UNIX/Perl time and Excel time have a look at the `ms_time.pl' program in
the examples directory of the WriteExcel distribution.

   Excel's built-in formats are shown in the following table:

     Index   Index   Format String
     0       0x00    General
     1       0x01    0
     2       0x02    0.00
     3       0x03    #,##0
     4       0x04    #,##0.00
     5       0x05    ($#,##0_);($#,##0)
     6       0x06    ($#,##0_);[Red]($#,##0)
     7       0x07    ($#,##0.00_);($#,##0.00)
     8       0x08    ($#,##0.00_);[Red]($#,##0.00)
     9       0x09    0%
     10      0x0a    0.00%
     11      0x0b    0.00E+00
     12      0x0c    # ?/?
     13      0x0d    # ??/??
     14      0x0e    m/d/yy
     15      0x0f    d-mmm-yy
     16      0x10    d-mmm
     17      0x11    mmm-yy
     18      0x12    h:mm AM/PM
     19      0x13    h:mm:ss AM/PM
     20      0x14    h:mm
     21      0x15    h:mm:ss
     22      0x16    m/d/yy h:mm
     ..      ....    ...........
     37      0x25    (#,##0_);(#,##0)
     38      0x26    (#,##0_);[Red](#,##0)
     39      0x27    (#,##0.00_);(#,##0.00)
     40      0x28    (#,##0.00_);[Red](#,##0.00)
     41      0x29    _(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)
     42      0x2a    _($* #,##0_);_($* (#,##0);_($* "-"_);_(@_)
     43      0x2b    _(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)
     44      0x2c    _($* #,##0.00_);_($* (#,##0.00);_($* "-"??_);_(@_)
     45      0x2d    mm:ss
     46      0x2e    [h]:mm:ss
     47      0x2f    mm:ss.0
     48      0x30    ##0.0E+0
     49      0x31    @

   For examples of these formatting codes see the 'Numerical formats'
worksheet created by formats.pl.

   Note 1. Numeric formats 23 to 36 are not documented by Microsoft and
may differ in international versions.

   Note 2. In Excel 5 the dollar sign appears as a dollar sign. In Excel
97-2000 it appears as the defined local currency symbol.

   Note 3. The red negative numeric formats display slightly differently
in Excel 5 and Excel 97-2000.

set_align()
-----------

     Default state:      Alignment is off
     Default action:     Left alignment
     Valid args:         'left'              Horizontal
                         'center'
                         'right'
                         'fill'
                         'justify'
                         'merge'

                         'top'               Vertical
                         'vcenter'
                         'bottom'
                         'vjustify'

   This method is used to set the horizontal and vertical text alignment
within a cell. Vertical and horizontal alignments can be combined. The
method is used as follows:

     my $format = $workbook->addformat();
     $format->set_align('center');
     $format->set_align('vcenter');
     $worksheet->set_row(0, 30);
     $worksheet->write(0, 0, "X", $format);

   Text can be aligned across two or more adjacent cells using the merge
property. See also, the set_merge() method.

   The `vjustify' (vertical justify) option can be used to provide
automatic text wrapping in a cell. The height of the cell will be adjusted
to accommodate the wrapped text. To specify where the text wraps use the
set_text_wrap() method.

   For further examples see the 'Alignment' worksheet created by
formats.pl.

set_merge()
-----------

     Default state:      Cell merging is off
     Default action:     Turn cell merging on
     Valid args:         1

   Text can be aligned across two or more adjacent cells using the
set_merge() method. This is an alias for the unintuitive
`set_align('merge')' method call.

   Only one cell should contain the text, the other cells should be blank:

     my $format = $workbook->addformat();
     $format->set_merge();

     $worksheet->write(1, 1, 'Merged cells', $format);
     $worksheet->write_blank(1, 2, $format);

   See also the `merge1.pl' and `merge2.pl' programs in the examples
directory.

set_text_wrap()
---------------

     Default state:      Text wrap is off
     Default action:     Turn text wrap on
     Valid args:         0, 1

   Here is an example using the text wrap property, the escape character
\n is used to indicate the end of line:

     my $format = $workbook->addformat();
     $format->set_text_wrap();
     $worksheet->write(0, 0, "It's\na bum\nwrap", $format);

   Excel will adjust the height of the row to accommodate the wrapped
text. A similar effect can be obtained without newlines using the
`set_align('vjustify')' method. See the `textwrap.pl' program in the
examples directory.

set_rotation()
--------------

     Default state:      Text rotation is off
     Default action:     Rotation style 1
     Valid args:         0 No rotation
                         1 Letters run from top to bottom
                         2 90° anticlockwise
                         3 90° clockwise

   Set the rotation of the text in a cell. See the 'Alignment' worksheet
created by formats.pl.

set_text_justlast()
-------------------

     Default state:      Justify last is off
     Default action:     Turn justify last on
     Valid args:         0, 1

   Only applies to Far Eastern versions of Excel.

set_pattern()
-------------

     Default state:      Pattern is off
     Default action:     Solid fill is on
     Valid args:         0 .. 31

   Examples of the available patterns are shown in the 'Patterns'
worksheet created by formats.pl. However, it is unlikely that you will
ever need anything other than Pattern 1 which is a solid fill of the
foreground color.

set_fg_color()
--------------

     Also applies to:    set_bg_color

     Default state:      Color is off
     Default action:     Undefined
     Valid args:         See set_color()

   Note, the foreground and background colours will only have an effect if
the cell pattern has been set. In the most common case you can specify the
solid fill pattern and the foreground colour as follows:

     my $format = $workbook->addformat();
     $format->set_pattern();         # Set pattern to 1, i.e. solid fill
     $format->set_fg_color('green'); # Note foreground and not background
     $worksheet->write(0, 0, "Ray", $format);

set_border()
------------

     Also applies to:    set_bottom()
                         set_top()
                         set_left()
                         set_right()

     Default state:      Border is off
     Default action:     Set border type 1
     Valid args:         0 No border
                         1 Thin single border
                         2 Medium single border
                         3 Dashed border
                         4 Dotted border
                         5 Thick single border
                         6 Double line border
                         7 Hair border

   A cell border is comprised of a border on the bottom, top, left and
right. These can be set to the same value using set_border() or
individually using the relevant method calls shown above. Examples of the
available border styles are shown in the 'Borders' worksheet created by
formats.pl.

set_border_color()
------------------

     Also applies to:    set_bottom_color()
                         set_top_color()
                         set_left_color()
                         set_right_color()

     Default state:      Color is off
     Default action:     Undefined
     Valid args:         See set_color()

   Set the colour of the cell borders.

FORMULAS AND FUNCTIONS IN EXCEL
===============================

   The first thing to note is that there are still some outstanding issues
with the implementation of formulas and functions:

     * Writing a formula is much slower than writing the equivalent string.
     * Unary minus isn't supported.
     * You cannot reference cells outside of the current worksheet.
     * You cannot use arrays constants, i.e. {1;2;3}, in functions.
     * You cannot use embedded double quotes in strings.
     * Whitespace is not preserved around operators.

   However, these constraints will be removed in future versions. They are
here because of a trade-off between features and time.

   The following is a brief introduction to formulas and functions in
Excel and Spreadsheet::WriteExcel.

   A formula is a string that begins with an equal sign:

     '=A1+B1'
     '=AVERAGE(1, 2, 3)'

   The formula can contain numbers, strings, boolean values, cell
references, cell ranges and functions. Formulas should be written as they
appear in Excel, that is cells and functions must be in uppercase.

   Cells in Excel are referenced using the A1 notation system where the
column is designated by a letter and the row by a number. Columns range
from A to IV i.e. 0 to 255, rows range from 1 to 16384. This system is
different from the zero indexed row and column syntax used by the
Spreadsheet::WriteExcel write() methods where, for example, the cell `C7'
would be referred to as `(6,2)'. In the examples directory of the distro
there is program called `A1convert.pl' which contains functions to help
you convert between the two systems.

   The Excel `$' notation in cell references is also supported. This
allows you to specify whether a row or column is relative or absolute.
This only has an effect if the cell is copied. The following examples show
relative and absolute values.

     '=A1'   # Column and row are relative
     '=$A1'  # Column is absolute and row is relative
     '=A$1'  # Column is relative and row is absolute
     '=$A$1' # Column and row are absolute

   The following table lists the operators that are available in Excel
functions. The majority of the operators are the same as Perl's.
Differences are indicated.

     Arithmetic operators:
     =====================
     Operator    Meaning                     Example

        +        Addition                    1+2
        -        Subtraction                 2-1
        *        Multiplication              2*3
        /        Division                    1/4
        ^        Exponentiation              2^3     # Equivalent to **
        -        Unary minus                 -(1+2)  # Not yet supported
        %        Percent (Not modulus)       13%     # Not supported, Note [1]

     Comparison operators:
     =====================
     Operator    Meaning                     Example
         =       Equal to                    A1 =  B1    # Equivalent to ==
         <>      Not equal to                A1 <> B1    # Equivalent to !=
         >       Greater than                A1 >  B1
         <       Less than                   A1 <  B1
         >=      Greater than or equal to    A1 > =B1
         <=      Less than or equal to       A1 <= B1

     String operator:
     ================
     Operator    Meaning                     Example

         &       Concatenation               "Hello " & "World!"  # Note [2]

     Reference operators:
     ====================
     Operator    Meaning                     Example
         :       Range operator              A1:A4               # Note [3]
         ,       Union operator              SUM(1, 2+2, B3)     # Note [4]

     Note [1]: You can get a percentage with formatting and modulus with MOD().
     Note [2]: Equivalent to ("Hello " . "World!") in Perl.
     Note [3]: This range is equivalent to cells A1, A2, A3 and A4.
     Note [4]: The comma behaves like the list separator in Perl.

   The range and comma operators can have different symbols in non-English
versions of Excel. These will be supported in a later version of
Spreadsheet::WriteExcel.

   The following table lists all of the core functions supported by Excel
5 and Spreadsheet::WriteExcel. Any additional functions that are available
through the "Analysis ToolPak" or other add-ins are not supported.

     ABS           DB            INDIRECT      NORMINV       SLN
     ACOS          DCOUNT        INFO          NORMSDIST     SLOPE
     ACOSH         DCOUNTA       INT           NORMSINV      SMALL
     ADDRESS       DDB           INTERCEPT     NOT           SQRT
     AND           DEGREES       IPMT          NOW           STANDARDIZE
     AREAS         DEVSQ         IRR           NPER          STDEV
     ASIN          DGET          ISBLANK       NPV           STDEVP
     ASINH         DMAX          ISERR         ODD           STEYX
     ATAN          DMIN          ISERROR       OFFSET        SUBSTITUTE
     ATAN2         DOLLAR        ISLOGICAL     OR            SUBTOTAL
     ATANH         DPRODUCT      ISNA          PEARSON       SUM
     AVEDEV        DSTDEV        ISNONTEXT     PERCENTILE    SUMIF
     AVERAGE       DSTDEVP       ISNUMBER      PERCENTRANK   SUMPRODUCT
     BETADIST      DSUM          ISREF         PERMUT        SUMSQ
     BETAINV       DVAR          ISTEXT        PI            SUMX2MY2
     BINOMDIST     DVARP         KURT          PMT           SUMX2PY2
     CALL          ERROR.TYPE    LARGE         POISSON       SUMXMY2
     CEILING       EVEN          LEFT          POWER         SYD
     CELL          EXACT         LEN           PPMT          T
     CHAR          EXP           LINEST        PROB          TAN
     CHIDIST       EXPONDIST     LN            PRODUCT       TANH
     CHIINV        FACT          LOG           PROPER        TDIST
     CHITEST       FALSE         LOG10         PV            TEXT
     CHOOSE        FDIST         LOGEST        QUARTILE      TIME
     CLEAN         FIND          LOGINV        RADIANS       TIMEVALUE
     CODE          FINV          LOGNORMDIST   RAND          TINV
     COLUMN        FISHER        LOOKUP        RANK          TODAY
     COLUMNS       FISHERINV     LOWER         RATE          TRANSPOSE
     COMBIN        FIXED         MATCH         REGISTER.ID   TREND
     CONCATENATE   FLOOR         MAX           REPLACE       TRIM
     CONFIDENCE    FORECAST      MDETERM       REPT          TRIMMEAN
     CORREL        FREQUENCY     MEDIAN        RIGHT         TRUE
     COS           FTEST         MID           ROMAN         TRUNC
     COSH          FV            MIN           ROUND         TTEST
     COUNT         GAMMADIST     MINUTE        ROUNDDOWN     TYPE
     COUNTA        GAMMAINV      MINVERSE      ROUNDUP       UPPER
     COUNTBLANK    GAMMALN       MIRR          ROW           VALUE
     COUNTIF       GEOMEAN       MMULT         ROWS          VAR
     COVAR         GROWTH        MOD           RSQ           VARP
     CRITBINOM     HARMEAN       MODE          SEARCH        VDB
     DATE          HLOOKUP       MONTH         SECOND        VLOOKUP
     DATEVALUE     HOUR          N             SIGN          WEEKDAY
     DAVERAGE      HYPGEOMDIST   NA            SIN           WEIBULL
     DAY           IF            NEGBINOMDIST  SINH          YEAR
     DAYS360       INDEX         NORMDIST      SKEW          ZTEST

   Function names in other European languages will be supported in a later
version of Spreadsheet::WriteExcel. For a general introduction to Excel's
formulas and an explanation of the functions have a look at the Excel help
files or the following links:
http://msdn.microsoft.com/library/default.asp?URL=/library/officedev/office97/s88f2.htm
and
http://msdn.microsoft.com/library/default.asp?URL=/library/officedev/office97/s992f.htm

   If your formula doesn't work in Spreadsheet::WriteExcel try the
following:

     1. Verify that the formula works in Excel (or Gnumeric or OpenOffice).
     2. Ensure that it isn't on the TODO list at the start of this section.
     3. Ensure that cell references and cell names are in uppercase.
     4. Ensure that you are using the U.S. style range and union operators.
     5. Ensure the function is in the above table.

   If you go through steps 1-5 and you still have a problem, mail me.

EXAMPLES
========

   There are additional examples in the examples directory of the
Spreadsheet::WriteExcel distro.

Example 1
---------

   The following example shows some of the basic features of
Spreadsheet::WriteExcel.

     #!/usr/bin/perl -w

     use strict;
     use Spreadsheet::WriteExcel;

     # Create a new workbook called simple.xls and add a worksheet
     my $workbook  = Spreadsheet::WriteExcel->new("simple.xls");
     my $worksheet = $workbook->addworksheet();

     # The general syntax is write($row, $column, $token). Note that row and
     # column are zero indexed

     # Write some text
     $worksheet->write(0, 0,  "Hi Excel!");

     # Write some numbers
     $worksheet->write(2, 0,  3);          # Writes 3
     $worksheet->write(3, 0,  3.00000);    # Writes 3
     $worksheet->write(4, 0,  3.00001);    # Writes 3.00001
     $worksheet->write(5, 0,  3.14159);    # TeX revision no.?

     # Write some formulas
     $worksheet->write(7, 0,  '=A3 + A6');
     $worksheet->write(8, 0,  '=IF(A5>3,"Yes", "No")');

     # Write a hyperlink
     $worksheet->write(10, 0, 'http://www.perl.com/');

Example 2
---------

   The following is a general example which demonstrates some features of
working with multiple worksheets.

     #!/usr/bin/perl -w

     use strict;
     use Spreadsheet::WriteExcel;

     # Create a new Excel workbook
     my $workbook = Spreadsheet::WriteExcel->new("regions.xls");

     # Add some worksheets
     my $north = $workbook->addworksheet("North");
     my $south = $workbook->addworksheet("South");
     my $east  = $workbook->addworksheet("East");
     my $west  = $workbook->addworksheet("West");

     # Add a Format
     my $format = $workbook->addformat();
     $format->set_bold();
     $format->set_color('blue');

     # Add a caption to each worksheet
     foreach my $worksheet (@{$workbook->worksheets()}) {
         $worksheet->write(0, 0, "Sales", $format);
     }

     # Write some data
     $north->write(0, 1, 200000);
     $south->write(0, 1, 100000);
     $east->write (0, 1, 150000);
     $west->write (0, 1, 100000);

     # Set the active worksheet
     $south->activate();

     # Set the width of the first column
     $south->set_column(0, 0, 20);

     # Set the active cell
     $south->set_selection(0, 1);

Example 3
---------

   This example shows how to use a conditional numerical format with
colours to indicate if a share price has gone up or down.

     use strict;
     use Spreadsheet::WriteExcel;

     # Create a new workbook and add a worksheet
     my $workbook  = Spreadsheet::WriteExcel->new("stocks.xls");
     my $worksheet = $workbook->addworksheet();

     # Set the column width for columns 1, 2, 3 and 4
     $worksheet->set_column(0, 3, 15);

     # Create a format for the column headings
     my $header = $workbook->addformat();
     $header->set_bold();
     $header->set_size(12);
     $header->set_color('blue');

     # Create a format for the stock price
     my $f_price = $workbook->addformat();
     $f_price->set_align('left');
     $f_price->set_num_format('$0.00');

     # Create a format for the stock volume
     my $f_volume = $workbook->addformat();
     $f_volume->set_align('left');
     $f_volume->set_num_format('#,##0');

     # Create a format for the price change. This is an example of a conditional
     # format. The number is formatted as a percentage. If it is positive it is
     # formatted in green, if it is negative it is formatted in red and if it is
     # zero it is formatted as the default font colour (in this case black).
     # Note: the [Green] format produces an unappealing lime green. Try
     # [Color 10] instead for a dark green.
     #
     my $f_change = $workbook->addformat();
     $f_change->set_align('left');
     $f_change->set_num_format('[Green]0.0%;[Red]-0.0%;0.0%');

     # Write out the data
     $worksheet->write(0, 0, 'Company',$header);
     $worksheet->write(0, 1, 'Price',  $header);
     $worksheet->write(0, 2, 'Volume', $header);
     $worksheet->write(0, 3, 'Change', $header);

     $worksheet->write(1, 0, 'Damage Inc.'       );
     $worksheet->write(1, 1, 30.25,    $f_price ); # $30.25
     $worksheet->write(1, 2, 1234567,  $f_volume); # 1,234,567
     $worksheet->write(1, 3, 0.085,    $f_change); # 8.5% in green

     $worksheet->write(2, 0, 'Dump Corp.'        );
     $worksheet->write(2, 1, 1.56,     $f_price ); # $1.56
     $worksheet->write(2, 2, 7564,     $f_volume); # 7,564
     $worksheet->write(2, 3, -0.015,   $f_change); # -1.5% in red

     $worksheet->write(3, 0, 'Rev Ltd.'          );
     $worksheet->write(3, 1, 0.13,     $f_price ); # $0.13
     $worksheet->write(3, 2, 321,      $f_volume); # 321
     $worksheet->write(3, 3, 0,        $f_change); # 0 in the font color (black)

Example 4
---------

   The following is a simple example of using functions.

     #!/usr/bin/perl -w

     use strict;
     use Spreadsheet::WriteExcel;

     # Create a new workbook and add a worksheet
     my $workbook  = Spreadsheet::WriteExcel->new("stats.xls");
     my $worksheet = $workbook->addworksheet('Test data');

     # Set the column width for columns 1
     $worksheet->set_column(0, 0, 20);

     # Create a format for the headings
     my $format = $workbook->addformat();
     $format->set_bold();

     # Write the sample data
     $worksheet->write(0, 0, 'Sample', $format);
     $worksheet->write(0, 1, 1);
     $worksheet->write(0, 2, 2);
     $worksheet->write(0, 3, 3);
     $worksheet->write(0, 4, 4);
     $worksheet->write(0, 5, 5);
     $worksheet->write(0, 6, 6);
     $worksheet->write(0, 7, 7);
     $worksheet->write(0, 8, 8);

     $worksheet->write(1, 0, 'Length', $format);
     $worksheet->write(1, 1, 25.4);
     $worksheet->write(1, 2, 25.4);
     $worksheet->write(1, 3, 24.8);
     $worksheet->write(1, 4, 25.0);
     $worksheet->write(1, 5, 25.3);
     $worksheet->write(1, 6, 24.9);
     $worksheet->write(1, 7, 25.2);
     $worksheet->write(1, 8, 24.8);

     # Write some statistical functions
     $worksheet->write(4,  0, 'Count', $format);
     $worksheet->write(4,  1, '=COUNT(B1:I1)');

     $worksheet->write(5,  0, 'Sum', $format);
     $worksheet->write(5,  1, '=SUM(B2:I2)');

     $worksheet->write(6,  0, 'Average', $format);
     $worksheet->write(6,  1, '=AVERAGE(B2:I2)');

     $worksheet->write(7,  0, 'Min', $format);
     $worksheet->write(7,  1, '=MIN(B2:I2)');

     $worksheet->write(8,  0, 'Max', $format);
     $worksheet->write(8,  1, '=MAX(B2:I2)');

     $worksheet->write(9,  0, 'Standard Deviation', $format);
     $worksheet->write(9,  1, '=STDEV(B2:I2)');

     $worksheet->write(10, 0, 'Kurtosis', $format);
     $worksheet->write(10, 1, '=KURT(B2:I2)');

Example 5
---------

   The following example converts a tab separated file called `tab.txt'
into an Excel file called `tab.xls'.

     #!/usr/bin/perl -w

     use strict;
     use Spreadsheet::WriteExcel;

     open (TABFILE, "tab.txt") or die "tab.txt: $!";

     my $workbook  = Spreadsheet::WriteExcel->new("tab.xls");
     my $worksheet = $workbook->addworksheet();

     # Row and column are zero indexed
     my $row = 0;

     while (<TABFILE>) {
         chomp;
         # Split on single tab
         my @Fld = split('\t', $_);

         my $col = 0;
         foreach my $token (@Fld) {
             $worksheet->write($row, $col, $token);
             $col++;
         }
         $row++;
     }

LIMITATIONS
===========

   The following limits are imposed by Excel or the version of the BIFF
file that has been implemented:

     Description                          Limit   Source
     -----------------------------------  ------  -------
     Maximum number of chars in a string  255     Excel 5
     Maximum number of columns            256     Excel 5, 97
     Maximum number of rows in Excel 5    16384   Excel 5
     Maximum number of rows in Excel 97   65536   Excel 97

   Note: the maximum row reference in a formula is the Excel 5 row limit
of 16384.

   The minimum file size is 6K due to the OLE overhead. The maximum file
size is approximately 7MB (7087104 bytes) of BIFF data. This can be
extended by using Takanori Kawai's OLE::Storage_Lite module
http://search.cpan.org/search?dist=OLE-Storage_Lite see the `big.pl'
example in the examples directory of the distro.

REQUIREMENTS
============

   This module requires Perl 5.005 (or later) and Parse::RecDescent:
http://search.cpan.org/search?dist=Parse-RecDescent

PORTABILITY
===========

   Spreadsheet::WriteExcel.pm will work on the majority of Windows, UNIX
and Macintosh platforms. Specifically, the module will work on any system
where perl packs floats in the 64 bit IEEE format. The float must also be
in little-endian format but WriteExcel.pm will reverse it as necessary.
Thus:

     print join(" ", map { sprintf "%#02x", $_ } unpack("C*", pack "d", 1.2345)), "\n";

   should give (or in reverse order):

     0x8d 0x97 0x6e 0x12 0x83 0xc0 0xf3 0x3f

   In general, if you don't know whether your system supports a 64 bit
IEEE float or not, it probably does. If your system doesn't, WriteExcel
will `croak()' with the message given in the `DIAGNOSTICS' in this node
section. You can check which platforms the module has been tested on at
the CPAN testers site:
http://testers.cpan.org/search?request=dist&dist=Spreadsheet-WriteExcel

DIAGNOSTICS
===========

Filename required in WriteExcel('Filename')
     A filename must be given in the constructor.

Can't open filename. It may be in use.
     The file cannot be opened for writing. The directory that you are
     writing to  may be protected or the file may be in use by another
     program.

Required floating point format not supported on this platform.
     Operating system doesn't support 64 bit IEEE float or it is
     byte-ordered in a way unknown to WriteExcel.

Unable to create tmp files via IO::File->new_tmpfile().
     This is a -w warning. You will see it if you are using
     Spreadsheet::WriteExcel in an environment where temporary files
     cannot be created, in which case all data will be stored in memory.
     The warning is for information only: it does not affect execution but
     it may effect the speed of execution for large files.

Maximum file size, 7087104, exceeded.
     The current OLE implementation only supports a maximum BIFF file of
     this size. This limit can be extended, see the `LIMITATIONS' in this
     node section.

Can't locate Parse/RecDescent.pm in @INC ...
     Spreadsheet::WriteExcel requires the Parse::RecDescent module.
     Download it from CPAN:
     http://search.cpan.org/search?dist=Parse-RecDescent

Couldn't parse formula ...
     There are a large number of warnings which relate to badly formed
     formulas and functions. See the `FORMULAS AND FUNCTIONS IN EXCEL' in
     this node section for suggestions on how to avoid these errors.

THE EXCEL BINARY FORMAT
=======================

   Excel data is stored in the "Binary Interchange File Format" (BIFF)
file format. Details of this format are given in the Excel SDK, the "Excel
Developer's Kit" from Microsoft Press. It is also included in the MSDN CD
library but is no longer available on the MSDN website. An older version
of the BIFF documentation is available at
http://www.cubic.org/source/archive/fileform/misc/excel.txt

   Issues relating to the Excel SDK are discussed, occasionally, at
news://microsoft.public.excel.sdk

   The BIFF portion of the Excel file is comprised of contiguous binary
records that have different functions and that hold different types of
data. Each BIFF record is comprised of the following three parts:

     Record name;   Hex identifier, length = 2 bytes
     Record length; Length of following data, length = 2 bytes
     Record data;   Data, length = variable

   The BIFF data is stored along with other data in an OLE Compound File.
This is a structured storage which acts like a file system within a file.
A Compound File is comprised of storages and streams which, to follow the
file system analogy, are like directories and files.

   The documentation for the OLE::Storage module,
http://user.cs.tu-berlin.de/~schwartz/pmh/guide.html , contains one of the
few descriptions of the OLE Compound File in the public domain.

   For a open source implementation of the OLE library see the 'cole'
library at http://arturo.directmail.org/filtersweb/

   The source code for the Excel plugin of the Gnumeric spreadsheet also
contains information relevant to the Excel BIFF format and the OLE
container, http://www.gnumeric.org/gnumeric

   In addition the source code for OpenOffice is available at
http://www.openoffice.org/

   An article describing Spreadsheet::WriteExcel and how it works appears
in Issue #19 of The Perl Journal, http://www.itknowledge.com/tpj/ It is
reproduced, by kind permission, in the doc directory of the distro.

   Please note that the provision of this information does not constitute
an invitation to start hacking at the BIFF or OLE file formats. There are
more interesting ways to waste your time. ;-)

WRITING EXCEL FILES
===================

   Depending on your requirements, background and general sensibilities
you may prefer one of the following methods of getting data into Excel:

   * CSV, comma separated variables or text. If the file extension is csv,
Excel will open and convert this format automatically. Generating a valid
CSV file isn't as easy as it seems. Have a look at the DBD::RAM, DBD::CSV
and Text::CSV_XS modules.

   * DBI with DBD::ADO or DBD::ODBC. Excel files contain an internal index
table that allows them to act like a database file. Using one of the
standard Perl database modules you can connect to an Excel file as a
database.

   * Win32::OLE module and office automation. This requires a Windows
platform and an installed copy of Excel. This is the most powerful and
complete method for interfacing with Excel. See
http://velocity.activestate.com/docs/ActivePerl/site/lib/Win32/OLE/TPJ.html
,
http://velocity.activestate.com/docs/ActivePerl/faq/Windows/ActivePerl-Winfaq12.html
and
http://velocity.activestate.com/docs/ActivePerl/site/lib/Win32/OLE.html If
your main platform is UNIX but you have the resources to set up a separate
Win32/MSOffice server, you can convert office documents to text,
postscript or PDF using Win32::OLE. For a demonstration of how to do this
using Perl see Docserver:
http://search.cpan.org/search?mode=module&query=docserver

   * HTML tables. This is an easy way of adding formatting.

   * XML, the Excel XML and HTML file specification are available from
http://msdn.microsoft.com/library/officedev/ofxml2k/ofxml2k.htm

READING EXCEL FILES
===================

   To read data from Excel files try:

   * Spreadsheet::ParseExcel. This uses the OLE::Storage-Lite module to
extract data from an Excel file.
http://search.cpan.org/search?dist=Spreadsheet-ParseExcel

   * OLE::Storage, aka LAOLA. This is a Perl interface to OLE file
formats. In particular, the distro contains an Excel to HTML converter
called Herbert, http://user.cs.tu-berlin.de/~schwartz/pmh/ There is also
an open source C/C++ project based on the LAOLA work. Try the Filters
Project http://arturo.directmail.org/filtersweb/ and the Excel to HTML
converter at the xlHtml Project http://www.xlhtml.org/

   * HTML tables. If the files are saved from Excel in a HTML format the
data can be accessed using HTML::TableExtract
http://search.cpan.org/search?dist=HTML-TableExtract

   * DBI with DBD::ADO or DBD::ODBC. See, the section `WRITING EXCEL
FILES' in this node.

   * Win32::OLE module and office automation. See, the section `WRITING
EXCEL FILES' in this node.

   If you wish to view Excel files on a UNIX/Linux platform check out the
excellent Gnumeric spreadsheet application at
http://www.gnumeric.org/gnumeric or OpenOffice at
http://www.openoffice.org/

   If you wish to view Excel files on a Windows platform which doesn't
have Excel installed you can use the free Microsoft Excel Viewer
http://officeupdate.microsoft.com/2000/downloaddetails/xlviewer.htm

BUGS
====

   Orange isn't.

   Formulas are formulae.

   OpenOffice: Numerical formats are not displayed due to some missing
records in Spreadsheet::WriteExcel. Someone with a good knowledge of C++,
and possibly of German, might help me to track this down in the OpenOffice
source. URLs are not displayed as links.

   Gnumeric: Some formatting is not displayed correctly. URLs are not
displayed as links.

   MS Access: The Excel files that are produced by this module are not
compatible with MS Access. Use DBI or ODBC instead.

   QuickView: If you wish to write files that are fully compatible with
QuickView it is necessary to write the cells in a sequential row by row
order.

   The lack of a portable way of writing a little-endian 64 bit IEEE float.

TO DO
=====

   Read a book, see a film or two.

ACKNOWLEDGEMENTS
================

   The following people contributed to the debugging and testing of
Spreadsheet::WriteExcel:

   Arthur@ais, Artur Silveira da Cunha, Cedric Bouvier, CPAN testers,
Daniel Gardner, Harold Bamford, James Holmes, Johan Ekenberg, John Wren,
Kenneth Stacey, Michael Buschauer, Mike Blazer, Paul J. Falbe, Paul
Medynski, Shenyu Zheng, Rich Sorden.

   The following people contributed code or examples:

   Andrew Benham, Marco Geri, Sam Kington, Takanori Kawai.

   Thanks to Damian Conway for the excellent Parse::RecDescent. Thanks to
Michael Meeks for Gnumeric.

AUTHOR
======

   John McNamara jmcnamara@cpan.org

     Lana Turner has collapsed!
     I was trotting along and suddenly
     it started raining and snowing
     and you said it was hailing
     but hailing hits you on the head
     hard so it was really snowing and
     raining and I was in such a hurry
     to meet you but the traffic
     was acting exactly like the sky
     and suddenly I see a headline
     LANA TURNER HAS COLLAPSED!
     there is no snow in Hollywood
     there is no rain in California
     I have been to lots of parties
     and acted perfectly disgraceful
     but I never actually collapsed
     oh Lana Turner we love you get up
         --Frank O'Hara

COPYRIGHT
=========

   © MM-MMI, John McNamara.

   All Rights Reserved. This module is free software. It may be used,
redistributed and/or modified under the same terms as Perl itself.

An abstract base class for Excel workbooks and worksheets.
**********************************************************

NAME
====

   BIFFwriter - An abstract base class for Excel workbooks and worksheets.

SYNOPSIS
========

   See the documentation for Spreadsheet::WriteExcel

DESCRIPTION
===========

   This module is used in conjunction with Spreadsheet::WriteExcel.

AUTHOR
======

   John McNamara jmcnamara@cpan.org

COPYRIGHT
=========

   © MM-MMI, John McNamara.

   All Rights Reserved. This module is free software. It may be used,
redistributed and/or modified under the same terms as Perl itself.

A class for defining Excel formatting.
**************************************

NAME
====

   Format - A class for defining Excel formatting.

SYNOPSIS
========

   See the documentation for Spreadsheet::WriteExcel

DESCRIPTION
===========

   This module is used in conjunction with Spreadsheet::WriteExcel.

AUTHOR
======

   John McNamara jmcnamara@cpan.org

COPYRIGHT
=========

   © MM-MMI, John McNamara.

   All Rights Reserved. This module is free software. It may be used,
redistributed and/or modified under the same terms as Perl itself.

A class for generating Excel formulas
*************************************

NAME
====

   Formula - A class for generating Excel formulas

SYNOPSIS
========

   See the documentation for Spreadsheet::WriteExcel

DESCRIPTION
===========

   This module is used in conjunction with Spreadsheet::WriteExcel. It
should not be used directly.

   The following notes are to help developers and maintainers understand
the sequence of operation. They are also intended as a pro-memoria for the
author. ;-)

   Spreadsheet::WriteExcel::Formula converts a textual representation of a
formula into the pre-parsed binary format that Excel uses to store
formulas. For example `1+2*3' is stored as follows: `1E 01 00 1E 02 00 1E
03 00 05 03'. This string is comprised of operators and operands arranged
in a reverse-Polish format. The meaning of the tokens in the above example
is shown in the following table:

     Token   Name        Value
     1E      ptgInt      0001   (stored as 01 00)
     1E      ptgInt      0002   (stored as 02 00)
     1E      ptgInt      0003   (stored as 03 00)
     05      ptgMul
     03      ptgAdd

   The tokens and token names are defined in the "Excel Developer's Kit"
from Microsoft Press. `ptg' stands for Parse ThinG (as in "That lexer
can't grok it, it's a parse thang.")

   In general the tokens fall into two categories: operators such as
`ptgMul' above and operands such as `ptgInt'. When the formula is
evaluated by Excel the operand tokens push values onto a stack. The
operator tokens then pop the required number of operands from the stack,
perform an operation and push the resulting value back onto the stack.
This methodology is similar to the basic operation of a reverse-Polish
(RPN) calculator.

   Spreadsheet::WriteExcel::Formula parses a formula using a
Parse::RecDescent parser (at a later stage it may use a `Parse::Yapp'
parser).

   The parser converts the textual representation of a formula into a
parse tree. Thus, `1+2*3' is converted into something like the following,
e stands for expression:

     e
                / | \
              1   +   e
       / | \
     2   *   3

   The function `_reverse_tree()' recurses down through this structure
swapping the order of operators followed by operands to produce a
reverse-Polish tree. Following the above example the resulting tree would
look like this:

     e
                / | \
              1   e   +
                / | \
              2   3   *

   The result of the recursion is a single array of tokens. In our example
the simplified form would look like the following:

     (1, 2, 3, *, +)

   The actual return value contains some additional information to help in
the secondary parsing stage:

     (_num, 1, _num, 2, _num, 3, ptgMul, ptgAdd, _arg, 1)

   The additional tokens are:

     Token   Meaning

     _num    The next token is a number
     _str    The next token is a string
     _ref    The next token is a cell reference
     _rng    The next token is a range
     _fnc    The next token is a function
     _arg    The next token is a the number of args for a function

   The `_arg' token is generated for all lists but is only used for
functions the take a variable number of arguments.

   A secondary parsing stage is carried out by `_parse_tokens()' which
converts these tokens into a binary string. For the `1+2*3' example this
would give:

     1E 01 00 1E 02 00 1E 03 00 05 03

   This two-pass method could probably have been reduced to a single pass
through the Parse::RecDescent parser. However, it was easier to develop
and debug this way.

   The token values and formula values are stored in the `%ptg' and
`%functions' hashes. These hashes and the parser object $parser are
exposed as global data. This breaks the OO encapsulation, but means that
they can be shared by several instances of Spreadsheet::WriteExcel called
from the same program.

   The parser is initialised by `_init_parser()'. The initialisation is
delayed until the first formula is parsed. This eliminates the overhead of
generating the parser in programs that are not processing formulas. (The
parser should really be pre-compiled, this is to-do when the grammar
stabilises).

AUTHOR
======

   John McNamara jmcnamara@cpan.org

COPYRIGHT
=========

   © MM-MMI, John McNamara.

   All Rights Reserved. This module is free software. It may be used,
redistributed and/or modified under the same terms as Perl itself.

A writer class to store BIFF data in a OLE compound storage file.
*****************************************************************

NAME
====

   OLEwriter - A writer class to store BIFF data in a OLE compound storage
file.

SYNOPSIS
========

   See the documentation for Spreadsheet::WriteExcel

DESCRIPTION
===========

   This module is used in conjunction with Spreadsheet::WriteExcel.

AUTHOR
======

   John McNamara jmcnamara@cpan.org

COPYRIGHT
=========

   © MM-MMI, John McNamara.

   All Rights Reserved. This module is free software. It may be used,
redistributed and/or modified under the same terms as Perl itself.

A writer class for Excel Workbooks.
***********************************

NAME
====

   Workbook - A writer class for Excel Workbooks.

SYNOPSIS
========

   See the documentation for Spreadsheet::WriteExcel

DESCRIPTION
===========

   This module is used in conjunction with Spreadsheet::WriteExcel.

AUTHOR
======

   John McNamara jmcnamara@cpan.org

COPYRIGHT
=========

   © MM-MMI, John McNamara.

   All Rights Reserved. This module is free software. It may be used,
redistributed and/or modified under the same terms as Perl itself.

A writer class for Excel Worksheets.
************************************

NAME
====

   Worksheet - A writer class for Excel Worksheets.

SYNOPSIS
========

   See the documentation for Spreadsheet::WriteExcel

DESCRIPTION
===========

   This module is used in conjunction with Spreadsheet::WriteExcel.

AUTHOR
======

   John McNamara jmcnamara@cpan.org

COPYRIGHT
=========

   © MM-MMI, John McNamara.

   All Rights Reserved. This module is free software. It may be used,
redistributed and/or modified under the same terms as Perl itself.

A writer class for Excel Workbooks.
***********************************

NAME
====

   Workbook - A writer class for Excel Workbooks.

SYNOPSIS
========

   See the documentation for Spreadsheet::WriteExcel

DESCRIPTION
===========

   This module is used in conjuction with Spreadsheet::WriteExcel.

AUTHOR
======

   John McNamara jmcnamara@cpan.org

COPYRIGHT
=========

   Copyright (c) 2000, John McNamara. All Rights Reserved. This module is
free software. It may be used, redistributed and/or modified under the
same terms as Perl itself.

Module to manipulate text delimited databases using SQL.
********************************************************

NAME
====

   Sprite - Module to manipulate text delimited databases using SQL.

SYNOPSIS
========

     use Sprite;

     $rdb = new Sprite;

     $rdb->set_delimiter (-Read  => '::')  ## OR: ('Read',  '::');
     $rdb->set_delimiter (-Write => '::')  ## OR: ('Write', '::');

     $rdb->set_os ('Win95');

     ## Valid arguments (case insensitive) include:
     ##
     ## Unix, Win95, Windows95, MSDOS, NT, WinNT, OS2, VMS,
     ## MacOS or Macintosh. Default determined by $^O.

     $rdb->set_lock_file ('c:\win95\tmp\Sprite.lck', 10);

     $rdb->set_db_dir ('Mac OS:Perl 5:Data') || die "Can't access dir!\n";

     $data = $rdb->sql (<<Query);   ## OR: @data = $rdb->sql (<<Query);
         .
         . (SQL)
         .
     Query

     foreach $row (@$data) {        ## OR: foreach $row (@data) {
         @columns = @$row;          ## NO null delimited string -- v3.2
     }

     $rdb->close;
     $rdb->close ($database);       ## To save updated database

DESCRIPTION
===========

   Here is a simple database where the fields are delimited by commas:

     Player,Years,Points,Rebounds,Assists,Championships
     ...
     Larry Bird,13,25,11,7,3
     Michael Jordan,14,29,6,5,5
     Magic Johnson,13,22,7,11,5
     ...

   Note: The first line must contain the field names (case sensitive).

Supported SQL Commands
======================

   Here are a list of the SQL commands that are supported by Sprite:

select - retrieves records that match specified criteria:
          select col1 [,col2] from database
                 where (cond1 OPERATOR value1)
                 [and|or (cond2 OPERATOR value2) ...]

     The '*' operator can be used to select all columns.

     The database is simply the file that contains the data. If the file
     is not in the current directory, the path must be specified.

     Sprite does not support multiple tables (or commonly knows as
     "joins").

     Valid column names can be used where [cond1..n] and [value1..n] are
     expected, such as:

     Example 1:

          select Player, Points from my_db
                 where (Rebounds > Assists)

     The following SQL operators can be used: =, <, >, <=, >=, <> as well
     as Perl's special operators: =~ and !~. The =~ and !~ operators are
     used to specify regular expressions, such as:

     Example 2:

          select * from my_db
                 where (Name =~ /Bird$/i)

     Selects records where the Name column ends with "Bird" (case
     insensitive).  For more information, look at a manual on regexps.

     Note: A path to a database can contain only the following characters:

          \w, \x80-\xFF, -, /, \, ., :

     If you have directories with spaces or other 'invalid' characters, you
     need to use the set_db_dir method.

update - updates records that match specified criteria.
          update database
            set cond1 = (value1)[,cond2 = (value2) ...]
                where (cond1 OPERATOR value1)
                [and|or (cond2 OPERATOR value2) ...]

     Example:

          update my_db
          	 set Championships = (Championships + 1)
                 where (Player = 'Larry Bird')

          update my_db
                 set Championships = (Championships + 1),
          	     Years = (12)
                 where (Player = 'Larry Bird')

delete - removes records that match specified criteria:
          delete from database
                 where (cond1 OPERATOR value1)
                 [and|or (cond2 OPERATOR value2) ...]

     Example:

          delete from my_db
                 where (Player =~ /Johnson$/i) or
                       (Years > 12)

alter - simplified version of SQL-92 counterpart
     Removes the specified column from the database. The other standard SQL
     functions for alter table are not supported:

          alter table database
                drop column column-name

          alter table database
                add column column-name

     Example:

          alter table my_db
                drop column Years

          alter table my_db
                add column Legend

insert - inserts a record into the database:
          insert into database
                 (col1, col2, ... coln)
          values
                 (val1, val2, ... valn)

     Example:

          insert into my_db
                 (Player, Years, Points, Championships)
          values
                 ('Kareem Abdul-Jabbar', 21, 26, 6)

     You don't have to specify all of the fields in the database! Sprite
     also does not require you to specify the fields in the same order as
     that of the database.

     Note: You should make it a habit to quote strings.

METHODS
=======

   Here are the available methods:

set_delimiter
     The set_delimiter function sets the read and write delimiter for the
     database. The delimiter is not limited to one character; you can have
     a string, and even a regexp (for reading only).

     *Return Value*

     None

set_os
     The set_os function can be used to notify Sprite as to the operating
     system that you're using. Default is determined by $^O.

     Note: If you're using Sprite on Windows 95/NT or on OS2, make sure to
     use backslashes - and NOT forward slashes - when specifying a path
     for a database or to the set_db_dir or set_lock_file methods!

     *Return Value*

     None

set_lock_file
     For any O/S that doesn't support flock (i.e Mac, Windows 95 and VMS),
     this method allows you to set a lock file to use and the number of
     tries that Sprite should try to obtain a 'fake' lock. However, this
     method is NOT fully reliable, but is better than no lock at all.

     'Sprite.lck' (either in the directory specified by set_db_dir or in
     the current directory) is used as the default lock file if one is not
     specified.

     *Return Value*

     None

set_db_dir
     A path to a database can contain only the following characters:

          \w, \x80-\xFF, -, /, \, ., :

     If your path contains other characters besides the ones listed above,
     you can use this method to set a default directory. Here's an example:

          $rdb->set_db_dir ("Mac OS:Perl 5:Data");

          $data = $rdb->sql ("select * from phone.db");

     Sprite will look for the file "Mac OS:Perl 5:Data:phone.db". Just to
     note, the database filename cannot have any characters besides the one
     listed above!

     *Return Value*

          0 - Failure
          1 - Success

sql
     The sql function is used to pass a SQL command to this module. All of
     the SQL commands described above are supported. The select SQL command
     returns an array containing the data, where the first element is the
     status.  All of the other other SQL commands simply return a status.

     *Return Value*   1 - Success   0 - Error

close
     The close function closes the file, and destroys the database object.
     You can pass a filename to the function, in which case Sprite will
     save the database to that file; the directory set by set_db_dir is
     used as the default.

     *Return Value*

     None

NOTES
=====

   Sprite is not the solution to all your data manipulation needs. It's
fine for small databases (less than 1000 records), but anything over that,
and you'll have to sit there and twiddle your fingers while Sprite goes
chugging away ... and returns a few *seconds* or so later.

   The main advantage of Sprite is that you can use Perl's regular
expressions to search through your data. Yippee!

SEE ALSO
========

   Text::CSV, RDB

ACKNOWLEDGEMENTS
================

   I would like to thank the following, especially Rod Whitby and Jim
Esten, for finding bugs and offering suggestions:

     Rod Whitby      (rwhitby@geocities.com)
     Jim Esten       (jesten@wdynamic.com)
     Dave Moore      (dmoore@videoactv.com)
     Shane Hutchins  (hutchins@ctron.com)
     Josh Hochman    (josh@bcdinc.com)
     Barry Harrison  (barryh@topnet.net)
     Lisa Farley     (lfarley@segue.com)
     Loyd Gore       (lgore@ascd.org)
     Tanju Cataltepe (tanju@netlabs.net)
     Haakon Norheim  (hanorhei@online.no)

COPYRIGHT INFORMATION
=====================

     Copyright (c) 1995-1998, Shishir Gundavaram
                 All Rights Reserved

     Permission  to  use,  copy, and distribute is hereby granted,
     providing that the above copyright notice and this permission
     appear in all copies and in supporting documentation.

A program flow utility.
***********************

NAME
====

   Startup - A program flow utility.

   *ALPHA* version as of `$Date: 1998/04/28 00:38:41 $'

SYNOPSIS
========

   Have a look at demonstration utility "replace" and at more detailed
description below. It might be useful to use "replace" generally as frame
for new programs.

DESCRIPTION
===========

   As developing with perl you certainly appreciate it to write easily
nifty programs. Unfortunately a bunch of boring problems makes life
uncomfortable.  With some of them I had to deal so often, that I created
this little collection. Imagine:

-
     You want to have an option to work on files recursively.

-
     You want some modules to print some info during work, but this output
     would hardly be predictable and thus might destroy your program
     output.

-
     You want to have a little logfile reporting actions.

-
     You want to report errors, but not via "die", and you dislike to write
     trapping code all the time.

   This module shall contribute to solve those problems, making your your
programs more valuable.

INIT METHODS
============

new
     *$S* = new S

     This is the modules constructor. Some basic initializations are done,
     as there are: msg_reset and forbid_logging are called; err_strpat,
     err_infopat and log_openpat are initialized and log_threshold is set
     to infinity.

init
     1 = *$S* -> init ({    SUB_FILES  => *\&sub*,    # no default
     SUB_STREAM => *\&sub*,    # no default    PROG_DATE  => *$date*,    #
     no default    PROG_NAME  => $name,    # no default    PROG_VER   =>
     *$version*, # no default    DIRMODE    => $string,  # Default: "0700"
       FILEMODE   => $string,  # Default: "0600"    FROM_STDIN => 1||0,
      # Default: 0    RECURSE    => 1||0,     # Default: 0    RELATIVE
     => 1||0,     # Default: 0    DESTPATH   => $path,    # Default: '.'
      SRCPATH    => $path,    # Default: '.'     LOGPATH    => $path,
     # Default: "$prog_name.log" })

     This method you normally will have to call. Via this you pass
     information like recursive and / or relative mode, program name and
     version and so on.  Init method will provide some default values.

     Init is called with an anonymous hash as parameter list. Each
     parameter you can change afterwards with an extra method. Quite
     necessary (but this depends on your wishes) is to init at least
     SUB_FILES and PROG_NAME.

go
     1||0 = *$S* -> go (*@pathes*)

     Works differently for stream mode and file mode. Anyway go will call
     a function in your application, that needs to return a true value (1)
     if successful. If your function returns a zero, go will call
     msg_error().

     Method go normally always returns 1. Zero is returned, when SUB_FILES
     or SUB_STREAM is needed but not defined, or if src_base or current
     directory is not available.

    go: stream mode
          Message mode is set to silent. Function provided via SUB_STREAM
          is called with parameter dest_path.

    go: file mode
          Function provided via SUB_FILES is called for each input file.
          Parameters are (Source_purepath $sp, Source_purefilename *$sf*,
          Destination_path *$dp*, $status).

          Thus path for input file would be: "$sp/*$sf*". *$dp* will be
          the path provided via DESTPATH if either relative mode is unset,
          or the input file path is not relative to the path provided via
          SRCPATH. If in relative mode and input file has a path relative
          to SRCPATH, *$dp* will get that relative part starting from
          DESTPATH.

          $status will be 1 if input file is a file, 0 if file doesn't
          exist and `-1' if file is no file but a directory.

sub_stream
     *\&function* = *$S* -> sub_stream ([*\&function*])

     Returns (optionally sets) the function doing the work when in stream
     mode.

sub_files
     *\&function* = *$S* -> sub_files ([*\&function*])

     Returns (optionally sets) the function doing the work when in file
     mode.

src_base
     $path = *$S* -> src_base ([$path])

     Returns (optionally sets) the base path for source input files.

dest_base
     $path = *$S* -> dest_base ([$path])

     Returns (optionally sets) the base destination path for your output
     files.

from_stdin
     1||0 = *$S* -> from_stdin ([1||0])

     Returns (optionally sets) stream mode.

dir_mode
     *$mode_string* = *$S* -> dir_mode ([*$mode_string*])

     Returns (optionally sets) the owning mode when creating a new
     directory.  Mode is evaluated as an octal number in string
     representation, e.g. "0700".

file_mode
     *$mode_string* = *$S* -> file_mode ([*$mode_string*])

     Returns (optionally sets) the owning mode when creating a file (as of
     now this is only when creating logfile). Mode is evaluated as an
     octal number in string representation, e.g. "0700".

recurse
     1||0 = *$S* -> recurse ([1||0])

     Returns (optionally sets) recurse mode. When in recurse mode,
     directories and directories in directories and ... of input file list
     will be scanned also.

relative
     1||0 = *$S* -> relative ([1||0])

     Returns (optionally sets) relative mode. Effects only in recurse
     mode. When in relative mode, output pathes will be created according
     to input path structure relatively to input base path. E.g.:

     Input base path is `/cdrom'. Scan path is `/cdrom'. Output path is ..
     Then starting at path . the same directory structure as in /cdrom/
     would be created and passed to sub_files function as output path.

prog_date
     *$date* = *$S* -> prog_date ([*$date*])

     Returns (optionally sets) date of application programs creation.

prog_name
     $name = *$S* -> prog_name ([$name])

     Returns (optionally sets) name of application program.

prog_ver
     *$ver* = *$S* -> prog_ver ([*$ver*])

     Returns (optionally sets) version of application program.

ERROR METHODS
=============

   Error is just a way to get around $!. It is little more than a place to
store an error message. It allows you to return 0 as error indicator in a
pure procedurale way over several returns and still to comprise "last
error" information.

error
     0 = *$S* -> error ($string, *$number*, *$longinfo*)

     Saves error message $string, error number *$number*, extra error
     information *$longinfo* and caller() info. Returns always zero.

err_caller
     *\@err_caller* = *$S* -> err_caller (*[caller()]*)

     Returns (and optionally sets) a reference to a caller() array (see:
     man perlfunc). It has the entries (package, filename, line). It is
     automatically set to "caller()" when calling error method.

err_info
     *$err_info* = *$S* -> err_info ([*$err_info*])

     Returns (and optionally sets) error info message, formatted according
     to err_infopat.

err_infopat
     *$err_infopat* = *$S* -> err_infopat ([*$err_infopat*])

     Gimmick pattern for method err_info. Defaults to `'$err_info''.  (See
     method gimmick below at misc section for details)

err_num
     *$err_num* = *$S* -> err_num ([*$err_num*])

     Returns (and optionally sets) error number.

err_str
     *$err_str* = *$S* -> err_str ([*$err_str*])

     Returns (and optionally sets) error message, formatted according to
     err_strpat.

err_strpat
     *$err_strpat* = *$S* -> err_strpat ([*$err_strpat*])

     Gimmick pattern for method err_str. Defaults to `'$err_package:
     $err_str''.  (See method gimmick below at misc section for details)

MESSAGE METHODS
===============

   Message is a userEss interface allowing you to pass some runtime
information to stdout.

msg
     1 = *$S* -> msg ($str)

     Prints message $str. Appends ':' if it is 1st message, inserts `' ''
     if it is 2nd, appends `', '' otherwise.

msg_error
     0 = *$S* -> msg_error ([str])

     Calls `msg_nl ("error!")' and then `msg ("Error: " . $S-'err_str())>.
     Latter message will be sent even in "silent" mode (see msg_silent).

msg_finish
     1 = *$S* -> msg_finish ($str)

     Calls `msg_nl ("$msg.")' unless msg_finish is already called.

msg_nl
     1 = *$S* -> msg_nl ($str)

     Prints message $str with a trailing newline \n. Disables internal
     "continue" mode: further messages will always be sent as msg_nl.

msg_warn
     1 = *$S* -> msg_warn ($str)

     Appends a '!' to message $str.

MESSAGE INIT METHODS
====================

charset
     *$charset_id* = *$S* -> charset ($charset_id)

     Sets standard character set to *$charset_id*. It defaults to
     $ENV{LC_CTYPE}.  It's main purpose is for future releases.

msg_reset
     *$S* = *$S* -> msg_reset ()

     Resets message variables to default values. You will call this
     normally always when starting a new work a la: 'Processing xyz'.

msg_autoindent
     1||0 = *$S* -> msg_autoindent ([1||0])

     Defaults to 1. Returns (optionally sets) autoindent mode. When set,
     msg_indent will be automatically set to the position after the first
     whitespace in the first message. (see also msg_beauty)

msg_beauty
     1||0 = *$S* -> msg_beauty ([1||0])

     Defaults to 1. Returns state of (optionally sets) "beauty" mode. When
     an output line gets longer than msg_maxcolumn and internal "continue"
     mode is set, a newline and an indent is inserted. Internal continue
     mode is unset when calling msg_nl method.

msg_indent
     *$pos* = *$S* -> msg_indent ([*$pos*])

     Defaults to 4. Returns (optionally defines) the indent for beauty
     mode. This value is overridden when msg_autoindent is set.

msg_maxcolumn
     *$pos* = *$S* -> msg_maxcolumn ([*$pos*])

     Defaults to 79. Returns (optionally sets) the maximal length of an
     output line, when in beauty mode.

msg_silent
     1||0 = *$S* -> msg_silent ([1||0])

     Defaults to 0. Returns (optionally sets) silent mode. When set to 1,
     no message except error messages will be printed to stdout.

LOGGING METHODS
===============

allow_logging
     1 = *$S* -> allow_logging ()

     You have to call this to enable logging.

forbid_logging
     0 = *$S* -> forbid_logging ()

     This is default. It forbids methods open_log and log, so that they
     will return always an error. No logfile will be opened, no log entry
     being written.

log_openpat
     *$pat* = *$S* -> log_openpat ([I<$pat])

     Returns (optionally sets) the gimmick pattern used for log opening
     entries.  Defaults to: `'----------  $date, $prog_name $prog_ver
     '."(perl $])\n"'

log_path
     $path = *$S* -> log_path ([$path])

     Returns (optionally sets) path/name of logfile to $path. This
     overrides the default value set when calling S->init. Default is file
     `basename($prog_name).".log"' in current directory.

open_log
     1||0 = *$S* -> open_log ()

     Opens the logfile *$S* -> log_path.

close_log
     1 = *$S* -> close_log ()

     Closes logfile.

log
     1||0 = *$S* -> log ($msg, *$pri*, *$threshold*)

     Adds a log message $msg, getting the priority character *$pri*.  If a
     threshold is given, log this entry only if threshold is smaller or
     equal *$S* -> log_threshold.

log_threshold
     *$threshold* = *$S* -> log_threshold ([*$threshold*])

     Defaults to 0xffffffff. Returns (optionally sets) logging threshold.
     If set, only log calls with a threshold smaller or equal than this
     threshold will be logged.

REDIRECTION METHODS
===================

catch_output
     1||0 = *$S* -> catch_output([*$mode_path*])

     1||0 = *$S* -> catch_stdout([*$mode_path*])

     1||0 = *$S* -> catch_stderr([*$mode_path*])

    catch_output File mode
          If parameter *$mode_path* is specified, STDOUT+STDERR / STDOUT /
          STDERR will be redirected to a file. *$mode_path* is simply
          given to an open call, so you might use this like:

               $S -> catch_output(">>my_stdout_stderr.txt");

    catch_output Pipe mode
          If parameter *$mode_path* is omitted, STDOUT+STDERR / STDOUT /
          STDERR will be sent to the input of a child process. This will
          check it's input if it is according to catch_output_pattern. If
          so, it will send STDOUT messages to $S->msg and STDERR messages
          to $S->msg_error.

          Note, that $S->msg and $S->msg_error are sending their output to
          your STDOUT.

          If you like to get the output passed catch_output_pattern
          yourself rather than printing it via msg or msg_error, you can
          pass a code reference to catch_output_sub. This function will
          then be called with matched output as parameter.

catch_output_sub
     *\&sub* = *$S* -> catch_output_sub([*\&sub*])

     *\&sub* = *$S* -> catch_stdout_sub([*\&sub*])

     *\&sub* = *$S* -> catch_stderr_sub([*\&sub*])

     Returns (optionally sets) the code reference, that will be called when
     some output passed catch_output_pattern in Pipe mode.

restore_output
     1||0 = *$S* -> restore_output()

     1||0 = *$S* -> restore_stdout()

     1||0 = *$S* -> restore_stderr()

     Restores the output that has been redirected via catch_output.

catch_output_pattern
     *$pattern* = *$S* -> catch_output_pattern([*$pattern*])

     *$pattern* = *$S* -> catch_stdout_pattern([*$pattern*])

     *$pattern* = *$S* -> catch_stderr_pattern([*$pattern*])

     When output is redirected, only those output lines will be regarded,
     that match $1 of this pattern. Default is: `'^(.*)$''.

MISCELLANEOUS METHODS
=====================

gimmick
     *$gimicked_string* = *$Startup* -> gimmick (*$control_string*)

     Replaces certain strings in a control string. You can use:

          $S             Seconds
          $M             Minutes
          $H             Hour
          $d             day
          $m             month
          $y             year
          $date          '$d.$m.$y'
          $time          '$H:$M:$S'

          $err_str       current error string
          $err_num       current error number
          $err_info      current error info (longer text)
          $err_package   package calling error method
          $err_filename  filename of package
          $err_line      line in package calling error method

          $prog_name     program name (if set by application)
          $prog_date     program date (if set by application)
          $prog_ver      program version (if set by application)

TO DO
=====

   Lots.

SEE ALSO
========

AUTHOR
======

   Martin Schwartz <`schwartz@cs.tu-berlin.de'>

format file modes like the `ls -l' command does
***********************************************

NAME
====

   Stat::lsMode - format file modes like the `ls -l' command does

SYNOPSIS
========

     use Stat::lsMode;

     $mode = (stat $file)[2];
     $permissions = format_mode($mode);
     # $permissions is now something like  `drwxr-xr-x'

     $permissions = file_mode($file);   # Same as above

     $permissions = format_perms(0644); # Produces just 'rw-r--r--'

     $permissions = format_perms(644);  # This generates a warning message:
     # mode 644 is very surprising.  Perhaps you meant 0644...

     Stat::lsMode->novice(0);           # Disable warning messages

DESCRIPTION
===========

   `Stat::lsMode' generates mode and permission strings that look like the
ones generated by the Unix `ls -l' command.  For example, a regular file
that is readable by everyone and writable only by its owner has the mode
string `-rw-r--r--'.  `Stat::lsMode' will either examine the file and
produce the right mode string for you, or you can pass it the mode that
you get back from Perl's stat call.

`format_mode'
-------------

   Given a mode number (such as the third element of the list returned by
stat), return the appopriate ten-character mode string as it would have
been generated by `ls -l'.  For example, consider a directory that is
readable and searchable by everyone, and also writable by its owner.  Such
a directory will have mode 040755.  When passed this value, `format_mode'
will return the string `drwxr-xr-x'.

   If `format_mode' is passed a permission number like `0755', it will
return a nine-character string insted, with no leading character to say
what the file type is.  For example, `format_mode(0755)' will return just
`rwxr-xr-x', without the leading d.

file_mode
---------

   Given a filename, do lstat on the file to determine the mode, and
return the mode, formatted as above.

Novice Operation Mode
---------------------

   A common mistake when dealing with permission modes is to use `644'
where you meant to use `0644'.  Every permission has a numeric
representation, but the representation only makes sense when you write the
number in octal.  The decimal number 644 corresponds to a permission
setting, but not the one you think.  If you write it in octal you get
01204, which corresponds to the unlikely permissions `-w----r-T', not to
`rw-r--r--'.

   The appearance of the bizarre permission `-w----r-T' in a program is
almost a sure sign that someone used `644' when they meant to use `0644'.
By default, this module will detect the use of such unlikely permissions
and issue a warning if you try to format them.  To disable these warnings,
use

     Stat::lsMode->novice(0);   # disable novice mode

     Stat::lsMode->novice(1);   # enable novice mode again

   The surprising permissions that are diagnosed by this mode are:

     111 => --xr-xrwx
     400 => rw--w----
     440 => rw-rwx---
     444 => rw-rwxr--
     551 => ---r--rwt
     600 => --x-wx--T
     640 => -w------T
     644 => -w----r-T
     660 => -w--w-r-T
     664 => -w--wx--T
     666 => -w--wx-wT
     700 => -w-rwxr-T
     711 => -wx---rwt
     750 => -wxr-xrwT
     751 => -wxr-xrwt
     751 => -wxr-xrwt
     755 => -wxrw--wt
     770 => r------wT
     771 => r------wt
     775 => r-----rwt
     777 => r----x--t

   Of these, only 400 is remotely plausible.

BUGS
====

   As far as I know, the precise definition of the mode bits is portable
between varieties of Unix.  The module should, however, examine `stat.h'
or use some other method to find out if there are any local variations,
because Unix being Unix, someone somewhere probably does it differently.

   Maybe it file_mode should have an option that says that if the file is
a symlink, to format the mode of the pointed to file instead of the mode
of the link itself, the way `ls -Ll' does.

SEE ALSO
========

   * `http://www.plover.com/~mjd/perl/lsMode/'.

   * `ls' in this node

   * `chmod' in this node

   * `stat' in this node

AUTHOR
======

   Mark-Jason Dominus (`mjd-perl-lsmode@plover.com').

Perl5 module for manipulating candidate features (help module for `Statistics::MaxEntropy')
*******************************************************************************************

NAME
====

   Candidates - Perl5 module for manipulating candidate features (help
module for `Statistics::MaxEntropy')

SYNOPSIS
========

     use Statistics::Candidates;

     # create a new candidates object and read candidate features
     $candidates = Statistics::Candidates->new($some_file);

     # checks for constant candidate features
     $candidates->check();

     # writes candidates that were not added to a file
     $candidates->write($some_other_file);

     # clear the administration about being added or not ...
     $candidates->clear();

DESCRIPTION
===========

   The `Candidates' object is for storage, retrieval, and manipulation of
candidate features.

   The reason for separating this code from `Maxentropy.pm' is that a set
of candidate features should be considered a separate object. Blessing
them into `MaxEntropy' would be unnatural.

   Also this code is simpler and more stable than that in the `MaxEntropy'
module.

   This module requires `Bit::SparseVector'.

METHODS
=======

new
          $candidates = Statistics::Candidates->new($file);

check
          $candidates->check();

write
          $candidates->write($file);

clear
          $candidates->clear();

FILE SYNTAX
===========

   The syntax of the candidate feature file is more or less the same as
that for the events file:

   * each line is an event (events specified in the same order as the
     events file);

   * each column is a feature;

   * constant feature functions are forbidden;

   * values are 0 or 1;

   * no space between features;

   * lines that start with `#' are ignored.

   Below is a set of candidates for m events, c candidate features; `f_ij'
are bits:

     name_c <tab> name_c-1 ... name_2 <tab> name_1 <newline>
     f_1c ... f_13 f_12 f_11 <newline>
     	     .
     	     .
              .
     f_ic ... f_i3 f_i2 f_i1 <newline>
     	     .
              .
              .
     f_mc ... f_m3 f_m2 f_m1

SEE ALSO
========

   See Statistics/MaxEntropy,
Statistics/SparseVector..

VERSION
=======

   Version 0.1

AUTHOR
======

   Hugo WL ter Doest, terdoest@cs.utwente.nl

   Hugo WL ter Doest, \texttt{terdoest\symbol{'100}cs.utwente.nl}

COPYRIGHT
=========

   Copyright (C) 1998 Hugo WL ter Doest, terdoest@cs.utwente.nl Univ. of
Twente, Dept. of Comp. Sc., Parlevink Research, Enschede, The Netherlands.

   Copyright (C) 1998 Hugo WL ter Doest,
\texttt{terdoest\symbol{'100}cs.utwente.nl} Univ. of Twente, Dept. of
Comp. Sc., Parlevink Research, Enschede, The Netherlands.

   `Statistics::Candidates' comes with ABSOLUTELY NO WARRANTY and may be
copied only under the terms of the GNU Library General Public License
(version 2, or later), which may be found in the distribution.

Module of basic descriptive statistical functions.
**************************************************

NAME
====

   Statistics::Descriptive - Module of basic descriptive statistical
functions.

SYNOPSIS
========

     use Statistics::Descriptive;
     $stat = Statistics::Descriptive::Full->new();
     $stat->add_data(1,2,3,4); $mean = $stat->mean();
     $var  = $stat->variance();
     $tm   = $stat->trimmed_mean(.25);
     $Statistics::Descriptive::Tolerance = 1e-10;

DESCRIPTION
===========

   This module provides basic functions used in descriptive statistics.
It has an object oriented design and supports two different types of data
storage and calculation objects: sparse and full. With the sparse method,
none of the data is stored and only a few statistical measures are
available. Using the full method, the entire data set is retained and
additional functions are available.

   Whenever a division by zero may occur, the denominator is checked to be
greater than the value `$Statistics::Descriptive::Tolerance', which
defaults to 0.0. You may want to change this value to some small positive
value such as 1e-24 in order to obtain error messages in case of very
small denominators.

METHODS
=======

Sparse Methods
--------------

$stat = Statistics::Descriptive::Sparse->new();
     Create a new sparse statistics object.

$stat->add_data(1,2,3);
     Adds data to the statistics variable. The cached statistical values
     are updated automatically.

$stat->count();
     Returns the number of data items.

$stat->mean();
     Returns the mean of the data.

$stat->sum();
     Returns the sum of the data.

$stat->variance();
     Returns the variance of the data.  Division by n-1 is used.

$stat->standard_deviation();
     Returns the standard deviation of the data. Division by n-1 is used.

$stat->min();
     Returns the minimum value of the data set.

$stat->mindex();
     Returns the index of the minimum value of the data set.

$stat->max();
     Returns the maximum value of the data set.

$stat->maxdex();
     Returns the index of the maximum value of the data set.

$stat->sample_range();
     Returns the sample range (max - min) of the data set.

Full Methods
------------

$stat = Statistics::Descriptive::Full->new();
     Create a new statistics object that inherits from
     Statistics::Descriptive::Sparse so that it contains all the methods
     described above.

$stat->add_data(1,2,4,5);
     Adds data to the statistics variable.  All of the sparse statistical
     values are updated and cached.  Cached values from Full methods are
     deleted since they are no longer valid.

     *Note:  Calling add_data with an empty array will delete all of your
     Full method cached values!*

$stat->get_data();
     Returns a copy of the data array.

$stat->sort_data();
     Sort the stored data and update the mindex and maxdex methods.  This
     method uses perl's internal sort.

$stat->presorted(1);
$stat->presorted();
     If called with a non-zero argument, this method sets a flag that says
     the data is already sorted and need not be sorted again.  Since some
     of the methods in this class require sorted data, this saves some
     time.  If you supply sorted data to the object, call this method to
     prevent the data from being sorted again. The flag is cleared
     whenever add_data is called.  Calling the method without an argument
     returns the value of the flag.

$x = $stat->percentile(25);
($x, $index) = $stat->percentile(25);
     Sorts the data and returns the value that corresponds to the
     percentile as defined in RFC2330:

          For example, given the 6 measurements:

          -2, 7, 7, 4, 18, -5

          Then F(-8) = 0, F(-5) = 1/6, F(-5.0001) = 0, F(-4.999) = 1/6, F(7) =
          5/6, F(18) = 1, F(239) = 1.

          Note that we can recover the different measured values and how many
          times each occurred from F(x) -- no information regarding the range
          in values is lost.  Summarizing measurements using histograms, on the
          other hand, in general loses information about the different values
          observed, so the EDF is preferred.

          Using either the EDF or a histogram, however, we do lose information
          regarding the order in which the values were observed.  Whether this
          loss is potentially significant will depend on the metric being
          measured.

          We will use the term "percentile" to refer to the smallest value of x
          for which F(x) >= a given percentage.  So the 50th percentile of the
          example above is 4, since F(4) = 3/6 = 50%; the 25th percentile is
          -2, since F(-5) = 1/6 < 25%, and F(-2) = 2/6 >= 25%; the 100th
          percentile is 18; and the 0th percentile is -infinity, as is the 15th
          percentile.

          Care must be taken when using percentiles to summarize a sample,
          because they can lend an unwarranted appearance of more precision
          than is really available.  Any such summary must include the sample
          size N, because any percentile difference finer than 1/N is below the
          resolution of the sample.

     taken from: RFC2330 - Framework for IP Performance Metrics, Section
     11.3.  Defining Statistical Distributions

     rfc2330 is available from:
     http://www.cis.ohio-state.edu/htbin/rfc/rfc2330.html

     If the percentile method is called in a list context then it will
     also return the index of the percentile.

$stat->median();
     Sorts the data and returns the median value of the data.

$stat->harmonic_mean();
     Returns the harmonic mean of the data.  Since the mean is undefined
     if any of the data are zero or if the sum of the reciprocals is zero,
     it will return undef for both of those cases.

$stat->geometric_mean();
     Returns the geometric mean of the data.

$stat->mode();
     Returns the mode of the data.

$stat->trimmed_mean(ltrim[,utrim]);
     `trimmed_mean(ltrim)' returns the mean with a fraction `ltrim' of
     entries at each end dropped. `trimmed_mean(ltrim,utrim)' returns the
     mean after a fraction `ltrim' has been removed from the lower end of
     the data and a fraction `utrim' has been removed from the upper end
     of the data.  This method sorts the data before beginning to analyze
     it.

$stat->frequency_distribution();
     `frequency_distribution(partitions)' slices the data into `partition'
     sets (where partition is greater than 1) and counts the number of
     items that fall into each partition. It returns an associative array
     where the keys are the numerical values of the partitions used. The
     minimum value of the data set is not a key and the maximum value of
     the data set is always a key. The number of entries for a particular
     partition key are the number of items which are greater than the
     previous partition key and less then or equal to the current
     partition key. As an example,

          $stat->add_data(1,1.5,2,2.5,3,3.5,4);
          %f = $stat->frequency_distribution(2);
          for (sort {$a <=> $b} keys %f) {
             print "key = $_, count = $f{$_}\n";
          }

     prints

          key = 2.5, count = 4
          key = 4, count = 3

     since there are four items less than or equal to 2.5, and 3 items
     greater than 2.5 and less than 4.

$stat->least_squares_fit();
$stat->least_squares_fit(@x);
     `least_squares_fit()' performs a least squares fit on the data,
     assuming a domain of `@x' or a default of 1..$stat->count(); It
     returns an array of four elements `($q, $m, $r, $rms)' where

    `$q and $m'
          satisfy the equation C($y = $m*$x + $q).

    $r
          is the Pearson linear correlation cofficient.

    `$rms'
          is the root-mean-square error.

     If case of error or division by zero, the empty list is returned.

     The array that is returned can be "coerced" into a hash structure by
     doing the following:

          my %hash = ();
          @hash{'q', 'm', 'r', 'err'} = $stat->least_squares_fit();

REPORTING ERRORS
================

   I read 4 of the 5 perl newsgroups
comp.lang.perl.{misc,moderated,modules,announce} and check my email at
work frequently, so please feel free to post errors to either or both of
those places.  However, realize that if you post to the newsgroup it has
the benefit of alerting other users of the problem.  When reporting
errors, please include the following to help me out:

   * Your version of perl.  This can be obtained by typing perl -v at the
     command line.

   * Which version of Statistics::Descriptive you're using.  As you can
     see below, I do make mistakes.  Unfortunately for me, right now there
     are thousands of CD's with the version of this module with the bugs
     in it.  Fortunately for you, I'm a very patient module maintainer.

   * Details about what the error is.  Try to narrow down the scope of the
     problem and send me code that I can run to verify and track it down.

   My email address can be found at www.perl.com under Who's Who.

REFERENCES
==========

   RFC2330, Framework for IP Performance Metrics

   The Art of Computer Programming, Volume 2, Donald Knuth.

   Handbook of Mathematica Functions, Milton Abramowitz and Irene Stegun.

   Probability and Statistics for Engineering and the Sciences, Jay Devore.

COPYRIGHT
=========

   Copyright (c) 1997,1998 Colin Kuskie. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

   Copyright (c) 1998 Andrea Spinelli. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

   Copyright (c) 1994,1995 Jason Kastner. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

REVISION HISTORY
================

v2.3
     Rolled into November 1998

     Code provided by Andrea Spinelli to prevent division by zero and to
     make consistent return values for undefined behavior.  Andrea also
     provided a test bench for the module.

     A bug fix for the calculation of frequency distributions.  Thanks to
     Nick Tolli for alerting this to me.

     Added 4 lines of code to Makefile.PL to make it easier for the
     ActiveState installation tool to use.  Changes work fine in
     perl5.004_04, haven't tested them under perl5.005xx yet.

v2.2
     Rolled into March 1998.

     Fixed problem with sending 0's and -1's as data.  The old 0 : true ?
     false thing.  Use defined to fix.

     Provided a fix for AUTOLOAD/DESTROY/Carp bug.  Very strange.

v2.1
     August 1997

     Fixed errors in statistics algorithms caused by changing the
     interface.

v2.0
     August 1997

     Fixed errors in removing cached values (they weren't being removed!)
     and added sort_data and presorted methods.

     June 1997

     Transferred ownership of the module from Jason to Colin.

     Rewrote OO interface, modified function distribution, added mindex,
     maxdex.

v1.1
     April 1995

     Added LeastSquaresFit and FrequencyDistribution.

v1.0
     March 1995

     Released to comp.lang.perl and placed on archive sites.

v.20
     December 1994

     Complete rewrite after extensive and invaluable e-mail correspondence
     with Anno Siegel.

v.10
     December 1994

     Initital concept, released to perl5-porters list.

Perl module for calculating critical values of common statistical distributions
*******************************************************************************

NAME
====

   Statistics::Distributions - Perl module for calculating critical values
of common statistical distributions

SYNOPSIS
========

     use Statistics::Distributions;

     $chis=chisqrdistr (2,.05);
     print "Chi-squared-crit (2 degrees of freedom, 95th percentile = 0.05 level) = $chis\n";
     $u=udistr (.05);
     print "u-crit (95th percentile = 0.05 level) = $u\n";
     $t=tdistr (1,.005);
     print "t-crit (1 degree of freedom, 99.5th percentile = 0.005 level) =$t\n";
     $f=fdistr (1,3,.01);
     print "F-crit (1 degree of freedom in numerator, 3 degrees of freedom in denominator, 99th percentile = 0.01 level) = $f\n";
     $uprob=Statistics::Distributions::uprob (-0.85);
     print "upper probability of the u distribution: Q(u) = 1-G(u) (u=1.43) = $uprob\n";
     $chisprob=Statistics::Distributions::chisqrprob (3,6.25);
     print "upper probability of the chi-square distribution: Q = 1-G (3 degrees of freedom, chi-squared = 6.25) = $chisprob\n";
     $tprob=Statistics::Distributions::tprob (3,6.251);
     print "upper probability of the t distribution: Q = 1-G (3 degrees of freedom  , t = 6.251) = $tprob\n";
     $fprob=Statistics::Distributions::fprob (3,5,.625);
     print "upper probability of the F distribution: Q = 1-G (3 degrees of freedom  in numerator, 5 degrees of freedom in denominator, F = 6.25) = $fprob\n";

DESCRIPTION
===========

   This Perl module calulates percentage points (5 significant digits) of
the u (standard normal) distribution, the student's t distribution, the
chi-square distribution and the F distribution. It can also calculate the
upper probability (5 significant digits) of the u (standard normal), the
chi-square, the t and the F distribution.  These critical values are
needed to perform statistical tests, like the u test, the t test, the F
test and the chi-squared test, and to calculate confidence intervals.  If
you are interested in more precise algorithms you could look at:  StatLib:
http://lib.stat.cmu.edu/apstat/  Applied Statistics Algorithms by
Griffiths, P. and Hill, I.D., Ellis Horwood: Chichester (1985)

AUTHOR
======

   Michael Kospach, mike.perl@gmx.at Nice formating, simplification and
bug repair by Matthias Trautner Kromann, mtk@id.cbs.dk

SEE ALSO
========

   Statistics::ChiSquare, Statistics::Table::t, Statistics::Table::F,
perl(1).

An implementation of Linear Threshold Units
*******************************************

NAME
====

   Statistics::LTU -  An implementation of Linear Threshold Units

SYNOPSIS
========

     use Statistics::LTU;

     my $acr_ltu = new Statistics::LTU::ACR(3, 1);    # 3 attributes, scaled

     $ltu->train([1,3,2],  $LTU_PLUS);
     $ltu->train([-1,3,0], $LTU_MINUS);
     ...
     print "LTU looks like this:\n";
     $ltu->print;

     print "[1,5,2] is in class ";
     if ($ltu->test([1,5,2]) > $LTU_THRESHOLD) { print "PLUS" }
     	                                 else { print "MINUS" };

     $ltu->save("ACR.saved") or die "Save failed!";
     $ltu2 = restore Statistics::LTU("ACR.saved");

EXPORTS
=======

   For readability, LTU.pm exports three scalar constants: $LTU_PLUS (+1),
$LTU_MINUS (-1) and $LTU_THRESHOLD (0).

DESCRIPTION
===========

   Statistics::LTU defines methods for creating, destroying, training and
testing Linear Threshold Units.  A linear threshold unit is a 1-layer
neural network, also called a perceptron.  LTU's are used to learn
classifications from examples.

   An LTU learns to distinguish between two classes based on the data
given to it.  After training on a number of examples, the LTU can then be
used to classify new (unseen) examples.  Technically, LTU's learn to
distinguish two classes by fitting a hyperplane between examples; if the
examples have n features, the hyperplane will have n dimensions.  In
general, the LTU's weights will converge to a define the separating
hyperplane.

   The LTU.pm file defines an uninstantiable base class, LTU, and four
other instantiable classes built on top of LTU.  The four individual
classes differs in the training rules used:

ACR - Absolute Correction Rule
TACR - Thermal Absolute Correction Rule (thermal annealing)
LMS - Least Mean Squares rule
RLS - Recursive Least Squares rule
   Each of these training rules behaves somewhat differently.  Exact
details of how these work are beyond the scope of this document; see the
additional documentation file (`ltu.doc') for discussion.

SCALARS
=======

   $LTU_PLUS and $LTU_MINUS (+1 and -1, respectively) may be passed to the
*train* method.  $LTU_THRESHOLD (set to zero) may be used to compare
values returned from the test method.

METHODS
=======

   Each LTU has the following methods:

*new TYPE(n_features, scaling)*
     Creates an LTU of the given TYPE.  TYPE must be one of:

    Statistics::LTU::ACR,
    Statistics::LTU::TACR,
    Statistics::LTU::LMS,   =item Statistics::LTU::RLS.
     `n_features' sets the number of attributes in the examples.  If
     scaling is 1, the LTU will automatically scale the input features to
     the range (-1, +1).  For example:

          $ACR_ltu = new Statistics::LTU::ACR(5, 1);

     creates an LTU that will train using the absolute correction rule.  It
     will have 5 variables and scale features automatically.

copy
     Copies the LTU and returns the copy.

destroy
     Destroys the LTU (undefines its substructures).  This method is kept
     for compatibility; it's probably sufficient simply to call
     *undef($ltu)*.

print
     Prints a human-readable description of the LTU, including the weights.

save(filename)
     Saves the LTU to the file filename.  All the weights and necessary
     permanent data are saved.  Returns 1 if the LTU was saved
     successfully, else 0.

*restore LTU(filename)*
     Static method.  Creates and returns a new LTU from filename.  The new
     LTU will be of the same type.

test(instance)
     Tests the LTU on instance, the instance vector, which must be a
     reference to an array.  Returns the raw (non-thresholded) result.  A
     typical use of this is:

          if ($ltu->test($instance) >= $LTU_PLUS) {
             # instance is in class 1
          } else {
             # instance is in class 2
          }

*correctly_classifies(instance, realclass)*
     Tests the LTU against an instance vector instance, which must be a
     reference to an array.  *realclass* must be a number.  Returns 1 if
     the LTU classifies instance in the same class as *realclass*.
     Technically: Returns 1 iff instance is on the *realclass* side of the
     LTU's hyperplane.

weights
     Returns a reference to a copy of the LTU's weights.

set_origin_restriction(orig)
     Sets LTU's origin restriction to orig, which should be 1 or 0.  If an
     LTU is origin-restricted, its hyperplane must pass through the origin
     (ie, so its intercept is zero).  This is usually used for preference
     predicates, whose classifications must be symmetrical.

is_cycling(n)
     Returns 1 if the LTU's weights seem to be cycling.  This is a
     heuristic test, based on whether the LTU's weights have been pushed
     out in the past n training instances.  See comments with the code.

version
     Returns the version of the LTU implementation.

   In addition to the methods above, each of the four classes of LTU
defines a *train* method.  The *train* method "trains" the LTU that an
instance belongs in a particular class.  For each *train* method, instance
must be a reference to an array of numbers, and value must be a number.
For convenience, two constants are defined: `$LTU_PLUS' and `$LTU_MINUS',
set to +1 and -1 respectively.  These can be given as arguments to the
*train* method.  A typical *train* call looks like:

     $ltu->train([1,3,-5], $Statistics_LTU_PLUS);

   which trains the LTU that the instance vector (1,3,-5) should be in the
PLUS class.

   * For ACR: 	*train(instance, value)*

     Returns 1 iff the LTU already classified the instance correctly, else
     0.

   * For RLS: 	*train(instance, value)*

     Returns undef.

   * For LMS: 	*train(instance, value, rho)*

     Returns 1 if the LTU already classified the instance correctly, else
     0.  *Rho* determines how much the weights are adjusted on each
     training instance.  It must be a positive number.

   * For TACR: 	*train(instance, value, temperature, rate)*

     Uses the thermal perceptron (absolute correction) rule to train the
     specified linear threshold unit on a particular instance_vector.  The
     instance_vector is a vector of numbers; each number is one attribute.
     The desired_value should be either $LTU_PLUS (for positive instances)
     or $LTU_MINUS (for negative instances).  The *temperature* and rate
     must be floating point numbers.

     This method returns 1 if the linear threshold unit already classified
     the instance correctly, otherwise it returns 0.  The TACR rule only
     trains on instances that it does not already classify correctly.

AUTHOR
======

   fawcett@nynexst.com (Tom Fawcett)

   LTU.pm is based on a C implementation by James Callan at the University
of Massachusetts.  His version has been in use for a long time, is stable,
and seems to be bug-free.  This Perl module was created by Tom Fawcett,
and any bugs you find were probably introduced in translation.  Send bugs,
comments and suggestions to *fawcett@nynexst.com*.

BUGS
====

   None known.  This Perl module has been moderately exercised but I don't
guarantee anything.

Perl5 module for Maximum Entropy Modeling and Feature Induction
***************************************************************

NAME
====

   MaxEntropy - Perl5 module for Maximum Entropy Modeling and Feature
Induction

SYNOPSIS
========

     use Statistics::MaxEntropy;

     # debugging messages; default 0
     $Statistics::MaxEntropy::debug = 0;

     # maximum number of iterations for IIS; default 100
     $Statistics::MaxEntropy::NEWTON_max_it = 100;

     # minimal distance between new and old x for Newton's method;
     # default 0.001
     $Statistics::MaxEntropy::NEWTON_min = 0.001;

     # maximum number of iterations for Newton's method; default 100
     $Statistics::MaxEntropy::KL_max_it = 100;

     # minimal distance between new and old x; default 0.001
     $Statistics::MaxEntropy::KL_min = 0.001;

     # the size of Monte Carlo samples; default 1000
     $Statistics::MaxEntropy::SAMPLE_size = 1000;

     # creation of a new event space from an events file
     $events = Statistics::MaxEntropy::new($file);

     # Generalised Iterative Scaling, "corpus" means no sampling
     $events->scale("corpus", "gis");

     # Improved Iterative Scaling, "mc" means Monte Carlo sampling
     $events->scale("mc", "iis");

     # Feature Induction algorithm, also see Statistics::Candidates POD
     $candidates = Statistics::Candidates->new($candidates_file);
     $events->fi("iis", $candidates, $nr_to_add, "mc");

     # writing new events, candidates, and parameters files
     $events->write($some_other_file);
     $events->write_parameters($file);
     $events->write_parameters_with_names($file);

     # dump/undump the event space to/from a file
     $events->dump($file);
     $events->undump($file);

DESCRIPTION
===========

   This module is an implementation of the Generalised and Improved
Iterative Scaling (GIS, IIS) algorithms and the Feature Induction (FI)
algorithm as defined in (*Darroch and Ratcliff 1972*) and (*Della Pietra
et al. 1997*). The purpose of the scaling algorithms is to find the
maximum entropy distribution given a set of events and (optionally) an
initial distribution. Also a set of candidate features may be specified;
then the FI algorithm may be applied to find and add the candidate
feature(s) that give the largest `gain' in terms of Kullback Leibler
divergence when it is added to the current set of features.

   Events are specified in terms of a set of feature functions
(properties) f_1...f_k that map each event to {0,1}: an event is a string
of bits. In addition of each event its frequency is given. We assume the
event space to have a probability distribution that can be described by

     p(x) = 1/Z e^{sum_i alpha_i f_i(x)}

     p(x) = 1/Z e^{sum_i alpha_i f_i(x)}

   \begin{equation*}     p(x) = \frac{1}{Z} \exp[\sum_i \alpha_i f_i(x)]
\end{equation*} where $Z$ is a normalisation factor given by
\begin{equation*}     Z = \sum_x \exp[\sum_i \alpha_i f_i(x)]
\end{equation*}

   where Z is a normalisation factor. The purpose of the IIS algorithm is
the find alpha_1..alpha_k such that D(p~||p), defined by

     D(p~||p) =
        sum_x p~ . log(p~(x) / p(x)),

   is minimal under the condition that p~[f_i] = p[f_i], for all i.

   The purpose of the scaling algorithms IIS GIS is the find
$\alpha_1..\alpha_k$ such that $D(\tilde{p}||p)$, defined by
\begin{equation*}     D(\tilde{p}||p) =        \sum_x \tilde{p} \log
(\frac{\tilde{p}(x)}{p(x)}), \end{equation*} is minimal under the
condition that for all $i$ $\tilde{p}[f_i]=p[f_i]$.

   The module requires the `Bit::SparseVector' module by Steffen Beyer and
the Data::Dumper module by Gurusamy Sarathy. Both can be obtained from
CPAN just like this module.

CONFIGURATION VARIABLES
-----------------------

`$Statistics::MaxEntropy::debug'
     If set to 1, lots of debug information, and intermediate results will
     be output. Default: 0

`$Statistics::MaxEntropy::NEWTON_max_it'
     Sets the maximum number of iterations in Newton's method. Newton's
     method is applied to find the new parameters \alpha_i of the features
     `f_i'. Default: 100.

`$Statistics::MaxEntropy::NEWTON_min'
     Sets the minimum difference between x' and x in Newton's method (used
     for computing parameter updates in IIS); if either the maximum number
     of iterations is reached or the difference between x' and x is small
     enough, the iteration is stopped. Default: `0.001'. Sometimes
     features have Infinity or -Infinity as a solution; these features are
     excluded from future iterations.

`$Statistics::MaxEntropy::KL_max_it'
     Sets the maximum number of iterations applied in the IIS algorithm.
     Default: 100.

`$Statistics::MaxEntropy::KL_min'
     Sets the minimum difference between KL divergences of two
     distributions in the IIS algorithm; if either the maximum number of
     iterations is reached or the difference between the divergences is
     enough, the iteration is stopped. Default: `0.001'.

`$Statistics::MaxEntropy::SAMPLE_size'
     Determines the number of (unique) events a sample should contain. Only
     makes sense if for sampling "mc" is selected (see below). Its default
     is `1000'.

METHODS
-------

new
          $events = Statistics::MaxEntropy::new($events_file);

     A new event space is created, and the events are read from $file. The
     events file is required, its syntax is described in `FILE SYNTAX' in
     this node.

write
          $events->write($file);

     Writes the events to a file. Its syntax is described in `FILE SYNTAX'
     in this node.

scale
          $events->scale($sample, $scaler);

     If `$scaler' equals `"gis"', the Generalised Iterative Scaling
     algorithm (*Darroch and Ratcliff 1972*) is applied on the event
     space; `$scaler' equals `"iis"', the Improved Iterative Scaling
     Algorithm (*Della Pietra et al. 1997*) is used. If `$sample' is
     `"corpus"', there is no sampling done to re-estimate the parameters
     (the events previously read are considered a good sample); if it
     equals `"mc"' Monte Carlo (Metropolis-Hastings) sampling is performed
     to obtain a random sample; if `$sample' is `"enum"' the complete
     event space is enumerated.

`fi'
          fi($scaler, $candidates, $nr_to_add, $sampling);

     Calls the Feature Induction algorithm. The parameter `$nr_to_add' is
     for the number of candidates it should add. If this number is greater
     than the number of candidates, all candidates are added. Meaningfull
     values for `$scaler' are `"gis"' and `"iis"'; default is `"gis"' (see
     previous item). `$sampling' should be one of `"corpus"', `"mc"',
     `"enum"'.  `$candidates' should be in the `Statistics::Candidates'
     class:

          $candidates = Statistics::Candidates->new($file);

     See Statistics/Candidates.

`write_parameters'
          $events->write_parameters($file);

`write_parameters_with_names'
          $events->write_parameters_with_names($file);

dump
          $events->dump($file);

     `$events' is written to $file using Data::Dumper.

`undump'
          $events = Statistics::MaxEntropy->undump($file);

     The contents of file $file is read and eval'ed into `$events'.

FILE SYNTAX
===========

   Lines that start with a `#' and empty lines are ignored.

   Below we give the syntax of in and output files.

EVENTS FILE (input/output)
--------------------------

   Syntax of the event file (n features, and m events); the following
holds for features:

   * each line is an event;

   * each column represents a feature function; the co-domain of a feature
     function is {0,1};

   * no space between feature columns;

   * constant features (i.e. columns that are completely 0 or 1) are
     forbidden;

   * 2 or more events should be specified (this is in fact a consequence of
     the previous requirement;

   The frequency of each event precedes the feature columns. Features are
indexed from right to left. This is a consequence of how
`Bit::SparseVector' reads bit strings. Each `f_ij' is a bit and `freq_i'
an integer in the following schema:

     name_n <tab> name_n-1 ... name_2 <tab> name_1 <newline>
     freq_1 <white> f_1n ... f_13 f_12 f_11 <newline>
       .                     .
       .                     .
       .                     .
     freq_i <white> f_in ... f_i3 f_i2 f_i1 <newline>
       .                     .
       .                     .
       .                     .
     freq_m <white> f_mn ... f_m3 f_m2 f_m1

   (m events, n features) The feature names are separated by tabs, not
white space. The line containing the feature names will be split on tabs;
this implies that (non-tab) white space may be part of the feature names.

PARAMETERS FILE (input/output)
------------------------------

   Syntax of the initial parameters file; one parameter per line:

     par_1 <newline>
      .
      .
      .
     par_i <newline>
      .
      .
      .
     par_n

   The syntax of the output distribution is the same. The alternative
procedure for saving parameters to a file `write_parameters_with_names'
writes files that have the following syntax

     n <newline>
     name_1 <tab> par_1 <newline>
      .
      .
      .
     name_i <tab> par_i <newline>
      .
      .
      .
     name_n <tab> par_n <newline>
     bitmask

   where bitmask can be used to tell other programs what features to use
in computing probabilities. Features that were ignored during scaling or
because they are constant functions, receive a 0 bit.

DUMP FILE (input/output)
------------------------

   A dump file contains the event space (which is a hash blessed into
class `Statistics::MaxEntropy') as a Perl expression that can be evaluated
with eval.

BUGS
====

   It's slow.

SEE ALSO
========

   `perl(1)' in this node, see Statistics/Candidates,
see Statistics/SparseVector,
see Bit/Vector,
Data/Dumper, POSIX, Carp.

DIAGNOSTICS
===========

   The module dies with an appropriate message if

   * it cannot open a specified events file;

   * if you specified a constant feature function (in the events file or
     the candidates file);

   * if the events file, candidates file, or the parameters file is not
     consistent; possible causes are (a.o.): insufficient or too many
     features for some event; inconsistent candidate lines; insufficient,
     or to many event lines in the candidates file.

   The module captures `SIGQUIT' and `SIGINT'. On a `SIGINT' (typically
<CONTROL-C> it will dump the current event space(s) and die. If a
`SIGQUIT' (<CONTROL-BACKSLASH>) occurs it dumps the current event space as
soon as possible after the first iteration it finishes.

REFERENCES
==========

(Abney 1997)
     Steven P. Abney, Stochastic Attribute Value Grammar, Computational
     Linguistics 23(4).

(Darroch and Ratcliff 1972)
     J. Darroch and D. Ratcliff, Generalised Iterative Scaling for
     log-linear models, Ann. Math. Statist., 43, 1470-1480, 1972.

(Jaynes 1983)
     E.T. Jaynes, Papers on probability, statistics, and statistical
     physics. Ed.: R.D. Rosenkrantz. Kluwer Academic Publishers, 1983.

(Jaynes 1997)
     E.T. Jaynes, Probability theory: the logic of science, 1997,
     unpublished manuscript.
     `URL:http://omega.math.albany.edu:8008/JaynesBook.html'

(Della Pietra et al. 1997)
     Stephen Della Pietra, Vincent Della Pietra, and John Lafferty,
     Inducing features of random fields, In: Transactions Pattern Analysis
     and Machine Intelligence, 19(4), April 1997.

VERSION
=======

   Version 0.8.

AUTHOR
======

   Hugo WL ter Doest, terdoest@cs.utwente.nl

   Hugo WL ter Doest, terdoest@cs.utwente.nl

   Hugo WL ter Doest, \texttt{terdoest\symbol{'100}cs.utwente.nl}

COPYRIGHT
=========

   Copyright (C) 1998 Hugo WL ter Doest, terdoest@cs.utwente.nl Univ. of
Twente, Dept. of Comp. Sc., Parlevink Research, Enschede, The Netherlands.

   Copyright (C) 1998 Hugo WL ter Doest,
\texttt{terdoest\symbol{'100}cs.utwente.nl} Univ. of Twente, Dept. of
Comp. Sc., Parlevink Research, Enschede, The Netherlands.

   `Statistics::MaxEntropy' comes with ABSOLUTELY NO WARRANTY and may be
copied only under the terms of the GNU Library General Public License
(version 2, or later), which may be found in the distribution.

perform ordinary least squares and associated statistics, v 0.07.
*****************************************************************

NAME
====

   Statistics::OLS - perform ordinary least squares and associated
statistics, v 0.07.

SYNOPSIS
========

     use Statistics::OLS;

     my $ls = Statistics::OLS->new();

     $ls->setData (\@xydataset) or die( $ls->error() );
     $ls->setData (\@xdataset, \@ydataset);

     $ls->regress();

     my ($intercept, $slope) = $ls->coefficients();
     my $R_squared = $ls->rsq();
     my ($tstat_intercept, $tstat_slope) = $ls->tstats();
     my $sigma = $ls->sigma();
     my $durbin_watson = $ls->dw();

     my $sample_size = $ls->size();
     my ($avX, $avY) = $ls->av();
     my ($varX, $varY, $covXY) = $ls->var();
     my ($xmin, $xmax, $ymin, $ymax) = $ls->minMax();

     # returned arrays are x-y or y-only data
     # depending on initial call to setData()
     my @predictedYs = $ls->predicted();
     my @residuals = $ls->residuals();

DESCRIPTION
===========

   I wrote *Statistics::OLS* to perform Ordinary Least Squares (linear
curve fitting) on two dimensional data: y = a + bx. The other simple
statistical module I found on CPAN (Statistics::Descriptive) is designed
for univariate analysis. It accomodates OLS, but somewhat inflexibly and
without rich bivariate statistics. Nevertheless, it might make sense to
fold OLS into that module or a supermodule someday.

   *Statistics::OLS* computes the estimated slope and intercept of the
regression line, their T-statistics, R squared, standard error of the
regression and the Durbin-Watson statistic. It can also return the
residuals.

   It is pretty simple to do two dimensional least squares, but much
harder to do multiple regression, so OLS is unlikely ever to work with
multiple independent variables.

   This is a beta code and has not been extensively tested. It has worked
on a few published datasets. Feedback is welcome, particularly if you
notice an error or try it with known results that are not reproduced
correctly.

USAGE
=====

Create a regression object: new()
---------------------------------

     use Statistics::OLS;
     my $ls = Statistics::OLS->new;

Register a dataset: setData()
-----------------------------

     $ls->setData (\@xydata);
     $ls->setData (\@xdata, \@ydata);

   The setData() method registers a two-dimensional dataset with the
regression object.  You can pass the dataset either as a reference to one
flat array containing the paired x,y data or as references to two arrays,
one each for the x and y data. [In either case, the data arrays in your
script are not cached (copied into the object). If you alter your data,
you may optionally call setData() again (if you want error checking-see
below) but you should at least call the regress() method (see below) to
recompute statistics for the new data. Or more simply, do not alter your
data.]

   As a single array, in your script, construct a flat array of the form
(x0, y0, ..., xn, yn) containing n+1 x,y data points.  Then pass a
reference to the data array to the setData() method. (If you do not know
what a reference is, just put a backslash (\) in front of the name of your
data array when you pass it as an argument to setData().)  Like this:

     my @xydata = qw( -3 9   -2 4   -1 1   0 0   1 1  2 4  3 9);
     $ls->setData (\@xydata);

   Or, you may find it more convenient to construct two equal length
arrays, one for the horizontal and one for the corresponding vertical
data. Then pass references to both arrays (horizontal first) to setData():

     my @xdata = qw( -3  -2  -1  0  1  2  3 );
     my @ydata = qw(  9   4   1  0  1  4  9 );
     $ls->setData (\@xdata, \@ydata);

   *Error checking:* The setData() method returns a postive integer on
success and 0 on failure. If setData() fails, you can recover an error
message about the failure with the error() method. The error string
returned will either be one of

     The data set does not contain an equal number of x and y values.
     The data element ... is non-numeric.
     The data set must contain at least three points.

   In your script, you could test for errors like:

     $ls->setData (\@data) or die( $ls->error() );

   In the current version, only numerals, decimal points (apologies to
Europeans), scientific notation (1.7E10) and minus signs are permitted.
Currencies ($), time (11:23am) or dates (23/05/98) are not yet supported
and will generate errors. I may figure these out someday.

Perform the regression: regress()
---------------------------------

     $ls->regress() or die ( $ls->error() );

   This performs most of the calculations. Call this method after setting
the data, but before asking for any regressions results. If you change
your data, previous calculations will generallly be inaccurate, so you
should call this method again. The regress() method returns 1 on success,
The only error message is

     No datset has been registered.

   although a number of undef results (due to divide by zero errors) may
be returned in specific statistics below.

Obtain regression results: coefficients(), rsq(), tstats(), etc.
----------------------------------------------------------------

     my ($intercept, $slope) = $ls->coefficients();
     my $R_squared = $ls->rsq();
     my ($tstat_intercept, $tstat_slope) = $ls->tstats();
     my $sigma = $ls->sigma();
     my $durbin_watson = $ls->dw();

     my $sample_size = $ls->size();
     my ($avX, $avY) = $ls->av();
     my ($varX, $varY, $covXY) = $ls->var();
     my ($xmin, $xmax, $ymin, $ymax) = $ls->minMax();

   Call these methods only after you have called regress().  Most of these
should be familiar from any econometrics text. If the slope is infinite
(variance of X is zero) it is set to undef. R-squared is 1.0 if the sample
variances of either X or Y are zero (or the data are colinear). If the
variance of X is zero, both T statistics are set to undef. sigma is an
estimate of the homoscedastic standard deviation of the error term, also
known as the standard error of the estimate. The variances use n-1.
Durbin-Watson returns undef if the data are colinear.

Obtain predicted or residual data: predicted() and residuals()
--------------------------------------------------------------

     my @predictedYs = $ls->predicted();
     my @residuals = $ls->residuals();

   Call these methods only after you have called regress().  Both methods
return data arrays, in the same format you used in setData(). If the data
was passed to setData() as a reference to an @xydata array of the form
(x0, y0, ..., xn, yn), then the results of these methods will be of this
same form, except that the y values will either be the predicted y based
on the coefficient estimates, or the residual error of that predicted y
from the observed value of y.

   If the data was passed as references to two arrays, @xdata = (x0 ...
xn) and @ydata = (y0 ... yn), then the results of these two methods will
be a single array of y type data, either the predicted y or residual
error. The original x data array will still correspond to these result
arrays.

BUGS AND TO DO
==============

   This module is beta code, so it is not guaranteed to work right.  I
have not exhaustively tested it.

   Possible future work includes support for other data formats, such as
date, time and currency.

   Generalization to multiple regression is probably not in the cards,
since it is more than an order of magnitude more difficult. Better to use
something Fortran based or maybe the Perl Data Language.

   It would make sense to fold this into Statistics::Descriptive as a more
comprehensive library, perhaps called `libstats'. But that might not
happen soon, since it sounds like a big project.

   Comments and bug reports are welcome.

AUTHOR
======

   Copyright (c) 1998 by Sanford Morton, smorton@pobox.com.  All rights
reserved.  This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

   This work is dedicated to the memory of Dr. Andrew Morton, who
requested it.  *Requiescat in pace*, my friend.

SEE ALSO
========

   The Statistics::Descriptive(1) module performs useful univariate
statistics and is well tested. The Perl Data Language (see CPAN) may also
prove useful for statistics.

   Simple linear regression is discussed in all econometrics and most
probablility and statistics texts. I used E<Basic Econometrics> 2nd ed.,
by Gujaratii, New York: McGraw-Hill,1988, for most of the formulas and the
test example (appendix 3A.6, page 87).

Perl5 extension for manipulating sparse bitvectors
**************************************************

NAME
====

   Statistics::SparseVector - Perl5 extension for manipulating sparse
bitvectors

SYNOPSIS
========

     use Statistics::SparseVector;

     # methods that create new bitvectors
     $vec = Statistics::SparseVector->new($n);
     $vec2 = $vec1->Clone();
     $vec = Statistics::SparseVector->new_Enum($s, $n);
     $vec = Statistics::SparseVector->new_Bin($s, $n);

     # miscellaneous
     $vec2->Substitute_Vector($vec1, $of22, $len2, $off1, $len1);
     $vec->Size();
     $vec->to_Enum();
     $vec->to_Bin();
     $vec->Fill();
     $vec->Empty();
     $vec->increment();
     $n = $vec->Norm();
     @list = $vec->indices();

     # manipulation on the bit level
     $vec->Bit_Off($i);
     $vec->Bit_On($i);
     $vec->bit_flip($i);
     $vec->bit_test($i);

     # overloaded operators
     # increment
     $vec++;
     # stringify
     "$vec"

DESCRIPTION
===========

   This module implements sparse bitvectors. Several methods for
manipulating bitvectors are implemented. On purpose the naming of the
methods is identical to the Bit::Vector package by Stephen Beyer; if you
find your vectors to be sparse (have little bits that are on) you can
easily switch to a less memory consuming representation.

Creation of bitvectors
----------------------

new
          $vec = Statistics::BitVector->new($n);

     A bitvector of length $n is created. All bits are zero.

Clone
          $clone = $vec->Clone();

     A copy of `$vec' is returned.

`new_Enum'
          $vec = Statistics::BitVector->new_Enum($enumstring, $n);

     A new bitvector of length $n is created from the comma-separated list
     of in `$enumstring'.

`new_Bin'
          $vec = Statistics::BitVector->new_Bin($bitstring, $n);

     A new bitvector of length $n is created from bitstring `$bitstring'.

Vector-wide manipulation of bits
--------------------------------

`Substitute_Vector'
          $vec2->Substitute_Vector($vec1, $off2, $len2, $off1, $len1);

     `$len2' contiguous bits in target vector `$vec2' starting from
     `$off2' are replaced by `$len1' contiguous bits from source vector
     `$vec1' starting at bit `$off1'. If `$off2' equals the length of
     `$vec2' the bits from `$vec1' are appended. If `$len1' is zero the
     `$len2' bits from `$vec2' are deleted.

`Fill'
          $vec->Fill();

     All bits of `$vec' are set to one.

Empty
          $vec->Empty();

     All bits of `$vec' are set to zero.

`increment'
          $vec->increment(); $vec++;

     The integer value of the bitvector is increased by one.

`Bit_Off'
          $vec->Bit_Off($i);

     Bit $i is set to zero.

`Bit_On'
          $vec->Bit_On($i);

     Bit $i is set to one.

`bit_flip'
          $vec->bit_flip($i);

     Bit $i is flipped.

`bit_test'
          $vec->bit_test($i);

     Returns 1 if bit $i is one, 0 otherwise.

Miscellany
----------

Size
          $n = $vec->Size();

     Returns the size of the vector.

`to_Enum'
          $enumstring = $vec->to_Enum();

     Returns a comma-separated list of bits that are set.

`indices'
     Returns an array of indices of bits that are set.

`to_Bin'
          $bitstring = $vec->to_Bin();

     Returns a bitstring; bits should be read from right to left.

`Norm'
     Returns the number of set bits.

Overloaded operators
--------------------

`++'
          $vec++;

     Same as method `increment'.

Double quotes
          $string = "$vec";

     Data::Dumper wants to stringify vectors. Probably because
     `Statistics::SparseVector' is an overloaded package it expects double
     quotes to be overloaded as well.

Remarks about the implementation
--------------------------------

   * Internally sparse vectors are represented by hashes.

   * Only a few methods from Bit::Vector are implemented. Maybe new ones
     will follow in the future.

   * Method `Substitute_Vector' is not thorougly debugged.

VERSION
=======

   Version 0.1.

AUTHOR
======

   Hugo WL ter Doest, terdoest@cs.utwente.nl

   Hugo WL ter Doest, \texttt{terdoest\symbol{'100}cs.utwente.nl}

SEE ALSO
========

   `perl(1)' in this node, `Bit::Vector(3)' in this node,
`Statistics::MaxEntropy(3)' in this node, `Statistics::ME.wrapper.pl(3)'
in this node, `Statistics::Candidates(3)' in this node.

COPYRIGHT
=========

   Copyright (C) 1998 Hugo WL ter Doest, terdoest@cs.utwente.nl Univ. of
Twente, Dept. of Comp. Sc., Parlevink Research, Enschede, The Netherlands.

   Copyright (C) 1998 Hugo WL ter Doest,
\texttt{terdoest\symbol{'100}cs.utwente.nl} Univ. of Twente, Dept. of
Comp. Sc., Parlevink Research, Enschede, The Netherlands.

   `Statistics::MaxEntropy' comes with ABSOLUTELY NO WARRANTY and may be
copied only under the terms of the GNU Library General Public License
(version 2, or later), which may be found in the distribution.

Solaris performance data collection and graphing package
********************************************************

NAME
====

   StatsView - Solaris performance data collection and graphing package

SYNOPSIS
========

     use StatsView::Graph;
     my $graph = StatsView::Graph->new("sar.txt");
     $graph->read("CPU usage");
     $graph->define(columns => [ "%idle" ]);
     $graph->save(file => "sar_idle_cpu.gif", format => "gif");

DESCRIPTION
===========

   StatsView::Graph is a package that was originally written for internal
use within the Sun UK Performance Centre.  It allows the display of the
output of the standard Solaris utilities sar, iostat, mpstat and vmstat,
as well as the output of vxstat if Veritas Volume Manager is in use.  It
also supports the iost+ utility (available as part of the CPAN
Solaris::Kstat package), and the output of the Oracle monitoring provided
by the sv script. The sv script is merely a GUI front-end around this
pakage.

PREREQUISITES
=============

   This package requires gnuplot, at least version beta 340.  If you wish
to produce GIF plots you will also need a gnuplot that is built with
support for the GD GIF library.

TERMINOLOGY
===========

     category   - A class of related data, for applications that
                  collect more than one type of data at a time
                  eg for sar, CPU utilisation, Disk IO etc
     column     - A time-series of data, eg %busy
     instance   - An entity for which data is collected
                  eg disk drive, Oracle tablespace
     sample     - All data collected at a given point in time
     data point - An individual statistic value
                  eg reads/sec for disk c0t0d0 at 10:35:04

   Data of 2 types can be displayed by StatsView - 2d or 3d.  2d data does
not have any instance information, eg for CPU usage, total idle, usr, sys,
wio.  3d data has instance information, eg for Disk usage, reads/sec,
writes/sec by disk.

METHODS
=======

new()
-----

   This takes a single argument, the name of a statistics file to open.
This can be the output of one of the following commands:

     iost+                      - see the Solaris::Kstats module
     iostat -x                  - extended device statistics format
     Built-in Oracle monitoring - collected via sv
     sar                        - binary or text format
     vmstat                     - standard format
     mpstat                     - standard format
     vxstat                     - Veritas VM statistics

   Note that iostat, mpstat and vmstat don't put timestamps in their
output, thus making it impossible to decide hown the data should be
graphed.  To circumvent this problem it is necessary to add a header line
to the start of the data files of the form:

     Start: 01/01/1998 12:00:00 Interval: 10

   Giving the start of the sampling period in dd/mm/yyyy hh:mm:ss format
and the interval between samples in seconds.  This is done automatically
if the data is collected via the sv script.

read()
------

   This reads in the data from the file.  For data files that contain more
than one category of data, the name of the category to read should be
given as an argument, eg for sar "CPU usage" or "Disk IO".  The
get_categories() method can be used to find out all the available
categories - see below.

define()
--------

   This defines the parameters of the graph that is to be drawn.  It takes
a list of key-value parameter pairs.  Different parameters are supported
depending on whether the data is 2d or 3d.  Parameters allowed for both 2d
and 3d data are:

     scale => "normal" | "logarithmic"

   The default is "normal".

   For 2d data the expected parameter is:

     columns => [ <list of columns to plot> ]

   For 3d data the expected parameters are:

     column    => <column name>
     instances => [ <list of instances to plot> ]

   The available columns and instances can be retrieved via the
get_columns() and get_instances() methods - see below.

plot()
------

   This takes no arguments, and plots the currently defined graph to the
screen.

print()
-------

   This prints the currently defined graph. It takes a list of key-value
parameter pairs.  Allowed parameters are:

     orientation => "landscape" | "portrait"   default: landscape
     color       => "monochrome" | "color"     default: color
     printer     => <printer command>          Eg "lp", "lp -d myprinter"
     type        => "postscript" | "laserjet ii" | "laserjet iii"

save()
------

   This saves the currently defined graph to a file.  It takes a list of
key-value parameter pairs.  Allowed parameters are:

     orientation => "landscape" | "portrait"   default: landscape
     color       => "monochrome" | "color"     default: color
     file        => <output filename>
     format      => "csv"          comma-separated text
                  | "postscript"   postscript format
                  | "cgm"          Computer Graphics Metafile
                                   - For M$ Word, etc
                  | "mif"          Framemaker
                  | "gif"          requires gnuplot built with GD support

get_data_type()
---------------

   This returns the type of the data in the file - either "2d" or "3d" (see
TERMINOLOGY above).  For data files that contain more than obe category of
data, the name of a catogory should be supplied as an argument.

get_columns()
-------------

   This returns a list of the available columns.

get_instances()
---------------

   This returns a list of the available instances, for 3d data.  For 2d
data it will return an empty list.

get_times()
-----------

   This returns a 3 element list of (start time, sampling interval, end
time).  Start and end time are expressed as a standard Unix 32-bit time
value, and the sampling interval is expressed in seconds.

get_title()
-----------

   This returns the title that will be displayed at the top of the graph.

get_categories()
----------------

   This will return a list of all the available categories, for files that
contain several categories of data.  For files that only contain 1
category of data it will return an empty list.

get_file()
----------

   This returns the name of the data file that has been read in.

AUTHOR
======

   Support questions and suggestions can be directed to
Alan.Burlison@uk.sun.com

COPYRIGHT AND DISCLAIMER
========================

   Copyright (c) 1998 Alan Burlison

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file,
with the exception that it cannot be placed on a CD-ROM or similar media
for commercial distribution without the prior approval of the author.

   This code is provided with no warranty of any kind, and is used
entirely at your own risk.

   This code was written by the author as a private individual, and is in
no way endorsed or warrantied by Sun Microsystems.

In-memory storage for hierarchical tag/value data structures
************************************************************

NAME
====

   Stone - In-memory storage for hierarchical tag/value data structures

SYNOPSIS
========

     use Stone;
     my $stone = Stone->new( Jim => { First_name => 'James',
     				  Last_name  => 'Hill',
     				  Age        => 34,
     				  Address    => {
     					 Street => ['The Manse',
     						    '19 Chestnut Ln'],
     					 City  => 'Garden City',
     					 State => 'NY',
     					 Zip   => 11291 }
     				},
     			  Sally => { First_name => 'Sarah',
     				     Last_name  => 'James',
     				     Age        => 30,
     				     Address    => {
     					 Street => 'Hickory Street',
     					 City  => 'Katonah',
     					 State => 'NY',
     					 Zip  => 10578 }
     				}
     			 );

     @tags    = $stone->tags;          # yields ('James','Sally');
     $address = $stone->Jim->Address;  # gets the address subtree
     @street  = $address->Street;      # yeilds ('The Manse','19 Chestnut Ln')

     $address = $stone->get('Jim')->get('Address'); # same as $stone->Jim->Address
     $address = $stone->get('Jim.Address'); # another way to express same thing

     # first Street tag in Jim's address
     $address = $stone->get('Jim.Address.Street[0]');
     # second Street tag in Jim's address
     $address = $stone->get('Jim.Address.Street[1]');
     # last Street tag in Jim's address
     $address = $stone->get('Jim.Address.Street[#]');

     # insert a tag/value pair
     $stone->insert(Martha => { First_name => 'Martha', Last_name => 'Steward'} );

     # find the first Address
     $stone->search('Address');

     # change an existing subtree
     $martha = $stone->Martha;
     $martha->replace(Last_name => 'Stewart');  # replace a value

     # iterate over the tree with a cursor
     $cursor = $stone->cursor;
     while (my ($key,$value) = $cursor->each) {
       print "$value: Go Bluejays!\n" if $key eq 'State' and $value eq 'Katonah';
     }

     # various format conversions
     print $stone->asTable;
     print $stone->asString;
     print $stone->asHTML;
     print $stone->asXML('Person');

DESCRIPTION
===========

   A Stone, consists of a series of tag/value pairs.  Any
given tag may be single-valued or multivalued.  A value can be another
Stone, allowing nested components.  A big Stone can be made up of a lot of
little stones (pebbles?).  You can obtain a Stone from a
Boulder/Stream, or Boulder/Store,
persistent database.  Alternatively you can build your own Stones bit by
bit.

   Stones can be exported into string, XML and HTML representations.  In
addition, they are flattened into a linearized representation when reading
from or writing to a Boulder/Stream, or one of its
descendents.

   See Stone, was designed for subclassing.  You should be able
to create subclasses which create or require particular tags and data
formats.  Currently only Stone/GB_Sequence,
subclasses Stone.

CONSTRUCTORS
============

   Stones are either created by calling the new() method, or by reading
them from a Boulder/Stream, or persistent database.

$stone = Stone->new()
---------------------

   This is the main constructor for the Stone class.  It can be called
without any parameters, in which case it creates an empty Stone object (no
tags or values), or it may passed an associative array in order to
initialize it with a set of tags.  A tag's value may be a scalar, an
anonymous array reference (constructed using [] brackets), or a hash
references (constructed using {} brackets).  In the first case, the tag
will be single-valued.  In the second, the tag will be multivalued. In the
third case, a subsidiary Stone will be generated automatically and placed
into the tree at the specified location.

   Examples:

     $myStone = new Stone;
     $myStone = new Stone(Name=>'Fred',Age=>30);
     $myStone = new Stone(Name=>'Fred',
                                  Friend=>['Jill','John','Jerry']);
     $myStone = new Stone(Name=>'Fred',
                                  Friend=>['Jill',
     			      'John',
     		              'Gerald'
     			      ],
     		     Attributes => { Hair => 'blonde',
     		                     Eyes => 'blue' }
                                  );

   In the last example, a Stone with the following structure is created:

     Name        Fred
     Friend      Jill
     Friend      John
     Friend      Gerald
     Attributes  Eyes    blue
                 Hair    blonde

   Note that the value corresponding to the tag "Attributes" is itself a
Stone with two tags, "Eyes" and "Hair".

   The XML representation (which could be created with asXML()) looks like
this:

     <?xml version="1.0" standalone="yes"?>
     <Stone>
        <Attributes>
           <Eyes>blue</Eyes>
           <Hair>blonde</Hair>
        </Attributes>
        <Friend>Jill</Friend>
        <Friend>John</Friend>
        <Friend>Gerald</Friend>
        <Name>Fred</Name>
     </Stone>

   More information on Stone initialization is given in the description of
the insert() method.

OBJECT METHODS
==============

   Once a Stone object is created or retrieved, you can manipulate it with
the following methods.

$stone->insert(%hash)
---------------------

$stone->insert(\%hash)
----------------------

   This is the main method for adding tags to a Stone.  This method
expects an associative array as an argument or a reference to one.  The
contents of the associative array will be inserted into the Stone.  If a
particular tag is already present in the Stone, the tag's current value
will be appended to the list of values for that tag.  Several types of
values are legal:

   * A scalar value

     The value will be inserted into the `Stone'.

          $stone->insert(name=>Fred,
                         age=>30,
                         sex=>M);
          $stone->dump;

          name[0]=Fred
          age[0]=30
          sex[0]=M

   * An ARRAY reference

     A multi-valued tag will be created:

          $stone->insert(name=>Fred,
          	       children=>[Tom,Mary,Angelique]);
          $stone->dump;

          name[0]=Fred
          children[0]=Tom
          children[1]=Mary
          children[2]=Angelique

   * A HASH reference

     A subsidiary `Stone' object will be created and inserted into the
     object as a nested structure.

          $stone->insert(name=>Fred,
                                 wife=>{name=>Agnes,age=>40});
          $stone->dump;

          name[0]=Fred
          wife[0].name[0]=Agnes
          wife[0].age[0]=40

   * A `Stone' object or subclass

     The `Stone' object will be inserted into the object as a nested
     structure.

          $wife = new Stone(name=>agnes,
                                    age=>40);
          $husband = new Stone;
          $husband->insert(name=>fred,
                                   wife=>$wife);
          $husband->dump;

          name[0]=fred
          wife[0].name[0]=agnes
          wife[0].age[0]=40

$stone->replace(%hash)
----------------------

$stone->replace(\%hash)
-----------------------

   The replace() method behaves exactly like insert() with the exception
that if the indicated key already exists in the *Stone*, its value will be
replaced.  Use replace() when you want to enforce a single-valued
tag/value relationship.

$stone->insert_list($key,@list) =head2 $stone->insert_hash($key,%hash) =head2 $stone->replace_list($key,@list) =head2 $stone->replace_hash($key,%hash)
------------------------------------------------------------------------------------------------------------------------------------------------------

   These are primitives used by the insert() and replace() methods.
Override them if you need to modify the default behavior.

$stone->delete($tag)
--------------------

   This removes the indicated tag from the Stone.

@values = $stone->get($tag [,$index])
-------------------------------------

   This returns the value at the indicated tag and optional index.  What
you get depends on whether it is called in a scalar or list context.  In a
list context, you will receive all the values for that tag.  You may
receive a list of scalar values or (for a nested record) or a list of
Stone objects. If called in a scalar context, you will either receive the
first or the last member of the list of values assigned to the tag.  Which
one you receive depends on the value of the package variable
`$Stone::Fetchlast'.  If undefined, you will receive the first member of
the list. If nonzero, you will receive the last member.

   You may provide an optional index in order to force get() to return a
particular member of the list.  Provide a 0 to return the first member of
the list, or '#' to obtain the last member.

   If the tag contains a period (.), get() will call index() on your
behalf (see below).

   If the tag begins with an uppercase letter, then you can use the
autogenerated method to access it:

     $stone->Tag_name([$index])

   This is exactly equivalent to:

     $stone->get('Teg_name' [,$index])

@values = $stone->search($tag)
------------------------------

   Searches for the first occurrence of the tag, traversing the tree in a
breadth-first manner, and returns it.  This allows you to retrieve the
value of a tag in a deeply nested structure without worrying about all the
intermediate nodes.  For example:

     $myStone = new Stone(Name=>'Fred',
     	 	      Friend=>['Jill',
     			       'John',
     			       'Gerald'
     			      ],
     		      Attributes => { Hair => 'blonde',
     				      Eyes => 'blue' }
     		    );

     $hair_colour = $stone->search('Hair');

   The disadvantage of this is that if there is a tag named "Hair" higher
in the hierarchy, this tag will be retrieved rather than the lower one.
In an array context this method returns the complete list of values from
the matching tag.  In a scalar context, it returns either the first or the
last value of multivalued tags depending as usual on the value of
`$Stone::Fetchlast'.

   `$Stone::Fetchlast' is also consulted during the depth-first traversal.
If `$Fetchlast' is set to a true value, multivalued intermediate tags
will be searched from the last to the first rather than the first to the
last.

   The Stone object has an AUTOLOAD method that invokes get() when you
call a method that is not predefined.  This allows a very convenient type
of shortcut:

     $name        = $stone->Name;
     @friends     = $stone->Friend;
     $eye_color   = $stone->Attributes->Eyes

   In the first example, we retrieve the value of the top-level tag Name.
In the second example, we retrieve the value of the Friend tag..  In the
third example, we retrieve the attributes stone first, then the Eyes value.

   NOTE: By convention, methods are only autogenerated for tags that begin
with capital letters.  This is necessary to avoid conflict with hard-coded
methods, all of which are lower case.

@values = $stone->index($indexstr)
----------------------------------

   You can access the contents of even deeply-nested *Stone* objects with
the index method.  You provide a *tag path*, and receive a value or list
of values back.

   Tag paths look like this:

     tag1[index1].tag2[index2].tag3[index3]

   Numbers in square brackets indicate which member of a multivalued tag
you're interested in getting.  You can leave the square brackets out in
order to return just the first or the last tag of that name, in a scalar
context (depending on the setting of *$Stone::Fetchlast*).  In an array
context, leaving the square brackets out will return all multivalued
members for each tag along the path.

   You will get a scalar value in a scalar context and an array value in
an array context following the same rules as get().  You can provide an
index of '#' in order to get the last member of a list or a [?] to obtain
a randomly chosen member of the list (this uses the rand() call, so be
sure to call srand() at the beginning of your program in order to get
different sequences of pseudorandom numbers.  If there is no tag by that
name, you will receive undef or an empty list.  If the tag points to a
subrecord, you will receive a *Stone* object.

   Examples:

     # Here's what the data structure looks like.
     $s->insert(person=>{name=>Fred,
     		    age=>30,
     		    pets=>[Fido,Rex,Lassie],
     		    children=>[Tom,Mary]},
     	   person=>{name=>Harry,
     		    age=>23,
     		    pets=>[Rover,Spot]});

     # Return all of Fred's children
     @children = $s->index('person[0].children');

     # Return Harry's last pet
     $pet = $s->index('person[1].pets[#]');

     # Return first person's first child
     $child = $s->index('person.children');

     # Return children of all person's
     @children = $s->index('person.children');

     # Return last person's last pet
     $Stone::Fetchlast++;
     $pet = $s->index('person.pets');

     # Return any pet from any person
     $pet = $s->index('person[?].pet[?]');

   Note that *index()* may return a *Stone* object if the tag path points
to a subrecord.

$array = $stone->at($tag)
-------------------------

   This returns an ARRAY REFERENCE for the tag.  It is useful to prevent
automatic dereferencing.  Use with care.  It is equivalent to:

     $stone->{'tag'}

   at() will always return an array reference.  Single-valued tags will
return a reference to an array of size 1.

@tags = $stone->tags()
----------------------

   Return all the tags in the Stone.  You can then use this list with
get() to retrieve values or recursively traverse the stone.

$string = $stone->asTable()
---------------------------

   Return the data structure as a tab-delimited table suitable for
printing.

$string = $stone->asXML([$tagname])
-----------------------------------

   Return the data structure in XML format.  The entire data structure
will be placed inside a top-level tag called <Stone>.  If you wish to
change this top-level tag, pass it as an argument to asXML().

   An example follows:

     print $stone->asXML('Address_list');
     # yields:
     <?xml version="1.0" standalone="yes"?>

     <Address_list>
        <Sally>
           <Address>
              <Zip>10578</Zip>
              <City>Katonah</City>
              <Street>Hickory Street</Street>
              <State>NY</State>
           </Address>
           <Last_name>Smith</Last_name>
           <Age>30</Age>
           <First_name>Sarah</First_name>
        </Sally>
        <Jim>
           <Address>
              <Zip>11291</Zip>
              <City>Garden City</City>
              <Street>The Manse</Street>
              <Street>19 Chestnut Ln</Street>
              <State>NY</State>
           </Address>
           <Last_name>Hill</Last_name>
           <Age>34</Age>
           <First_name>James</First_name>
        </Jim>
     </Address_list>

$hash = $stone->attributes([$att_name, [$att_value]]])
------------------------------------------------------

   attributes() returns the "attributes" of a tag.  Attributes are a
series of unique tag/value pairs which are associated with a tag, but are
not contained within it.  Attributes can only be expressed in the XML
representation of a Stone:

     <Sally id="sally_tate" version="2.0">
       <Address type="postal">
            <Zip>10578</Zip>
            <City>Katonah</City>
            <Street>Hickory Street</Street>
            <State>NY</State>
         </Address>
     </Sally>

   Called with no arguments, attributes() returns the current attributes
as a hash ref:

     my $att = $stone->Address->attributes;
     my $type = $att->{type};

   Called with a single argument, attributes() returns the value of the
named attribute, or undef if not defined:

     my $type = $stone->Address->attributes('type');

   Called with two arguments, attributes() sets the named attribute:

     my $type = $stone->Address->attributes(type => 'Rural Free Delivery');

   You may also change all attributes in one fell swoop by passing a hash
reference as the single argument:

     $stone->attributes({id=>'Sally Mae',version=>'2.1'});

$string = $stone->toString()
----------------------------

   toString() returns a simple version of the Stone that shows just the
topmost tags and the number of each type of tag.  For example:

     print $stone->Jim->Address;
         #yields => Zip(1),City(1),Street(2),State(1)

   This method is used internally for string interpolation.  If you try to
print or otherwise manipulate a Stone object as a string, you will obtain
this type of string as a result.

$string = $stone->asHTML([\&callback])
--------------------------------------

   Return the data structure as a nicely-formatted HTML 3.2 table,
suitable for display in a Web browser.  You may pass this method a
callback routine which will be called for every tag/value pair in the
object.  It will be passed a two-item list containing the current tag and
value.  It can make any modifications it likes and return the modified tag
and value as a return result.  You can use this to modify tags or values
on the fly, for example to turn them into HTML links.

   For example, this code fragment will turn all tags named "Sequence"
blue:

     my $callback = sub {
           my ($tag,$value) = @_;
     	return ($tag,$value) unless $tag eq 'Sequence';
     	return ( qq(<FONT COLOR="blue">$tag</FONT>),$value );
     }
     print $stone->asHTML($callback);

Stone::dump()
-------------

   This is a debugging tool.  It iterates through the *Stone* object and
prints out all the tags and values.

   Example:

     $s->dump;

     person[0].children[0]=Tom
     person[0].children[1]=Mary
     person[0].name[0]=Fred
     person[0].pets[0]=Fido
     person[0].pets[1]=Rex
     person[0].pets[2]=Lassie
     person[0].age[0]=30
     person[1].name[0]=Harry
     person[1].pets[0]=Rover
     person[1].pets[1]=Spot
     person[1].age[0]=23

$cursor = $stone->cursor()
--------------------------

   Retrieves an iterator over the object.  You can call this several times
in order to return independent iterators. The following brief example is
described in more detail in Stone/Cursor.

     my $curs = $stone->cursor;
     while (my($tag,$value) = $curs->next_pair) {
       print "$tag => $value\n";
     }
     # yields:
       Sally[0].Address[0].Zip[0] => 10578
       Sally[0].Address[0].City[0] => Katonah
       Sally[0].Address[0].Street[0] => Hickory Street
       Sally[0].Address[0].State[0] => NY
       Sally[0].Last_name[0] => James
       Sally[0].Age[0] => 30
       Sally[0].First_name[0] => Sarah
       Jim[0].Address[0].Zip[0] => 11291
       Jim[0].Address[0].City[0] => Garden City
       Jim[0].Address[0].Street[0] => The Manse
       Jim[0].Address[0].Street[1] => 19 Chestnut Ln
       Jim[0].Address[0].State[0] => NY
       Jim[0].Last_name[0] => Hill
       Jim[0].Age[0] => 34
       Jim[0].First_name[0] => James

AUTHOR
======

   Lincoln D. Stein <lstein@cshl.org>.

COPYRIGHT
=========

   Copyright 1997-1999, Cold Spring Harbor Laboratory, Cold Spring Harbor
NY.  This module can be used and distributed on the same terms as Perl
itself.

SEE ALSO
========

   See Boulder/Blast, Boulder/Genbank,
see Boulder/Medline,
Boulder/Unigene, Boulder/Omim,
`Boulder::SwissProt' in this node

Traverse tags and values of a Stone
***********************************

NAME
====

   Stone::Cursor - Traverse tags and values of a Stone

SYNOPSIS
========

     use Boulder::Store;
     $store = Boulder::Store->new('./soccer_teams');

     my $stone = $store->get(28);
     $cursor = $stone->cursor;
     while (my ($key,$value) = $cursor->each) {
       print "$value: Go Bluejays!\n" if $key eq 'State' and $value eq 'Katonah';
     }

DESCRIPTION
===========

   Boulder::Cursor is a utility class that allows you to create one or
more iterators across a Stone, object.  This is used for
traversing large Stone objects in order to identify or modify portions of
the record.

CLASS METHODS
-------------

Boulder::Cursor->new($stone)
     Return a new Boulder::Cursor over the specified Stone,
     object.  This will return an error if the object is not a
     Stone, or a descendent. This method is usually not called
     directly, but rather indirectly via the Stone, cursor()
     method:

          my $cursor = $stone->cursor;

OBJECT METHODS
--------------

$cursor->each()
     Iterate over the attached *Stone*.  Each iteration will return a
     two-valued list consisting of a tag path and a value.  The tag path is
     of a form that can be used with *Stone::index()* (in fact, a cursor
     is used internally to implement the Stone::dump() method.  When the
     end of the *Stone* is reached, `each()' will return an empty list,
     after which it will start over again from the beginning.  If you
     attempt to insert or delete from the stone while iterating over it,
     all attached cursors will reset to the beginnning.

     For example:

          $cursor = $s->cursor;
          while (($key,$value) = $cursor->each) {
                     print "$value: BOW WOW!\n" if $key=~/pet/;
          }

$cursor->reset()
     This resets the cursor back to the beginning of the associated
     *Stone*.

AUTHOR
======

   Lincoln D. Stein <lstein@cshl.org>.

COPYRIGHT
=========

   Copyright 1997-1999, Cold Spring Harbor Laboratory, Cold Spring Harbor
NY.  This module can be used and distributed on the same terms as Perl
itself.

SEE ALSO
========

   See Boulder, Stone,

Specialized Access to GenBank Records
*************************************

NAME
====

   Stone::GB_Sequence - Specialized Access to GenBank Records

SYNOPSIS
========

     use Boulder::Genbank;  # No need to use Stone::GB_Sequence directly
     $gb = Boulder::Genbank->newFh qw(M57939 M28274 L36028);

     while ($entry = <$gb>) {
       print "Entry's length is ",$entry->length,"\n";
       @cds   = $entry->match_features(-type=>'CDS');
       @exons = $entry->match_features(-type=>'Exon',-start=>100,-end=>300);
     }
     }

DESCRIPTION
===========

   Stone::GB_Sequence provides several specialized access methods to the
various fields in a GenBank flat file record.  You can return the sequence
as a Bio::Seq object, or query the sequence for features that match
positional or descriptional criteria that you provide.

CONSTRUCTORS
============

   This class is not intended to be created directly, but via a
Boulder/Genbank, stream.

METHODS
=======

   In addition to the standard Stone, methods and accessors,
the following methods are provided.  In the synopses, the variable $entry
refers to a previously-created Stone::GB_Sequence object.

$length = $entry->length
------------------------

   Get the length of the sequence.

$start = $entry->start
----------------------

   Get the start position of the sequence, currently always "1".

$end = $entry->end
------------------

   Get the end position of the sequence, currently always the same as the
length.

@feature_list = $entry->features(-pos=>[50,450],-type=>['CDS','Exon'])
----------------------------------------------------------------------

   features() will search the entry feature list for those features that
meet certain criteria.  The criteria are specified using the *-pos* and/or
*-type* argument names, as shown below.

-pos
     Provide a position or range of positions which the feature must
     overlap.  A single position is specified in this way:

          -pos => 1500;         # feature must overlap postion 1500

     or a range of positions in this way:

          -pos => [1000,1500];  # 1000 to 1500 inclusive

     If no criteria are provided, then features() returns all the features,
     and is equivalent to calling the Features() accessor.

-type, -types
     Filter the list of features by type or a set of types.  Matches are
     case-insensitive, so "exon", "Exon" and "EXON" are all equivalent.
     You may call with a single type as in:

          -type => 'Exon'

     or with a list of types, as in

          -types => ['Exon','CDS']

     The names "-type" and "-types" can be used interchangeably.

$seqObj = $entry->bioSeq;
-------------------------

   Returns a Bio/Seq, object from the Bioperl project.
Dies with an error message unless the Bio::Seq module is installed.

AUTHOR
======

   Lincoln D. Stein <lstein@cshl.org>.

COPYRIGHT
=========

   Copyright 1997-1999, Cold Spring Harbor Laboratory, Cold Spring Harbor
NY.  This module can be used and distributed on the same terms as Perl
itself.

SEE ALSO
========

   See Boulder, `Boulder:Genbank' in this node, see Stone,

persistency for perl data structures
************************************

NAME
====

   Storable - persistency for perl data structures

SYNOPSIS
========

     use Storable;
     store \%table, 'file';
     $hashref = retrieve('file');

     use Storable qw(nstore store_fd nstore_fd freeze thaw dclone);

     # Network order
     nstore \%table, 'file';
     $hashref = retrieve('file');	# There is NO nretrieve()

     # Storing to and retrieving from an already opened file
     store_fd \@array, \*STDOUT;
     nstore_fd \%table, \*STDOUT;
     $aryref = fd_retrieve(\*SOCKET);
     $hashref = fd_retrieve(\*SOCKET);

     # Serializing to memory
     $serialized = freeze \%table;
     %table_clone = %{ thaw($serialized) };

     # Deep (recursive) cloning
     $cloneref = dclone($ref);

     # Advisory locking
     use Storable qw(lock_store lock_nstore lock_retrieve)
     lock_store \%table, 'file';
     lock_nstore \%table, 'file';
     $hashref = lock_retrieve('file');

DESCRIPTION
===========

   The Storable package brings persistency to your perl data structures
containing SCALAR, ARRAY, HASH or REF objects, i.e. anything that can be
convenientely stored to disk and retrieved at a later time.

   It can be used in the regular procedural way by calling store with a
reference to the object to be stored, along with the file name where the
image should be written.  The routine returns undef for I/O problems or
other internal error, a true value otherwise. Serious errors are
propagated as a die exception.

   To retrieve data stored to disk, use retrieve with a file name, and the
objects stored into that file are recreated into memory for you, a
reference to the root object being returned. In case an I/O error occurs
while reading, undef is returned instead. Other serious errors are
propagated via die.

   Since storage is performed recursively, you might want to stuff
references to objects that share a lot of common data into a single array
or hash table, and then store that object. That way, when you retrieve
back the whole thing, the objects will continue to share what they
originally shared.

   At the cost of a slight header overhead, you may store to an already
opened file descriptor using the `store_fd' routine, and retrieve from a
file via `fd_retrieve'. Those names aren't imported by default, so you
will have to do that explicitely if you need those routines.  The file
descriptor you supply must be already opened, for read if you're going to
retrieve and for write if you wish to store.

     store_fd(\%table, *STDOUT) || die "can't store to stdout\n";
     $hashref = fd_retrieve(*STDIN);

   You can also store data in network order to allow easy sharing across
multiple platforms, or when storing on a socket known to be remotely
connected. The routines to call have an initial n prefix for *network*, as
in `nstore' and `nstore_fd'. At retrieval time, your data will be
correctly restored so you don't have to know whether you're restoring from
native or network ordered data.  Double values are stored stringified to
ensure portability as well, at the slight risk of loosing some precision
in the last decimals.

   When using `fd_retrieve', objects are retrieved in sequence, one object
(i.e. one recursive tree) per associated `store_fd'.

   If you're more from the object-oriented camp, you can inherit from
Storable and directly store your objects by invoking store as a method.
The fact that the root of the to-be-stored tree is a blessed reference
(i.e. an object) is special-cased so that the retrieve does not provide a
reference to that object but rather the blessed object reference itself.
(Otherwise, you'd get a reference to that blessed object).

MEMORY STORE
============

   The Storable engine can also store data into a Perl scalar instead, to
later retrieve them. This is mainly used to freeze a complex structure in
some safe compact memory place (where it can possibly be sent to another
process via some IPC, since freezing the structure also serializes it in
effect). Later on, and maybe somewhere else, you can thaw the Perl scalar
out and recreate the original complex structure in memory.

   Surprisingly, the routines to be called are named `freeze' and `thaw'.
If you wish to send out the frozen scalar to another machine, use
`nfreeze' instead to get a portable image.

   Note that freezing an object structure and immediately thawing it
actually achieves a deep cloning of that structure:

     dclone(.) = thaw(freeze(.))

   Storable provides you with a `dclone' interface which does not create
that intermediary scalar but instead freezes the structure in some
internal memory space and then immediatly thaws it out.

ADVISORY LOCKING
================

   The `lock_store' and `lock_nstore' routine are equivalent to store and
`nstore', only they get an exclusive lock on the file before writing.
Likewise, `lock_retrieve' performs as retrieve, but also gets a shared
lock on the file before reading.

   Like with any advisory locking scheme, the protection only works if you
systematically use `lock_store' and `lock_retrieve'.  If one side of your
application uses store whilst the other uses `lock_retrieve', you will get
no protection at all.

   The internal advisory locking is implemented using Perl's flock()
routine.  If your system does not support any form of flock(), or if you
share your files across NFS, you might wish to use other forms of locking
by using modules like LockFile::Simple which lock a file using a filesystem
entry, instead of locking the file descriptor.

SPEED
=====

   The heart of Storable is written in C for decent speed. Extra low-level
optimization have been made when manipulating perl internals, to sacrifice
encapsulation for the benefit of a greater speed.

CANONICAL REPRESENTATION
========================

   Normally Storable stores elements of hashes in the order they are
stored internally by Perl, i.e. pseudo-randomly.  If you set
`$Storable::canonical' to some TRUE value, Storable will store hashes with
the elements sorted by their key.  This allows you to compare data
structures by comparing their frozen representations (or even the
compressed frozen representations), which can be useful for creating
lookup tables for complicated queries.

   Canonical order does not imply network order, those are two orthogonal
settings.

ERROR REPORTING
===============

   Storable uses the "exception" paradigm, in that it does not try to
workaround failures: if something bad happens, an exception is generated
from the caller's perspective (see Carp, and `croak()').  Use
eval {} to trap those exceptions.

   When Storable croaks, it tries to report the error via the `logcroak()'
routine from the `Log::Agent' package, if it is available.

   Normal errors are reported by having store() or retrieve() return undef.
Such errors are usually I/O errors (or truncated stream errors at
retrieval).

WIZARDS ONLY
============

Hooks
-----

   Any class may define hooks that will be called during the serialization
and deserialization process on objects that are instances of that class.
Those hooks can redefine the way serialization is performed (and therefore,
how the symetrical deserialization should be conducted).

   Since we said earlier:

     dclone(.) = thaw(freeze(.))

   everything we say about hooks should also hold for deep cloning.
However, hooks get to know whether the operation is a mere serialization,
or a cloning.

   Therefore, when serializing hooks are involved,

     dclone(.) <> thaw(freeze(.))

   Well, you could keep them in sync, but there's no guarantee it will
always hold on classes somebody else wrote.  Besides, there is little to
gain in doing so: a serializing hook could only keep one attribute of an
object, which is probably not what should happen during a deep cloning of
that same object.

   Here is the hooking interface:

`STORABLE_freeze' *obj*, cloning
     The serializing hook, called on the object during serialization.  It
     can be inherited, or defined in the class itself, like any other
     method.

     Arguments: *obj* is the object to serialize, cloning is a flag
     indicating whether we're in a dclone() or a regular serialization via
     store() or freeze().

     Returned value: A LIST `($serialized, $ref1, $ref2, ...)' where
     $serialized is the serialized form to be used, and the optional
     $ref1, $ref2, etc... are extra references that you wish to let the
     Storable engine serialize.

     At deserialization time, you will be given back the same LIST, but
     all the extra references will be pointing into the deserialized
     structure.

     The *first time* the hook is hit in a serialization flow, you may
     have it return an empty list.  That will signal the Storable engine
     to further discard that hook for this class and to therefore revert
     to the default serialization of the underlying Perl data.  The hook
     will again be normally processed in the next serialization.

     Unless you know better, serializing hook should always say:

          sub STORABLE_freeze {
              my ($self, $cloning) = @_;
              return if $cloning;         # Regular default serialization
              ....
          }

     in order to keep reasonable dclone() semantics.

`STORABLE_thaw' *obj*, cloning, *serialized*, ...
     The deserializing hook called on the object during deserialization.
     But wait. If we're deserializing, there's no object yet... right?

     Wrong: the Storable engine creates an empty one for you.  If you know
     Eiffel, you can view `STORABLE_thaw' as an alternate creation routine.

     This means the hook can be inherited like any other method, and that
     *obj* is your blessed reference for this particular instance.

     The other arguments should look familiar if you know
     `STORABLE_freeze': cloning is true when we're part of a deep clone
     operation, *serialized* is the serialized string you returned to the
     engine in `STORABLE_freeze', and there may be an optional list of
     references, in the same order you gave them at serialization time,
     pointing to the deserialized objects (which have been processed
     courtesy of the Storable engine).

     When the Storable engine does not find any `STORABLE_thaw' hook
     routine, it tries to load the class by requiring the package
     dynamically (using the blessed package name), and then re-attempts
     the lookup.  If at that time the hook cannot be located, the engine
     croaks.  Note that this mechanism will fail if you define several
     classes in the same file, but perlmod(1) warned you.

     It is up to you to use these information to populate *obj* the way
     you want.

     Returned value: none.

Predicates
----------

   Predicates are not exportable.  They must be called by explicitely
prefixing them with the Storable package name.

`Storable::last_op_in_netorder'
     The `Storable::last_op_in_netorder()' predicate will tell you whether
     network order was used in the last store or retrieve operation.  If
     you don't know how to use this, just forget about it.

`Storable::is_storing'
     Returns true if within a store operation (via STORABLE_freeze hook).

`Storable::is_retrieving'
     Returns true if within a retrieve operation, (via STORABLE_thaw hook).

Recursion
---------

   With hooks comes the ability to recurse back to the Storable engine.
Indeed, hooks are regular Perl code, and Storable is convenient when it
comes to serialize and deserialize things, so why not use it to handle the
serialization string?

   There are a few things you need to know however:

   * You can create endless loops if the things you serialize via freeze()
     (for instance) point back to the object we're trying to serialize in
     the hook.

   * Shared references among objects will not stay shared: if we're
     serializing the list of object [A, C] where both object A and C refer
     to the SAME object B, and if there is a serializing hook in A that
     says freeze(B), then when deserializing, we'll get [A', C'] where A'
     refers to B', but C' refers to D, a deep clone of B'.  The topology
     was not preserved.

   That's why `STORABLE_freeze' lets you provide a list of references to
serialize.  The engine guarantees that those will be serialized in the
same context as the other objects, and therefore that shared objects will
stay shared.

   In the above [A, C] example, the `STORABLE_freeze' hook could return:

     ("something", $self->{B})

   and the B part would be serialized by the engine.  In `STORABLE_thaw',
you would get back the reference to the B' object, deserialized for you.

   Therefore, recursion should normally be avoided, but is nonetheless
supported.

Deep Cloning
------------

   There is a new Clone module available on CPAN which implements deep
cloning natively, i.e. without freezing to memory and thawing the result.
It is aimed to replace Storable's dclone() some day.  However, it does not
currently support Storable hooks to redefine the way deep cloning is
performed.

EXAMPLES
========

   Here are some code samples showing a possible usage of Storable:

     use Storable qw(store retrieve freeze thaw dclone);

     %color = ('Blue' => 0.1, 'Red' => 0.8, 'Black' => 0, 'White' => 1);

     store(\%color, '/tmp/colors') or die "Can't store %a in /tmp/colors!\n";

     $colref = retrieve('/tmp/colors');
     die "Unable to retrieve from /tmp/colors!\n" unless defined $colref;
     printf "Blue is still %lf\n", $colref->{'Blue'};

     $colref2 = dclone(\%color);

     $str = freeze(\%color);
     printf "Serialization of %%color is %d bytes long.\n", length($str);
     $colref3 = thaw($str);

   which prints (on my machine):

     Blue is still 0.100000
     Serialization of %color is 102 bytes long.

WARNING
=======

   If you're using references as keys within your hash tables, you're bound
to disapointment when retrieving your data. Indeed, Perl stringifies
references used as hash table keys. If you later wish to access the items
via another reference stringification (i.e. using the same reference that
was used for the key originally to record the value into the hash table),
it will work because both references stringify to the same string.

   It won't work across a store and retrieve operations however, because
the addresses in the retrieved objects, which are part of the stringified
references, will probably differ from the original addresses. The topology
of your structure is preserved, but not hidden semantics like those.

   On platforms where it matters, be sure to call binmode() on the
descriptors that you pass to Storable functions.

   Storing data canonically that contains large hashes can be
significantly slower than storing the same data normally, as temprorary
arrays to hold the keys for each hash have to be allocated, populated,
sorted and freed.  Some tests have shown a halving of the speed of storing
- the exact penalty will depend on the complexity of your data.  There is
no slowdown on retrieval.

BUGS
====

   You can't store GLOB, CODE, FORMLINE, etc... If you can define
semantics for those operations, feel free to enhance Storable so that it
can deal with them.

   The store functions will croak if they run into such references unless
you set `$Storable::forgive_me' to some TRUE value. In that case, the
fatal message is turned in a warning and some meaningless string is stored
instead.

   Setting `$Storable::canonical' may not yield frozen strings that
compare equal due to possible stringification of numbers. When the string
version of a scalar exists, it is the form stored, therefore if you happen
to use your numbers as strings between two freezing operations on the same
data structures, you will get different results.

   When storing doubles in network order, their value is stored as text.
However, you should also not expect non-numeric floating-point values such
as infinity and "not a number" to pass successfully through a
nstore()/retrieve() pair.

   As Storable neither knows nor cares about character sets (although it
does know that characters may be more than eight bits wide), any difference
in the interpretation of character codes between a host and a target
system is your problem.  In particular, if host and target use different
code points to represent the characters used in the text representation of
floating-point numbers, you will not be able be able to exchange
floating-point data, even with nstore().

CREDITS
=======

   Thank you to (in chronological order):

     Jarkko Hietaniemi <jhi@iki.fi>
     Ulrich Pfeifer <pfeifer@charly.informatik.uni-dortmund.de>
     Benjamin A. Holzman <bah@ecnvantage.com>
     Andrew Ford <A.Ford@ford-mason.co.uk>
     Gisle Aas <gisle@aas.no>
     Jeff Gresham <gresham_jeffrey@jpmorgan.com>
     Murray Nesbitt <murray@activestate.com>
     Marc Lehmann <pcg@opengroup.org>
     Justin Banks <justinb@wamnet.com>
     Jarkko Hietaniemi <jhi@iki.fi> (AGAIN, as perl 5.7.0 Pumpkin!)
     Salvador Ortiz Garcia <sog@msg.com.mx>
     Dominic Dunlop <domo@computer.org>
     Erik Haugan <erik@solbors.no>

   for their bug reports, suggestions and contributions.

   Benjamin Holzman contributed the tied variable support, Andrew Ford
contributed the canonical order for hashes, and Gisle Aas fixed a few
misunderstandings of mine regarding the Perl internals, and optimized the
emission of "tags" in the output streams by simply counting the objects
instead of tagging them (leading to a binary incompatibility for the
Storable image starting at version 0.6-older images are of course still
properly understood).  Murray Nesbitt made Storable thread-safe.  Marc
Lehmann added overloading and reference to tied items support.

TRANSLATIONS
============

   There is a Japanese translation of this man page available at
http://member.nifty.ne.jp/hippo2000/perltips/storable.htm , courtesy of
Kawai, Takanori <kawai@nippon-rad.co.jp>.

AUTHOR
======

   Raphael Manfredi `<Raphael_Manfredi@pobox.com>'

SEE ALSO
========

   Clone(3).

Perl extension for approximate matching (fuzzy matching)
********************************************************

NAME
====

   String::Approx - Perl extension for approximate matching (fuzzy
matching)

SYNOPSIS
========

     use String::Approx 'amatch';

     print if amatch("foobar");

     my @matches = amatch("xyzzy", @inputs);

     my @catches = amatch("plugh", ['2'], @inputs);

DESCRIPTION
===========

   String::Approx lets you match and substitute strings approximately.
With this you can emulate errors: typing errorrs, speling errors, closely
related vocabularies (colour color), genetic mutations (GAG ACT),
abbreviations (McScot, MacScot).

   The measure of *approximateness* is the *Levenshtein edit distance*.
It is the total number of "edits": insertions,

     word world

   deletions,

     monkey money

   and substitutions

     sun fun

   required to transform a string to another string.  For example, to
transform *"lead"* into *"gold"*, you need three edits:

     lead gead goad gold

   The edit distance of "lead" and "gold" is therefore three.

MATCH
=====

     use String::Approx 'amatch';

     $matched     = amatch("pattern")
     $matched     = amatch("pattern", [ modifiers ])

     $any_matched = amatch("pattern", @inputs)
     $any_matched = amatch("pattern", [ modifiers ], @inputs)

     @match       = amatch("pattern")
     @match       = amatch("pattern", [ modifiers ])

     @matches     = amatch("pattern", @inputs)
     @matches     = amatch("pattern", [ modifiers ], @inputs)

   Match pattern approximately.  In list context return the matched
*@inputs*.  If no inputs are given, match against the $_.  In scalar
context return true if any of the inputs match, false if none match.

   Notice that the pattern is a string.  Not a regular expression.  None
of the regular expression notations (^, ., *, and so on) work.  They are
characters just like the others.  Note-on-note: some limited form of
*"regular expressionism"* is planned in future: for example character
classes ([abc]) and *any-chars* (.).  But that feature will be turned on
by a special *modifier* (just a guess: "r"), so there should be no
backward compatibility problem.

   Notice also that matching is not symmetric.  The inputs are matched
against the pattern, not the other way round.  In other words: the pattern
can be a substring, a submatch, of an input element.  An input element is
always a superstring of the pattern.

MODIFIERS
---------

   With the modifiers you can control the amount of approximateness and
certain other control variables.  The modifiers are one or more strings,
for example `"i"', within a string optionally separated by whitespace.
The modifiers are inside an anonymous array: the `[ ]' in the syntax are
not notational, they really do mean `[ ]', for example `[ "i", "2" ]'.
`["2 i"]' would be identical.

   The implicit default approximateness is 10%, rounded up.  In other
words: every tenth character in the pattern may be an error, an edit.  You
can explicitly set the maximum approximateness by supplying a modifier like

     number
     number%

   Examples: `"3"', `"15%"'.

   Using a similar syntax you can separately control the maximum number of
insertions, deletions, and substitutions by prefixing the numbers with I,
D, or S, like this:

     Inumber
     Inumber%
     Dnumber
     Dnumber%
     Snumber
     Snumber%

   Examples: `"I2"', `"D20%"', `"S0"'.

   You can ignore case (`"A"' becames equal to `"a"' and vice versa) by
adding the `"i"' modifier.

   For example

     [ "i 25%", "S0" ]

   means *ignore case*, *allow every fourth character to be "an edit"*,
but allow *no substitutions*.  (See `NOTES' in this node about disallowing
substitutions or insertions.)

SUBSTITUTE
==========

     use String::Approx 'asubstitute';

     @substituted = asubstitute("pattern", "replacement")
     @substituted = asubstitute("pattern", "replacement", @inputs)
     @substituted = asubstitute("pattern", "replacement", [ modifiers ])
     @substituted = asubstitute("pattern", "replacement",
     			   [ modifiers ], @inputs)

   Substitute approximate pattern with replacement and return as a list
<copies> of *@inputs*, the substitutions having been made on the elements
that did match the pattern.  If no inputs are given, substitute in the $_.
The replacement can contain magic strings $&, $`, $' that stand for the
matched string, the string before it, and the string after it,
respectively.  All the other arguments are as in `amatch()', plus one
additional modifier, `"g"' which means substitute globally (all the
matches in an element and not just the first one, as is the default).

   See `BAD NEWS' in this node about the unfortunate stinginess of
`asubstitute()'.

INDEX
=====

     use String::Approx 'aindex';

     $index   = aindex("pattern")
     @indices = aindex("pattern", @inputs)
     $index   = aindex("pattern", [ modifiers ])
     @indices = aindex("pattern", [ modifiers ], @inputs)

   Like `amatch()' but returns the index/indices at which the pattern
matches approximately.  In list context and if `@inputs' are used, returns
a list of indices, one index for each input element.  If there's no
approximate match, `-1' is returned as the index.

   There's also backwards-scanning `arindex()'.

SLICE
=====

     use String::Approx 'aindex';

     ($index, $size)   = aslice("pattern")
     ([$i0, $s0], ...) = aslice("pattern", @inputs)
     ($index, $size)   = aslice("pattern", [ modifiers ])
     ([$i0, $s0], ...) = aslice("pattern", [ modifiers ], @inputs)

   Like `aindex()' but returns also the size of the match.  If the match
fails, returns an empty list (when matching against $_) or an empty
anonymous list corresponding to the particular input.

   Note that the size of the match will very probably be something you did
not expect (such as longer than the pattern).  This may or may not be
fixed in future releases.

   If the modifier

     "minimal_distance"

   is used, the minimal possible edit distance is returned as the third
element:

     ($index, $size, $distance) = aslice("pattern", [ modifiers ])
     ([$i0, $s0, $d0], ...)     = aslice("pattern", [ modifiers ], @inputs)

DISTANCE
========

     use String::Approx 'adist';

     $dist = adist("pattern", $input);
     @dist = adist("pattern", @input);

   Return the *edit distance* or distances between the pattern and the
input or inputs.  Zero edit distance means exact match.  (Remember that
the match can 'float' in the inputs, the match is a substring match.)  If
the pattern is longer than the input or inputs, the returned distance or
distance is or are negative.

     use String::Approx 'adistr';

     $dist = adistr("pattern", $input);
     @dist = adistr("pattern", @inputs);

   Return the relative *edit distance* or distances between the pattern
and the input or inputs.  Zero relative edit distance means exact match,
one means completely different.  (Remember that the match can 'float' in
the inputs, the match is a substring match.)  If the pattern is longer
than the input or inputs, the returned distance or distances is or are
negative.

CONTROLLING THE CACHE
=====================

   `String::Approx' maintains a LU (least-used) cache that holds the
'matching engines' for each instance of a *pattern+modifiers*.  The cache
is intended to help the case where you match a small set of patterns
against a large set of string.  However, the more engines you cache the
more you eat memory.  If you have a lot of different patterns or if you
have a lot of memory to burn, you may want to control the cache yourself.
For example, allowing a larger cache consumes more memory but probably
runs a little bit faster since the cache fills (and needs flushing) less
often.

   The cache has two parameters: max and purge.  The first one is the
maximum size of the cache and the second one is the cache flushing ratio:
when the number of cache entries exceeds max, max times purge cache
entries are flushed.  The default values are 1000 and 0.75, respectively,
which means that when the 1001st entry would be cached, 750 least used
entries will be removed from the cache.  To access the parameters you can
use the calls

     $now_max = String::Approx::cache_max();
     String::Approx::cache_max($new_max);

     $now_purge = String::Approx::cache_purge();
     String::Approx::cache_purge($new_purge);

     $limit = String::Approx::cache_n_purge();

   To be honest, there are actually *two* caches: the first one is used
far the patterns with no modifiers, the second one for the patterns with
pattern modifiers.  Using the standard parameters you will therefore
actually cache up to 2000 entries.  The above calls control both caches
for the same price.

   To disable caching completely use

     String::Approx::cache_disable();

   Note that this doesn't flush any possibly existing cache entries, to do
that use

     String::Approx::cache_flush_all();

NOTES
=====

   Because matching is by *substrings*, not by whole strings, insertions
and substitutions produce often very similar results: "abcde" matches
"axbcde" either by insertion or substitution of "x".

   The maximum edit distance is also the maximum number of edits.  That
is, the `"I2"' in

     amatch("abcd", ["I2"])

   is useless because the maximum edit distance is (implicitly) 1.  You
may have meant to say

     amatch("abcd", ["2D1S1"])

   or something like that.

   If you want to simulate transposes

     feet fete

   you need to allow at least edit distance of two because in terms of our
edit primitives a transpose is first one deletion and then one insertion.

TEXT POSITION
-------------

   The starting and ending positions of matching, substituting, indexing,
or slicing can be changed from the beginning and end of the input(s) to
some other positions by using either or both of the modifiers

     "initial_position=24"
     "final_position=42"

   or the both the modifiers

     "initial_position=24"
     "position_range=10"

   By setting the `"position_range"' to be zero you can limit (anchor) the
operation to happen only once (if a match is possible) at the position.

VERSION
=======

   Major release 3.

CHANGES FROM VERSION 2
======================

GOOD NEWS
---------

The version 3 is 2-3 times faster than version 2
No pattern length limitation
     The algorithm is independent on the pattern length: its time
     complexity is *O(kn)*, where k is the number of edits and n the
     length of the text (input).  The preprocessing of the pattern will of
     course take some *O(m)* (m being the pattern length) time, but
     `amatch()' and `asubstitute()' cache the result of this preprocessing
     so that it is done only once per pattern.

BAD NEWS
--------

You do need a C compiler to install the module
     Perl's regular expressions are no more used; instead a faster and more
     scalable algorithm written in C is used.

`asubstitute()' is now always stingy
     The string matched and substituted is now always stingy, as short as
     possible.  It used to be as long as possible.  This is an unfortunate
     change stemming from switching the matching algorithm.  Example: with
     edit distance of two and substituting for `"word"' from `"cork"' and
     `"wool"' previously did match `"cork"' and `"wool"'.  Now it does
     match `"or"' and `"wo"'.  As little as possible, or, in other words,
     with as much approximateness, as many edits, as possible.  Because
     there is no *need* to match the `"c"' of `"cork"', it is not matched.

no more `aregex()' because regular expressions are no more used
no more `compat1' for String::Approx version 1 compatibility
ACKNOWLEDGEMENTS
================

   The following people have provided valuable test cases, documentation
clarifications, and other feedback:

   Jared August, Anirvan Chatterjee, Steve A. Chervitz, Aldo Calpini,
David Curiel, Teun van den Dool, Alberto Fontaneda, Rob Fugina, Dmitrij
Frishman, Lars Gregersen, Kevin Greiner, B. Elijah Griffin, Mike Hanafey,
Mitch Helle, Ricky Houghton, Helmut Jarausch, Damian Keefe, Ben Kennedy,
Craig Kelley, Franz Kirsch, Dag Kristian, Mark Land, J. D. Laub, Sergey
Novoselov, Andy Oram, Eric Promislow, Nikolaus Rath, Stefan Ram, Dag
Kristian Rognlien, Stewart Russell, Slaven Rezic, Chris Rosin, Ilya
Sandler, Bob J.A. Schijvenaars, Ross Smith, Frank Tobin, Greg Ward, Rick
Wise.

   The matching algorithm was developed by Udi Manber, Sun Wu, and Burra
Gopal in the Department of Computer Science, University of Arizona.

AUTHOR
======

   Jarkko Hietaniemi <jhi@iki.fi>

count number of "1" bits in string
**********************************

NAME
====

   String::BitCount, BitCount showBitCount - count number of "1" bits in
string

SYNOPSIS
========

     use String::BitCount;

DESCRIPTION
===========

BitCount LIST
     Joins the elements of LIST into a single string and returns the the
     number of bits in this string.

showBitCount LIST
     Copies the elements of LIST to a new list and converts the new
     elements to strings of digits showing the number of set bits in the
     original byte.  In array context returns the new list.  In scalar
     context joins the elements of the new list into a single string and
     returns the string.

AUTHOR
======

   Winfried Koenig <win@in.rhein-main.de>

SEE ALSO
========

   perl(1)

Perl interface cyclic redundency check generation
*************************************************

NAME
====

   CRC - Perl interface cyclic redundency check generation

SYNOPSIS
========

     use String::CRC;

     ($crc_low, $crc_high) = crc("some string", 64);
     $crc_binary = crc("some string", 64);
     ($crc_low, $crc_high) = unpack("LL", $crc_binary);
     ($crc_small) = crc("some string", 32);

DESCRIPTION
===========

   The *CRC* module calculates CRC of various lenghts.  The default CRC
length is 32 bits.

   CRCs of 32 bits and smaller will be returned as an integer.

   CRCs that are larger than 32 bits will be returned as two integers if
called in list context and as a packed binary string if called in scalar
context.

COPYRIGHT
=========

   Taken from Matt Dillon's Diablo distribution with permission.

   The authors of this package (David Sharnoff & Matthew Dillon) disclaim
all copyrights and release it into the public domain.

Perl interface for cyclic redundency check generation
*****************************************************

NAME
====

   CRC32 - Perl interface for cyclic redundency check generation

SYNOPSIS
========

     use String::CRC32;

     $crc = crc32("some string");
     $crc = crc32("some string", initvalue);

     $somestring = "some string";
     $crc = crc32($somestring);

     open(SOMEFILE, "location/of/some.file");
     $crc = crc32(*SOMEFILE);
     close(SOMEFILE);

DESCRIPTION
===========

   The *CRC32* module calculates CRC sums of 32 bit lenghts.  It generates
the same CRC values as ZMODEM, PKZIP, PICCHECK and many others.

   Despite its name, this module is able to compute the checksum of
strings as well as of files.

EXAMPLES
========

     $crc = crc32("some string");

     results in the same as

     $crc = crc32(" string", crc32("some"));

   This is useful for subsequent CRC checking of substrings.

   You may even check files:

     open(SOMEFILE, "location/of/some.file");
     $crc = crc32(*SOMEFILE);
     close(SOMEFILE);

   A init value may also been supplied in the above example.

AUTHOR
======

   Soenke J. Peters <peters@simprovement.com>

   Please be so kind as to report any bugs/suggestions to the above
address.

COPYRIGHT
=========

   CRC algorithm code taken from CRC-32 by Craig Bruce.  The module stuff
is inspired by a similar perl module called String::CRC by David Sharnoff
& Matthew Dillon.  Horst Fickenscher told me that it could be useful to
supply an init value to the crc checking function and so I included this
possibility.

   The author of this package disclaims all copyrights and releases it
into the public domain

An extensible string validation module (allowing commonly used checks on strings to be called more concisely and consistently).
*******************************************************************************************************************************

NAME
====

   String::Checker - An extensible string validation module (allowing
commonly used checks on strings to be called more concisely and
consistently).

SYNOPSIS
========

     use String::Checker;

     String::Checker::register_check($checkname, \&sub);
     $return = String::Checker::checkstring($string, [ expectation, ... ]);

DESCRIPTION
===========

   This is a very simple library for checking a string against a given set
of expectations.  It contains a number of pre-defined expectations which
can be used, and can also be extended to perform any arbitrary match or
modification on a string.

   Why is this useful?  If you're only checking one string, it probably
isn't.  However, if you're checking a bunch of strings (say, for example,
CGI input parameters) against a set of expectations, this comes in pretty
handy.  As a matter of fact, the CGI::ArgChecker module is a simple,
CGI.pm aware wrapper for this library.

Checking a string
-----------------

   The checkstring function takes a string scalar and a reference to a
list of 'expectations' as arguments, and outputs a reference to a list,
containing the names of the expectations which failed.

   Each expectation, in turn, can either be a string scalar (the name of
the expectation) or a two-element array reference (the first element being
the name of the expectation, and second element being the argument to that
expectation.)  For example:

     $string = "foo";
     String::Checker::checkstring($string, [ 'allow_empty',
                                             [ 'max' => 20 ] ] );

   Note that the expectations are run in order.  In the above case, for
example, the 'allow_empty' expectation would be checked first, followed by
the 'max' expectation with an argument of 20.

Defined checks
--------------

   The module predefines a number of checks.  They are:

allow_empty
     Never fails - will convert an undef scalar to an empty string, though.

disallow_empty
     Fails if the input string is either undef or empty.

min
     Fails if the length of the input string is less than the numeric
     value of it's single argument.

max
     Fails if the length of the input string is more than the numeric
     value of it's single argument.

want_int
     Fails if the input string does not solely consist of numeric
     characters.

want_float
     Fails if the argument does not solely consist of numeric characters,
     plus an optional single '.'.

allow_chars
     Fails if the input string contains characters other than those in its
     argument.

disallow_chars
     Fails if the input string contains any of the characters in its
     argument.

upcase
     Never fails - converts the string to upper case.

downcase
     Never fails - converts the string to lower case.

stripxws
     Never fails - strips leading and trailing whitespace from the string.

enum
     Fails if the input string does not precisely match at least one of the
     elements of the array reference it takes as an argument.

match
     Fails if the input string does not match the regular expression it
     takes as an argument.

want_email
     Fails if the input string does not match the regular expression:
     ^\S+\@@[\w-]+\.[\w\.-]+$

want_phone
     Fails if the input string does not match the regular expression
     ^[0-9+.()-]*$

want_date
     Interprets the input string as a date, if possible.  This will fail
     if it can't figure out a date from the input.  In addition, it is
     possible to use this to standardize date input.  Pass a formatting
     string (see the strftime(3) man page) as an argument to this check,
     and the string will be formatted appropriately if possible.  This is
     based on the Date::Manip(1) module, so that documentation might prove
     valuable if you're using this check.

Extension checks
----------------

   Use register_check to register a new expectation checking routine.  This
function should be passed a new expectation name and a code reference.

   This code reference will be called every time the expectation name is
seen, with either one or two arguments.  The first argument will always be
a reference to the input string (the function is free to modify the value
of the string).  The second argument, if any, is the second element of a
two-part expectation, whatever that might be.

   The function should return undef unless there's a problem, in which case
it should return 1.  It's also best (if possible) to return undef if the
string is undef, so that the user can decide whether to allow_empty or
disallow_empty independent of your check.

   For example, registering a check to verify that the input word is "poot"
would look like:

     String::Checker::register_check("ispoot", sub {
         my($s) = shift;
         if ((defined($$s)) && ($$s ne 'poot')) {
             return 1;
         }
         return undef;
     };

BUGS
====

   Hopefully none.

AUTHOR
======

   J. David Lowe, dlowe@webjuice.com

SEE ALSO
========

   perl(1), CGI::ArgChecker(1)

find the character,line, and line position of the first difference
******************************************************************

NAME
====

   String::DiffLine - find the character,line, and line position of the
first difference

SYNOPSIS
========

     use String::DiffLine qw(diffline);
     ($char,$line,$lpos)=diffline("abc","abx");

DESCRIPTION
===========

diffline($str1,$str2)
     Returns a three-item list identifying the location of the first
     difference between the two strings: the character position (indexed
     from 0), the line number (indexed from 1), and the position in the
     line (indexed from 0). $/ is used as the line separator.

     If the strings are identical, the first element of the returned list
     is zero, the second element is the number of line separators plus one,
     and the last element is the number of characters following the last
     line separator.

AUTHOR
======

   Andrew Allen <andrew_d_allen@hotmail.com>

SEE ALSO
========

   perl(1).

Registry of string functions, including backslash escapes
*********************************************************

NAME
====

   String::Escape - Registry of string functions, including backslash
escapes

SYNOPSIS
========

     use String::Escape qw( printable unprintable );
     # Convert control, high-bit chars to \n or \xxx escapes
     $output = printable($value);
     # Convert escape sequences back to original chars
     $value = unprintable($input);

     use String::Escape qw( elide );
     # Shorten strings to fit, if necessary
     foreach (@_) { print elide( $_, 79 ) . "\n"; }

     use String::Escape qw( escape );
     # Defer selection of escaping routines until runtime
     $escape_name = $use_quotes ? 'qprintable' : 'printable';
     @escaped = escape($escape_name, @values);

DESCRIPTION
===========

   This module provides a flexible calling interface to some
frequently-performed string conversion functions, including applying and
removing C/Unix-style backslash escapes like \n and \t, wrapping and
removing double-quotes, and truncating to fit within a desired length.

   The escape() function provides for dynamic selection of operations by
using a package hash variable to map escape specification strings to the
functions which implement them. The lookup imposes a bit of a performance
penalty, but allows for some useful late-binding behaviour. Compound
specifications (ex. 'quoted uppercase') are expanded to a list of
functions to be applied in order. Other modules may also register their
functions here for later general use.

REFERENCE
=========

Escaping And Unescaping Functions
---------------------------------

   Each of these functions takes a single simple scalar argument and
returns its escaped (or unescaped) equivalent.

quote($value) : $escaped
     Add double quote characters to each end of the string.

quote_non_words($value) : $escaped
     As above, but only quotes empty, punctuated, and multiword values.

unquote($value) : $escaped
     If the string both begins and ends with double quote characters, they
     are removed, otherwise the string is returned unchanged.

printable($value) : $escaped
unprintable($value) : $escaped
     These functions convert return, newline, tab, backslash and
     unprintable characters to their backslash-escaped equivalents and
     back again.

qprintable($value) : $escaped
unqprintable($value) : $escaped
     The qprintable function applies printable escaping and then wraps the
     results with quote_non_words, while unqprintable applies  unquote and
     then unprintable.  (Note that this is not MIME quoted-printable
     encoding.)

String Elision Function
-----------------------

   This function extracts the leading portion of a provided string and
appends ellipsis if it's longer than the desired maximum excerpt length.

elide($string) : $elided_string
elide($string, $length) : $elided_string
elide($string, $length, $word_boundary_strictness) : $elided_string
     If the original string is shorter than $length, it is returned
     unchanged. At most $length characters are returned; if called with a
     single argument, $length defaults to $DefaultLength.

     Up to $word_boundary_strictness additional characters may be ommited
     in order to make the elided portion end on a word boundary; you can
     pass 0 to ignore word boundaries. If not provided,
     $word_boundary_strictness defaults to $DefaultStrictness.

$Elipses
     The string of characters used to indicate the end of the excerpt.
     Initialized to '...'.

$DefaultLength
     The default target excerpt length, used when the elide function is
     called with a single argument. Initialized to 60.

$DefaultStrictness
     The default word-boundary flexibility, used when the elide function
     is called without the third argument. Initialized to 10.

Escape By-Name
--------------

   These functions provide for the registration of string-escape
specification names and corresponding functions, and then allow the
invocation of one or several of these functions on one or several source
string values.

escape($escapes, $value) : $escaped_value
escape($escapes, @values) : @escaped_values
     Returns an altered copy of the provided values by looking up the
     escapes string in a registry of string-modification functions.

     If called in a scalar context, operates on the single value passed
     in; if called in a list contact, operates identically on each of the
     provided values.

     Valid escape specifications are:

    one of the keys defined in %Escapes
          The coresponding specification will be looked up and used.

    a sequence of names separated by whitespace,
          Each name will be looked up, and each of the associated
          functions will be applied successively, from left to right.

    a reference to a function
          The provided function will be called on with each value in turn.

    a reference to an array
          Each item in the array will be expanded as provided above.

     A fatal error will be generated if you pass an unsupported escape
     specification, or if the function is called with multiple values in a
     scalar context.

String::Escape::names() : @defined_escapes
     Returns a list of defined escape specification strings.

String::Escape::add( $escape_name, \&escape_function );
     Add a new escape specification and corresponding function.

%Escapes : $name, $operation, ...
     By default, the %Escapes hash is initialized to contain the following
     mappings:

    quote, unquote, or quote_non_words
    printable, unprintable, qprintable, or unqprintable,
    elide
          Run the above-described functions of the same names.

    uppercase, lowercase, or initialcase
          Alters the case of letters in the string to upper or lower case,
          or for initialcase, sets the first letter to upper case and all
          others to lower.

    none
          Return an unchanged copy of the original value.

EXAMPLES
========

   `print printable( "\tNow is the time\nfor all good folks\n" );'

   `*\tNow is the time\nfor all good folks\n*'

   `print escape('qprintable', "\tNow is the time\nfor all good folks\n"
);'

   `*"\tNow is the time\nfor all good folks\n"*'

   `print escape('uppercase qprintable', "\tNow is the time\nfor all good
folks\n" );'

   `*"\tNOW IS THE TIME\nFOR ALL GOOD FOLKS\n"*'

   `print join '--', escape('printable', "\tNow is the time\n", "for all
good folks\n" );'

   `*\tNow is the time\n--for all good folks\n*'

   `$string = 'foo bar baz this that the other';'

   `print elide( $string, 100 );'

   `*foo bar baz this that the other*'

   `print elide( $string, 12 );'

   `*foo bar...*'

   `print elide( $string, 12, 0 );'

   `*foo bar b...*'

PREREQUISITES AND INSTALLATION
==============================

   This package should run on any standard Perl 5 installation.

   To install this package, download and unpack the distribution archive
from http://www.evoscript.com/dist/ or your favorite CPAN mirror, and
execute the standard "perl Makefile.PL", "make test", "make install"
sequence.

STATUS AND SUPPORT
==================

   This release of String::Escape is intended for public review and
feedback.  It has been tested in several environments and no major
problems have been discovered, but it should be considered "beta" pending
that feedback.

     Name            DSLI  Description
     --------------  ----  ---------------------------------------------
     String::
     ::Escape        bdpf  Escape by-name registry and useful functions

   Further information and support for this module is available at
<www.evoscript.com>.

   Please report bugs or other problems to <bugs@evoscript.com>.

   The following changes are in progress or under consideration:

Use word-boundary test in elide's regular expression rather than \s|\Z.
Compare with TOMC's String::Edit package.
AUTHORS AND COPYRIGHT
=====================

   Copyright 1997, 1998 Evolution Online Systems, Inc. <www.evolution.com>

   You may use this software for free under the terms of the Artistic
License.

   Contributors: M. Simon Cavalletto <simonm@evolution.com>, Jeremy G.
Bishop <jeremy@evolution.com>

Parity (odd/even/mark/space) handling functions
***********************************************

NAME
====

   String::Parity, setEvenParity, setOddParity, setSpaceParity,
setMarkParity, isEvenParity, isOddParity isSpaceParity, isMarkParity,
EvenBytes, OddBytes, SpaceBytes, MarkBytes, showParity, showMarkSpace -
Parity (odd/even/mark/space) handling functions

SYNOPSIS
========

     use String::Parity;
     use String::Parity qw(:DEFAULT /show/);

DESCRIPTION
===========

setEvenParity LIST
     Copies the elements of LIST to a new list and converts the new
     elements to strings of bytes with even parity. In array context
     returns the new list.  In scalar context joins the elements of the
     new list into a single string and returns the string.

setOddParity LIST
     Like setEvenParity function, but converts to strings with odd parity.

setSpaceParity LIST
     Like setEvenParity function, but converts to strings with space (High
     bit cleared) parity.

setMarkParity LIST
     Like setEvenParity function, but converts to strings with mark (High
     bit set) parity.

EvenBytes LIST
     Returns the number of even parity bytes in the elements of LIST.

OddBytes LIST
     Returns the number of odd parity bytes in the elements of LIST.

SpaceBytes LIST
     Returns the number of space parity bytes in the elements of LIST.

MarkBytes LIST
     Returns the number of mark parity bytes in the elements of LIST.

isEvenParity LIST
     Returns TRUE if the LIST contains no byte with odd parity, FALSE
     otherwise.

isOddParity LIST
     Returns TRUE if the LIST contains no byte with even parity, FALSE
     otherwise.

isSpaceParity LIST
     Returns TRUE if the LIST contains no byte with mark parity, FALSE
     otherwise.

isMarkParity LIST
     Returns TRUE if the LIST contains no byte with space parity, FALSE
     otherwise.

showParity LIST
     Like setEvenParity function, but converts bytes with even parity to
     'e' and other bytes to 'o'.  The function showParity must be imported
     by a specialised import list.

showMarkSpace LIST
     Like setEvenParity function, but converts bytes with space parity to
     's' and other bytes to 'm'.  The function showMarkSpace must be
     imported by a specialised import list.

NOTES
=====

   Don't use this module unless you have to communicate with some old
device or protocol. Please make your application 8 bit clean and use the
internationally standardised ISO-8859-1 character set.

AUTHOR
======

   Winfried Koenig <win@in.rhein-main.de>

SEE ALSO
========

   perl(1), Exporter(1)

Parse a string into logical words
*********************************

NAME
====

   String::ParseWords - Parse a string into logical words

SYNOPSIS
========

     use String::ParseWords;

     $string = q("Word A" Word B);
     $words = String::ParseWords::parse($string);
     foreach (@$words) { print "$_\n"; }

     OUTPUT:
      Word A
      Word
      B

DESCRIPTION
===========

   *String::ParseWords* is designed to parse logical words from a string.
Logical words are defined as sets of characters between double quotes or
sets of characters between whitespace.

   One practical use for this module is to break apart group names for
authorization within apache 'require' directives.

SUBROUTINES
===========

parse ( STRING )
     Returns a reference to an anonymous array that contains the parsed
     words.

AUTHOR
======

   Christian Gilmore (`cgilmore@tivoli.com')

SEE ALSO
========

COPYRIGHT
=========

   Copyright (C) 2000, International Business Machines Corporation and
others. All Rights Reserved.

   This module is free software; you can redistribute it and/or modify it
under the terms of the IBM Public License.

create / identify strings by pattern
************************************

NAME
====

   String::Pattern - create / identify strings by pattern

SYNOPSIS
========

     use String::Pattern;
     use strict;

     my $code = "73545-ved-8877";
     my $name = "Benalgin";
     my $prescription = 'X';
     my $price = 10.99;
     my $date;

     my $p = new Pattern 'code: 1223144-x-67 name: Aspirin prescription: [pr_flag] price: $5.90';
     my $print_view = new Pattern q{
     	record date : 8/11/00
     	code: 1223144-x-67
     	name: Aspirin
     	[pr_flag] prescription
     	price: $5.90
     };

     $p->bind( '1223144-x-67' => \$code);
     $p->bind( Aspirin => \$name);
     $p->bind( '5.90' => \$price, '\d+(?:[,\.]\d{2})?');
     $p->bind( pr_flag => \$prescription);
     $print_view->bind_like($p);
     $print_view->bind( '8/11/00' => \$date);

     my $q="$p"; # equivalent ot my $q=$p->to_string;

     $prescription=" ";
     my $r = 'code: 1223144x-69 name: Aspirin-Bayer prescription: [ ] price: $3.124';

     for my $string ($r,	$p,	$q) {
     	print $string, "\n";
     	if ($p->identify($string)) {
     		print "Match on pattern \n";
     		$date = localtime;
     		print $print_view."\n";
     	}else{
     		print "Not match on pattern \n\n"
     	}
     }

DESCRIPTION
===========

   This module is designed to deal whith non atomic data strings
representations whith fixed number of items on it - such as addresses,
business cards, product descriptors etc. It simplificies string creation
based on preliminary defined human readable patterns ( templates ) and
identifying that any given string has format, "described" in the same
pattern.

Methods
-------

pattern
pattern ($string)
     if $string is supplied then it will be used as pattern, otherwise
     currently used pattern is returned

bind ( tag => \$var)
bind ( tag => \$var, $re)
     binds var ref to specific part of pattern (tag). When string is
     created, all occuriences of that tag will be replaced with the value
     of `$var'. Regular expession `$re' is used to describe what the tag
     looks like, and increases the accuracy of `identify' in this node
     method in ambiguous cases. Pattern is used to build one regular
     expession whith backreferences ( for each occurrence of tag ) , so
     brackets usage in `$re' must be only like this (?: ... ).

to_string
     Creates string based on pattern and bindings. This method is invoked
     when object ref is evaluated in string context

identify ($string)
     Returns 1 if $string matches on pattern and all occurrences of given
     tag are equal, then sets vars to first occurrence of respective
     bounded tag. Otherwise returns 0 and nothig is changed.

bind_like ($other_pattern_object)
     Gets bindings from other object. May be useful for copy like
     operations avoiding boring declararions.

     	my $p1 = new String::Pattern .....; 	my $p2 = new
     String::Pattern .....;

          # a lot of bind ...
          $p1->bind....;
          ...
          $p1->bind....;
          $p2->bind_like($p1);

          # $p2 specific binds
          $p2->bind....;

          if ($p1->identify(...)) {
          	print $p2
          }

     so $p2 have all of $p1 bindings plus one additional

to do
-----

erros and warnings
     Adding some useful warnings and erros about content of variables, and
     their ralations with tags in the pattern

AUTHOR
======

   Ivo Zdravkov, ivoz@starmail.com

SEE ALSO
========

   perl (1), perlre (3)

Generates a regex to partition a data set
*****************************************

NAME
====

   String::REPartition - Generates a regex to partition a data set

SYNOPSIS
========

     use String::REPartition;
     use strict;

     my($regex) = make_partition_re(0.5, \@some_really_big_list_of_strings);
     if ($string =~ /$regex/) {
       # $string is in the first half of the data
     } else {
       # $string is in the second half
     }

DESCRIPTION
===========

   This module exports a single function - make_partition_re.  It takes as
its first argument a number between 0 and 1, representing a percentage,
and as its second argument a reference to a list of strings.  It returns a
regular expression which is guaranteed to match the percentage of the
strings in the list represented by the number in the first argument.  More
importantly, the regexreturned is guaranteed *not* to match the rest of
the string in the list.  That is, if the inputs were '0.6' and a reference
to a list of 100 strings, the returned regex would match 60 of the strings
in the list and not match the other 40.

   Keep in mind that, since only integer operations may be performed on
these strings, (that is, there cannot be a regex which matches a fraction
of a string), the target number is rounded down.  If you have 4 strings in
your list and a ratio of 0.4, the resulting regex will match 1 string, not
1.6 strings.  More interestingly, with 4 strings and a ratio of 0.1, the
resulting regex will almost certainly be `/^()$/' - matching exactly 0 of
the strings in the list.  Furthermore, because of this rounding, the
returned regex may not match precisely the number expected by multiplying
the size of the list by the ratio, but instead be off by a small number in
either direction.

   c<make_partition_re()> will return c<undef> on a failure, and print a
warning to STDERR if $^W is true.  Currently, the only errors that can
occur relate directly to the validity of the inputs.  Furthermore, if the
strings in the list are not unique, the behaviour of this function is not
defined.  For a small amout of repetition the regex should still work, but
it should be clear that a solution cannot be found if the input list
consists only of many copies of the same string.

   The function finds its solution in roughly O(N) time - however, in
worst cases, I think it can get as high as O(N^2).  It's also true that
certain types of pathologically constructed data sets can break things and
cause it either to return an invalid regex or to enter an infinite loop.
While I haven't run into any of this in my testing, I'm not confident that
I've tested every possibility.

   So why would you want to use this?  Well, that's a question you'll have
to answer for yourself, mostly.  :)  However, the situations I envisaged
while developing the module were sort of like this: Imagine you have a
large set of data, indexed by a correspondingly large set of keywords.
Let's say you want to split this data into two partitions, perhaps in
order to store the data in two separate locations.  Maintaining a complete
list of the remote keys could be expensive - instead, you can simply store
a regular expression which matches the keys you keep remotely and does not
match the local ones.

   Another interesting feature is that a regex generated from a
sufficiently large subset of your data will, approximately, match the
appropriate percentage of strings from the complete data set.  This means
that you do not need to have all of the data before you generate a regex
to partition it.  As an example, generating a regex from roughly 10% of
the words in /usr/dict/words (selected randomly) gave me a regex that
matched within .3% of the desired result of all of the words.

Future Work
===========

   * As I indicate above, this module does not perform properly when data
     with non-unique strings is given to it.  I did not feel it was
     reasonable to take the time to check the list for uniqueness, so it
     will happily process data for which it may not be able to generate a
     valid solution.  This may change in future versions.

   * Internal rounding is a problem in some cases.  The sections of the
     code which are most responsible for this were rather hastily
     conceived and no doubt could be somewhat improved.  However, they are
     also somewhat confusing and I need to make this release in order to
     fix a few bugs.  The rounding problem will be addressed in the next
     release.

AUTHOR
======

   Copyright 2000 Avi Finkel <`avi@finkel.org'>

   This package is free software and is provided "as is" without express
or implied warranty.  It may be used, redistributed and/or modified under
the terms of the Perl Artistic License (see
http://www.perl.com/perl/misc/Artistic.html)

Perl module to generate random strings based on a pattern
*********************************************************

NAME
====

   String::Random - Perl module to generate random strings based on a
pattern

SYNOPSIS
========

     use String::Random;
     $foo = new String::Random;
     print $foo->randregex('\d\d\d'); # Prints 3 random digits
     print $foo->randpattern("...");  # Prints 3 random printable characters

   or

     use String::Random qw(random_string);
     print random_string("..."); # Also prints 3 random characters

DESCRIPTION
===========

   This module makes it trivial to generate random strings.

   As an example, let's say you are writing a script that needs to
generate a random password for a user.  The relevant code might look
something like this:

     use String::Random;
     $pass = new String::Random;
     print "Your password is ", $pass->randpattern("CCcc!ccn"), "\n";

   This would output something like this:

     Your password is UDwp$tj5

Patterns
--------

   The pre-defined patterns are as follows:

     c        Any lowercase character [A-Z]
     C        Any uppercase character [a-z]
     n        Any digit [0-9]
     !        A punctuation character [~`!@$%^&*()-_+={}[]|\:;"'.<>?/#,]
     .        Any of the above
     s        A "salt" character [A-Za-z0-9./]

   These can be modified, but if you need a different pattern it is better
to create another pattern, possibly using one of the pre-defined as a base.
For example, if you wanted a pattern A that contained all upper and lower
case letters (`[A-Za-z]'), the following would work:

     $foo = new String::Random;
     $foo->{'A'} = [ 'A'..'Z', 'a'..'z' ];

   or

     $foo = new String::Random;
     $foo->{'A'} = [ @{$foo->{'C'}}, @{$foo->{'c'}} ];

   The random_string function, described below, has an alternative
interface for adding patterns.

Methods
-------

randpattern LIST
     The randpattern method returns a random string based on the
     concatenation of all the pattern strings in the list.

     Please note that in a future revision, it will return a list of random
     strings corresponding to the pattern strings when used in list
     context.

randregex LIST
     The randregex method returns a random string that will match the
     regular expression passed in the list argument.

     Please note that the arguments to randregex are not real regular
     expressions.  Only a small subset of regular expression syntax is
     actually supported.  So far, the following regular expression
     elements are supported:

          []    Character classes
          {}    Repetition
          \w    Alphanumeric + "_".
          \d    Digits.
          \W    Printable characters other than those in \w.
          \D    Printable characters other than those in \d.

     Regular expression support is still very experimental.  Currently
     special characters inside [] are not supported (with the exception of
     "-" to denote ranges of characters).  The parser doesn't care for
     spaces in the "regular expression" either.

Functions
---------

random_string PATTERN,LIST
random_string PATTERN
     When called with a single scalar argument, random_string returns a
     random string using that scalar as a pattern.  Optionally, references
     to lists containing other patterns can be passed to the function.
     Those lists will be used for 0 through 9 in the pattern (meaning the
     maximum number of lists that can be passed is 10).  For example, the
     following code:

          print random_string("0101",
                              ["a", "b", "c"],
                              ["d", "e", "f"]), "\n";

     would print something like this:

          cebd

BUGS
====

   As noted above, randpattern doesn't do the right thing when called in a
list context.  Whether it does the right thing in a scalar context when
passed a list is up for debate.

   I don't even want to think about what kind of bugs might be in randregex
at this point.

AUTHOR
======

   Steven Pritchard <steve@silug.org>

SEE ALSO
========

   perl(1).

Perl implementation of REXX parse command
*****************************************

NAME
====

   String::RexxParse - Perl implementation of REXX parse command

   Download:

   http://www.danofsteel.com/Parser/String-RexxParse-1.07.tar.gz

AUTHOR
======

   Dan Campbell

Copyright
     Copyright (c) 1999, 2000 Dan Campbell. All rights reserved.  This
     program is free software; you can redistribute it and/or modify it
     under the same terms as Perl itself.

DESCRIPTION
===========

   Some long-time REXX programmers switching to Perl find it difficult to
give up REXX's template-based parsing abilities.  This module is my
attempt to provide such parsing in Perl.  Consider it BETA level code.
The documentation assumes a familiarity with REXX parse statements.

CHANGES
=======

Version 1.08
Version 1.07
          Template only contains variables (or . )
          Template only contains variables (or . ) or patterns (literal or variable)

     Added String::RexxParse->email which returns me email address.

     Internal optimizations for the following templates special cases:

          Template is only a single lvalue
          Template only contains variables (or . )
          Template only contains variables (or . ) or patterns (literal or variable)

SYNOPSIS
========

use String::RexxParse qw(parse);
parse $source, q! $var1 $var2 '(' $var3 ')' $var4 ($var5) $var6 !;
$parse = String::RexxParse->new(q! $var1 $var2 '(' $var3 ')' $var4 ($var5) $var6 !);
$parse->parse($source);
SYNTAX
======

parse EXPR, EXPR
     The first EXPR is the source string to be parsed and must resolve to
     a scalar value.

     The second EXPR is the template specification.  The first time parse
     is called with a particular template, the template is compiled, then
     used to parse the source expression.  Subsequent parse calls with the
     same template will use the previously compiled version of the template
     rather than compile the template again.

     The template is specified as a single expression, usually using some
     single-quotish type of quoting, like q!...! for instance.  The
     variable specifications, (or lvalue specifications) must not contain
     spaces.  If you want data assigned to *$qq{$one}*, do not specify it
     as *$qq{ $one }* but as *$qq{$one}*.  Although both are valid in
     Perl, only the latter is valid in a *String::RexxParse* template.
     Likewise, *substr( $b , pos( $source ) , length( $match ) )* is NOT
     valid, but *substr($b,pos($source),length($match))* is.  Also, there
     must be white space following any lvalue specification (unless it's
     the last item in the template).  *q/$b $c/* is OK, but *q/$b$c/* is
     not.

     If a variable's value is to be used as a pattern, it is enclosed in
     parentheses.

     Literal patterns are  enclosed in either single or double quotes.
     Patterns can contain spaces within the quotes or parentheses.

     A period (.) is used as a placeholder to skip part of the source
     string.

     Numeric patterns (absolute or relative position) are supported.  3,
     *=7*, *+5*, *-12*, *=($n)*, *+($x)*, *-($somenumber)* are all numeric
     patterns (if you use variables inside parentheses preceeded by =, +,
     or -, make sure they contain numeric values).  Remember that Perl
     starts counting position at zero, so absolute numeric patterns should
     be one less than in REXX to identify the same character position.

     All Perl variables used must either be in the package that called
     parse, or they must be explicitly referenced with their package name
     (i.e., if parse is called from package Pack, $a implies $Pack::a - if
     you want $a in package Sack, you must specify $Sack::a ).  Lexical
     variables  can not be used in the template.  To assign values to
     lexical variables do somthing like this:

          my ($b, $c, $d, $e) = parse $a, q! $x . $x '(' $x ')' $x !;

     If you're concerned about the compiled templates taking up memory
     after you're done with them, you can add 'drop' to the import list
     when you 'use String::RexxParse'.  Then pass the template to 'drop'
     when you're done with it.  Or just call
     *String::RexxParse::drop($template)*.  Or use the object oriented
     flavor discussed below.

     Consult your favorite REXX manual for more details on templates.

$parse->parse(EXPR);
     If you like, you can use String::RexxParse->new(EXPR) to create a
     *String::RexxParse* object.  The EXPR passed to new is a template
     specification as described above.  When you want to parse an EXPR,
     you just pass the string to the *String::RexxParse* object like so:
     $parse->parse(EXPR);

EXAMPLES
========

     REXX:
     parse var a b c '.' d '([' e '])' f qq.one

     Perl:
     parse $a, q! $b $c '.' $d '([' $e '])' $f $qq{one} !;
     # or
     $p = String::RexxParse->new(q! $b $c '.' $d '([' $e '])' $f $qq{one} !);
     $p->parse($a);

     ~~~~~~~~~~~~~~~

     REXX:
     parse var a b . '.' d '([' e '])' f qq.one

     Perl:
     parse $a, q!$b . '.' $d '([' $e '])' $f $qq{one}!;

     ~~~~~~~~~~~~~~~

     REXX:
     parse linein b c '.' d '([' e '])' f qq.one

     Perl:
     parse <>, q! $b $c '.' $d '([' $e '])' $f $qq{one} !;

     ~~~~~~~~~~~~~~~

     REXX:
     parse linein('filename') b c '.' d '([' e '])' f qq.one

     Perl:
     open FILE,"filename";
     parse <FILE>, q! $b $c '.' $d '([' $e '])' $f $qq{one}!;

     ~~~~~~~~~~~~~~~

     REXX:
     parse value(func(a)) with b c '.' d '([' e '])' f qq.one

     Perl:
     parse func($a), q! $b $c '.' $d '([' $e '])' $f $qq{one}!;

     ~~~~~~~~~~~~~~~

     REXX:
     variable = '.'
     parse a b c (variable) d

     Perl:
     $variable = '.';
     parse $a, q/$b $c ($variable) $d/;

     ~~~~~~~~~~~~~~~

     REXX:
     variable = "abc"
     parse a b c (' 'variable' ') d

     Perl:
     parse $a, q/$b $c (" $variable ") $d/;

     ~~~~~~~~~~~~~~~

     REXX:
     parse a b 12 c +8 d

     Perl:
     parse $a, q! $b 11 $c +8 $d !;
     # position 12 in REXX is position 11 in Perl!

     ~~~~~~~~~~~~~~~

     REXX:
     parse var a b . d '([' e '])' f -13 g +(eight) qq.one

     Perl:
     @list = parse $a,  q!$b '.' $d '([' $e '])' $f -13 $g +($eight) $qq{one}!;
     # In addition to assiging values to the variables identified in the template,
     # @list will contain a list of corresponding values.

BUGS, QUESTIONS, COMMENTS
=========================

   Please report any suspected bugs to Dan Campbell
(String::RexxParse->email).  Include the template and sample text that
produces the incorrect results, along with a description of the problem.
Questions and comments are also welcome.

emulate the sscanf() of the C stdio library
*******************************************

NAME
====

   sscanf - emulate the sscanf() of the C stdio library

SYNOPSIS
========

     use String::Scanf;	# this will import sscanf() into the
     			# current namespace

     @values = sscanf($scanf_format_string, $scalar_to_scan);

     # the default scan target is the $_
     @values = sscanf($scanf_format_string);

     # converting scanf formats to regexps (::format_to_re
     # is never exported to the current namespace)

     $regexp_string = String::Scanf::format_to_re($scanf_format_string);

DESCRIPTION
===========

   Perl sscanf() can be used very much like the C stdio sscanf(), for
detailed sscanf() documentation please refer to your usual documentation
resources. The supported formats are: `[diuoxefgsc]' and the character
class [].

   All of the format must match. If not, an empty list is returned and all
the values end up empty.

   The c format returns an anonymous list (see perlref) containing the
numeric values of the characters it matched.

   The ::format_to_re() function may be helpful if one wants to develop
her own parsing routines.

FEATURES
========

   Embedded underscores are accepted in numbers just like in Perl, even in
octal/hexadecimal numbers (Perl does not currently support this). Please
note the word *embedded*, not leading or trailing.

   If the `oh' formats are used, the octal/hexadecimal interpretation is
forced even without the leading 0 or `0x'.

LIMITATIONS
===========

   Certain features of the C sscanf() are unsupported:

     * the formats C<[npSC]>
     * in the C<[efg]> formats the C<INF> and various C<NaN>s

   The numeric formats are scanned in as strings, this meaning that
numeric overflows may occur. For example: `1.2345e67890' will match the
`%g' format but in most machines Perl cannot handle that large floating
point numbers and bizarre values may end up in the Perl variable. Similar
caveats apply for integer-type numbers. Results of such huge numbers (or
very tiny numbers, say, `1.24345e-67890') are implementation-defined,
which translates quite often as *garbage*.  NOTE: if you really want *Big*
numbers please consider using the Math::BigInt and Math::BigFloat, these
packages come standard with Perl 5, or the `Math::Pari' package, available
from CPAN.

   For Perl <integers> and *floating point numbers* are the same thing.
Also, the possible `hl' modifiers for the integers mean nothing: they are
accepted but still they do nothing because Perl does not care about
short/long integer differences.

   The character class format is not so rigorously checked for correctness
that an illegal character class definition could not be sneaked in. For
example `[z-a,X]' is a `bad' example: perfectly illegal as a character
class but `String::Scanf' will happily accept it. Beware.

   The ::format_to_re() only does the scanf format -> regular expression
conversion. It ignores tricky things like the c format (see above) and the
%n$ argument reordering. If you want these, you may as well use the full
::sscanf().

EXAMPLES
========

     # business as usual

     ($i, $s, $x) = sscanf('%d %3s %g', ' -5_678     abc 3.14e-99 9');

     # 'skip leading whitespace': $x becomes 42 despite the leading space
     # 'the illegal character': $y becomes 'ab' despite the '3'
     # 'c' format: $z becomes [120 100], the numeric values of 'x'
     # and 'd' (assuming ASCII or ISO Latin 1)

     ($x, $y, $z) = sscanf('%i%3[a-e]%2c', ' 42acxde');

     # reordering the arguments: $a becomes 34, $b becomes 12

     ($a, $b) = sscanf('%2$d %1$d', '12 34');

     # converting scanf formats to regexps

     $re = String::Scanf::format_to_re('%x');

   More examples in the test set `t/scanf.t'.

INTERNALS
=========

   The Perl `sscanf()' turns the C-`stdio' style `sscanf()' format string
into a Perl regexp (see perlre) which captures the wanted values into
submatches and returns the submatches as a list.

   Originally written for purposes of debugging but also useful for
educational purposes:

     String::Scanf::debug(1);	# turn on debugging: shows the regexps
     			# used and the possible reordering list
     			# and the character (%c) conversion targets
     String::Scanf::debug(0);		# turn off debugging
     print String::Scanf::debug(), "\n";	# the current debug status

VERSION
=======

   v1.1, $Id: Scanf.pm,v 1.8 1995/12/27 08:32:28 jhi Exp $

AUTHOR
======

   Jarkko Hietaniemi, `Jarkko.Hietaniemi@iki.fi'

quote strings for passing through the shell
*******************************************

NAME
====

   String::ShellQuote - quote strings for passing through the shell

SYNOPSIS
========

     $string = shell_quote @list;
     $string = shell_comment_quote $string;

DESCRIPTION
===========

   This module contains some functions which are useful for quoting strings
which are going to pass through the shell or a shell-like object.

shell_quote [string]...
     shell_quote quotes strings so they can be passed through the shell.
     Each string is quoted so that the shell will pass it along as a
     single argument and without further interpretation.  If no strings
     are given an empty string is returned.

shell_comment_quote [string]
     shell_comment_quote quotes the string so that it can safely be
     included in a shell-style comment (the current algorithm is that a
     sharp character is placed after any newlines in the string).

     This routine might be changed to accept multiple string arguments in
     the future.  I haven't done this yet because I'm not sure if the
     strings should be joined with blanks ($") or nothing ($,).  Cast your
     vote today!  Be sure to justify your answer.

EXAMPLES
========

     $cmd = 'fuser 2>/dev/null ' . shell_quote @files;
     @pids = split ' ', `$cmd`;

     print CFG "# Configured by: ",
     		shell_comment_quote($ENV{LOGNAME}), "\n";

AUTHOR
======

   Roderick Schertler <`roderick@argon.org'>

SEE ALSO
========

   perl(1).

calculate the similarity of two strings
***************************************

NAME
====

   String::Similarity - calculate the similarity of two strings

SYNOPSIS
========

     use String::Similarity;

     $similarity = similarity $string1, $string2;
     $similarity = similarity $string1, $string2, $limit;

DESCRIPTION
===========

$factor = similarity $string1, $string2, [$limit]
     The `similarity'-function calculates the similarity index of its two
     arguments.  A value of 0 means that the strings are entirely
     different. A value of 1 means that the strings are identical.
     Everything else lies between 0 and 1 and describes the amount of
     similarity between the strings.

     It roughly works by looking at the smallest number of edits to change
     one string into the other.

     You can add an optional argument `$limit' (default 0) that gives the
     minimum similarity the two strings must satisfy. `similarity' stops
     analyzing the string as soon as the result drops below the given
     limit, in which case the result will be invalid but lower than the
     given `$limit'. You can use this to speed up the common case of
     searching for the most similar string from a set by specifing the
     maximum similarity found so far.

SEE ALSO
========

     The basic algorithm is described in:
     "An O(ND) Difference Algorithm and its Variations", Eugene Myers,
     Algorithmica Vol. 1 No. 2, 1986, pp. 251-266;
     see especially section 4.2, which describes the variation used below.

     The basic algorithm was independently discovered as described in:
     "Algorithms for Approximate String Matching", E. Ukkonen,
     Information and Control Vol. 64, 1985, pp. 100-118.

AUTHOR
======

     Marc Lehmann <pcg@goof.com>
     http://www.goof.com/pcg/marc/

     (the underlying fstrcmp function was taken from gnu diffutils and
     modified by Peter Miller <pmiller@agso.gov.au> and Marc Lehmann
     <pcg@goof.com>).

Perl extension for fast, commonly used, string operations
*********************************************************

NAME
====

   String::StringLib - Perl extension for fast, commonly used, string
operations

   Use of String::StringLib is deprecated as of version 1.01. Please see
String::Strip (version 1.01 or better) instead.

AUTHOR
======

   Brent B. Powers (B2Pi), Powers@B2Pi.com

   Copyright(c) 1999,2000 Brent B. Powers. All rights reserved. This
program is free software, you may redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1), String::Strip

Perl extension for fast, commonly used, string operations
*********************************************************

NAME
====

   String::Strip - Perl extension for fast, commonly used, string
operations

SYNOPSIS
========

     use String::Strip;

     ...

     StripLTSpace($a);
     StripTSpace($a);
     StripLSpace($a);
     StripSpace($a);

DESCRIPTION
===========

   StripLTSpace - Removes Leading and Trailing spaces from given string

   StripTSpace - Removes Trailing spaces from given string

   StripLSpace - Removes Leading spaces from given string

   StripSpace - Removes all spaces from given string

   I do these things often, and these routines tend to be about 35% faster
than the corresponding regex methods.

AUTHOR
======

   Brent B. Powers (B2Pi), Powers@B2Pi.com

   Copyright(c) 1999,2000 Brent B. Powers. All rights reserved. This
program is free software, you may redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1).

Subroutine pre- and post-handlers
*********************************

NAME
====

   Sub::Versive - Subroutine pre- and post-handlers

SYNOPSIS
========

     use Sub::Versive qw(append_to_sub prepend_to_sub builtinify);

     sub foo { print "Hi there\n"; }

     append_to_sub  { print "Doing foo() now"; }     &foo;
     prepend_to_sub { print "Finished"; }            &foo;
     prepend_to_sub { print "Yes, it's stackable"; } &foo;

     prepend_to_sub { $@="Hijacked!"; do_something_else() }

     builtinify &foo;

     package bar;

     foo(); # Still works.

DESCRIPTION
===========

   The synopsis pretty much tells you all you need to know. You can add
pre- and post-actions to subroutines, stack them, have them force a
return, and make a subroutine available from everywhere.

   I'm sorry, incidentally, that this needs 5.6.1 and above, especially
since 5.6.1 isn't released right now. This is because of the prototyping
behaviour. If you want to make it work with 5.6.0, zap the prototypes and
pass subroutine references instead of subroutine names. I just vastly
prefer the syntax, that's all. You'll still need Devel::Peek from 5.6.0,
though.

EXPORT
------

   None by default, all three functions available.

AUTHOR
======

   Simon Cozens, `simon@cpan.org'

A switch statement for Perl
***************************

NAME
====

   Switch - A switch statement for Perl

VERSION
=======

   This document describes version 2.01 of Switch, released January  9,
2001.

SYNOPSIS
========

     use Switch;

     switch ($val) {

     case 1		{ print "number 1" }
     case "a"	{ print "string a" }
     case [1..10,42]	{ print "number in list" }
     case (@array)	{ print "number in list" }
     case /\w+/	{ print "pattern" }
     case qr/\w+/	{ print "pattern" }
     case (%hash)	{ print "entry in hash" }
     case (\%hash)	{ print "entry in hash" }
     case (\&sub)	{ print "arg to subroutine" }
     else		{ print "previous case not true" }
     	}

BACKGROUND
==========

   [Skip ahead to `"DESCRIPTION"' in this node if you don't care about the
whys and wherefores of this control structure]

   In seeking to devise a "Swiss Army" case mechanism suitable for Perl,
it is useful to generalize this notion of distributed conditional testing
as far as possible. Specifically, the concept of "matching" between the
switch value and the various case values need not be restricted to numeric
(or string or referential) equality, as it is in other languages. Indeed,
as Table 1 illustrates, Perl offers at least eighteen different ways in
which two values could generate a match.

     Table 1: Matching a switch value ($s) with a case value ($c)

     Switch  Case    Type of Match Implied   Matching Code
     Value   Value
     ======  =====   =====================   =============

     number  same    numeric or referential  match if $s == $c;
     or ref          equality

     object  method	result of method call   match if $s->$c();
     ref     name 				match if defined $s->$c();
     	or ref

     other   other   string equality         match if $s eq $c;
     non-ref non-ref
     scalar  scalar

     string  regexp  pattern match           match if $s =~ /$c/;

     array   scalar  array entry existence   match if 0<=$c && $c<@$s;
     ref             array entry definition  match if defined $s->[$c];
                     array entry truth       match if $s->[$c];

     array   array   array intersection      match if intersects(@$s, @$c);
     ref     ref     (apply this table to
                      all pairs of elements
                      $s->[$i] and
                      $c->[$j])

     array   regexp  array grep              match if grep /$c/, @$s;
     ref

     hash    scalar  hash entry existence    match if exists $s->{$c};
     ref             hash entry definition   match if defined $s->{$c};
                     hash entry truth        match if $s->{$c};

     hash    regexp  hash grep               match if grep /$c/, keys %$s;
     ref

     sub     scalar  return value defn       match if defined $s->($c);
     ref             return value truth      match if $s->($c);

     sub     array   return value defn       match if defined $s->(@$c);
     ref     ref     return value truth      match if $s->(@$c);

   In reality, Table 1 covers 31 alternatives, because only the equality
and intersection tests are commutative; in all other cases, the roles of
the $s and $c variables could be reversed to produce a different test. For
example, instead of testing a single hash for the existence of a series of
keys (`match if exists $s->{$c}'), one could test for the existence of a
single key in a series of hashes (`match if exists $c->{$s}').

   As Perltodo (perl.info), observes, a Perl case mechanism
must support all these "ways to do it".

DESCRIPTION
===========

   The Switch.pm module implements a generalized case mechanism that covers
the numerous possible combinations of switch and case values described
above.

   The module augments the standard Perl syntax with two new control
statements: switch and case. The switch statement takes a single scalar
argument of any type, specified in parentheses.  switch stores this value
as the current switch value in a (localized) control variable.  The value
is followed by a block which may contain one or more Perl statements
(including the case statement described below).  The block is
unconditionally executed once the switch value has been cached.

   A case statement takes a single scalar argument (in mandatory
parentheses if it's a variable; otherwise the parens are optional) and
selects the appropriate type of matching between that argument and the
current switch value. The type of matching used is determined by the
respective types of the switch value and the case argument, as specified
in Table 1. If the match is successful, the mandatory block associated
with the case statement is executed.

   In most other respects, the case statement is semantically identical to
an if statement. For example, it can be followed by an else clause, and
can be used as a postfix statement qualifier.

   However, when a case block has been executed control is automatically
transferred to the statement after the immediately enclosing switch block,
rather than to the next statement within the block. In other words, the
success of any case statement prevents other cases in the same scope from
executing. But see `"Allowing fall-through"' in this node below.

   Together these two new statements provide a fully generalized case
mechanism:

     use Switch;

     # AND LATER...

     %special = ( woohoo => 1,  d'oh => 1 );

     while (<>) {
         switch ($_) {

     case %special  { print "homer\n"; }       # if $special{$_}
     case /a-z/i    { print "alpha\n"; }       # if $_ =~ /a-z/i
     case [1..9]    { print "small num\n"; }   # if $_ in [1..9]

     case { $_[0] >= 10 } {                    # if $_ >= 10
         my $age = <>;
         switch (sub{ $_[0] < $age } ) {

     case 20  { print "teens\n"; }     # if 20 < $age
     case 30  { print "twenties\n"; }  # if 30 < $age
     else     { print "history\n"; }
                         }
                     }

     print "must be punctuation\n" case /\W/;  # if $_ ~= /\W/
             }

   Note that switches can be nested within case (or any other) blocks, and
a series of case statements can try different types of matches - hash
membership, pattern match, array intersection, simple equality, etc. -
against the same switch value.

   The use of intersection tests against an array reference is particularly
useful for aggregating integral cases:

     sub classify_digit
     {
             switch ($_[0]) { case 0            { return 'zero' }
                              case [2,4,6,8]    { return 'even' }
                              case [1,3,4,7,9]  { return 'odd' }
                              case /[A-F]/i     { return 'hex' }
                            }
     }

Allowing fall-through
---------------------

   Fall-though (trying another case after one has already succeeded) is
usually a Bad Idea in a switch statement. However, this is Perl, not a
police state, so there *is* a way to do it, if you must.

   If a case block executes an untargetted next, control is immediately
transferred to the statement after the case statement (i.e. usually
another case), rather than out of the surrounding switch block.

   For example:

     switch ($val) {
             case 1      { handle_num_1(); next }    # and try next case...
             case "1"    { handle_str_1(); next }    # and try next case...
             case [0..9] { handle_num_any(); }       # and we're done
             case /\d/   { handle_dig_any(); next }  # and try next case...
             case /.*/   { handle_str_any(); next }  # and try next case...
     }

   If $val held the number 1, the above switch block would call the first
three `handle_...' subroutines, jumping to the next case test each time it
encountered a next. After the thrid case block was executed, control would
jump to the end of the enclosing switch block.

   On the other hand, if $val held 10, then only the last two `handle_...'
subroutines would be called.

   Note that this mechanism allows the notion of *conditional
fall-through*.  For example:

     switch ($val) {
             case [0..9] { handle_num_any(); next if $val < 7; }
             case /\d/   { handle_dig_any(); }
     }

   If an untargetted last statement is executed in a case block, this
immediately transfers control out of the enclosing switch block (in other
words, there is an implicit last at the end of each normal case block).
Thus the previous example could also have been written:

     switch ($val) {
             case [0..9] { handle_num_any(); last if $val >= 7; next; }
             case /\d/   { handle_dig_any(); }
     }

Automating fall-through
-----------------------

   In situations where case fall-through should be the norm, rather than an
exception, an endless succession of terminal nexts is tedious and ugly.
Hence, it is possible to reverse the default behaviour by specifying the
string "fallthrough" when importing the module. For example, the following
code is equivalent to the first example in `"Allowing fall-through"' in
this node:

     use Switch 'fallthrough';

     switch ($val) {
             case 1      { handle_num_1(); }
             case "1"    { handle_str_1(); }
             case [0..9] { handle_num_any(); last }
             case /\d/   { handle_dig_any(); }
             case /.*/   { handle_str_any(); }
     }

   Note the explicit use of a last to preserve the non-fall-through
behaviour of the third case.

Higher-order Operations
-----------------------

   One situation in which switch and case do not provide a good substitute
for a cascaded if, is where a switch value needs to be tested against a
series of conditions. For example:

     sub beverage {
         switch (shift) {

     case sub { $_[0] < 10 }  { return 'milk' }
     case sub { $_[0] < 20 }  { return 'coke' }
     case sub { $_[0] < 30 }  { return 'beer' }
     case sub { $_[0] < 40 }  { return 'wine' }
     case sub { $_[0] < 50 }  { return 'malt' }
     case sub { $_[0] < 60 }  { return 'Moet' }
     else                     { return 'milk' }
                 }
             }

   The need to specify each condition as a subroutine block is tiresome. To
overcome this, when importing Switch.pm, a special "placeholder"
subroutine named `__' [sic] may also be imported. This subroutine converts
(almost) any expression in which it appears to a reference to a
higher-order function. That is, the expression:

     use Switch '__';

     __ < 2 + __

   is equivalent to:

     sub { $_[0] < 2 + $_[1] }

   With `__', the previous ugly case statements can be rewritten:

     case  __ < 10  { return 'milk' }
     case  __ < 20  { return 'coke' }
     case  __ < 30  { return 'beer' }
     case  __ < 40  { return 'wine' }
     case  __ < 50  { return 'malt' }
     case  __ < 60  { return 'Moet' }
     else           { return 'milk' }

   The `__' subroutine makes extensive use of operator overloading to
perform its magic. All operations involving __ are overloaded to produce
an anonymous subroutine that implements a lazy version of the original
operation.

   The only problem is that operator overloading does not allow the
boolean operators `&&' and `||' to be overloaded. So a case statement like
this:

     case  0 <= __ && __ < 10  { return 'digit' }

   doesn't act as expected, because when it is executed, it constructs two
higher order subroutines and then treats the two resulting references as
arguments to `&&':

     sub { 0 <= $_[0] } && sub { $_[0] < 10 }

   This boolean expression is inevitably true, since both references are
non-false. Fortunately, the overloaded `'bool'' operator catches this
situation and flags it as a error.

DEPENDENCIES
============

   The module is implemented using Filter::Util::Call and Text::Balanced
and requires both these modules to be installed.

AUTHOR
======

   Damian Conway (damian@conway.org)

BUGS
====

   There are undoubtedly serious bugs lurking somewhere in code this funky
:-) Bug reports and other feedback are most welcome.

COPYRIGHT
=========

   Copyright (c) 1997-2000, Damian Conway. All Rights Reserved.  This
module is free software. It may be used, redistributed and/or modified
under the terms of the Perl Artistic License   (see
http://www.perl.com/perl/misc/Artistic.html)

front-end to all the Athena and Xlib garbage for Perl GUI progamming
********************************************************************

NAME
====

   Sx - front-end to all the Athena and Xlib garbage for Perl GUI
progamming

DESCRIPTION
===========

   Using the Sx package is pretty simple.  At the minimum, you 'use Sx;'
To actually have X windows pop open and such, you need to do the following:

  1. To get everything started, you should call OpenDisplay().  If
     OpenDisplay() returns a non-zero value, it's ok to go on.
     OpenDisplay() creates what will eventually be your first window.

  2. After calling OpenDisplay(), you can go on to create all sorts of
     widgets with the MakeXXX() calls.  You can lay them out with calls to
     SetWidgetPos().

  3. When you are done creating the user interface, call ShowDisplay().
     This causes the window and components you've created to be displayed
     on the workstation screen.

     Until you call ShowDisplay(), the user can *NOT* see your window, and
     drawing into drawing areas has *NO* effect.

  4. If you need to, you can call any of the color allocation functions
     such as GetStandardColors(), etc.

  5. Finally, once the window is displayed and you've done all the
     initializations you wish, you must then call MainLoop(). After you
     call MainLoop(), events get processed as they come in and your
     callback functions are called as necessary.

     After calling MainLoop(), the correct way for your program to exit is
     to have one of your callback routines call exit() when appropriate
     (like after the user clicks on a "Quit" button).

        That's all you need to do.  Even though that may look like a lot to
do, it's really pretty simple in practice.  For example, here is a hello
world program with libsx:

     use Sx;

     OpenDisplay(@ARGV);
     MakeLabel("Hello World!");
     ShowDisplay;
     MainLoop;

   Granted it's one more line than a standard printf() type of hello world
program, but it's not all that bad.

   Hello world programs are nice, but you don't tend to write very many of
them.  Real applications need to be able to do much more.  Even these
"real" programs aren't all that bad in libsx.

   Here is a simple program that opens a window with a quit button and a
drawing area that you could use to draw whatever graphics you wanted:

     use Sx;

     sub quit { exit }

     sub draw_stuff {
       my($widget, $width, $height, $data) = @_;
       ClearDrawArea;
       DrawLine(0,0, $width, $height);   # just draw a diagonal line
     }

     $res = OpenDisplay("My Window",@ARGV);
     exit unless($res);

     $w[0] = MakeButton("Quit", \&quit, Nullsx);
     $w[1] = MakeDrawArea(300,300, \&draw_stuff, Nullsx);

     SetWidgetPos($w[1], PLACE_UNDER, $w[0], NO_CARE, Nullsx);

     ShowDisplay;
     GetStandardColors;

     MainLoop;   # off we go!

   The code above is the basic skeleton for a Sx program, even complicated
ones.  First you open the display with OpenDisplay().  Then you build your
interface by creating a bunch of widgets with the MakeXXX() calls.  Next
you layout the display by specifying the relative positions of the widgets
to each other.  Then you would get any fonts or colors you may need, and
finally you just enter the main loop.

   In Sx, your callback functions are where all the real work happens.
The program above has two callback functions, quit() and draw_stuff().
They are tied to events that happen in the interface.  When the user
clicks on the "Quit" button, your quit() function is called.  When the
drawing area gets resized or needs to be redrawn, your draw_stuff()
function gets called.

   Usually the process of creating the interface would get separated into
a separate function that is easy to modify (instead of cluttering up
main).   However, the basic outline is the same as above.  The only real
difference with more complicated interfaces is that they usually have a
lot more calls to the MakeXXX() functions and they tend to make use of the
extra void pointer argument in the callback routines.

GENERAL NOTES
-------------

Specifying Callbacks
     A callback for Sx is a code reference. As such, you can use whatever
     syntax you prefer to specify it :

     MakeButton('Quit',\&MyExit,$data);		# Direct Hard reference

     MakeButton('Quit','MyExit',$data);		# Direct Soft reference

     $callback = \&MyExit; MakeButton('Quit',$callback,$data);		#
     Hard reference in a variable

     $callback = 'MyExit'; MakeButton('Quit',$callback,$data);		#
     Soft reference in a variable

     MakeButton('Quit',sub { &MyExit }, $data);	# Anon sub

The $data parameter
     Most widgets (all those with a callback function associated) takes a
     $data parameter. This value will be passed to the callback along with
     other values depending on the widget. This parameter can be any kind
     of scalar value, i.e. you can use it to pass reference to other
     variables or anonymous constructs. If you don't need it, just use
     undef.

X Ressources
     OpenDisplay can be called with a list of arguments. The first argument
     should be the name of the application. The remaining arguments are
     parsed and any X-like commands is taken in account. OpenDisplay will
     return the list of all its argument which couldn't be recognized as
     standard X command-line arguments.

     All non-list widgets (i.e. anything but MakeScrollList and
     MakeThreeList) can take a last, optional, name argument. You can use
     this in conjunction with the application name passed to OpenDisplay
     to make your widget sensitive to ressource management through xrdb.
     By default, if you don't specify a name, widgets are created with
     their types as name (all widgets resulting from MakeButton calls will
     be called "button" and so on).

LABELS
------

   A label widget is a widget that displays some text or bitmap but can
not be clicked on or interacted with by the user.  Generally a label is
for informational purposes, such as saying what the current file name is.

`MakeLabel(txt)'
     This function creates a label that contains the text in the string
     pointed to by "txt".  The text will simply be displayed, with no
     fancy borders or special highlighting.  If the text contains new line
     characters, they will be interpreted properly.

     If the argument txt is NULL, then no label will be set for the widget.
     This is convenient if you plan to put a bitmap on this widget with the
     SetWidgetBitmap() function.

     This widget is useful for displaying a piece of textual information
     like a filename or user name.

     If this routine fails, FALSE is returned.

BUTTON WIDGETS
--------------

   A button widget is a button that a user can click on with the left
mouse button to indicate an action.  When a button is pressed, it is drawn
in inverse video and some action takes place.

   A button is connected to your code by a callback function which is
called when the user clicks on the button widget with the left mouse
button.

`MakeButton(label, callback, data)'
     This function creates a small rectangular button which the user can
     click on.  The character string pointed at by "label" will be printed
     inside the button.  If the string has newline characters in it, they
     will be interpreted properly (i.e. you will get a multiline label).
     The next two arguments are a callback function, and an arbitrary perl
     value that will be passed to the function.

     If you plan to attach a bitmap to this widget, you can specify Nullsx
     for the label text (see the docs for SetWidgetBitmap()).

     When the button is pressed, the callback will be called.  This
     function will have two arguments: the widget that user clicked on
     (which you can ignore if you do not need it) and the 'data',
     specified in the call to MakeButton().

`Make3Button(label,call1,call2,call3,data)'
     This is just a convenience function to avoid some translation table
     munging.  This function will create a button, but you can specify a
     different callback (or 'undef' if unwanted) for button 1, 2 or 3.

TOGGLES
-------

   A toggle widget is similar to a button widget except that it maintains
state.  That is, when a user clicks a toggle widget, it remains
highlighted until it is clicked again.  This is similar to an on/off
switch.

   Toggle widgets can also be used to create a group of "radio buttons".
A radio button group is a set of toggle widgets in which at most one of
them can be selected at any one time (it is possible for none of them to
be selected).

`MakeToggle(txt, state, widget, func, data)'
     This function makes a widget that will toggle between a highlighted
     `on' state and an unhighlighted `off' state.

     The first argument is the text that will be displayed inside the
     widget. The `state' argument is a boolean value of the initial state
     of the toggle button (TRUE == on/highlighted, FALSE == off).  The next
     argument, a Widget, is NULL if this widget is a simple toggle button
     by itself and not part of a radio group (described below).

     If you plan to display a bitmap for the toggle button, you may specify
     a NULL for the txt argument (and then call SetWidgetBitmap()).

     The func argument is a standard callback function. First argument will
     be the widget, the second argument the data you specified in the
     MakeToggle call.

     Each time the widget changes state, your callback function is called.
     That is, each time the user clicks the toggle, your function is
     called.

Radio Groups
------------

   It is possible to connect toggle widgets together to form a group of
widgets that are mutually exclusive.  That is to say, with a radio group,
you can have a set of widgets in which at most one of them will be
highlighted at any given time.  Therefore, if you had 3 widgets, A, B, and
C, only one could be highlighted at any one time, and clicking on another
unhighlights the current one and highlights the toggle clicked on.  This
is useful for selecting one choice of several (such as a size, which is
either small, medium or large, but not two at the same time).  Keep in
mind that it is possible for none of them to be selected.

   To build a radio group, you use the Widget argument of the MakeToggle()
function.  If you specify another valid toggle widget in the call to
MakeToggle(), the new widget becomes connected to the widget you
specified.  All the widgets you connect together form a radio group.  Any
single widget can *only* be in one radio group.

   Example:

     $widg1 = MakeToggleWidget("Thing 1", 1, Nullsx, 'func1', Nullsx);
     $widg2 = MakeToggleWidget("Thing 2", 0, $widg1, 'func2', Nullsx);
     $widg3 = MakeToggleWidget("Thing 3", 0, $widg1, 'func3', Nullsx);

   Notice how $widg2 and $widg3 specify $widg1 as their Widget argument.
This connects all three into a radio group in which only one can be set at
a time.  We initialize $widg1 to be initially set and the others off.  If
you specify more than one widget as `on', the results are undefined.

   The callback functions are called whenever a widget is highlighted or
unhighlighted.  The callbacks for the widget being unhighlighted happen
before the callbacks for the widget being highlighted.

`SetToggleState(widget, state)'
     SetToggleState() explicitly sets the state of a widget.

     The `state' argument is either TRUE (set the toggle to its highlighted
     state), or FALSE (unhighlight the widget). The callback routine for
     the widget is only called if there is a change in state.

`GetToggleState(widget)'
     This function returns the current state of the toggle widget.  The
     return values are either TRUE (the widget is selected) or FALSE (the
     widget is not highlighted).

SCROLL LIST
-----------

   A scroll list is a scrollable list of items organized in a veritical
fashion.  The user can scroll through the list of items using the mouse
and select individual items in the list of available choices.

`MakeScrollList(width, height, callback, data, list)'
     This function makes a scrollable list of items from which a user can
     select individual items.  The list contains strings of text.  The area
     given to display the list is width and height pixels large.  If the
     entire list will not fit, scrollbars appear that will let the user
     easily scroll through the list.

     The callback function, should expect to be called with a Widget
     argument, the string of text the user clicked on, the string's index
     in your table, and whatever user data you gave at widget creation time

     The list of strings passed in to MakeScrollList() must not be free()'d
     or otherwise deallocated for the entire lifetime of the widget (or
     until the list of strings is changed with ChangeScrollList()).

`GetCurrentListItem(widget)'
     This function returns the index of the currently selected item in the
     specified list widget.  The index value returned is an index into the
     table displayed by the list (specified when the widget was created or
     with ChangeScrollList()).

     If no item is selected in the list widget, this routine will return a
     -1.

`ChangeScrollList(widget, new_list)'
     This function changes the list of strings displayed by the list
     widget.  The new list of items is taken from the argument `new_list'.
     After this function is called, the old list can be free()'d.  Of
     course you can not free the new_list until the application is done or
     you change the list again.

`SetCurrentListItem(widget, index)'
     This function causes the item with specified index, to be highlighted
     in the list widget .  You must make sure that index is a valid index
     into the currently displayed list, results are undefined otherwise.

     After calling this function, the item with the this index will be
     highlighted in the list widget.

`Make3List(width,height,callback,data,array)'
     This function will do the same job as the standard MakeList call, but
     the callback function will be called on any button_down event and will
     have a new fourth argument which will be the event mask (see <X11/X.h>
     for values).

MENUS
-----

   Menus provide standard drop-down style menus that let the user select
from a variety of choices.  The Athena widgets do not support cascaded
menus, so a menu is only a single list of items.  A menu contains menu
items that are tied to callback functions in the application.  Menu items
must be text and can not be bitmaps.

`MakeMenu(name)'
     This function creates a menu button that contains the text pointed to
     by the character string name.  When the button is clicked, a menu pops
     up.  The menu contains items created with MakeMenuItem().

     You need to save the return value of this function to be able to pass
     it to MakeMenuItem() so that menu items can attached to a menu.

     If this function fails, it returns NULL.

`MakeMenuItem(menu, name, func, arg)'
     This function adds a menu item to a menu.  The menu item contains the
     text pointed to by the string name.  Whenever the user selects this
     menu item, the callback function, func, is called.  The final argument
     is an arbitrary value that is passed to the callback function.

     The first argument must be a widget returned by MakeMenu() (results
     are undefined if it is not).

     If MakeMenuItem() fails for any reason, a NULL is returned.

     Whenever the user selects this menu item, the callback will be called.

     Setting of widget attributes with SetFgColor(), SetBgColor(), etc work
     normally except that only one background color may be specified and it
     takes effect for the entire menu.  You can set different fonts for
     each menu item.

     NOTE: You do not need to call SetWidgetPos() for menu items.
     Successive menu items are placed below previous menu items.

`SetMenuItemChecked(widget, state)'
     This function sets the "checked" state of a menu item.  If a menu
     item is in the checked state, a bitmap of a check mark appears to the
     left of the menu item text.

     The first argument, w, is a menu item widget created with
     MakeMenuItem().  The second argument, state, is a boolean value of
     either TRUE (1) or FALSE (0) indicating whether or not the check mark
     should be drawn to the left of the menu item.  If the state argument
     is TRUE, the check mark is drawn.  If the state argument is FALSE, the
     check mark is removed.

`GetMenuItemChecked(widget)'
     This function returns a boolean result indicating whether the menu
     item referred to by the specified widget, is checked or not.

     If the menu item referred to by `w' is checked, a value of TRUE (1) is
     returned.  If the menu item does not currently have a check mark next
     to it, a value of FALSE (0) is returned.

SCROLLBARS
----------

   A scrollbar is a widget that allows a user to control some numeric
quantity interactively by using the mouse to scroll a slider, similar to
the volume slider on some radios.  The slider is called the "thumb" or
"thumb area" in X terminoligy.

`MakeHorizScrollbar(length, scroll_func, data)'
`MakeVertScrollbar(height,  scroll_func, data)'
     These two routines create scrollbars.  Scrollbars allow the user to
     interactively control some numeric quantity with the mouse.

     When the user presses the left mouse button, the value represented by
     the scrollbar increases.  When the press the middle mouse button, they
     can interactively adjust the value.  Clicking the right mouse button
     decreases the value represented by the scrollbar.

     The arguments to create a scrollbar are its length or height in
     pixels, a callback function to call when the scrollbar changes value
     and an extra void pointer argument that is passed to the callback
     function.

     If these routines fail, they return NULL.

     To set what values a scrollbar represents, you must use
     SetScrollbar().  These two routines only make a scrollbar and do not
     set it to return useful values.  You always have to call
     SetScrollbar() to set what a scrollbar represents (see the
     documentation for SetScrollbar() for more information).

     Your callback routine is called everytime the scrollbar changes.
     Since the calculations are done in floating point, the value may not
     have changed enough to be interesting, but your routine is still
     called.  You should take care to see that the value changed enough to
     be interesting to your applications (i.e. it is wasteful for a text
     editor to repaint the window when the new value is 0.003 different
     than the old value).

     A scrollbar callback routine should look like:

          sub scroll_func {
          	my($widget, $new_val, $data) = @_;
          }

     The first argument is the scrollbar widget that the user is
     manipulating.  The second argument is a floating point value that
     represents the new value of the scrollbar.  The third argument is the
     argument that was passed to *Make{Horiz,Vert}Scrollbar()*.

`SetScrollbar(widget, where, max, size_shown)'
     This function lets you set the values that a scrollbar represents.
     The first argument is a scrollbar widget.  The next three arguments
     are floating point numbers that specify the parameters of the
     scrollbar.

     Before discussing the details of the three float arguments, let us get
     some terms straight.  When we refer to the `container' of a scrollbar,
     we mean the entire box that makes up the scrollbar.  The `thumb' of a
     scrollbar is the gray area that the user can grab to manipulate.  We
     refer to the size or length of the thumb area (the amount of grey) as
     the `size shown'.  The total amount represented by the scrollbar is
     called `max'.

     The arguments mean the following:

    `where '
          This floating point number specifies where in the container the
          top of the thumb area should start.  If you have a maximum value
          of 100 and where is 50, the beginning of the thumb will be in
          the middle of the container.

    `max '
          The maximum value that the scroll bar can have.  You will
          receive numbers in the range 0 to max (inclusive).  Obviously
          max should be a positive, and is a float.

    `size_shown '
          This float value controls how big the grey area that the user
          can grab is.  This represents how much of whatever it is you are
          representing is visible.  For example, a text editor which shows
          24 lines of text would set size_shown to be 24 (out of whatever
          max is).  If you want the scrollbar to represent a percentage of
          something, where when it is 100%, the grey area is also 100% of
          the box, then you should set the size_shown to be equal to max.
          If this is confusing, there are examples below.

     Now, some examples to clarify things (in the following, assume that
     the argument, w, represents a scrollbar widget created with the
     MakeHorizScrollbar or MakeVertScrollbar() routines).

     For the first example, let's assume you want a scrollbar to let you
     set a color value which can range between 0 and 255 with the initial
     value at 67.  You sould set the scrollbar as follows:

          SetScrollbar($w, 67.0, 255.0, 1.0);

     The first value, 67.0, is where we would like the beginning of the
     thumb area to appear.  The next value, 255, is the maximum value the
     scrollbar can attain.  The third value, 1, is the size of the thumb
     area (the amount represented by the thumb relative to the maximum
     size).  This scrollbar will now return values in the range of 0 to 255
     (inclusive).  The thumb area will be small, and represents one value
     of the 255 possible divisions.  The position of the thumb area in the
     container represents its value.

     For the next example, suppose we wish to make a scrollbar represent
     some percentage of a value.  That is, the size of the thumb area
     should be proportional to the value of the scrollbar relative to its
     maximum (so when the value is at it maximum, the thumb area is 100% of
     the scrollbar).

     In this case we would like the size of the thumb area to represent the
     amount of the variable (note the difference from the above example).
     Let us suppose we want a scrollbar which can represent a percentage 0
     to 100, with the initial value being 50.

          SetScrollbar($w, 50.0, 100.0, 100.0);

     The first value, 50, is where the thumb area begins (in the middle of
     the container).  The next number is 100, and represents the maximum
     value of the scrollbar.  The next number, again 100, is the size
     shown.  Making this value the same as the max value (in this case
     100) causes the thumb area to vary according to the value the
     scrollbar represents.

     As a final example, let us take a text editor which is displaying a
     file.  In this case, let us assume the text file is 259 lines long,
     the window can display 47 lines, and the top line currently displayed
     is 72.  To create the correct scrollbar, we would do the following:

          SetScrollbar($w, 72.0, 259.0, 47.0);

     This creates a scrollbar which has a thumb area whose size is 47/259
     of the entire container, and is positioned 72/259'ths of the way down
     the container.

STRING ENTRY
------------

   A string entry widget is a widget that lets a user enter a single line
of ASCII text.  When the user presses return in the widget, a callback is
made to your application with a pointer to the new text.  Support routines
also exist to Set and Get the text in the widget.

   If you want multiple lines of text, see the text edit widget
documentation.

`MakeStringEntry(txt, size, func, data)'
     This function makes a string input widget.  A string input widget is a
     widget that lets a user enter/edit a single line string value such as
     a filename.

     The first argument is any default text you would like in the string
     entry widget.  You can specify "" if you don't want anything to
     appear.

     The next argument is the width in pixels of the string entry area.  Be
     careful in specifying the width since the default font used by the
     widget may not be wide enough to contain the text you want.  It is
     best if you call GetWidgetFont() and then call TextWidth() on a string
     of reasonable length and use the value returned by TextWidth() to be
     the width of the widget.  If you're lazy, a value of 150-200 is
     usually pretty good.

     The next argument is a callback function that is called whenever the
     user presses return in the string entry widget.  The first argument to
     the callback is the widget where the user pressed return.  For the
     most part you can ignore this (unless you want to change the text).
     The second argument is the string of text the user entered.  The final
     argument is the user data you passed in to MakeStringEntry().

`SetStringEntry(widget, new_text)'
     This function allows you to change the string of text displayed in a
     string entry widget.

     The first argument is the widget in which you would like to change the
     string (this widget should be a string entry widget).  The second
     argument is a pointer to the new text you would like displayed in the
     string entry area.

`GetStringEntry(widget)'
     This function lets you retrieve the text a user entered in a string
     widget.  The widget argument should be a string entry widget.

     The return value of this function is the string that is the contents
     of the string entry widget.

     If there is a problem, the function returns NULL.

TEXT EDIT
---------

   A text edit widget is an area used to display and optionally edit
multiple lines of text.  You can specify the text to be displayed as
either an in memory string or as a file name.  The text edit area manages
its scrollbars and internal affairs, you need not do anything (in fact
there are no callbacks for the text edit widget).

`MakeTextWidget(txt, is_file, editable, width, height)'
     This functions lets you create a text edit widget that will display
     some text and optionally let the user edit and manipulate it.  The
     first argument, txt, is a string (empty string is ok). The second
     argument, is_file, is a boolean value indicating if the first argument
     should be interpreted as a file name or not.  The next argument,
     editable, is a boolean value indicating whether or not the user is
     allowed to edit the text.  The final two arguments specify the width
     and height of the drawing area box.  If the area is too small to
     display the text, scrollbars will appear.

     The txt argument can either contain the entire string that you would
     like the user to edit, or it can contain the name of a file to be
     loaded into the text edit widget.  If the second argument is_file is
     TRUE (1), then the first argument gets interpreted as a file name.  If
     is_file is FALSE (0), then the first argument contains the actual text
     to be displayed.

     The argument `editable' is a boolean value indicating whether or not
     to allow editing of the text in the widget.  If you just wish to
     display some text (such as a help file), set the editable argument to
     FALSE (0) and the user will not be allowed to modify the text.

`SetTextWidgetText(widget, text, is_file)'
     This argument lets you modify the text displayed in a text edit
     widget.  The first argument identifies the text edit widget to change.
     The second argument is a string that either contains the actual text
     to display or the name of a file to read in.  If the is_file argument
     is TRUE (1), then the string pointed to by the argument, text, is
     interpreted as a file name.  If is_file is FALSE, the string pointed
     to by text is directly displayed in the text edit widget.

     If you wish to update the displayed text again, you should call
     SetTextWidgetText() again.

     BUGS: The function name is way too long.

`GetTextWidgetText(widget)'
     This function lets you retrieve the text contained in a text edit
     widget.  The only argument should be a text edit widget created with
     MakeTextWidget().

     The return from this function is a string that contains the current
     text in the widget.  If there is an error, a NULL is returned.

     BUGS: The function name is way too long.

FORMS
-----

`MakeForm(parent, where1, from1, where2, from2)'
     This function lets you create a new "form" widget in which to put
     child widgets.  A form widget is a container that holds other widgets.
     Normally there is no need to call this function, but if you want to
     have separate "groups" of widgets in your display and you can't lay
     them out that way with SetWidgetPos(), then using multiple form
     widgets may be the right thing.  In addition, a nifty little box gets
     drawn around the form widget (and all the children) and this can be a
     nice visual cue in your interface indicating what groups of widgets
     belong together.  A form widget creates a box that surrounds all the
     widgets contained inside of it (but the form widget itself is inactive
     and can't be clicked on by the user).

     If you use multiple form widgets in your display, the basic logic of
     how you create the display is a little different.  You can think of
     form widgets as miniature windows inside a larger window.

     Once you create a form widget, any other widgets you create with calls
     like MakeButton() and MakeLabel() become children of this form widget.
     Before you create another form widget, you must lay out all the
     children of the current form widget with calls to SetWidgetPos().
     After you lay out all the children of the current widget, then you can
     create another form widget, and repeat the process (or call
     SetForm()).

     Form widgets are layed out in a manner similar to regular widgets,
     except that usually their placement is relative to other form widgets.
     When you create a new form widget (after the first one), you specify
     where it should be placed relative to other form widgets that you
     created.  The first form widget is always placed in the top left
     corner of the window.

     The `parent' argument to MakeForm() specifies at what level the new
     form should be created.  If you specify TOP_LEVEL_FORM (which is the
     usual thing to do) the new form is created at the top level of the
     window.  If you pass another form widget for `parent', then this new
     form widget will be a child of the other form widget.  This lets you
     create hierarchical "boxes" in your display.

     The arguments where1, from1, where2, from2 are the same as in
     SetWidgetPos().  That is, you specify either NO_CARE, PLACE_UNDER, or
     PLACE_RIGHT for where1 and where2 and the from1/from2 arguments are
     the widgets you would like to place something to the right of or under
     (or they are NULL if you specified NO_CARE).  See SetWidgetPos() for
     more documentation.

     Now for an example:

     Let's say we want a display something like this:

          +------------+   +-----------------------+
          | +--------+ |   | +-------------------+ |
          | |  Btn1  | |   | |                   | |
          | +--------+ |   | |                   | |
          |            |   | |                   | |
          | +--------+ |   | |                   | |
          | |  Btn2  | |   | |                   | |
          | +--------+ |   | |                   | |
          +------------+   | |                   | |
                           | |                   | |
                           | |                   | |
                           | +-------------------+ |
                           +-----------------------+

     We have two rectangles (forms) which contain other widgets.  Inside
     the leftmost form are two buttons.  The form on the right has a single
     drawing area.  Skipping some of the unnecessary details, we could
     accomplish the above display with the following code:

          $form1 = MakeForm(TOP_LEVEL_FORM, NO_CARE, Nullsx, NO_CARE, Nullsx);
          $w[0]  = MakeButton("Btn1", Nullsx, Nullsx);
          $w[1]  = MakeButton("Btn2", Nullsx, Nullsx);

          SetWidgetPos($w[1], PLACE_UNDER, $w[0], NO_CARE, Nullsx);

          $form2 = MakeForm(TOP_LEVEL_FORM, PLACE_RIGHT, $form1, NO_CARE, Nullsx);
          $w[2]  = MakeDrawArea(200, 200, Nullsx, Nullsx);

     As you can see, we create the first form and specify that we don't
     care where it goes (the first form widget is always placed in the top
     left corner of the window).  Then we create some widgets to place
     inside of our new form.  Next, and this is important, we layout all
     the widgets inside of the first form.  In this case we only need to
     make one call to SetWidgetPos().  Then we create the next form, and
     specify that we want to place it to the right of form1.  Finally we
     create a drawing area widget, which is placed inside of form2.

     If you want to create hiearchies of form widgets, you would specify
     the form widget that should be the parent for the first argument to
     MakeForm().  This can get quite complicted, so you should make sure
     you know what you're doing if you want to create big hierarchies.

     NOTE: It is important that you layout all your widgets before you
     create a new form (unless you're creating a child form).

`SetForm(widget)'
     The SetForm() function allows you to change what is considered the
     current form.  Normally you only use this function to set the current
     form to be TOP_LEVEL_FORM.  You can cause your program to crash if you
     are not careful about what you set as the current form.

     The main purpose of this function is to let you create displays that
     have both form widgets and other "normal" widgets at the same level.
     Mainly you would want to do this if you wanted a large drawing area
     (or some other type of widget) but didn't want to bother creating an
     form widget just to hold that one widget.

     After calling this function, you can position any new widgets
     relative to other widgets (usually form widgets) created at the top
     level of the window.

     The normal calling sequence is: `SetForm(TOP_LEVEL_FORM)', although
     you can specify any other form widget you like.  Be careful, as it is
     possible to confuse the X layout routines and cause your program to
     crash.

     NOTE: Before you call SetForm() and start creating new widgets and
     positioning them, any previous form widgets should be completely
     layed out (i.e. you called SetWidgetPos() for all child widgets of
     any previously created form widgets).

WINDOWS
-------

   This file contains descriptions of the main high level startup and
window creation functions.

`OpenDisplay(args)'
     This function initiates everything with Sx.  You should call this
     function before you call any of the other functions.  A correctly
     written application will call OpenDisplay(), passing its command line
     arguments and count.  The return value from this function is the new
     list of arguments (or zero if an error occurred).  The X libraries
     accept various standard command line options such as -display or
     -font, and if your application passes the command line arguments to
     OpenDisplay(), these will be handled properly.  Any X options are
     removed from the return array, therefore it is best if you do your
     command line processing after calling OpenDisplay().

     You only need to call this function once to initialize the first
     window your program uses.  Any other windows you need should be
     created with MakeWindow().

     This function returns FALSE (0) if something went wrong (like being
     unable to open the display, etc). If everything went ok, it returns
     the new list of arguments as its result.

`ShowDisplay()'
     This function displays the currently active window (user interface)
     you've created with the MakeXXX() calls.  After this call completes,
     the interface will be visible on the display.

     Until you call this function, your interface will not be visible and
     drawing into a draw area will have no effect.

     Usually one calls ShowDisplay(), allocates some colors and then
     immediately calls MainLoop().

`MainLoop()'
     After calling this function, your program yields control to the user
     interface, and it is entirely driven by what the user does and the
     callbacks associated with the various widgets.  For a single window
     application, the general flow of events is:

          OpenDisplay(@ARGV);        # initialize the first window

          MakeXXX(....);             # create widgets

          ShowDisplay;               # put the window on the screen
                                     # optionally allocate colors
          MainLoop;                  # start the main loop going

     When you call this after calling ShowDisplay() for your first window
     (created by OpenDisplay()), the MainLoop() function never returns and
     your application should have some callback function that will exit()
     the program (such as a quit button or menu option).

     You should not call MainLoop() for NONEXCLUSIVE mode windows created
     with MakeWindow().  Those type of windows have their callbacks handled
     by the MainLoop() function that is already executing (i.e. the one you
     called for your original window).

     If the window is an EXCLUSIVE mode window, then MainLoop() keeps
     executing until CloseWindow() is called on the EXCLUSIVE mode window.
     That is, MainLoop() blocks until the EXCLUSIVE mode window is closed,
     and then it returns.

     If you create a non-exclusive mode window, the general order of events
     is:

          MakeWindow(NONEXCLUSIVE_WINDOW, ....);
          MakeXXX(...);
          ShowDisplay;

     This creates a window, puts interface objects into it, and then puts
     that window on the screen.  No other actions need to be taken, and
     when the callback that created this new window returns, all processing
     takes place normally, including the processing of the new window and
     its callbacks.

     For a window of EXCLUSIVE_WINDOW mode (like a popup), the general
     order execution is:

          MakeWindow(EXCLUSIVE_WINDOW, ....);
          MakeXXX(...);
          ShowDisplay;

          MainLoop;     # blocks until CloseWindow() is called

          # do something with whatever values the popup got for us

     When MainLoop() returns for an EXCLUSIVE_WINDOW, the window has been
     closed.

`SyncDisplay(void)'
     This function synchronizes the display with all drawing requests you
     have made.  Normally it is not necessary to call this function, but if
     you make many repeated function calls to draw graphics, they will be
     updated in a chunky fashion because X buffers drawing requests and
     sends a bunch of them at once.

     After this function completes, all drawing requests you have made are
     visible on the screen.

     NOTE: Normally you do not need to call this function because X ensures
     that everything you request gets drawn, but sometimes it is necessary
     to insure the synchronization of the display.

`MakeWindow(window_name, display_name, exclusive)'
     NOTE: Do not call this function to open your first window. Your
     application's first window is opened for you by OpenDisplay().  If
     your application only needs one window, do NOT call this function.

     This function opens a new window, possibly on a different display
     (workstation).  The new window has the name specified by the argument
     window_name and is opened on the display named by display_name (a
     string usually in the form of, "machine_name:0.0").  The final
     argument indicates whether the window should be an exclusive window or
     not (described below).

     After this functions returns, the current window is the one you just
     created and you can begin adding widgets to it with the MakeXXX()
     calls.  After have created and added any widgets you want, you should
     call ShowDisplay(), and if the window is an EXCLUSIVE_MODE window,
     then you should call MainLoop() (which blocks until the window is
     closed).  If you opened the window with the NONEXCLUSIVE_WINDOW
     option, you should NOT call MainLoop().

     If you pass SAME_DISPLAY, for the display name, the window opens on
     the same display as the original window opened by OpenDisplay().

     The argument, exclusive, indicates what type of window to open.  A
     normal window is a NONEXCLUSIVE_WINDOW.  That is, it will not block
     the user from interacting with your existing window.  An
     EXCLUSIVE_WINDOW is a popup window that blocks input to your main
     window until the popup is closed with CloseWindow().

     The EXCLUSIVE_WINDOW mode is useful for requestors that need an answer
     and the user should not be able to do other things in the application.
     Of course some user-interface folks don't think modal windows like
     this are good, but tough cookies for them because some times it's
     necessary.

`SetCurrentWindow(widget)'
     This function sets the currently active window for other function
     calls such as CloseWindow().  If you have multiple windows open on
     several displays, you must call this function switch the currently
     active one when you wish to manipulate the various windows.

     The argument must be a valid value returned by MakeWindow().  If you
     would like to set the current window to be the original window opened
     by OpenDisplay(), you can pass the #define, ORIGINAL_WINDOW.

     When you change windows, the current drawing area is also changed to
     be the last current drawing area in the new window (if there is a
     drawing area in the new window).

`CloseWindow()'
     This function closes and removes from the display, the currently
     active window.

     After calling this function, you should not refer to any of the
     widgets contained in the window as they are invalid (as is the window
     handle).

PREDEFINED POP-UPS
------------------

   Popup windows are simple dialog boxes that get a simple yes/no or
string answer from the user.  When these windows popup, they block input
to the previously active window.

`GetYesNo(question)'
     This function allows you to prompt the user for the answer to a simple
     yes or no type of question.  It simply pops up a dialog box with the
     text contained in the string question, and two okay/cancel buttons.

     If the user clicks Okay, this function returns TRUE.  If the user
     clicks Cancel, this function returns FALSE.  The text in the question
     string can have embedded newlines (\n characters) to break things up
     or to add spacing.

     SEE ALSO : GetString()

`GetString(msg, default)'
     This function allows you to prompt the user for a string of input.
     The first argument, msg, is a pointer to a string which will be
     displayed in the dialog box.  The next argument, default, is the
     default string to place in the text string box (it can be NULL or "").

     When you call this function, it pops up a small dialog box on the
     screen, and the user can enter the line of text.  When the user clicks
     ok or cancel, the function returns a pointer to the string of text the
     user entered.

     If the user clicks cancel, you get a NULL return value.

     SEE ALSO : GetYesNo()

DRAW AREAS
----------

   A drawing area is a rectangular area that supports drawing into,
receiving input from (mouse clicks, mouse motion and keypresses) and
redisplay requests from X.  You can draw any sort of graphics into a
drawing area as well as perform various types of interaction with mouse
and keyboard input.

`MakeDrawArea(width, height, callback, data)'
     The function MakeDrawArea() creates a drawing area which you can later
     use to draw graphics into and receive mouse and keyboard input from.
     The drawing are will have a width and height as you specify.  The
     callback function is called whenever the drawing area should be
     redisplayed (because it was obscured or resized).  The argument "data"
     is any kind of Sxperl object you want, and it is passed directly to
     the resize callback (and the other callbacks as well).

     The redisplay callback is where you should put all of your drawing
     code.  It is called for you when the application opens the window for
     the first time (by calling MainLoop()).  The redisplay callback
     function should looks like:

          sub redisplay {
          	my($widget, $width, $height, $data) = @_
          }

     The first argument is the drawing area widget that needs to be
     redrawn.  The second and third arguments are the new width and height
     of the drawing area (it may have been resized).  The final argument
     is the data passed to MakeDrawArea().

     If you are interested in receiving other types of input, see the
     functions, SetButtonDownCB(), SetButtonUpCB(), SetKeypressCB() and
     SetMouseMotionCB().  These functions will let you set callbacks for
     the other types of input.

     Each drawing area you create has its own state (foreground and
     background colors, drawing mode, and line width).  Only one drawing
     area can be active at any given time.  When an event happens for a
     drawing area, that drawing area becomes the active drawing area.  You
     can make other drawing areas active with SetDrawArea().

     If something goes wrong in creating the DrawArea, a FALSE value is
     returned.

`SetButtonDownCB(w, callback)'
     This function sets up a callback that will be called everytime the
     user presses a mouse button in the specified drawing area widget `w'.

     The callback function should looks like:

          sub  callback {
          	my($widget, $which_button, $x, $y, $data) = @_;
          }

     Then, whenever the user presses a mouse button in the drawing area,
     your callback is called.  The first argument is the drawing area
     widget where the event happened.  The next argument is an integer
     specifying which button was pressed.  It is a small positive integer.
     A value of one is the left mouse button, two is the middle mouse
     button and three is the right mouse button.  Technically, values of
     four and five are also possible though I've never seen a mouse with
     five buttons.  The x and y arguments are the position of the mouse
     where the user pressed the mouse button.  The final argument is the
     data argument given to MakeDrawArea().

     You can specify a null string for the function to turn off receiving
     button down events.

`SetButtonUpCB(widget, button_up)'
     This function sets up a callback that will be called everytime the
     user releases a mouse button in the specified drawing area widget `w'.

     Same behaviour as for SetButtonDownCB().

`SetKeypressCB(widget, callback)'
     This function lets you set a callback so that you will receive
     keyboard input in the drawing area.

     The callback function should looks like:

          sub  callback {
          	my($widget, $input, $up_or_down, $data) = @_;
          }

     Then, whenever the user presses keys in the drawing area, your
     callback function is called.  The first argument is the drawing area
     widget where the event happened.  The next argument is a string that
     contains what was typed by the user.  The up_or_down argument
     indicates whether the key was pressed released (a zero indicates a
     press, a 1 indicates a key release). The final argument is the
     argument given to MakeDrawArea().

     It is useful to know that the string returned to your program is not
     necessarily a single ASCII character. You will get the usual ASCII
     characters, including control characters (such as ^C or ^H).  But,
     the workstation's function keys will also be returned in a string
     such as "F11" or "F23".  You will also get other longer strings such
     as "Control_L", "Alt_R", or "Shift_L".  It is important to understand
     that even if you just press the shift key to get a capital letter,
     you will first receive the string "Shift_L" or "Shift_R", then you
     will receive a capital letter (say, "H").  You should probably ignore
     the "Shift_L" or "Shift_R" messages (but who knows, you may find some
     use for them).

     The argument, up_or_down, tells you whether the given key was pressed
     or released.  If the key was pressed down, up_or_down has a zero (0),
     if the key was released, up_or_down contains a 1.  This is useful for
     doing things like shift-clicking with the mouse or handling
     control-key combinations in an editor or other program.

     The arrow keys return strings such as "Left", "Up", "Right", or
     "Down".  Other keys on the keyboard may return strings such as "Home",
     "Prior", "Next", "Undo", "Help", etc.  Of course not all keyboards
     generate all of the strings (because they aren't set up to).

     You can specify a NULL for the function to turn off receiving keypress
     events.

`SetMouseMotionCB(widget, callback)'
     This function sets a callback so that whenever the mouse moves in your
     drawing area, the specified function will be called.  It is important
     to keep in mind that the function you specify is called every time
     the mouse moves in the drawing area, even if it is just passing
     through.

     The callback function should looks like:

          sub  callback {
          	my($widget, $x, $y, $data) = @_;
          }

     The first argument is (as usual) the Widget where the mouse was moved
     in.  The next two arguments are the current X and Y values of the
     mouse.  The final argument is the argument passed into MakeDrawArea().

     You should be very frugal with what happens in this function so as not
     to cause the application to lag behind the user too much.  Calling
     functions like sleep() are definitely out of the question.

     You can specify a NULL for the function to turn off receiving mouse
     motion events.

DRAWING
-------

   This contains documentation about the routines that let you draw in a
drawing area.

   The documentation for these functions is quite brief because they are
not all that complicated (how much can one really say about DrawLine()).

   Keep in mind that for all the drawing functions, the top-left corner of
a drawing area is considered to be 0,0.

   Also, all primitives are drawn in the current foreground color (set
either by SetColor() or SetFgColor().  Text is drawn with the current
foreground color and the background color.  Line, arc, and box primitives
are drawn with the current line width (as set by SetLineWidth()), and all
primitives are drawn in the current draw mode (set by SetDrawMode()).

`SetDrawArea(widget)'
     This sets the current drawing area to be that named by the Widget w.
     If `w' is not a drawing area widget, nothing happens.

     You need to call this function when you want to switch between
     multiple drawing areas.

     If you only have one drawing area you do not need to worry about this
     function at all.

     Any callbacks for a drawing area already have the current drawing area
     set to be the one where the event happened (so it is not necessary to
     call this function in a callback for a drawing area).

`SetColor(color)'
     This sets the foreground color to draw with in the current drawing
     area (each drawing area has its own foreground color).  The argument
     "color" should be a valid color obtained with one of the color
     functions (such as GetNamedColor() or GetRGBColor(), etc).

     To some extent this function duplicates the SetFgColor() function, but
     exists because it is faster than SetFgColor().

`SetLineWidth(width)'
     This functions sets the width of lines drawn in the current drawing
     area.  Each drawing area has its own line width.

     A width of zero is valid and tells the X server to draw lines as fast
     as it possibly can, possibly being a little inaccurate.  Larger
     numbers of course draw wider lines.

`SetDrawMode(mode)'
     This function sets the drawing mode for the current drawing area.  A
     drawing mode is one of:

          GXcopy, GXxor, GXinvert, GXor, GXclear,
          GXand, GXandReverse, GXnoop, GXnor, GXequiv,
          GXinvert, GXorReverse, GXcopyInverted,
          GXorInverted, GXnand, and GXset

     Most of these are stupid/useless modes defined by X (so ignore them).

     The primary mode is GXcopy (the default mode).  This causes all
     primitives to draw in the foreground color, overwriting any pixels
     already drawn.

     Libsx also defines a special mode: SANE_XOR.  The SANE_XOR mode will
     actually draw primitives in a true XOR mode so that you can draw
     things like rubber-band boxes that the user stretches with the mouse.
     You must use SANE_XOR if you want true XOR'ed primitives, GXxor will
     definitely NOT work as you expect.

     When you are done using SANE_XOR, you would normally call
     SetDrawMode() with an argument of GXcopy to restore normal drawing.

`GetDrawAreaSize(width, height)'
     This is a convience function that returns the size of the current
     drawing area.  The window dimension are returned in the two variables.

`ClearDisplay()'
     This function completely clears the current drawing area and sets it
     to the current background color (which may not be white).

     Generally, when your redisplay callback is called, this is the first
     thing want to do.

`DrawPixel(x1, y1)'
     This function draws a point in the current foreground color at the
     location x1, y1 in your current drawing area.  The top left corner of
     the drawing area is considered 0,0.

`GetPixel(x1, y1)'
     This function retrieves the pixel value at the location x1, y1 in the
     current drawing area.  The top left corner of the drawing area is
     considered 0,0.

     The pixel value returned to you will be between 0 and 255 (inclusive).
     The value you get back should be treated as an index to a colormap.
     To find out what actual color is displayed at that location, you need
     to look up the color in the colormap (which you should be maintaining
     as there is no way to get it after you've set it).

     NOTE: This function is *NOT* very high performance. It has to call
     GetImage() to do the bulk of the work.  This is unfortunate, but
     unavoidable because X does not provide an easy way to read individual
     pixels.

`DrawLine(x1, y1, x2, y2)'
     This function draws a line from x1,y1 to x2,y2 in the current
     foreground color in the current drawing area.  The top left corner of
     the drawing area is considered 0,0.

`DrawPolyline(@points)'
     This function accepts an array of points and draws them as a connected
     polyline on the display.  The line is drawn in the current foreground
     color in the current drawing area. The top left corner of the drawing
     area is considered 0,0.

     The `points' argument is a list of consecutive x, y pairs.

`DrawFilledPolygon (@points)'
     This function takes an array of points and draws them as a filled
     polygon on the display.  The polygon is filled with the current
     foreground color and is drawn in the current drawing area. The top
     left corner of the drawing area is considered 0,0.

`DrawBox(x, y, width, height)'
     This function draws a rectangular box starting at x,y with a width and
     height as specified.  If you make the call: `DrawBox(50,50,75,75)',
     you will get a box that starts at position 50,50 and goes for 75
     pixels in the X and Y directions (i.e the other extreme of the box
     would be at 125,125). The box is drawn in the current foreground
     color in the current drawing area. The top left corner of the drawing
     area is considered 0,0.

     If the width and height are negative, the box is still drawn properly.

`DrawFilledBox(x, y, width, height)'
     This function draws a filled rectangular box starting at x,y with a
     width and height as specified.  If you make the call:
     `DrawFilledBox(50,50,75,75)', you will get a filled box that starts at
     position 50,50 and goes for 75 pixels in the X and Y directions (i.e
     the other extreme of the box would be at 125,125). The box is filled
     with the current foreground color in the current drawing area. The top
     left corner of the drawing area is considered 0,0.

     If the width and height are negative, the box is still drawn properly.

`DrawText(string, x, y)'
     This function prints the text string "string" starting at x,y.  The
     text is drawn in the current foreground color.  The background of the
     text is filled with current background color of the drawing area
     widget.  The top left of the drawing area is 0,0.  The X,Y position
     you specify is the bottom left corner of where the text is drawn.

`DrawArc(x, y, width, height, angle1, angle2)'
     This function draws an arc/ellipse from the location x,y that is
     bounded by the box defined by the x,y, width and height.  That is, the
     arc/ellipse will always be contained in the box defined by the x,y
     position and the width and height arguments.  The X,Y arguments are
     not the center of the arc/circle.

     The arc begines at angle1 degrees and continues for angle2 degrees
     around the circle.  The arc is drawn in the current foreground color
     in the current drawing area. The top left corner of the drawing area
     is considered 0,0.

     If you want a circle, you would specify angle1 as 0, and angle2 as
     360.

     If the width and height are negative, the arc is still drawn properly.

`DrawFilledArc(x, y, width, height, angle1, angle2)'
     This function draws a filled arc/ellipse from the location x,y that is
     bounded by the box defined by the x,y, width and height.  That is, the
     arc/ellipse will always be contained in the box defined by the x,y
     position and the width and height arguments.  The X,Y arguments are
     not the center of the arc/circle.

     The arc begines at angle1 degrees and continues for angle2 degrees
     around the circle.  The arc is filled with the current foreground
     color in the current drawing area. The top left corner of the drawing
     area is considered 0,0.

     If you want a circle, you would specify angle1 as 0, and angle2 as
     360.

     If the width and height are negative, the arc is still drawn properly.

`DrawImage(data, x, y, width, height)'
     This function draws a bitmap image that has a width and height as
     specified by the arguments.  The image is drawn at location x,y in the
     current drawing area.  The "data" argument should contains at least
     width*height bytes of data.

     Each byte of the data is interpreted as a color value to draw the
     corresponding pixel with.

     Normally you would use this function when you have taken over the
     colormap with GetAllColors() (so that you can be guaranteed certain
     colors are in a given range).  If you have not taken over the
     colormap, you need to make sure that the bytes in the image data
     contain valid values that you've allocated with the color allocation
     functions (GetNamedColor(), GetRGBColor() or GetPrivateColor()).

     The top left corner of the drawing area is considered 0,0.

`GetImage(x, y, width, height, result)'
     This function retrieves a bitmap image from your drawing area that
     has a width and height as specified by the arguments.  The image is
     taken from the starting location x,y in the current drawing area.

     The 'result' variable will be filled with the 8-bit pixel values of
     the current drawing area.  Note that the pixel values are not the
     actual color values.  If you want the actual color values, you'll
     need to know what the current colormap is (which you would know if
     you've set the colormap) and then use the pixel values to index the
     colormap.

     The memory pointed to by data is packed with width*height bytes, with
     no extra padding or filling.  That is, the first width bytes
     correspond to line 0, the next width bytes correspond to line 1 of the
     image, etc.

     It is important to keep in mind that if you plan to save the pixel
     data in an image file, you need to also keep track of the colormap so
     that you can save that as well.  By themselves, the pixel values don't
     correspond to any particular color.

     A serious drawback of this function arises from the way X operates.
     If the drawing area from which you are "getting" the image is obscured
     by another window, that part of the bitmap will be empty.  The only
     way around this is to make sure that your window is in front of all
     the others before you call GetImage().  This is a serious limitation,
     but it's the way X operates.

     The top left corner of the drawing area is considered 0,0.  If you
     specify a starting x,y and width,height dimensions that are larger
     than your drawing area, you will get a BadMatch error and X will
     terminate your program (so be careful).

`ScrollDrawArea(dx, dy, x1, y1, x2, y2)'
     This function scrolls the box defined by (x1,y1) (x2,y2) by the
     amounts dx and dy in the X and Y directions respectively.  This means
     that the box whose upper left corner is (x1,y1) and whose lower right
     corner is (x2,y2) are scrolled by dx and dy pixels in X and Y.

     A positive value for dx causes the drawing area to scroll its contents
     to the left.  That is, whatever is at the left edge gets pushed off
     and the dx columns of pixels on the right hand side are cleared to the
     background color.  A negative value has the opposite effect.

     A positive value for dy corresponds to scrolling upwards.  That is,
     whatever is at the top of the drawing area is pushed up by dy pixels
     and the bottom dy rows of pixels are cleared to the background color.
     A negative value has the opposite effect.

     This function is useful for scrolling the drawing area to draw new
     information (such as a text editor might do to scroll text up or
     down).

     The new area exposed by the scroll is filled with the current
     background color of the drawing area.

COLOR STUFF
-----------

   This describes the routines for managing colors in your window.  For
example if you want to change what the foreground color is, or need to get
specific colors.  To get specific colors you use the functions discussed
in here.  It is important to remember that you can not call any of these
functions until you have called ShowDisplay().

   Colors are represented by integers.  When you get a color, you are
returned an integer that you can use in calls to SetFgColor(),
SetBgColor(), and SetColor().  You should attach no meaning to the
numbers, and just because green is 17 does not mean that 18 is a lighter
or darker shade of green.

   There are three ways to manipulate colors with Sxperl.  The first way
handles most of the common cases, and is done with GetNamedColor() or
GetRGBColor().

   The next method, GetPrivateColor(), allows your application to modify
the actual display color represented by a color number (something you
cannot do with the the previous methods).

   The final method gives you complete control in specifying the entire
colormap.  That is, you can determine exactly what integers map to what
colors so you can obtain smooth gradients (so for example black is color
0, and white is 255).  These routines work best on 8 bit displays but will
work on 24 bit displays.

   NOTE: You can NOT call any color function until you have called
ShowDisplay().

   The way colors work for drawing is like this.  There are usually 256
available colors on a workstation.  This is called an 8-bit display
because 2 to the 8'th power == 256.  These colors are stored in a table
(array) of 256 entries.  If you allocate a color, and it is in entry 37,
then to draw with the color that is stored there, you must use 37 as an
argument to the SetColor() function.  When you ask for a color, it may be
taken from anywhere in the array of 256 entries, and there is *NO*
guarantee that if you allocate a green color that the next color in the
table will be a lighter or darker green.  Even if you allocate many colors
using GetNamedColor() or GetRGBColor(), you have i<NO> assurances about
where those colors are in the array (chances are they won't be
contiguous).  If you need to have a contiguous set of numbers, you must
use GetAllColors() and then SetColorMap() or SetMyColorMap() to set up a
custom colormap with a known set of values.  When you get a private color,
your application can specify what values that color index should have.
This is useful when you want to interactively modify a color.

   It is important to remember that `getting a color' really means getting
an index into the color table where the actual color is stored.

`GetStandardColors()'
     This function sets 6 function returning standard colors, RED, GREEN,
     BLUE, YELLOW, BLACK, and WHITE.  The values returned can be used in
     calls to SetColor(), SetFgColor(), SetBgColor(), etc.

     Do not call RED, GREEN, BLUE, YELLOW, BLACK or WHITE before calling
     GetStandardColors().  The results are undefined if you do this.

     NOTE: You can only call GetStandardColors() after calling the
     ShowDisplay() function.

`GetNamedColor(name)'
     This function allocates an entry in the color table for the color
     given by the ascii string "name".  You can view the list of available
     color names with the showrgb command in a shell (some nice ones are
     "peachpuff", "burlywood3", "aquamarine", and "paleturquoise3").  Color
     names can have spaces in them.  The return value of the function is an
     integer that you can use in calls to SetColor() (or any of the other
     SetXXColor() calls). If an error occurred trying to allocate the color
     (very possible if you allocate a lot of colors), a -1 is returned.

`GetRGBColor(red, green, blue)'
     This function tries to allocate the color given by the red, green,
     blue triple r,g,b.  The arguments r,g, and b should be between 0 and
     255.  Overflow is not checked for.  The return value is an integer
     value usable in the SetColor() calls or a -1 if an error occurred.

`GetPrivateColor()'
     This function allocates a private color cell for use by the
     application.  A private color cell is one which you can change what
     color it represents.  For example, if you would like to let the user
     interactively manipulate some color, you would need to allocate a
     private color cell.

     The integer returned by this function is a reference to a color cell
     whose values you can set with SetPrivateColor().  The intial contents
     of the private color cell are undefined and you should probably call
     SetPrivateColor() immediately to set it to some known value.

     If an error occurs, a -1 is returned.

     When you are done with a private color cell, you should free it with
     FreePrivateColor().

`SetPrivateColor(which, red, green, blue)'
     This function sets the color cell referred to by `which' to have the
     r,g,b values specified.  The r,g,b values are given in the range 0-255
     (inclusive). Once this function is called, any thing drawn in the
     display with the color `which' will now have the new color determined
     by the r,g,b arguments.

`FreePrivateColor(which)'
     This function returns the color associated with the private color cell
     `which' to the system.  You should have allocated the color referred
     to by `which' with GetPrivateColor().

`GetAllColors()'
     This function is rather drastic and should be used with caution.  It
     immediately grabs an entire 256 entry colormap for private use.  This
     has the unfortunate effect of (temporarily) wiping out the colors in
     all the other windows on the display.  However this is necessary if
     you wish to get a smooth colormap to use in displaying a smooth-shaded
     or continuous tone picture.  Once GetAllColors() is called, the entire
     colormap is free for manipulation by your program.  The colormap
     remains allocated until you call FreeAllColors(), at which time
     everything goes back to normal.

     If an error occurred (quite possible), this routine returns FALSE.  If
     everything went ok and the colormap was successfully allocated, TRUE
     is returned.

     If you can avoid using this function, try to.  It is disconcerting for
     the user to have the colormap get wacked out and have most of their
     windows disappear (they don't really disappear of course, you just can
     see them usually).  However it is sometimes necessary to do this as
     there is no other way to get a smoothly continuous color map.

     Usually, you will want to call SetColorMap() or SetMyColorMap() right
     after this function.

     NOTE: On a 24 bit machine (like the SGI Indigo Elan I tested this
     with), only current drawing area gets the colormap, other widgets and
     windows are not affected.

`FreeAllColors()'
     This function frees a private colormap that was allocated with
     GetAllColors().  It has the beneficial effect of immediately restoring
     the rest of the colors on the screen and in other windows to those
     that existed prior to the call to GetAllColors().  This function is
     useful if wish to let the user restore their original colors
     temporarily (although this will happen automatically when the mouse
     moves outside the window).

`SetColorMap(num)'
     This function creates several predefined color maps that are very
     smoothly continuous.  It saves you the hassle of writing them yourself
     (even though they are mostly easy).  The "num" argument you pass in
     should be one of the following variable :

          GREY_SCALE_1    0
          GREY_SCALE_2    1
          RAINBOW_1       2
          RAINBOW_2       3

     The colormap GREY_SCALE_2 is a complete smooth color ramp from pure
     black (color 0) to pure white (color 255).  The other grey scale,
     GREY_SCALE_1 is a nearly pure ramp from black (color 0) to white
     (color 252), but also has a few additional colors thrown in near the
     end of the colormap.  The two RAINBOW_? colormaps have different
     types of smooth changing rainbows of color.  This are really only
     useful for drawing pretty patterns or doing false coloring.

     NOTE: You should call GetAllColors() before you call this routine.  It
     is not necessary, but if you don't, and GetAllColors() fails, you will
     never know about it, and your application may not work very well.

`SetMyColorMap(red1, green1, blue1, ..., redN, greenN, blueN)'
     Occasionally it is necessary to have absolute control over your
     colormap, and this function lets you do that.  This function lets you
     completely specify each and every color that will be in the colormap.
     The values for redi, greeni or bluei range from 0 to 255.  You need
     not specify a full list of 256 triplets, you can in fact only specify
     a few.

     NOTE: You should call GetAllColors() before you call this routine.  It
     is not necessary, but if you don't and GetAllColors() fails, you will
     never know about it, and your application may not work very well.

FONTS
-----

   Fonts are different type styles that can be used in various widgets.
You load a font by name and get a handle in return. The handle you get
allows you to set the font in the various widgets and font information
calls.

`GetFont(fontname)'
     This function loads the font named by fontname and returns a handle to
     the font or FALSE if there is an error.  The handle returned by this
     function is an XFont object and should be treated as an opaque data
     type.

     After you've loaded a font, you can then set that font in any widget
     that displays text.  You can also use the handle in calls to
     TextWidget() and FontHeight().

     When you are done with a font, you should free it with FreeFont().

`SetWidgetFont(widget, font)'
     This functions sets the font used by the widget `widget', to be the
     font referred to by the argument `font'.  The argument f should have
     been obtained with GetFont().

`GetWidgetFont(widget)'
     This function returns a handle to the font currently used by the
     Widget widget.  If an error occurs or there is no default font for the
     widget, a FALSE is returned.

     You should NOT call FreeFont() on any value returned by this function
     unless you are sure that you allocated the font with GetFont().

`FreeFont(font)'
     This function frees the resources associated with the font.  You
     should call this function when your application is done using a
     particular font.

     Of course you should make sure that no widget still uses the
     identified font.

`FontHeight(font)'
     This function returns an integer value that is the height in pixels of
     the specified font.   The height is defined to be the ascent of the
     characters (from the baseline to the top of a capital letter) plus the
     descent of the characters (the distance from the baseline to bottom of
     a descender character like `g' or `p').

`TextWidth(font, txt)'
     This functions returns the width in pixels used by the string pointed
     to by txt in the specifiedfont.  The entire string is used to
     determine the width.

MISCELLANEOUS
-------------

   The following function allows you to specify how the display should be
layed out.  It lets you logically position the components you created with
the MakeXXX() functions.  You will use this function to layout the
arrangement of your buttons, labels and drawing area(s).

`SetWidgetPos(widget, where1, from1, where2, from2)'
     This function lets you position a Widget in your window.  The idea is
     that you specify logical placement of the Widget (i.e. place it to the
     right of this widget, and under that widget).  Many layouts are
     possible, and you can even specify that you don't care where a
     specific widget is placed.

     There are three types of placement.  You can place a widget to the
     right of another widget with PLACE_RIGHT.  If the argument "where1"
     is PLACE_RIGHT, then the specified widget will be placed to the right
     of the Widget "from1".  If "where1" is equal to PLACE_UNDER, the
     widget will be placed under the widget "from1".  The same holds true
     for the argument "where2" and Widget "from2".  Having two arguments
     is necessary to be able to unambiguously specify where you want
     components placed in the display.  If you don't care about where a
     widget is placed, you can use NO_CARE for the `where' argument and a
     Nullsx value for the `from' argument.

     Generally, the first widget created need not be specified, it will
     always be in the top left corner.  Other widgets can the be placed
     relative to that widget.  For example, if you created 4 widgets
     ($w[0..4]) and wanted to arrange them in a column, you would do the
     following :

          SetWidgetPos($w[1], PLACE_UNDER, $w[0], NO_CARE, Nullsx);
          SetWidgetPos($w[2], PLACE_UNDER, $w[1], NO_CARE, Nullsx);
          SetWidgetPos($w[3], PLACE_UNDER, $w[2], NO_CARE, Nullsx);

     Notice how the third argument changes; we are placing the next widget
     underneath the previous widget.  The zero'th widget ($w[0]) doesn't
     have to be placed because it is always in the top left corner (this
     can not be changed).

     If you wanted to arrange things in a row, you would use PLACE_RIGHT
     instead of PLACE_UNDER.

     As a more complicated example, supposed you want to create two rows of
     widgets, and a drawing area.  You would do the following :

          # first three across the top
          SetWidgetPos($w[1], PLACE_RIGHT, $w[0], NO_CARE, Nullsx);
          SetWidgetPos($w[2], PLACE_RIGHT, $w[1], NO_CARE, Nullsx);
          SetWidgetPos($w[3], PLACE_RIGHT, $w[2], NO_CARE, Nullsx);

          # next three underneath the top row
          SetWidgetPos($w[4], PLACE_UNDER, $w[0], NO_CARE, Nullsx);
          SetWidgetPos($w[5], PLACE_UNDER, $w[0], PLACE_RIGHT, $w[4]);
          SetWidgetPos($w[6], PLACE_UNDER, $w[0], PLACE_RIGHT, $w[5]);

          # put the drawing area under the second row
          SetWidgetPos($w[7], PLACE_UNDER, $w[4], NO_CARE, Nullsx);

     It is useful to think of the window as a kind of grid in which you can
     put various pieces.  Just draw a picture of what you want and then use
     SetWidgetPos() to indicate to the system what is next to/underneath of
     what.

     Also, all imaginable layouts are not possible with SetWidgetPos().
     For example, you cannot specify specific pixel offsets for a widget,
     or that it be centered in the display, or right justified.  This
     limitaton is for the sake of simplicity.  Generally this should not be
     a problem (if it is, you are probably getting beyond the scope of what
     libsx was intended to provide, i.e. you're becoming an X hacker :).

     You can simulate more complicated layouts by cheating and creating
     label widgets whose label is just spaces and then placing other widget
     the left or underneath the label.  This works but is kind of hackish.
     See also SetWidgetInt() for another way to cheat.

`SetFgColor(widget, color)'
     This function sets the foreground color of a widget. If the widget is
     a drawing area, all future primitives are drawn with the specified
     color.  If the widget is some other type of widget, it sets the
     foreground color of the widget (such as its text) to be the specified
     color.

     The argument "color" should be an integer that was returned from the
     colormap functions (GetNamedColor(), GetRGBColor(), GetPrivateColor()
     or GetStandardColors()).

`SetBgColor(widget, color)'
     This function sets the background color of a widget.  If the specified
     widget is a drawing area, the next call to ClearDisplay() will clear
     the drawing area to the specified background color.

     The argument "color" should be an integer that was returned from the
     colormap functions (GetNamedColor(), GetRGBColor(), GetPrivateColor()
     or GetStandardColors()).

`SetBorderColor(widget, color)'
     This argument will set the border color that is drawn around a widget.
     The same effect happens for all of the different widgets - the border
     is redrawn with the new color.  This can be very useful for giving a
     nice visual offset to an important or dangerous button.  Of course you
     should avoid garish combinations of colors that are hard to look at.

`GetFgColor(widget)'
     This routine is a convience function that will return the current
     foreground color of any kind of widget.  This is mainly useful for
     drawing widgets to make sure that you draw things in the proper
     foreground color.  This can arise as a problem if you assume that
     black is going to be the default foreground color (which it normally
     is).  However, the user can change this default by using the -fg
     "color" option on the command line.  This is an X command line option,
     and can not be overriden by your program.  A real application would
     use this function to check the value and use it to draw in the user's
     preferred foreground color.  Other programs can just ignore the
     problem and still work ok as long as the user doesn't change the
     program's colors.

     This function returns the integer value of the foreground color that
     you can use in later calls to SetFgColor() or SetColor(). It returns
     -1 if you passed an invalid Widget to it.

`GetBgColor(widget)'
     This routine is a convience function that will return the current
     background color of any kind of widget.  This is mainly useful for
     drawing widgets to make sure that you draw things in the proper
     background color.  This can be a problem if you assume that white is
     going to be the default background color (which it normally is).
     However, the user can change this default by using the -bg "color"
     option on the command line.  This is an X command line option, and can
     not be overriden by your program.  A real application would use this
     function to check the value and use it to draw in the user's preferred
     background color.  Other programs can just ignore the problem and
     still work ok as long as the user doesn't change the program's colors.

     The other problem that crops up if you ignore the background color is
     that if you go to erase something by just drawing in white and white
     doesn't happen to be the actual background color, your program will
     look funny.

     This function returns the integer value of the background color that
     you can use in later calls to SetBgColor() or SetColor(). It returns
     -1 if you passed an invalid Widget to it.

`AddTimeOut(interval, func, data)'
     If you would like to animate a display or do some periodic processing
     (such as an auto-save feature for an editor), you can use time-outs.

     A time-out is a callback function that gets called when the specified
     amount of time has expired (or I should say more precisely, when at
     *least* that much time has passed, Unix a'int no real time system).

     The argument `interval' is an unsigned long and is specified in
     milliseconds. That is, a time out of 1 second would be an argument of
     1000.

     The callback should look like:

          sub  func {
          	my($data) = @_
          }

     The function is only called once, if you would like the function to be
     called repeatedly (to update an animation for example), the last thing
     the function should do is to call AddTimeOut() again.

     The value returned by AddTimeOut() can be used with RemoveTimeOut()
     to cancel that time-out.

`RemoveTimeOut(id)'
     Cancels a time-out callback which was previously registered with
     AddTimeOut().

     Argument id is an identifier returned by AddTimeOut().

`SetWidgetState(widget, state); '
     This function lets you enable or disable particular widgets in an
     interface.  If, for example, choosing one item from a menu should
     disable various other widgets, you can call this function.

     The Widget argument is the widget in question.  The state argument is
     a boolean, which indicates whether the widget should be active or not.
     A value of TRUE indicates that the widget should accept input, and a
     value of FALSE indicates that the widget should not accept input (it
     becomes greyed out).

     When you disable a widget, the user can no longer interact with that
     widget in any way (it becomes grey'ed out and just ignores all input).

`GetWidgetState(widget)'
     This function returns a boolean value indicating whether or not the
     specified widget is currently active.

     If the widget is active and accepting input, the return is TRUE, if
     the widget is inactive, the return value is FALSE.

`Beep()'
     This function is real complicated.  It beeps the workstation speaker.

`SetWidgetBitmap(widget, data, width, height)'
     This function lets you attach a bitmap to a widget instead of its
     default text.  This function only works correctly on Button, Toggle
     and Label widgets.  Using it on another type of widget yields
     undefined results.

     The widget will display the bitmap data given by the argument, data,
     whose width and height are given as the last two arguments.

     The bitmap data is only one bitplane deep, and is usually produced by
     a somewhat brain-dead X program called `bitmap'.  The output of the
     bitmap program is a file you can almost directly 'require' in your
     source code.  The contents of the file is an array of characters and
     two #defines that give the width and height of the bitmap.

     Thus, making a widget with a bitmap is a three step process.  First
     you would edit a bitmap using the `bitmap' program, then you need to
     edit the resulting file to convert it to perl syntax then you would
     do the following:

          require  'bmap.ph';

          $w = MakeButton(Nullsx, 'func', $a_value);
          SetWidgetBitmap($w, $bmap_bits,$bmap_width,$bmap_height);

     Bits which are a one in the bitmap are drawn in the widget's current
     foreground color and zero bits are drawn in the current background
     color.

ADDITION TO THE ORIGINAL LIBSX
------------------------------

   All the following functions and widgets were added to libsx.

`DestroyWidget(widget)'
     This function calls destroys a given widget and all it's descendant.
     Care should be taken not to re-use the widget after that.

`SetWidgetInt(widget, resource, value)'
     Sets the named resource with an integer value for a given widget.

`SetWidgetDat(widget, resource, value)'
     Sets the named resource with a 'string' value for a given widget.

`GetWidgetInt(widget, resource)'
     Get the integer value of the named resource.

`GetWidgetDat(widget, resource)'
     Get the string value of the named resource.

     The following functions are intended for Text widgets.

`AppendText(widget, text)'
     Append the given text to the end of widget. widget should be a 'text
     entry' widget.

`InsertText(widget, text)'
     Insert the given text in a 'text entry' widget at the current caret
     position.

`ReplaceText(widget, text, left, right)'
     Replace the text in the widget between position left and right by the
     given text.

`GetSelection(widget,buf)'
     Returns (in buf) the selected string from the given text widget.

`GetTextSelectionPos(widget,left,right)'
     Returns (in left and right) the start and the end of the selected
     area.

`SetTextSelection(widget,left,right)'
     Set the start (left) and the end (right) of the selected area.

`UnsetTextSelection(widget,left,right)'
     Unset the selection.

     Misceallaneous functions.

`WarpPointer(widget,x,y)' Moves the pointer to the (x,y) coordinates relative to the given widget.
`AddReadCallback(fd, func, data)' Adds an input callback which gets called if some data are readable for a given filedescriptor fd.
`AddWriteCallback(fd, func, data)' Like AddReadCallback() but checks for data writeable.
`RemoveReadWriteCallback(id)' Cancels an AddReadCallback() or AddWriteCallback() request; id is the value as returned by AddReadCallback() or AddWriteCallback().
`AddTranslation(widget, translation_table)'
     Add (override) a translation table for the specified widget. Each
     translation should associate an event to a perl action. This action
     will take, the widget as its first argument, then the event as packed
     datas followed by the rest of the specified arguments. Be warned that
     the arguments will be passed as strings. So if you want to pass perl
     variables, you should quote them and use eval in the callback.

     For example :

          sub pargs {
            my($w,$ev,@a) = @_;
            print "args are [@_]\n";
            SetLabel($w,join('-',@a));
          }

          sub quit { exit }

          @ARGV = OpenDisplay('test',@ARGV);

          $w1 = MakeButton('quit',\&quit,undef);

          AddTranslation($w1,
          		       '<Btn1Up>' => 'pargs(button1,up)',
          		       '<Btn1Down>' => 'pargs(button1,down)',
          		       '<Btn2Up>' => 'pargs(button2,up)',
          		       '<Btn2Down>' => 'pargs(button2,down)',
          		       '<Btn3Up>' => 'pargs(button3,up)',
          		       '<Btn3Down>' => 'pargs(button3,down)',
          		       '<Motion>' => 'pargs(motion)');

          ShowDisplay;

          MainLoop;

AUTHOR
======

   Original by Dominic Giampaolo <`dbg@sgi.com'>.

   Rewritten for Sx by Frederic Chauveau <`fmc@pasteur.fr'>.

A highly configurable Login widget for Sybperl and Perl/Tk
**********************************************************

NAME
====

   Sybase::Login - A highly configurable Login widget for Sybperl and
Perl/Tk

Change History
==============

     *1.0* - Initial Implementation

     *1.1* - Componentized for perl5.0021bh, handlers fixed

     1.2 - Set up for general distribution, added Version and VERSION.
     Changed funky menu generation to Optionmenus.

     1.3 - Added presentDBMenu and presentSrvMenu options.

     1.4 - OK, so I had troubles with PAUSE on 1.3

     *Todo:* - Subclass Optionmenu to dynamically set up the Server
     selections on post (or Buttondown?)

DESCRIPTION
===========

   Login is a Widget that presents a dialog box to the user so that the
user may enter his or her login name and password, as well as select the
appropriate database and server.

USAGE
=====

   One uses Login by creating a new Login widget, adding at least one
Database via the addDatabase method, configuring via the configure method,
and then getting a valid login via the getVerification method.

Sample Program
--------------

          #!/usr/local/bin/perl -w

          use Tk;
          use Sybase::DBlib;
          use Sybase::Login;
          use strict;

          my($main) = MainWindow->new;
          my($Login) = $main->Login;

          $Login->addDatabase('DB',	'SYBSRV1','SYB11');
          $Login->addDatabase('DBBACK',	'SYBSRV1','SYB11');

          $Login->configure(-User => $ENV{USER},
          		   -ULabel => 'User Name:',
          		   -Title => 'Please Login');

          my($msg) = $main->Message(-text => 'Ready to go')->pack;
          $main->Button(-text => 'kick me!',
          	       -command => sub {
          		 my($pwd, $usr, $db, $srv, $mDB);
          		 if ($Login->getVerification(-Force => 1)) {
          		   $pwd = $Login->cget(-Password);
          		   $usr = $Login->cget(-User);
          		   $db =  $Login->cget(-Database);
          		   $srv = $Login->cget(-Server);
          		   print "Results good:\n\tUser:\t\t$usr\n";
          		   print "\tPassword:\t$pwd\n\tDatabase:\t$db\n";
          		   print "\tServer:\t\t$srv\n";
          		   print "Verifying Login...\n";
          		   $mDB = Sybase::DBlib->dblogin("$usr","$pwd", "$srv");
          		   $mDB->dbuse($db);
          		   $mDB->dbclose;
          		   print "Login worked!!!\n";
          		 } else {
          		   print "Login cancelled at User request.\n";
          		 }
          	       })->pack;

          $main->Button(-text => 'exit',
          	       -command => sub {$main->destroy;})->pack;

          MainLoop;

          print "And I'm on my way home!\n";

          exit;

Operation
---------

   The user is presented with a dialog box.  The focus is on the username
entry if no user name has been configured; otherwise, it is on the
password entry.  If multiple databases have been configured, the user may
select the appropriate database from the menu button. If multiple servers
have been configured for the selected database, the user may select the
appropriate server from the menu button.

   When the user has finished entering information, she may press the OK
button to attempt to login, or the cancel button to abort the process.  If
the user presses the OK button, and the login succeeds, control returns to
the caller.  If the login fails, an error dialog box is displayed, and the
user may press retry, or may press cancel, in which case control returns
to the caller exactly as if the user had pressed cancel at the main login
screen.

   When control returns to the caller, the return value will be 1 if the
login was successful, or 0 if not.

Notes
-----

   A caller may define a message or error handler either before or after
calling any of the methods of this object. getCurrentVerification will
restore the handlers extant when invoked.

Methods
=======

getCurrentVerification
----------------------

   *$Login-*>*getCurrentVerification;*

   *(No parameters)*

   return 1 if the current configuration will result in a valid login, 0
otherwise.  No GUI is ever displayed.

getVerification
---------------

   *$Login-*>*getVerification(-Force =* ?);>

   If the current configuration is NOT valid, activate the login frame.
This will return 1 with a valid configuration, or 0 if the user hit
cancel.  If the -Force parameter is passed as 't', 'y', or 1, the login
frame will be activated even if the current configuration is valid.

addDatabase
-----------

   *$Login-*>*addDatabase(Database, Server List);*

   adds a database/server set.  The first parameter is the name of the
database, the second is a list of Associated Servers.  See the code above
for examples.

   Note that the first server in the list is the default server for that
database.  Further note that adding a database a second time simply alters
the servers.

clearDatabase
-------------

   *$Login-*>*clearDatabase([Database[, Database,...]]);*

   Clears the given Database entries, or all databases if if none are
specified.

Version
-------

   *$Login-*>Version

   *(No parameters)*

   Returns the current version of Login

Configuration Items
===================

   Any of the following configuration items may be set via the configure
method, or retrieved via the cget method.

-User
-----

   Set or get the username.  The default is blank.

-Password
---------

   Set or get the password.  The default is blank.

-Title
------

   Set or get the Title of the Login Widget.  The default is 'Database
Login'

-Database
---------

   Set or get the default Database.  The default is blank.  The call will
silently fail if the database is not configured via the AddDatabase
method.  If the configured server is not a valid server for the given
database, the server will be set to the default server for the database.

-Server
-------

   Set or get the default Server.  The default is blank.  The call will
silently fail if the server is not a valid server for the currently
configured database.

-OKText
-------

   Set or get the text for the OK button.  The default is OK.

-CancelText
-----------

   Set or get the text for the Cancel button.  The default is Cancel.

-ULabel
-------

   Set or get the label for the User name entry.  The default is 'User:'.

-PLabel
-------

   Set or get the label for the Password entry.  The default is
'Password:'.

-DLabel
-------

   Set or get the label for the Database Menu Button.  The default is
'Database:'.

-SLabel
-------

   Set or get the label for the Server Menu Button.  The default is
'Server:'.

-Labelfont
----------

   Set or get the font used for the labels.  The default is
'-Adobe-Courier-Bold-R-Normal-*-120-*'.

-EDlgTitle
----------

   Set or get the Title for the Error Dialog. The default is 'Database
Login Error!'.

-EDlgText
---------

   Set or get the text displayed in the Error Dialog.  The default is
'Unable to login to $db at $srv'.  $db will be interpreted as the Database
name, $srv will be interpreted as the Server name, $usr will be
interpreted as the User name, and $pwd will be interpreted as the password.

-EDlgRetry
----------

   Set or get the text for the Retry button in the Error Dialog. The
default is 'Retry'.

-EDlgCancel
-----------

   Set or get the text for the Cancel button in the Error Dialog. The
default is 'Cancel'.

-presentDBMenu
--------------

   If set False, do not display the database menu.  The database will be
as configured, or default.  Default is True.

-presentSrvMenu
---------------

   If set False, do not display the server menu.  The Server will be as
configured, or default for the database. Default is True.

Author
======

   *Brent B. Powers, B2Pi*

   Currently on-site at Merrill Lynch, powers@ml.com

   This code may be distributed under the same conditions as perl itself.

Return Sybase Object information
********************************

NAME
====

   Sybase::ObjectInfo - Return Sybase Object information

SYNOPSIS
========

     %info = grab Sybase::ObjectInfo($dbh, $database, \@table_list)

     where:
        $dbh is a Sybase::DBlib handle
        $database is the name of the database
        @table_list is an array containing the tables

     returns a hash for the form:
        $r = $info{$db_name}->{$table_name}->{$field_name}

     $r->{col_id}          # column order
       ->{col_type}        # column fundamental datatype
       ->{col_len}         # column datatype length
       ->{col_allownulls}  # does the column allow nulls
       ->{col_usertype}    # column usertype - if applicable
       ->{col_prec}        # column precision

DEPENDENCIES
============

     perl version 5.004

     Sybase::DBlib

DESCRIPTION
===========

   Grabs column information from Sybase system tables for a given list of
tables. Information includes column number, type, length, allow null
attribute, usertype, and precision.

     It performs the following SQL:
        select
           col_name    = c.name,
           type_name   = t.name,
           col_len     = c.length,
           col_order   = c.colid,
           ctype       = c.type,
           utype       = t.usertype,
           allownulls  = t.allownulls
        from
           $db_name..syscolumns c,
           $db_name..systypes t
        where
           c.id = object_id('$db_name..$tab_name')
           and c.usertype *= t.usertype
        order
           by c.colid

   followed by this for each field where utype > 100  to get the
underlying datatype for usertypes

     select
        name
     from
        $db_name..systypes
     where
        usertype < 100
        and type=$col->{ctype}
        and name not in ("sysname", "nchar", "nvarchar")

MISC
====

   When supplying the parameters to grab, $database can  be  null.  If  so,
then tables must be of the form  "database.owner.table"  (owner  can  be
null)

   If only  one  table  is  specified  then  table_list  can  be  a  scalar
containing the name of the table.

WISH LIST
=========

   I should convert this to use DBI/DBD at  some  point.  And  if  I'm  not
mistaken these kind of attributes are already  built  into  that  system
(thereby rendering this module close to obsolete if DBI is installed)

CONTACTS
========

   stephen.sprague@msdw.com

VERSION
=======

   version 0.1, 01-OCT-2000 version 0.2, 10-FEB-2000

transfer data between Sybase servers via bcp.
*********************************************

NAME
====

     Sybase::Xfer - transfer data between Sybase servers via bcp.

SYNOPSIS
========

     #!/usr/bin/perl5.005
     #the perl version
        use Sybase::Xfer;
        $h = new Sybase::Xfer( %switches );
        $h->xfer();
        $h->done();

     #!/bin/ksh
     #the bin version
        sybxfer <switches>

DEPENDENCIES
============

     requires at least perl version 5.005

     Sybase::DBlib
     Sybase::ObjectInfo (this comes packaged with Sybase::Xfer)
     Getopt::Long
     Tie::IxHash

DESCRIPTION
===========

   If you're in an environment with multiple servers and you don't want to
use cross-server joins then this module may be worth a gander. It
transfers data from one server to another server row-by-row in memory w/o
using an intermediate file.

   To juice things up it can take data from any set of sql commands as
long as the output of the sql matches the definition of the target table.
And it can take data from a perl subroutine if you're into that.

   It also has some smarts to delete rows in the target table before the
data is transferred by several methods. See the -truncate_flag,
-delete_flag and -auto_delete switches.

   Everything is controlled by switch settings sent as a hash to the
module.  In essence  one describes the *from source* and the *to source*
and the module takes it from there.

   Error handling:

   An attempt was made to build in hooks for robust error reporting via
perl callbacks. By default, it will print to stderr the data, the column
names, and their datatypes upon error.  This is especially useful when
sybase reports *attempt to load an oversized row* warning message.

   Auto delete:

   More recently the code has been tweaked to handle the condition where
data is bcp'ed into a table but the row already exists and the desired
result to replace the row. Originally, the -delete_flag option was meant
for this condition. ie. clean out the table via the -where_clause before
the bcp in was to occur. If this is action is too drastic, however, by
using the -auto_delete option one can be more precise and force only those
rows about to be inserted to be deleted before the bcp in begins. It will
bcp the 'key' information to a temp table, run a delete (in a loop so as
not to blow any log space) via a join between the temp table and target
table and then begin the bcp in. It's weird but in the right situation it
may be exactly what you want.  Typically used to manually replicate a
table.

OPTIONS SUMMARY
===============

HELP
----

-help | -h
     this help

FROM INFO
---------

-from_server | -fs        (string)
     from server name

-from_database | -fd     (string)
     from database name

-from_user | -fu         (string)
     from username

-from_password | -fp    (string)
     from username password

FROM SOURCES
------------

-from_table | -ft      (string)
     from table name

-from_sql (string)
     string is the sql to run against the from server

-from_script (string)
     string is the filename containing sql to run

-from_perl (coderef)
     coderef is perl sub to call to get data

-from_file | -ff (filename)
     name of file to read data from.

-from_file_delimiter | -ffd (delimiter)
     the delimiter used to separate fields. Used in conjunction with
     -from_file only.

TO INFO
-------

-to_server | -ts (string)
     to server name

-to_table | -tt (string)
     to table name

-to_user | -tu (string)
     to username

-to_password | -tp (string)
     to username password

FROM & TO INFO
--------------

-server | -S (string)
     set from_server and to_server

-database | -D (string)
     set from_database

-table | -T (string)
     set from_table and to_table

-user | -U (string)
     set from_user and to_user

-password | -P (string)
     set from_password and to_password

MISC
----

-batchsize | -bs (int)
     bcp batch size. Default=1000

-where_clause | -wc (string)
     append string when using -from_table to sql select statement

-truncate_flag | -tf
     truncate to_table

-delete_flag | -df
     delete *to_table* [where *where_clause*]

-app_name | -an (string)
     application name

-holdlock | -hl
     adds *holdlock* after the *from_table*

-trim_whitespace | -tw
     strips trailing whitespace

AUTO DELETE
-----------

-auto_delete [*c1,c2...*]
     *c1,c2...* are *to_table* column keys

-auto_delete_batchsize  (int)
     auto_delete batchsize

-scratch_db  (string)
     scratch database used by auto_delete

CALLBACKS
---------

-callback_pre_send (coderef)
     before row is sent callback

-callback_err_send (coderef)
     error on bcp_sendrow callback

-callback_err_batch (coderef)
     error on bcp_batch callback

-callback_print (coderef)
     any output that normally goes to stdout callback

ERROR HANDLING
--------------

-error_handling| -eh (string)
     string is abort, continue, or retry. Default is abort.

-error_data_file | -edf (filename)
     name of file to write the failed records into

-retry_max n
     number of times to retry an bcp_batch error

-retry_deadlock_sleep
     sleep time between calls to bcp_batch if deadlock error detected

FLAGS
-----

-echo
     echo sql commands

-silent
     don't print begin & end/summary messages

-progress_log
     print progess message on every bcp_batch

-debug
     programmer debug mode

OPTION DETAILS
==============

from sources
------------

     -from_table | -ft  <table_name>

   from table name. Use a fully qualified path to be safe. For example,
pubs..titles. This removes the dependency on the default database for the
-from_user value.

     -from_sql  <string>

   send sql in <string> to -from_server and xfer results to -to_table.
For example, 'select author_id, lname from pubs..authors' This implies the
-to_table has two columns of compatible type to store author_id and lname
in it.

     -from_script <file>

   send sql in <file> to from_server and xfer results to to_table.
Essentially the same as -from_sql except that it opens a file and gets the
sql from there.

     -from_perl <code-ref>

   call code reference repetitively for data. Call the code-ref for data
to send to -to_table.  user routine must return the following array:
($status, $array_ref)  where $status is true to call it again or false to
end the transfer. $arrary_ref is an array refernce to the row to send.
This switch is only available from the API for obvious reasons.

     -from_file <file>

   the file to read the actual data from. It must be a delimited file.
Using this option it behaves simliar to Sybase::BCP (in) and Sybase's own
bcp. I've attempted to make the error handling richer.

     -from_file_delimiter <regex>

   the delimiter to use to split each record in -from_file. Can be a
regular expression.

from information
----------------

     -from_server | -fs  <server_name>

     The name of the server get the data from. Also see switch -server.

     -from_database | -fd  <database_name>

   The name of the from database. Optional. Will execute a dbuse on the
from server. Also see switch -database.

     -from_user | -fu  <user_name>

   username to use on the from server. Also see switch -user.

     -from_password | -fp  <password>

   password to use on the from user. Also see switch -password.

to information
--------------

     -to_server | -ts <server_name>

   name of the to server. Also see switch -server.

     -to_table | -tt  <table_name>

   name of the to table. USE A FULLY QUALIFIED PATH. Eg. pubs..titles.
This removes the dependency on the the login default database. Also see
switch -table.

     -to_user | -tu <user_name>

   to user name. Also see switch -user.

     -to_password | -tp <password>

   to user password. Also see switch -password.

from and to short cuts
----------------------

   many times the from and to user/pw pair are the same. Or the table
names are the same on the two servers. These options are just a way to set
both the from and to options above with one switch.

     -server | -S <server>

   set from_server & to_server to this value. Also see switches
-from_server and -to_server.

     -database | -D  <database>

   set from_database only. The to_database name is set using a fully
qualified table name. This this the way bcp works. I'd change it if I
could. Also see switches -from_database and -to_database.

     -table | -T  <table>

   set the from_table & to_table to this value. Also see switches
-from_table and -to_table.

     -user | -U  <user_name>

   set from_user & to_user to this value. Also see switches -from_user and
-to_user.

     -password | -P  <password>

   set from_password & to_password to this value. Also see switches
-from_password and -to_password

other qualifiers
----------------

     -batchsize | -bs  <number>

   bcp batch size into the to_table. Default=1000.

     -where_clause | -wc <where_clause>

   send 'select * from *from_table* where *where_clause*' to the
*from_server*. The default is to use no where clause thereby just sending
'select * from *from_table*'.  This is only used when the *from_source* is
a table.  Also see -delete_flag.

     -truncate_flag | -tf

   send 'truncate table *to_table*' to the *to_server* before the transfer
begins.  This requires dbo privilege, remember. If you don't have dbo
privilege and you want to remove all the rows from the target table you
have two options. Use the -delete_flag with no -where_clause or truncate
the table via an alternate method (eg.  under a different user name)
before you run the transfer. Default is false.

     -delete_flag | -df

   send 'delete *to_table* [where *where_clause*]' to the *to_server*
before the transfer begins. Also see -where_clause. Default is false.  The
delete will be performed in batches in  the size given by -batch_size.

     -app_name | -an <val>

   name of program. Will append '_F' and '_T' to differentiate between the
from and to connections. This string appears in the field program_name in
the table master..sysprocesses.  Will truncate to 14 characters if longer.
Default is basename($0).

     -holdlock | hl

   if using *from_table* then this switch will add an additional
*holdlock* after the table. This is especially useful if the *from_table*
has the potential to be updated at the same time the transfer is taking
place. The default is noholdlock.

     -trim_whitespace | tw

   Will set *nsql*'s $Sybase::DBlib::nsql_strip_whitespace to true which
trims trailing whitespace before bcp'ing the data into target table. If a
field is all whitepace on the from table then the result of trimming
whitespace will be null. Therefore, the corresponding column on the to
table needs to permit nulls. Default is false.

auto delete
-----------

   The -auto_delete switch indicates that it should be ensured that any
rows selected from the *from_table* first be removed from the *to_table*.
This differs from the -delete_flag and -where_clause combination that
makes sweeping deletes. -auto_delete was added for the sole purpose of
keeping the -to_table up-to-date by transferring only 'changed' records
from the -from_table and not knowing just which records changed apriori.

     -auto_delete [c1,c2...]

   c1, c2, ... are the *unique key column names* into *to_table*. When
this switch is in effect the module will create a table in -scratch_db
named sybxfer$$, $$ being the current process number, with the columns c1,
c2, ...  Then it will bcp only those columns to this temp table. After
that bcp is complete it will perform a delete (in a loop of the
-auto_delete_batchsize) via a join by these columns in the temp table to
the *to_table* so as to remove the rows, if any. After the delete is
complete the temp table is dropped and all the columns specified will be
bcp'ed to the *to_table*.

   In essence, a simplisitic view is that the following is effectively
done.  'delete *to_table* where c1='cval1' and c2='cval2' ...' for every
row in the *from_table* for values c1, c2, ... I mention this only in this
way because the explanation above seems either too convoluted (or I can't
explain it clearly enough.)

     -auto_delete_batchsize | adb [i]

   batchsize to use when auto-deleting rows. 3000 is the default. See
-auto_delete.

     -scratch_db  [db]

   scratch database used by auto_delete. tempdb is the default. See
-auto_delete.

callbacks (also see error handling)
-----------------------------------

   callback switches are only valid from the API. ie. not from the script
*sybxfer*

     -callback_pre_send <code_ref>

   sub to call before sending row to *to_server*. first and only arg is
ref to the array of the data. cb routine returns ($status, \@row).
$status true means continue, $status false means abort.

   It's called like this:        ($status_cb_pre, $r_user_row) =
$opt->{callback_pre_send}->(\@row);

   It must return this:  return ($status, \@row)

     -callback_print <code_ref>

   sub to call if the catching of log messages desired. No return status
necessary.

   It's called like this: $opt->{callback_print}->($message)

error handling
--------------

   What to do upon encountering an error on bcp_sendrow or bcp_batch?

     -error_handling | -eh  <value>

   Value can be abort, continue or retry. I should probably have a
threshold number but I'll leave that until a later time.  When set to
continue the transfer will proceed and call any error callbacks that are
defined (see below) and examine the return status of those to decide what
to do next. If no error callbacks are defined and -error_handling set to
continue the module will print the offending record by describing the row
by record number, column-types and data values and continue to the next
record. If -error_handling is set to abort, the same is printed and the
xfer sub exits with a non-zero return code.

   When value is retry it attempts to behave like Sybase::BCP on error in
bcp_batch. These are where server errors are detected, like duplicate key
or deadlock error.

   By default, when -error_handling = retry

   * if a deadlock error is detected on the bcp_batch the program will
     sleep for -retry_deadlock_sleep seconds and rerun bcp_sendrow for all
     the rows in the batch and rerun bcp_batch once and repeat until no
     deadlock error or max tries.

   * if a non-deadlock error is detected on the bcp_batch the program will
     attempt to behave like Sybase::BCP by bcp_sendrow'ing and
     bcp_batch'ing every record. Those in error are written to the
     -error_data_file.

   The default is abort.

   Here's a deliberate example of a syntax type error and an example of
the output from the error_handler. Note This is detected on bcp_sendrow.
See below for bcp_batch error trace.

     #------
     #SAMPLE BCP_SENDROW ERROR FORMAT
     #------

     row #1
         1: ID                       char(10)        <bababooey >
         2: TICKER                   char(8)         <>
         3: CPN                      float(8)        <>
         4: MATURITY                 datetime(8)     <>
         5: SERIES                   char(6)         <JUNK>
         6: NAME                     varchar(30)     <>
         7: SHORT_NAME               varchar(20)     <>
         8: ISSUER_INDUSTRY          varchar(16)     <>
         9: MARKET_SECTOR_DES        char(6)         <>
        10: CPN_FREQ                 tinyint(1)      <>
        11: CPN_TYP                  varchar(24)     <>
        12: MTY_TYP                  varchar(18)     <>
        13: CALC_TYP_DES             varchar(18)     <>
        14: DAY_CNT                  int(4)          <>
        15: MARKET_ISSUE             varchar(25)     <bo_fixed_euro_agency_px>
     Column #16 actual length [26] > declared length [4]
        16: COUNTRY                  char(4)         <Sep 29 2000 12:00:00:000AM>
     Column #17 actual length [6] > declared length [4]
        17: CRNCY                    char(4)         <EMISCH>
        18: COLLAT_TYP               varchar(18)     <EBS (SWISS)>
        19: AMT_ISSUED               float(8)        <Govt>
        20: AMT_OUTSTANDING          float(8)        <CH>
        21: MIN_PIECE                float(8)        <>
        22: MIN_INCREMENT            float(8)        <CLEAN>
     Sybase error: Attempt to convert data stopped by syntax error in source field.

     Aborting on error.
       error_handling = abort
     1 rows read before abort

     #------
     #SAMPLE BCP_BATCH ERROR_FILE
     #------
     if B<-error_handling> = I<retry> and an error occurs on the bcp_batch then the -error_data_file will
     have this format.

     #recnum=1, reason=2601 Attempt to insert duplicate key row in object 'sjs_junk1' with unique index 'a'
     mwd|20010128|10.125
     #recnum=2, reason=2601 Attempt to insert duplicate key row in object 'sjs_junk1' with unique index 'a'
     lnux|20010128|2.875
     #recnum=3, reason=2601 Attempt to insert duplicate key row in object 'sjs_junk1' with unique index 'a'
     scmr|20010128|25.500
     #recnum=4, reason=2601 Attempt to insert duplicate key row in object 'sjs_junk1' with unique index 'a'
     qcom|20010128|84.625

     -retry_max <n>

   n is the number of times to retry a bcp_batch when an error is
detected. default is 3.

     -retry_deadlock_sleep <n>

   n is the number of secords to sleep between re-running a bcp_batch when
a deadlock error is detected.

     -callback_err_send <code_ref | hash_ref>

   sub to call if error detected on bcp sendrow. The module passes a hash
as seen below. It expects a 2 element array in return  ie. ($status,
\@row).  $status true means continue, $status false means abort.  Can also
be a hash_ref meaning to store the error rows keyed by row number.

   It's called like this if *code_ref*.  @row is the array of data:

     your_err_sendrow_cb(DB_ERROR => $DB_ERROR,
                         row_num  => $row_rum,
                         row_ptr  => \@row );

   It must return this:

     return ($status, \@row);

   It stores the error like this if *hash_ref*:

     $your_hash{ $row_num }->{msg} = $DB_ERROR;
     $your_hash{ $row_num }->{row} = \@row;

     -callback_err_batch <coderef>

   sub to call if an error detected on bcp_batch. The module passes a hash
as seen below. It expects a 2 element array in return. ie. ($status,
\@row).

   $status == 0 indicates to abort the batch.

   $status == 1 indicates to resend and batch a row at a time and report
errors to -error_data_file.

   $status > 1 indicates not to do a record by record send and batch but
to resend and batch once.

   It's called like this:

     your_err_batch_cb(DB_ERROR  => $DB_ERROR,
                       row_num   => $row_num,
                       rows      => \@row)

   It must return this:

     return ($status, \@row);

   A word about @row above. It's got a tad more info in it.  @row is a
array of hash refs. where:

     $row[$i]->{rn}  == row number in input file,
     $row[$i]->{row} == the actual array of data

miscellaneous boolean flags
---------------------------

     -echo

   echo sql commands running under the covers. Default is false.

     -silent

   don't print begin & end/summary messages. Default is false.

     -progress_log

   print progess message on every bcp_sendbatch. Default is true.

     -debug

   programmer debug mode. Default is false.

EXAMPLES
========

EXAMPLE #1  - simple table transfer
-----------------------------------

     my %opts = (
                  -from_server   => 'EARTH',
                  -to_server     => 'MARS',
                  -U             => 'steve',          #user 'steve' is valid on both servers/dbs
                  -P             => 'BobDobbs',       #same pw for both
                  -T             => 'lamr..cities',   #same db and table on both servers

     -truncate_flag => 1,                #issue a 'truncate table lamr..cities' on to server
     -batchsize     => 2000,
                   );

     my $h = new Sybase::Xfer(%opts);
     my $rs = $h->xfer();
     $rs && die 'xfer aborted';

EXAMPLE #2  - using 'from_sql'
------------------------------

     my %opts = (
                  -from_server    => 'NYP_FID_RATINGS',
                  -from_user      => 'rateuser',
                  -from_password  => 'grack',
                  -from_database  => 'fid_ratings',
                  -from_sql       => 'select id, name, rating from rating where name like "A%"',

     -to_server      => 'NYP_FID_DATAMART',
     -to_user        => 'fiduser',
     -to_password    => 'glorp',
     -to_table       => 'fid_datamart..ratings_sap',  #NOTE FULLY QUALIFIED NAME

     -batchsize      => 500,
     -error_handling => 'abort',
                    );

     my $h = new Sybase::Xfer(%opts);
     my $rs = $h->xfer();
     $rs && die 'xfer aborted';

EXAMPLE #3  - using all three callbacks
---------------------------------------

     my %opts = (
                  -from_server        => 'MOTO',
                  -from_user          => 'guest',
                  -from_password      => 'guest',
                  -from_database      => 'parts',
                  -from_sql           => "select partno, desc, price from elec\n" .
                                         "UNION\n" .
                                         "select partno, name, px from m777\n",

     -to_server          => 'MASTERMOTO',
     -to_user            => 'kingfish',
     -to_password        => 'shirley',
     -to_table           => 'summary..elec_contents',

     -callback_pre_send  => \&pre_send,
     -callback_err_send  => \&err_on_send,
     -callback_err_batch => \&err_batch,

     -batchsize          => 100,
                    );

     #-----
     #pre send callback. Adds 10000 to partno effectively between the time it
     #was pulled from the source and the time it gets pushed into the target table.
     #-----
        sub pre_send {
          my @row = @{ +shift };    #array reference to the row about to be sent to the 'to' server
          $row[0] += 10000;         #manipulate @row all you want
          my $status = 1;           #status true means continue, false means abort
          return ($status, \@row);  #mandatory return args
        }

     #----
     #error on 'send row' callback - fix a syntax error by nulling out offending value.
     #----
        sub err_on_send {

     my %err_data = @_;

      #just to be explicit about it
     my $err_message = $err_data{DB_ERROR};  #key #1 = 'DB_ERROR'
     my $err_row_num = $err_data{row_num};   #key #2 = 'row_num' : last row sent to server
     my @row =  @{ $err_data{row_ptr} };     #key #3 = 'row_ptr' : reference to the array of

     #nb.
     #for example purposes I'm hardwiring this. I real life you'd create closure and send
     #it via that to this routine has a parameter.
     #
     #list of datatypes of the columns
            my $p_datatypes->{part_no}->{col_id} = 1;
            my $p_datatypes->{part_no}->{col_type} = 'int';
            my $p_datatypes->{descr}->{col_id} = 2;
            my $p_datatypes->{descr}->{col_type} = 'varchar(30)';
            my $p_datatypes->{price}->{col_id} = 3;
            my $p_datatypes->{price}->{col_type} = 'float';

            my (@col_names, @col_types, $retry_status) = ();

     #get column names in column order
            my @col_names =  sort { $p_datatypes->{$a}->{col_id}
                             <=> $p_datatypes->{$b}->{col_id} }
                             keys %{ $p_datatypes };

     #get column types
            for my $col (@col_names) { push @col_types, $p_datatypes->{$col}->{col_type} }

     #for syntax errors compare data to data type
            my @row = ();
            if ($err_data{DB_ERROR} =~ /syntax/i ) {
               @row = @{ $err_data{row_ptr} };

     #check for character data in 'int' field
               for( my $i=0; $i<@row; $i++) {
                  if($col_types[$i] =~ /int/ && $row[$i] =~ /\D/ ) {
                     $row[$i] = undef;
                     $retry_status = 1;
                  }
               }
            }

     #if not a retry candidate then bail out
            unless ($retry_status) {
               cmp_print("row failed ($err_data{DB_ERROR})\n");
               for( my $i=0; $i<@row; $i++) { cmp_print("\t$i : $row[$i]\n") }
               cmp_error("xfer aborted");
            }

            return ($retry_status,\@row);
       }

     #----
     #error on 'send batch' callback
     #----
        sub err_batch {
          my %info = @_;                      #arg is a two keyed hash
          my $err_message = $info{DB_ERRROR}; #key #1 = 'DB_ERROR'
          my $err_row_num = $info{row_num};   #key #2 = 'row_num', last row sent to server
          my $status = 1;                     #status true means continue, false means abort
          return $status;                     #mandatory return arg
        }

EXAMPLE #4 - Using auto_delete
------------------------------

     my %opts = (
                  -user           => 'smoggy',
                  -password       => 'smoggy',
                  -table          => 'fx_rates..asia_geo_region',

     -from_server    => 'TEST',
     -to_server      => 'PROD',

     -auto_delete    => 'country_iso, id',   #unique key in table
     -auto_delete_batchsize => 10000,        #change the default
     -scratch_db     => 'tempdb',            #just to be explicit about it

     -batchsize      => 50000,
     -error_handling => 'abort',
                    );

     my $h = new Sybase::Xfer(%opts);
     my $rs = $h->xfer();
        $rs && die 'xfer aborted';>

WISH LIST
=========

   * Would like to convert from Sybase:: to DBI:: and ultimately be able
     to transfer data between different server makes and models.

   * Create the -to_table on the fly if it doesn't exist.

   * Incorporate logic to do the right thing when transferring data
     between Unicode and ISO versions of the Sybase server.

   * Allow DBlib handle to be passed in lieu of
     from_user/from_pwd/from_server

   * add option to drop indices before bcp and re-create indices after bcp.

BUGS
====

   * Deadlock retry features need to more thoroughly tested.

CONTACTS
========

Author's e-mail
     stephen.sprague@msdw.com

Michael Peppler's homepage
     http://www.mbay.net/~mpeppler/ for all things perl and Sybase
     including Sybase::DBLib, Sybase::BCP and a ton other goodies.
     Definitely a must see.

Sybperl mail-list
     This a good place to ask questions specifically about Sybase and Perl.
     I pulled these instructions from Michael's page:

     Send a message to listproc@list.cren.net with subscribe Sybperl-L
     *your-name* in the body to subscribe. The mailing list is archived
     and searchable at http://www.cren.net:8080/

Original idea
     Sybase::Xfer idea inspired by Mikhail Kopchenov.

VERSION
=======

   Version 0.31, 12-FEB-2000 Version 0.30, 10-FEB-2000 Version 0.20,
12-DEC-2000

manipulate Perl symbols and their names
***************************************

NAME
====

   Symbol - manipulate Perl symbols and their names

SYNOPSIS
========

     use Symbol;

     $sym = gensym;
     open($sym, "filename");
     $_ = <$sym>;
     # etc.

     ungensym $sym;      # no effect

     print qualify("x"), "\n";              # "Test::x"
     print qualify("x", "FOO"), "\n"        # "FOO::x"
     print qualify("BAR::x"), "\n";         # "BAR::x"
     print qualify("BAR::x", "FOO"), "\n";  # "BAR::x"
     print qualify("STDOUT", "FOO"), "\n";  # "main::STDOUT" (global)
     print qualify(\*x), "\n";              # returns \*x
     print qualify(\*x, "FOO"), "\n";       # returns \*x

     use strict refs;
     print { qualify_to_ref $fh } "foo!\n";
     $ref = qualify_to_ref $name, $pkg;

     use Symbol qw(delete_package);
     delete_package('Foo::Bar');
     print "deleted\n" unless exists $Foo::{'Bar::'};

DESCRIPTION
===========

   `Symbol::gensym' creates an anonymous glob and returns a reference to
it.  Such a glob reference can be used as a file or directory handle.

   For backward compatibility with older implementations that didn't
support anonymous globs, `Symbol::ungensym' is also provided.  But it
doesn't do anything.

   `Symbol::qualify' turns unqualified symbol names into qualified
variable names (e.g. "myvar" -> "MyPackage::myvar").  If it is given a
second parameter, qualify uses it as the default package; otherwise, it
uses the package of its caller.  Regardless, global variable names (e.g.
"STDOUT", "ENV", "SIG") are always qualified with "main::".

   Qualification applies only to symbol names (strings).  References are
left unchanged under the assumption that they are glob references, which
are qualified by their nature.

   `Symbol::qualify_to_ref' is just like `Symbol::qualify' except that it
returns a glob ref rather than a symbol name, so you can use the result
even if `use strict 'refs'' is in effect.

   `Symbol::delete_package' wipes out a whole package namespace.  Note
this routine is not exported by default-you may want to import it
explicitly.

Perl module for calling subroutines by approximate names!
*********************************************************

NAME
====

   Symbol::Approx::Sub - Perl module for calling subroutines by
approximate names!

SYNOPSIS
========

     use Symbol::Approx::Sub;

     sub a {
       # blah...
     }

     &aa; # executes &a if &aa doesn't exist.

     use Symbol::Approx::Sub (match => 'text_metaphone');
     use Symbol::Approx::Sub (match => 'string_approx');
     use Symbol::Approx::Sub (match => 'text_soundex');
     use Symbol::Approx::Sub (match => \&my_matcher);
     use Symbol::Approx::Sub (match => \&my_matcher, choose => \&my_chooser);

DESCRIPTION
===========

   This is _really_ stupid. This module allows you to call subroutines by
_approximate_ names. Why you would ever want to do this is a complete
mystery to me. It was written as an experiment to see how well I
understood typeglobs and AUTOLOADing.

   To use it, simply include the line:

     use Symbol::Approx::Sub;

   somewhere in your program. Then each time you call a subroutine that
doesn't exist in the the current package Perl will search for a subroutine
with approximately the same name. The meaning of 'approximately the same'
is configurable. The default is to find subroutines with the same Soundex
value (as defined by Text::Soundex) as the missing subroutine. There are
two other built-in matching styles using Text::MetaPhone and
String::Approx. To use either of these use:

     use Symbol::Approx::Sub (match => 'text_metaphone');

   or

     use Symbol::Approx::Sub (match => 'string_approx');

   when using Symbol::Approx::Sub.

   You can also use your own subroutine to do the matching. Your subroutine
should expect to receive the name of the missing subroutine followed by a
list containing all valid subroutine names and should return a list of all
matching subroutines. For example:

     sub my_matcher {
       my $sub_wanted = shift;

     my @subs = @_;

     return @subs;
     }

   This example isn't particularly useful as it says that all subroutine
names are an equally good match. To use this match subroutine in place of
the standard ones, give Symbol::Approx::Sub a reference to the subroutine
like this:

     use Symbol::Approx::Sub (match => \&my_matcher);

   Having retrieved a list of matches, we need to select one of them to
run. The default behaviour is to pick one at random, but again you can
configure this behaviour by writing a subroutine. This subroutine will be
passed a list of matching subroutine names and should return the name of
the subroutine to run. For example:

     sub my_chooser {
       return shift;
     }

   which will return the first subroutine name in the list. To make
Symbol::Approx::Sub use this subroutine in place of the standard one, give
Symbol::Approx::Sub a reference to the subroutine like this:

     use Symbol::Approx::Sub (choose => \&my_chooser);

   You can, of course, define both a matcher and a chooser like this:

     use Symbol::Approx::Sub (match => \&my_matcher, choose => \&my_chooser);

   or use you own chooser in conjunction with a standard matcher like this:

     use Symbol::Approx::Sub (match => 'text_metaphone',
                              choose => \&my_chooser);

CAVEAT
======

   I can't stress too strongly that this will make your code completely
unmaintainable and you really shouldn't use this module unless you're
doing something very stupid.

ACKNOWLEDGEMENTS
================

   This idea came to me whilst sitting in Mark-Jason Dominus' "Tricks of
the Wizards" tutorial. In order to protect his reputation I should
probably point out that just as the idea was forming in my head he clearly
said that this kind of thing was a very bad idea.

   Leon Brocard is clearly as mad as me as he pointed out some important
bugs and helped massively with the 'fuzzy-configurability'.

   Matt Freake helped by pointing out that Perl generally does what you
mean, not what you think it should do.

   Robin Houston spotted some nasty problems and (more importantly)
supplied patches.

AUTHOR
======

   Dave Cross <dave@dave.org.uk>

   With lots of help from Leon Brocard <leon@astray.com>

SEE ALSO
========

   perl(1).

low-level data manipulation modules for Symphero E-Commerce suite.
******************************************************************

NAME
====

   Symphero::Data - low-level data manipulation modules for Symphero
E-Commerce suite.

SYNOPSIS
========

   None, see individual manpages.

DESCRIPTION
===========

   Symphero::Data is actually a dummy package that includes the following
actual modules:

   * Symphero::MultiValueDB

   * Symphero::MultiValueHash

   * Symphero::SimpleHash

   * Symphero::Utils

EXPORTS
=======

   Nothing.

AUTHOR
======

   Brave New Worlds, Andrew Maltsev <amaltsev@xao.com>

SEE ALSO
========

   Suggested reading: Symphero/MultiValueDB,
Symphero/MultiValueHash,
Symphero/SimpleHash, Symphero/Utils.

3D database storage
*******************

NAME
====

   Symphero::MultiValueDB - 3D database storage

SYNOPSIS
========

     use Symphero::MultiValueDB;

     my $db=Symphero::MultiValueDB->new(dbh => $dbh, table => 'Users');

     $db->setid('username');

     my $password=$db->get('password');

     $db->put(a => 123, b => 234);

DESCRIPTION
===========

   Database support for Symphero::MultiValueHash class. Each accessing and
mutating method of SimpleHash and MultiValueHash actually goes into
underlying SQL database. No caching is performed (though database may
cache data itself).

   Database has the following structure (all fields may be BLOBS or have
different sizes, no checks of size limitations performed):

   * id

     Data hash ID (customer ID, shopping cart ID or something similar).

   * name

     Parameter name.

   * subname

     Parameter subname, used for multi-value parameters. Will be empty, but
     not NULL for single value parameters.

   * value

     Parameter value.

   It is recommended to make index on `id' and `name' fields together and
make primary key of `id', `name' and `subname' together. An example of SQL
clause to create table might look like:

   CREATE TABLE ShoppingCarts (    id char(20) DEFAULT " NOT NULL,    name
char(40) DEFAULT " NOT NULL,    subname char(40) DEFAULT " NOT NULL,
value char(200),    PRIMARY KEY (id,name,subname),    KEY idname (id,name)
);

METHODS
=======

   All methods of Symphero/MultiValueHash,
are available with the following changes and additions:

   * new ($@)

     Instead of accepting default values for the hash itself it requires
     the following parameters:

    -
          dbh

          DBI handler to SQL database.

    -
          table

          Name of the table in that database

    -
          id (optional)

          ID of data block inside the table - shopping cart ID, session
          ID, user ID or something similar.

          This parameter is optional in new() method, but required to
          store and retrieve data.

   * getref ($$), getsubref ($$)

     Disabled - always produce warning and return undef. We cannot easily
     trace if the values reference to which we return would be modified.

   * setid ($$)

     Switches the object to use new data block ID. Must be called if you
     did not pass "id" into new() method.

   * listids ($$$)

     Return a list of data block IDs for which condition is met. Condition
     is represented by name-value pair. The following example will return
     the list of shopping cart IDs for given user:

     use Symphero::MultiValueDB;

     my $sdb = Symphero::MultiValueDB->new(...);

     my @ids = $sdb->listids(logname => "testuser");

     print join(",",@ids),"\n";

EXPORTS
=======

   Nothing.

AUTHOR
======

   Andrew Maltsev, <am@xao.com>

SEE ALSO
========

3D extension of Symphero::SimpleHash
************************************

NAME
====

   Symphero::MultiValueHash - 3D extension of Symphero::SimpleHash

SYNOPSIS
========

     use Symphero::MultiValueHash;

DESCRIPTION
===========

   Provides API for manipulating data in a 3D hash. 3D means that any
element in such a hash can be accessed using three `coordinates' - `id',
`name' and `subname'.

   Based on Symphero::SimpleHash and adds the following methods:

getsub ($$)
getsubref ($$)
putsub ($$)
delsub ($$)
EXPORTS
=======

   Nothing.

AUTHOR
======

   Andrew Maltsev, <am@xao.com>

SEE ALSO
========

Simple 2D hash manipulations
****************************

NAME
====

   Symphero::SimpleHash - Simple 2D hash manipulations

SYNOPSIS
========

     use Symphero::SimpleHash;

     my $h=new Symphero::SimpleHash a => 11, b => 12, c => 13;

     $h->put(d => 14);

     $h->fill(\%config);

     my @keys=$h->keys;

DESCRIPTION
===========

   Base object from which various hash-like containers are derived.

   Methods are (alphabetical order, PERL API):

   * sub contains ($$)

     Returns key of the element, containing given text. Case is
     insignificant in comparision.

     If no value found `undef' is returned.

   * sub defined ($$)

     Boolean method to check if element with given key defined or not.
     Exactly the same as `defined ($hash->get($key))'.

   * sub delete ($$)

     Deletes given key from the hash.

   * sub exists ($$)

     Checks if given key exists in the hash or not (regardless of value,
     which can be undef).

   * sub fill ($@)

     Allows to fill hash with multiple values. Supports variety of argument
     formats:

     $hash->fill(key1 => value1, key2 => value2, ...);

     $hash->fill({ key1 => value1, key2 => value2, ... });

     $hash->fill([ key1 => value1 ], [ key2 => value2 ], ...);

   * sub get ($$)

     Returns element by given key.

   * sub getref ($$)

     Return reference to the element by given key or `undef' if such
     element does not exist.

   * sub keys ($)

     Returns array of keys.

   * sub new ($;@)

     Creates new hash and pre-fills it with given values. Values are in the
     same format as in fill().

   * sub put ($$$)

     Puts single key-value pair into hash. Usually called as:

     $hash->put(key => value);

   * sub value ($)

     Pure virtual method which is supposed to be overriden in all derived
     classes. Should return the value an object as a whole.

   * sub values ($)

     Returns array of values in the same order as $hash->keys returns keys
     (on non-modified hash).

JAVA STYLE API
==============

   In addition to normal Perl style API outlined above Symphero::SimpleHash
allows developer to use Java style API. Here is the mapping between Perl
API and Java API:

     isSet          --  defined
     containsKey    --  exists
     elements       --  values
     remove         --  delete
     containsValue  --  contains

EXPORTS
=======

   Nothing.

AUTHORS
=======

   Brave New Worlds: Bil Drury <bild@xao.com>, Andrew Maltsev <am@xao.com>.

SEE ALSO
========

Utility functions widely used by Symphero modules
*************************************************

NAME
====

   Symphero::Utils - Utility functions widely used by Symphero modules

SYNOPSIS
========

     use Symphero::Utils;

     or

     use Symphero::Utils (); # do not export any functions

DESCRIPTION
===========

   To be extended..

EXPORTS
=======

   eprint(), dprint(), t2ht(), t2hf(), t2hq(), generate_key(),
repair_key(), get_args().

AUTHOR
======

   Andrew Maltsev, <amaltsev@valinux.com>

SEE ALSO
========

a module to retrieve system load averages.
******************************************

NAME
====

   Sys::CpuLoad - a module to retrieve system load averages.

DESCRIPTION
===========

   This module retrieves the 1 minute, 5 minute, and 15 minute load average
of a machine.

SYNOPSIS
========

     use Sys::CpuLoad;
     print '1 min, 5 min, 15 min load average: ',
           join(',', CpuLoad::load()), "\n";

TO-DO
=====

   Support for systems without /proc/loadavg or /usr/bin/uptime by using
native system calls.  Ability to read CPU usage of individual CPUs on
multiprocessor machines.

AUTHOR
======

     Clinton Wong, clintdw@netcom.com

COPYRIGHT
=========

     Copyright (c) 1999 Clinton Wong. All rights reserved.
     This program is free software; you can redistribute it
     and/or modify it under the same terms as Perl itself.

Try really hard to get IP addr.
*******************************

NAME
====

   Sys::HostIP - Try really hard to get IP addr.

SYNOPSIS
========

     use Sys::HostIP;
     $ipaddr= hostip; # get (text) dotted-decimal ip

AUTHOR
======

   v, <v@rant.scriptmania.com>

SEE ALSO
========

   perl(1), IO::Socket, Sys::Hostname, ping, ipconfig, nbtstat, /etc/hosts

Try every conceivable way to get hostname
*****************************************

NAME
====

   Sys::Hostname - Try every conceivable way to get hostname

SYNOPSIS
========

     use Sys::Hostname;
     $host = hostname;

DESCRIPTION
===========

   Attempts several methods of getting the system hostname and then caches
the result.  It tries the first available of the C library's
gethostname(), ``$Config{aphostname}`', uname(2),
`syscall(SYS_gethostname)', ``hostname`', ``uname -n`', and the file
`/com/host'.  If all that fails it croaks.

   All NULs, returns, and newlines are removed from the result.

AUTHOR
======

   David Sundstrom <`sunds@asictest.sc.ti.com'>

   Texas Instruments

   XS code added by Greg Bacon <`gbacon@cs.uah.edu'>

Provide a moderately Object Oreiented Interface to lastlog                 files on some Unix-like systems.
***********************************************************************************************************

NAME
====

   Sys::Lastlog - Provide a moderately Object Oreiented Interface to
lastlog                files on some Unix-like systems.

SYNOPSIS
========

     use Sys::Lastlog;

     my $ll = Sys::Lastlog->new();

     while(my $llent = $ll->getllent() )
     {
       print $llent->ll_line(),"\n";
     }

DESCRIPTION
===========

   The lastlog file provided on most Unix-like systems stores information
about when each user on the system last logged in.  The file is sequential
and indexed on the UID (that is to say a user with UID 500 will have the
500th record in the file).  Most systems do not provide a C API to access
this file and programs such as 'lastlog' will provide their own methods of
doing this.

   This module provides an Object Oriented Perl API to access this file in
order that programs like 'lastlog' can written in Perl (for example the
'plastlog' program in this distribution) or that programs can determine a
users last login for their own purposes.

   The module provides three methods for accessing lastlog sequentially, by
UID or by login name.  Each method returns an object of type
Sys::Lastlog::Entry  that itself provides methods for accessing the
information for each record.

METHODS
-------

new
     The constructor of the class.  Returns a blessed object that the
     other methods can be called on.

getllent
     This method will sequentially return each record in the lastlog each
     time it is called, returning a false value when there are no more
     records to return.  Because the lastlog file is indexed on UID if
     there are gaps in the allocation of UIDs on a system will there will
     be as many empty records returned ( that is to say if for some reason
     there are no UIDs used between 200 and 500 this method will
     nonetheless return the 299 empty records .)

getlluid SCALAR $uid
     This method will return a record for the $uid specified or a false
     value if the UID is out of range, it does however perform no check
     that the UID has actually been assigned it must simply be less than
     or equal to the maximum UID currently assigned on the system.

getllnam SCALAR $logname
     This will return the record corresponding to the user name $logname or
     false if it is not a valid user name.

setllent
     Set the file pointer on the lastlog file back to the beginning of the
     file for repeated iteration over the file using getllent() .

PER RECORD METHODS
------------------

   These are the methods of the class Sys::Lastlog::Entry that give access
to the information for each record.

uid
     The UID that corresponds to this record.

ll_time
     The time in epoch seconds of this users last login.

ll_line
     The line (e.g. terminal ) that this user logged in via.

ll_host
     The host from which this user logged in from or the empty string if
     it was a local login.

EXPORT
------

   None at all

BUGS
====

   Probably.

   Some systems (notoriously Red Hat Linux) may mistakenly rotate the
lastlog file periodically - there is no benefit in doing this as the file
will only grow if new users are added to the system and in the authors
opinion it is important to keep an accurate record of all users last
logins however long ago for audit and security purposes. If you are on
such a system and care about this you should disable the rotation of this
file. On a Red Hat system this will involve editing /etc/logrotate.conf to
remove the file from the rotation.

   This should build on most systems given the notes in README but the
author would appreciate being informed of any unusual systems where
difficulty may be experienced.

AUTHOR
======

   Jonathan Stowe <jns@gellyfish.com>

COPYRIGHT AND LICENSE
=====================

   Copyright Jonathan Stowe 2001.

   This software comes with no warranty whatsoever.

   This is free software and may be distributed and/or modified under the
same terms as Perl itself.

SEE ALSO
========

   See Perl (perl.info).

Perl module to help make output easier.
***************************************

NAME
====

   Sys::OutPut - Perl module to help make output easier.

SYNOPSIS
========

     usage Sys::OutPut;

     talk $fmtstr [, @args];

     out  $fmtstr [, @args];

     put  $fmtstr [, @args];

     err  $fmtstr [, @args];

     debug $fmtstr [, @args];

     $Sys::OutPut::quiet = $::quiet;

     $Sys::OutPut::debug = $::debug;

DESCRIPTION
===========

   These subroutines will make generating output to STDOUT and `STDERR'
easier.

   All of the routines treat the *$fmtstr* argument as a printf format
string, with *@args* as the format string arguments.

   The *talk* routine generates output to `STDERR' only if the variable
`$Sys::OutPut::quiet' is non-null and non-zero.

   The out routine generates output to STDOUT, with a *newline* appended
to <$fmtstr>, if it is not already terminated with one.

   The put routine generates output to STDOUT, without any additional
trailing newline.

   The err routine generates output to `STDERR', with a *newline* appended
if needed.

   The debug routine generates output to `STDERR' only if the variable
`$Sys::OutPut::debug' is non-null and non-zero, which is also returned as
the result.  This allows for convenient usages such as in the following
example:

     sub foo {
     	...
     	return if debug "Stopping now.";
     	...
     	next if debug "Skipping further processing";
     	...
     }

   If not defined by the user, the `$Sys::OutPut::quiet' and
`$Sys::OutPut::debug' variables are initialized from their corresponding
main variables `$::quiet' and `$::debug', respectively, unless they are
already defined.

AUTHOR
======

   Alan K. Stebbens <aks@sgi.com>

BUGS
====

change directory temporarily
****************************

NAME
====

   *Sys::Pushd* - change directory temporarily

SYNOPSIS
========

     use Sys::Pushd;
     {
       my $ignore=new Sys::Pushd '../new/dir';
       # Cwd is ../new/dir
     }
     # After block exit, cwd is restored

DESCRIPTION
===========

   Synopsis pretty much says it all. Based conceptually on SelectSaver.

   Multiple directories may be given, in which case they will be chdird to
in order encountered.

BUGS
====

   Will break if immediate-destruction of objects ever ceases to be
reliable in Perl.

AUTHORS
=======

   J. Glick *jglick@sig.bsh.com*.

REVISION
========

   X<$Format: "`$Source$' last modified $Date$ release $SysPushdRelease$.
$Copyright$"$> `Sys-Pushd/lib/Sys/Pushd.pm' last modified Tue, 09 Sep 1997
17:07:06 -0400 release 0.001. Copyright (c) 1997 Strategic Interactive
Group. All rights reserved. This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

Set signal handlers with restoration of existing C sighandler
*************************************************************

NAME
====

   Sys::Signal - Set signal handlers with restoration of existing C
sighandler

SYNOPSIS
========

     use Sys::Signal ();
     eval {
         my $h = Sys::Signal->set(ALRM => sub { die "timeout\n" });
         alarm $timeout;
         ... do something thay may timeout ...
         alarm 0;
     };
     die $@ if $@;

DESCRIPTION
===========

   The *Sys::Signal* set method works much like `local $SIG{FOO}', but
with the added functionality of restoring the underlying signal handler to
the previous C function, rather than Perl's.  Unless, of course, Perl's C
signal handler was the previous handler.

AUTHOR
======

   Doug MacEachern

SEE ALSO
========

   perl(1).

Perl interface to the UNIX syslog(3) calls
******************************************

NAME
====

   Sys::Syslog, openlog, closelog, setlogmask, syslog - Perl interface to
the UNIX syslog(3) calls

SYNOPSIS
========

     use Sys::Syslog;                          # all except setlogsock, or:
     use Sys::Syslog qw(:DEFAULT setlogsock);  # default set, plus setlogsock

     setlogsock $sock_type;
     openlog $ident, $logopt, $facility;
     syslog $priority, $format, @args;
     $oldmask = setlogmask $mask_priority;
     closelog;

DESCRIPTION
===========

   Sys::Syslog is an interface to the UNIX `syslog(3)' program.  Call
`syslog()' with a string priority and a list of printf() args just like
`syslog(3)'.

   Syslog provides the functions:

openlog $ident, $logopt, $facility
     *$ident* is prepended to every message.  *$logopt* contains zero or
     more of the words pid, *ndelay*, *cons*, nowait.  *$facility*
     specifies the part of the system

syslog $priority, $format, @args
     If *$priority* permits, logs *($format, @args)* printed as by
     `printf(3V)', with the addition that *%m* is replaced with `"$!"'
     (the latest error message).

setlogmask $mask_priority
     Sets log mask *$mask_priority* and returns the old mask.

setlogsock $sock_type (added in 5.004_02)
     Sets the socket type to be used for the next call to `openlog()' or
     `syslog()' and returns TRUE on success, undef on failure.

     A value of 'unix' will connect to the UNIX domain socket returned by
     `_PATH_LOG' in `syslog.ph'.  A value of 'inet' will connect to an
     INET socket returned by getservbyname().  Any other value croaks.

     The default is for the INET socket to be used.

closelog
     Closes the log file.

   Note that openlog now takes three arguments, just like `openlog(3)'.

EXAMPLES
========

     openlog($program, 'cons,pid', 'user');
     syslog('info', 'this is another test');
     syslog('mail|warning', 'this is a better test: %d', time);
     closelog();

     syslog('debug', 'this is the last test');

     setlogsock('unix');
     openlog("$program $$", 'ndelay', 'user');
     syslog('notice', 'fooprogram: this is really done');

     setlogsock('inet');
     $! = 55;
     syslog('info', 'problem was %m'); # %m == $! in syslog(3)

SEE ALSO
========

   `syslog(3)' in this node

AUTHOR
======

   Tom Christiansen <`tchrist@perl.com'> and Larry Wall <`larry@wall.org'>.
UNIX domain sockets added by Sean Robinson <`robinson_s@sc.maricopa.edu'>
with support from Tim Bunce <Tim.Bunce@ig.co.uk> and the perl5-porters
mailing list.  Dependency on `syslog.ph' replaced with XS code bu Tom
Hughes <`tom@compton.nu'>.

Get a guaranteed unique identifier.
***********************************

NAME
====

   Sys::UniqueID - Get a guaranteed unique identifier.

   Great for generating database keys, temporary filenames, and even gets
out those tough grass stains!

SYNOPSIS
========

     use Sys::UniqueID;
     $id= uniqueid;

AUTHOR
======

   v, <v@rant.scriptmania.com>

SEE ALSO
========

   perl(1), Sys::HostIP

Object(ish) Interface to UTMP files.
************************************

NAME
====

   Sys::Utmp - Object(ish) Interface to UTMP files.

SYNOPSIS
========

     use Sys::Utmp;

     my $utmp = Sys::Utmp->new();

     while ( my $utent =  $utmp->getutent() )
     {
        if ( $utent->user_process )
        {
           print $utent->ut_user,"\n";
        }
      }

     $utmp->endutent;

DESCRIPTION
===========

   Sys::Utmp provides a vaguely object oriented interface to the Unix user
accounting file ( usually /etc/utmp ).  Whilst it would prefer to use the
getutent() function from the systems C libraries it will attempt to
provide its own if they are missing.

   This may not be the module that you are looking for - there is a
User::Utmp which provides a different procedural interface and may well be
more complete for your purposes.

METHODS
-------

new
     The constructor of the class.

getutent
     Iterates of the records in the utmp file returning a Sys::Utmp::Utent
     object for each record in turn - the methods that are available on
     these objects are descrived below in 'PER RECORD METHODS'

setutent
     Rewinds the file pointer on the utmp filehandle so repeated searches
     can be done.

endutent
     Closes the file handle on the utmp file.

PER RECORD METHODS
------------------

   As mentioned above the getutent method returns an object of the type
Sys::Utmp::Utent which provides methods for accessing the fields in the
utmp record.  There are also methods for determining the type of the
record.

   The access methods relate to the common names for the members of the C
struct utent - those provided are the superset from the Gnu implementation
and may not be available on all systems: where they are not they will
return the empty string.

ut_user
     Returns the use this record was created for if this is a record for a
     user process.  Some systems may return other information depending on
     the record type.  If no user was set this will be the empty string.

ut_id
     The identifier for this record - it might be the inittab tag or some
     other system dependent value.

ut_line
     For user process records this will be the name of the terminalor line
     that the user is connected on.

ut_pid
     The process ID of the process that created this record.

ut_type
     The type of the record this will have a value corresponding to one of
     the constants (not all of these may be available on all systems and
     there may well be others which should be described in the getutent
     manpage or in /usr/include/utmp.h ) :

    ACCOUNTING - record was created for system accounting purposes.
    BOOT_TIME - the record was created at boot time.
    DEAD_PROCESS - The process that created this record has terminated.
    EMPTY  - record probably contains no other useful information.
    INIT_PROCESS - this is a record for process created by init.
    LOGIN_PROCESS - this record was created for a login process (e.g. getty).
    NEW_TIME  - record created when the system time has been set.
    OLD_TIME - record recording the old tme when the system time has been set.
    RUN_LVL - records the time at which the current run level was started.
    USER_PROCESS - record created for a user process (e.g. a login )
     for convenience Sys::Utmp::Utent provides methods which are lower case
     versions of the constant names which return true if the record is of
     that type.

ut_host
     On systems which support this the method will return the hostname of
     the host for which the process that created the record was started -
     for example for a telnet login.

ut_time
     The time in epoch seconds wt which the record was created.

EXPORT
------

   No methods or constants are exported by default.

Exportable constants
--------------------

   These constants are exportable under the tag ':constants':

     ACCOUNTING
     BOOT_TIME
     DEAD_PROCESS
     EMPTY
     INIT_PROCESS
     LOGIN_PROCESS
     NEW_TIME
     OLD_TIME
     RUN_LVL
     USER_PROCESS

BUGS
     Probably.  This module has been tested on Linux, Solaris, FreeBSD ,SCO
     Openserver and SCO UnixWare and found to work on those platforms.  If
     you have difficulty building the module or it doesnt behave as
     expected then please contact the author including if appropriate your
     /usr/include/utmp.h

AUTHOR
======

   Jonathan Stowe, <Jonathan.Stowe@netscalibur.co.uk>

LICENCE
=======

   This Software is Copyright Netscalibur UK 2001.

   This Software is published as-is with no warranty express or implied.

   This is free software and can be distributed under the same terms as
Perl itself.

SEE ALSO
========

   See Perl (perl.info).

Organizes a Summary of mail statistics into Groups of related e-mail users
**************************************************************************

NAME
====

   SyslogScan::ByGroup - Organizes a Summary of mail statistics into
Groups of related e-mail users

SYNOPSIS
========

     # $summary is a SyslogScan::Summary object

     # default is to organize by internet host
     my $byGroup = new SyslogScan::ByGroup($summary);
     print $byGroup -> dump();

     # group by whether users use 'jupiter' or 'satellife' as
     # their machine name, and discard users who use neither

     my $pointerToGroupingRoutine = sub {
     	my $address = shift;

     return 'jupiter' if $address =~ /jupiter.healthnet.org$/;
     	return 'satellife' if $address =~ /satellife.healthnet.org$/;

     # ignore all others
     return undef;
         }

     my $groupByMachine = new SyslogScan::ByGroup($summary,
     						 $pointerToGroupingRoutine);
     print $groupByMachine -> dump();

     # Extract a SyslogScan::Group object
     my $jupiterGroup = $$groupByMachine{jupiter};
     print $jupiterGroup -> dump();

     # Extract a SyslogScan::Summary object
     my $summaryOfJupiter = $jupiterGroup{byAddress};
     print $summaryOfJupiter -> dump();

     # Create a summary by group, rather than a summary by address
     my $summaryByMachine = $groupByMachine -> createSummary();

DESCRIPTION
===========

   A SyslogScan::ByGroup object is a hash table of SyslogScan::Group
objects, each indexed by the group name as returned by the sorting
algorithm fed to 'new'.

   A SyslogScan::Group is a hash table with two members: 'byAddress',
which is a SyslogScan::Summary of each address which is a member of the
Group, and 'groupUsage', which is a SyslogScan::Usage object containing
the total usage of the group.

AUTHOR and COPYRIGHT
====================

   The author (Rolf Harold Nelson) can currently be e-mailed as
rolf@usa.healthnet.org.

   This code is Copyright (C) SatelLife, Inc. 1996.  All rights reserved.
This code is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

   In no event shall SatelLife be liable to any party for direct,
indirect, special, incidental, or consequential damages arising out of the
use of this software and its documentation (including, but not limited to,
lost profits) even if the authors have been advised of the possibility of
such damage.

SEE ALSO
========

   See SyslogScan/Summary, SyslogScan/Usage,

encapsulates a logged, successful delivery of mail from a sender to a list of recipients.
*****************************************************************************************

NAME
====

   SyslogScan::Delivery - encapsulates a logged, successful delivery of
mail from a sender to a list of recipients.

SYNOPSIS
========

   see SyslogScan/DeliveryIterator,

DESCRIPTION
===========

   A 'Delivery' object is an indication that mail was successfully
delivered or forwarded from a sender to a list of recipients.  You can
extract Delivery objects from a syslog file by using
SyslogScan/DeliveryIterator.

Variables
---------

     my $delivery = $iter -> next();

     #-----------------------------------------
     #  Sender, ReceiverList, Size, and Date are the most useful
     #-----------------------------------------

     # e-mail address of sender, may be 'undef' if the sender
     # could not be determined from the syslog
     my $sender = $$delivery{Sender};

     # reference to array of e-mail addresses of recipients
     my $paReceiverList = $$delivery{ReceiverList};
     my @aReceiverList = @$paReceiverList;
     print "The recipient(s) of the message was (were) ",
         join(' ',@aReceiverList), "\n";

     # size of message, may be 'undef' if the size could not be
     # determined from the syslog
     my $sizeInBytes = $$delivery{Size};

     # date the message was succesfully delivered or forwarded
     my $date = $$delivery{Date};

     #-----------------------------------------
     #    Id and Instance are more advanced features
     #-----------------------------------------

     # 'id' in syslog, useful for cross-referencing
     my $id = $$delivery{Id};

     # The first delivery of any message has Instance of 1; the next
     # deliveries will have Instance > 1, specifically a number equal to
     # the number of people who the message has previously been delivered
     # to, plus 1.  This is useful for detecing mass-mailings.

     # Suppose I send a message to 5 people, but only three copies are
     # delivered right away, the other two are deferred.  The first
     # Delivery has instance 1; the next delivery of the same message
     # will have instance 4.
     my $instance = $$delivery{Instance};
     my @aReceiverList = @{$$delivery{ReceiverList}};
     print "This message has so far been delivered to ",
         $instance + $@aReceiverList - 1, "people so far\n";

METHODS
=======

     # Manually create a new Delivery object.
     my $delivery = new SyslogScan::Delivery (Date => time(),
     					 Size => 100,
     					 From => 'foo@bar.com',
     					 ReceiverList =>
     					   [him@baz.edu, her@baz.edu],
     					 Instance => 1,
     					 Id => 'manual' . $id++);

     # print out contents, either in summary or in verbose mode
     print $delivery -> summary();
     print $delivery -> dump();

     # save/restore delivery to/from file
     open(OUT,">save.txt");
     $delivery -> persist(\*OUT);
     close(OUT);
     undef($delivery);

     open(IN,"save.txt");
     $delivery = SyslogScan::Delivery -> restore(\*IN);
     # $delivery is restored to its original state

SUPPORT
=======

   E-mail bugs to rolf@usa.healthnet.org.

AUTHOR and COPYRIGHT
====================

   This code is Copyright (C) SatelLife, Inc. 1996.  All rights reserved.
This code is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

   IN NO EVENT SHALL THE AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT,
INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OF THIS SOFTWARE AND ITS DOCUMENTATION (INCLUDING, BUT NOT LIMITED TO,
LOST PROFITS) EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

SEE ALSO
========

   See SyslogScan/DeliveryIterator,
SyslogScan/Summary,

scans a syslog file for "deliveries", successful transfers of mail to mailboxes or to other machines.
*****************************************************************************************************

NAME
====

   SyslogScan::DeliveryIterator - scans a syslog file for "deliveries",
successful transfers of mail to mailboxes or to other machines.

SYNOPSIS
========

     use SyslogScan::Delivery;
     use SyslogScan::DeliveryIterator;

     my $iter = new SyslogScan::DeliveryIterator(syslogList =>
     						["/var/log/syslog"]);

     my $delivery;
     while ($delivery = $iter -> next())
     {
         print $delivery -> summary();
     }

DESCRIPTION
===========

   A DeliveryIterator goes through your sendmail logging file (which may
be /var/log/syslog, /var/adm/messages, or something completely different)
looking for successful deliveries of mail to local user-accounts or
successful transfers of mail to remote machines.

   Here is an excerpt from a sample syslog:

   Jun 13 01:50:16 satellife sendmail[29556]: DAA29556:
from=<shookway@fs1.ho.man.ac.uk>, size=954, class=0, pri=30954, nrcpts=1,
msgid=<5B013544E0D@fs1.ho.man.ac.uk>, proto=ESMTP,
relay=curlew.cs.man.ac.uk [130.88.13.7]

   Jun 13 01:50:17 satellife sendmail[29558]: DAA29556:
to=<shoko@time.healthnet.org>, delay=00:00:05, mailer=fidogate,
stat=Deferred (Remote host is busy)

   ...

   Jun 13 14:55:50 satellife sendmail[29558]: DAA29556:
to=<shoko@time.healthnet.org>, delay=13:00:05, mailer=fidogate, stat=Sent

   The delivery is not registered until 14:55:50.  In order to figure out
the size and sender, the iterator needs to have gone over the 'from' entry
associated with message DAA29566, otherwise it will return a delivery with
'Sender' and 'Size' set to an undefined value (unless you specified
defaults when constructing your DeliveryIterator.)

METHOD 'NEW'
------------

   'new' creates a new iterator.

     my $iter =
         new SyslogScan::DeliveryIterator(startDate => "06.01.96 18:00:00",
     					 endDate => "06.02.96 06:00:00",
     					 syslogList =>
     					 [/var/log/syslog.090696,
     					  /var/log/syslog.090796],
     					 unknownSender => 'antiquity',
     					 unknownSize => 0,
     					 defaultYear => 1996);

   All of the above parameters are optional.

   *startDate* and *endDate* define a span of time; we ignore deliveries
that fall before *startDate* or after *endDate*.  This allows you to
generate statistical reports about mail delivered over a given span of
time.

   *syslogList* is a list of files to search through for deliveries.  The
alternative to specifying syslogList is to supply a file-handle to a
syslog file on each call to the next() method.

   *unknownSender* and *unknownSize* are what to specify as the sender and
the size if we cannot determine from the logs who sent the message and how
large the message is.

   *defaultYear* is the year in which the deliveries are assumed to have
taken place (this is not specified in the syslog file.)  Default is to
guess the year that makes the delivery take place close to now.  (For
example, if 'now' is February 3rd 1996, then by default a delivery made on
December 14th is assumed to be in 1995, and a delivery made on February
4th is assumed to be in 1996.

   *defaultYear* is deprecated, set the default year instead with
*SyslogScan::ParseDate::setDefaultYear*.

METHOD 'NEXT'
-------------

   Once an iterator is defined, the next() method will search for the next
delivery, skipping any deliveries which don't match the time constraints
of *startDate* and *endDate*.  There are two ways to call next():

     # poll syslogList members
     $delivery = $iter -> next;

     # poll filehandle
     open(LOG,"/var/log/syslog");
     $delivery = $iter -> next(\*LOG);

OTHER OPERATIONS
----------------

   The 'appendSyslog' method can add a syslog filename to the list of
syslog filenames which were specified at construction time as 'syslogList'.

   Setting the global variable *$::gbQuiet* to 1 will suppress some of the
error messages to STDERR.

BUGS
====

   If two messages have the same message ID through a bad coincidence, a
message is produced with sender of 'duplicate' and size of '0' rather than
using the unknownSender and unknownSize parameters.

   Sender and receiver address are downcased automatically.  It would
probably be better if this module downcased only the host-name part of the
address and not the user-name.

   Some mailings have a 'ctladdr' field; DeliveryIterator should probably
try to parse this as a backup clue for figuring out the sender.

AUTHOR and COPYRIGHT
====================

   The author (Rolf Harold Nelson) can currently be e-mailed as
rolf@usa.healthnet.org.

   This code is Copyright (C) SatelLife, Inc. 1996.  All rights reserved.
This code is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

   In no event shall SatelLife be liable to any party for direct,
indirect, special, incidental, or consequential damages arising out of the
use of this software and its documentation (including, but not limited to,
lost profits) even if the authors have been advised of the possibility of
such damage.

SEE ALSO
========

   See SyslogScan/Delivery,
SyslogScan/Summary,

Enhances basic SyslogEntry parsing by understanding sendmail to/from message syntax.
************************************************************************************

NAME
====

   SyslogScan::SendmailLine - Enhances basic SyslogEntry parsing by
understanding sendmail to/from message syntax.

DESCRIPTION
===========

   Suppose I run a 'new SyslogEntry' command and read in the following
line:

   Jun 13 01:32:26 satellife sendmail[23498]: WAA18677:
to=bar@foo.org,baz@foo.org, delay=03:50:20, mailer=smtp,
relay=relay.ulthar.com [128.206.5.3], stat=Sent (May, have (embedded,
commas))

   If I have not loaded in SendmailLine, then 'new SyslogEntry' will return
an 'UnsupportedEntry' object looking like this:

     month => Jun,
     day => 13,
     time => 01:32:26,
     machine => satellife,
     executable => sendmail,
     tag => 23498,
     content => WAA18677: to=bar@foo.org,baz@foo.org, delay=03:50:20, ...

   On the other hand, if I have a 'use SyslogScan::SendmailLine' command
before my call to 'new SyslogEntry', then I will a 'SendmailLine' object
with all of the above parameters, plus the following additional parameters:

     messageID => WAA18677
     toList => ( bar@foo.org, baz@foo.org )
     attrHash => ( to => "bar@foo.org,baz@foo.org",
     	     delay => "03:50:20",
     	     mailer => "smtp",
     	     relay => "relay.ulthar.com [128.206.5.3]",
     	     stat => "Sent (May, have (embedded, commas))"
     	     )

   Also well-supported is the 'From' line:

   Jun 13 01:34:54 satellife sendmail[26035]: BAA26035: from=<bar!baz!foo>,
size=7000, class=0, pri=37000, nrcpts=1,
msgid=<199606130634.BAA26035@satellife.healthnet.org>, proto=SMTP,
relay=uth.bar.com [155.247.14.2]

   will produce a SendmailLine object with the additional attributes of

     messageID => BAA26035
     attrHash => ( from => "<bar!baz!foo>",
     	     size => "7000",
     	     class => "0",
     	     pri => "37000"
     	     nrcpts => "1",
     	     msgid => "<199606130634.BAA26035@satellife.healthnet.org>",
     	     proto => "SMTP",
     	     relay => "uth.bar.com [155.247.14.2]"
     	     )

   Other types of lines are legal, but are not currently very thorougly
parsed, and therefore return somewhat minimal SendmailLine objects.

   Jun 13 13:05:35 satellife sendmail[19620]: NAA19606: NAA19620: return
to sender: unknown mailer error 2

   will return a SendmailLine object with the usual SyslogEntry attributes,
plus the single additional attribute of

   messageID => NAA19606

   while lines like the following produce SendmailLine objects with no
additional SendmailLine-specific attributes:

   Jun 13 03:00:05 satellife sendmail[26611]: alias database
/var/yp/nis.healthnet.org/mail.aliases rebuilt by root

   Note this is a subclass for SyslogScan::SyslogEntry which handles
certain types of logfile lines.  See the documentation for SyslogEntry for
further details of how SyslogEntry subclassing works.

   Also, see the SyslogScan::SendmailLineFrom and
SyslogScan::SendmailLineTo modules for examples of returned SendmailLine
objects.

AUTHOR and COPYRIGHT
====================

   The author (Rolf Harold Nelson) can currently be e-mailed as
rolf@usa.healthnet.org.

   This code is Copyright (C) SatelLife, Inc. 1996.  All rights reserved.
This code is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

   In no event shall SatelLife be liable to any party for direct,
indirect, special, incidental, or consequential damages arising out of the
use of this software and its documentation (including, but not limited to,
lost profits) even if the authors have been advised of the possibility of
such damage.

SEE ALSO
========

   See SyslogScan/SyslogEntry,
SyslogScan/SendmailLineFrom,
SyslogScan/SendmailLineTo,

encapsulates a 'From:' line in a syslog file
********************************************

NAME
====

   SyslogScan::SendmailLineFrom - encapsulates a 'From:' line in a syslog
file

DESCRIPTION
===========

   Here is a sample SendmailLineFrom object.

   If 'new SyslogScan::SendmailLineEntry' reads in a line like

   Jun 13 02:34:54 satellife sendmail[26035]: BAA26035:
from=<HELP-NET@BAR.TEMPLE.EDU>, size=7000, class=0, pri=37000, nrcpts=1,
msgid=<199606130634.BAA26035@satellife.healthnet.org>, proto=SMTP,
relay=vm.temple.edu [155.247.14.2]

   then it will return a SyslogScan::SendmailLineFrom object like this:

     # generic SyslogScan::SyslogEntry stuff
     day => 13,
     executable => 'sendmail',
     machine => 'satellife',
     month => 'Jun',
     tag => 26035,
     time => '02:34:54',
     content => 'BAA26035: from=<HELP-NET@BAR.TEMPLE.EDU>, size=7000, class=0, pri=37000, nrcpts=1, msgid=<199606130634.BAA26035@satellife.healthnet.org>, proto=SMTP, relay=vm.temple.edu [155.247.14.2]',

     # sendMailLineFrom-specific stuff
     messageID => 'BAA26035',
     attrHash => {
     	 'class' => 0,
              'from' => 'help-net@bar.temple.edu',
              'msgid' => '<199606130634.BAA26035@satellife.healthnet.org>',
              'nrcpts' => 1,
              'pri' => 37000,
              'proto' => 'SMTP',
              'relay' => 'vm.temple.edu [155.247.14.2]',
              'size' => 7000
     	 }

AUTHOR and COPYRIGHT
====================

   The author (Rolf Harold Nelson) can currently be e-mailed as
rolf@usa.healthnet.org.

   This code is Copyright (C) SatelLife, Inc. 1996.  All rights reserved.
This code is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

   In no event shall SatelLife be liable to any party for direct,
indirect, special, incidental, or consequential damages arising out of the
use of this software and its documentation (including, but not limited to,
lost profits) even if the authors have been advised of the possibility of
such damage.

SEE ALSO
========

   See SyslogScan/SendmailLine,

encapsulates a 'To:' line in a syslog file
******************************************

NAME
====

   SyslogScan::SendmailLineTo - encapsulates a 'To:' line in a syslog file

DESCRIPTION
===========

   Here is a sample SendmailLineTo object.

   If 'new SyslogScan::SendmailLineEntry' reads in a line like

   Jun 13 01:50:48 satellife sendmail[23498]: WAA18677:
to=mbe527@time.nums.nwu.edu,jsm341@anima.nums.nwu.edu, delay=03:52:42,
mailer=smtp, relay=anima.nums.nwu.edu. [165.124.50.10], stat=Sent
(AA097917369 Message accepted for delivery)

   then it will return a SyslogScan::SendmailLineTo object like this:

     # generic SyslogScan::SyslogEntry stuff
     day => 13,
     executable => 'sendmail',
     machine => 'satellife',
     messageID => 'WAA18677',
     month => 'Jun',
     tag => 23498,
     content => 'WAA18677: to=mbe527@time.nums.nwu.edu,jsm341@anima.nums.nwu.edu, delay=03:52:42, mailer=smtp, relay=anima.nums.nwu.edu. [165.124.50.10], stat=Sent (AA097917369 Message accepted for delivery)',

     # sendMailLineTo-specific stuff
     messageID => 'WAA18677'
     toList => (mbe527@time.nums.nwu.edu, jsm341@anima.nums.nwu.edu)
     attrHash => (
              'delay' => '03:52:42',
              'mailer' => 'smtp',
              'relay' => 'anima.nums.nwu.edu. [165.124.50.10]',
              'stat' => 'Sent (AA097917369 Message accepted for delivery)',
              'to' => 'mbe527@time.nums.nwu.edu,jsm341@anima.nums.nwu.edu'
     	 )

AUTHOR and COPYRIGHT
====================

   The author (Rolf Harold Nelson) can currently be e-mailed as
rolf@usa.healthnet.org.

   This code is Copyright (C) SatelLife, Inc. 1996.  All rights reserved.
This code is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

   In no event shall SatelLife be liable to any party for direct,
indirect, special, incidental, or consequential damages arising out of the
use of this software and its documentation (including, but not limited to,
lost profits) even if the authors have been advised of the possibility of
such damage.

SEE ALSO
========

   See SyslogScan/SendmailLineTo,

utilities for sendmail packages.
********************************

NAME
====

   SendmailUtil.pm - utilities for sendmail packages.

SYNOPSIS
========

     use SyslogScan::SendmailUtil;

     open(FH,"/var/log/syslog");
     my $transfer;
     while ($transfer = SyslogScan::SendmailUtil::getNextMailTranfer(\*FH))
     {
        # process the tranfer
     }

DESCRIPTION
===========

   getNextMailTransfer queries a filehandle pointing to a syslog for the
next line which is a sendmail 'To:', 'From:', and 'Clone:' lines, and
returns a SyslogScan::SendmailLineFrom, SyslogScan::SendmailLineTo, or
SyslogScan::SendmailLineClone object.

canonAddress() routine
======================

   The canonAddress() routine modifies the address of the Sendmail
routines to be all-lowercase, remove enclosing brackets, and append
'@localhost' to local addresses.  Modifying this routine will change how
SyslogScan canonicalizes.

AUTHOR and COPYRIGHT
====================

   The author (Rolf Harold Nelson) can currently be e-mailed as
rolf@usa.healthnet.org.

   This code is Copyright (C) SatelLife, Inc. 1996.  All rights reserved.
This code is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

   In no event shall SatelLife be liable to any party for direct,
indirect, special, incidental, or consequential damages arising out of the
use of this software and its documentation (including, but not limited to,
lost profits) even if the authors have been advised of the possibility of
such damage.

SEE ALSO
========

   See SyslogScan/SendmailLineFrom,
SyslogScan/SendmailLineTo,
SyslogScan/SyslogEntry,

encapsulates a tally of how many bytes people have sent and received through sendmail
*************************************************************************************

NAME
====

   SyslogScan::Summary - encapsulates a tally of how many bytes people
have sent and received through sendmail

SYNOPSIS
========

     Use SyslogScan::Summary;
     Use SyslogScan::DeliveryIterator;

     my $iter = new SyslogScan::DeliveryIterator(syslogList =>
     						[/var/log/syslog]);
     my $summary;
     if (defined $DOING_IT_THE_HARD_WAY_FOR_NO_PARTICULAR_REASON)
     {
     	# feed a series of SyslogScan::Delivery objects
     	$summary = new SyslogScan::Summary();
     	my $delivery;
     	while ($delivery = $iter -> next())
     	{
     	    $summary -> registerDelivery($delivery);

     # You would instead use:
     # $summary -> registerDelivery($delivery,'foo\.com\.$')
     # if you only cared to get statistics relating to how
     # much mail users at foo.com sent or received.
     	}
         }
         else
         {
     	# slurps up all deliveries in the iterator,
     	# producing the same effect as the block above
     	$summary = new SyslogScan::Summary($iter);
         }

     print $summary -> dump();

     use SyslogScan::Usage;
     my $usage = $$summary{'john_doe@foo.com'};
     if (defined $usage)
     {
     	print "Here is the usage of John Doe at foo.com:\n";
     	print $usage -> dump();
     }
     else
     {
         print "John Doe has neither sent nor received messages lately.\n";
     }

DESCRIPTION
===========

   A SyslogScan::Summary object will 'register' a series of
SyslogScan::Delivery objects.  All registered deliveries are grouped by
sender and receiver e-mail addresses, and then added up.  Three sums are
kept: Total Bytes Recieved, Total Bytes Sent, and Total Bytes Broadcast.

Methods
-------

static new() method
     new takes as arguments a (possibly null) list of
     SyslogScan::DeliveryIterator objects, from which it extracts and
     registers all queued deliveries.

registerDelivery() method
     *registerDelivery* takes as its first argument a SyslogScan::Delivery
     object followed by up to two optional patterns.  If the first pattern
     is specified, only those e-mail addresses which match the pattern are
     tallied.  This enables you to create an accounting summary for only
     those users at your site.

     If the second pattern is also specified, then deliveries will only be
     registered to the person matched by the first pattern if the second
     pattern matches the address at 'the other end of the pipe'.

     Pattern-matches are case-insensitive.  Remember the '(?!regexp)'
     operation if you want only addresses which do _not_ match the pattern
     to get passed through the filter.  For example, if mail to or from
     'support' is exempt from billing charges, note that the pattern-match

     /^(?!support)/

     does _not_ match 'support@foo.com' but _does_ match
     'random_guy@foo.com'.

registerAllInIterators() method
     Takes as parameters two patterns and a list of iterators, then feeds
     deliveries in the iterators and the patterns to registerDelivery().

     For example:

          $sum -> registerAllInIterators('foo\.com$','^(?!.*bar\.com$)',@iterList)

     will bill users at foo.com for all mail extracted from @iterList which
     was sent from foo.com to somewhere besides bar.com, or sent to foo.com
     from somewhere besides bar.com.

dump() method
     dump returns a string containing address lines alternating with usage
     reports.  Usage reports are in the form:

          B#,Bb        S#,Sb        R#,Rb

     Where:

     B# is the number of messages broadcast B# is the total number of
     bytes broadcast

     S# is the number of messages sent S# is the total number of bytes sent

     R# is the number of messages received R# is the total number of bytes
     received

persist() method
     *persist* takes as its single argument an output file-handle, and
     then persists the state of the summary to the file.

static restore() method
     restore takes as its single argument an input file-handle which
     stores the results of a previous persist() command, and then returns a
     copy of the object in the state in which it was originally persisted.

addSummary() method
     *addSummary* takes as its single argument a second
     SyslogScan::Summary object, and then adds this second summary to the
     $self object.

Example of use
--------------

   Suppose I have a function getTodaySummary() which gets a Summary of the
last 24 hours of sendmail logging.

     my $summary = getTodaySummary();
     open(SUMMARY1,">summary1.sav");
     $summary -> persist(\*SUMMARY1);
     close(SUMMARY1);
     exit 0;

     # wait 24 hours

     my $summary = getTodaySummary();
     open(SUMMARY2,">summary2.sav");
     $summary -> persist(\*SUMMARY2);
     close(SUMMARY2);
     exit 0;

     # some time later, you decide you want a summary of the total
     # for both days.  So, you write this program:

     open(INSUM1,"summary1.sav");
     my $sum = SyslogScan::Summary -> restore(\*INSUM1);

     open(INSUM2,"summary2.sav");
     my $sum2 = SyslogScan::Summary -> restore(\*INSUM2);

     $sum -> addSummary($sum2);
     print "Here is the grand total for both days:\n\n";
     print $sum -> dump();

Internals
---------

   A SyslogScan::Summary object is a hash of SyslogScan::Usage objects,
where the key is the e-mail address of the user in question.
SyslogScan::Usage has its own man page which describes how to extract
information without having to use the dump() method.

AUTHOR and COPYRIGHT
====================

   The author (Rolf Harold Nelson) can currently be e-mailed as
rolf@usa.healthnet.org.

   This code is Copyright (C) SatelLife, Inc. 1996.  All rights reserved.
This code is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

   In no event shall SatelLife be liable to any party for direct,
indirect, special, incidental, or consequential damages arising out of the
use of this software and its documentation (including, but not limited to,
lost profits) even if the authors have been advised of the possibility of
such damage.

SEE ALSO
========

   See SyslogScan/Usage,
SyslogScan/DeliveryIterator,
SyslogScan/Delivery, SyslogScan/ByGroup,

parses generic lines in syslog files.
*************************************

NAME
====

   SyslogScan::SyslogEntry - parses generic lines in syslog files.

SYNOPSIS
========

     use SyslogScan::SyslogEntry;

     open(FH,"/var/log/syslog");

     my $entry;

     # reads from filehandle $fh and returns an object
     # of a subclass of SyslogEntry.
     while ($entry = new SyslogScan::SyslogEntry (\*FH))
     {
     	# process $entry
     }

DESCRIPTION
===========

   All Syslog object share these data structures: month, day, time,
machine, executable, tag (optional), content.

   For example, if a syslog line looks like:

   Jun 13 02:32:27 satellife in.identd[25994]: connect from
mail.missouri.edu

   then the line returned by 'new SyslogEntry' will return a
SyslogEntry-derived object with at least this set of parameters:

     month => Jun,
     day => 13,
     time => 02:32:27,
     machine => satellife,
     executable => in.identd,
     tag => 25994,
     content => connect from mail.missouri.edu,
     unix_time => 834633147,
     raw => Jun 13 02:32:27 satellife in.identd[25994]: connect from mail.missouri.edu

   Since the executable is 'in.identd', SyslogEntry.pm will look for a
class called "SyslogScan::In_identdLine" derived from SyslogEntry, and
attempt to call that class's parseContent method.  If no such
In_identdLine class is in use, then the returned object is of the default
"SyslogScan::UnsupportedEntry" class.

   If the In_identdLine class throws a die() exception, SyslogEntry.pm
will catch the die() and return a "SyslogScan::BotchedEntry" object
containing the exception in "$errorString" and the failed handler in
"brokenHandler".

   "new SyslogEntry" returns the undefined value if at EOF.

BUGS
====

   In retrospect, this model of passing control to subclasses based on the
name of the controlling program doesn't work exceptionally elegantly in
perl.  I would probably do it more conventionally if I had it to do over
again.

AUTHOR and COPYRIGHT
====================

   The author (Rolf Harold Nelson) can currently be e-mailed as
rolf@usa.healthnet.org.

   Thanks to Allen S. Rout for his code contributions.

   This code is Copyright (C) SatelLife, Inc. 1996.  All rights reserved.
This code is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

   In no event shall SatelLife be liable to any party for direct,
indirect, special, incidental, or consequential damages arising out of the
use of this software and its documentation (including, but not limited to,
lost profits) even if the authors have been advised of the possibility of
such damage.

SEE ALSO
========

   See SyslogScan/SendmailLine,

encapsulates the total volumes of mail broadcast, sent, and received through sendmail by a single user or group.
****************************************************************************************************************

NAME
====

   SyslogScan::Usage - encapsulates the total volumes of mail broadcast,
sent, and received through sendmail by a single user or group.

   SyslogScan::Volume - encapsulates a number of messages along with a
total number of bytes

SYNOPSIS
========

   # $summary is a SyslogScan::Summary object

   use SyslogScan::Usage; my $usage = $$summary{'john_doe@foo.com'};
$usage -> dump();

   use SyslogScan::Volume; my $broadcastVolume = $usage ->
getBroadcastVolume(); my $sendVolume = $usage -> getSendVolume(); my
$receiveVolume = $usage -> getReceiveVolume();

   print "John Doe sent $$sendVolume[0] messages with $$sendVolume[1]
bytes\n";

DESCRIPTION
===========

Broadcast, Send, and Receive
----------------------------

   Volume of messages received has the obvious meaning.  Volume of
messages sent and volume of messages broadcast require more explanation.

   If I send out a message which has three recipients, then for the
purposes of the SyslogScan modules, I am *broadcasting* the message once,
but I am *sending* it three times.

Usage methods
-------------

new() method
     Creates a new, empty Usage object.

addUsage() method and deepCopy() method
          # $usage1 is 4 messages of 100 bytes Received
          # $usage2 is 1 message of 35 bytes Received

          my $usageTotal = $usage1 -> deepCopy();
          # $usageTotal is 4 messages of 100 bytes Received

          $usageTotal -> addUsage($usage2);
          # $usageTotal is 5 messages of 135 bytes Received

     Note that because we used deepCopy, *$usage1* is still 4 messages of
     100 bytes.

registerBroadcast, registerSend, registerReceive methods
          my $usage = new SyslogScan::Usage();
          $usage -> registerSend(512);
          $usage -> registerSend(34);
          $usage -> registerBroadcast(34);
          # $usage is now 2 messages, 546 bytes Sent,
          # and 1 message, 34 bytes Broadcast

getBroadcastVolume, getSendVolume, getReceiveVolume methods
     Returns deep copy of the applicable SyslogScan::Volume objects.

static deepCopy method
     Returns deep copy of the whole SyslogScan::Usage object.

static dump
     Returns a string containing (Message,Bytes) pairs for Broadcast, Send,
     and Receive volumes.

Volume methods
--------------

new() method
     Creates a new Volume object of 0 messages, 0 bytes.

deepCopy() method
     Creates a new Volume object with the same number of messages and bytes
     as the current Volume object.

addVolume(), addSize() methods
     addVolume() adds the volume of a second Volume object onto the volume
     of the current Volume object.

     addSize() adds on one message of the given size.

          use SyslogScan::Volume;

          my $volume1 = new SyslogScan::Volume();
          $volume1 -> addSize(512);

          my $volume2 = $volume1 -> deepCopy();
          # $volume2 is 1 message, 512 bytes

          $volume2 -> addSize(31);
          # $volume2 is 2 messages, 543 bytes

          $volume2 -> addVolume($volume1);
          # $volume2 is 3 messages, 1055 bytes

          $volume2 -> addVolume($volume2);
          # $volume2 is 6 messages, 2110 bytes

getMessageCount, getByteCount
     Gets the number of messages and the total number of bytes,
     respectively.

dump()
     Returns the string "getMessageCount(),getByteCount()"

Volume internals
----------------

   A Volume is simply a two-element array of ($messages, $bytes).

   $$volume[0] is the number of messages $$volume[1] is the number of bytes

AUTHOR and COPYRIGHT
====================

   The author (Rolf Harold Nelson) can currently be e-mailed as
rolf@usa.healthnet.org.

   This code is Copyright (C) SatelLife, Inc. 1996.  All rights reserved.
This code is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

   In no event shall SatelLife be liable to any party for direct,
indirect, special, incidental, or consequential damages arising out of the
use of this software and its documentation (including, but not limited to,
lost profits) even if the authors have been advised of the possibility of
such damage.

SEE ALSO
========

   See SyslogScan/Summary,

return full path of syslog file where mail messages are logged
**************************************************************

NAME
====

   SyslogScan::WhereIs::guess - return full path of syslog file where mail
messages are logged

SYNOPSIS
========

     my $syslogPath =
         new SyslogScan::Whereis::guess("/etc/syslog.conf");

DESCRIPTION
===========

   Scans a syslog configuration file to try to figure out where
"mail.info" messages are sent.  Default configuration file is
"/etc/syslog.conf".

   Returns undef if the syslog file cannot be determined.

BUGS
====

   It might have been more elegant to return an array of syslog files;
this would, as a bonus, permit multiple syslogs to be returned if mail
messages go to more than one place.

AUTHOR and COPYRIGHT
====================

   The author (Rolf Harold Nelson) can currently be e-mailed as
rolf@usa.healthnet.org.

   This code is Copyright (C) SatelLife, Inc. 1996.  All rights reserved.
This code is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

   In no event shall SatelLife be liable to any party for direct,
indirect, special, incidental, or consequential damages arising out of the
use of this software and its documentation (including, but not limited to,
lost profits) even if the authors have been advised of the possibility of
such damage.

SEE ALSO
========

   See SyslogScan/DeliveryIterator,

TFTP Client class
*****************

NAME
====

   TFTP - TFTP Client class

SYNOPSIS
========

     use TFTP;

     $tftp = new TFTP("some.host.name");
     $tftp->get("that.file");
     $tftp->octet;
     $tftp->put("this.file");
     $tftp->quit;

DESCRIPTION
===========

   `TFTP' is a class implementing a simple TFTP client in Perl as
described in RFC783.

OVERVIEW
========

   TFTP stands for Trivial File Transfer Protocol.

CONSTRUCTOR
===========

new (HOST [,OPTIONS])
     This is the constructor for a new TFTP object. `HOST' is the name of
     the remote host to which a TFTP connection is required.

     OPTIONS are passed in a hash like fashion, using key and value pairs.
     Possible options are:

     Port - The port number to connect to on the remote machine for the
     TFTP connection

     Mode - Set the transfer mode [NETASCII, OCTET] (defaults to NETASCII)

     Timeout - Set the timeout value before retry (defaults to 2 sec)

     *MaxTimeout* - Set the maximum timeout value before retry (defaults
     to 8 sec)

     *Retries* - Set the number of retries (defaults to 3 with arithmetic
     backoff)

METHODS
=======

mode (TYPE)
     This method will set the mode to be used with the remote TFTP server
     to specify the type of data transfer. The return value is the previous
     value.

netascii, ascii, octet, binary
     Synonyms for mode with the first argument set accordingly

get ( REMOTE_FILE [, LOCAL_FILE ] )
     Get `REMOTE_FILE' from the server and store locally. `LOCAL_FILE' may
     be a filename or a filehandle. If not specified the the file will be
     stored in the current directory with the same leafname as the remote
     file.

     Returns `LOCAL_FILE', or the generated local file name if `LOCAL_FILE'
     is not given.

put ( LOCAL_FILE [, REMOTE_FILE ] )
     Put a file on the remote server. `LOCAL_FILE' may be a name or a
     filehandle.  If `LOCAL_FILE' is a filehandle then `REMOTE_FILE' must
     be specified. If `REMOTE_FILE' is not specified then the file will be
     stored in the current directory with the same leafname as
     `LOCAL_FILE'.

     Returns `REMOTE_FILE', or the generated remote filename if
     `REMOTE_FILE' is not given.

quit
     Close the current socket and release any resources. A more complete
     way to release resources is to call 'undef $tftp;' on the session
     object.

REPORTING BUGS
==============

   When reporting bugs/problems please include as much information as
possible.  It may be difficult for me to reproduce the problem as almost
every setup is different.

   A small script which yields the problem will probably be of help. It
would also be useful if this script was run with the extra options `debug
=' 1> passed to the constructor, and the output sent with the bug report.
If you cannot include a small script then please include a Debug trace
from a run of your program which does yield the problem.

AUTHOR
======

   G. S. Marzot <gmarzot@baynetworks.com>

SEE ALSO
========

   tftp(1), tftpd(8), RFC 783
http://info.internet.isi.edu:80/in-notes/rfc/files/rfc783.txt

   Copyright (c) 1998 G. S. Marzot. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Maps relational tables into hashes
**********************************

NAME
====

   TableMap - Maps relational tables into hashes

SYNOPSIS
========

     use DBI;
     $dbh=DBI->connect(...);

     use TableMap;

     $database=new TableMap::DB(
       dbh         =>   $dbh,
         # DBI Database handler
       seq_mode =>   "ora",
         # Sequence handling mode
         # "ora": "select seqence.currval from dual";
         # "pg" : "select sequence.last_value";
         # db systems, which doesn't support sequences currently
         # doesn't supported (insert won't work)
       prepare_cached => 0,
         # Can use "prepare_cached" method of the DBI?
         # This causes problems for me, and that's why the
         # default is now 0. This param is not mandatory.
     );

     # You can use connect hash to specify connect parameters directly.
     # In this case you doesn't need to specify "dbh" parameter:
     # $database=new TableMap::DB(
     #   connect=> [$data_source, $username, $auth, \%attr],
     #   seq_currval => ...
     # );

     $company=$database->new_table (
       table => "company",    # Table name, mandatory
       key   => "id",         # Primary Key for the table
       seq   => "seq_company",# Sequence name for key field generation.
                              # Mandatory only if "insert" is in use
     );

     # $database->new_table(...)
     #   is the same as
     # new TableMap ( db => $database, ... )

     $user  =$database->new_table (
       table => "users",
       key   => "id",
       seq   => "seq_users",
       ref   => { company_id => [ $company, "user" ] },
         # This can be used for connecting tables.
         # This is similar to the SQL phrase:
         #
         # .. company_id  int references company (id),
         #
         # only the key field can be referenced.
     );

     %company_14_users= % {$company->{14}->user };

     # All user IDs
     keys %$user;

     # Sets Company #14 Data:
     $company_14 = $company->{14};
     $company_14->{tax_num} = "123456";
     $company_14->{phone1} = "+42456245546";
     $company_14->write;

     # Wrong example:
     # $company->{14}->{tax_num} = "123456"
     # $company->{14}->write;
     # This doesn't work, because it always create a new Row object,
     #   and the cache is stored per object.

     # Select a sub-relation
     $table=$user->select("company_id = ?",$id);

     # Select with constraint
     $user->constraint( company_id => $id );

     # New record
     $id=$company->new(
       { name=>"abc",
         phone1=>"30/123567",
         mobile=>"20/1234" } );
     if ($id) { print "Id: $id\n"; } else { print "Insert failed: "; };

     # Delete record
     delete $company->{13};
     %{ $company->{13} }=();

DESCRIPTION
===========

   This class is designed for mapping a table into a perl hash, which has
keys (these are the primary keys of the table), and the values are the
rows, represented by a hash.

Basic Usage
-----------

   You can create TableMap objects for tables. You must specify a
parameter hash to the constructor, which has the following keys:

db
     This is a reference to a TableMap::DB module. Normally you create a
     new TableMap object by the method of the "new_table" of a
     TableMap::DB instance, then you may not specify this.

table
     Specifies the table name

key
     Specifies the primary key. This must be specified, so if you don't
     have primary keys in your table, you cannot use the TableMap (for the
     whole table. You can use it for a subset of rows specified by the
     "constraint" param).

seq
     If you want to use "insert" with self-incremental keys, you must
     specify this. Database servers, which doesn't implement sequences
     (mySQL) currently not supported.

ref
     Creating a 1:N reference. The value is a hash reference, where the
     keys are database fields, and the values contains the reference
     information in an array reference:

     ref => {   field1 => [ $table1, "function1" ],   field2 => [ $table2,
     "function2" ], };

     In the example above you can use the reference field (company_id)
     from the "user" table to query the company in which the user work:
     $company_name = $user->{17}->company_id->{name}.

     function1 is the name of the function, which can be used for the
     back-reference, eg. can be used to determine the user-ids in one
     company: @user_ids= keys %{ $company->{45}->users }. "users" is the
     function name in this example.

where
     Specifies a "where" condition for selecting id-s, so you can select a
     subset of keys with this. Also available with the "search" function:

     @user_ids= keys %{ $table->search("age > 25") };

     or

     $table=new TableMap (table => "table", where => "age > 25");
     @user_ids=keys %$table;

constraint
     This is similar to "select", but it can be used only for equality
     test. The main advantage is that it can be used for deletion and
     insertion. If you insert something into a table, which has constraint
     parameter, all the values in the constraint hash is set in the new
     record. This constraint is used internally, when somebody creates a
     back reference by a back-reference function.

References
----------

   There is two kind of reference in this module. All two are set up by
"ref" parameter in the table. If you use a "ref" parameter, then the
"back_ref" is automatically created in the other table (if not already
exists).

ref
     $user->company_id gives a TableMap::Row record, which is a ROW in the
     company table. Each hash keys are field names.

back_ref
     $company->users gives a TableMap object, which is a COLLECTION of
     rows (represented by a hash), which gives back the employees of the
     companies. (you can use "keys ..." expression for the ids).

Caching
-------

   All the sql queries are cached in this module. This must be rethink,
because sometimes it is not the best solution.  I want some extra
parameter for caching in the newer versions. Now all the query results are
cached for 10 seconds.

   The Cache object is $TableMap::cache, and it can be invalidated by the
$TableMap::cache->invalidate_cache call.

   The cache is hierarchical (it is stored in tree structure).

   For more information on the cache you can see the source code.

Performance
-----------

   This module is NOT the most efficient method for getting data from the
database. It is written to avoid endless sql-query-typing with minimal
performance loss.

   The module uses two kind of sql queries:

select key from table
     This is used for querying all the keys from a table. This can be
     affected by the "constraint" and the "where" parameter.

select * from table where id=1234
     This is used for querying all the fields of one row. This can be
     affected by the "constraint" parameter, but not thw "where".

   Sometimes querying the whole table is more effective, (when you have
enough memory), but currently it is only a planned parameter.

TODO
----

   * This module is now usable for one purpose. I have profiled it, and
     I've found that the "read_data" function is the most time-consuming.
     This must be handled by re-organizing the cache.

   * I want to add a parameter for setting for the caching mode. Sometimes
     no caching is allowed, but sometimes te full table must be cached for
     good performance.

   * Cahce reorganization is needed, because reaching a cached data is
     quite slow.

COPYRIGHT
=========

   Copyrigh (c) 2000 Balázs Szabó (dLux) All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

AUTHOR
======

   dLux <dlux@kapu.hu>

Dynamic web page system
***********************

NAME
====

   Taco - Dynamic web page system

SYNOPSIS
========

     # In a dynamic document
     <title>[[$user_id]]s web page</title>
     Here are your favorite foods:<br>
     [[&list(driver=foods for_user=[[$user_id]] display_template=food_template)]]

     # For serving Taco web pages, put in httpd.conf
     PerlModule Apache::Taco
     <Files ~ "\.taco$">
      SetHandler perl-script
      PerlHandler Apache::Taco
     </Files>

     # For parsing stand-alone files, type at Unix prompt
     parse_file.pl [-s service] [-q query_string] filename
     (not ready yet, sorry)

DESCRIPTION
===========

   Taco is a software tool which facilitates the creation of dynamic web
pages.  It's meant to run under the Apache web server, using the mod_perl
extension.

   A Taco page is just like a regular HTML page, with one important
addition: a Taco page can contain Taco tags.  When a user requests a Taco
page, the Taco software finds all the Taco tags on the page and replaces
them with the appropriate text.  This text can come from a database, from
a discussion group, or from the query string, among other places.

   In fact, Taco itself doesn't define the functions you can have in a web
page.  Rather, the functionality is encapsulated in modules, which can be
plugged into Taco.  You can write your own modules or use common ones that
are already written.  The most basic module functionality is in the
Taco::Generic.pm module, which is distributed with the main Taco
distribution.  All modules, including Taco::Generic, are sub-classes of
Taco::Module.

   For more documentation, please see the other modules in this
distribution. See Taco::Module for a description of the syntax of the tags
(how to use them in a web page), or instructions on how to write your own
Taco module.  See any Taco module's documentation for a description of the
specific tags it defines.

DOCUMENTATION
=============

   The documentation for Taco is spread out among several modules.  Here
is a summary of what each module does and what its documentation covers:

     Apache::Taco     This is the PerlHandler to use with mod_perl.  Here you'll
                      find information on how to configure a mod_perl-enabled
                      server to load Taco pages.

     Taco::Arg        This module implements the ArgTable and ArgLayer objects
                      which hold all the parameters in the query string, the POSTed
                      form contents, arguments passed to functions in [[tags]],
                      parameters set using the [[&set]] tag, and so on.

     Taco::Template   This module controls the parsing and output of Taco templates.
                      Templates are searched for [[tags]], and each tag is passed
                      to the Taco::Dispatcher module, which decides which Taco module
                      (e.g. Taco::Generic) will handle the tag.

     Taco::Module     This is a base class for Taco extension modules.  An extension
                      module (Taco::Generic is an example) can supply more Taco tags for
                      use in templates.

     Taco::ServiceRegistry
                      A Taco service is basically a set of configuration information.
                      The ServiceRegistry file contains definitional information
                      about the various services.  To add a service to Taco, add an
                      entry in the ServiceRegistry file.

     Taco::Dispatcher This module provides the glue between a Taco "service" and
                      the Taco modules it uses.  It also has routines that parse
                      the insides of Taco [[tags]], so the definitions of Taco syntaxes
                      are given here.

     Taco::Generic    This is a fairly generic Taco extension module.  It provides
                      several tags, such as [[&set]] (puts an entry in the global
                      ArgTable), [[&if]] (a conditional statement), [[&mark_me]]
                      (useful for checking checkboxes and radio buttons and selecting
                      choices in a <select> list), and so on.

AUTHOR
======

   Ken Williams (ken@forum.swarthmore.edu)

   Copyright (c) 1998 Swarthmore College. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1).

Taco argument management
************************

NAME
====

   Taco::Arg.pm - Taco argument management

SYNOPSIS
========

   This module has three packages in it:

     Taco::ArgTable        -A class implementing a table of arguments
     Taco::ArgLayer        -A class implementing one layer in an ArgTable
     Taco::ArgUtil         -Utility functions for managing arguments

     # In a Taco tag's implementation function:
     my $flavor = $G::params->val('flavor');
     my $shoe_size = $G::params->val('shoe_size', 'my_func'); # Look only in the
                                                              # layer called "my_func"

DESCRIPTION
===========

   The Taco::Arg module contains classes that implement a table of
arguments.  It's somewhat like a 2-dimensional hash.  Whenever you put a
[[&tag(arg=value)]] in a Taco template, Taco will parse the tag for you,
put the arguments into the ArgTable (the global ArgTable is $G::params),
and then run your function.  While your function is running, it has access
to the $G::params object, which lets it get or set parameters, insert new
ArgLayers, etc.

The ArgTable Class
==================

   * new Taco::ArgTable

     Returns a new empty ArgTable object.

   * $table->insert_layer

     Puts a new empty ArgLayer in the table.  The first argument is the
     layer after which you want the new layer to appear.  The second
     argument, if present, is the name of the new layer.  If the second
     argument is not present, a new name will be invented.

     Returns the name of the new ArgLayer.

   * $table->new_temp(layer_name, key, value, key, value, ...)

     Puts a new temporary layer in the ArgTable, right after the layer
     called layer_name.  This method returns an object of class
     Taco::ArgLayerName.  This is a special object - when it goes out of
     scope, the layer associated with it will be deleted from the ArgTable.
     Because the scoping of this object is so significant, calling
     $table->new_temp in a void context (not assigning the result to a
     value) will cause Taco to die.  So don't do that.  If you don't want
     the layer to expire automatically, then you should probably use
     $table->insert_layer instead.

   * $table->exists(key)

     Returns true if the given argument is the name of a key in the table.
     Takes an optional list of layers to look in.

   * $table->set_arg(layer, key, value, key, value, ...)

     Sets the given keys to the given values in the given layer.  Passes
     the real work to Taco::ArgLayer::set_arg.

   * $table->add_arg(layer, key, value, key, value, ...)

     Adds the given keys, with the given values, to the given layer.
     Passes the real work to Taco::ArgLayer::add_arg.

   * $table->layer_names

     Returns the current list of layer names, in order of highest priority
     to lowest.

   * $table->get_layer(layer_name)

     Returns the ArgLayer object called layer_name.

   * $table->set_layer(layer_name, layer)

     Replaces the layer called layer_name with the given layer.  The table
     must already have a layer called layer_name.

   * $table->delete_layer(layer_name)

     Deletes the layer called layer_name from the table.

   * $table->layer_exists(layer_name)

     Returns true if there is a layer called layer_name in the table.  See
     also exists to see whether a key exists in the table.

   * $table->layer_containing(key)

     Returns the name of the layer containing the given key, or undef if
     no layers contain the given key.

   * $table->keys

     Returns a list of all the keys in the table.  Can take an optional
     list of layer names, in which case all the keys in those layers are
     returned, in no particular order.

   * $table->show_me(verbose)

     Prints the names of the layers in an ArgTable to STDERR, in order
     from highest priority to lowest.  If the verbose argument is true,
     each layer's ->show_me method will also be called, so you'll see all
     the data in the ArgTable.

   * $table->to_hash(names_only)

     Returns the table's data in a list of key=>value pairs.  If
     names_only is true, the keys returned will just be the names of the
     keys in the table.  Otherwise the keys will be of the form
     "param-flavor.3*+", where 'param' is the 'place', '3' is the 'group',
     and '*+' is the type of the 'flavor' key.  If none of these fancy
     things have values, setting the names_only flag will have no effect.

     Not implemented yet.

   * $table->to_query_string(names_only)

     Similar to to_hash, but returns the data in the form of an URL query
     string.

     Not implemented yet.

   * $table->to_arg_string(names_only)

     Similar to to_hash, but returns the data in the form of a template
     function argument string.

     Not implemented yet.

   Simple Access methods

   The following convenience methods can be used to look up table data more
easily. They all share two characteristics:  they take a key as input,
with an optional list of layers to look for the data in.  And they can be
called in either the singular or plural form (i.e. $table->val(key) or
$table->vals(key) ).

   When they are called in the singular form, they return a single scalar
value corresponding to the highest priority key of the given name.  When
they are called in the plural form, they return a list of scalars
corresponding to the values in the highest layer containing a key of the
given name.

   All these routines return the undefined value if no layer contains the
given key.

   * $table->val(key)

     Looks up the key in the table and returns the value.  See also
     ArgLayer::val.

   * $table->group(key)

     Looks up the key in the table and returns the group.  See also
     ArgLayer::group.

   * $table->type(key)

     Looks up the key in the table and returns the type.  See also
     ArgLayer::type.

   * $table->place(key)

     Looks up the key in the table and returns the place.  See also
     ArgLayer::place.

   * $table->get_arg(key)

     Looks up the key in the table and returns a hash structure containing
     the group, type, place, and value.  See also ArgLayer::get_arg.

The ArgLayer Class
==================

   An ArgLayer is a layer in an ArgTable.  Here is its underlying data
structure (don't assume that this is the structure of %$layer if $layer is
an ArgLayer object, but it will be in $layer somewhere).  This is provided
for you as a conceptual aid.

     {'flavor' => [
          {
             'val' => 'vanilla',
             'type' => '*',
             'group' => '1',
             'place' => '',
          },

          {
             'val' => 'chocolate',
             'type' => '*',
             'group' => '1',
             'place' => 'param',
          },

          {
             'val' => 'strawberry',
             'type' => '*',
             'group' => '',
             'place' => '',
          },
       ],

     'color' => [
          {
             'val' => 'red',
             'type' => '*',
             'group' => '',
             'place' => '',
          },

          {
             'val' => 'blue',
             'type' => '*',
             'group' => '',
             'place' => '',
          },
       ],
     };

   The entries for 'flavor' and 'color' will be referred to here as
"nodes."

Methods
-------

   * new Taco::ArgLayer

   * new Taco::ArgLayer(%hash)

   * new Taco::ArgLayer(@hash)

     Returns a new ArgLayer object.  If a list is given as input, it will
     be taken as a list of key-value pairs and used to create the
     ArgLayer.  In this case, &Taco::ArgUtil::parse will parse the
     incoming data.

   * $layer->dup()

     Returns a copy of the ArgLayer object.  The data in the copy is not
     linked to the data in the original, so if you change the data in one,
     the other will not be changed.

   * $layer->exists( $key )

     Returns a boolean value based on whether the given key exists in the
     ArgLayer.

   * $layer->delete( $key )

     Deletes all entries with the given name from the ArgLayer.

   * $layer->get_args( $key )

     Returns a list of all entries in the ArgLayer for the given key.

   * $layer->get_arg( $key )

     Same as $layer->get_args, but returns a scalar, which is the last
     element called $key in the ArgLayer.

   * $layer->set_arg('name', 'value', name, value, ...)

   * $layer->set_arg('name', {val=>...}, name, value, ...)

     Sets the values of the given keys in the ArgLayer.  Clears all args
     in this layer with these names! The named nodes don't have to exist
     already.  If a value is a hash reference, it will be assumed that
     you're passing a fully-formed argument node, such as the output of
     the &Taco::ArgUtil::parse function.  Otherwise we'll assume that
     you're passing just the value, and we'll wrap it in a hash to make it
     an argument node.

     See also add_arg() and merge().

   * $layer->add_arg('name', 'value', name, value, ...)

   * $layer->add_arg('name', {val=>...}, name, value, ...)

     Adds these args to the end of this layer's given nodes.   There don't
     have to be nodes with these names already.  If a value is a hash
     reference, it will be assumed that you're passing a fully-formed
     argument node, such as the output of the &Taco::ArgUtil::parse
     function.  Otherwise we'll assume that you're passing just the value,
     and we'll wrap it in a hash to make it an argument node.

     See also set_arg() and merge().

   * $layer->merge( $layer2 )

     Pushes the contents of the ArgLayer $layer2 into $layer.  The data in
     $layer2 will be put at the end of each node of $layer.

   * $layer->keys()

     Returns a list containing the names of all the keys in the layer, in
     no particular order.

   * $layer->each()

     Similar to Perl's each function for iterating over hashes, you can
     use it like this:

          while (($key, $value) = $layer->each) {
             # $key is a string
             # $value is a list of hashes
          }

   * $layer->show_me()

     Prints a representation of the data in an ArgLayer to STDERR.

   * $layer->to_hash( $name_only )

     Returns the layer's data in a list of key-value pairs.  If names_only
     is true, the keys returned will just be the names of the keys in the
     table.  Otherwise the keys will be of the form "param-flavor.3*+",
     where 'param' is the 'place', '3' is the 'group', and '*+' is the
     type of the 'flavor' key.  If none of these fancy things have values,
     setting the names_only flag will have no effect.

   * $layer->to_query_string( $name_only

     Similar to to_hash, but returns the data in the form of an URL query
     string.

     Not implemented yet.

   * $layer->to_arg_string(names_only)

     Similar to to_hash, but returns the data in the form of a template
     function argument string.

     Not implemented yet.

   * $layer->val('flavor')

   * $layer->group('flavor')

   * $layer->type('flavor')

   * $layer->place('flavor')

     Documentation not written yet, see also `$ArgTable-'val('flavor')>,
     etc.  It's very similar.

The ArgUtil Functions
=====================

   All these functions are in the namespace Taco::ArgUtil.  For example,
you'd call the unparse function by doing `&Taco::ArgUtil::unparse(...)'

   * unparse(name, ref, name_only)

     The inverse of &Taco::ArgUtil::parse, unparse translates a node in an
     ArgLayer to texty-hash format.

          name        - a string, the name of the node.
          ref         - a data structure in the format described below.
          name_only   - a boolean value: if true, omits the group, type, and place
                        information in the returned hash.  Prints all info by default.

     The 'ref' argument must be a reference to a list of hash references:

          $ref = [
             {'val' => 'beans',
              'group' => '3',
              'type'  => '*+',
              'place' => 'param',
             },

             {'val' => 'cheesecake',
              'type'  => '~',
             },

          {'val' => 'cheezo',
          },
           ];

           %hash = &Taco::ArgUtil::unparse('food', $ref);
           # Returns ('param-food.3*+' => 'beans', 'food~' => 'cheesecake', 'food' => 'cheezo').

   * parse(name, ref, name_only)

   * parse_query_string

   * parse_post

   * parse_arg_string

   * url_unencode

     Translates "the+stuff%21" to "the stuff!"

   * url_encode

     Translates "the stuff!" to "the+stuff%21"

AUTHOR
======

   Ken Williams (ken@forum.swarthmore.edu)

   Copyright (c) 1998 Swarthmore College. All rights reserved.

Dispatches functionality in templates to modules
************************************************

NAME
====

   Taco::Dispatcher.pm - Dispatches functionality in templates to modules

SYNOPSIS
========

   This module forms the connection between services and modules.  It
keeps track of which modules each service uses, and when any [[tag]] needs
to be evaluated, Taco::Dispatcher decides which module to hand it off to.

   This module also contains "chunker" functions that Taco::Template uses
to parse the syntax of templates.

DESCRIPTION
===========

   * &chunk_function( char, $text )

     Parses $text and returns a data structure in the following form.

          {
           type=>char,
           name=>function_name,
           args=>[arg1=>val1, arg2=>val2, ...],
          }

   * &chunk_variable( char, $text )

     Parses $text and returns a data structure of the form `{type=>char,
     name=>variable_name}'.  This is a simple process, since most of the
     time $text will not need any parsing, and will just be inserted into
     the variable_name slot.

   * &dispatch( chunk )

     Takes one argument, which is a template chunk like one created by
     `&chunk_whatever'.  Searches the various modules for the current
     service, looking for a module that claims to handle this chunk.  If
     it finds one, it lets that module handle it.

   * &set_modules( service, mod1, mod2, ... )

     Each service has a list of modules that it uses.  You use the
     `set_modules' function to set this list.  It will use Perl's @INC to
     look for the modules, so if you want to keep some modules in a
     non-standard location, do "use lib '/whatever/modules';".

   * &init_modules()

     When Taco is fired up, it will read the Taco::ServiceRegistry.pm file
     that contains definitions of the various Taco services.  After this
     file is read and all the services' modules have been created, Taco
     will call each module's init($service) method for each service that
     uses that module.

   * &get_modules( service )

     Returns a list of references to modules that this service uses.  If
     service is omitted, it defaults to the currently active service.

     See also `get_module_names'.

   * &get_module_names( service )

     Returns a list of the names of the modules that this service uses.
     If service is omitted, it defaults to the currently active service.

     See also `get_modules'.

   * &name2module( mod_name )

     Given a module name, returns a reference to the module object of that
     name.  If no module with the given name is currently loaded, the
     undefined value will be returned and a warning will be printed to
     STDERR.

   * &current_service( service_name )

     Get or set the currently active service.  With no arguments, this
     function just returns the name of the active service.  Given the name
     of a service, that service will be made the currently active service.

   * &services()

     Returns a list of all the names of services in
     Taco::ServiceRegistry.pm.

   * &service_info( attribute, service )

     Looks up an attribute in Taco::ServiceRegistry.pm.  If omitted, the
     service will default to the currently active service.

AUTHOR
======

   Ken Williams (ken@forum.swarthmore.edu)

   Copyright (c) 1998 Swarthmore College. All rights reserved.

Generic Taco template functions
*******************************

NAME
====

   Taco::Generic.pm - Generic Taco template functions

SYNOPSIS
========

   These are generic functions that any Taco template may want to have
available to it.

     [[&query]]
     [[&parse]]
     [[&set]]
     [[&if]]
     [[&mark_me]]

DESCRIPTION
===========

   The general syntax for any of these functions is:

     [[&name(arg1=val1 arg2='value two' ...)]
       or
     [[&name arg1=val1 arg2=[[&name2 arg="value two" ]] ...]
       or
     [[ &name ]]

   Whitespace is optional at the beginning and end of the tag.  A tag may
be spread across several lines, which is useful if you've got lots of
arguments you're passing to the function.  See the documentation for
Taco::Template for more information about the syntax.  If you really want
the juicy details you can look at the file t/docs/syntax.taco in the
distribution package - it has lots of valid syntaxes for function calls.

   * [[&query(trailing=&)]]

     This function will return the query string (verbatim).  The value of
     the trailing parameter will be appended if the query string exists (is
     not the empty string), which is useful in situations like this:

          <a href=page.taco?[[&query(trailing=&)]]flavor=cheese>Cheese City</a>

     If there's a query string (for example, "key=value"), this will
     appear as:

          <a href=page.taco?key=value&flavor=cheese>Cheese City</a>

     Otherwise it will appear as:

          <a href=page.taco?flavor=cheese>Cheese City</a>

     The only localized parameter is trailing.

   * [[&parse(parse_template=whatever)]]

     This will parse a template and insert its output here.  If you
     specify the `parse_template' parameter, it will look for the named
     template in the template directories.  In this way, it is similar to
     a server-side include.

     You can also use `[[&parse(parse_text="verbatim text")]]', though this
     is rarely useful.

     Taco will use the value of the `TemplatePath' attribute in the
     Taco::ServiceRegistry to look for your templates.  See also
     Taco::ServiceRegistry.

     Localized parameters are `parse_template' and `parse_text'.

   * [[&set(name=flavor value=raspberry)]]

     The above function call will set the "flavor" entry to "raspberry" in
     the 'set' layer of the global parameter table.  It will not output
     anything.

     Localized parameters are name and value.

     For more information about parameter tables, see Taco::Arg(3).

   * [[&if(condition='$var eq "hello"'                true_text='it is
     hello'                false_template=no_match)]]

     Use this function to write a conditional statement and output some
     text or a template based on the result.  The condition can be any
     Perl expression that will compile under Safe.pm's ":base_core"
     option.  This means that you're restricted to a small subset of Perl
     expressions, so check the error log if your template blows up - it
     might have an unallowable Perl expression in it.  Furthermore, the
     condition parameter must be present in the function call itself, so
     you can't put ...&condition=1&field=... in the query string.

     Using the Safe.pm module gives some protection against web users
     changing the query string and doing something very bad to your system.

     The `true_text' and `true_template' parameters specify what should be
     output if the condition evaluates to true.  You can use the special
     variable $result in your text (or template) to get the actual result
     of the evaluated condition.

     Likewise, the `false_text' and `false_template' parameters specify
     what should be output if the condition evaluates to false.  $result
     is still available, though it's probably not very interesting.

     Localized parameters are condition, `true_text', `true_template',
     `false_text', and `false_template'.

SEE ALSO
========

   Taco(3), Taco::Template(3), Taco::Module(3)

TO DO
=====

     It would be nice to have an [[&elsif]] tag or some similar idea.

AUTHOR
======

   Ken Williams (ken@forum.swarthmore.edu)

   Copyright (c) 1998 Swarthmore College. All rights reserved.

keep Perl files fresh
*********************

NAME
====

   Taco::LibLib.pm - keep Perl files fresh

SYNOPSIS
========

   Under normal mod_perl, Perl files will only get compiled when the
server starts up.  Any later changes you make to code files will not take
effect until you restart the server.

   To avoid this behavior, put LibLib::register($file); instead of require
$file; in your code.

   This is similar to Apache::StatInc, but for some reason I'm using this
instead.

DESCRIPTION
===========

   * register()
          Usage: &Taco::LibLib::register('file1.pl', 'file2.pl', ...);

     Use this function instead of "require 'file1.pl'", and your files
     will be magically compiled again whenever they get modified.

     You do not need to call freshen_codefiles() after
     register_codefiles().  Files will be freshened automatically.

   * freshen()
          Usage: &Taco::LibLib::freshen();

     Checks to see whether any code files have been modified since we last
     pulled them in.  If so, we pull them in again.

AUTHOR
======

   Ken Williams (ken@forum.swarthmore.edu)

   Copyright (c) 1998 Swarthmore College. All rights reserved.

abstract base class for Taco modules
************************************

NAME
====

   Taco::Module.pm - abstract base class for Taco modules

SYNOPSIS
========

   A Taco module defines what should happen when Taco encounters some
[[tags]] in a template.  It can define [[&functions]], or control what
happens when Taco fills in a [[$variable]], or even define some completely
new kind of [[%tag]].

   This class, Taco::Module, is an abstract class from which all Taco
modules should be derived.  It also provides one function which can be
used in templates, the [[&set_service]] function.

DESCRIPTION
===========

[[ &set_service( name=new_service ) ]]
--------------------------------------

   Use this function in a template to switch the currently active service.
The name parameter must be the name of a service in the
Taco::ServiceRegistry.pm file.

Using a module
--------------

   In order to use a Taco module, you need to make a Taco service that
uses the module.  See Taco::ServiceRegistry for more information about
adding modules to services.

Functions and Methods
---------------------

   * new

     This is the base class constructor.  To make a derived class, you
     need to override the constructor like so:

          sub new {
          	my $package = shift;
          	my $self = new Taco::Module;

          # Declare functions:
          $self->declare('func1', qw(arg1 arg2 arg2) );
          $self->declare('rainbow', qw(red orange yellow green blue indigo gravy) );

          return bless ($self, $package);
           }

     See also $module->declare().

   * $module->declare( NAME, ARGS )

     Use this method to make functions available to templates.  NAME is a
     string containing the name of the function you wish to export.  ARGS
     is a list of strings, and when your function is called in a template,
     parameters matching these names will not be propagated into
     lower-level templates.

     Generally you'll only use the declare() method in the module's
     constructor.

   * $module->init($service);

     When a module is created at server startup, Taco will call its init()
     method.  By default this method doesn't do anything, but overriding
     this method will let you read configuration files, open databases, or
     whatever you need to do.  For example, the Taco::DB module reads
     config.pl files for all the services that use Taco::DB.  The
     Taco::Generic module sets the ServiceRegistry's 'TemplatePath' to a
     default value if it hasn't been set already.

   * $self->has_function( CHUNK )

   * $self->has_variable( CHUNK )

   * $self->{'hook_testers'}

     When Taco encounters a [[tag]] in a template, it will step through
     the list of modules and ask each module whether it can handle that
     tag.  The mechanism for this asking process is handled by the
     `$self->{'hook_testers'}' hash.  A typical `hook_testers' hash looks
     like this:

          $self->{'hook_testers'} = {
             '$' => 'has_variable',
             '&' => 'has_function',
          };

     You can override the `has_variable' method and the `has_function'
     method in a module subclass.  For instance, if you want [[$cake]] to
     look up the value of 'cake' in a database, then your `has_variable'
     method should query the database to see whether it contains an entry
     for 'cake'.  This is exactly what the Taco::DB module does.

     All hook_tester functions should return a boolean value (true or
     false).

     Taco::Module contains base functions for the `has_function' and
     `has_variable' methods, which you shouldn't need to override for
     simple modules.

   * $self->find_value( CHUNK )

   * $self->run_function( CHUNK )

   * $self->{'hook_doers'}

     Once Taco has determined that your module will handle a certain tag,
     it uses the entries in the `$self->{'hook_doers'}' hash to let your
     module actually handle the tag.

     Each of the `hook_doers' should output a single string.  This string
     will be inserted into the template at the correct place.  The input
     to all the hook_doer functions is a "chunk", which is a data
     structure like this:

          $chunk = {
             'type' => '&',
             'name' => 'list', # For example
             # perhaps more stuff depending on
             # what kind of chunk it is
          };

     These chunks are the output of the Taco::Template chunker functions.
     A chunker function takes a string like [[&func(arg1=val arg2=val)]]
     and turns it into a data structure.  See Taco::Template for more info
     on chunks and chunkers.

     If you add entries to the `$self->{'hook_testers'}' and
     `$self->{'hook_doers'}' hashes, you can extend the syntax of Taco
     templates.  For instance, to enable some kind of hash lookup in
     templates, you could do something like this:

          $self->{'hook_testers'}{'%'} = 'has_hash';
          $self->{'hook_doers'}{'%'}   = 'do_hash_lookup';

     And then you'd write the `has_hash' and `do_hash_lookup' functions.
     You'll also need to supply a chunker for % tags.

Writing Taco modules
--------------------

   To create a new Taco module, you'll create a Perl module that's a
subclass of Taco::Module (through direct or indirect inheritance).  You'll
probably add some functions, so declare those in your constructor, using
the declare() method.  Look at Taco::Generic and Taco::DB for examples of
real Taco modules.

   When you're writing a function that needs to send text to the browser
(or whoever is filling in Taco templates), you shouldn't just use print().
In fact, you should probably _never_ print to STDOUT.  Use the
$template->output() method to output text, because sometimes it's safe to
just print your text, but other times you need to return it at the end of
the routine.  For example, consider this template:

     __________________
     [[ &list(driver=catalog_id
             display_text=[[&parse(parse_template=shower variable=value)]]
     ) ]]
     __________________

   If &parse printed its output instead of returning it, then it would
appear on the page above the call to &list, because &list hasn't run yet
when &parse is running.  It's all very complicated, it gives me a headache.

   Fortunately, $template->output() knows when you're in one situation and
when you're in the other.  See Taco::Template for more information about
about using $template->output() and $template->straight_output() to stream
your output properly.

AUTHOR
======

   Ken Williams (ken@forum.swarthmore.edu)

   Copyright (c) 1998 Swarthmore College. All rights reserved.

Definitions of Taco services
****************************

NAME
====

   Taco::ServiceRegistry - Definitions of Taco services

SYNOPSIS
========

     # In Taco/ServiceRegistry.pm:
        $root_dir = "/wherever/you/want";

     %registry = (
       "your_service" => {
         "Modules" => [ qw(Core TacoDB) ],  # The modules this service uses - required
         "TemplatePath" => ["$root_dir/your_service/templates", "/etc/templates"],
         "Taco::DB_config" => "$root_dir/your_service/config.pl",  # Add entries that your modules
                                                                   # need to have
       },
       ...
     );

DESCRIPTION
===========

   The Taco::ServiceRegistry.pm file contains configuration information
about the various Taco services you define.  Each key in the %registry hash
is the name of a Taco service, and the value is an anonymous hash of
various attributes of the service.

   The "Modules" attribute is currently the only required attribute - it
specifies which Taco modules the service uses.

   The "ServiceDir" attribute will be used to fill in other default
settings, such as "TemplatePath".  If you don't set it, it will be given a
default value of `"$root_dir/$service"' (where $service is the name of the
service being defined).

   The "TemplatePath" attribute is not required, but if it is not given, a
default value of `["$ServiceDir/templates"]' will be used (where
$ServiceDir is the value of the "ServiceDir" attribute).

   These three attributes are currently the only attributes known by Taco
- all other attributes are the property of specific modules.  For
instance, the Taco::DB module needs a "Taco::DB_config" attribute, a
"Taco::DB_data_dir" attribute, and so on.  It can set default values for
these attributes based on the values of the ServiceDir attributes, etc.
Please read the documentation for the modules you want to use to see what
information they require in the ServiceRegistry.

AUTHOR
======

   Ken Williams (ken@forum.swarthmore.edu)

SEE ALSO
========

   perl(1), Taco(3)

Taco templates
**************

NAME
====

   Taco::Template.pm - Taco templates

SYNOPSIS
========

     use Taco::Template;

     $template = new Taco::Template( 'Howdy, [[$name]]!' );
     $template->output($buffer);
     $string = $template->interpret;
     $string2 = &Taco::Template::interpret( 'And hello, [[$name2]]!' );
     # ... etc.

DESCRIPTION
===========

   This module is a class implementing fill-in templates for Taco.  It
provides support for streaming the output of a filled-in template.  The
specific syntaxes of the tags are not defined in this class, so it is
extensible and flexible.

Functions and Methods
---------------------

   * new Taco::Template($text);

     Creates a new Template object whose content is the given text.

   * find Taco::Template('name')

     Searches $G::params for an entry called 'name_text' or
     'name_template'.  Returns a template whose content is the value of
     'name_text', or whose content is the contents of the file referred to
     by 'name_template'.  If neither is found, returns the undefined value.

     May be called with an optional second argument, which is a reference
     to a scalar variable.  This scalar will be set to the string 'text'
     if the 'name_text' parameter is found, or 'template' if the
     'name_template' parameter is found, or the undefined value if neither
     is found:

          my $template = find Taco::Template('name', \$kind);
          if ($kind eq 'text') ...

     Note that if no suitable parameter is found in $G::params, no error
     will be printed to STDERR.  This allows you the flexibility to write
     code like this:

          # Template is required:
          my $template = find Taco::Template('display')
             or die ("Couldn't find 'display_template' or 'display_text'");

          # Template is optional:
          my $template = find Taco::Template('wrapping');
          if ($template) {
             # ... do something with $template ...
          }

   * $template->get_text()

     Returns the content of the template object.

   * $template->set_text('text blah [[$blah]]')

     Sets the content of the template to the given text.

   * $template->get_file('filename')

     Puts the contents of the file 'filename' into the template's content.
     If the filename has a leading slash, it is treated as an absolute
     filename.  If it does not, get_file will search the directories in
     the template's path for the given file.

     See also `set_path'.

   * $template->set_path('dir1', 'dir2', ...);

     Sets the path for the get_file method.  If called as an object
     method, will set the path for just the given template.  If called as
     a static class method, will set the default path for all templates:

          Taco::Template->set_path('/etc/templates');   # sets default path
          $my_templ->set_path('/etc/templates');  # only sets path for $my_templ

   * $template->set_property( name => 'property')

   * $template->get_property('name')

     The user of a template may wish to set some attribute of a template,
     and later retrieve that attribute.  These methods let you do so.
     This is useful to achieve small extensions to the functionality of
     the templates without having to derive a new class.

   * $template->output($buffer)

   * &Taco::Template::output($text, $buffer)

     Interprets and outputs the contents of the template.  Checks a flag
     to see whether printing is okay, or whether output should be added to
     the end of the buffer.  Typically, output will be buffered in nested
     tags:

          ____________ outer.tmpl: ________________________________
          [[ &list( key=[[&parse(parse_template=inner.tmpl)]] ) ]]
          ____________ inner.tmpl: ________________________________
          this is the key's value
          _________________________________________________________

     Since `&parse' is called inside `&list', it must not print its
     output, it must return it.  The Template class keeps track of when
     it's okay to print, and when a routine must return its output
     instead.  In this way, output can be streamed as much as possible.

     If the first argument to output is a reference, then this argument
     will be treated as a template object.  Otherwise, it will be treated
     as a string.

     Here is a simple example of a routine that uses output:

          sub do_something {
          	my $template  = find Taco::Template('stuff') or die ("Can't find my stuff");
          	my $buffer;

          	&Taco::Template::output('<ol start=[[$num]]>', $buffer);
          	# Instead of: print &Taco::Template::interpret('<ol start=[[$num]]>');

          $template->output($buffer);
          # Will append text to $buffer if necessary

          &Taco::Template::straight_output('</ol>', $buffer);

          return $buffer;
           }

   * $template->straight_output($buffer)

   * &Taco::Template::straight_output($text, $buffer)

     Identical to output, except the text will not be interpreted as a
     template, it will be output directly (or appended to $buffer).  This
     is useful for outputting chunks of text quickly when you know there
     are no tags in it:

          &Taco::Template::straight_output("</ol>\n", $buffer);

   * $template->interpret

   * &Taco::Template::interpret( $text )

     Returns the parsed contents of the template or text.  Will not print
     anything (assuming the functions called in the template are
     well-behaved and use `Taco::Template::output' and the like).

Controlling template syntax and execution
-----------------------------------------

   * &Taco::Template::set_chunker( char, \&routine );

     Sets the chunker for the given character.  The chunker will be called
     when building the syntax tree for a template.  A chunker routine
     takes two arguments: the character (such as $ or &) of the type of
     template call, and the text of the template call, with leading and
     trailing delimiters and whitespace removed.  For instance, with the
     following in a template:

          [[ &burp(because=have_gas) ]]

     The chunker will receive '&' as its first argument, and
     'burp(because=have_gas)' as its second argument.

     A chunker function should parse the text into a hash reference, which
     includes a 'type' field equal to the chunker's first argument.  The
     rest of the hash can have whatever structure the executor of that
     hook will need to execute it (see `set_executor').  The chunker
     returns a single argument, the hash reference with the 'type' field.

     Here is an example of a chunker which handles tags like `[[ $var ]]':

          sub chunk_variable {
            # returns {type=>'$', name=>'whatever'}

          my $type = shift;
          my $text = shift;
          return {
             type=>$type,
             name=>&Taco::Template::interpret($text),
                          # So we can handle things like [[ $var[[$two]] ]].
                          # If we didn't need to, we could just do name=>$text.
          };
           }

   * &Taco::Template::set_executor( char, \&routine );

     Sets the executor function for the given character.  The executor
     will be called to interpret the value of a template tag.  It takes
     one argument, a hash reference created by a chunker.  The executor
     should return a string which is the result of executing the given tag.

SEE ALSO
========

   Have a look at `Taco::Dispatcher.pm' if you're want to see the chunker
and executor functions.  They govern the syntax and execution of the
individual tags.

AUTHOR
======

   Ken Williams (ken@forum.swarthmore.edu)

   Copyright (c) 1998 Swarthmore College. All rights reserved.

Perl utility extensions for tainted data
****************************************

NAME
====

   Taint - Perl utility extensions for tainted data

SYNOPSIS
========

     use Taint;
     warn "Oops"
       if tainted $num, @ids;	# Test for tainted data
     kill $num, @ids;		# before using it

     use Carp;
     use Taint;
     sub baz { croak "Insecure request" if tainted @_; ... }

     use Taint qw(taint);
     taint @list, $item;		# Intentionally taint data

     use Taint qw(:ALL);
     $pi = 3.14159 + tainted_zero;	# I don't trust irrational numbers

DESCRIPTION
===========

   Perl has the ability to mark data as 'tainted', as described in
`perlsec(1)' in this node. Perl will prevent tainted data from being used
for some operations, and you may wish to add such caution to your own
code. The routines in this module provide convenient ways to taint data
and to check data for taint. To remove the taint from data, use the method
described in `perlsec(1)' in this node, or use the make_extractor routine.

   Please read `' in this node and `' in this node.

ROUTINES
========

tainted LIST
is_tainted EXPR
any_tainted LIST
all_tainted LIST
     Test one or more items for taint. tainted is an alias for
     any_tainted, provided for convenience. (Also, tainted is exported by
     default.) is_tainted is prototyped to take a *single scalar*
     argument, the others take lists. (If you're not sure which one to
     use, use tainted.) When taint checks are off, these always return
     false.

taintedness LIST
     This is a utility function, mostly useful for authors of subroutines
     in modules. It is possible that an algorithm, by its nature, doesn't
     propagate taintedness as it should. This routine returns the
     taintedness of its parameters in the form of a null string which is
     either tainted or not. (When taint checking is off, the return value
     is always an untainted null string.) That string may be (for example)
     appended to a return value to taint it if needed.

          sub frobnicate {
          	my($taintedness) = taintedness @_;	# save it
          	# ...do some stuff which may or may not
          	# properly propagate taint...
          	return undef if $you_want_to;
          	return $taintedness . $return_value;	# restore it
          }

taint LIST
     If taint checks are turned on, marks each (apparently) taintable
     argument in LIST as being tainted. (References and undef are never
     taintable and are left unchanged. Some tied and magical variables may
     fail to be tainted by this routine, try as it may.)

     To taint (the values of) an entire hash, use this idiom.

          taint @hash{ keys %hash };		# taint values of %hash

tainted_null
tainted_zero
     If you'd rather taint your data yourself, these constants will let
     you do it. tainted_null is a tainted null string, which may be
     appended to any data to taint it. (Of course, that will also
     stringify the data, if needed.) tainted_zero is (surprise) a tainted
     zero, which may be added to any number to taint it. Note that when
     taint checking is off, nothing can be tainted, so then these are
     merely mundane " and 0 values.

taint_checking
     This constant tells whether taint checks are in use.  This is usually
     only useful in connection with the allow_no_taint option (see `' in
     this node).

          print LOG "Warning: Taint checks not enabled\n"
          	unless taint_checking;

make_extractor EXPR
     This routine returns a coderef for a subroutine which untaints its
     arguments according to the pattern passed in the string EXPR.
     Although the argument to this routine must be untainted, the
     arguments to the generated code may be tainted or not. When taint
     checking is off, this routine and its generated code behave in
     essentially the same way, even though neither their parameters nor
     return values are tainted.

     Note: When untainting data, it's often easier to use the method
     described in `perlsec(1)' in this node, especially if you're
     unfamiliar with constructing strings to be used as regular
     expressions.

     Here's one way this routine might be used. This example is part of a
     server (similar in some ways to *fingerd*; see `fingerd(8)' in this
     node) which, when given a username, runs the Unix who command,
     extracts and untaints some information about that user, and reports
     it. Note that the regular expression is compiled just once, (within
     the make_extractor routine) even though the username may change every
     time through the main loop.

          while () {	# The server runs in an infinite loop
          	my $username = &get_next_request;
          	# $username must already be untainted! (But let's not
          	# assume it doesn't have metacharacters, even though
          	# Unix usernames can't have any.)
          	my $pattern =
          	    '^' .
          	    quotemeta($username) .
          	    '\s+(\S+)\s+(.+)$';
          	my $get_who = make_extractor $pattern;

          my %info = ();
          for (`who`) {
              # $_ has lines of tainted information
              my($tty, $date) = &$get_who($_);
              # but $tty and $date are untainted
              $info{$tty} = $date;
          }
          # %info now has untainted information
          ...
              }

     Any items which need to be extracted should be within memory parens.
     Because of that, the string should normally have at least one set of
     memory parens. The pattern will be applied to each of the arguments
     in turn, returning a list of all matched items in memory parens. Any
     arguments which fail to match will add no items to the list. If
     called in a scalar context, the generated sub will return just the
     first untainted item in the list. No locale is used; see `SECURITY',
     see Perllocale (perl.info).

     Note that the pattern may need to be written a little differently
     than usual, since it's going to be passed as a string. For example,
     it's not necessary to backwhack forward slashes in the pattern, since
     those aren't regexp metacharacters. Also, if the pattern is built up
     in an expression, it's important that the components all be
     untainted! And, of course, it needs to be a valid regular expression;
     otherwise, it causes an immediate error which may be trapped with
     eval.

     For a case-insensitive match, which would usually be indicated with
     the `/i' modifier, use the embedded `(?i)' modifier, as described in
     `perlre(1)' in this node. The other embeddable modifiers also work.

     If the pattern contains backslashes, as many do, it is especially
     problematic. For example, these attempts to make a pattern aren't
     doing what they might look like.

          $pattern1 = "(\w+)";	# effectively /(w+)/

          $pattern2 = '\Q' . $foo;	# doesn't use quotemeta

     Usually, though, single quotes will do what you expect (and double
     quotes will confuse you). To help in debugging, you may set
     `$Taint::DEBUGGING = 1' before calling make_extractor, which will
     produce an allegedly-helpful debugging message as a warning. This
     message will have a form of the regular expression passed, like
     `/(w+)/' for `$pattern1' above.

unconditional_untaint LIST
     By unpopular request, this routine is included. Don't use it. Use the
     method described in `perlsec(1)' in this node instead. You'd have to
     be crazy to use this routine. (If you are, read the module itself to
     see how to enable it. I'm not gonna tell you here.)

     Given a list of possibly tainted *lvalues*, this untaints each of them
     without any regard for whether they should be untainted or not.

allow_no_taint
     By default, importing symbols from this module requires taint checks
     to be turned on. If you wish to use this module without requiring
     taint checking (for example, if writing a module which may or may not
     be run under -T) either import this pseudo-item...

          use Taint qw(allow_no_taint);	# allow to run without -T
          use Taint;				# default import list

     or avoid importing any symbols by explicitly passing an empty import
     list.

          use Taint ();	# importing no symbols

     If you use either of these methods to allow taint checks not to be
     required, you may want to use the constant taint_checking (see `' in
     this node) to determine whether checks are on.

     It may be helpful to allow checks to be off during development, but
     be sure to require them after release!

Exports
-------

   The only routine exported by default is `tainted()'. Fortunately, this
is the only one most folks need. Other routines may be imported by name,
or with the pseudo-import tag :ALL, or the other pseudo-import tags
defined in Exporter.

NOTES
=====

   Tainting may be explicitly turned on with the -T invocation option (see
`-T', see Perlrun (perl.info)). Perl will force taint checking
to be on if a process was started with setuid or setgid privileges.  By
default, this module requires taint checking to be on (but see
`allow_no_taint' in this node).

   A set-id script may not necessarily run with privileges; that depends
upon your system, the privileges of the user running the script, and
possibly upon the configuration of perl. This means that if a set-id
script is run by its own id(s), it won't have any taint checks - so your
script may fail, but only when *you* run it!

   If you're having trouble getting your script to work when taint checks
are on, you should remember that Perl will automatically take some extra
precautions. By default, Perl doesn't use some environment variables that
it normally would, using locales may cause data to be tainted, and the
current directory ('.') won't be included in the `@INC' list. See
`perlsec(1)' in this node for the full list.

DIAGNOSTICS
===========

Attempt to taint read-only value
     Just what it sounds like. taint is not able to taint something which
     can't be modified, such as an expression or a constant.

Pattern was /.../o
     When `$Taint::DEBUGGING' is set to a true value, this message will be
     issued as a warning for each pattern passed to make_extractor().
     This sub will make an attempt to represent the pattern in the
     "traditional" `/foo/' format, although there are some differences.
     For example, some escapes, such as `\Q', aren't really part of the
     regular expression engine. So, if this shows a regular expression as
     `/\Q/', that means that it's trying to match a backslash followed by
     a capital Q. Also, this format does backwhack the slash mark itself
     (since it'll be quoted in the string by slashes), even though you
     don't want to pass a backslash before a true slash in the pattern.
     The represented pattern always ends in /o, since that option is
     always used internally in make_extractor().

sub unconditional_untaint() not properly imported
     You should read `perlsec(1)' in this node again to see how to untaint
     your data. Repeat as needed.

Can't make code from tainted string
     You tried to pass a tainted string to make_extractor(). You should be
     ashamed of yourself.

Wrong way to import unconditional_untaint()
     You should read `perlsec(1)' in this node again to see how to untaint
     your data. Repeat as needed.

Can't redefine
     You already had a subroutine with the same name as the
     `unconditional_untaint()' routine you were trying to import. How many
     of these do you need?

Taint checks not enabled
     Just what it sounds like. Somehow, you didn't have taint checks
     turned on, and (since you're using this module) you probably were
     counting on them. Possible reasons:  You thought your script would be
     run set-id, but it wasn't. You forgot to put -T on the top of your
     script.  You're using a module which uses this one, and you didn't
     know that that module expects taint checks to be on.  (If you wish to
     allow taint checks to be either on or off, see `' in this node.

Disabled option requested
     You tried to use the `unconditional_untaint()' routine, but whoever
     installed this module thought you shouldn't.  You should read
     `perlsec(1)' in this node again to see how to untaint your data.
     Repeat as needed.

Unexpected error
     Something went wrong when trying to taint some data, probably because
     you tried to taint the untaintable. (For example, a tied variable.)
     If this happens, please let the author of this module know the
     circumstances and the error message so that I can try to get a better
     error message into a future version.

BUGS
====

   We have no way to enforce understanding the docs.

   Debugging a program which uses taint checks can be problematic.

   Some modules aren't compatible with taint checking. Write to their
authors and offer to help improve the modules. Modules which implement
tied variables often need help.

   The look of some of this module's internal code makes some people think
its author was smoking crack. But some people think that when they see any
Perl code.

   `is_tainted @foo' isn't what you might think. And it don't use no good
grammars, neither, if you asks me.

   `taint %bar' doesn't do anything good. (Hey, I'd make an error message
if I knew how to detect it.)

   There is no routine which will taint all the taintable parts of a
structure more complex than a simple list.

   Taint checking is a largely-unexplored area of Perl. It's not unlikely
that there are as-yet undiscovered bugs in Perl's tainting code. While
working on this module and its tests, the author found three bugs in
Perl's internal taint handling. (Using taint checking is like using a
safety net with holes. At least it's better than no net at all.) Most new
versions of Perl (and even many subversions) fix at least one
tainting-related bug. The moral of the story: Stay on alert for
announcements about new versions of Perl and vital modules like this one.
(Watch comp.lang.perl.announce.)

   `no Taint;' doesn't turn off taint checks (lexically or otherwise), and
`use Taint;' doesn't turn them on. Dang.

   Some bugs are documented only in this sentence. (Please send
documentation patches and other corrections to the author.)

   The following data can never be tainted: references, undef, hash keys,
anything which is not a scalar, and some magical or tied variables.
Attempting to taint some of these may cause interesting and educational
results. (The module which implements a tied variable may allow (or even
force) tainting. (For that matter, a tied hash could conceivably have
tainted keys! But untainting those would be ...interesting.) Although a
reference can't be tainted, it may reference a thingy which is tainted in
whole or in part.)

   There's no routine which taints data "in passing". That is, there's
nothing to which you can pass *@foo* and get back a tainted copy of it,
leaving @foo unmodified. I have a wonderful reason for this, but there's
not enough room to write it here in the margin.

   Okay, here's the reason, which is simply too big and complex to stuff
into the BUGS section of the manpage.

   Suppose you have a module that you're adding taint checks to.  You've
got a sub that ends something like this:

     ...
     return &foo(@bar);
         }

   Now you decide to add taint to the data you're returning, so you apply
the (hypothetical) taint_in_passing routine to it.

     ...
     return taint_in_passing &foo(@bar);
         }

   Unknown to you, somebody has been calling your sub in a scalar context,
and somebody else has been calling it in a list context.  Now,
`&foo(@bar)' is being called in the context of taint_in_passing, which
will be the wrong context part of the time.

   You may be wondering now why we don't simply make taint_in_passing
notice the context it's called in, with wantarray, so that it can evaluate
its args in the same context it was called in. (If you're wondering why we
don't just have it return the number of elements returned by `&foo(@bar)'
when it's called in a scalar context, you don't understand context issues
very well.) But that's not something that can be done with Perl, at least
not currently.  By the time the sub is called, the args have already been
evaluated, context right or wrong.

   Thus, there's no way to write a taint_in_passing sub which can be
counted on to do the right thing. :-(

   Instead, you should see what your code returns in different contexts,
and then do the right thing, whatever that is.

   This module's author believes that a taint_in_passing sub in this
module would be misused by people who don't understand this issue.  If you
still want one, now that you understand this issue of context, you should
be able to make one which will do what you need for your application. Just
don't add it to this module unless and until you can change my mind. :-)
Thanks!

   Some bugs should be construed as features, and vice versa. This may be
one of them.

AUTHOR
======

   Tom Phoenix, <`rootbeer@teleport.com'>

COPYRIGHT
=========

   This entire module is Copyright (C) 1997 by Tom Phoenix. This module is
experimental and may be installed for TESTING AND DEVELOPMENT PURPOSES
ONLY. It may not be distributed or redistributed except through the
Comprehensive Perl Archive Network (CPAN). A modified or partial copy of
this package must not be redistributed without prior written permission.
In particular, this module and Perl's taint checking may not do what you
want, and they may do what you do not want; using this module in any way
without understanding that fact is strictly forbidden.

DISCLAIMER
==========

   THIS ENTIRE MODULE, INCLUDING ITS DOCUMENTATION AND ALL OTHER FILES, IS
PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS
FOR A PARTICULAR PURPOSE.

   You must read and understand all appropriate documentation, especially
including `perlsec(1)' in this node and this manpage. I say again, this
module and Perl's taint checking may not do what you want, and they may do
what you do not want; using this module in any way without understanding
that fact is strictly forbidden.

   Although all reasonable efforts have been made to ensure its quality,
utility, and accuracy, it is the users' responsibility to decide whether
this is suitable for any given purpose. You runs your code and you takes
your chances.

   Okay, this is a heck of a disclaimer. Try not to be too scared; the
author uses this code himself (when not writing about himself in the third
person). Watch the newsgroup comp.lang.perl.announce for announcements of
new versions of this module and other cool stuff.

SEE ALSO
========

   `perlsec(1)' in this node and `perlre(1)' in this node.

module for manipulation of tar archives.
****************************************

NAME
====

   Tar - module for manipulation of tar archives.

SYNOPSIS
========

     use Tar;

     $tar = Tar->new();
     $tar->add_files("file/foo.c", "file/bar.c");
     $tar->add_data("file/bar.c","This is the file contents");
     $tar->write("files.tar");

DESCRIPTION
===========

   This module is definitely tentative, and several things will be changed
rather shortly. The exported routines will not be exported [done], all the
calls to croak() should be replaced with returning undef() and putting
error messages in a package global [done].

   At the moment these methods are implemented:

new()
     Returns a new Tar object. If given a filename as an argument, it will
     try to load that as a tar file.

`add_files(@filenamelist)'
     Takes a list of filenames and adds them to the in-memory archive.

`add_data($filename,$data,$opthashref)'
     Takes a filename, a scalar full of data and optionally a reference to
     a hash with specific options. Will add a file to the in-memory
     archive, with name $filename and content $data. Specific options can
     be set using `$opthashref', which will be documented later.

`remove(@filenamelist)'
     Removes any entries with names matching any of the given filenames
     from the in-memory archive. String comparisons are done with eq.

`read('`file.tar'')'
     Try to read the given tarfile into memory. Will replace any previous
     content in `$tar'!

`write('`file.tar'')'
     Will write the in-memory archive to disk.

data()
     Returns the in-memory archive. This is a list of references to hashes,
     the internals of which is not currently documented.

`extract(@filenames)'
     Write files whose names are equivalent to any of the names in
     `@filenames' to disk, creating subdirectories as neccesary. This
     might not work too well under VMS and MacOS.

CHANGES
=======

Version 0.04
Made changes to write_tar so that Solaris' tar likes the resulting        archives better.
Protected the calls to readlink() and symlink(). AFAIK this module        should now run just fine on Windows NT.
Add method to write a single entry to disk (extract)
Added method to add entries entirely from scratch (add_data)
Changed name of add() to add_file()
All calls to croak() removed and replaced with returning undef       and setting Tar::error.
Better handling of tarfiles with garbage at the end.

Tcl extension module for Perl
*****************************

NAME
====

   Tcl - Tcl extension module for Perl

SYNOPSIS
========

     use Tcl;

     $interp = new Tcl;
     $interp->Eval('puts "Hello world"');

DESCRIPTION
===========

   The Tcl extension module gives access to the Tcl library with
functionality and interface similar to the C functions of Tcl.  In other
words, you can

create Tcl interpreters
     The Tcl interpreters so created are Perl objects whose destructors
     delete the interpreters cleanly when appropriate.

execute Tcl code in an interpreter
     The code can come from strings, files or Perl filehandles.

bind in new Tcl procedures
     The new procedures can be either C code (with addresses presumably
     obtained using *dl_open* and *dl_find_symbol*) or Perl subroutines
     (by name, reference or as anonymous subs). The (optional) deleteProc
     callback in the latter case is another perl subroutine which is called
     when the command is explicitly deleted by name or else when the
     destructor for the interpreter object is explicitly or implicitly
     called.

Manipulate the result field of a Tcl interpreter
Set and get values of variables in a Tcl interpreter
Tie perl variables to variables in a Tcl interpreter
     The variables can be either scalars or hashes.

Methods in class Tcl
--------------------

   To create a new Tcl interpreter, use

     $i = new Tcl;

   The following methods and routines can then be used on the Perl object
returned (the object argument omitted in each case).

Init ()
     Invoke *Tcl_Init* on the interpeter.

Eval (STRING)
     Evaluate script STRING in the interpreter. If the script returns
     successfully (TCL_OK) then the Perl return value corresponds to
     interp->result otherwise a die exception is raised with the $@
     variable corresponding to interp->result. In each case, *corresponds*
     means that if the method is called in scalar context then the string
     interp->result is returned but if the method is called in list context
     then interp->result is split as a Tcl list and returned as a Perl
     list.

GlobalEval (STRING)
     Evalulate script STRING at global level. Otherwise, the same as
     Eval() above.

EvalFile (FILENAME)
     Evaluate the contents of the file with name FILENAME. Otherwise, the
     same as Eval() above.

EvalFileHandle (FILEHANDLE)
     Evaluate the contents of the Perl filehandle FILEHANDLE. Otherwise,
     the same as Eval() above. Useful when using the filehandle DATA to
     tack on a Tcl script following an __END__ token.

call (PROC, ARG, ...)
     Looks up procedure PROC in the interpreter and invokes it directly
     with arguments (ARG, ...) without passing through the Tcl parser. For
     example, spaces embedded in any ARG will not cause it to be split
     into two Tcl arguments before being passed to PROC.

result ()
     Returns the current interp->result field. List v. scalar context is
     handled as in Eval() above.

CreateCommand (CMDNAME, CMDPROC, CLIENTDATA, DELETEPROC)
     Binds a new procedure named CMDNAME into the interpreter. The
     CLIENTDATA and DELETEPROC arguments are optional. There are two cases:

     (1) CMDPROC is the address of a C function

     (presumably obtained using *dl_open* and *dl_find_symbol*. In this
     case CLIENTDATA and DELETEPROC are taken to be raw data of the
     ClientData and deleteProc field presumably obtained in a similar way.

     (2) CMDPROC is a Perl subroutine

     (either a sub name, a sub reference or an anonymous sub). In this case
     CLIENTDATA can be any perl scalar (e.g. a ref to some other data) and
     DELETEPROC must be a perl sub too. When CMDNAME is invoked in the Tcl
     interpeter, the arguments passed to the Perl sub CMDPROC are

          (CLIENTDATA, INTERP, LIST)

     where INTERP is a Perl object for the Tcl interpreter which called out
     and LIST is a Perl list of the arguments CMDNAME was called with.  As
     usual in Tcl, the first element of the list is CMDNAME itself.  When
     CMDNAME is deleted from the interpreter (either explicitly with
     DeleteCommand or because the destructor for the interpeter object is
     called), it is passed the single argument CLIENTDATA.

DeleteCommand (CMDNAME)
     Deletes command CMDNAME from the interpreter. If the command was
     created with a DELETEPROC (see CreateCommand above), then it is
     invoked at this point. When a Tcl interpreter object is destroyed
     either explicitly or implicitly, an implicit DeleteCommand happens on
     all its currently registered commands.

SetResult (STRING)
     Sets interp->result to STRING.

AppendResult (LIST)
     Appends each element of LIST to interp->result.

AppendElement (STRING)
     Appends STRING to interp->result as an extra Tcl list element.

ResetResult ()
     Resets interp->result.

SplitList (STRING)
     Splits STRING as a Tcl list. Returns a Perl list or the empty list if
     there was an error (i.e. STRING was not a properly formed Tcl list).
     In the latter case, the error message is left in interp->result.

SetVar (VARNAME, VALUE, FLAGS)
     The FLAGS field is optional. Sets Tcl variable VARNAME in the
     interpreter to VALUE. The FLAGS argument is the usual Tcl one and can
     be a bitwise OR of the constants $Tcl::GLOBAL_ONLY,
     $Tcl::LEAVE_ERR_MSG, $Tcl::APPEND_VALUE, $Tcl::LIST_ELEMENT.

SetVar2 (VARNAME1, VARNAME2, VALUE, FLAGS)
     Sets the element VARNAME1(VARNAME2) of a Tcl array to VALUE. The
     optional argument FLAGS behaves as in SetVar above.

GetVar (VARNAME, FLAGS)
     Returns the value of Tcl variable VARNAME. The optional argument FLAGS
     behaves as in SetVar above.

GetVar2 (VARNAME1, VARNAME2, FLAGS)
     Returns the value of the element VARNAME1(VARNAME2) of a Tcl array.
     The optional argument FLAGS behaves as in SetVar above.

UnsetVar (VARNAME, FLAGS)
     Unsets Tcl variable VARNAME. The optional argument FLAGS behaves as
     in SetVar above.

UnsetVar2 (VARNAME1, VARNAME2, FLAGS)
     Unsets the element VARNAME1(VARNAME2) of a Tcl array.  The optional
     argument FLAGS behaves as in SetVar above.

Linking Perl and Tcl variables
------------------------------

   You can tie a Perl variable (scalar or hash) into class Tcl::Var so
that changes to a Tcl variable automatically "change" the value of the
Perl variable. In fact, as usual with Perl tied variables, its current
value is just fetched from the Tcl variable when needed and setting the
Perl variable triggers the setting of the Tcl variable.

   To tie a Perl scalar $scalar to the Tcl variable *tclscalar* in
interpreter *$interp* with optional flags $flags (see SetVar above), use

     tie $scalar, Tcl::Var, $interp, "tclscalar", $flags;

   Omit the $flags argument if not wanted.

   To tie a Perl hash *%hash* to the Tcl array variable array in
interpreter *$interp* with optional flags $flags (see SetVar above), use

     tie %hash, Tcl::Var, $interp, "array", $flags;

   Omit the $flags argument if not wanted. Any alteration to Perl variable
*$hash{"key"}* affects the Tcl variable *array(key)* and *vice versa*.

AUTHOR
------

   Malcolm Beattie, mbeattie@sable.ox.ac.uk, 23 Oct 1994.

Extension module for Perl giving access to Tk via the Tcl extension
*******************************************************************

NAME
====

   Tcl::Tk - Extension module for Perl giving access to Tk via the Tcl
extension

SYNOPSIS
========

     use Tcl;
     use Tcl::Tk qw(:widgets :misc);
     $interp = new Tcl::Tk;
     label(".l", -text => "Hello world");
     tkpack ".l";
     MainLoop;

DESCRIPTION
===========

   The Tcl::Tk submodule of the Tcl module gives access to the Tk library.
It does this by creating a Tcl interpreter object (using the Tcl extension)
and binding in all of Tk into the interpreter (in the same way that *wish*
or other Tcl/Tk applications do).

Access to the Tcl and Tcl::Tk extensions
----------------------------------------

   To get access to the Tcl and Tcl::Tk extensions, put the commands
use Tcl;     use Tcl::Tk;

   near the top of your program. You can also import short-cut functions
into your namespace from Tcl::Tk if you want to avoid using method calls
for everything.

Creating a Tcl interpreter for Tk
---------------------------------

   To create a Tcl interpreter initialised for Tk, use

     $i = new Tcl::Tk (DISPLAY, NAME, SYNC);

   All arguments are optional. This creates a Tcl interpreter object $i,
and creates a main toplevel window. The window is created on display
DISPLAY (defaulting to the display named in the DISPLAY environment
variable) with name NAME (defaulting to the name of the Perl program, i.e.
the contents of Perl variable $0). If the SYNC argument is present and
true then an *XSynchronize()* call is done ensuring that X events are
processed synchronously (and thus slowly). This is there for completeness
and is only very occasionally useful for debugging errant X clients
(usually at a much lower level than Tk users will want).

Entering the main event loop
----------------------------

   The Perl method call

     $i->MainLoop;

   on the Tcl::Tk interpreter object enters the Tk event loop. You can
instead do `Tcl::Tk::MainLoop' or `Tcl::Tk->MainLoop' if you prefer.  You
can even do simply MainLoop if you import it from Tcl::Tk in the use
statement. Note that commands in the Tcl and Tcl::Tk extensions closely
follow the C interface names with leading Tcl_ or Tk_ removed.

Creating widgets
----------------

   If desired, widgets can be created and handled entirely by Tcl/Tk code
evaluated in the Tcl interpreter object $i (created above). However, there
is an additional way of creating widgets in the interpreter directly from
Perl. The names of the widgets (frame, toplevel, label etc.)  can be
imported as direct commands from the Tcl::Tk extension. For example, if
you have imported the label command then

     $l = label(".l", -text => "Hello world);

   executes the command

     $i->call("label", ".l", "-text", "Hello world);

   and hence gets Tcl to create a new label widget .l in your Tcl/Tk
interpreter. You can either import such commands one by one with, for
example,

     use Tcl::Tk qw(label canvas MainLoop winfo);

   or you can use the pre-defined Exporter tags *:widgets* and *:misc*.
The *:widgets* tag imports all the widget commands and the *:misc* tag
imports all non-widget commands (see the next section).

   Let's return to the creation of the label widget above. Since Tcl/Tk
creates a command ".l" in the interpreter and creating a similarly named
sub in Perl isn't a good idea, the Tcl::Tk extension provides a slightly
more convenient way of manipulating the widget. Instead of returning the
name of the new widget as a string, the above label command returns a Perl
reference to the widget's name, blessed into an almost empty class. Perl
method calls on the object are translated into commands for the Tcl/Tk
interpreter in a very simplistic fashion. For example, the Perl command

     $l->configure(-background => "green");

   is translated into the command

     $i->call($$l, "configure", "-background", "green");

   for execution in your Tcl/Tk interpreter. Notice that it simply
dereferences the object to find the widget name. There is no automagic
conversion that happens: if you use a Tcl command which wants a widget
pathname and you only have an object returned by `label()' (or `button()'
or `entry()' or whatever) then you must dereference it yourself.

Non-widget Tk commands
----------------------

   For convenience, the non-widget Tk commands (such as destroy, focus,
`wm', `winfo' and so on) are also available for export as Perl commands
and translate into into their Tcl equivalents for execution in your Tk/Tcl
interpreter. The names of the Perl commands are the same as their Tcl
equivalents except for two: Tcl's pack command becomes `tkpack' in Perl
and Tcl's bind command becomes `tkbind' in Perl. The arguments you pass to
any of these Perl commands are not touched by the Tcl parser: each Perl
argument is passed as a separate argument to the Tcl command.

AUTHOR
------

   Malcolm Beattie, mbeattie@sable.ox.ac.uk

write out TeX's DVI (DeVice Independent) file
*********************************************

NAME
====

   TeX::DVI - write out TeX's DVI (DeVice Independent) file

SYNOPSIS
========

     use TeX::DVI;
     use Font::TFM;

     my $dvi = new TeX::DVI "texput.dvi";
     my $font = new_at Font::TFM "cmr10", 12
     	or die "Error loading cmr10 at 12 pt: $Font::TFM::errstr\n";
     $dvi->preamble();
     $dvi->begin_page();
     $dvi->push();
     my $fn = $dvi->font_def($font);
     $dvi->font($fn);
     $dvi->word("difficulty");
     $dvi->hskip($font->space());
     $dvi->word("AVA");
     $dvi->black_box($font->em_width(), $font->x_height());
     $dvi->pop();
     $dvi->end_page();
     $dvi->postamble();
     $dvi->close();

DESCRIPTION
===========

   Method *TeX::DVI::new* creates a new DVI object in memory and opens the
output DVI file. After that, elements can be written into the file using
appropriate methods.

   These are the methods available on the *Font::TFM* object:

preamble, postamble, begin_page, end_page, push, pop
     Writes out appropriate command of the `.dvi' file.

font_def
     The parameter is a reference to a *Font::TFM* object. Info out of this
     object will be printed out. The method returns the internal number of
     the font in this `.dvi' file.

font
     Writes out the font_sel command, the parametr is the number returned
     by font_def.

hskip, vskip
     Skips.

black_box
     Creates a black box, can be used for hrules and vrules.

special
     Writes out the special command, one parameter is written as the
     command.

word
     Writes out a word given as the first parameter. The currently selected
     font is used to gather information about ligatures and kernings,
     that's why it's possible to say

          $dvi->word("difficulty");

          and the C<ffi> will be ligatured all right.

close
     Close the file.

BUGS
====

   The error handling is rather weak - the modul currently assumes you
know why you call the method you call.

VERSION
=======

   0.100

AUTHOR
======

   (c) 1996-1998 Jan Pazdziora, adelton@fi.muni.cz,
http://www.fi.muni.cz/~adelton/ at Faculty of Informatics, Masaryk
University in Brno, Czech Republic

SEE ALSO
========

   Font::TFM(3), TeX::DVI::Parse(3), perl(1).

parse TeX's DVI output file
***************************

NAME
====

   TeX::DVI::Parse - parse TeX's DVI output file

SYNOPSIS
========

     use TeX::DVI::Parse;
     my $dvi_parse = new TeX::DVI::Parse("test.dvi");
     $dvi_parse->parse();

DESCRIPTION
===========

   I have created this module on request from Mirka Misáková. She wanted
to do some post-processing on the DVI file and I said that it will be
better to parse the DVI file directly, instead of the output of the
*dvitype* program.

   As the result there is this module *TeX::DVI::Parse* that recognizes
all commands from the DVI file and for each command found it calls method
of appropriate name, if defined in the class.

   The example above is not very reasonable because the core
*TeX::DVI::Parse* module doesn't itself define any methods for the DVI
commands. You will probably want to inherit a new class and define the
functions yourself:

     packages My_Parse_DVI;
     use TeX::DVI::Parse;
     @ISA = qw( TeX::DVI::Parse );

     sub set_char
     	{
     	my ($self, $ord, $char) = @_;
     	## print the info or something;
     	}

   As an example there is class *TeX::DVI::Print* coming in this file, so
you can do

     use TeX::DVI::Parse;
     my $dvi_parse = new TeX::DVI::Print("test.dvi");
     $dvi_parse->parse();

   and get listing of DVI's content printed in (hopefully) readable form.

Methods
-------

   For creating new classes, a documentation of expected methods names and
their parameters is necessary, so here is the list. The names come from
the *dvitype* documentation and that is also the basic reference for the
meaning of the parameters. Note that each method receives as the first two
parameters *$self* and *$ord*, reference to the parsing object and the
byte value of the command as found in the DVI file.  These are mandatory
so only the other parameters to each method are listed below.

set_char - typeset character and shift right by its width
     *$char* - specifies the ordinal value of the character.

put_char - as set_char but without moving
     *$char* - ordinal value of the character.

set_rule - typeset black rectangle and shift to the right
     $height, $width - dimensions of the rectangle.

put_rule - as set_rule without moving
     $height, $width - dimensions of the rectangle.

nop - no operation
     no parameter

bop - begin of page
     *$number[0]* .. *$number[9]*, *$prev_page* - the ten numbers that
     specify the page, the pointer to the start of the previous page.

eop - end of page
     no parameter

push - push to the stack
     no parameter

pop - pop from the stack
     no parameter

right - move right
     $value - how much to move.

move_w, move_x, down, move_y, move_z - move position
     all take one parameter, $value.

fnt_def - define font
     $k, $c, $s, $d, *$a*, *$l*, $n - number of the font, checksum, scale
     factor, design size, length of the directory and length of the
     filename, name of the font.

fnt_num - select font
     $k - number of the font.

special - generic DVI primitive
     $k, $x - length of the special and its data.

preamble
     $i, $num, *$den*, *$mag*, $k, $x - ID of the format, numerator and
     denumerator of the multiplication fraction, magnification, length of
     the comment and comment.

post - postamble
     $p, $num, *$den*, *$mag*, *$l*, $u, $s, $t - pointer to the last
     page, the next three are as in preamble, maximal dimensions (*$l* and
     $u), maximal depth of the stack and the final page number.

post_post - post postamble
     $q, $i, *$dummy* - pointer to the postamble, ID and the last fill.

undefined_command - for byte that has no other meaning
     no parameter

VERSION
=======

   0.02

SEE ALSO
========

   Font::TFM(3), TeX::DVI(3), perl(1).

AUTHOR
======

   (c) 1997-1998 Jan Pazdziora, adelton@fi.muni.cz,
http://www.fi.muni.cz/~adelton/ at Faculty of Informatics, Masaryk
University in Brno, Czech Republic

hyphenate words using TeX's patterns
************************************

NAME
====

   TeX::Hyphen - hyphenate words using TeX's patterns

SYNOPSIS
========

     use TeX::Hyphen;
     my $hyp = new TeX::Hyphen "hyphen.tex";
     my $word = "representation";
     my @points = $hyp->hyphenate($word);
     print $hyp->visualize($word), "\n";

DESCRIPTION
===========

   Constructor new() creates a new Hyphen object and loads the file with
patterns into memory. Then you can ask it for hyphenation of a word by
calling a method of this object. If no file is specified, the default
Donald E. Knuth's `hyphen.tex', that is included in this module, is used
instead.

   Method hyphenate() returns list of places where the word can be
divided, so

     $hyp->visualize('representation')

   returns list (3, 5, 8, 10). Method visualize() can be used to show these
poins, so

     $hyp->visualize('representation')

     should give C<rep-re-sen-ta-tion>.

   Variables *$TeX::Hyphen::LEFTMIN* and *$TeX::Hyphen::RIGHTMIN* can be
used to restrict minimal starting and ending substring where it is not
possible to hyphenate. They both default to 2 but should be changed to
match the paratemers used to generate the patterns.

   Variable *$TeX::Hyphen::DEBUG* can be set to see some statistics and
processing.

   The file with hyphenation patterns may contain `\'' and `\v' accents,
used in the Czech (and other) languages.

CHANGES
=======

  1. trial Wed Nov  3 16:06:02 MET 1999 Parsing of patterns extended to
     allow other styles as well - Spanish pattern file provided by Adrian
     Perez Jorge.

  2. Fri Dec 11 10:58:01 MET 1998 Bug fixes concering LEFTMIN and RIGHTMIN
     values and use of exceptions (thanks go to Vladimir Volovich).

  3. Mon Jul 21 18:53:26 MET DST 1997 Exception table handling added -
     error spotted by Jon Orwant.

  4. Wed Jul  9 14:49:42 MET DST 1997 Added the default `hyphen.tex' into
     the module and possibility to call the constructior without argument
     to get this default pattern file.

  5. Wed Apr  9 15:41:32 MET DST 1997 Hash lookup made faster.

     Method TeX::Hyphen::visualize() only takes one argument, it calls
     hyphenate().

  6. Sun Feb 16 13:55:26 MET 1997 Hash lookup made faster.

     Original name *Hyphen* chaged to *TeX::Hyphen*.

VERSION
=======

   0.101

SEE ALSO
========

   perl(1).

AUTHOR
======

   (c) 1997, 1999 Jan Pazdziora, adelton@fi.muni.cz at Faculty of
Informatics, Masaryk University, Brno

a fast, flexible and extensible template processing system
**********************************************************

NAME
====

   Template Toolkit - a fast, flexible and extensible template processing
system

SYNOPSIS
========

     use Template;

     # some useful options (see below for full list)
     my $config = {
         INCLUDE_PATH => '/search/path',  # or list ref
         INTERPOLATE  => 1,               # expand "$var" in plain text
         POST_CHOMP   => 1,               # cleanup whitespace
         PRE_PROCESS  => 'header',        # prefix each template
         EVAL_PERL    => 1,               # evaluate Perl code blocks
     };

     # create Template object
     my $template = Template->new($config);

     # define template variables for replacement
     my $vars = {
         var1  => $value,
         var2  => \%hash,
         var3  => \@list,
         var4  => \&code,
         var5  => $object,
     };

     # specify input filename, or file handle, text reference, etc.
     my $input = 'myfile.html';

     # process input template, substituting variables
     $template->process($input, $vars)
         || die $template->error();

SUMMARY OF TEMPLATE DIRECTIVES
==============================

     GET       - evaluate and print a variable or value
     	      [%   GET variable %]    # 'GET' keyword is optional
                 [%       variable %]
                 [%       hash.key %]
                 [%         list.n %]
                 [%     code(args) %]
     	      [% obj.meth(args) %]
                 [%  "value: $var" %]

     CALL      - as above without printing result (e.g. call code)
     	      [%  CALL variable %]

     SET       - assign a value to a variable
     	      [% SET variable = value %]    # 'SET' also optional
                 [%     variable = other_variable
                        variable = 'literal text @ $100'
                        variable = "interpolated text: $var"
                        list     = [ val, val, val, val, ... ]
     		     list     = [ val..val ]
                        hash     = { var => val, var => val, ... }
                 %]

     DEFAULT   - as SET above, if variable(s) not set
                 [% DEFAULT variable = value %]

     INSERT    - insert a file without any processing
     	      [% INSERT legalese.txt %]

     INCLUDE   - process another template file/block, localising vars
                 [% INCLUDE template %]
                 [% INCLUDE template  var = val, ... %]

     PROCESS   - as above, without localising variables
                 [% PROCESS template %]
                 [% PROCESS template  var = val, ... %]

     WRAPPER   - process a template to enclose specified block
     	      [% WRAPPER template %]
     		 content
     	      [% END %]

     BLOCK     - define a named template block for INCLUDE, etc.
                 [% BLOCK template %]
                    content
     	      [% END %]

     FOREACH   - repeat block for each value in a list
     	      [% FOREACH variable = [ val, val, val ] %]
                 [% FOREACH variable = list %]
                 [% FOREACH list %]
                    content...
                    [% variable %]
                 [% END %]

     WHILE     - iterate while condition is true
                 [% WHILE condition %]
     	         content
     	      [% END %]

     IF / UNLESS / ELSIF / ELSE
     	    - process block if condition is true/false.
                 [% IF condition %]
                    content
     	      [% ELSIF condition %]
     		 content
     	      [% ELSE %]
     		 content
                 [% END %]

     [% UNLESS condition %]
        content
     [% # ELSIF/ELSE as per IF, above %]
     	         content
     [% END %]

     SWITCH / CASE
     	    - multi-way switch/case statement
     	      [% SWITCH variable %]
                 [% CASE val1 %]
                    content
                 [% CASE [ val2, val3 ] %]
                    content
                 [% CASE %]         # or [% CASE DEFAULT %]
                    content
                 [% END %]

     MACRO     - create a named macro for some other directive or block
                 [% MACRO name <directive> %]
     	      [% MACRO name(arg1, arg2) <directive> %]
     	      ...
     	      [% name %]
                 [% name(val1, val2) %]

     FILTER    - post-process block through a filter
                 [% FILTER name %]
                 [% FILTER name( params ) %]
                 [% FILTER alias = name( params ) %]
                    content
                 [% END %]

     USE       - load a "plugin" module (or any regular Perl module
                 with LOAD_PERL option)
                 [% USE name %]
                 [% USE name( params ) %]
                 [% USE var = name( params ) %]
                 ...
                 [% name.method %]
                 [% var.method %]

     PERL / RAWPERL
               - evaluate blocks of Perl code (requires EVAL_PERL option)
                 [% PERL %]
     		 # perl code goes here
     		 $stash->set('foo', 10);
     		 print "set 'foo' to ", $stash->get('foo'), "\n";
     		 print $context->include('footer', { var => $val });
                 [% END %]

     [% RAWPERL %]
                      # raw perl code goes here, no magic but fast.
        $output .= 'some output';
     [% END %]

     TRY / THROW / CATCH / FINAL
               - exception handling
     	      [% TRY %]
     		 content
                    [% THROW type info %]
     	      [% CATCH type %]
     		 catch content
                    [% error.type %] [% error.info %]
                 [% CATCH %]	# or [% CATCH DEFAULT %]
     		 content
                 [% FINAL %]
                    this block is always processed
                 [% END %]

     NEXT      - next item in a FOREACH/WHILE loop
                 [% NEXT %]

     BREAK     - break out of FOREACH/WHILE loop
                 [% BREAK %]

     RETURN    - stop processing current template
                 [% RETURN %]

     STOP      - stop processing all templates and return to caller
                 [% STOP %]

     COMMENT   - ignored and deleted
                 [% # this is a comment to the end of line
                    foo = 'bar'
                 %]

     [%# placing the '#' immediately inside the directive
         tag comments out the entire directive
     %]

     TAGS      - define new tag style or characters (default: [% %])
                 [% TAGS html %]
                 [% TAGS <!-- --> %]

VERSION
=======

   This is version 2.00-beta5 of the Template Toolkit.

   Please consult the Changes file for information about visible changes
in the Template Toolkit between releases.  The TODO file contains details
of known bugs, planned enhancements, features, fixes, etc.

   The latest version of the Template Toolkit can be downloaded from any
CPAN site in the directory:

     /modules/by-module/Template/

   For a list of CPAN sites, see:

     http://www.cpan.org/

   Information regarding interim and development versions is posted to the
templates mailing list and available from the Template Toolkit web site:

     http://www.template-toolkit.org/

DESCRIPTION
===========

   The Template Toolkit is a collection of modules which implement a fast,
flexible, powerful and extensible template processing system.  It was
originally designed and remains primarily useful for generating dynamic
web content, but it can be used equally well for processing any kind of
text documents.  This POD documentation is all generated using the
Template Toolkit batch mode utility `ttree', for example.

   At the simplest level it provides an easy way to process template
files, filling in embedded variable references with their equivalent
values.

     Dear [% name %],

     It has come to our attention that your account is in
     arrears to the sum of [% debt %].

     Please settle your account before [% deadline %] or we
     will be forced to revoke your Licence to Thrill.

     The Management.

   By default, template directives are embedded within the character
sequences '[%' ... '%]' but you can changes these and various other
options to configure how the Template Toolkit looks, feels and works.  You
can set the INTERPOLATE option, for example, if you prefer to embed your
variables in Perl style:

     Dear $name,

     It has come to our attention that your account is in
     arrears to the sum of $debt.
     ...

   The Template.pm module is the front end to the Template Toolkit,
providing access to the full range of functionality through a single
module with a simple interface.  It loads the other modules as required
and instantiates a default set of objects to handle subsequent template
processing requests.  Configuration parameters may be passed to the
Template.pm constructor, new(), which are then used to configure the
underlying objects.

     use Template;

     my $tt = Template->new({
     	INCLUDE_PATH => '/usr/local/templates',
     	INTERPOLATE  => 1,
     }) || die "$Template::ERROR\n";

   The Template object implements a process() method for processing
template files or text.  The name of the input template (or various other
sources) is passed as the first argument, followed by a reference to a
hash array of variable definitions for substitution in the template.

     my $vars = {
     	name     => 'Count Edward van Halen',
     	debt     => '3 riffs and a solo',
     	deadline => 'the next chorus',
     };

     $template->process('letters/overdrawn', $vars)
     	|| die $template->error(), "\n";

   The process() method returns true (1) on success and prints the
template output to STDOUT, by default.  On error, the process() method
returns false (undef).  The error() method can be called to retrieve
details of the error.

   A number of special directives are provided, such as INSERT, INCLUDE
and PROCESS, which allow content to be built up from smaller template
components.  This permits a modular approach to building a web site or
other content repository, promoting reusability, cross-site consistency,
ease of construction and subsequent maintenance.  Common elements such as
headers, footers, menu bars, tables, and so on, can be created as separate
template files which can then be processed into other documents as
required.  All defined variables are inherited by these templates along
with any additional "local" values specified.

     [% PROCESS header
          title = "The Cat Sat on the Mat"
     %]

     [% PROCESS menu %]

     The location of the missing feline has now been established.
     Thank you for your assistance.

     [% INSERT legal/disclaimer %]

     [% PROCESS footer %]

   You can also define a template as a BLOCK within the same file and
PROCESS it just like any other template file.  This can be invaluable for
building up repetitive elements such as tables, menus, etc.

     [% BLOCK tabrow %]
        <tr><td>[% name %]</td><td>[% email %]</td></tr>
     [% END %]

     <table>
     [% PROCESS tabrow name="tom"   email="tom@here.org"    %]
     [% PROCESS tabrow name="dick"  email="disk@there.org"  %]
     [% PROCESS tabrow name="larry" email="larry@where.org" %]
     </table>

   One of the key features that sets the Template Toolkit apart from other
template processors is the ability to bind template variables to any kind
of Perl data: scalars, lists, hash arrays, sub-routines and objects.

     my $vars = {
     	root   => 'http://here.com/there',
     	menu   => [ 'modules', 'authors', 'scripts' ],
     	client => {
     	    name => 'Doctor Joseph von Satriani',
     	    id   => 'JVSAT',
     	}
     	checkout => sub { my $total = shift; ...; return $something },
     	shopcart => My::Cool::Shopping::Cart->new(),
     };

   The Template Toolkit will automatically Do The Right Thing to access
the data in an appropriate manner to return some value which can then be
output.  The dot operator '.' is used to accesses into lists and hashes or
to call object methods.  The FOREACH directive is provided for iterating
through lists, and various logicial tests are available using directives
such as IF, UNLESS, ELSIF, ELSE, SWITCH, CASE, etc.

     [% FOREACH section = menu %]
        <a href="[% root %]/[% section %]/index.html">[% section %]</a>
     [% END %]

     <b>Client</a>: [% client.name %] (id: [% client.id %])

     [% IF shopcart.nitems %]
        Your shopping cart contains the following items:
        <ul>
        [% FOREACH item = shopcart.contents %]
     	  <li>[% item.name %] : [% item.qty %] @ [% item.price %]
        [% END %]
        </ul>

     [% checkout(shopcart.total) %]

     [% ELSE %]
        No items currently in shopping cart.
     [% END %]

   The Template Toolkit also provides a number of additional directives
for advanced processing and programmatical functionality.  It supports
output filters (FILTER), allows custom macros to be defined (MACRO), has a
fully-featured exception handling system (TRY, THROW, CATCH, FINAL) and
supports a plugin architecture (USE) which allows special plugin modules
and even regular Perl modules to be loaded and used with the minimum of
fuss.  The Template Toolkit is "just" a template processor but you can
trivially extend it to incorporate the functionality of any Perl module
you can get your hands on.  Thus, it is also a scalable and extensible
template framework, ideally suited for managing the presentation layer for
application servers, content management systems and other web applications.

   Rather than embedding Perl code or some other scripting language
directly into template documents, it encourages you to keep functional
components (i.e. Perl code) separate from presentation components (e.g.
HTML templates).  The template variables provide the interface between the
two layers, allowing data to be generated in code and then passed to a
template component for displaying (pipeline model) or for sub-routine or
object references to be bound to variables which can then be called from
the template as and when required (callback model).

   The directives that the Template Toolkit provide implement their own
mini programming language, but they're not really designed for serious,
general purpose programming.  Perl is a far more appropriate language for
that.  If you embed application logic (e.g. Perl or other scripting
language fragments) in HTML templates then you risk losing the clear
separation of concerns between functionality and presentation.  It becomes
harder to maintain the two elements in isolation and more difficult, if
not impossible, to reuse code or presentation elements by themselves.  It
is far better to write your application code in separate Perl modules,
libraries or scripts and then use templates to control how the resulting
data is presented as output.  Thus you should think of the Template
Toolkit language as a set of layout directives for displaying data, not
calculating it.

   Having said that, the Template Toolkit doesn't force you into one
approach or the other.  It attempts to be pragmatic rather than dogmatic
in allowing you to do whatever best gets the job done.  Thus, if you
enable the EVAL_PERL option then you can happily embed real Perl code in
your templates within PERL ... END directives.

   The Template Toolkit uses a fast YACC-like parser which compiles
templates into Perl code for maximum runtime efficiency.  It also has an
advanced caching mechanism which manages in-memory and on-disk (i.e.
persistant) versions of compiled templates.  The modules that comprise the
toolkit are highly configurable and the architecture around which they're
built is designed to be extensible.  The Template Toolkit provides a
powerful framework around which content creation and delivery systems can
be built while also providing a simple interface through the Template
front-end module for general use.

METHODS
=======

new(\%config)
-------------

   The new() constructor method (implemented by the Template::Base base
class) instantiates a new Template object.  A reference to a hash array of
configuration items may be passed as a parameter.

     my $tt = Template->new({
     	INCLUDE_PATH => '/usr/local/templates',
     	EVAL_PERL    => 1,
     }) || die $Template::ERROR, "\n";

   A reference to a new Template object is returned, or undef on error.
In the latter case, the error message can be retrieved by calling error()
as a class method (e.g. `Template->error()') or by examining the $ERROR
package variable directly (e.g. `$Template::ERROR').

     my $tt = Template->new(\%config)
         || die Template->error(), "\n";

     my $tt = Template->new(\%config)
         || die $Template::ERROR, "\n";

   For convenience, configuration items may also be specified as a list of
items instead of a hash array reference.  These are automatically folded
into a hash array by the constructor.

     my $tt = Template->new(INCLUDE_PATH => '/tmp', POST_CHOMP => 1)
     	|| die $Template::ERROR, "\n";

process($template, \%vars, $output)
-----------------------------------

   The process() method is called to process a template.  The first
parameter indicates the input template as one of: a filename relative to
INCLUDE_PATH, if defined; a reference to a text string containing the
template text; or a file handle reference (e.g. IO::Handle or sub-class)
or GLOB (e.g. \*STDIN), from which the template can be read.  A reference
to a hash array may be passed as the second parameter, containing
definitions of template variables.

     $text = "[% INCLUDE header %]\nHello world!\n[% INCLUDE footer %]";

     $tt->process('welcome.tt2')
         || die $tt->error(), "\n";

     $tt->process(\$text)
         || die $tt->error(), "\n";

     $tt->process(\*DATA)
         || die $tt->error(), "\n";

     __END__
     [% INCLUDE header %]
     This is a template defined in the __END__ section which is
     accessible via the DATA "file handle".
     [% INCLUDE footer %]

   By default, the processed template output is printed to STDOUT.  The
process() method then returns 1 to indicate success.  A third parameter
may be passed to the process() method to specify a different output
location.  This value may be one of: a plain string indicating a filename
which will be opened (relative to OUTPUT_PATH, if defined) and the output
written to; a file GLOB opened ready for output; a reference to a scalar
(e.g. a text string) to which output/error is appended; a reference to a
subroutine which is called, passing the output as a parameter; or any
object reference which implements a 'print' method (e.g. IO::Handle,
Apache::Request, etc.) which will be called, passing the generated output
as a parameter.

   Examples:

     $tt->process('welcome.tt2', $vars, 'welcome.html')
         || die $tt->error(), "\n";

     $tt->process('welcome.tt2', $vars,
     		 sub { my $output = shift; print $output })
         || die $tt->error(), "\n";

     my $output = '';

     $tt->process('welcome.tt2', $vars, \$output)
         || die $tt->error(), "\n";

     print "output: $output\n";

   In an Apache/mod_perl handler:

     sub handler {
     	my $r    = shift;
     	my $file = $r->path_info();

     my $tt   = Template->new();
     	my $vars = { ... }

     # direct output to Apache::Request via $r->print($output)
     $tt->process($file, $vars, $r) || do {
         $r->log_reason($tt->error());
         return SERVER_ERROR;
     };

     return OK;
         }

   The OUTPUT configuration item can be used to specify a default output
location other than \*STDOUT.  The OUTPUT_PATH specifies a directory which
should be prefixed to all output locations specified as filenames.

     my $tt = Template->new({
     	OUTPUT      => sub { ... },       # default
     	OUTPUT_PATH => '/tmp',
     	...
     }) || die Template->error(), "\n";

     # use default OUTPUT (sub is called)
     $tt->process('welcome.tt2', $vars)
         || die $tt->error(), "\n";

     # write file to '/tmp/welcome.html'
     $tt->process('welcome.tt2', $vars, 'welcome.html')
         || die $tt->error(), "\n";

   The process() method returns 1 on success or undef on error.  The error
message generated in the latter case can be retrieved by calling the
error() method.  See also `CONFIGURATION OPTIONS' in this node which
describes how error handling may be further customised.

error()
-------

   When called as a class method, it returns the value of the $ERROR
package variable.  Thus, the following are equivalent.

     my $tt = Template->new()
         || die Template->error(), "\n";

     my $tt = Template->new()
         || die $Template::ERROR, "\n";

   When called as an object method, it returns the value of the internal
_ERROR variable, as set by an error condition in a previous call to
process().

     $tt->process('welcome.tt2')
         || die $tt->error(), "\n";

   Errors are represented in the Template Toolkit by objects of the
Template::Exception class.  The error() object method will generally
return an object of this class although there may be a few cases where
strings are returned (these should soon be "fixed" to also return
exception objects).  The type() and info() methods can be used to retrieve
the error type and information string, respectively.  The as_string()
method can be called to return a string of the form "$type - $info".  This
method is also overloaded onto the stringification operator allowing the
object reference itself to be printed to return the formatted error string.

     $tt->process('somefile') || do {
     	my $error = $tt->error();
     	print "error type: ", $error->type(), "\n";
     	print "error info: ", $error->info(), "\n";
     	print $error, "\n";
     };

service()
---------

   The Template module delegates most of the effort of processing templates
to an underlying Template::Service object.  This method returns a reference
to that object.

context()
---------

   The Template::Service module uses a core Template::Context object for
runtime processing of templates.  This method returns a reference to that
object and is equivalent to $template->service->context();

TEMPLATE SYNTAX
===============

   By default, template directives are embedded within the character
sequences '[%' and '%]'.  e.g.

     [% PROCESS header %]

     <h1>Hello World!</h1>
     <a href="[% page.next %]"><img src="[% icon.next %].gif"></a>

     [% PROCESS footer %]

   You can change the tag characters using the START_TAG, END_TAG and
TAG_STYLE configuration options.  You can also use the TAGS directive to
define a new tag style for the current template file.

   Directives may be embedded anywhere in a line of text and can be split
across several lines.  Insignificant whitespace is generally ignored
within the directive.

     [% INCLUDE header
        title = 'Hello World'
        bgcol = '#ffffff'
     %]

     [%INCLUDE menu align='right'%]

     Name: [% name %]  ([%id%])

   You can also set the INTERPOLATE option to allow simple variable
references to be embedded directly in templates, prefixed by a '$'.

     # INTERPOLATE => 0
     <td>[% name %]</td>  <td>[% email %]</td>

     # INTERPOLATE => 1
     <td>$name</td>  <td>$email</td>

   The '#' character is used to indicate comments within a directive.
When placed immediately inside the opening directive tag, it causes the
entire directive to be ignored.

     [%# this entire directive is ignored no
         matter how many lines it wraps onto
     %]

   In any other position, it causes the remainder of the current line to
be treated as a comment.

     [% # this is a comment
        theta = 20      # so is this
        rho   = 30      # <aol>me too!</aol>
     %]

   You can add '-' or '+' to the immediate start or end of a directive tag
to control the whitespace chomping options.  See the PRE_CHOMP and
POST_CHOMP options for further details.

     [% BLOCK foo -%]		# remove trailing newline
     This is block foo
     [%- END %]			# remove leading newline

   The simplest directives are GET and SET which retrieve and update
variable values respectively.  The GET and SET keywords are actually
optional as the parser is smart enough to see them for what they really
are.  Thus, you'll generally see:

     [% SET foo = 10 %]
     [% GET foo %]

   written as:

     [% foo = 10 %]
     [% foo %]

   You can also express simple logical statements as implicit GET
directives:

     [% title or template.title or 'Default Title' %]

     [% mode == 'graphics' ? "Graphics Mode Enabled" : "Text Mode" %]

   All other directives should start with a keyword specified in UPPER
CASE (but see the ANYCASE option).  All directives keywords are in UPPER
CASE to make them visually distinctive and to distinguish them from
variables of the same name but different case.  It is perfectly valid, for
example, to define a variable called 'stop' which is entirely separate
from the STOP directive.

     [% stop = 'Clackett Lane Bus Depot' %]

     The bus will next stop at [% stop %]    # variable

     [% STOP %]                              # directive

   Directives such as FOREACH, WHILE, BLOCK, FILTER, etc., mark the start
of a block which may contain text or other directives up to the
appropriate END directive.  Blocks may be nested indefinately.  The IF,
UNLESS, ELSIF and ELSE directives also define blocks and may be grouped
together in the usual manner.

     [% FOREACH item = [ 'foo' 'bar' 'baz' ] %]
        * Item: [% item %]
     [% END %]

     [% BLOCK footer %]
        Copyright 2000 [% me %]
        [% INCLUDE company/logo %]
     [% END %]

     [% IF foo %]
        [% FOREACH thing = foo.things %]
     	  [% thing %]
        [% END %]
     [% ELSIF bar %]
        [% INCLUDE barinfo %]
     [% ELSE %]
        do nothing...
     [% END %]

   Block directives can also be used in a convenient side-effect notation.

     [% INCLUDE userinfo FOREACH user = userlist %]

     [% INCLUDE debugtxt msg="file: $error.info"
          IF debugging %]

     [% "Danger Will Robinson" IF atrisk %]

   versus:

     [% FOREACH user = userlist %]
        [% INCLUDE userinfo %]
     [% END %]

     [% IF debugging %]
        [% INCLUDE debugtxt msg="file: $error.info" %]
     [% END %]

     [% IF atrisk %]
     Danger Will Robinson
     [% END %]

   Multiple FILTER directives can be chained together in sequence.  They
are called in the order defined, piping the output of one into the input
of the next.

     [% PROCESS somefile FILTER truncate(100) FILTER html %]

   The pipe character, '|', can also be used as an alias for FILTER.

     [% PROCESS somefile | truncate(100) | html %]

   The output of a directive can be captured by simply assigning the
directive to a variable.

     [% headtext = PROCESS header title="Hello World" %]

     [% people = PROCESS userinfo FOREACH user = userlist %]

   Multiple directives can be included within a single tag when delimited
by semi-colons, ';'.  Note however that the TAGS directive must always be
specified in a tag by itself.

     [% IF title;
           INCLUDE header;
        ELSE;
     	  INCLUDE other/header  title="Some Other Title";
        END
     %]

   versus

     [% IF title %]
        [% INCLUDE header %]
     [% ELSE %]
        [% INCLUDE other/header  title="Some Other Title" %]
     [% END %]

TEMPLATE VARIABLES
==================

   A reference to a hash array may be passed as the second argument to the
process() method, containing definitions of template variables.  The
VARIABLES (a.k.a. PRE_DEFINE) option can also be used to pre-define
variables for all templates processed by the object.

     my $tt = Template->new({
     	VARIABLES => {
     	    version => 3.14,
     	    release => 'Sahara',
     	},
     });

     my $vars = {
     	serial_no => 271828,
     };

     $tt->process('myfile', $vars);

   'myfile':

     This is version [% version %] ([% release %]).
     Serial number: [% serial_no %]

   output:

     This is version 3.14 (Sahara)
     Serial number: 271828

   Variable names may contain any alphanumeric characters or underscores.
They may be lower, upper or mixed case although the usual convention is to
use lower case.  The case *is* significant however, and 'foo', 'Foo' and
'FOO' are all different variables.  Upper case variable names are
permitted, but not recommended due to a possible conflict with an existing
or future reserved word.  As of version 2.00, these are:

     GET CALL SET DEFAULT INSERT INCLUDE PROCESS WRAPPER
     IF UNLESS ELSE ELSIF FOR FORNEXT WHILE SWITCH CASE
     USE PLUGIN FILTER MACRO PERL RAWPERL BLOCK META
     TRY THROW CATCH FINAL BREAK RETURN STOP CLEAR
     TO STEP AND OR NOT MOD DIV END

   The variable values may be of virtually any Perl type, including simple
scalars, references to lists, hash arrays, subroutines or objects.  The
Template Toolkit will automatically apply the correct procedure to
accessing these values as they are used in the template.

   Example:

     my $vars = {
     	article => 'The Third Shoe',
     	person  => {
     	    id    => 314,
     	    name  => 'Mr. Blue',
     	    email => 'blue@nowhere.org',
     	},
     	primes  => [ 2, 3, 5, 7, 11, 13 ],
     	wizard  => sub { return join(' ', 'Abracadabra!', @_) },
     	cgi     => CGI->new('mode=submit&debug=1'),
     };

   template:

     [% article %]

     [% person.id %]: [% person.name %] <[% person.email %]>

     [% primes.first %] - [% primes.last %], including [% primes.3 %]
     [% primes.size %] prime numbers: [% primes.join(', ') %]

     [% wizard %]
     [% wizard('Hocus Pocus!') %]

     [% cgi.param('mode') %]

   output:

     The Third Shoe

     314: Mr. Blue <blue@nowhere.org>

     2 - 13, including 7
     6 prime numbers: 2, 3, 5, 7, 11, 13

     Abracadabra!
     Abracadabra! Hocus Pocus!

     submit

Scalar Values
-------------

   Regular scalar variables are accessed by simply specifying their name.
As these are just entries in the top-level variable hash they can be
considered special cases of hash array referencing as described below,
with the main namespace hash automatically implied.

     [% article %]

Hash Array References
---------------------

   Members of hash arrays are accessed by specifying the hash reference
and key separated by the dot '.' operator.

     my $vars = {
       	'home' => 'http://www.myserver.com/homepage.html',
       	'page' => {
       	    'this' => 'mypage.html',
       	    'next' => 'nextpage.html',
       	    'prev' => 'prevpage.html',
       	},
     };

     template:

     <a href="[% home %]">Home</a>
     <a href="[% page.prev %]">Previous Page</a>
     <a href="[% page.next %]">Next Page</a>

   output:

     <a href="http://www.myserver.com/homepage.html">Home</a>
     <a href="prevpage.html">Previous Page</a>
     <a href="nextpage.html">Next Page</a>

   Any key in a hash which starts with a '_' or '.' character will be
considered private and cannot be evaluated or updated from within a
template.  The undefined value will be returned for any such variable
accessed which the Template Toolkit will silently ignore (unless the DEBUG
option is enabled).

     my $vars = {
     	message => 'Hello World!',
     	_secret => "On the Internet, no-one knows you're a dog",
     	thing   => {
     	     public  => 123,
     	    _private => 456,
     	   '.hidden' => 789,
     	},
     };

   template:

     [% message %]		# outputs "Hello World!"
     [% _secret %]               # no output
     [% thing.public %]          # outputs "123"
     [% thing._private %]        # no output
     [% thing..hidden %]         # ERROR: unexpected token (..)

   To access a hash entry using a key stored in another variable, prefix
the key variable with '$' to have it interpolated before use (see
`Variable Interpolation' in this node).

     [% pagename = 'next' %]
     [% page.$pagename %]       # same as [% page.next %]

   When you assign to a variable that contains multiple namespace elements
(i.e. it has one or more '.' characters in the name), any hashes required
to represent intermediate namespaces will be created automatically.  In
this following example, the 'product' variable automatically springs into
life as a hash array unless otherwise defined.

     [% product.id    = 'XYZ-2000'
        product.desc  = 'Bogon Generator'
        product.price = 666
     %]

     The [% product.id %] [% product.desc %]
     costs $[% product.price %].00

   output:

     The XYZ-2000 Bogon Generator
     costs $666.00

   You can use Perl's familiar '{' ... '}' construct to explicitly create
a hash and assign it to a variable.  Note that commas are optional between
key/value pairs and '=' can be used in place of '=>'.

     [% product = {
       	 id    => 'XYZ-2000',
       	 desc  => 'Bogon Generator',
       	 price => 666,
        }
     %]

List References
---------------

   Items in lists are also accessed by use of the dot operator.

     my $vars = {
       	'people' => [ 'Tom', 'Dick', 'Larry' ],
     };

   template:

     [% people.0 %]			# Tom
     [% people.1 %]			# Dick
     [% people.2 %]			# Larry

   The FOREACH directive can be used to iterate through items in a list.

     [% FOREACH person = people %]
     Hello [% person %]
     [% END %]

   output:

     Hello Tom
     Hello Dick
     Hello Larry

   Lists can be constructed in-situ using the regular anonymous list '['
... ']' construct.  Commas between items are optional.

     [% cols = [ 'red', 'green', 'blue' ] %]

     [% FOREACH c = cols %]
        ...

   or:

     [% FOREACH c = [ 'red', 'green', 'blue' ] %]
        ...

   You can also create simple numerical sequences using the familiar '..'
operator:

     [% n = [ 1 .. 4 ] %]    # n is [ 1, 2, 3, 4 ]

     [% x = 4
        y = 8
        z = [x..y]           # z is [ 4, 5, 6, 7, 8 ]
     %]

Subroutines
-----------

   Template variables can contain references to Perl subroutines.  When
the variable is used, the Template Toolkit will automatically call the
subroutine, passing any additional arguments specified.  The return value
from the subroutine is used as the variable value and inserted into the
document output.

     my $vars = {
     	wizard  => sub { return join(' ', 'Abracadabra!', @_) },
     };

   template:

     [% wizard %]			# Abracadabra!
     [% wizard('Hocus Pocus!') %]	# Abracadabra! Hocus Pocus!

Objects
-------

   Template variables can also contain references to Perl objects.
Methods are called using the dot operator to specify the method against
the object variable.  Additional arguments can be specified as with
subroutines.

     use CGI;

     ...

     my $vars = {
     	# hard coded CGI params for purpose of example
     	cgi  => CGI->new('mode=submit&debug=1'),
     };

   template:

     [% FOREACH p = cgi.param %]		# returns list of param keys
     [% p %] => [% cgi.param(p) %]	# fetch each param value
     [% END %]

   output:

     mode => submit
     debug => 1

   Object methods can also be called as lvalues.  That is, they can appear
on the left side of an assignment.  The method will be called passing the
assigning value as an argument.

     [% myobj.method = 10 %]

   equivalent to:

     [% myobj.method(10) %]

Parameters and Return Values
----------------------------

   Subroutines and methods will be passed any arguments specified in the
template.  Any template variables in the argument list will first be
evaluated and their resultant values passed to the code.

     my $vars = {
     	mycode => sub { return 'received ' . join(', ', @_) },
     };

   template:

     [% foo = 10 %]
     [% mycode(foo, 20) %]		# received 10, 20

   Named parameters may also be specified.  These are automatically
collected into a single hash array which is passed by reference as the last
parameter to the sub-routine.  Named parameters can be specified using
either '=>' or '=' and can appear anywhere in the argument list.

     my $vars = {
     	myjoin => \&myjoin,
     };

     sub myjoin {
     	# look for hash ref as last argument
     	my $params = ref $_[-1] eq 'HASH' ? pop : { };
     	return join($params->{ joint } || ' + ', @_);
     }

   template:

     [% myjoin(10, 20, 30) %]
     [% myjoin(10, 20, 30, joint = ' - ' %]
     [% myjoin(joint => ' * ', 10, 20, 30 %]

   output:

     10 + 20 + 30
     10 - 20 - 30
     10 * 20 * 30

   Parenthesised parameters may be added to any element of a variable, not
just those that are bound to code or object methods.  At present,
parameters will be ignored if the variable isn't "callable" but are
supported for future extensions.  Think of them as "hints" to that
variable, rather than just arguments passed to a function.

     [% r = 'Romeo' %]
     [% r(100, 99, s, t, v) %]		# outputs "Romeo"

   User code should return a value for the variable it represents. This
can be any of the Perl data types described above: a scalar, or reference
to a list, hash, subroutine or object.  Where code returns a list of
multiple values the items will automatically be folded into a list
reference which can be accessed as per normal.

     my $vars = {
     	# either is OK, first is recommended
     	items1 => sub { return [ 'foo', 'bar', 'baz' ] },
     	items2 => sub { return ( 'foo', 'bar', 'baz' ) },
     };

   template:

     [% FOREACH i = items1 %]
        ...
     [% END %]

     [% FOREACH i = items2 %]
        ...
     [% END %]

Error Handling
--------------

   Errors can be reported from user code by calling die().  Errors raised
in this way are caught by the Template Toolkit and converted to structured
exceptions which can be handled from within the template.  A reference to
the exception object is then available as the 'error' variable.

     my $vars = {
     	barf => sub {
     	    die "a sick error has occured\n";
     	},
     };

   template:

     [% TRY %]
        [% barf %]	    # calls sub which throws error via die()
     [% CATCH %]
        [% error.info %]	    # outputs "a sick error has occured\n"
     [% END %]

   Error messages thrown via die() are converted to exceptions of type
'undef'.  Exceptions of user-defined types can be thrown by calling die()
with a reference to a Template::Exception object.

     use Template::Exception;

     ...

     my $vars = {
     	login => sub {
     	    ...
     	    die Template::Exception->new('badpwd',
     					 'password too silly');
     	},
     };

   template:

     [% TRY %]
        [% login %]
     [% CATCH badpwd %]
        Bad password: [% error.info %]
     [% CATCH %]
        Some other '[% error.type %]' error: [% error.info %]
     [% END %]

   The exception types 'stop' and 'return' are used to implement the STOP
and RETURN directives.  Throwing an exception as:

     die Template::Exception->new('stop');

   has the same effect as the directive:

     [% STOP %]

   Subroutines and methods can also raise errors by returning a list or
reference to a list containing the undefined value (undef) followed by an
exception object or error message.  This is supported for backwards
compatability with version 1 but may be deprecated in some future version.

     my $vars = {
     	# currently equivalent
     	barf => sub {
     	    die "I'm sorry Dave, I can't do that";
     	},
     	yack => sub {
     	    return (undef, "I'm sorry Dave, I can't do that");
     	},
     };

Virtual Variable Methods
------------------------

   The Template Toolkit provides virtual methods for manipulating variable
values.  The following methods can be called against any scalar value:

defined
     Returns true if the value is defined.

          [% user = get_user(uid) IF uid.defined %]

length
     Returns the length of the string representation of the item:

          [% IF password.length < 8 %]
             Password too short, dumbass!
          [% END %]

split
     Calls Perl's split() function to split a string into a list of
     strings.

          [% FOREACH dir = mypath.split(':') %]
             [% dir %]
          [% END %]

   The following can be called against hash references.

keys, values, each
     The regular hash operators returning lists of keys, values or both.
     Note how we use a '$' prefix on the 'key' variable in this example to
     have it interpolated (i.e. replaced with its value) before use.

          [% FOREACH key = product.keys %]
             [% key %] => [% product.$key %]
          [% END %]

import
     The import method can be called on a hash array to import the contents
     of another hash array.

          [% hash1 = {
          	   foo => 'Foo',
                 bar => 'Bar',
             }
             hash2 = {
                 wiz => 'Wiz',
                 woz => 'Woz',
             }
          %]

          [% hash1.import(hash2) %]
          [% hash1.wiz %]			# Wiz

     You can also call the import() method by itself to import a hash array
     into the current namespace hash.

          [% user = { id => 'lwall', name => 'Larry Wall' } %]
          [% import(user) %]
          [% id %]: [% name %]		# lwall: Larry Wall

   The following virtual methods are provided for lists:

first, last
     Returns the first/last item in the list.

          [% results.first %] to [% results.last %]

size, max
     Returns the size of a list (number of elements) and the maximum index
     number (size - 1), respectively.

          [% results.size %] search results matched your query

reverse
     Returns the items of the list in reverse order.

          [% FOREACH s = scores.reverse %]
             ...
          [% END %]

join
     Joins the items in the list into a single string, using Perl's join
     function.

          [% items.join(', ') %]

sort, nsort
     Returns the items in alpha (sort) or numerical (nsort) order.

          [% library = books.sort %]

     Where the list contains hash array references, a hash key can be
     passed as an argument to specify the sort field.

          [% library = books.sort('author') %]

   You can also define your own virtual methods for scalars, lists and hash
arrays.  The Template::Stash package variables $SCALAR_OPS, $LIST_OPS and
$HASH_OPS are references to hash arrays that define these virtual methods.
HASH_OPS and LIST_OPS methods are subroutines that accept a hash/list
reference as the first item.  SCALAR_OPS are subroutines that accept a
scalar value as the first item.  Any other arguments specified when the
method is called will be passed to the subroutine.

     # define list method to return new list of odd numbers only
     $Template::Stash::LIST_OPS->{ odd } = sub {
     	my $list = shift;
     	return [ grep { $_ % 2 } @$list ];
     };

   template:

     [% primes = [ 2, 3, 5, 7, 9 %] %]
     [% primes.odd.join(', ') %]		# 3, 5, 7, 9

   See also the examples in the t/vmeth.t test script.

Compound Variables
------------------

   Compound 'dotted' variables may contain any number of separate
elements.  Each element may evaluate to any of the permitted variable
types and the processor will then correctly use this value to evaluate the
rest of the variable.  Arguments may be passed to any of the intermediate
elements.

     [% myorg.people.sort('surname').first.fullname %]

   Intermediate variables may be used and will behave entirely as expected.

     [% sorted = myorg.people.sort('surname') %]
     [% sorted.first.fullname %]

   This simplified dotted notation has the benefit of hiding the
implementation details of your data.  For example, you could implement a
data structure as a hash array one day and then change it to an object the
next without requiring any change to the templates.

Variable Interpolation
----------------------

   The Template Toolkit uses '$' consistently to indicate that a variable
should be interpolated in position.  Most frequently, you see this in
double-quoted strings:

     [% fullname = "$honorific $firstname $surname" %]

   Or embedded in plain text when the INTERPOLATE option is set:

     Dear $honorific $firstname $surname,

   The same rules apply within directives.  If a variable is prefixed with
a '$' then it is replaced with its value before being used.  The most
common use is to retrieve an element from a hash where the key is stored
in a variable.

     [% uid = 'abw' %]
     [% userlist.$uid %]		    # same as 'userlist.abw'

   Curly braces can be used to delimit interpolated variable names where
necessary.

     [% userlist.${me.id}.name %]

   Directives such as INCLUDE, PROCESS, etc., that accept a template name
as the first argument, will automatically quote it for convenience.

     [% INCLUDE foo/bar.txt %]

   equivalent to:

     [% INCLUDE "foo/bar.txt" %]

   To INCLUDE a template whose name is stored in a variable, simply prefix
the variable name with '$' to have it interpolated.

     [% myfile = 'header' %]
     [% INCLUDE $myfile %]

   equivalent to:

     [% INCLUDE header %]

   Note also that a variable containing a reference to a Template::Document
object can also be processed in this way.

     my $vars = {
     	header => Template::Document->new({ ... }),
     };

   template:

     [% INCLUDE $header %]

Local and Global Variables
--------------------------

   Any simple variables that you create, or any changes you make to
existing variables, will only persist while the template is being
processed.  The top-level variable hash is copied before processing begins
and any changes to variables are made in this copy, leaving the original
intact.  The same thing happens when you INCLUDE another template.  The
current namespace hash is cloned to prevent any variable changes made in
the included template from interfering with existing variables.  The
PROCESS option bypasses the localisation step altogether making it
slightly faster, but requiring greater attention to the possibility of
side effects caused by creating or changing any variables within the
PROCESSed template.

     [% BLOCK change_name %]
        [% name = 'bar' %]
     [% END %]

     [% name = 'foo' %]
     [% INCLUDE change_name %]
     [% name %]			    # foo
     [% PROCESS change_name %]
     [% name %]			    # bar

   Dotted compound variables behave slightly differently because the
localisation process is only skin deep.  The current variable namespace
hash is copied, but no attempt is made to perform a deep-copy of other
structures within it (hashes, arrays, objects, etc).  A variable
referencing a hash, for example, will be copied to create a new reference
but which points to the same hash.  Thus, the general rule is that simple
variables (undotted variables) are localised, but existing complex
structures (dotted variables) are not.

     [% BLOCK all_change %]
        [% x = 20 %]		    # changes copy
        [% y.z = 'zulu' %]	    # changes original
     [% END %]

     [% x = 10
        y = { z => 'zebra' }
     %]
     [% INCLUDE all_change %]
     [% x %]			    # still '10'
     [% y.z %]			    # now 'zulu'

   If you create a complex structure such as a hash or list reference
within a local template context then it will cease to exist when the
template is finished processing.

     [% BLOCK new_stuff %]
        [% # define a new 'y' hash array in local context
           y = { z => 'zulu' }
        %]
     [% END %]

     [% x = 10 %]
     [% INCLUDE new_stuff %]
     [% x %]			    # outputs '10'
     [% y %]			    # nothing, y is undefined

   Similarly, if you update an element of a complex variable which
*doesn't* already exists then a hash will be created automatically and
deleted again at the end of the block.

     [% BLOCK new_stuff %]
        [% y.z = 'zulu' %]
     [% END %]

   However, if the hash *does* already exist then you will modify the
original with permanent effect.  To avoid potential confusion, it is
recommended that you don't update elements of complex variables from
within blocks or templates included by another.

   If you want to create or update truly global variables then you can use
the 'global' namespace.  This is a hash array automatically created in the
top-level namespace which all templates, localised or otherwise see the
same reference to.  Changes made to variables within this hash are visible
across all templates.

     [% global.version = 123 %]

Special Variables
-----------------

   A number of special variables are automatically defined by the Template
Toolkit.

template
     The 'template' variable contains a reference to the main template
     being processed, in the form of a Template::Document object.  This
     variable is correctly defined within PRE_PROCESS, PROCESS and
     POST_PROCESS templates, allowing standard headers, footers, etc., to
     access metadata items from the main template.  The 'name' and
     'modtime' metadata items are automatically provided, giving the
     template name and modification time in seconds since the epoch.

     Note that the 'template' variable always references the top-level
     template, even when processing other template components via INCLUDE,
     PROCESS, etc.

component
     The 'component' variable is like 'template' but always contains a
     reference to the current, innermost template component being
     processed.  In the main template, the 'template' and 'component'
     variable will reference the same Template::Document object.  In any
     other template component called from the main template, the
     'template' variable will remain unchanged, but 'component' will
     contain a new reference to the current component.

     This example should demonstrate the difference:

          $template->process('foo')
          	|| die $template->error(), "\n";

     'foo':

          [% template.name %]		    # foo
          [% component.name %]	    # foo
          [% PROCESS footer %]

     'footer':

          [% template.name %]		    # foo
          [% component.name %]            # footer

error
     Within a CATCH block, the 'error' variable contains a reference to the
     Template::Exception object thrown from within the TRY block.  The
     'type' and 'info' methods can be called or the variable itself can be
     printed for automatic stringification into a message of the form
     "$type error - $info".  See Template/Exception,
     for further details.

          [% TRY %]
             ...
          [% CATCH %]
             [% error %]
          [% END %]

TEMPLATE DIRECTIVES
===================

Accessing and Updating Template Variables
-----------------------------------------

GET
     The GET directive retrieves and outputs the value of the named
     variable.

          [% GET foo %]

     The GET keyword is optional.  A variable can be specified in a
     directive tag by itself.

          [% foo %]

     The variable may take any of the forms described above:

          [% foo %]
          [% bar.baz %]
          [% biz.baz(10) %]
          ...etc...

     You can also specify expressions using the logical (and, or, not, ?:)
     and mathematic operators (+ - * / % mod div).

          [% template.title or default.title %]

          [% score * 100 %]

          [% order.nitems ? checkout(order.total) : 'no items' %]

     The 'div' operator returns the integer result of division.  Both '%'
     and 'mod' return the modulus (i.e. remainder) of division.  'mod' is
     provided as an alias for '%' for backwards compatability with version
     1.

          [% 15 / 6 %]	    # 2.5
          [% 15 div 6 %]	    # 2
          [% 15 mod 6 %]	    # 3

CALL
     The CALL directive is similar to GET in evaluating the variable named,
     but doesn't print the result returned.  This can be useful when a
     variable is bound to a sub-routine or object method which you want to
     call but aren't interested in the value returned.

          [% CALL dbi.disconnect %]

          [% CALL inc_page_counter(page_count) %]

SET
     The SET directive allows you to assign new values to existing
     variables or create new temporary variables.

          [% SET title = 'Hello World' %]

     The SET keyword is also optional.

     [% title = 'Hello World' %]

     Variables may be assigned the values of other variables, unquoted
     numbers (digits), literal text ('single quotes') or quoted text
     ("double quotes").  In the latter case, any variable references within
     the text will be interpolated when the string is evaluated.  Variables
     should be prefixed by '$', using curly braces to explicitly scope the
     variable name where necessary.

          [% foo  = 'Foo'  %]               # literal value 'Foo'
          [% bar  =  foo   %]               # value of variable 'foo'
          [% cost = '$100' %]               # literal value '$100'
          [% item = "$bar: ${cost}.00" %]   # value "Foo: $100.00"

     Multiple variables may be assigned in the same directive and are
     evaluated in the order specified.  Thus, the above could have been
     written:

          [% foo  = 'Foo'
             bar  = foo
             cost = '$100'
             item = "$bar: ${cost}.00"
          %]

     Simple expressions can also be used, as per GET.

          [% ten    = 10
             twenty = 20
             thirty = twenty + ten
             forty  = 2 * twenty
             fifty  = 100 div 2
             six    = twenty mod 7
          %]

DEFAULT
     The DEFAULT directive is similar to SET but only updates variables
     that are currently undefined or have no "true" value (in the Perl
     sense).

          [% DEFAULT
             name = 'John Doe'
             id   = 'jdoe'
          %]

     This can be particularly useful in common template components to
     ensure that some sensible default are provided for otherwise
     undefined variables.

          [% DEFAULT
             title = 'Hello World'
             bgcol = '#ffffff'
          %]
          <html>
          <head>
          <title>[% title %]</title>
          </head>

          <body bgcolor="[% bgcol %]">

Processing Other Template Files and Blocks
------------------------------------------

INSERT
     The INSERT directive is used to insert the contents of an external
     file at the current position.

          [% INSERT myfile %]

     No attempt to parse or process the file is made.  The contents,
     possibly including any embedded template directives, are inserted
     intact.

     The filename specified should be relative to one of the INCLUDE_PATH
     directories.  Absolute (i.e. starting with /) and relative (i.e.
     starting with .) filenames may be used if the ABSOLUTE and RELATIVE
     options are set, respectively.  Both these options are disabled by
     default.

          my $template = Template->new({
          	INCLUDE_PATH => '/here:/there',
          });

          $template->process('myfile');

     'myfile':

          [% INSERT foo %]		# looks for /here/foo then /there/foo
          [% INSERT /etc/passwd %]	# file error: ABSOLUTE not set
          [% INSERT ../secret %]	# file error: RELATIVE not set

     For convenience, the filename does not need to be quoted as long as it
     contains only alphanumeric characters, underscores, dots or forward
     slashes.  Names containing any other characters should be quoted.

          [% INSERT misc/legalese.txt            %]
          [% INSERT 'dos98/Program Files/stupid' %]

     To evaluate a variable to specify a filename, you should explicitly
     prefix it with a '$' or use double-quoted string interpolation.

          [% language = 'en'
             legalese = 'misc/legalese.txt'
          %]

          [% INSERT $legalese %]		# 'misc/legalese.txt'
          [% INSERT "$language/$legalese" %]  # 'en/misc/legalese.txt'

INCLUDE
     The INCLUDE directive is used to process and include the output of
     another template file or block.

          [% INCLUDE header %]

     If a BLOCK of the specified name is defined in the same file, or in a
     file from which the current template has been called (i.e. a parent
     template) then it will be used in preference to any file of the same
     name.

          [% INCLUDE table %]		    # uses BLOCK defined below

          [% BLOCK table %]
             <table>
             ...
             </table>
          [% END %]

     If a BLOCK definition is not currently visible then the template name
     should be a file relative to one of the INCLUDE_PATH directories, or
     an absolute or relative file name if the ABSOLUTE/RELATIVE options are
     appropriately enabled.  The INCLUDE directive automatically quotes the
     filename specified, as per INSERT described above.  When a variable
     contains the name of the template for the INCLUDE directive, it should
     be explicitly prefixed by '$'.

          [% myheader = 'my/misc/header' %]
          [% INCLUDE  myheader %]              # 'myheader'
          [% INCLUDE $myheader %]		 # 'my/misc/header'

     Any template directives embedded within the file will be processed
     accordingly.  All variables currently defined will be visible and
     accessible from within the included template.

          [% title = 'Hello World' %]
          [% INCLUDE header %]
          <body>
          ...

     'header':     <html>     <title>[% title %]</title>

     output:     <html>     <title>Hello World</title>     <body>     ...

     Local variable definitions may be specified after the template name,
     temporarily masking any existing variables.  Insignificant whitespace
     is ignore within directives so you can add variable definitions on the
     same line, the next line or split across several line with comments
     interspersed, if you prefer.

          [% INCLUDE table %]

          [% INCLUDE table title="Active Projects" %]

          [% INCLUDE table
          	 title   = "Active Projects"
               bgcolor = "#ffffff"	# white
          	 border  = 2
          %]

     The INCLUDE directive localises (i.e. copies) all variables before
     processing the template.  Any changes made within the included
     template will not affect variables in the including template.

          [% foo = 10 %]

          foo is originally [% foo %]
          [% INCLUDE bar %]
          foo is still [% foo %]

          [% BLOCK bar %]
             foo was [% foo %]
             [% foo = 20 %]
             foo is now [% foo %]
          [% END %]

     output:     foo is originally 10        foo was 10        foo is now
     20     foo is still 10

     Technical Note: the localisation of the stash (that is, the process by
     which variables are copied before an INCLUDE to prevent being
     overwritten) is only skin deep.  The top-level variable namespace
     (hash) is copied, but no attempt is made to perform a deep-copy of
     other structures (hashes, arrays, objects, etc.)  Therefore, a 'foo'
     variable referencing a hash will be copied to create a new 'foo'
     variable but which points to the same hash array.  Thus, if you update
     compound variables (e.g. foo.bar) then you will change the original
     copy, regardless of any stash localisation.  If you're not worried
     about preserving variable values, or you trust the templates you're
     including then you might prefer to use the PROCESS directive which is
     faster by virtue of not performing any localisation.

PROCESS
     The PROCESS directive is similar to INCLUDE but does not perform any
     localisation of variables before processing the template.  Any changes
     made to variables within the included template will be visible in the
     including template.

          [% foo = 10 %]

          foo is [% foo %]
          [% PROCESS bar %]
          foo is [% foo %]

          [% BLOCK bar %]
             [% foo = 20 %]
             changed foo to [% foo %]
          [% END %]

     output:

          foo is 10
             changed foo to 20
          foo is 20

          [% INCLUDE table %]

     Parameters may be specified in the PROCESS directive, but these too
     will become visible changes to current variable values.

          [% foo = 10 %]
          foo is [% foo %]
          [% PROCESS bar
             foo = 20
          %]
          foo is [% foo %]

          [% BLOCK bar %]
             this is bar, foo is [% foo %]
          [% END %]

     output:

          foo is 10
             this is bar, foo is [% 20 %]
          foo is 20

     The PROCESS directive is slightly faster than INCLUDE because it
     avoids the need to localise (i.e. copy) the variable stash before
     processing the template.  As with INSERT and INCLUDE, the first
     parameter does not need to be quoted as long as it contains only
     alphanumeric characters, underscores, periods or forward slashes.  A
     '$' prefix can be used to explicitly indicate a variable which should
     be interpolated to provide the template name:

          [% myheader = 'my/misc/header' %]
          [% PROCESS  myheader %]              # 'myheader'
          [% PROCESS $myheader %]		 # 'my/misc/header'

WRAPPER
     It's not unusual to find yourself adding common headers and footers to
     pages or sub-sections within a page.  Something like this:

          [% INCLUDE section/header
             title = 'Quantum Mechanics'
          %]
             Quantum mechanics is a very interesting subject wish
             should prove easy for the layman to fully comprehend.
          [% INCLUDE section/footer %]

          [% INCLUDE section/header
             title = 'Desktop Nuclear Fusion for under $50'
          %]
             This describes a simple device which generates significant
             sustainable electrical power from common tap water by process
             of nuclear fusion.
          [% INCLUDE section/footer %]

     The individual template components being included might look like
     these:

     section/header:     <p>     <h2>[% title %]</h2>

     section/footer:     </p>

     The WRAPPER directive provides a way of simplifying this a little.  It
     encloses a block up to a matching END directive, which is first
     processed to generate some output.  This is then passed to the named
     template file or BLOCK as the 'content' variable.

          [% WRAPPER section
             title = 'Quantum Mechanics'
          %]
             Quantum mechanics is a very interesting subject wish
             should prove easy for the layman to fully comprehend.
          [% END %]

          [% WRAPPER section
             title = 'Desktop Nuclear Fusion for under $50'
          %]
             This describes a simple device which generates significant
             sustainable electrical power from common tap water by process
             of nuclear fusion.
          [% END %]

     The single 'section' template can then be defined as:

          <p>
          <h2>[% title %]</h2>
          [% content %]
          </p>

     Like other block directives, it can be used in side-effect notation:

          [% INSERT legalese.txt WRAPPER big_bold_table %]

BLOCK
     The BLOCK ... END construct can be used to define template component
     blocks which can be processed with the INCLUDE, PROCESS and WRAPPER
     directives.

          [% BLOCK tabrow %]
          <tr><td>[% name %]<td><td>[% email %]</td></tr>
          [% END %]

          <table>
          [% PROCESS tabrow  name='Fred'  email='fred@nowhere.com' %]
          [% PROCESS tabrow  name='Alan'  email='alan@nowhere.com' %]
          </table>

     A BLOCK definition can be used before it is defined, as long as the
     definition resides in the same file.  The block definition itself does
     not generate any output.

          [% PROCESS tmpblk %]

          [% BLOCK tmpblk %] This is OK [% END %]

     Anonymous BLOCKs can be used to define block macros.  The enclosing
     block is processed each time the macro is called.

          [% MACRO whereabouts BLOCK %]
             The [% animal %] sat on the [% place %].
          [% END %]

          [% foo(animal='cat', place='mat') %]    # The cat sat on the mat
          [% foo(animal='dog', place='log') %]    # The dog sat on the log

     You can also use anonymous BLOCK to capture the output of a template
     fragment, should you need to:

          [% mytext = BLOCK %]
             This is part of the block
             [% INCLUDE this ; INCLUDE that %]
             More block.
          [% END %]

     The BLOCK content is processed once and the output assigned to the
     variable.

Conditional Processing
----------------------

IF / UNLESS / ELSIF / ELSE
     The IF and UNLESS directives can be used to process or ignore a block
     based on some run-time condition.

          [% IF frames %]
             [% INCLUDE frameset %]
          [% END %]

          [% UNLESS text_mode %]
             [% INCLUDE biglogo %]
          [% END %]

     Multiple conditions may be joined with ELSIF and/or ELSE blocks.

          [% IF age < 10 %]
             Hello [% name %], does your mother know you're
             using her AOL account?
          [% ELSIF age < 18 %]
             Sorry, you're not old enough to enter
             (and too dumb to lie about your age)
          [% ELSE %]
             Welcome [% name %].
          [% END %]

     The following conditional and boolean operators may be used:

          == != < <= > >= ! && || and or not

     Conditions may be arbitrarily complex and are evaluated with the same
     precedence as in Perl.  Parenthesis may be used to explicitly
     determine evaluation order.

          # ridiculously contrived complex example
          [% IF (name == 'admin' || uid <= 0) && mode == 'debug' %]
             I'm confused.
          [% ELSIF more > less %]
             That's more or less correct.
          [% END %]

SWITCH / CASE
     The SWITCH / CASE construct can be used to perform a multi-way
     conditional test.  The SWITCH directive expects an expression which is
     first evaluated and then compared against each CASE statement in turn.
     Each CASE directive should contain a single value or a list of values
     which should match.  CASE may also be left blank or written as [% CASE
     default %] to specify a default match.  Only one CASE matches, there
     is no drop-through between CASE statements.

     [% SWITCH myvar %]     [% CASE value1 %]        ...      [% CASE [
     value2 value3 ] %]   # multiple values        ...      [% CASE
     myhash.keys %]         # ditto        ...      [% CASE %]
            # default        ...      [% END %]

Loop Processing
---------------

FOREACH
     The FOREACH directive will iterate through the items in a list,
     processing the enclosed block for each one.

          my $vars = {
          	foo   => 'Foo',
            	items => [ 'one', 'two', 'three' ],
          };

          template:

          Things:
          [% FOREACH thing = [ foo 'Bar' "$foo Baz" ] %]
             * [% thing %]
          [% END %]

          Items:
          [% FOREACH i = items %]
             * [% i %]
          [% END %]

          Stuff:
          [% stuff = [ foo "$foo Bar" ] %]
          [% FOREACH s = stuff %]
             * [% s %]
          [% END %]

     output:

          Things:
            * Foo
            * Bar
            * Foo Baz

          Items:
            * one
            * two
            * three

          Stuff:
            * Foo
            * Foo Bar

     When the FOREACH directive is used without specifying a target
     variable, any iterated values which are hash references will be
     automatically imported.

          [% userlist = [
          	  { id => 'tom',   name => 'Thomas'  },
          	  { id => 'dick',  name => 'Richard'  },
          	  { id => 'larry', name => 'Lawrence' },
             ]
          %]

          [% FOREACH user = userlist %]
             [% user.id %] [% user.name %]
          [% END %]

     short form:

          [% FOREACH userlist %]
             [% id %] [% name %]
          [% END %]

     Note that this particular usage creates a localised variable context
     to prevent the imported hash keys from overwriting any existing
     variables.  The imported definitions and any other variables defined
     in such a FOREACH loop will be lost at the end of the loop, when the
     previous context and variable values are restored.

     The FOREACH directive can also be used to iterate through the entries
     in a hash array.  Each entry in the hash is returned in sorted order
     (based on the key) as a hash array containing 'key' and 'value' items.

          [% users = {
          	 tom   => 'Thomas',
          	 dick  => 'Richard',
               larry => 'Lawrence',
             }
          %]

          [% FOREACH u = users %]
             * [% u.key %] : [% u.value %]
          [% END %]

     Output:

          * dick : Richard
          * larry : Lawrence
          * tom : Thomas

     The NEXT directive starts the next iteration in the FOREACH loop.

          [% FOREACH user = userlist %]
             [% NEXT IF user.isguest %]
             Name: [% user.name %]    Email: [% user.email %]
          [% END %]

     The BREAK directive can be used to prematurely exit the loop..

          [% FOREACH match = results.nsort('score').reverse %]
             [% BREAK IF match.score < 50 %]
             [% match.score %] : [% match.url %]
          [% END %]

     The FOREACH directive is implemented using the Template::Iterator
     module.  A reference to the iterator object for a FOREACH directive is
     implicitly available in the 'loop' variable.  This can be used to call
     methods on the iterator object to return the list size, maximum index
     (size - 1), current index (0..size-1), current iteration number
     (1..size), boolean values to indicate if the loop is in the first/last
     iteration, and so on.  See Template/Iterator,
     for further details.

          [% FOREACH item = itemlist %]
             [% "<ul>\n" IF loop.first %]
             <li>[% loop.number %]/[% loop.size %] : [% item %]
             [% "</ul>\n" IF loop.last %]
          [% END %]

     The 'iterator' plugin can also be used to explicitly create an
     iterator object.  See Template::Plugin::Iterator for further details.

          [% USE stuff = iterator(['a', 'b', 'c']) %]

          [% FOREACH item = stuff %]
          *  [% stuff.index %] : [% item %]
          [% END %]

     output:

          *  0 : a
          *  1 : b
          *  2 : c

WHILE
     The WHILE directive can be used to repeatedly process a template block
     while a conditional expression evaluates true.  The expression may be
     arbitrarily complex as per IF / UNLESS.

          [% WHILE total < 100 %]
             ...
             [% total = calculate_new_total %]
          [% END %]

     An assignment can be enclosed in parenthesis to evaluate the assigned
     value.

          [% WHILE (user = get_next_user_record) %]
             [% user.name %]
          [% END %]

     The NEXT directive can be used to start the next iteration of a WHILE
     loop and BREAK can be used to exit the loop, both as per FOREACH.

     The Template Toolkit uses a failsafe counter to prevent runaway WHILE
     loops which would otherwise never terminate.  If the loop exceeds 1000
     iterations then an 'undef' exception will be thrown, reporting the
     error:

          WHILE loop terminated (> 1000 iterations)

     The $Template::Directive::WHILE_MAX variable controls this behaviour
     and can be set to a higher value if necessary.

Filters, Plugins, Macros and Perl
---------------------------------

FILTER
     The FILTER directive can be used to post-process the output of a
     block.  A number of standard filters are provided with the Template
     Toolkit.  The 'html' filter, for example, escapes the '<', '>' and
     '&' characters to prevent them from being interpreted as HTML tags or
     entity reference.

          [% FILTER html %]
             HTML text may have < and > characters embedded
             which you want converted to the correct HTML entities.
          [% END %]

     output:

          HTML text may have &lt; and &gt; characters embedded
          which you want converted to the correct HTML entities.

     The FILTER directive can also follow various other non-block
     directives.  For example:

          [% INCLUDE mytext FILTER html %]

     The '|' character can also be used as an alias for 'FILTER'.

          [% INCLUDE mytext | html %]

     Multiple filters can be chained together and will be called in
     sequence.

          [% INCLUDE mytext FILTER html FILTER html_para %]

     or

          [% INCLUDE mytext | html | html_para %]

     Filters come in two flavours, known as 'static' or 'dynamic'.  A
     static filter is a simple subroutine which accepts a text string as
     the only argument and returns the modified text.  The 'html' filter is
     an example of a static filter, implemented as:

          sub html_filter {
          	my $text = shift;
          	for ($text) {
          	    s/&/&amp;/g;
          	    s/</&lt;/g;
          	    s/>/&gt;/g;
          	}
          	return $text;
          }

     Dynamic filters can accept arguments which are specified when the
     filter is called from a template.  The 'repeat' filter is such an
     example, accepting a numerical argument which specifies the number of
     times that the input text should be repeated.

          [% FILTER repeat(3) %]blah [% END %]

     output:

          blah blah blah

     These are implemented as filter 'factories'.  The factory subroutine
     is passed a reference to the current Template::Context object along
     with any additional arguments specified.  It should then return a
     subroutine reference (closure) which implements the filter.  The
     'repeat' filter factory is implemented like this:

          sub repeat_filter_factory {
          	my ($context, $iter) = @_;
          	$iter = 1 unless defined $iter;

          return sub {
              my $text = shift;
              $text = '' unless defined $text;
              return join('\n', $text) x $iter;
          }
              }

     The FILTERS option, described in `CONFIGURATION OPTIONS' in this
     node, allows custom filters to be defined when a Template object is
     instantiated.  The Template::Context define_filter() method allows
     further filters to be defined at any time.

     The FILTER directive automatically quotes the name of the filter.  As
     with INCLUDE et al, you can use a variable to provide the name of the
     filter, prefixed by '$'.

          [% myfilter = 'html' %]
          [% FILTER $myfilter %]	# same as [% FILTER html %]
             ...
          [% END %]

     A template variable can also be used to define a static filter
     subroutine.  However, the Template Toolkit will automatically call any
     subroutine bound to a variable and use the value returned.  Thus, the
     above example could be implemented as:

          my $vars = {
          	myfilter => sub { return 'html' },
          };

     template:

          [% FILTER $myfilter %]	# same as [% FILTER html %]
             ...
          [% END %]

     To define a template variable that evaluates to a subroutine reference
     that can be used by the FILTER directive, you should create a
     subroutine that, when called automatically by the Template Toolkit,
     returns another subroutine reference which can then be used to perform
     the filter operation.  Note that only static filters can be
     implemented in this way.

          my $vars = {
          	myfilter => sub { \&my_filter_sub },
          };

          sub my_filter_sub {
          	my $text = shift;
          	# do something
              return $text;
          }

     template:

          [% FILTER $myfilter %]
             ...
          [% END %]

     Alternately, you can bless a subroutine reference into a class (any
     class will do) to fool the Template Toolkit into thinking it's an
     object rather than a subroutine.  This will then bypass the automatic
     "call-a-subroutine-to-return-a-value" magic.

          my $vars = {
          	myfilter => bless(\&my_filter_sub, 'anything_you_like'),
          };

     template:

          [% FILTER $myfilter %]
             ...
          [% END %]

     Filters bound to template variables remain local to the variable
     context in which they are defined.  That is, if you define a filter in
     a PERL block within a template that is loaded via INCLUDE, then the
     filter definition will only exist until the end of that template when
     the stash is delocalised, restoring the previous variable state.  If
     you want to define a filter which persists for the lifetime of the
     processor, or define additional dynamic filter factories, then you can
     call the define_filter() method on the current Template::Context
     object.

     See `TEMPLATE TOOLKIT FILTERS' in this node for a complete list of
     available filters, their descriptions and examples of use.

USE
     The USE directive can be used to load and initialise "plugin"
     extension modules.

          [% USE myplugin %]

     A plugin is a regular Perl module that conforms to a particular
     object-oriented interface, allowing it to be loaded into and used
     automatically by the Template Toolkit.  For details of this interface
     and information on writing plugins, consult Template/Plugin.

     The plugin name is case-sensitive and will be appended to the
     PLUGIN_BASE value (default: 'Template::Plugin') to construct a full
     module name.  Any periods, '.', in the name will be converted to '::'.

          [% USE MyPlugin %]     #  => Template::Plugin::MyPlugin
          [% USE Foo.Bar  %]     #  => Template::Plugin::Foo::Bar

     Various standard plugins are included with the Template Toolkit (see
     below and `TEMPLATE TOOLKIT PLUGINS' in this node).  These can be
     specified in lower case and are mapped to the appropriate name.

          [% USE cgi   %]        # => Template::Plugin::CGI
          [% USE table %]        # => Template::Plugin::Table

     Any additional parameters supplied in parenthesis after the plugin
     name will be also be passed to the new() constructor.  A reference to
     the current Template::Context object is always passed as the first
     parameter.

          [% USE MyPlugin('foo', 123) %]

     equivalent to:

          Template::Plugin::MyPlugin->new($context, 'foo', 123);

     Named parameters may also be specified.  These are collated into a
     hash which is passed by reference as the last parameter to the
     constructor, as per the general code calling interface.

          [% USE url('/cgi-bin/foo', mode='submit', debug=1) %]

     equivalent to:

          Template::Plugin::URL->new($context, '/cgi-bin/foo'
          			       { mode => 'submit', debug => 1 });

     The plugin may represent any data type; a simple variable, hash, list
     or code reference, but in the general case it will be an object
     reference.  Methods can be called on the object (or the relevant
     members of the specific data type) in the usual way:

          [% USE table(mydata, rows=3) %]

          [% FOREACH row = table.rows %]
             <tr>
             [% FOREACH item = row %]
          	  <td>[% item %]</td>
             [% END %]
             </tr>
          [% END %]

     An alternative name may be provided for the plugin by which it can be
     referenced:

          [% USE scores = table(myscores, cols=5) %]

          [% FOREACH row = scores.rows %]
             ...
          [% END %]

     You can use this approach to create multiple plugin objects with
     different configurations.  This example shows how the 'format' plugin
     is used to create sub-routines bound to variables for formatting text
     as per printf().

          [% USE bold = format('<b>%s</b>') %]
          [% USE ital = format('<i>%s</i>') %]

          [% bold('This is bold')   %]
          [% ital('This is italic') %]

     Output:

          <b>This is bold</b>
          <i>This is italic</i>

     The URL plugin allows you to build dynamic URLs from a base part and
     optional query parameters.

          [% USE mycgi = URL('/cgi-bin/foo.pl', debug=1) %]
          <a href="[% mycgi %]">...
          <a href="[% mycgi(mode='submit') %]"...

     Output:

          <a href="/cgi-bin/foo.pl?debug=1">...
          <a href="/cgi-bin/foo.pl?mode=submit&debug=1">...

     The CGI plugin is an example of one which delegates to another Perl
     module.  In this this case, it is to Lincoln Stein's CGI.pm module.
     All of the methods provided by CGI.pm are available via the plugin.

          [% USE CGI %]

          [% CGI.start_form %]

          [% CGI.checkbox_group(name   =>   'colours',
                                values => [ 'red' 'green' 'blue' ])
          %]

          [% CGI.popup_menu(name   =>   'items',
                            values => [ 'foo' 'bar' 'baz' ])
          %]

          [% CGI.end_form %]

     Simon Matthews has written a DBI plugin which provides an interface to
     Tim Bunce's DBI module (both available from CPAN).  Here's a short
     example:

          [% USE DBI('DBI:mSQL:mydbname') %]

          [% FOREACH user = DBI.query('SELECT * FROM users') %]
             [% user.id %] [% user.name %] [% user.etc.etc %]
          [% END %]

     See `TEMPLATE TOOLKIT PLUGINS' in this node for more information on
     the plugins distributed with the toolkit or available from CPAN.

     The LOAD_PERL option (disabled by default) provides a further way by
     which external Perl modules may be loaded.  If a regular Perl module
     (i.e. not a Template::Plugin::* or other module relative to some
     PLUGIN_BASE) supports an object-oriented interface and a new()
     constructor then it can be loaded and instantiated automatically.  The
     following trivial example shows how the IO::File module might be used.

          [% USE file = IO.File('/tmp/mydata') %]

          [% WHILE (line = file.getline) %]
             <!-- [% line %] -->
          [% END %]

MACRO
     The MACRO directive allows you to define a directive or directive
     block which is then evaluated each time the macro is called.

          [% MACRO header INCLUDE header %]

     Calling the macro as:

          [% header %]

     is then equivalent to:

          [% INCLUDE header %]

     Macros can be passed named parameters when called.  These values
     remain local to the macro.

          [% header(title='Hello World') %]

     equivlant to:

          [% INCLUDE header title='Hello World' %]

     A MACRO definition may include parameter names.  Values passed to the
     macros are then mapped to these local variables.  Other named
     parameters may follow these.

          [% MACRO header(title) INCLUDE header %]

          [% header('Hello World') %]
          [% header('Hello World', bgcol='#123456') %]

     equivalent to:

          [% INCLUDE header title='Hello World' %]
          [% INCLUDE header title='Hello World' bgcol='#123456# %]

     A MACRO may preceed any directive and must conform to the structure
     of the directive.

          [% MACRO header IF frames %]
             [% INCLUDE frames/header %]
          [% ELSE %]
             [% INCLUDE header %]
          [% END %]

          [% header %]

     A MACRO may also be defined as an anonymous BLOCK.  The block will be
     evaluated each time the macro is called.

          [% MACRO header BLOCK %]
             ...content...
          [% END %]

          [% header %]

PERL
     The PERL directive is used to mark the start of a block which contains
     Perl code for evaluation.  The EVAL_PERL option must be enabled for
     Perl code to be evaluated or a 'perl' exception will be thrown with
     the message 'EVAL_PERL not set'.

     Perl code is evaluated in the Template::Perl package.  The $context
     package variable contains a reference to the current Template::Context
     object.  This can be used to access the functionality of the Template
     Toolkit to process other templates, load plugins, filters, etc.  See
     Template/Context, for further details.

          [% PERL %]
             print $context->include('myfile');
          [% END %]

     The $stash variable contains a reference to the top-level stash object
     which manages template variables.  Through this, variable values can
     be retrieved and updated.  See Template/Stash,
     for further details.

          [% PERL %]
             $stash->set(foo => 'bar');
             print "foo value: ", $stash->get('foo');
          [% END %]

     Output     foo value: bar

     Output is generated from the PERL block by calling print().  Note that
     the Template::Perl::PERLOUT handle is selected (tied to an output
     buffer) instead of STDOUT.

          [% PERL %]
             print "foo\n";	                        # OK
             print PERLOUT "bar\n";                   # OK, same as above
             print Template::Perl::PERLOUT "baz\n";   # OK, same as above
             print STDOUT "qux\n";			# WRONG!
          [% END %]

     The PERL block may contain other template directives.  These are
     processed before the Perl code is evaluated.

          [% name = 'Fred Smith' %]

          [% PERL %]
             print "[% name %]\n";
          [% END %]

     Thus, the Perl code in the above example is evaluated as:

          print "Fred Smith\n";

     Exceptions may be thrown from within PERL blocks via die() and will be
     correctly caught by enclosing TRY blocks.

          [% TRY %]
             [% PERL %]
                die "nothing to live for\n";
             [% END %]
          [% CATCH %]
             error: [% error.info %]
          [% END %]

     output:        error: nothing to live for

RAWPERL
     The Template Toolkit parser reads a source template and generates the
     text of a Perl subroutine as output.  It then uses eval() to evaluate
     it into a subroutine reference.  This subroutine is then called to
     process the template, passing a reference to the current
     Template::Context object through which the functionality of the
     Template Toolkit can be accessed.  The subroutine reference can be
     cached, allowing the template to be processed repeatedly without
     requiring any further parsing.

     For example, a template such as:

          [% PROCESS header %]
          The [% animal %] sat on the [% location %]
          [% PROCESS footer %]

     is converted into the following Perl subroutine definition:

          sub {
          	my $context = shift;
          	my $stash   = $context->stash;
          	my $output  = '';
          	my $error;

          	eval { BLOCK: {
          	    $output .=  $context->process('header');
          	    $output .=  "The ";
          	    $output .=  $stash->get('animal');
          	    $output .=  " sat on the ";
          	    $output .=  $stash->get('location');
          	    $output .=  $context->process('footer');
          	    $output .=  "\n";
          	} };
          	if ($@) {
          	    $error = $context->catch($@, \$output);
          	    die $error unless $error->type eq 'return';
          	}

          	return $output;
          }

     To examine the Perl code generated, such as in the above example, set
     the $Template::Parser::DEBUG package variable to any true value.  You
     can also set the $Template::Directive::PRETTY variable true to have
     the code formatted in a readable manner for human consumption.  The
     source code for each generated template subroutine will be printed to
     STDERR on compilation (i.e. the first time a template is used).

          $Template::Parser::DEBUG = 1;
          $Template::Directive::PRETTY = 1;

          ...

          $template->process($file, $vars)
          	|| die $template->error(), "\n";

     The PERL ... END construct allows Perl code to be embedded into a
     template (when the EVAL_PERL option is set), but it is evaluated at
     "runtime" using eval() each time the template subroutine is called.
     This is inherently flexible, but not as efficient as it could be,
     especially in a persistant server environment where a template may be
     processed many times.

     The RAWPERL directive allows you to write Perl code that is integrated
     directly into the generated Perl subroutine text.  It is evaluated
     once at compile time and is stored in cached form as part of the
     compiled template subroutine.  This makes RAWPERL blocks more
     efficient than PERL blocks.

     The downside is that you must code much closer to the metal.  Within
     PERL blocks, you can call print() to generate some output.  RAWPERL
     blocks don't afford such luxury.  The code is inserted directly into
     the generated subroutine text and should conform to the convention of
     appending to the '$output' variable.

          [% PROCESS  header %]

          [% RAWPERL %]
             $output .= "Some output\n";
             ...
             $output .= "Some more output\n";
          [% END %]

     The critical section of the generated subroutine for this example
     would then look something like:

          ...
          eval { BLOCK: {
          	$output .=  $context->process('header');
              $output .=  "\n";
              $output .= "Some output\n";
          	...
              $output .= "Some more output\n";
              $output .=  "\n";
          } };
          ...

     As with PERL blocks, the $context and $stash references are
     pre-defined and available for use within RAWPERL code.

Exception Handling and Flow Control
-----------------------------------

TRY / THROW / CATCH / FINAL
     The Template Toolkit supports fully functional, nested exception
     handling.  The TRY directive introduces an exception handling scope
     which continues until the matching END directive.  Any errors that
     occur within that block will be caught and can be handled by one of
     the CATCH blocks defined.

          [% TRY %]
             ...blah...blah...
             [% CALL somecode %]
             ...etc...
             [% INCLUDE someblock %]
             ...and so on...
          [% CATCH %]
             An error occurred!
          [% END %]

     Errors are raised as exceptions (objects of the Template::Exception
     class) and contain two fields, 'type' and 'info'.  The exception
     'type' can be any string containing letters, numbers, '_' or '.', and
     is used to indicate the kind of error that occurred.  The 'info' field
     contains an error message indicating what actually went wrong.  Within
     a catch block, the exception object is aliased to the 'error'
     variable.  You can access the 'type' and 'info' fields directly.

          [% mydsn = 'dbi:MySQL:foobar' %]
          ...

          [% TRY %]
             [% USE DBI(mydsn) %]
          [% CATCH %]
             ERROR! Type: [% error.type %]
                    Info: [% error.info %]
          [% END %]

     output (assuming a non-existant database called 'foobar'):

          ERROR!  Type: DBI
                  Info: Unknown database "foobar"

     The 'error' variable can also be specified by itself and will return a
     string of the form "$type error - $info".

          ...
          [% CATCH %]
          ERROR: [% error %]
          [% END %]

     output:

          ERROR: DBI error - Unknown database "foobar"

     Each CATCH block may be specified with a particular exception type
     denoting the kind of error that it should catch.  Multiple CATCH
     blocks can be provided to handle different types of exception that may
     be thrown in the TRY block.  A CATCH block specified without any type,
     as in the previous example, is a default handler which will catch any
     otherwise uncaught exceptions.  This can also be specified as [%
     CATCH DEFAULT %].

          [% TRY %]
             [% INCLUDE myfile %]
             [% USE DBI(mydsn) %]
             [% CALL somecode %]
             ...
          [% CATCH file %]
             File Error! [% error.info %]
          [% CATCH DBI %]
             [% INCLUDE database/error.html %]
          [% CATCH %]
             [% error %]
          [% END %]

     Remember that you can specify multiple directives within a single tag,
     each delimited by ';'.  Thus, you might prefer to write your simple
     CATCH blocks more succinctly as:

          [% TRY %]
             ...
          [% CATCH file; "File Error! $error.info" %]
          [% CATCH DBI;  INCLUDE database/error.html %]
          [% CATCH; error %]
          [% END %]

     or even:

          [% TRY %]
             ...
          [% CATCH file ;
                 "File Error! $error.info" ;
             CATCH DBI ;
          	   INCLUDE database/error.html ;
             CATCH ;
          	   error ;
             END
          %]

     The DBI plugin, as you should by now have realised, throws exceptions
     of the 'DBI' type.   The other specific exception caught here is of
     the 'file' type.

     A 'file' error is automatically thrown by the Template Toolkit when it
     can't find a file, or fails to load, parse or process a file that has
     been requested by an INCLUDE, PROCESS, INSERT or WRAPPER directive.
     If 'myfile' can't be found in the example above, the [% INCLUDE myfile
     %] directive will raise a 'file' exception which is then caught by the
     [% CATCH file %] block, generating the output:

          File Error! myfile: not found

     Note that the DEFAULT option (disabled by default) allows you to
     specify a default file to be used any time a template file can't be
     found.  This will prevent file exceptions from ever being raised when
     a non-existant file is requested (unless, of course, the DEFAULT file
     doesn't exist).  Errors encountered once the file has been found
     (i.e. read error, parse error) will be raised as file exceptions as
     per usual.

     Uncaught exceptions (i.e. the TRY block doesn't have a type specific
     or default CATCH handler) may be caught by enclosing TRY blocks which
     can be nested indefinately across multiple templates.  If the error
     isn't caught at any level then processing will stop and the Template
     process() method will return a false value to the caller.  The
     relevant Template::Exception object can be retrieved by calling the
     error() method.

          [% TRY %]
             ...
             [% TRY %]
                [% INCLUDE $user.header %]
             [% CATCH file %]
          	  [% INCLUDE header %]
             [% END %]
             ...
          [% CATCH DBI %]
             [% INCLUDE database/error.html %]
          [% END %]

     In this example, the inner TRY block is used to ensure that the first
     INCLUDE directive works as expected.  We're using a variable to
     provide the name of the template we want to include, user.header, and
     it's possible this contains the name of a non-existant template, or
     perhaps one containing invalid template directives.  If the INCLUDE
     fails  with a 'file' error then we CATCH it in the inner block and
     INCLUDE the default 'header' file instead.  Any DBI errors that occur
     within the scope of the outer TRY block will be caught in the
     relevant CATCH block, causing the 'database/error.html' template to
     be processed.  Note that included templates inherit all currently
     defined template variable so these errors file can quite happily
     access the 'error' variable to retrieve information about the
     currently caught exception.  e.g.

     'database/error.html':

          <h2>Database Error</h2>
          A database error has occurred: [% error.info %]

     You can also specify a FINAL block.  This is always processed
     regardless of the outcome of the TRY and/or CATCH block.  If an
     exception is uncaught then the FINAL block is processed before jumping
     to the enclosing block or returning to the caller.

          [% TRY %]
             ...
          [% CATCH this %]
             ...
          [% CATCH that %]
             ...
          [% FINAL %]
             All done!
          [% END %]

     The output from the TRY block is left intact up to the point where an
     exception occurs.  For example, this template:

          [% TRY %]
             This gets printed
             [% THROW food 'carrots' %]
             This doesn't
          [% CATCH food %]
             culinary delights: [% error.info %]
          [% END %]

     generates the following output:

          This gets printed
          culinary delights: carrots

     The CLEAR directive can be used in a CATCH or FINAL block to clear
     any output created in the TRY block.

          [% TRY %]
             This gets printed
             [% THROW food 'carrots' %]
             This doesn't
          [% CATCH food %]
             [% CLEAR %]
             culinary delights: [% error.info %]
          [% END %]

     output:

          culinary delights: carrots

          Exception types are hierarchical, with each level being separated by
          the familiar dot.  A 'DBI.connect' exception is a more specific kind
          of 'DBI' error.  Similarly, a 'myown.error.barf' is a more specific
          kind of 'myown.error' type which itself is also a 'myown' error.  A
          CATCH handler that specifies a general exception type (such as 'DBI'
          or 'myown.error') will also catch more specific types that have the
          same prefix as long as a more specific handler isn't defined.  Note
          that the order that CATCH handlers are defined in is irrelevant; a
          more specific handler which always catch an exception in preference to
          a more generic or default one.

          [% TRY %]
             ...
          [% CATCH DBI ;
               INCLUDE database/error.html ;
             CATCH DBI.connect ;
               INCLUDE database/connect.html ;
             CATCH ;
               INCLUDE error.html ;
             END
          %]

     In this example, a 'DBI.connect' error has it's own handler, a more
     general 'DBI' block is used for all other DBI or DBI.* errors and a
     default handler catches everything else.

     Exceptions can be raised in a template using the THROW directive.  The
     first parameter is the exception type which doesn't need to be quoted
     (but can be, it's the same as INCLUDE) followed by the relevant error
     message which can be any regular value such as a quoted string,
     variable, etc.

          [% THROW food "Missing ingredients: $recipe.error" %]

          [% THROW user.login 'no user id: please login' %]

          [% THROW $myerror.type "My Error: $myerror.info" %]

     Exceptions can also be thrown from Perl code which you've bound to
     template variables, or defined as a plugin or other extension.  To
     raise an exception, call die() passing a reference to a
     Template::Exception object as the argument.  This will then be caught
     by any enclosing TRY blocks from where the code was called.

          use Template::Exception;
          ...

          my $vars = {
          	foo => sub {
          	    # ... do something ...
          	    die Template::Exception->new('myerr.naughty',
          					 'Bad, bad error');
          	},
          };

     template:

          [% TRY %]
             ...
             [% foo %]
             ...
          [% CATCH myerr ;
               "Error: $error" ;
             END
          %]

     output:

          Error: myerr.naughty error - Bad, bad error

     You can also call die() with a single string, as is common in much
     existing Perl code.  This will automatically be converted to an
     exception of the 'undef' type (that's the literal string 'undef', not
     the undefined value).  If the string isn't terminated with a newline
     then Perl will append the familiar " at $file line $line" message.

          sub foo {
          	# ... do something ...
          	die "I'm sorry, Dave, I can't do that\n";
          }

     If you're writing a plugin, or some extension code that has the
     current Template::Context in scope (you can safely skip this section
     if this means nothing to you) then you can also raise an exception by
     calling the context throw() method.  You can pass it an
     Template::Exception object reference, a pair of ($type, $info)
     parameters or just an $info string to create an exception of 'undef'
     type.

          $context->throw($e);	    # exception object
          $context->throw('Denied');	    # 'undef' type
          $context->throw('user.passwd', 'Bad Password');

NEXT
     The NEXT directive can be used to start the next iteration of a
     FOREACH or WHILE loop.

          [% FOREACH user = userlist %]
             [% NEXT IF user.isguest %]
             Name: [% user.name %]    Email: [% user.email %]
          [% END %]

BREAK
     The BREAK directive can be used to prematurely exit a FOREACH or WHILE
     loop.

          [% FOREACH user = userlist %]
             Name: [% user.name %]    Email: [% user.email %]
             [% BREAK IF some.condition %]
          [% END %]

RETURN
     The RETURN directive can be used to stop processing the current
     template and return to the template from which it was called, resuming
     processing at the point immediately after the INCLUDE, PROCESS or
     WRAPPER directive.  If there is no enclosing template then the
     Template process() method will return to the calling code with a true
     value.

          Before
          [% INCLUDE half_wit %]
          After

          [% BLOCK half_wit %]
          This is just half...
          [% RETURN %]
          ...a complete block
          [% END %]

     output:

          Before
          This is just half...
          After

STOP
     The STOP directive can be used to indicate that the processor should
     stop gracefully without processing any more of the template document.
     This is a planned stop and the Template process() method will return a
     *true* value to the caller.  This indicates that the template was
     processed successfully according to the directives within it.

          [% IF something.terrible.happened %]
             [% INCLUDE fatal/error.html %]
             [% STOP %]
          [% END %]

          [% TRY %]
             [% USE DBI(mydsn) %]
             ...
          [% CATCH DBI.connect %]
             <p>Cannot connect to the database: [% error.info %]</p>
             <br>
             We apologise for the inconvenience.  The cleaning lady
             has removed the server power to plug in her vacuum cleaner.
             Please try again later.
             </p>
             [% INCLUDE footer %]
             [% STOP %]
          [% END %]

CLEAR
     The CLEAR directive can be used to clear the output buffer for the
     current enclosing block.   It is most commonly used to clear the
     output generated from a TRY block up to the point where the error
     occurred.

          [% TRY %]
             blah blah blah            # this is normally left intact
             [% THROW some 'error' %]  # up to the point of error
             ...
          [% CATCH %]
             [% CLEAR %]               # clear the TRY output
             [% error %]               # print error string
          [% END %]

Miscellaneous
-------------

META
     The META directive allows simple metadata items to be defined within a
     template.  These are evaluated when the template is parsed and as such
     may only contain simple values (e.g. it's not possible to interpolate
     other variables values into META variables).

          [% META
             title   = 'The Cat in the Hat'
             author  = 'Dr. Seuss'
             version = 1.23
          %]

     The 'template' variable contains a reference to the main template
     being processed.  These metadata items may be retrieved as attributes
     of the template.

          <h1>[% template.title %]</h1>
          <h2>[% template.author %]</h2>

     The 'name' and 'modtime' metadata items are automatically defined for
     each template to contain its name and modification time in seconds
     since the epoch.

          [% USE date %]		# use Date plugin to format time
          ...
          [% template.name %] last modified
          at [% date.format(template.modtime) %]

     The PRE_PROCESS and POST_PROCESS options allow common headers and
     footers to be added to all templates.  The 'template' reference is
     correctly defined when these templates are processed, allowing headers
     and footers to reference metadata items from the main template.

          $template = Template->new({
          	PRE_PROCESS  => 'header',
          	POST_PROCESS => 'footer',
          });

          $template->process('catinhat');

     header:     <html>     <head>     <title>[% template.title %]</title>
        </head>     <body>

     catinhat:     [% META        title   = 'The Cat in the Hat'
     author  = 'Dr. Seuss'        version = 1.23        year    = 2000
     %]

          The cat in the hat sat on the mat.

     footer:     <hr>     &copy; [% template.year %] [% template.author %]
        </body>     </html>

     The output generated from the above example is:

     <html>     <head>     <title>The Cat in the Hat</title>     </head>
      <body>

          The cat in the hat sat on the mat.

          <hr>
          &copy; 2000 Dr. Seuss
          </body>
          </html>

     Template.name template.modtime

TAGS
     The TAGS directive can be used to set the START_TAG and END_TAG values
     on a per-template file basis.

          [% TAGS <+ +> %]

          <+ INCLUDE header +>

     The TAGS directive may also be used to set a named TAG_STYLE

          [% TAGS html %]
          <!-- INCLUDE header -->

     See the TAGS and TAG_STYLE configuration options for further details.

FORNEXT
     TODO

CONFIGURATION OPTIONS
=====================

   The Template module accepts configuration items destined for any other
Template::* module that it may create and will forward them appropriately.
The following list summarises the various options under several broad
categories.

Template Style and Parsing Options
----------------------------------

START_TAG, END_TAG
     The START_TAG and END_TAG options are used to specify character
     sequences or regular expressions that mark the start and end of a
     template directive.  The default values for START_TAG and END_TAG are
     '[%' and '%]' respectively, giving us the familiar directive style:

          [% example %]

     Any Perl regex characters can be used and therefore should be escaped
     (or use the Perl quotemeta function) if they are intended to
     represent literal characters.

          my $template = Template->new({
            	START_TAG => quotemeta('<+'),
            	END_TAG   => quotemeta('+>'),
          });

     example:

          <+ INCLUDE foobar +>

     The TAGS directive can also be used to set the START_TAG and END_TAG
     values on a per-template file basis.

          [% TAGS <+ +> %]

TAG_STYLE
     The TAG_STYLE option can be used to set both START_TAG and END_TAG
     according to pre-defined tag styles.

          my $template = Template->new({
            	TAG_STYLE => 'php',
          });

     Available styles are:

          template    [% ... %]               (default)
          template1   [% ... %] or %% ... %%  (Template version 1)
          metatext    %% ... %%               (Text::MetaText)
          php         <? ... ?>               (PHP)
          asp         <% ... %>               (ASP)
          mason       <% ...  >               (HTML::Mason)
          html        <!-- ... -->            (HTML comments)

     Any values specified for START_TAG and/or END_TAG will over-ride
     those defined by a TAG_STYLE.

     The TAGS directive may also be used to set a TAG_STYLE

          [% TAGS html %]
          <!-- INCLUDE header -->

PRE_CHOMP, POST_CHOMP
     Anything outside a directive tag is considered plain text and is
     generally passed through unaltered (but see the INTERPOLATE option).
     This includes all whitespace and newlines characters surrounding
     directive tags.  Any directives that don't generate any output will
     leave gaps in the output document.

     Example:

          Foo
          [% a = 10 %]
          Bar

     Output:

          Foo

          Bar

     The PRE_CHOMP and POST_CHOMP options can help to clean up some of this
     extraneous whitespace.  Both are disabled by default.

          my $template = Template->new({
          	PRE_CHOMP  => 1,
          	POST_CHOMP => 1,
          });

     With PRE_CHOMP set true, the newline and whitespace preceeding a
     directive at the start of a line will be deleted.  This has the
     effect of concatenating a line that starts with a directive onto the
     end of the previous line.

          Foo <----------.
          	       |
              ,---(PRE_CHOMP)----'
              |
              `-- [% a = 10 %] --.
          	       |
              ,---(POST_CHOMP)---'
              |
              `-> Bar

     With POST_CHOMP set true, any whitespace after a directive up to and
     including the newline will be deleted.  This has the effect of joining
     a line that ends with a directive onto the start of the next line.

     PRE_CHOMP and POST_CHOMP can be activated for individual directives by
     placing a '-' immediately at the start and/or end of the directive.

          [% FOREACH user = userlist %]
             [%- user -%]
          [% END %]

     The '-' characters activate both PRE_CHOMP and POST_CHOMP for the one
     directive '[%- name -%]'.  Thus, the template will be processed as if
     written:

          [% FOREACH user = userlist %][% user %][% END %]

     Similarly, '+' characters can be used to disable PRE_CHOMP or
     POST_CHOMP (i.e.  leave the whitespace/newline intact) options on a
     per-directive basis.

          [% FOREACH user = userlist %]
          User: [% user +%]
          [% END %]

     With POST_CHOMP set on, the above example would be parsed as if
     written:

          [% FOREACH user = userlist %]User: [% user %]
          [% END %]

TRIM
     The TRIM option can be set to have any leading and trailing whitespace
     automatically removed from the output of all template files and
     BLOCKs.

     By example, the following BLOCK definition

          [% BLOCK foo %]
          Line 1 of foo
          [% END %]

     will be processed is as "\nLine 1 of foo\n".  When INCLUDEd, the
     surrounding newlines will also be introduced.

          before
          [% INCLUDE foo %]
          after

     output:     before

          Line 1 of foo

          after

     With the TRIM option set to any true value, the leading and trailing
     newlines (which count as whitespace) will be removed from the output
     of the BLOCK.

          before
          Line 1 of foo
          after

     The TRIM option is disabled (0) by default.

INTERPOLATE
     The INTERPOLATE flag, when set to any true value will cause variable
     references in plain text (i.e. not surrounded by START_TAG and
     END_TAG) to be recognised and interpolated accordingly.

          my $template = Template->new({
            	INTERPOLATE => 1,
          });

     Variables should be prefixed by a '$' to identify them.  Curly braces
     can be used in the familiar Perl/shell style to explicitly scope the
     variable name where required.

          # INTERPOLATE = 0
          <a href="http://[% server %]/[% help %]">
          <img src="[% images %]/help.gif"></a>
          [% myorg.name %]

          # INTERPOLATE = 1
          <a href="http://$server/$help">
          <img src="$images/help.gif"></a>
          $myorg.name

          # explicit scoping with {  }
          <img src="$images/${icon.next}.gif">

ANYCASE
     By default, directive keywords should be expressed in UPPER CASE.  The
     ANYCASE option can be set to allow directive keywords to be specified
     in any case.

          # ANYCASE => 0 (default)
          [% INCLUDE foobar %]	# OK
          [% include foobar %]        # ERROR
          [% include = 10   %]        # OK, 'include' is a variable

          # ANYCASE => 1
          [% INCLUDE foobar %]	# OK
          [% include foobar %]	# OK
          [% include = 10   %]        # ERROR, 'include' is reserved word

     One side-effect of enabling ANYCASE is that you cannot use a variable
     of the same name as a reserved word, regardless of case.  The reserved
     words are currently:

          GET CALL SET DEFAULT INSERT INCLUDE PROCESS WRAPPER
          IF UNLESS ELSE ELSIF FOR FORNEXT WHILE SWITCH CASE
          USE PLUGIN FILTER MACRO PERL RAWPERL BLOCK META
          TRY THROW CATCH FINAL BREAK RETURN STOP CLEAR
          TO STEP AND OR NOT MOD DIV END

     The only lower case reserved words that cannot be used for variables,
     regardless of the ANYCASE option, are the operators:

          and or not mod div

Template Files and Blocks
-------------------------

INCLUDE_PATH
     The INCLUDE_PATH is used to specify one or more directories in which
     template files are located.  When a template is requested that isn't
     defined locally as a BLOCK, each of the INCLUDE_PATH directories is
     searched in turn to locate the template file.  Multiple directories
     can be specified as a reference to a list or as a single string where
     each directory is delimited by ':'. The DELIMITER option can be set
     to redefine the delimiter value.

          my $template = Template->new({
              INCLUDE_PATH => '/usr/local/templates',
          });

          my $template = Template->new({
              INCLUDE_PATH => '/usr/local/templates:/tmp/my/templates',
          });

          my $template = Template->new({
              INCLUDE_PATH => [ '/usr/local/templates',
                                '/tmp/my/templates' ],
          });

DELIMITER
     Used to provide an alternative delimiter character sequence for
     separating paths specified in the INCLUDE_PATH.  May be useful for
     operating systems that permit the use of ':' in file names.

          # tolerate Silly Billy's file system conventions
          my $template = Template->new({
          	DELIMITER    => ' ',
              INCLUDE_PATH => 'C:/HERE/NOW D:/THERE/THEN',
          });

          # better solution: install Linux!  :-)

ABSOLUTE
     The ABSOLUTE flag is used to indicate if templates specified with
     absolute filenames (e.g. '/foo/bar') should be processed.  It is
     disabled by default and any attempt to load a template by such a name
     will cause a 'file' exception to be raised.

          my $template = Template->new({
          	ABSOLUTE => 1,
          });

          # this is why it's disabled by default
          [% INSERT /etc/passwd %]

RELATIVE
     The RELATIVE flag is used to indicate if templates specified with
     filenames relative to the current directory (e.g. './foo/bar' or
     '../../some/where/else') should be loaded.  It is also disabled by
     default, and will raise a 'file' error if such template names are
     encountered.

          my $template = Template->new({
          	RELATIVE => 1,
          });

          [% INCLUDE ../logs/error.log %]

DEFAULT
     The DEFAULT option can be used to specify a default template which
     should be used whenever a specified template can't be found in the
     INCLUDE_PATH.

          my $template = Template->new({
          	DEFAULT => 'notfound.html',
          });

     If a non-existant template is requested through the Template process()
     method, or by an INCLUDE, PROCESS or WRAPPER directive, then the
     DEFAULT template will instead be processed, if defined.  Note that the
     DEFAULT template is not used when templates are specified with
     absolute or relative filenames, or as a reference to a input file
     handle or text string.

BLOCKS
     The BLOCKS option can be used to pre-define a default set of template
     blocks.  These should be specified as a reference to a hash array
     mapping template names to template text, subroutines or
     Template::Document objects.

          my $template = Template->new({
          	BLOCKS => {
          	    header  => 'The Header.  [% title %]',
          	    footer  => sub { return $some_output_text },
          	    another => Template::Document->new({ ... }),
          	},
          });

AUTO_RESET
     The AUTO_RESET option is set by default and causes the local BLOCKS
     cache for the Template::Context object to be reset on each call to the
     Template process() method.  This ensures that any BLOCKs defined
     within a template will only persist until that template is finished
     processing.  This prevents BLOCKs defined in one processing request
     from interfering with other independant requests subsequently
     processed by the same context object.

     The BLOCKS item may be used to specify a default set of block
     definitions for the Template::Context object.  Subsequent BLOCK
     definitions in templates will over-ride these but they will be
     reinstated on each reset if AUTO_RESET is enabled (default), or if
     the Template::Context reset() method is called.

RECURSION
     The template processor will raise a file exception if it detects
     direct or indirect recursion into a template.  Setting this option to
     any true value will allow templates to include each other recursively.

Template Variables
------------------

VARIABLES, PRE_DEFINE
     The VARIABLES option (or PRE_DEFINE - they're equivalent) can be used
     to specify a hash array of template variables that should be used to
     pre-initialise the stash when it is created.  These items are ignored
     if the STASH item is defined.

          my $template = Template->new({
          	VARIABLES => {
          	    title   => 'A Demo Page',
          	    author  => 'Joe Random Hacker',
          	    version => 3.14,
          	},
          };

     or

          my $template = Template->new({
          	PRE_DEFINE => {
          	    title   => 'A Demo Page',
          	    author  => 'Joe Random Hacker',
          	    version => 3.14,
          	},
          };

Runtime Processing Options
--------------------------

EVAL_PERL
     This flag is used to indicate if PERL and/or RAWPERL blocks should be
     evaluated.  By default, it is disabled and any PERL or RAWPERL blocks
     encountered will be ignored.  Note however that any RAWPERL blocks
     should always contain valid Perl code, regardless of the EVAL_PERL
     flag.  The parser will fail to compile templates that contain invalid
     Perl code in RAWPERL blocks and will throw a 'file' exception.

PRE_PROCESS, POST_PROCESS
     These values may be set to contain the name(s) of template files
     (relative to INCLUDE_PATH) which should be processed immediately
     before and/or after each template.  These do not get added to
     templates processed into a document via directives such as INCLUDE,
     PROCESS, WRAPPER etc.

          my $template = Template->new({
          	PRE_PROCESS  => 'header',
          	POST_PROCESS => 'footer',
          };

     Multiple templates may be specified as a reference to a list.  Each is
     processed in the order defined.

          my $template = Template->new({
          	PRE_PROCESS  => [ 'config', 'header' ],
          	POST_PROCESS => 'footer',
          };

     The PRE_PROCESS and POST_PROCESS templates are evaluated in the same
     variable context as the main document and may define or update
     variables for subseqent use.

     config:     [% # set some site-wide variables        bgcolor =
     '#ffffff'        version = 2.718     %]

     header:     [% DEFAULT title = 'My Funky Web Site' %]     <html>
     <head>     <title>[% title %]</title>     </head>     <body
     bgcolor="[% bgcolor %]">

     footer:     <hr>     Version [% version %]     </body>     </html>

     The Template::Document object representing the main template being
     processed is available within PRE_PROCESS and POST_PROCESS templates
     as the 'template' variable.  Metadata items defined via the META
     directive may be accessed accordingly.

          $template->process('mydoc.html', $vars);

     mydoc.html:     [% META title = 'My Document Title' %]     blah blah
     blah     ...

     header:     <html>     <head>     <title>[% template.title
     %]</title></head>     <body bgcolor="[% bgcolor %]">

PROCESS
     The PROCESS option may be set to contain the name(s) of template files
     (relative to INCLUDE_PATH) which should be processed instead of the
     main template passed to the Template process() method.  This can be
     used to apply consistent wrappers around all templates, similar to
     the use of PRE_PROCESS and POST_PROCESS templates.

          my $template = Template->new({
          	PROCESS  => 'content',
          };

          # processes 'content' instead of 'foo.html'
          $template->process('foo.html');

     A reference to the original template is available in the 'template'
     variable.  Metadata items can be inspected and the template can be
     processed by specifying it as a variable reference (i.e. prefixed by
     '$') to an INCLUDE, PROCESS or WRAPPER directive.

     content:     <html>     <head>     <title>[% template.title %]</title>
        </head>

     <body>     [% PROCESS $template %]     <hr>     &copy; Copyright [%
     template.copyright %]     </body>     </html>

     foo.html:     [% META        title     = 'The Foo Page'        author
       = 'Fred Foo'        copyright = '2000 Fred Foo'     %]     <h1>[%
     template.title %]</h1>     Welcome to the Foo Page, blah blah blah

     output:

ERROR
     The ERROR (or ERRORS if you prefer) configuration item can be used to
     name a single template or specify a hash array mapping exception types
     to template names, to be used for error handling.  If an uncaught
     exception is raised from within a template then the appropriate error
     template will instead be processed.

     If specified as a single value then that template will be processed
     for all uncaught exceptions.

          my $template = Template->new({
          	ERROR => 'error.html'
          });

     If the ERROR item is a hash reference the keys are assumed to be
     exception types and the relevant template for a given exception will
     be selected.  A 'default' template may be provided for the general
     case.  Note that 'ERROR' can be pluralised to 'ERRORS' if you find it
     more appropriate in this case.

          my $template = Template->new({
          	ERRORS => {
          	    user     => 'user/index.html',
          	    dbi      => 'error/database',
          	    default  => 'error/default',
          	},
          });

     In this example, any 'user' exceptions thrown will cause the
     'user/index.html' template to be processed, 'dbi' errors are handled
     by 'error/database' and all others by the 'error/default' template.
     Any PRE_PROCESS and/or POST_PROCESS templates will also be applied to
     these error templates.

     Note that exception types are hierarchical and a 'foo' handler will
     catch all 'foo.*' errors (e.g. foo.bar, foo.bar.baz) if a more
     specific handler isn't defined.  Be sure to quote any exception types
     that contain periods to prevent Perl concatenating them into a single
     string (i.e. `user.passwd' is parsed as 'user'.'passwd').

          my $template = Template->new({
          	ERROR => {
          	    'user.login'  => 'user/login.html',
          	    'user.passwd' => 'user/badpasswd.html',
          	    'user'        => 'user/index.html',
          	    'default'     => 'error/default',
          	},
          });

     In this example, any template processed by the $template object, or
     other templates or code called from within, can raise a 'user.login'
     exception and have the service redirect to the 'user/login.html'
     template.  Similarly, a 'user.passwd' exception has a specific
     handling template, 'user/badpasswd.html', while all other 'user' or
     'user.*' exceptions cause a redirection to the 'user/index.html' page.
     All other exception types are handled by 'error/default'.

     Exceptions can be raised in a template using the THROW directive,

          [% THROW user.login 'no user id: please login' %]

     or by calling the throw() method on the current Template::Context
     object,

          $context->throw('user.passwd', 'Incorrect Password');
          $context->throw('Incorrect Password');    # type 'undef'

     or from Perl code by calling die() with a Template::Exception object,

          die Template::Exception->new('user.denied', 'Invalid User ID');

     or by simply calling die() with an error string.  This is
     automagically caught and converted to an  exception of 'undef' type
     which can then be handled in the usual way.

          die "I'm sorry Dave, I can't do that";

OUTPUT
     Default output location or handler.  This may be specified as one of:
     a file name (relative to OUTPUT_PATH, if defined, or the current
     working directory if not specified absolutely); a file handle (e.g.
     GLOB or IO::Handle) opened for writing; a reference to a text string
     to which the output is appended (the string isn't cleared); a
     reference to a subroutine which is called, passing the output text as
     an argument; or as a reference to any object that supports the print()
     method.  This latter option includes the Apache::Request object which
     is passed as the argument to Apache/mod_perl handlers.

     example 1 (file name):

          my $template = Template->new({
          	OUTPUT => "/tmp/foo",
          });

     example 2 (text string):

          my $output = '';

          my $template = Template->new({
          	OUTPUT => \$output,
          });

     example 3 (file handle):

          open (TOUT, "> $file") || die "$file: $!\n";

          my $template = Template->new({
          	OUTPUT => \*TOUT,
          });

     example 4 (subroutine):

          sub output { my $out = shift; print "OUTPUT: $out" }

          my $template = Template->new({
          	OUTPUT => \&output,
          });

     example 5 (Apache/mod_perl handler):

     sub handler { 	my $r = shift;

          my $t = Template->new({
              OUTPUT => $r,
          });

          ...
              }

     The default OUTPUT location be overridden by passing a third parameter
     to the Template process() method.  This can be specified as any of the
     above argument types.

          $t->process($file1, $vars, "/tmp/foo");
          $t->process($file2, $vars, "bar");
          $t->process($file3, $vars, \*MYGLOB);
          $t->process($file4, $vars, $r);  # Apache::Request
          ...

OUTPUT_PATH
     The OUTPUT_PATH allows a directory to be specified into which output
     files should be written.  An output file can be specified by the
     OUTPUT option, or passed by name as the third paramater to the
     Template process() method.

          my $template = Template->new({
          	INPUT_PATH  => "/tmp/src",
          	OUTPUT_PATH => "/tmp/dest",
          });

          my $vars = {
          	...
          };

          foreach my $file ('foo.html', 'bar.html') {
          	$template->process($file, $vars, $file)
          	    || die $template->error();
          }

     This example will read the input files '/tmp/src/foo.html' and
     '/tmp/src/bar.html' and write the processed output to
     '/tmp/dest/foo.html' and '/tmp/dest/bar.html', respectively.

Caching and Compiling Options
-----------------------------

CACHE_SIZE
     The Template::Provider module caches compiled templates to avoid the
     need to re-parse template files or blocks each time they are used.
     The CACHE_SIZE option is used to limit the number of compiled
     templates that the module should cache.

     By default, the CACHE_SIZE is undefined and all compiled templates are
     cached.  When set to any positive value, the cache will be limited to
     storing that many compiled templates.  When a new template is loaded
     and compiled and the cache is full (i.e. the number of entries ==
     CACHE_SIZE), the least recently used compiled template is discarded
     to make room for the new one.

     The CACHE_SIZE can be set to 0 to disable caching altogether.

          my $template = Template->new({
          	CACHE_SIZE => 64,   # only cache 64 compiled templates
          });

          my $template = Template->new({
          	CACHE_SIZE => 0,   # don't cache any compiled templates
          });

COMPILE_EXT
     From version 2 onwards, the Template Toolkit has the ability to
     compile templates to Perl code and save them to disk for subsequent
     use (e.g. cache persistance).  The COMPILE_EXT option may be provided
     to specify a filename extension for compiled template files.  It is
     undefined by default and no attempt will be made to read or write any
     compiled template file.

          my $template = Template->new({
          	COMPILE_EXT => '.ttc',
          });

     If COMPILE_EXT is defined (and COMPILE_DIR isn't, see below) then
     compiled template files with the COMPILE_EXT extension will be
     written to the same directory from which the source template files
     were loaded.

     Compiling and subsequent reuse of templates happens automatically
     whenever the COMPILE_EXT or COMPILE_DIR options are set.  The Template
     Toolkit will automatically reload and reuse compiled files when it
     finds them on disk.  If the corresponding source file has been
     modified since the compiled version as written, then it will load and
     re-compile the source and write a new compiled version to disk.

     This form of cache persistance offers significant benefits in terms of
     time and resources required to reload templates.  Compiled templates
     can be reloaded by a simple call to Perl's require(), leaving Perl to
     handle all the parsing and compilation.  This is a Good Thing.

COMPILE_DIR
     The COMPILE_DIR option is used to specify an alternate directory root
     under which compiled template files should be saved.

          my $template = Template->new({
          	COMPILE_DIR => '/tmp/ttc',
          });

     The COMPILE_EXT option may also be specified to have a consistent file
     extension added to these files.

          my $template1 = Template->new({
          	COMPILE_DIR => '/tmp/ttc',
          	COMPILE_EXT => '.ttc1',
          });

          my $template2 = Template->new({
          	COMPILE_DIR => '/tmp/ttc',
          	COMPILE_EXT => '.ttc2',
          });

     When COMPILE_EXT is undefined, the compiled template files have the
     same name as the original template files, but reside in a different
     directory tree.

     Each directory in the INCLUDE_PATH is replicated in full beneath the
     COMPILE_DIR directory.  This example:

          my $template = Template->new({
          	COMPILE_DIR  => '/tmp/ttc',
          	INCLUDE_PATH => '/home/abw/templates:/usr/share/templates',
          });

     would create the following directory structure:

          /tmp/ttc/home/abw/templates/
          /tmp/ttc/usr/share/templates/

     Files loaded from different INCLUDE_PATH directories will have their
     compiled forms save in the relevant COMPILE_DIR directory.

Plugins and Filters
-------------------

PLUGINS
     The PLUGINS options can be used to provide a reference to a hash array
     that maps plugin names to Perl module names.  A number of standard
     plugins are defined (e.g. 'table', 'cgi', 'dbi', etc.) which map to
     their corresponding Template::Plugin::* couterpart.  These can be
     redefined by values in the PLUGINS hash.

          my $template = Template->new({
          	PLUGINS => [
          	    cgi => 'MyOrg::Template::Plugin::CGI',
          	    foo => 'MyOrg::Template::Plugin::Foo',
          	    bar => 'MyOrg::Template::Plugin::Bar',
          	],
          });

     The USE directive is used to create plugin objects and does so by
     calling the plugin() method on the current Template::Context object.
     If the plugin name is defined in the PLUGINS hash then the
     corresponding Perl module is loaded via require().  The context then
     calls the load() class method which should return the class name
     (default and general case) or a prototype object against which the
     new() method can be called to instantiate individual plugin objects.

     If the plugin name is not defined in the PLUGINS hash then the
     PLUGIN_BASE and/or LOAD_PERL options come into effect.

PLUGIN_BASE
     If a plugin is not defined in the PLUGINS hash then the PLUGIN_BASE
     is used to attempt to construct a correct Perl module name which can
     be successfully loaded.

     The PLUGIN_BASE can be specified as a single value or as a reference
     to an array of multiple values.  The default PLUGIN_BASE value,
     'Template::Plugin', is always added the the end of the PLUGIN_BASE
     list (a single value is first converted to a list).  Each value should
     contain a Perl package name to which the requested plugin name is
     appended.

     example 1:

          my $template = Template->new({
          	PLUGIN_BASE => 'MyOrg::Template::Plugin',
          });

          [% USE Foo %]    # => MyOrg::Template::Plugin::Foo
                             or        Template::Plugin::Foo

     example 2:

          my $template = Template->new({
          	PLUGIN_BASE => [   'MyOrg::Template::Plugin',
          			 'YourOrg::Template::Plugin'  ],
          });

          [% USE Foo %]    # =>   MyOrg::Template::Plugin::Foo
                             or YourOrg::Template::Plugin::Foo
                             or          Template::Plugin::Foo

LOAD_PERL
     If a plugin cannot be loaded using the PLUGINS or PLUGIN_BASE
     approaches then the provider can make a final attempt to load the
     module without prepending any prefix to the module path.  This allows
     regular Perl modules (i.e. those that don't reside in the
     Template::Plugin or some other such namespace) to be loaded and used
     as plugins.

     By default, the LOAD_PERL option is set to 0 and no attempt will be
     made to load any Perl modules that aren't named explicitly in the
     PLUGINS hash or reside in a package as named by one of the PLUGIN_BASE
     components.

     Plugins loaded using the PLUGINS or PLUGIN_BASE receive a reference to
     the current context object as the first argument to the new()
     constructor.  Modules loaded using LOAD_PERL are assumed to not
     conform to the plugin interface.  They must provide a new() class
     method for instantiating objects but it will not receive a reference
     to the context as the first argument.  Plugin modules should provide a
     load() class method (or inherit the default one from the
     Template::Plugin base class) which is called the first time the plugin
     is loaded.  Regular Perl modules need not.  In all other respects,
     regular Perl objects and Template Toolkit plugins are identical.

     If a particular Perl module does not conform to the common, but not
     unilateral, new() constructor convention then a simple plugin wrapper
     can be written to interface to it.

FILTERS
     The FILTERS option can be used to specify custom filters which can
     then be used with the FILTER directive like any other.  These are
     added to the standard filters which are available by default.  Filters
     specified via this option will mask any standard filters of the same
     name.

     The FILTERS option should be specified as a reference to a hash array
     in which each key represents the name of a filter.  The corresponding
     value should contain a reference to an array containing a subroutine
     reference and a flag which indicates if the filter is static (0) or
     dynamic (1).  A filter may also be specified as a solitary subroutine
     reference and is assumed to be static.

          $template = Template->new({
            	FILTERS => {
            	    'sfilt1' =>   \&static_filter,      # static
                  'sfilt2' => [ \&static_filter, 0 ], # same as above
            	    'dfilt1' => [ \&dyanamic_filter_factory, 1 ],
            	},
          });

     Additional filters can be specified at any time by calling the
     define_filter() method on the current Template::Context object.  The
     method accepts a filter name, a reference to a filter subroutine and
     an optional flag to indicate if the filter is dynamic.

          my $context = $template->context();
          $context->define_filter('new_html', \&new_html);
          $context->define_filter('new_repeat', \&new_repeat, 1);

          Static filters are those where a single subroutine reference is used
          for all invocations of a particular filter.  Filters that don't accept
          any configuration parameters (e.g. 'html') can be implemented
          statically.  The subroutine reference is simply returned when that
          particular filter is requested.  The subroutine is called to filter
          the output of a template block which is passed as the only argument.
          The subroutine should return the modified text.

          sub static_filter {
            	my $text = shift;
          	# do something to modify $text...
            	return $text;
          }

     The following template fragment:

          [% FILTER sfilt1 %]
          Blah blah blah.
          [% END %]

     is approximately equivalent to:

          &static_filter("\nBlah blah blah.\n");

     Filters that can accept parameters (e.g. 'truncate') should be
     implemented dynamically.  In this case, the subroutine is taken to be
     a filter 'factory' that is called to create a unique filter subroutine
     each time one is requested.  A reference to the current
     Template::Context object is passed as the first parameter, followed by
     any additional parameters specified.  The subroutine should return
     another subroutine reference (usually a closure) which implements the
     filter.

          sub dynamic_filter_factory {
          	my ($context, @args) = @_;

          return sub {
              my $text = shift;
          	    # do something to modify $text...
          	    return $text;
          }
              }

     The following template fragment:

          [% FILTER dfilt1(123, 456) %]
          Blah blah blah
          [% END %]

     is approximately equivalent to:

          my $filter = &dynamic_filter_factory($context, 123, 456);
          &$filter("\nBlah blah blah.\n");

     See the FILTER directive for further examples.

Compatibility, Customisation and Extension
------------------------------------------

V1DOLLAR
     In version 1 of the Template Toolkit, an optional leading '$' could
     be placed on any template variable and would be silently ignored.

          # VERSION 1
          [% $foo %]       ===  [% foo %]
          [% $hash.$key %] ===  [% hash.key %]

     To interpolate a variable value the '${' ... '}' construct was used.
     Typically, one would do this to index into a hash array when the key
     value was stored in a variable.

     example:

          my $vars = {
          	users => {
          	    aba => { name => 'Alan Aardvark', ... },
          	    abw => { name => 'Andy Wardley', ... },
                  ...
          	},
          	uid => 'aba',
              ...
          };

          $template->process('user/home.html', $vars)
          	|| die $template->error(), "\n";

     'user/home.html':

          [% user = users.${uid} %]     # users.aba
          Name: [% user.name %]         # Alan Aardvark

     This was inconsistent with double quoted strings and also the
     INTERPOLATE mode, where a leading '$' in text was enough to indicate a
     variable for interpolation, and the additional curly braces were used
     to delimit variable names where necessary.  Note that this use is
     consistent with UNIX and Perl conventions, among others.

          # double quoted string interpolation
          [% name = "$title ${user.name}" %]

          # INTERPOLATE = 1
          <img src="$images/help.gif"></a>
          <img src="$images/${icon.next}.gif">

     For version 2, these inconsistencies have been removed and the syntax
     clarified.  A leading '$' on a variable is now used exclusively to
     indicate that the variable name should be interpolated (e.g.
     subsituted for its value) before being used.  The earlier example
     from version 1:

          # VERSION 1
          [% user = users.${uid} %]
          Name: [% user.name %]

     can now be simplified in version 2 as:

          # VERSION 2
          [% user = users.$uid %]
          Name: [% user.name %]

     The leading dollar is no longer ignored and has the same effect of
     interpolation as '${' ... '}' in version 1.  The curly braces may
     still be used to explicitly scope the interpolated variable name
     where necessary.

     e.g.

          [% user = users.${me.id} %]
          Name: [% user.name %]

     The rule applies for all variables, both within directives and in
     plain text if processed with the INTERPOLATE option.  This means that
     you should no longer (if you ever did) add a leading '$' to a variable
     inside a directive, unless you explicitly want it to be interpolated.

     One obvious side-effect is that any version 1 templates with variables
     using a leading '$' will no longer be processed as expected.  Given
     the following variable definitions,

          [% foo = 'bar'
             bar = 'baz'
          %]

     version 1 would interpret the following as:

          # VERSION 1
          [% $foo %] => [% GET foo %] => bar

     whereas version 2 interprets it as:

          # VERSION 2
          [% $foo %] => [% GET $foo %] => [% GET bar %] => baz

     In version 1, the '$' is ignored and the value for the variable 'foo'
     is retrieved and printed.  In version 2, the variable '$foo' is first
     interpolated to give the variable name 'bar' whose value is then
     retrieved and printed.

     The use of the optional '$' has never been strongly recommended, but
     to assist in backwards compatibility with any version 1 templates that
     may rely on this "feature", the V1DOLLAR option can be set to 1
     (default: 0) to revert the behaviour and have leading '$' characters
     ignored.

          my $template = Template->new({
          	V1DOLLAR => 1,
          });

LOAD_TEMPLATES
     The LOAD_TEMPLATE option can be used to provide a reference to a list
     of Template::Provider objects or sub-classes thereof which will take
     responsibility for loading and compiling templates.

          my $template = Template->new({
          	LOAD_TEMPLATES => [
          	    MyOrg::Template::Provider->new({ ... }),
          	    Template::Provider->new({ ... }),
          	],
          });

     When a PROCESS, INCLUDE or WRAPPER directive is encountered, the named
     template may refer to a locally defined BLOCK or a file relative to
     the INCLUDE_PATH (or an absolute or relative path if the appropriate
     ABSOLUTE or RELATIVE options are set).  If a BLOCK definition can't be
     found (see the Template::Context template() method for a discussion of
     BLOCK locality) then each of the LOAD_TEMPLATES provider objects is
     queried in turn via the fetch() method to see if it can supply the
     required template.  Each provider can return a compiled template, an
     error, or decline to service the request in which case the
     responsiblity is passed to the next provider.  If none of the
     providers can service the request then a 'not found' error is
     returned.  The same basic provider mechanism is also used for the
     INSERT directive but it bypasses any BLOCK definitions and doesn't
     attempt is to parse or process the contents of the template file.

     This is an implementation of the 'Chain of Responsiblity' design
     pattern as described in "Design Patterns", Erich Gamma, Richard Helm,
     Ralph Johnson, John Vlissides), Addision-Wesley, ISBN 0-201-63361-2,
     page 223.

     If LOAD_TEMPLATES is undefined, a single default provider will be
     instantiated using the current configuration parameters.  For example,
     the Template::Provider INCLUDE_PATH option can be specified in the
     Template configuration and will be correctly passed to the provider's
     constructor method.

          my $template = Template->new({
          	INCLUDE_PATH => '/here:/there',
          });

LOAD_PLUGINS
     The LOAD_PLUGINS options can be used to specify a list of provider
     objects (i.e. they implement the fetch() method) which are responsible
     for loading and instantiating template plugin objects.  The plugin()
     method queries each provider in turn in a "Chain of Responsibility" as
     per the template() and filter() methods.

          my $template = Template->new({
          	LOAD_PLUGINS => [
          	    MyOrg::Template::Plugins->new({ ... }),
          	    Template::Plugins->new({ ... }),
          	],
          });

     By default, a single Template::Plugins object is created using the
     current configuration hash.  Configuration items destined for the
     Template::Plugins constructor may be added to the Template
     constructor.

          my $template = Template->new({
          	PLUGIN_BASE => 'MyOrg::Template::Plugins',
          	LOAD_PERL   => 1,
          });

LOAD_FILTERS
     The LOAD_FILTERS option can be used to specify a list of provider
     objects (i.e. they implement the fetch() method) which are responsible
     for returning and/or creating filter subroutines.  The filter()
     method queries each provider in turn in a "Chain of Responsibility" as
     per the template() and plugin() methods.

          my $template = Template->new({
          	LOAD_FILTERS => [
          	    MyTemplate::Filters->new(),
          	    Template::Filters->new(),
          	],
          });

     By default, a single Template::Filters object is created for the
     LOAD_FILTERS list.

TOLERANT
     The TOLERANT flag is used by the various Template Toolkit provider
     modules (Template::Provider, Template::Plugins, Template::Filters) to
     control their behaviour when errors are encountered.  By default, any
     errors are reported as such, with the request for the particular
     resource (template, plugin, filter) being denied and an exception
     raised.  When the TOLERANT flag is set to any true values, errors will
     be silently ignored and the provider will instead return
     STATUS_DECLINED.  This allows a subsequent provider to take
     responsibility for providing the resource, rather than failing the
     request outright.  If all providers decline to service the request,
     either through tolerated failure or a genuine disinclination to
     comply, then a '<resource> not found' exception is raised.

SERVICE
     A reference to a Template::Service object, or sub-class thereof, to
     which the Template module should delegate.  If unspecified, a
     Template::Service object is automatically created using the current
     configuration hash.

          my $template = Template->new({
          	SERVICE => MyOrg::Template::Service->new({ ... }),
          });

CONTEXT
     A reference to a Template::Context object which is used to define a
     specific environment in which template are processed.  A
     Template::Context object is passed as the only parameter to the Perl
     subroutines that represent "compiled" template documents.  Template
     subroutines make callbacks into the context object to access Template
     Toolkit functionality, for example, to to INCLUDE or PROCESS another
     template (include() and process() methods, respectively), to USE a
     plugin (plugin()) or instantiate a filter (filter()) or to access the
     stash (stash()) which manages variable definitions via the get() and
     set() methods.

          my $template = Template->new({
          	CONTEXT => MyOrg::Template::Context->new({ ... }),
          });

STASH
     A reference to a Template::Stash object or sub-class which will take
     responsibility for managing template variables.

          my $stash = MyOrg::Template::Stash->new({ ... });
          my $template = Template->new({
          	STASH => $stash,
          });

     If unspecified, a default stash object is created using the VARIABLES
     configuration item to initialise the stash variables.  These may also
     be specified as the PRE_DEFINE option for backwards compatibility with
     version 1.

          my $template = Template->new({
          	VARIABLES => {
          	    id    => 'abw',
          	    name  => 'Andy Wardley',
          	},
          };

PARSER
     The Template::Parser module implements a parser object for compiling
     templates into Perl code which can then be executed.  A default object
     of this class is created automatically and then used by the
     Template::Provider whenever a template is loaded and requires
     compilation.  The PARSER option can be used to provide a reference to
     an alternate parser object.

          my $template = Template->new({
          	PARSER => MyOrg::Template::Parser->new({ ... }),
          });

GRAMMAR
     The GRAMMAR configuration item can be used to specify an alternate
     grammar for the parser.  This allows a modified or entirely new
     template langauge to be constructed and used by the Template Toolkit.

     Source templates are compiled to Perl code by the Template::Parser
     using the Template::Grammar (by default) to define the language
     structure and semantics.  Compiled templates are thus inherently
     "compatible" with each other and there is nothing to prevent any
     number of different template languages being compiled and used within
     the same Template Toolkit processing environment (other than the usual
     time and memory constraints).

     The Template::Grammar file is constructed from a YACC like grammar
     (using Parse::YAPP) and a skeleton module template.  These files are
     provided, along with a small script to rebuild the grammar, in the
     'parser' sub-directory of the distribution.  You don't have to know or
     worry about these unless you want to hack on the template language or
     define your own variant.  There is a README file in the same directory
     which provides some small guidance but it is assumed that you know
     what you're doing if you venture herein.  If you grok LALR parsers,
     then you should find it comfortably familiar.

     By default, an instance of the default Template::Grammar will be
     created and used automatically if a GRAMMAR item isn't specified.

          use MyOrg::Template::Grammar;

          my $template = Template->new({
             	GRAMMAR = MyOrg::Template::Grammar->new();
          });

TEMPLATE TOOLKIT FILTERS
========================

   The following standard filters are distributed with the Template
Toolkit.

html
     Converts the characters '<', '>' and '&' to '&lt;', '&gt;' and '&amp',
     respectively, protecting them from being interpreted as representing
     HTML tags or entities.

          [% FILTER html %]
          Binary "<=>" returns -1, 0, or 1 depending on...
          [% END %]

     output:

          Binary "&lt;=&gt;" returns -1, 0, or 1 depending on...

html_para
     This filter formats a block of text into HTML paragraphs.  A sequence
     of two or more newlines is used as the delimiter for paragraphs which
     are then wrapped in HTML <p>...</p> tags.

          [% FILTER html_para %]
          The cat sat on the mat.

          Mary had a little lamb.
          [% END %]

     output:

          <p>
          The cat sat on the mat.
          </p>

          <p>
          Mary had a little lamb.
          </p>

html_break
     Similar to the html_para filter described above, but uses the HTML tag
     sequence <br><br> to join paragraphs.

          [% FILTER html_para %]
          The cat sat on the mat.

          Mary had a little lamb.
          [% END %]

     output:

          The cat sat on the mat.
          <br>
          <br>
          Mary had a little lamb.

format(format)
     The 'format' filter takes a format string as a parameter (as per
     printf()) and formats each line of text accordingly.

          [% FILTER format('<!-- %-40s -->') %]
          This is a block of text filtered
          through the above format.
          [% END %]

     output:

          <!-- This is a block of text filtered        -->
          <!-- through the above format.               -->

truncate(length)
     Truncates the text block to the length specified, or a default length
     of 32.  Truncated text will be terminated with '...' (i.e. the '...'
     falls inside the required length, rather than appending to it).

          [% FILTER truncate(21) %]
          I have much to say on this matter that has previously
          been said on more than one occassion.
          [% END %]

     output:

          I have much to say...

repeat(iterations)
     Repeats the text block for as many iterations as are specified
     (default: 1).

          [% FILTER repeat(3) %]
          Am I repeating myself?
          [% END %]

     output:

          Am I repeating myself?
          Am I repeating myself?
          Am I repeating myself?

remove(string)
     Searches the input text for any occurences of the specified string and
     removes them.  A Perl regular expression may be specified as the
     search string.

          [% "The  cat  sat  on  the  mat" FILTER remove('\s+') %]

     output:

          Thecatsatonthemat

     The '|' character is an alias for FILTER, allowing the previous
     example to be written as:

          [% "The  cat  sat  on  the  mat" | remove('\s+') %]

replace(search, replace)
     Similar to the remove filter described above, but taking a second
     parameter which is used as a replacement string for instances of the
     search string.

          [% "The  cat  sat  on  the  mat" | replace('\s+', '_') %]

     output:

          The_cat_sat_on_the_mat

redirect(file)
     The 'redirect' filter redirects the output of the block into a
     separate file, specified relative to the OUTPUT_PATH configuration
     item.

          [% FOREACH user = myorg.userlist %]
             [% FILTER redirect("users/${user.id}.html") %]
                [% INCLUDE userinfo %]
             [% END %]
          [% END %]

     A 'file' exception will be thrown if the OUTPUT_PATH option is
     undefined.

eval(template_text)
     The 'eval' filter evaluates the block as template text, processing
     any directives embedded within it.  This allows template variables to
     contain template fragments, or for some method to be provided for
     returning template fragments from an external source such as a
     database, which can then be processed in the template as required.

          my $replace  = {
          	fragment => "The cat sat on the [% place %]",
          };
          $template->process($file, $replace);

     The following example:

          [% fragment | eval %]

     is therefore equivalent to

          The cat sat on the [% place %]

evalperl(perlcode)
     The 'evalperl' filter evaluates the block as Perl code.  The EVAL_PERL
     option must be set to a true value or a 'perl' exception will be
     thrown.

          [% my_perl_code | evalperl %]

     In most cases, the [% PERL %] ... [% END %] block should suffice for
     evaluating Perl code, given that template directives are processed
     before being evaluate as Perl.  Thus, the previous example could have
     been written in the more verbose form:

          [% PERL %]
          [% my_perl_code %]
          [% END %]

     as well as

          [% FILTER evalperl %]
          [% my_perl_code %]
          [% END %]

     It is an unfortunate circumstance that this filter cannot simply be
     called 'perl'.  This is due to the clash with the reserved word of
     that name (i.e. PERL blocks).

TEMPLATE TOOLKIT PLUGINS
========================

   The following plugin modules are distributed with the Template Toolkit.

Date
     The Date plugin provides an easy way to generate formatted time and
     date strings by delegating to the POSIX strftime() routine.   See
     Template/Plugin/Date, for further details.

          [% USE date %]
          [% date.format %]		# current time/date

          File last modified: [% date.format(template.modtime) %]

Format
     The Format plugin provides a simple way to format text according to a
     printf()-like format.   See Template/Plugin/Format,
     for further details.

          [% USE bold = format('<b>%s</b>') %]
          [% bold('Hello') %]

URL
     The URL plugin provides a simple way of contructing URLs from a base
     part and a variable set of parameters.  See
     Template/Plugin/URL, for further details.

          [% USE mycgi = url('/cgi-bin/bar.pl', debug=1) %]

          [% mycgi %]
             # ==> /cgi/bin/bar.pl?debug=1

          [% mycgi(mode='submit') %]
             # ==> /cgi/bin/bar.pl?mode=submit&debug=1

Table
     The Table plugin allows you to format a list of data items into a
     virtual table by specifying a fixed number of rows or columns, with
     an optional overlap.  See Template/Plugin/Table,
     for further details.

          [% USE table(list, rows=10, overlap=1) %]

          [% FOREACH item = table.col(3) %]
             [% item %]
          [% END %]

CGI
     The CGI plugin is a wrapper around Lincoln Stein's
     <lstein@genome.wi.mit.edu> CGI.pm module.  The plugin is distributed
     with the Template Toolkit (see Template/Plugin/CGI)
     and the CGI module itself is distributed with
     recent versions Perl, or is available from CPAN.

Datafile
     Provides an interface to data stored in a plain text file in a simple
     delimited format.  The first line in the file specifies field names
     and subsequent lines contain data, delimited by the same non-word
     character as the fields in the first line.  Blank lines and comments
     (lines starting '#' are ignored).   See
     Template/Plugin/Datafile, for further
     details.

     /tmp/mydata:

          # define names for each field
          id : email : name : tel
          # here's the data
          fred : fred@here.com : Fred Smith : 555-1234
          bill : bill@here.com : Bill White : 555-5678

     example:

          [% USE userlist = datafile('/tmp/mydata') %]

          [% FOREACH user = userlist %]
             [% user.name %] ([% user.id %])
          [% END %]

XML::DOM
     The XML::DOM plugin gives access to the XML Document Object Module via
     Clark Cooper <cooper@sch.ge.com> and Enno Derksen's <enno@att.com>
     XML::DOM module.  The plugin is distributed with the Template Toolkit
     (see Template/Plugin/XML/DOM) and
     requires the XML::DOM module, available from CPAN:

          http://www.cpan.org/modules/by-module/XML

XML::RSS
     The XML::RSS plugin is a simple interface to Jonathan Eisenzopf's
     <eisen@pobox.com> XML::RSS module.  An RSS (Rich Site Summary) file
     is typically used to store short news 'headlines' describing
     different links within a site.  This plugin allows you to parse RSS
     files and format the contents accordingly using templates.  The
     plugin is distributed with the Template Toolkit (see
     Template/Plugin/XML/RSS) and requires the
     XML::RSS module, also available from CPAN:

          http://www.cpan.org/modules/by-module/XML

   The following module is distributed separately from the Template
Toolkit.

DBI
     Simon Matthews <sam@knowledgepool.com> has developed a DBI plugin for
     the Template Toolkit which brings the full power of Tim Bunce's
     <Tim.Bunce@ig.co.uk> database interface module (DBI) to your
     templates.  The DBI plugin and the DBI modules themselves are
     available from CPAN at:

          http://www.cpan.org/modules/by-module/Template/
          http://www.cpan.org/modules/by-module/DBI/

SEE ALSO
========

   The Template Toolkit web site contains the latest information, news and
other resources.

     http://www.template-toolkit.org/

   A mailing list exists for up-to-date information on the Template Toolkit
and for following and contributing to the development process.  To
subscribe, send an email to

     templates-request@template-toolkit.org

   with the message 'subscribe' in the body.  You can also use the web
interface to subscribe or browse the archives:

     http://www.template-toolkit.org/mailman/listinfo/templates

   The `tpage' and `ttree' scripts are distributed and installed along
with the Template Toolkit.  The `tpage' script simply processes named
files or STDIN if unspecified, using a default Template object.  The
`ttree' script can be used to process entire directory trees of templates,
allowing large content systems such as web sites to be rebuilt from a
single command or configuration file.

     perldoc tpage
     perldoc ttree

   The `Template::Tutorial' document provides an introduction to the
Template Toolkit and shows some typical examples of usage.

     perldoc Template::Tutorial

   You may also like to consult the paper 'Building and Managing Web
Systems with the Template Toolkit' and accompanying slides from the
presentation at the 4th Perl Conference.  These are available from the
Template Toolkit web site:

     http://www.template-toolkit.org/docs.html

   The following modules comprise the Template Toolkit.  Consult the
individual documentation for further details.

`Template::Service|Template::Service' in this node
     The Template::Service module handles the template processing
     lifecycle, adding PRE_PROCESS and POST_PROCESS templates, handling
     redirection through any defined PROCESS template, and dispatching any
     ERROR templates to handle uncaught exceptions.  The actual processing
     of these templates is handled by an underlying
     `Template::Context|Template::Context' in this node object.

`Template::Context|Template::Context' in this node
     The Template::Context module defines a class of objects which each
     represent a unique run-time environment in which templates are
     processed.  The context maintains references to the stash of variables
     currently defined (`Template::Stash|Template::Stash' in this node)
     and to provider objects for templates
     (`Template::Provider|Template::Provider' in this node), filters
     (`Template::Filters|Template::Filters' in this node) and plugins
     (`Template::Plugins|Template::Plugins' in this node).

`Template::Stash|Template::Stash' in this node
     The Template::Stash module defines an object class which is used for
     storing, retrieving and evaluating variables and their values.

`Template::Provider|Template::Provider' in this node
     The Template::Provider module defines an object class which is used to
     find, load, parse, compile and then cache template documents.  The
     cache implements a simple fetch($template) method which will accept a
     wide range of inputs (filename, text ref, GLOB, IO::Handle, etc) and
     attempt to read the template and call on a
     `Template::Parser|Template::Parser' in this node to parse and compile
     it to a `Template::Document|Template::Document' in this node which is
     then cached.

`Template::Document|Template::Document' in this node
     Template::Document objects are thin wrappers around the Perl
     subroutines which have been compiled from source templates by the
     `Template::Parser|Template::Parser' in this node.  These objects also
     maintain any metadata values for the template and have references to
     any BLOCKs defined within the the template.

`Template::Parser|Template::Parser' in this node
     The Template::Parser module defines an object class which implements
     the template parser and compiler.  The template text is first scanned
     by a Perl regex which extracts the embedded directives and lexes the
     tokens contained within.  A DFA (Deterministic Finite-state Automaton)
     then iterates through the tokens using the rules and states defined in
     `Template::Grammar|Template::Grammar' in this node and generates a
     compiled template document as a Perl subroutine.

`Template::Grammar|Template::Grammar' in this node
     The Template::Grammar module defines the rules and state tables for
     the `Template::Parser|Template::Parser' in this node DFA.  These are
     generated by the Parse::Yapp module.  The Template-Toolkit
     distribution contains a parser directory which contains further files
     and information concerning the grammar and compilation thereof.

`Template::Directive|Template::Directive' in this node
     This module implements a number of factory methods which are used by
     the `Template::Parser|Template::Parser' in this node to generate Perl
     code from source templates.

`Template::Filters|Template::Filters' in this node
     This module implements the various FILTER subroutines and provides a
     simple interface through which filter subs can be retrieved.

`Template::Plugins|Template::Plugins' in this node
     This module provides access to the standard Template Toolkit or user
     defined plugin modules.

`Template::Plugin|Template::Plugin' in this node
     Base class for Template::Plugin::* modules.

`Template::Exception|Template::Exception' in this node
     The Template::Exception module defines an exception type for
     representing error conditions within the Template Toolkit.

`Template::Iterator|Template::Iterator' in this node
     The Template::Iterator module defines a data iterator which is used
     by the FOREACH directive.  This may be sub-classed to create more
     specialised iterators for traversing data sets.

`Template::Constants|Template::Constants' in this node
     Defines various constants used in the Template Toolkit.

`Template::Config|Template::Config' in this node
     Implements a number of factory methods through which other Template::*
     modules can be automatically loaded and instantiated.

`Template::Base|Template::Base' in this node
     A common base class for many Template::* modules.

`Template::Test|Template::Test' in this node
     Module for testing the Template Toolkit, primarily used by the test
     scripts in the 't' distribution sub-directory.

AUTHOR
======

   Andy Wardley <abw@kfs.org>

     http://www.template-toolkit.org/
     http://www.kfs.org/~abw/

COPYRIGHT
=========

     Copyright (C) 1996-2000 Andy Wardley.  All Rights Reserved.
     Copyright (C) 1998-2000 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

ACKNOWLEDGEMENTS
================

   The Template Toolkit was derived in part from ideas and techniques
developed in the Text::MetaText module.  This itself was the public
manifestation of an earlier template processing system I developed while
working at Peritas Ltd. (http://www.knowledgepool.com/).

   In later years, the Template Toolkit was developed Canon Research
Centre Europe Ltd. (http://www.cre.canon.co.uk) as part of a general
research theme into Web-related publishing and dynamic content generation.

   Many people have contributed ideas, inspiration, fixes and features to
the Template Toolkit.  Their efforts continue to be very much appreciated.
Please let me know if you think anyone is missing from this list.

     Chuck Adams               <scrytch@uswest.net>
     Thierry-Michel Barral     <kktos@electron-libre.com>
     Neil Bowers               <neilb@cre.canon.co.uk>
     Leon Brocard              <acme@astray.com>
     Chris Dean                <ctdean@babycenter.com>
     Francois Desarmenien      <desar@club-internet.fr>
     Horst Dumcke              <hdumcke@cisco.com>
     Michael Fowler            <michael@shoebox.net>
     Perrin Harkins            <pharkins@etoys.com>
     Rafael Kitover            <caelum@debian.org>
     Hans von Lengerke         <hans@lengerke.org>
     Jonas Liljegren           <jonas@paranormal.se>
     Simon Matthews            <sam@knowledgepool.com>
     Craig McLane              <mclanec@oxy.edu>
     Leslie Michael Orchard    <deus_x@ninjacode.com>
     Eugene Miretskiy          <eugene@invision.net>
     Martin Portman            <mrp@cre.canon.co.uk>
     Randal L. Schwartz        <merlyn@stonehenge.com>
     Paul Sharpe               <paul@miraclefish.com>
     Doug Steinwand            <dsteinwand@etoys.com>
     Drew Taylor               <dtaylor@vialogix.com>
     Swen Thuemmler            <Swen.Thuemmler@paderlinx.de>
     Jim Vaughan               <jim@mrjim.com>
     Chris Winters             <cwinters@intes.net

base class module implementing common functionality
***************************************************

NAME
====

   Template::Base - base class module implementing common functionality

SYNOPSIS
========

     package Template::MyModule;
     use base qw( Template::Base );

     sub _init {
     	my ($self, $config) = @_;
     	$self->{ doodah } = $config->{ doodah }
     	    || return $self->error("No 'doodah' specified");
     	return $self;
     }

DESCRIPTION
===========

   Base class module which implements a constructor and error reporting
functionality for various Template Toolkit modules.

PUBLIC METHODS
==============

new(\%config)
-------------

   Constructor method which accepts a reference to a hash array or a list
of `name => value' parameters which are folded into a hash.  The _init()
method is then called, passing the configuration hash and should return
true/false to indicate success or failure.  A new object reference is
returned, or undef on error.  Any error message raised can be examined via
the error() class method or directly via the package variable ERROR in the
derived class.

     my $module = Template::MyModule->new({ ... })
         || die Template::MyModule->error(), "\n";

     my $module = Template::MyModule->new({ ... })
         || die "constructor error: $Template::MyModule::ERROR\n";

error($msg)
-----------

   May be called as an object method to get/set the internal _ERROR member
or as a class method to get/set the $ERROR variable in the derived class's
package.

     my $module = Template::MyModule->new({ ... })
         || die Template::MyModule->error(), "\n";

     $module->do_something()
     	|| die $module->error(), "\n";

   When called with parameters (multiple params are concatenated), this
method will set the relevant variable and return undef.  This is most
often used within object methods to report errors to the caller.

     package Template::MyModule;

     ...

     sub foobar {
     	my $self = shift;
     	...
     	return $self->error('some kind of error...')
     	    if $some_condition;
     	...
     }

AUTHOR
======

   Andy Wardley <abw@kfs.org>

     http://www.template-toolkit.org/
     http://www.kfs.org/~abw/

REVISION
========

   $Revision: 1.1 $

COPYRIGHT
=========

     Copyright (C) 1996-2000 Andy Wardley.  All Rights Reserved.
     Copyright (C) 1998-2000 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   L<Template|Template

object for loading, compiling and caching template documents
************************************************************

NAME
====

   Template::Cache - object for loading, compiling and caching template
documents

SYNOPSIS
========

     use Template::Cache;

     $cache    = Template::Cache->new({
     		    INCLUDE_PATH = \@search_path,
     		});

     $template = $cache->fetch($filename);
     $template = $cache->fetch($filehandle, $name);
     $template = $cache->fetch(\$text, $name);

     warn $cache->error()
         unless $template;

     $cache->store($template, $name);

DESCRIPTION
===========

   The Template::Cache module defines an object class which is used to
find, load, compile and cache template document files.  A Template::Cache
object is created by, or supplied as a configuration item to a
Template::Context which calls its fetch() method to request templates as
they are required.

   The cache can load templates from files specified either by filename or
by passing a file handle or GLOB reference (e.g. \*STDIN) to the fetch()
method.  A reference to a text string containing the template text may
also be passed to fetch(). This method returns a cache version of the
template document if it exists or calls _load() to load and compile the
template.  Compiled templates are then cached by their filename or a
specific alias which can be passed as a second parameter to fetch().  A
template whose source is a file handle, glob or text reference (i.e.  the
first parameter is any kind of reference) will not be cached unless an
alias is specifically provided.

   The _load() method takes the input source (filename, file handle, text
ref, etc.) as its only parameter and attempts to read the content.  If a
filename has been specified then the method will look in each directory
specified in the PATH configuration option to find the file.  If the PATH
has not been specified then the current directory only is searched.

   Once loaded, the template text is passed to _compile() which delegates
the task of parsing and compiling the document to a Template::Parser
object.  The PARSER configuration option may be specified to provide a
reference to a Template::Parser, or subclass thereof, which should be used
instead.  See Template/Parser, for further
information.

   In some environments it is desirable to share a template cache among
multiple template processors.  In an Apache/mod_perl server, for example,
one may have different template processors rendering different parts of a
web site but sharing the same template repository.  This can be acheived
by explicitly supplying a reference to a Template::Cache as the CACHE
configuration item passed to the Template constructor, new().  This is
then passed to the Template::Context constructor.

     use Template;

     my $cache = Template::Cache->new({
     	INCLUDE_PATH => '/user/abw/templates:/usr/local/templates',
     });

     my $tp1 = Template->new({
     	CACHE => $cache,
     });

     my $tp2 = Template->new({
     	CACHE => $cache,
     });

PUBLIC METHODS
==============

new(\%config)
-------------

   Constructor method which instantiates a new Template::Cache object.  A
hash reference may be passed containing the following configuration items:

CACHE
     The CACHE option specifies to default behaviour for the cache:
     whether to cache compiled documents or not.  A value of 1 (CACHE_ALL)
     will cause all compiled templates to be cached.  A value of 0
     (CACHE_NONE) will cause none of them to be cached and re-parsed on
     demand.  The default is CACHE_ALL.

     The Template::Constants provides a ':cache' export tagset which
     imports the definitions for CACHE_ALL and CACHE_NONE.  Other caching
     strategies may be support in the future.

     The CACHE option can also be applied on a per-directory basis, as
     shown below.

INCLUDE_PATH
     The INCLUDE_PATH option specifies one or directories in which to look
     for template files.  Multiple directories can be delimited by a ':'
     (or the value of the PATH_SEPARATOR) or specified as a reference to a
     list.

          my $cache = Template::Cache->new({
          	INCLUDE_PATH => '/usr/local/templates:/usr/web/templates',
          });

          my $cache = Template::Cache->new({
          	INCLUDE_PATH => [ '/usr/local/templates', '/usr/web/templates' ],
          });

     Each directory entry may be followed by a hash array reference
     containing caching options specific to those directories.

          use Template::Cache;
          use Template::Constants qw( :cache );

          my $tcache = Template::Cache->new({
          	INCLUDE_PATH => [
          	    # CACHE_ALL files (default) in these directories
          	    '/user/web/elements:/usr/local/web/elements'
          	    # CACHE_NONE of the files from this directory
          	    '/user/web/templates' => { CACHE => CACHE_NONE },

          ],
              });

PARSER
     A reference to a Template::Parser object, or sub-class thereof, which
     should be used for parsing and compiling templates as they are loaded.
     A default Template::Parser object when first used if this option is
     not specified.

fetch($template, $alias)
------------------------

   This method is called to load, parse and compile template documents.
The first parameter should contain the name of a template file relative to
one of the PATH directories, or in the current directory if PATH wasn't
specified.  Alternatively, $template may be a reference to a SCALAR
variable containing the template text, or a reference to a file handle
(e.g. IO::Handle et al) or GLOB from which the template content should be
read.

   The compiled template is then cached internally using the template file
name or another alias specified as the second parameter.  If $template is
a reference then it will only be cached if an $alias is provided.  The
template will not be cache if $alias is set to 0.

   Future calls to fetch() where $template matches a cached entry will
return the compiled template without re-compiling it.

     $t = $cache->fetch('myfile');	# compiles template
     $t = $cache->fetch('myfile');	# returns cached version
     $t = $cache->fetch($filehandle);    # read file - don't cache
     $t = $cache->fetch(\*DATA, 'foo');  # read file, cache as 'foo'
     $t = $cache->fetch('foo');          # return cached 'foo'

   Calling fetch() with a non-zero alias will always cause the entry to be
cached under that name.  If $template represents an existing template in
the cache then it will cached under the new $alias as well as the original
cache name.

store($template, $alias)
------------------------

   Allows a pre-compiled template block ($template) to be added to the
cache under a given name ($alias).

     if ($compiled = $cache->compile($mytext)) {
     	$cache->store($compiled, 'my_compiled_template')
     }

error()
-------

   Returns the current error condition which is represented as a
`Template::Exception|Template::Exception' in this node object.

AUTHOR
======

   Andy Wardley <cre.canon.co.uk>

REVISION
========

   $Revision: 1.17 $

COPYRIGHT
=========

   Copyright (C) 1996-1999 Andy Wardley.  All Rights Reserved.  Copyright
(C) 1998-1999 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Template|Template' in this node

factory module for loading and instantiating other toolkit modules
******************************************************************

NAME
====

   Template::Config - factory module for loading and instantiating other
toolkit modules

SYNOPSIS
========

     use Template::Config;

DESCRIPTION
===========

   This module implements various methods for loading and instantiating
other modules that comprise the Template Toolkit.  It provides a consistent
way to create toolkit components and allows custom modules to be used in
place of the regular ones.

   Package variables such as $STASH, $SERVICE, $CONTEXT, etc., contain the
default module/package name for each component (Template::Stash,
Template::Service and Template::Context, respectively) and are used by the
various factory methods (stash(), service() and context()) to load the
appropriate module.  Changing these package variables will cause
subsequent calls to the relevant factory method to load and instantiate an
object from the new class.

PUBLIC METHODS
==============

load($module)
-------------

   Load a module via require().  Any occurences of '::' in the module name
are be converted to '/' and '.pm' is appended.  Returns 1 on success or
undef on error.  Use $class->error() to examine the error string.

parser(\%config)
----------------

   Instantiate a new parser object of the class whose name is denoted by
the package variable $PARSER (default: Template::Parser).  Returns a
reference to a newly instantiated parser object or undef on error.

provider(\%config)
------------------

   Instantiate a new template provider object (default:
Template::Provider).  Returns an object reference or undef on error, as
above.

plugins(\%config)
-----------------

   Instantiate a new plugins provider object (default: Template::Plugins).
Returns an object reference or undef on error, as above.

filters(\%config)
-----------------

   Instantiate a new filter provider object (default: Template::Filters).
Returns an object reference or undef on error, as above.

stash(\%vars)
-------------

   Instantiate a new stash object (default: Template::Templates) using the
contents of the optional hash array passed by parameter as initial variable
definitions.  Returns an object reference or undef on error, as above.

context(\%config)
-----------------

   Instantiate a new template context object (default: Template::Context).
Returns an object reference or undef on error, as above.

service(\%config)
-----------------

   Instantiate a new template service object (default: Template::Service).
Returns an object reference or undef on error, as above.

AUTHOR
======

   Andy Wardley <abw@kfs.org>

     http://www.template-toolkit.org/
     http://www.kfs.org/~abw/

REVISION
========

   $Revision: 1.1 $

COPYRIGHT
=========

     Copyright (C) 1996-2000 Andy Wardley.  All Rights Reserved.
     Copyright (C) 1998-2000 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   L<Template|Template

defines constants for the Template Toolkit
******************************************

NAME
====

   Template::Constants - defines constants for the Template Toolkit

SYNOPSIS
========

     use Template::Constants qw( :status :error :all );

DESCRIPTION
===========

   The Template::Constants modules defines, and optionally exports into the
caller's namespace, a number of constants used by the Template package.

   Constants may be used by specifying the Template::Constants package
explicitly:

     use Template::Constants;

     print Template::Constants::STATUS_DECLINED;

   Constants may be imported into the caller's namespace by naming them as
options to the `use Template::Constants' statement:

     use Template::Constants qw( STATUS_DECLINED );

     print STATUS_DECLINED;

   Alternatively, one of the following tagset identifiers may be specified
to import sets of constants; :status, :error, :all.

     use Template::Constants qw( :status );

     print STATUS_DECLINED;

   See Exporter, for more information on exporting
variables.

EXPORTABLE TAG SETS
===================

   The following tag sets and associated constants are defined:

     :status
       STATUS_OK                 # no problem, continue
       STATUS_RETURN             # ended current block then continue (ok)
       STATUS_STOP               # controlled stop (ok)
       STATUS_DONE               # iterator is all done (ok)
       STATUS_DECLINED           # provider declined to service request (ok)
       STATUS_ERROR              # general error condition (not ok)

     :error
       ERROR_RETURN              # return a status code (e.g. 'stop'
       ERROR_FILE		      # file error: I/O, parse, recursion
       ERROR_UNDEF		      # undefined variable value used
       ERROR_PERL                # error in [% PERL %] block

     :all         All the above constants.

AUTHOR
======

   Andy Wardley <abw@kfs.org>

     http://www.template-toolkit.org/
     http://www.kfs.org/~abw/

REVISION
========

   $Revision: 1.1 $

COPYRIGHT
=========

     Copyright (C) 1996-2000 Andy Wardley.  All Rights Reserved.
     Copyright (C) 1998-2000 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Template|Template' in this node, L<Exporter|Exporter

runtime context in which templates are processed
************************************************

NAME
====

   Template::Context - runtime context in which templates are processed

SYNOPSIS
========

     use Template::Context;

     # constructor
     $context = Template::Context->new(\%config)
     	|| die $Template::Context::ERROR;

     # fetch (load and compile) a template
     $template = $context->template($template_name)
     	|| die $context->error();

     # fetch (load and instantiate) a plugin object
     $plugin = $context->plugin($name, \@args)
     	|| die $context->error();

     # fetch (return or create) a filter subroutine
     $filter = $context->filter($name, \@args, $alias)
     	|| die $context->error();

     # process/include a template, errors are thrown via die()
     $output = $context->process($template, \%vars);
     $output = $context->include($template, \%vars);

     # raise an exception via die()
     $context->throw($error_type, $error_message, \$output_buffer);

     # catch an exception, clean it up and fix output buffer
     $exception = $context->catch($exception, \$output_buffer);

     # save/restore the stash to effect variable localisation
     $new_stash = $context->localise(\%vars);
     $old_stash = $context->delocalise();

     # add new BLOCK or FILTER definitions
     $context->define_block($name, $block);
     $context->define_filter($name, \&filtersub, $is_dynamic);

     # reset context, clearing any imported BLOCK definitions
     $context->reset();

     # methods for accessing internal items
     $stash     = $context->stash();
     $tflag     = $context->trim();
     $epflag    = $context->eval_perl();
     $providers = $context->templates();
     $providers = $context->plugins();
     $providers = $context->filters();
     ...

DESCRIPTION
===========

   The Template::Context module defines an object class for representing a
a runtime context in which templates are processed.  It provides an
interface to the fundamental operations of the Template Toolkit processing
engine through which compiled templates (i.e. Perl code constructed from
the template source) can process templates, load plugins and filters,
raise exceptions and so on.

   A default Template::Context object is created by the Template module.
Any Template::Context options may be passed to the Template new()
constructor method and will be forwarded to the Template::Context
constructor.

     use Template;

     my $template = Template->new({
     	TRIM      => 1,
     	EVAL_PERL => 1,
     	BLOCKS    => {
     	    header => 'This is the header',
     	    footer => 'This is the footer',
     	},
     });

   Similarly, the Template::Context constructor will forward all
configuration parameters onto other default objects (e.g.
Template::Provider, Template::Plugins, Template::Filters, etc.) that it
may need to instantiate.

     $context = Template::Context->new({
     	INCLUDE_PATH => '/home/abw/templates', # provider option
     	TAG_STYLE    => 'html',                # parser option
     });

   A Template::Context object (or subclass/derivative) can be explicitly
instantiated and passed to the Template new() constructor method as the
CONTEXT item.

     use Template;
     use Template::Context;

     my $context  = Template::Context->new({ TRIM => 1 });
     my $template = Template->new({ CONTEXT => $context });

   The Template module uses the Template::Config context() factory method
to create a default context object when required.  The
$Template::Config::CONTEXT package variable may be set to specify an
alternate context module.  This will be loaded automatically and its new()
constructor method called by the context() factory method when a default
context object is required.

     use Template;

     $Template::Config::CONTEXT = 'MyOrg::Template::Context';

     my $template = Template->new({
     	EVAL_PERL   => 1,
     	EXTRA_MAGIC => 'red hot',  # your extra config items
     	...
     });

METHODS
=======

new(\%params)
-------------

   The new() constructor method is called to instantiate a
Template::Context object.  Configuration parameters may be specified as a
HASH reference or as a list of (name => value) pairs.

     my $context = Template::Context->new({
     	INCLUDE_PATH => 'header',
     	POST_PROCESS => 'footer',
     });

     my $context = Template::Context->new( EVAL_PERL => 1 );

   The new() method returns a Template::Context object (or sub-class) or
undef on error.  In the latter case, a relevant error message can be
retrieved by the error() class method or directly from the
$Template::Context::ERROR package variable.

     my $context = Template::Context->new(\%config)
     	|| die Template::Context->error();

     my $context = Template::Context->new(\%config)
     	|| die $Template::Context::ERROR;

   The following configuration items may be specified.

VARIABLES, PRE_DEFINE
     The VARIABLES option (or PRE_DEFINE - they're equivalent) can be used
     to specify a hash array of template variables that should be used to
     pre-initialise the stash when it is created.  These items are ignored
     if the STASH item is defined.

          my $context = Template::Context->new({
          	VARIABLES => {
          	    title   => 'A Demo Page',
          	    author  => 'Joe Random Hacker',
          	    version => 3.14,
          	},
          };

     or

          my $context = Template::Context->new({
          	PRE_DEFINE => {
          	    title   => 'A Demo Page',
          	    author  => 'Joe Random Hacker',
          	    version => 3.14,
          	},
          };

BLOCKS
     The BLOCKS option can be used to pre-define a default set of template
     blocks.  These should be specified as a reference to a hash array
     mapping template names to template text, subroutines or
     Template::Document objects.

          my $context = Template::Context->new({
          	BLOCKS => {
          	    header  => 'The Header.  [% title %]',
          	    footer  => sub { return $some_output_text },
          	    another => Template::Document->new({ ... }),
          	},
          });

TRIM
     The TRIM option can be set to have any leading and trailing whitespace
     automatically removed from the output of all template files and
     BLOCKs.

     By example, the following BLOCK definition

          [% BLOCK foo %]
          Line 1 of foo
          [% END %]

     will be processed is as "\nLine 1 of foo\n".  When INCLUDEd, the
     surrounding newlines will also be introduced.

          before
          [% INCLUDE foo %]
          after

     output:     before

          Line 1 of foo

          after

     With the TRIM option set to any true value, the leading and trailing
     newlines (which count as whitespace) will be removed from the output
     of the BLOCK.

          before
          Line 1 of foo
          after

     The TRIM option is disabled (0) by default.

EVAL_PERL
     This flag is used to indicate if PERL and/or RAWPERL blocks should be
     evaluated.  By default, it is disabled and any PERL or RAWPERL blocks
     encountered will be ignored.  Note however that any RAWPERL blocks
     should always contain valid Perl code, regardless of the EVAL_PERL
     flag.  The parser will fail to compile templates that contain invalid
     Perl code in RAWPERL blocks and will throw a 'file' exception.

RECURSION
     The template processor will raise a file exception if it detects
     direct or indirect recursion into a template.  Setting this option to
     any true value will allow templates to include each other recursively.

LOAD_TEMPLATES
     The LOAD_TEMPLATE option can be used to provide a reference to a list
     of Template::Provider objects or sub-classes thereof which will take
     responsibility for loading and compiling templates.

          my $context = Template::Context->new({
          	LOAD_TEMPLATES => [
          	    MyOrg::Template::Provider->new({ ... }),
          	    Template::Provider->new({ ... }),
          	],
          });

     When a PROCESS, INCLUDE or WRAPPER directive is encountered, the named
     template may refer to a locally defined BLOCK or a file relative to
     the INCLUDE_PATH (or an absolute or relative path if the appropriate
     ABSOLUTE or RELATIVE options are set).  If a BLOCK definition can't be
     found (see the Template::Context template() method for a discussion of
     BLOCK locality) then each of the LOAD_TEMPLATES provider objects is
     queried in turn via the fetch() method to see if it can supply the
     required template.  Each provider can return a compiled template, an
     error, or decline to service the request in which case the
     responsiblity is passed to the next provider.  If none of the
     providers can service the request then a 'not found' error is
     returned.  The same basic provider mechanism is also used for the
     INSERT directive but it bypasses any BLOCK definitions and doesn't
     attempt is to parse or process the contents of the template file.

     This is an implementation of the 'Chain of Responsiblity' design
     pattern as described in "Design Patterns", Erich Gamma, Richard Helm,
     Ralph Johnson, John Vlissides), Addision-Wesley, ISBN 0-201-63361-2,
     page 223.

     If LOAD_TEMPLATES is undefined, a single default provider will be
     instantiated using the current configuration parameters.  For example,
     the Template::Provider INCLUDE_PATH option can be specified in the
     Template::Context configuration and will be correctly passed to the
     provider's constructor method.

          my $context = Template::Context->new({
          	INCLUDE_PATH => '/here:/there',
          });

LOAD_PLUGINS
     The LOAD_PLUGINS options can be used to specify a list of provider
     objects (i.e. they implement the fetch() method) which are responsible
     for loading and instantiating template plugin objects.  The plugin()
     method queries each provider in turn in a "Chain of Responsibility" as
     per the template() and filter() methods.

          my $context = Template::Context->new({
          	LOAD_PLUGINS => [
          	    MyOrg::Template::Plugins->new({ ... }),
          	    Template::Plugins->new({ ... }),
          	],
          });

     By default, a single Template::Plugins object is created using the
     current configuration hash.  Configuration items destined for the
     Template::Plugins constructor may be added to the Template::Context
     constructor.

          my $context = Template::Context->new({
          	PLUGIN_BASE => 'MyOrg::Template::Plugins',
          	LOAD_PERL   => 1,
          });

LOAD_FILTERS
     The LOAD_FILTERS option can be used to specify a list of provider
     objects (i.e. they implement the fetch() method) which are responsible
     for returning and/or creating filter subroutines.  The filter()
     method queries each provider in turn in a "Chain of Responsibility" as
     per the template() and plugin() methods.

          my $context = Template::Context->new({
          	LOAD_FILTERS => [
          	    MyTemplate::Filters->new(),
          	    Template::Filters->new(),
          	],
          });

     By default, a single Template::Filters object is created for the
     LOAD_FILTERS list.

STASH
     A reference to a Template::Stash object or sub-class which will take
     responsibility for managing template variables.

          my $stash = MyOrg::Template::Stash->new({ ... });
          my $context = Template::Context->new({
          	STASH => $stash,
          });

     If unspecified, a default stash object is created using the VARIABLES
     configuration item to initialise the stash variables.  These may also
     be specified as the PRE_DEFINE option for backwards compatibility with
     version 1.

          my $context = Template::Context->new({
          	VARIABLES => {
          	    id    => 'abw',
          	    name  => 'Andy Wardley',
          	},
          };

template($name)
---------------

   Returns a compiled template by querying each of the TEMPLATES providers
(instances of Template::Provider, or sub-class).  On error, undef is
returned and the internal error string set to contain a relevant message.
This can be retrieved via error().

     $template = $context->template('header')
         || die $context->error(), "\n";

plugin($name, \@args)
---------------------

   Instantiates a plugin object by querying each of the PLUGINS providers.
The default PLUGINS provider is a Template::Plugins object which attempts
to load plugin modules, according the various configuration items such as
PLUGIN_BASE, LOAD_PERL, etc., and then instantiate an object via new().  A
reference to a list of constructor arguments may be passed as the second
parameter.  These are forwarded to the plugin constructor.

   Returns a reference to a plugin (which is generally an object, but
doesn't have to be) or undef on failure.  Errors can be retrieved via
error().

     $plugin = $context->plugin('DBI', 'dbi:msql:mydbname')
     	|| die $context->error(), "\n";

filter($name, \@args, $alias)
-----------------------------

   Instantiates a filter subroutine by querying the FILTERS providers.
The default FILTERS providers is a Template::Filters object.  Additional
arguments may be passed by list reference along with an optional alias
under which the filter will be cached for subsequent use.  The filter is
cached under its own $name if $alias is undefined.  Subsequent calls to
filter($name) will return the cached entry, if defined.  Specifying
arguments bypasses the caching mechanism and always creates a new filter.

     # static filter (no args)
     $filter = $context->filter('html')
     	|| die $context->error(), "\n";

     # dynamic filter (args) aliased to 'padright'
     $filter = $context->filter('format', '%60s', 'padright')
     	|| die $context->error(), "\n";

     # retrieve previous filter via 'padright' alias
     $filter = $context->filter('padright')
     	|| die $context->error(), "\n";

process($template, \%vars)
--------------------------

   Processes a template named or referenced by the first parameter and
returns the output generated.  An optional reference to a hash array may
be passed as the second parameter, containing variable definitions which
will be set before the template is processed.  The template is processed
in the current context, with no localisation of variables performed.
Errors are thrown as Template::Exception objects via die().

     $output = $context->process('header', { title => 'Hello World' });

include($template, \%vars)
--------------------------

   Similar to process() above, but using localised variables.  Changes
made to any variables will only persist until the include() method
completes.

     $output = $context->include('header', { title => 'Hello World' });

throw($error_type, $error_message, \$output)
--------------------------------------------

   Raises an exception in the form of a Template::Exception object by
calling die().  This method may be passed a reference to an existing
Template::Exception object; a single value containing an error message
which is used to instantiate a Template::Exception of type 'undef'; or a
pair of values representing the exception type and info from which a
Template::Exception object is instantiated.  e.g.

     $context->throw($exception);
     $context->throw("I'm sorry Dave, I can't do that");
     $context->throw('denied', "I'm sorry Dave, I can't do that");

   The optional third parameter may be a reference to the current output
buffer.  This is then stored in the exception object when created,
allowing the catcher to examine and use the output up to the point at
which the exception was raised.

     $output .= 'blah blah blah';
     $output .= 'more rhubarb';
     $context->throw('yack', 'Too much yacking', \$output);

catch($exception, \$output)
---------------------------

   Catches an exception thrown, either as a reference to a
Template::Exception object or some other value.  In the latter case, the
error string is promoted to a Template::Exception object of 'undef' type.
This method also accepts a reference to the current output buffer which is
passed to the Template::Exception constructor, or is appended to the
output buffer stored in an existing Template::Exception object, if unique
(i.e. not the same reference).  By this process, the correct state of the
output buffer can be reconstructed for simple or nested throws.

define_block($name, $block)
---------------------------

   Adds a new block definition to the internal BLOCKS cache.  The first
argument should contain the name of the block and the second a reference
to a Template::Document object or template sub-routine, or template text
which is automatically compiled into a template sub-routine.  Returns a
true value (the sub-routine or Template::Document reference) on success or
undef on failure.  The relevant error message can be retrieved by calling
the error() method.

define_filter($name, \&filter, $is_dynamic)
-------------------------------------------

   Adds a new filter definition by calling the store() method on each of
the LOAD_FILTERS providers until accepted (in the usual case, this is
accepted straight away by the one and only Template::Filters provider).
The first argument should contain the name of the filter and the second a
reference to a filter subroutine.  The optional third argument can be set
to any true value to indicate that the subroutine is a dynamic filter
factory.  Returns a true value or throws a 'filter' exception on error.

localise(\%vars)
----------------

   Clones the stash to create a context with localised variables.  Returns
a reference to the newly cloned Template::Stash object which is also stored
internally.

     $stash = $context->localise();

delocalise()
------------

   Restore the stash to its state prior to localisation.

     $stash = $context->delocalise();

visit(\%blocks)
---------------

   This method is called by Template::Document objects immediately before
they process their content.  It is called to register any local BLOCK
definitions with the context object so that they may be subsequently
delivered on request.

leave()
-------

   Compliment to visit(), above.  Called by Template::Document objects
immediately after they process their content.

reset()
-------

   Clears the local BLOCKS cache of any BLOCK definitions.  Any initial
set of BLOCKS specified as a configuration item to the constructor will be
reinstated.

AUTOLOAD
--------

   An AUTOLOAD method provides access to context configuration items.

     $stash     = $context->stash();
     $tflag     = $context->trim();
     $epflag    = $context->eval_perl();
     ...

AUTHOR
======

   Andy Wardley <abw@kfs.org>

     http://www.template-toolkit.org/
     http://www.kfs.org/~abw/

REVISION
========

   $Revision: 1.3 $

COPYRIGHT
=========

     Copyright (C) 1996-2000 Andy Wardley.  All Rights Reserved.
     Copyright (C) 1998-2000 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Template|Template' in this node,
`Template::Document|Template::Document' in this node,
`Template::Exception|Template::Exception' in this node,
`Template::Filters|Template::Filters' in this node,
`Template::Plugins|Template::Plugins' in this node,
`Template::Provider|Template::Provider' in this node,
`Template::Service|Template::Service' in this node,
L<Template::Stash|Template::Stash

a compiled template document
****************************

NAME
====

   Template::Document - a compiled template document

SYNOPSIS
========

     use Template::Document;

     $doc = Template::Document->new({
     	BLOCK => sub { # some perl code; return $some_text },
     	DEFBLOCKS => {
     	    header => sub { # more perl code; return $some_text },
     	    footer => sub { # blah blah blah; return $some_text },
     	},
     	METADATA => {
     	    author  => 'Andy Wardley',
     	    version => 3.14,
     	}
     }) || die $Template::Document::ERROR;

     print $doc->process($context);

DESCRIPTION
===========

   This module defines an object class whose instances represent compiled
template documents.  The Template::Parser module creates a
Template::Document instance to encapsulate a template as it is compiled
into Perl code.

   The constructor method, new(), expects a reference to a hash array
containing the BLOCK, DEFBLOCKS and METADATA items.  The BLOCK item should
contain a reference to a Perl subroutine or a textual representation of
Perl code, as generated by the Template::Parser module, which is then
evaluated into a subroutine reference using eval().  The DEFLOCKS item
should reference a hash array containing further named BLOCKs which may be
defined in the template.  The keys represent BLOCK names and the values
should be subroutine references or text strings of Perl code as per the
main BLOCK item.  The METADATA item should reference a hash array of
metadata items relevant to the document.

   The process() method can then be called on the instantiated
Template::Document object, passing a reference to a Template::Content
object as the first parameter.  This will install any locally defined
blocks (DEFBLOCKS) in the the contexts() BLOCKS cache (via a call to
visit()) so that they may be subsequently resolved by the context.  The
main BLOCK subroutine is then executed, passing the context reference on
as a parameter.  The text returned from the template subroutine is then
returned by the process() method, after calling the context leave() method
to permit cleanup and de-registration of named BLOCKS previously installed.

   An AUTOLOAD method provides access to the METADATA items for the
document.  The Template::Service module installs a reference to the main
Template::Document object in the stash as the 'template' variable.  This
allows metadata items to be accessed from within templates, including
PRE_PROCESS templates.

   header:     <html>     <head>     <title>[% template.title %]
</head>     ...

   Template::Document objects are usually created by the Template::Parser
but can be manually instantiated or sub-classed to provide custom template
components.

METHODS
=======

new(\%config)
-------------

   Constructor method which accept a reference to a hash array containing
the structure as shown in this example:

     $doc = Template::Document->new({
     	BLOCK => sub { # some perl code; return $some_text },
     	DEFBLOCKS => {
     	    header => sub { # more perl code; return $some_text },
     	    footer => sub { # blah blah blah; return $some_text },
     	},
     	METADATA => {
     	    author  => 'Andy Wardley',
     	    version => 3.14,
     	}
     }) || die $Template::Document::ERROR;

   BLOCK and DEFBLOCKS items may be expressed as references to Perl
subroutines or as text strings containing Perl subroutine definitions, as
is generated by the Template::Parser module.  These are evaluated into
subroutine references using eval().

   Returns a new Template::Document object or undef on error.  The error()
class method can be called, or the $ERROR package variable inspected to
retrieve the relevant error message.

process($context)
-----------------

   Main processing routine for the compiled template document.  A
reference to a Template::Context object should be passed as the first
parameter.  The method installs any locally defined blocks via a call to
the context visit() method, processes it's own template, passing the
context reference by parameter and then calls leave() in the context to
allow cleanup.

     print $doc->process($context);

   Returns a text string representing the generated output for the
template.  Errors are thrown via die().

block()
-------

   Returns a reference to the main BLOCK subroutine.

blocks()
--------

   Returns a reference to the hash array of named DEFBLOCKS subroutines.

AUTOLOAD
--------

   An autoload method returns METADATA items.

     print $doc->author();

PACKAGE SUB-ROUTINES
====================

write_perl_file(\%config)
-------------------------

   This package subroutine is provided to effect persistance of compiled
templates.  If the COMPILE_EXT option (to indicate a file extension for
saving compiled templates) then the Template::Parser module call this
subroutine before calling the new() constructor.  At this stage, the
parser has a representation of the template as text strings containing
Perl code.  We can write that to a file, enclosed in a small wrapper which
will allow us to susequently require() the file and have Perl parse and
compile it into a Template::Document.  Thus we have persistance of
compiled templates.

AUTHOR
======

   Andy Wardley <abw@kfs.org>

     http://www.template-toolkit.org/
     http://www.kfs.org/~abw/

REVISION
========

   $Revision: 1.1 $

COPYRIGHT
=========

     Copyright (C) 1996-2000 Andy Wardley.  All Rights Reserved.
     Copyright (C) 1998-2000 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Template|Template' in this node, L<Template::Parser|Template::Parser

exception handling class for the Template Toolkit
*************************************************

NAME
====

   Template::Exception - exception handling class for the Template Toolkit

SYNOPSIS
========

     use Template::Exception;

     my $exception = Template::Exception->new($type, $info);
     $type = $exception->type;
     $info = $exception->info;
     ($type, $info) = $exception->type_info;

     print $exception->as_string();

     $handler = $exception->select_handler(\@candidates);

DESCRIPTION
===========

   The Template::Exception module defines an object class for representing
exceptions within the template processing life cycle.  Exceptions can be
raised by modules within the Template Toolkit, or can be generated and
returned by user code bound to template variables.

   Exceptions can be raised in a template using the THROW directive,

     [% THROW user.login 'no user id: please login' %]

   or by calling the throw() method on the current Template::Context
object,

     $context->throw('user.passwd', 'Incorrect Password');
     $context->throw('Incorrect Password');    # type 'undef'

   or from Perl code by calling die() with a Template::Exception object,

     die Template::Exception->new('user.denied', 'Invalid User ID');

   or by simply calling die() with an error string.  This is automagically
caught and converted to an  exception of 'undef' type which can then be
handled in the usual way.

     die "I'm sorry Dave, I can't do that";

   Each exception is defined by its type and a information component (e.g.
error message).  The type can be any identifying string and may contain
dotted components (e.g. 'foo', 'foo.bar', 'foo.bar.baz').  Exception types
are considered to be hierarchical such that 'foo.bar' would be a specific
type of the more general 'foo' type.

AUTHOR
======

   Andy Wardley <abw@kfs.org>

     http://www.template-toolkit.org/
     http://www.kfs.org/~abw/

REVISION
========

   $Revision: 1.1 $

COPYRIGHT
=========

     Copyright (C) 1996-2000 Andy Wardley.  All Rights Reserved.
     Copyright (C) 1998-2000 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Template|Template' in this node, L<Template::Context|Template::Context

post-processing filters for template blocks
*******************************************

NAME
====

   Template::Filters - post-processing filters for template blocks

SYNOPSIS
========

     use Template::Filters;

     $filters = Template::Filters->new(\%config);

     ($filter, $error) = $filters->fetch($name, \@args, $context);

DESCRIPTION
===========

   The Template::Plugins module implements a provider for creating and/or
returning subroutines that implement the standard filters.  Additional
custom filters may be provided via the FILTERS options.

METHODS
=======

new(\%params)
-------------

   Constructor method which instantiates and returns a reference to a
Template::Filters object.  A reference to a hash array of configuration
items may be passed as a parameter.  These are described below.

     my $filters = Template::Filters->new({
     	FILTERS => { ... },
     });

     my $template = Template->new({
     	LOAD_FILTERS => [ $filters ],
     });

   A default Template::Filters module is created by the Template.pm module
if the LOAD_FILTERS option isn't specified.  All configuration parameters
are forwarded to the constructor.

     $template = Template->new({
         FILTERS => { ... },
     });

fetch($name, \@args, $context)
------------------------------

   Called to request that a filter of a given name be provided.  The name
of the filter should be specified as the first parameter.  This should be
one of the standard filters or one specified in the FILTERS configuration
hash.  The second argument should be a reference to an array containing
configuration parameters for the filter.  This may be specified as 0, or
undef where no parameters are provided.  The third argument should be a
reference to the current Template::Context object.

   The method returns a reference to a filter sub-routine on success.  It
may also return (undef, STATUS_DECLINE) to decline the request, to allow
delegation onto other filter providers in the LOAD_FILTERS chain of
responsibility.  On error, ($error, STATUS_ERROR) is returned where $error
is an error message or Template::Exception object indicating the error
that occurred.

   When the TOLERANT option is set, errors are automatically downgraded to
a STATUS_DECLINE response.

CONFIGURATION OPTIONS
=====================

   The following list details the configuration options that can be
provided to the Template::Plugins new() constructor.

FILTERS
     The FILTERS option can be used to specify custom filters which can
     then be used with the FILTER directive like any other.  These are
     added to the standard filters which are available by default.  Filters
     specified via this option will mask any standard filters of the same
     name.

     The FILTERS option should be specified as a reference to a hash array
     in which each key represents the name of a filter.  The corresponding
     value should contain a reference to an array containing a subroutine
     reference and a flag which indicates if the filter is static (0) or
     dynamic (1).  A filter may also be specified as a solitary subroutine
     reference and is assumed to be static.

          $filters = Template::Filters->new({
            	FILTERS => {
            	    'sfilt1' =>   \&static_filter,      # static
                  'sfilt2' => [ \&static_filter, 0 ], # same as above
            	    'dfilt1' => [ \&dyanamic_filter_factory, 1 ],
            	},
          });

     Additional filters can be specified at any time by calling the
     define_filter() method on the current Template::Context object.  The
     method accepts a filter name, a reference to a filter subroutine and
     an optional flag to indicate if the filter is dynamic.

          my $context = $template->context();
          $context->define_filter('new_html', \&new_html);
          $context->define_filter('new_repeat', \&new_repeat, 1);

          Static filters are those where a single subroutine reference is used
          for all invocations of a particular filter.  Filters that don't accept
          any configuration parameters (e.g. 'html') can be implemented
          statically.  The subroutine reference is simply returned when that
          particular filter is requested.  The subroutine is called to filter
          the output of a template block which is passed as the only argument.
          The subroutine should return the modified text.

          sub static_filter {
            	my $text = shift;
          	# do something to modify $text...
            	return $text;
          }

     The following template fragment:

          [% FILTER sfilt1 %]
          Blah blah blah.
          [% END %]

     is approximately equivalent to:

          &static_filter("\nBlah blah blah.\n");

     Filters that can accept parameters (e.g. 'truncate') should be
     implemented dynamically.  In this case, the subroutine is taken to be
     a filter 'factory' that is called to create a unique filter subroutine
     each time one is requested.  A reference to the current
     Template::Context object is passed as the first parameter, followed by
     any additional parameters specified.  The subroutine should return
     another subroutine reference (usually a closure) which implements the
     filter.

          sub dynamic_filter_factory {
          	my ($context, @args) = @_;

          return sub {
              my $text = shift;
          	    # do something to modify $text...
          	    return $text;
          }
              }

     The following template fragment:

          [% FILTER dfilt1(123, 456) %]
          Blah blah blah
          [% END %]

     is approximately equivalent to:

          my $filter = &dynamic_filter_factory($context, 123, 456);
          &$filter("\nBlah blah blah.\n");

     See the FILTER directive for further examples.

TOLERANT
     The TOLERANT flag is used by the various Template Toolkit provider
     modules (Template::Provider, Template::Plugins, Template::Filters) to
     control their behaviour when errors are encountered.  By default, any
     errors are reported as such, with the request for the particular
     resource (template, plugin, filter) being denied and an exception
     raised.  When the TOLERANT flag is set to any true values, errors will
     be silently ignored and the provider will instead return
     STATUS_DECLINED.  This allows a subsequent provider to take
     responsibility for providing the resource, rather than failing the
     request outright.  If all providers decline to service the request,
     either through tolerated failure or a genuine disinclination to
     comply, then a '<resource> not found' exception is raised.

TEMPLATE TOOLKIT FILTERS
========================

   The following standard filters are distributed with the Template
Toolkit.

html
     Converts the characters '<', '>' and '&' to '&lt;', '&gt;' and '&amp',
     respectively, protecting them from being interpreted as representing
     HTML tags or entities.

          [% FILTER html %]
          Binary "<=>" returns -1, 0, or 1 depending on...
          [% END %]

     output:

          Binary "&lt;=&gt;" returns -1, 0, or 1 depending on...

html_para
     This filter formats a block of text into HTML paragraphs.  A sequence
     of two or more newlines is used as the delimiter for paragraphs which
     are then wrapped in HTML <p>...</p> tags.

          [% FILTER html_para %]
          The cat sat on the mat.

          Mary had a little lamb.
          [% END %]

     output:

          <p>
          The cat sat on the mat.
          </p>

          <p>
          Mary had a little lamb.
          </p>

html_break
     Similar to the html_para filter described above, but uses the HTML tag
     sequence <br><br> to join paragraphs.

          [% FILTER html_para %]
          The cat sat on the mat.

          Mary had a little lamb.
          [% END %]

     output:

          The cat sat on the mat.
          <br>
          <br>
          Mary had a little lamb.

format(format)
     The 'format' filter takes a format string as a parameter (as per
     printf()) and formats each line of text accordingly.

          [% FILTER format('<!-- %-40s -->') %]
          This is a block of text filtered
          through the above format.
          [% END %]

     output:

          <!-- This is a block of text filtered        -->
          <!-- through the above format.               -->

truncate(length)
     Truncates the text block to the length specified, or a default length
     of 32.  Truncated text will be terminated with '...' (i.e. the '...'
     falls inside the required length, rather than appending to it).

          [% FILTER truncate(21) %]
          I have much to say on this matter that has previously
          been said on more than one occassion.
          [% END %]

     output:

          I have much to say...

repeat(iterations)
     Repeats the text block for as many iterations as are specified
     (default: 1).

          [% FILTER repeat(3) %]
          Am I repeating myself?
          [% END %]

     output:

          Am I repeating myself?
          Am I repeating myself?
          Am I repeating myself?

remove(string)
     Searches the input text for any occurences of the specified string and
     removes them.  A Perl regular expression may be specified as the
     search string.

          [% "The  cat  sat  on  the  mat" FILTER remove('\s+') %]

     output:

          Thecatsatonthemat

     The '|' character is an alias for FILTER, allowing the previous
     example to be written as:

          [% "The  cat  sat  on  the  mat" | remove('\s+') %]

replace(search, replace)
     Similar to the remove filter described above, but taking a second
     parameter which is used as a replacement string for instances of the
     search string.

          [% "The  cat  sat  on  the  mat" | replace('\s+', '_') %]

     output:

          The_cat_sat_on_the_mat

redirect(file)
     The 'redirect' filter redirects the output of the block into a
     separate file, specified relative to the OUTPUT_PATH configuration
     item.

          [% FOREACH user = myorg.userlist %]
             [% FILTER redirect("users/${user.id}.html") %]
                [% INCLUDE userinfo %]
             [% END %]
          [% END %]

     A 'file' exception will be thrown if the OUTPUT_PATH option is
     undefined.

eval(template_text)
     The 'eval' filter evaluates the block as template text, processing
     any directives embedded within it.  This allows template variables to
     contain template fragments, or for some method to be provided for
     returning template fragments from an external source such as a
     database, which can then be processed in the template as required.

          my $replace  = {
          	fragment => "The cat sat on the [% place %]",
          };
          $template->process($file, $replace);

     The following example:

          [% fragment | eval %]

     is therefore equivalent to

          The cat sat on the [% place %]

evalperl(perlcode)
     The 'evalperl' filter evaluates the block as Perl code.  The EVAL_PERL
     option must be set to a true value or a 'perl' exception will be
     thrown.

          [% my_perl_code | evalperl %]

     In most cases, the [% PERL %] ... [% END %] block should suffice for
     evaluating Perl code, given that template directives are processed
     before being evaluate as Perl.  Thus, the previous example could have
     been written in the more verbose form:

          [% PERL %]
          [% my_perl_code %]
          [% END %]

     as well as

          [% FILTER evalperl %]
          [% my_perl_code %]
          [% END %]

     It is an unfortunate circumstance that this filter cannot simply be
     called 'perl'.  This is due to the clash with the reserved word of
     that name (i.e. PERL blocks).

AUTHOR
======

   Andy Wardley <abw@kfs.org>

     http://www.template-toolkit.org/
     http://www.kfs.org/~abw/

REVISION
========

   $Revision: 1.1 $

COPYRIGHT
=========

     Copyright (C) 1996-2000 Andy Wardley.  All Rights Reserved.
     Copyright (C) 1998-2000 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Template|Template' in this node, L<Template::Context|Template::Context

Base iterator class used by the FOREACH directive.
**************************************************

NAME
====

   Template::Iterator - Base iterator class used by the FOREACH directive.

SYNOPSIS
========

     my $iter = Template::Iterator->new(\@data, \%options);

DESCRIPTION
===========

   The Template::Iterator module defines a generic data iterator for use
by the FOREACH directive.

   It may be used as the base class for custom iterators.

PUBLIC METHODS
==============

new(\@data)
-----------

   Constructor method.  A reference to a list of values is passed as the
first parameter and subsequent get_first() and get_next() calls will return
each element.

get_first()
-----------

   Returns a ($value, $error) pair for the first item in the iterator set.
The $error returned may be zero or undefined to indicate a valid datum was
successfully returned.  Returns an error of STATUS_DONE if the list is
empty.

get_next()
----------

   Returns a ($value, $error) pair for the next item in the iterator set.
Returns an error of STATUS_DONE if all items in the list have been visited.

get_all()
---------

   Returns a (\@values, $error) pair for all remaining items in the
iterator set.  Returns an error of STATUS_DONE if all items in the list
have been visited.

size(), max(), index(), number(), first(), last()
-------------------------------------------------

   Return the size of the iteration set, the maximum index number (size -
1), the current index number (0..max), the iteration number offset from 1
(index + 1, i.e. 1..size), and boolean values indicating if the current
iteration is the first or last in the set, respectively.

AUTHOR
======

   Andy Wardley <abw@kfs.org>

     http://www.template-toolkit.org/
     http://www.kfs.org/~abw/

REVISION
========

   $Revision: 1.1 $

COPYRIGHT
=========

     Copyright (C) 1996-2000 Andy Wardley.  All Rights Reserved.
     Copyright (C) 1998-2000 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   L<Template|Template

LALR(1) parser for compiling template documents
***********************************************

NAME
====

   Template::Parser - LALR(1) parser for compiling template documents

SYNOPSIS
========

     use Template::Parser;

     $parser   = Template::Parser->new(\%config);
     $template = $parser->parse($text)
         || die $parser->error(), "\n";

DESCRIPTION
===========

   The Template::Parser module implements a LALR(1) parser and associated
methods for parsing template documents into Perl code.

PUBLIC METHODS
==============

new(\%params)
-------------

   The new() constructor creates and returns a reference to a new
Template::Parser object.  A reference to a hash may be supplied as a
parameter to provide configuration values.  These may include:

START_TAG, END_TAG
     The START_TAG and END_TAG options are used to specify character
     sequences or regular expressions that mark the start and end of a
     template directive.  The default values for START_TAG and END_TAG are
     '[%' and '%]' respectively, giving us the familiar directive style:

          [% example %]

     Any Perl regex characters can be used and therefore should be escaped
     (or use the Perl quotemeta function) if they are intended to
     represent literal characters.

          my $parser = Template::Parser->new({
            	START_TAG => quotemeta('<+'),
            	END_TAG   => quotemeta('+>'),
          });

     example:

          <+ INCLUDE foobar +>

     The TAGS directive can also be used to set the START_TAG and END_TAG
     values on a per-template file basis.

          [% TAGS <+ +> %]

TAG_STYLE
     The TAG_STYLE option can be used to set both START_TAG and END_TAG
     according to pre-defined tag styles.

          my $parser = Template::Parser->new({
            	TAG_STYLE => 'php',
          });

     Available styles are:

          template    [% ... %]               (default)
          template1   [% ... %] or %% ... %%  (Template version 1)
          metatext    %% ... %%               (Text::MetaText)
          php         <? ... ?>               (PHP)
          asp         <% ... %>               (ASP)
          mason       <% ...  >               (HTML::Mason)
          html        <!-- ... -->            (HTML comments)

     Any values specified for START_TAG and/or END_TAG will over-ride
     those defined by a TAG_STYLE.

     The TAGS directive may also be used to set a TAG_STYLE

          [% TAGS html %]
          <!-- INCLUDE header -->

PRE_CHOMP, POST_CHOMP
     Anything outside a directive tag is considered plain text and is
     generally passed through unaltered (but see the INTERPOLATE option).
     This includes all whitespace and newlines characters surrounding
     directive tags.  Any directives that don't generate any output will
     leave gaps in the output document.

     Example:

          Foo
          [% a = 10 %]
          Bar

     Output:

          Foo

          Bar

     The PRE_CHOMP and POST_CHOMP options can help to clean up some of this
     extraneous whitespace.  Both are disabled by default.

          my $parser = Template::Parser->new({
          	PRE_CHOMP  => 1,
          	POST_CHOMP => 1,
          });

     With PRE_CHOMP set true, the newline and whitespace preceeding a
     directive at the start of a line will be deleted.  This has the
     effect of concatenating a line that starts with a directive onto the
     end of the previous line.

          Foo <----------.
          	       |
              ,---(PRE_CHOMP)----'
              |
              `-- [% a = 10 %] --.
          	       |
              ,---(POST_CHOMP)---'
              |
              `-> Bar

     With POST_CHOMP set true, any whitespace after a directive up to and
     including the newline will be deleted.  This has the effect of joining
     a line that ends with a directive onto the start of the next line.

     PRE_CHOMP and POST_CHOMP can be activated for individual directives by
     placing a '-' immediately at the start and/or end of the directive.

          [% FOREACH user = userlist %]
             [%- user -%]
          [% END %]

     The '-' characters activate both PRE_CHOMP and POST_CHOMP for the one
     directive '[%- name -%]'.  Thus, the template will be processed as if
     written:

          [% FOREACH user = userlist %][% user %][% END %]

     Similarly, '+' characters can be used to disable PRE_CHOMP or
     POST_CHOMP (i.e.  leave the whitespace/newline intact) options on a
     per-directive basis.

          [% FOREACH user = userlist %]
          User: [% user +%]
          [% END %]

     With POST_CHOMP set on, the above example would be parsed as if
     written:

          [% FOREACH user = userlist %]User: [% user %]
          [% END %]

INTERPOLATE
     The INTERPOLATE flag, when set to any true value will cause variable
     references in plain text (i.e. not surrounded by START_TAG and
     END_TAG) to be recognised and interpolated accordingly.

          my $parser = Template::Parser->new({
            	INTERPOLATE => 1,
          });

     Variables should be prefixed by a '$' to identify them.  Curly braces
     can be used in the familiar Perl/shell style to explicitly scope the
     variable name where required.

          # INTERPOLATE = 0
          <a href="http://[% server %]/[% help %]">
          <img src="[% images %]/help.gif"></a>
          [% myorg.name %]

          # INTERPOLATE = 1
          <a href="http://$server/$help">
          <img src="$images/help.gif"></a>
          $myorg.name

          # explicit scoping with {  }
          <img src="$images/${icon.next}.gif">

ANYCASE
     By default, directive keywords should be expressed in UPPER CASE.  The
     ANYCASE option can be set to allow directive keywords to be specified
     in any case.

          # ANYCASE => 0 (default)
          [% INCLUDE foobar %]	# OK
          [% include foobar %]        # ERROR
          [% include = 10   %]        # OK, 'include' is a variable

          # ANYCASE => 1
          [% INCLUDE foobar %]	# OK
          [% include foobar %]	# OK
          [% include = 10   %]        # ERROR, 'include' is reserved word

     One side-effect of enabling ANYCASE is that you cannot use a variable
     of the same name as a reserved word, regardless of case.  The reserved
     words are currently:

          GET CALL SET DEFAULT INSERT INCLUDE PROCESS WRAPPER
          IF UNLESS ELSE ELSIF FOR FORNEXT WHILE SWITCH CASE
          USE PLUGIN FILTER MACRO PERL RAWPERL BLOCK META
          TRY THROW CATCH FINAL BREAK RETURN STOP CLEAR
          TO STEP AND OR NOT MOD DIV END

     The only lower case reserved words that cannot be used for variables,
     regardless of the ANYCASE option, are the operators:

          and or not mod div

V1DOLLAR
     In version 1 of the Template Toolkit, an optional leading '$' could
     be placed on any template variable and would be silently ignored.

          # VERSION 1
          [% $foo %]       ===  [% foo %]
          [% $hash.$key %] ===  [% hash.key %]

     To interpolate a variable value the '${' ... '}' construct was used.
     Typically, one would do this to index into a hash array when the key
     value was stored in a variable.

     example:

          my $vars = {
          	users => {
          	    aba => { name => 'Alan Aardvark', ... },
          	    abw => { name => 'Andy Wardley', ... },
                  ...
          	},
          	uid => 'aba',
              ...
          };

          $template->process('user/home.html', $vars)
          	|| die $template->error(), "\n";

     'user/home.html':

          [% user = users.${uid} %]     # users.aba
          Name: [% user.name %]         # Alan Aardvark

     This was inconsistent with double quoted strings and also the
     INTERPOLATE mode, where a leading '$' in text was enough to indicate a
     variable for interpolation, and the additional curly braces were used
     to delimit variable names where necessary.  Note that this use is
     consistent with UNIX and Perl conventions, among others.

          # double quoted string interpolation
          [% name = "$title ${user.name}" %]

          # INTERPOLATE = 1
          <img src="$images/help.gif"></a>
          <img src="$images/${icon.next}.gif">

     For version 2, these inconsistencies have been removed and the syntax
     clarified.  A leading '$' on a variable is now used exclusively to
     indicate that the variable name should be interpolated (e.g.
     subsituted for its value) before being used.  The earlier example
     from version 1:

          # VERSION 1
          [% user = users.${uid} %]
          Name: [% user.name %]

     can now be simplified in version 2 as:

          # VERSION 2
          [% user = users.$uid %]
          Name: [% user.name %]

     The leading dollar is no longer ignored and has the same effect of
     interpolation as '${' ... '}' in version 1.  The curly braces may
     still be used to explicitly scope the interpolated variable name
     where necessary.

     e.g.

          [% user = users.${me.id} %]
          Name: [% user.name %]

     The rule applies for all variables, both within directives and in
     plain text if processed with the INTERPOLATE option.  This means that
     you should no longer (if you ever did) add a leading '$' to a variable
     inside a directive, unless you explicitly want it to be interpolated.

     One obvious side-effect is that any version 1 templates with variables
     using a leading '$' will no longer be processed as expected.  Given
     the following variable definitions,

          [% foo = 'bar'
             bar = 'baz'
          %]

     version 1 would interpret the following as:

          # VERSION 1
          [% $foo %] => [% GET foo %] => bar

     whereas version 2 interprets it as:

          # VERSION 2
          [% $foo %] => [% GET $foo %] => [% GET bar %] => baz

     In version 1, the '$' is ignored and the value for the variable 'foo'
     is retrieved and printed.  In version 2, the variable '$foo' is first
     interpolated to give the variable name 'bar' whose value is then
     retrieved and printed.

     The use of the optional '$' has never been strongly recommended, but
     to assist in backwards compatibility with any version 1 templates that
     may rely on this "feature", the V1DOLLAR option can be set to 1
     (default: 0) to revert the behaviour and have leading '$' characters
     ignored.

          my $parser = Template::Parser->new({
          	V1DOLLAR => 1,
          });

GRAMMAR
     The GRAMMAR configuration item can be used to specify an alternate
     grammar for the parser.  This allows a modified or entirely new
     template langauge to be constructed and used by the Template Toolkit.

     Source templates are compiled to Perl code by the Template::Parser
     using the Template::Grammar (by default) to define the language
     structure and semantics.  Compiled templates are thus inherently
     "compatible" with each other and there is nothing to prevent any
     number of different template languages being compiled and used within
     the same Template Toolkit processing environment (other than the usual
     time and memory constraints).

     The Template::Grammar file is constructed from a YACC like grammar
     (using Parse::YAPP) and a skeleton module template.  These files are
     provided, along with a small script to rebuild the grammar, in the
     'parser' sub-directory of the distribution.  You don't have to know or
     worry about these unless you want to hack on the template language or
     define your own variant.  There is a README file in the same directory
     which provides some small guidance but it is assumed that you know
     what you're doing if you venture herein.  If you grok LALR parsers,
     then you should find it comfortably familiar.

     By default, an instance of the default Template::Grammar will be
     created and used automatically if a GRAMMAR item isn't specified.

          use MyOrg::Template::Grammar;

          my $parser = Template::Parser->new({
             	GRAMMAR = MyOrg::Template::Grammar->new();
          });

parse($text)
------------

   The parse() method parses the text passed in the first parameter and
returns a reference to a Template::Document object which contains the
compiled representation of the template text.  On error, undef is returned.

   Example:

     $doc = $parser->parse($text)
     	|| die $parser->error();

AUTHOR
======

   Andy Wardley <abw@kfs.org>

     http://www.template-toolkit.org/
     http://www.kfs.org/~abw/

REVISION
========

   $Revision: 1.1 $

COPYRIGHT
=========

     Copyright (C) 1996-2000 Andy Wardley.  All Rights Reserved.
     Copyright (C) 1998-2000 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   The original Template::Parser module was derived from a standalone
parser generated by version 0.16 of the Parse::Yapp module.  The following
copyright notice appears in the Parse::Yapp documentation.

     The Parse::Yapp module and its related modules and shell
     scripts are copyright (c) 1998 Francois Desarmenien,
     France. All rights reserved.

     You may use and distribute them under the terms of either
     the GNU General Public License or the Artistic License, as
     specified in the Perl README file.

SEE ALSO
========

   The Template Toolkit web site contains the latest information, news and
other resources.

     http://www.template-toolkit.org/

   A mailing list exists for up-to-date information on the Template Toolkit
and for following and contributing to the development process.  To
subscribe, send an email to

     templates-request@template-toolkit.org

   with the message 'subscribe' in the body.  You can also use the web
interface to subscribe or browse the archives:

     http://www.template-toolkit.org/mailman/listinfo/templates

   The `tpage' and `ttree' scripts are distributed and installed along
with the Template Toolkit.  The `tpage' script simply processes named
files or STDIN if unspecified, using a default Template object.  The
`ttree' script can be used to process entire directory trees of templates,
allowing large content systems such as web sites to be rebuilt from a
single command or configuration file.

     perldoc tpage
     perldoc ttree

   The `Template::Tutorial' document provides an introduction to the
Template Toolkit and shows some typical examples of usage.

     perldoc Template::Tutorial

   You may also like to consult the paper 'Building and Managing Web
Systems with the Template Toolkit' and accompanying slides from the
presentation at the 4th Perl Conference.  These are available from the
Template Toolkit web site:

     http://www.template-toolkit.org/docs.html

   The following modules comprise the Template Toolkit.  Consult the
individual documentation for further details.

`Template::Service|Template::Service' in this node
     The Template::Service module handles the template processing
     lifecycle, adding PRE_PROCESS and POST_PROCESS templates, handling
     redirection through any defined PROCESS template, and dispatching any
     ERROR templates to handle uncaught exceptions.  The actual processing
     of these templates is handled by an underlying
     `Template::Context|Template::Context' in this node object.

`Template::Context|Template::Context' in this node
     The Template::Context module defines a class of objects which each
     represent a unique run-time environment in which templates are
     processed.  The context maintains references to the stash of variables
     currently defined (`Template::Stash|Template::Stash' in this node)
     and to provider objects for templates
     (`Template::Provider|Template::Provider' in this node), filters
     (`Template::Filters|Template::Filters' in this node) and plugins
     (`Template::Plugins|Template::Plugins' in this node).

`Template::Stash|Template::Stash' in this node
     The Template::Stash module defines an object class which is used for
     storing, retrieving and evaluating variables and their values.

`Template::Provider|Template::Provider' in this node
     The Template::Provider module defines an object class which is used to
     find, load, parse, compile and then cache template documents.  The
     cache implements a simple fetch($template) method which will accept a
     wide range of inputs (filename, text ref, GLOB, IO::Handle, etc) and
     attempt to read the template and call on a
     `Template::Parser|Template::Parser' in this node to parse and compile
     it to a `Template::Document|Template::Document' in this node which is
     then cached.

`Template::Document|Template::Document' in this node
     Template::Document objects are thin wrappers around the Perl
     subroutines which have been compiled from source templates by the
     `Template::Parser|Template::Parser' in this node.  These objects also
     maintain any metadata values for the template and have references to
     any BLOCKs defined within the the template.

`Template::Parser|Template::Parser' in this node
     The Template::Parser module defines an object class which implements
     the template parser and compiler.  The template text is first scanned
     by a Perl regex which extracts the embedded directives and lexes the
     tokens contained within.  A DFA (Deterministic Finite-state Automaton)
     then iterates through the tokens using the rules and states defined in
     `Template::Grammar|Template::Grammar' in this node and generates a
     compiled template document as a Perl subroutine.

`Template::Grammar|Template::Grammar' in this node
     The Template::Grammar module defines the rules and state tables for
     the `Template::Parser|Template::Parser' in this node DFA.  These are
     generated by the Parse::Yapp module.  The Template-Toolkit
     distribution contains a parser directory which contains further files
     and information concerning the grammar and compilation thereof.

`Template::Directive|Template::Directive' in this node
     This module implements a number of factory methods which are used by
     the `Template::Parser|Template::Parser' in this node to generate Perl
     code from source templates.

`Template::Filters|Template::Filters' in this node
     This module implements the various FILTER subroutines and provides a
     simple interface through which filter subs can be retrieved.

`Template::Plugins|Template::Plugins' in this node
     This module provides access to the standard Template Toolkit or user
     defined plugin modules.

`Template::Plugin|Template::Plugin' in this node
     Base class for Template::Plugin::* modules.

`Template::Exception|Template::Exception' in this node
     The Template::Exception module defines an exception type for
     representing error conditions within the Template Toolkit.

`Template::Iterator|Template::Iterator' in this node
     The Template::Iterator module defines a data iterator which is used
     by the FOREACH directive.  This may be sub-classed to create more
     specialised iterators for traversing data sets.

`Template::Constants|Template::Constants' in this node
     Defines various constants used in the Template Toolkit.

`Template::Config|Template::Config' in this node
     Implements a number of factory methods through which other Template::*
     modules can be automatically loaded and instantiated.

`Template::Base|Template::Base' in this node
     A common base class for many Template::* modules.

`Template::Test|Template::Test' in this node
     Module for testing the Template Toolkit, primarily used by the test
     scripts in the 't' distribution sub-directory

base class for Template Toolkit plugins
***************************************

NAME
====

   Template::Plugin - base class for Template Toolkit plugins

SYNOPSIS
========

     package MyOrg::Template::Plugin::MyPlugin;
     use base qw( Template::Plugin );
     use Template::Plugin;
     use MyModule;

     sub new {
         my $class   = shift;
         my $context = shift;
     	bless {
     	    ...
     	}, $class;
     }

DESCRIPTION
===========

   A "plugin" for the Template Toolkit is simply a Perl module which
exists in a known package location (e.g. Template::Plugin::*) and conforms
to a regular standard, allowing it to be loaded and used automatically.

   The Template::Plugin module defines a base class from which other
plugin modules can be derived.  A plugin does not have to be derived from
Template::Plugin but should at least conform to its object-oriented
interface.

   It is recommended that you create plugins in your own package namespace
to avoid conflict with toolkit plugins.  e.g.

     package MyOrg::Template::Plugin::FooBar;

   Use the PLUGIN_BASE option to specify the namespace that you use.  e.g.

     use Template;
     my $template = Template->new({
     	PLUGIN_BASE => 'MyOrg::Template::Plugin',
     });

PLUGIN API
==========

   The following methods form the basic interface between the Template
Toolkit and plugin modules.

load($context)
     This method is called by the Template Toolkit when the plugin module
     is first loaded.  It is called as a package method and thus implicitly
     receives the package name as the first parameter.  A reference to the
     Template::Context object loading the plugin is also passed.  The
     default behaviour for the load() method is to simply return the class
     name.  The calling context then uses this class name to call the new()
     package method.

          package MyPlugin;

          sub load {               # called as MyPlugin->load($context)
          	my ($class, $context) = @_;
          	return $class;       # returns 'MyPlugin'
          }

new($context, @params)
     This method is called to instantiate a new plugin object for the USE
     directive.  It is called as a package method against the class name
     returned by load().  A reference to the Template::Context object
     creating the plugin is passed, along with any additional parameters
     specified in the USE directive.

          sub new {                # called as MyPlugin->new($context)
          	my ($class, $context, @params) = @_;
          	bless {
          	    _CONTEXT => $context,
          	}, $class;	     # returns blessed MyPlugin object
          }

fail($error)
     This method is used for reporting errors.  It returns undef.  e.g.

          sub new {
          	my ($class, $context, $dsn) = @_;

          return $class->fail('No data source specified')
              unless $dsn;

          bless {
              _DSN => $dsn,
          }, $class;
              }

error()
     This method returns the error as set by the above fail() method.  It
     is called by the loading/creating Template::Context object.

DEEPER MAGIC
============

   The Template::Context object that handles the loading and use of
plugins calls the new(), fail() and error() methods against the package
name returned by the load() method.  In pseudo-code terms, it might look
something like this:

     $class  = MyPlugin->load($context);       # returns 'MyPlugin'

     $object = $class->new($context, @params)  # MyPlugin->new(...)
     	|| die $class->error();               # MyPlugin->error()

   The load() method may alterately return a blessed reference to an
object instance.  In this case, new(), fail() and error() are then called
as object methods against that prototype instance.

     package YourPlugin;

     sub load {
         my ($class, $context) = @_;
     	bless {
     	    _CONTEXT => $context,
     	}, $class;
     }

     sub new {
     	my ($self, $context, @params) = @_;
     	return $self;
     }

   In this example, we have implemented a 'Singleton' plugin.  One object
gets created when load() is called and this simply returns itself for each
call to new().

   Another implementation might require individual objects to be created
for every call to new(), but with each object sharing a reference to some
other object to maintain cached data, database handles, etc.  This
pseudo-code example demonstrates the principle.

     package MyServer;

     sub load {
         my ($class, $context) = @_;
     	bless {
     	    _CONTEXT => $context,
     	    _CACHE   => { },
     	}, $class;
     }

     sub new {
     	my ($self, $context, @params) = @_;
     	MyClient->new($self, @params);
     }

     sub add_to_cache   { ... }

     sub get_from_cache { ... }

     package MyClient;

     sub new {
     	my ($class, $server, $blah) = @_;
     	bless {
     	    _SERVER => $server,
     	    _BLAH   => $blah,
     	}, $class;
     }

     sub get {
     	my $self = shift;
     	$self->{ _SERVER }->get_from_cache(@_);
     }

     sub put {
     	my $self = shift;
     	$self->{ _SERVER }->add_to_cache(@_);
     }

   When the plugin is loaded, a MyServer instance is created.  The new()
method is called against this object which instantiates and returns a
MyClient object, primed to communicate with the creating MyServer.

Template::Plugin BASE CLASS
===========================

   The Template::Plugin module implements a base class from which other
Template Toolkit plugins can be derived.  In addition, it also acts as a
general-purpose wrapper object, providing a delegation service via an
AUTOLOAD method to an underlying object.

   A reference to another object should be passed as a parameter (following
the context reference) to the base class new() constructor.  All methods
then called on the Template::Plugin object will be delegated to the
underlying object via an AUTOLOAD method.

     package Template::Plugin::MyPlugin;
     use base qw( Template::Plugin );
     use MyModule;

     sub new {
         my $class   = shift;
         my $context = shift;
     	$class->SUPER::new($context, MyModule->new(@_));
     }

   The name of a Perl module/class may be specified instead of a
reference.  The constructor will attempt to load the module and
instantiate an object via its new() method.  Any additional parameters
passed will be forwarded onto new().

     package Template::Plugin::CGI;
     use base qw( Template::Plugin );

     sub new {
         my $class   = shift;
         my $context = shift;
     	$class->SUPER::new($context, 'CGI', @_);
     }

AUTHOR
======

   Andy Wardley <abw@kfs.org>

     http://www.template-toolkit.org/
     http://www.kfs.org/~abw/

REVISION
========

   $Revision: 1.1 $

COPYRIGHT
=========

     Copyright (C) 1996-2000 Andy Wardley.  All Rights Reserved.
     Copyright (C) 1998-2000 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Template|Template' in this node, `Template::Plugins|Template::Plugins'
in this node, L<Template::Context|Template::Context

interface to Text::Autoformat module
************************************

NAME
====

   Template::Plugin::Autoformat - interface to Text::Autoformat module

SYNOPSIS
========

     [% USE autoformat(options) %]

     [% autoformat(text, more_text, ..., options) %]

     [% FILTER autoformat(options) %]
        a block of text
     [% END %]

EXAMPLES
========

     # define some text for the examples
     [% text = BLOCK %]
        Be not afeard.  The isle is full of noises, sounds and sweet
        airs that give delight but hurt not.
     [% END %]

     # pass options to constructor...
     [% USE autoformat(case => 'upper') %]
     [% autoformat(text) %]

     # and/or pass options to the autoformat subroutine itself
     [% USE autoformat %]
     [% autoformat(text, case => 'upper') %]

     # using the autoformat filter
     [% USE autoformat(left => 10, right => 30) %]
     [% FILTER autoformat %]
        Be not afeard.  The isle is full of noises, sounds and sweet
        airs that give delight but hurt not.
     [% END %]

     # another filter example with configuration options
     [% USE autoformat %]
     [% FILTER autoformat(left => 20) %]
        Be not afeard.  The isle is full of noises, sounds and sweet
        airs that give delight but hurt not.
     [% END %]

     # another FILTER example, defining a 'poetry' filter alias
     [% USE autoformat %]
     [% text FILTER poetry = autoformat(left => 20, right => 40) %]

     # reuse the 'poetry' filter alias
     [% text FILTER poetry %]

     # shorthand form ('|' is an alias for 'FILTER')
     [% text | autoformat %]

     # using forms
     [% USE autoformat(form => '>>>>.<<<', numeric => 'AllPlaces') %]
     [% autoformat(10, 20.32, 11.35) %]

DESCRIPTION
===========

   The autoformat plugin is an interface to Damian Conway's
Text::Autoformat Perl module which provides advanced text wrapping and
formatting.

   Configuration options may be passed to the plugin constructor via the
USE directive.

     [% USE autoformat(right => 30) %]

   The autoformat subroutine can then be called, passing in text items
which will be wrapped and formatted according to the current configuration.

     [% autoformat('The cat sat on the mat') %]

   Additional configuration items can be passed to the autoformat
subroutine and will be merged with any existing configuration specified
via the constructor.

     [% autoformat(text, left => 20) %]

   Configuration options are passed directly to the Text::Autoformat
plugin.  At the time of writing, the basic configuration items are:

     left	left margin (default: 1)
     right	right margin (default 72)
     justify 	justification as one of 'left', 'right', 'full'
                 or 'centre' (default: left)
     case        case conversion as one of 'lower', 'upper',
                 'sentence', 'title', or 'highlight' (default: none)
     squeeze 	squeeze whitespace (default: enabled)

   The plugin also accepts a 'form' item which can be used to define a
format string.  When a form is defined, the plugin will call the
underlying form() subroutine in preference to autoformat().

     [% USE autoformat(form => '>>>>.<<') %]
     [% autoformat(123.45, 666, 3.14) %]

   Additional configuration items relevant to forms can also be specified.

     [% USE autoformat(form => '>>>>.<<', numeric => 'AllPlaces') %]
     [% autoformat(123.45, 666, 3.14) %]

   These can also be passed directly to the autoformat subroutine.

     [% USE autoformat %]
     [% autoformat( 123.45, 666, 3.14,
     		   form    => '>>>>.<<',
     		   numeric => 'AllPlaces' )
     %]

   See Text/Autoformat, for further details.

AUTHORS
=======

   Robert McArthur <mcarthur@dstc.edu.au> wrote the original plugin code,
with some modifications and additions from Andy Wardley <abw@kfs.org>.

   Damian Conway <damian@conway.org> wrote the Text::Autoformat module (in
his copious spare time :-) which does all the clever stuff.

REVISION
========

   $Revision: 2.2 $

COPYRIGHT
=========

   Copyright (C) 2000 Robert McArthur & Andy Wardley.  All Rights Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Template::Plugin|Template::Plugin' in this node,
`Text::Autoformat|Text::Autoformat' in this node

simple Template Plugin interface to CGI.pm module
*************************************************

NAME
====

   Template::Plugin::CGI - simple Template Plugin interface to CGI.pm
module

SYNOPSIS
========

     [% USE CGI %]
     [% CGI.param('parameter') %]

     [% USE things = CGI %]
     [% things.param('name') %]

     # see CGI docs for other methods provided by the CGI object

DESCRIPTION
===========

   This is a very simple Template Toolkit Plugin interface to the CGI
module.  A CGI object will be instantiated via the following directive:

     [% USE CGI %]

   CGI methods may then be called as follows:

     [% CGI.header %]
     [% CGI.param('parameter') %]

   An alias can be used to provide an alternate name by which the object
should be identified.

     [% USE mycgi = CGI %]
     [% mycgi.start_form %]
     [% mycgi.popup_menu({ Name   => 'Color'
     			  Values => [ 'Green' 'Black' 'Brown' ] }) %]

   Parenthesised parameters to the USE directive will be passed to the
plugin constructor:

   [% USE cgiprm = CGI('uid=abw&name=Andy+Wardley') %]     [%
cgiprm.param('uid') %]

AUTHOR
======

   Andy Wardley <kfs.org>

REVISION
========

   $Revision: 2.0 $

COPYRIGHT
=========

   Copyright (C) 1996-1999 Andy Wardley.  All Rights Reserved.  Copyright
(C) 1998-1999 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `CGI|CGI' in this node, `Template::Plugin|Template::Plugin' in this
node,

Template Plugin interface to the DBI.pm module
**********************************************

NAME
====

   Template::Plugin::DBI - Template Plugin interface to the DBI.pm module

SYNOPSIS
========

     # use positional arguments...
     [% USE DBI('dbi:driver:database', 'username', 'password') %]

     # ...or named parameters...
     [% USE DBI(data_source = 'dbi:driver:database',
                username    = 'username',
                password    = 'password') %]

     # ...or call connect() explicitly
     [% USE DBI %]
     [% DBI.connect(dsn, user, pass) %]

     [% FOREACH item = DBI.query( 'SELECT rows FROM table' ) %]
        Here's some row data: [% item.field %]
     [% END %]

     [% query = DBI.prepare('SELECT * FROM user WHERE manager = ?') %]
     [% FOREACH user = query.execute('sam') %]
        ...
     [% FOREACH user = query.execute('abw') %]
        ...

     [% IF DBI.do("DELETE FROM users WHERE uid = 'sam'") %]
        Oh No!  The user was deleted!
     [% END %]

DESCRIPTION
===========

   This Template Toolkit plugin module provides an interface to the Perl
DBI/DBD modules, allowing you to integrate SQL queries into your template
documents.

   A DBI plugin object can be created as follows:

     [% USE DBI %]

   This creates an uninitialised DBI object.  You can then open a
connection to a database using the connect() method.

     [% DBI.connect('dbi:driver:database', 'username', 'password') %]

   The DBI connection can be opened when the plugin is created by passing
arguments to the constructor, called from the USE directive.

     [% USE DBI('dbi:driver:database', 'username', 'password') %]

   You can also use named parameters to provide the data source connection
string, user name and password.

     [% USE DBI(data_source => 'dbi:driver:database',
                username    => 'username',
                password    => 'password')  %]

   Lazy Template hackers may prefer to use 'dsn' or 'connect' as a
shorthand form of the 'data_source' parameter, and 'user' and 'pass' as
shorthand forms of 'username' and 'password', respectively.

     [% USE DBI(connect => 'dbi:driver:database',
                user    => 'username',
                pass    => 'password')  %]

   Any additional DBI attributes can be specified as named parameters.
The 'PrintError' attribute defaults to 0 unless explicitly set true.

     [% USE DBI(dsn, user, pass, ChopBlanks=1) %]

   Methods can then be called on the plugin object using the familiar
dotted notation:

     [% FOREACH item = DBI.query( 'SELECT rows FROM table' ) %]
        Here's some row data: [% item.field %]
     [% END %]

   See `OBJECT METHODS' in this node below for further details of the
methods available.

   An alternate variable name can be provided for the plugin as per regular
Template Toolkit syntax:

     [% USE mydb = DBI('dbi:driver:database','username','password') %]

     [% FOREACH item = mydb.query( 'SELECT rows FROM table' ) %]
        ...

   You can also specify the DBI plugin name in lower case if you prefer:

     [% USE dbi(dsn, user, pass) %]
     [% FOREACH item = dbi.query( 'SELECT rows FROM table' ) %]
        ...

   The disconnect() method can be called to explicitly disconnect the
current database, but this generally shouldn't be necessary as it is
called automatically when the plugin goes out of scope.  You can call
connect() at any time to open a connection to another database.  The
previous connection will be closed automatically.

OBJECT METHODS
==============

connect($data_source, $username, $password)
-------------------------------------------

   Establishes a database connection.  This method accepts both positional
and named parameter syntax.  e.g.

     [% DBI.connect(data_source, username, password) %]
     [% DBI.connect(data_source = 'dbi:driver:database'
                    username    = 'foo'
                    password    = 'bar' ) %]

   The connect method allows you to connect to a data source explicitly.
It can also be used to reconnect an exisiting object to a different data
source.

query($sql)
-----------

   This method submits an SQL query to the database and creates an iterator
object to return the results.  This may be used directly in a FOREACH
directive as shown below.  Data is automatically fetched a row at a time
from the query result set as required for memory efficiency.

     [% FOREACH row = DBI.query('select * from users') %]
        Each [% row.whatever %] can be processed here
     [% END %]

prepare($sql)
-------------

   Prepare a query for later execution.  This returns a compiled query
object (of the Template::Plugin::DBI::Query class) on which the execute()
method can subsequently be called.

     [% query = DBI.prepare('SELECT * FROM users WHERE id = ?') %]

execute(@args)
--------------

   Execute a previously prepared query.  This method should be called on
the query object returned by the prepare() method.  Returns an iterator
object which can be used directly in a FOREACH directive.

     [% query = DBI.prepare('SELECT * FROM users WHERE manager = ?') %]

     [% FOREACH user = query.execute('sam') %]
        [% user.name %]
     [% END %]

     [% FOREACH user = query.execute('sam') %]
        [% user.name %]
     [% END %]

do($sql)
--------

   The do() method executes a sql statement from which no records are
returned.  It will return true if the statement was successful

     [% IF DBI.do("DELETE FROM users WHERE uid = 'sam'") %]
        The user was successfully deleted.
     [% END %]

quote($value, $type)
--------------------

   Calls the quote() method on the underlying DBI handle to quote the value
specified in the appropriate manner for its type.

disconnect()
------------

   Disconnects the current database.

PRE-REQUISITES
==============

   Perl 5.005, Template-Toolkit 2.00, DBI 1.02

SEE ALSO
========

   For general information on the Template Toolkit and DBI modules, see
Template, and `DBI' in this node.

AUTHORS
=======

   The DBI plugin was written by Simon A Matthews,
<sam@knowledgepool.com>, with contributions from Andy Wardley
<abw@kfs.org>.

HISTORY
=======

  1. 2000/11/03  abw Modified connect method to pass all named arguments
     to DBI.  e.g.

          [% USE DBI(dsn, user, pass, ChopBlanks=1) %]

  2. 2000/11/14  abw Added prev() and next() methods to
     Template::Plugin::DBI:Iterator to return the previous and next items
     in the iteration set or undef if not available.

  3. 2000/11/31  sam Added _connect method to Plugin::DBI for backwards
     compatability with code from version 1 of Template that subclassed
     the plugin

     Changed the new method on the DBI plugin so that it checks to see if
     it is being called by a subclassed object.

     Fixed the return value in the DBI plugin when connect is called more
     than once in the lifetime of the plugin.

COPYRIGHT
=========

   Copyright (C) 1999-2000 Simon Matthews.  All Rights Reserved

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

plugin to construct records from a simple data file
***************************************************

NAME
====

   Template::Plugin::Datafile - plugin to construct records from a simple
data file

SYNOPSIS
========

     [% USE mydata = datafile('/path/to/datafile') %]
     [% USE mydata = datafile('/path/to/datafile', delim = '|') %]

     [% FOREACH record = mydata %]
        [% record.this %]  [% record.that %]
     [% END %]

DESCRIPTION
===========

   This plugin provides a simple facility to construct a list of hash
references, each of which represents a data record of known structure,
from a data file.

     [% USE datafile(filename) %]

   A absolute filename must be specified (for this initial implementation
at least - in a future version it might also use the INCLUDE_PATH).  An
optional 'delim' parameter may also be provided to specify an alternate
delimiter character.

     [% USE userlist = datafile('/path/to/file/users')     %]
     [% USE things   = datafile('items', delim = '|') %]

   The format of the file is intentionally simple.  The first line defines
the field names, delimited by colons with optional surrounding whitespace.
Subsequent lines then defines records containing data items, also
delimited by colons.  e.g.

     id : name : email : tel
     abw : Andy Wardley : abw@cre.canon.co.uk : 555-1234
     neilb : Neil Bowers : neilb@cre.canon.co.uk : 555-9876

   Each line is read, split into composite fields, and then used to
initialise a hash array containing the field names as relevant keys.  The
plugin returns a blessed list reference containing the hash references in
the order as defined in the file.

     [% FOREACH user = userlist %]
        [% user.id %]: [% user.name %]
     [% END %]

   The first line of the file must contain the field definitions.  After
the first line, blank lines will be ignored, along with comment line which
start with a '#'.

BUGS
====

   Should handle file names relative to INCLUDE_PATH.  Doesn't permit use
of ':' in a field.  Some escaping mechanism is required.

AUTHOR
======

   Andy Wardley <kfs.org>

REVISION
========

   $Revision: 2.0 $

COPYRIGHT
=========

   Copyright (C) 1996-1999 Andy Wardley.  All Rights Reserved.  Copyright
(C) 1998-1999 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Template::Plugin|Template::Plugin' in this node,

generate formatted date strings
*******************************

NAME
====

   Template::Plugin::Date - generate formatted date strings

SYNOPSIS
========

     [% USE date %]

     # use current time and default format
     [% date.format %]

     # specify time as seconds since epoch or 'h:m:s d-m-y' string
     [% date.format(960973980) %]
     [% date.format('4:20:36 21/12/2000') %]

     # specify format
     [% date.format(mytime, '%H:%M:%S') %]

     # specify locale
     [% date.format(date.now, '%a %d %b %y', 'en_GB') %]

     # named parameters
     [% date.format(mytime, format = '%H:%M:%S') %]
     [% date.format(locale = 'en_GB') %]
     [% date.format(time   = date.now,
     		   format = '%H:%M:%S',
                    locale = 'en_GB) %]

     # specify default format to plugin
     [% USE date(format = '%H:%M:%S', locale = 'de_DE') %]

     [% date.format %]
     ...

DESCRIPTION
===========

   The Date plugin provides an easy way to generate formatted time and date
strings by delegating to the POSIX strftime() routine.

   The plugin can be loaded via the familiar USE directive.

     [% USE date %]

   This creates a plugin object with the default name of 'date'.  An
alternate name can be specified as such:

     [% USE myname = date %]

   The plugin provides the format() method which accepts a time value, a
format string and a locale name.  All of these parameters are optional
with the current system time, default format ('%H:%M:%S %d-%b-%Y') and
current locale being used respectively, if undefined.  Default values for
the time, format and/or locale may be specified as named parameters in the
USE directive.

     [% USE date(format = '%a %d-%b-%Y', locale = 'fr_FR') %]

   When called without any parameters, the format() method returns a string
representing the current system time, formatted by strftime() according to
the default format and for the default locale (which may not be the
current one, if locale is set in the USE directive).

     [% date.format %]

   The plugin allows a time/date to be specified as seconds since the
epoch, as is returned by time().

     File last modified: [% date.format(filemod_time) %]

   The time/date can also be specified as a string of the form 'h:m:s
d/m/y'.  Any of the characters : / - or space may be used to delimit
fields.

     [% USE day = date(format => '%A', locale => 'en_GB') %]
     [% day.format('4:20:00 9-13-2000') %]

   Output:

     Tuesday

   A format string can also be passed to the format() method, and a locale
specification may follow that.

     [% date.format(filemod, '%d-%b-%Y') %]
     [% date.format(filemod, '%d-%b-%Y', 'en_GB') %]

   Any or all of these parameters may be named.  Positional parameters
should always be in the order ($time, $format, $locale).

     [% date.format(format => '%H:%M:%S') %]
     [% date.format(time => filemod, format => '%H:%M:%S') %]
     [% date.format(mytime, format => '%H:%M:%S') %]
     [% date.format(mytime, format => '%H:%M:%S', locale => 'fr_FR') %]
     ...etc...

   The now() method returns the current system time in seconds since the
epoch.

     [% date.format(date.now, '%A') %]

AUTHORS
=======

   Thierry-Michel Barral <kktos@electron-libre.com> wrote the original
plugin and Andy Wardley <abw@cre.canon.co.uk> provided some minor
fixups/enhancements, a test script and documentation).

REVISION
========

   $Revision: 2.0 $

COPYRIGHT
=========

   Copyright (C) 2000 Thierry-Michel Barral, Andy Wardley.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Template::Plugin|Template::Plugin' in this node, `POSIX|POSIX' in this
node

simple Template Plugin interface to Data::Dumper
************************************************

NAME
====

   Template::Plugin::Dumper - simple Template Plugin interface to
Data::Dumper

SYNOPSIS
========

     [% USE Dumper %]

     [% Dumper.dump(variable) %]
     [% Dumper.dump_html(variable) %]

DESCRIPTION
===========

   This is a very simple Template Toolkit Plugin Interface to the
Data::Dumper module.  A Dumper object will be instantiated via the
following directive:

     [% USE Dumper %]

   As a standard plugin, you can also specify its name in lower case:

     [% USE dumper %]

   The Data::Dumper 'Pad', 'Indent' and 'Varname' options are supported as
constructor arguments to affect the output generated.  See
Data/Dumper, for further details.

     [% USE dumper(Indent=0, Pad="<br>") %]

   These options can also be specified in lower case.

     [% USE dumper(indent=0, pad="<br>") %]

METHODS
=======

   There are two methods supported by the Dumper object.  Each will output
into the template the contents of the variables passed to the object
method.

dump()
------

   Generates a raw text dump of the data structure(s) passed

     [% USE Dumper %]
     [% Dumper.dump(myvar) %]
     [% Dumper.dump(myvar, yourvar) %]

dump_html()
-----------

   Generates a dump of the data structures, as per dump(), but with the
characters <, > and E<amp> converted to their equivalent HTML entities and
newlines converted to <br>.

     [% USE Dumper %]
     [% Dumper.dump_html(myvar) %]

AUTHOR
======

   Simon Matthews <sam@knowledgepool.com>

COPYRIGHT
=========

   Copyright (C) 2000 Simon Matthews All Rights Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Data::Dumper|Data::Dumper' in this node,
`Template::Plugin|Template::Plugin' in this node,

simple Template Plugin interface to create formatting function
**************************************************************

NAME
====

   Template::Plugin::Format - simple Template Plugin interface to create
formatting function

SYNOPSIS
========

     [% USE format %]
     [% commented = format('# %s') %]
     [% commented('The cat sat on the mat') %]

     [% USE bold = format('<b>%s</b>') %]
     [% bold('Hello') %]

DESCRIPTION
===========

   The format plugin constructs sub-routines which format text according to
a printf()-like format string.

AUTHOR
======

   Andy Wardley <kfs.org>

REVISION
========

   $Revision: 2.0 $

COPYRIGHT
=========

   Copyright (C) 1996-1999 Andy Wardley.  All Rights Reserved.  Copyright
(C) 1998-1999 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Template::Plugin|Template::Plugin' in this node,

plugin to create Template::Iterator objects
*******************************************

NAME
====

   Template::Plugin::Iterator - plugin to create Template::Iterator objects

SYNOPSIS
========

     [% USE iterator(list, args) %]

     [% FOREACH item = iterator %]
        [% '<ul>' IF iterator.first %]
        <li>[% item %]
        [% '</ul>' IF iterator.last %]
     [% END %]

DESCRIPTION
===========

   The iterator plugin provides a way to create a Template::Iterator object
to iterate over a data set.  An iterator is implicitly automatically by the
FOREACH directive.  This plugin allows the iterator to be explicitly
created with a given name.

AUTHOR
======

   Andy Wardley <abw@kfs.org>

REVISION
========

   $Revision: 2.0 $

COPYRIGHT
=========

   Copyright (C) 2000 Andy Wardley.  All Rights Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Template::Iterator|Template::Iterator' in this node,
`Template::Plugin|Template::Plugin' in this node

Generate Java Classes from XML description files and templates.
***************************************************************

NAME
====

   Template::Plugin::Java - Generate Java Classes from XML description
files and templates.

SYNOPSIS
========

   From an xml file such as:

     <aBean>
     	<java: option1="value1">
     		<option2>value2</option2>
     	</java:>
     	<foo>10</foo>
     	<bar>String</bar>
     	<container>
     		<baz>20</baz>
     	</container>
     </aBean>

   Through the program "tjava":

   tjava [options] [file.xml ...]

   Via a template, such as:

     [% USE Java %]
     package $package;

     public class $class {

     [% FOREACH Java.variables %]
     $type $name = $initializer;
     [% END %]

     //... etc
     }

   To generated Java source code in the appropriate directory as
determined by the package of the .xml file's directory, specified package
option if any, and CLASSPATH.

OPTIONS
=======

   Any options may be given besides those listed, these are passed
directly to the Templates being processed in the stash (the variable table
at time of processing). They can be given in the <java:> ... </java:>
section of an XML file (in which case, don't use the - dashes) as
attributes or elements, or on the command line.

*-template*
     Name of the template to process. No extension is assumed by default
     unlike in the previous version.

*-package*
     Destination package to put the generated classes, otherwise will be
     determined from how the current directory relates to the CLASSPATH.

*-class*
     Class name to use, otherwise will infer from the root tag of the XML
     file.

*-templatePath*
     Colon separated path where the templates can be found, overrides the
     environment variable TEMPLATEPATH. This doesn't work right now, so
     use the TEMPLATEPATH environment variable.

*-genContainers*
     If set to 0, classes for subcontainers will not be generated. This is
     generally not useful.

*-containerTemplate*
     By default set to Container, this is the default template, as well as
     the template used for sub-containers.

*-containerNamePrefix*
     By default, if generating class Foo that needs to have a sub
     container wrapped in tag <bar>, it's name will be FooBar. This is
     safe and won't cause collisions with different classes having sub
     containers of the same name (until some sort  of dependency checking
     code is introduced). To turn this off, set it to the empty string "".

*-interface*
     Interface to add to list of implemented interfaces, can be supplied
     multiple times. Make sure you append any necessary code to implement
     any of these interfaces.

*-append*
     Text to insert in the generated class body.

*-appendFile*
     Will insert text read from the file specified into the generated
     class body.  This option and the *-append* option are mutually
     exclusive.

*-file[s]*
     The XML file(s) to parse. This is useful for when the Plugin is
     instantiated from a custom script, not via tjava or inside a template.

     Any other option will be placed into the stash for the templates to
     use, making tjava very useful with your custom templates.

     Anything that's not an option will be assumed to be a file.

DESCRIPTION
===========

   Template::Plugin::Java is a plugin module for the Template toolkit that
makes it easier to write templates for generating Java source code,
ultimately for transforming XML descriptions into Java language sources.

   It can be used either directly on the command line, or loaded from a
Template with a `[% USE Java %]' statement, or in many other ways. It
tries to be intelligent and figure out what context you are using it in.

   I'll write more eventually, for now see the examples in the
distribution.

METHODS
=======

new
     This, the constructor, does everything necessary to create a new
     instance of the Java plugin, based on context. If not given a
     context, takes control of the command line and then parses any
     options and files given. This is what the "tjava" utility does.

template
     Sets the Template of the instance (and therefore the context) when
     called with a parameter, returns it otherwise.

context
     Sets the Template::Context of the instance when called with a
     parameter, returns it otherwise.

getInitializer
     Returns an initializer string for a type.

variables
     Returns a list of variable description hashes.

variableDeclarations($options_hashref)
     Returns a list of <type> <name> strings such as: 	String foo 	int bar
     ...

     These can be used in a template in this way: 	function ([%
     Java.variableDeclarations.join(", ") %]) { 	...  	}

variableNames
     Returns a list of variable names.

getVariables
     Returns a hashref of variables, taking a raw variables hash.  Takes
     an optional variable type string.

scalar
     Whether or not a java type is a Scalar type.

string
     Whether or not a java type is a String type.

array
     Whether or not a java type is an Array type.

arrayType
     Figures out the type of elements a Vector will take.  Parameters:
     name, arrayref TODO: This should be an aggregate, not merely the type
     of the first element.

encapsulatePrimitive
     Translate int to Integer, long to Long, etc.

mapType
     Maps a perl scalar or reference to a Java type.  Parameters: name of
     element, value of element.

genClass
     Generates a container class.

     Parameters: name of tag to create container from, hashref to gen from.
     Returns:    name of class generated.

castJavaString
     Casts a java String to another type using the appropriate code.
     Parameters: name of variable to cast, type to cast to.

ENVIRONMENT
===========

   These are the environment variables used.

TEMPLATEPATH
     Colon separated path to where templates can be found. Overridden by
     the *-templatePath* command line option.

CLASSPATH
     Used for many things, like inferring the package of the current
     directory, where to put generated files that are in other packages,
     and other evil things I have not yet thought of.

AUTHOR
======

   Rafael Kitover (caelum@debian.org)

COPYRIGHT
=========

   This program is Copyright (c) 2000 by Rafael Kitover. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

BUGS
====

   Probably many.

   The *-templatePath* option should actually work.

TODO
====

   A very great deal.  Including more documentation.  DBClass doesn't work
in tt 1.x.  Non-sense options in java: contexts should be somehow handled?

SEE ALSO
========

   `perl(1)' in this node, `Template(3)' in this node,
`Template::Plugin::Java::Utils(3)' in this node,
`Template::Plugin::JavaSQL(3)' in this node
`Template::Plugin::Java::Constants(3)' in this node,

Constants for the Java Template plugin modules.
***********************************************

NAME
====

   Template::Plugin::Java::Constants - Constants for the Java Template
plugin modules.

SYNOPSIS
========

   use Template::Plugin::Java::Constants qw/:regex/; use
Template::Plugin::Java::Constants qw/:boolean/; use
Template::Plugin::Java::Constants qw/:all/;

DESCRIPTION
===========

regex
     The "regex" tag exports qr// compiled regular expressions SCALAR,
     PRIMITIVE, STRING and ARRAY, these are for matching Java types. All
     of these match a whole line, with no extra whitespace, and return the
     matched java type as $1. They may be used as:

     $string =~ /@{[SCALAR]}/; # Ugly but effective and relatively fast.

    SCALAR
          Any primitive or encapsulated primitive: int, or Integer, or
          String, etc.

    PRIMITIVE
          Only primitive types like int, float, double, byte, etc.

    STRING
          An incarnation of java.lang.String.

    ARRAY
          A java.util.Vector.

boolean
     The boolean tag just exports the constants TRUE as 1 and FALSE as 0.

all
     Exports all of the proceeding.

AUTHOR
======

   Rafael Kitover (caelum@debian.org)

COPYRIGHT
=========

   This program is Copyright (c) 2000 by Rafael Kitover. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `perl(1)' in this node, `Template(3)' in this node,
`Template::Plugin::Java::Utils(3)' in this node,
`Template::Plugin::Java::SQL(3)' in this node

Utility functions for Template::Plugin::Java.
*********************************************

NAME
====

   Template::Plugin::Java::Utils - Utility functions for
Template::Plugin::Java.

SYNOPSIS
========

     use Template::Plugin::Java::Utils qw/list of subroutines to import/;

SUBROUTINES
===========

createTemplate
     Creates a new Template with reasonable options.

parseOptions
     Replaces c_c with cC and nosomething=whatever with something=0 in the
     keys of a hash.

setOption
     Adds to or sets an option in a hash, supports nested arrays and
     boolean options. The logic here is one of those things that just
     works the way it is and seems decipherable, but don't mess with it.

parseCmdLine
     Parses @ARGV into a hash of options and values, leaving everything
     else that is most likely a list of files on @ARGV.

*sqlType2JavaType( type_name [, precision for numeric types] )*
     Maps some ANSI SQL data types to the closest Java variable types. The
     default case is byte[] for unrecognized sql types.

*simplifyPath( path )*
     Remove any dir/../ or /./ or extraneous / from a path, as well as
     prepending the current directory if necessary.

*findPackageDir( directory )*
     Find package in $ENV{CLASSPATH}.

*determinePackage([ optional directory ])*
     Determine the package of the current or passed-in directory.

*isNum( string )*
     Determines whether a string is a number or not. Uses the more powerful
     DBI::looks_like_number heuristic if available.

*castJavaString( variable_name, target_type )*
     Casts a java String to another type using the appropriate code.

*javaTypeName( javaType )*
     Transform a java type name to a character string version. In other
     words, String remains String, but byte[] becomes byteArray.

ENVIRONMENT
===========

   These are the environment variables used.

TEMPLATEPATH
     Colon separated path to where templates can be found, used by default
     in the createTemplate subroutine.

CLASSPATH
     Searched in *findPackageDir* to find a directory relative to it.

AUTHOR
======

   Rafael Kitover (caelum@debian.org)

COPYRIGHT
=========

   This program is Copyright (c) 2000 by Rafael Kitover. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

BUGS
====

   None known.

TODO
====

   Nothing here.

SEE ALSO
========

   `perl(1)' in this node, `Template(3)' in this node,
`Template::Plugin::Java(3)' in this node, `Template::Plugin::JavaSQL(3)'
in this node `Template::Plugin::Java::Constants(3)' in this node,

Help generate Java from database schemas.
*****************************************

NAME
====

   Template::Plugin::JavaSQL - Help generate Java from database schemas.

SYNOPSES
========

   Within an XML file processed by the Java plugin:

     <sql:
     	query="select foo as f, bar as b from some_table"
     >

     or

     <sql:
     	table="some_table"
     >

   Via a template such as:

     [% USE Java %]
     [% Use JavaSQL %]
     ...
     String query =
     "select [% JavaSQL.columnNames.join(", ") %] from [% JavaSQL.tables.join(", ") %]";
     [% IF JavaSQL.where %]
     query += " where [% JavaSQL.where %] ";
     [% ELSE %]
     query += " where 0=0 ";
     [% END %]
     [% FOREACH JavaSQL.columns %]
     if (${varName}Set) { query += " and $name = ?"; }
     [% END %]
     [% IF JavaSQL.order %]
     query += "order by [% JavaSQL.order %]";
     [% END %]
     stmt = myConnection.prepareStatement(query);

   Just use the DBClass.template from the distribution for fully functional
database classes.

DESCRIPTION
===========

   In addition to methods that refer to parts of a SQL query, any columns
resultant from the query or table will be added as java variables to the
variables hash, with close-as-possible mapped types.

METHODS
=======

new
     Constructor. If given one parameter of type Template::Context, will
     use that as a context. Then process the contents of "sql:" within the
     stash. This is what typically happens inside a template when a [% USE
     JavaSQL %] directive is encountered.

context
     Returns Template::Context this instance has, if any.

query
     The complete query, either supplied at instantiation or inferred from
     other arguments.

where
     The "where" portion of the SQL query, excluding the word "where"
     itself.

tables
     A list of tables used by the query.

tableCount
     Number of tables used by query.

updatable
     Whether the query used can be used to update the table.

order
     An ORDER BY clause, if one was used.

columnNames
     A list of column names used in the query.

isColumn
     Check whether a variable name is a column.

varToColumn
     Gives the column name mapping of the Java variable name.

columnToVar
     Gives the Java variable name mapping of the column name.

columnCount
     Number of columns returned from query.

columns
     Intended to be used as [% FOREACH JavaSQL.columns %] ...  See `' in
     this node.

parseQuery
     Used internally to parse a SQL query and set the appropriate state
     variables.

ENVIRONMENT
===========

DBI_DSN
     DBI Data Source Name, for example, the data source for MySQL and
     database name "test" it would be: dbi:mysql:database=test

DBI_USER
     User name to connect to the database as.

DBI_PASS
     Password for database, can be blank for no password.

AUTHOR
======

   Rafael Kitover (caelum@debian.org) The concept and related templates
are based on Andrew Lanthier's dbgen framework (an unreleased development
utility).

COPYRIGHT
=========

   This program is Copyright (c) 2000 by Rafael Kitover. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

BUGS
====

   Probably many.

TODO
====

   A very great deal.

SEE ALSO
========

   `perl(1)' in this node, `Template(3)' in this node,
`Template::Plugin::Java::Utils(3)' in this node,
`Template::Plugin::Java::Constants(3)' in this node,

presents a data set as rows and columns
***************************************

NAME
====

   Template::Plugin::Table - presents a data set as rows and columns

SYNOPSIS
========

     [% USE table(list, rows=n, cols=n, overlap=n, pad=0) %]

     [% FOREACH item = table.row(n) %]
        [% item %]
     [% END %]

     [% FOREACH item = table.col(n) %]
        [% item %]
     [% END %]

     [% FOREACH row = table.rows %]
        [% FOREACH item = row %]
           [% item %]
        [% END %]
     [% END %]

     [% FOREACH col = table.cols %]
        [% col.first %] - [% col.last %] ([% col.size %] entries)
     [% END %]

DESCRIPTION
===========

   The Table plugin allows you to format a list of data items into a
virtual table.  When you create a Table plugin via the USE directive,
simply pass a list reference as the first parameter and then specify a
fixed number of rows or columns.

     [% USE Table(list, rows=5) %]
     [% USE table(list, cols=5) %]

   The 'Table' plugin name can also be specified in lower case as shown in
the second example above.  You can also specify an alternative variable
name for the plugin as per regular Template Toolkit syntax.

     [% USE mydata = table(list, rows=5) %]

   The plugin then presents a table based view on the data set.  The data
isn't actually reorganised in any way but is available via the row(),
col(), rows() and cols() as if formatted into a simple two dimensional
table of n rows x n columns.  Thus, if our sample 'alphabet' list
contained the letters 'a' to 'z', the above USE directives would create
plugins that represented the following views of the alphabet.

     [% USE table(alphabet, ... %]

     rows=5                  cols=5
     a  f  k  p  u  z        a  g  m  s  y
     b  g  l  q  v           b  h  n  t  z
     c  h  m  r  w           c  i  o  u
     d  i  n  s  x           d  j  p  v
     e  j  o  t  y           e  k  q  w
                             f  l  r  x

   We can request a particular row or column using the row() and col()
methods.

     [% USE table(alphabet, rows=5) %]
     [% FOREACH item = table.row(0) %]
        # [% item %] set to each of [ a f k p u z ] in turn
     [% END %]

     [% FOREACH item = table.col(2) %]
        # [% item %] set to each of [ m n o p q r ] in turn
     [% END %]

   Data in rows is returned from left to right, columns from top to
bottom.  The first row/column is 0.  By default, rows or columns that
contain empty values will be padded with the undefined value to fill it to
the same size as all other rows or columns.  For example, the last row
(row 4) in the first example would contain the values [ e j o t y undef ].
The Template Toolkit will safely accept these undefined values and print a
empty string.  You can also use the IF directive to test if the value is
set.

     [% FOREACH item = table.row(4) %]
        [% IF item %]
           Item: [% item %]
        [% END %]
     [% END %]

   You can explicitly disable the 'pad' option when creating the plugin to
returned shortened rows/columns where the data is empty.

     [% USE table(alphabet, cols=5, pad=0) %]
     [% FOREACH item = table.col(4) %]
        # [% item %] set to each of 'y z'
     [% END %]

   The rows() method returns all rows/columns in the table as a reference
to a list of rows (themselves list references).  The row() methods when
called without any arguments calls rows() to return all rows in the table.

   Ditto for cols() and col().

     [% USE table(alphabet, cols=5) %]
     [% FOREACH row = table.rows %]
        [% FOREACH item = row %]
           [% item %]
        [% END %]
     [% END %]

   The Template Toolkit provides the first(), last() and size() methods
that can be called on list references to return the first/last entry or
the number of entried.  The following example shows how we might use this
to provide an alphabetical index split into 3 even parts.

     [% USE table(alphabet, cols=3, pad=0) %]
     [% FOREACH group = table.col %]
        [ [% group.first %] - [% group.last %] ([% group.size %] letters) ]
     [% END %]

   This produces the following output:

     [ a - i (9 letters) ]
     [ j - r (9 letters) ]
     [ s - z (8 letters) ]

   We can also use the general purpose join() list method which joins the
items of the list using the connecting string specified.

     [% USE table(alphabet, cols=5) %]
     [% FOREACH row = table.rows %]
        [% row.join(' - ') %]
     [% END %]

   Data in the table is ordered downwards rather than across but can easily
be transformed on output.  For example, to format our data in 5 columns
with data ordered across rather than down, we specify 'rows=5' to order
the data as such:

     a  f  .  .
     b  g  .
     c  h
     d  i
     e  j

   and then iterate down through each column (a-e, f-j, etc.) printing the
data across.

     a  b  c  d  e
     f  g  h  i  j
     .  .
     .

   In addition to a list reference, the Table plugin constructor may be
passed a reference to a Template::Iterator object or subclass thereof.
The get_all() method is first called on the iterator to return all
remaining items.  These are then available via the usual Table interface.

     [% USE DBI(dsn,user,pass) -%]

     # query() returns an iterator
     [% results = DBI.query('SELECT * FROM alphabet ORDER BY letter') %]

     # pass into Table plugin
     [% USE table(results, rows=8 overlap=1 pad=0) -%]

     [% FOREACH row = table.cols -%]
        [% row.first.letter %] - [% row.last.letter %]:
           [% row.join(', ') %]
     [% END %]

AUTHOR
======

   Andy Wardley <abw@kfs.org>

REVISION
========

   $Revision: 2.1 $

COPYRIGHT
=========

   Copyright (C) 2000 Andy Wardley.  All Rights Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Template::Plugin|Template::Plugin' in this node,

constructs query URL's with parameters
**************************************

NAME
====

   Template::Plugin::URL - constructs query URL's with parameters

SYNOPSIS
========

     [% USE url('/cgi-bin/foo.pl') %]

     [% url(debug = 1, id = 123) %]
        # ==> /cgi/bin/foo.pl?debug=1&id=123

     [% USE mycgi = url('/cgi-bin/bar.pl', mode='browse', debug=1) %]

     [% mycgi %]
        # ==> /cgi/bin/bar.pl?mode=browse&debug=1

     [% mycgi(mode='submit') %]
        # ==> /cgi/bin/bar.pl?mode=submit&debug=1

     [% mycgi(debug='d2 p0', id='D4-2k[4]') %]
        # ==> /cgi-bin/bar.pl?mode=browse&debug=d2%20p0&id=D4-2k%5B4%5D

DESCRIPTION
===========

   The URL plugin can be used to construct complex URLs from a base stem
and a hash array of additional query parameters.

   The constructor should be passed a base URL and optionally, a hash array
reference of default parameters and values.  Used from with a Template
Documents, this would look something like the following:

     [% USE url('http://www.somewhere.com/cgi-bin/foo.pl') %]
     [% USE url('/cgi-bin/bar.pl', mode='browse') %]
     [% USE url('/cgi-bin/baz.pl', mode='browse', debug=1) %]

   When the plugin is then called without any arguments, the default base
and parameters are returned as a formatted query string.

     [% url %]

   For the above three examples, these will produce the following outputs:

     http://www.somewhere.com/cgi-bin/foo.pl
     /cgi-bin/bar.pl?mode=browse
     /cgi-bin/baz.pl?mode=browse&debug=1

   Additional parameters may be also be specified:

     [% url(mode='submit', id='wiz') %]

   Which, for the same three examples, produces:

     http://www.somewhere.com/cgi-bin/foo.pl?mode=submit&id=wiz
     /cgi-bin/bar.pl?mode=submit&id=wiz
     /cgi-bin/baz.pl?mode=browse&debug=1&id=wiz

   A new base URL may also be specified as the first option:

     [% url('/cgi-bin/waz.pl', test=1) %]

   producing

     /cgi-bin/waz.pl?test=1
     /cgi-bin/waz.pl?mode=browse&test=1
     /cgi-bin/waz.pl?mode=browse&debug=1&test=1

   The ordering of the parameters is non-deterministic due to fact that
Perl's hashes themselves are unordered.  This isn't a problem as the
ordering of CGI parameters is insignificant (to the best of my knowledge).
All values will be properly escaped thanks to some code borrowed from
Lincoln Stein's CGI.pm.  e.g.

     [% USE url('/cgi-bin/woz.pl') %]
     [% url(name="Elrich von Benjy d'Weiro") %]

   Here the spaces and "'" character are escaped in the output:

     /cgi-bin/woz.pl?name=Elrich%20von%20Benjy%20d%27Weiro

   Alternate name may be provided for the plugin at construction time as
per regular Template Toolkit syntax.

     [% USE mycgi = url('cgi-bin/min.pl') %]

     [% mycgi(debug=1) %]

AUTHOR
======

   Andy Wardley <abw@kfs.org>

REVISION
========

   $Revision: 2.0 $

COPYRIGHT
=========

   Copyright (C) 2000 Andy Wardley.  All Rights Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Template::Plugin|Template::Plugin' in this node,

wrap text using the Text::Wrap module.
**************************************

NAME
====

   Template::Plugin::Wrap - wrap text using the Text::Wrap module.

SYNOPSIS
========

     [% USE wrap %]

     # call wrap subroutine
     [% wrap(mytext, width, initial_tab,  subsequent_tab) %]

     # or use wrap FILTER
     [% mytext FILTER wrap(width, initital_tab, subsequent_tab) %]

DESCRIPTION
===========

   This plugin provides an interface to the Text::Wrap module which
provides simple paragraph formatting.

   It defines a 'wrap' subroutine which can be called, passing the input
text and further optional parameters to specify the page width (default:
72), and tab characters for the first and subsequent lines (no defaults).

     [% USE wrap %]

     [% text = BLOCK %]
     First, attach the transmutex multiplier to the cross-wired
     quantum homogeniser.
     [% END %]

     [% wrap(text, 40, '* ', '  ') %]

   Output:

     * First, attach the transmutex
       multiplier to the cross-wired quantum
       homogeniser.

   It also registers a 'wrap' filter which accepts the same three optional
arguments but takes the input text directly via the filter input.

     [% FILTER bullet = wrap(40, '* ', '  ') -%]
     First, attach the transmutex multiplier to the cross-wired quantum
     homogeniser.
     [%- END %]

     [% FILTER bullet -%]
     Then remodulate the shield to match the harmonic frequency, taking
     care to correct the phase difference.
     [% END %]

   Output:

     * First, attach the transmutex
       multiplier to the cross-wired quantum
       homogeniser.

     * Then remodulate the shield to match
       the harmonic frequency, taking
       care to correct the phase difference.

AUTHOR
======

   Andy Wardley <kfs.org>

   The Text::Wrap module was written by David Muir Sharnoff
<muir@idiom.com> with help from Tim Pierce and many others.

REVISION
========

   $Revision: 2.1 $

COPYRIGHT
=========

   Copyright (C) 1996-2000 Andy Wardley.  All Rights Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Template::Plugin|Template::Plugin' in this node,
`Text::Wrap|Text::Wrap' in this node

simple Template Toolkit plugin interfacing to the XML::DOM module
*****************************************************************

NAME
====

   Template::Plugin::XML::DOM - simple Template Toolkit plugin interfacing
to the XML::DOM module

SYNOPSIS
========

     [% USE doc = XML.DOM('/path/to/file.xml') %]

     # print all HREF attributes of all CODEBASE elements
     [% FOREACH node = doc.getElementsByTagName('CODEBASE') %]
        * [% s.getAttribute('href') %]     # or just '[% s.href %]'
     [% END %]

     # see XML::DOM docs for other methods provided by this object

PRE-REQUISITES
==============

   This plugin requires that the XML::Parser and XML::DOM modules be
installed.  These are available from CPAN:

     http://www.cpan.org/modules/by-module/XML

DESCRIPTION
===========

   This is a very simple Template Toolkit Plugin interface to the XML::DOM
module.   The plugin loads the XML::DOM module, instantiates a parser and
parser the file passed by name as a parameter.  An XML::DOM::Node object
is returned through which the XML document can be traverse.  See
XML/DOM, for full details.

     [% USE dom = XML.DOM('myxmlfile') %]

   The constructor will also accept configuration options destined for the
XML::Parser.

     [% USE dom = XML.DOM('myxmlfile',
     			  ProtocolEncoding => 'ISO-8859-1') %]

   This plugin also provides an AUTOLOAD method for XML::DOM::Node which
calls getAttribute() for any undefined methods.  Thus, you can use the
short form of

     [% node.attribute %]

   in place of

     [% node.getAttribute('attribute') %]

AUTHOR
======

   This plugin module was written by Andy Wardley <cre.canon.co.uk>.

   The XML::DOM module is by Enno Derksen <enno@att.com> and Clark Cooper
<coopercl@sch.ge.com>.  It extends the the XML::Parser module, also by
Clark Cooper which itself is built on James Clark's expat library.

REVISION
========

   $Revision: 2.1 $

COPYRIGHT
=========

   Copyright (C) 2000 Andy Wardley.  All Rights Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `XML::DOM|XML::DOM' in this node, `XML::Parser|XML::Parser' in this
node, `Template::Plugin|Template::Plugin' in this node,

Template Toolkit plugin to the XML::RSS module
**********************************************

NAME
====

   Template::Plugin::XML::RSS - Template Toolkit plugin to the XML::RSS
module

SYNOPSIS
========

     [% USE news = XML.RSS($filename) %]

     [% FOREACH item = news.items %]
        [% item.title %]
        [% item.link  %]
     [% END %]

PRE-REQUISITES
==============

   This plugin requires that the XML::Parser and XML::RSS modules be
installed.  These are available from CPAN:

     http://www.cpan.org/modules/by-module/XML

DESCRIPTION
===========

   This Template Toolkit plugin provides a simple interface to the
XML::RSS module.

     [% USE news = XML.RSS('mysite.rdf') %]

   It creates an XML::RSS object, which is then used to parse the RSS file
specified as a parameter in the USE directive.  A reference to the
XML::RSS object is then returned.

   An RSS (Rich Site Summary) file is typically used to store short news
'headlines' describing different links within a site.  This example is
extracted from http://slashdot.org/slashdot.rdf.

     <?xml version="1.0"?><rdf:RDF
     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
     xmlns="http://my.netscape.com/rdf/simple/0.9/">

       <channel>
     	<title>Slashdot:News for Nerds. Stuff that Matters.</title>
     	<link>http://slashdot.org</link>
     	<description>News for Nerds.  Stuff that Matters</description>
       </channel>

       <image>
     	<title>Slashdot</title>
     	<url>http://slashdot.org/images/slashdotlg.gif</url>
     	<link>http://slashdot.org</link>
       </image>

       <item>
     	<title>DVD CCA Battle Continues Next Week</title>
     	<link>http://slashdot.org/article.pl?sid=00/01/12/2051208</link>
       </item>

       <item>
     	<title>Matrox to fund DRI Development</title>
     	<link>http://slashdot.org/article.pl?sid=00/01/13/0718219</link>
       </item>

       <item>
     	<title>Mike Shaver Leaving Netscape</title>
     	<link>http://slashdot.org/article.pl?sid=00/01/13/0711258</link>
       </item>

     </rdf:RDF>

   The attributes of the channel and image elements can be retrieved
directly from the plugin object using the familiar dotted compound
notation:

     [% news.channel.title  %]
     [% news.channel.link   %]
     [% news.channel.etc... %]

     [% news.image.title    %]
     [% news.image.url      %]
     [% news.image.link     %]
     [% news.image.etc...   %]

   The list of news items can be retrieved using the 'items' method:

     [% FOREACH item = news.items %]
        [% item.title %]
        [% item.link  %]
     [% END %]

AUTHOR
======

   Andy Wardley <cre.canon.co.uk>

CREDITS
=======

   The XML::RSS module, which implements all of the functionality that
this plugin delegates to, was written by Jonathan Eisenzopf
<eisen@pobox.com>.

   This plugin was inspired by an article in Web Techniques by Randal
Schwartz <merlyn@stonehenge.com>.

REVISION
========

   $Revision: 2.0 $

COPYRIGHT
=========

   Copyright (C) 2000 Andy Wardley.  All Rights Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `XML::RSS|XML::RSS' in this node,  `Template::Plugin|Template::Plugin'
in this node,

Template Toolkit plugin to the XML::XPath module
************************************************

NAME
====

   Template::Plugin::XML::XPath - Template Toolkit plugin to the
XML::XPath module

SYNOPSIS
========

     # load plugin and specify XML file to parse
     [% USE xpath = XML.XPath(xmlfile) %]
     [% USE xpath = XML.XPath(file => xmlfile) %]
     [% USE xpath = XML.XPath(filename => xmlfile) %]

     # load plugin and specify XML text to parse
     [% USE xpath = XML.XPath(xmltext) %]
     [% USE xpath = XML.XPath(xml => xmltext) %]
     [% USE xpath = XML.XPath(text => xmltext) %]

     # then call any XPath methods (see XML::XPath docs)
     [% FOREACH page = xpath.findnodes('/html/body/page') %]
        [% page.getAttribute('title') %]
     [% END %]

PRE-REQUISITES
==============

   This plugin requires that the XML::Parser and XML::XPath modules be
installed.  These are available from CPAN:

     http://www.cpan.org/modules/by-module/XML

DESCRIPTION
===========

   This is a Template Toolkit plugin interfacing to the XML::XPath module.
=head1 AUTHOR

   This plugin module was written by Andy Wardley <abw@kfs.org>.

   The XML::XPath module is by Matt Sergeant <matt@sergeant.org<gt>.

REVISION
========

   $Revision: 2.1 $

COPYRIGHT
=========

   Copyright (C) 2000 Andy Wardley.  All Rights Reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   For further information see XML/XPath,
XML/Parser, and Template/Plugin.

provider module for loading and instantiating plugins
*****************************************************

NAME
====

   Template::Plugins - provider module for loading and instantiating
plugins

SYNOPSIS
========

     use Template::Plugins;

     $plugin_provider = Template::Plugins->new(\%options);

     ($plugin, $error) = $plugin_provider->fetch($name, @args);

DESCRIPTION
===========

   The Template::Plugins module defines a provider class which can be used
to load and instantiate Template Toolkit plugin modules.

METHODS
=======

new(\%params)
-------------

   Constructor method which instantiates and returns a reference to a
Template::Plugins object.  A reference to a hash array of configuration
items may be passed as a parameter.  These are described below.

   Note that the Template.pm front-end module creates a Template::Plugins
provider, passing all configuration items.  Thus, the examples shown below
in the form:

     $plugprov = Template::Plugins->new({
     	PLUGIN_BASE => 'MyTemplate::Plugin',
         LOAD_PERL   => 1,
     	...
     });

   can also be used via the Template module as:

     $ttengine = Template->new({
     	PLUGIN_BASE => 'MyTemplate::Plugin',
         LOAD_PERL   => 1,
     	...
     });

   as well as the more explicit form of:

     $plugprov = Template::Plugins->new({
     	PLUGIN_BASE => 'MyTemplate::Plugin',
         LOAD_PERL   => 1,
     	...
     });

     $ttengine = Template->new({
     	LOAD_PLUGINS => [ $plugprov ],
     });

fetch($name, @args)
-------------------

   Called to request that a plugin of a given name be provided.  The
relevant module is first loaded (if necessary) and the load() class method
called to return the factory class name (usually the same package name) or
a factory object (a prototype).  The new() method is then called as a
class or object method against the factory, passing all remaining
parameters.

   Returns a reference to a new plugin object or ($error, STATUS_ERROR) on
error.  May also return (undef, STATUS_DECLINED) to decline to serve the
request.  If TOLERANT is set then all errors will be returned as declines.

CONFIGURATION OPTIONS
=====================

   The following list details the configuration options that can be
provided to the Template::Plugins new() constructor.

PLUGINS
     The PLUGINS options can be used to provide a reference to a hash array
     that maps plugin names to Perl module names.  A number of standard
     plugins are defined (e.g. 'table', 'cgi', 'dbi', etc.) which map to
     their corresponding Template::Plugin::* couterpart.  These can be
     redefined by values in the PLUGINS hash.

          my $plugins = Template::Plugins->new({
          	PLUGINS => [
          	    cgi => 'MyOrg::Template::Plugin::CGI',
          	    foo => 'MyOrg::Template::Plugin::Foo',
          	    bar => 'MyOrg::Template::Plugin::Bar',
          	],
          });

     The USE directive is used to create plugin objects and does so by
     calling the plugin() method on the current Template::Context object.
     If the plugin name is defined in the PLUGINS hash then the
     corresponding Perl module is loaded via require().  The context then
     calls the load() class method which should return the class name
     (default and general case) or a prototype object against which the
     new() method can be called to instantiate individual plugin objects.

     If the plugin name is not defined in the PLUGINS hash then the
     PLUGIN_BASE and/or LOAD_PERL options come into effect.

PLUGIN_BASE
     If a plugin is not defined in the PLUGINS hash then the PLUGIN_BASE
     is used to attempt to construct a correct Perl module name which can
     be successfully loaded.

     The PLUGIN_BASE can be specified as a single value or as a reference
     to an array of multiple values.  The default PLUGIN_BASE value,
     'Template::Plugin', is always added the the end of the PLUGIN_BASE
     list (a single value is first converted to a list).  Each value should
     contain a Perl package name to which the requested plugin name is
     appended.

     example 1:

          my $plugins = Template::Plugins->new({
          	PLUGIN_BASE => 'MyOrg::Template::Plugin',
          });

          [% USE Foo %]    # => MyOrg::Template::Plugin::Foo
                             or        Template::Plugin::Foo

     example 2:

          my $plugins = Template::Plugins->new({
          	PLUGIN_BASE => [   'MyOrg::Template::Plugin',
          			 'YourOrg::Template::Plugin'  ],
          });

          [% USE Foo %]    # =>   MyOrg::Template::Plugin::Foo
                             or YourOrg::Template::Plugin::Foo
                             or          Template::Plugin::Foo

LOAD_PERL
     If a plugin cannot be loaded using the PLUGINS or PLUGIN_BASE
     approaches then the provider can make a final attempt to load the
     module without prepending any prefix to the module path.  This allows
     regular Perl modules (i.e. those that don't reside in the
     Template::Plugin or some other such namespace) to be loaded and used
     as plugins.

     By default, the LOAD_PERL option is set to 0 and no attempt will be
     made to load any Perl modules that aren't named explicitly in the
     PLUGINS hash or reside in a package as named by one of the PLUGIN_BASE
     components.

     Plugins loaded using the PLUGINS or PLUGIN_BASE receive a reference to
     the current context object as the first argument to the new()
     constructor.  Modules loaded using LOAD_PERL are assumed to not
     conform to the plugin interface.  They must provide a new() class
     method for instantiating objects but it will not receive a reference
     to the context as the first argument.  Plugin modules should provide a
     load() class method (or inherit the default one from the
     Template::Plugin base class) which is called the first time the plugin
     is loaded.  Regular Perl modules need not.  In all other respects,
     regular Perl objects and Template Toolkit plugins are identical.

     If a particular Perl module does not conform to the common, but not
     unilateral, new() constructor convention then a simple plugin wrapper
     can be written to interface to it.

TOLERANT
     The TOLERANT flag is used by the various Template Toolkit provider
     modules (Template::Provider, Template::Plugins, Template::Filters) to
     control their behaviour when errors are encountered.  By default, any
     errors are reported as such, with the request for the particular
     resource (template, plugin, filter) being denied and an exception
     raised.  When the TOLERANT flag is set to any true values, errors will
     be silently ignored and the provider will instead return
     STATUS_DECLINED.  This allows a subsequent provider to take
     responsibility for providing the resource, rather than failing the
     request outright.  If all providers decline to service the request,
     either through tolerated failure or a genuine disinclination to
     comply, then a '<resource> not found' exception is raised.

TEMPLATE TOOLKIT PLUGINS
========================

   The following plugin modules are distributed with the Template Toolkit.

Date
     The Date plugin provides an easy way to generate formatted time and
     date strings by delegating to the POSIX strftime() routine.   See
     Template/Plugin/Date, for further details.

          [% USE date %]
          [% date.format %]		# current time/date

          File last modified: [% date.format(template.modtime) %]

Format
     The Format plugin provides a simple way to format text according to a
     printf()-like format.   See Template/Plugin/Format,
     for further details.

          [% USE bold = format('<b>%s</b>') %]
          [% bold('Hello') %]

URL
     The URL plugin provides a simple way of contructing URLs from a base
     part and a variable set of parameters.  See
     Template/Plugin/URL, for further details.

          [% USE mycgi = url('/cgi-bin/bar.pl', debug=1) %]

          [% mycgi %]
             # ==> /cgi/bin/bar.pl?debug=1

          [% mycgi(mode='submit') %]
             # ==> /cgi/bin/bar.pl?mode=submit&debug=1

Table
     The Table plugin allows you to format a list of data items into a
     virtual table by specifying a fixed number of rows or columns, with
     an optional overlap.  See Template/Plugin/Table,
     for further details.

          [% USE table(list, rows=10, overlap=1) %]

          [% FOREACH item = table.col(3) %]
             [% item %]
          [% END %]

CGI
     The CGI plugin is a wrapper around Lincoln Stein's
     <lstein@genome.wi.mit.edu> CGI.pm module.  The plugin is distributed
     with the Template Toolkit (see Template/Plugin/CGI)
     and the CGI module itself is distributed with
     recent versions Perl, or is available from CPAN.

Datafile
     Provides an interface to data stored in a plain text file in a simple
     delimited format.  The first line in the file specifies field names
     and subsequent lines contain data, delimited by the same non-word
     character as the fields in the first line.  Blank lines and comments
     (lines starting '#' are ignored).   See
     Template/Plugin/Datafile, for further
     details.

     /tmp/mydata:

          # define names for each field
          id : email : name : tel
          # here's the data
          fred : fred@here.com : Fred Smith : 555-1234
          bill : bill@here.com : Bill White : 555-5678

     example:

          [% USE userlist = datafile('/tmp/mydata') %]

          [% FOREACH user = userlist %]
             [% user.name %] ([% user.id %])
          [% END %]

XML::DOM
     The XML::DOM plugin gives access to the XML Document Object Module via
     Clark Cooper <cooper@sch.ge.com> and Enno Derksen's <enno@att.com>
     XML::DOM module.  The plugin is distributed with the Template Toolkit
     (see Template/Plugin/XML/DOM) and
     requires the XML::DOM module, available from CPAN:

          http://www.cpan.org/modules/by-module/XML

XML::RSS
     The XML::RSS plugin is a simple interface to Jonathan Eisenzopf's
     <eisen@pobox.com> XML::RSS module.  An RSS (Rich Site Summary) file
     is typically used to store short news 'headlines' describing
     different links within a site.  This plugin allows you to parse RSS
     files and format the contents accordingly using templates.  The
     plugin is distributed with the Template Toolkit (see
     Template/Plugin/XML/RSS) and requires the
     XML::RSS module, also available from CPAN:

          http://www.cpan.org/modules/by-module/XML

   The following module is distributed separately from the Template
Toolkit.

DBI
     Simon Matthews <sam@knowledgepool.com> has developed a DBI plugin for
     the Template Toolkit which brings the full power of Tim Bunce's
     <Tim.Bunce@ig.co.uk> database interface module (DBI) to your
     templates.  The DBI plugin and the DBI modules themselves are
     available from CPAN at:

          http://www.cpan.org/modules/by-module/Template/
          http://www.cpan.org/modules/by-module/DBI/

BUGS / ISSUES
=============

   * It might be worthwhile being able to distinguish between absolute
     module names and those which should be applied relative to PLUGIN_BASE
     directories.  For example, use 'MyNamespace::MyModule' to denote
     absolute module names (e.g. LOAD_PERL), and 'MyNamespace.MyModule' to
     denote relative to PLUGIN_BASE.

AUTHOR
======

   Andy Wardley <abw@kfs.org>

     http://www.template-toolkit.org/
     http://www.kfs.org/~abw/

REVISION
========

   $Revision: 1.1 $

COPYRIGHT
=========

     Copyright (C) 1996-2000 Andy Wardley.  All Rights Reserved.
     Copyright (C) 1998-2000 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Template|Template' in this node, `Template::Plugin|Template::Plugin'
in this node, L<Template::Context|Template::Context

repository for compiled templates, loaded from disk.
****************************************************

NAME
====

   Template::Provider - repository for compiled templates, loaded from
disk.

SYNOPSIS
========

     $provider = Template::Provider->new(\%options);

     ($template, $error) = $provider->fetch($name);

DESCRIPTION
===========

   The Template::Provider is used to load, parse, compile and cache
template documents.  This object may be sub-classed to provide more
specific facilities for loading, or otherwise providing access to
templates.

   The Template::Context objects maintain a list of Template::Provider
objects which are polled in turn (via fetch()) to return a requested
template.  Each may return a compiled template, raise an error, or decline
to serve the reqest, giving subsequent providers a chance to do so.

   This is the "Chain of Responsiblity" pattern.  See 'Design Patterns' for
further information.

   This documentation needs work.

PUBLIC METHODS
==============

new(\%options)
--------------

   Constructor method which instantiates and returns a new
Template::Provider object.  The optional parameter may be a hash reference
containing any of the following items:

INCLUDE_PATH
     The INCLUDE_PATH is used to specify one or more directories in which
     template files are located.  When a template is requested that isn't
     defined locally as a BLOCK, each of the INCLUDE_PATH directories is
     searched in turn to locate the template file.  Multiple directories
     can be specified as a reference to a list or as a single string where
     each directory is delimited by ':'. The DELIMITER option can be set
     to redefine the delimiter value.

          my $provider = Template::Provider->new({
              INCLUDE_PATH => '/usr/local/templates',
          });

          my $provider = Template::Provider->new({
              INCLUDE_PATH => '/usr/local/templates:/tmp/my/templates',
          });

          my $provider = Template::Provider->new({
              INCLUDE_PATH => [ '/usr/local/templates',
                                '/tmp/my/templates' ],
          });

DELIMITER
     Used to provide an alternative delimiter character sequence for
     separating paths specified in the INCLUDE_PATH.  May be useful for
     operating systems that permit the use of ':' in file names.

          # tolerate Silly Billy's file system conventions
          my $provider = Template::Provider->new({
          	DELIMITER    => ' ',
              INCLUDE_PATH => 'C:/HERE/NOW D:/THERE/THEN',
          });

          # better solution: install Linux!  :-)

ABSOLUTE
     The ABSOLUTE flag is used to indicate if templates specified with
     absolute filenames (e.g. '/foo/bar') should be processed.  It is
     disabled by default and any attempt to load a template by such a name
     will cause a 'file' exception to be raised.

          my $provider = Template::Provider->new({
          	ABSOLUTE => 1,
          });

          # this is why it's disabled by default
          [% INSERT /etc/passwd %]

RELATIVE
     The RELATIVE flag is used to indicate if templates specified with
     filenames relative to the current directory (e.g. './foo/bar' or
     '../../some/where/else') should be loaded.  It is also disabled by
     default, and will raise a 'file' error if such template names are
     encountered.

          my $provider = Template::Provider->new({
          	RELATIVE => 1,
          });

          [% INCLUDE ../logs/error.log %]

DEFAULT
     The DEFAULT option can be used to specify a default template which
     should be used whenever a specified template can't be found in the
     INCLUDE_PATH.

          my $provider = Template::Provider->new({
          	DEFAULT => 'notfound.html',
          });

     If a non-existant template is requested through the Template process()
     method, or by an INCLUDE, PROCESS or WRAPPER directive, then the
     DEFAULT template will instead be processed, if defined.  Note that the
     DEFAULT template is not used when templates are specified with
     absolute or relative filenames, or as a reference to a input file
     handle or text string.

CACHE_SIZE
     The Template::Provider module caches compiled templates to avoid the
     need to re-parse template files or blocks each time they are used.
     The CACHE_SIZE option is used to limit the number of compiled
     templates that the module should cache.

     By default, the CACHE_SIZE is undefined and all compiled templates are
     cached.  When set to any positive value, the cache will be limited to
     storing that many compiled templates.  When a new template is loaded
     and compiled and the cache is full (i.e. the number of entries ==
     CACHE_SIZE), the least recently used compiled template is discarded
     to make room for the new one.

     The CACHE_SIZE can be set to 0 to disable caching altogether.

          my $provider = Template::Provider->new({
          	CACHE_SIZE => 64,   # only cache 64 compiled templates
          });

          my $provider = Template::Provider->new({
          	CACHE_SIZE => 0,   # don't cache any compiled templates
          });

COMPILE_EXT
     From version 2 onwards, the Template Toolkit has the ability to
     compile templates to Perl code and save them to disk for subsequent
     use (e.g. cache persistance).  The COMPILE_EXT option may be provided
     to specify a filename extension for compiled template files.  It is
     undefined by default and no attempt will be made to read or write any
     compiled template file.

          my $provider = Template::Provider->new({
          	COMPILE_EXT => '.ttc',
          });

     If COMPILE_EXT is defined (and COMPILE_DIR isn't, see below) then
     compiled template files with the COMPILE_EXT extension will be
     written to the same directory from which the source template files
     were loaded.

     Compiling and subsequent reuse of templates happens automatically
     whenever the COMPILE_EXT or COMPILE_DIR options are set.  The Template
     Toolkit will automatically reload and reuse compiled files when it
     finds them on disk.  If the corresponding source file has been
     modified since the compiled version as written, then it will load and
     re-compile the source and write a new compiled version to disk.

     This form of cache persistance offers significant benefits in terms of
     time and resources required to reload templates.  Compiled templates
     can be reloaded by a simple call to Perl's require(), leaving Perl to
     handle all the parsing and compilation.  This is a Good Thing.

COMPILE_DIR
     The COMPILE_DIR option is used to specify an alternate directory root
     under which compiled template files should be saved.

          my $provider = Template::Provider->new({
          	COMPILE_DIR => '/tmp/ttc',
          });

     The COMPILE_EXT option may also be specified to have a consistent file
     extension added to these files.

          my $provider1 = Template::Provider->new({
          	COMPILE_DIR => '/tmp/ttc',
          	COMPILE_EXT => '.ttc1',
          });

          my $provider2 = Template::Provider->new({
          	COMPILE_DIR => '/tmp/ttc',
          	COMPILE_EXT => '.ttc2',
          });

     When COMPILE_EXT is undefined, the compiled template files have the
     same name as the original template files, but reside in a different
     directory tree.

     Each directory in the INCLUDE_PATH is replicated in full beneath the
     COMPILE_DIR directory.  This example:

          my $provider = Template::Provider->new({
          	COMPILE_DIR  => '/tmp/ttc',
          	INCLUDE_PATH => '/home/abw/templates:/usr/share/templates',
          });

     would create the following directory structure:

          /tmp/ttc/home/abw/templates/
          /tmp/ttc/usr/share/templates/

     Files loaded from different INCLUDE_PATH directories will have their
     compiled forms save in the relevant COMPILE_DIR directory.

TOLERANT
     The TOLERANT flag is used by the various Template Toolkit provider
     modules (Template::Provider, Template::Plugins, Template::Filters) to
     control their behaviour when errors are encountered.  By default, any
     errors are reported as such, with the request for the particular
     resource (template, plugin, filter) being denied and an exception
     raised.  When the TOLERANT flag is set to any true values, errors will
     be silently ignored and the provider will instead return
     STATUS_DECLINED.  This allows a subsequent provider to take
     responsibility for providing the resource, rather than failing the
     request outright.  If all providers decline to service the request,
     either through tolerated failure or a genuine disinclination to
     comply, then a '<resource> not found' exception is raised.

PARSER
     The Template::Parser module implements a parser object for compiling
     templates into Perl code which can then be executed.  A default object
     of this class is created automatically and then used by the
     Template::Provider whenever a template is loaded and requires
     compilation.  The PARSER option can be used to provide a reference to
     an alternate parser object.

          my $provider = Template::Provider->new({
          	PARSER => MyOrg::Template::Parser->new({ ... }),
          });

fetch($name)
------------

   Returns a compiled template for the name specified.  If the template
cannot be found then (undef, STATUS_DECLINED) is returned.  If an error
occurs (e.g. read error, parse error) then ($error, STATUS_ERROR) is
returned, where $error is the error message generated.  If the TOLERANT
flag is set the the method returns (undef, STATUS_DECLINED) instead of
returning an error.

store($name, $template)
-----------------------

   Stores the compiled template, $template, in the cache under the name,
$name.  Susbequent calls to fetch($name) will return this template in
preference to any disk-based file.

include_path(\@newpath))
------------------------

   Accessor method for the INCLUDE_PATH setting.  If called with an
argument, this method will replace the existing INCLUDE_PATH with the new
value.

AUTHOR
======

   Andy Wardley <abw@kfs.org>

     http://www.template-toolkit.org/
     http://www.kfs.org/~abw/

REVISION
========

   $Revision: 1.1 $

COPYRIGHT
=========

     Copyright (C) 1996-2000 Andy Wardley.  All Rights Reserved.
     Copyright (C) 1998-2000 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   L<Template|Template

custom template processing service
**********************************

NAME
====

   Template::Service - custom template processing service

SYNOPSIS
========

     use Template::Service;

     my $service = Template::Service->new({
     	PRE_PROCESS  => [ 'config', 'header' ],
     	POST_PROCESS => 'footer',
     	ERROR        => {
     	    user     => 'user/index.html',
     	    dbi      => 'error/database',
     	    default  => 'error/default',
     	},
     });

     my $output = $service->process($template_name, \%replace)
     	|| die $service->error(), "\n";

DESCRIPTION
===========

   The Template::Service module implements an object class for providing a
consistent template processing service.

   Standard header (PRE_PROCESS) and footer (POST_PROCESS) templates may
be specified which are prepended and appended to all templates processed
by the service (but not any other templates or blocks INCLUDEd or
PROCESSed from within).  An ERROR hash may be specified which redirects
the service to an alternate template file in the case of uncaught
exceptions being thrown.  This allows errors to be automatically handled
by the service and a guaranteed valid response to be generated regardless
of any processing problems encountered.

   A default Template::Service object is created by the Template module.
Any Template::Service options may be passed to the Template new()
constructor method and will be forwarded to the Template::Service
constructor.

     use Template;

     my $template = Template->new({
     	PRE_PROCESS  => 'header',
     	POST_PROCESS => 'footer',
     });

   Similarly, the Template::Service constructor will forward all
configuration parameters onto other default objects (e.g.
Template::Context) that it may need to instantiate.

   A Template::Service object (or subclass/derivative) can be explicitly
instantiated and passed to the Template new() constructor method as the
SERVICE item.

     use Template;
     use Template::Service;

     my $service = Template::Service->new({
     	PRE_PROCESS  => 'header',
     	POST_PROCESS => 'footer',
     });

     my $template = Template->new({
     	SERVICE => $service,
     });

   The Template::Service module can be sub-classed to create custom service
handlers.

     use Template;
     use MyOrg::Template::Service;

     my $service = MyOrg::Template::Service->new({
     	PRE_PROCESS  => 'header',
     	POST_PROCESS => 'footer',
     	COOL_OPTION  => 'enabled in spades',
     });

     my $template = Template->new({
     	SERVICE => $service,
     });

   The Template module uses the Template::Config service() factory method
to create a default service object when required.  The
$Template::Config::SERVICE package variable may be set to specify an
alternate service module.  This will be loaded automatically and its new()
constructor method called by the service() factory method when a default
service object is required.  Thus the previous example could be written as:

     use Template;

     $Template::Config::SERVICE = 'MyOrg::Template::Service';

     my $template = Template->new({
     	PRE_PROCESS  => 'header',
     	POST_PROCESS => 'footer',
     	COOL_OPTION  => 'enabled in spades',
     });

METHODS
=======

new(\%config)
-------------

   The new() constructor method is called to instantiate a
Template::Service object.  Configuration parameters may be specified as a
HASH reference or as a list of (name => value) pairs.

     my $service1 = Template::Service->new({
     	PRE_PROCESS  => 'header',
     	POST_PROCESS => 'footer',
     });

     my $service2 = Template::Service->new( ERROR => 'error.html' );

   The new() method returns a Template::Service object (or sub-class) or
undef on error.  In the latter case, a relevant error message can be
retrieved by the error() class method or directly from the
$Template::Service::ERROR package variable.

     my $service = Template::Service->new(\%config)
     	|| die Template::Service->error();

     my $service = Template::Service->new(\%config)
     	|| die $Template::Service::ERROR;

   The following configuration items may be specified:

PRE_PROCESS, POST_PROCESS
     These values may be set to contain the name(s) of template files
     (relative to INCLUDE_PATH) which should be processed immediately
     before and/or after each template.  These do not get added to
     templates processed into a document via directives such as INCLUDE,
     PROCESS, WRAPPER etc.

          my $service = Template::Service->new({
          	PRE_PROCESS  => 'header',
          	POST_PROCESS => 'footer',
          };

     Multiple templates may be specified as a reference to a list.  Each is
     processed in the order defined.

          my $service = Template::Service->new({
          	PRE_PROCESS  => [ 'config', 'header' ],
          	POST_PROCESS => 'footer',
          };

     The PRE_PROCESS and POST_PROCESS templates are evaluated in the same
     variable context as the main document and may define or update
     variables for subseqent use.

     config:     [% # set some site-wide variables        bgcolor =
     '#ffffff'        version = 2.718     %]

     header:     [% DEFAULT title = 'My Funky Web Site' %]     <html>
     <head>     <title>[% title %]</title>     </head>     <body
     bgcolor="[% bgcolor %]">

     footer:     <hr>     Version [% version %]     </body>     </html>

     The Template::Document object representing the main template being
     processed is available within PRE_PROCESS and POST_PROCESS templates
     as the 'template' variable.  Metadata items defined via the META
     directive may be accessed accordingly.

          $service->process('mydoc.html', $vars);

     mydoc.html:     [% META title = 'My Document Title' %]     blah blah
     blah     ...

     header:     <html>     <head>     <title>[% template.title
     %]</title></head>     <body bgcolor="[% bgcolor %]">

PROCESS
     The PROCESS option may be set to contain the name(s) of template files
     (relative to INCLUDE_PATH) which should be processed instead of the
     main template passed to the Template::Service process() method.  This
     can be used to apply consistent wrappers around all templates,
     similar to the use of PRE_PROCESS and POST_PROCESS templates.

          my $service = Template::Service->new({
          	PROCESS  => 'content',
          };

          # processes 'content' instead of 'foo.html'
          $service->process('foo.html');

     A reference to the original template is available in the 'template'
     variable.  Metadata items can be inspected and the template can be
     processed by specifying it as a variable reference (i.e. prefixed by
     '$') to an INCLUDE, PROCESS or WRAPPER directive.

     content:     <html>     <head>     <title>[% template.title %]</title>
        </head>

     <body>     [% PROCESS $template %]     <hr>     &copy; Copyright [%
     template.copyright %]     </body>     </html>

     foo.html:     [% META        title     = 'The Foo Page'        author
       = 'Fred Foo'        copyright = '2000 Fred Foo'     %]     <h1>[%
     template.title %]</h1>     Welcome to the Foo Page, blah blah blah

     output:

ERROR
     The ERROR (or ERRORS if you prefer) configuration item can be used to
     name a single template or specify a hash array mapping exception types
     to template names, to be used for error handling.  If an uncaught
     exception is raised from within a template then the appropriate error
     template will instead be processed.

     If specified as a single value then that template will be processed
     for all uncaught exceptions.

          my $service = Template::Service->new({
          	ERROR => 'error.html'
          });

     If the ERROR item is a hash reference the keys are assumed to be
     exception types and the relevant template for a given exception will
     be selected.  A 'default' template may be provided for the general
     case.  Note that 'ERROR' can be pluralised to 'ERRORS' if you find it
     more appropriate in this case.

          my $service = Template::Service->new({
          	ERRORS => {
          	    user     => 'user/index.html',
          	    dbi      => 'error/database',
          	    default  => 'error/default',
          	},
          });

     In this example, any 'user' exceptions thrown will cause the
     'user/index.html' template to be processed, 'dbi' errors are handled
     by 'error/database' and all others by the 'error/default' template.
     Any PRE_PROCESS and/or POST_PROCESS templates will also be applied to
     these error templates.

     Note that exception types are hierarchical and a 'foo' handler will
     catch all 'foo.*' errors (e.g. foo.bar, foo.bar.baz) if a more
     specific handler isn't defined.  Be sure to quote any exception types
     that contain periods to prevent Perl concatenating them into a single
     string (i.e. `user.passwd' is parsed as 'user'.'passwd').

          my $service = Template::Service->new({
          	ERROR => {
          	    'user.login'  => 'user/login.html',
          	    'user.passwd' => 'user/badpasswd.html',
          	    'user'        => 'user/index.html',
          	    'default'     => 'error/default',
          	},
          });

     In this example, any template processed by the $service object, or
     other templates or code called from within, can raise a 'user.login'
     exception and have the service redirect to the 'user/login.html'
     template.  Similarly, a 'user.passwd' exception has a specific
     handling template, 'user/badpasswd.html', while all other 'user' or
     'user.*' exceptions cause a redirection to the 'user/index.html' page.
     All other exception types are handled by 'error/default'.

     Exceptions can be raised in a template using the THROW directive,

          [% THROW user.login 'no user id: please login' %]

     or by calling the throw() method on the current Template::Context
     object,

          $context->throw('user.passwd', 'Incorrect Password');
          $context->throw('Incorrect Password');    # type 'undef'

     or from Perl code by calling die() with a Template::Exception object,

          die Template::Exception->new('user.denied', 'Invalid User ID');

     or by simply calling die() with an error string.  This is
     automagically caught and converted to an  exception of 'undef' type
     which can then be handled in the usual way.

          die "I'm sorry Dave, I can't do that";

AUTO_RESET
     The AUTO_RESET option is set by default and causes the local BLOCKS
     cache for the Template::Context object to be reset on each call to the
     Template process() method.  This ensures that any BLOCKs defined
     within a template will only persist until that template is finished
     processing.  This prevents BLOCKs defined in one processing request
     from interfering with other independant requests subsequently
     processed by the same context object.

     The BLOCKS item may be used to specify a default set of block
     definitions for the Template::Context object.  Subsequent BLOCK
     definitions in templates will over-ride these but they will be
     reinstated on each reset if AUTO_RESET is enabled (default), or if
     the Template::Context reset() method is called.

process($input, \%replace)
--------------------------

   The process() method is called to process a template specified as the
first parameter, $input.  This may be a file name, file handle (e.g. GLOB
or IO::Handle) or a reference to a text string containing the template
text.  An additional hash reference may be passed containing template
variable definitions.

   The method processes the template, adding any PRE_PROCESS or
POST_PROCESS templates defined, and returns the output text.  An uncaught
exception thrown by the template will be handled by a relevant ERROR
handler if defined.  Errors that occur in the PRE_PROCESS or POST_PROCESS
templates, or those that occur in the main input template and aren't
handled, cause the method to return undef to indicate failure.  The
appropriate error message can be retrieved via the error() method.

     $service->process('myfile.html', { title => 'My Test File' })
     	|| die $service->error();

context()
---------

   Returns a reference to the internal context object which is, by
default, an instance of the Template::Context class.

error()
-------

   Returns the most recent error message.

AUTHOR
======

   Andy Wardley <abw@kfs.org>

     http://www.template-toolkit.org/
     http://www.kfs.org/~abw/

REVISION
========

   $Revision: 1.2 $

COPYRIGHT
=========

     Copyright (C) 1996-2000 Andy Wardley.  All Rights Reserved.
     Copyright (C) 1998-2000 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   L<Template|Template

magical storage for template variables
**************************************

NAME
====

   Template::Stash - magical storage for template variables

SYNOPSIS
========

     use Template::Stash;

     my $stash = Template::Stash->new(\%vars);

     # get variable values
     $value = $stash->get($variable);
     $value = $stash->get(\@compound);

     # set variable value
     $stash->set($variable, $value);
     $stash->set(\@compound, $value);

     # default variable value
     $stash->set($variable, $value, 1);
     $stash->set(\@compound, $value, 1);

     # set variable values en masse
     $stash->update(\%new_vars)

     # methods for (de-)localising variables
     $stash = $stash->clone(\%new_vars);
     $stash = $stash->declone();

DESCRIPTION
===========

   The Template::Stash module defines an object class which is used to
store variable values for the runtime use of the template processor.
Variable values are stored internally in a hash reference (which itself is
blessed to create the object) and are accessible via the get() and set()
methods.

   Variables may reference hash arrays, lists, subroutines and objects as
well as simple values.  The stash automatically performs the right magic
when dealing with variables, calling code or object methods, indexing into
lists, hashes, etc.

   The stash has clone() and declone() methods which are used by the
template processor to make temporary copies of the stash for localising
changes made to variables.

PUBLIC METHODS
==============

new(\%params)
-------------

   The new() constructor method creates and returns a reference to a new
Template::Stash object.

     my $stash = Template::Stash->new();

   A hash reference may be passed to provide variables and values which
should be used to initialise the stash.

     my $stash = Template::Stash->new({ var1 => 'value1',
     				       var2 => 'value2' });

get($variable)
--------------

   The get() method retrieves the variable named by the first parameter.

     $value = $stash->get('var1');

   Dotted compound variables can be retrieved by specifying the variable
elements by reference to a list.  Each node in the variable occupies two
entries in the list.  The first gives the name of the variable element,
the second is a reference to a list of arguments for that element, or 0 if
none.

     [% foo.bar(10).baz(20) %]

     $stash->get([ 'foo', 0, 'bar', [ 10 ], 'baz', [ 20 ]);

set($variable, $value, $default)
--------------------------------

   The set() method sets the variable name in the first parameter to the
value specified in the second.

     $stash->set('var1', 'value1');

   Dotted compound variables may be specified as per get() above.

     [% foo.bar = 30 %]

     $stash->set([ 'foo', 0, 'bar', 0 ], 30);

   The magical variable 'IMPORT' can be specified whose corresponding
value should be a hash reference.  The contents of the hash array are
copied (i.e. imported) into the current namespace.

     # foo.bar = baz, foo.wiz = waz
     $stash->set('foo', { 'bar' => 'baz', 'wiz' => 'waz' });

     # import 'foo' into main namespace: foo = baz, wiz = waz
     $stash->set('IMPORT', $stash->get('foo'));

clone(\%params)
---------------

   The clone() method creates and returns a new Template::Stash object
which represents a localised copy of the parent stash.  Variables can be
freely updated in the cloned stash and when declone() is called, the
original stash is returned with all its members intact and in the same
state as they were before clone() was called.

   For convenience, a hash of parameters may be passed into clone() which
is used to update any simple variable (i.e. those that don't contain any
namespace elements like 'foo' and 'bar' but not 'foo.bar') variables while
cloning the stash.  For adding and updating complex variables, the set()
method should be used after calling clone().  This will correctly resolve
and/or create any necessary namespace hashes.

   A cloned stash maintains a reference to the stash that it was copied
from in its '_PARENT' member.

declone()
---------

   The declone() method returns the '_PARENT' reference and can be used to
restore the state of a stash as described above.

AUTHOR
======

   Andy Wardley <abw@kfs.org>

     http://www.template-toolkit.org/
     http://www.kfs.org/~abw/

REVISION
========

   $Revision: 1.1 $

COPYRIGHT
=========

     Copyright (C) 1996-2000 Andy Wardley.  All Rights Reserved.
     Copyright (C) 1998-2000 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Template|Template' in this node, L<Template::Context|Template::Context

module for automating test scripts for the Template Toolkit
***********************************************************

NAME
====

   Template::Test - module for automating test scripts for the Template
Toolkit

SYNOPSIS
========

     use Template::Test;

     $Template::Test::DEBUG = 0;   # set this true to see each test running
     $Template::Test::EXTRA = 2;   # 2 extra tests follow test_expect()...

     # ok() can be called any number of times before test_expect
     ok( $true_or_false )

     # test_expect() splits $input into individual tests, processes each
     # and compares generated output against expected output
     test_expect($input, $template, \%replace );

     # $input is text or filehandle (e.g. DATA section after __END__)
     test_expect( $text );
     test_expect( \*DATA );

     # $template is a Template object or configuration hash
     my $template_cfg = { ... };
     test_expect( $input, $template_cfg );
     my $template_obj = Template->new($template_cfg);
     test_expect( $input, $template_obj );

     # $replace is a hash reference of template variables
     my $replace = {
     	a => 'alpha',
     	b => 'bravo'
     };
     test_expect( $input, $template, $replace );

     # ok() called after test_expect should be declared in $EXTRA (2)
     ok( $true_or_false )
     ok( $true_or_false )

DESCRIPTION
===========

   The Template::Test module defines the test_expect() and other related
subroutines which can be used to automate test scripts for the Template
Toolkit.  See the numerous tests in the 't' sub-directory of the
distribution for examples of use.

   The test_expect() subroutine splits an input document into a number of
separate tests, processes each one using the Template Toolkit and then
compares the generated output against an expected output, also specified
in the input document.  It generates the familiar "ok/not ok" output
compatible with Test::Harness.

   The test input should be specified as a text string or a reference to a
filehandle (e.g. GLOB or IO::Handle) from which it can be read.  In
particular, this allows the test input to be placed after the __END__
marker and read via the DATA filehandle.

     use Template::Test;

     test_expect(\*DATA);

     __END__
     # this is the first test (this is a comment)
     -- test --
     blah blah blah [% foo %]
     -- expect --
     blah blah blah value_of_foo

     # here's the second test (no surprise, so is this)
     -- test --
     more blah blah [% bar %]
     -- expect --
     more blah blah value_of_bar

   Blank lines between test sections are generally ignored.  Any line
starting with '#' is treated as a comment and is ignored.

   The second and third parameters to test_expect() are optional.  The
second may be either a reference to a Template object which should be used
to process the template fragments, or a reference to a hash array
containing configuration values which should be used to instantiate a new
Template object.

     # pass reference to config hash
     my $config = {
     	INCLUDE_PATH => '/here/there:/every/where',
     	POST_CHOMP   => 1,
     };
     test_expect(\*DATA, $config);

     # or create Template object explicitly
     my $template = Template->new($config);
     test_expect(\*DATA, $template);

   The third parameter may be used to reference a hash array of template
variable which should be defined when processing the tests.  This is
passed to the Template process() method.

     my $replace = {
     	a => 'alpha',
     	b => 'bravo',
     };

     test_expect(\*DATA, $config, $replace);

   The second parameter may be left undefined to specify a default Template
configuration.

     test_expect(\*DATA, undef, $replace);

   For testing the output of different Template configurations, a
reference to a list of named Template objects also may be passed as the
second parameter.

     my $tt1 = Template->new({ ... });
     my $tt2 = Template->new({ ... });
     my @tts = [ one => $tt1, two => $tt1 ];

     The first object in the list is used by default.  Other objects may be
     switched in with the '-- use $name --' marker.  This should immediately
     follow a '-- test --' line.  That object will then be used for the rest
     of the test, or until a different object is selected.

     -- test --
     -- use one --
     [% blah %]
     -- expect --
     blah, blah

     -- test --
     still using one...
     -- expect --
     ...

     -- test --
     -- use two --
     [% blah %]
     -- expect --
     blah, blah, more blah

   The test_expect() sub counts the number of tests, and then calls
ntests() to generate the familiar "1..$ntests\n" test harness line.  Each
test defined generates two test numbers.  The first indicates that the
input was processed without error, and the second that the output matches
that expected.

   Additional test may be run before test_expect() by calling ok().  These
test results are cached until ntests() is called and the final number of
tests can be calculated.  Then, the "1..$ntests" line is output, along
with "ok $n" / "not ok $n" lines for each of the cached test result.
Subsequent calls to ok() then generate an output line immediately.

     my $something = SomeObject->new();
     ok( $something );

     my $other = AnotherThing->new();
     ok( $other );

     test_expect(\*DATA);

   If any tests are to follow after test_expect() is called then these
should be pre-declared by setting the $EXTRA package variable.  This value
(default: 0) is added to the grand total calculated by ntests().  The
results of the additional tests are also registered by calling ok().

     $Template::Test::EXTRA = 2;

     # can call ok() any number of times before test_expect()
     ok( $did_that_work );
     ok( $make_sure );
     ok( $dead_certain );

     # <some> number of tests...
     test_expect(\*DATA, $config, $replace);

     # here's those $EXTRA tests
     ok( defined $some_result && ref $some_result eq 'ARRAY' );
     ok( $some_result->[0] eq 'some expected value' );

   If you don't want to call test_expect() at all then you can call
ntests($n) to declare the number of tests and generate the test header
line.  After that, simply call ok() for each test passing a true or false
values to indicate that the test passed or failed.

     ntests(2);
     ok(1);
     ok(0);

   If you're really lazy, you can just call ok() and not bother declaring
the number of tests at all.  All tests results will be cached until the
end of the script and then printed in one go before the program exits.

     ok( $x );
     ok( $y );

   You can identify only a specific part of the input file for testing
using the '- start -' and '- stop -' markers.  Anything before the first
'- start -' is ignored, along with anything after the next '- stop -'
marker.

     -- test --
     this is test 1 (not performed)
     -- expect --
     this is test 1 (not performed)

     -- start --

     -- test --
     this is test 2
     -- expect --
     this is test 2

     -- stop --

     ...

   For historical reasons and general utility, the module also defines a
'callsign' subroutine which returns a hash mapping a..z to their phonetic
alphabet equivalent (e.g. radio callsigns).  This is used by many of the
test scripts as a "known source" of variable values.

     test_expect(\*DATA, $config, callsign());

   A banner() subroutine is also provided which prints a simple banner
including any text passed as parameters, if $DEBUG is set.

     banner('Testing something-or-other');

   example output:

     #------------------------------------------------------------
     # Testing something-or-other (27 tests completed)
     #------------------------------------------------------------

   The $DEBUG package variable can be set to enable debugging mode.

   The $PRESERVE package variable can be set to stop the test_expect()
from converting newlines in the output and expected output into the
literal strings '\n'.

HISTORY
=======

   This module started its butt-ugly life as the t/texpect.pl script.  It
was cleaned up to became the Template::Test module some time around
version 0.29.  It underwent further cosmetic surgery for version 2.00 but
still retains some rear-end resemblances.

BUGS / KNOWN "FEATURES"
=======================

   Imports all methods by default.  This is generally a Bad Thing, but
this module is only used in test scripts (i.e. at build time) so a) we
don't really care and b) it saves typing.

   The line splitter may be a bit dumb, especially if it sees lines like -
this - that aren't supposed to be special markers.  So don't do that.

AUTHOR
======

   Andy Wardley <abw@kfs.org>

     http://www.template-toolkit.org/
     http://www.kfs.org/~abw/

REVISION
========

   $Revision: 1.1 $

COPYRIGHT
=========

     Copyright (C) 1996-2000 Andy Wardley.  All Rights Reserved.
     Copyright (C) 1998-2000 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   L<Template|Template

a tutorial on using and abusing the Perl Template Toolkit
*********************************************************

NAME
====

   Template Tutorial - a tutorial on using and abusing the Perl Template
Toolkit

DESCRIPTION
===========

   This tutorial document provides a introduction to the Template Toolkit
and demonstrates some of the typical ways it may be used.  It covers the
generation of static pages from templates using the `tpage' and `ttree'
scripts and then goes on to show dynamic content generation using CGI
scripts and Apache/mod_perl handlers.

   Various features of the Template Toolkit are introduced and described
briefly and explained by use of example.  For a complete reference and
guide to the template directives, features and options, consult the
Template documentation.  e.g.

     perldoc Template

INTRODUCTION
============

   The Template Toolkit is a set of Perl modules which collectively
implement a template processing system.  In this context, a template is a
text document containing special markup tags called 'directives'.  A
directive is an instruction for the template processor to perform some
action and substitute the result into the document in place of the
original directive.  Directives include those to define or insert a
variable value, iterate through a list of values (FOREACH), declare a
conditional block (IF/UNLESS/ELSE), include and process another template
file (INCLUDE) and so on.

   In all other respects, the document is a plain text file and may
contain any other content (e.g. HTML, XML, RTF, LaTeX, etc).  Directives
are inserted in the document within the special markup tags which are '[%'
and '%]' by default, but can be changed via the module configuration
options.  Here's an example of an HTML document with additional Template
Toolkit directives.

     [% INCLUDE header
        title = 'This is an HTML example'
     %]

     <h1>Some Interesting Links</h1>

     [% webpages = [
           { url => 'http://foo.org', title => 'The Foo Organsiation' }
           { url => 'http://bar.org', title => 'The Bar Organsiation' }
        ]
     %]

     Links:
     <ul>
     [% FOREACH link = webpages %]
        <li><a href="[% link.url %]">[% link.title %]</a>
     [% END %]
     </ul>

     [% INCLUDE footer %]

   This example shows how the INCLUDE directive is used to load and process
separate 'header' and 'footer' template files, including the output in the
current document.  These files might look like this:

   header:     <html>     <head>     <title>[% title %]</title>     </head>

   <body bgcolor="#ffffff">

   footer:     <hr>

     <center>
     &copy; Copyright 2000 Me, Myself, I
     </center>

     </body>
     </html>

   The example also uses the FOREACH directive to iterate through the
'webpages' list to build a table of links.  In this example, we have
defined this list within the template to contain a number of hash
references, each containing a 'url' and 'title' member.  The FOREACH
directive iterates through the list, aliasing 'link' to each item (hash
ref).  The *[% link.url %]* and *[% link.title %]* directives then access
the individual values in the hash and insert them into the document.

   The following sections show other ways in which data can be defined for
use in a template.

GENERATING STATIC PAGES
=======================

   Having created a template file we can now process it to generate some
real output.  The quickest and easiest way to do this is to use the
`tpage' script.  This is provided as part of the Template Toolkit and
should be installed in your usual Perl bin directory.

   Assuming you saved your template file as 'mypage.html', you would run
the command:

     tpage mypage.html

   This will process the template file, sending the output to STDOUT (i.e.
whizzing past you on the screen).  You may want to redirect the output to
a file but be careful not to specify the same name as the template file,
or you'll overwrite it.  You may want to use one prefix for your templates
such as '.atml' (for 'Another Template Markup Language', perhaps?) and the
regular '.html' for the output files (assuming you're creating HTML, that
is).  Alternatively, you might redirect the output to another directory.
e.g.

     tpage mypage.atml > mypage.html
     tpage templates/mypage.html > html/mypage.html

   The *tpage* script is very basic and only really intended to give you
an easy way to process a template without having to write any Perl code.
A much more flexible tool is *ttree*, described below, but for now let's
look at the output generated by processing the above example (some
whitespace removed for brevity):

     <html>
     <head>
     <title>This is an HTML example</title>
     </head>

     <body bgcolor="#ffffff">

     <h1>Some Interesting Links</h1>

     Links:
     <ul>
        <li><a href="http://foo.org">The Foo Organsiation</a>
        <li><a href="http://bar.org">The Bar Organsiation</a>
     </ul>

     <hr>

     <center>
     &copy; Copyright 2000 Me, Myself, I
     </center>

     </body>
     </html>

   The header and footer template files have been included (assuming you
created them and they're in the current directory) and the link data has
been built into an HTML list.

   The `ttree' script, also distributed as part of the Template Toolkit,
provides a more flexible way to process template documents.  The first
time you run the script, it will ask you if it should create a
configuration file, usually called '.ttreerc' in your home directory.
Answer 'y' to have it create the file.

   The `ttree' documentation describes how you can change the location of
this file and also explains the syntax and meaning of the various options
in the file.  Comments are written to the sample configuration file which
should also help.

     perldoc ttree
     ttree -h

   In brief, the configuration file describes the directories in which
template files are to be found (src), where the corresponding output
should be written to (dest), and any other directories (lib) that may
contain template files that you plan to INCLUDE into your source
documents.  You can also specify processing options (such as 'verbose' and
'recurse') and provide regular expression to match files that you don't
want to process (ignore, accept) or should be copied instead of processed
(copy).

   An example `.ttreerc' file is shown here:

   $HOME/.ttreerc:     verbose     recurse

     # this is where I keep other ttree config files
     cfg = ~/.ttree

     src  = ~/websrc/src
     lib  = ~/websrc/lib
     dest = ~/public_html/test

     ignore = \b(CVS|RCS)\b
     ignore = ^#

   You can create many different configuration files and store them in the
directory specified in the 'cfg' option, shown above.  You then add the
`-f filename' option to `ttree' to have it read that file.

   When you run the script, it compares all the files in the 'src'
directory (including those in sub-directories if the 'recurse' option is
set), with those in the 'dest' directory.  If the destination file doesn't
exist or has an earlier modification time than the corresponding source
file, then the source will be processed with the output written to the
destination file.  The -a option forces all files to be processed,
regardless of modification times.

   The script *doesn't* process any of the files in the 'lib' directory,
but it does add it to the INCLUDE_PATH for the template processor so that
it can locate these files via an INCLUDE or PROCESS directive.  Thus, the
'lib' directory is an excellent place to keep template elements such as
header, footers, etc., that aren't complete documents in their own right.

   You can also specify various Template Toolkit options from the
configuration file.  Consult the *ttree* documentation and help summary
(`ttree -h') for full details.  e.g.

   $HOME/.ttreerc:     pre_process = config     interpolate     post_chomp

   The 'pre_process' option allows you to specify a template file which
should be processed before each file.  Unsurprisingly, there's also a
'post_process' option to add a template after each file.  In the fragment
above, we have specified that the 'config' template should be used as a
prefix template.  We can create this file in the 'lib' directory and use
it to define some common variables, including those web page links we
defined earlier and might want to re-use in other templates.  We could
also include an HTML header, title, or menu bar in this file which would
then be prepended to each and every template file, but for now we'll keep
all that in a separate 'header' file.

   $lib/config:     [% root     = '~/abw'        home     =
"$root/index.html"        images   = "$root/images"        email    =
'abw@kfs.org'        graphics = 1        webpages = [          { url =>
'http://foo.org', title => 'The Foo Organsiation' }          { url =>
'http://bar.org', title => 'The Bar Organsiation' }        ]     %]

   Assuming you've created or copied the 'header' and 'footer' files from
the earlier example into your 'lib' directory, you can now start to create
web pages like the following in your 'src' directory and process them with
`ttree'.

   $src/newpage.html:     [% INCLUDE header        title = 'Another
Template Toolkit Test Page'     %]

     <a href="[% home %]">Home</a>
     <a href="mailto:[% email %]">Email</a>

     [% IF graphics %]
     <img src="[% images %]/logo.gif" align=right width=60 height=40>
     [% END %]

     [% INCLUDE footer %]

   Here we've shown how pre-defined variables can be used as flags to
enable certain feature (e.g. 'graphics') and to specify common items such
as an email address and URL's for the home page, images directory and so
on.  This approach allows you to define these values once so that they're
consistent across all pages and can easily be changed to new values.

   When you run *ttree*, you should see output similar to the following
(assuming you have the verbose flag set).

     ttree 1.14 (Template Toolkit version 1.02a)

     Source: /home/abw/websrc/src
        Destination: /home/abw/public_html/test
       Include Path: [ /home/abw/websrc/lib ]
     Ignore: [ \b(CVS|RCS)\b, ^# ]
       Copy: [  ]
     Accept: [ * ]

     + newpage.html

   The '+' before 'newpage.html' shows that the file was processed, with
the output being written to the destination directory.  If you run the
same command again, you'll see the following line displayed instead
showing a '-' and giving a reason why the file wasn't processed.

     - newpage.html                     (not modified)

   It has detected a 'newpage.html' in the destination directory which is
more recent than that in the source directory and so hasn't bothered to
waste time re-processing it.  To force all files to be processed, use the
-a option.  You can also specify one or more filenames as command line
arguments to `ttree':

     tpage newpage.html

   This is what the destination page looks like.

   $dest/newpage.html:     <html>     <head>     <title>Another Template
Toolkit Test Page</title>     </head>

   <body bgcolor="#ffffff">

   <a href="~/abw/index.html">Home</a>     <a
href="mailto:abw@kfs.org">Email me</a>

     <img src="~/abw/images/logo.gif" align=right width=60 height=40>

     <hr>

     <center>
     &copy; Copyright 2000 Me, Myself, I
     </center>

     </body>
     </html>

   You can add as many documents as you like to the 'src' directory and
`ttree' will apply the same process to them all.  In this way, it is
possible to build an entire tree of static content for a web site with a
single command.  The added benefit is that you can be assured of
consistency in links, header style, or whatever else you choose to
implement in terms of common templates elements or variables.

DYNAMIC CONTENT GENERATION VIA CGI SCRIPT
=========================================

   The Template modules provides a simple front-end to the Template
Toolkit for use in CGI scripts and Apache/mod_perl handlers.  Simply 'use'
the Template module, create an object instance with the new() method and
then call the process() method on the object, passing the name of the
template file as a parameter.  The second parameter passed is a reference
to a hash array of variables that we want made available to the template:

     #!/usr/bin/perl -w

     use strict;
     use Template;

     my $file = 'src/greeting.html';
     my $vars = {
        message  => "Hello World\n"
     };

     my $template->new();

     $template->process($file, $vars)
     	|| die "Template process failed: ", $template->error(), "\n";

   So that our scripts will work with the same template files as our
earlier examples, we'll can add some configuration options to the
constructor to tell it about our environment:

     my $template->new({
     	# where to find template files
     	INCLUDE_PATH => '/home/abw/websrc/src:/home/abw/websrc/lib',
     	# pre-process lib/config to define any extra values
     	PRE_PROCESS  => 'config',
     });

   Note that here we specify the 'config' file as a PRE_PROCESS option.
This means that the templates we process can use the same global variables
defined earlier for our static pages.  We don't have to replicate their
definitions in this script.  However, we can supply additional data and
functionality specific to this script via the hash of variables that we
pass to the process() method.

   These entries in this hash may contain simple text or other values,
references to lists, others hashes, sub-routines or objects.  The Template
Toolkit will automatically apply the correct procedure to access these
different types when you use the variables in a template.

   Here's a more detailed example to look over.  Amongst the different
template variables we define in `$vars', we create a reference to a CGI
object and a 'get_user_projects' sub-routine.

     #!/usr/bin/perl -w

     use strict;
     use Template;
     use CGI;

     $| = 1;
     print "Content-type: text/html\n\n";

     my $file = 'userinfo.html';
     my $vars = {
         'version'  => 3.14,
     	'days'     => [ qw( mon tue wed thu fri sat sun ) ],
     	'worklist' => \&get_user_projects,
         'cgi'      => CGI->new(),
     	'me'       => {
             'id'     => 'abw',
             'name'   => 'Andy Wardley',
     	},
     };

     sub get_user_projects {
     	my $user = shift;
     	my @projects = ...   # do something to retrieve data
     	return \@projects;
     }

     my $template = Template->new({
     	INCLUDE_PATH => '/home/abw/websrc/src:/home/abw/websrc/lib',
     	PRE_PROCESS  => 'config',
     });

     $template->process($userinfo, $vars)
     	|| die $template->error();

   Here's a sample template file that we might create to build the output
for this script.

   $src/userinfo.html:     [% INCLUDE header        title = 'Template
Toolkit CGI Test'     %]

     <a href="mailto:[% email %]">Email [% me.name %]</a>

     <p>This is version [% version %]</p>

     <h3>Projects</h3>
     <ul>
     [% FOREACH project = worklist(me.id) %]
        <li> <a href="[% project.url %]">[% project.name %]</a>
     [% END %]
     </ul>

     [% INCLUDE footer %]

   This example shows how we've separated the Perl implementation (code)
from the presentation (HTML) which not only makes them easier to maintain
in isolation, but also allows the re-use of existing template elements
such as headers and footers, etc.  By using template to create the output
of your CGI scripts, you can give them the same consistency as your static
pages built via `ttree' or other means.

   Furthermore, we can modify our script so that it processes any one of a
number of different templates based on some condition.  A CGI script to
maintain a user database, for example, might process one template to
provide an empty form for new users, the same form with some default
values set for updating an existing user record, a third template for
listing all users in the system, and so on.  You can use any Perl
functionality you care to write to implement the logic of your application
and then choose one or other template to generate the desired output for
the application state.

DYNAMIC CONTENT GENERATION VIA APACHE/MOD_PERL HANDLER
======================================================

   The Template module can be used in a similar way from an Apache/mod_perl
handler.  Here's an example of a typical Apache httpd.conf file:

     PerlModule CGI;
     PerlModule Template
     PerlModule MyOrg::Apache::User

     PerlSetVar websrc_root   /home/abw/websrc

     <Location /user/bin>
         SetHandler     perl-script
         PerlHandler    MyOrg::Apache::User
     </Location>

   This defines a location called '/user/bin' to which all requests will
be forwarded to the handler() method of the MyOrg::Apache::User module.
That module might look something like this:

     package MyOrg::Apache::User;

     use strict;
     use vars qw( $VERSION );
     use Apache::Constants qw( :common );
     use Template qw( :template );
     use CGI;

     $VERSION = 1.59;

     sub handler {
     	my $r = shift;

     	my $websrc = $r->dir_config('websrc_root')
     	    or return fail($r, SERVER_ERROR,
     			   "'websrc_root' not specified");

     	my $template = Template->new({
     	    INCLUDE_PATH  => "$websrc/src/user:$websrc/lib",
     	    PRE_PROCESS   => 'config',
     	    OUTPUT        => $r,     # direct output to Apache request
     	});

     	my $params = {
     	    uri     => $r->uri,
     	    cgi     => CGI->new,
     	};

     	# use the path_info to determine which template file to process
     	my $file = $r->path_info;
     	$path =~ s[^/][];

     	$r->content_type('text/html');
     	$r->send_http_header;

     	$template->process($path, $params)
     	    || return fail($r, SERVER_ERROR, $template->error());

     	return OK;
     }

     sub fail {
     	my ($r, $status, $message) = @_;
     	$r->log_reason($message, $r->filename);
     	return $status;
     }

   The handler accepts the request and uses it to determine the
'websrc_root' value from the config file.  This is then used to define an
INCLUDE_PATH for a new Template object.  The URI is extracted from the
request and a CGI object is created.  These are both defined as template
variables.

   The name of the template file itself is taken from the PATH_INFO element
of the request.  In this case, it would comprise the part of the URL
coming after '/user/bin',  e.g for '/user/bin/edit', the template file
would be 'edit' located in "$websrc/src/user".  The headers are sent and
the template file is processed.  All output is sent directly to the
print() method of the Apache request object.

USING PLUGINS TO EXTEND FUNCTIONALITY
=====================================

   As we've already shown, it is possible to bind Perl data and functions
to template variables when creating dynamic content via a CGI script or
Apache/mod_perl process.  The Template Toolkit also supports a plugin
interface which allows you define such additional data and/or
functionality in a separate module and then load and use it as required
with the USE directive.

   The main benefit to this approach is that you can load the extension
into any template document, even those that are processed "statically" by
`tpage' or `ttree'.  You *don't* need to write a Perl wrapper to
explicitly load the module and make it available via the stash.

   Let's demonstrate this principle using the DBI plugin written by Simon
Matthews <sam@knowledgepool.com>.  You can create this template in your
'src' directory and process it using `ttree' to see the results.  Of
course, this example relies on the existence of the appropriate SQL
database but you should be able to adapt it to your own resources, or at
least use it as a demonstrative example of what's possible.

     [% INCLUDE header
        title = 'User Info'
     %]

     [% USE DBI('dbi:mSQL:mydbname') %]

     <table border=0 width="100%">
     <tr>
       <th>User ID</th>
       <th>Name</th>
       <th>Email</th>
     </tr>

     [% FOREACH user = DBI.query('SELECT * FROM user ORDER BY id') %]
     <tr>
       <td>[% user.id %]</td>
       <td>[% user.name %]</td>
       <td>[% user.email %]</td>
     </tr>
     [% END %]

     </table>

     [% INCLUDE footer %]

   A plugin is simply a Perl module in a known location and conforming to
a known standard such that the Template Toolkit can find and load it
automatically.  You can create your own plugin by inheriting from the
`Template::Plugin' module.

   Here's an example which defines some data items ('foo' and 'people')
and also an object method ('bar').  We'll call the plugin 'FooBar' for
want of a better name and create it in the
'MyOrg::Template::Plugin::FooBar' package.  We've added a 'MyOrg' to the
regular 'Template::Plugin::*' package to avoid any conflict with existing
plugins.

   You can create a module stub using the Perl utlity h2xs:

     h2xs -A -X -n MyOrg::Template::Plugin::FooBar

   This will create a directory structure representing the package name
along with a set of files comprising your new module.  You can then edit
FooBar.pm to look something like this:

     package MyOrg::Template::Plugin::FooBar;

     use Template::Plugin;
     use vars qw( $VERSION @ISA );

     @ISA = qw( Template::Plugin );
     $VERSION = 1.23;

     sub new {
         my ($class, $context, @params) = @_;

     bless {
         _CONTEXT => $context,
                 foo      => 25,
                 people   => [ 'tom', 'dick', 'harry' ],
     }, $class;
         }

     sub bar {
     	my ($self, @params) = @_;
         # ...do something...
     	return $some_value;
     }

   The plugin constructor new() receives the class name as the first
parameter, as is usual in Perl, followed by a reference to something
called a Template::Context object.  You don't need to worry too much about
this at the moment, other than to know that it's the main processing
object for the Template Toolkit.  It provides access to the functionality
of the processor and some plugins may need to communicate with it.  We
don't at this stage, but we'll save the reference anyway in the '_CONTEXT'
member.  The leading underscore is a convention which indicates that this
item is private and the Template Toolkit won't attempt to access this
member.  The other members defined, 'foo' and 'people' are regular data
items which will be made available to templates using this plugin.
Following the context reference are passed any additional parameters
specified with the USE directive, such as the data source parameter,
'dbi:mSQL:mydbname', that we used in the earlier DBI example.

   If you used h2xs to create the module stub then you'll already have a
Makefile.PL and you can incite the familiar incantation to build and
install it.  Don't forget to add some tests to test.pl!

     perl Makefile.PL
     make
     make test
     make install

   If you don't or can't install it to the regular place for your Perl
modules (perhaps because you don't have the required privileges) then you
can set the PERL5LIB environment variable to specify another location.  If
you're using `ttree' then you can add the following line to your
configuration file instead.  This has the effect of add '/path/to/modules'
to the @INC array to a similar end.

   $HOME/.ttreerc:     perl5lib = /path/to/modules

   One further configuration item must be added to inform the toolkit of
the new package name we have adopted for our plugins:

   $HOME/.ttreerc:     plugin_base = 'MyOrg::Template::Plugin'

   If you're writing Perl code to control the Template modules directly,
then this value can be passed as a configuration parameter when you create
the module.

     use Template;

     my $template = Template->new({
     	PLUGIN_BASE => 'MyOrg::Template::Plugin'
     });

   Now we can create a template which uses this plugin:

     [% INCLUDE header
        title = 'FooBar Plugin Test'
     %]

     [% USE FooBar %]

     Some values available from this plugin:
       [% FooBar.foo %] [% FooBar.bar %]

     The users defined in the 'people' list:
     [% FOREACH uid = FooBar.people %]
       * [% uid %]
     [% END %]

     [% INCLUDE footer %]

   The 'foo', 'bar' and 'people' items of the FooBar plugin are
automatically resolved to the appropriate data items or method calls on
the underlying object.

   Using this approach, it is possible to create application functionality
in a single module which can then be loaded and used on demand in any
template.  The simple interface between template directives and plugin
objects allows complex, dynamic content to be built from a few simple
template documents without knowing anything about the underlying
implementation.

AUTHOR
======

   Andy Wardley <abw@kfs.org>

     http://www.template-toolkit.org/
     http://www.kfs.org/~abw/

REVISION
========

   $Revision: 2.0 $

COPYRIGHT
=========

     Copyright (C) 1996-2000 Andy Wardley.  All Rights Reserved.
     Copyright (C) 1998-2000 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Template|Template' in this node, `tpage|tpage' in this node,
L<ttree|ttree

Various utility functions for the Template Tookit.
**************************************************

NAME
====

   Template::Utils - Various utility functions for the Template Tookit.

SYNOPSIS
========

     use Template::Utils qw( :all );

     my $handler = output_handler($target);
     my $target  = update_hash(\%target, \%params, \%defaults)

DESCRIPTION
===========

   The Template::Utils module defines a number of general sub-routines used
by the Template Toolkit.  These can be called by explicitly prefixing the
`Template::Utils' package name to the sub-routine, or by first importing
the functions into the current package by passing the ':subs' or ':all'
tagset names to the `use Template::Utils' line.

UTILITY SUB-ROUTINES
====================

output_handler($target)
-----------------------

   Creates a closure which can be called to send output to a particular
target.  The $target parameter may be an existing CODE ref (the ref is
returned), a reference to a GLOB such as `\*STDOUT' (a closure which print
to the GLOB is returned), a reference to an IO::Handle (a closure which
calls the handle's print() method is returned) or a reference to a target
string (a closure which appends output to the string is returned).

   The closure returned will print all parameters passed to it, as per
print().

     open(ERRLOG, "> $errorlog")
     	|| die "$errorlog: $!\n";

     my $fh = IO::File->new("> $myfile")
     	|| die "$myfile: $!\n";

     my $h1 = output_handler(\*STDERR);
     my $h2 = output_handler(\*ERRLOG);
     my $h3 = output_handler($fh);
     my $h4 = output_handler(\$mystring);

     foreach my $h ( $h1, $h2, h3, $h4 ) {
         &$h("An error has occured...\n");
     }

update_hash(\%target, \%params, \%defaults)
-------------------------------------------

   Updates the target hash referenced by the first paramter with values
specified in the second.  The third parameter may also reference a hash
which is used to define the valid keys and default values.

   A reference to the target hash ($target) is returned.

AUTHOR
======

   Andy Wardley <cre.canon.co.uk>

REVISION
========

   $Revision: 1.8 $

COPYRIGHT
=========

   Copyright (C) 1996-1999 Andy Wardley.  All Rights Reserved.  Copyright
(C) 1998-1999 Canon Research Centre Europe Ltd.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `Template|Template' in this node

Color screen output using ANSI escape sequences
***********************************************

NAME
====

   Term::ANSIColor - Color screen output using ANSI escape sequences

SYNOPSIS
========

     use Term::ANSIColor;
     print color 'bold blue';
     print "This text is bold blue.\n";
     print color 'reset';
     print "This text is normal.\n";
     print colored ("Yellow on magenta.\n", 'yellow on_magenta');
     print "This text is normal.\n";
     print colored ['yellow on_magenta'], "Yellow on magenta.\n";

     use Term::ANSIColor qw(:constants);
     print BOLD, BLUE, "This text is in bold blue.\n", RESET;

     use Term::ANSIColor qw(:constants);
     $Term::ANSIColor::AUTORESET = 1;
     print BOLD BLUE "This text is in bold blue.\n";
     print "This text is normal.\n";

DESCRIPTION
===========

   This module has two interfaces, one through color() and colored() and
the other through constants.

   color() takes any number of strings as arguments and considers them to
be space-separated lists of attributes.  It then forms and returns the
escape sequence to set those attributes.  It doesn't print it out, just
returns it, so you'll have to print it yourself if you want to (this is so
that you can save it as a string, pass it to something else, send it to a
file handle, or do anything else with it that you might care to).

   The recognized attributes (all of which should be fairly intuitive) are
clear, reset, dark, bold, underline, underscore, blink, reverse,
concealed, black, red, green, yellow, blue, magenta, on_black, on_red,
on_green, on_yellow, on_blue, on_magenta, on_cyan, and on_white.  Case is
not significant.  Underline and underscore are equivalent, as are clear
and reset, so use whichever is the most intuitive to you.  The color alone
sets the foreground color, and on_color sets the background color.

   Note that not all attributes are supported by all terminal types, and
some terminals may not support any of these sequences.  Dark, blink, and
concealed in particular are frequently not implemented.

   Attributes, once set, last until they are unset (by sending the
attribute "reset").  Be careful to do this, or otherwise your attribute
will last after your script is done running, and people get very annoyed
at having their prompt and typing changed to weird colors.

   As an aid to help with this, colored() takes a scalar as the first
argument and any number of attribute strings as the second argument and
returns the scalar wrapped in escape codes so that the attributes will be
set as requested before the string and reset to normal after the string.
Alternately, you can pass a reference to an array as the first argument,
and then the contents of that array will be taken as attributes and color
codes and the remainder of the arguments as text to colorize.

   Normally, colored() just puts attribute codes at the beginning and end
of the string, but if you set $Term::ANSIColor::EACHLINE to some string,
that string will be considered the line delimiter and the attribute will
be set at the beginning of each line of the passed string and reset at the
end of each line.  This is often desirable if the output is being sent to
a program like a pager that can be confused by attributes that span lines.
Normally you'll want to set $Term::ANSIColor::EACHLINE to `"\n"' to use
this feature.

   Alternately, if you import `:constants', you can use the constants
CLEAR, RESET, BOLD, DARK, UNDERLINE, UNDERSCORE, BLINK, REVERSE, CONCEALED,
BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, ON_BLACK, ON_RED, ON_GREEN,
ON_YELLOW, ON_BLUE, ON_MAGENTA, ON_CYAN, and ON_WHITE directly.  These are
the same as color('attribute') and can be used if you prefer typing:

     print BOLD BLUE ON_WHITE "Text\n", RESET;

   to

     print colored ("Text\n", 'bold blue on_white');

   When using the constants, if you don't want to have to remember to add
the `, RESET' at the end of each print line, you can set
$Term::ANSIColor::AUTORESET to a true value.  Then, the display mode will
automatically be reset if there is no comma after the constant.  In other
words, with that variable set:

     print BOLD BLUE "Text\n";

   will reset the display mode afterwards, whereas:

     print BOLD, BLUE, "Text\n";

   will not.

   The subroutine interface has the advantage over the constants interface
in that only two subroutines are exported into your namespace, versus
twenty-two in the constants interface.  On the flip side, the constants
interface has the advantage of better compile time error checking, since
misspelled names of colors or attributes in calls to color() and colored()
won't be caught until runtime whereas misspelled names of constants will
be caught at compile time.  So, polute your namespace with almost two
dozen subroutines that you may not even use that often, or risk a silly
bug by mistyping an attribute.  Your choice, TMTOWTDI after all.

DIAGNOSTICS
===========

Invalid attribute name %s
     (F) You passed an invalid attribute name to either color() or
     colored().

Name "%s" used only once: possible typo
     (W) You probably mistyped a constant color name such as:

          print FOOBAR "This text is color FOOBAR\n";

     It's probably better to always use commas after constant names in
     order to force the next error.

No comma allowed after filehandle
     (F) You probably mistyped a constant color name such as:

          print FOOBAR, "This text is color FOOBAR\n";

     Generating this fatal compile error is one of the main advantages of
     using the constants interface, since you'll immediately know if you
     mistype a color name.

Bareword "%s" not allowed while "strict subs" in use
     (F) You probably mistyped a constant color name such as:

          $Foobar = FOOBAR . "This line should be blue\n";

     or:

          @Foobar = FOOBAR, "This line should be blue\n";

     This will only show up under use strict (another good reason to run
     under use strict).

RESTRICTIONS
============

   It would be nice if one could leave off the commas around the constants
entirely and just say:

     print BOLD BLUE ON_WHITE "Text\n" RESET;

   but the syntax of Perl doesn't allow this.  You need a comma after the
string.  (Of course, you may consider it a bug that commas between all the
constants aren't required, in which case you may feel free to insert
commas unless you're using $Term::ANSIColor::AUTORESET.)

   For easier debuging, you may prefer to always use the commas when not
setting $Term::ANSIColor::AUTORESET so that you'll get a fatal compile
error rather than a warning.

NOTES
=====

   Jean Delvare provided the following table of different common terminal
emulators and their support for the various attributes:

     clear    bold     dark    under    blink   reverse  conceal
      ------------------------------------------------------------------------
      xterm         yes      yes      no      yes     bold      yes      yes
      linux         yes      yes      yes    bold      yes      yes      no
      rxvt          yes      yes      no      yes  bold/black   yes      no
      dtterm        yes      yes      yes     yes    reverse    yes      yes
      teraterm      yes    reverse    no      yes    rev/red    yes      no
      aixterm      kinda   normal     no      yes      no       yes      yes

   Where the entry is other than yes or no, that emulator interpret the
given attribute as something else instead.  Note that on an aixterm, clear
doesn't reset colors; you have to explicitly set the colors back to what
you want.  More entries in this table are welcome.

AUTHORS
=======

   Original idea (using constants) by Zenin (zenin@best.com), reimplemented
using subs by Russ Allbery (rra@stanford.edu), and then combined with the
original idea by Russ with input from Zenin.

Terminal control using ANSI escape sequences.
*********************************************

NAME
====

   Term::ANSIScreen - Terminal control using ANSI escape sequences.

SYNOPSIS
========

     # qw/:color/ is exported by default, i.e. color() & colored()

     use Term::ANSIScreen qw/:color :cursor :screen :keyboard/;

     print setmode(1), setkey('a','b');
     print "40x25 mode now, with 'a' mapped to 'b'.";
     <STDIN>; resetkey; setmode 3; cls;

     locate 1, 1; print "@ This is (1,1)", savepos;
     print locate(24,60), "@ This is (24,60)"; loadpos;
     print down(2), clline, "@ This is (3,15)\n";

     color 'black on white'; clline;
     print "This line is black on white.\n";
     print color 'reset'; print "This text is normal.\n";

     print colored ("This text is bold blue.\n", 'bold blue');
     print "This text is normal.\n";
     print colored ['bold blue'], "This text is bold blue.\n";
     print "This text is normal.\n";

     use Term::ANSIScreen qw/:constants/; # constants mode

     print BLUE ON GREEN . "Blue on green.\n";

     $Term::ANSIScreen::AUTORESET = 1;
     print BOLD GREEN . ON_BLUE "Bold green on blue.", CLEAR;
     print "\nThis text is normal.\n";

DESCRIPTION
===========

   Term::ANSIScreen is a superset of Term::ANSIColor.  In addition to
color-sequence generating subroutines exported by `:color' and
`:constants', this module also features `:cursor' for cursor positioning,
`:screen' for screen control, as well as `:keyboard' for key mapping.

NOTES
-----

   * All subroutines in Term::ANSIScreen will print its return value if
     called under a void context.

   * The cursor position, current color, screen mode and keyboard mappings
     affected by Term::ANSIScreen will last after the program terminates.
     You might want to reset them before the end of your program.

The `:color' function set (exported by default)
-----------------------------------------------

   Term::ANSIScreen recognizes (case-insensitively) following color
attributes: clear, reset, bold, underline, underscore, blink, reverse,
concealed, black, red, green, yellow, blue, magenta, on_black, on_red,
on_green, on_yellow, on_blue, on_magenta, on_cyan, and on_white.

   The color alone sets the foreground color, and on_color sets the
background color. You may also use on_color without the underscore, e.g.
"black on white".

color LIST
     Takes any number of strings as arguments and considers them to be
     space-separated lists of attributes.  It then forms and returns the
     escape sequence to set those attributes.

colored EXPR, LIST
     Takes a scalar as the first argument and any number of attribute
     strings as the second argument, then returns the scalar wrapped in
     escape codes so that the attributes will be set as requested before
     the string and reset to normal after the string.

     Alternately, you can pass a reference to an array as the first
     argument, and then the contents of that array will be taken as
     attributes and color codes and the remainder of the arguments as text
     to colorize.

     Normally, this function just puts attribute codes at the beginning
     and end of the string, but if you set $Term::ANSIScreen::EACHLINE to
     some string, that string will be considered the line delimiter and
     the attribute will be set at the beginning of each line of the passed
     string and reset at the end of each line.  This is often desirable if
     the output is being sent to a program like a pager, which can be
     confused by attributes that span lines.

     Normally you'll want to set $Term::ANSIColor::EACHLINE to `"\n"' to
     use this feature.

The `:constants' function set
-----------------------------

   If you import `:constants' you can use the constants CLEAR, RESET,
BOLD, UNDERLINE, UNDERSCORE, BLINK, REVERSE, CONCEALED, BLACK, RED, GREEN,
YELLOW, BLUE, MAGENTA, ON_BLACK, ON_RED, ON_GREEN, ON_YELLOW, ON_BLUE,
ON_MAGENTA, ON_CYAN, and ON_WHITE directly.  These are the same as
color('attribute') and can be used if you prefer typing:

     print BOLD BLUE ON_WHITE "Text\n", RESET;
     print BOLD BLUE ON WHITE "Text\n", RESET; # _ is optional

   to     print colored ("Text\n", 'bold blue on_white');

   When using the constants, if you don't want to have to remember to add
the `, RESET' at the end of each print line, you can set
$Term::ANSIColor::AUTORESET to a true value.  Then, the display mode will
automatically be reset if there is no comma after the constant.  In other
words, with that variable set:

     print BOLD BLUE "Text\n";

   will reset the display mode afterwards, whereas:

     print BOLD, BLUE, "Text\n";

   will not.

The `:cursor' function set
--------------------------

locate [EXPR, EXPR]
     Sets the cursor position. The first argument is its row number, and
     the second one its column number.  If omitted, the cursor will be
     located at (1,1).

up    [EXPR] =item down  [EXPR] =item left  [EXPR] =item right [EXPR]
     Moves the cursor toward any direction for EXPR characters. If
     omitted, EXPR is 1.

savepos =item loadpos
     Saves/restores the current cursor position.

The `:screen' function set
--------------------------

cls
     Clears the screen with the current background color, and set cursor
     to (1,1).

clline
     Clears the current row with the current background color, and set
     cursor to the 1st column.

setmode EXPR
     Sets the screen mode to EXPR. Under DOS, ANSI.SYS recognizes
     following values:

          0:  40 x  25 x   2 (text)   1:  40 x  25 x 16 (text)
          2:  80 x  25 x   2 (text)   3:  80 x  25 x 16 (text)
          4: 320 x 200 x   4          5: 320 x 200 x  2
          6: 640 x 200 x   2          7: Enables line wrapping
            13: 320 x 200 x   4         14: 640 x 200 x 16
            15: 640 x 350 x   2         16: 640 x 350 x 16
            17: 640 x 480 x   2         18: 640 x 480 x 16
            19: 320 x 200 x 256

wrapon =item wrapoff
     Enables/disables the line-wraping mode.

The `:keyboard' function set
----------------------------

setkey EXPR, EXPR
     Takes a scalar representing a single keystroke as the first argument
     (either a character or an escape sequence in the form of
     "num1;num2"), and maps it to a string defined by the second argument.
     Afterwards, when the user presses the mapped key, the string will
     get outputed instead.

resetkey [LIST]
     Resets each keys in the argument list to its original mapping.  If
     called without an argument, resets all previously mapped keys.

DIAGNOSTICS
===========

Invalid attribute name %s
     You passed an invalid attribute name to either color() or colored().

Identifier %s used only once: possible typo
     You probably mistyped a constant color name such as:

          print FOOBAR "This text is color FOOBAR\n";

     It's probably better to always use commas after constant names in
     order to force the next error.

No comma allowed after filehandle
     You probably mistyped a constant color name such as:

          print FOOBAR, "This text is color FOOBAR\n";

     Generating this fatal compile error is one of the main advantages of
     using the constants interface, since you'll immediately know if you
     mistype a color name.

Bareword %s not allowed while "strict subs" in use
     You probably mistyped a constant color name such as:

          $Foobar = FOOBAR . "This line should be blue\n";

     or:

          @Foobar = FOOBAR, "This line should be blue\n";

     This will only show up under use strict (another good reason to run
     under use strict).

AUTHORS
=======

   Original idea (using constants) by Zenin (zenin@best.com),
reimplemented using subs by Russ Allbery (rra@stanford.edu), and then
combined with the original idea by Russ with input from Zenin to
Term::ANSIColor. Screen mode and keyboard mapping codes were added by
Autrijus Tang, along with revised code and documentation.

COPYRIGHT
=========

   Copyright 2001 by Autrijus Tang <autrijus@autrijus.org>.  Based on
works of Zenin (zenin@best.com),                   Russ Allbery
(rra@stanford.edu).

   All rights reserved.  This module is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

Perl termcap interface
**********************

NAME
====

   Term::Cap - Perl termcap interface

SYNOPSIS
========

     require Term::Cap;
     $terminal = Tgetent Term::Cap { TERM => undef, OSPEED => $ospeed };
     $terminal->Trequire(qw/ce ku kd/);
     $terminal->Tgoto('cm', $col, $row, $FH);
     $terminal->Tputs('dl', $count, $FH);
     $terminal->Tpad($string, $count, $FH);

DESCRIPTION
===========

   These are low-level functions to extract and use capabilities from a
terminal capability (termcap) database.

   The *Tgetent* function extracts the entry of the specified terminal
type TERM (defaults to the environment variable TERM) from the database.

   It will look in the environment for a *TERMCAP* variable.  If found,
and the value does not begin with a slash, and the terminal type name is
the same as the environment string TERM, the *TERMCAP* string is used
instead of reading a termcap file.  If it does begin with a slash, the
string is used as a path name of the termcap file to search.  If *TERMCAP*
does not begin with a slash and name is different from TERM, *Tgetent*
searches the files `$HOME/.termcap', `/etc/termcap', and
`/usr/share/misc/termcap', in that order, unless the environment variable
*TERMPATH* exists, in which case it specifies a list of file pathnames
(separated by spaces or colons) to be searched *instead*.  Whenever
multiple files are searched and a tc field occurs in the requested entry,
the entry it names must be found in the same file or one of the succeeding
files.  If there is a `:tc=...:' in the *TERMCAP* environment variable
string it will continue the search in the files as above.

   *OSPEED* is the terminal output bit rate (often mistakenly called the
baud rate).  *OSPEED* can be specified as either a POSIX termios/SYSV
termio speeds (where 9600 equals 9600) or an old BSD-style speeds (where
13 equals 9600).

   *Tgetent* returns a blessed object reference which the user can then
use to send the control strings to the terminal using *Tputs* and *Tgoto*.
It calls croak on failure.

   *Tgoto* decodes a cursor addressing string with the given parameters.

   The output strings for *Tputs* are cached for counts of 1 for
performance.  *Tgoto* and *Tpad* do not cache.  `$self->{_xx}' is the raw
termcap data and `$self->{xx}' is the cached version.

     print $terminal->Tpad($self->{_xx}, 1);

   *Tgoto*, *Tputs*, and *Tpad* return the string and will also output the
string to $FH if specified.

   The extracted termcap entry is available in the object as
`$self->{TERMCAP}'.

EXAMPLES
========

     # Get terminal output speed
     require POSIX;
     my $termios = new POSIX::Termios;
     $termios->getattr;
     my $ospeed = $termios->getospeed;

     # Old-style ioctl code to get ospeed:
     #     require 'ioctl.pl';
     #     ioctl(TTY,$TIOCGETP,$sgtty);
     #     ($ispeed,$ospeed) = unpack('cc',$sgtty);

     # allocate and initialize a terminal structure
     $terminal = Tgetent Term::Cap { TERM => undef, OSPEED => $ospeed };

     # require certain capabilities to be available
     $terminal->Trequire(qw/ce ku kd/);

     # Output Routines, if $FH is undefined these just return the string

     # Tgoto does the % expansion stuff with the given args
     $terminal->Tgoto('cm', $col, $row, $FH);

     # Tputs doesn't do any % expansion.
     $terminal->Tputs('dl', $count = 1, $FH);

Perl word completion module
***************************

NAME
====

   Term::Complete - Perl word completion module

SYNOPSIS
========

     $input = Complete('prompt_string', \@completion_list);
     $input = Complete('prompt_string', @completion_list);

DESCRIPTION
===========

   This routine provides word completion on the list of words in the array
(or array ref).

   The tty driver is put into raw mode using the system command `stty raw
-echo' and restored using `stty -raw echo'.

   The following command characters are defined:

<tab>
     Attempts word completion.  Cannot be changed.

^D
     Prints completion list.  Defined by *$Term::Complete::complete*.

^U
     Erases the current input.  Defined by *$Term::Complete::kill*.

<del>, <bs>
     Erases one character.  Defined by *$Term::Complete::erase1* and
     *$Term::Complete::erase2*.

DIAGNOSTICS
===========

   Bell sounds when word completion fails.

BUGS
====

   The completion character <tab> cannot be changed.

AUTHOR
======

   Wayne Thompson

lowlevel graphics using gnuplot drawing routines.
*************************************************

NAME
====

   Term::Gnuplot - lowlevel graphics using gnuplot drawing routines.

SYNOPSIS
========

     use Term::Gnuplot ':ALL';
     list_terms();
     change_term('dumb') or die "Cannot set terminal.\n";
     term_init();				# init()
     term_start_plot();			# graphics();
     $xmax = scaled_xmax();
     $ymax = scaled_ymax();
     linetype(-2);
     move(0,0);
     vector($xmax-1,0);
     vector($xmax-1,$ymax-1);
     vector(0,$ymax-1);
     vector(0,0);
     justify_text(LEFT);
     put_text(h_char()*5, $ymax - v_char()*3,"Terminal Test, Perl");
     $x = $xmax/4;
     $y = $ymax/4;
     $xl = h_tic()*5;
     $yl = v_tic()*5;
     linetype(2);
     arrow($x,$y,$x+$xl,$y,1);
     arrow($x,$y,$x+$xl/2,$y+$yl,1);
     arrow($x,$y,$x,$y+$yl,1);
     arrow($x,$y,$x-$xl/2,$y+$yl,0);
     arrow($x,$y,$x-$xl,$y,1);
     arrow($x,$y,$x-$xl,$y-$yl,1);
     arrow($x,$y,$x,$y-$yl,1);
     arrow($x,$y,$x+$xl,$y-$yl,1);
     term_end_plot();			# text();
     Term::Gnuplot::reset();

EXPORTS
=======

   None by default.

Exportable and export tags:
---------------------------

`:SETUP'
          change_term test_term init_terminal list_terms  plot_outfile_set
          term_init term_start_plot term_end_plot
          term_start_multiplot term_end_multiplot plotsizes_scale
          setcanvas

`:JUSTIFY'
          LEFT CENTRE RIGHT

`:FIELDS'
          name description xmax ymax v_char h_char v_tic h_tic
          scaled_xmax scaled_ymax

`:METHODS'
          init scale graphics linetype move vector point text_angle
          justify_text put_text arrow text

%description
     Hash of `name => description' pairs.  In particular, `keys
     %description' contains names of supported terminals.

:ALL
     All of the above.

DESCRIPTION
===========

   Below I include the contents of the file `term/README' from gnuplot
distribution (see `gnuplot `term' in this node'). It explains the meaning
of the methods of `"SYNOPSIS"' in this node.

   All methods are supported under Perl, the options method is available as
set_options(). The discription below includes underscores, that are
deleted in the perl interface.

   The functions which are not included in the description below:

`change_term($newname)'
test_term()
init_terminal()
     self-explanatory.

list_terms()
     Print names/descriptions of supported terminals.

`plot_outfile_set($filename)'
     set the output file.  This should be done before setting the terminal
     type.

`plotsizes_scale($xfactor, $yfactor)'
     set the size of the output device (such as a graphic file) in
     fractions of the default size.  Some output drivers may ignore this
     request.  The request is active until the next request.

     Does not change sizes reported by xmax() and ymax()!  After such a
     call one should use the following calls:

scaled_xmax(), scaled_ymax()
     Report xmax() and ymax() corrected by the scaling factors given to
     plotsizes_scale().

term_init(), term_start_plot(), term_end_plot()
     higher-level functions variants of init(), graphics(), text().  Should
     be prefered over init(), graphics(), text() if the output file is
     changed, since they take into account resetting of output file mode
     (if needed).

term_start_multiplot(), term_end_multiplot()
     Interfaces to C functions with the same names.  How to use them
     outside of gnuplot proper is not clear.

_term_descrs()
     Returns hash of names/descriptions of supported terminals (available
     as %Term::Gnuplot::description too).

setcanvas($ptk_canvas)
     Sets the Tk widget for direct-draw operations (may be used with
     terminal 'tkcanvas' with the option 'tkperl_canvas').

   *NOTE.* Some terminals require calling set_options() before init()!

gnuplot `term/README'
=====================

   DOCUMENTATION FOR GNUPLOT TERMINAL DRIVER WRITERS

   By Russell Lang 1/90

   Updated for new file layout by drd 4/95

   Paragraphs about inclusion of TERM_HELP added by rcc 1/96

   No change to the interface between gnuplot and the terminal drivers,
but we would like to make the terminal drivers standalone

   1) in order move the support for the terminal drivers outside of the
support for the main program, thereby encouraging a library of
contributed drivers 2) To make it easy for users to add contributed
drivers, by adding    a single #include line to term.h 3) To allow
individual compilation on DOS, to save the overlay    manager from having
to load _all_ drivers together.

   CORRECTION - scale() interface is no longer supported, since it is
incompatible with multiplot.

   Whole of terminal driver should be contained in one <driver>.trm file,
with a fairly strict layout as detailed below - this allows the gnuplot
maintainers to change the way the terminal drivers are compiled without
having to change the drivers themselves.

   term.h, and therefore each file.trm file, may be loaded more than once,
with different sections selected by macros.

   Each driver provides all the functions it needs, and a table of
function pointers and other data to interface to gnuplot.  The table entry
is currently defined as follows in plot.h:

     struct TERMENTRY {

     /* required entries */

     char *name;
     char *description;
     unsigned int xmax,ymax,v_char,h_char,v_tic,h_tic;

     void (*options) __PROTO((void));
     void (*init) __PROTO((void));
     void (*reset) __PROTO((void));
     void (*text) __PROTO((void));
     int (*scale) __PROTO((double, double));
     void (*graphics) __PROTO((void));
     void (*move) __PROTO((unsigned int, unsigned int));
     void (*vector) __PROTO((unsigned int, unsigned int));
     void (*linetype) __PROTO((int));
     void (*put_text) __PROTO((unsigned int, unsigned int,char*));

     /* optional entries */

     int (*text_angle) __PROTO((int));
     int (*justify_text) __PROTO((enum JUSTIFY));
     void (*point) __PROTO((unsigned int, unsigned int,int));
     void (*arrow) __PROTO((unsigned int, unsigned int, unsigned int,
     		   unsigned int, int));
        int (*set_font) __PROTO((char *font));  /* "font,size" */
     void (*set_pointsize) __PROTO((double size)); /* notification of set pointsize */
     int flags; /* various flags */
        void (*suspend) __PROTO((void)); /* after one plot of multiplot */
        void (*resume) __PROTO((void));  /* before subsequent plot of multiplot */
        void (*boxfill) __PROTO((int style, unsigned int x1, unsigned int y1, unsigned int width, unsigned int height)); /* clear part of multiplot */
        void (*linewidth) __PROTO((double linewidth));
        void (*pointsize) __PROTO((double pointsize));
       };

   One consequence of (1) is that we would like drivers to be backwards
compatible - drivers in the correct form below should work in future
versions of gnuplot without change. C compilers guarantee to fill
unitialised members of a structure to zero, so gnuplot can detect old
drivers, in which fields have not been initalised, and can point new
interface entry pointers to dummy functions.

   We can add fields to the terminal structure, but only at the end of the
list.  If you design a terminal that cant work without a new interface
being defined, and consequent changes to the main gnuplot source, please
contact bug-gnuplot@dartmouth.edu simply to ensure that you have the most
up to date defn of the terminal structure. Also, please ensure that the
'set term' command checks for 0 values in added fields when an old driver
is selected, and a pointer to a suitable 'cant do' function is provided.
It is therefore not required (and in fact not possible) to add padding
fields to the end of all drivers.

   Similarly, if you add an optional field to an old driver, take care to
ensure that all intervening fields are padded with zeros.

   Some of the above fields are required - this should not be a problem,
since they were all required in earlier releases of gnuplot.  The later
fields are interfaces to capabilities that not all devices can do, or for
which the generic routines provided should be adequate.  There are several
null ('cant do') functions provided by term.c which a driver can reference
in the table. Similarly, for bitmap devices, there are generic routines
for lines and text provided by bitmap.c

   Here's a brief description of each variable:

   The char *name is a pointer to a string containing the name of the
terminal.  This name is used by the 'set terminal' and 'show terminal'
commands.  The name must be unique and must not be confused with an
abbreviation of another name.  For example if the name "postscript"
exists, it is not possible to have another name "postscript2".  Keep the
name under 15 characters.

   The char *description is a pointer to a string containing a description
of the terminal, which is displayed in response to the 'set terminal'
command.  Keep the description under 60 characters.

   xmax is the maximum number of points in the x direction.  The range of
points used by gnuplot is 0 to xmax-1.

   ymax is the maximum number of points in the y direction.  The range of
points used by gnuplot is 0 to ymax-1.

   v_char is the height of characters, in the same units as xmax and ymax.
The border for labelling at the top and bottom of the plot is calculated
using v_char.  v_char is used as the vertical line spacing for characters.

   h_char is the width of characters, in the same units as xmax and ymax.
The border for labelling at the left and right of the plot is calculated
using h_char, for example.  If the _justify_text function returns FALSE,
h_char is used to justify text right or centre.  If characters are not
fixed width, then the _justify_text function must correctly justify the
text.

   v_tic is the vertical size of tics along the x axis, in the same units
as ymax.

   h_tic is the horizontal size of tics along the y axis, in the same
units as xmax.

   v_tic and h_tic should give tics of the same physical size on the
output. The ratio of these two quantities is used by gnuplot to set the
aspect ratio to 1 so that circles appear circular when 'set size square'
is active.

   All the above values need not be static - values can be substituted
into the table during terminal initialisation, based on options for
example.

   Here's a brief description of what each term.c function does:

   _options()  Called when terminal type is selected.  This procedure
should parse options on the command line.  A list of the currently
selected options should be stored in term_options[] in a form suitable for
use with the set term command.  term_options[] is used by the save
command.  Use options_null() if no options are available.

   _init()  Called once, when the device is first selected.  This procedure
should set up things that only need to be set once, like handshaking and
character sets etc...  There is a global variable 'pointsize' which you
might want to use here.  If set pointsize is issued after init has been
called, the set_pointsize() function is called.

   _reset()  Called when gnuplot is exited, the output device changed or
the terminal type changed.  This procedure should reset the device,
possibly flushing a buffer somewhere or generating a form feed.

   _scale(xs,ys) Called just before _graphics(). This takes the x and y
scaling factors as information. If the terminal would like to do its own
scaling, it returns TRUE. Otherwise, it can ignore the information and
return FALSE: do_plot will do the scaling for you. null_scale is provided
to do just this, so most drivers can ignore this function entirely. The
Latex driver is currently the only one providing its own scaling. PLEASE
DO NOT USE THIS INTERFACE - IT IS NOT COMPATIBLE WITH MULTIPLOT.

   _graphics()  Called just before a plot is going to be displayed.  This
procedure should set the device into graphics mode.  Devices which can't
be used as terminals (like plotters) will probably be in graphics mode
always and therefore won't need this.

   _text()  Called immediately after a plot is displayed.  This procedure
should set the device back into text mode if it is also a terminal, so
that commands can be seen as they're typed.  Again, this will probably do
nothing if the device can't be used as a terminal. This call can be used
to trigger conversion and output for bitmap devices.

   _move(x,y)  Called at the start of a line.  The cursor should move to
the (x,y) position without drawing.

   _vector(x,y)  Called when a line is to be drawn.  This should display a
line from the last (x,y) position given by _move() or _vector() to this
new (x,y) position.

   _linetype(lt)  Called to set the line type before text is displayed or
line(s) plotted.  This procedure should select a pen color or line style
if the device has these capabilities.  lt is an integer from -2 to 0 or
greater.  An lt of -2 is used for the border of the plot.  An lt of -1 is
used for the X and Y axes.  lt 0 and upwards are used for plots 0 and
upwards.  If _linetype() is called with lt greater than the available line
types, it should map it to one of the available line types.  Most drivers
provide 9 different linetypes (lt is 0 to 8).

   _put_text(x,y,str)  Called to display text at the (x,y) position, while
in graphics mode.   The text should be vertically (with respect to the
text) justified about (x,y).  The text is rotated according to _text_angle
and then horizontally (with respect to the text) justified according to
_justify_text.

   The following are optional

   _text_angle(ang)  Called to rotate the text angle when placing the y
label.  If ang = 0 then text is horizontal.  If ang = 1 then text is
vertically upwards.  Returns TRUE if text can be rotated, FALSE otherwise.
[But you must return TRUE if called with ang=0]

   _justify_text(mode)  Called to justify text left, right or centre.  If
mode = LEFT then text placed by _put_text is flushed left against (x,y).
If mode = CENTRE then centre of text is at (x,y).  If mode = RIGHT then
text is placed flushed right against (x,y).  Returns TRUE if text can be
justified Returns FALSE otherwise and then _put_text assumes text is
flushed left; justification of text is then performed by calculating the
text width using strlen(text) * h_char.

   _point(x,y,point)  Called to place a point at position (x,y).  point is
-1 or an integer from 0 upwards.  At least 6 point types (numbered 0 to 5)
are normally provided.  Point type -1 is a dot.  If point is more than the
available point types then it should be mapped back to one of the
available points.  Two _point() functions called do_point() and
line_and_point() are provided in term.c and should be suitable for most
drivers.  do_point() draws the points in the current line type.  If your
driver uses dotted line types (generally because it is monochrome), you
should use line_and_point() which changes to line type 0 before drawing
the point.  line type 0 should be solid.

   There is a global variable 'pointsize' which is controlled by the set
pointsize command. If possible, use that. pointsize should be examined at
terminal init. If it is subsequently changed, the set_pointsize() fn will
be called.

   _arrow(sx,sy,ex,ey,head)  Called to draw an arrrow from (sx,sy) to
(ex,ey).  A head is drawn on the arrow if head = TRUE.  An _arrow()
function called do_arrow() is provided in term.c which will draw arrows
using the _move() and _vector() functions.  Drivers should use do_arrow
unless it causes problems.

   _set_font() is called to set the font of labels, etc [new 3.7 feature]
fonts are selected as strings "name,size"

   _pointsize() is used to set the pointsize for subsequent points

   _flags stores various flags describing driver capabilities. Currently
three bits are allocated   - TERM_CAN_MULTIPLOT - driver can do multiplot
fully-interactively when output is not redirected. ie text and graphics
go to different places, or driver can flip using suspend.    -
TERM_CANT_MULTIPLOT - driver cannot multiplot, even if output   is
redirected.    - TERM_BINARY - output file must be opened in binary mode
Another bit is earmarked for VMS_PASTHRU, but not yet implemented.

   _suspend() - called before gnuplot issues a prompt in multiplot mode
linux vga driver uses this entry point to flip from graphics to    text
mode. X11 driver will take this opportunity to paint the window    on the
display.

   _resume() - called after suspend(), before subsequent plots of a
multiplot.

   _boxfill() - fills a box in given style (currently unimplemented -
always            background colour at present). used by 'clear' in
multiplot for            support of inset graphs

   _linewidth() - sets the linewidth

   The following should illustrate the order in which calls to these
routines are made:

     _options()
      _init()
        _scale(xs,ys)
        _graphics()
          _linewidth(lw)
          _linetype(lt)
          _move(x,y)
          _vector(x,y)
          _pointsize(size)
          _point(x,y,point)
          _text_angle(angle)
          _justify(mode)
          _set_font(font)
          _put_text(x,y,text)
          _arrow(sx,sy,ex,ey)
        _text()
        _graphics()
          .
        _suspend()
        _set_pointsize()
        _resume()
          .
        _text()
      _reset()

   -----------------------------------

   BITMAP DEVICES

   A file bitmap.c is provided, implementing a generic set of bitmap
routines. It provides all the routines required to generate a bitmap in
memory, drawing lines and writing text. A simple driver need provide only
a text() entry point, which converts and outputs the stored bitmap in the
format required by the device.

   Internally, the bitmap is built of one or more planes of 1 bit per
pixel. In fact, I think the library would be easier to use if it offered
one or more planes of pixels with 1,2,4 or 8 bits per pixel, since not all
bitmap devices are based on planes, and the planes have to be recombined
at the end at present.  In general, a device would use either planes or
bits-per-pixel, though I guess a 24-bit bitmap could use 3 planes of 8 bits
per pixel..?

   The pixels are currently organised horizontally packed into bytes.

   ie

     ********%%%%%%%%$$$$$$$$!!!!!!!! etc
     ^^^^^^^^@@@@@@@@########++++++++ etc

   where like symbols are stored in one byte. Vertical packing can be
arranged by reversing x and y dimensions and setting the global
b_rastermode to TRUE.  (eg epson 8-pin dot-matrix printer)

   Functions provided are

   (internal fns ? - should probably be static, not external ?)

     b_setpixel(x,y,value)
     b_setmaskpixel(x,y,value)
     b_putc(x,y,char,angle)
     b_setvalue(size)

   setting up stuff

     b_makebitmap(x,y,planes)  - make a bitmap of size x * y
     b_freebitmap()            - free bitmap
     b_charsize(size)

   gnuplot driver interface functions  (can go straight into gnuplot
structure)

     b_setlinetype(linetype)
     b_move(x,y)
     b_vector(x,y)
     b_put_text(x,y,*str)
     b_text_angle(ang)

   I think that the library could be made easier to use if we defined a
structure which described the bitmap (raster mode, planes, bits-per-pixel,
colours, etc) and then added to the gnuplot term struct a pointer to this
structure. Then we could have b_graphics() routine which did all the
initialisation that presently has to be done by the driver graphics()
entry point.  Also, one day I would like to have parsing, including
terminal driver options, table-driven, but I'm getting ahead of myself
here.

   At present, bitmap.c is linked into gnuplot unconditionally. Perhaps it
should be put into a library, so that it is linked in only if any of the
user-selected drivers require bitmap support.

   There may be scope to do similar things with some of the other stuff
that is shared by several drivers. Rather than requiring, for example,
that LATEX driver is required if EMTEX is to be used, the shared routines
could be extracted to a library and linked if any of the drivers which use
them are used.  Just a thought...

   -----------------------------------

   FILE LAYOUT ----------

   I think a file layout like the following will leave most flexibility to
the gnuplot maintainers. I use REGIS for example.

     #include "driver.h"

     #ifdef TERM_REGISTER
     register_term(regis) /* no ; */
     #endif

     #ifdef TERM_PROTO
     TERM_PUBLIC void REGISinit __PROTO((void));
     TERM_PUBLIC void REGISgraphics __PROTO((void));
     /* etc */
     #define GOT_REGIS_PROTO
     #endif

     #ifndef TERM_PROTO_ONLY
     #ifdef TERM_BODY

     TERM_PUBLIC void REGISinit()
     {
       /* etc */
     }

     /* etc */

     #endif

     #ifdef TERM_TABLE

     TERM_TABLE_START(regis_driver)
       /* no { */
       "regis", "REGIS graphics language",
       REGISXMAX, /* etc */
       /* no } */
     TERM_TABLE_END(regis_driver)

     #undef LAST_TERM
     #define LAST_TERM regis_driver

     #endif /* TERM_TABLE */
     #endif /* TERM_PROTO_ONLY */

     #ifdef TERM_HELP
     START_HELP(regis)
     "1 regis",
     "?set terminal regis",
     "?regis",
     " The `regis` terminal device generates output in the REGIS graphics language.",
     " It has the option of using 4 (the default) or 16 colors.",
     "",
     " Syntax:",
     "         set term regis {4 | 16}"
     END_HELP(regis)
     #endif

   -------------

   The first three lines in the TERM_HELP section must contain the same
name as that specified by register_term, since this is the name that will
be entered into the list of available terminals.  If more than one name is
registered, the additional names should have their own two "?" lines, but
not the "1" line.

   Each record is enclosed in double-quotes and (except for the last
record) followed by a comma.  The text is copied as a single string into
gnuplot.doc, so the syntax must obey the rules of that entity.  If the
text includes double-quotes or backslashes, these must be escaped by
preceding each occurence with a backslash.

   -------------

   Rationale:

   We may want to compile all drivers into term.c or one driver at a time
this layout should support both TERM_PUBLIC will be static  if all modules
are in term.c, or blank otherwise.  Please make private support functions
static if possible.

   We may include term.h, and therefore all these files, one or more times.
If just once (all modules compiled into term.c) putting the four parts in
this order should make it work.

   we may compile the table entries into either an array or a linked list
This organisation should support both

   For separate compilation, we may write a program which defines
TERM_REGISTER and #include term.h to find out which drivers are selected
in term.h and thereby generate a makefile.

   For a driver which depends on another (eg enhpost and pslatex on post)
the driver can do something like

     #ifndef GOT_POST_PROTO
     #define TERM_PROTO_ONLY
     #include "post.trm"
     #undef TERM_PROTO_ONLY
     #endif

   this is probably needed only in the TERM_TABLE section only, but may
also be used in the body. The TERM_PROTO_ONLY means that we pick up only
the protos from post.trm, even if current driver is being compiled with
TERM_BODY or TERM_TABLE

   If we do it the linked-list way, the arg to TERM_TABLE_START will be
the name of the variable, so any valid, unique name is fine.  The
TERM_TABLE_START macro will do all the work of linking the entries
together, probably using LAST_TERM

   The inclusion of the TERM_HELP section (and removal of terminal
documentation from the master gnuplot.doc file) means that the online help
will include discussions of only those terminals available to the user.
For generation of the printed manual, all can be included.

   Please make as many things as possible static, but do still try to use
unique names since all drivers may all be compiled into term.o

   The bit in the PROTO section is basically what you would put into a .h
file if we had them - everything that is needed by the TABLE_ENTRY should
be defined in this part. In particular, dont forget all the maxes and
character sizes and things for the table entry.

   Dont forget to put TERM_PUBLIC in the defns of the fns as well as the
prototypes. It will probably always expand to 'static' except for pcs.

Using Term::Gnuplot from C libraries
====================================

   The interface of this module to gnuplot version 3.7 is going via a
translation layer in `Gnuplot.h'.  This layer isolates low-level drawing
routines from gnuplot program.  (In doing this unsupported job it does
some nasty thing, in particular `Gnuplot.h' cannot be included in more than
one C compilation unit.)

   In fact `Gnuplot.h' can be used by any C program or library which wants
to use device-independent plotting routines of gnuplot.

   C library should use the same syntax of calls as `Term::Gnuplot', with
the only difference that to call low-level _init() method one calls
gptable_init(), to set terminal one calls `termset(name)', and to get a
property of terminal (say `xmax') one uses `termprop(xmax)'.

   To set options one can setup the array token and data `c_token',
`num_tokens', `input_line', then call options().  Alternately, one can
define `SET_OPTIONS_FROM_STRING', then a call `set_options_from(string)'
is avalable.  This call will set up all these variables and will call
options().  However, the logic of the parsing of the string is very
primitive.

   *NOTES.*

   * To initialize the facilities of `Gnuplot.h' from C one needs to call
     setup_gpshim().  This call can be made as many times as wanted, only
     the first call will do anything.

   * NULL argument to term_set_output() means "reset back to stdout".

   * `Gnuplot.h' expects that the macro/function `croak(...)' is defined.
     This function should have the same syntax as printf(), and should not
     return.  It is used as an error-reporting function.

   * One should define functions `int StartOutput()', `int EndOutput()' and
     `int OutLine(char *s)' which will be used by gnuplot for error
     messages and for terminal listing.  Alternatively, one can define
     `GNUPLOT_OUTLINE_STDOUT', and gnuplot will put these messages to
     stdout.

Runtime link with gnuplot DLL
-----------------------------

   There are two different ways to use the plotting calls via `Gnuplot.h'.
One can either establish the link to gnuplot library at *compile/link
time*, or to postpone this link to *run time*.  By default `Gnuplot.h'
provides the first way, to switch to the second way define
`DYNAMIC_GNUPLOT' before including `Gnuplot.h'.

   To establish a link at *run time*, one needs to load a dynamic library
which is compiled from `Gnuplot.h' - but without `DYNAMIC_GNUPLOT' defined.
Feed the result of the call to get_term_ftable() as an argument to
set_term_ftable(), as in (with error-condition checking disabled):

     typedef struct t_ftable *(*g_ftable)(void);
     g_ftable g_ftable_addr;
     void *handle = dlopen("gnuterm.dll", mode);

     g_ftable_addr = (g_ftable) dlsym(handle, "get_term_ftable");
     set_term_ftable((*g_ftable_addr)());

   This means that any C library/program which uses the API provided by
`Gnuplot.h' does not *need* to be even linked with gnuplot, neither it
requires include files of gnuplot.  If plotting is done in some situations
only, one will not need the overhead of gnuplot plotting library
(`gnuterm.dll' in the above example) unless plotting is requested.

Runtime link of a Perl module with `Term::Gnuplot'
--------------------------------------------------

   To facilitate *run time* link the `Term::Gnuplot' Perl module provides
a Perl subroutine get_term_ftable() which is a variant of C
get_term_ftable() which returns an integer instead of an address.  One can
feed this integer to a C function `v_set_term_ftable(void*)', which will
establish a runtime link.  Thus the external XS library which wants to use
Term::Gnuplot at runtime can put this in `.xs' file:

     #define int_set_term_ftable(a) (v_set_term_ftable((void*)a))
     extern  void v_set_term_ftable(void *a);
     ...

     void
     int_set_term_ftable(a)
       IV a

   include `Gnuplot.h' (with `DYNAMIC_GNUPLOT' defined) into any C file,
and define this Perl subroutine

     sub link_gnuplot {
       eval 'use Term::Gnuplot 0.56; 1' or die;
       int_set_term_ftable(Term::Gnuplot::get_term_ftable());
     }

   in `.pm' file.

   Now if it needs to do plotting, it calls link_gnuplot(), then does the
plotting - without a need to interact with gnuplot at compile/link time,
and having the additional burden of low-level plotting code loaded in the
executable/DLL.

   After a call link_gnuplot(), all the `Gnuplot.h' API calls made from
the above C file will be directed through the vtables of the Perl module
`Term::Gnuplot'.

Using different Plotting libraries
----------------------------------

   In fact `Gnuplot.h' knows almost nothing about gnuplot, with a notable
exceptions that there is an API call `term = change_term(name)', which
returns a table of methods.  Thus *in principle* `Gnuplot.h' can establish
a runtime-link with any plotting library which supports (or can be coerced
to support) this call.  (The table is assumed to be compatible with
gnuplot layout of `struct termentry'.)

   `Gnuplot.h' uses also a handful of other gnuplot APIs (such as changing
output file and several initialization shortcuts), but they should be easy
to be ignored if an interface to another plotting library is needed.

Examples
========

High-level plotting
-------------------

     sub ploth {
       my ($xmin, $xmax, $sub) = (shift, shift, shift);
       my $wpoints = scaled_xmax() - 1;
       my $hpoints = scaled_ymax() - 1;
       my $delta = ($xmax - $xmin)/$wpoints;
       my (@ys, $y);
       my ($ymin, $ymax) = (1e300, -1e300);
       my $x = $xmin;
       for my $i (0 .. $wpoints) {
         $y = $sub->($x);
         push @ys, $y;
         $ymin = $y if $ymin > $y;
         $ymax = $y if $ymax < $y;
         $x += $delta;
       }
       my $deltay = ($ymax - $ymin)/$hpoints;
       $_ = ($_ - $ymin)/$deltay + $yfix for @ys;

     term_start_plot();

     linetype -2;
     move 0, $yfix;
     vector 0, $hpoints + $yfix;
     vector $wpoints, $hpoints + $yfix;
     vector $wpoints, $yfix;
     vector 0, $yfix;

     linetype -1;
     if ($xmin < 0 && $xmax > 0) {
       my $xzero = -$xmin/$delta;
       move $xzero, $yfix;
       vector $xzero, $hpoints + $yfix;
     }
     if ($ymin < 0 && $ymax > 0) {
       my $yzero = -$ymin/$deltay + $yfix;
       move 0, $yzero;
       vector $wpoints, $yzero;
     }

     linetype 0;
     move 0, int($ys[0] + 0.5);
     linetype 0;
     for my $i (1 .. $wpoints) {
       $x += $delta;
       vector $i, int($ys[$i] + 0.5);
     }
     term_end_plot();
       }

   This function should be used as in

     ploth(-1,3, sub { sin( (shift)**6 ) })

   $yfix should be set to 1 for gif terminal to compensate for off-by-one
bug.

Multifile plotting
------------------

     use strict;
     use Term::Gnuplot qw(:ALL);

     my ($yfix, $ext) = (1, 'gif');
     plot_outfile_set "manypl1.$ext";		# Need to set before plotterm()

     change_term "gif";
     set_options "size", 300, ',', 200;
     term_init();

     for my $k (1..6) {
       plot_outfile_set "manypl$k.$ext" unless $k == 1;
       ploth( -1, 3, sub { sin((shift)**$k) } );
     }

   Here we use the function ploth() from `High-level plotting' in this
node, it should be in the same scope so that $yfix is visible there.  Note
that gif terminal requires $yfix to be 1 to circumvent a bug, and requires
a literal `','' in the set_options call.

   If a terminal does not support direct setting of the size of the output
device, one may set global rescaling factors by calling plotsizes_scale():

     plotsizes_scale(300/xmax(), 200/ymax());

BUGS and LIMITATIONS
====================

   The following C macros are set to reasonable values, no peeking is
performed to get correct values, this may break Gnuplot on some systems:

     NO_ATEXIT HAVE_ON_EXIT PIPES HAVE_LIBC_H

   No testing for

     X11

   macros is performed either, however, this may only increase size of the
executable (since `X11' module is not making any direct X calls, but calls
an external program to serve the requests).

   Apparently gif terminal has off-by-one error: yrange is `1..ymax()'.
All the bugs of gnuplot low-level plotting show in this module as well.

SEE ALSO
========

   See Term/GnuplotTerminals.

documentation of gnuplot output devices
***************************************

NAME
====

   Term::GnuplotTerminals - documentation of gnuplot output devices

aed767
======

   The `aed512' and aed767 terminal drivers support AED graphics terminals.
The two drivers differ only in their horizontal ranges, which are 512 and
768 pixels, respectively.  Their vertical range is 575 pixels.  There are
no options for these drivers.

aifm
====

   Several options may be set in aifm--the Adobe Illustrator 3.0+ driver.

   Syntax:

     set terminal aifm {<color>} {"<fontname>"} {<fontsize>}

   <color> is either color or `monochrome'; "<fontname>" is the name of a
valid PostScript font; <fontsize> is the size of the font in PostScript
points, before scaling by the `set size' command.  Selecting default sets
all options to their default values: `monochrome', "Helvetica", and 14pt.

   Since AI does not really support multiple pages, multiple graphs will be
drawn directly on top of one another.  However, each graph will be grouped
individually, making it easy to separate them inside AI (just pick them up
and move them).

   Examples:

     set term aifm
     set term aifm 22
     set size 0.7,1.4; set term aifm color "Times-Roman" 14

amiga
=====

   The amiga terminal, for Commodore Amiga computers, allows the user to
plot either to a screen (default), or, if Kickstart 3.0 or higher is
installed, to a window on the current public screen. The font and its size
can also be selected.

   Syntax:

     set terminal amiga {screen | window} {"<fontname>"} {<fontsize>}

   The default font is 8-point "topaz".

   The screen option uses a virtual screen, so it is possible that the
graph will be larger than the screen.

apollo
======

   The apollo terminal driver supports the Apollo Graphics Primitive
Resource with rescaling after window resizing.  It has no options.

   If a fixed-size window is desired, the gpr terminal may be used instead.

atari ST (via AES)
==================

   The `atari' terminal has options to set the character size and the
screen colors.

   Syntax:

     set terminal atari {<fontsize>} {<col0> <col1> ... <col15.}

   The character size must appear if any colors are to be specified.  Each
of the (up to 16) colors is given as a three-digit hex number, where the
digits represent RED, GREEN and BLUE (in that order).  The range of 0-15
is scaled to whatever color range the screen actually has.  On a normal ST
screen, odd and even intensities are the same.

   Examples:

     set terminal atari 4    # use small (6x6) font
     set terminal atari 6 0  # set monochrome screen to white on black
     set terminal atari 13 0 fff f00 f0 f ff f0f
                # set first seven colors to black, white, green, blue,
                # cyan, purple, and yellow and use large font (8x16).

   Additionally, if an environment variable GNUCOLORS exists, its contents
are interpreted as an options string, but an explicit terminal option takes
precedence.

atari ST (via VDI)
==================

   The `vdi' terminal is the same as the `atari' terminal, except that it
sends output to the screen via the VDI and not into AES-Windows.

   The `vdi' terminal has options to set the character size and the screen
colors.

   Syntax:

     set terminal vdi {<fontsize>} {<col0> <col1> ... <col15.}

   The character size must appear if any colors are to be specified.  Each
of the (up to 16) colors is given as a three-digit hex number, where the
digits represent RED, GREEN and BLUE (in that order).  The range of 0-15
is scaled to whatever color range the screen actually has.  On a normal ST
screen, odd and even intensities are the same.

   Examples:

     set terminal vdi 4    # use small (6x6) font
     set terminal vdi 6 0  # set monochrome screen to white on black
     set terminal vdi 13 0 fff f00 f0 f ff f0f
                # set first seven colors to black, white, green, blue,
                # cyan, purple, and yellow and use large font (8x16).

   Additionally, if an environment variable GNUCOLORS exists, its contents
are interpreted as an options string, but an explicit terminal option takes
precedence.

cgi
===

   The cgi and `hcgi' terminal drivers support SCO CGI drivers.  `hcgi' is
for printers; the environment variable CGIPRNT must be set.  cgi may be
used for either a display or hardcopy; if the environment variable CGIDISP
is set, then that display is used.  Otherwise CGIPRNT is used.

   These terminals have no options.

cgm
===

   The cgm terminal generates a Computer Graphics Metafile.  This file
format is a subset of the ANSI X3.122-1986 standard entitled "Computer
Graphics - Metafile for the Storage and Transfer of Picture Description
Information".  Several options may be set in cgm.

   Syntax:

     set terminal cgm {<mode>} {<color>} {<rotation>} {solid | dashed}
                      {width <plot_width>} {linewidth <line_width>}
                      {"<font>"} {<fontsize>}

   where <mode> is `landscape', `portrait', or default; <color> is either
color or `monochrome'; <rotation> is either rotate or `norotate'; solid
draws all curves with solid lines, overriding any dashed patterns;
<plot_width> is the width of the page in points; <line_width> is the line
width in points; <font> is the name of a font; and `<fontsize'> is the
size of the font in points.

   By default, cgm uses rotated text for the Y axis label.

   The first six options can be in any order.  Selecting default sets all
options to their default values.

   Examples:

     set terminal cgm landscape color rotate dashed width 432 \
                    linewidth 1  'Arial Bold' 12       # defaults
     set terminal cgm 14 linewidth 2  14  # wider lines & larger font
     set terminal cgm portrait 'Times Roman Italic' 12
     set terminal cgm color solid    # no pesky dashes!

font
----

   The first part of a Computer Graphics Metafile, the metafile
description, includes a font table.  In the picture body, a font is
designated by an index into this table.  By default, this terminal
generates a table with the following fonts:

     Arial
     Arial Italic
     Arial Bold
     Arial Bold Italic
     Times Roman
     Times Roman Italic
     Times Roman Bold
     Times Roman Bold Italic
     Helvetica
     Roman

   Case is not distinct, but the modifiers must appear in the above order
(that is, not 'Arial Italic Bold').  'Arial Bold' is the default font.

   You may also specify a font name which does not appear in the default
font table.  In that case, a new font table is constructed with the
specified font as its only entry.  You must ensure that the spelling,
capitalization, and spacing of the name are appropriate for the
application that will read the CGM file.

fontsize
--------

   Fonts are scaled assuming the page is 6 inches wide.  If the size
command is used to change the aspect ratio of the page or the CGM file is
converted to a different width (e.g. it is imported into a document in
which the margins are not 6 inches apart), the resulting font sizes will
be different.  To change the assumed width, use the width option.

linewidth
---------

   The linewidth option sets the width of lines in pt.  The default width
is 1 pt.  Scaling is affected by the actual width of the page, as discussed
under the fontsize and width options

rotate
------

   The `norotate' option may be used to disable text rotation.  For
example, the CGM input filter for Word for Windows 6.0c can accept rotated
text, but the DRAW editor within Word cannot.  If you edit a graph (for
example, to label a curve), all rotated text is restored to horizontal.
The Y axis label will then extend beyond the clip boundary.  With
`norotate', the Y axis label starts in a less attractive location, but the
page can be edited without damage.  The rotate option confirms the default
behavior.

solid
-----

   The solid option may be used to disable dashed line styles in the
plots.  This is useful when color is enabled and the dashing of the lines
detracts from the appearance of the plot. The `dashed' option confirms the
default behavior, which gives a different dash pattern to each curve.

size
----

   Default size of a CGM page is 32599 units wide and 23457 units high for
landscape, or 23457 units wide by 32599 units high for portrait.

width
-----

   All distances in the CGM file are in abstract units.  The application
that reads the file determines the size of the final page.  By default,
the width of the final page is assumed to be 6 inches (15.24 cm).  This
distance is used to calculate the correct font size, and may be changed
with the width option.  The keyword should be followed by the width in
points.  (Here, a point is 1/72 inch, as in PostScript.  This unit is
known as a "big point" in TeX.)  gnuplot arithmetic can be used to convert
from other units, as follows:

     set terminal cgm width 432            # default
     set terminal cgm width 6*72           # same as above
     set terminal cgm width 10/2.54*72     # 10 cm wide

winword6
--------

   The default font table was chosen to match, where possible, the default
font assignments made by the Computer Graphics Metafile input filter for
Microsoft Word 6.0c, although the filter makes available only 'Arial' and
'Times Roman' fonts and their bold and/or italic variants.  Other fonts
such as 'Helvetica' and 'Roman' are not available.  If the CGM file
includes a font table, the filter mostly ignores it.  However, it changes
certain font assignments so that they disagree with the table.  As a
workaround, the winword6 option deletes the font table from the CGM file.
In this case, the filter makes predictable font assignments.  'Arial Bold'
is correctly assigned even with the font table present, which is one
reason it was chosen as the default.

   winword6 disables the color tables for a similar reason--with the color
table included, Microsoft Word displays black for color 7.

   Linewidths and pointsizes may be changed with `set linestyle'.

corel
=====

   The corel terminal driver supports CorelDraw.

   Syntax:

     set terminal corel {  default
                         | {monochrome | color
                              {<fontname> {"<fontsize>"
                                 {<xsize> <ysize> {<linewidth> }}}}}

   where the fontsize and linewidth are specified in points and the sizes
in inches.  The defaults are monochrome, "SwitzerlandLight", 22, 8.2, 10
and 1.2.

debug
=====

   This terminal is provided to allow for the debugging of gnuplot.  It is
likely to be of use only for users who are modifying the source code.

svga
====

   The svga terminal driver supports PCs with SVGA graphics.  It can only
be be used if it is compiled with DJGPP.  Its only option is the font.

   Syntax:

     set terminal svga {"<fontname>"}

dumb
====

   The dumb terminal driver has an optional size specification and trailing
linefeed control.

   Syntax:

     set terminal dumb {[no]feed} {<xsize> <ysize>}

   where <xsize> and <ysize> set the size of the dumb terminals. Default is
79 by 24. The last newline is printed only if `feed' is enabled.

   Examples:

     set term dumb nofeed
     set term dumb 79 49 # VGA screen---why would anyone do that?

dxf
===

   The dxf terminal driver creates pictures that can be imported into
AutoCad (Release 10.x).  It has no options of its own, but some features
of its plots may be modified by other means.  The default size is 120x80
AutoCad units, which can be changed by `set size'.  dxf uses seven colors
(white, red, yellow, green, cyan, blue and magenta), which can be changed
only by modifying the source file.  If a black-and-white plotting device
is used, the colors are mapped to differing line thicknesses.  See the
description of the AutoCad print/plot command.

dxy800a
=======

   This terminal driver supports the Roland DXY800A plotter.  It has no
options.

eepic
=====

   The eepic terminal driver supports the extended LaTeX picture
environment.  It is an alternative to the latex driver.

   The output of this terminal is intended for use with the "eepic.sty"
macro package for LaTeX.  To use it, you need "eepic.sty", "epic.sty" and a
printer driver that supports the "tpic" \specials.  If your printer driver
doesn't support those \specials, "eepicemu.sty" will enable you to use some
of them.

   Although dotted and dashed lines are possible with eepic and are
tempting, they do not work well for high-sample-rate curves, fusing the
dashes all together into a solid line.  For now, the eepic driver creates
only solid lines.  There is another gnuplot driver (tpic) that supports
dashed lines, but it cannot be used if your DVI driver doesn't support
"tpic" \specials.

   All drivers for LaTeX offer a special way of controlling text
positioning: If any text string begins with '{', you also need to include
a '}' at the end of the text, and the whole text will be centered both
horizontally and vertically by LaTeX. -- If the text string begins with
'[', you need to continue it with: a position specification (up to two out
of t,b,l,r), ']{', the text itself, and finally, '}'. The text itself may
be anything LaTeX can typeset as an LR-box. \rule{}{}'s may help for best
positioning.

   The eepic terminal has no options.

   Examples: About label positioning: Use gnuplot defaults (mostly
sensible, but sometimes not really best):

     set title '\LaTeX\ -- $ \gamma $'

   Force centering both horizontally and vertically:

     set label '{\LaTeX\ -- $ \gamma $}' at 0,0

   Specify own positioning (top here):

     set xlabel '[t]{\LaTeX\ -- $ \gamma $}'

   The other label - account for long ticlabels:

     set ylabel '[r]{\LaTeX\ -- $ \gamma $\rule{7mm}{0pt}'

emxvga
======

   The emxvga, `emxvesa' and `vgal' terminal drivers support PCs with SVGA,
vesa SVGA and VGA graphics boards, respectively.  They are intended to be
compiled with "emx-gcc" under either DOS or OS/2.  They also need VESA and
SVGAKIT maintained by Johannes Martin (JMARTIN@GOOFY.ZDV.UNI-MAINZ.DE) with
additions by David J. Liu (liu@phri.nyu.edu).

   Syntax:

     set terminal emxvga
     set terminal emxvesa {vesa-mode}
     set terminal vgal

   The only option is the vesa mode for `emxvesa', which defaults to
G640x480x256.

epson-180dpi
============

   This driver supports a family of Epson printers and derivatives.

   epson-180dpi and `epson-60dpi' are drivers for Epson LQ-style 24-pin
printers with resolutions of 180 and 60 dots per inch, respectively.

   `epson-lx800' is a generic 9-pin driver appropriate for printers like
the Epson LX-800, the Star NL-10 and NX-1000, the PROPRINTER, and so forth.

   `nec-cp6' is generix 24-pin driver that can be used for printers like
the NEC CP6 and the Epson LQ-800.

   The `okidata' driver supports the 9-pin OKIDATA 320/321 Standard
printers.

   The `starc' driver is for the Star Color Printer.

   The `tandy-60dpi' driver is for the Tandy DMP-130 series of 9-pin,
60-dpi printers.

   Only `nec-cp6' has any options.

   Syntax:

     set terminal nec-cp6 {monochrome | colour | draft}

   which defaults to monochrome.

   With each of these drivers, a binary copy is required on a PC to print.
Do not use print--use instead `copy file /b lpt1:'.

excl
====

   The excl terminal driver supports Talaris printers such as the EXCL
Laser printer and the 1590.  It has no options.

hercules
========

   These drivers supports PC monitors with autodetected graphics boards.
They can be used only when compiled with Zortech C/C++.  None have options.

fig
===

   The fig terminal device generates output in the Fig graphics language.

   Syntax:

     set terminal fig {monochrome | color} {small | big}
                      {pointsmax <max_points>}
                      {landscape | portrait}
                      {metric | inches}
                      {fontsize <fsize>}
                      {size <xsize> <ysize>}
                      {thickness <units>}
                      {depth <layer>}

   `monochrome' and color determine whether the picture is black-and-white
or color.  small and `big' produce a 5x3 or 8x5 inch graph in the default
`landscape' mode and 3x5 or 5x8 inches in `portrait' mode.  <max_points>
sets the maximum number of points per polyline.  Default units for editing
with "xfig" may be `metric' or `inches'.  fontsize sets the size of the
text font to <fsize> points.  size sets (overrides) the size of the drawing
area to <xsize>*<ysize> in units of inches or centimeters depending on the
`inches' or `metric' setting in effect.  depth sets the default depth layer
for all lines and text.  The default depth is 10 to leave room for adding
material with "xfig" on top of the plot.

   `thickness' sets the default line thickness, which is 1 if not
specified.  Overriding the thickness can be achieved by adding a multiple
of 100 to the to the `linetype' value for a plot command.  In a similar
way the depth of plot elements (with respect to the default depth) can be
controlled by adding a multiple of 1000 to <linetype>.  The depth is then
<layer> + <linetype>/1000 and the thickness is (<linetype>%1000)/100 or,
if that is zero, the default line thickness.

   Additional point-plot symbols are also available with the fig driver.
The symbols can be used through `pointtype' values % 100 above 50, with
different fill intensities controlled by <pointtype> % 5 and outlines in
black (for <pointtype> % 10 < 5) or in the current color.  Available
symbols are

     50 - 59:  circles
     60 - 69:  squares
     70 - 79:  diamonds
     80 - 89:  upwards triangles
     90 - 99:  downwards triangles

   The size of these symbols is linked to the font size.  The depth of
symbols is by default one less than the depth for lines to achieve nice
error bars.  If <pointtype> is above 1000, the depth is <layer> +
<pointtype>/1000-1.  If <pointtype>%1000 is above 100, the fill color is
(<pointtype>%1000)/100-1.

   Available fill colors are (from 1 to 9): black, blue, green, cyan, red,
magenta, yellow, white and dark blue (in monochrome mode: black for 1 to 6
and white for 7 to 9).

   See `plot with' for details of <linetype> and <pointtype>.

   The `big' option is a substitute for the `bfig' terminal in earlier
versions, which is no longer supported.

   Examples:

     set terminal fig monochrome small pointsmax 1000  # defaults

     plot 'file.dat' with points linetype 102 pointtype 759

   would produce circles with a blue outline of width 1 and yellow fill
color.

     plot 'file.dat' using 1:2:3 with err linetype 1 pointtype 554

   would produce errorbars with black lines and circles filled red.  These
circles are one layer above the lines (at depth 9 by default).

   To plot the error bars on top of the circles use

     plot 'file.dat' using 1:2:3 with err linetype 1 pointtype 2554

gif
===

   The gif terminal driver generates output in GIF format.  It uses Thomas
Boutell's gd library, which is available from http://www.boutell.com/gd/

   Syntax:

     set terminal gif {transparent} {interlace}
                      {small | medium | large}
                      {size <x>,<y>}
                      {<color0> <color1> <color2> ...}

   transparent instructs the driver to generate transparent GIFs.  The
first color will be the transparent one.

   interlace instructs the driver to generate interlaced GIFs.

   The choice of fonts is small (6x12 pixels), `medium' (7x13 Bold) or
large (8x16).

   The size <x,y> is given in pixels--it defaults to 640x480.  The number
of pixels can be also modified by scaling with the `set size' command.

   Each color must be of the form 'xrrggbb', where x is the literal
character 'x' and 'rrggbb' are the red, green and blue components in hex.
For example, 'x00ff00' is green.  The background color is set first, then
the border colors, then the X & Y axis colors, then the plotting colors.
The maximum number of colors that can be set is 256.

   Examples:

     set terminal gif small size 640,480 \
                      xffffff x000000 x404040 \
                      xff0000 xffa500 x66cdaa xcdb5cd \
                      xadd8e6 x0000ff xdda0dd x9500d3    # defaults

   which uses white for the non-transparent background, black for borders,
gray for the axes, and red, orange, medium aquamarine, thistle 3, light
blue, blue, plum and dark violet for eight plotting colors.

     set terminal gif transparent xffffff \
                      x000000 x202020 x404040 x606060 \
                      x808080 xA0A0A0 xC0C0C0 xE0E0E0 \

   which uses white for the transparent background, black for borders, dark
gray for axes, and a gray-scale for the six plotting colors.

   The page size is 640x480 pixels.  The gif driver can create either color
or monochromatic output, but you have no control over which is produced.

   The current version of the gif driver does not support animated GIFs.

unixplot
========

   The unixplot driver produces device-independent output in the GNU plot
graphics language.  The default size of the PostScript results generated by
"plot2ps" is 5 x 3 inches; this can be increased up to about 8.25 x 8.25 by
`set size'.

   Syntax:

     set terminal unixplot {"<fontname>"} {<fontsize>}

   which defaults to 10-point "Courier".

   There is a non-GNU version of the unixplot driver which cannot be
compiled unless this version is left out.

gpic
====

   The gpic terminal driver generates GPIC graphs in the Free Software
Foundations's "groff" package.  The default size is 5 x 3 inches.  The only
option is the origin, which defaults to (0,0).

   Syntax:

     set terminal gpic {<x> <y>}

   where x and y are in inches.

   A simple graph can be formatted using

     groff -p -mpic -Tps file.pic > file.ps.

   The output from pic can be pipe-lined into eqn, so it is possible to put
complex functions in a graph with the `set label' and `set {x/y}label'
commands.  For instance,

     set ylab '@space 0 int from 0 to x alpha ( t ) roman d t@'

   will label the y axis with a nice integral if formatted with the
command:

     gpic filename.pic | geqn -d@@ -Tps | groff -m[macro-package] -Tps
         > filename.ps

   Figures made this way can be scaled to fit into a document.  The pic
language is easy to understand, so the graphs can be edited by hand if
need be.  All co-ordinates in the pic-file produced by gnuplot are given
as x+gnuplotx and y+gnuploty.  By default x and y are given the value 0.
If this line is removed with an editor in a number of files, one can put
several graphs in one figure like this (default size is 5.0x3.0 inches):

     .PS 8.0
     x=0;y=3
     copy "figa.pic"
     x=5;y=3
     copy "figb.pic"
     x=0;y=0
     copy "figc.pic"
     x=5;y=0
     copy "figd.pic"
     .PE

   This will produce an 8-inch-wide figure with four graphs in two rows on
top of each other.

   One can also achieve the same thing by the command

     set terminal gpic x y

   for example, using

     .PS 6.0
     copy "trig.pic"
     .PE

gpr
===

   The gpr terminal driver supports the Apollo Graphics Primitive Resource
for a fixed-size window.  It has no options.

   If a variable window size is desired, use the apollo terminal instead.

grass
=====

   The grass terminal driver gives gnuplot capabilities to users of the
GRASS geographic information system.  Contact
grassp-list@moon.cecer.army.mil for more information.  Pages are written
to the current frame of the GRASS Graphics Window.  There are no options.

hp2623a
=======

   The hp2623a terminal driver supports the Hewlett Packard HP2623A.  It
has no options.

hp2648
======

   The hp2648 terminal driver supports the Hewlett Packard HP2647 and
HP2648.  It has no options.

hp500c
======

   The hp500c terminal driver supports the Hewlett Packard HP DeskJet 500c.
It has options for resolution and compression.

   Syntax:

     set terminal hp500c {<res>} {<comp>}

   where res can be 75, 100, 150 or 300 dots per inch and comp can be
"rle", or "tiff".  Any other inputs are replaced by the defaults, which
are 75 dpi and no compression.  Rasterization at the higher resolutions
may require a large amount of memory.

hpgl
====

   The hpgl driver produces HPGL output for devices like the HP7475A
plotter.  There are two options which can be set--the number of pens and
"eject", which tells the plotter to eject a page when done.  The default
is to use 6 pens and not to eject the page when done.

   The international character sets ISO-8859-1 and CP850 are recognized via
`set encoding iso_8859_1' or `set encoding cp850' (see `set encoding' for
details).

   Syntax:

     set terminal hpgl {<number_of_pens>} {eject}

   The selection

     set terminal hpgl 8 eject

   is equivalent to the previous `hp7550' terminal, and the selection

     set terminal hpgl 4

   is equivalent to the previous `hp7580b' terminal.

   The `pcl5' driver supports the Hewlett-Packard Laserjet III.  It
actually uses HPGL-2, but there is a name conflict among the terminal
devices.  It has several options

   Syntax:

     set terminal pcl5 {<mode>} {<font>} {<fontsize>}

   where <mode> is `landscape', or `portrait', <font> is `stick',
`univers', or `cg_times', and <fontsize> is the size in points.

   With `pcl5' international characters are handled by the printer; you
just put the appropriate 8-bit character codes into the text strings.  You
don't need to bother with `set encoding'.

   HPGL graphics can be imported by many software packages.

hpljii
======

   The hpljii terminal driver supports the HP Laserjet Series II printer.
The `hpdj' driver supports the HP DeskJet 500 printer.  These drivers
allow a choice of resolutions.

   Syntax:

     set terminal hpljii | hpdj {<res>}

   where res may be 75, 100, 150 or 300 dots per inch; the default is 75.
Rasterization at the higher resolutions may require a large amount of
memory.

   The hp500c terminal is similar to `hpdj'; hp500c additionally supports
color and compression.

hppj
====

   The hppj terminal driver supports the HP PaintJet and HP3630 printers.
The only option is the choice of font.

   Syntax:

     set terminal hppj {FNT5X9 | FNT9X17 | FNT13X25}

   with the middle-sized font (FNT9X17) being the default.

imagen
======

   The imagen terminal driver supports Imagen laser printers.  It is
capable of placing multiple graphs on a single page.

   Syntax:

     set terminal imagen {<fontsize>} {portrait | landscape}
                         {[<horiz>,<vert>]}

   where fontsize defaults to 12 points and the layout defaults to
`landscape'.  `<horiz'> and `<vert'> are the number of graphs in the
horizontal and vertical directions; these default to unity.

   Example:

     set terminal imagen portrait [2,3]

   puts six graphs on the page in three rows of two in portrait
orientation.

iris4d
======

   The iris4d terminal driver supports Silicon Graphics IRIS 4D computers.
Its only option is 8- or 24-bit color depth.  The default is 8.

   Syntax:

     set terminal iris4d {8 | 24}

   The color depth is not really a choice - the value appropriate for the
hardware should be selected.

   When using 24-bit mode, the colors can be directly specified via the
file .gnuplot_iris4d that is searched in the current directory and then in
the home directory specified by the HOME environment variable.  This file
holds RGB values for the background, border, labels and nine plotting
colors, in that order.  For example, here is a file containing the default
colors:

     85   85   85     Background   (dark gray)
     0    0    0      Boundary     (black)
     170  0    170    Labeling     (magenta)
     85   255  255    Plot Color 1 (light cyan)
     170  0    0      Plot Color 2 (red)
     0    170  0      Plot Color 3 (green)
     255  85   255    Plot Color 4 (light magenta)
     255  255  85     Plot Color 5 (yellow)
     255  85   85     Plot Color 6 (light red)
     85   255  85     Plot Color 7 (light green)
     0    170  170    Plot Color 8 (cyan)
     170  170  0      Plot Color 9 (brown)

   This file must have exactly 12 lines of RGB triples.  No empty lines are
allowed, and anything after the third number on a line is ignored.

kyo
===

   The kyo and `prescribe' terminal drivers support the Kyocera laser
printer.  The only difference between the two is that kyo uses "Helvetica"
whereas `prescribe' uses "Courier".  There are no options.

latex
=====

   The latex and `emtex' drivers allow two options.

   Syntax:

     set terminal latex | emtex {courier | roman} {<fontsize>}

   fontsize may be any size you specify.  The default is 10-point Roman.

   Unless your driver is capable of building fonts at any size (e.g.
dvips), stick to the standard 10, 11 and 12 point sizes.

   METAFONT users beware: METAFONT does not like odd sizes.

   All drivers for LaTeX offer a special way of controlling text
positioning: If any text string begins with '{', you also need to include
a '}' at the end of the text, and the whole text will be centered both
horizontally and vertically by LaTeX. -- If the text string begins with
'[', you need to continue it with: a position specification (up to two out
of t,b,l,r), ']{', the text itself, and finally, '}'. The text itself may
be anything LaTeX can typeset as an LR-box. \rule{}{}'s may help for best
positioning.

   Examples: About label positioning: Use gnuplot defaults (mostly
sensible, but sometimes not really best):

     set title '\LaTeX\ -- $ \gamma $'

   Force centering both horizontally and vertically:

     set label '{\LaTeX\ -- $ \gamma $}' at 0,0

   Specify own positioning (top here):

     set xlabel '[t]{\LaTeX\ -- $ \gamma $}'

   The other label - account for long ticlabels:

     set ylabel '[r]{\LaTeX\ -- $ \gamma $\rule{7mm}{0pt}'

linux
=====

   The linux driver has no additional options to specify.  It looks at the
environment variable GSVGAMODE for the default mode; if not set, it uses
1024x768x256 as default mode or, if that is not possible, 640x480x16
(standard VGA).

macintosh
=========

   Several options may be set in the 'macintosh' driver.

   Syntax:

     set terminal macintosh {singlewin | multiwin} {vertical | novertical} {size <width>, <height> | default}

   'singlewin' limits the output to a single window and is useful for
animations.  'multiwin' allows multiple windows.  'vertical' is only valid
under the gx option. With this option, rotated text

     be drawn vertically. novertical turns this option off.
      size <width>, <height> overrides the graph size set in the preferences
     dialog until it is cleared with either 'set term mac size default'
     or 'set term mac default'.

     'set term mac size default' sets the window size settings to those set in
        the preferences dialog.

     'set term mac default' sets all options to their default values.
        Default values: nogx, multiwin, novertical.

     If you generate graphs under the multiwin option and then switch to singlewin,
     the next plot command will cause one more window to be created. This new
     window will be reused as long as singlewin is in effect. If you switch back
     to multiwin, generate some graphs, and then switch to singlewin again, the
     orginal 'singlewin' window will be resused if it is still open. Otherwise
     a new 'singlewin' window will be created. The 'singlewin' window is not numbered.

mf
==

   The mf terminal driver creates a input file to the METAFONT program.
Thus a figure may be used in the TeX document in the same way as is a
character.

   To use a picture in a document, the METAFONT program must be run with
the output file from gnuplot as input.  Thus, the user needs a basic
knowledge of the font creating process and the procedure for including a
new font in a document.  However, if the METAFONT program is set up
properly at the local site, an unexperienced user could perform the
operation without much trouble.

   The text support is based on a METAFONT character set.  Currently the
Computer Modern Roman font set is input, but the user is in principal free
to chose whatever fonts he or she needs.  The METAFONT source files for the
chosen font must be available.  Each character is stored in a separate
picture variable in METAFONT.  These variables may be manipulated (rotated,
scaled etc.) when characters are needed.  The drawback is the
interpretation time in the METAFONT program.  On some machines (i.e. PC)
the limited amount of memory available may also cause problems if too many
pictures are stored.

   The mf terminal has no options.

METAFONT Instructions
---------------------

   - Set your terminal to METAFONT:

     set terminal mf

   - Select an output-file, e.g.:

     set output "myfigures.mf"

   - Create your pictures. Each picture will generate a separate
character. Its default size will be 5*3 inches. You can change the size by
saying `set size 0.5,0.5' or whatever fraction of the default size you
want to have.

   - Quit gnuplot.

   - Generate a TFM and GF file by running METAFONT on the output of
gnuplot.  Since the picture is quite large (5*3 in), you will have to use
a version of METAFONT that has a value of at least 150000 for memmax.  On
Unix systems these are conventionally installed under the name bigmf.  For
the following assume that the command virmf stands for a big version of
METAFONT.  For example:

   - Invoke METAFONT:

     virmf '&plain'

   - Select the output device: At the METAFONT prompt ('*') type:

     \mode:=CanonCX;     % or whatever printer you use

   - Optionally select a magnification:

     mag:=1;             % or whatever you wish

   - Input the gnuplot-file:

     input myfigures.mf

   On a typical Unix machine there will usually be a script called "mf"
that executes virmf '&plain', so you probably can substitute mf for virmf
&plain.  This will generate two files: mfput.tfm and mfput.$$$gf (where
$$$ indicates the resolution of your device).  The above can be
conveniently achieved by typing everything on the command line, e.g.:
virmf '&plain' '\mode:=CanonCX; mag:=1; input myfigures.mf' In this case
the output files will be named myfigures.tfm and myfigures.300gf.

   - Generate a PK file from the GF file using gftopk:

     gftopk myfigures.300gf myfigures.300pk

   The name of the output file for gftopk depends on the DVI driver you
use.  Ask your local TeX administrator about the naming conventions.
Next, either install the TFM and PK files in the appropriate directories,
or set your environment variables properly.  Usually this involves setting
TEXFONTS to include the current directory and doing the same thing for the
environment variable that your DVI driver uses (no standard name here...).
This step is necessary so that TeX will find the font metric file and
your DVI driver will find the PK file.

   - To include your pictures in your document you have to tell TeX the
font:

     \font\gnufigs=myfigures

   Each picture you made is stored in a single character.  The first
picture is character 0, the second is character 1, and so on...  After
doing the above step, you can use the pictures just like any other
characters.  Therefore, to place pictures 1 and 2 centered in your
document, all you have to do is:

     \centerline{\gnufigs\char0}
     \centerline{\gnufigs\char1}

   in plain TeX.  For LaTeX you can, of course, use the picture
environment and place the picture wherever you wish by using the \makebox
and \put macros.

   This conversion saves you a lot of time once you have generated the
font; TeX handles the pictures as characters and uses minimal time to
place them, and the documents you make change more often than the pictures
do.  It also saves a lot of TeX memory.  One last advantage of using the
METAFONT driver is that the DVI file really remains device independent,
because no \special commands are used as in the eepic and tpic drivers.

mgr
===

   The mgr terminal driver supports the Mgr Window system.  It has no
options.

mif
===

   The mif terminal driver produces Frame Maker MIF format version 3.00.
It plots in MIF Frames with the size 15*10 cm, and plot primitives with
the same pen will be grouped in the same MIF group.  Plot primitives in a
gnuplot page will be plotted in a MIF Frame, and several MIF Frames are
collected in one large MIF Frame.  The MIF font used for text is "Times".

   Several options may be set in the MIF 3.00 driver.

   Syntax:

     set terminal mif {colour | monochrome} {polyline | vectors}
                      {help | ?}

   colour plots lines with line types >= 0 in colour (MIF sep. 2-7) and
`monochrome' plots all line types in black (MIF sep. 0).  `polyline' plots
curves as continuous curves and `vectors' plots curves as collections of
vectors.  help and ? print online help on standard error output--both
print a short description of the usage; help also lists the options;

   Examples:

     set term mif colour polylines    # defaults
     set term mif                     # defaults
     set term mif vectors
     set term mif help

mtos
====

   The mtos terminal has no options.  It sends data via a pipe to an
external program called GPCLIENT.  It runs under MULTITOS, Magic 3.x,
MagicMAC. and MiNT.  If you cannot find GPCLIENT, than mail to
dirk@lstm.uni-erlangen.de.

next
====

   Several options may be set in the next driver.

   Syntax:

     set terminal next {<mode>} {<type> } {<color>} {<dashed>}
                {"<fontname>"} {<fontsize>} title {"<newtitle>"}

   where <mode> is  default, which sets all options to their defaults;
<type> is either new or old, where old invokes the old single window;
<color> is either color or `monochrome'; <dashed> is either solid or
`dashed'; "<fontname>" is the name of a valid PostScript font; <fontsize>
is the size of the font in PostScript points; and <title> is the title for
the GnuTerm window.  Defaults are  new, `monochrome', `dashed',
"Helvetica", 14pt.

   Examples:

     set term next default
     set term next 22
     set term next color "Times-Roman" 14
     set term next color "Helvetica" 12 title "MyPlot"
     set term next old

   Pointsizes may be changed with `set linestyle'.

pbm
===

   Several options may be set in the pbm terminal--the driver for PBMplus.

   Syntax:

     set terminal pbm {<fontsize>} {<mode>}

   where <fontsize> is small, `medium', or large and <mode> is
`monochrome', `gray' or color.  The default plot size is 640 pixels wide
and 480 pixels high; this may be changed by `set size'.

   The output of the pbm driver depends upon <mode>: `monochrome' produces
a portable bitmap (one bit per pixel), `gray' a portable graymap (three
bits per pixel) and color a portable pixmap (color, four bits per pixel).

   The output of this driver can be used with Jef Poskanzer's excellent
PBMPLUS package, which provides programs to convert the above PBMPLUS
formats to GIF, TIFF, MacPaint, Macintosh PICT, PCX, X11 bitmap and many
others.  PBMPLUS may be obtained from ftp.x.org.  The relevant files have
names that begin with "netpbm-1mar1994.p1"; they reside in
/contrib/utilities.  The package can probably also be obtained from one of
the many sites that mirrors ftp.x.org.

   Examples:

     set terminal pbm small monochrome             # defaults
     set size 2,2; set terminal pbm color medium

dospc
=====

   The dospc terminal driver supports PCs with arbitrary graphics boards,
which will be automatically detected.  It should be used only if you are
not using the gcc or Zortec C/C++ compilers.

pm
==

   The pm terminal driver provides an OS/2 Presentation Manager window in
which the graph is plotted.  The window is opened when the first graph is
plotted.  This window has its own online help as well as facilities for
printing, copying to the clipboard and some line type and color
adjustments.  The `multiplot' option is supported.

   Syntax:

     set terminal pm {server {n}} {persist} {widelines} {enhanced} {"title"}

   If `persist' is specified, each graph appears in its own window and all
windows remain open after gnuplot exits.  If server is specified, all
graphs appear in the same window, which remains open when gnuplot exits.
This option takes an optional numerical argument which specifies an
instance of the server process.  Thus multiple server windows can be in
use at the same time.

   If `widelines' is specified, all plots will be drawn with wide lines.
If `enhanced' is specified, sub- and superscripts and multiple fonts are
enabled using the same syntax as the enhanced postscript option (see `set
terminal postscript enhanced' for details).  Font names for the basic
PostScript fonts may be abbreviated to single letters.

   If title is specified, it will be used as the title of the plot window.
It will also be used as the name of the server instance, and will override
the optional numerical argument.

   Linewidths may be changed with `set linestyle'.

png
===

   The png terminal driver supports Portable Network Graphics.  To compile
it, you will need  the third-party libraries "libpng" and "zlib"; both are
available at ftp://ftp.uu.net/graphics/png.  png has two options.

   Syntax:

     set terminal png {small | medium | large}
                      {monochrome | gray | color}

   The defaults are small (fontsize) and monochrome.

postscript
==========

   Several options may be set in the postscript driver.

   Syntax:

     set terminal postscript {<mode>} {enhanced | noenhanced}
                             {color | monochrome} {solid | dashed}
                             {<duplexing>}
                             {"<fontname>"} {<fontsize>}

   where <mode> is `landscape', `portrait', `eps' or default; solid draws
all plots with solid lines, overriding any dashed patterns; <duplexing> is
`defaultplex', simplex or `duplex' ("duplexing" in PostScript is the
ability of the printer to print on both sides of the same page--don't set
this if your printer can't do it); `enhanced' activates the "enhanced
PostScript" features (subscripts, superscripts and mixed fonts);
`"<fontname'"> is the name of a valid PostScript font; and `<fontsize'> is
the size of the font in PostScript points.

   default mode sets all options to their defaults: `landscape',
`monochrome', `dashed', `defaultplex', `noenhanced', "Helvetica" and 14pt.

     Default size of a PostScript plot is 10 inches wide and 7 inches high.

   `eps' mode generates EPS (Encapsulated PostScript) output, which is just
regular PostScript with some additional lines that allow the file to be
imported into a variety of other applications.  (The added lines are
PostScript comment lines, so the file may still be printed by itself.)  To
get EPS output, use the `eps' mode and make only one plot per file.  In
`eps' mode the whole plot, including the fonts, is reduced to half of the
default size.

   Examples:

     set terminal postscript default       # old postscript
     set terminal postscript enhanced      # old enhpost
     set terminal postscript landscape 22  # old psbig
     set terminal postscript eps 14        # old epsf1
     set terminal postscript eps 22        # old epsf2
     set size 0.7,1.4; set term post portrait color "Times-Roman" 14

   Linewidths and pointsizes may be changed with `set linestyle'.

   The postscript driver supports about 70 distinct pointtypes, selectable
through the `pointtype' option on plot and `set linestyle'.

   Several possibly useful files about gnuplot's PostScript are included
in the /docs/ps subdirectory of the gnuplot distribution and at the
distribution sites.  These are "ps_symbols.gpi" (a gnuplot command file
that, when executed, creates the file "ps_symbols.ps" which shows all the
symbols available through the postscript terminal), "ps_guide.ps" (a
PostScript file that contains a summary of the enhanced syntax and a page
showing what the octal codes produce with text and symbol fonts) and
"ps_file.doc" (a text file that contains a discussion of the organization
of a PostScript file written by gnuplot).

   A PostScript file is editable, so once gnuplot has created one, you are
free to modify it to your heart's desire.  See the "editing postscript"
section for some hints.

enhanced postscript
-------------------

     Control      Examples        Explanation
      ^           a^x             superscript
      _           a_x             subscript
      @           @x or a@^b_c    phantom box (occupies no width)
      &           &{space}        inserts space of specified length

   Braces can be used to place multiple-character text where a single
character is expected (e.g., 2^{10}).  To change the font and/or size, use
the full form:  {/[fontname][=fontsize | *fontscale] text}.  Thus
{/Symbol=20 G} is a 20-point GAMMA) and {/*0.75 K} is a K at
three-quarters of whatever fontsize is currently in effect.  (The '/'
character MUST be the first character after the '{'.)

   If the encoding vector has been changed by `set encoding', the default
encoding vector can be used instead by following the slash with a dash.
This is unnecessary if you use the Symbol font, however--since /Symbol
uses its own encoding vector, gnuplot will not apply any other encoding
vector to it.

   The phantom box is useful for a@^b_c to align superscripts and
subscripts but does not work well for overwriting an accent on a letter.
(To do the latter, it is much better to use `set encoding iso_8859_1' to
change to the ISO Latin-1 encoding vector, which contains a large variety
of letters with accents or other diacritical marks.)  Since the box is
non-spacing, it is sensible to put the shorter of the subscript or
superscript in the box (that is, after the @).

   Space equal in length to a string can be inserted using the '&'
character.  Thus

     'abc&{def}ghi'

   would produce

     'abc   ghi'.

   You can access special symbols numerically by specifying
\character-code (in octal), e.g., {/Symbol \245} is the symbol for
infinity.

   You can escape control characters using \, e.g.,  \\, \{, and so on.

   But be aware that strings in double-quotes are parsed differently than
those enclosed in single-quotes.  The major difference is that backslashes
may need to be doubled when in double-quoted strings.

   Examples (these are hard to describe in words--try them!):

     set xlabel 'Time (10^6 {/Symbol m}s)'
     set title '{/Symbol=18 \362@_{/=9.6 0}^{/=12 x}} \
                {/Helvetica e^{-{/Symbol m}^2/2} d}{/Symbol m}'

   The file "ps_guide.ps" in the /docs/ps subdirectory of the gnuplot
source distribution contains more examples of the enhanced syntax.

editing postscript
------------------

   The PostScript language is a very complex language--far too complex to
describe in any detail in this document.  Nevertheless there are some
things in a PostScript file written by gnuplot that can be changed without
risk of introducing fatal errors into the file.

   For example, the PostScript statement "/Color true def" (written into
the file in response to the command `set terminal postscript color'), may
be altered in an obvious way to generate a black-and-white version of a
plot.  Similarly line colors, text colors, line weights and symbol sizes
can also be altered in straight-forward ways.  Text (titles and labels)
can be edited to correct misspellings or to change fonts.  Anything can be
repositioned, and of course anything can be added or deleted, but
modifications such as these may require deeper knowledge of the PostScript
language.

   The organization of a PostScript file written by gnuplot is discussed in
the text file "ps_file.doc" in the /docs/ps subdirectory.

pslatex and pstex
=================

   The `pslatex' and `pstex' drivers generate output for further
processing by LaTeX and TeX, respectively.  Figures generated by `pstex'
can be included in any plain-based format (including LaTeX).

   Syntax:

     set terminal pslatex | |pstex {<color>} {<dashed>} {<rotate>}
                                   {auxfile} {<font_size>}

   <color> is either color or `monochrome'.  <rotate> is either rotate or
`norotate' and determines if the y-axis label is rotated.  <font_size> is
used to scale the font from its usual size.

   If `auxfile' is specified, it directs the driver to put the PostScript
commands into an auxiliary file instead of directly into the LaTeX file.
This is useful if your pictures are large enough that dvips cannot handle
them.  The name of the auxiliary PostScript file is derived from the name
of the TeX file given on the `set output' command; it is determined by
replacing the trailing `.tex' (actually just the final extent in the file
name--and the option will be turned off if there is no extent) with `.ps'
in the output file name.  Remember to close the file before leaving
gnuplot.

   All drivers for LaTeX offer a special way of controlling text
positioning: If any text string begins with '{', you also need to include
a '}' at the end of the text, and the whole text will be centered both
horizontally and vertically by LaTeX. -- If the text string begins with
'[', you need to continue it with: a position specification (up to two out
of t,b,l,r), ']{', the text itself, and finally, '}'. The text itself may
be anything LaTeX can typeset as an LR-box. \rule{}{}'s may help for best
positioning.

   Examples:

     set term pslatex monochrome dashed rotate       # set to defaults

   To write the PostScript commands into the file "foo.ps":

     set term pslatex auxfile
     set output "foo.tex"; plot ...: set output

   About label positioning: Use gnuplot defaults (mostly sensible, but
sometimes not really best):

     set title '\LaTeX\ -- $ \gamma $'

   Force centering both horizontally and vertically:

     set label '{\LaTeX\ -- $ \gamma $}' at 0,0

   Specify own positioning (top here):

     set xlabel '[t]{\LaTeX\ -- $ \gamma $}'

   The other label - account for long ticlabels:

     set ylabel '[r]{\LaTeX\ -- $ \gamma $\rule{7mm}{0pt}'

   Linewidths and pointsizes may be changed with `set linestyle'.

pstricks
========

   The pstricks driver is intended for use with the "pstricks.sty" macro
package for LaTeX.  It is an alternative to the eepic and latex drivers.
You need "pstricks.sty", and, of course, a printer that understands
PostScript, or a converter such as Ghostscript.

   PSTricks is available via anonymous ftp from the /pub directory at
Princeton.EDU.  This driver definitely does not come close to using the
full capability of the PSTricks package.

   Syntax:

     set terminal pstricks {hacktext | nohacktext} {unit | nounit}

   The first option invokes an ugly hack that gives nicer numbers; the
second has to do with plot scaling.  The defaults are `hacktext' and
`nounit'.

qms
===

   The qms terminal driver supports the QMS/QUIC Laser printer, the Talaris
1200 and others.  It has no options.

regis
=====

   The regis terminal device generates output in the REGIS graphics
language.  It has the option of using 4 (the default) or 16 colors.

   Syntax:

     set terminal regis {4 | 16}

rgip
====

   The rgip and `uniplex' terminal drivers support RGIP metafiles.  They
can combine several graphs on a single page, but only one page is allowed
in a given output file.

   Syntax:

     set terminal rgip | uniplex {portrait | landscape}
                                 {[<horiz>,<vert>]} {<fontsize>}

   permissible values for the font size are in the range 1-8, with the
default being 1.  The default layout is landscape.  Graphs are placed on
the page in a `horiz'x`vert' grid, which defaults to [1,1].

   Example:

     set terminal uniplex portrait [2,3]

   puts six graphs on a page in three rows of two in portrait orientation.

sun
===

   The sun terminal driver supports the SunView window system.  It has no
options.

tek410x
=======

   The tek410x terminal driver supports the 410x and 420x family of
Tektronix terminals.  It has no options.

table
=====

   Instead of producing a graph, the table terminal prints out the points
on which a graph would be based, i.e., the results of processing the plot
or `splot' command, in a multicolumn ASCII table of X Y {Z} R values.  The
character R takes on one of three values: "i" if the point is in the active
range, "o" if it is out-of-range, or "u" if it is undefined.  The data
format is determined by the format of the axis labels (see `set format').

   For those times when you want the numbers, you can display them on the
screen or save them to a file.  This can be useful if you want to generate
contours and then save them for further use, perhaps for plotting with
plot;  see `set contour' for an example.  The same method can be used to
save interpolated data (see `set samples' and `set dgrid3d').

tek40
=====

   This family of terminal drivers supports a variety of VT-like terminals.
`tek40xx' supports Tektronix 4010 and others as well as most TEK emulators;
`vttek' supports VT-like tek40xx terminal emulators; `kc-tek40xx' supports
MS-DOS Kermit Tek4010 terminal emulators in color: `km-tek40xx' supports
them in monochrome; `selanar' supports Selanar graphics; and `bitgraph'
supports BBN Bitgraph terminals.  None have any options.

texdraw
=======

   The texdraw terminal driver supports the LaTeX texdraw environment.  It
is intended for use with "texdraw.sty" and "texdraw.tex" in the texdraw
package.

   It has no options.

tgif
====

   Tgif is an X11-based drawing tool--it has nothing to do with GIF.

   The tgif driver supports different pointsizes (with `set pointsize'),
different label fonts and font sizes (e.g. `set label "Hallo" at x,y font
"Helvetica,34"') and multiple graphs on the page.  The proportions of the
axes are not changed.

   Syntax:

     set terminal tgif {portrait | landscape} {<[x,y]>}
                       {solid | dashed}
                       {"<fontname>"} {<fontsize>}

   where <[x,y]> specifies the number of graphs in the x and y directions
on the page, "<fontname>" is the name of a valid PostScript font, and
<fontsize> specifies the size of the PostScript font.  Defaults are
`portrait', `[1,1]', `dashed', `"Helvetica"', and 18.

   The solid option is usually prefered if lines are colored, as they often
are in the editor.  Hardcopy will be black-and-white, so `dashed' should be
chosen for that.

   Multiplot is implemented in two different ways.

   The first multiplot implementation is the standard gnuplot multiplot
feature:

     set terminal tgif
     set output "file.obj"
     set multiplot
     set origin x01,y01
     set size  xs,ys
     plot ...
          ...
     set origin x02,y02
     plot ...
     set nomultiplot

   See `set multiplot' for further information.

   The second version is the [x,y] option for the driver itself.  The
advantage of this implementation is that everything is scaled and placed
automatically without the need for setting origins and sizes; the graphs
keep their natural x/y proportions of 3/2 (or whatever is fixed by `set
size').

   If both multiplot methods are selected, the standard method is chosen
and a warning message is given.

   Examples of single plots (or standard multiplot):

     set terminal tgif                  # defaults
     set terminal tgif "Times-Roman" 24
     set terminal tgif landscape
     set terminal tgif landscape solid

   Examples using the built-in multiplot mechanism:

     set terminal tgif portrait [2,4]  # portrait; 2 plots in the x-
                                       # and 4 in the y-direction
     set terminal tgif [1,2]           # portrait; 1 plot in the x-
                                       # and 2 in the y-direction
     set terminal tgif landscape [3,3] # landscape; 3 plots in both
                                       # directions

tkcanvas
========

   This terminal driver generates tk canvas widget commands.  To use it,
rebuild gnuplot (after uncommenting or inserting the appropriate line in
"term.h"), then

     gnuplot> set term tkcanvas
     gnuplot> set output 'plot.file'

   After invoking "wish", execute the following sequence of tcl commands:

     % source plot.file
     % canvas .c
     % pack .c
     % gnuplot .c

   The code generated by gnuplot creates a tcl procedure called "gnuplot"
that takes the name of a canvas as its argument.  When the procedure is,
called, it clears the canvas, finds the size of the canvas and draws the
plot in it, scaled to fit.

   The current version of tkcanvas supports neither `multiplot' nor
`replot'.

tpic
====

   The tpic terminal driver supports the LaTeX picture environment with
tpic \specials.  It is an alternative to the latex and eepic terminal
drivers.  Options are the point size, line width, and dot-dash interval.

   Syntax:

     set terminal tpic <pointsize> <linewidth> <interval>

   where `pointsize' and linewidth are integers in milli-inches and
interval is a float in inches.  If a non-positive value is specified, the
default is chosen: pointsize = 40, linewidth = 6, interval = 0.1.

   All drivers for LaTeX offer a special way of controlling text
positioning: If any text string begins with '{', you also need to include
a '}' at the end of the text, and the whole text will be centered both
horizontally and vertically by LaTeX. -- If the text string begins with
'[', you need to continue it with: a position specification (up to two out
of t,b,l,r), ']{', the text itself, and finally, '}'. The text itself may
be anything LaTeX can typeset as an LR-box. \rule{}{}'s may help for best
positioning.

   Examples: About label positioning: Use gnuplot defaults (mostly
sensible, but sometimes not really best):

     set title '\LaTeX\ -- $ \gamma $'

   Force centering both horizontally and vertically:

     set label '{\LaTeX\ -- $ \gamma $}' at 0,0

   Specify own positioning (top here):

     set xlabel '[t]{\LaTeX\ -- $ \gamma $}'

   The other label - account for long ticlabels:

     set ylabel '[r]{\LaTeX\ -- $ \gamma $\rule{7mm}{0pt}'

unixpc
======

   The unixpc terminal driver supports AT&T 3b1 and AT&T 7300 Unix PC.  It
has no options.

unixplot
========

   The unixplot terminal driver generates output in the Unix "plot"
graphics language.  It has no options.

   This terminal cannot be compiled if the GNU version of plot is to be
used; in that case, use the `gnugraph' terminal instead.

vx384
=====

   The vx384 terminal driver supports the Vectrix 384 and Tandy color
printers.  It has no options.

VWS
===

   The VWS terminal driver supports the VAX Windowing System.  It has no
options.  It will sense the display type (monochrome, gray scale, or
color.)  All line styles are plotted as solid lines.

windows
=======

   Three options may be set in the windows terminal driver.

   Syntax:

     set terminal windows {<color>} {"<fontname>"} {<fontsize>}

   where `<color'> is either color or `monochrome', `"<fontname'"> is the
name of a valid Windows font, and `<fontsize'> is the size of the font in
points.

   Other options may be set with the graph-menu, the initialization file,
and `set linestyle'.

   The Windows version normally terminates immediately as soon as the end
of any files given as command line arguments is reached (i.e. in
non-interactive mode). It will also not show the text-window at all, in
this mode, only the plot. By giving the optional argument `/noend' or
`-noend', you can disable this behaviour.

graph-menu
----------

   The `gnuplot graph' window has the following options on a pop-up menu
accessed by pressing the right mouse button or selecting Options from the
system menu:

   `Bring to Top' when checked brings the graph window to the top after
every plot.

   Color when checked enables color linestyles.  When unchecked it forces
monochrome linestyles.

   `Copy to Clipboard' copies a bitmap and a Metafile picture.

   `Background...' sets the window background color.

   `Choose Font...' selects the font used in the graphics window.

   `Line Styles...' allows customization of the line colors and styles.

   `Print...' prints the graphics windows using a Windows printer driver
and allows selection of the printer and scaling of the output.  The output
produced by Print is not as good as that from gnuplot's own printer
drivers.

   `Update wgnuplot.ini' saves the current window locations, window sizes,
text window font, text window font size, graph window font, graph window
font size, background color and linestyles to the initialization file
`WGNUPLOT.INI'.

printing
--------

   In order of preference, graphs may be be printed in the following ways.

   1. Use the gnuplot command `set terminal' to select a printer and `set
output' to redirect output to a file.

   2. Select the `Print...' command from the `gnuplot graph' window.  An
extra command `screendump' does this from the text window.

   3. If `set output "PRN"' is used, output will go to a temporary file.
When you exit from gnuplot or when you change the output with another `set
output' command, a dialog box will appear for you to select a printer port.
If you choose OK, the output will be printed on the selected port, passing
unmodified through the print manager.  It is possible to accidentally (or
deliberately) send printer output meant for one printer to an incompatible
printer.

text-menu
---------

   The `gnuplot text' window has the following options on a pop-up menu
accessed by pressing the right mouse button or selecting Options from the
system menu:

   `Copy to Clipboard' copies marked text to the clipboard.

   Paste copies text from the clipboard as if typed by the user.

   `Choose Font...' selects the font used in the text window.

   `System Colors' when selected makes the text window honor the System
Colors set using the Control Panel.  When unselected, text is black or
blue on a white background.

   `Update wgnuplot.ini' saves the current text window location, text
window size, text window font and text window font size to the
initialisation file `WGNUPLOT.INI'.

   `MENU BAR'

   If the menu file `WGNUPLOT.MNU' is found in the same directory as
WGNUPLOT.EXE, then the menu specified in `WGNUPLOT.MNU' will be loaded.
Menu commands:

   [Menu] starts a new menu with the name on the following line.

   [EndMenu] ends the current menu.

   [-] inserts a horizontal menu separator.

   [|] inserts a vertical menu separator.

   [Button] puts the next macro on a push button instead of a menu.

   Macros take two lines with the macro name (menu entry) on the first
line and the macro on the second line.  Leading spaces are ignored.  Macro
commands:

   [INPUT] -- Input string with prompt terminated by [EOS] or {ENTER}

   [EOS] -- End Of String terminator.  Generates no output.

   [OPEN] -- Get name of file to open from list box, with title of list box
terminated by [EOS], followed by default filename terminated by [EOS] or
{ENTER}.  This uses COMMDLG.DLL from Windows 3.1.

   [SAVE] -- Get name of file to save.  Similar to [OPEN]

   Macro character substitutions:

   {ENTER} -- Carriage Return '\r'

   {TAB} -- Tab '\011'

   {ESC} -- Escape '\033'

   {^A} -- '\001'

   ...

   {^_} -- '\031'

   Macros are limited to 256 characters after expansion.

wgnuplot.ini
------------

   Windows gnuplot will read some of its options from the `[WGNUPLOT]'
section of `WGNUPLOT.INI' in the Windows directory.  A sample
`WGNUPLOT.INI' file:

     [WGNUPLOT]
     TextOrigin=0 0
     TextSize=640 150
     TextFont=Terminal,9
     GraphOrigin=0 150
     GraphSize=640 330
     GraphFont=Arial,10
     GraphColor=1
     GraphToTop=1
     GraphBackground=255 255 255
     Border=0 0 0 0 0
     Axis=192 192 192 2 2
     Line1=0 0 255 0 0
     Line2=0 255 0 0 1
     Line3=255 0 0 0 2
     Line4=255 0 255 0 3
     Line5=0 0 128 0 4

   The `GraphFont' entry specifies the font name and size in points.  The
five numbers given in the Border, Axis and Line entries are the `Red'
intensity (0-255), `Green' intensity, `Blue' intensity, `Color Linestyle'
and `Mono Linestyle'.  `Linestyles' are 0=SOLID, 1=DASH, 2=DOT, 3=DASHDOT,
4=DASHDOTDOT.  In the sample `WGNUPLOT.INI' file above, Line 2 is a green
solid line in color mode, or a dashed line in monochrome mode.  The default
line width is 1 pixel.  If `Linestyle' is negative, it specifies the width
of a SOLID line in pixels.  Line1 and any linestyle used with the points
style must be SOLID with unit width.

windows3.0
----------

   Windows 3.1 is preferred, but WGNUPLOT will run under Windows 3.0 with
the following restrictions: 1. COMMDLG.DLL and SHELL.DLL (available with
Windows 3.1 or Borland C++ 3.1) must be in the windows directory.

   2. WGNUPLOT.HLP produced by Borland C++ 3.1 is in Windows 3.1 format.
You need to use the WINHELP.EXE supplied with Borland C++ 3.1.

   3. It will not run in real mode due to lack of memory.

   4. TrueType fonts are not available in the graph window.

   5. Drag-drop does not work.

x11
===

   gnuplot provides the x11 terminal type for use with X servers.  This
terminal type is set automatically at startup if the DISPLAY environment
variable is set, if the TERM environment variable is set to `xterm', or if
the `-display' command line option is used.

   Syntax:

     set terminal x11 {reset} {<n>}

   Multiple plot windows are supported: `set terminal x11 <n'> directs the
output to plot window number n.  If n>0, the terminal number will be
appended to the window title and the icon will be labeled `gplt <n'>.  The
active window may distinguished by a change in cursor (from default to
crosshair.)

   Plot windows remain open even when the gnuplot driver is changed to a
different device.  A plot window can be closed by pressing the letter q
while that window has input focus, or by choosing close from a window
manager menu.  All plot windows can be closed by specifying reset, which
actually terminates the subprocess which maintains the windows (unless
`-persist' was specified).

   Plot windows will automatically be closed at the end of the session
unless the `-persist' option was given.

   The size or aspect ratio of a plot may be changed by resizing the
gnuplot window.

   Linewidths and pointsizes may be changed from within gnuplot with `set
linestyle'.

   For terminal type x11, gnuplot accepts (when initialized) the standard
X Toolkit options and resources such as geometry, font, and name from the
command line arguments or a configuration file.  See the X(1) man page (or
its equivalent) for a description of such options.

   A number of other gnuplot options are available for the x11 terminal.
These may be specified either as command-line options when gnuplot is
invoked or as resources in the configuration file "/.Xdefaults".  They are
set upon initialization and cannot be altered during a gnuplot session.

command-line_options
--------------------

   In addition to the X Toolkit options, the following options may be
specified on the command line when starting gnuplot or as resources in your
".Xdefaults" file:

     `-clear`   requests that the window be cleared momentarily before a
                new plot is displayed.
     `-gray`    requests grayscale rendering on grayscale or color displays.
                (Grayscale displays receive monochrome rendering by default.)
     `-mono`    forces monochrome rendering on color displays.
     `-persist` plot windows survive after main gnuplot program exits
     `-raise`   raise plot window after each plot
     `-noraise` do not raise plot window after each plot
     `-tvtwm`   requests that geometry specifications for position of the
                window be made relative to the currently displayed portion
                of the virtual root.

   The options are shown above in their command-line syntax.  When entered
as resources in ".Xdefaults", they require a different syntax.

   Example:

     gnuplot*gray: on

   gnuplot also provides a command line option (`-pointsize <v'>) and a
resource, `gnuplot*pointsize: <v'>, to control the size of points plotted
with the points plotting style.  The value v is a real number (greater
than 0 and less than or equal to ten) used as a scaling factor for point
sizes.  For example, `-pointsize 2' uses points twice the default size, and
`-pointsize 0.5' uses points half the normal size.

monochome_options
-----------------

   For monochrome displays, gnuplot does not honor foreground or background
colors.  The default is black-on-white.  `-rv' or `gnuplot*reverseVideo:
on' requests white-on-black.

color_resources
---------------

   For color displays, gnuplot honors the following resources (shown here
with their default values) or the greyscale resources.  The values may be
color names as listed in the X11 rgb.txt file on your system, hexadecimal
RGB color specifications (see X11 documentation), or a color name followed
by a comma and an `intensity' value from 0 to 1.  For example, `blue, 0.5'
means a half intensity blue.

     gnuplot*background:  white
     gnuplot*textColor:   black
     gnuplot*borderColor: black
     gnuplot*axisColor:   black
     gnuplot*line1Color:  red
     gnuplot*line2Color:  green
     gnuplot*line3Color:  blue
     gnuplot*line4Color:  magenta
     gnuplot*line5Color:  cyan
     gnuplot*line6Color:  sienna
     gnuplot*line7Color:  orange
     gnuplot*line8Color:  coral

   The command-line syntax for these is, for example,

   Example:

     gnuplot -background coral

grayscale_resources
-------------------

   When `-gray' is selected, gnuplot honors the following resources for
grayscale or color displays (shown here with their default values).  Note
that the default background is black.

     gnuplot*background: black
     gnuplot*textGray:   white
     gnuplot*borderGray: gray50
     gnuplot*axisGray:   gray50
     gnuplot*line1Gray:  gray100
     gnuplot*line2Gray:  gray60
     gnuplot*line3Gray:  gray80
     gnuplot*line4Gray:  gray40
     gnuplot*line5Gray:  gray90
     gnuplot*line6Gray:  gray50
     gnuplot*line7Gray:  gray70
     gnuplot*line8Gray:  gray30

line_resources
--------------

   gnuplot honors the following resources for setting the width (in
pixels) of plot lines (shown here with their default values.)  0 or 1
means a minimal width line of 1 pixel width.  A value of 2 or 3 may
improve the appearance of some plots.

     gnuplot*borderWidth: 2
     gnuplot*axisWidth:   0
     gnuplot*line1Width:  0
     gnuplot*line2Width:  0
     gnuplot*line3Width:  0
     gnuplot*line4Width:  0
     gnuplot*line5Width:  0
     gnuplot*line6Width:  0
     gnuplot*line7Width:  0
     gnuplot*line8Width:  0

   gnuplot honors the following resources for setting the dash style used
for plotting lines.  0 means a solid line.  A two-digit number `jk' (`j'
and k are >= 1  and <= 9) means a dashed line with a repeated pattern of
`j' pixels on followed by k pixels off.  For example, '16' is a "dotted"
line with one pixel on followed by six pixels off.  More elaborate on/off
patterns can be specified with a four-digit value.  For example, '4441' is
four on, four off, four on, one off.  The default values shown below are
for monochrome displays or monochrome rendering on color or grayscale
displays.  For color displays, the default for each is 0 (solid line)
except for `axisDashes' which defaults to a '16' dotted line.

     gnuplot*borderDashes:   0
     gnuplot*axisDashes:    16
     gnuplot*line1Dashes:    0
     gnuplot*line2Dashes:   42
     gnuplot*line3Dashes:   13
     gnuplot*line4Dashes:   44
     gnuplot*line5Dashes:   15
     gnuplot*line6Dashes: 4441
     gnuplot*line7Dashes:   42
     gnuplot*line8Dashes:   13

xlib
====

   The xlib terminal driver supports the X11 Windows System.  It generates
gnulib_x11 commands.  `set term x11' behaves similarly to `set terminal
xlib; set output "|gnuplot_x11"'.  xlib has no options, but see x11.

AUTHOR
======

   Autogenerated from `*.trm' files in gnuplot terminals subdirectory.

SEE ALSO
========

   See Term/Gnuplot.

Perl extension to display a progress bar
****************************************

NAME
====

   Term::ProgressBar - Perl extension to display a progress bar

SYNOPSIS
========

     use Term::ProgressBar;
     my $num_items = 100;
     my $bar = new Term::Progressbar('working magic', $num_items);
     foreach (0 .. $num_items-1) {
         # do work for item $_
         update $bar;
     }

DESCRIPTION
===========

   This module provides a simple progress indicator for command line
programs.  You initialize a ProgressBar object with a brief description of
what is happening and the number of things that need doing, and after each
thing is done you call the object's update() method.

   At the moment, this is presented to the user (on stderr) as a sequence
of 50 hash marks (no matter how many things are being done).

METHODS
=======

`new(desc, num_items)'
     Create and return a new progress bar, which is displayed to the user.
     Parameters are:

    desc - descriptive name of what you're doing (eg 'working magic')
    `num_items' - total number of items which must be completed
update()
     Update the progress bar by one 'tick'.  You should call this after
     completing each one of the 'items' included in the counter's total.
     The progress bar will be updated accordingly (at present, this means
     more text printed to stderr).

AUTHOR
======

   Ed Avis, epa98@doc.ic.ac.uk

SEE ALSO
========

   perl(1).

Perl extension for prompting a user for information
***************************************************

NAME
====

   Term::Prompt - Perl extension for prompting a user for information

SYNOPSIS
========

     use Term::Prompt;
     $value = &prompt(...);

     use Term::Prompt qw(termwrap);

     print &termwrap(...);

DESCRIPTION
===========

     This perl routine will take a prompt, a default response and a list of
     possible responses and deal with the user interface, (and the user!),
     by displaying the prompt, showing the default, and checking to be sure
     that the response is one of the legal choices.
     --Mark Henderson

     Derived from im_prompt2.pl, from anlpasswd (see
     ftp://info.mcs.anl.gov/pub/systems/), with permission. Revisions for Perl 5,
     addition of alternative help text presentation, addition of floating point
     type, addition of regular expression type, addition of yes/no type, and line
     wrapping by E. Allen Smith.

     Additional "types" that could be added would be a phone type,
     a social security type, a generic numeric pattern type...

     The usage is the following:
     x = don't care, a = alpha-only, n = numeric-only, i = ignore case
     c = case sensitive, r = ranged by the low and high values
     f = floating-point, y = yes/no, e = regular expression - Added by Allen

     $result = &prompt("x", "text prompt", "help prompt", "default" );

     $result = &prompt("a", "text prompt", "help prompt", "default" );

     $result = &prompt("n", "text prompt", "help prompt", "default" );

     The result will be a positive integer or 0.

     $result = &prompt("i", "text prompt", "help prompt", "default",
     	                 "legal_options-ignore-case-list");

     $result = &prompt("c", "text prompt", "help prompt", "default",
     	                 "legal_options-case-sensitive-list");

     $result = &prompt("r", "text prompt", "help prompt", "default",
                           "low", "high");

     $result = &prompt("f", "text prompt", "help prompt", "default");

     The result will be a floating-point number.

     $result = &prompt("y", "text prompt", "help prompt", "default")

     The result will be 1 for y, 0 for n. A default not starting with y or n
     (or the uc versions of these) will be treated as y for positive, n for
     negative.

     $result = &prompt("e", "text prompt", "help prompt", "default",
                           "regular expression");

     The regular expression for the last has ^ and $ surrounding it automatically;
     just put in .* before or after if you need to free it up before or
     after. - Allen

     What, you might ask, is the difference between a "text prompt" and a
     "help prompt"?  Think about the case where the "legal_options" look
     something like: "1-1000".  Now consider what happens when you tell someone
     that "0" is not between 1-1000 and that the possible choices are:  :)
     1 2 3 4 5 .....
     This is what the "help prompt" is for.

     It will work off of unique parts of "legal_options".

     Changed by Allen - it will be treated as a true "help prompt" if you
     capitalize the type of prompt, and otherwise will be treated as a list of
     options. Capitalizing the type of prompt will also mean that a return may be
     accepted as a response, even if there is no default; whether it actually is
     will depend on the type of prompt.

Other Functions
---------------

   Part of Term::Prompt is the optionally exported function termwrap,
which is used to wrap lines to the width of the currently selected
filehandle (or to STDOUT or STDERR if the width of the current filehandle
cannot be determined).  It uses the GetTerminalSize function from
Term::ReadKey then Text::Wrap.

AUTHOR
======

   Mark Henderson (henderson@mcs.anl.gov or systems@mcs.anl.gov) Primary
contact author: Allen Smith (easmith@beatrice.rutgers.edu)

SEE ALSO
========

   See Perl (perl.info), Term/ReadKey, and
Text/Wrap.

Table-driven query routine.
***************************

NAME
====

   *Term::Query* - Table-driven query routine.

SYNOPSIS
========

`use *Term::Query*'
     `qw( *query* *query_table* query_table_set_defaults
     query_table_process );'

   `$result = *query* $prompt, $flags, [ $*optional_args* ];'

   `$*ok* = *query_table* \@array;'

   `*query_table_set_defaults* \@array;'

   `$*ok* = *query_table_process* \@array, \&flagsub, \&querysub;'

DESCRIPTION
===========

query
-----

   The query subroutine fulfills the need for a generalized
question-response subroutine, with programmatic defaulting, validation,
condition and error checking.

   Given *$prompt* and $flags, and possibly additional arguments,
depending upon the characters in $flags, query issues a prompt to STDOUT
and solicits input from STDIN.  The input is validated against a set of
test criteria as configured by the characters in $flags; if any of the
tests fail, an error message is noted, and the query is reattempted.

   When STDIN is not a tty (not interactive), prompts are not issued, and
errors cause a return rather than attempting to obtain more input.  This
non-interactive behaviour can be disabled by setting the variable
`$Foce_Interactive' as below:

     $Term::Query::Force_Interactive = 1;

   When `$Force_Interactive' is a non-null, non-zero value, query will
issue prompts, error messages, and ask for additional input even when the
input is not interactive.

query_table
-----------

   The query_table subroutine performs multiple queries, by invoking
query, setting associated variables with the results of each query.
Prompts, flags, and other arguments for each query are given in an array,
called a *query table*, which is passed to the query_table subroutine by
reference.

query_table_set_defaults
------------------------

   The query_table_set_defaults subroutine causes any variables named in
the given *query table* array to be assigned their corresponding default
values, if any.  This is a non-interactive subroutine.

query_table_process
-------------------

   A general interface to processing a *query table* is available with the
query_table_process subroutine.  It accepts a *query table* array, and two
subroutine references, a *&flagsub* and a *&querysub*.  The *&flagsub* is
invoked on each each flag character given in the $flags argument of the
*query table* (see below).  The *&querysub* is invoked for each query in
the *query table*.

   The query_table and query_table_set_defaults subroutines both use
query_table_process to perform their functions.

Query Table
-----------

   The format of the *query table* array passed to query_table,
query_table_set_defaults, and query_table_process subroutines is:

     @array = ( $prompt1, $flags1, [ $arglist1, ... ],
                $prompt2, $flags2, [ $arglist2, ... ],
     	    ...
     	    $promptN, $flagsN, [ $arglistN, ... ] );

   In English, there are three items per query: a prompt string, a flags
string, and an array of arguments.  Note that the syntax used above uses
`[ ... ]' to denote a Perl 5 anonymous array, not an optional set of
arguments.  Of course, if there are no arguments for a particular query,
the corresponding anonymous array can be the null string or zero.

   The query table design is such that a query table can be created with a
set of variables, their defaults, value constraints, and help strings, and
it can be used to both initialize the variables' values and to
interactively set their new values.  The query_table_set_defaults
subroutine performs the former, while query_table does the latter.

Flag Characters
---------------

   With typical usage, given *$prompt* and $flags, query prints *$prompt*
and then waits for input from the user.  The handling of the response
depends upon the flag characters given in the $flags string.

   The flag characters indicate the type of input, how to process it,
acceptable values, etc.  Some flags simply indicate the type or processing
of the input, and do not require additional arguments.  Other flags
require that subsequent arguments to the query subroutine be given.  The
arguments must be given in the same order as their corresponding flag
characters.

   The ordering of the flags in the $flags argument is important - it
determines the ordering of the tests.  For example, if both the a and m
flags are given as `"am"', then this indicates that an after subroutine
call should be performed first, followed by a regular expression match
test.

   All tests are applied in the order given in the $flags until a
particular test fails.  When a test fails, an error message is generated
and the input is reattempted, except in the case of the I flag.

Flag Characters Without Arguments
---------------------------------

i
     The input must be an integer.

n
     The input must be a number, real or integer.

Y
     The input is a `"yes"' or "no", with a default answer of `"yes"'.

N
     The input is a `"yes"' or "no", with a default answer of "no".

r
     Some input is required; an empty response will be refused.  This
     option is only meaningful when there is no default input (see the d
     flag character below).

s
     Strip and squeeze the input.  Leading and trailing blanks are
     eliminated, and embedded whitespace is "squeezed" to single blank
     characters.  This flag is implied by the k and K flags.

H
     Do not treat input of ? as a request for help.  This disables
     automatic help, unless implemented with the after (a flag) subroutine.

Flag Characters With Arguments
------------------------------

   The following flag characters indicate the presence of an argument to
query.  The arguments must occur in the same order as their corresponding
flag characters.  For example, if both the V and h flags are given as
`"Vh"', then the first argument must be the variable name, and the next
the help string, in that order.

a *\&after*
     The next argument is the after subroutine, to be invoked after the
     input has been solicited.  This feature provides for an "open ended"
     input validation, completely at the control of the user of the Query
     module.    The after subroutine is invoked in this manner:

          &$after( \$input );

     If the after sub returns an undef, then query processing stops with
     an immediate undef return value.

     If the after sub returns a null or zero value, then the input is
     rejected and resolicted.  No error messages are displayed except the
     "Please try again." message.

     Since the after sub has the reference to the *$input* variable, it is
     free to change the value of input indirectly; ie:

          $$input = $some_new_value;

b *\&before*
     The next argument is the before subroutine, to be invoked before any
     input is attempted.    If the before sub returns a non-null, non-zero
     value, the current query will be attempted.  If a null or zero value
     is returned, the current query will be abandoned, with a null return.

     This feature, used in a *query table*, allows for selective queries to
     be programmed by using before subs on the optional queries.  For
     example, using the following anonymous sub as the b flag argument:

          sub { $> == 0; }

     will cause the corresponding query to only be issued for the root
     user.

     The ordering of the b flag in the $flags argument is unimportant,
     since, by definition, this test is always performed before attempting
     any input.

d *$default*
     The next argument is the default input.  This string is used instead
     of an empty response from the user.  The default value can be a
     scalar value, a reference to a scalar value, or a reference to a
     subroutine, which will be invoked for its result only if a default
     value is needed (no input is given).

h *$help_string*
     The next argument is the *help string*, which is printed in response
     to an input of "?".  In order to enter a ? as actual text, it must be
     prefixed with a backslash: "\".

k *\@array*
     The next argument is a reference to an array of allowable keywords.
     The input is matched against the array elements in a case-insensitive
     manner, with unambiguous abbreviations allowed.  This flag implies the
     s flag.

     The matching can be made case-sensitive by setting the following
     variable prior to the invocation of query:

          $Query::Case_sensitive = 1;

     By default, this variable is null.

K *\@array*
     The next argument is a reference to an array of disallowed keywords In
     this case, for the input to be unacceptable, it must match exactly,
     case-insensitive, one of the array elements.  This flag implies the s
     flag.

     The k option is useful for soliciting new, unique keywords to a
     growing list.  Adding new fields to a database, for example.

     The matching can be made case-sensitive by setting the
     `$Query::Case_sensitive' variable (see above).

l *$maxlen*
     The next argument specifies the maximum length of the input.

m *$regular_expression*
     The next argument specifies a regular expression pattern against which
     the input will be matched.

I $reference
     The next argument is the input: either a simple scalar value, or a
     reference to a value, such as a SCALAR variable reference (eg:
     `\$somevar'), or a CODE reference (eg: `sub {..}').  In any case, the
     resulting value is used as input instead of reading from STDIN.

     If the input returned by the reference does not match other
     constraints, additional input is not attempted.  An error message is
     noted, and an undef return is taken.

     This option is handy for applications which have already acquired the
     input, and wish to use the validation features of query.

     It is also useful to embed a query definition in a *query table* which
     does not actually perform a query, but instead does a variable
     assignment dynamically, using the I reference value.

J $reference
     The next argument is the input reference, as with the I flag, except
     that if the input fails any of the constraints, additional input is
     solicited from the input.  In other words, the J flag sets a
     *one-time* only input reference.  Think of it as *jumping* into the
     query loop with an initial input.

V *variable_name_or_ref*
     The next argument is the variable name or reference to receive the
     validated input as its value.  This option, and its corresponding
     variable name, would normally be present on all entries used with
     query_table in order to retain to the values resulting from each
     query.

     The value can either be a string representing the variable name, or a
     reference to a variable, eg: `\$some_var'.

Details
-------

   The query processing proceeds basically in the same order as defined by
the flags argument, with some exceptions.  For example, the before
subroutine is always performed prior to input.

   There are implicit precedences in the ordering of some of the flag
tests.  Generally, flags have their corresponding tests performed in the
same order as the given flags.  Some flag tests, however, require that
other flags' tests be performed beforehand in order to be effective.  For
example, when given the k flag and an s flag, stripping the input would
only be effective if the strip were done on the input before testing the
input against the keyword table.  In other words, the s flag has
precedence over the k flag.  If the user supplies the flags string as
`"ks"', the effective ordering would still be `"sk"'.

   The table below indicates the precedences of the flag tests:

     Given Flag       Flags With Higher Precedence
     ==========       ================================
     i (int)          s (strip), d (default), h (help)
     k (key)          s (strip), d (default), h (help)
     K (nonkey)       s (strip), d (default), h (help)
     l (maxlen)                  d (default), h (help)
     m (match)                   d (default), h (help)
     n (numeric)      s (strip), d (default), h (help)
     N (no)           s (strip), d (default), h (help)
     r (required)                d (default), h (help)
     s (strip)                   d (default), h (help)
     Y (yes)          s (strip), d (default), h (help)

   Except for the implied precedence indicated in the table above, the
ordering of the flag tests proceeds in the same order as given in the
flags argument.

   Excepting the precedences above, query processing proceeds generally as
described below.

   * If the b flag was given, the "before" subroutine is invoked as a
     "pre-input" test.  If the sub returns a 0, empty string, or undef, the
     query is abandoned.  Otherwise, processing continues.

   * If the I or J flags were given, then input is obtained, without
     prompting, from the associated reference.  If the reference type is
     CODE, then it is invoked and the resulting return value is used as
     the input.  Otherwise the reference is evaluated in a scalar context
     and used as the input.  The J flag test is only done once, on the
     first entry into the input loop.

   * In the absence either the I or J flags, query will issue the given
     prompt and obtain input from STDIN.  If an EOF occurs, an undef value
     will result.

   * The input is examined for "null" input (that is, the empty string),
     and processing quits in this case.  Since most input is obtained from
     STDIN, a null input indicates an end-of-file (EOF).  If the input is
     not null, a terminating newline is removed, and the input testing
     continues.  At this point, an empty input string does not indicate an
     EOF.

   * If the s, k, or K flags were given, the input is trimmed of leading
     and trailing blanks, and all whitespace is "squeezed" to single
     blanks.

   * If the input is an empty response, and there is a default input (d
     flag), use it instead.

   * Unless the H flag is given, if the input is the character "?"  with
     nothing else, then print some helpful information.  If the user had
     supplied a *help string*, it is printed, otherwise the message:

     You are being asked "*$prompt*"

     is displayed.  Also, some information about the expected response,
     according to any given flag characters, is displayed.  Finally, the
     user is returned to the prompt, and given another opportunity to
     enter a response.

   * If input is required (indicated by the r flag), and if the input is
     empty, produce an error message, and query again.

   * If there was a a flag, the corresponding after subroutine is invoked
     with the input reference as its argument.  If the subroutine returns
     a non-null, non-zero value, the input succeeds, otherwise it fails.
     It is up to the after subroutine to display any appropriate error
     messages.

   * If the query was flagged Y or N, match the input against the pattern:

          /^(y(es?)?|no?)$/i

     If the match fails, print an error message, and query again.  When the
     match succeeds, replace the input with the complete word `"yes"' or
     "no";

   * If an integer response is required (i flagged), check for integer
     input.  If not, print an error, and query again.  A successful integer
     input is returned.

   * If a numeric response is required (n flagged), check for proper
     numeric input (either integer or real format).  Errors produce a
     warning, and another query.

   * If the query was given a keyword table (flagged with k), the input is
     matched against the allowable keyword list.  If an exact match is
     found, the keyword is returned as the input.  Failing an exact match,
     an abbreviation search is performed against the keywords.  If a single
     match is found, it is returned as the input.  If no match is found, an
     error message is produced, and the user is returned to the query to
     try again.  Otherwise, the input was ambiguous, an error noted
     showing the matches, and the user is queried again.

     The matching is case-insensitive or not, according to the value of the
     variable `$Query::Case_sensitive', which is nil, by default.  The
     variable may be set by the user to change the matching from
     case-insensitive to case-sensitive.

   * If the query was given an unacceptable keyword list (flagged with K),
     the input is compared against the unacceptable keywords.  If it
     matches any keywords exactly, an error is noted, and the query is
     performed again.

     The matching is case-insensitive by default.  Set the variable
     `$Query::Case_sensitive' to a non-null, non-zero value to make the
     keyword matching case-sensitive.

   * If the query was m flagged with a Perl regular expression pattern,
     then the input is matched against the pattern.  Failures are noted
     with an error message, and the query reattempted.

   * If the query was l flagged with a maximum input length, the length of
     the input is checked against the maximum.  A length violation is noted
     with an error message and the user is queried again.

   * If the query has a variable defined with the V flag, the variable is
     assigned the input string.  This is always done last, after and only
     if all tests are successful.

     If the variable is a string name and not qualified with a package name
     (ie:  `$foo::variable'), then the variable is qualified at the level
     outside of the Query.pm module.

   * Finally, having passed whatever conditions were flagged, the input is
     returned to the user.

EXAMPLE
=======

   The following are typical usage samples:

   * To perform a simple "yes" or "no" query, with "no" as the default
     answer:

          $ans = &query("Do you wish to quit? (yn)",'N');

   * An equivalent alternative is:

          query "Do you wish to quit? (yn)", 'NV', \$ans;

   * To perform the same query, with some supplied helpful information:

          $ans = &query("Do you wish to quit? (yn)",'Nh',<<'EOF');
          You are being asked if you wish to quit.  If you answer "yes",
          then all changes will be lost.  An answer of "no", will allow
          you to return to continue making changes.
          EOF

   * To solicit an integer input:

          $mode = &query("Please enter the file mode:",'idh','644',<<'EOF');
          Please enter the 3 digit numeric file mode; if you are unsure
          of how the file mode is used, please see the man page for "chmod".
          EOF

   * To solicit one of several keywords:

          @keys = split(' ','SGI DEC IBM Sun HP Apple');
          $vendor = &query('Please enter a vendor:','rkd',\@keys,'SGI');

   * To solicit a new, unique keyword to be used as a database field name,
     with a regexp pattern to check it against:

          @fields = split(' ','Index Vendor Title'); # existing fields
          $newfield = &query('New field name:','rKm',\@fields,'^\w+$');

ENVIRONMENT
===========

COLUMNS
     This variable is used to control the width of output when listing the
     keyword arrays.  If not defined, 80 is used by default.

DEPENDENCIES
============

Carp.pm
     Used to produce usage error messages.

Array::PrintCols::print_cols
     Used to produce displays of the keyword arrays.

FILES
=====

   None.

AUTHOR
======

   Copyright (C) 1995  Alan K. Stebbens <aks@hub.ucsb.edu>

   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.

DIAGNOSTICS
===========

Input is required.
     Issued when an empty response is given, and there is no default input.

Please answer with 'yes' or 'no', or enter '?' for help.
     Issued for Y or N flagged queries, and the input is not reconizeable.

Please enter an integer number.
     Printed when non-integer input is given for i flagged queries.

Please enter a number, real or integer.
     Printed when non-numeric input is given for n flagged queries.

The input '*$input*' is ambiguous; it matches the following:
     Issued in response to k flagged queries with input which matches more
     than one of the allowed keywords.

The input '*$input*' fails to match any of the allowed keywords:
     Printed when input to a k flagged query does not match any of the
     keywords.

The input '%s' matches a disallowed keyword '%s'.
     Printed when the input matches one of the unacceptable keywords given
     on a K flagged query.

'%s' fails to match '%s'
     This results from input failing to match the regular expression given
     on a m flagged query.

Input is %d characters too long; cannot exceed %d characters.
     The length of the input exceeded the maximum length given with the l
     flag argument.

Please try again, or enter '?' for help.
query: The k flag needs an array reference.
     The next argument in the argument list to query wasn't an array
     reference.

query: The K flag needs an array reference.
     The next argument in the argumentlist to query wasn't an array
     reference.

BUGS
====

A perl module for simple terminal control
*****************************************

NAME
====

   Term::ReadKey - A perl module for simple terminal control

SYNOPSIS
========

     use Term::ReadKey;
     ReadMode 4; # Turn off controls keys
     while (not defined ($key = ReadKey(-1)) {
     	# No key yet
     }
     print "Get key $key\n";
     ReadMode 0; # Reset tty mode before exiting

DESCRIPTION
===========

   Term::ReadKey is a compiled perl module dedicated to providing simple
control over terminal driver modes (cbreak, raw, cooked, etc.,) support for
non-blocking reads, if the architecture allows, and some generalized handy
functions for working with terminals. One of the main goals is to have the
functions as portable as possible, so you can just plug in "use
Term::ReadKey" on any architecture and have a good likelyhood of it
working.

ReadMode MODE [, Filehandle]
     Takes an integer argument, which can currently be one of the following
     values:

          0    Restore original settings.
          1    Change to cooked mode.
          2	 Change to cooked mode with echo off.
                (Good for passwords)
          3    Change to cbreak mode.
          4    Change to raw mode.
          5    Change to ultra-raw mode.
                (LF to CR/LF translation turned off)

          Or, you may use the synonyms:

          restore
          normal
          noecho
          cbreak
          raw
          ultra-raw

     These functions are automatically applied to the STDIN handle if no
     other handle is supplied. Modes 0 and 5 have some special properties
     worth mentioning: not only will mode 0 restore original settings, but
     it cause the next ReadMode call to save a new set of default
     settings. Mode 5 is similar to mode 4, except no CR/LF translation is
     performed, and if possible, parity will be disabled (only if not
     being used by the terminal, however. It is no different from mode 4
     under Windows.)

     If you are executing another program that may be changing the
     terminal mode, you will either want to say

          ReadMode 1
          system('someprogram');
          ReadMode 1;

          which resets the settings after the program has run, or:

          $somemode=1;
          ReadMode 0;
          system('someprogram');
          ReadMode 1;

          which records any changes the program may have made, before resetting the
          mode.

ReadKey MODE [, Filehandle]
     Takes an integer argument, which can currently be one of the following
     values:

          0    Perform a normal read using getc
          -1   Perform a non-blocked read
          >0	 Perform a timed read

     (If the filehandle is not supplied, it will default to STDIN.) If
     there is nothing waiting in the buffer during a non-blocked read,
     then undef will be returned. Note that if the OS does not provide any
     known mechanism for non-blocking reads, then a `ReadKey -1' can die
     with a fatal error. This will hopefully not be common.

     If MODE is greater then zero, then ReadKey will use it as a timeout
     value in seconds (fractional seconds are allowed), and won't return
     undef until that time expires. (Note, again, that some OS's may not
     support this timeout behaviour.) If MODE is less then zero, then this
     is treated as a timeout of zero, and thus will return immediately if
     no character is waiting. A MODE of zero, however, will act like a
     normal getc.

     There are currently some limitations with this call under Windows. It
     may be possible that non-blocking reads will fail when reading
     repeating keys from more then one console.

ReadLine MODE [, Filehandle]
     Takes an integer argument, which can currently be one of the following
     values:

          0    Perform a normal read using scalar(<FileHandle>)
          -1   Perform a non-blocked read
          >0	 Perform a timed read

     If there is nothing waiting in the buffer during a non-blocked read,
     then undef will be returned. Note that if the OS does not provide any
     known mechanism for non-blocking reads, then a `ReadLine 1' can die
     with a fatal error. This will hopefully not be common. Note that a
     non-blocking test is only performed for the first character in the
     line, not the entire line.  This call will probably not do what you
     assume, especially with ReadMode's higher then 1. For example,
     pressing Space and then Backspace would appear to leave you where you
     started, but any timeouts would now be suspended.

     This call is currently not available under Windows.

GetTerminalSize [Filehandle]
     Returns either an empty array if this operation is unsupported, or a
     four element array containing: the width of the terminal in
     characters, the height of the terminal in character, the width in
     pixels, and the height in pixels. (The pixel size will only be valid
     in some environments.)

     Under Windows, this function must be called with an "output"
     filehandle, such as STDOUT, or a handle opened to CONOUT$.

SetTerminalSize WIDTH,HEIGHT,XPIX,YPIX [, Filehandle]
     Return -1 on failure, 0 otherwise. Note that this terminal size is
     only for informative value, and changing the size via this mechanism
     will not change the size of the screen. For example, XTerm uses a
     call like this when it resizes the screen. If any of the new
     measurements vary from the old, the OS will probably send a SIGWINCH
     signal to anything reading that tty or pty.

     This call does not work under Windows.

GetSpeeds [, Filehandle]
     Returns either an empty array if the operation is unsupported, or a
     two value array containing the terminal in and out speeds, in
     decimal. E.g, an in speed of 9600 baud and an out speed of 4800 baud
     would be returned as (9600,4800). Note that currently the in and out
     speeds will always be identical in some OS's. No speeds are reported
     under Windows.

GetControlChars [, Filehandle]
     Returns an array containing key/value pairs suitable for a hash. The
     pairs consist of a key, the name of the control character/signal, and
     the value of that character, as a single character. This call does
     nothing under Windows.

     Each key will be an entry from the following list:

          DISCARD
          DSUSPEND
          EOF
          EOL
          EOL2
          ERASE
          ERASEWORD
          INTERRUPT
          KILL
          MIN
          QUIT
          QUOTENEXT
          REPRINT
          START
          STATUS
          STOP
          SUSPEND
          SWITCH
          TIME

     Thus, the following will always return the current interrupt
     character, regardless of platform.

          %keys = GetControlChars;
          $int = $keys{INTERRUPT};

SetControlChars [, Filehandle]
     Takes an array containing key/value pairs, as a hash will produce.
     The pairs should consist of a key that is the name of a legal control
     character/signal, and the value should be either a single character,
     or a number in the range 0-255. SetControlChars will die with a
     runtime error if an invalid character name is passed or there is an
     error changing the settings. The list of valid names is easily
     available via

          %cchars = GetControlChars();
          @cnames = keys %cchars;

     This call does nothing under Windows.

AUTHOR
======

   Kenneth Albanowski <kjahds@kjahds.com>

Perl interface to various readline packages. If no real package is found, substitutes stubs instead of basic functions.
***********************************************************************************************************************

NAME
====

   Term::ReadLine - Perl interface to various readline packages. If no
real package is found, substitutes stubs instead of basic functions.

SYNOPSIS
========

     use Term::ReadLine;
     $term = new Term::ReadLine 'Simple Perl calc';
     $prompt = "Enter your arithmetic expression: ";
     $OUT = $term->OUT || STDOUT;
     while ( defined ($_ = $term->readline($prompt)) ) {
       $res = eval($_), "\n";
       warn $@ if $@;
       print $OUT $res, "\n" unless $@;
       $term->addhistory($_) if /\S/;
     }

DESCRIPTION
===========

   This package is just a front end to some other packages. At the moment
this description is written, the only such package is Term-ReadLine,
available on CPAN near you. The real target of this stub package is to set
up a common interface to whatever Readline emerges with time.

Minimal set of supported functions
==================================

   All the supported functions should be called as methods, i.e., either as

     $term = new Term::ReadLine 'name';

   or as

     $term->addhistory('row');

   where $term is a return value of Term::ReadLine->Init.

ReadLine
     returns the actual package that executes the commands. Among possible
     values are `Term::ReadLine::Gnu', Term::ReadLine::Perl,
     `Term::ReadLine::Stub Exporter'.

new
     returns the handle for subsequent calls to following functions.
     Argument is the name of the application. Optionally can be followed
     by two arguments for IN and `OUT' filehandles. These arguments should
     be globs.

readline
     gets an input line, *possibly* with actual readline support. Trailing
     newline is removed. Returns undef on EOF.

`addhistory'
     adds the line to the history of input, from where it can be used if
     the actual readline is present.

IN, $`OUT'
     return the filehandles for input and output or undef if readline
     input and output cannot be used for Perl.

`MinLine'
     If argument is specified, it is an advice on minimal size of line to
     be included into history.  undef means do not include anything into
     history. Returns the old value.

`findConsole'
     returns an array with two strings that give most appropriate names for
     files for input and output using conventions `"<$in"', `">out"'.

Attribs
     returns a reference to a hash which describes internal configuration
     of the package. Names of keys in this hash conform to standard
     conventions with the leading `rl_' stripped.

Features
     Returns a reference to a hash with keys being features present in
     current implementation. Several optional features are used in the
     minimal interface: `appname' should be present if the first argument
     to new is recognized, and `minline' should be present if `MinLine'
     method is not dummy.  `autohistory' should be present if lines are
     put into history automatically (maybe subject to `MinLine'), and
     `addhistory' if `addhistory' method is not dummy.

     If Features method reports a feature `attribs' as present, the method
     Attribs is not dummy.

Additional supported functions
==============================

   Actually Term::ReadLine can use some other package, that will support
reacher set of commands.

   All these commands are callable via method interface and have names
which conform to standard conventions with the leading `rl_' stripped.

   The stub package included with the perl distribution allows some
additional methods:

`tkRunning'
     makes Tk event loop run when waiting for user input (i.e., during
     readline method).

`ornaments'
     makes the command line stand out by using termcap data.  The argument
     to `ornaments' should be 0, 1, or a string of a form `"aa,bb,cc,dd"'.
     Four components of this string should be names of *terminal
     capacities*, first two will be issued to make the prompt standout,
     last two to make the input line standout.

`newTTY'
     takes two arguments which are input filehandle and output filehandle.
     Switches to use these filehandles.

   One can check whether the currently loaded ReadLine package supports
these methods by checking for corresponding Features.

EXPORTS
=======

   None

ENVIRONMENT
===========

   The environment variable `PERL_RL' governs which ReadLine clone is
loaded. If the value is false, a dummy interface is used. If the value is
true, it should be tail of the name of the package to use, such as Perl or
`Gnu'.

   As a special case, if the value of this variable is space-separated,
the tail might be used to disable the ornaments by setting the tail to be
`o=0' or `ornaments=0'.  The head should be as described above, say

   If the variable is not set, or if the head of space-separated list is
empty, the best available package is loaded.

     export "PERL_RL=Perl o=0"	# Use Perl ReadLine without ornaments
     export "PERL_RL= o=0"		# Use best available ReadLine without ornaments

   (Note that processing of `PERL_RL' for ornaments is in the discretion
of the particular used `Term::ReadLine::*' package).

Perl extension for the GNU Readline/History Library
***************************************************

NAME
====

   Term::ReadLine::Gnu - Perl extension for the GNU Readline/History
Library

SYNOPSIS
========

     use Term::ReadLine;
     $term = new Term::ReadLine 'ProgramName';
     while ( defined ($_ = $term->readline('prompt>')) ) {
       ...
     }

DESCRIPTION
===========

Overview
--------

   This is an implementation of Term::ReadLine using the GNU
Readline/History Library.

   For basic functions object oriented interface is provided. These are
described in the section `"Standard Methods"|"Standard Methods"' in this
node and `"`Term::ReadLine::Gnu' in this node
Functions"|"`Term::ReadLine::Gnu' Functions"'.

   This package also has the interface with the almost all functions and
variables which are documented in the GNU Readline/History Library Manual.
They are documented in the section `"`Term::ReadLine::Gnu' in this node
Functions"|"`Term::ReadLine::Gnu' Functions"' and `"`Term::ReadLine::Gnu'
in this node Variables"|"`Term::ReadLine::Gnu' Variables"' briefly.  For
more detail of the GNU Readline/History Library, see 'GNU Readline Library
Manual' and 'GNU History Library Manual'.

   The sample programs under `eg/' directory and test programs under `t/'
directory in the `Term::ReadLine::Gnu' distribution include many example
of this module.

Standard Methods
----------------

   These methods are standard methods defined by Term::ReadLine.

ReadLine
     returns the actual package that executes the commands. If you have
     installed this package,  possible value is `Term::ReadLine::Gnu'.

`new(NAME,[IN[,OUT]])'
     returns the handle for subsequent calls to following functions.
     Argument is the name of the application.  Optionally can be followed
     by two arguments for IN and `OUT' file handles. These arguments
     should be globs.

`readline(PROMPT[,PREPUT])'
     gets an input line, with actual `GNU Readline' support.  Trailing
     newline is removed.  Returns undef on EOF.  `PREPUT' is an optional
     argument meaning the initial value of input.

     The optional argument `PREPUT' is granted only if the value `preput'
     is in Features.

     `PROMPT' may include some escape sequences.  Use
     `RL_PROMPT_START_IGNORE' to begin a sequence of non-printing
     characters, and `RL_PROMPT_END_IGNORE' to end of such a sequence.

`AddHistory(LINE1, LINE2, ...)'
     adds the lines to the history of input, from where it can be used if
     the actual readline is present.

IN, `OUT'
     return the file handles for input and output or undef if readline
     input and output cannot be used for Perl.

`MinLine([MAX])'
     If argument MAX is specified, it is an advice on minimal size of line
     to be included into history.  undef means do not include anything
     into history.  Returns the old value.

`findConsole'
     returns an array with two strings that give most appropriate names for
     files for input and output using conventions `"<$in"', `">$out"'.

Attribs
     returns a reference to a hash which describes internal configuration
     (variables) of the package.  Names of keys in this hash conform to
     standard conventions with the leading `rl_' stripped.

     See section "Variables" for supported variables.

Features
     Returns a reference to a hash with keys being features present in
     current implementation. Several optional features are used in the
     minimal interface: `appname' should be present if the first argument
     to new is recognized, and `minline' should be present if `MinLine'
     method is not dummy.  `autohistory' should be present if lines are
     put into history automatically (maybe subject to `MinLine'), and
     `addHistory' if `AddHistory' method is not dummy.  `preput' means the
     second argument to readline method is processed.  `getHistory' and
     `setHistory' denote that the corresponding methods are present.
     `tkRunning' denotes that a Tk application may run while ReadLine is
     getting input.

`Term::ReadLine::Gnu' Functions
-------------------------------

   All these GNU Readline/History Library functions are callable via
method interface and have names which conform to standard conventions with
the leading `rl_' stripped.

   Almost methods have lower level functions in `Term::ReadLine::Gnu::XS'
package.  To use them full qualified name is required.  Using method
interface is preferred.

Readline Convenience Functions

    Naming Function

         `add_defun(NAME, FUNC [,KEY=-1])'
               Add name to the Perl function `FUNC'.  If optional argument
               KEY is specified, bind it to the `FUNC'.  Returns reference
               to `FunctionPtr'.

                    Example:
                    	# name name `reverse-line' to a function reverse_line(),
                    	# and bind it to "\C-t"
                    	$term->add_defun('reverse-line', \&reverse_line, "\ct");

    Selecting a Keymap

         `make_bare_keymap'
                    Keymap	rl_make_bare_keymap()

         `copy_keymap(MAP)'
                    Keymap	rl_copy_keymap(Keymap|str map)

         `make_keymap'
                    Keymap	rl_make_keymap()

         `discard_keymap(MAP)'
                    Keymap	rl_discard_keymap(Keymap|str map)

         `get_keymap'
                    Keymap	rl_get_keymap()

         `set_keymap(MAP)'
                    Keymap	rl_set_keymap(Keymap|str map)

         `get_keymap_by_name(NAME)'
                    Keymap	rl_get_keymap_by_name(str name)

         `get_keymap_name(MAP)'
                    str	rl_get_keymap_name(Keymap map)

    Binding Keys

         `bind_key(KEY, FUNCTION [,MAP])'
                    int	rl_bind_key(int key, FunctionPtr|str function,
                    		    Keymap|str map = rl_get_keymap())

               Bind KEY to the FUNCTION.  FUNCTION is the name added by the
               `add_defun' method.  If optional argument `MAP' is
               specified, binds in `MAP'.  Returns non-zero in case of
               error.

         `unbind_key(KEY [,MAP])'
                    int	rl_unbind_key(int key, Keymap|str map = rl_get_keymap())

               Bind KEY to the null function.  Returns non-zero in case of
               error.

         `unbind_function(FUNCTION [,MAP])'
                    int	rl_unbind_function(FunctionPtr|str function,
                    			   Keymap|str map = rl_get_keymap())

         `unbind_command(COMMAND [,MAP])'
                    int	rl_unbind_command(str command,
                    			  Keymap|str map = rl_get_keymap())

         `generic_bind(TYPE, KEYSEQ, DATA, [,MAP])'
                    int	rl_generic_bind(int type, str keyseq,
                    			FunctionPtr|Keymap|str data,
                    			Keymap|str map = rl_get_keymap())

         `parse_and_bind(LINE)'
                    void	rl_parse_and_bind(str line)

               Parse LINE as if it had been read from the `~/.inputrc'
               file and perform any key bindings and variable assignments
               found.  For more detail see 'GNU Readline Library Manual'.

         `read_init_file([FILENAME])'
                    int	rl_read_init_file(str filename = '~/.inputrc')

    Associating Function Names and Bindings

         `named_function(NAME)'
                    FunctionPtr rl_named_function(str name)

         `get_function_name(FUNCTION)'
                    str	rl_get_function_name(FunctionPtr function)

         `function_of_keyseq(KEYMAP [,MAP])'
                    (FunctionPtr|Keymap|str data, int type)
                    	rl_function_of_keyseq(str keyseq,
                    			      Keymap|str map = rl_get_keymap())

         `invoking_keyseqs(FUNCTION [,MAP])'
                    (@str)	rl_invoking_keyseqs(FunctionPtr|str function,
                    			    Keymap|str map = rl_get_keymap())

         `function_dumper([READABLE])'
                    void	rl_function_dumper(int readable = 0)

         `list_funmap_names'
                    void	rl_list_funmap_names()

         `funmap_names' (undocumented)
                    (@str)	rl_funmap_names()

    Allowing Undoing

         `begin_undo_group'
                    int	rl_begin_undo_group()

         `end_undo_group'
                    int	rl_end_undo_group()

         `add_undo(WHAT, START, END, TEXT)'
                    int	rl_add_undo(int what, int start, int end, str text)

         `free_undo_list'
                    void	free_undo_list()

         `do_undo'
                    int	rl_do_undo()

         `modifying([START [,END]])'
                    int	rl_modifying(int start = 0, int end = rl_end)

    Redisplay

         `redisplay'
                    void	rl_redisplay()

         `forced_update_display'
                    int	rl_forced_update_display()

         `on_new_line'
                    int	rl_on_new_line()

         `on_new_line_with_prompt'
                    int	rl_on_new_line_with_prompt()	# GRL 4.1

         `reset_line_state'
                    int	rl_reset_line_state()

         `message(FMT[, ...])'
                    int	rl_message(str fmt, ...)

         `clear_message'
                    int	rl_clear_message()

         `save_prompt'
                    void	rl_save_prompt()

         `restore_prompt'
                    void	rl_restore_prompt()

    Modifying Text

         `insert_text(TEXT)'
                    int	rl_insert_text(str text)

         `delete_text([START [,END]])'
                    int	rl_delete_text(start = 0, end = rl_end)

         `copy_text([START [,END]])'
                    str	rl_copy_text(start = 0, end = rl_end)

         `kill_text([START [,END]])'
                    int	rl_kill_text(start = 0, end = rl_end)

    Utility Functions

         `read_key'
                    int	rl_read_key()

         `getc(FILE)'
                    int	rl_getc(FILE *)

         `stuff_char(C)'
                    int	rl_stuff_char(int c)

         initialize
                    int	rl_initialize()

         `reset_terminal([TERMINAL_NAME])'
                    int	rl_reset_terminal(str terminal_name = getenv($TERM))

         `ding'
                    int	ding()

         `display_match_list(MATCHES [,LEN [,MAX]])'
                    void	rl_display_match_list(\@matches, len = $#maches, max) # GRL 4.0

               Since the first element of an array @matches as treated as
               a possible completion, it is not displayed.  See the
               descriptions of `completion_matches()'.

               When MAX is ommited, the max length of an item in @matches
               is used.

    Alternate Interface

         `callback_handler_install(PROMPT, LHANDLER)'
                    void	rl_callback_handler_install(str prompt, pfunc lhandler)

         `callback_read_char'
                    void	rl_callback_read_char()

         `callback_handler_remove'
                    void	rl_callback_handler_remove()

Readline Signal Handling

    `cleanup_after_signal'
               void	rl_cleanup_after_signal()	# GRL 4.0

    `free_line_state'
               void	rl_free_line_state()	# GRL 4.0

    `reset_after_signal'
               void	rl_reset_after_signal()	# GRL 4.0

    `resize_terminal'
               void	rl_resize_terminal()	# GRL 4.0

    `set_signals'
               int	rl_set_signals()	# GRL 4.0

    `clear_signals'
               int	rl_clear_signals()	# GRL 4.0

Completion Functions

    `complete_internal([WHAT_TO_DO])'
               int	rl_complete_internal(int what_to_do = TAB)

    `completion_matches(TEXT [,FUNC])'
               (@str)	completion_matches(str text,
               			   pfunc func = filename_completion_function)

    `filename_completion_function(TEXT, STATE)'
               str	filename_completion_function(str text, int state)

    `username_completion_function(TEXT, STATE)'
               str	username_completion_function(str text, int state)

    `list_completion_function(TEXT, STATE)'
               str	list_completion_function(str text, int state)

History Functions

    Initializing History and State Management

         `using_history'
                    void	using_history()

    History List Management

         `addhistory(STRING[, STRING, ...])'
                    void	add_history(str string)

         `StifleHistory(MAX)'
                    int	stifle_history(int max|undef)

               stifles the history list, remembering only the last MAX
               entries.  If MAX is undef, remembers all entries.  This is
               a replacement of unstifle_history().

         `unstifle_history'
                    int	unstifle_history()

               This is equivalent with 'stifle_history(undef)'.

         `SetHistory(LINE1 [, LINE2, ...])'
               sets the history of input, from where it can be used if the
               actual readline is present.

         `remove_history(WHICH)'
                    str	remove_history(int which)

         `replace_history_entry(WHICH, LINE)'
                    str	replace_history_entry(int which, str line)

         `clear_history'
                    void	clear_history()

         `history_is_stifled'
                    int	history_is_stifled()

    Information About the History List

         `where_history'
                    int	where_history()

         `current_history'
                    str	current_history()

         `history_get(OFFSET)'
                    str	history_get(offset)

         `history_total_bytes'
                    int	history_total_bytes()

         `GetHistory'
               returns the history of input as a list, if actual readline
               is present.

    Moving Around the History List

         `history_set_pos(POS)'
                    int	history_set_pos(int pos)

         `previous_history'
                    str	previous_history()

         `next_history'
                    str	next_history()

    Searching the History List

         `history_search(STRING [,DIRECTION])'
                    int	history_search(str string, int direction = -1)

         `history_search_prefix(STRING [,DIRECTION])'
                    int	history_search_prefix(str string, int direction = -1)

         `history_search_pos(STRING [,DIRECTION [,POS]])'
                    int	history_search_pos(str string,
                    			   int direction = -1,
                    			   int pos = where_history())

    Managing the History File

         `ReadHistory([FILENAME [,FROM [,TO]]])'
                    int	read_history(str filename = '~/.history',
                    		     int from = 0, int to = -1)

                    int	read_history_range(str filename = '~/.history',
                    			   int from = 0, int to = -1)

               adds the contents of FILENAME to the history list, a line
               at a time.  If FILENAME is false, then read from
               `~/.history'.  Start reading at line `FROM' and end at TO.
               If `FROM' is omitted or zero, start at the beginning.  If
               TO is omitted or less than `FROM', then read until the end
               of the file.  Returns true if successful, or false if not.
               `read_history()' is an aliase of `read_history_range()'.

         `WriteHistory([FILENAME])'
                    int	write_history(str filename = '~/.history')

               writes the current history to FILENAME, overwriting
               FILENAME if necessary.  If FILENAME is false, then write
               the history list to `~/.history'.  Returns true if
               successful, or false if not.

         `append_history(NELEMENTS [,FILENAME])'
                    int	append_history(int nelements, str filename = '~/.history')

         `history_truncate_file([FILENAME [,NLINES]])'
                    int	history_truncate_file(str filename = '~/.history',
                    			      int nlines = 0)

    History Expansion

         `history_expand(LINE)'
                    (int result, str expansion) history_expand(str line)

               Note that this function returns `expansion' in scalar
               context.

         `history_arg_extract(LINE, [FIRST [,LAST]])'
                    str history_arg_extract(str line, int first = 0, int last = '$')

         `get_history_event(STRING, CINDEX [,QCHAR])'
                    (str text, int cindex) = get_history_event(str  string,
                    					   int  cindex,
                    					   char qchar = '\0')

         `history_tokenize(LINE)'
                    (@str)	history_tokenize(str line)

`Term::ReadLine::Gnu' Variables
-------------------------------

   Following GNU Readline/History Library variables can be accessed from
Perl program.  See 'GNU Readline Library Manual' and ' GNU History Library
Manual' for each variable.  You can access them with Attribs methods.
Names of keys in this hash conform to standard conventions with the
leading `rl_' stripped.

   Examples:

     $attribs = $term->Attribs;
     $v = $attribs->{library_version};	# rl_library_version
     $v = $attribs->{history_base};	# history_base

Readline Variables
          str rl_line_buffer
          int rl_point
          int rl_end
          int rl_mark
          int rl_done
          int rl_pending_input
          int rl_erase_empty_line (GRL 4.0)
          str rl_prompt (read only)
          int rl_already_prompted (GRL 4.1)
          str rl_library_version (read only)
          str rl_terminal_name
          str rl_readline_name
          filehandle rl_instream
          filehandle rl_outstream
          pfunc rl_startup_hook
          pfunc rl_pre_input_hook (GRL 4.0)
          pfunc rl_event_hook
          pfunc rl_getc_function
          pfunc rl_redisplay_function
          pfunc rl_last_func (not documented)
          Keymap rl_executing_keymap (read only)
          Keymap rl_binding_keymap (read only)

Signal Handling Variables
          int rl_catch_signals (GRL 4.0)
          int rl_catch_sigwinch (GRL 4.0)

Completion Variables
          pfunc rl_completion_entry_function
          pfunc rl_attempted_completion_function
          pfunc rl_filename_quoting_function
          pfunc rl_filename_dequoting_function
          pfunc rl_char_is_quoted_p
          int rl_completion_query_items
          str rl_basic_word_break_characters
          str rl_basic_quote_characters
          str rl_completer_word_break_characters
          str rl_completer_quote_characters
          str rl_filename_quote_characters
          str rl_special_prefixes
          int rl_completion_append_character
          int rl_ignore_completion_duplicates
          int rl_filename_completion_desired
          int rl_filename_quoting_desired
          int rl_inhibit_completion
          pfunc rl_ignore_some_completion_function
          pfunc rl_directory_completion_hook
          pfunc rl_completion_display_matches_hook (GRL 4.0)

History Variables
          int history_base
          int history_length
          int max_input_history (read only)
          char history_expansion_char
          char history_subst_char
          char history_comment_char
          str history_no_expand_chars
          str history_search_delimiter_chars
          int history_quotes_inhibit_expansion
          pfunc history_inhibit_expansion_function

Function References
          rl_getc
          rl_redisplay
          rl_callback_read_char
          rl_display_match_list
          filename_completion_function
          username_completion_function
          list_completion_function
          shadow_redisplay
          Tk_getc

Custom Completion
-----------------

   In this section variables and functions for custom completion is
described with examples.

   Most of descriptions in this section is cited from GNU Readline Library
manual.

`rl_completion_entry_function'
     This variable holds reference refers to a generator function for
     `completion_matches()'.

     A generator function is called repeatedly from
     `completion_matches()', returning a string each time.  The arguments
     to the generator function are TEXT and STATE.  TEXT is the partial
     word to be completed.  STATE is zero the first time the function is
     called, allowing the generator to perform any necessary
     initialization, and a positive non-zero integer for each subsequent
     call.  When the generator function returns undef this signals
     `completion_matches()' that there are no more possibilities left.

     If the value is undef, built-in `filename_completion_function' is
     used.

     A sample generator function, `list_completion_function', is defined
     in Gnu.pm.  You can use it as follows;

          use Term::ReadLine;
          ...
          my $term = new Term::ReadLine 'sample';
          my $attribs = $term->Attribs;
          ...
          $attribs->{completion_entry_function} =
          	$attribs->{list_completion_function};
          ...
          $attribs->{completion_word} =
          	[qw(reference to a list of words which you want to use for completion)];
          $term->readline("custom completion>");

     See also `completion_matches'.

`rl_attempted_completion_function'
     A reference to an alternative function to create matches.

     The function is called with TEXT, `LINE_BUFFER', START, and END.
     `LINE_BUFFER' is a current input buffer string.  START and END are
     indices in `LINE_BUFFER' saying what the boundaries of TEXT are.

     If this function exists and returns null list or undef, or if this
     variable is set to undef, then an internal function `rl_complete()'
     will call the value of `$rl_completion_entry_function' to generate
     matches, otherwise the array of strings returned will be used.

     The default value of this variable is undef.  You can use it as
     follows;

          use Term::ReadLine;
          ...
          my $term = new Term::ReadLine 'sample';
          my $attribs = $term->Attribs;
          ...
          sub sample_completion {
              my ($text, $line, $start, $end) = @_;
              # If first word then username completion, else filename completion
              if (substr($line, 0, $start) =~ /^\s*$/) {
          	    return $term->completion_matches($text,
          					     $attribs->{'username_completion_function'});
              } else {
          	    return ();
              }
          }
          ...
          $attribs->{attempted_completion_function} = \&sample_completion;

`completion_matches(TEXT, ENTRY_FUNC)'
     Returns an array of strings which is a list of completions for TEXT.
     If there are no completions, returns undef.  The first entry in the
     returned array is the substitution for TEXT.  The remaining entries
     are the possible completions.

     `ENTRY_FUNC' is a generator function which has two arguments, and
     returns a string.  The first argument is TEXT.  The second is a state
     argument; it is zero on the first call, and non-zero on subsequent
     calls.  `ENTRY_FUNC' returns a undef to the caller when there are no
     more matches.

     If the value of `ENTRY_FUNC' is undef, built-in
     `filename_completion_function' is used.

     `completion_matches' is a Perl wrapper function of an internal
     function `completion_matches()'.  See also
     `$rl_completion_entry_function'.

`completion_function'
     A variable whose content is a reference to a function which returns a
     list of candidates to complete.

     This variable is compatible with Term::ReadLine::Perl and very easy
     to use.

          use Term::ReadLine;
          ...
          my $term = new Term::ReadLine 'sample';
          my $attribs = $term->Attribs;
          ...
          $attribs->{completion_function} = sub {
          	my ($text, $line, $start) = @_;
          	return qw(a list of candidates to complete);
          }

`list_completion_function(TEXT, STATE)'
     A sample generator function defined by `Term::ReadLine::Gnu'.
     Example code at `rl_completion_entry_function' shows how to use this
     function.

`Term::ReadLine::Gnu' Specific Features
---------------------------------------

`Term::ReadLine::Gnu' Specific Functions

    `CallbackHandlerInstall(PROMPT, LHANDLER)'
          This method provides the function `rl_callback_handler_install()'
          with the following addtional feature compatible with readline
          method; ornament feature, Term::ReadLine::Perl compatible
          completion function, histroy expansion, and addition to history
          buffer.

    `call_function(FUNCTION, [COUNT [,KEY]])'
               int	rl_call_function(FunctionPtr|str function, count = 1, key = -1)

    `rl_get_all_function_names'
          Returns a list of all function names.

    `shadow_redisplay'
          A redisplay function for password input.  You can use it as
          follows;

               $attribs->{redisplay_function} = $attribs->{shadow_redisplay};
               $line = $term->readline("password> ");

    `rl_filename_list'
          Returns candidates of filename to complete.  This function can
          be used with `completion_function' and is implemented for the
          compatibility with Term::ReadLine::Perl.

    `list_completion_function'
          See the description of section `"Custom Completion"|"Custom
          Completion"' in this node.

`Term::ReadLine::Gnu' Specific Variables

    `do_expand'
          When true, the history expansion is enabled.  By default false.

    `completion_function'
          See the description of section `"Custom Completion"|"Custom
          Completion"' in this node.

    `completion_word'
          A reference to a list of candidates to complete for
          `list_completion_function'.

`Term::ReadLine::Gnu' Specific Commands

    `operate-and-get-next'
          The equivalent of the Korn shell `C-o'
          `operate-and-get-next-history-line' editing command and the Bash
          `operate-and-get-next'.

          This command is bound to `\C-o' by default for the compatibility
          with the Bash and Term::ReadLine::Perl.

    `display-readline-version'
          Shows the version of `Term::ReadLine::Gnu' and the one of the GNU
          Readline Library.

    `change-ornaments'
          Change ornaments interactively.

FILES
=====

`~/.inputrc'
     Readline init file.  Using this file it is possible that you would
     like to use a different set of key bindings.  When a program which
     uses the Readline library starts up, the init file is read, and the
     key bindings are set.

     Conditional key binding is also available.  The program name which is
     specified by the first argument of new method is used as the
     application construct.

     For example, when your program call new method like this;

          ...
          $term = new Term::ReadLine 'PerlSh';
          ...

     your `~/.inputrc' can define key bindings only for it as follows;

          ...
          $if PerlSh
          Meta-Rubout: backward-kill-word
          "\C-x\C-r": re-read-init-file
                  "\e[11~": "Function Key 1"
          $endif
          ...

EXPORTS
=======

   None.

SEE ALSO
========

GNU Readline Library Manual
GNU History Library Manual
Term::ReadLine
Term::ReadLine::Perl (Term-ReadLine-Perl-xx.tar.gz)

and `t/*' in the Term::ReadLine::Gnu distribution
Works which use Term::ReadLine::Gnu

    Perl Debugger
               perl -d

    The Perl Shell (psh)
               http://www.focusresearch.com/gregor/psh/

          The Perl Shell is a shell that combines the interactive nature
          of a Unix shell with the power of Perl.  The goal is to
          eventually have a full featured shell that behaves as expected
          for normal shell activity.  But, the Perl Shell will use Perl
          syntax and functionality for for control-flow statements and
          other things.

    Ghostscript Shell
               http://www.panix.com/~jdf/gshell/

          It provides a friendly way to play with the Ghostscript
          interpreter, including command history and auto-completion of
          Postscript font names and reserved words.

    SPP (Synopsys Plus Perl)
               http://www.stanford.edu/~jsolomon/SPP/

          SPP (Synopsys Plus Perl) is a Perl module that wraps around
          Synopsys' shell programs.  SPP is inspired by the original
          dc_perl written by Steve Golson, but it's an entirely new
          implementation.  Why is it called SPP and not dc_perl?  Well,
          SPP was written to wrap around any of Synopsys' shells.

     If you know any other works which can be listed here, please let me
     know.

AUTHOR
======

   Hiroo Hayashi `<hiroo.hayashi@computer.org>'

   `http://www.perl.org/CPAN/authors/Hiroo_HAYASHI/'

TODO
====

   GTK+ support in addition to Tk.

BUGS
====

   `rl_add_defun()' can define up to 16 functions.

   Ornament feature works only on prompt strings.  It requires very hard
hacking of `display.c:rl_redisplay()' in GNU Readline library to ornament
input line.

   `newTTY()' is not tested yet.

Asking the user for a password
******************************

NAME
====

   Term::ReadPassword - Asking the user for a password

SYNOPSIS
========

     use Term::ReadPassword;
     while (1) {
       my $password = read_password('password: ');
       redo unless defined $password;
       if ($password eq 'flubber') {
         print "Access granted.\n";
         last;
       } else {
         print "Access denied.\n";
         redo;
       }
     }

DESCRIPTION
===========

   This module lets you ask the user for a password in the traditional way,
from the keyboard, without echoing.

   This is not intended for use over the web; user authentication over the
web is another matter entirely. Also, this module should generally be used
in conjunction with Perl's crypt() function, sold separately.

   The read_password function prompts for input, reads a line of text from
the keyboard, then returns that line to the caller. The line of text
doesn't include the newline character, so there's no need to use chomp.

   While the user is entering the text, a few special characters are
processed. The character delete (or the character backspace) will back up
one character, removing the last character in the input buffer (if any).
The character CR (or the character LF) will signal the end of input,
causing the accumulated input buffer to be returned. And, optionally, the
character Control-C may be used to terminate the input operation. (See
details below.) All other characters, even ones which would normally have
special purposes, will be added to the input buffer.

   It is not recommended, though, that you use the as-yet-unspecified
control characters in your passwords, as those characters may become
meaningful in a future version of this module. Applications which allow
the user to set their own passwords may wish to enforce this rule, perhaps
with code something like this:

     {
       # Naked block for scoping and redo
       my $new_pw = read_password("Enter your new password: ");
       if ($new_pw =~ /([^\x20-\x7E])/) {
         my $bad = unpack "H*", $1;
     	print "Your password may not contain the ";
     	print "character with hex code $bad.\n";
     	redo;
       } elsif (length($new_pw) < 5) {
         print "Your password must be longer than that!\n";
     	redo;
       } elsif ($new_pw ne read_password("Enter it again: ")) {
     	print "Passwords don't match.\n";
     	redo;
       } else {
         &change_password($new_pw);
     	print "Your password is now changed.\n";
       }
     }

   The second parameter to read_password is the optional idle_timeout
value. If it is a non-zero number and there is no keyboard input for that
many seconds, the input operation will terminate. Notice that this is not
an overall time limit, as the timer is restarted with each new character.

   The third parameter will optionally allow the input operation to be
terminated by the user with Control-C. If this is not supplied, or is
false, a typed Control-C will be entered into the input buffer just as any
other character. In that case, there is no way from the keyboard to
terminate the program while it is waiting for input. (That is to say, the
normal ability to generate signals from the keyboard is suspended during
the call to read_password.)

   If the input operation terminates early (either because the idle_timeout
was exceeded, or because a Control-C was enabled and typed), the return
value will be undef. In either case, there is no way provided to discover
what (if anything) was typed before the early termination, or why the
input operation was terminated.

   So as to discourage users from typing their passwords anywhere except at
the prompt, any input which has been "typed ahead" before the prompt
appears will be discarded. And whether the input operation terminates
normally or not, a newline character will be printed, so that the cursor
will not remain on the line after the prompt.

SECURITY
========

   You would think that a module dealing with passwords would be full of
security features. You'd think that, but you'd be wrong. For example, perl
provides no way to erase a piece of data from memory. (It's easy to erase
it so that it can't be accessed from perl, but that's not the same thing
as expunging it from the actual memory.) If you've entered a password,
even if the variable that contained that password has been erased, it may
be possible for someone to find that password, in plaintext, in a core
dump. And that's just one potential security hole.

   In short, if serious security is an issue, don't use this module.

AUTHOR
======

   Tom Phoenix <rootbeer@redcat.com>

SEE ALSO
========

   Term::ReadLine, `crypt', see Perlfunc (perl.info), and your
system's manpages for the low-level I/O operations used here.

Perl extension for retrieving terminal size
*******************************************

NAME
====

   Term::Size - Perl extension for retrieving terminal size

SYNOPSIS
========

     use Term::Size;

     ($columns, $rows) = Term::Size::chars *STDOUT{IO};
     ($x, $y) = Term::Size::pixels;

DESCRIPTION
===========

   *Term::Size* is a Perl module which provides a straightforward way to
retrieve the terminal size.

   Both functions take an optional filehandle argument, which defaults to
`*STDIN{IO}'.  They both return a list of two values, which are the
current width and height, respectively, of the terminal associated with
the specified filehandle.

   `Term::Size::chars' returns the size in units of characters, whereas
`Term::Size::pixels' uses units of pixels.

   In a scalar context, both functions return the first element of the
list, that is, the terminal width.

   The functions may be imported.

   If you need to pass a filehandle to either of the `Term::Size'
functions, beware that the `*STDOUT{IO}' syntax is only supported in Perl
5.004 and later.  If you have an earlier version of Perl, or are
interested in backwards compatibility, use `*STDOUT' instead.

EXAMPLES
========

   1. Refuse to run in a too narrow window.

     use Term::Size;

     die "Need 80 column screen" if Term::Size::chars *STDOUT{IO} < 80;

   2. Track window size changes.

     use Term::Size 'chars';

     my $changed = 1;

     while (1) {
             local $SIG{'WINCH'} = sub { $changed = 1 };

     if ($changed) {
             ($cols, $rows) = chars;
             # Redraw, or whatever.
             $changed = 0;
     }
         }

RETURN VALUES
=============

   Both functions return undef if there is an error.

   If the terminal size information is not available, the functions will
normally return `(0, 0)', but this depends on your system.  On character
only terminals, `pixels' will normally return `(0, 0)'.

BUGS
====

   It only works on Unix systems.

AUTHOR
======

   Tim Goodwin, <tim@uunet.pipex.com>, 1997-04-23.

simple tool for building text-based user interfaces
***************************************************

NAME
====

   Term::TUI - simple tool for building text-based user interfaces

SYNOPSIS
========

   If TUI_Run is the only routine being used:

     use Term::TUI;
     $flag=&TUI_Run($command,\%desc);

     $version=&Term::TUI::TUI_Version;

   If other TUI subroutines are used:

     use Term::TUI qw(:all);
     $flag=&TUI_Run($command,\%desc);

     &TUI_Out($message);

     $flag=&TUI_Script(\%desc,$script,$sep);

DESCRIPTION
===========

   Many times, I've wanted to quickly write a nice text-based user
interface around a set of perl routines only to end up writing the full
(though simple) parser and interface to make it nice enough, and friendly
enough, to be usable.

   This module creates a simple but powerful text based user interface
around perl routines, adding such features as command line history,
command line editing, and online help (command completion will also be
implemented), while hiding all details of the interface from the
programmer.

   The interface is described in a simple hash which is passed to the
TUI_Run command.  This routine exits only when the user has exited the
program (returning a flag signalling any special exit conditions).

ROUTINES
========

TUI_Run
          use Term::TUI;
          $flag=&TUI_Run($command,\%desc);

     The TUI_Run command is used to run the interface.  It prompts the user
     for commands and executes them (based on description of passed in as
     %desc) until the user exits.  The return flag is 0 unless the user
     exited with the Abort command when it is 1.

TUI_Script
          use Term::TUI qw(:all);
          $flag=&TUI_Script(\%desc,$script [,$sep]);

     This allows you to pass in commands in a "script" instead of an
     interactive session.  The script is a series of commands separated by
     a semicolon (or the string included in $sep).

TUI_Version
          use Term::TUI qw(:all);
          $vers=&TUI_Version;

     Returns the version of the module.

TUI_Out
          use Term::TUI qw(:all);
          &TUI_Out($mess);

     This is used in the routines given in the description hash to send a
     message to STDOUT.

INTERFACE DESCRIPTION
=====================

   The interface allows you to describe multiple "modes" organized in a
simple tree-like hierarchy (or modes, submodes, subsubmodes, etc.), each
of which has it's own set of commands specific to that mode.  I've
modelled it after a unix filesystem with directories being "modes" and
executables being equivalent to commands.  So, you might want to model the
following tree:

     /
     +--------------------+
     math                 string
     |                    |
     +-----+-----+        +------+
     hex   add*  mult*    len*   substr*
     |
     +-----+
     add*  mult*

   Here the "executables" are marked with asterixes(*). So in math mode,
you could type "add" or "mult" to add a list of numbers together or
multiply them together.  It also has a submode "hex" where you can do that
in hexidecimal.

   I find this type of interface very conveniant in many cases, but a
nuisance to write.  This module handles this trivially.  The above
interface can be written with the following 2 perl commands:

     %modes =
      (".HELP"  => "This is the main help.\nNot a lot of info here.",
       "math"   => {".HELP" => "A simple calculator.  Currently it can\n" .
                               "only add and multiply in hex or decimal.",
                    "add"   => [ "Add numbers together."  ,    Add,0 ],
                    "mult"  => [ "Multiply numbers together.", Mult,0 ],
                    "hex"   => {".HELP"  => "Math in hex.",
                                "add"   => [ "Add hex numbers together.",
                                             Add,1 ],
                                "mult"  => [ "Multiply hex numbers together.",
                                             Mult,1 ]
                               }
                   },
       "string" => {".HELP" => "String operations",
                    "subs"  => [ "Take STRING,POS,LEN and returns substring.",
                                 Substring ],
                    "len"   => [ "Returns the length of a string.",
                                 Length ]
                   }
     );

     $flag=&TUI_Run("sample",\%modes);
     print "*** ABORT ***\n"  if ($flag);

   You also have to write an Add, Mult, Substring, and Length subroutine
of course, but once that's done, you end up with a rather nice text based
user interface.  The following are excerpts from a session using the
sample interface defined above:

   Changing modes is trivial.  Just type in the new mode using a syntax
similar to the unix filesystem:

     sample> string
     sample:string> /math/hex
     sample:math/hex> ..
     sample:math> hex
     sample:math/hex> /
     sample>

   When in a given mode, you can just type commands relevant to that mode:

     sample:string> subs barnyard 1 3
       Substring = arn
     sample:string> len barnyard
       Length = 8

   You can also explicitely type in the mode for a command.  In this
situation, commands can be typed as MODE/CMD ARGS or MODE CMD ARGS
equivalently:

     sample:string> /math/hex/add 4 6 1
       Total = b
     sample:string> /math mult 4 6 2
       Total = 48

   There are several built-in commands including "..", "/", "help",
"abort", "exit", and "quit".  The last two ("exit" and "quit") are
equivalent and mean to exit and return 0.  "abort" exits with a value of 1.

   There is also online help:

     sample> help

     This is the main help.
     Not a lot of info here.

     Additional help:

     Modes: math string
     Cmds : .. / abort exit help quit

     sample> help /string

     String operations

     Additional help:

     Cmds : .. / abort exit help quit
            len subs

     sample> math
     sample:math> help

     A simple calculator.  Currently it can only
     add and multiply in hex or decimal.

     Additional help:

     Modes: hex
     Cmds : .. / abort exit help quit
            add mult

     sample:math> help add

     Add numbers together.

     sample:math> help /string len

     Returns the length of a string.

     sample:math> help /string/subs

     Take STRING,POS,LEN and returns a substring.

   Currently, Term::TUI does not have much in the way of bells and
whistles, and I doubt it ever will.  It's not designed for a full-blown,
feature-rich user interface.  It's mainly intended for simple control or
config tools (similar to lpc for example) used primarily by the sysadmin
type people (who else is interested in a text-based interface after all
:-).

   There is also a non-interactive form which allows the same interface to
be called in scripts.

     &TUI_Script(\%modes,"/math add 3 5; string; subs barnyard 1 3");

   returns

     Total = 8
     Substring = arn

   TUI DOES use one of the Term::ReadLine modules for the interactive
session, so if you have Term::ReadLine::GNU or Term::ReadLine::Perl
installed, you can use things like command history and command line
editing.

KNOWN PROBLEMS
==============

   None known at this point.

AUTHOR
======

   Sullivan Beck (sbeck@cise.ufl.edu)

provides a simple framework for writing test scripts
****************************************************

NAME
====

     Test - provides a simple framework for writing test scripts

SYNOPSIS
========

     use strict;
     use Test;

     # use a BEGIN block so we print our plan before MyModule is loaded
     BEGIN { plan tests => 14, todo => [3,4] }

     # load your module...
     use MyModule;

     ok(0); # failure
     ok(1); # success

     ok(0); # ok, expected failure (see todo list, above)
     ok(1); # surprise success!

     ok(0,1);             # failure: '0' ne '1'
     ok('broke','fixed'); # failure: 'broke' ne 'fixed'
     ok('fixed','fixed'); # success: 'fixed' eq 'fixed'
     ok('fixed',qr/x/);   # success: 'fixed' =~ qr/x/

     ok(sub { 1+1 }, 2);  # success: '2' eq '2'
     ok(sub { 1+1 }, 3);  # failure: '2' ne '3'
     ok(0, int(rand(2));  # (just kidding :-)

     my @list = (0,0);
     ok @list, 3, "\@list=".join(',',@list);      #extra diagnostics
     ok 'segmentation fault', '/(?i)success/';    #regex match

     skip($feature_is_missing, ...);    #do platform specific test

DESCRIPTION
===========

   See Test/Harness, expects to see particular output when
it executes tests.  This module aims to make writing proper test scripts
just a little bit easier (and less error prone :-).

TEST TYPES
==========

   * NORMAL TESTS

     These tests are expected to succeed.  If they don't something's
     screwed up!

   * SKIPPED TESTS

     Skip is for tests that might or might not be possible to run depending
     on the availability of platform specific features.  The first argument
     should evaluate to true (think "yes, please skip") if the required
     feature is not available.  After the first argument, skip works
     exactly the same way as do normal tests.

   * TODO TESTS

     TODO tests are designed for maintaining an *executable TODO list*.
     These tests are expected NOT to succeed.  If a TODO test does succeed,
     the feature in question should not be on the TODO list, now should it?

     Packages should NOT be released with succeeding TODO tests.  As soon
     as a TODO test starts working, it should be promoted to a normal test
     and the newly working feature should be documented in the release
     notes or change log.

RETURN VALUE
============

   Both ok and skip return true if their test succeeds and false otherwise
in a scalar context.

ONFAIL
======

     BEGIN { plan test => 4, onfail => sub { warn "CALL 911!" } }

   While test failures should be enough, extra diagnostics can be
triggered at the end of a test run.  `onfail' is passed an array ref of
hash refs that describe each test failure.  Each hash will contain at
least the following fields: package, `repetition', and result.  (The file,
line, and test number are not included because their correspondence to a
particular test is tenuous.)  If the test had an expected value or a
diagnostic string, these will also be included.

   The optional `onfail' hook might be used simply to print out the
version of your package and/or how to report problems.  It might also be
used to generate extremely sophisticated diagnostics for a particularly
bizarre test failure.  However it's not a panacea.  Core dumps or other
unrecoverable errors prevent the `onfail' hook from running.  (It is run
inside an END block.)  Besides, `onfail' is probably over-kill in most
cases.  (Your test code should be simpler than the code it is testing,
yes?)

SEE ALSO
========

   See Test/Harness, and, perhaps, test coverage analysis
tools.

AUTHOR
======

   Copyright (c) 1998-1999 Joshua Nathaniel Pritikin.  All rights reserved.

   This package is free software and is provided "as is" without express
or implied warranty.  It may be used, redistributed and/or modified under
the terms of the Perl Artistic License (see
http://www.perl.com/perl/misc/Artistic.html)

Perl module for portable testing of commands and scripts
********************************************************

NAME
====

   Test::Cmd - Perl module for portable testing of commands and scripts

SYNOPSIS
========

     use Test::Cmd;

     $test = Test::Cmd->new(prog => 'program_or_script_to_test',
     			interpreter => 'script_interpreter',
     			string => 'identifier_string',
     			workdir => '',
     			subdir => 'dir',
     			match_sub => $code_ref,
     			verbose => 1);

     $test->verbose(1);

     $test->prog('program_or_script_to_test');

     $test->basename(@suffixlist);

     $test->interpreter('script_interpreter');

     $test->string('identifier string');

     $test->workdir('prefix');

     $test->workpath('subdir', 'file');

     $test->subdir('subdir', ...);
     $test->subdir(['sub', 'dir'], ...);

     $test->write('file', <<'EOF');
     contents of file
     EOF
     $test->write(['subdir', 'file'], <<'EOF');
     contents of file
     EOF

     $test->read(\$contents, 'file');
     $test->read(\@lines, 'file');
     $test->read(\$contents, ['subdir', 'file']);
     $test->read(\@lines, ['subdir', 'file']);

     $test->writable('dir', rwflag);

     $test->preserve(condition, ...);

     $test->cleanup(condition);

     $test->run(prog => 'program_or_script_to_test',
     		interpreter => 'script_interpreter',
     		chdir => 'dir', args => 'arguments', stdin => <<'EOF');
     input to program
     EOF

     $test->pass(condition);
     $test->pass(condition, funcref);

     $test->fail(condition);
     $test->fail(condition, funcref);
     $test->fail(condition, funcref, caller);

     $test->no_result(condition);
     $test->no_result(condition, funcref);
     $test->no_result(condition, funcref, caller);

     $test->stdout;
     $test->stdout(run_number);

     $test->stderr;
     $test->stderr(run_number);

     $test->diff();

     $test->match($lines, $matches);

     $test->match_exact(\@lines, \@matches);
     $test->match_exact($lines, $matches);

     $test->match_regex(\@lines, \@regexes);
     $test->match_regex($lines, $regexes);

     sub func {
     	my ($self, $lines, $matches) = @_;
     	# code to match $line and $matches
     }
     $test->match_sub(\&func);
     $test->match_sub(sub { code to match $_[1] and $[2] });

     $test->here;

DESCRIPTION
===========

   The `Test::Cmd' module provides a framework for portable automated
testing of executable commands and scripts (in any language, not just
Perl), especially commands and scripts that require file system
interaction.

   In addition to running tests and evaluating conditions, the `Test::Cmd'
module manages and cleans up one or more temporary workspace directories,
and provides methods for creating files and directories in those workspace
directories from in-line data (that is, here-documents), allowing tests to
be completely self-contained.

   The `Test::Cmd' module inherits File::Spec methods
(`file_name_is_absolute()', `catfile()', etc.) to support writing tests
portably across a variety of operating and file systems.

   A `Test::Cmd' environment object is created via the usual invocation:

     $test = Test::Cmd->new();

   Arguments to the `Test::Cmd::new' method are keyword-value pairs that
may be used to initialize the object, typically by invoking the same-named
method as the keyword.

   No `Test::Cmd' methods (including the new() method) exit, die or throw
any other sorts of exceptions (but they all do return useful error
indications).  Exceptions should be handled by the test itself or a
subclass specific to the program under test.

   The `Test::Cmd' module may be used in conjunction with the Test module
to report test results in a format suitable for the Test::Harness module.
A typical use would be to call the `Test::Cmd' methods to prepare and
execute the test, and call the `ok()' method exported by the Test module
to test the conditions:

     use Test;
     use Test::Cmd;
     BEGIN { $| = 1; plan => 3 }
     $test = Test::Cmd->new(prog => 'test_program', workdir => '');
     ok($test);
     $wrote_file = $test->write('input_file', <<'EOF');
     This is input to test_program,
     which we expect to process this
     and exit successfully (status 0).
     EOF
     ok($wrote_file);
     $test->run(args => 'input_file');
     ok($? == 0);

   Alternatively, the `Test::Cmd' module provides `pass()', `fail()', and
`no_result()' methods that report test results for use with the Aegis
change management system.  These methods terminate the test immediately,
reporting PASSED, FAILED, or NO RESULT respectively, and exiting with
status 0 (success), 1 or 2 respectively.  This allows for a distinction
between an actual failed test and a test that could not be properly
evaluated because of an external condition (such as a full file system or
incorrect permissions):

     use Test::Cmd;
     $test = Test::Cmd->new(prog => 'test_program', workdir => '');
     Test::Cmd->no_result(! $test);
     $wrote_file = $test->write('input_file', <<'EOF');
     This is input to test_program,
     which we expect to process this
     and exit successfully (status 0).
     EOF
     $test->no_result(! $wrote_file);
     $test->run(args => 'input_file');
     $test->fail($? != 0);
     $test->pass;

   It is not a good idea to intermix the two reporting models.  If you use
the Test module and its ok method, do not use the `Test::Cmd' pass, fail
or `no_result' methods, and vice versa.

METHODS
=======

   Methods supported by the `Test::Cmd' module include:

new
     Create a new `Test::Cmd' environment.  Arguments with which to
     initialize the environment are passed in as keyword-value pairs.
     Fails if a specified temporary working directory or subdirectory
     cannot be created.  Does NOT die or exit on failure, but returns
     FALSE if the test environment object cannot be created.

verbose
     Sets the verbose level for the environment object to the specified
     value.

prog
     Specifies the executable program or script to be tested.  Returns the
     absolute path name of the current program or script.

`basename'
     Returns the basename of the current program or script.  Any specified
     arguments are a list of file suffixes that may be stripped from the
     basename.

`interpreter'
     Specifies the program to be used to interpret prog as a script.
     Returns the current value of `interpreter'.

string
     Specifies an identifier string for the functionality being tested to
     be printed on failure or no result.

`workdir'
     When an argument is specified, creates a temporary working directory
     with the specified name.  If the argument is a NULL string ("), the
     directory is named `testcmd' by default, followed by the unique ID of
     the executing process.

     Returns the absolute pathname to the temporary working directory, or
     FALSE if the directory could not be created.

`workpath'
     Returns the absolute path name to a subdirectory or file under the
     current temporary working directory by concatenating the temporary
     working directory name with the specified arguments.

`subdir'
     Creates new subdirectories under the temporary working dir, one for
     each argument.  An argument may be an array reference, in which case
     the array elements are concatenated together using the
     `File::Spec-&'catfile> method.  Subdirectories multiple levels deep
     must be created via a separate argument for each level:

          $test->subdir('sub', ['sub', 'dir'], [qw(sub dir ectory)]);

     Returns the number of subdirectories actually created.

write
     Writes the specified text (second argument) to the specified file name
     (first argument).  The file name may be an array reference, in which
     case all the array elements except the last are subdirectory names to
     be concatenated together.  The file is created under the temporary
     working directory.  Any subdirectories in the path must already exist.

read
     Reads the contents of the specified file name (second argument) into
     the scalar or array referred to by the first argument.  The file name
     may be an array reference, in which case all the array elements except
     the last are subdirectory names to be concatenated together.  The file
     is assumed to be under the temporary working directory unless it is an
     absolute path name.

     Returns TRUE on successfully opening and reading the file, FALSE
     otherwise.

writable
     Makes the specified directory tree writable (`rwflag' == TRUE) or not
     writable (`rwflag' == FALSE).

preserve
     Arranges for the temporary working directories for the specified
     `Test::Cmd' environment to be preserved for one or more conditions.
     If no conditions are specified, arranges for the temporary working
     directories to be preserved for all conditions.

cleanup
     Removes any temporary working directories for the specified
     `Test::Cmd' environment.  If the environment variable `PRESERVE' was
     set when the `Test::Cmd' module was loaded, temporary working
     directories are not removed.  If any of the environment variables
     `PRESERVE_PASS', `PRESERVE_FAIL', or `PRESERVE_NO_RESULT' were set
     when the `Test::Cmd' module was loaded, then temporary working
     directories are not removed if the test passed, failed, or had no
     result, respectively.  Temporary working directories are also
     preserved for conditions specified via the preserve method.

     Typically, this method is not called directly, but is used when the
     script exits to clean up temporary working directories as appropriate
     for the exit status.

run
     Runs a test of the program or script for the test environment.
     Standard output and error output are saved for future retrieval via
     the stdout and stderr methods.

     Arguments are supplied as keyword-value pairs:

    args
          Specifies the command-line arguments to be supplied to the
          program or script under test for this run:

               $test->run(args => 'arg1 arg2');

    chdir
          Changes directory to the path specified as the value argument:

               $test->run(chdir => 'xyzzy');

          If the specified path is not an absolute path name (begins with
          '/' on Unix systems), then the subdirectory is relative to the
          temporary working directory for the environment
          (`$test-&'workdir>).  Note that, by default, the `Test::Cmd'
          module does NOT chdir to the temporary working directory, so to
          execute the test under the temporary working directory, you must
          specify an explicit chdir to the current directory:

               $test->run(chdir => '.');		# Unix-specific

               $test->run(chdir => $test->curdir);	# portable

    `interpreter'
          Specifies the program to be used to interpret prog as a script,
          for this run only.  This does not change the
          `$test-&'interpreter> value of the test environment.

    prog
          Specifies the executable program or script to be run, for this
          run only.  This does not change the `$test-&'prog> value of the
          test environment.

    stdin
          Pipes the specified value (string or array ref) to the program
          or script under test for this run:

               $test->run(stdin => <<_EOF_);
               input to the program under test
               _EOF_

     Returns the exit status of the program or script.

pass
     Exits the test successfully.  Reports "PASSED" on the error output and
     exits with a status of 0.  If a condition is supplied, only exits the
     test if the condition evaluates TRUE.  If a function reference is
     supplied, executes the function before reporting and exiting.

fail
     Exits the test unsuccessfully.  Reports "FAILED test of {string} at
     line {line} of {file}." on the error output and exits with a status
     of 1.  If a condition is supplied, only exits the test if the
     condition evaluates TRUE.  If a function reference is supplied,
     executes the function before reporting and exiting.  If a caller
     level is supplied, prints a simple calling trace N levels deep as
     part of reporting the failure.

`no_result'
     Exits the test with an indeterminate result (the test could not be
     performed due to external conditions such as, for example, a full
     file system).  Reports "NO RESULT for test of {string} at line {line}
     of {file}." on the error output and exits with a status of 2.  If a
     condition is supplied, only exits the test if the condition evaluates
     TRUE.  If a function reference is supplied, executes the function
     before reporting and exiting.  If a caller level is supplied, prints
     a simple calling trace N levels deep as part of reporting the failure.

stdout
     Returns the standard output from the specified run number.  If there
     is no specified run number, then returns the standard output of the
     last run.  Returns the standard output as either a scalar or an array
     of output lines, as appropriate for the calling context.  Returns
     undef if there has been no test run.

stderr
     Returns the error output from the specified run number.  If there is
     no specified run number, then returns the error output of the last
     run.  Returns the error output as either a scalar or an array of
     output lines, as apporpriate for the calling context.  Returns undef
     if there has been no test run.

diff
     Not Yet Implemented.

match
     Matches one or more input lines against an equal number of expected
     lines using the currently-registered line-matching function.  The
     default line-matching function is the `match_regex' method, which
     means that the default is to match lines against regular expressions.

`match_exact'
     Compares two arrays of lines for exact matches.  The arguments are
     passed in as either scalars, in which case each is split on newline
     boundaries, or as array references.  An unequal number of lines in
     the two arrays fails immediately and returns FALSE before any
     comparisons are performed.

     Returns TRUE if each line matched its corresponding line in the other
     array, FALSE otherwise.

`match_regex'
     Matches one or more input lines against an equal number of regular
     expressions.  The arguments are passed in as either scalars, in which
     case each is split on newline boundaries, or as array references.
     Trailing newlines are stripped from each line and regular expression.
     An unequal number of lines and regular expressions fails immediately
     and returns FALSE before any comparisons are performed.  Comparison is
     performed for each entire line, that is, with each regular expression
     anchored at both the start of line (^) and end of line ($).

     Returns TRUE if each line matched each regular expression, FALSE
     otherwise.

`match_sub'
     Registers the specified code reference as the line-matching function
     to be called by the match method.  This can be a user-supplied
     subroutine, or the `match_exact' or `match_regex' methods supplied by
     the `Test::Cmd' module:

          $test->match_sub(\&Test::Cmd::match_exact);

          $test->match_sub(\&Test::Cmd::match_regex);

     The `match_exact' and `match_regex' subroutine names are exportable
     from the `Test::Cmd' module, and may be specified at object
     initialization:

          use Test::Cmd qw(match_exact match_regex);
          $test_exact = Test::Cmd->new(match_sub => \&match_exact);
          $test_regex = Test::Cmd->new(match_sub => \&match_regex);

`here'
     Returns the absolute path name of the current working directory.
     (This is essentially the same as the `Cwd::cwd' method, except that
     the `Test::Cmd::here' method preserves the directory separators
     exactly as returned by the underlying operating-system-dependent
     method.  The `Cwd::cwd' method canonicalizes all directory separators
     to '/', which makes for consistent path name representations within
     Perl, but may mess up another program or script to which you try to
     pass the path name.)

ENVIRONMENT
===========

   Several environment variables affect the default values in a newly
created `Test::Cmd' environment object.  These environment variables must
be set when the module is loaded, not when the object is created.

`PRESERVE'
     If set to a true value, all temporary working directories will be
     preserved on exit, regardless of success or failure of the test.  The
     full path names of all temporary working directories will be reported
     on error output.

`PRESERVE_FAIL'
     If set to a true value, all temporary working directories will be
     preserved on exit from a failed test.  The full path names of all
     temporary working directories will be reported on error output.

`PRESERVE_NO_RESULT'
     If set to a true value, all temporary working directories will be
     preserved on exit from a test for which there is no result.  The full
     path names of all temporary working directories will be reported on
     error output.

`PRESERVE_PASS'
     If set to a true value, all temporary working directories will be
     preserved on exit from a successful test.  The full path names of all
     temporary working directories will be reported on error output.

VERBOSE
     When set to a true value, enables verbose reporting of various
     internal things (path names, exact command line being executed, etc.).

PORTABLE TESTS
==============

   Although the `Test::Cmd' module is intended to make it easier to write
portable tests for portable utilities that interact with file systems, it
is still very easy to write non-portable tests if you're not careful.

   The best and most comprehensive set of portability guidelines is the
standard "Writing portable Perl" document at:

     http://www.perl.com/pub/doc/manual/html/pod/perlport.html

   To reiterate one important point from the "WpP" document:  Not all Perl
programs have to be portable.  If the program or script you're testing is
UNIX-specific, you can (and should) use the `Test::Cmd' module to write
UNIX-specific tests.

   That having been said, here are some hints that may help keep your tests
portable, if that's a requirement.

Use the `Test::Cmd-&'here> method for current directory path.
     The normal Perl way to fetch the current working directory is to use
     the `Cwd::cwd' method.  Unfortunately, the `Cwd::cwd' method
     canonicalizes the path name it returns, changing the native directory
     separators into the forward slashes favored by Perl and UNIX.  For
     most Perl scripts, this makes a great deal of sense and keeps code
     uncluttered.

     Passing in a file name that has had its directory separators altered,
     however, may confuse the command or script under test, or make it
     difficult to compare output from the command or script with an
     expected result.  The `Test::Cmd::here' method returns the absolute
     path name of the current working directory, like `Cwd::cwd', but does
     not manipulate the returned path in any way.

Use File::Spec methods for manipulating path names.
     The File::Spec module provides a system-independent interface for
     manipulating path names.  Because the `Test::Cmd' class is a sub-class
     of the File::Spec class, you can use these methods directly as
     follows:

          if (! Test::Cmd->file_name_is_absolute($prog)) {
          	my $prog = Test::Cmd->catfile(Test::Cmd->here, $prog);
          }

     For details about the available methods and their use, see the
     documentation for the File::Spec module and its sub-modules,
     especially the File::Spec::Unix modules.

Use Config for file-name suffixes, where possible.
     The standard Config module provides values that reflect the file-name
     suffixes on the system for which the Perl executable was built.  This
     provides convenient portability for situations where a file name may
     have different extensions on different systems:

          $foo_exe = "foo$Config{_exe}";
          ok(-f $foo_exe);

     (Unfortunately, there is no existing `$Config' value that specifies
     the suffix for a directly-executable Perl script.)

Avoid generating executable programs or scripts.
     How to make a file or script executable varies widely from system to
     system, some systems using file name extensions to indicate
     executability, others using a file permission bit.  The differences
     are complicated to accomodate in a portable test script.  The easiest
     way to deal with this complexity is to avoid it if you can.

     If your test somehow requires executing a script that you generate
     from the test itself, the best way is to generate the script in Perl
     and then explicitly feed it to the Perl executable on the local
     system.  To be maximally portable, use the $^X variable instead of
     hard-coding "perl" into the string you execute:

          $line = "This is output from the generated perl script.";
          $test->write('script', <<EOF);
          print STDOUT "$line\\n";
          EOF
          $output = `$^X script`;
          ok($output eq "$line\n");

     This completely avoids having to make the `script' file itself
     executable.  (Since you're writing your test in Perl, it's safe to
     assume that Perl itself is executable.)

     If you must generate a directly-executable script, then use the
     `$Config{'startperl'}' variable at the start of the script to generate
     the appropriate magic that will execute it as a Perl script:

          use Config;
          $line = "This is output from the generated perl script.";
          $test->write('script', <<EOF);
          $Config{'startperl'};
          print STDOUT "$line\\n";
          EOF
          chdir($test->workdir);
          chmod(0755, 'script');	# POSIX-SPECIFIC
          $output = `script`;
          ok($output eq "$line\n");

   Addtional hints on writing portable tests are welcome.

SEE ALSO
========

   perl(1), File::Find(3), File::Spec(3), Test(3), Test::Harness(3).

   A rudimentary page for the Test::Cmd module is available at:

     http://www.baldmt.com/Test-Cmd/

AUTHORS
=======

   Steven Knight, knight@baldmt.com

COPYRIGHT
=========

   Copyright 1999-2000 Steven Knight.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

ACKNOWLEDGEMENTS
================

   Thanks to Greg Spencer for the inspiration to create this package and
the initial draft of its implementation as a specific testing package for
the Cons software construction utility.  Information about Cons is
available at:

     http://www.dsmit.com/cons/

   The general idea of managing temporary working directories in this way,
as well as the test reporting of the pass, fail and `no_result' methods,
come from the testing framework invented by Peter Miller for his Aegis
project change supervisor.  Aegis is an excellent bit of work which
integrates creation and execution of regression tests into the software
development process.  Information about Aegis is available at:

     http://www.tip.net.au/~millerp/aegis.html

run perl standard test scripts with statistics
**********************************************

NAME
====

   Test::Harness - run perl standard test scripts with statistics

SYNOPSIS
========

   use Test::Harness;

   runtests(@tests);

DESCRIPTION
===========

   (By using the Test, module, you can write test scripts
without knowing the exact output this module expects.  However, if you
need to know the specifics, read on!)

   Perl test scripts print to standard output `"ok N"' for each single
test, where N is an increasing sequence of integers. The first line output
by a standard test script is `"1..M"' with M being the number of tests
that should be run within the test script. Test::Harness::runtests(@tests)
runs all the testscripts named as arguments and checks standard output for
the expected `"ok N"' strings.

   After all tests have been performed, runtests() prints some performance
statistics that are computed by the Benchmark module.

The test script output
----------------------

   Any output from the testscript to standard error is ignored and
bypassed, thus will be seen by the user. Lines written to standard output
containing `/^(not\s+)?ok\b/' are interpreted as feedback for runtests().
All other lines are discarded.

   It is tolerated if the test numbers after ok are omitted. In this case
Test::Harness maintains temporarily its own counter until the script
supplies test numbers again. So the following test script

     print <<END;
     1..6
     not ok
     ok
     not ok
     ok
     ok
     END

   will generate

     FAILED tests 1, 3, 6
     Failed 3/6 tests, 50.00% okay

   The global variable $Test::Harness::verbose is exportable and can be
used to let runtests() display the standard output of the script without
altering the behavior otherwise.

   The global variable $Test::Harness::switches is exportable and can be
used to set perl command line options used for running the test script(s).
The default value is -w.

   If the standard output line contains substring ` # Skip' (with
variations in spacing and case) after ok or `ok NUMBER', it is counted as
a skipped test.  If the whole testscript succeeds, the count of skipped
tests is included in the generated output.

   Test::Harness reports the text after ` # Skip(whatever)' as a reason
for skipping.  Similarly, one can include a similar explanation in a
`1..0' line emitted if the test is skipped completely:

     1..0 # Skipped: no leverage found

EXPORT
======

   `&runtests' is exported by Test::Harness per default.

DIAGNOSTICS
===========

`All tests successful.\nFiles=%d,  Tests=%d, %s'
     If all tests are successful some statistics about the performance are
     printed.

`FAILED tests %s\n\tFailed %d/%d tests, %.2f%% okay.'
     For any single script that has failing subtests statistics like the
     above are printed.

`Test returned status %d (wstat %d)'
     Scripts that return a non-zero exit status, both `$? >> 8' and $? are
     printed in a message similar to the above.

`Failed 1 test, %.2f%% okay. %s'
`Failed %d/%d tests, %.2f%% okay. %s'
     If not all tests were successful, the script dies with one of the
     above messages.

ENVIRONMENT
===========

   Setting `HARNESS_IGNORE_EXITCODE' makes harness ignore the exit status
of child processes.

   Setting `HARNESS_NOTTY' to a true value forces it to behave as though
STDOUT were not a console.  You may need to set this if you don't want
harness to output more frequent progress messages using carriage returns.
Some consoles may not handle carriage returns properly (which results in a
somewhat messy output).

   Setting `HARNESS_COMPILE_TEST' to a true value will make harness attempt
to compile the test using perlcc before running it.

   If `HARNESS_FILELEAK_IN_DIR' is set to the name of a directory, harness
will check after each test whether new files appeared in that directory,
and report them as

     LEAKED FILES: scr.tmp 0 my.db

   If relative, directory name is with respect to the current directory at
the moment runtests() was called.  Putting absolute path into
`HARNESS_FILELEAK_IN_DIR' may give more predicatable results.

   The value of `HARNESS_PERL_SWITCHES' will be prepended to the switches
used to invoke perl on each test.  For example, setting
`HARNESS_PERL_SWITCHES' to "-W" will run all tests with all warnings
enabled.

   Harness sets `HARNESS_ACTIVE' before executing the individual tests.
This allows the tests to determine if they are being executed through the
harness or by any other means.

SEE ALSO
========

   See Test, for writing test scripts and also Benchmark,
for the underlying timing routines.

AUTHORS
=======

   Either Tim Bunce or Andreas Koenig, we don't know. What we know for
sure is, that it was inspired by Larry Wall's TEST script that came with
perl distributions for ages. Numerous anonymous contributors exist.
Current maintainer is Andreas Koenig.

BUGS
====

   Test::Harness uses $^X to determine the perl binary to run the tests
with. Test scripts running via the shebang (#!) line may not be portable
because $^X is not consistent for shebang scripts across platforms. This
is no problem when Test::Harness is run with an absolute path to the perl
binary or when $^X can be found in the path.

easy creation of test scripts
*****************************

NAME
====

   *Test::Helper* - easy creation of test scripts

SYNOPSIS
========

     use Test::Helper;
     test {
       comm 'Doing first part of test';
       ok $variable==$correct_value;
       ok not runs {this_should_die()};
     };

DESCRIPTION
===========

   Enclose the body of your test script within a test block. Within that
block, run individual tests with the ok function, which should be passed a
scalar that you desire to be true; this will print "ok number" or "not ok
number" as appropriate. Similarly, the *runs* command will expect its body
not to signal an error when run; use it with ok, negated or not. Note that
the test block keeps track of how many tests there are and outputs the
first line accordingly (it stores up the messages); if an uncaught
exception is raised within the body, it simulates one last failed test and
propagates the exception in order to ensure that it is counted as a
failure. *comm* just writes out a comment to the standard output where it
will be visible in verbose testing mode. syntax_check checks the syntax of
modules and scripts listed in the MANIFEST.

SEE ALSO
========

   See `Test::Harness(3)' in this node, for how test scripts are run; and
`ExtUtils::MakeMaker(3)' in this node, for where to put test scripts
(usually as files `t/*.t') in a distribution.

AUTHORS
=======

   Jesse Glick, *jglick@sig.bsh.com*

REVISION
========

   X<$Format: "`$Source$' last modified $Date$. Release
$TestHelperRelease$. $Copyright$"$> `Test-Helper/lib/Test/Helper.pm' last
modified Fri, 05 Sep 1997 16:08:15 -0400. Release 0.002. Copyright (c)
1997 Strategic Interactive Group. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Procedural style unit testing interface
***************************************

NAME
====

     Test::Unit - Procedural style unit testing interface

SYNOPSIS
========

     use Test::Unit;

     # your code to be tested goes here

     sub foo { return 23 };
     sub bar { return 42 };

     # define tests

     sub test_foo { assert(foo() == 23, "Your message here"); }
     sub test_bar { assert(bar() == 42, "I will be printed if this fails"); }

     # set_up and tear_down are used to
     # prepare and release resources need for testing

     sub set_up    { print "hello world\n"; }
     sub tear_down { print "leaving world again\n"; }

     # run your test

     create_suite();
     run_suite();

DESCRIPTION
===========

     Test::Unit is the procedural style interface to a sophisticated
     unit testing framework for Perl that is derived from the JUnit
     testing framework for Java by Kent Beck and Erich Gamma. While
     this framework is originally intended to support unit testing
     in an object-oriented development paradigm (with support for
     inheritance of tests etc.), Test::Unit is intended to  provide
     a simpler interface to the framework that is more suitable for
     use in a scripting style environment. Therefore, Test::Unit
     does not provide much support for an object-oriented approach
     to unit testing - if you want that, please have a look at
     Test::Unit::TestCase.

     You test a given unit (a script, a module, whatever) by using
     Test::Unit, which exports the following routines into your
     namespace:

     assert()       - used to assert that a boolean condition is true
     create_suite() - used to create a test suite consisting of all
                      methods with a name prefix of 'test'
     run_suite()    - runs the test suite (text output)
     add_suite()    - used to add test suites to each other

     For convenience, create_suite() will automatically build a test
     suite for a given package. This will build a test case for each
     subroutine in the package given that has a name starting with
     "test" and pack them all together into one TestSuite object for
     easy testing. If you dont give a package name to create_suite(),
     the current package is taken as default.

     Test output is one status line (a "." for every successful test
     run, or an "F" for any failed test run, to indicate progress),
     one result line ("OK" or "!!!FAILURES!!!"), and possibly many
     lines reporting detailed error messages for any failed tests.

     Please remember, Test::Unit is intended to be a simple and
     convenient interface. If you need more functionality, take the
     object-oriented approach outlined in Test::Unit::TestCase.

AUTHOR
======

     Copyright (c) 2000, 2001 Christian Lemburg, <lemburg@acm.org>.

     All rights reserved. This program is free software; you can
     redistribute it and/or modify it under the same terms as
     Perl itself.

     Thanks go to the other PerlUnit framework people:
     Brian Ewins, Cayte Lindner, J.E. Fritz, Zhon Johansen.

     Thanks for patches go to:
     Matthew Astley, David Esposito.

SEE ALSO
========

     - Test::Unit::TestCase
     - the procedural style examples in the examples directory

unit testing framework assertion class
**************************************

NAME
====

     Test::Unit::Assert - unit testing framework assertion class

SYNOPSIS
========

     # this class is not intended to be used directly,
     # normally you get the functionality by subclassing from
     # Test::Unit::TestCase

     use Test::Unit::TestCase;

     # more code here ...

     $self->assert($your_condition_here, $your_optional_message_here);

     # NOTE: if you want to use regexes in comparisons, do it like this:

     $self->assert(scalar("foo" =~ /bar/), $your_optional_message_here);

DESCRIPTION
===========

     This class is used by the framework to assert boolean conditions
     that determine the result of a given test. The optional message
     will be displayed if the condition fails. Normally, it is not
     used directly, but you get the functionality by subclassing from
     Test::Unit::TestCase.

     There is one problem with assert(): the arguments to assert() are
     evaluated in list context, e.g. making a failing regex "pull" the
     message into the place of the first argument. Since this is ususally
     just plain wrong, please use scalar() to force the regex comparison
     to yield a useful boolean value. I currently do not see a way around
     this, since function prototypes don't work for object methods, and
     any other tricks (counting argument number, and complaining if there
     is only one argument and it looks like a string, etc.) don't appeal
     to me. Thanks to Matthew Astley for noting this effect.

     The procedural interface to this framework, Test::Unit, does not have
     this problem, as it exports a "normal" assert() function, and that can
     and does use a function prototype to correct the problem.

AUTHOR
======

     Copyright (c) 2000 Christian Lemburg, <lemburg@acm.org>.

     All rights reserved. This program is free software; you can
     redistribute it and/or modify it under the same terms as
     Perl itself.

     Thanks go to the other PerlUnit framework people:
     Brian Ewins, Cayte Lindner, J.E. Fritz, Zhon Johansen.

     Thanks for patches go to:
     Matthew Astley, David Esposito.

SEE ALSO
========

     - Test::Unit::TestCase
     - Test::Unit::Exception
     - The framework self-testing suite (Test::Unit::tests::AllTests)

unit testing framework exception class
**************************************

NAME
====

     Test::Unit::Exception - unit testing framework exception class

SYNOPSIS
========

     # this class is not intended to be used directly

DESCRIPTION
===========

     This class is used by the framework to communicate the result
     of assertions, which will throw an instance of a subclass
     of this class in case of errors or failures.

AUTHOR
======

     Copyright (c) 2000 Christian Lemburg, <lemburg@acm.org>.

     All rights reserved. This program is free software; you can
     redistribute it and/or modify it under the same terms as
     Perl itself.

     Thanks go to the other PerlUnit framework people:
     Brian Ewins, Cayte Lindner, J.E. Fritz, Zhon Johansen.

     Thanks for patches go to:
     Matthew Astley.

SEE ALSO
========

     - Test::Unit::Assert
     - Test::Unit::ExceptionError
     - Test::Unit::ExceptionFailure

unit testing framework exception class
**************************************

NAME
====

     Test::Unit::ExceptionError - unit testing framework exception class

SYNOPSIS
========

     # this class is not intended to be used directly

DESCRIPTION
===========

     This class is used by the framework to communicate the result
     of assertions, which will throw an instance of this class
     in case of errors (that is, syntax errors and the like, not
     failed tests, as these are classified as failures).

AUTHOR
======

     Copyright (c) 2000 Christian Lemburg, <lemburg@acm.org>.

     All rights reserved. This program is free software; you can
     redistribute it and/or modify it under the same terms as
     Perl itself.

     Thanks go to the other PerlUnit framework people:
     Brian Ewins, Cayte Lindner, J.E. Fritz, Zhon Johansen.

SEE ALSO
========

     - Test::Unit::Exception
     - Test::Unit::Assert

unit testing framework exception class
**************************************

NAME
====

     Test::Unit::ExceptionFailure - unit testing framework exception class

SYNOPSIS
========

     # this class is not intended to be used directly

DESCRIPTION
===========

     This class is used by the framework to communicate the result
     of assertions, which will throw an instance of this class
     in case of failures (that is, failed tests, not syntax errors
     and the like, these are classified as errors).

AUTHOR
======

     Copyright (c) 2000 Christian Lemburg, <lemburg@acm.org>.

     All rights reserved. This program is free software; you can
     redistribute it and/or modify it under the same terms as
     Perl itself.

     Thanks go to the other PerlUnit framework people:
     Brian Ewins, Cayte Lindner, J.E. Fritz, Zhon Johansen.

SEE ALSO
========

     - Test::Unit::Exception
     - Test::Unit::Assert

unit testing framework helper class
***********************************

NAME
====

     Test::Unit::HarnessUnit - unit testing framework helper class

SYNOPSIS
========

     # this class is not intended to be used directly

DESCRIPTION
===========

     This is a test runner which outputs in the same format that
     Test::Harness expects.

AUTHOR
======

     Copyright (c) 2000 Brian Ewins.

     All rights reserved. This program is free software; you can
     redistribute it and/or modify it under the same terms as
     Perl itself.

     Thanks go to the other PerlUnit framework people:
     Christian Lemburg, Cayte Lindner, J.E. Fritz, Zhon Johansen.

SEE ALSO
========

     - Test::Unit::UnitHarness
     - Test::Unit::TestRunner
     - Test::Unit::TkTestRunner

unit testing framework helper class
***********************************

NAME
====

     Test::Unit::InnerClass - unit testing framework helper class

SYNOPSIS
========

     # this class is not intended to be used directly

DESCRIPTION
===========

     This class is used by the framework to emulate the anonymous
     inner classes feature of Java. It is much easier to port Java
     to Perl using this class.

AUTHOR
======

     Copyright (c) 2000 Christian Lemburg, <lemburg@acm.org>.

     All rights reserved. This program is free software; you can
     redistribute it and/or modify it under the same terms as
     Perl itself.

     Thanks go to the other PerlUnit framework people:
     Brian Ewins, Cayte Lindner, J.E. Fritz, Zhon Johansen.

SEE ALSO
========

     - the JUnit testing framework by Kent Beck and Erich Gamma

unit testing framework abstract base class
******************************************

NAME
====

     Test::Unit::Test - unit testing framework abstract base class

SYNOPSIS
========

     # this class is not intended to be used directly

DESCRIPTION
===========

     This class is used by the framework to define the interface
     of a test. It is an abstract base class implemented by
     Test::Unit::TestCase and Test::Unit::TestSuite.

     Due to the nature of the Perl OO implementation, this class
     is not really needed, but rather serves as documentation
     of the interface.

AUTHOR
======

     Copyright (c) 2000 Christian Lemburg, <lemburg@acm.org>.

     All rights reserved. This program is free software; you can
     redistribute it and/or modify it under the same terms as
     Perl itself.

     Thanks go to the other PerlUnit framework people:
     Brian Ewins, Cayte Lindner, J.E. Fritz, Zhon Johansen.

SEE ALSO
========

     - Test::Unit::Assert
     - Test::Unit::TestCase
     - Test::Unit::TestSuite

unit testing framework base class
*********************************

NAME
====

     Test::Unit::TestCase - unit testing framework base class

SYNOPSIS
========

     package FooBar;
     use base qw(Test::Unit::TestCase);

     sub new {
         my $self = shift()->SUPER::new(@_);
         # your state for fixture here
         return $self;
     }

     sub set_up {
         # provide fixture
     }
     sub tear_down {
         # clean up after test
     }
     sub test_foo {
         # test the foo feature
     }
     sub test_bar {
         # test the bar feature
     }

DESCRIPTION
===========

     (Taken from the JUnit TestCase class documentation)

     A test case defines the "fixture" (resources need for testing)
     to run multiple tests. To define a test case:

     1) implement a subclass of TestCase
     2) define instance variables that store the state of the fixture
     3) initialize the fixture state by overriding set_up()
     4) clean-up after a test by overriding tear_down().

     Each test runs in its own fixture so there can be no side
     effects among test runs. Here is an example:

     package MathTest;
     use base qw(Test::Unit::TestCase);

     sub new {
     	  my $self = shift()->SUPER::new(@_);
     	  $self->{value_1} = 0;
     	  $self->{value_2} = 0;
     	  return $self;
     }

     sub set_up {
     	  my $self = shift;
     	  $self->{value_1} = 2;
     	  $self->{value_2} = 3;
     }

         For each test implement a method which interacts with the
         fixture.  Verify the expected results with assertions specified
         by calling $self->assert() with a boolean value.

     sub test_add {
     	  my $self = shift;
     	  my $result = $self->{value_1} + $self->{value_2};
     	  $self->assert($result == 5);
     }

         Once the methods are defined you can run them. The normal way to
         do this uses reflection to implement run_test. It dynamically
         finds and invokes a method. For this the name of the test case
         has to correspond to the test method to be run. The tests to be
         run can be collected into a TestSuite. The framework provides
         different test runners, which can run a test suite and collect
         the results. A test runner either expects a method suite()
         as the entry point to get a test to run or it will extract the
         suite automatically.

     If you do not like the rather verbose backtrace that appears
     when a test fails, you can use the quell_backtrace() method.
     You will get any message provided, but not the backtrace.

AUTHOR
======

     Framework JUnit authored by Kent Beck and Erich Gamma.

     Ported from Java to Perl by Christian Lemburg.

     Copyright (c) 2000 Christian Lemburg, <lemburg@acm.org>.

     All rights reserved. This program is free software; you can
     redistribute it and/or modify it under the same terms as
     Perl itself.

     Thanks go to the other PerlUnit framework people:
     Brian Ewins, Cayte Lindner, J.E. Fritz, Zhon Johansen.

     Thanks for patches go to:
     Matthew Astley.

SEE ALSO
========

     - Test::Unit::TestSuite
     - Test::Unit::TestRunner
     - Test::Unit::TkTestRunner
     - For further examples, take a look at the framework self test
       collection (Test::Unit::tests::AllTests).

unit testing framework helper class
***********************************

NAME
====

     Test::Unit::TestFailure - unit testing framework helper class

SYNOPSIS
========

     # this class is not intended to be used directly

DESCRIPTION
===========

     This class is used by the framework to record the results
     of failed tests, which will throw an instance of a subclass of
     Test::Unit::Exception in case of errors or failures.

AUTHOR
======

     Copyright (c) 2000 Christian Lemburg, <lemburg@acm.org>.

     All rights reserved. This program is free software; you can
     redistribute it and/or modify it under the same terms as
     Perl itself.

     Thanks go to the other PerlUnit framework people:
     Brian Ewins, Cayte Lindner, J.E. Fritz, Zhon Johansen.

SEE ALSO
========

     - Test::Unit::TestResult
     - Test::Unit::Exception

unit testing framework abstract base class
******************************************

NAME
====

     Test::Unit::TestListener - unit testing framework abstract base class

SYNOPSIS
========

     # this class is not intended to be used directly

DESCRIPTION
===========

     This class is used by the framework to define the interface
     of a test listener. It is an abstract base class implemented by
     the test runners.

     Due to the nature of the Perl OO implementation, this class
     is not really needed, but rather serves as documentation
     of the interface.

     Each of the add_ methods gets two arguments: 'test' and
     'exception'.  The test is a Test::Unit::Test and the exception
     is a Test::Unit::Exception.  Typically you want to display
     test->name() and keep the rest as details.

AUTHOR
======

     Copyright (c) 2000 Brian Ewins, Christian Lemburg, <lemburg@acm.org>.

     All rights reserved. This program is free software; you can
     redistribute it and/or modify it under the same terms as
     Perl itself.

     Thanks go to the other PerlUnit framework people:
     Cayte Lindner, J.E. Fritz, Zhon Johansen.

SEE ALSO
========

     - Test::Unit::Exception
     - Test::Unit::TestRunner
     - Test::Unit::TkTestRunner

unit testing framework helper class
***********************************

NAME
====

     Test::Unit::TestLoader - unit testing framework helper class

SYNOPSIS
========

     # this class is not intended to be used directly

DESCRIPTION
===========

     This class is used by the framework to load testcase classes
     into the runtime environment. It handles testcase class names
     (that is, classes inheriting from Test::Unit::TestCase),
     Test::Harness style test files, and directory names.

     =head1 AUTHOR

     Copyright (c) 2000 Brian Ewins.

     All rights reserved. This program is free software; you can
     redistribute it and/or modify it under the same terms as
     Perl itself.

     Thanks go to the other PerlUnit framework people:
     Christian Lemburg, Cayte Lindner, J.E. Fritz, Zhon Johansen.

SEE ALSO
========

     - Test::Unit::TestCase
     - Test::Unit::UnitHarness
     - Test::Unit::TkTestRunner

unit testing framework helper class
***********************************

NAME
====

     Test::Unit::TestResult - unit testing framework helper class

SYNOPSIS
========

     # this class is not intended to be used directly

DESCRIPTION
===========

     This class is used by the framework to record the results
     of tests, which will throw an instance of a subclass of
     Test::Unit::Exception in case of errors or failures.

     To achieve this, this class gets called with a test case
     as argument. It will call this test case's run method back
     and catch any exceptions thrown.

     This is the quintessential call tree of the communication
     needed to record the results of a given test:

     $aTestCase->run() {
     	# creates result
     	$aTestResult->run($aTestCase) {
     	    # catches exception and records it
     	    $aTestCase->run_bare() {
     		# runs test method inside eval
     		$aTestCase->run_test() {
     		    # calls method $aTestCase->name()
     		    # and propagates exception
     		    # method will call Assert::assert()
     		    # to cause failure if test fails on
     		    # test assertion
     		    # it finds this because $aTestCase is-a Assert
     		}
     	    }
     	}
     }

AUTHOR
======

     Copyright (c) 2000 Christian Lemburg, <lemburg@acm.org>.

     All rights reserved. This program is free software; you can
     redistribute it and/or modify it under the same terms as
     Perl itself.

     Thanks go to the other PerlUnit framework people:
     Brian Ewins, Cayte Lindner, J.E. Fritz, Zhon Johansen.

SEE ALSO
========

     - Test::Unit::Assert
     - Test::Unit::TestCase
     - Test::Unit::Exception

unit testing framework helper class
***********************************

NAME
====

     Test::Unit::TestRunner - unit testing framework helper class

SYNOPSIS
========

     use Test::Unit::TestRunner;

     my $testrunner = Test::Unit::TestRunner->new();
     $testrunner->start($my_testcase_class);

DESCRIPTION
===========

     This class is the test runner for the command line style use
     of the testing framework.

     It is used by simple command line tools like the TestRunner.pl
     script provided.

     The class needs one argument, which is the name of the class
     encapsulating the tests to be run.

     Options:
     	-wait : wait for user confirmation between tests
     	-v    : Version info

AUTHOR
======

     Framework JUnit authored by Kent Beck and Erich Gamma.

     Ported from Java to Perl by Christian Lemburg.

     Copyright (c) 2000 Christian Lemburg, <lemburg@acm.org>.

     All rights reserved. This program is free software; you can
     redistribute it and/or modify it under the same terms as
     Perl itself.

     Thanks go to the other PerlUnit framework people:
     Brian Ewins, Cayte Lindner, J.E. Fritz, Zhon Johansen.

SEE ALSO
========

     - Test::Unit::TestCase
     - Test::Unit::TestListener
     - Test::Unit::TestSuite
     - Test::Unit::TestResult
     - Test::Unit::TkTestRunner
     - For further examples, take a look at the framework self test
       collection (Test::Unit::tests::AllTests).

unit testing framework base class
*********************************

NAME
====

     Test::Unit::TestSuite - unit testing framework base class

SYNOPSIS
========

     use Test::Unit::TestSuite;

     # more code here ...

     sub suite {
     	my $class = shift;

     # create an empty suite
     my $suite = Test::Unit::TestSuite->empty_new("A Test Suite");

     # get and add an existing suite
     $suite->add_test(Test::Unit::TestSuite->new("MyModule::Suite_1"));

     # extract suite by way of suite method and add
     $suite->add_test(MyModule::Suite_2->suite());

     # get and add another existing suite
     $suite->add_test(Test::Unit::TestSuite->new("MyModule::TestCase_2"));

     # return the suite built
     return $suite;
         }

DESCRIPTION
===========

     This class is normally not used directly, but it can be used
     for creating your own custom built aggregate suites.

     Normally, this class just provides the functionality of
     auto-building a test suite by extracting methods with a name
     prefix of "test" from a given package to the test runners.

AUTHOR
======

     Framework JUnit authored by Kent Beck and Erich Gamma.

     Ported from Java to Perl by Christian Lemburg.

     Copyright (c) 2000 Christian Lemburg, <lemburg@acm.org>.

     All rights reserved. This program is free software; you can
     redistribute it and/or modify it under the same terms as
     Perl itself.

     Thanks go to the other PerlUnit framework people:
     Brian Ewins, Cayte Lindner, J.E. Fritz, Zhon Johansen.

SEE ALSO
========

     - Test::Unit::TestRunner
     - Test::Unit::TkTestRunner
     - For further examples, take a look at the framework self test
       collection (Test::Unit::tests::AllTests).

unit testing framework helper class
***********************************

NAME
====

     Test::Unit::TkTestRunner - unit testing framework helper class

SYNOPSIS
========

     use Test::Unit::TkTestRunner;
     Test::Unit::TkTestRunner::main($my_testcase_class);

DESCRIPTION
===========

     This class is the test runner for the GUI style use
     of the testing framework.

     It is used by simple command line tools like the TkTestRunner.pl
     script provided.

     The class needs as arguments the names of the classes
     encapsulating the tests to be run.

     =head1 AUTHOR

     Framework JUnit authored by Kent Beck and Erich Gamma.

     Copyright (c) 2000 Brian Ewins.

     All rights reserved. This program is free software; you can
     redistribute it and/or modify it under the same terms as
     Perl itself.

     Thanks go to the other PerlUnit framework people:
     Christian Lemburg, Cayte Lindner, J.E. Fritz, Zhon Johansen.

     Thanks for patches go to:
     David Esposito.

SEE ALSO
========

     - Test::Unit::TestLoader
     - Test::Unit::TestListener
     - Test::Unit::TestResult
     - Test::Unit::TestRunner
     - Test::Unit::TestCase
     - Test::Unit::TestSuite
     - For further examples, take a look at the framework self test
       collection (Test::Unit::tests::AllTests).

Tutorial on unit testing
************************

NAME
====

     Test::Unit::Tutorial - Tutorial on unit testing

SYNOPSIS
========

     perldoc Test::Unit::Tutorial

DESCRIPTION
===========

     Here should be extensive documentation on what unit testing is,
     why it is useful, and how to do it with the Test::Unit collection
     of modules.

     Sorry for not implementing this yet.

     Please have a look at the examples in the examples directory
     and read the README file that came with this distribution.

     A short tutorial on how to use the unit testing framework is
     included in the Test::Unit::TestCase documentation.

     Further examples can be found by looking at the self test
     collection, starting in Test::Unit::tests::AllTests.

AUTHOR
======

     Christian Lemburg <lemburg@acm.org>

SEE ALSO
========

     - The module documentation for all modules in the Test::Unit tree.
     - Refactoring. Improving The Design Of Existing Code. Martin Fowler.
       Addison-Wesley, 1999.
     - The JUnit (unit testing framework for Java) documentation.
     - http://www.xProgramming.com/

unit testing framework helper class
***********************************

NAME
====

     Test::Unit::UnitHarness - unit testing framework helper class

SYNOPSIS
========

     # this class is not intended to be used directly

DESCRIPTION
===========

     This is a makeover of Test::Harness to allow its tests
     to be retrofitted as unit tests.

AUTHOR
======

     Copyright (c) 2000 Brian Ewins.

     All rights reserved. This program is free software; you can
     redistribute it and/or modify it under the same terms as
     Perl itself.

     Thanks go to the other PerlUnit framework people:
     Christian Lemburg, Cayte Lindner, J.E. Fritz, Zhon Johansen.

SEE ALSO
========

     - Test::Unit::UnitHarness
     - Test::Unit::TestRunner
     - Test::Unit::TkTestRunner

unit testing framework self tests
*********************************

NAME
====

     Test::Unit::tests::AllTests - unit testing framework self tests

SYNOPSIS
========

     # command line style use

     perl TestRunner.pl Test::Unit::tests::AllTests

     # GUI style use

     perl TkTestRunner.pl Test::Unit::tests::AllTests

DESCRIPTION
===========

     This class is used by the unit testing framework to encapsulate
     all the self tests of the framework.

     =head1 AUTHOR

     Framework JUnit authored by Kent Beck and Erich Gamma.

     Ported from Java to Perl by Christian Lemburg.

     Copyright (c) 2000 Christian Lemburg, <lemburg@acm.org>.

     All rights reserved. This program is free software; you can
     redistribute it and/or modify it under the same terms as
     Perl itself.

     Thanks go to the other PerlUnit framework people:
     Brian Ewins, Cayte Lindner, J.E. Fritz, Zhon Johansen.

SEE ALSO
========

     - Test::Unit::TestCase
     - Test::Unit::TestSuite

create an abbreviation table from a list
****************************************

NAME
====

   abbrev - create an abbreviation table from a list

SYNOPSIS
========

     use Text::Abbrev;
     abbrev $hashref, LIST

DESCRIPTION
===========

   Stores all unambiguous truncations of each element of LIST as keys in
the associative array referenced by $hashref.  The values are the original
list elements.

EXAMPLE
=======

     $hashref = abbrev qw(list edit send abort gripe);

     %hash = abbrev qw(list edit send abort gripe);

     abbrev $hashref, qw(list edit send abort gripe);

     abbrev(*hash, qw(list edit send abort gripe));

strings with annotation about their origin
******************************************

NAME
====

   Text::Annotated::Line - strings with annotation about their origin

SYNOPSIS
========

     use Text::Annotated::Line;

     # construct a line
     $line = new Text::Annotated::Line(
          filename => 'foo',
          linenr   => 23,
          content  => 'This is the line content',
     );

     # print the line, with annotation
     print $line->stringify_annotated, "\n";

     # print the line without annotation
     print $line, "\n";

DESCRIPTION
===========

FIELDS
------

   All of the following fields must be set through the constructor new():

filename
     name of the file the string originates from

linenr
     number of the line in the file the string is located

content
     the actual content of the string

METHODS
-------

new()
     Constructs a new Text::Annotated::Line object. Fields can be set by
     passing them as a hash to new().

stringify()
     Returns the line without annotations. This method is used for
     overloading, so you implicitly call it in any circumstance where you
     use a Text::Annotated::Line object where a string is expected.

stringify_annotated()
     Returns a string with the content AND the annotation if the format
     `[filename#linenr]content'. Trailing newlines in the content are
     omitted.

SEE ALSO
========

   Filters for handling annotated lines are described in
Text/Annotated/Reader, and
Text/Annotated/Writer.

CVS VERSION
===========

   This is CVS version $Revision: 1.3 $, last updated at $Date: 2000/12/05
15:45:10 $.

AUTHOR
======

   Wim Verhaegen <wim.verhaegen@ieee.org>

COPYRIGHT
=========

   Copyright (c) 2000 Wim Verhaegen. All rights reserved.  This program is
free software; you can redistribute and/or modify it under the same terms
as Perl itself.

a filter for annotating lines coming from a file
************************************************

NAME
====

   Text::Annotated::Reader - a filter for annotating lines coming from a
file

SYNOPSIS
========

     use Text::Annotated::Reader;

     my $reader = new Text::Annotated::Reader(input => 'text.in');
     $reader->read();
     $ra_annotated_lines = $reader->{annotated_lines};

DESCRIPTION
===========

   Text::Annotated::Reader is a subclass of Text::Filter, with as purpose
the reading of lines from a file, and annotating the filename and
linenumber for each line. The following issues are specific to
Text::Annotated::Reader:

   * The set_input() method only accepts filenames as a valid input
     argument.  This requirement is also imposed on the input argument
     passed to new(), as new() invokes set_input().

   * The read() method executes the input operation. run() is an alias for
     read().

   * The reader() method builds a Text::Annotated::Reader filter with the
     supplied arguments, calls read() and finally returns the filter. It
     is thus possible to combine the whole input operation in a single
     statement like

          my $ra_annotated_lines =
            Text::Annotated::Reader->reader(input => 'text.in')->{annotated_lines};

SEE ALSO
========

   More info on using filters is available from Text/Filter.

   See Text/Annotated/Line, describes annotated
lines.

CVS VERSION
===========

   This is CVS version $Revision: 1.4 $, last updated at $Date: 2000/12/05
15:45:11 $.

AUTHOR
======

   Wim Verhaegen <wim.verhaegen@ieee.org>

COPYRIGHT
=========

   Copyright (c) 2000 Wim Verhaegen. All rights reserved.  This program is
free software; you can redistribute and/or modify it under the same terms
as Perl itself.

filter for writing Text::Annotated lines
****************************************

NAME
====

   Text::Annotated::Writer - filter for writing Text::Annotated lines

SYNOPSIS
========

     use Text::Annotated::Writer;

     my $writer = new Text::Annotated::Writer(
          input  => $ra_annotated_lines, # ref to array with Text::Annotated objects
     	 output => 'text.out', # output file
          no_annotation => 1,   # suppresses writing of the annotations
     );
     $writer->write(); # actually writes the lines to file

DESCRIPTION
===========

   Text::Annotated::Writer is a subclass of Text::Filter, with as purpose
the dumping of annotated lines to an array of ASCII lines or a file. The
following issues are specific to Text::Annotated::Writer:

   * The list of allowed arguments to new() includes the `no_annotation'
     flag. When set to a true value, the annotation of the lines is
     suppressed in the output, and only the ASCII content is shown. The
     default behaviour is to output the annotation with each line.

   * The write() method executes the output operation. run() is an alias
     for write().

   * The writer() method builds a Text::Annotated::Writer filter with the
     supplied arguments, calls write() and finally returns the filter. It
     is thus possible to combine the whole output operation in a single
     statement like

          Text::Annotated::Writer->writer(
          	input  => $ra_annotated_lines,
              output => 'text.out',
              no_annotation => 1,
          );

SEE ALSO
========

   More info on using filters is available from Text/Filter.

   See Text/Annotated/Line, describes annotated
lines.

CVS VERSION
===========

   This is CVS version $Revision: 1.4 $, last updated at $Date: 2000/12/05
15:45:11 $.

AUTHOR
======

   Wim Verhaegen <wim.verhaegen@ieee.org>

COPYRIGHT
=========

   Copyright (c) 2000 Wim Verhaegen. All rights reserved.  This program is
free software; you can redistribute and/or modify it under the same terms
as Perl itself.

Automatic and manual text wrapping and reformating formatting
*************************************************************

NAME
====

   Text::Autoformat - Automatic and manual text wrapping and reformating
formatting

VERSION
=======

   This document describes version 1.04 of Text::Autoformat, released
December  5, 2000.

SYNOPSIS
========

     # Minimal use: read from STDIN, format to STDOUT...

     use Text::Autoformat;
     autoformat;

     # In-memory formatting...

     $formatted = autoformat $rawtext;

     # Configuration...

     $formatted = autoformat $rawtext, { %options };

     # Margins (1..72 by default)...

     $formatted = autoformat $rawtext, { left=>8, right=>70 };

     # Justification (left by default)...

     $formatted = autoformat $rawtext, { justify => 'left' };
     $formatted = autoformat $rawtext, { justify => 'right' };
     $formatted = autoformat $rawtext, { justify => 'full' };
     $formatted = autoformat $rawtext, { justify => 'centre' };

     # Filling (does so by default)...

     $formatted = autoformat $rawtext, { fill=>0 };

     # Squeezing whitespace (does so by default)...

     $formatted = autoformat $rawtext, { squeeze=>0 };

     # Case conversions...

     $formatted = autoformat $rawtext, { case => 'lower' };
     $formatted = autoformat $rawtext, { case => 'upper' };
     $formatted = autoformat $rawtext, { case => 'sentence' };
     $formatted = autoformat $rawtext, { case => 'title' };
     $formatted = autoformat $rawtext, { case => 'highlight' };

BACKGROUND
==========

The problem
-----------

   Perl plaintext formatters just aren't smart enough. Given a typical
piece of plaintext in need of formatting:

     In comp.lang.perl.misc you wrote:
     : > <CN = Clooless Noobie> writes:
     : > CN> PERL sux because:
     : > CN>    * It doesn't have a switch statement and you have to put $
     : > CN>signs in front of everything
     : > CN>    * There are too many OR operators: having |, || and 'or'
     : > CN>operators is confusing
     : > CN>    * VB rools, yeah!!!!!!!!!
     : > CN> So anyway, how can I stop reloads on a web page?
     : > CN> Email replies only, thanks - I don't read this newsgroup.
     : >
     : > Begone, sirrah! You are a pathetic, Bill-loving, microcephalic
     : > script-infant.
     : Sheesh, what's with this group - ask a question, get toasted! And how
     : *dare* you accuse me of Ianuphilia!

   both the venerable Unix `fmt' in this node tool and Perl's standard
Text::Wrap module produce:

     In comp.lang.perl.misc you wrote:  : > <CN = Clooless Noobie>
     writes:  : > CN> PERL sux because:  : > CN>    * It doesn't
     have a switch statement and you have to put $ : > CN>signs in
     front of everything : > CN>    * There are too many OR
     operators: having |, || and 'or' : > CN>operators is confusing
     : > CN>    * VB rools, yeah!!!!!!!!!  : > CN> So anyway, how
     can I stop reloads on a web page?  : > CN> Email replies only,
     thanks - I don't read this newsgroup.  : > : > Begone, sirrah!
     You are a pathetic, Bill-loving, microcephalic : >
     script-infant.  : Sheesh, what's with this group - ask a
     question, get toasted! And how : *dare* you accuse me of
     Ianuphilia!

   Other formatting modules - such as Text::Correct and Text::Format -
provide more control over their output, but produce equally poor results
when applied to arbitrary input. They simply don't understand the
structural conventions of the text they're reformatting.

The solution
------------

   The Text::Autoformat module provides a subroutine named `autoformat'
that wraps text to specified margins. However, `autoformat' reformats its
input by analysing the text's structure, so it wraps the above example
like so:

     In comp.lang.perl.misc you wrote:
     : > <CN = Clooless Noobie> writes:
     : > CN> PERL sux because:
     : > CN>    * It doesn't have a switch statement and you
     : > CN>      have to put $ signs in front of everything
     : > CN>    * There are too many OR operators: having |, ||
     : > CN>      and 'or' operators is confusing
     : > CN>    * VB rools, yeah!!!!!!!!! So anyway, how can I
     : > CN>      stop reloads on a web page? Email replies
     : > CN>      only, thanks - I don't read this newsgroup.
     : >
     : > Begone, sirrah! You are a pathetic, Bill-loving,
     : > microcephalic script-infant.
     : Sheesh, what's with this group - ask a question, get toasted!
     : And how *dare* you accuse me of Ianuphilia!

   Note that the various quoting conventions have been observed. In fact,
their structure has been used to determine where some paragraphs begin.
Furthermore `autoformat' correctly distinguished between the leading '*'
bullets of the nested list (which were outdented) and the leading emphatic
'*' of "*dare*" (which was inlined).

DESCRIPTION
===========

Paragraphs
----------

   The fundamental task of the `autoformat' subroutine is to identify and
rearrange independent paragraphs in a text. Paragraphs typically consist
of a series of lines containing at least one non-whitespace character,
followed by one or more lines containing only optional whitespace.  This
is a more liberal definition than many other formatters use: most require
an empty line to terminate a paragraph. Paragraphs may also be denoted by
bulleting, numbering, or quoting (see the following sections).

   Once a paragraph has been isolated, `autoformat' fills and re-wraps its
lines according to the margins that are specified in its argument list.
These are placed after the text to be formatted, in a hash reference:

     $tidied = autoformat($messy, {left=>20, right=>60});

   By default, `autoformat' uses a left margin of 1 (first column) and a
right margin of 72.

   Normally, `autoformat' only reformats the first paragraph it encounters,
and leaves the remainder of the text unaltered. This behaviour is useful
because it allows a one-liner invoking the subroutine to be mapped onto a
convenient keystroke in a text editor, to provide one-paragraph-at-a-time
reformatting:

     % cat .exrc

     map f !Gperl -MText::Autoformat -e'autoformat'

   (Note that to facilitate such one-liners, if `autoformat' is called in
a void context without any text data, it takes its text from STDIN and
writes its result to STDOUT).

   To enable `autoformat' to rearrange the entire input text at once, the
all argument is used:

     $tidied_all = autoformat($messy, {left=>20, right=>60, all=>1});

Bulleting and (re-)numbering
----------------------------

   Often plaintext will include lists that are either:

     * bulleted,
     * simply numbered (i.e. 1., 2., 3., etc.), or
     * hierarchically numbered (1, 1.1, 1.2, 1.3, 2, 2.1. and so forth).

   In such lists, each bulleted item is implicitly a separate paragraph,
and is formatted individually, with the appropriate indentation:

     * bulleted,
     * simply numbered (i.e. 1., 2., 3.,
       etc.), or
     * hierarchically numbered (1, 1.1,
       1.2, 1.3, 2, 2.1. and so forth).

   More importantly, if the points are numbered, the numbering is checked
and reordered. For example, a list whose points have been rearranged:

     2. Analyze problem
     3. Design algorithm
     1. Code solution
     5. Test
     4. Ship

   would be renumbered automatically by `autoformat':

     1. Analyze problem
     2. Design algorithm
     3. Code solution
     4. Ship
     5. Test

   The same reordering would be performed if the "numbering" was by letters
(`a.' `b.' `c.' etc.) or Roman numerals (`i.' `ii.' `iii.)' or by some
combination of these (`1a.' `1b.' `2a.' `2b.' etc.) Handling disordered
lists of letters and Roman numerals presents an interesting challenge. A
list such as:

     C. Put cat in box.
     D. Close lid.
     E. Activate Geiger counter.

   should be reordered as `A.' `B.' `C.,' whereas:

     C. Put cat in box.
     D. Close lid.
     XLI. Activate Geiger counter.

   should be reordered `I.' `II.' `III.'

   The `autoformat' subroutine solves this problem by always interpreting
alphabetic bullets as being letters, unless the full list consists only of
valid Roman numerals, at least one of which is two or more characters long.

Quoting
-------

   Another case in which contiguous lines may be interpreted as belonging
to different paragraphs, is where they are quoted with distinct quoters.
For example:

     : > CN> So anyway, how can I stop reloads on a web page?
     : > CN> Email replies only, thanks - I don't read this newsgroup.
     : > Begone, sirrah! You are a pathetic, Bill-loving,
     : > microcephalic script-infant.
     : Sheesh, what's with this group - ask a question, get toasted!
     : And how *dare* you accuse me of Ianuphilia!

   `autoformat' recognizes the various quoting conventions used in this
example and treats it as three paragraphs to be independently reformatted.

   Block quotations present a different challenge. A typical formatter
would render the following quotation:

     "We are all of us in the gutter,
      but some of us are looking at the stars"
                             -- Oscar Wilde

   like so:

     "We are all of us in the gutter, but some of us are looking at
     the stars" -- Oscar Wilde

   `autoformat' recognizes the quotation structure by matching the
following regular expression against the text component of each paragraph:

     / \A(\s*)               # leading whitespace for quotation
       (["']|``)             # opening quotemark
       (.*)                  # quotation
       (''|\2)               # closing quotemark
       \s*?\n                # trailing whitespace after quotation
       (\1[ ]+)              # leading whitespace for attribution
                             #   (must be indented more than quotation)
       (--|-)                # attribution introducer
       ([^\n]*?\n)           # first attribution line
       ((\5[^\n]*?$)*)       # other attribution lines
                             #   (indented no less than first line)
       \s*\Z                 # optional whitespace to end of paragraph
     /xsm

   When reformatted (see below), the indentation and the attribution
structure will be preserved:

     "We are all of us in the gutter, but some of us are looking
      at the stars"
                             -- Oscar Wilde

Widow control
-------------

   Note that in the last example, `autoformat' broke the line at column
68, four characters earlier than it should have. It did so because, if the
full margin width had been used, the formatting would have left the last
two words by themselves on an oddly short last line:

     "We are all of us in the gutter, but some of us are looking at
      the stars"

   This phenomenon is known as "widowing" and is heavily frowned upon in
typesetting circles. It looks ugly in plaintext too, so `autoformat'
avoids it by stealing extra words from earlier lines in a paragraph, so as
to leave enough for a reasonable last line. The heuristic used is that
final lines must be at least 10 characters long (though this number may be
adjusted by passing a `widow => *minlength*' argument to `autoformat').

   If the last line is too short, the paragraph's right margin is reduced
by one column, and the paragraph is reformatted. This process iterates
until either the last line exceeds nine characters or the margins have
been narrowed by 10% of their original separation. In the latter case, the
reformatter gives up and uses its original formatting.

Justification
-------------

   The `autoformat' subroutine also takes a named argument: `{justify =>
*type*}', which specifies how each paragraph is to be justified.  The
options are: `'left'' (the default), `'right',' `'centre'' (or
`'center''), and `'full''. These act on the complete paragraph text (but
not on any quoters before that text). For example, with `'right''
justification:

     R3>     Now is the Winter of our discontent made
     R3> glorious Summer by this son of York. And all
     R3> the clouds that lour'd upon our house In the
     R3>              deep bosom of the ocean buried.

   Full justification is interesting in a fixed-width medium like plaintext
because it usually results in uneven spacing between words. Typically,
formatters provide this by distributing the extra spaces into the first
available gaps of each line:

     R3> Now  is  the  Winter  of our discontent made
     R3> glorious Summer by this son of York. And all
     R3> the  clouds  that  lour'd  upon our house In
     R3> the deep bosom of the ocean buried.

   This produces a rather jarring visual effect, so `autoformat' reverses
the strategy and inserts extra spaces at the end of lines:

     R3> Now is the Winter  of  our  discontent  made
     R3> glorious Summer by this son of York. And all
     R3> the clouds that lour'd  upon  our  house  In
     R3> the deep bosom of the ocean buried.

   Most readers find this less disconcerting.

Implicit centring
-----------------

   Even if explicit centring is not specified, `autoformat' will attempt
to automatically detect centred paragraphs and preserve their
justification. It does this by examining each line of the paragraph and
asking: "if this line were part of a centred paragraph, where would the
centre line have been?"

   The answer can be determined by adding the length of leading whitespace
before the first word, plus half the length of the full set of words on
the line. That is, for a single line:

     $line =~ /^(\s*)(.*?)(\s*)$/
     $centre = length($1)+0.5*length($2);

   By making the same estimate for every line, and then comparing the
estimates, it is possible to deduce whether all the lines are centred with
respect to the same axis of symmetry (with an allowance of E<plusminus>1
to cater for the inevitable rounding when the centre positions of
even-length rows were originally computed). If a common axis of symmetry
is detected, `autoformat' assumes that the lines are supposed to be
centred, and switches to centre-justification mode for that paragraph.

Case transformations
--------------------

   The `autoformat' subroutine can also optionally perform case conversions
on the text it processes. The `{case => *type*}' argument allows the user
to specify five different conversions:

`'upper''
     This mode unconditionally converts every letter in the reformatted
     text to upper-case;

`'lower''
     This mode unconditionally converts every letter in the reformatted
     text to lower-case;

`'sentence''
     This mode attempts to generate correctly-cased sentences from the
     input text.  That is, the first letter after a sentence-terminating
     punctuator is converted to upper-case. Then, each subsequent word in
     the sentence is converted to lower-case, unless that word is
     originally mixed-case or contains punctuation.  For example, under
     `{case => 'sentence'}':

          'POVERTY, MISERY, ETC. are the lot of the PhD candidate. alas!'

     becomes:

          'Poverty, misery, etc. are the lot of the PhD candidate. Alas!'

     Note that `autoformat' is clever enough to recognize that the period
     after abbreviations such as etc. is not a sentence terminator.

     If the argument is specified as `'sentence  '' (with one or more
     trailing whitespace characters) those characters are used to replace
     the single space that appears at the end of the sentence. For example,
     `autoformat($text, {case=>'sentence  '}') would produce:

          'Poverty, misery, etc. are the lot of the PhD candidate.  Alas!'

'title'
     This mode behaves like `'sentence'' except that the first letter of
     every word is capitalized:

          'What I Did On My Summer Vacation In Monterey'

`'highlight''
     This mode behaves like 'title' except that trivial words are not
     capitalized:

          'What I Did on my Summer Vacation in Monterey'

OTHER FEATURES
==============

The form sub
------------

   The `form()' subroutine may be exported from the module.  It takes a
series of format (or "picture") strings followed by replacement values,
interpolates those values into each picture string, and returns the
result. The effect is similar to the inbuilt perl format mechanism,
although the field specification syntax is simpler and some of the
formatting behaviour is more sophisticated.

   A picture string consists of sequences of the following characters:

<
     Left-justified field indicator.  A series of sequential <'s specify a
     left-justified field to be filled by a subsequent value.

>
     Right-justified field indicator.  A series of sequential >'s specify
     a right-justified field to be filled by a subsequent value.

^
     Centre-justified field indicator.  A series of sequential ^'s specify
     a centred field to be filled by a subsequent value.

>>>.<<<<
     A numerically formatted field with the specified number of digits to
     either side of the decimal place. See `Numerical formatting' in this
     node below.

[
     Left-justified block field indicator.  Just like a < field, except it
     repeats as required on subsequent lines. See below.

]
     Right-justified block field indicator.  Just like a > field, except
     it repeats as required on subsequent lines. See below.

|
     Centre-justified block field indicator.  Just like a ^ field, except
     it repeats as required on subsequent lines. See below.

]]].[[[[
     A numerically formatted block field with the specified number of
     digits to either side of the decimal place.  Just like a >>>.<<<<
     field, except it repeats as required on subsequent lines. See below.

\
     Literal escape of next character (e.g. `\|' is formatted as '|', not
     a one character wide centre-justified block field).

Any other character
     That literal character.

   Any substitution value which is undef (either explicitly so, or because
it is missing) is replaced by an empty string.

Controlling line filling.
-------------------------

   Note that, unlike the a perl format, form preserves whitespace
(including newlines) unless called with certain options.

   The "squeeze" option (when specified with a true value) causes any
sequence of spaces and/or tabs (but not newlines) in an interpolated
string to be replaced with a single space.

   The "fill" option causes newlines to also be squeezed.

   Hence:

     $frmt = "# [[[[[[[[[[[[[[[[[[[[[";
     $data = "h  e\t \tl lo\nworld\t\t\t\t\t";

     print form $frmt, $data;
     # h  e            l lo
     # world

     print form {squeeze=>1}, $frmt, $data;
     # h e l lo
     # world

     print form {fill=>1}, $frmt, $data;
     # h  e            l lo world

     print form {squeeze=>1, fill=>1}, $frmt, $data;
     # h e l lo world

   Whether or not filling or squeezing is in effect, form can also be
directed to trim any extra whitespace from the end of each line it
formats, using the "trim" option. If this option is specified with a true
value, every line returned by form will automatically have the
substitution `s/[ \t]+$//gm' applied to it.

   Hence:

     print length form "[[[[[[[[[[", "short";
     # 11

     print length form {trim=>1}, "[[[[[[[[[[", "short";
     # 6

Temporary and permanent default options
---------------------------------------

   If form is called with options, but no template string or data, it
resets it's defaults to the options specified. If called in a void context:

     form { squeeze => 1, trim => 1 };

   the options become permanent defaults.

   However, when called with only options in non-void context, form resets
its defaults to those options and returns an object. The reset default
values persist only until that returned object is destroyed.  Hence to
temporarily reset form's defaults within a single subroutine:

     sub single {
             my $tmp = form { squeeze => 1, trim => 1 };

     # do formatting with the obove defaults

     } # form's defaults revert to previous values as $tmp object destroyed

How form hyphenates
-------------------

   Any line with a block field repeats on subsequent lines until all block
fields on that line have consumed all their data. Non-block fields on
these lines are replaced by the appropriate number of spaces.

   Words are wrapped whole, unless they will not fit into the field at
all, in which case they are broken and (by default) hyphenated. Simple
hyphenation is used (i.e. break at the *N-1*th character and insert a
'-'), unless a suitable alternative subroutine is specified instead.

   Words will not be broken if the break would leave less than 2
characters on the current line. This minimum can be varied by setting the
'minbreak' option to a numeric value indicating the minumum total broken
characters (including hyphens) required on the current line. Note that,
for very narrow fields, words will still be broken (but *unhyphenated*).
For example:

     print form '|', 'split';

   would print:

     s
     p
     l
     i
     t

   whilst:

     print form {minbreak=>1}, '|', 'split';

   would print:

     s-
     p-
     l-
     i-
     t

   Alternative breaking subroutines can be specified using the "break"
option in a configuration hash. For example:

     form { break => \&my_line_breaker }
          $format_str,
          @data;

   form expects any user-defined line-breaking subroutine to take three
arguments (the string to be broken, the maximum permissible length of the
initial section, and the total width of the field being filled).  The
`hypenate' sub must return a list of two strings: the initial (broken)
section of the word, and the remainder of the string respectively).

   For example:

     sub tilde_break = sub($$$)
     {
             (substr($_[0],0,$_[1]-1).'~', substr($_[0],$_[1]-1));
     }

     form { break => \&tilde_break }
          $format_str,
          @data;

   makes '~' the hyphenation character, whilst:

     sub wrap_and_slop = sub($$$)
     {
             my ($text, $reqlen, $fldlen) = @_;
             if ($reqlen==$fldlen) { $text =~ m/\A(\s*\S*)(.*)/s }
             else                  { ("", $text) }
     }

     form { break => \&wrap_and_slop }
          $format_str,
          @data;

   wraps excessively long words to the next line and "slops" them over the
right margin if necessary.

   The Text::Autoformat package provides three functions to simplify the
use of variant hyphenation schemes. The exportable subroutine
`Text::Autoformat::break_wrap' generates a reference to a subroutine
implementing the "wrap-and-slop" algorithm shown in the last example,
which could therefore be rewritten:

     use Text::Autoformat qw( form break_wrap );

     form { break => break_wrap }
          $format_str,
          @data;

   The subroutine `Text::Autoformat::break_with' takes a single string
argument and returns a reference to a sub which hyphenates with that
string. Hence the first of the two examples could be rewritten:

     use Text::Autoformat qw( form break_wrap );

     form { break => break_with('~') }
          $format_str,
          @data;

   The subroutine `Text::Autoformat::break_TeX' returns a reference to a
sub which hyphenates using Jan Pazdziora's TeX::Hyphen module. For example:

     use Text::Autoformat qw( form break_wrap );

     form { break => break_TeX }
          $format_str,
          @data;

   Note that in the previous examples there is no leading '\&' before
`break_wrap', `break_with', or `break_TeX', since each is being directly
*called* (and returns a reference to some other suitable subroutine);

The form formatting algorithm
-----------------------------

   The algorithm form uses is:

     1. split the first string in the argument list
        into individual format lines and add a terminating
        newline (unless one is already present).

     2. for each format line...

     2.1. determine the number of fields and shift
          that many values off the argument list and
          into the filling list. If insufficient
          arguments are available, generate as many
          empty strings as are required.

     2.2. generate a text line by filling each field
          in the format line with the initial contents
          of the corresponding arg in the filling list
          (and remove those initial contents from the arg).

     2.3. replace any <,>, or ^ fields by an equivalent
          number of spaces. Splice out the corresponding
          args from the filling list.

     2.4. Repeat from step 2.2 until all args in the
          filling list are empty.

     3. concatenate the text lines generated in step 2

     4. repeat from step 1 until the argument list is empty

form examples
-------------

   As an example of the use of form, the following:

     $count = 1;
     $text = "A big long piece of text to be formatted exquisitely";

     print form q
     {
             ||||  <<<<<<<<<<
             ----------------
             ^^^^  ]]]]]]]]]]\|
                             =
             ]]].[[[

     }, $count, $text, $count+11, $text, "123 123.4\n123.456789";

   produces the following output:

     1    A big long
                     ----------------
     12     piece of|
          text to be|
           formatted|
          exquisite-|
                  ly|
                    =
                     123.0
                     123.4
                     123.456

   Picture strings and replacement values can be interleaved in the
traditional format format, but care is needed to ensure that the correct
number of substitution values are provided. For example:

     $report = form
             'Name           Rank    Serial Number',
             '====           ====    =============',
             '<<<<<<<<<<<<<  ^^^^    <<<<<<<<<<<<<',
              $name,         $rank,  $serial_number,
             ''
             'Age    Sex     Description',
             '===    ===     ===========',
             '^^^    ^^^     [[[[[[[[[[[',
              $age,  $sex,   $description;

How form consumes strings
-------------------------

   Unlike format, within form non-block fields do consume the text they
format, so the following:

     $text = "a line of text to be formatted over three lines";
     print form "<<<<<<<<<<\n  <<<<<<<<\n    <<<<<<\n",
                 $text,        $text,        $text;

   produces:

     a line of
       text to
         be fo-

   not:

     a line of
       a line
         a line

   To achieve the latter effect, convert the variable arguments to
independent literals (by double-quoted interpolation):

     $text = "a line of text to be formatted over three lines";
     print form "<<<<<<<<<<\n  <<<<<<<<\n    <<<<<<\n",
                "$text",      "$text",      "$text";

   Although values passed from variable arguments are progressively
consumed *within* form, the values of the original variables passed to form
are not altered.  Hence:

     $text = "a line of text to be formatted over three lines";
     print form "<<<<<<<<<<\n  <<<<<<<<\n    <<<<<<\n",
                 $text,        $text,        $text;
     print $text, "\n";

   will print:

     a line of
       text to
         be fo-
     a line of text to be formatted over three lines

   To cause form to consume the values of the original variables passed to
it, pass them as references. Thus:

     $text = "a line of text to be formatted over three lines";
     print form "<<<<<<<<<<\n  <<<<<<<<\n    <<<<<<\n",
                 \$text,       \$text,       \$text;
     print $text, "\n";

   will print:

     a line of
       text to
         be fo-
     rmatted over three lines

   Note that, for safety, the "non-consuming" behaviour takes precedence,
so if a variable is passed to form both by reference and by value, its
final value will be unchanged.

Numerical formatting
--------------------

   The ">>>.<<<" and "]]].[[[" field specifiers may be used to format
numeric values about a fixed decimal place marker. For example:

     print form '(]]]]].[[)', <<EONUMS;
                1
                1.0
                1.001
                1.009
                123.456
                1234567
                one two
     EONUMS

   would print:

   (    1.0 )         (    1.0 )         (    1.00)         (    1.01)
   (  123.46)         (#####.##)         (?????.??)          (?????.??)

   Fractions are rounded to the specified number of places after the
decimal, but only significant digits are shown. That's why, in the above
example, 1 and 1.0 are formatted as "1.0", whilst 1.001 is formatted as
"1.00".

   You can specify that the maximal number of decimal places always be used
by giving the configuration option 'numeric' a value that matches
/\bAllPlaces\b/i. For example:

     print form { numeric => AllPlaces },
                '(]]]]].[[)', <<'EONUMS';
                1
                1.0
     EONUMS

   would print:

   (    1.00)         (    1.00)

   Note that although decimal digits are rounded to fit the specified
width, the integral part of a number is never modified. If there are not
enough places before the decimal place to represent the number, the entire
number is replaced with hashes.

   If a non-numeric sequence is passed as data for a numeric field, it is
formatted as a series of question marks. This querulous behaviour can be
changed by giving the configuration option 'numeric' a value that matches
/\bSkipNaN\b/i in which case, any invalid numeric data is simply ignored.
For example:

     print form { numeric => 'SkipNaN' }
                '(]]]]].[[)',
                <<EONUMS;
                1
                two three
                4
     EONUMS

   would print:

   (    1.0 )         (    4.0 )

Filling block fields with lists of values
-----------------------------------------

   If an argument corresponding to a field is an array reference, then form
automatically joins the elements of the array into a single string,
separating each element with a newline character. As a result, a call like
this:

     @values = qw( 1 10 100 1000 );
     print form "(]]]].[[)", \@values;

   will print out

     (   1.00)
     (  10.00)
     ( 100.00)
     (1000.00)

   as might be expected.

   Note however that arrays must be passed by reference (so that form
knows that the entire array holds data for a single field). If the previous
example had not passed @values by reference:

     @values = qw( 1 10 100 1000 );
     print form "(]]]].[[)", @values;

   the output would have been:

     (   1.00)
     10
     100
     1000

   This is because @values would have been interpolated into form's
argument list, so only $value[0] would have been used as the data for the
initial format string. The remaining elements of @value would have been
treated as separate format strings, and printed out "verbatim".

   Note too that, because arrays must be passed using a reference, their
original contents are consumed by form, just like the contents of scalars
passed by reference.

   To avoid having an array consumed by form, pass it as an anonymous
array:

     print form "(]]]].[[)", [@values];

Headers, footers, and pages
---------------------------

   The form subroutine can also insert headers, footers, and page-feeds as
it formats. These features are controlled by the "header", "footer",
"pagefeed", "pagelen", and "pagenum" options.

   The "pagenum" option takes a scalar value or a reference to a scalar
variable and starts page numbering at that value. If a reference to a
scalar variable is specified, the value of that variable is updated as the
formatting proceeds, so that the final page number is available in it
after formatting. This can be useful for multi-part reports.

   The "pagelen" option specifies the total number of lines in a page
(including headers, footers, and page-feeds).

   If the "header" option is specified with a string value, that string is
used as the header of every page generated. If it is specified as a
reference to a subroutine, that subroutine is called at the start of every
page and its return value used as the header string. When called, the
subroutine is passed the current page number.

   Likewise, if the "footer" option is specified with a string value, that
string is used as the footer of every page generated. If it is specified
as a reference to a subroutine, that subroutine is called at the start of
every page and its return value used as the footer string. When called,
the footer subroutine is passed the current page number. If the option is
specified as a hash, it acts as described above for the "header" option.

   Both the header and footer options can also be specified as hash
references.  In this case the hash entires for keys "left", "centre" (or
"center"), and "right" specify what is to appear on the left, centre, and
right of the header/footer. The entry for the key "width" specifies how
wide the footer is to be. The  "left", "centre", and "right" values may be
literal strings, or subroutines (just as a normal header/footer
specification may be.) See the second example, below.

   The "pagefeed" option acts in exactly the same way, to produce a
pagefeed which is appended after the footer. But note that the pagefeed is
not counted as part of the page length.

   All three of these page components are recomputed at the start of each
new page, before the page contents are formatted (recomputing the header
and footer makes it possible to determine how many lines of data to format
so as to adhere to the specified page length).

   When the call to form is complete and the data has been fully formatted,
the footer subroutine is called one last time, with an extra argument of 1.
The string returned by this final call is used as the final footer.

   So for example, a 60-line per page report, starting at page 7, with
appropriate headers and footers might be set up like so:

     $page = 7;

     form { header => sub { "Page $_[0]\n\n" },
            footer => sub { return "" if $_[1];
                            "-"x50 . "\n" . form ">"x50", "...".($_[0]+1);
                          },
            pagefeed => "\n\n",
            pagelen  => 60
            pagenum  => \$page,
          },
          $template,
          @data;

   Note the recursive use of form within the "footer" option.

   Alternatively, to set up headers and footers such that the running head
is right justified in the header and the page number is centred in the
footer:

     form { header => { right => "Running head" },
            footer => { centre => sub { "Page $_[0]" } },
            pagelen  => 60
          },
          $template,
          @data;

The tag sub
-----------

   The tag subroutine may be exported from the module.  It takes two
arguments: a tag specifier and a text to be entagged. The tag specifier
indicates the indenting of the tag, and of the text. The sub generates an
end-tag (using the usual "/tag" variant), unless an explicit end-tag is
provided as the third argument.

   The tag specifier consists of the following components (in order):

An optional vertical spacer (zero or more whitespace-separated newlines)
     One or more whitespace characters up to a final mandatory newline.
     This vertical space is inserted before the tag and after the end-tag

An optional tag indent
     Zero or more whitespace characters. Both the tag and the end-tag are
     indented by this whitespace.

An optional left (opening) tag delimiter
     Zero or more non-"word" characters (not alphanumeric or '_').  If the
     opening delimiter is omitted, the character '<' is used.

A tag
     One or more "word" characters (alphanumeric or '_').

Optional tag arguments
     Any number of any characters

An optional right (closing) tag delimiter
     Zero or more non-"word" characters which balance some sequential
     portion of the opening tag delimiter. For example, if the opening
     delimiter is "<-(" then any of the following are acceptible closing
     delimiters: ")->", "->", or ">".  If the closing delimiter is
     omitted, the "inverse" of the opening delimiter is used (for example,
     ")->"),

An optional vertical spacer (zero or more newlines)
     One or more whitespace characters up to a mandatory newline. This
     vertical space is inserted before and after the complete text.

An optional text indent
     Zero or more space of tab characters. Each line of text is indented
     by this whitespace (in addition to the tag indent).

   For example:

     $text = "three lines\nof tagged\ntext";

     print tag "A HREF=#nextsection", $text;

   prints:

     <A HREF=#nextsection>three lines
     of tagged
     text</A>

   whereas:

     print tag "[-:GRIN>>>\n", $text;

   prints:

     [-:GRIN>>>:-]
     three lines
     of tagged
     text
     [-:/GRIN>>>:-]

   and:

     print tag "\n\n   <BOLD>\n\n   ", $text, "<END BOLD>";

   prints:

     <BOLD>

     three lines
     of tagged
     text

     <END BOLD>

   (with the indicated spacing fore and aft).

AUTHOR
======

   Damian Conway (damian@conway.org)

BUGS
====

   There are undoubtedly serious bugs lurking somewhere in code this funky
:-) Bug reports and other feedback are most welcome.

COPYRIGHT
=========

   Copyright (c) 1997-2000, Damian Conway. All Rights Reserved.  This
module is free software. It may be used, redistributed and/or modified
under the terms of the Perl Artistic License   (see
http://www.perl.com/perl/misc/Artistic.html)

Extract delimited text sequences from strings.
**********************************************

NAME
====

   Text::Balanced - Extract delimited text sequences from strings.

SYNOPSIS
========

     use Text::Balanced qw (
     			extract_delimited
     			extract_bracketed
     			extract_quotelike
     			extract_codeblock
     			extract_variable
     			extract_tagged
     			extract_multiple

     gen_delimited_pat
     gen_extract_tagged
     		       );

     # Extract the initial substring of $text that is delimited by
     # two (unescaped) instances of the first character in $delim.

     ($extracted, $remainder) = extract_delimited($text,$delim);

     # Extract the initial substring of $text that is bracketed
     # with a delimiter(s) specified by $delim (where the string
     # in $delim contains one or more of '(){}[]<>').

     ($extracted, $remainder) = extract_bracketed($text,$delim);

     # Extract the initial substring of $text that is bounded by
     # an HTML/XML tag.

     ($extracted, $remainder) = extract_tagged($text);

     # Extract the initial substring of $text that is bounded by
     # a C<BEGIN>...C<END> pair. Don't allow nested C<BEGIN> tags

     ($extracted, $remainder) =
     	extract_tagged($text,"BEGIN","END",undef,{bad=>["BEGIN"]});

     # Extract the initial substring of $text that represents a
     # Perl "quote or quote-like operation"

     ($extracted, $remainder) = extract_quotelike($text);

     # Extract the initial substring of $text that represents a block
     # of Perl code, bracketed by any of character(s) specified by $delim
     # (where the string $delim contains one or more of '(){}[]<>').

     ($extracted, $remainder) = extract_codeblock($text,$delim);

     # Extract the initial substrings of $text that would be extracted by
     # one or more sequential applications of the specified functions
     # or regular expressions

     @extracted = extract_multiple($text,
     			      [ \&extract_bracketed,
     				\&extract_quotelike,
     				\&some_other_extractor_sub,
     				qr/[xyz]*/,
     				'literal',
     			      ]);

   # Create a string representing an optimized pattern (a la Friedl) #
that matches a substring delimited by any of the specified characters #
(in this case: any type of quote or a slash)

     $patstring = gen_delimited_pat(q{'"`/});

   # Generate a reference to an anonymous sub that is just like
extract_tagged # but pre-compiled and optimized for a specific pair of
tags, and consequently # much faster (i.e. 3 times faster). It uses qr//
for better performance on # repeated calls, so it only works under Perl
5.005 or later.

     $extract_head = gen_extract_tagged('<HEAD>','</HEAD>');

     ($extracted, $remainder) = $extract_head->($text);

DESCRIPTION
===========

   The various `extract_...' subroutines may be used to extract a
delimited string (possibly after skipping a specified prefix string).  The
search for the string always begins at the current pos location of the
string's variable (or at index zero, if no pos position is defined).

General behaviour in list contexts
----------------------------------

   In a list context, all the subroutines return a list, the first three
elements of which are always:

[0]
     The extracted string, including the specified delimiters.  If the
     extraction fails an empty string is returned.

[1]
     The remainder of the input string (i.e. the characters after the
     extracted string). On failure, the entire string is returned.

[2]
     The skipped prefix (i.e. the characters before the extracted string).
     On failure, the empty string is returned.

   Note that in a list context, the contents of the original input text
(the first argument) are not modified in any way.

   However, if the input text was passed in a variable, that variable's
pos value is updated to point at the first character after the extracted
text. That means that in a list context the various subroutines can be
used much like regular expressions. For example:

     while ( $next = (extract_quotelike($text))[0] )
     {
     	# process next quote-like (in $next)
     }

General behaviour in scalar and void contexts
---------------------------------------------

   In a scalar context, the extracted string is returned, having first been
removed from the input text. Thus, the following code also processes each
quote-like operation, but actually removes them from $text:

     while ( $next = extract_quotelike($text) )
     {
     	# process next quote-like (in $next)
     }

   Note that if the input text is a read-only string (i.e. a literal), no
attempt is made to remove the extracted text.

   In a void context the behaviour of the extraction subroutines is
exactly the same as in a scalar context, except (of course) that the
extracted substring is not returned.

A note about prefixes
---------------------

   Prefix patterns are matched without any trailing modifiers (`/gimsox'
etc.)  This can bite you if you're expecting a prefix specification like
'.*?(?=<H1>)' to skip everything up to the first <H1> tag. Such a prefix
pattern will only succeed if the <H1> tag is on the current line, since .
normally doesn't match newlines.

   To overcome this limitation, you need to turn on /s matching within the
prefix pattern, using the `(?s)' directive: '(?s).*?(?=<H1>)'

`extract_delimited'
-------------------

   The `extract_delimited' function formalizes the common idiom of
extracting a single-character-delimited substring from the start of a
string. For example, to extract a single-quote delimited string, the
following code is typically used:

     ($remainder = $text) =~ s/\A('(\\.|[^'])*')//s;
     $extracted = $1;

   but with `extract_delimited' it can be simplified to:

     ($extracted,$remainder) = extract_delimited($text, "'");

   `extract_delimited' takes up to four scalars (the input text, the
delimiters, a prefix pattern to be skipped, and any escape characters) and
extracts the initial substring of the text that is appropriately
delimited. If the delimiter string has multiple characters, the first one
encountered in the text is taken to delimit the substring.  The third
argument specifies a prefix pattern that is to be skipped (but must be
present!) before the substring is extracted.  The final argument specifies
the escape character to be used for each delimiter.

   All arguments are optional. If the escape characters are not specified,
every delimiter is escaped with a backslash (\).  If the prefix is not
specified, the pattern `'\s*'' - optional whitespace - is used. If the
delimiter set is also not specified, the set `/["'`]/' is used. If the
text to be processed is not specified either, $_ is used.

   In list context, `extract_delimited' returns a array of three elements,
the extracted substring (*including the surrounding delimiters*), the
remainder of the text, and the skipped prefix (if any). If a suitable
delimited substring is not found, the first element of the array is the
empty string, the second is the complete original text, and the prefix
returned in the third element is an empty string.

   In a scalar context, just the extracted substring is returned. In a
void context, the extracted substring (and any prefix) are simply removed
from the beginning of the first argument.

   Examples:

     # Remove a single-quoted substring from the very beginning of $text:

     $substring = extract_delimited($text, "'", '');

     # Remove a single-quoted Pascalish substring (i.e. one in which
     # doubling the quote character escapes it) from the very
     # beginning of $text:

     $substring = extract_delimited($text, "'", '', "'");

     # Extract a single- or double- quoted substring from the
     # beginning of $text, optionally after some whitespace
     # (note the list context to protect $text from modification):

     ($substring) = extract_delimited $text, q{"'};

     # Delete the substring delimited by the first '/' in $text:

     $text = join '', (extract_delimited($text,'/','[^/]*')[2,1];

   Note that this last example is not the same as deleting the first
quote-like pattern. For instance, if $text contained the string:

     "if ('./cmd' =~ m/$UNIXCMD/s) { $cmd = $1; }"

     then after the deletion it would contain:

     "if ('.$UNIXCMD/s) { $cmd = $1; }"

   not:

     "if ('./cmd' =~ ms) { $cmd = $1; }"

   See `"extract_quotelike"' in this node for a (partial) solution to this
problem.

`extract_bracketed'
-------------------

   Like `"extract_delimited"', the `extract_bracketed' function takes up
to three optional scalar arguments: a string to extract from, a delimiter
specifier, and a prefix pattern. As before, a missing prefix defaults to
optional whitespace and a missing text defaults to $_. However, a missing
delimiter specifier defaults to `'{}()[]<>'' (see below).

   `extract_bracketed' extracts a balanced-bracket-delimited substring
(using any one (or more) of the user-specified delimiter brackets: '(..)',
'{..}', '[..]', or '<..>'). Optionally it will also respect quoted
unbalanced brackets (see below).

   A "delimiter bracket" is a bracket in list of delimiters passed as
`extract_bracketed''s second argument. Delimiter brackets are specified by
giving either the left or right (or both!) versions of the required
bracket(s). Note that the order in which two or more delimiter brackets
are specified is not significant.

   A "balanced-bracket-delimited substring" is a substring bounded by
matched brackets, such that any other (left or right) delimiter bracket
*within* the substring is also matched by an opposite (right or left)
delimiter bracket *at the same level of nesting*. Any type of bracket not
in the delimiter list is treated as an ordinary character.

   In other words, each type of bracket specified as a delimiter must be
balanced and correctly nested within the substring, and any other kind of
("non-delimiter") bracket in the substring is ignored.

   For example, given the string:

     $text = "{ an '[irregularly :-(] {} parenthesized >:-)' string }";

   then a call to `extract_bracketed' in a list context:

     @result = extract_bracketed( $text, '{}' );

   would return:

     ( "{ an '[irregularly :-(] {} parenthesized >:-)' string }" , "" , "" )

   since both sets of `'{..}'' brackets are properly nested and evenly
balanced.  (In a scalar context just the first element of the array would
be returned. In a void context, $text would be replaced by an empty
string.)

   Likewise the call in:

     @result = extract_bracketed( $text, '{[' );

   would return the same result, since all sets of both types of specified
delimiter brackets are correctly nested and balanced.

   However, the call in:

     @result = extract_bracketed( $text, '{([<' );

   would fail, returning:

     ( undef , "{ an '[irregularly :-(] {} parenthesized >:-)' string }"  );

   because the embedded pairs of `'(..)''s and `'[..]''s are
"cross-nested" and the embedded `'>'' is unbalanced. (In a scalar context,
this call would return an empty string. In a void context, $text would be
unchanged.)

   Note that the embedded single-quotes in the string don't help in this
case, since they have not been specified as acceptable delimiters and are
therefore treated as non-delimiter characters (and ignored).

   However, if a particular species of quote character is included in the
delimiter specification, then that type of quote will be correctly handled.
for example, if $text is:

     $text = '<A HREF=">>>>">link</A>';

   then

     @result = extract_bracketed( $text, '<">' );

   returns:

     ( '<A HREF=">>>>">', 'link</A>', "" )

   as expected. Without the specification of `"' as an embedded quoter:

     @result = extract_bracketed( $text, '<>' );

   the result would be:

     ( '<A HREF=">', '>>>">link</A>', "" )

   In addition to the quote delimiters `'', `"', and ``', full Perl
quote-like quoting (i.e. q{string}, qq{string}, etc) can be specified by
including the letter 'q' as a delimiter. Hence:

     @result = extract_bracketed( $text, '<q>' );

   would correctly match something like this:

     $text = '<leftop: conj /and/ conj>';

   See also: `"extract_quotelike"' and `"extract_codeblock"'.

`extract_tagged'
----------------

   `extract_tagged' extracts and segments text between (balanced)
specified tags.

   The subroutine takes up to five optional arguments:

  1. A string to be processed ($_ if the string is omitted or undef)

  2. A string specifying a pattern to be matched as the opening tag.  If
     the pattern string is omitted (or undef) then a pattern that matches
     any standard HTML/XML tag is used.

  3. A string specifying a pattern to be matched at the closing tag.  If
     the pattern string is omitted (or undef) then the closing tag is
     constructed by inserting a / after any leading bracket characters in
     the actual opening tag that was matched (not the pattern that matched
     the tag). For example, if the opening tag pattern is specified as
     `'{{\w+}}'' and actually matched the opening tag `"{{DATA}}"', then
     the constructed closing tag would be `"{{/DATA}}"'.

  4. A string specifying a pattern to be matched as a prefix (which is to
     be skipped). If omitted, optional whitespace is skipped.

  5. A hash reference containing various parsing options (see below)

        The various options that can be specified are:

`reject => $listref'
     The list reference contains one or more strings specifying patterns
     that must not appear within the tagged text.

     For example, to extract an HTML link (which should not contain nested
     links) use:

          extract_tagged($text, '<A>', '</A>', undef, {reject => ['<A>']} );

`ignore => $listref'
     The list reference contains one or more strings specifying patterns
     that are not be be treated as nested tags within the tagged text
     (even if they would match the start tag pattern).

     For example, to extract an arbitrary XML tag, but ignore "empty"
     elements:

          extract_tagged($text, undef, undef, undef, {ignore => ['<[^>]*/>']} );

     (also see `"gen_delimited_pat"' in this node below).

`fail => $str'
     The fail option indicates the action to be taken if a matching end
     tag is not encountered (i.e. before the end of the string or some
     `reject' pattern matches). By default, a failure to match a closing
     tag causes `extract_tagged' to immediately fail.

     However, if the string value associated with <reject> is "MAX", then
     `extract_tagged' returns the complete text up to the point of failure.
     If the string is "PARA", `extract_tagged' returns only the first
     paragraph after the tag (up to the first line that is either empty or
     contains only whitespace characters).  If the string is "", the the
     default behaviour (i.e. failure) is reinstated.

     For example, suppose the start tag "/para" introduces a paragraph,
     which then continues until the next "/endpara" tag or until another
     "/para" tag is encountered:

          $text = "/para line 1\n\nline 3\n/para line 4";

          extract_tagged($text, '/para', '/endpara', undef,
          			{reject => '/para', fail => MAX );

          # EXTRACTED: "/para line 1\n\nline 3\n"

     Suppose instead, that if no matching "/endpara" tag is found, the
     "/para" tag refers only to the immediately following paragraph:

          $text = "/para line 1\n\nline 3\n/para line 4";

          extract_tagged($text, '/para', '/endpara', undef,
          		{reject => '/para', fail => MAX );

          # EXTRACTED: "/para line 1\n"

     Note that the specified fail behaviour applies to nested tags as well.

   On success in a list context, an array of 6 elements is returned. The
elements are:

[0]
     the extracted tagged substring (including the outermost tags),

[1]
     the remainder of the input text,

[2]
     the prefix substring (if any),

[3]
     the opening tag

[4]
     the text between the opening and closing tags

[5]
     the closing tag (or "" if no closing tag was found)

   On failure, all of these values (except the remaining text) are undef.

   In a scalar context, `extract_tagged' returns just the complete
substring that matched a tagged text (including the start and end tags).
undef is returned on failure. In addition, the original input text has the
returned substring (and any prefix) removed from it.

   In a void context, the input text just has the matched substring (and
any specified prefix) removed.

`gen_extract_tagged'
--------------------

   (Note: This subroutine is only available under Perl5.005)

   `gen_extract_tagged' generates a new anonymous subroutine which
extracts text between (balanced) specified tags. In other words, it
generates a function identical in function to `extract_tagged'.

   The difference between `extract_tagged' and the anonymous subroutines
generated by `gen_extract_tagged', is that those generated subroutines:

   * do not have to reparse tag specification or parsing options every time
     they are called (whereas `extract_tagged' has to effectively rebuild
     its tag parser on every call);

   * make use of the new qr// construct to pre-compile the regexes they use
     (whereas `extract_tagged' uses standard string variable interpolation
     to create tag-matching patterns).

   The subroutine takes up to four optional arguments (the same set as
`extract_tagged' except for the string to be processed). It returns a
reference to a subroutine which in turn takes a single argument (the text
to be extracted from).

   In other words, the implementation of `extract_tagged' is exactly
equivalent to:

     sub extract_tagged
     {
     	my $text = shift;
     	$extractor = gen_extract_tagged(@_);
     	return $extractor->($text);
     }

   (although `extract_tagged' is not currently implemented that way, in
order to preserve pre-5.005 compatibility).

   Using `gen_extract_tagged' to create extraction functions for specific
tags is a good idea if those functions are going to be called more than
once, since their performance is typically twice as good as the more
general-purpose `extract_tagged'.

`extract_quotelike'
-------------------

   `extract_quotelike' attempts to recognize, extract, and segment any one
of the various Perl quotes and quotelike operators (see `perlop(3)' in
this node) Nested backslashed delimiters, embedded balanced bracket
delimiters (for the quotelike operators), and trailing modifiers are all
caught. For example, in:

     extract_quotelike 'q # an octothorpe: \# (not the end of the q!) #'

     extract_quotelike '  "You said, \"Use sed\"."  '

     extract_quotelike ' s{([A-Z]{1,8}\.[A-Z]{3})} /\L$1\E/; '

     extract_quotelike ' tr/\\\/\\\\/\\\//ds; '

   the full Perl quotelike operations are all extracted correctly.

   Note too that, when using the /x modifier on a regex, any comment
containing the current pattern delimiter will cause the regex to be
immediately terminated. In other words:

     'm /
     	(?i)		# CASE INSENSITIVE
     	[a-z_]		# LEADING ALPHABETIC/UNDERSCORE
     	[a-z0-9]*	# FOLLOWED BY ANY NUMBER OF ALPHANUMERICS
        /x'

   will be extracted as if it were:

     'm /
     	(?i)		# CASE INSENSITIVE
     	[a-z_]		# LEADING ALPHABETIC/'

   This behaviour is identical to that of the actual compiler.

   `extract_quotelike' takes two arguments: the text to be processed and a
prefix to be matched at the very beginning of the text. If no prefix is
specified, optional whitespace is the default. If no text is given, $_ is
used.

   In a list context, an array of 11 elements is returned. The elements
are:

[0]
     the extracted quotelike substring (including trailing modifiers),

[1]
     the remainder of the input text,

[2]
     the prefix substring (if any),

[3]
     the name of the quotelike operator (if any),

[4]
     the left delimiter of the first block of the operation,

[5]
     the text of the first block of the operation (that is, the contents of
     a quote, the regex of a match or substitution or the target list of a
     translation),

[6]
     the right delimiter of the first block of the operation,

[7]
     the left delimiter of the second block of the operation (that is, if
     it is a s, tr, or y),

[8]
     the text of the second block of the operation (that is, the
     replacement of a substitution or the translation list of a
     translation),

[9]
     the right delimiter of the second block of the operation (if any),

[10]
     the trailing modifiers on the operation (if any).

   For each of the fields marked "(if any)" the default value on success is
an empty string.  On failure, all of these values (except the remaining
text) are undef.

   In a scalar context, `extract_quotelike' returns just the complete
substring that matched a quotelike operation (or undef on failure). In a
scalar or void context, the input text has the same substring (and any
specified prefix) removed.

   Examples:

     # Remove the first quotelike literal that appears in text

     $quotelike = extract_quotelike($text,'.*?');

     # Replace one or more leading whitespace-separated quotelike
     # literals in $_ with "<QLL>"

     do { $_ = join '<QLL>', (extract_quotelike)[2,1] } until $@;

     # Isolate the search pattern in a quotelike operation from $text

     ($op,$pat) = (extract_quotelike $text)[3,5];
     if ($op =~ /[ms]/)
     {
     	print "search pattern: $pat\n";
     }
     else
     {
     	print "$op is not a pattern matching operation\n";
     }

`extract_quotelike' and "here documents"
----------------------------------------

   `extract_quotelike' can successfully extract "here documents" from an
input string, but with an important caveat in list contexts.

   Unlike other types of quote-like literals, a here document is rarely a
contiguous substring. For example, a typical piece of code using here
document might look like this:

     <<'EOMSG' || die;
     This is the message.
     EOMSG
     	exit;

   Given this as an input string in a scalar context, `extract_quotelike'
would correctly return the string "<<'EOMSG'\nThis is the message.\nEOMSG",
leaving the string " || die;\nexit;" in the original variable. In other
words, the two separate pieces of the here document are successfully
extracted and concatenated.

   In a list context, `extract_quotelike' would return the list

[0]
     "<<'EOMSG'\nThis is the message.\nEOMSG\n" (i.e. the full extracted
     here document, including fore and aft delimiters),

[1]
     " || die;\nexit;" (i.e. the remainder of the input text,
     concatenated),

[2]
     "" (i.e. the prefix substring - trivial in this case),

[3]
     "<<" (i.e. the "name" of the quotelike operator)

[4]
     "'EOMSG'" (i.e. the left delimiter of the here document, including
     any quotes),

[5]
     "This is the message.\n" (i.e. the text of the here document),

[6]
     "EOMSG" (i.e. the right delimiter of the here document),

[7..10]
     "" (a here document has no second left delimiter, second text, second
     right delimiter, or trailing modifiers).

   However, the matching position of the input variable would be set to
"exit;" (i.e. after the closing delimiter of the here document), which
would cause the earlier " || die;\nexit;" to be skipped in any sequence of
code fragment extractions.

   To avoid this problem, when it encounters a here document whilst
extracting from a modifiable string, `extract_quotelike' silently
rearranges the string to an equivalent piece of Perl:

     <<'EOMSG'
     This is the message.
     EOMSG
     || die;
     	exit;

   in which the here document *is* contiguous. It still leaves the
matching position after the here document, but now the rest of the line on
which the here document starts is not skipped.

   To prevent <extract_quotelike> from mucking about with the input in
this way (this is the only case where a list-context `extract_quotelike'
does so), you can pass the input variable as an interpolated literal:

     $quotelike = extract_quotelike("$var");

`extract_codeblock'
-------------------

   `extract_codeblock' attempts to recognize and extract a balanced
bracket delimited substring that may contain unbalanced brackets inside
Perl quotes or quotelike operations. That is, `extract_codeblock' is like
a combination of `"extract_bracketed"' and `"extract_quotelike"'.

   `extract_codeblock' takes the same initial three parameters as
`extract_bracketed': a text to process, a set of delimiter brackets to
look for, and a prefix to match first. It also takes an optional fourth
parameter, which allows the outermost delimiter brackets to be specified
separately (see below).

   Omitting the first argument (input text) means process $_ instead.
Omitting the second argument (delimiter brackets) indicates that only
`'{'' is to be used.  Omitting the third argument (prefix argument)
implies optional whitespace at the start.  Omitting the fourth argument
(outermost delimiter brackets) indicates that the value of the second
argument is to be used for the outermost delimiters.

   Once the prefix an dthe outermost opening delimiter bracket have been
recognized, code blocks are extracted by stepping through the input text
and trying the following alternatives in sequence:

  1. Try and match a closing delimiter bracket. If the bracket was the same
     species as the last opening bracket, return the substring to that
     point. If the bracket was mismatched, return an error.

  2. Try to match a quote or quotelike operator. If found, call
     `extract_quotelike' to eat it. If `extract_quotelike' fails, return
     the error it returned. Otherwise go back to step 1.

  3. Try to match an opening delimiter bracket. If found, call
     `extract_codeblock' recursively to eat the embedded block. If the
     recursive call fails, return an error. Otherwise, go back to step 1.

  4. Unconditionally match a bareword or any other single character, and
     then go back to step 1.

        Examples:

     # Find a while loop in the text

     if ($text =~ s/.*?while\s*\{/{/)
     {
             $loop = "while " . extract_codeblock($text);
     }

     # Remove the first round-bracketed list (which may include
     # round- or curly-bracketed code blocks or quotelike operators)

     extract_codeblock $text, "(){}", '[^(]*';

   The ability to specify a different outermost delimiter bracket is useful
in some circumstances. For example, in the Parse::RecDescent module,
parser actions which are to be performed only on a successful parse are
specified using a `<defer:...>' directive. For example:

     sentence: subject verb object
                     <defer: {$::theVerb = $item{verb}} >

   Parse::RecDescent uses `extract_codeblock($text, '{}<>')' to extract
the code within the `<defer:...>' directive, but there's a problem.

   A deferred action like this:

     <defer: {if ($count>10) {$count--}} >

   will be incorrectly parsed as:

     <defer: {if ($count>

   because the "less than" operator is interpreted as a closing delimiter.

   But, by extracting the directive using
`extract_codeblock($text, '{}', undef, '<>')' the '>' character is only
treated as a delimited at the outermost level of the code block, so the
directive is parsed correctly.

`extract_multiple'
------------------

   The `extract_multiple' subroutine takes a string to be processed and a
list of extractors (subroutines or regular expressions) to apply to that
string.

   In an array context `extract_multiple' returns an array of substrings
of the original string, as extracted by the specified extractors.  In a
scalar context, `extract_multiple' returns the first substring
successfully extracted from the original string. In both scalar and void
contexts the original string has the first successfully extracted
substring removed from it. In all contexts `extract_multiple' starts at
the current pos of the string, and sets that pos appropriately after it
matches.

   Hence, the aim of of a call to `extract_multiple' in a list context is
to split the processed string into as many non-overlapping fields as
possible, by repeatedly applying each of the specified extractors to the
remainder of the string. Thus `extract_multiple' is a generalized form of
Perl's split subroutine.

   The subroutine takes up to four optional arguments:

  1. A string to be processed ($_ if the string is omitted or undef)

  2. A reference to a list of subroutine references and/or qr// objects
     and/or literal strings and/or hash references, specifying the
     extractors to be used to split the string. If this argument is
     omitted (or undef) the list:

          [
                  sub { extract_variable($_[0], '') },
                  sub { extract_quotelike($_[0],'') },
                  sub { extract_codeblock($_[0],'{}','') },
          ]

     is used.

  3. An number specifying the maximum number of fields to return. If this
     argument is omitted (or undef), split continues as long as possible.

     If the third argument is N, then extraction continues until N fields
     have been successfully extracted, or until the string has been
     completely processed.

     Note that in scalar and void contexts the value of this argument is
     automatically reset to 1 (under -w, a warning is issued if the
     argument has to be reset).

  4. A value indicating whether unmatched substrings (see below) within the
     text should be skipped or returned as fields. If the value is true,
     such substrings are skipped. Otherwise, they are returned.

        The extraction process works by applying each extractor in
sequence to the text string. If the extractor is a subroutine it is called
in a list context and is expected to return a list of a single element,
namely the extracted text.  Note that the value returned by an extractor
subroutine need not bear any relationship to the corresponding substring
of the original text (see examples below).

   If the extractor is a precompiled regular expression or a string, it is
matched against the text in a scalar context with a leading '\G' and the
gc modifiers enabled. The extracted value is either $1 if that variable is
defined after the match, or else the complete match (i.e. $&).

   If the extractor is a hash reference, it must contain exactly one
element.  The value of that element is one of the above extractor types
(subroutine reference, regular expression, or string).  The key of that
element is the name of a class into which the successful return value of
the extractor will be blessed.

   If an extractor returns a defined value, that value is immediately
treated as the next extracted field and pushed onto the list of fields.
If the extractor was specified in a hash reference, the field is also
blessed into the appropriate class,

   If the extractor fails to match (in the case of a regex extractor), or
returns an empty list or an undefined value (in the case of a subroutine
extractor), it is assumed to have failed to extract.  If none of the
extractor subroutines succeeds, then one character is extracted from the
start of the text and the extraction subroutines reapplied. Characters
which are thus removed are accumulated and eventually become the next
field (unless the fourth argument is true, in which case they are
disgarded).

   For example, the following extracts substrings that are valid Perl
variables:

     @fields = extract_multiple($text,
                                [ sub { extract_variable($_[0]) } ],
                                undef, 1);

   This example separates a text into fields which are quote delimited,
curly bracketed, and anything else. The delimited and bracketed parts are
also blessed to identify them (the "anything else" is unblessed):

     @fields = extract_multiple($text,
                [
                     { Delim => sub { extract_delimited($_[0],q{'"}) } },
                     { Brack => sub { extract_bracketed($_[0],'{}') } },
                ]);

   This call extracts the next single substring that is a valid Perl
quotelike operator (and removes it from $text):

     $quotelike = extract_multiple($text,
                                   [
                                     sub { extract_quotelike($_[0]) },
                                   ], undef, 1);

   Finally, here is yet another way to do comma-separated value parsing:

     @fields = extract_multiple($csv_text,
                               [
                                     sub { extract_delimited($_[0],q{'"}) },
                                     qr/([^,]+)(.*)/,
                               ],
                               undef,1);

   The list in the second argument means: *"Try and extract a ' or "
delimited string, otherwise extract anything up to a comma..."*.  The
undef third argument means: *"...as many times as possible..."*, and the
true value in the fourth argument means *"...discarding anything else that
appears (i.e. the commas)"*.

   If you wanted the commas preserved as separate fields (i.e. like split
does if your split pattern has capturing parentheses), you would just make
the last parameter undefined (or remove it).

`gen_delimited_pat'
-------------------

   The `gen_delimited_pat' subroutine takes a single (string) argument and
builds a Friedl-style optimized regex that matches a string delimited by
any one of the characters in the single argument. For example:

     gen_delimited_pat(q{'"})

   returns the regex:

     (?:\"(?:\\\"|(?!\").)*\"|\'(?:\\\'|(?!\').)*\')

   Note that the specified delimiters are automatically quotemeta'd.

   A typical use of `gen_delimited_pat' would be to build special purpose
tags for `extract_tagged'. For example, to properly ignore "empty" XML
elements (which might contain quoted strings):

     my $empty_tag = '<(' . gen_delimited_pat(q{'"}) . '|.)+/>';

     extract_tagged($text, undef, undef, undef, {ignore => [$empty_tag]} );

   `gen_delimited_pat' may also be called with an optional second argument,
which specifies the "escape" character(s) to be used for each delimiter.
For example to match a Pascal-style string (where ' is the delimiter and "
is a literal ' within the string):

     gen_delimited_pat(q{'},q{'});

   Different escape characters can be specified for different delimiters.
For example, to specify that '/' is the escape for single quotes and '%'
is the escape for double quotes:

     gen_delimited_pat(q{'"},q{/%});

   If more delimiters than escape chars are specified, the last escape char
is used for the remaining delimiters.  If no escape char is specified for
a given specified delimiter, '\' is used.

   Note that `gen_delimited_pat' was previously called `delimited_pat'.
That name may still be used, but is now deprecated.

DIAGNOSTICS
===========

   In a list context, all the functions return `(undef,$original_text)' on
failure. In a scalar context, failure is indicated by returning undef (in
this case the input text is not modified in any way).

   In addition, on failure in any context, the `$@' variable is set.
Accessing `$@->{error}' returns one of the error diagnostics listed below.
Accessing `$@->{pos}' returns the offset into the original string at which
the error was detected (although not necessarily where it occurred!)
Printing `$@' directly produces the error message, with the offset
appended.  On success, the `$@' variable is guaranteed to be undef.

   The available diagnostics are:

`Did not find a suitable bracket: "%s"'
     The delimiter provided to `extract_bracketed' was not one of
     `'()[]<>{}''.

`Did not find prefix: /%s/'
     A non-optional prefix was specified but wasn't found at the start of
     the text.

`Did not find opening bracket after prefix: "%s"'
     `extract_bracketed' or `extract_codeblock' was expecting a particular
     kind of bracket at the start of the text, and didn't find it.

`No quotelike operator found after prefix: "%s"'
     `extract_quotelike' didn't find one of the quotelike operators q, qq,
     `qw', `qx', s, tr or y at the start of the substring it was
     extracting.

`Unmatched closing bracket: "%c"'
     `extract_bracketed', `extract_quotelike' or `extract_codeblock'
     encountered a closing bracket where none was expected.

`Unmatched opening bracket(s): "%s"'
     `extract_bracketed', `extract_quotelike' or `extract_codeblock' ran
     out of characters in the text before closing one or more levels of
     nested brackets.

`Unmatched embedded quote (%s)'
     `extract_bracketed' attempted to match an embedded quoted substring,
     but failed to find a closing quote to match it.

`Did not find closing delimiter to match '%s''
     `extract_quotelike' was unable to find a closing delimiter to match
     the one that opened the quote-like operation.

`Mismatched closing bracket: expected "%c" but found "%s"'
     `extract_bracketed', `extract_quotelike' or `extract_codeblock' found
     a valid bracket delimiter, but it was the wrong species. This usually
     indicates a nesting error, but may indicate incorrect quoting or
     escaping.

`No block delimiter found after quotelike "%s"'
     `extract_quotelike' or `extract_codeblock' found one of the quotelike
     operators q, qq, `qw', `qx', s, tr or y without a suitable block
     after it.

`Did not find leading dereferencer'
     `extract_variable' was expecting one of '$', '@', or '%' at the start
     of a variable, but didn't find any of them.

`Bad identifier after dereferencer'
     `extract_variable' found a '$', '@', or '%' indicating a variable,
     but that character was not followed by a legal Perl identifier.

`Did not find expected opening bracket at %s'
     `extract_codeblock' failed to find any of the outermost opening
     brackets that were specified.

`Improperly nested codeblock at %s'
     A nested code block was found that started with a delimiter that was
     specified as being only to be used as an outermost bracket.

`Missing second block for quotelike "%s"'
     `extract_codeblock' or `extract_quotelike' found one of the quotelike
     operators s, tr or y followed by only one block.

`No match found for opening bracket'
     `extract_codeblock' failed to find a closing bracket to match the
     outermost opening bracket.

`Did not find opening tag: /%s/'
     `extract_tagged' did not find a suitable opening tag (after any
     specified prefix was removed).

`Unable to construct closing tag to match: /%s/'
     `extract_tagged' matched the specified opening tag and tried to
     modify the matched text to produce a matching closing tag (because
     none was specified). It failed to generate the closing tag, almost
     certainly because the opening tag did not start with a bracket of
     some kind.

`Found invalid nested tag: %s'
     `extract_tagged' found a nested tag that appeared in the "reject" list
     (and the failure mode was not "MAX" or "PARA").

`Found unbalanced nested tag: %s'
     `extract_tagged' found a nested opening tag that was not matched by a
     corresponding nested closing tag (and the failure mode was not "MAX"
     or "PARA").

`Did not find closing tag'
     `extract_tagged' reached the end of the text without finding a
     closing tag to match the original opening tag (and the failure mode
     was not "MAX" or "PARA").

AUTHOR
======

   Damian Conway (damian@conway.org)

BUGS AND IRRITATIONS
====================

   There are undoubtedly serious bugs lurking somewhere in this code, if
only because parts of it give the impression of understanding a great deal
more about Perl than they really do.

   Bug reports and other feedback are most welcome.

COPYRIGHT
=========

     Copyright (c) 1997-2000, Damian Conway. All Rights Reserved.
     This module is free software. It may be used, redistributed
     and/or modified under the terms of the Perl Artistic License
         (see http://www.perl.com/perl/misc/Artistic.html)

Simple lexical text/html/etc template parser
********************************************

NAME
====

     Text::BasicTemplate -- Simple lexical text/html/etc template parser

SYNOPSIS
========

     use Text::BasicTemplate;
     $bt = Text::BasicTemplate->new;
     my %dict = (
       name => 'John',
       location => sub { hostname() },
       condiments => [ 'Salt', 'Pepper', 'Catsup' ],
       sideeffects => { 'Salt' => 'causes high blood pressure',
     		    'Pepper' => 'causes mariachi music',
     		    'Catsup' => 'brings on warner bros. cartoons' },
       new => int rand 2
     );

     $tmpl = "Hello, %name%; your mail is in %$MAIL%. Welcome to %location%!";
     print $bt->parse(\$tmpl,\%dict);

     $tmpl = "%if new%First time, %name%?%fi%".
             " Care for some %condiments%? ".
             " They are bad for you.  %sideeffects%."
     $bt->{hash_specifier}->{condiments} = ' ';
     print $bt->parse(\$tmpl,\%dict);

DESCRIPTION
===========

   *Text::BasicTemplate* is a relatively straightforward template parsing
module.  Its overall function is to permit the separation of
format-dependent output from code.

   This module provides standard key/value substitutions, lexical
evaluation/parsing, customizable formatting of perl datatypes, and
assorted utility functions.

   Templates may be structured by the use of arbitrarily nestable
if-conditions (including elsif and else), and by the use of subroutine
substitutions to provide list parsing.  In general, the syntax for
conditionals is that of perl itself.

   Text::BasicTemplate attempts to be as fast and as secure as possible.
It may be safely used upon tainted templates and with tainted
substitutions without fear of execution of any malicious code.

GETTING STARTED
===============

   If you have previously used Text::BasicTemplate v0.x, it is important
to read the COMPATIBILITY section - many things have changed, and
compatibility is not guaranteed to be preserved in future versions.

   In general, start with the SYNTAX section, and be sure to at least skim
the new() section (for configuration settings) and parse() section (for an
explanation of the dictionary).

SYNTAX
======

   One of the difficulties in employing a new template parser is picking
up the apropriate syntax.  Text::BasicTemplate does not spare you that,
but it does adhere fairly closely to the syntax of perl itself with
respect to operators, conditional operations, template subroutine calls,
etc.

   Anything to which Text::BasicTemplate should pay attention in a
template is enclosed in percentage signs (%) - any such segments will be
interpreted as identifiers, operations, conditionals, or apropriate
combinations thereof.

   The simplest of these are variable substitutions; if parse() was passed
a dictionary containing the pair (foo => "bar"), any instances of %foo% in
the template will be evaluated as "bar."  Other variable substitutions are
available for lists and hashes, passed by reference in the parse()
dictionary, as in (bar => \@r, snaf => \%h).  In such a case %bar% will be
evaluated to the contents of @r, and %snaf% to the contents of %h.  Both
will be formatted according to the configured delimiters (see LIST/HASH
FORMATTING).  Subroutine references may also be included in the
dictionary; in their simple form, given ( subref => \&myfunction ),
%subref% in the template will be evaluated to whatever is returned from
&myfunction().  For more detail and features in subroutine handling, see
*SUBROUTINE SUBTITUTIONS*.

   In v0.9.7, BasicTemplate introduced simple conditional evaluation,
providing one-level equality/inequality comparisons.  In 2.0, after a
total rewrite, the conditional evaluation was replaced with a lexically
parsed scoping evaluation, providing arbitrarily deep nesting, most major
unary and binary perl comparison operators, arbitrary combination of
operations, nonconditional evaluation, etc.  For the full explanation,
read on:

SCOPING
-------

   Scoped evaluation is available to arbitrary depths, following the usual
if/elsif/else pattern.  if conditions are terminated by a *fi*.  By
example:

     # single if
     %if <condition>%
       <block>
     %fi%

     # if-else
     %if <condition>%
       <block>
     %else%
       <block2>
     %fi%

     # if-elsif
     %if <condition>%
       <block>
     %elsif <alternate condition>%
       <block2>
     %fi%

     # if-else-elsif
     %if <condition>%
       <block>
     %elsif <alternate condition>%
       <block2>
     %else%
       <block3>
     %fi%

   A block above is some amount of further template contents, including
none (%if <condition>%%fi% is perfectly valid, albeit not generally
useful).  A block may contain further conditions.  Dictionary variables
used in a conditional will only be evaluated if they come into scope - for
example, an elsif will not be evaluated unless its preceeding if or elsif
evaluted false - the principal consequence of this is that subroutines
referenced in a conditional will be called only if they come into scope
per the above.

IDENTIFIERS
-----------

   Numeric literals may be given without alteration, e.g. %123%.

   String literals should be given in double quotes, e.g. %"hello"%, or in
single quotes, e.g. %'goodbye'%.  Either sort may contain quotes of the
other sort.

   Scalar, list and hash variables should be given by name, e.g. %foo%.

   %% gives a literal % sign and is considered normal text.

   Environment variables may be used as %$PATH%.

   Subroutine references should generally be referenced as %&foo%, or
%&foo(arg1,arg2,...)% as apropriate.  %foo% may be used for subroutines
that return a scalar and will not require further parsing of their output
- see SUBROUTINE SUBSTITUTIONS.

EVALUATION
----------

   Statements, conditional or otherwise, may be used outside of if/else
contexts, and will have the results of the evaluation inserted at the
point in which they occurred in the template.  If used in an if/else
statement, they will be evaluated, but the apropriate block will be output
instead (pretty much the usual, IOW).

   *There is no operator precedence or conditional short-circuiting.* %1
|| 2% will evaluate both 1 and 2 (and return 2).  Evaluation order is not
guaranteed.  For all matters requiring precedence, parentheses should be
employed (e.g. %1 && (0 || 3)%).

   Most of the perl unary and binary operators are supported; the trinary
conditional is not.  Operators presently provided are as follows:

   *eq ne lt le gt ge* - identical to their perl equivalents.  Return 1 or
false.

   *=~ !~* - also equivalent to the perl versions, but must be enabled by
setting *enable_pattern_operator* true (see new()), as a malformed pattern
may kill the script - so do not use them if you think you might be
evaluating untrusted untrusted templates.  The form for these is =~
pattern, not =~ /pattern/.

   *== != < <= > >= <=>* - perl equivalent

   *&& and || or* - the two ands and the two ors are considered
equivalent, as there is no operator precedence in BasicTemplate.  && and
and return the value of the last operand.

   *. x* - perl equivalent; operand for x must be numeric.

   *+ - * / *** - perl equivalent, divide-by-zero will be checked.

   *div mod* - equivalent to int(x/y) and x % y respectively.

   *^ & | << >>* - perl equivalent

   *! defined* - perl equivalent.

   Examples: %foo + bar% - evaluates to result of foo+bar, where foo and
bar are variables given in the dictionary.

   %if foo && (bar || snaf)%   <block> %fi% - evaluates foo, bar and snaf,
outputs the block if the foo and one or more of bar and snaf were true.

   %"your name: " . &yourname% - outputs the string "your name: ",
followed by whatever was returned by the subroutine referenced by the
dictionary entry for yourname.

   %if $MAIL =~ Maildir%   Bernstein would be proud.  %else%   Eric Allman
wants you for a sunbeam.  %fi% - evaluates according to whether the
environment variable $MAIL contains the pattern 'Maildir.'

   Note that blocks inside conditional statements begin immediately
following the closing %, so in the above examples, the newline and spaces
would be considered part of the block and output if the condition
evaluated true.  This is acceptable for most whitespace-independent
usages, but you should not include whitespace in a conditional block if
you do not want it in the output.

LIST/HASH FORMATTING
--------------------

   List references will be parsed and  delimited according to
$obj->{list_delimiter}->{listname} if supplied, and
$obj->{list_delimiter}->{__default} if not (the latter is set with the
default_list_delimiter argument to new()).  The default is ", ".

   Hash references will be delimited using
$obj->{hash_delimiter}->{hashname} between pairs, and
$obj->{hash_specifier}->{hashname} between key and value.  As above,
__default will be used if a delimiter has not been specified for the
specific variable.  The defaults are ", " and "=" respectively.

   Example:

     $bt = Text::BasicTemplate->new(default_list_delimiter => ' and');

     $ss = "path: %path%" . "\n" . "env: %env%";
     $bt->{hash_specifier}->{env} = " is ";
     $bt->{hash_delimiter}->{env} = ", ";
     print $bt->parse(\$ss, { path => [ split(/:/,$ENV{PATH}) ],
                              env => \%ENV });

   Output from the above would be of the form:

     /bin and /usr/bin and /usr/local/bin
     SHELL is bash, VISUAL is emacs, RSYNC_RSH is ssh

SUBROUTINE SUBSTITUTIONS
------------------------

   Subroutine references are something of a special-case in
Text::BasicTemplate.  In a simple form, they can be used thusly:

     sub heart_of_oak {
       return "me lads, 'tis to glory we steer";
     }
     $bt = Text::BasicTemplate->new();
     $ss = "come cheer up %&rest_of_verse%";
     %ov = ( rest_of_verse => \&heart_of_oak );
     print $bt->parse(\$ss,\%ov);

   This would output "come cheer up me lads, 'tis to glory we steer," by
calling &heart_of_oak() and inserting its return value into the template.

   You can pass literals and variables defined in the template to a
subroutine, as follows:

     sub heart_of_oak {
       my @lines = ( "come cheer up me lads",
                     "'tis to glory we steer",
                     "to find something new in this wonderful year" );
       my $which = shift;
       my $loud = shift || 0;
       return $loud ? uc $lines[$which] : $lines[$which];
     }
     $bt = Text::BasicTemplate->new();
     $ss = "song: %&song(1,$loud)%, %&song(2,$loud)%, %&song(3,$loud)%";
     print $bt->parse(\$ss, { song => \&heart_of_oak, loud => 1 });

   This would produce the lines of the song, separated by ", "; as written
above (with loud == 1 in the dictionary), it will be shouted (inserted in
capitals, as per the call to uc()) - in the template, the use of $variable
in a subroutine call indicates that $variable should be gotten from the
dictionary rather than interpreted literally.  Use of $ is not the normal
BasicTemplate syntax - %variable% would be more proper, but introduces a
nasty parsing mess until the re engine gains balancing abilities
(scheduled for perl5.6 as of this writing).

   The argument $_bt_dict has special meaning, and will be replaced with
the hashref being used as the active substitution dictionary, thus giving
your routines access to it - it will be passed in the form of a hashref,
which you are free to alter during the call, so long as you keep the
effects of your caching options in mind.

   The available formatting of arguments passed to these subroutines is
any combination of:

     word, word,
     word => word, word
     word => "word \"word\" 'word'"
     word => 'word "word"'
     word => "word\nword",

     # as in:
     %&mysubroutine(foo,bar,snaf => 3,str => "foo bar", word => 'k"ib"o', flap => "\"ing\"")%

   In the first case, each word argument may contain anything but [,=>]
(that is, a comma, an = or a >; yes, that is not entirely proper).  If you
need to use any of those characters, put the arguments in quotes.  Parsing
with quotations is more accurate, but depends on lookbehind assertions and
is accordingly slow (the parse results are cached, so this is mostly an
issue in repetitive executions rather than use of many instances in one
template).

   When performing database queries, which may return in increments and
have separate beginning and ending operations, you can use three code
references in a single list reference, for beginning, middle and end.  The
first will be called once at the beginning, the second repeatedly until it
returns false, and the third once afterward.  For example:

     sub $number_count = 10;
     sub numbers_start { "Countdown, kinda like BASIC: " }
     sub numbers_list { $number_count-- }
     sub numbers_end { "\"blastoff. whee.\"" }
     my %ov = (
       numbers => [ \&numbers_start, \&numbers_list, \&numbers_end ]
     );
     $bt = Text::BasicTemplate->new();
     $ss = '%numbers%';
     print $bt->parse(\$ss,\%ov);

   This would call &numbers_start and insert the result, then call and
insert &numbers_list until it $number_count reached zero, then call
&numbers_end once and insert that.  This may easily be applied, for
example, to an execute, fetch, fetch, fetch, ..., finish sequence in DBI.
If you need only part of these three functions (e.g. a routine that does
not need a finish function), you can pass any one as an empty code
reference (e.g. \ sub { }).

   The real use of subroutine references becomes apparent when you need
the output from a function parsed into a template of its own.  As noted
above in the song() example, you can pass arguments to a subroutine via
the template.  This extends to passing hashes, e.g. %&foo(name => value)%,
in which (name,value) will be passed to the subroutine referenced as foo
in the parse() dictionary.  You may also pass an argument (bt_template =>
filename), in which case the output from the coderef will be assumed to be
a hashref; this hashref will then be added to the current parse()
dictionary (where duplication occurs, the hashref will take precedence)
and used as the dictionary given to a recursive call of parse() on the
file specified by bt_template.  So...

     sub start {
       return "hello, ";
     }
     my $pcount = 0;
     sub getname {
       my @people = ( { firstname => 'John', lastname => 'Doe' },
                      { firstname => 'Susan', lastname => 'Smith' }
                    );
       return $people[$pcount++];
     }
     sub end {
       return "Nice to see you.";
     }
     # assume that /path/hello-template contains
     # The Esteemed %firstname% %lastname%, Lord of All You Survey
     $bt = Text::BasicTemplate->new();
     $ss = "Greeting: \"%&greeting(bt_template => /path/hello-template)%\"";
     print $bt->parse(\$ss, { greeting => [ \&start, \&getname, \&end ] });

   In this instance, the return values of &start and &end will be used
as-is.  &getname will be called until it reaches undef (on the third
call); the hashrefs returned will be parsed into two copies of
/tmp/hello-template.  The final output would therefore be:

     hello, The Esteemed John Doe, Lord of All You Survey
     The Esteemed Susan Smith, Lord of All You Survey
     Nice to see you.

   This has obvious usefulness in terms of taking database output and
making presentable (e.g. HTML) output from it, amongst other uses.

PRAGMA/PREPROCESS FUNCTIONS
===========================

   Some basic pragma functions are provided for use in templates.  These
follow the same syntactical conventions as subroutine substitutions, but
correspond to programs internal to Text::BasicTemplate rather than
supplied by calling code.  Pragmas should not be used on untrusted
templates - when templates are not trustworthy, they should be disabled by
setting $object->{pragma_enable}->{name_of_pragma} to false, or more
simply disabling all pragmas by setting $object->{pragma_enable} = {}.  If
an option pragma_enable is passed to new(), it will be taken as a
substitute for the enabled list and not overridden.

   Individual pragmas may be added or overridden with code of your own by
setting $object->{pragma_functions}->{name_of_pragma} to a CODE reference.
The referenced routine should expect to be passed a list containing a
reference to the Text::BasicTemplate object, a hashref to the active
dictionary (which may be {}), followed by any arguments passed in the
template.  Pragma routines must match ^bt_, or they will not be
interpreted as pragmas.

   Pragmas provided are as follows.  Note that they follow, to a reasonable
extent, the format given by the Apache 1.3 mod_include specification, with
a few additions.  Options in [ square brackets ] are optional.

bt_include({ file | virtual }, filename, [ noparse ])
-----------------------------------------------------

   Includes a file in the given location in the template.  The first option
specifies from where the file should be loaded, equivalent to the Apache
mod_include form.  file means any regular path and filename.  *virtual* is
interpreted as relative to $object->{include_document_root} or
$ENV{DOCUMENT_ROOT} in that order of precedence; if no document root is
specified, no include is done.  *semisecure* is a restricted form of the
file form, in which files must match \w[\w\-.]{0,254} to be included (this
means, generally, that the included files must be in the working
directory, unless you chdir() or something).

   If *noparse* is supplied, the included file will be inserted as-is
without further adjustment.  Otherwise it will be run through parse() as
would any normal template.  You should use the noparse option when
including an untrusted template from a trusted one.

   bt_include() will only include readable regular files (that is, those
passing -e, -f and -r).  Note that this is suceptible to race conditions,
so it does not confer any security where a race could be exploited by the
usual file/symlink swapping.

   Examples:

     %&bt_include(file,templates/boxscores.html)%
      Includes the file, parses according to the active dictionary
     %&bt_include(file,orders/summary.txt,noparse)%
      Includes the file but without any parsing on the way
     %&bt_include(virtual,index.html)%
      Includes the file index.html from the document_root directory,
      with parsing.

   bt_include() is one the user might want to override if template files
are stored in a database or other non-file mechanism.

bt_exec({ cmd | cgi }, command, parse)
--------------------------------------

   Analogous to the Apache mod_include 'exec' directive.  Executes the
specified command and inserts its stdout output into the template in place
of the directive.  If parse is specified, this output will be handed to
parse() as if it were a template file.

   If cmd is given, the command will be read, parsed if selected, and
inserted as-is without validation on the command.  If cgi is given, the
output will be skipped up and including the first blank line to remove
HTTP headers.

   bt_exec() is not secure and should not be used except with trusted
templates and on trusted binaries.  For this reason it is disabled by
default and must be manually enabled by setting
$object->{pragma_enable}->{bt_exec} true either when calling new() or
subsequently.

COMPATIBILITY
=============

   Text::BasicTemplate 2.0 is a major rewrite from v0.9.8 and previous
versions.  Compatibility has been preserved to a degree, enough that with
compatibility mode enabled, there should be no difference in either output
or calling conventions.

   *Backwards-compatibility mode is enabled by default in v2.0, but will
be disabled in some future version, possibly without notice.*

   Backwards compatibility is a concern in two respects, that of template
format and calling conventions.

TEMPLATE FORMAT
---------------

   The BasicTemplate 2.0 template format is only minimally compatible with
the older form.  If your templates include conditionals or simple_ssi
HTML-style include directives, you will need to update your templates
and/or use compatibility mode.  A template that uses only variable
substitution (e.g. "Hello %name%") will not need compatibility mode.

   Compatibility mode is enabled by passing 'compatibility_mode_0x => 1'
to new() (see the POD for new()).  Note that compatibility mode is slower
than standard mode, because of conversion overhead.

   The convert_template_0x_2x() function can convert a 0.x template to a
2.0 template - see the POD for that function for the details.  This
function can easily be placed in a script to convert your templates in
place, and it is likely that such a script will be provided with
Text::BasicTemplate releases.

CALLING CONVENTIONS
-------------------

   In general, there should be no necessary change between 0.x calls and
2.x calls.  All the old calls have been replaced with stubs which call the
new versions.  These are roughly as follows:

     push(), parse_push() -- replaced by parse()
     print(), parse_print() -- replaced by print parse()
     list_cache() -- replaced by list_lexicon_cache()
     purge_cache() -- replaced by purge_*_cache()
     uncache() -- replaced by purge_lexicon_cache(), purge_file_cache()

USEFUL FUNCTIONS
================

new()
     Make a Text::BasicTemplate object.  Syntax is as follows:

          $bt = Text::BasicTemplate->new(
           max_parse_recursion => 32,
           use_file_cache => 0,
           use_lexicon_cache => 1,
           use_scalarref_lexicon_cache => 0,
           use_full_cond_cache => 1,
           use_cond2rpn_cache => 1,
           use_dynroutine_arg_cache => 1,
           use_flock => 1,
           default_list_delimiter => ", ",
           default_hash_delimiter => ", ",
           default_hash_specifier => "=",
           default_undef_identifier => "",
           compatibility_mode_0x => 1,
           eval_subroutine_refs => 1,
           strip_html_comments => 0,
           strip_c_comments => 0,
           strip_cpp_comments => 0,
           strip_perl_comments => 0,
           condense_whitespace => 0,
           simple_ssi => 1
          );

     All explicit arguments to new() are optional; the values shown above
     are the defaults.

     Configuration arguments given to new() have the following meanings:

    *max_parse_recursion*: When performing a recursive parse() on a template, as in the case of a subroutine substitution with a bt_template parameter (see the SYNTAX section), parsing will stop if recursion goes more than this depth - the typical cause would be a template A that included a subroutine reference that used a template B, which used a C, which used A again.
    *use_file_cache*: Templates specified to parse() by filename are read into memory before being given to the lexer.  If this option is set, the contents of the file will be cached in a hash after being read.  This is largely unnecessary if (as per default) lexicon caching is enabled.  Do not turn this on unless you have disabled lexicon caching, or are doing something dubious to the cache yourself.
    *use_lexicon_cache*: If true, the lexicon generated from an input template will be cached prior to parsing.  This is the normal form of caching, and enables subsequent calls to parse() to skip over the lexical parsing of templates, generally the most expensive part of the process.
    *use_scalarref_lexicon_cache*: If true, the above lexicon caching applies to templates given to parse() via scalar reference, as well as by filename. This is generally fine, but if you pass the contents of multiple templates by a reference to the same scalar, you may get cache mismatching.
    *use_full_cond_cache*: Controls caching of the results of evaluation of conditionals.  Has three settings, off (0), normal (1), and persistent (2).  If set off, every conditional will be reevaluated every time it is executed (this is not very expensive unless use_cond2rpn_cache is set off also; see documentation for that option).  This is necessary only if you intend to change the values in the dictionary during a parse(), as in the case of a template-referenced subroutine calling a method that changes the dictionary. This cache adds some speed; the operation normally requires O(n) where n is the number of operators in the conditional, plus the cond2rpn conversion overhead, if applicable.  When use_full_cond_cache is set to 1 (on, as per normal), conditionals are cached only for the span of one parse() call; if a template-referenced routine changes the dictionary for a variable already used in a conditional, the change will have no effect until the next call to parse().  When set to 2 (persistent), the conditional cache does not expire when parse() completes a single template, and indeed will not expire at all unless you call purge_fullcond_cache() manually.  This setting can be useful for fast repeated parsing of the same data into multiple templates, but is not suitable when the dictionary is changing.
    *use_dynroutine_arg_cache*: Subroutine substitutions in templates may be passed arguments; these arguments are parsed into a suitable list before being handed to the subroutine in question.  If this is enabled, the results of that parsing will be cached to speed future use.  This does not incur cache mismatches; leave enabled unless you have a good reason not to.
    *use_flock*: If set true, template files will be flock()ed with a LOCK_SH while being read.  Otherwise, they will be read blindly.  Win32 afflictees might wish to disable this; in general, leave it alone.  Note that files generally will need to be read only once each if either lexicon or file caching is enabled (see above).
    *default_list_delimiter*: When listrefs are substituted into a template, they will be join()ed with the contents of $self->{list_delimiter}->{name} if defined, or with this default value otherwise.  If you wish your listrefs contatenated with no delimiting, set this to ".  Default is ', '.
    *default_hash_delimiter*: As above, but separates key/value pairs in hashref substitution.  If %x = (y => z, x => p), this delimiter will be placed between y=z and x=p.  Overridden by $self->{hash_delimiter}->{name}.  Deault ', '.
    *default_hash_specifier*: As above, separating keys and values in hashref substitution.  In the above %x, this delimiter goes between y and z, and between x and p.  Overriden by $self->{hash_specifier}->{name}.  Default '='.
    *default_undef_identifier*: When a template calls for a substitution key which is undefined in the dictionary, this value will be substituted instead. Default is ".  Something obvious like '**undefined**' might be a good choice for debugging purposes.
    *eval_subroutine_refs*: This option enables evaluation of subroutine reference substitutions, e.g. %&myroutine()%.  Generally a safe option, but you might want to disable it if parsing untrustworthy templates.

    *compatibility_mode_0x*: Enables compatibility with templates written for Text::BasicTemplate v0.x.  See COMPATIBILITY section.
    *strip_html_comments*: If set true, HTML comments (<!- ... ->) will be removed from the parse results.  Note that nested comments are not properly stripped.  Default off.
    *strip_c_comments*: If true, C comments (/* ... */) will be removed from parse results.  Default off.
    *strip_cpp_comments*: If true, C and C++ comments (/* ... */ and // ...\n) will be removed from parse results.  Default off.
    *strip_perl_comments*: If true, perl and similar style comments (# ... \n) will be removed from parse results.  Default off.
    *condense_whitespace*: If true, whitespace in parse results will be condensed to the first byte of each, as would be done by most web browsers.  Useful for tightening bandwidth usage on HTML templates without making the input templates themselves unreadable.  Default off.
    *simple_ssi*: If true, server-parsed HTML directives of the #include persuasion will have the file referenced in their file="" or virtual="" arguments inserted in their place.  The form is <!-#include file="..."->.  This usage is deprecated in favor of the %&bt_include()% function - see the SYNTAX section.  Default off; this should not be enabled when using untrusted templates.
*parse SOURCE_TEMPLATE [ OVR ]*
     Given a source template in SOURCE_TEMPLATE, parses that template
     according to the key/value hash referenced by $ovr, then returns the
     result.

     If SOURCE_TEMPLATE is given as a scalar, it will be interpreted as a
     filename, and the contents of that file will be read, parsed, and
     returned.  If given as a scalar reference, it will be interpreted as
     a reference to a buffer containing the template (the referenced
     template will not be modified, and copies of the relevant parts will
     be used to build the lexicon).  If SOURCE_TEMPLATE contains an array
     reference, that array will be used instead of generating a new
     lexicon.

     If use_file_template_cache is true and the source template is loaded
     from a file, or if use_scalarref_lexicon_cache is true and the source
     template is given in a scalar reference, the lexicon will be cached
     to accelerate future parsing of the template.  If the contents of
     either the file or the referenced buffer changes during the lifespan
     of the Text::BasicTemplate object, the code will not notice - if you
     need to change the templates in this fashion, use *uncache()* to
     delete the cached lexicon.  Lexicon references are not cached, since
     the code assumes if you make your own templates you are capable of
     caching them, too.

     For templates stored in and loaded from files, note that they will be
     read and parsed in core, so you probably should not try to parse
     templates that would occupy a significant amount of your available
     memory.  For large seldom-used templates, also consider disabling
     lexicon caching or calling *uncache()* afterwards.

     *OVR* is a euphemism for some arbitrary combination of lists, scalar
     paris, hashrefs and listrefs.  These should cumulatively amount to
     the substitution dictionary - the simple form is { x => 'y' }, in
     which all %x% in the template will be replaced with y.  (x,y) will
     work also (and by extension, you may pass lists of these, or raw
     hashes).  The dictionary is parsed once, start-to-finish, so in the
     event of duplicated entries, the last entry of a given name will be
     the only one retained.

     Note on backwards-compatibility: in v0.x, it was possible to pass
     scalars of the form "x=y".  This is deprecated, and is only available
     if *compatibility_mode_0x* is set true.  Further, as references are
     now legal fodder for substitutions, ("x",\%y) means that %x% will
     parse to the contents of %y - if %y contains part of your
     substitution dictionary, then the above will present an error in any
     case, and ("x","y",\%y) is likely what you intended.

parse_range \@lexicon $start $end [ \@ov ]
     Parses and returns the relevant parts of the specified lexicon over
     the given range.  This has the happy side effect of eliminating the
     obnoxious passing around of chunks of the lexicon.  Instead one need
     only pass references to a single lexicon and the range over which it
     should be parsed.  This routine does the actual work of parse(), but
     is really only useful internally.

cond_evaluate CONDITIONAL [ \%ovr ]
     Evaluates the specified conditional left-to-right.  At present it does
     not handle operators also, just boolean/scalar evaluation.

identifier_evaluate $identifier \%ovr [ $type, $name ]
     Evaluates the specified identifier and returns its value.  Literals,
     being of the form \d+, "[...]" and '[...]', are returned as-is
     (leading and trailing quotes will be removed from string literals).

     Identifiers of standard (no special type) form are returned as they
     appear in \%ovr; if those stored values are listrefs or hashrefs,
     they will be returned in formatted form - listrefs will be returned
     as a scalar delimited by the value of
     $self->{list_delimiter}->{name}, hashes will be mapped into a scalar
     using $self->{hash_specifier}->{name} and
     $self->{hash_delimiter}->{name}, which three have the form ", ", "="
     and ", " respectively by default.

     Identifiers of the form $name will be checked against the environment
     variable of the same name, and if present, that value will be
     returned, otherwise undef will be returned.

     Identififers of the form &name will be returned according to those
     entries in \%ovr of the form &name - this is used to provide a
     separate namespace for substitutions, e.g. for CGI parameters.

     Identifiers of the form !name will be evaluated according to the
     return value(s) from whatever stored procedure(s) have been
     registered under that name, if any.  See `store_dynroutine' for
     details.

evaluate_dynroutine $name, $args, \%ovr
     Evalutes a routine referenced by a template.  The general form gives
     the name of the routine in $name (if no such named routine is
     available, returns undef), any arguments as a scalar $args, and the
     key-sub list in $ovr.

     $args should be given as a scalar - it will be parsed in
     parse_dynroutine_args and the result cached against future use.

parse_dynroutine_args $argstr
     Pulls apart the argument string passed to a template-referenced
     dynamic routine, and returns a listref for it.

     Format tolerance is only minimally clever.  The formats tolerated
     are, in any combination:

          word, word,
          word => word, word
          word => "word \"word\" 'word'"
          word => 'word "word"'
          word => "word\nword",

     In the first case, each word argument may contain anything but [,=>'"]
     (that is, ', ", =, or >; yes, that is not entirely proper).  If you
     need to use any of those characters, put the arguments in quotes.
     Parsing with quotations is more accurate, but depends on lookbehind
     assertions and is accordingly slow (the parse results are cached, so
     this is mostly an issue in repetitive executions rather than use of
     many instances in one template).

evaluate_pragma $name, $args, \%ovr
is_identifier \$candidate
     Takes a reference to a scalar containing a potential identifier.  In
     a scalar context, returns 1 or 0.  In a list context, returns
     (type,name) where type is one of the identififer type designators (&,
     !, $, etc) and name is the remainder of the identifier.

lex \$src
     Splits the specified source buffer into a series of tokens, returns a
     listref to the resulting lexicon.  See *ABOUT* for the details.

load_from_file $filename
     Loads a template from the specified file.  If use_file_cache is true,
     the file will be stored in the file cache (not necessary if caching
     is enabled for lexicons).

     This code is very trusting concerning its filename - the only check
     performed is to strip leading <, >, | and + signs to try to ensure
     that the filehandle obtained is read-only.  Trailing pipes will be
     left alone, so that "/path/to/binary|" may use the output from
     'binary'.

bt_exec
dump_lexicon \@lexicon [ $start_pos [ $end_pos ] ]
     Returns a dump of the given lexicon.  Principally used for debugging
     the module, or if you need to optimize templates to save lexical
     storage.  If $start_pos/$end_pos are given, only that range of the
     lexical array is dumped.

dump_stack \@stack
     Dumps the contents of a conditional-eval stack, which consists of a
     list of listrefs containing [ type, value ], type being one of the
     lexeme_types, value being either the identififer or an operator,
     depending on the type.

list_lexicon_cache
     Lists the lexicons cached for files/scalars/etc.

list_file_cache
     Lists the files cached in the file cache.  Empty unless
     use_file_cache is true.

list_cond2rpn_cache
     Lists the conditional-to-RPN conversion cache.  Empty if
     *use_cond2rpn_cache* is false.

list_fullcond_cache
     Lists the contents of the conditional evaluation cache.  Empty unless
     *use_full_cond_cache* is set true.

taint_enabled
     Tries to work out if taint checking is enabled, so that the right
     things can be enabled/disabled by new().

is_tainted SCALAR
     Returns true if taint checking is enabled and the specified variable
     is tainted.

debug DEBUGLEVEL
     Activates debugging output.

purge_lexicon_cache

purge_cond2rpn_cache
purge_fullcond_cache
purge_file_cache
     Purges the given cache.

list_cache
     Compatibility function for BasicTemplate 0.x; synonym for
     list_lexicon_cache

push, parse_push
     Compatibility functions for BasicTemplate 0.x; synonym for parse.

print, parse_print
     Compatibility functions for BasicTempltae 0.x

purge_cache
     Compatibility function for BasicTemplate 0.x; purges all applicable
     caches.

uncache FILE
     Compatibility function for BasicTemplate 0.x; purges the specified
     file from the file and lexicon caches.

convert_template_0x_2x $buffer
     Backwards-compatibility function for BasicTemplate 0.x; converts a
     template constructed for v0.x to v2.x.  Used internally for
     conversions on-the-fly in backwards-compatible mode.

     Note that this method will have no effect unless the 0.x template
     contains conditionals - simple %key% substitutions are the same in
     both versions.

HISTORY
=======

   2.004: Fixed a dumb oversight in test suite where valid comparison
strings assumed that the iteration order in a hash would be consistent and
predictable.  Passes make-test under perl5.6 now.

   2.0: Major rewrite.  Introduced lexical parsing, nested conditionals,
list/hash formatting, subroutine references, operator evaluation and much
other related stuff.

   0.9.8: Added subroutine-reference parsing.  This makes it possible to
bind keys to subroutines which will be called (once per template) when
needed; this can make things quicker if the template-specific
informational requirements may not be easily predicted in advance.

   0.9.7: Made stripping of lingering keys optional (default off); it was
causing problems with URI-encoded substitutions, and in retrospect
probably was not a good idea anyway.  Thanks to Ian Baker <ian@sonic.net>
for the bug report.

   0.9.6.1: Fixed stupid idiotic bug caused by overzealous optimization
(some things were not meant to be done with references - setting cache
scalars, for iinstance).  Renamed from ParsePrint to BasicTemplate for
submission to CPAN.  Fixed oversight wherein files inserted via simple_ssi
#includes were having keys stripped, but not parsed first.

   First fully public release.  Hooray...

   0.9.6: Rewrote argument handling in constructor the same way;
deprecated old style arg passage.

   0.9.5: Rewrote argument handling in parse_push to handle arbitrary
combinations of different arg types.

   0.9.4.1: Fixed nasty bug that set the lvalue in comparison to the name
of the entitity lvalue, not the value thereof.

   0.9.4: Lots of optimizations.  Inlined eval_conditional(), introduced
caching of condititionals (parse-once, print repeatedly), other such
changes.  Approximately doubled output speed to about 3100
conditionals/sec on my i686-200 Linux box.

   0.9.3: First stable, releaseable version.  Much documentation.

AUTHOR
======

   Text::BasicTemplate is by Devin Carraway <tbtpod@devin.com>, originally
written for Sonoma.Net in 1996.  Maintained until v0.9.5 as ParsePrint,
then Text::ParsePrint, then renamed for CPAN upload to Text::BasicTemplate.
Assorted further assistance and debugging rendered by Ian Baker
<ian@sonic.net> and Eric Eisenhart <tbtpod@eisenhart.com>.

COPYRIGHT
=========

   Copyright (c) 1996-1997 by Devin Carraway and Sonoma.Net.  Copyright
(c) 1997-1999 by Devin Carraway.  Released under terms of the Perl
Artistic License.

a corruptor of innocent text
****************************

NAME
====

   *Text::Bastardize* - a corruptor of innocent text

SYNOPSIS
========

     #!/usr/bin/perl -w
     use strict;
     use Text::Bastardize;

     my $text = new Text::Bastardize;
     while (my $line = <>) {
     	$text->charge($line);
     	$text->k3wlt0k();
     }

DESCRIPTION
===========

   *Bastardize* provides an magical object into which text can be charged
and then returned in various, slighty modified ways.

   *Bastardize* has the following methods

new
     new creates the array object.

charge
     charge defines the object's value, and is the reccomended way to do
     so.

peek
     peek returns the object's value.

rdct
     rdct converts english to hyperreductionist english.

     (ex. "english" becomes "")

pig
     pig pig latin.

     (ex. "hi there" becomes "ihay erethay")

k3wlt0k
     k3wlt0k a k3wlt0kizer developed originally by Fmh.

     The SYNOPSIS has an example of k3wlt0k in use, try tossing that into
     a file and running it with "sh|perl *k3wlt0k-filename*" :-)

rot13
     rot13 implements rot13 "encryption" in perl.

     (ex. "foo bar" becomes "sbb one")

rev
     rev reverses the arrangement of characters.

censor
     censor attempts to censor text which might be innaproriate.

n20e
     n20e performs numerical abbreviations.

     (ex. "numerical_abbreviation" becomes "n20e")

Bind Perl structures to text files
**********************************

NAME
====

   Text::Bind - Bind Perl structures to text files

SYNOPSIS
========

     use Text::Bind;

     # Create a new object
     $text = new Text::Bind;              	# or
     $text = new Text::Bind "page.html"		# or
     $text = new Text::Bind \*IN;

     # Bind a string value to a data site
     $text->bind_site("astring", "Hello World!");

     # Bind a function to a data site
     $text->bind_site("form", \&generate_form);

     # Bind a filehandle to a data site
     $text->bind_site("filehandle", \*FILE);

     # Bind an object to a data site
     $some_object = new SomeClass;
     $text->bind_site("object", $some_object);

     # Read text
     $text->read_text(\*OUT, "page.html");	# or
     $text->read_text(\*OUT, \*IN);		# or
     $text->read_text(\*OUT);   			# or
     $text->read_text;

DESCRIPTION
===========

   *Text::Bind* allows you to bind Perl structures (strings, routines,
filehandles, objects) to specific locations (called *data sites*) in text
files.

   The main purpose of this module is to support HTML templates for CGI
programs.  Therefore, HTML pages design can be kept separate from CGI
code.  However, the class is general enough to be used in other contexts
than CGI application development.  For example, it could be used to do
form letters.

   To create a new object, do one of the following:

     $text = new Text::Bind;
     $text = new Text::Bind $filename;
     $text = new Text::Bind \*FILE;

   If no argument is given during object instantiation, then the input
must be specified during the *read_text* method.  Otherwise, a filename or
a filehandle can be listed to specify the input source of the text data.

   To have the data processed, use the *read_text* method in one of the
following ways:

     $text->read_text;
     $text->read_text(\*OUT);
     $text->read_text(\*OUT, $filename);
     $text->read_text(\*OUT, \*FILE);

   When called with no arguments, input is read from what is specified
during object instantiation, and output goes to STDOUT.  If arguments are
specified, the first argument is the output filehandle.  If undefined,
STDOUT is used.  The second argument is the filename or the filehandle of
the input.  If not defined, input is read from what is specified during
object instantiation.

   The syntax for specifying data sites in the input and how to bind Perl
structures to those sites is covered in the following sections.

Data Site Syntax
================

   To define a data site, the syntax is as follows:

     ##PL_name=value##

   where the components mean the following:

`##PL_'
     Start of a data site.

name
     Type name of the site, possible values:

    site
          Specifies a labeled data site where the data for the site
          determined thru the bind_site method.

    file
          Specifies the name of file that defines the contents of the data
          site.  Works in a similiar manner as HTTP server-side file
          include directive.  If a trailing pipe is included in the value,
          then the value is treated as program to invoke, and the output
          of the program is used to fill the site.

    `beginloop'
          The start of a repeatable loop.  Text following, and up to the
          end-of-loop data site, is treated as a repeatable segment.  See
          `"Data Site Loops"' in this node for more information.

    `endloop'
          The end point of a repeatable loop.  See `"Data Site Loops"' in
          this node for more information.

     The name is case insensitive.

=
     Separator of name and value.

value
     String value associated with name.  Value is case sensitive.

`##'
     End of data site.

   Data sites that do not have a binding during processing of text input
are expanded to the empty string.

   Duplicate sites can occur.  The binding will be reexecuted each time
the site occurs.

Example data sites
------------------

   A data site for an HTML form:

     <html>
     <body>
     ##PL_site=inputform##
     </body>
     </html>

   The call to bind_site may look like:

     $text->bind_site("inputform", \&create_form)

   The following shows how a file can bound to a site:

     <html>
     <body>
     ...
     <hr>
     ##PL_file=copyright.html##
     </body>
     </html>

   The contents of `copyright.html' will replace the site definition.

   The following shows how the output of a program can be included:

     ##PL_file=/bin/ls -l |##

Data Site Bindings via bind_site Method
=======================================

   The *bind_site* method takes 2 arguments, the name of the site to bind
to and a value to define the value of the site during the read_text
method.  Example:

     $text->bind_site($name, $bind);

   The $name of the data site corresponds to the value of a
##PL_site=value## data site.

   The bind value can be one of the following Perl data structures:

scalar string
     The data site is replaced with the value of the scalar string.

function
     A reference to a function.  The function is invoked as follows:

          &func($textobj, $outfh, $site_name);

     Where, $textobj is the Text::Bind object.  $outfh is the output
     filehandle.  The function uses $outfh to output the data that should
     go in the location of the data site.  For example:

          print $outfh "... data here ...";

     $site_name is the name of the site the function is being called for.

     Since the Text::Bind object is passed to the function, the function
     can change bindings.  Any changes will affect any data sites following
     the site being processed.

     Additional arguments can be passed to the bind_site method when
     binding a function.  For example:

          $text->bind_site($site_name, \&func, $arg1, $arg2);

     A copy of those arguments will be passed as extra arguments when the
     function is invoked.  Continuing with the previous example, the
     function would be called as follows:

          &func($page_obj, $outfh, $site_name, $arg1, $arg2);

     Since the function may only exist for the purpose of filling the
     contents of a site, an anonymous function can be passed instead of a
     named function.  For example:

          $text->bind_site($site_name, sub {
          	my($txtobj, $fh, $site) = @_;

          ## ... code here ...
              });

     Note, the return value of the function is used within in data site
     loops.  See `"Data Site Loops"' in this node for more information.

filehandle
     A reference to a filehandle (technically a reference to a glob of a
     filehandle).  The filehandle is read until EOF and any data read goes
     in the location of the site.

object
     An object reference.  Text::Bind will attempt to call the method
     *fill_site* of the object.  Therefore, the object must have defined a
     method called fill_site, or a runtime error will occur.

     The method is invoked with the same arguments as in a function
     binding:

          $object->fill_site($page_obj, $outfh, $site_name);

     Any additional arguments passed during the bind_site call will be
     passed to the registered object's fill_site method like in function
     bindings:

          $object->fill_site($page_obj, $outfh, $site_name,
          		       $arg1, $arg2, ..., $argN);

     Note, the return value of the *fill_site* method is used within in
     data site loops.  See `"Data Site Loops"' in this node for more
     information.

array
     Actually, a reference to an array.  The values of the array are
     iterated over each time the data site is evaluated.  The items in the
     array can be scalar strings, functions, filehandles, or objects, as
     defined above.

     Binding an array to a site is most applicable for loops created by
     `##PL_beginloop##'.  See `"Data Site Loops"' in this node for more
     information.

Data Site Loops
===============

   Occasionally, there is a need to have a block of text be repeatable.
For example, lets take the following text data:

     ##PL_beginloop##Item = ##PL_site=listvalue##
     ##PL_endloop##

   And the following bindings:

     $text->bind_site('listvalue', [ 1, 2, 3, 4 ]);

   Will generated the following output:

     Item = 1
     Item = 2
     Item = 3
     Item = 4

   The text between the begin and end data sites is repeated until the
evaluation of ALL data sites within the loop generate no more data.

   Within a loop, types of data sites are treated as follows:

scalar string
     Will always be printed.  However, a scalar string data site will
     always be treated to have no more data when determine end of loop
     condition.

function or object
     Will always be invoked.  However, the return value is check to
     determine if the last value has been generated for the data site.  A
     return value of false tells `Text::Bind' that no more data exists for
     this site.

     WARNING: If the loop contains multiple data sites, it is possible
     that a function, or object method, will be called again if the other
     sites have not signified an end of data condition.  Hence, the
     function/method should still return a false value for the duraction of
     the loop.

filehandle
     Will always be printed.  However, a filehandle data site will always
     be treated to have no more data when determine end of loop condition.
     Also, since the EOF condition will be set after the first evaluation
     of the data site, subsequent evaluation will generate no data unless
     something resets the filehandle.

array
     The items of the array are iterated over until end of the array is
     reached.  Once the last item is reached, the end of data condition is
     set for the site.

Loop Examples
-------------

   A good example of loops is when populating an HTML table with data:

     <table>
     ##PL_beginloop##
     <tr>
     <td>##PL_site=lastname##</td>
     <td>##PL_site=firstname##</td>
     <td>##PL_site=street##</td>
     <td>##PL_site=city##</td>
     <td>##PL_site=state##</td>
     <td>##PL_site=zip##</td>
     </tr>
     ##PL_endloop##

LIMITATIONS
===========

   * Data site loops cannot be nested.

   * Multiple data site loops cannot exist on a single line.

AUTHOR
======

   Earl Hood, earlhood@bigfoot.com

   http://www.oac.uci.edu/indiv/ehood

format a script's output without programming
********************************************

NAME
====

   Text::Boilerplate - format a script's output without programming

SYNOPSIS
========

     use Text::Boilerplate;

     # Create a Boilerplate from a text string
     $boiler = new Text::Boilerplate $text;

     # Create a Boilerplate by loading a file
     $boiler = Text::Boilerplate->load($filename);

     # Create a Boilerplate by loading from a filehandle
     $boiler = Boilerplate->load(\*FILEHANDLE);

     # Fill in all tags in a Boilerplate
     print STDOUT $boiler->fill({
         'Tag Name'  => $value,
         'Tag Name2' => $value,
         'Tag Name3' => [
             { Subtag1 => $subval, Subtag2 => $subval2 },
             { Subtag1 => $subval3, Subtag2 => $subval4 }
         ],
     });

     # Get the Perl code to produce the Boilerplate
     $boiler->code();

     # Get information on the tags in the Boilerplate
     $boiler->tag_info();

DESCRIPTION
===========

   Boilerplates let you separate what a script does from what its output
looks like, using a simple mark-up language which is easy for
non-programmers to learn.  Using Boilerplates can make creating and
maintaining dynamic web pages and e-mail messages much easier.

Using the Boilerplate Mark-Up System
------------------------------------

   The Boilerplate mark-up system is designed to allow the look and feel
for script-generated text (i.e. dynamic HTML pages, form letters, etc.) to
be designed by someone who doesn't know how to program.

   Say, for example, that you need to develop a CGI script for a local
bookstore that lists their top three best-selling books, plus their
customer of the week.  If, like me, you have no real aptitude for HTML
page design, you'd probably have someone else design the actual page,
which, let's say, should look like this:

     <HTML>

     <HEAD>
         <TITLE>Boring Bookshop</TITLE>
     </HEAD>

     <BODY>
         <H1>Boring Books</H1>

     <P>
         <B>Customer Of The Week:</B> Bob Smeed
     </P>

     <P>
         <B>Top Three Best-Selling Books</B>

     1. <I>Book Title #1</I> by Author<BR>
     2. <I>Book Title #2</I> by Author #2<BR>
     3. <I>Book Title #3</I> by Author #3<BR>
             </P>
         </BODY>

     </HTML>

   Well, you could just hard-code the HTML into your script with print
statements.  Sooner or later, though, Boring Books is going to want
changes made to the HTML.  If this were an ordinary web page, they could
simply ask a page designer to make whatever fixes they want (e.g. putting
their logo on top, putting the top-selling books into an HTML table,
changing the background, etc.) without bothering you, the programmer.  In
this case, though, the HTML is buried inside a script, and even if the
graphics person is willing to make changes to your code, there's a strong
possibility that they might introduce errors into your script whenever
they edit it.

   That's where the Boilerplate mark-up system comes in.  Instead of
sticking your HTML in the script, you could create a separate text file,
consisting of:

     <HTML>
     <HEAD>
             <TITLE>Boring Bookshop</TITLE>
         </HEAD>
     <BODY>
             <H1>Boring Books</H1>

     <P>
         <B>Customer Of The Week:</B> [* "Customer" *]
     </P>

     <P>
         <B>Top Three Best-Selling Books</B>
         [* REPEAT NAME="Top Books" *]
             [* "Rank" *]. <I>[* "Title" *]</I>
             by [* "Author" *]<BR>
         [* /REPEAT *]
     </P>
         </BODY>

     </HTML>

   Then, in your script, add a few lines to load this file from disk and
fill it in with book titles and so forth.  Assuming you named the above
file "boringbooks.html", the code would look something like this:

     use Text::Boilerplate;

     # Do whatever is necessary to figure out the top-selling
     # books and customer of the week, print the HTML header,
     # etc.

     # Load the Boilerplate from its file
     $boiler = Text::Boilerplate->load('./boringbooks.html');

     # Print out the Boilerplate, filling in books
     # and customer
     print STDOUT $boiler->fill({
         'Customer'  => $customer,
         'Top Books' => \@books_info,      # @books_info:
                                           # A list of hashes a la
        });                                    # { 'Rank' => $rank,
                                           #   'Title' => $title,
                                           #   'Author => $author }

Efficiency
----------

   The Boilerplate system is designed to fill in values extremely quickly,
at the expense of some additional time taken during initialization.
Therefore, to get the most out of it, try to use as few 'load's or 'new's
as possible, and as many 'fill's as you want.  In CGI scripts, a good way
of doing this is to use FastCGI, like so:

     use CGI::Fast;
     use Text::Boilerplate;

     # Load the boilerplate for our dynamic page
     $boiler = Boilerplate->new(<<EOF);
     <HTML>
     <HEAD><TITLE>Greetings</TITLE></HEAD>
     <BODY>Hello, [* VALUE NAME="User Name" *]</BODY>
     </HTML>
     EOF

     # Start accepting web hits
     while ($form = new CGI::Fast) {

         # Print 'em out a personalized page, assuming that
         # they entered 'Name' on a previous form
         print $form->header();
         print $boiler->fill({'User Name' => $form->param('Name')});
     }

METHODS
=======

   Text::Boilerplate encapsulates a number of different modules allowing
you to create, learn about, and fill in boilerplate text.

Static Methods
--------------

new()
     Arguments: $text

     Creates a new Text::Boilerplate from a scalar.  For example:

          $form_ltr = new Text::Boilerplate("Dear [* 'Name' *],");

     This would create a new Text::Boilerplate with a VALUE fill-in tag
     named 'Name'.

load()
     Arguments: $filename

     Loads in a Text::Boilerplate from a text file or filehandle.  For
     example:

          $boiler = Text::Boilerplate->load('page1.boil');

     Load() croaks if it can't open the file.  I don't know if this is a
     bug or a feature.

     If you already have a filehandle open containing boilerplate text,
     you can pass load() a filehandle reference, like this:

          $boiler = Text::Boilerplate->load(\*DATA);

     This could be helpful if you want to store Text::Boilerplate data at
     the end of your script.  (Although this *would* defeat the purpose a
     bit...)

fill()
     Fills in all of the tags in a Boilerplate with the data provided to
     it, formatted appropriately, and returns the text of the filled-in
     Boilerplate.  Example:

          $boiler = Text::Boilerplate->new(<<EOF);
          In Xanadu did [* VALUE NAME="Person" *]
          A stately [* VALUE NAME="Item" *] decree...
          EOF

          $filled_boiler = $boiler->fill({
              'Person' => 'Kubla Khan',
              'Item'   => 'Pleasure-Dome',
          });

     $filled_boiler is now:

          In Xanadu did Kubla Khan
          A stately Pleasure-Dome decree...

     See `"BOILERPLATE TAGS"' in this node for a full discussion of
     Boilerplate tag syntax.

code()
     Behind the scenes, a Boilerplate is just a Perl subroutine compiled
     from the text of the Boilerplate document.  If for some strange
     reason you want to see the Perl code for this subroutine, use the
     code() method.  Keep in mind that this code is not especially
     human-readable.

tag_info()
     Returns a list of hashes containing the name, type, and attributes of
     all of the tags in the Boilerplate, like so:

          ( { 'Name'     => $name,
              'Type'     => $type,
              'Contents' => $contents }, ...)

     For nested tags (such as REPEAT), the 'Contents' key will contain a
     reference to a list of all of the tags contained between the tag
     (i.e. `[* REPEAT NAME="fish" *]') and its terminator (i.e. `[*
     /REPEAT *]').  Other tags will hold a reference to an empty list in
     the 'Contents' value.  =back

BOILERPLATE TAGS
================

   All of this is useless without tags to fill in.  Boilerplate tags are
always sandwiched between '[* ' and ' *]'.  They generally consist of a
tag type, followed by a list of attributes, e.g.:

     [* TAG NAME="name of tag" ATTR2="Another" ATTR3 *]

   Tag types and attribute names are case-insensitive; tag values are not.
Therefore, THIS="that" means the same thing as this="that", but not the
same as THIS="THAT".

   There are three ways to assign a value to an attribute: using a double
quote, using a single quote, and using no quotes.  These are all the same:

     [* TAG NAME="thing" *]
     [* TAG NAME='thing' *]
     [* TAG NAME=thing *]

   You can't use spaces in an attribute value without putting quotes
around the value.

General Tags
------------

   Tags of general utility.

VALUE
     Attributes: NAME

     Description: The VALUE tag is the simplest and most commonly-used of
     all Boilerplate tags.  It just fills in whatever data provided by the
     script.  Since it is so frequently used, there's a shortcut for it:
     just use the NAME attribute's value in quotes, and the Boilerplate
     module will interpret it as though it were a VALUE tag.

     (N.B.: I have since come to dislike using VALUE as a tag name, since
     it's so frequently an attribute.  Be prepared for changes.)

     Examples:

          [* VALUE NAME="User Name" *] has [* VALUE NAME="time" *]
          hours left on the system.

          The quick [* "Color" *] [* "Animal" *] jumped over the
          lazy [* "Other Animal" *]

REPEAT.../REPEAT
     Attributes: NAME

     Description: The REPEAT tag fills in as many copies of whatever is
     between it and its closing tag as are required by the data supplied
     by the script.

     If a SEPARATOR block appears within the REPEAT block, the contents of
     SEPARATOR are filled in between every repetition of the REPEAT block.
     Note that SEPARATOR cannot access data given to the REPEAT block by
     the script.

     Examples:

          <B>The users on this system are:</B>
          <OL>
          [* REPEAT NAME="User List" *]
              <LI>[* "Username" *]
          [* /REPEAT *]
          </OL>

          <B>Your menu item choices:</B>
          [* REPEAT NAME="Menu List" *]
          <P>
              [* "Menu Item" *]
          </P>
          [* SEPARATOR *]
          <HR>
          [* /SEPARATOR *]
          [* /REPEAT *]

SEPARATOR.../SEPARATOR
     Separates the repeating items in a REPEAT block.  See `"REPEAT"' in
     this node for details.  SEPARATOR's tags are filled in from the same
     set of values as the block surrounding the repeat.  (Don't worry
     about this overmuch.)

ENV
     Attributes: NAME

     Returns the environment variable (or equivalent) for which it's named.
     Probably not terribly useful on machines which don't support such
     things.  A frequent use of ENV is to create a form that calls its
     creating script, like so:

          <FORM METHOD="post" ACTION="[* ENV NAME='SCRIPT_NAME' *]">

     Since, in the CGI protocol, SCRIPT_NAME always contains the relative
     URL of the current script, the proper URL to call the script would be
     filled into the ACTION tag.

     The ENV tag opens up potential security holes if you keep sensitive
     data hanging around in environment variables.

IF.../IF
     Attributes: NAME

     If the value for which IF is named is true, it fills that in.  If that
     value is false, the section remains blank.  If an ELSE block appears
     within the IF block, the ELSE block is filled in.  For example:

          [* IF NAME="Items Found" *]
              [* "Items Found" *] items were found.
              [* ELSE *]
                  No items were found.
              [* /ELSE *]
          [* /IF *]

ELSE.../ELSE
     Inside an IF.../IF block, defines what to print if the IF value is
     false. See `"IF"' in this node.

Web Tags
--------

   While you're welcome to use the following tags for any purpose, they're
probably most useful in generating HTML pages on-the-fly.

INPUT
     Attributes: VALUE *any attribute*

     The INPUT tag is used for generating a form input HTML tag with a
     dynamic VALUE.  For example:

          <FORM METHOD="post" ACTION="/cgi-bin/other_script.pl">

          <P>
              User Name: [* INPUT NAME="User Name" *]
          </P>

          <INPUT TYPE="submit">

          </FORM>

     If the script decided that 'User Name' should be 'Christabel', for
     example, the filled-in boilerplate would be:

          <FORM METHOD="post" ACTION="/cgi-bin/other_script.pl">

          <P>
              User Name: <INPUT NAME="User Name" VALUE="Christabel">
          </P>

          <INPUT TYPE="submit">

          </FORM>

          If you wish for the input field to have a default value, you can
          specify it using the VALUE attribute, like so:

          [* INPUT NAME="User Name" VALUE="Person From Porlock" *]

     That way, if the script doesn't have a value for 'User Name', it will
     default to 'Person From Porlock'.

     Any other attributes given to INPUT will be copied verbatim into the
     filled-in tag, e.g.:

          [* INPUT NAME="User Name" SIZE="20" MAXSIZE="25" *]

     will become something like:

          <INPUT NAME="User Name" VALUE="Christabel" SIZE="20" MAXSIZE="25">

     Note that I only recommend using INPUT for simple fill-in fields, like
     text and number input types.  See `"RADIO"' in this node and
     `"CHECKBOX"' in this node for more complex form inputs.

RADIO
     Attributes: NAME VALUE

     Used to generate HTML <INPUT TYPE="radio"> tags.  The HTML tag is
     marked CHECKED if the value supplied by the script for this tag is
     equal to the tag's VALUE attribute.

CHECKBOX
     Attributes: NAME VALUE

     Used to generate HTML <INPUT TYPE="checkbox"> tags.  The HTML tag is
     marked CHECKED if one of the values supplied by the script for this
     tag is equal to the tag's VALUE attribute.

     Programmer's note: takes an array reference as argument.

SELECT.../SELECT
     ATTRIBUTES: NAME *any attribute*

     The SELECT tag is used to generate option lists with
     script-controllable selections.  The options are specified in the
     document with HTML <OPTION> tags, just as in ordinary HTML.  Values in
     the SELECT tag are passed on into the generated HTML.  For example:

          [* SELECT NAME="Poet" SIZE="4" *]
              <OPTION>Coleridge
          	<OPTION>Browning
              <OPTION>Wordsworth
          [* /SELECT *]

     If the script chose a value of "Browning" for "Poet", the script would
     return:

          <SELECT NAME="Poet" SIZE="4">
              <OPTION VALUE="Coleridge">Coleridge
          	<OPTION VALUE="Browning" SELECTED>Browning
          	<OPTION VALUE="Wordsworth">Wordsworth
          </SELECT>

     Programmer's note: this tag accepts an array ref, permitting multiple
     selections that way.

MENU
     Attributes: NAME any

     Used to create an HTML <SELECT> menu on-the-fly for a list of options.
     While the Boilerplate SELECT tag chooses from a list of options
     already present in the Boilerplate, MENU generates the appropriate tag
     from data supplied by the script.

     Programmer's note: this tag accepts a list of hashes, a la:

          [ { 'Option' => $opt, 'Value' => $val, 'Selected' => $sel } ... ]

SEE ALSO
========

   See Perl (perl.info), Text/Template, and
Text/Vpp.

COPYRIGHT
=========

   Copyright (c) 1997 Steve Nelson. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

AUTHOR
======

   senelson@negentropy.com (Steve Nelson)

comma-separated values manipulation routines
********************************************

NAME
====

   Text::CSV - comma-separated values manipulation routines

SYNOPSIS
========

     use Text::CSV;

     $version = Text::CSV->version();      # get the module version

     $csv = Text::CSV->new();              # create a new object

     $status = $csv->combine(@columns);    # combine columns into a string
     $line = $csv->string();               # get the combined string

     $status = $csv->parse($line);         # parse a CSV string into fields
     @columns = $csv->fields();            # get the parsed fields

     $status = $csv->status();             # get the most recent status
     $bad_argument = $csv->error_input();  # get the most recent bad argument

DESCRIPTION
===========

   Text::CSV provides facilities for the composition and decomposition of
comma-separated values.  An instance of the Text::CSV class can combine
fields into a CSV string and parse a CSV string into fields.

FUNCTIONS
=========

version
          $version = Text::CSV->version();

     This function may be called as a class or an object method.  It
     returns the current module version.

new
          $csv = Text::CSV->new();

     This function may be called as a class or an object method.  It
     returns a reference to a newly created Text::CSV object.

combine
          $status = $csv->combine(@columns);

     This object function constructs a CSV string from the arguments,
     returning success or failure.  Failure can result from lack of
     arguments or an argument containing an invalid character.  Upon
     success, `string()' can be called to retrieve the resultant CSV
     string.  Upon failure, the value returned by `string()' is undefined
     and `error_input()' can be called to retrieve an invalid argument.

string
          $line = $csv->string();

     This object function returns the input to parse() or the resultant
     CSV string of `combine()', whichever was called more recently.

parse
          $status = $csv->parse($line);

     This object function decomposes a CSV string into fields, returning
     success or failure.  Failure can result from a lack of argument or
     the given CSV string is improperly formatted.  Upon success, fields()
     can be called to retrieve the decomposed fields .  Upon failure, the
     value returned by fields() is undefined and `error_input()' can be
     called to retrieve the invalid argument.

fields
          @columns = $csv->fields();

     This object function returns the input to `combine()' or the
     resultant decomposed fields of parse(), whichever was called more
     recently.

status
          $status = $csv->status();

     This object function returns success (or failure) of `combine()' or
     parse(), whichever was called more recently.

error_input
          $bad_argument = $csv->error_input();

     This object function returns the erroneous argument (if it exists) of
     `combine()' or parse(), whichever was called more recently.

EXAMPLE
=======

     require Text::CSV;

     my $csv = Text::CSV->new;

     my $column = '';
     my $sample_input_string = '"I said, ""Hi!""",Yes,"",2.34,,"1.09"';
     if ($csv->parse($sample_input_string)) {
       my @field = $csv->fields;
       my $count = 0;
       for $column (@field) {
         print ++$count, " => ", $column, "\n";
       }
       print "\n";
     } else {
       my $err = $csv->error_input;
       print "parse() failed on argument: ", $err, "\n";
     }

     my @sample_input_fields = ('You said, "Hello!"',
     			     5.67,
     			     'Surely',
     			     '',
     			     '3.14159');
     if ($csv->combine(@sample_input_fields)) {
       my $string = $csv->string;
       print $string, "\n";
     } else {
       my $err = $csv->error_input;
       print "combine() failed on argument: ", $err, "\n";
     }

CAVEATS
=======

   This module is based upon a working definition of CSV format which may
not be the most general.

  1. Allowable characters within a CSV field include 0x09 (tab) and the
     inclusive range of 0x20 (space) through 0x7E (tilde).

  2. A field within CSV may be surrounded by double-quotes.

  3. A field within CSV must be surrounded by double-quotes to contain a
     comma.

  4. A field within CSV must be surrounded by double-quotes to contain an
     embedded double-quote, represented by a pair of consecutive
     double-quotes.

  5. A CSV string may be terminated by 0x0A (line feed) or by 0x0D,0x0A
     (carriage return, line feed).

AUTHOR
======

   Alan Citterman `<alan@mfgrtl.com>'

SEE ALSO
========

   perl(1)

comma-separated values manipulation routines
********************************************

NAME
====

   Text::CSV_XS - comma-separated values manipulation routines

SYNOPSIS
========

     use Text::CSV_XS;

     $csv = Text::CSV_XS->new();           # create a new object
     $csv = Text::CSV_XS->new(\%attr);     # create a new object

     $status = $csv->combine(@columns);    # combine columns into a string
     $line = $csv->string();               # get the combined string

     $status = $csv->parse($line);         # parse a CSV string into fields
     @columns = $csv->fields();            # get the parsed fields

     $status = $csv->status();             # get the most recent status
     $bad_argument = $csv->error_input();  # get the most recent bad argument

     $status = $csv->print($io, $columns); # Write an array of fields immediately
                                           # to a file $io

     $columns = $csv->getline($io);        # Read a line from file $io, parse it
                                           # and return an array ref of fields

     $csv->types(\@t_array);               # Set column types

DESCRIPTION
===========

   Text::CSV_XS provides facilities for the composition and decomposition
of comma-separated values.  An instance of the Text::CSV_XS class can
combine fields into a CSV string and parse a CSV string into fields.

FUNCTIONS
=========

version()
     (Class method) Returns the current module version.

new(\%attr)
     (Class method) Returns a new instance of Text::CSV_XS. The objects
     attributes are described by the (optional) hash ref `\%attr'.
     Currently the following attributes are available:

    quote_char
          The char used for quoting fields containing blanks, by default
          the double quote character (`"'). A value of undef suppresses
          quote chars. (For simple cases only).

    eol
          An end-of-line string to add to rows, usually undef (nothing,
          default), `"\012"' (Line Feed) or `"\015\012"' (Carriage Return,
          Line Feed)

    escape_char
          The char used for escaping certain characters inside quoted
          fields, by default the same character. (`"')

    sep_char
          The char used for separating fields, by default a comme. (`,')

    binary
          If this attribute is TRUE, you may use binary characters in
          quoted fields, including line feeds, carriage returns and NUL
          bytes. (The latter must be escaped as `"0'.) By default this
          feature is off.

    types
          A set of column types; this attribute is immediately passed to
          the types method below. You must not set this attribute
          otherwise, except for using the types method. For details see
          the description of the types method below.

    always_quote
          By default the generated fields are quoted only, if they need
          to, for example, if they contain the separator. If you set this
          attribute to a TRUE value, then all fields will be quoted. This
          is typically easier to handle in external applications. (Poor
          creatures who aren't using Text::CSV_XS. :-)

     To sum it up,

          $csv = Text::CSV_XS->new();

     is equivalent to

          $csv = Text::CSV_XS->new({
              'quote_char'  => '"',
              'escape_char' => '"',
              'sep_char'    => ',',
              'binary'      => 0
          });

combine
          $status = $csv->combine(@columns);

     This object function constructs a CSV string from the arguments,
     returning success or failure.  Failure can result from lack of
     arguments or an argument containing an invalid character.  Upon
     success, `string()' can be called to retrieve the resultant CSV
     string.  Upon failure, the value returned by `string()' is undefined
     and `error_input()' can be called to retrieve an invalid argument.

print
          $status = $csv->print($io, $columns);

     Similar to combine, but it expects an array ref as input (not an
     array!)  and the resulting string is not really created, but
     immediately written to the $io object, typically an IO handle or any
     other object that offers a print method. Note, this implies that the
     following is wrong:

          open(FILE, ">whatever");
          $status = $csv->print(\*FILE, $columns);

     The glob `\*FILE' is not an object, thus it doesn't have a print
     method. The solution is to use an IO::File object or to hide the glob
     behind an IO::Wrap object. See `IO::File(3)' in this node and
     `IO::Wrap(3)' in this node for details.

     For performance reasons the print method doesn't create a result
     string.  In particular the *$csv->string()*, *$csv->status()*,
     *$csv-*fields()> and *$csv->error_input()* methods are meaningless
     after executing this method.

string
          $line = $csv->string();

     This object function returns the input to parse() or the resultant CSV
     string of `combine()', whichever was called more recently.

parse
          $status = $csv->parse($line);

     This object function decomposes a CSV string into fields, returning
     success or failure.  Failure can result from a lack of argument or the
     given CSV string is improperly formatted.  Upon success, fields() can
     be called to retrieve the decomposed fields .  Upon failure, the value
     returned by fields() is undefined and `error_input()' can be called
     to retrieve the invalid argument.

     You may use the *types()* method for setting column types. See the
     description below.

getline
          $columns = $csv->getline($io);

     This is the counterpart to print, like parse is the counterpart to
     combine: It reads a row from the IO object $io using $io->getline()
     and parses this row into an array ref. This array ref is returned by
     the function or undef for failure.

     The *$csv->string()*, *$csv->fields()* and *$csv->status()* methods
     are meaningless, again.

types
          $csv->types(\@tref);

     This method is used to force that columns are of a given type. For
     example, if you have an integer column, two double columns and a
     string column, then you might do a

          $csv->types([Text::CSV_XS::IV(),
                       Text::CSV_XS::NV(),
                       Text::CSV_XS::NV(),
                       Text::CSV_XS::PV()]);

     Column types are used only for decoding columns, in other words by
     the parse() and *getline()* methods.

     You can unset column types by doing a

          $csv->types(undef);

     or fetch the current type settings with

          $types = $csv->types();

fields
          @columns = $csv->fields();

     This object function returns the input to `combine()' or the resultant
     decomposed fields of parse(), whichever was called more recently.

status
          $status = $csv->status();

     This object function returns success (or failure) of `combine()' or
     parse(), whichever was called more recently.

error_input
          $bad_argument = $csv->error_input();

     This object function returns the erroneous argument (if it exists) of
     `combine()' or parse(), whichever was called more recently.

EXAMPLE
=======

     require Text::CSV_XS;

     my $csv = Text::CSV_XS->new;

     my $column = '';
     my $sample_input_string = '"I said, ""Hi!""",Yes,"",2.34,,"1.09"';
     if ($csv->parse($sample_input_string)) {
       my @field = $csv->fields;
       my $count = 0;
       for $column (@field) {
         print ++$count, " => ", $column, "\n";
       }
       print "\n";
     } else {
       my $err = $csv->error_input;
       print "parse() failed on argument: ", $err, "\n";
     }

     my @sample_input_fields = ('You said, "Hello!"',
     			     5.67,
     			     'Surely',
     			     '',
     			     '3.14159');
     if ($csv->combine(@sample_input_fields)) {
       my $string = $csv->string;
       print $string, "\n";
     } else {
       my $err = $csv->error_input;
       print "combine() failed on argument: ", $err, "\n";
     }

CAVEATS
=======

   This module is based upon a working definition of CSV format which may
not be the most general.

  1. Allowable characters within a CSV field include 0x09 (tab) and the
     inclusive range of 0x20 (space) through 0x7E (tilde). In binary mode
     all characters are accepted, at least in quoted fields:

  2. A field within CSV may be surrounded by double-quotes. (The quote
     char)

  3. A field within CSV must be surrounded by double-quotes to contain a
     comma.  (The separator char)

  4. A field within CSV must be surrounded by double-quotes to contain an
     embedded double-quote, represented by a pair of consecutive
     double-quotes. In binary mode you may additionally use the sequence
     `"0' for representation of a NUL byte.

  5. A CSV string may be terminated by 0x0A (line feed) or by 0x0D,0x0A
     (carriage return, line feed).

AUTHOR
======

   Alan Citterman `<alan@mfgrtl.com>' wrote the original Perl module.
Please don't send mail concerning Text::CSV_XS to Alan, as he's not
involved in the C part which is now the main part of the module.

   Jochen Wiedmann `<joe@ispsoft.de>' rewrote the encoding and decoding in
C by implementing a simple finite-state machine and added the variable
quote, escape and separator characters, the binary mode and the print and
getline methods.

SEE ALSO
========

   `perl(1)' in this node, `IO::File(3)' in this node, `IO::Wrap(3)' in
this node

an object class for formatting text between  			different platforms.
********************************************************************

NAME
====

   Text::ConvertPlatform - an object class for formatting text between
different platforms.

SYNOPSIS
========

     # Initialization statement
     my $philip = new Text::ConvertPlatform; # or whatever you prefer

     $philip->filename("i_love_unix.html");	# file that is to be worked on
     $philip->filename;	# returns current FILENAME
     $philip->convert_to("unix");	# set conversion mode - default is "unix"
     				# there is no need to set this if you are
     				# using the default
     				# other modes are: "dos", "mac"
     $philip->process_file;	# convert FILENAME
     $philip->replace_file;	# overwrite FILENAME with NEWCONTENTS
     $philip->backup_file;	# create a copy of FILENAME with a .bak extension
     $philip->oldcontents;	# returns original contents of processed file
     $philip->newcontents;	# returns results of a processed file

DESCRIPTION
===========

   I've been quite bored at work lately and decided to write an easy way to
format text between different platforms. Specifically, it converts return
characters and optionally backs up the file it works on.

AUTHOR
======

   Philip Mikal, "djphil@aztec.asu.edu". Co-authored by Phil Stracchino.
Inspired from Adrian Scott's em.pl, which was given to me from Ken Berger.
I'd also like to thank Randy Ray for answering questions I had when
setting up this distribution.

SEE ALSO
========

   perl(1).

Module for implementing text wrapping
*************************************

NAME
====

   Text::Correct - Module for implementing text wrapping

SYNOPSIS
========

     use Text::Correct qw( wrap $MAX_LEN $PARA );
     $MAX_LEN = 60;  # 60 columns of text
     $PARA = 0;      # condense newlines
     print wrap($firstline_lead, $otherline_lead, @text);

     use Text::Correct qw( wrap );
     wrap("\t", "", $speech);  # "regular" paragraph formatting

DESCRIPTION
===========

   This module is sort of a different approach to text wrapping than taken
in Text::Wrap.  This module allows for condensing of newlines, to format
long blocks of text into one, or (as the default) to format paragraphs
(these are blocks of text separated by two or more newlines) individually.

Functions
---------

wrap(INITAL_LEAD, SUBSEQUENT_LEAD, TEXT)
     The first argument is the lead to be placed in front of the first
     line; the second is the lead to be placed in front of each subsequent
     line.  Following that is a list of lines of text.  The function is
     not exported by default.

expand(TEXT)
     This converts tabs to NULL characters.  This function is used
     internally, but is governed by the $TAB variable.

unexpand(TEXT)
     This converts series of NULL characters to tabs.  This function is
     used internally, but is governed by the $TAB variable.

Variables
---------

$Text::Correct::MAX_LEN
     The number of characters of text (excluding a newline) per line.

$Text::Correct::PARA
     A boolean deciding whether or not to invoke paragraph mode.  If
     paragraph mode is on, text will be split up into blocks separated by
     two or more newlines.  If it is off, the text will be treated as a
     single block, which means the text is condensed into one paragraph.

$Text::Correct::TAB
     This holds the number of spaces a tab is to represent.  It defaults
     to 8, and is used in determining the length of a string with tabs in
     it.

COMING SOON
===========

   I plan to reimplement this module using formline().

BUGS
====

   If text contains NULL characters, expand() and unexpand() will not work
properly.  Fix:  don't use NULL characters. ;)

AUTHOR
======

   Jeff Pinyan, japhy+perl@pobox.com, CPAN ID: PINYAN

SEE ALSO
========

     Text::Wrap
     Text::Tabs

Perl extension to find regexp delimited strings with proper nesting
*******************************************************************

NAME
====

   Text::DelimMatch - Perl extension to find regexp delimited strings with
proper nesting

SYNOPSIS
========

     use Text::DelimMatch;

     $mc = new Text::DelimMatch, $startdelim, $enddelim;

     $mc->quote('"');
     $mc->escape("\\");
     $mc->double_escape('"');
     $mc->case_sensitive(1);

     ($prefix, $match, $remainder) = $mc->match($string);
     ($prefix, $nextmatch, $remainder) = $mc->match();

DESCRIPTION
===========

   These routines allow you to match delimited substrings in a buffer.
The delimiters can be specified with any regular expression and the start
and end delimiters need not be the same.  If the delimited text is
properly nested, entire nested groups are returned.

   In addition, you may specify quoting and escaping characters that
contribute to the recognition of start and end delimiters.

   For example, if you specify the start and end delimiters as '\(' and
'\)', respectively, and the double quote character as a quoting character,
and the backslash as an escaping character, then the delimited substring
in this buffer is "(ma(t)c\)h)":

     'prefix text "(quoted text)" \(escaped \" text) (ma(t)c\)h) postfix text'

   In order to support this rather complex interface, the matching context
is encapsulated in an object.  The object, Text::DelimMatch, has the
following public methods:

new $start, $end, $escape, $dblesc, $qs1, $qe1, ... $qsn, $qen
     Creates a new object.  All of the arguments are optional, and can be
     set with other methods, but they must be passed in the specified
     order: start delimiter, end delimiter, escape characters, double
     escape characters, and a set of quote characters.

match $string
     In an array context, returns ($pre, $match, $post) where $pre is the
     text preceding the first match, $match is the matched text (including
     the delimiters), and $post is the rest of the text in the buffer.  In
     a scalar context, returns $match.

     If $string is not provided on subsequent calls, the $post from the
     previous match is used, unless keep is false.  If keep is false, the
     match always fails.

delim $start, $end
     Set the start and end delimiters.  Only one set of delimiters can be
     in use at any one time.

     Returns the delimters in use before this call.

quote $startq, $endq
     Specifies the start and end quote characters.  Multiple quote
     character pairs are supported, so this function is additive.  To
     clear the current settings, pass no arguments, e.g., $mc->quote().

     If only $start is passed, $end is assumed to be the same.

     In matching, quotes occur in pairs.  In other words, if (",") and
     (',') are both specified as quote pairs and a string beginning with "
     is found, it is ended only by another ", not by '.

     Returns the quote hash in use before this call.

escape $esc
     Specifies a set of escaping characters.  This can only be a string of
     characters.  $esc can be a regexp set or a simple string.  If it is a
     simple string, it will be translated into the regexp set "[
     quotemeta($esc) ]".

     Returns the escape characters in use before this call.

double_escape $esc
     Specifies a set of double-escaping characters, i.e., characters that
     are considered escaped if they occur in pairs.  For example, in some
     languages,

          'Don''t you see?'

     defines a string containing a single apostrophe.

     $esc can only be a string of characters.  $esc can be a regexp set or
     a simple string.  If it is a simple string, it will be translated
     into the regexp set "[ quotemeta($esc) ]".

     Returns the double-escaping characters in use before this call.

case_sensitive $bool
     Sets case sensitivity to $bool or true if $bool is not specified.

     Returns the case sensitivity in use before this call.

keep $bool
     Sets keep to $bool or true if $bool is not specified.

     Keep, which is true by default, specifies whether or not the matching
     context object keeps a local copy of the buffer used in matching.
     Keeping a local copy allows repeated matching on the same buffer, but
     might be a bad idea if the buffer is a terabyte long. ;-)

     Returns the keep setting in use before this call.

error $seterr
     Returns the last error that occured.  If $seterr is passed, the error
     is set to that value.  Some common kinds of bad input are detected
     and an error condition is raised.  If an error condition is raised,
     all matching fails until the error is cleared.

     The most common error is a bad regular expression, for example
     specifing the start delimiter as "(" instead of "\\(".  Remember,
     these are regexps!

pre_matched
     Returns the prefix text from the last match if keep is true.  Sets an
     error and returns an empty string if keep is false.

matched
     Returns the matched text from the last match if keep is true.  Sets
     an error and returns an empty string if keep is false.

post_matched
     Returns the postfix text from the last match if keep is true.  Sets
     an error and returns an empty string if keep is false.

debug $bool
     Sets debug to $bool or true if $bool is not specified.

     If debug is true, informative and progress messages are printed to
     STDOUT by some methods.

     Returns the debugging setting in use before this call.

dump
     For debugging, prints all of the instance variables for a particular
     object.

slow $bool
     For debugging.  Some classes of delimited strings can be located with
     much faster algorithms than can be used in the most general case.  If
     slow is true, the slower, general algorithm is always used.

   For simplicity, and backward compatibility with the previous (limited
release) incarnation of this module, the following functions are also
available directly:

nested_match ($string, $start, $end, $three)
     If $three is true, returns ($pre, $match, $post) in an array context
     otherwise returns ("$pre$match", $post).  In a scalar context, returns
     "$pre$match".

skip_nested_match ($string, $start, $end, $three)
     If $three is true, returns ($pre, $match, $post) in an array context
     otherwise returns ("$pre$match", $post).  In a scalar context, returns
     $post.

EXAMPLES
========

     $mc = new Text::DelimMatch '"';
     $mc->('pre "match" post') == '"match"';

     $mc->delim("\\(", "\\)");
     $mc->('pre (match) post')   == ('pre ', '(match)', ' post');
     $mc->('pre (ma(t)ch) post') == ('pre ', '(ma(t)ch)', ' post');

     $mc->quote('"');
     $mc->escape("\\");
     $mc->('pre (ma")"tch) post') == ('pre ', '(ma")"tch)', ' post');
     $mc->('pre (ma(t)c\)h\") post') == ('pre ', '(ma(t)c\)h\")', ' post');

   See also test.pl in the distribution.

AUTHOR
======

   Norman Walsh, norm@berkshire.net

COPYRIGHT
=========

   Copyright (C) Small Planet Software and Norman Walsh.  All rights
reserved.  This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

WARRANTY
========

   THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

SEE ALSO
========

   perl(1).

Phonetic encoding of words.
***************************

NAME
====

   Text::DoubleMetaphone - Phonetic encoding of words.

SYNOPSIS
========

     use Text::DoubleMetaphone qw( double_metaphone );
     my($code1, $code2) = double_metaphone("Aubrey");

DESCRIPTION
===========

   This module implements a "sounds like" algorithm developed by Lawrence
Philips which he published in the June, 2000 issue of *C/C++ Users
Journal*.  Double Metaphone is an improved version of Philips' original
Metaphone algorithm.

   In contrast to the Soundex and Metaphone algorithms, Double Metaphone
will sometimes return two encodings for words that can be plausibly
pronounced multiple ways.

   For additional details, see Philips' discussion of the algorithm at:

     http://www.cuj.com/archive/1806/feature.html

FUNCTIONS
=========

double_metaphone( STRING )
     Takes a word and returns a phonetic encoding.  In an array context,
     it returns one or two phonetic encodings for the word.  In a scalar
     context, it returns the first encoding.  The first encoding is
     usually based on the most commonly heard U.S. pronounciation of the
     word.

AUTHOR
======

   Copyright 2000, Maurice Aubrey <maurice@hevanet.com>.  All rights
reserved.

   This code is based heavily on the C++ implementation by Lawrence
Philips, and incorporates several bug fixes courtesy of Kevin Atkinson
<kevina@users.sourceforge.net>.

   This module is free software; you may redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

Man Pages
---------

   See Text/Metaphone, Text/Soundex,

Additional References
---------------------

   Philips, Lawrence. *C/C++ Users Journal*, June, 2000.

   Philips, Lawrence. *Computer Language*, Vol. 7, No. 12 (December), 1990.

   Kevin Atkinson (author of the Aspell spell checker) maintains a page
dedicated to the Metaphone and Double Metaphone algorithms at
<http://aspell.sourceforge.net/metaphone/>

The Extensible Perl PreProcessor
********************************

NAME
====

   EP3 - The Extensible Perl PreProcessor

SYNOPSIS
========

     use Text::EP3;
     [use Text::EP3::{Extension}] # Language Specific Modules
     my $object = new Text::EP3 file;
     $object->ep3_execute;
        [other methods that can be invoked]
        $object->ep3_process([$filename, [$condition]]);
        $object->ep3_output_file([$filename]);
        $object->ep3_parse_command_line;
        $object->ep3_modules([@modules]);
        $object->ep3_includes([@include_directories]);
        $object->ep3_reset;
        $object->ep3_end_comment([$string]);
        $object->ep3_start_comment([$string]);
        $object->ep3_line_comment([$string]);
        $object->ep3_delimeter([$string]);
        $object->ep3_gen_depend_list([$value]);
        $object->ep3_keep_comments([$value]);
        $object->ep3_protect_comments([$value]);
        $object->ep3_defines($string1=$string2);

DESCRIPTION
===========

   EP3 is a Perl5 program that preprocesses STDIN or some set of input
files and produces an output file.  EP3 only works on input files and
produces output files. It seems to me that if you want to preprocess
arrays or somesuch, you should be using perl.  EP3 was first developed to
provide a flexible preprocessor for the Verilog hardware description
language. Verilog presents some problems that were not easily solved by
using cpp or m4. I wanted to be able to use a normal preprocessor, but
extend its functionality.  So I wrote EP3 - the Extensible Perl
PreProcessor. The main difference between EP3 and other preprocessors is
its built-in extensibility. Every directive in EP3 is really a method
defined in EP3, one of its submodules, or embedded in the file that is
being processed. By linking the directive name to the associated methods,
other methods could be added, thus extending the preprocessor.

   Many of the features of EP3 can be modified via command line switches.
For every command line switch, there is an also accessor method.

Directives and Method Invocation
     Directives are preceded with the a user defined delimeter. The
     default delimeter is `@'. This delimeter was chosen to avoid
     conflicts with other preprocessor delimeters (`#' and the Verilog
     backtick), as well as Verilog syntax that might be found a the
     beginning of a line (`$', `&', etc.). A directive is defined in Perl
     as the beginning of the line, any amount of whitespace, and the
     delimeter immediately followed by Perl word characters (0-9A-Za-z_).

     EP3 looks for directives, strips off the delimeter, and then invokes
     a method of the same name. The standard directives are defined within
     the EP3 program. Library or user defined directives may be loaded as
     perl modules either via the use command or from a command line switch
     for inclusion at the beginning of the EP3 run. Using the "include"
     directive coupled with the "perl_begin/end" directives perl
     subroutines (and hence EP3 directives) may be dynamically included
     during the EP3 run.

Directive Extension Method 1: The use command.
     A module may be included with the use statement provided that it
     pushes its package name onto EP3's @ISA array (thus telling EP3 to
     inherit its methods).  For a Verilog module whose filename is
     Verilog.pm and has the package name Text::EP3::Verilog, the following
     line must be included ...

          push (@Text::EP3::ISA, qw(Text::EP3::Verilog));

     This package can then be simply included in whatever script you are
     using to call EP3 with the line:

          use Text::EP3::Verilog;

     All methods within the module are now available to EP3 as directives.

Directive Extension Method 2: The command line switch.
     A module can be included at run time with the -module modulename
     switch on the command line (assuming the ep3_parse_command_line
     method is invoked). The modulename is assumed to have a .pm extension
     and exist somewhere in the directories specified in @INC.  All
     methods within the module are now available to EP3 as directives.

Directive Extension Method 3: The ep3_modules accessor method.
     Modules can be added by using the accessor method ep3_modules.

          $object->ep3_modules("module1","module2", ....);

     All methods within the module are now available to EP3 as directives.

Directive Extension Method 4: Embedded in the source code or included files.
     Using the perl_begin and perl_end directives to delineate perl
     sections, subroutines can be declared (as methods) anywhere in a
     processed file or in a file that the process file includes. In this
     way, runtime methods are made available to EP3. For example ...

          1 Text to be printed ...
          @perl_begin
          sub hello {
          	my $self = shift;
          	print "Hello there\n";
          }
          @perl_end
          2 Text to be printed ...
          @hello
          3 Text to be printed ...

          would result in
          1 Text to be printed ...
          2 Text to be printed ...
          Hello there
          3 Text to be printed ...

     Using this method, libraries of directives can be built and included
     with the include directive (but it is recommended that they be moved
     into a module when they become static).

Input Files and Processing
     Input files are processed one line at a time. The EP3 engine attempts
     to perform substitutions with elements stored in macro/define/replace
     lists. All directive lines are preprocessed before being evaluated
     (the only exception being the key portions of the if[n]def and define
     directives). Directive lines can be extended across multiple lines by
     placing the `\' character at the end of each line. Comments are
     normally protected from the preprocessor, but protection can be
     dynamically turned off and then back on. From a command line switch,
     comments can also be deleted from the output.

Output Files
     EP3 typically writes output to Perl's STDOUT, but can be assigned to
     any output file. EP3 can also be run in "dependency check" mode via a
     command line switch. In this mode, normal output is suppressed, and
     all dependent files are output in the order accessed.  NOTE! EP3 uses
     the select call to change the default output file for included perl
     blocks. However, if you are using a method invocation of ep3, note
     that the default output for the rest of your script will be changed
     as well.  (This can be easily worked with, but should be known
     beforehand).

     Most parameters can be modified before invoking EP3 including
     directive string, comment delimeters, comment protection and
     inclusion, include path, and startup defines.

Standard Directives
===================

   EP3 defines a standard set of preprocessor directives with a few
special additions that integrate the power of Perl into the coded language.

The define directive
     @define key definition The define directive assigns the definition to
     the key. The definition can contain any character including
     whitespace. The key is searched for as an individual word (i.e the
     input to be searched is tokenized on Perl word boundaries). The
     definition contains everything from the whitespace following the key
     until the end of the line.

The replace directive
     @replace key definition The replace directive is identical to the
     define directive except that the substitution is performed if the key
     exists anywhere, not just on word boundaries.

The macro directive
     @macro key(value[,value]*) definition The macro directive tokenizes
     as the define directive, replacing the key(value,...) text with the
     definition and saving the value list. The definition is then parsed
     and the original macro values are replaced with the saved values.

The eval directive
     @eval key expr The eval directive first evaluates the expr using
     Perl. Any valid Perl expr is accepted. This key is then defined with
     the result of the evaluation.

The include directive
     @include <file> or "file" [condition] The include directive looks for
     the "file" in the present directory, and <file> anywhere in the
     include path (definable via command line switch). Included files are
     recursively evaluated by the preprocessor. If the optional condition
     is specified, only those lines in between the text strings "@mark
     condition_BEGIN" and "@mark condition_END" will be included. The
     condition can be any string. For example if the file "file.V"
     contains the following lines:

          1 Stuff before
          @mark PORT_BEGIN
          2 Stuff middle
          @mark PORT_END
          3 Stuff after

     Then any file with the following line:

          @include "file.V" PORT

     will include the following line from file.V

          2 Stuff middle

     This is useful for partial inclusion of files (like port list
     specifications in Verilog).

The enum directive
     @enum a,b,c,d,...  enum generates multiple define's with each
     sequential element receiving a 1 up count from the previous element.
     Default starts at 0. If any element is a number, the enum value will
     be set to that value.

The ifdef and ifndef directives
     @ifdef and @ifndef key Conditional compilation directives. The key is
     defined if it was placed in the define/replace list by define,
     replace, or any command that generates a define or replace.

The if directive
     @if expr The expression is evaluated using Perl. The expression can
     be any valid Perl expression. This allows for a wide range of
     conditional compilation.

The elif [elsif] directive
     @[elif|elsif] key | expr The else if directive. Used for either
     "if[n]def" or "if".

The else directive
     @else The else directive. Used for either "if[n]def" or "if".

The endif directive
     @endif The conclusion of any "if[n]def" or "if" block.

The comment directive
     @comment on|off|default|previous The comment switch can be one of
     "on", "off", "default", or "previous". This is used to turn comments
     on or off in the resultant file. This directive is very useful when
     including other files with commented header descriptions. By using
     "comment off" and "comment previous" surrounding a header the output
     will not see the included files comments. Using "comment on" with
     "comment previous" insures that comments are included (as in an
     attached synthesis directive file). The default comment setting is
     on. This can be altered by a command line switch. The "comment
     default" directive will restore the comment setting to the EP3
     invocation default.

The ep3 directive
     @ep3 on|off The "ep3 off" directive turns off preprocessing until the
     "ep3 on" directive is encountered. This can greatly speed up
     processing of large files where postprocessing is only necessary in
     small chunks.

The perl_begin and perl_end directives
     @perl_begin perl code here ....  (Single line and multi-line output
     mechanisms are available)

     @> text to be output after variable interpolation or

     @>> text to be output

          after variable interpolation

          @<<

     @perl_end

     The "perl" directives provide the underlying language with all of the
     power of perl, embedded in the preprocessed code. Anything enclosed
     within the "perl_begin" and "perl_end" directives will be evaluated
     as a Perl script. This can be used to include a subroutine that can
     later be called as a directive. Using this type of extension,
     directive libraries can be developed and included to perform a
     variety of powerful source code development features.  This construct
     can also be used to mimic and expand the VHDL generate capabilities.
     The "@>" and "@>> @<<" directives from within a perl_[begin|end]
     block directs ep3 to perform variable interpolation on the given line
     and then print it to the output.

The debug directive
     @debug on|off|value The debug directive enables debug statements to
     go to the output file. The debug statements are preceded by the Line
     Comment string. Currently the debug values that will enable printouts
     are the following:

          0x01  1  - Primary messages (Entering Subroutines)
          0x02  2  - ep3_process Engine
          0x04  4  - define (replace, macro, eval, enum)
          0x08  8  - include
          0x10  16 - if (else, ifdef, etc.)
          0x20  32 - perl_begin/end

EP3 Methods
===========

   EP3 defines several methods that can be invoked by the user.

ep3_execute
     Execute sets up EP3 to act like a perl script. It parses the command
     line, includes any modules specified on the command line, loads in
     any specified modules, does any preexisting defines, sets up the
     output files, and then processes the input. Sort of the whole shebang.

ep3_parse_command_line
     ep3_parse_command_line does just that - parses the command line
     looking for EP3 options. It uses the GetOpt::Long module.

ep3_modules
     This method will find and include any modules specified as arguments.
     It expects just the name and will append .pm to it before doing a
     require.  The module returns the methods specified in the objects
     methods array.

ep3_output_file
     ep3_output_file  determines what the output should be (either the
     processed text or a list of dependencies) and where it should go. It
     then proceeds to open the required output files.  NOTE! - this module
     uses select to change the default output file.  The module returns
     the output filename.

ep3_reset
     ep3_reset resets all of the internal EP3 lists (defines, replaces,
     keycounts, etc.) so that a user can do multiple files independently
     from within one script.

ep3_process([$filename [$condition]])
     ep3_process is the guts of the whole thing. It takes a filename as
     input and produces the specified output. This is the method that is
     iteratively called by the include directive. A null filenam will
     cause ep3_process to look for filenames in ARGV.

ep3_includes([@include_directories])
     This method will add the specified directories to the ep3 include
     path.

ep3_defines($string1=$string2);
     This method will initialize defines with string1 defined as string 2.
     It initializes all of the defines in the objects Defines array.

ep3_end_comment([$string]);
     This method sets the end_comment string to the value specifed.  If
     null, the method returns the current value.

ep3_start_comment([$string]);
     This method sets the start_comment string to the value specifed.  If
     null, the method returns the current value.

ep3_line_comment([$string]);
     This method sets the end_commenline string to the value specifed.  If
     null, the method returns the current value.

ep3_delimeter([$string]);
     This method sets the delimeter string to the value specifed.  If
     null, the method returns the current value.

ep3_gen_depend_list([$value]);
     This method enables/disables dependency list generation. When
     gen_depend_list is 1, a dependency list is generated. When it is 0,
     normal operation occurs.  If null, the method returns the current
     value.

ep3_keep_comments([$value]);
     This method sets the keep_comments variable to the value specifed.
     If null, the method returns the current value.

ep3_protect_comments([$value]);
     This method sets the protect_comments variable to the value specifed.
     If null, the method returns the current value.

EP3 Options
===========

   EP3 Options can be set from the command line (if ep3_execute or
ep3_parse_command_line is invoked) or the internal variables can be
explicitly set.

[-no]protect
          Should comments be protected from substution?
          Default: 1

[-no]comment
          Should comments be passed to the output?
          Default: 1

[-no]depend
          Are we generating a dependency list or simply processing?
          Default: 0

-delimeter string
          The directive delimeter - can be a string
          Default: @

-define string1=string2
          Defines from the command line.
          Multiple -define options can be specified
          Default: ()

-includes directory
          Where to look for include files.
          Multiple -include options can be specified
          Default: ()

-output_filename filename
          Where to place the output.
          Default: STDOUT

-modules filename
          Modules to load (just the module name, expecting to find module.pm somewhere in @INC.
          Multiple -modules options can be specified
          Default: ()

-line_comment string
          The Line Comment string.
          Default: //

-start_comment string
          The Start Comment string.
          Default: /*

-end_comment string
          The End Comment string.
          Default: */

AUTHOR
======

   Gary Spivey, Dept. of Defense, Ft. Meade, MD.  spivey@romulus.ncsc.mil

   Many thanks to Steve Bresson for his help, ideas, and code ...

SEE ALSO
========

   perl(1).

Verilog extension for the EP3 preprocessor.
*******************************************

NAME
====

   Text::EP3::Verilog - Verilog extension for the EP3 preprocessor.

SYNOPSIS
========

     use Text::EP3;
     use Text::EP3::Verilog;

DESCRIPTION
===========

   This module is an EP3 extension for the Verilog Hardware Description
Language.

The signal directive
     @signal key definition Take a list of signals and generate signal
     lists in the differing formats that Verilog uses.  This is
     accomplished by formatting a list of new defines and then calling the
     EP3 define method For example, the following command:

          @signal KEY a[3:0], b, c[width:0], etc.

     will cause the following to be done:

          Define KEY with the list as it appears (can be used in further signal defs)
          Define KEY{SIG} with the signal list (can be used in port lists)
             	e.g. replace KEY{SIG} with  a[3:0], b, c[width:0]
          Define KEY{EVENT} with the reg list  (To be used in event lists)
             	e.g. replace KEY{EVENT} with a or b or c
          Define KEY{IN}  with the input list (you supply the first input and the trailing ';'
             	e.g. replace KEY{INPUT} with [3:0] a;\ninput b;\ninput[width:0] c
             	or ... make the line
             	input KEY{INPUT}; become ..
             	input [3:0] a;
             	input b;
             	input [width:0] c;
          Define KEY{OUT} with the output list (output [] sig).
             	e.g. like KEY{IN}
          Define KEY{INOUT}  with the inout list (inout [] sig).
             	e.g. like KEY{IN}
          Define KEY{WIRE} with the wire list (wire [] sig).
             	e.g. like KEY{IN}
          Define KEY{REG} with the reg list (reg [] sig).
             	e.g. like KEY{IN}
          Define KEY{DSP} with the printf list (sig=%0[b|x] depending on width).
             	e.g. replace KEY{DSP} with a=%0x, b=%0b, c=%0x
             	This can be used in the $display task
                	$display("KEY{DSP}",KEY{SIG});

     If the module and the test bench default is set up properly, the user
     needs only enter the signals in one place in the module file. This
     section can be included conditionally (e.g. @include "file" PORT) in
     the test bench and the signals can be automatically generated in the
     correct format in whichever header they are used. This means that a
     user can produce a module and its test bench by simply filling in the
     port list, the behavioral code, and the stimulus (which is of course,
     the real work). All of the signal header crud can be taken care of
     automagically.

The step directive
     @step number [command] The step directive is useful to save verbage
     in test benches. @step 5 command; generates the following code:

          repeat 5 @ (posedge tclk); command;

     The posdege can be changed to " or negedge (or whatever) using the
     edgetype directive. The tclk can be changed using the edgename
     directive.

The edgename directive
     @edgename name The edgename directive allows the user to change the
     name used in the step directive. The default is 'tclk'.

The edgetype directive
     @edgetype type The edgetype directive allows the user to change the
     type used in the step directive. The default is 'posedge'.

The denum directive
     @denum key, key, [value], key, ...  denum works like the ep3 enum,
     except that it generates verilog define statements. It also replaces
     KEY anywhere in the text with `KEY so that the verilog defines will
     work.  (e.g. @denum orange, blue, green     will generate:

          `define orange 0
          `define blue 0
          `define green 0
          @define orange `orange
          @define blue `blue
          @define green `green

AUTHOR
======

   Gary Spivey, Dept. of Defense, Ft. Meade, MD.  spivey@romulus.ncsc.mil

SEE ALSO
========

   perl(1).

Porter's stemming algorithm
***************************

NAME
====

   Text::English - Porter's stemming algorithm

SYNOPSIS
========

     use Text::English;
     @stems = Text::English::stem( @words );

DESCRIPTION
===========

   This routine applies the Porter Stemming Algorithm to its parameters,
returning the stemmed words.  It is derived from the C program "stemmer.c"
as found in freewais and elsewhere, which contains these notes:

     Purpose:    Implementation of the Porter stemming algorithm documented
                 in: Porter, M.F., "An Algorithm For Suffix Stripping,"
                 Program 14 (3), July 1980, pp. 130-137.
     Provenance: Written by B. Frakes and C. Cox, 1986.

   I have re-interpreted areas that use Frakes and Cox's "WordSize"
function. My version may misbehave on short words starting with "y", but I
can't think of any examples.

   The step numbers correspond to Frakes and Cox, and are probably in
Porter's article (which I've not seen).  Porter's algorithm still has
rough spots (e.g current/currency, -ings words), which I've not attempted
to cure, although I have added support for the British -ise suffix.

NOTES
=====

   This is version 0.1. I would welcome feedback, especially improvements
to the punctuation-stripping step.

AUTHOR
======

   Ian Phillipps <ian@unipalm.pipex.com>

COPYRIGHT
=========

   Copyright Public IP Exchange Ltd (PIPEX).  Available for use under the
same terms as perl.

a perl module to provide FIGlet abilities, akin to banner
*********************************************************

NAME
====

   Text::FIGlet - a perl module to provide FIGlet abilities, akin to banner

SYNOPSIS
========

     my $font = Text::FIGlet-Greater_Than_Special_Sequencenew(-f=>"doh");
     $font->figify(-A=>"Hello World");

DESCRIPTION
===========

   new

*-D=>*boolean
     If true, switches  to  the German (ISO 646-DE) character set.  Turns
     `[', `\' and `]' into umlauted A, O and U,  respectively.   `{',  `|'
     and `}' turn into the respective lower case versions of these.  `~'
     turns into  s-z. Assumin, of course, that the font author included
     these characters. This option is deprecated, which means it may not
     appear in upcoming versions of *Text::FIGlet*.

*-d=>*`fontdir'
     Whence to load the font.

     Defaults to `/usr/games/lib/figlet'

*-f=>*`fontfile'
     The font to load.

     Defaults to `standard'

*-m=>**smushmode*
     Specifies how *Text::FIGlet* should "smush" and kern consecutive
     characters together.  On the command line, *-m0* can be useful, as it
     tells FIGlet to kern characters without smushing them together.
     Otherwise, this option is rarely needed, as a *Text::FIGlet* font file
     specifies the best smushmode to use with the  font.  -m  is,
     therefore,  most  useful to font designers testing the various

     -2        Get mode from font file (default).

          Every  FIGlet  font  file specifies the best
          smushmode to use with the font.   This  will
          be  one  of  the  smushmodes (-1 through 63)
          described in the following paragraphs.

     -1        No smushing or kerning.

          Characters are simply concatenated together.

     -0        Fixed width.

          This will pad each character in the font such that they are all
          a consistent width. The padding is done such that the character
          is centered in it's "cell", and any odd padding is the trailing edge.

     0        Kern only.

          Characters  are  pushed  together until they touch.

   `figify'

*-A=>*text
     The text to transmogrify.

-L *-R* -X
     These  options  control whether FIGlet prints left-to-right or
     right-to-left. -L selects left-to-right printing. *-R* selects
     right-to-left printing.  -X (default) makes FIGlet use whichever is
     specified in the font file.

-c -l -r -x
     These  options  handle  the justification of *Text::FIGlet* output.
     -c centers the  output  horizontally.   -l makes  the  output
     flush-left.  -r makes it flush- right.  -x (default) sets the
     justification according to whether left-to-right or right-to-left text
     is selected.  Left-to-right  text  will  be  flush- left, while
     right-to-left text will be flush-right.  (Left-to-rigt versus
     right-to-left  text  is  controlled by -L, *-R* and -X.)

*-w=>**outputwidth*
     The output width, output text is wrapped to this value by breaking the
     input on whitspace where possible. There are two special width values

          -1 the text is not wrapped.
           1 the text is wrapped after very character.

     NOTE: This currently broken, it wraps to width but breaks on the
     nearest input character, not necessarily whitespace.

     Defaults to 80

EXAMPLES
========

   `perl -MText::FIGlet -e 'print Text::FIGlet->new()->figify(-A=>"Hello
World")''

ENVIRONMENT
===========

   *Text::FIGlet* will make use of these environment variables if present

FIGFONT
     The default font to load.  It should reside in the directory
     specified by FIGLIB.

FIGLIB
     The default location of fonts.

FILES
=====

   FIGlet home page

     http://st-www.cs.uiuc.edu/users/chai/figlet.html
     http://mov.to/figlet/

   FIGlet font files, these can be found at

     http://www.internexus.net/pub/figlet/
     ftp://wuarchive.wustl.edu/graphics/graphics/misc/figlet/
     ftp://ftp.plig.org/pub/figlet/

SEE ALSO
========

   `figlet' in this node

CAVEATS
=======

$/ is used to
          split incoming text into seperate lines.
          item create the output string
          item parse the font file

   Consequently, make sure it is set appropriately i.e.;  Don't mess with
it, *perl* sets it correctly for you.

AUTHOR
======

   Jerrad Pierce <jpierce@cpan.org>|<webmaster@pthbb.rg>

a class implementing a fill-in template
***************************************

NAME
====

   Text::FillIn.pm - a class implementing a fill-in template

SYNOPSIS
========

     use Text::FillIn;

     # Set the functions to do the filling-in:
     Text::FillIn->hook('$', sub { return ${$_[0]} });  # Hard reference
     Text::FillIn->hook('&', "main::run_function");     # Symbolic reference
     sub run_function { return &{$_[0]} }

     $template = new Text::FillIn('some text with [[$vars]] and [[&routines]]');
     $filled_in = $template->interpret();  # Returns filled-in template
     print $filled_in;
     $template->interpret_and_print();  # Prints template to currently
                                        # selected filehandle

     # Or
     $template = new Text::FillIn();
     $template->set_text('the text is [[ $[[$var1]][[$var2]] ]]');
     $TVars{'var1'} = 'two_';
     $TVars{'var2'} = 'parter';
     $TVars{'two_parter'} = 'interpreted';
     $template->interpret_and_print();  # Prints "the text is interpreted"

     # Or
     $template = new Text::FillIn();
     $template->get_file('/etc/template_dir/my_template');  # Fetches a file

     # Or
     $template = new Text::FillIn();
     $template->path('.', '/etc/template_dir');  # Where to find templates
     $template->get_file('my_template'); # Gets ./my_template or
                                         # /etc/template_dir/my_template

DESCRIPTION
===========

   This module provides a class for doing fill-in templates.  These
templates may be used as web pages with dynamic content, e-mail messages
with fill-in fields, or whatever other uses you might think of.
*Text::FillIn* provides handy methods for fetching files from the disk,
printing a template while interpreting it (also called streaming), and
nested fill-in sections (i.e. expressions like [[ $th[[$thing2]]ing1 ]]
are legal).

   Note that the version number here is 0.04 - that means that the
interface may change a bit.  In fact, it's already changed some with
respect to 0.02 (see the CHANGES file).  In particular, the $LEFT_DELIM,
$RIGHT_DELIM, %HOOK, and @TEMPLATE_PATH variables are gone, replaced by a
default/instance variable system.

   I might also change the default hooks or something.  Please read the
CHANGES file before upgrading to find out whether I've changed anything
you use.

   In this documentation, I generally use "template" to mean "an object of
class Text::FillIn".

Defining the structure of templates
-----------------------------------

   * delimiters

     *Text::FillIn* has some special variables that it uses to do its
     work.  You can set those variables and customize the way templates
     get filled in.

     The delimiters that set fill-in sections of your form apart from the
     rest of the form are generally *[[* and *]]*, but they don't have to
     be, you can set them to whatever you want.  So you could do this:

          Text::FillIn->Ldelim('{');
          Text::FillIn->Rdelim('}');
          $template->set_text('this is a {$variable} and a {&function}.');

     Whatever you set the delimiter to, you can put backslashes before
     them in your templates, to force them to be interpreted as literals:

          $template->set_text('some [[$[[$var2]][[$var]]]] and \[[ text \]]');
          $template->interpret_and_print();
          # Prints "some stuff and [[ text ]]"

     You cannot currently have several different kinds of delimiters in a
     single template.

   * interpretation hooks

     In order to interpret templates, `Text::FillIn' needs to know how to
     treat different kinds of [[tags]] it finds.  The way it accomplishes
     this is through "hook functions."  These are various functions that
     `Text::FillIn' will run when confronted with various kinds of fill-in
     fields.  There are two hooks provided by default:

          Text::FillIn->hook('$') is \&find_value,
          Text::FillIn->hook('&') is \&run_function.

     So if you leave these hooks the way they are, when *Text::FillIn* sees
     some text like "some [[$vars]] and some [[&funk]]", it will run
     `&Text::FillIn::find_value' to find the value of [[$vars]], and it
     will run `&Text::FillIn::run_function' to find the value of
     [[&funk]].  This is based on the first non-whitespace character after
     the delimiter, which is required to be a non-word character (no
     letters, numbers, or underscores).  You can define hooks for any
     non-word character you want:

          $template = new Text::FillIn("some [[!mushrooms]] were in my shoes!");
          $template->hook('!', "main::scream_it");  # or \&scream_it
          sub scream_it {
             my $text = shift;
             return uc($text); # Uppercase-it
          }
          $new_text = $template->interpret();
          # Returns "some MUSHROOMS were in my shoes!"

     Every hook function will be passed all the text between the
     delimiters, without any surrounding whitespace or the leading
     identifier (the & or $, or whatever).  Hooks can be given as either
     hard references or symbolic references, but if they are symbolic,
     they need to use the complete package name and everything.

     Beginning in version 0.04, you may use some object's methods as hook
     functions.  For example, if you have a template $template and another
     object `$myObj', you can instruct $template to call
     `$myObj->find_value()' and `$myObj->run_function()' to fill in
     templates.  See the `$template->object()' method below.

   * the default hook functions

     The hook functions installed with the shipping version of this module
     are `&Text::FillIn::find_value' and `&Text::FillIn::run_function'.
     They are extremely simple.  I suggest you take a look at them to see
     how they work.  What follows here is a description of how these
     functions will fill in your templates.

     The `&find_value' function looks for an entry in a hash called
     %main::TVars.  So put an entry in this hash if you want it to be
     available to templates:

          my $template = new Text::FillIn( 'hey, [[$you]]!' );
          $::TVars{'you'} = 'Sam';
          $template->interpret_and_print();  # Prints "hey, Sam!"

     The `&run_function' function looks for a function in the `TExport'
     package and runs it.  The reason it doesn't look in the main package
     is that you probably don't want to make all the functions in your
     program available to the templates (not that putting all your
     program's functions in the main package is always the greatest
     programming style).  Here are a couple of ways to make functions
     available:

          sub TExport::add_numbers {
             my $result;
             foreach (@_) {
                $result += $_;
             }
             return $result;
          }

          #  or, if you like:

          package TExport;
          sub add_numbers {
             my $result;
             foreach (@_) {
                $result += $_;
             }
             return $result;
          }

     The `&run_function' function will split the argument string at
     commas, and pass the resultant list to your function:

          my $template = new Text::FillIn(
             'Pi is about [[&add_numbers(3,.1,.04,.001,.0006)]]'
          );
          $template->interpret_and_print;

     In the original version of `Text::FillIn', I didn't provide any hook
     functions.  I expected people to write their own, partly because I
     didn't want to stifle creativity or anything.  I now include hook
     functions because the ones I give will probably work okay for most
     people, and providing them means it's easier to use the module right
     out of "the box."  But I hope you won't be afraid to write your own
     hooks - if mine don't work well for you, by all means go ahead and
     replace them with your own.  If you think you've written some really
     killer hooks, let me know.  I may include cool ones with future
     distributions.

   * template directories

     You can tell `Text::FillIn' where to look for templates:

          Text::FillIn->path('.', '/etc/template_dir');
          $template->get_file('my_template'); # Gets ./my_template or /etc/template_dir/my_template

METHODS
=======

   * new Text::FillIn($text)

     This is the constructor, which means it returns a new object of type
     *Text::FillIn*.  If you feed it some text, it will set the template's
     text to be what you give it:

          $template = new Text::FillIn("some [[$vars]] and some [[&funk]]");

   * $template->get_file( $filename );

     This will look for a template called $filename (in the directories
     given in *$template->path()*) and slurp it in.  If $filename starts
     with / , then *Text::FillIn* will treat $filename as an absolute
     path, and not search through the directories for it:

          $template->get_file( "my_template" );
          $template->get_file( "/weird/place/with/template" );

     The default path is ('.').

   * $template->interpret()

     Returns the interpreted contents of the template:

          $interpreted_text = $template->interpret();

     This, along with interpret_and_print, are the main point of this
     whole module.

   * $template->interpret_and_print()

     Interprets the [[ fill-in parts ]]  of a template and prints the
     template, streaming its output as much as possible.  This means that
     if it encounters an expression like "[[ stuff [[ more stuff]] ]]", it
     will fill in [[ more stuff ]], then use the filled-in value to
     resolve the value of [[ stuff something ]], and then print it out.

     If it encounters an expression like "stuff1 [[thing1]] stuff2
     [[thing2]]", it will print stuff1, then the value of [[thing1]], then
     stuff2, then the value of [[thing2]].  This is as streamed as
     possible if you want nested brackets to resolve correctly.

   The following methods all get and/or set certain attributes of the
template.  They can all be called as instance methods, a la
`$template->Ldelim()', or as static methods, a la
`Text::FillIn->Ldelim()'.  Using an instance method only changes the given
template, it does not affect the properties of any other template.  Using
a static method will change the default behavior of all templates created
in the future.

   I think I need to reserve the right to change what happens when you
create a template $t, then change the default behavior of all templates,
then call $t->interpret() - should it use the new defaults or the old
defaults?  Currently it uses the old defaults, but that might change.

   * $template->Ldelim($new_delimiter)

   * $template->Rdelim($new_delimiter)

     Get or set the left or right delimiter.  When called with no
     arguments, simply returns the delimiter.  When called with an
     argument, sets the delimiter.

   * $template->text($new_text)

     Get or set the contents of the template.

   * $template->path($dir1, $dir2, ...)

     Get or set the list of directories to search for templates in.  The
     path is used in the get_file() method.

   * $template->hook($character, $hook_function)

     Get or set the functions for filling in the sections of the template
     between delimiters.  The first argument is the non-word character the
     hook is installed under.  The second argument, if present, is the
     function to install as a hook.  It may either be a hard reference to
     a function, a string containing the fully package-qualified name of a
     function, or if you're using objects to fill in your template, a
     method name.  See also the subsection on interpretation hooks in the
     DESCRIPTION section.

   * $template->object($obj)

     As of version 0.04, you may use method calls on an arbitrary object as
     template hooks.  This can be very powerful.  Your code might look
     like this:

          $t   = new Text::FillIn("some [[$animal]]s");
          $obj = new MyClass(animal=>'chicken');  # Create some object
          $t->object($obj);  # Tell $t to use methods of $obj as hooks
          $t->hook('$', 'lookup_var');  # Set the method name for '$'
          $t->interpret_and_print();  # Calls $obj->lookup_var()

     The object methods will be passed the same arguments as regular
     (static) hook functions.

   * $template->property( $name, $value );

     This method lets you get and set arbitrary properties of the
     template, like this:

          $template->property('color', 'blue');  # Set the color
          # ... some code...
          $color = $template->property('color'); # Get the color

     The *Text::FillIn* class doesn't actually pay any attention
     whatsoever to the properties - it's purely for your own convenience,
     so that small changes in functionality can be achieved without having
     to subclass *Text::FillIn*.

COMMON MISTAKES
===============

   If you want to use nested fill-ins on your template, make sure things
get printed in the order you think they'll be printed.  If you have
something like this: `[[$var_number_[[&get_number]]]]', and your
&get_number *prints* a number, you won't get the results you probably
want.  *Text::FillIn* will print your number, then try to interpret
`[[$var_number_]]', which probably won't work.

   The solution is to make &get_number return its number rather than print
it.  Then *Text::FillIn* will turn `[[$var_number_[[&get_number]]]]' into
`[[$var_number_5]]', and then print the value of `$var_number_5'.  That's
probably what you wanted.

TO DO
=====

   The deprecated methods get_text(), set_text(), get_property(), and
set_property() will be removed in version 0.06 and greater.  Use text()
and property() instead.

   By slick use of local() variables, it would be possible to have
Text::FillIn keep track of when it's doing nested tags and when it's not,
allowing the user to nest tags using arbitrary depth and not have to worry
about the above "common mistake."  This would let hook functions be
oblivious to whether they're supposed to print their results or return
them, since Text::FillIn would keep track of it all.  This will take some
doing on my part, but it's not insurmountable.  It would probably involve
evaluating the tags from the outside in, rather than the inside out.

BUGS
====

   The interpreting engine can be fooled by certain backslashing sequences
like `\\[[$var]]', which looks to it like the `[[' is backslashed.  I
think I know how to fix this, but I need to think about it a little.

AUTHOR
======

   Ken Williams (ken@forum.swarthmore.edu)

   Copyright (c) 1998 Swarthmore College. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

base class for objects that can read and write text lines
*********************************************************

NAME
====

   Text::Filter - base class for objects that can read and write text lines

SYNOPSIS
========

   A plethora of tools exist that operate as filters: they get data from a
source, operate on this data, and write possibly modified data to a
destination. In the Unix world, these tools can be chained using a
technique called pipelining, where the output of one filter is connected
to the input of another filter. Some non-Unix worlds are reported to have
similar provisions.

   To create Perl modules for filter functionality seems trivial at first.
Just open the input file, read and process it, and write output to a
destination file. But for really reusable modules this approach is too
simple. A reusable module should not read and write files itself, but rely
on the calling program to provide input as well as to handle the output.

   `Text::Filter' is a base class for modules that have in common that
they process text lines by reading from some source (usually a file),
manipulating the contents and writing something back to some destination
(usually some other file).

   This module can be used on itself, but it is most powerfull when used
to derive modules from it. See section EXAMPLES for an extensive example.

DESCRIPTION
===========

   The main purpose of the `Text::Filter' class is to abstract out the
details out how input and output must be done. Although in most cases
input will come from a file, and output will be written to a file,
advanced modules require more detailed control over the input and output.
For example, the module could be called from another module, in this case
the callee could be allowed to process only a part of the input. Or, a
program could have prepared data in an array and wants to call the module
to process this data as if it were read from a file.  Also, the input
stream provides a pushback functionality to make peeking at the input easy.

   `Text::Filter' can be used on its own as a convenient input/output
handler. For example:

     use Text::Filter;
     my $filter = new Text::Filter (input = *STDIN, output = *STDOUT);
     my $line;
     while (defined ($line = $filter->readline)) {
         $filter->writeline ($line);
     }

   Its real power shows when such a program is turned into a module for
optimal reuse.

   When creating a module that is to process lines of text, it can be
derived from `Text::Filter', for example:

     package MyFilter;

     BEGIN {
     	use vars qw(@ISA);
     	@ISA = qw(Text::Filter);
     }

   The constructor method must then call the new() method of the
`Text::Filter' class to set up the base class. This is conveniently done
by calling SUPER::new(). A hash containing attributes must be passed to
this method, some of these attributes will be used by the base class setup.

     sub new {
     	my $proto = shift;
     	my $class = ref($proto) || $proto;
     	# ... fetch non-attribute arguments from @_ ...
     	# Create the instance, using the attribute arguments.
     	my $self = $class->SUPER::new (@_);

   Finally, the newly created object must be re-blessed into the desired
class, and returned:

     # Rebless into the desired class.
     	bless ($self, $class);
         }

   When creating new instances for this class, attributes input and output
can be used to specify how input and output is to be handled. Several
possible values can be supplied for these attributes.

   For input:

   * A scalar, containing a file name.  The named file will be opened,
     input lines will be read using <>.

   * A file handle (glob).  Lines will be read using <>.

   * An instance of class IO::File.  Lines will be read using <>.

   * A reference to an array.  Input lines will be shift()ed from the
     array.

   * A reference to an anonymous subroutine.  This routine will be called
     to get the next line of data.

   For output:

   * A scalar, containing a file name.  The named file will be created
     automatically, output lines will be written using print().

   * A file handle (glob).  Lines will be written using print().

   * An instance of class IO::File.  Lines will be written using print().

   * A reference to an array.  Output lines will be push()ed into the
     array.  The array will be initialised to `()' if necessary.

   * A reference to a scalar.  Output lines will be appended to the scalar.
     The scalar will be initialised to "" if necessary.

   * A reference to an anonymous subroutine.  This routine will be called
     to append a line of text to the destination.

   Additional attributes can be used to specify actions to be performed
after the data is fetched, or prior to being written. For example, to
strip line endings upon input, and add them upon output.

CONSTRUCTOR
===========

   The constructor is called new() and takes a hash with attributes as its
parameter.

   The following attributes are recognized and used by the constructor,
all others are ignored.

   The constructor will return a blessed hash containing all the original
attributes, plus some new attributes. The names of the new attributes all
start with `_filter_', the new attributes should not be touched.

input
     This designates the input source. The value must be a scalar
     (containing a file name), a file handle (either a glob or an instance
     of class IO::File), an array reference, or a reference to a
     subroutine, as described above.

     If a subroutine is specified, it must return the next line to be
     processed, and undef at end.

input_postread
     This attribute can be used to select an action to be performed after
     the data has been read.  Its prime purpose is to handle line endings
     (e.g. remove a trailing newline).

     The value can be 'none' or 0 (no action), 'chomp' or 1 (standard
     chomp() operation), an array reference, or a reference to a
     subroutine. Default value is 0 (no chomping).

     If the value is a reference to a subroutine, this will be called with
     the text line that was just read as its only argument, and it must
     return the new contents of the text line..

output
     This designates the output. The value must be a scalar (containing a
     file name), a file handle (either a glob or an instance of class
     IO::File), or a reference to a subroutine, as described above.

     Note: when a file name is passed, a '>' will be prepended if
     necessary.

output_prewrite
     This attribute can be used to select an action to be performed just
     before the data is added to the output.  Its prime purpose is to
     handle line endings (e.g. add a trailing newline).  The value can be
     'none' or 0 (no action) , 'newline' or 1 (append the value of $/ to
     the line), or a reference to a subroutine. Default value is 0 (no
     action).

     If the value is 'newline' or 1, and the value of $/ is "" (paragraph
     mode), two newlines will be added.

     If the value is a reference to a subroutine, this will be called with
     the text line as its only argument, and it must return the new
     contents of the line to be output.

INSTANCE METHODS
================

$filter->readline
     If there is anything in the pushback buffer, this is returned and the
     pushback buffer is marked empty.

     Otherwise, returns the next line from the input stream, or undef if
     there is no more input.

$filter->pushback ($line)
     Pushes a line of text back to the input stream.  Returns the line.

$filter->peek
     Peeks at the input.  Short for pushback(readline()).

$filter->writeline ($line)
     Adds `$line' to the output stream.

$filter->set_input ($input [ , $postread ])
     Sets the input method to `$input'.  If the optional argument
     `$postread' is defined, sets the input line postprocessing strategy
     as well.

$filter->set_output ($output, [ $prewrite ])
     Sets the output method to `$output'.  If the optional argument
     `$prewrite' is defined, sets the output line preprocessing strategy
     as well.

EXAMPLE
=======

   This is an example of how to use the `Text::Filter' class.

   It implements a module that provides a single instance method: grep(),
that performs some kind of grep(1)-style function (how surprising!).

   A class method grepper() is also provided for easy access to do 'the
right thing' in the most common case.

     package Grepper;

     use strict;
     use Text::Filter;

     # Setup.
     BEGIN {
     	use vars qw(@ISA);
     	@ISA = ();

     # This class exports static method, so we need Exporter:
     use Exporter;
     use vars qw(@EXPORT);
     @EXPORT = qw(grepper);
     push (@ISA, qw(Exporter));

     # This class derives from Text::Filter.
     push (@ISA, qw(Text::Filter));
         }

     # Constructor. Major part of the job is done by the superclass.
     sub new {
     	my $proto = shift;
     	my $class = ref($proto) || $proto;

     # Create a new instance by calling the superclass constructor.
     my $self = $class->SUPER::new(@_);
     # The superclass constructor will take care of handling
     # the input and output attributes, and setup everything for
     # handling the IO.

     # Bless the object into the desired class.
     bless ($self, $class);

     # And return it.
     $self;
         }

     # Instance method, just an example. No magic.
     sub grep {
     	my $self = shift;
     	my $pat = shift;
     	my $line;
     	while ( defined ($line = $self->readline) ) {
     	    $self->writeline ($line) if $line =~ $pat;
     	}
     }

     # Class method, for convenience.
     # Usage: grepper (<input file>, <output file>, <pattern>);
     sub grepper {
     	my ($input, $output, $pat) = @_;

     # Create a Grepper object.
     my $grepper = new Grepper (input => $input, output => $output);

     # Call its grep method.
     $grepper->grep ($pat);
         }

AUTHOR AND CREDITS
==================

   Johan Vromans (jvromans@squirrel.nl) wrote this module.

COPYRIGHT AND DISCLAIMER
========================

   This program is Copyright 1998,1999 by Squirrel Consultancy. All rights
reserved.

   This program is free software; you can redistribute it and/or modify it
under the terms of either: a) the GNU General Public License as published
by the Free Software Foundation; either version 1, or (at your option) any
later version, or b) the "Artistic License" which comes with Perl.

   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 either the GNU General Public
License or the Artistic License for more details.

object for chaining Text::Filter objects and running them sequentially, feeding the output of each filter to the input of the  next one.
****************************************************************************************************************************************

NAME
====

   Text::Filter::Chain - object for chaining Text::Filter objects and
running them sequentially, feeding the output of each filter to the input
of the next one.

SYNOPSIS
========

     use Text::Filter::Chain;

     # let's assume this is a filter which converts text to all lowercase
     $lc = new LowerCaser(input => 'foo.txt'); # reads from file foo.txt

     # and assume the following filter greps for a specified pattern
     $grep = new Grepper(pattern => '\bfoo\b',
                         output  => 'foo.out'); # writes to file foo.out

     # then these commands will read from foo.txt, convert the text to all
     # lowercase, filter out all lines with the word 'foo' and write to foo.out
     $chain = new Text::Filter::Chain(filters => [$lc,$grep]);
     $chain->run(); # this invokes the run() method on $lc and $grep

DESCRIPTION
===========

new()
     Returns a new empty `Text::Filter::Chain' object. Optionally, an
     ordered array of filters can be specified by passing a filters
     argument to new(). All filters are checked using is_valid_filter().

add_filter($filter)
     Adds the filter object $filter to the end of the array of filters.
     The filter is checked using is_valid_filter().

is_valid_filter($filter)
     Checks whether $filter is a valid filter for inclusion in a
     `Text::Filter::Chain'. The following requirements need to be met:

          a set_input() method must be available for setting the filter
          input;

          a set_output() method must be available for setting the filter
          output;

          a run() method must be available which runs the filter on its
          entire input.

     Note that $filter does not need to be a `Text::Filter' or derived
     object.  However, deriving at least the final filter in the chain
     from `Text::Filter' adds the benefit of automagical output buffer
     creation (see run()).

set_input()
     Sets the arguments which will be passed to the set_input() method of
     the first filter in the chain in run().

set_output()
     Sets the arguments which will be passed to the set_output() method of
     the final filter in the chain in run().

run()
     Runs all filters in the chain. This means that the run() method will
     be invoked on each filter object, and that the data will be buffered
     in between the filter: the output of the first filter is written to
     an array, which is used as the input of the 2nd filter, and so on.

     If set_input() was invoked on the chain, these arguments will be
     passed to the set_input() method of the first filter in the chain.
     If this is not the case, the input of the first filter must have been
     defined in some other way, or run() will fail during the processing
     of the first filter.

     If set_output() was invoked on the chain, these arguments will be
     passed to the set_output() method of the final filter in the chain.
     If this is not the case, the output of the final filter must have been
     defined in some other way, or run() will fail during the processing
     of the final filter.

     However, a fallback is provided for filters derived from the
     `Text::Filter' class. If no output is specified for the final filter,
     and no chain output is given, the chain output will default to an
     empty array before processing all filters.  This array is accessible
     as the 1st element in the ref to array kept in the output field of
     the chain.

SEE ALSO
========

   More info on text filters is found in Text/Filter.

AUTHOR
======

   Wim Verhaegen <wim.verhaegen@ieee.org>

COPYRIGHT
=========

   Copyright (c) 2000 Wim Verhaegen. All rights reserved.  This program is
free software; you can redistribute and/or modify it under the same terms
as Perl itself.

Parse and create fixed length field records
*******************************************

NAME
====

   Text::FixedLength - Parse and create fixed length field records

SYNOPSIS
========

     use Text::FixedLength;

     # -- get fixed length records from delimited text
     my @fL = qw(4L 4L 4L 4L); # -- left justified (which is default)
     my @fR = qw(4R 4R 4R 4R); # -- right justified (not default)
     my $str= join "\t", qw(1 2 3 4);
     my @a1 = delim2fixed([ $str ],"\t", \@fL);
     my @a2 = delim2fixed([ $str ],"\t", \@fR);
     # -- $a1[0] would now hold: '1   2   3   4   '
     # -- $a2[0] would now hold: '   1   2   3   4'

     # -- get delimited text from fixed length
     my @a1 = fixed2delim([ '2233344441' ], [qw(2 3 4 1)], ':');
     # -- $a1[0] would now hold: 22:333:4444:1

DESCRIPTION
===========

   Text::FixedLength was made to be able to manipulate fixed length field
records. You can manipulate arrays of data, or files of data.  This module
allows you to change between delimited and fixed length records.

   E.g. DELIM (with ':' as the delim) aaa:bbb:ccccc:dddddd      FIXED
'dion    almaer   mn55446'            where the format is left justified:
8 9 2 5 (SEE FORMATS)

FORMATS
=======

     You need to be familiar with the format array references used
     to create, and parse fixed length fields.
     The array reference holds the length of the field, and optionally
     holds either 'L' for left justified, or 'R' for right justified.
     By default fields are left justified (but you can change this
     default via the setJustify(L || R) functino)

     For example if you had the following fixed length record:

     1234567890123456789012345 <- place holder
     dion    almaer    mn55446

     The format (if all left justified) would be:
     $format = [ 8, 10, 2, 5 ];

FUNCTIONS
=========

   o *delim2fixed*($filename | $dataAREF, $delim,
$formatAREF,[$outfilename])

     delim2fixed returns fixed length field records from delimited records

     ARGUMENTS:
     1: Filename or an array reference holding delimited strings
     2: Delimiter for the data in arg 1
     3: Format array reference of the fixed lengths (see FORMATS)
     4: [OPTIONAL] Filename to write the fixed length data too

     RETURNS: Depending on wantarray it will return either an array of
              fixed length records, an array reference, or nothing
     e.g. @array = delim2fixed('file',':',[ qw(2 2 4 10) ]);
          $scalar = delim2fixed([ 'foo:bar:whee' ],':',[ qw(5 5 5) ]);
          delim2fixed('file',"\t",[ qw(6 10 4 1) ], 'outputfile');

   o *fixed2delim*($filename | $dataAREF, $formatAREF, $delim,
[$outfilename])

     fixed2delim returns delimited records from fixed length records

     ARGUMENTS:
     1. Filename or an array reference holding fixed length records
     2. Format array reference for the data in arg 1
     3. Delimiter for the output data
     4: [OPTIONAL] Filename to write the delimited data too

     RETURNS: Depending on wantarray it will return either an array of
              delimited records, an array reference, or nothing
     e.g. @array = fixed2delim('file',[ qw(2 2 4 10) ],':');
          $scalar = fixed2delim([ 'foo   bar whee' ],':',[ qw(6 4 4) ]);
          fixed2delim('file',[ qw(6 10 4 1) ],"\t",'outputfile');

     NOTE: The resulting strings are cleaned of whitespace at the
           beginning and the end. So '  foo  ' becomes 'foo'
           You do not need to worry about the justification of the
           text as the whitespace is cleaned

   o *setJustify*($justchar) [either 'L' or 'R'] [default: L]

     setJustify sets the default justification (originally set to left).

     ARGUMENTS: either L for left justified, or R for right justified

   o *setCrop*($bool) [either 1 or 0] [default: 1]

     setCrop sets whether records should be cropped to the size of the format
     or not.

     For example if you have a string 'whee' that is meant to be fit into
     a fixed format of 2 then if setCrop is true the record will be changed
     to 'wh' to constrain it

various niceties for Text::FixedLength lovers.
**********************************************

NAME
====

   Text::FixedLength::Extra - various niceties for Text::FixedLength
lovers.

SYNOPSIS
========

     use Text::FixedLength::Extra; #automatically uses Text::FixedLength

     my %format        =   (record_type => '3L', total_orders => '5R');
     my @field_order   = qw(record_type total_orders);
     my %data          =   (record_type => 'F',  total_orders => 300);

     # Bonus One: Simplified API to Text::FixedLength !
     $x = fixedlength(\%format, \%data, \@field_order);

     # Bonus Two: Zero filling and processing of integers and floating points !
     my %format        =   (record_type => '3R', total_orders => '10R*F3');
     my @field_order   = qw(record_type total_orders);
     my %data          =   (record_type => 'F',  total_orders => 300.52894);

     $x = fixedlength(\%format, \%data, \@field_order);

DESCRIPTION
===========

   Right now, Text::FixedLength::Extra does two things for those who like
using Text::FixedLength - simpler API and extended number processing.

Simplified API to Text::FixedLength
-----------------------------------

   A function, fixedlength() has been created which should make it easier
to create fixed-width reports. Here is a sample of setting up data for use
with fixedlength:

     # the fields we will format and their formatting instructions
     my %format =
       (
        record_type => '3',
        upc => '13L',
        lcc_label => '5R',
        lcc_catalog => '7R',
        lcc_config => '1',
        artist_name => '30L',
        item_title => '30L',
        quoted_price => '6R',
        quantity => '4R',
        customer_title => '30L',
        customer_reference => '20L'
       );

     # how to order the fields in %format
     my @format =  qw(record_type   upc     lcc_label     lcc_catalog
     lcc_config     artist_name     item_title     quoted_price     quantity
     customer_title     customer_reference    );

     my %data = ( record_type => '23423' ... customer_reference => 'adfja;kdf');

     my $formatted_line = fixedlength(\%format, %data, \@format);

Number processing
-----------------

   The standard format instruction with Text::FixedLength is

     WIDTH JUSTIFICATION?

   E.g. 6L creates a left-justified field taking up 6 spaces, filling any
non-used spaces with a spaces.

   This module re-implements the Text::FixedLength::getFixed function to
handle additional optional syntax for formatting numbers. The new format
instruction is:

     WIDTH JUSTIFICATION? (ZERO_FILL? D)?
       or
     WIDTH JUSTIFICATION? (ZERO_FILL? F PLACES_AFTER_DECIMAL)?

   If you dont understand the above let me give you a nice set of examples:

     10R*F3 means uses 10 spaces, zero fill if necessary and allow 3 places after the decimal point.

     10R*D  means uses 10 spaces, zero fill if necessary.

     10RF3  means uses 10 spaces, space fill (not zero-fill, note there was no * in the specification) if necessary and allow 3 places after the decimal point.

EXPORT
------

   fixedlength()

OVERWRITTEN
-----------

   Text::FixedLength::getFixed()

AUTHOR
======

   T. M. Brannon, <TBONE@CPAN.ORG>

SEE ALSO
========

   perl(1). Parse::FixedLength

ASCII Flowchart maker
*********************

NAME
====

   Text::Flowchart - ASCII Flowchart maker

AUTHOR
======

   Jim Thomason, jim3@psynet.net

SYNOPSIS
========

     +-------+      +-------------+
     | BEGIN >---+  |             |
     +-------+   +--> Do you need |
                    | to make a   N------+
           +--------Y flowchart?  |      |
           |        |             |      |
           |        +-------------+      |
           |                             |
           |         +------------+      |
           |         |            |      |
     +-----V-------+ | So use it. |      |
     |             | |            |      |
     | Then my     | +--^---V-----+      |
     | module may  |    |   |            |
     | help.       |    |   |            |
     |             >----+   |            |
     +-------------+        |            |
                            |      +-----V-------+
                            |      |             |
                            |      | Then go do  |
                            +------> something   |
                                   | else.       |
                                   |             |
                                   +-------------+

DESCRIPTION
===========

   Text::Flowchart does what the synopsis implies, it makes ASCII
flowcharts.  It also (hopefully) makes it easy to make ASCII flowcharts.

REQUIRES
========

   Carp

OBJECT METHODS
==============

CREATION
--------

   New flowcharts are created with the new constructor.

   $object = Text::Flowchart->new();

   You can also initialize values at creation time, such as:

     $object = Text::Flowchart->new(
     			"width"	=>	120,
     			"debug"	=>	1
     		);

ACCESSORS
---------

   There aren't any.  Well, there aren't any that you really should use.

   Why's that, you ask?  Because that's how the module is written.  Once
an object is added into a flowchart, its appearance becomes set in stone.
And I mean totally set in stone, you cannot remove a box from a flowchart,
it sticks around until the flowchart is destroyed.  Even if you poked
around in the internals of the module and discovered that ->string is an
accessor in the box class, for instance, it wouldn't do you any good since
objects are immediately rendered upon their creation.  Even if you
re-render the object after fiddling with it, it's not going to work since
the objects are inserted into the flowchart's internal grid once they're
rendered.

   So basically, declare everything you need to declare about an object
when you create it, and make sure that that's the information you're going
to use when you print it out.  It's not *that* hard.  :)

Methods
-------

   There are several methods you are allowed to invoke upon your flowchart
object.

new (?width? ?height? ?pad? ?debug?)
     This is the object constructor that actually creates your flowchart
     object.  All parameters are optional and are passed in a hash.

    width
          Optional. Specifies the width of your flowchart object, or uses
          the module default (72).

          The width of a flowchart must be specified, it cannot grow to
          accomodate objects placed within it.  If you try to place an
          object beyond the edge of the flowchart, you'll die with an
          error.

    height
          Optional. Specifies the height of your flowchart object, or uses
          the module default (0).

          The default height of 0 means that your flowchart will grow in
          height as much as necessary to accomodate the height of whatever
          you insert into your flowchart.  You can also specify a specific
          height so that your flowchart will be no taller than 17 rows,
          for example.  If you try to place an object beyond the bottom of
          the flowchart, you'll die with an error.

    pad
          Optional. pad allows you to specify a padding character.  The
          padding character is what is used to fill in the space between
          boxes and lines.  The default padding character is a space
          (\040), but you can set it to anything else you'd like.  This is
          most useful when debugging, IMHO.  Very useful in combination
          with debug (see below).  Set to " " by default.

    debug
          Optional. debug will print out the x & y coordinates of the
          flowchart.  This should greatly help you place your boxes where
          you want them to be.  Off by default, set to 1 to enable.

    directed
          Optional. directed specifies that your flowchart is direction
          dependent.  This will add on arrows to all of your lines.
          Flowcharts are non-directed by default.  Set this to 1 to use a
          directed flowchart.

     For example:

          $flowchart = Text::Flowchart::new->();	#boring flowchart, no options

          $flowchart = Text::Flowchart::new->(	#flowchart specifying new width, a % as the padding character, and using the debugging option
          	"width" => 100,
          	"pad" 	=> "%",
          	"debug"	=> 1
          );

          $flowchart = Text::Flowchart::new(		#using periods as the padding character
          	"pad"	=> "."
          );

box (string x_coord y_coord ?x_pad? ?y_pad? ?width? ?height?)
     You use the box method to add a new box into your flowchart object.
     All parameters are passed in a hash.

     The text within a box is wrapped at word boundaries if possible, or
     at the appropriate width if not possible so that all of your text
     fits inside your box.

    string
          Required. string is the message that you'll see within the box.
          Want your box to say "Hi there!"?  "string" => "Hi there!";
          Easy as pie.

    x_coord
          Required. The x coordinate of the upper left corner of the box.
          Use the debug option to help you find your coordinates.

    y_coord
          Required. The y coordinate of the upper left corner of the box.
          Use the debug option to help you find your coordinates.

    x_pad
          Optional. x_pad allows you to specify the amount of horizontal
          white space between the edges of the box and the text within.
          If this option is not specified, it'll use the default of a
          single space.

    y_pad
          Optional. y_pad allows you to specify the amount of vertical
          white space between the edges of the box and the text within.
          If this option is not specified, it'll use the default of a
          single line of white space.

    width
          Optional. width allows you to specify the width of the box.  The
          narrowest possible box has a width of 3.  You must take into
          account your x_pad value, as well as the edges of the box when
          you specify a width.  If no width is specified, it will use the
          default of 15.

          If you specify a width of 0 (zero), then your box will grow
          horizontally to accomodate all of your text, or until it reaches
          the width of the flowchart, whichever is lesser.  Be careful!
          This will put all of your box message onto the same line.  You
          almost never want your width to be 0.

    height
          Optional. height allows you to specify the height of the box.
          The shortest possible box has a height of 3.  You must take into
          account your y_pad value, as well as the edges of the box when
          you specify a height.  If no height is specified, it will use
          the default of 0 (zero).

          If you specify a height of 0 (zero), then your box will grow
          vertically to accomodate all of your text, or until it reaches
          the height of the flowchart, whichever is lesser.  You most
          likely want a box width of some fixed value, and a box height of
          zero so it will grow to accomodate your message.

          If you specify a non-zero box height, then your string will be
          truncated once the box reaches the height that you specified.
          It will still be created, you just won't have all of your text
          in it.

          For example:

               $example_box = $flowchart->box(								#creates a box at (15,0)
               	"string" => "Do you need to make a flowchart?",
               	"x_coord" => 15,
               	"y_coord" => 0
               );

               Output:

                             +-------------+
                             |             |
                             | Do you need |
                             | to make a   |
                             | flowchart?  |
                             |             |
                             +-------------+

               $example_box2 = $flowchart->box(								#creates a box at (0,0), with new x_pad and y_pad values
               	"string"  => "Do you need to make a flowchart?",
               	"x_coord" => 0,
               	"y_coord" => 0,
               	"x_pad"	  => 0,
               	"y_pad"	  => 3
               );

               Output:

               +-------------+
               |             |
               |             |
               |             |
               |Do you need  |
               |to make a    |
               |flowchart?   |
               |             |
               |             |
               |             |
               +-------------+

               $example_box3 = $flowchart->box(								#creates a box at (0,0), with new x_pad and y_pad values
               	"string"  => "Do you need to make a flowchart?",
               	"x_coord" => 0,
               	"y_coord" => 0,
               	"x_pad"	  => 2,
               	"y_pad"	  => 0
               );

               Output:

               +-------------+
               |  Do you     |
               |  need to    |
               |  make a     |
               |  flowchart  |
               |  ?          |
               +-------------+

relate ([from, from side, ?on side?], [to, to side, ?on side?], ?reason?)
     the relate method connects boxes to each other.  Once two boxes are
     related, a line is automatically drawn between then, listing a reason
     if given, and arrows if it's a directed flowchart.  The relate method
     spares you the trouble of having to re-position your lines if you
     move your boxes around.  You may still have to do some fiddling (such
     as changing the sides that are connected), but it's much less trouble
     than re-arranging the boxes and the lines.

    (from or to)
          Required. This is the box that you're relating from or to, it's
          the first item in an anonymous array.

    (from or to) side
          Required. This is the side of the box that you're relating from
          or to.  This must be either "top", "bottom", "right", or "left".
          It's the second item in an anonymous array.

    ?on side?
          Optional. This optional item specifies where on the box side
          you'd like to draw the line from.  If zero, it will take the
          first available slot starting from the left (if drawing from the
          top or bottom) or from the top (it drawing from the right or
          left).  If -1, it will take the first available slot starting
          from the other side (right for top and bottom or bottom for
          right or left).  If any other number, it will draw the line at
          that position, along the side, again counting from the left or
          the top.

    reason
          Optional. reason is a name and value pair that specifies why you
          would take that route.  The value must be one character long,
          you'll die with an error if it isn't.  reasons only make sense
          in a directed flowchart, they don't appear in non-directed ones.
          Typical values are "Y" for yes and "N" for no.  If no reason is
          specified, the default direction character will be used.

          For example:

          $flowchart = Text::Flowchart->new( 	"width" => 50,
          "directed" => 1);

               $example_box = $flowchart->box(								#creates a box at (0,0)
               	"string" => "Do you need to make a flowchart?",
               	"x_coord" => 0,
               	"y_coord" => 2,
               );

                $example_box2 = $flowchart->box(								#creates a box at (15,0)
               	"string" => "Yes I do.",
               	"x_coord" => 19,
               	"y_coord" => 0,
               	"width"	  => 13
               );

                $example_box3 = $flowchart->box(								#creates a box at (15,0)
               	"string" => "No I don't.",
               	"x_coord" => 19,
               	"y_coord" => 7
               );

               $flowchart->relate(
               	[$example_box, "right"] => [$example_box2, "left"]
               );

                $flowchart->relate(
               	[$example_box, "right", -1] => [$example_box3, "left"]
               );

               $flowchart->draw();

               Output:

               +-----------+
                                +-->           |
                +-------------+ |  | Yes I do. |
                |             >-+  |           |
                | Do you need |    +-----------+
                | to make a   |
                | flowchart?  |
                |             >--+ +-------------+
                +-------------+  +->             |
               | No I don't. |
               |             |
               +-------------+

          $flowchart = Text::Flowchart->new( 	"width" => 50);	#A
          non-directed chart

               $example_box = $flowchart->box(	#creates a box at (0,0)
               	"string" => "Do you need to make a flowchart?",
               	"x_coord" => 0,
               	"y_coord" => 2,
               );

                $example_box2 = $flowchart->box(	#creates a box at (15,0)
               	"string" => "Yes I do.",
               	"x_coord" => 19,
               	"y_coord" => 0,
               	"width"	  => 13
               );

                $example_box3 = $flowchart->box(	#creates a box at (15,0)
               	"string" => "No I don't.",
               	"x_coord" => 19,
               	"y_coord" => 7
               );

               $flowchart->relate(
               	[$example_box, "right"] => [$example_box2, "left"]
               );

                $flowchart->relate(
               	[$example_box, "right", -1] => [$example_box3, "left"]
               );

               $flowchart->draw();

               Output:

               +-----------+
                                +--+           |
                +-------------+ |  | Yes I do. |
                |             +-+  |           |
                | Do you need |    +-----------+
                | to make a   |
                | flowchart?  |
                |             +--+ +-------------+
                +-------------+  +-+             |
               | No I don't. |
               |             |
               +-------------+

          $flowchart = Text::Flowchart->new( 	"width" => 50,
          "directed" => 1 );

               $example_box = $flowchart->box(	#creates a box at (0,0)
               	"string" => "Do you need to make a flowchart?",
               	"x_coord" => 0,
               	"y_coord" => 2,
               );

                $example_box2 = $flowchart->box(	#creates a box at (15,0)
               	"string" => "Yes I do.",
               	"x_coord" => 19,
               	"y_coord" => 0,
               	"width"	  => 13
               );

                $example_box3 = $flowchart->box(	#creates a box at (15,0)
               	"string" => "No I don't.",
               	"x_coord" => 19,
               	"y_coord" => 7
               );

               $flowchart->relate(
               	[$example_box, "right"] => [$example_box2, "left"],
               	"reason" => "Y"
               );

                $flowchart->relate(
               	[$example_box, "right", -1] => [$example_box3, "left"],
               	"reason" => "N"
               );

               $flowchart->draw();

               Output:

               +-----------+
                                +-->           |
                +-------------+ |  | Yes I do. |
                |             Y-+  |           |
                | Do you need |    +-----------+
                | to make a   |
                | flowchart?  |
                |             N--+ +-------------+
                +-------------+  +->             |
               | No I don't. |
               |             |
               +-------------+

    draw (?FILEHANDLE?)
               the draw method actuall outputs your flowchart.  You can optionally give it a glob to a filehandle to re-direct the output to that filehandle.

               For example:

               $flowchart->draw();	#draw your flowchart on STDOUT;

               $flowchart->draw(*FILE);	#send it to the FILE filehandle.

          Required. This is the box that you're relating from or to, it's
          the first item in an anonymous array.

HISTORY
=======

- 1.00 12/21/99
     First public release onto CPAN.

EXAMPLE
=======

   This code will print out the flowchart shown up in the SYNOPSIS.

   use Text::Flowchart;

   $flowchart = Text::Flowchart->new(  	"width" => 50,  	"directed" => 0);

   $begin = $flowchart->box(  	"string" => "BEGIN",
"x_coord" => 0,  	"y_coord" => 0,  	"width"   => 9,  	"y_pad"   => 0  );

   $start = $flowchart->box(  	"string" => "Do you need to make a
flowchart?",  	"x_coord" => 15,  	"y_coord" => 0  );

   $yes = $flowchart->box(  	"string" => "Then my module may help.",
	"x_coord" => 0,  	"y_coord" => 10  );

   $use = $flowchart->box(  	"string" => "So use it.",
"x_coord" => 16,  	"y_coord" => 8,  	"width"	  => 14  );

   $no = $flowchart->box(  	"string" => "Then go do something
else.",  	"x_coord" => 30,  	"y_coord" => 17  );

   $flowchart->relate(  	[$begin, "right"] => [$start, "left", 1]
);

   $flowchart->relate(  	[$start, "left", 3] => [$yes, "top", 5],
"reason" => "Y"  );

   $flowchart->relate(  	[$start, "right", 2] => [$no, "top", 5],
"reason" => "N"  );

   $flowchart->relate(  	[$yes, "right", 4] => [$use, "bottom", 2]
);

   $flowchart->relate(  	[$use, "bottom", 6] => [$no, "left", 2]  );

   $flowchart->draw();

FAQ
===

   *Why in the world did you write this thing?*

   There's a flowcharting-type program that a couple of people use at
work.  It is only available on PCs.  I got cranky about not being able to
use it, so I wrote my own.  Admittedly, mine isn't as powerful or as easy
to use as theirs is, but I'm quite pleased with it nonetheless.  Real
programmers don't use software tools.  Real programmers write software
tools.

   *Hey!  I created a box, and then I tried to change its string and it
didn't work!  What gives?*

   Boxes are rendered upon their creation.  You cannot change their
strings once their are created.  I may change this in a future release,
but for now just wait until you're U<sure> you know what you want in a box
before you create it, okay?  That way you won't have to change it later.

   *Hey!  I'm running a memory tracer, and even though I deleted a box,
the memory wasn't freed up.  Do you have a memory leak or what?*

   Nope.  Boxes are stored internally inside the flowchart object.  The
box variable that you get back from ->box is just a reference to the box
that lives inside the flowchart.  Since the flowchart still knows the box
exists (even if you don't), the memory is not freed up.  Naturally, it
will be freed once perl exits.  I may add in the ability to remove boxes
to a future release.

   *I want to draw lines from the left side of a box to the left side of
another box, but I get an error. Why?*

   Because you can't draw lines like that.  :)

   Basically, there are 10 types of lines that can be drawn (all of which
are done by the relate method, naturally). They look like:

     +---+  +--+        +--+  +  +        +  +-+  +-+  +        +
               |        |     |  |        |    |  |    |        |
               +--+  +--+     +  +--+  +--+    +  +    +--+  +--+
                                    |  |
                                    +  +

     Or horizontal, zig-zagging horizontal, vertical, zig-zagging vertical, and corners.  Connecting the same sides of boxes would require another type of line,
     (the "handle", FWIW), and Text::Flowchart can't draw those.  If I can think of a good way to implement them I will.  Incidentally, you can draw your own lines
     if you need to, using the ->line method.

     $flowchart->line(
     	"from"	=> [xfrom, yfrom],
     	"to"	=> [yfrom, yto],
     	"reason"=> "Y"
     );

   But you really should use relate and not connect the same sides of
boxes, it will make your life much simpler.

   *I made a flowchart, but all of the lines cross over each other and
make a mess.  Why?*

   Text::Flowchart has no collision detection.  If you try to place a box
where another box already was, it'll gladly be drawn over.  Whichever
boxes or lines are drawn last will take priority.  If things are being
over-written, then you need to change the coordinates of your boxes so
they stop over-writing each other, or change the box sides that are
related so they don't draw over boxes.

   *Squares and rectangles are boring.  Can I draw other shapes?*

   Not yet.  The module is actually numerous packages, heavily subclassing
each other.  Adding in additional shapes is quite easy, actually.  You'd
just need to define a subclass of the Text::Flowchart::Shape class and
define the necessary functions.  You'd have to declare a render method to
actually create the ASCII object, a relate method that knows how to draw
the lines between objects, a get_next_coord method to get the next
available coordinate on a given side, and make the necessary modifications
to your new constructor (calling ::Shape's init(), of course), and you're
done!

   It's actually much easier than it sounds, from a programming
standpoint.  Figuring out how to properly render and relate object, that's
tricky.  I will be adding more shapes into a future release.  If anyone
wants to add their own shapes, e-mail 'em to me and I may add them in in
the future.

   *So what is it with these version numbers anyway?*

   I'm going to try to be consistent in how I number the releases.

   The *hundredths* digit will indicate bug fixes, etc.

   The *tenths* digit will indicate new and/or better functionality, as
well as some minor new features.

   The ones digit will indicate a major new feature or re-write.

   Basically, if you have x.ab and x.ac comes out, you want to get it
guaranteed.  Same for x.ad, x.ae, etc.

   If you have x.ac and x.ba comes out, you'll probably want to get it.
Invariably there will be bug fixes from the last "hundredths" release, but
it'll also have additional features.  These will be the releases to be
sure to read up on to make sure that nothing drastic has changes.

   If you have x.ac and y.ac comes out, it will be the same as x.ac->x.ba
but on a much larger scale.

   *Anything else you want to tell me?*

   Sure, anything you need to know.  Just drop me a message.

MISCELLANEA
===========

   If there's something that you feel would be worthwhile to include,
please let me know and I'll consider adding it.

   How do you know what's a worthwhile addition?  Basically, if it would
make your life easier.  Am I definitely going to include it?  Nope.  No
way.  But I'll certainly consider it, all suggestions are appreciated.  I
may even be nice and fill you in on some of the ideas I have for a future
release, if you ask nicely.  :)

COPYRIGHT (again) and LICENSE
=============================

   Copyright (c) 1999 James A Thomason III (jim3@psynet.net). All rights
reserved.  This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.  *Except if you profit from
its distribution.  If this module or works based upon this module are
distributed in a way that makes you money, you must first contact me to
work out a licensing arrangement.  I'm just giving the thing away, but I'm
not going to allow people to make money off of it unless I get a cut.  :)
Amounts will be hammered out on an individual basis.  CPAN mirrors are
exempt from this stipulation.  If you're not sure if you're distributing
it in a way that makes you money, contact me with details and we'll make a
decision.*

CONTACT INFO
============

   So you don't have to scroll all the way back to the top, I'm Jim
Thomason (jim3@psynet.net) and feedback is appreciated.  Bug
reports/suggestions/questions/etc.  Hell, drop me a line to let me know
that you're using the module and that it's made your life easier.  :-)

Various subroutines to format text.
***********************************

NAME
====

   *Text::Format* - Various subroutines to format text.

SYNOPSIS
========

     use Text::Format;

     $text = Text::Format->new (
         {
             text           =>  [], # all
             columns        =>  72, # format, paragraphs, center
             leftMargin     =>   0, # format, paragraphs, center
             rightMargin    =>   0, # format, paragraphs, center
             firstIndent    =>   4, # format, paragraphs
             bodyIndent     =>   0, # format, paragraphs
             rightFill      =>   0, # format, paragraphs
             rightAlign     =>   0, # format, paragraphs
             justify        =>   0, # format, paragraphs
             extraSpace     =>   0, # format, paragraphs
             abbrevs        =>  {}, # format, paragraphs
             hangingIndent  =>   0, # format, paragraphs
             hangingText    =>  [], # format, paragraphs
             noBreak        =>   0, # format, paragraphs
             noBreakRegex   =>  {}, # format, paragraphs
             tabstop        =>   8, # expand, unexpand,  center
         }
     ); # these are the default values

     %abbr = (foo => 1, bar => 1);
     $text->abbrevs(\%abbr);
     $text->abbrevs();
     $text->abbrevs({foo => 1,bar => 1});
     $text->abbrevs(qw/foo bar/);
     $text->text(\@text);

     $text->columns(132);
     $text->tabstop(4);
     $text->extraSpace(1);
     $text->firstIndent(8);
     $text->bodyIndent(4);
     $text->config({tabstop => 4,firstIndent => 0});
     $text->rightFill(0);
     $text->rightAlign(0);

DESCRIPTION
===========

   The format routine will format under all circumstances even if the
width isn't enough to contain the longest words.  Text::Wrap will die
under these circumstances, although I am told this is fixed.  If columns
is set to a small number and words are longer than that and the leading
'whitespace' than there will be a single word on each line.  This will let
you make a simple word list which could be indented or right aligned.
There is a chance for croaking if you try to subvert the module.  If you
don't pass in text then the internal text is worked on, though not modfied.
*Text::Format* is meant for more powerful text formatting than Text::Wrap
allows.  I also have a module called *Text::NWrap* that is meant as a
direct replacement for Text::Wrap.  *Text::NWrap* requires *Text::Format*
since it uses *Text::Format->format* to do the actual wrapping but gives
you the interface of Text::Wrap.

   General setup should be explained with the below graph.

     columns
     <------------------------------------------------------------>
     <----------><------><---------------------------><----------->
      leftMargin  indent  text is formatted into here  rightMargin

   indent is firstIndent or bodyIndent depending on where we are in the
paragraph.

format @ARRAY || \@ARRAY || [<FILEHANDLE>] || NOTHING
     Allows to do some advanced formatting of text into a paragraph, with
     indent for first line and body set separately.  Can specify total
     width of text, right fill with spaces or right align or justify
     (align to both margins), right margin and left margin, non-breaking
     space, two spaces at end of sentence, hanging indents (tagged
     paragraphs).  Strips all leading and trailing whitespace before
     proceeding.  Text is first split into words and then reassembled.  If
     no text is passed in then the internal text in the object is
     formatted.

paragraphs @ARRAY || \@ARRAY || [<FILEHANDLE>] || NOTHING
     Considers each element of text as a paragraph and if the indents are
     the same for first line and the body then the paragraphs are
     separated by a single empty line otherwise they follow one under the
     other.  If hanging indent is set then a single empty line will
     separate each paragraph as well.  Calls format to do the actual
     formatting.  If no text is passed in then the internal text in the
     object is formatted, though not changed.

center @ARRAY || NOTHING
     Centers a list of strings in @ARRAY or internal text.  Empty lines
     appear as, you guessed it, empty lines.  Center strips all leading and
     trailing whitespace before proceeding.  Left margin and right margin
     can be set.  If no text is passed in then the internal text in the
     object is formatted.

expand @ARRAY || NOTHING
     Expand tabs in the list of text to tabstop number of spaces in @ARRAY
     or internal text.  Doesn't modify the internal text just passes back
     the modified text.  If no text is passed in then the internal text in
     the object is formatted.

unexpand @ARRAY || NOTHING
     Tabstop number of spaces are turned into tabs in @ARRAY or internal
     text.  Doesn't modify the internal text just passes back the modified
     text.  If no text is passed in then the internal text in the object is
     formatted.

new \%HASH || NOTHING
     Instantiates the object.  If you pass a reference to a hash, or an
     anonymous hash then it's used in setting attributes.

config \%HASH
     Allows the configuration of all object attributes at once.  Returns
     the object prior to configuration.  You can use it to make a clone of
     your object before you change attributes.

columns NUMBER || NOTHING
     Set width of text or retrieve width.  This is total width and includes
     indentation and the right and left margins.

tabstop NUMBER || NOTHING
     Set tabstop size or retrieve tabstop size, only used by expand,
     unexpand and center.

firstIndent NUMBER || NOTHING
     Set or get indent for the first line of paragraph.  This is the number
     of spaces to indent.

bodyIndent NUMBER || NOTHING
     Set or get indent for the body of paragraph.  This is the number of
     spaces to indent.

leftMargin NUMBER || NOTHING
     Set or get width of left margin.  This is the number of spaces used
     for the margin.

rightMargin NUMBER || NOTHING
     Set or get width of right margin.  This is the number of spaces used
     for the margin.

rightFill 0 || 1 || NOTHING
     Set right fill or retrieve its value.  The filling is done with
     spaces.  Keep in mind that if rightAlign is also set then both
     rightFill and rightAlign are ignored.

rightAlign 0 || 1 || NOTHING
     Set right align or retrieve its value.  Text is aligned with the right
     side of the margin.  Keep in mind that if rightFill is also set then
     both rightFill and rightAlign are ignored.

justify 0 || 1 || NOTHING
     Set justify or retrieve its value.  Text is aligned with both margins,
     adding extra spaces as necessary to align text with left and right
     margins.  Keep in mind that if either of rightAlign or rightFill are
     set then justify is ignored, even if both are set in which case they
     are all ignored.

text \@ARRAY || NOTHING
     Pass in a reference to your text, or an anonymous array of text that
     you want the routines to manipulate.  Returns the text held in the
     object.

hangingIndent 0 || 1 || NOTHING
     Use hanging indents in front of a paragraph, returns current value of
     attribute.  This is also called a tagged paragraph.

hangingText \@ARRAY || NOTHING
     The text that will be displayed in front of each paragraph, if you
     call format then only the first element is used, if you call
     paragraphs then paragraphs cycles through all of them.  If you have
     more paragraphs than elements in your array than the remainder of the
     paragraphs will not have a hanging indented text.  Pass a reference to
     your array.  This is also called a tagged paragraph.

noBreak 0 || 1 || NOTHING
     Set whether you want to use the non-breaking space feature.

noBreakRegex \%HASH || NOTHING
     Pass in a reference to your hash that would hold the regexes on which
     not to break.  Returns the hash.  eg.

          {'^Mrs?\.$' => '^\S+$','^\S+$' => '^(?:S|J)r\.$'}

     don't break names such as Mr. Jones, Mrs. Jones, Jones Jr.

     The breaking algorithm is simple.  If there should not be a break at
     the current end of sentence, then a backtrack is done till there are
     two words on which breaking is allowed.  If no two such words are
     found then the end of sentence is broken anyhow.  If there is a
     single word on current line then no backtrack is done and the word is
     stuck on the end.  This is so you can make a list of names for
     example.

extraSpace 0 || 1 || NOTHING
     Add extra space after end of sentence, normally format would add 1
     space after end of sentence, if this is set to 1 then 2 spaces are
     used.  Abbreviations are not followed by two spaces.  There are a few
     internal abbreviations and you can add your own to the object with
     abbrevs

abbrevs \%HASH || @ARRAY || NOTHING
     Add to the current abbreviations, takes a reference to your hash or an
     array of abbreviations, if called a second time the original reference
     is removed and replaced by the new one.  Returns the current INTERNAL
     abbreviations.

EXAMPLE
=======

     use Text::Format;

     $text = new Text::Format;
     $text->rightFill(1);
     $text->columns(65);
     $text->tabstop(4);
     print $text->format("a line to format to an indented regular
             paragraph using 65 character wide display");
     print $text->paragraphs("paragraph one","paragraph two");
     print $text->center("hello world","nifty line 2");
     print $text->expand("\t\thello world\n","hmm,\twell\n");
     print $text->unexpand("    hello world\n","    hmm");
     $text->config({columns => 132, tabstop => 4});

     $text = Text::Format->new();
     print $text->format(@text);
     print $text->paragraphs(@text);
     print $text->center(@text);
     print $text->format([<FILEHANDLE>]);
     print $text->format([$fh->getlines()]);
     print $text->paragraphs([<FILEHANDLE>]);
     print $text->expand(@text);
     print $text->unexpand(@text);

     $text = Text::Format->new
         ({tabstop => 4,bodyIndent => 4,text => \@text});
     print $text->format();
     print $text->paragraphs();
     print $text->center();
     print $text->expand();
     print $text->unexpand();

     print Text::Format->new({columns => 95})->format(@text);

BUGS
====

   Line length can exceed columns specified if columns is set to a small
number and long words plus leading whitespace exceed column length
specified.  Actually I see this as a feature since it can be used to make
up a nice word list.

AUTHOR
======

   Gabor Egressy *gabor@vmunix.com*

   Copyright (c) 1998 Gabor Egressy.  All rights reserved.  All wrongs
reversed.  This program is free software; you can redistribute and/or
modify it under the same terms as Perl itself.

ACKNOWLEDGMENTS
===============

   *Tom Phoenix* found bug with code for two spaces at end of sentence and
provided code fragment for a better solution, some preliminary suggestions
on design

   *Brad Appleton* suggesting and explanation of hanging indents,
suggestion for non-breaking whitespace, general suggestions with regard to
interface design

   *Byron Brummer* suggestion for better interface design and object
design, code for better implementation of getting abbreviations

   *H. Merijn Brand* suggestion for justify feature and original code for
doing the justification.  I changed the code to take into account the
extra space at end of sentence feature.

TODO
====

German grundform reduction
**************************

NAME
====

   Text::German - German grundform reduction

SYNOPSYS
========

   `use Text::German;'

   `$stem = Text::German::reduce($word)'

DESCRIPTION
===========

   This is a rather incomplete implementaion of work done by Gudrun
Putze-Meier `<gudrun.pm@t-online.de>'. I have to confess that I never read
her original paper. So all credit belongs to her, all bugs are mine. I
tried to get some insight from an implementation of two students of mine.
They remain anonymous because their work was the wost piece of code I ever
saw. My code behaves mostly as their implementation did except it is about
75 times faster.

AUTHOR
======

   Ulrich Pfeifer `<pfeifer@ls6.informatik.uni-dortmund.de>'

A text graphics rendering toolkit
*********************************

NAME
====

   Text::Graphics - A text graphics rendering toolkit

DESCRIPTION
===========

   This is a toolkit for rendering plain text via an API like that used
for graphics rendering in GUI toolkits.  This package might be used when
you want to do sophisticated rendering of plain text, e.g., for graphing,
creating of complex forms for email and fax, and so on.

SYNOPSIS
========

     use Text::Graphics;
     my $text = "A text graphics rendering toolkit.\n";
     my $page = Text::Graphics::Page->new( 20, 10);
     my $panel0 = Text::Graphics::BorderedPanel->new( 20, 10);
     my $panel1 =
      Text::Graphics::FilledBorderedTextPanel->new($text x 3, 25, 12);
     $panel0->setBackground("#");
     $panel1->setBackground(" ");
     $page->add($panel0);
     $page->add($panel1, 5, 2);
     $page->render();

     +-------------------+
     |###################|
     |####+--------------+
     |####|A text graphic|
     |####|rendering tool|
     |####|text graphics |
     |####|toolkit. A tex|
     |####|graphics rende|
     |####|toolkit.      |
     |####|              |
     +----+--------------+

User API
========

`Text::Graphics::Page'
----------------------

   Class to represent a page.

`new (width, height)'
     Construct a new page with the specified width and height.

`add (Panel, x_offset, y_offset)'
     Add a Panel at the specified offset.

`render ( [ scalar_reference ] )'
     Render the page.  If an argument is given, it is assumed to be a
     SCALAR REFERENCE, and rendering will be done to such reference.  e.g.,
     if you want to render to $buf, you might do

          $w->render(\ $buf);

     If no argument to render() is provided, then rendering is simply done
     to STDOUT using print.

`Text::Graphics::Panel'
-----------------------

   Class to represent a panel.

`new (width, height)'
     Construct a new panel with the specified width and height.

`add (Panel, x_offset, y_offset)'
     Add a Panel at the specified offset.  This child panel is contained
     within its parent and will not extend beyond the parents boundaries.

`setBackground ( background )'
     Set the background on the panel to the specified char.

`getSize ()'
     Get the size of a panel.  This method is a hook for layout managers.
     E.g., If you set up a wrapped text panel with height 0, then call
     getSize(), then it will return the same width but the new "desired"
     height.  (If you are interested in how to write a layout manager on
     top of this code, please contact me (SF) as I have done so but have
     not released it.)

`setSize (width, height)'
     Set the size of a panel.  This method is a hook for layout managers.

`getOffset ()'
     get the offset of a panel.  This method is a hook for layout managers.

`setOffset (x_offset, y_offset)'
     set the offset of a panel.  This method is a hook for layout managers.

Subclassing
===========

   Most of the work you might do with this module will be by subclassing
panel.  The idea is you make a new panel, like LinePanel, that has a
constructor setting character to draw and the start and end coordinates
for the line.  Then, in the LinePanels `_drawSelf(gc)' routine, it calls
on the gc to draw a line:

     package LinePanel;
     use vars qw (@ISA);
     @ISA = qw (Panel);

     sub new {
      my $this = {};
      bless $this, shift;
      $this->{char} = shift;
      $this->{startx} = shift;
      $this->{starty} = shift;
      $this->{endx} = shift;
      $this->{endy} = shift;
      return $this;
     }

     sub _drawSelf {
      my $this = shift;
      my $gc = shift;

     $gc->drawLine($this->{char},
                   $this->{startx}, $this->{starty},
     		$this->{endx}, $this->{endy});

     }

   There are some other subclasses included, particularly those for text
handling.

   Actually the `drawLine()' method for the GraphicsContext is not
included b/c I just do not need it, though I have a mostly working version
if anyone is interested (it is not complicated =).

   GraphicsContext does include the following methods, however:

`drawBorder(x_offset, y_offset, width, height)'
     Draw a border with the specified coordinates.

`fillRect(char, x_offset, y_offset, width, height)'
     Fill the specified rectangle with the specified character.  Note that
     filling with " " is a good way to get an "opaque" panel.

`drawString(string, x_offset, y_offset)'
     Draw the specified string at the specified offset.  If you want to
     control the width then you probably want to look at FilledTextPanel.

AUTHORS
=======

     Stephen Farrell <stephen@farrell.org>
     Jeremy Mayes

RFC 822/2068 header and `unheader' functions
********************************************

NAME
====

   Text::Header - RFC 822/2068 header and `unheader' functions

SYNOPSIS
========

     use Text::Header;     # header and unheader exported

     # Construct headers similar to CGI.pm and HTTP::Headers

     @HEADERS = header(content_type => 'text/html',
                       author => 'Nathan Wiger',
                       last_modified => $date,
                       accept => [qw(text/html text/plain)]);

     # The above produces the array:

     @HEADERS = ("Content-Type: text/html\n",
                 "Author: Nathan Wiger\n",
                 "Last-Modified: Wed Sep 27 13:31:06 PDT 2000\n",
                 "Accept: text/html, text/plain\n");

     # Can also construct SMTP headers to format mail

     @mail_headers = header(from => 'Nathan Wiger <nate@sun.com>',
                            to => 'perl5-porters@perl.org');

     print $MAIL @mail_headers, "\nKeep up the great work!\n";

     # The above would print this to the $MAIL handle:

     From: Nathan Wiger <nate@sun.com>
     To: perl5-porters@perl.org

     Keep up the great work!

DESCRIPTION
===========

   This module provides two new functions, header and `unheader', which
provide general-purpose RFC 822 header construction and parsing.  They do
not provide any intelligent defaults of HTTP-specific methods.  They are
simply aimed at providing an easy means to address the mechanics of header
parsing.

   The output style is designed to mimic `CGI.pm' and `HTTP::Headers', so
that users familiar with these interfaces will feel at home with these
functions. As shown above, the headers function automatically does the
following:

     1. uc's the first letter of each tag token and lc's the
        rest, also converting _'s to -'s automatically

     2. Adds a colon separating each tag and its value, and
        exactly one newline after each one

     3. Combines list elements into a comma-delimited
        string

   Note that a list is always joined into a comma-delimited string. To
insert multiple separate headers, simply call header with multiple args:

     push @out, header(accept => 'text/html',
                       accept => 'text/plain');

   This would create multiple "Accept:" lines.

   Note that unlike `CGI.pm', the header function provided here does not
provide any intelligent defaults. If called as:

     @out_headers = header;

   It will return an empty list. This allows header to be more general
pupose, so it can provide SMTP and other headers as well. You can also use
it as a generic text formatting tool, hence the reason it's under the
`Text::' hierarchy.

   The `unheader' function works in exactly the opposite direction from
header, pulling apart headers and returning a list. `unheader':

     1. lc's the entire tag name, converting -'s to _'s

     2. Separates each tag based on the colon delimiter,
        chomping newlines.

     3. Returns a list of tag/value pairs for easy assignment
        to a hash

   So, assuming the `@HEADERS' array shown up top:

     %myheaders = unheader(@HEADERS);

   The hash `%myheaders' would have the following values:

     %myheaders = (
         content_type => 'text/html',
         author => 'Nathan Wiger',
         last_modified => 'Wed Sep 27 13:31:06 PDT 2000',
         accept => 'text/html, text/plain'
     );

   Note that all keys are converted to lowercase, and their values have
their newlines stripped. However, note that comma-separated fields are not
split up on input. This cannot be done reliably because some fields, such
as the HTTP `Date:' header, can contain commas even though they are not
lists. Inferring this type of structure would require knowledge of
content, and these functions are specifically designed to be
content-independent.

   The `unheader' function will respect line wrapping, as seen in SMTP
headers. It will simply join the lines and return the value, so that:

     %mail = unheader("To: Nathan Wiger <nate@sun.com>,
                               perl5-porters@perl.org");

   Would return:

     $mail{to} = "Nathan Wiger <nate@sun.com>, perl5-porters@perl.org"

   Notice that multiple spaces between the comma separator have been
condensed to a single space. Since the header and `unheader' functions are
direct inverses, this call:

     @out = header unheader @in;

   Will result in `@out' being exactly equivalent to `@in'.

REFERENCES
==========

   This is designed as both a Perl 5 module and also a Perl 6 prototype.
Please see the Perl 6 proposal at http://dev.perl.org/rfc/333.html

   This module is designed to be fully compliant with the internet
standards RFC 822 (SMTP Headers) and RFC 2068 (HTTP Headers).

AUTHOR
======

   Copyright (c) 2000 Nathan Wiger <nate@sun.com>. All Rights Reserved.

   This module is free software; you may copy this under the terms of the
GNU General Public License, or the Artistic License, copies of which
should have accompanied your Perl kit.

Perl extension for blah blah blah
*********************************

NAME
====

   Text::Hyphenate - Perl extension for blah blah blah

SYNOPSIS
========

     use Text::Hyphenate qw(hyphenate);

     $hyphenated = hyphenate($width, $text);

     # OR:

     $hyphenater = Text::Hyphenate->new($width);
     $hyphenated = $hyphenater->hyphenate($text);

     =head1 DESCRIPTION

   Stub documentation for Text::Hyphenate was created by h2xs. It looks
like the author of the extension was negligent enough to leave the stub
unedited.

   Blah blah blah.

AUTHOR
======

   A. U. Thor, a.u.thor@a.galaxy.far.far.away

SEE ALSO
========

   perl(1).

Perl interface to iconv() codeset conversion function
*****************************************************

NAME
====

   Text::Iconv - Perl interface to iconv() codeset conversion function

SYNOPSIS
========

     use Text::Iconv;
     $converter = Text::Iconv->new("fromcode", "tocode");
     $converted = $converter->convert("Text to convert");

DESCRIPTION
===========

   The *Text::Iconv* module provides a Perl interface to the iconv()
function as defined by the Single UNIX Specification.  The convert()
method converts the encoding of characters in the input string from the
*fromcode* codeset to the *tocode* codeset, and returns the result.

   Settings of *fromcode* and *tocode* and their permitted combinations
are implementation-dependent.  Valid values are specified in the system
documentation

ERRORS
======

   If the conversion can't be initialized an exception is raised (using
croak()).

   As an experimental feature, this version of *Text:Iconv* provides a new
class attribute *raise_error* and a corresponding class method for setting
and getting its value.  The handling of errors during conversion now
depends on the setting of this attribute.  If *raise_error* is set to a
true value, an exception is raised; otherwise, the convert() method only
returns undef.  By default *raise_error* is false.  Warnings are no longer
emitted.  Example usage:

     Text::Iconv->raise_error(1);     # Conversion errors raise exceptions
     Text::Iconv->raise_error(0);     # Conversion errors return undef
     $a = Text::Iconv->raise_error(); # Get current setting

   Consult `iconv(3)' in this node for details on errors that might occur.

NOTES
=====

   The supported codesets, their names, the supported conversions, and the
quality of the conversions are all system-dependent.

AUTHOR
======

   Michael Piotrowski <mxp@dynalabs.de>

SEE ALSO
========

   iconv(1), iconv(3)

a module encapsulating access to the Ispell program.
****************************************************

NAME
====

   Text::Ispell.pm - a module encapsulating access to the Ispell program.

SYNOPSIS
========

     # Brief:
     use Text::Ispell;
     Text::Ispell::spellcheck( $string );
     # or
     use Text::Ispell qw( spellcheck ); # import the function
     spellcheck( $string );

     # Useful:
     use Text::Ispell qw( :all );  # import all symbols
     for my $r ( spellcheck( "hello hacking perl shrdlu 42" ) ) {
       print "$r->{'type'}: $r->{'term'}\n";
     }

DESCRIPTION
===========

   Text::Ispell::spellcheck() takes one argument.  It must be a string,
and it should contain only printable characters.  One allowable exception
is a terminal newline, which will be chomped off anyway.  The line is fed
to a coprocess running ispell for analysis.  The line is parsed on
non-wordchars into a sequence of terms.  By default, the set of wordchars
is defined in ispell as letters, digits, and the apostrophe.  In other
words, the line is subjected the equivalent of

     split /[^a-zA-Z0-9']+/

   (ispell has a means to add characters to the default set, but currently
Text::Ispell does not provide access to that feature.)

   The result of ispell's analysis of each term is a categorization of the
term into one of six types: ok, root, miss, none, compound, and guess.
Some of these carry additional information.

   Text::Ispell::spellcheck returns a list of objects, each corresponding
to a term in the spellchecked string.  Each object is a hash (hash-ref)
with at least two entries: 'term' and 'type'.  The former contains the
term ispell is reporting on, and the latter is ispell's determination of
that term's type (see above).  For types 'ok' and 'none', that is all the
information there is.  For the type 'root', an additional hash entry is
present: 'root'.  Its value is the word which ispell identified in the
dictionary as being the likely root of the current term.  For the type
'miss', an additional hash entry is present: 'misses'.  Its value is a
string of words, comma-separated, which ispell identified as being
"near-misses" of the current term, when scanning the dictionary.

   A quickie example:

     use Text::Ispell qw( spellcheck );
     Text::Ispell::allow_compounds(1);
     for my $r ( spellcheck( "hello hacking perl salmoning fruithammer shrdlu 42" ) ) {
       if ( $r->{'type'} eq 'ok' ) {
         # as in the case of 'hello'
         print "'$r->{'term'}' was found in the dictionary.\n";
       }
       elsif ( $r->{'type'} eq 'root' ) {
         # as in the case of 'hacking'
         print "'$r->{'term'}' can be formed from root '$r->{'root'}'\n";
       }
       elsif ( $r->{'type'} eq 'miss' ) {
         # as in the case of 'perl'
         print "'$r->{'term'}' was not found in the dictionary;\n";
         print "Near misses: $r->{'misses'}\n";
       }
       elsif ( $r->{'type'} eq 'guess' ) {
         # as in the case of 'salmoning'
         print "'$r->{'term'}' was not found in the dictionary;\n";
         print "Root/affix Guesses: $r->{'guesses'}\n";
       }
       elsif ( $r->{'type'} eq 'compound' ) {
         # as in the case of 'fruithammer'
         print "'$r->{'term'}' is a valid compound word.\n";
       }
       elsif ( $r->{'type'} eq 'none' ) {
         # as in the case of 'shrdlu'
         print "No match for term '$r->{'term'}'\n";
       }
       # and numbers are skipped entirely, as in the case of 42.
     }

ERRORS
------

   `Text::Ispell::spellcheck()' starts the ispell coprocess if the
coprocess seems not to exist.  Ordinarily this is simply the first time
it's called.

   ispell is spawned via the `Open2::open2()' function, which throws an
exception (i.e. dies) if the spawn fails.  The caller should be prepared
to catch this exception - unless, of course, the default behavior of die
is acceptable.

Nota Bene
---------

   The full location of the ispell executable is stored in the variable
`$Text::Ispell::path'.  The default value is `/usr/local/bin/ispell'.  If
your ispell executable has some name other than this, then you must set
`$Text::Ispell::path' accordingly before you call
`Text::Ispell::spellcheck()' (or any other function in the module) for the
first time!

AUX FUNCTIONS
=============

add_word(word)
--------------

   Adds a word to the personal dictionary.  Be careful of capitalization.
If you want the word to be added "case-insensitively", you should call
`add_word_lc()'

add_word_lc(word)
-----------------

   Adds a word to the personal dictionary, in lower-case form.  This
allows ispell to match it in a case-insensitive manner.

accept_word(word)
-----------------

   Similar to adding a word to the dictionary, in that it causes ispell to
accept the word as valid, but it does not actually add it to the
dictionary.  Presumably the effects of this only last for the current
ispell session, which will mysteriously end if any of the
coprocess-restarting functions are called...

parse_according_to(formatter)
-----------------------------

   Causes ispell to parse subsequent input lines according to the
specified formatter.  As of ispell v. 3.1.20, only 'tex' and 'nroff' are
supported.

set_params_by_language(language)
--------------------------------

   Causes ispell to set its internal operational parameters according to
the given language.  Legal arguments to this function, and its effects,
are currently unknown by the author of Text::Ispell.

save_dictionary()
-----------------

   Causes ispell to save the current state of the dictionary to its disk
file.  Presumably ispell would ordinarily only do this upon exit.

terse_mode(bool:terse)
----------------------

   In terse mode, ispell will not produce reports for "correct" words.
This means that the calling program will not receive results of the types
'ok', 'root', and 'compound'.

   ispell starts up in NON-terse mode, i.e. reports are produced for all
terms, not just "incorrect" ones.

FUNCTIONS THAT RESTART ISPELL
=============================

   The following functions cause the current ispell coprocess, if any, to
terminate.  This means that all the changes to the state of ispell made by
the above functions will be lost, and their respective values reset to
their defaults.  The only function above whose effect is persistent is
save_dictionary().

   Perhaps in the future we will figure out a good way to make this state
information carry over from one instantiation of the coprocess to the next.

allow_compounds(bool)
---------------------

   When this value is set to True, compound words are accepted as legal -
as long as both words are found in the dictionary; more than two words are
always illegal.  When this value is set to False, run-together words are
considered spelling errors.

   The default value of this setting is dictionary-dependent, so the
caller should set it explicitly if it really matters.

make_wild_guesses(bool)
-----------------------

   This setting controls when ispell makes "wild" guesses.

   If False, ispell only makes "sane" guesses, i.e.  possible root/affix
combinations that match the current dictionary; only if it can find none
will it make "wild" guesses, which don't match the dictionary, and might
in fact be illegal words.

   If True, wild guesses are always made, along with any "sane" guesses.
This feature can be useful if the dictionary has a limited word list, or a
word list with few suffixes.

   The default value of this setting is dictionary-dependent, so the
caller should set it explicitly if it really matters.

use_dictionary([dictionary])
----------------------------

   Specifies what dictionary to use instead of the default.  Dictionary
names are actually file names, and are searched for according to the
following rule: if the name does not contain a slash, it is looked for in
the directory containing the default dictionary, typically /usr/local/lib.
Otherwise, it is used as is: if it does not begin with a slash, it is
construed from the current directory.

   If no argument is given, the default dictionary will be used.

use_personal_dictionary([dictionary])
-------------------------------------

   Specifies what personal dictionary to use instead of the default.

   Dictionary names are actually file names, and are searched for
according to the following rule: if the name begins with a slash, it is
used as is (i.e. it is an absolute path name). Otherwise, it is construed
as relative to the user's home directory ($HOME).

   If no argument is given, the default personal dictionary will be used.

FUTURE ENHANCEMENTS
===================

   ispell options:

     -w chars
          Specify additional characters that can be part of a word.

DEPENDENCIES
============

   Text::Ispell uses the external program ispell, which is the
"International Ispell", available at

     http://fmg-www.cs.ucla.edu/geoff/ispell.html

   as well as various archives and mirrors, such as

     ftp://ftp.math.orst.edu/pub/ispell-3.1/

   This is a very popular program, and may already be installed on your
system.

   Text::Ispell also uses the standard perl modules FileHandle,
IPC::Open2, and Carp.

AUTHOR
======

   jdporter@min.net (John Porter)

   This module is free software; you may redistribute it and/or modify it
under the same terms as Perl itself.

simple line  editor
*******************

NAME
====

   Text::LineEditor - simple line  editor

SYNOPSIS
========

     use Text::LineEditor;

     $text = &line_editor();

DESCRIPTION
===========

   `Text::LineEditor' implements a -very- simple editor like Berkley mail
used to use.

FUNCTIONS
=========

line_editor ();
     Returns the text entered.  If the text has been abandoned with ~x it
     returns an empty string.

EDITING COMMANDS
================

   To append text, just type.  To end, type '.' by itself on a line.
Tilde commands for editing (by themselves on a line):    ~h     This help
message    ~e, ~v Edit message using visual editor    ~w <filename>
  Write current text to file <filename>    ~p     Print current text
using 'lpr'    ~.     End message as normal    ~x     Quit, abandon text

A macro pre-processor with embedded perl capability
***************************************************

NAME
====

   Text::MacroScript - A macro pre-processor with embedded perl capability

SYNOPSIS
========

     use Text::MacroScript ;

     # new() for macro processing

     my $Macro = Text::MacroScript->new ;
     while( <> ) {
         print $Macro->expand( $_ ) if $_ ;
     }

     # Canonical use (the filename improves error messages):
     my $Macro = Text::MacroScript->new ;
     while( <> ) {
         print $Macro->expand( $_, $ARGV ) if $_ ;
     }

     # new() for embedded macro processing

     my $Macro = Text::MacroScript->new( -embedded => 1 ) ;
     # Delimiters default to <: and :>
     # or
     my $Macro = Text::MacroScript->new( -opendelim => '[[', -closedelim => ']]' ) ;
     while( <> ) {
         print $Macro->expand_delimited( $_, $ARGV ) if $_ ;
     }

     # Create a macro object and create initial macros/scripts from the file(s)
     # given:
     my $Macro = Text::MacroScript->new(
                     -file => [ 'local.macro', '~/.macro/global.macro' ]
                     ) ;

     # Create a macro object and create initial macros/scripts from the
     # definition(s) given:
     my $Macro = Text::MacroScript->new(
                     -macro => [
                             [ 'MAX_INT' => '32767' ],
                         ],
                     -script => [
                         [ 'DHM2S' =>
                             [
                                 my $s = (#0*24*60*60)+(#1*60*60)+(#2*60) ;
                                 "#0 days, #1 hrs, #2 mins = $s secs"
                             ],
                         ],
                     -variable => [ '*MARKER*' => 0 ],
                     ) ;

     # We may of course use any combination of the options.

     my $Macro = Text::MacroScript->new( -comment => 1 ) ; # Create the %%[] macro.

     # define()

     $Macro->define( -macro, $macroname, $macrobody ) ;

     $Macro->define( -script, $scriptname, $scriptbody ) ;

     $Macro->define( -variable, $variablename, $variablebody ) ;

     # undefine()

     $Macro->undefine( -macro, $macroname ) ;

     $Macro->undefine( -script, $scriptname ) ;

     $Macro->undefine( -variable, $variablename ) ;

     # undefine_all()

     $Macro->undefine( -macro ) ;

     $Macro->undefine( -script ) ;

     $Macro->undefine( -variable ) ;

     # list()

     @macros    = $Macro->list( -macro ) ;
     @macros    = $Macro->list( -macro, -namesonly ) ;

     @scripts   = $Macro->list( -script ) ;
     @scripts   = $Macro->list( -script, -namesonly ) ;

     @variables = $Macro->list( -variable ) ;
     @variables = $Macro->list( -variable, -namesonly ) ;

     # load_file() - always treats the contents as within delimiters if we are
     # doing embedded processing.

     $Macro->load_file( $filename ) ;

     # expand_file() - calls expand_embedded() if we are doing embedded
     # processing otherwise calls expand().

     $Macro->expand_file( $filename ) ;
     @expanded = $Macro->expand_file( $filename ) ;

     # expand()

     $expanded = $Macro->expand( $unexpanded ) ;
     $expanded = $Macro->expand( $unexpanded, $filename ) ;

     # expand_embedded()

     $expanded = $Macro->expand_embedded( $unexpanded ) ;
     $expanded = $Macro->expand_embedded( $unexpanded, $filename ) ;

   This bundle also includes the macro and `macrodir' scripts which allows
us to expand macros without having to use/understand
`Text::MacroScript.pm', although you will have to learn the handful of
macro commands available and which are documented here and in macro. macro
provides more documentation on the embedded approach.

   The `macroutil.pl' library supplied provides some functions which you
may choose to use in HTML work for example.

DESCRIPTION
===========

   Define macros, scripts and variables in macro files or directly in text
files.

   Commands may appear in separate macro files which are loaded in either
via the text files they process (e.g. via the `%LOAD' command), or may be
embedded directly in text files. Almost every command that can appear in a
file has an equivalent object method so that programmers may achieve the
same things in code as can be achieved by macro commands in texts; there
are also additional methods which have no command equivalents.

   Most the examples given here use the macro approach. However this
module now directly supports an embedded approach and this is now
documented. Although you may specify your own delimiters where shown in
examples we use the default delimiters of `>:' and `:<' throughout.

Public methods
--------------

     new         class   object
     get         class   object
     define              object
     undefine            object
     list                object
     undefine_all        object
     load_file           object
     expand_file         object
     expand              object
     expand_embedded     object

Summary of Commands
-------------------

   These commands may appear in separate `macro' files, and/or in the body
of files. Wherever a macroname or scriptname is encountered it will be
replaced by the body of the macro or the result of the evaluation of the
script using any parameters that are given.

   Note that if we are using an embedded approach commands, macro names and
script names should appear between delimiters. (Except when we `%LOAD'
since this assumes the whole file is `embedded'.)

     %DEFINE macroname [macro body]

     %DEFINE macroname
     multi-line
     macro body
     #0, #1 are the first and second parameters if any used
     %END_DEFINE

     %UNDEFINE macroname

     %UNDEFINE_ALL   # Undefine all macros

     %DEFINE_SCRIPT scriptname [script body]

     %DEFINE_SCRIPT scriptname
     multi-line
     script body
     arbitrary perl
     optional parameters are in @Param, although #0, etc may be used
     any variables are in %Var, although #varname may be used
     %END_DEFINE

     %UNDEFINE scriptname

     %UNDEFINE_ALL_SCRIPT

     %DEFINE_VARIABLE variablename [variable value]

     %UNDEFINE variablename

     %UNDEFINE_ALL_VARIABLE

     %LOAD[path/filename]    # Instantiate macros/scripts/variables in this
                             # file, but discard the text

     %INCLUDE[path/filename] # Instantiate macros/scripts/variables in this
                             # file and output the resultant text

     %REQUIRE[path/filename] # Make Perl require a file e.g. of functions,
                             # modules, etc. which can then be accessed within
                             # scripts.

     %CASE [condition]       # Provides #ifdef-type functionality
     %END_CASE

   Thus, in the body of a file we may have, for example:

     %DEFINE &B [Billericky Rickety Builders]
     Some arbitrary text.
     We are writing to complain to the &B about the shoddy work they did.

   If we are taking the embedded approach the example above might become:

     <:%DEFINE BB [Billericky Rickety Builders]:>
     Some arbitrary text.
     We are writing to complain to the <:BB:> about the shoddy work they did.

   When using an embedded approach we don't have to make the macro or
script name unique within the text, (although each must be distinct from
each other), since the delimiters are used to signify them. However since
expansion applies recursively it is still wise to make names distinctive.

Macro systems vs embedded systems
---------------------------------

   Macro systems read all the text, substituting anything which matches a
macro name with the macro's body (or script name with the result of the
execution of the script). This makes macro systems slower (they have to
check for macro/script names everywhere, not just in a delimited section)
and more risky (if we choose a macro/script name that normally occurs in
the text we'll end up with a mess) than embedded systems. On the other
hand because they work on the whole text not just delimited bits, macro
systems can perform processing that embedded systems can't. Macro systems
are used extensively, for example the CPP, C pre-processor, with its
#DEFINE's, etc.

   Essentially, embedded systems print all text until they hit an opening
delimiter. They then execute any code up until the closing delimiter. The
text that results replaces everything between and including the
delimeters. They then carry on printing text until they hit an opening
delimeter and so on until they've finished processing all the text. This
module now provides both approaches.

Creating macro objects with new()
---------------------------------

   For macro processing:

     my $Macro = Text::MacroScript->new ;

   For embedded macro processing:

     my $Macro = Text::MacroScript->new( -embedded => 1 ) ;
     # Delimiters default to <: and :>

   Or specify your own delimiters:

   my $Macro = Text::MacroScript->new( -opendelim => '[[', -closedelim =>
']]' ) ;

   Or specify one delimiter to use for both (probably not wise):

     my $Macro = Text::MacroScript->new( -opendelim => '%%' ) ;
     # -closedelim defaults to -opendelim, e.g. %% in this case

   The full list of options that may be specified at object creation:

   `-comment' optional integer; 1 = create the `%%[]' comment macro;
default 0.

   `-file' optional array reference of strings; read macros and scripts
from the file(s) given - they are `%LOAD'ed so are treated as already
embedded if we are doing embedded processing. Default is a reference to an
empty array.

   `-macro' optional array reference of macros, in the form:

     my $Macro = Text::MacroScript->new(
                     -macro => [
                         ["name1"=>"body1"],
                         ["name2"=>"body2"],
                         ["name3"=>"body3"],
                     ],
                     ) ;

   Default is a reference to an empty array.

   `-script' optional array reference of scripts, in the form:

     my $Macro = Text::MacroScript->new(
                     -script => [
                         ["name1"=>"body1"],
                         ["name2"=>"body2"],
                         ["name3"=>"body3"],
                     ],
                     ) ;

   Default is a reference to an empty array.

   `-variable' optional array reference of variables, in the form:

     my $Macro = Text::MacroScript->new(
                     -variable => [
                         ["name1"=>"value1"],
                         ["name2"=>"value2"],
                         ["name3"=>"value3"],
                     ],
                     ) ;

   Default is a reference to an empty array.

   `-embedded' optional integer, 1 = use embedded processing; 0 = use macro
processing. Default is 0. If set to 1 then the delimiters become <: and :>
unless otherwise specified.

   `-opendelim' optional string, default is undef unless `-embedded' is 1
in which case default is <: if `-opendelim' is undefined or the empty
string.

   `-closedelim' optional string, default is undef unless `-embedded' is 1
in which case default is :> if `-closedelim' is undefined or the empty
string and `-opendelim' is <: or `-opendelim' if `-opendelim' is not <:.

Defining Macros with `%DEFINE' and define()
-------------------------------------------

   In files we would write:

     %DEFINE MAC [The Mackintosh Macro]

   The equivalent method call is:

     $Macro->define( -macro, 'MAC', 'The Mackintosh Macro' ) ;

   We can call our macro anything, excluding white-space characters and [,
although [ is not advised. So a name like `%*&!' is fine - indeed names
which could not normally appear in the text are recommended to avoid
having the wrong thing substituted. We should also avoid calling macros,
scripts or variables names beginning with #. All names are case-sensitive.

   Note that if we define a macro and then a script with the same name the
script will effectively replace the macro.

   We can have parameters (for macros and scripts), e.g.:

     %DEFINE *P [The forename is #0 and the surname is #1]

   Parameters used in the source text can contain square brackets since
macro will grab up to the last square bracket on the line. The only thing
we can't pass are `|'s since these are used to separate parameters.
White-space between the macro name and the [ is optional in definitions
but *not allowed* in the source text.

   Parameters are named #0, #1, etc. There is a limit of 100 parameters,
i.e.  #0..#99, and we must use all those we specify. In the example above
we must use *P[param1|param2], e.g. *P[Jim|Hendrix]; if we don't
`Text::MacroScript.pm' will croak. Note that macro names and their
parameters must all be on the same line (although this is relaxed if you
use paragraph mode).

   Because we use # to signify parameters if you require text that
consists of a # followed by digits then you should escape the #, e.g.

     %DEFINE *GRAY[<font color="\#121212">#0</font>]

   We can use as many more parameters than we need, for example add a
third to document: *P[Jim|Hendrix|Musician] will become `The forename is
Jim and the surname is Hendrix', just as in the previous example; the
third parameter, `Musician', will simply be thrown away.

   If we take an embedded approach we might write this example thus:

     <:%DEFINE P [The forename is #0 and the surname is #1]:>

   and in the text, <:P[Jim|Hendrix]:> will be transformed appropriately.

   If we define a macro, script or variable and later define the same name
the later definition will replace the earlier one. This is useful for
making local macro definitions over-ride global ones, simply by loading
the global ones first.

   Although macros can have plain textual names like this:

     %DEFINE MAX_INT [32767]

   It is generally wise to use a prefix and/or suffix to make sure we don't
expand something unintentionally, e.g.

     %DEFINE $MAX_INT [65535]

   *Macro expansion is no respector of quoted strings or anything else* -
*if the name matches the expansion will take place!*

   Multi-line definitions are permitted (here's an example I use with the
lout typesetting language):

     %DEFINE SCENE
     @Section
         @Title {#0}
     @Begin
     @PP
     @Include {#1}
     @End @Section
     %END_DEFINE

   This allows us to write the following in our lout files:

     SCENE[ The title of the scene | scene1.lt ]

   which is a lot shorter than the definition.

   The body of a macro may not contain a literal null. If you really need
one then use a script and represent the null as `chr(0)'.

   *Converting a macro to a script*

   This can be achieved very simply. For a one line macro simply enclose
the body between qq{ and }, e.g.

     %DEFINE $SURNAME [Baggins]

   becomes

     %DEFINE_SCRIPT $SURNAME [qq{Baggins}]

   For a multi-line macro use a here document, e.g.

     %DEFINE SCENE
     @Section
         @Title {#0}
     @Begin
     @PP
     @Include {#1}
     @End @Section
     %END_DEFINE

   becomes

     %DEFINE_SCRIPT SCENE
     <<__EOT__
     \@Section
         \@Title {#0}
     \@Begin
     \@PP
     \@Include {#1}
     \@End \@Section
     __EOT__
     %END_DEFINE

   Note that the @s had to be escaped because they have a special meaning
in perl.

Defining Scripts with `%DEFINE_SCRIPT' and define()
---------------------------------------------------

   Instead of straight textual substitution, we can have some perl executed
(after any parameters have been replaced in the perl text):

     %DEFINE_SCRIPT *ADD ["#0 + #1 = " . (#0 + #1)]

   or by using the equivalent method call:

     $Macro->define( -script, '*ADD', '"#0 + #1 = " . (#0 + #1)' ) ;

   These would be used as *ADD[5|11] in the text which would be output as:

     These would be used as 5 + 11 = 16 in the text...

   In script definitions we can use an alternative way of passing
parameters instead of or in addition to the #0 syntax.

   This is particularly useful if we want to take a variable number of
parameters since the #0 etc syntax does not provide for this. An array
called `@Param' is available to our perl code that has any parameters.
This allows things like the following to be achieved:

     %DEFINE_SCRIPT ^PEOPLE
     # We don't use the name hash number params but read straight from the
     # array:
     my $a = "friends and relatives are " ;
     $a .= join ", ", @Param ;
     $a ;
     %END_DEFINE

   The above would expand in the following text:

     Her ^PEOPLE[Anna|John|Zebadiah].

   to     Her friends and relatives are Anna, John, Zebadiah.

   In addition to having access to the parameters either using the #0
syntax or the `@Param' array, we can also access any variables that have
been defined using `%DEFINE_VARIABLE' (see later). These are accessible
either using #variablename similarly to the #0 parameter syntax, or via
the `%Var' hash.  Although we can change both `@Param' and `%Var' elements
in our script, the changes to `@Param' only apply within the script
whereas changes to `%Var' apply from that point on globally.

   Note that if you require a literal # followed by digits in a script
body then you must escape the # like this `\#'.

   Macro names can be any length and consist of any characters (including
non-printable which is probably only useful within code), except
white-space and [, although ] is not recommended and a leading # should be
avoided.

   Here's a simple date-stamp style:

     %DEFINE_SCRIPT *DATESTAMP
     {
         my( $d, $m, $y ) = (localtime( time ))[3..5] ;
         $m++ ;
         $m = "0$m" if $m < 10 ;
         $d = "0$d" if $d < 10 ;
         $y += 1900 ;
         "#0 on $y/$m/$d" ;
     }
     %END_DEFINE

   If we wanted to add the above in code we'd have to make sure the
$variables weren't interpolated:

     $Macro->define( -script, '*DATESTAMP', <<'__EOT__' ) ;
     {
         my( $d, $m, $y ) = (localtime( time ))[3..5] ;
         $m++ ;
         $m = "0$m" if $m < 10 ;
         $d = "0$d" if $d < 10 ;
         $y += 1900 ;
         "#0 on $y/$m/$d" ;
     }
     __EOT__

     Here's (a somewhat contrived example of) how the above would be used:

     <HTML>
     <HEAD><TITLE>Test Page</TITLE></HEAD>
     <BODY>
     *DATESTAMP[Last Updated]<P>
     This page is up-to-date and will remain valid until *DATESTAMP[midnight]
     </BODY>
     </HTML>

   Thus we could have a file, `test.html.m' containing:

     %DEFINE_SCRIPT *DATESTAMP
     {
         my( $d, $m, $y ) = (localtime( time ))[3..5] ;
         $m++ ;
         $m = "0$m" if $m < 10 ;
         $d = "0$d" if $d < 10 ;
         $y += 1900 ;
         "#0 on $y/$m/$d" ;
     }
     %END_DEFINE
     <HTML>
     <HEAD><TITLE>Test Page</TITLE></HEAD>
     <BODY>
     *DATESTAMP[Last Updated]<P>
     This page is up-to-date and will remain valid until *DATESTAMP[midnight]
     </BODY>
     </HTML>

   which when expanded, either in code using `$Macro->expand()', or using
the simple macro utility supplied with `Text::MacroScript.pm':

     [1]% macro test.html.m > test.html

   `test.html' will contain just this:

     <HTML>
     <HEAD><TITLE>Test Page</TITLE></HEAD>
     <BODY>
     Last Updated on 1999/08/21<P>
     This page is up-to-date and will remain valid until midnight on 1999/08/21
     </BODY>
     </HTML>

   Of course in practice we wouldn't want to define everything in-line
like this.  See `%LOAD' later for an alternative.

   This example written in embedded style might be written thus:

     <:
     %DEFINE_SCRIPT DATESTAMP
     {
         my( $d, $m, $y ) = (localtime( time ))[3..5] ;
         $m++ ;
         $m = "0$m" if $m < 10 ;
         $d = "0$d" if $d < 10 ;
         $y += 1900 ;
         "#0 on $y/$m/$d" ;
     }
     %END_DEFINE
     :>
     <HTML>
     <HEAD><TITLE>Test Page</TITLE></HEAD>
     <BODY>
     <!-- Note how the parameter must be within the delimiters. -->
     <:DATESTAMP[Last Updated]:><P>
     This page is up-to-date and will remain valid until <:DATESTAMP[midnight]:>
     </BODY>
     </HTML>

   For more (and better) HTML examples see the example file `html.macro'.

   The body of a script may not contain a literal null. If you really need
one then represent the null as `chr(0)'.

Defining Variables with `%DEFINE_VARIABLE' and define()
-------------------------------------------------------

   We can also define variables:

     %DEFINE_VARIABLE &*! [89.1232]

   or in code:

     $Macro->define( -variable, '&*!', 89.1232 ) ;

   Note that there is no multi-line version of `%DEFINE_VARIABLE'.

   All current variables are available inside `%DEFINE_SCRIPT' scripts in
the `%Var' hash:

     %DEFINE_SCRIPT *TEST1
     $a = '' ;
     while( my( $key, $val ) each( %Var ) ) {
         $a .= "$key = $val\n" ;
     }
     $a ;
     %END_DEFINE

   Here's another example:

   %DEFINE_VARIABLE XCOORD[256]     %DEFINE_VARIABLE YCOORD[112]         :
   The X coord is *SCALE[X|16] and the Y coord is *SCALE[Y|16]

   %DEFINE_SCRIPT *SCALE     my $coord = shift @Param ;     my $scale =
shift @Param ;     my $val   = $Var{$coord} ;     $val %= scale ; # Scale
it     $val ;     %END_DEFINE

   Variables may be modified within script `%DEFINE's, e.g.

     %DEFINE_VARIABLE VV[Foxtrot]
     # VV eq 'Foxtrot'
     # other text
     # Here we use the #variable synax:
     %DEFINE_SCRIPT VV[#VV='Alpha']
     # VV eq 'Alpha' - note that we *must* refer to the script (as we've done
     # on the line following) for it to execute.
     # other text
     # Here we use perl syntax:
     %DEFINE_SCRIPT VV[$Var{'VV'}='Tango']
     # VV eq 'Tango' - note that we *must* refer to the script (as we've done
     # on the line following) for it to execute.

   As we can see variables support the #variable syntax similarly to
parameters which support #0 etc and ara available in scripts via the
`@Param' array.  Note that changing parameters within a script only apply
within the script; whereas changing variables in the `%Var' hash in a
script changes them from that point on globally.

   Variables are also used with `%CASE' (covered later).

Loading and including files with `%LOAD' and `load_file()', and `%INCLUDE' and `expand_file()'
----------------------------------------------------------------------------------------------

   Although we can define macros directly in the files that require them
it is often more useful to define them separately and include them in all
those that need them.

   One way of achieving this is to load in the macros/scripts first and
then process the file(s). In code this would be achieved like this:

     $Macro->load_file( $macro_file ) ; # Loads definitions only, ignores any
                                        # other text. If working in embedded
                                        # mode the file is treated as if
                                        # wrapped in delimiters.
     $Macro->expand_file( $file ) ;     # Expands definitions (and instantiates
                                        # any definitions that appear in the
                                        # file); output is to the current
                                        # output filehandle.
     my @expanded = $Macro->expand_file( $file ) ; # Output to array.

   From the command line it would be achieved thus:

     [2]% macro -f ~/.macro/html.macros test.html.m > test.html

   One disadvantage of this approach, especially if we have lots of macro
files, is that we can easily forget which macro files are required by
which text files. One solution to this is to go back to `%DEFINE'ing in
the text files themselves, but this would lose reusability. The answer to
both these problems is to use the `%LOAD' command which loads the
definitions from the named file at the point it appears in the text file:

     %LOAD[~/.macro/html.macros]
     <HTML>
     <HEAD><TITLE>Test Page Again</TITLE></HEAD>
     <BODY>
     *DATESTAMP[Last Updated]<P>
     This page will remain valid until *DATESTAMP[midnight]
     </BODY>
     </HTML>

   The above text has the same output but we don't have to remember or
explicitly load the macros. In code we can simply do this:

     my @expanded = $Macro->expand_file( $file ) ;

   or from the command line:

     [3]% macro test.html.m > test.html

     At the beginning of our lout typesetting files we might put this line:

     %LOAD[local.macros]

   The first line of the `local.macros' file is:

     %LOAD[~/.macro/lout.macros]

   So this loads both global macros then local ones (which if they have
the same name will of course over-ride).

   This saves repeating the `%DEFINE' definitions in all the files and
makes maintenance easier.

   `%LOAD' loads perl scripts and macros, but ignores any other text. Thus
we can use `%LOAD', or its method equivalent `load_file()', on any file,
and it will only ever instantiate macros and scripts and produce no
output. When we are using embedded processing any file `%LOAD'ed is
treated as if wrapped in delimiters.

   If we want to include the entire contents of another file, and perform
macro expansion on that file then use `%INCLUDE', e.g.

     %INCLUDE[/path/to/file/with/scripts-and-macros-and-text]

   The `%INCLUDE' command will instantiate any macros and scripts it
encounters and include all other lines of text (with macro/script
expansion) in the output stream.

   Macros and scripts are expanded in the following order: 1. scripts
(longest named first, shortest named last) 2. macros  (longest named
first, shortest named last)

Requiring files using `%REQUIRE'
--------------------------------

   We often want our scripts to have access to a bundle of functions that
we have created or that are in other modules. This can now be achieved by:

     %REQUIRE[/path/to/mylibrary.pl]

   An example library `macroutil.pl' is provided with examples of usage in
`html.macro'.

   There is no equivalent object method because if we're writing code we
can `use' or `require' as needed and if we're writing macros then we use
`%REQUIRE'.

Skipping text using `%CASE' and `%END_CASE'
-------------------------------------------

   It is possible to selectively skip parts of the text.

     %CASE[0]
     All the text here will be discarded.
     No matter how much there is.
     This is effectively a `comment' case.
     %END_CASE

   The above is useful for multi-line comments.

   We can also skip selectively. Here's an if...then:

     %CASE[#OS eq 'Linux']
     Skipped if the condition is FALSE.
     %END_CASE

   The condition can be any perl fragment. We can use previously defined
variables either using the #variable syntax as shown above or using the
exported perl name, thus in this case either `#OS', or `%Var{'OS'}'
whichever we prefer.

   If the condition is true the text is output with macro/script expansion
as normal; if the condition is false the text is skipped.

   The if...then...else structure:

     %DEFINE_VARIABLE OS[Linux]

     %CASE[$Var{'OS'} eq 'Linux']
     Linux specific stuff.
     %CASE[#OS ne 'Linux']
     Non-linux stuff - note that both references to the OS variable are
     identical in the expression (#OS is converted internally to $Var{'0S'} so
     the eval sees the same code in both cases
     %END_CASE

   Although nested `%CASE's are not supported we can get the same
functionality (and indeed more versatility because we can use full perl
expressions), e.g.:

     %DEFINE_VARIABLE TARGET[Linux]

     %CASE[#TARGET eq 'Win32' or #TARGET eq 'DOS']
     Win32/DOS stuff.
     %CASE[#TARGET eq 'Win32']
     Win32 only stuff.
     %CASE[#TARGET eq 'DOS']
     DOS only stuff.
     %CASE[#TARGET eq 'Win32' or #TARGET eq 'DOS']
     More Win32/DOS stuff.
     %END_CASE

   Although macro doesn't support nested `%CASE''s we can still represent
logic like this:

     if cond1 then
         if cond2
             do cond1 + cond2 stuff
         else
             do cond1 stuff
         end if
     else
         do other stuff
     end if

   By `unrolling' the expression and writing something like this:

     %CASE[#cond1 and #cond2]
         do cond1 + cond2 stuff
     %CASE[#cond1 and (not #cond2)]
         do cond1 stuff
     %CASE[(not #cond1) and (not #cond2)]
         do other stuff
     %END_CASE

   In other words we must fully specify the conditions for each case.

   We can use any other macro/script command within `%CASE' commands, e.g.
`%DEFINE's, etc., as well as have any text that will be macro/script
expanded as normal.

Undefining with `%UNDEFINE' and `undefine()'
--------------------------------------------

   Macros and scripts may be undefined in files:

     %UNDEFINE *P
     %UNDEFINE_SCRIPT *DATESTAMP
     %UNDEFINE_VARIABLE &*!

   and in code:

     $Macro->undefine( -macro, '*P' ) ;
     $Macro->undefine( -script, '*DATESTAMP' ) ;
     $Macro->undefine( -variable, '&*!' ) ;

   All macros, scripts and variables can be undefined:

     %UNDEFINE_ALL
     %UNDEFINE_ALL_SCRIPT
     %UNDEFINE_ALL_VARIABLE

     $Macro->undefine_all( -macro ) ;
     $Macro->undefine_all( -script ) ;
     $Macro->undefine_all( -variable ) ;

   One use of undefining everything is to ensure we get a clean start. We
might head up our files thus:

     %UNDEFINE_ALL
     %UNDEFINE_ALL_SCRIPT
     %UNDEFINE_ALL_VARIABLE
     %LOAD[mymacros]
     text goes here

Listing macros, scripts and variables with list()
-------------------------------------------------

   We can list the macros, scripts and variables in code with list:

     $Macro->list( -macro ) ;

   This will print the macros currently defined to the current file handle
- if there is one. If used in an array context will provide the list one
macro per array element:

     @macros = $Macro->list( -macro ) ;

     # Just give us the macro names:
     @macros = $Macro->list( -macro, -nameonly ) ;

   There are equivalents for scripts and variables:

     @scripts   = $Macro->list( -script ) ;
     @variables = $Macro->list( -variable ) ;

Commenting
----------

   Generally the text files that we process are in formats that support
commenting, e.g. HTML:

     <!-- This is an HTML comment -->

   Sometimes however we want to put comments in our macro source files
that won't end up in the output files. One simple way of achieving this is
to define a macro whose body is empty; when its called with any number of
parameters (our comments), their text is thrown away:

     %DEFINE %%[]

   which is used like this in texts:

     The comment comes %%[Here | [anything] put here will disappear]here!

   The output of the above will be:

     The comment comes here!

   We can add the definition in code:

     $Macro->define( -macro, '%%', '' ) ;

   Or the macro can be added automatically for us when we create the Macro
object:

     my $Macro = Text::MacroScript->new( -comment => 1 ) ;
     # All other options may be used too of course.

   However the easiest way to comment is to use `%CASE':

     %CASE[0]
     This unconditionally skips text up until the end marker since the
     condition is always false.
     %END_CASE

IMPORTABLE FUNCTIONS
====================

   In version 1.25 I introduced some useful importable functions. These
have now been removed from the module. Instead I supply a perl library
`macroutil.pl' which has these functions (abspath, relpath, today) since
Text::MacroScript can now `require' in any library file you like using the
`%REQUIRE' directive.

EXAMPLES
========

   I now include a sample `html.macro' file for use with HTML documents.
It uses the `macrodir' program (supplied). The macro examples include
macros which use `relpath' and also two macros which will include `new'
and `updated' images up until a specified expiry date using variables.

   (Also see DESCRIPTION.)

BUGS
====

   Lousy error reporting for embedded perl in most cases.

AUTHOR
======

   Mark Summerfield. I can be contacted as <summer@perlpress.com> - please
include the word 'macroscript' in the subject line.

COPYRIGHT
=========

   Copyright (c) Mark Summerfield 1999-2000. All Rights Reserved.

   This module may be used/distributed/modified under the LGPL.

an object-oriented text macro engine
************************************

NAME
====

   Text::Macros.pm - an object-oriented text macro engine

SYNOPSIS
========

   use Text::Macros;

     # poetic:
     my $macro_expander = new Text::Macros qw( {{ }} );
     $text = expand_macros $macro_expander $data_object, $text;

     # noisy:
     $macro_expander = Text::Macros->new( "\Q[[", "\Q]]", 1 );
     print $macro_expander->expand_macros( $data_object, $text );

DESCRIPTION
===========

   Typical usage might look like this:

     my $template = <<EOF;
       To: [[ RecipientEmail ]]
       From: [[ SenderEmail ]]
       Subject: Payment Past Due on Account # [[ AccountNum ]]

     Dear [[ RecipientName ]]:
     Your payment of [[ PaymentAmount ]] is [[ DaysPastDue ]] days past due.
      EOF

     # get a data object from somewhere, e.g.:
     my $data_object = $database->get_record_object( 'acctnum' => $account_num );

     # make a macro expander:
     my $macro_expander = Text::Macros->new( "\Q[[", "\Q]]" );

     # expand the macros in the template:
     my $email_text = $macro_expander->expand_macros( $data_object, $template );

   To support this, a "data object" would need to exist which would need to
define methods which will be used as macro names, e.g. like this:

     package RecordObject;
     sub RecipientEmail { $_[0]->{'RecipientEmail'} }
     sub SenderEmail    { $_[0]->{'SenderEmail'}    }
     sub AccountNum     { $_[0]->{'AccountNum'}     }
     sub RecipientName  { $_[0]->{'RecipientName'}  }
     sub PaymentAmount  { $_[0]->{'PaymentAmount'}  }
     sub DaysPastDue    { $_[0]->{'DaysPastDue'}    }

   Alternatively, the data object class might have AUTOLOAD defined, for
example like this:

     package RecordObject;
     sub AUTOLOAD {
      my $self = shift;
      my $name = $AUTOLOAD;
      $name =~ s/.*:://;
      $self->{$name}
     }

   If this is the case, then the macro expander should be instructed not to
assert that the macro names encountered are valid for the object - since
CAN might fail, even though the calls will be handled by AUTOLOAD.  To do
this, pass a true value for the third value to the constructor:

     my $macro_expander = Text::Macros->new( "\Q[[", "\Q]]", 1 );

   Macros can take arguments.  Any strings which occur inside the macro
text after the macro name will be passed as arguments to the macro method
call.  By default, the macro name and any arguments are all separated by
newlines.  You can override this behavior; see the documentation of
parse_args, below.

   Example:

     $macro_expander = new Macros qw( {{ }} );

     print $macro_expander->expand_macros( $cgi_query,
       "You entered {{ param
        Name }} as your name."
     );

   This will replace the substring

     {{ param
     Name }}

   with the result of calling

     $cgi_query->param("Name")

   (Obviously this example is a little contrived.)

METHODS
=======

The Constructor
---------------

     Text::Macros->new( $open_delim, $close_delim, $no_CAN_check, $parse_args_cr );

   The delimiters are regular expressions; this gives you the greatest
power in determining how macros are to be detected in the text.  But it
means that if you simply want them to be considered literal strings, then
you must quotemeta them.

   Since the macro expander will be calling object methods, you have an
option: do you want any encountered macro names to be required to be valid
for the given object?  Or do you have some kind of autoloading in effect,
which will handle undefined methods?

   If you have some kind of autoloading, pass a true value for the third
argument to new().  If you want the expander to assert CAN for each method,
pass false (the default).

   The fourth argument, $parse_args_cr, is a reference to a sub which
implements your macro argument parsing policy.  See the section on
parse_args, below.

The Main Method: Expand Macros
------------------------------

     $text = $macro_expander->expand_macros( $data_object, $text );

   The $data_object argument is not an object of the Macros package.
Rather, this is the object upon which the macro will be called as a method.

   expand_macros() returns the result of replacing all the macros it finds
with their appropriate expansions.  Note that recursion can occur; that is,
if the expansion of a macro results in text which also contains a valid
macro, that new macro will also be expanded.  The text will be scanned for
macros, and those macros will be expanded, until none are found.

A Utility Method: Call Macro
----------------------------

     $macro_expander->call_macro( $data_object, $macro_name, @arguments );

   This is used internally by expand_macros(), but you can call it
directly if you wish.

   Essentially all this does is this:

     $macro_expander->call_macro( $data_object, $macro_name, @arguments );

   results in the call:

     $data_object->$macro_name( @arguments );

   All the macros supported by the data object can be predefined, or you
might have some kind of autoloading mechanism in place for it.  If you
have autoloading in effect, you should have passed a true value as the
third argument to new().  If you pass false (the default), the
call_macro() will check to see that the object CAN do the method; and if
it can't an exception will be thrown.

   Note: data objects' macro methods must return a string.  They can take
any number of arguments, which will all be strings.

Parsing the Macro Arguments: parse_args
---------------------------------------

   This is used internally by expand_macros().

   expand_macros tries to call the sub which was passed by reference as the
fourth argument to new(), if there was one.  If no such coderef was given
to the constructor, then expand_macros calls the parse_args method in the
Text::Macros class, which implements the default behavior of splitting the
arg text on newlines, triming off leading/trailing whitespace, and then
dropping any list elements which are " (empty strings).

   To implement some behavior other than the default, you may derive a
class from Text::Macros which overrides parse_args.  The parse_args method
takes the Text::Macros object reference as the first arg (as usual), and
the macro text as the second argument.  This is all the text between the
delimiters, as it occurs in the template text.  This method is responsible
for extracting the macro name and the values of any arguments from the
macro text.  It is advisable that the parse_args routine strip any leading
and trailing whitespace from the argument values.  (It happens
automatically for the macro name, though, so you needn't worry about that.)

   Example:

     package MyMacroParser;
     @ISA = qw( Text::Macros );
     sub parse_args {
        my( $self, $macro_text ) = @_;
        # return a list of args extracted from $macro_text...
     }

   And then, of course, you would instantiate a MyMacroParser rather than a
Text::Macros.  Everything else about its usage would be identical.

   If you prefer, you can redefine the Text::Macros::parse_args sub
directly.  That might look something like this:

     *Text::Macros::parse_args = sub {
        my( $self, $macro_text ) = @_;
        # return a list of args extracted from $macro_text...
     };

   Alternatively, you may pass a code reference as the fourth argument to
new().  The arguments to and results from this sub are the same as for the
parse_args method, as described above, even though it is not (necessarily)
a method itself.

   The precedence is this: if a sub was passed to new(), that is called;
if not, the parse_args() of the derived class is called, if defined; if
not, the parse_args() of the base class (Text::Macros) is called.

EXAMPLES
========

   Brief examples of all these usage techniques can be found in the test
script, test.pl, which accompanies this distribution.  Any questions can
be directed to the author via email.

AUTHOR
======

   jdporter@min.net (John Porter)

COPYRIGHT
=========

   This module is free software; you may redistribute it and/or modify it
under the same terms as Perl itself.

v.0.33  General purpose text/data merging methods in Perl.
**********************************************************

NAME
====

   Text::Merge - v.0.33  General purpose text/data merging methods in Perl.

SYNOPSIS
========

     $merge = new Text::Merge;

     $merge->line_by_line();		# query
     $merge->line_by_line(0);	# turn off
     $merge->line_by_line(1);	# turn on

     $merge->set_delimiters('<<', '>>');            # user defined delims

     $success = $merge->publish($template, \%data);
     $success = $merge->publish($template, \%data, \%actions);
     $success = $merge->publish($template, $item);

     $success = $merge->publish_to($handle, $template, \%data);
     $success = $merge->publish_to($handle, $template, \%data, \%actions);
     $success = $merge->publish_to($handle, $template, $item);

     $text = $merge->publish_text($template, \%data);
     $text = $merge->publish_text($template, \%data, \%actions);
     $text = $merge->publish_text($template, $item);

     $success = $merge->publish_email($mailer, $headers, $template, \%data);
     $success = $merge->publish_email($mailer, $headers, $template,
     						     \%data, \%actions);
     $success = $merge->publish_email($mailer, $headers, $template, $item);

     $datahash = $merge->cgi2data();        # if you used "CGI(:standard)"
     $datahash = $merge->cgi2data($cgi);    # if you just used CGI.pm

DESCRIPTION
===========

   The `Text::Merge' package is designed to provide a quick, versatile,
and extensible way to combine presentation templates and data structures.
The `Text::Merge' package attempts to do this by assuming that templates
are constructed with text and that objects consist of data and functions
that operate on that data.  `Text::Merge' is very simple, in that it works
on one file and one object at a time, although an extension exists to
display lists (`Text::Merge::Lists') and `Text::Merge' itself could easily
be extended further.

   This is not XML and is intended merely to "flatten" the learning curve
for non-programmers who design display pages for programmers or to provide
programmers with a quick way of merging page templates with data sets or
objects without extensive research.

   The templates can be interpreted "line by line" or taken as a whole.

Technical Details
-----------------

   This object is normally inherited and so the new() function is the
constructor.  It just blesses an anonymous HASH reference, sets two flags
within that HASH, and returns it.  I'm am acutely aware of the criticisms
of the overuse of OOP (Object Oriented Programming).  This module needs to
be OO because of its extensibility and encapsulation; I wanted to impose
classification of the objects to allow the greatest flexibility in context
of implementation.  `Text::Merge' is generally used on web servers, and
can become integrated quickly into the httpd using mod_perl, hence the
encapsulation and inheritance provided by the Perl OO model clearly
outweighed the constraints thereby imposed.  That's my excuse...what's
yours?

   There are four public methods for the `Text::Merge' object:
`publish()', `publish_to()', `publish_text()', `publish_email()'.  The
first, `publish()', sends output to the currently selected file handle
(normally STDOUT).  The second method, `publish_text()', returns the
merged output as a text block.  The last method, `publish_email()', sends
the merged output as a formatted e-mail message to the designated mailer.

   Support is provided to merge the data and the functions performed on
that data with a text template that contains substitution tag markup used
to designate the action or data conversion.  Data is stored in a HASH that
is passed by reference to the publishing methods.  The keys of the data
hash correspond to the field names of the data, and they are associated
with their respective values.  Actions (methods) are similarly referenced
in a hash, keyed by the action name used in the template.

   Here is a good example of a publishing call in Perl:

     $obj = new Text::Merge;
     %data = ( 'Name'=>'John Smith', 'Age'=>33, 'Sex'=>'not enough' );
     %actions = ( 'Mock' => \&mock_person,  'Laud' => \&laud_person );
     $obj->publish($template, \%data, \%actions);

   In this example, `mock_person()' and `laud_person()' would be
subroutines that took a single hash reference, the data set, as an
argument.  In this way you can create dynamic or complex composite
components and reference them with a single tag in the template.  The
actions HASH has been found to be useful for default constructs that can
be difficult to code manually, giving page designers an option to work
with quickly.

Markup Tags
-----------

   Simply put, tags are replaced with what they designate.  A tag
generally consists of a prefix, followed by a colon, then either an action
name or a field name followed by zero or more formatting directives
seperated by colons.  In addition, blocks of output can be contained
within curly brackets in certain contexts for conditional display.

REF: tags
     Simple data substitution is achieved with the REF: tag.  Here is an
     example of the use of a REF: tag in context, assume we have a
     key-value pair in our data HASH associating the key 'Animal' with the
     value of 'turtle':

          The quick brown REF:Animal jumped over the lazy dog.

     when filtered, becomes:

          The quick brown turtle jumped over the lazy dog.

     The REF: tag designators may also contain one or more format
     directives.  These are chained left to right, and act to convert the
     data before it is displayed.  For example:

          REF:Animal:lower:trunc3

     would result in the first three letters of the SCALAR data value
     associated with Animal in lower case.  See the section, `Data
     Conversions Formats', for a list of the available SCALAR data
     formatting directives.  Note that some conversions may be
     incompatible or contradictory.  The system will not necessarily warn
     you of such cases, so be forewarned.

     Any REF: tag designator can be surrounded by curly brace pairs
     containing text that would be included in the merged response only if
     the result of the designator is not empty (has a length).  There must
     be no spaces between the tag and the curly braced text.  If
     line-by-line mode is turned off, then the conditional text block may
     span multiple lines.  For example:

          The {quick brown }REF:Animal{ jumps over where the }lazy dog lies.

     Might result in:

          The quick brown fox jumps over where the lazy dog lies.

     or, if the value associated with the data key 'Animal' was undefined,
     empty, or zero:

          The lazy dog lies.

IF: tags
     The IF: tag designators performs a conditional display.  The syntax
     is as follows:

          IF:FieldName:formats{Text to display}

     This designator would result in the string *Text to display* being
     returned if the formatted data value is not empty.  The curly braced
     portion is required, and no curly braces are allowed before the
     designator.

NEG: tags
     The NEG: tag designator is similar to the IF: tag, but the bracketed
     text is processed only if the formatted data value is empty (zero
     length) or zero.  Effectively the NEG: can be thought of as *if not*.
     Here is an example:

          NEG:FieldName:formats{Text to display if the result is empty.}

ACT: tags
     The ACT: tag designates that an action is to be performed (a
     subroutine call) to obtain the result for substition.  The key name
     specified in the designator is used to look up the reference to the
     appropriate subroutine, and the data HASH reference is passed as the
     sole argument to that subroutine.  The returned value is the value
     used for the substition.

     ACT: is intended to be used to insert programmatic components into
     the document.  It can only specify action key names and has no
     equivalent tags to IF: and NEG:.  The curly brace rules for the ACT:
     tag are exactly the same as those for the REF: tag.

Conditional Text Braces
     All tags support conditional text surrounded by curly braces.  If the
     `line_by_line()' switch is set, then the entire tag degignator must
     be on a single line of text, but if the switch is OFF (default) then
     the conditional text can span multiple lines.

     The two conditional tags, IF: and NEG:, require a single conditional
     text block, surrounded by curly braces, immediately following
     (suffixing) the field name or format string.  For example:

          IF:SomeField{this text will print}

     The REF: and ACT: tags allow for curly braces both at the beginning
     (prefixing) and at the end (suffixing).  For example:

          {Some optional text }REF:SomeValue{ more text.}

Command Braces
     You may bracket entire constructs (along with any conditional text)
     with double square brackets to set them off from the rest of the
     document.  The square brackets would be removed during substitution:

          The [[IF:VerboseVar{quick, brown }]]fox jumped over the lazy dog.

     assuming that 'VerboseVar' represented some data value, the above
     example would result in one of:

          The quick, brown fox jumped over the lazy dog.
          or
          The fox jumped over the lazy dog.

Data Conversion Formats
     Here is a list of the data conversion format and the a summary.
     Details are undetermined in some cases for exceptions, but all of the
     conversion to some satisfactory degree.  These conversion methods
     will treat all values as SCALAR values:

          upper	-  converts all lowercase letters to uppercase
          lower	-  converts all uppercase letters to lower
          proper	-  treats the string as a Proper Noun
          trunc## -  truncate the scalar to ## characters (## is an integer)
          words## -  reduce to ## words seperated by spaces (## is an integer)
          paragraph## -  converts to a paragraph ## columns wide
          indent## - indents plain text ## spaces
          int	-  converts the value to an integer
          float	-  converts the value to a floating point value
          string  -  converts the numeric value to a string (does nothing)
          detab	-  replaces tabs with spaces, aligned to 8-char columns
          html	-  replaces newlines with HTML B<BR> tags
          dollars	-  converts the value to 2 decimal places
          percent	-  converts the value to a percentage
          abbr	-  converts a time value to m/d/yy format
          short	-  converts a time value to m/d/yy H:MMpm format
          time	-  converts a time value to H:MMpm (localtime am/pm)
          24h	-  converts a time value to 24hour format (localtime)
          dateonly - converts a time value to Jan. 1, 1999 format
          date	- same as 'dateonly' with 'time'
          ext	-  converts a time value to extended format:
          	        Monday, Januay 12th, 1999 at 12:20pm
          unix	-  converts a time value to UNIX date string format
          escape	-  performs a browser escape on the value (&#123;)
          unescape - performs a browser unescape (numeric only)
          urlencode - performs a url encoding on the value (%3B)
          urldecode - performs a url decoding (reverse of urlencode)

     Most of the values are self-explanatory, however a few may need
     explanation:

     The trunc format must be suffixed with an integer digit to define at
     most how many characters should be displayed, as in `trunc14'.

     The html format just inserts a <BR> construct at every newline in the
     string.  This allows text to be displayed appropriately in some cases.

     The escape format performs an HTML escape on all of the reserved
     characters of the string.  This allows values to be displayed
     correctly on browsers in most cases.  If your data is not
     prefiltered, it is usually a good idea to use escape on strings where
     HTML formatting is prohibited.  For example a '$' value would be
     converted to '&#36;'.

     The `unescape' format does the reverse of an escape format, however it
     does not operate on HTML mnemonic escapes, allowing special
     characters to remain intact.  This can be used to reverse escapes
     inherent in the use of other packages.

     The `urlencode' and `urldecode' formats either convert a value (text
     string) to url encoded format, converting special characters to their
     %xx equivalent, or converting to the original code by decoding %xx
     characters respectively from the url encoded value.

Item Support
------------

   The publishing methods all require at the very least a template, a data
set, and the action set; although either the data set or the action set or
both could be empty or null.  You may also *bundle* this information into
a single HASH (suitable for blessing as a class) with the key 'Data'
associated with the data HASH reference, and the key 'Actions' associated
with the action HASH reference.  A restatement of a previous example might
look like this:

     $obj = new Text::Merge;
     $data = { 'Name'=>'John Smith', 'Age'=>33, 'Sex'=>'not enough' };
     $actions = { 'Mock' => \&mock_person,  'Laud' => \&laud_person };
     $item = { 'Data' => $data,  'Actions' => $actions };
     $obj->publish($template, $item);

   In addition, if you specify a key 'ItemType' in your $item and give it
a value, then the item reference will be handed to any methods invoked by
the ACT: tags, rather than just the data hash.  This allows you to
construct items that can be merged with templates.  For example, the
following code is valid:

     %data = ( 'Author' => 'various',  'Title' => 'The Holy Bible' );
     %actions = ( 'Highlight' => \&highlight_item );
     $item = { 'ItemType'=>'book', 'Data'=>\%data, 'Actions'=>\%actions };
     bless $item, Some::Example::Class;
     $obj->publish($template, $item);

   In this last example, the designator `ACT:Highlight' would result in
the object $item being passed as the only argument to the subroutine
`highlight_item()' referenced in the action HASH.

Line by Line Mode
-----------------

   By default, the publishing methods slurp in the entire template and
process it as a text block.  This allows for multi-line conditional text
blocks.  However, in some cases the resulting output may be very large, or
you may want the output to be generated line by line for some other reason
(such as unbuffered output).  This is accomplished through the
`line_by_line()' method, which accepts an optional boolean value, which
sets the current setting if specified or returns the current settingif
not.  Note that this has the most notable impact on the `publish()' and
`publish_email()' methods, since the results of the merge operations are
sent to a handle.  If the line by line switch is set, then the
`publish_text()' method will substitute line by line, but will still
return the entire merged document as a single text block (not line by
line).

   This is turned OFF by default.

Templates
---------

   Templates consist of text documents that contain special substitution
designators as described previously.  The template arguments passed to the
publishing functions can take one of three forms:

File Handle
     This is a FileHandle object not a glob.  You must use the FileHandle
     package that comes with the Perl distribution for this type of
     template argument.  Processing begins at the current file position
     and continues until the end of file condition is reached.

File Path
     If the argument is a scalar string with no whitespace, it is assumed
     to be a file path.  The template at that location will be used when
     merging the document.

Text Block
     If the argument is a scalar string that contains whitespace, it is
     assumed to be the actual text template.  Substitution will be
     performed on a locally scoped copy of this argument.

     Note that you should not use this type of template argument if your
     template is very large and you are using line by line mode.  In this
     case you should use a FileHandle or file path argument.

Methods
-------

new()
     This method gives us a blessed hash reference, with the following
     attribute keys:

          _Text_Merge_LineMode

     Other keys can be added by objects which inherit `Text::Merge'.

line_by_line($setting)
     This method returns the current setting if the `$setting' argument is
     omitted.  Otherwise it resets the line-by-line mode to the setting
     requested.  A non-zero value tells the publishing methods to process
     the template line by line.  For those methods that output results to
     a handle, then those results will also be echoed line by line.

set_delimiters($start, $end)
     This method assigns a new command delimiter set for the tags (double
     square brackets by default).  The 'colon' character is not allowed
     within the delimiter, and the delimiter may not be a single curly
     bracket.  Both the $start and $end delimiters must be provided, and
     they cannot be identical.

publish($template, $dataref, $actionref)
     This is the normal publishing method.  It merges the specified
     template with the data and any provided actions.  The output is sent
     to the currently selected handle, normally STDOUT.

publish_to($handle, $template, $dataref, $actionref)
     This is similar to the normal publishing method.  It merges the
     specified template with the data and any provided actions.  The
     output is sent to the specified $handle or to the currently selected
     handle, normally STDOUT, if the $handle argument is omitted.

publish_text($template, $dataref, $actionref)
     This method works similar to the `publish_to()' method, except it
     returns the filtered output as text rather than sending it to the
     currently selected filehandle.

publish_email($mailer, $headers, $filepath, $data, $actions)
     This method is similar to `publish()' but opens a handle to
     `$mailer', and sending the merged data formatted as an e-mail
     message.  `$mailer' may contain the sequences `RECIPIENT' and/or
     `SUBJECT'.  If either does not exists, it will be echoed at the
     beginning of the email (in the form of a header), allowing e-mail to
     be passed preformatted.  This is the preferred method; use a mailer
     that can be told to accept the "To:", "Subject:" and "Reply-To:"
     fields within the body of the passed message and do not specify the
     `RECIPIENT' or `SUBJECT' tags in the `$mailer' string.  Returns false
     if failed, true if succeeded.  The recommended mail program is
     'sendmail'.  `$headers' is a HASH reference, containing the header
     information.  Only the following header keys are recognized:

          To
          Subject
          Reply-To
          CC
          From (works for privileged users only)

     The values associated with these keys will be used to construct the
     desired e-mail message header.  Secure minded site administrators
     might put hooks in here, or even better clean the data,  to protect
     access to the system as a precaution, to avoid accidental mistakes
     perhaps.

     Note: the `$mailer' argument string should begin with the type of
     pipe required for your request.  For sendmail, this argument would
     look something like (note the vertical pipe):

          '|/usr/bin/sendmail -t'

     Be careful not to run this with write permission on the sendmail file
     and forget the process pipe!!!

cgi2data($cgi)
     This method converts `CGI.pm' parameters to a data hash reference
     suitable for merging.  The $cgi parameter is a CGI object and is
     optional, but you must have imported the :standard methods from
     `CGI.pm' if you omit the $cgi paramter.  This method returns a hash
     reference containing the parameters as data.  Basically it turns list
     values into list references and puts everything in a hash keyed by
     field name.

PREREQUISITES
=============

   This module was written and tested in Perl 5.005 and runs with `-Tw'
set and `use strict'.  It requires use of the package FileHandle which is
part of the standard perl distribution.

AUTHOR
======

   This software is released under the Perl Artistic License.  Derive what
you wish, as you wish, but please attribute releases and include derived
source code.  (C) 1997-2000 by Steven D. Harris, perl@nullspace.com

v.0.30 Text/data merge with lists/table support
***********************************************

NAME
====

   Text::Merge::Lists - v.0.30 Text/data merge with lists/table support

SYNOPSIS
========

     $filter = new Text::Merge::Lists($template_path);

     $filter->set_max_nesting_depth($intval);

DESCRIPTION
===========

   The `Text::Merge::Lists' package is designed to extend the
`Text::Merge' package with "list styles" in addition to the other
formatting methods of fields.  This allows the display of fields that
contain "lists" of items in addition to the normal "scalar" fields
supported by `Text::Merge'.  See the `Text::Merge' package documentation
for more information on templates and merging.

   All the features of the `Text::Merge' package are supported and invoked
in an identical fashion.  The only difference in your programs to use the
`Text::Merge::Lists' object instead of the `Text::Merge' object is the
constructor, which must be invoked with the "Template Path" to the
directory containing your various arbitrary lists style directories,
described later.  See the `Text::Merge' object for a description of the
publishing methods available to you.

   Lists can be nested, and you can use the `set_max_nesting_depth()'
object method to override the default maximum nesting depth of 3.  That is
to say, you can only have a list of a list of a list by default.  If you
want to nest further you will need to adjust this value.  The depth limit
here is to prevent you from clobbering the perl stack (and possibly other
memory!) with deep recursion.

List Structure
--------------

   A list variable is a reference to an ARRAY of data HASH references or
item HASH references.  Basically, the equivalent of the $data or $item
argument to the publishing methods.  If you apply a list style to a SCALAR
it will be treated as a list of one item.  Undefined lists are not
considered empty, but they are undefined as one would expect.  Here is an
example list assignment to the variable `$fruit_list':

     $apple = { 'Color'=>'Red', 'Size'=>'medium', 'Shape'=>'round' };
     $pear = { 'Color'=>'Green', 'Size'=>'medium', 'Shape'=>'pear-shaped' };
     $grape = { 'Color'=>'Purple', 'Size'=>'small', 'Shape'=>'round' };
     $fruit_list = [ $apple, $pear, $grape ];

List Style Syntax
-----------------

   If you have read the `Text::Merge' module documentation, which is
recommended, then you may be familiar with the syntax for displaying
arbitrary fields using different styles, such as this example for a
displaying a numerical value, stored in the `MyDollars' field, as a decimal
value with two decimal places:

     REF:MyDollars:dollars

   There are many display styles available, some of which only apply to
*particular types of data*.  These are described in detail in the
`Text::Merge' module documentation.

   The `Text::Merge::Lists' object extends the `Text::Merge' object with
support for list (ARRAY) references.  By using the list style designators,
you can display lists in various contexts, just as you would any other
field value.  The templates for the various lists styles are stored in
directories corresponding to the list style names.  These are located in
the path provided to the constructor.

   The individual items stored in the lists should be data or item HASH
references as described in the `Text::Merge' documentation.  These objects
have an "ItemType" designator, allowing the individual list styles to
display each type differently in that context.  These listing templates
are plain text files, ending in '.txt' and stored in the style directory.
For example, a list style of 'showcase' stored in the templates path
`/usr/templates/' would have all of it's files stored in the path,
`/usr/templates/showcase/'.  If you had an item type of 'book' to display
in a given list, that template would be stored at
`/usr/templates/showcase/book.txt'.  The template will be used for each
occurrence of the item type 'book' in any list displayed using the
'showcase' style.  In most cases, the listing templates will be output
"end on end" but that may not always be the case as described later.

   The syntax for a reference to an item list field named, `DisplayItems',
for the example list style of 'showcase' would look something like this:

     REF:DisplayItems:list_showcase

   Notice the `list_' portion (that is an 'underscore').  This tells the
filter that you want to treat the field `DisplayItems' as a list of items
and use the 'showcase' list style.  The system will then look-up any
templates it needs for the list in the 'showcase' directory mentioned
above.

List Style Features
-------------------

   Each list style has various special features that you can use by
providing certain files in the list style directory.  These include a
header, a footer, a default item, and a message to display if the list is
empty.

List Header
     The list header is an HTML fragment contained in a plain text file
     that is treated by the filter as if it were part of the original
     document (as opposed to a list item), it is displayed immediately
     before the list itself.  It is contained in the file `header.txt' in
     the list style directory.  This file is optional.

List Footer
     The list footer is similar to the list header described above.  It is
     displayed immediately following the list itself.  It is contained in
     the file `footer.txt' in the list style directory.  This file is also
     optional.

Default Item Type
     You may provide a listing fragment that will be used for any item
     that does not have a template in the designated list style directory.
     This could be an error message, or it my display information
     universal to all of your objects.  You can use this item template if
     all of your items are very similar and you don't want to construct a
     template for each item in that style.

     The default item template is located in a file called `default.txt'
     in the designated list style directory.  This file is optional.

Empty List Message
     Similar to a header or footer, the empty list message is a file
     contained in the designate style directory that is treated as part of
     the parent document for display purposes, if no items exist in your
     list.  If this file is not provided, then empty lists are constructed
     as empty strings.  The file name for the empty list message is
     `empty.txt' in the designated list style directory and is optional.

Table Style Syntax
------------------

   In addition to list styles, `Text::Merge::Lists' also supports HTML
table styles.  Table styles are trickier to set up than list styles, but
the principle is basically the same, and you get the benefit of having
more than one column in your list display.  You maintain full control over
the styling of the individual cells and the table attributes.  All tables
are HTML.

   The syntax of a table style is very similar to the syntax of a list
style, but you need to specify the number of columns for the table in the
tag.  For example:

     REF:ItemList:table4_options

   The example listed above would generate a table using the table style
defintion, "options", that is four columns wide.  The number is required
and must be at least 1.  Large numbers (>10) are discouraged because they
are practically unusable.

   A table generated by a table style is basically a "grid" of the
specified width with a "filler" cell at the end of the table if necessary.
The filler cell may be one or more cells wide, up to one less than the
specified table width.  With this in mind, there are more restrictions on
the templates required for a table style, as described later.

   Just as is the case with the list styles, individual items stored in
the lists should be data or item HASH references as described in the
`Text::Merge' documentation.  These objects have an "ItemType" designator,
allowing the individual table styles to display the cell for each type
differently in the same context.  The cell templates are plain text files,
ending in '.txt' and stored in the table style directory.

   For example, a table style of 'options' stored in the templates path
`/usr/templates/' would be located at `/usr/templates/tables/options/'.
If you had an item of type 'choice' to display in a given list, then the
cell template for display of that particular item would be
`/usr/templates/tables/options/choice.txt'.  Notice that the path was
created by stringing together the list-styles/template
(`/usr/templates')path, the table styles subdirectory (`tables/'), and the
directory and path for the individual style and item type
(`options/choice.txt').

   If you choose to construct a table style, take care to include all the
required elements.  Start and finish your cell templates with the <TD> and
</TD> elements respectively.  Start your header with <TABLE> and end it
with </TABLE>.  Remember that the Text::Merge::Lists methods will insert
the <TR> and </TR> elements for rows containing your cell templates.  Only
use <TR> and </TR> in the header and footer files, and if you do be sure
to use only one cell in each row and use the `TableColumns' field to
assign the COLSPAN for that table.  Observing these few things should keep
your tables functional.

Table Style Features
--------------------

   Each table style has similar requirements for the files stored in the
designated table style directory.  The required files include a header, a
footer, a filler template, a default cell template, and the optional
template to use if the list is empty.  The header, footer, and empty
templates will all have access to the data of the calling template, in
addition the header and footer templates will also have the additional
field TableColumns set.  Likewise, the filler template will have the
FillerColumns field set, and that must be used to set the COLSPAN of the
last table cell as described later.

Table Header Template
     The table header is contained in a file named `header.txt' in the
     table style directory.  This file *must contain* the <TABLE ...>
     element defintion.  It may also contain full table rows to start off
     the table.  Because table styles may be invoked with a variable
     column count, the field `TableColumns' is provided to use for a cell
     in these table rows, and while limited, it does allow the insertion
     of header rows.  For example, this might be the contents of a common
     header.txt file:

          <TABLE BORDER=1>
          	<TR NOSAVE><TD ALIGN=CENTER
          		COLSPAN="REF:TableColumns"><B>Title</B></TD></TR>

     Notice the `REF:TableColumns' portion of the code, which will be
     replaced with the number of columns in the table when the table is
     created.  This allows for a "variable width" header that covers all
     columns.

Table Footer Template
     The table footer is contained in a file named `footer.txt' and is
     very similar to the `header.txt' file described above.  The
     `footer.txt' file *must contain* the </TABLE> element closing out the
     table.  Before that element, any number of optional footer rows can
     be listed, and they too can use the `TableColumns' field to span the
     table columns as well.  For example:

          <TR><TD COLSPAN="REF:TableColumns">This
          			is the last table row.</TD></TR></TABLE>

     Notice the `REF:TableColumns' field used in the the last cell
     definition, just as is done with the header rows.  Also notice the
     </TABLE> listed at the very end.  This basically closes out the table
     and is required.  You can also include other HTML after this element
     if you wish, but it will not be included in the table itself.

Table Filler Template
     The table filler cell is contained in a file named `filler.txt' in
     the table style directory.  This is the template used for the last
     cell of a table to fill the empty spaces that may be left if the
     number of items in the list is not evenly divisible by the number of
     columns in the table.  A field named `FillerColumns' is provided to
     this template and it *must be used* to specify the COLSPAN of the
     cell.  This template, as with all other cell templates, must contain
     the <TD ...> and </TD> elements of the cell.  This is a simple
     example filler cell template:

          <TD COLSPAN="REF:FillerColumns"><I>this is filler</I></TD>

     The filler cell will be created with a single non-blocking space
     character (*&nbsp;*) as content if no `filler.txt' template file
     exists.

Item Type Cell Template
     Each item in the list can be displayed based on its `ItemType'
     attribute if a cell template exists in the table style directory that
     is named with the item type followed by the '.txt' suffix.  If such a
     template exists, it will be used to display the cell using the item
     data and actions.  Every cell template *must contain* the
     <TD...>...</TD> elements to work properly in the table style.

Default Cell Template
     The default cell template will be used if there is no cell template
     for the item type to be displayed.  That is to say, if no file as
     described above exists for the item type in question, a file called
     'default.txt' will be used to display the item.  The  'default.txt'
     file is required if your table style definition is be robust.

Empty Table Template
     The empty table template is used if the list exists but contains no
     items.  The empty table template is contained in a file in the table
     style directory named 'empty.txt'.  This template will have access to
     all the data and actions of the calling template.  Note that if the
     'empty.txt' template is used, then none of the other templates will be
     used for that table style and the results of processing 'empty.txt'
     will be the only thing displayed.

Methods
-------

   These are the methods that extend the basic functions of the
`Text::Merge' object.  Note that we overload `convert_value()' in order to
insert our list style format recognition and interpretation.  This is very
elegant and easy to do.

new($liststyles)
     This method constructs a `Text::Merge::Lists' object.  It basically
     grabs a new `Text::Merge' object and then assigns the liststyles
     directory (which is required).  If the template path is omitted, an
     the call is treated as a normal `Text::Merge' object request.

convert_value($dataref, $name, $style, $item)
     This method catches list styles and handles them, otherwise the
     `Text::Merge' method is used.

set_max_nesting_depth($intval)
     This method assigns the maximum nesting depth for lists.  The default
     maximum depth is 3.

sort_method($methodstr, $listref)
     This method returns the sorted list by processing the `$methodstr'
     for each item in the list.  A common `$methodstr' might look
     something like:

          $method = 'REF:SomeField reverse numeric';

     Which would perform a reverse numeric sort on the list.  Basically a
     merge is performed on the $methodstr and the sort algorithm is
     sensitive to the keyword designators: reverse and numeric, which must
     appear at the end of the sort method string.

     These must be items, where the data is contained in the 'Data' field.
     For instance:

          $item = { 'ItemType' => 'someitem',
          	  'Data' => { 'field1' => 'val1',
          		      'field2' => 'val2' } };

PREREQUISITES
=============

   This module inherits and extends the `Text::Merge' module by this
author.  This module was written and tested under perl 5.005 and runs with
`-Tw' set and `use strict'.

AUTHOR
======

   This software is released under the Perl Artistic License.  Modify as
you please, but please attribute releases and include all derived source
code.  (C) 1997, 1998, 1999, by Steven D. Harris, sharris@nullspace.com

Perl extension implementing meta-language for processing  "template" text files.
********************************************************************************

NAME
====

   Text::MetaText - Perl extension implementing meta-language for
processing "template" text files.

SYNOPSIS
========

     use Text::MetaText;

     my $mt = Text::MetaText->new();

     # process file content or text string
     print $mt->process_file($filename, \%vardefs);
     print $mt->process_text($textstring, \%vardefs);

     # pre-declare a BLOCK for subsequent INCLUDE
     $mt->declare($textstring, $blockname);
     $mt->declare(\@content, $blockname);

SUMMARY OF METATEXT DIRECTIVES
==============================

     %% DEFINE
        variable1 = value          # define variable(s)
        variable2 = "quoted value"
     %%

     %% SUBST variable  %%         # insert variable value
     %% variable %%                # short form of above

     %% BLOCK blockname %%         # define a block 'blockname'
        block text...
     %% ENDBLOCK %%

     %% INCLUDE blockname %%       # include 'blockname' block text
     %% INCLUDE filename  %%       # include external file 'filename'

     %% INCLUDE file_or_block      # a more complete example...
        variable = value           # additional variable definition(s)
        if       = condition       # conditional inclusion
        unless   = condition       # conditional exclusion
        format   = format_string   # printf-like format string with '%s'
        filter   = fltname(params) # post-process filter
     %%

     %% TIME                       # current system time, as per time(2)
        format   = format_string   # display format, as per strftime(3C)
     %%

DESCRIPTION
===========

   MetaText is a text processing and markup meta-language which can be
used for processing "template" files.  This module is a Perl 5 extension
implementing a MetaText object class which processes text files,
interpreting and acting on the embedded MetaText directives within.

   Like a glorified pre-processor, MetaText can; include files, define and
substitute variable values, execute conditional actions based on variables,
call other perl functions or object methods and capture the resulting
output back into the document, and more.  It can format the resulting
output of any of these operations in a number of ways.  The objects, and
inherently, the format and symantics of the MetaText langauge itself, are
highly configurable.

   MetaText was originally designed to aid in the creation of html
documents in a large web site.  It remains well suited for this and
similar tasks, being able to create web pages (dynamically or statically)
that are consistent with each other, yet easily customisable:

   * standard headers, footers and other elements can be defined in
     separate files and then inserted into web documents:

          %% INCLUDE header %%

   * variables can be defined externally or from within a document, then
     can be substituted back into the text.  This is useful for including
     your *%% name %%* or *%% email %%* address or any other variable, and
     for encoding URL's or file paths that can then be changed en masse.
     e.g.

          <img src="%% imgroot %%/foo/bar.gif">

   * conditional actions can be made based on variable definitions,
     allowing easily and instantly customisable web pages. e.g

          %% INCLUDE higraphics/header if="higfx && userid != abw" %%

   * blocks of text can be internally defined simplifying the creation of
     repetitive elements.  e.g.

          %% BLOCK table_row %%
          <tr> <td>%% userid %%</td> <td>%% name %%</td> </tr>
          %% ENDBLOCK %%

          %% INCLUDE table_row userid=lwall  name="Larry Wall"         %%
          %% INCLUDE table_row userid=tomc   name="Tom Christiansen"   %%
          %% INCLUDE table_row userid=merlyn name="Randal L. Schwartz" %%

   * in addition, the *metapage* utility is a script which can
     automatically traverse document trees, processing updated files to
     assist in web document management and other similar tasks.

PREREQUISITES
=============

   MetaText requires Perl 5.004 or later.  The Date::Format module should
also be installed.  This is available from CPAN (in the "TimeDate"
distribution) as described in the following section.  The *metapage*
utility also requires the File::Recurse module, distributed in the
"File-Tools" bundle, also available from CPAN.

OBTAINING AND INSTALLING THE METATEXT MODULE
============================================

   The MetaText module is available from CPAN.  As the 'perlmod' man page
explains:

     CPAN stands for the Comprehensive Perl Archive Network.
     This is a globally replicated collection of all known Perl
     materials, including hundreds of unbunded modules.

     [...]

     For an up-to-date listing of CPAN sites, see
     http://www.perl.com/perl/ or ftp://ftp.perl.com/perl/ .

   Within the CPAN archive, MetaText is in the "Text::" group which forms
part of the the category:

     *) String Processing, Language Text Processing,
        Parsing and Searching

   The module is available in the following directories:

     /modules/by-module/Text/Text-MetaText-<version>.tar.gz
     /authors/id/ABW/Text-MetaText-<version>.tar.gz

   For the latest information on MetaText or to download the latest
pre-release/beta version of the module, consult the definitive reference,
the MetaText Home Page:

     http://www.kfs.org/~abw/perl/metatext/

   MetaText is distributed as a single gzipped tar archive file:

     Text-MetaText-<version>.tar.gz

   Note that "<version>" represents the current MetaText Revision number,
of the form "0.18".  See `REVISION' in this node below to determine the
current version number for Text::MetaText.

   Unpack the archive to create a MetaText installation directory:

     gunzip Text-MetaText-<version>.tar.gz
     tar xvf Text-MetaText-<version>.tar

   'cd' into that directory, make, test and install the MetaText module:

     cd Text-MetaText-<version>
     perl Makefile.PL
     make
     make test
     make install

   The 't' sub-directory contains a number of small sample files which are
processed by the test script (called by 'make test').  See the README file
in that directory for more information.  A logfile (test.log) is generated
to report any errors that occur during this process.  Please note that the
test suite is incomplete and very much in an 'alpha' state.  Any further
contributions here are welcome.

   The 'make install' will install the module on your system.  You may need
root access to perform this task.  If you install the module in a local
directory (for example, by executing "perl Makefile.PL LIB=~/lib" in the
above - see `perldoc MakeMaker' for full details), you will need to ensure
that the PERL5LIB environment variable is set to include the location, or
add a line to your scripts explicitly naming the library location:

     use lib '/local/path/to/lib';

   The *metapage* utility is a script designed to automate MetaText
processing of files.  It can traverse directory trees, identify modified
files (by comparing the time stamp of the equivalent file in both "source"
and "destination" directories), process them and direct the resulting
output to the appropriate file location in the destination tree.  One can
think of *metapage* as the MetaText equivalent of the Unix make(1S)
utility.

   The installation process detailed above should install *metapage* in
your system's perl 'installbin' directory (try `perl '-V:installbin'' to
check this location).  See the *metapage* documentation (`perldoc
metapage') for more information on configuring and using *metapage*.

USING THE METATEXT MODULE
=========================

   To import and use the MetaText module the following line should appear
in your Perl script:

     use Text::MetaText;

   MetaText is implemented using object-oriented methods.  A new MetaText
object is created and initialised using the Text::MetaText->new() method.
This returns a reference to a new MetaText object.

     my $mt = Text::MetaText->new;

   A number of configuration options can be specified when creating a
MetaText object.  A reference to a hash array of options and their
associated values should be passed as a parameter to the new() method.

     $my $mt = Text::MetaText->new( { 'opt1' => 'val1', 'opt2' => 'val2' } );

   The configurations options available are described in full below.  All
keywords are treated case-insensitively (i.e. "LIB", "lib" and "Lib" are
all considered equal).

LIB
     The INCLUDE directive causes the external file specified ("INCLUDE
     <file>") to be imported into the current document.  The LIB option
     specifies one or more directories in which the file can be found.
     Multiple directories should be separated by a colon or comma.  The
     current directory is also searched by default.

          my $mt = Text::MetaText->new( { LIB => "/tmp:/usr/metatext/lib" } );

CASE
     The default behaviour for MetaText is to treat variable names and
     identifiers case insensitively.   Thus, the following are treated
     identically:

          %% INCLUDE foo %%
          %% INCLUDE Foo %%
          %% INCLUDE FOO %%

     When running with CASE sensitivity disabled, the MetaText processor
     converts all variable and symbol names to lower case.

     Setting the CASE option to any non-zero value causes the document to
     be processed case sensitively.

          my $mt = Text::MetaText->new( { CASE => 1 } ); # case sensitive

     Note that the configuration options described in this section are
     always treated case insensitively regardless of the CASE setting.

CASEVARS
     When running in the default case-insensitive mode (CASE => 0), all
     variable names are folded to lower case.  It is convenient to allow
     applications to specify some variables that are upper or mixed case
     to distinguish them from normal variables.  The metapage utility uses
     this to define a number of 'system variables' that hold information
     about the file being processed: FILETIME, FILEMOD, FILEPATH, etc.  By
     defining these as CASEVARS, the processor will attempt to
     differentiate them from normal variables by their case.  Thus, the
     calling application can define variables that are guaranteed not to
     conflict with any user-defined variables (while CASE insensitive) and
     are also effectively read-only.

          my $mt = Text::MetaText->new( {
              CASEVARS => [ 'AUTHOR', 'COPYRIGHT' ],
          });

          print $mt->process_file($file, {
          	AUTHOR    => 'Andy Wardley',
          	COPYRIGHT => '(C) Copyright Andy Wardley 1998',
          });

     The input file:

          %% DEFINE copyright = "(C) Ima Plagiarist" %%
          %% COPYRIGHT %%
          %% copyright %%

     produces the following output:

          (C) Copyright Andy Wardley 1998        # COPYRIGHT
          (C) Ima Plagiarist                     # copyright

     Note that CASEVARS can only apply to variables that are pre-defined
     (i.e. specified in the hash array that is be passed to process_xxxx()
     as a second parameter).  It is not possible to re-define a CASEVARS
     variable with a DEFINE directive because the variable name will always
     be folded to lower case (when CASE == 0).  e.g.

          %% DEFINE COPYRIGHT = "..." %%

     is interpreted as:

          %% DEFINE copyright = "..." %%

     It is recommended that such variables always be specified in UPPER
     CASE as a visual clue to indicate that they have a special meaning and
     behaviour.

MAGIC
     MetaText directives are identifed in the document being processed as
     text blocks surrounded by special "magic" identifers.  The default
     identifiers are a double percent string, "%%", for both opening and
     closing identifiers.  Thus, a typical directive looks like:

          %% INCLUDE some/file %%

          and may be embedded within other text:

          normal text, blah, blah %% INCLUDE some/file %% more normal text

     The MAGIC option allows new identifiers to be defined.  A single
     value assigned to MAGIC defines a token to be used for both opening
     and closing identifiers:

          my $mt = Text::MetaText->new( { MAGIC => '++' } );

          ++ INCLUDE file ++

     A reference to an array providing two values (elements 0 and 1)
     indicates separate tokens to be used for opening and closing
     identifiers:

          my $mt = Text::MetaText->new( { MAGIC => [ '<!--', '-->' ] } );

          <!-- INCLUDE file -->

CHOMP
     When MetaText processes a file it identifies directives and replaces
     them with the result of whatever magical process the directive
     represents (e.g. file contents for an INCLUDE, variable value for a
     SUBST, etc).  Anything outside the directive, including newline
     characters, are left intact.  Where a directive is defined that has
     no corresponding output (DEFINE, for example, which silently sets a
     variable value), the trailing newline characters can leave large
     tracts of blank lines in the output documents.

     For example:

          line 1
          %% DEFINE f="foo" %%
          %% DEFINE b="bar" %%
          line 2

     Produces the following output:

          line 1

          line 2

     This happens because the newline characters at the end of the second
     and third lines are left intact in the output text.

     Setting CHOMP to any true value will remove any newline characters
     that appear *immediately after* a MetaText directive.  Any characters
     coming between the directive and the newline, including whitespace,
     will override this behaviour and cause the intervening characters and
     newline to be output intact.

     With CHOMP set, the following example demonstrates the behaviour:

          line 1
          %% DEFINE f="foo" %%
          %% DEFINE b="bar" %%<space>
          line 2

     Produces the following output (Note that "<space>" is intended to
     represent a single space character, not the string "<space>" itself,
     although the effect would be identical):

          line 1
          <space>
          line 2

TRIM
     The TRIM configuration parameter, when set to any true value, causes
     the leading and trailing newlines (if present) within a defined BLOCK
     to be deleted.  This behaviour is enabled by default.  The following
     block definition:

          %% BLOCK camel %%
          The eye of the needle
          %% ENDBLOCK %%

     would define the block as "The eye of the needle" rather than "\nThe
     eye of the needle\n".  With TRIM set to 0, the newlines are left
     intact.

     It is possible to override the TRIM behaviour by specifying the trim
     value as a parameter in a BLOCK definition directive:

          %% BLOCK trim %%
          ...content...
          %% ENDBLOCK %%

     or conversely:

          %% BLOCK trim=0 %%
          ...content...
          %% ENDBLOCK %%

FILTER
     There may be times when you may want to INCLUDE a file or element in a
     document but want to filter the contents in some way.  You may wish
     to escape (i.e. prefix with a backslash '\') certain characters such
     as quotes, search for certain text and replace with an alternative
     phrase, or perform some other post-processing task.  The FILTER option
     allows you to define one or more code blocks that can be called as
     filter functions from an INCLUDE directive.  Each code block is given
     a unique name to identify it and may have calling parameters
     (parenthesised and separated by commas) that can be specified as part
     of the directive.  e.g.

          %% INCLUDE foo filter="slurp(prm1, prm2, ...)" %%

     Two default filters are pre-defined: escape() and sr().  escape()
     takes as a parameter a perl-like regular expression pattern that
     indicates characters that should be 'escaped' (i.e. prefixed by a
     backslash '\') in the text.  For example, to escape any of the
     character class `["'\]' you would specify the filter as:

          %% INCLUDE foo filter="escape([\"'\\])" %%

     The second filter, sr(), takes two arguments, a search string and a
     replace string.  A simple substitution is made on the included text.
     e.g.

          %% INCLUDE foo filter="sr(spam, \"processed meat\")" %%

     Note that quotes and other special metacharacters should be escaped
     within the filter string as shown in the two examples above.

     Additional filters can be specified by passing a reference to a hash
     array that contains the name of the filter and the code itself in
     each key/value pair.  Your filter function should be designed to
     accept the name of the function as the first parameter, followed by a
     line of text to be processed.  Any additional parameters specified in
     the INCLUDE directive follow.  The filter function is called for each
     line of an INCLUDE block and should return the modified text.

     Example:

          my $mt = Text::MetaText->new( {
              FILTER => {
                  'xyzzy' => sub {
                       my ($filtername, $text, @params) = @_;
                       $text = # do something here...
          		 $text;  # return modified text
                  }
              }
          } );

          %% INCLUDE file1 filter="xyzzy(...)" %%

     A new FILTER definition will replace any existing filter with the
     same name.

EXECUTE
     The SUBST directive performs a simple substitution for the value of
     the named variable.  In the example shown below, the entire
     directive, including the surrounding 'magic' tokens '%%', is replaced
     with the value of the variable 'foo':

          %% SUBST foo %%  (or more succinctly, %% foo %%)

     If the named variable has not been defined, MetaText can interpret the
     variable as the name of an object method in the current class or as a
     function in the main package.

     If the EXECUTE flag is set to any true value, the MetaText processor
     will interpret the variable as an object method and attempt to apply
     it to its own object instance (i.e. $self->$method(...)).  If the
     method is not defined, the processor fails quietly (but see ROGUE
     below to see what can happens next).  This allows classes to be
     derived from MetaText that implement methods that can be called (when
     EXECUTE == 1) as follows:

          %% method1 ... %%       # calls $self->method1(...);
          %% method2 ... %%       # calls $self->method2(...);

     The text returned from the method is used as a replacement value for
     the directive.

     The following pseudo-code example demonstrates this:

          package MyMetaText;
          @ISA = qw( Text::MetaText );

          sub foo { "This is method 'foo'" }  # simple return string
          sub bar { "This is method 'bar'" }  # "        "         "

          package main;

          my $mt = MyMetaText->new( { EXECUTE => 1 } );
          print $mt->process("myfile");

     which, for the file 'myfile':

          %% foo %%
          %% bar %%

     generates the following output:

          This is method 'foo'
          This is method 'bar'

     If the EXECUTE flag is set to a value > 1 and the variable name does
     not correspond to a class method, the processor tries to interpret the
     variable as a function in the main package.  Like the example above,
     the processor fails silently if the function is not defined (but see
     ROGUE below).

     The following pseudo-code extract demonstrates this:

          my $mt = Text::MetaText->new( { EXECUTE => 2 } );
          print $mt->processs("myfile");

          sub foo { "This is function 'foo'" }  # simple return string
          sub bar { "This is function 'bar'" }  # "        "         "

          which, for the file 'myfile':

          %% foo %%
          %% bar %%

     generates the following output:

          This is function 'foo'
          This is function 'bar'

     Any additional parameters specified in the directive are passed to the
     class method or function as a hash array reference.  The original
     parameter string is also passed.  Note that the first parameter
     passed to class methods is the MetaText (or derivative) object
     reference itself.

     Example:

          %% foo name="Seuss" title="Dr" %%

     causes the equivalent of (when EXECUTE is any true value):

          $self->foo(                                  # implicit $self ref
          	{ 'name' => 'Seuss', 'title' => 'Dr' },  # hash ref of params
          	  'name="Seuss" title="Dr"' );           # parameter string

     and/or (when EXECUTE > 1):

          &main::foo(
          	{ 'name' => 'Seuss', 'title' => 'Dr' },  # hash ref of params
          	  'name="Seuss" title="Dr"' );           # parameter string

ROGUE
     This configuration item determines how MetaText behaves when it
     encounters a directive it does not recognise.  The ROGUE option may
     contain one or more of the ROGUE keywords separated by any non-word
     character.  The keywords and their associated meanings are:

          warn    Issue a warning (via the ERROR function, if
                  specified) when the directive is encountered.

          delete  Delete any unrecognised directives.

     The default behaviour is to silently leave any unrecognised directive
     in the processed text.

     Example:

          my $mt = Text::MetaText->new( { ROGUE => "delete,warn" } );

DELIMITER
     The DELIMITER item specifies the character or character sequence that
     is used to delimit lists of data.  This is used, for example, by the
     "in" operator which can be used in evaluation conditions.  e.g.

          %% INCLUDE hardenuf if="uid in abw,wrigley" %%

     In this case, the condition evaluates true if the uid variable
     contains the value "abw" or "wrigley".  The default delimiter
     character is a comma.

     The example:

          my $mt = Text::MetaText->new( { DELIMITER => ":" } );

     would thus correctly process:

          %% INCLUDE hardenuf if="uid in abw:wrigley" %%

ERROR
     The ERROR configuration item allows an alternative error reporting
     function to be specified for error handling.  The function should
     expect a printf() like calling convention.

     Example:

          my $mt = Text::MetaText->new( {
              ERROR => sub {
                  my ($format, @params) = @_;
                  printf(STDERR "ERROR: $format", @params);
              }
          } );

DEBUG
     The DEBUG item allows an alternative debug function to be provided.
     The function should expect a printf() like calling convention, as per
     the ERROR option described above.  The default DEBUG function sends
     debug messages to STDERR, prefixed by a debug string: 'D> '.

DEBUGLEVEL
     The DEBUGLEVEL item specifies which, if any, of the debug messages are
     displayed during the operation of the MetaText object.  Like the ROGUE
     option described above, the DEBUGLEVEL value should be constructed
     from one or more of the following keywords:

          none      no debugging information (default)
          info      general processing information
          config    MetaText object configuration items
          preproc   pre-processing phase
          process   processing phase
          postproc  post-processing phase
          data      additional data parameters in debug messages
          content   content of pre-processed INCLUDE blocks
          function  list functions calls as executed
          evaluate  trace conditional evaluations
          test      used for any temporary test code
          all       all of the above (excluding "none", obviously)

     Example:

          my $mt = Text::MetaText->new( {
          	DEBUGLEVEL => "preproc,process,data"
          } );

MAXDEPTH
     It is possible for MetaText to become stuck in an endless loop if a
     circular dependancy exists between one or more files.  For example:

          foo:
              %% INCLUDE bar %%

          bar:
              %% INCLUDE foo %%

     To detect and avoid such conditions, MetaText allows files to be
     nested up to MAXDEPTH times.  By default, this value is 32.  If you
     are processing a file which has nested INCLUDE directives to a depth
     greater than 32 and MetaText returns with a "Maximum recursion
     exceeded" warning, set this confiuration item to a higher value.  e.g.

          my $mt = Text::MetaText->new( { MAXDEPTH => 42 } );

PROCESSING TEXT FILES AND STRINGS
=================================

   The MetaText methods for processing text files and strings are:

     process_file($file, ...);
     process_text($text, ...);

   The process() method is also supported for backward compatibility with
older versions of MetaText.  The process() method simply calls
process_file(), passing all arguments to it.

   The process_file() method processes a text file interpreting any
MetaText directives embedded within it.  The first parameter should be the
name of the file which  should reside in the current working directory or
in one of the directories specified in the LIB configuration option.  A
filename starting with a slash '/' or a period '.' is considered to be an
absolute path or a path relative to the current working directory,
respectively.  In these cases, the LIB path is not searched.  The optional
second parameter may be a reference to a hash array containing a number of
variable/value definitions that should be pre-defined when processing the
file.

     print $mt->process_file("somefile", { name => "Fred" });

   If "somefile" contains:

     Hello %% name %%

   then the output generated would be:

     Hello Fred

   Pre-defining variables in this way is equivalent to using the DEFINE
directive (described below) at the start of the INCLUDE file

     %% DEFINE name="Fred" %%
     Hello %% name %%

   The process_file() function will continue until it reaches the end of
the file or a line containing the pattern "__END__" or "__MTEND__" by
itself ("END" or "MTEND" enclosed by double underscores, no other
characters or whitespace on the line).

   Note that the pre-processor (a private method which is called by
process(), so feel free to forget all about it) *does* scan past any
__END__ or __MTEND__ marker.  In practice, that means you can define
blocks after, but use them before, the terminating  marker. e.g.

     Martin, %% INCLUDE taunt %%

     __MTEND__               << processor stops here and ignores
                                everything following
     %% BLOCK taunt %%       << but the pre-processor has correctly
     you Camper!                continued and parsed this block so that
     %% ENDBLOCK %%             it can be included in the main body

   produces the output:

     Martin, you Camper!

   The process_file() function returns a string containing the processed
file or block output.  On error, a warning is generated (see `USING THE
METATEXT MODULE' in this node) and undef is returned.

     my $output = $mt->process_file("myfile");
     print $output if defined $output;

   The process_text() method is identical to process_file() except that the
first parameter should represent a text string to be processed rather than
the name of a file.  All other parameters, behaviour and return values are
the same as for process_file().

     my $text   = "%% INCLUDE header %% test! %% INCLUDE footer %%";
     my $output = $mt->process_text($text);
     print $output if defined $output;

METATEXT DIRECTIVES
===================

   A MetaText directive is a block of text in a file that is enclosed by
the MAGIC identifiers (by default '%%').  A directive may span multiple
lines and may include blank lines within in.  Whitespace within a
directive is generally ignored except where quoted as part of a specific
value.

     %% DEFINE
        name    = Yorick
        age     = 30
        comment = "A fellow of infinite jest"
     %%

   The first word of the directive indicates the directive type.
Directives may be specified in upper, lower or mixed case, irrespective of
the CASE sensitivity flag (which affects only variable names).  The general
convention is to specify the directive type in UPPER CASE to aid clarity.

   The MetaText directives are:

DEFINE
     Define the values for one or more variables

SUBST
     Substitute the value of a named variable

INCLUDE
     Process and include the contents of the named file or block

BLOCK
     Define a named block which can be subsequently INCLUDE'd

ENDBLOCK
     Marks the end of a BLOCK definition

   To improve clarity and reduce excessive, unnecessary and altogether
undesirable verbosity, a directive block that doesn't start with a
recognised MetaText directive is assumed to be a 'SUBST' variable
substitution.  Thus,

     %% SUBST foo %%

   can be written more succinctly as

     %% foo %%

   When MetaText processes directives, it is effectively performing a
"search and replace".  The MetaText directive block is replaced with
whatever text is appropriate for the directive specified.  Generally
speaking, MetaText does not alter any text content or formatting outside of
directive blocks.  The only exception to this rule is when CHOMP is turned
on (see `USING THE METATEXT MODULE' in this node) and newlines immediately
following a directive are subsequently deleted.

DEFINE
------

   The DEFINE directive allows simple variables to be assigned values.
Multiple variables may be defined in a single DEFINE directive.

     %% DEFINE
        name  = Caliban
        quote = "that, when I waked, I cried to dream again."
     %%

   It is also possible to use other variable values to DEFINE new
variables.  Use the '$' prefix to indicate a variable rather than an
absolute value.  If necessary, surround the variable name with braces '{'
'}' to separate it from any surrounding text.

     %% DEFINE
        server = www.kfs.org
        home   = /~abw/
     %%

     %% DEFINE
        homepage = http://$server${home}index.html
     %%

   In the above example, the 'homepage' variable adopts the value
'http://www.kfs.org/~abw/index.html' which is constructed from the text
string 'http://' and 'index.html' and the values for $server and $home.
Notice how the 'home' variable is enclosed in braces.  Without these, the
homepage variable would not be constructed correctly, looking instead for
a variable called 'homeindex.html'

     %% DEFINE
        homepage = http://$server$homeindex.html   ## WRONG!
     %%

   See `  ' in this node below for further information.

   Variables defined within a file or passed to the process_file() or
process_text() functions as a hash array remain defined until the file or
block is processed in entirety.  Variable values will be inherited by any
nested files or blocks INCLUDE'd into the file.  Re-definitions of
existing variables will persist within the file or block, masking any
existing values, until the end of the file or block when the previous
values will be restored.

   The following example illustrates this:

     foo:
         Hello %% name %%              # name assumes any predefined value
         %% DEFINE name=tom %%
     	Hello %% name %%              # name = 'tom'
         %% INCLUDE bar name='dick' %% # name = 'dick' for "INCLUDE bar"
     	Hello %% name %%              # name = 'tom'

     bar:
     	Hello %% name %%              # name = 'dick'
         %% DEFINE name='harry' %%     # name = 'harry'
         Hello %% name %%

   Processing the file 'foo' as follows:

     print $mt->process_file('foo', { 'name' => 'nobody' });

   produces the following output (with explanatory comments added for
clarity):

     Hello nobody                      # value from process() hash
     Hello tom                         # from foo
     Hello dick                        # from bar
     Hello harry                       # re-defined in bar
     Hello tom                         # restored to previous value in foo

SUBST
-----

   A SUBST directive performs a simple variable substitution.  If the
variable is defined, its value will be inserted in place of the directive.

   Example:

     %% DEFINE place = World %%
     Hello %% SUBST place %%!

   generates the following output:

     Hello World!

   The SUBST keyword can be omitted for brevity.  Thus "%% place %%" is
processed identically to "%% SUBST place %%".

   If the variable is undefined, the MetaText processor will, according to
the value of the EXECUTE configuration value, try to execute a class
method or a function in the main package with the same name as the SUBST
variable.  If EXECUTE is set to any true value, the processor will try to
make a corresponding method call for the current object (that is, the
current instantiation of the MetaText or derived class).  If no such
method exists and EXECUTE is set to any value greater than 1, the
processor will then try to execute a function in the main package with the
same name as the SUBST variable  In either case, the text returned from
the method or function is included into the current block in place of the
SUBST directive (non-text values are automatically coerced to text
strings).  If neither a variable, method or function exists, the SUBST
directive will either be deleted or left intact (and additionally, a
warning may be issued), depending on the value of the ROGUE configuration
item.

   See EXTENDING METATEXT below for more information on deriving MetaText
classes and using EXECUTE to extend the meta-language.

   The "format" and "filter" options as described in the INCLUDE section
below are applied to the processed SUBST result before being inserted back
into the document.

   Some MetaText variables have a special meaning.  Unless specifically
defined otherwise, the variable(s) listed below generate the following
output:

     TIME    The current system time in seconds since the epoch,
             00:00:00 Jan 1 1970.  Use the "format" option to
             specify a time/date format.

INCLUDE
-------

   The INCLUDE directive instructs MetaText to load and process the
contents of the file or block specified.  If the target is a file, it
should reside in the current directory or a directory specified in the LIB
configuration variable.  Alternatively, the target may be a text block
specified with BLOCK..ENDBLOCK directives (see below).

     %% INCLUDE chapter1 %%

   The target may also be a variable name and should be prefixed with a
'$' to identify it as such.  On evaluation, the value of the named
variable will be used as the target:

   Example:

     %% DEFINE chapter=ch1 %%
     %% INCLUDE $chapter   %%

     is equivalent to:

     %% INCLUDE ch1 %%

   Additional variables may be defined for substitution within the file:

     %% INCLUDE chapter2 bgcolor=#ffffff title="Chapter 2" %%

   The contents of the file "chapter2":

     <html><head><title>%%title%%</title></head>
     <body bgcolor="%% bgcolor %%">
       ...
     </body>

   would produce the output:

     <html><head><title>Chapter 2</title></head>
     <body bgcolor="#ffffff">
       ...
     </body>

   Defining variables in this way is equivalent to using the DEFINE
directive.  Variables remain in scope for the lifetime of the file being
processed and then revert to any previously defined values (or undefined).
Any additional files processed via further INCLUDE directives within the
file will also inherit any defined variable values.

   Example:

     %% INCLUDE file1 name="World" %%

   for the files:

     file1:                   # name => "World" from INCLUDE directive
         %% INCLUDE file2 %%

     file2:                   # inherits "name" variable from file1
         %% INCLUDE file3 %%

     file3:                   # inherits "name" variable from file2
         Hello %% name %%

   produces the output:

     Hello World

   The output generated by INCLUDE and SUBST directives can be formatted
using a printf-like template.  The format string should be specified as a
"format" option in the INCLUDE or SUBST directive.  Each line of the
included text is formatted and concatentated to create the final output.
Within the format string, '%s' is used to represent the text.

   For example, the 'author' element below could be used to display details
of the author of the current document.

     author:
         File:   %% file %%
         Author: %% name %%
     	Date:   %% date %%

   For inclusion in an HTML document, the text can be encapsulated in HTML
comment tags ("<!-" and "->") using a format string:

     %% INCLUDE author
        file   = index.html
        name   = "Andy Wardley"
        date   = 19-Mar-1987
        format = "<!-- %-12s -->"
     %%

   Which produces the following output:

     <!-- File:   index.html   -->
     <!-- Author: Andy Wardley -->
     <!-- Date:   19-Mar-1987  -->

   Note that the print format is applied to each line of the included
text.  To encapsulate the element as a whole, simply apply the formatting
outside of the INCLUDE directive:

     <!--
        %% INCLUDE author
        ...
        %%
     -->

   In these examples, the formatting is applied as if the replacement
value/line is a character string.  Any of the standard printf(3) format
tokens can be used to coerce the value into a specific type.

   There are a number of pre-defined format types:

     dquoted      # encloses each line in double quotes: "like this"
     squoted      # encloses each line in single quotes: 'like this'
     quoted       # same as "dquoted"

   Examples:

     %% some_quote format=quoted %%

   As mentioned in the SUBST section above, the TIME variable is used to
represent the current system time in seconds since the epoch (see time(2)).
The "format" option can also be employed to represent such values in a more
user-friendly format.  Any format string that does not contain a '%s'
token is assumed to be a time-based value and is formatted using the
time2str() function from the Date::Format module (distributed as part of
the TimeDate package).

   Example:

     The date is %% TIME format="%d-%b-%y" %%

   Generates:

     The date is 19-Mar-98

   See `perldoc Date::Format' for information on the formatting characters
available.

   The pragmatic token '%P' can be added to a format to override this
behaviour and force the use of printf().  The '%P' token is otherwise
ignored.

   Example:

     %% DEFINE foo=123456789  %%
     %% foo format="%d-%b-%y" %%  # "day-month-year" using time2str
     %% foo format="%d"       %%  # "day" using timestr
     %% foo format="%P%d"     %%  # decimal value using printf
     %% foo format="%s"       %%  # string value using printf

     Generates:

     29-Nov-73
     29
     123456789
     123456789

   Text that is inserted with an INCLUDE or SUBST directive can also be
filtered.  There are two default filters provided, 'escape' which can be
used to escape (prefix with a backslash '\') certain characters, and 'sr'
which is used to perform simple search and replace actions.  Other filters
may be added with the FILTER option when creating the object (see the
FILTER section in `USING THE METATEXT MODULE' in this node, above).

   Like the 'format' option, output filters work on a line of text at a
time.  Any parameters required for the filter can be specified in
parentheses after the filter name.  The 'escape' filter expects a
perl-style character class indicating the characters to escape.  The 'sr'
filter expects two parameters, a search pattern and a replacement string,
separated by a comma.  Note that parameters that include embedded spaces
should be quoted.  The quote characters themselves must also be escaped as
they already form part of a quoted string (the filter text).  (This way of
representing parameters is admittedly far from ideal and may be improved
in a future version.)

   Example:

     %% DEFINE text="Madam I'm Adam" %%
     %% SUBST  text filter="escape(['])"               %%
     %% SUBST  text filter="sr(Adam, \"Frank Bough\")" %%

   Generates:

     Madam I\'m Adam
     Madam I'm Frank Bough

   Conditional tests can be applied to INCLUDE blocks to determine if the
block should evaluated or ignored.  Variables and absolute values can be
used and can be evaluated in the following ways:

     a == b       # a is equal to b
     a != b       # a is not equal to b
     a >  b       # a is greater than b
     a <  b       # a is less than b
     a => b       # a is greater than or equal to b
     a <= b       # a is less than or equal to b
     a =~ b       # a matches the perl regex pattern b
     a !~ b       # a does not match the perl regex pattern b
     a in b,c,d   # a appears in the list b, c, d (see DELIMITER)

   The items on the right of the evaluations can be absolute values or
variable names which should be prefixed by a '$'.  The items on the left
of the evaluation are assumed to be variable names.  There is no need to
prefix these with a '$', but you can if you choose.

   The single equality, "a = b", is treated identically to a double
equality "a == b" although the two traditionally represent different
things (the first, an assignment, the second, a comparison).  In this
context, I consider the former usage confusing and would recommend use of
the latter at all times.

   Variables without any comparison operator or operand are tested for a
true/false value.

   Examples:

     %% INCLUDE foo if="name==fred"        %%
     %% INCLUDE foo if="$name==fred"       %%  # equivalent to above
     %% INCLUDE foo if="name==$goodguy"    %%
     %% INCLUDE foo if="hour > 10"         %%
     %% INCLUDE foo if="tonk =~ [Ss]pl?at" %%
     %% INCLUDE foo if="camper"            %%

   Multiple conditions can be joined using the following boolean operators

     a && b       # condition 'a' and 'b'
     a || b       # condition 'a' or  'b'
     a ^  b       # condition 'a' xor 'b'
     a and b      # same as "a && b" but with lower precedence
     a or  b      # same as "a || b" but with lower precedence
     a xor b      # same as "a ^  b" but with lower precedence

   Conditional equations are evaluated left to right and may include
parentheses to explicitly set precedence.

   Examples:

     %% INCLUDE tonk
        if="hardenuf && uid in abw,wrigley"
     %%
     %% INCLUDE tapestry
        if="(girly && studly < 1) || uid == neilb"
     %%
     %% INCLUDE tapestry
        if="($girly && $studly < 1) || $uid == neilb"
     %%

   Note that the third example above is identical in meaning to the second,
but explicitly prefixes variable names with '$'.  This is optional for
elements on the left hand side of comparison operators, but mandatory for
those on the right that might otherwise be interpreted as absolute values.

BLOCK..ENDBLOCK
---------------

   In some cases it is desirable to have a block of text available to be
inserted via INCLUDE without having to define it in an external file.  The
BLOCK..ENDBLOCK directives allow this.

   A BLOCK directive with a unique identifier marks the start of a block
definition.  The block continues, including any valid MetaText directives,
until an ENDBLOCK directive is found.

   A BLOCK..ENDBLOCK definition may appear anywhere in the file.  It is in
fact possible to INCLUDE the block before it has been defined as long as
the block definition resides in the same file.

   Processing of a file stops when it encounters an __END__ or __MTEND__
marker on a line by itself.  Blocks can be defined after this marker even
though the contents of the file after the marker are ignored by the
processor.

     # include a block defined later
     %% INCLUDE greeting name=Prospero %%

     __END__
     %% BLOCK greeting %%
     Hello %% name %%
     %% ENDBLOCK %%

   This produces the following output:

     # include a block defined later
     Hello Prospero

   Additional variable definitions specified in an INCLUDE directive will
be applied to blocks just as they would to external files.

   By default, BLOCK definitions are "trimmed".  That is, the leading and
trailing newlines (if present) in the block definition are deleted.  This
allows blocks to be defined:

     %% BLOCK example1 %%
     Like this!
     %% ENDBLOCK %%

   and not:

     %% BLOCK example2 %%Like this!%% ENDBLOCK %%

   This behaviour can be disabled by specifying a TRIM configuration
parameter with a zero value.  See the TRIM option, mentioned above.  A
"trim" or "trim=0" parameter can be added to a block to override the
behaviour for that BLOCK definition only.  e.g.

     %% BLOCK sig trim=0 %%
     --
     This is my .signature
     %% ENDBLOCK %%

   A BLOCK..ENDBLOCK definition that appears in the main part of a document
(i.e. before, or in the absence of an __END__ line) will not appear in the
processed output.  A simple "print" flag added to the BLOCK directive
overrides this behaviour, causing a copy of the BLOCK to appear in it's
place:

     %% DEFINE name=Caliban %%

     %% BLOCK greeting print %%
     Hello %% name %%
     %% ENDBLOCK %%

     %% INCLUDE greeting name="Prospero" %%

   produces the following output:

     Hello Caliban

     Hello Prospero

   Conditions ("if" and "unless") can be applied to BLOCK directives, but
they affect how and when the BLOCK itself is printed, rather than
determining if the block gets defined or not.  Conditionals have no effect
on BLOCK directives that do not include a "print" flag.

   It is possible to pre-declare blocks for subsequent inclusion by using
the public declare() method.  The first parameter should be a text string
containing the content of the block.  The second paramter is the block
name by which it should consequently be known.  The content string is
parsed and an internal block definition is stored.

   Example:

     $mt->declare("<title>%%title%%</title>", html_title);

   This can subsequently be used as if the block was defined in any other
way:

     %% INCLUDE html_title
        title = "My test page"
     %%

   It is also possible to pass an array reference to declare() as the
content parameter.  In this context, it is assumed that the array is a
pre-parsed list of text strings or Text::MetaText::Directive (or
derivative) references which should be installed as the block definition
for the named block.  This process assumes an understanding of the
MetaText directive structure and internal symbol table entries.  If you
don't know why you would want to do this, then the chances are that you
don't need to do it.  "Experts only" in other words.

VARIABLE INTERPOLATION
======================

   MetaText allows variable values to be interpolated into directive
operands and other variable values.  This is useful for style-sheet
processing and other applications where a particular view required can be
encoded in a variable and interpolated by the processor.

   By example, the file 'mousey.html':

     %% INCLUDE $style/header %%

     The cat sat on the mouse.

     %% INCLUDE $style/footer %%

   can be processed in the following ways to create customised output:

     $t1 = $mt->process_file('mousey.html', {'style' => 'text'});
     $t2 = $mt->process_file('mousey.html', {'style' => 'graphics'});

   Variable interpolation is also useful for building up complex variables
based on sub-elements:

     %% DEFINE root=/user/abw %%

     %% DEFINE
        docs   = $root/docs
        images = $root/images
     %%

   Note though, that there is no guaranteed order of definition for
multiple variables within a single DEFINE directive.  The following is
INCORRECT as there is no guarantee that 'base' will be defined before
'complex'.

     %% DEFINE
        base    = /here
        complex = $base/and/there    # WRONG! $base may not be defined yet
     %%

   In such circumstances, it is necessary to define variables in separate
directives.

     %% DEFINE base=/here %%
     %% DEFINE complex=$base/and/there %%

   Where necessary, variable names may be enclosed in braces to delimit
them from surrounding text:

     %% DEFINE
        homepage = http://$server${home}index.html
     %%

EXTENDING METATEXT
==================

   MetaText may be used as a base class for deriving other text processing
modules.  Any member function of a derived class can be called directly as
a MetaText directive.  See the EXECUTE configuration option for more
details.

   Pseudo-code example:

     package MyMetaText;
     @ISA = qw( Text::MetaText );

     # define a new derived class method, get_name()
     sub get_name {
         my $self   = shift;
         my $params = shift;

     # return name from an ID hash, for example
     	$self->{ PEOPLE }->{ $params->{'id'} } || 'nobody';
         }

     package main;

     # use the new derived class
     my $mmt = MyMetaText { EXECUTE => 1 };

     # process 'myfile'
     print $mmt->process('myfile');

   which, for a sample file, 'myfile':

     %% get_name id=foo %%
     %% get_name id=bar %%

   is equivalent to:

     print $mmt->get_name({ 'id' => 'foo' }), "\n";
     print $mmt->get_name({ 'id' => 'bar' }), "\n";

   Alternatively, a simple calling script can be written that defines
functions that themselves can be called from within a document:

     my $mt = Text::MetaText->new( { EXECUTE => 2 } );

     print $mt->process("myfile");

     sub get_name {
         my $params = shift;
         $global_people->{ $params->{'id'} } || 'nobody';
     }

WARNINGS AND ERRORS
===================

   The following list indicates warning or error messages that MetaText can
generate and their associated meanings.

"CASEVARS option expects an array reference"
     The configuration hash array passed to Text::MetaText->new() contained
     a CASEVARS entry that did not contain an array reference.  See `USING
     THE METATEXT MODULE' in this node.

"Closing directive tag missing in %s"
     A MetaText directive was found that was not terminated before the end
     of the file.  e.g. `%% INCLUDE something ...'  The processor attempts
     to compensate, but check your source files and add any missing MAGIC
     tokens.

"Directive constructor failed: %s"
     The MetaText parser detected a failed attempt to construct a Directive
     object.  This error should only happen in cases where a derived
     Directive class has been used (which should imply you know what you're
     doing and what the error means.  The specific Directive constructor
     error is appended to the error message.

"Invalid configuration parameter: %s"
     An invalid configuration parameter was identified in the hash array
     passed to Text::MetaText->new().  See `USING THE METATEXT MODULE' in
     this node.

"Invalid debug/error function"
     The debug or error handling routine specified for the ERROR or DEBUG
     configuration options was not a code reference.  See the ERROR and/or
     DEBUG sections for more details.

"Invalid debug option: %s"
     A token was specified for the DEBUGLEVEL configuration item which was
     invalid.  See the DEBUGLEVEL section for a complete list of valid
     tokens.

"Invalid factory object"
     A `FACTORY' configuration item was specified which did not contain a
     reference to a Text::MetaText::Factory object, or derivative.

"Invalid input reference passed to declare()"
     The declare() method was called and the first parameter was not a
     reference to an ARRAY or a text string.  These are (currently) the
     only two valid input types.

"Invalid rogue option: %s"
     A token was specified for the ROGUE configuration item which was
     invalid.  See the ROGUE section for a complete list of valid tokens.

"Maximum recursion exceeded"
     The processed file had multiple INCLUDE directives that nested to a
     depth greater than MAXDEPTH (default: 32).  Set MAXDEPTH higher to
     avoid this problem, or check your files for circular dependencies.

"Missing directive keyword"
     A MetaText directive was identified that had no keyword or other
     content.  e.g. `%%    %%'

"Parse error at %s line %s: %s"
     The pre-processor was unable to correctly parse a block or file.  The
     error message reports the file name and line number (or 'text string'
     in the case of parse_text()) and the specific error details.

"Text::MetaText->new expects a hash array reference"
     The new() method can accept a reference to a hash array as the first
     parameter which contains configuration variables and values.  This
     error is generated if the parameter is not a hash array reference.

"Unrecognise directive: %s"
     An internal error that should never happen.  The pre-processor has
     identified a directive type that the processor then failed to
     recognise.

"Unrecognised token: %s"
     A `%% SUBST <variable> %%' or `%% <variable> %%' directive was found
     for which there was no corresponding <variable> defined.  This
     warning is only generated when the 'warn' token is set for the ROGUE
     option.

"Unmatched parenthesis: %s"
     A conditional evaluation ("if" or "unless") for a directive is missing
     a closing parenthesis.  e.g. `%% INCLUDE foobar if="(foo && bar ||
     baz" %%'

"%s: non-existant or invalid filter"
     An INCLUDE or SUBST directive included a "filter" option that refers
     to a non-existant filter.  e.g. `%% INCLUDE foo filter=nosuchfilter()
     %%'

"%s: no such block defined"
     The _process($symbol) method could not process the named symbol
     because it was not defined in the symbol table.

AUTHOR
======

   Andy Wardley <abw@kfs.org>

   See also:

     http://www.kfs.org/~abw/

   My thanks extend to the people who have used and tested MetaText.  In
particular, the members of the Peritas Online team; Simon Matthews, Simon
Millns and Gareth Scott; who brutally tested the software over a period of
many months and provided valuable feedback, ideas and of course, bug
reports.  Deep respect is also due to the members of the SAS Team at Canon
Research Centre Europe Ltd; Tim "TimNix" O'Donoghue, Neil "NeilOS" Bowers,
Ave "AveSki" Wrigley, Martin "MarTeX" Portman, Channing "Chango" Walton and
Gareth "Gazola" Rees.  Don't go changing now...  :-)

   I welcome bug reports, enhancement suggestions, comments, criticisms
(hopefully constructive) and patches related to MetaText.  I would
appreciate hearing from you if you find MetaText particularly useful or
indeed if it *doesn't* do what you want, for whatever reason.  Hopefully
this will help me make MetaText help you more.

   It pains me to say that MetaText comes without guarantee or warranty of
suitability for any purpose whatsoever.  That doesn't mean it doesn't do
anything good, but just that I don't want some scrupulous old git to sue me
because they thought I implied it did something it doesn't.  *<sigh>*

   Text::MetaText is based on a template processing language I developed
while working at Peritas Ltd.  I am indebted to Peritas for allowing me to
use this work as the basis for MetaText and to release it to the public
domain.  I am also pleased to note that Canon Research Centre Europe
supports the Perl community and the Free Software ideology in general.

REVISION
========

   $Revision: 0.22 $

COPYRIGHT
=========

   Copyright (c) 1996-1998 Andy Wardley.  All Rights Reserved.

   This program is free software; you can redistribute it and/or modify it
under the terms of the Perl Artistic License.

SEE ALSO
========

   For more information, see the accompanying documentation and support
files:

     README    Text based version of this module documentation.
     Changes   Somewhat verbose list of per-version changes.
     Todo      Known bugs and possible future enhancements.
     Features  A summary of MetaText features and brief comparison to
               other perl 'template' modules.

   For information about the *metapage* utility, consult the specific
documentation:

     perldoc metapage
       or
     man metapage

     For more information about the author and other Perl development work:

     http://www.kfs.org/~abw/
     http://www.kfs.org/~abw/perl/
     http://www.cre.canon.co.uk/perl/

   For more information about Perl in general:

     http://www.perl.com/

MetaText Directive object class.
********************************

NAME
====

   Text::MetaText::Directive - MetaText Directive object class.

SYNOPSIS
========

     use Text::MetaText::Directive;
     my $directive = Text::MetaText::Directive->new(\%params);

DESCRIPTION
===========

   Objects of the Text::MetaText::Directive class are instantiated by the
Text::MetaText::Factory class from within the Text::MetaText module.  The
Factory and Directive classes can be sub-classed to create a more specific
processing system.

AUTHOR
======

   Andy Wardley <abw@kfs.org>

   See also:

     http://www.kfs.org/~abw/

REVISION
========

   $Revision: 0.4 $

COPYRIGHT
=========

   Copyright (c) 1996-1998 Andy Wardley.  All Rights Reserved.

   This program is free software; you can redistribute it and/or modify it
under the terms of the Perl Artistic License.

SEE ALSO
========

   For more information, see the main Text::MetaText documentation:

     perldoc Text::MetaText

     For more information about the author and other Perl development work:

     http://www.kfs.org/~abw/
     http://www.kfs.org/~abw/perl/
     http://www.cre.canon.co.uk/perl/

   For more information about Perl in general:

     http://www.perl.com/

Factory class for instatiating Directive objects.
*************************************************

NAME
====

   Text::MetaText::Factory - Factory class for instatiating Directive
objects.

SYNOPSIS
========

     use Text::MetaText::Factory;
     my $factory = Text::MetaText::Factory->new(\%cfg);

DESCRIPTION
===========

   The Text::MetaText::Factory module is used by Text::MetaText to
instantiate Text::MetaText::Directive objects.  The Factory and Directive
classes can be sub-classed to create a more specific processing system.

AUTHOR
======

   Andy Wardley <abw@kfs.org>

   See also:

     http://www.kfs.org/~abw/

REVISION
========

   $Revision: 0.2 $

COPYRIGHT
=========

   Copyright (c) 1996-1998 Andy Wardley.  All Rights Reserved.

   This program is free software; you can redistribute it and/or modify it
under the terms of the Perl Artistic License.

SEE ALSO
========

   For more information, see the main Text::MetaText documentation:

     perldoc Text::MetaText

     For more information about the author and other Perl development work:

     http://www.kfs.org/~abw/
     http://www.kfs.org/~abw/perl/
     http://www.cre.canon.co.uk/perl/

   For more information about Perl in general:

     http://www.perl.com/

A modern soundex.  Phonetic encoding of words.
**********************************************

NAME
====

   Text::Metaphone - A modern soundex.  Phonetic encoding of words.

SYNOPSIS
========

     use Text::Metaphone;
     $phoned_words = Metaphone('Schwern');

DESCRIPTION
===========

   `Metaphone()' is a function whereby a string/word is broken down into a
rough approximation of its english phonetic pronunciation.  Very similar
in concept and purpose to soundex, but much more comprehensive in its
approach.

FUNCTIONS
=========

Metaphone
          $phoned_word = Metaphone($word, $max_phone_len);

     Takes a word and encodes it according to the Metaphone algorithm.
     The algorithm only deals with alphabetical characters, all else is
     ignored.

     If $max_phone_len is provided, Metaphone will only encode up to that
     many characters for each word.

     'sh' is encoded as 'X', 'th' is encoded as '0'.  This can be changed
     in the metaphone.h header file.

CAVEATS
=======

Metaphone algorithm changes
     I have made a few minor changes to the traditional metaphone
     algorithm found in the books.  The most significant one is that it
     will differenciate between SCH and SCHW making the former K (As in
     School) and the latter sh (as in Schwartz and Schwern).

     My changes can be turned off by defining the USE_TRADITIONAL_METAPHONE
     flag in metaphone.h.

     Due to these changes, any users of Metaphone v1.00 or earlier which
     have stored metaphonetic encodings, they should recalculate those
     with the new verison.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

Man pages
---------

   See Text/Soundex,

Books, Journals and Magazines
-----------------------------

Binstock, Andrew & Rex, John. "Metaphone:  A Modern Soundex." *Practical Algorithms For Programmers.*  Reading, Mass:  Addion-Wesley, 1995  pp160-169
     Contains an explaination of the basic metaphone concept & algorithm
     and C code from which I learned of Metaphone and ported this module.

Parker, Gary. "A Better Phonetic Search." *C Gazette*, Vol. 5, No. 4 (June/July), 1990.
     This is the public-domain C version of metaphone from which Binstock
     & Rex based their own..  I haven't actually read it.

Philips, Lawrence. *Computer Language*, Vol. 7, No. 12 (December), 1990.
     And here's the original Metaphone algorithm as presented in Pick
     BASIC.

COPYRIGHT, et al.
=================

   Copyright (c) 1997-1999 Michael G Schwern.  All Rights Reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

removes vowels from words phrases
*********************************

NAME
====

   Text::Munge::Vowels - removes vowels from words phrases

SYNOPSIS
========

     use Text::Munge::Vowels;

     $obj = new Text::Munge::Vowels();
     $obj->add_stopwords LIST

     $string = $obj->munge LIST

DESCRIPTION
===========

   Text::Munge::Vowels strips vowels spaces from words and phrases to
shorten the length of simple text messages, as might be used for to send
weather forecasts or short news items to alphanumeric pagers with limited
message or screen sizes.

   Note that there's another module on CPAN called *Lingua-EN-Squeeze*
intended for the same purpose.

EXAMPLE
=======

     use Text::Munge::Vowels();

     $munger = new Text::Munge::Vowels();

     $text = "This sentence will have some of it\'s vowels removed.";

     print $munger->munge($text), "\n";

CAVEATS
=======

   Overuse can make messages unreadable. "Decoding" the output of this
module requires a human (?) brain familiar with the language and the
context of the messages.

   Some would argue the use of this module is suspect.

FUTURE ENHANCEMENTS
===================

   Improve the regular expression in *$DefaultMungeRule* to ignore double
or triple vowels in short words.

   Actually, I am working on a separate module which will load specialized
vocabularies from XML files. If this module evolves at all, it will be as
a wrapper to that module.

AUTHOR
======

   Robert Rothenberg <wlkngowl@unix.asb.com>

a simple text wrapping module
*****************************

NAME
====

   *Text::NWrap* - a simple text wrapping module

SYNOPSIS
========

     use Text::NWrap;

     $NWrap::columns = 132;
     NWrap::wrap('    ','',@text);

DESCRIPTION
===========

   *Text::NWrap* is a simple interface to *Text::Format*.  If you want
more functionality just use *Text::Format*.  *Text::NWrap* is meant to
replace Text::Wrap.  Its interface is basically identical to Text::Wrap's.
However, nothing is exported by default and it does not call die under
any circumstance.

wrap $firstIndent, $bodyIndent, @text
     Wrap @text using $firstIndent for the first line's indent and
     $bodyIndent for the indentation of the body of the paragraph.

$columns
     Lets you set the width of the paragraph.  Default is 72 characters
     wide.

EXAMPLE
=======

     use Text::NWrap;

     print NWrap::wrap('','',"hello world this is some silly example",
             "and some more text that should explain the use");

     use Text::NWrap qw(wrap $columns);

     $columns = 20;
     wrap("\t",'',"some text that should be wrapped");

AUTHOR
======

   Gabor Egressy *gabor@vmunix.com*

   Copyright (c) 1998 Gabor Egressy.  All rights reserved.  All wrongs
reversed.  This program is free software; you can redistribute and/or
modify it under the same terms as Perl itself.

Overloaded class for printing numbers
*************************************

NAME
====

   Text::Number - Overloaded class for printing numbers

SYNOPSIS
========

   Provides a facility for transparently configuring numbers to print the
way you want them to.  Calculations are always executed using the full
precision of the number, but printing is rounded to the number of places
of your choosing.

   Extended printing operations are configurable via the format method.

DESCRIPTION
===========

   `use Text::Number;'

   `$allowance = number(value => 5, places => 2)';

   `print STDOUT "My allowance is $allowance dollars."'

   > My allowance is 5.00 dollars.

   `require Text::Number;'

   `$allowance = Text::Number-'new(value => 5, places => 2)>;

   `$allowance += 5000; print "$allowance";'

   > 5005.00

   `$allowance->format(type => 'number'); print "$allowance";'

   > 5,005.00

EXPORTS
=======

   If you import `Text::Number' with the <use> statement, the number
constructor will be imported into your namespace.  If you'd rather not
import this symbol, `require Text::Number' instead and use either `new
Text::Number' or `Text::Number->number' as your constructor.

OPERATORS
=========

   Objects created by this module should function transparently with these
operators:

   `+ - / * "" x ** ++ += -- -= *= /= < > <= >= <=>'

   abs atan2 cos exp log sin sqrt

METHODS
=======

new (synonymous with number)
----------------------------

   `$number = number(6);' (only if you used)

   `$number = new Text::Number(value => 6, places => 0)'

   `$number = Text::Number->number(6)'

places
------

   Returns the display precision of the number.

   `$precision = $number->places'

value
-----

   Returns the real value of the number.

   `$value = $number->value'

format
------

   Use this method to configure the number for more sophisticated printing
option, i.e., anything other than plain old decimal point control.  If you
invoke this method, you need to have Number::Format installed on your
system, as this module is used to generate the formats.  The module is
only loaded at runtime so Text::Number will work without it, except you
won't have access to these formatting options.

   Number::Format is a very useful and feature-rich module.  Please see
the pod for that module for a better description of it capabilities.

   `$success = $number->format(type => number)' inserts commas, or the
local equivalent, into numbers > 1000.  It can also insert the localized
decimal point character.

   `$success = $number->format(type => picture, template => template )'

   Please see the Number::Format docs for more information.

   `$success = $number->format(type => negative,template => template )'

   Please see the Number::Format docs for more information.

   `$success = $number->format(type => price)'

   Prepends the printed output with the local currency symbol.  Please see
the Number::Format docs for more information.

   `$success = $number->format(type => bytes)'

   Prints the number as K or M. Please see the Number::Format docs for
more information.

   `$success = $number->format()'

   Will remove the advanced formatting option.

CAVEATS and NOTES
=================

Performance Issues
------------------

   I wrote this to help me transparently configure number printing formats
for figures that get passed around between objects that print.  In this
capacity it works pretty decently for me.  *However*, using these objects
in place of numeric scalars adds a fair bit of memory and processor
consumption, so I'd recommend only using them when you need to print
numbers, and for the occasional calculation.

   If you have many calculations to do, you can do the calculations first,
and then stuff the value into a Text::Number object.

Exception Handling
------------------

   All calculations that can throw exceptions are wrapped in evals.  If
your calculation threw an exception (say, divided bt zero), the return
value will be an empty string.  I was considering returning an instance of
the object with the value set to zero, but this seemed confusing, since
you wouldn't necessarily know if the value was the result of math or of
the exception.  I also considered undef.

   I'm open to suggestion on this - if anyone is using this object and has
suggestions, please send them to me <fix@fixler.com>

REQUIRES
========

   Perl 5.005

   POSIX

   Number::Format (optional)

AUTHOR
======

   Eric Fixler <fix@fixler.com>

   Copyright 1999.  You are free to use, modify, and redistribute this
module as long as the source remains freely available, and credit is given
to the the original author (i.e., me).

TODO
====

   Fuller and better implementation of Number::Format methods.

   Elimination of POSIX call (there's only one).

   Implement mod arithmetic.

   Is Text::Number really the right name for this package?

ACKNOWLEDGEMENTS
================

   Tom Christansen and Nathan Torkington; their StrNum/overload example in
the [excellent] Perl Cookbook was the beginning of this module.

   William R. Ward <wrw@bayview.com> author of Number::Format.

SEE ALSO
========

   Number::Format

Embedding of Adobe PFB/PFA + AFM format fonts. Inherits from Text/PDF/Dict,
************************************************************************************************

NAME
====

   Text::PDF::AFont - Embedding of Adobe PFB/PFA + AFM format fonts.
Inherits from Text/PDF/Dict,

METHODS
=======

Text::PDF::AFont->new $parent, $name, $psfile, $afmfile, $pdfname [ , $encoding [ , @glyphs ]]
----------------------------------------------------------------------------------------------

   Creates a new font object with given parent and name from pfb/pfa from
psfile and afm from afmfile.

   The $pdfname is the name that this particular font object will be
referenced by throughout the PDF file. If you want to play silly games
with naming, then you can write the code to do it!

   The $encoding is the name of one of the encoding schemes specified in
the pdf-specification (v1.3 2nd Ed.), 'latin1' or 'custom'. 'latin1' is a
variant of the standard WinAnsiEncoding especially customized for
iso-8859-1 (aka. iso-latin-1).  If you use 'custom' as encoding, you have
to supply the @glyphs array which should specify 256 glyph-names as
defined by the "PostScript(R) Language Reference 3rd. Ed. - Appendix E"

   If you do not give $encoding, than the afms internal encoding is used.

   If you give an unknown $encoding, the encoding defaults to
WinAnsiEncoding.

   Returns the new font object.

Text::PDF::AFont->newNonEmbed $parent, $afmfile, $pdfname [ , $encoding [, @glyphs ]]
-------------------------------------------------------------------------------------

   Creates a new font object with given parent and name from pfb/pfa from
psfile and afm from afmfile.

   All the rules for Text::PDF::AFont->new apply here, but instead of
having a embedded font included in the pdf-file you only have a reference
to the font included in the pdf-file.  This results in far smaller
filesizes, but requires the viewing/printing application to have the
actual font properly installed at their platform.

   Returns the new font object.

Text::PDF::AFont->newCore $parent, $fontname, $pdfname [, $encoding [, @glyphs ]]
---------------------------------------------------------------------------------

   Creates a new font object with given parent and fontname from one of
the 14 Adobe Core Fonts as supported by the Adobe PDF Reader applications
versions 3.0 and up.

   Valid values for fontname are:

     Courier-Bold
     Courier-BoldOblique
     Courier-Oblique
     Courier
     Helvetica-Bold
     Helvetica-BoldOblique
     Helvetica-Oblique
     Helvetica
     Symbol
     Times-Bold
     Times-BoldItalic
     Times-Italic
     Times-Roman
     ZapfDingbats

   All the rules of Text::PDF::AFont->newNonEmbed apply here, but don't
require you to specify an afm-file since the fonts are internally
supported by both the Adobe PDF Reader applications and this module.

   Returns the new font object.

$f->reencode $parentpdf $pdfname $encoding [@glyphs]
----------------------------------------------------

   Reencodes the current font $f with encoding $encoding (optional variant
@glyphs) to be used with name $pdfname.

   Returns the new font object.

$f->width($text)
----------------

   Returns the width of the text in em.

$f->out_text($text)
-------------------

   Acknowledges the text to be output for subsetting purposes, etc.

a wrapper api for the Text::PDF::* modules of Martin Hosken.
************************************************************

NAME
====

   Text::PDF::API - a wrapper api for the Text::PDF::* modules of Martin
Hosken.

SYNOPSIS
========

     use Text::PDF::API;

     $pdf = Text::PDF::API->new( %defaults );

     $pdf->end;

DESCRIPTION
===========

Base Methods
------------

$pdf = Text::PDF::API->new [%defaults]
     This creates a new pdf-object initializes it with the given defaults
     and returns it.  See the functions getDefault and *setDefault* for a
     list of supported parameters.

$pdf->info $title, $subject, $creator, $author, $keywords
     This creates the pdf-info-object and initializes it with the given
     values.

$pdf->saveas $file
     This saves the pdf-object to a file indicated by $file.

$pdf->end
     This destroys the pdf-object and frees its memory.

$pdf->getDefault $parameter
     This returns the pdf-object default indicated by *$parameter*.

     The current supported defaults are:

     PageSize, valid values:

          'a0'		=>	[ 2380	, 3368	]
          'a1'		=>	[ 1684	, 2380	]
          'a2'		=>	[ 1190	, 1684	]
          'a3'		=>	[ 842	, 1190	]
          'a4'		=>	[ 595	, 842	]
          'a5'		=>	[ 421	, 595	]
          'a6'		=>	[ 297	, 421	]
          'letter'	=>	[ 612	, 792	]
          'broadsheet'	=>	[ 1296	, 1584	]
          'ledger'	=>	[ 1224	, 792	]
          'tabloid'	=>	[ 792	, 1224	]
          'legal'		=>	[ 612	, 1008	]
          'executive'	=>	[ 522	, 756	]
          '36x36'		=>	[ 2592	, 2592	]

     PageWidth, valid values:

          0 .. 32535 points (remember default = 72dpi)

          PageHeight, valid values:

          0 .. 32535 points (remember default = 72dpi)

     PageOrientation, valid values:

     	Landscape, Portrait

     Compression

          0, 1 (= off, on)

     PDFVersion

          0 .. 3 (corresponding to the adobe acrobat versions up to 4.0)

$pdf->setDefault $parameter , $value
     This sets the pdf-object defaults (see $pdf->getDefault for details).

$pdf->newpage [ $width, $height ]
$pdf->newpage [ $pagesize ]
     This creates a new page in the pdf-object and assigns it to the
     default page context.  If $width and $height are not given the
     funtion falls back to any given defaults (PageSize then
     PageWidth+PageHeight) and as a last resort to 'A4'.  You can use also
     specify oonly the Pagesize as given under the defaults.

$pdf->endpage
     This closes the current page.

Generic Methods
---------------

$pdf->savePdfState
$pdf->restorePdfState
     Saves and restores the state of the pdf-document BUT NOT of the
     pdf-object.

     BEWARE: Don't cross page boundaries with save/restore, if you really
     don't know the pdf-specification well enough.

$pdf->saveState {currently broken}
$pdf->restoreState {currently broken}
     Saves and restores the state of the pdf-object and the underlying
     document.

     NOTE: All states are automagically restored if you issue a
     $pdf->endpage.

Font State Methods
------------------

$pdf->setFontDir $directory
     Sets the default font search directory.

$directory = $pdf->getFontDir
     Gets the default font search directory.

$pdf->addFontPath $directory
     Adds a directory to the font search path.

$pdf->newFont $fontname, $ttfile
$pdf->newFont $fontname, $psffile, $afmfile
$pdf->newFont $fontname
     Adds a new font to the pdf-object. Based on the fonts name either a
     core, truetype or postscript font is assumed: TrueType have a ','
     between the family and style names whereas the postscript and core
     fonts use a '-'.

     BEWARE: Postscript fonts other than the core fonts are supported, BUT
     the implementation is still somewhere in alpha/beta stage and may not
     result in valid pdf-files under certain conditions.

     NOTE: this function is for BACKWARD COMPATIBLITY ONLY (as of version
     0.5) and will be removed sometime before version 1.0.

     *RECOMMENDATION:* Start using the following three functions below.

$pdf->newFontCore $fontname [, $encoding [, @glyphs ]]
$pdf->newFontTTF $fontname, $ttffile [, $encoding ]
$pdf->newFontPS $fontname, $psffile, $afmfile [, $encoding [, @glyphs ]]
     Although you can add a font thru the $pdf->newFont function, these
     three new functions are much more stable (newFontPS is alpha-quality)
     and reliable.

     The $encoding is the name of one of the encoding schemes supported by
     Unicode::Map8, 'asis' or 'custom'. If you use 'custom' as encoding,
     you have to supply the @glyphs array which should specify 256
     glyph-names as defined by the "PostScript(R) Language Reference 3rd.
     Ed. - Appendix E"

     If you do not give $encoding or 'asis', than the afms internal
     encoding is used.

     If you give an unknown $encoding, the encoding defaults to
     WinAnsiEncoding.

$pdf->addCoreFonts
     This is a shortcut to add all pdf-core-fonts to the pdf-object.

$pdf->useFont $name, $size [, $encoding ]
     This selects the font at the specified size and encoding.  The font
     must have been loaded with the same $name parameter with $pdf->newFont

     If you do not give $encoding, than the encoding from $pdf->newFont???
     is used.

     NOTE: As of version API 0.5 you can specify any encoding supported by
     Unicode::Map8, since the fonts are automagically reencoded to use the
     new encoding if it differs from that encoding specified at
     $pdf->newFont???.

$pdf->setFontTranslate $tx, $ty
     Sets the translation (aka. x,y-offset) in the
     Font-Transformation-Matrices.

$pdf->setFontScale $scalex, $scaley
     Sets the scale in the Font-Transformation-Matrices.

$pdf->setFontSkew $alfa, $beta
     Sets the skew in the Font-Transformation-Matrices specified in
     degrees (0..360).

$pdf->setFontRotation $alfa
     Sets the rotation in the Font-Transformation-Matrices specified in
     degrees (0..360) counter-clock-wise from the right horizontal.

$pdf->clearFontMatrix
     Resets all Font-Transformation-Matrices.

$pdf->calcFontMatrix
     Calculates the final Transformation-Matrix for use with the *Text*
     functions.

$pdf->setFontMatrix $a, $b, $c, $d, $e, $f
     Sets the final Transformation-Matrix directly.

($a, $b, $c, $d, $e, $f)=$pdf->getFontMatrix
     Returns the final Transformation-Matrix. Use $pdf->calcFontMatrix and
     then $pdf->getFontMatrix to retrive the combined effects of
     Translate, Skew, Scale & Rotate.

$pdf->setCharSpacing $spacing
$pdf->setWordSpacing $spacing
$pdf->setTextLeading $leading
$pdf->setTextRise $rise
$pdf->setTextRendering $rendering
Text Block Methods
------------------

$pdf->beginText
     Starts a text block.

$pdf->endText
     Ends a text block

$pdf->charSpacing [ $spacing ]
$pdf->wordSpacing [ $spacing ]
$pdf->textLeading [ $leading ]
$pdf->textRise [ $rise ]
$pdf->textRendering [ $rendering ]
$pdf->textMatrix [ @matrix ]
     Sets the parameter for the text-block only. If parameter is not given
     the default as defined by $pdf->set* is used.

$pdf->textPos $mx, $my
     Sets a new text position, but honoring the current FontMatrix.

$pdf->textFont [ $font, $size [, $encoding ] ]
     Switches the font within the text-block or resets to the last
     $pdf->useFont.  BEWARE: you can only change to a new font before a
     matrix or pos command since changing it after such command gives
     pdf-errors !!!

$pdf->textAdd $text
     Adds text to the text-block.

$pdf->textNewLine [ $leading ]
     Moves the text-pointer to a new line using TextLeading as default.

Text Utility Methods
--------------------

$pdf->calcTextWidth $text
     Calculates the width of the text based on the parameters set by
     useFont.

     BEWARE: Does not consider parameters specified by setFont* and
     *Matrix functions.

$pdf->showText $text
     Displays the $text based on the parameters given by the *Font*
     functions.

$pdf->showTextXY $x, $y, $text
$pdf->showTextXY_R $x, $y, $text
$pdf->showTextXY_C $x, $y, $text
     Like $pdf->showText but overrides the x,y-offsets of the Matrices.
     The *_R and *_C variants perform right and center alignment !

$pdf->printText $x, $y, $font, $size, $encoding, $text
     Like a $pdf->useFont followed by a $pdf->showTextXY.

Graphic State Methods
---------------------

$pdf->setGfxTranslate $tx, $ty
$pdf->setGfxScale $scalex, $scaley
$pdf->setGfxSkew $alfa, $beta
$pdf->setGfxRotation $alfa
$pdf->clearGfxMatrix
$pdf->calcGfxMatrix
$pdf->setGfxMatrix $a, $b, $c, $d, $e, $f
($a, $b, $c, $d, $e, $f)=$pdf->getGfxMatrix
     These functions behave like the the font functions BUT affect the
     whole global graphics state.

     BEWARE: If you use both the Gfx and Font versions of these functions
     the final result for Text would be the combined effects of both the
     Gfx and Font parameters.

$pdf->useGfxState
     Adds the parameters of the functions above to the current graphics
     state.  To revert to the former parameters use $pdf->savePdfState and
     $pdf->restorePdfState.

$pdf->useGfxFlatness $flatness
$pdf->useGfxLineCap $linecap
$pdf->useGfxLineDash @dasharray
$pdf->useGfxLineJoin $linejoin
$pdf->useGfxLineWidth $linewidth
$pdf->useGfxMeterlimit $limit
Color Methods
-------------

$pdf->setColorFill $red, $green, $blue
$pdf->setColorFill $cyan, $magenta, $yellow, $black
$pdf->setColorFill $gray
$pdf->setColorStroke $red, $green, $blue
$pdf->setColorStroke $cyan, $magenta, $yellow, $black
$pdf->setColorStroke $gray
Drawing Methods
---------------

$pdf->moveTo $x, $y
$pdf->lineTo $x, $y
$pdf->curveTo $x1, $y1, $x2, $y2, $x3, $y3
$pdf->rect $x, $y, $w, $h
$pdf->closePath
$pdf->endPath
$pdf->rectXY $x1, $y1, $x2, $y2
$pdf->lineXY $x1, $y1, $x2, $y2
($xs,$ys,$xe,$ye)=$pdf->arcXYabDG $x, $y, $a, $b, $delta, $gamma, $move
($xs,$ys,$xe,$ye)=$pdf->arcXYrDG $x, $y, $r, $delta, $gamma, $move
$pdf->ellipsisXYAB $x, $y, $a, $b
$pdf->circleXYR $x, $y, $r
$pdf->stroke
$pdf->closestroke
$pdf->fill
$pdf->closefill
$pdf->fillNZ
$pdf->fillstroke
$pdf->closefillstroke
$pdf->fillstrokeNZ
$pdf->closefillstrokeNZ
     quot errat demonstrandum

Bitmap Methods
--------------

( $key , $width , $height ) = $pdf->newImage $file
     Current loading support includes NetPBM images of the RAW_BITS
     variation and non-interlaced/non-filtered PNG.  Transperancy/Opacity
     information is currently ignored as well as Alpha-Channel information.

( $key , $width , $height ) = $pdf->rawImage $name, $width $height $type @imagearray
     This function supports loading of point-arrays for embedding image
     information into the pdf. $type must be one of the following:

          '-rgb' ... each element of the array is a color component
          		in the range of 0..255
          '-RGB' ... each element of the array is a hex-encoded color pixel
          		with two hex-digits per color component

     $name must be a unique name for this image (at least 8 characters
     long).

$pdf->placeImage $key, $x, $y, $scalex, $scaley
HISTORY
=======

Version 0.00
     GENESIS

Version 0.01
     inital implementation without documentation

Version 0.01_01
     you can create pages, still no docs

Version 0.01_02 - 0.01_11
     various conceptual design stages

Version 0.01_12
     first public snapshot with some docs and first implementation of font
     caching (released as 0.01_12_snapshot)

Version 0.01_14
     reimplementaion of font-handling with unification of core and
     truetype fonts under the function "newFont"

Version 0.01_15
     implementaion of font-encoding for truetypes

Version 0.01_16
     reimplementaion of font-encoding thru CID because Acrobat seems to
     ignore encoding tables for TTs when using normal embedding

Version 0.01_17
     implementaion of printText, useFont, showText & showTextXY

Version 0.01_18
     implementaion of *FontMatrix functions, changes in showText &
     showTextXY

Version 0.01_19
     addition of setFontTranslate, Skew, Rotate & Scale with cleanup in
     *FontMatrix

Version 0.01_20
     end of text/font implementation, let it stabilize :)

Version 0.02
     genesis of the graphical interface (CTM handling copied from fonts)

Version 0.02_01
     added text and graphic state functions

Version 0.02_02
     cleanup/extension of dokumentation, but still not finished

Version 0.02_03
     proposed implementation of drawing functions (NOT FINISHED)

Version 0.02_04
     finished implemetation of needed drawing functions

Version 0.03
     bugfixes in drawing and font functions first implementation of state
     functions

Version 0.03_01
     first implementation of bitmap functions

Version 0.03_02
     bugfixes in text/font functions

Version 0.03_03
     added support for loading of PNM(netpbm) and PNG bitmaps

Version 0.03_04
     added circle and ellipsis drawing functions

Version 0.03_05
     fixed calcTextWidth to allow the type1 core fonts to be measured too.
     added showTextXY_R and _C functions for alignment procedures :)

Version 0.04-0.43
     rewrite of type1 core-font handling to ease development support for
     other type1 fonts in future releases of Text::PDF and Text::PDF::API.

     small bugfixes in calcTextWidth and showTextXY_[RC].

     small documentation update

Version 0.05 (Oct. 2000)
     major rewrite to use Unicode::Map8 instead of the homegrown functions
     :) , add another dependency but at least a fast one

Versions 0.5_pre??? (Dec. 2000)
     major rewrite of font-handling routines stalls the tutorial/exaples
     collection.  now adobe-type1 fonts (pfb/pfa + afm) and the core-fonts
     can be used the same way as truetype with the Unicode::Map8 encodings.

Version 0.5 (07-01-2001)
     documemtation update and release of the much hacked 0.5_pre??? code :)

Version 0.5001 to 0.5003
     minor bugfixes:

     under certain conditions the 'image' functions stopped working, hope
     that my newly invented "nigma-hash" keygenerator fixes this.

     the symbol and zapfdingbat corefonts did not work ... since they
     missed attributes and had wrong font-flags set ... doesn't anybody
     use them ?

Version 0.6
     removed: "nigma-hash" keygenerator had some disadvantages.

     added: Digest::REHLHA module for key-generation (this comes with the
     API).

     added: $p->arcXYrDG() and $p->arcXYabDG() to relief users of the (in
     my opinion) 'mind boggling' bezier-curve function for arcs.

     added: $p->info() to include copyright/generator information in the
     pdf.

     added: new text-block functions to ease the use of text.

     changed: unicode<->name mapping was broken under perl-5.004xx.

     *PLEASE NOTE:* this is now the minimum required version for the
     upcoming APIx module-chain.

CONTRIBUTORS / BUGHUNTERS / THANKS
==================================

   Martin Hosken [mhosken@sil.org] - for writing Text::PDF in the first
place

   Lester Hightower [hightowe@TheAIMSGroup.com] - fixes/reports:
perl-5.004xx, key-generation, Makefile.PL

BUGS
====

   MANY! If you find some report them to
perl-text-pdf-modules@yahoogroups.com.

TODO ( in no particular order )
===============================

   documentation ?

   drawing functions ?

   more bitmap import functions (jpeg,tiff,xbm,xpm,...?)

   function to populate a Text::PDF::API object from an existing pdf-file ?

Corresponds to a PDF array. Inherits from `PDF::Objind' in this node
********************************************************************

NAME
====

   Text::PDF::Array - Corresponds to a PDF array. Inherits from
`PDF::Objind' in this node

INSTANCE VARIABLES
==================

   This object is not an array but an associative array containing the
array of elements. Thus, there are special instance variables for an array
object, beginning with a space

var
     Contains the actual array of elements

METHODS
=======

PDF::Array->new($parent, @vals)
-------------------------------

   Creates an array with the given storage parent and an optional list of
values to initialise the array with.

$a->outobjdeep($fh, $pdf)
-------------------------

   Outputs an array as a PDF array to the given filehandle.

$a->removeobj($elem)
--------------------

   Removes all occurrences of an element from an array.

$a->elementsof
--------------

   Returns a list of all the elements in the array. Notice that this is
not the array itself but the elements in the array.

$a->add_elements
----------------

   Appends the given elements to the array. An element is only added if it
is defined.

$a->val
-------

   Returns the value of the array, this is a reference to the actual array
containing the elements.

$a->copy($pdf)
--------------

   Copies the array with deep-copy on elements which are not full PDF
objects with respect to a particular $pdf output context

A special form of `PDF::String' in this node which holds the strings *true* or false
************************************************************************************

NAME
====

   PDF::Bool - A special form of `PDF::String' in this node which holds
the strings *true* or false

METHODS
=======

$b->convert($str)
-----------------

   Converts a string into the string which will be stored.

as_pdf
------

   Converts the value to a PDF output form

PDF Dictionaries and Streams. Inherits from `PDF::Objind' in this node
**********************************************************************

NAME
====

   Text::PDF::Dict - PDF Dictionaries and Streams. Inherits from
`PDF::Objind' in this node

INSTANCE VARIABLES
==================

   There are various special instance variables which are used to look
after, particularly, streams. Each begins with a space:

stream
     Holds the stream contents for output

streamfile
     Holds the stream contents in an external file rather than in memory.
     This is not the same as a PDF file stream. The data is stored in its
     unfiltered form.

streamloc
     If both ' stream' and ' streamfile' are empty, this indicates where
     in the source PDF the stream starts.

METHODS
=======

$d->outobjdeep($fh)
-------------------

   Outputs the contents of the dictionary to a PDF file. This is a
recursive call.

   It also outputs a stream if the dictionary has a stream element. If
this occurs then this method will calculate the length of the stream and
insert it into the stream's dictionary.

$d->read_stream($force_memory)
------------------------------

   Reads in a stream from a PDF file. If the stream is greater than
`PDF::Dict::mincache' (defaults to 32768) bytes to be stored, then the
default action is to create a file for it somewhere and to use that file
as a data cache. If $force_memory is set, this caching will not occur and
the data will all be stored in the $self->{' stream'} variable.

Holds the trailers and cross-reference tables for a PDF file
************************************************************

NAME
====

   Text::PDF::File - Holds the trailers and cross-reference tables for a
PDF file

SYNOPSIS
========

     $p = Text::PDF::File->open("filename.pdf", 1);
     $p->new_obj($obj_ref);
     $p->free_obj($obj_ref);
     $p->append_file;
     $p->close;

DESCRIPTION
===========

   This class keeps track of the directory aspects of a PDF file. There
are two parts to the directory: the main directory object which is the
parent to all other objects and a chain of cross-reference tables and
corresponding trailer dictionaries starting with the main directory object.

INSTANCE VARIABLES
==================

   Within this class hierarchy, rather than making everything visible via
methods, which would be a lot of work, there are various instance
variables which are accessible via associative array referencing. To
distinguish instance variables from content variables (which may come from
the PDF content itself), each such variable will start with a space.

   Variables which do not start with a space directly reflect elements in
a PDF dictionary. In the case of a Text::PDF::File, the elements reflect
those in the trailer dictionary.

   Since some variables are not designed for class users to access,
variables are marked in the documentation with (R) to indicate that such
an entry should only be used as read-only information. (P) indicates that
the information is private and not designed for user use at all, but is
included in the documentation for completeness and to ensure that nobody
else tries to use it.

newroot
     This variable allows the user to create a new root entry to occur in
     the trailer dictionary which is output when the file is written or
     appended. If you wish to over-ride the root element in the dictionary
     you have, use this entry to indicate that without losing the current
     Root entry. Notice that newroot should point to a PDF level object
     and not just to a dictionary which does not have object status.

INFILE (R)
     Contains the filehandle used to read this information into this PDF
     directory. Is an IO object.

fname (R)
     This is the filename which is reflected by INFILE, or the original IO
     object passed in.

update (R)
     This indicates that the read file has been opened for update and that
     at some point, $p->appendfile() can be called to update the file with
     the changes that have been made to the memory representation.

maxobj (R)
     Contains the first useable object number above any that have already
     appeared in the file so far.

outlist (P)
     This is a list of Objind which are to be output when the next
     appendfile or outfile occurs.

firstfree (P)
     Contains the first free object in the free object list. Free objects
     are removed from the front of the list and added to the end.

lastfree (P)
     Contains the last free object in the free list. It may be the same as
     the firstfree if there is only one free object.

objcache (P)
     All objects are held in the cache to ensure that a system only has
     one occurrence of each object. In effect, the objind class acts as a
     container type class to hold the PDF object structure and it would be
     unfortunate if there were two identical place-holders floating around
     a system.

epos (P)
     The end location of the read-file.

   Each trailer dictionary contains a number of private instance variables
which hold the chain together.

loc (P)
     Contains the location of the start of the cross-reference table
     preceding the trailer.

xref (P)
     Contains an anonymous array of each cross-reference table entry.

prev (P)
     A reference to the previous table. Note this differs from the Prev
     entry which is in PDF which contains the location of the previous
     cross-reference table.

METHODS
=======

Text::PDF::File->new
--------------------

   Creates a new, empty file object which can act as the host to other PDF
objects.  Since there is no file associated with this object, it is
assumed that the object is created in readiness for creating a new PDF
file.

$p = Text::PDF::File->open($filename, $update)
----------------------------------------------

   Opens the file and reads all the trailers and cross reference tables to
build a complete directory of objects.

   $update specifies whether this file is being opened for updating and
editing, or simply to be read.

   $filename may be an IO object

$p->append_file()
-----------------

   Appends the objects for output to the read file and then appends the
appropriate tale.

$p->out_file($fname)
--------------------

   Writes a PDF file to a file of the given filename based on the current
list of objects to be output. It creates the trailer dictionary based on
information in $self.

   $fname may be an IO object;

$p->create_file($fname)
-----------------------

   Creates a new output file (no check is made of an existing open file) of
the given filename or IO object. Note, make sure that $p->{' version'} is
set correctly before calling this function.

$p->close_file
--------------

   Closes up the open file for output by outputting the trailer etc.

($value, $str) = $p->readval($str)
----------------------------------

   Reads a PDF value from the current position in the file. If $str is too
short then read some more from the current location in the file until the
whole object is read. This is a recursive call which may slurp in a whole
big stream (unprocessed).

   Returns the recursive data structure read and also the current $str
that has been read from the file.

$ref = $p->read_obj($objind)
----------------------------

   Given an indirect object reference, locate it and read the object
returning the read in object.

$objind = $p->new_obj($obj)
---------------------------

   Creates a new, free object reference based on free space in the cross
reference chain.  If nothing free then thinks up a new number. If $obj
then turns that object into this new object rather than returning a new
object.

$p->out_obj($objind)
--------------------

   Indicates that the given object reference should appear in the output
xref table whether with data or freed.

$p->free_obj($objind)
---------------------

   Marks an object reference for output as being freed.

$p->remove_obj($objind)
-----------------------

   Removes the object from all places where we might remember it

$p->ship_out(@objects)
----------------------

   Ships the given objects (or all objects for output if @objects is
empty) to the currently open output file (assuming there is one). Freed
objects are not shipped, and once an object is shipped it is switched such
that this file becomes its source and it will not be shipped again unless
out_obj is called again. Notice that a shipped out object can be re-output
or even freed, but that it will not cause the data already output to be
changed.

PRIVATE METHODS & FUNCTIONS
===========================

   The following methods and functions are considered private to this
class. This does not mean you cannot use them if you have a need, just
that they aren't really designed for users of this class.

$offset = $p->locate_obj($num, $gen)
------------------------------------

   Returns a file offset to the object asked for by following the chain of
cross reference tables until it finds the one you want.

update($fh, $str)
-----------------

   Keeps reading $fh for more data to ensure that $str has at least a line
full for `readval' to work on. At this point we also take the opportunity
to ignore comments.

$objind = $p->test_obj($num, $gen)
----------------------------------

   Tests the cache to see whether an object reference (which may or may
not have been getobj()ed) has been cached. Returns it if it has.

$p->add_obj($objind)
--------------------

   Adds the given object to the internal object cache.

$tdict = $p->readxrtr($xpos)
----------------------------

   Recursive function which reads each of the cross-reference and trailer
tables in turn until there are no more.

   Returns a dictionary corresponding to the trailer chain. Each trailer
also includes the corresponding cross-reference table.

   The structure of the xref private element in a trailer dictionary is of
an anonymous hash of cross reference elements by object number. Each
element consists of an array of 3 elements corresponding to the three
elements read in [location, generation number, free or used]. See the PDF
Specification for details.

$p->out_trailer($tdict)
-----------------------

   Outputs the body and trailer for a PDF file by outputting all the
objects in the ' outlist' and then outputting a xref table for those
objects and any freed ones. It then outputs the trailing dictionary and
the trailer code.

Text::PDF::File->_new
---------------------

   Creates a very empty PDF file object (used by new and open)

AUTHOR
======

   Martin Hosken Martin_Hosken@sil.org

   Copyright Martin Hosken 1999 and onwards

   No warranty or expression of effectiveness, least of all regarding
anyone's safety, is implied in this software or documentation.

Licensing
---------

   This Perl Text::PDF module is licensed under the Perl Artistic License.

Abstract superclass for PDF stream filters
******************************************

NAME
====

   PDF::Filter - Abstract superclass for PDF stream filters

SYNOPSIS
========

     $f = Text::PDF::Filter->new;
     $str = $f->outfilt($str, 1);
     print OUTFILE $str;

     while (read(INFILE, $dat, 4096))
     { $store .= $f->infilt($dat, 0); }
     $store .= $f->infilt("", 1);

DESCRIPTION
===========

   A Filter object contains state information for the process of outputting
and inputting data through the filter. The precise state information stored
is up to the particular filter and may range from nothing to whole objects
created and destroyed.

   Each filter stores different state information for input and output and
thus may handle one input filtering process and one output filtering
process at the same time.

METHODS
=======

Text::PDF::Filter->new
----------------------

   Creates a new filter object with empty state information ready for
processing data both input and output.

$dat = $f->infilt($str, $isend)
-------------------------------

   Filters from output to input the data. Notice that $isend == 0 implies
that there is more data to come and so following it $f may contain state
information (usually due to the break-off point of $str not being tidy).
Subsequent calls will incorporate this stored state information.

   $isend == 1 implies that there is no more data to follow. The final
state of $f will be that the state information is empty. Error messages
are most likely to occur here since if there is required state information
to be stored following this data, then that would imply an error in the
data.

$str = $f->outfilt($dat, $isend)
--------------------------------

   Filter stored data ready for output. Parallels `infilt'.

Ascii85 filter for PDF streams. Inherits from Text/PDF/Filter,
*************************************************************************************

NAME
====

   Text::PDF::ASCII85Decode - Ascii85 filter for PDF streams. Inherits from
Text/PDF/Filter,

Run Length encoding filter for PDF streams. Inherits from Text/PDF/Filter,
*************************************************************************************************

NAME
====

   Text::PDF::RunLengthDecode - Run Length encoding filter for PDF
streams. Inherits from Text/PDF/Filter,

Ascii Hex encoding (very inefficient) for PDF streams. Inherits from Text/PDF/Filter,
************************************************************************************************************

NAME
====

   Text::PDF::ASCIIHexDecode - Ascii Hex encoding (very inefficient) for
PDF streams.  Inherits from Text/PDF/Filter,

Inherits from Text/PDF/String, and stores PDF names (things beginning with /)
****************************************************************************************************

NAME
====

   Text::PDF::Name - Inherits from Text/PDF/String,
and stores PDF names (things beginning with /)

METHODS
=======

$n->convert
-----------

   Converts a name into a string by removing the / and converting any hex
munging

as_pdf
------

   Returns a name formatted as PDF

Numbers in PDF. Inherits from Text/PDF/String,
*********************************************************************

NAME
====

   Text::PDF::Number - Numbers in PDF. Inherits from
Text/PDF/String,

METHODS
=======

$n->convert($str)
-----------------

   Converts a string from PDF to internal, by doing nothing

$n->as_pdf
----------

   Converts a number to PDF format

PDF indirect object reference. Also acts as an abstract superclass for all elements in a PDF file.
**************************************************************************************************

NAME
====

   Text::PDF::Objind - PDF indirect object reference. Also acts as an
abstract superclass for all elements in a PDF file.

INSTANCE VARIABLES
==================

   Instance variables differ from content variables in that they all start
with a space.

parent
     For an object which is a reference to an object in some source, this
     holds the reference to the source object, so that should the
     reference have to be de-referenced, then we know where to go and get
     the info.

objnum (R)
     The object number in the source (only for object references)

objgen (R)
     The object generation in the source

     There are other instance variables which are used by the parent for
     file control.

isfree
     This marks whether the object is in the free list and available for
     re-use as another object elsewhere in the file.

nextfree
     Holds a direct reference to the next free object in the free list.

METHODS
=======

Text::PDF::Objind->new()
------------------------

   Creates a new indirect object

uid
---

   Returns a Unique id for this object, creating one if it didn't have one
before

$r->val
-------

   Returns the val of this object or reads the object and then returns its
value.

   Note that all direct subclasses *must* make their own versions of this
subroutine otherwise we could be in for a very deep loop!

$r->realise
-----------

   Makes sure that the object is fully read in, etc.

$r->outobjdeep($fh, $pdf)
-------------------------

   If you really want to output this object, then you must need to read it
first.  This also means that all direct subclasses must subclass this
method or loop forever!

$r->outobj($fh)
---------------

   If this is a full object then outputs a reference to the object,
otherwise calls outobjdeep to output the contents of the object at this
point.

$r->elementsof
--------------

   Abstract superclass function filler. Returns self here but should return
something more useful if an array.

$r->empty
---------

   Empties all content from this object to free up memory or to be read to
pass the object into the free list. Simplistically undefs all instance
variables other than object number and generation.

$r->merge($objind)
------------------

   This merges content information into an object reference place-holder.
This occurs when an object reference is read before the object definition
and the information in the read data needs to be merged into the object
place-holder

$r->is_obj($pdf)
----------------

   Returns whether this object is a full object with its own object number
or whether it is purely a sub-object. $pdf indicates which output file we
are concerned that the object is an object in.

$r->copy($pdf, $res)
--------------------

   Returns a new copy of this object. The object is assumed to be some kind
of associative array and the copy is a deep copy for elements which are
not PDF objects, according to $pdf, and shallow copy for those that are.
Notice that calling copy on an object forces at least a one level copy
even if it is a PDF object. The returned object loses its PDF object
status though.

   If $res is defined then the copy goes into that object rather than
creating a new one. It is up to the caller to bless $res, etc. Notice that
elements from $self are not copied into $res if there is already an entry
for them existing in $res.

Represents a PDF page, inherits from Text/PDF/Pages,
**************************************************************************

NAME
====

   Text::PDF::Page - Represents a PDF page, inherits from
Text/PDF/Pages,

DESCRIPTION
===========

   Represents a page of output in PDF. It also keeps track of the content
stream, any resources (such as fonts) being switched, etc.

   Page inherits from Pages due to a number of shared methods. They are
really structurally quite different.

INSTANCE VARIABLES
==================

   A page has various working variables:

curstrm
     The currently open stream

METHODS
=======

Text::PDF::Page->new($pdf, $parent, $index)
-------------------------------------------

   Creates a new page based on a pages object (perhaps the root object).

   The page is also added to the parent at this point, so pages are
ordered in a PDF document in the order in which they are created rather
than in the order they are closed.

   Only the essential elements in the page dictionary are created here,
all others are either optional or can be inherited.

   The optional index value indicates the index in the parent list that
this page should be inserted (so that new pages need not be appended)

$p->add($str)
-------------

   Adds the string to the currently active stream for this page. If no
stream exists, then one is created and added to the list of streams for
this page.

   The slightly cryptic name is an aim to keep it short given the number
of times people are likely to have to type it.

$p->ship_out($pdf)
------------------

   Ships the page out to the given output file context

a PDF pages hierarchical element. Inherits from Text/PDF/Dict,
***********************************************************************************

NAME
====

   Text::PDF::Pages - a PDF pages hierarchical element. Inherits from
Text/PDF/Dict,

DESCRIPTION
===========

   A Pages object is the parent to other pages objects or to page objects
themselves.

METHODS
=======

Text::PDF::Pages->new($parent)
------------------------------

   This creates a new Pages object. Notice that $parent here is not the
file context for the object but the parent pages object for this pages. If
we are using this class to create a root node, then $parent should point
to the file context, which is identified by not having a Type of Pages.

$p->out_obj($isnew)
-------------------

   Tells all the files that this thing is destined for that they should
output this object come time to output. If this object has no parent, then
it must be the root. So set as the root for the files in question and tell
it to be output too.  If $isnew is set, then call new_obj rather than
out_obj to create as a new object in the file.

$p->find_prop($key)
-------------------

   Searches up through the inheritance tree to find a property.

$p->add_font($pdf, $font)
-------------------------

   Creates or edits the resource dictionary at this level in the
hierarchy. If the font is already supported even through the hierarchy,
then it is not added.

$p->bbox($xmin, $ymin, $xmax, $ymax, [$param])
----------------------------------------------

   Specifies the bounding box for this and all child pages. If the values
are identical to those inherited then no change is made. $param specifies
the attribute name so that other 'bounding box'es can be set with this
method.

$p->proc_set(@entries)
----------------------

   Ensures that the current resource contains all the entries in the
proc_sets listed. If necessary it creates a local resource dictionary to
achieve this.

PDF Standard inbuilt font resource object. Inherits from Text/PDF/Dict,
********************************************************************************************

NAME
====

   Text::PDF::SFont - PDF Standard inbuilt font resource object. Inherits
from Text/PDF/Dict,

METHODS
=======

Text::PDF::SFont->new($parent, $name, $pdfname)
-----------------------------------------------

   Creates a new font object with given parent and name. The name must be
from one of the core 14 base fonts included with PDF. These are:

     Courier,     Courier-Bold,   Courier-Oblique,   Courier-BoldOblique
     Times-Roman, Times-Bold,     Times-Italic,      Times-BoldItalic
     Helvetica,   Helvetica-Bold, Helvetica-Oblique, Helvetica-BoldOblique
     Symbol,      ZapfDingbats

   The $pdfname is the name that this particular font object will be
referenced by throughout the PDF file. If you want to play silly games
with naming, then you can write the code to do it!

   All fonts in this system are full PDF objects.

BUGS
====

   Currently no width support for Symbol or ZapfDingbats, I haven't got my
head around the AFMs yet.

   MacExpertEncoding not supported yet (I don't have the width info for any
of the fonts)

$f->width($text)
----------------

   Returns the width of the text in em.

$f->trim($text, $len)
---------------------

   Trims the given text to the given length (in per mille em) returning
the trimmed text

$f->out_text($text)
-------------------

   Acknowledges the text to be output for subsetting purposes, etc.

PDF String type objects and superclass for simple objects that are basically stringlike (Number, Name, etc.)
************************************************************************************************************

NAME
====

   Text::PDF::String - PDF String type objects and superclass for simple
objects that are basically stringlike (Number, Name, etc.)

METHODS
=======

Text::PDF::String->from_pdf($string)
------------------------------------

   Creates a new string object (not a full object yet) from a given string.
The string is parsed according to input criteria with escaping working.

Text::PDF::String->new($string)
-------------------------------

   Creates a new string object (not a full object yet) from a given string.
The string is parsed according to input criteria with escaping working.

$s->convert($str)
-----------------

   Returns $str converted as per criteria for input from PDF file

$s->val
-------

   Returns the value of this string (the string itself).

$->as_pdf
---------

   Returns the string formatted for output as PDF

$s->outobjdeep
--------------

   Outputs the string in PDF format, complete with necessary conversions

Inherits from Text/PDF/Dict, and represents a TrueType font within a PDF file.
***************************************************************************************************

NAME
====

   Text::PDF::TTFont - Inherits from Text/PDF/Dict,
and represents a TrueType font within a PDF file.

DESCRIPTION
===========

   A font consists of two primary parts in a PDF file: the header and the
font descriptor. Whilst two fonts may share font descriptors, they will
have their own header dictionaries including encoding and widhth
information.

INSTANCE VARIABLES
==================

   There are no instance variables beyond the variables which directly
correspond to entries in the appropriate PDF dictionaries.

METHODS
=======

Text::PDF::TTFont->new($parent, $fontfname, $pdfname, %opts)
------------------------------------------------------------

   Creates a new font resource for the given fontfile. This includes the
font descriptor and the font stream. The $pdfname is the name by which
this font resource will be known throught a particular PDF file.

   All font resources are full PDF objects.

$t->width($text)
----------------

   Measures the width of the given text according to the widths in the font

$t->trim($text, $len)
---------------------

   Trims the given text to the given length (in per mille em) returning
the trimmed text

$t->out_text($text)      Indicates to the font that the text is to be output and returns the text to be output
--------------------------------------------------------------------------------------------------------------

$f->copy
--------

   Copies the font object excluding the name, widths and encoding, etc.

TITLE
=====

   Text::PDF::TTIOString - internal IO type handle for string output for
font embedding. This code is ripped out of IO::Scalar, to save the direct
dependence for so little. See IO::Scalar for details

Inherits from `PDF::Dict' in this node and represents a TrueType Type 0 font within a PDF file.
***********************************************************************************************

NAME
====

   Text::PDF::TTFont0 - Inherits from `PDF::Dict' in this node and
represents a TrueType Type 0 font within a PDF file.

DESCRIPTION
===========

   A font consists of two primary parts in a PDF file: the header and the
font descriptor. Whilst two fonts may share font descriptors, they will
have their own header dictionaries including encoding and widhth
information.

INSTANCE VARIABLES
==================

   There are no instance variables beyond the variables which directly
correspond to entries in the appropriate PDF dictionaries.

METHODS
=======

Text::PDF::TTFont->new($parent, $fontfname. $pdfname)
-----------------------------------------------------

   Creates a new font resource for the given fontfile. This includes the
font descriptor and the font stream. The $pdfname is the name by which
this font resource will be known throughout a particular PDF file.

   All font resources are full PDF objects.

out_text($text)
---------------

   Returns the string to be put into a content stream for text to be
output in this font.  The text is assumed to be UTF8 encoded and the
return string is a glyph sequence for the text. If subsetting is enabled,
then all the glyphs returned are also marked for output.

width($text)
------------

   Returns the width of the string, assuming it to be UTF8 encoded.

outobjdeep($fh, $pdf)
---------------------

   Handles the creation of the font stream including subsetting at this
point. So if you get this far, that's it for subsetting.

ship_out($pdf)
--------------

   Ship this font out to the given $pdf file context

empty
-----

   Empty the font of as much as possible in order to save memory

Utility functions for PDF library
*********************************

NAME
====

   Text::PDF::Utils - Utility functions for PDF library

DESCRIPTION
===========

   A set of utility functions to save the fingers of the PDF library users!

FUNCTIONS
=========

PDFBool
-------

   Creates a Bool via Text::PDF::Bool->new

PDFArray
--------

   Creates an array via Text::PDF::Array->new

PDFDict
-------

   Creates a dict via Text::PDF::Dict->new

PDFName
-------

   Creates a name via Text::PDF::Name->new

PDFNum
------

   Creates a number via Text::PDF::Number->new

PDFStr
------

   Creates a string via Text::PDF::String->new

asPDFBool
---------

   Returns a boolean value in PDF output form

asPDFStr
--------

   Returns a string in PDF output form (including () or <>)

asPDFName
---------

   Returns a Name in PDF Output form (including /)

asPDFNum
--------

   Returns a number in PDF output form

unpacku($str)
-------------

   Returns a list of unicode values for the given UTF8 string

parse text into an array of tokens or array of arrays
*****************************************************

NAME
====

   Text::ParseWords - parse text into an array of tokens or array of arrays

SYNOPSIS
========

     use Text::ParseWords;
     @lists = &nested_quotewords($delim, $keep, @lines);
     @words = &quotewords($delim, $keep, @lines);
     @words = &shellwords(@lines);
     @words = &parse_line($delim, $keep, $line);
     @words = &old_shellwords(@lines); # DEPRECATED!

DESCRIPTION
===========

   The &nested_quotewords() and &quotewords() functions accept a delimiter
(which can be a regular expression) and a list of lines and then breaks
those lines up into a list of words ignoring delimiters that appear inside
quotes.  &quotewords() returns all of the tokens in a single long list,
while &nested_quotewords() returns a list of token lists corresponding to
the elements of @lines.  &parse_line() does tokenizing on a single string.
The &*quotewords() functions simply call &parse_lines(), so if you're
only splitting one line you can call &parse_lines() directly and save a
function call.

   The $keep argument is a boolean flag.  If true, then the tokens are
split on the specified delimiter, but all other characters (quotes,
backslashes, etc.) are kept in the tokens.  If $keep is false then the
&*quotewords() functions remove all quotes and backslashes that are not
themselves backslash-escaped or inside of single quotes (i.e.,
&quotewords() tries to interpret these characters just like the Bourne
shell).  NB: these semantics are significantly different from the original
version of this module shipped with Perl 5.000 through 5.004.  As an
additional feature, $keep may be the keyword "delimiters" which causes the
functions to preserve the delimiters in each string as tokens in the token
lists, in addition to preserving quote and backslash characters.

   &shellwords() is written as a special case of &quotewords(), and it
does token parsing with whitespace as a delimiter- similar to most Unix
shells.

EXAMPLES
========

   The sample program:

     use Text::ParseWords;
     @words = &quotewords('\s+', 0, q{this   is "a test" of\ quotewords \"for you});
     $i = 0;
     foreach (@words) {
         print "$i: <$_>\n";
         $i++;
     }

   produces:

     0: <this>
     1: <is>
     2: <a test>
     3: <of quotewords>
     4: <"for>
     5: <you>

   demonstrating:

  1. a simple word

  2. multiple spaces are skipped because of our $delim

  3. use of quotes to include a space in a word

  4. use of a backslash to include a space in a word

  5. use of a backslash to remove the special meaning of a double-quote

  6. another simple word (note the lack of effect of the backslashed
     double-quote)
        Replacing `&quotewords('\s+', 0, q{this   is...})' with
`&shellwords(q{this   is...})' is a simpler way to accomplish the same
thing.

AUTHORS
=======

   Maintainer is Hal Pomeranz <pomeranz@netcom.com>, 1994-1997 (Original
author unknown).  Much of the code for &parse_line() (including the
primary regexp) from Joerk Behrends <jbehrends@multimediaproduzenten.de>.

   Examples section another documentation provided by John Heidemann
<johnh@ISI.EDU>

   Bug reports, patches, and nagging provided by lots of folks- thanks
everybody!  Special thanks to Michael Schwern <schwern@envirolink.org> for
assuring me that a &nested_quotewords() would be useful, and to Jeff
Friedl <jfriedl@yahoo-inc.com> for telling me not to worry about
error-checking (sort of- you had to be there).

Query processing framework
**************************

NAME
====

   Text::Query - Query processing framework

SYNOPSIS
========

     use Text::Query;

     # Constructor
     $query = Text::Query->new([QSTRING] [OPTIONS]);

     # Methods
     $query->prepare(QSTRING [OPTIONS]);
     $query->match([TARGET]);
     $query->matchscalar([TARGET]);

DESCRIPTION
===========

   This module provides an object that matches a data source against a
query expression.

   Query expressions are compiled into an internal form when a new object
is created or the prepare method is called; they are not recompiled on
each match.

   The class provided by this module uses four packages to process the
query.  The query parser parses the question and calls a query expression
builder (internal form of the question). The optimizer is then called to
reduce the complexity of the expression. The solver applies the expression
on a data source.

   The following parsers are provided:

Text::Query::ParseAdvanced
Text::Query::ParseSimple
   The following builders are provided:

Text::Query::BuildAdvancedString
Text::Query::BuildSimpleString
   The following solver is provided:

Text::Query::SolveSimpleString
Text::Query::SolveAdvancedString
EXAMPLES
========

     use Text::Query;
     my $q=new Text::Query('hello and world',
                           -parse => 'Text::Query::ParseAdvanced',
                           -solve => 'Text::Query::SolveAdvancedString',
                           -build => 'Text::Query::BuildAdvancedString');
     die "bad query expression" if not defined $q;
     print if $q->match;
     ...
     $q->prepare('goodbye or adios or ta ta',
                 -litspace => 1,
                 -case => 1);
     #requires single space between the two ta's
     if($q->match($line)) {
     #doesn't match "Goodbye"
     ...
     $q->prepare('"and" or "or"');
     #quoting operators for literal match
     ...
     $q->prepare('\\bintegrate\\b', -regexp => 1);
     #won't match "disintegrated"

CONSTRUCTOR
===========

new ([QSTRING] [OPTIONS])
     This is the constructor for a new Text::Query object.  If a `QSTRING'
     is given it will be compiled to internal form.

     OPTIONS are passed in a hash like fashion, using key and value pairs.
     Possible options are:

     *-parse* - Package name of the parser. Default is
     Text::Query::ParseSimple.

     *-build* - Package name of the builder. Default is Text::Query::Build.

     *-optimize* - Package name of the optimizer. Default is
     Text::Query::Optimize.

     *-solve* - Package name of the solver. Default is Text::Query::Solve.

     *-mode* - Name of predefined group of packages to use.  Options are
             currently `simple_text' and `advanced_text'.

     These options are handled by the configure method.

     All other options are passed to the parser prepare function.  See the
     corresponding manual pages for a description.

     If `QSTRING' is undefined, the prepare function is not called.

     The constructor will croak if a `QSTRING' was supplied and had
     illegal syntax.

METHODS
=======

configure ([OPTIONS])
     Set the parse, build, optimize or solve packages. See the CONSTRUCTOR
     description for explanations.

prepare (QSTRING [OPTIONS])
     Compiles the query expression in `QSTRING' to internal form and sets
     any options (same as in the constructor).  prepare may be used to
     change the query expression and options for an existing query object.
     If OPTIONS are omitted, any options set by a previous call to
     prepare are persistent.

     The optimizer (-optimize) is called with the result of the parser
     (-parse).  The parser uses the builder (-build) to construct the
     internal form.

     This method returns a reference to the query object if the syntax of
     the expression was legal, or croak if not.

match ([TARGET])
     Calls the match method of the solver (-solve).

matchscalar ([TARGET])
     Calls the matchscalar method of the solver (-solve).

SEE ALSO
========

   Text::Query::ParseAdvanced(3), Text::Query::ParseSimple(3),
Text::Query::BuildSimpleString(3), Text::Query::BuildAdvanedString(3),
Text::Query::SolveSimpleString(3), Text::Query::SolveAdvancedString(3),

   Text::Query::Build(3), Text::Query::Parse(3), Text::Query::Solve(3),
Text::Query::Optimize(3)

AUTHORS
=======

   Eric Bohlman (ebohlman@netcom.com)

   Loic Dachary (loic@senga.org)

Match text against Boolean expression
*************************************

NAME
====

   Text::Query::Advanced - Match text against Boolean expression

SYNOPSIS
========

     use Text::Query::Advanced;

     # Constructor
     $query = Text::Query::Advanced->new([QSTRING] [OPTIONS]);

     # Methods
     $query->prepare(QSTRING [OPTIONS]);
     $query->match([TARGET]);
     $query->matchscalar([TARGET]);

     # Methods that can be overridden to produce custom query trees, etc.

     $query->build_final_expression(Q1);
     $query->build_expression(Q1,Q2);
     $query->build_expression_finish(Q1);
     $query->build_conj(Q1,Q2,F);
     $query->build_near(Q1,Q2);
     $query->build_concat(Q1,Q2);
     $query->build_negation(Q1);
     $query->build_literal(Q1);

DESCRIPTION
===========

   This module provides an object that matches a string or list of strings
against a Boolean query expression similar to an AltaVista "advanced
query".  Elements of the query expression may be regular expressions or
literal text.

   Query expressions are compiled into an internal form (currently, a
regular expression making use of most of the tricks listed in Recipe 6.17
of _The Perl Cookbook_) when a new object is created or the prepare method
is called; they are not recompiled on each match.

   The class provided by this module may be subclassed to produce query
processors that match against input other than literal strings, e.g.
indices.

   Query expressions consist of literal strings (or regexps) joined by the
following operators, in order of precedence from lowest to highest:

OR, |
AND, &
NEAR
NOT, !
   Operator names are not case-sensitive.  Note that if you want to use a |
in a regexp, you need to backwhack it to keep it from being seen as a query
operator.  Sub-expressions may be quoted in single or double quotes to
match "and," "or," or "not" literally and may be grouped in parentheses
(`(, )') to alter the precedence of evaluation.

   A parenthesized sub-expression may also be concatenated with other sub-
expressions to match sequences: `(Perl or Python) interpreter' would match
either "Perl interpreter" or "Python interpreter".  Concatenation has a
precedence higher than NOT but lower than AND.  Juxtaposition of simple
words has the highest precedence of all.

EXAMPLES
========

     use Text::Query::Advanced;
     my $q=new Text::Query::Advanced('hello and world');
     die "bad query expression" if not defined $q;
     print if $q->match;
     ...
     $q->prepare('goodbye or adios or ta ta',-litspace=>1,-case=>1);
     #requires single space between the two ta's
     if ($q->match($line)) {
     #doesn't match "Goodbye"
     ...
     $q->prepare('"and" or "or"');
     #quoting operators for literal match
     ...
     $q->prepare('\\bintegrate\\b',-regexp=>1);
     #won't match "disintegrated"

CONSTRUCTOR
===========

new ([QSTRING] [OPTIONS])
     This is the constructor for a new Text::Query object.  If a `QSTRING'
     is given it will be compiled to internal form.

     OPTIONS are passed in a hash like fashion, using key and value pairs.
     Possible options are:

     *-case* - If true, do case-sensitive match.

     *-litspace* - If true, match spaces (except between operators) in
     `QSTRING' literally.  If false, match spaces as `\s+'.

     *-near* - Sets the number of words that can occur between two
     expressions and still satisfy the NEAR operator.  The default is 10.

     *-regexp* - If true, treat patterns in `QSTRING' as regular
     expressions rather than literal text.

     *-whole* - If true, match whole words only, not substrings of words.

     The constructor will return undef if a `QSTRING' was supplied and had
     illegal syntax.

METHODS
=======

prepare (QSTRING [OPTIONS])
     Compiles the query expression in `QSTRING' to internal form and sets
     any options (same as in the constructor).  prepare may be used to
     change the query expression and options for an existing query object.
     If OPTIONS are omitted, any options set by a previous call to the
     constructor or prepare remain in effect.

     This method returns a reference to the query object if the syntax of
     the expression was legal, or undef if not.

match ([TARGET])
     If `TARGET' is a scalar, match returns a true value if the string
     specified by `TARGET' matches the query object's query expression.  If
     `TARGET' is not given, the match is made against $_.

     If `TARGET' is an array, match returns a (possibly empty) list of all
     matching elements.  If the elements of the array are references to
     sub- arrays, the match is done against the first element of each
     sub-array.  This allows arbitrary information (e.g. filenames) to be
     associated with each string to match.

     If `TARGET' is a reference to an array, match returns a reference to
     a (possibly empty) list of all matching elements.

matchscalar ([TARGET])
     Behaves just like MATCH when `TARGET' is a scalar or is not given.
     Slightly faster than MATCH under these circumstances.

CODE-GENERATION METHODS
=======================

   The following methods are used to generate regexps based on query
elements.  They may be overridden to generate other forms of matching
code, such as trees to be used by a custom version of match that evaluates
index lists or the like.

   All these methods return a scalar corresponding to the code that
performs the specified options.  As supplied, they return regexp strings,
but overridden methods could return objects, array references, etc.

   Parameters Q1 and Q2 are the same type of scalar as the return values.

build_final_expression(Q1)
     Does any final processing to generate code to match a top-level
     expression.  As supplied, optionally adds case-insensitivity code and
     then uses `qr//' to compile the regexp.  The return value will be
     stored in the object's `matchexp' field.  It is NOT necessarily of a
     type that can be passed to the other code-generation methods.

build_expression(Q1,Q2)
     Generate code to match `Q1' OR `Q2'

build_expression_finish(Q1)
     Generate any code needed to enclose an expression.  As supplied,
     encloses the generated regexp in non-capturing parentheses.

build_conj(Q1,Q2,F)
     Generate code needed to match `Q1' AND `Q2'.  F will be true if this
     is the first time this method is called in a sequence of several
     conjunctions (the supplied method uses this to factor a common ^ out
     of the generated sub- expressions, which greatly speeds up matching).

     =item build_near(Q1,Q2)

     Generate code needed to match `Q1' NEAR `Q2'.

build_concat(Q1,Q2)
     Generate code needed to match `Q1' immediately followed by `Q2'.

build_negation(Q1)
     Generate code needed to match NOT `Q1'.

build_literal(Q1)
     Generate code to match `Q1' as a literal.

AUTHOR
======

   Eric Bohlman (ebohlman@netcom.com)

CREDITS
=======

   The parse_tokens routine was adapted from the parse_line routine in
Text::Parsewords.

COPYRIGHT
=========

   Copyright (c) 1998-1999 Eric Bohlman. All rights reserved.  This
program is free software; you can redistribute and/or modify it under the
same terms as Perl itself.  =cut

Base class for query builders
*****************************

NAME
====

   Text::Query::Build - Base class for query builders

SYNOPSIS
========

     package Text::Query::BuildMy;

     use Text::Query::Build;

     use vars qw(@ISA);

     @ISA = qw(Text::Query::Build);

DESCRIPTION
===========

   This module provides a virtual base class for query builders.

   Query builders are called by the parser logic. A given set of functions
is provided by the builder to match a Boolean logic.  All the methods
return a scalar corresponding to the code that performs the specified
options.

   Parameters Q1 and Q2 are the same type of scalar as the return values.

METHODS
=======

matchstring()
     Return a string that represent the last built expression. Two
     identical expressions should generate the same string. This is for
     testing purpose.

CODE-GENERATION METHODS
=======================

build_init()
     Called before building the expression. A chance to initialize object
     data.

build_final_expression(Q1)
     Does any final processing to generate code to match a top-level
     expression.  The return value is NOT necessarily of a type that can
     be passed to the other code-generation methods.

build_expression(Q1,Q2)
     Generate code to match `Q1' OR `Q2'

build_expression_finish(Q1)
     Generate any code needed to enclose an expression.

build_conj(Q1,Q2,F)
     Generate code needed to match `Q1' AND `Q2'.  F will be true if this
     is the first time this method is called in a sequence of several
     conjunctions.

     =item build_near(Q1,Q2)

     Generate code needed to match `Q1' NEAR `Q2'.

build_concat(Q1,Q2)
     Generate code needed to match `Q1' immediately followed by `Q2'.

build_negation(Q1)
     Generate code needed to match NOT `Q1'.

build_literal(Q1)
     Generate code to match `Q1' as a literal.

build_scope_start($scope)
     Generate code to enter in the `$scope' query context.

build_scope_end($scope,Q1)
     Generate code needed to match `Q1' in the `$scope' context.

build_mandatory(Q1)
     Generate code to match `Q1' (think + in AltaVista syntax).

build_forbiden(Q1)
     Generate code to match NOT `Q1' (think - in AltaVista syntax).

SEE ALSO
========

   Text::Query(3)

AUTHORS
=======

   Eric Bohlman (ebohlman@netcom.com)

   Loic Dachary (loic@senga.org)

Builder for Text::Query::ParseAdvanced to build regexps
*******************************************************

NAME
====

   Text::Query::BuildAdvancedString - Builder for
Text::Query::ParseAdvanced to build regexps

SYNOPSIS
========

     use Text::Query;
     my $q=new Text::Query('hello and world',
                           -parse => 'Text::Query::ParseAdvanced',
                           -solve => 'Text::Query::SolveAdvancedString',
                           -build => 'Text::Query::BuildAdvancedString');

DESCRIPTION
===========

   Build a regexp to match the advanced query parsed by
Text::Query::ParseAdvanced.  The words of the query can be regular
expressions and will provide the expected result if the `-regexp' option
is set.

SEE ALSO
========

   Text::Query(3) Text::Query::Build(3)

AUTHORS
=======

   Eric Bohlman (ebohlman@netcom.com)

   Loic Dachary (loic@senga.org)

Builder for Text::Query::ParseSimple to build regexps
*****************************************************

NAME
====

   Text::Query::BuildSimpleString - Builder for Text::Query::ParseSimple
to build regexps

SYNOPSIS
========

     use Text::Query;
     my $q=new Text::Query('+hello +world',
                           -parse => 'Text::Query::ParseSimple',
                           -solve => 'Text::Query::SolveSimpleString',
                           -build => 'Text::Query::BuildSimpleString');

DESCRIPTION
===========

   Build a regexp to match the simple query parsed by
Text::Query::ParseSimple.  The words of the query can be regular
expressions and will provide the expected result if the `-regexp' option
is set.

SEE ALSO
========

   Text::Query(3) Text::Query::Build(3)

AUTHORS
=======

   Eric Bohlman (ebohlman@netcom.com)

   Loic Dachary (loic@senga.org)

Base class for query parsers
****************************

NAME
====

   Text::Query::Parse - Base class for query parsers

SYNOPSIS
========

     package Text::Query::OptimizeSmart;

     use Text::Query::Optimize;

     use vars qw(@ISA);

     @ISA = qw(Text::Query::Optimize);

DESCRIPTION
===========

   This module provides a virtual base class for query optimizers.

   It defines the optimize method that is called by the `Text::Query'
object to optimize the internal query.

METHODS
=======

optimize (INTERNAL)
     Returns the INTERNAL argument after optimization. The default
     implementation returns the argument untouched.

SEE ALSO
========

   Text::Query(3)

AUTHORS
=======

   Eric Bohlman (ebohlman@netcom.com)

   Loic Dachary (loic@senga.org)

Base class for query parsers
****************************

NAME
====

   Text::Query::Parse - Base class for query parsers

SYNOPSIS
========

     package Text::Query::ParseThisSyntax;

     use Text::Query::Parse;

     use vars qw(@ISA);

     @ISA = qw(Text::Query::Parse);

DESCRIPTION
===========

   This module provides a virtual base class for query parsers.

   It defines the prepare method that is called by the `Text::Query'
object to compile the query string.

MEMBERS
=======

*-build* Pointer to a Text::Query::Build object.
scope Scope stack. Defines the context in which the query must be solved.
token The current token. Destroyed by prepare.
tokens A reference to the list of all the tokens. Filled by parse_tokens. Destroyed by prepare.
parseopts A reference to a hash table containing all the parameters given to the prepare function.
*-verbose* Integer indicating the desired verbose level.
METHODS
=======

prepare (QSTRING [OPTIONS])
     Compiles the query expression in `QSTRING' to internal form and sets
     any options. First calls `build_init' to reset the builder and
     destroy the token and tokens members. Then calls parse_tokens to fill
     the tokens member. Then calls expression to use the tokens from
     tokens. The expression is expected to call the build_* functions to
     build the compiled expression. At last calls `build_final_expression'
     with the result of expression.

     A derived parser must redefine this function to define default values
     for specific options.

expression ()
     Must be redefined by derived package. Returns the internal form of the
     question built from build_* functions using the tokens.

parse_tokens (QSTRING)
     Must be redefined by derived package. Parses the `QSTRING' scalar and
     fills the tokens member with lexical units.

     Shortcuts to the corresponding function of the Text::Query::Build
     object found in the `-build' member.

OPTIONS
=======

   These are the options of the prepare method and the constructor.

-quotes defaults to \'\"
     Defines the quote characters.

-case defaults to 0
     If true, do case-sensitive match.

-litspace defaults to 0
     If true, match spaces (except between operators) in `QSTRING'
     literally.  If false, match spaces as `\s+'.

-regexp defaults to 0
     If true, treat patterns in `QSTRING' as regular expressions rather
     than literal text.

-whole defaults to 0
     If true, match whole words only, not substrings of words.

SEE ALSO
========

   Text::Query(3)

AUTHORS
=======

   Eric Bohlman (ebohlman@netcom.com)

   Loic Dachary (loic@senga.org)

Parse AltaVista advanced query syntax
*************************************

NAME
====

   Text::Query::ParseAdvanced - Parse AltaVista advanced query syntax

SYNOPSIS
========

     use Text::Query;
     my $q=new Text::Query('hello and world',
                           -parse => 'Text::Query::ParseAdvanced',
                           -solve => 'Text::Query::SolveAdvancedString',
                           -build => 'Text::Query::BuildAdvancedString');

DESCRIPTION
===========

   This module provides an object that parses a string containing a
Boolean query expression similar to an AltaVista "advanced query".

   It's base class is Text::Query::Parse;

   Query expressions consist of literal strings (or regexps) joined by the
following operators, in order of precedence from lowest to highest:

OR, |
AND, &
NEAR, ~
NOT, !
   Operator names are not case-sensitive.  Note that if you want to use a |
in a regexp, you need to backwhack it to keep it from being seen as a query
operator.  Sub-expressions may be quoted in single or double quotes to
match "and," "or," or "not" literally and may be grouped in parentheses
(`(, )') to alter the precedence of evaluation.

   A parenthesized sub-expression may also be concatenated with other sub-
expressions to match sequences: `(Perl or Python) interpreter' would match
either "Perl interpreter" or "Python interpreter".  Concatenation has a
precedence higher than NOT but lower than AND.  Juxtaposition of simple
words has the highest precedence of all.

OPTIONS
=======

   These are the additional options of the prepare method and the
constructor.

-near defaults to 10
     Sets the number of words that can occur between two expressions and
     still satisfy the NEAR operator.

-operators defaults to and, or, not, near
     Sets the operator names. The argument of the option is a pointer to a
     hash table mapping the default names to desired names. For instance:

          {
          	'or' => 'ou',
          	'and' => 'et',
          	'near' => 'proche',
          	'not' => 'non',
          }

-scope_map default to {}
     Map the scope names to other names. If a scope is specified as
     `scope:' search the map for an entry whose key is scope and replace
     scope with the scalar found. For instance:

          {
          	 'scope' => 'otherscope'
          }

SEE ALSO
========

   Text::Query(3) Text::Query::Parse(3)

AUTHORS
=======

   Eric Bohlman (ebohlman@netcom.com)

   Loic Dachary (loic@senga.org)

Parse AltaVista simple query syntax
***********************************

NAME
====

   Text::Query::ParseSimple - Parse AltaVista simple query syntax

SYNOPSIS
========

     use Text::Query;
     my $q=new Text::Query('hello and world',
                           -parse => 'Text::Query::ParseSimple',
                           -solve => 'Text::Query::SolveSimpleString',
                           -build => 'Text::Query::BuildSimpleString');

DESCRIPTION
===========

   This module provides an object that parses a string containing a
Boolean query expression similar to an AltaVista "simple query". Elements
of the query expression may be assigned weights.

   It's base class is Text::Query::Parse;

   Query expressions are compiled into an internal form when a new object
is created or the prepare method is called; they are not recompiled on each
match.

   Query expressions consist of words (sequences of non-whitespace) or
phrases (quoted strings) separated by whitespace.  Words or phrases
prefixed with a + must be present for the expression to match; words or
phrases prefixed with a - must be absent for the expression to match.

   Words or phrases may optionally be followed by a number in parentheses
(no whitespace is allowed between the word or phrase and the parenthesized
number).  This number specifies the weight given to the word or phrase.
If a weight is not given, a weight of 1 is assumed.

EXAMPLES
========

     use Text::Query;
     my $q=new Text::Query('+hello world',
                           -solve => 'Text::Query::SolveSimpleString',
                           -build => 'Text::Query::BuildSimpleString');
     die "bad query expression" if not defined $q;
     $count=$q->match;
     ...
     $q->prepare('goodbye adios -"ta ta"', -litspace=>1);
     #requires single space between the two ta's
     if ($q->match($line, -case=>1)) {
     #doesn't match "Goodbye"
     ...
     $q->prepare('\\bintegrate\\b', -regexp=>1);
     #won't match "disintegrated"
     ...
     $q->prepare('information(2) retrieval');
     #information has twice the weight of retrieval

SEE ALSO
========

   Text::Query(3) Text::Query::Parse(3)

AUTHORS
=======

   Eric Bohlman (ebohlman@netcom.com)

   Loic Dachary (loic@senga.org)

Match text against simple query expression and return relevance value for ranking
*********************************************************************************

NAME
====

   Text::Query::Simple - Match text against simple query expression and
return relevance value for ranking

SYNOPSIS
========

     use Text::Query::Simple;

     # Constructor
     $query = Text::Query::Simple->new([QSTRING] [OPTIONS]);

     # Methods
     $query->prepare(QSTRING [OPTIONS]);
     $query->match([TARGET]);
     $query->matchscalar([TARGET]);

DESCRIPTION
===========

   This module provides an object that tests a string or list of strings
against a query expression similar to an AltaVista "simple  query" and
returns a "relevance value."  Elements of the query expression may be
regular expressions or literal text, and may be assigned weights.

   Query expressions are compiled into an internal form when a new object
is created or the prepare method is called; they are not recompiled on each
match.

   Query expressions consist of words (sequences of non-whitespace),
regexps or phrases (quoted strings) separated by whitespace.  Words or
phrases prefixed with a + must be present for the expression to match;
words or phrases prefixed with a - must be absent for the expression to
match.

   A successful match returns a count of the number of times any of the
words (except ones prefixed with -) appeared in the text.  This type of
result is useful for ranking documents according to relevance.

   Words or phrases may optionally be followed by a number in parentheses
(no whitespace is allowed between the word or phrase and the parenthesized
number).  This number specifies the weight given to the word or phrase; it
will be added to the count each time the word or phrase appears in the
text.  If a weight is not given, a weight of 1 is assumed.

EXAMPLES
========

     use Text::Query::Simple;
     my $q=new Text::Query::Simple('+hello world');
     die "bad query expression" if not defined $q;
     $count=$q->match;
     ...
     $q->prepare('goodbye adios -"ta ta",-litspace=>1);
     #requires single space between the two ta's
     if ($q->match($line,-case=>1)) {
     #doesn't match "Goodbye"
     ...
     $q->prepare('\\bintegrate\\b',-regexp=>1);
     #won't match "disintegrated"
     ...
     $q->prepare('information(2) retrieval');
     #information has twice the weight of retrieval

CONSTRUCTOR
===========

new ([QSTRING] [OPTIONS])
     This is the constructor for a new Text::Query::Simple object.  If a
     `QSTRING' is given it will be compiled to internal form.

     OPTIONS are passed in a hash like fashion, using key and value pairs.
     Possible options are:

     *-case* - If true, do case-sensitive match.

     *-litspace* - If true, match spaces (except between operators) in
     `QSTRING' literally.  If false, match spaces as `\s+'.

     *-regexp* - If true, treat patterns in `QSTRING' as regular
     expressions rather than literal text.

     *-whole* - If true, match whole words only, not substrings of words.

     The constructor will return undef if a `QSTRING' was supplied and had
     illegal syntax.

METHODS
=======

prepare (QSTRING [OPTIONS])
     Compiles the query expression in `QSTRING' to internal form and sets
     any options (same as in the constructor).  prepare may be used to
     change the query expression and options for an existing query object.
     If OPTIONS are omitted, any options set by a previous call to the
     constructor or prepare remain in effect.

     This method returns a reference to the query object if the syntax of
     the expression was legal, or undef if not.

match ([TARGET])
     If `TARGET' is a scalar, match returns the number of words in the
     string specified by `TARGET' that match the query object's query
     expression.  If `TARGET' is not given, the match is made against $_.

     If `TARGET' is an array, match returns a list of references to
     anonymous arrays consisting of each element followed by its match
     count.  The list is sorted in descending order by match count.  If
     the elements of `TARGET' were anonymous arrays, the match count is
     appended to each element.  This allows arbitrary information (such as
     a filename) to be associated with each element.

     If `TARGET' is a reference to an array, match returns a reference to
     a sorted list of matching items, with counts, for all elements.

matchscalar ([TARGET])
     Behaves just like MATCH when `TARGET' is a scalar or is not given.
     Slightly faster than MATCH under these circumstances.

RESTRICTIONS
============

   This module requires Perl 5.005 or higher due to the use of evaluated
expressions in regexes

AUTHOR
======

   Eric Bohlman (ebohlman@netcom.com)

CREDITS
=======

   The parse_tokens routine was adapted from the parse_line routine in
Text::Parsewords.

COPYRIGHT
=========

   Copyright (c) 1998 Eric Bohlman. All rights reserved.  This program is
free software; you can redistribute and/or modify it under the same terms
as Perl itself.  =cut

Base class for query resolution
*******************************

NAME
====

   Text::Query::Solve - Base class for query resolution

SYNOPSIS
========

     package Text::Query::SolveSource;

     use Text::Query::Parse;

     use vars qw(@ISA);

     @ISA = qw(Text::Query::Solve);

DESCRIPTION
===========

   This module provides a virtual base class for query resolution.

   It defines the match and matchscalar method that is called by the
`Text::Query' object to apply a query on a data source.

METHODS
=======

match (EXPR [TARGET])
     If `TARGET' is a scalar, match returns a true value if the data source
     specified by `TARGET' matches the EXPR query expression.  If `TARGET'
     is not given, the match is made against $_.

     If `TARGET' is an array, match returns a (possibly empty) list of all
     matching elements.  If the elements of the array are references to
     sub- arrays, the match is done against the first element of each
     sub-array.  This allows arbitrary information (e.g. filenames) to be
     associated with each data source to match.

     If `TARGET' is a reference to an array, match returns a reference to
     a (possibly empty) list of all matching elements.

matchscalar (EXPR [TARGET])
     Behaves just like MATCH when `TARGET' is a scalar or is not given.

SEE ALSO
========

   Text::Query(3)

AUTHORS
=======

   Eric Bohlman (ebohlman@netcom.com)

   Loic Dachary (loic@senga.org)

Apply query expression on strings
*********************************

NAME
====

   Text::Query::SolveAdvancedString - Apply query expression on strings

SYNOPSIS
========

     use Text::Query;
     my $q=new Text::Query('hello and world',
                           -parse => 'Text::Query::ParseAdvanced',
                           -solve => 'Text::Query::SolveAdvancedString',
                           -build => 'Text::Query::BuildAdvancedString');

     $q->match('this hello is a world')

DESCRIPTION
===========

   Applies an expression built by Text::Query::BuildAdvancedString to a
list of strings.

METHODS
=======

match ([TARGET])
     If `TARGET' is a scalar, match returns a true value if the string
     specified by `TARGET' matches the query object's query expression.  If
     `TARGET' is not given, the match is made against $_.

     If `TARGET' is an array, match returns a (possibly empty) list of all
     matching elements.  If the elements of the array are references to
     sub- arrays, the match is done against the first element of each
     sub-array.  This allows arbitrary information (e.g. filenames) to be
     associated with each string to match.

     If `TARGET' is a reference to an array, match returns a reference to
     a (possibly empty) list of all matching elements.

matchscalar ([TARGET])
     Behaves just like MATCH when `TARGET' is a scalar or is not given.
     Slightly faster than MATCH under these circumstances.

AUTHORS
=======

   Eric Bohlman (ebohlman@netcom.com)

   Loic Dachary (loic@senga.org)

Apply query expression on strings
*********************************

NAME
====

   Text::Query::SolveSimpleString - Apply query expression on strings

SYNOPSIS
========

     use Text::Query;
     my $q=new Text::Query('+hello +world',
                           -parse => 'Text::Query::ParseSimple',
                           -solve => 'Text::Query::SolveSimpleString',
                           -build => 'Text::Query::BuildSimpleString');

     $q->match('this hello is a world')

DESCRIPTION
===========

   Applies an expression built by Text::Query::BuildSimpleString to a list
of strings.

METHODS
=======

match ([TARGET])
     If `TARGET' is a scalar, match returns a true value if the string
     specified by `TARGET' matches the query object's query expression.  If
     `TARGET' is not given, the match is made against $_.

     If `TARGET' is an array, match returns a (possibly empty) list of all
     matching elements.  If the elements of the array are references to
     sub- arrays, the match is done against the first element of each
     sub-array.  This allows arbitrary information (e.g. filenames) to be
     associated with each string to match.

     If `TARGET' is a reference to an array, match returns a reference to
     a (possibly empty) list of all matching elements.

matchscalar ([TARGET])
     Behaves just like MATCH when `TARGET' is a scalar or is not given.
     Slightly faster than MATCH under these circumstances.

AUTHORS
=======

   Eric Bohlman (ebohlman@netcom.com)

   Loic Dachary (loic@senga.org)

parse Unix "refer" files
************************

NAME
====

   Text::Refer - parse Unix "refer" files

   *This is Alpha code, and may be subject to changes in its public
interface.  It will stabilize by June 1997, at which point this notice
will be removed.  Until then, if you have any feedback, please let me
know!*

SYNOPSIS
========

   Pull in the module:

     use Text::Refer;

   Parse a refer stream from a filehandle:

     while ($ref = input Text::Refer \*FH)  {
     	# ...do stuff with $ref...
     }
     defined($ref) or die "error parsing input";

   Same, but using a parser object for more control:

   # Create a new parser:     $parser = new Text::Refer::Parser
LeadWhite=>'KEEP';

   # Parse:     while ($ref = $parser->input(\*FH))  { 	# ...do stuff with
$ref...      }     defined($ref) or die "error parsing input";

   Manipulating reference objects, using high-level methods:

     # Get the title, author, etc.:
     $title      = $ref->title;
     @authors    = $ref->author;      # list context
     $lastAuthor = $ref->author;      # scalar context

     # Set the title and authors:
     $ref->title("Cyberiad");
     $ref->author(["S. Trurl", "C. Klapaucius"]);   # arrayref for >1 value!

     # Delete the abstract:
     $ref->abstract(undef);

   Same, using low-level methods:

     # Get the title, author, etc.:
     $title      = $ref->get('T');
     @authors    = $ref->get('A');      # list context
     $lastAuthor = $ref->get('A');      # scalar context

     # Set the title and authors:
     $ref->set('T', "Cyberiad");
     $ref->set('A', "S. Trurl", "C. Klapaucius");

     # Delete the abstract:
     $ref->set('X');                    # sets to empty array of values

   Output:

     print $ref->as_string;

DESCRIPTION
===========

   *This module supercedes the old Text::Bib.*

   This module provides routines for parsing in the contents of
"refer"-format bibliographic databases: these are simple text files which
contain one or more bibliography records.  They are usually found lurking
on Unix-like operating systems, with the extension `.bib'.

   Each record in a "refer" file describes a single paper, book, or
article.  Users of nroff/troff often employ such databases when
typesetting papers.

   Even if you don't use *roff, this simple, easily-parsed parameter-value
format is still useful for recording/exchanging bibliographic information.
With this module, you can easily post-process "refer" files: search them,
convert them into LaTeX, whatever.

Example
-------

   Here's a possible "refer" file with three entries:

     %T Cyberiad
     %A Stanislaw Lem
     %K robot fable
     %I Harcourt/Brace/Jovanovich

     %T Invisible Cities
     %A Italo Calvino
     %K city fable philosophy
     %X In this surreal series of fables, Marco Polo tells an
        aged Kublai Khan of the many cities he has visited in
        his lifetime.

     %T Angels and Visitations
     %A Neil Gaiman
     %D 1993

   The lines separating the records must be *completely blank*; that is,
they cannot contain anything but a single newline.

   See refer(1) or grefer(1) for more information on "refer" files.

Syntax
------

   *From the GNU manpage, `grefer(1)':*

   The  bibliographic  database  is a text file consisting of records
separated by one or more blank lines.  Within each record  fields  start
with a % at the beginning of a line.  Each field has a one character name
that immediately  follows the  %.  It is best to use only upper and lower
case letters for the names of fields. The name  of  the  field should  be
followed by exactly one space, and then by the contents of the field.
Empty  fields  are  ignored.   The conventional meaning of each field is
as follows:

A
     The name of an author. If the name contains a title such as Jr. at
     the end, it should	be separated from the last name by a comma.  There
     can be multiple occurrences of the A field.  The order is significant.
     It is a good idea always to supply an A field or a Q field.

B
     For an article that is part of a book, the title of the book

C
     The place (city) of publication.

D
     The date of publication.  The year should be specified in full.  If
     the month is specified, the name rather than the number of the month
     should be used, but only the first three letters are required.  It is
     a good idea always to supply a D field; if the date is unknown, a
     value such as "in press" or "unknown" can be used.

E
     For  an article that is part of a book, the name of an editor of the
     book.  Where the work has editors and no authors, the names of the
     editors should be  given as A fields and , (ed) or , (eds)  should  be
     appended to the last author.

G
     US Government ordering number.

I
     The publisher (issuer).

J
     For an article in a journal, the name of the journal.

K
     Keywords to be used for searching.

L
     Label.

     NOTE: Uniquely identifies the entry.  For example, "Able94".

N
     Journal issue number.

O
     Other information.  This is usually printed at the end of the
     reference.

P
     Page number.  A range of pages can be specified as m-n.

Q
     The name of the author, if the author is not a person.  This will
     only be used if there are no A fields.  There can only be one Q field.

     NOTE: Thanks to Mike Zimmerman for clarifying this for me: it means a
     "corporate" author: when the "author" is listed as an organization
     such as the UN, or RAND Corporation, or whatever.

R
     Technical report number.

S
     Series name.

T
     Title.  For an article in a book or journal, this should be the title
     of the article.

V
     Volume number of the journal or book.

X
     Annotation.

     NOTE: Basically, a brief abstract or description.

   For all fields except A and E, if there is more than one occurrence of
a particular field in a record, only the last such field will be used.

   If accent strings are used, they should follow the character to be
accented.  This means that the AM macro must  be used  with  the -ms
macros.  Accent strings should not be quoted: use one \ rather than two.

Parsing records from "refer" files
----------------------------------

   You will nearly always use the `input()' constructor to create new
instances, and nearly always as shown in the `"SYNOPSIS"' in this node.

   Internally, the records are parsed by a parser object; if you invoke
the class method `Text::Refer::input()', a special default parser is used,
and this will be good enough for most tasks.  However, for more complex
tasks, feel free to use `"class Text::Refer::Parser"' in this node to
build (and use) your own fine-tuned parser, and `input()' from that
instead.

CLASS Text::Refer
=================

   Each instance of this class represents a single record in a "refer"
file.

Construction and input
----------------------

new
     *Class method, constructor.* Build an empty "refer" record.

input FILEHANDLE
     *Class method.* Input a new "refer" record from a filehandle.  The
     default parser is used:

          while ($ref = input Text::Refer \*STDIN) {
          	# ...do stuff with $ref...
          }

     Do not use this as an instance method; it will not re-init the object
     you give it.

Getting/setting attributes
--------------------------

attr ATTR, [VALUE]
     *Instance method.* Get/set the attribute by its one-character name,
     ATTR.  The VALUE is optional, and may be given in a number of ways:

        * *If the VALUE is given as undefined*, the attribute will be
          deleted:

               $ref->attr('X', undef);        # delete the abstract

        * *If a defined, non-reference scalar VALUE is given,* it is used
          to replace the existing values for the attribute with that
          single value:

               $ref->attr('T', "The Police State Rears Its Ugly Head");
               $ref->attr('D', 1997);

        * *If an arrayref VALUE is given,* it is used to replace the
          existing values for the attribute with *all elements of that
          array:*

               $ref->attr('A', ["S. Trurl", "C. Klapaucius"]);

          We use an arrayref since an empty array would be impossible to
          distinguish from the next two cases, where the goal is to "get"
          instead of "set"...

     This method returns the current (or new) value of the given attribute,
     just as get() does:

        * *If invoked in a scalar context,* the method will return the
          last value (this is to mimic the behavior of *groff*).  Hence,
          given the above, the code:

               $author = $ref->attr('A');

          will set `$author' to `"C. Klapaucius"'.

        * *If invoked in an array context,* the method will return the list
          of all values, in order.  Hence, given the above, the code:

               @authors = $ref->attr('A');

          will set `@authors' to `("S. Trurl", "C. Klapaucius")'.

     Note: this method is used as the basis of all "named" access methods;
     hence, the following are equivalent in every way:

          $ref->attr(T => $title)    <=>   $ref->title($title);
          $ref->attr(A => \@authors) <=>   $ref->author(\@authors);
          $ref->attr(D => undef)     <=>   $ref->date(undef);
          $auth  = $ref->attr('A')   <=>   $auth  = $ref->author;
          @auths = $ref->attr('A')   <=>   @auths = $ref->author;

author, book, city, ... [VALUE]
     *Instance methods.* For every one of the standard fields in a "refer"
     record, this module has designated a high-level attribute name:

          A  author     G  govt_no      N  number        S  series
          B  book       I  publisher    O  other_info    T  title
          C  city       J  journal      P  page          V  volume
          D  date       K  keywords     Q  corp_author   X  abstract
          E  editor     L  label        R  report_no

     Then, for each field F with high-level attribute name *FIELDNAME*,
     the method `FIELDNAME()' works as follows:

          $ref->attr('F', @args)     <=>   $ref->FIELDNAME(@args)

     Which means:

          $ref->attr(T => $title)    <=>   $ref->title($title);
          $ref->attr(A => \@authors) <=>   $ref->author(\@authors);
          $ref->attr(D => undef)     <=>   $ref->date(undef);
          $auth  = $ref->attr('A')   <=>   $auth  = $ref->author;
          @auths = $ref->attr('A')   <=>   @auths = $ref->author;

     See the documentation of attr() for the argument list.

get ATTR
     *Instance method.* Get an attribute, by its one-character name.  In
     an array context, it returns all values (empty if none):

          @authors = $ref->get('A');      # returns list of all authors

     In a scalar context, it returns the last value (undefined if none):

          $author = $ref->get('A');       # returns the last author

set ATTR, VALUES...
     *Instance method.* Set an attribute, by its one-character name.

          $ref->set('A', "S. Trurl", "C. Klapaucius");

     An empty array of VALUES deletes the attribute:

          $ref->set('A');       # deletes all authors

     No useful return value is currently defined.

Output
------

as_string [OPTSHASH]
     *Instance method.* Return the "refer" record as a string, usually for
     printing:

          print $ref->as_string;

     The options are:

    Quick
          If true, do it quickly, but unsafely.  *This does no fixup on
          the values at all:* they are output as-is.  That means if you
          used parser-options which destroyed any of the formatting
          whitespace (e.g., `Newline=TOSPACE' with `LeadWhite=KILLALL'),
          there is a risk that the output object will be an invalid
          "refer" record.

     The fields are output with %L first (if it exists), and then the
     remaining fields in alphabetical order.  The following "safety
     measures" are normally taken:

        * Lines longer than 76 characters are wrapped (if possible, at a
          non-word character a reasonable length in, but there is a chance
          that they will simply be "split" if no such character is
          available).

        * Any occurences of '%' immediately after a newline are preceded
          by a single space.

     These safety measures are slightly time-consuming, and are silly if
     you are merely outputting a "refer" object which you have read in
     verbatim (i.e., using the default parser-options) from a valid
     "refer" file.  In these cases, you may want to use the Quick option.

     =cut

     sub as_string {     my ($self, %opts) = @_;     my ($key, $val);

          # Figure out the keys to use, and put them in order:
          my @keys = sort grep {(length == 1) && ($_ ne 'L')} (keys %$self);
          defined($self->{'L'}) && unshift(@keys, 'L');

          # Output:
          my @lines;
          foreach $key (@keys) {
          	foreach $val (@{$self->{$key}}) {
          	    unless ($opts{Quick}) {
          		### print "UNWRAPPED = [$val]\n";
          		_wrap($val);             # make sure no line exceeds 80 chars
          		### print "WRAPPED   = [$val]\n";
          		$val =~ s/\n%/\n %/g;    # newlines must NOT be followed by %
          		$val =~ s/\n+\Z//;       # strip trailing newlines
          	    }
          	    push @lines, join('', '%', $key, ' ', $val, "\n");
          	}
          }
          join '', @lines;
          }

CLASS Text::Refer::Parser
=========================

   Instances of this class do the actual parsing.

Parser options
--------------

   The options you may give to new() are as follows:

ForgiveEOF
     Normally, the last record in a file must end with a blank line, or
     else this module will suspect it of being incomplete and return an
     error.  However, if you give this option as true, it will allow the
     last record to be terminated by an EOF.

GoodFields
     By default, the parser accepts any (one-character) field name that is
     a printable ASCII character (no whitespace).  Formally, this is:

          [\041-\176]

     However, when compiling parser options, you can supply your own
     regular expression for validating (one-character) field names.
     (*note:* you must supply the square brackets; they are there to remind
     you that you should give a well-formed single-character expression).
     One standard expression is provided for you:

          $Text::Refer::GroffFields  = '[A-EGI-LN-TVX]';  # legal groff fields

     Illegal fields which are encounterd during parsing result in a syntax
     error.

     NOTE: You really shouldn't use this unless you absolutely need to.
     The added regular expression test slows down the parser.

LeadWhite
     In many "refer" files, continuation lines (the 2nd, 3rd, etc. lines
     of a field) are written with leading whitespace, like this:

          %T Incontrovertible Proof that Pi Equals Three
             (for Large Values of Three)
          %A S. Trurl
          %X The author shows how anyone can use various common household
             objects to obtain successively less-accurate estimations of
             pi, until finally arriving at a desired integer approximation,
             which nearly always is three.

     This leading whitespace serves two purposes: (1) it makes it
     impossible to mistake a continuation line for a field, since % can no
     longer be the first character, and (2) it makes the entries easier to
     read.  The LeadWhite option controls what is done with this
     whitespace:

          KEEP	- default; the whitespace is untouched
          KILLONE	- exactly one character of leading whitespace is removed
          KILLALL	- all leading whitespace is removed

     See the section below on "using the parser options" for hints and
     warnings.

Newline
     The Newline option controls what is done with the newlines that
     separate adjacent lines in the same field:

          KEEP	- default; the newlines are kept in the field value
          TOSPACE	- convert each newline to a single space
          KILL	- the newlines are removed

     See the section below on "using the parser options" for hints and
     warnings.

   Default values will be used for any options which are left unspecified.

Notes on the parser options
---------------------------

   The default values for Newline and LeadWhite will preserve the input
text exactly.

   The `Newline=TOSPACE' option, when used in conjunction with the
`LeadWhite=KILLALL' option, effectively "word-wraps" the text of each
field into a single line.

   *Be careful!* If you use the `Newline=KILL' option with either the
`LeadWhite=KILLONE' or the `LeadWhite=KILLALL' option, you could end up
eliminating all whitespace that separates the word at the end of one line
from the word at the beginning of the next line.

Public interface
----------------

new PARAMHASH
     *Class method, constructor.* Create and return a new parser.  See
     above for the `"parser options"' in this node which you may give in
     the PARAMHASH.

create [CLASS]
     *Instance method.* What class of objects to create.  The default is
     `Text::Refer'.

input FH
     *Instance method.* Create a new object from the next record in a
     "refer" stream.  The actual class of the object is given by the
     `class()' method.

     Returns the object on success, '0' on *expected* end-of-file, and
     undefined on error.

     Having two false values makes parsing very simple: just `input()'
     records until the result is false, then check to see if that last
     result was 0 (end of file) or undef (failure).

NOTES
=====

Under the hood
--------------

   Each "refer" object has instance variables corresponding to the actual
field names ('T', 'A', etc.).  Each of these is a reference to an array of
the actual values.

   Notice that, for maximum flexibility and consistency (but at the cost of
some space and access-efficiency), the semantics of "refer" records do not
come into play at this time: since everything resides in an array, you can
have as many %K, %D, etc. records as you like, and given them entirely
different semantics.

   For example, the Library Of Boring Stuff That Everyone Reads (LOBSTER)
uses the unused %Y as a "year" field.  The parser accomodates this case by
politely not choking on LOBSTER .bibs (although why you would want to eat
a lobster bib instead of the lobster is beyond me...).

Performance
-----------

   Tolerable.  On my 90MHz/32 MB RAM/I586 box running Linux 1.2.13 and
Perl5.002, it parses a typical 500 KB "refer" file (of 1600 records) as
follows:

     8 seconds of user time for input and no output
         10 seconds of user time for input and "quick" output
         16 seconds of user time for input and "safe" output

   So, figure the individual speeds are:

     input:            200 records ( 60 KB) per second.
     "quick" output:   800 records (240 KB) per second.
     "safe" output:    200 records ( 60 KB) per second.

   By contrast, a C program which does the same work is about 8 times as
fast.  But of course, the C code is 8 times as large, and 8 times as
ugly...  `:-)'

Note to serious bib-file users
------------------------------

   I actually do not use "refer" files for *roffing... I used them as a
quick-and-dirty database for WebLib, and that's where this code comes
from.  If you're a serious user of "refer" files, and this module doesn't
do what you need it to, please contact me: I'll add the functionality in.

BUGS
====

   Some combinations of parser-options are silly.

CHANGE LOG
==========

   $Id: Refer.pm,v 1.106 1997/04/22 18:41:41 eryq Exp $

Version 1.101
     Initial release.  Adapted from Text::Bib.

AUTHOR
======

   Copyright (C) 1997 by Eryq, `eryq@enteract.com',
`http://www.enteract.com/~eryq'.

NO WARRANTY
===========

   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.

   For a copy of the GNU General Public License, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

Perl module for reflowing text files using Knuth's paragraphing algorithm.
**************************************************************************

NAME
====

   Text::Reflow - Perl module for reflowing text files using Knuth's
paragraphing algorithm.

SYNOPSIS
========

     use Text::Reflow qw(reflow_file reflow_string reflow_array);

     reflow_file($infile, $outfile, key => value, ...);

     $output = reflow_string($input, key => value, ...);

     $output = reflow_array(\@input, key => value, ...);

DESCRIPTION
===========

   These routines will reflow the paragraphs in the given file,
filehandle, string or array using Knuth's paragraphing algorithm (as used
in TeX) to pick "good" places to break the lines.

   Each routine takes ascii text data with paragraphs separated by blank
lines and reflows the paragraphs.  If two or more lines in a row are
"indented" then they are assumed to be a quoted poem and are passed
through unchanged (but see below)

   The reflow algorithm tries to keep the lines the same length but also
tries to break at punctuation, and avoid breaking within a proper name or
after certain *connectives* ("a", "the", etc.). The result is a file with
a more "ragged" right margin than is produced by fmt or Text::Wrap but it
is easier to read since fewer phrases are broken across line breaks.

   For `reflow_file', if $infile is the empty string, then the input is
taken from STDIN and if $outfile is the empty string, the output is
written to STDOUT.  Otherwise, $infile and $outfile may be a string, a
FileHandle reference or a FileHandle glob.

   A typical invocation is:

     reflow_file("myfile", "");

   which reflows the whole of `myfile' and prints the result to STDOUT.

KEYWORD OPTIONS
---------------

   The behaviour of Reflow can be adjusted by setting various keyword
options.  These can be set globally by referencing the appropriate
variable in the Text::Reflow package, for example:

     $Text::Reflow::maximum = 80;
     $Text::Reflow::optimum = 75;

   will set the maximum line length to 80 characters and the optimum line
length to 75 characters for all subsequent reflow operations.  Or they can
be passed to a reflow_ function as a keyword parameter, for example:

     $out = reflow_string($in, maximum => 80, optimum => 75);

   in which case the new options only apply to this call.

   The following options are currently implemented, with their default
values:

optimum => [65]
     The optimum line length in characters.  This can be either a number
     or a reference to an array of numbers:  in the latter case, each
     optimal line length is tried in turn for each paragraph, and the one
     which leads to the best overall paragraph is chosen.  This results in
     less ragged paragraphs, but some paragraphs will be wider or narrower
     overall than others.

maximum => 75
     The maximum allowed line length.

indent => ""
     Each line of output has this string prepended. `indent => string' is
     equivalent to `indent1 => string, indent2 => string'.

indent1 => ""
     A string which is used to indent the first line in any paragraph.

indent2 => ""
     A string which is used to indent the second and subsequent line in
     any paragraph.

quote => ""
     Characters to strip from the beginning of a line before processing.
     To reflow a quoted email message and then restore the quotes you
     might want to use

          quote => "> ", indent => "> "

skipto => ""
     Skip to the first line starting with the given pattern before starting
     to reflow. This is useful for skipping Project Gutenberg headers or
     contents tables.

skipindented => 2
     If skipindented = 0 then all indented lines are flowed in with the
     surrounding paragraph.  If skipindented = 1 then any indented line
     will not be reflowed.  If skipindented = 2 then any two or more
     adjacent indented lines will not be reflowed.  The purpose of the
     default value is to allow poetry to pass through unchanged, but not
     to allow a paragraph indentation from preventing the first line of
     the paragraph from being reflowed.

noreflow => ""
     A pattern to indicate that certain lines should not be reflowed.  For
     example, a table of contents might have a line of dots.  The option:

          noreflow => '(\.\s*){4}\.'

     will not reflow any lines containing five or more consecutive dots.

frenchspacing => 'n'
     Normally two spaces are put at the end of a sentance or a clause.
     The frenchspacing option (taken from the TeX macro of the same name)
     disables this feature.

oneparagraph => 'n'
     Set this to 'y' if you want the whole input to be flowed into a single
     paragraph, ignoring blank lines in the input.

semantic => 30
     This parameter indicates the extent to which semantic factors matter
     (breaking on punctuation, avoiding a break within a clause etc.).
     Set this to zero to minimise the raggedness of the right margin, at
     the expense of readability.

namebreak => 10
     Penalty for splitting up a name

sentence => 20
     Penalty for sentence widows and orphans (ie splitting a line
     immediately after the first word in a sentence, or before the last
     word in a sentence)

independent => 10
     Penalty for independent clause widows and orphans.

dependent => 6
     Penalty for dependent clause widows and orphans.

shortlast => 5
     Penalty for a short last line in a paragraph (one or two words).

connpenalty => 1
     Multiplier for the "negative penalty" for breaking at a connective.
     In other words, increasing this value makes connectives an even more
     attractive place to break a line.

EXPORT
------

   None by default.

AUTHOR
======

   Original `reflow' perl script written by Michael Larsen,
larsen@edu.upenn.math.

   Modified, enhanced and converted to a perl module with XSUB by Martin
Ward, Martin.Ward@durham.ac.uk

SEE ALSO
========

   perl(1).

   See "TeX the Program" by Donald Knuth for a description of the
algorithm used.

Converts roman algarism in integer numbers and the contrary, recognize algarisms.
*********************************************************************************

NAME
====

   Text::Roman - Converts roman algarism in integer numbers and the
contrary, recognize algarisms.

SYNOPSIS
========

     use Text::Roman;

     print roman(123);

DESCRIPTION
===========

   Text::Roman::roman() is a very simple algarism converter. It converts a
single integer (in arabic algarisms) at a time to its roman correspondent.
The conventional roman numbers goes from 1 up to 3999. MROMANS (milhar
romans) range is 1 up to 3999*1000+3999=4002999.

   Up to these number we will found symbols as:??????but they do not
concern this specific package. There is no concern for mix cases, like
'Xv', 'XiiI', as legal roman algarism numbers.

*roman($int)*: return string containing  the roman corresponding to the given integer, or " if the integer is out of domain...

*roman2int($str)*: return " if $str is not roman or return integer if it is.
*isroman($str)*: verify whether the given string is a conventional roman number, if it is return 1; if it is not return 0...
   Quite same follows for *mroman2int($str)* and *ismroman($str)*, except
that these functions treat milhar romans.

SPECIFICATION
=============

   Roman number has origin in following BNF-like formula:

   a =	I{1,3}

   b =	V\a?|IV|\a

   e =	X{1,3}\b?|X{0,3}IX|\b

   ee =	IX|\b

   f =	L\e?|XL\ee?|\e

   g =	C{1,3}\f?|C{0,3}XC\ee?|\f

   gg =	XC\ee?|\f

   h =	D\g?|CD\gg?|\g

   j =	M{1,3}\h?|M{0,3}CM\gg?|\h

REFERENCES
==========

   Especification supplied by redactor's manual of newspaper "O Estado de
São Paulo".  URL: http://www.estado.com.br/redac/norn-nro.html

EXAMPLE
=======

     use Text::Roman;

     $roman	= "XXXV";
     $mroman	= 'L_X_XXIII';
     print roman(123), "\n";
     print roman2int($roman), "\n"	if isroman($roman);
     print mroman2int($mroman), "\n"	if ismroman($mroman);

BUGS
====

   No one known.

AUTHOR
======

   Peter de Padua Krauss, krauss@ifqsc.sc.usp.br.

COPYRIGHT
=========

   1.2-krauss/set/97; 1.0-krauss/3/ago/97

Lightweight processor for full-featured template
************************************************

NAME
====

     Text::ScriptTemplate - Lightweight processor for full-featured template

SYNOPSIS
========

     use Text::ScriptTemplate;

     $tmpl = new Text::ScriptTemplate;    # create processor object
     $tmpl->setq(TEXT => "hello, world"); # export data to template
     $tmpl->load($file);                  # loads template from named file
     $tmpl->pack(q{TEXT: <%= $TEXT; %>}); # loads template from in-memory data

     print $tmpl->fill;                   # prints "TEXT: hello, world"

     # load intermixed Perl script and text as a template
     $tmpl->pack(q{<% for (1..3) { %>i = <%= "$_\n"; %><% } %>});

     print $tmpl->fill;                   # prints "i = 1\ni = 2\ni = 3\n"

DESCRIPTION
===========

   This is a varient of Text::SimpleTemplate, a module for template-based
text generation.

   Template-based text generation is a way to separate program code and
data, so non-programmer can control final result (like HTML) as desired
without tweaking the program code itself. By doing so, jobs like website
maintenance is much easier because you can leave program code unchanged
even if page redesign was needed.

   The idea of this module is simple. Whenever a block of text surrounded
by '<%' and '%>' (or any pair of delimiters you specify) is found, it will
be taken as Perl expression, and will be handled specially by template
processing engine. With this module, Perl script and text can be
intermixed closely.

   Major goal of this library is to provide support of powerful PHP-style
template with smaller resource. This is useful when PHP, HTML::Embperl, or
Apache::ASP is overkill, but their template style is still desired.

INSTALLATION / REQUIREMENTS
===========================

   This module requires Carp.pm and FileHandle.pm.  Since these are
standard modules, all you need is perl itself.

   For installation, standard procedure of

     perl Makefile.PL
     make
     make test
     make install

   should work just fine.

TEMPLATE SYNTAX AND USAGE
=========================

   Any block of text surrounded by '<%' and '%>' will be handled specially
by template processor.

   For block surrounded by '<%=' and '%>, it will be taken as simple perl
expression, and will be replace by its evaluated result.

   For block surrounded by '<%' and '%>, it will be taken as part of
control structure, and after all parts are merged into one big block, it
will be evaluated and the result will be handled as output.

   Suppose you have a following template named "sample.tmpl":

     === Module Information ===
     <% if ($HAS->{Text::ScriptTemplate}) { %>
     Name: <%= $INFO->{Name}; %>
     Description: <%= $INFO->{Description}; %>
     Author: <%= $INFO->{Author}; %> <<%= $INFO->{Email}; %>>
     <% } else { %>
     Text::ScriptTemplate is not installed.
     <% } %>

   With the following code...

     use Safe;
     use Text::ScriptTemplate;

     $tmpl = new Text::ScriptTemplate;
     $tmpl->setq(INFO => {
         Name        => "Text::ScriptTemplate",
         Description => "Lightweight processor for full-featured template",
         Author      => "Taisuke Yamada",
         Email       => "tai\@imasy.or.jp",
     });
     $tmpl->setq(HAS => { Text::ScriptTemplate => 1 }); # installed
     $tmpl->load("sample.tmpl");

     print $tmpl->fill(PACKAGE => new Safe);

   ...you will get following result:

     === Module Information ===

     Name: Text::ScriptTemplate
     Description: Lightweight processor for full-featured template
     Author: Taisuke Yamada <tai@imasy.or.jp>

   If you change

     $tmpl->setq(HAS => { Text::ScriptTemplate => 1 }); # installed

   to

     $tmpl->setq(HAS => { Text::ScriptTemplate => 0 }); # not installed

   then you will get

     === Module Information ===

     Text::ScriptTemplate is not installed.

   You can embed any control strucure as long as intermixed text block is
surround by set of braces. This means

     hello world<% if ($firsttime); %>

   must be written as

     <% do { %>hello world<% } if ($firsttime); %>

   If you want to know more on this, please read TEMPLATE INTERNAL section
for the detail.

   Also, as you might have noticed, any scalar data can be exported to
template namespace, even hash reference or code reference.

   Finally, although I used "Safe" module in example above, this is not a
requirement. However, if you want to control power of the template editor
over program logic, its use is strongly recommended (see the Safe manpage
for more).

RESERVED NAMES
==============

   Since template can be evaluated in separate namespace, this module does
not have much restriction on variable or function name you define in
theory.

   However, due to internal structure of this module, please consider all
names starting with "_" (underscore) as reserved for internal usage.

METHODS
=======

   Following methods are currently available.

$tmpl = new Text::ScriptTemplate;
     Constructor. Returns newly created object.

     If this method was called through existing object, cloned object will
     be returned. This cloned instance inherits all properties except for
     internal buffer which holds template data. Cloning is useful for
     chained template processing.

$tmpl->setq($name => $data, $name => $data, ...);
     Exports scalar data ($data) to template namespace, with $name as a
     scalar variable name to be used in template.

     You can repeat the pair to export multiple sets in one operation.

$tmpl->load($file, %opts);
     Loads template file ($file) for later evaluation.  File can be
     specified in either form of pathname or fileglob.

     This method accepts DELIM option, used to specify delimiter for
     parsing template. It is speficied by passing reference to array
     containing delimiter pair, just like below:

          $tmpl->load($file, DELIM => [qw(<? ?>)]);

     Returns object reference to itself.

$tmpl->pack($data, %opts);
     Loads in-memory data ($data) for later evaluation.  Except for this
     difference, works just like $tmpl->load.

$text = $tmpl->fill(%opts);
     Returns evaluated result of template, which was preloaded by either
     $tmpl->pack or $tmpl->load method.

     This method accepts two options: PACKAGE and OHANDLE.

     PACKAGE option specifies the namespace where template evaluation
     takes place. You can either pass the name of the package, or the
     package object itself. So either of

          $tmpl->fill(PACKAGE => new Safe);
          $tmpl->fill(PACKAGE => new Some::Module);
          $tmpl->fill(PACKAGE => 'Some::Package');

     works. In case Safe module (or its subclass) was passed, its "reval"
     method will be used instead of built-in eval.

     OHANDLE option is for output selection. By default, this method
     returns the result of evaluation, but with OHANDLE option set, you
     can instead make it print to given handle.  Either style of

          $tmpl->fill(OHANDLE => \*STDOUT);
          $tmpl->fill(OHANDLE => new FileHandle(...));

     is supported.

TEMPLATE INTERNAL
=================

   Internally, template processor converts template into one big perl
script, and then simply executes it. Conversion rule is fairly simple - If
you have following template,

     <% if ($bool) { %>
     hello, <%= $name; %>
     <% } %>

   it will be converted into

     if ($bool) {
         $_handle->(q{
     hello, });
         $_handle->(do{ $name; });
         $_handle->(q{
     });
     }

   Note line breaks are preserved. After all conversion is done, it will
be executed. And depending on existance of OHANDLE option, $_handle (this
is a code reference to predefined function) will either print or buffer
its argument.

NOTES / BUGS
============

   Nested template delimiter will cause this module to fail.

SEE ALSO
========

   See Safe, and Text/SimpleTemplate,

CONTACT ADDRESS
===============

   Please send any bug reports/comments to <tai@imasy.or.jp>.

AUTHORS / CONTRIBUTORS
======================

     - Taisuke Yamada <tai@imasy.or.jp>

COPYRIGHT
=========

   Copyright 2001. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl module to allow quick searching of directories for given text.
*******************************************************************

NAME
====

   *Text::Search* - Perl module to allow quick searching of directories
for given text.

   Version 0.91

SYNOPSIS
========

   use Text::Search;

   Simple Search: my $term = 'foo AND bar';

   my $search = Text::Search->new(); my @results = $search->Find($term);

   foreach (@results) { print "Found $term in $_->{'FILENAME'}
$_->{'OCCURENCES'} times.\n" };

   RegEx Search: my @terms = ('(foo.*)','(bar)');

   my $search = Text::Search->new('RegExSearch', '1'); my @results =
$search->Find(@terms);

   foreach (@results) { print "Found $_->{'FILENAME'} with
$_->{'OCCURENCES'}.\n" };

DESCRIPTION
===========

   *Text::Search* takes in a given directory and search term, and will
recursively search for all occurences for the term. Features include:
extension filtering, binary filter (won't search binary files), simple and
regex search expressions.

   Information is returned as an array of hashes sorted descending by
number of occurences.

CONSTRUCTORS
============

`Text::Search->new()'
     `$search = Text::Search->new('RegExSearch', '1', 'DocumentRoot',
     '/usr/home/mike', 'FileFilter, '(^.*\.htm*$)' );'

     Prepares a search to be performed. The search will execute with a
     $search->Find().

     RegExSearch = Set to 1 if this is to be a regular expression search.
     0 if this is a simple search. (Default)

     DocumentRoot = Where to begin the search from, search is recursive.
     Default is (/usr).

     WebRoot = For use with a website. Only needs to be set if your
     DocumentRoot is set to something other than your WebRoot.

     FileFilter = Regular expression to filter out unwanted files. Default
     is all files.

     Recursive = Set to 0 to turn off recursive searching. Default is 1.

     Highlight = Set to 1 to turn on Highlighting of matched words. Useful
     for bolding matched text in websites. Default is 0.

     HighlightBegin = Customize the code to appear before a match. Default
     is '<b>'.

     HighlightEnd = Customize the code to appear after a match. Default is
     '</b>'.

`$search->Find()'
     `@results = $search->Find('blowfish OR foo AND bar');' `@results =
     $search->Find('(blowfish)|(foo)','(bar)');'

     Executes a search for the given terms.

     Data is returned in an array of hashes which can be accessed like so:

     `foreach (@results) { print "$_->{'FILENAME'} : $_->{'FILEKSIZE'} :
     $_->{'LAST_MODIFIED'} : $_->{'OCCURENCES'}\n" };'

     OR

     `print "Most likely target is $results[0]{'FILENAME'}\n";'

     The following keys are available in the returned hash:

     FULLNAME = Full path and filename of file. (ie. /home/doug/readme.txt)

     FILENAME = Name of the file (ie. readme.txt)

     FILEPATH = Path to the file (ie. /home/doug)

     FILESIZE = Size of file in bytes.

     FILEKSIZE = Size of file in kilobytes.

     LAST_MODIFIED_EPOCH = Time since file was last modified in seconds.

     LAST_MODIFIED = Date and Time of last modified in long format.

     OCCURENCES = Number of times the search pattern was matched.

     URL = For Website use, the path and filename of file from the given
     DocumentRoot.

     SNIPPET = Snippet of text containing text of the first matched term.

     TITLE = Pulled from the <TITLE> tag of an HTML page.

     META_TITLE = Pulled from the <meta name="title"> tag.

     META_DESCRIPTION = Pulled from the <meta name="description"> tag.

     META_KEYWORDS = Pulled from the <meta name="keywords"> tag.

EXAMPLES
========

Simple script usage.
--------------------

   use Text::Search;

   my $search = Text::Search->new('DocumentRoot', '/usr/home/bill/ebooks');

   print "Searching:\n\n";

   my @results = $search->Find('romeo AND juliette');

   foreach (@results) { print "Found it $_->{'OCCURENCES'} times in
$_->{'FILENAME'}\n" };

Web based application.
----------------------

   This is an excellent way to add a search engine to any html site.

   require ("cgi-lib.pl"); use Text::Search;

   &ReadParse (*input);

   my $search = Text::Search->new('DocumentRoot', $ENV{'DOCUMENT_ROOT'},
'FileFilter', '(^.*\.html$)');

   my @results = $search->Find($input{'User_Search'});

   print "Content-type: text/html \n\n";

   print "Sorry, I couldn't find your request!" if (scalar @results == 0);

   foreach (@results) { print "<a
href=\"$_->{'URL'}\">$_->{'URL'}</a><br>Relevancy:
$_->{'OCCURENCES'}<br>Last Updated: $_->{'LAST_MODIFIED'}<br><hr>\n" };

BUGS
====

   Be careful when using simple search. It will attemp to quote any
illegal characters, etc. But for security sake, do your own checks before
passing user input into the simple search.

   If you have trouble with the HTML grabbing (ie. Title tags, Meta tags),
take a look at the syntax of the HTML document. Text::Search tries to be
forgiving, but it expects something like this:

   <title>This is my title</title>

   <meta name="description" content="This is my wonderful website">

DISCLAIMER
==========

   This package 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.

COPYRIGHT
=========

   Copyright (c) 2001 Mike Miller.  All rights reserved.

LICENSE
=======

   This program is free software: you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Mike Miller <mrmike@2bit.net>

module for splitting text into sentences
****************************************

NAME
====

   Text::Sentence - module for splitting text into sentences

SYNOPSIS
========

     use Text::Sentence qw( split_sentences );
     use locale;
     use POSIX qw( locale_h );

     setlocale( LC_CTYPE, 'iso_8859_1' );
     @sentences = split_sentences( $text );

DESCRIPTION
===========

   The `Text::Sentence' module contains the function split_sentences, which
splits text into its constituent sentences, based on a fairly approximate
regex. If you set the locale before calling it, it will deal correctly with
locale dependant capitalization to identify sentence boundaries. Certain
well know exceptions, such as abreviations, may cause incorrect
segmentations.

FUNCTIONS
=========

split_sentences( $text )
------------------------

   The split sentences function takes a scalar containing ascii text as an
argument and returns an array of sentences that the text has been split
into.

     @sentences = split_sentences( $text );

SEE ALSO
========

     locale
     POSIX

AUTHOR
======

   Ave Wrigley <wrigley@cre.canon.co.uk>

COPYRIGHT
=========

   Copyright (c) 1997 Canon Research Centre Europe (CRE). All rights
reserved.  This script and any associated documentation or files cannot be
distributed outside of CRE without express prior permission from CRE.

read and write SIL Shoebox Standard Format (.sf) files
******************************************************

NAME
====

   Text::Shoebox - read and write SIL Shoebox Standard Format (.sf) files

SYNOPSIS
========

     use Text::Shoebox;
     my $lex = [];
     foreach my $file (@ARGV) {
       read_sf(
         from_file => $file, into => $lex,
       ) or warn "read from $file failed\n";
     }
     print scalar(@$lex), " entries read.\n";

     die "hw field-names differ\n"
      unless are_hw_keys_uniform($lex);
     warn "hw field-values aren't unique\n"
      unless are_hw_values_unique($lex);

     write_fs(from => $lex, to_file => "merged.sf")
      or die "Couldn't write to merged.sf: $!";

DESCRIPTION
===========

   The Summer Institute of Linguistics (`http://www.sil.org/') makes a
piece of free software called "the Linguist's Shoebox", or just "Shoebox"
for short.  It's a simple database program generally used for making
lexicon databases (altho it can also be used for databases of field notes,
etc.).

   Shoebox can export its databases to SF (Standard Format) files, a
simple text format.  Reading and writing those SF files is what this Perl
module, Text::Shoebox, is for.  (I have heard that Standard Format
predates Shoebox quite a bit, and is used by other programs.  If you use
SF files with something other than Shoebox, I'd be interested in hearing
about it, particularly about whether such files and Text::Shoebox are
happily compatible.)

FUNCTIONS
=========

$lex_lol = read_fs(...options...)
     Reads entries in Standard Format from the source specified.  If no
     entries were read, returns false.  Otherwise, returns a reference to
     the array that the entries were added to (which will be a new array,
     unless the "into" option is set).

     The options are:

    from_file => STRING
          This specifies that the source of the SF data is a file, whose
          filespec is given.

    from_fh => FILEHANDLE
          This specifies that the source of the SF data is a given
          filehandle.  (Examples of filehandle values: or global
          filehandle passed either like `*MYFH{IO}' or `*MYFH'; or object
          values from an IO class like IO::Socket or IO::Handle.)

          The filehandle isn't closed when all its data is read.

    rs => STRING
          This specifies that the given string should be used as the record
          separator (newline string) for the data source being read from.

          If the SF source is specified by a "from_file" option, and you
          don't specify an "rs" option, then Text::Shoebox will try
          guessing the line format of the file by reading the first 2K of
          the file and looking for a CRLF ("\cm\cj"), an LF ("\cj"), or a
          CR ("\cm").  If you need to stop it from trying to guess, just
          stipulate an "rs" value of $/.

          If the SF source is specified by a "from_file" option, and you
          don't specify an "rs" option, then Text::Shoebox will just use
          the value in the Perl variable $/ (the global RS value).

    into => ARRAYREF
          If this option is stipulated, then entries read will be pushed
          to the end of the array specified.  Otherwise the entries will
          be put into a new array.

     Example use:

          use Text::Shoebox;
          my $lexicon = read_fs(from_file => 'foo.sf')
           || die "No entries?";
          print scalar(@$lexicon), " entries read.\n";
          print "First entry has ",
           @{ $lexicon->[0] } / 2 , " fields.\n";

write_fs(...options...)
     This writes the given lexicon, in Standard Format, to the destination
     specified.  If all entries were written, returns true; otherwise (in
     case of an IO error), returns false, in which case you should check
     $!.

     The options are:

    from => ARRAYREF
          This option must be present, to specify the lexicon that you
          want to write out.

    to_file => STRING
          This specifies that the SF data is to be written to the file
          specified.  (Note that the file is opened in overwrite mode, not
          append mode.)

    to_handle => FILEHANDLE
          This specifies that the destination for the SF data is the given
          filehandle.

          The filehandle isn't closed when all the data is written to it.

    rs => STRING
          This specifies that the given string should be used as the record
          separator (newline string) for the SF data written.

          If not specified, defaults to "\n".

are_hw_keys_uniform($lol)
     This function returns true iff all the entries in the lexicon have the
     same key for their headword fields (i.e., the first field per record).
     This will always be true if you read the lexicon from one file; but if
     you read it from several, it's possible that the different files have
     different keys marking headword fields.

are_hw_values_unique($lex_lol)
     This function returns true iff all the headword values in all non-null
     entries in the lexicon $lol are unique - i.e., if no two (or more)
     entries have the same values for their headword fields.  I don't know
     if uniqueness is a requirement for SF lexicons that you'd want to
     import into Shoebox, but some tasks you put lexicons to might require
     it.

A NOTE ABOUT VALIDITY
=====================

   I make very few assumptions about what characters can be in a field key
in SF files.  Just now, I happen to assume they can't start with an
underscore (lest they be considered comments), and can't contain any
whitespace characters.

   I make essentially no assumptions about what can be in a field value,
except that there can be no newline followed immediately by a backslash.
(Any newline-backslash sequence in turned into newline-space-backslash.)

   You should be aware that Shoebox, or whatever other programs use SF
files, may have a *much* more restricted view of what can be in a field
key or value.

COPYRIGHT
=========

   Copyright 2000, Sean M. Burke `sburke@cpan.org', all rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Sean M. Burke, `sburke@cpan.org'

   Please contact me if you find that this module is not behaving
correctly.  I've tested it only on Shoebox files I generate on my own.

   I hasten to point out, incidentally, that I am not in any way
affiliated with the Summer Institute of Linguistics.

Yet another module for template processing
******************************************

NAME
====

     Text::SimpleTemplate - Yet another module for template processing

SYNOPSIS
========

     use Text::SimpleTemplate;

     $tmpl = new Text::SimpleTemplate;    # create processor object
     $tmpl->setq(TEXT => "hello, world"); # export data to template
     $tmpl->load($file);                  # loads template from named file
     $tmpl->pack(q{TEXT: <% $TEXT; %>});  # loads template from in-memory data

     print $tmpl->fill;                   # prints "TEXT: hello, world"

DESCRIPTION
===========

   This is yet another library for template-based text generation.

   Template-based text generation is a way to separate program code and
data, so non-programmer can control final result (like HTML) as desired
without tweaking the program code itself. By doing so, jobs like website
maintenance is much easier because you can leave program code unchanged
even if page redesign was needed.

   The idea is simple. Whenever a block of text surrounded by '<%' and
'%>' (or any pair of delimiters you specify) is found, it will be taken as
Perl expression, and will be replaced by its evaluated result.

   Major goal of this library is simplicity and speed. While there're many
modules for template processing, this module has near raw Perl-code (i.e.,
"s|xxx|xxx|ge") speed, while providing simple-to-use objective interface.

INSTALLATION / REQUIREMENTS
===========================

   This module requires Carp.pm and FileHandle.pm.  Since these are
standard modules, all you need is perl itself.

   For installation, standard procedure of

     perl Makefile.PL
     make
     make test
     make install

   should work just fine.

TEMPLATE SYNTAX AND USAGE
=========================

   Suppose you have a following template named "sample.tmpl":

     === Module Information ===
     Name: <% $INFO->{Name}; %>
     Description: <% $INFO->{Description}; %>
     Author: <% $INFO->{Author}; %> <<% $INFO->{Email}; %>>

   With the following code...

     use Safe;
     use Text::SimpleTemplate;

     $tmpl = new Text::SimpleTemplate;
     $tmpl->setq(INFO => {
         Name        => "Text::SimpleTemplate",
         Description => "Yet another module for template processing",
         Author      => "Taisuke Yamada",
         Email       => "tai\@imasy.or.jp",
     });
     $tmpl->load("sample.tmpl");

     print $tmpl->fill(PACKAGE => new Safe);

   ...you will get following result:

     === Module Information ===
     Name: Text::SimpleTemplate
     Description: Yet another module for template processing
     Author: Taisuke Yamada <tai@imasy.or.jp>

   As you might have noticed, any scalar data can be exported to template
namespace, even hash reference or code reference.

   By the way, although I used "Safe" module in example above, this is not
a requirement. However, if you want to control power of the template
editor over program logic, its use is strongly recommended (see
Safe, for more).

DIRECT ACCESS TO TEMPLATE NAMESPACE
===================================

   In addition to its native interface, you can also access directly to
template namespace.

     $FOO::text = 'hello, world';
     @FOO::list = qw(foo bar baz);

     $tmpl = new Text::SimpleTemplate;
     $tmpl->pack(q{TEXT: <% $text; %>, LIST: <% "@list"; %>});

     print $tmpl->fill(PACKAGE => 'FOO');

   While I don't recommend this style, this might be useful if you want to
export list, hash, or subroutine directly without using reference.

METHODS
=======

   Following methods are currently available.

$tmpl = Text::SimpleTemplate->new;
     Constructor. Returns newly created object.

     If this method was called through existing object, cloned object will
     be returned. This cloned instance inherits all properties except for
     internal buffer which holds template data. Cloning is useful for
     chained template processing.

$tmpl->setq($name => $data, $name => $data, ...);
     Exports scalar data ($data) to template namespace, with $name as a
     scalar variable name to be used in template.

     You can repeat the pair to export multiple sets in one operation.

$tmpl->load($file, %opts);
     Loads template file ($file) for later evaluation.  File can be
     specified in either form of pathname or fileglob.

     This method accepts DELIM option, used to specify delimiter for
     parsing template. It is speficied by passing reference to array
     containing delimiter pair, just like below:

          $tmpl->load($file, DELIM => [qw(<? ?>)]);

     Returns object reference to itself.

$tmpl->pack($data, %opts);
     Loads in-memory data ($data) for later evaluation.  Except for this
     difference, works just like $tmpl->load.

$text = $tmpl->fill(%opts);
     Returns evaluated result of template, which was preloaded by either
     $tmpl->pack or $tmpl->load method.

     This method accepts two options: PACKAGE and OHANDLE.

     PACKAGE option specifies the namespace where template evaluation
     takes place. You can either pass the name of the package, or the
     package object itself. So either of

          $tmpl->fill(PACKAGE => new Safe);
          $tmpl->fill(PACKAGE => new Some::Module);
          $tmpl->fill(PACKAGE => 'Some::Package');

     works. In case Safe module (or its subclass) was passed, its "reval"
     method will be used instead of built-in eval.

     OHANDLE option is for output selection. By default, this method
     returns the result of evaluation, but with OHANDLE option set, you
     can instead make it print to given handle.  Either style of

          $tmpl->fill(OHANDLE => \*STDOUT);
          $tmpl->fill(OHANDLE => new FileHandle(...));

     is supported.

NOTES / BUGS
============

   Nested template delimiter will cause this module to fail.

CONTACT ADDRESS
===============

   Please send any bug reports/comments to <tai@imasy.or.jp>.

AUTHORS / CONTRIBUTORS
======================

     - Taisuke Yamada <tai@imasy.or.jp>
     - Lin Tianshan <lts@www.qz.fj.cn>

COPYRIGHT
=========

   Copyright 1999-2001. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Implementation of the Soundex Algorithm as Described by Knuth
*************************************************************

NAME
====

   Text::Soundex - Implementation of the Soundex Algorithm as Described by
Knuth

SYNOPSIS
========

     use Text::Soundex;

     $code = soundex($name);    # Get the soundex code for a name.
     @codes = soundex(@names);  # Get the list of codes for a list of names.

     # This is how you define what you want to be returned if your
     # input string has no indentifiable codes within it.

     # Make the change permanent.
     $Text::Soundex::nocode = 'Z000';

     # Make the change temporary.
     {
         local $Text::Soundex::nocode = 'Z000';   # Temporary change.
         $code = soundex($name);
     }

DESCRIPTION
===========

   This module implements the soundex algorithm as described by Donald
Knuth in Volume 3 of *The Art of Computer Programming*.  The algorithm is
intended to hash words (in particular surnames) into a small space using a
simple model which approximates the sound of the word when spoken by an
English speaker.  Each word is reduced to a four character string, the
first character being an upper case letter and the remaining three being
digits.

   The value returned for strings which have no soundex encoding is set in
the scalar `$Text::Soundex::nocode'.  This is initially set to undef, but
many people seem to prefer an *unlikely* value like `Z000' (how unlikely
this is depends on the data set being dealt with.)  Any value can be
assigned to `$Text::Soundex::nocode'.

   For backward compatibility with older versions of this module the
`$Text::Soundex::nocode' is exported into the caller's namespace as
`$soundex_nocode'.

   In scalar context soundex returns the soundex code of its first
argument, and in array context a list is returned in which each element is
the soundex code for the corresponding argument passed to soundex e.g.

     @codes = soundex qw(Mike Stok);

   leaves `@codes' containing `('M200', 'S320')'.

   If you wish to use Text::Soundex for searching for your name in one of
the US Censuses made publicly available, you must instruct the module of
your intentions by doing one of the following:

     # First method:
     use Text::Soundex qw(:NARA-Ruleset);
     $code = soundex($name);

     # Second method:
     use Text::Soundex qw(soundex_nara);
     $code = soundex_nara($name);

   This is necessary, as the algorithm used by the US Censuses is slightly
different than that defined by Knuth and others. The descrepancy can be
shown using the name "Ashcraft":

     print soundex("Ashcraft"), "\n";       # prints: A226
     print soundex_nara("Ashcraft"), "\n";  # prints: A261

   Their is also a speed hit involved when using the NARA ruleset. (The
encoding is slightly more complicated)

EXAMPLES
========

   Knuth's examples of various names and the soundex codes they map to are
listed below:

     Euler, Ellery -> E460
     Gauss, Ghosh -> G200
     Hilbert, Heilbronn -> H416
     Knuth, Kant -> K530
     Lloyd, Ladd -> L300
     Lukasiewicz, Lissajous -> L222

   so:

     $code = soundex 'Knuth';         # $code contains 'K530'
     @list = soundex qw(Lloyd Gauss); # @list contains 'L300', 'G200'

UNDERNEATH THE COVERS (a word from Mark)
========================================

   To ease use for the user, the XS version is transparently accessible via
soundex() when it exists for the current platform. Basically what this
means is that if you are on a platform with XS code compiled, the call to
soundex() will complete about 7X faster. If for whatever reason you care,
and you want to choose which code to use, I have provided access to the
individual calls.

     # The following calls are split up by functionality.

     # Always uses the 100% perl version.
     ... = Text::Soundex::soundex_noxs(...);

     # Always uses the XS version. (7X faster)
     ... = Text::Soundex::soundex_xs(...);

     # Use the XS version if possible, otherwise
     # it will revert to the 100% perl version.
     ... = Text::Soundex::soundex(...);

     =head1 LIMITATIONS

   As the soundex algorithm was originally used a long time ago in the US
it considers only the English alphabet and pronunciation.

   As it is mapping a large space (arbitrary length strings) onto a small
space (single letter plus 3 digits) no inference can be made about the
similarity of two strings which end up with the same soundex code.  For
example, both `Hilbert' and `Heilbronn' end up with a soundex code of
`H416'.

AUTHOR
======

   This code was originally implemented by Mike Stok (`mike@stok.co.uk')
as an example of unreadable perl 4 code and refined into a library.  The
code is now maintained by Mark Mielke <markm@nortelnetworks.com> who
recast the code and made it speedy in 1997. Mark has since added the XS
code to accomplish the encoding at a speed upwards of 7X faster. Please
report any bugs or other to Mark Mielke <markm@nortelnetworks.com>.

   Ian Phillips (`ian@pipex.net') and Rich Pinder (`rpinder@hsc.usc.edu')
supplied ideas and spotted mistakes for v1.x.

   Dave Carlson (`dcarlsen@csranet.com') made the request for the NARA
ruleset to be included. The ruleset is named "NARA", as the descrepancy
was discovered due to the fact that it was the NARA soundex machine that
was producing "invalid" codes in certain cases. The NARA soundex page can
be viewed at: `http://www.nara.gov/genealogy/soundex/soundex.html'

Perl extension to strip the high bit off of ISO-8859-1 text.
************************************************************

NAME
====

   Text::Striphigh - Perl extension to strip the high bit off of
ISO-8859-1 text.

SYNOPSIS
========

     use Text::Striphigh 'striphigh'

     $SevenBitsText = striphigh($TextContainingEightBitCharacters);

DESCRIPTION
===========

   The Text::Striphigh module exports a single function: `striphigh'. This
function takes one argument, a string possibly containing high ASCII
characters in the ISO-8859-1 character set, and transforms this into a
string containing only 7 bits ASCII characters, by substituting every high
bit character with a similar looking standard ASCII character, or with a
sequence of standard ASCII characters.

   Because of precisely the deficiency this package tries to offer a
workaround for is present in some of the things that process pod, there
are no examples in this manpage. Look at the source or the test script if
you want examples.

MAINTENANCE
===========

   If you ever want to change the striphigh function yourself, then don't
change the one containing the mile long `tr{}{}' statement that you see at
first, change the one behind the `__DATA__' that's a lot more readable.

   After you've done that, simply run the `Striphigh.pm' file through perl
to generate a new version of the first routine, and in fact of the entire
file, something like this:

     perl -w Striphigh.pm > Striphigh.pm.new
     mv Striphigh.pm.new Striphigh.pm

BUGS
====

   Assumes the input text is ISO-8859-1, without even looking at the LOCALE
settings.

   Some translations are probably less than optimal.

   People will be offended if you run their names through this function,
and print the result on an envelope using an outdated printing device.
However, it's probably better than having that printer print a name with a
high ASCII character in it which happens to be the command to set the
printer on fire.

AUTHOR
======

   Jan-Pieter Cornet <johnpc@xs4all.nl>

Manipulate fixed-format pages
*****************************

NAME
====

   Text::Structured - Manipulate fixed-format pages

SYNOPSIS
========

     use Text::Structured;
     $st  = new Text::Structured($page);
     $foo = $st->get_text_at($r,$c,$len);
     $foo = $st->get_text_re($r,$re);

DESCRIPTION
===========

   *Text::Structured* is a class for manipulating fixed-format pages of
text.  A page is treated as a series of rows and columns with the row and
column of the top left hand corner of the page being (0,0).

SUPERCLASSES
============

   *Text::StructuredBase*

CLASS METHODS
=============

new($page)
----------

   Create a new *Text::Structured* object.  $page is a string containing a
page of text.

OBJECT METHODS
==============

get_text_at($r,$c,$len)
-----------------------

   Returns a substring of length *$len* starting at row $r, column $c.
This method will die() if $r < 0 or $r > the number of lines in the page.
See also `substr()', see Perlfunc (perl.info).

get_text_re($r,$re)
-------------------

   Returns a string which is the result of applying the regular expression
*$re* to row $r of the page.  This method will die() if $r < 0 or $r > the
number of lines in the page.

do_method()
-----------

   This method can be used with the *Text::FillIn* module (available from
CPAN) to fill a template using methods from *Text::Structured* e.g.

     use Text::FillIn;
     use Text::Structured;

     $page = q{foo bar
     baz quux};
     $st = new Text::Structured($page);
     # set delimiters
     Text::FillIn->Ldelim('(:');
     Text::FillIn->Rdelim(':)');
     $template = new Text::FillIn;
     $template->object($st);
     $template->hook('&','do_method');
     $template->set_text(q{Oh (:&get_text_at(0,0,3):), it's a (:&get_text_re(1,(\w+)$):)!});
     $foo = $template->interpret;
     print "$foo\n";

   Prints 'Oh foo, it's a quux!'.

AUTHOR
======

   Paul Sharpe <paul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1999 Paul Sharpe. England.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Structured text base class
**************************

NAME
====

   Text::StructuredBase - Structured text base class

SYNOPSIS
========

     use base qw/Text::StructuredBase/;

     $object->debug($n);

DESCRIPTION
===========

   *Text::StructuredBase* acts as a base class for *Text::Structured*.

BASE CLASS METHODS
==================

AUTOLOAD()
----------

   AUTOLOAD() provides default accessor methods (apart from DESTROY()) for
any of its subclasses.  For AUTOLOAD() to catch calls to these methods
objects must be implemented as an anonymous hash.  Object attributes must

   * have UPPER CASE names

   * have keys in attribute _PERMITTED (an anonymous hash)

   The name accessor method is the name of the attribute in *lower case*.
The 'set' versions of these accessor methods require a single scalar
argument (which could of course be a reference.)  Both 'set' and 'get'
versions return the attribute's value.

   *Special Attributes*

/_L$/
     Attribute names matching the pattern /_L$/ will be treated as
     arrayrefs.  These accessors require an arrayref as an argument.  If
     the attribute is defined they return the arrayref, otherwise they
     return an empty arrayref.

     A method **_l_add(@foo)* can be called on this type of attribute to
     add the elements in *@foo* to the array.  If the attribute is defined
     they return the arrayref, otherwise they return an empty arrayref.

/_H$/
     Attribute names matching the pattern /_H$/ will be treated as
     hashrefs.  These accessors require a reference to an array containing
     key/value pairs.  If the attribute is defined they return the hashref,
     otherwise they return an empty hashref.

     A method **_h_byname(@list)* can be called on this type of attribute.
     These methods will return a list which is the hash slice of the *_H*
     attribute value over *@list* or an empty list if the attribute is
     undefined.

     A method **_h_add(\%foo)* can be called on this type of attribute to
     add the elements in *%foo* to the hash.  If the attribute is defined
     they return the hashref, otherwise they return an empty hashref.

debug($n)
---------

   As a class method sets the class attribute *$Debugging* to $n.  As an
object method sets the object attribute *$_DEBUG* to $n.

AUTHOR
======

   Paul Sharpe <paul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1999 Paul Sharpe. England.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

expand and unexpand tabs per the unix expand(1) and unexpand(1)
***************************************************************

NAME
====

   Text::Tabs - expand and unexpand tabs per the unix expand(1) and
unexpand(1)

SYNOPSIS
========

     use Text::Tabs;

     $tabstop = 4;
     @lines_without_tabs = expand(@lines_with_tabs);
     @lines_with_tabs = unexpand(@lines_without_tabs);

DESCRIPTION
===========

   Text::Tabs does about what the unix utilities expand(1) and unexpand(1)
do.  Given a line with tabs in it, expand will replace the tabs with the
appropriate number of spaces.  Given a line with or without tabs in it,
unexpand will add tabs when it can save bytes by doing so.  Invisible
compression with plain ascii!

BUGS
====

   expand doesn't handle newlines very quickly - do not feed it an entire
document in one string.  Instead feed it an array of lines.

AUTHOR
======

   David Muir Sharnoff <muir@idiom.com>

Text::TagTemplate
*****************

NAME
====

     Text::TagTemplate

VERSION
=======

     $Revision: 1.4 $

SYNOPSIS
========

     use Text::TagTemplate qw( :standard );

     # Define a single tag to substitute in a template.
     add_tag( MYTAG => 'Hello world.' );

     # Define several tags all at once. The  tags()  method wipes out
     # all current tags.
     tags( +{ FOO => 'The string foo.',  # Single-quoted string
              BAR => "$ENV{ USER }",     # Double-quoted string
     	 LIST => join( '<LI>', @list ),  # Function call

     # Functions or subroutines that get called each time
     # the tag is replaced, possibly producing different
     # results for the same tag if it appears twice or more.
     TIME => \&time(),          # Reference to a function
     SUB => sub {               # Anonymous subroutine
     	my( $params ) = @_;
     			return $params->{ NAME };
     		}
     	} );

     # Add a couple of tags to the existing set.  Takes a hash-ref.
     add_tags( +{ TAG1 => "Hello $ENV{ USER }",
     	     TAG2 => rand( 10 ),  # random number between 0 and 10
     	} );

     # Set the template file to use.
     template_file( 'template.htmlt' );

     # This is list of items to construct a list from.
     list( 'One', 'Two', 'Three' );

     # These are template-fragment files to use for making the list.
     entry_file( 'entry.htmlf' );
     join_file(  'join.htmlf'  );

     # This is a callback sub used to make the tags for each entry in a
     # parsed list.
     entry_callback( sub {
     	my( $item ) = @_;
     	return +{ ITEM => $item };
     } );

     # Add a new tag that contains the whole parsed list.
     add_tag( LIST => parse_list_files );

     # Print the template file with substitutions.
     print parse_file;

DESCRIPTION
===========

   This module is designed to make the process of constructing web-based
applications (such as CGI programs and Apache::Registry scripts) much
easier, by separating the logic and application development from the HTML
coding, and allowing ongoing changes to the HTML without requiring
non-programmers to modify HTML embedded deep inside Perl code.

   This module provides a mechanism for including special HTML-like tags
in a file (or scalar) and replacing those tags at run-time with
dynamically generated content. For example the special tag     <#USERINFO
FIELD="favorite_color">

   might be replaced by "green" after doing a database lookup. Usually
each special tag will have its own subroutine which is executed every time
the tag is seen.

   Each subroutine can be basically anything you might want to do in Perl
including database lookups or whatever. You simply create subroutines to
return whatever is appropriate for replacing each special tag you create.

   Attributes in the special tags (such as the FIELD="favorite_color" in
the example above) are passed to the matching subroutine.

   It is not web-specific, though, despite the definite bias that way, and
the template-parsing can just as easily be used on any other text
documents.  The examples here will assume that you are using it for
convential CGI applications.

   It provides functions for parsing strings, and constructing lists of
repeated elements (as in the output of a search engine).

   It is object-oriented, but - like the CGI module - it does not require
the programmer to use an OO interface.  You can just import the
":standard" set of methods and use them with no object reference, and it
will create and use an internal object automatically.  This is the
recommended method of using it unless you either need multiple template
objects, or you are concerned about namespace pollution.

TEMPLATES
=========

   The structure of templates is as any other text file, but with extra
elements added that are processed by the CGI as it prints the file to the
browser.  These extra elements are referred to in this manual as "tags",
which should not be confused with plain HTML tags - these tags are
replaced before the browser even begins to process the HTML tags.  The
syntax for tags intentionally mimics HTML tags, though, to simplify
matters for HTML-coders.

   A tag looks like this:

     <#TAG>

   or optionally with parameters like:

     <#TAG NAME=VALUE>

   or with quoted parameters like:

     <#TAG NAME="Value, including spaces etc.">

   The tag name is the first part after the opening <# of the whole tag.
It must be a simple identifier - I recommend sticking to the character set
[A-Z_] for this.  The following parameters are optional and only used if
the tag-action is a callback subroutine (see below).  They are supplied in
HTML-style name/value pairs.  The parameter name like the tag name must be
a simple identifier, and again I recommend that it is drawn from the
character set [A-Z_].  The value can be any string, quoted if it contains
spaces and the like.  Even if quoted, it may not contain any of:

     < > " & =

     which should be replaced with their HTML escape equivalents:

     &lt; &gt; &quot; &amp; &#061;

   This may be a bug.  At present, other HTML escapes are not permitted in
the value.  This may also be a bug.

   Tag names and parameter names are, by default, case-insensitive (they
are converted to upper-case when supplied).  You can change this behaviour
by using the auto_cap() method.  I don't recommend doing that, though.

   There are four special parameters that can be supplied to any tag,
HTMLESC and URLESC.  Two of them cause the text returned by the tag to be
HTML or URL escaped, which makes outputting data from plain-text sources
like databases or text files easier for the programmer.  An example might
be:

     <#FULL_NAME HTMLESC>

   which would let the programmer simply put the full-name data into the
tag without first escaping it.  Another might be:

     <A HREF="/cgi-bin/lookup.cgi?key=<#RECORD_KEY URLESC>">

   A typical template might look like:

     <HTML><HEAD><TITLE>A template</TITLE></HEAD>
     <BODY>

     <P>This is a tag:  <#TAG></P>

     <P>This is a list:</P>

     <#LIST>

     <P>This is a tag that calls a callback:  <#ITEM ID=358></P>

     </BODY></HTML>

   Note that it is a full HTML document.

TAGS
====

   You can supply the tags that will be used for substitutions in several
ways.  Firstly, you can set the tags that will be used directly, erasing
all tags currently stored, using the tags() method.  This method - when
given an argument - removes all present tags and replaces them with tags
drawn from the hash-reference you must supply.  For example:

     tags( +{ FOO => 'A string called foo.',
              BAR => 'A string called bar.' } );

   The keys to the hash-ref supplied are the tag names; the values are the
substitution actions (see below for more details on actions).

   If you have an existing hash you can use it to define several tags.
For example:

     tags( \%ENV );

   would add a tag for each environment variable in the %ENV hash.

   Secondly, you can use the add_tags() method to add all the tags in the
supplied hash-ref to the existing tags, replacing the existing ones where
there is conflict.  For example:

     add_tags( +{ FOOBAR => 'A string called foobar added.',
                  BAR    => 'This replaces the previous value for BAR' } );

   Thirdly, you can add a single tag with add_tag(), which takes two
arguments, the tag name and the tag value.  For example:

     add_tag( FOO => 'This replaces the previous value for FOO' );

   Which one of these is the best one to use depends on your application
and coding style, of course.

ACTIONS
=======

   Whichever way you choose to supply tags for substitutions, you will
need to supply an action for each tag.  These come in two sorts:  scalar
values (or scalar refs, which are treated the same way), and subroutine
references for callbacks.

Scalar Text Values
------------------

   A scalar text value is simply used as a string and substituted in the
output when parsed. All of the following are scalar text values:

     tags( +{ FOO => 'The string foo.',  # Single-quoted string
              BAR => "$ENV{ USER }",     # Double-quoted string
              LIST => join( '<LI>', @list ),  # Function call
     } );

Subroutine References
---------------------

   If the tag action is a subroutine reference then it is treated as a
callback.  The value supplied to it is a single hash-ref containing the
parameter name/value pairs supplied in the tag in the template.  For
example, if the tag looked like:

     <#TAG NAME="Value">

   the callback would have an @_ that looked like:

     +{ NAME => 'Value' }

   The callback must return a simple scalar value that will be substituted
in the output. For example:

     add_tag( TAG  => sub {
                         my( $params ) = @_;
                         my $name = $params->{ NAME };
     	    my $text = DatabaseLookup("$name");
     	    return $text;
                     }
             } );

   You can use these callbacks to allow the HTML coder to look up data in a
database, to set global configuration parameters, and many other situations
where you wish to allow more flexible user of your templates.

   For example, the supplied value can be the key to a database lookup and
the callback returns a value from the database; or it can be used to set
context for succeeding tags so that they return different values.  This
sort of thing is tricky to code but easy to use for the HTMLer, and can
save a great deal of future coding work.

Default Action
--------------

   If no action is supplied for a tag, the default action is used.  The
default default action is to die() with an error, since usually the use of
unknown tags indicates a bug in the application.  You may wish to simply
ignore unknown tags and replace them with blank space, in which case you
can use the unknown_action() method to change it.  If you wish to ignore
unknown tags, you set this to the special value "IGNORE". For example:

     unknown_action( 'IGNORE' );

   Unknown tags will then be left in the output (and typically ignored by
web browsers.)  The default action is indicated by the special value
"DIE".  If you want to have unknown tags just be replaced by warning text
(and be logged with a warn() call), use the special value "WARN".  For
example:

     unknown_action( 'WARN' );

   If the default action is a subroutine reference then the name of the
unknown tag is passed as a parameter called "TAG". For example:

     unknown_action( sub {
     		    my( $params ) = @_;
     		    my $tagname   = $params->{ TAG };
     		    return "<BLINK>$tagname is unknown.</BLINK>";
     } );

   You may also specify a custom string to be substituted for any unknown
tags. For example:

     unknown_action( '***Unknown Tag Used Here***' );

PARSING
=======

   Once you have some tags defined by your program you need to specify
which template to parse and replace tags in.

   You can supply a string to parse, or the name of file to use.  The
latter is usually easier.  For example:

     template_string( 'A string containing some tag: <#FOO>' );

   or:

     template_file( 'template.htmlt' );

   These methods just set the internal string or file to look for; the
actual parsing is done by the parse() or parse_file() methods.  These
return the parsed template, they don't store it internally anywhere, so
you have to store or print it yourself.  For example:

     print parse_file;

   will print the current template file using the current set of tags for
substitutions.  Or:

     $parsed = parse;

   will put the parsed string into $parsed using the current string and
tags for substitutions.

   These methods can also be called using more parameters to skip the
internally stored strings, files, and tags.  See the per-method
documentation below for more details; it's probably easier to do it the
step-by-step method, though.

MAKING LISTS
============

   One of the things that often comes up in CGI applications is the need to
produce a list of results - say from a search engine.

   Because you don't necessarily know in advance the number of elements,
and usually you want each element formatted identically, it's hard to do
this in a single template.

   This module provides a convenient interface for doing this using two
templates for each list, each a fragment of the completed list.  The
"entry" template is used for each entry in the list.  The "join" template
is inserted in between each pair of entries.  You only need to use a
"join" template if you, say, want a dividing line between each entry but
not one following the end of the list.  The entry template is the
interesting one.

   There's a complicated way of making a list tag and an easy way.  I
suggest using the easy way.  Let's say you have three items in a list and
each of them is a hashref containing a row from a database.  You also have
a file with a template fragment that has tags with the same names as the
columns in that database.  To make a list using three copies of that
template and add it as a tag to the current template object, you can do:

     add_list_tag( ITEM_LIST => \@list );

   and then when you use the tag, you can specify the template file in a
parameter like this:

     <#ITEM_LIST ENTRY_FILE="entry.htmlf">

   If the columns in the database are "name", "address" and "phone", that
template might look like:

     <LI>Name: <#NAME HTMLESC><BR>
     Address: <#ADDRESS HTMLESC><BR>
     Phone: <#PHONE HTMLESC</LI>

   Note that the path to the template can be absolute or relative; it can
be any file on the system, so make sure you trust your HTML people if you
use this method to make a list tag for them.

   The second argument to add_list_tag is that list of tag hashrefs.  It
might look like:

     +[ +{
     	NAME => 'Jacob',
     	ADDRESS => 'A place',
     	PHONE => 'Some phone',
     }, +{
     	NAME => 'Matisse',
     	ADDRESS => 'Another place',
     	PHONE => 'A different phone',
     }, ]

   and for each entry in that list, it will use the hash ref as a miniature
set of tags for that entry.

   If you want to use the long way to make a list (not recommended; it's
what add_list_tag() uses internally), there are three things you need to
set:

A list (array).
An entry template.
A subroutine that takes one element of the list as an argument and returns a hash reference to a set of tags (which should appear in the entry_template.)
     You set the list of elements that you want to be made into a parsed
     list using the list() method.  It just takes a list.  Obviously, the
     ordering in that list is important.  Each element is a scalar, but it
     can be a reference, of course, and will usually be either a key or a
     reference to a more complex set of data.  For example:

          list( $jacob, $matisse, $alejandro );

     or 	list( \%hash1, \%hash2, \%hash3 );

     You set the templates for the entry and join templates with the
     entry_string() & join_string() or entry_file() & join_file() methods.
     These work in the way you would expect.  For example:

          entry_string( '<P>Name:  <#NAME></P><P>City:  <#CITY></P>' );
          join_string( '' );

     or:

          entry_file( 'entry.htmlf' );
          join_file(  'join.htmlf'  );

     Usually the _file methods are the ones you want.

     In the join template, you can either just use the existing tags
     stored in the object (which is recommended, since usually you don't
     care what's in the join template, if you use it at all) or you can
     supply your own set of tags with the join_tags() method, which works
     just like the tags() method.

     The complicated part is the callback.  You must supply a subroutine
     to generate the tags for each entry.  It's easier than it seems.

     The callback is set with the entry_callback() method.  It is called
     for each entry in the list, and its sole argument will be the item we
     are looking at from the list, a single scalar.  It must return a
     hash-ref of name/action pairs of the tags that appear in the entry
     template.  A callback might look like this:

          entry_callback( sub {
          	my( $person ) = @_;   # $person is assumed to be a hash-ref

          my $tags= +{ NAME => $person->name,
                       CITY => $person->city };

          return $tags;
          	} );

     You then have to make the list from this stuff, using the
     parse_list() or parse_list_files() methods.  These return the full
     parsed list as a string.  For example:

          $list = parse_list;

     or more often you'll be wanting to put that into another tag to put
     into your full-page template, like:

          add_tag( LIST => parse_list_files );

     That example above might produce a parsed list looking like:

          <P>Name:  Jacob</P><P>City:  Norwich</P>
          <P>Name:  Matisse</P><P>City:  San Francisco</P>
          <P>Name:  Alejandro</P><P>City:  San Francisco</P>

     which you could then insert into your output.

     If you're lazy and each item in your list is either a hashref or can
     easily be turned into one (for example, by returning a row from a
     database as a hashref) you may just want to return it directly, like
     this:

          entry_callback( sub {
          	( $userid ) = @_;
          	$sth = $dbh->prepare( <<"EOS" );
          SELECT * FROM users WHERE userid = "$userid"
          EOS
          	$sth->execute;
          	return $sth->fetchrow_hashref;
          } );

     or more even more lazily, something like this:

          $sth = $dbh->prepare( <<"EOS" );
          SELECT * FROM users
          EOS
          $sth->execute;
          while ( $user = $sth->fetchrow_hashref ) {
          	push @users, $user;
          }
          list( @users );
          entry_callback( sub { return $_[ 0 ] } );

     Isn't that easy?  What's even easier is that the default value for
     entry_callback() is `sub { return $_[ 0 ] }', so if your list is a
     list of hashrefs, you don't even need to touch it.

WHICH INTERFACE?
================

   You have a choice when using this module.  You may either use an
object-oriented interface, where you create new instances of
Text::TagTemplate objects and call methods on them, or you may use the
conventional interface, where you import these methods into your namespace
and call them without an object reference.  This is very similar to the
way the CGI module does things.  I recommend the latter method, because
the other forces you to do a lot of object referencing that isn't
particularly clear to read.  You might need to use it if you want multiple
objects or you are concerned about namespace conflicts.  You'll also want
to use the object interface if you're running under mod_perl, because
mod_perl uses a global to store the template object, and it won't get
deallocated between handler calls.

   For the OO interface, just use:

     use Text::TagTemplate;
     my $parser = new Text::TagTemplate;

   For the conventional interface, use:

     use Text::TagTemplate qw( :standard );

   and you'll get all the commonly-used methods automatically imported.
If you want the more obscure configuration methods, you can have them too
with:

     use Text::TagTemplate qw( :standard :config );

   The examples given here all use the conventional interface, for
clarity.  The OO interface would look like:

     $parser = new Text::TagTemplate;
     $parser->template_file( 'default.htmlt' );
     $parser->parse;

PER-METHOD DOCUMENTATION
========================

new() or `new( %tags )' or `new( \%tags )'
     Instantiate a new template object.  Optionally take a hash or
     hash-ref of tags to add initially.

`auto_cap()' or `auto_cap( $new_value )'
     Returns whether tag names will automatically be capitalised, and if a
     value is supplied sets the auto-capitalisation to this value first.
     Default is 1; changing it is not recommended but hey go ahead and
     ignore me anyway, what do I know?  Setting it to false will make tag
     names case-sensitive and you probably don't want that.

`unknown_action()' or `unknown_action( $action )'
     Returns what to do with unknown tags.  If a value is supplied sets
     the action to this value first.  If the action is the special value
     'DIE' then it will die at that point. This is the default.  If the
     action is the special value 'IGNORE' then unknown tags will be
     ignored by the module, and will appear unchanged in the parsed
     output.  If the special value 'WARN' is used then the the unknown
     tags will be replaced by warning text and logged with a  warn()
     call.  Other special values may be supplied later, so if scalar
     actions are require it is suggested that a scalar ref be supplied,
     where these special actions will not be taken no matter what the
     value.

tags() or `tags( %tags )' or `tags( \%tags )'
     Returns the contents of the tags as a hash-ref of tag/action pairs.
     If tags are supplied as a hash or hashref, it first sets the contents
     to these tags, clearing all previous tags.

`add_tag( $tag_name, $tag_action )'
     Adds a new tag.  Takes a tag name and the tag action.

`add_list_tag( $tag_name, \@list, $entry_callback, @join_tags )'
     Add a tag that will build a parsed list, allowing the person using
     the tag to supply the filename of the entry and join templates, or to
     supply the strings directly in tag parameters (which is currently
     annoying given the way they need to be escaped).  The tag will take
     parameters for ENTRY_STRING, ENTRY_FILE, JOIN_STRING or JOIN_FILE.

     No checking is currently performed on the filenames given.  This
     shouldn't be a security problem unless you're allowing untrusted
     users to write your templates for you, which mean it's a bug that I
     need to fix (since I want untrusted users to be able to write
     templates under some circumstnaces).

`add_tags( %tags )' or `add_tags( \%tags )'
     Adds a bunch of tags.  Takes a hash or hash-ref of tag/action pairs.

`delete_tag( $name )'
     Delete a tag by name.

`clear_tags()'
     Clears all existing tags.

list() or `list( @list )'
     Returns (and sets if supplied) the list of values to be used in
     parse_list() or parse_list_files() calls.

`template_string()' or `template_string( $string )'
     Returns (and sets if supplied) the default template string for
     parse().

`template_file()' or `template_file( $file )'
     Returns (and sets if supplied) the default template file for
     parse_file().

`entry_string()' or `entry_string( $string )'
     Returns (and sets if supplied) the entry string to be used in
     parse_list() calls.

`entry_file()' or `entry_file( $file )'
     Returns (and sets if supplied) the entry file to be used in
     parse_list_files() calls.

`entry_callback()' or `entry_callback( $callback )'
     Returns (and sets if supplied) the callback sub to be used in
     parse_list() or parse_list_files() calls.  If you don't set this, the
     default is just to return the item passed in, which will only work if
     the item is a hashref suitable for use as a set of tags.

`join_string()' or `join_string( $string )'
     Returns (and sets if supplied) the join string to be used in
     parse_list() calls.

`join_file()' or `join_file( $file )'
     Returns (and sets if supplied) the join file to be used in
     parse_list_files() calls.

`join_tags()' or `join_tags( %tags )' or `join_tags( \%tags )'
     Returns (and sets if supplied) the join tags to be used in
     parse_list() and parse_list_files() calls.

parse() or `parse( $string )' or `parse( $string, %tags )' or `parse( $string, \%tags )'
     Parse a string, either the default string, or a string supplied.
     Returns the string.  Can optionally also take the tags hash or
     hash-ref directly as well.

parse_file() or `parse_file( $file )' or `parse_file( $file, %tags )' or `parse_file( $file, \%tags )'
     Parses a file, either the default file or the supplied filename.
     Returns the parsed file.  Dies if the file cannot be read.  Can
     optionally take the tags hash or hash-ref directly.

`parse_list()' or `parse_list( \@list )'
or `parse_list( \@list, $entry_string, $join_string )'
or `parse_list( \@list, $entry_string, $join_string, $entry_callback, \%join_tags )'
     Makes a string from a list of entries, either the default or a
     supplied list.

     At least one template string is needed: the one  to use for each
     entry, and another is optional, to be used to join the entries.

     A callback subroutine must be supplied using entry_callback(), which
     takes the entry value from the list and must return a hash-ref of
     tags to be interpolated in the entry string.  This will be called for
     each entry in the list.  You can also supply a set of tags for the
     join string using join_tags(), but by default the main tags will be
     used in that string.

     You can also optionally supply the strings for the entry and join
     template.  Otherwise the strings set previously (with entry_string()
     and join_string() ) will be used.

     Finally, you can also supply the callback sub and join tags directly
     if you want.

`parse_list_files()' or `parse_list_files( \@list )'
or `parse_list_files( \@list, $entry_file, $join_file )'
or `parse_list_files( \@list, $entry_file, $join_file, $entry_callback )'
or `parse_list_files( \@list, $entry_file, $join_file, $entry_callback, %join_tags )'
or `parse_list_files( \@list, $entry_file, $join_file, $entry_callback, \%join_tags )'
     Exactly as parse_list(), but using filenames, not strings.

COPYRIGHT
=========

   Copyright (C) 2000 SF Interactive, Inc.  All rights reserved.

LICENSE
=======

   This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or (at
your option) any later version.

   This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
License for more details.

   You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

AUTHOR
======

   Jacob Davies

     <jacob@sfinteractive.com>
     <jacob@well.com>

SEE ALSO
========

   The README file supplied with the distribution, and the example/
subdirectory there, which contains a full CGI application using this
module.

   The CGI module documentation.

   Apache::TagRegistry(1)

Expand template text with embedded Perl
***************************************

NAME
====

   Text::Template - Expand template text with embedded Perl

VERSION
=======

   This file documents `Text::Template' version *1.30*

SYNOPSIS
========

     use Text::Template;

     $template = new Text::Template (TYPE => FILE,  SOURCE => 'filename.tmpl');
     $template = new Text::Template (TYPE => ARRAY, SOURCE => [ ... ] );
     $template = new Text::Template (TYPE => FILEHANDLE, SOURCE => $fh );
     $template = new Text::Template (TYPE => STRING, SOURCE => '...' );
     $template = new Text::Template (PREPEND => q{use strict;}, ...);

     # Use a different template file syntax:
     $template = new Text::Template (DELIMITERS => [$open, $close], ...);

     $recipient = 'King';
     $text = $template->fill_in();  # Replaces `{$recipient}' with `King'
     print $text;

     $T::recipient = 'Josh';
     $text = $template->fill_in(PACKAGE => T);

     $hash = { recipient => 'Abed-Nego' };
     $text = $template->fill_in(HASH => $hash, ...); # Recipient is Abed-Nego

     # Call &callback in case of programming errors in template
     $text = $template->fill_in(BROKEN => \&callback, BROKEN_ARG => [...]);

     # Evaluate program fragments in Safe compartment with restricted permissions
     $text = $template->fill_in(SAFE => $compartment, ...);

     # Print result text instead of returning it
     $success = $template->fill_in(OUTPUT => \*FILEHANDLE, ...);

     # Parse template with different template file syntax:
     $text = $template->fill_in(DELIMITERS => [$open, $close], ...);
     # Note that this is *faster* than using the default delimiters

     # Prepend specified perl code to each fragment before evaluating:
     $text = $template->fill_in(PREPEND => q{use strict 'vars';}, ...);

     use Text::Template 'fill_in_string';
     $text = fill_in_string( <<EOM, PACKAGE => 'T', ...);
     Dear {$recipient},
     Pay me at once.
            Love,
             G.V.
     EOM

     use Text::Template 'fill_in_file';
     $text = fill_in_file($filename, ...);

     # All templates will always have `use strict vars' attached to all fragments
     Text::Template->always_prepend(q{use strict 'vars';});

DESCRIPTION
===========

   This is a library for generating form letters, building HTML pages, or
filling in templates generally.  A `template' is a piece of text that has
little Perl programs embedded in it here and there.  When you `fill in' a
template, you evaluate the little programs and replace them with their
values.

   You can store a template in a file outside your program.  People can
modify the template without modifying the program.  You can separate the
formatting details from the main code, and put the formatting parts of the
program into the template.  That prevents code bloat and encourages
functional separation.

Example
-------

   Here's an example of a template, which we'll suppose is stored in the
file `formletter.tmpl':

     Dear {$title} {$lastname},

     It has come to our attention that you are delinquent in your
     {$monthname[$last_paid_month]} payment.  Please remit
     ${sprintf("%.2f", $amount)} immediately, or your patellae may
     be needlessly endangered.

     Love,

     Mark "Vizopteryx" Dominus

   The result of filling in this template is a string, which might look
something like this:

     Dear Mr. Gates,

     It has come to our attention that you are delinquent in your
     February payment.  Please remit
     $392.12 immediately, or your patellae may
     be needlessly endangered.

     Love,

     Mark "Vizopteryx" Dominus

   Here is a complete program that transforms the example template into
the example result, and prints it out:

     use Text::Template;

     my $template = new Text::Template (SOURCE => 'formletter.tmpl')
       or die "Couldn't construct template: $Text::Template::ERROR";

     my @monthname = qw(January February March April May June
                                July August September October November December);
     my %vars = (title => 'Mr.',
     	    firstname => 'Bill',
     	    lastname => 'Gates',
     	    last_paid_month => 1,   # February
     	    amount => 392.12,
     	    monthname => \@monthname,
     	   );

     my $result = $template->fill_in(HASH => \%vars);

     if (defined $result) { print $result }
     else { die "Couldn't fill in template: $Text::Template::ERROR" }

Philosophy
----------

   When people make a template module like this one, they almost always
start by inventing a special syntax for substitutions.  For example, they
build it so that a string like `%%VAR%%' is replaced with the value of
`$VAR'.  Then they realize the need extra formatting, so they put in some
special syntax for formatting.  Then they need a loop, so they invent a
loop syntax.  Pretty soon they have a new little template language.

   This approach has two problems: First, their little language is
crippled. If you need to do something the author hasn't thought of, you
lose.  Second: Who wants to learn another language?  You already know
Perl, so why not use it?

   `Text::Template' templates are programmed in Perl.  You embed Perl code
in your template, with `{' at the beginning and `}' at the end.  If you
want a variable interpolated, you write it the way you would in Perl.  If
you need to make a loop, you can use any of the Perl loop constructions.
All the Perl built-in functions are available.

Details
=======

Template Parsing
----------------

   The `Text::Template' module scans the template source.  An open brace
`{' begins a program fragment, which continues until the matching close
brace `}'.  When the template is filled in, the program fragments are
evaluated, and each one is replaced with the resulting value to yield the
text that is returned.

   A backslash \ in front of a brace (or another backslash that is in
front of a brace) escapes its special meaning.  The result of filling out
this template:

     \{ The sum of 1 and 2 is {1+2}  \}

   is

     { The sum of 1 and 2 is 3  }

   If you have an unmatched brace, `Text::Template' will return a failure
code and a warning about where the problem is.  Backslashes that do not
precede a brace are passed through unchanged.  If you have a template like
this:

     { "String that ends in a newline.\n" }

   The backslash inside the string is passed through to Perl unchanged, so
the \n really does turn into a newline.  See the note at the end for
details about the way backslashes work.  Backslash processing is not done
when you specify alternative delimiters with the `DELIMITERS' option.
(See `"Alternative Delimiters"' in this node, below.)

   Each program fragment should be a sequence of Perl statements, which
are evaluated the usual way.  The result of the last statement executed
will be evaluted in scalar context; the result of this statement is a
string, which is interpolated into the template in place of the program
fragment itself.

   The fragments are evaluated in order, and side effects from earlier
fragments will persist into later fragments:

     {$x = @things; ''}The Lord High Chamberlain has gotten {$x}
     things for me this year.
     { $diff = $x - 17;
       $more = 'more'
       if ($diff == 0) {
         $diff = 'no';
       } elsif ($diff < 0) {
         $more = 'fewer';
       }
               '';
     }
     That is {$diff} {$more} than he gave me last year.

   The value of $x set in the first line will persist into the next
fragment that begins on the third line, and the values of `$diff' and
`$more' set in the second fragment will persist and be interpolated into
the last line.  The output will look something like this:

     The Lord High Chamberlain has gotten 42
     things for me this year.

     That is 35 more than he gave me last year.

   That is all the syntax there is.

The `$OUT' variable
-------------------

   There is one special trick you can play in a template.  Here is the
motivation for it:  Suppose you are going to pass an array, `@items', into
the template, and you want the template to generate a bulleted list with a
header, like this:

     Here is a list of the things I have got for you since 1907:
       * Ivory
       * Apes
       * Peacocks
       * ...

   One way to do it is with a template like this:

     Here is a list of the things I have got for you since 1907:
     { my $blist = '';
               foreach $i (@items) {
                 $blist .= qq{  * $i\n};
               }
               $blist;
             }

   Here we construct the list in a variable called `$blist', which we
return at the end.  This is a little cumbersome.  There is a shortcut.

   Inside of templates, there is a special variable called `$OUT'.
Anything you append to this variable will appear in the output of the
template.  Also, if you use `$OUT' in a program fragment, the normal
behavior, of replacing the fragment with its return value, is disabled;
instead the fragment is replaced with the value of `$OUT'.  This means
that you can write the template above like this:

     Here is a list of the things I have got for you since 1907:
     { foreach $i (@items) {
                 $OUT .= "  * $i\n";
               }
             }

   `$OUT' is reinitialized to the empty string at the start of each
program fragment.  It is private to `Text::Template', so you can't use a
variable named `$OUT' in your template without invoking the special
behavior.

General Remarks
---------------

   All `Text::Template' functions return undef on failure, and set the
variable `$Text::Template::ERROR' to contain an explanation of what went
wrong.  For example, if you try to create a template from a file that does
not exist, `$Text::Template::ERROR' will contain something like:

     Couldn't open file xyz.tmpl: No such file or directory

new
---

     $template = new Text::Template ( TYPE => ..., SOURCE => ... );

   This creates and returns a new template object.  new returns undef and
sets `$Text::Template::ERROR' if it can't create the template object.
SOURCE says where the template source code will come from.  TYPE says what
kind of object the source is.

   The most common type of source is a file:

     new Text::Template ( TYPE => 'FILE', SOURCE => $filename );

   This reads the template from the specified file.  The filename is
opened with the Perl open command, so it can be a pipe or anything else
that makes sense with open.

   The TYPE can also be STRING, in which case the SOURCE should be a
string:

     new Text::Template ( TYPE => 'STRING',
                                  SOURCE => "This is the actual template!" );

   The TYPE can be ARRAY, in which case the source should be a reference
to an array of strings.  The concatenation of these strings is the
template:

     new Text::Template ( TYPE => 'ARRAY',
                                  SOURCE => [ "This is ", "the actual",
                                              " template!",
                                            ]
                                );

   The TYPE can be FILEHANDLE, in which case the source should be an open
filehandle (such as you got from the FileHandle or `IO::*' packages, or a
glob, or a reference to a glob).  In this case `Text::Template' will read
the text from the filehandle up to end-of-file, and that text is the
template:

     # Read template source code from STDIN:
     new Text::Template ( TYPE => 'FILEHANDLE',
                                  SOURCE => \*STDIN  );

   If you omit the TYPE attribute, it's taken to be FILE.  SOURCE is
required.  If you omit it, the program will abort.

   The words TYPE and SOURCE can be spelled any of the following ways:

     TYPE	SOURCE
     Type	Source
     type	source
     -TYPE	-SOURCE
     -Type	-Source
     -type	-source

   Pick a style you like and stick with it.

`DELIMITERS'
     You may also add a `DELIMITERS' option.  If this option is present,
     its value should be a reference to an array of two strings.  The first
     string is the string that signals the beginning of each program
     fragment, and the second string is the string that signals the end of
     each program fragment.  See `"Alternative Delimiters"' in this node,
     below.

compile
-------

     $template->compile()

   Loads all the template text from the template's source, parses and
compiles it.  If successful, returns true; otherwise returns false and
sets `$Text::Template::ERROR'.  If the template is already compiled, it
returns true and does nothing.

   You don't usually need to invoke this function, because `fill_in' (see
below) compiles the template if it isn't compiled already.

   If there is an argument to this function, it must be a reference to an
array containing alternative delimiter strings.  See `"Alternative
Delimiters"', below.

`fill_in'
---------

     $template->fill_in(OPTIONS);

   Fills in a template.  Returns the resulting text if successful.
Otherwise, returns undef  and sets `$Text::Template::ERROR'.

   The OPTIONS are a hash, or a list of key-value pairs.  You can write
the key names in any of the six usual styles as above; this means that
where this manual says PACKAGE (for example) you can actually use any of

     PACKAGE Package package -PACKAGE -Package -package

   Pick a style you like and stick with it.  The all-lowercase versions
may yield spurious warnings about

     Ambiguous use of package => resolved to "package"

   so you might like to avoid them and use the capitalized versions.

   At present, there are seven legal options:  PACKAGE, `BROKEN',
`BROKEN_ARG', SAFE, HASH, OUTPUT, and `DELIMITERS'.

PACKAGE
     PACKAGE specifies the name of a package in which the program
     fragments should be evaluated.  The default is to use the package from
     which `fill_in' was called.  For example, consider this template:

          The value of the variable x is {$x}.

     If you use `$template->fill_in(PACKAGE => 'R')' , then the $x in the
     template is actually replaced with the value of `$R::x'.  If you omit
     the PACKAGE option, $x will be replaced with the value of the $x
     variable in the package that actually called `fill_in'.

     You should almost always use PACKAGE.  If you don't, and your
     template makes changes to variables, those changes will be propagated
     back into the main program.  Evaluating the template in a private
     package helps prevent this.  The template can still modify variables
     in your program if it wants to, but it will have to do so explicitly.
     See the section at the end on `Security'.

     Here's an example of using PACKAGE:

          Your Royal Highness,

          Enclosed please find a list of things I have gotten
          for you since 1907:

          { foreach $item (@items) {
                      $item_no++;
              $OUT .= " $item_no. \u$item\n";
            }
          }

          Signed,
          Lord High Chamberlain

     We want to pass in an array which will be assigned to the array
     `@items'.  Here's how to do that:

          @items = ('ivory', 'apes', 'peacocks', );
          $template->fill_in();

     This is not very safe.  The reason this isn't as safe is that if you
     had a variable named `$item_no' in scope in your program at the point
     you called `fill_in', its value would be clobbered by the act of
     filling out the template.  The problem is the same as if you had
     written a subroutine that used those variables in the same way that
     the template does.  (`$OUT' is special in templates and is always
     safe.)

     One solution to this is to make the `$item_no' variable private to the
     template by declaring it with my.  If the template does this, you are
     safe.

     But if you use the PACKAGE option, you will probably be safe even if
     the template does not declare its variables with my:

          @Q::items = ('ivory', 'apes', 'peacocks', );
          $template->fill_in(PACKAGE => 'Q');

     In this case the template will clobber the variable `$Q::item_no',
     which is not related to the one your program was using.

     Templates cannot affect variables in the main program that are
     declared with my, unless you give the template references to those
     variables.

HASH
     You may not want to put the template variables into a package.
     Packages can be hard to manage:  You can't copy them, for example.
     HASH provides an alternative.

     The value for HASH should be a reference to a hash that maps variable
     names to values.  For example,

          $template->fill_in(HASH => { recipient => "The King",
          			     items => ['gold', 'frankincense', 'myrrh']
          			   });

     will fill out the template and use `"The King"' as the value of
     `$recipient' and the list of items as the value of `@items'.

     The full details of how it works are a little involved, so you might
     want to skip to the next section.

     Suppose the key in the hash is key and the value is value.

        * If the value is undef, then any variables named $key, `@key',
          `%key', etc., are undefined.

        * If the value is a string or a number, then $key is set to that
          value in the template.

        * If the value is a reference to an array, then `@key' is set to
          that array.  If the value is a reference to a hash, then `%key'
          is set to that hash.  Similarly if value is any other kind of
          reference.  This means that

               var => "foo"

          and

               var => \"foo"

          have almost exactly the same effect.  (The difference is that in
          the former case, the value is copied, and in the latter case it
          is aliased.)

     Normally, the way this works is by allocating a private package,
     loading all the variables into the package, and then filling out the
     template as if you had specified that package.  A new package is
     allocated each time.  However, if you *also* use the PACKAGE option,
     `Text::Template' loads the variables into the package you specified,
     and they stay there after the call returns.  Subsequent calls to
     `fill_in' that use the same package will pick up the values you
     loaded in.

     If the argument of HASH is a reference to an array instead of a
     reference to a hash, then the array should contain a list of hashes
     whose contents are loaded into the template package one after the
     other.  You can use this feature if you want to combine several sets
     of variables.  For example, one set of variables might be the defaults
     for a fill-in form, and the second set might be the user inputs, which
     override the defaults when they are present:

          $template->fill_in(HASH => [\%defaults, \%user_input]);

     You can also use this to set two variables with the same name:

          $template->fill_in(HASH => [{ v => "The King" },
                                              { v => [1,2,3] },
                                     ]
                                    );

     This sets `$v' to `"The King"' and `@v' to `(1,2,3)'.

`BROKEN'
     If any of the program fragments fails to compile or aborts for any
     reason, and you have set the `BROKEN' option to a function reference,
     `Text::Template' will invoke the function.  This function is called
     the *`BROKEN' function*.  The `BROKEN' function will tell
     `Text::Template' what to do next.

     If the `BROKEN' function returns undef, `Text::Template' will
     immediately abort processing the template and return the text that it
     has accumulated so far.  If your function does this, it should set a
     flag that you can examine after `fill_in' returns so that you can
     tell whether there was a premature return or not.

     If the `BROKEN' function returns any other value, that value will be
     interpolated into the template as if that value had been the return
     value of the program fragment to begin with.  For example, if the
     `BROKEN' function returns an error string, the error string will be
     interpolated into the output of the template in place of the program
     fragment that cased the error.

     If you don't specify a `BROKEN' function, `Text::Template' supplies a
     default one that returns something like

          Program fragment at line 17 delivered error ``Illegal
          division by 0''

     Since this is interpolated into the template at the place the error
     occurred, a template like this one:

          (3+4)*5 = { 3+4)*5 }

     yields this result:

          (3+4)*5 = Program fragment at line 1 delivered error
          ``syntax error''

     If you specify a value for the `BROKEN' attribute, it should be a
     reference to a function that `fill_in' can call instead of the
     default function.

     `fill_in' will pass a hash to the `broken' function.  The hash will
     have at least these three members:

    text
          The source code of the program fragment that failed

    error
          The text of the error message (`$@') generated by eval

    lineno
          The line number of the template data at which the  program
          fragment began

     There may also be an `arg' member.  See `BROKEN_ARG', below

`BROKEN_ARG'
     If you supply the `BROKEN_ARG' option to `fill_in', the value of the
     option is passed to the `BROKEN' function whenever it is called.  The
     default `BROKEN' function ignores the `BROKEN_ARG', but you can write
     a custom `BROKEN' function that uses the `BROKEN_ARG' to get more
     information about what went wrong.

     The `BROKEN' function could also use the `BROKEN_ARG' as a reference
     to store an error message or some other information that it wants to
     communicate back to the caller.  For example:

          $error = '';

          sub my_broken {
             my %args = @_;
             my $err_ref = $args{arg};
             ...
             $$err_ref = "Some error message";
             return undef;
          }

          $template->fill_in(BROKEN => \&my_broken,
          		   BROKEN_ARG => \$error,
          		  );

          if ($error) {
            die "It didn't work: $error";
          }

     If one of the program fragments in the template fails, it will call
     the `BROKEN' function, `my_broken', and pass it the `BROKEN_ARG',
     which is a reference to $error.  `my_broken' can store an error
     message into $error this way.  Then the function that called
     `fill_in' can see if `my_broken' has left an error message for it to
     find, and proceed accordingly.

SAFE
     If you give `fill_in' a SAFE option, its value should be a safe
     compartment object from the Safe package.  All evaluation of program
     fragments will be performed in this compartment.  See Safe,
     for full details about such compartments and how to restrict the
     operations that can be performed in them.

     If you use the PACKAGE option with SAFE, the package you specify will
     be placed into the safe compartment and evaluation will take place in
     that package as usual.

     If not, SAFE operation is a little different from the default.
     Usually, if you don't specify a package, evaluation of program
     fragments occurs in the package from which the template was invoked.
     But in SAFE mode the evaluation occurs inside the safe compartment
     and cannot affect the calling package.  Normally, if you use HASH
     without PACKAGE, the hash variables are imported into a private,
     one-use-only package.  But if you use HASH and SAFE together without
     PACKAGE, the hash variables will just be loaded into the root
     namespace of the Safe compartment.

OUTPUT
     If your template is going to generate a lot of text that you are just
     going to print out again anyway,  you can save memory by having
     `Text::Template' print out the text as it is generated instead of
     making it into a big string and returning the string.  If you supply
     the OUTPUT option to `fill_in', the value should be a filehandle.
     The generated text will be printed to this filehandle as it is
     constructed.  For example:

          $template->fill_in(OUTPUT => \*STDOUT, ...);

     fills in the $template as usual, but the results are immediately
     printed to STDOUT.  This may result in the output appearing more
     quickly than it would have otherwise.

     If you use OUTPUT, the return value from `fill_in' is still true on
     success and false on failure, but the complete text is not returned to
     the caller.

`PREPEND'
     You can have some Perl code prepended automatically to the beginning
     of every program fragment.  See ``PREPEND' in this node feature and
     using `strict' in templates' below.

`DELIMITERS'
     If this option is present, its value should be a reference to a list
     of two strings.  The first string is the string that signals the
     beginning of each program fragment, and the second string is the
     string that signals the end of each program fragment.  See
     `"Alternative Delimiters"' in this node, below.

     If you specify `DELIMITERS' in the call to `fill_in', they override
     any delimiters you set when you created the template object with new.

Convenience Functions
=====================

`fill_this_in'
--------------

   The basic way to fill in a template is to create a template object and
then call `fill_in' on it.   This is useful if you want to fill in the
same template more than once.

   In some programs, this can be cumbersome.  `fill_this_in' accepts a
string, which contains the template, and a list of options, which are
passed to `fill_in' as above.  It constructs the template object for you,
fills it in as specified, and returns the results.  It returns undef and
sets `$Text::Template::ERROR' if it couldn't generate any results.

   An example:

     $Q::name = 'Donald';
     $Q::amount = 141.61;
     $Q::part = 'hyoid bone';

     $text = Text::Template->fill_this_in( <<'EOM', PACKAGE => Q);
     Dear {$name},
     You owe me \\${sprintf('%.2f', $amount)}.
     Pay or I will break your {$part}.
     	Love,
     	Grand Vizopteryx of Irkutsk.
     EOM

   Notice how we included the template in-line in the program by using a
`here document' with the `<<' notation.

   `fill_this_in' is a deprecated feature.  It is only here for backwards
compatibility, and may be removed in some far-future version in
`Text::Template'.  You should use `fill_in_string' instead.  It is
described in the next section.

`fill_in_string'
----------------

   It is stupid that `fill_this_in' is a class method.  It should have
been just an imported function, so that you could omit the
`Text::Template->' in the example above.  But I made the mistake four
years ago and it is too late to change it.

   `fill_in_string' is exactly like `fill_this_in' except that it is not a
method and you can omit the `Text::Template->' and just say

     print fill_in_string(<<'EOM', ...);
     Dear {$name},
       ...
     EOM

   To use `fill_in_string', you need to say

     use Text::Template 'fill_in_string';

   at the top of your program.   You should probably use `fill_in_string'
instead of `fill_this_in'.

`fill_in_file'
--------------

   If you import `fill_in_file', you can say

     $text = fill_in_file(filename, ...);

   The ... are passed to `fill_in' as above.  The filename is the name of
the file that contains the template you want to fill in.  It returns the
result text. or undef, as usual.

   If you are going to fill in the same file more than once in the same
program you should use the longer new / `fill_in' sequence instead.  It
will be a lot faster because it only has to read and parse the file once.

Including files into templates
------------------------------

   People always ask for this.  "Why don't you have an include function?"
they want to know.  The short answer is this is Perl, and Perl already has
an include function.  If you want it, you can just put

     {qx{cat filename}}

   into your template.  VoilE<agrave>.

   If you don't want to use cat, you can write a little four-line function
that opens a file and dumps out its contents, and call it from the
template.  I wrote one for you.  In the template, you can say

     {Text::Template::_load_text(filename)}

   If that is too verbose, here is a trick.  Suppose the template package
that you are going to be mentioning in the `fill_in' call is package Q.
Then in the main program, write

     *Q::include = \&Text::Template::_load_text;

   This imports the `_load_text' function into package Q with the name
include.  From then on, any template that you fill in with package Q can
say

     {include(filename)}

   to insert the text from the named file at that point.  If you are using
the HASH option instead, just put `include =>
\&Text::Template::_load_text' into the hash instead of importing it
explicitly.

   Suppose you don't want to insert a plain text file, but rather you want
to include one template within another?  Just use `fill_in_file' in the
template itself:

     {Text::Template::fill_in_file(filename)}

   You can do the same importing trick if this is too much to type.

Miscellaneous
=============

my variables
------------

   People are frequently surprised when this doesn't work:

     my $recipient = 'The King';
     my $text = fill_in_file('formletter.tmpl');

   The text `The King' doesn't get into the form letter.  Why not?
Because `$recipient' is a my variable, and the whole point of my variables
is that they're private and inaccessible except in the scope in which
they're declared.  The template is not part of that scope, so the template
can't see `$recipient'.

   If that's not the behavior you want, don't use my.  my means a private
variable, and in this case you don't want the variable to be private.  Put
the variables into package variables in some other package, and use the
PACKAGE option to `fill_in':

     $Q::recipient = $recipient;
     my $text = fill_in_file('formletter.tmpl', PACKAGE => 'Q');

   or pass the names and values in a hash with the HASH option:

     my $text = fill_in_file('formletter.tmpl', HASH => { recipient => $recipient });

Security Matters
----------------

   All variables are evaluated in the package you specify with the PACKAGE
option of `fill_in'.  if you use this option, and if your templates don't
do anything egregiously stupid, you won't have to worry that evaluation of
the little programs will creep out into the rest of your program and wreck
something.

   Nevertheless, there's really no way (except with Safe) to protect
against a template that says

     { $Important::Secret::Security::Enable = 0;
       # Disable security checks in this program
     }

   or

     { $/ = "ho ho ho";   # Sabotage future uses of <FH>.
       # $/ is always a global variable
     }

   or even

     { system("rm -rf /") }

   so *don't* go filling in templates unless you're sure you know what's
in them.  If you're worried, or you can't trust the person who wrote the
template, use the SAFE option.

   A final warning: program fragments run a small risk of accidentally
clobbering local variables in the `fill_in' function itself.  These
variables all have names that begin with `$fi_', so if you stay away from
those names you'll be safe.  (Of course, if you're a real wizard you can
tamper with them deliberately for exciting effects; this is actually how
`$OUT' works.)  I can fix this, but it will make the package slower to do
it, so I would prefer not to.  If you are worried about this, send me mail
and I will show you what to do about it.

Alternative Delimiters
----------------------

   Lorenzo Valdettaro pointed out that if you are using `Text::Template'
to generate TeX output, the choice of braces as the program fragment
delimiters makes you suffer suffer suffer.  Starting in version 1.20, you
can change the choice of delimiters to something other than curly braces.

   In either the new() call or the `fill_in()' call, you can specify an
alternative set of delimiters with the `DELIMITERS' option.  For example,
if you would like code fragments to be delimited by `[@--' and `--@]'
instead of `{' and `}', use

     ... DELIMITERS => [ '[@--', '--@]' ], ...

   Note that these delimiters are *literal strings*, not regexes.  (I
tried for regexes, but it complicates the lexical analysis too much.)
Note also that `DELIMITERS' disables the special meaning of the backslash,
so if you want to include the delimiters in the literal text of your
template file, you are out of luck--it is up to you to choose delimiters
that do not conflict with what you are doing.  The delimiter strings may
still appear inside of program fragments as long as they nest properly.
This means that if for some reason you absolutely must have a program
fragment that mentions one of the delimiters, like this:

     [@--
     	print "Oh no, a delimiter: --@]\n"
     --@]

   you may be able to make it work by doing this instead:

     [@--
     	# Fake matching delimiter in a comment: [@--
     	print "Oh no, a delimiter: --@]\n"
     --@]

   It may be safer to choose delimiters that begin with a newline
character.

   Because the parsing of templates is simplified by the absence of
backslash escapes, using alternative `DELIMITERS' *speeds up* the parsing
process by 20-25%.  This shows that my original choice of `{' and `}' was
very bad.  I therefore recommend that you use alternative delimiters
whenever possible.

`PREPEND' feature and using strict in templates
-----------------------------------------------

   Suppose you would like to use strict in your templates to detect
undeclared variables and the like.  But each code fragment is a separate
lexical scope, so you have to turn on strict at the top of each and every
code fragment:

     { use strict;
       use vars '$foo';
       $foo = 14;
       ...
     }

     ...

     { # we forgot to put `use strict' here
       my $result = $boo + 12;    # $boo is misspelled and should be $foo
       # No error is raised on `$boo'
     }

   Because we didn't put `use strict' at the top of the second fragment,
it was only active in the first fragment, and we didn't get any strict
checking in the second fragment.  Then we mispelled `$foo' and the error
wasn't caught.

   `Text::Template' version 1.22 and higher has a new feature to make this
easier.  You can specify that any text at all be automatically added to
the beginning of each program fragment.

   When you make a call to `fill_in', you can specify a

     PREPEND => 'some perl statements here'

   option; the statements will be prepended to each program fragment for
that one call only.  Suppose that the `fill_in' call included a

     PREPEND => 'use strict;'

   option, and that the template looked like this:

     { use vars '$foo';
       $foo = 14;
       ...
     }

     ...

     { my $result = $boo + 12;    # $boo is misspelled and should be $foo
       ...
     }

   The code in the second fragment would fail, because `$boo' has not been
declared.  `use strict' was implied, even though you did not write it
explicitly, because the `PREPEND' option added it for you automatically.

   There are two other ways to do this.  At the time you create the
template object with new, you can also supply a `PREPEND' option, in which
case the statements will be prepended each time you fill in that template.
If the `fill_in' call has its own `PREPEND' option, this overrides the
one specified at the time you created the template.  Finally, you can make
the class method call

     Text::Template->always_prepend('perl statements');

   If you do this, then call calls to `fill_in' for any template will
attach the perl statements to the beginning of each program fragment,
except where overridden by `PREPEND' options to new or `fill_in'.

Prepending in Derived Classes
-----------------------------

   This section is technical, and you should skip it on the first few
readings.

   Normally there are three places that prepended text could come from.
It could come from the `PREPEND' option in the `fill_in' call, from the
`PREPEND' option in the new call that created the template object, or from
the argument of the `always_prepend' call.  `Text::Template' looks for
these three things in order and takes the first one that it finds.

   In a subclass of `Text::Template', this last possibility is ambiguous.
Suppose S is a subclass of `Text::Template'.  Should

     Text::Template->always_prepend(...);

   affect objects in class Derived?  The answer is that you can have it
either way.

   The `always_prepend' value for `Text::Template' is normally stored in
a hash variable named `%GLOBAL_PREPEND' under the key `Text::Template'.
When `Text::Template' looks to see what text to prepend, it first looks in
the template object itself, and if not, it looks in
`$GLOBAL_PREPEND{*class*}' where class is the class to which the template
object belongs.  If it doesn't find any value, it looks in
`$GLOBAL_PREPEND{'Text::Template'}'.  This means that objects in class
Derived *will* be affected by

     Text::Template->always_prepend(...);

   *unless* there is also a call to

     Derived->always_prepend(...);

   So when you're designing your derived class, you can arrange to have
your objects ignore `Text::Template::always_prepend' calls by simply
putting `Derived->always_prepend('')' at the top of your module.

   Of course, there is also a final escape hatch: Templates support a
`prepend_text' that is used to look up the appropriate text to be
prepended at `fill_in' time.  Your derived class can override this method
to get an arbitrary effect.

JavaScript
----------

   Jennifer D. St Clair asks:

     > Most of my pages contain JavaScript and Stylesheets.
             > How do I change the template identifier?

   Jennifer is worried about the braces in the JavaScript being taken as
the delimiters of the Perl program fragments.  Of course, disaster will
ensue when perl tries to evaluate these as if they were Perl programs.
The best choice is to find some unambiguous delimiter strings that you can
use in your template instead of curly braces, and then use the
`DELIMITERS' option.  However, if you can't do this for some reason, there
are  two easy workarounds:

   1. You can put \ in front of `{', `}', or \ to remove its special
meaning.  So, for example, instead of

     if (br== "n3") {
     		// etc.
     }

   you can put

     if (br== "n3") \{
     		// etc.
     \}

   and it'll come out of the template engine the way you want.

   But here is another method that is probably better.  To see how it
works, first consider what happens if you put this into a template:

     { 'foo' }

   Since it's in braces, it gets evaluated, and obviously, this is going
to turn into

     foo

   So now here's the trick: In Perl, `q{...}' is the same as `'...''.  So
if we wrote

     {q{foo}}

   it would turn into

     foo

   So for your JavaScript, just write

     {q{if (br== "n3") {
     	  	 // etc.
        }}
     }

   and it'll come out as

     if (br== "n3") {
     	  	  // etc.
     }

   which is what you want.

Shut Up!
--------

   People sometimes try to put an initialization section at the top of
their templates, like this:

     { ...
       $var = 17;
     }

   Then they complain because there is a 17 at the top of the output that
they didn't want to have there.

   Remember that a program fragment is replaced with its own return value,
and that in Perl the return value of a code block is the value of the last
expression that was evaluated, which in this case is 17.  If it didn't do
that, you wouldn't be able to write `{$recipient}' and have the recipient
filled in.

   To prevent the 17 from appearing in the output is very simple:

     { ...
       $var = 17;
       '';
     }

   Now the last expression evaluated yields the empty string, which is
invisible.  If you don't like the way this looks, use

     { ...
       $var = 17;
       ($SILENTLY);
     }

   instead.  Presumably, `$SILENTLY' has no value, so nothing will be
interpolated.  This is what is known as a `trick'.

Compatibility
-------------

   Every effort has been made to make this module compatible with older
versions.  There are three exceptions.  One is the output format of the
default `BROKEN' subroutine; I decided that the old format was too
verbose.  If this bothers you, it's easy to supply a custom subroutine
that yields the old behavior.  The second is that the `$OUT' feature
arrogates the `$OUT' variable for itself.  If you had templates that
happened to use a variable named `$OUT', you will have to change them to
use some other variable or all sorts of strangeness may result.

   The third incompatibility is with the behavior of the \ metacharacter.
In 0.1b, \\ was special everywhere, and the template processor always
replaced it with a single backslash before passing the code to Perl for
evaluation.  The rule now is more complicated but probably more
convenient.  See the section on backslash processing, below, for a full
discussion.

   With a minor change to fix the format of the default `BROKEN'
subroutine, this version passes the test suite from the old version.  (It
is in `t/01-basic.t'.) The old test suite was too small, but it's a little
reassuring.

Backslash Processing
--------------------

   In `Text::Template' beta versions, the backslash was special whenever
it appeared before a brace or another backslash.  That meant that while
`{"\n"}' did indeed generate a newline, `{"\\"}' did not generate a
backslash, because the code passed to Perl for evaluation was `"\"' which
is a syntax error.  If you wanted a backslash, you would have had to write
`{"\\\\"}'.

   In `Text::Template' versions 1.0 through 1.10, there was a bug:
Backslash was special everywhere.  In these versions, `{"\n"}' generated
the letter n.

   The bug has been corrected in version 1.11, but I did not go back to
exactly the old rule, because I did not like the idea of having to write
`{"\\\\"}' to get one backslash.  The rule is now more complicated to
remember, but probably easier to use.  The rule is now: Backslashes are
always passed to Perl unchanged *unless* they occur as part of a sequence
like `\\\\\\{' or `\\\\\\}'.  In these contexts, they are special; \\ is
replaced with \, and `\{' and `\}' signal a literal brace.

   Examples:

     \{ foo \}

   is not evaluated, because the \ before the braces signals that they
should be taken literally.  The result in the output looks like this:

     { foo }

   This is a syntax error:

     { "foo}" }

   because `Text::Template' thinks that the code ends at the first `}',
and then gets upset when it sees the second one.  To make this work
correctly, use

     { "foo\}" }

   This passes `"foo}"' to Perl for evaluation.  Note there's no \ in the
evaluated code.  If you really want a \ in the evaluated code, use

     { "foo\\\}" }

   This passes `"foo\}"' to Perl for evaluation.

   Starting with `Text::Template' version 1.20, backslash processing is
disabled if you use the `DELIMITERS' option to specify alternative
delimiter strings.

A short note about `$Text::Template::ERROR'
-------------------------------------------

   In the past some people have fretted about `violating the package
boundary' by examining a variable inside the `Text::Template' package.
Don't feel this way.  `$Text::Template::ERROR' is part of the published,
official interface to this package.  It is perfectly OK to inspect this
variable.  The interface is not going to change.

   If it really, really bothers you, you can import a function called
`TTerror' that returns the current value of the `$ERROR' variable.  So you
can say:

     use Text::Template 'TTerror';

     my $template = new Text::Template (SOURCE => $filename);
     unless ($template) {
       my $err = TTerror;
       die "Couldn't make template: $err; aborting";
     }

   I don't see what benefit this has over just doing this:

     use Text::Template;

     my $template = new Text::Template (SOURCE => $filename)
       or die "Couldn't make template: $Text::Template::ERROR; aborting";

   But if it makes you happy to do it that way, go ahead.

Sticky Widgets in Template Files
--------------------------------

   The CGI module provides functions for `sticky widgets', which are form
input controls that retain their values from one page to the next.
Sometimes people want to know how to include these widgets into their
template output.

   It's totally straightforward.  Just call the CGI functions from inside
the template:

     { $q->checkbox_group(NAME => 'toppings',
     	  	     LINEBREAK => true,
     		     COLUMNS => 3,
     		     VALUES => \@toppings,
     		    );
     }

Author
------

   Mark-Jason Dominus, Plover Systems

   Please send questions and other remarks about this software to
`mjd-perl-template@pobox.com'

   You can join a very low-volume (<10 messages per year) mailing list for
announcements about this package.  Send an empty note to
`mjd-perl-template-request@plover.com' to join.

   For updates, visit `http://www.plover.com/~mjd/perl/Template/'.

Support?
--------

   This software is version 1.0.  It is a complete rewrite of an older
package, and may have bugs.  Suggestions and bug reports are always
welcome.  Send them to `mjd-perl-template@plover.com'.  (That is my
address, not the address of the mailing list.  The mailing list address is
a secret.)

Thanks
------

   Many thanks to the following people for offering support,
encouragement, advice, and all the other good stuff.

   Klaus Arnhold / Kevin Atteson / Chris.Brezil / Mike Brodhead / Tom
Brown / Tim Bunce / Juan E. Camacho / Joseph Cheek / San Deng / Bob
Dougherty / Dan Franklin / Todd A. Green / Donald L. Greer Jr. /
Michelangelo Grigni / Tom Henry / Matt X. Hunter / Robert M. Ioffe /
Daniel LaLiberte / Reuven M. Lerner / Joel Meulenberg / Jason Moore / Bek
Oberin / Ron Pero / Hans Persson / Jonathan Roy / Shabbir J. Safdar /
Jennifer D. St Clair / Uwe Schneider / Randal L. Schwartz / Michael G
Schwern / Brian C. Shensky / Niklas Skoglund / Tom Snee / Hans Stoop /
Michael J. Suzio / Dennis Taylor / James H. Thompson / Shad Todd / Lorenzo
Valdettaro / Larry Virden / Andy Wardley / Matt Womer / Andrew G Wood /
Michaely Yeung

   Special thanks to:

Jonathan Roy
     for telling me how to do the Safe support (I spent two years worrying
     about it, and then Jonathan pointed out that it was trivial.)

Ranjit Bhatnagar
     for demanding less verbose fragments like they have in ASP, for
     helping me figure out the Right Thing, and, especially, for talking me
     out of adding any new syntax.  These discussions resulted in the
     `$OUT' feature.

Bugs and Caveats
----------------

   my variables in `fill_in' are still susceptible to being clobbered by
template evaluation.  They all begin with `fi_', so avoid those names in
your templates.

   The line number information will be wrong if the template's lines are
not terminated by `"\n"'.  You should let me know if this is a problem.
If you do, I will fix it.

   The default format for reporting of broken program fragments has
changed since version 0.1.

   The `$OUT' variable has a special meaning in templates, so you cannot
use it as if it were a regular variable.

   There are not quite enough tests in the test suite.

A class to handle ISO thesaurii
*******************************

NAME
====

   Text::Thesaurus::ISO - A class to handle ISO thesaurii

SYNOPSIS
========

     use Text::Thesaurus::ISO;

     $thes = new Text::Thesaurus::ISO;
     $thes->open("myisothesfile");
     $thes->reopen("myisothesfile");
     %entry = $thes->terminfo("dumpy");
     @broaderterms = $thes->broader("dumpy");
     @narrowerterms = $thes->narrower("dumpy");
     $dateentered = $thes->dateentered("dumpy");
     $datechanged = $thes->datechanged("dumpy");
     @alternatives = $thes->alternatives("dumpy");
     @sources = $thes->sources("dumpy");
     @links = $thes->links("dumpy");
     @scopenotes = $thes->scopenote("dumpy");
     @historynotes = $thes->history("dumpy");

DESCRIPTION
===========

   This module defines an abstract ROADS Thesaurus object and a number of
methods that operate on these objects.  These methods allow new Thesaurus
objects to be created, specify what Thesaurus file to use, retrieve all
the information from the thesaurus concerning a given term, find broader
terms for a given term and find narrower terms for a given term.

METHODS
=======

new
---

   This creates a new (empty) thesaurus object.

open
----

   Opens an ISO thesaurus file specified by its single parameter.  It also
checks if the backend database exists for this file and if not, creates it.

reopen
------

   Opens an ISO thesaurus file specified by its single parameter.  This
method always reindexes the ISO thesaurus file, and so should be called if
the ISO thesaurus file has been changed since the last time the index was
generated.  Note that this call can be quite time consuming, especially on
a large thesaurus file, so its probably best avoided in interactive
systems (have a batch script that periodically updates the thesaurus
indexes behind the scenes instead).

terminfo
--------

   Takes a term (a word or phrase) and returns all the information for
that term from its thesaurus record.  The information is returned in a
hash array keyed on the attribute name in the ISO thesaurus record (ie BT,
TERM, UF, etc).

broader
-------

   Takes a term and returns a list of all the broader terms for it.

narrower
--------

   Takes a term and returns a list of all the narrower terms for it.

dateentered
-----------

   Takes a thesaurus term as a parameter and returns the date that the
term's record was entered into the thesaurus file.  Returns an undef value
if the term does not exist in the thesaurus file or if there is no entry
date recorded.

datechanged
-----------

   Takes a thesaurus term as a parameter and returns the date that the
term's record was last changed in the thesaurus file.  Returns an undef
value if the term does not exist in the thesaurus file or if there is no
changed date recorded.

alternatives
------------

   Takes a thesaurus term as a parameter and returns an array of
alternative terms based on that.

sources
-------

   Takes a thesaurus term as a parameter and returns an array of source
statements that detail where the term was extracted from.

links
-----

   Takes a thesaurus term as a parameter and returns an array of links to
other terms in the thesaurus.

scopenote
---------

   Takes a thesaurus term as a parameter and returns an array of scope
notes applying to that term.  The scope notes often provide human readable
descriptions of the term and the its limits.

history
-------

   Takes a thesaurus term as a parameter and returns an array of historical
notes.  These are usually human readable comments made when major changes
have been made to the thesaurus that effect the specified term's entry.

BUGS
====

   None known of as yet.  It is intended that more methods will be added
in the future to specifically retreive various parts of the thesaurus
record which will hopefully make the terminfo method obsolete.  Also note
that this version has only been tested against a single ISO thesaurus file
(a demonstration version of the Art and Architecture Thesaurus) - feedback
of bugs with other thesaurii are most welcome.

COPYRIGHT
=========

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   It was developed by the Department of Computer Studies at Loughborough
University of Technology, as part of the ROADS project.  ROADS is funded
under the UK Electronic Libraries Programme (eLib), and the European
Commission Telematics for Research Programme.

AUTHOR
======

   Jon Knight <j.p.knight@lut.ac.uk> Martin Hamilton
<m.t.hamilton@lut.ac.uk>

Templating system perl library
******************************

NAME
====

   Text::Tmpl - Templating system perl library

SYNOPSIS
========

   *use Text::Tmpl;*

   $context    = *new Text::Tmpl*;

   $return     = $context->set_delimiters($opentag,
$closetag);

   $return     = $context->register_simple($name,
$coderef);

   $return     = $context->register_pair($isnamed,
$open_name, $close_name, $coderef);

   $return     = $context->alias_simple($old_name,
$new_name);

   $return     = $context->alias_pair($old_open_name,
$old_close_name, $new_open_name,                  $new_close_name);

   $context->set_debug($to_debug_or_not_to_debug);

   $context->set_strip($to_strip_or_not_to_strip);

   $return     = $context->set_dir($directory);

   $return     = $context->set_value($name, $value);

   $return     = $context->set_values($hashref);

   $subcontext = $context->loop_iteration($loop_name);

   $output     = $context->parse_file($template_filename);

   $output     = $context->parse_string($template);

   $errno      = Text::Tmpl::errno();

   $errstr     = Text::Tmpl::strerror();

DESCRIPTION
===========

Design goals
------------

   simplicity, reusability, speed, complete separation of logic from
formatting.

Feature set
-----------

   variables, loops, conditionals, extensibility of tags, includes,
arbitrary delimiters.

Usage
-----

   For starters, make sure you 'use Text::Tmpl'.

   Each function is described below:

new
     This function initializes the library.  It allocates and returns the
     "global" context structure, and also configures all of the default
     tag behavior.

set_delimiters
     This function lets you change the delimiters marking the beginning
     and end of a tag (by default, these are "<!-#" and "->"), for the
     specified context.

set_value
     This function stores the name=value pair in the current context.

set_values
     This function dumps the name=value pairs from a hash reference into
     the current context.

set_debug
     This function turns debugging output on or off.  Note that debugging
     output hasn't been written yet - this is just a placeholder.

set_strip
     This function enables or disables the newline stripping feature.  If
     enabled, the parser removes a single newline (if present) from after
     any tag.

set_dir
     This function sets the directory where templates will be sought, both
     by parse_file and by the include tag.  Search order is always current
     directory then this searched directory.

loop_iteration
     This function adds an iteration to the loop named loop_name, and
     returns a unique context for that loop iteration.

parse_file
     This function opens $template_filename, and parses the contents of
     that file as a template, returning the output.

parse_string
     This function parses template directly, in the same way that
     Text::Tmpl::parse_file does.

register_simple
     This function registers a new simple tag named $name, which when
     encountered will cause the parser to call $coderef.  See
     template_extend(1) for the gory details.

register_pair
     This function registers a new tag pair $open_name/$close_name, which
     when encountered will cause the parser to call $coderef.  See
     template_extend for the gory details.

alias_simple
     This function copies the definition of a simple tag, previously
     registered as $old_name, to also be called by $new_name.

alias_pair
     This function copies the definition of a tag pair, previously
     registered as $old_open_name/$old_close_name, to also be called by
     $new_open_name/$new_close_name.

errno
     This function returns the error number of the last error - see the
     RETURN VALUES section below.

strerror
     This function returns a string describing the last error - see the
     RETURN VALUES section below.

RETURN VALUES
=============

   All of the above functions which return numeric values will return 0 if
they fail, or 1 otherwise.  The ones which return contexts will return
undef if they fail, or a valid pointer otherwise.

   A function which fails will also set a global error number, which you
can read using the errno() or strerror() package functions.

BUGS
====

   Hopefully none.

AUTHOR
======

   J. David Lowe, dlowe@pootpoot.com

SEE ALSO
========

   libtmpl(1), template_syntax(1), template_extend(1)

Reads a tree of text strings into a data structure
**************************************************

NAME
====

   Text::TreeFile - Reads a tree of text strings into a data structure

SYNOPSIS
========

     use Text::TreeFile;

     # need to set $filename, e.g.:  my $filename='treetest.tre';

     my $treeref=Text::TreeFile->new($filename);
     # or other option: my $treeref=Text::TreeFile->new($filename,'mult');

     die "TreeFile constructor failed to read file $filename\n"
       unless defined $treeref;

     my $topref=$treeref->{top}; # scalar or array for top-level tree(s)
     showlines($topref,0);            # see EXAMPLE, below

REQUIRES
========

   *TreeFile* uses modules:  FileHandle, Exporter and *Autoloader*.

DESCRIPTION
===========

   The `TreeFile.pm' module supports a simple ASCII text file format for
representing tree structures.  It loads the contents of such a file into a
tree (or array of trees) of two-element array nodes, where the first
element of each node is a text string and the second is an array of child
nodes.  It supports comments, continuation lines and include files, and
uses a strict (two-space-per-level) indentation scheme in the file to
indicate hierarchical nesting.

OPTIONS
=======

   TreeFile implements an option between single or multiple top-level
trees per file.  The option is exercised by the presence or absence of a
second argument to new(), as demonstrated in the *"SYNOPSIS"* section,
above (the two lines where "my $treeref=" occurs).

(default case)
     If the new() constructor is not given a second argument, the default
     option occurs: A single top-level tree is read, per file.  This leaves
     the remainder of each file's contents available for some other
     facility to use.  In this case new() returns (a reference to) the
     top-level tree (node).

(optional case)
     If the new() constructor is given a second argument, multiple
     top-level trees are read from each file (and the entire file needs to
     conform to the TreeFile syntax).  In this case new() returns (a
     reference to) an array containing (references to) the top-level trees.

EXAMPLE
=======

     use Text::TreeFile;

     sub showlines;

     # set $filename string and $wantmult boolean
     # my $filename='treetest.tre';
     # my $wantmult=1;   # or:  =0;  # or: omit from new() constructor;

     my $treeref;
     $treeref=Text::TreeFile->new($filename) if not $wantmult;
     $treeref=Text::TreeFile->new($filename,'mult') if $wantmult;
     die "TreeFile constructor returned undef\n" unless defined $treeref;

     my $topref=$treeref->{top}; # node or array of nodes for top-level tree(s)
     showlines($topref,0);

     sub showlines { my ($spec,$level)=@_;
       if(ref($$spec[0]) eq 'ARRAY') { #         want-mult case
         for my $item (@$spec) {
           print('  'x$level);print("$$item[0]\n");
           for(@{$$item[1]}) { showlines $_,$level; } } }
       else { # spec[0] is the top-level string: no-want-mult case
         print('  'x$level);print("$$spec[0]\n");
         for(@{$$spec[1]}) { showlines $_,$level+1; } } }

FILE FORMAT
===========

   The file format supported relies upon indentation of text strings, to
indicate hierarchical nesting for the tree structure.  Strict indentation
(of two space characters per nesting level) is used to represent
parent-child structure.

Comments
--------

   A line consisting exclusively of whitespace, or a line beginning with
either the pound-sign ("#"), the semicolon (";"), or the forward slash
("/") character will be ignored as a comment.  In the very first line of a
file, the initial characters, "exec ", will indicate a comment line.

Continuation Lines
------------------

   A line beginning with whitespace followed by three period (".")
characters, will be concatenated to the previous line, as a continuation.
The preceding end-of-line, the initial whitespace and the ellipsis ("...")
will be removed and otherwise ignored, to allow long strings to be
represented within line-length constraints.

   As a rule, it's probably a good idea to make sure any line that is
continued with a continuation line have no trailing spaces, and that any
spaces that are desired in the resulting concatenation occur between the
ellipsis ("...") and the remainder of the continuation line.  Perhaps a
later version of the module will remove trailing spaces on each line, to
further reduce surprises.

Include Files
-------------

   In addition, any line consisting of indentation followed by "include"
will be interpreted as a file-include request.  In this case, succeeding
whitespace followed by a file specification will cause the contents of the
named file to be substituted at that point in the tree.  The remainder of
the include-file line is ignored as commentary.

AUTHOR
======

   John Kirk <`johnkirk@dystanhays.com'>

COPYRIGHT
=========

   Copyright (c) 2000 John Kirk. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   `Text::TreeFile::details(3pm)' in this node - for precise definition of
syntax,

   `Text::TreeFile::internals(3pm)' in this node - for implementation
commentary,

   and `http://perl.dystanhays.com/jnk' - for related material.

precise usage specifications
****************************

NAME
====

   Text::TreeFile::details - precise usage specifications

SYNOPSIS
========

     use Text::TreeFile;

     my $filename='demodata/treetest.tre';

     # read in single-tree mode
     my $tf=Text::TreeFile->new($filename);

     my $treeref=$$tf{top};

     print "The string content of the top-level tree node is:\n\n";
     print "    $$treeref[0]\n\n";
     print "It has ",scalar @{$$treeref[1]}," second-level child nodes\n";

DESCRIPTION
===========

   First, each public function is described.  Then, a test script.  After
that, a few more details.

CONSTRUCTOR: new [ filename, [ *endq* ] ]
=========================================

   The constructor (function new()) for module *Text::TreeFile* can be
invoked with zero, one or two parameters.  The first is a filename to be
read into an internal tree structure of strings; the second, a
single/multiple tree flag.  If no parameters are specified, an object (a
blessed reference to a hash) will be returned with only the prototype
entries present.  In this case, one might create a tree by other external
means and put it into the hash.

Parameter: filename
-------------------

   If at least one parameter is specified, the first will be taken to be
the name of the tree file to be read.  If it contains a slash ("/")
character, the leading path up to the final file name will be remembered
(under key, "*idir*") and used as a prefix for all include files named in
the course of reading the tree(s).  The filename is remembered under key,
"*iname*" in the blessed hash created.

Parameter: *endq*
-----------------

   If two parameters are specified in the call to new(), the second will
be interpreted as an indicator whether reading the file should stop at the
end of the first full top-level tree.  If present, the string specified in
this parameter is copied into the blessed hash under the key, "*endq*".
This will indicate multiple-tree mode, in which case the entire file will
be read and interpreted as a tree of text strings.  If unspecified, or
specified as undef, the default of single-tree mode will be used for
reading the file.

Single-tree Reading Mode
------------------------

   In the default file reading mode, only a single (the first, if there
are more than one) top-level tree will be read from the file.  The element
of the module's blessed hash with key, "top", will have as value a
reference to this tree (node).  (To access file data following the first
tree in the file, refer to the `internals' in this node documentation
file.)

Multiple-tree Reading Mode
--------------------------

   If the *endq* parameter is specified to new(), the entire file must
conform to proper tree file syntax, and will be read into a data structure
consisting of an array of top-level trees (tree nodes).  In this case the
element of the blessed hash with key, "top", will have as its value a
reference to this array instead of a reference to just a single top-level
tree (node).

FUNCTION: *showlines*
=====================

   *showlines()* is called with a reference to a tree data structure as
its first parameter and, optionally, an initial (integer) level number as
its second parameter.  It recursively prints the contents of the tree.

FUNCTION: *showglobals*
=======================

   *showglobals()* is called with no parameters, and shows the contents of
the blessed hash which is taken to contain global variables.,

TEST SCRIPT: test.pl
====================

   The test.pl script conducts some tests of the module.

EXPORTS
=======

   Nothing is exported by default.  Functions *showlines()* and
*showglobals()* may be imported on request.  The module's new() function
returns a blessed reference to a hash containing a number of data items,
notably one with key, "top" which is the (top node of) the resulting tree
of text strings read from the file.

Key: "top"
----------

   The tree structure of text strings returned by this module is
remembered under the key, "top", in the object hash whose blessed
reference is returned by new().

Nodes
-----

   Each node of the tree of text strings created by this module is an
array of two elements, the first being a text string which is the content
of this node, and the second being a reference to an array of references
to the child nodes of the current node.

EXCEPTIONS
==========

   The new() function will return the undef value if *_loadtree()* returns
false.

   The *_loadtree()* function prints a warning to STDOUT and returns the
undef value if an internal error allows it to be called with no input
filename specified at the top file nesting level.  The module should not
allow this to occur.

   As a separate case, the prior paragraph's description applies, with a
slightly different warning message, below the top file nesting level.

   If a filename is specified, but *_loadtree()* is unsuccessful in
opening the file, a warning is printed to STDOUT and the undef value is
returned.

   If *_readspec()* finds a line without an indent of an exact multiple of
two space characters, it issues a *die()* call with a warning message.

BUGS
====

   The module doesn't use the *Carp(3pm)* module for warnings, calls
*die()* in some exceptional cases, uses "`print STDOUT'" for warnings, and
returns special values in most exceptional cases.  It should use
*Carp(3pm)* to issue warnings and then return special values, for all
exceptions.

implementation details
**********************

NAME
====

   Text::TreeFiles::internals - implementation details

SYNOPSIS
========

     use Text::TreeFile;

     sub _loadtree;
     sub _readspec;

DESCRIPTION
===========

     (Nothing written, yet.)

Name
====

   Text::Trie

Usage
-----

     use Text::Trie qw(Trie walkTrie);
     @trie = Trie 'abc', 'ab', 'ad';
     walkTrie sub {print("[",shift,"]")}, sub {print(shift)}, sub {print "->"},
       sub {print ","}, sub {print "("}, sub {print ")"}, @trie;

`Trie'
     Given list of strings returns an array that consists of common heads
     and tails of strings. Element of an array is a string or an array
     reference. Each element corresponds to a group of arguments.

     Arguments are split into groups according to the first letter. If
     group consists of one element, it results in the string element in
     the output array. If group consists of several elements, then the
     corresponding element of output array looks like

          [$head, ...]

     where $head is the common head of the group, the rest is the result of
     recursive application of `Trie' to tails of elements of the group.

`walkTrie'
     Takes 6 references to subroutines and an array as arguments. Array is
     interpreted as output of `Trie', the routine walks over the tree
     depth-first. If element of the array is a reference to array, it is
     interpreted as a node, and the `walkTrie' is applied to the
     corresponding array (without the first element) recursively.
     Otherwise the element is interpreted as a leaf of the tree.

     Subroutines are executed when (in the order of arguments of
     `walkTrie'):

        * a leaf of the tree is met, argument is the corresponding element
          of array;

        * a node is met, argument is the first element of the
          corresponding array;

        * a node that is not-empty is met, argument is the reference to the
          corresponding array; is called after the previous one;

        * between two sibling nodes or leafs, argument is the next node or
          leaf;

        * before executing any other code for a node, argument is the node;

        * after executing any other code for a node, argument is the node;

     Any one of the first six arguments can be undef instead of being a
     reference to a subroutine.

Exports
-------

   None by default, `Trie' and `walkTrie' are @EXPORTABLE.

Configuration
-------------

   Variable $Text::Trie::step can be set to a value bigger than 1 to set
the length of smallest units arguments can be broken into.

AUTHOR
======

   Contact Ilya Zakharevich, *ilya@math.ohio-state.edu*.

Remove accents from a string
****************************

NAME
====

   Text::Unaccent - Remove accents from a string

SYNOPSIS
========

     use Text::Unaccent;

     $unaccented = unac_string($charset, $string);
     $unaccented = unac_string_utf16($string);

DESCRIPTION
===========

   Text::Unaccent is a module that remove accents from a string.
`unac_string' converts the input string from the specified  charset to
UTF-16 and call `unac_string_utf16' to return the unaccented equivalent.
The conversion from  and to  UTF-16  is  done  with iconv(1).

METHODS
=======

$unaccented = unac_string($charset, $string)
     Return the unaccented equivalent of the  string $string. The
     character set of $string is specified by the $charset argument. The
     returned string is coded using the same character set. Valid values
     for the $charset argument are character sets known by iconv(1). Under
     GNU/Linux try `iconv --list' for a complete list.

$unaccented = unac_string_utf16($string)
     Return the unaccented equivalent of the  string $string. The
     character set of $string must be UTF-16.

AUTHOR
======

   Loic Dachary (loic@senga.org) http://www.sourceforge.net/projects/unac/

SEE ALSO
========

   iconv(1).

Perl extension for a versatile text pre-processor
*************************************************

NAME
====

   Text::Vpp - Perl extension for a versatile text pre-processor

SYNOPSIS
========

     use Text::Vpp ;

     $fin = Text::Vpp-> new('input_file_name') ;

     $fin->setVar('one_variable_name' => 'value_one',
                  'another_variable_name' => 'value_two') ;

     $res = $fin -> substitute ; # or directly $fin -> substitute('file_out')

     die "Vpp error ",$fin->getErrors,"\n" unless $res ;

     $fout = $fin->getText ;

     print "Result is : \n\n",join("\n",@$fout) ,"\n";

DESCRIPTION
===========

   This class enables to preprocess a file a bit like cpp.

   First you create a Vpp object passing the name of the file to process,
then you call setvar() to set the variables you need.

   Finally you call substitute on the Vpp object.

NON-DESCRIPTION
===============

   Note that it's not designed to replace the well known cpp. Note also
that if you think of using it to pre-process a perl script, you're likely
to shoot yourself in the foot. Perl has a lot of built-in mechanisms so
that a pre-processor is not necessary for most cases.

   On the other hand some advanced perl users do use Vpp to pre-process
their code to gain speed. But in this case you should really think hard
about the maintenance of your code. Adding Vpp syntax in your code will
make it more difficult to maintain. Even more so if the code maintainer
will not be yourself. Furthermore, the build procedure may also be more
complex.  So please, do consider the trade-off between speed and
complexity.

INPUT FILE SYNTAX
=================

Comments
--------

   All lines beginning with '#' are skipped. (May be changed with
setCommentChar())

   When setActionChar() is called with '#' as a parameter, Vpp doesn't
skip lines beginning with '#'. In this case, there's no comment possible.

in-line eval
------------

   Lines beginning with '@EVAL' (@ being pompously named the 'action char')
are evaluated as small perl script.  If a line contains (multiple) @@
Perl-Expression @@ constructs these are replaced by the value of that
Perl-Expression.  You can access all (non-lexically scoped) variables and
subroutines from any Perl package iff you use fully qualified names, i.e.
for a subroutine foo in package main  use  *::foo* or *main::foo* To call
one of the methods of a Vpp-object, like setActionChar, this has to called
as  "${self}->setActionChar('@');" Be sure you know what you do, if you
call such methods from within an @EVAL line.

Multi-line input
----------------

   Lines ending with \ are concatenated with the following line.

Variables substitution
----------------------

   You can specify variables in your text beginning with $ (like in perl,
but may be changed with setPrefixChar() ) and optionally ending in a
Suffix which can be specified by setSuffixChar().  These variables can be
set either by the setVar() method, the setVarFromFile() method or by the
'eval' capability of Vpp (See below).

Advanced variables substitution
-------------------------------

   To use more complicated variables like hash or array accesses you have
to use either the 'in-line eval' above or a cheaper and more convenient
method. For that you can 'QUOTE' lines like

     @QUOTE
     any lines
     @ENDQUOTE

   or

     @QUOTE ( ListPrefix [,ListSeparator] )
     any lines
     @ENDQUOTE

   In both cases the lines between the '@QUOTE' and '@ENDQUOTE' are
concatenated while keeping the end-of-line character.

   In the resulting string all '$' are protected unless $prefix or $suffix
or $ListPrefix contains a '$'. Furthermore all '@' are protected unless
one of these variables contains a '@'.

   Then all variables (defined by $prefix/$suffix) are preprocessed to
make them ready for substitution later on.  Likewise $ListPrefix (if
given) is converted to '@'.

   Then this possible multiline construct is quoted by Perl's 'qq' and
given to Perl's eval.

   Therefore any constructs which interpolate in a double quoted string,
will interpolate here too, i.e. variable starting with '$' or '@' (unless
protected, see above) and all characters escaped by '\'.

   Note the standard trick to interpolate everything within a double
quoted string by using the anonymous array construct " @{[expression]} ".
The $ListSeparator is used to locally set Perl's variable '$"' (or
$LIST_SEPARATOR in module English.pm).  You can take any delimiting
character but not brackets of any sort to delimit either ListPrefix or
ListSeparator .

   Note that this feature which raised a lot of discussions between the
Vpp contributors should be considered as 'alpha' stage. We may have
simpler ideas in the future to implement the same functionnality (hint:
all other ideas are welcome). So the interface or the feature itself may
be changed. Contact Helmut for further discussions.

Output generation by Perl code
------------------------------

   For complex generation of output one can specify one or more Perl
subroutines which can be called from within an @EVAL statement.  To
specify the Perl code you say

     @PERL  <<  Termination_Regexp
     any perl source lines not matching 'Termination_Regexp'
     termination line matching 'Termination_Regexp'

   Note, that any output *have to* use the predefined Perl sub `Vpp_Out'.
Note, that the subroutine names should be unique even across included
files.  To access the variables set by e.g. setVar, you *have to* use the
predefined hash-ref `$VAR'.  Here is an example which generates constants
for a C-program which amount to the probability that you draw a specified
sequence out of a set.

     @PERL << ^END_OF_PERL$
     sub Chances($$) {
       my ($nseq,$num) = @_;
       # compute the chance to draw a sequence of nseq specific balls
       # out of num balls.
       my $chance;
       if ( $nseq > $num ) {
         $chance= 0;
       } else {
         $chance= 1;
         for (my $k=1; $k <= $nseq; $k++) {
           $chance*= $k/($num-$k);
         }
       }
       Vpp_Out("const double chance_${nseq}_of_$num = $chance;");
     }
     END_OF_PERL

   This produces no output by itself. Lateron you can use it as

     @EVAL &Chances(7,49)

   to produce the C-statement

     const double chance_7_of_49 = 1.35815917929809e-08;

Setting variables
-----------------

   Lines beginning by @ are 'evaled' using variables defined by setVar()
or setVarFromFile(). You can use only scalar variables. This way, you can
also define variables in your text which can be used later.

Conditional statements
----------------------

   Text::Vpp understands @IF, @ELSIF, @ENDIF,and so on.  @INCLUDE and @IF
can be nested.

   @IF and @ELSIF are followed by a Perl expression which will be evaled
using the variables you have defined (either with setVar(),
setVarFromFile() or in an @EVAL line).

Loop statements
---------------

   Text::Vpp also understands

   @FOREACH $MyLoopVar ( Perl-List-Expression ) ... (any) lines which may
depend on $MyLoopVar  @ENDFOR

   These loops may be nested.

Inclusion
---------

   Text::Vpp understands  @INCLUDE  Filename or Perl-Expression  @INCLUDE
{ action => '\\', backslash => 0, file => 'add_on.001' }

   The file name may be a bare words if it contains only alphanumeric
characters or '-', '.' or '_'. Otherwise, the file name must be quoted.

   If the Perl-Expression is a string, it is taken as a filename.

   If it is an anonymous hash, it must have a value for the key 'file' and
it may have values for 'action', 'comment', 'prefix', 'suffix',
'substitute' and 'backslash'.  If given these values will override the
current values during the processing of the included file.

Constructor
===========

new(file, optional_var_hash_ref, ...)
-------------------------------------

   The constructor call `new(file,
optional_var_hash_ref,optional_action_char,' `
optional_comment_char, optional_prefix_char,' `
optional_suffix_char, optional_substitute,' `
optional_backslash_switch);'

   creates the Vpp object. The file parameter may be a filename or a
blessed reference for an object which "can('getline')".  The second
parameter can be a hash containing all variables needed for the substitute
method, the following (optional) parameters specify the corresponding
special characters.

Methods
=======

substitute([output_file])
-------------------------

   Perform the substitute, inclusion, and so on and write the result in
*output_file*. This maybe a filename or a blessed reference which
"can('print')" .  Returns 1 on completion, 0 in case of an error.

   If output_file is not specified this function stores the substitution
result in an internal variable. The result can be retrieved with getText()

     You may prefix the filename with >> to get the output
     appended to an existing file.

rewind()
--------

   If method 'substitute' is called more than once, you have to call
'rewind' in between.  CAUTION  If you have called method 'new' with a
blessed reference          instead of a filename, you must not call
'rewind' unless          your object has a 'seek' method. Otherwise you
have to do          actions yourself which simulate 'rewind' for your
object.

getText()
---------

     Returns an array ref containing the result. You can then get the total
     file with  join "\n",@{VppObj->getText}

getErrors()
-----------

   Returns an array ref containing the errors.

setVar( key1=> value1, key2 => value2 ,...) or setVar(hash_ref)
---------------------------------------------------------------

   Declare variables for the substitute.  Note that calling this function
clobbers previously stored values.

setVarFromFile( Filename_or_Ref )
---------------------------------

   Declares a File or an object which can 'getline'.  The file must
contain a valid Perl expression yielding an anonymous hash, as created
e.g. by Data::Dumper Note that calling this function clobbers previously
stored values.

setActionChar(char)
-------------------

   Enables the user to use different char as action char. (default @)

   Example: setActionChar('#') will enable Vpp to understand #include,
#ifdef ..

setCommentChar(char)
--------------------

   Enables the user to use different char as comment char. (default #)
This value may be set to undef so that no comments are possible.

setPrefixChar(char)
-------------------

   Enables the user to use different char(s) as prefix char(s), i.e.
variables in your text (only) are prefixed by that character(s) instead of
the default '$'. If no suffix character(s) has been defined (or set to
'undef') variables may be specified in the form ${variable} where '$' is
the current prefix char(s). This form is necessary, if any character which
is allowed within a name (regexp '\w') immediately follows the variable.
Note, that all variables in 'actions' (like @@ @EVAL @FOREACH @IF) must
still be prefixed by '$'.

setSuffixChar(char)
-------------------

   Enables the user to use different char(s) as suffix char(s), i.e.
variables in your text (only) are suffixed by that character(s).  Note,
that all variables in 'actions' (like @@ @EVAL @FOREACH @IF) don't use
this.

setSubstitute([prefix,suffix])
------------------------------

   Enables the user to specify the prefix and suffix used to mark a Perl
expression within the text that will be replaced by its value. The default
value is twice the 'action' char as suffix and prefix.

ignoreBackslash()
-----------------

   By default, line ending with '\' are glued to the following line (like
in ksh). Once this method is called '\' will be left as is.

CAVEATS
=======

   Version 1.0 now requires files included with '@INCLUDE' to be quoted.
Version 1.1 now requires calls to method 'rewind' if 'substitute' is
called more than once for the same Vpp-object.

AUTHOR
======

   Dominique Dumont    Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1996-2000 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

   Additional bugs have been introduced by Helmut Jarausch
jarausch@igpm.rwth-aachen.de

SEE ALSO
========

   perl(1),Text::Template(3).

line wrapping to form simple paragraphs
***************************************

NAME
====

   Text::Wrap - line wrapping to form simple paragraphs

SYNOPSIS
========

     use Text::Wrap

     print wrap($initial_tab, $subsequent_tab, @text);
     print fill($initial_tab, $subsequent_tab, @text);

     use Text::Wrap qw(wrap $columns $huge);

     $columns = 132;
     $huge = 'die';
     $huge = 'wrap';

DESCRIPTION
===========

   Text::Wrap::wrap() is a very simple paragraph formatter.  It formats a
single paragraph at a time by breaking lines at word boundaries.
Indentation is controlled for the first line ($initial_tab) and all
subsequent lines ($subsequent_tab) independently.

   Lines are wrapped at $Text::Wrap::columns columns.
$Text::Wrap::columns should be set to the full width of your output device.

   When words that are longer than $columns are encountered, they are
broken up.  Previous versions of wrap() die()ed instead.  To restore the
old (dying) behavior, set $Text::Wrap::huge to 'die'.

   Text::Wrap::fill() is a simple multi-paragraph formatter.  It formats
each paragraph separately and then joins them together when it's done.  It
will destroy any whitespace in the original text.  It breaks text into
paragraphs by looking for whitespace after a newline.  In other respects
it acts like wrap().

EXAMPLE
=======

     print wrap("\t","","This is a bit of text that forms
     	a normal book-style paragraph");

AUTHOR
======

   David Muir Sharnoff <muir@idiom.com> with help from Tim Pierce and many
many others.

proportional line wrapping to form simple paragraphs
****************************************************

NAME
====

   Text::WrapProp - proportional line wrapping to form simple paragraphs

SYNOPSIS
========

     use Text::WrapProp

     print wrap_prop($text, $width, $ref_width_table);

     use Text::WrapProp qw(wrap_prop);

DESCRIPTION
===========

   Text::WrapProp::wrap_prop() is a very simple paragraph formatter for
proportional text. It formats a single paragraph at a time by breaking
lines at word boundries.  You must supply the column width in floating
point units which should be set to the full width of your output device. A
reference to a character width table must also be supplied. The width units
can be any metric you choose, as long as the column width and the width
table use the same metric.

   Proportional wrapping is most commonly used in the publishing industry.
In the HTML age, custom proportional wrapping is less often performed as
the browser performs the calculations automatically.

EXAMPLE
=======

     my @width_table = (0.05) x 256;
     print wrap_prop("This is a bit of text that forms a normal book-style paragraph. Supercajafrajalisticexpialadocious!", 4.00, \@width_table);

BUGS
====

   It's not clear what the correct behavior should be when WrapProp() is
presented with a word that is longer than a line.  The previous behavior
was to die.  Now the word is split at line-length.

AUTHOR
======

   James Briggs <71022.3700@compuserve.com>, styled after Text::Wrap.

Simple word wrapping routine
****************************

NAME
====

   Text::Wrapper - Simple word wrapping routine

SYNOPSIS
========

     require Text::Wrapper;
     $wrapper = Text::Wrapper->new(columns => 60, body_start => '    ');
     print $wrapper->wrap($text);

DESCRIPTION
===========

   *Text::Wrapper* provides simple word wrapping.  It breaks long lines,
but does not alter spacing or remove existing line breaks.  If you're
looking for more sophisticated text formatting, try the *Text::Format*
module.

   Reasons to use *Text::Wrapper* instead of *Text::Format*:

   * *Text::Wrapper* is significantly smaller.

   * It does not alter existing whitespace or combine short lines.  It
     only breaks long lines.

   Again, if *Text::Wrapper* doesn't meet your needs, try *Text::Format*.

Methods
-------

$wrapper = Text::Wrapper->new( [options] )
     Constructs a new *Text::Wrapper* object.  The options are specified
     by key and value.  The keys are:

          body_start  The text that begins the second and following lines of
                      a paragraph.  (Default '')

          columns     The number of columns to use.  This includes any text
                      in body_start or par_start.  (Default 70)

          par_start   The text that begins the first line of each paragraph.
                      (Default '')

$wrapper->body_start( [$value] )
$wrapper->columns( [$value] )
$wrapper->par_start( [$value] )
     If $value is supplied, sets the option and returns the previous value.
     If omitted, just returns the current value.

$wrapper->wrap($text)
     Returns a word wrapped copy of $text.  The original is not altered.

BUGS
====

   Does not handle tabs (they're treated just like spaces).

   Does not break words that can't fit on one line.

AUTHOR
======

   Christopher J. Madsen <`chris_madsen@geocities.com'>

Templating system C library
***************************

NAME
====

   libtmpl - Templating system C library

SYNOPSIS
========

   *#include "template.h"*

   context_p template_init(void)

   int template_set_delimiters(context_p ctx,    char *opentag, char
*closetag)

   int template_register_simple(context_p ctx, char *name,    void
(*function)(context_p, char **, int, char**))

   int template_register_pair(context_p ctx,    char named_context, char
*open_name, char *close_name,    void (*function)(context_p, int, char**))

   int template_alias_simple(context_p ctx, char *old_name,    char
*new_name)

   int template_alias_pair(context_p ctx,    char *old_open_name, char
*old_close_name,    char *new_open_name, char *new_close_name)

   int template_set_value(context_p ctx, char *name,    char *value)

   void template_set_debug(context_p ctx, int debug)

   void template_set_strip(context_p ctx, int strip)

   int template_set_dir(context_p ctx, char *directory)

   void template_destroy(context_p ctx)

   context_p template_loop_iteration(context_p ctx,    char *loop_name)

   int template_parse_file(context_p ctx,    char *template_filename, char
**output)

   int template_parse_string(context_p ctx, char *template,    char
**output)

   extern int template_errno

   char * template_strerror(void)

DESCRIPTION
===========

Design goals
------------

   simplicity, reusability, speed, complete separation of logic from
formatting.

Feature set
-----------

   variables, loops, conditionals, extensibility of tags, includes,
arbitrary delimiters.

Usage
-----

   For starters, make sure you #include "template.h" and link against
libtmpl.a.

   Each function is described below:

template_init
     This function initializes the library.  It allocates and returns the
     "global" context structure, and also configures all of the default
     tag behavior.

     template_init() can fail with TMPL_EMALLOC.

template_set_delimiters
     This function lets you change the delimiters marking the beginning
     and end of a tag (by default, these are "<!-#" and "->" in the given
     context.

     template_set_delimiters() can fail with TMPL_ENULLARG.

template_set_value
     This function stores the name=value pair in the current context.

     template_set_value() can fail with TMPL_ENULLARG.

template_set_debug
     This function turns debugging output on or off.  Note that debugging
     output hasn't been written yet - this is just a placeholder.

template_set_strip
     This function enables or disables the newline stripping feature.  If
     enabled, the parser removes a single newline (if present) from after
     any tag.

template_set_dir
     This function sets the directory where templates will be sought, both
     by parse_file and by the include tag.  Search order is always current
     directory then this searched directory.

     template_set_dir() can fail with TMPL_ENULLARG.

template_loop_iteration
     This function adds an iteration to the loop named loop_name, and
     returns a unique context for that loop iteration.

     template_loop_iteration() can fail with TMPL_ENULLARG, TMPL_EMALLOC.

template_parse_file
     This function opens template_filename, and parses the contents of
     that file as a template, placing the output into *output.  It
     allocates all the memory for you, but it is up to the programmer to
     free *output!

     template_parse_file() can fail with TMPL_ENULLARG, TMPL_ENOTFOUND,
     TMPL_EFOPEN, TMPL_EMALLOC or TMPL_EPARSE.

template_parse_string
     This function parses template directly, in the same way that
     template_parse_file does.

     template_parse_string() can fail with TMPL_ENULLARG, TMPL_EMALLOC or
     TMPL_EPARSE.

template_register_simple
     This function registers a new simple tag named name, which when
     encountered will cause the parser to call function.  See
     template_extend(1) for the gory details.

     template_register_simple() can fail with TMPL_ENULLARG, TMPL_EMALLOC.

template_register_pair
     This function registers a new tag pair open_name/close_name, which
     when encountered will cause the parser to call function.  See
     template_extend for the gory details.

     template_register_pair() can fail with TMPL_ENULLARG, TMPL_EMALLOC.

template_alias_simple
     This function copies the definition of a simple tag, previously
     registered as old_name, to also be called by new_name.

     template_alias_simple() can fail with TMPL_ENULLARG, TMPL_EMALLOC.

template_alias_pair
     This function copies the definition of a tag pair, previously
     registered as old_open_name/old_close_name, to also be called by
     new_open_name/new_close_name.

     template_alias_pair() can fail with TMPL_ENULLARG, TMPL_EMALLOC.

template_destroy
     This function blows away all of the memory allocated within the given
     context.  You should really *only* call this on the context returned
     by template_init, and only at the end of your code.

template_errno
     This is a global variable containing the error number of the last
     error - see the RETURN VALUES section below.

template_strerror
     This function returns a string describing the last error - see the
     RETURN VALUES section below.

RETURN VALUES
=============

   All of the above functions which return int values will return 0 if
they fail, or 1 otherwise.  The ones which return context_p pointers will
return NULL if they fail, or a valid pointer otherwise.

   A function which fails will also set a global error number, which you
can read or use template_strerror() to describe.

BUGS
====

   Hopefully none.

AUTHOR
======

   J. David Lowe, dlowe@pootpoot.com

SEE ALSO
========

   Text::Tmpl(1), template_syntax(1), template_extend(1)

how to extend the Text::Tmpl template library (with C or Perl).
***************************************************************

NAME
====

   template_extend - how to extend the Text::Tmpl template library (with C
or Perl).

SYNOPSIS
========

   Perl:

     $context->register_simple("name", \&simple_handler);
     sub simple_handler {
         my($context, $name, @args) = @_;
         # do stuff to build a return string
         return "result string!";
     }

     $context->register_pair($is_named, "open", "close",
                             \&pair_handler);
     sub pair_handler {
         my($context, $name, @args) = @_;
         # do stuff to the context
         return;
     }

     $subctx  = Text::Tmpl::context_get_anonymous_child($ctx);
     $subctx  = Text::Tmpl::context_get_named_child($ctx, $name);
     $peerctx = Text::Tmpl::context_add_peer($ctx);
     $return  = Text::Tmpl::context_set_named_child($ctx, $name);
     Text::Tmpl::context_output_contents($ctx, $output);

   C:

     int template_register_simple(context_p ctx, char *name,
        void (*function)(context_p, char **, int, char**))
     void
     simple_handler(context_p ctx, char **output, int argc, char **argv) {
         char *returnstring;
         /* do stuff to build a return string */
         *output = (char *)calloc(1, strlen(returnstring));
         strncpy(*output, returnstring, strlen(returnstring));
         return;
     }

     int template_register_pair(context_p ctx, char named_context,
        char *open_name, char *close_name,
        void (*function)(context_p, int, char**))
     void
     pair_handler(context_p ctx, int argc, char **argv) {
         /* do stuff to the context */
         return;
     }

     context_p context_get_anonymous_child(context_p ctx);
     context_p context_get_named_child(context_p ctx, char *name);
     int       context_set_named_child(context_p ctx, char *name);
     context_p context_add_peer(context_p ctx);
     void      context_output_contents(context_p ctx, char output_contents);

DESCRIPTION
===========

   Creating new tags in this templating system is pretty easy, despite the
somewhat daunting API.  The perl and C APIs are virtually identical in
both usage and effects, so I'm going to be discussing the process in a
(hopefully) language independent way.

   Note that tags are global in scope - a tag can be registered at any
point before the parsing stage and will be visible to the entire template.
This may change in future versions, if there seems to be a demand for
scoped tags.

Tag Argument Passing
--------------------

   Arguments to any tag are passed into the tag function as an argc/argv
pair in the C API, or a list in the Perl API.  Either way, element 0 of the
argument list will be the tag name, so the first argument is actually
element 1.

Simple Tags
-----------

   Simple tags are lone tags which generate a string for inclusion in the
parsed output.  A perl simple tag function simply returns a string,
whereas a C simple tag function has to allocate a new string (which the
caller will free() after use.)

   The echo tag function in C looks like:

     void
     simple_tag_echo(context_p ctx, char **output, int argc, char **argv)
     {
         int size;

     if (argc < 1)
     {
         *output = NULL;
         return;
     }

     size = strlen(argv[1]);
     *output = (char *)calloc(1, size + 1);
     strncpy(*output, argv[1], size);
     (*output)[size] = '\0';

     return;
      }

   This illustrates a couple of things: errors from simple tags should be
indicated by making *output a NULL pointer, and don't forget to
null-terminate *output.

   In perl, you would duplicate this by:

     sub simple_tag_echo
     {
         my $context = shift || return undef;
         my $name    = shift || return undef;
         my $string  = shift || return undef;

     return $string;
      }

   It should also be pointed out that all of the argument parsing,
including variable interpolation, has already happened by this point.

   Simple tags are called with the context in which they are found.  They
can make changes to the context, but the results may be unexpected - for
example, attempting to disable the output of the entire surrounding
context will not work.

   The output string from a single tag will (if not NULL) be run through
the parser.  This means that a simple tag can output a template fragment.
So, for example, if you wanted to implement an "else" tag, you could:

     sub simple_tag_else
     {
         my $context = shift || return undef;
         my $name    = shift || return undef;

     return "<!--#endif--><!--#ifn-->";
      }

Tag Pairs
---------

   Tag pairs are more complicated.  As the name implies, tag pairs have a
beginning and an end, denoted by two distinct tags.  When a beginning tag
is found, the parser scans forward to find the matching closing tag, and
then parses everything in between in the context of the tag function.

   There are two kinds of tag pairs - those with named contexts, and those
with anonymous contexts.  A named context is used for tag pairs which
allow the programmer to pre-build some (or all) of the context structure
before parsing takes place, such as the loop tag.  An anonymous context is
used when the context is constructed completely at parse time, such as the
comment tag.  The actual name of the context, in a named context tag pair,
is the first argument to the opening tag (for example <!-#loop "foo"->
retrieves the named context "foo" from the parent context).

   The tag function is called before parsing of the context begins, so it
gets to completely set up the context beforehand.  So the comment tag, for
example, simply disables output of the context:

     void
     tag_pair_comment(context_p ctx, int argc, char **argv)
     {
         context_output_contents(ctx, 0);
         return;
     }

   The contents of the context are never even parsed, since the parser
knows that it won't be output.

The context_* functions
-----------------------

   This group of functions is used to manipulate context structures in
ways the main template API doesn't allow.  Before we dive into it, some
understanding of the context structure will be required.

   Contexts are quite simple, really.  They contain a list of variables
and a flag which determines whether the contents of the context should be
output.  Each context can also know about a number of other contexts
internally: its parent, its peer(s) - each peer representing a loop
iteration - and its named children.  A context may have zero or more of
each of these.  For example, the initial context returned from
template_init has no parent, no peers and no named children initially.  If
you call template_loop_iteration, the main context will gain a single
named child context, which in turn will have the main context as a parent,
no peers (yet) and no named children.  If you call template_loop_iteration
on the main context with the same name again, the named child will gain a
peer context.  And so on, and so forth...

   In summary: the parent context provides nested scopes, peers represent
iterations over the same chunk of the template, and named children are
contexts which can be fetched by name both at preparation time and parse
time.

context_get_anonymous_child
     Creates and returns an unnamed context with the parent set to the
     current context (i.e. a new context within the scope of the current
     context).

context_get_named_child
     This function returns a named context within the scope of the current
     context, if it exists.

context_set_named_child
     This function creates a new named context within the scope of the
     current context.

context_add_peer
     This function adds a peer context to the context passed in, and
     initializes it.

context_output_contents
     This function sets the output_contents flag in the current context.

RETURN VALUES
=============

   Functions which return context_p pointers will return NULL if there is
any problem at all.  Functions which return integers return 0 on failure
and 1 on success.

BUGS
====

   Hopefully none.

AUTHOR
======

   J. David Lowe, dlowe@pootpoot.com

SEE ALSO
========

   libtmpl(1), Text::Tmpl(1), template_syntax(1)

description of the syntax of a Text::Tmpl template.
***************************************************

NAME
====

   template_syntax - description of the syntax of a Text::Tmpl template.

SYNOPSIS
========

   In general:

   <!-#function "argument1", $argument2, "argu" $ment
"3"-><!-#endfunction->

   Specifically:

   <!-#echo "text"->

   <!-#include "file"->

   <!-#comment->This won't be printed<!-#endcomment->

   <!-#if "value"->This will be printed if "value" is "true"<!-#endif->

   <!-#ifn "value"->This will be printed if "value" is "false"<!-#endifn->

   <!-#loop "loopname"->This may be printed a bunch of times<!-#endloop->

   <!-#debug-><!-#include "debug-include.tmpl"-><!-#enddebug->

   debug-include.tmpl:

   Variables in this context: <!-#loop "variables-" $number->

   <!-#echo $variable_name-> == <!-#echo $variable_value->

   <!-#endloop->

   Named children (loops) in this context: <!-#loop "named_children-"
$number->

   <!-#loop $nc_name-> <!-#echo $nc_name->: <!-#include
"debug-include.tmpl"-> <!-#endloop->

   <!-#endloop->

DESCRIPTION
===========

   The specific tags listed above are merely the default tags in the
template library.  It is possible to add tags of your own.

   The tag format is: open_tag_delimiter (default: "<!-#") + function name
+ some whitespace + comma-separated argument list (described below) +
close_tag_delimiter (default: "->").

   Each argument in the comma-separated argument list consists of variables
and strings - everything else is ignored.  A variable looks like $foo,
where foo is any number of alphanumeric characters.  A string is anything
(including whitespace, newlines, etc...) within double-quotes.  To put
literal double quotes into a string, escape with a backslash.  For
example, the following list:

   "argument1", $argument2, "argu" $ment "3"

   would become:

   argument1, (the value of $argument2), argu(the value of $ment)3

   Tag pair nesting is possible (and infinite, at least if you have an
infinite stack...)  Also, the result of a simple tag evaluation will
actually be parsed again, so you can (for example) include another
template into the current one, and it will be parsed.

echo
     The echo tag is replaced by the concatenated string values of each of
     its arguments.

include
     The include tag is replaced by the contents of the named file.

comment / *endcomment*
     The comment/endcomment tag pair, and everything it contains, is
     replaced by nothing.

if / *endif*
     The if/endif tag pair, and everything it contains, is replaced by
     nothing or by the complete contents of the tag pair, depending on the
     "truth" of the first argument to the tag.  If the argument is true,
     the complete contents of the tag pair are output - otherwise, nothing
     is output.

ifn / *endifn*
     The ifn/endifn tag pair, and everything it contains, is replaced by
     nothing or by the complete contents of the tag pair, depending on the
     "truth" of the first argument to the tag.  If the argument is false,
     the complete contents of the tag pair are output - otherwise, nothing
     is output.

loop / *endloop*
     The loop/endloop tag pair is replaced by everything it contains,
     repeated 0 or more times.  The first argument to the loop tag is the
     name of the loop, and the number of repetitions is equal to the
     number of times that loop_iteration() was called in the current
     context with that loop name as an argument.

debug / *enddebug*
     The debug/enddebug tag pair is replaced by everything it contains.
     This pair also dumps all of the information about the parent context
     into this sub-context, so that you can see the internal state of the
     context as output.  The format for using the debug/enddebug tag pair
     is shown in the SYNOPSIS above.

BUGS
====

   Hopefully none.

AUTHOR
======

   J. David Lowe, dlowe@pootpoot.com

SEE ALSO
========

   libtmpl(1), Text::Tmpl(1), template_extend(1)

David Rolsky (grimes@waste.org)
*******************************

NAME
====

   Thesaurus - David Rolsky (grimes@waste.org)

SYNOPSIS
========

     use Thesaurus;

     $th = new Thesaurus( -files => ['file1', 'file2'],
     		      -ignore_case => 1 );

     @words = $th->find('vegan');

     %words = $th->find('animal', 'liberation');

     foreach $word ( @{ $words{animal} } )
     {
         #something ...
     }

     $th->add_file('file1', 'file2');

     $th->add('tofu', 'alternative methodologies');

     $th->delete('meat', 'vivisection');

DESCRIPTION
===========

   Thesaurus is a module that allows you to create lists of related
things.  It was created in order to facilitate searches of a database of
Chinese names in Anglicized form.  Because there are various schemes to
create phonetic representations of Chinese words, the following can all
represent the same Chinese character:

     Woo
     Wu
     Ng

   Thesaurus can be used for anything that fits into a scalar by using the
new method with no parameters and then calling the add method to add data.

   Thesaurus also acts as the parent class to several child classes which
implement various forms of persistence for the data structure.  This
module can be used on its own to instantiate an object that lives for the
life of its scope.

METHODS
=======

   * new(%params)
          $th = Thesaurus->new(%params);

     The new method returns a Thesaurus object.

     Parameters:

   * ignore_case (0 or 1) - A boolean parameter.  If true, then the object
     will be case insensitive.  It is _always_ case-preservative for its
     data.

   * find(@items);
          @words = $th->find('Big Hat');
          %words = $th->find('Big Hat', 'Faye Wong');

     The find method returns either a list or a hash, depending on
     context.  Given a single word to find, it returns the list of words
     that it is associated with, including the word that was given.  If no
     matches  are found then it returns an empty list.

     If it is given multiple words, it returns a hash.  The keys of the has
     are the words given, and the keys are list references containing the
     associated words.  If no words were found then the key has a value of
     0.  If none of the words match then an empty list is returned.

   * add(\@list1, \@list2)
          $th->add(\@related1, \@related2);

     The add method takes a list of list references.  Each of these
     references should contain a set of associated scalars.  Like the add
     files method, if an entry in the files matches an entry already in
     the object, then it is appended to the existing list, otherwise a new
     entry is created.

   * delete(@items)
          $th->delete($element);

     The delete method takes a list of items to delete.  All the
     associations for the given items will be removed.

   * dump
          @list_refs = $th->dump;

     Returns a list of list references.  Each one of these list references
     contains one set of associations.  Each association list is returned
     once (not once per item).

AUTHOR
======

   Dave Rolsky, <autarch@urth.org>

SEE ALSO
========

   Thesaurus::File, Thesaurus::DBM, Thesaurus::DBI

COPYRIGHT
=========

   Copyright (c) 1999 David Rolsky. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Subclass of Thesaurus that creates data structure in a database.
****************************************************************

NAME
====

   Thesaurus::DBI - Subclass of Thesaurus that creates data structure in a
database.

SYNOPSIS
========

     use Thesaurus::DBI;

     my $thesaurus = Thesaurus::DBI( ignore_case => 1,
                                     configuration => 'myconfig',
                                     dbh => $dbh );

DESCRIPTION
===========

   This subclass of Thesaurus creates and maintains its data structure
inside a database.  Use the thesaurus_dbi_config.pl script to create a
configuration for Thesaurus::DBI.  This script creates and/or modifies the
Thesaurus::DBI::Config module, which contains configuration data for your
particular setup.  You can create and maintain multiple

   THIS SUBCLASS HAS NOT YET BEEN IMPLEMENTED!

METHODS
=======

   * new(%params)

     This method returns a new Thesaurus::DBI object using the specified
     configuration.

     This method takes the following parameters:

   * ignore_case (0 or 1) - A boolean parameter.  If true, then the object
     will be case insensitive.  It is _always_ case-preservative for its
     data.

   * configuration ($) - The name that identifies the configuration you
     want to use.  This was specified in the thesaurus_dbi_config.pl
     script.

   * dbh ($) - This is an optional parameter which should be an open
     database handle.  If this is not given then Thesaurus::DBI will
     attempt to open a database handle based on information specified by
     the configuration name.  However, you may not wish to store the
     information necessary to open these handles (such as a password) in
     the Thesaurus::DBI::Config module (which stores it in plaintext).  If
     this parameter is given, then Thesaurus::DBI will not attempt to make
     a database handle.

AUTHOR
======

   Dave Rolsky, <autarch@urth.org>

SEE ALSO
========

   Thesaurus, Thesaurus::File, Thesaurus::DBM

Subclass of Thesaurus that ties data structure to DBM file.
***********************************************************

NAME
====

   Thesaurus::DBM - Subclass of Thesaurus that ties data structure to DBM
file.

SYNOPSIS
========

     use Thesaurus qw(DB_File Storable);

     my $book = Thesaurus->new( ignore_case => 1,
                                filename => $filename,
                                flags => $flags,
                                mode => $mode,
                                extra => \@more_params );

DESCRIPTION
===========

   This subclass of Thesaurus implements a tied interface to a DBM file on
disk, allowing persistence.

use Thesaurus::DBM (@params)
============================

   Thesaurus::DBM takes the same parameters as MLDBM.  The most important
are the first two, which are the DBM file module to use and the
serialization module to use.  See the MLDBM documentation for more details.

   Thesaurus::DBM will not work with SDBM_File, NDBM_File, or ODBM_File
because they doe not support exists on tied hashes.  I believe that this
is fixed in Perl 5.6 (at least for SDBM_File).

   Thesaurus::DBM now supports locking.  When locking is enabled all
operations are atomic.

METHODS
=======

   * new( %params );

     This method returns a new Thesaurus::DBM object tied to a DBM file as
     defined by the parameters passed to this method.

     This method takes the following parameters:

   * ignore_case (0 or 1) - A boolean parameter.  If true, then the object
     will be case insensitive.  It is _always_ case-preservative for its
     data.

   * filename ($) - The DBM filename.

   * flags ($) - Flags passed to the appropriate DBM module.

   * mode ($) - Mode passed to the appropriate DBM module.

   * extra (\@) - Anything passed to this parameter will be passed to the
     DBM module as an additional argument.

     For the BerkeleyDB module, and others that don't follow the
     AnyDBM_File module syntax, just put all the parameters in extra and
     Thesaurus::DBM will handle this appropriately.

   * locking ($) - A true or false value indicating whether or not you
     wish the object to attempt to get a lock for reading and writing to
     the DBM file.  Locking is safer but slower.  The default is to enable
     locking.

   * lock_wait ($) - How long, in seconds, to wait for a lock.  The
     default is 2 seconds.

   All other methods are indentical to Thesaurus.

AUTHOR
======

   Dave Rolsky, <autarch@urth.org>

SEE ALSO
========

   Thesaurus, Thesaurus::File, Thesaurus::DBI, MLDBM, DB_File, GDBM_File

COPYRIGHT
=========

   Copyright (c) 1999 David Rolsky. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Subclass of Thesaurus that implements persistence using CSV format text files.
******************************************************************************

NAME
====

   Thesaurus::File - Subclass of Thesaurus that implements persistence
using CSV format text files.

SYNOPSIS
========

     use Thesaurus::File;

     my $book = Thesaurus->new( ignore_case => 1,
                                files => ['file1.csv', 'file2.csv'] );

DESCRIPTION
===========

   This subclass of Thesaurus implements persistence through the use of
CSV format text files.

METHODS
=======

   * add_files
          $th->add_files($filename1, $filenam2, ...);

     This method adds the contents of the given files to the thesaurus
     object.  If an entry in the files matches an entry already in the
     object, then it is appended to the existing list, otherwise a new
     entry is created.

   * save(%params)

     Writes the contents of the object to a CSV format file.  It takes the
     following named parameters:

   * filename ($) - The filename where the data will be written.

   * mode ($) - This determines whether to write or append the data.  This
     should be a string ('write' or 'append').

AUTHOR
======

   Dave Rolsky, <autarch@urth.org>

SEE ALSO
========

   Thesaurus, Thesaurus::DBM, Thesaurus::DBI

COPYRIGHT
=========

   Copyright (c) 1999 David Rolsky. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

worker thread pools to run Perl code asynchronously
***************************************************

NAME
====

   Thread::Pool - worker thread pools to run Perl code asynchronously

SYNOPSIS
========

     use Thread::Pool;
     my $pool = Thread::Pool->new(Min => 5, Max => 10);
     $pool->enqueue(\&foo, @args);
     $pool->set_min(7);
     $pool->set_max(20);

DESCRIPTION
===========

   The Thread::Pool module implements pools of worker threads. Once a
thread pool is created, jobs (i.e. Perl subs with arguments) may be
enqueued for the pool to execute. When a thread in the pool becomes free,
it takes another job from the pool's work queue and calls it.  If a job is
enqueued while no thread is free and the number of active threads does not
exceed a given maximum, a new thread is added to the pool immediately to
hande the new job. A pool can be configured to have a minimum number of
threads which are always running and waiting for jobs to carry out. A pool
can be configured to have a maximum number of threads - only that number
of threads will ever be created in the pool and new jobs have to wait
until an existing worker thread becomes free.

METHODS
=======

new
     Create a new thread pool. Arguments are optional and are of the form
     of key/value pairs. Passing `Min => $min' invokes `set_min($min)'
     (q.v.) for the pool. The default min value is zero. Passing `Max =>
     $max' invokes `set_max($max)' (q.v.) for the pool. The default max
     value is -1.

enqueue(CODE [, ARG, ...])
     Enqueues a new job for the pool to carry out. CODE can be a reference
     to a subroutine or the name of one. Unqualified subroutine names
     default to the caller's package. The subroutine will be called
     (optionally with any given arguments) in one of the worker threads in
     the pool either immediately (if the number of active threads in the
     pool has not reached its configured maximum) or when a thread becomes
     free (if it has reached its maximum).

set_min(MIN)
     Sets the minimum number of threads in the pool to MIN. If MIN is
     increased then more threads are immediately created in the pool to
     bring the number up to MIN. When the queue of jobs for the pool is
     emptied, MIN worker threads will wait around for more work rather
     than finishing.

set_max(MAX)
     Sets the maximum number of threads in the pool to MAX meaning that no
     more than MAX threads will ever be running concurrently for that pool.
     If MAX is -1 then the limit is infinite. That means that if a new job
     is enqueued while all threads are active, a new thread is always
     created immediately to handle the job.

SEE ALSO
========

   `Thread' in this node

AUTHOR
======

   Malcolm Beattie, mbeattie@sable.ox.ac.uk.

base class for tied arrays
**************************

NAME
====

   Tie::Array - base class for tied arrays

SYNOPSIS
========

     package NewArray;
     use Tie::Array;
     @ISA = ('Tie::Array');

     # mandatory methods
     sub TIEARRAY { ... }
     sub FETCH { ... }
     sub FETCHSIZE { ... }

     sub STORE { ... }        # mandatory if elements writeable
     sub STORESIZE { ... }    # mandatory if elements can be added/deleted
     sub EXISTS { ... }       # mandatory if exists() expected to work
     sub DELETE { ... }       # mandatory if delete() expected to work

     # optional methods - for efficiency
     sub CLEAR { ... }
     sub PUSH { ... }
     sub POP { ... }
     sub SHIFT { ... }
     sub UNSHIFT { ... }
     sub SPLICE { ... }
     sub EXTEND { ... }
     sub DESTROY { ... }

     package NewStdArray;
     use Tie::Array;

     @ISA = ('Tie::StdArray');

     # all methods provided by default

     package main;

     $object = tie @somearray,Tie::NewArray;
     $object = tie @somearray,Tie::StdArray;
     $object = tie @somearray,Tie::NewStdArray;

DESCRIPTION
===========

   This module provides methods for array-tying classes. See
Perltie (perl.info), for a list of the functions required in order
to tie an array to a package. The basic Tie::Array package provides stub
DESTROY, and EXTEND methods that do nothing, stub DELETE and EXISTS
methods that croak() if the delete() or exists() builtins are ever called
on the tied array, and implementations of PUSH, POP, SHIFT, UNSHIFT,
SPLICE and CLEAR in terms of basic FETCH, STORE, FETCHSIZE, STORESIZE.

   The *Tie::StdArray* package provides efficient methods required for
tied arrays which are implemented as blessed references to an "inner" perl
array.  It inherits from Tie::Array, and should cause tied arrays to
behave exactly like standard arrays, allowing for selective overloading of
methods.

   For developers wishing to write their own tied arrays, the required
methods are briefly defined below. See the Perltie (perl.info),
section for more detailed descriptive, as well as
example code:

TIEARRAY classname, LIST
     The class method is invoked by the command `tie @array, classname'.
     Associates an array instance with the specified class. LIST would
     represent additional arguments (along the lines of AnyDBM_File,
     and compatriots) needed to complete the association. The
     method should return an object of a class which provides the methods
     below.

STORE this, index, value
     Store datum value into index for the tied array associated with
     object *this*. If this makes the array larger then class's mapping of
     undef should be returned for new positions.

FETCH this, index
     Retrieve the datum in index for the tied array associated with object
     *this*.

FETCHSIZE this
     Returns the total number of items in the tied array associated with
     object *this*. (Equivalent to `scalar(@array)').

STORESIZE this, count
     Sets the total number of items in the tied array associated with
     object *this* to be count. If this makes the array larger then
     class's mapping of undef should be returned for new positions.  If
     the array becomes smaller then entries beyond count should be deleted.

EXTEND this, count
     Informative call that array is likely to grow to have count entries.
     Can be used to optimize allocation. This method need do nothing.

EXISTS this, key
     Verify that the element at index key exists in the tied array *this*.

     The Tie::Array implementation is a stub that simply croaks.

DELETE this, key
     Delete the element at index key from the tied array *this*.

     The Tie::Array implementation is a stub that simply croaks.

CLEAR this
     Clear (remove, delete, ...) all values from the tied array associated
     with object *this*.

DESTROY this
     Normal object destructor method.

PUSH this, LIST
     Append elements of LIST to the array.

POP this
     Remove last element of the array and return it.

SHIFT this
     Remove the first element of the array (shifting other elements down)
     and return it.

UNSHIFT this, LIST
     Insert LIST elements at the beginning of the array, moving existing
     elements up to make room.

SPLICE this, offset, length, LIST
     Perform the equivalent of splice on the array.

     offset is optional and defaults to zero, negative values count back
     from the end of the array.

     length is optional and defaults to rest of the array.

     LIST may be empty.

     Returns a list of the original length elements at offset.

CAVEATS
=======

   There is no support at present for tied @ISA. There is a potential
conflict between magic entries needed to notice setting of @ISA, and those
needed to implement 'tie'.

   Very little consideration has been given to the behaviour of tied arrays
when $[ is not default value of zero.

AUTHOR
======

   Nick Ing-Simmons <nik@tiuk.ti.com>

Space-efficient, typed, external C Arrays (Alpha)
*************************************************

NAME
====

   Tie::CArray - Space-efficient, typed, external C Arrays (Alpha)

SYNOPSIS
========

     use Tie::CArray;
     $dblarr = new Tie::CDoubleArray(10000);

     @values = (0..10000);
     $dblarr = new Tie::CIntArray(10000,\@values);
     ref $dblarr eq 'Tie::CIntArray' and
       $dblarr->set(0,1) and
       $dblarr->get(0) == 1;

     tie @array, 'Tie::CDoubleArray', 10000, \@values;
     print $array[0], join ', ', @dbl[1..20];

DESCRIPTION
===========

   Several XS classes and methods to deal with typed, space-efficient C
arrays are provided. Range checked and tieable.

   There are hand-optimized, fast XS versions for the three basic C-types
array of *INT*, *DOUBLE* and STRING and some sequential aggregate types
int[2][], int[3][], int[4][], double[2][] and double[3][].

   This roughly reflects to:

     CArray
         CIntArray               int[]
             CInt2Array          int[][2]
             CInt3Array          int[][3]
             CInt4Array          int[][4]
         CDoubleArray            double[]
             CDouble2Array       double[][2]
             CDouble3Array       double[][3]
         CStringArray            *char[]

   Typed C arrays need about three times less space then untyped perl
arrays.  Such as various computional geometry modules dealing with 10.000
- 200.000 double[3]. Modification is done in-place and preferably in bulk.

   It might also be easier to write XSUBs by converting the data to
CArray's before, pass this pointer to the C func, and handle the results
in Perl then.

   The Fetch/Store operations with tied arrays copy the scalars to perl
and back, so it shouldn't be abused for BIG data.

   Perl's safemalloc/safefree is used.

EFFICIENT GROW
==============

   CArray's are efficiently growable, which is needed for several
algorithms, such as placing extra sentinels at the end, adding three
points for a super-triangle for Delaunay triangulation, ...

   Extra space is always allocated to fit nicely into the page boundary,
defined by the system granularity.  For now it's 2048, half of the usual
4096, but this can be tweaked (e.g. for many small arrays) in the C
function freesize().

CLASS METHODS
=============

new ( size, [ template, [ values ]] )
     The new method is provided for all classes, the optional arrayref
     initarg applies only to the base Array classes, not the aggregate.

     The constructor creates a new `Tie::CArray' object. For the Array
     classes the second optional argument is used to initialize it with an
     array. The second argument may also be used by a seperate init call.
     If the optionally provided values arrayref is shorter that the
     allocated size, the rest will stay uninitialized.

          $D = new Tie::CDoubleArray( 1000, ,[0..999] );

len ()
     The len method returns the length of the array, 1+ the index of the
     last element. To enlarge the array grow() should be used.

          $D  = new Tie::CDoubleArray(5000);
          for my $j (0 .. $D->len-1) { $D->set($_, 0.0)); }
          $D->len; # => 5000

get ( index )
     get returns the value at the given index, which will be scalar or a
     list.  Croaks with "index out of range" on wrong index.

          $I = new Tie::CIntArray(2,[0,1]);
          print $I->get(1); # => 1
          print $I->get(2);
            => croak "index out of range"

          $I2 = new Tie::CInt2Array(2,[[0,1]]);
          print $I->get(0); # => (0 1)

set ( index, value )
     The set method is provided for all classes.  It changes the value at
     the given index.  The value should be either a scalar or an arrayref.
     Croaks with "index out of range" on wrong index.  Returns nothing.

          $I = new Tie::CIntArray(100);
          map { $I->set($_,$i[$_]) } (0..99);
          $I->set(99,-1);
          $I->set(100);
            => "index out of range"

          $I2 = Tie::CInt2Array->new(2);
          $I2->set(0, [1,0]);
          $I2->set(1, [0,1]);

list ()
     Returns the content of the flat array representation as arrayref.

init ( ARRAYREF )
     Initializes the array with the values from the arrayref.  Returns
     nothing.

     This is the same as the second new argument.  If the provided values
     arrayref is shorter that the allocated size, the rest will stay
     uninitialized.

          $I = Tie::CIntArray::new(100) ;
          $I->init( [0..99] );

grow ( n )
     Adds room for n elements to the array. These elements must be
     initialized extra with set.  To support faster grow() a certain
     number of already pre-allocated items at the end of the array will be
     used. (see free) Returns nothing.

delete ( index )
     Deletes the item at the given index. free is incremented and the
     remaining array items are shifted.  Returns nothing.

get_grouped_by ( size, index )
     Returns a list of subsequent values.  It returns a list of size
     indices starting at size * index.  This is useful to abuse the
     unstructured array as typed array of the same type, such as
     *double[3] or *int[2].

     But this is normally not used since fast get methods are provided for
     the sequential classes, and those methods can be used on flat arrays
     as well.  (Internally all sequential arrays are flat).

          Tie::CInt3Array::get($I,0) == $I->get_grouped_by(3,0)

     $ptr->get_grouped_by(2,4) returns the 4-th pair if the array is seen
     as list of pairs.

          $ptr->get_grouped_by(3,$i) => (ptr[i*3] ptr[i*3+1] ptr[i*3+2] )

slice ( start, size, [ stride=1 ] )
     C++ like slice operator on a flat array. - In contrast to
     get_grouped_by() which semantics are as on a grouped array.

     Returns a list of size items, starting at start, with interim offsets
     of stride which defaults to 1.  This is useful to return columns or
     rows of a flat matrix.

          $I = new Tie::CIntArray (9, [0..8]);
          $I->slice ( 0, 3, 3 ); # 1st column
            => (0 3 6)
          $I->slice ( 0, 3, 1 ); # 1st row
            => (0 1 2)
          $I->get_grouped_by(3, 0);
            => (0 1 2)

isort ( [ cmpfunc ] )
     "Indirect sort" (numerically ascending only for now)

     Returns a fresh sorted index list of integers (0 .. len-1) resp. a
     CIntArray object in scalar context.

     The optional cmpfunc argument is not yet implemented.

nreverse ()
     "Reverse in place". (The name comes from lisp, where `n' denotes the
     destructive version).  Destructively swaps all array items. Returns
     nothing.

     To perform a copying reverse define

     sub reverse { nreverse($_[0]->copy()) }

SOME SEQUENTIAL CLASSES and CONVERSION
======================================

   To mix and change parallel and sequential data structures, some
sequential types (int[2],int[3],int[4],double[2],double[3]) are derived
from their base classes with fast, hand-optimized get and set methods to
return and accept lists instead of scalars.

   The input argument must be an arrayref, the result will be an array in
list context and an arrayref in scalar context.

   Conversion

   The Arrays for Int2, Int3, Int4, Double2 and Double3 can also be
converted from and to parallel base arrays with fast XS methods.  Parallel
arrays are sometimes preferred over structured arrays, but delete/ insert
of structures in parallel arrays is costly.

     # three parallel CIntArray's
     $X = new Tie::CIntArray(1000);
     $Y = new Tie::CIntArray(1000);
     $Z = new Tie::CIntArray(1000);

     # copy to one sequential *int[3], new memory
     $I = $X->ToInt3($Y,$Z);

     # or to an existing array
     $I = new Tie::CIntArray(3000);
     $I = $X->ToInt3($Y,$Z,$I);

     # copies back with allocating new memory
     ($X, $Y, $Z) = $I->ToPar();

     # copies back with reusing some existing memory (not checked!)
     ($X, $Y, $Z) = $I->ToPar($X,$Z);  # Note: I3 will be fresh.

ToPar ( SeqArray, [ Tie::CArray,... ] )
     This returns a list of Tie::CArray objects, copied from the sequential
     object to plain parallel CArray objects. This is a fast slice.

          *int[2] => (*int, *int)

          Tie::CInt2Array::ToPar
          Tie::CInt3Array::ToPar
          Tie::CInt4Array::ToPar
          Tie::CDouble2Array::ToPar
          Tie::CDouble3Array::ToPar

     If the optional CArray args are given the memory for the returned
     objects are not new allocated, the space from the given objects is
     used instead.

To$Type$Num ( CArray, ..., [ CArray ] )
     This returns a sequential CArray object copied from the parallel
     objects given as arguments to one sequential CArray. This is a fast
     map.

          *int, *int => *int[2]

          Tie::CIntArray::ToInt2
          Tie::CIntArray::ToInt3
          Tie::CIntArray::ToInt4
          Tie::CDoubleArray::ToDouble2
          Tie::CDoubleArray::ToDouble3

     If the last optional CArray arg is defined the memory for the returned
     object is not new allocated, the space from the given object is used
     instead.

ARBITRARY STRUCTURED ARRAYS, PACK-STYLE TEMPLATES
=================================================

   Some special sequential arrays are hand-optimized for speed but can
hold only limited data types (int[2] .. double[3]).

   To support arbitrary structured arrays a second template argument may be
provided which must be a arrayref of a hash, where its keys name the
accessor and the values pack-style letters.

     tie @A, 'Tie::CArray', 200,
                  [ x => 'd',
                    y => 'd',
                    z => 'd',
                    attr => [ age   => 'i',
                              dirty => 'i',
                              owner => 's' ],
                    refcount => 'i' ];
       $A->init ...

     for (my $i = 0; $i < @A; $i++) {
       printf("x,y,z: (%d %d %d),\nattr: (age=%d, dirty=%d, owner=%s)\nrefcount=%d",
              $A[$i]->{x}, $A[$i]->{y}, $A[$i]->{z},
              $A[$i]->{attr}->{age}, $A[$i]->{attr}->{dirty}, $A[$i]->{attr}->{owner},
              $A[$i]->{refcount}
             );
     }

     tie @utmp, 'Tie::CArray', 100,
           [ ut_type => 's',
             ut_pid  => 'i',
             ut_line    => 'a12',
             ut_id      => 'a4',
             ut_user    => 'a32',
             ut_host    => 'a256',
             ut_exit    => [ # struct exit_status
                             e_termination => 's',
                             e_exit        => 's' ],
             ut_session => 'l',
             ut_tv      => [ # struct timeval
                             tv_sec  => 'l'
                             tv_usec => 'l' ],
             ut_addr_v6 => 'l4',
             pad        => 'a20' ];

   The following subset of `pack()|perlfunc' in this node template letters
is supported:

i
     signed integer (default)

I
     unsigned integer

c
     signed character (one byte integer)

c
     unsigned character (one byte integer)

s
     signed short integer

S
     unsigned short integer

n
     unsigned short integer in network byte order

l
     signed long integer

L
     unsigned long integer

N
     unsigned long integer in network byte order

q
     signed long long integer (long long/int64)

     (only if the system has quads and perl was compiled for 64 bit)

Q
     unsigned long long integer (unsigned long long/uint64)

     (only if the system has quads and perl was compiled for 64 bit)

L
     unsigned long integer

f
     float

d
     double

aN
     fixed-length, null-padded ASCII string of length N

AN
     fixed-length, space-padded ASCII string of length N

ZN
     fixed-length, null-terminated ASCII string of length N

INTERNAL METHODS
================

DESTROY ()
     This used to crash on certain DEBUGGING perl's, but seems to be okay
     now.  Returns nothing.

Tie::CArray::itemsize ( )
Tie::CStringArray::itemsize ( [index] )
     Returns the size in bytes per item stored in the array. This is only
     used internally to optimize memory allocation and the free list.

     A CStringArray object accepts the optional index argument, which
     returns the string length at the given index. Without argument it
     returns the size in bytes of a char * pointer (which is 4 on 32 bit
     systems).

copy ()
     Returns a freshly allocated copy of the array with the same contents.

_freelen ()
     Internal only.  Returns the number of free elements at the end of the
     array.  If grow() needs less or equal than free elements to be added,
     no new room will be allocated.

     This is primarly for performance measures.

TIEARRAY METHODS
================

   *Not tested yet!*

tie (var, type, size)
     After tying a array variable to an `Tie::CArray' class the variable
     can be used just as any normal perl array.

          tie @array, 'Tie::CDoubleArray', 200;
          print $array[200];
            => croak "index out of range"

SEE ALSO
========

     http://www.perl.com//CPAN/authors/id/RURBAN/         or
     http://xarch.tu-graz.ac.at/home/rurban/software/perl or
     ftp://xarch.tu-graz.ac.at/pub/autocad/urban/perl

   `perlxs(1)' in this node, `tie', see Perlfunc (perl.info),
`Tie::Array(3)' in this node, `Geometry::Points(3)' in this node,
`C::Dynalib::Poke(3)' in this node, `Tie::MmapArray(3)' in this node

TODO
====

   Not all pack letters are implemented yet.

AUTHOR
======

   Reini Urban <rurban@x-ray.at>

   Andrew Ford wrote the arbitrary structure code.

COPYRIGHT
=========

   Copyright (c) 1999 Reini Urban.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

WARNING
=======

   The author makes NO WARRANTY, implied or otherwise, about the
suitability of this software for safety or security purposes.

   CArrays are now always ranged checked which cannot be turned off, so
it's not that dangerous anymore to read or write to not-owned memory areas.

   The author shall not in any case be liable for special, incidental,
consequential, indirect or other similar damages arising from the use of
this software.

   Your mileage will vary. If in any doubt *DO NOT USE IT*. You've been
warned.

BUGS
====

   There are certainly some. Not fully tested yet.  Tests for copy, grow,
delete, tie are pending.  Also some more conversion tests, esp. with
double and degenerate (grow, cut) cases.

  1. realloc() in string_set() with DEBUGGING perl fails sometimes.

  2. An implicit DESTROY invocation sometimes asserts a DEBUGGING perl,
     regardless if PERL_MALLOC or the WinNT msvcrt.dll malloc is used.
     (5.00502 - 5.00558) Esp. on perl shutdown, when freeing the extra
     objects at the second GC.

     This became much better in 0.08 than in previous versions.

        This is alpha, not fully tested yet!

VERSION
=======

   $Revision 0.12 $ $Date 2000-01-11 $

Case preserving but case insensitive hash table
***********************************************

NAME
====

   Tie::CPHash - Case preserving but case insensitive hash table

SYNOPSIS
========

     require Tie::CPHash;
     tie %cphash, 'Tie::CPHash';

     $cphash{'Hello World'} = 'Hi there!';
     printf("The key `%s' was used to store `%s'.\n",
            tied(%cphash)->key('HELLO WORLD'),
            $cphash{'HELLO world'});

DESCRIPTION
===========

   The *Tie::CPHash* provides a hash table that is case preserving but
case insensitive.  This means that

     $cphash{KEY}    $cphash{key}
     $cphash{Key}    $cphash{keY}

   all refer to the same entry.  Also, the hash remembers which form of
the key was last used to store the entry.  The keys and each functions
will return the key that was used to set the value.

   An example should make this clear:

     tie %h, 'Tie::CPHash';
     $h{Hello} = 'World';
     print $h{HELLO};            # Prints 'World'
     print keys(%h);             # Prints 'Hello'
     $h{HELLO} = 'WORLD';
     print $h{hello};            # Prints 'WORLD'
     print keys(%h);             # Prints 'HELLO'

   The additional key method lets you fetch the case of a specific key:

     # When run after the previous example, this prints 'HELLO':
     print tied(%h)->key('Hello');

   (The tied function returns the object that `%h' is tied to.)

   If you need a case insensitive hash, but don't need to preserve case,
just use `$hash{lc $key}' instead of `$hash{$key}'.  This has a lot less
overhead than *Tie::CPHash*.

AUTHOR
======

   Christopher J. Madsen <`chris_madsen@geocities.com'>

LRU Cache in Memory
*******************

NAME
====

   Tie::Cache - LRU Cache in Memory

SYNOPSIS
========

     use Tie::Cache;
     tie %cache, 'Tie::Cache', 100, { Debug => 1 };
     tie %cache2, 'Tie::Cache', { MaxCount => 100, MaxBytes => 1000 };
     tie %cache3, 'Tie::Cache', 100, { Debug => 1 , WriteSync => 0};

     # Options ##################################################################
     #
     # Debug =>	 0 - DEFAULT, no debugging output
     #		 1 - prints cache statistics upon destroying
     #		 2 - prints detailed debugging info
     #
     # MaxCount =>	 Maximum entries in cache.
     # MaxBytes =>   Maximum bytes in cache, sum of keys and values.
     # MaxSize  =>   Maximum size of each cache entry. Larger entries are not cached.
     #                   This helps prevent much of the cache being flushed when
     #                   you set an exceptionally large entry.
     # WriteSync =>  1 - DEFAULT, write() when data is dirtied for
     #                   TRUE CACHE (see below)
     #               0 - write() dirty data as late as possible, when leaving
     #                   cache, or when cache is being DESTROY'd
     #
     ############################################################################

     # cache supports normal tied hash functions
     $cache{1} = 2;       # STORE
     print "$cache{1}\n"; # FETCH

     # FIRSTKEY, NEXTKEY
     while(($k, $v) = each %cache) { print "$k: $v\n"; }

     delete $cache{1};    # DELETE
     %cache = ();         # CLEAR

DESCRIPTION
===========

   This module implements a least recently used (LRU) cache in memory
through a tie interface.  Any time data is stored in the tied hash, that
key/value pair has an entry time associated with it, and as the cache
fills up, those members of the cache that are the oldest are removed to
make room for new entries.

   So, the cache only "remembers" the last written entries, up to the size
of the cache.  This can be especially useful if you access great amounts
of data, but only access a minority of the data a majority of the time.

   The implementation is a hash, for quick lookups, overlaying a doubly
linked list for quick insertion and deletion.  On a WinNT PII 300, writes
to the hash were done at a rate 3100 per second, and reads from the hash
at 6300 per second.  Work has been done to optimize refreshing cache
entries that are frequently read from, code like $cache{entry}, which
moves the entry to the end of the linked list internally.

INSTALLATION
============

   Tie::Cache installs easily using the make or nmake commands as shown
below.  Otherwise, just copy Cache.pm to $PERLLIB/site/Tie

     > perl Makefile.PL
     > make
             > make test
     > make install

     * use nmake for win32
     ** you can also just copy Cache.pm to $perllib/Tie

BENCMARKS
=========

   There is another simpler LRU cache implementation in CPAN,
Tie::Cache::LRU, which has the same basic size limiting functionality, and
for this functionality, the exact same interface.  This other cache takes
writes about 20% faster but cache reads are about 50% slower.  Here are
some numbers to illustrate:

     Module			Read/s	Write/s	Delete/s Platform
     ------			------	-------	-------- --------
     Tie::Cache v.08	 6300	3100	4800	 perl 5.00404 WinNT PII300
     Tie::Cache::LRU v.05	 3700	3700	4500	 perl 5.00404 WinNT PII300
     --
     Tie::Cache v.08	10600	5300	8500	 perl 5.00503 Solaris PII300

   The reason for using an cache is that you are probably doing more reads
than writes, so you will likely want to use this module, but may want to
consider Tie::Cache::LRU if your i/o mix is write heavy.

TRUE CACHE
==========

   To use class as a true cache, which acts as the sole interface for some
data set, subclass the real cache off Tie::Cache, with @ISA = qw(
'Tie::Cache' ) notation.  Then override the read() method for behavior
when there is a cache miss, and the write() method for behavior when the
cache's data changes.

   When WriteSync is 1 or TRUE (DEFAULT), write() is called immediately
when data in the cache is modified.  If set to 0, data that has been
modified in the cache gets written out when the entries are deleted or
during the DESTROY phase of the cache object, usually at the end of a
script.

TRUE CACHE EXAMPLE
==================

     use Tie::Cache;

     # personalize the Tie::Cache object, by inheriting from it
     package My::Cache;
     @ISA = qw(Tie::Cache);

     # override the read() and write() member functions
     # these tell the cache what to do with a cache miss or flush
     sub read {
        my($self, $key) = @_;
        print "cache miss for $key, read() data\n";
        rand() * $key;
     }
     sub write {
        my($self, $key, $value) = @_;
        print "flushing [$key, $value] from cache, write() data\n";
     }

     my $cache_size   = $ARGV[0] || 2;
     my $num_to_cache = $ARGV[1] || 4;
     my $Debug = $ARGV[2] || 1;

     tie %cache, 'My::Cache', $cache_size, {Debug => $Debug};

     # load the cache with new data, each through its contents,
     # and then reload in reverse order.
     for(1..$num_to_cache) { print "read data $_: $cache{$_}\n" }
     while(my($k, $v) = each %cache) { print "each data $k: $v\n"; }
     for(my $i=$num_to_cache; $i>0; $i--) { print "read data $i: $cache{$i}\n"; }

     # clear cache in 2 ways, write will flush out to disk
     %cache = ();
     undef %cache;

NOTES
=====

   Many thanks to all those who helped me make this module a reality,
including:

     :) Tom Hukins who provided me insight and motivation for
        finishing this module.
     :) Jamie McCarthy, for trying to make Tie::Cache be all
        that it can be.
     :) Rob Fugina who knows how to "TRULY CACHE".

AUTHOR
======

   Please send any questions or comments to Joshua Chamas at
chamas@alumni.stanford.org

COPYRIGHT
=========

   Copyright (c) 1999 Joshua Chamas.  All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

A Least-Recently Used cache
***************************

NAME
====

   Tie::Cache::LRU - A Least-Recently Used cache

SYNOPSIS
========

     tie %cache, 'Tie::Cache::LRU', 500;
     tie %cache, 'Tie::Cache::LRU', '400k'; #UNIMPLEMENTED

     # Use like a normal hash.

     $cache_obj = tied %cache;
     $current_size = $cache_obj->curr_size;

     $max_size = $cache_obj->max_size;
     $cache_obj->max_size($new_size);

DESCRIPTION
===========

   This is an implementation of a least-recently used (LRU) cache keeping
the cache in RAM.

   A LRU cache is similar to the kind of cache used by a web browser.  New
items are placed into the top of the cache.  When the cache grows past its
size limit, it throws away items off the bottom.  The trick is that
whenever an item is -accessed-, it is pulled back to the top.  The end
result of all this is that items which are frequently accessed tend to
stay in the cache.

USAGE
=====

   The cache is extremely simple, is just holds a simple scalar.  If you
want to cache an object, just place it into the cache:

     $cache{$obj->id} = $obj;

   This doesn't make a copy of the object, it just holds a reference to
it.  (Note: This means that your object's destructor will not be called
until it has fallen out of the cache (and all other references to it have
disappeared, of course)!)

   If you want to cache an array, place a reference to it in the cache:

     $cache{$some_id} = \@array;

   Or, if you're worried about the consequences of tossing around
references and want to cache a copy instead, you can do something like
this:

     $cache{$some_id} = [@array];

Tied Interface
--------------

tie
          tie %cache, 'Tie::Cache::LRU';
          tie %cache, 'Tie::Cache::LRU', $cache_size;

     This ties a cache to %cache which will hold a maximum of $cache_size
     keys.  If $cache_size is not given it uses a default value,
     Tie::Cache::LRU::DEFAULT_MAX_SIZE.

     If the size is set to 0, the cache is effectively turned off.  This is
     useful for "removing" the cache from a program without having to make
     deep alterations to the program itself, or for checking performance
     differences with and without a cache.

     All of the expected hash operations (exists, delete, slices, etc...)
     work on the %cache.

Object Interface
----------------

   There's a few things you just can't do through the tied interface.  To
do them, you need to get at the underlying object, which you do with
tied().

     $cache_obj = tied %cache;

   And then you can call a few methods on that object:

max_size
          $cache_obj->max_size($size);
          $size = $cache_obj->max_size;

     An accessor to alter the maximum size of the cache on the fly.

     If max_size() is reset, and it is lower than the current size, the
     cache is immediately truncated.

     The size must be an integer greater than or equal to 0.

curr_size
          $size = $cache_obj->curr_size;

     Returns the current number of items in the cache.

FUTURE
======

   Should eventually allow the cache to be in shared memory.

   Max size by memory use unimplemented.

   For small cache sizes, it might be more efficient to just use an array
instead of a linked list.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com> for Arena Networks

SEE ALSO
========

   `perl(1)' in this node

Maintains sorted lists of top entries
*************************************

NAME
====

   Tie::CacheHash - Maintains sorted lists of top entries

SYNOPSIS
========

     use Tie::CacheHash;
     tie %hash1, 'Tie::CacheHash', 10, 100;
     tie %hash2, 'Tie::CacheHash', '5%', '10%';

DESCRIPTION
===========

   Of course you can get the "top 100" entries of any perl hash:

     @top_keys = (sort my_sort_func keys %my_hash)[0..99];

   But if your hash has more than a few thousand entries, that sort
operation may take several seconds.  And if you have tens of thousands of
entries, the sort may take many minutes.

   (If you are reading this documentation past the expiration date on the
bottom of the carton, please adjust the numbers accordingly.  Sorting is
always problematic for sufficiently large n.)

   Many programs will need to keep track of a "top 100" (or "bottom 100")
to perform such operations as expiring the oldest items out of a cache.
Sorting the entire array and skimming off the top items is not always an
acceptable algorithm.  Tie::CacheHash provides a simple and reasonably
efficient solution.  Its primary design goal is reasonable responsiveness
on every operation, i.e. no unpredictable long delays, and it achieves
this goal by avoiding the sorting of huge arrays.

   The two parameters you pass after the classname are the minimum and
maximum allowable size for the cache.  The largest array the module will
ever have to sort will be somewhat above the maximum (how much depends on
the distribution of your data), so picking a good 'max' will help control
the maximum delay you will experience.

   A 'min' of 0 means it is OK for the cache to run dry and never
replenish itself (###I think###), so you probably want a minimum of at
least 1.  A minimum/maximum of a very large integer (try 2**30) means to
keep the whole hash in the cache.

   Duplicate values are allowed;  if you don't specify your own sort
function, they will be secondarily sorted by key.

   If you pass in a subhash, you MUST NOT alter its data directly:  only
through the CacheHash.

BUGS
====

   There should be a way to store or delete large amounts of data at once,
without cache overhead between each entry.  For now, it should work to
munge the {h} array directly and then call cache_rebuild, but that's an
ugly workaround.

   There should be a way to set cache_pos's secondary (key) sort function,
instead of forcing "cmp".  (This would mean a tertiary sort to ensure
predictable sort order in case the user screws up and returns 0 for
nonequal keys.)

   Not sure yet whether the undefined value is handled properly in all
cases.  Should be tested with a subhash of a type known to choke and die
horribly on undef (ideally, Tie::CacheHash would not provoke such
behavior).

   The percent-style min/max arguments don't work yet (but they're an
awfully cool idea aren't they?).

   Because it's not a full 1.0 release yet, "make test" still does a
tremendous amount of randomized stress testing.  This takes longer than it
really should (typically 15-30 seconds, sometimes more).  When it gets
closer to release, this will be backed-off.

   The Monte Carlo algorithm has a number of places where its performance
could be further optimized.  In some cases the impact is significant.
These are marked in the code as "BUG".

   The cmp() method probably has room for performance improvement if we
make the very fair assumption that sort_func and sort_rev will not change
during a sort!

   The different DEBUG levels are neither well-thought-out nor documented.

   Haven't tested setting cache minimum to 0.

   Haven't tested setting cache maximum to 2**30.

AUTHOR
======

   Jamie McCarthy <jamie@mccarthy.org>.

Access Perl scalars as arrays of characters
*******************************************

NAME
====

   Tie::CharArray - Access Perl scalars as arrays of characters

SYNOPSIS
========

     use Tie::CharArray;
     my $foobar = 'a string';

     tie my @foo, 'Tie::CharArray', $foobar;
     $foo[0] = 'A';    # $foobar = 'A string'
     push @foo, '!';   # $foobar = 'A string!'
     print "@foo\n";   # prints: A   s t r i n g !

     tie my @bar, 'Tie::CharArray::Ord', $foobar;
     $bar[0]--;        # $foobar = '@ string!'
     pop @bar;         # $foobar = '@ string'
     print "@bar\n";   # prints: 64 32 115 116 114 105 110 103

DESCRIPTION
===========

   In low-level programming languages such as C, and to some extent Java,
strings are not primitive data types but arrays of characters, which in
turn are treated as integers.  This closely matches the internal
representation of strings in the memory.

   Perl, on the other hand, abstracts such internal details away behind
the concept of scalars, which can be treated as either strings or numbers,
and appear as primitive types to the programmer.  This often better
matches the way people think about the data, which facilitates programming
by making common high-level manipulation tasks trivial.

   Sometimes, though, the low-level view is better suited for the task at
hand.  Perl does offer functions such as ord()/chr(), pack()/unpack() and
substr() that can be used to solve such tasks with reasonable efficiency.
For someone used to the direct access to the internal representation
offered by other languages, however, these functions may feel awkward.
While this is often only a symptom of thinking in un-Perlish terms,
sometimes being able to manipulate strings as character arrays really does
simplify the code, making the intent more obvious by eliminating syntactic
clutter.

   This module provides a way to manipulate Perl strings through tied
arrays.  The operations are implemented in terms of the aforementioned
string manipulation functions, but the programmer normally need not be
aware of this.  As Perl has no primitive character type, two alternative
representations are provided:

Strings as arrays of single-character strings
---------------------------------------------

   The first way is to represent characters as strings of length 1.  In
most cases this is the most convenient representation, as such
"characters" can be printed without explicit transformations and written
as ordinary Perl string literals.

   This representation is provided by the main class Tie::CharArray.  As
the class maps most array operations directly to calls to substr(),
several features of that function apply.  (Below, `@foo' is an array tied
to Tie::CharArray and $n is a positive integer.)

   * `$foo[@foo]' is an empty string, `$foo[@foo+$n]' is undef.

   * Assigning to `$foo[@foo+$n]' is a fatal error.  So is splice() beyond
     the end of the array.

   * If you assign an empty string (or undef) to an element, any later
     elements are shifted down.

   * If you assign a string longer than one character to an element, any
     later elements are shifted up.

   In general, if you only put one-character strings into the array, and
don't go beyond its end, there should be no problems.

Strings as arrays of small integers
-----------------------------------

   While the representation described above is usually the most convenient
one, it still does not allow direct arithmetic manipulation of the
character code values.  For tasks where this is needed, an alternative
representation is provided by the subclass Tie::CharArray::Ord.  Note that
it is perfectly possible to manipulate a single string through both
interfaces at the same time.  As the array operations are still based on
substr(), the first two of the above caveats apply here as well.

BUGS
====

   Exposing the peculiarities of substr() to the user might be considered
a bug.  In any case, it is a feature which one should probably not rely
on, as it might change in future revisions.

AUTHORS
=======

   Copyright 2000, Ilmari Karonen.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Address bug reports and comments to: perl@itz.pp.sci.fi

SEE ALSO
========

   Tie::Array, substr()

A trivial implementaion of Tie::Cache by using a tied handle of a hash for storage.
***********************************************************************************

NAME
====

   Tie::Collection - A trivial implementaion of Tie::Cache by using a tied
handle of a hash for storage.

SYNOPSIS
========

   use Tie::Collection; use DB_File; use Fcntl;

   $dbm = tie %hash2, DB_File, 'file.db', O_RDWR | O_CREAT, 0644; tie
%hash, Tie::Collection, $dbm, {MaxBytes => $cache_size};

DESCRIPTION
===========

   Tie::Collection implements a trivial implementation of *Tie::Cache* by
Joshua Chamas, that gets a tied hash handle to store the data. Assumption
was that most common use will be disk storage, therfore the storage hash
will probably be tied.

   Tie::Collection is useful with DB_File or *MLDBM*, as will as with
*Tie::DBI*. It was designed to be used with *HTML::HTPL* in order to cache
objects accesses via a key, so they don't have to be read from disk again
and again.

   Tie::Collection needs two parameters: The handled of the tied hash, and
a hashref with parameters to pass to *Tie::Cache*. (See manpage).

AUTHOR
======

   Ariel Brosh, schop@cpan.org.  *Tie::Cache* was written by Joshua
Chamas, chamas@alumni.stanford.org

SEE ALSO
========

   perl(1), see Tie/Cache.

COPYRIGHT
=========

   Tie::Collection is part of the HTPL package. See `HTML::HTPL' in this
node

Have a counter in a scalar.
***************************

NAME
====

   Tie::Counter - Have a counter in a scalar.

SYNOPSIS
========

     use Tie::Counter;

     tie my $counter => 'Tie::Counter';

     my @array = qw /Red Green Blue/;

     foreach my $colour (@array) {           # Prints:
         print "  $counter  $colour\n";      #   0  Red
     }                                       #   1  Green
                                             #   2  Blue

DESCRIPTION
===========

   `Tie::Counter' allows you to tie a scalar in such a way that it
increments each time it is used. This might be useful for interpolating
counters in strings.

   The tie takes an optional extra argument, the first value of the
counter, defaulting to 0. Any argument for which magical increment is
defined on is allowed. Assigning to the counter will set a new value.

REVISION HISTORY
================

     $Log: Counter.pm,v $
     Revision 1.1  1999/07/20 03:03:06  abigail
     Initial revision

AUTHOR
======

   This package was written by Abigail.

COPYRIGHT and LICENSE
=====================

   This package is copyright 1999 by Abigail.

   This program is free and open software. You may use, copy, modify,
distribute and sell this program (and any modified variants) in any way
you wish, provided you do not restrict others to do the same.

Cycle through a list of values via a scalar.
********************************************

NAME
====

   Tie::Cycle - Cycle through a list of values via a scalar.

SYNOPSIS
========

     use Tie::Cycle;

     tie my $cycle, 'Tie::Cycle', [ qw( FFFFFF 000000 FFFF00 ) ];

     print $cycle; # FFFFFF
     print $cycle; # 000000
     print $cycle; # FFFF00
     print $cycle; # FFFFFF  back to the beginning

DESCRIPTION
===========

   You use `Tie::Cycle' to go through a list over and over again.  Once
you get to the end of the list, you go back to the beginning.  You don't
have to worry about any of this since the magic of tie does that for you.

   The tie takes an array reference as its third argument.  The tie should
succeed unless the argument is not an array reference or the referenced
array contains less than two elements.

   During the tie, this module makes a shallow copy of the array
reference.  If the array reference contains references, and those
references are changed after the tie, the elements of the cycle will
change as well. See the included test.pl script for an example of this
effect.

AUTHOR
======

   brian d foy <comdog@panix.com>.

COPYRIGHT and LICENSE
=====================

   Copyright 2000 by brian d foy.

   This software is available under the same terms as perl.

Tie hashes to DBI relational databases
**************************************

NAME
====

   Tie::DBI - Tie hashes to DBI relational databases

SYNOPSIS
========

     use Tie::DBI;
     tie %h,Tie::DBI,'mysql:test','test','id',{CLOBBER=>1};

     tie %h,Tie::DBI,{db       => 'mysql:test',
     		   table    => 'test',
                      key      => 'id',
                      user     => 'nobody',
                      password => 'ghost',
                      CLOBBER  => 1};

     # fetching keys and values
     @keys = keys %h;
     @fields = keys %{$h{$keys[0]}};
     print $h{'id1'}->{'field1'};
     while (($key,$value) = each %h) {
       print "Key = $key:\n";
       foreach (sort keys %$value) {
     	print "\t$_ => $value->{$_}\n";
       }
     }

     # changing data
     $h{'id1'}->{'field1'} = 'new value';
     $h{'id1'} = { field1 => 'newer value',
                   field2 => 'even newer value',
                   field3 => "so new it's squeaky clean" };

     # other functions
     tied(%h)->commit;
     tied(%h)->rollback;
     tied(%h)->select_where('price > 1.20');
     @fieldnames = tied(%h)->fields;
     $dbh = tied(%h)->dbh;

DESCRIPTION
===========

   This module allows you to tie Perl associative arrays (hashes) to SQL
databases using the DBI interface.  The tied hash is associated with a
table in a local or networked database.  One column becomes the hash key.
Each row of the table becomes an associative array, from which individual
fields can be set or retrieved.

USING THE MODULE
================

   To use this module, you must have the DBI interface and at least one
DBD (database driver) installed.  Make sure that your database is up and
running, and that you can connect to it and execute queries using DBI.

Creating the tie
----------------

     tie %var,Tie::DBI,[database,table,keycolumn] [,\%options]

   Tie a variable to a database by providing the variable name, the tie
interface (always "Tie::DBI"), the data source name, the table to tie to,
and the column to use as the hash key.  You may also pass various flags to
the interface in an associative array.

database
     The database may either be a valid DBI-style data source string of the
     form "dbi:driver:database_name[:other information]", or a database
     handle that has previously been opened.  See the documentation for DBI
     and your DBD driver for details.  Because the initial "dbi" is always
     present in the data source, Tie::DBI will add it for you if necessary.

     Note that some drivers (Oracle in particular) have an irritating habit
     of appending blanks to the end of fixed-length fields.  This will
     screw up Tie::DBI's routines for getting key names.  To avoid this you
     should create the database handle with a ChopBlanks option of TRUE.
     You should also use a *PrintError* option of true to avoid complaints
     during STORE and LISTFIELD calls.

table
     The table in the database to bind to.  The table must previously have
     been created with a SQL CREATE statement.  This module will not create
     tables for you or modify the schema of the database.

key
     The column to use as the hash key.  This column must prevoiusly have
     been defined when the table was created.  In order for this module to
     work correctly, the key column must be unique and not nullable.  For
     best performance, the column should be also be declared a key.  These
     three requirements are automatically satisfied for primary keys.

   It is possible to omit the database, table and keycolumn arguments, in
which case the module tries to retrieve the values from the options array.
The options array contains a set of option/value pairs.  If not provided,
defaults are assumed.  The options are:

user
     Account name to use for database authentication, if necessary.
     Default is an empty string (no authentication necessary).

password
     Password to use for database authentication, if necessary.  Default is
     an empty string (no authentication necessary).

db
     The database to bind to the hash, if not provided in the argument
     list.  It may be a DBI-style data source string, or a
     previously-opened database handle.

table
     The name of the table to bind to the hash, if not provided in the
     argument list.

key
     The name of the column to use as the hash key, if not provided in the
     argument list.

CLOBBER (default 0)
     This controls whether the database is writable via the bound hash.  A
     zero value (the default) makes the database essentially read only.  An
     attempt to store to the hash will result in a fatal error.  A CLOBBER
     value of 1 will allow you to change individual fields in the database,
     and to insert new records, but not to delete entire records.  A
     CLOBBER value of 2 allows you to delete records, but not to erase the
     entire table.  A CLOBBER value of 3 or higher will allow you to erase
     the entire table.

          Operation                       Clobber      Comment

          $i = $h{strawberries}->{price}     0       All read operations
          $h{strawberries}->{price} += 5     1       Update fields
          $h{bananas}={price=>23,quant=>3}   1       Add records
          delete $h{strawberries}            2       Delete records
          %h = ()                            3       Clear entire table
          undef %h                           3       Another clear operation

     All database operations are contingent upon your access privileges.
     If your account does not have write permission to the database, hash
     store operations will fail despite the setting of CLOBBER.

AUTOCOMMIT (default 1)
     If set to a true value, the "autocommit" option causes the database
     driver to commit after every store statement.  If set to a false
     value, this option will not commit to the database until you
     explicitly call the Tie::DBI commit() method.

     The autocommit option defaults to true.

DEBUG (default 0)
     When the DEBUG option is set to a non-zero value the module will echo
     the contents of SQL statements and other debugging information to
     standard error.  Higher values of DEBUG result in more verbose (and
     annoying) output.

WARN (default 1)
     If set to a non-zero value, warns of illegal operations, such as
     attempting to delete the value of the key column.  If set to a zero
     value, these errors will be ignored silently.

USING THE TIED ARRAY
====================

   The tied array represents the database table.  Each entry in the hash
is a record, keyed on the column chosen in the tie() statement.
Ordinarily this will be the table's primary key, although any unique
column will do.

   Fetching an individual record returns a reference to a hash of field
names and values.  This hash reference is itself a tied object, so that
operations on it directly affect the database.

Fetching information
--------------------

   In the following examples, we will assume a database table structured
like this one:

     -produce-
         produce_id    price   quantity   description

     strawberries  1.20    8          Fresh Maine strawberries
     apricots      0.85    2          Ripe Norwegian apricots
     bananas       1.30    28         Sweet Alaskan bananas
     kiwis         1.50    9          Juicy New York kiwi fruits
     eggs          1.00   12          Farm-fresh Atlantic eggs

   We tie the variable %produce to the table in this way:

     tie %produce,Tie::DBI,{db    => 'mysql:stock',
                            table => 'produce',
                            key   => 'produce_id',
                            CLOBBER => 2 # allow most updates
                            };

   We can get the list of keys this way:

     print join(",",keys %produce);
        => strawberries,apricots,bananas,kiwis

   Or get the price of eggs thusly:

     $price = $produce{eggs}->{price};
     print "The price of eggs = $price";
         => The price of eggs = 1.2

   String interpolation works as you would expect:

     print "The price of eggs is still $produce{eggs}->{price}"
         => The price of eggs is still 1.2

   Various types of syntactic sugar are allowed.  For example, you can
refer to $produce{eggs}{price} rather than $produce{eggs}->{price}.  Array
slices are fully supported as well:

     ($apricots,$kiwis) = @produce{apricots,kiwis};
     print "Kiwis are $kiwis->{description};
         => Kiwis are Juicy New York kiwi fruits

     ($price,$description) = @{$produce{eggs}}{price,description};
         => (2.4,'Farm-fresh Atlantic eggs')

   If you provide the tied hash with a comma-delimited set of record
names, and you are not requesting an array slice, then the module does
something interesting.  It generates a single SQL statement that fetches
the records from the database in a single pass (rather than the multiple
passes required for an array slice) and returns the result as a reference
to an array.  For many records, this can be much faster.  For example:

     $result = $produce{apricots,bananas};
         => ARRAY(0x828a8ac)

     ($apricots,$bananas) = @$result;
     print "The price of apricots is $apricots->{price}";
         => The price of apricots is 0.85

   Field names work in much the same way:

     ($price,$quantity) = @{$produce{apricots}{price,quantity}};
     print "There are $quantity apricots at $price each";
         => There are 2 apricots at 0.85 each";

Updating information
--------------------

   If CLOBBER is set to a non-zero value (and the underlying database
privileges allow it), you can update the database with new values.  You
can operate on entire records at once or on individual fields within a
record.

   To insert a new record or update an existing one, assign a hash
reference to the record.  For example, you can create a new record in
%produce with the key "avocados" in this manner:

     $produce{avocados} = { price       => 2.00,
                            quantity    => 8,
                            description => 'Choice Irish avocados' };

   This will work with any type of hash reference, including records
extracted from another table or database.

   Only keys that correspond to valid fields in the table will be
accepted.  You will be warned if you attempt to set a field that doesn't
exist, but the other fields will be correctly set.  Likewise, you will be
warned if you attempt to set the key field.  These warnings can be turned
off by setting the WARN option to a zero value.  It is not currently
possible to add new columns to the table.  You must do this manually with
the appropriate SQL commands.

   The same syntax can be used to update an existing record.  The fields
given in the hash reference replace those in the record.  Fields that
aren't explicitly listed in the hash retain their previous values.  In the
following example, the price and quantity of the "kiwis" record are
updated, but the description remains the same:

     $produce{kiwis} = { price=>1.25,quantity=>20 };

   You may update existing records on a field-by-field manner in the
natural way:

     $produce{eggs}{price} = 1.30;
     $produce{eggs}{price} *= 2;
     print "The price of eggs is now $produce{eggs}{price}";
         => The price of eggs is now 2.6.

   Obligingly enough, you can use this syntax to insert new records too,
as in $produce{mangoes}{description}="Sun-ripened Idaho mangoes".
However, this type of update is inefficient because a separate SQL
statement is generated for each field.  If you need to update more than
one field at a time, use the record-oriented syntax shown earlier.  It's
much more efficient because it gets the work done with a single SQL
command.

   Insertions and updates may fail for any of a number of reasons, most
commonly:

  1. You do not have sufficient privileges to update the database

  2. The update would violate an integrity constraint, such as making a
     non-nullable field null, overflowing a numeric field, storing a
     string value in a numeric field, or violating a uniqueness constraint.
        The module dies with an error message when it encounters an error
during an update.  To trap these erorrs and continue processing, wrap the
update an eval().

Other functions
---------------

   The tie object supports several useful methods.  In order to call these
methods, you must either save the function result from the tie() call
(which returns the object), or call tied() on the tie variable to recover
the object.

connect(), error(), errstr()
     These are low-level class methods.  Connect() is responsible for
     establishing the connection with the DBI database.  Errstr() and
     error() return $DBI::errstr and $DBI::error respectively.  You may
     may override these methods in subclasses if you wish.  For example,
     replace connect() with this code in order to use persistent database
     connections in Apache modules:

          use Apache::DBI;  # somewhere in the declarations
          sub connect {
          my ($class,$dsn,$user,$password,$options) = @_;
             return Apache::DBI->connect($dsn,$user,
                                         $password,$options);
          }

commit()
          (tied %produce)->commit();

     When using a database with the autocommit option turned off, values
     that are stored into the hash will not become permanent until commit()
     is called.  Otherwise they are lost when the application terminates or
     the hash is untied.

     Some SQL databases don't support transactions, in which case you will
     see a warning message if you attempt to use this function.

rollback()
          (tied %produce)->rollback();

     When using a database with the autocommit option turned off, this
     function will roll back changes to the database to the state they were
     in at the last commit().  This function has no effect on database that
     don't support transactions.

select_where()
          @keys=(tied %produce)->select_where('price > 1.00 and quantity < 10');

     This executes a limited form of select statement on the tied table and
     returns a list of records that satisfy the conditions.  The argument
     you provide should be the contents of a SQL WHERE clause, minus the
     keyword "WHERE" and everything that ordinarily precedes it.  Anything
     that is legal in the WHERE clause is allowed, including function
     calls, ordering specifications, and sub-selects.  The keys to those
     records that meet the specified conditions are returned as an array,
     in the order in which the select statement returned them.

     Don't expect too much from this function.  If you want to execute a
     complex query, you're better off using the database handle (see below)
     to make the SQL query yourself with the DBI interface.

dbh()
          $dbh = (tied %produce)->dbh();

     This returns the tied hash's underlying database handle.  You can use
     this handle to create and execute your own SQL queries.

CLOBBER, DEBUG, WARN
     You can get and set the values of CLOBBER, DEBUG and WARN by directly
     accessing the object's hash:

          (tied %produce)->{DEBUG}++;

     This lets you change the behavior of the tied hash on the fly, such as
     temporarily granting your program write permission.

     There are other variables there too, such as the name of the key
     column and database table.  Change them at your own risk!

PERFORMANCE
===========

   What is the performance hit when you use this module rather than the
direct DBI interface?  It can be significant.  To measure the overhead, I
used a simple benchmark in which Perl parsed a 6180 word text file into
individual words and stored them into a database, incrementing the word
count with each store.  The benchmark then read out the words and their
counts in an each() loop.  The database driver was mySQL, running on a 133
MHz Pentium laptop with Linux 2.0.30.  I compared Tie::RDBM, to DB_File,
and to the same task using vanilla DBI SQL statements.  The results are
shown below:

     UPDATE         FETCH
       Tie::DBI      70 s        6.1  s
       Vanilla DBI   14 s        2.0  s
       DB_File        3 s        1.06 s

   There is about a five-fold penalty for updates, and a three-fold
penalty for fetches when using this interface.  Some of the penalty is due
to the overhead for creating sub-objects to handle individual fields, and
some of it is due to the inefficient way the store and fetch operations
are implemented.  For example, using the tie interface, a statement like
$h{record}{field}++ requires as much as four trips to the database: one to
verify that the record exists, one to fetch the field, and one to store
the incremented field back.  If the record doesn't already exist, an
additional statement is required to perform the insertion.  I have
experimented with cacheing schemes to reduce the number of trips to the
database, but the overhead of maintaining the cache is nearly equal to the
performance improvement, and cacheing raises a number of potential
concurrency problems.

   Clearly you would not want to use this interface for applications that
require a large number of updates to be processed rapidly.

BUGS
====

BUGS
====

   The each() call produces a fatal error when used with the Sybase driver
to access Microsoft SQL server. This is because this server only allows
one query to be active at a given time.  A workaround is to use keys() to
fetch all the keys yourself.  It is not known whether real Sybase
databases suffer from the same problem.

   The delete() operator will not work correctly for setting field values
to null with DBD::CSV or with DBD::Pg.  CSV files do not have a good
conception of database nulls.  Instead you will set the field to an empty
string.  DBD::Pg just seems to be broken in this regard.

AUTHOR
======

   Lincoln Stein, lstein@cshl.org

COPYRIGHT
=========

     Copyright (c) 1998, Lincoln D. Stein

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AVAILABILITY
============

   The latest version can be obtained from:

     http://www.genome.wi.mit.edu/~lstein/Tie-DBI/

SEE ALSO
========

   perl(1), DBI(3), Tie::RDBM(3)

A wrapper around the DB_File Berkeley database system
*****************************************************

NAME
====

   Tie::DB_File::SplitHash - A wrapper around the DB_File Berkeley
database system

SYNOPSIS
========

     use Tie::DB_File::SplitHash;

     [$X =] tie %hash,  'Tie::DB_File::SplitHash', $filename, $flags, $mode, $DB_HASH, $multi_n;

     $status = $X->del($key [, $flags]) ;
     $status = $X->put($key, $value [, $flags]) ;
     $status = $X->get($key, $value [, $flags]) ;
     $status = $X->seq($key, $value, $flags) ;
     $status = $X->sync([$flags]) ;
     $status = $X->fd ;

     untie %hash ;

   $multi_n determines the 'spread out' or number of files the hash will be
split between. The larger the number, the larger the final hash can be.

DESCRIPTION
===========

   Transparently splits a Berkeley database (DB_File) into multiple files
to allow the exceeding of file system limits on file size. From the
outside, it behaves identically with Berkeley DB hash support in general.
This has the potential to greatly expand the amount of data that can be
stored on a file size limitted file system.

   It does so by taking a SHA1 hash of the key to be stored, folding the
resulting hash into a value from 0 to X and storing the data to a db file
selected by the value 0 to X. The randomizing behavior of the SHA1 and
subsequent fold down distribute the records essentially randomly between
the X+1 database files, raising the capacity of the database to (X+1)
times the capacity of a single file database on the average.

   NOTE: Using an 'in-memory' database is not supported by this.  Use
DB_File directly if you want to do that. Additionally, BTREE and RECNO DBs
are not supported.

CHANGES
=======

   1.01 2000.03.06 - Removed 'dependancies' on built-ins that caused
'make' failures                   and added install tests.

`DESTROY;'
     Called when the tied object is being destroyed.

COPYRIGHT
=========

   Copyright 1999, Benjamin Franz (<URL:http://www.nihongo.org/snowhare/>)
and FreeRun Technologies, Inc. (<URL:http://www.freeruntech.com/>). All
Rights Reserved.  This software may be copied or redistributed under the
same terms as Perl itelf.

AUTHOR
======

   Benjamin Franz

TODO
====

   Testing.

VERSION
=======

   1.01 - 2000.03.06

Locking access to Berkeley DB 1.x
*********************************

NAME
====

   Tie::DB_FileLock - Locking access to Berkeley DB 1.x

SYNOPSIS
========

     use Tie::DB_FileLock;

     [$X =] tie %hash, 'Tie::DB_FileLock', [$file, $flags, $mode, $DB_HASH];
     [$X =] tie %hash, 'Tie::DB_FileLock', $file, $flags, $mode, $DB_BTREE;

     $X->debug($value);

     $status = $X->del($key [, $flags]);
     $status = $X->put($key, $value [, $flags]);
     $status = $X->get($key, $value [, $flags]);
     $status = $X->seq($key, $value, $flags);
     $status = $X->sync([$flags]);
     $status = $X->fd();

     # BTREE only
     $count = $X->get_dup($key);
     @list  = $X->get_dup($key);
     %list  = $X->get_dup($key, 1);
     $status = $X->find_dup($key, $value);
     $status = $X->del_dup($key, $value);

     # DBM Filters
     $old_filter = $db->filter_store_key  ( sub { ... } );
     $old_filter = $db->filter_store_value( sub { ... } );
     $old_filter = $db->filter_fetch_key  ( sub { ... } );
     $old_filter = $db->filter_fetch_value( sub { ... } );

     [undef $X;]
     untie %hash;

DESCRIPTION
===========

   Module DB_File allows perl to tie hashes to on-disk dbm files, but
fails to provide any method by which the hashes might be locked, providing
exclusive access or preventing page-level collisions.  Tie::DB_FileLock
extends DB_File, providing a locking layer using flock().

   Unlike Tie::DB_Lock, Tie::DB_FileLock does not duplicate files to allow
concurrent access for readers and writers.  Tie::DB_FileLock is therefore
suitable for large dbms with relatively short locking periods.

   Tie::DB_FileLock is designed as a drop-in replacement for DB_File,
requiring minimal code changes.  Change all occurrences of "DB_File" to
"Tie::DB_FileLock" and all should be well.  DB_RECNO is not presently
supported by Tie::DB_FileLock.

   Arguments to Tie::DB_FileLock are identical as those to DB_File.  The
dbm is locked for shared access if opened RO, exclusively otherwise.  The
default, as in DB_File, is read/write/create.

   Use of the predefined references $DB_HASH, $DB_BTREE, and $DB_RECNO, is
identical as with DB_File.  When creating your own, the new call is the
same, but the object created is a DB_File::XXX thing and not a
Tie::DB_FileLock::XXX thing - therefore error messages will refer to
DB_File::XXX.

LOCKING
=======

   The locking autoline presented by 'Programming Perl' is incorrect for
multiple simultaneous writers.  The problem is that a successful flock()
lags the tie() by some amount of time.  However the snapshot of the
on-disk dbm is that from the time of the tie() and not of the flock(),
therefore once the flock() succeeds, the dbm may have changed and
therefore must be tie()ed again, loading the latest state of the dbm.

   Locking cannot be at the level of methods like FETCH() and STORE()
because then statements like $hash{$a}++ are not atomic: that is, a
different access could (will) take place between the FETCH($a) and the
STORE($a + 1).

   Therefore locking must occur at a coarser level and the programmer must
not dawdle when locks are active.  In the case of loops, an effort need be
made to untie() the dbm periodically, permitting other processes their
due.  At some additional cost, a program may yield access to others by
breaking a loop like:

     tie(%db, 'Tie::DB_FileLock', "arg1.db");
     foreach (1..10000) { accesses; }
     untie(%db);

   into:

     my $dbobj = tie(%db, 'Tie::DB_FileLock', "arg1.db");
     foreach (1..10000) {
       accesses;
       if ($_ % 100 == 0) {
          $dbobj->unlockDB();
          $dbobj->lockDB();
       }
     }
     untie(%db);

SPEED
=====

   The first law of thermodynamics holds true for object methods.  Access
through DB_FileLock is slower than through DB_File.  Working with a 40meg
dbm containing 110k records, we find

     Keys	Values	Store
     	DB_File		30s	35s	55s
     	DB_FileLock	40s	45s	60s

   All values +/- ~3s.  YMMV.  Previous versions of DB_FileLock had a very
inefficient FIRSTKEY() routine.

AUTHOR
======

   John M Vinopal, banshee@resort.com

SEE ALSO
========

   DB_File(3p).

ties hashes to databases using shared and exclusive locks
*********************************************************

NAME
====

   Tie::DB_Lock - ties hashes to databases using shared and exclusive locks

SYNOPSIS
========

     use Tie::DB_Lock;
     use DB_File;

     tie(%hash, 'Tie::DB_Lock', $filename, 'rw');  # Open for writing
     $hash{'key'} = 'value';
     untie %hash;

     tie(%hash2, 'Tie::DB_Lock', $filename); # Default is read-only
     print("Value is $hash2{'key'}\n");
     untie %hash;

DESCRIPTION
===========

   This is a front-end for the DB_File package.

   If you tie a hash in read-only mode, this module puts a shared lock on
the database file, copies it to a temporary file, unlocks the original
database, and then ties the tempfile using DB_File.

   If you tie the hash in read-write mode, we put an exclusive lock on the
database and tie it directly using DB_File.

   The reason I copy the whole file every time I read from it is that this
allows the program to read from the file for as long as it wants to,
without interfering with other people's writes.  This works well if you
typically have long, sustained reads, and short, bursty writes.  See the
README file for help in deciding whether you want to use this package.

   You don't always need to call untie() explicitly - it will be called for
you when %hash goes out of scope.  And if all goes as planned, you'll never
know the temporary file ever existed, since it will evaporate when %hash
goes away.

OPTIONS
=======

   * $Tie::DB_Lock::TEMPDIR

     You can specify the directory in which to place the temporary files
     that get created when you open a database for read-only access.  To
     do so, set the variable `$Tie::DB_Lock::TEMPDIR' to the directory you
     want to use.  You may get the best results if your temporary
     directory resides on the same disk (or filesystem) as your databases.

   * $Tie::DB_Lock::WAIT_TIME

   * $Tie::DB_Lock::RETRIES

     By default, DB_Lock will try once every second for fifteen seconds to
     put locks on the things it's trying to lock.  After that it will give
     up.  Change the number of seconds between attempts by setting the
     value of `$Tie::DB_Lock::WAIT_TIME' (must be an integer), and change
     the number of attempts by setting the value of
     `$Tie::DB_Lock::RETRIES'.

   * $Tie::DB_Lock::VERBOSE

     If you think something funny is going on with your database and you
     want to watch the locking process happening, you can set the variable
     `$Tie::DB_Lock::VERBOSE' to a true value.  A bunch of diagnostic
     messages will get printed to STDERR.

   * $Tie::DB_Lock::TIEPACK

     Don't change this unless you're sure.  If you change it, DB_Lock will
     use a different back-end database TIEHASH package instead of DB_File.
     Any database you want to use must reside entirely in a single file
     so that it can be locked properly and copied to the temporary
     directory.

WARNINGS
========

   Whenever a tie() fails because a lock blocked your access, tie() will
return the undefined value.  CHECK THE RETURN VALUE from tie()!

     tie(%hash, 'Tie::DB_Lock', $file, 'rw') or die $!;

   If you don't check the return value, you'll probably continue on your
merry way, thinking that you opened the database when in fact you didn't.

A NOTE ON DEADLOCK, by Jay Scott
================================

   Deadlock is rare, but it's awful when it happens.

   If each process wants more than one DB file before it can start work,
and processes do not all ask for their DB files in the same order, and the
processes write, then there's a risk of deadlock. The simplest case is
that process 1 wants files A and B and holds A, and process 2 wants A and
B and holds B. Neither process can get what it needs, and they both wait
forever. To avoid this, do one of the following: (1) Have all processes
open DB files in the same order, first A, then B. (2) Use a special
locking or coordination scheme.

   Deadlock can happen pretty much whenever you're using locks on a
resource.

TO DO
=====

     Maybe change from using FileHandle to IO::File?  Benchmarks involved.

     Allow other database back-ends than DB_File.

AUTHOR
======

   Ken Williams				ken@forum.swarthmore.edu

   Copyright (c) 1998 Ken Williams. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   perl(1), perltie(1), perlfunc(1), DB_File(3)

class definition for reading directories via a tied hash
********************************************************

NAME
====

   Tie::Dir - class definition for reading directories via a tied hash

SYNOPSIS
========

     use Tie::Dir qw(DIR_UNLINK);

     # Both of these produce identical results
     #(ie %hash is tied)
     tie %hash, Tie::Dir, ".", DIR_UNLINK;
     new Tie::Dir \%hash, ".", DIR_UNLINK;

     # This creates a reference to a hash, which is tied.
     $hash = new Tie::Dir ".";

     # All these examples assume that %hash is tied (ie one of the
     # first two tie methods was used

     # itterate through the directory
     foreach $file ( keys %hash ) {
     	...
     }

     # Set the access and modification times (touch :-)
     $hash{SomeFile} = time;

     # Obtain stat information of a file
     @stat = @{$hash{SomeFile}};

     # Check if entry exists
     if(exists $hash{SomeFile}) {
     	...
     }

     # Delete an entry, only if DIR_UNLINK specified
     delete $hash{SomeFile};

DESCRIPTION
===========

   This module provides a method of reading directories using a hash.

   The keys of the hash are the directory entries and the values are a
reference to an array which holds the result of stat being called on the
entry.

   The access and modification times of an entry can be changed by
assigning to an element of the hash. If a single number is assigned then
the access and modification times will both be set to the same value,
alternatively the access and modification times may be set separetly by
passing a reference to an array with 2 entries, the first being the access
time and the second being the modification time.

new [hashref,] dirname [, options]
     This method ties the hash referenced by `hashref' to the directory
     `dirname'.  If `hashref' is omitted then new returns a reference to a
     hash which hash been tied, otherwise it returns the result of tie

     The possible options are:

    DIR_UNLINK
          Delete operations on the hash will cause unlink to be called on
          the corresponding file

AUTHOR
======

   Graham Barr <bodg@tiuk.ti.com>, from a quick hack posted by Kenneth
Albanowski <kjahds@kjahds.com>  to the perl5-porters mailing list based on
a neat idea by Ilya Zakharevich.

Perl extension for `Discovery' hashes
*************************************

NAME
====

   Tie::Discovery - Perl extension for `Discovery' hashes

SYNOPSIS
========

     use Tie::Discovery;
     my %config = ();
     my $obj = tie %config, "Tie::Discovery";

     sub discover_os { ... }
     $obj->register("os",\&discover_os);

     $config{os};

DESCRIPTION
===========

   A `discovery' hash is a hash that's designed to help you solve the data
dependency problem. It's based on the principle of least work; some times,
you may spend a lot of time in your program finding out paths, filenames,
operating system specifics, network information and so on that you may not
end up using. Discovery hashes allow you to get the data when you need it,
and only when you need it.

   To use a discovery hash, first tie a hash as shown above. You will want
to keep hold of the object returned by tie. You can then add things to
discover by calling the register method as shown above. The above code
`$obj->register("os",\&discover_os);' means that when (and only when!) the
value `$config{os}' is fetched, the sub `&discover_os' will be called to
find it. The return value of that sub will then be cached to save a
look-up next time.

   The real power comes from the fact that you may refer to the tied hash
inside of the discovery subroutines. This allows for fast, neat and
flexible top-down programming, and helps you avoid hard-coding values.
For instance, let us find the OS by calling the uname program.

     $obj->register( os => sub { `$config{path_to_uname}` } );

   Now we need code to find the program itself:

     use File::Spec::Functions;
     $obj->register( path_to_uname => sub {
     	foreach (path) {
     		return catfile($_,"uname") if -x catfile($_,"uname")
     	}
     	die "Couldn't even find uname"
     };

   Fetching `$config{os}' may now need a further call to fetch
`$config{path_to_uname}' unless the path is already cached. And, of
course, we needn't stop at two levels.

   Fuller examples of this technique are seen in the forthcoming `CTAN' in
this node and `SysConf' in this node modules.

METHODS
-------

   Aside from the usual hash methods, the following are available:

register(name,sub)
     Registers name as an entry in the hash, to be discovered by running
     sub

store(name,value)
     Stores value directly into the hash under the name key. The only time
     you should need to do this is to set the value of the debug key; if
     set, this shows a trace of the discovery process.

EXPORT
------

   Nothing.

LIMITATIONS
-----------

   At present, since a subroutine reference signifies something to look
up, you can't usefully return one from your discovery subroutine.

AUTHOR
======

   Simon Cozens <simon@cpan.org>

SEE ALSO
========

   perl(1), see Tie/Hash,

Hashes (and objects based on hashes) with encrypting fields.
************************************************************

NAME
====

   Tie::EncryptedHash - Hashes (and objects based on hashes) with
encrypting fields.

SYNOPSIS
========

     use Tie::EncryptedHash;

     my %s = ();
     tie %s, Tie::EncryptedHash, 'passwd';

     $s{foo}  = "plaintext";     # Normal field, stored in plaintext.
     print $s{foo};              # (plaintext)

     $s{_bar} = "signature";     # Fieldnames that begin in single
                                 # underscore are encrypted.
     print $s{_bar};             # (signature)  Though, while the password
                                 # is set, they behave like normal fields.
     delete $s{__password};      # Delete password to disable access
                                 # to encrypting fields.
     print $s{_bar};             # (Blowfish NuRVFIr8UCAJu5AWY0w...)

     $s{__password} = 'passwd';  # Restore password to gain access.
     print $s{_bar};             # (signature)

     $s{_baz}{a}{b} = 42;        # Refs are fine, we encrypt them too.

DESCRIPTION
===========

   Tie::EncryptedHash augments Perl hash semantics to build secure,
encrypting containers of data.  Tie::EncryptedHash introduces special hash
fields that are coupled with encrypt/decrypt routines to encrypt
assignments at STORE() and decrypt retrievals at FETCH().  By design,
*encrypting fields* are associated with keys that begin in single
underscore.  The remaining keyspace is used for accessing normal hash
fields, which are retained without modification.

   While the password is set, a Tie::EncryptedHash behaves exactly like a
standard Perl hash.  This is its *transparent mode* of access.  Encrypting
and normal fields are identical in this mode.  When password is deleted,
encrypting fields are accessible only as ciphertext.  This is
Tie::EncryptedHash's *opaque mode* of access, optimized for serialization.

   Encryption is done with Crypt::CBC(3) which encrypts in the cipher block
chaining mode with Blowfish, DES or IDEA.  Tie::EncryptedHash uses Blowfish
by default, but can be instructed to employ any cipher supported by
Crypt::CBC(3).

MOTIVATION
==========

   Tie::EncryptedHash was designed for storage and communication of key
material used in public key cryptography algorithms.  I abstracted out the
mechanism for encrypting selected fields of a structured data record
because of the sheer convenience of this data security method.

   Quite often, applications that require data confidentiality eschew
strong cryptography in favor of OS-based access control mechanisms because
of the additional costs of cryptography integration.  Besides cipher
implementations, which are available as ready-to-deploy perl modules, use
of cryptography in an application requires code to aid conversion and
representation of encrypted data.  This code is usually encapsulated in a
data access layer that manages encryption, decryption, access control and
re-structuring of flat plaintext according to a data model.
Tie::EncryptedHash provides these functions under the disguise of a Perl
hash so perl applications can use strong cryptography without the cost of
implementing a complex data access layer.

CONSTRUCTION
============

Tied Hash
---------

   `tie %h, Tie::EncryptedHash, 'Password', 'Cipher';'

   Ties %h to Tie::EncryptedHash and sets the value of password and cipher
to 'Password' and 'Cipher'.  Both arguments are optional.

Blessed Object
--------------

   `$h = new Tie::EncryptedHash __password =' 'Password',
       __cipher => 'Cipher';>

   The new() constructor returns an object that is both tied and blessed
into Tie::EncryptedHash.  Both arguments are optional.  When used in this
manner, Tie::EncryptedHash behaves like a class with encrypting data
members.

RESERVED ATTRIBUTES
===================

   The attributes __password, __cipher and __hide are reserved for
communication with object methods.  They are "write-only" from everywhere
except the class to which the hash is tied.  __scaffolding is inaccessible.
Tie::EncryptedHash stores the current encryption password and some
transient data structures in these fields and restricts access to them on
need-to-know basis.

__password
----------

   `$h{__password} = "new password"; delete $h{__password};'

   The password is stored under the attribute __password.  In addition to
specifying a password at construction, assigning to the __password
attribute sets the current encryption password to the assigned value.
Deleting the __password unsets it and switches the hash into opaque mode.

__cipher
--------

   `$h{__cipher} = 'DES'; $h{__cipher} = 'Blowfish';'

   The cipher used for encryption/decryption is stored under the attribute
__cipher.  The value defaults to 'Blowfish'.

__hide
------

   `$h{__hide} = 1;'

   Setting this attribute *hides* encrypting fields in opaque mode.
'undef' is returned at FETCH() and EXISTS().

BEHAVIOR
========

References
----------

   A reference stored in an encrypting field is serialized before
encryption.  The data structure represented by the reference is folded
into a single line of ciphertext which is stored under the first level
key.  In the opaque mode, therefore, only the first level of keys of the
hash will be visible.

Opaque Mode
-----------

   The opaque mode introduces several other constraints on access of
encrypting fields.  Encrypting fields return ciphertext on FETCH() unless
__hide attribute is set, which forces Tie::EncryptedHash to behave as if
encrypting fields don't exist.  Irrespective of __hide, however, DELETE()
and CLEAR() fail in opaque mode.  So does STORE() on an existing
encrypting field.  Plaintext assignments to encrypting fields are silently
ignored, but ciphertext assignments are fine.  Ciphertext assignments can
be used to move data between different EncryptedHashes.

Multiple Passwords and Ciphers
------------------------------

   Modality of Tie::EncryptedHash's access system breaks down when more
than one password is used to with different encrypting fields.  This is a
feature.  Tie::EncryptedHash lets you mix passwords and ciphers in the same
hash.  Assign new values to __password and __cipher and create a new
encrypting field.  Transparent mode will be restricted to fields encrypted
with the current password.

Error Handling
--------------

   Tie::Encrypted silently ignores access errors.  It doesn't carp/croak
when you perform an illegal operation (like assign plaintext to an
encrypting field in opaque mode).  This is to prevent data lossage, the
kind that results from abnormal termination of applications.

QUIRKS
======

Autovivification
----------------

   Due to the nature of autovivified references (which spring into
existence when an undefined reference is dereferenced), references are
stored as plaintext in transparent mode.  Analogous ciphertext
representations are maintained in parallel and restored to encrypting
fields when password is deleted.  This process is completely transparent
to the user, though it's advisable to delete the password after the final
assignment to a Tie::EncryptedHash.  This ensures plaintext
representations and scaffolding data structures are duly flushed.

Data::Dumper
------------

   Serialization of references is done with Data::Dumper, therefore the
nature of data that can be assigned to encrypting fields is limited by what
Data::Dumper can grok.  We set $Data::Dumper::Purity = 1, so
self-referential and recursive structures should be OK.

Speed
-----

   Tie::EncryptedHash'es keep their contents encrypted as much as
possible, so there's a rather severe speed penalty.  With Blowfish,
STORE() on EncryptedHash can be upto 70 times slower than a standard perl
hash.  Reference STORE()'es will be quicker, but speed gain will be
adjusted at FETCH().  FETCH() is about 35 times slower than a standard
perl hash.  DES affords speed improvements of upto 2x, but is not
considered secure for long-term storage of data.  These values were
computed on a DELL PIII-300 Mhz notebook with 128 Mb RAM running perl
5.003 on Linux 2.2.16.  Variations in speed might be different on your
machine.

STANDARD USAGE
==============

   The standard usage for this module would be something along the lines
of: populate Tie::EncryptedHash with sensitive data, delete the password,
serialize the encrypted hash with Data::Dumper, store the result on disk or
send it over the wire to another machine.  Later, when the sensitive data
is required, procure the EncryptedHash, set the password and accesses the
encrypted data fields.

SEE ALSO
========

   Data::Dumper(3), Crypt::CBC(3), Crypt::DES(3), Crypt::Blowfish(3),
Tie::SecureHash(3)

ACKNOWLEDGEMENTS
================

   The framework of Tie::EncryptedHash derives heavily from Damian Conway's
Tie::SecureHash.  Objects that are blessed as well as tied are just one of
the pleasant side-effects of stealing Damian's code.  Thanks to Damian for
this brilliant module.

   PacificNet (http://www.pacificnet.net) loaned me the aforementioned
notebook to hack from the comfort of my bed.  Thanks folks!

AUTHOR
======

   Vipul Ved Prakash <mail@vipul.net>

LICENSE
=======

   Artistic.

A lightweight but robust filesystem based persistent LRU cache
**************************************************************

NAME
====

   Tie::FileLRUCache - A lightweight but robust filesystem based
persistent LRU cache

CHANGES
=======

   1.01 19991209 Added 'detainting' to cache management code.

SYNOPSIS
========

OBJECT INTERFACE
----------------

     use Tie::FileLRUCache;
     my $cache = Tie::FileLRUCache->new({ -cache_dir => $directory, -keep_last => 100 });

     # Inserting value into LRU cache using '-key'
     $cache->update({ -key => $key, -value => $value });

     # Inserting value into LRU cache using '-cache_key'
     my $cache_key = $cache->make_cache_key({ -key => $key });
     $cache->update({ -cache_key => $cache_key, -value => $value });

     # Checking LRU cache
     my ($in_cache,$value) = $cache->check({ -key => $key });
     if ($in_cache) {
         return $value;
     }
     # Not in cache - do something else

     # Checking LRU cache with speed up hack for objects, hashes, arrays etc used as keys
     my $cache_key = $cache->make_cache_key({ -key => $something });
     my ($in_cache,$value) = $cache->check({ -cache_key => $cache_key });
     if ($in_cache) {
         return $value;
     }
     # Not in cache - do something else

     # Deleting a key and its value from the cache
     $cache->delete({ -key => $key });

     # Clearing LRU cache
     $cache->clear;

TIED INTERFACE
--------------

     use Tie::FileLRUCache;

     [$X =] tie %hash,  'Tie::FileLRUCache', $cache_dir, $keep_last_n;

     # Adding a key/value to the cache
     $hash{$key} = $value;

     # Checking the cache
     if (not exists $hash{$key}) {;
         # No match
           .
           .
           .

     } else {
         my $value = $hash{$key};
           .
           .
           .

     }

     # Removing a value from the cache;
     delete $hash{$key};

     # Clearing the cache
     %hash = ();

     Note: Iteration over the cache (each, keys, values) is _NOT_
     supported.

DESCRIPTION
===========

   Provides a persistent filesystem based LRU cache.

   It uses the 'last accessed' timestamp generated by the file system to
determine the 'oldest' cache entry and discards the oldest cache entries
when needed to stay under the -keep_last limit.

   If you store thing very fast (such that many entries receive the _same_
time stamp), it is essentially a coin toss which entry within a single
timestamped second gets purged from the cache to make room for new ones.

OBJECT METHODS
==============

`new($parm_ref);'
     Creates and optionally initializes a Tie::FileLRUCache object:

     Example:

          my $cache = Tie::FileLRUCache->new({
                               -cache_dir => '/tmp/testing',
                               -keep_last => 100,
                             });

`check($parm_ref);'
     Reads the cache for the key.

     Returns two values: $cache_hit (true if a hit was found, false if not)
                        $value     (the cached value, undef if no hit)

     Examples:

          my ($cache_hit,$value) = $cache->check({ -key => $key });

          my ($cache_hit,$value) = $cache->check({ -cache_key => $cache_key });

     The '-key' form is used when you just want to use a raw key. It can
     use blessed objects, hash refs, scalars, or array refs as keys. The
     more complex structures take a speed penalty for computing a
     canonical form.  You can minimize this penalty by using the
     '-cache_key' form instead.

     The '-cache_key' form is used for performance reasons when using keys
     such as complex blessed objects or hashes as a key. The -cache_key is
     obtained with a call to 'make_cache_key'. It is legal to mix
     -cache_key and -key based calls - they are cross-compatible.

`make_cache_key($parm_ref);'
     Generates a cache key by canonicalizing a passed key as a network
     ordered canonical Storable string.

     Example:

          my $cache_key = $cache->make_cache_key({ -key => $key });

`clear;'
     Completely clears the cache.

`update($parm_ref);'
     Updates the Least Recently Used cache for the specified key with the
     passed value.  '-keep_last' is optional after the first access to a
     dataset. It will use the _most recent_ 'keep_last' used if not
     specified.

     It is legal to use ordinary scalars, hash references, or array
     references as keys as well as objects as -keys or -values.
     Basically, anything that Storable can serialize can be used.

     Examples:

          $cache->update({ -key => $key, -value => $value });

          $cache->update({ -key => $key, -value => $value, -keep_last => 100});

          my $cache_key = $cache->make_cache_key({ -key => $key });
          $cache->update({ -cache_key => $cache_key, -value => $value });

          my $cache_key = $cache->make_cache_key({ -key => $key });
          $cache->update({ -cache_key => $cache_key, -value => $value, -keep_last => 50 });

`delete($parm_ref);'
     Forces the deletion of a specific key from the cache.

     Example:

          $cache->delete({ -key => $key });

COPYRIGHT
=========

   Copyright 1999, Benjamin Franz (<URL:http://www.nihongo.org/snowhare/>)
and FreeRun Technologies, Inc. (<URL:http://www.freeruntech.com/>). All
Rights Reserved.  This software may be copied or redistributed under the
same terms as Perl itelf.

AUTHOR
======

   Benjamin Franz

TODO
====

   Debugging.

Alternate between two values.
*****************************

NAME
====

   Tie::FlipFlop - Alternate between two values.

SYNOPSIS
========

     use Tie::FlipFlop;

     tie my $flipflop => Tie::FlipFlop => qw /Red Green/;

     print  $flipflop;      # Prints 'Red'.
     print  $flipflop;      # Prints 'Green'.
     print  $flipflop;      # Prints 'Red'.

DESCRIPTION
===========

   `Tie::FlipFlop' allows you to tie a scalar in such a way that refering
to the scalar alternates between two values. When tying the scalar, exactly
two extra arguments have to be given, the values to be alternated between.

   Assigning to the scalar leads to a fatal, but trappable, error.

REVISION HISTORY
================

     $Log: FlipFlop.pm,v $
     Revision 1.1  1999/07/19 22:07:22  abigail
     Initial revision

AUTHOR
======

   This package was written by Abigail.

COPYRIGHT and LICENSE
=====================

   This package is copyright 1999 by Abigail.

   This program is free and open software. You may use, copy, modify,
distribute and sell this program (and any modified variants) in any way
you wish, provided you do not restrict others to do the same.

base class definitions for tied handles
***************************************

NAME
====

   Tie::Handle, Tie::StdHandle  - base class definitions for tied handles

SYNOPSIS
========

     package NewHandle;
     require Tie::Handle;

     @ISA = (Tie::Handle);

     sub READ { ... }		# Provide a needed method
     sub TIEHANDLE { ... }	# Overrides inherited method

     package main;

     tie *FH, 'NewHandle';

DESCRIPTION
===========

   This module provides some skeletal methods for handle-tying classes. See
Perltie (perl.info), for a list of the functions required in
tying a handle to a package.  The basic Tie::Handle package provides a new
method, as well as methods TIEHANDLE, PRINT, PRINTF and GETC.

   For developers wishing to write their own tied-handle classes, the
methods are summarized below. The Perltie (perl.info),
section not only documents these, but has sample code as well:

TIEHANDLE classname, LIST
     The method invoked by the command `tie *glob, classname'. Associates
     a new glob instance with the specified class. LIST would represent
     additional arguments (along the lines of AnyDBM_File,
     and compatriots) needed to complete the association.

WRITE this, scalar, length, offset
     Write length bytes of data from scalar starting at offset.

PRINT this, LIST
     Print the values in LIST

PRINTF this, format, LIST
     Print the values in LIST using format

READ this, scalar, length, offset
     Read length bytes of data into scalar starting at offset.

READLINE this
     Read a single line

GETC this
     Get a single character

CLOSE this
     Close the handle

OPEN this, filename
     (Re-)open the handle

BINMODE this
     Specify content is binary

EOF this
     Test for end of file.

TELL this
     Return position in the file.

SEEK this, offset, whence
     Position the file.

     Test for end of file.

DESTROY this
     Free the storage associated with the tied handle referenced by *this*.
     This is rarely needed, as Perl manages its memory quite well. But the
     option exists, should a class wish to perform specific actions upon
     the destruction of an instance.

MORE INFORMATION
================

   The Perltie (perl.info), section contains an example of
tying handles.

base class definitions for tied hashes
**************************************

NAME
====

   Tie::Hash, Tie::StdHash - base class definitions for tied hashes

SYNOPSIS
========

     package NewHash;
     require Tie::Hash;

     @ISA = (Tie::Hash);

     sub DELETE { ... }		# Provides needed method
     sub CLEAR { ... }		# Overrides inherited method

     package NewStdHash;
     require Tie::Hash;

     @ISA = (Tie::StdHash);

     # All methods provided by default, define only those needing overrides
     sub DELETE { ... }

     package main;

     tie %new_hash, 'NewHash';
     tie %new_std_hash, 'NewStdHash';

DESCRIPTION
===========

   This module provides some skeletal methods for hash-tying classes. See
Perltie (perl.info), for a list of the functions required in
order to tie a hash to a package. The basic Tie::Hash package provides a
new method, as well as methods TIEHASH, EXISTS and CLEAR. The
*Tie::StdHash* package provides most methods required for hashes in
Perltie (perl.info). It inherits from Tie::Hash, and causes tied
hashes to behave exactly like standard hashes, allowing for selective
overloading of methods. The new method is provided as grandfathering in
the case a class forgets to include a TIEHASH method.

   For developers wishing to write their own tied hashes, the required
methods are briefly defined below. See the Perltie (perl.info),
section for more detailed descriptive, as well as
example code:

TIEHASH classname, LIST
     The method invoked by the command `tie %hash, classname'. Associates
     a new hash instance with the specified class. LIST would represent
     additional arguments (along the lines of AnyDBM_File,
     and compatriots) needed to complete the association.

STORE this, key, value
     Store datum value into key for the tied hash *this*.

FETCH this, key
     Retrieve the datum in key for the tied hash *this*.

FIRSTKEY this
     Return the (key, value) pair for the first key in the hash.

NEXTKEY this, lastkey
     Return the next key for the hash.

EXISTS this, key
     Verify that key exists with the tied hash *this*.

     The Tie::Hash implementation is a stub that simply croaks.

DELETE this, key
     Delete the key key from the tied hash *this*.

CLEAR this
     Clear all values from the tied hash *this*.

CAVEATS
=======

   The Perltie (perl.info), documentation includes a method
called DESTROY as a necessary method for tied hashes. Neither Tie::Hash
nor *Tie::StdHash* define a default for this method. This is a standard
for class packages, but may be omitted in favor of a simple default.

MORE INFORMATION
================

   The packages relating to various DBM-related implementations (DB_File,
`NDBM_File', etc.) show examples of general tied hashes, as does the
Config, module. While these do not utilize Tie::Hash, they serve as
good working examples.

Let a hash have default values
******************************

NAME
====

   Tie::HashDefaults - Let a hash have default values

SYNOPSIS
========

     use Tie::HashDefaults;

     tie %h, 'Tie::HashDefaults', \%defaults1, \%defaults0;

DESCRIPTION
===========

   This creates a data structure which is essentially an array of hashes;
this list contains all the hashes (passed by ref) in the argument list;
but it also contains a new, internally created, anonymous hash.  This hash
is used to store any insertions into the tied hash.

   Whenever a fetch (or an exists) is done on the tied hash, the requested
key is searched for in each hash in the list, beginning with the internal
"storage" hash; if it is not found in that hash, the key is looked for in
the first default hash, then the next, and so on, until it is found in one
of them, or there are none left to search.

   When an iteration (keys or each) is done on the tied hash, the set of
keys returned is the union of keys from all of the default hashes, along
with the storage hash.

   For operations that alter a hash - store, delete, clear - the default
hashes are never touched.  Only the storage hash is cleared.  One effect
of this is that if the tied hash is cleared, e.g. via `%h = ();', and
immediately following that an iteration is started (via keys or each), it
is likely that some keys will be returned.  (Unless, of course, there is
no data in any of the given default hashes.)

Manipulating the Defaults List
------------------------------

   The list of default hashes can be manipulated directly.  To do this, a
special method on the tied object returns an array, by reference,
containing the list of default hashes.  Any changes to this array are
reflected inside the Tie::HashDefaults object.  For example, to add another
defaults source that takes precedence over the others already on the list:

     unshift @{ tied(%h)->get_defaults_list }, \%new_default_source;

   Or, to reverse the order in which the defaults are consulted:

     $ar = tied(%h)->get_defaults_list;
     @$ar = reverse @$ar;

   (Once you have the array-ref "handle" on the defaults list array, it's
good for as long as the tied object stays tied.)

   NOTE: calling `get_defaults_list' also resets the iterator; so don't
call it within an each loop on a hash tied to this class.

AUTHOR
======

   jdporter@min.net (John Porter)

COPYRIGHT
=========

   This is free software.  This software may be modified and distributed
under the same terms as Perl itself.

provides a tied array of packed integers of any bit length
**********************************************************

NAME
====

   Tie::IntegerArray - provides a tied array of packed integers of any bit
length

SYNOPSIS
========

     use Tie::IntegerArray;

     # an array of signed 16-bit integers with no undef support and
     # starting room for 100,000 items.  You can expect this to consume a
     # bit more than 200K of memory versus more than 800K for a normal
     # Perl array.
     my @integer_array;
     tie @integer_array, 'Tie::IntegerArray',
        bits => 16,
        signed => 1,
        undef => 0,
        size => 100_000;

     # put a value in
     $integer_array[0] = 10;

     # and print it out
     print "Int 0: $integer_array[0]\n";

     # the full range of array operations are available

DESCRIPTION
===========

   This module provides an array interface to packed array of integers.  A
packed array of integers is useful in situations where you need to store a
large set of integers in as small a space as possible.  Access to the
packed array will be significantly slower than access to a normal array
but for many applications the reduction in memory usage makes this a good
trade-off.

USAGE
=====

   To create an IntegerArray you call tie with a number of optional
arguements.  These arguements let you fine-tune the storage of your
integers.  The simplest tie call uses no options:

     my @integer_array;
     tie @integer_array, 'Tie::IntegerArray';

   This will create an array of signed integers with the same size as
native ints on your platform.  By default the array does not support undef
- values are 0 by default.  This may be ideal for many applications - read
below for other options.

OPTIONS
=======

   * bits (defaults to your machine's int size)

     This option specifies how many bits to use to store the integer value.
     This setting determines the possible range of your integers.  If you
     specify unsigned integers (see below) then the maximum range on your
     integers is simply 2^bits.  For example, 8 bits provides an unsigned
     range of 0 - 255.

     Since the integers are stored in a packed array you can calculate the
     size of your array by multiplying the number of items by the number of
     bits.

     Attempting to store a value into the array that is too large or too
     small for the available bit size will cause an error.

   * signed (defaults to 1)

     If you set signed to 1 then your integers will be signed.  This
     reduces their positive range by a power of 2 but provides equal
     negative range.  For example, an 8 bit signed integer has a range from
     -128 - 127.

   * undef (defaults to 0)

     By default IntegerArrays do not support undef.  This means that array
     values will be 0 until they are set to some value.  Calling defined()
     on an array value will return true if exists() will.  You can change
     this by setting undef to 1.  This requires extra memory - 1 bit per
     array entry.

   * size (defaults to 1)

     IntegerArrays grow automatically as you add items but you can specify
     a size arguement to pre-allocate space.  This will improve performance
     for large arrays.

FUTURE PLANS
============

   This module is functionally complete but not yet fully optimized.  It
relies on Tie::Array for the more advanced array functions (push, pop,
etc) and a native implementation could be faster.  If this module proves
at all popular then I will definitely move in that direction.

CREDITS
=======

   Steffen Beyer - Bit::Vector is pure magic.

AUTHOR
======

   Sam Tregar, sam@tregar.com

LICENSE
=======

   HTML::Template : A module for using HTML Templates with Perl Copyright
(C) 2000 Sam Tregar (sam@tregar.com)

   This module is free software; you can redistribute it and/or modify it
under the terms of either:

   a) the GNU General Public License as published by the Free Software
Foundation; either version 1, or (at your option) any later version, or

   b) the "Artistic License" which comes with this module.

   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 either the GNU General Public
License or the Artistic License for more details.

   You should have received a copy of the Artistic License with this
module, in the file ARTISTIC.  If not, I'll be glad to provide one.

   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

SEE ALSO
========

   Bit::Vector

ordered associative arrays for Perl
***********************************

NAME
====

   Tie::IxHash - ordered associative arrays for Perl

SYNOPSIS
========

     # simple usage
     use Tie::IxHash;
     tie HASHVARIABLE, Tie::IxHash [, LIST];

     # OO interface with more powerful features
     use Tie::IxHash;
     TIEOBJECT = Tie::IxHash->new( [LIST] );
     TIEOBJECT->Splice( OFFSET [, LENGTH [, LIST]] );
     TIEOBJECT->Push( LIST );
     TIEOBJECT->Pop;
     TIEOBJECT->Shift;
     TIEOBJECT->Unshift( LIST );
     TIEOBJECT->Keys( [LIST] );
     TIEOBJECT->Values( [LIST] );
     TIEOBJECT->Indices( LIST );
     TIEOBJECT->Delete( [LIST] );
     TIEOBJECT->Replace( OFFSET, VALUE, [KEY] );
     TIEOBJECT->Reorder( LIST );
     TIEOBJECT->SortByKey;
     TIEOBJECT->SortByValue;
     TIEOBJECT->Length;

DESCRIPTION
===========

   This Perl module implements Perl hashes that preserve the order in
which the hash elements were added.  The order is not affected when values
corresponding to existing keys in the IxHash are changed.  The elements can
also be set to any arbitrary supplied order.  The familiar perl array
operations can also be performed on the IxHash.

Standard TIEHASH Interface
--------------------------

   The standard TIEHASH mechanism is available. This interface is
recommended for simple uses, since the usage is exactly the same as
regular Perl hashes after the tie is declared.

Object Interface
----------------

   This module also provides an extended object-oriented interface that
can be used for more powerful operations with the IxHash.  The following
methods are available:

FETCH, STORE, DELETE, EXISTS
     These standard TIEHASH methods mandated by Perl can be used directly.
     See the tie entry in perlfunc(1) for details.

Push, Pop, Shift, Unshift, Splice
     These additional methods resembling Perl functions are available for
     operating on key-value pairs in the IxHash. The behavior is the same
     as the corresponding perl functions, except when a supplied hash key
     already exists in the hash. In that case, the existing value is
     updated but its order is not affected.  To unconditionally alter the
     order of a supplied key-value pair, first DELETE the IxHash element.

Keys
     Returns an array of IxHash element keys corresponding to the list of
     supplied indices.  Returns an array of all the keys if called without
     arguments.  Note the return value is mostly only useful when used in
     a list context (since perl will convert it to the number of elements
     in the array when used in a scalar context, and that may not be very
     useful).

     If a single argument is given, returns the single key corresponding to
     the index.  This is usable in either scalar or list context.

Values
     Returns an array of IxHash element values corresponding to the list
     of supplied indices.  Returns an array of all the values if called
     without arguments.  Note the return value is mostly only useful when
     used in a list context (since perl will convert it to the number of
     elements in the array when used in a scalar context, and that may not
     be very useful).

     If a single argument is given, returns the single value corresponding
     to the index.  This is usable in either scalar or list context.

Indices
     Returns an array of indices corresponding to the supplied list of
     keys.  Note the return value is mostly only useful when used in a
     list context (since perl will convert it to the number of elements in
     the array when used in a scalar context, and that may not be very
     useful).

     If a single argument is given, returns the single index corresponding
     to the key.  This is usable in either scalar or list context.

Delete
     Removes elements with the supplied keys from the IxHash.

Replace
     Substitutes the IxHash element at the specified index with the
     supplied value-key pair.  If a key is not supplied, simply
     substitutes the value at index with the supplied value. If an element
     with the supplied key already exists, it will be removed from the
     IxHash first.

Reorder
     This method can be used to manipulate the internal order of the IxHash
     elements by supplying a list of keys in the desired order.  Note
     however, that any IxHash elements whose keys are not in the list will
     be removed from the IxHash.

Length
     Returns the number of IxHash elements.

SortByKey
     Reorders the IxHash elements by textual comparison of the keys.

SortByValue
     Reorders the IxHash elements by textual comparison of the values.

EXAMPLE
=======

     use Tie::IxHash;

     # simple interface
     $t = tie(%myhash, Tie::IxHash, 'a' => 1, 'b' => 2);
     %myhash = (first => 1, second => 2, third => 3);
     $myhash{fourth} = 4;
     @keys = keys %myhash;
     @values = values %myhash;
     print("y") if exists $myhash{third};

     # OO interface
     $t = Tie::IxHash->new(first => 1, second => 2, third => 3);
     $t->Push(fourth => 4); # same as $myhash{'fourth'} = 4;
     ($k, $v) = $t->Pop;    # $k is 'fourth', $v is 4
     $t->Unshift(neg => -1, zeroth => 0);
     ($k, $v) = $t->Shift;  # $k is 'neg', $v is -1
     @oneandtwo = $t->Splice(1, 2, foo => 100, bar => 101);

     @keys = $t->Keys;
     @values = $t->Values;
     @indices = $t->Indices('foo', 'zeroth');
     @itemkeys = $t->Keys(@indices);
     @itemvals = $t->Values(@indices);
     $t->Replace(2, 0.3, 'other');
     $t->Delete('second', 'zeroth');
     $len = $t->Length;     # number of key-value pairs

     $t->Reorder(reverse @keys);
     $t->SortByKey;
     $t->SortByValue;

BUGS
====

   You cannot specify a negative length to `Splice'. Negative indexes are
OK, though.

   Indexing always begins at 0 (despite the current $[ setting) for all
the functions.

TODO
====

   Addition of elements with keys that already exist to the end of the
IxHash must be controlled by a switch.

   Provide TIEARRAY interface when it stabilizes in Perl.

   Rewrite using XSUBs for efficiency.

AUTHOR
======

   Gurusamy Sarathy        gsar@umich.edu

   Copyright (c) 1995 Gurusamy Sarathy. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

VERSION
=======

   Version 1.21    20 Nov 1997

SEE ALSO
========

   perl(1)

Tie LDAP database to Perl hash.
*******************************

NAME
====

     Tie::LDAP - Tie LDAP database to Perl hash.

SYNOPSIS
========

     use Tie::LDAP;

     tie %LDAP, 'Tie::LDAP', {
         host => $host, # LDAP hostname (defaults to 127.0.0.1)
         port => $port, # Port number (defaults to 389)
         user => $user, # Full DN used to access LDAP database
         pass => $pass, # Password used with above DN
         base => $base, # Base DN used for each/keys/values operation
     };

DESCRIPTION
===========

   This library allows you to tie LDAP database to Perl hash.  Once tied,
all hash operation will cause corresponding LDAP operation, as you would
(probably) expect.

   Referencing tied hash will return hash reference to named LDAP entry
that holds lowercased attribute as hash key, and reference to ARRAY
containing data as hash value.

   Storing data is as easy as fetching: just push hash reference - with
the same structure as fetched hash - back in.

   Also, fetching/storing data into fetched hash reference will work as
expected - it will manipulate corresponding field in fetched LDAP entry.

EXAMPLE
=======

   Here's a brief example of how you can use this module:

     use Tie::LDAP;

     ## connect
     tie %LDAP, 'Tie::LDAP', { base => 'o=IMASY, c=JP' };

     ## lookup entry for [dn: cn=tai, o=IMASY, c=JP]
     $info = $LDAP{q{cn=tai, o=IMASY, c=JP}};

     ## lookup each attributes
     $user = $info->{username}->[0];
     $mail = @{$info->{mailaddr}};

     ## update each attributes
     $info->{username} = ['newname'];
     $info->{mailaddr} = ['tai@imasy.or.jp', 'tyamada@tk.elec.waseda.ac.jp'];

     ## update entry
     $LDAP{q{cn=tai, o=IMASY, c=JP}} = {
       username => ['newname'],
       mailaddr => ['tai@imasy.or.jp', 'tyamada@tk.elec.waseda.ac.jp'],
     };

     ## dump database (under base DN of [o=IMASY, c=JP]) in LDIF style
     while (my($dn, $hash) = each %LDAP) {
       print "dn: $dn\n";
       while (my($name, $list) = each %{$hash}) {
         foreach (@{$list}) {
           print "$name: $_\n";
         }
       }
       print "\n";
     }

     ## disconnect
     untie %LDAP;

BUGS
====

   Doing each/keys/values operation to tied hash works (as shown in
example), but could be _very_ slow, depending on the size of the database.
This is because all operation is done synchronously.

   Also, though this is not a bug, substituting empty array to tied hash
will cause whole database to be cleared out.

COPYRIGHT
=========

   Copyright 1998-2000, T. Yamada <tai@imasy.or.jp>.  All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   See Net/LDAPapi,

Tie LDAP database entry to Perl hash.
*************************************

NAME
====

     Tie::LDAP::Entry - Tie LDAP database entry to Perl hash.

SYNOPSIS
========

     use Tie::LDAP;

     tie %LDAP, 'Tie::LDAP', {
         host => $host,
         user => $user,
         pass => $user,
         base => $base,
     };

     $data = $LDAP{$path};

     ## Simple hash operation, but also updates corresponding LDAP entry
     $data->{username} = 'tai@imasy.or.jp';
     ...

DESCRIPTION
===========

   See Tie/LDAP.

COPYRIGHT
=========

   Copyright 1998-1999, T. Yamada <tai@imasy.or.jp>.  All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   See Tie/LDAP, Net/LDAP,

ordered hashes
**************

NAME
====

   Tie::LLHash.pm - ordered hashes

DESCRIPTION
===========

   This class implements an ordered hash-like object.  It's a cross
between a Perl hash and a linked list.  Use it whenever you want the speed
and structure of a Perl hash, but the orderedness of a list.

   Don't use it if you want to be able to address your hash entries by
number, like you can in a real list ($list[5]).

   See also Tie::IxHash by Gurusamy Sarathy.  It's similar (it also does
ordered hashes), but it has a different internal data structure and a
different flavor of usage.  IxHash stores its data internally as both a
hash and an array in parallel.  LLHash stores its data as a bidirectional
linked list, making both inserts and deletes very fast.  IxHash therefore
makes your hash behave more like a list than LLHash does.  This module
keeps more of the hash flavor.

SYNOPSIS
========

     use Tie::LLHash;

     # A new empty ordered hash:
     tie (%hash, "Tie::LLHash");
     # A new ordered hash with stuff in it:
     tie (%hash2, "Tie::LLHash", key1=>$val1, key2=>$val2);
     # Allow easy insertions at the end of the hash:
     tie (%hash2, "Tie::LLHash", {lazy=>1}, key1=>$val1, key2=>$val2);

     # Add some entries:
     (tied %hash)->first('the' => 'hash');
     (tied %hash)->insert('here' => 'now', 'the');
     (tied %hash)->first('All' => 'the');
     (tied %hash)->insert('are' => 'right', 'the');
     (tied %hash)->insert('things' => 'in', 'All');
     (tied %hash)->last('by' => 'gum');

     $value = $hash{'things'}; # Look up a value
     $hash{'here'} = 'NOW';    # Set the value of an EXISTING RECORD!

     $key = (tied %hash)->key_before('in');  # Returns the previous key
     $key = (tied %hash)->key_after('in');   # Returns the next key

     # Luxury routines:
     $key = (tied %hash)->current_key;
     $val = (tied %hash)->current_value;
     (tied %hash)->next;
     (tied %hash)->prev;
     (tied %hash)->reset;

     # If lazy-mode is set, new keys will be added at the end.
     $hash{newkey} = 'newval';
     $hash{newkey2} = 'newval2';

METHODS
=======

   * insert(key, value, previous_key)

     This inserts a new key-value pair into the hash right after the
     `previous_key' key.  If `previous_key' is undefined (or not
     supplied), this is exactly equivalent to `first(key, value)'.  If
     `previous_key' is defined, then it must be a string which is already
     a key in the hash - otherwise we'll croak().

   * first(key, value)  (or)  first()

     Gets or sets the first key in the hash.  Without arguments, simply
     returns a string which is the first key in the database.  With
     arguments, it inserts a new key-value pair at the beginning of the
     hash.

   * last(key, value)  (or)  last()

     Gets or sets the last key in the hash.  Without arguments, simply
     returns a string which is the last key in the database.  With
     arguments, it inserts a new key-value pair at the end of the hash.

   * key_before(key)

     Returns the name of the key immediately before the given key.  If no
     keys are before the given key, returns undef.

   * key_after(key)

     Returns the name of the key immediately after the given key.  If no
     keys are after the given key, returns undef.

   * current_key()

     When iterating through the hash, this returns the key at the current
     position in the hash.

   * current_value()

     When iterating through the hash, this returns the value at the
     current position in the hash.

   * next()

     Increments the current position in the hash forward one item.
     Returns the new current key, or undef if there are no more entries.

   * prev()

     Increments the current position in the hash backward one item.
     Returns the new current key, or undef if there are no more entries.

   * reset()

     Resets the current position to be the start of the order.  Returns
     the new current key, or undef if there are no keys.

   Here is a smattering of ways you can iterate over the hash.  I include
it here simply because iteration is probably important to people who need
ordered data.

     while (($key, $val) = each %hash) {
        print ("$key: $val\n");
     }

     foreach $key (keys %hash) {
        print ("$key: $hash{$key}\n");
     }

     my $obj = tied %hash;  # For the following examples

     $key = $obj->reset;
     while (exists $hash{$key}) {
        print ("$key: $hash{$key}\n");
        $key = $obj->next;
     }

     $obj->reset;
     while (exists $hash{$obj->current_key}) {
        $key = $obj->current_key;
        print ("$key: $hash{$key}\n");
        $obj->next;
     }

WARNINGS
========

   * Unless you're using lazy-mode, don't add new elements to the hash by
     simple assignment, a la <$hash{$new_key} = $value>, because LLHash
     won't know where in the order to put the new element.

TO DO
=====

   I could speed up the keys() routine in a scalar context if I knew how to
sense when NEXTKEY is being called on behalf of keys().  Not sure whether
this is possible.

   I may also want to add a method for... um, I forgot.  Something.

AUTHOR
======

   Ken Williams <ken@forum.swarthmore.edu>

   Copyright (c) 1998 Swarthmore College. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

A system allowing the use of anonymous arrays as keys to a hash.
****************************************************************

NAME
====

   Tie::ListKeyedHash - A system allowing the use of anonymous arrays as
keys to a hash.

SYNOPSIS
========

     use Tie::ListKeyedHash;

     [$X =] tie %hash,  'Tie::ListKeyedHash';

     $hash{['key','items','live']} = 'Hello!';
     $hash{['key','trees','grow']} = 'Goodbye!';

     print $hash{['key','items','live']},"\n";
     my (@list) =  keys %{$hash{['key']}};
     print "@list\n";

     untie %hash ;

     Alternatively keys are accessible as:

     $hash{'key','items','live'} = 'Hello!';

     This way slows down the accesses by around 10% and cannot
     be used for keys that conflict with the value of '$;'.

     Also usable via the object interface methods 'put',
     'get','exists','delete','clear'. The object interface
     is about 2x as fast as the tied interface.

DESCRIPTION
===========

   Tie::ListKeyedHash ties a hash so that you can use a reference to an
array as the key of the hash.

CHANGES
=======

0.41 09 Jun 1999
----------------

   Minor documentation changes.

0.40 04 May 1999
----------------

   Yet Another Rename to Tie::ListKeyedHash. Final rename, I promise.

0.30 04 May 1999
----------------

   Renamed to 'Tie::ListKeyedHash' after discussion on
comp.lang.perl.module and added (on the suggestion of Ilya Zakharevich,
<ilya@math.ohio-state.edu>) support for using the tie hash as
$hash{'key1','key2','key3'} as well as its native mode of
$hash{['key1','key2','key3']}

0.20 30 April 1999
------------------

   Initial public release as 'Tie::ArrayHash'

METHODS
=======

`new(....);'
     Returns the object reference for the tie.

`TIEHASH(....);'
     Returns the object reference for the tie.

`STORE($key_ref,$value);'
     Stores the $value into the arrayhash location pointed to by the
     $key_ref array reference.

     If the '$key_ref' is a $; seperated text string instead of an array
     reference, it splits it on $; and uses the resulting array as the
     actual key.

`FETCH($key_ref);'
     Returns the value pointed to by the $key_ref array reference.

     If the '$key_ref' is a $; seperated text string instead of an array
     reference, it splits it on $; and uses the resulting array as the
     actual key.

`DELETE($key_ref);'
     Deletes a specified item from the arrayhash.

     If the '$key_ref' is a $; seperated text string instead of an array
     reference, it splits it on $; and uses the resulting array as the
     actual key.

`CLEAR;'
     Clears the entire arrayhash.

`EXISTS($key_ref);'
     Returns true if the specified arrayhash key exists, false if it does
     not.

     If the '$key_ref' is a $; seperated text string instead of an array
     reference, it splits it on $; and uses the resulting array as the
     actual key.

`FIRSTKEY;'
     Returns the first key.

`NEXTKEY;'
     Returns the next key.

`DESTROY;'

`clear;'
     Clears the entire hash.

`exists([@key_list]);'
     Returns true of the specified hash element exists, false if it does
     not.  Just as with normal hashes, intermediate elements will be
     created if they do not already exist.

     The strange elsif construct provides a performance boost for shallow
     keys.

`get([@key_list]);'
     Returns the contents of the object field denoted by the @key_list.
     This is a way of making arbitrary keys that act like hashes, with the
     'hardwiring' requirements of hashes. The routine returns the the
     contents addressed by 'key1','key2','key3',...

     The strange elsif construct provides a performance boost for shallow
     keys.

`put([@key_list],$value);';
     Sets $value as the contents of the object field denoted by the
     @key_list.  This is a way of making arbitrary keys that act like
     hashes, without the 'hardwiring' requirements of hashes.

     The strange elsif construct provides a performance boost for shallow
     keys.

`delete([@key_list]);';
     Deletes the object field denoted by the @key_list.

     This is a way of making arbitrary keys that act like hashes, without
     the 'hardwiring' requirements of hashes.

     The strange elsif construct provides a performance boost for shallow
     keys.

BUGS
====

   To Be Determined.

TODO
====

   FIRSTKEY, NEXTKEY have to be tested completely.

AUTHORS
=======

   Benjamin Franz <snowhare@nihongo.org>

VERSION
=======

   Version 0.40 May 1999

   Copyright (c) Benjamin Franz 1999. All rights reserved.

     This program is free software; you can redistribute it
     and/or modify it under the same terms as Perl itself.

SEE ALSO
========

   perl perltie

Hashes which represent mathematical functions.
**********************************************

NAME
====

   Tie::Math - Hashes which represent mathematical functions.

SYNOPSIS
========

     use Tie::Math;
     tie %fibo, 'Tie::Math', sub { f(n) = f(n-1) + f(n-2) },
                             sub { f(0) = 0;  f(1) = 1 };

     # Calculate and print the fifth fibonacci number
     print $fibo{5};

DESCRIPTION
===========

   Defines hashes which represent mathematical functions, such as the
fibonacci sequence, factorials, etc...  Functions can be expressed in a
manner which a math or physics student might find a bit more familiar.  It
also automatically employs memoization.

   Multi-variable functions are supported.  f() is simply passed two
variables (f(X,Y) for instance) and the hash is accessed in the same way
($func{3,-4}).

tie
          tie %func, 'Tie::Math', \&function;
          tie %func, 'Tie::Math', \&function, \&initialization;

     &function contains the definition of the mathematical function.  Use
     the f() subroutine and N index provided.  So to do a simple
     exponential function represented by "f(N) = N**2":

          tie %exp, 'Tie::Math', sub { f(N) = N**2 };

     &initialization contains any special cases of the function you need to
     define.  In the fibonacci example in the SYNOPSIS you have to define
     f(0) = 1 and f(1) = 1;

          tie %fibo, 'Tie::Math', sub { f(N) = f(N-1) + f(N-2) },
                                  sub { f(0) = 1;  f(1) = 1; };

     The &initializaion routine is optional.

     Each calculation is "memoized" so that for each element of the array
     the calculation is only done once.

     While the variable N is given by default, A through Z are all
     available.  Simply import them explicitly:

          # Don't forget to import f()
          use Tie::Math qw(f X);

     There's no real difference which variable you use, its just there for
     your preference.  (NOTE: I had to use captial letters to avoid
     clashing with the y// operator)

EXAMPLE
=======

   Display a polynomial equation in a table.

     use Tie::Math;

     tie %poly, 'Tie::Math', sub { f(N) = N**2 + 2*N + 1 };

     print "  f(N) = N**2 + 2*N + 1 where N == -3 to 3\n";
     print "\t x \t poly\n";
     for my $x (-3..3) {
         printf "\t % 2d \t % 3d\n", $x, $poly{$x};
     }

   This should display:

     f(N) = N**2 + 2*N + 1 where N == -3 to 3
            x       poly
            -3        4
            -2        1
            -1        0
             0        1
             1        4
             2        9
             3       16

   How about Pascal's Triangle!

     use Tie::Math qw(f X Y);

     my %pascal;
     tie %pascal, 'Tie::Math', sub {
                                   if( X <= Y and Y > 0 and X > 0 ) {
                                       f(X,Y) = f(X-1,Y-1) + f(X,Y-1);
                                   }
                                   else {
                                       f(X,Y) = 0;
                                   }
                               },
                               sub {
                                   f(1,1) = 1;
                                   f(1,2) = 1;
                                   f(2,2) = 1;
                               };

     #'#
     $height = 5;
     for my $y (1..$height) {
         print " " x ($height - $y);
         for my $x (1..$y) {
             print $pascal{$x,$y};
         }
         print "\n";
     }

   This should produce a nice neat little triangle:

     1
            1 1
           1 2 1
          1 3 3 1
         1 4 6 4 1

EFFICIENCY
==========

   Memoization is automatically employed so no f(X) is calculated twice.
This radically increases efficiency in many cases.

BUGS, CAVAETS and LIMITATIONS
=============================

   Certain functions cannot be properly expressed.  For example, the
equation defining a circle, f(X) = sqrt(1 - X**2), has two solutions for
each f(X).

   There's some horrific hacks in here to make up for the limitations of
the current lvalue subroutine implementation.  Namely missing wantlvalue().

   This code use the experimental lvalue subroutine feature which will
hopefully change in the future.

   The interface is currently very alpha and will probably change in the
near future.

   This module BREAKS 5.6.0's DEBUGGER!  Neat, eh?

   This module uses the old multidimensional hash emulation from the Perl
4 days.  While this isn't currently a bad thing, it may eventually be
destined for the junk heap.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

TODO
====

   Easier ways to set boundries ie. "f(X,Y) = X + Y where X > 0 and Y > 1"

mmap a file as a tied array
***************************

NAME
====

   Tie::MmapArray - mmap a file as a tied array

SYNOPSIS
========

     use Tie::MmapArray;

     tie @array, 'Tie::MmapArray', $filename;
     tie @array, 'Tie::MmapArray', $filename, $template;
     tie @array, 'Tie::MmapArray', $filename, { template => $template,
                                                nels     => 0,
     					       mode     => "rw",
     					       shared   => 1,
     					       offset   => 0 };

     $len = (tied @array)->record_size;

DESCRIPTION
===========

   The Tie::MmapArray module lets you use mmap to map in a file as a perl
array rather than reading the file into dynamically allocated memory. It
depends on your operating system supporting UNIX or POSIX.1b mmap, of
course.  (Code to use the equivalent functions on Win32 platforms has been
contributed but has not been tested yet.)

   The type of array elements is defined by the template argument or
option.  This is a Perl pack()-style template, which defaults to "i".  The
template may be an array reference, in which case the elements are defined
by pairs of name and template for each element.  A template string may
define multiple fields, in which case that element is regarded as an array
of fields (which need not be of the same type).

   The following example shows the utmp file on Linux mapped to an array:

     tie @utmp, 'Tie::MmapArray', '/var/log/utmp',
         { mode     => "rw",
           template => [ ut_type    => 's',
                         ut_pid     => 'i',	# pid_t
                         ut_line    => 'a12',
                         ut_id      => 'a4',
                         ut_user    => 'a32',
                         ut_host    => 'a256',
                         ut_exit    => [ # struct exit_status
                                         e_termination => 's',
                                         e_exit        => 's' ],
                         ut_session => 'l',
                         ut_tv      => [ # struct timeval
                                         tv_sec  => 'l',
                                         tv_usec => 'l' ],
                         ut_addr_v6 => 'l4',
                         pad        => 'a20' ] };

   This can be scanned as follows:

     for (my $i = 0; $i < @utmp; $i++) {
         printf("pid: %d, user: %s\n",
                $utmp[$i]->{ut_pid}, $utmp[$i]->{ut_user});
     }

   The following subset of pack() template letters is supported:

i
     signed integer (default)

I
     unsigned integer

c
     signed character (one byte integer)

c
     unsigned character (one byte integer)

s
     signed short integer

S
     unsigned short integer

n
     unsigned short integer in network byte order

l
     signed long integer

L
     unsigned long integer

N
     unsigned long integer in network byte order

f
     float

d
     double

aN
     fixed-length, null-padded ASCII string of length N

AN
     fixed-length, space-padded ASCII string of length N

ZN
     fixed-length, null-terminated ASCII string of length N

   The size of the array is defined by the *nels* option.  If this is zero
then it is calculated as the file size divided by the element size.

   If the file size is smaller than the size required for the requested
elements then a single zero byte will be written to the final byte of the
requested size.  This seems to prevent the module dying with a
segmentation or bus error if memory is accessed beyond the end of the file
and generally results in a file with holes (unallocated blocks).  Precise
details of the behaviour of the module are subject to change.

BUGS, RESTRICTIONS AND FUTURE DIRECTIONS
========================================

   This is version 0.02 of the module and there are likely to be many
bugs.  The interface may change as the result of feedback.

   The options mode and shared are not yet used.

   Not all pack letters are implemented yet.

   push, pop, shift, unshift, and splice operations are not yet supported.
It is debateable whether they should be as they could be very expensive
if the mmaped file was large (say a Gigabyte or two).  Perhaps there
should be an option to explicitly allow these operations.

AUTHOR
======

   Andrew Ford <A.Ford@ford-mason.co.uk>, 27 December 1999.

CREDITS
=======

   The module was inspired by Malcolm Beatie's Mmap module.

   Reini Urban <rurban@x-ray.at> provided intial code for Win32 platforms.

"tie"-like multidimensional data structures
*******************************************

NAME
====

   Tie::Multidim - "tie"-like multidimensional data structures

SYNOPSIS
========

     use Tie::Multidim;
     my $foo = new Tie::Multidim \%h, '%@%';
     $foo->[2]{'die'}[4] = "isa";

DESCRIPTION
===========

   This module implements multi-dimensional data structures on a hash.
`$foo->[2]{'die'}[4]' gets "mapped" to `$bar{"2;die;4"}', where the ';' is
actually $SUBSEP ($;), and %bar is a hash you provide.

   It is particularly useful in two, not disjoint, situations:

  1. the data space (matrix, if you prefer) is sparsely populated;

  2. the hash into which the data is mapped is tied.
        This illustrates (1):

     my %matrix; # hash to store the data in.
     local $; = ' ';
     my $foo = new Tie::Multidim \%matrix, '@@'; # array-of-arrays.

     print $foo->[5432][9876];
     # prints the value of  $matrix{"5432 9876"}.

   This illustrates (2):

     my %matrix;
     tie %matrix, 'Matrix';  # some hashtie-able class.
     local $; = ";"; # gets remembered by the object.
     my $foo = new Tie::Multidim \%matrix, '%@%';
     # 3-level structure: hash of arrays of hashes.

     $foo->{'human'}[666]{'beast'} = "value";

     # causes a call to
     sub Matrix::STORE {
       my( $self, $index, $value ) = @_;
       my( $x, $y, $z ) = split $;, $index;
       # with $x = 'human', $y = 666, and $z = 'beast'.
     }

METHODS
=======

new
---

   This is the constructor.

   The first argument is a hash-reference.  This hash will be used by the
Tie::Multidim object to actually store the data.  The reference can be to
an anonymous hash, to a normal hash, or to a tied hash.  Tie::Multidim
doesn't care, as long as it supports the normal hash get and set
operations (STORE and FETCH methods, in TIEHASH terminology).

   The second argument is a string containing '@' and '%' characters (a al
function prototypes).  The multidimensional data structure will be
constructed to have as many dimensions as there are characters in this
string; and each dimension will be of the type indicated by the character.
'@%' is an array of hashes; '%@' is a hash of arrays; and so on.

storage
-------

   This returns the same hash reference that was passed as the first
argument to the constructor.  Not exactly a method, it must be called as a
package function, and passed the multidim reference.

     $foo = new Tie::Multidim, \%h, '@@';
     $hashref = Tie::Multidim::storage( $foo );
     # same effect as:
     $hashref = \%h;

AUTHOR
======

   jdporter@min.net (John Porter)

COPYRIGHT
=========

   This module is free software; you may redistribute it and/or modify it
under the same terms as Perl itself.

Implements a Hash where the key is a subnet
*******************************************

NAME
====

   Tie::NetAddr::IP - Implements a Hash where the key is a subnet

SYNOPSIS
========

     use Tie::NetAddr::IP;

     my %WhereIs;

     tie %WhereIs, Tie::NetAddr::IP;

     $WhereIs{"10.0.10.0/24"} = "Lab, First Floor";
     $WhereIs{"10.0.20.0/24"} = "Datacenter, Second Floor";
     $WhereIs{"10.0.30.0/27"} = "Remote location";
     $WhereIs{"0.0.0.0/0"} = "God knows where";

     foreach $host ("10.0.10.1", "10.0.20.15", "10.0.32.17", "10.10.0.1") {
        print "Host $host is in ", $WhereIs{$host}, "\n";
     }

     foreach $subnet (keys %WhereIs) {
        print "Network ", $subnet, " is used in ",
        $WhereIs{$subnet}, "\n";
     }

     untie %WhereIs;

DESCRIPTION
===========

   This module overloads hashes so that the key can be a subnet as in
*NetAddr::IP*. When looking values up, an interpretation will be made to
find the given key *within* the subnets specified in the hash.

   The code sample provided on the SYNOPSIS would print out the locations
of every machine in the foreach loop.

   Care must be taken, as only strings that can be parsed as an IP address
by *NetAddr::IP* can be used as keys for this hash.

   Iterators on the hash such as foreach, each, keys and values will only
see the actual subnets provided as keys to the hash. When looking up a
value such as in `$hash{$ipaddress}' this IP address will be looked up
among the subnets existing as keys within the hash. The matching subnet
with the longest mask (ie, the most specific subnet) will win and its
associated value will be returned.

   This code can be distributed freely according to the terms set forth in
the PERL license provided that proper credit is maintained. Please send
bug reports and feedback to the author for further improvement.

AUTHOR
======

   Luis E. Munoz (lem@cantv.net)

SEE ALSO
========

   perl(1), NetAddr::IP(3).

Keeps a number within a range of values.
****************************************

NAME
====

   Tie::NumRange - Keeps a number within a range of values.

SYNOPSIS
========

     use Tie::NumRange;

     tie my($chr), Tie::NumRange => (
       100,  # initial
       0,    # min
       255,  # max
     );

     $chr *= 3;  # $chr is 255
     $chr = -5;  # $chr is 0

     tie my($positive), Tie::NumRange => (
       1,
       1,
       undef
     );

     $positive = 2**16;  # ok
     $positive = 0;      # $pos is 1

DESCRIPTION
===========

   This module institutes a range of values for a number.  The lower and
upper bounds can be unlimited by passing undef in their place.

Constructor
-----------

     tie $number, Tie::NumRange => ($init, $min, $max);

   If `$min' is undef, the number has no lower bound.  Likewise for `$max'.

AUTHOR
======

     Jeff "japhy" Pinyan
     CPAN ID: PINYAN
     japhy@pobox.com
     http://www.pobox.com/~japhy/

Tie one array to another, with index offset
*******************************************

NAME
====

   Tie::OffsetArray - Tie one array to another, with index offset

SYNOPSIS
========

     use Tie::OffsetArray;

     tie @a, 'Tie::OffsetArray', 1, \@b; # offset=1; use given array.

     tie @c, 'Tie::OffsetArray', 2;      # use anonymous array.

     $a[0] = 'x';                        # assign to $b[1];

     tied(@a)->array->[0] = 'y';         # assign to $b[0].

DESCRIPTION
===========

   When tied to this class, an array's behavior is completely normal.  For
its internal storage, it uses another array, either one supplied by the
caller, or a new anonymous one.  Accesses to the tied array are mapped
down to the storage array by offsetting the index by some constant amount.

   A special method on the tied object returns a reference to the storage
array, so that the elements below the offset can be accessed.  This is
particularly useful if the storage array was not supplied by the caller.

AUTHOR
======

   jdporter@min.net (John Porter)

COPYRIGHT
=========

   This is free software.  This software may be modified and distributed
under the same terms as Perl itself.

creates scalars specific to a filehandle
****************************************

NAME
====

   Tie::PerFH - creates scalars specific to a filehandle

SYNOPSIS
========

     use Tie::PerFH;
     use strict;

     tie my($font), 'Tie::PerFH';

     # $font is 'blue' when STDOUT is select()ed
     $font = "blue";

     select OTHER_FH;

     # $font is 'red' when OTHER_FH is select()ed
     $font = "red";

DESCRIPTION
===========

   This module creates scalars that hold different values depending on
which filehandle is selected (much like the format variables, and the
autoflush variable).

AUTHOR
======

     Jeff "japhy" Pinyan
     CPAN ID: PINYAN
     japhy@pobox.com
     http://www.pobox.com/~japhy/

persistent data structures via tie
**********************************

NAME
====

   Tie::Persistent  - persistent data structures via tie

SYNOPSIS
========

     use Tie::Persistent;

     tie %DB, 'Tie::Persistent', 'file', 'rw'; # read data from 'file'

     # now create/add/modify database
     ...

     untie %DB;			# stores data back into 'file'

     tie %ReadOnly, 'Tie::Persistent', 'file';
     foreach (keys %ReadOnly) {
       print "$_ => $ReadOnly{$_}\n";
     }

DESCRIPTION
===========

   The Persistent package makes working with persistent data real easy by
using the tie interface.

   It works by storing data contained in a variable into a file (not
unlike a database). The primary advantage is speed, as the whole
datastructure is kept in memory (which is also a limitation), and, of
course, that you can use arbitrary data structures inside the variable
(unlike DB_File).

   If you want to make an arbitrary object persistent, just store its ref
in a scalar tied to 'Tie::Persistent'.

   *Beware*: not every data structure or object can be made persistent.
For example, it may not contain GLOB or CODE refs, as these are not really
dumpable (yet?).

   Also, it works only for variables, you cannot use it for file handles.
[A persistent file handle? Hmmm... Hmmm! Let me think about it.  I have a
vague idea, I'll have to do some unconscious work on...]

PARAMETERS
==========

   tie %Hash,   'Tie::Persistent', file, mode, *other...*;

   tie @Array,  'Tie::Persistent', file, mode, *other...*;

   tie $Scalar, 'Tie::Persistent', file, mode, *other...*;

file
     Filename to store the data in. No naming convention is enforced, but I
     personally use the suffix 'pdb' for "Perl Data Base" (or "Persistent
     Data Base"?). No file locking is done; see the section on locking
     below.

mode (optional)
     Same as mode for POSIX fopen() or IO::File::open. Basically a
     combination of 'r', 'w', 'a' and '+'. Semantics:

          'r' .... read only. Modifications in the data are not stored back
                   into the file. A non-existing file gives an error. This is
                   the default if no mode is given.

          'rw' ... read/write. Modifications are stored back, if the file does
                   not exist, it is created.

          'w' .... write only. The file is not read, the variable starts out empty.

          'a', '+' ... append. Same as 'w', but creates numbered backup files.

          'ra', 'r+' ... Same as 'rw', but creates numbered backup files.

     When some kind of write access is specified, a backup file of the old
     dataset is always created. [You'll thank me for that, believe me.]
     The reason is simple: when you tie a variable read-write (the contents
     get restored from the file), and your program isn't fully debugged
     yet, it may die in the middle of some modifications, but the data
     will still be written back to the file, possibly leaving them
     inconsistent. Then you always have at least the previous version that
     you can restore from.

     The default backup filenames follow the Emacs notation, i.e. a '~' is
     appended; for numbered backup files (specified as 'a' or '+'), an
     additional number and a '~' is appended.

     For a file 'data.pdb', the normal backup file would be 'data.pdb~' and
     the numbered backup files would be 'data.pdb~1~', 'data.pdb~2~' and so
     on. The latest backup file is the one with the highest number. The
     backup filename format can be overridden, see below.

other (optional, experimental)
     This can be a reference to another (possibly tied) variable or a name
     of another tieable package.

     If a ref is given, it is used internally to store the variable data
     instead of an anonymous variable ref. This allows to make other tied
     datastructures persistent, e.g. you could first tie a hash to
     Tie::IxHash to make it order-preserving and then give it to
     Tie::Persistent to make it persistent.

     A plain name is used to create this tied variable internally. Trailing
     arguments are passed to the other tieable package.

     Example:

          tie %h, 'Tie::Persistent', 'file', 'rw', 'Tie::IxHash';

     or

          tie %ixh, 'Tie::IxHash';
          tie %ph,  'Tie::Persistent', 'file', 'w', \%ixh;
          # you can now use %ixh as an alias for %ph

     NOTE: This is an experimental feature. It may or may not work with
     other Tie:: packages. I have only tested it with 'Tie::IxHash'.
     Please report success or failure.

LOCKING
=======

   The data file is not automatically locked. Locking has to be done
outside of the package. I recommend using a module like 'Lockfile::Simple'
for that.

   There are typical two scenarios for locking: you either lock just the
'tie' and/or 'untie' calls, but not the data manipulation, or you lock the
whole 'tie' - modify data - 'untie' sequence.

CONFIGURATION VARIABLES
=======================

   *`$Tie::Persistent::Readable'* controls which format to use to store
the data inside the file. 'false' means to use 'Storable', which is faster
(and the default), 'true' means to use 'Data::Dumper', which is slower but
much more readable and thus meant for debugging.  This only influences the
way the datastructure is *written*, format detection on read is automatic.

   *`$Tie::Persistent::BackupFile'* points to a sub that determines the
backup filename format. It gets the filename as $_[0] and returns the
backup filename. The default is

     sub { "$_[0]~"; }

   which is the Emacs backup format. For NT, you might want to change this
to

     sub { "$_[0].bak"; }

   or something.

   *`$Tie::Persistent::NumberedBackupFile'* points to a sub that
determines the numbered backup filename format. It gets the filename and a
number as $_[0] and $_[1] respectively and returns the backup filename.
The default is

     sub { "$_[0]~$_[1]~"; }

   which is the extended Emacs backup format.

NOTES
=====

   There is a module called 'Class::Eroot' that intends to do the same
thing but uses a more difficult interface (and also is rather old, not
that this is a bad thing per se), so I think my module could be of some
use.

   'Tie::Persistent' uses 'Storable' and 'Data::Dumper' internally, so
these must be installed.

   For testing, I use 'Tie::IxHash', but 'make test' still does some tests
if it is not installed.

BUGS
====

   Numbered backupfile creation might have problems if the filename
contains the first six digits of the speed of light (in m/s).

   All other bugs, please tell me!

AUTHOR
======

   Roland Giersig <Roland.Giersig@bigfoot.com>

COPYRIGHT
=========

   Copyright (c) 1999 Roland Giersig. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   See Storable, Data/Dumper.

Randomly pick (and remove) an element from a set.
*************************************************

NAME
====

   Tie::Pick - Randomly pick (and remove) an element from a set.

SYNOPSIS
========

     use Tie::Pick;

     tie my $beatle => Tie::Pick => qw /Paul Ringo George John/;

     print "My favourite beatles are $beatle and $beatle.\n";
     # Prints: My favourite beatles are John and Ringo.

DESCRIPTION
===========

   `Tie::Pick' lets you randomly pick an element from a set, and have that
element removed from the set.

   The set to pick from is given as an list of extra parameters on tieing
the scalar. If the set is exhausted, the scalar will have the undefined
value. A new set to pick from can be given by assigning a reference to an
array of the values of the set to the scalar.

   The algorithm used for picking values of the set is a variant of the
Fisher-Yates algorithm, as discussed in Knuth [3]. It was first published
by Fisher and Yates [2], and later by Durstenfeld [1]. The difference is
that we only perform one iteration on each look up.

   If you want to pick elements from a set, without removing the element
after picking it, see the `Tie::Select' module.

CAVEAT
======

   Salfi [4] points to a big caveat. If the outcome of a random generator
is solely based on the value of the previous outcome, like a linear
congruential method, then the outcome of a shuffle depends on exactly
three things: the shuffling algorithm, the input and the seed of the
random generator. Hence, for a given list and a given algorithm, the
outcome of the shuffle is purely based on the seed. Many modern computers
have 32 bit random numbers, hence a 32 bit seed. Hence, there are at most
2^32 possible shuffles of a list, foreach of the possible algorithms.  But
for a list of n elements, there are n! possible permutations.  Which means
that a shuffle of a list of 13 elements will not generate certain
permutations, as 13! > 2^32.

REFERENCES
==========

[1]
     R. Durstenfeld: *CACM*, 7, 1964. pp 420.

[2]
     R. A. Fisher and F. Yates: *Statistical Tables*. London, 1938.
     Example 12.

[3]
     D. E. Knuth: *The Art of Computer Programming*, Volume 2, Third
     edition.  Section 3.4.2, Algorithm P, pp 145. Reading:
     Addison-Wesley, 1997.  ISBN: 0-201-89684-2.

[4]
     R. Salfi: *COMPSTAT 1974*. Vienna: 1974, pp 28 - 35.

REVISION HISTORY
================

     $Log: Pick.pm,v $
     Revision 1.1  1999/07/20 06:55:25  abigail
     Initial revision

AUTHOR
======

   This package was written by Abigail.

COPYRIGHT and LICENSE
=====================

   This package is copyright 1999 by Abigail.

   This program is free and open software. You may use, copy, modify,
distribute and sell this program (and any modified variants) in any way
you wish, provided you do not restrict others to do the same.

Tie hashes to relational databases
**********************************

NAME
====

   Tie::RDBM - Tie hashes to relational databases

SYNOPSIS
========

     use Tie::RDBM;
     tie %h,Tie::RDBM,'mysql:test',{table=>'Demo',create=>1,autocommit=>0};
     $h{'key1'} = 'Some data here';
     $h{'key2'} = 42;
     $h{'key3'} = { complex=>['data','structure','here'],works=>'true' };
     $h{'key4'} = new Foobar('Objects work too');
     print $h{'key3'}->{complex}->[0];
     tied(%h)->commit;
     untie %h;

DESCRIPTION
===========

   This module allows you to tie Perl associative arrays (hashes) to SQL
databases using the DBI interface.  The tied hash is associated with a
table in a local or networked database.  One field of the table becomes the
hash key, and another becomes the value.  Once tied, all the standard hash
operations work, including iteration over keys and values.

   If you have the Storable module installed, you may store arbitrarily
complex Perl structures (including objects) into the hash and later
retrieve them.  When used in conjunction with a network-accessible
database, this provides a simple way to transmit data structures between
Perl programs on two different machines.

TIEING A DATABASE
=================

     tie %VARIABLE,Tie::RDBM,DSN [,\%OPTIONS]

   You tie a variable to a database by providing the variable name, the
tie interface (always "Tie::RDBM"), the data source name, and an optional
hash reference containing various options to be passed to the module and
the underlying database driver.

   The data source may be a valid DBI-style data source string of the form
"dbi:driver:database_name[:other information]", or a previously-opened
database handle.  See the documentation for DBI and your DBD driver for
details.  Because the initial "dbi" is always present in the data source,
Tie::RDBM will automatically add it for you.

   The options array contains a set of option/value pairs.  If not
provided, defaults are assumed.  The options are:

user ["]
     Account name to use for database authentication, if necessary.
     Default is an empty string (no authentication necessary).

password ["]
     Password to use for database authentication, if necessary.  Default is
     an empty string (no authentication necessary).

db ["]
     The data source, if not provided in the argument.  This allows an
     alternative calling style:

          tie(%h,Tie::RDBM,{db=>'dbi:mysql:test',create=>1};

table ['pdata']
     The name of the table in which the hash key/value pairs will be
     stored.

key ['pkey']
     The name of the column in which the hash key will be found.  If not
     provided, defaults to "pkey".

value ['pvalue']
     The name of the column in which the hash value will be found.  If not
     provided, defaults to "pvalue".

frozen ['pfrozen']
     The name of the column that stores the boolean information indicating
     that a complex data structure has been "frozen" using Storable's
     freeze() function.  If not provided, defaults to "pfrozen".

     NOTE: if this field is not present in the database table, or if the
     database is incapable of storing binary structures, Storable features
     will be disabled.

create [0]
     If set to a true value, allows the module to create the database table
     if it does not already exist.  The module emits a CREATE TABLE command
     and gives the key, value and frozen fields the data types most
     appropriate for the database driver (from a lookup table maintained in
     a package global, see DATATYPES below).

     The success of table creation depends on whether you have table create
     access for the database.

     The default is not to create a table.  tie() will fail with a fatal
     error.

drop [0]
     If the indicated database table exists, but does not have the required
     key and value fields, Tie::RDBM can try to add the required fields to
     the table.  Currently it does this by the drastic expedient of
     DROPPING the table entirely and creating a new empty one.  If the drop
     option is set to true, Tie::RDBM will perform this radical
     restructuring.  Otherwise tie() will fail with a fatal error.  "drop"
     implies "create".  This option defaults to false.

     A future version of Tie::RDBM may implement a last radical
     restructuring method; differences in DBI drivers and database
     capabilities make this task harder than it would seem.

autocommit [1]
     If set to a true value, the "autocommit" option causes the database
     driver to commit after every store statement.  If set to a false
     value, this option will not commit to the database until you
     explicitly call the Tie::RDBM commit() method.

     The autocommit option defaults to true.

DEBUG [0]
     When the "DEBUG" option is set to a true value the module will echo
     the contents of SQL statements and other debugging information to
     standard error.

USING THE TIED ARRAY
====================

   The standard fetch, store, keys(), values() and each() functions will
work as expected on the tied array.  In addition, the following methods
are available on the underlying object, which you can obtain with the
standard tie() operator:

commit()
          (tied %h)->commit();

     When using a database with the autocommit option turned off, values
     that are stored into the hash will not become permanent until commit()
     is called.  Otherwise they are lost when the application terminates or
     the hash is untied.

     Some SQL databases don't support transactions, in which case you will
     see a warning message if you attempt to use this function.

rollback()
          (tied %h)->rollback();

     When using a database with the autocommit option turned off, this
     function will roll back changes to the database to the state they were
     in at the last commit().  This function has no effect on database that
     don't support transactions.

DATABASES AND DATATYPES
=======================

   Perl is a weakly typed language.  Databases are strongly typed.  When
translating from databases to Perl there is inevitably some data type
conversion that you must worry about.  I have tried to keep the details as
transparent as possible without sacrificing power; this section discusses
the tradeoffs.

   If you wish to tie a hash to a preexisting database, specify the
database name, the table within the database, and the fields you wish to
use for the keys and values.  These fields can be of any type that you
choose, but the data type will limit what can be stored there.  For
example, if the key field is of type "int", then any numeric value will be
a valid key, but an attempt to use a string as a key will result in a run
time error.  If a key or value is too long to fit into the data field, it
will be truncated silently.

   For performance reasons, the key field should be a primary key, or at
least an indexed field.  It should also be unique.  If a key is present
more than once in a table, an attempt to fetch it will return the first
record found by the SQL select statement.

   If you wish to store Perl references in the database, the module needs
an additional field in which it can store a flag indicating whether the
data value is a simple or a complex type.  This "frozen" field is treated
as a boolean value.  A "tinyint" data type is recommended, but strings
types will work as well.

   In a future version of this module, the "frozen" field may be turned
into a general "datatype" field in order to minimize storage.  For future
compatability, please use an integer for the frozen field.

   If you use the "create" and/or "drop" options, the module will
automatically attempt to create a table for its own use in the database if
a suitable one isn't found.  It uses information defined in the package
variable %Tie::RDBM::Types to determine what kind of data types to create.
This variable is indexed by database driver.  Each index contains a
four-element array indicating what data type to use for each of the key,
value and frozen fields, and whether the database can support binary
types.  Since I have access to only a limited number of databases, the
table is currently short:

     Driver     Key Field      Value Field     Frozen Field  Binary?

     mysq       varchar(127)   longblob        tinyint       1
     mSQL       char(255)      char(255)       int           0
     Sybase     varchar(255)   varbinary(255)  tinyint       1
     default    varchar(255)   varbinary(255)  tinyint       1

   The "default" entry is used for any driver not specifically mentioned.

   You are free to add your own entries to this table, or make
corrections.  Please send me e-mail with any revisions you make so that I
can share the wisdom.

STORABLE CAVEATS
================

   Because the Storable module packs Perl structures in a binary format,
only those databases that support a "varbinary" or "blob" type can handle
complex datatypes.  Furthermore, some databases have strict limitations on
the size of these structures.  For example, SyBase and MS SQL Server have
a "varbinary" type that maxes out at 255 bytes.  For structures larger
than this, the databases provide an "image" type in which storage is
allocated in 2K chunks!  Worse, access to this image type uses a
non-standard SQL extension that is not supported by DBI.

   Databases that do not support binary fields cannot use the Storable
feature.  If you attempt to store a reference to a complex data type in
one of these databases it will be converted into strings like
"HASH(0x8222cf4)", just as it would be if you tried the same trick with a
conventional tied DBM hash.  If the database supports binary fields of
restricted length, large structures may be silently truncated.  Caveat
emptor.

   It's also important to realize the limitations of the Storable
mechanism.  You can store and retrieve entire data structures, but you
can't twiddle with individual substructures and expect them to persist
when the process exits.  To update a data structure, you must fetch it
from the hash, make the desired modifications, then store it back into the
hash, as the example below shows:

   *Process #1:*    tie %h,Tie::RDBM,'mysql:Employees:host.somewhere.com',
                  {table=>'employee',user=>'fred',password=>'xyzzy'};
$h{'Anne'} = { office=>'999 Infinity Drive, Rm 203',                   age
  =>  29,                   salary =>  32100 };    $h{'Mark'} = {
office=>'000 Iteration Circle, Rm -123',                   age    =>  32,
                salary =>  35000 };

   *Process #2:*    tie %i,Tie::RDBM,'mysql:Employees:host.somewhere.com',
                  {table=>'employee',user=>'george',password=>'kumquat2'};
  foreach (keys %i) {       $info = $i{$_};       if ($info->{age} > 30) {
        # Give the oldies a $1000 raise          $info->{salary} += 1000;
        $i{$_} = $info;       }    }

   This example also demonstrates how two Perl scripts running on
different machines can use Tie::RDBM to share complex data structures (in
this case, the employee record) without resorting to sockets, remote
procedure calls, shared memory, or other gadgets

PERFORMANCE
===========

   What is the performance hit when you use this module?  It can be
significant.  I used a simple benchmark in which Perl parsed a 6180 word
text file into individual words and stored them into a database,
incrementing the word count with each store.  The benchmark then read out
the words and their counts in an each() loop.  The database driver was
mySQL, running on a 133 MHz Pentium laptop with Linux 2.0.30.  I compared
Tie::RDBM, to DB_File, and to the same task using vanilla DBI SQL
statements.  The results are shown below:

     STORE       EACH() LOOP
       Tie::RDBM     28 s        2.7  s
       Vanilla DBI   15 s        2.0  s
       DB_File        3 s        1.08 s

   During stores, there is an approximately 2X penalty compared to
straight DBI, and a 15X penalty over using DB_File databases.  For the
each() loop (which is dominated by reads), the performance is 2-3 times
worse than DB_File and much worse than a vanilla SQL statement.  I have
not investigated the bottlenecks.

TO DO LIST
==========

     - Store strings, numbers and data structures in separate
       fields for space and performance efficiency.

     - Expand data types table to other database engines.

     - Catch internal changes to data structures and write them into
       database automatically.

BUGS
====

   Yes.

AUTHOR
======

   Lincoln Stein, lstein@w3.org

COPYRIGHT
=========

     Copyright (c) 1998, Lincoln D. Stein

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AVAILABILITY
============

   The latest version can be obtained from:

     http://www.genome.wi.mit.edu/~lstein/Tie-DBM/

SEE ALSO
========

   perl(1), DBI(3), Storable(3)

Implements "range hashes" in Perl
*********************************

NAME
====

   Tie::RangeHash - Implements "range hashes" in Perl

REQUIREMENTS
============

   `Tie::RangeHash' is written for Perl 5.005_62 or 5.6.0 and tested on the
latter. It should work in Perl 5.005, although I have not tested it.

   It uses the following modules:

     Carp
     Tie::Hash

   The test suite will use `Time::HiRes' if it is available.

Installation
------------

   Installation is pretty standard:

     perl Makefile.PL
     make
     make test
     make install

SYNOPSIS
========

     use Tie::RangeHash;

     tie %hash, Tie::RangeHash;

     $hash{'A,C'} = 1;
     $hash{'D,F'} = 2;
     $hash{'G,K'} = 3;

     $hash{'E'};           # returns '2'
     $hash{'BB'};          # returns '1'

     $hash{'KL'};          # returns nothing ('undef')

DESCRIPTION
===========

   This module allows hashes to associate a value with a range of keys
rather than a single key.

   For example, you could pass date ranges to the hash and then query it
with a specific date, like so:

     $cost{'1999-12-15,2000-01-14'} = 150;
     $cost{'2000-01-15,2000-02-14'} = 103;
     $cost{'2000-02-15,2000-03-14'} =  97;

   and then query the cost on a specific date:

     $this_cost = $cost{'2000-02-08'};

   Numeric key ranges can also be used:

     tie %hash, 'Tie::RangeHash', {
       Type => Tie::RangeHash::TYPE_NUMBER
     };

     $hash{'1.4,1.8'}      = 'Jim';
     $hash{'1.0,1.399999'} = 'Ned';
     $hash{'1.800001,2.0'} = 'Boo';

   If string or numeric comparisons are not appropriate for the keys you
need, a custom comparison routine can be specified:

     sub reverse_compare {
       my ($A, $B) = @_;
       return ($B cmp $A);
     }

     tie %hash, 'Tie::RangeHash', {
       Comparison => \&reverse_compare
     };

   The comparison routine should work the same as custom sort subroutines
do (A < B returns -1, A=B returns 0, A > B returns 1). Your keys must also
be representable as a string (a future version of this module may add
filters to overcome that limitation).

   If you need to define your own separator, you can do so:

     tie %hash, 'Tie::RangeHash', {
       Separator => '..'
      };

   or

     tie %hash, 'Tie::RangeHash', {
       Separator => qr/\s/
      };

   Note that if you define it as a regular expression, warnings and errors
will use the default comma ',' separator (since there is no way to
"reverse" a regular expression).

   Duplicate and overlapping ranges are not supported. Once a range is
defined, it exists for the lifetime of the hash. (Future versions may
allow you to change this behavior.)

   Warnings are now disabled by default unless you run Perl with the -W
flag.  In theory, you should also be able to say

     use warnings 'Tie::RangeHash';

   but this does not always seem to work. (Apparently something is broken
with warnings.)

   Internally, the hash is actually a binary tree. Values are retrieved by
searching the tree for nodes that where the key is within range.

CAVEATS
=======

   The binary-tree code is spontaneously written and has a very simple
tree-banacing scheme. (It needs some kind of scheme since sorted data will
produce a very lopsided tree which is no more efficient than an array.) It
appears to work, but has not been fully tested.

   A future version of this module may use an improved binary-tree
algorithm.  Or it may use something else.

   This module is incomplete... It needs the FIRSTKEY, NEXTKEY, and
(maybe) DESTROY methods.

AUTHOR
======

   Robert Rothenberg <rrwo@cpan.org>

LICENSE
=======

   Copyright (c) 2000 Robert Rothenberg. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

use references as hash keys
***************************

NAME
====

   Tie::RefHash - use references as hash keys

SYNOPSIS
========

     require 5.004;
     use Tie::RefHash;
     tie HASHVARIABLE, 'Tie::RefHash', LIST;

     untie HASHVARIABLE;

DESCRIPTION
===========

   This module provides the ability to use references as hash keys if you
first tie the hash variable to this module.

   It is implemented using the standard perl TIEHASH interface.  Please
see the tie entry in perlfunc(1) and perltie(1) for more information.

EXAMPLE
=======

     use Tie::RefHash;
     tie %h, 'Tie::RefHash';
     $a = [];
     $b = {};
     $c = \*main;
     $d = \"gunk";
     $e = sub { 'foo' };
     %h = ($a => 1, $b => 2, $c => 3, $d => 4, $e => 5);
     $a->[0] = 'foo';
     $b->{foo} = 'bar';
     for (keys %h) {
        print ref($_), "\n";
     }

AUTHOR
======

   Gurusamy Sarathy        gsar@activestate.com

VERSION
=======

   Version 1.21    22 Jun 1999

SEE ALSO
========

   perl(1), perlfunc(1), perltie(1)

Use regular expressions as hash keys
************************************

NAME
====

   Tie::RegexpHash - Use regular expressions as hash keys

REQUIREMENTS
============

   `Tie::RegexpHash' is written for and tested on Perl 5.6.0. A future
version might be tweaked to run on 5.005.

   It uses only standard modules.

Installation
------------

   Installation is pretty standard:

     perl Makefile.PL
     make
     make install

   No test suite is available in this version.

SYNOPSIS
========

     use Tie::RegexpHash;

     my %hash;

     tie %hash, 'Tie::RegexpHash';

     $hash{ qr/^5(\s+|-)?gal(\.|lons?)?/i } = '5-GAL';

     $hash{'5 gal'};     # returns "5-GAL"
     $hash{'5GAL'};      # returns "5-GAL"
     $hash{'5  gallon'}; # also returns "5-GAL"

     my $rehash = Tie::RegexpHash->new();

     $rehash->add( qr/\d+(\.\d+)?/, "contains a number" );
     $rehash->add( qr/s$/,          "ends with an \`s\'" );

     $rehash->match( "foo 123" );  # returns "contains a number"
     $rehash->match( "examples" ); # returns "ends with an `s'"

DESCRIPTION
===========

   This module allows one to use regular expressions for hash keys, so that
values can be associated with anything that matches the key.

   Hashes can be operated on using the standard tied hash interface in
Perl, or using an object-orineted interface described below.

METHODS
=======

new
---

     my $obj = Tie::RegexpHash->new()

   Creates a new "RegexpHash" (Regular Expression Hash) object.

add
---

     $obj->add( $key, $value );

   Adds a new key/value pair to the hash. $key can be a Regexp or a string
(which is compiled into a Regexp).

   If $key is already defined, the value will be changed. If $key matches
an existing key (but is not the same), a warning will be shown if warnings
are enabled.

match
-----

     $value = $obj->match( $quasikey );

   Returns the value associated with `$quasikey'. (`$quasikey' can be a
string which matches an existing Regexp or an actual Regexp.)  Returns
'undef' if there is no match.

   Regexps are matched in the order they are defined.

match_exists
------------

     if ($obj->match_exists( $quasikey )) ...

   Returns a true value if there exists a matching key.

remove
------

     $value = $obj->remove( $quasikey );

   Deletes the key associated with `$quasikey'.  If `$quasikey' matches an
existing key (but is not the same), a warning will be shown if warnings
are enabled.

   Returns the value associated with the key.

clear
-----

     $obj->clear();

   Removes all key/value pairs.

AUTHOR
======

   Robert Rothenberg <rrwo@cpan.org>

LICENSE
=======

   Copyright (c) 2001 Robert Rothenberg. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Send output of your STDERR to a process or mail
***********************************************

NAME
====

   Tie::STDERR - Send output of your STDERR to a process or mail

SYNOPSIS
========

     use Tie::STDERR;
     if (;

     use Tie::STDERR 'root';

     use Tie::STDERR 'root', 'Errors in the script';

     use Tie::STDERR '>> /tmp/log';

     use Tie::STDERR '| mail -s Error root';

     use Tie::STDERR \&func;

     use Tie::STDERR \$append_to_scalar;

DESCRIPTION
===========

   Sends all output that would otherwise go to STDERR either by email to
root or whoever is responsible, or to a file or a process, or calls your
function at the end of the script. This way you can easily change the
destination of your error messages from *inside* of your script.  The mail
will be sent or the system command or Perl function run only if there
actually is some output detected - something like cron would do.

   The behaviour of the module is directed via the arguments to use, as
shown above. If you do not give arguments, an e-mail to root is sent.  You
can give up to two scalars - name of the recipient and the subject of the
email. Argument that starts with | will send the output to a process. If
it starts with > or >>, it will be written (appended) to a file. If the
argument is explicit undef, if will untie previous tieness. Reference to a
functions registers a callback Perl function that will be passed the
string of the data sent to STDERR during your script and reference to
scalar registers scalar, to which this data will be appended.

   The module will catch all output, including your explicit prints to
STDERR, warnings about undefined values, dies and even dies as a result of
compilation error. You do not need any special treatment/functions -
Tie::STDERR will catch all. However, if you run external command (system,
"), stderr output from that process won't be caught. It is because we tie
Perl's STDERR fileglob, not the external filehandle. This has the
advantage that you can say

     {
     local *STDERR; untie *STDERR;
     print STDERR "Now we go directly to STDERR\n";
     }

   My main goal was to provide a tool that could be used easily,
especially (but not only) for CGI scripts. My assumption is that the CGI
scripts should run without anything being sent to STDERR (and error_log,
where it mixes up with other messages, even if you use CGI::Carp). We've
found it usefull to get delivered the error and warning messages together
with any relevant information (%ENV) via email.

   Under mod_perl/Apache::Registry, Tie::STDERR tries to work as with
normal scripts - sends the message at the end of each request. This is
done by registering a cleanup handler. If you

     use Tie::STDERR 'arguments';

   in your scripts, everything is fine, because the new parameters are
reset each time the script is run. However, if you use some home grown
module like we do (CGI::BuildPage, wrapper around CGI) that uses
Tie::STDERR, that use will only be called once, during the compilation of
the module and the arguments are not reset and the cleanup handler will
not be registered. So next time your Apache::Registry script uses this
CGI::BuildPage or however you call it, you won't probably get receive the
e-mail. The solution is to call explicitely function
Tie::STDERR::register_apache_cleanup in your module - I've put it into the
new method that is called in every reasonable script.  (This is however
subject to change. Let me know if you find better solution or if this
explanation is unclear.)

BUGS
====

   The Tie::STDERR catches the compile time errors, but it doesn't get the
reason, only the fact that there was an error. I do not know how to fix
this.

VERSION
=======

   0.26

AUTHOR
======

   (c) 1998 Jan Pazdziora, adelton@fi.muni.cz,
http://www.fi.muni.cz/~adelton/ at Faculty of Informatics, Masaryk
University in Brno, Czech Republic

base class definitions for tied scalars
***************************************

NAME
====

   Tie::Scalar, Tie::StdScalar - base class definitions for tied scalars

SYNOPSIS
========

     package NewScalar;
     require Tie::Scalar;

     @ISA = (Tie::Scalar);

     sub FETCH { ... }		# Provide a needed method
     sub TIESCALAR { ... }	# Overrides inherited method

     package NewStdScalar;
     require Tie::Scalar;

     @ISA = (Tie::StdScalar);

     # All methods provided by default, so define only what needs be overridden
     sub FETCH { ... }

     package main;

     tie $new_scalar, 'NewScalar';
     tie $new_std_scalar, 'NewStdScalar';

DESCRIPTION
===========

   This module provides some skeletal methods for scalar-tying classes. See
Perltie (perl.info), for a list of the functions required in
tying a scalar to a package. The basic Tie::Scalar package provides a new
method, as well as methods TIESCALAR, FETCH and STORE. The *Tie::StdScalar*
package provides all the methods specified in  Perltie (perl.info).
It inherits from Tie::Scalar and causes scalars tied
to it to behave exactly like the built-in scalars, allowing for selective
overloading of methods. The new method is provided as a means of
grandfathering, for classes that forget to provide their own TIESCALAR
method.

   For developers wishing to write their own tied-scalar classes, the
methods are summarized below. The Perltie (perl.info),
section not only documents these, but has sample code as well:

TIESCALAR classname, LIST
     The method invoked by the command `tie $scalar, classname'.
     Associates a new scalar instance with the specified class. LIST would
     represent additional arguments (along the lines of AnyDBM_File,
     and compatriots) needed to complete the association.

FETCH this
     Retrieve the value of the tied scalar referenced by *this*.

STORE this, value
     Store data value in the tied scalar referenced by *this*.

DESTROY this
     Free the storage associated with the tied scalar referenced by *this*.
     This is rarely needed, as Perl manages its memory quite well. But the
     option exists, should a class wish to perform specific actions upon
     the destruction of an instance.

MORE INFORMATION
================

   The Perltie (perl.info), section uses a good example of
tying scalars by associating process IDs with priority.

Scalar variables that time out
******************************

NAME
====

   Tie::Scalar::Timeout - Scalar variables that time out

SYNOPSIS
========

     use Tie::Scalar::Timeout;

     tie my $k, 'Tie::Scalar::Timeout', EXPIRES => '+2s';

     $k = 123;
     sleep(3);
     # $k is now undef

     tie my $m, 'Tie::Scalar::Timeout', NUM_USES => 3, VALUE => 456;

     tie my $n, 'Tie::Scalar::Timeout', VALUE => 987, NUM_USES => 1,
         POLICY => 777;

     tie my $p, 'Tie::Scalar::Timeout', VALUE => 654, NUM_USES => 1,
         POLICY => \&expired;
     sub expired { $is_expired++ }

DESCRIPTION
===========

   This module allows you to tie a scalar variable whose value will be
reset (subject to an expiry policy) after a certain time and/or a certain
number of uses. One possible application for this module might be to time
out session variables in mod_perl programs.

   When tying, you can specify named arguments in the form of a hash. The
following named parameters are supported:

EXPIRES
     Use EXPIRES to specify an interval or absolute time after which the
     value will be reset. (Technically, the value will still be there, but
     the module's FETCH sub will return the value as dictated by the
     expiry policy.)

     Values for the EXPIRES field are modelled after Netscape's cookie
     expiration times. Except, of course, that negative values don't
     really make sense in a universe with linear, one-way time. The
     following forms are all valid for the EXPIRES field:

          +30s                    30 seconds from now
          +10m                    ten minutes from now
          +1h                     one hour from now
          +3M                     in three months
          +10y                    in ten years time
          25-Apr-2001 00:40:33    at the indicated time & date

     Assigning a value to the variable causes EXPIRES to be reset to the
     original value.

VALUE
     Using the VALUE hash key, you can specify an initial value for the
     variable.

`NUM_USES'
     Alternatively or in addition to EXPIRES, you can also specify a
     maximum number of times the variable may be read from before it
     expires. If both EXPIRES and `NUM_USES' are set, the variable will
     expire when either condition becomes true. If `NUM_USES' isn't set or
     set to a negative value, it won't influence the expiry process.

     Assigning a value to the variable causes `NUM_USES' to be reset to the
     original value.

POLICY
     The expiration policy determines what happens to the variable's value
     when it expires. If you don't specify a policy, the variable will be
     undef after it has expired. You can specify either a scalar value or
     a code reference as the value of the POLICY parameter. If you specify
     a scalar value, that value will be returned after the variable has
     expired. Thus, the default expiration policy is equivalent to

          POLICY => undef

     If you specify a code reference as the value of the POLICY parameter,
     that code will be called when the variable value is FETCH()ed after it
     has expired. This might be used to set some other variable, or reset
     the variable to a different value, for example.

BUGS
====

   None known so far. If you find any bugs or oddities, please do tell me
about them.

AUTHOR
======

   Marcel GrE<uuml>nauer <marcel@codewerk.com>

COPYRIGHT
=========

   Copyright 2000 Marcel GrE<uuml>nauer. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1), Tie::Scalar(3pm).

A tied hash that supports namespace-based encapsulation
*******************************************************

NAME
====

   Tie::SecureHash - A tied hash that supports namespace-based
encapsulation

VERSION
=======

   This document describes version 1.00 of Tie::SecureHash, released
December 3, 1998

SYNOPSIS
========

     use Tie::SecureHash;

     # CREATE A SECURE HASH

     my %hash;
     tie %hash, Tie::SecureHash;

     # CREATE A REFERENCE TO A SECURE HASH (BLESSED INTO Tie::SecureHash!)

     my $hashref = Tie::SecureHash->new();

     # CREATE A REFERENCE TO A SECURE HASH (BLESSED INTO $some_other_class)

     my $hashref = Tie::SecureHash->new($some_other_class);

     # CREATE NEW ENTRIES IN THE HASH

     package MyClass;

     sub new
     {
     	my ($class, %args) = @_
     	my $self = Tie::SecureHash->($class);

     $self->{MyClass::public}     = $args{public};
     $self->{MyClass::_protected} = $args{protected};
     $self->{MyClass::__private}  = $args{private};

     return $self;
     	}

     # SAME EFFECT, EASIER SYNTAX...

     package MyClass;

     sub new
     {
     	my ($class, %args) = @_
     	my $self = Tie::SecureHash->($class,
     			public     => $args{public},
     			_protected => $args{protected},
     			__private  => $args{private},
     			);

     return $self;
     	}

     # ACCESS RESTRICTIONS ON ENTRIES

     package MyClass;

     sub print_attributes
     {
         my $self = $_[0];
     				# OKAY? (ACCESSIBLE WHERE?)

     print $self->{public};	#  YES  (ANYWHERE)
     print $self->{_protected};	#  YES  (ONLY IN MyClass HIERARCHY)
     print $self->{__private};	#  YES  (ONLY IN MyClass)
     	}

     package SonOfMyClass; @ISA = qw( MyClass );

     sub print_attributes
     {
         my $self = $_[0];
     				# OKAY? (ACCESSIBLE WHERE?)

     print $self->{public};	#  YES  (ANYWHERE)
     print $self->{_protected};	#  YES  (ONLY IN MyClass HIERARCHY)
     print $self->{__private};	#  NO!  (ONLY IN MyClass)
     	}

     package main;

     my $object = MyClass->new();
     				# OKAY? (ACCESSIBLE WHERE?)

     print $object->{public};	#  YES  (ANYWHERE)
     print $object->{_protected};	#  NO!  (ONLY IN MyClass HIERARCHY)
     print $object->{__private};	#  NO!  (ONLY IN MyClass)

     # DEBUGGING

     $object->Tie::SecureHash::debug();

DESCRIPTION
===========

   [Coming soon]

DIAGNOSTICS
===========

`Private key %s of tied securehash inaccessible from package %s'
     Private keys can only be accessed from their "owner" package. An
     attempt was made to access a private key from some other package.

`Private key %s of tied securehash inaccessible from file %s'
     Private keys can only be accessed from the lexical scope of the file
     in which they were originally declared. An attempt was made to access
     a private key from some lexical scope (probably another file, but
     perhaps an eval).

`Protected key %s of tied securehash inaccessible from package %s'
     Protected keys can only be accessed from theie "owner" package and any
     of its subclasses. An attempt was made to access a protected key from
     some package not in the owner's inheritance hierarchy.

`Entry for key %s of tied securehash cannot be created from package %s'
     Keys must be declared from within the lexical scope of their owner's
     package.  In other words, the qualifier for a key declaration must be
     the same as the current package. An attempt was made to declare a key
     from some package other than its owner.

`Private key %s does not exist in tied securehash'
     Securehash keys are not autovivifying; they must be declared using a
     fully qualified key before they can be used. An attempt was made to
     access or assign to an unqualified private key (one with two leading
     underscores), before the corresponding fully qualified key was
     declared.

`Protected key %s does not exist in tied securehash'
     Securehash keys are not autovivifying; they must be declared using a
     fully qualified key before they can be used. An attempt was made to
     access or assign to an unqualified protected key (one with a single
     leading underscore), before the corresponding fully qualified key was
     declared.

`Public key %s does not exist in tied securehash'
     Securehash keys are not autovivifying; they must be declared using a
     fully qualified key before they can be used. An attempt was made to
     access or assign to an unqualified public key (one with no leading
     underscore), before the corresponding fully qualified key was
     declared.

`Ambiguous key %s (when accessed from package %s). Could be: %s'
     An unqualified key was used to access the securehash, but it was
     ambiguous in the context. The error message lists the set of fully
     qualified keys that might have matched.

`Invalid key %s'
     An attempt was made to access the securehash (or declare a key)
     through an improperly formatted key. This almost always means that
     the qualifier isn't a valid package name.

`%s can't be both "strict" and "fast"'
     Tie::SecureHash detected that both the $Tie::SecureHash::strict and
     $Tie::SecureHash::fast keys were set. But the two modes are mutually
     exclusive.

`Accessing securehash via unqualified key %s will be unsafe in 'fast' mode. Use %s::%s'
     This warning is issued in "strict" mode, and points out an access
     attempt which will break if the code is converted to "fast" mode.

`Tie'ing a securehash directly will circumvent 'fast' mode. Use Tie::SecureHash::new instead'
     This warning is issued in "strict" mode, and points out an explicit
     tie to the Tie::SecureHash module. Hashes tied in this way will not
     speed up under "fast" mode.

`Tie'ing a securehash directly should never happen in 'fast' mode. Use Tie::SecureHash::new instead'
     This warning is issued in "fast" mode, and points out an explicit tie
     to the Tie::SecureHash module. Hashes tied in this way will still be
     slow. This diagnostic can be turned off by setting
     $Tie::SecureHash::fast to any value other than 1.

`Unable to assign to securehash because the following existing keys are inaccessible from package %s and cannot be deleted: %s'
     An attempt was made to assign a completely new set of entries to a
     securehash.  Typically something like this:

          %securehash = ();

     This doesn't work unless all the existing keys are accessible at the
     point of the assignment.

AUTHOR
======

   Damian Conway (damian@cs.monash.edu.au)

BUGS AND IRRITATIONS
====================

   There are undoubtedly serious bugs lurking somewhere in this code :-)
Bug reports and other feedback are most welcome.

COPYRIGHT
=========

     Copyright (c) 1998-2000, Damian Conway. All Rights Reserved.
           This module is free software. It may be used, redistributed
           and/or modified under the terms of the Perl Artistic License
        (see http://www.perl.com/perl/misc/Artistic.html)

Perl module implementing intelligent objects
********************************************

NAME
====

   Tie::SentientHash - Perl module implementing intelligent objects

SYNOPSIS
========

     use Tie::SentientHash;

     tie %hash, 'Tie::SentientHash', $meta_data, $initial_data;

     $hashref    = Tie::SentientHash->new($meta_data, $initial_data);
     $modified   = $hashref->modified($key [, $bool])
     $untiedhash = $hashref->export;
     $metadata   = $hashref->_metadata;
     $modified   = $hashref->_modified;

     $hashref->{key} = 'value';
     $hashref->{key1}{key2} = $value;
     $value2 = $hashref->{key};
     undef $hashref;

DESCRIPTION
===========

   The `Tie::SentientHash' package provides intelligent objects.  The
objects are represented as hashes which:

   * provide read-only elements

   * provide 'special' elements that are handled by user-supplied functions

   * disallow changes to the data as specified by metadata

   * track changes and call a 'commit changes' function when the object is
     destroyed

   References to scalars, arrays, hashes and objects can be stored in hash
elements in which case the referenced object is tied to an internal class
of the appropriate type (Tie::SentientHash::NestedHash, ::NestedArray or
::NestedScalar), so that changes to the nested data structures can be
tracked.

   The constructor is invoked with two hash references: the first contains
metadata and the second the initial data values.  The metadata hash may
contain the following flags:

READONLY
     a list of hash entries that are read-only (read-only elements cannot
     be modified - except by special element handlers - or deleted and are
     not deleted when the CLEAR method is called)

SPECIAL
     a hash of name/subroutine-refs pairs that specifies elements that are
     handled specially (special elements also cannot be deleted).  The user
     function is called both for STORE (with four arguments) and for FETCH
     (with three arguments).  The arguments are: a reference to the
     metadata hash, a reference to the data hash, the element key and if
     the funtion is being called for a STORE operation, the value to be
     stored.  SPECIAL elements can be used to implement calculated
     attributes.

TRACK_CHANGES
     flag to indicate that the class should keep track of the keys of
     modified (top-level) hash elements

COMMIT_SUB
     a reference to a subroutine to commit changes (called with a reference
     to the data hash and a reference to the metadata hash)

FORBID_INSERTS
     forbid inserts into hash and sub-hashes/arrays

FORBID_DELETES
     forbid deletes from hash

FORBID_CHANGES
     forbid any changes

   Trying to change an object in a way that is forbidden by the metadata
will cause the module to croak.

   Changes are only tracked at the top level.

   The API is as follows:

tie %hash, 'Tie::SentientHash', $meta_data, $initial_data
     Functional interface to create a new sentient hash.  $meta_data
     describes the properties of the sentient hash (as outlined above) and
     $initial_data is the initial content of the sentient hash.

Tie::SentientHash->new($meta_data, $initial_data)
     Object oriented constructor for a sentient hash.

$hashref->modified([$key [, $bool]])
     If called with no arguments in a scalar returns an indication of
     whether the sentient hash has been modified.  If called with no
     arguments in an array context returns the list of elements that have
     been modified.  Otherwise queries or sets the modification status of a
     specific top level element.

$untiedhash = $hashref->export
     Creates an "untied" copy of the sentient hash.

   If a commit function is specified when the sentient hash is created it
will be called when the destructor is called (normall when it is
garbage-collected).

EXAMPLE
=======

   I use Tie::SentientHash as the basis for implementing persistent
objects in my CGI/mod_perl scripts.  The details of reading and writing
the objects from and to the database is handled by a class, but neither
the class nor the high level code needs to keep track of whether the
object has been changed in any way.

   For example if you had a pay per view system of some kind you could
have a script that contained the following fragment:

     sub pay_per_view ($$) {
       my($cust_id, $cost) = @_;

     my $cust = load Customer $cust_id;
     $cust->{CREDIT} -= $cost;
        }

   The customer object would be implemented in a module sketched out
below.  A commit function is specified on the call to create a new
sentient object, and that function will be called when $cust goes out of
scope at the end of the pay_per_view function and can write the modified
object back to the database.  If none of the attributes had been modified
then the commit function would not be invoked.

     package Customer;

     sub load ($$) {
       my ($class, $cust_id) = @_;
       my $data = {};

     # read customer data from a database into $data

     my $meta = { COMMIT_SUB     => \&_commit,
                  READONLY       => [ qw( CUST_ID ) ],
                  FORBID_INSERTS => 1 };

     return bless Tie::SentientHash->new($meta, $data), $class;
        }

     sub _commit ($$) {
       my ($meta, $data) = @_;

     # As we have been called, something has changed.  The names of
     # the modified fields are the keys of $meta->{MODIFIED}.  We had
     # better write the data back out to the database.

        }

RESTRICTIONS
============

   Full array semantics are only supported for Perl version 5.005.

   Starting with version 0.54 blessed objects may be stored in the
*sentient hash*, however this functionality is experimental, has not been
exhaustively tested, may not work, and may be subject to change.  Use at
your own peril!

   Tie::SentientHash ties nested elements to internal subclasses so it can
track changes.  If you keep references to such elements and modify them
directly then Tie::SentientHash may not be aware of the changes.

   Objects of classes that use the tie mechanism may not work when stored
in a sentient hash.

   If you use an object as the data for a new sentient hash, then the hash
will not be re-blessed, i.e. if $object is an object then after

     $href = Tie::SentientHash->new($meta, $object);

   $href will be blessed in the same class as $object.  This means you
cannot use the modified or export methods on $href.  However you can use
them on the tied array, e.g.:

     @keys    = (tied %$href)->modified;
     $newhash = (tied %$href)->export;

   As Tie::Sentient recursively ties nested elements to internal
subclasses it may not be very efficent on large, deeply nested data
structures.  (If I find the time I may provide a C implementation that
would be faster in this regard).

AUTHOR
======

   Andrew Ford <A.Ford@ford-mason.co.uk>

   Please let me know if you use this module.

SEE ALSO
========

   perl(1).

COPYRIGHT
=========

   Copyright 1999-2001 Andrew Ford and Ford & Mason Ltd. All rights
reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Merge multiple data sources into a hash
***************************************

NAME
====

   Tie::ShadowHash - Merge multiple data sources into a hash

SYNOPSIS
========

     use Tie::ShadowHash;
     use DB_File;
     tie (%db, 'DB_File', 'file.db');
     $obj = tie (%hash, 'Tie::ShadowHash', \%db, "otherdata.txt");

     # Accesses search %db first, then the hashed "otherdata.txt".
     print "$hash{key}\n";

     # Changes override data sources, but don't change them.
     $hash{key} = 'foo';
     delete $hash{bar};

     # Add more data sources on the fly.
     %extra = (fee => 'fi', foe => 'fum');
     $obj->add (\%extra);

     # Add a text file as a data source, taking the first "word" up
     # to whitespace on each line as the key and the rest of the line
     # as the value.
     $split = sub { split (' ', $_[0], 2) };
     $obj->add ([text => "pairs.txt", $split]);

     # Add a text file as a data source, splitting each line on
     # whitespace and taking the first "word" to be the key and an
     # anonymous array consisting of the remaining words to be the
     # data.
     $split = sub { split (' ', $_[0]) };
     $obj->add ([text => "triples.txt", $split]);

DESCRIPTION
===========

   This module merges together multiple sets of data in the form of hashes
into a data structure that looks to Perl like a single simple hash.  When
that hash is accessed, the data structures managed by that shadow hash are
searched in order they were added for that key.  This allows the rest of a
program simple and convenient access to a disparate set of data sources.

   Tie::ShadowHash can handle anything that looks like a hash; just give
it a reference as one of the additional arguments to tie().  This includes
other tied hashes, so you can include DB and DBM files as data sources for
a shadow hash.  If given a plain file name instead of a reference, it will
build a hash to use internally, with each chomped line of the file being
the key and the number of times that line is seen in the file being the
value.

   Tie::Shadowhash also supports special tagged data sources that can take
options specifying their behavior.  The only tagged data source currently
supported is "text", which takes a filename of a text file and a reference
to a sub.  The sub is called for every line of the file, with that line as
an argument, and is expected to return a list.  The first element of the
list will be the key, and the second and subsequent elements will be the
value or values.  If there is more than one value, the value stored in the
hash and associated with that key is an anonymous array containing all of
them.

   Tagged data sources are distinguished from normal data sources by
passing them to tie() (or to add() - see below) as an anonymous array.
The first element is the data source tag and the remaining elements are
arguments for that data source.  For a text data source, see the usage
summary above for examples.

   The shadow hash can be modified, and the modifications override the data
sources, but modifications aren't propagated back to the data sources.  In
other words, the shadow hash treats all data sources as read-only and saves
your modifications only in internal memory.  This lets you make changes to
the shadow hash for the rest of your program without affecting the
underlying data in any way (and this behavior is the main reason why this
is called a shadow hash).

   If the shadow hash is cleared, by assigning the empty list to it, by
explicitly calling CLEAR(), or by some other method, all data sources are
dropped from the shadow hash.  There is no other way of removing a data
source from a shadow hash after it's been added (you can, of course, always
untie the shadow hash and dispose of the underlying object if you saved it
to destroy the shadow hash completely).

   You can call the add() method of the underlying object to add data
sources to the shadow hash.  It takes the same arguments as the initial
tie() does and interprets them in the same way.

DIAGNOSTICS
===========

Can't open file %s: %s
     Tie::ShadowHash was given a file name to use as a source, but when it
     tried to open that file, the open failed with that system error
     message.

Invalid source type %s
     Tie::Shadowhash was given a tagged data source of an unknown type.
     The only currently supported tagged data source is "text".

CAVEATS
=======

   It's worth paying *very* careful attention to `"The untie Gotcha"',
see Perltie (perl.info), when using this module.  It's also
important to be careful about what you do with tied hashes that are
included in a shadow hash.  Tie::ShadowHash stores a reference to such
arrays; if you untie them out from under a shadow hash, you may not get
the results you expect.  Remember that if you put something in a shadow
hash, you'll need to clean out the shadow hash as well as everything else
that references a variable if you want to free it completely.

   Not all tied hashes implement EXISTS; in particular, ODBM, NDBM, some
old versions of GDBM, and versions of SDBM in Perl 5.005_56 or earlier
don't.  Calling exists on a shadow hash that includes one of those tied
hashes as a data source may therefore result in a runtime error.
Tie::ShadowHash doesn't use exists except to implement the EXISTS method
because of this.

   Because it can't use EXISTS due to the above problem, Tie::ShadowHash
cannot correctly distinguish between a non-existent key and an existing key
associated with an undefined value.  This isn't a large problem, since many
tied hashes can't store undefined values anyway, but it means that if one
of your data sources contains a given key associated with an undefined
value and one of your later data sources contains the same key but with a
defined value, when the shadow hash is accessed using that key, it will
return the first defined value it finds.  This is an exception to the
normal rule that all data sources are searched in order and the value
returned by an access is the first value found.  (Tie::ShadowHash does
correctly handle undefined values stored directly in the shadow hash.)

AUTHOR
======

   Russ Allbery <rra@stanford.edu>.

Perl module to keep hashes in a sorted order
********************************************

NAME
====

   Tie::SortHash - Perl module to keep hashes in a sorted order

SYNOPSIS
========

     use Tie::SortHash;

     my %people = (
                   'John Doe'  => 33,
                   'Jane Doe'  => 29,
                   'Jim Smith' => 15,
                  );

     my $sortblock = q(
                       my $c = (split /\s+/, $a)[1];
                       my $d = (split /\s+/, $b)[1];

     $c cmp $d
        ||
                         $hash{$a} <=> $hash{$b}
                        );

     tie %people, 'Tie::SortHash', \%people, $sortblock;

     foreach my $name ( keys %people ) {
       print $name . " is " . $people{$name} . " years old.\n";
     }

     # This output will always be
     Jane Doe is 29 years old.
     John Doe is 33 years old.
     Jim Smith is 15 years old.

DESCRIPTION
===========

   This module is a designed to be a light weight hash sorting mechanism.
It is often frustrating to have a hash return elements in a random order,
such as when using the `keys()', `values()' and `each()' functions, or
simply when iterating over them.

METHODS
=======

Tie
---

   In order to tie() your hash to `Tie::SortHash', you can use any of
these methods:

     tie HASH, 'Tie::SortHash', HASHREF, SORTBLOCK;

     tie HASH, 'Tie::SortHash', HASHREF;

     tie HASH, 'Tie::SortHash';

   It is important to remember that if you have elements in your HASH
already, you must supply a reference to that hash in `HASHREF'.

   For example:

     tie %people, 'Tie::SortHash', \%people;

   If you don't, ` %people' will be set to an empty hash.  You probably
don't want that.

Standard Tied Hash Methods
--------------------------

   `Tie::SortHash' implements all the methods that a tied hash class
should.  These are: TIEHASH, CLEAR, DELETE, DESTROY, EXISTS, FETCH,
FIRSTKEY, NEXTKEY and STORE.  With the exception of a few, these all work
as they would on a normal hash.  Those exceptions include:

FIRSTKEY
     This will produce the first key according to the `"sortblock"' in
     this node.

NEXTKEY
     This will produce each key according to the `"sortblock"' in this
     node, excluding the first which is hanled by FIRSTKEY.

     It is a *really* bad idea to change the `"sortblock"' in this node in
     the middle of an iteration, unless you actually want to.  ( I'd be
     interested in why, though. )

sortblock
---------

   After you have tied your hash, you can change the sort block at any
time.  Some examples include:

     (tied %people)->sortblock( q( $hash{$b} <=> $hash{$a} ) );

   or:

     my $tied_ref = tie my %people, 'Tie::SortHash', \%people;

     $tied_ref->sortblock( q(
                             $hash{$a} <=> $hash{$b}
                                       ||
                                    $b cmp $a
                         )  );

   It is important to remember a few things about the sort block.

Always pass the sort block in a non-interpolated scalar
     This allows you to have greater control over the sorting that you
     would like to do.  With out it, you couldn't sort by value because
     your program would complain that ` %hash' hasn't been declared.  And
     `$a' and <$b> would need to be represented more like
     `$Tie::SortHash::a'.

` %hash' is generic within your sort block.
     This is because the internal representation of the tie hash is most
     likley not representative of the hash you're tieing.  And it allows
     the ability to manipulate and sort accoring to value.

     In other words, within your `"sortblock"' in this node, ` %hash' is
     the `Tie::SortHash's' representation of your hash.

What happens when you have a syntax error in your `"sortblock"' in this node?
     The program dies, just like it would with any other syntax error.  You
     will recieve a nice message ( `$@' ) when this occurs.  It will die
     when you try to assign to the `"sortblock"' in this node.

AUTHOR
======

   Casey Tweten, crt@kiski.net

COPYRIGHT
=========

   Copyright (c) 2000 Casey Tweten. All rights reserved.  This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

VERSION
=======

   Version 1.00 Aug 19, 2000

SEE ALSO
========

   See Perl (perl.info),(1), see Perltie (perl.info),
Perlfaq4 (perl.info).

Fixed-table-size, fixed-key-length hashing
******************************************

NAME
====

   Tie::SubstrHash - Fixed-table-size, fixed-key-length hashing

SYNOPSIS
========

     require Tie::SubstrHash;

     tie %myhash, 'Tie::SubstrHash', $key_len, $value_len, $table_size;

DESCRIPTION
===========

   The Tie::SubstrHash package provides a hash-table-like interface to an
array of determinate size, with constant key size and record size.

   Upon tying a new hash to this package, the developer must specify the
size of the keys that will be used, the size of the value fields that the
keys will index, and the size of the overall table (in terms of key-value
pairs, not size in hard memory). *These values will not change for the
duration of the tied hash*. The newly-allocated hash table may now have
data stored and retrieved. Efforts to store more than `$table_size'
elements will result in a fatal error, as will efforts to store a value
not exactly `$value_len' characters in length, or reference through a key
not exactly `$key_len' characters in length. While these constraints may
seem excessive, the result is a hash table using much less internal memory
than an equivalent freely-allocated hash table.

CAVEATS
=======

   Because the current implementation uses the table and key sizes for the
hashing algorithm, there is no means by which to dynamically change the
value of any of the initialization parameters.

Perl extension for tie'ing a filehandle to Syslog
*************************************************

NAME
====

   Tie::Syslog - Perl extension for tie'ing a filehandle to Syslog

SYNOPSIS
========

     use Tie::Syslog;

     ###
     ##  Pass up to four args:
     ##    facility.priority   ('local0.error')
     ##    identity            ('my_program')
     ##    log options         ('pid')
     ##    setlogsock          ('inet'|'unix')
     ###
     tie *MYLOG, 'Tie::Syslog','local0.error','my_program','pid','inet';

     print MYLOG "I made an error."; ## this will be syslogged
     printf MYLOG "Error %d", 42;    ## syslog as "Error 42"

     untie *MYLOG;

DESCRIPTION
===========

   This module allows you to tie a filehandle (output only) to syslog. This
becomes useful in general when you want to capture any activity that
happens on STDERR and see that it is syslogged for later perusal. You can
also create an arbitrary filehandle, say LOG, and send stuff to syslog by
printing to this filehandle. This module depends on the Sys::Syslog module
to actually get info to syslog.

   Tie your filehandle to syslog using a glob to the filehandle. When it is
tied to the 'Tie::Syslog' class, you may optionally pass four arguments
that determine the behavior of the output bound to syslog.

   You first specify a facility and priority to direct your filehandle
traffic to the proper channels in syslog. I suggest reviewing a manpage
for syslog on your local system to identify what the facilities and
priorities actually are. Nonetheless, this first argument is specified as
a string consisting of the facility followed by a dot, followed by the
priority. For example, the default setting is 'local0.error'. If you do
not specify a first arg, this default is used.

   The second argument is an identifier string. This is the string that
shows up in evey line of output that syslog writes. You may use this
identifier to help sort out syslog lines produced by different
applications (with different id's.) If you do not specify a value for this
argument, it will default to the name of the running program. (This is
derived from the special $0 variable, stripping off everything up to the
final appearing forward slash character.)

   The third argument is a string of comma separated log options specific
to syslog. Current documentation supports 'pid,cons,ndelay,nowait'. Check
your local listings, as you may pass values that are only part of your
local system. I suggest checking your man pages for syslog, and perhaps
looking inside your site_perl/$archname/sys/syslog.ph for other such
values.  If you do not pass this third argument, it defaults to the string
'pid', which makes syslog put a [12345] pid value on each line of output.

   The fourth argument is either the string 'inet' or 'unix'. This is
passed to the Sys::Syslog::setlogsock() call to specify the socket type to
be used when opening the connection to syslog. If this argument is not
specified, then the default used is 'inet'. Many perl installations still
have original Sys::Syslog which does not have the setlogsock() routine.
There is also no $VERSION constant to test in Sys::Syslog, so we'll test
the symbol table to see if the routine exists. If the routine does not
exist, then the fourth argument is silently ignored. I did not want to
require people to have "the latest" version of perl just to use this
module.

   An aside on using 'STDERR':

   The blessed object that is returned from tie also has one additional
member function. In the case that you tie the filehandle 'STDERR' (or a
dup'ed copy of STDERR) then you may want to capture information going to
the warn() and die() functions. You may call ExtendedSTDERR() to setup the
proper handler function to deal with the special signals for __DIE__ and
__WARN__. Because this module really has no knowledge of what filehandle
is being tied, I contemplated trying to make this automatic for when the
STDERR filehandle is used. But, alas, one may have a different name for
what is really STDERR, plus the TIEHANDLE function has no way of knowing
what the filehandle symbol is anyway.  I also decided to put the logic of
how to handle the two signal cases into this module, when perhaps they
might be more suited to be at the level of whoever is calling this module.
Well, you don't have to call the routine ExtendedSTDERR() if you don't
like what it does. I felt obligated to provide a proper solution to the
signal handling since a common use of this module would be to capture
STDERR for syslogging.

     my $x = tie *STDERR, 'Tie::Syslog', 'local0.debug';
     $x->ExtendedSTDERR();            ## set __DIE__,__WARN__ handler

     print STDERR "I made an error."; ## this will be syslogged
     printf STDERR "Error %d", 42;    ## syslog as "Error 42"
     warn "Another error was made.";  ## this will also be syslogged
     eval {
         die "exception thrown";      ## this is *NOT* syslogged
     };
     die "Killing me softly?!";       ## syslogged, then script ends

     undef $x;                        ## be sure to do this, else warns!
     untie *STDERR;

   When used with STDERR, combined with the good habit of using the perl -w
switch, this module happens to be useful in catching unexpected errors in
any of your code, or team's code. Tie::Syslog is pretty brain-dead.
However, it can become quite flexible if you investigate your options with
the actual syslog daemon. Syslog has a variety of options available,
including notifying console, logging to other machines running syslog, or
email support in the event of Bad Things. Consult your syslog documentation
to get /etc/syslog.conf setup by your sysadmin and use Tie::Syslog to get
information into those channels.

BUGS
====

   If you do not specify an identity (2nd arg) to tie() it defaults to the
name of the executable via special var $0. It is split by the character
'/', so non-unix systems will end up with a "full name" for its identity,
if left unspecified.

AUTHOR
======

   Copyright (C) 1999 Broc Seib. All rights reserved. This program is free
software; you can redistribute it and/or modify it under the same terms as
Perl itself.

REVISION
========

   $Id: Syslog.pm,v 1.5 1999/09/02 05:36:38 bseib Exp $

SEE ALSO
========

   Read perldoc perltie for info on how to tie a filehandle.  Read perldoc
Sys::Syslog.  Read man syslog to learn more about syslog.

interface to directory of files
*******************************

NAME
====

   Tie::TextDir - interface to directory of files

SYNOPSIS
========

     use Tie::TextDir;
     tie (%hash, 'Tie::TextDir', '/some_directory', 'rw');  # Open in read/write mode
     $hash{'one'} = "some text";         # Creates file /some_directory/one
                                         # with contents "some text"
     untie %hash;

     tie (%hash, 'Tie::TextDir', '/etc');    # Defaults to read-only mode
     print $hash{'passwd'};  # Prints contents of /etc/passwd

DESCRIPTION
===========

   This is the Tie::TextDir module.  It is a TIEHASH interface which lets
you tie a Perl hash to a directory of textfiles.

   To use it, tie a hash to a directory:

     tie (%hash, "/some_directory", 'rw');  # Open in read/write mode

   If you pass 'rw' as the third parameter, you'll be in read/write mode,
and any changes you make to the hash will create or modify files in the
given directory.  If you don't open in read/write mode you'll be in
read-only mode, and any changes you make to the hash won't have any effect
in the given directory.

LIMITATIONS
===========

   You may not use the empty string, '.', or '..' as a key in a hash,
because they would all cause integrity problems in the directory.

   This has only been tested on the UNIX platform, and some of the shadier
techniques probably won't work right on MacOS or DOS.

CAUTIONS
========

   Strange characters can cause problems when used as the keys in a hash.
For instance, if you accidentally store '../../f' as a key, you'll
probably mess something up.  If you knew what you were doing, you're
probably okay.  I'd like to add an optional (by default on) "safe" mode
that URL-encodes keys (I've lost the name of the person who suggested
this, but thanks!).

AUTHOR
======

   Ken Williams (ken@forum.swarthmore.edu)

COPYRIGHT
=========

   Copyright (c) 1998 Ken Williams/Swarthmore College.  All rights
reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1).

A Perl tie to a dictionary file
*******************************

NAME
====

   `Tie::TieDict' - A Perl tie to a dictionary file

SYNOPSIS
========

     tie %MyDict, 'Tie::TieDict', *FILEHANDLE, $Dict, $fold

     tie %MyDict, 'Tie::TieDict', $FileName, $Dict, $fold

   *dict* is optional; defaults to true.  If *dict* is true, search the
file in dictionary order  - ignore anything but whitespace and word
characters.

   fold is optional; defaults to true.  If fold is true, ignore case.

DESCRIPTION
===========

Methods
-------

   `Data_scan' - this scans the passed string and returns the working
structure for whatever the string is.  Defaults to just returning the
string; override this method if you want something better.

   `Data_fmt' - this formats the passed structure into a string.  This
structure was (most likely) generated by `Data_scan' and should able to be
read by it later.

Format of file
--------------

     KEY - DATA

   The KEY begins with any non space character, may otherwise contain any
character, but must end with a character other than a dash or a space.
The DATA part is scanned by the `Data_scan' method.

AUTHOR
======

   Randall Maas (`randym@acm.org' in this node, `http:' in this node)

False and true, alternately, ad infinitum.
******************************************

NAME
====

   Tie::Toggle - False and true, alternately, ad infinitum.

SYNOPSIS
========

     use Tie::Toggle;

     tie my $toggle, 'Tie::Toggle';

     foreach my $number ( 0 .. 10 )
     	{
     	next unless $toggle;

     	print $number, "\n";
     	}

     =head1 DESCRIPTION

   You use `Tie::Toggle' to go back and forth between false and true over
and over again. You don't have to worry about any of this since the magic
of tie does that for you by using `Tie::Cycle'.

   You can also use `Tie::FlipFlop' by Abigail to do the same thing, but
with any two values.

AUTHOR
======

   brian d foy <brian+cpan@smithrenaud.com>.

COPYRIGHT and LICENSE
=====================

   Copyright 2000 by brian d foy.

   This software is available under the same terms as perl.

Edit hash in transactions not changing order during trans.
**********************************************************

NAME
====

   Tie::TransactHash - Edit hash in transactions not changing order during
trans.

SYNOPSIS
========

     use Tie::TransactHash;
     $::edit_db = tie %::edit_me, TransactHash, \%::db_as_hash, $::db;
     while (($key, $value)=each %edit_me)) {
       $::edit_me{$key} ++ if $key =~ m/counters/ ;
     }

DESCRIPTION
===========

   Tie::TransactHash is a package which provides facilities for editing
any other hash in transactions.  A transaction is a group of changes which
go together and are either all applied or none.  When working on a
standard perl hash or a hash indexed DBM file, one advantage is that the
original hash remains untouched during the transaction, so its order (the
order the each(), keys() or values functions give out) is maintained -
changes can be made to the transact hash whilst iterating over it.

OVERVIEW
========

   Editing a hash causes problems because it rearranges the hash.  If the
editing is to be done in sequence then this makes life difficult.  The
TransactHash class uses a fixed sequence hash class which overlays the
normal hash and allows editing in place.  It stores all of the changes to
the original hash in memory until it is told to apply them.

   As a side effect of this design, the class also provides a
commit/rollback system.  When a commit is called, the order of the hidden
hash will be changed.

   A commit will normally be done as the TransactHash object is being
destroyed.  This could be undesirable if your program exits when it
discovers a failure.  You can change the.

   If you can accept the re-ordering, then you can do partial edits and
commit half way through.

   When working on a DBM file, if a crash occurs during the editing and no
commit has been called then the original hash will be left intact.  If
however the crash occurs during the commit, bad things could happen.

     use DB_File;
     use Tie::TransactHash;
     use Fcntl;

     $::db = tie %::db_as_hash, DB_File, $::dbname, O_RDWR|O_CREAT, 0640, $db_type
       or die $!;

     $::edit_db = tie %::edit_me, TransactHash, \%::db_as_hash, $::db;
     #the $::db doesn't really do any good right now, but in future it might

     my $count = 0;
     my ($key,$value)
     while(($key,$_)=each %edit_me) {
       s/bouncy/bouncy, very very bouncy./;
       m/Fred/ && do {
     	 $count++;
     	 $edit_me{ Fred . $count } = $key;
       }
     }
     print "Found Fred in the values $count times\n";

   Generally, this package should be used if you want to occasionally do
small numbers of changes across the values of a large hash.  If you are
using it overly (often or for large numbers of changes on the database),
then you should probably switch to btree indexed hashes (Berkley DBM)
which give you the same ordering effect but don't use a large chunk of
memory.  Alternately you could consider some kind of multi-pass algorithm
(scan through the database putting planned changes to a file then apply
them afterwards all in one go).

METHODS
=======

new( \%hidehash [,$hideobj] )
-----------------------------

   This creates a new TransactHash, hiding the hash \%hidehash.

TIEHASH (and other hash methods)
--------------------------------

   This is simply a call to new.  See above.  The other hash methods are
just as for a standard hash (see perltie) and act just like one.

Iterator functions (FIRSTKEY & NEXTKEY)
---------------------------------------

   The iterators first iterate over the hidden hash as normal (giving out
changed values) then iterate over the storehash skipping values in the
original hash.

commit() and reset()
--------------------

   These functions are not normally visible in the hash interface, but can
be used as object methods.  commit() updates the original hidden hash
(which changes its order) and reset() loses all of the changes that we
have made.

   In the hash interface commit is called as the variable is destroyed.
This should happen at exit time, but didn't seem to to me.  Assigning
undef to the variable you stored the object in and untie()ing the hash
will force it to happen.

$transhash->autostore()
-----------------------

   This method stores a true or false value in the object telling it
whether it should automatically commit if it is destroyed.  If this is set
to false, then the object method $transhash->commit() must be called to
store any changes, otherwise they will be lost.

   If this is set to true, then be aware that exiting your program from
some kind of error condition of your program (that is, not one perl knows
about) would commit the changes.

$transhash->verify_write()
--------------------------

   This function checks that a write has committed to the hash correctly.
It does this by checking that all of the values in the old temporary
stores match those in the new ones.

   This function is untested since I don't have a sensible test case for
it yet and don't need it myself.  should work though.

COPYING
-------

     Copyright (c) 1997 Michael De La Rue

   This is free software and may be distributed under the same terms as
perl.  There is no warantee.  See the file COPYING which should have been
included with the distribution for one set of terms under which it may be
distributed.  The artistic license, distributed with perl gives the other
one.

Tied interface to multi-dimensional (Two-Level) hash files
**********************************************************

NAME
====

   Tie::TwoLevelHash - Tied interface to multi-dimensional (Two-Level)
hash files

SYNOPSIS
========

     # Tie to Hash-o-hashes
     use Tie::TwoLevelHash;
     tie (%hash, 'Tie::TwoLevelHash', $file, 'rw');  # Open in read/write mode

     $hash{PEOPLE} = {YOU => "me"}; # Set value YOU in hash PEOPLE withing hash %hash to "me"

     # Tie to hash within a Hash-o-hashes
     use Tie::TwoLevelHash:
     tie (%hash, 'Tie::TwoLevelHash', "$file, <SingHash>" 'rw');  # Open in read/write mode

     $hash{YOU} = "me"; # Set key YOU in hash <SingHash> (within HoH's) to "me"

     untie %hash;

     tie (%hash, 'Tie::TwoLevelHash', $file);    # Defaults to read-only mode

     ...

     untie %hash;

DESCRIPTION
===========

   This is the Tie::TwoLevelHash module.  It is a TIEHASH interface which
lets you tie to a text file which is a multi-dimensional (two level) hash.

   To use it, tie a hash to a directory:

     tie(%hash, 'Tie::TwoLevelHash', $file, 'rw');  # Open in read/write mode

   If you pass 'rw' as the third parameter, you'll be in read/write mode,
and any changes you make to the hash will create or modify the file.  If
you don't open in read/write mode you'll be in read-only mode, and any
changes you make to the hash won't have any effect in the given file. It's
actually useless to tie to the file in read mode and make write calls to
it, or the hash you are tying to it. If you do, it may croak, depending on
what you are trying. If you want to grab values and play with them, do
that in your script, and get the values out of the hash name you are tying
with, so you can write to a local hash, and not affect, or try to affect
the hash you are tying with.

Two Level Hash Files
====================

   A two level hash file (I use a .tlh extension) is a file after the same
format as the defunct(?) Windows .ini files. A simple example of a small
TLH file is as follows:

     # This is a TLH file
     # Comments on top of this file are allowed

     COLORS
     	Red: #ff0000
     	Black: #000000
     	White: #ffffff

     PEOPLE
     	Dog: Zeke
     	Cat: Tigger
     	PerlHacker: Randal
     	Author: Kevin Meltzer

     EXTRA
     	Key: Val
     	Test: Vest

   This file is a textual representation of a two-level hash, also known
as a Hash of hashes. The file itself is the main hash, and each section
contains another hash. So, this file contains the hash COLORS the hash
PEOPLE and the hash EXTRA.  *Tie::TwoLevelHash* allows for you to tie to
the entire hash of hashes, or directly to one of the hashes within that
hash of hashes. When you make a change in your script to the tied hash, it
makes that change in your file.

EXAMPLES
========

Tying to hash of hashes
-----------------------

     $file = "foo.tlh";
     tie(%hash, 'Tie::TwoLevelHash', $file, 'rw');

     # Set %foo to equal %hash
     %foo = %hash;

     # Grab value of BAR in hash FOO into $bar
     $bar = $hash{FOO}->{BAR};

     # Set existing value
     $hash{PEOPLE} = {You => "me"};

     # Set new value
     $hash{COLORS} = {YELLOW => "flowery"};

     # Set new record
     $hash{HATS} = {BLACK => "Cowboy", RED => "Baseball", WHITE => "Beanie"};

     # Add new record with predefined hash
     %new = (ONE => "1",
     	TWO => "2",
     	THREE => "3",
     	FOUR => "4",
     	);

     $hash{NUM} = {%new}; # Works, or can use \%new instead of {%new}

     # Clear, set then delete entry
     $hash{PEOPLE} = {FOO => ""};
     $hash{PEOPLE} = {FOO => "Bar"};
     $hash{PEOPLE} = {FOO => undef};

     # Added new element to existing record
     $hash{PEOPLE} = {'FOO' => "FOObar"};

     $hash{EXTRA} = undef;

     untie %hash;

     The resulting TLH file would be (assuming you began with the TLH example above):

     # This is a TLH file
     # Comments on top of this file are allowed

     COLORS
     	Black: #000000
     	Red: #ff0000
     	White: #ffffff
     	Yellow: flowery

     HATS
     	BLACK: Cowboy
     	RED: Baseball
     	WHITE: Pope hat

     NUM
     	FOUR: 4
     	ONE: 1
     	THREE: 3
     	TWO: 2

     PEOPLE
     	Author: Kevin Meltzer
     	Cat: Tigger
     	Dog: Zeke
     	FOO: FOObar
     	PerlHacker: Randal

Tying to a hash within a hash of hashes
---------------------------------------

     tie(%hash, 'Tie::TwoLevelHash', "$file, PEOPLE", 'rw');

     # Set %foo to equal %hash
     %foo = %hash;

     # Grab value of FOO into $bar
     $bar = $hash{FOO};

     # Set existing value
     $hash{Cat} = "Gizmo";

     # Set new value
     $hash{Someone} = "Larry";

     # Clear, set then delete entry
     $hash{FOO} = "";
     $hash{FOO} = "bar";
     $hash{FOO} = undef;

     untie %hash;

   The resulting TLH file would be:

     # This is a TLH file
     # Comments on top of this file are allowed

     COLORS
     	Red: #ff0000
     	Black: #000000
     	White: #ffffff

     PEOPLE
     	Author: Kevin Meltzer
     	Cat: Gizmo
     	Dog: Zeke
     	PerlHacker: Randal
     	Someone: Larry

     EXTRA
     	Key: Val
     	Test: Vest

Getting the value of your tied hash to your local script
--------------------------------------------------------

   When you are tied to the hash, tie doesn't actually export the values
in that hash (or HoH) by default. So, *Tie::TwoLevelHash* exports a method
that allows you to muck around with the hash's actual values within your
script. This can also be useful if, for whatever reason, you don't want to
write out the hash file whenever you make a change, and wish to do it at a
later time, while still working with the new values.

With a hash-o-hashes
....................

     # Tie your hash, but use a scaler to be object-like
     tie(%hash, "Tie::TwoLevelHash" , $file, 'rw');

     # Make untied copy of your tied HoH
     %bar = %hash;

   Now, you can generally use %bar as you would any other hash-o-hashes.
Above we tied to the entire hash-o-hashes, so %bar will be filled with hash
references. You could do something like the following to list all the hash
names, and values:

     foreach $key (keys %bar) {
     print "$key\n";
     	$foo = $bar{$key};
     	%foo = %$foo; # Deref the lower hash
     	foreach $fookey (keys %foo) {
     		print "\t$fookey\: $foo{$fookey}\n";
     	}
     }

   Now, say you wanted to change one of the values, but not change it in
your TLH file just yet. You can do this like:

     # This line changes the value in %bar
     $bar{PEOPLE}->{Comedian} = "Sienfeld";

     # This line writes the new value to your tied hash (and TLH)
     $hash{PEOPLE} = $bar{PEOPLE};

With a hash in a hash-o-hashes
..............................

   This way is slightly different. Right now, trying to make a copy of your
hash the same way you do above, does not copy the hash correctly. So,
there is a method, *GetHash* , which will export it correctly.

     # Tie your hash, but use a scaler to be object-like
     $foo = tie(%hash, "Tie::TwoLevelHash" , "$file, PEOPLE", 'rw');

     # Now, we will call the method that exports the hash
     # We will import it into the hash %bar
     %bar = $foo->GetHash;

   Now, you can generally use %bar as you would any other hash. Above we
tied only to one hash in the hash-o-hashes, so %bar will be one hash.  You
could do something like the following to list all the hash names, and
values:

     foreach $key (keys %goo) {
     	print "$key\: $goo{$key}\n";
     }

   Now, if you wanted to change values before writting the new TLH file
out via your tie:

     # This line will set key Comedian to Sienfeld locally
     $bar{Comedian} = "Sienfeld";

     # Now, we write out the new hash
     %hash = %bar;

CHANGING VALUES
===============

   I won't go into how to change value in a hash. When you are tying to a
hash in the hash of hashes, you make your calls as usual. You make your
calls as usual when you are tied to the entire HoH's, except when you are
setting new values (anything that would call STORE).

   Due to tie() not being very friendly while tying to HoH's, you can not
make a call such as

   $hash{FOO}->{BAR} = "zog";

   when tied to a HoH's. So, you must make this call like:

   $hash{FOO} = {BAR => "zog"};

   You can see how/when to do this in the EXAMPLE section.  When you want
to delete a key in a hash, use undef like:

   $hash{FOO} = {BAR => undef};

   or, when tying to single hash:

   $hash{BAR} = undef;

   %hash = ();

   This will CLEAR the hash, as well as remove ALL data from the file you
are tied to.  Be *sure* you want to do this when you call it.

INSTALLATION
============

   You install Tie::TwoLevelHash, as you would install any perl module
library, by running these commands:

     perl Makefile.PL
     make
     make test
     make install
     make clean

AUTHOR
======

   Copyright 1998, Kevin Meltzer.  All rights reserved.  It may be used
and modified freely, but I do request that this copyright notice remain
attached to the file.  You may modify this module as you wish, but if you
redistribute a modified version, please attach a note listing the
modifications you have made.

   Address bug reports and comments to: kmeltz@cris.com

   The author makes no warranties, promises, or gaurentees of this
software. As with all software, use at your own risk.

VERSION
=======

   Version $Revision: 1.2 $  $Date: 1998/10/30 13:52:04 $

CHANGES
=======

   $Log: TwoLevelHash.pm,v $ Revision 1.2  1998/10/30 13:52:04  kmeltz
Fixed FETCH so it will return correctly when doing %foo = %bar; when using
a tie to a HoH's. Still not working right for hash in the HoH's, so the
GetHash method stays.

   Revision 1.1  1998/10/27 15:43:47  kmeltz Changed croaks to carps for
Hash Invalid warning. May need to continue script, so let script die and
module return undef.  Changed CLEAR to not erase TLH file when clearing
hash in HoH's, or resetting it.  Added exported method GetHash. This
allows for user to import hash values into their script, and change values
before setting them to TLH file.  Changed a bunch in the POD.

AVAILABILITY
============

   The latest version of Tie::TwoLevelHash should always be available from:

     $CPAN/modules/by-authors/id/K/KM/KMELTZ/

   Visit http://www.perl.com/CPAN/ to find a CPAN site near you.

SEE ALSO
========

   `perl(1)' in this node, `perlfunc(1)' in this node, `perltie(1)' in
this node

An array interface to a bit vector.
***********************************

NAME
====

     Tie::VecArray - An array interface to a bit vector.

SYNOPSIS
========

     require Tie::VecArray;

     $vector = '';
     vec($vector, 0, 32) = 33488897;

     # Tie the vector to an array as 8 bits.
     $obj = tie @array, 'Tie::VecArray', 8, $vector;

     @array[0..3] = qw(1 255 256 -1);

     # SURPRISE!  Its 1, 255, 0, 255!
     print @array[0..3];

     # Look at the same vector as a 32 bit vector.
     $obj->bits(32);

     # Back to 33488897
     print $array[0];

DESCRIPTION
===========

   This module implements an array interface to a bit vector.

Method
------

tie
          $vec_obj = tie(@array, 'Tie::VecArray', $bits);
          $vec_obj = tie(@array, 'Tie::VecArray', $bits, $vec);

     Creates a new @array tied to a bit vector.  $bits is the number of
     bits which will be passed to vec() to interpret the vector.

     If $vec is given that will be used as the bit vector, otherwise the
     vector will start out empty.

bits
          $bits = $vec_obj->bits;
          $vec_obj->bits($bits);

     Get/set the bit size we'll use to interpret the vector.

     When setting the bit size the length of the array might be ambiguous.
     (For instance, going from a one bit vector with five entries to a two
     bit vector... do you have two or three entries?)  The length of the
     array will always round up.  This can cause odd things to happen.
     Consider:

          $vec_obj = tie @vec, 'Tie::VecArray', 1;

          # A one bit vector with 5 entries.
          @vec[0..4] = (1) x 5;

          # prints a size of 5, as expected.
          print scalar @vec;

          # Switch to two bit interpretation.
          $vec_obj->bits(2);

          # This returns 3 since it will round up.
          print scalar @vec;

          # Switch back to one bit.
          $vec_obj->bits(1);

          # Whoops, 6!
          print scalar @vec;

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   `vec', see Perlfunc (perl.info), `vec', see Tie/Array,

place watchpoints on Perl variables.
************************************

NAME
====

     Tie::Watch - place watchpoints on Perl variables.

SYNOPSIS
========

     use Tie::Watch;

     $watch = Tie::Watch->new(
         -variable => \$frog,
         -debug    => 1,
         -shadow   => 0,
         -fetch    => [\&fetch, 'arg1', 'arg2', ..., 'argn'],
         -store    => \&store,
         -destroy  => sub {print "Final value=$frog.\n"},
     }
     %vinfo = $watch->Info;
     $args  = $watch->Args(-fetch);
     $val   = $watch->Fetch;
     print "val=", $watch->Say($val), ".\n";
     $watch->Store('Hello');
     $watch->Unwatch;

DESCRIPTION
===========

   This class module binds one or more subroutines of your devising to a
Perl variable.  All variables can have FETCH, STORE and DESTROY callbacks.
Additionally, arrays can define CLEAR, EXTEND, FETCHSIZE, POP, PUSH,
SHIFT, SPLICE, STORESIZE and UNSHIFT callbacks, and hashes can define
CLEAR, DELETE, EXISTS, FIRSTKEY and NEXTKEY callbacks.  If these term are
unfamiliar to you, I *really* suggest you read Perltie (perl.info).

   With Tie::Watch you can:

     . alter a variable's value
     . prevent a variable's value from being changed
     . invoke a Perl/Tk callback when a variable changes
     . trace references to a variable

   Callback format is patterned after the Perl/Tk scheme: supply either a
code reference, or, supply an array reference and pass the callback code
reference in the first element of the array, followed by callback
arguments.  (See examples in the Synopsis, above.)

   Tie::Watch provides default callbacks for any that you fail to specify.
Other than negatively impacting performance, they perform the standard
action that you'd expect, so the variable behaves "normally".  Once you
override a default callback, perhaps to insert debug code like print
statements, your callback normally finishes by calling the underlying
(overridden) method.  But you don't have to!

   To map a tied method name to a default callback name simply lowercase
the tied method name and uppercase its first character.  So FETCH becomes
Fetch, NEXTKEY becomes Nextkey, etcetera.

   Here are two callbacks for a scalar. The FETCH (read) callback does
nothing other than illustrate the fact that it returns the value to assign
the variable.  The STORE (write) callback uppercases the variable and
returns it.  In all cases the callback must return the correct read or
write value - typically, it does this by invoking the underlying method.

     my $fetch_scalar = sub {
         my($self) = @_;
         $self->Fetch;
     };

     my $store_scalar = sub {
         my($self, $new_val) = @_;
         $self->Store(uc $new_val);
     };

   Here are FETCH and STORE callbacks for either an array or hash.  They
do essentially the same thing as the scalar callbacks, but provide a
little more information.

     my $fetch = sub {
         my($self, $key) = @_;
         my $val = $self->Fetch($key);
         print "In fetch callback, key=$key, val=", $self->Say($val);
         my $args = $self->Args(-fetch);
         print ", args=('", join("', '",  @$args), "')" if $args;
         print ".\n";
         $val;
     };

     my $store = sub {
         my($self, $key, $new_val) = @_;
         my $val = $self->Fetch($key);
         $new_val = uc $new_val;
         $self->Store($key, $new_val);
         print "In store callback, key=$key, val=", $self->Say($val),
           ", new_val=", $self->Say($new_val);
         my $args = $self->Args(-store);
         print ", args=('", join("', '",  @$args), "')" if $args;
         print ".\n";
         $new_val;
     };

   In all cases, the first parameter is a reference to the Watch object,
used to invoke the following class methods.

METHODS
=======

$watch = Tie::Watch->new(-options => values);
     The watchpoint constructor method that accepts option/value pairs to
     create and configure the Watch object.  The only required option is
     *-variable*.

     *-variable* is a reference to a scalar, array or hash variable.

     *-debug* (default 0) is 1 to activate debug print statements internal
     to Tie::Watch.

     *-shadow* (default 1) is 0 to disable array and hash shadowing.  To
     prevent infinite recursion Tie::Watch maintains parallel variables for
     arrays and hashes.  When the watchpoint is created the parallel shadow
     variable is initialized with the watched variable's contents, and when
     the watchpoint is deleted the shadow variable is copied to the
     original variable.  Thus, changes made during the watch process are
     not lost.  Shadowing is on my default.  If you disable shadowing any
     changes made to an array or hash are lost when the watchpoint is
     deleted.

     Specify any of the following relevant callback parameters, in the
     format described above: *-fetch*, *-store*, *-destroy*.  Additionally
     for arrays: *-clear*, *-extend*, *-fetchsize*, *-pop*, *-push*,
     *-shift*, *-splice*, *-storesize* and *-unshift*.  Additionally for
     hashes: *-clear*, *-delete*, *-exists*, *-firstkey* and *-nextkey*.

$args = $watch->Args(-fetch);
     Returns a reference to a list of arguments for the specified callback,
     or undefined if none.

$watch->Fetch();  $watch->Fetch($key);
     Returns a variable's current value.  $key is required for an array or
     hash.

%vinfo = $watch->Info();
     Returns a hash detailing the internals of the Watch object, with these
     keys:

          %vinfo = {
              -variable =>  SCALAR(0x200737f8)
              -debug    =>  '0'
              -shadow   =>  '1'
              -value    =>  'HELLO SCALAR'
              -destroy  =>  ARRAY(0x200f86cc)
              -fetch    =>  ARRAY(0x200f8558)
              -store    =>  ARRAY(0x200f85a0)
              -legible  =>  above data formatted as a list of string, for printing
          }

     For array and hash Watch objects, the *-value* key is replaced with a
     *-ptr* key which is a reference to the parallel array or hash.
     Additionally, for an array or hash, there are key/value pairs for all
     the variable specific callbacks.

$watch->Say($val);
     Used mainly for debugging, it returns $val in quotes if required, or
     the string "undefined" for undefined values.

$watch->Store($new_val);  $watch->Store($key, $new_val);
     Store a variable's new value.  $key is required for an array or hash.

$watch->Unwatch();
     Stop watching the variable.

EFFICIENCY CONSIDERATIONS
=========================

   If you can live using the class methods provided, please do so.  You
can meddle with the object hash directly and improved watch performance,
at the risk of your code breaking in the future.

AUTHOR
======

   Stephen.O.Lidie@Lehigh.EDU

HISTORY
=======

     lusol@Lehigh.EDU, LUCC, 96/05/30
     . Original version 0.92 release, based on the Trace module from Hans Mulder,
       and ideas from Tim Bunce.

     lusol@Lehigh.EDU, LUCC, 96/12/25
     . Version 0.96, release two inner references detected by Perl 5.004.

     lusol@Lehigh.EDU, LUCC, 97/01/11
     . Version 0.97, fix Makefile.PL and MANIFEST (thanks Andreas Koenig).
       Make sure test.pl doesn't fail if Tk isn't installed.

     Stephen.O.Lidie@Lehigh.EDU, Lehigh University Computing Center, 97/10/03
     . Version 0.98, implement -shadow option for arrays and hashes.

     Stephen.O.Lidie@Lehigh.EDU, Lehigh University Computing Center, 98/02/11
     . Version 0.99, finally, with Perl 5.004_57, we can completely watch arrays.
       With tied array support this module is essentially complete, so its been
       optimized for speed at the expense of clarity - sorry about that. The
       Delete() method has been renamed Unwatch() because it conflicts with the
       builtin delete().

     Stephen.O.Lidie@Lehigh.EDU, Lehigh University Computing Center, 99/04/04
     . Version 1.0, for Perl 5.005_03, update Makefile.PL for ActiveState, and
       add two examples (one for Perl/Tk).

COPYRIGHT
=========

   Copyright (C) 1996 - 1999 Stephen O. Lidie. All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl interface to the Tiger Hash Algorithm
******************************************

NAME
====

   Tiger - Perl interface to the Tiger Hash Algorithm

SYNOPSIS
========

     use Tiger;

     $context = new Tiger;
     $context->reset();

     $context->add(LIST);
     $context->addfile(HANDLE);

     $digest = $context->digest();
     $string = $context->hexdigest();

     $digest = $context->hash($string);
     $string = $context->hexhash($string);

DESCRIPTION
===========

   The *Tiger* module allows you to use the Tiger hash algorithm developed
by Ross Anderson and Eli Biham in Perl programs.

   A new Tiger context object is created with the new operation.  Multiple
simultaneous digest context can be maintained if desired.  The context is
updated with the add operation which adds the strings contained in the
LIST parameter.

   The final message digest value is returned by the digest operation as a
24-byte binary string. This operation delivers the result of operations
since the last new or reset operation. Once the operation has been
performed, the context must be reset before being used to calculate
another digest value.

   Several convenience functions are also provided. The *addfile*
operation takes an open file-handle and reads it until end-of file in
8192-byte blocks adding the contents to the context. The *hexdigest*
operation calls digest and returns the result as a printable string of
hexadecimal digits in eight-digit groups. The hash operation performs the
complete series of steps: reset, add, digest on the supplied scalar value,
and returns the result as a 24-byte binary string. The *hexhash* operation
does the same thing, but returns the result in the format of the
*hexdigest* operation.

NOTE
====

   The Tiger extension may be redistributed either under the GPL or the
Perl Artistic License.  The Tiger code has been appropriated from the GNU
Privacy Guard, and slightly modified to interface with Perl.

AUTHOR
======

   The Tiger interface was written by Rafael Sevilla
(`dido@pacific.net.ph'), shamelessly stealing from the SHA interface
written by Uwe Hollerbach (`uh@alumni.caltech.edu').

   For more information on Tiger see:

   http://www.cs.technion.ac.il/~biham/Reports/Tiger/

A Perl module to calculate time availability.
*********************************************

NAME
====

   Time::Avail - A Perl module to calculate time availability.

SYNOPSIS
========

   `use Time::Avail;'

   `$minRemaining = timeAvailable( $timeStartStr, $timeEndStr, $dayMask );'

DESCRIPTION
===========

   The *timeAvailable* function compares the time interval specified by
*timeStartStr*, *timeEndStr*, and *dayMask* with the current day and time.
*timeAvailable* returns *0 * if the current day and time do not fall within
the specified time interval, otherwise the number of minutes remaining is
returned.  *timeStartStr* and *timeEndStr* are string parameters that must
adhere to a *HH:MM 24 hour* format, where *HH* represents a two digit hour
value and *MM* represents a two digit minute value.  *dayMask* is a
bitmask which specifies the valid days for the time interval.

   The *dayMask* parameter is constructed by OR'ing together one or more
of the following dayMask constants:

   * Time::Avail::DAY_MONDAY

   * Time::Avail::DAY_TUESDAY

   * Time::Avail::DAY_WEDNESDAY

   * Time::Avail::DAY_THURSDAY

   * Time::Avail::DAY_FRIDAY

   * Time::Avail::DAY_SATURDAY

   * Time::Avail::DAY_SUNDAY

   * Time::Avail::DAY_WEEKDAY

   * Time::Avail::DAY_WEEKEND

   * Time::Avail::DAY_EVERYDAY

EXAMPLES
--------

   To calculate the time remaining given a starting time of 5am and an
ending time of 5pm for Sunday and Monday, the call to *timeAvailable* can
be coded as follows:

   `$minRemaining = timeAvailable( "05:00", "17:00",
Time::Avail::DAY_SUNDAY | Time::Avail::DAY_MONDAY );'

   To calculate the time remaining given a starting time of 10:30am and an
ending time of 7:45pm for Saturday, Sunday, and Monday, the call to
*timeAvailable* can be coded as follows:

   `$minRemaining = timeAvailable( "10:30", "19:45",
Time::Avail::DAY_SATURDAY |  Time::Avail::DAY_SUNDAY
|Time::Avail::DAY_MONDAY );'

   or

   `$minRemaining = timeAvailable( "10:30", "19:45",
Time::Avail::DAY_WEEKEND | Time::Avail::DAY_MONDAY );'

   To calculate the time remaining given a starting time of 7am and an
ending time of 7pm for everyday but Saturday and Sunday, the call to
*timeAvailable* can be coded as follows:

   `$minRemaining = timeAvailable( "07:00", "19:00",
Time::Avail::DAY_WEEKDAY );'

   To calculate the time remaining given a starting time of 10pm and an
ending time of 2am for everyday, the call to *timeAvailable* can be coded
as follows:

   `$minRemaining = timeAvailable( "22:00", "02:00",
Time::Avail::DAY_EVERYDAY );'

VERSION
=======

   1.00

HISTORY
=======

     Version 1.00
     ------------
     	- Released.

AUTHOR
======

   Peter Santoro peter@pscomp.com

COPYRIGHT
=========

   Copyright (c) 1998 Peter Santoro.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself; however, you must leave this copyright statement
intact.

DATE
====

   December 19, 1998

SOURCE
======

   This distribution can be also be found at the author's web site:

     http://www.connix.com/~psantoro/

Module to convert from standard time to swatch 'beat' time.
***********************************************************

NAME
====

   Time::Beat - Module to convert from standard time to swatch 'beat' time.

SYNOPSIS
========

   use Time::Beat qw ( beattime );

   my $time_in_beats = beattime(time());

DESCRIPTION
===========

   `Time::Beat' is a module to provide you with the time in beats.  It
takes a `time()' formatted string, and outputs the time in beats.  The
basic algorithm for doing this is to take time in GMT+1 hour, convert it
into seconds, and divide by 86.4.  Hopefully I'll get it converting
backwards at some point.

FUNCTIONS
=========

beattime [time string]
     beattime is the one and only function in Time::Beat.  It will give you
     the current time in beats if you do not specify a time string.  If you
     specify a time string it will return that particular time in beats.

CHANGES
=======

   If gmtime.hours == 23 before then problems were caused because the hour
became 24 - it should have been 0.  The problem has now been fixed.

AUTHOR
======

   James A. Duncan <j@mesduncan.co.uk>

SEE ALSO
========

   perl(1)

format times ala POSIX asctime
******************************

NAME
====

   Time::CTime - format times ala POSIX asctime

SYNOPSIS
========

     use Time::CTime
      	print ctime(time);
     print asctime(localtime(time));
     print strftime(template, localtime(time));

strftime conversions
--------------------

     %%	PERCENT
     %a	day of the week abbr
     %A	day of the week
     %b	month abbr
     %B 	month
     %c 	ctime format: Sat Nov 19 21:05:57 1994
     %d 	DD
     %D 	MM/DD/YY
     %e 	numeric day of the month
     %f 	floating point seconds (milliseconds): .314
     %F 	floating point seconds (microseconds): .314159
     %h 	month abbr
     %H 	hour, 24 hour clock, leading 0's)
     %I 	hour, 12 hour clock, leading 0's)
     %j 	day of the year
     %k 	hour
     %l 	hour, 12 hour clock
     %m 	month number, starting with 1
     %M 	minute, leading 0's
     %n 	NEWLINE
     %o	ornate day of month -- "1st", "2nd", "25th", etc.
     %p 	AM or PM
     %r 	time format: 09:05:57 PM
     %R 	time format: 21:05
     %S 	seconds, leading 0's
     %t 	TAB
     %T 	time format: 21:05:57
     %U 	week number, Sunday as first day of week
     %w 	day of the week, numerically, Sunday == 0
     %W 	week number, Monday as first day of week
     %x 	date format: 11/19/94
     %X 	time format: 21:05:57
     %y	year (2 digits)
     %Y	year (4 digits)
     %Z 	timezone in ascii. eg: PST

DESCRIPTION
===========

   This module provides routines to format dates.  They correspond to the
libc routines.  &strftime() supports a pretty good set of coversions -
more than most C libraries.

   strftime supports a pretty good set of conversions.

   The POSIX module has very similar functionality.  You should consider
using it instead if you do not have allergic reactions to system libraries.

GENESIS
=======

   Written by David Muir Sharnoff <muir@idiom.com>.

   The starting point for this package was a posting by Paul Foley
<paul@ascent.com>

   Copyright (C) 1996-1999 David Muir Sharnoff.  All Rights Reserved.  Use
and redistribution allowed at user's own risk.

simply report the number of days in a month
*******************************************

NAME
====

   Time::DaysInMonth - simply report the number of days in a month

SYNOPSIS
========

     use Time::DaysInMonth;
     $days = days_in($year, $month_1_to_12);
     $leapyear = is_leap($year);

DESCRIPTION
===========

   DaysInMonth is simply a package to report the number of days in a
month.  That's all it does.  Really!

AUTHOR
======

   David Muir Sharnoff <muir@idiom.com>

   Copyright (C) 1996-1999 David Muir Sharnoff.  All Rights Reserved.  Use
and redistribution allowed at user's own risk.

High resolution ualarm, usleep, and gettimeofday
************************************************

NAME
====

   Time::HiRes - High resolution ualarm, usleep, and gettimeofday

SYNOPSIS
========

     use Time::HiRes qw( usleep ualarm gettimeofday tv_interval );

     usleep ($microseconds);

     ualarm ($microseconds);
     ualarm ($microseconds, $interval_microseconds);

     $t0 = [gettimeofday];
     ($seconds, $microseconds) = gettimeofday;

     $elapsed = tv_interval ( $t0, [$seconds, $microseconds]);
     $elapsed = tv_interval ( $t0, [gettimeofday]);
     $elapsed = tv_interval ( $t0 );

     use Time::HiRes qw ( time alarm sleep );
     $now_fractions = time;
     sleep ($floating_seconds);
     alarm ($floating_seconds);
     alarm ($floating_seconds, $floating_interval);

DESCRIPTION
===========

   The `Time::HiRes' module implements a Perl interface to the usleep,
ualarm, and gettimeofday system calls. See the EXAMPLES section below and
the test scripts for usage; see your system documentation for the
description of the underlying gettimeofday, usleep, and ualarm calls.

   If your system lacks gettimeofday(2) you don't get gettimeofday() or the
one-arg form of tv_interval().  If you don't have usleep(3) or select(2)
you don't get usleep() or sleep().  If your system don't have ualarm(3) or
setitimer(2) you don't get ualarm() or alarm().  If you try to import an
unimplemented function in the use statement it will fail at compile time.

   The following functions can be imported from this module.  No functions
are exported by default.

gettimeofday ()
     In array context it returns a 2 element array with the seconds and
     microseconds since the epoch.  In scalar context it returns floating
     seconds like Time::HiRes::time() (see below).

usleep ( $useconds )
     Issues a usleep for the number of microseconds specified. See also
     Time::HiRes::sleep() below.

ualarm ( $useconds [, $interval_useconds ] )
     Issues a ualarm call; interval_useconds is optional and will be 0 if
     unspecified, resulting in alarm-like behaviour.

tv_interval ( $ref_to_gettimeofday [, $ref_to_later_gettimeofday] )
     Returns the floating seconds between the two times, which should have
     been returned by gettimeofday(). If the second argument is omitted,
     then the current time is used.

time ()
     Returns a floating seconds since the epoch. This function can be
     imported, resulting in a nice drop-in replacement for the time
     provided with perl, see the EXAMPLES below.

sleep ( $floating_seconds )
     Converts $floating_seconds to microseconds and issues a usleep for the
     result.  This function can be imported, resulting in a nice drop-in
     replacement for the sleep provided with perl, see the EXAMPLES below.

alarm ( $floating_seconds [, $interval_floating_seconds ] )
     Converts $floating_seconds and $interval_floating_seconds and issues a
     ualarm for the results.  The $interval_floating_seconds argument is
     optional and will be 0 if unspecified, resulting in alarm-like
     behaviour.  This function can be imported, resulting in a nice drop-in
     replacement for the alarm provided with perl, see the EXAMPLES below.

EXAMPLES
========

     use Time::HiRes qw(usleep ualarm gettimeofday tv_interval);

     $microseconds = 750_000;
     usleep $microseconds;

     # signal alarm in 2.5s & every .1s thereafter
     ualarm 2_500_000, 100_000;

     # get seconds and microseconds since the epoch
     ($s, $usec) = gettimeofday;

     # measure elapsed time
     # (could also do by subtracting 2 gettimeofday return values)
     $t0 = [gettimeofday];
     # do bunch of stuff here
     $t1 = [gettimeofday];
     # do more stuff here
     $t0_t1 = tv_interval $t0, $t1;

     $elapsed = tv_interval ($t0, [gettimeofday]);
     $elapsed = tv_interval ($t0);	# equivalent code

     #
     # replacements for time, alarm and sleep that know about
     # floating seconds
     #
     use Time::HiRes;
     $now_fractions = Time::HiRes::time;
     Time::HiRes::sleep (2.5);
     Time::HiRes::alarm (10.6666666);

     use Time::HiRes qw ( time alarm sleep );
     $now_fractions = time;
     sleep (2.5);
     alarm (10.6666666);

C API
=====

   In addition to the perl API described above, a C API is available for
extension writers.  The following C functions are available in the
modglobal hash:

     name             C prototype
     ---------------  ----------------------
     Time::NVtime     double (*)()
     Time::U2time     void (*)(UV ret[2])

   Both functions return equivalent information (like gettimeofday) but
with different representations.  The names `NVtime' and `U2time' were
selected mainly because they are operating system independent.
(gettimeofday is Un*x-centric.)

   Here is an example of using NVtime from C:

     double (*myNVtime)();
     SV **svp = hv_fetch(PL_modglobal, "Time::NVtime", 12, 0);
     if (!svp)         croak("Time::HiRes is required");
     if (!SvIOK(*svp)) croak("Time::NVtime isn't a function pointer");
     myNVtime = (double(*)()) SvIV(*svp);
     printf("The current time is: %f\n", (*myNVtime)());

AUTHORS
=======

   D. Wegscheid <wegscd@whirlpool.com> R. Schertler <roderick@argon.org>
J. Hietaniemi <jhi@iki.fi> G. Aas <gisle@aas.no>

REVISION
========

   $Id: HiRes.pm,v 1.20 1999/03/16 02:26:13 wegscd Exp $

   $Log: HiRes.pm,v $ Revision 1.20  1999/03/16 02:26:13  wegscd Add
documentation for NVTime and U2Time.

   Revision 1.19  1998/09/30 02:34:42  wegscd No changes, bump version.

   Revision 1.18  1998/07/07 02:41:35  wegscd No changes, bump version.

   Revision 1.17  1998/07/02 01:45:13  wegscd Bump version to 1.17

   Revision 1.16  1997/11/13 02:06:36  wegscd version bump to accomodate
HiRes.xs fix.

   Revision 1.15  1997/11/11 02:17:59  wegscd POD editing, courtesy of
Gisle Aas.

   Revision 1.14  1997/11/06 03:14:35  wegscd Update version # for
Makefile.PL and HiRes.xs changes.

   Revision 1.13  1997/11/05 05:36:25  wegscd change version # for
Makefile.pl and HiRes.xs changes.

   Revision 1.12  1997/10/13 20:55:33  wegscd Force a new version for
Makefile.PL changes.

   Revision 1.11  1997/09/05 19:59:33  wegscd New version to bump version
for README and Makefile.PL fixes.  Fix bad RCS log.

   Revision 1.10  1997/05/23 01:11:38  wegscd Conditional compilation;
EXPORT_FAIL fixes.

   Revision 1.2  1996/12/30 13:28:40  wegscd Update documentation for what
to do when missing ualarm() and friends.

   Revision 1.1  1996/10/17 20:53:31  wegscd Fix =head1 being next to
__END__ so pod2man works

   Revision 1.0  1996/09/03 18:25:15  wegscd Initial revision

COPYRIGHT
=========

   Copyright (c) 1996-1997 Douglas E. Wegscheid.  All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Julian calendar manipulations
*****************************

NAME
====

   Time::JulianDay - Julian calendar manipulations

SYNOPSIS
========

     use Time::JulianDay

     $jd = julian_day($year, $month_1_to_12, $day)
     $jd = local_julian_day($seconds_since_1970);
     $jd = gm_julian_day($seconds_since_1970);
     ($year, $month_1_to_12, $day) = inverse_julian_day($jd)
     $dow = day_of_week($jd)

     print (Sun,Mon,Tue,Wed,Thu,Fri,Sat)[$dow];

     $seconds_since_jan_1_1970 = jd_secondslocal($jd, $hour, $min, $sec)
     $seconds_since_jan_1_1970 = jd_secondsgm($jd, $hour, $min, $sec)
     $seconds_since_jan_1_1970 = jd_timelocal($sec,$min,$hours,$mday,$month_0_to_11,$year)
     $seconds_since_jan_1_1970 = jd_timegm($sec,$min,$hours,$mday,$month_0_to_11,$year)

DESCRIPTION
===========

   JulianDay is a package that manipulates dates as number of days since
some time a long time ago.  It's easy to add and subtract time using
julian days...

   The day_of_week returned by day_of_week() is 0 for Sunday, and 6 for
Saturday and everything else is in between.

GENESIS
=======

   Written by David Muir Sharnoff <muir@idiom.com> with help from previous
work by Kurt Jaeger aka PI <zrzr0111@helpdesk.rus.uni-stuttgart.de>  	based
on postings from: Ian Miller <ian_m@cix.compulink.co.uk>; Gary Puckering
<garyp%cognos.uucp@uunet.uu.net> 	based on Collected Algorithms of the ACM
?; and the unknown-to-me author of Time::Local.

efficiently compute time from local and GMT time
************************************************

NAME
====

   Time::Local - efficiently compute time from local and GMT time

SYNOPSIS
========

     $time = timelocal($sec,$min,$hours,$mday,$mon,$year);
     $time = timegm($sec,$min,$hours,$mday,$mon,$year);

DESCRIPTION
===========

   These routines are the inverse of built-in perl fuctions localtime()
and gmtime().  They accept a date as a six-element array, and return the
corresponding time(2) value in seconds since the Epoch (Midnight, January
1, 1970).  This value can be positive or negative.

   It is worth drawing particular attention to the expected ranges for the
values provided.  While the day of the month is expected to be in the
range 1..31, the month should be in the range 0..11.  This is consistent
with the values returned from localtime() and gmtime().

   The timelocal() and timegm() functions perform range checking on the
input $sec, $min, $hours, $mday, and $mon values by default.  If you'd
rather they didn't, you can explicitly import the timelocal_nocheck() and
timegm_nocheck() functions.

     use Time::Local 'timelocal_nocheck';

     {
         # The 365th day of 1999
         print scalar localtime timelocal_nocheck 0,0,0,365,0,99;

     # The twenty thousandth day since 1970
     print scalar localtime timelocal_nocheck 0,0,0,20000,0,70;

     # And even the 10,000,000th second since 1999!
     print scalar localtime timelocal_nocheck 10000000,0,0,1,0,99;
     	}

   Your mileage may vary when trying these with minutes and hours, and it
doesn't work at all for months.

   Strictly speaking, the year should also be specified in a form
consistent with localtime(), i.e. the offset from 1900.  In order to make
the interpretation of the year easier for humans, however, who are more
accustomed to seeing years as two-digit or four-digit values, the
following conventions are followed:

   * Years greater than 999 are interpreted as being the actual year,
     rather than the offset from 1900.  Thus, 1963 would indicate the year
     Martin Luther King won the Nobel prize, not the year 2863.

   * Years in the range 100..999 are interpreted as offset from 1900, so
     that 112 indicates 2012.  This rule also applies to years less than
     zero (but see note below regarding date range).

   * Years in the range 0..99 are interpreted as shorthand for years in the
     rolling "current century," defined as 50 years on either side of the
     current year.  Thus, today, in 1999, 0 would refer to 2000, and 45 to
     2045, but 55 would refer to 1955.  Twenty years from now, 55 would
     instead refer to 2055.  This is messy, but matches the way people
     currently think about two digit dates.  Whenever possible, use an
     absolute four digit year instead.

   The scheme above allows interpretation of a wide range of dates,
particularly if 4-digit years are used.

   Please note, however, that the range of dates that can be actually be
handled depends on the size of an integer (time_t) on a given platform.
Currently, this is 32 bits for most systems, yielding an approximate range
from Dec 1901 to Jan 2038.

   Both timelocal() and timegm() croak if given dates outside the supported
range.

IMPLEMENTATION
==============

   These routines are quite efficient and yet are always guaranteed to
agree with localtime() and gmtime().  We manage this by caching the start
times of any months we've seen before.  If we know the start time of the
month, we can always calculate any time within the month.  The start times
themselves are guessed by successive approximation starting at the current
time, since most dates seen in practice are close to the current date.
Unlike algorithms that do a binary search (calling gmtime once for each
bit of the time value, resulting in 32 calls), this algorithm calls it at
most 6 times, and usually only once or twice.  If you hit the month cache,
of course, it doesn't call it at all.

   timelocal() is implemented using the same cache.  We just assume that
we're translating a GMT time, and then fudge it when we're done for the
timezone and daylight savings arguments.  Note that the timezone is
evaluated for each date because countries occasionally change their
official timezones.  Assuming that localtime() corrects for these changes,
this routine will also be correct.  The daylight savings offset is
currently assumed to be one hour.

BUGS
====

   The whole scheme for interpreting two-digit years can be considered a
bug.

   Note that the cache currently handles only years from 1900 through 2155.

   The proclivity to croak() is probably a bug.

Object Oriented time objects
****************************

NAME
====

   Time::Object - Object Oriented time objects

SYNOPSIS
========

     use Time::Object;

     my $t = localtime;
     print "Time is $t\n";
     print "Year is ", $t->year, "\n";

DESCRIPTION
===========

   This module replaces the standard localtime and gmtime functions with
implementations that return objects. It does so in a backwards compatible
manner, so that using localtime/gmtime in the way documented in perlfunc
will still return what you expect.

   The module actually implements most of an interface described by Larry
Wall on the perl5-porters mailing list here:
http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2000-01/msg00241.html

USAGE
=====

   After importing this module, when you use localtime or gmtime in a
scalar context, rather than getting an ordinary scalar string representing
the date and time, you get a Time::Object object, whose stringification
happens to produce the same effect as the localtime and gmtime functions.
There is also a new() constructor provided, which is the same as
localtime(), except when passed a Time::Object object, in which case it's
a copy constructor. The following methods are available on the object:

     $t->sec               # also available as $t->second
     $t->min               # also available as $t->minute
     $t->hour
     $t->mday              # also available as $t->day_of_month
     $t->mon               # based at 1
     $t->_mon              # based at 0
     $t->monname           # February
     $t->month             # same as $t->monname
     $t->year              # based at 0 (year 0 AD is, of course 1 BC).
     $t->_year             # year minus 1900
     $t->yr                # 2 digit year
     $t->wday              # based at 1 = Sunday
     $t->_wday             # based at 0 = Sunday
     $t->day_of_week       # based at 0 = Sunday
     $t->wdayname          # Tuesday
     $t->day               # same as wdayname
     $t->yday              # also available as $t->day_of_year
     $t->isdst             # also available as $t->daylight_savings
     $t->hms               # 01:23:45
     $t->ymd               # 2000/02/29
     $t->mdy               # 02/29/2000
     $t->dmy               # 29/02/2000
     $t->date              # Tue Feb 29 01:23:45 2000
     "$t"                  # same as $t->date
     $t->epoch             # seconds since the epoch
     $t->tzoffset          # timezone offset in a Time::Seconds object
     $t->strftime(FORMAT)  # same as POSIX::strftime (without POSIX.pm)

Date Calculations
-----------------

   It's possible to use simple addition and subtraction of objects:

     use Time::Seconds;

     	my $seconds = $t1 - $t2;
     	$t1 += ONE_DAY; # add 1 day (constant from Time::Seconds)

   The following are valid ($t1 and $t2 are Time::Object objects):

     $t1 - $t2; # returns Time::Seconds object
     $t1 - 42; # returns Time::Object object
     $t1 + 533; # returns Time::Object object

   However adding a Time::Object object to another Time::Object object
will cause a runtime error.

   Note that the first of the above returns a Time::Seconds object, so
while examining the object will print the number of seconds (because of
the overloading), you can also get the number of minutes, hours, days,
weeks and years in that delta, using the Time::Seconds API.

Date Comparisons
----------------

   Date comparisons are also possible, using the full suite of "<", ">",
"<=", ">=", "<=>", "==" and "!=".

Global Overriding
-----------------

   Finally, it's possible to override localtime and gmtime everywhere, by
including the 'overrideGlobally' tag in the import list:

     use Time::Object 'overrideGlobally';

   I'm not too keen on this name yet - suggestions welcome...

AUTHOR
======

   Matt Sergeant, matt@sergeant.org

License
-------

   This module is free software, you may distribute it under the same terms
as Perl.

Bugs
----

   The test harness leaves much to be desired. Patches welcome.

date parsing both relative and absolute
***************************************

NAME
====

   Time::ParseDate - date parsing both relative and absolute

SYNOPSIS
========

     use Time::ParseDate;
     $seconds_since_jan1_1970 = parsedate("12/11/94 2pm", NO_RELATIVE => 1)
     $seconds_since_jan1_1970 = parsedate("12/11/94 2pm", %options)

OPTIONS
=======

   Date parsing can also use options.  The options are as follows:

     FUZZY	-> it's okay not to parse the entire date string
     NOW	-> the "current" time for relative times (defaults to time())
     ZONE	-> local timezone (defaults to $ENV{TZ})
     WHOLE	-> the whole input string must be parsed
     GMT	-> input time is assumed to be GMT, not localtime
     UK	-> prefer UK style dates (dd/mm over mm/dd)
     DATE_REQUIRED -> do not default the date
     TIME_REQUIRED -> do not default the time
     NO_RELATIVE -> input time is not relative to NOW
     TIMEFIRST -> try parsing time before date [not default]
     PREFER_PAST -> when year or day of week is ambigueous, assume past
     PREFER_FUTURE -> when year or day of week is ambigueous, assume future
     SUBSECOND -> parse fraction seconds
     VALIDATE -> only accept normal values for HHMMSS, YYMMDD.  Otherwise
     	days like -1 might give the last day of the previous month.

DATE FORMATS RECOGNIZED
=======================

Absolute date formats
---------------------

     Dow, dd Mon yy
     Dow, dd Mon yyyy
     Dow, dd Mon
     dd Mon yy
     dd Mon yyyy
     Month day{st,nd,rd,th}, year
     Month day{st,nd,rd,th}
     Mon dd yyyy
     yyyy/mm/dd
     yyyy/mm
     mm/dd/yy
     mm/dd/yyyy
     mm/yy
     yy/mm      (only if year > 12, or > 31 if UK)
     yy/mm/dd   (only if year > 12 and day < 32, or year > 31 if UK)
     dd/mm/yy   (only if UK, or an invalid mm/dd/yy or yy/mm/dd)
     dd/mm/yyyy (only if UK, or an invalid mm/dd/yyyy)
     dd/mm      (only if UK, or an invalid mm/dd)

Relative date formats:
----------------------

     count "days"
     count "weeks"
     count "months"
     count "years"
     Dow "after next"
     Dow 			(requires PREFER_PAST or PREFER_FUTURE)
     "next" Dow
     "tomorrow"
     "today"
     "yesterday"
     "last" dow
     "last week"
     "now"
     "now" "+" count units
     "now" "-" count units
     "+" count units
     "-" count units

Absolute time formats:
----------------------

     hh:mm:ss[.ddd]
     hh:mm
     hh:mm[AP]M
     hh[AP]M
     hhmmss[[AP]M]
     "noon"
     "midnight"

Relative time formats:
----------------------

     count "minuts"
     count "seconds"
     count "hours"
     "+" count units
     "+" count
     "-" count units
     "-" count

Timezone formats:
-----------------

     [+-]dddd
     GMT[+-]d+
     [+-]dddd (TZN)
     TZN

Special formats:
----------------

     [ d]d/Mon/yyyy:hh:mm:ss [[+-]dddd]
     yy/mm/dd.hh:mm

DESCRIPTION
===========

   This module recognizes the above date/time formats.   Usually a date
and a time are specified.  There are numerous options for controlling what
is recognized and what is not.

   The return code is always the time in seconds since January 1st, 1970
or undef if it was unable to parse the time.

   If a timezone is specified it must be after the time.  Year
specifications can be tacked onto the end of absolute times.

   If `parsedate()' is called from array contect, then it will return two
elements.  On sucessful parses, it will return the seconds and what
remains of its input string.  On unsucessful parses, it will return undef
and an error string.

EXAMPLES
========

     $seconds = parsedate("Mon Jan  2 04:24:27 1995");
     $seconds = parsedate("Tue Apr 4 00:22:12 PDT 1995");
     $seconds = parsedate("04.04.95 00:22", ZONE => PDT);
     $seconds = parsedate("Jan 1 1999 11:23:34.578", SUBSECOND => 1);
     $seconds = parsedate("122212 950404", ZONE => PDT, TIMEFIRST => 1);
     $seconds = parsedate("+3 secs", NOW => 796978800);
     $seconds = parsedate("2 months", NOW => 796720932);
     $seconds = parsedate("last Tuesday");

     ($seconds, $remaining) = parsedate("today is the day");
     ($seconds, $error) = parsedate("today is", WHOLE=>1);

AUTHOR
======

   David Muir Sharnoff <muir@idiom.com>.  Copyright (C) 1996-1999 All
Rights Reserved.  Use and redistribution allowed at user's own risk.

A Perl module to deal with time periods.
****************************************

NAME
====

   Time::Period - A Perl module to deal with time periods.

SYNOPSIS
========

   `use Time::Period;'

   `$result = inPeriod($time, $period);'

DESCRIPTION
===========

   The *inPeriod* function determines if a given time falls within a given
period.  *inPeriod* returns 1 if the time does fall within the given
period, 0 if not, and *-1* if *inPeriod* detects a malformed time or
period.

   The time is specified as per the `time()' function, which is assumed to
be the number of non-leap seconds since January 1, 1970.

   The period is specified as a string which adheres to the format

     sub-period[, sub-period...]

   or the string "none" or whitespace.  The string "none" is not case
sensitive.

   If the period is blank, then any time period is assumed because the time
period has not been restricted.  In that case, *inPeriod* returns 1.  If
the period is "none", then no time period applies and *inPeriod* returns 0.

   A sub-period is of the form

     scale {range [range ...]} [scale {range [range ...]}]

   Scale must be one of nine different scales (or their equivalent codes):

     Scale  | Scale | Valid Range Values
            | Code  |
     *******|*******|************************************************
     year   |  yr   | n     where n is an integer 0<=n<=99 or n>=1970
     month  |  mo   | 1-12  or  jan, feb, mar, apr, may, jun, jul,
            |       |           aug, sep, oct, nov, dec
     week   |  wk   | 1-6
     yday   |  yd   | 1-365
     mday   |  md   | 1-31
     wday   |  wd   | 1-7   or  su, mo, tu, we, th, fr, sa
     hour   |  hr   | 0-23  or  12am 1am-11am 12noon 12pm 1pm-11pm
     minute |  min  | 0-59
     second |  sec  | 0-59

   The same scale type may be specified multiple times.  Additional scales
simply extend the range defined by previous scales of the same type.

   The range for a given scale must be a valid value in the form of

     v

   or

     v-v

   For the range specification v-v, if the second value is larger than the
first value, the range wraps around unless the scale specification is year.

   Year does not wrap because the year is never really reset, it just
increments.  Ignoring that fact has lead to the dreaded year 2000
nightmare.  When the year rolls over from 99 to 00, it has really rolled
over a century, not gone back a century.  *inPeriod* supports the
dangerous two digit year notation because it is so rampant.  However,
*inPeriod* converts the two digit notation to four digits by prepending
the first two digits from the current year.  In the case of 99-1972, the
99 is translated to whatever current century it is (probably 20th), and
then range 99-1972 is treated as 1972-1999.  If it were the 21st century,
then the range would be 1972-2099.

   Anyway, if v-v is 9-2 and the scale is month, September, October,
November, December, January, and February are the months that the range
specifies.  If v-v is 2-9, then the valid months are February, March,
April, May, Jun, July, August, and September.  9-2 is the same as Sep-Feb.

   v isn't a point in time.  In the context of the hour scale, 9 specifies
the time period from 9:00:00 am to 9:59:59 am.  This is what most people
would call 9-10.  In other words, v is discrete in its time scale.  9
changes to 10 when 9:59:59 changes to 10:00:00, but it is 9 from 9:00:00
to 9:59:59.  Just before 9:00:00, v was 8.

   Note that whitespace can be anywhere and case is not important.  Note
also that scales must be specified either in long form (year, month, week,
etc.) or in code form (yr, mo, wk, etc.).  Scale forms may be mixed in a
period statement.

   Furthermore, when using letters to specify ranges, only the first two
for week days or the first three for months are significant.  January is a
valid specification for jan, and Sunday is a valid specification for su.
Sun is also valid for su.

PERIOD EXAMPLES
---------------

   To specify a time period from Monday through Friday, 9am to 5pm, use a
period such as

     wd {Mon-Fri} hr {9am-4pm}

   When specifing a range by using -, it is best to think of - as meaning
through.  It is 9am through 4pm, which is just before 5pm.

   To specify a time period from Monday through Friday, 9am to 5pm on
Monday, Wednesday, and Friday, and 9am to 3pm on Tuesday and Thursday, use
a period such as

     wd {Mon Wed Fri} hr {9am-4pm}, wd{Tue Thu} hr {9am-2pm}

   To specify a time period that extends Mon-Fri 9am-5pm, but alternates
weeks in a month, use a period such as

     wk {1 3 5} wd {Mon Wed Fri} hr {9am-4pm}

   Or how about a period that specifies winter?

     mo {Nov-Feb}

   This is equivalent to the previous example:

     mo {Jan-Feb Nov-Dec}

   As is

     mo {jan feb nov dec}

   And this is too:

     mo {Jan Feb}, mo {Nov Dec}

   Wait!  So is this:

     mo {Jan Feb} mo {Nov Dec}

   To specify a period that describes every other half-hour, use something
like

     minute { 0-29 }

   To specify the morning, use

     hour { 12am-11am }

   Remember, 11am is not 11:00:00am, but rather 11:00:00am - 11:59:59am.

   Hmmmm, 5 second blocks could be a fun period...

     sec {0-4 10-14 20-24 30-34 40-44 50-54}

   To specify every first half-hour on alternating week days, and the
second half-hour the rest of the week, use the period

     wd {1 3 5 7} min {0-29}, wd {2 4 6} min {30-59}

VERSION
=======

   1.20

HISTORY
=======

     Version 1.20
     ------------
     	- Added the ability to specify no time period.

     Version 1.13
     ------------
     	- Cleaned up the error checking code.

     Version 1.12
     ------------
     	- Updated email and web space information.

     Version 1.11
     ------------
     	- Minor bug fix in 1.10.

     Version 1.10
     ------------
     	- Released.

AUTHOR
======

   Patrick Ryan <pgryan@geocities.com>

COPYRIGHT
=========

   Copyright (c) 1997 Patrick Ryan.  All rights reserved.  This Perl module
uses the conditions given by Perl.  This module may only be distributed
and or modified under the conditions given by Perl.

DATE
====

   August 26, 1997

SOURCE
======

   This distribution can be found at

     http://www.geocities.com/SiliconValley/Lakes/8456/

   or

     http://www.perl.com/CPAN/modules/by-module/Time/

a simple API to convert seconds to other date values
****************************************************

NAME
====

   Time::Seconds - a simple API to convert seconds to other date values

SYNOPSIS
========

     use Time::Object;
     use Time::Seconds;

     my $t = localtime;
     $t += ONE_DAY;

     my $t2 = localtime;
     my $s = $t - $t2;

     print "Difference is: ", $s->days, "\n";

DESCRIPTION
===========

   This module is part of the Time::Object distribution. It allows the user
to find out the number of minutes, hours, days, weeks or years in a given
number of seconds. It is returned by Time::Object when you delta two
Time::Object objects.

   Time::Seconds also exports the following constants:

     ONE_DAY
     ONE_WEEK
     ONE_HOUR
     ONE_MINUTE
     	ONE_MONTH
     	ONE_YEAR
     	ONE_FINANCIAL_MONTH
     LEAP_YEAR
     NON_LEAP_YEAR

   Since perl does not (yet?) support constant objects, these constants
are in seconds only, so you cannot, for example, do this: `print
ONE_WEEK->minutes;'

METHODS
=======

   The following methods are available:

     my $val = Time::Seconds->new(SECONDS)
     $val->seconds;
     $val->minutes;
     $val->hours;
     $val->days;
     $val->weeks;
     	$val->months;
     	$val->financial_months; # 30 days
     $val->years;

   The methods make the assumption that there are 24 hours in a day, 7
days in a week, 365.24225 days in a year and 12 months in a year.  (from
The Calendar FAQ at http://www.tondering.dk/claus/calendar.html)

AUTHOR
======

   Matt Sergeant, matt@sergeant.org

   Tobias Brox, tobiasb@tobiasb.funcom.com

LICENSE
=======

   Please see Time::Object for the license.

Bugs
====

   Currently the methods aren't as efficient as they could be, for reasons
of clarity. This is probably a bad idea.

Perl module to calculate run time
*********************************

NAME
====

   Time::SoFar - Perl module to calculate run time

SYNOPSIS
========

     use Time::SoFar qw( runtime runinterval figuretimes );

     # [...] denotes optional arguments
     $times = runtime( [$no_optimize] );
     @times = runtime( [$no_optimize] );

     $times = runinterval( [$no_optimize] );
     @times = runinterval( [$no_optimize] );

     $times = figuretimes( $seconds [, $no_optimize] );
     @times = figuretimes( $seconds [, $no_optimize] );

SAMPLES
=======

     my $elapsed = runtime();
     print "Elapsed time $elapsed\n";
     # prints, eg, "Elapsed time 17:34\n"

     my $sincethen = runinterval(1);
     print "Time since then $sincethen\n";
     # prints, eg, "Time since then 0:00:00:51\n"

     ($day, $hour, $min, $sec) = figuretimes(86400 + 2*3600 + 3*60 + 4, 1);
     # $day = 1; $hour = 2; $min = 3; $sec = 4;

     @times = figuretimes(2*3600 + 3*60 + 4);
     # @times = (2, 3, 4)

     @times = figuretimes(17,1);
     # @times = (0, 0, 0, 17)

     $times = figuretimes(2*3600 + 3*60 + 4, 1);
     # $times = '0:02:03:04';

DESCRIPTION
===========

   *Time::SoFar* has two functions for calculating how long a script has
been running. `runtime()' always works from the time the script was
started (using $^T). `runinterval()' works from the last time `runtime()'
or `runinterval()' was called (or since the start of the script).

   Both `runtime()' and `runinterval()' use `figuretimes()' to render a
raw number of seconds into component time units. Both take an optional
boolean argument that gets passed to `figuretimes()' to influence its
output.

   In an array context `figuretimes()' returns the timecomponents as an
array, in a scalar context it returns those components as a : delimited
string. The default behaviour is to optimize away 0 output from the longer
period end of the output, leaving a minimum of minutes:seconds. This is
good for arrays that will be passed to `join()', but not so good for a
list of variables, so this behaviour can be disabled by using a true value
for *$no_optimize*.

INHERITANCE
===========

   Time::SoFar inherits only from Exporter.

CAVEATS
=======

   Time::SoFar has a granularity of seconds, and is therefore not so
useful for small elapsed times.

PREREQUISITES
=============

   Only stock perl modules are used.

OSNAMES
=======

   So long as $^T and `time()' are calculated using the same epoch there
should be no operating system dependence.

SEE ALSO
========

   $^T in Perlvar (perl.info).

COPYRIGHT
=========

   Copyright 2000 by Eli the Bearded / Benjamin Elijah Griffin.  Released
under the same license(s) as Perl.

AUTHOR
======

   Eli the Bearded wrote this to do away with all the $^T one liners at
the end of his batch processing scripts.

Use tied scalars as timers
**************************

NAME
====

   Time::Stopwatch - Use tied scalars as timers

SYNOPSIS
========

     use Time::Stopwatch;
     tie my $timer, 'Time::Stopwatch';

     do_something();
     print "Did something in $timer seconds.\n";

     my @times = map {
         $timer = 0;
         do_something_else();
         $timer;
     } 1 .. 5;

DESCRIPTION
===========

   The `Time::Stopwatch' module provides a convenient interface to timing
functions through tied scalars.  From the point of view of the user,
scalars tied to the module simply increase their value by one every second.

   Using the module should mostly be obvious from the synopsis.  You can
provide an initial value for the timers either by assigning to them or by
passing the value as a third argument to tie().

   If you have the module `Time::HiRes' installed, the timers created by
`Time::Stopwatch' will automatically count fractional seconds.  Do not
assume that the values of the timers are always integers.  You may test
the constant `Time::Stopwatch::HIRES' to find out whether high resolution
timing is enabled.

CHANGE LOG
==========

  1. (27 Feb 2001) Modified tests to give more information, reduced
     subsecond accuracy test to 1/10 seconds to allow for inaccurate
     select() implementations.  Tweaked synopsis and README.

SEE ALSO
========

   `Time::HiRes', tie()

AUTHORS
=======

   Copyright 2000-2001, Ilmari Karonen.  All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Address bug reports and comments to: perl@itz.pp.sci.fi

Store times in a portable format
********************************

NAME
====

   Time::Storable - Store times in a portable format

SYNOPSIS
========

     use Time::Storable;

DESCRIPTION
===========

   The idea is to provide some format for storing dates - particularly
dates that fall outside of the epoch - that is, either before 1970, or
after 2038. This is a combination of Time::JulianDay type dates, and
regular epoch time type time stamps.

   The time is stored in a single format, rather than in two numbers, for
simplicity of putting this in a database. This module provides a full set
of tools for getting useful information out of this time storage format,
so that it is not a burden to put it in this format.

   The time format used here is just experimental. I'm not sure if this is
the best way do to things or not. It's susceptible to rounding error if
you treat it like a number. But the whole point of making it look like a
number was specifically so that you can put it in numerical database
fields, rather than having to put it in a string field.

   Please let me know what you think about this, and I'll incorporate
ideas into the next version.

   Eventually there will be convenient ways to get seconds, minutes,
hours, days, months, years out of a Time::Storable string. Perhaps even
this evening.

AUTHOR
======

   Rich Bowen <rbowen@rcbowen.com>

SEE ALSO
========

   perl(1).

miscellaneous timezone manipulations routines
*********************************************

NAME
====

   Time::Timezone - miscellaneous timezone manipulations routines

SYNOPSIS
========

     use Time::Timezone;
     print tz2zone();
     print tz2zone($ENV{'TZ'});
     print tz2zone($ENV{'TZ'}, time());
     print tz2zone($ENV{'TZ'}, undef, $isdst);
     $offset = tz_local_offset();
     $offset = tz_offset($TZ);

DESCRIPTION
===========

   This is a collection of miscellaneous timezone manipulation routines.

   `tz2zone()' parses the TZ environment variable and returns a timezone
string suitable for inclusion in `date' in this node-like output.  It
opionally takes a timezone string, a time, and a is-dst flag.

   `tz_local_offset()' determins the offset from GMT time in seconds.  It
only does the calculation once.

   `tz_offset()' determines the offset from GMT in seconds of a specified
timezone.

   `tz_name()' determines the name of the timezone based on its offset

AUTHORS
=======

   Graham Barr <bodg@tiuk.ti.com> David Muir Sharnoff <muir@idiom.com>
Paul Foley <paul@ascent.com>

Force time() to return seconds since UNIX epoch
***********************************************

NAME
====

   Time::Unix - Force time() to return seconds since UNIX epoch

SYNOPSIS
========

     use Time::Unix;     # time() now returns UNIX epoch seconds

DESCRIPTION
===========

   This module does one thing: It imports a new version of time() that
returns seconds since the UNIX epoch on ALL platforms.  It is intended
mainly as a proof-of-concept for the below Perl 6 RFC.

   In addition to importing a time() function, it also imports a systime()
function which gives you direct access to the system's native epoch (i.e.,
what time() would return if you hadn't used this module).

   This doesn't do anything useful on UNIX platforms, so don't do that.

REFERENCES
==========

   See http://dev.perl.org/rfc/99.html for a complete description.

AUTHOR
======

   Copyright (c) 2000, Nathan Wiger <nate@sun.com>. All Rights Reserved.

   This module is free software; you may copy this under the terms of the
GNU General Public License, or the Artistic License, copies of which
should have accompanied your Perl kit.

control over the flow of time
*****************************

NAME
====

   Time::Warp - control over the flow of time

SYNOPSIS
========

     use Time::Warp qw(scale to time);

     to(time + 5);  # 5 seconds ahead
     scale(2);      # make time flow twice normal

DESCRIPTION
===========

   Our external experience unfolds in 3 1/2 dimensions (time has a
dimensionality of 1/2).  The Time::Warp module offers developers control
over the measurement of time.

API
===

   * to($desired_time)

     The theory of relativity asserts that all physical laws are enforced
     relative to the observer.  Since the starting point of time is
     arbitrary, it is permissable to change it.  This has the effect of
     making it appear as if time is moving forwards or backward
     instanteously.  For example, on some types of operating systems time
     starts at Wed Dec 31 19:00:00 1969 (this will likely change as we
     approach 2030 and with the acceptance of 64-bit CPUs).

          to(time + 60*60);       # 1 hour ahead

   * scale($factor)

     Changes the speed at which time is progressing.

          scale(scale * 2);   # double the speed of time

     Note that it is not possible to stop time or cause it to reverse since
     this is forbidden by the second law of thermodynamics.

ALSO SEE
========

   See Time/HiRes, and Event.

SUPPORT
=======

   Please direct your insights or complaints to perl-loop@perl.org.

DISCLAIMER
==========

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THIS IS NOT A TIME
MACHINE.  THIS MODULE CANNOT BE USED TO VIOLATE THE SECOND LAW OF
THERMODYNAMICS.

COPYRIGHT
=========

   Copyright © 1999, 2000 Joshua Nathaniel Pritikin.  All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

miscellaneous timezone manipulations routines
*********************************************

NAME
====

   Time::Zone - miscellaneous timezone manipulations routines

SYNOPSIS
========

     use Time::Zone;
     print tz2zone();
     print tz2zone($ENV{'TZ'});
     print tz2zone($ENV{'TZ'}, time());
     print tz2zone($ENV{'TZ'}, undef, $isdst);
     $offset = tz_local_offset();
     $offset = tz_offset($TZ);

DESCRIPTION
===========

   This is a collection of miscellaneous timezone manipulation routines.

   `tz2zone()' parses the TZ environment variable and returns a timezone
string suitable for inclusion in `date' in this node-like output.  It
opionally takes a timezone string, a time, and a is-dst flag.

   `tz_local_offset()' determins the offset from GMT time in seconds.  It
only does the calculation once.

   `tz_offset()' determines the offset from GMT in seconds of a specified
timezone.

   `tz_name()' determines the name of the timezone based on its offset

AUTHORS
=======

   Graham Barr <gbarr@pobox.com> David Muir Sharnoff <muir@idiom.com> Paul
Foley <paul@ascent.com>

by-name interface to Perl's built-in gmtime() function
******************************************************

NAME
====

   Time::gmtime - by-name interface to Perl's built-in gmtime() function

SYNOPSIS
========

     use Time::gmtime;
     $gm = gmtime();
     printf "The day in Greenwich is %s\n",
        (qw(Sun Mon Tue Wed Thu Fri Sat Sun))[ gm->wday() ];

     use Time::gmtime w(:FIELDS;
     printf "The day in Greenwich is %s\n",
        (qw(Sun Mon Tue Wed Thu Fri Sat Sun))[ gm_wday() ];

     $now = gmctime();

     use Time::gmtime;
     use File::stat;
     $date_string = gmctime(stat($file)->mtime);

DESCRIPTION
===========

   This module's default exports override the core gmtime() function,
replacing it with a version that returns "Time::tm" objects.  This object
has methods that return the similarly named structure field name from the
C's tm structure from `time.h'; namely sec, min, hour, mday, mon, year,
wday, yday, and isdst.

   You may also import all the structure fields directly into your
namespace as regular variables using the :FIELDS import tag.  (Note that
this still overrides your core functions.)  Access these fields as
variables named with a preceding `tm_' in front their method names.  Thus,
`$tm_obj->mday()' corresponds to $tm_mday if you import the fields.

   The gmctime() function provides a way of getting at the scalar sense of
the original CORE::gmtime() function.

   To access this functionality without the core overrides, pass the use
an empty import list, and then access function functions with their full
qualified names.  On the other hand, the built-ins are still available via
the `CORE::' pseudo-package.

NOTE
====

   While this class is currently implemented using the Class::Struct
module to build a struct-like class, you shouldn't rely upon this.

AUTHOR
======

   Tom Christiansen

by-name interface to Perl's built-in localtime() function
*********************************************************

NAME
====

   Time::localtime - by-name interface to Perl's built-in localtime()
function

SYNOPSIS
========

     use Time::localtime;
     printf "Year is %d\n", localtime->year() + 1900;

     $now = ctime();

     use Time::localtime;
     use File::stat;
     $date_string = ctime(stat($file)->mtime);

DESCRIPTION
===========

   This module's default exports override the core localtime() function,
replacing it with a version that returns "Time::tm" objects.  This object
has methods that return the similarly named structure field name from the
C's tm structure from `time.h'; namely sec, min, hour, mday, mon, year,
wday, yday, and isdst.

   You may also import all the structure fields directly into your
namespace as regular variables using the :FIELDS import tag.  (Note that
this still overrides your core functions.)  Access these fields as
variables named with a preceding `tm_' in front their method names.  Thus,
`$tm_obj->mday()' corresponds to $tm_mday if you import the fields.

   The ctime() function provides a way of getting at the scalar sense of
the original CORE::localtime() function.

   To access this functionality without the core overrides, pass the use
an empty import list, and then access function functions with their full
qualified names.  On the other hand, the built-ins are still available via
the `CORE::' pseudo-package.

NOTE
====

   While this class is currently implemented using the Class::Struct
module to build a struct-like class, you shouldn't rely upon this.

AUTHOR
======

   Tom Christiansen

internal object used by Time::gmtime and Time::localtime
********************************************************

NAME
====

   Time::tm - internal object used by Time::gmtime and Time::localtime

SYNOPSIS
========

   Don't use this module directly.

DESCRIPTION
===========

   This module is used internally as a base class by Time::localtime And
Time::gmtime functions.  It creates a Time::tm struct object which is
addressable just like's C's tm structure from `time.h'; namely with sec,
min, hour, mday, mon, year, wday, yday, and isdst.

   This class is an internal interface only.

AUTHOR
======

   Tom Christiansen

a graphical user interface toolkit for Perl
*******************************************

NAME
====

   Tk - a graphical user interface toolkit for Perl

SYNOPSIS
========

     use Tk;
     $top = new MainWindow;
     MainLoop;

DESCRIPTION
===========

   The Perl/Tk manual is split up into a number of sections:

Introduction
------------

   * `Tk::overview|Tk::overview' in this node

   * `Tk::UserGuide|Tk::UserGuide' in this node

Tk Geometry Management
----------------------

   * `Tk::Adjuster|Tk::Adjuster' in this node

   * `Tk::form|Tk::form' in this node

   * `Tk::grid|Tk::grid' in this node

   * `Tk::pack|Tk::pack' in this node

   * `Tk::place|Tk::place' in this node

   * `Tk::Table|Tk::Table' in this node

   * `Tk::Tiler|Tk::Tiler' in this node

   * `Tk::Wm|Tk::Wm' in this node

Binding Events and Callbacks
----------------------------

   * `Tk::After|Tk::After' in this node

   * `Tk::bind|Tk::bind' in this node

   * `Tk::bindtags|Tk::bindtags' in this node

   * `Tk::callbacks|Tk::callbacks' in this node

   * `Tk::Error|Tk::Error' in this node

   * `Tk::event|Tk::event' in this node

   * `Tk::exit|Tk::exit' in this node

   * `Tk::fileevent|Tk::fileevent' in this node

   * `Tk::IO|Tk::IO' in this node

Tk Image Classes
----------------

   * `Tk::Animation|Tk::Animation' in this node

   * `Tk::Bitmap|Tk::Bitmap' in this node

   * `Tk::Compound|Tk::Compound' in this node

   * `Tk::Image|Tk::Image' in this node

   * `Tk::Photo|Tk::Photo' in this node

   * `Tk::Pixmap|Tk::Pixmap' in this node

Tix Extensions
--------------

   * `Tk::Balloon|Tk::Balloon' in this node

   * `Tk::BrowseEntry|Tk::BrowseEntry' in this node

   * `Tk::DialogBox|Tk::DialogBox' in this node

   * `Tk::DirTree|Tk::DirTree' in this node

   * `Tk::DItem|Tk::DItem' in this node

   * `Tk::InputO|Tk::InputO' in this node

   * `Tk::LabFrame|Tk::LabFrame' in this node

   * `Tk::Mwm|Tk::Mwm' in this node

   * `Tk::NoteBook|Tk::NoteBook' in this node

   * `Tk::TixGrid|Tk::TixGrid' in this node

   * `Tk::tixWm|Tk::tixWm' in this node

   * `Tk::TList|Tk::TList' in this node

   * `Tk::Tree|Tk::Tree' in this node

Tk Widget Classes
-----------------

   * `Tk::Button|Tk::Button' in this node

   * `Tk::Canvas|Tk::Canvas' in this node

   * `Tk::Checkbutton|Tk::Checkbutton' in this node

   * `Tk::Entry|Tk::Entry' in this node

   * `Tk::Frame|Tk::Frame' in this node

   * `Tk::HList|Tk::HList' in this node

   * `Tk::Label|Tk::Label' in this node

   * `Tk::Listbox|Tk::Listbox' in this node

   * `Tk::Menu|Tk::Menu' in this node

   * `Tk::Menubutton|Tk::Menubutton' in this node

   * `Tk::Message|Tk::Message' in this node

   * `Tk::Optionmenu|Tk::Optionmenu' in this node

   * `Tk::Radiobutton|Tk::Radiobutton' in this node

   * `Tk::Scale|Tk::Scale' in this node

   * `Tk::Scrollbar|Tk::Scrollbar' in this node

   * `Tk::Text|Tk::Text' in this node

   * `Tk::Toplevel|Tk::Toplevel' in this node

Tk Generic Methods
------------------

   * `Tk::Font|Tk::Font' in this node

   * `Tk::send|Tk::send' in this node

   * `Tk::tkvars|Tk::tkvars' in this node

   * `Tk::Widget|Tk::Widget' in this node

   * `Tk::X11Font|Tk::X11Font' in this node

User Interaction
----------------

   * `Tk::DropSite|Tk::DropSite' in this node

   * `Tk::Clipboard|Tk::Clipboard' in this node

   * `Tk::focus|Tk::focus' in this node

   * `Tk::grab|Tk::grab' in this node

   * `Tk::selection|Tk::selection' in this node

Creating and Configuring Widgets
--------------------------------

   * `Tk::CmdLine|Tk::CmdLine' in this node

   * `Tk::MainWindow|Tk::MainWindow' in this node

   * `Tk::option|Tk::option' in this node

   * `Tk::options|Tk::options' in this node

   * `Tk::palette|Tk::palette' in this node

   * `Tk::Xrm|Tk::Xrm' in this node

Popups and Dialogs
------------------

   * `Tk::chooseColor|Tk::chooseColor' in this node

   * `Tk::ColorEditor|Tk::ColorEditor' in this node

   * `Tk::Dialog|Tk::Dialog' in this node

   * `Tk::Dialog|Tk::Dialog' in this node

   * `Tk::FileSelect|Tk::FileSelect' in this node

   * `Tk::getOpenFile|Tk::getOpenFile' in this node

   * `Tk::messageBox|Tk::messageBox' in this node

Derived Widgets
---------------

   * `Tk::composite|Tk::composite' in this node

   * `Tk::configspec|Tk::configspec' in this node

   * `Tk::Derived|Tk::Derived' in this node

   * `Tk::mega|Tk::mega' in this node

   * `Tk::ROText|Tk::ROText' in this node

   * `Tk::Scrolled|Tk::Scrolled' in this node

   * `Tk::TextUndo|Tk::TextUndo' in this node

   * `Tk::Reindex|Tk::Reindex' in this node

   * `Tk::Pane|Tk::Pane' in this node

   * `Tk::ProgressBar|Tk::ProgressBar' in this node

C Programming
-------------

   * Internals

   * pTk

   * 3DBorder

   * BackgdErr

   * BindTable

   * CanvPsY

   * CanvTkwin

   * CanvTxtInfo

   * Clipboard

   * ClrSelect

   * ConfigWidg

   * ConfigWind

   * CoordToWin

   * CrtErrHdlr

   * CrtGenHdlr

   * CrtImgType

   * CrtItemType

   * CrtMainWin

   * CrtPhImgFmt

   * CrtSelHdlr

   * CrtWindow

   * DeleteImg

   * DoOneEvent

   * DoWhenIdle

   * DrawFocHlt

   * EventHndlr

   * EventInit

   * FileHndlr

   * FindPhoto

   * FontId

   * FreeXId

   * GeomReq

   * GetAnchor

   * GetBitmap

   * GetCapStyl

   * GetClrmap

   * GetColor

   * GetCursor

   * GetFont

   * GetFontStr

   * GetGC

   * GetImage

   * GetJoinStl

   * GetJustify

   * GetOption

   * GetPixels

   * GetPixmap

   * GetRelief

   * GetRootCrd

   * GetScroll

   * GetSelect

   * GetUid

   * GetVisual

   * GetVRoot

   * HandleEvent

   * IdToWindow

   * ImgChanged

   * InternAtom

   * MainLoop

   * MaintGeom

   * MainWin

   * ManageGeom

   * MapWindow

   * MeasureChar

   * MoveToplev

   * Name

   * NameOfImg

   * OwnSelect

   * ParseArgv

   * Preserve

   * QWinEvent

   * Restack

   * RestrictEv

   * SetAppName

   * SetClass

   * SetGrid

   * SetVisual

   * Sleep

   * StrictMotif

   * TextLayout

   * TimerHndlr

   * Tk_Init

   * WindowId

Implementation
--------------

   * `Tk::Eventloop|Tk::Eventloop' in this node

   * `Tk::Item|Tk::Item' in this node

   * `Tk::Submethods|Tk::Submethods' in this node

   * `Tk::WidgetDemo|Tk::WidgetDemo' in this node

   * `Tk::widgets|Tk::widgets' in this node

Experimental Modules
--------------------

   * `Tk::Common|Tk::Common' in this node

   * `Tk::SunConst|Tk::SunConst' in this node

   * `Tk::WinPhoto|Tk::WinPhoto' in this node

Other Modules and Languages
---------------------------

   * `Tk::Compile|Tk::Compile' in this node

   * `Tk::Tcl-perl|Tk::Tcl-perl' in this node

   * `Tk::X|Tk::X' in this node

AUTHOR
======

   Nick Ing-Simmons

SEE ALSO
========

   `perl(1)|perl' in this node, `wish(1)|wish' in this node.

Allow size of packed widgets to be adjusted by user
***************************************************

NAME
====

   Tk::Adjuster - Allow size of packed widgets to be adjusted by user

SYNOPSIS
========

   use Tk::Adjuster;

   *$adjuster* = $widget->*Adjuster**(?options?)*;

WIDGET-SPECIFIC OPTIONS
=======================

Name: restore
Class: Restore
Switch: *-restore*
     Specifies a boolean value that determines whether the Adjuster should
     forcibly attempt to make room for itself (by reducing the size of its
     managed widget) when it is unmapped (for example, due to a size
     change in a top level window).  The default value is 1.

Name: *side*
Class: Side
Switch: *-side*
     Specifies the side on which the managed widget lies relative to the
     Adjuster. In conjunction with the pack geometry manager, this relates
     to the side of the master against which the managed widget and the
     Adjuster are packed.  Must be left, right, top, or *bottom*. Defaults
     to top.

Name: widget
Class: *Widget*
Switch: *-widget*
     Specifies the widget which is to be managed by the Adjuster.

DESCRIPTION
===========

   *Tk::Adjuster* is a Frame containing a "line" and a "blob".

   Dragging with Mouse Button-1 results in a line being dragged to
indicate new size. Releasing Button-1 submits GeometryRequests on behalf
of the managed widget which will cause the packer to change the widget's
size.

   If Drag is done with Shift button down, then GeometryRequests are made
in "real time" so that text-flow effects can be seen, but as a lot more
work is done behaviour may be sluggish.

   If widget is packed with -side => left or -side => right then width is
adjusted. If packed -side => top or -side => bottom then height is
adjusted.

   *packPropagate* is turned off for the master window to prevent
adjustment changing overall window size. Similarly *packPropagate* is
turned off for the managed widget if it has things packed inside it. This
is so that the GeometryRequests made by *Tk::Adjuster* are not overridden
by pack.

   In addition, the managed widget is made non-expandable to prevent the
geometry manager reallocating freed space in the master back to the
managed widget.  Note however that expansion is turned off only after the
Adjuster is mapped, which allows the managed widget to expand naturally on
window creation.

   The Tk::Widget method, *packAdjust*, calls pack on the widget, then
creates an instance of *Tk::Adjuster*, and packs that "after" the widget.
Its use has two disadvantages however: the Adjuster widget is not made
available to the caller, and options cannot be set on the Adjuster. For
these reasons, the Tk::Adjuster method, *packAfter* is preferred, but
*packAdjust* is retained for backwards compatibility.

WIDGET METHODS
==============

*$adjuster*->*packAfter*(*managed_widget, ?pack_options?*)
     This command configures the Adjuster's *-widget* and *-side* options
     respectively to *managed_widget* and the *-side* value specified in
     *pack_options* (top if not specified). It then packs the Adjuster
     after *managed_widget*, with *-fill* set to x or y as appropriate.

*$adjuster*->*packForget**?(boolean)?*
     This command calls *Tk::Widget::packForget* on the Adjuster.  If a
     parameter is provided and it has a true boolean value, then
     *packForget* is also called on the managed widget.

*$adjuster*->slave
     This command returns the value *$adjuster*->*cget('-widget')*, ie. the
     reference to the managed widget.

EXAMPLES
========

   *Using an Adjuster to separate two widgets, whereby the left widget is
managed, and right widget expands to fill space on a window resize*

   a) Using packAfter (preferred interface)

     use Tk;
     use Tk::Adjuster;

     my $f = MainWindow->new;
     my $lst1 = $f->Listbox();
     my $adj1 = $f->Adjuster();
     my $lst2 = $f->Listbox();

     my $side = 'left';
     $lst1->pack(-side => $side, -fill => 'both', -expand => 1);
     $adj1->packAfter($lst1, -side => $side);
     $lst2->pack(-side => $side, -fill => 'both', -expand => 1);
     MainLoop;

   b) Using packAdjust

     use Tk;
     use Tk::Adjuster;

     my $f = MainWindow->new;
     my $lst1 = $f->Listbox();
     my $lst2 = $f->Listbox();

     my $side = 'left';
     $lst1->packAdjust(-side => $side, -fill => 'both');
     $lst2->pack      (-side => $side, -fill => 'both', -expand => 1);
     MainLoop;

   c) Using the standard Tk::Widget::pack

     use Tk;
     use Tk::Adjuster;

     my $f = MainWindow->new;
     my $side = 'left';
     my $lst1 = $f->Listbox();
     my $adj  = $f->Adjuster(-widget => $lst1, -side => $side);
     my $lst2 = $f->Listbox();

     $lst1->pack(-side => $side, -fill => 'both', -expand => 1);
     $adj->pack (-side => $side, -fill => 'y');
     $lst2->pack(-side => $side, -fill => 'both', -expand => 1);

     MainLoop;

   Changing the above examples so that $side has the value 'right' means
the left widget expands to fill space on a window resize.

   Changing the above examples so that $side has the value 'top' produces
a testcase with a horizontal Adjuster.  Here the bottom widget expands to
fill space on a window resize.  Packing to the 'bottom' makes the top
widget expand to fill space on window resize.

   *Using -restore => 0 for multiple columns*

   In the case of multiple columns (or rows) the "restore" functionality
of the Adjuster can be inconvenient. When the user adjusts the width of
one column and thereby pushes the Adjuster of another column off the
window, this adjuster tries to restore itself by reducing the size of its
managed widget.  This has the effect that column widths shrink; and the
original size is not restored when the user reverses the originating
change. The *-restore* option can be used to turn off this functionality.
(It makes some sense, however, to leave *-restore* turned on for the
first-packed Adjuster, so that at least one Adjuster always remains
visible.)

     use Tk;
     use Tk::Adjuster;
     my $f = MainWindow->new;
     my $lst1 = $f->Listbox();
     my $adj1 = $f->Adjuster();
     my $lst2 = $f->Listbox();
     my $adj2 = $f->Adjuster(-restore => 0);
     my $lst3 = $f->Listbox();

     my $side = 'left';
     $lst1->pack(-side => $side, -fill => 'both', -expand => 1);
     $adj1->packAfter($lst1, -side => $side);
     $lst2->pack(-side => $side, -fill => 'both', -expand => 1);
     $adj2->packAfter($lst2, -side => $side);
     $lst3->pack(-side => $side, -fill => 'both', -expand => 1);

     MainLoop;

BUGS
====

   It is currently not possible to configure the appearance of the
Adjuster.  It would be nice to be able to set the width and relief of the
Adjuster "line" and the presence/absence of the "blob" on the Adjuster.

   Tk::Adjuster works theoretically with the grid geometry manager but
there are currently some problems which seem to be due to bugs in grid:

     a) There's never an Unmap event for the adjuster, so the "restore"
        functionality has no effect.
     b) After adjusting, widgets protrude into the border of the master.
     c) grid('Propagate', 0) on MainWindow has no effect - window shrinks/grows
        when widgets are adjusted.
     d) Widgets shuffle to correct position on startup

Execute a command after a time delay
************************************

NAME
====

   Tk::after - Execute a command after a time delay

     $widget->after(*ms*)

     $id = $widget->after(*ms*?,callback?)

     $id = $widget->repeat(*ms*?,callback?)

     $widget->*afterCancel*($id)

     $id = $widget->*afterIdle*(callback)

     $widget->*afterInfo*?($id)?

DESCRIPTION
===========

   This method is used to delay execution of the program or to execute a
callback in background sometime in the future.

   In perl/Tk $widget->after is implemented via the class `Tk::After', and
callbacks are associated with $widget, and are automatically cancelled
when the widget is destroyed. An almost identical interface, but without
automatic cancel, and without repeat is provided via Tk::after method.

   The internal Tk::After class has the following synopsis:

     $id = Tk::After->new($widget,$time,'once',callback);
     $id = Tk::After->new($widget,$time,'repeat',callback);
     $id->cancel;

   The after method has several forms as follows:

$widget->after(*ms*)
     The value *ms* must be an integer giving a time in milliseconds.  The
     command sleeps for *ms* milliseconds and then returns.  While the
     command is sleeping the application does not respond to events.

$widget->after(*ms*,callback)
     In this form the command returns immediately, but it arranges for
     callback be executed *ms* milliseconds later as an event handler.
     The callback will be executed exactly once, at the given time.  The
     command will be executed in context of $widget.  If an error occurs
     while executing the delayed command then the `Tk::Error|Tk::Error' in
     this node mechanism is used to report the error.  The after command
     returns an identifier (an object in the perl/Tk case) that can be
     used to cancel the delayed command using *afterCancel*.

$widget->repeat(*ms*,callback)
     In this form the command returns immediately, but it arranges for
     callback be executed *ms* milliseconds later as an event handler.
     After callback has executed it is re-scheduled, to be executed in a
     futher *ms*, and so on until it is cancelled.

$widget->*afterCancel*($id)
$id->cancel
     Cancels the execution of a delayed command that was previously
     scheduled.  $id indicates which command should be canceled;  it must
     have been the return value from a previous after command.  If the
     command given by $id has already been executed (and is not scheduled
     to be executed again) then *afterCancel* has no effect.

$widget->*afterCancel*(callback)
     *This form is not robust in perl/Tk - its use is deprecated.* This
     command should also cancel the execution of a delayed command.  The
     callback argument is compared with pending callbacks, if a match is
     found, that callback is cancelled and will never be executed;  if no
     such callback is currently pending then the *afterCancel* has no
     effect.

$widget->*afterIdle*(callback)
     Arranges for callback to be evaluated later as an idle callback.  The
     script will be run exactly once, the next time the event loop is
     entered and there are no events to process.  The command returns an
     identifier that can be used to cancel the delayed command using
     *afterCancel*.  If an error occurs while executing the script then the
     `Tk::Error|Tk::Error' in this node mechanism is used to report the
     error.

$widget->*afterInfo*?($id)?
     This command returns information about existing event handlers.  If
     no $id argument is supplied, the command returns a list of the
     identifiers for all existing  event handlers created by the after
     command for this MainWindow. If $id is supplied, it specifies an
     existing handler; $id must have been the return value from some
     previous call to after and it must not have triggered yet or been
     cancelled. In this case the command returns a list with two elements.
     The first element of the list is the callback associated  with $id,
     and the second element is either idle or timer to indicate what kind
     of event handler it is.

   The after(*ms*) and *afterIdle* forms of the command assume that the
application is event driven:  the delayed commands will not be executed
unless the application enters the event loop.  In applications that are
not normally event-driven, the event loop can be entered with the *vwait*
and update commands.

SEE ALSO
========

   `Tk::Error|Tk::Error' in this node `Tk::callbacks|Tk::callbacks' in
this node

KEYWORDS
========

   cancel, delay, idle callback, sleep, time

Display sequence of Tk::Photo images
************************************

NAME
====

   Tk::Animation - Display sequence of Tk::Photo images

SYNOPSIS
========

     use Tk::Animation
     my $img = $widget->Animation('-format' => 'gif', -file => 'somefile.gif');

     $img->start_animation($period);
     $img->stop_animation;

     $img->add_frames(@images);

DESCRIPTION
===========

   In the simple case when `Animation' is passed a GIF89 style GIF with
multiple 'frames', it will build an internal array of Photo images.

   `start_animation($period)' then initiates a repeat with specified
*$period* to sequence through these images.

   `stop_animation' cancels the repeat and resets the image to the first
image in the sequence.

   The `add_frames' method adds images to the sequence. It is provided to
allow animations to be constructed from separate images.  All images must
be Photos and should all be the same size.

BUGS
====

   The 'period' should probably be a property of the Animation object
rather than specified at 'start' time. It may even be embedded in the GIF.

Canvas with Axes
****************

NAME
====

   Axis - Canvas with Axes

SYNOPSIS
========

     $mw = MainWindow->new;
     $t = $mw->Axis(-xmax => 10, -ymax => 10);
     $t->create('line',$t->plx(2),$t->ply(3.1),$t->plx(4),$t->ply(4));

DESCRIPTION
===========

   This is an improved version of the axis widget. Changes with respect to
the previous version are :

   * the 'pack' has been moved out the widget. One has to do his own
     packing

   * it is now possible to work in the coordinates of the axis. The
     following piece of code draws a line between the points (2 , 3.1)  (4
     , 4).

AUTHOR
======

     Kris Boulez		(Kris.Boulez@rug.ac.be)
     Biomolecular NMR unit	<http://bionmr1.rug.ac.be/~kris>
     University of Ghent, Belgium

geometry manager
****************

NAME
====

   BLT Table - geometry manager

SYNOPSIS
========

     use Tk::BLT::Table;

     $table = $frame->Table(-relief => 'ridge');
     $table->configure(-border => 5);
     $entry = $table->Entry;
     $table->put(0, 0, $entry);
     $table->Create(0, 1, 'Button', -text => "Button 1", -command => \&foo);

DESCRIPTION
===========

     The blt_table command is a geometry manager for Tk.  It arranges
     windows tabularly.  The table consists of individual rows and columns
     whose spacing define its layout. Windows, called slaves, are
     positioned in the table by specifying the row and column.  Only one
     slave can be specified at a single position in the table.  But slaves
     may span multiple rows and columns.

     By default, blt_table tries to arrange all its slaves in the minimum
     space required. It determines this by querying each slave window for
     its requested size.  The maximum requested height all slaves spanning
     a particular row is the row's normal size.  Similarly, the maximum
     requested width of all slaves spanning a particular column is the
     column's normal size.  This, in turn, specifies the table's size,
     which is the sum of the normal sizes of the rows and columns.  The
     number of rows and columns a table contains is determined by the
     indices specified.

Creating a table
================

     Tables are created by invoking the blt_table command.

     $table = $frame->Table(%options);

   `$frame' is the pathname of a window which must already exist.
Blt_table will arrange its slave windows inside of `$table'.  Slave
windows are added by designating the slave window's pathname and table
position.

     The following arguments are available for the blt_table (all frame
     arguments are also available) :

-height
     Specifies a desired window height that the table widget should request
     from its geometry manager.

-width
     Specifies a desired window width that the table widget should request
     from its geometry manager.

-row
     the rows of the table specified in argument will have the same heigth
     than the rows of the table.

-col
     the columns of the table specified in argument will have the same
     width than the columns of the table.

-xscrollincrement
-yscrollincrement
-xscrollcommand
-yscrollcommand
Creating a cell
===============

     The 2 possibilities are :

     ($cell) = $table->Create($row, $column, 'name_of_Widget', %options);

     or :

     $widget = $table->What_you_want;

     $table->put($row, $column, $widget);

Cell configuration
------------------

     $table->Cell('configure', [$row, $column], %options);
     $table->Cell('configure', $widget, %options);

     Possible options are :

-anchor
     Specifies how the slave window will be arranged if there is extra
     space in the span surrounding the window.  may have any of the forms
     accepted by Tk_GetAnchor.  For example, if is center then the window
     is centered in the rows and columns it spans; if is w then the window
     will be drawn such it touches the leftmost edge of the span. This
     option defaults to center.

-columnspan
     Specifies the number of columns spanned by the slave. The default span
     is 1.

-fill
     Indicates if the slave should be expanded to occupy any extra space in
     the span.  must be one of the following: none, x, y, both.  If is x,
     the width slave window is expanded.  If is y, the height is expanded.
     The default is none.

-ipadx
     Specifies an extra padding in addition to the width requested by the
     slave window.  can be any value accepted by Tk_GetPixels.  The default
     is 0.

-ipady
     Specifies an extra padding in addition to the height requested by the
     slave window.  can be any value accepted by Tk_GetPixels.  The default
     is 0.

-padx
     Specifies an extra padding to the width of the span occupying the
     slave window.  can be any value accepted by Tk_GetPixels.  The default
     is 0.

-pady
     Specifies an extra padding to the height of the span occupying the
     slave window.  can be any value accepted by Tk_GetPixels.  The default
     is 0.

-reqheight
     Specifies limits for the requested height of the slave window.  These
     limits also constrain the amount of internal padding given to the
     slave.  is a list of bounding values.  See the section BOUNDING LIST
     FORMAT for a description of this list.  By default there are no
     constraints.

-reqwidth
     Specifies the limits of the width which a slave may request.  These
     limits also affect the amount of internal padding given to the slave.
     is a list of bounding values.  See the section BOUNDING LIST FORMAT
     for a description of this list.  By default there are no constraints.

-rowspan
     Specifies the number of rows spanned by the slave window. The default
     span is 1.

Columns and rows configuration
==============================

     $table->Row('configure', $row, %options);
     $table->Columns('configure', $columns, %options);

   Valid options are :

-padx
     Specifies an extra padding to the normal width of the column.  can be
     any value accepted by Tk_GetPixels.  The default padding is 0.

-resize
     Indicates that the column can expand or shrink from its normal width
     when the table is resized.  must be one of the following: none,
     expand, shrink, or both.  If is expand the width of the column is
     expanded if there is extra space in the master window.  If is shrink
     its width may be reduced beyond its normal width if there is not
     enough space in the master.  The default is none.

-width
     Specifies the limits within which the width of the column may expand
     or shrink.  is a list of bounding values.  See the section BOUNDING
     LIST FORMAT for a description of this list.  By default there are no
     constraints.

Other commands
==============

Row and Column
--------------

size :
          $table->Row('sizes', $row);
          $table->Column('sizes', $column);

          Returns the sizes of the given column (row) in the table.

forget :
          $table->Cell('forget', [$row, $column]);
          $table->Cell('forget', $widget);
          $table->Row('forget', $row);
          $table->Column('forget', $column);

     Requests that cell (row, column) no longer have its geometry managed.
     The window will be unmapped so that it no longer appears on the
     screen.  If slave is not currently managed by any table, an error
     message is returned, otherwise the empty string.

configure
          $table->Cell('configure');
          $table->Row('configure');
          $table->Column('configure');

Table
-----

$table->get($row, $column);
     return the slave in the cell ($row, $column).

$table->under($x, $y);
     return the slave located at $x, $y

$table->dimension;
     return the number of rows and columns of the table.

$table->tablex($x);
     Given a screen x-coordinate $x this command returns the table
     x-coordinate that is displayed at that location.

$table->tabley($y);
     Given a screen y-coordinate `$y' this command returns the table
     y-coordinate that is displayed at that location.

$table->layout
          Forces layout of the table geometry manager.  This is useful to get the
          geometry manager to calculate the normal width and height of each row and
          column.

Bounding list format
====================

   Constraints for various options (-reqheight, -reqwidth, -height, and
-width) are specified by supplying a bounding list of values.  Each value
must be in a form accepted by Tk_GetPixels.  The interpretation of this
list is based upon the number of values it contains:

[]
     empty list. No bounding is performed.

[ $x ]
     Set the size of the window or partition at $x.  The size  of  the
     partition  or window cannot grow or shrink.

[ $min,  $max ]
     Bound the size of the window or partition  between `$min' and `$max'.

[ $min, $max, $nom ]
     Bound the size of the window or partition  between `$min'  and
     `$max'.  In addition, set the normal size to `$nom'.

     The maximum bound max can also be specified as `"Inf"' to indicate a
     unlimited maximum bound.  This can be useful when you wish only to
     set the minimum or nominal size of a window or partition.

Example
=======

     #!/usr/local/bin/perl
     BEGIN { unshift (@INC,qw(./blib .)) }
     use Tk;
     use Tk::BLT::Table;

     %attribx = (-fill => 'x', -border => 1, -relief => 'sunken');
     $top = new MainWindow;
         $table = Table $top -relief => 'ridge';
         configure $table -border => 5;

     $entry = Entry $table;
     put $table 0, 0, $entry;
     Create $table
         0, 1, 'Button', -text => "Button 1", -command => \&foo,
         0, 2, 'Entry',
         1, 2, 'Button', -text => "Button 3",
         2, 0, 'Entry',
         2, 1, 'Button', -text => "Button 5",
         2, 2, 'Entry';

     Cell $table 'configure',[1, 2], -anchor => "se";
     # $table->Row('forget', 0);
     # $table->Column('forget', 1);
     # $table->Column('configure', 1);

     ($table1) = Create $table
         1, 0, 'Table', -anchor => 'nw',-border => 5, -relief => 'raised';
     Create $table1
         0, 0, 'Button', -text => "But 1", -columnspan => 2, -fill => 'both',
         0, 2, 'Button', -text => "But 2", -rspan => 2, -fill => 'both',
         1, 0, 'Button', -text => "But 4", -rspan => 2, -fill => 'both',
         2, 1, 'Button', -text => "But 3", -cspan => 2, -fill => 'both',
         1, 1, 'Button', -text => "But 5", -fill => 'both';

     ($table0) = Create $table
         1, 1, 'Table', -border => 10, -relief => 'sunken', -fill => 'both';

     ($tablet) = Create $table0 0, 1, 'Table',-fill => 'x';
     Create $tablet
         0, 0, 'Label', -text => '1', %attribx,
         0, 1, 'Label', -text => '2', %attribx;

     ($tables) = Create $table0 2, 1, 'Table',-fill => 'x';
     Create $tables
         0, 0, 'Label', -text => '4', -fill => 'x', -border => 1, -relief => 'sunken',
         0, 1, 'Label', -text => '3', -fill => 'x', -border => 1, -relief => 'sunken';

     ($table3, $scrollv1, $scrollv2) = Create $table0
         1, 1, 'Table', -height => 200,
         1, 0, 'Scrollbar', -orient => 'vertical', -fill => 'y',
         1, 2, 'Scrollbar', -orient => 'vertical', -fill => 'y';
     configure $scrollv1 -command => ['yview', $table3];
     configure $scrollv2 -command => ['yview', $table3];
     configure $table3
         -yscrollcommand => sub { $scrollv1->set(@_); $scrollv2->set(@_); },
         -col => [$tablet, $tables];

     Create $table3
         0, 0, 'Text', -width => 6, -height => 8,
         5, 1, 'Button', -text => "Button 3", -command => sub {$table3->under(50, 50);},
         1, 0, 'Button', -text => "Button 4",
         1, 1, 'Entry',
         2, 0, 'Entry',
         2, 1, 'Button', -text => "Button 5",
         3, 0, 'Button', -text => "Button 6",
         3, 1, 'Entry',
         4, 0, 'Entry',
         4, 1, 'Button', -text => "Button 7",
         5, 0, 'Button', -text => "Button 8";

     ($table4) = Create $table3 0, 1, 'Table', -border => 2, -relief => 'groove';
     Create $table4
         1, 0, 'Button', -text => "Button 4",
         1, 1, 'Entry',
         2, 0, 'Entry',
         2, 1, 'Button', -text => "Button 5",
         3, 0, 'Button', -text => "Button 6",
         3, 1, 'Entry',
         4, 0, 'Entry';

     $table->pack(-fill => 'both', -expand => 1);
     # print $table->tablex(20)," ",$table->tabley(20),"\n";
     MainLoop;

     sub foo {
         @dim =  $table->dimension;
         $, = ' ';
         for($i=0; $i<$dim[0];$i++) {
     	print "$i : ",$table->Row('size', $i)," ",
     	$table->Column('size',$i),"\n";
         }
     }

pop up help balloons.
*********************

NAME
====

   Tk::Balloon - pop up help balloons.

SYNOPSIS
========

     use Tk::Balloon;
     ...
     $b = $top->Balloon(-statusbar => $status_bar_widget);

     # Normal Balloon:
     $b->attach($widget,
     	       -balloonmsg => "Balloon help message",
     	       -statusmsg => "Status bar message");

     # Balloon attached to entries in a menu widget:
     $b->attach($menu, -state => 'status',
     		      -msg => ['first menu entry',
     			       'second menu entry',
     			       ...
     			      ],
     	      );

     # Balloon attached to individual items in a canvas widget:
     $b->attach($canvas, -balloonposition => 'mouse',
     			-msg => {'item1' => 'msg1',
     				 'tag2'  => 'msg2',
     				  ...
     				},
     	      );

DESCRIPTION
===========

   *Balloon* provides the framework to create and attach help balloons to
various widgets so that when the mouse pauses over the widget for more
than a specified amount of time, a help balloon is popped up.

Balloons and Menus
------------------

   If the balloon is attached to a Menu widget and the message arguments
are array references, then each element in the array will be the message
corresponding to a menu entry. The balloon message will then be shown for
the entry which the mouse pauses over. Otherwise it is assumed that the
balloon is to be attached to the Menu as a whole.  You can have separate
status and balloon messages just like normal balloons.

Balloons and Canvases
---------------------

   If the balloon is attached to a Canvas widget and the message arguments
are hash references, then each hash key should correspond to a canvas item
ID or tag and the associated value will correspond to the message for that
canvas item. The balloon message will then be shown for the current item
(the one at the position of the mouse). Otherwise it is assumed that the
balloon is to be attached to the Canvas as a whole.  You can have separate
status and balloon messages just like normal balloons.

OPTIONS
=======

   *Balloon* accepts all of the options that the Frame widget accepts. In
addition, the following options are also recognized.

*-initwait*
     Specifies the amount of time to wait without activity before popping
     up a help balloon. Specified in milliseconds. Defaults to 350
     milliseconds. This applies to both the popped up balloon and the
     status bar message.

*-state*
     Can be one of *'balloon'*, *'status'*, *'both'* or *'none'*
     indicating that the help balloon, status bar help, both or none
     respectively should be activated when the mouse pauses over the
     client widget. Default is *'both'*.

*-statusbar*
     Specifies the widget used to display the status message. This widget
     should accept the *-text* option and is typically a Label. If the
     widget accepts the *-textvariable* option and that option is defined
     then it is used instead of the *-text* option.

*-balloonposition*
     Can be one of *'widget'* or *'mouse'*. It controls where the balloon
     will popup. *'widget'* makes the balloon appear at the lower right
     corner of the widget it is attached to (default), and *'mouse'* makes
     the balloon appear below and to the right of the current mouse
     position.

*-postcommand*
     This option takes a CODE reference which will be executed before the
     balloon and statusbar messages are displayed and should return a true
     or false value to indicate whether you want the balloon to be
     displayed or not. This also lets you control where the balloon is
     positioned by returning a true value that looks like *X,Y* (matches
     this regular expression: `/^(\d+),(\d+)$/'). If the postcommand
     returns a value that matches that re then those coordinates will be
     used as the position to post the balloon. Warning: this subroutine
     should return quickly or the balloon response will appear slow.

*-cancelcommand*
     This option takes a CODE reference which will be executed before the
     balloon and statusbar messages are canceled and should return a true
     or false value to indicate whether you want the balloon to be canceled
     or not. Warning: this subroutine should return quickly or the balloon
     response will appear slow.

*-motioncommand*
     This option takes a CODE reference which will be executed for any
     motion event and should return a true or false value to indicate
     whether the currently displayed balloon should be canceled
     (deactivated).  If it returns true then the balloon will definitely
     be canceled, if it returns false then it may still be canceled
     depending the internal rules.  Note: a new balloon may be posted
     after the *-initwait* time interval, use the *-postcommand* option to
     control that behavior.  Warning: the subroutine should be extremely
     fast or the balloon response will appear slow and consume a lot of
     CPU time (it is executed every time the mouse moves over the widgets
     the balloon is attached to).

METHODS
=======

   The *Balloon* widget supports only three non-standard methods:

*attach(*widget, options)
-------------------------

   Attaches the widget indicated by widget to the help system. The allowed
options are:

*-statusmsg*
     The argument is the message to be shown on the status bar when the
     mouse pauses over this client. If this is not specified, but *-msg*
     is specified then the message displayed on the status bar is the same
     as the argument for *-msg*. If you give it a scalar reference then it
     is dereferenced before being displayed. Useful if the postcommand is
     used to change the message.

*-balloonmsg*
     The argument is the message to be displayed in the balloon that will
     be popped up when the mouse pauses over this client. As with
     *-statusmsg* if this is not specified, then it takes its value from
     the *-msg* specification if any. If neither *-balloonmsg* nor *-msg*
     are specified, or they are the empty string then no balloon is popped
     up instead of an empty balloon. If you give it a scalar reference
     then it is dereferenced before being displayed. Useful if the
     postcommand is used to change the message.

*-msg*
     The catch-all for *-statusmsg* and *-balloonmsg*. This is a
     convenient way of specifying the same message to be displayed in both
     the balloon and the status bar for the client.

*-initwait*
*-state*
*-statusbar*
*-balloonposition*
*-postcommand*
*-cancelcommand*
*-motioncommand*
     These options allow you to override the balloon's default value for
     those option for some of the widgets it is attached to. It accepts the
     same values as above and will default to the *Balloon*'s value.

*detach(*widget)
----------------

   Detaches the specified widget from the help system.

destroy
-------

   Destroys the specified balloon.

EXAMPLES
========

   See the balloon demo included with the widget demo script that came with
the distribution for examples on various ways to use balloons.

NOTES
=====

   Because of the overhead associated with each balloon you create (from
tracking the mouse movement to know when to activate and deactivate them)
you will see the best performance (low CPU consumption) if you create as
few balloons as possible and attach them to as many widgets as you can.
In other words, don't create a balloon for each widget you want to attach
one to.

CAVEATS
=======

   Pressing any button will deactivate (cancel) the current balloon, if
one exists. You can usually make the balloon reappear by moving the mouse
a little. Creative use of the 3 command options can help you out also. If
the mouse is over the balloon when a menu is unposted then the balloon
will remain until you move off of it.

BUGS
====

   Hopefully none, probably some.

AUTHORS
=======

   *Rajappa Iyer* rsi@earthling.net did the original coding.

   *Jason A. Smith* <smithj4@rpi.edu> added support for menus and made some
other enhancements.

   *Slaven Rezic* <eserte@cs.tu-berlin.de> added support for canvas items.

HISTORY
=======

   The code and documentation was derived from Balloon.tcl from the Tix4.0
distribution by Ioi Lam and modified by the above mentioned authors. This
code may be redistributed under the same terms as Perl.

Images that display two colors
******************************

NAME
====

   Tk::Bitmap - Images that display two colors

       *$image* = $widget->Bitmap?(name??,options?)

DESCRIPTION
===========

   A bitmap is an image whose pixels can display either of two colors or
be transparent.  A bitmap image is defined by four things:  a background
color, a foreground color, and two bitmaps, called the source and the mask.
Each of the bitmaps specifies 0/1 values for a rectangular array of
pixels, and the two bitmaps must have the same dimensions.  For pixels
where the mask is zero, the image displays nothing, producing a
transparent effect.  For other pixels, the image displays the foreground
color if the source data is one and the background color if the source
data is zero.

CREATING BITMAPS
================

   Bitmaps are created using $widget->Bitmap.  Bitmaps support the
following options:

*-background* => color
     Specifies a background color for the image in any of the standard
     ways accepted by Tk.  If this option is set to an empty string then
     the background pixels will be transparent.  This effect is achieved
     by using the source bitmap as the mask bitmap, ignoring any
     *-maskdata* or *-maskfile* options.

*-data* => string
     Specifies the contents of the source bitmap as a string.  The string
     must adhere to X11 bitmap format (e.g., as generated by the bitmap
     program).  If both the *-data* and *-file* options are specified, the
     *-data* option takes precedence.

*-file* => name
     name gives the name of a file whose contents define the source bitmap.
     The file must adhere to X11 bitmap format (e.g., as generated by the
     bitmap program).

*-foreground* => color
     Specifies a foreground color for the image in any of the standard
     ways accepted by Tk.

*-maskdata* => string
     Specifies the contents of the mask as a string.  The string must
     adhere to X11 bitmap format (e.g., as generated by the bitmap
     program).  If both the *-maskdata* and *-maskfile* options are
     specified, the *-maskdata* option takes precedence.

*-maskfile* => name
     name gives the name of a file whose contents define the mask.  The
     file must adhere to X11 bitmap format (e.g., as generated by the
     bitmap program).

IMAGE METHODS
=============

   When a bitmap image is created, Tk also creates a new object.  This
object supports the configure and cget methods described in
Tk/options, which can be used to enquire and modify the
options described above.

SEE ALSO
========

   `Tk::Image|Tk::Image' in this node `Tk::Pixmap|Tk::Pixmap' in this node
`Tk::Photo|Tk::Photo' in this node

KEYWORDS
========

   bitmap, image

entry widget with popup choices.
********************************

NAME
====

   Tk::BrowseEntry - entry widget with popup choices.

SYNOPSIS
========

     use Tk::BrowseEntry;

     $b = $frame->BrowseEntry(-label => "Label", -variable => \$var);
     $b->insert("end", "opt1");
     $b->insert("end", "opt2");
     $b->insert("end", "opt3");
     ...
     $b->pack;

DESCRIPTION
===========

   BrowseEntry is a poor man's ComboBox. It may be considered an enhanced
version of LabEntry which provides a button to popup the choices of the
possible values that the Entry may take. BrowseEntry supports all the
options LabEntry supports except *-textvariable*. This is replaced by
*-variable*. Other options that BrowseEntry supports.

*-listwidth*
     Specifies the width of the popup listbox.

*-variable*
     Specifies the variable in which the entered value is to be stored.

*-browsecmd*
     Specifies a function to call when a selection is made in the popped
     up listbox. It is passed the widget and the text of the entry
     selected. This function is called after the entry variable has been
     assigned the value.

*-listcmd*
     Specifies the function to call when the button next to the entry is
     pressed to popup the choices in the listbox. This is called before
     popping up the listbox, so can be used to populate the entries in the
     listbox.

*-arrowimage*
     Specifies the image to be used in the arrow button beside the entry
     widget. The default is an downward arrow image in the file
     cbxarrow.xbm

*-choices*
     Specifies the list of choices to pop up.  This is a reference to an
     array of strings specifying the choices.

*-state*
     Specifies one of three states for the widget: normal, readonly, or
     disabled.  If the widget is disabled then the value may not be changed
     and the arrow button won't activate.  If the widget is readonly, the
     entry may not be edited, but it may be changed by choosing a value
     from the popup listbox.  normal is the default.

METHODS
=======

*insert(*index, string)
     Inserts the text of string at the specified index. This string then
     becomes available as one of the choices.

delete(*index1*, *index2*)
     Deletes items from *index1* to *index2*.

BUGS
====

   BrowseEntry should really provide more of the ComboBox options.

AUTHOR
======

   *Rajappa Iyer* rsi@earthling.net

   *Chris Dean* ctdean@cogit.com made additions.

   This code was inspired by ComboBox.tcl in Tix4.0 by Ioi Lam and bears
more than a passing resemblance to ComboBox code. This may be distributed
under the same conditions as Perl.

Create and manipulate Button widgets
************************************

NAME
====

   Tk::Button - Create and manipulate Button widgets

   $button = *$parent*->Button(?options?);

STANDARD OPTIONS
================

*-activebackground*	*-cursor*	*-highlightthickness*	*-takefocus*
*-activeforeground*	*-disabledforeground*	*-image*	*-text*
*-anchor*	*-font*	-justify	*-textvariable*
*-background*	*-foreground*	*-padx*	*-underline*
*-bitmap*	*-highlightbackground*	*-pady*	*-wraplength*
*-borderwidth*	*-highlightcolor*	*-relief*

   See Tk/options, for details of the standard options.

WIDGET-SPECIFIC OPTIONS
=======================

Name:	command
Class:	Command
Switch:	*-command*
     Specifies a `Tk callback|Tk::callbacks', see Perl (perl.info),
     to associate with the button.  This command is typically invoked when
     mouse button 1 is released over the button window.

Name:	default
Class:	Default
Switch:	*-default*
     Specifies one of three states for the default ring: normal, active,
     or disabled.  In active state, the button is drawn with the platform
     specific appearance for a default button.  In normal state, the
     button is drawn with the platform specific appearance for a
     non-default button, leaving enough space to draw the default button
     appearance.  The normal and active states will result in buttons of
     the same size.  In disabled state, the button is drawn with the
     non-default button appearance without leaving space for the default
     appearance.  The disabled state may result in a smaller button than
     the active state.  ring.

Name:	height
Class:	*Height*
Switch:	*-height*
     Specifies a desired height for the button.  If an image or bitmap is
     being displayed in the button then the value is in screen units (i.e.
     any of the forms acceptable to *Tk_GetPixels*); for text it is in
     lines of text.  If this option isn't specified, the button's desired
     height is computed from the size of the image or bitmap or text being
     displayed in it.

Name:	state
Class:	State
Switch:	*-state*
     Specifies one of three states for the button:  normal, active, or
     disabled.  In normal state the button is displayed using the
     *foreground* and background options.  The active state is typically
     used when the pointer is over the button.  In active state the button
     is displayed using the *activeForeground* and *activeBackground*
     options.  Disabled state means that the button should be insensitive:
     the default bindings will refuse to activate the widget and will
     ignore mouse button presses.  In this state the *disabledForeground*
     and background options determine how the button is displayed.

Name:	width
Class:	Width
Switch:	*-width*
     Specifies a desired width for the button.  If an image or bitmap is
     being displayed in the button then the value is in screen units (i.e.
     any of the forms acceptable to *Tk_GetPixels*); for text it is in
     characters.  If this option isn't specified, the button's desired
     width is computed from the size of the image or bitmap or text being
     displayed in it.

DESCRIPTION
===========

   The Button method creates a new window (given by the $widget argument)
and makes it into a button widget.  Additional options, described above,
may be specified on the command line or in the option database to
configure aspects of the button such as its colors, font, text, and
initial relief.  The *button* command returns its $widget argument.  At
the time this command is invoked, there must not exist a window named
$widget, but $widget's parent must exist.

   A button is a widget that displays a textual string, bitmap or image.
If text is displayed, it must all be in a single font, but it can occupy
multiple lines on the screen (if it contains newlines or if wrapping
occurs because of the *-wraplength* option) and one of the characters may
optionally be underlined using the *-underline* option.  It can display
itself in either of three different ways, according to the *-state* option;
it can be made to appear raised, sunken, or flat; and it can be made to
flash.  When a user invokes the button (by pressing mouse button 1 with
the cursor over the button), then the `Tk callback|Tk::callbacks', see
Perl (perl.info), specified in the *-command* option is invoked.

WIDGET METHODS
==============

   The Button method creates a widget object.  This object supports the
configure and cget methods described in Tk/options,
which can be used to enquire and modify the options described above.  The
widget also inherits all the methods provided by the generic
`Tk::Widget|Tk::Widget' in this node class.

   The following additional methods are available for button widgets:

$button->flash
     Flash the button.  This is accomplished by redisplaying the button
     several times, alternating between active and normal colors.  At the
     end of the flash the button is left in the same normal/active state
     as when the command was invoked.  This command is ignored if the
     button's state is disabled.

$button->*invoke*
     Invoke the `callback|Tk::callbacks' in this node associated with the
     buttons *-command* option, if there is one.  The return value is the
     return value from the callback, or the undefined value if there is no
     callback associated with the button.  This command is ignored if the
     button's state is disabled.

DEFAULT BINDINGS
================

   Tk automatically creates class bindings for buttons that give them
default behavior:

[1]
     A button activates whenever the mouse passes over it and deactivates
     whenever the mouse leaves the button.  Under Windows, this binding is
     only active when mouse button 1 has been pressed over the button.

[2]
     A button's relief is changed to sunken whenever mouse button 1 is
     pressed over the button, and the relief is restored to its original
     value when button 1 is later released.

[3]
     If mouse button 1 is pressed over a button and later released over
     the button, the button is invoked.  However, if the mouse is not over
     the button when button 1 is released, then no invocation occurs.

[4]
     When a button has the input focus, the space key causes the button to
     be invoked.

     If the button's state is disabled then none of the above actions
     occur:  the button is completely non-responsive.

     The behavior of buttons can be changed by defining new bindings for
     individual widgets or by redefining the class bindings.

KEYWORDS
========

   button, widget

Create and manipulate Canvas widgets                      =for category  Tk Widget Classes
******************************************************************************************

NAME
====

   Tk::Canvas - Create and manipulate Canvas widgets

   =for category  Tk Widget Classes

SYNOPSIS
========

   *$canvas* = *$parent*->Canvas(?options?);

STANDARD OPTIONS
================

   *-background*	*-highlightthickness*	*-insertwidth*	*-state*
*-borderwidth*	*-insertbackground*	*-relief*	*-tile*
*-cursor*	*-insertborderwidth*	*-selectbackground*	*-takefocus*
*-highlightbackground*	*-insertofftime*	*-selectborderwidth*	*-xscrollcommand*
*-highlightcolor*	*-insertontime*	*-selectforeground*	*-yscrollcommand*

WIDGET-SPECIFIC OPTIONS
=======================

Name:	*closeEnough*
Class:	*CloseEnough*
Switch:	*-closeenough*
     Specifies a floating-point value indicating how close the mouse cursor
     must be to an item before it is considered to be "inside" the item.
     Defaults to 1.0.

Name:	*confine*
Class:	*Confine*
Switch:	*-confine*
     Specifies a boolean value that indicates whether or not it should be
     allowable to set the canvas's view outside the region defined by the
     *scrollRegion* argument.  Defaults to true, which means that the view
     will be constrained within the scroll region.

Name:	height
Class:	*Height*
Switch:	*-height*
     Specifies a desired window height that the canvas widget should
     request from its geometry manager.  The value may be specified in any
     of the forms described in the `"COORDINATES"' in this node section
     below.

Name:	*scrollRegion*
Class:	*ScrollRegion*
Switch:	*-scrollregion*
     Specifies a list with four coordinates describing the left, top,
     right, and bottom coordinates of a rectangular region.  This region
     is used for scrolling purposes and is considered to be the boundary
     of the information in the canvas.  Each of the coordinates may be
     specified in any of the forms given in the `"COORDINATES"' in this
     node section below.

Name:	state
Class:	State
Switch:	*-state*
     Modifies the default state of the canvas where state may be set to
     one of: normal, disabled, or hidden. Individual canvas objects all
     have their own state option, which overrides the default state. Many
     options can take separate specifications such that the appearance of
     the item can be different in different situations. The options that
     start with "active" control the appearence when the mouse pointer is
     over it, while the option starting with "disabled" controls the
     appearence when the state is disabled.

Name:	width
Class:	width
Switch:	*-width*
     Specifies a desired window width that the canvas widget should
     request from its geometry manager.  The value may be specified in any
     of the forms described in the `"COORDINATES"' in this node section
     below.

Name:	*xScrollIncrement*
Class:	*ScrollIncrement*
Switch:	*-xscrollincrement*
     Specifies an increment for horizontal scrolling, in any of the usual
     forms permitted for screen distances.  If the value of this option is
     greater than zero, the horizontal view in the window will be
     constrained so that the canvas x coordinate at the left edge of the
     window is always an even multiple of *xScrollIncrement*;
     furthermore, the units for scrolling (e.g., the change in view when
     the left and right arrows of a scrollbar are selected) will also be
     *xScrollIncrement*.  If the value of this option is less than or
     equal to zero, then horizontal scrolling is unconstrained.

Name:	*yScrollIncrement*
Class:	*ScrollIncrement*
Switch:	*-yscrollincrement*
     Specifies an increment for vertical scrolling, in any of the usual
     forms permitted for screen distances.  If the value of this option is
     greater than zero, the vertical view in the window will be
     constrained so that the canvas y coordinate at the top edge of the
     window is always an even multiple of *yScrollIncrement*;
     furthermore, the units for scrolling (e.g., the change in view when
     the top and bottom arrows of a scrollbar are selected) will also be
     *yScrollIncrement*.  If the value of this option is less than or
     equal to zero, then vertical scrolling is unconstrained.

DESCRIPTION
===========

   The Canvas method creates a new window (given by the $canvas argument)
and makes it into a canvas widget.  Additional options, described above,
may be specified on the command line or in the option database to
configure aspects of the canvas such as its colors and 3-D relief.  The
canvas command returns its $canvas argument.  At the time this command is
invoked, there must not exist a window named $canvas, but $canvas's parent
must exist.

   Canvas widgets implement structured graphics.  A canvas displays any
number of items, which may be things like rectangles, circles, lines, and
text.  Items may be manipulated (e.g. moved or re-colored) and
`callbacks|Tk::callbacks' in this node may be associated with items in
much the same way that the `bind|Tk::bind' in this node method allows
callbacks to be bound to widgets.  For example, a particular callback may
be associated with the *<Button-1>* event so that the callback is invoked
whenever button 1 is pressed with the mouse cursor over an item.  This
means that items in a canvas can have behaviors defined by the Callbacks
bound to them.

DISPLAY LIST
============

   The items in a canvas are ordered for purposes of display, with the
first item in the display list being displayed first, followed by the next
item in the list, and so on.  Items later in the display list obscure
those that are earlier in the display list and are sometimes referred to
as being *"on top"* of earlier items.  When a new item is created it is
placed at the end of the display list, on top of everything else.  Widget
methods may be used to re-arrange the order of the display list.

   Window items are an exception to the above rules.  The underlying
window systems require them always to be drawn on top of other items.  In
addition, the stacking order of window items is not affected by any of the
canvas methods; you must use the `raise|Tk::Widget' in this node and
`lower|Tk::Widget' in this node Tk widget methods instead.

ITEM IDS AND TAGS
=================

   Items in a canvas widget may be named in either of two ways: by id or
by tag.  Each item has a unique identifying number which is assigned to
that item when it is created.  The id of an item never changes and id
numbers are never re-used within the lifetime of a canvas widget.

   Each item may also have any number of tags associated with it.  A tag
is just a string of characters, and it may take any form except that of an
integer.  For example, "x123" is OK but "123" isn't.  The same tag may be
associated with many different items.  This is commonly done to group
items in various interesting ways;  for example, all selected items might
be given the tag "selected".

   The tag all is implicitly associated with every item in the canvas;  it
may be used to invoke operations on all the items in the canvas.

   The tag current is managed automatically by Tk; it applies to the
*current item*, which is the topmost item whose drawn area covers the
position of the mouse cursor.  If the mouse is not in the canvas widget or
is not over an item, then no item has the current tag.

   When specifying items in canvas methods, if the specifier is an integer
then it is assumed to refer to the single item with that id.  If the
specifier is not an integer, then it is assumed to refer to all of the
items in the canvas that have a tag matching the specifier.  The symbol
*tagOrId* is used below to indicate that an argument specifies either an
id that selects a single item or a tag that selects zero or more items.

   *tagOrId* may contain a logical expressions of tags by using operators:
'E<amp>E<amp>', '||', '^' '!', and parenthezised subexpressions.  For
example:

   $c->find('withtag',  '(aE<amp>E<amp>!b)|(!aE<amp>E<amp>b)');

   or equivalently:

   $c->find('withtag', 'a^b');

   will find only those items with either "a" or "b" tags, but not both.

   Some methods only operate on a single item at a time;  if *tagOrId* is
specified in a way that names multiple items, then the normal behavior is
for the methods is to use the first (lowest) of these items in the display
list that is suitable for the method.  Exceptions are noted in the method
descriptions below.

COORDINATES
===========

   All coordinates related to canvases are stored as floating-point
numbers.  Coordinates and distances are specified in screen units, which
are floating-point numbers optionally followed by one of several letters.
If no letter is supplied then the distance is in pixels.  If the letter is
m then the distance is in millimeters on the screen;  if it is c then the
distance is in centimeters; i means inches, and p means printers points
(1/72 inch).  Larger y-coordinates refer to points lower on the screen;
larger x-coordinates refer to points farther to the right.

TRANSFORMATIONS
===============

   Normally the origin of the canvas coordinate system is at the
upper-left corner of the window containing the canvas.  It is possible to
adjust the origin of the canvas coordinate system relative to the origin
of the window using the *xview* and *yview* methods;  this is typically
used for scrolling.  Canvases do not support scaling or rotation of the
canvas coordinate system relative to the window coordinate system.

   Individual items may be moved or scaled using methods described below,
but they may not be rotated.

INDICES
=======

   Text items support the notion of an index for identifying particular
positions within the item.

   Indices are used for methods such as inserting text, deleting a range
of characters, and setting the insertion cursor position.  An index may be
specified in any of a number of ways, and different types of items may
support different forms for specifying indices.

   In a similar fashion, line and polygon items support index for
identifying, inserting and deleting subsets of their coordinates.  Indices
are used for commands such as inserting or deleting a range of characters
or coordinates, and setting the insertion cursor position. An index may be
specified in any of a number of ways, and different types of items may
support different forms for specifying indices.

   Text items support the following forms for an index;  if you define new
types of text-like items, it would be advisable to support as many of
these forms as practical.  Note that it is possible to refer to the
character just after the last one in the text item;  this is necessary for
such tasks as inserting new text at the end of the item.  Lines and
Polygons don't support the insertion cursor and the selection. Their
indices are supposed to be even always, because coordinates always appear
in pairs.

number
     A decimal number giving the position of the desired character within
     the text item.  0 refers to the first character, 1 to the next
     character, and so on. If indexes are odd for lines and polygons, they
     will be automatically decremented by one.  A number less than 0 is
     treated as if it were zero, and a number greater than the length of
     the text item is treated as if it were equal to the length of the
     text item. For polygons, numbers less than 0 or greater then the
     length of the coordinate list will be adjusted by adding or
     substracting the length until the result is between zero and the
     length, inclusive.

end
     Refers to the character or coordinate just after the last one in the
     item (same as the number of characters or coordinates in the item).

insert
     Refers to the character just before which the insertion cursor is
     drawn in this item. Not valid for lines and polygons.

sel.first
     Refers to the first selected character in the item.  If the selection
     isn't in this item then this form is illegal.

sel.last
     Refers to the last selected character in the item.  If the selection
     isn't in this item then this form is illegal.

[*x,y*]
     Refers to the character or coordinate at the point given by x and y,
     where x and y are specified in the coordinate system of the canvas.
     If x and y lie outside the coordinates covered by the text item, then
     they refer to the first or last character in the line that is closest
     to the given point.  The Tcl string form "@x,y" is also allowed.

DASH PATTERNS
=============

   Many items support the notion of an dash pattern for outlines.

   The first possible syntax is a list of integers. Each element
represents the number of pixels of a line segment. Only the odd segments
are drawn using the "outline" color. The other segments are drawn
transparant.

   The second possible syntax is a character list containing only 5
possible characters *[.,-_ ]*. The space can be used to enlarge the space
between other line elements, and can not occur as the first position in
the string. Some examples:

     -dash .     = -dash [2,4]
     -dash -     = -dash [6,4]
     -dash -.    = -dash [6,4,2,4]
     -dash -..   = -dash [6,4,2,4,2,4]
     -dash '. '  = -dash [2,8]
     -dash ','   = -dash [4,4]

   The main difference of this syntax with the previous is that it it
shape-conserving. This means that all values in the dash list will be
multiplied by the line width before display. This assures that "." will
always be displayed as a dot and "-" always as a dash regardless of the
line width.

   On systems where only a limited set of dash patterns, the dash pattern
will be displayed as the most close dash pattern that is available. For
example, on Windows only the first 4 of the above examples are available.
The last 2 examples will be displayed identically as the first one.

WIDGET METHODS
==============

   The Canvas method creates a widget object.  This object supports the
configure and cget methods described in Tk/options,
which can be used to enquire and modify the options described above.  The
widget also inherits all the methods provided by the generic
`Tk::Widget|Tk::Widget' in this node class.

   The following additional methods are available for canvas widgets:

*$canvas*->*addtag*(*tag, searchSpec, *?*arg, arg, ...*?)
     For each item that meets the constraints specified by *searchSpec*
     and the *arg*s, add tag to the list of tags associated with the item
     if it isn't already present on that list.  It is possible that no
     items will satisfy the constraints given by *searchSpec* and *arg*s,
     in which case the method has no effect.  This command returns an
     empty string as result.  *SearchSpec* and *arg*'s may take any of the
     following forms:

    *above **tagOrId*
          Selects the item just after (above) the one given by *tagOrId*
          in the display list.  If *tagOrId* denotes more than one item,
          then the last (topmost) of these items in the display list is
          used.

    all
          Selects all the items in the canvas.

    *below **tagOrId*
          Selects the item just before (below) the one given by *tagOrId*
          in the display list.  If *tagOrId* denotes more than one item,
          then the first (lowest) of these items in the display list is
          used.

    *closest **x y *?*halo*? ?start?
          Selects the item closest to the point given by x and y.  If more
          than one item is at the same closest distance (e.g. two items
          overlap the point), then the top-most of these items (the last
          one in the display list) is used.  If *halo* is specified, then
          it must be a non-negative value.  Any item closer than *halo* to
          the point is considered to overlap it.  The start argument may
          be used to step circularly through all the closest items.  If
          start is specified, it names an item using a tag or id (if by
          tag, it selects the first item in the display list with the
          given tag).  Instead of selecting the topmost closest item, this
          form will select the topmost closest item that is below start in
          the display list;  if no such item exists, then the selection
          behaves as if the start argument had not been specified.

    enclosed x1 *y1* x2 *y2*
          Selects all the items completely enclosed within the rectangular
          region given by x1, *y1*, x2, and *y2*.  *X1* must be no greater
          then x2 and *y1* must be no greater than *y2*.

    overlapping x1 *y1* x2 *y2*
          Selects all the items that overlap or are enclosed within the
          rectangular region given by x1, *y1*, x2, and *y2*.  *X1* must
          be no greater then x2 and *y1* must be no greater than *y2*.

    *withtag **tagOrId*
          Selects all the items given by *tagOrId*.

*$canvas*->*bbox*(*tagOrId, *?*tagOrId, tagOrId, ...*?)
     Returns a list with four elements giving an approximate bounding box
     for all the items named by the *tagOrId* arguments.  The list has the
     form "*x1 y1 x2 y2*" such that the drawn areas of all the named
     elements are within the region bounded by x1 on the left, x2 on the
     right, *y1* on the top, and *y2* on the bottom.  The return value may
     overestimate the actual bounding box by a few pixels.  If no items
     match any of the *tagOrId* arguments or if the matching items have
     empty bounding boxes (i.e. they have nothing to display) then an
     empty string is returned.

*$canvas*->bind(*tagOrId*?, sequence? ?,callback?)
     This method associates callback with all the items given by *tagOrId*
     such that whenever the event sequence given by sequence occurs for
     one of the items the callback will be invoked.  This method is
     similar to the bind method except that it operates on items in a
     canvas rather than entire widgets.  See Tk/bind, for
     complete details on the syntax of sequence and the substitutions
     performed on callback before invoking it.  If all arguments are
     specified then a new binding is created, replacing any existing
     binding for the same sequence and *tagOrId* (if the first character
     of command is "+" then command augments an existing binding rather
     than replacing it).  In this case the return value is an empty string.
     If callback is omitted then the method returns the callback
     associated with *tagOrId* and sequence (an error occurs if there is
     no such binding).  If both callback and sequence are omitted then the
     method returns a list of all the sequences for which bindings have
     been defined for *tagOrId*.

     The only events for which bindings may be specified are those related
     to the mouse and keyboard (such as Enter, *Leave*, *ButtonPress*,
     *Motion*, and *KeyPress*) or virtual events.  The handling of events
     in canvases uses the current item defined in `"ITEM IDS AND TAGS"' in
     this node above.  Enter and *Leave* events trigger for an item when
     it becomes the current item or ceases to be the current item; note
     that these events are different than Enter and *Leave* events for
     windows.  Mouse-related events are directed to the current item, if
     any.  Keyboard-related events are directed to the focus item, if any
     (see the `focus|' in this node method below for more on this).  If a
     virtual event is used in a binding, that binding can trigger only if
     the virtual event is defined by an underlying mouse-related or
     keyboard-related event.

     It is possible for multiple bindings to match a particular event.
     This could occur, for example, if one binding is associated with the
     item's id and another is associated with one of the item's tags.
     When this occurs, all of the matching bindings are invoked.  A
     binding associated with the all tag is invoked first, followed by one
     binding for each of the item's tags (in order), followed by a binding
     associated with the item's id.  If there are multiple matching
     bindings for a single tag, then only the most specific binding is
     invoked.  A continue in a callback terminates that subroutine, and a
     break method terminates that subroutine and skips any remaining
     callbacks for the event, just as for the bind method.

     If bindings have been created for a canvas window using the
     *CanvasBind* method, then they are invoked in addition to bindings
     created for the canvas's items using the bind method.  The bindings
     for items will be invoked before any of the bindings for the window
     as a whole.

*$canvas*->*canvasx*(*screenx*?, *gridspacing*?)
     Given a window x-coordinate in the canvas *screenx*, this method
     returns the canvas x-coordinate that is displayed at that location.
     If *gridspacing* is specified, then the canvas coordinate is rounded
     to the nearest multiple of *gridspacing* units.

*$canvas*->*canvasy*(*screeny, *?*gridspacing*?)
     Given a window y-coordinate in the canvas *screeny* this method
     returns the canvas y-coordinate that is displayed at that location.
     If *gridspacing* is specified, then the canvas coordinate is rounded
     to the nearest multiple of *gridspacing* units.

*$canvas*->*coords*(*tagOrId *?*x0,y0 ...*?)
     Query or modify the coordinates that define an item.  If no
     coordinates are specified, this method returns a list whose elements
     are the coordinates of the item named by *tagOrId*.  If coordinates
     are specified, then they replace the current coordinates for the
     named item.  If *tagOrId* refers to multiple items, then the first
     one in the display list is used.

*$canvas*->create(*type, x, y, *?*x, y, ...*?, ?*option, value, ...*?)
     Create a new item in *$canvas* of type type.  The exact format of the
     arguments after type depends on type, but usually they consist of the
     coordinates for one or more points, followed by specifications for
     zero or more item options.  See the subsections on individual item
     types below for more on the syntax of this method.  This method
     returns the id for the new item.

*$canvas*->*dchars*(*tagOrId, first, *?last?)
     For each item given by *tagOrId*, delete the characters, or
     coordinates, in the range given by first and last, inclusive.  If
     some of the items given by *tagOrId* don't support Text items
     interpret first and last as indices to a character, line and polygon
     items interpret them indices to a coordinate (an x,y pair).  within
     the item(s) as described in `"INDICES"' in this node above.  If last
     is omitted, it defaults to first.  This method returns an empty
     string.

*$canvas*->delete(?*tagOrId, tagOrId, ...*?)
     Delete each of the items given by each *tagOrId*, and return an empty
     string.

*$canvas*->*dtag*(*tagOrId, *?*tagToDelete*?)
     For each of the items given by *tagOrId*, delete the tag given by
     *tagToDelete* from the list of those associated with the item.  If an
     item doesn't have the tag *tagToDelete* then the item is unaffected
     by the method.  If *tagToDelete* is omitted then it defaults to
     *tagOrId*.  This method returns an empty string.

*$canvas*->find(*searchCommand, *?*arg, arg, ...*?)
     This method returns a list consisting of all the items that meet the
     constraints specified by *searchCommand* and *arg*'s.
     *SearchCommand* and args have any of the forms accepted by the
     *addtag* method.  The items are returned in stacking order, with the
     lowest item first.

     =item focus

*$canvas*->focus(?*tagOrId*?)
     Set the keyboard focus for the canvas widget to the item given by
     *tagOrId*.  If *tagOrId* refers to several items, then the focus is
     set to the first such item in the display list that supports the
     insertion cursor.  If *tagOrId* doesn't refer to any items, or if
     none of them support the insertion cursor, then the focus isn't
     changed.  If *tagOrId* is an empty string, then the focus item is
     reset so that no item has the focus.  If *tagOrId* is not specified
     then the method returns the id for the item that currently has the
     focus, or an empty string if no item has the focus.

     Once the focus has been set to an item, the item will display the
     insertion cursor and all keyboard events will be directed to that
     item.  The focus item within a canvas and the focus window on the
     screen (set with the focus method) are totally independent: a given
     item doesn't actually have the input focus unless (a) its canvas is
     the focus window and (b) the item is the focus item within the canvas.
     In most cases it is advisable to follow the focus widget method with
     the *CanvasFocus* method to set the focus window to the canvas (if it
     wasn't there already).

*$canvas*->*gettags*(*tagOrId*)
     Return a list whose elements are the tags associated with the item
     given by *tagOrId*.  If *tagOrId* refers to more than one item, then
     the tags are returned from the first such item in the display list.
     If *tagOrId* doesn't refer to any items, or if the item contains no
     tags, then an empty string is returned.

*$canvas*->*icursor*(*tagOrId, index*)
     Set the position of the insertion cursor for the item(s) given by
     *tagOrId* to just before the character whose position is given by
     index.  If some or all of the items given by *tagOrId* don't support
     an insertion cursor then this method has no effect on them.  See
     `"INDICES"' in this node above for a description of the legal forms
     for index.  Note:  the insertion cursor is only displayed in an item
     if that item currently has the keyboard focus (see the widget method
     focus, below), but the cursor position may be set even when the item
     doesn't have the focus.  This method returns an empty string.

*$canvas*->index(*tagOrId, index*)
     This method returns a decimal string giving the numerical index
     within *tagOrId* corresponding to index.  Index gives a textual
     description of the desired position as described in `"INDICES"' in
     this node above.  Text items interpret index as an index to a
     character, line and polygon items interpret it as an index to a
     coordinate (an x,y pair).  The return value is guaranteed to lie
     between 0 and the number of characters, or coordinates, within the
     item, inclusive.  If *tagOrId* refers to multiple items, then the
     index is processed in the first of these items that supports indexing
     operations (in display list order).

*$canvas*->insert(*tagOrId, beforeThis, string*)
     For each of the items given by *tagOrId*, if the item supports text
     or coordinate, insertion then string is inserted into the item's text
     just before the character, or coordinate, whose index is *beforeThis*.
     Text items interpret *beforethis* as an index to a  character, line
     and polygon items interpret it as an index to a coordinate (an x,y
     pair).  For lines and polygons the string must be a valid coordinate
     sequence.  See `"INDICES"' in this node above for information about
     the forms allowed for *beforeThis*.  This method returns an empty
     string.

*$canvas*->*itemcget*(*tagOrId, *option)
     Returns the current value of the configuration option for the item
     given by *tagOrId* whose name is option.  This method is similar to
     the `cget|Tk::option' in this node method except that it applies to a
     particular item rather than the widget as a whole.  Option may have
     any of the values accepted by the create method when the item was
     created.  If *tagOrId* is a tag that refers to more than one item,
     the first (lowest) such item is used.

*$canvas*->*itemconfigure*(*tagOrId, *?option?, ?value?, ?*option, value, ...*?)
     This method is similar to the `configure|Tk::option' in this node
     method except that it modifies item-specific options for the items
     given by *tagOrId* instead of modifying options for the overall
     canvas widget.  If no option is specified, returns a list describing
     all of the available options for the first item given by *tagOrId*
     (see Tk/options, for information on the format of
     this list).  If option is specified with no value, then the method
     returns a list describing the one named option (this list will be
     identical to the corresponding sublist of the value returned if no
     option is specified).  If one or more *option-value* pairs are
     specified, then the method modifies the given widget option(s) to
     have the given value(s) in each of the items given by *tagOrId*;  in
     this case the method returns an empty string.  The options and values
     are the same as those permissible in the create method when the
     item(s) were created; see the sections describing individual item
     types below for details on the legal options.

*$canvas*->*lower*(*tagOrId, *?*belowThis*?)
     Move all of the items given by *tagOrId* to a new position in the
     display list just before the item given by *belowThis*.  If *tagOrId*
     refers to more than one item then all are moved but the relative
     order of the moved items will not be changed.  *BelowThis* is a tag
     or id;  if it refers to more than one item then the first (lowest) of
     these items in the display list is used as the destination location
     for the moved items.  Note: this method has no effect on window
     items.  Window items always obscure other item types, and the
     stacking order of window items is determined by the raise and *lower*
     methods of the widget, not the raise and *lower* methods for canvases.
     This method returns an empty string.

*$canvas*->move(*tagOrId, xAmount, yAmount*)
     Move each of the items given by *tagOrId* in the canvas coordinate
     space by adding *xAmount* to the x-coordinate of each point
     associated with the item and *yAmount* to the y-coordinate of each
     point associated with the item.  This method returns an empty string.

*$canvas*->postscript(?*option, value, option, value, ...*?)
     Generate a Postscript representation for part or all of the canvas.
     If the *-file* option is specified then the Postscript is written to
     a file and an empty string is returned;  otherwise the Postscript is
     returned as the result of the method.  If the interpreter that owns
     the canvas is marked as safe, the operation will fail because safe
     interpreters are not allowed to write files.  If the *-channel*
     option is specified, the argument denotes the name of a channel
     already opened for writing. The Postscript is written to that
     channel, and the channel is left open for further writing at the end
     of the operation.  The Postscript is created in Encapsulated
     Postscript form using version 3.0 of the Document Structuring
     Conventions.  Note: by default Postscript is only generated for
     information that appears in the canvas's window on the screen.  If
     the canvas is freshly created it may still have its initial size of
     1x1 pixel so nothing will appear in the Postscript.  To get around
     this problem either invoke the update method to wait for the canvas
     window to reach its final size, or else use the *-width* and *-height*
     options to specify the area of the canvas to print.  The option-value
     argument pairs provide additional information to control the
     generation of Postscript.  The following options are supported:

    *-colormap* => *hashRef*
          *HashRef* must be a reference to a hash variable or an anonymous
          hash that specifies a color mapping to use in the Postscript.
          Each value of the hash must consist of Postscript code to set a
          particular color value (e.g. "*1.0 1.0 0.0 setrgbcolor*").  When
          outputting color information in the Postscript, Tk checks to see
          if there is a key in the hash with the same name as the color.
          If so, Tk uses the value of the element as the Postscript method
          to set the color.  If this option hasn't been specified, or if
          there isn't a key in *hashRef* for a given color, then Tk uses
          the red, green, and blue intensities from the X color.

    *-colormode* => mode
          Specifies how to output color information.  Mode must be either
          color (for full color output), *gray* (convert all colors to
          their gray-scale equivalents) or *mono* (convert all colors to
          black or white).

    *-file* => *fileName*
          Specifies the name of the file in which to write the Postscript.
          If this option isn't specified then the Postscript is returned
          as the result of the method instead of being written to a file.

    *-fontmap* => *hashRef*
          *HashRef* must be a reference to a hash variable or an anonymous
          hash that specifies a font mapping to use in the Postscript.
          Each value of the hash must consist of an array reference with
          two elements, which are the name and point size of a Postscript
          font.  When outputting Postscript commands for a particular
          font, Tk checks to see if *hashRef* contains a value with the
          same name as the font.  If there is such an element, then the
          font information contained in that element is used in the
          Postscript.  Otherwise Tk attempts to guess what Postscript font
          to use.  Tk's guesses generally only work for well-known fonts
          such as Times and Helvetica and Courier, and only if the X font
          name does not omit any dashes up through the point size.  For
          example, *-*-Courier-Bold-R-Normal-*-120-** will work but
          **Courier-Bold-R-Normal*120** will not;  Tk needs the dashes to
          parse the font name).

    *-height* => size
          Specifies the height of the area of the canvas to print.
          Defaults to the height of the canvas window.

    *-pageanchor* => anchor
          Specifies which point of the printed area of the canvas should
          appear over the positioning point on the page (which is given by
          the *-pagex* and *-pagey* options).  For example,
          *-pageanchor*=>n means that the top center of the area of the
          canvas being printed (as it appears in the canvas window) should
          be over the positioning point. Defaults to center.

    *-pageheight* => size
          Specifies that the Postscript should be scaled in both x and y so
          that the printed area is size high on the Postscript page.  Size
          consists of a floating-point number followed by c for
          centimeters, i for inches, m for millimeters, or p or nothing
          for printer's points (1/72 inch).  Defaults to the height of the
          printed area on the screen.  If both *-pageheight* and
          *-pagewidth* are specified then the scale factor from
          *-pagewidth* is used (non-uniform scaling is not implemented).

    *-pagewidth* => size
          Specifies that the Postscript should be scaled in both x and y so
          that the printed area is size wide on the Postscript page.  Size
          has the same form as for *-pageheight*.  Defaults to the width
          of the printed area on the screen.  If both *-pageheight* and
          *-pagewidth* are specified then the scale factor from
          *-pagewidth*  is used (non-uniform scaling is not implemented).

    *-pagex* => position
          Position gives the x-coordinate of the positioning point on the
          Postscript page, using any of the forms allowed for
          *-pageheight*.  Used in conjunction with the *-pagey* and
          *-pageanchor* options to determine where the printed area
          appears on the Postscript page.  Defaults to the center of the
          page.

    *-pagey* => position
          Position gives the y-coordinate of the positioning point on the
          Postscript page, using any of the forms allowed for
          *-pageheight*.  Used in conjunction with the *-pagex* and
          *-pageanchor* options to determine where the printed area
          appears on the Postscript page.  Defaults to the center of the
          page.

    *-rotate* => boolean
          Boolean specifies whether the printed area is to be rotated 90
          degrees.  In non-rotated output the x-axis of the printed area
          runs along the short dimension of the page ("portrait"
          orientation); in rotated output the x-axis runs along the long
          dimension of the page ("landscape" orientation).  Defaults to
          non-rotated.

    *-width* => size
          Specifies the width of the area of the canvas to print.
          Defaults to the width of the canvas window.

    -x => position
          Specifies the x-coordinate of the left edge of the area of the
          canvas that is to be printed, in canvas coordinates, not window
          coordinates.  Defaults to the coordinate of the left edge of the
          window.

    -y => position
          Specifies the y-coordinate of the top edge of the area of the
          canvas that is to be printed, in canvas coordinates, not window
          coordinates.  Defaults to the coordinate of the top edge of the
          window.

*$canvas*->raise(*tagOrId, *?*aboveThis*?)
     Move all of the items given by *tagOrId* to a new position in the
     display list just after the item given by *aboveThis*.  If *tagOrId*
     refers to more than one item then all are moved but the relative
     order of the moved items will not be changed.  *AboveThis* is a tag
     or id;  if it refers to more than one item then the last (topmost) of
     these items in the display list is used as the destination location
     for the moved items.  Note: this method has no effect on window
     items.  Window items always obscure other item types, and the
     stacking order of window items is determined by the raise and *lower*
     widget commands, not the raise and *lower* methods for canvases.
     This method returns an empty string.

*$canvas*->scale(*tagOrId, xOrigin, yOrigin, xScale, yScale*)
     Rescale all of the items given by *tagOrId* in canvas coordinate
     space.  *XOrigin* and *yOrigin* identify the origin for the scaling
     operation and *xScale* and *yScale* identify the scale factors for x-
     and y-coordinates, respectively (a scale factor of 1.0 implies no
     change to that coordinate).  For each of the points defining each
     item, the x-coordinate is adjusted to change the distance from
     *xOrigin* by a factor of *xScale*.  Similarly, each y-coordinate is
     adjusted to change the distance from *yOrigin* by a factor of
     *yScale*.  This method returns an empty string.

*$canvas*->scan(*option, args*)
     This method is used to implement scanning on canvases.  It has two
     forms, depending on option:

    *$canvas*->*scanMark*(*x, y*)
          Records x and y and the canvas's current view;  used in
          conjunction with later *scanDragto* method.  Typically this
          method is associated with a mouse button press in the widget and
          x and y are the coordinates of the mouse.  It returns an empty
          string.

    *$canvas*->*scanDragto*(*x, y, ?gain?*.)
          This method computes the difference between its x and y
          arguments (which are typically mouse coordinates) and the x and
          y arguments to the last *scanMark* method for the widget.  It
          then adjusts the view by 10 times the difference in coordinates.
          This method is typically associated It then adjusts the view by
          *gain* times the difference in coordinates, where *gain*
          defaults to 10.  This command is typically associated with mouse
          motion events in the widget, to produce the effect of dragging
          the canvas at high speed through its window.  The return value
          is an empty string.

*$canvas*->select(*option, *?*tagOrId, arg*?)
     Manipulates the selection in one of several ways, depending on option.
     The method may take any of the forms described below.  In all of the
     descriptions below, *tagOrId* must refer to an item that supports
     indexing and selection;  if it refers to multiple items then the
     first of these that supports indexing and the selection is used.
     Index gives a textual description of a position within *tagOrId*, as
     described in `"INDICES"' in this node above.

    *$canvas*->*selectAdjust*(*tagOrId, index*)
          Locate the end of the selection in *tagOrId* nearest to the
          character given by index, and adjust that end of the selection
          to be at index (i.e. including but not going beyond index).  The
          other end of the selection is made the anchor point for future
          *selectTo* method calls.  If the selection isn't currently in
          *tagOrId* then this method behaves the same as the *selectTo*
          widget method.  Returns an empty string.

    *$canvas*->*selectClear*
          Clear the selection if it is in this widget.  If the selection
          isn't in this widget then the method has no effect.  Returns an
          empty string.

    *$canvas*->*selectFrom*(*tagOrId, index*)
          Set the selection anchor point for the widget to be just before
          the character given by index in the item given by *tagOrId*.
          This method doesn't change the selection;  it just sets the
          fixed end of the selection for future *selectTo* method calls.
          Returns an empty string.

    *$canvas*->*selectItem*
          Returns the id of the selected item, if the selection is in an
          item in this canvas.  If the selection is not in this canvas
          then an empty string is returned.

    *$canvas*->*selectTo*(*tagOrId, index*)
          Set the selection to consist of those characters of *tagOrId*
          between the selection anchor point and index.  The new selection
          will include the character given by index; it will include the
          character given by the anchor point only if index is greater
          than or equal to the anchor point.  The anchor point is
          determined by the most recent *selectAdjust* or *selectFrom*
          method calls for this widget.  If the selection anchor point for
          the widget isn't currently in *tagOrId*, then it is set to the
          same character given by index.  Returns an empty string.

*$canvas*->type(*tagOrId*)
     Returns the type of the item given by *tagOrId*, such as rectangle or
     text.  If *tagOrId* refers to more than one item, then the type of
     the first item in the display list is returned.  If *tagOrId* doesn't
     refer to any items at all then an empty string is returned.

*$canvas*->*xview*(?args?)
     This method is used to query and change the horizontal position of the
     information displayed in the canvas's window.  It can take any of the
     following forms:

    *$canvas*->*xview*
          Returns a list containing two elements.  Each element is a real
          fraction between 0 and 1;  together they describe the horizontal
          span that is visible in the window.  For example, if the first
          element is .2 and the second element is .6, 20% of the canvas's
          area (as defined by the *-scrollregion* option) is off-screen to
          the left, the middle 40% is visible in the window, and 40% of
          the canvas is off-screen to the right.  These are the same
          values passed to scrollbars via the *-xscrollcommand* option.

    *$canvas*->*xviewMoveto*(*fraction*)
          Adjusts the view in the window so that *fraction* of the total
          width of the canvas is off-screen to the left.  *Fraction* must
          be a fraction between 0 and 1.

    *$canvas*->*xviewScroll*(*number, what*)
          This method shifts the view in the window left or right
          according to number and *what*.  Number must be an integer.
          What must be either *units* or *pages* or an abbreviation of one
          of these.  If *what* is *units*, the view adjusts left or right
          in units of the *xScrollIncrement* option, if it is greater than
          zero, or in units of one-tenth the window's width otherwise.  If
          *what is **pages* then the view adjusts in units of nine-tenths
          the window's width.  If number is negative then information
          farther to the left becomes visible;  if it is positive then
          information farther to the right becomes visible.

*$canvas*->*yview*(*?args*?)
     This method is used to query and change the vertical position of the
     information displayed in the canvas's window.  It can take any of the
     following forms:

    *$canvas*->*yview*
          Returns a list containing two elements.  Each element is a real
          fraction between 0 and 1;  together they describe the vertical
          span that is visible in the window.  For example, if the first
          element is .6 and the second element is 1.0, the lowest 40% of
          the canvas's area (as defined by the *-scrollregion* option) is
          visible in the window.  These are the same values passed to
          scrollbars via the *-yscrollcommand* option.

    *$canvas*->*yviewMoveto*(*fraction*)
          Adjusts the view in the window so that *fraction* of the canvas's
          area is off-screen to the top.  *Fraction* is a fraction between
          0 and 1.

    *$canvas*->*yviewScroll*(*number, what*)
          This method adjusts the view in the window up or down according
          to number and *what*.  Number must be an integer.  What must be
          either *units* or *pages*.  If *what* is *units*, the view
          adjusts up or down in units of the *yScrollIncrement* option, if
          it is greater than zero, or in units of one-tenth the window's
          height otherwise.  If *what* is *pages* then the view adjusts in
          units of nine-tenths the window's height.  If number is negative
          then higher information becomes visible;  if it is positive then
          lower information becomes visible.

OVERVIEW OF ITEM TYPES
======================

   The sections below describe the various types of items supported by
canvas widgets.  Each item type is characterized by two things: first, the
form of the create method used to create instances of the type;  and
second, a set of configuration options for items of that type, which may
be used in the create and *itemconfigure* methods.  Most items don't
support indexing or selection or the methods related to them, such as
index and insert.  Where items do support these facilities, it is noted
explicitly in the descriptions below.  At present, text, line and polygon
items provide this support.  For lines and polygons the indexing facility
is used to manipulate the coordinates of the item.

ARC ITEMS
=========

   Items of type arc appear on the display as arc-shaped regions.  An arc
is a section of an oval delimited by two angles (specified by the *-start*
and *-extent* options) and displayed in one of several ways (specified by
the *-style* option).  Arcs are created with methods of the following form:

     $canvas->createArc(x1, y1, x2, y2, ?option, value, option, value, ...?)

   The arguments x1, *y1*, x2, and *y2* give the coordinates of two
diagonally opposite corners of a rectangular region enclosing the oval
that defines the arc.  After the coordinates there may be any number of
option-value pairs, each of which sets one of the configuration options
for the item.  These same option-value pairs may be used in
*itemconfigure* methods to change the item's configuration.  The following
options are supported for arcs:

*-dash* => pattern
*-activedash* => pattern
*-disableddash* => pattern
     This option specifies dash patterns for the normal state, the active
     state, and the disabled state of an arc item.  pattern may have any
     of the forms accepted by *Tk_GetDash*.  If the dash options are
     omitted then the default is a solid outline.

*-dashoffset* => offset
     The starting offset into the pattern provided by the *-dash* option.
     *-dashoffset* is ignored if there is no *-dash* pattern.

*-extent* => *degrees*
     Specifies the size of the angular range occupied by the arc.  The
     arc's range extends for *degrees* degrees counter-clockwise from the
     starting angle given by the *-start* option.  *Degrees* may be
     negative.  If it is greater than 360 or less than -360, then *degrees*
     modulo 360 is used as the extent.

*-fill* => color
*-activefill* => color
*-disabledfill* => color
     Specifies the color to be used to fill the arc region in its normal,
     active, and disabled states, Color may have any of the forms accepted
     by *Tk_GetColor*.  If color is an empty string (the default), then
     then the arc will not be filled.

*-outline* => color
*-activeoutline* => color
*-disabledoutline* => color
     This option specifies the color that should be used to draw the
     outline of the arc in its normal, active and disabled states.  Color
     may have any of the forms accepted by *Tk_GetColor*.  This option
     defaults to *black*.  If color is specified as undef then no outline
     is drawn for the arc.

*-outlinestipple* => bitmap
*-activeoutlinestipple* => bitmap
*-disabledoutlinestipple* => bitmap
     This option specifies stipple patterns that should be used to draw the
     outline of the arc in its normal, active and disabled states.
     Indicates that the outline for the arc should be drawn with a stipple
     pattern; bitmap specifies the stipple pattern to use, in any of the
     forms accepted by *Tk_GetBitmap*.  If the *-outline* option hasn't
     been specified then this option has no effect.  If bitmap is an empty
     string (the default), then the outline is drawn in a solid fashion.

*-start* => *degrees*
     Specifies the beginning of the angular range occupied by the arc.
     *Degrees* is given in units of degrees measured counter-clockwise
     from the 3-o'clock position;  it may be either positive or negative.

*-state* => state
     Modifies the state of the arc item where state may be set to one of:
     normal, disabled, hidden or "". If set to empty, the state of the
     canvas itself is used. An arc item may also be in the "active" state
     if the mouse is currently over it.  Many options can take separate
     specifications in normal, active and disabled states such that the
     appearance of the item can be different in each state.

*-stipple* => bitmap
*-activestipple* => bitmap
*-disabledstipple* => bitmap
     This option specifies stipple patterns that should be used to fill the
     the arc in its normal, active and disabled states.  bitmap specifies
     the stipple pattern to use, in any of the forms accepted by
     *Tk_GetBitmap*.  If the *-fill* option hasn't been specified then
     this option has no effect.  If bitmap is an empty string (the
     default), then filling is done in a solid fashion.

*-style* => type
     Specifies how to draw the arc.  If type is *pieslice* (the default)
     then the arc's region is defined by a section of the oval's perimeter
     plus two line segments, one between the center of the oval and each
     end of the perimeter section.  If type is *chord* then the arc's
     region is defined by a section of the oval's perimeter plus a single
     line segment connecting the two end points of the perimeter section.
     If type is arc then the arc's region consists of a section of the
     perimeter alone.  In this last case the *-fill* option is ignored.

*-tags* => *tagList*
     Specifies a set of tags to apply to the item.  *TagList* consists of
     a list of tag names, which replace any existing tags for the item.
     *TagList* may be an empty list.

*-updatecommand* => command
     Specifies a callback that is to be executed every time the arc item
     is updated on the screen.

*-width* => *outlineWidth*
*-activewidth* => *outlineWidth*
*-disabledwidth* => *outlineWidth*
     Specifies the width of the outline to be drawn around the arc's
     region, in its normal, active and disabled states.  *outlineWidth*
     may be in any of the forms described in the `"COORDINATES"' in this
     node section above.  If the *-outline* option has been specified as
     undef then this option has no effect.  Wide outlines will be drawn
     centered on the edges of the arc's region.  This option defaults to
     1.0.

BITMAP ITEMS
============

   Items of type bitmap appear on the display as images with two colors,
foreground and background.  Bitmaps are created with methods of the
following form:

     $canvas->createBitmap(x, y, ?option, value, option, value, ...?)

   The arguments x and y specify the coordinates of a point used to
position the bitmap on the display (see the *-anchor* option below for
more information on how bitmaps are displayed).  After the coordinates
there may be any number of option-value pairs, each of which sets one of
the configuration options for the item.  These same option-value pairs may
be used in *itemconfigure* methods to change the item's configuration.
The following options are supported for bitmaps:

*-anchor* => *anchorPos*
     *AnchorPos* tells how to position the bitmap relative to the
     positioning point for the item;  it may have any of the forms
     accepted by *Tk_GetAnchor*.  For example, if *anchorPos* is center
     then the bitmap is centered on the point;  if *anchorPos* is n then
     the bitmap will be drawn so that its top center point is at the
     positioning point.  This option defaults to center.

*-background* => color
*-activebackground* => color
*-disabledbackground* => color
     Specifies the color to use for each of the bitmap's '0' valued pixels
     in its normal, active and disabled states.  Color may have any of the
     forms accepted by *Tk_GetColor*.  If this option isn't specified, or
     if it is specified as undef, then nothing is displayed where the
     bitmap pixels are 0;  this produces a transparent effect.

*-bitmap* => bitmap
*-activebitmap* => bitmap
*-disabledbitmap* => bitmap
     Specifies the bitmaps to display in the item in its normal, active and
     disabled states.  Bitmap may have any of the forms accepted by
     *Tk_GetBitmap*.

*-foreground* => color
*-activeforeground* => bitmap
*-disabledforeground* => bitmap
     Specifies the color to use for each of the bitmap's '1' valued pixels
     in its normal, active and disabled states.  Color may have any of the
     forms accepted by *Tk_GetColor* and defaults to *black*.

*-state* => state
     Modifies the state of the bitmap item where state may be set to one
     of: normal, disabled, or hidden.  An bitmap item may also be in the
     "active" state if the mouse is currently over it.  Many options can
     take separate specifications in normal, active and disabled states
     such that the appearance of the item can be different in each state.

*-tags* => *tagList*
     Specifies a set of tags to apply to the item.  *TagList* consists of
     a list of tag names, which replace any existing tags for the item.
     *TagList* may be an empty list.

*-updatecommand* => command
     Specifies a callback that is to be executed every time the bitmap
     item is updated on the screen.

GRID ITEMS
==========

   Items of type grid are intended for producing a visual reference for
interpreting other items. They can be drawn as either lines (with dash
style) or as rectangular "dots" at each grid point.

   Items of type grid are unlike other items they always cover the whole
of the canvas, but are never enclosed by nor overlap any area and are not
near any point. That is they are intended to be always visible but not
"pickable", as such they do support the "active" state.  They are like
other items in that: multiple grids are permitted, they can be raised and
lowered relative to other items, they can be moved and scaled. As yet
grids do not apear in PostScript output.

   Grids have outline like configure options. Grids are created with
methods of the following form:

     $canvas->createGrid(x1, y1, x2, y2, ?option, value, option, value, ...?)

   The arguments x1, *y1* give the origin of the grid. x2, and *y2* give
the coordinates of the next grid point in their respective directions.
After the coordinates there may be any number of option-value pairs, each
of which sets one of the configuration options for the item.  These same
option-value pairs may be used in *itemconfigure* methods to change the
item's configuration.  The following options are supported for grids:

*-lines* => boolean
     If *-lines* is set to a true value then lines are drawn for both X
     and Y grids in the style determined by *-dash*. Otherwise retangular
     "dots" are drawn at each grid point.

*-dash* => pattern
*-disableddash* => pattern
     This option specifies dash patterns for the normal state, and the
     disabled state of a grid item.  pattern may have any of the forms
     accepted by *Tk_GetDash*.  If the dash options are omitted then the
     default is a solid outline.

*-dashoffset* => offset
     The starting offset into the pattern provided by the *-dash* option.
     *-dashoffset* is ignored if there is no *-dash* pattern.

*-color* => color
*-disabledcolor* => color
     This option specifies the color that should be used to draw the
     outline of the grid in its normal and disabled states.  Color may
     have any of the forms accepted by *Tk_GetColor*.  This option
     defaults to *black*.  If color is undef then no grid will be drawn.

*-stipple* => bitmap
*-disabledstipple* => bitmap
     This option specifies stipple patterns that should be used to draw the
     outline of the rectangle in its normal and disabled states.  bitmap
     specifies the stipple pattern to use, in any of the forms accepted by
     *Tk_GetBitmap*.  If bitmap is an empty string (the default), then the
     outline is drawn in a solid fashion.

*-state* => state
     Modifies the state of the rectangle item where state may be set to
     one of: normal, disabled, or hidden. Many options can take separate
     specifications in normal and disabled states such that the appearance
     of the item can be different in each state.

*-tags* => *tagList*
     Specifies a set of tags to apply to the item.  *TagList* consists of
     a list of tag names, which replace any existing tags for the item.
     *TagList* may be an empty list.

*-updatecommand* => command
     Specifies a callback that is to be executed every time the grid item
     is updated on the screen.

*-width* => *outlineWidth*
*-disabledwidth* => *outlineWidth*
     Specifies the width of the lines drawn by the grid or the size (in
     both X and Y) of the dots, in its normal and disabled states.  This
     option defaults to 1.0.

IMAGE ITEMS
===========

   Items of type image are used to display images on a canvas.  Images are
created with methods of the following form:

     $canvas->createImage(x, y, ?option, value, option, value, ...?)

   The arguments x and y specify the coordinates of a point used to
position the image on the display (see the *-anchor* option below for more
information).  After the coordinates there may be any number of
option-value pairs, each of which sets one of the configuration options
for the item.  These same option-value pairs may be used in
*itemconfigure* methods to change the item's configuration.  The following
options are supported for images:

*-anchor* => *anchorPos*
     *AnchorPos* tells how to position the image relative to the
     positioning point for the item;  it may have any of the forms
     accepted by *Tk_GetAnchor*.  For example, if *anchorPos* is center
     then the image is centered on the point;  if *anchorPos* is n then
     the image will be drawn so that its top center point is at the
     positioning point.  This option defaults to center.

*-image* => name
*-activeimage* => name
*-disabledimage* => name
     Specifies the name of the images to display in the item in is normal,
     active and disabled states.  This image must have been created
     previously with the *imageCreate* method.

*-state* => state
     Modifies the state of the image item where state may be set to one of:
     normal, disabled, or hidden.  An image item may also be in the
     "active" state if the mouse is currently over it.  Many options can
     take separate specifications in normal, active and disabled states
     such that the appearance of the item can be different in each state.

*-tags* => *tagList*
     Specifies a set of tags to apply to the item.  *TagList* consists of
     a list of tag names, which replace any existing tags for the item;
     it may be an empty list.

*-updatecommand* => command
     Specifies a callback that is to be executed every time the image item
     is updated on the screen.

LINE ITEMS
==========

   Items of type line appear on the display as one or more connected line
segments or curves.  Line items support coordinate indexing operations
using the canvas methods: *dchars, index, insert.* Lines are created with
methods of the following form:

     $canvas->createLine(x1, y1..., xn, yn, ?option, value, option, value, ...?)

   The arguments x1 through *yn* give the coordinates for a series of two
or more points that describe a series of connected line segments.  After
the coordinates there may be any number of option-value pairs, each of
which sets one of the configuration options for the item.  These same
option-value pairs may be used in *itemconfigure* methods to change the
item's configuration.  The following options are supported for lines:

*-arrow* => where
     Indicates whether or not arrowheads are to be drawn at one or both
     ends of the line.  Where must have one of the values none (for no
     arrowheads), first (for an arrowhead at the first point of the line),
     last (for an arrowhead at the last point of the line), or both (for
     arrowheads at both ends).  This option defaults to none.

*-arrowshape* => shape
     This option indicates how to draw arrowheads.  The shape argument
     must be a list with three elements, each specifying a distance in any
     of the forms described in the `"COORDINATES"' in this node section
     above.  The first element of the list gives the distance along the
     line from the neck of the arrowhead to its tip.  The second element
     gives the distance along the line from the trailing points of the
     arrowhead to the tip, and the third element gives the distance from
     the outside edge of the line to the trailing points.  If this option
     isn't specified then Tk picks a "reasonable" shape.

*-capstyle* => style
     Specifies the ways in which caps are to be drawn at the endpoints of
     the line.  Style may have any of the forms accepted by
     *Tk_GetCapStyle* (*butt*, *projecting*, or round).  If this option
     isn't specified then it defaults to *butt*.  Where arrowheads are
     drawn the cap style is ignored.

*-dash* => pattern
*-activedash* => pattern
*-disableddash* => pattern
     This option specifies dash patterns for the normal state, the active
     state, and the disabled state of a line item.  pattern may have any
     of the forms accepted by *Tk_GetDash*.  If the dash options are
     omitted then the default is a solid outline.

*-dashoffset* => offset
     The starting offset into the pattern provided by the *-dash* option.
     *-dashoffset* is ignored if there is no *-dash* pattern.

*-fill* => color
*-activefill* => color
*-disabledfill* => color
     Specifies the color to be used to fill the line in its normal,
     active, and disabled states.  Color may have any of the forms
     acceptable to *Tk_GetColor*.  It may also be undef, in which case the
     line will be transparent.  This option defaults to *black*.

*-joinstyle* => style
     Specifies the ways in which joints are to be drawn at the vertices of
     the line.  Style may have any of the forms accepted by
     *Tk_GetCapStyle* (*bevel*, *miter*, or round).  If this option isn't
     specified then it defaults to *miter*.  If the line only contains two
     points then this option is irrelevant.

*-smooth* => boolean
     Boolean must have one of the forms accepted by *Tk_GetBoolean*.  It
     indicates whether or not the line should be drawn as a curve.  If so,
     the line is rendered as a set of parabolic splines: one spline is
     drawn for the first and second line segments, one for the second and
     third, and so on.  Straight-line segments can be generated within a
     curve by duplicating the end-points of the desired line segment.

*-splinesteps* => number
     Specifies the degree of smoothness desired for curves:  each spline
     will be approximated with number line segments.  This option is
     ignored unless the *-smooth* option is true.

*-state* => state
     Modifies the state of the line item where state may be set to one of:
     normal, disabled, or hidden.  A line item may also be in the "active"
     state if the mouse is currently over it.  Many options can take
     separate specifications in normal, active and disabled states such
     that the appearance of the item can be different in each state.

*-stipple* => bitmap
*-activestipple* => bitmap
*-disabledstipple* => bitmap
     This option specifies stipple patterns that should be used to fill the
     the line in its normal, active and disabled states.  bitmap specifies
     the stipple pattern to use, in any of the forms accepted by
     *Tk_GetBitmap*.  If bitmap is an empty string (the default), then
     filling is done in a solid fashion.

*-tags* => *tagList*
     Specifies a set of tags to apply to the item.  *TagList* consists of
     a list of tag names, which replace any existing tags for the item.
     *TagList* may be an empty list.

*-updatecommand* => command
     Specifies a callback that is to be executed every time the line item
     is updated on the screen.

*-width* => *lineWidth*
*-activewidth* => *lineWidth*
*-disabledwidth* => *lineWidth*
     Specifies the width of the line in its normal, active and disabled
     states.  *lineWidth* may be in any of the forms described in the
     `"COORDINATES"' in this node section above.

     Wide lines will be drawn centered on the path specified by the points.
     If this option isn't specified then it defaults to 1.0.

OVAL ITEMS
==========

   Items of type *oval* appear as circular or oval regions on the display.
Each oval may have an outline, a fill, or both.  Ovals are created with
methods of the following form:

     $canvas->createOval(x1, y1, x2, y2, ?option, value, option, value, ...?)

   The arguments x1, *y1*, x2, and *y2* give the coordinates of two
diagonally opposite corners of a rectangular region enclosing the oval.
The oval will include the top and left edges of the rectangle not the
lower or right edges.  If the region is square then the resulting oval is
circular; otherwise it is elongated in shape.  After the coordinates there
may be any number of option-value pairs, each of which sets one of the
configuration options for the item.  These same option-value pairs may be
used in *itemconfigure* methods to change the item's configuration.  The
following options are supported for ovals:

*-dash* => pattern
*-activedash* => pattern
*-disableddash* => pattern
     This option specifies dash patterns for the normal state, the active
     state, and the disabled state of an oval item.  pattern may have any
     of the forms accepted by *Tk_GetDash*.  If the dash options are
     omitted then the default is a solid outline.

*-dashoffset* => offset
     The starting offset into the pattern provided by the *-dash* option.
     *-dashoffset* is ignored if there is no *-dash* pattern.

*-fill* => color
*-activefill* => color
*-disabledfill* => color
     Specifies the color to be used to fill the oval in its normal,
     active, and disabled states.  Color may have any of the forms
     accepted by *Tk_GetColor*.  If color is undef (the default), then
     then the oval will not be filled.

*-outline* => color
*-activeoutline* => color
*-disabledoutline* => color
     This option specifies the color that should be used to draw the
     outline of the oval in its normal, active and disabled states.  Color
     may have any of the forms accepted by *Tk_GetColor*.  This option
     defaults to *black*.  If color is undef then no outline will be drawn
     for the oval.

*-outlinestipple* => bitmap
*-activeoutlinestipple* => bitmap
*-disabledoutlinestipple* => bitmap
     This option specifies stipple patterns that should be used to draw the
     outline of the oval in its normal, active and disabled states.
     bitmap specifies the stipple pattern to use, in any of the forms
     accepted by *Tk_GetBitmap*.  If the *-outline* option hasn't been
     specified then this option has no effect.  If bitmap is an empty
     string (the default), then the outline is drawn in a solid fashion.

*-state* => state
     Modifies the state of the oval item where state may be set to one of:
     normal, disabled, or hidden.  An oval item may also be in the "active"
     state if the mouse is currently over it.  Many options can take
     separate specifications in normal, active and disabled states such
     that the appearance of the item can be different in each state.

*-stipple* => bitmap
*-activestipple* => bitmap
*-disabledstipple* => bitmap
     This option specifies stipple patterns that should be used to fill the
     the oval in its normal, active and disabled states.  bitmap specifies
     the stipple pattern to use, in any of the forms accepted by
     *Tk_GetBitmap*.  If the *-fill* option hasn't been specified then
     this option has no effect.  If bitmap is an empty string (the
     default), then filling is done in a solid fashion.

*-tags* => *tagList*
     Specifies a set of tags to apply to the item.  *TagList* consists of
     a list of tag names, which replace any existing tags for the item.
     *TagList* may be an empty list.

*-updatecommand* => command
     Specifies a callback that is to be executed every time the oval item
     is updated on the screen.

*-width* => *outlineWidth*
*-activewidth* => *outlineWidth*
*-disabledwidth* => *outlineWidth*
     Specifies the width of the outline to be drawn around the oval, in
     its normal, active and disabled states.  *outlineWidth* specifies the
     width of the outline to be drawn around the oval, in any of the forms
     described in the `"COORDINATES"' in this node section above.

     If the *-outline* option hasn't been specified then this option has
     no effect.  Wide outlines are drawn centered on the oval path defined
     by x1, *y1*, x2, and *y2*.  This option defaults to 1.0.

POLYGON ITEMS
=============

   Items of type *polygon* appear as polygonal or curved filled regions on
the display.  Polygon items support coordinate indexing operations using
the canvas methods: *dchars, index, insert.* Polygons are created with
methods of the following form:

     $canvas->createPolygon(x1, y1, ..., xn, yn, ?option, value, option, value, ...?)

   The arguments x1 through *yn* specify the coordinates for three or more
points that define a closed polygon.  The first and last points may be the
same;  whether they are or not, Tk will draw the polygon as a closed
polygon.  After the coordinates there may be any number of option-value
pairs, each of which sets one of the configuration options for the item.
These same option-value pairs may be used in *itemconfigure* methods to
change the item's configuration.  The following options are supported for
polygons:

*-dash* => pattern
*-activedash* => pattern
*-disableddash* => pattern
     This option specifies dash patterns for the normal state, the active
     state, and the disabled state of an polygon item.  pattern may have
     any of the forms accepted by *Tk_GetDash*.  If the dash options are
     omitted then the default is a solid outline.

*-dashoffset* => offset
     The starting offset into the pattern provided by the *-dash* option.
     *-dashoffset* is ignored if there is no *-dash* pattern.

*-fill* => color
*-activefill* => color
*-disabledfill* => color
     Specifies the color to be used to fill the polygon in its normal,
     active, and disabled states.  Color may have any of the forms
     acceptable to *Tk_GetColor*.  If color is undef then the polygon will
     be transparent.  This option defaults to *black*.

*-joinstyle* => style
     Specifies the ways in which joints are to be drawn at the vertices of
     the outline.  Style may have any of the forms accepted by
     *Tk_GetCapStyle* (*bevel*, *miter*, or round).  If this option isn't
     specified then it defaults to *miter*.

*-outline* => color
*-activeoutline* => color
*-disabledoutline* => color
     This option specifies the color that should be used to draw the
     outline of the polygon in its normal, active and disabled states.
     Color may have any of the forms accepted by *Tk_GetColor*.  If color
     is undef then no outline will be drawn for the polygon.  This option
     defaults to undef (no outline).

*-outlinestipple* => bitmap
*-activeoutlinestipple* => bitmap
*-disabledoutlinestipple* => bitmap
     This option specifies stipple patterns that should be used to draw the
     outline of the polygon in its normal, active and disabled states.
     bitmap specifies the stipple pattern to use, in any of the forms
     accepted by *Tk_GetBitmap*.  If the *-outline* option hasn't been
     specified then this option has no effect.  If bitmap is an empty
     string (the default), then the outline is drawn in a solid fashion.

*-smooth* => boolean
     Boolean must have one of the forms accepted by *Tk_GetBoolean* It
     indicates whether or not the polygon should be drawn with a curved
     perimeter.  If so, the outline of the polygon becomes a set of
     parabolic splines, one spline for the first and second line segments,
     one for the second and third, and so on.  Straight-line segments can
     be generated in a smoothed polygon by duplicating the end-points of
     the desired line segment.

*-splinesteps* => number
     Specifies the degree of smoothness desired for curves:  each spline
     will be approximated with number line segments.  This option is
     ignored unless the *-smooth* option is true.

*-state* => state
     Modifies the state of the polygon item where state may be set to one
     of: normal, disabled, or hidden.  A polygon item may also be in the
     "active" state if the mouse is currently over it.  Many options can
     take separate specifications in normal, active and disabled states
     such that the appearance of the item can be different in each state.

*-stipple* => bitmap
*-activestipple* => bitmap
*-disabledstipple* => bitmap
     This option specifies stipple patterns that should be used to fill the
     the polygon in its normal, active and disabled states.  bitmap
     specifies the stipple pattern to use, in any of the forms accepted by
     *Tk_GetBitmap*.  If bitmap is an empty string (the default), then
     filling is done in a solid fashion.

*-tags* => *tagList*
     Specifies a set of tags to apply to the item.  *TagList* consists of
     a list of tag names, which replace any existing tags for the item.
     *TagList* may be an empty list.

*-updatecommand* => command
     Specifies a callback that is to be executed every time the polygon
     item is updated on the screen.

*-width* => *outlineWidth*
*-activewidth* => *outlineWidth*
*-disabledwidth* => *outlineWidth*
Specifies the width of the outline to be drawn around
     the polygon, in its normal, active and disabled states.
     *outlineWidth* may be in any of the forms described in the COORDINATES
     section above.  *OutlineWidth* specifies the width of the outline to
     be drawn around the polygon, in any of the forms described in the
     `"COORDINATES"' in this node section above.  If the *-outline* option
     hasn't been specified then this option has no effect.  This option
     defaults to 1.0.

     Polygon items are different from other items such as rectangles, ovals
     and arcs in that interior points are considered to be "inside" a
     polygon (e.g. for purposes of the *find closest* and *find
     overlapping* methods) even if it is not filled.  For most other item
     types, an interior point is considered to be inside the item only if
     the item is filled or if it has neither a fill nor an outline.  If
     you would like an unfilled polygon whose interior points are not
     considered to be inside the polygon, use a line item instead.

RECTANGLE ITEMS
===============

   Items of type rectangle appear as rectangular regions on the display.
Each rectangle may have an outline, a fill, or both.  Rectangles are
created with methods of the following form:

     $canvas->createRectangle(x1, y1, x2, y2, ?option, value, option, value, ...?)

   The arguments x1, *y1*, x2, and *y2* give the coordinates of two
diagonally opposite corners of the rectangle (the rectangle will include
its upper and left edges but not its lower or right edges).  After the
coordinates there may be any number of option-value pairs, each of which
sets one of the configuration options for the item.  These same
option-value pairs may be used in *itemconfigure* methods to change the
item's configuration.  The following options are supported for rectangles:

*-dash* => pattern
*-activedash* => pattern
*-disableddash* => pattern
     This option specifies dash patterns for the normal state, the active
     state, and the disabled state of a rectangle item.  pattern may have
     any of the forms accepted by *Tk_GetDash*.  If the dash options are
     omitted then the default is a solid outline.

*-dashoffset* => offset
     The starting offset into the pattern provided by the *-dash* option.
     *-dashoffset* is ignored if there is no *-dash* pattern.

*-fill* => color
*-activefill* => color
*-disabledfill* => color
     Specifies the color to be used to fill the rectangle in its normal,
     active, and disabled states.  Color may be specified in any of the
     forms accepted by *Tk_GetColor*.  If color is undef (the default),
     then the rectangle will not be filled.

*-outline* => color
*-activeoutline* => color
*-disabledoutline* => color
     This option specifies the color that should be used to draw the
     outline of the rectangle in its normal, active and disabled states.
     Color may have any of the forms accepted by *Tk_GetColor*.  This
     option defaults to *black*.  If color is undef then no outline will be
     drawn for the rectangle.

*-outlinestipple* => bitmap
*-activeoutlinestipple* => bitmap
*-disabledoutlinestipple* => bitmap
     This option specifies stipple patterns that should be used to draw the
     outline of the rectangle in its normal, active and disabled states.
     bitmap specifies the stipple pattern to use, in any of the forms
     accepted by *Tk_GetBitmap*.  If the *-outline* option hasn't been
     specified then this option has no effect.  If bitmap is an empty
     string (the default), then the outline is drawn in a solid fashion.

*-state* => state
     Modifies the state of the rectangle item where state may be set to
     one of: normal, disabled, or hidden.  A rectangle item may also be in
     the "active" state if the mouse is currently over it.  Many options
     can take separate specifications in normal, active and disabled
     states such that the appearance of the item can be different in each
     state.

*-stipple* => bitmap
*-activestipple* => bitmap
*-disabledstipple* => bitmap
     This option specifies stipple patterns that should be used to fill the
     the rectangle in its normal, active and disabled states.  bitmap
     specifies the stipple pattern to use, in any of the forms accepted by
     *Tk_GetBitmap*.  If the *-fill* option hasn't been specified then
     this option has no effect.  If bitmap is an empty string (the
     default), then filling is done in a solid fashion.

*-tags* => *tagList*
     Specifies a set of tags to apply to the item.  *TagList* consists of
     a list of tag names, which replace any existing tags for the item.
     *TagList* may be an empty list.

*-updatecommand* => command
     Specifies a callback that is to be executed every time the rectangle
     item is updated on the screen.

*-width* => *outlineWidth*
*-activewidth* => *outlineWidth*
*-disabledwidth* => *outlineWidth*
     Specifies the width of the outline to be drawn around the rectangle,
     in its normal, active and disabled states.  *OutlineWidth* specifies
     the width of the outline to be drawn around the rectangle, in any of
     the forms described in the `"COORDINATES"' in this node section above.

     If the *-outline* option hasn't been specified then this option has
     no effect.  Wide outlines are drawn centered on the rectangular path
     defined by x1, *y1*, x2, and *y2*.  This option defaults to 1.0.

TEXT ITEMS
==========

   A text item displays a string of characters on the screen in one or
more lines.  Text items support indexing and selection, along with the
following text-related canvas methods:  *dchars*, focus, *icursor*, index,
insert, select.  Text items are created with methods of the following form:

     $canvas->createText(x, y, ?option, value, option, value, ...?)

   The arguments x and y specify the coordinates of a point used to
position the text on the display (see the options below for more
information on how text is displayed).  After the coordinates there may be
any number of option-value pairs, each of which sets one of the
configuration options for the item.  These same option-value pairs may be
used in *itemconfigure* methods to change the item's configuration.  The
following options are supported for text items:

*-anchor* => *anchorPos*
     *AnchorPos* tells how to position the text relative to the
     positioning point for the text;  it may have any of the forms
     accepted by *Tk_GetAnchor*.  For example, if *anchorPos* is center
     then the text is centered on the point;  if *anchorPos* is n then the
     text will be drawn such that the top center point of the rectangular
     region occupied by the text will be at the positioning point.  This
     option defaults to center.

*-fill* => color
*-activefill* => color
*-disabledfill* => color
     Specifies the color to be used to fill the text in its normal,
     active, and disabled states.  Color may have any of the forms
     accepted by *Tk_GetColor*.  If color is undef then the text will be
     transparent.  If this option isn't specified then it defaults to
     *black*.

*-font* => *fontName*
     Specifies the font to use for the text item.  FontName may be any
     string acceptable to *Tk_GetFontStruct*.  If this option isn't
     specified, it defaults to a system-dependent font.

-justify => how
     Specifies how to justify the text within its bounding region.  How
     must be one of the values left, right, or center.  This option will
     only matter if the text is displayed as multiple lines.  If the
     option is omitted, it defaults to left.

*-state* => state
     Modifies the state of the text item where state may be set to one of:
     normal, disabled, or hidden.  A text item may also be in the "active"
     state if the mouse is currently over it.  Many options can take
     separate specifications in normal, active and disabled states such
     that the appearance of the item can be different in each state.

*-stipple* => bitmap
*-activestipple* => bitmap
*-disabledstipple* => bitmap
     This option specifies stipple patterns that should be used to fill the
     the text in its normal, active and disabled states.  bitmap specifies
     the stipple pattern to use, in any of the forms accepted by
     *Tk_GetBitmap*.  If bitmap is an empty string (the default) then the
     text is drawn in a solid fashion.

*-tags* => *tagList*
     Specifies a set of tags to apply to the item.  *TagList* consists of
     a list of tag names, which replace any existing tags for the item.
     *TagList* may be an empty list.

*-text* => string
     String specifies the characters to be displayed in the text item.
     Newline characters cause line breaks.  The characters in the item may
     also be changed with the insert and delete methods.  This option
     defaults to an empty string.

*-updatecommand* => command
     Specifies a callback that is to be executed every time the text item
     is updated on the screen.

*-width* => *lineLength*
     Specifies a maximum line length for the text, in any of the forms
     described in the `"COORDINATES"' in this node section above.  If this
     option is zero (the default) the text is broken into lines only at
     newline characters.  However, if this option is non-zero then any
     line that would be longer than *lineLength* is broken just before a
     space character to make the line shorter than *lineLength*;  the
     space character is treated as if it were a newline character.

WINDOW ITEMS
============

   Items of type window cause a particular window to be displayed at a
given position on the canvas.  Window items are created with methods of
the following form:

       *$canvas*->*createWindow*(*x, y*?, *-option*=>value,
*-option*=>value, ...?)

   The arguments x and y specify the coordinates of a point used to
position the window on the display (see the *-anchor* option below for
more information on how bitmaps are displayed).  After the coordinates
there may be any number of *option-value* pairs, each of which sets one of
the configuration options for the item.  These same option-value pairs may
be used in *itemconfigure* method to change the item's configuration.  The
following options are supported for window items:

*-anchor* => *anchorPos*
     *AnchorPos* tells how to position the window relative to the
     positioning point for the item;  it may have any of the forms
     accepted by *Tk_GetAnchor*.  For example, if *anchorPos* is center
     then the window is centered on the point;  if *anchorPos* is n then
     the window will be drawn so that its top center point is at the
     positioning point.  This option defaults to center.

*-height* => *pixels*
     Specifies the height to assign to the item's window.  *Pixels* may
     have any of the forms described in the `"COORDINATES"' in this node
     section above.  If this option isn't specified, or if it is specified
     as an empty string, then the window is given whatever height it
     requests internally.

*-state* => state
     Modifies the state of the window item where state may be set to one
     of: normal, disabled, or hidden.

*-tags* => *tagList*
     Specifies a set of tags to apply to the item.  *TagList* consists of
     a list of tag names, which replace any existing tags for the item.
     *TagList* may be an empty list.

*-updatecommand* => command
     Specifies a callback that is to be executed every time the window
     item is updated on the screen.

*-width* => *pixels*
     Specifies the width to assign to the item's window.  *Pixels* may
     have any of the forms described in the `"COORDINATES"' in this node
     section above.  If this option isn't specified, or if it is specified
     as an empty string, then the window is given whatever width it
     requests internally.

*-window* => $widget
     Specifies the window to associate with this item.  The window
     specified by $widget must either be a child of the canvas widget or a
     child of some ancestor of the canvas widget.  *PathName* may not
     refer to a top-level window.

     Note:  due to restrictions in the ways that windows are managed, it
     is not possible to draw other graphical items (such as lines and
     images) on top of window items.  A window item always obscures any
     graphics that overlap it, regardless of their order in the display
     list.

APPLICATION-DEFINED ITEM TYPES
==============================

   It is possible for individual applications to define new item types for
canvas widgets using C code.  See the documentation for
*Tk_CreateItemType*.

BINDINGS
========

   Canvas has default bindings to allow scrolling if necessary: <Up>,
<Down>, <Left> and <Right> (and their <Control-*> counter parts).  Further
<Proir>, <Next>, <Home> and <End>.  These bindings allow you to navigate
the same way as in other widgets that can scroll.

CREDITS
=======

   Tk's canvas widget is a blatant ripoff of ideas from Joel Bartlett's
*ezd* program.  *Ezd* provides structured graphics in a Scheme environment
and preceded canvases by a year or two.  Its simple mechanisms for placing
and animating graphical objects inspired the functions of canvases.

KEYWORDS
========

   canvas, widget

Another radio button style widget (with a check mark)
*****************************************************

NAME
====

   Tk::CheckBox - Another radio button style widget (with a check mark)

SYNOPSIS
========

     use Tk;

     my $MainWindow = MainWindow->new();

     Tk::MainLoop;

DESCRIPTION
===========

   A radio button style widget that uses a check mark in a box.  Useful as
a boolean field.

AUTHORS
=======

   Damion K. Wilson, dkw@rcm.bm

HISTORY    =cut
===============

Create and manipulate Checkbutton widgets
*****************************************

NAME
====

   Tk::Checkbutton - Create and manipulate Checkbutton widgets

   *$checkbutton* = *$parent*->Checkbutton(?options?);

STANDARD OPTIONS
================

*-activebackground*	*-cursor*	*-highlightthickness*	*-takefocus*
*-activeforeground*	*-disabledforeground*	*-image*	*-text*
*-anchor*	*-font*	-justify	*-textvariable*
*-background*	*-foreground*	*-padx*	*-underline*
*-bitmap*	*-highlightbackground*	*-pady*	*-wraplength*
*-borderwidth*	*-highlightcolor*	*-relief*

   See Tk/options, for details of the standard options.

WIDGET-SPECIFIC OPTIONS
=======================

Name:	command
Class:	Command
Switch:	*-command*
     Specifies a `Tk callback|Tk::callbacks', see Perl (perl.info),
     to associate with the button.  This command is typically invoked when
     mouse button 1 is released over the button window.  The button's
     global variable (*-variable* option) will be updated before the
     command is invoked.

Name:	height
Class:	*Height*
Switch:	*-height*
     Specifies a desired height for the button.  If an image or bitmap is
     being displayed in the button then the value is in screen units (i.e.
     any of the forms acceptable to *Tk_GetPixels*); for text it is in
     lines of text.  If this option isn't specified, the button's desired
     height is computed from the size of the image or bitmap or text being
     displayed in it.

Name:	*indicatorOn*
Class:	*IndicatorOn*
Switch:	*-indicatoron*
     Specifies whether or not the indicator should be drawn.  Must be a
     proper boolean value.  If false, the *relief* option is ignored and
     the widget's relief is always sunken if the widget is selected and
     raised otherwise.

Name:	*offValue*
Class:	Value
Switch:	*-offvalue*
     Specifies value to store in the button's associated variable whenever
     this button is deselected.  Defaults to "0".

Name:	*onValue*
Class:	Value
Switch:	*-onvalue*
     Specifies value to store in the button's associated variable whenever
     this button is selected.  Defaults to "1".

Name:	*selectColor*
Class:	Background
Switch:	*-selectcolor*
     Specifies a background color to use when the button is selected.  If
     *indicatorOn* is true then the color applies to the indicator.  Under
     Windows, this color is used as the background for the indicator
     regardless of the select state.  If *indicatorOn* is false, this
     color is used as the background for the entire widget, in place of
     background or *activeBackground*, whenever the widget is selected.
     If specified as an empty string then no special color is used for
     displaying when the widget is selected.

Name:	*selectImage*
Class:	*SelectImage*
Switch:	*-selectimage*
     Specifies an image to display (in place of the image option) when the
     checkbutton is selected.  This option is ignored unless the image
     option has been specified.

Name:	state
Class:	State
Switch:	*-state*
     Specifies one of three states for the checkbutton:  normal, active,
     or disabled.  In normal state the checkbutton is displayed using the
     *foreground* and background options.  The active state is typically
     used when the pointer is over the checkbutton.  In active state the
     checkbutton is displayed using the *activeForeground* and
     *activeBackground* options.  Disabled state means that the checkbutton
     should be insensitive:  the default bindings will refuse to activate
     the widget and will ignore mouse button presses.  In this state the
     *disabledForeground* and background options determine how the
     checkbutton is displayed.

Name:	variable
Class:	Variable
Switch:	*-variable*
     Specifies reference to a variable to set to indicate whether or not
     this button is selected.  Defaults to `\$widget->{'Value'}' member of
     the widget's hash. In general perl variables are undef unless
     specifically initialized which will not match either default
     *-onvalue* or default *-offvalue*.

Name:	width
Class:	Width
Switch:	*-width*
     Specifies a desired width for the button.  If an image or bitmap is
     being displayed in the button then the value is in screen units (i.e.
     any of the forms acceptable to *Tk_GetPixels*); for text it is in
     characters.  If this option isn't specified, the button's desired
     width is computed from the size of the image or bitmap or text being
     displayed in it.

DESCRIPTION
===========

   The Checkbutton method creates a new window (given by the $widget
argument) and makes it into a checkbutton widget.  Additional options,
described above, may be specified on the command line or in the option
database to configure aspects of the checkbutton such as its colors, font,
text, and initial relief.  The *checkbutton* command returns its $widget
argument.  At the time this command is invoked, there must not exist a
window named $widget, but $widget's parent must exist.

   A checkbutton is a widget that displays a textual string, bitmap or
image and a square called an *indicator*.  If text is displayed, it must
all be in a single font, but it can occupy multiple lines on the screen
(if it contains newlines or if wrapping occurs because of the *wrapLength*
option) and one of the characters may optionally be underlined using the
underline option.  A checkbutton has all of the behavior of a simple
button, including the following: it can display itself in either of three
different ways, according to the state option; it can be made to appear
raised, sunken, or flat; it can be made to flash; and it invokes a `Tk
callback|Tk::callbacks', see Perl (perl.info), whenever mouse
button 1 is clicked over the checkbutton.

   In addition, checkbuttons can be *selected*.  If a checkbutton is
selected then the indicator is normally drawn with a selected appearance,
and a Tcl variable associated with the checkbutton is set to a particular
value (normally 1).  Under Unix, the indicator is drawn with a sunken
relief and a special color.  Under Windows, the indicator is drawn with a
check mark inside.  If the checkbutton is not selected, then the indicator
is drawn with a deselected appearance, and the associated variable is set
to a different value (typically 0).  Under Unix, the indicator is drawn
with a raised relief and no special color.  Under Windows, the indicator
is drawn without a check mark inside.  By default, the name of the
variable associated with a checkbutton is the same as the name used to
create the checkbutton.  The variable name, and the "on" and "off" values
stored in it, may be modified with options on the command line or in the
option database.  Configuration options may also be used to modify the way
the indicator is displayed (or whether it is displayed at all).  By
default a checkbutton is configured to select and deselect itself on
alternate button clicks.  In addition, each checkbutton monitors its
associated variable and automatically selects and deselects itself when
the variables value changes to and from the button's "on" value.

WIDGET METHODS
==============

   The Checkbutton method creates a widget object.  This object supports
the configure and cget methods described in Tk/options,
which can be used to enquire and modify the options described above.  The
widget also inherits all the methods provided by the generic
`Tk::Widget|Tk::Widget' in this node class.

   The following additional methods are available for checkbutton widgets:

*$checkbutton*->*deselect*
     Deselects the checkbutton and sets the associated variable to its
     "off" value.

*$checkbutton*->flash
     Flashes the checkbutton.  This is accomplished by redisplaying the
     checkbutton several times, alternating between active and normal
     colors.  At the end of the flash the checkbutton is left in the same
     normal/active state as when the command was invoked.  This command is
     ignored if the checkbutton's state is disabled.

*$checkbutton*->*invoke*
     Does just what would have happened if the user invoked the checkbutton
     with the mouse: toggle the selection state of the button and invoke
     the `Tk callback|Tk::callbacks', see Perl (perl.info),
     associated with the checkbutton, if there is one.  The return value
     is the return value from the `Tk callback|Tk::callbacks', see Perl (perl.info),
     or an empty string if there is no command
     associated with the checkbutton.  This command is ignored if the
     checkbutton's state is disabled.

*$checkbutton*->select
     Selects the checkbutton and sets the associated variable to its "on"
     value.

*$checkbutton*->toggle
     Toggles the selection state of the button, redisplaying it and
     modifying its associated variable to reflect the new state.

BINDINGS
========

   Tk automatically creates class bindings for checkbuttons that give them
the following default behavior:

[1]
     On Unix systems, a checkbutton activates whenever the mouse passes
     over it and deactivates whenever the mouse leaves the checkbutton.  On
     Mac and Windows systems, when mouse button 1 is pressed over a
     checkbutton, the button activates whenever the mouse pointer is inside
     the button, and deactivates whenever the mouse pointer leaves the
     button.

[2]
     When mouse button 1 is pressed over a checkbutton, it is invoked (its
     selection state toggles and the command associated with the button is
     invoked, if there is one).

[3]
     When a checkbutton has the input focus, the space key causes the
     checkbutton to be invoked.  Under Windows, there are additional key
     bindings; plus (+) and equal (=) select the button, and minus (-)
     deselects the button.

     If the checkbutton's state is disabled then none of the above actions
     occur:  the checkbutton is completely non-responsive.

     The behavior of checkbuttons can be changed by defining new bindings
     for individual widgets or by redefining the class bindings.

KEYWORDS
========

   checkbutton, widget

Manipulate Tk clipboard
***********************

NAME
====

   Tk::clipboard - Manipulate Tk clipboard

   $widget->*clipboard*Option?(args)?

DESCRIPTION
===========

   This command provides an interface to the Tk clipboard, which stores
data for later retrieval using the selection mechanism.  In order to copy
data into the clipboard, *clipboardClear* must be called, followed by a
sequence of one or more calls to *clipboardAppend*.  To ensure that the
clipboard is updated atomically, all appends should be completed before
returning to the event loop.

   The following methods are currently supported:

$widget->*clipboardClear*
     Claims ownership of the clipboard on $widget's display and removes
     any previous contents.   Returns an empty string.

$widget->*clipboardAppend*(?*-format*=>format?,?*-type*=>type?,?-?,data)
     Appends data to the clipboard on $widget's display in the form given
     by type with the representation given by format and claims ownership
     of the clipboard on $widget's display.

     Type specifies the form in which the selection is to be returned (the
     desired "target" for conversion, in ICCCM terminology), and should be
     an atom name such as STRING or FILE_NAME; see the Inter-Client
     Communication Conventions Manual for complete details.  Type defaults
     to STRING.

     The format argument specifies the representation that should be used
     to transmit the selection to the requester (the second column of
     Table 2 of the ICCCM), and defaults to STRING.  If format is STRING,
     the selection is transmitted as 8-bit ASCII characters.  See the
     `Tk::Selection' in this node documentation for explanation of what
     happens if format is not STRING.  Note that arguments passed to
     *clipboardAppend* are concatenated before conversion, so the caller
     must take care to ensure appropriate spacing across string
     boundaries.  All items appended to the clipboard with the same type
     must have the same format.

     A - argument may be specified to mark the end of options:  the next
     argument will always be used as data.  This feature may be convenient
     if, for example, data starts with a -.

KEYWORDS
========

   clear, format, clipboard, append, selection, type

Clock widget with analog and digital display
********************************************

NAME
====

   Tk::Clock - Clock widget with analog and digital display

SYNOPSIS
========

   use Tk use Tk::Clock;

   $clock = $parent->Clock (?-option => <value> ...?);

   $clock->config (	# These reflect the defaults     useDigital	=> 1,
   useAnalog	=> 1,     anaScale	=> 100,     handColor	=>
"Green4",     secsColor	=> "Green2",     tickColor	=> "Yellow4",
tickFreq	=> 1,     timeFont	=> "fixed",     timeColor	=>
"Red4",     timeFormat	=> "HH.MM:SS",     dateFont	=> "fixed",
dateColor	=> "Blue4",     dateFormat	=> "dd-mm-yy");

DESCRIPTION
===========

   Create a clock canvas with both an analog- and a digital display. Either
can be disabled by setting useAnalog or useDigital to 0 resp.

   Legal dateFormat characters are d and dd for date, ddd and dddd for
weekday, m, mm, mmm and mmmm for month, y and yy for year and any
separators :, -, / or space.

   Legal timeFormat characters are H and HH for hour, h and hh for AM/PM
hour, M and MM for minutes, S and SS for seconds, A for AM/PM indicator
and any separators :, -, . or space.

   Meaningful values for tickFreq are 1, 5 and 15 showing all ticks, tick
every 5 minutes or the four main ticks only, though any positive integer
will do (put a tick on any tickFreq minute).

   The analog clock can be enlaged or reduced using anaScale for which the
default of 100% is about 72x72 pixels. Future enhancement will include
auto sizing for anaScale 0.

BUGS
====

   If the system load's too high, the clock might skip some seconds.

   Due to the fact that the year is expressed in 2 digit's, this widget is
not Y2K compliant in the default configuration.

   There's no check if either format will fit in the given space.

TODO
====

   * Using POSIX' strftime () for dateFormat. Current implementation
would probably make this very slow.  * Auto sizing to fit (analog) clock
in given space.

AUTHOR
======

   H.Merijn Brand <merijn@hempseed.com>

   Thanks to Larry Wall for inventing perl.  Thanks to Nick Ing-Simmons
for providing perlTk.  Thanks to Achim Bohnet for introducing me to OO
(and converting     the basics of my clock.pl to Tk::Clock.pm).  Thanks to
Sriram Srinivasan for understanding OO though his Panther book.

An OO Tk Canvas
***************

NAME
====

   Tk::Cloth - An OO Tk Canvas

SYNOPSIS
========

     use Tk::Cloth;

     $cloth = $parent->Cloth;
     $cloth->pack(-fill => 'both', -expand => 1);

     $rect = $cloth->Rectangle(
     	-coords => [ 0,0,100,100],
     	-fill => 'red'
     );

     $tag = $cloth->tag;
     $tag->Line(
     	-coords => [10,10,100,100],
     	-foreground => 'black'
     );
     $tag->Line(
     	-coords => [50,50,100,100],
     	-foreground => 'black'
     );
     $tag->move(30,30);

     $tag->bind("<1>", [ &button1 ]);

DESCRIPTION
===========

   *Tk::Cloth* provides an object-orientated approach to a canvas and
canvas items.

SEE ALSO
========

   `Tk::Canvas|Tk::Canvas' in this node

AUTHOR
======

   Graham Barr <`gbarr@pobox.com'>

   Current maintainer is Slaven Rezic <`eserte@cs.tu-berlin.de'>.

COPYRIGHT
=========

   Copyright (c) 1997-1998 Graham Barr. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Process standard X11 command line options and set initial resources
*******************************************************************

NAME
====

   Tk::CmdLine - Process standard X11 command line options and set initial
resources

SYNOPSIS
========

     Tk::CmdLine::SetArguments([@argument]);

     my $value = Tk::CmdLine::cget([$option]);

     Tk::CmdLine::SetResources((\@resource | $resource) [, $priority]);

     Tk::CmdLine::LoadResources(
         [ -symbol   => $symbol     ]
         [ -file     => $fileSpec   ]
         [ -priority => $priority   ]
         [ -echo     => $fileHandle ] );

DESCRIPTION
===========

   Process standard X11 command line options and set initial resources.

   The X11R5 man page for X11 says: "Most X programs attempt to use the
same names for command line options and arguments. All applications
written with the X Toolkit Intrinsics automatically accept the following
options: ...".  This module processes these command line options for
perl/Tk applications using the SetArguments function.

   This module can optionally be used to load initial resources explicitly
via function SetResources, or from specified files (default: the standard
X11 application-specific resource files) via function LoadResources.

Command Line Options
--------------------

*-background* Color | *-bg* Color
     Specifies the color to be used for the window background.

*-class* Class
     Specifies the class under which resources for the application should
     be found.  This option is useful in shell aliases to distinguish
     between invocations of an application, without resorting to creating
     links to alter the executable file name.

*-display* Display | *-screen* Display
     Specifies the name of the X server to be used.

*-font* *Font* | *-fn* *Font*
     Specifies the font to be used for displaying text.

*-foreground* Color | *-fg* Color
     Specifies the color to be used for text or graphics.

*-geometry* Geometry
     Specifies the initial size and location of the first
     `MainWindow|Tk::MainWindow' in this node.

*-iconic*
     Indicates that the user would prefer that the application's windows
     initially not be visible as if the windows had been immediately
     iconified by the user.  Window managers may choose not to honor the
     application's request.

*-motif*
     Specifies that the application should adhere as closely as possible
     to Motif look-and-feel standards. For example, active elements such
     as buttons and scrollbar sliders will not change color when the
     pointer passes over them.

*-name* Name
     Specifies the name under which resources for the application should
     be found.  This option is useful in shell aliases to distinguish
     between invocations of an application, without resorting to creating
     links to alter the executable file name.

*-synchronous*
     Indicates that requests to the X server should be sent synchronously,
     instead of asynchronously. Since Xlib normally buffers requests to
     the server, errors do do not necessarily get reported immediately
     after they occur. This option turns off the buffering so that the
     application can be debugged. It should never be used with a working
     program.

*-title* *TitleString*
     This option specifies the title to be used for this window. This
     information is sometimes used by a window manager to provide some
     sort of header identifying the window.

*-xrm* *ResourceString*
     Specifies a resource pattern and value to override any defaults. It
     is also very useful for setting resources that do not have explicit
     command line arguments.

     The *ResourceString* is of the form <pattern>:<value>, that is (the
     first) ':' is used to determine which part is pattern and which part
     is value. The (<pattern>, <value>) pair is entered into the options
     database with *optionAdd* (for each `MainWindow|Tk::MainWindow' in
     this node configured), with interactive priority.

Initial Resources
-----------------

   There are several mechanism for initializing the resource database to
be used by an X11 application. Resources may be defined in a
$HOME/.Xdefaults file, a system application defaults file (e.g.
/usr/lib/X11/app-defaults/<CLASS>), or a user application defaults file
(e.g. $HOME/<CLASS>).  The Tk::CmdLine functionality for setting initial
resources concerns itself with the latter two.

   Resource files contain data lines of the form <pattern>:<value>.  They
may also contain blank lines and comment lines (denoted by a ! character
as the first non-blank character). Refer to `option|Tk::option' in this
node for a description of <pattern>:<value>.

System Application Defaults Files
     System application defaults files may be specified via environment
     variable $XFILESEARCHPATH which, if set, contains a colon-separated
     list of file patterns.

User Application Defaults Files
     User application defaults files may be specified via environment
     variables $XUSERFILESEARCHPATH, $XAPPLRESDIR or $HOME.

METHODS
=======

SetArguments
     Extract the X11 options contained in a specified array (@ARGV by
     default).

          Tk::CmdLine::SetArguments([@argument])

     The X11 options may be specified using a single dash - as per the X11
     convention, or using two dashes - as per the POSIX standard (e.g.
     *-geometry* *100x100*, *-geometry* *100x100* or
     *-geometry=**100x100*).  The options may be interspersed with other
     options or arguments.  A - by itself terminates option processing.

     By default, command line options are extracted from @ARGV the first
     time a MainWindow is created. The Tk::MainWindow constructor
     indirectly invokes SetArguments to do this.

cget
     Get the value of a configuration option specified via SetArguments.
     (cget first invokes SetArguments if it has not already been invoked.)

          Tk::CmdLine::cget([$option])

     The valid options are: *-class*, *-name*, *-screen* and *-title*.  If
     no option is specified, *-class* is implied.

     A typical use of cget might be to obtain the application class in
     order to define the name of a resource file to be loaded in via
     LoadResources.

          my $class = Tk::CmdLine::cget(); # process command line and return class

SetResources
     Set the initial resources.

          Tk::CmdLine::SetResources((\@resource | $resource) [, $priority])

     A single resource may be specified using a string of the form
     '<pattern>:<value>'. Multiple resources may be specified by passing
     an array reference whose elements are either strings of the above
     form, and/or anonymous arrays of the form [ <pattern>, <value> ]. The
     optional second argument specifies the priority, as defined in
     `option|Tk::option' in this node, to be associated with the resources
     (default: userDefault).

     Note that SetResources first invokes SetArguments if it has not
     already been invoked.

LoadResources
     Load initial resources from one or more files.

          Tk::CmdLine::LoadResources(
              [ -symbol   => $symbol     ]
              [ -file     => $fileSpec   ]
              [ -priority => $priority   ]
              [ -echo     => $fileHandle ] );

     [ *-symbol* => $symbol ] specifies the name of an environment variable
     that, if set, defines a colon-separated list of one or more
     directories and/or file patterns. $XUSERFILESEARCHPATH is a special
     case.  If $XUSERFILESEARCHPATH is not set, $XAPPLRESDIR is checked
     instead.  If $XAPPLRESDIR is not set, $HOME is checked instead.

     An item is identified as a file pattern if it contains one or more
     /%[A-Za-z]/ patterns. Only patterns *%L*, %T and *%N* are currently
     recognized. All others are replaced with the null string. Pattern
     *%L* is translated into $LANG. Pattern %T is translated into
     *app-defaults*. Pattern *%N* is translated into the application class
     name.

     Each file pattern, after substitutions are applied, is assumed to
     define a FileSpec to be examined.

     When a directory is specified, FileSpecs <DIRECTORY>/<LANG>/<CLASS>
     and <DIRECTORY>/<CLASS> are defined, in that order.

     [ *-file* => $fileSpec ] specifies a resource file to be loaded in.
     The file is silently skipped if if does not exist, or if it is not
     readable.

     [ *-priority* => $priority ] specifies the priority, as defined in
     `option|Tk::option' in this node, to be associated with the resources
     (default: userDefault).

     [ *-echo* => $fileHandle ] may be used to specify that a line should
     be printed to the corresponding FileHandle (default: \*STDOUT)
     everytime a file is examined / loaded.

     If no *-symbol* or *-file* options are specified, LoadResources
     processes symbol $XFILESEARCHPATH with priority startupFile and
     $XUSERFILESEARCHPATH with priority userDefault.  (Note that
     $XFILESEARCHPATH and $XUSERFILESEARCHPATH are supposed to contain
     only patterns. $XAPPLRESDIR and $HOME are supposed to be a single
     directory. LoadResources does not check/care whether this is the
     case.)

     For each set of FileSpecs, LoadResources examines each FileSpec to
     determine if the file exists and is readable. The first file that
     meets this criteria is read in and SetResources is invoked.

     Note that LoadResources first invokes SetArguments if it has not
     already been invoked.

NOTES
=====

   This module is an object-oriented module whose methods can be invoked
as object methods, class methods or regular functions. This is
accomplished via an internally-maintained object reference which is
created as necessary, and which always points to the last object used.
SetArguments, SetResources and LoadResources return the object reference.

EXAMPLES
========

  1. @ARGV is processed by Tk::CmdLine at MainWindow creation.

          use Tk;

          # <Process @ARGV - ignoring all X11-specific options>

          my $mw = MainWindow->new();

          MainLoop();

  2. @ARGV is processed by Tk::CmdLine before MainWindow creation.  An
     @ARGV of (-geometry=100x100 -opt1 a b c -bg red) is equal to (-opt1 a
     b c) after SetArguments is invoked.

          use Tk;

          Tk::CmdLine::SetArguments(); # Tk::CmdLine->SetArguments() works too

          # <Process @ARGV - not worrying about X11-specific options>

          my $mw = MainWindow->new();

          MainLoop();

  3. Just like 2) except that default arguments are loaded first.

          use Tk;

          Tk::CmdLine::SetArguments(qw(-name test -iconic));
          Tk::CmdLine::SetArguments();

          # <Process @ARGV - not worrying about X11-specific options>

          my $mw = MainWindow->new();

          MainLoop();

  4. @ARGV is processed by Tk::CmdLine before MainWindow creation.
     Standard resource files are loaded in before MainWindow creation.

          use Tk;

          Tk::CmdLine::SetArguments();

          # <Process @ARGV - not worrying about X11-specific options>

          Tk::CmdLine::LoadResources();

          my $mw = MainWindow->new();

          MainLoop();

  5. @ARGV is processed by Tk::CmdLine before MainWindow creation.
     Standard resource files are loaded in before MainWindow creation
     using non-default priorities.

          use Tk;

          Tk::CmdLine::SetArguments();

          # <Process @ARGV - not worrying about X11-specific options>

          Tk::CmdLine::LoadResources(-echo => \*STDOUT,
              -priority => 65, -symbol => 'XFILESEARCHPATH' );
          Tk::CmdLine::LoadResources(-echo => \*STDOUT,
              -priority => 75, -symbol => 'XUSERFILESEARCHPATH' );

          my $mw = MainWindow->new();

          MainLoop();

  6. @ARGV is processed by Tk::CmdLine before MainWindow creation.
     Standard resource files are loaded in before MainWindow creation.
     Individual resources are also loaded in before MainWindow creation.

          use Tk;

          Tk::CmdLine::SetArguments();

          # <Process @ARGV - not worrying about X11-specific options>

          Tk::CmdLine::LoadResources();

          Tk::CmdLine::SetResources( # set a single resource
              '*Button*background: red',
              'widgetDefault' );

          Tk::CmdLine::SetResources( # set multiple resources
              [ '*Button*background: red', '*Button*foreground: blue' ],
              'widgetDefault' );

          my $mw = MainWindow->new();

          MainLoop();

ENVIRONMENT
===========

HOME (optional)
     Home directory which may contain user application defaults files as
     $HOME/$LANG/<CLASS> or $HOME/<CLASS>.

LANG (optional)
     The current language (default: C).

XFILESEARCHPATH (optional)
     Colon-separated list of FileSpec patterns used in defining system
     application defaults files.

XUSERFILESEARCHPATH (optional)
     Colon-separated list of FileSpec patterns used in defining user
     application defaults files.

XAPPLRESDIR (optional)
     Directory containing user application defaults files as
     $XAPPLRESDIR/$LANG/<CLASS> or $XAPPLRESDIR/<CLASS>.

SEE ALSO
========

   `MainWindow|Tk::MainWindow' in this node `option|Tk::option' in this
node

HISTORY
=======

   * 1999.03.04 Ben Pavon <ben.pavon@hsc.hac.com>

     Rewritten as an object-oriented module.

     Allow one to process command line options in a specified array (@ARGV
     by default).  Eliminate restrictions on the format and location of
     the options within the array (previously the X11 options could not be
     specified in POSIX format and had to be at the beginning of the
     array).

     Added the SetResources and LoadResources functions to allow the
     definition of resources prior to MainWindow creation.

a general purpose Tk widget Color Editor
****************************************

NAME
====

   Tk::ColorEditor - a general purpose Tk widget Color Editor

SYNOPSIS
========

     use Tk::ColorEditor;

     $cref = $mw->ColorEditor(-title => $title, -cursor => @cursor);

     $cref->Show;

DESCRIPTION
===========

   ColorEditor is implemented as an object with various methods, described
below.  First, create your ColorEditor object during program initialization
(one should be sufficient), and then configure it by specifying a list of
Tk widgets to colorize. When it's time to use the editor, invoke the Show()
method.

   ColorEditor allows some customization: you may alter the color attribute
menu by adding and/or deleting menu items and/or separators, turn the
status window on or off, alter the configurator's list of color widgets,
or even supply your own custom color configurator callback.

  1. Call the constructor to create the editor object, which in turn
     returns a blessed reference to the new object:

          use Tk::ColorEditor;

          $cref = $mw->ColorEditor(
              -title  => $title,
              -cursor => @cursor,
          );

          mw     - a window reference, usually the result of a MainWindow->new
                   call.  As the default root of a widget tree, $mw and all
                   descendant widgets at object-creation-time are configured
                   by the default color configurator procedure.  (You probably
                   want to change this though or you might end up colorizing
                   ColorEditor!)
          title  - Toplevel title, default = ' '.
          cursor - a valid Tk '-cursor' specification (default is
                   'top_left_arrow').  This cursor is used over all ColorEditor
                   "hot spots".

  2. Invoke the configure() method to change editor characteristics:

          $cref->configure(-option => value, ..., -option-n => value-n);

          options:
            -command             : a callback to a  `set_colors' replacement.
            -widgets             : a reference to a list of widget references
                                   for the color configurator.
            -display_status      : TRUE IFF display the ColorEditor status
                                   window when applying colors.
            -add_menu_item       : 'SEP', or a color attribute menu item.
            -delete_menu_item    : 'SEP', a color attribute menu item, or color
                                   attribute menu ordinal.

          For example:

          $cref->configure(-delete_menu_item   => 3,
              -delete_menu_item   => 'disabledforeground',
              -add_menu_item      => 'SEP',
              -add_menu_item      => 'New color attribute',
              -widgets            => [$ce, $qu, $f2b2],
              -widgets            => [$f2->Descendants],
              -command            => [\&my_special_configurator, some, args ]
          );

  3. Invoke the Show() method on the editor object, say, by a button or
     menu press:

          $cref->Show;

  4. The cget(-widgets) method returns a reference to a list of widgets
     that are colorized by the configurator.  Typically, you add new
     widgets to this list and then use it in a subsequent configure() call
     to expand your color list.

          $cref->configure(
              -widgets => [
                  @{$Filesystem_ref->cget(-widgets)}, @{$cref->cget(-widgets)},
              ]
          );

  5. The delete_widgets() method expects a reference to a list of widgets
     which are then removed from the current color list.

          $cref->delete_widgets($OBJTABLE{$objname}->{'-widgets'})

AUTHORS
=======

   Stephen O. Lidie, Lehigh University Computing Center.  95/03/05
lusol@Lehigh.EDU

   Many thanks to Guy Decoux (decoux@moulon.inra.fr) for doing the initial
translation of tcolor.tcl to TkPerl, from which this code has been derived.

Perl/Tk module providing a Colour selection dialogue box.
*********************************************************

NAME
====

   ColourChooser - Perl/Tk module providing a Colour selection dialogue
box.

SYNOPSIS
========

     use Tk::ColourChooser ;

     my $col_dialog = $Window->ColourChooser ;
     my $colour     = $col_dialog->Show ;
     if( $colour ) {
         # They pressed OK and the colour chosen is in $colour - could be
         # transparent which is 'None' unless -transparent is set.
     }
     else {
         # They cancelled.
     }

     # May optionally have the colour initialised.
     my $col_dialog = $Window->ColourChooser( -colour => 'green' ) ;
     my $col_dialog = $Window->ColourChooser( -colour => '#0A057C' ) ;

     # The title may also be overridden; and we can insist that only hex values
     # are returned rather than colour names. We can disallow transparent.
     my $col_dialog = $Window->ColourChooser(
                         -language    => 'en', # Or 'de' or 'fr'.
                         -title       => 'Select a colour',
                         -colour      => '0A057C',
                         -transparent => 0,
                         -hexonly     => 1,
                         -showhex     => 1,
                         ) ;

DESCRIPTION
===========

   ColourChooser is a dialogue box which allows the user to pick a colour
from the list in rgb.txt (supplied with X Windows), or to create a colour
by setting RGB (red, green, blue) values with slider controls.

   You can scroll through all the named colours by using the <Down> and
<Up> arrow keys on the keyboard or by clicking the mouse on the scrollbar
and then clicking the colour list.

Options
-------

`-language' This is optional. Default is `en'. This option allows you to set the language for the title and labels. Valid values are `en' (english), `de' (german), `fr' (french) and `english' (for backward compatibility) which is also the default. Translations are by Babelfish. Other languages will be added if people provide translations.
`-title'   This is optional and allows you to set the title. Default is 'Colour Chooser' in the `-language' specified.
`-colour'  This is optional and allows you to specify the colour that is shown when the dialogue is invoked. It may be specified as a colour name from rgb.txt or as a six digit hex number with an optional leading hash, i.e. as 'HHHHHH' or '#HHHHHH'. Default is 'black'.
`-hexonly' This is optional. If set to 1 it forces the ColourChooser to only return colours as hex numbers in Tk format ('#HHHHHH'); if set to 0 it returns colours as names if they are named in rgb.txt, and as hex numbers if they have no name. Transparent is always returned as 'None' however. Default is 0.
`-transparent' This is optional. If set to 0 it stops ColourChooser offering the Transparent button so that only valid colours may be chosen - or cancel. Default is 1.
`-showhex' This is optional. If set to 1 it shows the hex value of the colour in the title bar. Default is 0.
   The user has three options:

OK
--

   Pressing OK will return the selected colour, as a name if it has one or
as an RGB value if it doesn't. (Colours which do not have names are listed
as 'Unnamed' in the colour list box.) If the `-hexonly' option has been
specified the colour is always returned as a Tk colour hex value, i.e. in
the form '#HHHHHH' except if Transparent is chosen in which case 'None' is
returned.

   OK is pressed by a mouse click or <Return> or <o> or <Control-o> or
<Alt-o>.

Transparent
-----------

   Pressing Transparent will return the string 'None' which is xpm's name
for transparent.

   Transparent is pressed by a mouse click or <t> or <Control-t> or
<Alt-t>.

Cancel
------

   Pressing Cancel will return an empty string.

   Cancel is pressed by a mouse click or <Escape> or <c> or <Control-c> or
<Alt-c>. (Note that if the language is not english then the letter to press
will be the first letter of the translation of the word 'Cancel'.

INSTALLATION
============

   ColourChooser.pm should be placed in any Tk directory in any lib
directory in Perl's %INC path, for example, '/usr/lib/perl5/Tk'.

   ColourChooser looks for the file rgb.txt on your system - if it can't
find it you will only be able to specify colours by RGB value.

BUGS
====

   Does almost no error checking.

   Can be slow to load because rgb.txt is large; however we now load a
single instance of the colour names when the module is first used and
these names are then shared.

   If you scroll the list by keyboard or use the mouse to move the colour
sliders the colour updates as you go; but if you use the mouse on the
scrollbar you must click the colour name box for the colour to update. I
don't know why this is and any advice on how to fix it would be welcome.

AUTHOR
======

   Mark Summerfield. I can be contacted as <summer@perlpress.com> - please
include the word 'colourchooser' in the subject line.

   The code draws from Stephen O. Lidie's work.

COPYRIGHT
=========

   Copyright (c) Mark Summerfield 1999-2000. All Rights Reserved.

   This module may be used/distributed/modified under the LGPL.

A multicolumn list widget with sortable & sizeable columns
**********************************************************

NAME
====

   Tk::Columns - A multicolumn list widget with sortable & sizeable columns

SYNOPSIS
========

     use Tk::Columns;

     $Columns = $parent->B<Columns>
        (
         '-columnlabels' => [qw (column1 column2)]
         '-listbackground' => 'white',
         '-listforeground' => 'black',
         '-buttonforeground' => 'black',
         '-buttonbackground' => 'blue',
        );

     $ColumnHeader = $Columns->B<ColumnButton>
        (
         '-listfont' => '-adobe-new century schoolbook-medium-r-normal--14-*-*-*-*-*-*-*',
         '-buttoncolor' => 'beige',
         '-text' => 'column3',
         '-width' => 15,
         '-trimcount' => 2,
         '-listbackground' => 'white',
         '-listforeground' => 'black',
         '-buttonforeground' => 'black',
         '-buttonbackground' => 'blue',
         '-sort' => 'true',
         '-sortcommand' => '$a cmp $b',
         '-image' => $icon_image,
         '-buttoncommand' => sub {...},
         '-selectcommand' => sub {...}
        );

     $Columns->insert ('end', ['List', 'Row', 'Contents']);
     $Columns->insert ('end', {'column1' => 'List', 'column2' => 'Row', 'column3' => 'Contents'});
     $Columns->insert ('end', 'List', 'Row', 'Contents');
     $Columns->delete (0, 'end');

     ...

     Tk::MainLoop;

DESCRIPTION
===========

   Implements a multicolumn list with resizeable, scrollable columns and
configurable sorting by column. Other features include column selection
callbacks and row selection callbacks, global and per-column color and
font selection, and column insertion data specified by column label (hash)
or by index (list).

STANDARD OPTIONS
================

Columns
     *-background -foreground -font -bg*

ColumnButton
     *-font -image -foreground -background -borderwidth -relief -text
     -width -bg*

   See Tk for details of the standard options.

WIDGET-SPECIFIC OPTIONS
=======================

Name:	*buttonbackground*
Class:	*ButtonBackground*
Switch:	*-buttonbackground*
Aliases:	*-buttoncolor* *-color*
     Specifies the background (surface) color for all existing buttons

Name:	*buttoncommand*
Class:	*ButtonCommand*
Switch:	*-buttoncommand*
     Specifies a callback to be executed when a column header is clicked.
     The callback is passed the list index. When specified, this callback
     is registered for every existing listbox and sets the default for new
     ones.  If the *-sort* option is turned on, it overrides this option
     but does not negate it, allowing it to return when the *-sort* option
     is turned off.

Name:	*buttonfont*
Class:	*ButtonFont*
Switch:	*-buttonfont*
     Specifies the font to use for all the existing column header labels

Name:	columns
Class:	Columns
Switch:	*-columns*
Aliases:	*-columnlabels*
     This option takes a reference to a list of options. If the list
     consists of scalar values, these are assumed to be the labels for
     column headers. These elements are created with default options which
     should normally be alright.  If the list consists of references to
     arrays, then these are assumed to be key => value pairs specifying
     the options to pass to $Columns->addcolumn.

Name:	image
Class:	Image
Switch:	*-image*
     Setting this to a reference to a Tk::Image causes that image to be
     set for all of the column labels and sets the default for all future
     columns. By default column headers are displayed without icons.

     See Tk/Label,

    Name:	*listbackground*
    Class:	*ListBackground*
    Switch:	*-listbackground*
    Aliases:	*-listcolor* *-background* *-bg*
          Specifies the background (surface) color for all existing
          listboxes and sets the default for all new ones. Default is
          'white'

    Name:	*listfont*
    Class:	*ListFont*
    Switch:	*-listfont*
    Alias:	*-font*
          Specifies the font for all existing listboxes and sets the
          default for all new ones. The default is to use the system
          default font.

    Name:	*listforeground*
    Class:	*ListForeground*
    Switch:	*-listforeground*
          Specifies the foreground (writing) color for all existing
          listboxes and sets the default for all new ones. Default is
          'black'

    Name:	*selectcommand*
    Class:	*SelectCommand*
    Switch:	*-selectcommand*
    Aliases:	*-command*
          Specifies a callback to be executed when a list entry is
          double-clicked.  The callback is passed the list index. When
          specified, this callback is registered for every existing
          listbox and sets the default for new ones.

    Name:	*selectmode*
    Class:	*SelectMode*
    Switch:	*-selectmode*
          Sets the selection mode for all existing listboxes and sets the
          default to use for new ones. The default is 'browse'.

    Name:	*trimcount*
    Class:	*TrimCount*
    Switch:	*-trimcount*
          Specifies the number of button trim 'handles' for all existing
          buttons.

    Name:	zoom
    Class:	*Zoom*
    Switch:	*-zoom*
          This option takes a boolean argument. When set to 1, all the
          existing columns are 'zoomed', that is, reduced to their
          smallest width. When set to 0, all the columns are returned to
          the original widths

WIDGET METHODS
==============

$Button = *$Columns*->ColumnButton (option => value, ...)
$Button = *$Columns*->addcolumn (option => value, ...)
$Button = *$Columns*->Column (option => value, ...)
$Button = *$Columns*->Button (option => value, ...)
$Button = *$Columns*->column (option => value, ...)
     Creates a column header and an attached listbox. The listbox is
     'tied' to any preexisting ones. The new listbox is padded with empty
     rows to match its siblings. This method really invokes an
     instantiation of the ColumnButton class. All the options given apply
     to the ColumnButton. The widget reference returned can be used to
     alter the column's behaviour later. The following options are
     available :-

    *-background* => color
    *-buttonbackground* => color
    *-bg* => color
    *-buttoncolor* => color
    *-color* => color
          Specifies the button's background (surface) color.

    *-buttoncommand* => callback
          Specifies a callback to be executed when a column header is
          clicked. The callback is passed the list index. If the *-sort*
          option is turned on, it overrides this option but does not
          negate it, allowing it to return when the *-sort* option is
          turned off.

    *-font* => *fontspec*
    *-buttonfont* => *fontspec*
          Specifies the font for the text in the button label.

    *-foreground* => color
    *-buttonforeground* => color
    *-fg* => color
          Specifies the button's foreground (text) color. Defaults to
          black.

    *-image* => image
          Setting this to a reference to a Tk::Image causes that image to
          be displayed in the column label.

          See Tk/Label,

    *-listbackground* => color
    *-slavecolor* => color
          Sets the background color for the attached listbox

    *-listfont* => *fontspec*
          Specifies the font for the text in the attached listbox.

    *-listforeground* => color
          Sets the foreground (text) color for the attached listbox.

    *-listselectmode* => mode
          Sets the selection mode for the attached listbox.

    *-selectcommand* => callback
    *-command* => callback
          Specifies a callback to be executed when a list entry is
          double-clicked.  The callback is passed the list index.

    *-slave* => widget
          DO NOT USE ! This option is use to inform the button which
          widget it must manage. It is provided here only for completeness.

    *-sort* => boolean
          Setting this to boolean 'true' allows all columns to be sorted
          by this column when the button is pressed. Each invocation
          reverses the sort order. The sort method can be specified with
          *-sortcommand*. Setting this to boolean false (0) disables the
          sorting. When active, this option overrides any existing
          *-buttoncommand*. When inactive, any preexisting
          *-buttoncommand* is re-enabled.

    *-sortcommand* => string
    *-sortfunction* => string
    *-sortmethod* => string
          This specifies the sort function to pass to the sort Perl
          function for sorting of this column. The default is '{lc ($a)
          cmp lc ($b)}' for (caseless) alphanumeric comparison.

          Read the *perlfunc* documentation for more details on sort.

    *-trimcount* => integer
          Specifies the number of trim 'handles' for the button. It
          defaults to 2.  Setting it to 0 makes the column unresizeable.

    *-width* => integer
          Set this to the desired width of the column, in characters. The
          default is the natural width of the text and image parts
          combined.

    *-zoom* => boolean
          This option takes a boolean argument. When set to 1, the column
          is 'zoomed', that is, its width is reduced to the smallest
          possible setting. When set to 0, the column is returned to its
          original width.

*$Columns*->activate(index)
     Sets the row element to the one indicated by index. If index is
     outside the range of elements in the listbox then the closest element
     is activated. The active element is drawn with an underline when the
     widget has the input focus, and its index may be retrieved with the
     index active.

     See listbox for more details.

*$Columns*->*bbox*(index, *[columnspec]*)
     Returns a list of four numbers describing the bounding box of the
     text in the element given by index in the listbox specified by column
     or the first listbox in the composite. The first two elements of the
     list give the x and y coordinates of the upper-left corner of the
     screen area covered by the text (specified in pixels relative to the
     widget) and the last two elements give the width and height of the
     area, in pixels. If no part of the element given by index is visible
     on the screen, or if index refers to a non-existent element, then the
     result is an empty string; if the element is partially visible, the
     result gives the full area of the element, including any parts that
     are not visible.

     See listbox for more details.

*$Columns*->*buttonhash*()
     Returns a hash of column buttons keyed by column label

*$Columns*->*buttons*()
     Returns an ordered list of the column buttons

*$Columns*->*buttonwidth*(*columnspec*, *?newwidth?*)
*$Columns*->*columnwidth*(*columnspec*, *?newwidth?*)
*$Columns*->width(*columnspec*, *?newwidth?*)
     This uses the numeric or textual *columnspec* to locate a column
     header and sets the width to *newwidth* if present, or returns the
     current width of that column. It the column doesn't exist then the
     return value 0 is quietly returned.

*$Columns*->*columnlabels*(*array reference*)
*$Columns*->columns(*array reference*)
     This invokes *$Columns*->configure (*-columnlabels* => *array
     reference*). See *-columnlabels* for details as this is a convenience
     method.

*$Columns*->*curselection*()
     Returns a list containing the numerical indices of all of the
     elements in the listbox that are currently selected. If there are no
     elements selected in the listbox then an empty string is returned.

     See listbox for more details.

*$Columns*->delete(where, where)
     This has identical behaviour to listbox->delete.

     See listbox for more details.

*$Columns*->get(from, to)
     Retrieves the rows in the range from .. to. This method is an analog
     of the listbox->get method. The data returned is an array of
     references to the row lists specified.

     See listbox for more details.

*$Columns*->index(index)
     Returns the integer index value that corresponds to index. If index
     is end the return value is a count of the number of elements in the
     listbox (not the index of the last element).

     See listbox for more details.

*$Columns*->*indexedbutton*(*columnspec*)
     Returns the column button associated with the numeric column index or
     the textual column name.

*$Columns*->*indexedlist*(*columnspec*)
     Returns the listbox associated with the numeric column index or the
     textual column name.

*$Columns*->insert(where, ?<option>?, ...)
     This method inserts rows across all listboxes. where is the same as
     documented in the listbox pod. The following options can be a list of
     scalars, a list of references to hashes, or a list of references to
     arrays. These can appear in any order. A list of scalars will be
     interpreted up to an array reference or the end of the parameter
     list, whichever comes first. The list is padded out so it can be
     applied to all listboxes. It is then inserted using where.

     An array reference is dereferenced and applied just as the inline
     list. A hash is assumed to be keyed by the column header labels. It
     is converted into a list using the column header order and applied
     normally after 'padding'.

     NOTE: The insertions are 'cached' and then applied to each listbox at
     once, avoiding flicker and slow updates.

*$Columns*->labels()
     Returns an ordered list of the column names

*$Columns*->*listhash*()
*$Columns*->hash()
     Returns a hash of listboxes keyed by column label

*$Columns*->*lists*()
     Returns an ordered list of the column listboxes

*$Columns*->nearest(y)
     Given a y-coordinate within the listbox window, this command returns
     the index of the (visible) listbox element nearest to that
     y-coordinate.

     See listbox for more details.

*$Columns*->selection (option, argument)
     Adjusts the selection. It has several forms, depending on option.

     See listbox for more details.

*$Columns*->see(index)
     Makes row index visible.

     See listbox for more details.

*$Columns*->size()
*$Columns*->rows()
     Returns the number of rows.

*$Columns*->update(where, ...)
*$Columns*->replace(where, ...)
     This takes the same options as <$Columns>->insert but deletes the row
     found there first.

BINDINGS
========

[1]
     Pressing and releasing the left mouse button on a columns label will
     cause the *-sortcommand* or the default sort method to be invoked if
     the *-sort* option has been enabled. Otherwise, the callback
     specified in *-buttoncommand* is invoked if it is defined.

[2]
     Double-clicking the left mouse button on any listbox will cause the
     callback specified by *-selectcommand* to be invoked with the row
     index of the selected listbox item.

[3]
     Pressing and releasing the right mouse button on the column label
     trim elements will cause that column to 'zoom'.  That is, it will
     collapse the column to its smallest size without the need to drag it.
     When pressed again, the column will return to its original size. The
     mouse pointer will change to a 'resize' form when this action is
     possible.

[4]
     Pressing the left mouse button on the column label trim elements will
     initiate resizing of that column. The edge of the column will follow
     the mouse horizontally until the button is released whereupon the
     column will remain at the selected size. The mouse pointer will
     change to a 'resize' form when this action is possible.

REQUIREMENTS
============

Tk::TiedListbox from *Tk-Contrib-0.06*
CAVEATS
=======

   I regret that there appears to be no way to justify the listboxes. If
anyone knows, please tell me how.

AUTHORS
=======

   Damion K. Wilson, dwilson@ibl.bm, http://pwp.ibl.bm/~dkw

COPYRIGHT
=========

   Copyright (c) 1999 Damion K. Wilson.

   All rights reserved.

   This program is free software, you may redistribute it and/or modify it
under the same terms as Perl itself.

HISTORY
=======

*July 4, 1999*: fixed scrollbar redisplay failure after insertion bug
*September 1, 1999*: Rewrite with legacy support
*November 25, 1999*: Fixed index and delete methods

Drop down list entry widget
***************************

NAME
====

   Tk::ComboEntry - Drop down list entry widget

SYNOPSIS
========

     use Tk;

     my $MainWindow = MainWindow->new();

     Tk::MainLoop;

DESCRIPTION
===========

   A Drop down listbox + entry widget with nice keyboard bindings

AUTHORS
=======

   Damion K. Wilson, dkw@rcm.bm

HISTORY    =cut
===============

private class used by Drag&Drop
*******************************

NAME
====

   Tk::DragDrop::Common - private class used by Drag&Drop

DESCRIPTION
===========

   This class provides methods to automate the the loading and declaring
of Drop and Site 'types'.

Create multi-line compound images.
**********************************

NAME
====

   Tk::Compound - Create multi-line compound images.

DESCRIPTION
===========

   Compound image types can be used to create images that consists of
multiple horizontal lines; each line is composed of a series of items
(texts, bitmaps, images or spaces) arranged from left to right. Compound
images are mainly used to embed complex drawings into widgets that support
the *-image* option. As shown in the EXAMPLE section below, a compound
image can be used to display a bitmap and a text string simutaneously in a
Tk Button widget.

   Compound images can only be used on windows on the same display as, and
with the same pixel depth and visual as the $widget used to create them.

CREATING COMPOUND IMAGES
========================

   Compounds are created using $widget->Compound.  Compounds support the
following options:

*-background* => color
     Specifies the background color of the compound image. This color is
     also used as the default background color for the bitmap items in the
     compound image.

*-borderwidth* => *pixels*
     Specifies a non-negative value indicating the width of the 3-D border
     drawn around the compound image.

*-font* => font
     Specifies the default font for the text items in the compound image.

*-foreground* => color
     Specifies the default foreground color for the bitmap and text items
     in the compound image.

*-padx* => value
     Specifies a non-negative value indicating how much extra space to
     request for the compound image in the X-direction. The value may have
     any of the forms acceptable to *Tk_GetPixels(3)*.

*-pady* => value
     Specifies a non-negative value indicating how much extra space to
     request for the compound image in the Y-direction.

*-relief* => value
     Specifies the 3-D effect desired for the background of the compound
     image. Acceptable values are *raised*, *sunken*, flat, *ridge*, and
     *groove*.

*-showbackground* => value
     Specifies whether the background and the 3D borders should be drawn.
     Must be a valid boolean value. By default the background is not drawn
     and the compound image appears to have a transparent background.

IMAGE COMMAND
=============

   When a compound image is created, Tk also creates a new object.  This
object supports the configure and cget methods described in
Tk/options, which can be used to enquire and modify the
options described above.

   The object also supports the following methods:

*$compound*->Line?(*option =* value ...>)?
     Creates a new line at the bottom of the compound image. Lines support
     the following options:

    *-anchor* value
          Specifies how the line should be aligned along the horizontal
          axis.  When the values are w, sw or *nw*, the line is aligned to
          the left. When the values are c, s or n, the line is aligned to
          the middle.  When the values are e, *se* or ne, the line is
          aligned to the right.

    *-padx* => value
          Specifies a non-negative value indicating how much extra space to
          request for this line in the X-direction.

*$compound*->*Itemtype*?(*option =* value ...>)?
     Creates a new item of the type *Itemtype* at the end of the last line
     of the compound image. All types of items support these following
     common options:

    *-anchor* value
          Specifies how the item should be aligned along the vertical
          axis. When the values are n, *nw* or ne, the item is aligned to
          the top of the line. When the values are c, w or e, the item is
          aligned to the middle of the line.  When the values are s, *se*
          or sw, the item is aligned to the bottom of the line.

    *-padx* => value
          Specifies a non-negative value indicating how much extra space to
          request for this item in the X-direction.

    *-pady* => value
          Specifies a non-negative value indicating how much extra space to
          request for this item in the Y-direction.

    *item-type* can be any of the following:
*$compound*->Bitmap?(*option =* value ...>)?
     Creates a new bitmap item of at the end of the last line of the
     compound image. Additional options accepted by the bitmap type are:

    *-background* => color
          Specifies the background color of the bitmap item.

    *-bitmap* => name
          Specifies a bitmap to display in this item, in any of the forms
          acceptable to *Tk_GetBitmap(3)*.

    *-foreground* => color
          Specifies the foreground color of the bitmap item.

*$compound*->Image?(*option =* value ...>)?
     Creates a new image item of at the end of the last line of the
     compound image. Additional options accepted by the image type are:

    *-image* => name
          Specifies an image to display in this item. name must have been
          created with the *image create* command.

*$compound*->*Space*?(*option =* value ...>)?
     Creates a new space item of at the end of the last line of the
     compound image. Space items do not display anything. They just acts as
     space holders that add additional spaces between items inside a
     compound image. Additional options accepted by the image type are:

    *-width* => value
          Specifies the width of this space. The value may have any of the
          forms acceptable to *Tk_GetPixels(3)*.

    *-height* => value
          Specifies the height of this space. The value may have any of
          the forms acceptable to *Tk_GetPixels(3)*.

*$compound*->Text?(*option =* value ...>)?
     Creates a new text item of at the end of the last line of the compound
     image. Additional options accepted by the text type are:

    *-background* => color
          Specifies the background color of the text item.

    *-font* => name
          Specifies the font to be used for this text item.

    *-foreground* => color
          Specifies the foreground color of the text item.

    -justify value
          When there are multiple lines of text displayed in a text item,
          this option determines how the lines line up with each other.
          value must be one of left, center, or right.  *Left* means that
          the lines' left edges all line up, center means that the lines'
          centers are aligned, and right means that the lines' right edges
          line up.

    *-text* => string
          Specifies a text string to display in this text item.

    *-underline* value
          Specifies the integer index of a character to underline in the
          text item. 0 corresponds to the first character of the text
          displayed in the text item, 1 to the next character, and so on.

    *-wraplength* value
          This option specifies the maximum line length of the label
          string on this text item. If the line length of the label string
          exceeds this length, it is wrapped onto the next line, so that
          no line is longer than the specified length. The value may be
          specified in any of the standard forms for screen distances. If
          this value is less than or equal to 0 then no wrapping is done:
          lines will break only at newline characters in the text.

EXAMPLE
=======

   The following example creates a compound image with a bitmap and a text
string and places this image into a *Button(n)* widget. Notice that the
image must be created using the widget that it resides in.

     my $b = $parent->Button;
     my $c = $b->Compound;
     $b->configure(-image => $c);
     $c->Line;
     $c->Bitmap(-bitmap => 'warning');
     $c->Space(-width => 8);
     $c->Text(-text => "Warning", -underline => 0);
     $b->pack;

KEYWORDS
========

   image(n), Tix(n)

Defining behaviour of 'configure' for composite widgets.
********************************************************

NAME
====

   Tk::ConfigSpecs - Defining behaviour of 'configure' for composite
widgets.

     sub Populate
     {
      my ($composite,$args) = @_;
      ...
      $composite->ConfigSpecs('-attribute' => [ where,dbName,dbClass,default ]);
      $composite->ConfigSpecs('-alias' => '-otherattribute');
      $composite->ConfigSpecs('DEFAULT' => [ where ]);
      ...
     }

     $composite->configure(-attribute => value);

DESCRIPTION
===========

   The aim is to make the composite widget configure method look as much
like a regular Tk widget's configure as possible.  (See Tk/options,
for a description of this behaviour.)  To enable this the
attributes that the composite as a whole accepts needs to be defined.

Defining the ConfigSpecs for a class.
-------------------------------------

   Typically a widget will have one or more calls like the following

     $composite->ConfigSpecs(-attribute => [where,dbName,dbClass,default]);

   in its Populate method. When ConfigSpecs is called this way (with
arguments) the arguments are used to construct or augment/replace a hash
table for the widget. (More than one *-option*=>value pair can be
specified to a single call.)

   *dbName*, *dbClass* and default are only used by *ConfigDefault*
described below, or to respond to 'inquiry' configure commands.

   It may be either one of the values below, or a list of such values
enclosed in [].

   The currently permitted values of where are:

'ADVERTISED'
     apply configure to *advertised* subwidgets.

'DESCENDANTS'
     apply configure recursively to all descendants.

'CALLBACK'
     Setting the attribute does `Tk::Callback->new($value)' before storing
     in `$composite->{Configure}{-attribute}'. This is appropriate for
     `-command => ...' attributes that are handled by the composite and not
     forwarded to a subwidget. (E.g. *Tk::Tiler* has `-yscrollcommand' to
     allow it to have scrollbar attached.)

     This may be the first of several 'validating' keywords (e.g. font,
     cursor, anchor etc.) that core Tk makes special for C code.

'CHILDREN'
     apply configure to all children.  (Children are the immediate
     descendants of a widget.)

'METHOD'
     Call `$cw->attribute(value)'

     This is the most general case. Simply have a method of the composite
     class with the same name as the attribute.  The method may do any
     validation and have whatever side-effects you like.  (It is probably
     worth 'queueing' using *afterIdle* for more complex side-effects.)

'PASSIVE'
     Simply store value in `$composite->{Configure}{-attribute}'.

     This form is also a useful placeholder for attributes which you
     currently only handle at create time.

'SELF'
     Apply configure to the core widget (e.g. Frame) that is the basis of
     the composite. (This is the default behaviour for most attributes
     which makes a simple Frame behave the way you would expect.) Note
     that once you have specified ConfigSpecs for an attribute you must
     explicitly include 'SELF' in the list if you want the attribute to
     apply to the composite itself (this avoids nasty infinite recursion
     problems).

$reference (blessed)
     Call $reference->configure(-attribute => value)

     A common case is where $reference is a subwidget.

     $reference may also be result of

          Tk::Config->new(setmethod,getmethod,args,...);

     *Tk::Config* class is used to implement all the above keyword types.
     The class has configure and cget methods so allows higher level code
     to always just call one of those methods on an object of some kind.

*hash reference*
     Defining:

          $cw->ConfigSpecs(
          	...
          	-option => [ { -optionX=>$w1, -optionY=>[$w2, $w3] },
          			dbname dbclass default ],
          	...
          	);

     So `$cw->configure(-option => value)' actually does

          $w1->configure(-optionX => value);
          $w2->configure(-optionY => value);
          $w3->configure(-optionY => value);

'otherstring'
     Call

          $composite->Subwidget('otherstring')->configure( -attribute => value );

     While this is here for backward compatibility with Tk-b5, it is
     probably better just to use the subwidget reference directly.  The
     only case for retaining this form is to allow an additional layer of
     abstraction - perhaps having a 'current' subwidget - this is unproven.

Aliases
     `ConfigSpecs( -alias => '-otherattribute' )' is used to make `-alias'
     equivalent to `-otherattribute'. For example the aliases

          -fg => '-foreground',
          -bg => '-background'

     are provided automatically (if not already specified).

Default Values
--------------

   When the Populate method returns *ConfigDefault* is called.  This calls

     $composite->ConfigSpecs;

   (with no arguments) to return a reference to a hash. Entries in the hash
take the form:

     '-attribute' => [ where, dbName, dbClass, default ]

   *ConfigDefault* ignores 'where' completely (and also the DEFAULT entry)
and checks the 'options' database on the widget's behalf, and if an entry
is present matching dbName/dbClass

     -attribute => value

   is added to the list of options that new will eventually apply to the
widget. Likewise if there is not a match and default is defined this
default value will be added.

   Alias entries in the hash are used to convert user-specified values for
the alias into values for the real attribute.

New()-time Configure
--------------------

   Once control returns to new, the list of user-supplied options
augmented by those from *ConfigDefault* are applied to the widget using the
configure method below.

   Widgets are most flexible and most Tk-like if they handle the majority
of their attributes this way.

Configuring composites
----------------------

   Once the above have occurred calls of the form:

     $composite->configure( -attribute => value );

   should behave like any other widget as far as end-user code is
concerned.  configure will be handled by *Tk::Derived::configure* as
follows:

     $composite->ConfigSpecs;

   is called (with no arguments) to return a reference to a hash
*-attribute* is looked up in this hash, if *-attribute* is not present in
the hash then *'DEFAULT'* is looked for instead.  (Aliases are tried as
well and cause redirection to the aliased attribute).  The result should
be a reference to a list like:

     [ where, dbName, dbClass, default ]

   at this stage only where is of interest, it maps to a list of object
references (maybe only one) foreach one

     $object->configure( -attribute => value );

   is evaled.

Inquiring attributes of composites
----------------------------------

     $composite->cget( '-attribute' );

   This is handled by  *Tk::Derived::cget* in a similar manner to
configure. At present if where is a list of more than one object it is
ignored completely and the "cached" value in

     $composite->{Configure}{-attribute}.

   is returned.

CAVEATS
=======

   It is the author's intention to port as many of the "Tix" composite
widgets as make sense. The mechanism described above may have to evolve in
order to make this possible, although now aliases are handled I think the
above is sufficient.

SEE ALSO
========

   `Tk::composite|Tk::composite' in this node, `Tk::options|Tk::options'
in this node

context-sensitive help with perl/Tk
***********************************

NAME
====

   Tk::ContextHelp - context-sensitive help with perl/Tk

SYNOPSIS
========

     use Tk::ContextHelp;

     $ch = $top->ContextHelp;
     $ch->attach($widget, -msg => ...);

     $ch->HelpButton($top)->pack;

     $ch2 = $top->ContextHelp(-podfile => "perlfaq");
     $ch2->attach($widget2, -pod => 'description');

DESCRIPTION
===========

   *ContextHelp* provides a context-sensitive help system. By activating
the help system (either by clicking on a *HelpButton* or calling the
activate method, the cursor changes to a left pointer with a question mark
and the user may click on any widget in the window to get a help message
or jump to the corresponding pod entry.

   *ContextHelp* accepts all the options that the Label widget accepts. In
addition, the following options are also recognized.

*-callback*
     Set a callback to be called on each state change (useful for own
     HelpButton implementations).

*-cursor*
     Use another cursor for the help mode instead of the left pointer with
     question mark.

*-helpkey*
     Enable use of a help key. A common choice would be "F1" (or written as
     "<F1>") or maybe "<Help>", if your keyboard has a help key.

*-offcursor*
     Use another cursor for the help mode shown if the underlying widget is
     not attached to the help system. The default is a left pointer with a
     strike-through question mark.

*-podfile*
     Set the pod file for the *-pod* argument of attach. The default is $0
     (the current script).

*-stayactive*
     If set to true, help mode is active until set to false. So the user
     may browse over all topics he like.

*-verbose*
     Be verbose if something goes wrong. Default is true.

*-widget*
     Use another widget instead of the default Label for displaying
     messages. Another possible choice would be Message.

METHODS
=======

   The *ContextHelp* widget supports the following non-standard methods:

*attach(*widget, option)
     Attaches the widget indicated by widget to the context-sensitive help
     system. Option may be one of the following:

    *-msg*
          The argument is the message to be shown in a popup window.

    *-pod*
          The argument is a regular expression to jump in the
          corresponding pod file. For example, if you have a topic
          DESCRIPTION where you want to jump to, you can specify

               $contexthelp->attach($widget, -pod => '^\s*DESCRIPTION');

    *-podfile*
          The argument is a pod name to be used instead of the default pod
          file.  *-podfile* may be used together with *-pod* or all alone.

    *-command*
          The argument is a user-defined command to be called when
          activating the help system on this widget.

*detach(*widget)
     Detaches the specified widget widget from the help system.

activate
     Turn the help system on.

deactivate
     Turn the help system off.

toggle
     Toggle help system on or off.

*HelpButton(*top, options)
     Create a help button. It is a regular Button with *-bitmap* set to
     the help cursor bitmap and *-command* set to activation of the help
     system. The argument top is the parent widget, options are additional
     options for the help button.

     The button stays pressed as the help is activated. Clicking on the
     pressed button causes the end of the help mode. Clicking with
     mousebutton-3 causes the help system to stay active until the user
     clicks on the button over again.

BUGS
====

   * The user cannot click on the border of an attached widget to raise the
     help window.

   * While in help mode, it is possible to click on buttons even if the
     buttons aren't attached to the help system. This is non-intuitive, but
     hard to fix. (Maybe a solution: create inputo-widgets for all
     not-attached widgets while in context mode)

TODO
====

     * optional use of html browsers (netscape -remote openURL ...)

     * on Win32, make InputO work and use the native help system

AUTHOR
======

   Slaven Rezic <`eserte@cs.tu-berlin.de'>

   Some code and documentation is derived from Rajappa Iyer's
*Tk::Balloon*.

   Copyright (c) 1998,2000 Slaven Rezic. All rights reserved.  This
package is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   Tk::Balloon(3), Tk::Pod(3).

a geometry manager for scaling two subwidgets
*********************************************

NAME
====

   Tk::CornerBox - a geometry manager for scaling two subwidgets

SYNOPSIS
========

     use Tk;

     use Tk::CornerBox;

     my $l_MainWindow = MainWindow->new();

     my $l_Corner = $l_MainWindow->CornerBox();

     $l_Corner->place
        (
         '-width' => 20,
         '-height' => 20,
         '-relx' => 1,
         '-rely' => 1,
         '-anchor' => 'se',
         '-x' => -3,
         '-y' => -3,
        );

     Tk::MainLoop();

DESCRIPTION
===========

   The CornerBox is a simple textured widget that allows you to resize the
window its in by dragging it.  You use it by creating one in the regular
Tk manner and (preferably) packing or placing it in the lower right corner
of your window. It is frame derived and should act accordingly.

AUTHORS
=======

   Damion K. Wilson, dkw@rcm.bm

   Based on the little corner drag widget that you see all over the place.

   Hey, I know it's a M$oft thingy but I've got to integrate my Perl/Tk
apps into that environment.

HISTORY    February 1999: Actually started using it
===================================================

Tix Display Items
*****************

NAME
====

   Tk::DItem - Tix Display Items

DESCRIPTION
===========

   The Tix *Display Items* and *Display Types* are devised to solve a
general problem: many Tix widgets (both existing and planned ones) display
many items of many types simultaneously.

   For example, a hierarchical listbox widget (see Tk/HList)
can display items of images, plain text and subwindows in the
form of a hierarchy. Another widget, the tabular listbox widget (see
Tk/TList) also displays items of the same types, although it
arranges the items in a tabular form. Yet another widget, the spreadsheet
widget (see Tk/TixGrid), also displays similar types
items, but in yet another format.

   In these examples, the display items in different widgets are only
different in how they are arranged by the *host widget*. In Tix, display
items are clearly separated from the host widgets. The advantage is
two-fold: first, the creation and configuration of display items become
uniform across different host widgets. Second, new display item types can
be added without the need to modify the existing host widgets.

   In a way, Tix display items are similar to the items inside Tk the
canvas widget. However, unlike the Tix display items, the canvas items are
not independent of the canvas widget; this makes it impossible to use the
canvas items inside other types of TK widgets.

   The appearance of a display item is controlled by a set of attributes.
It is observed that each the attributes usually fall into one of two
categroies: "*individual*" or "*collective*". For example, the text items
inside a HList widget may all display a different text string; however, in
most cases, the text items share the same color, font and spacing. Instead
of keeping a duplicated version of the same attributes inside each display
item, it will be advantageous to put the collective attributes in a
special object called a *display style*. First, there is the space
concern: a host widget may have many thousands of items; keeping
dupilcated attributes will be very wasteful. Second, when it becomes
necessary to change a collective attribute, such as changing all the text
items' foreground color to red, it will be more efficient to change only
the display style object than to modify all the text items one by one.

   The attributes of the a display item are thus stored in two places: it
has a set of *item options* to store its individual attributes. Each
display item is also associated with a *display style*, which specifies
the collective attributes of all items associated with itself.

   The division between the individual and collective attributes are fixed
and cannot be changed. Thus, when it becomes necessary for some items to
differ in their collective attributes, two or more *display styles* can be
used. For example, suppose you want to display two columns of text items
inside an HList widget, one column in red and the other in blue. You can
create a TextStyle object called "$red" which defines a red foreground,
and another called "$blue", which defines a blue foreground. You can then
associate all text items of the first column to "$red" and the second
column to "$blue"

DISPLAY ITEM TYPES AND OPTIONS
==============================

   Currently there are three types of display items: text, *imagetext* and
window.

IMAGETEXT ITEMS
===============

   Display items of the type *imagetext* are used to display an image
together with a text string. Imagetext items support the following options:

Imagetext Item Options
----------------------

Name:	bitmap
Class:	Bitmap
Switch:	*-bitmap*
     Specifies the bitmap to display in the item.

Name:	image
Class:	Image
Switch:	*-image*
     Specifies the image to display in the item. When both the *-bitmap*
     and *-image* options are specified, only the image will be displayed.

Name:	*imageTextStyle*
Class:	*ImageTextStyle*
Switch:	*-style*
     Specifies the display style to use for this item. Must be the name of
     a *imagetext* display style that has already be created with
     *ItemStyle*.

Name:	*showImage*
Class:	*ShowImage*
Switch:	*-showimage*
     A Boolean value that specifies whether the image/bitmap should be
     displayed.

Name:	*showText*
Class:	*ShowText*
Switch:	*-showtext*
     A Boolean value that specifies whether the text string should be
     displayed.

Name:	text
Class:	Text
Switch:	*-text*
     Specifies the text string to display in the item.

Name:	underline
Class:	*Underline*
Switch:	*-underline*
     Specifies the integer index of a character to underline in the text
     string in the item.  0 corresponds to the first character of the text
     displayed in the widget, 1 to the next character, and so on.

Imagetext Style Options
-----------------------

   The style information of *imagetext* items are stored in the
*imagetext* display style. The following options are supported:

   STANDARD OPTIONS

   *-activebackground*	*-activeforeground* *-anchor*	*-background*
*-disabledbackground*	*-disabledforeground* *-foreground*	*-font*
-justify	*-padx* *-pady*	*-selectbackground*
*-selectforeground*	*-wraplength*

   See Tk/options, for details of the standard options.

   *STYLE-SPECIFIC OPTIONS*

Name:	gap
Class:	*Gap*
Switch:	*-gap*
     Specifies the distance between the bitmap/image and the text string,
     in number of pixels.

Name:	*textAnchor*
Class:	*TextAnchor*
Switch:	*-textanchor*
     The anchor position on the image to which text part is attached.
     This is a perl/Tk addition. Defaults to e for compatibility with
     standard Tix. The interesting cases are

    n
          Text is centred above the image.

    s
          Text is centred below the image

    e
          Text is centred to right of the image.

    w
          Text is centred to left of the image.

    c
          Text is centred over the image.

     The sw, *se*, ne, and b<nw> cases look rather odd.

     To get items to line up correctly it will usually be necessary to
     specify *-anchor* as well. e.g. with default e then anchoring item as
     a whole w lines images up down left with text stuck to right side.

TEXT ITEMS
==========

   Display items of the type text are used to display a text string in a
widget. Text items support the following options:

Text Item Options
-----------------

Name:	*textStyle*
Class:	*TextStyle*
Switch:	*-style*
     Specifies the display style to use for this text item. Must be the
     name of a text display style that has already be created with
     *ItemStyle*.

Name:	text
Class:	Text
Switch:	*-text*
     Specifies the text string to display in the item.

Name:	underline
Class:	*Underline*
Switch:	*-underline*
     Specifies the integer index of a character to underline in the item.
     0 corresponds to the first character of the text displayed in the
     widget, 1 to the next character, and so on.

Text Style Options
------------------

   STANDARD OPTIONS

   *-activebackground*	*-activeforeground* *-anchor*	*-background*
*-disabledbackground*	*-disabledforeground* *-foreground*	*-font*
-justify	*-padx* *-pady*	*-selectbackground*
*-selectforeground*	*-wraplength*

   See Tk/options, for details of the standard options.

WINDOW ITEMS
============

   Display items of the type window are used to display a sub-window in a
widget. Window items support the following options:

Window Item Options
-------------------

Name:	*windowStyle*
Class:	*WindowStyle*
Switch:	*-style*
     Specifies the display style to use for this window item. Must be the
     name of a window display style that has already be created with the
     *ItemStyle* method.

Name:	window
Class:	Window
Switch:	*-window*
Alias:	*-widget*
     Specifies the sub-window to display in the item.

Window Style Options
--------------------

   *STYLE STANDARD OPTIONS*

   *-anchor*	*-padx*	*-pady*

   See Tk/options, for details of the standard options.

CREATING DISPLAY ITEMS
======================

   Display items do not exist on their and thus they cannot be created
independently of the widgets they reside in. As a rule, display items are
created by special methods of their "host" widgets. For example, the HList
widgets has a method item which can be used to create new display items.
The following code creates a new text item at the third column of the
entry foo inside an HList widget:

     my $hlist = $parent->HList(-columns=>3);
     $hlist->add('foo');
     $hlist->itemCreate('foo', 2, -itemtype=>'text', -text=>'Hello');

   The *itemCreate* method of the HList widget accepts a variable number
of arguments. The special argument *-itemtype* specifies which type of
display item to create. Options that are valid for this type of display
items can then be specified by one or more *option-value* pairs.

   After the display item is created, they can then be configured or
destroyed using the methods provided by the host widget. For example, the
HList widget has the methods *itemConfigure*, *itemCget* and *itemDelete*
for accessing the display items.

CREATING AND MANIPULATING ITEM STYLES
=====================================

   Item styles are created with *ItemStyle*:

SYNOPSIS
========

      $widget->*ItemStyle*(*itemType* ?,*-stylename*=>name?
?,*-refwindow*=>*pathName*? ?,option=>value, ...>?);

   *itemType* must be one of the existing display items types such as
text, *imagetext*, window or any new types added by the user. Additional
arguments can be given in one or more *option-value* pairs. option can be
any of the valid option for this display style or any of the following:

*-stylename* => name
     Specifies a name for this style. If unspecified, then a default name
     will be chosen for this style.

*-refwindow* => *$otherwidget*
     Specifies a window to use for determine the default values of the
     display type. If unspecified, the $widget will be used. Default
     values for the display types can be set via the options database. The
     following example sets the *-disablebackground* and
     *-disabledforeground* options of a text display style via the option
     database:

          $widget->optionAdd('*table.list*disabledForeground' => 'blue');
          $widget->optionAdd('*table.list*disabledBackground' => 'darkgray');
          $widget->ItemStyle('text', -refwindow => $table_list, -fg => 'red');

     By using the option database to set the options of the display styles,
     we can advoid hard-coding the option values and give the user more
     flexibility in customization. See Tk/option, for a
     detailed description of the option database.

STYLE METHODS
=============

   The *ItemStyle* method creates an object.  This object supports the
configure and cget methods described in Tk/options,
which can be used to enquire and modify the options described above.

   The following additional methods are available for item styles:

$style->delete
     Destroy this display style object.

EXAMPLE
=======

   The following example creates two columns of data in a HList widget.
The first column is in red and the second column in blue. The colors of
the columns are controlled by two different text styles. Also, the anchor
and font of the second column is chosen so that the income data is aligned
properly.

     use strict;
     use Tk;
     use Tk::HList;
     use Tk::ItemStyle;

     my $mw = MainWindow->new();

     my $hlist = $mw->HList(-columns=>2)->pack;

     my $red  = $hlist->ItemStyle('text', -foreground=>'#800000');
     my $blue = $hlist->ItemStyle('text', -foreground=>'#000080', -anchor=>'e');

     my $e;
     foreach ([Joe => '$10,000'], [Peter => '$20,000'],
              [Raj => '$90,000'],  [Zinh => '$0']) {
         $e = $hlist->addchild("");
         $hlist->itemCreate($e, 0, -itemtype=>'text',
     		-text=>$_->[0], -style=>$red );
         $hlist->itemCreate($e, 1, -itemtype=>'text',
     		-text=>$_->[1], -style=>$blue);
     }

     Tk::MainLoop;

SEE ALSO
========

   `Tk::HList|Tk::HList' in this node `Tk::TixGrid|Tk::TixGrid' in this
node `Tk::TList|Tk::TList' in this node

KEYWORDS
========

   display item, display style, item style

a date/time widget for perl/Tk
******************************

NAME
====

   Tk::Date - a date/time widget for perl/Tk

SYNOPSIS
========

     use Tk::Date;
     $date_widget = $top->Date->pack;
     $date_widget->get("%x %X");

DESCRIPTION
===========

   Tk::Date implements a date/time widget. There are three ways to input a
date:

   * Using the keyboard to input the digits and the tab key or the mouse
     pointer to move focus between fields.

   * Using up and down cursor keys to increment/decrement the date (only
     with installed Tk::NumEntryPlain widget).

   * Selecting up and down arrow buttons will increment or decrement the
     value of the active field (only with installed Tk::FireButton widget).

The Date/Time Format
--------------------

   Unlike Java, Perl does not have a date/time object. However, it is
possible to use the unix time (seconds since epoch, that is 1st January
1970) as a replacement. This is limited, since on most architectures, the
valid range is between 14th December 1901 and 19th January 2038. For other
dates, it is possible to use a hash notation:

     { y => year,
       m => month,
       d => day,
       H => hour,
       M => minute,
       S => second }

   The abbreviations are derivated from the format letters of strftime.
Note that year is the full year (1998 instead of 98) and month is the real
month number, as opposed to the output of localtime(), where the month is
subtracted by one.

   In this document, the first method will be referred as *unixtime* and
the second method as *datehash*.

STANDARD OPTIONS
================

   Tk::Date descends from Frame and inherits all of its options.

-orient
     Specified orientation of the increment and decrements buttons. May be
     vertical (default) or horizontal.

WIDGET-SPECIFIC OPTIONS
=======================

   Some options are only available if the prerequisite modules from the
Tk-GBARR distribution are installed too.

-allarrows
     If true then all entry fields will obtain arrows. Otherwise only one
     arrow pair for each date and time will be drawn. This option can be
     set only while creating the widget. This option needs the Tk::NumEntry
     widget to be installed.

-bell
     Specifies a boolean value. If true then a bell will ring if the user
     attempts to enter an illegal character (e.g. a non-digit).

-check
     If set to a true value, Tk::Date makes sure that the user can't input
     incorrect dates. This option can be set only while creating the
     widget.

-choices
     Creates an additional choice button. The argument to *-choices* must
     be one of now, `today', yesterday or tomorrow, or an array with a
     combination of those. If only one is used, only a simple button is
     created, otherwise an optionmenu. This option can be set only while
     creating the widget.

     Examples:

          -choices => 'now'
          -choices => ['today', 'yesterday', 'tomorrow']

     It is possible to specify user-defined values. User-defined values
     should be defined as array elements with two elements. The first
     element is the label for the button or optionmenu entry. The second
     element specifies the time associated with this value. It may be
     either a date hash (missing values are set to the current date) or a
     subroutine which calculates unix seconds.

     Here are two examples. The first defines an additional optionmenu
     entry for this year's christmas and the second defines an entry for
     the day before yesterday.

          -choices => ['today',
                               ['christmas' => { 'm' => 12, 'd' => 25}]
                              ]
                  -choices => ['today',
          	     'yesterday',
                               ['the day before yesterday' => sub { time()-86400*2 }]
                              ]

-command
     Specifies a callback which is executed every time after an arrow
     button is selected. The callback is called with the following
     arguments: reference of date widget, field specifier, increment value.
     The field specifier is either "date" or "time" or one of "H", "M",
     "S", "d", "m", "y" for the possible time and date fields.

-datefmt
     This is a sprintf/printf-like format string for setting the order and
     format of the date entries. By default, the format string is
     "%2d.%2m.%4y" meaning a two-character wide day entry, followed by a
     dot, followed by a two-character wide month entry, another dot, and
     finally a four-character wide year entry. The characters are the same
     as in the strftime function (see POSIX). It is also
     possible to use the 'A' letter for displaying the (localized) weekday
     name. See below in the EXAMPLES section for a more US-like date
     format. This option can be set only while creating the widget.

-decbitmap
     Sets the bitmap for the decrease button. Defaults to FireButton's
     default decrease bitmap.

-editable
     If set to a false value, disables editing of the date widget. All
     entries are converted to labels and there are no arrow buttons.
     Defaults to true (widget is editable). This option can be set only
     while creating the widget.

-fields
     Specifies which fields are constructed: date, time or both. Defaults
     to both. This option can be set only while creating the widget.

-incbitmap
     Sets the bitmap for the increase button. Defaults to FireButton's
     default increase bitmap.

-monthmenu
     Use an optionmenu for input of the month.

-monthnames
     Replace the standard month names (either English or as supplied by
     the locale system) with a user-defined array. The argument should be a
     reference to a hash with 12 elements.

-precommand
     Specifies a callback which is executed every time when an arrow button
     is selected and before actually execute the increment or decrement
     command. The callback is called with following arguments: date widget,
     type (either date or time) and increment (+1 or -1). If the callback
     returns with a false value, the increment or decrement command will
     not be executed.

-repeatinterval
     Specifies the amount of time between invokations of the increment or
     decrement. Defaults to 50 milliseconds.

-repeatdelay
     Specifies the amount of time before the increment or decrement is
     first done after the Button-1 is pressed over the widget. Defaults to
     500 milliseconds.

-timefmt
     This is a sprintf/printf-like format string for setting the order and
     format of the time entries. By default, the format string is
     "%2H.%2M.%2S" meaning a two-character wide hour entry, followed by a
     dot, followed by a two-character wide minute entry, another dot, and
     finally a two-character wide seconds entry. The characters are the
     same as in the strftime function (see POSIX). This
     option can be set only while creating the widget.

-selectlabel
     Change label text for choice menu. Defaults to 'Select:'. This option
     can be set only while creating the widget.

-value
     Sets an initial value for the widget. The argument may be *unixtime*,
     *datehash* or now (for the current time).

-varfmt
     Specifies the format of the *-variable* or *-value* argument. May be
     *unixtime* (default) or *datehash*. This option can be set only while
     creating the widget.

-variable
     Ties the specified variable to the widget. (See Bugs)

-weekdays
     Replace the standard weekday names (either English or as supplied by
     the locale system) with a user-defined array. The argument should be a
     reference to a hash with seven elements. The names have to start with
     Sunday.

METHODS
=======

   The Date widget supports the following non-standard method:

get([fmt])
     Gets the current value of the date widget. If fmt is not given or
     equal "%s", the returned value is in unix time (seconds since epoch).
     This should work on all systems.

     Otherwise, fmt is a format string which is fed to strftime.  strftime
     needs the `POSIX|POSIX' in this node module installed and therefore
     may not work on all systems.

EXAMPLES
========

   Display a date widget with only the date field in the format dd/mm/yyyy
and get the value in the same format:

     $date = $top->Date(-datefmt => '%2d/%2m/%4y',
     	  	     -fields => 'date',
     		     -value => 'now')->pack;
     # this "get" only works for systems with POSIX.pm
     $top->Button(-text => 'Get date',
     	       -command => sub { warn $date->get("%d/%m/%Y") })->pack;

   Use the datehash format instead of unixtime:

     $top->Date(-fields  => 'date',
     	     -value   => {'d' => '13', 'm' => '12', 'y' => '1957'},
     	     -varfmt => 'datehash',
     	    )->pack;

NOTES
=====

   Please note that the full set of features only available, if the
Tk-GBARR distribution is also installed. However, the widget also works
without this distribution, only lacking the arrow buttons.

   If the POSIX module is available, localised weekday and month names
will be used instead of English names. Otherwise you have to use the
-weekday and -monthnames options.

BUGS/TODO
=========

     - The -orient option can be only set while creating the widget. Also
       other options are only settable at create time.

     - waiting for a real perl Date/Time object
     - tie interface (-variable) does not work if the date widget gets destroyed
       (see uncommented DESTROY)
     - get and set must use the tied variable, otherwise tieying does no work
       at all
     - -from/-to is missing (limit) (or -minvalue, -maxvalue?)
     - range check (in DateNumEntryPlain::incdec)
     - am/pm
     - more interactive examples are needed for some design issues (how strong
       signal errors? ...)
     - check date-Function
     - optionally use Tk::DateEntry for the date part
     - -command is not fully implemented

SEE ALSO
========

   `Tk|Tk' in this node, `Tk::NumEntryPlain|Tk::NumEntryPlain' in this
node, `Tk::FireButton|Tk::FireButton' in this node, `POSIX|POSIX' in this
node

AUTHOR
======

   Slaven Rezic <eserte@cs.tu-berlin.de>

COPYRIGHT
=========

   Copyright (c) 1997, 1998, 1999, 2000 Slaven Rezic. All rights reserved.
This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Drop down calendar widget for selecting dates.
**********************************************

NAME
====

   Tk::DateEntry - Drop down calendar widget for selecting dates.

SYNOPSIS
========

   $dateentry = $parent->DateEntry (<options>);

DESCRIPTION
===========

   Tk::DateEntry is a drop down widget for selecting dates. It looks like
the BrowseEntry widget with an Entry followed by an arrow button, but in
stead of displaying a Listbox the DateEntry displays a calendar with
buttons for each date. The calendar contains buttons for browsing through
the months.

   When the drop down is opened, the widget will try to read the current
content of the widget (the -textvariable), and display the month/year
specified. If the variable is entry, or contains invalid data, the current
month is displayed. If one or two digit year is specified, the widget
tries to guess the correct century by using a "100 year window".

REQUIREMENTS
============

   Tk::DateEntry requires Time::Local and POSIX (strftime) (and basic
Perl/Tk of course....)

OPTIONS
=======

-arrowimage => image
     Use alternative image for the arrow button.

-dateformat => integer
     Specify dateformat to use:

          1 = MM/DD/YYYY - default.

          2 = YYYY/MM/DD

          3 = DD/MM/YYYY

     See also "DATE FORMATS" below.

-parsecmd => \&callback
     In stead of using one of the builtin dateformats, you can specify your
     own by supplying a subroutine for parsing (-parsecmd) and formatting
     (-formatcmd) of the date string. These options overrides -dateformat.
     See "DATE FORMATS" below.

-formatcmd => \&callback
     See -parsecmd above and "DATE FORMATS" below.

-background => color
     Sets the background color for the Entry subwidget. Note that the
     dropdown calendar is not affected by this option. See also
     -boxbackground, -buttonbackground and -todaybackground.

-buttonbackground => color
     Sets the background color for all button in the dropdown calendar.

-boxbackground => color
     Sets the background color for the dropdown widget (not including the
     buttons).

-todaybackground => color
     Sets the background color for the button representing the current
     date.

-font => font
     Sets the font for all subwidgets.

-daynames => [qw/Sun Mon Tue Wed Thu Fri Sat/]
     Specifies the daynames which is used in the calendar heading.  The
     default is [qw/S M Tu W Th F S/]. Note that the array MUST begin with
     the name of Sunday, even if -weekstart specifies something else than
     0 (which is Sunday). See also "WEEKS" below.

-weekstart => number
     Use this if you don't want the weeks to start on Sundays. Specify a
     number between 0 (Sunday) and 6 (Saturday). See "WEEKS" below.

-headingfmt => string
     Format for the Month name heading. The month name heading is created
     by calling strftime(format,0,0,0,1,month,year). Default format is '%B
     %Y'.  Note that only month and year will have sensible values,
     including day and/or time in the heading is possible, but it makes no
     sense.

-state => string
     'normal', 'disabled' or 'readonly'. The latter forces the user to use
     the drop down, editing in the Entry subwidget is disabled.

-width => number
     Width of the Entry subwidget, default is 10 (which fits the default
     date format MM/DD/YYYY).

     All other options are handled by the Entry subwidget.

DATE FORMATS
============

   The default date format is MM/DD/YYYY. Since Tk::DateEntry has to parse
the date to decide which month to display, you can't specify strftime
formats directly (like "-dateformat => 'Date: %D. %B'").

   The "builtin" date formats are:

     -dateformat => 1       - MM/DD/YYYY (default)

     -dateformat => 2       - YYYY/MM/DD

     -dateformat => 3       - DD/MM/YYYY

   Trailing fields that are missing will be replaced by the current date,
if the year is specified by one or two digits, the widget will guess the
century by using a "100 year window".

   If you're not satisified with any of these formats, you might specify
your own parse- and format routine by using the -parsecmd and -formatcmd
options.

   The -parsecmd subroutine will be called whenever the pulldown is opened.
The subroutine will be called with the current content of -textvariable as
the only argument. It should return a three element list: (year, month,
day).  Any undefined elements will be replaced by default values.

   The -formatcmd subroutine will be called whenever the user selects a
date.  It will be called with three arguments: (year, month, day). It
should return a single string which will be assigned to the -textvariable.

   See "EXAMPLES" below.

WEEKS
=====

   The default is to display the calendar the same way as the unix "cal"
command does: Weeks begin on Sunday, and the daynames are S, M, Tu, W, Th,
F, and S.

   However, some people prefer to start the weeks at Monday (saving both
Saturday and Sunday to the weekEND...)  This can be achived by specifying
-weekstart=>1. -weekstart=>0 causes the week to start at Sunday, which is
the default. If you have a very odd schedule, you could also start the
week at Wednesday by specifying -weekstart=>3 .....

   If you don't like the "cal" headings, you might specify something else
by using the -daynames option.

   See "EXAMPLES" below.

EXAMPLES
========

The simplest way:
-----------------

     $parent-&>DateEntry-&>pack;

Other daynames:
---------------

   If you want the "locale's abbreviated weekday name" you do it like this:

     use POSIX qw/strftime/;
     my @daynames=();
     foreach (0..6) {
     	push @daynames,strftime("%a",0,0,0,1,1,1,$_);
     }
     $parent->DateEntry(-daynames=>\@daynames)->pack;

Other date formats:
-------------------

   A Norwegian would probably do something like this:

     my $dateentry=$parent->DateEntry
     	(-weekstart=>1,
     	 -daynames=>[qw/Son Man Tir Ons Tor Fre Lor/],
     	 -parsecmd=>sub {
     		my ($d,$m,$y) = ($_[0] =~ m/(\d*)\/(\d*)-(\d*)/);
     		return ($y,$m,$d);
     	 },
     	 -formatcmd=>sub {
     		sprintf ("%d/%d-%d",$_[2],$_[1],$_[0]);
     	 }
     	)->pack;

   Note that this -parsecmd will return (undef,undef,undef) even if one or
two of the fields are present. A more sophisticated regex might be
needed....

CAVEATS
=======

   Tk::DateEntry uses timelocal(), localtime() and strftime().  These
functions are based on the standard unix time representation, which is the
number of seconds since 1/1/1970.

   This means that Tk::DateEntry don't support dates prior to 1970, and on
a 32 bit computer it don't support dates after 12/31/2037.

SEE ALSO
========

   Tk::Entry

Base class for widgets derived from others
******************************************

NAME
====

   Tk::Derived - Base class for widgets derived from others

SYNOPSIS
========

     package Tk::Whatever;
     require Tk::Something;
     require Tk::Derived;

     @ISA = qw(Tk::Derived Tk::Something);

     sub Populate
     {
      my ($cw,$args) = @_;
      ...
      $cw->SUPER::Populate($args);
      $cw->ConfigSpecs(...);
      ...
     }

DESCRIPTION
===========

   Tk::Derived is used with perl5's multiple inheritance to override some
methods normally inherited from Tk::Widget.

   Tk::Derived should precede any Tk widgets in the class's @ISA.

   Tk::Derived's main purpose is to apply wrappers to configure and cget
methods of widgets to allow the derived widget to add to or modify
behaviour of the configure options supported by the base widget.

   The derived class should normally override the Populate method provided
by Tk::Derived and call ConfigSpecs to declare configure options.

   The public methods provided by Tk::Derived are as follows:

->ConfigSpecs(-key => [*kind*, name, Class, default], ...)
SEE ALSO
========

   `Tk::ConfigSpecs|Tk::ConfigSpecs' in this node `Tk::mega|Tk::mega' in
this node

an alternative to the scale widget
**********************************

NAME
====

   Dial - an alternative to the scale widget

SYNOPSIS
========

     use Tk::Dial;

     $dial = $top->Dial(-margin =>  20,
     		    -radius =>  48,
     		    -min    =>	 0,
     		    -max    => 100,
     		    -value  =>   0,
     		    -format => '%d');

     margin - blank space to leave around dial
     radius - radius of dial
     min, max - range of possible values
     value  - current value
     format - printf-style format for displaying format

   Values shown above are defaults.

DESCRIPTION
===========

   A dial looks like a speedometer: a 3/4 circle with a needle indicating
the current value.  Below the graphical dial is an entry that displays the
current value, and which can be used to enter a value by hand.

   The needle is moved by pressing button 1 in the canvas and dragging. The
needle will follow the mouse, even if the mouse leaves the canvas, which
allows for high precision. Alternatively, the user can enter a value in
the entry space and press Return to set the value; the needle will be set
accordingly.

TO DO
=====

     Configure
     Tick marks
     Step size

AUTHORS
=======

   Roy Johnson, rjohnson@shell.com

   Based on a similar widget in XV, a program by John Bradley,
bradley@cis.upenn.edu

HISTORY    August 1995: Released for critique by pTk mailing list
=================================================================

Create modal dialog and wait for a response.
********************************************

NAME
====

   Tk::Dialog - Create modal dialog and wait for a response.

SYNOPSIS
========

       *$dialog* = *$parent*->*Dialog*(*-option* => value, ... );

DESCRIPTION
===========

   This procedure is part of the Tk script library - its arguments
describe a dialog box.  After creating a dialog box, *Dialog* waits for
the user to select one of the buttons either by clicking on the button
with the mouse or by typing return to invoke the default button (if any).
Then it returns the text string of the selected button.

   While waiting for the user to respond, *Dialog* sets a local grab.
This prevents the user from interacting with the application in any way
except to invoke the dialog box.  See Show() method.

   The following option/value pairs are supported:

*-title*
     Text to appear in the window manager's title bar for the dialog.

*-text*
     Message to appear in the top portion of the dialog box.

*-bitmap*
     If non-empty, specifies a bitmap to display in the top portion of the
     dialog, to the left of the text.  If this is an empty string then no
     bitmap is displayed in the dialog.

*-default_button*
     Text label string of the button that displays the default ring.

*-buttons*
     A reference to a list of button label strings.  Each string specifies
     text to display in a button, in order from left to right.

METHODS
=======

`$answer = $dialog->*Show*(?-global?);'
     This method displays the dialog, waits for the user's response, and
     stores the text string of the selected button in `$answer'.  If
     *-global* is specified a global (rather than local) grab is performed.

EXAMPLE
=======

   *$dialog* = *$mw*->*Dialog*(-text => 'Save File?', -bitmap =>
'question', -title => 'Save File Dialog', -default_button => 'Yes',
-buttons => [qw/Yes No Cancel/);

KEYWORDS
========

   bitmap, dialog, modal, messageBox

create and manipulate a dialog screen.
**************************************

NAME
====

   Tk::DialogBox - create and manipulate a dialog screen.

SYNOPSIS
========

     use Tk::DialogBox
     ...
     $d = $top->DialogBox(-title => "Title", -buttons => ["OK", "Cancel"]);
     $w = $d->add(Widget, args);
     ...
     $button = $d->Show;

DESCRIPTION
===========

   *DialogBox* is very similar to *Dialog* except that it allows any
widget in the top frame. *DialogBox* creates two frames--"top" and
"bottom". The bottom frame shows all the specified buttons, lined up from
left to right. The top frame acts as a container for all other widgets
that can be added with the *add()* method. The non-standard options
recognized by *DialogBox* are as follows:

*-title*
     Specify the title of the dialog box. If this is not set, then the
     name of the program is used.

*-buttons*
     The buttons to display in the bottom frame. This is a reference to an
     array of strings containing the text to put on each button. There is
     no default value for this. If you do not specify any buttons, no
     buttons will be displayed.

*-default_button*
     Specifies the default button that is considered invoked when user
     presses <Return> on the dialog box. This button is highlighted. If no
     default button is specified, then the first element of the array
     whose reference is passed to the *-buttons* option is used as the
     default.

METHODS
=======

   *DialogBox* supports only two methods as of now:

add(widget, options)
     Add the widget indicated by widget. *Widget* can be the name of any
     Tk widget (standard or contributed). Options are the options that the
     widget accepts. The widget is advertized as a subwidget of
     *DialogBox*.

*Show(**grab*)
     Display the dialog box, until user invokes one of the buttons in the
     bottom frame. If the grab type is specified in *grab*, then Show uses
     that grab; otherwise it uses a local grab. Returns the name of the
     button invoked.

BUGS
====

   There is no way of removing a widget once it has been added to the top
frame.

   There is no control over the appearance of the buttons in the bottom
frame nor is there any way to control the placement of the two frames with
respect to each other e.g. widgets to the left, buttons to the right
instead of widgets on the top and buttons on the bottom always.

AUTHOR
======

   *Rajappa Iyer* rsi@earthling.net

   This code is distributed under the same terms as Perl.

Create and manipulate DirTree widgets
*************************************

NAME
====

   Tk::DirTree - Create and manipulate DirTree widgets

SYNOPSIS
========

       *use Tk::DirTree;*

       *$dirtree* = *$parent*->*DirTree*(?options?);

SUPER-CLASS
===========

   The *DirTree* class is derived from the `Tree|Tk::Tree' in this node
class and inherits all the methods, options and subwidgets of its
super-class.

STANDARD OPTIONS
================

   Tree supports all the standard options of a Tree widget.  See
Tk/options, for details on the standard options.

WIDGET-SPECIFIC OPTIONS
=======================

Name:		*browseCmd*
Class:		*BrowseCmd*
Switch:		*-browsecmd*
     Specifies a `callback|Tk::callbacks' in this node to call whenever
     the user browses on a directory (usually by single-clicking on the
     name of the directory). The callback is called with one argument, the
     complete pathname of the directory.

Name:		command
Class:		Command
Switch:		*-command*
     Specifies the `callback|Tk::callbacks' in this node to be called when
     the user activates on a directory (usually by double-clicking on the
     name of the directory). The callback is called with one argument, the
     complete pathname of the directory.

Name:		*dircmd*
Class:		*DirCmd*
Switch:		*-dircmd*
     Specifies the `callback|Tk::callbacks' in this node to be called when
     a directory listing is needed for a particular directory. If this
     option is not specified, by default the DirTree widget will attempt
     to read the directory as a Unix directory. On special occasions, the
     application programmer may want to supply a special method for
     reading directories: for example, when he needs to list remote
     directories. In this case, the *-dircmd* option can be used. The
     specified callback accepts two arguments: the first is the name of
     the directory to be listed; the second is a Boolean value indicating
     whether hidden sub-directories should be listed. This callback
     returns a list of names of the sub-directories of this directory. For
     example:

          sub read_dir {
              my( $dir, $showhidden ) = @_;
              return( qw/DOS NORTON WINDOWS/ ) if $dir eq "C:\\";
              return();
          }

Name:		*showHidden*
Class:		*ShowHidden*
Switch:		*-showhidden*
     Specifies whether hidden directories should be shown. By default, a
     directory name starting with a period "." is considered as a hidden
     directory. This rule can be overridden by supplying an alternative
     *-dircmd* option.

Name:		directory
Class:		Directory
Switch:		*-directory*
Alias:		*-value*
     Specifies the name of the current directory to be displayed in the
     DirTree widget.

DESCRIPTION
===========

   The *DirTree* constructor method creates a new window (given by the
$dirtree argument) and makes it into a DirTree widget.  Additional options,
described above, may be specified on the command line or in the option
database to configure aspects of the DirTree such as its cursor and
relief.  The DirTree widget displays a list view of a directory, its
previous directories and its sub-directories. The user can choose one of
the directories displayed in the list or change to another directory.

WIDGET METHODS
==============

   The *DirTree* method creates a widget object.  This object supports the
configure and cget methods described in Tk/options,
which can be used to enquire and modify the options described above.  The
widget also inherits all the methods provided by the generic
`Tk::Widget|Tk::Widget' in this node class.

   The following additional methods are available for DirTree widgets:

*$dirtree*->chdir(dir)
     Change the current directory to dir.

BINDINGS
========

   The mouse and keyboard bindings of the DirTree widget are the same as
the bindings of the `Tree|Tk::Tree' in this node widget.

KEYWORDS
========

   directory, tree, tix

SEE ALSO
========

   `Tk::Tree|Tk::Tree' in this node `Tk::HList|Tk::HList' in this node

AUTHOR
======

   Perl/TK version by Chris Dean <ctdean@cogit.com>.  Original Tcl/Tix
version by Ioi Kim Lam.

A multicolumn list widget with sortable & sizeable columns
**********************************************************

NAME
====

   Tk::DockFrame - A multicolumn list widget with sortable & sizeable
columns

SYNOPSIS
========

     use Tk::DockFrame;

     $DockPort = $parent->DockPort();

     $DockPort->pack();

     $DockFrame = $parent->DockFrame
        (
         '-dock' => $DockPort,
         '-trimcount' => 1,
         '-sensitivity' => 10,
         '-decorate' => 0,
         '-trimgap' => 2
        );

     $DockFrame->Widget (...)->pack();

     ...

     Tk::MainLoop;

DESCRIPTION
===========

   The two public classes in this module combine to implement a dockable
widget subsystem.

   Objects of class DockFrame are simple frames which can be made to
"float" free as Toplevel widgets or packed as Frames. Dockframes can have
any number of direct children but the favored use is to pack a single
Frame based child widget and add widgets to that using any geometry
manager.

   DockPorts are simple frame widgets which must be managed by the packer.
They normally have no width or height and are thus rendered invisible.
DockFrame children of the same parentage, when dragged over them, will be
converted from "floating" Toplevels into Frame widgets rendered within the
DockPort, resizing it accordingly.

IMPORTANT UPDATE
     The DockFrames are now managed WITHIN the DockPorts, therefore any
     geometry manager can be used with all the widgets described here

STANDARD OPTIONS
================

DockFrame
     *-background -borderwidth -relief -bg -width -height*

DockPort
     none

   See Tk for details of the standard options.

WIDGET-SPECIFIC OPTIONS
=======================

Name:	*dock*
Class:	*Dock*
Switch:	*-dock*
     Used to "dock" a DockFrame to a DockPort. The parameter passed must be
     a reference to a DockPort and nothing else. If a DockPort is not
     specified in this manner on creation, then the DockFrame will
     initially "float" free.

Name:	*trimcount*
Class:	*TrimCount*
Switch:	*-trimcount*
     Specifies the number of button trim drag 'handles'. Specifying 0 will
     prevent attachment/detachment of the DockFrame.

Name:	*sensitivity*
Class:	*Sensitivity*
Switch:	*-sensitivity*
     The DockFrame will "dock" when it gets within the specified number of
     pixels of the DockPort.

Name:	*decorate*
Class:	*Decorate*
Switch:	*-decorate*
     Boolean value indicating whether or not to instruct the window
     manager to add decoration (titlebar, etc) to the undocked DockFrame.
     It is important to note here that, due to the nature of the event
     handling, dragging the DockFrame by the titlebar will not cause it to
     dock.

Name:	*trimgap*
Class:	*Trimgap*
Switch:	*-trimgap*
     This option specifies the number of pixels to leave between the
     "handles" and the first child widget

WIDGET METHODS
==============

*$DockFrame*->*dock* (*$DockPort*)
     Immediately docks the DockFrame to the specified DockPort

*$DockFrame*->*undock*()
     Immediately undocks the DockFrame

BINDINGS
========

[1]
     Pressing and holding the left mouse button on a DockFrame trim
     element allows movement of that DockFrame. If the DockFrame is
     "dragged" over a DockPort, it will "dock" and dragging will cease
     until the "handle" is released and then selected again.

AUTHORS
=======

   Damion K. Wilson, dwilson@ibl.bm, http://pwp.ibl.bm/~dkw

COPYRIGHT
=========

   Copyright (c) 1999 Damion K. Wilson.

   All rights reserved.

   This program is free software, you may redistribute it and/or modify it
under the same terms as Perl itself.

HISTORY
=======

*October 1, 1999*: Written to replace experimental Tk::DockingGroup with no legacy support

private class used by Drag&Drop
*******************************

NAME
====

   Tk::DragDrop::Common - private class used by Drag&Drop

DESCRIPTION
===========

   This class provides methods to automate the the loading and declaring
of Drop and Site 'types'.

Constants for Sun's Drag&Drop protocol
**************************************

NAME
====

   Tk::DragDrop::SunConst - Constants for Sun's Drag&Drop protocol

DESCRIPTION
===========

   This module defines symbolic name subs for the numeric constants that
make up Sun's Drag&Drop protocol. They are in this module with Exporter as
they are shared between the two halves (Dropper and Receiver) of the
protocol.

Receive side of Drag & Drop abstraction
***************************************

NAME
====

   Tk::DropSite - Receive side of Drag & Drop abstraction

     use Tk::DropSite qw(...);
     $widget->DropSite(-entercommand => ...,
                       -dropcommand  => ...,
                       -motioncommand  => ...,
                       -dropcommand  => ...,
                      );

DESCRIPTION
===========

   `DropSite' creates an object which represents a site on which things
may be "Dropped".

   A DropSite provides the following methods:

   =over 4

$site->Enter($token,$event)
$site->Leave($token,$event)
$site->Motion($token,$event)
$site->Drop($token,$event)

Create and manipulate Entry widgets
***********************************

NAME
====

   Tk::Entry - Create and manipulate Entry widgets

       $entry = *$parent*->Entry(?options?);

STANDARD OPTIONS
================

   *-background*	*-highlightbackground*	*-insertontime*	*-selectforeground*
*-borderwidth*	*-highlightcolor*	*-insertwidth*	*-takefocus*
*-cursor*	*-highlightthickness*	-justify	*-textvariable*
*-exportselection*	*-insertbackground*	*-relief*	*-xscrollcommand*
*-font*	*-insertborderwidth*	*-selectbackground*
*-foreground*	*-insertofftime*	*-selectborderwidth*

WIDGET-SPECIFIC OPTIONS
=======================

Name:	*invalidCommand*
Class:	*InvalidCommand*
Switch:	*-invalidcommand*
Alias:	*-invcmd*
     Specifies a script to eval when *validateCommand* returns 0.  Setting
     it to <undef> disables this feature (the default).  The best use of
     this option is to set it to *bell*.  See *Validation* below for more
     information.

Name:	show
Class:	Show
Switch:	*-show*
     If this option is specified, then the true contents of the entry are
     not displayed in the window.  Instead, each character in the entry's
     value will be displayed as the first character in the value of this
     option, such as "*".  This is useful, for example, if the entry is to
     be used to enter a password.  If characters in the entry are selected
     and copied elsewhere, the information copied will be what is
     displayed, not the true contents of the entry.

Name:	state
Class:	State
Switch:	*-state*
     Specifies one of two states for the entry:  normal or disabled.  If
     the entry is disabled then the value may not be changed using widget
     methods and no insertion cursor will be displayed, even if the input
     focus is in the widget.

Name:	validate
Class:	*Validate*
Switch:	*-validate*
     Specifies the mode in which validation should operate: none, focus,
     focusin, focusout, key, or all.  It defaults to none.  When you want
     validation, you must explicitly state which mode you wish to use.
     See *Validation* below for more.

Name:	*validateCommand*
Class:	*ValidateCommand*
Switch:	*-validatecommand*
Alias:	*-vcmd*
     Specifies a script to eval when you want to validate the input into
     the entry widget.  Setting it to undef disables this feature (the
     default).  This command must return a valid boolean value.  If it
     returns 0 (or the valid boolean equivalent) then it means you reject
     the new edition and it will not occur and the *invalidCommand* will
     be evaluated if it is set. If it returns 1, then the new edition
     occurs.  See *Validation* below for more information.

Name:	width
Class:	Width
Switch:	*-width*
     Specifies an integer value indicating the desired width of the entry
     window, in average-size characters of the widget's font.  If the
     value is less than or equal to zero, the widget picks a size just
     large enough to hold its current text.

DESCRIPTION
===========

   The Entry method creates a new window (given by the $entry argument)
and makes it into an entry widget.  Additional options, described above,
may be specified on the command line or in the option database to
configure aspects of the entry such as its colors, font, and relief.  The
entry command returns its $entry argument.  At the time this command is
invoked, there must not exist a window named $entry, but $entry's parent
must exist.

   An entry is a widget that displays a one-line text string and allows
that string to be edited using methods described below, which are
typically bound to keystrokes and mouse actions.  When first created, an
entry's string is empty.  A portion of the entry may be selected as
described below.  If an entry is exporting its selection (see the
*exportSelection* option), then it will observe the standard X11 protocols
for handling the selection;  entry selections are available as type STRING.
Entries also observe the standard Tk rules for dealing with the input
focus.  When an entry has the input focus it displays an *insertion
cursor* to indicate where new characters will be inserted.

   Entries are capable of displaying strings that are too long to fit
entirely within the widget's window.  In this case, only a portion of the
string will be displayed;  methods described below may be used to change
the view in the window.  Entries use the standard *xScrollCommand*
mechanism for interacting with scrollbars (see the description of the
*-xscrollcommand* option for details).  They also support scanning, as
described below.

VALIDATION
==========

   Validation of entry widgets is derived from part of the patch written by
jhobbs@cs.uoregon.edu.  This works by setting the *validateCommand* option
to a callback which will be evaluated according to the validate option as
follows:

none
     Default.  This means no validation will occur.

focus
     *validateCommand* will be called when the entry receives or loses
     focus.

focusin
     *validateCommand* will be called when the entry receives focus.

focusout
     *validateCommand* will be called when the entry loses focus.

key
     *validateCommand* will be called when the entry is edited.

all
     *validateCommand* will be called for all above conditions.

   The *validateCommand* and *invalidCommand* are called with the following
arguments:

   * The proposed value of the entry.  If you are configuring the entry
     widget to have a new textvariable, this will be the value of that
     textvariable.

   * The characters to be added (or deleted). This will be undef if
     validation is due to focus, explcit call to validate or if change is
     due to `-textvariable' changing.

   * The current value of entry i.e. before the proposed change.

   * index of char string to be added/deleted, if any. -1 otherwise

   * type of action. 1 == INSERT, 0 == DELETE, -1 if it's a forced
     validation or textvariable validation

   In general, the *textVariable* and *validateCommand* can be dangerous
to mix. If you try set the *textVariable* to something that the
*validateCommand* will not accept it will be set back to the value of the
entry widget.  Using the *textVariable* for read-only purposes will never
cause problems.

   The *validateCommand* will turn itself off by setting validate to none
when an error occurs, for example when the *validateCommand* or
*invalidCommand* encounters an error in its script while evaluating, or
*validateCommand* does not return a valid boolean value.

   With the perl/Tk version validate option is supposed to be "suspended"
while executing the *validateCommand* or the *invalidCommand*.  This is
experimental but in theory either callback can "correct" the value of the
widget, and override the proposed change. (*validateCommand* should still
return false to inhibit the change from happening when it returns.)

WIDGET METHODS
==============

   The Entry method creates a widget object.  This object supports the
configure and cget methods described in Tk/options,
which can be used to enquire and modify the options described above.  The
widget also inherits all the methods provided by the generic
`Tk::Widget|Tk::Widget' in this node class.

   Many of the additional methods for entries take one or more indices as
arguments.  An index specifies a particular character in the entry's
string, in any of the following ways:

number
     Specifies the character as a numerical index, where 0 corresponds to
     the first character in the string.

anchor
     Indicates the anchor point for the selection, which is set with the
     *selectionFrom* and *selectionAdjust* methods.

end
     Indicates the character just after the last one in the entry's string.
     This is equivalent to specifying a numerical index equal to the length
     of the entry's string.

insert
     Indicates the character adjacent to and immediately following the
     insertion cursor.

sel.first
     Indicates the first character in the selection.  It is an error to
     use this form if the selection isn't in the entry window.

sel.last
     Indicates the character just after the last one in the selection.  It
     is an error to use this form if the selection isn't in the entry
     window.

*@*number
     In this form, number is treated as an x-coordinate in the entry's
     window;  the character spanning that x-coordinate is used.  For
     example, "*@0*" indicates the left-most character in the window.

   Abbreviations may be used for any of the forms above, e.g. "e" or
"*sel.f*".  In general, out-of-range indices are automatically rounded to
the nearest legal value.

   The following additional methods are available for entry widgets:

$entry->*bbox*(index)
     Returns a list of four numbers describing the bounding box of the
     character given by index.  The first two elements of the list give
     the x and y coordinates of the upper-left corner of the screen area
     covered by the character (in pixels relative to the widget) and the
     last two elements give the width and height of the character, in
     pixels.  The bounding box may refer to a region outside the visible
     area of the window.

$entry->delete(*first, *?last?)
     Returns the current value of the configuration option given by option.
     Option may have any of the values accepted by the entry command.

$entry->configure(?option?, ?*value, option, value, ...*?)
     Query or modify the configuration options of the widget.  If no
     option is specified, returns a list describing all of the available
     options for $entry (see `Tk::configure' in this node for information
     on the format of this list).  If option is specified with no value,
     then the command returns a list describing the one named option (this
     list will be identical to the corresponding sublist of the value
     returned if no option is specified).  If one or more *option-value*
     pairs are specified, then the command modifies the given widget
     option(s) to have the given value(s);  in this case the command
     returns an empty string.  Option may have any of the values accepted
     by the entry command.

$entry->delete(*first, *?last?)
     Delete one or more elements of the entry.  First is the index of the
     first character to delete, and last is the index of the character
     just after the last one to delete.  If last isn't specified it
     defaults to first+1, i.e. a single character is deleted.  This method
     returns an empty string.

$entry->get
     Returns the entry's string.

$entry->*icursor*(index)
     Arrange for the insertion cursor to be displayed just before the
     character given by index.  Returns an empty string.

$entry->index(index)
     Returns the numerical index corresponding to index.

$entry->insert(*index, string*)
     Insert the characters of string just before the character indicated
     by index.  Returns an empty string.

$entry->scan(*option, args*)
$entry->scanOption(args)
     This method is used to implement scanning on entries.  It has two
     forms, depending on Option:

    $entry->*scanMark*(x)
          Records x and the current view in the entry widget;  used in
          conjunction with later *scanDragto* methods.  Typically this
          method is associated with a mouse button press in the widget.  It
          returns an empty string.

    $entry->*scanDragto*(x)
          This method computes the difference between its x argument and
          the x argument to the last *scanMark* method for the widget.  It
          then adjusts the view left or right by 10 times the difference
          in x-coordinates.  This method is typically associated with
          mouse motion events in the widget, to produce the effect of
          dragging the entry at high speed through the widget.  The return
          value is an empty string.

$entry->selection(*option, arg*)
$entry->selectionOption(*arg*)
     This method is used to adjust the selection within an entry.  It has
     several forms, depending on Option:

    $entry->*selectionAdjust*(index)
          Locate the end of the selection nearest to the character given by
          index, and adjust that end of the selection to be at index (i.e
          including but not going beyond index).  The other end of the
          selection is made the anchor point for future *selectionTo*
          methods.  If the selection isn't currently in the entry, then a
          new selection is created to include the characters between index
          and the most recent selection anchor point, inclusive.  Returns
          an empty string.

    $entry->*selectionClear*
          Clear the selection if it is currently in this widget.  If the
          selection isn't in this widget then the method has no effect.
          Returns an empty string.

    $entry->*selectionFrom*(index)
          Set the selection anchor point to just before the character
          given by index.  Doesn't change the selection.  Returns an empty
          string.

    $entry->*selectionPresent*
          Returns 1 if there is are characters selected in the entry, 0 if
          nothing is selected.

    $entry->*selectionRange*(*start, *end)
          Sets the selection to include the characters starting with the
          one indexed by start and ending with the one just before end.
          If end refers to the same character as start or an earlier one,
          then the entry's selection is cleared.

    $entry->*selectionTo*(index)
          If index is before the anchor point, set the selection to the
          characters from index up to but not including the anchor point.
          If index is the same as the anchor point, do nothing.  If index
          is after the anchor point, set the selection to the characters
          from the anchor point up to but not including index.  The anchor
          point is determined by the most recent *selectionFrom* or
          *selectionAdjust* method in this widget.  If the selection isn't
          in this widget then a new selection is created using the most
          recent anchor point specified for the widget.  Returns an empty
          string.

$entry->validate
     This command is used to force an evaluation of the *validateCommand*
     independent of the conditions specified by the validate option.  It
     returns 0 or 1.

$entry->*xview*(args)
     This command is used to query and change the horizontal position of
     the text in the widget's window.  It can take any of the following
     forms:

    $entry->*xview*
          Returns a list containing two elements.  Each element is a real
          fraction between 0 and 1;  together they describe the horizontal
          span that is visible in the window.  For example, if the first
          element is .2 and the second element is .7, 20% of the entry's
          text is off-screen to the left, the middle 50% is visible in the
          window, and 30% of the text is off-screen to the right.  These
          are the same values passed to scrollbars via the
          *-xscrollcommand* option.

    $entry->*xview*(index)
          Adjusts the view in the window so that the character given by
          index is displayed at the left edge of the window.

    $entry->*xviewMoveto*(*fraction*)
          Adjusts the view in the window so that the character *fraction*
          of the way through the text appears at the left edge of the
          window.  *Fraction* must be a fraction between 0 and 1.

    $entry->*xviewScroll*(*number, what*)
          This method shifts the view in the window left or right
          according to number and *what*.  Number must be an integer.
          What must be either *units* or *pages* or an abbreviation of one
          of these.  If *what* is *units*, the view adjusts left or right
          by number average-width characters on the display;  if it is
          *pages* then the view adjusts by number screenfuls.  If number
          is negative then characters farther to the left become visible;
          if it is positive then characters farther to the right become
          visible.

DEFAULT BINDINGS
================

   Tk automatically creates class bindings for entries that give them the
following default behavior.  In the descriptions below, "word" refers to a
contiguous group of letters, digits, or "_" characters, or any single
character other than these.

[1]
     Clicking mouse button 1 positions the insertion cursor just before
     the character underneath the mouse cursor, sets the input focus to
     this widget, and clears any selection in the widget.  Dragging with
     mouse button 1 strokes out a selection between the insertion cursor
     and the character under the mouse.

[2]
     Double-clicking with mouse button 1 selects the word under the mouse
     and positions the insertion cursor at the beginning of the word.
     Dragging after a double click will stroke out a selection consisting
     of whole words.

[3]
     Triple-clicking with mouse button 1 selects all of the text in the
     entry and positions the insertion cursor before the first character.

[4]
     The ends of the selection can be adjusted by dragging with mouse
     button 1 while the Shift key is down;  this will adjust the end of
     the selection that was nearest to the mouse cursor when button 1 was
     pressed.  If the button is double-clicked before dragging then the
     selection will be adjusted in units of whole words.

[5]
     Clicking mouse button 1 with the Control key down will position the
     insertion cursor in the entry without affecting the selection.

[6]
     If any normal printing characters are typed in an entry, they are
     inserted at the point of the insertion cursor.

[7]
     The view in the entry can be adjusted by dragging with mouse button 2.
     If mouse button 2 is clicked without moving the mouse, the selection
     is copied into the entry at the position of the mouse cursor.

[8]
     If the mouse is dragged out of the entry on the left or right sides
     while button 1 is pressed, the entry will automatically scroll to
     make more text visible (if there is more text off-screen on the side
     where the mouse left the window).

[9]
     The Left and Right keys move the insertion cursor one character to the
     left or right;  they also clear any selection in the entry and set
     the selection anchor.  If Left or Right is typed with the Shift key
     down, then the insertion cursor moves and the selection is extended
     to include the new character.  Control-Left and Control-Right move
     the insertion cursor by words, and Control-Shift-Left and
     Control-Shift-Right move the insertion cursor by words and also
     extend the selection.  Control-b and Control-f behave the same as
     Left and Right, respectively.  Meta-b and Meta-f behave the same as
     Control-Left and Control-Right, respectively.

[10]
     The Home key, or Control-a, will move the insertion cursor to the
     beginning of the entry and clear any selection in the entry.
     Shift-Home moves the insertion cursor to the beginning of the entry
     and also extends the selection to that point.

[11]
     The End key, or Control-e, will move the insertion cursor to the end
     of the entry and clear any selection in the entry.  Shift-End moves
     the cursor to the end and extends the selection to that point.

[12]
     The Select key and Control-Space set the selection anchor to the
     position of the insertion cursor.  They don't affect the current
     selection.  Shift-Select and Control-Shift-Space adjust the selection
     to the current position of the insertion cursor, selecting from the
     anchor to the insertion cursor if there was not any selection
     previously.

[13]
     Control-/ selects all the text in the entry.

[14]
     Control-\ clears any selection in the entry.

[15]
     The F16 key (labelled Copy on many Sun workstations) or Meta-w copies
     the selection in the widget to the clipboard, if there is a selection.

[16]
     The F20 key (labelled Cut on many Sun workstations) or Control-w
     copies the selection in the widget to the clipboard and deletes the
     selection.  If there is no selection in the widget then these keys
     have no effect.

[17]
     The F18 key (labelled Paste on many Sun workstations) or Control-y
     inserts the contents of the clipboard at the position of the
     insertion cursor.

[18]
     The Delete key deletes the selection, if there is one in the entry.
     If there is no selection, it deletes the character to the right of
     the insertion cursor.

[19]
     The BackSpace key and Control-h delete the selection, if there is one
     in the entry.  If there is no selection, it deletes the character to
     the left of the insertion cursor.

[20]
     Control-d deletes the character to the right of the insertion cursor.

[21]
     Meta-d deletes the word to the right of the insertion cursor.

[22]
     Control-k deletes all the characters to the right of the insertion
     cursor.

[23]
     Control-t reverses the order of the two characters to the right of
     the insertion cursor.

     If the entry is disabled using the *-state* option, then the entry's
     view can still be adjusted and text in the entry can still be
     selected, but no insertion cursor will be displayed and no text
     modifications will take place.

     The behavior of entries can be changed by defining new bindings for
     individual widgets or by redefining the class bindings.

KEYWORDS
========

   entry, widget

Method invoked to process background errors
*******************************************

NAME
====

   Tk::Error - Method invoked to process background errors

   Customization:

     require Tk::ErrorDialog;

   or

     sub Tk::Error
     {
       my ($widget,$error,@locations) = @_;
       ...

     }

DESCRIPTION
===========

   The *Tk::Error* method is invoked by perl/Tk when a background error
occurs. Two possible implementations are provided in the distribution and
individual applications or users can (re)define a *Tk::Error* method (e.g.
as a perl sub) if they wish to handle background errors in some other
manner.

   A background error is one that occurs in a command that didn't
originate with the application.  For example, if an error occurs while
executing a `callback|Tk::callbacks' in this node specified with a
`bind|Tk::bind' in this node or a `after|Tk::after' in this node command,
then it is a background error.  For a non-background error, the error can
simply be returned up through nested subroutines until it reaches the
top-level code in the application; then the application can report the
error in whatever way it wishes.  When a background error occurs, the
unwinding ends in the Tk library and there is no obvious way for Tk to
report the error.

   When Tk detects a background error, it saves information about the
error and invokes the *Tk::Error* method later when Tk is idle.

   *Tk::Error* is invoked by perl/Tk as if by the perl code:

       *$mainwindow*->*Tk::Error*(*"error message"*, *location ...*);

   *$mainwindow* is the *MainWindow* associated with widget which detected
the error, *"error message"* is a string describing the error that has
been detected, location is a list of one or more "locations" which
describe the call sequence at the point the error was detected.

   The locations are a typically a mixture of perl location reports giving
script name and line number, and simple strings describing locations in
core Tk or perl/Tk C code.

   Tk will ignore any result returned by the *Tk::Error* method.  If
another error occurs within the *Tk::Error* method (for example if it
calls die) then Tk reports this error itself by writing a message to
stderr (this is to avoid infinite loops due to any bugs in *Tk::Error*).

   If several background errors accumulate before *Tk::Error* is invoked
to process them, *Tk::Error* will be invoked once for each error, in the
order they occurred.  However, if *Tk::Error* calls *Tk->break*, then any
remaining errors are skipped without calling *Tk::Error*.

   The Tk module includes a default *Tk::Error* subroutine that simply
reports the error on stderr.

   An alternate definition is provided via :

       `require Tk::ErrorDialog;'

   that posts a dialog box containing the error message and offers the
user a chance to see a stack trace showing where the error occurred.

BUGS
====

   If after or *fileevent* are not invoked as methods of a widget then
perl/Tk is unable to provide a *$mainwindow* argument.  To support such
code from earlier versions of perl/Tk perl/Tk therefore calls *Tk::Error*
with string 'Tk' instead: *Tk->Tk::Error\(...\)*.  In this case the
*Tk::Error* in *Tk::ErrorDialog* and similar implementations cannot
"popup" a window as they don't know which display to use.  A mechanism to
supply the *MainWindow* in applications which only have one (a very common
case) should be provided.

SEE ALSO
========

   `Tk::bind|Tk::bind' in this node `Tk::after|Tk::after' in this node
`Tk::fileevent|Tk::fileevent' in this node

KEYWORDS
========

   background error, reporting

ToolKit for Events
******************

NAME
====

   Tk::Event - ToolKit for Events

SYNOPSIS    use Tk::Event;
==========================

     Tk::Event->fileevent(\*FH, 'readable' => callback);

     Tk::Event->lineavail(\*FH, callback);

     use Tk::Event::Signal qw(INT);

     $SIG{'INT'} = callback;

     use Tk::Event::process;

     Tk::Event->proc($pid, callback);

     QueueEvent(callback [, position])

DESCRIPTION
===========

   That is better than nothing but still hard to use. Most scripts want
higher level result (a line, a "block" of data etc.)

   So it has occured to me that we could use new-ish TIEHANDLE thus:

   my $obj = tie SOMEHANDLE,Tk::Event::IO;

   while (<SOMEHANDLE>)  {  }

   Then the READLINE routine registers a callback and looks something like:

   sub READLINE  {   my $obj = shift;   Event->io(*$obj,'readable',sub {
sysread(*$obj,${*$obj},1,length(${*$obj}) });   my $pos;   while (($pos =
index(${*$obj},$/) < 0)    {     DoOneEvent();    }
Event->io(*$obj,'readable',"); # unregister   $pos += length($/);   my
$result = substr(${*$obj},0,$pos);   substr(${*$obj},0,$pos) = ";   return
$result;  }

   This is using the scalar part of the glob representing the _inner_ IO
as a buffer in which to accumulate chars.

ToolKit for Events
******************

NAME
====

   Tk::Event - ToolKit for Events

     Tk::Event->fileevent(\*FH, 'readable' => callback);

     Tk::Event->lineavail(\*FH, callback);

     use Tk::Event::Signal qw(INT);

     $SIG{'INT'} = callback;

     use Tk::Event::process;

     Tk::Event->proc($pid, callback);

     QueueEvent(callback [, position])

DESCRIPTION
===========

   That is better than nothing but still hard to use. Most scripts want
higher level result (a line, a "block" of data etc.)

   So it has occured to me that we could use new-ish TIEHANDLE thus:

   my $obj = tie SOMEHANDLE,Tk::Event::IO;

   while (<SOMEHANDLE>)  {  }

   Then the READLINE routine registers a callback and looks something like:

   sub READLINE  {   my $obj = shift;   Event->io(*$obj,'readable',sub {
sysread(*$obj,${*$obj},1,length(${*$obj}) });   my $pos;   while (($pos =
index(${*$obj},$/) < 0)    {     DoOneEvent();    }
Event->io(*$obj,'readable',"); # unregister   $pos += length($/);   my
$result = substr(${*$obj},0,$pos);   substr(${*$obj},0,$pos) = ";   return
$result;  }

   This is using the scalar part of the glob representing the _inner_ IO
as a buffer in which to accumulate chars.

Entry that reflects its state in the background color
*****************************************************

NAME
====

   Tk::FcyEntry - Entry that reflects its state in the background color

SYNOPSIS
========

     use Tk;
     use Tk::FcyEntry;	# replaces the standard Entry widget
     ...
     $fcye = $w->Entry( ... everything as usual ... );
     ...

DESCRIPTION
===========

   *FcyEntry* is like a normal `Entry|Tk::Entry' in this node widget
except:

   * default background color is 'white'

   * if the state of the widget is disabled the background color is set to
     be the same as the normal background and the foreground used is the
     same as the disabledForeground of a button. (xxx: still not true,
     values hardcoded)

BUGS
====

   background configuration honoured after next state change.

SEE ALSO
========

   `Tk|Tk' in this node `Tk::Entry|Tk::Entry' in this node

KEYWORDS
========

   entry, widget, editcolor

AUTHOR
======

   Achim Bohnet <`ach@mpe.mpg.de'>

   Copyright (c) 1997-1998 Achim Bohnet. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

A highly configurable File Dialog widget for Perl/Tk.
*****************************************************

NAME
====

   Tk::FileDialog - A highly configurable File Dialog widget for Perl/Tk.

DESCRIPTION
===========

   The widget is composed of a number of sub-widgets, namely, a listbox
for files and (optionally) directories, an entry for filename, an
(optional) entry for pathname, an entry for a filter pattern, a 'ShowAll'
checkbox (for enabling display of .* files and directories), and three
buttons, namely OK, Rescan, and Cancel.  Note that the labels for all
subwidgets (including the text for the buttons and Checkbox) are
configurable for foreign language support.

SYNOPSIS
========

Usage Description
-----------------

   To use FileDialog, simply create your FileDialog objects during
initialization (or at least before a Show).  When you wish to display the
FileDialog, invoke the 'Show' method on the FileDialog object;  The method
will return either a file name, a path name, or undef.  undef is returned
only if the user pressed the Cancel button.

Example Code
------------

   The following code creates a FileDialog and calls it.  Note that
perl5.002gamma is required.

          #!/usr/local/bin/perl -w

          use Tk;
          use Tk::FileDialog;
          use strict;

          my($main) = MainWindow->new;
          my($Horiz) = 1;
          my($fname);

          my($LoadDialog) = $main->FileDialog(-Title =>'This is my title',
          				    -Create => 0);

          $LoadDialog->configure(-FPat => '*pl',
          		       -ShowAll => 'NO');

          $main->Entry(-textvariable => \$fname)
          	->pack(-expand => 1,
          	       -fill => 'x');

          $main->Button(-text => 'Kick me!',
          	      -command => sub {
          		  $fname = $LoadDialog->Show(-Horiz => $Horiz);
          		  if (!defined($fname)) {
          		      $fname = "Fine,Cancel, but no Chdir anymore!!!";
          		      $LoadDialog->configure(-Chdir =>'NO');
          		  }
          	      })
          	->pack(-expand => 1,
          	       -fill => 'x');

          $main->Checkbutton(-text => 'Horizontal',
          		   -variable => \$Horiz)
          	->pack(-expand => 1,
          	       -fill => 'x');

          $main->Button(-text => 'Exit',
          	      -command => sub {
          		  $main->destroy;
          	      })
          	->pack(-expand => 1,
          	       -fill => 'x');

          MainLoop;

          print "Exit Stage right!\n";

          exit;

METHODS
=======

     The following non-standard method may be used with a FileDialog object

Show
----

   Displays the file dialog box for the user to operate.  Additional
configuration items may be passed in at Show-time In other words, this
code snippet:

     $fd->Show(-Title => 'Ooooh, Preeeeeety!');

   is the same as this code snippet:

     $fd->configure(-Title => 'Ooooh, Preeeeeety!');
     $fd->Show;

CONFIGURATION
=============

   Any of the following configuration items may be set via the configure
(or Show) method, or retrieved via the cget method.

Flags
-----

   Flags may be configured with either 1,'true', or 'yes' for 1, or 0,
'false', or 'no' for 0. Any portion of 'true', 'yes', 'false', or 'no' may
be used, and case does not matter.

-Chdir
------

     Enable the user to change directories. The default is 1. If disabled,
     the directory list box will not be shown.

-Create
-------

     Enable the user to specify a file that does not exist. If not
     enabled, and the user specifies a non-existent file, a dialog box
     will be shown informing the user of the error (This Dialog Box is
     configurable via the EDlg* switches, below).

     default: 1

-ShowAll
--------

     Determines whether hidden files (.*) are displayed in the File and
     Directory Listboxes.  The default is 0. The Show All Checkbox
     reflects the setting of this switch.

-DisableShowAll
---------------

     Disables the ability of the user to change the status of the ShowAll
     flag. The default is 0 (the user is by default allowed to change the
     status).

-Grab
-----

     Enables the File Dialog to do an application Grab when displayed. The
     default is 1.

-Horiz
------

     True sets the File List box to be to the right of the Directory List
     Box. If 0, the File List box will be below the Directory List box.
     The default is 1.

-SelDir
-------

     If True, enables selection of a directory rather than a file, and
     disables the actions of the File List Box. The default is 0.

Special
-------

-FPat
-----

     Sets the default file selection pattern. The default is '*'. Only
     files matching this pattern will be displayed in the File List Box.

-Geometry
---------

     Sets the geometry of the File Dialog. Setting the size is a dangerous
     thing to do.  If not configured, or set to ", the File Dialog will be
     centered.

-SelHook
--------

     SelHook is configured with a reference to a routine that will be
     called when a file is chosen. The file is called with a sole
     parameter of the full path and file name of the file chosen. If the
     Create flag is disabled (and the user is not allowed to specify new
     files), the file will be known to exist at the time that SelHook is
     called. Note that SelHook will also be called with directories if the
     SelDir Flag is enabled, and that the FileDialog box will still be
     displayed. The FileDialog box should not be destroyed from within the
     SelHook routine, although it may generally be configured.

     SelHook routines return 0 to reject the selection and allow the user
     to reselect, and any other value to accept the selection. If a
     SelHook routine returns non-zero, the FileDialog will immediately be
     withdrawn, and the file will be returned to the caller.

     There may be only one SelHook routine active at any time. Configuring
     the SelHook routine replaces any existing SelHook routine.
     Configuring the SelHook routine with 0 removes the SelHook routine.
     The default SelHook routine is undef.

Strings
-------

   The following two switches may be used to set default variables, and to
get final values after the Show method has returned (but has not been
explicitly destroyed by the caller)

     *-File*  The file selected, or the default file. The default is ".

     *-Path*  The path of the selected file, or the initial path. The
     default is $ENV{'HOME'}.

Labels and Captions
-------------------

   For support of internationalization, the text on any of the subwidgets
may be changed.

     -Title  The Title of the dialog box. The default is 'Select File:'.

     *-DirLBCaption*  The Caption above the Directory List Box. The
     default is 'Directories'.

     *-FileLBCaption*  The Caption above the File List Box. The default is
     'Files'.

     *-FileEntryLabel*  The label to the left of the File Entry. The
     Default is 'Filename:'.

     *-PathEntryLabel*  The label to the left of the Path Entry. The
     default is 'Pathname:'.

     *-FltEntryLabel*  The label to the left of the Filter entry. The
     default is 'Filter:'.

     *-ShowAllLabel*  The text of the Show All Checkbutton. The default is
     'Show All'.

Button Text
-----------

   For support of internationalization, the text on the three buttons may
be changed.

     *-OKButtonLabel*  The text for the OK button. The default is 'OK'.

     *-RescanButtonLabel*  The text for the Rescan button. The default is
     'Rescan'.

     *-CancelButtonLabel*  The text for the Cancel button. The default is
     'Cancel'.

Error Dialog Switches
---------------------

   If the Create switch is set to 0, and the user specifies a file that
does not exist, a dialog box will be displayed informing the user of the
error. These switches allow some configuration of that dialog box.

-EDlgTitle
----------

     The title of the Error Dialog Box. The default is 'File does not
     exist!'.

-EDlgText
---------

     The message of the Error Dialog Box. The variables $path, $file, and
     $filename (the full path and filename of the selected file) are
     available. The default is *"You must specify an existing
     file.\n(\$filename not found)"*

Author
======

   *Brent B. Powers, Merrill Lynch (B2Pi)*

   powers@ml.com

   This code may be distributed under the same conditions as Perl itself.

FileEntry widget with optional file selection box
*************************************************

NAME
====

   Tk::FileEntry - FileEntry widget with optional file selection box

SYNOPSIS
========

     use Tk::FileEntry;

     $fileentry = $parent->FileEntry(
     				-filebitmap	=> BITMAP,
     				-command	=> CALLBACK,
     				-variable	=> SCALARREF,
     				);

DESCRIPTION
===========

WIDGET-SPECIFIC OPTIONS
=======================

Option: *-filebitmap*
Name: *fileBitmap*
Class: *FileBitmap*
     Specifies the bitmap to be used for the button that invokes the File
     Dialog.

*-command*
     ...

*-variable*
     ...

BUGS
====

   If *FileEntry* is resized to a value smaller than at creation time the
Openfile Bitmap vanishes.

   FileSelection of alpha release Tk800.003 does not work (my fault!).  So
FileEntrys FileSelction dialog will not work with this release.

SEE ALSO
========

   `Tk|Tk' in this node `Tk::Entry|Tk::Entry' in this node
`Tk::FileSelect|k::FileSelect' in this node

KEYWORDS
========

   fileentry, tix, widget, file selector

AUTHOR
======

   Achim Bohnet <`ach@mpe.mpg.de'>

   This code is inspired by the documentation of FileEntry.n of the
Tix4.1.0 distribution by Ioi Lam.  The bitmap data are also from Tix4.1.0.
For everything else:

   Copyright (c) 1997-1998 Achim Bohnet. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

a widget for choosing files
***************************

NAME
====

   Tk::FileSelect - a widget for choosing files

SYNOPSIS
========

     use Tk::FileSelect;

     $FSref = $top->FileSelect(-directory => $start_dir);
                   $top            - a window reference, e.g. MainWindow->new
                   $start_dir      - the starting point for the FileSelect
     $file = $FSref->Show;
                   Executes the fileselector until either a filename is
                   accepted or the user hits Cancel. Returns the filename
                   or the empty string, respectively, and unmaps the
                   FileSelect.
     $FSref->configure(option => value[, ...])
                   Please see the Populate subroutine as the configuration
                   list changes rapidly.

DESCRIPTION
===========

   This Module pops up a Fileselector box, with a directory entry on top,
a list of directories in the current directory, a list of files in the
current directory, an entry for entering/modifying a file name, an accept
button and a cancel button.

   You can enter a starting directory in the directory entry. After
hitting Return, the listboxes get updated. Double clicking on any
directory shows you the respective contents. Single clicking on a file
brings it into the file entry for further consideration, double clocking
on a file pops down the file selector and calls the optional command with
the complete path for the selected file.  Hitting return in the file
selector box or pressing the accept button will also work. *NOTE* the file
selector box will only then get destroyed if the file name is not zero
length. If you want yourself take care of it, change the if(length(.. in
sub accept_file.

AUTHORS
=======

   Based on original FileSelect by Klaus Lichtenwalder,
Lichtenwalder@ACM.org, Datapat GmbH, Munich, April 22, 1995 adapted by
Frederick L. Wagner, derf@ti.com, Texas Instruments Incorporated, Dallas,
21Jun95

HISTORY
=======

950621 - The following changes were made:
-----------------------------------------

   * Rewrote Tk stuff to take advantage of new Compound widget module, so
     FileSelect is now composed of 2 LabEntry and 2 ScrlListbox2
     subwidgets.

   * Moved entry labels (from to the left of) to above the entry fields.

   * Caller is now able to control these aspects of widget, in both
     FileSelect (new) and configure :

     (Please see subroutine Populate for details, as these options change
     rapidly!)

   * I changed from Double-Button-1 to Button-1 in the Files listbox, to
     work with multiple mode in addition to browse mode.  I also made some
     name changes (LastPath -> saved_path, ...).

   * The show method is not yet updated.

   * The topLevel stuff is not done yet.  I took it out while I toy with
     the idea of FileSelect as a subwidget.  Then the 'normal' topLevel
     thing with Buttons along the bottom could be build on top of it.

   * By request of Henry Katz <katz@fs09.webo.dg.com>, I added the
     functionality of using the Directory entry as a filter. So, if you
     want to only see the *.c files, you add a .c (the *'s already there
     :) and hit return.

95/10/17, SOL, LUCC.  lusol@Lehigh.EDU
--------------------------------------

   *      Allow either file or directory names to be accepted.

   * Require double click to move into a new directory rather than a single
     click.  This allows a single click to select a directory name so it
     can be accepted.

   * Add -verify list option so that standard Perl file test operators
     (like -d and -x) can be specified for further name validation.  The
     default value is the special value '!-d' (not a directory), so any
     name can be selected as long as it's not a directory - after all,
     this IS FileSelect!

     For example:

          $fs->configure(-verify => ['-d', [\&verify_code, $P1, $P2, ... $Pn]]);

     ensures that the selected name is a directory.  Further, if an
     element of the list is an array reference, the first element is a
     code reference to a subroutine and the remaining optional elements
     are it's parameters.  The subroutine is called like this:

          &verify_code($cd, $leaf, $P1, $P2, ... $Pn);

     where $cd is the current directory, $leaf is a directory or file
     name, and $P1 .. $Pn are your optional parameters.  The subroutine
     should return TRUE if success or FALSE if failure.

961008 - derf@ti.com :
----------------------

   By request of Jim Stern <js@world.northgrum.com> and Brad Vance
<bvance@ti.com>, I updated the Accept and Show functions to support
selection of multiple files.  I also corrected a typo in the -verify code.

Button that keeps invoking callback when pressed
************************************************

NAME
====

   Tk::FireButton - Button that keeps invoking callback when pressed

SYNOPSIS
========

     use Tk::FireButton;

     $fire = $parent->FireButton( ... );

     # May/should change:
     $w->Whatever(... -bitmap => $Tk::FireButton::INCBITMAP, ...);
     $w->Whatever(... -bitmap => $Tk::FireButton::DECBITMAP, ...);
     $w->Whatever(... -bitmap => $Tk::FireButton::HORIZINCBITMAP, ...);
     $w->Whatever(... -bitmap => $Tk::FireButton::HORIZDECBITMAP, ...);

DESCRIPTION
===========

   *FireButton* is-a Button widget (see Tk/Button) that
keeps invoking the callback bound to it as long as the <FireButton> is
pressed.

   Four suitable bitmaps are predefined in this package: $INCBITMAP and
$DECBITMAP for vertical increment and decrement buttons, and
$HORIZINCBITMAP and $HORIZDECBITMAP for horizontal increment and decrement
buttons. See below for methods accessing these bitmaps.

SUPER-CLASS
===========

   The *FireButton* widget-class is derived from the Button widget-class
and inherits all the methods and options its super-class (see
Tk/Button).

STANDARD OPTIONS
================

   *FireButton* supports all the standard options of a Button widget.  See
Tk/options, for details on the standard options.

WIDGET-SPECIFIC OPTIONS
=======================

Name:             *repeatDelay*
Class:            *RepeatDelay*
Switch:           *-repeatdelay*
Fallback:		*300* (milliseconds)
     Specifies the amount of time before the callback is first invoked
     after the Button-1 is pressed over the widget.

Name:             *repeatInterval*
Class:            *RepeatInterval*
Switch:           *-repeatinterval*
Fallback:		100 (milliseconds)
     Specifies the amount of time between invokations of the callback
     bound to the widget with the command option.

CHANDED OPTION FALLBACK VALUES
==============================

   The fallback values of the following options as different from the
Button widget:

     -padx               => 0,
     -pady               => 0,

METHODS
=======

   Same as for `Button|Tk::Button' in this node widget.

   Additionally, there are four methods returning the names of the
standard increment and decrement bitmaps: INCBITMAP, HORIZINCBITMAP,
DECBITMAP, and HORIZDECBITMAP.

   Subclasses of FireButton may override these methods to supply different
increment and decrement bitmaps.

ADVERTISED WIDGETS
==================

   None.

HISTORY
=======

   The code was extracted from Tk::NumEntry and slightly modified by Achim
Bohnet >ach@mpe.mpg.de>.  Tk::NumEntry's author is Graham Barr
>gbarr@pobox.com>. The current maintainer is Slaven Rezic
>eserte@cs.tu-berlin.de>.

Create and inspect fonts.
*************************

NAME
====

   font - Create and inspect fonts.

       $widget->*Font*(option?, *arg, arg, ...*?)

       $font->Option?(*arg, arg, ...*)?

DESCRIPTION
===========

   The *Font* method provides several facilities for dealing with fonts,
such as defining named fonts and inspecting the actual attributes of a
font.  The command has several different forms, determined by the first
argument.  The following forms are currently supported:

$font->*actual*(*-option*?)
$widget->*fontActual*(font?, *-option*?)
     Returns information about the actual attributes that are obtained when
     font is used on $font's display; the actual attributes obtained may
     differ from the attributes requested due to platform-dependant
     limitations, such as the availability of font families and pointsizes.
     font is a font description; see `"FONT DESCRIPTION"' in this node
     below.  If option is specified, returns the value of that attribute;
     if it is omitted, the return value is a list of all the attributes
     and their values.  See `"FONT OPTIONS"' in this node below for a list
     of the possible attributes.

$font->configure(*-option*??=>value, *-option*=>value, ...?)
     Query or modify the desired attributes for $font.  If no *-option* is
     specified, returns a list describing all the options and their values
     for fontname.  If a single *-option* is specified with no value, then
     returns the current value of that attribute.  If one or more
     *option-value* pairs are specified, then the method modifies the
     given named font to have the given values; in this case, all widgets
     using that font will redisplay themselves using the new attributes
     for the font.  See `"FONT OPTIONS"' in this node below for a list of
     the possible attributes.

     Note: the above behaviour differs in detail to configure on widgets,
     images etc.

$font = $widget->*Font*(*-option*=>value, ...>?)
$font = $widget->*fontCreate*(?fontname??, *-option*=>value, ...>?)
     Creates a new font object and returns a reference to it.  fontname
     specifies the name for the font; if it is omitted, then Tk generates
     a new name of the form fontx, where x is an integer.  There may be any
     number of *option-value* pairs, which provide the desired attributes
     for the new named font.  See `"FONT OPTIONS"' in this node below for
     a list of the possible attributes.

     Note: the created font is not shared between widgets of different
     `MainWindow|Tk::MainWindow' in this nodes.

$font->delete
$widget->*fontDelete*(fontname?, fontname, ...?)
     Delete the specified named fonts.  If there are widgets using the
     named font, the named font won't actually be deleted until all the
     instances are released.  Those widgets will continue to display using
     the last known values for the named font.  If a deleted named font is
     subsequently recreated with another call to *fontCreate*, the widgets
     will use the new named font and redisplay themselves using the new
     attributes of that font.

$widget->*fontFamilies*
     The return value is a list of the case-insensitive names of all font
     families that exist on $widget's display.

$font->*measure*(text)
$widget->*fontMeasure*(font, text)
     Measures the amount of space the string text would use in the given
     font when displayed in $widget.  font is a font description; see
     `"FONT DESCRIPTION"' in this node below.  The return value is the
     total width in pixels of text, not including the extra pixels used by
     highly exagerrated characters such as cursive "f".  If the string
     contains newlines or tabs, those characters are not expanded or
     treated specially when measuring the string.

$font->*metrics*(*-option*?)
$widget->*fontMetrics*(font?, *-option*?)
     Returns information about the metrics (the font-specific data), for
     font when it is used on $widget's display.  font is a font
     description; see `"FONT DESCRIPTION"' in this node below.  If option
     is specified, returns the value of that metric; if it is omitted, the
     return value is a list of all the metrics and their values.  See
     `"FONT METRICS"' in this node below for a list of the possible
     metrics.

$widget->*fontNames*
     The return value is a list of all font objects that are currently
     defined for $widget's MainWindow.

FONT DESCRIPTION
================

   The following formats are accepted as a font description anywhere font
is specified as an argument above; these same forms are also permitted
when specifying the *-font* option for widgets.

[1] fontname
     The name of a named font, created using the *fontCreate* method.  When
     a widget uses a named font, it is guaranteed that this will never
     cause an error, as long as the named font exists, no matter what
     potentially invalid or meaningless set of attributes the named font
     has.  If the named font cannot be displayed with exactly the
     specified attributes, some other close font will be substituted
     automatically.

[1a] $font
     A font object created using the *Font* method. This is essentially
     the same as using a named font. The object is a reference to the
     name, and carries additional information e.g. which MainWindow it
     relates to in an manner peculiar to perl/Tk.

[3] *systemfont*
     The platform-specific name of a font, interpreted by the graphics
     server.  This also includes, under X, an XLFD (see `[4]|' in this
     node) for which a single "*" character was used to elide more than
     one field in the middle of the name.  See `"PLATFORM-SPECIFIC
     ISSUES"' in this node for a list of the system fonts.

[3] [family,?size,??style,??*style ...*?]
     A properly formed list whose first element is the desired font family
     and whose optional second element is the desired size.  The
     interpretation of the size attribute follows the same rules described
     for `-size|' in this node in `"FONT OPTIONS"' in this node below.
     Any additional optional arguments following the size are font styles.
     Possible values for the style arguments are as follows:

          normal	bold	roman	italic
          underline	overstrike

[4] X-font names (XLFD)
     A Unix-centric font name of the form

     *-foundry-family-weight-slant-setwidth-addstyle-pixel-point-resx-resy-spacing-width-charset-encoding*.
     The "*" character may be used to skip individual fields that the user
     does not care about.  There must be exactly one "*" for each field
     skipped, except that a "*" at the end of the XLFD skips any remaining
     fields; the shortest valid XLFD is simply "*", signifying all fields
     as defaults.  Any fields that were skipped are given default values.
     For compatibility, an XLFD always chooses a font of the specified
     pixel size (not point size); although this interpretation is not
     strictly correct, all existing applications using XLFDs assumed that
     one "point" was in fact one pixel and would display incorrectly
     (generally larger) if the correct size font were actually used.

[5] *option value *?*option value ...*?
     A properly formed list of *option-value* pairs that specify the
     desired attributes of the font, in the same format used when defining
     a named font; see `"FONT OPTIONS"' in this node below.

   When font description font is used, the system attempts to parse the
description according to each of the above five rules, in the order
specified.  Cases [1] and [2] must match the name of an existing named
font or of a system font.  Cases [3], [4], and [5] are accepted on all
platforms and the closest available font will be used.  In some situations
it may not be possible to find any close font (e.g., the font family was a
garbage value); in that case, some system-dependant default font is
chosen.  If the font description does not match any of the above patterns,
an error is generated.

FONT METRICS
============

   The following options are used by the *metrics*/*fontMetrics* method to
query font-specific data determined when the font was created.  These
properties are for the whole font itself and not for individual characters
drawn in that font.  In the following definitions, the "baseline" of a
font is the horizontal line where the bottom of most letters line up;
certain letters, such as lower-case "g" stick below the baseline.

*-ascent*
     The amount in pixels that the tallest letter sticks up above the
     baseline of the font, plus any extra blank space added by the
     designer of the font.  ($font-<gt>*ascent* is provided for
     compatibility.)

*-descent*
     The largest amount in pixels that any letter sticks down below the
     baseline of the font, plus any extra blank space added by the
     designer of the font.  ($font-<gt>*descent* is provided for
     compatibility.)

*-linespace*
     Returns how far apart vertically in pixels two lines of text using
     the same font should be placed so that none of the characters in one
     line overlap any of the characters in the other line.  This is
     generally the sum of the ascent above the baseline line plus the
     descent below the baseline.

*-fixed*
     Returns a boolean flag that is "1" if this is a fixed-width font,
     where each normal character is the the same width as all the other
     characters, or is "0" if this is a proportionally-spaced font, where
     individual characters have different widths.  The widths of control
     characters, tab characters, and other non-printing characters are not
     included when calculating this value.

FONT OPTIONS
============

   The following options are supported on all platforms, and are used when
constructing a named font or when specifying a font using style [5] as
above:

*-family* => name
     The case-insensitive font family name.  Tk guarantees to support the
     font families named *Courier* (a monospaced "typewriter" font),
     *Times* (a serifed "newspaper" font), and *Helvetica* (a sans-serif
     "European" font).  The most closely matching native font family will
     automatically be substituted when one of the above font families is
     used.  The name may also be the name of a native, platform-specific
     font family; in that case it will work as desired on one platform but
     may not display correctly on other platforms.  If the family is
     unspecified or unrecognized, a platform-specific default font will be
     chosen.

*-size* => size
     The desired size of the font.  If the size argument is a positive
     number, it is interpreted as a size in points.  If size is a negative
     number, its absolute value is interpreted as a size in pixels.  If a
     font cannot be displayed at the specified size, a nearby size will be
     chosen.  If size is unspecified or zero, a platform-dependent default
     size will be chosen.

     The original Tcl/Tk authors believe sizes should normally be
     specified in points so the application will remain the same ruler
     size on the screen, even when changing screen resolutions or moving
     scripts across platforms. While this is an admirable goal it does not
     work as well in practice as they hoped.  The mapping between points
     and  pixels is set when the application starts, based on alleged
     properties of the installed monitor, but it can be overridden by
     calling the  `scaling|Tk::Widget' in this node command. However this
     can be problematic when system has no way of telling if (say) an 11"
     or 22" monitor is attached, also if it can tell then some monitor
     sizes may result in poorer quality scaled fonts being used rather
     than a "tuned" bitmap font.  In addition specifying pixels is useful
     in certain circumstances such as when a piece of text must line up
     with respect to a fixed-size bitmap.

     At present the Tcl/Tk scheme is used unchanged, with "point" size
     being returned by *actual* (as an integer), and used internally.
     Suggestions for work-rounds to undesirable behaviour welcome.

*-weight* => weight
     The nominal thickness of the characters in the font.  The value
     normal specifies a normal weight font, while bold specifies a bold
     font.  The closest available weight to the one specified will be
     chosen.  The default weight is normal.

*-slant* => *slant*
     The amount the characters in the font are slanted away from the
     vertical.  Valid values for slant are *roman* and italic.  A roman
     font is the normal, upright appearance of a font, while an italic
     font is one that is tilted some number of degrees from upright.  The
     closest available slant to the one specified will be chosen.  The
     default slant is *roman*.

*-underline* => boolean
     The value is a boolean flag that specifies whether characters in this
     font should be underlined.  The default value for underline is false.

*-overstrike* => boolean
     The value is a boolean flag that specifies whether a horizontal line
     should be drawn through the middle of characters in this font.  The
     default value for overstrike is false.

PLATFORM-SPECIFIC ISSUES
========================

   The following named system fonts are supported:

X Windows:
     All valid X font names, including those listed by xlsfonts(1), are
     available.

MS Windows:
          system       ansi       device
          systemfixed  ansifixed  oemfixed

Macintosh:
          system       application

COMPATIBILITY WITH PREVIOUS VERSIONS
====================================

   In prior versions of perl/Tk the $widget->*Font* method was a perl
wrapper on the original "[4] X-font names (XLFD)" style as described above
(which was the only form supported by versions of core tk prior to version
tk8.0).  This module is provided in its original form (it has just been
renamed) via:

     use Tk::X11Font;
     I<$widget>-Greater_Than_Special_SequenceB<X11Font>(...)

   However the methods of the old scheme have been mimiced as closely as
possible with the new scheme. It is intended that code should work without
modification, except for the case of using :

     @names = $font->Name;

   i.e. the Name method in an array/list context. This now returns one
element on all platforms (as it did on Win32), while previously on X
systems it returned a list of fonts that matched an under-specified
pattern.

   Briefly the methods supported for compatibilty are as follows:

$newfont = $font->Clone(*-option*=>value, ...>?)
     Returns a new font object $newfont related to the original $font by
     changing the values of the specified *-option*s.

$font->Family - maps to -family
$font->Weight - maps to -weight
$font->Slant - maps to -slant
$font->Pixel and Point - map to -size
   New code should use $font->configure to achieve same effect as last
four items above.

Foundry, Swidth, Adstyle, Xres, Yres, Space, Avgwidth, Registry, Encoding
     Are all ignored if set, and return '*' if queried.

$font->Name
     Returns the name of a named font, or a string representation of an
     unnamed font. Using $font in a scalar context does the same. Note
     this is distinctly different from behaviour of `X11Font's
     Name|Tk::X11Font' in this node in a list context.

$font->Pattern
     Returns a XLFD string for the font based on *actual* values, and some
     heuristics to map Tk's forms to the "standard" X conventions.

SEE ALSO
========

   `Tk::options|Tk::options' in this node

   `Tk::X11Font|Tk::X11Font' in this node

KEYWORDS
========

   font

a font dialog widget for perl/Tk
********************************

NAME
====

   Tk::FontDialog - a font dialog widget for perl/Tk

SYNOPSIS
========

     use Tk::FontDialog;
     $font = $top->FontDialog->Show;

DESCRIPTION
===========

   Tk::FontDialog implements a font dialog widget. XXX

WIDGET-SPECIFIC OPTIONS
=======================

-font
     The dialog font.

-initfont
     The initial font.

-fontsizes
     A list of font sizes. The default contains sizes from 0 to 72 points
     (XXX or pixels?).

-nicefont
     If set, font names are displayed in its font style. This may be slow,
     especially if you have many fonts or 16 bit fonts (e.g. Asian fonts).

-nicefontsbutton
     If set to false, then the "Nice fonts" button is not displayed.

-fixedfont
     If set, proportional font families are not listed, leaving only the
     fixed fonts. This is slow, as each font must be checked to see if it
     is fixed or proportional.

-fixedfontsbutton
     If set to false, then the "Fixed fonts" button is not displayed.

-sampletext
     The sample text which should contain all letters. The default is "The
     Quick Brown Fox Jumps Over The Lazy Dog" German readers may probably
     use "Franz jagt im komplett verwahrlosten Taxi quer durch Bayern".

INTERNATIONALIZATION
====================

   There are a couple of options to change the labels of the dialog. Note
that you can prepend a tilde (`~') to get an accelerator key with `Alt'.
Here is a list of these options with the default (English) setting:

-familylabel (Family:)
-sizelabel (Size:)
-weightlabel (Bold)
-slantlabel (Italic)
-underlinelabel (Underline)
-overstrikelabel (Overstrike)
-oklabel (OK)
-applylabel (Apply)
-cancellabel (Cancel)
-altsamplelabel (Alt sample)
-nicefontslabel (Nicefonts)
-fixedfontslabel (Fixed Only)
BUGS/TODO
=========

     - better POD
     - XXX
     - ConfigSpecs handling is poor
       put at least -font into configspecs
     - run test, call dialog for 2nd time: immediate change of font?
     - better name for nicefont
     - restrict on charsets and encodings (xlsfonts? X11::Protocol::ListFonts?)
       difficult because core Tk font handling ignores charsets and encodings

SEE ALSO
========

   `Tk::font|Tk::font' in this node

AUTHOR
======

   Slaven Rezic <eserte@cs.tu-berlin.de>

   Suggestions by Michael Houghton <herveus@Radix.Net>.

COPYRIGHT
=========

   Copyright (c) 1998,1999 Slaven Rezic. All rights reserved.  This module
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Create and manipulate Frame widgets
***********************************

NAME
====

   Tk::Frame - Create and manipulate Frame widgets

       *$frame* = *$parent*->Frame(?options?);

STANDARD OPTIONS
================

*-borderwidth*	*-highlightbackground*	*-highlightthickness*	*-takefocus*
*-class*	*-highlightcolor*	*-relief* *-cursor*

   See Tk/options, for details of the standard options.

WIDGET-SPECIFIC OPTIONS
=======================

Name:	background
Class:	Background
Switch:	*-background*
     This option is the same as the standard background option except that
     its value may also be specified as an undefined value.  In this case,
     the widget will display no background or border, and no colors will
     be consumed from its colormap for its background and border.

Name:	colormap
Class:	*Colormap*
Switch:	*-colormap*
     Specifies a colormap to use for the window.  The value may be either
     new, in which case a new colormap is created for the window and its
     children, or the name of another window (which must be on the same
     screen and have the same visual as $widget), in which case the new
     window will use the colormap from the specified window.  If the
     colormap option is not specified, the new window uses the same
     colormap as its parent.  This option may not be changed with the
     configure method.

Name:	container
Class:	Container
Switch:	*-container*
     The value must be a boolean.  If true, it means that this window will
     be used as a container in which some other application will be
     embedded (for example, a Tk toplevel can be embedded using the *-use*
     option).  The window will support the appropriate window manager
     protocols for things like geometry requests.  The window should not
     have any children of its own in this application.  This option may
     not be changed with the configure method.

Name:	height
Class:	*Height*
Switch:	*-height*
     Specifies the desired height for the window in any of the forms
     acceptable to *Tk_GetPixels*.  If this option is less than or equal
     to zero then the window will not request any size at all.

Name:	*visual*
Class:	*Visual*
Switch:	*-visual*
     Specifies visual information for the new window in any of the forms
     accepted by *Tk_GetVisual*.  If this option is not specified, the new
     window will use the same visual as its parent.  The *visual* option
     may not be modified with the configure method.

Name:	width
Class:	Width
Switch:	*-width*
     Specifies the desired width for the window in any of the forms
     acceptable to *Tk_GetPixels*.  If this option is less than or equal
     to zero then the window will not request any size at all.

DESCRIPTION
===========

   The Frame method creates a new window (given by the $widget argument)
and makes it into a frame widget.  Additional options, described above,
may be specified on the command line or in the option database to
configure aspects of the frame such as its background color and relief.
The frame command returns the path name of the new window.

   A frame is a simple widget.  Its primary purpose is to act as a spacer
or container for complex window layouts.  The only features of a frame are
its background color and an optional 3-D border to make the frame appear
raised or sunken.

WIDGET METHODS
==============

   The Frame method creates a widget object.  This object supports the
configure and cget methods described in Tk/options,
which can be used to enquire and modify the options described above.  The
widget also inherits all the methods provided by the generic
`Tk::Widget|Tk::Widget' in this node class.

BINDINGS
========

   When a new frame is created, it has no default event bindings: frames
are not intended to be interactive.

KEYWORDS
========

   frame, widget

User configuration window for Tk with interface to Getopt::Long
***************************************************************

NAME
====

   Tk::Getopt - User configuration window for Tk with interface to
Getopt::Long

SYNOPSIS
========

     use Tk::Getopt;
     @opttable = (['opt1', '=s', 'default'], ['opt2', '!', 1], ...);
     $opt = new Tk::Getopt(-opttable => \@opttable,
                           -options => \%options,
     			  -filename => "$ENV{HOME}/.options");
     $opt->set_defaults;     # set default values
     $opt->load_options;     # configuration file
     $opt->get_options;      # command line
     $opt->process_options;  # process callbacks, check restrictions ...
     print $options->{'opt1'}, $options->{'opt2'} ...;
     ...
     $top = new MainWindow;
     $opt->option_editor($top);

   or using a `Getopt::Long|Getopt::Long' in this node-like interface

     $opt = new Tk::Getopt(-getopt => ['help'   => \$HELP,
     				      'file:s' => \$FILE,
     				      'foo!'   => \$FOO,
     				      'num:i'  => \$NO,
     				     ]);

   or an alternative Getopt::Long interface

     %optctl = ('foo' => \$foo,
     	       'bar' => \$bar);
     $opt = new Tk::Getopt(-getopt => [\%optctl, "foo!", "bar=s"]);

DESCRIPTION
===========

   `Tk::Getopt' provides an interface to access command line options via
`Getopt::Long|Getopt::Long' in this node and editing with a graphical user
interface via a Tk window.

   Unlike Getopt::Long, this package uses a object oriented interface, so
you have to create a new `Tk::Getopt' object with new. Unlike other
packages in the Tk hierarchy, this package does not define a Tk widget. The
graphical interface is calles by the method *option_editor*.

   After creating an object with new, you can parse command line options
by calling get_options. This method calls itself
*Getopt::Long::GetOptions*.

METHODS
=======

*new Tk::Getopt(**arg_hash*)
     Constructs a new object of the class `Tk::Getopt'. Arguments are
     passed in a hash (just like Tk widgets and methods). There are many
     variants to specify the option description. You can use an interface
     similar to *Getopt::Long::GetOptions* by using *-getopt* or a more
     powerful interface by using *-opttable*. Internally, the option
     description will be converted to the *-opttable* interface. One of
     the arguments *-getopt* or *-opttable* are mandatory.

     The arguments for new are:

    -getopt
          *-getopt* should be a reference to a hash or an array. This hash
          has the same format as the argument to the
          *Getopt::Long::GetOptions* function.  Look at Getopt/Long,
          for a detailed description. Note also that not all
          of GetOptions is implemented, see `"BUGS"' in this node for
          further information.

          Example:

               new Tk::Getopt(-getopt => [\%options,
                                          "opt1=i", "opt2=s" ...]);

    -opttable
          *-opttable* provides a more powerful interface. The options are
          stored in variables named *$opt_XXX* or in a hash when
          *-options* is given (see below). *-opttable* should be a
          reference to an array containing all options. Elements of this
          array may be strings, which indicate the beginning of a new
          group, or array references describing the options. The first
          element of this array is the name of the option, the second is
          the type (`=s' for string, `=i' for integer, ! for boolean, `=f'
          for float etc., see Getopt/Long) for a
          detailed list. The third element is optional and contains the
          default value (otherwise the default is undefined). Further
          elements are optional too and describe more attributes. For a
          complete list of these attributes refer to `"OPTTABLE
          ARGUMENTS"' in this node.

          If an option has no name, then the third element in the
          description array will be used as an global message for the
          current option page.  This message can be multi-line.  Example:
            [", ", 'This is an explanation for this option group.']

          Here is an example for a simple opttable:

               @opttable =
                   ('First section',
               	 ['', '', 'Section description'],
               	 ['debug', '!',  0],
                    ['age',   '=i', 18],

               'Second section',
               ['', '', 'Description for 2nd section'],
                        ['browser', '=s', 'tkweb'],
                        ['foo',     '=f', undef],
                       );
                   new Tk::Getopt(-opttable => \@opttable,
                                  -options => \%options);

    -options
          This argument should be a reference to an (empty) hash. Options
          are set into this hash. If this argument is missing, options
          will be stored in variables named *$opt_XXX*.

    -filename
          This argument is optional and specifies the filename for loading
          and saving options.

    -nosafe
          If set to true, do not use a safe compartment when loading
          options (see *load_options*).

set_defaults
     Sets default values. This only applies if the *-opttable* variant is
     used.

*load_options(*filename)
     Loads options from file filename, or, if not specified, from object's
     filename as specified in new. The loading is done in a safe
     compartment ensure security.The loaded file should have a reference
     to a hash named *$loadoptions*.

*save_options(*filename)
     Writes options to file filename, or, if not specified, from object's
     filename as specified in new. The saving is done with
     `Data::Dumper|Data::Dumper' in this node. Since saving may fail, you
     should call this method inside of `eval {}' and check *$@*. Possible
     exceptions are `No Data::Dumper' (cannot find the Data::Dumper
     module) and `Writing failed' (cannot write to file).

get_options
     Gets options via GetOptions. Returns the same value as GetOptions,
     i.e.  0 indicates that the function detected one or more errors.

     If you want to process options which does not appear in the GUI, you
     have two alternatives:

        * Use the *-opttable* variant of the new constructor and mark all
          non-GUI options with nogui, e.g.

               new Tk::Getopt(-opttable => ['not-in-gui', '!', undef,
                                            nogui => 1], ...)

        * Use *Getopt::Long::passthrough* and process non-GUI options
          directly with *Getopt::Long::GetOptions*. The remaining args can
          be passed to get_options.

          Example:

               use Tk::Getopt;
               use Getopt::Long;

               $Getopt::Long::passthrough = 1;
               GetOptions('options!' => \$preloadopt);
               $Getopt::Long::passthrough = 0;

               $opt = new Tk::Getopt( ... );
               $opt->get_options;

usage
     Generates an usage string from object's opttable. The usage string is
     constructed from the option name, default value and help entries.

*process_options(*[*undo_hash*])
     Checks wheather given values are valid (if strict is set) and calls
     any callbacks specified by the sub option. If *undo_hash* is given
     and the new value of an option did not change, no sub is called.

*option_editor(*widget, [*arguments ...*])
     Pops the option editor up. The editor provides facilitied for editing
     options, undoing, restoring to their default valued and saving to the
     default options file.

     The first argument is the parent widget. Further optional arguments
     are passed as a hash:

    -callback
          Execute additional callback after creating the option editor.
          Arguments passed to this callback are: reference to the
          `Tk::Getopt' object and a reference to the option editor window.

    -nosave
          Disable saving of options.

    -buttons
          Specify, which buttons should be drawn. It is advisable to draw
          at least the OK and Cancel buttons. The default set looks like
          this:

               -buttons => [qw/ok apply cancel undo lastsaved save defaults/]

    -toplevel
          Use another widget class instead of Toplevel for embedding the
          option editor, e.g. Frame to embed the editor into another
          toplevel widget (do not forget to pack the frame!). See also the
          `-pack' option below.

    -pack
          If using `-toplevel' with a non-Toplevel widget (e.g. Frame) and
          using the `-wait' option, then packing have to be done through
          the `-pack' option. The argument to this option is a array
          reference of pack options, e.g.

               $opt->option_editor(-toplevel => "Frame",
                                   -wait => 1,
                                   -pack => [-fill => "both", -expand => 1]);

    -statusbar
          Use an additional status bar for help messages.

    -string
          Change button labels and title. This argument should be a hash
          reference with following keys: `optedit', undo, `lastsaved',
          save, defaults, ok, `cancel', `helpfor'.

    -wait
          Do not return immediately, but rather wait for the user pressing
          OK or Cancel.

     Since the option editor uses the `NoteBook' widget, options may be
     grouped in several pages. Grouping is only possible if using the
     `-opttable' variant of new. Help messages are shown in balloons and,
     if specified, in a statusbar.

     *option_editor* returns a reference to the created window.

     Note: this method returns immediately to the calling program.

     Buttons in the option editor window:

    OK
          Accept options and close option editor window.

    Cancel
          Set old values and close option editor window.

    Undo
          Set old values. Further selections toggle between new and old
          values.

    Last saved
          Set last saved options. This button is not displayed if no
          filename was given in new.

    Save
          Save options to file. This button is not displayed if no
          filename was given in new.

     The option types are translated to following widgets:

    Boolean
          Checkbutton (*_boolean_widget*)

    Integer and Float
          Scale, if range is set, otherwise either *BrowseEntry* or Entry
          (*_integer_widget*, *_float_widget*).

    String
          *BrowseEntry* if choices is set, otherwise entry
          (*_string_widget*).  *FileDialog* if subtype is set to file.

OPTTABLE ARGUMENTS
==================

   Additional attributes in an option description have to be key-value
pairs with following keys:

alias
     An array of aliases also accepted by Getopt::Long.

label
     A label to be displayed in the GUI instead of the option name.

help
     A short help string used by usage and the Balloon help facility in
     *option_editor*.

longhelp
     A long help string used by *option_editor*.

choices
     An array of additional choices for the option editor.

range
     An array with the beginning and end of a range for an integer or
     float value.

strict
     Must be used with choices or range. When set to true, options have to
     match either the choices or the range.

subtype
     The only permitted subtypes are file and dir to be used with string
     options. The GUI interface will pop up a file dialog for this option
     (either for selecting files or directories).

var
     Use variable instead of *$options->{optname}* or *$opt_optname* to
     store the value.

nogui
     This option will not have an entry in the GUI.

widget
     This should be a reference to a subroutine for creating an own widget.
     Folowing arguments will be passed to this subroutine: a reference to
     the `Tk::Getopt' object, Frame object, options entry.  The subroutine
     should create a widget in the frame (packing is not necessary!) and
     should return a reference to the created widget.

   Here is an example for using a complex opttable description:

     @opttable =
         ('Misc',   # Head of first group
     	 ['debug', # name of the option (--debug)
           '!',     # type boolean, accept --nodebug
           0,       # default is 0 (false)
           callback => sub { $^W = 1
                                 if $options->{'debug'}; }
           # additional attribute: callback to be called if
           # you set or change the value
           ],
          ['age',
           '=i',    # option accepts integer value
           18,
           strict => 1, # value must be in range
           range => [0, 100], # allowed range
           alias => ['year', 'years'] # possible aliases
           ],
     	 'External', # Head of second group
          ['browser',
           '=s',    # option accepts string value
           'tkweb',
           choices => ['mosaic', 'netscape',
                       'lynx', 'chimera'],
           # choices for the list widget in the GUI
           label => 'WWW browser program'
           # label for the GUI instead of 'browser'
           ],
          ['foo',
           '=f',    # option accepts float value
           undef,   # no default value
           help => 'This is a short help',
           # help string for usage() and the help balloon
           longhelp => 'And this is a slightly longer help'
           # longer help displayed in the GUI's help window
           ]);

REQUIREMENTS
============

   You need at least:

   * perl5.004 (perl5.003 near 5.004 may work too, e.g perl5.003_26)

   * Tk400.202 (better: Tk800.007) (only if you want the GUI)

   * Data-Dumper-2.07 (only if you want to save options and it's anyway
     standard in perl5.005)

BUGS
====

   Be sure to pass a real hash reference (not a uninitialized reference)
to the -options switch in `new Tk::Getopt'. Use either:

     my %options;
     my $opt = new Tk::Getopt(-options => \%options ...)

   or

     my $options = {};
     my $opt = new Tk::Getopt(-options => $options ...)

   Note the initial assignement for $options in the second example.

   Not all of Getopt::Long is supported (array and hash options, <>,
abbrevs).

   The option editor probably should be a real widget.

   The option editor window may grow very large if NoteBook is not used
(should use a scrollable pane).

   If the user resizes the window, the buttons at bottom may disappear.
This is confusing and it is advisable to disallow the resizing:

     $opt_editor = $opt->option_editor;
     $opt_editor->resizable(0,0);

   The API will not be stable until version 1.00.

   This manual is confusing. In fact, the whole module is confusing.

   Setting variables in the editor should not set immediately the real
variables.  This should be done only by Apply and Ok buttons.

AUTHOR
======

   Slaven Rezic <eserte@cs.tu-berlin.de>

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   `perl|perl' in this node `Getopt::Long|Getopt::Long' in this node
`Data::Dumper|Data::Dumper' in this node `Tk|Tk' in this node
`Tk::FileDialog|Tk::FileDialog' in this node `Tk::NoteBook|Tk::NoteBook'
in this node `Tk::Tiler|Tk::Tiler' in this node `Safe|Safe' in this node

Beginings of a lowlevel PostScript viewing widget
*************************************************

NAME
====

   Ghostscript - Beginings of a lowlevel PostScript viewing widget

SYNOPSIS
========

     my $gs= $parent->Ghostscript(
                     'x_pixels_per_inch' => $scale,
                     'y_pixels_per_inch' => $scale,
                     'BoundingBox' => [ 0,0, $width, $height]
                     );
     $gs->Postscript("....");

DESCRIPTION
===========

   Tested with gs3 via `pgs' and `Ghostview.pm'.

   Aim is to have both GS and "Display Postscript" widgets which present
same interface to higher level document viewers.

Create and manipulate Tix Hierarchial List widgets
**************************************************

NAME
====

   Tk::HList - Create and manipulate Tix Hierarchial List widgets

   *$hlist* = *$parent*->*HList*(?options?);

STANDARD OPTIONS
================

   *-background*	*-borderwidth*	*-cursor*	*-exportselection*
*-foreground*	*-font*	*-height*	*-highlightcolor*
*-highlightthickness*	*-relief*	*-selectbackground*
*-selectforeground*	*-xscrollcommand*	*-yscrollcommand* *-width*

   See Tk/options, for details of the standard options.

WIDGET-SPECIFIC OPTIONS
=======================

Name:	*browsecmd*
Class:	*BrowseCmd*
Switch:	*-browsecmd*
     Specifies a perl/Tk `callback|Tk::callbacks' in this node to be
     executed when the user browses through the entries in the HList
     widget.

Name:	columns
Class:	Columns
Switch:	*-columns*
     Specifies the number of columns in this HList widget. This option can
     only be set during the creation of the HList widget and cannot be
     changed subsequently.

Name:	command
Class:	Command
Switch:	*-command*
     Specifies the perl/Tk `callback|Tk::callbacks' in this node to be
     executed when the user invokes a list entry in the HList widget.
     Normally the user invokes a list entry by double-clicking it or
     pressing the Return key.

Name:	*drawBranch*
Class:	*DrawBranch*
Switch:	*-drawbranch*
     A Boolean value to specify whether branch line should be drawn to
     connect list entries to their parents.

Name:	*foreground*
Class:	*Foreground*
Switch:	*-foreground*
Alias:	*-fg*
     *[OBSOLETE]* Specifies the default foreground color for the list
     entries.

Name:	gap
Class:	*Gap*
Switch:	*-gap*
     *[OBSOLETE]* The default distance between the bitmap/image and the
     text in list entries.

Name:	header
Class:	Header
Switch:	*-header*
     A Boolean value specifying whether headers should be displayed for
     this HList widget (see the header method below).

Name:	height
Class:	*Height*
Switch:	*-height*
     Specifies the desired height for the window in number of characters.

Name:	indent
Class:	*Indent*
Switch:	*-indent*
     Specifies the amount of horizontal indentation between a list entry
     and its children. Must be a valid screen distance value.

Name:	*indicator*
Class:	*Indicator*
Switch:	*-indicator*
     Specifies whether the indicators should be displayed inside the HList
     widget. See the *indicator* method below.

Name:	*indicatorCmd*
Class:	*IndicatorCmd*
Switch:	*-indicatorcmd*
     Specifies a perl/Tk `callback|Tk::callbacks' in this node to be
     executed when the user manipulates the indicator of an HList entry.
     The *-indicatorcmd* is triggered when the user press or releases the
     mouse button over the indicator in an HList entry. By default the
     perl/Tk callback specified by *-indicatorcmd* is executed with two
     additional arguments, the entryPath of the entry whose indicator has
     been triggered and additional information about the event.  The
     additional information is one of the following strings:  *<Arm>*,
     *<Disarm>*, and *<Activate>*.

Name:	*itemType*
Class:	*ItemType*
Switch:	*-itemtype*
     Specifies the default type of display item for this HList widget. When
     you call the *itemCreate*, add and *addchild* methods, display items
     of this type will be created if the *-itemtype* option is not
     specified .

Name:	*padX*
Class:	*Pad*
Switch:	*-padx*
     *[OBSOLETE]* The default horizontal padding for list entries.

Name:	*padY*
Class:	*Pad*
Switch:	*-padx*
     *[OBSOLETE]* The default vertical padding for list entries.

Name:	*selectBackground*
Class:	*SelectBackground*
Switch:	*-selectbackground*
     Specifies the background color for the selected list entries.

Name:	*selectBorderWidth*
Class:	*BorderWidth*
Switch:	*-selectborderwidth*
     Specifies a non-negative value indicating the width of the 3-D border
     to draw around selected items.  The value may have any of the forms
     acceptable to *Tk_GetPixels*.

Name:	*selectForeground*
Class:	*SelectForeground*
Switch:	*-selectforeground*
     Specifies the foreground color for the selected list entries.

Name:	*selectMode*
Class:	*SelectMode*
Switch:	*-selectmode*
     Specifies one of several styles for manipulating the selection.  The
     value of the option may be arbitrary, but the default bindings expect
     it to be either single, browse, multiple, or *extended*; the default
     value is single.

Name:	*sizeCmd*
Class:	*SizeCmd*
Switch:	*-sizecmd*
     Specifies a perl/Tk `callback|Tk::callbacks' in this node to be
     called whenever the HList widget changes its size.  This method can
     be useful to implement "*user scroll bars when needed*" features.

Name:	separator
Class:	Separator
Switch:	*-separator*
     Specifies the character to used as the separator character when
     intepreting the path-names of list entries. By default the character
     "." is used.

Name:	width
Class:	Width
Switch:	*-width*
     Specifies the desired width for the window in characters.

DESCRIPTION
===========

   The *HList* method creates a new window (given by the $widget argument)
and makes it into a HList widget.  Additional options, described above,
may be specified on the command line or in the option database to
configure aspects of the HList widget such as its cursor and relief.

   The HList widget can be used to display any data that have a
hierarchical structure, for example, file system directory trees. The list
entries are indented and connected by branch lines according to their
places in the hierachy.

   Each list entry is identified by an *entryPath*. The entryPath is a
sequence of *entry names* separated by the separator charactor (specified
by the *-separator* option). An *entry name* can be any string that does
not contain the separator charactor, or it can be the a string that
contains only one separator charactor.

   For example, when "." is used as the separator charactor,
"one.two.three" is the entryPath for a list entry whose parent is
"one.two", whose parent is "one", which is a toplevel entry (has no
parents).

   Another examples: ".two.three" is the entryPath for a list entry whose
parent is ".two", whose parent is ".", which is a toplevel entry.

DISPLAY ITEMS
=============

   Each list entry in an HList widget is associated with a display item.
The display item determines what visual information should be displayed
for this list entry. Please see Tk/DItem, for a list of
all display items.  When a list entry is created by the *itemCreate*, add
or *addchild* widget methods, the type of its display item is determined
by the *-itemtype* option passed to these methods. If the *-itemtype* is
omitted, then by default the type specified by this HList widget's
*-itemtype* option is used.

WIDGET METHODS
==============

   The *HList* method creates a widget object.  This object supports the
configure and cget methods described in Tk/options,
which can be used to enquire and modify the options described above.  The
widget also inherits all the methods provided by the generic
`Tk::Widget|Tk::Widget' in this node class.

   The following additional methods are available HList widgets:

*$hlist*->add(*$entryPath* ?,option=>value, ...?)
     Creates a new list entry with the pathname *$entryPath*. A list entry
     must be created after its parent is created (unless this entry is a
     top-level entry, which has no parent).  See also `"BUGS"' in this
     node below.  This method returns the entryPath of the newly created
     list entry. The following configuration options can be given to
     configure the list entry:

    *-at* => position
          Insert the new list at the position given by position.  position
          must be a valid integer. The position 0 indicates the first
          position, 1 indicates the second position, and so on.

    *-after* => *afterWhich*
          Insert the new list entry after the entry identified by
          *afterWhich*. *afterWhich* must be a valid list entry and it
          mush have the same parent as the new list entry

    *-before* => *beforeWhich*
          Insert the new list entry before the entry identified by
          *beforeWhich*. *beforeWhich* must be a valid list entry and it
          mush have the same parent as the new list entry

    *-data* => string
          Specifies a string to associate with this list entry. This
          string can be queried by the info method. The application
          programmer can use the *-data* option to associate the list entry
          with the data it represents.

    *-itemtype* => type
          Specifies the type of display item to be display for the new list
          entry. type must be a valid display item type. Currently the
          available display item types are *imagetext*, text, and $widget.
          If this option is not specified, then by default the type
          specified by this HList widget's *-itemtype* option is used.

    *-state* => state
          Specifies whether this entry can be selected or invoked by the
          user.  Must be either normal or disabled.

     The add method accepts additional configuration options to configure
     the display item associated with this list entry. The set of
     additional configuration options depends on the type of the display
     item given by the *-itemtype* option. Please see Tk/DItem,
     for a list of the configuration options for each of the
     display item types.

*$hlist*->*addchild*(*$parentPath, *?*option, value, ..., *?)
     Adds a new child entry to the children list of the list entry
     identified by *$parentPath*. Or, if *$parentPath* is set to be the
     empty string, then creates a new toplevel entry. The name of the new
     list entry will be a unique name automatically generated by the HList
     widget. Usually if *$parentPath* is foo, then the entryPath of the
     new entry will be *foo.0*, *foo.1*, ... etc.  This method returns the
     entryPath of the newly created list entry.  option can be any option
     for the add method.  See also `"BUGS"' in this node below.

*$hlist*->*anchorSet*(*$entryPath*)
     Sets the anchor to the list entry identified by *$entryPath*.  The
     anchor is the end of the selection that is fixed while the user is
     dragging out a selection with the mouse.

*$hlist*->*anchorClear*
     Removes the anchor, if any, from this HList widget. This only removes
     the surrounding highlights of the anchor entry and does not affect
     its selection status.

*$hlist*->*columnWidth*(*$col*?, *-char*?, ?width?)
     Querys or sets the width of a the column *$col* in the HList widget.
     The value of *$col* is zero-based: 0 stands for the first column, 1
     stands for the second, and so on. If no further parameters are given,
     returns the current width of this column (in number of pixels).
     Additional parameters can be given to set the width of this column:

    *$hlist*->*columnWidth*(*$col*, ")
          An empty string indicates that the width of the column should be
          just wide enough to display the widest element in this column.
          In this case, the width of this column may change as a result of
          the elements in this column changing their sizes.

    *$hlist*->*columnWidth*(*$col, *width)
          width must be in a form accepted by *Tk_GetPixels*.

    *$hlist*->*columnWidth*(*$col, **-char, **nChars*)
          The width is set to be the average width occupied by *nChars*
          number of characters of the font specified by the *-font* option
          of this HList widget.

*$hlist*->delete(option, *$entryPath*)
     Delete one or more list entries. option may be one of the following:

    all
          Delete all entries in the HList. In this case the *$entryPath*
          does not need to be specified.

    entry
          Delete the entry specified by *$entryPath* and all its
          offsprings, if any.

    offsprings
          Delete all the offsprings, if any, of the entry specified by
          *$entryPath*. However, *$entryPath* itself is not deleted.

    siblings
          Delete all the list entries that share the same parent with the
          entry specified by *$entryPath*. However, *$entryPath* itself is
          not deleted.

*$hlist*->*dragsiteSet*(*$entryPath*)
     Sets the dragsite to the list entry identified by *$entryPath*. The
     dragsite is used to indicate the source of a drag-and-drop action.
     Currently drag-and-drop functionality has not been implemented in Tix
     yet.

*$hlist*->*dragsiteClear*
     Remove the dragsite, if any, from the this HList widget. This only
     removes the surrounding highlights of the dragsite entry and does not
     affect its selection status.

*$hlist*->*dropsiteSet*(*$entryPath*)
     Sets the dropsite to the list entry identified by *$entryPath*. The
     dropsite is used to indicate the target of a drag-and-drop action.
     Currently drag-and-drop functionality has not been implemented in Tix
     yet.

*$hlist*->*dropsiteClear*
     Remove the dropsite, if any, from the this HList widget. This only
     removes the surrounding highlights of the dropsite entry and does not
     affect its selection status.

*$hlist*->*entrycget*(*$entryPath*, option)
     Returns the current value of the configuration option given by option
     for the entry indentfied by *$entryPath*. Option may have any of the
     values accepted by the add method.

*$hlist*->*entryconfigure*(*$entryPath* ?,option?, ?value=>option, ...?)
     Query or modify the configuration options of the list entry indentfied
     by *$entryPath*. If no option is specified, returns a list describing
     all of the available options for *$entryPath* (see Tk/options,
     for information on the format of this list.) If option is
     specified with no value, then the method returns a list describing
     the one named option (this list will be identical to the
     corresponding sublist of the value returned if no option is
     specified). If one or more *option-value* pairs are specified, then
     the method modifies the given option(s) to have the given value(s);
     in this case the method returns an empty string.  Option may have any
     of the values accepted by the add or *addchild* method. The exact set
     of options depends on the value of the *-itemtype* option passed to
     the the add or *addchild* method when this list entry is created.

*$hlist*->header(option, *$col* ?,args, ...?)
     Manipulates the header items of this HList widget. If the *-header*
     option of this HList widget is set to true, then a header item is
     displayed at the top of each column. The *$col* argument for this
     method must be a valid integer. 0 indicates the first column, 1 the
     second column, ... and so on. This method supports the following
     options:

    *$hlist*->header(cget, *$col*, option)
          If the *$col*-th column has a header display item, returns the
          value of the specified option of the header item. If the header
          doesn't exist, returns an error.

    *$hlist*->header(*configure, **$col, *?option?, *?value, option, value, ...*?)
          Query or modify the configuration options of the header display
          item of the *$col*-th column. The header item must exist, or an
          error will result.  If no option is specified, returns a list
          describing all of the available options for the header display
          item (see Tk/options, for information on the
          format of this list.) If option is specified with no value, then
          the method returns a list describing the one named option (this
          list will be identical to the corresponding sublist of the value
          returned if no option is specified). If one or more
          *option-value* pairs are specified, then the method modifies the
          given option(s) to have the given value(s); in this case the
          method returns an empty string. Option may have any of the
          values accepted by the *header create* method. The exact set of
          options depends on the value of the *-itemtype* option passed to
          the the header create method when this display item was created.

    *$hlist*->header(*create, **$col, *?*-itemtype type*? ?*option value ...*?
          Creates a new display item as the header for the *$col*-th
          column. See also `"BUGS"' in this node below.  If an header
          display item already exists for this column, it will be replaced
          by the new item.  An optional parameter *-itemtype* can be used
          to specify what type of display item should be created. If the
          *-itemtype* is not given, then by default the type specified by
          this HList widget's *-itemtype* option is used. Additional
          parameters, in *option-value* pairs, can be passed to configure
          the appearance of the display item. Each *option-value* pair
          must be a valid option for this type of display item or one of
          the following:

         *-borderwidth* => color
               Specifies the border width of this header item.

         *-headerbackground* => color
               Specifies the background color of this header item.

         *-relief* => type
               Specifies the relief type of the border of this header item.

    *$hlist*->header(*delete, **$col*)
          Deletes the header display item for the *$col*-th column.

    *$hlist*->header(*exists, **$col*)
          Return true if an header display item exists for the *$col*-th
          column; return false otherwise.

    *$hlist*->header(size, *$entryPath*)
          If an header display item exists for the *$col*-th column ,
          returns its size in pixels in a two element list *(width,
          height)*; returns an error if the header display item does not
          exist.

*$hlist*->hide(option ?,*$entryPath*?)
     Makes some of entries invisible without deleting them.  Option can be
     one of the following:

    entry
          Hides the list entry identified by *$entryPath*.

     Currently only the entry option is supported. Other options will be
     added in the next release.

*$hlist*->*indicator*(option, *$entryPath*, ?*args, ...*?)
     Manipulates the indicator on the list entries. An indicator is usually
     a small display item (such as an image) that is displayed to the left
     to an entry to indicate the status of the entry.  For example, it may
     be used to indicate whether a directory is opened or closed.  Option
     can be one of the following:

    *$hlist*->*indicator*(cget, *$entryPath*, option)
          If the list entry given by *$entryPath* has an indicator, returns
          the value of the specified option of the indicator. If the
          indicator doesn't exist, returns an error.

    *$hlist*->*indicator*(configure, *$entryPath*, ?option?, *?value, option, value, ...*?)
          Query or modify the configuration options of the indicator
          display item of the entry specified by *$entryPath*. The
          indicator item must exist, or an error will result.  If no
          option is specified, returns a list describing all of the
          available options for the indicator display item (see
          Tk/options, for information on the format of this
          list). If option is specified with no value, then the method
          returns a list describing the one named option (this list will
          be identical to the corresponding sublist of the value returned
          if no option is specified). If one or more *option-value* pairs
          are specified, then the method modifies the given option(s) to
          have the given value(s); in this case the method returns an
          empty string.  Option may have any of the values accepted by the
          *indicator create* method. The exact set of options depends on
          the value of the *-itemtype* option passed to the the *indicator
          create* method when this display item was created.

    *$hlist*->*indicator*(*create, **$entryPath, *?, *-itemtype type*? ?*option value ...*?)
          Creates a new display item as the indicator for the entry
          specified by *$entryPath*. If an indicator display item already
          exists for this entry, it will be replaced by the new item.  An
          optional parameter *-itemtype* can be used to specify what type
          of display item should be created. If the *-itemtype* is not
          given, then by default the type specified by this HList widget's
          *-itemtype* option is used. Additional parameters, in
          *option-value* pairs, can be passed to configure the appearance
          of the display item. Each *option-value* pair must be a valid
          option for this type of display item.

    *$hlist*->*indicator*(delete, *$entryPath*)
          Deletes the indicator display item for the entry given by
          *$entryPath*.

    *$hlist*->*indicator*(exists, *$entryPath*)
          Return true if an indicator display item exists for the entry
          given by *$entryPath*; return false otherwise.

    *$hlist*->*indicator*(size, *$entryPath*)
          If an indicator display item exists for the entry given by
          *$entryPath*, returns its size in a two element list of the form
          {*width height*}; returns an error if the indicator display item
          does not exist.

*$hlist*->info(option, *arg, ...*)
     Query information about the HList widget. option can be one of the
     following:

    *$hlist*->info(anchor)
          Returns the entryPath of the current anchor, if any, of the HList
          widget. If the anchor is not set, returns the empty string.

    *$hlist*->*infoBbox*(*$entryPath*)
          Returns a list of four numbers describing the visible bounding
          box of the entry given *$entryPath*. The first two elements of
          the list give the x and y coordinates of the upper-left corner
          of the screen area covered by the entry (specified in pixels
          relative to the widget) and the last two elements give the
          lower-right corner of the area, in pixels. If no part of the
          entry given by index is visible on the screen then the result is
          an empty string; if the entry is partially visible, the result
          gives the only the visible area of the entry.

    *$hlist*->info(children ?,*$entryPath*?)
          If *$entryPath* is given, returns a list of the entryPath's of
          its children entries. Otherwise returns a list of the toplevel
          entryPath's.

    *$hlist*->info(data ?,*$entryPath*?)
          Returns the data associated with *$entryPath*.

    *$hlist*->info(*dragsite*)
          Returns the entryPath of the current dragsite, if any, of the
          HList widget. If the dragsite is not set, returns the empty
          string.

    *$hlist*->info(*dropsite*)
          Returns the entryPath of the current dropsite, if any, of the
          HList widget. If the dropsite is not set, returns the empty
          string.

    *$hlist*->info(exists, *$entryPath*)
          Returns a boolean value indicating whether the list entry
          *$entryPath* exists.

    *$hlist*->info(hidden, *$entryPath*)
          Returns a boolean value indicating whether the list entry
          *$entryPath* is hidden or not.

    *$hlist*->info(next, *$entryPath*)
          Returns the entryPath of the list entry, if any, immediately
          below this list entry. If this entry is already at the bottom of
          the HList widget, returns an empty string.

    *$hlist*->info(parent, *$entryPath*)
          Returns the name of the parent of the list entry identified by
          *$entryPath*. If *entryPath* is a toplevel list entry, returns
          the empty string.

    *$hlist*->info(prev, *$entryPath*)
          Returns the entryPath of the list entry, if any, immediately
          above this list entry. If this entry is already at the top of
          the HList widget, returns an empty string.

    *$hlist*->info(selection)
          Returns a list of selected entries in the HList widget. If no
          entries are selected, returns an empty string.

*$hlist*->item(*option, *?*args, ...*?)
     Creates and configures the display items at individual columns the
     entries. The form of additional of arguments depends on the choice of
     option:

    *$hlist*->*itemCget*(*$entryPath*, *$col*, option)
          Returns the current value of the configure option of the display
          item at the column designated by *$col* of the entry specified by
          *$entryPath*.

    *$hlist*->*itemConfigure*(*$entryPath*, *$col* ?,option?, *?value, option, value, ...*?)
          Query or modify the configuration options of the display item at
          the column designated by *$col* of the entry specified by
          *$entryPath*. If no option is specified, returns a list
          describing all of the available options for *$entryPath* (see
          Tk/options, for information on the format of
          this list). If option is specified with no value, then the
          method returns a list describing the one named option (this list
          will be identical to the corresponding sublist of the value
          returned if no option is specified). If one or more
          *option-value* pairs are specified, then the method modifies the
          given option(s) to have the given value(s); in this case the
          method returns an empty string.  Option may have any of the
          values accepted by the item create method. The exact set of
          options depends on the value of the *-itemtype* option passed to
          the the item create method when this display item was created.

    *$hlist*->*itemCreate*(*$entryPath*, *$col* ?,*-itemtype*=>type? ?,*option value ...*?)
          Creates a new display item at the column designated by *$col* of
          the entry specified by *$entryPath*. An optional parameter
          *-itemtype* can be used to specify what type of display items
          should be created. If the *-itemtype* is not specified, then by
          default the type specified by this HList widget's *-itemtype*
          option is used.  Additional parameters, in *option-value* pairs,
          can be passed to configure the appearance of the display item.
          Each *option- value* pair must be a valid option for this type of
          display item.

    *$hlist*->*itemDelete*(*$entryPath*, *$col*)
          Deletes the display item at the column designated by *$col* of
          the entry specified by *$entryPath*.

    *$hlist*->*itemExists*(*$entryPath*, *$col*)
          Returns true if there is a display item at the column designated
          by *$col* of the entry specified by *$entryPath*; returns false
          otherwise.

*$hlist*->nearest(y)
     *$hlist*->nearest(y) Given a y-coordinate within the HList window,
     this method returns the entryPath of the (visible) HList element
     nearest to that y-coordinate.

*$hlist*->see(*$entryPath*)
     Adjust the view in the HList so that the entry given by *$entryPath*
     is visible. If the entry is already visible then the method has no
     effect; if the entry is near one edge of the window then the HList
     scrolls to bring the element into view at the edge; otherwise the
     HList widget scrolls to center the entry.

*$hlist*->selection(option, *arg*, ...)
*$hlist*->selectionOption(*arg*, ...)
     This method is used to adjust the selection within a HList widget. It
     has several forms, depending on option:

    *$hlist*->*selectionClear*(?from?, ?to?)
          When no extra arguments are given, deselects all of the list
          entrie(s) in this HList widget. When only from is given, only
          the list entry identified by from is deselected. When both from
          and to are given, deselects all of the list entrie(s) between
          between from and to, inclusive, without affecting the selection
          state of elements outside that range.

    *$hlist*->*selectionGet*
          This is an alias for the *infoSelection* method.

    *$hlist*->*selectionIncludes*(*$entryPath*)
          Returns 1 if the list entry indicated by *$entryPath* is
          currently selected; returns 0 otherwise.

    *$hlist*->*selectionSet*(from?, to?)
          Selects all of the list entrie(s) between between from and to,
          inclusive, without affecting the selection state of entries
          outside that range. When only from is given, only the list entry
          identified by from is selected.

*$hlist*->show(option ?,*$entryPath*?)
     Show the entries that are hidden by the hide method, option can be
     one of the following:

    entry
          Shows the list entry identified by *$entryPath*.

     Currently only the entry option is supported. Other options will be
     added in future releases.

*$hlist*->*xview*(args)
     This method is used to query and change the horizontal position of the
     information in the widget's window. It can take any of the following
     forms:

    *$hlist*->*xview*
          Returns a list containing two elements.  Each element is a real
          fraction between 0 and 1; together they describe the horizontal
          span that is visible in the window.  For example, if the first
          element is .2 and the second element is .6, 20% of the HList
          entry is off-screen to the left, the middle 40% is visible in
          the window, and 40% of the entry is off-screen to the right.
          These are the same values passed to scrollbars via the
          *-xscrollcommand* option.

    *$hlist*->*xview*(*$entryPath*)
          Adjusts the view in the window so that the list entry identified
          by *$entryPath* is aligned to the left edge of the window.

    *$hlist*->*xview*(*moveto* => *fraction*)
          Adjusts the view in the window so that *fraction* of the total
          width of the HList is off-screen to the left. *fraction* must be
          a fraction between 0 and 1.

    *$hlist*->*xview*(scroll => *number, what*)
          This method shifts the view in the window left or right
          according to number and *what*. Number must be an integer.  What
          must be either *units* or *pages* or an abbreviation of one of
          these. If *what* is *units*, the view adjusts left or right by
          number character units (the width of the 0 character) on the
          display; if it is *pages* then the view adjusts by number
          screenfuls. If number is negative then characters farther to the
          left become visible; if it is positive then characters farther
          to the right become visible.

*$hlist*->*yview*(*?args*?)
     This method is used to query and change the vertical position of the
     entries in the widget's window. It can take any of the following
     forms:

    *$hlist*->*yview*
          Returns a list containing two elements, both of which are real
          fractions between 0 and 1.  The first element gives the position
          of the list element at the top of the window, relative to the
          HList as a whole (0.5 means it is halfway through the HList, for
          example).  The second element gives the position of the list
          entry just after the last one in the window, relative to the
          HList as a whole.  These are the same values passed to
          scrollbars via the *-yscrollcommand* option.

    *$hlist*->*yview*(*$entryPath*)
          Adjusts the view in the window so that the list entry given by
          *$entryPath* is displayed at the top of the window.

    *$hlist*->*yview*(*moveto* => *fraction*)
          Adjusts the view in the window so that the list entry given by
          *fraction* appears at the top of the window. *Fraction* is a
          fraction between 0 and 1; 0 indicates the first entry in the
          HList, 0.33 indicates the entry one-third the way through the
          HList, and so on.

    *$hlist*->*yview*(scroll => *number, what*)
          This method adjust the view in the window up or down according to
          number and *what*.  Number must be an integer.  What must be
          either *units* or *pages*.  If *what* is *units*, the view
          adjusts up or down by number lines; if it is *pages* then the
          view adjusts by number screenfuls.  If number is negative then
          earlier entries become visible; if it is positive then later
          entries become visible.

BINDINGS
========

[1]
     If the *-selectmode* is "browse", when the user drags the mouse
     pointer over the list entries, the entry under the pointer will be
     highlighted and the *-browsecmd* callback will be called with one
     parameter, the entryPath of the highlighted entry. Only one entry can
     be highlighted at a time. The *-command* callback will be called when
     the user double-clicks on a list entry.

[2]
     If the *-selectmode* is "single", the entries will only be
     highlighted by mouse <ButtonRelease-1> events. When a new list entry
     is highlighted, the *-browsecmd* callback will be called with one
     parameter indicating the highlighted list entry. The *-command*
     callback will be called when the user double-clicks on a list entry.

[3]
     If the *-selectmode* is "multiple", when the user drags the mouse
     pointer over the list entries, all the entries under the pointer will
     be highlighted. However, only a contiguous region of list entries can
     be selected. When the highlighted area is changed, the *-browsecmd*
     callback will be called with an undefined parameter. It is the
     responsibility of the *-browsecmd* callback to find out the exact
     highlighted selection in the HList. The *-command* callback will be
     called when the user double-clicks on a list entry.

[4]
     If the *-selectmode* is "extended", when the user drags the mouse
     pointer over the list entries, all the entries under the pointer will
     be highlighted. The user can also make disjointed selections using
     <Control-ButtonPress-1>. When the highlighted area is changed, the
     *-browsecmd* callback will be called with an undefined parameter. It
     is the responsibility of the *-browsecmd* callback to find out the
     exact highlighted selection in the HList. The *-command* callback
     will be called when the user double-clicks on a list entry.

[5]
     *Arrow key bindings:* <Up> arrow key moves the anchor point to the
     item right on top of the current anchor item. <Down> arrow key moves
     the anchor point to the item right below the current anchor item.
     <Left> arrow key moves the anchor to the parent item of the current
     anchor item. <Right> moves the anchor to the first child of the
     current anchor item. If the current anchor item does not have any
     children, moves the anchor to the item right below the current anchor
     item.

EXAMPLE
=======

   This example demonstrates how to use an HList to store a file directory
structure and respond to the user's browse events:

     use strict;
     use Tk;
     use Tk::Label;
     use Tk::HList;

     my $mw = MainWindow->new();
     my $label = $mw->Label(-width=>15);
     my $hlist = $mw->HList(
                         -itemtype   => 'text',
                         -separator  => '/',
                         -selectmode => 'single',
                         -browsecmd  => sub {
                                   my $file = shift;
                                   $label->configure(-text=>$file);
                                }
                         );

     foreach ( qw(/ /home /home/ioi /home/foo /usr /usr/lib) ) {
         $hlist->add($_, -text=>$_);
     }

     $hlist->pack;
     $label->pack;

     MainLoop;

BUGS
====

   The fact that the display item at column 0 is implicitly associated
with the whole entry is probably a design bug. This was done for backward
compatibility purposes. The result is that there is a large overlap
between the item method and the add, *addchild*, *entrycget* and
*entryconfigure* methods.  Whenever multiple columns exist, the programmer
should use ONLY the item method to create and configure the display items
in each column; the add, *addchild*, *entrycget* and *entryconfigure*
should be used ONLY to create and configure entries.

KEYWORDS
========

   Hierarchical Listbox

SEE ALSO
========

   `Tk::DItem|Tk::DItem' in this node

Tk I/O routines for the LWP library
***********************************

NAME
====

   LWP::TkIO - Tk I/O routines for the LWP library

SYNOPSIS
========

     use Tk;
     require LWP::TkIO;
     require LWP::UserAgent;

DESCRIPTION
===========

   This module provide replacement functions for the LWP::IO functions.
Require this module if you use Tk and want non exclusive IO behaviour from
LWP.

   See also LWP/IO.

Entry widget with history capability
************************************

NAME
====

   Tk::HistEntry - Entry widget with history capability

SYNOPSIS
========

     use Tk::HistEntry;

     $hist1 = $top->HistEntry(-textvariable => \$var1);
     $hist2 = $top->SimpleHistEntry(-textvariable => \$var2);

DESCRIPTION
===========

   `Tk::HistEntry' defines entry widgets with history capabilities. The
widgets come in two flavours:

`HistEntry' (in package `Tk::HistEntry::Browse') - with associated browse entry
`SimpleHistEntry' (in package `Tk::HistEntry::Simple') - plain widget without browse entry
   The user may browse with the *Up* and *Down* keys through the history
list.  New history entries may be added either manually by binding the
Return key to *historyAdd()* or automatically by setting the *-command*
option.

OPTIONS
=======

   *HistEntry* is an descendant of *BrowseEntry* and thus supports all of
its standard options.

   *SimpleHistEntry* is an descendant of Entry and supports all of the
Entry options.

   In addition, the widgets support following specific options:

*-textvariable* or *-variable*
     Variable which is tied to the HistEntry widget. Either
     *-textvariable* (like in Entry) or *-variable* (like in BrowseEntry)
     may be used.

*-command*
     Specifies a callback, which is executed when the Return key was
     pressed or the *invoke* method is called. The callback reveives three
     arguments: the reference to the HistEntry widget, the current
     textvariable value and a boolean value, which tells whether the
     string was added to the history list (e.g. duplicates and empty
     values are not added to the history list).

*-dup*
     Specifies whether duplicate entries are allowed in the history list.
     Defaults to true.

*-bell*
     If set to true, rings the bell if the user tries to move off of the
     history or if a search was not successful. Defaults to true.

*-limit*
     Limits the number of history entries. Defaults to unlimited.

*-match*
     Turns auto-completion on.

*-case*
     If set to true a true value, then be case sensitive on
     auto-completion. Defaults to 1.

METHODS
=======

*historyAdd(*[string])
     Adds string (or the current textvariable value if not set) manually
     to the history list. *addhistory* is an alias for *historyAdd*.
     Returns the added string or undef if no addition was made.

*invoke(*[string])
     Invokes the command specified with *-command*.

*history(*[*arrayref*])
     Without argument, returns the current history list. With argument (a
     reference to an array), replaces the history list.

*historySave(*file)
     Save the history list to the named file.

*historyMergeFromFile(*file)
     Merge the history list from the named file to the end of the current
     history list of the widget.

historyReset
     Remove all entries from the history list.

KEY BINDINGS
============

*Up*, *Control-p*
     Selects the previous history entry.

*Down*, *Control-n*
     Selects the next history entry.

*Meta-<*, *Alt-<*
     Selects first entry.

*Meta->*, *Alt->*
     Selects last entry.

Control-r
     The current content of the widget is searched backward in the history.

Control-s
     The current content of the widget is searched forward in the history.

Return
     If *-command* is set, adds current content to the history list and
     executes the associated callback.

EXAMPLE
=======

   This is an simple example for Tk::HistEntry. More examples can be found
in the t and examples directories of the source distribution.

     use Tk;
     use Tk::HistEntry;

     $top = new MainWindow;
     $he = $top->HistEntry(-textvariable => \$foo,
                           -command => sub {
                               # automatically adds $foo to history
                               print STDERR "Do something with $foo\n";
                           })->pack;
     $b = $top->Button(-text => 'Do it',
                       -command => sub { $he->invoke })->pack;
     MainLoop;

   If you like to not depend on the installation of Tk::HistEntry, you can
write something like this:

     $Entry = "SimpleHistEntry";
     eval {
         # try loading the module, otherwise $Entry is left to the value "Entry"
     	require Tk::HistEntry;
     	$Entry = "SimpleHistEntry";
     };
     $entry = $status_frame->$Entry(-textvariable => \$res)->pack;
     $entry->bind("<Return>" => sub {
                                    # check whether the historyAdd method is
     		                   # known to the widget
     		                   if ($entry->can('historyAdd')) {
     				       $entry->historyAdd;
     				   }
                                });

BUGS/TODO
=========

     - C-s/C-r do not work as nice as in gnu readline
     - use -browsecmd from Tk::BrowseEntry
     - use Tie::Array if present

AUTHOR
======

   Slaven Rezic <eserte@cs.tu-berlin.de>

CREDITS
=======

   Thanks for Jason Smith <smithj4@rpi.edu> and Benny Khoo
<kkhoo1@penang.intel.com> for their suggestions. The auto-completion code
is stolen from Tk::IntEntry by Dave Collins <Dave.Collins@tiuk.ti.com>.

COPYRIGHT
=========

   Copyright (c) 1997, 2000, 2001 Slaven Rezic. All rights reserved.  This
package is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

high level interface to Tk's 'fileevent' mechanism
**************************************************

NAME
====

   Tk::IO - high level interface to Tk's 'fileevent' mechanism

SYNOPSIS
========

     my $fh = Tk::IO->new(-linecommand => callback, -childcommand => callback);
     $fh->exec("command")
     $fh->wait
     $fh->kill

WARNING
=======

   INTERFACES TO THIS MODULE MAY CHANGE AS PERL'S IO EVOLVES AND WITH PORT
OF TK4.1

DESCRIPTION
===========

   Tk::IO is now layered on perl's IO::Handle class. Interfaces have
changed, and are still evolving.

   In theory C methods which enable non-blocking IO as in earlier Tk-b*
release(s) are still there. I have not changed them to use perl's
additional Configure information, or tested them much.

   Assumption is that exec is used to fork a child process and a callback
is called each time a complete line arrives up the implied pipe.

   "line" should probably be defined in terms of perl's input record
separator but is not yet.

   The -childcommand callback is called when end-of-file occurs.

   $fh->wait can be used to wait for child process while processing other
Tk events.

   $fh->kill can be used to send signal to child process.

BUGS
====

   Still not finished.  Idea is to use "exec" to emulate "system" in a
non-blocking manner.

Canvas with dragable icon management
************************************

NAME
====

   Tk::IconCanvas - Canvas with dragable icon management

SYNOPSIS
========

     use Tk;

     my $MainWindow = MainWindow->new();

     Tk::MainLoop;

DESCRIPTION
===========

AUTHORS
=======

   Damion K. Wilson, dkw@rcm.bm

HISTORY    =cut
===============

Create and manipulate images
****************************

NAME
====

   Tk::Image - Create and manipulate images

   *$image* = $widget->type(?*arg arg ...*?)

   *$image*->method(?*arg arg ...*?)

DESCRIPTION
===========

   The image constructors and methods are used to create, delete, and
query images.  It can take several different forms, depending on the type.

   The constructors require a $widget to invoke them, this is used to
locate a *MainWindow*. (This is because the underlying Tk code registers
the images in the data structure for the *MainWindow*.)

   The legal forms are:

$widget->type?(?name?,?option=>*value ...*)?
     Creates a new image and returns an object.  type specifies the type
     of the image, which must be one of the types currently defined (e.g.,
     Bitmap).  name specifies the name for the image;  if it is omitted
     then Tk picks a name of the form imagex, where x is an integer.
     There may be any number of option=>value pairs, which provide
     configuration options for the new image.  The legal set of options is
     defined separately for each image type;  see below for details on the
     options for built-in image types.  If an image already exists by the
     given name then it is replaced with the new image and any instances
     of that image will redisplay with the new contents.

*$image*->delete
     Deletes the image *$image* and returns an empty string.  If there are
     instances of the image displayed in widgets, the image won't actually
     be deleted until all of the instances are released.  However, the
     association between the instances and the image manager will be
     dropped.  Existing instances will retain their sizes but redisplay as
     empty areas.  If a deleted image is recreated (with the same name)
     the existing instances will use the new image.

*$image*->height
     Returns a decimal string giving the height of image name in pixels.

$widget->*imageNames*
     Returns a list containing all existing images for $widget's
     *MainWindow*.

*$image*->type
     Returns the type of  *$image* (the value of the type method when the
     image was created).

$widget->*imageTypes*
     Returns a list whose elements are all of the valid image types (i.e.,
     all of the values that may be supplied for the type to create an
     image).

*$image*->width
     Returns a decimal string giving the width of image name in pixels.

BUILT-IN IMAGE TYPES
====================

   The following image types are defined by Tk so they will be available
in any Tk application.  Individual applications or extensions may define
additional types.

Bitmap
     Each pixel in the image displays a foreground color, a background
     color, or nothing.  See Tk/Bitmap, for more
     information.

Pixmap
     Pixmap is slightly more general than Bitmap, each pixel can be any
     available color or "transparent" (rendered as background color of the
     widget image is displayed in). Pixmap is best used for icons and other
     simple graphics with only a few colors.

     Pixmap is derived from Tix. See Tk/Pixmap, for more
     information.

Photo
     Displays a variety of full-color images, using dithering to
     approximate colors on displays with limited color capabilities.  See
     Tk/Photo, documentation for more information.

SEE ALSO
========

   `Tk::Bitmap|Tk::Bitmap' in this node `Tk::Pixmap|Tk::Pixmap' in this
node `Tk::Photo|Tk::Photo' in this node

KEYWORDS
========

   height, image, types of images, width

Create and manipulate TIX InputO widgets
****************************************

NAME
====

   Tk::InputO - Create and manipulate TIX InputO widgets

   *$inputonly* = *$parent*->*InputO*(?options?);

STANDARD OPTIONS
================

   Only the following three standard options are supported by *InputO*:

   cursor	width	height

   See Tk/options, for details of the standard options.

WIDGET-SPECIFIC OPTIONS
=======================

   *InputO* does not have any widget specific options.

DESCRIPTION
===========

   The *InputO* method creates a new window (given by the $widget
argument) and makes it into a *InputO* widget.  Additional options,
described above, may be specified on the command line or in the option
database to configure aspects of the *InputO* such as its cursor or width.

   *InputO* widgets are not visible to the user. The only purpose of
*InputO* widgets are to accept inputs from the user, which can be done
with the bind method.

WIDGET METHODS
==============

   The *InputO* method creates a widget object.  This object supports the
configure and cget methods described in Tk/options,
which can be used to enquire and modify the options described above.  The
widget also inherits all the methods provided by the generic
`Tk::Widget|Tk::Widget' in this node class.

BINDINGS
========

   *InputO* widgets have no default bindings.

what is Perl Tk interface doing when you call Tk functions.
***********************************************************

NAME
====

   CallingTk -  what is Perl Tk interface doing when you call Tk functions.

   *This document is under construction. The information is believed to be
pertinent to the version of* `portableTk' *available when it was created.
All the details are subject to change.*

DESCRIPTION
===========

PreCompiling
     Before the actual compilation stage a script scans the source and
     extracts the subcommands of different commands. This information
     resides in the file `pTk/Methods.def'.

Compilation
     During compilation the above file is included in the source of booting
     routine of dynamic (or static) library. More precisely, the booting
     code of module Tk calls the subroutine Boot_Glue() from the module
     `tkGlue.c', and this subroutine includes the file (with appropriate
     macro definitions).

Inside `use Tk;'
     The module bootstraps the C code, then loads the Perl libraries. The
     heart of the Perl code is contained in the `Tk::Widget' library, all
     the widgets inherit from this module. Code for toplevels is loaded
     from `Tk::MainWindow'.

     During bootstrap of the C glue code the `Xevent::?' codes and a
     handful of `Tk::Widget' and Tk::Image routines are defined. (Much
     more XSUBs are created from `Tk.xs' code.) The widget subcommands are
     glued to Perl basing on the list included from `pTk/Methods.def'. In
     fact all the subcommands are glued to XSUBs that are related to the
     same C subroutine XStoWidget(), but have different data parts.

     During the Perl code bootstrap the method `Tk::Widget::import' is
     called. This call requires all the code from particular widget
     packages.

     Code from the widget packages calls an obscure command like

          (bless \"Text")->WidgetClass;

     This command (actually Tk::Widget::WidgetClass()) creates three
     routines: Tk::Widget::Text(), Tk::Widget::isText(), and
     Tk::Text::isText(). The first one is basically new of `Tk::Text', the
     other two return constants. It also puts the class into depository.

Inside `$top = MainWindow->new;'
     This is quite intuitive. This call goes direct to
     `Tk::MainWindow::new', that calls XSUB
     `Tk::MainWindow::CreateMainWindow', that calls C subroutine
     Tk_CreateMainWindow(). It is a Tk subroutine, so here black magic
     ends (almost).

     The only remaining black magic is that the Tk initialization routine
     creates a lot of commands, but the subroutine for creation is usurped
     by *portableTk* and the commands are created in the package Tk. They
     are associated to XSUBs that are related to one of three C
     subroutines XStoSubCmd(), XStoBind(), or XStoTk(), but have different
     data parts.

     The result of the call is blessed into `Tk::MainWindow', as it should.

Inside `$top->title('Text demo');'
     The package `Tk::Toplevel' defines a lot of subroutines on the fly on
     some list. All the commands from the list are converted to the
     corresponding subcommands of `wm' method of the widget. Here
     subcommand is a command with some particular second argument (in this
     case `"title"'). Recall that the first argument is $self.

     Now `Tk::Toplevel' @ISA `Tk::Widget', that in turn @ISA Tk. So a call
     to `$top->wm('title','Text demo')' calls `Tk::wm', that is defined
     during call to Tk_CreateMainWindow(). As it is described above, the
     XSUB associated to XStoSubCmd() is called.

     This C routine is defined in `tkGlue.c'. It gets the data part of
     XSUB, creates a SV with the name of the command, and calls Call_Tk()
     with the XSUB data as the first argument, and with the name of XSUB
     stuffed into the Perl stack in the place there tk expects it. (In
     fact it can also reorder the arguments if it thinks it is what you
     want).

     The latter procedure extracts name of tk procedure and `clientData'
     from the first argument and makes a call, using Perl stack as `argv'
     for the procedure. A lot of black magic is performed afterwards to
     convert result of the procedure to a Perl array return.

Inside `$text = $top->Text(background => $txtBg);'
     Above we discussed how the command `Tk::Widget::Text' is created. The
     above command calls it via inheritance. It is translated to

          Tk::Text::new($top, background => $txtBg);

     The package `Tk::Text' has no method new, so the `Tk::Widget::new' is
     called. In turn it calls `Tk::Text->DoInit($top)', that is
     `Tk::Widget::DoInit(Tk::Text,$top)', that initializes the bindings if
     necessary. Then it creates the name for the widget of the form
     `.text0', and calls `Tk::text('.text0', background => $txtBg)' (note
     lowercase). The result of the call is blessed into `Tk::Text', and
     the method `bindtags' for this object is called.

     Now the only thing to discuss is who defines the methods text and
     `bindtags'. The answer is that they are defined in `tkWindow.c', and
     these commands are created in the package Tk in the same sweep that
     created the command `Tk::wm' discussed above.

     So the the same C code that corresponds to the processing of
     corresponding TCL commands is called here as well (this time via
     `XStoTk' interface).

Inside `$text->insert('insert','Hello, world!');'
     As we discussed above, the subcommands of widget procedures correspond
     to XSUB `XStoWidget'. This XSUB substitutes the first argument $text
     (that is a hash reference) to an appropriate value from this hash,
     adds the additional argument after the first one that contains the
     name of the subcommand extracted from the data part of XSUB, and calls
     the corresponding Tk C subroutine via `Call_Tk'.

   Ilya Zakharevich <ilya@math.ohio-state.edu>

Base class for Menu items
*************************

NAME
====

   Tk::Menu::Item - Base class for Menu items

SYNOPSIS
========

     require Tk::Menu::Item;

     my $but = $menu->Button(...);
     $but->configure(...);
     my $what = $but->cget();

     package Whatever;
     require Tk::Menu::Item;
     @ISA = qw(Tk::Menu::Item);

     sub PreInit
     {
      my ($class,$menu,$info) = @_;
      $info->{'-xxxxx'} = ...
      my $y = delete $info->{'-yyyy'};
     }

DESCRIPTION
===========

   Tk::Menu::Item is the base class from which Tk::Menu::Button,
Tk::Menu::Cascade, Tk::Menu::Radiobutton and Tk::Menu::Checkbutton are
derived.  There is also a Tk::Menu::Separator.

   Constructors are declared so that $menu->Button(...) etc. do what you
would expect.

   The `-label' option is pre-processed allowing ~ to be prefixed to the
character to derive a `-underline' value. Thus

     $menu->Button(-label => 'Goto ~Home',...)

     is equivalent to

     $menu->Button(-label => 'Goto Home', -underline => 6, ...)

   The `Cascade' menu item creates a sub-menu and accepts these options:

*-menuitems*
     A list of items for the sub-menu.  Within this list (which is also
     accepted by Menu and Menubutton) the first two elements of each item
     should be the "constructor" name and the label:

          -menuitems => [
                         [Button      => '~Quit', -command => [destroy => $mw]],
                         [Checkbutton => '~Oil',  -variable => \$oil],
                        ]

*-postcommand*
     A callback to be invoked before posting the menu.

*-tearoff*
     Specifies whether sub-menu can be torn-off or not.

*-menuvar*
     Scalar reference that will be set to the newly-created sub-menu.

   The returned object is currently a blessed reference to an array of two
items: the containing Menu and the 'label'.  Methods configure and cget
are mapped onto underlying `entryconfigure' and `entrycget'.

   The main purpose of the OO interface is to allow derived item classes to
be defined which pre-set the options used to create a more basic item.

BUGS
====

   This OO interface is very new. Using the label as the "key" is a problem
for separaror items which don't have one. The alternative would be to use
an index into the menu but that is a problem if items are deleted (or
inserted other than at the end).

   There should probably be a PostInit entry point too, or a more widget
like defered 'configure'.

JPEG loader for Tk::Photo
*************************

NAME
====

   Tk::JPEG - JPEG loader for Tk::Photo

SYNOPSIS
========

     use Tk;
     use Tk::JPEG;

     my $image = $widget->Photo('-format' => 'jpeg', -file => 'something.jpg');

DESCRIPTION
===========

   This is an extension for Tk800.015 and later which supplies JPEG format
loader for Photo image type.

   JPEG access is via release 5 of the The Independent JPEG Group's (IJG)
free JPEG software.

AUTHOR
======

   Nick Ing-Simmons <nick@ni-s.u-net.com>

labeled frame.
**************

NAME
====

   Tk::LabFrame - labeled frame.

SYNOPSIS
========

       *use Tk::LabFrame;*

       $f = *$parent*->*LabFrame*(?*-label*=>text, *-labelside*=>where,
...?);

DESCRIPTION
===========

   *LabFrame* is exactly like Frame and additionaly allows to add a label
to the frame.

WIDGET-OPTIONS
==============

   *LabFrame* supports the same options as the `Frame|Tk::Frame' in this
node widget.

   Additional options of *LabFrame* are:

*-label* => text
     The text of the label to be placed with the Frame.

*-labelside* => where
     Where can be one of left, right, top, *bottom* or *acrosstop*.  The
     first four work as might be expected and place the label to the left,
     right, above or below the frame respectively. The *acrosstop* creates
     a grooved frame around the central frame and puts the label near the
     northwest corner such that it appears to "overwrite" the groove.

EXAMPLE
=======

   Run the following test program to see this in action:

     use strict;
     use Tk;
     require Tk::LabFrame;
     require Tk::LabEntry;

     my $test = 'Test this';
     my $mw = Tk::MainWindow->new;
     my $f = $mw->LabFrame(-label => "This is a label",
     			   -labelside => "acrosstop");
     $f->LabEntry(-label => "Testing", -textvariable => \$test)->pack;
     $f->pack;
     Tk::MainLoop;

BUGS
====

   Perhaps *LabFrame* should be subsumed within the generic pTk labeled
widget mechanism.

AUTHOR
======

   *Rajappa Iyer* rsi@earthling.net

   This code is derived from LabFrame.tcl and LabWidg.tcl in the Tix4.0
distribution by Ioi Lam. The code may be redistributed under the same
terms as Perl.

Create and manipulate Label widgets
***********************************

NAME
====

   Tk::Label - Create and manipulate Label widgets

   $label = *$parent*->Label(?options?);

STANDARD OPTIONS
================

   *-anchor*	*-font*	*-image*	*-takefocus*
*-background*	*-foreground*	-justify	*-text*
*-bitmap*	*-highlightbackground*	*-padx*	*-textvariable*
*-borderwidth*	*-highlightcolor*	*-pady*	*-underline*
*-cursor*	*-highlightthickness*	*-relief*	*-wraplength*

   See Tk/options, for details of the standard options.

WIDGET-SPECIFIC OPTIONS
=======================

Name:	height
Class:	*Height*
Switch:	*-height*
     Specifies a desired height for the label.  If an image or bitmap is
     being displayed in the label then the value is in screen units (i.e.
     any of the forms acceptable to *Tk_GetPixels*); for text it is in
     lines of text.  If this option isn't specified, the label's desired
     height is computed from the size of the image or bitmap or text being
     displayed in it.

Name:	width
Class:	Width
Switch:	*-width*
     Specifies a desired width for the label.  If an image or bitmap is
     being displayed in the label then the value is in screen units (i.e.
     any of the forms acceptable to *Tk_GetPixels*); for text it is in
     characters.  If this option isn't specified, the label's desired
     width is computed from the size of the image or bitmap or text being
     displayed in it.

DESCRIPTION
===========

   The Label method creates a new window (given by the $widget argument)
and makes it into a label widget.  Additional options, described above,
may be specified on the command line or in the option database to
configure aspects of the label such as its colors, font, text, and initial
relief.  The label command returns its $widget argument.  At the time this
command is invoked, there must not exist a window named $widget, but
$widget's parent must exist.

   A label is a widget that displays a textual string, bitmap or image.
If text is displayed, it must all be in a single font, but it can occupy
multiple lines on the screen (if it contains newlines or if wrapping
occurs because of the *wrapLength* option) and one of the characters may
optionally be underlined using the underline option.  The label can be
manipulated in a few simple ways, such as changing its relief or text,
using the commands described below.

WIDGET METHODS
==============

   The Label method creates a widget object.  This object supports the
configure and cget methods described in Tk/options,
which can be used to enquire and modify the options described above.  The
widget also inherits all the methods provided by the generic
`Tk::Widget|Tk::Widget' in this node class.

BINDINGS
========

   When a new label is created, it has no default event bindings: labels
are not intended to be interactive.

KEYWORDS
========

   label, widget

Create and manipulate Listbox widgets
*************************************

NAME
====

   Tk::Listbox - Create and manipulate Listbox widgets

   *$listbox* = *$parent*->Listbox(?options?);

STANDARD OPTIONS
================

   *-background*	*-foreground*	*-relief*	*-takefocus*
*-borderwidth*	*-height*	*-selectbackground*	*-width*
*-cursor*	*-highlightbackground*	*-selectborderwidth*	*-xscrollcommand*
*-exportselection*	*-highlightcolor*	*-selectforeground*	*-yscrollcommand*
*-font*	*-highlightthickness*	*-setgrid*

   See Tk/options, for details of the standard options.

WIDGET-SPECIFIC OPTIONS
=======================

Name:	height
Class:	*Height*
Switch:	*-height*
     Specifies the desired height for the window, in lines.  If zero or
     less, then the desired height for the window is made just large
     enough to hold all the elements in the listbox.

Name:	*selectMode*
Class:	*SelectMode*
Switch:	*-selectmode*
     Specifies one of several styles for manipulating the selection.  The
     value of the option may be arbitrary, but the default bindings expect
     it to be either single, browse, multiple, or *extended*;  the default
     value is browse.

Name:	width
Class:	Width
Switch:	*-width*
     Specifies the desired width for the window in characters.  If the
     font doesn't have a uniform width then the width of the character "0"
     is used in translating from character units to screen units.  If zero
     or less, then the desired width for the window is made just large
     enough to hold all the elements in the listbox.

DESCRIPTION
===========

   The Listbox method creates a new window (given by the $widget argument)
and makes it into a listbox widget.  Additional options, described above,
may be specified on the command line or in the option database to
configure aspects of the listbox such as its colors, font, text, and
relief.  The listbox command returns its $widget argument.  At the time
this command is invoked, there must not exist a window named $widget, but
$widget's parent must exist.

   A listbox is a widget that displays a list of strings, one per line.
When first created, a new listbox has no elements.  Elements may be added
or deleted using methods described below.  In addition, one or more
elements may be selected as described below.  If a listbox is exporting
its selection (see *exportSelection* option), then it will observe the
standard X11 protocols for handling the selection.  Listbox selections are
available as type STRING; the value of the selection will be the text of
the selected elements, with newlines separating the elements.

   It is not necessary for all the elements to be displayed in the listbox
window at once;  commands described below may be used to change the view
in the window.  Listboxes allow scrolling in both directions using the
standard *xScrollCommand* and *yScrollCommand* options.  They also support
scanning, as described below.

INDICES
=======

   Many of the methods for listboxes take one or more indices as arguments.
An index specifies a particular element of the listbox, in any of the
following ways:

number
     Specifies the element as a numerical index, where 0 corresponds to
     the first element in the listbox.

active
     Indicates the element that has the location cursor.  This element
     will be displayed with an underline when the listbox has the keyboard
     focus, and it is specified with the activate method.

anchor
     Indicates the anchor point for the selection, which is set with the
     *selection anchor* method.

end
     Indicates the end of the listbox.  For most commands this refers to
     the last element in the listbox, but for a few commands such as index
     and insert it refers to the element just after the last one.

*@*x*,*y
     Indicates the element that covers the point in the listbox window
     specified by x and y (in pixel coordinates).  If no element covers
     that point, then the closest element to that point is used.

   In the method descriptions below, arguments named index, first, and
last always contain text indices in one of the above forms.

WIDGET METHODS
==============

   The Listbox method creates a widget object.  This object supports the
configure and cget methods described in Tk/options,
which can be used to enquire and modify the options described above.  The
widget also inherits all the methods provided by the generic
`Tk::Widget|Tk::Widget' in this node class.

   The following additional methods are available for listbox widgets:

*$listbox*->activate(index)
     Sets the active element to the one indicated by index.  If index is
     outside the range of elements in the listbox then the closest element
     is activated.  The active element is drawn with an underline when the
     widget has the input focus, and its index may be retrieved with the
     index active.

*$listbox*->*bbox*(index)
     Returns a list of four numbers describing the bounding box of the
     text in the element given by index.  The first two elements of the
     list give the x and y coordinates of the upper-left corner of the
     screen area covered by the text (specified in pixels relative to the
     widget) and the last two elements give the width and height of the
     area, in pixels.  If no part of the element given by index is visible
     on the screen, or if index refers to a non-existent element, then the
     result is an empty string;  if the element is partially visible, the
     result gives the full area of the element, including any parts that
     are not visible.

*$listbox*->*curselection*
     Returns a list containing the numerical indices of all of the
     elements in the listbox that are currently selected.  If there are no
     elements selected in the listbox then an empty string is returned.

*$listbox*->delete(*first, *?last?)
     Deletes one or more elements of the listbox.  First and last are
     indices specifying the first and last elements in the range to
     delete.  If last isn't specified it defaults to first, i.e. a single
     element is deleted.

*$listbox*->get(*first, *?last?)
     If last is omitted, returns the contents of the listbox element
     indicated by first, or an empty string if first refers to a
     non-existent element.  If last is specified, the command returns a
     list whose elements are all of the listbox elements between first and
     last, inclusive.  Both first and last may have any of the standard
     forms for indices.

*$listbox*->index(index)
     Returns the integer index value that corresponds to index.  If index
     is end the return value is a count of the number of elements in the
     listbox (not the index of the last element).

*$listbox*->insert(*index, *?*element, element, ...*?)
     Inserts zero or more new elements in the list just before the element
     given by index.  If index is specified as end then the new elements
     are added to the end of the list.  Returns an empty string.

*$listbox*->nearest(y)
     Given a y-coordinate within the listbox window, this command returns
     the index of the (visible) listbox element nearest to that
     y-coordinate.

*$listbox*->scan(*option, args*)
     This command is used to implement scanning on listboxes.  It has two
     forms, depending on option:

    *$listbox*->*scanMark*(*x, y*)
          Records x and y and the current view in the listbox window;
          used in conjunction with later *scan dragto* commands.
          Typically this command is associated with a mouse button press in
          the widget.  It returns an empty string.

    *$listbox*->*scanDragto*(*x, y*.)
          This command computes the difference between its x and y
          arguments and the x and y arguments to the last *scan mark*
          command for the widget.  It then adjusts the view by 10 times the
          difference in coordinates.  This command is typically associated
          with mouse motion events in the widget, to produce the effect of
          dragging the list at high speed through the window.  The return
          value is an empty string.

*$listbox*->see(index)
     Adjust the view in the listbox so that the element given by index is
     visible.  If the element is already visible then the command has no
     effect; if the element is near one edge of the window then the listbox
     scrolls to bring the element into view at the edge;  otherwise the
     listbox scrolls to center the element.

*$listbox*->selection(*option, arg*)
     This command is used to adjust the selection within a listbox.  It
     has several forms, depending on option:

    *$listbox*->*selectionAnchor*(index)
          Sets the selection anchor to the element given by index.  If
          index refers to a non-existent element, then the closest element
          is used.  The selection anchor is the end of the selection that
          is fixed while dragging out a selection with the mouse.  The
          index anchor may be used to refer to the anchor element.

    *$listbox*->*selectionClear*(*first, *?last?)
          If any of the elements between first and last (inclusive) are
          selected, they are deselected.  The selection state is not
          changed for elements outside this range.

    *$listbox*->*selectionIncludes*(index)
          Returns 1 if the element indicated by index is currently
          selected, 0 if it isn't.

    *$listbox*->*selectionSet*(*first, *?last?)
          Selects all of the elements in the range between first and last,
          inclusive, without affecting the selection state of elements
          outside that range.

*$listbox*->size
     Returns a decimal string indicating the total number of elements in
     the listbox.

*$listbox*->*xview*(args)
     This command is used to query and change the horizontal position of
     the information in the widget's window.  It can take any of the
     following forms:

    *$listbox*->*xview*
          Returns a list containing two elements.  Each element is a real
          fraction between 0 and 1;  together they describe the horizontal
          span that is visible in the window.  For example, if the first
          element is .2 and the second element is .6, 20% of the listbox's
          text is off-screen to the left, the middle 40% is visible in the
          window, and 40% of the text is off-screen to the right.  These
          are the same values passed to scrollbars via the
          *-xscrollcommand* option.

    *$listbox*->*xview*(index)
          Adjusts the view in the window so that the character position
          given by index is displayed at the left edge of the window.
          Character positions are defined by the width of the character 0.

    *$listbox*->*xview*(*moveto* => *fraction*)
          Adjusts the view in the window so that *fraction* of the total
          width of the listbox text is off-screen to the left.  *fraction*
          must be a fraction between 0 and 1.

    *$listbox*->*xview*(scroll => *number, what*)
          This command shifts the view in the window left or right
          according to number and *what*.  Number must be an integer.
          What must be either *units* or *pages* or an abbreviation of one
          of these.  If *what* is *units*, the view adjusts left or right
          by number character units (the width of the 0 character) on the
          display;  if it is *pages* then the view adjusts by number
          screenfuls.  If number is negative then characters farther to
          the left become visible;  if it is positive then characters
          farther to the right become visible.

*$listbox*->*yview*(*?args*?)
     This command is used to query and change the vertical position of the
     text in the widget's window.  It can take any of the following forms:

    *$listbox*->*yview*
          Returns a list containing two elements, both of which are real
          fractions between 0 and 1.  The first element gives the position
          of the listbox element at the top of the window, relative to the
          listbox as a whole (0.5 means it is halfway through the listbox,
          for example).  The second element gives the position of the
          listbox element just after the last one in the window, relative
          to the listbox as a whole.  These are the same values passed to
          scrollbars via the *-yscrollcommand* option.

    *$listbox*->*yview*(index)
          Adjusts the view in the window so that the element given by
          index is displayed at the top of the window.

    *$listbox*->*yview*(*moveto* => *fraction*)
          Adjusts the view in the window so that the element given by
          *fraction* appears at the top of the window.  *Fraction* is a
          fraction between 0 and 1;  0 indicates the first element in the
          listbox, 0.33 indicates the element one-third the way through
          the listbox, and so on.

    *$listbox*->*yview*(scroll => *number, what*)
          This command adjusts the view in the window up or down according
          to number and *what*.  Number must be an integer.  What must be
          either *units* or *pages*.  If *what* is *units*, the view
          adjusts up or down by number lines;  if it is *pages* then the
          view adjusts by number screenfuls.  If number is negative then
          earlier elements become visible;  if it is positive then later
          elements become visible.

DEFAULT BINDINGS
================

   Tk automatically creates class bindings for listboxes that give them
Motif-like behavior.  Much of the behavior of a listbox is determined by
its *selectMode* option, which selects one of four ways of dealing with
the selection.

   If the selection mode is single or browse, at most one element can be
selected in the listbox at once.  In both modes, clicking button 1 on an
element selects it and deselects any other selected item.  In browse mode
it is also possible to drag the selection with button 1.

   If the selection mode is multiple or *extended*, any number of elements
may be selected at once, including discontiguous ranges.  In multiple
mode, clicking button 1 on an element toggles its selection state without
affecting any other elements.  In *extended* mode, pressing button 1 on an
element selects it, deselects everything else, and sets the anchor to the
element under the mouse;  dragging the mouse with button 1 down extends
the selection to include all the elements between the anchor and the
element under the mouse, inclusive.

   Most people will probably want to use browse mode for single selections
and *extended* mode for multiple selections; the other modes appear to be
useful only in special situations.

   In addition to the above behavior, the following additional behavior is
defined by the default bindings:

[1]
     In *extended* mode, the selected range can be adjusted by pressing
     button 1 with the Shift key down:  this modifies the selection to
     consist of the elements between the anchor and the element under the
     mouse, inclusive.  The un-anchored end of this new selection can also
     be dragged with the button down.

[2]
     In *extended* mode, pressing button 1 with the Control key down
     starts a toggle operation: the anchor is set to the element under the
     mouse, and its selection state is reversed.  The selection state of
     other elements isn't changed.  If the mouse is dragged with button 1
     down, then the selection state of all elements between the anchor and
     the element under the mouse is set to match that of the anchor
     element;  the selection state of all other elements remains what it
     was before the toggle operation began.

[3]
     If the mouse leaves the listbox window with button 1 down, the window
     scrolls away from the mouse, making information visible that used to
     be off-screen on the side of the mouse.  The scrolling continues
     until the mouse re-enters the window, the button is released, or the
     end of the listbox is reached.

[4]
     Mouse button 2 may be used for scanning.  If it is pressed and
     dragged over the listbox, the contents of the listbox drag at high
     speed in the direction the mouse moves.

[5]
     If the Up or Down key is pressed, the location cursor (active
     element) moves up or down one element.  If the selection mode is
     browse or *extended* then the new active element is also selected and
     all other elements are deselected.  In *extended* mode the new active
     element becomes the selection anchor.

[6]
     In *extended* mode, Shift-Up and Shift-Down move the location cursor
     (active element) up or down one element and also extend the selection
     to that element in a fashion similar to dragging with mouse button 1.

[7]
     The Left and Right keys scroll the listbox view left and right by the
     width of the character 0.  Control-Left and Control-Right scroll the
     listbox view left and right by the width of the window.
     Control-Prior and Control-Next also scroll left and right by the
     width of the window.

[8]
     The Prior and Next keys scroll the listbox view up and down by one
     page (the height of the window).

[9]
     The Home and End keys scroll the listbox horizontally to the left and
     right edges, respectively.

[10]
     Control-Home sets the location cursor to the the first element in the
     listbox, selects that element, and deselects everything else in the
     listbox.

[11]
     Control-End sets the location cursor to the the last element in the
     listbox, selects that element, and deselects everything else in the
     listbox.

[12]
     In *extended* mode, Control-Shift-Home extends the selection to the
     first element in the listbox and Control-Shift-End extends the
     selection to the last element.

[13]
     In multiple mode, Control-Shift-Home moves the location cursor to the
     first element in the listbox and Control-Shift-End moves the location
     cursor to the last element.

[14]
     The space and Select keys make a selection at the location cursor
     (active element) just as if mouse button 1 had been pressed over this
     element.

[15]
     In *extended* mode, Control-Shift-space and Shift-Select extend the
     selection to the active element just as if button 1 had been pressed
     with the Shift key down.

[16]
     In *extended* mode, the Escape key cancels the most recent selection
     and restores all the elements in the selected range to their previous
     selection state.

[17]
     Control-slash selects everything in the widget, except in single and
     browse modes, in which case it selects the active element and
     deselects everything else.

[18]
     Control-backslash deselects everything in the widget, except in
     browse mode where it has no effect.

[19]
     The F16 key (labelled Copy on many Sun workstations) or Meta-w copies
     the selection in the widget to the clipboard, if there is a selection.

     The behavior of listboxes can be changed by defining new bindings for
     individual widgets or by redefining the class bindings.

KEYWORDS
========

   listbox, widget

Create modal dialog and wait for a password response.
*****************************************************

NAME
====

   Tk::LockDisplay - Create modal dialog and wait for a password response.

SYNOPSIS
========

       $lock = *$parent*->*LockDisplay*(*-option* => value, ... );

DESCRIPTION
===========

   This widget fills the display with a screensaver-like animation, makes
a global grab and then waits for the user's authentication string, usually
their password.  Until the password is entered the display cannot be used:
window manager commands are ignored, etcetera. Note, X server requests are
not blocked.

   Password verification is perforemd via a callback passed during widget
creation.

   While waiting for the user to respond, *LockDisplay* sets a global
grab.  This prevents the user from interacting with any application in any
way except to type characters in the LockDisplay entry box.  See the
*Lock()* method.

   The following option/value pairs are supported:

*-authenticate*
     Password verification subroutine - it's passed two positional
     parameters, the username and password, and should return 1 if success,
     else 0.

*-animation*
     A string indicating what screensaver plugin to use, or 'none' to
     disable the screensaver.  Supplied plugins are 'lines' (default),
     'neko'  and 'counter', which reside in the directory
     .../Tk/LockDisplay.  You can drop a plugin of your own in that
     directory - see the section Plugin Format below for details.  You can
     also supply your own animation subroutine by passing a CODE
     reference.  The subroutine is passed a single parameter, the canvas
     widget reference, which you can draw upon as you please.

*-animationinterval*
     The number of milliseconds between calls to the screen saver
     animation code.  Default is 200 milliseconds.  Plugins can specifiy
     their own interval by returning the number of milliseconds (> 1)
     during initialization.

*-hide*
     How many seconds of display inactivity before hiding the password
     entry widget and canvas title text. Default is 10 seconds.

*-text*
     Title text centered in canvas.

*-foreground*
     Title text color.

*-background*
     Canvas color.

*-debug*
     Set to 1 allows a <Double-1> event to unlock the display.  Used while
     debugging your authentication callback or plugin.

METHODS
=======

`$lock->*Lock*;'
     This method locks the display and waits for the user's authentication
     data.

EXAMPLE
=======

   $lock = *$mw*->*LockDisplay*(-authenticate => \&check_pw);

   sub check_pw {

     # Perform AFS validation unless on Win32.

     my($user, $pw) = @_;

     if ($^O eq 'MSWin32') {
     	($pw eq $^O) ? exit(0) : return(0);
     } else {
     	system "/usr/afsws/bin/klog $user " . quotemeta($pw) . " 2> /dev/null";
     	($? == 0) ? exit(0) : return(0);
     }

   } # end check_pw

PLUGIN FORMAT
=============

   Refer to the "counter" plugin file .../Tk/LockDisplay/counter.pm for
details on the structure of a LockDisplay animation plugin.  Basically,
you create a ".pm" file that describes your plugin, "counter.pm" for
instance.  This file must contain a subroutine called Animate($canvas),
where $canvas is the canvas widget reference passed to it.

   LockDisplay first require()s your plugin file, and, if that succeeds,
calls it once to perform initialization.  Animate() should return 0 for
failure, 1 for success, and > 1 for success and to specifiy a private
-animationinterval (in milliseconds).  Subsequent calls to Animate() are
for its "main loop" processing.  As before, the return code should be 0 or
1 for failure or success, respectively.

HISTORY
=======

Version 1.0
          Beta Release.

Version 1.1
          . Implement plugins and other fixes suggested by Achim Bohnet.
            Thanks!
          . Allow plugin name 'none' to disable screensaver.  Thanks to
            Roderick Anderson!

Version 1.2
          . getlogin() fails on HPUX, so try getpwuid() as a fallback.
            Thanks to Paul Schinder for the CPAN-Testers bug report.
          . Plugins can return() their own -animationinterval value
            during preset.
          . Add 'neko' plugin.

Version 1.3
          . Fix value of pi in neko plugin!
          . Add Windows 95 support

AUTHOR
======

   Stephen.O.Lidie@Lehigh.EDU

COPYRIGHT
=========

   Copyright (C) 1998 - 1998, Stephen O. Lidie.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

KEYWORDS
========

   screeensaver, dialog, modal

Multicolumn Listbox.
********************

NAME
====

   Tk::MListbox - Multicolumn Listbox.

SYNOPSIS
========

     use Tk::MListbox;
     $ml = $parent->MListbox (<options>);

DESCRIPTION
===========

   Tk::MListbox is a multicolumn Listbox widget with builtin capabilites
for sorting, resizing and repositioning of the columns.

   Sorting is done by clicking on one of the column headings in the
widget. The first click will sort the data with the selected column as
key, a new click will reverse the sort order.

   The columns may be resized by dragging a separator line which is drawn
between each column.

   A column's position in the widget might be changed by dragging it's
heading left or right.

   Tk::MListbox is used in a way similar to the standard Listbox, but in
stead of scalar values MListbox operates on lists of data. In addition to
methods for accessing the data in the MListbox, the widget offer methods
for manipulation of the individual columns.

AUTHOR
======

   Hans Jorgen Helgesen, hans_helgesen@hotmail.com (from March 2000:
hans.helgesen@novit.no)

SEE ALSO
========

   See Tk/Listbox,

STANDARD OPTIONS
================

   *-background* *-foreground* *-relief* *-takefocus*
*-borderwidth*	*-heigh* *-selectbackground*	*-cursor*
*-highlightbackground* *-selectborderwidth* *-xscrollcommand*
*-exportselection* *-highlightcolor* *-selectforeground* *-yscrollcommand*
*-font* *-highlightthickness* *-setgrid*

   See Tk/options, for details of the standard options.

REQUIREMENTS
============

   Tk::MListbox requires Tk::Pane.  (and basic Perl/Tk of course....)

WIDGET SPECIFIC OPTIONS
=======================

-columns => list
     Defines the columns in the widget. Each element in the list describes
     a column. See the COLUMNS section below.

-configurecommand => callback
     The -configurecommand callback will be called whenever the layout of
     the widget has changed due to user interaction. That is, the user
     changes the width of a column by dragging the separator, or moves a
     column by dragging the column header.

     This option is useful if the application wants to store the widget
     layout for later retrieval. The widget layout can be obtained by the
     callback by calling the method columnPackInfo().

-moveable => boolean
     A value of 1 indicates that it is okay for the user to move the
     columns by dragging the column headers. 0 disables this function.

     Default: 1

-resizeable => boolean
     A value of 1 indicates that it is okay for the user to resize the
     columns by dragging the column separators. 0 disables this function.

     Default: 1

     Note that you can also specify -resizeable on a column by column
     basis. See the COLUMNS section below.

-selectmode => string
     Should be "single", "browse", "multiple", or "extended".

     Default is "browse". See Tk/Listbox.

-separatorcolor => string
     Specifies the color of the separator lines (the vertical lines that
     separates the columns).

     Default: *black*

     Note that you can also specify -separatorcolor on a column by column
     basis. See the COLUMNS section below.

-separatorwidth => integer
     Specifies the width in pixels of the separator lines (the vertical
     lines that separates the columns).

     Default: 1

     Note that you can also specify -separatorwidth on a column by column
     basis. See the COLUMNS section below.

-sortable => boolean
     A value of 1 indicates that it is okay for the user to sort the data
     by clicking column headings. 0 disables this function.

     Default: 1

     Note that you can also specify -sortable on a column by column basis.
     See COLUMNS below.

COLUMNS
=======

   The MListbox widget is a collection of *MLColumn* widgets.  Each
MLColumn contains a Listbox, a heading and the separator bar.  The columns
are created and maintained through the -columns option or the column
methods of the widget. The columns are indexed from 0 and up. Initially,
column 0 is the leftmost column of the widget. The column indices *are not
changed* when the columns are moved or hidden. The only ways to change the
column indices are to call columnInsert(), columnDelete() or
configure(-column).

   Each column has its own set of options which might be passed to
MListbox::configure(-columns), MListbox::insert(),
MListbox::columnConfigure() or MLColumn::configure().

   The following code snippets are all equal:

   1.  $ml=$mw->MListbox(-columns=>[[-text=>'Heading1',
              -sortable=>0],
[-text=>'Heading2']]);

   2.  $ml=$mw->MListbox;     $ml->columnInsert(0,-text=>'Heading1',
-sortable=>0);     $ml->columnInsert(0,-text=>'Heading2');

   3.  $ml=$mw->MListbox;     $c=$ml->columnInsert(0,-text=>'Heading1');
 $ml->columnInsert(0,-text=>'Heading2');     $c->configure(-sortable=>0);

   4.  $ml=$mw->MListbox;     $ml->columnInsert(0,-text=>'Heading1');
$ml->columnInsert(0,-text=>'Heading2');
$ml->columnConfigure(0,-sortable=>0);

   (See the columnConfigure() method below for details on column options).

   All column methods expects one or two column indices as arguments.  The
column indices might be an integer (between 0 and the number of columns
minus one), 'end' for the last column, or a reference to the MLColumn
widget (obtained by calling MListbox->columnGet() or by storing the return
value from MListbox->columnInsert()).

WIDGET METHODS
==============

$ml->bindColumns(sequence,callback)
     Adds the binding to all column headers in the widget. See the section
     BINDING EVENTS TO MLISTBOX below.

$ml->bindRows(sequence,callback)
     Adds the binding to all listboxes in the widget. See the section
     BINDING EVENTS TO MLISTBOX below.

$ml->bindSeparators(sequence,callback)
     Adds the binding to all separators in the widget. See the section
     BINDING EVENTS TO MLISTBOX below.

COLUMN METHODS
--------------

   (Methods for accessing and manipulating individual columns in the
MListbox widget)

$ml->columnConfigure(index,option=>value...)
     Set option values for a specific column.  Equal to
     $ml->columnGet(index)->configure(...).

     The following column options are supported:

          -comparecommand => callback

          Specifies a callback to use when sorting the MListbox with this
          column as key. The callback will be called with two scalar
          arguments, each a value from this particular column. The
          callback should return an integer less than, equal to, or
          greater than 0, depending on how the tow arguments are ordered.
          If for example the column should be sorted by numerical value:

               -comparecommand => sub { $_[0] <=> $_[1]}

          The default is to sort the columns alphabetically.

          -text => string

          Specifies the text to be used in the heading button of the
          column.

          -resizeable => boolean

          A value of 1 indicates that it is okay for the user to resize
          this column by dragging the separator. 0 disables this function.

          Default: 1

          -separatorcolor => string

          Specifies the color of the separator line, default is *black*.

          -separatorwidth => integer

          Specifies the width of the separator line in pixels. Default is
          1.

          -sortable => boolean

          A value of 1 indicates that it is okay for the user to sort the
          data by clicking this column's heading. 0 disables this function.

          Default: 1

$ml->columnDelete(first,last)
     If last is omitted, deletes column first. If last is specified,
     deletes all columns from first to last, inclusive.

     All previous column indices greater than last (or first if last is
     omitted) are decremented by the number of columns deleted.

$ml->columnGet(first,last)
     If last is not specified, returns the MLColumn widget specified by
     first.  If both first and last are specified, returns an array
     containing all columns from first to last.

$ml->columnHide(first,last)
     If last is omitted, hides column first. If last is specified, hides
     all columns from first to last, inclusive.

     Hiding a column is equal to calling $ml->columnGet(index)->packForget.
     The column is not deleted, all data are still available, and the
     column indices remain the same.

     See also the columnShow() method below.

$ml->columnIndex(index)
     Returns an integer index for the column specifed by index.

$ml->columnInsert(index,option=>value...)
     Creates a new column in the MListbox widget. The column will get the
     index specified by index. If index is 'end', the new column's index
     will be one more than the previous highest column index.

     If column index exists, the new column will be placed to the left of
     this column. All previous column indices equal to or greater than
     index will be incremented by one.

     Returns the newly created MLColumn widget.

     (See the columnConfigure() method above for details on column
     options).

$ml->columnPack(array)
     Repacks all columns in the MListbox widget according to the
     specification in array. Each element in array is a string on the
     format *index:width*. index is a column index, width defines the
     columns width in pixels (may be omitted). The columns are packed left
     to right in the order specified by by array.  Columns not specified
     in array will be hidden.

     This method is most useful if used together with the columnPackInfo()
     method.

$ml->columnPackInfo
     Returns an array describing the current layout of the MListbox
     widget. Each element of the array is a string on the format
     *index:width* (see columnPack() above). Only indices of columns that
     are currently shown (not hidden) will be returned. The first element
     in the returned array represents the leftmost column.

     This method may be used in conjunction with columnPack() to save and
     restore the column configuration.

$ml->columnShow(index,option=>value)
     Shows a hidden column (see the columnHide() method above).  The
     column to show is specified by index.

     By default, the column is pack'ed at the rigthmost end of the
     MListbox widget. This might be overridden by specifying one of the
     following options:

          -after => index

          Place the column after (to the right of) the column specified by
          index.

          -before => index

          Place the column before (to the left of) the column specified by
          index.

ROW METHODS
-----------

   (Methods for accessing and manipulating rows of data)

   Many of the methods for MListbox take one or more indices as arguments.
See Tk/Listbox, for a description of row indices.

$ml->delete(first,last)
     Deletes one or more row elements of the MListbox. First and last are
     indices specifying the first and last elements in the range to
     delete. If last isn't specified it defaults to first, i.e. a single
     element is deleted.

$ml->get(first,last)
     If last is omitted, returns the content of the MListbox row indicated
     by first. If last is specified, the command returns a list whose
     elements are all of the listbox rows between first and last.

     The returned elements are all array references. The referenced arrays
     contains one element for each column of the MListbox.

$ml->getRow(index)
     In scalar context, returns the value of column 0 in the MListbox row
     specified by index. In list context, returns the content of all
     columns in the row as an array.

     This method is provided for convenience, since retrieving a single
     row with the get() method might produce some ugly code.

     The following two code snippets are equal:

          1. @row=$ml->getRow(0);

          2. @row=@{($ml->get(0))[0]};

$ml->sort(*descending*, *columnindex*...)
     Sorts the content of the MListbox. If *descending* is a *true* value,
     the sort order will be descending. The default is ascending sort.

     If *columnindex* is specified, the sort will be done with the
     specified column as key. You can specify as many *columnindex*
     arguments as you wish. Sorting is done on the first column, then on
     the second, etc...

     The default is to sort the data on all columns of the listbox, with
     column 0 as the first sort key, column 1 as the second, etc.

OTHER LISTBOX METHODS
=====================

   Most other Tk::Listbox methods works for the MListbox widget.  This
includes the methods activate, cget, curselection, index, nearest, see,
selectionXXX, size, xview, yview.

   See Tk/Listbox.

ADVERTISED SUBWIDGETS
=====================

pane
     All MListbox columns are packed inside a Tk::Pane (this is done to
     enable horizontal scrolling).

   Apart from "pane", the MListbox widget has no subwidgets, except for
the variable number of MLColumns, which obviously cannot be advertised.
The MLColumn widgets might be obtained by calling the columnGet() or
columnInsert() methods.

   The MLColumn widget (which represents a single column in the MListbox)
advertises the following subwidgets:

listbox
     The individual Listbox. Note that this is not the standard
     Tk::Listbox, but a derived version (CListbox). Several of the
     widget's methods will not work as expected.

separator
     The column separator line. This is a Canvas.

heading
     The column heading. This is a "HButton" (a Button with an additional
     -pixelwidth option).

frame
     A Frame which contains the "listbox" and the "heading" subwidgets
     (but not the "separator").

   Example: If you want to change the background color of the heading of
column 4:

     $ml->columnGet(4)->Subwidget("heading")
         ->configure(-background=>'blue');

BINDING EVENTS TO MLISTBOX
==========================

   Calling $ml->bind(...) probably makes little sense, since the call does
not specify whether the binding should apply to the listbox, the header
button or the separator line between each column.

   In stead of the ordinary bind, the following methods should be used:

$ml->bind(sequence,callback)
     Synonym for $ml->bindRows(sequence,callback).

$ml->bindRows(sequence,callback)
     Synonym for $ml->bindSubwidgets('listbox',sequence,callback)

$ml->bindColumns(sequence,callback)
     Synonym for $ml->bindSubwidgets('heading',sequence,callback)

$ml->bindSeparators(sequence,callback)
     Synonym for $ml->bindSubwidgets('separator',sequence,callback)

$ml->bindSubwidgets(*subwidget*,sequence,callback)
     Adds the binding specified by sequence and callback to all subwidgets
     of the given type (should be 'listbox', 'heading' or 'separator').

     The binding is stored in the widget, and if you create a new column
     by calling $ml->columnInsert(), all bindings created by
     $ml->bindSubwidgets() are automatically copied to the new column.

     The callback is called with the MListbox widget as first argument, and
     the index of the column where the event occured as the second
     argument.

     NOTE that $ml->bindSubwidgets() does not support all of Tk's callback
     formats.  The following are supported:

          \&subname
          sub { code }
          [ \&subname, arguments...]
          [ sub { code }, arguments...]

     If sequence is undefined, then the return value is a list whose
     elements are all the sequences for which there exist bindings for
     *subwidget*.

     If sequence is specified without callback, then the callback currently
     bound to sequence is returned, or an empty string is returned if
     there is no binding for sequence.

     If sequence is specified, and callback is an empty string, then the
     current binding for sequence is destroyed, leaving sequence unbound.
     An empty string is returned.

     An empty string is returned in all other cases.

Root widget of a widget tree
****************************

NAME
====

   Tk::MainWindow - Root widget of a widget tree

SYNOPSIS
========

     use Tk;

     my $mw = MainWindow->new( ... options ... );

     my $this = $mw->ThisWidget -> pack ;
     my $that = $mw->ThatWidget;
     ...

     MainLoop;

DESCRIPTION
===========

   Perl/Tk applications (which have windows associated with them) create
one or more *MainWindow*s which act as the containers and parents of the
other widgets.

   *Tk::MainWindow* is a special kind of `Toplevel|Tk::Toplevel' in this
node widget. It is the root of a widget tree. Therefore `$mw->Parent'
returns undef.

   The default title of a MainWindow is the basename of the script
(actually the Class name used for options lookup, i.e. with basename with
inital caps) or 'Ptk' as the fallback value.  If more than one MainWindow
is created or several instances of the script are running at the same time
the string `" #n"' is appended where the number n is set to get a unique
value.

   Unlike the standard Tcl/Tk's wish, perl/Tk allows you to create several
MainWindows.  When the last *MainWindow* is destroyed the Tk eventloop
exits (the eventloop is entered with the call of MainLoop). Various
resources (bindings, fonts, images, colors) are maintained or cached for
each MainWindow, so each MainWindow consumes more resources than a
Toplevel. However multiple MainWindows can make sense when the user can
destroy them independently.

METHODS
=======

   You can apply all methods that a `Toplevel|Tk::Toplevel' in this node
widget accepts.

   The method *$w*->*MainWindow* applied to any widget will return the
*MainWindow* to which the widget belongs (the  MainWindow belongs to
itself).

MISSING
=======

   Documentation is incomplete.  Here are some missing items that should
be explained in more detail:

   * The new mechanism for MainWindows is slightly different to other
     widgets.

   * There no explanation about what resources are bound to a MainWindow
     (e.g., ClassInit done per MainWindow)

   * Passing of command line options to override or augment arguments of
     the new method (see Tk/CmdLine).

SEE ALSO
========

   `Tk::Toplevel|Tk::Toplevel' in this node `Tk::CmdLine|Tk::CmdLine' in
this node

Create and manipulate Menu widgets
**********************************

NAME
====

   Tk::Menu - Create and manipulate Menu widgets

       *$menu* = *$parent*->Menu(?options?);

STANDARD OPTIONS
================

   *-activebackground*	*-background*	*-disabledforeground*	*-relief*
*-activeborderwidth*	*-borderwidth*	*-font*	*-takefocus*
*-activeforeground*	*-cursor*	*-foreground*

   See Tk/options, for details of the standard options.

WIDGET-SPECIFIC OPTIONS
=======================

Name:	*postCommand*
Class:	Command
Switch:	*-postcommand*
     If this option is specified then it provides a
     `callback|Tk::callbacks' in this node to execute each time the menu
     is posted.  The callback is invoked by the post method before posting
     the menu. Note that in 8.0 on Macintosh and Windows, all commands in
     a menu systems are executed before any are posted. This is due to the
     limitations in the individual platforms' menu managers.

Name:	*selectColor*
Class:	Background
Switch:	*-selectcolor*
     For menu entries that are check buttons or radio buttons, this option
     specifies the color to display in the indicator when the check button
     or radio button is selected.

Name:	*tearOff*
Class:	*TearOff*
Switch:	*-tearoff*
     This option must have a proper boolean value, which specifies whether
     or not the menu should include a tear-off entry at the top.  If so,
     it will exist as entry 0 of the menu and the other entries will
     number starting at 1.  The default menu bindings arrange for the menu
     to be torn off when the tear-off entry is invoked.

Name:	*tearOffCommand*
Class:	*TearOffCommand*
Switch:	*-tearoffcommand*
     If this option has a non-empty value, then it specifies a `Tk
     callback|Tk::callbacks', see Perl (perl.info), to invoke
     whenever the menu is torn off.  The actual command will consist of
     the value of this option, followed by a space, followed by the name
     of the menu window, followed by a space, followed by the name of the
     name of the torn off menu window.  For example, if the option's is
     "*a b*" and menu *.x.y* is torn off to create a new menu
     *.x.tearoff1*, then the command "*a b .x.y .x.tearoff1*" will be
     invoked.

Name:	title
Class:	Title
Switch:	*-title*
     The string will be used to title the window created when this menu is
     torn off. If the title is NULL, then the window will have the title
     of the menubutton or the text of the cascade item from which this menu
     was invoked.

Name:	type
Class:	Type
Switch:	*-type*
     This option can be one of *menubar*, *tearoff*, or normal, and is set
     when the menu is created. While the string returned by the
     configuration database will change if this option is changed, this
     does not affect the menu widget's behavior. This is used by the
     cloning mechanism and is not normally set outside of the Tk library.

DESCRIPTION
===========

   The Menu method creates a new top-level window (given by the $widget
argument) and makes it into a menu widget.  Additional options, described
above, may be specified on the command line or in the option database to
configure aspects of the menu such as its colors and font.  The menu
command returns its $widget argument.  At the time this command is invoked,
there must not exist a window named $widget, but $widget's parent must
exist.

   A menu is a widget that displays a collection of one-line entries
arranged in one or more columns.  There exist several different types of
entries, each with different properties.  Entries of different types may be
combined in a single menu.  Menu entries are not the same as entry
widgets.  In fact, menu entries are not even distinct widgets; the entire
menu is one widget.

   Menu entries are displayed with up to three separate fields.  The main
field is a label in the form of a text string, a bitmap, or an image,
controlled by the *-label*, *-bitmap*, and *-image* options for the entry.
If the  *-accelerator* option is specified for an entry then a second
textual field is displayed to the right of the label.  The accelerator
typically describes a keystroke sequence that may be typed in the
application to cause the same result as invoking the menu entry.  The
third field is an *indicator*.  The indicator is present only for
checkbutton or radiobutton entries.  It indicates whether the entry is
selected or not, and is displayed to the left of the entry's string.

   In normal use, an entry becomes active (displays itself differently)
whenever the mouse pointer is over the entry.  If a mouse button is
released over the entry then the entry is invoked.  The effect of
invocation is different for each type of entry; these effects are
described below in the sections on individual entries.

   Entries may be disabled, which causes their labels and accelerators to
be displayed with dimmer colors.  The default menu bindings will not allow
a disabled entry to be activated or invoked.  Disabled entries may be
re-enabled, at which point it becomes possible to activate and invoke them
again.

   Whenever a menu's active entry is changed, a <<MenuSelect>> virtual
event is sent to the menu. The active item can then be queried from the
menu, and an action can be taken, such as setting context-sensitive help
text for the entry.

COMMAND ENTRIES
---------------

   The most common kind of menu entry is a command entry, which behaves
much like a button widget.  When a command entry is invoked, a callback is
executed.  The callback is specified with the *-command* option.

SEPARATOR ENTRIES
-----------------

   A separator is an entry that is displayed as a horizontal dividing
line.  A separator may not be activated or invoked, and it has no behavior
other than its display appearance.

CHECKBUTTON ENTRIES
-------------------

   A checkbutton menu entry behaves much like a checkbutton widget.  When
it is invoked it toggles back and forth between the selected and
deselected states.  When the entry is selected, a particular value is
stored in a particular global variable (as determined by the *-onvalue*
and *-variable* options for the entry);  when the entry is deselected
another value (determined by the *-offvalue* option) is stored in the
global variable.  An indicator box is displayed to the left of the label
in a checkbutton entry.  If the entry is selected then the indicator's
center is displayed in the color given by the *-selectcolor* option for
the entry; otherwise the indicator's center is displayed in the background
color for the menu.  If a *-command* option is specified for a checkbutton
entry, then its value is evaluated each time the entry is invoked;  this
happens after toggling the entry's selected state.

RADIOBUTTON ENTRIES
-------------------

   A radiobutton menu entry behaves much like a radiobutton widget.
Radiobutton entries are organized in groups of which only one entry may be
selected at a time.  Whenever a particular entry becomes selected it
stores a particular value into a particular global variable (as determined
by the *-value* and *-variable* options for the entry).  This action
causes any previously-selected entry in the same group to deselect itself.
Once an entry has become selected, any change to the entry's associated
variable will cause the entry to deselect itself.  Grouping of radiobutton
entries is determined by their associated variables:  if two entries have
the same associated variable then they are in the same group.  An
indicator diamond is displayed to the left of the label in each
radiobutton entry.  If the entry is selected then the indicator's center
is displayed in the color given by the *-selectcolor* option for the entry;
otherwise the indicator's center is displayed in the background color for
the menu.  If a *-command* option is specified for a radiobutton entry,
then its value is evaluated each time the entry is invoked;  this happens
after selecting the entry.

CASCADE ENTRIES
---------------

   A cascade entry is one with an associated menu (determined by the
*-menu* option).  Cascade entries allow the construction of cascading
menus.  The *postcascade* method can be used to post and unpost the
associated menu just next to of the cascade entry.  The associated menu
must be a child of the menu containing the cascade entry (this is needed
in order for menu traversal to work correctly).

   A cascade entry posts its associated menu by invoking

   *$menu*->post(*x,y*)

   where menu is the path name of the associated menu, and x and y are the
root-window coordinates of the upper-right corner of the cascade entry.
On Unix, the lower-level menu is unposted by executing

   *$menu*->*unpost*

   where menu is the name of the associated menu.  On other platforms, the
platform's native code takes care of unposting the menu.

   If a *-command* option is specified for a cascade entry then it is
evaluated whenever the entry is invoked. This is not supported on Windows.

TEAR-OFF ENTRIES
----------------

   A tear-off entry appears at the top of the menu if enabled with the
*tearOff* option.  It is not like other menu entries in that it cannot be
created with the add method and cannot be deleted with the delete method.
When a tear-off entry is created it appears as a dashed line at the top of
the menu.  Under the default bindings, invoking the tear-off entry causes
a torn-off copy to be made of the menu and all of its submenus.

MENUBARS
--------

   Any menu can be set as a menubar for a toplevel window (see the
`Toplevel|Tk::Toplevel' in this node constructor for syntax). On the
Macintosh, whenever the toplevel is in front, this menu's cascade items
will appear in the menubar across the top of the main monitor. On Windows
and Unix, this menu's items will be displayed in a menubar accross the top
of the window. These menus will behave according to the interface
guidelines of their platforms. For every menu set as a menubar, a clone
menu is made. See `"CLONES"' in this node for more information.

SPECIAL MENUS IN MENUBARS
-------------------------

   Certain menus in a menubar will be treated specially.  On the Macintosh,
access to the special Apple and Help menus is provided. On Windows, access
to the Windows System menu in each window is provided. On X Windows, a
special right-justified help menu is provided. In all cases, these menus
must be created with the command name of the menubar menu concatenated
with the special name. So for a menubar named .menubar, on the Macintosh,
the special menus would be .menubar.apple and .menubar.help; on Windows,
the special menu would be .menubar.system; on X Windows, the help menu
would be .menubar.help.

   When Tk sees an Apple menu on the Macintosh, that menu's contents make
up the first items of the Apple menu on the screen whenever the window
containing the menubar is in front. The menu is the first one that the
user sees and has a title which is an Apple logo.  After all of the
Tk-defined items, the menu will have a separator, followed by all of the
items in the user's Apple Menu Items folder.  Since the System uses a
different menu definition procedure for the Apple menu than Tk uses for
its menus, and the system APIs do not fully support everything Tk tries to
do, the menu item will only have its text displayed. No font attributes,
images, bitmaps, or colors will be displayed. In addition, a menu with a
tearoff item will have the tearoff item displayed as "(TearOff)".

   When Tk see a Help menu on the Macintosh, the menu's contents are
appended to the standard help menu on the right of the user's menubar
whenever the user's menubar is in front. The first items in the menu are
provided by Apple. Similar to the Apple Menu, cusomization in this menu is
limited to what the system provides.

   When Tk sees a System menu on Windows, its items are appended to the
system menu that the menubar is attached to. This menu has an icon
representing a spacebar, and can be invoked with the mouse or by typing
Alt+Spacebar.  Due to limitations in the Windows API, any font changes,
colors, images, bitmaps, or tearoff images will not appear in the system
menu.

   When Tk see a Help menu on X Windows, the menu is moved to be last in
the menubar and is right justified.

SEPARATORS IN MENUBARS
----------------------

   Separator entries are not displayed in menubars.  The last separator
entry causes remaining entries to be right justified.

CLONES
------

   When a menu is set as a menubar for a toplevel window, or when a menu
is torn off, a clone of the menu is made. This clone is a menu widget in
its own right, but it is a child of the original. Changes in the
configuration of the original are reflected in the clone. Additionally,
any cascades that are pointed to are also cloned so that menu traversal
will work right. Clones are destroyed when either the tearoff or menubar
goes away, or when the original menu is destroyed.

WIDGET METHODS
--------------

   The Menu method creates a widget object.  This object supports the
configure and cget methods described in Tk/options,
which can be used to enquire and modify the options described above.  The
widget also inherits all the methods provided by the generic
`Tk::Widget|Tk::Widget' in this node class, and the `Tk::Wm|Tk::Wm' in
this node class.

   Many of the methods for a menu take as one argument an indicator of
which entry of the menu to operate on.  These indicators are called
indexes and may be specified in any of the following forms:

number
     Specifies the entry numerically, where 0 corresponds to the top-most
     entry of the menu, 1 to the entry below it, and so on.

active
     Indicates the entry that is currently active.  If no entry is active
     then this form is equivalent to none.  This form may not be
     abbreviated.

end
     Indicates the bottommost entry in the menu.  If there are no entries
     in the menu then this form is equivalent to none.  This form may not
     be abbreviated.

last
     Same as end.

none
     Indicates "no entry at all";  this is used most commonly with the
     activate option to deactivate all the entries in the menu.  In most
     cases the specification of none causes nothing to happen in the
     method.  This form may not be abbreviated.

*@*number
     In this form, number is treated as a y-coordinate in the menu's
     window;  the entry closest to that y-coordinate is used.  For
     example, "*@0*" indicates the top-most entry in the window.

pattern
     If the index doesn't satisfy one of the above forms then this form is
     used.  Pattern is pattern-matched against the label of each entry in
     the menu, in order from the top down, until a matching entry is found.
     (In perl/Tk the matching is under review, but exact match should
     work.)

   The following methods are possible for menu widgets:

*$menu*->activate(index)
     Change the state of the entry indicated by index to active and
     redisplay it using its active colors.  Any previously-active entry is
     deactivated.  If index is specified as none, or if the specified
     entry is disabled, then the menu ends up with no active entry.
     Returns an empty string.

*$menu*->add(*type, *?*option, value, option, value, ...*?)
     Add a new entry to the bottom of the menu.  The new entry's type is
     given by type and must be one of *cascade*, *checkbutton*, command,
     *radiobutton*, or separator, or a unique abbreviation of one of the
     above.  If additional arguments are present, they specify any of the
     following options:

    *-activebackground* => value
          Specifies a background color to use for displaying this entry
          when it is active.  If this option is specified as an empty
          string (the default), then the *activeBackground* option for the
          overall menu is used.  If the $Tk::strictMotif variable has been
          set to request strict Motif compliance, then this option is
          ignored and the *-background* option is used in its place.  This
          option is not available for separator or tear-off entries.

    *-activeforeground* => value
          Specifies a foreground color to use for displaying this entry
          when it is active.  If this option is specified as an empty
          string (the default), then the *activeForeground* option for the
          overall menu is used.  This option is not available for
          separator or tear-off entries.

    *-accelerator* => value
          Specifies a string to display at the right side of the menu
          entry.  Normally describes an accelerator keystroke sequence
          that may be typed to invoke the same function as the menu entry.
          This option is not available for separator or tear-off entries.

    *-background* => value
          Specifies a background color to use for displaying this entry
          when it is in the normal state (neither active nor disabled).
          If this option is specified as an empty string (the default),
          then the background option for the overall menu is used.  This
          option is not available for separator or tear-off entries.

    *-bitmap* => value
          Specifies a bitmap to display in the menu instead of a textual
          label, in any of the forms accepted by *Tk_GetBitmap*.  This
          option overrides the *-label* option but may be reset to an
          empty string to enable a textual label to be displayed.  If a
          *-image* option has been specified, it overrides *-bitmap*.
          This option is not available for separator or tear-off entries.

    *-columnbreak* => value
          When this option is zero, the appears below the previous entry.
          When this option is one, the menu appears at the top of a new
          column in the menu.

    *-command* => value
          For command, checkbutton, and radiobutton entries, specifies a
          callback to execute when the menu entry is invoked.  For cascade
          entries, specifies a callback to execute when the entry is
          activated (i.e. just before its submenu is posted).  Not
          available for separator or tear-off entries.

    *-font* => value
          Specifies the font to use when drawing the label or accelerator
          string in this entry.  If this option is specified as an empty
          string (the default) then the font option for the overall menu
          is used.  This option is not available for separator or tear-off
          entries.

    *-foreground* => value
          Specifies a foreground color to use for displaying this entry
          when it is in the normal state (neither active nor disabled).
          If this option is specified as an empty string (the default),
          then the *foreground* option for the overall menu is used.  This
          option is not available for separator or tear-off entries.

    *-hidemargin* => value
          Specifies whether the standard margins should be drawn for this
          menu entry. This is useful when creating palette with images in
          them, i.e., color palettes, pattern palettes, etc. 1 indicates
          that the margin for the entry is hidden; 0 means that the margin
          is used.

    *-image* => value
          Specifies an image to display in the menu instead of a text
          string or bitmap The image must have been created by some
          previous invocation of *image create*.  This option overrides
          the *-label* and *-bitmap* options but may be reset to an empty
          string to enable a textual or bitmap label to be displayed.
          This option is not available for separator or tear-off entries.

    *-indicatoron* => value
          Available only for checkbutton and radiobutton entries.  Value
          is a boolean that determines whether or not the indicator should
          be displayed.

    *-label* => value
          Specifies a string to display as an identifying label in the menu
          entry.  Not available for separator or tear-off entries.

    *-menu* => value
          Available only for cascade entries.  Specifies the path name of
          the submenu associated with this entry.  The submenu must be a
          child of the menu.

    *-offvalue* => value
          Available only for checkbutton entries.  Specifies the value to
          store in the entry's associated variable when the entry is
          deselected.

    *-onvalue* => value
          Available only for checkbutton entries.  Specifies the value to
          store in the entry's associated variable when the entry is
          selected.

    *-selectcolor* => value
          Available only for checkbutton and radiobutton entries.
          Specifies the color to display in the indicator when the entry is
          selected.  If the value is an empty string (the default) then
          the *selectColor* option for the menu determines the indicator
          color.

    *-selectimage* => value
          Available only for checkbutton and radiobutton entries.
          Specifies an image to display in the entry (in place of the
          *-image* option) when it is selected.  Value is the name of an
          image, which must have been created by some previous invocation
          of *image create*.  This option is ignored unless the *-image*
          option has been specified.

    *-state* => value
          Specifies one of three states for the entry:  normal, active, or
          disabled.  In normal state the entry is displayed using the
          *foreground* option for the menu and the background option from
          the entry or the menu.  The active state is typically used when
          the pointer is over the entry.  In active state the entry is
          displayed using the *activeForeground* option for the menu along
          with the *activebackground* option from the entry.  Disabled
          state means that the entry should be insensitive:  the default
          bindings will refuse to activate or invoke the entry.  In this
          state the entry is displayed according to the
          *disabledForeground* option for the menu and the background
          option from the entry.  This option is not available for
          separator entries.

    *-underline* => value
          Specifies the integer index of a character to underline in the
          entry.  This option is also queried by the default bindings and
          used to implement keyboard traversal.  0 corresponds to the
          first character of the text displayed in the entry, 1 to the
          next character, and so on.  If a bitmap or image is displayed in
          the entry then this option is ignored.  This option is not
          available for separator or tear-off entries.

    *-value* => value
          Available only for radiobutton entries.  Specifies the value to
          store in the entry's associated variable when the entry is
          selected.  If an empty string is specified, then the *-label*
          option for the entry as the value to store in the variable.

    *-variable* => value
          Available only for checkbutton and radiobutton entries.
          Specifies the name of a global value to set when the entry is
          selected.  For checkbutton entries the variable is also set when
          the entry is deselected.  For radiobutton entries, changing the
          variable causes the currently-selected entry to deselect itself.

     The add method returns an empty string.

*$menu*->clone(*$parent* ?, *cloneType?*)
     Makes a clone of the current menu as a child of *$parent*. This clone
     is a menu in its own right, but any changes to the clone are
     propogated to the original menu and vice versa. *cloneType* can be
     normal, *menubar*, or *tearoff*. Should not normally be called
     outside of the Tk library. See `"CLONES"' in this node for more
     information.

*$menu*->delete(*index1*?, *index2*?)
     Delete all of the menu entries between *index1* and *index2*
     inclusive.  If *index2* is omitted then it defaults to *index1*.
     Attempts to delete a tear-off menu entry are ignored (instead, you
     should change the *tearOff* option to remove the tear-off entry).

*$menu*->*entrycget*(*index, option*)
     Returns the current value of a configuration option for the entry
     given by index.  Option may have any of the values accepted by the add
     method.

*$menu*->*entryconfigure*(index ?,options?)
     This method is similar to the configure method, except that it
     applies to the options for an individual entry, whereas configure
     applies to the options for the menu as a whole.  Options may have any
     of the values accepted by the add method.  If options are specified,
     options are modified as indicated in the method call and the method
     returns an empty string.  If no options are specified, returns a list
     describing the current options for entry index (see Tk/options,
     for information on the format of this list).

*$menu*->index(index)
     Returns the numerical index corresponding to index, or none if index
     was specified as none.

*$menu*->insert(*index, type*?, *-option*=>value, ...?)
     Same as the add method except that it inserts the new entry just
     before the entry given by index, instead of appending to the end of
     the menu.  The type, *-option*, and value arguments have the same
     interpretation as for the add widget method.  It is not possible to
     insert new menu entries before the tear-off entry, if the menu has
     one.

*$menu*->*invoke*(index)
     Invoke the action of the menu entry.  See the sections on the
     individual entries above for details on what happens.  If the menu
     entry is disabled then nothing happens.  If the entry has a callback
     associated with it then the result of that callback is returned as
     the result of the *invoke* widget method.  Otherwise the result is an
     empty string.  Note:  invoking a menu entry does not automatically
     unpost the menu;  the default bindings normally take care of this
     before invoking the *invoke* method.

*$menu*->post(*x, y*)
     Arrange for the menu to be displayed on the screen at the root-window
     coordinates given by x and y.  These coordinates are adjusted if
     necessary to guarantee that the entire menu is visible on the screen.
     This method normally returns an empty string.  If the *postCommand*
     option has been specified, then its value is executed before posting
     the menu and the result of that callback is returned as the result of
     the post widget method.  If an error returns while executing the
     method, then the error is returned without posting the menu.

*$menu*->*postcascade*(index)
     Posts the submenu associated with the cascade entry given by index,
     and unposts any previously posted submenu.  If index doesn't
     correspond to a cascade entry, or if *$menu* isn't posted, the method
     has no effect except to unpost any currently posted submenu.

*$menu*->type(index)
     Returns the type of the menu entry given by index.  This is the type
     argument passed to the add widget method when the entry was created,
     such as command or separator, or *tearoff* for a tear-off entry.

*$menu*->*unpost*
     Unmap the window so that it is no longer displayed.  If a lower-level
     cascaded menu is posted, unpost that menu.  Returns an empty string.
     This method does not work on Windows and the Macintosh, as those
     platforms have their own way of unposting menus.

*$menu*->*yposition*(index)
     Returns a decimal string giving the y-coordinate within the menu
     window of the topmost pixel in the entry specified by index.

MENU CONFIGURATIONS
===================

   The default bindings support four different ways of using menus:

*Pulldown Menus in Menubar*
     This is the most command case. You create a menu widget that will
     become the menu bar. You then add cascade entries to this menu,
     specifying the pull down menus you wish to use in your menu bar. You
     then create all of the pulldowns. Once you have done this, specify
     the menu using the *-menu* option of the toplevel's method. See the
     toplevel manual entry for details.

*Pulldown Menus in Menu Buttons*
     This is the compatable way to do menu bars.  You create one menubutton
     widget for each top-level menu, and typically you arrange a series of
     menubuttons in a row in a menubar window.  You also create the
     top-level menus and any cascaded submenus, and tie them together with
     *-menu* options in menubuttons and cascade menu entries.  The
     top-level menu must be a child of the menubutton, and each submenu
     must be a child of the menu that refers to it.  Once you have done
     this, the default bindings will allow users to traverse and invoke
     the tree of menus via its menubutton;  see the *menubutton*
     documentation for details.

Popup Menus
     Popup menus typically post in response to a mouse button press or
     keystroke.  You create the popup menus and any cascaded submenus,
     then you call the *Post* method at the appropriate time to post the
     top-level menu.

     *$menu*->*Post*($x,*$y*?,$entry?)

     $x and *$y* are the root window coordinates at which the *$menu* will
     be displayed. If $entry is specified then that entry is centred on
     that point, otherwise the top-left corner of the *$menu* is placed at
     that point.

     Menu also inherits methods from Tk/Wm, and so the method
     Popup can be used to position menu relative to other windows, the
     mouse cursor or the screen.

*Option Menus*
     An option menu consists of a menubutton with an associated menu that
     allows you to select one of several values.  The current value is
     displayed in the menubutton and is also stored in a global variable.
     Use the Tk/Optionmenu, class to create option
     menubuttons and their menus.

*Torn-off Menus*
     You create a torn-off menu by invoking the tear-off entry at the top
     of an existing menu.  The default bindings will create a new menu
     that is a copy of the original menu and leave it permanently posted
     as a top-level window.  The torn-off menu behaves just the same as
     the original menu.

DEFAULT BINDINGS
================

   Tk automatically creates class bindings for menus that give them the
following default behavior:

[1]
     When the mouse enters a menu, the entry underneath the mouse cursor
     activates;  as the mouse moves around the menu, the active entry
     changes to track the mouse.

[2]
     When the mouse leaves a menu all of the entries in the menu
     deactivate, except in the special case where the mouse moves from a
     menu to a cascaded submenu.

[3]
     When a button is released over a menu, the active entry (if any) is
     invoked.  The menu also unposts unless it is a torn-off menu.

[4]
     The Space and Return keys invoke the active entry and unpost the menu.

[5]
     If any of the entries in a menu have letters underlined with with
     *-underline* option, then pressing one of the underlined letters (or
     its upper-case or lower-case equivalent) invokes that entry and
     unposts the menu.

[6]
     The Escape key aborts a menu selection in progress without invoking
     any entry.  It also unposts the menu unless it is a torn-off menu.

[7]
     The Up and Down keys activate the next higher or lower entry in the
     menu.  When one end of the menu is reached, the active entry wraps
     around to the other end.

[8]
     The Left key moves to the next menu to the left.  If the current menu
     is a cascaded submenu, then the submenu is unposted and the current
     menu entry becomes the cascade entry in the parent.  If the current
     menu is a top-level menu posted from a menubutton, then the current
     menubutton is unposted and the next menubutton to the left is posted.
     Otherwise the key has no effect.  The left-right order of menubuttons
     is determined by their stacking order:  Tk assumes that the lowest
     menubutton (which by default is the first one created) is on the left.

[9]
     The Right key moves to the next menu to the right.  If the current
     entry is a cascade entry, then the submenu is posted and the  current
     menu entry becomes the first entry in the submenu.  Otherwise, if the
     current menu was posted from a menubutton, then the current
     menubutton is unposted and the next menubutton to the right is posted.

     Disabled menu entries are non-responsive:  they don't activate and
     they ignore mouse button presses and releases.

     The behavior of menus can be changed by defining new bindings for
     individual widgets or by redefining the class bindings.

BUGS
====

   At present it isn't possible to use the option database to specify
values for the options to individual entries.

SEE ALSO
========

   `Tk::callbacks|Tk::callbacks' in this node

KEYWORDS
========

   menu, widget

Ties a Tk::Menubutton widget to a hash object thingy
****************************************************

NAME
====

   Tk::MenuHash - Ties a Tk::Menubutton widget to a hash object thingy

SYNOPSIS
========

     use Tk::MenuHash;

     my $MB = new Tk::MenuHash ($Menubutton);
     my $MB = new Tk::MenuHash (
         $MW->Menubutton (
             -relief       => 'raised',
             -text         => 'Pick something',
             -underline    => 0,
         )->pack (
             -side         => 'left',
         )
     );

     $MB->{'Some list item label'}   = [ \&CommandFunction, 'args' ];
     $MB->{'Some other label'}       = \&CommandFunction;
     $MB->{'Some lable name'}        = 'default';

     delete $MB->{'Some other label'};

     $MB->configure ( -text => 'Pick something else' );

     my $menuText = $MB->{"Anything, it doesn't matter"};

     ##############################################################
     ## Or you can do it this way, but it needs two vars so I don't
     ## recommend it...

     tie my %MB, 'Tk::MenuHash', $Menubutton;
     ## Or...
     tie my %MB, 'Tk::MenuHash', $MW->Menubutton (
         -relief       => 'raised',
         -text         => 'Pick something',
         -underline    => 0,
     )->pack (
         -side         => 'left',
     );

     $MB{'Some list item label'}   = [ \&CommandFunction, 'args' ];
     $MB{'Some other label'}       = \&CommandFunction;
     $MB{'Some lable name'}        = 'default';

     delete $MB{'Some other label'};

     $Menubutton->configure ( -text => 'Pick something else' );

     my $menuText = $MB{"Anything, it doesn't matter"};

DESCRIPTION
===========

   Creates a tied *Tk::Menubutton* widget hash reference object kinda
thingy....

   It's actually much simplier then it sounds, at least to use.  It walks
and talks half like an object, and half like a (tied) hash reference.  This
is because it's both in one (it's a blessed reference to a tied hash of the
same class).

WARNING:
     This is *not* a valid Tk widget as you would normally think of it.
     You can not (currently) call it as

          my $menuHash = $MW->MenuHash(); ## Don't try this (yet)!

     The *2.x* release will be a true widget and thus walk and talk
     currently as such.  As much as I will try and maintain this current
     API for future compatibility, this may not be entire possible.  The
     *2.x* release will solidify this widget's API, but until then
     consider this API in a state of flux.  Thanks

   When you add a key (label) to the hash it added it to the menubutton.
The value assigned must be either a valid *Tk::Menubutton* *-command*
option, or the string 'default' (case is not important).  The default is
simply a function that configure()s the Menubuttons *-text* to that of the
selected label.  You can then retrieve the text by just reading a key (any
key, even if it doesn't exist, it doesn't matter) from the hash.

   The new() method passes back a reference to a tie()d MenuHash, but with
all the properties (and methods) of the Menubutton you passed it.  With
this type you can set and delete fields as hash keys references:

     $MenuHash->{'Some label'} = 'default';

   But also call Tk::Menubutton (or sub-classes of it, if that's what you
passed the constructor) methods:

     $MenuHash->configure ( -text => 'Pick something' );

   This involves *black magic* to do, but it works.  See the AUTOLOAD
method code if you have a morbid interest in this, however it's more that
we are dealing with 3 objects in 2 classes.

   I prefer this useage myself as it meens I only need to carry around one
var that walks and talks almost exactly like a "real" *Tk::Menubutton*
(that is, you can call any valid Tk::Menubutton method off it directly),
but with the added (and *much* needed IMHO) feature of being able to easily
add, delete, select, and read menu options as simple hash ref keys.

EXAMPLE
=======

     use Tk;
     use Tk::MenuHash;

     my $MW = new MainWindow;

     my $menu = new Tk::MenuHash ($MW->Menubutton (
         -relief       => 'raised',
         -text         => 'Pick something',
         -underline    => 0,
     )->pack (
         -side         => 'left',
     ));

     $menu->{'Option one (default)'}               = 'default';
     $menu->{'Option two (print "two")'}           = sub { print "two\n" };
     $menu->{'Option three (exit)'}                = sub { $MW->destroy };
     $menu->{'Option four (print current text)'}   = sub { print "$menu->{foobar}\n" };

     MainLoop;

AUTHOR
======

   Zenin <zenin@bawdycaste.com>

   aka Byron Brummer <byron@omix.com>

COPYRIGHT
=========

   Copyright (c) 1998, 1999 OMIX, Inc.

   Available for use under the same terms as perl.

Create and manipulate Menubutton widgets
****************************************

NAME
====

   Tk::Menubutton - Create and manipulate Menubutton widgets

   *$menubutton* = *$parent*->Menubutton(?options?);

STANDARD OPTIONS
================

*-activebackground*	*-cursor*	*-highlightthickness*	*-takefocus*
*-activeforeground*	*-disabledforeground*	*-image*	*-text*
*-anchor*	*-font*	-justify	*-textvariable*
*-background*	*-foreground*	*-padx*	*-underline*
*-bitmap*	*-highlightbackground*	*-pady*	*-wraplength*
*-borderwidth*	*-highlightcolor*	*-relief*

   See Tk/options, for details of the standard options.

WIDGET-SPECIFIC OPTIONS
=======================

Name:	*direction*
Class:	*Height*
Switch:	*-direction*
     Specifies where the menu is going to be popup up. above tries to pop
     the menu above the menubutton. below tries to pop the menu below the
     menubutton. left tries to pop the menu to the left of the menubutton.
     right tries to pop the menu to the right of the menu button. flush
     pops the menu directly over the menubutton.

Name:	height
Class:	*Height*
Switch:	*-height*
     Specifies a desired height for the menubutton.  If an image or bitmap
     is being displayed in the menubutton then the value is in screen
     units (i.e. any of the forms acceptable to *Tk_GetPixels*); for text
     it is in lines of text.  If this option isn't specified, the
     menubutton's desired height is computed from the size of the image or
     bitmap or text being displayed in it.

Name:	*indicatorOn*
Class:	*IndicatorOn*
Switch:	*-indicatoron*
     The value must be a proper boolean value.  If it is true then a small
     indicator rectangle will be displayed on the right side of the
     menubutton and the default menu bindings will treat this as an option
     menubutton.  If false then no indicator will be displayed.

Name:	menu
Class:	*MenuName*
Switch:	*-menu*
     Specifies the path name of the menu associated with this menubutton.
     The menu must be a child of the menubutton.

Name:	state
Class:	State
Switch:	*-state*
     Specifies one of three states for the menubutton:  normal, active, or
     disabled.  In normal state the menubutton is displayed using the
     *foreground* and background options.  The active state is typically
     used when the pointer is over the menubutton.  In active state the
     menubutton is displayed using the *activeForeground* and
     *activeBackground* options.  Disabled state means that the menubutton
     should be insensitive:  the default bindings will refuse to activate
     the widget and will ignore mouse button presses.  In this state the
     *disabledForeground* and background options determine how the button
     is displayed.

Name:	width
Class:	Width
Switch:	*-width*
     Specifies a desired width for the menubutton.  If an image or bitmap
     is being displayed in the menubutton then the value is in screen
     units (i.e. any of the forms acceptable to *Tk_GetPixels*); for text
     it is in characters.  If this option isn't specified, the
     menubutton's desired width is computed from the size of the image or
     bitmap or text being displayed in it.

DESCRIPTION
===========

   The Menubutton method creates a new window (given by the $widget
argument) and makes it into a menubutton widget.  Additional options,
described above, may be specified on the command line or in the option
database to configure aspects of the menubutton such as its colors, font,
text, and initial relief.  The *menubutton* command returns its $widget
argument.  At the time this command is invoked, there must not exist a
window named $widget, but $widget's parent must exist.

   A menubutton is a widget that displays a textual string, bitmap, or
image and is associated with a menu widget.  If text is displayed, it must
all be in a single font, but it can occupy multiple lines on the screen
(if it contains newlines or if wrapping occurs because of the *wrapLength*
option) and one of the characters may optionally be underlined using the
underline option.  In normal usage, pressing mouse button 1 over the
menubutton causes the associated menu to be posted just underneath the
menubutton.  If the mouse is moved over the menu before releasing the
mouse button, the button release causes the underlying menu entry to be
invoked.  When the button is released, the menu is unposted.

   Menubuttons are typically organized into groups called menu bars that
allow scanning: if the mouse button is pressed over one menubutton
(causing it to post its menu) and the mouse is moved over another
menubutton in the same menu bar without releasing the mouse button, then
the menu of the first menubutton is unposted and the menu of the new
menubutton is posted instead.

   There are several interactions between menubuttons and menus;  see the
menu manual entry for information on various menu configurations, such as
pulldown menus and option menus.

WIDGET METHODS
==============

   The Menubutton method creates a widget object.  This object supports
the configure and cget methods described in Tk/options,
which can be used to enquire and modify the options described above.  The
menu method returns the menu associated with the widget.  The widget also
inherits all the methods provided by the generic `Tk::Widget|Tk::Widget'
in this node class.

DEFAULT BINDINGS
================

   Tk automatically creates class bindings for menubuttons that give them
the following default behavior:

[1]
     A menubutton activates whenever the mouse passes over it and
     deactivates whenever the mouse leaves it.

[2]
     Pressing mouse button 1 over a menubutton posts the menubutton: its
     relief changes to raised and its associated menu is posted under the
     menubutton.  If the mouse is dragged down into the menu with the
     button still down, and if the mouse button is then released over an
     entry in the menu, the menubutton is unposted and the menu entry is
     invoked.

[3]
     If button 1 is pressed over a menubutton and then released over that
     menubutton, the menubutton stays posted: you can still move the mouse
     over the menu and click button 1 on an entry to invoke it.  Once a
     menu entry has been invoked, the menubutton unposts itself.

[4]
     If button 1 is pressed over a menubutton and then dragged over some
     other menubutton, the original menubutton unposts itself and the new
     menubutton posts.

[5]
     If button 1 is pressed over a menubutton and released outside any
     menubutton or menu, the menubutton unposts without invoking any menu
     entry.

[6]
     When a menubutton is posted, its associated menu claims the input
     focus to allow keyboard traversal of the menu and its submenus.  See
     the menu documentation for details on these bindings.

[7]
     If the underline option has been specified for a menubutton then
     keyboard traversal may be used to post the menubutton: Alt+x, where x
     is the underlined character (or its lower-case or upper-case
     equivalent), may be typed in any window under the menubutton's
     toplevel to post the menubutton.

[8]
     The F10 key may be typed in any window to post the first menubutton
     under its toplevel window that isn't disabled.

[9]
     If a menubutton has the input focus, the space and return keys post
     the menubutton.

     If the menubutton's state is disabled then none of the above actions
     occur:  the menubutton is completely non-responsive.

     The behavior of menubuttons can be changed by defining new bindings
     for individual widgets or by redefining the class bindings.

KEYWORDS
========

   menubutton, widget

Another menubar with help menu support, etc
*******************************************

NAME
====

   Tk::Menustrip - Another menubar with help menu support, etc

SYNOPSIS
========

     use Tk::Menustrip;
     use Tk;

     my $MainWindow = MainWindow->new();

     my $l_Menubar = $this->Menustrip();

     $l_Menubar->MenuLabel     ('File'),
     $l_Menubar->MenuEntry     ('File', 'Save', sub {Save();});
     $l_Menubar->MenuSeparator ('File');
     $l_Menubar->MenuEntry     ('File', 'Exit', sub {Exit();});

     $l_Menubar->MenuLabel     ('Help', '-right');
     $l_Menubar->MenuEntry     ('Help', 'About...');
     $l_Menubar->MenuSeparator ('Help');
     $l_Menubar->MenuEntry     ('Help', 'Help On...');

     $l_Menubar->pack(-fill => 'x');

     Tk::MainLoop;

DESCRIPTION
===========

AUTHORS
=======

   Damion K. Wilson, dkw@rcm.bm

HISTORY    =cut
===============

Perl/Tk module for message and button dialogue boxes.
*****************************************************

NAME
====

   MesgBox - Perl/Tk module for message and button dialogue boxes.

SYNOPSIS
========

     use MesgBox;

     # Example 1: an 'OK' box.
     # Pressing <Space>, <Return>, <o>, <Control-o> or <Alt-o> will close the box.

     my $msg = $Window->MesgBox(-title => 'Test', -text => 'Test Complete.');
     $msg->Show;

     # Example 2: a 'Yes/No' box.
     # Pressing <Space>, <Return>, <y>, <Control-y> or <Alt-y>
     # presses the 'Yes' button;
     # pressing <n>, <Control-n> or <Alt-n> presses the 'No' button.

     my $msg = $Window->MesgBox(
         -title     => 'Save File?',
         -text      => "Save '$filename'?",
         -icon      => 'QUESTION',
         -buttons   => ['Yes', 'No'],
         -defbutton => 'Yes',
         );
     my $ans = $msg->Show;
     &save_file if $ans eq 'Yes';

     # Example 3: an 'OK/Cancel' box.
     # Pressing <Space>, <Return>, <o>, <Control-o> or <Alt-o> presses the 'OK'
     # button;
     # pressing <Escape>, <c>, <Control-c> or <Alt-c> presses the 'Cancel'
     # button.

     my $msg = $Window->MesgBox(
         -title   => 'Print',
         -text    => 'Print the page',
         -buttons => ['OK', 'Cancel'],
         );
     my $ans = $msg->Show;
     &print if $ans eq 'OK';

DESCRIPTION
===========

   This message box is similar to the MsgBox function provided with
Windows. It provides a message text with an optional 'icon' and any
buttons required. It is not as versatile as the Dialog box supplied with
Tk but is simpler, and it provides automatic keyboard bindings.

   All options are optional, although defining a `-title' and `-text' is
only sensible. Leaving out everything else will provide a simple OK button.

   The keyboard is bound such that the first letter of each button is
bound both as a letter alone and in conjunction with both Control and Alt.
This letter is also displayed underlined. It is recommended that each
button's text begins with a unique letter. Any button with the text 'OK'
will be the default button responding to <Return>, unless overridden by
the `-defbutton' option. Any button with the text 'Cancel' will be the
default cancel button responding to <Escape> unless overridden by the
`-canbutton' option.

   `-title' is the text which appears in the title bar.

   `-text' is the text which appears in the body of the message. It may
include newlines which are respected, but it will wrap.

   `-icon' is the 'icon' which appears to the left of the message. It may
be one of Tk's standard bitmaps: info 'i', error '(\)', warning '!',
question '?'; or one of the MesgBox versions: INFO 'i', ERROR 'E', WARNING
'!', QUESTION '?'. It may be undefined meaning no image appears.

   `-defbutton' is the default button. It defaults to the 'OK' button if
there is one. The default button is the button 'pressed' when the user
presses <Return>.

   `-canbutton' is the cancel button. It defaults to the 'Cancel' button
if there is one. The cancel button is the button 'pressed' when the user
presses <Escape>.

   `-buttons' is an array of button captions. By default it is set to a
list consisting of one element, 'OK'. You may use any text, e.g. 'OK',
'Cancel', 'Yes', 'Retry', etc. You may have as many buttons as you like -
although too many might not fit on the screen...

   `-aspect' is the ratio of width to height. Generally increase this past
the default of 200, say to 300, 400 or 500 to make the message box wider
and shorter.

   -justify sets the justification for the `-text' - may be 'center',
'left' or 'right'. Defaults to 'center'.

   `-textfg' sets the foreground colour for the `-text'; default is black.

   `-textbg' sets the background colour for the `-text'; default is
lightgrey.

   `-buttonfont' sets the font for the button; default is 12pt Helvetica.

   `-bindctrl' sets the keyboard bindings to include <Control-$letter>,
defaults to true.

   `-bindalt' sets the keyboard bindings to include <Alt-$letter>, defaults
to true.

   `-bindord' sets the keyboard bindings to include <$letter>, defaults to
true.

   `-buttonpadx' sets the left and right padding around the button,
defaults to 0.

   `-buttonpady' sets the above and below padding around the button,
defaults to 0.

   `-buttonfg' sets the button foreground colour, defaults to black.

   `-buttonbg' sets the button foreground colour, defaults to lightgrey.

   `-buttonHL' sets the button highlight colour, defaults to lightgrey.

INSTALLATION
============

   MesgBox.pm should be placed in any Tk directory in any lib directory in
Perl's %INC path, for example, '/usr/lib/perl5/Tk'.

BUGS
====

   MesgBox does almost no error checking.

CHANGES
=======

   1999/01/18  First public release.

   1999/01/22  Minor documentation changes.

   1999/01/23  Tidied up set_icon.

   1999/02/23  Should now be Windows compatible.

   1999/08/05  Just changed the files to make them more CPAN friendly.

   1999/08/08  Changed licence to LGPL.

   1999/09/06  Minor change to packaging for CPAN.

   1999/10/01  Changed the Show() method so that it is now compatible with
           Tk800.015 as well as earlier Tk800 versions.

   2000/05/05  Minor increment because I accidentally deleted it from CPAN.

   2000/09/16  Added new options to control colours and padding: almost
all the             new code was supplied by Daniel Berger.

AUTHOR
======

   Mark Summerfield. I can be contacted as <summer@perlpress.com> - please
include the word 'mesgbox' in the subject line.

   The code draws very heavily from Stephen O. Lidie's Dialog.pm module.

COPYRIGHT
=========

   Copyright (c) Mark Summerfield 1999,2000. All Rights Reserved.

   This module may be used/distributed/modified under the LGPL.

Create and manipulate Message widgets
*************************************

NAME
====

   Tk::Message - Create and manipulate Message widgets

   *$message* = *$parent*->Message(?options?);

STANDARD OPTIONS
================

*-anchor*	*-font*	*-highlightthickness*	*-takefocus*
*-background*	*-foreground*	*-padx*	*-text*
*-borderwidth*	*-highlightbackground*	*-pady*	*-textvariable*
*-cursor*	*-highlightcolor*	*-relief*	*-width*

   See Tk/options, for details of the standard options.

WIDGET-SPECIFIC OPTIONS
=======================

Name:	*aspect*
Class:	*Aspect*
Switch:	*-aspect*
     Specifies a non-negative integer value indicating desired aspect
     ratio for the text.  The aspect ratio is specified as
     100*width/height.  100 means the text should be as wide as it is
     tall, 200 means the text should be twice as wide as it is tall, 50
     means the text should be twice as tall as it is wide, and so on.
     Used to choose line length for text if width option isn't specified.
     Defaults to 150.

Name:	justify
Class:	Justify
Switch:	-justify
     Specifies how to justify lines of text.  Must be one of left, center,
     or right.  Defaults to left.  This option works together with the
     anchor, *aspect*, *padX*, *padY*, and width options to provide a
     variety of arrangements of the text within the window.  The *aspect*
     and width options determine the amount of screen space needed to
     display the text.  The anchor, *padX*, and *padY* options determine
     where this rectangular area is displayed within the widget's window,
     and the justify option determines how each line is displayed within
     that rectangular region.  For example, suppose anchor is e and
     justify is left, and that the message window is much larger than
     needed for the text.  The the text will displayed so that the left
     edges of all the lines line up and the right edge of the longest line
     is *padX* from the right side of the window;  the entire text block
     will be centered in the vertical span of the window.

Name:	width
Class:	Width
Switch:	*-width*
     Specifies the length of lines in the window.  The value may have any
     of the forms acceptable to *Tk_GetPixels*.  If this option has a
     value greater than zero then the *aspect* option is ignored and the
     width option determines the line length.  If this option has a value
     less than or equal to zero, then the *aspect* option determines the
     line length.

DESCRIPTION
===========

   The Message method creates a new window (given by the $widget argument)
and makes it into a message widget.  Additional options, described above,
may be specified on the command line or in the option database to
configure aspects of the message such as its colors, font, text, and
initial relief.  The message command returns its $widget argument.  At the
time this command is invoked, there must not exist a window named $widget,
but $widget's parent must exist.

   A message is a widget that displays a textual string.  A message widget
has three special features.  First, it breaks up its string into lines in
order to produce a given aspect ratio for the window.  The line breaks are
chosen at word boundaries wherever possible (if not even a single word
would fit on a line, then the word will be split across lines).  Newline
characters in the string will force line breaks;  they can be used, for
example, to leave blank lines in the display.

   The second feature of a message widget is justification.  The text may
be displayed left-justified (each line starts at the left side of the
window), centered on a line-by-line basis, or right-justified (each line
ends at the right side of the window).

   The third feature of a message widget is that it handles control
characters and non-printing characters specially.  Tab characters are
replaced with enough blank space to line up on the next 8-character
boundary.  Newlines cause line breaks.  Other control characters (ASCII
code less than 0x20) and characters not defined in the font are displayed
as a four-character sequence *\x**hh* where *hh* is the two-digit
hexadecimal number corresponding to the character.  In the unusual case
where the font doesn't contain all of the characters in
"0123456789abcdef\x" then control characters and undefined characters are
not displayed at all.

WIDGET METHODS
==============

   The Message method creates a widget object.  This object supports the
configure and cget methods described in Tk/options,
which can be used to enquire and modify the options described above.  The
widget also inherits all the methods provided by the generic
`Tk::Widget|Tk::Widget' in this node class.

DEFAULT BINDINGS
================

   When a new message is created, it has no default event bindings:
messages are intended for output purposes only.

BUGS
====

   Tabs don't work very well with text that is centered or right-justified.
The most common result is that the line is justified wrong.

KEYWORDS
========

   message, widget

Calendar widget which shows one month at a time.
************************************************

NAME
====

   Tk::Month - Calendar widget which shows one month at a time.

SYNOPSIS
========

     use Tk;
     use Tk::Month;

     $m = $parent->Tk::Month(
     		-month		=> 'July',
     		-year		=> '1997',
     		-title		=> '%b %y',
     		-command	=> \&press,
     		-printformat	=> '%e',
     		-navigation	=> [0|1],
     		-includeall	=> [0|1],
     		-showall	=> [0|1],
     		-first		=> [0|1|2|3|4|5|6],
     	)->pack();

     $m->configure(
     		-month		=> 'July',
     		-year		=> '1997',
     		-command	=> \&press,
     		-printformat	=> '%e %B %Y %A',
     		-navigation	=> [0|1],
     		-includeall	=> [0|1],
     		-showall	=> [0|1],
     		-first		=> [0|1|2|3|4|5|6],
     );

     $m->separator();
     $m->command(
     		-label		=> 'Label',
     		-command	=> \&callback,
     );

DESCRIPTION
===========

   Tk::Month is a general purpose calendar widget which shows one month at
a time and allowes user defined button actions.

FUNCTIONS
=========

$m->separator();
----------------

     Adds a separator to the title menu.

$m->command(...);
-----------------

     Adds an entry to the title menu. This can be used to add
     extra functionality, such as closing the calendar widget or
     printing a month.

OPTIONS
=======

-month => 'month'
-----------------

     Sets the required month. The default is the current month.

-year => 'year'
---------------

     Sets the required year. The default is the current year.

-title => 'strftime format'
---------------------------

     Sets the format for the widget title.
     The default is '%B %Y'.

-command => \&press
-------------------

     Set the command to execute when a button is pressed.
     This function must accept a string
     (the title of the Month widget)
     and an array of arrays of dates.
     Each date is of the format specified by the -printformat option.
     The default is to print out the list on standard output.

-printformat	=> "strftime format"
---------------------------------

     Set the default format for dates when they are passed in an
     array of arrays to the -command function.
     The default is '%e %B %Y'.

DISCONTINUED -printcommand	=> \&print
-------------------------------------

     Add an entry to the title menu using the 'command' function.

DISCONTINUTED -close		=> $widget,
---------------------------------

     Add an entry to the title menu using the 'command' function.

-showall		=> [0|1]
------------------

     Causes the dates on buttons not actually in the month to be
     dsiplay. The default is to not show these dates.

-includeall	=> [0|1]
--------------------

     Causes the side buttons to include all the non-month dates.
     The defaults is to include all the dates.

-first	=> [0|1|2|3|4|5|6]
-------------------------

     Sets the first day of the week.
     The default is 0 (i.e. Sunday).

-navigation	=> [0|1],
---------------------

     Sets whether the navigation buttons and menu are included.
     The default is to show the naviagation aids.

a 'more' or 'less' like text widget
***********************************

NAME
====

   Tk::More - a 'more' or 'less' like text widget

SYNOPSIS
========

     use Tk::More;

     $more = $parent->More(...text widget options ...);
     $more->Load(FILENAME);

DESCRIPTION
===========

   *Tk::More* is a readonly text widget with additional key bindings as
found in UNI* command line tool more.  As in more an additional
status/command line is added at the bottom.

ADDITIONAL BINDINGS
===================

Key-G
     goto end of file

Key-f
     like next key

Key-b
     like prior key

Key-k
     like up key

Key-j
     like down key

Key-/
     search forward

Key-n
     find next match

Key-N
     find previous match

BUGS
====

   Besides that most of more bindings are not implemented. This bugs me
most (high to low priority):

   * Reverse search missing

   * better status line implementation

   * Cursor movement: up/down move displayed area regardless where
insert cursor is

   * add History, Load, Search (also as popup menu)

   * Key-u and Key-d should move 1/2 screen and not 90% of a screen

   * bad history impl.

SEE ALSO
========

   `Tk::ROText|Tk::ROText' in this node more(1)

AUTHOR
======

   Achim Bohnet <`ach@mpe.mpg.de'>

   Copyright (c) 1997-1998 Achim Bohnet. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Do not use
**********

NAME
====

   Tk::Multi::Any - Do not use

SYNOPSIS
========

DESCRIPTION
===========

   This class contains a Print dialog box. Do not use it. This class will
be removed on the next version. The other Multi widget will use the soon
to be released PrintDialog widget.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1997-1998 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1), Tk(3), Tk::Multi(3), Tk::Multi::Manager(3)

Tk composite widget with a scroll window and more
*************************************************

NAME
====

   Tk::Multi::Canvas - Tk composite widget with a scroll window and more

SYNOPSIS
========

     use Tk::Multi::Manager;

     use Tk::Multi::Canvas ;

     my $manager = yourWindow -> MultiManager
      (
       menu => $menu_ref , # optionnal
       title => "windows" # optionnal
      ) -> pack ();

     # Don't pack it, the manager will do it
     my $w1 = $manager -> newSlave('type' => 'MultiCanvas', 'title' => 'a_label');

DESCRIPTION
===========

   This composite widget features :

   * a scrollable Canvas

   * A print button (The shell print command may be modified by setting
     $Tk::Multi::Canvas::printCmd to the appropriate shell command. By
     default, it is set to 'lp -opostscript')

   * a clear button

   This widget will forward all unrecognize commands to the Canvas object.

   Note that this widget should be created only by the Multi::Manager.

WIDGET-SPECIFIC OPTIONS
=======================

title
-----

   Some text which will be displayed above the test window.

menu_button
-----------

   The log window feature a set of menu items which must be added in a
menu.  This menu ref must be passed with the menu_button prameter to the
object during its instaciation

WIDGET-SPECIFIC METHODS
=======================

setSize( heigth, [ width ])
---------------------------

   Will resize the canvas window.

print
-----

   Will raise a popup window with an Entry to modify the actual print
command, a print button, a default button (to restore the default print
command), and a cancel button.

doPrint
-------

   Print the label and the content of the text window. The print is invoked
by dumping the text content into a piped command.

   You may want to set up a new command to print correctly on your machine.
You may do it by using the setPrintCmd method or by invoking the 'print'
method.

setPrintCmd('print command')
----------------------------

   Will set the $printCmd class variable to the passed string. You may use
this method to set the appropriate print command on your machine. Note that
using this method will affect all other Tk::Multi::Canvas object since the
modified variable is not an instance variable but a class variable.

clear
-----

   clear all items in the canvas.

Delegated methods
=================

   By default all widget method are delegated to the Text widget. Excepted
:

command(-label => 'some text', -command => sub {...} )
------------------------------------------------------

   Delegated to the menu entry managed by Multi::Manager. Will add a new
command to the aforementionned menu.

TO DO
=====

   I'm not really satisfied with print management. May be one day, I'll
write a print management composite widget which will look like Netscape's
print window. But that's quite low on my priority list. Any volunteer ?

   Dragging middle mouse button to scroll the canvas.

   Defines ressources for the config options.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

SEE ALSO
========

   perl(1), Tk(3), Tk::Multi(3), Tk::Multi::Manager(3)

Tk composite widget with a scroll window and more
*************************************************

NAME
====

   Tk::Multi::Frame - Tk composite widget with a scroll window and more

SYNOPSIS
========

     use Tk::Multi::Manager;

     use Tk::Multi::Frame ;

     my $manager = yourWindow -> MultiManager
      (
       menu => $menu_ref , # optionnal
       printSub => $sub_ref ,  # optionnal
       title => "windows" # optionnal
      ) -> pack ();

     # Don't pack it, the manager will do it
     my $w1 = $manager -> newSlave('type' => 'MultiFrame', 'title' => 'a_label');

DESCRIPTION
===========

   This composite widget features :

   * a scrollable Frame

   * A print button (if the printSub parameter was provided)

     (The shell print command may be modified by setting
     $Tk::Multi::Frame::printCmd to the appropriate shell command. By
     default, it is set to 'lp -opostscript')

   This widget will forward all unrecognize commands to the Frame object.

   Note that this widget should be created only by the Multi::Manager.

WIDGET-SPECIFIC OPTIONS
=======================

title
-----

   The frame title (See Tk/TFrame)

menu_button
-----------

   The log window feature a set of menu items which must be added in a
menu.  This menu ref must be passed with the menu_button prameter to the
object during its instaciation

printSub
--------

   By itself, a frame cannot be printed. So if the user wants to print
some informations related to what's packed inside the frame, he must
provide a sub ref which will return a string. This string will be printed
as is by the widget.

WIDGET-SPECIFIC METHODS
=======================

print
-----

   Will raise a popup window with an Entry to modify the actual print
command, a print button, a default button (to restore the default print
command), and a cancel button.

doPrint
-------

   Print the label and the content of the text window. The print is invoked
by dumping the text content into a piped command.

   You may want to set up a new command to print correctly on your machine.
You may do it by using the setPrintCmd method or by invoking the 'print'
method.

setPrintCmd('print command')
----------------------------

   Will set the $printCmd class variable to the passed string. You may use
this method to set the appropriate print command on your machine. Note that
using this method will affect all other Tk::Multi::Frame object since the
modified variable is not an instance variable but a class variable.

clear
-----

   clear all items in the canvas.

Delegated methods
=================

   By default all widget method are delegated to the TFrame widget.
Excepted :

command(-label => 'some text', -command => sub {...} )
------------------------------------------------------

   Delegated to the menu entry managed by Multi::Manager. Will add a new
command to the aforementionned menu.

TO DO
=====

   I'm not really satisfied with print management. May be one day, I'll
write a print management composite widget which will look like Netscape's
print window. But that's quite low on my priority list. Any volunteer ?

   Dragging middle mouse button to scroll the canvas.

   Defines ressources for the config options.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

SEE ALSO
========

   perl(1), Tk(3), Tk::Multi(3), Tk::Multi::Manager(3)

Tk composite widget managing Tk::Multi slaves
*********************************************

NAME
====

   Tk::Multi::Manager - Tk composite widget managing Tk::Multi slaves

SYNOPSIS
========

     use Tk::Multi::Manager ;
     use Tk::Multi::Text ; # if you use MultiText as a slave

     my $manager = yourWindow -> MultiManager
      (
       menu => $menu_ref , # optionnal
       title => "windows", # optionnal
       help => "Explain what your set of widget do" #optionnal
      ) -> pack ();

     # Don't pack it, the managet will do it
     my $w1 = $manager -> newSlave
      (
       'type' => 'MultiText',
       'title' => 'a_label',
       help => "Explain what your slave widget does" #optionnal
      );

DESCRIPTION
===========

   The manager is a composite widget made of a menu cascade of check
buttons and slaves which can be Tk::Multi::Text.

   The user can add windows to the manager. Each window visibility is
controled by a check button in the menu cascade.  The check button
actually tells the packer to forget the window. note that the window
object is not destroyed.

   The main menu bar will feature a 'Help' menu on the right. If the main
help which explain the purpose of the Multi::Manager and its slaves is
provided when creating the widget, the Help sub-menu will feature a
'global' label.

   Each slave widget which is created with a help will have its own label
in the help menu.

Multi widgets
=============

   This package features the following Multi widgets:

   * See Tk/Multi/Text

   * See Tk/Multi/Canvas

Constructor configuration options
=================================

menu
----

   The widget may use a 'menu' argument which will be used to create a
menu item and releveant sub-menus to control the sub-window.  If not
provided, the widget will create a its own menu.

title
-----

   The optionnal title argument contains the title of the menu created by
the manager.

help
----

   The argument may be a string or a sub reference.

   When the help menu is invoked, either the help string will be displayed
in a Tk/Dialog, box or the sub will be run. In this case
it is the user's responsability to provide a readable help from the sub.

Methods
=======

newSlave(...) ;
---------------

   Create a new slave to manager. Returns the slave widget object.
Parameters are:

   * type: specifies the kind of Multi widget (e.g. MultiText).

   * title: specifies the title of the widget (mandatory).

   * before: specify that you want this new slave to be packed before
     (well, above) another widget. This parameter will be set to the
     'title' of this other widget.

   * side: when set to 'top', the widget will be packed on top of the
     others.  (default to 'bottom').

   * hidden: specifies whether the widget is to be packed right now or not
     (default 0)

   * destroyable: a 'destroy' button is created if this parameter is
     defined (default no).  Returns the slave widget reference.

   * help: This argument may be specified like the help parameter defined
     above for the constructor.

getSlave('name of the slave');
------------------------------

   Return the slave widget or undef.

hide('name of the slave');
--------------------------

   Hide the slave.

show('name of the slave');
--------------------------

   Show the slave.

destroySlave( 'name of the slave') ;
------------------------------------

   Destroy the slave

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1997-1999 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1), Tk(3), Tk::Multi::Text(3), Tk::Multi::Canvas(3)

Tk composite widget with a scroll window and more
*************************************************

NAME
====

   Tk::Multi::Text - Tk composite widget with a scroll window and more

SYNOPSIS
========

     use Tk::Multi::Manager;

     use Tk::Multi::Text ;

     my $manager = yourWindow -> MultiManager
      (
       menu => $menu_ref , # optionnal
       title => "windows" # optionnal
      ) -> pack ();

     # Don't pack it, the managet will do it
     my $w1 = $manager -> newSlave('type' => 'MultiText', 'title' => 'a_label');

DESCRIPTION
===========

   This composite widget features :

   * a scrollable read-only text window (based on ROtext)

   * A print menu button (The shell print command may be modified by
     setting $Tk::Multi::Text::printCmd to the appropriate shell command.
     By default, it is set to 'lp -ol70 -otl66 -o12 -olm10')

   * a clear menu button.

   This widget will forward all unrecognize commands to the ROtext object.

   Note that this widget should be created only by the Multi::Manager.

WIDGET-SPECIFIC OPTIONS
=======================

title
-----

   Some text which will be displayed above the test window.

menu_button
-----------

   The log window feature a set of menu items which must be added in a
menu.  This menu ref must be passed with the menu_button prameter to the
object during its creation.

data
----

   A string which will be displayed in the text window.

WIDGET-SPECIFIC METHODS
=======================

insertText($some_text)
----------------------

   Insert the passed string at the bottom of the text window

print
-----

   Will raise a popup window with an Entry to modify the actual print
command, a print button, a default button (to restore the default print
command), and a cancel button.

clear
-----

   Is just a delete('1.0','end') .

Delegated methods
=================

   By default all widget method are delegated to the Text widget. Excepted
:

command(-label => 'some text', -command => sub {...} )
------------------------------------------------------

   Delegated to the menu entry managed by Multi::Manager. Will add a new
command to the aforementionned menu.

TO DO
=====

   Defines ressources for the config options.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1997-1998 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1), Tk(3), Tk::Multi(3), Tk::Multi::Manager(3)

Toplevel MultiManager
*********************

NAME
====

   Tk::Multi::Toplevel - Toplevel MultiManager

SYNOPSIS
========

     use Multi::Toplevel ;

     my $mw = MainWindow-> new ;

     my $p = $mw->MultiTop();

     # If Multi::Toplevel is the only Tk window of your application
     $mw -> withdraw ; # hide the main window
     # destroy the main window when close is called
     $p -> OnDestroy(sub{$mw->destroy});

     # add a 'bar' menu with a 'foo' button on the menu bar
     $p->menuCommand(name => 'foo', menu => 'bar',
                     sub => sub{warn "invoked  bar->foo\n";});

     # add a menu button on the 'File' menu
     $p->add(
             'command',
             -label => 'baz',
             command => sub {warn "invoked  File->baz\n";}
            );

DESCRIPTION
===========

   This class is a Tk/Multi/Manager, packed in a
Toplevel window. It features also :

   * 'File->show internal...' button to invoke an Object Scanner (See
     Tk/ObjScanner)

   * A facility to manage user menus with sorted buttons

   * A help facility based on Tk/Pod,

Users menus
===========

   By default the Multi::Toplevel widget comes with 3 menubuttons:

   * 'File' for the main widget commands

   * 'windows' to manage the Multi slaves widget

   * 'Help'

   The user can also add its own menus and menu buttons to the main
menubar.  When needed the user can call the menuCommand method to add a
new menu button (and as new menu if necessary) . Then the user can remove
the menu button with the menuRemove command.

   For instance, if the user call :

     $widget->->menuCommand(name => 'foo', menu => 'example',
       sub => \&a_sub);

     The menubar will feature a new 'example' menu with a 'foo' button.

   Then if the user call :

     $widget->->menuCommand(name => 'bar', menu => 'example',
       sub => \&a_sub);

   The menubar will feature a new 'bar' button in the 'example' menu. Note
that menu buttons are sorted alphabetically.

   Then if the user call :

     $widget->menuRemove(name => 'bar', menu => 'example');

   The bar button will be removed from the menu bar.

Constructor configuration options
=================================

manager
-------

   Object reference that will be scanned by the ObjScanner. Usefull when
you want to debug the object that actually use the Multi::TopLevel. By
default the ObjScanner will scan the Multi::TopLevel object.

podName
-------

   This the name of the pod file that will be displayed with the
'Help'->'global' button. This should be set to the pod file name of the
class or the application using this widget.

   By default, the help button will display the pod file of
Multi::TopLevel.

podSection
----------

   This the section of the pod file that will be displayed with the
'Help'->'global' button.

   By default, the help button will display the 'DESCRIPTION' pod section.

Advertised widgets
==================

   * fileMenu: 'File' Tk::Menu (on the left of the menu bar)

   * menubar : the Tk::Frame containing the menu buttons

   * multiMgr: The Tk::Multi::Manager

delegated methods
=================

   * newSlave, hide, show, destroySlave : To the Tk::Multi::Manager

   * add, delete, insert : To the 'File' Tk::Menu

Methods
=======

menuCommand()
-------------

   Parameters are :

   * name: button_name

   * menu: menu_name

   * command: subref

   Will add the 'button_name' button in the 'menu_name' menu to invoke the
sub ref. If necessary, the 'menu_name' menu will be created.

menuRemove ()
-------------

   * name: button_name

   * menu: menu_name

   Will remove the 'button_name' button from the 'menu_name' menu.  If no
buttons are left, the 'menu_name' menu will be removed from the menu bar.

showHelp (...)
--------------

   Parameters are :

   * pod: pod file name (optional, defaults to the file name passed to the
     constructor or to 'Tk::Multi::Toplevel')

   * section: pod_section (optional, defaults to the sectione name passed
     to the constructor or to 'DESCRIPTION')

   Will invoke the Tk::Pod documentation widget of the specified pod file
and pod section.

BUGS
====

   Users menu does not fold when you insert a lot of buttons.

   Tk::Pod 0.10 does not display the specified section. Use a later
version or this patch
(http://www.xray.mpe.mpg.de/mailing-lists/ptk/1998-11/msg00033.html)

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998-1999 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1), Tk(3), Tk::Multi::Manager(3), Tk::Pod(3), Tk::ObjScanner(3),
Tk::mega(3)

Communicate with the Motif(tm) window manager.
**********************************************

NAME
====

   Tk::Mwm - Communicate with the Motif(tm) window manager.

       *use Tk::Mwm;*

       *$toplevel*->*mwm*Option?(args)?

       *$toplevel*->*mwm*(option ?,args?)

DESCRIPTION
===========

   Interface to special extentions supported by mwm.

METHODS
=======

*$toplevel*->*mwmDecoration*?(?option??=>value? ?,...?)?
     When no options are given, this method returns the values of all the
     decorations options for the toplevel window with the *$toplevel*.
     When only one option is given without specifying the value, the
     current value of that option is returned.  When more than one
     "option-value" pairs are passed to this method, the specified values
     will be assigned to the corresponding options. As a result, the
     appearance of the Motif decorations around the toplevel window will
     be changed.  Possible options are: *-border*, *-menu*, *-maximize*,
     *-minimize*, *-resizeh* and *-title*. The value must be a Boolean
     value. The values returned by this command are undefined when the
     window is not managed by mwm.

*$toplevel*->*mwmIsmwmrunning*
     This returns value is true if mwm is running on the screen where the
     specified window is located, false otherwise.

*$toplevel*->*mwmProtocol*
     When no additional options are given, this method returns all
     protocols associated with this toplevel window.

*$toplevel*->*mwmProtocol*(activate => *protocol_name*)
     Activate the mwm protocol message in mwm's menu.

*$toplevel*->*MwmProtocol*(add => *protocol_name*, *menu_message*)
     Add a new mwm protocol message for this toplevel window. The message
     is identified by the string name specified in *protocol_name*.  A
     menu item will be added into mwm's menu as specified by
     *menu_message*.  Once a new mwm protocol message is added to a
     toplevel, it can be caught by the TK protocol method. Here is an
     example:

         *$toplevel*->*mwmProtocol*(*'add'* => 'MY_PRINT_HELLO', '"Print
     Hello"  _H Ctrl<Key>H');

         *$toplevel*->protocol(*'MY_PRINT_HELLO'* => sub {print "Hello"});

*$toplevel*->*mwmProtocol*(*'deactivate'* => *protocol_name*)
     Deactivate the mwm protocol message in mwm's menu.

*$toplevel*->*mwmProtocol*(*'delete'* => *protocol_name*)
     Delete the mwm protocol message from mwm's menu. Please note that the
     window manager protocol handler associated with this protocol (by the
     protocol method) is not deleted automatically. You have to delete the
     protocol handle explicitly.  E.g.:

         *$mw*->*mwmProtocol*(*'delete'* => 'MY_PRINT_HELLO');

         *$mw*->protocol(*'MY_PRINT_HELLO'* => ");

BUGS
====

   This is a Tix extension which perl/Tk has adopted. It has not been
tested as perl/Tk's author has not got round to installing a Motif Window
Manager.

   On some versions of mwm, the *-border* will not disappear unless
*-resizeh* is turned off. Also, the *-title* will not disappear unless all
of *-title*, *-menu*, *-maximize* and *-minimize* are turned off.

SEE ALSO
========

   `Tk::Wm|Tk::Wm' in this node `Tk::tixWm|Tk::tixWm' in this node
`Tk::Toplevel|Tk::Toplevel' in this node

KEYWORDS
========

   window manager, mwm, TIX

AUTHOR
======

   Ioi Kim Lam - ioi@graphics.cis.upenn.edu

display several windows in limited space with notebook metaphor.
****************************************************************

NAME
====

   Tk::NoteBook - display several windows in limited space with notebook
metaphor.

SYNOPSIS
========

     use Tk::NoteBook;
     ...
     $w = $frame->NoteBook();
     $page1 = $w->add("page1", options);
     $page2 = $w->add("page2", options);
     ...
     $page2 = $w->add("page2", options);

DESCRIPTION
===========

   The NoteBook widget provides a notebook metaphor to display several
windows in limited space. The notebook is divided into a stack of pages of
which only one is displayed at any time. The other pages can be selected
by means of choosing the visual "tabs" at the top of the widget.
Additionally, the <Tab> key may be used to traverse the pages.  If
*-underline* is used, Alt- bindings will also work.

   The widget takes all the options that a Frame does. In addition, it
supports the following options:

*-dynamicgeometry*
     If set to false (default and recommended), the size of the NoteBook
     will match the size of the largest page. Otherwise the size will
     match the size of the current page causing the NoteBook to change
     size when different pages of different sizes are selected.

*-ipadx*
     The amount of internal horizontal padding around the pages.

*-ipady*
     The amount of internal vertical padding around the pages.

METHODS
=======

   The following methods may be used with a NoteBook object in addition to
standard methods.

add(*pageName*, options)
     Adds a page with name *pageName* to the notebook. Returns an object
     of type Frame. The recognized options are:

    *-anchor*
          Specifies how the information in a tab is to be displayed. Must
          be one of n, ne, e, *se*, s, sw, w, *nw* or center.

    *-bitmap*
          Specifies a bitmap to display on the tab of this page. The bitmap
          is displayed only if none of the *-label* or *-image* options
          are specified.

    *-image*
          Specifies an image to display on the tab of this page. The image
          is displayed only if the *-label* option is not specified.

    *-label*
          Specifies the text string to display on the tab of this page.

    -justify
          When there are multiple lines of text displayed in a tab, this
          option determines the justification of the lines.

    *-createcmd*
          Specifies a `callback|Tk::callbacks' in this node to be called
          the first time the page is shown on the screen. This option can
          be used to delay the creation of the contents of a page until
          necessary. It can be useful in situations where there are a
          large number of pages in a NoteBook widget; with *-createcmd*
          you do not have to make the user wait until all pages are
          constructed before displaying the first page.

    *-raisecmd*
          Specifies a `callback|Tk::callbacks' in this node to be called
          whenever this page is raised by the user.

    *-state*
          Specifies whether this page can be raised by the user. Must be
          either normal or disabled.

    *-underline*
          Specifies the integer index of a character to underline in the
          tab. This option is used by the default bindings to implement
          keyboard traversal for menu buttons and menu entries. 0
          corresponds to the first character of text displayed on the
          widget, 1 to the next character and so on.

    *-wraplength*
          This option specifies the maximum line length of the label string
          on this tab. If the line length of the label string exceeds this
          length, then it is wrapped onto the next line so that no line is
          longer than the specified length. The value may be specified in
          any standard forms for screen distances. If this value is less
          than or equal to 0, then no wrapping is done: lines will break
          only at newline characters in the text.

delete(*pageName*)
     Deletes the page identified by *pageName*.

*pagecget(**pageName*, *-option*)
     Returns the current value of the configuration option given by
     *-option* in the page given by *pageName*. Option may have any of the
     values accepted in the add method.

*pageconfigure(**pageName*, options)
     Like configure for the page indicated by *pageName*. Options may be
     any of the options accepted by the add method.

*raise(**pageName*)
     Raise the page identified by *pageName*.

raised()
     Returns the name of the currently raised page.

AUTHORS
=======

   *Rajappa Iyer*  <rsi@earthling.net> Nick Ing-Simmons
<nick@ni-s.u-net.com>

   This code and documentation was derived from NoteBook.tcl in Tix4.0
written by Ioi Lam. It may be distributed under the same conditions as
Perl itself.

A numeric Entry widget with inc. & dec. Buttons
***********************************************

NAME
====

   Tk::NumEntry - A numeric Entry widget with inc. & dec. Buttons

SYNOPSIS
========

       *use Tk::NumEntry;*

       *$parent*->*NumEntry*(?*-option*=>value, ...?);

DESCRIPTION
===========

   *Tk::NumEntry* defines a widget for entering integer numbers. The widget
also contains buttons for increment and decrement.

   *Tk::NumEntry* supports all the options and methods that the plain
NumEntry widget provides (see Tk/NumEntryPlain),
plus the following options

STANDARD OPTIONS
================

   Besides the standard options of the `Entry|Tk::Entry' in this node
widget NumEntry supports:

   *-orient* *-repeatdelay* *-repeatinterval*

   The *-orient* option specifies the packing order of the increment and
decrement buttons.

WIDGET-SPECIFIC OPTIONS
=======================

Name:             *buttons*
Class:            Buttons
Switch:           *-buttons*
Fallback:		1
     Boolean that defines if the inc and dec buttons are visible.

WIDGET METHODS
==============

   Subclasses of NumEntry may override the following methods to use
different widgets for the composition of the NumEntry. These are:
NumEntryPlainWidget, FireButtonWidget, IncFireButtonWidget and
DecFireButtonWidget. FireButtonWidget is used if IncFireButtonWidget or
DecFireButtonWidget are not defined.

AUTHOR
======

   Graham Barr <`gbarr@pobox.com'>

   Current maintainer is Slaven Rezic <`eserte@cs.tu-berlin.de'>.

ACKNOWLEDGEMENTS
================

   I would to thank  Achim Bohnet <`ach@mpe.mpg.de'> for all the feedback
and testing. And for the splitting of the original Tk::NumEntry into
Tk::FireButton, Tk::NumEntryPlain and Tk::NumEntry

COPYRIGHT
=========

   Copyright (c) 1997-1998 Graham Barr. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

   Except the typo's, they blong to Achim :-)

A numeric entry widget
**********************

NAME
====

   Tk::NumEntryPlain - A numeric entry widget

SYNOPSIS
========

       *use Tk::NumEntryPlain*;

DESCRIPTION
===========

   *Tk::NumEntryPlain* defines a widget for entering integer numbers.

   *Tk::NumEntryPlain* supports all the options and methods that a normal
`Entry|Tk::Entry' in this node widget provides, plus the following options

STANDARD OPTIONS
================

   *-repeatdelay* *-repeatinterval*

WIDGET-SPECIFIC OPTIONS
=======================

-minvalue
     Defines the minimum legal value that the widget can hold. If this
     value is undef then there is no minimum value (default = undef).

-maxvalue
     Defines the maximum legal value that the widget can hold. If this
     value is undef then there is no maximum value (default = undef).

-bell
     Specifies a boolean value. If true then a bell will ring if the user
     attempts to enter an illegal character into the entry widget, and
     when the user reaches the upper or lower limits when using the
     up/down buttons for keys (default = true).

-textvariable
     Reference to a scalar variable that contains the value currently in
     the *NumEntry*.  Use the variable only for reading (see `"CAVEATS"'
     in this node below).

-value
     Specifies the value to be inserted into the entry widget. Similar to
     the standard *-text* option, but will perform a range check on the
     value.

WIDGET METHODS
==============

*$numentry*->*incdec*(*increment*)
     Increment the value of the entry widget by the specified increment. If
     increment is 0, then perform a range check.

CAVEATS
=======

-textvariable
     *-textvariable* should only be used to read out the current value in
     the *NumEntry*.

     Values set via *-textvariable* are not valided. Therefore it's
     possible to insert, e.g., 'abc', into the *NumEntry*.

SEE ALSO
========

   `Tk::NumEntry|Tk::NumEntry' in this node `Tk::Entry|Tk::Entry' in this
node

HISTORY
=======

   The code was extracted from *Tk::NumEntry* and slightly modified by
Achim Bohnet <ach@mpe.mpg.de>.  *Tk::NumEntry*'s author is Graham Barr
<gbarr@pobox.com>.

   Current maintainer is Slaven Rezic <eserte@cs.tu-berlin.de>.

COPYRIGHT
=========

   Copyright (c) 1997-1998 Graham Barr. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Tk composite widget Obj editor
******************************

NAME
====

   Tk::ObjEditor - Tk composite widget Obj editor

SYNOPSIS
========

     use Tk::ObjEditor;

     my $editor = $mw->ObjEditor( caller => $object,
                                   direct => [1|0],
                                   [title=>"windows"]) -> pack ;

DESCRIPTION
===========

   This widget provides a GUI to edit the attributes of an object or the
elements of a simple hash or array.

   The editor is a Tk/ObjScanner, with additional
function to edit data.

   When the user double clicks (with left button) on an item, the value of
the item will be displayed in the HList.

   If the value is a scalar, the scalar will be displayed in the text
window.  (Which is handy if the value is a multi-line string)

   Use the right button of the mouse of an element to modify its value.
Depending on the context, you will also be able to delete the element or
to add a sub-element.

   This may be not clear. If yes, I think that trying this widget will be
much clearer than any explanation I can write. So run the Tk widget demo
and you'll find the Obj editor demo in the "User Contributed
Demonstration" section.

Direct or undirect edit
=======================

   As the constructor will pass a reference to the data structure to be
edited, the data can be edited :

not directly
     In this case, the data structure is cloned. The widget will edit the
     cloned version of the data structure. This enable the user to cancel
     the edition. This means that any reference to the internals of old
     data structure will stay on the old datastructure and will not be
     aware of the new values entered with this widget.

directly
     In this case, the data structure is not cloned. The edition is
     performed on the passed reference. Any reference to the internals of
     old data structure will be updated on-line. The drawback is that the
     user cannot cancel (or undo) the edition.

Constructor parameters
======================

   * caller: The ref of the object or hash or array to edit (mandatory).

   * title: the title of the menu created by the editor (optionnal)

   * direct: Set to 1 if you want to perform direct edition.

CAVEATS
=======

   Like Tk/ObjScanner, ObjEditor does not detect
recursive data structures. It will just keep on displaying the tree until
the user gets tired of clicking on the HList items.

AUTHOR
======

   Dominique Dumont, Guillaume Degremont.

   Copyright (c) 1997-2001 Dominique Dumont, Guillaume Degremont. All
rights reserved.  This program is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

SEE ALSO
========

   perl(1), see Tk, Tk/HList, Tk/ObjScanner,

Tk composite widget obj editor popup dialog
*******************************************

NAME
====

   Tk::ObjEditorDialog - Tk composite widget obj editor popup dialog

SYNOPSIS
========

     use Tk::ObjEditorDialog;

     my $editor = $mw->ObjEditorDialog( caller => $object,
                                         direct => [1|0],
                                         [title=>"windows"]) ;

     $editor -> Show;

DESCRIPTION
===========

   This widget is a `ObjEditor' in this node within a `DialogBox' in this
node widget. I.e. it will appear in its own toplevel window when you
invoke the Show() method like the FileDialog widget.

Constructor parameters
======================

   * caller: The ref of the object or hash or array to edit (mandatory).

   * title: the title of the menu created by the editor (optionnal)

   * direct: Set to 1 if you want to perform direct edition.

Method
======

Show(grab)
----------

   As in Tk/DialogBox, this method displays the
dialog box, until user invokes one of the buttons in the bottom frame. If
the grab type is specified in grab, then Show uses that grab; otherwise it
uses a local grab. Returns the name of the button invoked.

CAVEATS
=======

   Like Tk/ObjScanner, ObjEditor does not detect
recursive data structures. It will just keep on displaying the tree until
the user gets tired of clicking on the HList items.

AUTHOR
======

   Dominique Dumont.

   Copyright (c) 2001 Dominique Dumont. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   perl(1), see Tk, Tk/HList, Tk/ObjScanner,
see Tk/ObjEditor, Tk/DialogBox,

Tk data scanner
***************

NAME
====

   Tk::ObjScanner - Tk data scanner

SYNOPSIS
========

     use Tk::ObjScanner;

     my $scanner = $mw->ObjScanner( caller => $object,
                                    title=>"windows") -> pack ;

     my $mw -> ObjScanner
     (
      caller 		    => $object,
      title 		    => 'demo setting the scanner options',
      background 	    => 'white',
      selectbackground => 'beige',
      foldImage 		=> $mw->Photo(-file => Tk->findINC('folder.xpm')),
      openImage 		=> $mw->Photo(-file => Tk->findINC('openfolder.xpm')),
      itemImage 		=> $mw->Photo(-file => Tk->findINC('textfile.xpm')),
     )
     -> pack(expand => 1, fill => 'both') ;

DESCRIPTION
===========

   The scanner provides a GUI to scan the attributes of an object. It can
also be used to scan the elements of a hash or an array.

   The scanner is a composite widget made of a Tk/HList,
and a text window (actually a `TK::ROText' in this node). This widget acts
as a scanner to the object (or hash ref) passed with the 'caller'
parameter. The scanner will retrieve all keys of the hash/object and
insert them in the HList.

   When the user double clicks on a key, the corresponding value will be
added in the HList.

   If the value is a scalar, the scalar will be displayed in the text
window.  (Which is handy if the value is a multi-line string)

Constructor parameters
======================

   * caller: The ref of the object or hash or array to scan (mandatory).

   * title: the title of the menu created by the scanner (optional)

   * destroyable: If set, a menu entry will allow the user to destroy the
     scanner widget. (optional, default 1) . You may want to set this
     parameter to 0 if the destroy can be managed by a higher level object.

   * background: the background color for subwidgets (optional)

   * selectbackground: the select background color for HList (optional)

   * itemImage: the image for a scalar item (optional, default 'file.xbm')

   * foldImage: the image for a composite item (array or hash) when closed
     (optional, default 'folder.xbm')

   * openImage: the image for a composite item (array or hash) when open
     (optional, default 'openfolder.xbm')

WIDGET-SPECIFIC METHODS
=======================

updateListBox
-------------

   Update the keys of the listbox. This method may be handy if the scanned
object wants to update the listbox of the scanner when the scanned object
gets new attributes.

CAVEATS
=======

   The name of the widget is misleading as any data (not only object) may
be scanned. This widget is in fact a DataScanner.

   ObjScanner may fail if an object involves a lot of internal perl magic.
In this case, I'd be glad to hear about and I'll try to fix the problem.

   ObjScanner does not detect recursive data structures. It will just keep
on displaying the tree until the user gets tired of clicking on the HList
items.

   There's no sure way to detect if a reference is a pseudo-hash or not.
When a reference is believed to be a pseudo-hash, ObjScanner will display
the content of the reference like a hash. If the reference is should not
be displayed like a pseudo-hash, you can turn off the pseudo-hash view
with the check button on the top right of the widget.

THANKS
======

   To Rudi Farkas for all the improvements provided to ObjScanner.

   To Slaven Rezic for the propotype code of the pseudo-hash viewer.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1997-2001 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1), Tk(3), Tk::HList(3)

Interface to OpenLook properties of toplevel windows.
*****************************************************

NAME
====

   Tk::OlWm - Interface to OpenLook properties of toplevel windows.

     use Tk::OlWm;

     $toplevel->OL_DECOR(
                          CLOSE  => flag,
                          FOOTER => flag,
                          HEADER => flag,
                          RESIZE => flag,
                          PIN => flag,
                          ICON_NAME => flag,
                        );

     $toplevel->OL_WIN_BUSY( flag );

     $toplevel->OL_PIN_STATE( flag );

DESCRIPTION
===========

   A simple perl-only module that adds a few methods to `Tk::Wm|Tk::Wm' in
this node class.  These methods manipulate properties of the
`$toplevel|Tk::Toplevel' in this node to communicate with an OpenLook
window manager, e.g. Sun's `olwm' or `olvwm'.

   In the synopsis above flag is a "boolean" value - i.e. an integer with
0 meaning false and other values meaning true.

   All the *name => flag* pairs are optional.

STATUS
======

   Works for me, it is in 'Contrib' because I cannot support something
which has been developed just by dumping properties of Sun applications
and guessing.

AUTHOR
======

   Nick Ing-Simmons <nik@tiuk.ti.com>

Let the user select one of some predefined options values
*********************************************************

NAME
====

   Tk::Optionmenu - Let the user select one of some predefined options
values

SYNOPSIS
========

     use Optionmenu;

     $opt = $w->Optionmenu(
     			-options => REFERENCE_to_OPTIONLIST,
     			-command => CALLBACK,
     			-variable => SCALAR_REF,
     			);

     $opt->addOptions( OPTIONLIST );

     # OPTION LIST is
     #   a)  $val1, $val2, $val3,...
     #   b)  [ $lab1=>$val1], [$lab2=>val2], ... ]
     #   c)  combination of a) and b), e.g.,
     #       val1, [$lab2=>val2], val3, val4, [...], ...

DESCRIPTION
===========

   The *Optionmenu* widget allows the user chose between a given set of
options.

   If the user should be able to change the available option have a look
at Tk/BrowseEntry.

OPTIONS
=======

-options
     (Re)sets the list of options presented.

-command
     Defines the `callback|Tk::callbacks' in this node that is invokes
     when a new option is selected.

-variable
     Reference to a scalar that contains the current value of the selected
     option.

METHODS
=======

addOptions
     Adds OPTION_LIST to the already available options.

EXAMPLE
=======

     use Tk;
     my $mw = MainWindow->new();

     my $var;
     my $opt = $mw->Optionmenu(
                 -options => [qw(jan feb mar apr)],
                 -command => sub { print "got: ", shift, "\n" },
     		-variable => \$var,
                 )->pack;

     $opt->addOptions([may=>5],[jun=>6],[jul=>7],[aug=>8]);

     $mw->Label(-textvariable=>\$var, -relief=>'groove')->pack;
     $mw->Button(-text=>'Exit', -command=>sub{$mw->destroy})->pack;

     MainLoop;

SEE ALSO
========

   See Tk/Menubutton, Tk/BrowseEntry,

PNG loader for Tk::Photo
************************

NAME
====

   Tk::PNG - PNG loader for Tk::Photo

SYNOPSIS
========

     use Tk;
     use Tk::PNG;

     my $image = $widget->Photo('-format' => 'png', -file => 'something.png');

DESCRIPTION
===========

   This is an extension for Tk800.* which supplies PNG format loader for
Photo image type.

AUTHOR
======

   Nick Ing-Simmons <nick@ni-s.u-net.com>

A window panner
***************

NAME
====

   Tk::Pane - A window panner

     use Tk::Pane;

     $pane = $mw->Scrolled(Pane, Name => 'fred',
     	-scrollbars => 'soe',
     	-sticky => 'we',
     	-gridded => 'y'
     );

     $pane->Frame;

     $pane->pack;

DESCRIPTION
===========

   *Tk::Pane* provides a scrollable frame widget. Once created it can be
treated as a frame, except it is scrollable.

OPTIONS
=======

*-gridded* => *direction*
     Specifies if the top and left edges of the pane should snap to a grid
     column. This option is only useful if the widgets in the pane are
     managed by the grid geometry manager. Possible values are x, y and
     *xy*.

*-sticky* => style
     If Pane is larger than its requested dimensions, this option may be
     used to position (or stretch) the slave within its cavity. Style is a
     string that contains zero or more of the characters n, s, e or w. The
     string can optionally contains spaces or commas, but they are
     ignored. Each letter refers to a side (north, south, east, or west)
     that the slave will "stick" to. If both n and s (or e and w) are
     specified, the slave will be stretched to fill the entire height (or
     width) of its cavity.

METHODS
=======

*$pane*->see($widget ?,options?)
     Adjusts the view so that $widget is visable. Aditional parameters in
     *options-value* pairs can be passed, each *option-value* pair must be
     one of the following

    *-anchor* => anchor
          Specifies how to make the widget visable. If not given then as
          much of the widget as possible is made visable.

          Possible values are n, s, w, e, *nw*, ne, sw and *se*.  This
          will cause an edge on the widget to be aligned with the
          corresponding edge on the pane. for example *nw* will cause the
          top left of the widget to be placed at the top left of the pane.
          s will cause the bottom of the widget to be placed at the bottom
          of the pane, and as much of the widget as possible made visable
          in the x direction.

*$pane*->*xview*
     Returns a list containing two elements, both of which are real
     fractions between 0 and 1. The first element gives the position of
     the left of the window, relative to the Pane as a whole (0.5 means it
     is halfway through the Pane, for example). The second element gives
     the position of the right of the window, relative to the Pane as a
     whole.

*$pane*->*xview*($widget)
     Adjusts the view in the window so that widget is displayed at the
     left of the window.

*$pane*->*xview*(*moveto* => *fraction*)
     Adjusts the view in the window so that *fraction* of the total width
     of the Pane is off-screen to the left. fraction must be a fraction
     between 0 and 1.

*$pane*->*xview*(scroll => number, *what*)
     This command shifts the view in the window left or right according to
     number and *what*. Number must be an integer. What must be either
     *units* or *pages* or an abbreviation of one of these. If *what* is
     *units*, the view adjusts left or right by number*10 screen units on
     the display; if it is *pages* then the view adjusts by number
     screenfuls. If number is negative then widgets farther to the left
     become visible; if it is positive then widgets farther to the right
     become visible.

*$pane*->*yview*
     Returns a list containing two elements, both of which are real
     fractions between 0 and 1. The first element gives the position of
     the top of the window, relative to the Pane as a whole (0.5 means it
     is halfway through the Pane, for example). The second element gives
     the position of the bottom of the window, relative to the Pane as a
     whole.

*$pane*->*yview*($widget)
     Adjusts the view in the window so that widget is displayed at the top
     of the window.

*$pane*->*yview*(*moveto* => *fraction*)
     Adjusts the view in the window so that *fraction* of the total width
     of the Pane is off-screen to the top. fraction must be a fraction
     between 0 and 1.

*$pane*->*yview*(scroll => number, *what*)
     This command shifts the view in the window up or down according to
     number and *what*. Number must be an integer. What must be either
     *units* or *pages* or an abbreviation of one of these. If *what* is
     *units*, the view adjusts up or down by number*10 screen units on the
     display; if it is *pages* then the view adjusts by number screenfuls.
     If number is negative then widgets farther up become visible; if it
     is positive then widgets farther down become visible.

AUTHOR
======

   Graham Barr <`gbarr@pobox.com'>

COPYRIGHT
=========

   Copyright (c) 1997-1998 Graham Barr. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

A collapsable frame with title.
*******************************

NAME
====

   Tk::Panel - A collapsable frame with title.

SYNOPSIS
========

     use Tk;
     use Tk::Panel;

     $m = $parent->Tk::Panel(
     		-relief	=> <relief of inner boundary>,
     		-border	=> <border size of inner boundary>
     		-text	=> <text of title>
     		-toggle	=> <0|1>
     		-state	=> <normal|active|disabled>
     		-show	=> 1|0
     	);

     $m->Widget()->pack();

DESCRIPTION
===========

     This is a frame type object with a boundary and a title.
     The title can include a checkbox allowing the contents of
     the panel to be collapsed.

     Further widgets can be created inside the Panel.

OPTIONS
=======

-relief => <relief of inner boundary>
-------------------------------------

     Sets the relief of inner boundary. The default is 'raised'.

-border => <border size of inner boundary>
------------------------------------------

     Sets the relief of inner boundary.

-text => "title text"
---------------------

     Sets the title of the Panel.

-toggle => 1|0
--------------

     This sets if the Panel can be collapsed via the title.

-state => <normal|active|disabled>
----------------------------------

     This sets the state of the check button version of the title.

-show => 1|0
------------

     This sets if the Panel is expanded or collapsed.

Parse perl's pod files.
***********************

NAME
====

   Pod::Parse - Parse perl's pod files.

SYNOPSIS
========

   *THIS TK SNAPSHOT SHOULD BE REPLACED BY A CPAN MODULE*

DESCRIPTION
===========

   A module designed to simplify the job of parsing and formatting "pods",
the documentation format used by perl5. This consists of several different
functions to present and modify predigested pod files.

GUESSES
=======

   This is a work in progress, so I may have some stuff wrong, perhaps
badly.  Some of my more reaching guesses:

   * An =index paragraph should be split into lines, and each line placed
     inside an `X' formatting command which is then preprended to the next
     paragraph, like this:

          =index foo
          foo2
          foo3
          foo2!subfoo

          Foo!

          Will become:

          X<foo>X<foo2>X<foo3>X<foo2!subfoo>Foo!

   * A related change: that an `X' command is to be used for indexing
     data. This implies that all formatters need to at least ignore the
     `X' command.

   * Inside an =command, no special significance is to be placed on the
     first line of the argument. Thus the following two lines should be
     parsed identically:

          =item 1. ABC

          =item 1.
          ABC

     Note that neither of these are identical to this:

          =item 1.

          ABC

     which puts the "ABC" in a separate paragraph.

   * I actually violate this rule twice: in parsing =index commands, and in
     passing through the =pragma commands. I hope this make sense.

   * I added the =comment command, which simply ignores the next paragraph

   * I also added =pragma, which also ignores the next paragraph, but this
     time it gives the formatter a chance at doing something sinister with
     it.

POD CONVENTIONS
===============

   This module has two goals: first, to simplify the usage of the pod
format, and secondly the codification of the pod format. While perlpod
contains some information, it hardly gives the entire story. Here I
present "the rules", or at least the rules as far as I've managed to work
them out.

Paragraphs: The basic element
     The fundamental "atom" of a pod file is the paragraph, where a
     paragraph is defined as the text up to the next completely blank line
     ("\n\n"). Any pod parser will read in paragraphs sequentially,
     deciding what do to with each based solely on the current state and
     on the text at the _beginning_ of the paragraph.

Commands: The method of communication
     A paragraph that starts with the `=' symbol is assumed to be a
     special command.  All of the alphanumeric characters directly after
     the `=' are assumed to be part of the name of the command, up to the
     first whitespace. Anything past that whitespace is considered "the
     arugment", and the argument continues up till the end of the
     paragraph, regardless of newlines or other whitespace.

Text: Commands that aren't Commands
     A paragraph that doesn't start with `=' is treated as either of two
     types of text. If it starts with a space or tab, it is considered a
     verbatim paragraph, which will be printed out... verbatim. No
     formatting changes whatsover may be done. (Actually, this isn't quite
     true, but I'll get back to that at a later date.)

     A paragraph that doesn't start with whitespace or `=' is assumed to
     consist of formmated text that can be molded as the formatter sees
     fit. Reformatting to fit margins, whatever, it's fair game. These
     paragraphs also can contain a number of different formatting codes,
     which verbatim paragraphs can't. These formatting codes are covered
     later.

=cut: The uncommand
     There is one command that needs special mention: =cut. Anything after
     a paragraph starting with =cut is simply ignored by the formatter. In
     addition, any text before a valid command is equally ignored. Any
     valid `=' command will reenable formating. This fact is used to great
     benefit by Perl, which is glad to ignore anything between an `='
     command and `=cut', so you can embed a pod document right inside a
     perl program, and neither will bother the other.

Reference to paragraph commands

    =cut
          Ignore anything till the next paragraph starting with `='.

    =head1
          A top-level heading. Anything after the command (either on the
          same line or on further lines) is included in the heading, up
          until the end of the paragraph.

    =head2
          Secondary heading. Same as =head1, but different. No, there
          isn't a head3, head4, etc.

    =over [N]
          Start a list. The N is the number of characters to indent by.
          Not all formatters will listen to this, though. A good number to
          use is 4.

          While =over sounds like it should just be indentation, it's more
          complex then that. It actually starts a nested environment,
          specifically for the use of =item's. As this command recurses
          properly, you can use more then one, you just have to make sure
          they are closed off properly by =back commands.

    =back
          Ends the last =over block. Resets the indentation to whatever it
          was previously. Closes off the list of =item's.

    =item
          The point behind =over and =back. This command should only be
          used between them. The argument supplied should be consistent
          (within a list) to one of three types: enumeration, itemization,
          or description. To exemplify:

          An itemized list

               =over 4

               =item *

               A bulleted item

               =item *

               Another bulleted item

               =back

               An enumerated list

               =over 4

               =item 1.

               First item.

               =item 2.

               Second item.

               =back

               A described list

               =over 4

               =item Item #1

               First item

               =item Item #2 (which isn't really like #1, but is the second).

               Second item

               =back

               If you aren't consistent about the arguments to =item, Pod::Parse will
               complain.

    =comment
          Ignore this paragraph

    =pragma
          Ignore this paragraph, as well, unless you know what you are
          doing.

    =index
          Undecided at this time, but probably magic involving X<>.

Reference to formatting directives

    ...
          Format text inside the brackets as bold.

    ...
          Format text inside the brackets as italics.

          Replace with a zero-width character. You'll probably figure out
          some uses for this.

    And yet more that I haven't described yet...
USAGE
=====

Parse
-----

   This function takes a list of files as an argument. If no argument is
given, it defaults to the contents of @ARGV. Parse then reads through each
file and returns the data as a list. Each element of this list will be a
nested list containing data from a paragraph of the pod file. Elements
pertaining to "=over" paragraphs will themselves contain the nested
entries for all of the paragraphs within that list. Thus, it's easier to
parse the output of Parse using a recursive parses. (Um, did that parse?)

   It is *highly* recommended that you use the output of Simplify, not
Parse, as it's simpler.

   The output will consist of a list, where each element in the list
matches one of these prototypes:

[0,0,0,0,$filename]
     This is produced at the beginning of each file parsed, where
     $filename is the name of that file.

[-1,0,0,0,$filename]
     End of same.

[1,$line,$pos,0,$verbatim]
     This is produced for each paragraph of verbatim text. $verbatim is
     the text, $line is the line offset of the paragraph within the file,
     and $pos is the byte offset. (In all of the following elements, $pos
     and $line have identical meanings, so I'll skip explaining them each
     time.)

[2,$line,$pos,$level,$heading]
     Producded by a =head1 or =head2 command. $level is either 1 or 2, and
     $heading is the argument.

[3,$line,$pos,0,$item]
     $item is the argument from an =item paragraph.

[4,$line,$pos,0,$index]
     $index is the argument from an =index paragraph.

[6,$line,$pos,0,$text]
     Normal formatted text paragraph. $text is the text.

[7,$line,$pos,0,$pragma]
     $pragma is the argument from a =pragma paragraph.

[8,$line,$pos,$indentation,$type,...]
     This item is produced for each matching =over/=back pair.
     $indentation is the argument to =over, $type is 1 if the embedded
     =item's are bulleted, 2 if they are enumerated, 3 if they are text,
     and 0 if there are no items.

     The "..." indicates an unlimited number of further elements which are
     themselves nested arrays in exactly the format being described. In
     other words, a list item includes all the paragraphs inside the list
     inside itself. (Clear? No? Nevermind.)

[9,$line,$pos,0,$cut]
     $cut contains the text from a =cut paragraph. You shouldn't need to
     use this, but I _suppose_ it might be necessary to do special breaks
     on a cut. I doubt it though. This one is "depreciated", as Larry put
     it. Or perhaps disappreciated.

Simplify
--------

   This procedure takes as it's input the convoluted output from Parse(),
and outputs a much simpler array consisting of pairs of commands and
arguments, designed to be easy (easier?) to parse in your pod formatting
code.

   It is used very simply by saying something like:

     @Pod = Simplify(Parse());

     while($cmd = shift @Pod) { $arg = shift @Pod;
     	#...
     }

   Where #... is the code that responds to any of the commands from the
following list. Note that you are welcome to ignore any of the commands
that you want to. Many contain duplicate information, or at least
information that will go unused. A formatted based on this data can be
quite simple indeed. (See pod2text for entirely too simple an example.)

Reference to Simplify commands
------------------------------

"filename"
     The argument contains the name of the pod file that is being parsed.
     These will be present at the start of each file. You should open an
     output file, output headers, etc., based on this, and not when you
     start parsing.

"endfile"
     The end of the file. Each file will be ended before the next one
     begins, and after all files are done with. You can do end processing
     here. The argument is the same name as in "filename".

"setline"
     This gives you a chance to record the "current" input line, probably
     for debugging purposes. In this case, "current" means that the next
     command you see that was derived from an input paragraph will have
     start at the arguments line in the file.

"setloc"
     Same as setline, but the byte offset in the input, instead of the
     line offset.

"pragma"
     The argument contains the text of a pragma command.

"text"
     The argument contains a paragraph of formatted text.

"verbatim"
     The argument contains a paragraph of verbatim text.

"cut"
     A =cut command was hit. You shouldn't really need to listen for this
     one.

"index"
     The argument contains an =index paragraph. (Note: Current =index
     commands are not fed through, but turned into X<> commands.)

"head1"

"head2"
     The argument contains the argument from a header command.

"setindent"
     If you are tracking indentation, use the argument to set the
     indentation level.

"listbegin"
     Start a list environment. The argument is the type of list (1,2,3 or
     0).

"listend"
     Ends a list environment. Same argument as listbegin.

"listtype"
     The argument is the type of list. You can just record the argument
     when you see one of these, instead of paying attention to listbegin &
     listend.

"over"
     The argument is the indentation. It's probably better to listen to the
     "list..." commands.

"back"
     Ends an "over" list. The argument is the original indentation.

"item"
     The argument is the text of the =item command.

   Note that all of these various commands you've seen are syncronized
properly so you don't have to pay attention to all at once, but they are
all output for your benefit. Consider the following example:

     listtype 2
     listbegin 2
     setindent 4
     over 4
     item 1.
     text Item #1
     item 2.
     text Item #2
     setindent 0
     listend 2
     back 0
     listtype 0

     =head2 Normalize

   This command is normally invoked by Parse, so you shouldn't need to deal
with it. It just cleans up text a little, turning spare '<', '>', and '&'
characters into HTML escapes (<, etc.) as well as generating warnings for
some pod formatting mistakes.

Normalize2
----------

   A little more aggresive formating based on heuristics. Not applied by
default, as it might confuse your own heuristics.

%Escapes
--------

   This hash is exported from Pod::Parse, and contains default ASCII
translations for some common HTML escape sequences. You might like to use
this as a basis for an %HTML_Escapes array in your own formatter.

Full-color images
*****************

NAME
====

   Tk::Photo - Full-color images

       $widget->Photo(?name??, options?)

DESCRIPTION
===========

   A photo is an `image|Tk::Image' in this node whose pixels can display
any color or be transparent.  A photo image is stored internally in full
color (32 bits per pixel), and is displayed using dithering if necessary.
Image data for a photo image can be obtained from a file or a string, or it
can be supplied from C code through a procedural interface.  At present,
only GIF and PPM/PGM formats are supported, but an interface exists to
allow additional image file formats to be added easily.  A photo image is
transparent in regions where no image data has been supplied.

CREATING PHOTOS
===============

   Photos are created using the Photo method.  Photo supports the
following options:

*-data* => string
     Specifies the contents of the image as a string.  The format of the
     string must be one of those for which there is an image file format
     handler that will accept string data.  If both the *-data* and
     *-file* options are specified, the *-file* option takes precedence.

*-format* => *format-name*
     Specifies the name of the file format for the data specified with the
     *-data* or *-file* option.

*-file* => name
     name gives the name of a file that is to be read to supply data for
     the photo image.  The file format must be one of those for which
     there is an image file format handler that can read data.

*-gamma* => value
     Specifies that the colors allocated for displaying this image in a
     window should be corrected for a non-linear display with the specified
     gamma exponent value.  (The intensity produced by most CRT displays
     is a power function of the input value, to a good approximation;
     gamma is the exponent and is typically around 2).  The value
     specified must be greater than zero.  The default value is one (no
     correction).  In general, values greater than one will make the image
     lighter, and values less than one will make it darker.

*-height* => number
     Specifies the height of the image, in pixels.  This option is useful
     primarily in situations where the user wishes to build up the contents
     of the image piece by piece.  A value of zero (the default) allows the
     image to expand or shrink vertically to fit the data stored in it.

*-palette* => *palette-spec*
     Specifies the resolution of the color cube to be allocated for
     displaying this image, and thus the number of colors used from the
     colormaps of the windows where it is displayed.  The *palette-spec*
     string may be either a single decimal number, specifying the number
     of shades of gray to use, or three decimal numbers separated by
     slashes (/), specifying the number of shades of red, green and blue
     to use, respectively.  If the first form (a single number) is used,
     the image will be displayed in monochrome (i.e., grayscale).

*-width* => number
     Specifies the width of the image, in pixels.    This option is useful
     primarily in situations where the user wishes to build up the contents
     of the image piece by piece.  A value of zero (the default) allows the
     image to expand or shrink horizontally to fit the data stored in it.

IMAGE METHODS
=============

   When a photo image is created, Tk also creates a new object.  This
object supports the configure and cget methods described in
Tk/options, which can be used to enquire and modify the
options described above.

   Those options that write data to the image generally expand the size of
the image, if necessary, to accommodate the data written to the image,
unless the user has specified non-zero values for the *-width* and/or
*-height* configuration options, in which case the width and/or height,
respectively, of the image will not be changed.

   The following addition methods are available for photo images:

*$image*->*blank*
     Blank the image; that is, set the entire image to have no data, so it
     will be displayed as transparent, and the background of whatever
     window it is displayed in will show through.

*$image*->copy(*sourceImage* ?,*option value(s) ...*?)
     Copies a region from the image called *sourceImage* (which must be a
     photo image) to the image called *$image*, possibly with pixel
     zooming and/or subsampling.  If no options are specified, this method
     copies the whole of *sourceImage* into *$image*, starting at
     coordinates (0,0) in *$image*.  The following options may be
     specified:

    *-from* => *x1 y1 ?x2 y2?*
          Specifies a rectangular sub-region of the source image to be
          copied.  (*x1,y1*) and (*x2,y2*) specify diagonally opposite
          corners of the rectangle.  If x2 and *y2* are not specified, the
          default value is the bottom-right corner of the source image.
          The pixels copied will include the left and top edges of the
          specified rectangle but not the bottom or right edges.  If the
          *-from* option is not given, the default is the whole source
          image.

    *-to* => *x1 y1 ?x2 y2?*
          Specifies a rectangular sub-region of the destination image to be
          affected.  (*x1,y1*) and (*x2,y2*) specify diagonally opposite
          corners of the rectangle.  If x2 and *y2* are not specified, the
          default value is (*x1,y1*) plus the size of the source region
          (after subsampling and zooming, if specified).  If x2 and *y2*
          are specified, the source region will be replicated if necessary
          to fill the destination region in a tiled fashion.

    *-shrink*
          Specifies that the size of the destination image should be
          reduced, if necessary, so that the region being copied into is
          at the bottom-right corner of the image.  This option will not
          affect the width or height of the image if the user has
          specified a non-zero value for the *-width* or *-height*
          configuration option, respectively.

    *-zoom* => *x y*
          Specifies that the source region should be magnified by a factor
          of x in the X direction and y in the Y direction.  If y is not
          given, the default value is the same as x.  With this option,
          each pixel in the source image will be expanded into a block of
          x x y pixels in the destination image, all the same color.  x
          and y must be greater than 0.

    *-subsample* => *x y*
          Specifies that the source image should be reduced in size by
          using only every xth pixel in the X direction and yth pixel in
          the Y direction.  Negative values will cause the image to be
          flipped about the Y or X axes, respectively.  If y is not given,
          the default value is the same as x.

*$image*->data(?*option value(s), ...*?)
     returns image data in the form of a string.  The following options
     may be specified:

    *-background* => * color*
          If the color is specified, the data will not contain any
          transparency information. In all transparent pixels the color
          will be replaced by the specified color.

    *-format* => *format-name*
          Specifies the name of the image file format handler to be used to
          convert the data.  Specifically, this method searches for the
          first handler whose name matches a initial substring of
          *format-name* and which has the capability to write an string.
          If this option is not given, the data is returned in the default
          format as accepted by *$image*->put.

    *-from* => *x1 y1 ?x2 y2?*
          Specifies a rectangular region of *$image* to be written to the
          string.  If only x1 and *y1* are specified, the region extends
          from *(x1,y1)* to the bottom-right corner of *$image*.  If all
          four coordinates are given, they specify diagonally opposite
          corners of the rectangular region.  The default, if this option
          is not given, is the whole image.

*-grayscale*
     If this options is specified, the data will not contain color
     information. All pixel data will be transformed into grayscale.

*$image*->get(*x,y*)
     Returns the color of the pixel at coordinates (x,y) in the image as a
     list of three integers between 0 and 255, representing the red, green
     and blue components respectively.

*$image*->put(data ?,*-format*=>*format-name*? ?,*-to*=>* x1 y1 ?x2 y2?*?)
     Sets pixels in * imageName* to the data specified in data. This
     command first searches the list of image file format handlers for a
     handler that can interpret the data in data, and then reads the image
     in filename into imageName (the destination image). The following
     options may be specified:

    *-format **format-name*
          Specifies the format of the image data in data.  Specifically,
          only image file format handlers whose names begin with
          *format-name* will be used while searching for an image data
          format handler to read the data. Otherwise data is used to form
          a two-dimensional array of pixels that are then copied into the
          *$image*. data is structured then as a list of horizontal rows,
          from top to bottom, each of which is a list of colors, listed
          from left to right.  Each color may be specified by name (e.g.,
          blue) or in hexadecimal form (e.g., #2376af).

    *-from **x1 y1 x2 y2*
          Specifies a rectangular sub-region of the image file data to be
          returned. If only x1 and *y1* are specified, the region extends
          from (*x1,y1*) to the bottom-right corner of the image in the
          image file.  If all four coordinates are specified, they specify
          diagonally opposite corners or the region. The default, if this
          option is not specified, is the whole of the image.

    *-shrink*
          If this option, the size of imageName will be reduced, if
          necessary, so that the region into which the image file data are
          read is at the bottom-right corner of the imageName.  This option
          will not affect the width or height of the image if the user has
          specified a non-zero value for the *-width* or *-height*
          configuration option, respectively.

    *-to **x y*
          Specifies the coordinates of the top-left corner of the region of
          imageName into which data from filename are to be read.  The
          default is (0,0).

*$image*->read(filename ?,*option value(s), ...*?)
     Reads image data from the file named filename into the image.  This
     method first searches the list of image file format handlers for a
     handler that can interpret the data in filename, and then reads the
     image in filename into *$image* (the destination image).  The
     following options may be specified:

    *-format* => *format-name*
          Specifies the format of the image data in filename.
          Specifically, only image file format handlers whose names begin
          with *format-name* will be used while searching for an image data
          format handler to read the data.

    *-from* => *x1 y1 ?x2 y2?*
          Specifies a rectangular sub-region of the image file data to be
          copied to the destination image.  If only x1 and *y1* are
          specified, the region extends from (*x1,y1*) to the bottom-right
          corner of the image in the image file.  If all four coordinates
          are specified, they specify diagonally opposite corners or the
          region.  The default, if this option is not specified, is the
          whole of the image in the image file.

    *-shrink*
          If this option, the size of *$image* will be reduced, if
          necessary, so that the region into which the image file data are
          read is at the bottom-right corner of the *$image*.  This option
          will not affect the width or height of the image if the user has
          specified a non-zero value for the *-width* or *-height*
          configuration option, respectively.

    *-to* => *x y*
          Specifies the coordinates of the top-left corner of the region of
          *$image* into which data from filename are to be read.  The
          default is (0,0).

*$image*->*redither*
     The dithering algorithm used in displaying photo images propagates
     quantization errors from one pixel to its neighbors.  If the image
     data for *$image* is supplied in pieces, the dithered image may not
     be exactly correct.  Normally the difference is not noticeable, but
     if it is a problem, this method can be used to recalculate the
     dithered image in each window where the image is displayed.

*$image*->write(filename ?,*option value(s), ...*?)
     Writes image data from *$image* to a file named filename.  The
     following options may be specified:

    *-background** color*
          If the color is specified, the data will not contain any
          transparency information. In all transparent pixels the color
          will be replaced by the specified color.

    *-format* => *format-name*
          Specifies the name of the image file format handler to be used to
          write the data to the file.  Specifically, this subcommand
          searches for the first handler whose name matches a initial
          substring of *format-name* and which has the capability to write
          an image file.  If this option is not given, this subcommand
          uses the first handler that has the capability to write an image
          file.

    *-from* => *x1 y1 ?x2 y2?*
          Specifies a rectangular region of *$image* to be written to the
          image file.  If only x1 and *y1* are specified, the region
          extends from *(x1,y1)* to the bottom-right corner of *$image*.
          If all four coordinates are given, they specify diagonally
          opposite corners of the rectangular region.  The default, if
          this option is not given, is the whole image.

    *-grayscale*
          If this options is specified, the data will not contain color
          information. All pixel data will be transformed into grayscale.

IMAGE FORMATS
=============

   The photo image code is structured to allow handlers for additional
image file formats to be added easily.  The photo image code maintains a
list of these handlers.  Handlers are added to the list by registering
them with a call to *Tk_CreatePhotoImageFormat*.  The standard Tk
distribution comes with handlers for PPM/PGM and GIF formats, which are
automatically registered on initialization.

   When reading an image file or processing string data specified with the
*-data* configuration option, the photo image code invokes each handler in
turn until one is found that claims to be able to read the data in the
file or string.  Usually this will find the correct handler, but if it
doesn't, the user may give a format name with the *-format* option to
specify which handler to use.  In fact the photo image code will try those
handlers whose names begin with the string specified for the *-format*
option (the comparison is case-insensitive).  For example, if the user
specifies *-format gif*, then a handler named GIF87 or GIF89 may be
invoked, but a handler named JPEG may not (assuming that such handlers had
been registered).

   When writing image data to a file, the processing of the *-format*
option is slightly different: the string value given for the *-format*
option must begin with the complete name of the requested handler, and may
contain additional information following that, which the handler can use,
for example, to specify which variant to use of the formats supported by
the handler.

COLOR ALLOCATION
================

   When a photo image is displayed in a window, the photo image code
allocates colors to use to display the image and dithers the image, if
necessary, to display a reasonable approximation to the image using the
colors that are available.  The colors are allocated as a color cube, that
is, the number of colors allocated is the product of the number of shades
of red, green and blue.

   Normally, the number of colors allocated is chosen based on the depth
of the window.  For example, in an 8-bit PseudoColor window, the photo
image code will attempt to allocate seven shades of red, seven shades of
green and four shades of blue, for a total of 198 colors.  In a 1-bit
StaticGray (monochrome) window, it will allocate two colors, black and
white.  In a 24-bit DirectColor or TrueColor window, it will allocate 256
shades each of red, green and blue.  Fortunately, because of the way that
pixel values can be combined in DirectColor and TrueColor windows, this
only requires 256 colors to be allocated.  If not all of the colors can be
allocated, the photo image code reduces the number of shades of each
primary color and tries again.

   The user can exercise some control over the number of colors that a
photo image uses with the *-palette* configuration option.  If this option
is used, it specifies the maximum number of shades of each primary color
to try to allocate.  It can also be used to force the image to be
displayed in shades of gray, even on a color display, by giving a single
number rather than three numbers separated by slashes.

CREDITS
=======

   The photo image type was designed and implemented by Paul Mackerras,
based on his earlier photo widget and some suggestions from John
Ousterhout.

SEE ALSO
========

   `Tk::Bitmap|Tk::Bitmap' in this node `Tk::Image|Tk::Image' in this node
`Tk::Pixmap|Tk::Pixmap' in this node

KEYWORDS
========

   photo, image, color

Create color images from XPM files.
***********************************

NAME
====

   Tk::Pixmap - Create color images from XPM files.

       $widget->Pixmap?(name?,options?)?

DESCRIPTION
===========

   XPM is a popular X Window image file format for storing color icons.
The Pixmap image type can be used to create color images using XPM files.

   Pixmaps support the following options:

*-data* => string
     Specifies the contents of the source pixmap as a string.  The string
     must adhere to the XPM file format (e.g., as generated by the
     *pixmap(1)* program). If both the *-data* and *-file* options are
     specified, the *-data* option takes precedence.  Please note that the
     XPM file parsing code in the xpm library is somewhat fragile. The
     first line of the string must be "*/* XPM* */" or otherwise a
     segmatation fault will be caused.

*-file* => name
     name gives the name of a file whose contents define the source
     pixmap.  The file must adhere to the XPM file format (e.g., as
     generated by the *pixmap(1)* program).

IMAGE METHODS
=============

   When a pixmap image is created, Tk also creates a new object.  This
object supports the configure and cget methods described in
Tk/options, which can be used to enquire and modify the
options described above.

SEE ALSO
========

   `Tk::Image|Tk::Image' in this node

KEYWORDS
========

   pixmap, image, tix

POD browser toplevel widget
***************************

NAME
====

   Tk::Pod - POD browser toplevel widget

SYNOPSIS
========

     use Tk::Pod

     Tk::Pod->Dir(@dirs)			# add dirs to search path for POD

     $pod = $parent->Pod(
     		-file = > $name		# search and display POD for name
     		);

DESCRIPTION
===========

   Simple POD browser with hypertext capabilities in a Toplevel widget

SEE ALSO
========

   `Tk::Pod_usage|Tk::Pod_usage' in this node
`Tk::Pod::Text|Tk::Pod::Text' in this node `tkpod|tkpod' in this node
`perlpod|perlpod' in this node

AUTHOR
======

   Nick Ing-Simmons <`nick@ni-s.u-net.com'>

   Code currently maintained by Achim Bohnet <`ach@mpe.mpg.de'>.  Please
send bug reports to <`ptk@lists.stanford.edu'>.

   Copyright (c) 1997-1998 Nick Ing-Simmons.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Widget to access perlindex POD full text index
**********************************************

NAME
====

   Tk::Pod::Search - Widget to access perlindex POD full text index

     use Tk::Pod::Search;
     ...
     $widget = $parent->PodSearch( ... );
     ...
     $widget->configure( -search => WORDS_TO_SEARCH );

DESCRIPTION
===========

   GUI interface to the full POD text indexer *perlindex*.

OPTIONS
=======

Class: Search
Member: search
Option: -search
     Expects a list of words (or a whitespace seperated list).

Class: undef
Member: undef
Option: -command
     Defines a call back that is called when the use selects a POD file.
     It gets the full path name of the POD file as argument.

METHODS
=======

$widget->*method1**(...,?...?)*
SEE ALSO
========

   Tk::Pod::Text, tkpod, perlindex, Tk::Pod, Tk::Parse, Tk::Pod::Search_db

KEYWORDS
========

   widget, tk, pod, search, full text

AUTHOR
======

   Achim Bohnet <`ach@mpe.mpg.de'>

   Copyright (c) 1997-1998 Achim Bohnet. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

dirty OO wrapper for `perlindex''s search functionality
*******************************************************

NAME
====

   Tk::Pod::Search_db - dirty OO wrapper for `perlindex''s search
functionality

SYNOPSIS
========

     ** THIS IS ALPHA SOFTWARE everything may and should change **
     **   stuff here is more a scratch pad than docomentation!  **

     use Tk::Pod::Search_db;
     ...
     $idx = Tk::Pod::Search_db->new?(INDEXDIR)?;
     ...
     @hits = $idx->searchWords(WORD1,...); # @hits is a list of
                                              # relpath1,score1,...  where
                                              # score is increasing
     $prefix = $idx->prefix();

     @word = Tk::Pod::Search_db::normalize(STRING1,...);

DESCRIPTION
===========

   Module to search POD documentation.  Before you can use the module one
should create the indices with C<perlindex -index).

MISSING
=======

   Enable options like -maxhits (currently = 15).  Solve PREFIX
dependency.  Interface for @stop and @unknown also as methods return lists
for last searchWords call?

   Lots more ...

METHODS
=======

$idx = Tk::Pod::Search_db->new(INDEXDIR)
     Interface may change to support options like -maxhits

$idx->seachWords(WORD1?,...?)
     search for WORD(s). Return a list of

          relpath1, score1, relpath2, score2, ...

     or empty list if no match is found.

$pathprefix = $idx->pathprefix()
     The return path prefix and `$relpath' give together the full path
     name of the POD documentation.

          $fullpath = $patchprefix . '/' . $relpath

     Note: Should make it easy to use Tk::Pod::Search with perlindex but
     index specific prefix handling is a mess up to know.

SEE ALSO
========

   tkpod, perlindex perlpod, Tk::Pod::Search

AUTHORS
=======

   Achim Bohnet  <`ach@mpe.mpg.de'>

   Most of the code here is borrowed from `perlindex' in this node written
by Ulrich Pfeifer <`Ulrich.Pfeifer@de.uu.net'>.

   Copyright (c) 1997-1998 Achim Bohnet. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

POD browser widget
******************

NAME
====

   Tk::Pod::Text - POD browser widget

SYNOPSIS
========

     use Tk::Pod::Text;

     $pod = $parent->PodText(
     		-file		=> ?
     		-scrollbars	=> ?
     		);

     $file = $pod->cget('-path');   # ?? the name path is confusing :-(

DESCRIPTION
===========

   *Tk::Pod::Text* is a readonly text widget that can display POD
documentation.

SEE ALSO
========

   `Tk::More|Tk::More' in this node `Tk::Pod|Tk::Pod' in this node
`perlpod|perlpod' in this node `tkpod|tkpod' in this node
`perlindex|perlindex' in this node

KNOWN BUGS
==========

   See TODO files of Tk-Pod distribution

POD TO VERIFY *PodText* WIDGET
==============================

   For *PodText* see Tk/Pod/Text.

   A `fixed width' font.

   Text in *slant italics*.

   A <=for> paragraph is hidden between here

   A file: `/usr/local/bin/perl'.  A variable $a without markup.

   boofar is in S<>.

   German Umlaute:

auml: E<auml>,
Auml: E<Auml>,
ouml: E<ouml>,
Ouml: E<Ouml>,
Uuml: E<uuml>,
Uuml: E<Uuml>,
sz: E<szlig>.
   Pod with Umlaut: ExtUtils/MakeMaker, and
ExtUtils::MakeMaker.

   Details:  Perlpod (perl.info), or perl, perlfunc.

   Here some code in a as is paragraph

     use Tk;
     my $mw = MainWindow->new;
     ...
     MainLoop
     __END__

   Fonts: sanserif, fixed, bold, *italics*, normal, or file
`/path/to/a/file'

   Mixed Fonts: *bold-sanserif*, *`bold-fixed'*, **bold-italics**

   Other POD docu: Tk::Font, Tk::BrowseEntry

AUTHOR
======

   Nick Ing-Simmons <`nick@ni-s.u-net.com'>

   Code currently maintained by Achim Bohnet <`ach@mpe.mpg.de'>.  Please
send bug reports to <`ptk@lists.stanford.edu'>.

   Copyright (c) 1998 Nick Ing-Simmons.  All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

How to use the perl/Tk POD browser widget
*****************************************

NAME
====

   Tk::Pod_usage - How to use the perl/Tk POD browser widget

DESCRIPTION
===========

   To navigate through the documentation one could use

Hyperlinks
----------

   A *click* on a hyperlink display the corresponding documentation (if
there is any) in the same window.

   With <Button-2> the documentation is loaded into a new window
(<Shift-Button-1> works also for those with only a 2 button mouse).

Selection
---------

   A *double click* tries to load the documentation for the selected word
in the same window.

   If the Shift key is simultaneously pressed a new browser window is
opened.

Search
------

   Pressing <Key-/> lets you search in the displayed documentation.

Section Menu
------------

   The Section Menu

   The 'Section' menu allows to directly jump to the start of a section in
the documentation.

Action Menu
-----------

   If you press the right mouse button you get a popup menu that allows:

o Back
     in history of displayed documentation

o Reload
     the documentation

o Edit
     start editor with source of the displayed document.

     The used editor is selected by the first definition of the
     environment variables `XEDITOR', `VISUAL', `EDITOR' or as default
     `/usr/bin/vi'.

o Search ...
     Full text search of the POD in the perl library directories.  (Note:
     to use it one has to install perlindex distribution.)

SEE ALSO
========

   `tkpod' in this node Perlpod (perl.info), `pod2man' in
this node `pod2text' in this node `pod2html' in this node Tk/Pod,
see Tk/Pod/Text,

KEYWORDS
========

   pod, browser, tk, hypertext

AUTHOR
======

   Achim Bohnet <`ach@mpe.mpg.de'>

   Copyright (c) 1997-1998 Achim Bohnet. All rights reserved.  This
documentation is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

An Entry widget with an automatic, configurable right-click menu built in, plus input masks.
********************************************************************************************

NAME
====

   PopEntry - An Entry widget with an automatic, configurable right-click
menu built in, plus input masks.

SYNOPSIS
--------

     use PopEntry;
     $dw = $parent->PopEntry(
         -pattern   => 'alpha', 'alphanum', 'capsonly', 'signed_int',
                    'unsigned_int', 'float', 'nondigit', or any supplied regexp.
         -nomenu    => 0 or 1,
         -case      => 'upper', 'lower', 'capitalize',
         -maxwidth  => int,
         -minvalue  => int,
         -maxvalue  => int,
         -nospace   => 0 or 1,
         -menuitems => ['string', 'package::callback', 'binding', 'index'],
      );
      $dw->pack;

DESCRIPTION
-----------

   An Entry widget with a right-click menu attached automatically.  In
addition, certain field masks can easily be applied to the Entry widget in
order to force the end-user into entering only the values you want him or
her to enter.

   By default, there are five items attached to the right-click menu: Cut,
Copy, Paste, Delete and Sel. All.  The default bindings for the items are
Control-x, Control-c, Control-v, Control-d, and Control-a, respectively.

   The difference between 'Cut' and 'Delete' is that the former
automatically copies the contents that were cut to the clipboard, while
the latter does not.

OPTIONS
-------

   *-pattern =>* string

   The pattern specified here creates an input mask for the PopEntry widget.  There are seven pre-defined masks:

   * alpha - Upper and lower case a-z only.

   * alphanum - Alpha-numeric characters only.

   * capsonly - Upper case A-Z only.

   * nondigit - Any characters except 0-9.

   * float - A float value, which may or may not include a decimal.

   * signed_int - A signed integer value, which may or may not include a
     '+'.

   * unsigned_int - An unsigned integer value.

You may also specify a regular expression of your own design using Perl's standard regular expression mechanisms.  Be sure to use single quotes, e.g.  '/\d\w\d/'

   *-nomenu =>* **0* or 1*

   If set to true, then no right-click menu will appear.  Presumably, you would set this if you were only interested in the input-mask functionality.  The default is, of course, 0.

   *-nospace =>* **0* or 1*

   If set to true (1), the user may not enter whitespace before, after or between words within that PopEntry widget.  The default is 0.

   *-maxwidth =>* int

   Specifies the maximum number of characters that the user can enter in that particular PopEntry widget.  Note that this is not the same as the width of the widget itself.

   *-maxvalue =>* *int or float*

   If one of the pre-defined numeric patterns is chosen, this specifies the maximum allowable value that may be entered by a user for the widget.

   *-minvalue =>* *int or float*

   If one of the pre-defined numeric patterns is chosen, this specifies the minimum allowable value for the first digit (0-9).  This should work better.

   *-menuitems =>* *['string', 'callback', '<binding>', 'underline_index']*

   If specified, this creates a user-defined right-click menu rather than the one that is provided by default.  The value specified must be a four element nested anonymous array that contains (in this order):

  1. a string that appears on the menu,

  2. a callback (in 'package::callback' syntax format),

  3. a binding for that option (see below),

  4. an index value specifying the character in the string to be
     underlined.

The binding specified need only be in the form, '<Control-x>'.  You needn't explicitly bind it yourself.  Your callback will automatically be bound to the event sequence you specified.

METHODS
-------

   *$lpe->deleteItem(index, ?index?)*

   Deletes the menu option at the specified index.  A range of values may be deleted as well, e.g. $lpe->deleteItem(3,'end');  Returns an array reference if a single item is deleted, or a reference to an array of references if more than one item is deleted.

   *$lpe->addItem(?index?, $item)*

   Adds a menu option at the specified index, where $item is an anonymous array consisting of four elements (see the -menuitems option for details).  If no index is specified, the new item will be added at the end of the menu.  If an item already exists at that index, the current menu items will be "bumped" down.  Returns the list of menuitems.

ADVERTISED SUBWIDGETS
---------------------

   *$lpe->Subwidget('popupmenu')*

   Returns a reference to the popupmenu (a toplevel widget).

KNOWN BUGS
----------

   The -minvalue only works for the first digit.

   There is still potential for odd results if your bind happens to
coincide with a binding already used by the Window Manager.  In windows,
where I did most of my testing, this meant that Control-v would paste
twice, once because MS Windows told it to, and once because I told it to.
I got different (bad) results with Control-v in KDE on Mandrake 7.2.

PLANNED CHANGES
---------------

   Fix the issues mentioned above.

   Automatically bind the 'Alt' key to the underlined character.

   Give the option to remove bindings completely.

AUTHOR
------

   Daniel J. Berger djberg96@hotmail.com

SEE ALSO
--------

   Entry

A graphical progress bar
************************

NAME
====

   Tk::ProgressBar - A graphical progress bar

     use Tk::ProgressBar;

     $progress = $parent->ProgressBar(
     	-width => 200,
     	-length => 20,
         -anchor => 's',
     	-from => 0,
     	-to => 100,
     	-blocks => 10,
     	-colors => [0, 'green', 50, 'yellow' , 80, 'red'],
     	-variable => \$percent_done
     );

     $progress->value($position);

DESCRIPTION
===========

   *Tk::ProgressBar* provides a widget which will show a graphical
representation of a value, given maximum and minimum reference values.

STANDARD OPTIONS
================

   The following standard widget options are supported:

*-borderwidth*
*-highlightthickness*
     Defaults to 0.

*-padx*
     Defaults to 0.

*-pady*
     Defaults to 0.

*-relief*
     Defaults to `sunken'

*-troughcolor*
     The color to be used for the background (trough) of the progress bar.
     Default is to use grey55.

WIDGET-SPECIFIC OPTIONS
=======================

*-anchor*
     This can be used to position the start point of the bar. Default is
     'w' (horizontal bar starting from the left). A vertical bar can be
     configured by using either 's' or 'n'.

*-blocks*
     This controls the number of blocks to be used to construct the
     progress bar. The default is to break the bar into 10 blocks.

*-colors*
     Controls the colors to be used for different positions of the
     progress bar.  The colors should be supplied as a reference to an
     array containing pairs of positions and colors.

          -colors => [ 0, 'green', 50, 'red' ]

     means that for the range 0 to 50 the progress bar should be green and
     for higher values it should be red.

*-from*
     This sets the lower limit of the progress bar.  If the bar is set to a
     value below the lower limt no bar will be displayed. Defaults to 0.
     See the `-to' description for more information.

*-gap*
     This is the spacing (in pixels) between each block. Defaults to 1.
     Use 0 to get a continuous bar.

*-length*
     Specifies the desired long dimension of the ProgressBar in screen
     units (i.e. any of the forms acceptable to Tk_GetPixels). For vertical
     ProgressBars this is the ProgressBars height; for horizontal scales it
     is the ProgressBars width.  The default length is calculated from the
     values of `-padx', `-borderwidth', `-highlightthickness' and the
     difference between `-from' and `-to'.

*-resolution*
     A real value specifying the resolution for the scale. If this value
     is greater than zero then the scale's value will always be rounded to
     an even multiple of this value, as will tick marks and the endpoints
     of the scale. If the value is less than zero then no rounding occurs.
     Defaults to 1 (i.e., the value will be integral).

*-to*
     This sets the upper limit of the progress bar. If a value is specified
     (for example, using the value method) that lies above this value the
     full progress bar will be displayed. Defaults to 100.

*-variable*
     Specifies the reference to a scalar variable to link to the
     ProgressBar.  Whenever the value of the variable changes, the
     ProgressBar will upate to reflect this value. (See also the value
     method below.)

*-value*
     The can be used to set the current position of the progress bar when
     used in conjunction with the standard configure. It is usually
     recommended to use the value method instead.

*-width*
     Specifies the desired narrow dimension of the ProgressBar in screen
     units (i.e.  any of the forms acceptable to Tk_GetPixels). For
     vertical ProgressBars this is the ProgressBars width; for horizontal
     bars this is the ProgressBars height.  The default width is derived
     from the values of `-borderwidth' and `-pady' and
     `-highlightthickness'.

WIDGET METHODS
==============

*$ProgressBar*->value(?value?)
     If value is omitted, returns the current value of the ProgressBar.  If
     value is given, the value of the ProgressBar is set. If $value is
     given but undefined the value of the option *-from* is used.

AUTHOR
======

   Graham Barr <`gbarr@pobox.com'>

COPYRIGHT
=========

   Copyright (c) 1997-1998 Graham Barr. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Another, simpler ProgressBar
****************************

NAME
====

   Tk::ProgressIndicator - Another, simpler ProgressBar

SYNOPSIS
========

     use Tk::ProgressIndicator;

     my $MainWindow = MainWindow->new();

     $ProgressIndicator = $MainWindow->ProgressIndicator
        (
         '-current' => 0,
         '-limit' => 200,
         '-increment' => 10,
         '-height' => 20,
         '-width' => 400
        );

     Tk::MainLoop;

     ...

     $ProgressIndicator->configure ('-current' => ++$index);

DESCRIPTION
===========

   A progress bar widget.

AUTHORS
=======

   Damion K. Wilson, dkw@rcm.bm

HISTORY    =cut
===============

'readonly' perl/Tk Text widget
******************************

NAME
====

   Tk::ROText - 'readonly' perl/Tk Text widget

SYNOPSIS
========

     use Tk::ROText;
     ...
     $ro = $mw->ROText(?options,...?);

DESCRIPTION
===========

   This "*IS A*" text widget with all bindings removed that would alter
the contents of the text widget. The contents can still be modified via
method calls.

KEYS
====

   widget, text, readonly

SEE ALSO
========

   See Tk/Text,

Read-only Tk::TextANSIColor
***************************

NAME
====

   Tk::ROTextANSIColor - Read-only Tk::TextANSIColor

SYNOPSIS
========

     use Tk::ROTextANSIColor;

     $wid = $mw->ROTextANSIColor(?options,...?);

     $wid->insert($pos, $string, ?taglist, ?string, ?taglist);

     use Term::ANSIColor;
     $red = color('red');  # Retrieve color codes
     $bold = color('bold');
     $wid->insert('end', "$red red text $bold with bold\n");

DESCRIPTION
===========

   This is a read-only version of `Tk::TextANSIColor'.

SEE ALSO
========

   See Tk/ROText, Tk/TextANSIColor,

AUTHOR
======

   Tim Jenness (<`t.jenness@jach.hawaii.edu'>)

COPYRIGHT
=========

   Copyright (c) 1999-2000 Tim Jenness. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Create and manipulate Radiobutton widgets
*****************************************

NAME
====

   Tk::Radiobutton - Create and manipulate Radiobutton widgets

   *$radiobutton* = *$parent*->Radiobutton(?options?);

STANDARD OPTIONS
================

*-activebackground*	*-cursor*	*-highlightthickness*	*-takefocus*
*-activeforeground*	*-disabledforeground*	*-image*	*-text*
*-anchor*	*-font*	-justify	*-textvariable*
*-background*	*-foreground*	*-padx*	*-underline*
*-bitmap*	*-highlightbackground*	*-pady*	*-wraplength*
*-borderwidth*	*-highlightcolor*	*-relief*

   See Tk/options, for details of the standard options.

WIDGET-SPECIFIC OPTIONS
=======================

Name:	command
Class:	Command
Switch:	*-command*
     Specifies a `Tk callback|Tk::callbacks', see Perl (perl.info),
     to associate with the button.  This command is typically invoked when
     mouse button 1 is released over the button window.  The button's
     global variable (*-variable* option) will be updated before the
     command is invoked.

Name:	height
Class:	*Height*
Switch:	*-height*
     Specifies a desired height for the button.  If an image or bitmap is
     being displayed in the button then the value is in screen units (i.e.
     any of the forms acceptable to *Tk_GetPixels*); for text it is in
     lines of text.  If this option isn't specified, the button's desired
     height is computed from the size of the image or bitmap or text being
     displayed in it.

Name:	*indicatorOn*
Class:	*IndicatorOn*
Switch:	*-indicatoron*
     Specifies whether or not the indicator should be drawn.  Must be a
     proper boolean value.  If false, the *relief* option is ignored and
     the widget's relief is always sunken if the widget is selected and
     raised otherwise.

Name:	*selectColor*
Class:	Background
Switch:	*-selectcolor*
     Specifies a background color to use when the button is selected.  If
     *indicatorOn* is true then the color applies to the indicator.  Under
     Windows, this color is used as the background for the indicator
     regardless of the select state.  If *indicatorOn* is false, this
     color is used as the background for the entire widget, in place of
     background or *activeBackground*, whenever the widget is selected.
     If specified as an empty string then no special color is used for
     displaying when the widget is selected.

Name:	*selectImage*
Class:	*SelectImage*
Switch:	*-selectimage*
     Specifies an image to display (in place of the image option) when the
     radiobutton is selected.  This option is ignored unless the image
     option has been specified.

Name:	state
Class:	State
Switch:	*-state*
     Specifies one of three states for the radiobutton:  normal, active,
     or disabled.  In normal state the radiobutton is displayed using the
     *foreground* and background options.  The active state is typically
     used when the pointer is over the radiobutton.  In active state the
     radiobutton is displayed using the *activeForeground* and
     *activeBackground* options.  Disabled state means that the radiobutton
     should be insensitive:  the default bindings will refuse to activate
     the widget and will ignore mouse button presses.  In this state the
     *disabledForeground* and background options determine how the
     radiobutton is displayed.

Name:	value
Class:	Value
Switch:	*-value*
     Specifies value to store in the button's associated variable whenever
     this button is selected.

Name:	variable
Class:	Variable
Switch:	*-variable*
     Specifies reference to a variable to set whenever this button is
     selected.  Changes in this variable also cause the button to select
     or deselect itself. Defaults to the value `\$Tk::selectedButton'.

Name:	width
Class:	Width
Switch:	*-width*
     Specifies a desired width for the button.  If an image or bitmap is
     being displayed in the button, the value is in screen units (i.e. any
     of the forms acceptable to *Tk_GetPixels*); for text it is in
     characters.  If this option isn't specified, the button's desired
     width is computed from the size of the image or bitmap or text being
     displayed in it.

DESCRIPTION
===========

   The Radiobutton method creates a new window (given by the $widget
argument) and makes it into a radiobutton widget.  Additional options,
described above, may be specified on the command line or in the option
database to configure aspects of the radiobutton such as its colors, font,
text, and initial relief.  The *radiobutton* command returns its $widget
argument.  At the time this command is invoked, there must not exist a
window named $widget, but $widget's parent must exist.

   A radiobutton is a widget that displays a textual string, bitmap or
image and a diamond or circle called an *indicator*.  If text is
displayed, it must all be in a single font, but it can occupy multiple
lines on the screen (if it contains newlines or if wrapping occurs because
of the *wrapLength* option) and one of the characters may optionally be
underlined using the underline option.  A radiobutton has all of the
behavior of a simple button: it can display itself in either of three
different ways, according to the state option; it can be made to appear
raised, sunken, or flat; it can be made to flash; and it invokes a `Tk
callback|Tk::callbacks', see Perl (perl.info), whenever mouse
button 1 is clicked over the check button.

   In addition, radiobuttons can be *selected*.  If a radiobutton is
selected, the indicator is normally drawn with a selected appearance, and
a Tcl variable associated with the radiobutton is set to a particular
value (normally 1).  Under Unix, the indicator is drawn with a sunken
relief and a special color.  Under Windows, the indicator is drawn with a
round mark inside.  If the radiobutton is not selected, then the indicator
is drawn with a deselected appearance, and the associated variable is set
to a different value (typically 0).  Under Unix, the indicator is drawn
with a raised relief and no special color.  Under Windows, the indicator
is drawn without a round mark inside.  Typically, several radiobuttons
share a single variable and the value of the variable indicates which
radiobutton is to be selected.  When a radiobutton is selected it sets the
value of the variable to indicate that fact;  each radiobutton also
monitors the value of the variable and automatically selects and deselects
itself when the variable's value changes.  By default the variable
*selectedButton* is used;  its contents give the name of the button that is
selected, or the empty string if no button associated with that variable
is selected.  The name of the variable for a radiobutton, plus the
variable to be stored into it, may be modified with options on the command
line or in the option database.  Configuration options may also be used to
modify the way the indicator is displayed (or whether it is displayed at
all).  By default a radiobutton is configured to select itself on button
clicks.

WIDGET METHODS
==============

   The Radiobutton method creates a widget object.  This object supports
the configure and cget methods described in Tk/options,
which can be used to enquire and modify the options described above.  The
widget also inherits all the methods provided by the generic
`Tk::Widget|Tk::Widget' in this node class.

   The following additional methods are available for radiobutton widgets:

*$radiobutton*->*deselect*
     Deselects the radiobutton and sets the associated variable to an
     empty string.  If this radiobutton was not currently selected, the
     command has no effect.

*$radiobutton*->flash
     Flashes the radiobutton.  This is accomplished by redisplaying the
     radiobutton several times, alternating between active and normal
     colors.  At the end of the flash the radiobutton is left in the same
     normal/active state as when the command was invoked.  This command is
     ignored if the radiobutton's state is disabled.

*$radiobutton*->*invoke*
     Does just what would have happened if the user invoked the radiobutton
     with the mouse: selects the button and invokes its associated Tcl
     command, if there is one.  The return value is the return value from
     the Tcl command, or an empty string if there is no command associated
     with the radiobutton.  This command is ignored if the radiobutton's
     state is disabled.

*$radiobutton*->select
     Selects the radiobutton and sets the associated variable to the value
     corresponding to this widget.

BINDINGS
========

   Tk automatically creates class bindings for radiobuttons that give them
the following default behavior:

[1]
     On Unix systems, a radiobutton activates whenever the mouse passes
     over it and deactivates whenever the mouse leaves the radiobutton.  On
     Mac and Windows systems, when mouse button 1 is pressed over a
     radiobutton, the button activates whenever the mouse pointer is inside
     the button, and deactivates whenever the mouse pointer leaves the
     button.

[2]
     When mouse button 1 is pressed over a radiobutton it is invoked (it
     becomes selected and the command associated with the button is
     invoked, if there is one).

[3]
     When a radiobutton has the input focus, the space key causes the
     radiobutton to be invoked.

     If the radiobutton's state is disabled then none of the above actions
     occur:  the radiobutton is completely non-responsive.

     The behavior of radiobuttons can be changed by defining new bindings
     for individual widgets or by redefining the class bindings.

KEYWORDS
========

   radiobutton, widget

change the base index of Text-like widgets
******************************************

NAME
====

   Tk::Reindex - change the base index of Text-like widgets

     use Tk::ReindexedText;
     $t1=$w->ReindexedText(-linestart => 2);

     use Tk::ReindexedROText;
     $t2=$w->ReindexedROText(-linestart => 0);

DESCRIPTION
===========

   Creates a new widget class based on Text-like widgets that can redefine
the line number base (normally Text widgets start line numbers at 1), or
possibly other manipulations on indexes.

STANDARD OPTIONS
================

   The newly-defined widget takes all the same options as the base widget,
which defaults to Text.

WIDGET-SPECIFIC OPTIONS
=======================

Name:   *lineStart*
Class:  *LineStart*
Switch: *-linestart*
     Sets the line number of the first line in the Text widget. The
     default *-toindexcmd* and *-fromindexcmd* use this configuration
     option.

     -item Name:   *toIndexCmd*  *fromIndexCmd*

     -item Class:  *ToIndexCmd*  *FromIndexCmd*

     -item Switch: *-toindexcmd* *-fromindexcmd*

     These two options specify callbacks that are called with a list of
     indexes and are responsible for translating them to/from indexes that
     the base Text widget can understand. The callback is passed the
     widget followed by a list of indexes, and should return a list of
     translated indexes. *-toindexcmd* should translate from 'user'
     indexes to 'native' Text-compatible indexes, and *-fromindexcmd*
     should translate from 'native' indexes to 'user' indexes.

     The default callbacks simply add/subtract the offset given by the
     *-linestart* option for all indexes in 'line.character' format.

     It would probably be prudent to make these functions inverses of each
     other.

CLASS METHODS
=============

import
     To make new Reindex widgets, this function should be called via use
     with the name of the Text-like base class that you are extending with
     "Reindex" capability.  'use base(Tk::Reindex Tk::nameofbasewidget)'
     should also be specified for that widget.

BUGS
====

   I've used the word "indexes" instead of "indices" throughout the
documentation.

   All the built-in perl code for widget bindings & methods will use the
new 'user' indexes.  Which means all this index manipulation might might
break code that is trying to parse/manipulate indexes. Or even assume that
'1.0' is the beginning index.  *Tk::Text::Contents* comes to mind.

AUTHOR
======

   Andrew Allen <ada@fc.hp.com>

   This code may be distributed under the same conditions as Perl.

Browse directories with FTP.
****************************

NAME
====

     RemoteFileSelect.pm--Browse directories with FTP.

SYNOPSIS
========

     require Tk::RemoteFileSelect;

     my $file = $mw -> Tk::RemoteFileSelect( -directory => '.' );

DESCRIPTION
===========

   A RemoteFileSelect contains two listboxes that display subdirectories
and files, a directory entry and a file name entry, and buttons for each
operation, which are labeled with Alt-key accelerators.

   When entering a file name, the RemoteFileSelect verifies whether the
file already exists.  If a file is selected in the listbox, the
RemoteFileSelect returns that file's name when the user clicks the
'Accept' button, presses Enter after typing a name in the file entry, or
double clicks on a selection in the file list box.

   Additionally, if the Net::FTP module is installed, RemoteFileSelect
will activate an additional "Host" button on the FileSelect widget, where
you can enter the host name, and your user id and password, and select
files on the remote host.

   If a file name is selected on the local host, then the RemoteFileSelect
widget returns the path to the file name, the same as a standard
FileSelect widget.

   If a file is selected on a remote host, then the RemoteFileSelect
widget returns the name in the form:

     host:/full-pathname-of-file

   RemoteFileSelect requires the Net::FTP module to be installed.  If it
cannot find and load Net::FTP, the RemoteFileSelect widget behaves like a
standard FileSelect widget, and the "Host" button is grayed out.

   RemoteFileSelect.pm was developed with the Net::FTP module distributed
with libnet-1.0703, from http://www.cpan.org/.

   All other operations function as in a FileSelect widget.  Please refer
to the FileSelect.pm POD documentation.

VERSION INFO
============

     First development version.

     $Revision: 0.55 $

Canvas widget with arbitrary rotation support
*********************************************

NAME
====

   Tk::RotCanvas - Canvas widget with arbitrary rotation support

     $canvas = $parent->RotCanvas(?options?);
     my $obj = $canvas->create('polygon', @coords, %options);
     $canvas->rotate($obj, $angle, ?x, y?);

DESCRIPTION
===========

   This module is a small wrapper around the Canvas widget that adds a new
rotate() method. This method allows the rotation of various canvas objects
by arbitrary angles.

NEW METHODS
===========

   As mentioned previously, there is only one new method. All other canvas
methods work as expected.

*$canvas*->rotate(*TagOrID, angle* ?,*x, y*?)
     This method rotates the object identified by TagOrID by an angle
     *angle*.  The angle is specified in *degrees*. If a coordinate is
     specified, then the object is rotated about that point. Else, the
     object is rotated about its center of mass.

LIMITATIONS
===========

   As it stands, the module can only handle the following object types:

   * Lines

   * Rectangles

   * Polygons

   All other object types (bitmap, image, arc, text, window and oval) can
not be handled yet. A warning is issued if the user tries to rotate one of
these object types. Hopefully, more types will be handled in the future.

MORE DETAILS YOU DON'T NEED TO KNOW
===================================

   To be able to handle rectangles, the module intercepts any calls to
*createRectangle()* and create() and changes all rectangles to polygons.
The user should not be alarmed if type() returned *polygon* when a
rectangle was expected.

AUTHOR
======

   Ala Qumsieh *aqumsieh@hyperchip.com*

COPYRIGHTS
==========

   This module is distributed under the same terms as Perl itself.

Create and manipulate Scale widgets
***********************************

NAME
====

   Tk::Scale - Create and manipulate Scale widgets

   $scale = *$parent*->Scale(?options?);

STANDARD OPTIONS
================

*-activebackground*	*-font*	*-highlightthickness*	*-repeatinterval*
*-background*	*-foreground*	*-orient*	*-takefocus*
*-borderwidth*	*-highlightbackground*	*-relief*	*-troughcolor*
*-cursor*	*-highlightcolor*	*-repeatdelay*

   See Tk/options, for details of the standard options.

WIDGET-SPECIFIC OPTIONS
=======================

Name:	*bigIncrement*
Class:	*BigIncrement*
Switch:	*-bigincrement*
     Some interactions with the scale cause its value to change by "large"
     increments;  this option specifies the size of the large increments.
     If specified as 0, the large increments default to 1/10 the range of
     the scale.

Name:	command
Class:	Command
Switch:	*-command*
     Specifies the prefix of a `Tk callback|Tk::callbacks', see Perl (perl.info),
     to invoke whenever the scale's value is changed via
     a method.  The actual command consists of this option followed by a
     space and a real number indicating the new value of the scale.

Name:	digits
Class:	*Digits*
Switch:	*-digits*
     An integer specifying how many significant digits should be retained
     when converting the value of the scale to a string.  If the number is
     less than or equal to zero, then the scale picks the smallest value
     that guarantees that every possible slider position prints as a
     different string.

Name:	from
Class:	From
Switch:	*-from*
     A real value corresponding to the left or top end of the scale.

Name:	label
Class:	Label
Switch:	*-label*
     A string to display as a label for the scale.  For vertical scales
     the label is displayed just to the right of the top end of the scale.
     For horizontal scales the label is displayed just above the left end
     of the scale.  If the option is specified as an empty string, no
     label is displayed.

Name:	length
Class:	Length
Switch:	*-length*
     Specifies the desired long dimension of the scale in screen units
     (i.e. any of the forms acceptable to *Tk_GetPixels*).  For vertical
     scales this is the scale's height;  for horizontal scales it is the
     scale's width.

Name:	resolution
Class:	Resolution
Switch:	*-resolution*
     A real value specifying the resolution for the scale.  If this value
     is greater than zero then the scale's value will always be rounded to
     an even multiple of this value, as will tick marks and the endpoints
     of the scale.  If the value is less than zero then no rounding
     occurs.  Defaults to 1 (i.e., the value will be integral).

Name:	*showValue*
Class:	*ShowValue*
Switch:	*-showvalue*
     Specifies a boolean value indicating whether or not the current value
     of the scale is to be displayed.

Name:	*sliderLength*
Class:	*SliderLength*
Switch:	*-sliderlength*
     Specfies the size of the slider, measured in screen units along the
     slider's long dimension.  The value may be specified in any of the
     forms acceptable to *Tk_GetPixels*.

Name:	*sliderRelief*
Class:	*SliderRelief*
Switch:	*-sliderrelief*
     Specifies the relief to use when drawing the slider, such as *raised*
     or *sunken*.

Name:	state
Class:	State
Switch:	*-state*
     Specifies one of three states for the scale:  normal, active, or
     disabled.  If the scale is disabled then the value may not be changed
     and the scale won't activate.  If the scale is active, the slider is
     displayed using the color specified by the *activeBackground* option.

Name:	*tickInterval*
Class:	*TickInterval*
Switch:	*-tickinterval*
     Must be a real value.  Determines the spacing between numerical tick
     marks displayed below or to the left of the slider.  If 0, no tick
     marks will be displayed.

Name:	to
Class:	To
Switch:	*-to*
     Specifies a real value corresponding to the right or bottom end of
     the scale.  This value may be either less than or greater than the
     from option.

Name:	variable
Class:	Variable
Switch:	*-variable*
     Specifies the name of a global variable to link to the scale.
     Whenever the value of the variable changes, the scale will update to
     reflect this value.  Whenever the scale is manipulated interactively,
     the variable will be modified to reflect the scale's new value.

Name:	width
Class:	Width
Switch:	*-width*
     Specifies the desired narrow dimension of the trough in screen units
     (i.e. any of the forms acceptable to *Tk_GetPixels*).  For vertical
     scales this is the trough's width;  for horizontal scales this is the
     trough's height.

DESCRIPTION
===========

   The Scale method creates a new window (given by the $widget argument)
and makes it into a scale widget.  Additional options, described above,
may be specified on the command line or in the option database to
configure aspects of the scale such as its colors, orientation, and
relief.  The scale command returns its $widget argument.  At the time this
command is invoked, there must not exist a window named $widget, but
$widget's parent must exist.

   A scale is a widget that displays a rectangular *trough* and a small
slider.  The trough corresponds to a range of real values (determined by
the from, to, and resolution options), and the position of the slider
selects a particular real value.  The slider's position (and hence the
scale's value) may be adjusted with the mouse or keyboard as described in
the `"BINDINGS"' in this node section below.  Whenever the scale's value
is changed, a Tcl command is invoked (using the command option) to notify
other interested widgets of the change.  In addition, the value of the
scale can be linked to a Tcl variable (using the variable option), so that
changes in either are reflected in the other.

   Three annotations may be displayed in a scale widget:  a label
appearing at the top right of the widget (top left for horizontal scales),
a number displayed just to the left of the slider (just above the slider
for horizontal scales), and a collection of numerical tick marks just to
the left of the current value (just below the trough for horizontal
scales).  Each of these three annotations may be enabled or disabled using
the configuration options.

WIDGET METHODS
==============

   The Scale method creates a widget object.  This object supports the
configure and cget methods described in Tk/options,
which can be used to enquire and modify the options described above.  The
widget also inherits all the methods provided by the generic
`Tk::Widget|Tk::Widget' in this node class.

   The following additional methods are available for scale widgets:

$scale->*coords*(?value?)
     Returns a list whose elements are the x and y coordinates of the
     point along the centerline of the trough that corresponds to value.
     If value is omitted then the scale's current value is used.

$scale->get(?*x, y*?)
     If x and y are omitted, returns the current value of the scale.  If x
     and y are specified, they give pixel coordinates within the widget;
     the command returns the scale value corresponding to the given pixel.
     Only one of x or y is used:  for horizontal scales y is ignored, and
     for vertical scales x is ignored.

$scale->identify(*x, y*)
     Returns a string indicating what part of the scale lies under the
     coordinates given by x and y.  A return value of slider means that
     the point is over the slider;  trough1 means that the point is over
     the portion of the slider above  or to the left of the slider; and
     trough2 means that the point is over the portion of the slider below
     or to the right of the slider.  If the point isn't over one of these
     elements, an empty string is returned.

$scale->set(value)
     This command is invoked to change the current value of the scale, and
     hence the position at which the slider is displayed.  Value gives the
     new value for the scale.  The command has no effect if the scale is
     disabled.

BINDINGS
========

   Tk automatically creates class bindings for scales that give them the
following default behavior.  Where the behavior is different for vertical
and horizontal scales, the horizontal behavior is described in parentheses.

[1]
     If button 1 is pressed in the trough, the scale's value will be
     incremented or decremented by the value of the resolution option so
     that the slider moves in the direction of the cursor.  If the button
     is held down, the action auto-repeats.

[2]
     If button 1 is pressed over the slider, the slider can be dragged
     with the mouse.

[3]
     If button 1 is pressed in the trough with the Control key down, the
     slider moves all the way to the end of its range, in the direction
     towards the mouse cursor.

[4]
     If button 2 is pressed, the scale's value is set to the mouse
     position.  If the mouse is dragged with button 2 down, the scale's
     value changes with the drag.

[5]
     The Up and Left keys move the slider up (left) by the value of the
     resolution option.

[6]
     The Down and Right keys move the slider down (right) by the value of
     the resolution option.

[7]
     Control-Up and Control-Left move the slider up (left) by the value of
     the *bigIncrement* option.

[8]
     Control-Down and Control-Right move the slider down (right) by the
     value of the *bigIncrement* option.

[9]
     Home moves the slider to the top (left) end of its range.

[10]
     End moves the slider to the bottom (right) end of its range.

     If the scale is disabled using the state option then none of the
     above bindings have any effect.

     The behavior of scales can be changed by defining new bindings for
     individual widgets or by redefining the class bindings.

KEYWORDS
========

   scale, slider, trough, widget

Create and manipulate Scrollbar widgets
***************************************

NAME
====

   Tk::Scrollbar - Create and manipulate Scrollbar widgets

   *$scrollbar* = *$parent*->Scrollbar(?options?);

STANDARD OPTIONS
================

*-activebackground*	*-highlightbackground*	*-orient*	*-takefocus*
*-background*	*-highlightcolor*	*-relief*	*-troughcolor*
*-borderwidth*	*-highlightthickness*	*-repeatdelay*
*-cursor*	*-jump*	*-repeatinterval*

   See Tk/options, for details of the standard options.

WIDGET-SPECIFIC OPTIONS
=======================

Name:	*activeRelief*
Class:	*ActiveRelief*
Switch:	*-activerelief*
     Specifies the relief to use when displaying the element that is
     active, if any.  Elements other than the active element are always
     displayed with a raised relief.

Name:	command
Class:	Command
Switch:	*-command*
     Specifies a callback to invoke to change the view in the widget
     associated with the scrollbar.  When a user requests a view change by
     manipulating the scrollbar, the callback is invoked.  The callback is
     passed additional arguments as described later. This option almost
     always has a value such as *[xview => $widget]* or *[yview =>
     $widget]*, consisting of the a widget object and either *xview* (if
     the scrollbar is for horizontal scrolling) or *yview* (for vertical
     scrolling).  All scrollable widgets have *xview* and *yview* methods
     that take exactly the additional arguments appended by the scrollbar
     as described in `"SCROLLING COMMANDS"' in this node below.

Name:	*elementBorderWidth*
Class:	*BorderWidth*
Switch:	*-elementborderwidth*
     Specifies the width of borders drawn around the internal elements of
     the scrollbar (the two arrows and the slider).  The value may have
     any of the forms acceptable to *Tk_GetPixels*.  If this value is less
     than zero, the value of the *borderWidth* option is used in its place.

Name:	width
Class:	Width
Switch:	*-width*
     Specifies the desired narrow dimension of the scrollbar window, not
     including 3-D border, if any.  For vertical scrollbars this will be
     the width and for horizontal scrollbars this will be the height.  The
     value may have any of the forms acceptable to *Tk_GetPixels*.

DESCRIPTION
===========

   The Scrollbar method creates a new window (given by the $widget
argument) and makes it into a scrollbar widget.  Additional options,
described above, may be specified on the command line or in the option
database to configure aspects of the scrollbar such as its colors,
orientation, and relief.  The *scrollbar* command returns its $widget
argument.  At the time this command is invoked, there must not exist a
window named $widget, but $widget's parent must exist.

   A scrollbar is a widget that displays two arrows, one at each end of
the scrollbar, and a slider in the middle portion of the scrollbar.  It
provides information about what is visible in an *associated window* that
displays an document of some sort (such as a file being edited or a
drawing).  The position and size of the slider indicate which portion of
the document is visible in the associated window.  For example, if the
slider in a vertical scrollbar covers the top third of the area between
the two arrows, it means that the associated window displays the top third
of its document.

   Scrollbars can be used to adjust the view in the associated window by
clicking or dragging with the mouse.  See `"BINDINGS"' in this node below
for details.

ELEMENTS
========

   A scrollbar displays five elements, which are referred to in the
methods for the scrollbar:

arrow1
     The top or left arrow in the scrollbar.

trough1
     The region between the slider and arrow1.

slider
     The rectangle that indicates what is visible in the associated widget.

trough2
     The region between the slider and arrow2.

arrow2
     The bottom or right arrow in the scrollbar.

WIDGET METHODS
==============

   The Scrollbar method creates a widget object.  This object supports the
configure and cget methods described in Tk/options,
which can be used to enquire and modify the options described above.  The
widget also inherits all the methods provided by the generic
`Tk::Widget|Tk::Widget' in this node class.

   The following additional methods are available for scrollbar widgets:

*$scrollbar*->activate(?*element*?)
     Marks the element indicated by *element* as active, which causes it
     to be displayed as specified by the *activeBackground* and
     *activeRelief* options.  The only element values understood by this
     command are arrow1, slider, or arrow2.  If any other value is
     specified then no element of the scrollbar will be active.  If
     *element* is not specified, the command returns the name of the
     element that is currently active, or an empty string if no element is
     active.

*$scrollbar*->*delta*(*deltaX, deltaY*)
     Returns a real number indicating the fractional change in the
     scrollbar setting that corresponds to a given change in slider
     position.  For example, if the scrollbar is horizontal, the result
     indicates how much the scrollbar setting must change to move the
     slider *deltaX* pixels to the right (*deltaY* is ignored in this
     case).  If the scrollbar is vertical, the result indicates how much
     the scrollbar setting must change to move the slider *deltaY* pixels
     down.  The arguments and the result may be zero or negative.

*$scrollbar*->*fraction*(*x, y*)
     Returns a real number between 0 and 1 indicating where the point
     given by x and y lies in the trough area of the scrollbar.  The value
     0 corresponds to the top or left of the trough, the value 1
     corresponds to the bottom or right, 0.5 corresponds to the middle,
     and so on.  X and y must be pixel coordinates relative to the
     scrollbar widget.  If x and y refer to a point outside the trough,
     the closest point in the trough is used.

*$scrollbar*->get
     Returns the scrollbar settings in the form of a list whose elements
     are the arguments to the most recent set method.

*$scrollbar*->identify(*x, y*)
     Returns the name of the element under the point given by x and y
     (such as arrow1), or an empty string if the point does not lie in any
     element of the scrollbar.  X and y must be pixel coordinates relative
     to the scrollbar widget.

*$scrollbar*->set(*first, last*)
     This command is invoked by the scrollbar's associated widget to tell
     the scrollbar about the current view in the widget.  The command
     takes two arguments, each of which is a real fraction between 0 and 1.
     The fractions describe the range of the document that is visible in
     the associated widget.  For example, if first is 0.2 and last is 0.4,
     it means that the first part of the document visible in the window is
     20% of the way through the document, and the last visible part is 40%
     of the way through.

SCROLLING COMMANDS
==================

   When the user interacts with the scrollbar, for example by dragging the
slider, the scrollbar notifies the associated widget that it must change
its view.  The scrollbar makes the notification by evaluating a callback
specified as the scrollbar's *-command* option.  The callback may take
several forms.  In each case, the intial arguments passed are those
specified in the *-command* callback itself, which usually has a form like
[*yview* => $widget].  (Which will invoke $widget->*yview*(...) where the
... part is as below. See Tk/callbacks, for details.)
The callback is passed additional arguments as follows:

*moveto*,*fraction*
     *Fraction* is a real number between 0 and 1.  The widget should
     adjust its view so that the point given by *fraction* appears at the
     beginning of the widget.  If *fraction* is 0 it refers to the
     beginning of the document.  1.0 refers to the end of the document,
     0.333 refers to a point one-third of the way through the document,
     and so on.

*scroll,**number,**units*
     The widget should adjust its view by number units.  The units are
     defined in whatever way makes sense for the widget, such as
     characters or lines in a text widget.  Number is either 1, which
     means one unit should scroll off the top or left of the window, or
     -1, which means that one unit should scroll off the bottom or right
     of the window.

scroll,number,page
     The widget should adjust its view by number pages.  It is up to the
     widget to define the meaning of a page;  typically it is slightly
     less than what fits in the window, so that there is a slight overlap
     between the old and new views.  Number is either 1, which means the
     next page should become visible, or -1, which means that the previous
     page should become visible.

OLD COMMAND SYNTAX
==================

   In versions of Tk before 4.0, the set and get widget commands used a
different form.  This form is still supported for backward compatibility,
but it is deprecated.  In the old command syntax, the set method has the
following form:

*$scrollbar*->set(*totalUnits, windowUnits, firstUnit, lastUnit*)
     In this form the arguments are all integers.  *TotalUnits* gives the
     total size of the object being displayed in the associated widget.
     The meaning of one unit depends on the associated widget;  for
     example, in a text editor widget units might correspond to lines of
     text.  *WindowUnits* indicates the total number of units that can fit
     in the associated window at one time.  *FirstUnit* and *lastUnit*
     give the indices of the first and last units currently visible in the
     associated window (zero corresponds to the first unit of the object).

   Under the old syntax the get method returns a list of four integers,
consisting of the *totalUnits*, *windowUnits*, *firstUnit*, and *lastUnit*
values from the last set method.

   The callbacks generated by scrollbars also have a different form when
the old syntax is being used, the callback is passed a single argument:

unit
     *Unit* is an integer that indicates what should appear at the top or
     left of the associated widget's window.  It has the same meaning as
     the *firstUnit* and *lastUnit* arguments to the set method.

   The most recent set method determines whether or not to use the old
syntax.  If it is given two real arguments then the new syntax will be
used in the future, and if it is given four integer arguments then the old
syntax will be used.

BINDINGS
========

   Tk automatically creates class bindings for scrollbars that give them
the following default behavior.  If the behavior is different for vertical
and horizontal scrollbars, the horizontal behavior is described in
parentheses.

[1]
     Pressing button 1 over arrow1 causes the view in the associated
     widget to shift up (left) by one unit so that the document appears to
     move down (right) one unit.  If the button is held down, the action
     auto-repeats.

[2]
     Pressing button 1 over trough1 causes the view in the associated
     widget to shift up (left) by one screenful so that the document
     appears to move down (right) one screenful.  If the button is held
     down, the action auto-repeats.

[3]
     Pressing button 1 over the slider and dragging causes the view to
     drag with the slider.  If the jump option is true, then the view
     doesn't drag along with the slider;  it changes only when the mouse
     button is released.

[4]
     Pressing button 1 over trough2 causes the view in the associated
     widget to shift down (right) by one screenful so that the document
     appears to move up (left) one screenful.  If the button is held down,
     the action auto-repeats.

[5]
     Pressing button 1 over arrow2 causes the view in the associated
     widget to shift down (right) by one unit so that the document appears
     to move up (left) one unit.  If the button is held down, the action
     auto-repeats.

[6]
     If button 2 is pressed over the trough or the slider, it sets the
     view to correspond to the mouse position;  dragging the mouse with
     button 2 down causes the view to drag with the mouse.  If button 2 is
     pressed over one of the arrows, it causes the same behavior as
     pressing button 1.

[7]
     If button 1 is pressed with the Control key down, then if the mouse
     is over arrow1 or trough1 the view changes to the very top (left) of
     the document;  if the mouse is over arrow2 or trough2 the view changes
     to the very bottom (right) of the document;  if the mouse is anywhere
     else then the button press has no effect.

[8]
     In vertical scrollbars the Up and Down keys have the same behavior as
     mouse clicks over arrow1 and arrow2, respectively.  In horizontal
     scrollbars these keys have no effect.

[9]
     In vertical scrollbars Control-Up and Control-Down have the same
     behavior as mouse clicks over trough1 and trough2, respectively.  In
     horizontal scrollbars these keys have no effect.

[10]
     In horizontal scrollbars the Up and Down keys have the same behavior
     as mouse clicks over arrow1 and arrow2, respectively.  In vertical
     scrollbars these keys have no effect.

[11]
     In horizontal scrollbars Control-Up and Control-Down have the same
     behavior as mouse clicks over trough1 and trough2, respectively.  In
     vertical scrollbars these keys have no effect.

[12]
     The Prior and Next keys have the same behavior as mouse clicks over
     trough1 and trough2, respectively.

[13]
     The Home key adjusts the view to the top (left edge) of the document.

[14]
     The End key adjusts the view to the bottom (right edge) of the
     document.

SEE ALSO
========

   `Tk::callbacks|Tk::callbacks' in this node `Tk::Scrolled|Tk::Scrolled'
in this node

KEYWORDS
========

   scrollbar, widget

Create a widget with attached scrollbar(s)
******************************************

NAME
====

   Tk::Scrolled - Create a widget with attached scrollbar(s)

SYNOPSIS
========

       *$whatever* = *$parent*->*Scrolled*(*Whatever*
?,*-scrollbars*=>where? ?,...?);

DESCRIPTION
===========

   To stop a flood of *ScrlWhatever* widgets Perl/Tk introcuded the special
constructor *Scrolled*.  *Scrolled* creates a widget of the given Class
*Whatever* with attached `scrollbar(s)|Tk::Scrollbar' in this node.

OPTIONS
=======

   All options beside *-scrollbars* explained below are passed to the
*Whatever* widget constructor.

-scrollbars
     Expects as argument the position where the scrollbars should be
     created:  w, e or n, s or a combination of them.  If the one or both
     positions are prefixed with o the scrollbar will only show up if
     there is a 'real' need to scroll.

ADVERTISED SUBWIDGETS
=====================

   See `"Subwidget"', see Tk/mega, how to use advertised
widgets.

scrolled
     the scrolled widget

widget
     same as scrolled above.  widget is the kind of widget passed to
     scrolled as first argument in all lowercase.

xscrollbar
     the Scrollbar widget used for horizontal scrolling (if it exists)

yscrollbar
     the Scrollbar widget used for vertical scrolling (if it exists)

corner
     a frame in the corner between the vertical and horizontal scrolbar

BUGS
====

   If a widget does not support *-{x,y}scrollcommand* options, *Scrolled*
does not complain if the specified widget class does not support them.
E.g.,

       *$parent*->*Scrolled*(*'Button'*, ...)

   One does not get an error message or warning when one tries to
configure scrollbars after the widget construction:

       *$ascrolled*->configure(*-scrollbars* => *'e'*);

SEE ALSO
========

   `Tk::Scrollbar|Tk::Scrollbar' in this node

KEYWORDS
========

   scrolled, scrollbar

Search Dialog Widget for Perl/Tk Text.
**************************************

NAME
====

     SearchDialog.pm--Search Dialog Widget for Perl/Tk Text.

SYNOPSIS
========

     use Tk::SearchDialog;

     my $dialog = $mw -> SearchDialog;
     my @searchoptions = $dialog -> Show;

DESCRIPTION
===========

   The Tk::SearchDialog widget pops up a dialog box that allows entry of
search and/or replacement text, and search options.

   The SearchDialog returns a list of ($option, $value) pairs (see below)
when the user clicks the "Search!" button, and undef if the user clicks
the "Cancel" button.

SEARCH OPTIONS
==============

   The SearchDialog returns a list with the following search
specifications.  All specifications are string scalar values.  The
'-option*' options are set to '1' when selected, and '0' or undef if not
selected. Labels and titles are read-only.

-searchstring
-------------

-replacestring
--------------

-optioncase
-----------

-optionregex
------------

-optionbackward
---------------

-optionquery
------------

-entrylabel
-----------

-replacelabel
-------------

-optiontitle
------------

-optcaselabel
-------------

-optregexlabel
--------------

-optbackwardlabel
-----------------

-optquerylabel
--------------

-searchlabel
------------

-cancellable
------------

-accept
-------

BUGS
====

   Allow all option defaults to be set by the calling module.  Should have
some entry validation.

VERSION INFORMATION
===================

   $Id: SearchDialog.pm,v 0.42 2000/12/30 12:02:47 kiesling Exp $

   Author: rkiesling@mainmatter.com <Robert Kiesling>

a widget for choosing a file to read or write
*********************************************

NAME
====

     SelFile - a widget for choosing a file to read or write

SYNOPSIS
========

     use Tk;
     use Tk::SelFile;

     $mw = MainWindow->new;  # As an example.

     $start_dir = ".";       # As an example.
     $sfw = $mw->SelFile(
     		     -directory => $start_dir,
     		     -width     =>  30,
     		     -height    =>  20,
     		     -filelistlabel  => 'Files',
     		     -filter         => '*',
     		     -filelabel      => 'File',
     		     -dirlistlabel   => 'Directories',
     		     -dirlabel       => 'Filter',
     		     -readbutlabel   => 'Read',
     		     -writebutlabel  => 'Write',
     		     -cancelbutlabel => 'Cancel',
     		     );
     Please see the Populate subroutine as the configuration
     list may change.

     ($opcode, $filename) = $sfw->Show;

     $opcode will have the value -readbutlabel (e.g. 'READ'),
     -writebutlabel (e.g. 'WRITE') or -cancelbutlabel (e.g. 'CANCEL').
     An empty string for the text assigned to -readbutlabel or
     -writebutlabel will eliminate that particular button.
     $filename will be a file pathname, or in the case of CANCEL
     it will be a single space character.

     $SFref = $sfw->configure(option => value[, ...])

DESCRIPTION
===========

     This Module pops up a file selector box, with a directory entry
     with filter on top, a list of directories in the current directory,
     a list of files in the current directory, an entry for entering
     or modifying a file name, a read button, a write button, a
     cancel button, a HOME button, and a button to return to the
     starting directory (-directory).

     The button to return to the starting directory is motivated by
     the idea that an application may have a directory unrelated to
     the home directory, e.g. a library of data, that is set to be
     the starting directory.  If the user goes to the home directory,
     the user may not recall the starting directory that was set by
     the application.

     A call to SelFile few (or no options, such as shown below)
     will result in the default values shown in the example
     given in the SYNOPSIS section.  The most uptodate list of
     configuration variables and default values can be found in the
     subroutine Populate as arguments to the subroutine ConfigSpecs.

     $sfw = $mw->SelFile;

     A dialog box error message is generated if the user clicks the
     Read button for a file that does not exist.
     For Write, a dialog box that requests whether the user wishes
     to overwrite the file is generated for a file that already exists.
     Also for Write, a dialog box error message is generated is the
     file name is blank.

     This widget can be configured for requesting a file name to read,
     requesting a file name for writing, or for requesting either.
     For the initial call to SelFile that configures the widget,
     if -readbutlabel is not a member of the argument list, then
     the default value is used (i.e. Read).  If on the other hand
     it is present but specifies an empty string, as shown below
     -readbutlabel   => '',
     then the button is not created.  An analogous rule applies
     to the argument -writebutlabel.

     The file name output is a single space character rather than undef
     when CANCEL is selected so that the user can process the return values
     without checking the values, e.g. storing the result for later use.

AUTHORS
=======

   Based on original FileSelect by Klaus Lichtenwalder,
Lichtenwalder@ACM.org, Datapat GmbH, Munich, April 22, 1995 adapted by
Frederick L. Wagner, derf@ti.com, Texas Instruments Incorporated, Dallas,
21Jun95 further adapted by Alan Louis Scheinine, scheinin@crs4.it, Centro
di Ricerca, Sviluppo e Studi Superiori in Sardegna (CRS4) Cagliari, 14
November 1995

HISTORY
=======

   Alan Scheinine wants to thank David Greaves (davidg@oak.reading.sgi.com)
for pointing out errors and for suggesting improvements.  He also wants to
thank Nick Ing-Simmons (nik@tiuk.ti.com) for sending the soon-to-be
FileSelect for Tk-b9.  This SelFile program diverges from SelectFile with
regard to style but nonetheless has benefited from the ideas and actual
code of SelectFile.

   Future history.  For Tk-b9, "show" and "subwidget" should become "Show"
and "Subwidget" Change $cw->subwidget('dialog')->show;  Tk-b8 to
$cw->Subwidget('dialog')->Show;  Tk-b9

Handlers for Tk::Workspace.pm shell clients.
********************************************

NAME
====

     Tk::Shell.pm -- Handlers for Tk::Workspace.pm shell clients.

DESCRIPTION
===========

   This module is incomplete.

   There's no API or calling synopsis at the moment.  It's primary purpose
is to provide some abstraction, and hopefully data hiding, from the parent
Workspace process.

   Results may be unpredictable due to the I/O buffering behavior of
called programs.  Most programs that have line-oriented output should work
okay.  At this point Workspaces do not understand terminal escape
sequences.

   The buffers of the child process's STDOUT and STDERR pipes are set to
an abnormally high value: 65535 bytes each.  Hopefully that will help
prevent blocking from either channel.  If the programs that you run within
the browser create more output than that, then you'd probably want to run
them in an xterm, anyway.  If your Perl installation doesn't have that
much memory available, you can adjust the numbers (the third argument in
the setvbuf calls) downward, and be more careful of what programs you run.

   Broken pipe errors happen occasionally.  The program prints a message
to the browser's STDERR (that is, on the terminal, unless you've
redirected STDERR from the shell prompt), and goes on, instead of killing
the process that's running the browser.

   This module is tested under several varieties of Linux, and Solaris.
It is untested, and probably unusable, under MS Windoze.

a Tk Perl module for building slide-like presentations.
*******************************************************

NAME
====

   Tk::SlideShow - a Tk Perl module for building slide-like presentations.

DESCRIPTION
===========

   This module provide Perl with the ability to :

   * build interactive and visual presentations with Perl and Tk,

   * build simple slide simply,

   * build sophisticated slides (and even more than PowerPoint one) up to
     real GUI,

   * build structured presentations, precisely computed,

   * take advantage of your knowledge of Perl and Tk for building
     presentations,

   * build portable presentations on all Unix provided with Tk/Perl

   * build presentations that will let the attendees wonder how they will
     do it with Microsoft PP `:-)'.

   * build presentations without leaving your prefered developping
     enviroment : Unix,

   To summarize the philosophy of *Tk::SlideShow*, you have to understand
that slides will be defined and descripted :

in a Perl script,
     for everything that is easier to define in Perl,

interactively (with mouse)
     for everything that is easier to define interactively. These
     informations will be saved automaticaly on slide's specific files -
     in Perl of course.

   In this document, I have tried to interlace a tutorial and a full
description approach. This may sound it a little bit amazing, but I think
it was possible in this case.

FIRST CONTACT
=============

   First of all, to build a presentation with *Tk::SlideShow*, you had
better create a presentation specific directory for keeping all the files
that will be created.

   In this directory, you have to edit the main script : This script will
have to `use Tk::SlideShow;' and some of its methods.

   The init method lets *Tk::SlideShow* self initialize for a new
presentation.  It understands 2 parameters as the sizes (resp. width and
height) of the main window. Without these parameters, the sizes of the
window will be the mawimum sizes of the X11 root. But sometimes, like me,
you have a bigger definition on your Unix desktop than on your laptop. And
perhaps, you will preferably travel the world with your laptop rather than
with your desktop, to show your presentations. So, for example, you will
design your presentation for a definition of `1024x768' instead of
`1600x1280' desktop 21 inch screen. Your script will therefor begin with
something like :

     my $p = Tk::SlideShow->init(1024,768);

   As Larry says often, it's useless to `or die'. Method init return an
instance of class *Tk::SlideShow*. You may feel it useless to use an
instance of *Tk::SlideShow* that will be probably uniq during the life of
the script execution, but this help for internal locality of variables and
also reduce the number of character to type. Now to invoke a
*Tk::SlideShow* method, you will just have to type `$p->method' rather
than `Tk::SlideShow->method' (remember, laziness ...).

   Methods `mw', can, h and w help you to access internals objets and
variables respectively : `MainWindow', Canvas, width and height of it.  In
case you need them you probably had better to insert this small line in
the beginning of your script :

     my ($mw,$c,$h,$w) = ($p->mw, $p->canvas, $p->h, $p->w);

   For pratical reason, I will suppose in future examples that these lines
are at the beginning of my examples scripts without mentioning it.

   Now, I am sure you're dying to know how to create a simple slide. This
is simple, as promised above. Let's look at it first and explain it
afterward :

     $p->save;
     $p->add('hello', sub {
             $p->Text('t1','Hello World !');
     	$p->load;
     });
     $p->play;

   Just try (run) it (remember : As I said before, you have to add lines
at the beginning of your script) !

   While running the script with Perl, it will create a big window
containing a Tk Canvas : in the middle : a text. Note that you are able to
drag the text "Hello World !" with the button 1, where you want it to be.
Pressing key s, you will save its positions. Pressing key q will quit the
presentation. If you play it again, you will find your text at the same
place were you let it just after you press key s. Pressing key space or
`backspace' let's you navigate thru different slides. Here, you just have
one .. so ...

   This is how it looks. Now let's explain what it means :

   First, I call the save method. As described more precisely later, this
make all your slides sensible to a keypress on s for saving the artistic
caracteristics of your slides on a file.

   Then I call method add. This is for pushing a new slide on the pile of
slides. I give to arguments : a name to the slide to reference it later
and because I like to gave a name to what I am creating, and a `codeREF'
which is the real slide definition. This sub will be called when the time
of showing the slide has come.

   Here I put a small text : `Hello world'. note that I do not specify
it's place. I just give the text. I will specify it's place later, during
the *artistic* step of the presentation building. The *artistic*
specifications, by the way, will be loaded when calling method load.

   At the end of my small example, I call the method play to ask
*Tk::SlideShow* to play all the slides in sequence.

   That's all !

   It sounds simple, doesn't it ?

   I'm sure you have tones of questions, for how to do this or that. But
that's not the point of this simple example to answer your questions. It's
just a first contact with *Tk::SlideShow*.

GORY DETAILS
============

   Let's now have a look at all the methods more precisely. I will continue
to give examples, of course.

Method add
----------

   As, I'm sure you have understood : the central method for you is the
add method. This is where you are going to specify your slides.

   As I mention above, this method add a new slide on the pile of already
existing slides.

   You have to give it a uniq name (or id) as a first parameter.  It lets
you reference it in the future more easely (as you will see later). This
name can be whatever a filename (without its directory) can be. Keep in
mind, that the position of most of your objects will be saved in file call
`slide-name.pl', where name will be replace by the first argument to
method add.

   Then you have to give it a sub reference (as a second argument).

Method current
--------------

   During building your presentation, you will probably have to test
several times the look of what you have done and to add artistic value to
it. So, you need a method that helps you to jump to a particular slide,
given its name. This method is current. That's the reason why I recommend
to add a line before the call to method play :

     $p->current(shift || 0);

   So that if your presentation is in file `pres.pl' and you start it like
this,

     prompt-unix> pres.pl hello

   you will directly see the slide named hello. Actually, slides are
internally stored in a ARRAY, and you can also specify the index of your
slide in this ARRAY :

     prompt-unix> pres.pl 2347

   This will accelerate the access to a very big presentation !

Methods save and load
---------------------

   As mention above, these methods deal with persistance of your added
artistic value. So, I am sure you realize how important they are `:-)' !

   The method save may be called, but only once (is needed). It just
indicates to *Tk::SlideShow* that you do want *Tk::SlideShow* to save the
modifications you have done during the presentation until pressing key s.
If this is not what you want, just comment the `$p->save;' line.

   The method load must be called when you want *Tk::SlideShow* to load
what have been saved by method save : mainly, the position of the objects
your are going to define.  You may specify a filename as an argument to
method load (you will see later in this documentation, where this is
relevant), but most of the time this is useless.

   There is (at least) one file per slide that contains positions and
other characteristics of objects (color, fonts). The file will have the
name `slide-xxx' where xxx is the name of the slide (that is the name you
give as a first argument to method add). This file contains a Perl script
that is automaticaly generated by *Tk::SlideShow*. So you will have at
least as many files as you have slides. That's a good reason, I think, for
creating a specific directory for your presentation.

   It may sound obscure that you may have to specify an argument, but we
will see later that it is very usefull in some cases.

   But remember : you call method save once, and method load many times,
often at least once per slide.

Method `bg'
-----------

   This method is used to specify a sub reference that will be called
before playing a slide. It stands for background.

   (This sub will receive the *Tk::SlideShow* object as argument.)

   Here is an example :

     $p->bg( sub {
     		 $c->configure(-background,'chocolate');
     		 $c->createText($w,0,-text,"Olivier Bouteille",
     				-anchor => 'ne',
     				-font => $s->f1,
     				-fill => 'yellow');
     	      });

   Remember $c is a global variable that I suppose you have initialized
previously as mentioned above. It contains the canvas where all objects
will be drawn. That the second and the last time I recall it to you.

   In this example, this is clear that you like chocolate ... as a color
for the background of you presentation, and that you like to insist on the
fact that you are the author of the presentation `:-)'.

   For simplicity I have added the possibility to specify only a color as
an argument instead of a sub reference. So :

     $p->bg('chocolate');

   will work as a simplify expression of

     $p->bg( sub {$c->configure(-background,'chocolate')};

General look of your presentation script
----------------------------------------

   To summarize what you have learned up to now, here's the look of the
script of your presentation :

     use Tk::SlideShow;

     my $p = Tk::SlideShow->init(1024,768);
     $p->save;
             my ($mw,$c,$h,$w) = ($p->mw, $p->canvas, $p->h, $p->w);

     $p->add('menu',         sub { ...; $p->load });
     $p->add('introduction', sub { ...; $p->load });
     ...
     $p->add('development',  sub { ...; $p->load });
     $p->add('conclusion',   sub { ...; $p->load });

     $p->current(shift || 0);
     $p->play;

   Now you should be able to build any presentation. But it would be to
tedious to specify everything. So there are some more concept in
*Tk::SlideShow* that will help your expression.

Sprites
=======

   Sprites are graphics objects that you can place or change interactively
on a slide.  You describe it in Perl, and you place it with the mouse.
Sometimes you can also modify there shape interactively. The
characteristics that will be modified interactively will be called *IC*
(i.e. Interactive Characteristique) of Sprites in this document.

   These objects may be as complicated as Tk canvas drawing. They are
composed of Tk/Canvas items.

   Each *Sprite* has a name (an identifier) as they are very important for
*Tk::SlideShow*. This name has to be uniq in a slide, but you can reuse it
in differents slides. In a first approach, the syntax for the is a string
without a character /. In fact this character is possible but it has a
special meaning for *Tk::SlideShow* as we will see it later. The name will
be used to tag (in the sens of Tk tags) every canvas items composing a
*Sprite*.

   There is a set of methods that can be applied on them.

   *Tk::SlideShow* provide some builtin Sprites, but you can add some more
*Sprite*.

   After being described in the Perl script, they aspect and position my
be modified during running the presentation.

builtin Sprites
---------------

   You have already met a *Sprite*, without knowing it : The Text
*Sprite*. You create a Text *Sprite* by calling the method Text on the
*Tk::SlideShow* object. This is very simple :

     $p->Text('ident', 'text body', @options);

   The ident is mandatory. `@options' are optionals and directly passed to
Tk when creating a canvas text item. So, look at Tk documentation to know
what options you can use.

   What has been done for text has also been done for image.  The syntax
is as follow :

     $p->Image('ident','filename.gif',@options);

   and for animated images :

     $p->Anim('ident','filename.gif',@options);

   Specificaly for the *Sprite* Text, I have added an interactive font
family chooser and a color chooser. You may access it by double clicking
respectively with button 1 and 2 on the `Sprite' text itself.. I'm not
sure, this functionnality is necessary : I usualy prefer to have a
structured access (i.e. in the script) to font families and color.

   Now, here is a more useful definition of a slide :

     $p->add('menu', sub {
        $p->Text('title','Abstract',-font => $p->f3);
        my $i = 0;
        for (split(/,/,'Introduction,Development,Conclusion')) {
     	$p->Text("i$i",$_,$p->f1); $i++;
        }
        $p->load;
     });

   Here are some comments on this slide definition :

   * Here, I have not been structured but rather PowerPoint oriented.
     Actually, there will probably have more than one slide with such a
     title in a presentation. So, it would have been better to define a
     sub like this :

          sub title { $p->Text('title',shift,-font => $p->f3);}

     and call it at the beginning of each of my slides containing a title !
     So, if I want to change the color of my titles, I will have to do it
     just once.

   * For the same reasons, it would have been more structured to :

          sub items {
                     my $i = 0; for (@_) {$p->Text("item$i",$_, $p->f1); $i++}
          }

   * Nothing in this example specify any position. This will be done
     later, during the execution. But I am sure you have already understand
     it, since I already mention it  several times.

   So, a more suitable definition of the slide would be something like :

     $p->add('summarize', sub {
             titre('Menu');
     	items(qw(Introduction Development Conclusion));
             $p->load;
     });

   Simple, isn't it ?

   There exists some more *Sprite* in *Tk::SlideShow*, but their
definition is so simple that I think it will be more suitable to look at
the code in the file `Tk/SlideShow/Sprite.pm' and think of it as
custumable examples.

adding your own *Sprite*
------------------------

   Yes it's possible. Actually, this is very simple. Just have a look at
`Tk/SlideShow.pm' and you will find that it takes only a few lines to do
it, or to reuse it.

   A *Sprite* is just a Perl object with an identifier that is also used
as Tk tag. It store a relative coordinates `x,y)', tag name, and all
others IC. It knows how to give a Perl persistant string of itself.

   You can add characteristic to this object either by inheriting class
`Tk::SlideShow::Sprite', or by simply adding keys to the Perl object
(which is not very academic !).

   Let's take examples :

Example 1
---------

   Imagine you want to create a new kind of *Sprite*. A little logo that
symbolise a man in front of a computer.

   Here's the function you may write :

     sub compuman { # given an id as a standalone argument
       my $s = $p->newSprite(shift);
       my $id = $s->id;
                 # here are options
       my @o1 = (-width ,4,-fill, 'black', -tags ,$id);
       my @o2 = (-fill,'blue', -tags ,$id);
       my @o3 = (-width ,4,-fill,'red', -tags ,$id);
                 $c->createLine(qw(10 20 10 40 25 40 25 50),@o1);      # chair
       $c->createLine(qw(15 15 15 35 30 35 30 50 35 50),@o1);# body
                 $c->createOval(qw(11 11 18 18),@o2);		  # head
       $c->createLine(qw(15 25 30 25),@o1);		  # feet
       $c->createLine(qw(30 27 40 22),@o3);		  # keyboard
       $c->createPolygon(qw(35 20 40 0 55 10 55 20),@o3);	  # screen
                 $c->createLine(qw(45 20 45 30 35 30 35 30),@o3);	  # screen foot
       $s->pan(1);
       return $s;
               }

   What this example shows is :

   * The `compuman' sub argument is an identifier that will be use as Tk
     tag,

   * The drawing as been design by hand on a small paper. The origin is
     (0,0) by convention,

   * I've created a new *Sprite* using method `newSprite'. I pass the id
     of the *Sprite*,

   * I turn the *Sprite* pannable (or *draggable* with button) with button
     1 by using method `pan' on it,

   * Coordinates are from (0,0) to (45,50) but you will be able to place
     where you want in the slide.

   Once this little function written, I can use it everywhere in the
presentation, to place computer men symbols as many times as I'd like.  I
will be able to place it interactively, and to save it's position pressing
on the s key.

Example 2
---------

   Imagine you would like to have text surrounded by a frame, and with a
special color background, that you will reused a lot in your presentation.
Here is the kind of function you may write :

     sub framed {
       my ($id,$text) = @_;
       my $s = $p->newSprite($id);
       my $idw = $c->createText(0,0,'-text',$t, -justify, 'center',
     		   -font => $p->f1, -tags => $id);
       $c->createRectangle($c->bbox($idw), -fill,'light blue',-tags => $id);
       $c->raise($idw);
       $s->pan(1);
       return $s;
     }

   Then, each time in a definition, you would like to have such a framed
text, then just call `framed' like this.

     frame ('id1',"This is an\nImportant message");

Example 3
---------

   Let's have an other example, a more classic example.  Imagine you want
to explain a source example (perl, of course) in your presentation.  You
will probably want to have a *Sprite* specialized representing these
scripts examples. To be consistant, you want it to look very similar in
the whole presentation slides. Even perhaps in all the presentations you
will build in your job, or even ... your life (horror !)

   Here's what you can do :

     sub example { # given the id and the text of the script
               my ($id,$t) = @_;
       my $s = $p->newSprite($id);
       my @t = (-tags => $id);
       # here is the label of the script
       $c->createText(0,0,-text,'Script example', -font => $p->f1,
     		 @t, -anchor => 'sw');
       # the text of the script example
               my $idw = $c->createText(0,0,-text,$t,-font => $p->ff1, @t,
     		  -anchor => 'nw');
       # a rectangle around the example with a nice background
       $c->createRectangle($c->bbox($idw), -fill,'light green',$p);
       $c->raise($idw);
       $s->pan(1);
       return $s;
     }

   Here, I've created an new *Sprite*, which consists of a 2 text items.
One with a fixe text : `Script Example' and one with the the text of the
example which is passed as an argument to the function.

   Note that font used for these texts (`f1' and `ff1') will be explained
later.

Example 4
---------

   Let's animate our Sprites, now. Here's something that will be difficult
to do with PowerPoint, as far as I know.

   Let's look at this function :

     sub ticker {
       my ($id,$text) = @_;
       my $s = $p->newSprite($id>->pan(1);
       my $idw = $c->createText(0,0,-text,$text,
     			       -font => $p->f1, -tags => $id,);
       sub wrap_round {
     	my $tag = shift;
     	my $t = $c->itemcget($tag,-text);
     	$c->dchars($tag,'0');			# delete the first  character.
     	$c->insert($tag,'end',substr($t,0,1));  # add it at the end of string.
     	$c->after(100,[\&wrap_round,$tag]);
       }
       wrap_round($idw);
       return $s;
     }

   This function create a new type of *Sprite* that display a single line
of text that looks like a ticker tape. For animation, I use the *Tk/after*
method, of course.

   Simple and powerful, isn't it : This is just Perl and Tk !

Managing progression in the slide discovery
===========================================

   Often, you'd like to explain progressively a complex slide. So, you'd
like to let Sprites appear in a particular order, so that attendees will
discover the complex slide progresively.

   *Tk::SlideShow* provides you with the ability to let the Sprites appear
progresively as you press button 3 of your mouse. They will appear,
slipping from top, bottom, left or right edge of the slide.

   Here's how to do it (reusing the subs title and items decribed
previously) :

     $p->add('menu', sub {
        titre('MENU');
        items('Introduction','Development','Conclusion');
        # ....
        $p->load;
        $p->a_bottom('titre');
        $p->a_left(map{"item$_"}(0..2));
     })

   What we see here is that after loading the position of our title and
items, I ask for title to appear slipping from bottom to it's place when I
will press button 3. If I press it again and again, I will see the items
arriving on my slide, slipping for the left side of it to there final
place. You may have used as well method `a_right' or `a_top' for making
them arrive repectively from right or from top side of the slide. Note
that you can play back this evolution by pressing `Control-Button-3'.

   If you need to let several Sprites enter the slide together, then just
give an `refARRAY' of tags of these Sprites instead of just one tag. As an
example you may try, just add [] around map instruction in the previous
example :

     $p->a_left([map{"item$_"}(0..2)]);

   You will see that the 3 items will arrive on the slide simultaneously !

   You are also able to let appear a  *Sprite* suddenly by using method
`a_warp'.

   Sometimes you may want to make a *Sprite* leave the slide. Just replace
the prefix `a_' (standing for arrive) by `l_' (standing for leaving).

   Sometimes, it is useful to show a *Sprite* evolving thru a path.  This
is done by using method `a_multipos'. You have to give it a number of
position, the *Sprite* have to take. It will move from one position to
another by clicking on button 3. As usual you don't have to specify in the
script the coordinates of the positions. Just the number of position. When
you play the slide for the first time, the *Sprite* will stand in a
default position. Just drag it where you wan't it to be with button 1. Do
this for each position. Then save it (press s key). It will remenber where
you have *mouse-ly* specified each position.  The script example is
trivial :

     $p->add('workflow', sub {
        titre('WorkFlow');
        $p->Image('adoc','document.gif');
        # ....
        $p->load;
        $p->a_multipos(10);
     }

   That will help describing the different stage of a document in workflow
system, for example. Here, the document will have 10 differents position,
it will remember.

   You may want to specify the positions explicitly (computed, e.g.) in
the script. This is posible, of course. Just use the method `multipos' on
the *Sprite* object, and give an ARRAY of the positions just like you will
define a line in a Tk canvas.

Linking Sprites
===============

   It's often useful to link *Sprite* together, with a line, or an arrow or
whatever.

   *Tk::SlideShow* provide you with this ability.

   For example, to link two Sprites with a simple line with a title on the
middle of the line, just call method `newLink' as follows :

     $p->newLink($sprite1,$sprite2,'Title');

   Interactively, you will be able to change the attach point of the link
(here, a line) by clicking on the line, with Button 1 or 3. The attach
point will turn around the bounding box of the *Sprite*, successively
following the eigth cardinals points (nw, n, ne, e, se, s, sw, w).

   If you want an simple arrow, replace Link by Arroa, a Double
arrowreplace Link by DblArrow.

     $p->newArrow($sprite1,$sprite2,"Titre");
     $p->newDblArrow($sprite1,$sprite2,"Titre");

   Note that you can change IC of arrows shape using keyboard `Up',
`Down', `Left', `Right' when mouse is over the arrow, and their Control
counter part if the mouse is on the arrow.

   You can also change the attach (cardinal) point of the arrow (which
inherit from link) on each *Sprite* it links together, by clicking button
1 or 3 on the arrow.

   You can even add your new way of linking Sprites. As an example, I
provide in *Tk::SlideShow* a method `newOrg' that will helps you to create
hierarchical organisation graph. Look at Tk::SlideShow examples to see how
it looks.  Look at `Tk/SlideShow.pm' definition of `newOrg' method to see
how in less than 20 lines it is done, and at the example below, using Org
*Sprite*.

hyperlinks
==========

   Sometimes it may be useful to jump from one slide to another by
clicking on a *Sprite*. This is also implemented. Here's how to do it.

     $p->warp('i1','<Double-1>', 'introduction');

   In this example, if you double click with button 1 on *Sprite* i1, you
will jump directly to slide named `introduction'.

Big Fontes
==========

   X11 is not so much provided with big fonts, such as these one you want
to use for a presentation. So you have to take a scalable font and to
resize it. *Tk::SlideShow* provide you with a minimal set of fonts.

   There are severals methods for that, used in my previous examples :

f
     This method return a scalable `charter' font of a point size of 150.
     If you give it an argument, this will be taken to be multiplied to
     150. The family used by default is `charter'. You may change this
     default family by using the method family with the new family as
     argument. The list of family depends on your distribution of X11. On
     my Linux box I have approximatly 20 family that are all free fonts.

     Here's where you may get these nice and funny fonts :

     ftp://ftp.gimp.org/pub/gimp

f1, f2, ..., f5
     These method return proportional fonts bigger and bigger, that I feel
     sufficient for my presentations.

ff1, ff2, ... ff5
     These methods return fixed fonts bigger and bigger, that I feel
     sufficient for my presentations.

Sprites id with /
=================

   Sprites interactive characteristics (IC) are stored in slide id
dependent file. For example, in a slide called menu, Sprites IC will be
stored in file `slide-menu.pl'. If you want these Sprites IC not to be
stored in slide id dependent file, you just have to prefix the *Sprite* id
with the name of the file followed by a /. For example, a *Sprite* called
`org/i1' will see its IC be stored in file `org'.

   The reason for this functionnality, is that there are case where you
would like to resuse Sprites, in severals Slides.

   Here are some examples :

Example 1
---------

   Imagine you want you presentation to have on all slides (or most of
them) the menu of it on the right side of each slide. You may define this
variable at the begining of your script :

     my @plan = (
     	    'intro'      => "Introduction",
     	    'pos'        => "Position of the problem",
     	    'present'    => "Presentation",
     	    'dev'        => "Development",
     	    'solutions'  => "Solutions",
     	    'conclusion' => "Conclusion" );

   Left members stand for slide identifiers, and right members are text
you will see on the slide.

   So, you may write this small sub :

     sub small_summarize {
       my $count = 0;
       my @p = @plan;
       while(@p) {
         my ($slide,$title) = (shift @p, shift @p);
         my $id = "som/i$count";
         $p->Text($id,$title, -font, $p->f1, -fill,'blue', -anchor,'w');
         $p->warp($id,'<Double-1>',$diapo);
         $count ++;
       }
       $p->load('som'); # this load only place for sprites names som/...
     }

   You learn here that you can get the current id of the slide being
played, with method `currentName'.

   You will have to call the `small_summarize' method at the begin of each
slide definition.

   Interactively, the first time you will see the small menu, you will be
able to place it manually, and save it (by pressing s key). Then, each
time you will reuse this sub, Sprites define in will be placed at the same
position. This is achieved because of the fact that the *Sprite* ids
starts with string `som/' so that there IC will be stored in file `som'.

Exemple 2
---------

   Imagine now that you would like to present your organisation.  You
would like to show your organisation graph one each slide.

   You describe you organisation in a Perl variable :

     my %org = ( 'a' => "Computer\nService",
     	    'a.b' => "Design\nDepartment",
     	    'a.c' => "Develop\nDepartment");

   You may use the `framed' *Sprite* define above to put the entities
description.

     sub org {
       my %sprites;
       # creating boixes
       $sprites{$name}= $p->Framed("org/$name",$desc)
         while my($name,$desc) = each %org ;

     # creating links
     while(my($name,$sprite) = each %sprites) {
       my ($sup) = ($name =~ /(.*)\.\w+/);
       $p->Org($sprite,$sprites{$sup})
     		if exists $sprites{$sup};
     }
     $p->load('org');
     	}

   You will have to place your boxes as you like during a first try of
playing your slides (as usual now).

   Then you will just have to call sub `org' at the beginning of each
slide you would like this graph to be seen.

   Note that :

   * It is simple to change the color of the box entity depending on the
     name of the slide describing this entity,

   * You can mix example 1 and 2,

   * You can easily make box entities hyperlinks to slides.

DOCUMENTATION
=============

   As far as I am concerned, I feel that considering a paper copy of
slides as a documentation of a presentation is non sense. You have to add
your speach added value to it. That's why, in case I want to let some
documentation, I like to add to my presentation, a documentation to each
slides. This helps me also to prepare the presentation.

   To add documentation to my slides, I have choosen to use html as a
language. Maybe in a future release, somebody else will want to express
attach documentation to slide in a different language (maybe pod).

   So, that's the reason for the method html on a `Tk::SlideShow::Diapo'
object.

   To let you add an header and a footer to your presentation paper, I
have added 2 methods for the `Tk::SlideShow' object : `htmlheader' and
`htmlfooter'.

   To output the whole documentation on a file, you may use the method
html on the `Tk::SlideShow' object (note that this is not on the
`Tk::SlideShow::Diapo' object this time). This method take the name of a
directory where it will produce differents snapshots of your slides, plus
HTML documentation explicitly attached to each slides (or
Tk::SlideShow::Diapo).

   Note that the technic used to snapshot your slides is by using the X11
command `xwd'. Then it is converted in GIF image format, so that your
images will be viewable on most of browsers. As for now, I use convert
(from ImageMagick) to convert xwd to gif format as well as for realizing
the thumbnail.

   So to sumarize this here's the look of a more complete example of a
`Tk::SlideShow' script :

     use Tk::SlideShow;

     my $p = Tk::SlideShow->init(1024,768);
     $p->save;
             my ($mw,$c,$h,$w) = ($p->mw, $p->canvas, $p->h, $p->w);
     my $d; # stands for a diapo.
     $d = $p->add('menu',         sub { ...; $p->load });
     $d->html('blah blah on the menu slide');
     $d = $p->add('introduction', sub { ...; $p->load });
     $d->html('blah blah on the introduction slide');
     ...
     $d = $p->add('development',  sub { ...; $p->load });
     $d->html('blah blah on the development slide');
     $d = $p->add('conclusion',   sub { ...; $p->load });
     $d->html('blah blah on the conclusion slide');

     if (grep (/-html/,@ARGV)) {
       $p->html("doc");
       exit 0;
     }

     $p->current(shift || 0);
     $p->play;

SYNOPSIS
========

   Here is a summurized synopsis of *Tk::SlideShow* methods.  Remember
that it is an alpha stage release. I hope the API will not change, but it
is not garanteed (by me) up to now. So if you already use this interface
for building presentation, you'd better keep the file `SlideShow.pm' used,
not to far.

Base Level
----------

     use Tk::SlideShow;
     my $p = Tk::SlideShow->new;	# initialize canvas according
     				# to the current screen
     $p->bg(?sub|color?);          # change background
     my $d = $p->add(?'nom',sub);  # add a slide
     $d->html('..');		# add html documentation
     my ($mw,$c,$h,$w) = ($p->mw,$p->canvas,$p->h,$p->w);
     				# retrieve context variables
     $p->current(?slideid);	# retrieve/set current slide
     $p->currentName;		# retrieve current Name of the slide
     $p->warp($spriteid,$tkevent,$slideid);
     			# jump on slideid in case of tkevent on spriteid
     $p->save;		# make the presentation save-able by pressing 's'
     $p->load(?file)	# load sprites locations from file or
     			# default slide file
     $p->play;		# play the slides

     $p->a_top(sprideid,...);
     $p->a_left(spriteid,...);
     $p->a_bottom(spriteid,...);
     $p->a_right(spriteid,...);
     			# make designated sprites arrive on the slide
     			# from top left bottom or right
     			# sequencialy in this order
     			# on button3 click.
     $p->l_top(sprideid,...);
     $p->l_left(spriteid,...);
     $p->l_bottom(spriteid,...);
     $p->l_right(spriteid,...);
     			# make them leave the slide instead of arrive
     $p->a_multipos(spriteid,nbposition);
     			# make the spriteid evolve on a button 3 click thru
     			# up to nbposition

     $p->html('directory')	# produces on complete html documentation
     $p->htmlheader(?header?);
     $p->htmlfooter(?footer?);
     			# get/set documentation header/footer

Sprites
-------

     $p->newSprite($id);	 # create an empty sprite
     $p->Text($id,$texte,@texte_options);
     			 # return a predefined Text sprite
     $p->Window($id,$widget,$canvas_widget_options);
     			 # Predefined tk window Sprite
     $p->Image($filename);  # Predefined Image Sprite
     $p->Anim($filename);   # Predefined Animation GIF Sprite

AUTHOR
======

   Olivier Bouteille (bouteille@dial.oleane.com)

   Will you be kind enough to excuse my poor english, and send me
corrections.

SEE ALSO
========

   Perl(1). et *Tk/perl*

a geometry manager for scaling two subwidgets
*********************************************

NAME
====

   Tk::SplitFrame - a geometry manager for scaling two subwidgets

SYNOPSIS
========

     use Tk;

     use Tk::SplitFrame;

     my $MainWindow = MainWindow->new();

     my $SplitFrame = $MainWindow->SplitFrame
        (
         '-orientation' => 'vertical',
         '-trimcolor'  => '#c7c7c7',
         '-background'  => 'white',
         '-sliderposition' => 60,
         '-borderwidth' => 2,
         '-sliderwidth' => 7,
         '-relief'      => 'sunken',
         '-height'      => 100,
         '-width'       => 100,
         '-padbefore'   => 0,
         '-padafter'    => 0
        );

     # Values shown above are defaults.

     my $LeftLabel = $SplitFrame->Label ('-text' => 'Left');

     my $RightLabel = $SplitFrame->Label ('-text' => 'Right');

     $SplitFrame->pack (-expand => true, -fill => both);

     $SplitFrame->configure ('-sliderposition' => 22);

     Tk::MainLoop;

DESCRIPTION
===========

   A SplitFrame is a geometry manager for the two subwidgets instantiated
against it. It has a sliding divider between them which, when moved,
resizes them so that they each remain in contact with it.

   The divider can be arranged vertically or horizontally at create time.
The children our arranged in the order that they are instantiated, from
left to right or from top to bottom. After instantiation, the order is
fixed. The children should NOT be packed or placed, the split frame is
responsible for this.

   The split frame will adjust itself initially to the preferred size of
the children.

   It is a basic frame itself and can be packed or placed wherever needed
in other frames or toplevel windows.

AUTHORS
=======

   Damion K. Wilson, dkw@rcm.bm

   Based on the split windows that you see all the time in Windows, Mac,
Java, etc.

HISTORY    October 1997: Actually started using it
==================================================

a X/TK digital clock widget based on strftime.
**********************************************

NAME
====

   Tk::StrfClock - a X/TK digital clock widget based on strftime.

SYNOPSIS
========

     use Tk::StrfClock;

     $top->StrfClock(
     	-format	=> <strftime format string>,
     	-update => [<seconds>|s|m|h|d],
     	-advance => [<seconds>],
     );

DESCRIPTION
===========

   Tk::StrfClock is a digital clock widget, with all the other attributes
of a Tk::Label.

OPTIONS
=======

-format => <strftime format string>
-----------------------------------

     Sets the required date/time format using POSIX strftime format.
     The default is "%I:%M:%S%p, %A, %e %B %Y.".

-update => <seconds>|s|m|h|d|a
------------------------------

     Sets how often the clock is updated.  If set to the characters
     s, m, h, d or a then the clock is updated exactly on the second,
     minute, hour, day or is automatically guessed.

     The default is 'a'.

-advance => <seconds>
---------------------

     Sets the clock fast or slow this many seconds. The default is
     0.

Other Tk::Label options.
------------------------

MINIMAL EXAMPLE
===============

     use Tk;
     use Tk::StrfClock;

     my $top=MainWindow->new();
     $top->StrfClock()->pack();
     MainLoop();

TESTING
=======

     Run the module itself to start a test program.
     To increase the size of the fond add something like

     *StrfClock*font: -*-fixed-medium-r-normal--20-*-*-*-*-*-*-*

     to your .Xdefaults file.

add aliases for tk sub-commands
*******************************

NAME
====

   Tk::Submethods - add aliases for tk sub-commands

SYNOPSIS
========

     use Tk::Submethods ( 'command1' => [qw(sub1 sub2 sub3)],
                          'command2' => [qw(sub1 sub2 sub3)]);

DESCRIPTION
===========

   Creates `->commandSub(...)' as an alias for `->command('sub',...)'
e.g. `->grabRelease' for `->grab('release')'.

   For each command/subcommand pair this creates a closure with command
and subcommand as bound lexical variables and assigns a reference to this
to a 'glob' in the callers package.

   Someday the sub-commands may be created directly in the C code.

Constants for Sun's Drag&Drop protocol
**************************************

NAME
====

   Tk::DragDrop::SunConst - Constants for Sun's Drag&Drop protocol

DESCRIPTION
===========

   This module defines symbolic name subs for the numeric constants that
make up Sun's Drag&Drop protocol. They are in this module with Exporter as
they are shared between the two halves (Dropper and Receiver) of the
protocol.

A Titled Frame widget
*********************

NAME
====

   Tk::TFrame - A Titled Frame widget

SYNOPSIS
========

     use Tk::TFrame;

     $frame1 = $parent->TFrame(
     	-label => [ -text => 'Title' ]
     	-borderwidth => 2,
     	-relief => 'groove'
     );

     # or simply
     $frame2 = $parent->TFrame(
        -label => 'Title'
     );

     $frame1->pack;
     $frame2->pack;

DESCRIPTION
===========

   *Tk::TFrame* provides a frame but with a title which overlaps the border
by half of it's height.

SEE ALSO
========

   `Tk::LabFrame|Tk::LabFrame' in this node

AUTHOR
======

   Graham Barr <`gbarr@pobox.com'>

COPYRIGHT
=========

   Copyright (c) 1997-1998 Graham Barr. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Create and manipulate Tix Tabular List widgets
**********************************************

NAME
====

   Tk::TList - Create and manipulate Tix Tabular List widgets

       *$tlist* = *$parent*->*TList*(?options?);

SUPER-CLASS
===========

   None.

STANDARD OPTIONS
================

*-background*	*-borderwidth*	*-class*	*-cursor*	*-foreground*
*-font*	*-height*	*-highlightcolor*	*-highlightthickness*
*-relief*	*-selectbackground*	*-selectforeground*
*-xscrollcommand*	*-yscrollcommand*	*-width*

   See Tk/options, for details of the standard options.

WIDGET-SPECIFIC OPTIONS
=======================

Name:	*browsecmd*
Class:	*BrowseCmd*
Switch:	*-browsecmd*
     Specifies a perl/Tk callback to be executed when the user browses
     through the entries in the TList widget.

Name:	command
Class:	Command
Switch:	*-command*
     Specifies the perl/Tk callback to be executed when the user invokes a
     list entry in the TList widget. Normally the user invokes a list
     entry by double-clicking it or pressing the Return key.

Name:	*foreground*
Class:	*Foreground*
Switch:	*-foreground*
Alias:	*-fg*
     Specifies the default foreground color for the list entries.

Name:	height
Class:	*Height*
Switch:	*-height*
     Specifies the desired height for the window in number of characters.

Name:	*itemType*
Class:	*ItemType*
Switch:	*-itemtype*
     Specifies the default type of display item for this TList widget. When
     you call the insert methods, display items of this type will be
     created if the *-itemtype* option is not specified.

Name:	orient
Class:	*Orient*
Switch:	*-orient*
     Specifies the order of tabularizing the list entries. When set to
     "*vertical*", the entries are arranged in a column, from top to
     bottom. If the entries cannot be contained in one column, the
     remaining entries will go to the next column, and so on. When set to
     "*horizontal*", the entries are arranged in a row, from left to
     right. If the entries cannot be contained in one row, the remaining
     entries will go to the next row, and so on.

Name:	*padX*
Class:	*Pad*
Switch:	*-padx*
     The default horizontal padding for list entries.

Name:	*padY*
Class:	*Pad*
Switch:	*-padx*
     The default vertical padding for list entries.

Name:	*selectBackground*
Class:	*SelectBackground*
Switch:	*-selectbackground*
     Specifies the background color for the selected list entries.

Name:	*selectBorderWidth*
Class:	*BorderWidth*
Switch:	*-selectborderwidth*
     Specifies a non-negative value indicating the width of the 3-D border
     to draw around selected items.  The value may have any of the forms
     acceptable to *Tk_GetPixels*.

Name:	*selectForeground*
Class:	*SelectForeground*
Switch:	*-selectforeground*
     Specifies the foreground color for the selected list entries.

Name:	*selectMode*
Class:	*SelectMode*
Switch:	*-selectmode*
     Specifies one of several styles for manipulating the selection.  The
     value of the option may be arbitrary, but the default bindings expect
     it to be either single, browse, multiple, or *extended*; the default
     value is single.

Name:	*sizeCmd*
Class:	*SizeCmd*
Switch:	*-sizecmd*
     Specifies a perl/Tk callback to be called whenever the TList widget
     changes its size. This command can be useful to implement "user scroll
     bars when needed" features.

Name:	state
Class:	State
Switch:	*-state*
     Specifies whether the TList command should react to user actions. When
     set to "normal", the TList reacts to user actions in the normal way.
     When set to "disabled", the TList can only be scrolled, but its
     entries cannot be selected or activated.

Name:	width
Class:	Width
Switch:	*-width*
     Specifies the desired width for the window in characters.

DESCRIPTION
===========

   The *TList* method creates a new window (given by the $widget argument)
and makes it into a TList widget.  Additional options, described above,
may be specified on the command line or in the option database to
configure aspects of the TList widget such as its cursor and relief.

   The TList widget can be used to display data in a tabular format. The
list entries of a TList widget are similar to the entries in the Tk
listbox widget. The main differences are (1) the TList widget can display
the list entries in a two dimensional format and (2) you can use graphical
images as well as multiple colors and fonts for the list entries.

   Each list entry is identified by an index, which can be in the
following forms:

number
     An integer that indicates the position of the entry in the list. 0
     means the first position, 1 means the second position, and so on.

end
     Indicates the end of the listbox. For some commands this means just
     after the last entry; for other commands it means the last entry.

*@*x,y
     Indicates the element that covers the point in the listbox window
     specified by x and y (in pixel coordinates). If no element covers that
     point, then the closest element to that point is used.

DISPLAY ITEMS
=============

   Each list entry in an TList widget is associated with a display item.
The display item determines what visual information should be displayed
for this list entry. Please see Tk/DItem, for a list of
all display items.

   When a list entry is created by the insert command, the type of its
display item is determined by the *-itemtype* option passed to these
commands. If the *-itemtype* is omitted, then by default the type
specified by this TList widget's *-itemtype* option is used.

WIDGET METHODS
==============

   The *TList* method creates a widget object.

   This object supports the configure and cget methods described in
Tk/options, which can be used to enquire and modify the
options described above.  The widget also inherits all the methods
provided by the generic `Tk::Widget|Tk::Widget' in this node class.

   The following additional methods are available for TList widgets:

*$tlist*->*anchorSet*(index)
     Sets the anchor to the list entry identified by index. The anchor is
     the end of the selection that is fixed while dragging out a selection
     with the mouse.

*$tlist*->*anchorClear*
     Removes the anchor, if any, from this TList widget. This only removes
     the surrounding highlights of the anchor entry and does not affect its
     selection status.

*$tlist*->delete(*from, *?to?)
     Deletes one or more list entries between the two entries specified by
     the indices from and to. If to is not specified, deletes the single
     entry specified by from.

*$tlist*->*dragsiteSet*(index)
     Sets the dragsite to the list entry identified by index. The dragsite
     is used to indicate the source of a drag-and-drop action. Currently
     drag-and-drop functionality has not been implemented in Tix yet.

*$tlist*->*dragsiteClear*
     Remove the dragsite, if any, from the this TList widget. This only
     removes the surrounding highlights of the dragsite entry and does not
     affect its selection status.

*$tlist*->*dropsiteSet*(index)
     Sets the dropsite to the list entry identified by index. The dropsite
     is used to indicate the target of a drag-and-drop action. Currently
     drag-and-drop functionality has not been implemented in Tix yet.

*$tlist*->*dropsiteClear*
     Remove the dropsite, if any, from the this TList widget. This only
     removes the surrounding highlights of the dropsite entry and does not
     affect its selection status.

*$tlist*->*entrycget*(*index, option*)
     Returns the current value of the configuration option given by option
     for the entry indentfied by index. Option may have any of the values
     accepted by the insert method.

*$tlist*->*entryconfigure*(*index, *?option?, *?value, option, value, ...*?)
     Query or modify the configuration options of the list entry identified
     by index. If no option is specified, returns a list describing all of
     the available options for index (see *Tk_ConfigureInfo* for
     information on the format of this list). If option is specified with
     no value, then the method returns a list describing the one named
     option (this list will be identical to the corresponding sublist of
     the value returned if no option is specified). If one or more
     *option-value* pairs are specified, then the command modifies the
     given option(s) to have the given value(s); in this case the method
     returns an empty string.  Option may have any of the values accepted
     by the insert method. The exact set of options depends on the value
     of the *-itemtype* option passed to the the insert method when this
     list entry is created.

*$tlist*->insert(*index, *?*option, value, ...*?)
     Creates a new list entry at the position indicated by index. The
     following configuration options can be given to configure the list
     entry:

    *-itemtype* => type
          Specifies the type of display item to be display for the new list
          entry. type must be a valid display item type. Currently the
          available display item types are image, *imagetext*, text, and
          $widget. If this option is not specified, then by default the
          type specified by this TList widget's *-itemtype* option is used.

    *-state* => state
          Specifies whether this entry can be selected or invoked by the
          user.  Must be either normal or disabled.

    *-data* => data
          Arbitrary data to be associated with the entry (a perl scalar
          value).

     The insert method accepts additional configuration options to
     configure the display item associated with this list entry. The set
     of additional configuration options depends on the type of the display
     item given by the *-itemtype* option. Please see Tk/DItem,
     for a list of the configuration options for each of the
     display item types.

*$tlist*->info(*option, **arg, ...*)
     Query information about the TList widget. option can be one of the
     following:

    *$tlist*->info(*anchor, *index)
          Returns the index of the current anchor, if any, of the TList
          widget. If the anchor is not set, returns the empty string.

    *$tlist*->info(*dragsite, *index)
          Returns the index of the current dragsite, if any, of the TList
          widget. If the dragsite is not set, returns the empty string.

    *$tlist*->info(*dropsite, *index)
          Returns the index of the current dropsite, if any, of the TList
          widget. If the dropsite is not set, returns the empty string.

    *$tlist*->info(selection)
          Returns a list of selected elements in the TList widget. If no
          entries are selected, returns an empty string.

*$tlist*->nearest(*x, y*)
     Given an *(x,y)* coordinate within the TList window, this command
     returns the index of the TList element nearest to that coordinate.

*$tlist*->see(index)
     Adjust the view in the TList so that the entry given by index is
     visible. If the entry is already visible then the command has no
     effect; otherwise TList scrolls to bring the element into view at the
     edge to which it is nearest.

*$tlist*->selection(*option, **arg, ...*)
     This command is used to adjust the selection within a TList widget. It
     has several forms, depending on option:

    *$tlist*->*selectionClear*(?from?, ?to?)
          When no extra arguments are given, deselects all of the list
          entrie(s) in this TList widget. When only from is given, only
          the list entry identified by from is deselected. When both from
          and to are given, deselects all of the list entrie(s) between
          between from and to, inclusive, without affecting the selection
          state of entries outside that range.

    *$tlist*->*selectionIncludes*(index)
          Returns 1 if the list entry indicated by index is currently
          selected; returns 0 otherwise.

    *$tlist*->*selectionSet*(*from, *?to?)
          Selects all of the list entrie(s) between between from and to,
          inclusive, without affecting the selection state of entries
          outside that range. When only from is given, only the list entry
          identified by from is selected.

*$tlist*->*xview*(args)
     This command is used to query and change the horizontal position of
     the information in the widget's window. It can take any of the
     following forms:

    *$tlist*->*xview*
          Returns a list containing two elements.  Each element is a real
          fraction between 0 and 1; together they describe the horizontal
          span that is visible in the window.  For example, if the first
          element is 0.2 and the second element is 0.6, 20% of the TList
          entry is off-screen to the left, the middle 40% is visible in
          the window, and 40% of the entry is off-screen to the right.
          These are the same values passed to scrollbars via the
          *-xscrollcommand* option.

    *$tlist*->*xview*(index)
          Adjusts the view in the window so that the list entry identified
          by index is aligned to the left edge of the window.

    *$tlist*->*xviewMoveto*(*fraction*)
          Adjusts the view in the window so that *fraction* of the total
          width of the TList is off-screen to the left. *fraction* must be
          a fraction between 0 and 1.

    *$tlist*->*xviewScroll*(*number, what*)
          This command shifts the view in the window left or right
          according to number and *what*. Number must be an integer.  What
          must be either *units* or *pages* or an abbreviation of one of
          these. If *what* is *units*, the view adjusts left or right by
          number character units (the width of the 0 character) on the
          display; if it is *pages* then the view adjusts by number
          screenfuls. If number is negative then characters farther to the
          left become visible; if it is positive then characters farther
          to the right become visible.

*$tlist*->*yview*(*?args*?)
     This command is used to query and change the vertical position of the
     entries in the widget's window. It can take any of the following
     forms:

    *$tlist*->*yview*
          Returns a list containing two elements, both of which are real
          fractions between 0 and 1.  The first element gives the position
          of the list element at the top of the window, relative to the
          TList as a whole (0.5 means it is halfway through the TList, for
          example).  The second element gives the position of the list
          entry just after the last one in the window, relative to the
          TList as a whole.  These are the same values passed to
          scrollbars via the *-yscrollcommand* option.

    *$tlist*->*yview*(index)
          Adjusts the view in the window so that the list entry given by
          index is displayed at the top of the window.

    *$tlist*->*yviewMoveto*(*fraction*)
          Adjusts the view in the window so that the list entry given by
          *fraction* appears at the top of the window. *Fraction* is a
          fraction between 0 and 1; 0 indicates the first entry in the
          TList, 0.33 indicates the entry one-third the way through the
          TList, and so on.

    *$tlist*->*yviewScroll*(*number, what*)
          This command adjust the view in the window up or down according
          to number and *what*.  Number must be an integer.  What must be
          either *units* or *pages*.  If *what* is *units*, the view
          adjusts up or down by number lines; if it is *pages* then the
          view adjusts by number screenfuls.  If number is negative then
          earlier entries become visible; if it is positive then later
          entries become visible.

BINDINGS
========

[1]
     If the *-selectmode* is "browse", when the user drags the mouse
     pointer over the list entries, the entry under the pointer will be
     highlighted and the *-browsecmd* procedure will be called with one
     parameter, the index of the highlighted entry. Only one entry can be
     highlighted at a time. The *-command* procedure will be called when
     the user double-clicks on a list entry.

[2]
     If the *-selectmode* is "single", the entries will only be
     highlighted by mouse <ButtonRelease-1> events. When a new list entry
     is highlighted, the *-browsecmd* procedure will be called with one
     parameter indicating the highlighted list entry. The *-command*
     procedure will be called when the user double-clicks on a list entry.

[3]
     If the *-selectmode* is "multiple", when the user drags the mouse
     pointer over the list entries, all the entries under the pointer will
     be highlighted. However, only a contiguous region of list entries can
     be selected. When the highlighted area is changed, the *-browsecmd*
     procedure will be called with an undefined parameter. It is the
     responsibility of the *-browsecmd* procedure to find out the exact
     highlighted selection in the TList. The *-command* procedure will be
     called when the user double-clicks on a list entry.

[4]
     If the *-selectmode* is "extended", when the user drags the mouse
     pointer over the list entries, all the entries under the pointer will
     be highlighted. The user can also make disjointed selections using
     <Control-ButtonPress-1>. When the highlighted area is changed, the
     *-browsecmd* procedure will be called with an undefined parameter. It
     is the responsibility of the *-browsecmd* procedure to find out the
     exact highlighted selection in the TList. The *-command* procedure
     will be called when the user double-clicks on a list entry.

EXAMPLE
=======

   This example demonstrates how to use an TList to store a list of
numbers:

     use strict;
     use Tk ();
     use Tk::TList;

     my $mw = Tk::MainWindow->new();
     my $image = $mw->Getimage('folder');
     my $tlist = $mw->TList(-orient => 'vertical');
     for my $text ( qw/one two three four five six seven eight nine/ ) {
         $tlist->insert('end',
     		 -itemtype=>'imagetext', -image=>$image, -text=>$text);
     }

     $tlist->pack(-expand=>'yes', -fill=>'both');

     Tk::MainLoop;

SEE ALSO
========

   `Tk::options|Tk::options' in this node `Tk::Widget|Tk::Widget' in this
node `Tk::DItem|Tk::DItem' in this node `Tk::HList|Tk::HList' in this node
`Tk::TixGrid|Tk::TixGrid' in this node

KEYWORDS
========

   Tix(n), Tabular Listbox, Display Items

User interface for database applications. Tk::TM - Tk Transaction Manager - screen transactions with user.
**********************************************************************************************************

NAME
====

   Tk::TM - User interface for database applications.  Tk::TM - Tk
Transaction Manager - screen transactions with user.

SYNOPSIS
========

Using SQL and Widget Generator:
          use Tk::TM::Lib;
          Tk::TM::Common::DBILogin('dsn', 'user', '');
          my $mw  =new Tk::MainWindow;
          my $mnu =$mw->tmMenu;
          my $do  =new Tk::TM::DataObject();
          $do->set(-sqgfd=>[
               ['cruptb',undef,'id',   undef,  undef,'ID',   'Entry']
              ,['crub',  undef,'class','    3',['select class from entity where x=?',1],'Class','Entry']
              ,['crutb', undef,'name', undef,  undef,'Name', 'Entry']
              ]
            ,-sqgsf=>'entity'
            ,-sqgso=>'id'
            ,-sqgscr=>$mw
            ,-sqgpt=>[-rowcount=>5]
            )->form(-t=>$mnu);
          $mnu->Retrieve;
          Tk::MainLoop;

Using SQL Statements:
          use Tk::TM::Lib;
          Tk::TM::Common::DBILogin('dsn', 'user', '');
          my $mw =new Tk::MainWindow;
          my $mnu =$mw->tmMenu;
          my $tbl =$mw->tmTable(-rowcount=>3, -colspecs=>
                                 [['col1','Entry']
                                 ,['col2','Entry']
                                 ,['col3','Entry']]
                                )->form(-t=>$mnu);
          my $bln =$mw->tmBlank(-wgspecs=>
                                 [['col1','Entry']
                                 ,['col2','Entry']
                                 ,['col3','Entry',-width=>30]]
                                )->form(-t=>$tbl);
          new Tk::TM::DataObject(-wgtbl=>$tbl, -wgbln=>$bln
                                ,-sqlsel=>['select...',value...]
                                ,-sqlins=>['insert...',fieldnumber...]
                                ,-sqlupd=>['update...',fieldnumber...]
                                ,-sqldel=>['delete...',fieldnumber...]
                                );
          $mnu->Retrieve;
          Tk::MainLoop;

Low Level:
          use Tk::TM::Lib;
          Tk::TM::Common::DBILogin('dsn', 'user', '');
          my $mw =new Tk::MainWindow;
          my $mnu =$mw->tmMenu;
          my $tbl =$mw->tmTable(-rowcount=>3, -colspecs=>
                                 [['col1','Entry']
                                 ,['col2','Entry']
                                 ,['col3','Entry']]
                                )->form(-t=>$mnu);
          my $bln =$mw->tmBlank(-wgspecs=>
                                 [['col1','Entry']
                                 ,['col2','Entry']
                                 ,['col3','Entry',-width=>30]]
                                )->form(-t=>$tbl);
          my $sub =sub{ my $self =shift;
             if    ($_[0] eq 'dbRead') {$self->DBICmd('select * from table')}
             elsif ($_[0] eq 'dbIns')  {$self->DBICmd('insert...')}
             elsif ($_[0] eq 'dbUpd')  {$self->DBICmd('update...')}
             elsif ($_[0] eq 'dbDel')  {$self->DBICmd('delete from table...')}
             else                      {$self->doDefault(@_)}
          };
          new Tk::TM::DataObject(-cbcmd=>$sub, -wgtbl=>$tbl, -wgbln=>$bln); # or:
          # $mnu->set(-dos=>[
          # new Tk::TM::DataObject(-cbcmd=>$sub, -wgtbl=>$tbl, -wgbln=>$bln)
          # ]);
          $mnu->Retrieve;
          Tk::MainLoop;

DESCRIPTION
===========

   This module is something like 'Transaction Manager' in JYACC JAM RAD.

   It releases user interface for database applications - screen
transactions with user.

   It contains data manipulation object (Tk::TM::DataObject), data widgets
(tmTable, tmBlank), menu and action bar widgets (tmMenu, tmActionBar,
based on Tk::TM::DataObjSet).

   See also:

   Tk::TM::wApp - Tk Transaction Manager Application Window.  This is
level above Tk::TM::Lib.

   Tk::TM::Try - Tk Transaction Manager Error processing functions.
Implements error processing functions may be used (or not be used) in
application.

MODULES
=======

   Tk::TM::Lib - to import all TM components (modules) into a program, it
have not own data or functions.

   Tk::TM::Common - common data and functions

   Tk::TM::Lang - language localisation

   Tk::TM::DataObject - objects to manipulate with tabular data: retrieve,
navigate, edit, save...  Tk::TM::DataObject uses Tk widgets to present
data, it can also simmultaniosly use one tmTable and one tmBlank widgets,
mentioned below.  DBI can be used to interact with databases in several
levels.  The base level is using defined by programmer function(s) for
database and user interactions.  More developed levels are autogeneration
of SQL.  Next more developed levels may be based on prepared in database
metadata.  Inherited from Tk::TM::DataObject may be developed
`Tk::TM::DataObjTixGrid' that uses `tixGrid' widget and
`Tk::TM::DataObjSeq' that uses sequentialy accessible data files as xBase
files.

   Tk::TM::wgTable - table widget tmTable, populated with Tk widgets. It
may be replaced with `tixGrid' in future.

   Tk::TM::wgBlank - blank widget tmBlank, presents data row-by-row with
Tk widgets.

   Tk::TM::DataObjSet - base object for menu and action bar widgets,
mentioned below.  It contains several Tk::TM::DataObjects and uses current
Tk::TM::DataObject or all Tk::TM::DataObjects to achieve required by user
operations.

   Tk::TM::wgActionBar - the simplest widget tmActionBar with user actions
as 'retrieve', 'save', 'next', 'previous'...

   Tk::TM::wgMenu - more complex widget tmMenu with more user actions -
menu and toolbar in CUA-style.

COMMON OBJECT METHODS
=====================

   `perlobj' and `perltoot' recommends common object methods new,
initialize, DESTROY. The only DESTROY word is special.

   Tk introduces it`s manner of constructing and creating widgets and
methods Populate, configure, cget, destroy, OnDestroy.

   So, it was needed to specify for TM objects sufficient and unified
range of common object methods: new, initialize, set, setpush, destroy,
destroybind, DESTROY.  And there was a little problem - should first
letters of words be capitalised (f.e. 'setpush' or 'SetPush')? Now it is
not for better focusing on parameters of such methods as new and set and
for common manners of perl programming.  But in future there may become
compatible names as 'New', 'Set', etc..

new Class (parameters) -> object
     Creates and returns a new object with given parameters. This is as in
     `perlobj'.  Derived from Tk objects have not this function.

initialize
$obj->initialize (parameters) -> object
     Initializes object as initialize in <perlobj>.  Usually initialize is
     called from new.  initialize is useful in inherited objects, that can
     not use ancestor`s function new but need to do ancestor`s initialise
     code

set
$obj->set () -> @names_of_parameters
$obj->set (parameter) -> value
$obj->set (list of parameters and values) -> object
     Gets or sets parameters of object as cget and configure in Tk.  set
     is called from initialize or outside object.

setpush
$obj->setpush (parameter, value) -> object
     Pushes given value into given parameter of type 'reference to array'
     or 'reference to hash'.  This is useful method when filling list
     parameters without using interim variables.

destroy
$obj->destroy
     Finishing using of object, disposing or destroying it as in Tk.  It
     was impossible to use DESTROY because of losing object inside it.
     For Tk widget objects destroybind is used instead of destroy.

DESTROY
$obj->DESTROY
     Standard object`s destructor, see `perlobj'.  Due to problem of
     losing object inside DESTROY, and thankfully to absence of needs, it
     is not used.

destroybind
$obj->destroybind
     Destruction method, called from Tk OnDestroy event.  Used only for
     widgets, for other objects destroy is used.

Tk::TM::Lib MODULE
==================

Tk::TM::Lib
     Tk::TM::Lib module imports all TM components (modules) into a program.

use Tk::TM::Lib
     Imports all TM components (modules) into a program

Tk::TM::Common MODULE
=====================

Tk::TM::Common
     Tk::TM::Common module contains common data and functions.

use Tk::TM::Common
     Imports Tk::TM::Common module into application.  This does
     Tk::TM::Lib module.

$Tk::TM::Common::About
     Default 'Help / About' text: reference to list of rows or sub.  See
     also `-about'

$Tk::TM::Common::DBH
     Default database connection handle, undef in default. Example:
     $Tk::TM::Common::DBH =DBI->connect("DBI:XBase:.")

$Tk::TM::Common::Debug
     Debug level: 0 -none (default), 1 -print actions to STDOUT.

$Tk::TM::Common::Echo
     Echo mode - printing commands to be executed: 0 -none, 1 -print
     (default).

$Tk::TM::Common::Edit
     Default mode for application: 0 -view only, 1 -allow edit data
     (default).  See `-mdedt'

$Tk::TM::Common::Help
     Default 'Help / Help' text: reference to list of rows or sub.  See
     also `-help'

Tk::TM::Common::DBILogin (dsn, user, password, ?opt, ?dbopt) -> dbh
Tk::TM::Common::DBILogin (screen, dsn, user, password, ?opt, ?dbopt)
     Database login dialog, see `DBI->connect'.  Options (default none):
     '#dsn' or '#edit' - allow to edit dsn, '#return' - instead of
     modifying $Tk::TM::Common::DBH only return dbh and return instead of
     exit when 'cancel' button pressed, '#center' - center login dialog on
     screen.  Screen parameter is used for calls from `Tk::TM::wApp'.

Tk::TM::Lang MODULE
===================

Tk::TM::Lang
     Tk::TM::Lang module contains language localisation.  The functions of
     this module are used par excellence internally by `Tk::TM',
     application may only specify required localisation in
     $Tk::TM::Lang::Lang.

use Tk::TM::Lang
     Imports Tk::TM::Lang module into application.  This does Tk::TM::Lib
     module.

$Tk::TM::Lang::Lang
     Switch of language localisation: false - international (no
     localisation), other - turn on localisation - language name such as
     'ru' may be used.

Tk::TM::Lang::txtHelp -> \@help_text
     Returns reference to array of rows of embedded help text.

Tk::TM::Lang::txtMenu -> \@menu_items_texts
     Returns reference to array of texts of menu items

Tk::TM::Lang::txtMsg (msg) -> lang_msg
     Returns given string translated into used localisation.

Tk::TM::DataObject MODULE
=========================

Tk::TM::DataObject
     Tk::TM::DataObject module implements object to manipulate with
     tabular data: retrieve, navigate, edit, save...  This object contains
     data store (data system) may be filled with SQL select and updated
     synchronously with SQL inserts, updates, deletes.  Tk::TM::DataObject
     may be classified into:

     Object data: `-wgtbl', `-wgbln', `-wgarr', `-wgmnu', `-wgind',
     `-mdedt', `-dsdtm', `-cbcmd', `-cbXXX', `-dbh', `-dbfnm', `-dbfds',
     `-dbfaw', `-sqlsel', `-sqlins', `-sqlupd', `-sqldel', `-sqgscr',
     `-sqgfd', `-sqgsf', `-sqgsj', `-sqgsc', `-sqgso', `-sqgpt', `-sqgpb',
     `-parm', `-parmc'

     Options of Tk::TM::DataObject operation: "#end", "#force", "#reread",
     "#save", "#silent", "#undo", "#wgs", "#dta"

     Common object methods: `new Tk::TM::DataObject', `$do->initialize',
     `$do->destroy', `$do->DESTROY', `$do->set', `$do->setpush'

     Data system dependent level methods with prefix 'ds', that
     implementation reflects data storage type - array of rows or
     `tixGrid'; many of this commands are used internally only, externally
     used variants (mentioned below) has not prefix 'ds' and observes
     modification flags: `$do->dsReset', `$do->dsDisplay',
     `$do->dsDispWg', `$do->dsFocus' `$do->dsRowCount', `$do->dsRowDta',
     `$do->dsRowFeed', `$do->dsRowFeedAll', `$do->dsRowGo',
     `$do->dsRowNew', `$do->dsRowDel', `$do->dsRowUpd', `$do->dsFldDta',
     `$do->dsFldUpd'

     Abstract level methods without prefix 'ds' does not depends on data
     system implementation (array of rows or `tixGrid') and observes
     modification flags.  Method with 'ds' prefix should not be used by
     programmer if there is abstract level method with the same name.
     Function `$do->Stop' plays important role within codes of abstract
     level functions, they often calls it to finish data editing if it is.

     Internally used widget level methods with 'wg' prefix:
     `$do->wgFldFocusIn', `$do->wgFldFocusOut', `$do->wgFldHelper',
     `$do->wgIndicate'

     Commands, used outside data objects to control them: `$do->Display',
     `$do->Stop', `$do->Save', `$do->Sleep', `$do->Clear', `$do->Retrieve',
     `$do->RowGo', `$do->RowNew', `$do->RowDel', `$do->RowUndo',
     `$do->Export', `$do->Find', `$do->FindNxt', `$do->Import',
     `$do->Print', `$do->Action'

     Implementations of commands above with prefix 'do', used inside data
     object: `$do->doDefault', `$do->doExport', `$do->doImport',
     `$do->doPrint'

     Useful methods for programming events (callbacks) used in
     implementations above: `$do->DBICmd', `$do->DBICnd', `$do->DBIGen',
     `$do->DBIHlp'

     Events (callbacks) and transaction scheme: dbRead, dbIns, dbUpd,
     dbDel, rwChg0, rwChg1, rwIns0, rwIns1, rwUpd0, rwUpd1, rwDel0,
     fdChg0, fdChg1, fdHelp, fdUpd0, fdUpd1, doEnd, doExport, doImport,
     doPrint, usAct

use Tk::TM::DataObject
     Imports Tk::TM::DataObject module into application to use data
     objects.  This does Tk::TM::Lib module.

new Tk::TM::DataObject (parameter=>value...)
     Creates and returns data object with parameters specified (see
     Parameters of Tk::TM::DataObject).  Includes newly created data
     object into list of all data objects
     `@$Tk::TM::DataObject::Available'.

Parameters of Tk::TM::DataObject
--------------------------------

   Parameters may be set or get with `new Tk::TM::DataObject' and
`$do->set' methods of data object (see also new and set).  There may be
described only most used parameters.

-cbcmd
     Callback function for all events (see Events of Tk::TM::DataObject).
     Default value is `$do->doDefault'.  Slots for particular events
     `-cbXXX' may be used instead of `-cbcmd'.

-cbXXX
     Callbacks for particular events. Optional.  'XXX' means name of
     event, f.e. dbRead.  Callbacks `-cbXXX' are implemented within
     `$do->doDefault' method of data object, and so programmer should use
     `-cbcmd' or `-cbXXX', but not both.

-dbfaw
     Widget width adaptation to database fields switch.  Contains margin
     of widget width.

-dbfds
     Reference to array of references to hashes with descriptions of
     fields.  Filled in `$do->DBICmd'('select...').

-dbfnm
     Reference to hash "fieldName => fieldNumber".  Filled in
     `$do->DBICmd'('select...').

-dbh
     Database handle (see DBI) to use with database methods.  If not set,
     $Tk::TM::Common::DBH will be used, or other may be programmed.

-dsdtm
     Data store margin - max number of rows to keep in it.

-mdedt
     Enable edit actions for user (edit mode).  Values: 0 or " - disable,
     digit -enable, 'c'reate or 'i'nsert enable, 'u'pdate enable, 'd'elete
     enable.  Default is $Tk::TM::Common::Edit.

-parm
     Programmer`s parameters, hash reference.  Does`nt used by `Tk::TM',
     may be used for programmer`s needs.

-parmc
     Common to Tk::TM::DataObjSet object programmer`s parameters, hash
     reference.  This is also available via $do->{`-wgmnu'}->{-parm}.

-sqgxxx - SQL and Widget Generator parameters
-sqgscr = screen to generate widgets on, generation trigger
     If `-sqgscr' and `-sqgsf' specified, widget required will be
     generated and returned by `$do->set'.

-sqgfd = [['cruvpktb', table, field, filter value, helper select, ?inccol, label, ?colSpan, ?rowSpan, wgType, ?wgOpt]]
     'crupktb' is field usage: 'c'reate or 'i'nsert, 'r'ead or 's'elect,
     'u'pdate, 'v'iew only, 'p'rimary key, 'k'ey for commands, 't'able
     widget, 'b'lank widget.  If table name is empty string, it will be
     automatically filled if possible; undefined table name will not be
     used in 'select' generation.  Field name may be also expression to
     select.  Filter value or sub will be used in 'where' clause and in
     `$do->RowNew' if defined.  Helper select is value compliant to
     `$do->DBIHlp' and `$do->DBIGen' interfaces, it may be 'sql select'
     string, reference to array with 'sql select' string and numbers of
     fields or subs, reference to array of references to arrays with data
     strings.  Values after 'helper select' are used for table or blank
     widget fields.

-sqgsf = 'select from' clause
-sqgsj = 'select where/join' subclause
-sqgsc = 'select where/condition' subclause with/without parameters
-sqgso = 'select order by' clause
     All clauses are strings to be placed after keyword mentioned.
     Where/condition parameter `-sqgsc' may be also reference to array
     with string subclause and values or subs for SQL statement parameters.

-sqgpt = parameters for table widget
     See Tk::TM::wgTable.

-sqgpb = parameters for blank widget
     See Tk::TM::wgBlank.

-sqlxxx - SQL templates for simplest SQL generator
-sqlsel = SQL 'select' statement and parameters
-sqlins = SQL 'insert' statement and parameters
-sqlupd = SQL 'update' statement and parameters
-sqldel = SQL 'delete' statement and parameters
     SQL templates for simplest SQL generator - strings, array refs, refs
     to arrays of refs.

     Simple string is SQL statement.  'insert', 'update', 'delete' will be
     automatically supplied with all data values of current row as
     parameters.  'update' will be also supplied with old data values.

     Reference to array with string as first element is SQL statement with
     parameters.  'select' parameters may be values or subs to evaluate.
     'insert', 'update', 'delete' parameters are subs to evaluate or
     column numbers, negative values are treated like slices (f.e.
     ['insert into table values (?,?,?)',0,-2] tells use columns 0,1,2).
     'update' old values are discovered as decrease of numbering (f.e.
     ['update table set xxx=?, yyy=? where k=?',0,-1,0]).

     Reference to array with reference as first element is treated as
     sequence of SQL statements to execute within single transaction.

-wgarr
     Widgets for row-by-row data performance.  Alternative or addition to
     `-wgbln'.  There no need of widget for each field, absent widgets
     should be replaced with undefs.  Optional.

-wgbln
     tmBlank widget for data object use.  Optional.

-wgind
     Indicator widget for data object use with `$do->wgIndicate'.
     Optional.

-wgmnu
     Navigator widget - ancestor of Tk::TM::DataObjSet.  This may be used
     instead of `-dos' of Tk::TM::DataObjSet, but `-dos' is more
     recommended.

-wgscr
     Parent screen for data object. Default is parent of widgets used.

-wgtbl
     tmTable widget for data object use.  Optional.

Options of Tk::TM::DataObject operation
---------------------------------------

   This describes options of data object operations.  This options are
used as parameters of methods as `$do->Retrieve', `$do->Stop',
`$do->doDefault', `$do->doImport', `$do->DBICmd'...  There may be several
options catenated within one option string, f.e. '#force#end'.  Some of
this options are used internally, some may be used by programmer.

"#dta"
     Drop data buffer.  Used in `$do->Sleep'

"#end"
     End of data object operation. It is no need to redisplay data.  Used
     in `$do->Stop'

"#force"
     Cancel of operation is not allowed, answer should be certain - 'yes'
     or 'no'.  Used in `$do->Stop'

"#reread"
     Keep current position of data store.  Used in `$do->Retrieve'

"#save"
     Save modified data without ask of user.  Used in `$do->Stop'

"#silent"
     Do not display error message box.  Used in `$do->doImport',
     `$do->DBICmd'

"#undo"
     Undo unsaved modification of current record of data.  Used in
     `$do->Stop'

"#wgs"
     Destroy linked widgets.  Used in `$do->Sleep'

Methods of Tk::TM::DataObject
-----------------------------

$do->Action (actionName)
     Executes callback usAct.  This is used for may be added by programmer
     menu 'Actions'.

$do->Clear (?opt) -> success
     Clears data inside data object`s data store.  Saves modified data if
     needed via `$do->Stop'($opt .'#end').  Data object become ready for
     insertion and editing new records of data.

$do->DBICmd (?dbh, ?opt, command, arguments) -> result
$do->DBICmd (?dbh, ?opt, command, [arguments], command, [arguments]...) ->result
     Simplest DBI interface, executes dbh command.  Database connection
     handle dbh may be specified as argument, or may be given from data
     object`s property `-dbh' or from $Tk::TM::Common::DBH.  Option
     '#silent' declines usage of message box to display error occurred.
     Command may be any dbh method (as 'selectrow' or 'do') or string
     incipient with 'select', 'selectrow', 'insert', 'update', 'delete'.
     Commands 'select' and 'selectrow' retrieves data directly into data
     object`s data store.  Several commands may be specified to execute
     them within one database transaction.  With one command specified
     autocommit is assumed.

$do->DBICnd() -> success
     Query condition and sort dialog.  Works with all modes of SQL
     generation.

$do->DBIGen(sql, opt, ?command) -> sql command
     SQL generator.  In simplest mode it uses `-sqlsel', `-sqlins',
     `-sqlupd', `-sqldel'.  In complex mode it uses `-sqgscr', `-sqgfd',
     `-sqgsf', `-sqgsj', `-sqgsc', `-sqgso', `-sqgpt', `-sqgpb'.

$do->DBIHlp (?SQL, \@parameters, ?\@out_fields) -> success
     Displays entry helper screen for `-fdHelp' event, updates fields if
     chosen.  Parameters may be for SQL command if it is, or to directly
     display.  Output field numbers are relative to current field number.
     If output field numbers omitted, current field is used for output.

$do->destroy
     Destructs data object, see destroy.  Saves modified data if needed
     via `$do->Stop'('#force#end').  Excludes data object from list of all
     data objects `@$Tk::TM::DataObject::Available'

$do->DESTROY
     Destructor, see DESTROY. Does nothing.

$do->Display -> success
     Displays current data on screen.  This is not very useful method
     because all high-level methods keep screen actual.

$do->doDefault (operation, options, args...) -> success
     Implements default actions for all programmable events, evaluates
     appropriate `piXXX' code if it exists.  This is default value for
     `-cbcmd' data object`s parameter.  Events and options are described in
     Events of Tk::TM::DataObject and Options of Tk::TM::DataObject
     operation

$do->doExport (?file, ?format) -> filename
     Exports data from data object`s data store to specified file.  If no
     file specified, uses `Tk::FileSelect' to ask user for filename.
     Returns filename on success or empty string on failure.  See also
     `$do->Export'

$do->doImport (?file, ?format) -> filename
     Imports data from file into data object.  If no file specified, uses
     `Tk::FileSelect' to ask user for filename.  Importing each row of
     data is implemented via insert attempt and update attempt.  Returns
     filename on success or empty string on failure.  See also
     `$do->Import'

$do->doPrint (?file, ?format) -> filename
     Prints data on printer device or into file specified.  See also
     `$do->Print'.  Not implemented yet.

$do->dsDisplay -> success
     Displays current data on screen: `-wgtbl', `-wgbln', `-wgarr'.  Calls
     `$do->dsDispWg'.

$do->dsDispWg -> success
     Displays current data in by-row widgets: `-wgbln', `-wgarr'

$do->dsFldDta (?field) -> data
     Returns data from current or specified widget.  Parameter may be data
     widget or field number or field name.

$do->dsFldUpd (field, data) -> success
     Replaces (updates) data in specified field, displays it on screen.
     Field may be identified by number or name.

$do->dsFocus
     Sets focus (focusForce) to current widget.

$do->dsReset (?) -> success (always)
     Resets data store, drops all rows of data.  Does not displays data on
     screen, but may this in different releases.

$do->dsRowCount -> number_of_rows
     Returns number of data rows in data store.

$do->dsRowDel -> success
     Deletes current row of data in data store.  Displays changes on
     screen.

$do->dsRowDta (?row) ->\@data_row
     Returns reference to array containing data of current or specified row

$do->dsRowFeed (\@data_row) -> success
     Pushes specified data row into data store.  Does not displays data on
     screen.

$do->dsRowFeedAll (\@data) -> success
     Replaces all data in data store with specified.  Does not displays
     data on screen.

$do->dsRowGo (?row) -> success
     Make specified row current and display this on screen.  If no row
     specified, only redisplays data on screen.  Row may be specified
     absolutely or with commands 'next', 'prev', 'pgdn', 'pgup', 'top',
     'bot'.  Data on screen will be redisplayed in all cases except 'next'
     and 'prev' optimisations.

$do->dsRowNew -> success
     Creates (appends) new row into data store, makes it current, displays
     it on screen, sets focus to it.

$do->dsRowUpd (\@data) -> success
     Replaces (updates) data in the current row with data specified,
     displays it on screen.

$do->Export (?file, ?format) -> filename
     Exports data from data store into file.  Saves modified data if
     needed via `$do->Stop'(").  If no file specified, uses
     `Tk::FileSelect' to ask user for filename.  Returns filename on
     success or empty string on failure.  See involved: `-cbcmd',
     doExport, `$do->doExport'

$do->Find -> success
     Presents Find dialog to user and finds in current column first
     occurrence.  See also `$do->FindNxt'

$do->FindNxt (?offset) -> success
     Finds next occurrence of Find string in current column, goes to row
     found.  Default and usual offset is 1, 0 is used for call from
     `$do->Find'.

$do->Import (?file, ?format) -> filename
     Imports data from file into data object.  Saves modified data if
     needed via `$do->Stop'(").  If no file specified, uses
     `Tk::FileSelect' to ask user for filename.  Importing each row of
     data is implemented via insert attempt and update attempt.  Returns
     filename on success or empty string on failure.  See involved:
     `-cbcmd', doImport, `$do->doImport'

$do->initialize (parameters)
     Initialises object, see initialize.

$do->Print (?file, ?format)
     Prints data of data object.  Saves modified data if needed via
     `$do->Stop'(").  See involved: `-cbcmd', doPrint, `$do->doPrint'.

$do->Retrieve (?opt) -> success
     Retrieves data into data store.  Saves modified data if needed via
     `$do->Stop'(").  Option string may contain `$do->Stop'(") options and
     '#reread' that keeps current row in data store unchanged.  Without
     option '#reread' method `$do->RowGo' ('top') is used.  See involved:
     `-cbcmd', dbRead, `$do->dsRowFeed', `$do->dsRowFeedAll',
     `$do->DBICmd'.

$do->RowDel -> success
     Deletes current row of data.  Saves modified data if needed via
     `$do->Stop'('#save').  See involved: `-cbcmd', rwDel0, dbDel, rwChg1
     `$do->dsRowDel', `$do->DBICmd'

$do->RowGo (row) -> success
     Goes to specified row of data: 'top', 'bot', 'pgup', 'pgdn', 'prev',
     'next', directly defined row identifier.  Saves modified data if
     needed via `$do->Stop'('#save').  See involved: `-cbcmd', rwChg1,
     `$do->dsRowGo'

$do->RowNew -> success
     Creates (appends) new row of data.  Saves modified data if needed via
     `$do->Stop'('#save').  See involved: `-cbcmd', rwIns0, rwIns1, rwChg1,
     `$do->dsRowNew'

$do->RowUndo -> success
     Undoes editing of current row of data via `$do->Stop'('#undo').  See
     involved: rwChg1

$do->Save (?opt) -> success
     Saves modified data via `$do->Stop'($opt .'#save').  See involved:
     rwChg1

$do->Sleep (?opt) -> success
     Makes data object inactive, frees resources engaged by it.  Saves
     modified data via `$do->Stop'($opt .'#end').  Option "#wgs" destroys
     data widgets.  Option "#dta" drops data buffer.  `$do->Retrieve'
     (`#reread') will awake sleeping data object.  Sleep procedure may be
     need application to control resources used.

$do->set (parameter) -> value
$do->set (parameter=>value...) -> data object
     Gets or sets parameters of data object.  See set, Parameters of
     Tk::TM::DataObject

$do->setpush (parameter, value) -> data object
     Pushes list parameter into data object.  See setpush, Parameters of
     Tk::TM::DataObject

$do->Stop (?opt) -> success
     Stops data editing user transaction if it is.  Other methods often
     calls it.  See involved: `-cbcmd', rwChg0, dbIns, dbUpd, rwUpd1,
     doEnd, `$do->wgFldFocusOut'

$do->wgFldFocusIn (widget, ?fieldNo, ?screenRowNo)
     Callback for `FocusIn' Tk event.  All used for data object widgets
     are bind to it.

$do->wgFldFocusOut (?widget, ?fieldNo, ?screenRowNo)
     Callback for `FocusOut' Tk event.  All used for data object widgets
     are bind to it.  This method is called also by `$do->Stop'

$do->wgFldHelper (?widget, ?fieldNo, ?screenRowNo)
     Callback for '<Key-F4>' Tk event.  All used for data object widgets
     are bind to it.  This method may be called also outside callbacks.

$do->wgIndicate (?string)
     Indicates current state of data object in `-wgind'

Events of Tk::TM::DataObject
----------------------------

   This describes programmable events (callbacks) of Tk::TM::DataObject
and transaction scheme of them.  This events may be implemented by
programmer with `-cbcmd' or `-cbXXX' routines.  See also `$do->doDefault'.

   Chains of events:

   Change current row: rwChg0, rwChg1, fdChg1

   Begin to modify row: rwUpd0, fdUpd0, fdUpd1

   Begin to insert row: rwChg0, rwIns0, rwIns1, rwChg1, fdChg1

   Save modified row: dbIns | dbUpd, rwUpd1, rwChg1

   Delete row: rwChg0, rwDel0, dbDel, rwChg1

dbDel (opt, rowNo, undef, undef, \@old_data)
     Delete row of data into database.  This may be `$do->DBICmd'('delete
     ...', @old_data)

dbIns (opt, rowNo, undef, undef, \@old_data, \@new_data)
     Insert new row of data into database.  This may be
     `$do->DBICmd'($opt, 'insert ...', @new_data)

dbRead (opt)
     Read data from database.  This may be `$do->DBICmd'($opt, 'select
     ...')

dbUpd (opt, rowNo, undef, undef, \@old_data, \@new_data)
     Update row of data into database.  This may be `$do->DBICmd'($opt,
     'update ...', @old_data, @new_data)

doEnd (opt, rowNo, undef, undef, \@row_data)
     End of using data object, `-parm' may be modified.  Invoked from
     `$do->Stop' ("#end").

doExport (file, format)
     Export data from data store.  In default this is `$do->doExport'

doImport (file, format)
     Import data into data store.  In default this is `$do->doImport'

doPrint (file format)
     Print data from data store.  In default this is `$do->doPrint'

fdChg0 (?)
     Before changing current field (should current field be changed?).
     Not implemented.

fdChg1 (opt, rowNo, fieldNo, widget)
     After current field was changed.  This may occur after rwChg1.

fdHelp (opt, rowNo, fieldNo, widget)
     After key F4 (field fill help) was pressed, this may be entry helper
     screen displayed.  Before this is occurred rwUpd0, fdUpd0

fdUpd0 (opt, rowNo, fieldNo, widget)
     Before updating (modifying) current field (should field be updated?).
     In current implementation this occurs after user have been modified
     data in a widget.  This may occur after rwUpd0.

fdUpd1 (opt, rowNo, fieldNo, widget, old_value, new_valie)
     After current field was modified (accept changes?).  In current
     implementation this occurs after user have been modified data in a
     widget and exited this widget.

rwChg0 (opt, rowNo)
     Before changing current row in data store (should current row be
     changed?).  Detail data objects should be saved in this event with
     `$do->Save'

rwChg1 (opt, rowNo)
     After current row in data store was changed.  Detail data objects
     should be retrieved in this event with `$do->Retrieve'

rwDel0 (opt, rowNo)
     Before deleting current row (should row be deleted?)  This occurs
     after rwChg0 and before dbDel.

rwIns0 (opt)
     Before inserting (appending) new row (should new row be inserted?).
     This occurs after rwChg0.  Master data objects should be saved in
     this event with `$do->Save'.

rwIns1 (opt, rowNo)
     After new row is inserted (appended) into data store.  New row is
     current row.  This occurs before dbIns.  Default values should be
     supplied for this row.

rwUpd0 (opt, rowNo)
     Before updating (modifying) current row (should row be modified?).
     This occurs after rwChg0 and before dbUpd.

rwUpd1 (opt, rowNo, undef, undef, \@old_data, \@new_data)
     After current data row was updated (modified).  This occurs after
     dbIns or dbUpd and before rwChg1.  Here may be
     `$do->DBICmd'('selectrow ...', @old_data)

usAct (actionName, rowNo, fieldNo, widget)
     Called by `$do->Action' when user shoosed item from 'Actions' menu.

Tk::TM::wgTable MODULE
======================

Tk::TM::wgTable
     Module Tk::TM::wgTable contains table widget tmTable, populated with
     Tk widgets.

tmTable
     Widget tmTable is implemented by module Tk::TM::wgTable.  It is
     inherited from `Tk::Frame'.

use Tk::TM::wgTable
     Imports Tk::TM::wgTable module into application to use data objects.
     This does Tk::TM::Lib module.

$mw->tmTable (parameter=>value...)
     Creates and returns table widget with parameters specified.
     Parameters may be Tk options (use configure) or tmTable (use set).

-do
     Data object to use with this widget

-colspecs
     Specifications of columns: [[header, widgetType,
     widgetOption,...],...].  Header may be text for Label widget or
     reference to array of options for Label widget, the first value in
     this array should be text.  Other parameters of column are type of
     widget (f.e.Entry) for data and options for this widget creation.
     There no need of widget for each field, absent widgets should be
     replaced with undefs.

-rowcount
     Number of on-screen rows of widgets in table

$tbl->Display -> success
     Displays data from data object `-do' within this table widget.

$tbl->Focus -> success
     Sets focus (focusForce) to current widget within this table widget.

Tk::TM::wgBlank MODULE
======================

Tk::TM::wgBlank
     Module Tk::TM::wgBlank contains blank widget tmBlank, that presents
     data row-by-row with Tk widgets.

tmBlank
     Widget tmBlank is implemented by module Tk::TM::wgBlank.  It is
     inherited from `Tk::Frame'.

use Tk::TM::wgBlank
     Imports Tk::TM::wgBlank module into application to use data objects.
     This does Tk::TM::Lib module.

$mw->tmBlank (parameter=>value...)
     Creates and returns table widget with parameters specified.
     Parameters may be Tk options (use configure) or tmBlank (use set).

-do
     Data object to use with this widget

-wgspecs
     Specifications of widgets: [[?incCol, label, ?colSpan, ?rowSpan,
     widgetType, widgetOption,...],...].

     Label may be text for Label widget or reference to array of options
     for Label widget, the first value in this array should be text.

     Parameter 'widgetType' is type of widget (f.e.Entry) for data,
     followed with options for this widget creation.

     Optional 'incCol' parameter is digit to add to current column number
     in grid geometry manager. Default column number is 0 for label and 1
     for widget.

     Optional 'colSpan' parameter is digit - number of columns for widget
     in grid geometry manager. Default is 1.

     Optional 'rowSpan' parameter is digit - number of rows for widget in
     grid geometry manager. Default is 1.

     There no need of widget for each field, absent widgets should be
     replaced with undefs.

$bln->Display -> success
     Displays data from data object `-do' within this widget.

$bln->Focus -> success
     Sets focus (focusForce) to current widget within this widget.

Tk::TM::DataObjSet MODULE
=========================

Tk::TM::DataObjSet
     Module Tk::TM::DataObjSet implements base object for menu and action
     bar widgets, described below.  Descriptions of Tk::TM::wgActionBar
     and Tk::TM::wgMenu modules does not contains parameters and methods,
     described for Tk::TM::DataObjSet.  So read it here.

     Tk::TM::DataObjSet object contains several Tk::TM::DataObjects and
     uses current Tk::TM::DataObject or all this Tk::TM::DataObjects (see
     `-mdscr') to achieve required by user operations.

     Tk::TM::DataObjSet may be classified to:

     Parameters: `-dos', `-wgind', `-mdmnu', `-mdtbr', `-mdedt', `-mdnav',
     `-mdscr', `-about', `-help', `-parm'

     Common object methods: new, initialize destroybind, DESTROY, set,
     setpush

     Methods of itself: `$dos->DataObject', `$dos->doAll',
     `$dos->doCurrent', `$dos->Help'

     Procedures to transfer to all data objects (see description of data
     object): `$do->Stop', `$do->Save', `$do->Clear', `$do->Retrieve',
     `$do->Reread'

     Procedures to transfer to current data object (see description of
     data object): `$do->Find', `$do->FindNxt', `$do->FldHelp',
     `$do->RowGo', `$do->RowNew', `$do->RowDel', `$do->RowUndo',
     `$do->Export', `$do->Import', `$do->Print', `$do->Action'

use Tk::TM::DataObjSet
     Imports Tk::TM::wgBlank module into application to use data objects.
     This does Tk::TM::wgActionBar, Tk::TM::wgMenu, Tk::TM::Lib modules.

new Tk::TM::DataObjSet (parameter=>value...)
     Creates and returns Tk::TM::DataObject widget with parameters
     specified.  Parameters may be specified with set also.  Tk options
     for inherited widgets may be specified with configure).  Do not use
     this method, use `$mw->tmActionBar' or `$mw->tmMenu'.

-about
     Text or routine to produce about text for 'Help / About' menu.

-dos
     Reference to array of data objects managed by this object.  Default
     value is `@Tk::TM::DataObject::Available' - list of all existed data
     objects in application.

-help
     Text or routine to produce help text for 'Help / Help' menu.

-mdedt
     Enable edit actions for user (edit mode).  Value is controlled by
     current data object.

-mdmnu
     Type of menu to use: 'bar' - menu bar `Tk::Menu' (default), 'button'
     - menu with `Tk::Menubutton's, " - no menu.

-mdnav
     Enable only navigation buttons for user (navigation mode).  Default
     is disabled (false).

-mdscr
     Restrict operations on all data objects to data objects in the same
     parent widget as current.  Default is disabled.

-mdtbr
     Type of toolbar (action bar) to use: true - use toolbar (default),
     false - no toolbar.

-parm
     Programmer`s parameters, hash reference.  Does`nt used by `Tk::TM',
     may be used for programmer`s needs.  Default value is
     `$Tk::TM::DataObjSet::Parm', and so all data object sets in
     application shares the same area of parameters.

-wgind
     Indicator widget for data objects. See `-wgind' in it`s description.

$dos->DataObject -> current data object
     Returns current data object

$dos->doAll (sub, args) -> success
     Executes given sub for all data objects or restricted with `-mdscr'

$dos->doCurrent (sub, args) -> success
     Executes given sub for current data object.

$dos->Help (-about|-help)
     Executes help screen.

Tk::TM::wgActionBar MODULE
==========================

Tk::TM::wgActionBar
     Module Tk::TM::wgActionBar implements the simplest widget tmActionBar
     with user actions as 'retrieve', 'save', 'next', 'previous'...  It
     inherits from Tk::TM::DataObjSet, and below are only description of
     Tk::TM::wgActionBar features.

tmActionBar
     Widget tmActionBar is implemented by module Tk::TM::wgActionBar.

use Tk::TM::wgActionBar
     Imports Tk::TM::wgActionBar module into application to use action bar
     objects.  This does Tk::TM::Lib module.

$mw->tmActionBar (parameter=>value...)
     Creates and returns action bar widget with parameters specified.
     Parameters may be Tk options (use configure) or Tk::TM::DataObjSet
     (use set).

$mw->setActions (@actions)
     Sets 'Actions' menu.  Each action may be string with action name to
     use with `$do->Action' call (usAct callback), or reference to array
     of [name, type, options for `Tk::Menu'].

Tk::TM::wgMenu MODULE
=====================

Tk::TM::wgMenu
     Module Tk::TM::wgMenu implements widget tmMenu - menu and toolbar in
     CUA-style, more complex then tmActionBar, with more user actions.  It
     inherits from Tk::TM::DataObjSet, and below are only description of
     Tk::TM::wgMenu features.

tmMenu
     Widget tmMenu is implemented by module Tk::TM::wgMenu.

use Tk::TM::wgMenu
     Imports Tk::TM::wgMenu module into application to use menu objects.
     This does Tk::TM::Lib module.

$mw->tmMenu (parameter=>value...)
     Creates and returns menu widget with parameters specified.
     Parameters may be Tk options (use configure) or Tk::TM::DataObjSet
     (use set).

$mw->setActions (@actions)
     Sets 'Actions' menu.  Each action may be string with action name to
     use with `$do->Action' call (usAct callback), or reference to array
     of [name, type, options for `Tk::Menu'].

VERSION
=======

"16-18/11/2000"
     Bug 'bad event type or keysym "~"' fixed in 'wgMenu.pm'.

     Status Line support implemented, but without comments for fields.

     Bug of incorrect 'pgup' within table fixed in 'wgTable.pm'.

     Scrollbar in 'wgTable.pm' implemented.

"22/10-03/11/2000"
     exit calls replaced with `Tk::exit' calls to avoid abnormal program
     terminations.

     `Key-F4' bindings moved from Tk::TM::DataObject, Tk::TM::wgBlank,
     Tk::TM::wgTable to Tk::TM::wgMenu to avoid conflict with 'Alt-F4'.

     Tk::TM::Common::DBILogin unified for `Tk::TM::wApp' use.

     Sleeping DataObject can operate with data in current row:
     `$do->Sleep' and `$do->Retrieve' uses new DataObject`s parameter
     `-dsslp' to indicate sleeping and save `-dsrid'.

     `-parmc' DataObject`s parameter created.

     `-wgnav' DataObject`s parameter renamed to `-wgmnu' for unification
     with `Tk::TM::wApp'.

     Error processing for callbacks added.

     `$do->DBICmd' corrected - undefined attributes inserted into 'do'
     arguments.

     `-dsrd0' DataObject`s parameter corrected - now it is filled with
     copy of `$do->dsRowDta'.

     `-sqlsel', `-sqlins', `-sqlupd', `-sqldel' DataObject`s parameters
     added - simplest sql generator features implemented, see also
     `$do->DBIGen'.

     `-sqgscr', `-sqgfd', `-sqgsf', `-sqgsj', `-sqgsc', `-sqgso',
     `-sqgpt', `-sqgpb' DataObject`s parameters added - SQL and Widget
     generator created, see also `$do->DBIGen'.

     `-mdedt' may contain 'c'reate or 'i'nsert, 'u'pdate, 'd'elete.

     `$do->DBICnd' - Query condition and sort dialog created.

     `-dbfaw' DataObject`s parameter added - widget width adaptation to
     database fields implemented.

"12/08/2000" - fixed "bad event type or keysym 'ä'"

"06/02/2000" - first documented release
     TO DO:

     - Test and Debug

     - tmDialogBox - approve and document?

     - Conflict of 'F4' and 'Alt+F4' callbacks

"12/12/1999" - documentation was began
     This documentation was began.

     Some reviewing done.

     Modules `Lib', Common, `Lang' created.

     TO DO:

     - Review api and naming

     - Approve code

     - Debug

     - Document realised

     - Action interfaces- methods to customise additional actions

     - DataObjSet actions for all DataObjects (as reread or query) may
     involve only DataObjects on current screen - window or panel.

AUTHOR
======

   Andrew V Makarow <makarow@mail.com>, Denis E Medvedyuk <demed@mail.com>

Tk Transaction Manager Error processing functions. See Tk::TM::Lib for main descriptions and principles.
********************************************************************************************************

NAME
====

   Tk::TM::Try - Tk Transaction Manager Error processing functions.  See
Tk::TM::Lib for main descriptions and principles.

SYNOPSIS
========

     use Tk::TM::Try;
     Try sub{
          TryHdr('title','stage');
          TryHdr(undef,'stage1');
         }
        ,sub{
         };
     Try(sub{...},0);
     TryDBI $dbh
           ,sub{ #transaction
            }
           ,sub{ #after rollback
            };

DESCRIPTION
===========

   This module implements error processing functions may be used (or not
be used) in application.

VARIABLES
=========

     use vars qw($ErrorDie $Error);

$Tk::TM::Try::ErrorDie
     Die if error occurred. Default is false outside Try and true inside.

$Tk::TM::Try::Error
     Last error occurred. Value is $@.

FUNCTIONS
=========

     @EXPORT = qw(Try(@) TryDBI(@) TryHdr);

Try ( eval {...}, default ) -> result
Try ( eval {...}, \&catch ) -> result
Try ( sub  {...}, ... ) -> result
     Try-Catch construction.  Function Try returns result of eval on
     success.  If error occurred (determined by $@), it returns default
     value or result of catch evaluation.

TryDBI ( ?dbh, sub {...}, default ) -> result
TryDBI ( ?dbh, sub {...}, \&catch ) -> result
     Try-Catch construction for database transaction.  Default database
     handle may be given from current data object or $Tk::TM::Common::DBH.
     $dbh->{AutoCommit} and $dbh->{RaiseError} are used inside TryDBI.

TryHdr (subject, stage)
TryHdr (undef, stage)
     Declare title and/or stage name of transaction to insert into $@
     inside Try.  May be used only inside Try(sub{},...).

VERSION
=======

"02/04/2000"
     Created.

     TO DO:

     - Approve

     - Debug and Test

AUTHOR
======

   Andrew V Makarow <makarow@mail.com>, Denis E Medvedyuk <demed@mail.com>

Tk Transaction Manager Application Window. See Tk::TM::Lib for main descriptions and principles.
************************************************************************************************

NAME
====

   Tk::TM::wApp - Tk Transaction Manager Application Window.  See
Tk::TM::Lib for main descriptions and principles.

SYNOPSIS
========

     use Tk::TM::wApp;
     use DBI;

     my $mw  =new Tk::TM::wApp;

     $mw->setscr(0,'Login');
     $mw->setscr(0,'Screen 1',   \&Screen1);
     $mw->setscr(1,'Screen 1.1', \&Screen1_1);
     $mw->setscr(0,'Screen 2',   \&Screen2);
     $mw->Start();

     Tk::MainLoop;

     ..............................

     sub Screen1_1 { # two subs - for screen and for data object
      my ($self, $cmd, $opt, $mst) =@_;
      return(1) if $cmd =~/stop/;

     my $wgt=$self->{-wgscr}->tmTable(
              -rowcount=>10
             ,-colspecs=>[['Col1' ,'Entry']
                         ,['Col2' ,'Entry']
                         ,['Col3' ,'Entry']
                         ,['Col4' ,'Entry']]
             )->pack;

     my $do;
     if (!$self->{-dos}) {
        $do =new Tk::TM::DataObject();
        $self->{-dos} =[$do];
     }
     else {
        $do =$self->{-dos}->[0];
     }

     my $rwm =$mst->{-dos}->[0]->dsRowDta();
     my $flt =$rwm->[0];
     $self->{-title} =$flt;

     $do->set(-wgtbl=>$wgt
             ,-mdedt=>0
             ,-cbdbRead=>
                 sub{$_[0]->DBICmd("select * from table where field=?",$flt)}
             );

     $do->Retrieve('#reread')
      }

     ..............................

     sub Screen1_2 { # unified sub for screen with single data object
      my ($self, $cmd, $opt, $row, $fld, $wg, $dta, $new) =(shift, shift, @_);

      if    ($cmd eq 'stop')   {
            return(1)
      }
      elsif ($cmd eq 'start')  {

     my $wgt=$self->{-wgscr}->tmTable(
          -rowcount=>10
         ,-colspecs=>[['Name','Entry']]
         )->pack;

     my $do;
     if (!$self->{-dos}) {
        $do =new Tk::TM::DataObject();
        $self->{-dos} =[$do];
     }
     else {
        $do =$self->{-dos}->[0];
     }

     my $rwm =$row->{-dos}->[0]->dsRowDta();
     $do->{-parm}->{XXX} =$rwm->[0];
     $self->{-title} =$do->{-parm}->{dsn};

     $do->set(-wgtbl=>$wgt
             ,-mdedt=>0
             ,-cbcmd=>\&DataSources
             );
     $do->Retrieve('#reread')
       }
       elsif ($cmd eq 'dbRead') {
     $self->DBICmd("select...", $self->{-parm}->{XXX})
       }
       else  {return $self->doDefault($cmd, @_)}
      }

     ..............................

DESCRIPTION
===========

   This module implements application window with Tk Transaction Manager
features.  `Tk::TM::wApp' is level above Tk::TM::Lib, see there other
descriptions and principles.  There is no need to call 'use' for
Tk::TM::Lib, this is done by using `Tk::TM::wApp'.

   The components of application window are:

   Data editing bar menu with toolbar, implemented with Tk::TM::wgMenu
(tmMenu widget).

   Navigation pane with list of screen names to open, implemented with
`Tk::Tree'.

   Screen pane for widgets of application screens, implemented with
`Tk::Frame'.

PARAMETERS
==========

   Tk parameters of `Tk::TM::wApp' window may be set via configure Tk
method. They may be all parameters of `Tk::MainWindow'.

   TM parameters may be accessed via set method of `Tk::TM'. They are:
`-wgmnu', `-wgnav', `-wgscr', `-title', `-mdnav', `-parm'

-mdnav = 'treee' || 'tree' || 'lst'
     Mode of navigation between application screens.  Default is 'treee'
     ('tree exact'), that means that detail screen may be opened only if
     it`s master screen is current; this mode may be excluded in future.
     Mode 'tree' means that detail screen should be opened for it`s master
     screen and if master was previously used.  Mode 'lst' means that
     screens are using `-parm' values filled in 'stop' command of screen`s
     sub or doEnd event of data object.

-parm = {}
     Programmer`s parameters. This hash is also accessible via parameter
     `-parm' of tmMenu widget (Tk::TM::wgMenu), accessible via `-wgmnu'.

-title = $mw->cget(-title)
     Title of application, the first part of window`s title.  Other parts
     are combined for current application`s screen.  Default value is
     title of the window.

-wgnav
     Widget with list of all available application screens.  This is
     navigation pane of application.  `Tk::Tree' is used.

-wgmnu
     Menu and toolbar for data editing.  tmMenu widget (Tk::TM::wgMenu) is
     used.

-wgscr
     Widget for application screens, to create application widgets inside
     it.  `Tk::Frame' widget is used.

METHODS
=======

   Common object methods as new, initialize, set are described under
Tk::TM::Lib.

   Special methods are setscr, Start.

setscr (level, label, ?sub, ?parm, ?opt)
     Defines screen of application.  Level is number of nest of screen in
     tree, where 0 is top level.  Label of the screen will be displayed at
     the navigation pane and as part of the title of the window.  Special
     label 'Login' is used for predefined login screen.  Sub is code to
     create widgets and data objects of screen.  Sub may also be filename
     relative to $0 path, it will be executed with do to obtain code.
     Parm is hash reference with parameters of the screen to use inside
     sub.  Opt is hash reference with screen options, available via screen
     description, see \&callback.

Start
     Opens the first screen of application.

CALLBACK INTERFACE
==================

\&callback (self, command, opt, parent)
     setscr method defines callback to start and stop application screen.
     Parameters are description of this screen, command ('start' or
     'stop'), option string, description of parent screen.

     The command is string 'start' or 'stop'.

     The descriptions are hash references with entries `-cbcmd', `-cbnme',
     `-do', `-dos', `-wgapp', `-wgmnu', `-wgscr', `-label', `-title',
     `-parm', `-parmc', `-reread', `-rereadc'

start
     Start performance of screen.  If `-dos' is not defined, this is the
     first open of screen.

stop
     Stop performance of screen.  The operation may be declared with
     'return(1)' only.

-cbcmd
     Reference to this callback sub.

-cbnme
     Name of this callback sub for dynamic loading.

-do
     Reference to first data object in `-dos' list, to shorten access from
     outside.

-dos
     Reference to list of data objects of screen. Callback should set it.
     At the first open of the screen this is not defined.

-label
     Label of the screen as displayed in `-wgnav'.  Title of application
     window is combined with title of application, label of the screen,
     title of the screen (described below at `-title')

-parm
     Programmer`s parameters of the screen, defined with setscr hash ref.
     It is not the same as '-parm' in `Tk::TM::wApp' or Tk::TM::wgMenu.

-parmc
     Common to `Tk::TM::wApp' or Tk::TM::wgMenu object programmer`s
     parameters.  This is also available via `-wgapp' or `-wgmnu'.

-reread
     Reread this master screen internally before it's detail open.

-rereadc
     Reread this master screen internally before it's detail open and turn
     off this toggle.

-title
     Title of the screen, represents data displayed on screen.  Title of
     application window is combined with title of application, label of
     the screen (described above at `-label'), title of the screen.

-wgapp
     Application window, provided by `Tk::TM::wApp'.

-wgmnu
     Application`s menu bar, provided by `Tk::TM::wApp'.

-wgscr
     Widget for application screen, to create application widgets inside
     it.  Provided by `Tk::TM::wApp'.  `Tk::Frame' widget is used.

VERSION
=======

"16-18/11/2000"
     Status Line implemented.

"22-25/10/2000"
     exit calls replaced with `Tk::exit' calls to avoid abnormal program
     terminations.

     Tk::TM::Common::DBILogin used for login screen.

     setscr - Sub may be filename relative to $0 path, it will be executed
     with do to obtain code. Opt parameter added.

     Master's DataObject data is not retrieved when it's detail opening,
     as in 'tree' mode was. Application supposes now that only current row
     of master data is needed and this is unchanged in database by other
     screens.  To do internal reread `-reread' and `-rereadc' screen
     descriptions may be used.

     Error processing for callbacks added.

     `-do' screen description created.

     `-opt' screen description removed, `-parm' should be used instead.

     `-parmc' screen description created.

     `-wglst' parameter of `Tk::TM::wApp' renamed to `-wgnav'.

     `-mdlst' parameter of `Tk::TM::wApp' renamed to `-mdnav'.  New value
     'treee' ('tree exact') is set as default.

"06/02/2000"
     TO DO:

     - Approve

     - Debug and Test

"31/01/2000"
     Created.

AUTHOR
======

   Andrew V Makarow <makarow@mail.com>, Denis E Medvedyuk <demed@mail.com>

An alternative to the NoteBook widget : a tabbed geometry manager
*****************************************************************

NAME
====

   Tk::TabFrame - An alternative to the NoteBook widget : a tabbed
geometry manager

SYNOPSIS
========

     use Tk::TabFrame;

     $TabbedFrame = $widget->TabFrame
        (
         -font => '-adobe-times-medium-r-normal--20-*-*-*-*-*-*-*',
         -tabcurve => 2,
         -padx => 5,
         -pady => 5,
         [normal frame options...],
        );

     font     - font for tabs
     tabcurve - curve to use for top corners of tabs
     padx     - padding on either side of children
     pady     - padding above and below children

     $CurrentSelection = $l_Window->cget ('-current');
     $CurrentSelection = $l_Window->cget ('-raised');

     current  - (Readonly) currently selected widget
     raised   - (Readonly) currently selected widget

     $child = $TabbedFrame->Frame # can also be Button, Label, etc
        (
         -caption => 'Tab label',
         -tabcolor => 'yellow',
         [widget options...],
        );

     caption  - label text for the widget's tab
     tabcolor - background for the tab button

   Values shown above are defaults.

DESCRIPTION
===========

   A tabbed frame geometry manager (like NoteBook). I haven't used
NoteBook so I can't really say what behaviour differences or similarities
there are. This widget uses direct subwidget creation (no Add methods) and
has colors for the tabs.

AUTHORS
=======

   Damion K. Wilson, dkw@rcm.bm

HISTORY
=======

   January 28, 1998 : Created

   February 2, 1999 : raise/lower semantics changed somehow in Tk800.012.
Added                    explicit lower calls for frame and button
reordering.

a form management arrangement using Tk::TabFrame
************************************************

NAME
====

   Tk::TabbedForm - a form management arrangement using Tk::TabFrame

SYNOPSIS
========

     use Tk;

     my $MainWindow = MainWindow->new();

     Tk::MainLoop;

DESCRIPTION
===========

   An extended TabFrame, allowing managed subwidgets used as entry fields.
Each field widget is given a 'set' and a 'get' method to provide widget
independent methods of maintaining and querying data. The form will pass
back a hash of all field values on request.

AUTHORS
=======

   Damion K. Wilson, dkw@rcm.bm

HISTORY    =cut
===============

Scrollable 2 dimensional table of Tk widgets
********************************************

NAME
====

   Tk::Table - Scrollable 2 dimensional table of Tk widgets

SYNOPSIS
========

     use Tk::Table;

     $table = $parent->Table(-rows => number,
                             -columns => number,
                             -scrollbars => anchor,
                             -fixedrows => number,
                             -fixedcolumns => number,
                             -takefocus => boolean);

     $widget = $table->Button(...);

     $old = $table->put($row,$col,$widget);
     $old = $table->put($row,$col,"Text");  # simple Label
     $widget = $table->get($row,$col);

     $cols = $table->totalColumns;
     $rows = $table->totalRows;

     $table->see($widget);
     $table->see($row,$col);

     ($row,$col) = $table->Posn($widget);

DESCRIPTION
===========

   Tk::Table is an all-perl widget/geometry manager which allows a two
dimensional table of arbitary perl/Tk widgets to be displayed.

   Entries in the Table are simply ordinary perl/Tk widgets. They should
be created with the Table as their parent. Widgets are positioned in the
table using:

     $table->put($row,$col,$widget)

   All the widgets in each column are set to the same width - the requested
width of the widest widget in the column.  Likewise, all the widgets in
each row are set to the same height - the requested height of the tallest
widget in the column.

   A number of rows and/or columns can be marked as 'fixed' - and so can
serve as 'headings' for the remainder the rows which are scrollable.

   The requested size of the table as a whole is such that the number of
rows specified by -rows (default 10), and number of columns specified by
-columns (default 10) can be displayed.

   If the Table is told it can take the keyboard focus then cursor and
scroll keys scroll the displayed widgets.

   The Table will create and manage its own scrollbars if requested via
-scrollbars.

   The Tk::Table widget is derived from a Tk::Frame, so inherits all its
configure options.

BUGS / Snags / Possible enhancements
====================================

   * Very large Tables consume a lot of X windows

   * No equivalent of pack's -anchor/-pad etc. options

A simple flat-file DBMS editor using Tk::SplitFrame, Tk::TabbedForm, and Tk::Columns
************************************************************************************

NAME
====

   Tk::TableEdit - A simple flat-file DBMS editor using Tk::SplitFrame,
Tk::TabbedForm, and Tk::Columns

SYNOPSIS
========

     use Tk;

     my $MainWindow = MainWindow->new();

     Tk::MainLoop;

DESCRIPTION
===========

   A compound widget built from the TabbedForm, SplitFrame, and Column
widgets. It implements a simplified interface to a flat file database. Try
out the demo.

AUTHORS
=======

   Damion K. Wilson, dkw@rcm.bm

HISTORY    =cut
===============

Create and manipulate tables
****************************

NAME
====

   TableMatrix - Create and manipulate tables

Synopsis
========

   *$table* = *$parent*->*TableMatrix*(?options?);

STANDARD OPTIONS
================

   *-anchor  -background  -cursor    -exportselection  -font  -foreground
 -highlightbackground  -highlightcolor  -highlightthickness
-insertbackground  -insertborderwidth  -insertofftime    -insertontime
-insertwidth  -invertselected  -padx    -pady  -relief  -takefocus
-xscrollcommand    -yscrollcommand*

Widget-specific Options
=======================

Switch: *-autoclear*
Name: *autoClear*
Class: *AutoClear*
     A boolean value which specifies whether the first keypress in a cell
     will delete whatever text was previously there.  Defaults to 0.

Switch:  *-bordercursor*
Name: *borderCursor*
Class: Cursor
     Specifies the name of the cursor to show when over borders, a visual
     indication that interactive resizing is allowed (it is thus affect by
     the value of -resizeborders).  Defaults to *crosshair *.

Switch: *-borderwidth or -bd*
Name: *borderWidth*
Class: *BorderWidth*
     Specifies a non-negative value indicating the width of the 3-D border
     to draw on interior table cells (if such a border is being drawn; the
     *relief * option typically determines this).  This can be overridden
     by the a tag's borderwidth option.  It can also be affected by the
     defined *-drawmode* for the table.  The value may have any of the
     forms acceptable to *Tk_GetPixels*.

Switch: *-browsecommand or -browsecmd*
Name: *browseCommand*
Class: *BrowseCommand*
     Specifies a command (callback) which will be evaluated anytime the
     active cell changes. The Previous Index and the Current index is
     passed to this command as arguments.

Switch: *-cache*
Name: cache
Class: Cache
     A boolean value that specifies whether an internal cache of the table
     contents should be kept.  This greatly enhances speed performance
     when used with *-command * but uses extra memory.  Can maintain state
     when both *-command * and *-variable * are empty.  The cache is
     automatically flushed whenever the value of *-cache * or *-variable *
     changes, otherwise you have to explicitly *flush * it.  Defaults to
     false.

Switch: *-colorigin*
Name: *colOrigin*
Class: *Origin*
     Specifies what column index to interpret as the leftmost column in
     the table. This value is used for user indices in the table.
     Defaults to 0.

Switch: *-cols*
Name: *cols*
Class: *Cols*
     Number of cols in the table.  Defaults to 10.

Switch: *-colseparator*
Name: *colSeparator*
Class: Separator
     Specifies a separator character that will be interpreted as the
     column separator when cutting or pasting data in a table.  By default,
     columns are separated as elements of a tcl list.

Switch: *-colstretchmode*
Name: *colStretchMode*
Class: *StretchMode*
     Specifies one of the following stretch modes for columns to fill
     extra allocated window space:

*none *
     Columns will not stretch to fill the assigned window space.  If the
     columns are too narrow, there will be a blank space at the right of
     the table.  This is the default.

*unset *
     Only columns that do not have a specific width set will be stretched.

*all *
     All columns will be stretched by the same number of pixels to fill
     the window space allocated to the table.  This mode can interfere
     with interactive border resizing which tries to force column width.

*last *
     The last column will be stretched to fill the window space allocated
     to the table.

*fill *
     (only valid for *-rowstretch * currently)

     The table will get more or less columns according to the window space
     allocated to the table.  This mode has numerous quirks and may
     disappear in the future.

Switch: *-coltagcommand*
Name: *colTagCommand*
Class: *TagCommand*
     Provides the name of a procedure that will be evaluated by the widget
     to determine the tag to be used for a given column.  When displaying
     a cell, the table widget will first check to see if a tag has been
     defined using the *tag col * widget method.  If no tag is found, it
     will evaluate the named procedure passing the column number in
     question as the sole argument.  The procedure is expected to return
     the name of a tag to use, or a null string. Errors occuring during
     the evaluation of the procedure, or the return of an invalid tag name
     are silently ignored.

     The Current column number is passed as an argument to the col command.

Switch: *-colwidth*
Name: *colWidth*
Class: *ColWidth*
     Default column width, interpreted as characters in the default font
     when the number is positive, or pixels if it is negative.  Defaults
     to 10.

Switch: *-command*
Name: command
Class: Command
     Specified a command to use as a procedural interface to cell values.
     If *-usecommand * is true, this command will be used instead of any
     reference to the *-variable * array.  When retrieving cell values,
     the return value of the command is used as the value for the cell.

     Args passed to this callback: The Set Flag (=1 if setting, else
     retrieving), the current row, the current col, the cell value (if
     setting).

Switch: *-drawmode*
Name: *drawMode*
Class: *DrawMode*
     Sets the table drawing mode to one of the following options:

*slow *
     The table is drawn to an offscreen pixmap using the Tk bordering
     functions (double-buffering).  This means there will be no flashing,
     but this mode is slow for larger tables.

*compatible *
     The table is drawn directly to the screen using the Tk border
     functions. It is faster, but the screen may flash on update.  This is
     the default.

*fast *
     The table is drawn directly to the screen and the borders are done
     with fast X calls, so they are always one pixel wide only.  As a side
     effect, it restricts *-borderwidth * to a range of 0 or 1.  This mode
     provides best performance for large tables, but can flash on redraw
     and is not 100% Tk compatible on the border mode.

*single *
     The table is drawn to the screen as in fast mode, but only single
     pixel lines are drawn (not square borders).

Switch: *-flashmode*
Name: *flashMode*
Class: *FlashMode*
     A boolean value which specifies whether cells should flash when their
     value changes.  The table tag *flash * will be applied to these cells
     for the duration specified by *-flashtime *.  Defaults to 0.

Switch: *-flashtime*
Name: *flashTime*
Class: *FlashTime*
     The amount of time, in 1/4 second increments, for which a cell should
     flash when its value has changed.  *-flashmode * must be on.  Defaults
     to 2.

Switch: *-height*
Name: height
Class: *Height*
     Specifies the desired height for the window, in rows. If zero or less,
     then the desired height for the window is made just large enough to
     hold all the rows in the table.  The height can be further limited by
     *-maxheight *.

Switch: *-invertselected*
Name: *invertSelected*
Class: *InvertSelected*
     Specifies whether the foreground and background of an item should
     simply have their values swapped instead of merging the *sel * tag
     options when the cell is selected.  Defaults to 0 (merge).

Switch: *-maxheight*
Name: *maxHeight*
Class: *MaxHeight*
     The max height in pixels that the window will request.  Defaults to
     600.

Switch: *-maxwidth*
Name: *maxWidth*
Class: *MaxWidth*
     The max width in pixels that the window will request.  Defaults to
     800.

Switch: *-multiline*
Name: *multiline*
Class: Multiline
     Specifies the default setting for the multiline tag option.  Defaults
     to 1.

Switch: *-resizeborders*
Name: *resizeBorders*
Class: *ResizeBorders*
     Specifies what kind of interactive border resizing to allow, must be
     one of row, col, both (default) or none.

Switch: *-rowheight*
Name: *rowHeight*
Class:
     *RowHeight*  Default row height, interpreted as lines in the default
     font when the number is positive, or pixels if it is negative.
     Defaults to 1.

Switch: *-roworigin*
Name: *rowOrigin*
Class: *Origin*
     Specifies what row index to interpret as the topmost row in the
     table. This value is used for user indices in the table.  Defaults to
     0.

Switch: *-rows*
Name: rows
Class: *Rows*
     Number of rows in the table.  Defaults to 10.

Switch: *-rowseparator*
Name: *rowSeparator*
Class: Separator
     Specifies a separator character that will be interpreted as the row
     separator when cutting or pasting data in a table.  By default, rows
     are separated as tcl lists.

Switch: *-rowstretchmode*
Name: *rowStretchMode*
Class: *StretchMode*
     Specifies the stretch modes for rows to fill extra allocated window
     space.  See *-colstretchmode * for valid options.

Switch: *-rowtagcommand*
Name: *rowTagCommand*
Class: *TagCommand*
     Provides the name of a procedure that can evaluated by the widget to
     determine the tag to be used for a given row.  The procedure must be
     defined by the user to accept a single argument (the row number), and
     return a tag name or null string.  This operates in a similar manner
     as *-coltagcommand *, except that it applies to row tags.

     The Current row number is passed as an argument to the row command.

Switch: *-selectioncommand or -selcmd*
Name: *selectionCommand*
Class: *SelectionCommand*
     Specifies a command (callback) to evaluate when the selection is
     retrieved from a table via the selection mechanism (ie: evaluating
     "*selection get *"). The return value from this command will become
     the string passed on by the selection mechanism.  The following
     arguments are passed to this callback: The number of rows in the
     selection, number of columns in the selection, the selection string,
     the number of cell in the selection.

Switch: *-selectmode*
Name: *selectMode*
Class: *SelectMode*
     Specifies one of several styles for manipulating the selection.  The
     value of the option may be arbitrary, but the default bindings expect
     it to be either *single *, *browse *, *multiple *, or *extended *; the
     default value is *browse *.  These styles are like those for the Tk
     listbox, except expanded for 2 dimensions.

Switch: *-selecttitle*
Name: *selectTitles*
Class: *SelectTitles*
     Specifies whether title cells should be allowed in the selection.
     Defaults to 0 (disallowed).

Switch: *-selecttype*
Name: *selectType*
Class: *SelectType*
     Specifies one of several types of selection for the table.  The value
     of the option may be one of *row *, *col *, *cell *, or *both *
     (meaning *row && col *); the default value is *cell *.  These types
     define whether an entire row/col is affected when a cell's selection
     is changed (set or clear).

Switch: *-sparsearray*
Name: *sparseArray*
Class: *SparseArray*
     A boolean value that specifies whether an associated Tcl array should
     be kept as a sparse array (1, the default) or as a full array (0).
     If true, then cell values that are empty will be deleted from the
     array (taking less memory).  If false, then all values in the array
     will be maintained.

Switch: *-state*
Name: state
Class: State
     Specifies one of two states for the entry:  *normal * or disabled.
     If the table is disabled then the value may not be changed using
     widget commands and no insertion cursor will be displayed, even if
     the input focus is in the widget.  Also, all insert or delete methods
     will be ignored.  Defaults to *normal *.

Switch: *-titlecols*
Name: *titleCols*
Class: *TitleCols*
     Number of columns to use as a title area.  Defaults to 0.

Switch: *-titlerows*
Name: *titleRows*
Class: *TitleRows*
     Number of rows to use as a title area.  Defaults to 0.

Switch: *-usecommand*
Name: *useCommand*
Class: *UseCommand*
     A boolean value which specifies whether to use the *command * option.
     This value sets itself to zero if *command * is used and returns an
     error. Defaults to 1 (will use *command * if specified).

Switch: *-validate*
Name: validate
Class: *Validate*
     A boolean specifying whether validation should occur for the active
     buffer. Defaults to 0.

Switch: *-validatecommand or -vcmd*
Name: *validateCommand*
Class: *ValidateCommand*
     Specifies a command (callback) to execute when the active cell is
     edited.  This command is expected to return a 1 or 0.  If it returns
     1, then it is assumed the new value is OK, otherwise the new value is
     rejected (the edition will not take place).  Errors in this command
     are handled in the background. The following arguments are supplied
     to the callback: row, col, oldContents of cell, potential new
     contents of cell, Current Index in the cell.

Switch: *-variable*
Name: variable
Class: Variable
     Global Tcl array variable to attach to the table's C array.  It will
     be created if it doesn't already exist or is a simple variable.  Keys
     used by the table in the array are of the form *row *,*col * for
     cells and the special key *active * which contains the value of the
     active cell buffer.  The Tcl array is managed as a sparse array (the
     table doesn't require all valid indices have values).  No stored value
     for an index is equivalent to the empty string, and clearing a cell
     will remove that index from the Tcl array, unless the *-sparsearray *
     options is set to 0.

Switch: *-width*
Name: width
Class: Width
     Specifies the desired width for the window, in columns. If zero or
     less, then the desired width for the window is made just large enough
     to hold all the columns in the table.  The width can be further
     limited by *-maxwidth *.

Switch: *-wrap*
Name: wrap
Class: *Wrap*
     Specifies the default wrap value for tags.  Defaults to 0.

DESCRIPTION
===========

   The *TableMatrix * command creates a 2-dimensional grid of cells.  The
table can use a Tcl array variable or Tcl command for data storage and
retrieval.  The widget has an active cell, the contents of which can be
edited (when the state is normal).  The widget supports a default style
for the cells and also multiple *tags *, which can be used to change the
style of a row, column or cell (see TAGS for details).  A cell *flash *
can be set up so that changed cells will change color for a specified
amount of time ("blink").   Cells can have embedded images or windows, as
described in `Tags' in this node and `Embedded Windows' in this node
respectively.

   One or more cells may be selected as described below.   If a table is
exporting its selection (see *-exportselection * option), then it will
observe the standard X11 protocols for handling the selection.   See `the
Selection' in this node for details. It is not necessary for all the cells
to be displayed in the table window at once; commands described below may
be used to change the view in the window. Tables allow scrolling in both
directions using the standard *-xscrollcommand * and *-yscrollcommand *
options.   They also support scanning, as described below.

   In order to obtain good performance, the table widget supports multiple
drawing modes, two of which are fully Tk compatible.

Indices
=======

   Many of the widget commands for tables take one or more indices as
arguments. An index specifies a particular cell of the table, in any of
the following ways:

*number,number *
     Specifies the cell as a numerical index of row,col which corresponds
     to the index of the associated Tcl array, where
     *-roworigin,-colorigin * corresponds to the first cell in the table
     (0,0 by default).

*active *
     Indicates the cell that has the location cursor. It is specified with
     the *activate * widget command.

*anchor *
     Indicates the anchor point for the selection, which is set with the
     *selection anchor * widget command.

*bottomright *
     Indicates the bottom-rightmost cell visible in the table.

*end *
     Indicates the bottom right cell of the table.

*origin *
     Indicates the top-leftmost editable cell of the table, not
     necessarily in the display.  This takes into account the user
     specified origin and title area.

*topleft *
     Indicates the top-leftmost editable cell visible in the table (this
     excludes title cells).

*@x,y*
     Indicates the cell that covers the point in the table window
     specified by *x * and *y * (in pixel coordinates).  If no cell covers
     that point, then the closest cell to that point is used. In the
     widget command descriptions below, arguments named *index *, *first
     *, and *last * always contain text indices in one of the above forms.

Tags
====

   A tag is a textual string that is associated with zero or more rows,
columns or cells in a table.  Tags may contain arbitrary characters, but
it is probably best to avoid using names which look like indices.  There
may be any number of tags associated with rows, columns or cells in a
table.  There are several permanent tags in each table that can be
configured by the user and will determine the attributes for special cells:

*active *
     This tag is given to the *active * cell

*flash *
     If flash mode is on, this tag is given to any recently edited cells.

*sel *
     This tag is given to any selected cells.

*title *
     This tag is given to any cells in the title rows and columns.  This
     tag has *-state * *disabled * by default.

   Tags control the way cells are displayed on the screen.  Where
appropriate, the default for displaying cells is determined by the options
for the table widget.  However, display options may be associated with
individual tags using the `tagConfigure' in this node method.  If a cell
has been tagged, then the display options associated with the tag override
the default display style.  The following options are currently supported
for tags:

*-anchor* anchor
     Anchor for item in the cell space.

*-background * or *-bg * *color *
     Background color of the cell.

*-borderwidth * or *-bd * *pixels *
     Borderwidth of the cell.

*-font* *fontName *
     Font for text in the cell.

*-foreground* or *-fg * *color *
     Foreground color of the cell.

-justify *justify *
     How to justify multi-line text in a cell. It must be one of *left *,
     *right *, or center.

*-image* *imageName *
     An image to display in the cell instead of text.

*-multiline* *boolean *
     Whether to display text with newlines on multiple lines.

*-relief*
     The relief for the cell.

*-showtext* boolean
     Whether to show the text over an image.  This does not currently work
     on Windows or Mac for all cases due to the lack of clipping support
     in Tk's X emulation (patch submitted).

*-state* state
     The state of the cell, to allow for certain cells to be disabled.
     This prevents the cell from being edited by the *insert * or *delete
     * methods, but a direct *set * will not be prevented.

*-wrap* boolean
     Whether characters should wrap in a cell that is not wide enough.

   A priority order is defined among tags, and this order is used in
implementing some of the tag-related functions described below.  When a
cell is displayed, its properties are determined by the tags which are
assigned to it.  Including the special tags, this order is *flash *,
*active *, *sel *, *title *, *celltag *, *rowtag *, *coltag *, default.

   If a cell has several tags associated with it, and if their display
options conflict, then the options of the highest priority tag are used.
If a particular display option hasn't been specified for a particular tag,
or if it is specified as an empty string, then that option will never be
used; the next-highest-priority tag's option will used instead.  If no tag
specifies a particular display option, then the default style for the
widget will be used.

   Images are used for display purposes only.  Editing in that cell will
still be enabled and any querying of the cell will show the text value of
the cell, regardless of the value of *-showtext *.

Embedded Windows
================

   There may be any number of embedded windows in a table widget (one per
cell), and any widget may be used as an embedded window (subject to the
usual rules for geometry management, which require the table window to be
the parent of the embedded window or a descendant of its parent).  The
embedded window's position on the screen will be updated as the table is
modified or scrolled, and it will be mapped and unmapped as it moves into
and out of the visible area of the table widget.  Each embedded window
occupies one cell's worth of space in the table widget, and it is referred
to by the index of the cell in the table.  Windows associated with the
table widget are destroyed when the table widget is destroyed.

   Windows are used for display purposes only.  A value still exists for
that cell, but will not be shown unless the window is deleted in some way.
If the window is destroyed or lost by the table widget to another geometry
manager, then any data associated with it is lost (the cell it occupied
will no longer appear in *window names *).

   When an embedded window is added to a table widget with the window
configure widget command, several configuration options may be associated
with it.  These options may be modified with later calls to the window
configure widget command.  The following options are currently supported:

*-create* callback
     NOT CURRENTLY SUPPORTED.  Specifies a Tcl script that may be
     evaluated to create the window for the annotation.   If no -window
     option has been specified for this cell then this script will be
     evaluated when the cell is about to be displayed on the screen.
     Script must create a window for the cell and return the name of that
     window as its result. If the cell's window should ever be deleted,
     the script will be evaluated again the next time the cell is
     displayed.

*-background* or *-bg* color
     Background color of the cell.  If not specified, it uses the table's
     default background.

*-padx* *pixels *
     As defined in the Tk options man page.

*-pady* *pixels*
     As defined in the Tk options man page.

*-relief* *relief*
     The relief to use for the cell in which the window lies.  If not
     specified, it uses the table's default relief.

*-sticky* *sticky *
     Stickiness of the window inside the cell, as defined by the *grid *
     command.

*-window* $widget
     Specifies the a window to display in the  annotation.  It must exist
     before being specified here.

the Selection
=============

   Table selections are available as type STRING.  By default, the value
of the selection will be the values of the selected cells in nested Tcl
list form where each row is a list and each column is an element of a row
list. You can change the way this value is interpreted by setting the
*-rowseparator * and *-colseparator * options.   For example, default
Excel format would be to set *-rowseparator * to "\n" and *-colseparator *
to "\t".  Changing these values affects both how the table sends out the
selection and reads in pasted data, ensuring that the table should always
be able to cut and paste to itself.  It is possible to change how pastes
are handled by editing the table library procedure *tk_tablePasteHandler
*.  This might be necessary if *-selectioncommand * is set.

Row/Col Spanning
================

   Individual cells can span multiple rows and/or columns.  This is done
via the *spans * command (see below for exact arguments).  Cells in the
title area that span are not permitted to span beyond the title area, and
will be constrained accordingly.  If the title area shrinks during a
configure, sanity checking will occur to ensure the above.  You may set
spans on regular cells that extend beyond the defined row/col area.  These
spans will not be constrained, so that when the defined row/col area
expands, the span will expand with it.

   When setting a span, checks are made as to whether the span would
overlap an already spanning or hidden cell.  This is an error and it not
allowed. Spans can affect the overall speed of table drawing, although not
significantly.  If spans are not used, then there is no performance loss.

   Cells *hidden * by spanning cells still have valid data.  This will be
seen during cut and paste operations that involve hidden cells, or through
direct access by a command like *get * or *set *.

   The drawing properties of spanning cells apply to only the visual area
of the cell.  For example, if a cell is center justified over 5 columns,
then when viewing any portion of those columns, it will appear centered in
the visible area. The non-visible column area will not be considered in
the centering calculations.

Command Substitution
====================

   The various option based commands that the table supports all support
the familiar Tk %-substitution model (see `Tk::bind ' in this node for
more details).   The following %-sequences are recognized and substituted
by the table widget:

*%c *
     For *SelectionCommand *, it is the maximum number of columns in any
     row in the selection.  Otherwise it is the column of the triggered
     cell.

*%C *
     A convenience substitution for *%r *,*%c *.

*%i *
     For *SelectionCommand*, it is the total number of cells in the
     selection. For *Command *, it is 0 for a read (get) and 1 for a write
     (set). Otherwise it is the current cursor position in the cell.

%r
     For *SelectionCommand *, it is the number of rows in the selection.
     Otherwise it is the row of the triggered cell.

*%s *
     For *ValidateCommand *, it is the current value of the cell being
     validated.  For *SelectionCommand *, it is the default value of the
     selection. For *BrowseCommand *, it is the index of the last active
     cell. For *Command *, it is empty for reads (get) and the current
     value of the cell for writes (set).

*%S *
     For *ValidateCommand *, it is the potential new value of the cell
     being validated.  For *BrowseCommand *, it is the index of the new
     active cell.

*%W *
     The pathname to the window for which the command was generated.

Widget Methods
==============

   The *$window-*>*TableMatrix * method creates a widget object. This
object supports the configure and cget methods described in
Tk/options, which can be used to enquire and modify the
options described above.  The widget also inherits all the methods
provided by the generic `Tk::Widget|Tk::Widget' in this node class.

   The following additional methods are available for scale widgets:

*$table*->activate(index)
     Sets the active cell to the one indicated by index.

*$table*->*bbox*(first, ?last?)
     It returns the bounding box for the specified cell (range) as a
     4-tuple of x, y, width and height in pixels.  It clips the box to the
     visible portion, if any, otherwise an empty string is returned.

*$table*->border(*option, args*)
     This command is a voodoo hack to implement border sizing for tables.
     This is normally called through bindings, with the following as valid
     options:

*$table*->*borderMark*(*x, y*, ?*row|col*?)
     Records *x * and *y * and the row and/or column border under that
     point in the table window, if any; used in conjunction with later
     *border dragto * commands.  Typically this command is associated with
     a mouse button press in the widget.  If *row * or *col * is not
     specified, it returns a tuple of both border indices (an empty item
     means no border). Otherwise, just the specified item is returned.

*$table*->*borderDragto*(*x, y*)
     This command computes the difference between its *x * and *y *
     arguments and the *x * and *y * arguments to the last *border mark *
     command for the widget.  It then adjusts the previously marked border
     by the difference.  This command is typically associated with mouse
     motion events in the widget, to produce the effect of interactive
     border resizing.

*$table*->cget(option)
     Returns the current value of the configuration option given by
     *option *.  *Option * may have any of the values accepted by the
     *table * command.

*$table*->clear(option, ?first?, ?last?)
     This command is a convenience routine to clear certain state
     information managed by the table.  *first * and *last * represent
     valid table indices.  If neither are specified, then the command
     operates on the whole table.  The following options are recognized:

*$table*->*clearCache*(?first?, ?last?)
     Clears the specified section of the cache, if the table has been
     keeping one.

*$table*->*clearSizes*(?first?, ?last?)
     Clears the specified row and column areas of specific height/width
     dimensions.  When just one index is specified, for example *2,0 *,
     that is interpreted as row 2 *and * column 0.

*$table*->*clearTags*(?first?, ?last?)
     Clears the specified area of tags (all row, column and cell tags).

*$table*->*clearAll*(?first?, ?last?)
     Performs all of the above clear functions on the specified area.

*$table*->*colWidth*(?*col*?, ?*value, col, value, ...*?)
     If no *col * is specified, returns a list describing all cols for
     which a width has been set.  If *col * is specified with no value, it
     prints out the width of that col in characters (positive number) or
     pixels (negative number).  If one or more *col-value * pairs are
     specified, then it sets each col to be that width in characters
     (positive number) or pixels (negative number).  If *value * is
     *default *, then the col uses the default width, specified by
     *-colwidth *.

    *$table*->configure(?option?, ?*value, option, value, ...*?)
          Query or modify the configuration options of the widget. If no
          *option * is specified, returns a list describing all of the
          available options for *pathName * (see *Tk_ConfigureInfo * for
          information on the format of this list).  If *option * is
          specified with no *value *, then the command returns a list
          describing the one named option (this list will be identical to
          the corresponding sublist of the value returned if no *option *
          is specified).  If one or more *option-value * pairs are
          specified, then the command modifies the given widget option(s)
          to have the given value(s);  in this case the command returns an
          empty string. *Option * may have any of the values accepted by
          the *table * command.

    *$table*->*curselection*(?value?)
          With no arguments, it returns the sorted indices of the currently
          selected cells.  Otherwise it sets all the selected cells to the
          given value.  The set has no effect if there is no associated
          Tcl array or the state is disabled.

    *$table*->*curvalue*(?value?)
          If no value is given, the value of the cell being edited
          (indexed by *active *) is returned, else it is set to the given
          value.

    *$table*->delete(*option, arg*, ?*arg*?)
          This command is used to delete various things in a table.  It
          has several forms, depending on the *option *:

    *$table*->*deleteActive*(index, ?index?)
          Deletes text from the active cell.  If only one index is given,
          it deletes the character after that index, otherwise it deletes
          from the first index to the second.  *index * can be a number,
          *insert * or *end *.

    *$table*->*deleteCols*(?switches?, index, ?count?)
          Deletes *count * cols starting at (and including) col *index *.
          The *index * will be constrained to the limits of the tables.
          If *count * is negative, it deletes cols to the left.  Otherwise
          it deletes cols to the right.  *count * defaults to 1 (meaning
          just the column specified).  The selection will be cleared.  At
          the moment, spans are not adjusted with this action.  Optional
          switches are:

    *-holddimensions *
          Causes the table cols to be unaffected by the deletion (empty
          cols may appear).   By default the dimensions are adjusted by
          *count *.

    *-holdtags *
          Causes the tags specified by the *tag * method to not move along
          with the data.  Also prevents specific widths set by the *width
          * method from being adjusted.   By default, these tags are
          properly adjusted.

    *-holdwindows *
          Causes the embedded windows created with the *window * method to
          not move along with the data.  By default, these windows are
          properly adjusted.

    *-keeptitles *
          Prevents title area cells from being changed.  Otherwise they
          are treated just like regular cells and will move as specified.

    *$table*->*deleteRows*(?switches?, index, ?count?)
          Deletes *count * rows starting at (and including) row *index *.
          If *count * is negative, it deletes rows going up.  Otherwise it
          deletes rows going down.  The selection will be cleared.  The
          switches are the same as those for column deletion.

    *$table*->get(first, ?last?)
          Returns the value of the cells specified by the table indices
          *first * and (optionally) *last * in a list.

    *$table*->hidden(?index?, ?*index, ...*?)
          When called without args, it returns all the *hidden * cells
          (those cells covered by a spanning cell).  If one index is
          specified, it returns the spanning cell covering that index, if
          any.  If multiple indices are specified, it returns 1 if all
          indices are hidden cells, 0 otherwise.

    *$table*->*icursor*(?*arg*?)
          With no arguments, prints out the location of the insertion
          cursor in the active cell.  With one argument, sets the cursor
          to that point in the string.  0 is before the first character,
          you can also use *insert * or *end * for the current insertion
          point or the end of the text.  If there is no active cell, or
          the cell or table is disabled, this will return -1.

    *$table*->index(index, ?*row|col*?)
          Returns the integer cell coordinate that corresponds to *index *
          in the form row,col.  If *row * or *col * is specified, then
          only the row or column index is returned.

    *$table*->insert(*option, arg, arg*)
          This command is used to into various things into a table.  It
          has several forms, depending on the *option *:

    *$table*->*insertActive*(*index, value*)
          The *value * is a text string which is inserted at the *index *
          postion of the active cell.  The cursor is then positioned after
          the new text. *index * can be a number, *insert * or *end *.

    *$table*->*insertCols*(?switches?, index, ?count?)
          Inserts *count * cols starting at col *index *.  If *count * is
          negative, it inserts before the specified col.  Otherwise it
          inserts after the specified col.  The selection will be cleared.
          The switches are the same as those for column deletion.

    *$table*->*insertRows*(?switches?, index, ?count?)
          Inserts *count * rows starting at row *index *.  If *count * is
          negative, it inserts before the specified row.  Otherwise it
          inserts after the specified row.  The selection will be cleared.
          The switches are the same as those for column deletion.

    *$table*->*reread*()
          Rereads the old contents of the cell back into the editing
          buffer.  Useful for a key binding when <Escape> is pressed to
          abort the edit (a default binding).

    *$table*->*rowHeight*(?row?, ?*value, row, value, ...*?)
          If no *row * is specified, returns a list describing all rows
          for which a height has been set.  If *row * is specified with no
          value, it prints out the height of that row in characters
          (positive number) or pixels (negative number).  If one or more
          *row-value * pairs are specified, then it sets each row to be
          that height in lines (positive number) or pixels (negative
          number).  If *value * is *default *, then the row uses the
          default height, specified by *-rowheight *.

    *$table*->scan(*option, args*)
          This command is used to implement scanning on tables.  It has
          two forms, depending on *option *:

    *$table*->*scanMark*(*x, y*)
          Records *x * and *y * and the current view in the table window;
          used in conjunction with later *scan dragto * commands.
          Typically this command is associated with a mouse button press
          in the widget.  It returns an empty string.

    *$table*->*scanDragto*(*x, y*.)
          This command computes the difference between its *x * and *y *
          arguments and the *x * and *y * arguments to the last *scan mark
          * command for the widget.  It then adjusts the view by 5 times
          the difference in coordinates.  This command is typically
          associated with mouse motion events in the widget, to produce
          the effect of dragging the list at high speed through the
          window.  The return value is an empty string.

    *$table*->see(index)
          Adjust the view in the table so that the cell given by *index *
          is positioned as the cell one off from top left (excluding title
          rows and columns) if the cell is not currently visible on the
          screen.  The actual cell may be different to keep the screen
          full.

    *$table*->selection(*option, arg*)
          This command is used to adjust the selection within a table.
          It has several forms, depending on *option *:

    *$table*->*selectionAnchor*(index)
          Sets the selection anchor to the cell given by *index *.  The
          selection anchor is the end of the selection that is fixed while
          dragging out a selection with the mouse.  The index *anchor *
          may be used to refer to the anchor cell.

    *$table*->*selectionClear*(first?last?)
          If any of the cells between *first * and *last * (inclusive) are
          selected, they are deselected.   The selection state is not
          changed for cells outside this range.  *first * may be specified
          as *all * to remove the selection from all cells.

    *$table*->*selectionIncludes*(index)
          Returns 1 if the cell indicated by *index * is currently
          selected, 0 if it isn't.

    *$table*->*selectionSet*(first, ?last?)
          Selects all of the cells in the range between *first * and *last
          *, inclusive, without affecting the selection state of cells
          outside that range.

     perltk note this needs to be perlized

    *$table*->set(?*row|col*?, index, ?value?, ?*index, value, ...*?)
          Sets the specified index to the associated value.  Table
          validation will not be triggered via this method.  If *row * or
          *col * precedes the list of index/value pairs, then the value is
          assumed to be a Tcl list whose values will be split and set into
          the subsequent columns (if *row * is specified) or rows (for
          *col *).  For example, * set row 2,3 {2,3 2,4 2,5} * will set 3
          cells, from 2,3 to 2,5.  The setting of cells is silently
          bounded by the known table dimensions.

    *$table*->*spans*(?index?, ?*rows,cols, index, rows,cols, ...*?)
          This command is used to manipulate row/col spans.  When called
          with no arguments, all known spans are returned as a list of
          tuples of the form {index span}.  When called with only the
          *index *, the span for that *index * only is returned, if any.
          Otherwise an even number of *index rows,cols * pairs are used to
          set spans.  A span starts at the *index * and continues for the
          specified number of rows and cols. Negative spans are not
          supported.  A span of 0,0 unsets any span on that cell.  See
          EXAMPLES for more info.

    *$table*->tag(option, ?*arg, arg, ...*?)
          This command is used to manipulate tags.  The exact behavior of
          the command depends on the *option * argument that follows the
          *tag * argument. *cget *, *cell *, and *row|col * complain about
          unknown tag names.  The following forms of the command are
          currently supported:

    *$table*->*tagCell*(*tagName, ?index, ...?*)
          With no arguments, prints out the list of cells that use the
          *tag *. Otherwise it sets the specified cells to use the *tag *.
          If *tag * is ", the cells are reset to the default *tag *.
          Tags added during -*tagcommand evaluation do not register here.

    *$table*->*tagCget*(*tagName, option*)
          This command returns the current value of the option named
          *option * associated with the tag given by *tagName *.  *Option
          * may have any of the values accepted by the *tag configure *
          widget command.

    *$table*->*tagCol*(*tagName, ?col, ...?*)
          With no arguments, prints out the list of cols that use the *tag
          *. Otherwise it sets the specified cols to use the tag.  If *tag
          * is ", the cols are reset to the default *tag *.  Tags added
          during -coltagcommand evaluation do not register here.  If
          *tagName * does not exist, it is not created, but nor is an
          error generated.

    *$table*->*tagConfigure*(*tagName*, ?option?, ?value?, ?*option, value, ...*?)
          This command is similar to the *configure * widget command
          except that it modifies options associated with the tag given by
          *tagName * instead of modifying options for the overall table
          widget.  If no *option * is specified, the command returns a
          list describing all of the available options for *tagName * (see
          *Tk_ConfigureInfo * for information on the format of this list).
          If *option * is specified with no *value *, then the command
          returns a list describing the one named option (this list will
          be identical to the corresponding sublist of the value returned
          if no *option * is specified).  If one or more *option-value *
          pairs are specified, then the command modifies the given
          option(s) to have the given value(s) in *tagName *; in this case
          the command returns an empty string. See TAGS above for details
          on the options available for tags.

    *$table*->*tagDelete*(*tagName*)
          Deletes a tag.  No error if the tag does not exist.

    *$table*->*tagExists*(*tagName*)
          Returns 1 if the named tag exists, 0 otherwise.

    *$table*->*tagIncludes*(*tagName, index*)
          Returns 1 if the specified index has the named tag, 0 otherwise.

    *$table*->*tagNames*(?pattern?)
          If no pattern is specified, shows the names of all defined tags.
          Otherwise the *pattern * is used as a glob pattern to show only
          tags matching that pattern.

    *$table*->*tagRow*(*tagName, ?row, ...?*)
          With no arguments, prints out the list of rows that use the *tag
          *. Otherwise it sets the specified rows to use the *tag *.  If
          *tag * is ", the rows are reset to use the default tag.  Tags
          added during -rowtagcommand evaluation do not register here.  If
          *tagName * does not exist, it is not created, but nor is an
          error generated.

    *$table*->validate(index)
          Explicitly validates the specified index based on the current
          *-validatecommand * and returns 0 or 1 based on whether the cell
          was validated.

    *$table*->window(option, ?*arg, arg, ...*?)
          This command is used to manipulate embedded windows.  The exact
          behavior of the command depends on the *option * argument that
          follows the *window * argument.  The following forms of the
          command are currently supported:

    *$table*->*windowCget*(*index, option*)
          This command returns the current value of the option named
          *option * associated with the window given by *index *.  *Option
          * may have any of the values accepted by the *window configure *
          widget command.

    *$table*->*windowConfigure*(index, ?option?, ?value?, ?*option, value, ...*?)
          This command is similar to the *configure * widget command
          except that it modifies options associated with the embedded
          window given by *index * instead of modifying options for the
          overall table widget.  If no *option * is specified, the command
          returns a list describing all of the available options for *index
          * (see *Tk_ConfigureInfo * for information on the format of this
          list).  If *option * is specified with no *value *, then the
          command returns a list describing the one named option (this
          list will be identical to the corresponding sublist of the value
          returned if no *option * is specified).  If one or more
          *option-value * pairs are specified, then the command modifies
          the given option(s) to have the given value(s) in *index *; in
          this case the command returns an empty string. See EMBEDDED
          WINDOWS above for details on the options available for windows.

    *$table*->*windowDelete*(index, ?*index, ...*?)
          Deletes an embedded window from the table.  The associated
          window will also be deleted.

    *$table*->*windowMove*(*indexFrom, indexTo*)
          Moves an embedded window from one cell to another.  If a window
          already exists in the target cell, it will be deleted.

    *$table*->*windowNames*(?pattern?)
          If no pattern is specified, shows the cells of all embedded
          windows. Otherwise the pattern is used as a glob pattern to show
          only cells matching that pattern.

    *$table*->*xview*(args)
          This command is used to query and change the horizontal position
          of the information in the widget's window.  It can take any of
          the following forms:

    *$table*->*xview*()
          Returns a list containing two elements. Each element is a real
          fraction between 0 and 1;  together they describe the horizontal
          span that is visible in the window. For example, if the first
          element is .2 and the second element is .6, 20% of the table's
          text is off-screen to the left, the middle 40% is visible in the
          window, and 40% of the text is off-screen to the right. These
          are the same values passed to scrollbars via the
          *-xscrollcommand * option.

    *$table*->*xview*(index)
          Adjusts the view in the window so that the column given by
          *index * is displayed at the left edge of the window.

    *$table*->*xviewMoveto*(*fraction*)
          Adjusts the view in the window so that *fraction * of the total
          width of the table text is off-screen to the left. *fraction *
          must be a fraction between 0 and 1.

    *$table*->*xviewScroll*(*number, what*)
          This command shifts the view in the window left or right
          according to *number * and *what *. *Number * must be an
          integer. *What * must be either *units * or *pages * or an
          abbreviation of one of these. If *what * is *units *, the view
          adjusts left or right by *number * character units (the width of
          the *0 * character) on the display;  if it is *pages * then the
          view adjusts by *number * screenfuls. If *number * is negative
          then characters farther to the left become visible;  if it is
          positive then characters farther to the right become visible.

    *$table*->*yview*(*?args*?)
          This command is used to query and change the vertical position
          of the text in the widget's window.  It can take any of the
          following forms:

    *$table*->*yview*()
          Returns a list containing two elements, both of which are real
          fractions between 0 and 1.  The first element gives the position
          of the table element at the top of the window, relative to the
          table as a whole (0.5 means it is halfway through the table, for
          example).  The second element gives the position of the table
          element just after the last one in the window, relative to the
          table as a whole.  These are the same values passed to scrollbars
          via the *-yscrollcommand * option.

    *$table*->*yview*(index)
          Adjusts the view in the window so that the row given by *index *
          is displayed at the top of the window.

    *$table*->*yviewMoveto*(*fraction*)
          Adjusts the view in the window so that the element given by
          *fraction * appears at the top of the window. *Fraction * is a
          fraction between 0 and 1;  0 indicates the first element in the
          table, 0.33 indicates the element one-third the way through the
          table, and so on.

    *$table*->*yviewscroll*(*number, what*)
          This command adjusts the view in the window up or down according
          to *number * and *what *.  *Number * must be an integer.  *What
          * must be either *units * or *pages *.  If *what * is *units *,
          the view adjusts up or down by *number * lines; if it is *pages
          * then the view adjusts by *number * screenfuls.  If *number *
          is negative then earlier elements become visible; if it is
          positive then later elements become visible.

Default Bindings
================

   The initialization creates class bindings that give the following
default behaviour:

[1]
     Clicking Button-1 in a cell activates that cell.  Clicking into an
     already active cell moves the insertion cursor to the character
     nearest the mouse.

[2]
     Moving the mouse while Button-1 is pressed will stroke out a
     selection area. Exiting while Button-1 is pressed causing scanning to
     occur on the table along with selection.

[3]
     Moving the mouse while Button-2 is pressed causes scanning to occur
     without any selection.

[4]
     Home moves the table to have the origin in view.

[5]
     End moves the table to have the *end * cell in view.

[6]
     Control-Home moves the table to the origin and activates that cell.

[7]
     Control-End moves the table to the end and activates that cell.

[8]
     Shift-Control-Home extends the selection to the origin.

[9]
     Shift-Control-End extends the selection to the end.

[10]
     The left, right, up and down arrows move the active cell.

[11]
     Shift-<arrow> extends the selection in that direction.

[12]
     Control-leftarrow and Control-rightarrow move the insertion cursor
     within the cell.

[13]
     Control-slash selects all the cells.

[14]
     Control-backslash clears selection from all the cells.

[15]
     Backspace deletes the character before the insertion cursor in the
     active cell.

[16]
     Delete deletes the character after the insertion cursor in the active
     cell.

[17]
     Escape rereads the value of the active cell from the specified data
     source, discarding any edits that have may been performed on the cell.

[18]
     Control-a moves the insertion cursor to the beginning of the active
     cell.

[19]
     Control-e moves the insertion cursor to the end of the active cell.

[20]
     Control-minus and Control-equals decrease and increase the width of
     the column with the active cell in it.

[21]
     Moving the mouse while Button-3 (the right button on Windows) is
     pressed while you are over a border will cause interactive resizing
     of that row and/or column to occur, based on the value of
     *-resizeborders *. Some bindings may have slightly different behavior
     dependent on the *-selectionmode * of the widget. If the widget is
     disabled using the *-state * option, then its view can still be
     adjusted and cells can still be selected, but no insertion cursor will
     be displayed and no cell modifications will take place. The behavior
     of tables can be changed by defining new bindings for individual
     widgets or by redefining the class bindings.  The default bindings
     are either compiled in the TableMatrix.pm file

Performance Issues
==================

   The number of rows and columns or a table widget should not
significantly affect the speed of redraw.  Recalculation and redraw of
table parameters and cells is restricted as much as possible. The display
cell with the insert cursor is redrawn each time the cursor blinks, which
causes a steady stream of graphics traffic.  Set the *-insertofftime *
option to 0 avoid this.  The use of a *-command* with the table without a
cache can cause significant slow-down, as the command is called once for
each request of a cell value.

Examples
========

   Set the topleft title area to be one spanning cell.  This overestimates
both row and column span by one, but the command does all the constraining
for us.  *$table span [$table cget -roworigin],[$table cget -colorigin]
[$table cget -titlerows],[$table cget -titlecols]  *Force a table window
refresh (useful for the slight chance that a bug in the table is not
causing proper refresh):  *$table configure -padx [$table cget -padx]  *

Keywords
========

   table, widget, extension

Create and manipulate Text widgets
**********************************

NAME
====

   Tk::Text - Create and manipulate Text widgets

   text $text ?options?

   *-background*	*-highlightbackground*	*-insertontime*	*-selectborderwidth*
*-borderwidth*	*-highlightcolor*	*-insertwidth*	*-selectforeground*
*-cursor*	*-highlightthickness*	*-padx*	*-setgrid*
*-exportselection*	*-insertbackground*	*-pady*	*-takefocus*
*-font*	*-insertborderwidth*	*-relief*	*-xscrollcommand*
*-foreground*	*-insertofftime*	*-selectbackground*	*-yscrollcommand*

WIDGET-SPECIFIC OPTIONS
=======================

Name:	height
Class:	*Height*
Switch:	*-height*
     Specifies the desired height for the window, in units of characters
     in the font given by the *-font* option.  Must be at least one.

Name:	*spacing1*
Class:	*Spacing1*
Switch:	*-spacing1*
     Requests additional space above each text line in the widget, using
     any of the standard forms for screen distances.  If a line wraps,
     this option only applies to the first line on the display.  This
     option may be overriden with *-spacing1* options in tags.

Name:	*spacing2*
Class:	*Spacing2*
Switch:	*-spacing2*
     For lines that wrap (so that they cover more than one line on the
     display) this option specifies additional space to provide between
     the display lines that represent a single line of text.  The value
     may have any of the standard forms for screen distances.  This option
     may be overriden with *-spacing2* options in tags.

Name:	*spacing3*
Class:	*Spacing3*
Switch:	*-spacing3*
     Requests additional space below each text line in the widget, using
     any of the standard forms for screen distances.  If a line wraps,
     this option only applies to the last line on the display.  This
     option may be overriden with *-spacing3* options in tags.

Name:	state
Class:	State
Switch:	*-state*
     Specifies one of two states for the text:  normal or disabled.  If
     the text is disabled then characters may not be inserted or deleted
     and no insertion cursor will be displayed, even if the input focus is
     in the widget.

Name:	*tabs*
Class:	Tabs
Switch:	*-tabs*
     Specifies a set of tab stops for the window.  The option's value
     consists of a list of screen distances giving the positions of the
     tab stops.  Each position may optionally be followed in the next list
     element by one of the keywords left, right, center, or numeric, which
     specifies how to justify text relative to the tab stop.  *Left* is
     the default; it causes the text following the tab character to be
     positioned with its left edge at the tab position.  *Right* means
     that the right edge of the text following the tab character is
     positioned at the tab position, and center means that the text is
     centered at the tab position.  Numeric means that the decimal point
     in the text is positioned at the tab position;  if there is no
     decimal point then the least significant digit of the number is
     positioned just to the left of the tab position;  if there is no
     number in the text then the text is right-justified at the tab
     position.  For example, *-tabs => [qw/2c left 4c 6c center/]* creates
     three tab stops at two-centimeter intervals;  the first two use left
     justification and the third uses center justification.  If the list
     of tab stops does not have enough elements to cover all of the tabs
     in a text line, then Tk extrapolates new tab stops using the spacing
     and alignment from the last tab stop in the list.  The value of the
     *tabs* option may be overridden by *-tabs* options in tags.  If no
     *-tabs* option is specified, or if it is specified as an empty list,
     then Tk uses default tabs spaced every eight (average size)
     characters.

Name:	width
Class:	Width
Switch:	*-width*
     Specifies the desired width for the window in units of characters in
     the font given by the *-font* option.  If the font doesn't have a
     uniform width then the width of the character "0" is used in
     translating from character units to screen units.

Name:	wrap
Class:	*Wrap*
Switch:	*-wrap*
     Specifies how to handle lines in the text that are too long to be
     displayed in a single line of the text's window.  The value must be
     none or *char* or word.  A wrap mode of none means that each line of
     text appears as exactly one line on the screen;  extra characters
     that don't fit on the screen are not displayed.  In the other modes
     each line of text will be broken up into several screen lines if
     necessary to keep all the characters visible.  In *char* mode a
     screen line break may occur after any character; in word mode a line
     break will only be made at word boundaries.

DESCRIPTION
===========

   The Text method creates a new window (given by the $text argument) and
makes it into a text widget.  Additional options, described above, may be
specified on the command line or in the option database to configure
aspects of the text such as its default background color and relief.  The
text command returns the path name of the new window.

   A text widget displays one or more lines of text and allows that text
to be edited.  Text widgets support four different kinds of annotations on
the text, called tags, marks, embedded windows or embedded images.  Tags
allow different portions of the text to be displayed with different fonts
and colors.  In addition, `Tk callbacks|Tk::callbacks', see Perl (perl.info),
can be associated with tags so that scripts are invoked
when particular actions such as keystrokes and mouse button presses occur
in particular ranges of the text.  See `"TAGS"' in this node below for
more details.

   The second form of annotation consists of marks, which are floating
markers in the text.  Marks are used to keep track of various interesting
positions in the text as it is edited.  See `"MARKS"' in this node below
for more details.

   The third form of annotation allows arbitrary windows to be embedded in
a text widget.  See `"EMBEDDED WINDOWS"' in this node below for more
details.

   The fourth form of annotation allows Tk images to be embedded in a text
widget.  See `"EMBEDDED IMAGES"' in this node below for more details.

INDICES
=======

   Many of the methods for texts take one or more indices as arguments.
An index is a string used to indicate a particular place within a text,
such as a place to insert characters or one endpoint of a range of
characters to delete.  Indices have the syntax

     base modifier modifier modifier ...

   Where base gives a starting point and the *modifier*s adjust the index
from the starting point (e.g. move forward or backward one character).
Every index must contain a base, but the *modifier*s are optional.

   The base for an index must have one of the following forms:

line.*char*
     Indicates *char*'th character on line line.  Lines are numbered from
     1 for consistency with other UNIX programs that use this numbering
     scheme.  Within a line, characters are numbered from 0.  If *char* is
     end then it refers to the newline character that ends the line.

*@*x*,*y
     Indicates the character that covers the pixel whose x and y
     coordinates within the text's window are x and y.

end
     Indicates the end of the text (the character just after the last
     newline).

mark
     Indicates the character just after the mark whose name is mark.

tag*.first*
     Indicates the first character in the text that has been tagged with
     tag.  This form generates an error if no characters are currently
     tagged with tag.

tag*.last*
     Indicates the character just after the last one in the text that has
     been tagged with tag.  This form generates an error if no characters
     are currently tagged with tag.

$widget
     Indicates the position of the embedded window referenced by $widget.
     This form generates an error if $widget does not reference to an
     embedded window.

imageName
     Indicates the position of the embedded image whose name is imageName.
     This form generates an error if there is no embedded image by the
     given name.

     If the base could match more than one of the above forms, such as a
     mark and imageName both having the same value, then the form earlier
     in the above list takes precedence.  If modifiers follow the base
     index, each one of them must have one of the forms listed below.
     Keywords such as chars and wordend may be abbreviated as long as the
     abbreviation is unambiguous.

*+ *count* chars*
     Adjust the index forward by count characters, moving to later lines
     in the text if necessary.  If there are fewer than count characters
     in the text after the current index, then set the index to the last
     character in the text.  Spaces on either side of count are optional.

*- *count* chars*
     Adjust the index backward by count characters, moving to earlier
     lines in the text if necessary.  If there are fewer than count
     characters in the text before the current index, then set the index
     to the first character in the text.  Spaces on either side of count
     are optional.

*+ *count* lines*
     Adjust the index forward by count lines, retaining the same character
     position within the line.  If there are fewer than count lines after
     the line containing the current index, then set the index to refer to
     the same character position on the last line of the text.  Then, if
     the line is not long enough to contain a character at the indicated
     character position, adjust the character position to refer to the last
     character of the line (the newline).  Spaces on either side of count
     are optional.

*- *count* lines*
     Adjust the index backward by count lines, retaining the same
     character position within the line.  If there are fewer than count
     lines before the line containing the current index, then set the index
     to refer to the same character position on the first line of the text.
     Then, if the line is not long enough to contain a character at the
     indicated character position, adjust the character position to refer
     to the last character of the line (the newline).  Spaces on either
     side of count are optional.

linestart
     Adjust the index to refer to the first character on the line.

lineend
     Adjust the index to refer to the last character on the line (the
     newline).

wordstart
     Adjust the index to refer to the first character of the word
     containing the current index.  A word consists of any number of
     adjacent characters that are letters, digits, or underscores, or a
     single character that is not one of these.

wordend
     Adjust the index to refer to the character just after the last one of
     the word containing the current index.  If the current index refers
     to the last character of the text then it is not modified.

     If more than one modifier is present then they are applied in
     left-to-right order.  For example, the index "*end - 1 chars*" refers
     to the next-to-last character in the text and "*insert wordstart - 1
     c*" refers to the character just before the first one in the word
     containing the insertion cursor.

TAGS
====

   The first form of annotation in text widgets is a tag.  A tag is a
textual string that is associated with some of the characters in a text.
Tags may contain arbitrary characters, but it is probably best to avoid
using the the characters " " (space), +, or -: these characters have
special meaning in indices, so tags containing them can't be used as
indices.  There may be any number of tags associated with characters in a
text.  Each tag may refer to a single character, a range of characters, or
several ranges of characters.  An individual character may have any number
of tags associated with it.

   A priority order is defined among tags, and this order is used in
implementing some of the tag-related functions described below.  When a
tag is defined (by associating it with characters or setting its display
options or binding callbacks to it), it is given a priority higher than
any existing tag.  The priority order of tags may be redefined using the
"$text->*tagRaise*" and "$text->*tagLower*" methods.

   Tags serve three purposes in text widgets.  First, they control the way
information is displayed on the screen.  By default, characters are
displayed as determined by the background, font, and *foreground* options
for the text widget.  However, display options may be associated with
individual tags using the "$text->*tagConfigure*" method.  If a character
has been tagged, then the display options associated with the tag override
the default display style.  The following options are currently supported
for tags:

*-background* => color
     Color specifies the background color to use for characters associated
     with the tag.  It may have any of the forms accepted by *Tk_GetColor*.

*-bgstipple* => bitmap
     Bitmap specifies a bitmap that is used as a stipple pattern for the
     background.  It may have any of the forms accepted by *Tk_GetBitmap*.
     If bitmap hasn't been specified, or if it is specified as an empty
     string, then a solid fill will be used for the background.

*-borderwidth* => *pixels*
     *Pixels* specifies the width of a 3-D border to draw around the
     background.  It may have any of the forms accepted by *Tk_GetPixels*.
     This option is used in conjunction with the *-relief* option to give
     a 3-D appearance to the background for characters; it is ignored
     unless the *-background* option has been set for the tag.

*-fgstipple* => bitmap
     Bitmap specifies a bitmap that is used as a stipple pattern when
     drawing text and other foreground information such as underlines.  It
     may have any of the forms accepted by *Tk_GetBitmap*.  If bitmap
     hasn't been specified, or if it is specified as an empty string, then
     a solid fill will be used.

*-font* => *fontName*
     FontName is the name of a font to use for drawing characters.  It may
     have any of the forms accepted by *Tk_GetFontStruct*.

*-foreground* => color
     Color specifies the color to use when drawing text and other
     foreground information such as underlines.  It may have any of the
     forms accepted by *Tk_GetColor*.

-justify => justify
     If the first character of a display line has a tag for which this
     option has been specified, then justify determines how to justify the
     line.  It must be one of left, right, or center.  If a line wraps,
     then the justification for each line on the display is determined by
     the first character of that display line.

*-lmargin1* => *pixels*
     If the first character of a text line has a tag for which this option
     has been specified, then *pixels* specifies how much the line should
     be indented from the left edge of the window.  *Pixels* may have any
     of the standard forms for screen distances.  If a line of text wraps,
     this option only applies to the first line on the display;  the
     *-lmargin2* option controls the indentation for subsequent lines.

*-lmargin2* => *pixels*
     If the first character of a display line has a tag for which this
     option has been specified, and if the display line is not the first
     for its text line (i.e., the text line has wrapped), then *pixels*
     specifies how much the line should be indented from the left edge of
     the window.  *Pixels* may have any of the standard forms for screen
     distances.  This option is only used when wrapping is enabled, and it
     only applies to the second and later display lines for a text line.

*-offset* => *pixels*
     *Pixels* specifies an amount by which the text's baseline should be
     offset vertically from the baseline of the overall line, in pixels.
     For example, a positive offset can be used for superscripts and a
     negative offset can be used for subscripts.  *Pixels* may have any of
     the standard forms for screen distances.

*-overstrike* => boolean
     Specifies whether or not to draw a horizontal rule through the middle
     of characters.  Boolean may have any of the forms accepted by
     *Tk_GetBoolean*.

*-relief* => *relief*
     *Relief* specifies the 3-D relief to use for drawing backgrounds, in
     any of the forms accepted by *Tk_GetRelief*.  This option is used in
     conjunction with the *-borderwidth* option to give a 3-D appearance
     to the background for characters; it is ignored unless the
     *-background* option has been set for the tag.

*-rmargin* => *pixels*
     If the first character of a display line has a tag for which this
     option has been specified, then *pixels* specifies how wide a margin
     to leave between the end of the line and the right edge of the window.
     *Pixels* may have any of the standard forms for screen distances.
     This option is only used when wrapping is enabled.  If a text line
     wraps, the right margin for each line on the display is determined by
     the first character of that display line.

*-spacing1* => *pixels*
     *Pixels* specifies how much additional space should be left above
     each text line, using any of the standard forms for screen distances.
     If a line wraps, this option only applies to the first line on the
     display.

*-spacing2* => *pixels*
     For lines that wrap, this option specifies how much additional space
     to leave between the display lines for a single text line.  *Pixels*
     may have any of the standard forms for screen distances.

*-spacing3* => *pixels*
     *Pixels* specifies how much additional space should be left below
     each text line, using any of the standard forms for screen distances.
     If a line wraps, this option only applies to the last line on the
     display.

*-state* => state
     State specifies if the text is hidden or normal.  Hidden text is not
     displayed and takes no space on screen, but further on behaves just
     as normal text.

*-tabs* => *tabList*
     *TabList* specifies a set of tab stops in the same form as for the
     *-tabs* option for the text widget.  This option only applies to a
     display line if it applies to the first character on that display
     line.  If this option is specified as an empty string, it cancels the
     option, leaving it unspecified for the tag (the default).  If the
     option is specified as a non-empty string that is an empty list, such
     as *-tabs =* " ">, then it requests default 8-character tabs as
     described for the *tabs* widget option.

*-underline* => boolean
     Boolean specifies whether or not to draw an underline underneath
     characters.  It may have any of the forms accepted by *Tk_GetBoolean*.

*-wrap* => mode
     Mode specifies how to handle lines that are wider than the text's
     window.  It has the same legal values as the *-wrap* option for the
     text widget:  none, *char*, or word.  If this tag option is
     specified, it overrides the *-wrap* option for the text widget.

*-elide* => value
     If value is true then text covered by the tag is not displayed.

*-data* => value
     Allows an arbitrary perl scalar value to be associated with the tag.

   If a character has several tags associated with it, and if their
display options conflict, then the options of the highest priority tag are
used.  If a particular display option hasn't been specified for a
particular tag, or if it is specified as an empty string, then that option
will never be used;  the next-highest-priority tag's option will used
instead.  If no tag specifies a particular display option, then the default
style for the widget will be used.

   The second purpose for tags is event bindings.  You can associate
bindings with a tag in much the same way you can associate bindings with a
widget class:  whenever particular X events occur on characters with the
given tag, a given <perl/Tk callback|Tk::callbacks> will be executed.  Tag
bindings can be used to give behaviors to ranges of characters; among
other things, this allows hypertext-like features to be implemented.  For
details, see the description of the *tagBind* widget method below.

   The third use for tags is in managing the selection.  See `"THE
SELECTION"' in this node below.

MARKS
=====

   The second form of annotation in text widgets is a mark.  Marks are
used for remembering particular places in a text.  They are something like
tags, in that they have names and they refer to places in the file, but a
mark isn't associated with particular characters.  Instead, a mark is
associated with the gap between two characters.  Only a single position
may be associated with a mark at any given time.  If the characters around
a mark are deleted the mark will still remain;  it will just have new
neighbor characters.  In contrast, if the characters containing a tag are
deleted then the tag will no longer have an association with characters in
the file.  Marks may be manipulated with the "$text->mark" text widget
method, and their current locations may be determined by using the mark
name as an index in methods.

   Each mark also has a *gravity*, which is either left or right.  The
gravity for a mark specifies what happens to the mark when text is
inserted at the point of the mark.  If a mark has left gravity, then the
mark is treated as if it were attached to the character on its left, so
the mark will remain to the left of any text inserted at the mark position.
If the mark has right gravity, new text inserted at the mark position will
appear to the right of the mark.  The gravity for a mark defaults to right.

   The name space for marks is different from that for tags:  the same
name may be used for both a mark and a tag, but they will refer to
different things.

   Two marks have special significance.  First, the mark insert is
associated with the insertion cursor, as described under `"THE INSERTION
CURSOR"' in this node below.  Second, the mark current is associated with
the character closest to the mouse and is adjusted automatically to track
the mouse position and any changes to the text in the widget (one
exception:  current is not updated in response to mouse motions if a mouse
button is down;  the update will be deferred until all mouse buttons have
been released).  Neither of these special marks may be deleted.

EMBEDDED WINDOWS
================

   The third form of annotation in text widgets is an embedded window.
Each embedded window annotation causes a window to be displayed at a
particular point in  the text.  There may be any number of embedded
windows in a text widget, and any widget may be used as an embedded window
(subject to the usual rules for geometry management, which require the
text window to be the parent of the embedded window or a descendant of its
parent).  The embedded window's position on the screen will be updated as
the text is modified or scrolled, and it will be mapped and unmapped as it
moves into and out of the visible area of the text widget.  Each embedded
window occupies one character's worth of index space in the text widget,
and it may be referred to either by the name of its embedded window or by
its position in the widget's index space.  If the range of text containing
the embedded window is deleted then the window is destroyed.

   When an embedded window is added to a text widget with the
*widgetCreate* method, several configuration options may be associated
with it.  These options may be  modified later with the *widgetConfigure*
method.  The following options are currently supported:

*-align* => where
     If the window is not as tall as the line in which it is displayed,
     this option determines where the window is displayed in the line.
     Where must have one of the values top (align the top of the window
     with the top of the line), center (center the window within the range
     of the line), *bottom* (align the bottom of the window with the
     bottom of the line's area), or *baseline* (align the bottom of the
     window with the baseline of the line).

*-create* => callback
     Specifies a `callback|Tk::callbacks' in this node that may be
     evaluated to create the window for the annotation.  If no *-window*
     option has been specified for the annotation this callback will be
     evaluated when the annotation is about to be displayed on the screen.
     Callback must create a window for the annotation and return the name
     of that window as its result.  If the annotation's window should ever
     be deleted, callback will be evaluated again the next time the
     annotation is displayed.

*-padx* => *pixels*
     *Pixels* specifies the amount of extra space to leave on each side of
     the embedded window.  It may have any of the usual forms defined for
     a screen distance (see *Tk_GetPixels*).

*-pady* => *pixels*
     *Pixels* specifies the amount of extra space to leave on the top and
     on the bottom of the embedded window.  It may have any of the usual
     forms defined for a screen distance (see *Tk_GetPixels*).

*-stretch* => boolean
     If the requested height of the embedded window is less than the
     height of the line in which it is displayed, this option can be used
     to specify whether the window should be stretched vertically to fill
     its line.  If the *-pady* option has been specified as well, then the
     requested padding will be retained even if the window is stretched.

*-window* => $widget
     Specifies the name of a window to display in the annotation.

EMBEDDED IMAGES
===============

   The final form of annotation in text widgets is an embedded image.
Each embedded image annotation causes an image to be displayed at a
particular point in  the text.  There may be any number of embedded images
in a text widget, and a particular image may be embedded in multiple
places in the same text widget.  The embedded image's position on the
screen will be updated as the text is modified or scrolled.  Each embedded
image occupies one character's worth of index space in the text widget,
and it may be referred to either by its position in the widget's index
space, or the name it is assigned when the image is inserted into the text
widget with *imageCreate*.  If the range of text containing the embedded
image is deleted then that copy of the image is removed from the screen.

   When an embedded image is added to a text widget with the image create
method, a name unique to this instance of the image is returned.  This
name may then be used to refer to this image instance.  The name is taken
to be the value of the *-name* option (described below).  If the *-name*
option is not provided, the *-image* name is used instead.  If the
imageName is already in use in the text widget, then *#**nn* is added to
the end of the imageName, where *nn* is an arbitrary integer.  This insures
the imageName is unique.  Once this name is assigned to this instance of
the image, it does not change, even though the *-image* or *-name* values
can be changed with *image configure*.

   When an embedded image is added to a text widget with the *imageCreate*
method, several configuration options may be associated with it.  These
options may be modified later with the *image configure* method.  The
following options are currently supported:

*-align* => where
     If the image is not as tall as the line in which it is displayed,
     this option determines where the image is displayed in the line.
     Where must have one of the values top (align the top of the image
     with the top of the line), center (center the image within the range
     of the line), *bottom* (align the bottom of the image with the bottom
     of the line's area), or *baseline* (align the bottom of the image
     with the baseline of the line).

*-image* => image
     Specifies the name of the Tk image to display in the annotation.  If
     image is not a valid Tk image, then an error is returned.

*-name* => *ImageName*
     Specifies the name by which this image instance may be referenced in
     the text widget. If *ImageName* is not supplied, then the name of the
     Tk image is used instead.  If the imageName is already in use, *#nn*
     is appended to the end of the name as described above.

*-padx* => *pixels*
     *Pixels* specifies the amount of extra space to leave on each side of
     the embedded image.  It may have any of the usual forms defined for a
     screen distance.

*-pady* => *pixels*
     *Pixels* specifies the amount of extra space to leave on the top and
     on the bottom of the embedded image.  It may have any of the usual
     forms defined for a screen distance.

THE SELECTION
=============

   Selection support is implemented via tags.  If the *exportSelection*
option for the text widget is true then the sel tag will be associated
with the selection:

[1]
     Whenever characters are tagged with sel the text widget will claim
     ownership of the selection.

[2]
     Attempts to retrieve the selection will be serviced by the text
     widget, returning all the characters with the sel tag.

[3]
     If the selection is claimed away by another application or by another
     window within this application, then the sel tag will be removed from
     all characters in the text.

     The sel tag is automatically defined when a text widget is created,
     and it may not be deleted with the "$text->*tagDelete*" method.
     Furthermore, the *selectBackground*, *selectBorderWidth*, and
     *selectForeground* options for the text widget are tied to the
     *-background*, *-borderwidth*, and *-foreground* options for the sel
     tag:  changes in either will automatically be reflected in the other.

THE INSERTION CURSOR
====================

   The mark named insert has special significance in text widgets.  It is
defined automatically when a text widget is created and it may not be
unset with the "$text->*markUnset*" widget command.  The insert mark
represents the position of the insertion cursor, and the insertion cursor
will automatically be drawn at this point whenever the text widget has the
input focus.

WIDGET METHODS
==============

   The Text method creates a widget object.  This object supports the
configure and cget methods described in Tk/options,
which can be used to enquire and modify the options described above.  The
widget also inherits all the methods provided by the generic
`Tk::Widget|Tk::Widget' in this node class.

   The following additional methods are available for text widgets:

$text->*bbox*(index)
     Returns a list of four elements describing the screen area of the
     character given by index.  The first two elements of the list give
     the x and y coordinates of the upper-left corner of the area occupied
     by the character, and the last two elements give the width and height
     of the area.  If the character is only partially visible on the
     screen, then the return value reflects just the visible part.  If the
     character is not visible on the screen then the return value is an
     empty list.

$text->compare(*index1, op, index2*)
     Compares the indices given by *index1* and *index2* according to the
     relational operator given by op, and returns 1 if the relationship is
     satisfied and 0 if it isn't.  *Op* must be one of the operators <,
     <=, ==, >=, >, or !=.  If op is == then 1 is returned if the two
     indices refer to the same character, if op is < then 1 is returned if
     *index1* refers to an earlier character in the text than *index2*, and
     so on.

$text->debug(?boolean?)
     If boolean is specified, then it must have one of the true or false
     values accepted by Tcl_GetBoolean.  If the value is a true one then
     internal consistency checks will be turned on in the B-tree code
     associated with text widgets.  If boolean has a false value then the
     debugging checks will be turned off.  In either case the command
     returns an empty string.  If boolean is not specified then the
     command returns *on* or *off* to indicate whether or not debugging is
     turned on.  There is a single debugging switch shared by all text
     widgets:  turning debugging on or off in any widget turns it on or
     off for all widgets.  For widgets with large amounts of text, the
     consistency checks may cause a noticeable slow-down.

$text->delete(*index1, *?*index2*?)
     Delete a range of characters from the text.  If both *index1* and
     *index2* are specified, then delete all the characters starting with
     the one given by *index1* and stopping just before *index2* (i.e. the
     character at *index2* is not deleted).  If *index2* doesn't specify a
     position later in the text than *index1* then no characters are
     deleted.  If *index2* isn't specified then the single character at
     *index1* is deleted.  It is not allowable to delete characters in a
     way that would leave the text without a newline as the last character.
     The command returns an empty string.

$text->*dlineinfo*(index)
     Returns a list with five elements describing the area occupied by the
     display line containing index.  The first two elements of the list
     give the x and y coordinates of the upper-left corner of the area
     occupied by the line, the third and fourth elements give the width
     and height of the area, and the fifth element gives the position of
     the baseline for the line, measured down from the top of the area.
     All of this information is measured in pixels.  If the current wrap
     mode is none and the line extends beyond the boundaries of the window,
     the area returned reflects the entire area of the line, including the
     portions that are out of the window.  If the line is shorter than the
     full width of the window then the area returned reflects just the
     portion of the line that is occupied by characters and embedded
     windows.  If the display line containing index is not visible on the
     screen then the return value is an empty list.

$text->dump(?switches?, *index1, *?*index2*?)
     Return the contents of the text widget from *index1* up to, but not
     including *index2*, including the text and information about marks,
     tags, and embedded windows.  If *index2* is not specified, then it
     defaults to one character past *index1*.  The information is returned
     in the following format:

     *key1 value1 index1 key2 value2 index2* ...

   The possible key values are text, mark, *tagon*, *tagoff*, and $text.
The corresponding value is the text, mark name, tag name, or window name.
The index information is the index of the start of the text, the mark, the
tag transition, or the window.  One or more of the following switches (or
abbreviations thereof) may be specified to control the dump:

*-all*
     Return information about all elements: text, marks, tags, and windows.
     This is the default.

*-command* => callback
     Instead of returning the information as the result of the dump
     operation, invoke the callback on each element of the text widget
     within the range.  The callback has three arguments appended to it
     before it is evaluated: the key, value, and index.

*-mark*
     Include information about marks in the dump results.

*-tag*
     Include information about tag transitions in the dump results. Tag
     information is returned as *tagon* and *tagoff* elements that
     indicate the begin and end of each range of each tag, respectively.

*-text*
     Include information about text in the dump results.  The value is the
     text up to the next element or the end of range indicated by *index2*.
     A text element does not span newlines.  A multi-line block of text
     that contains no marks or tag transitions will still be dumped as a
     set of text seqments that each end with a newline.  The newline is
     part of the value.

*-window*
     Include information about embedded windows in the dump results.  The
     value of a window is its Tk pathname, unless the window has not been
     created yet.  (It must have a create script.)  In this case an empty
     string is returned, and you must query the window by its index
     position to get more information.

$text->get(*index1, *?*index2*?)
     Return a range of characters from the text.  The return value will be
     all the characters in the text starting with the one whose index is
     *index1* and ending just before the one whose index is *index2* (the
     character at *index2* will not be returned).  If *index2* is omitted
     then the single character at *index1* is returned.  If there are no
     characters in the specified range (e.g. *index1* is past the end of
     the file or *index2* is less than or equal to *index1*) then an empty
     string is returned.  If the specified range contains embedded
     windows, no information about them is included in the returned string.

$text->image(option, ?*arg, arg, ...*?)
$text->imageOption(?*arg, arg, ...*?)
     This method is used to manipulate embedded images.  The behavior of
     the method depends on the option argument that follows the image
     prefix.  The following forms of the methods are currently supported:

    $text->*imageCget*(*index, option*)
          Returns the value of a configuration option for an embedded
          image.  Index identifies the embedded image, and option
          specifies a particular configuration option, which must be one of
          the ones listed in `"EMBEDDED IMAGES"' in this node.

    $text->*imageConfigure*(*index, *?*option, value, ...*?)
          Query or modify the configuration options for an embedded image.
          If no option is specified, returns a list describing all of the
          available options for the embedded image at index (see
          Tk/options, for information on the format of this
          list).  If option is specified with no value, then the command
          returns a list describing the one named option (this list will be
          identical to the corresponding sublist of the value returned if
          no option is specified).  If one or more *option-value* pairs
          are specified, then the command modifies the given option(s) to
          have the given value(s);  in this case the command returns an
          empty string.  See `"EMBEDDED IMAGES"' in this node for
          information on the options that are supported.

    $text->*imageCreate*(*index, *?*option, value, ...*?)
          This command creates a new image annotation, which will appear
          in the text at the position given by index.  Any number of
          *option-value* pairs may be specified to configure the
          annotation.  Returns a unique identifier that may be used as an
          index to refer to this image.  See `"EMBEDDED IMAGES"' in this
          node for information on the options that are supported, and a
          description of the identifier returned.

    $text->*imageNames*
          Returns a list whose elements are the names of all image
          instances currently embedded in $text.

$text->index(index)
     Returns the position corresponding to index in the form line.char
     where line is the line number and *char* is the character number.
     Index may have any of the forms described under `"INDICES"' in this
     node above.

$text->insert(*index, chars, *?*tagList, chars, tagList, ...*?)
     Inserts all of the chars arguments just before the character at index.
     If index refers to the end of the text (the character after the last
     newline) then the new text is inserted just before the last newline
     instead.  If there is a single chars argument and no *tagList*, then
     the new text will receive any tags that are present on both the
     character before and the character after the insertion point; if a tag
     is present on only one of these characters then it will not be
     applied to the new text.  If *tagList* is specified then it consists
     of a list of tag names;  the new characters will receive all of the
     tags in this list and no others, regardless of the tags present around
     the insertion point.  If multiple chars-*tagList* argument pairs are
     present, they produce the same effect as if a separate insert widget
     command had been issued for each pair, in order.  The last *tagList*
     argument may be omitted.

$text->mark(*option, *?*arg, arg, ...*?)
     This command is used to manipulate marks.  The exact behavior of the
     command depends on the option argument that follows the mark
     argument.  The following forms of the command are currently supported:

    $text->*markGravity*(*markName, *?*direction*?)
          If *direction* is not specified, returns left or right to
          indicate which of its adjacent characters *markName* is attached
          to.  If *direction* is specified, it must be left or right; the
          gravity of *markName* is set to the given value.

    $text->*markNames*
          Returns a list whose elements are the names of all the marks that
          are currently set.

    $text->*markNext*(index)
          Returns the name of the next mark at or after index.  If index
          is specified in numerical form, then the search for the next
          mark begins at that index.  If index is the name of a mark, then
          the search for the next mark begins immediately after that mark.
          This can still return a mark at the same position if there are
          multiple marks at the same index.  These semantics mean that the
          *mark next* operation can be used to step through all the marks
          in a text widget in the same order as the mark information
          returned by the dump operation.  If a mark has been set to the
          special end index, then it appears to be after end with respect
          to the *mark next* operation.  An empty string is returned if
          there are no marks after index.

    $text->*markPrevious*(index)
          Returns the name of the mark at or before index.  If index is
          specified in numerical form, then the search for the previous
          mark begins with the character just before that index.  If index
          is the name of a mark, then the search for the next mark begins
          immediately before that mark.  This can still return a mark at
          the same position if there are multiple marks at the same index.
          These semantics mean that the *mark previous* operation can be
          used to step through all the marks in a text widget in the
          reverse order as the mark information returned by the dump
          operation.  An empty string is returned if there are no marks
          before index.

    $text->*markSet*(*markName, index*)
          Sets the mark named *markName* to a position just before the
          character at index.  If *markName* already exists, it is moved
          from its old position; if it doesn't exist, a new mark is
          created.  This command returns an empty string.

    $text->*markUnset*(*markName*?, *markName, markName, ...*?)
          Remove the mark corresponding to each of the *markName*
          arguments.  The removed marks will not be usable in indices and
          will not be returned by future calls to "$text->*markNames*".
          This command returns an empty string.

$text->scan(option, args) or
$text->scanoption(args)
     This method is used to implement scanning on texts.  It has two
     forms, depending on option:

    $text->*scanMark*(*x, y*)
          Records x and y and the current view in the text window, for use
          in conjunction with later *scanDragto* method.  Typically this
          method is associated with a mouse button press in the widget.
          It returns an empty string.

    $text->*scanDragto*(*x, y*)
          This command computes the difference between its x and y
          arguments and the x and y arguments to the last *scanMark*
          method for the widget.  It then adjusts the view by 10 times the
          difference in coordinates.  This command is typically associated
          with mouse motion events in the widget, to produce the effect of
          dragging the text at high speed through the window.  The return
          value is an empty string.

$text->search(?switches,? *pattern, index, *?*stopIndex*?)
     Searches the text in $text starting at index for a range of
     characters that matches pattern.  If a match is found, the index of
     the first character in the match is returned as result;  otherwise an
     empty string is returned.  One or more of the following switches (or
     abbreviations thereof) may be specified to control the search:

    *-forwards*
          The search will proceed forward through the text, finding the
          first matching range starting at or after the position given by
          index.  This is the default.

    *-backwards*
          The search will proceed backward through the text, finding the
          matching range closest to index whose first character is before
          index.

    *-exact*
          Use exact matching:  the characters in the matching range must be
          identical to those in pattern.  This is the default.

    *-regexp*
          Treat pattern as a regular expression and match it against the
          text using the rules for regular expressions (see the regexp
          command for details).

    *-nocase*
          Ignore case differences between the pattern and the text.

    *-count** varName*
          The argument following *-count* gives the name of a variable; if
          a match is found, the number of characters in the matching range
          will be stored in the variable.

    *-hidden*
          Find hidden text as well. By default only displayed text is
          found.

    -
          This switch has no effect except to terminate the list of
          switches: the next argument will be treated as pattern even if
          it starts with -.

   The matching range must be entirely within a single line of text.  For
regular expression matching the newlines are removed from the ends of the
lines before matching:  use the *$* feature in regular expressions to
match the end of a line.  For exact matching the newlines are retained.
If *stopIndex* is specified, the search stops at that index: for forward
searches, no match at or after *stopIndex* will be considered;  for
backward searches, no match earlier in the text than *stopIndex* will be
considered.  If *stopIndex* is omitted, the entire text will be searched:
when the beginning or end of the text is reached, the search continues at
the other end until the starting location is reached again;  if
*stopIndex* is specified, no wrap-around will occur.

$text->see(index)
     Adjusts the view in the window so that the character given by index
     is completely visible.  If index is already visible then the command
     does nothing.  If index is a short distance out of view, the command
     adjusts the view just enough to make index visible at the edge of the
     window.  If index is far out of view, then the command centers index
     in the window.

$text->tag(*option, *?*arg, arg, ...*?)
     This command is used to manipulate tags.  The exact behavior of the
     command depends on the option argument that follows the tag argument.
     The following forms of the command are currently supported:

    $text->*tagAdd*(*tagName, index1, *?*index2, index1, index2, ...*?)
          Associate the tag *tagName* with all of the characters starting
          with *index1* and ending just before *index2* (the character at
          *index2* isn't tagged).  A single command may contain any number
          of *index1*-*index2* pairs.  If the last *index2* is omitted
          then the single character at *index1* is tagged.  If there are
          no characters in the specified range (e.g. *index1* is past the
          end of the file or *index2* is less than or equal to *index1*)
          then the command has no effect.

    $text->*tagBind*(*tagName, *?sequence?, ?*script*?)
          This command associates *script* with the tag given by *tagName*.
          Whenever the event sequence given by sequence occurs for a
          character that has been tagged with *tagName*, the script will
          be invoked.  This method is similar to the bind command except
          that it operates on characters in a text rather than entire
          widgets.  See the Tk/bind, documentation for
          complete details on the syntax of sequence and the substitutions
          performed on *script* before invoking it.  If all arguments are
          specified then a new binding is created, replacing any existing
          binding for the same sequence and *tagName* (if the first
          character of *script* is "+" then *script* augments an existing
          binding rather than replacing it).  In this case the return
          value is an empty string.  If *script* is omitted then the
          command returns the *script* associated with *tagName* and
          sequence (an error occurs if there is no such binding).  If both
          *script* and sequence are omitted then the command returns a
          list of all the sequences for which bindings have been defined
          for *tagName*.

          The only events for which bindings may be specified are those
          related to the mouse and keyboard (such as Enter, *Leave*,
          *ButtonPress*, *Motion*, and *KeyPress*) or virtual events.
          Event bindings for a text widget use the current mark described
          under `"MARKS"' in this node above.  An Enter event triggers for
          a tag when the tag first becomes present on the current
          character, and a *Leave* event triggers for a tag when it ceases
          to be present on the current character.  Enter and *Leave*
          events can happen either because the current mark moved or
          because the character at that position changed.  Note that these
          events are different than Enter and *Leave* events for windows.
          Mouse and keyboard events are directed to the current character.
          If a virtual event is used in a binding, that binding can
          trigger only if the virtual event is defined by an underlying
          mouse-related or keyboard-related event.

          It is possible for the current character to have multiple tags,
          and for each of them to have a binding for a particular event
          sequence.  When this occurs, one binding is invoked for each
          tag, in order from lowest-priority to highest priority.  If
          there are multiple matching bindings for a single tag, then the
          most specific binding is chosen (see the the documentation for
          the bind command for details).  continue and break commands
          within binding scripts are processed in the same way as for
          bindings created with the bind command.

          If bindings are created for the widget as a whole using the bind
          command, then those bindings will supplement the tag bindings.
          The tag bindings will be invoked first, followed by bindings for
          the window as a whole.

    $text->*tagCget*(*tagName, option*)
          This command returns the current value of the option named option
          associated with the tag given by *tagName*.  Option may have any
          of the values accepted by the *tag configure* method.

    $text->*tagConfigure*(*tagName, *?option?, ?value?, ?*option, value, ...*?)
          This command is similar to the configure method except that it
          modifies options associated with the tag given by *tagName*
          instead of modifying options for the overall text widget.  If no
          option is specified, the command returns a list describing all
          of the available options for *tagName* (see Tk/options,
          for information on the format of this list).  If
          option is specified with no value, then the command returns a
          list describing the one named option (this list will be
          identical to the corresponding sublist of the value returned if
          no option is specified).  If one or more *option-value* pairs
          are specified, then the command modifies the given option(s) to
          have the given value(s) in *tagName*; in this case the command
          returns an empty string.  See `"TAGS"' in this node above for
          details on the options available for tags.

    $text->*tagDelete*(*tagName, *?*tagName, ...*?)
          Deletes all tag information for each of the *tagName* arguments.
          The command removes the tags from all characters in the file and
          also deletes any other information associated with the tags,
          such as bindings and display information.  The command returns
          an empty string.

    $text->*tagLower*(*tagName*?, *belowThis*?)
          Changes the priority of tag *tagName* so that it is just lower
          in priority than the tag whose name is *belowThis*.  If
          *belowThis* is omitted, then *tagName*'s priority is changed to
          make it lowest priority of all tags.

    $text->*tagNames*(?index?)
          Returns a list whose elements are the names of all the tags that
          are active at the character position given by index.  If index
          is omitted, then the return value will describe all of the tags
          that exist for the text (this includes all tags that have been
          named in a "$text->tag" widget command but haven't been deleted
          by a "$text->*tagDelete*" method, even if no characters are
          currently marked with the tag).  The list will be sorted in
          order from lowest priority to highest priority.

    $text->*tagNextrange*(*tagName, index1, *?*index2*?)
          This command searches the text for a range of characters tagged
          with *tagName* where the first character of the range is no
          earlier than the character at *index1* and no later than the
          character just before *index2* (a range starting at *index2*
          will not be considered).  If several matching ranges exist, the
          first one is chosen.  The command's return value is a list
          containing two elements, which are the index of the first
          character of the range and the index of the character just after
          the last one in the range.  If no matching range is found then
          the return value is an empty string.  If *index2* is not given
          then it defaults to the end of the text.

    $text->*tagPrevrange*(*tagName, index1, *?*index2*?)
          This command searches the text for a range of characters tagged
          with *tagName* where the first character of the range is before
          the character at *index1* and no earlier than the character at
          *index2* (a range starting at *index2* will be considered).  If
          several matching ranges exist, the one closest to *index1* is
          chosen.  The command's return value is a list containing two
          elements, which are the index of the first character of the
          range and the index of the character just after the last one in
          the range.  If no matching range is found then the return value
          is an empty string.  If *index2* is not given then it defaults
          to the beginning of the text.

    $text->*tagRaise*(*tagName, *?*aboveThis*?)
          Changes the priority of tag *tagName* so that it is just higher
          in priority than the tag whose name is *aboveThis*.  If
          *aboveThis* is omitted, then *tagName*'s priority is changed to
          make it highest priority of all tags.

    $text->*tagRanges*(*tagName*)
          Returns a list describing all of the ranges of text that have
          been tagged with *tagName*.  The first two elements of the list
          describe the first tagged range in the text, the next two
          elements describe the second range, and so on.  The first
          element of each pair contains the index of the first character
          of the range, and the second element of the pair contains the
          index of the character just after the last one in the range.  If
          there are no characters tagged with tag then an empty string is
          returned.

    $text->*tagRemove*(*tagName, index1, *?*index2, index1, index2, ...*?)
          Remove the tag *tagName* from all of the characters starting at
          *index1* and ending just before *index2* (the character at
          *index2* isn't affected).  A single command may contain any
          number of *index1*-*index2* pairs.  If the last *index2* is
          omitted then the single character at *index1* is tagged.  If
          there are no characters in the specified range (e.g. *index1* is
          past the end of the file or *index2* is less than or equal to
          *index1*) then the command has no effect.  This command returns
          an empty string.

$text->widget(*option?, arg, arg, ...*?)
$text->widgetOption(?*arg, arg, ...*?)
     This method is used to manipulate embedded windows.  The behavior of
     the method depends on the option argument that follows the window
     argument.  The following forms of the method are currently supported:

    $text->*windowCget*(*index, option*)
          Returns the value of a configuration option for an embedded
          window.  Index identifies the embedded window, and option
          specifies a particular configuration option, which must be one of
          the ones listed in `"EMBEDDED WINDOWS"' in this node above.

    $text->*windowConfigure*(index?, *option, value, ...*?)
          Query or modify the configuration options for an embedded window.
          If no option is specified, returns a list describing all of the
          available options for the embedded window at index (see
          Tk/options, for information on the format of this
          list).  If option is specified with no value, then the command
          returns a list describing the one named option (this list will be
          identical to the corresponding sublist of the value returned if
          no option is specified).  If one or more *option-value* pairs
          are specified, then the command modifies the given option(s) to
          have the given value(s);  in this case the command returns an
          empty string.  See `"EMBEDDED WINDOWS"' in this node above for
          information on the options that are supported.

    $text->*windowCreate*(index?, *option, value, ...*?)
          This command creates a new window annotation, which will appear
          in the text at the position given by index.  Any number of
          *option-value* pairs may be specified to configure the
          annotation.  See `"EMBEDDED WINDOWS"' in this node above for
          information on the options that are supported.  Returns an empty
          string.

    $text->*windowNames*
          Returns a list whose elements are the names of all windows
          currently embedded in $text.

$text->*xview*(*option, args*)
     This command is used to query and change the horizontal position of
     the text in the widget's window.  It can take any of the following
     forms:

    $text->*xview*
          Returns a list containing two elements.  Each element is a real
          fraction between 0 and 1;  together they describe the portion of
          the document's horizontal span that is visible in the window.
          For example, if the first element is .2 and the second element
          is .6, 20% of the text is off-screen to the left, the middle 40%
          is visible in the window, and 40% of the text is off-screen to
          the right.  The fractions refer only to the lines that are
          actually visible in the window:  if the lines in the window are
          all very short, so that they are entirely visible, the returned
          fractions will be 0 and 1, even if there are other lines in the
          text that are much wider than the window.  These are the same
          values passed to scrollbars via the *-xscrollcommand* option.

    $text->*xviewMoveto*(*fraction*)
          Adjusts the view in the window so that *fraction* of the
          horizontal span of the text is off-screen to the left.
          *Fraction* is a fraction between 0 and 1.

    $text->*xviewScroll*(*number, what*)
          This command shifts the view in the window left or right
          according to number and *what*.  Number must be an integer.
          What must be either *units* or *pages* or an abbreviation of one
          of these.  If *what* is *units*, the view adjusts left or right
          by number average-width characters on the display;  if it is
          *pages* then the view adjusts by number screenfuls.  If number
          is negative then characters farther to the left become visible;
          if it is positive then characters farther to the right become
          visible.

$text->*yview*(*?args*?)
     This command is used to query and change the vertical position of the
     text in the widget's window.  It can take any of the following forms:

    $text->*yview*
          Returns a list containing two elements, both of which are real
          fractions between 0 and 1.  The first element gives the position
          of the first character in the top line in the window, relative
          to the text as a whole (0.5 means it is halfway through the
          text, for example).  The second element gives the position of
          the character just after the last one in the bottom line of the
          window, relative to the text as a whole.  These are the same
          values passed to scrollbars via the *-yscrollcommand* option.

    $text->*yviewMoveto*(*fraction*)
          Adjusts the view in the window so that the character given by
          *fraction* appears on the top line of the window.  *Fraction* is
          a fraction between 0 and 1;  0 indicates the first character in
          the text, 0.33 indicates the character one-third the way through
          the text, and so on.

    $text->*yviewScroll*(*number, what*)
          This command adjust the view in the window up or down according
          to number and *what*.  Number must be an integer.  What must be
          either *units* or *pages*.  If *what* is *units*, the view
          adjusts up or down by number lines on the display;  if it is
          *pages* then the view adjusts by number screenfuls.  If number
          is negative then earlier positions in the text become visible;
          if it is positive then later positions in the text become
          visible.

    $text->*yview*(?*-pickplace*,? index)
          Changes the view in the $text's window to make index visible.
          If the *-pickplace* option isn't specified then index will
          appear at the top of the window.  If *-pickplace* is specified
          then the widget chooses where index appears in the window:

         [1]
               If index is already visible somewhere in the window then the
               command does nothing.

         [2]
               If index is only a few lines off-screen above the window
               then it will be positioned at the top of the window.

         [3]
               If index is only a few lines off-screen below the window
               then it will be positioned at the bottom of the window.

         [4]
               Otherwise, index will be centered in the window.

   The *-pickplace* option has been obsoleted by the see widget command
(see handles both x- and y-motion to make a location visible, whereas
*-pickplace* only handles motion in y).

$text->*yview*(number)
     This command makes the first character on the line after the one
     given by number visible at the top of the window.  Number must be an
     integer.  This command used to be used for scrolling, but now it is
     obsolete.

BINDINGS
========

   Tk automatically creates class bindings for texts that give them the
following default behavior.  In the descriptions below, "word" refers to a
contiguous group of letters, digits, or "_" characters, or any single
character other than these.

[1]
     Clicking mouse button 1 positions the insertion cursor just before
     the character underneath the mouse cursor, sets the input focus to
     this widget, and clears any selection in the widget.  Dragging with
     mouse button 1 strokes out a selection between the insertion cursor
     and the character under the mouse.

[2]
     Double-clicking with mouse button 1 selects the word under the mouse
     and positions the insertion cursor at the beginning of the word.
     Dragging after a double click will stroke out a selection consisting
     of whole words.

[3]
     Triple-clicking with mouse button 1 selects the line under the mouse
     and positions the insertion cursor at the beginning of the line.
     Dragging after a triple click will stroke out a selection consisting
     of whole lines.

[4]
     The ends of the selection can be adjusted by dragging with mouse
     button 1 while the Shift key is down;  this will adjust the end of
     the selection that was nearest to the mouse cursor when button 1 was
     pressed.  If the button is double-clicked before dragging then the
     selection will be adjusted in units of whole words;  if it is
     triple-clicked then the selection will be adjusted in units of whole
     lines.

[5]
     Clicking mouse button 1 with the Control key down will reposition the
     insertion cursor without affecting the selection.

[6]
     If any normal printing characters are typed, they are inserted at the
     point of the insertion cursor.

[7]
     The view in the widget can be adjusted by dragging with mouse button
     2.  If mouse button 2 is clicked without moving the mouse, the
     selection is copied into the text at the position of the mouse cursor.
     The Insert key also inserts the selection, but at the position of the
     insertion cursor.

[8]
     If the mouse is dragged out of the widget while button 1 is pressed,
     the entry will automatically scroll to make more text visible (if
     there is more text off-screen on the side where the mouse left the
     window).

[9]
     The Left and Right keys move the insertion cursor one character to the
     left or right;  they also clear any selection in the text.  If Left
     or Right is typed with the Shift key down, then the insertion cursor
     moves and the selection is extended to include the new character.
     Control-Left and Control-Right move the insertion cursor by words, and
     Control-Shift-Left and Control-Shift-Right move the insertion cursor
     by words and also extend the selection.  Control-b and Control-f
     behave the same as Left and Right, respectively.  Meta-b and Meta-f
     behave the same as Control-Left and Control-Right, respectively.

[10]
     The Up and Down keys move the insertion cursor one line up or down
     and clear any selection in the text.  If Up or Right is typed with
     the Shift key down, then the insertion cursor moves and the selection
     is extended to include the new character.  Control-Up and
     Control-Down move the insertion cursor by paragraphs (groups of lines
     separated by blank lines), and Control-Shift-Up and
     Control-Shift-Down move the insertion cursor by paragraphs and also
     extend the selection.  Control-p and Control-n behave the same as Up
     and Down, respectively.

[11]
     The Next and Prior keys move the insertion cursor forward or backwards
     by one screenful and clear any selection in the text.  If the Shift
     key is held down while Next or Prior is typed, then the selection is
     extended to include the new character.  Control-v moves the view down
     one screenful without moving the insertion cursor or adjusting the
     selection.

[12]
     Control-Next and Control-Prior scroll the view right or left by one
     page without moving the insertion cursor or affecting the selection.

[13]
     Home and Control-a move the insertion cursor to the beginning of its
     line and clear any selection in the widget.  Shift-Home moves the
     insertion cursor to the beginning of the line and also extends the
     selection to that point.

[14]
     End and Control-e move the insertion cursor to the end of the line
     and clear any selection in the widget.  Shift-End moves the cursor to
     the end of the line and extends the selection to that point.

[15]
     Control-Home and Meta-< move the insertion cursor to the beginning of
     the text and clear any selection in the widget.  Control-Shift-Home
     moves the insertion cursor to the beginning of the text and also
     extends the selection to that point.

[16]
     Control-End and Meta-> move the insertion cursor to the end of the
     text and clear any selection in the widget.  Control-Shift-End moves
     the cursor to the end of the text and extends the selection to that
     point.

[17]
     The Select key and Control-Space set the selection anchor to the
     position of the insertion cursor.  They don't affect the current
     selection.  Shift-Select and Control-Shift-Space adjust the selection
     to the current position of the insertion cursor, selecting from the
     anchor to the insertion cursor if there was not any selection
     previously.

[18]
     Control-/ selects the entire contents of the widget.

[19]
     Control-\ clears any selection in the widget.

[20]
     The F16 key (labelled Copy on many Sun workstations) or Meta-w copies
     the selection in the widget to the clipboard, if there is a selection.

[21]
     The F20 key (labelled Cut on many Sun workstations) or Control-w
     copies the selection in the widget to the clipboard and deletes the
     selection.  If there is no selection in the widget then these keys
     have no effect.

[22]
     The F18 key (labelled Paste on many Sun workstations) or Control-y
     inserts the contents of the clipboard at the position of the
     insertion cursor.

[23]
     The Delete key deletes the selection, if there is one in the widget.
     If there is no selection, it deletes the character to the right of
     the insertion cursor.

[24]
     Backspace and Control-h delete the selection, if there is one in the
     widget.  If there is no selection, they delete the character to the
     left of the insertion cursor.

[25]
     Control-d deletes the character to the right of the insertion cursor.

[26]
     Meta-d deletes the word to the right of the insertion cursor.

[27]
     Control-k deletes from the insertion cursor to the end of its line;
     if the insertion cursor is already at the end of a line, then
     Control-k deletes the newline character.

[28]
     Control-o opens a new line by inserting a newline character in front
     of the insertion cursor without moving the insertion cursor.

[29]
     Meta-backspace and Meta-Delete delete the word to the left of the
     insertion cursor.

[30]
     Control-x deletes whatever is selected in the text widget.

[31]
     Control-t reverses the order of the two characters to the right of
     the insertion cursor.

     If the widget is disabled using the *-state* option, then its view
     can still be adjusted and text can still be selected, but no
     insertion cursor will be displayed and no text modifications will
     take place.

     The behavior of texts can be changed by defining new bindings for
     individual widgets or by redefining the class bindings.

PERFORMANCE ISSUES
==================

   Text widgets should run efficiently under a variety of conditions.  The
text widget uses about 2-3 bytes of main memory for each byte of text, so
texts containing a megabyte or more should be practical on most
workstations.  Text is represented internally with a modified B-tree
structure that makes operations relatively efficient even with large texts.
Tags are included in the B-tree structure in a way that allows tags to
span large ranges or have many disjoint smaller ranges without loss of
efficiency.  Marks are also implemented in a way that allows large numbers
of marks.  In most cases it is fine to have large numbers of unique tags,
or a tag that has many distinct ranges.

   One performance problem can arise if you have hundreds or thousands of
different tags that all have the following characteristics: the first and
last ranges of each tag are near the beginning and end of the text,
respectively, or a single tag range covers most of the text widget.  The
cost of adding and deleting tags like this is proportional to the number
of other tags with the same properties.  In contrast, there is no problem
with having thousands of distinct tags if their overall ranges are
localized and spread uniformly throughout the text.

   Very long text lines can be expensive, especially if they have many
marks and tags within them.

   The display line with the insert cursor is redrawn each time the cursor
blinks, which causes a steady stream of graphics traffic.  Set the
*-insertofftime* option to 0 avoid this.

SEE ALSO
========

   `Tk::ROText|Tk::ROText' in this node `Tk::TextUndo|Tk::TextUndo' in
this node

KEYWORDS
========

   text, widget

An improved text widget for perl/tk
***********************************

NAME
====

   Tk::Text::SuperText - An improved text widget for perl/tk

SYNOPSIS
========

   *$super_text* = *$paren*->*SuperText*(?options?);

STANDARD OPTIONS
================

   *-background*	*-highlightbackground*	*-insertontime*	*-selectborderwidth*
*-borderwidth*	*-highlightcolor*	*-insertwidth*	*-selectforeground*
*-cursor*	*-highlightthickness*	*-padx*	*-setgrid*
*-exportselection*	*-insertbackground*	*-pady*	*-takefocus*
*-font*	*-insertborderwidth*	*-relief*	*-xscrollcommand*
*-foreground*	*-insertofftime*	*-selectbackground*	*-yscrollcommand*
*-ansicolor*

   See Tk/options, for details of the standard options.

   *-height*	*-spacing1*	*-spacing2*	*-spacing3*
*-state*	*-tabs*	*-width*	*-wrap*

   See Tk/Text, for details of theis options.

WIDGET-SPECIFIC OPTIONS
=======================

Name:	*indentMode*
Class:	*IndentMode*
Switch:	*-indentmode*
     Specifies how to indent when a new line is inserted in the text.  The
     possible modes are none for no indent at all or *auto* for positioning
     the insertion cursor right below the first non-white space character
     of the previous line.

Name:	*undoDepth*
Class:	*UndoDepth*
Switch:	*-undodepth*
     Sets the maximum depth for the undo buffer:a number specifies the
     numbers of insert or delete operations that can be stored in the
     buffer before the oldest one is poped out and forgotten;0 stops the
     undo feature,undef sets unlimited depth.

Name:	*redoDepth*
Class:	*RedoDepth*
Switch:	*-redodepth*
     Sets the maximum depth for the redo buffer:a number specifies the
     numbers of undo operations that can be stored in the buffer before
     the oldest one is poped out and forgotten;0 stops the redo
     feature,undef sets unlimited depth.

Name:	*showMatching*
Class:	*ShowMatching*
Switch:	*-showmatching*
     With a value of 1 activates the matching parentheses feature.0
     deactivates it.

Name:	*matchHighlightTime*
Class:	*MatchHighlightTime*
Switch:	*-matchhighlighttime*
     Sets the number of milliseconds the match highlight stays visible;
     with a value of 0 the highlight stays on till next match.

Name:	*matchForeground*
Class:	*MatchForeground*
Switch:	*-matchforeground*
     Set the foreground color for the char hilighted by the
     match-parentheses command.

Name:	*matchBackground*
Class:	*MatchBackground*
Switch:	*-matchbackground*
     Set the background color for the char hilighted by the
     match-parentheses command.

Name:	*matchingCouples*
Class:	*MatchingCouples*
Switch:	*-matchingcouples*
     Sets the chars that are searched for a matching counterpart.  The
     format is a simple string with matching chars coupled in left-right
     order; here's an example: *{}[]()""* .  For double couples ("") the
     match is done only on the forwarding chars.

Name:	*insertMode*
Class:	*InsertMode*
Switch:	*-insertmode*
     Sets the default insert mode: insert or overwrite .

Name:	*ansiColor*
Class:	*AnsiColor*
Switch:	*-ansicolor*
     Enables or disables use of Tk-TextANSIColor module (by Tim Jenness
     <t.jenness@jach.hawaii.edu>).  This option was implemented by Jim
     Turner <turnerjw2@netscape.net> (THANKS for the support!)

DESCRIPTION
===========

   *Tk::Text::SuperText* implements many new features over the standard
Tk/Text, widget while supporting all it's standard
features.Its used simply as the Tk/Text, widget.  New
Features:

   * Unlimited undo/redo.

     So you can undo and redo whatever you deleted/inserted whenever you
     want.  To reset the undo and redo buffers call this method:
     *$w*->*resetUndo*;

   * Rectangular selections.

     Rectangular text zones can be selected,copied,deleted,shifted with
     the mouse or with the keyboard.

   * Selection right/left char and tab shift.

     Text selections can be shifted left/right of  one or more chars or a
     tabs.

   * Normal and 'inline' selection paste.

     The 'normal' paste is the normal text paste you know :

    Paste Buffer:
          line x

          line y

    Text Buffer:
          line 1

          line2

    Normal paste at line 1:
          *line x*

          *line y*

          line 1

          line 2

    The 'inline' paste work as this:
    Inline paste at line 1:
          *line x* line 1

          *line y* line 2

   * Parentheses matching.

     To help you inspect nested parentheses,brackets and other
     characters,*SuperText* has both an automatic parenthesis matching
     mode,and a find matching command.  Automatic parenthesis matching is
     activated when you type or when you move the insertion cursor after a
     parenthesis.It momentarily highlightsthe matching character if that
     character is visible in the window.To find a matching character
     anywhere in the file,position the cursor after the it,and call the
     find matching command.

   * Autoindenting.

     When you press the Return or Enter key,spaces and tabs are inserted
     to line up the insert point under the start of the previous line.

   * Control codes insertion.

     You can directly insert a non printable control character in the text.

   * Commands are managed via virtual events.

     Every *SuperText* command is binded to a virtual event,so to call it
     or to bind it to a key sequence use the Tk/event,
     functions.  I used this format for key bind so there's no direct
     key-to-command bind,and this give me more flexibility;however you can
     use normal binds.

     Example:

     *$w*->*eventAdd*(*'Tk::Text::SuperText','<<SelectAll>>','<Control-a>'*);

     To set default events bindigs use this methos: *$w*->*bindDefault*;

   * Default key bindings are redefined (not really a feature :).

     Every virtual event has an associated public method with the same
     name of the event but with the firts char in lower case (eg:
     *<<MouseSelect>>* event has a corresponding
     *$super_text*->*mouseSelect* method).

     Virtual Event/Command		Default Key Binding

     *MouseSetInsert*			*<Button1>* *MouseSelect*			*<B1-Motion>*
     *MouseSelectWord*		*<Double-1>* *MouseSelectLine*		*<Triple-1>*
     *MouseSelectAdd*			*<Shift-1>* *MouseSelectAddWord*		*<Double-Shift-1>*
     *MouseSelectAddLine*		*<Triple-Shift-1>*
     *MouseSelectAutoScan*		*<B1-Leave>*
     *MouseSelectAutoScanStop*	*<B1-Enter>*,*<ButtonRelease-1>*
     *MouseMoveInsert*		*<Alt-1>* *MouseRectSelection*		*<Control-B1-Motion>*
     *MouseMovePageTo*		*<2>* *MouseMovePage*			*<B2-Motion>*
     *MousePasteSelection*		*<ButtonRelease-2>*

     *MoveLeft*				*<Left>* *SelectLeft*			*<Shift-Left>*
     *SelectRectLeft*			*<Shift-Alt-Left>* *MoveLeftWord*			*<Control-Left>*
     *SelectLeftWord*			*<Shift-Control-Left>* *MoveRight*				*<Right>*
     *SelectRight*			*<Shift-Right>* *SelectRectRight*		*<Shift-Alt-Right>*
     *MoveRightWord*			*<Control-Right>*
     *SelectRightWord*		*<Shift-Control-Right>* *MoveUp*				*<Up>*
     *SelectUp*				*<Shift-Up>* *SelectRectUp*			*<Shift-Alt-Up>*
     *MoveUpParagraph*		*<Control-Up>*
     *SelectUpParagraph*		*<Shift-Control-Up>*
     *MoveDown*				*<Down>* *SelectDown*			*<Shift-Down>*
     *SelectRectDown*			*<Shift-Alt-Down>*
     *MoveDownParagraph*		*<Control-Down>*
     *SelectDownParagraph*		*<Shift-Control-Down>*
     *MoveLineStart*			*<Home>* *SelectToLineStart*		*<Shift-Home>*
     *MoveTextStart*			*<Control-Home>*
     *SelectToTextStart*		*<Shift-Control-Home>* *MoveLineEnd*			*<End>*
     *SelectToLineEnd*		*<Shift-End>* *MoveTextEnd*			*<Control-End>*
     *SelectToTextEnd*		*<Shift-Control-End>* *MovePageUp*			*<Prior>*
     *SelectToPageUp*			*<Shift-Prior>* *MovePageLeft*			*<Control-Prior>*
     *MovePageDown*			*<Next>* *SelectToPageDown*		*<Shift-Next>*
     *MovePageRight*			*<Control-Next>*
     *SetSelectionMark*		*<Control-space>*,*<Select>*
     *SelectToMark*			*<Shift-Control-space>*,*<Shift-Select>*

     *SelectAll*				*<Control-a>* *SelectionShiftLeft*		*<Control-comma>*
     *SelectionShiftLeftTab*	*<Control-Alt-comma>*
     *SelectionShiftRight*		*<Control-period>*
     *SelectionShiftRightTab*	*<Control-Alt-period>*

     *Ins*					*<Insert>* Enter				*<Return>*
     *AutoIndentEnter*		*<Control-Return>*
     *NoAutoindentEnter*		*<Shift-Return>* Del					*<Delete>*
     *BackSpace*				*<BackSpace>* *DeleteToWordStart*		*<Shift-BackSpace>*
     *DeleteToWordEnd*		*<Shift-Delete>*
     *DeleteToLineStart*		*<Alt-BackSpace>*
     *DeleteToLineEnd*		*<Alt-Delete>* *DeleteWord*			*<Control-BackSpace>*
     *DeleteLine*			*<Control-Delete>*

     *InsertControlCode*		*<Control-Escape>*

     *FocusNext*				*<Control-Tab>* *FocusPrev*				*<Shift-Control-Tab>*

     *FlashMatchingChar*		*<Control-b>*
     *RemoveMatch*			*<Control-B>* *FindMatchingChar*		*<Control-j>*
     *JumpToMatchingChar*		*<Control-J>*

     Escape				*<Escape>*

     *Tab* 					*<Tab>*

     *LeftTab* 				*<Shift-Tab>*

     Copy 				*<Control-c>*

     *Cut* 					*<Control-x>*

     Paste 				*<Control-v>*

     *InlinePaste* 			*<Control-V>*

     Undo 				*<Control-z>*

     *Redo*					*<Control-Z>*

     *Destroy*				*<Destroy>*

     *MenuSelect*			*<Alt-KeyPress>*

   * Public methods.

     $widget->*mouseSetInsert*

     $widget->*museSelect*

     $widget->*mouseSelectWord*

     $widget->*mouseSelectLine*

     $widget->*mouseSelectAdd*

     $widget->*mouseSelectAddWord*

     $widget->*mouseSelectAddLine*

     $widget->*mouseSelectAutoScan*

     $widget->*mouseSelectAutoScanStop*

     $widget->*mouseMoveInsert*

     $widget->*mouseRectSelection*

     $widget->*mouseMovePageTo*

     $widget->*mouseMovePage*

     $widget->*mousePasteSelection*

     $widget->*moveLeft*

     $widget->*selectLeft*

     $widget->*selectRectLeft*

     $widget->*moveLeftWord*

     $widget->*selectLeftWord*

     $widget->*moveRight*

     $widget->*selectRight*

     $widget->*selectRectRight*

     $widget->*moveRightWord*

     $widget->*selectRightWord*

     $widget->*moveUp*

     $widget->*selectUp*

     $widget->*selectRectUp*

     $widget->*moveUpParagraph*

     $widget->*selectUpParagraph*

     $widget->*moveDown*

     $widget->*selectDown*

     $widget->*selectRectDown*

     $widget->*moveDownParagraph*

     $widget->*selectDownParagraph*

     $widget->*moveLineStart*

     $widget->*selectToLineStart*

     $widget->*moveTextStart*

     $widget->*selectToTextStart*

     $widget->*moveLineEnd*

     $widget->*selectToLineEnd*

     $widget->*moveTextEnd*

     $widget->*selectToTextEnd*

     $widget->*movePageUp*

     $widget->*selectToPageUp*

     $widget->*movePageLeft*

     $widget->*movePageDown*

     $widget->*selectToPageDown*

     $widget->*movePageRight*

     $widget->*setSelectionMark*

     $widget->*selectToMark*

     $widget->*selectAll*

     $widget->*selectionShiftLeft*

     $widget->*selectionShiftLeftTab*

     $widget->*selectionShiftRight*

     $widget->*selectionShiftRightTab*

     $widget->*ins*

     $widget->enter

     $widget->*autoIndentEnter*

     $widget-> *noAutoindentEnter*

     $widget->del

     $widget->*backSpace*

     $widget->*deleteToWordStart*

     $widget->*deleteToWordEnd*

     $widget->*deleteToLineStart*

     $widget->*deleteToLineEnd*

     $widget->*deleteWord*

     $widget->*deleteLine*

     $widget->*insertControlCode*

     $widget->*focusNext*

     $widget->*focusPrev*

     $widget->*flashMatchingChar*

     $widget->*removeMatch*

     $widget->*findMatchingChar*

     $widget->*jumpToMatchingChar*

     $widget->escape

     $widget->*tab*

     $widget->*leftTab*

     $widget->copy

     $widget->cut

     $widget->paste

     $widget->*inlinePaste*

     $widget->undo

     $widget->redo

     $widget->destroy

     $widget->*menuSelect*

AUTHOR
======

   Alessandro Iob <*alexiob@dlevel.com*>.

SEE ALSO
========

   `Tk::Text|Tk::Text' in this node `Tk::ROText|Tk::ROText' in this node
`Tk::TextUndo|Tk::TextUndo' in this node

KEYWORDS
========

   text, widget

Tk::Text widget with support for ANSI color escape codes
********************************************************

NAME
====

   Tk::TextANSIColor - Tk::Text widget with support for ANSI color escape
codes

SYNOPSIS
========

     use Tk::TextANSIColor;

     $wid = $mw->TextANSIColor(?options,...?);

     $wid->insert($pos, $string, ?taglist, ?string, ?taglist);

     use Term::ANSIColor;
     $red = color('red');  # Retrieve color codes
     $bold = color('bold');
     $wid->insert('end', "$red red text $bold with bold\n");

DESCRIPTION
===========

   This widget extends the capabilities of the standard Tk::Text widget by
adding support for ANSI color escape codes. When these escape codes are
detected they are replaced by equivalent tags.

   This widget was developed to solve the problem associated with driving
a scrolling status display on a GUI as well as a status display going to
an Xterm without having to know whether an xterm or Tk window is receiving
the status information. Mainly used in conjunction with a tied filehandle:

     $text = $MW->TextANSIColor->pack;
     tie *TEXT, "Tk::TextANSIColor", $text;

     $info = colored("Some information\n", 'red');

     # Print information to all filehandles
     print TEXT $info
     print STDOUT $info

   Currently the Term::ANSIColor module is required in order to decode the
escape codes (and probably to generate them in the first place).

TAGS
====

   This widget uses the following tags internally:

     ANSIbd - bold
     ANSIul - underline
     ANSIfgCOL - foreground color
     ANSIbgCOL - background color

   where COL can be one of black, red, green, yellow, blue, magenta, cyan
or white.

   If required, the tags can be altered after the widget is created by
using the tagConfigure() method. e.g.:

     $widget->tagConfigure('ANSIfgred', -foreground => 'blue');

   in order to make 'red' appear 'blue'.

REQUIREMENTS
============

   This modules requires the Term::ANSIColor module.  The Tk module is
also required.

SEE ALSO
========

   See Tk/Text, Term/ANSIColor,

AUTHOR
======

   Tim Jenness (<`t.jenness@jach.hawaii.edu'>)

COPYRIGHT
=========

   Copyright (c) 1999-2000 Tim Jenness. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

perl/tk text widget with bindings to undo changes.
**************************************************

NAME
====

   Tk::TextUndo - perl/tk text widget with bindings to undo changes.

SYNOPSIS
========

       *use Tk::TextUndo;*

       *$testundo* = *$parent*->*TextUndo*(?*-option*=>value, ...?);

DESCRIPTION
===========

   This IS-A text widget with an unlimited 'undo' history but without a
re'undo' capability.

Bindings
--------

   The `TextUndo' widget has the same bindings as the `Text|Tk::Text' in
this node widget.  In addition there are the following bindings:

Event <L4> <<Undo>>
     undo the last change.  Pressing <L4> several times undo step by step
     the changes made to the text widget.

Methods
-------

   The `TextUndo' widget has the same methods as Text widget.  Additional
methods for the `TextUndo' widget are:

$text->Load($filename);
     Loads the contents of the $filename into the text widget. Load()
     delete the previous contents of the text widget as well as it's undo
     history of the previous file.

$text->Save(?$otherfilename?)
     Save contents of the text widget to a file. If the $otherfilename is
     not specified, the text widget contents writes the file of $filename
     used in the last Load() call.  If no file was previously Load()'ed an
     error message pops up.  The default filename of the last Load() call
     is not overwriten by $otherfilename.

$text->FileName(?$otherfilename?)
     If passed an argument sets the file name associated with the loaded
     document. Returns the current file name associated with the document.

KEYS
====

   widget, text, undo

SEE ALSO
========

   See Tk/Text, Tk/ROText,

gang together Listboxes
***********************

NAME
====

   Tk::TiedListbox - gang together Listboxes

     use Tk::TiedListbox

     $l1 = $widget->Listbox(-exportselection => 0,...);
     $l2 = $widget->Listbox(-exportselection => 0,...);
     $l3 = $widget->Listbox(-exportselection => 0,...);
     $l1->tie([$l2,$l3]);

DESCRIPTION
===========

   TiedListbox causes two or more Listboxes to be operated in tandem.  One
application is emulating multi-column listboxes. The scrolling, selection,
or both mechanisms may be tied together. The methods tie and untie are
provided, along with overridden versions of some of the Listbox methods to
provide tandem operation.

   Scrollbars are fully supported. You can use either explicitly created
`Scrollbar|Tk::Scrollbar' in this nodes, the *ScrlListbox* widget, or the
`Scrolled|Tk::Scrolled' in this node super-widget. Tricks to "attach"
multiple tied listboxes to a single scrollbar are unnecessary and will
lead to multiple calls of the listbox methods (a bad thing).

   The configuration options, geometry, and items of the Listboxes are not
altered by tying them. The programmer will have to make sure that the
setup of the Listboxes make sense together. Here are some (unenforced)
guidelines:

   For listboxes with tied selection:

   * set *-exportselection* to 0 for all but possibly one Listbox

   * use identical *-selectmode* for all Listboxes

   * if items are added/deleted, they should be done all at once and at
     the same index, or the selection should be cleared

   * Listboxes should have the same number of items

   For listboxes with tied scrolling:

   * use the same window height and font for all Listboxes

   * Listboxes should have the same number of items

METHODS
=======

*$listbox*->tie?(?option?, [listbox,...])?
     Ties together *$listbox* and the list of Listboxes with the given
     option. Returns *$listbox*.

     If no arguments are given, returns a list containing two items: the
     tie option ("scroll", "selection", or "all") and the list of Listboxes
     to which *$listbox* is tied.

     option can be one of "scroll", "selection", or "all".  If omitted,
     "all" is assumed. "scroll" makes the tied Listboxes scroll together,
     "selection" makes selections occur simultaneously in all tied
     Listboxes, and "all" effects both actions.

     All the Listboxes are untied (if previously tied) before being tied
     to each other; hence a Listbox can only be in one "tie group" at a
     time. "Tiedness" is commutative.

     The tie method can be called with either Listbox or TiedListbox
     objects. All Listbox objects specified are reblessed to TiedListbox
     objects.

     Code such as below can be used to tie ScrlListboxes:

          $slb1=ScrlListbox(...); # or Scrolled('Listbox',...
          $slb2=ScrlListbox(...); # or Scrolled('Listbox',...
          $slb1->tie([$slb2->Subwidget('scrolled')]);

*$listbox*->*untie()*
     This function unties the Listbox from its "tie group". The other items
     in the "tie group" (if more than one) remain tied to each other.

     Returns a list containing two items: the old tie option ("scroll",
     "selection", or "all") and the list of Listboxes to which *$listbox*
     was tied.

OVERRIDDEN METHODS
==================

   You probably don't care about these. They are just details to tie
together the behaviors of the listboxes.

   All overriden methods take identical arguments as the corresponding
Listbox methods (see Tk/Listbox, for a full
description). All overridden methods that take an index interpret that
index in the context of the listbox object provided.

*$listbox*->activate(...)
*$listbox*->selection(...)
     To allow tied selection, these functions are overridden for listboxes
     tied together with the "selection" or "all" option. When an item is
     selected or activated in one listbox, the items with the same index
     (if present) are selected or activated in all tied listboxes.

     The selection('includes',...) submethod returns only information
     about the given *$listbox*.

*$listbox*->scan(...)
*$listbox*->see(...)
*$listbox*->*yview*(...)
     To allow tied scrolling, these functions are overridden for listboxes
     tied together with the "scroll" or "all" option. When one listbox is
     scrolled, all the other tied listboxes are scrolled by the same number
     of items (if possible). An attempt is made to keep items of the same
     index at the top of each tied listbox, while not interfering with the
     normal scrolling operations.

     The *yview* method with no arguments returns only information about
     the given *$listbox*.

     Horizontal scrolling (via *xview*) is not tied.

BUGS
====

   Reblessing the widgets to TiedListbox might be too weird. It will
disable any additional features for widgets in a class derived from
Listbox (none yet that I know of).

   The bindtags for reblessed widgets aren't updated. This is probably
wouldn't be a good thing to do automatically anyway.

AUTHOR
======

   Andrew Allen <ada@fc.hp.com>

   This code may be distributed under the same conditions as Perl.

Scrollable frame with sub-widgets arranged into rows
****************************************************

NAME
====

   Tk::Tiler - Scrollable frame with sub-widgets arranged into rows

SYNOPSIS
========

     use Tk::Tiler;

     my $tl = $parent->Scrolled('Tiler', -columns => n, -rows => n);

     my $a  = $tl->Xxxxx(...);
     my $b  = $tl->Xxxxx(...);
     my $c  = $tl->Xxxxx(...);

     $tl->Manage($a,$b,$c);

DESCRIPTION
===========

   Tiler is derived form Tk::Frame. It is a geometry managing widget which
accepts widgets to manage. It places the widgets in a grid with as many
widgets as possible in a row. All the "slots" in the grid are the same
size, which is determined by the largest managed widget.

   The grid may be scrolled vertically.

Create and manipulate Tix Grid widgets
**************************************

NAME
====

   Tk::TixGrid - Create and manipulate Tix Grid widgets

SYNOPSIS
========

       *$tixgrid* = *$parent*->*TixGrid*?(options)?;

     The port of C code and bindings is done but needs
     debugging.  THERE ARE KNOWN BUGS. Work in progress ...

STANDARD OPTIONS
================

   *-background* 	*-borderwidth* 	*-cursor* 	*-font*
*-foreground* 	*-height* 	*-highlightbackground* 	*-highlightcolor*
*-highlightthickness* 	*-padx* 	*-pady* 	*-relief*
*-selectbackground* 	*-selectborderwidth* 	*-selectforeground*
*-state* 	*-takefocus* 	*-width* 	*-xscrollcommand*
*-yscrollcommand*

   See Tk/options, for details of the standard options.

WIDGET-SPECIFIC OPTIONS
=======================

Name:	*browseCmd*
Class:	*BrowseCmd*
Switch:	*-browsecmd*
     ?docu here?  Not in configure output but used in bindings ??!!

     If defined, gives a perl/Tk `callback|Tk::callbacks' in this node to
     be executed when the user browses a grid cell (This is normally the
     case when the user clicks on an entry).  When this callback is
     called, it is passed with two additional parameters: x y, where (x,y)
     is the location of the cell that has just been clicked.

Name:	Command
Class:	Command
Switch:	*-command*
     ?docu here?  Not in configure output but used in bindings ??!!

Name:	*editDoneCmd*
Class:	*EditDoneCmd*
Switch:	*-editdonecmd*
     If defined, gives a perl/Tk `callback|Tk::callbacks' in this node to
     be executed when the user has edited grid cell. When this callback is
     called, it is passed with two additional parameters: x y, where (x,y)
     is the location of the cell that has just been edited.

Name:	*editNotifyCmd*
Class:	*EditNotifyCmd*
Switch:	*-editnotifycmd*
     If defined gives a perl/Tk `callback|Tk::callbacks' in this node to
     be executed when the user tries to edit a grid cell.  When this
     callback is called, it is passed with two additional parameters: x y,
     where (x,y,) is the location of the cell. This callback should return
     a boolean value: *true* indicates that the cell is editable and false
     otherwise.

Name:	*FloatingCols*
Class:	*floatingCols*
Switch:	*-floatingcols*
     Defines the number of columns that fixed when the widget is
     horizontally scrolled.  These column(s) can be used as label(s) for
     the column(s).  The floating column(s) can be configured in the
     *-formatcmd* callback with the *formatBorder* method.  The default
     value is 0.

Name:	*FloatingRows*
Class:	*floatingRows*
Switch:	*-floatingrows*
     Defines the number of rows that are fixed when the widget is
     vertically scrolled.  These row(s) can be used as label(s) for the
     row(s).  The floating row(s) can be configured in the *-formatcmd*
     callback with the *formatBorder* method.  The default value is 0.

Name:	*formatCmd*
Class:	*FormatCmd*
Switch:	*-formatcmd*
     If defined, gives a perl/Tk `callback|Tk::callbacks' in this node to
     be executed when the grid cells need to be formatted on the screen.
     Normally, this callback calls the format method (see below).  When
     this callback is called, it is passed with five additional
     parameters: type x1 *y1* x2 *y2*. type gives the logical type of the
     region in the grid. It may be one of the following.

    *x-region*
          the horizontal margin

    *y-region*
          the vertical margin

    *s-region*
          the area where the horizontal and vertical margins are joined

    main
          all the cells that do not fall into the above three types

     x1 *y1* x2 *y2* gives the extent of the region that needs formatting.

Name:	leftMargin
Class:	LeftMargin
Switch:	*-leftmargin*
     In the number of cells, gives the width of vertical margin.  A zero
     indicates that no vertical should be drawn.

Name:	*itemType*
Class:	*ItemType*
Switch:	*-itemtype*
     ?docu here?

Name:	*selectMode*
Class:	*SelectMode*
Switch:	*-selectmode*
     Specifies one of several styles for manipulating the selection.  The
     value of the option may be arbitrary, but the default bindings expect
     it to be either single, browse, multiple, or *extended*; the default
     value is single.

Name:	*selectUnit*
Class:	*SelectUnit*
Switch:	*-selectunit*
     Specifies the selection unit. Valid values are *cell*, column or row.

Name:	*sizeCmd*
Class:	*SizeCmd*
Switch:	*-sizecmd*
     ?docu here?

Name:	*topMargin*
Class:	TopMargin
Switch:	*-topmargin*
     In the number of cells, gives the height of horizontal margin.  A
     zero indicates that no horizontal should be drawn.

DESCRIPTION
===========

   The *TixGrid* method creates a TixGrid new window and returns a blessed
reference of this TixGrid widget.  Additional options, described above,
may be specified on the command line or in the option database to
configure aspects of the *TixGrid* widget such as its cursor and relief.

   A Grid widget displays its contents in a two dimensional grid of cells.
Each cell may contain one Tix display item, which may be in text, graphics
or other formats. See Tk/DItem, for more information about
Tix display items. Individual cells, or groups of cells, can be formatted
with a wide range of attributes, such as its color, relief and border.

WIDGET METHODS
==============

   The *TixGrid* method creates a TixGrid widget and returns a blessed
reference of this TixGrid widget.  This reference may be used to invoke
various operations on the widget.  It has the following general form:

       *$tixgrid*->method?(*arg, arg, ...*)?

   *arg*s determine the exact behavior of the method. The following
methods are possible for *TixGrid* widgets:

*$tixgrid*->anchor(action, x, y)
*$tixgrid*->anchorAction(x, y)
     Manipulates the *anchor cell* of the *TixGrid* widget.  The anchor
     cell is the end of the selection that is fixed while the user is
     dragging out a selection with the mouse.  Action can be clear, get or
     set.  If action is clear, x and y args are not accepted.

*$tixgrid*->*bdtype*(x, y ?,*xbdWidth*, *ybdWidth*?)
     ????

*$tixgrid*->cget('*-option*')
     Returns the current value of the configuration option given by
     *-option*. *-option* may have any of the values accepted by the
     *TixGrid* constructor method.

*$tixgrid*->configure(?*-option*??=>value, *-option*=>value, ...?)
     Query or modify the configuration options of the widget.  If no
     *-option* is specified, returns a list describing all of the
     available options for *$tixgrid* (see *Tk_ConfigureInfo* for
     information on the format of this list.) If *-option* is specified
     with no value, then the method returns a list describing the one
     named option (this list will be identical to the corresponding
     sublist of the value returned if no *-option* is specified).  If one
     or more *option-value* pairs are specified, then the method modifies
     the given widget option(s) to have the given value(s); in this case
     the method returns an empty string. *-option* may have any of the
     values accepted by the *TixGrid* constructor method.

*$tixgrid*->delete(*dim*, from?, to?)
*$tixgrid*->*deleteColumn*(from?, to?)
*$tixgrid*->*deleteRow*(from?, to?)
     *Dim* may be row or column. If to is not given, deletes a single row
     (or column) at the position from.  If to is given, deletes the range
     of rows (or columns) from position from through to.

*$tixgrid*->*dragsite*(option, x, y)
     ?docu here? not implemented :-(

*$tixgrid*->*dropsite*(option, x, y)
     ?docu here? not implemented :-(

*$tixgrid*->*editApply*
     If any cell is being edited, de-highlight the cell and applies the
     changes.

*$tixgrid*->*editSet*(x, y)
     Highlights the cell at (x,y) for editing, if the *-editnotify*
     callback returns true for this cell.

*$tixgrid*->*entrycget*(x, y, '*-option*')
     Returns the current value of the configuration option given by
     *-option* of the cell at (x,y).  *-option* may have any of the values
     accepted by the set method.

*$tixgrid*->*entryconfigure*(x, y?, *-option*??=>value, *-option*=>value, ...?)
     Query or modify the configuration options of the cell at (x,y).  If
     no *-option* is specified, returns a list describing all of the
     available options for the cell (see *Tk_ConfigureInfo* for information
     on the format of this list.)  If *-option* is specified with no
     value, then the method returns a list describing the one named option
     (this list will be identical to the corresponding sublist of the
     value returned if no *-option* is specified.) If one or more
     *option-value* pairs are specified, then the method modifies the
     given widget option(s) to have the given value(s); in this case the
     method returns an empty string.  Option may have any of the values
     accepted by the set method.

*$tixgrid*->format(option, ?args, ...?)

*$tixgrid*->*formatBorder*(*x1,y1*, *x2,y2*, options);

*$tixgrid*->*formatGrid*(*x1,y1*, *x2,y2*, options);
     the format method can only be called by the *-formatcmd* callback of
     the tixGrid widget.

     ?docu complete?

*$tixgrid*->*geometryinfo*(?width, ?height, ...?)
     ?docu here?  Return a list of 4 floats! Currently "{first1 last1}
     {first2,last2}" :-(

*$tixgrid*->index(*$coordx*, *$coordy*)
     ?docu here?

     retuns *(nx, ny)* of entry at position (*$coordx*, *$coordy*).
     (??widget or screen offset??)

*$tixgrid*->info(option, ?args, ...?)
     ?docu here?

*$tixgrid*->move(*dim*, from, to, offset)
*$tixgrid*->*moveColumn*(from, to, offset)
*$tixgrid*->*moveRow*(from, to, offset)
     *Dim* may be row or column. Moves the range of rows (or columns) from
     position from through to by the distance indicated by offset. For
     example, *$tixgrid*->*moveRow*(2, 4, 1) moves the rows 2,3,4 to rows
     3,4,5.

*$tixgrid*->nearest(x, y)
     ?docu here?  screen pos (pixels) to entry (nx,ny) translation.

*$tixgrid*->selection(option, x1, *y1* ?,x2, *y2*?)

*$tixgrid*->selectionOption(x1, *y1* ?,x2, *y2*?)
     Option one of: *adjust*, clear, *includes*, set, and toggle.

     x1 (y1) has not to be greater than x2 (y2), but only x2 and y2 can be
     'max'.

     BUG: *selection includes*: has no visible effect (as in Tix). Eh???

     BUG: *selection clear*: only works for 0, 0, max, max (as in Tix).
     Eh???

     When *x2, y2* are not given they default to *x1, y1*, respectively.

    *$tixgrid*->*selectionAdjust*(x1, *y1* ?,x2, *y2*?)
          ?docu here?

    *$tixgrid*->*selectionClear*(x1, *y1* ?,x2, *y2*?)
          ?docu here?

    *$tixgrid*->*selectionIncludes*(x1, *y1* ?,x2, *y2*?)
          ?docu here?

    *$tixgrid*->*selectionSet*(x1, *y1* ?,x2, *y2*?)
          ?docu here?

    *$tixgrid*->*selectionToggle*(x1, *y1* ?,x2, *y2*?)
          ?docu here?

*$tixgrid*->set(x, y?, *-itemtype*=>type??, *-option*=>value, ...?)
     Creates a new display item at the cell at (x,y). The optional
     *-itemtype* parameter gives the type of the display item.  An
     additional list of *option-value* pairs specify options of the
     display item. If a display item already exists at this cell, the old
     item will be deleted automatically.

*$tixgrid*->size(*dim*, index?, *-option*??=>value, ...?)
*$tixgrid*->*sizeColumn*(index?, *-option*??=>value, ...?)
*$tixgrid*->*sizeRow*(index?, *-option*??=>value, ...?)
     Queries or sets the size of the row or column given by *dim* and
     index. *Dim* may be row or column.  Index may be any non-negative
     integer that gives the position of a given row (or column).  Index
     can also be the string default; in this case, this method queries or
     sets the default size of all rows (or columns).  When no
     *option-value* pair is given, this method returns a list containing
     the current size setting of the given row (or column).  When
     *option-value* pairs are given, the corresponding options of the size
     setting of the given row are changed. *-option* may be one of the
     following:

    *-pad0* => *pixels*
          Specifies the paddings to the left of a column or the top of a
          row.

    *-pad1* => *pixels*
          Specifies the paddings to the right of a column or the bottom of
          a row.

    *-size* => val
          Specifies the width of a column or the height of a row.  Val may
          be: *auto* - the width of the column is set the widest cell in
          the column; a valid Tk screen distance unit (see
          *Tk_GetPixels*); or a real number following by the word chars
          (e.g. *3.4chars*) that sets the width of the column to the given
          number of characters.

*$tixgrid*->sort(*dimension*, start, end, ?*args ...*?)
     ?docu here? (not supported on Win* OSs up to now)

*$tixgrid*->unset(x, y)
     Clears the cell at (x,y) by removing its display item.

*$tixgrid*->*xview*
     ?docu here?

*$tixgrid*->*yview*
     ?docu here?

BINDINGS
========

   to be done.

SEE ALSO
========

   `Tk::DItem|Tk::DItem' in this node `Tk::callbacks|Tk::callbacks' in
this node `Tk::FloatEntry|Tk::FloatEntry' in this node

BUGS
====

   C code and bindings of TixGrid have some bugs.

KEYWORDS
========

   tix, tixgrid, table, display item, spreadsheet

methods for Tix widgets
***********************

NAME
====

   Tk::TixWidget - methods for Tix widgets

SYNOPSIS
========

     use Tk::TixWidget;
     @ISA = qw(Tk::Widget Tk::TixWidget);

DESCRIPTION
===========

   `Tk::TixWidget' provides methods that emulate the those used by Tcl/Tix
widgets.  There are currently only two methods supported: `tixEvent' and
`tixGetimage'.

tixGetimage( name )
===================

   Given name, look for an image file with that base name and return a
Tk::Image.  File extensions are tried in this order: `xpm', gif, `ppm',
`xbm' until a valid iamge is found.  If no image is found, try a builtin
image with that name.

tixEvent( option, ?value? )
===========================

   Return or set the tixEvent variable option.  Currently, the only option
used is "type".

AUTHOR
======

   Chris Dean <`ctdean@cogit.com'>

Create and manipulate Toplevel widgets
**************************************

NAME
====

   Tk::Toplevel - Create and manipulate Toplevel widgets

       *$toplevel* = *$parent*->Toplevel(?options?);

STANDARD OPTIONS
================

*-borderwidth*	*-highlightbackground*	*-highlightthickness*	*-takefocus*
*-class*	*-highlightcolor*	*-relief* *-cursor*

   See Tk/options, for details of the standard options.

WIDGET-SPECIFIC OPTIONS
=======================

Name:	background
Class:	Background
Switch:	*-background*
     This option is the same as the standard background option except that
     its value may also be specified as an undefined value.  In this case,
     the widget will display no background or border, and no colors will
     be consumed from its colormap for its background and border.

Name:	colormap
Class:	*Colormap*
Switch:	*-colormap*
     Specifies a colormap to use for the window.  The value may be either
     new, in which case a new colormap is created for the window and its
     children, or the name of another window (which must be on the same
     screen and have the same visual as $widget), in which case the new
     window will use the colormap from the specified window.  If the
     colormap option is not specified, the new window uses the default
     colormap of its screen.  This option may not be changed with the
     configure method.

Name:	container
Class:	Container
Switch:	*-container*
     The value must be a boolean.  If true, it means that this window will
     be used as a container in which some other application will be
     embedded (for example, a Tk toplevel can be embedded using the *-use*
     option).  The window will support the appropriate window manager
     protocols for things like geometry requests.  The window should not
     have any children of its own in this application.  This option may
     not be changed with the configure method.

Name:	height
Class:	*Height*
Switch:	*-height*
     Specifies the desired height for the window in any of the forms
     acceptable to *Tk_GetPixels*.  If this option is less than or equal
     to zero then the window will not request any size at all.

Name:	menu
Class:	Menu
Switch:	*-menu*
     Specifies a menu widget to be used as a menubar. On the Macintosh, the
     menubar will be displayed accross the top of the main monitor. On
     Microsoft Windows and all UNIX platforms, the menu will appear accross
     the toplevel window as part of the window dressing maintained by the
     window manager.

Name:	""
Class:	""
Switch:	*-screen*
     Specifies the screen on which to place the new window.  Any valid
     screen name may be used, even one associated with a different display.
     Defaults to the same screen as its parent.  This option is special in
     that it may not be specified via the option database, and it may not
     be modified with the configure method.

Name:	use
Class:	Use
Switch:	*-use*
     This option is used for embedding. If the value isn't an empty string,
     it must be the the window identifier of a container window, specified
     as a hexadecimal string like the ones returned by the *winfo id*
     command. The toplevel widget will be created as a child of the given
     container instead of the root window for the screen.  If the container
     window is in a Tk application, it must be a frame or toplevel widget
     for which the *-container* option was specified.  This option may not
     be changed with the configure method.

Name:	*visual*
Class:	*Visual*
Switch:	*-visual*
     Specifies visual information for the new window in any of the forms
     accepted by *Tk_GetVisual*.  If this option is not specified, the new
     window will use the default visual for its screen.  The *visual*
     option may not be modified with the configure method.

Name:	width
Class:	Width
Switch:	*-width*
     Specifies the desired width for the window in any of the forms
     acceptable to *Tk_GetPixels*.  If this option is less than or equal
     to zero then the window will not request any size at all.

DESCRIPTION
===========

   The Toplevel method creates a new toplevel widget (given by the $widget
argument).  Additional options, described above, may be specified on the
command line or in the option database to configure aspects of the
toplevel such as its background color and relief.  The toplevel command
returns the path name of the new window.

   A toplevel is similar to a frame except that it is created as a
top-level window:  its X parent is the root window of a screen rather than
the logical parent from its path name.  The primary purpose of a toplevel
is to serve as a container for dialog boxes and other collections of
widgets.  The only visible features of a toplevel are its background color
and an optional 3-D border to make the toplevel appear raised or sunken.

WIDGET METHODS
==============

   The Toplevel method creates a widget object.  This object supports the
configure and cget methods described in Tk/options,
which can be used to enquire and modify the options described above.  The
widget also inherits all the methods provided by the generic
`Tk::Widget|Tk::Widget' in this node class, and the `Tk::Wm|Tk::Wm' in
this node class.

BINDINGS
========

   When a new toplevel is created, it has no default event bindings:
toplevels are not intended to be interactive.

SEE ALSO
========

   `Tk::Widget|Tk::Widget' in this node `Tk::Wm|Tk::Wm' in this node

KEYWORDS
========

   toplevel, widget

Create and manipulate Tree widgets
**********************************

NAME
====

   Tk::Tree - Create and manipulate Tree widgets

SYNOPSIS
========

       *use Tk::Tree;*

       $tree = *$parent*->Tree(?options?);

SUPER-CLASS
===========

   The Tree class is derived from the `HList|Tk::HList' in this node class
and inherits all the methods, options and subwidgets of its super-class.
A Tree widget is not scrolled by default.

STANDARD OPTIONS
================

   Tree supports all the standard options of an HList widget.  See
Tk/options, for details on the standard options.

WIDGET-SPECIFIC OPTIONS
=======================

Name:		*browseCmd*
Class:		*BrowseCmd*
Switch:		*-browsecmd*
     Specifies a `callback|Tk::callbacks' in this node to call whenever
     the user browses on an entry (usually by single-clicking on the
     entry). The callback is called with one argument, the pathname of the
     entry.

Name:		*closeCmd*
Class:		*CloseCmd*
Switch:		*-closecmd*
     Specifies a `callback|Tk::callbacks' in this node to call whenever an
     entry needs to be closed (See `"BINDINGS"' in this node below). This
     method is called with one argument, the pathname of the entry. This
     method should perform appropriate actions to close the specified
     entry. If the *-closecmd* option is not specified, the default
     closing action is to hide all child entries of the specified entry.

Name:		command
Class:		Command
Switch:		*-command*
     Specifies a `callback|Tk::callbacks' in this node to call whenever
     the user activates an entry (usually by double-clicking on the
     entry). The callback is called with one argument, the pathname of the
     entry.

Name:		*ignoreInvoke*
Class:		*IgnoreInvoke*
Switch:		*-ignoreinvoke*
     A Boolean value that specifies when a branch should be opened or
     closed. A branch will always be opened or closed when the user presses
     the (+) and (-) indicators. However, when the user invokes a branch
     (by doublc-clicking or pressing <Return>), the branch will be opened
     or closed only if *-ignoreinvoke* is set to false (the default
     setting).

Name:		*openCmd*
Class:		*OpenCmd*
Switch:		*-opencmd*
     Specifies a `callback|Tk::callbacks' in this node to call whenever an
     entry needs to be opened (See `"BINDINGS"' in this node below). This
     method is called with one argument, the pathname of the entry. This
     method should perform appropriate actions to open the specified
     entry. If the *-opencmd* option is not specified, the default opening
     action is to show all the child entries of the specified entry.

DESCRIPTION
===========

   The Tree method creates a new window and makes it into a Tree widget
and return a reference to it.  Additional options, described above, may be
specified on the command line or in the option database to configure
aspects of the Tree widget such as its cursor and relief.

   The Tree widget can be used to display hierarchical data in a tree
form. The user can adjust the view of the tree by opening or closing parts
of the tree.

   To display a static tree structure, you can add the entries into the
Tree widget and hide any entries as desired. Then you can call the
*autosetmode* method. This will set up the Tree widget so that it handles
all the open and close events automatically.  the demonstration program
`Tixish/examples/perl-tix-tree').

   The above method is not applicable if you want to maintain a dynamic
tree structure, i.e, you do not know all the entries in the tree and you
need to add or delete entries subsequently. To do this, you should first
create the entries in the Tree widget. Then, use the setmode method to
indicate the entries that can be opened or closed, and use the *-opencmd*
and *-closecmd* options to handle the opening and closing events. (Please
see the demonstration program `Tixish/examples/perl-tix-dyntree').

   Use either

       *$parent*->*Scrolled*(*'Tree'*, ... );

   or

       *$parent*->*ScrlTree*( ... );

   to create a scrolled Tree. See Tk/Scrolled, for
details.

WIDGET METHODS
==============

   The Tree method creates a widget object.  This object supports the
configure and cget methods described in Tk/options,
which can be used to enquire and modify the options described above.  The
widget also inherits all the methods provided by the generic
`Tk::Widget|Tk::Widget' in this node class.

   The following additional methods are available for Tree widgets:

$tree->*autosetmode*
     This method calls the setmode method for all the entries in this Tree
     widget: if an entry has no child entries, its mode is set to none.
     Otherwise, if the entry has any hidden child entries, its mode is set
     to open; otherwise its mode is set to close.

$tree->close(*entryPath*)
     Close the entry given by *entryPath* if its mode is close.

$tree->*getmode*(*entryPath*)
     Returns the current mode of the entry given by *entryPath*.

$tree->open(*entryPath*)
     Open the entry given by *entryPath* if its mode is open.

$tree->setmode(*entryPath, mode*)
     This method is used to indicate whether the entry given by
     *entryPath* has children entries and whether the children are
     visible. mode must be one of open, close or none. If mode is set to
     open, a (+) indicator is drawn next the the entry. If mode is set to
     close, a (-) indicator is drawn next the the entry. If mode is set to
     none, no indicators will be drawn for this entry. The default mode is
     none. The open mode indicates the entry has hidden children and this
     entry can be opened by the user. The close mode indicates that all
     the children of the entry are now visible and the entry can be closed
     by the user.

BINDINGS
========

   The basic mouse and keyboard bindings of the Tree widget are the same
as the `bindings of the HList|Tk::HList' in this node widget.  In
addition, the entries can be opened or closed under the following
conditions:

[1]
     If the mode of the entry is open, it can be opened by clicking on its
     (+) indicator.

[2]
     If the mode of the entry is close, it can be closed by clicking on
     its (-) indicator.

SEE ALSO
========

   `Tk::HList|Tk::HList' in this node

AUTHOR
======

   Perl/TK version by Chris Dean <ctdean@cogit.com>.  Original Tcl/Tix
version by Ioi Kim Lam.

ACKNOWLEDGEMENTS
================

   Thanks to Achim Bohnet <ach@mpe.mpg.de> for all his help.

Tk widget to draw a tree in a Canvas
************************************

NAME
====

   Tk::TreeGraph - Tk widget to draw a tree in a Canvas

SYNOPSIS
========

     use Tk ;
     use Tk::TreeGraph ;

     use strict ;

     my $mw = MainWindow-> new ;

     my $tg = $mw -> Scrolled('TreeGraph') ->pack(-expand => 1, -fill => 'both');

     $tg -> addLabel (text => 'some tree');

     my $ref = [qw/some really_silly text/];

     $tg -> addNode
      (
       nodeId => '1.0',
       text => $ref
      ) ;

     # EITHER add the arrow and the node
     $tg -> addDirectArrow
      (
       from => '1.0',
       to => '1.1'
      ) ;

     $tg->addNode
      (
       nodeId => '1.1',
       text => ['some','text']
      ) ;

     # OR add a node after another one, in this case the widget
     # will draw the arrow
     $tg->addNode
      (
       after =>'1.0',
       nodeId => '1.1',
       text => ['some','text']
      );

     $tg->arrowBind
      (
       button => '<1>',
       color => 'orange',
       command =>  sub{my %h = @_;
                       warn "clicked 1 arrow $h{from} -> $h{to}\n";}
      );

     $tg->nodeBind
      (
       button => '<2>',
       color => 'red',
       command => sub {my %h = @_;
                       warn "clicked 2 node $h{nodeId}\n";}
      );

     $tg->command( on => 'arrow', label => 'dummy 2',
                     command => sub{warn "arrow menu dummy2\n";});

     $tg->arrowBind(button => '<3>', color => 'green',
                  command => sub{$tg->popupMenu(@_);});

     $tg->command(on => 'node', label => 'dummy 1',
                     command => sub{warn "node menu dummy1\n";});

     $tg->nodeBind(button => '<3>', color => 'green',
                  command => sub{$tg->popupMenu(@_);});

     # adjust scrolled area with some margin
     my @array = $tg->bbox("all") ;
     $tg->configure(-scrollregion => [0, 0, $array[2] + 50, $array[3] + 50 ]);

     MainLoop ; # Tk's

DESCRIPTION
===========

   Tk::TreeGraph is a Canvas specialized to draw trees on a Canvas using
arrows and nodes. A node is simply some text imbedded in a rectangular
shape.

   TreeGraph is able to draw the following items:

   * node: some text in a rectangular shape.

   * direct arrow: an arrow to go from one node to the following one.

   * slanted arrow: an arrow to make a new branch.

   * shortcuts arrow: an arrow to represent a shortcut between 2 nodes from
     different branches.

   TreeGraph also provides :

   * a binding on nodes on button 1 to 'select' them.

   * Methods to bind nodes and arrows on user's call-back.

CAVEATS
=======

   You might say that the tree is a weird tree since it is drawn downward
and assymetric and adding branches leaves a some void between them.

   You'd be right. I'm not a specialist in tree drawing algorithms but the
crude algorithm used here works quite fine with drawing id trees for VCS
system. But as usual, I'm always listening for suggestions or even better,
patches ;-) .

   Note that the tree MUST be drawn from top to bottom and from left to
right. Unless you may get a very confusing drawing of a tree.

About Scrolling
===============

   First versions of TreeGraph used to tinker with a -scrollregion option
each time addNode was called. This was not consistent since the scrollbars
are added by the user when calling TreeGraph (using
Scrolled('TreeGraph')). Hence from now on, it will be the responsability
of the user to set a satisfying -scrollregion.

   The user may write this after all nodes are drawn to set the
scrollregion :

     my @array = $tg->bbox("all") ;
     $tg->configure(-scrollregion => [0, 0, $array[2] + 50, $array[3] + 50 ]);

   Furthermore, since configure will called only once, the resulting code
will be faster.

Widget Options
==============

   * -nodeColor: Color of the node rectangle.

   * -nodeTextColor: Color of the text within the nodes

   * -labelColor

   * -arrowColor

   * -shortcutColor: Color of the shortcut arrow (default 'orange')

   * -shortcutStyle: Style of the shortcut arrow. The arrow can be drawn as
     a 'straight' arrow or a 'spline'. (default 'straight')

   * -nodeTag: boolean. By default the nodeId is added at the beginning of
     the node text.

   * -arrowDeltaY: length of direct arrows (downward). default 40

   * -branchSeparation: minimum width between 2 branches of the tree
     (default 120)

   * -x_start: x coordinate of the root of the tree. (default 100)

   * -y_start: y coordinate of the root of the tree.(default 100)

Drawing Methods added to Canvas
===============================

   You draw the tree node after node with addNode using the 'after'
parameter. Then the object will infer the kind of arrow needed between the
2 nodes. Using the 'after' parameter, you no longer need to call youself
the addSlantedArrow or addDirectArrow methods.

addNode(...)
------------

   * nodeId: string to identify this node.

   * text: text string or array ref. This text will be written inside the
     rectangle

   * after: Either a [x,y] array ref setting the coordinate of the root of
     the tree (this can be used to draw the a first tree in the canvas
     and/or to draw a second tree in the canvas). If after is a nodeId, an
     arrow (direct or slanted) will be drawn from the 'after' node to this
     new node.

   Will add a new node (made of a rectangle with the text inside).

   Note that this method will add the nodeId on top of the passed text
('text' parameter).

modifyNode(...)
---------------

   * nodeId: string to identify the node to modify (mandatory).

   * text: text string or array ref. This text will be overwritten inside
     the rectangle. Note that modifyNode will refuse to change the text if
     the new text has more lines than the older text (because the text
     would not fit in the rectangle).

   * nodeColor: new color of the outline of the rectangle.

   * nodeTextColor: new color of the text of the node.

   * nodeFill: new color filling the rectangle.

   Will modify an existing node. Note that the geometry of the node will
not be changed.

flashNode(...)
--------------

   * nodeId: string to identify the node to modify (mandatory).

   * time: time in ms between each flash (default 500 ms)

   * nodeColor: new color of the outline of the rectangle.

   * nodeTextColor: new color of the text of the node.

   * nodeFill: new color filling the rectangle.

   Will make an existing node flash. Calling a second time this method on
a node will make the flashing stop.

addDirectArrow(...)
-------------------

   You can use this method if you want to change the default aspect of the
direct arrow. In this case do not use the 'after' parameter of the
addNode() method.

   * from: node id where the arrow starts

   * to: node id where the arrow ends

   Add a new straight (i.e. vertical) arrow starting from a node. Note that
the 'from' nodeId must be defined. The 'to' nodeId must NOT be defined.
(Remember that you must draw the tree from top to bottom)

addSlantedArrow(...)
--------------------

   You can use this method if you want to change the default aspect of the
slanted arrow. In this case do not use the 'after' parameter of the
addNode() method.

   Parameters are:

   * from: node id where the arrow starts

   * to: node id where the arrow ends

   Add a new branch connecting node 'id' to node 'id2'.  Note that the
'from' nodeId must be defined. The 'to' nodeId must NOT be defined.
(Remember that you must draw the tree from left to right)

addLabel(...)
-------------

   Put some text on the top of the graph.

   * text: text to be inserted on the top of the graph.

addShortcutInfo(...)
--------------------

   * from: node id where the arrow starts

   * to: node id where the arrow ends

   Declare that a shortcut arrow will be drawn from node 'arrow_start' and
'arrow_end'.

addAllShortcuts()
-----------------

   This method is to be called once all nodes, direct arrow and branch
arrows are drawn and all relevant calls to addShortcutInfo are done.

   It will draw shortcut arrows between the ids declared with the
addShortcutInfo method.

clear()
-------

   Clear the graph.

Management methods
==================

nodeBind(...)
-------------

   * button: button name to bind (e.g. '<1>')

   * color: color of the node when it is clicked on.

   * command: sub ref

   Bind the 'button' on all nodes. When 'button' is clicked, the node text
color will change to 'color' and the callback sub will be called with
these parameters:

     (on => 'node', nodeId => $nodeId)

arrowBind(...)
--------------

   * button: button name to bind (e.g. '<1>')

   * color: color of the node when it is clicked on.

   * command: sub ref

   Bind the 'button' on arrows. When 'button' is clicked, the arrow color
will change to 'color' and the callback sub will be called with these
parameters:

     (
       on   => 'arrow',
       from => nodeId_on_arrow_start,
       to   => nodeId_on_arrow_tip
     )

unselectAllNodes()
------------------

   Unselect all previously selected nodes (see button <1> binding)

getSelectedNodes()
------------------

   Return an array containing nodeIds of all nodes currently selected.

getNodeRectangle(...)
---------------------

   Returns the rectangle reference of the passed nodeId or of the node
selected by the user.

   Parameters are :

   * nodeId: nodeId attached to the rectangle

command(...)
------------

   This will add a new entry on a Popup menu which can be raised on a node
or an arrow.

   Parameters are :

   * on: either 'node' or 'arrow'

   * label: Label of the Popup menu entry

   * command: sub ref runned when the menu is invoked

   The callback will be invoked with these parameters when the command is
set for *nodes* :

     (on => 'node', nodeId => $nodeId)

   The callback will be invoked with these parameters when the command is
set for *arrows* :

     (
       on   => 'arrow',
       from => nodeId_on_arrow_start,
       to   => nodeId_on_arrow_tip
     )

Private methods
===============

   These functions are documented only for people wanting to improve or
inherit this widget.

setArrow(...)
-------------

   * color: color of the arrow when selected.

   Reset any previously selected arrow to default color and set the current
arrow to the color. This function should be used with a bind.

   Returns (from => $endNodeId, to => $tipNodeId) to specify the nodes the
arrow is attached to.

setNode()
---------

   * color: color of the arrow when selected.

   * nodeId: nodeId to select (optional, default to the node under the
     mouse pointer)

   Set node either from passed nodeId or from the mouse pointer.  When a
node is set, only the text is highlighted

   Returns the nodeId of the current node (i.e. the node clicked by the
user if this function was used in a bind)

toggleNode(...)
---------------

   * color: color of the arrow when selected.

   * nodeId: nodeId to select (optional, default to the node under the
     mouse pointer)

   Will toggle the node rectangle between 'color' and default.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998-2000 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1), Tk(3), Tk::Canvas(3)

Writing Tk applications in perl5.
*********************************

NAME
====

   perl/Tk - Writing Tk applications in perl5.

   This manual page is for beginners.  It assumes you know some perl, and
have got perl+Tk running.  Please run the 'widget' demo before reading
this text; it will teach you the various widget types supported by Tk.

Some background
===============

   Tk GUI programming is event-driven.  (This may already be familiar to
you.)  In event-driven programs, the main GUI loop is outside of the user
program and inside the GUI library.  This loop will watch all events of
interest, and activate the correct handler procedures to handle these
events.  Some of these handler procedures may be user-supplied; others
will be part of the library.

   For a programmer, this means that you're not watching what is happening;
instead, you are requested by the toolkit to perform actions whenever
necessary.  So, you're not watching for 'raise window / close window /
redraw window' requests, but you tell the toolkit which routine will
handle such cases, and the toolkit will call the procedures when required.

First requirements
==================

   Any perl program that uses Tk needs to include `use Tk'.  A program
should also use `use strict' and the -w switch to ensure the program is
working without common errors.

   Any Tk application starts by creating the Tk main window.  You then
create items inside the main window, or create new windows, before
starting the mainloop.  (You can also create more items and windows while
you're running.)  The items will be shown on the display after you pack
them; more info on this later.  Then you do a Tk mainloop; this will start
the GUI and handle all events.  That's your application.  A trivial
one-window example is show below:

     #! /usr/bin/perl5 -w

     use strict;
     use Tk;

     my $main = MainWindow->new;
     $main->Label(-text => 'Hello, world!')->pack;
     $main->Button(-text => 'Quit',
                   -command => [$main => 'destroy']
                   )->pack;
     MainLoop;

   Please run this example.  It shows you two items types also shown in the
widget demo; it also shows you how items are created and packed.  Finally,
note the typical Tk style using `-option' => value pairs.

Item creation
=============

   Tk windows and widgets are hierarchical, i.e. one includes one or more
others.  You create the first Tk window using `MainWindow->new'.  This
returns a window handle, assigned to `$main' in the example above.  Keep
track of the main handle.

   You can use any Tk handle to create sub-items within the window or
widget.  This is done by calling the Tk constructor method on the variable.
In the example above, the Label method called from `$main' creates a label
widget inside the main window.  In the constructor call, you can specify
various options; you can later add or change options for any widget using
the configure method, which takes the same parameters as the constructor.
The one exception to the hierarchical structure is the Toplevel
constructor, which creates a new outermost window.

   After you create any widget, you must render it by calling pack.  (This
is not entirely true; more info later).  If you do not need to refer to
the widget after construction and packing, call pack off the constructor
results, as shown for the label and button in the example above.  Note
that the result of the compound call is the result of pack, which is a
valid Tk handle.

   Windows and widgets are deleted by calling destroy on them; this will
delete and un-draw the widget and all its children.

Standard Tk types
=================

Button
Radiobutton
Checkbutton
Listbox
Scrollbar
Entry
Text
Canvas
Frame
Toplevel
Scale
Menu
Menubutton
Variables and callback routines
===============================

   Most graphical interfaces are used to set up a set of values and
conditions, and then perform the appropriate action.  The Tk toolkit is
different from your average text-based prompting or menu driven system in
that you do not collect settings yourself, and decide on an action based
on an input code; instead, you leave these values to your toolkit and only
get them when the action is performed.

   So, where a traditional text-based system would look like this: (yes,
this is obviously dumb code)

     #! /usr/bin/perl5 -w

     use strict;

     print "Please type a font name\n";
     my $font = <>; chomp $font;
     # Validate font

     print "Please type a file name\n";
     my $filename = <>; chomp $filename;
     # Validate filename

     print "Type <1> to fax, <2> to print\n";
     my $option = <>; chomp $option;
     if ($option eq 1) {
         print "Faxing $filename in font $font\n";
     } elsif ($option eq 2) {
         print "Now sending $filename to printer in font $font\n";
     }

   The (slightly larger) example below shows how to do this is Tk.  Note
the use of callbacks.  Note, also, that Tk handles the values, and the
subroutine uses get to get at the values.  If a user changes his mind and
wants to change the font again, the application never notices; it's all
handled by Tk.

     #! /usr/bin/perl5 -w

     use strict;
     use Tk;

     my $main = MainWindow->new;
     $main->Label(-text => 'Print file')->pack;
     my $font = $main->Entry(-width => 10);
     $font->pack;
     my $filename = $main->Entry(-width => 10);
     $filename->pack;
     $main->Button(-text => 'Fax',
                   -command => sub{do_fax($filename, $font)}
                   )->pack;
     $main->Button(-text => 'Print',
                   -command => sub{do_print($filename, $font)}
                   )->pack;
     MainLoop;

     sub do_fax {
         my ($file, $font) = @_;
         my $file_val = $file->get;
         my $font_val = $font->get;
         print "Now faxing $file_val in $font_val\n";
     }

     sub do_print {
         my ($file, $font) = @_;
         my $file_val = $file->get;
         my $font_val = $font->get;
         print "Sending file $file_val to printer in $font_val\n";
     }

The packer.  Grouping and frames.
=================================

   In the examples above, you must have noticed the `pack|Tk::pack' in
this node calls.  This is one of the more complicated parts of Tk.  The
basic idea is that any window or widget should be subject to a Tk widget
placement manager; the *packer* is one of the placement managers.

   The actions of the packer are rather simple: when applied to a widget,
the packer positions that widget on the indicated position within the
remaining space in its parent.  By default, the position is on top; this
means the next items will be put below.  You can also specify the left,
right, or bottom positions.  Specify position using *-side => 'right'*.

   Additional packing parameters specify the behavior of the widget when
there is some space left in the frame or when the window size is
increased.  If widgets should maintain a fixed size, specify nothing; this
is the default.  For widgets that you want to fill up the current
horizontal space, specify *-fill => 'x'*, y, or both; for widgets that
should grow, specify *-expand => 1*.  These parameters are not shown in
the example below; see the widget demo.

   If you want to group some items within a window that have a different
packing order than others, you can include them in a Frame.  This is a
do-nothing window type that is meant for packing (and to play games with
borders and colors).

   The example below shows the use of pack and frames:

     #! /usr/bin/perl5 -w

     use strict;
     use Tk;

     # Take top, the bottom -> now implicit top is in the middle
     my $main = MainWindow->new;
     $main->Label(-text => 'At the top (default)')->pack;
     $main->Label(-text => 'At the bottom')->pack(-side => 'bottom');
     $main->Label(-text => 'The middle remains')->pack;

     # Since left and right are taken, bottom will not work...
     my $top1 = $main->Toplevel;
     $top1->Label(-text => 'Left')->pack(-side => 'left');
     $top1->Label(-text => 'Right')->pack(-side => 'right');
     $top1->Label(-text => '?Bottom?')->pack(-side => 'bottom');

     # But when you use frames, things work quite alright
     my $top2 = $main->Toplevel;
     my $frame = $top2->Frame;
     $frame->pack;
     $frame->Label(-text => 'Left2')->pack(-side => 'left');
     $frame->Label(-text => 'Right2')->pack(-side => 'right');
     $top2->Label(-text => 'Bottom2')->pack(-side => 'bottom');

     MainLoop;

More than one window
====================

   Most real applications require more than one window.  As you read
before, you can create more outermost windows by using Toplevel.  Each
window is independent; destroying a toplevel window does not affect the
others as long as they are not a child of the closed toplevel.  Exiting
the main window will end the application.  The example below shows a
trivial three-window application:

     #! /usr/bin/perl5 -w

     use strict;
     use Tk;

     my $main = MainWindow->new;
     fill_window($main, 'Main');
     my $top1 = $main->Toplevel;
     fill_window($top1, 'First top-level');
     my $top2 = $main->Toplevel;
     fill_window($top2, 'Second top-level');
     MainLoop;

     sub fill_window {
         my ($window, $header) = @_;
         $window->Label(-text => $header)->pack;
         $window->Button(-text => 'close',
                         -command => [$window => 'destroy']
                         )->pack(-side => 'left');
         $window->Button(-text => 'exit',
                         -command => [$main => 'destroy']
                         )->pack(-side => 'right');
     }

More callbacks
==============

   So far, all callback routines shown called a user procedure.  You can
also have a callback routine call another Tk routine.  This is the way
that scroll bars are implemented: scroll-bars can call a Tk item or a user
procedure, whenever their position has changed.  The Tk item that has a
scrollbar attached calls the scrollbar when its size or offset has
changed.  In this way, the items are linked.  You can still ask a
scrollbar's position, or set it by hand - but the defaults will be taken
care of.

   The example below shows a listbox with a scroll bar.  Moving the
scrollbar moves the listbox.  Scanning a listbox (dragging an item with
the left mouse button) moves the scrollbar.

     #! /usr/bin/perl5 -w

     use strict;
     use Tk;

     my $main = MainWindow->new;
     my $box = $main->Listbox(-relief => 'sunken',
                              -width => -1, # Shrink to fit
                              -height => 5,
                              -setgrid => 1);
     my @items = qw(One Two Three Four Five Six Seven
                    Eight Nine Ten Eleven Twelve);
     foreach (@items) {
        $box->insert('end', $_);
     }
     my $scroll = $main->Scrollbar(-command => ['yview', $box]);
     $box->configure(-yscrollcommand => ['set', $scroll]);
     $box->pack(-side => 'left', -fill => 'both', -expand => 1);
     $scroll->pack(-side => 'right', -fill => 'y');

     MainLoop;

Canvases and tags
=================

   One of the most powerful window types in Tk is the Canvas window.  In a
canvas window, you can draw simple graphics and include other widgets.
The canvas area may be larger than the visible window, and may then be
scrolled.  Any item you draw on the canvas has its own id, and may
optionally have one or more tags.  You may refer to any item by its id,
and may refer to any group of items by a common tag; you can move, delete,
or change groups of items using these tags, and you can bind actions to
tags.  For a properly designed (often structured) canvas, you can specify
powerful actions quite simply.

   In the example below, actions are bound to circles (single click) and
blue items (double-click); obviously, this can be extended to any tag or
group of tags.

     #! /usr/bin/perl5 -w

     use strict;
     use Tk;

     # Create main window and canvas
     my $main = MainWindow->new;
     my $canvas = $main->Canvas;
     $canvas->pack(-expand => 1, -fill => 'both');

     # Create various items
     create_item($canvas, 1, 1, 'circle', 'blue', 'Jane');
     create_item($canvas, 4, 4, 'circle', 'red', 'Peter');
     create_item($canvas, 4, 1, 'square', 'blue', 'James');
     create_item($canvas, 1, 4, 'square', 'red', 'Patricia');

     # Single-clicking with left on a 'circle' item invokes a procedure
     $canvas->bind('circle', '<1>' => sub {handle_circle($canvas)});
     # Double-clicking with left on a 'blue' item invokes a procedure
     $canvas->bind('blue', '<Double-1>' => sub {handle_blue($canvas)});
     MainLoop;

     # Create an item; use parameters as tags (this is not a default!)
     sub create_item {
         my ($can, $x, $y, $form, $color, $name) = @_;

     my $x2 = $x + 1;
     my $y2 = $y + 1;
     my $kind;
     $kind = 'oval' if ($form eq 'circle');
     $kind = 'rectangle' if ($form eq 'square');
     $can->create(($kind, "$x" . 'c', "$y" . 'c',
                   "$x2" . 'c', "$y2" . 'c'),
                  -tags => [$form, $color, $name],
                  -fill => $color);
             }

     # This gets the real name (not current, blue/red, square/circle)
     # Note: you'll want to return a list in realistic situations...
     sub get_name {
         my ($can) = @_;
         my $item = $can->find('withtag', 'current');
         my @taglist = $can->gettags($item);
         my $name;
         foreach (@taglist) {
             next if ($_ eq 'current');
             next if ($_ eq 'red' or $_ eq 'blue');
             next if ($_ eq 'square' or $_ eq 'circle');
             $name = $_;
             last;
         }
         return $name;
     }

     sub handle_circle {
         my ($can) = @_;
         my $name = get_name($can);
         print "Action on circle $name...\n";
     }

     sub handle_blue {
         my ($can) = @_;
         my $name = get_name($can);
         print "Action on blue item $name...\n";
     }

An Object Oriented Wait Dialog for Perl/Tk, of the Please Wait variety.
***********************************************************************

NAME
====

   Tk::WaitBox - An Object Oriented Wait Dialog for Perl/Tk, of the Please
Wait variety.

DESCRIPTION
===========

   A WaitBox consists of a number of subwidgets:

bitmap
------

   A bitmap (configurable via the *-bitmap* command, the default is an
hourglass) on the left side of the WaitBox

label
-----

   A label (configurable via the *-txt1* command), with text in the upper
portion of the right hand frame

secondary label
---------------

   Another label (configurable via the *-txt2* command, the default is
'Please Wait'), with text in the lower portion of the right hand frame

userframe
---------

   A frame displayed, if required, between the label and the secondary
label.  For details, see the example code and the Advertised Widget section

cancel button
-------------

   If a cancelroutine (configured via the *-cancelroutine* command) is
defined, a frame will be packed below the labels and bitmap, with a single
button.  The text of the button will be 'Cancel' (configurable via the
*-canceltext* command), and the button will call the supplied subroutine
when pressed.

SYNOPSIS
========

Usage Description

Basic Usage
-----------

   To use, create your WaitDialog objects during initialization, or at
least before a Show.  When you wish to display the WaitDialog object,
invoke the 'Show' method on the WaitDialog object; when you wish to cease
displaying the WaitDialog object, invoke the 'unShow' method on the object.

Configuration
-------------

   Configuration may be done at creation or via the configure method.

Example Code
------------

          #!/usr/local/bin/perl -w

          use Tk;
          use Tk::WaitBox;
          use strict;

          my($root) = MainWindow->new;
          my($utxt) = "Initializing...";

          my($wd) = $root->WaitBox(
          	-bitmap =>'questhead', # Default would be 'hourglass'
          	-txt2 => 'tick-tick-tick', #default would be 'Please Wait'
          	-title => 'Takes forever to get service around here',
          	-cancelroutine => sub {
          	    print "\nI'm canceling....\n";
          	    $wd->unShow;
          	    $utxt = undef;
          	});
          $wd->configure(-txt1 => "Hurry up and Wait, my Drill Sergeant told me");
          $wd->configure(-foreground => 'blue',-background => 'white');

          ### Do something quite boring with the user frame
          my($u) = $wd->{SubWidget}(uframe);
          $u->pack(-expand => 1, -fill => 'both');
          $u->Label(-textvariable => \$utxt)->pack(-expand => 1, -fill => 'both');

          ## It would definitely be better to do this with a canvas... this is dumb
          my($base) = $u->Frame(-background =>'gray',
          		       -relief => 'sunken',
          		       -borderwidth => 2,
          		       -height => 20)
          	 ->pack(-side => 'left', -anchor => 'w',-expand => 1,
          		-fill => 'both');
          my($bar) = $base->Frame(-borderwidth => 2,
          			 -relief => 'raised', -height => 20,
          			 -width => 0, -background => 'blue')
          	 ->pack(-fill => 'y', -side => 'left');

          $wd->configure(-canceltext => 'Halt, Cease, Desist'); # default is 'Cancel'

          $wd->Show;

          for (1..15) {
              sleep(1);
              $bar->configure(-width => int($_/15*$base->Width));
              $utxt = 100*$_/15 . "% Complete";
              $root->update;
              last if !defined($utxt);
          }

          $wd->unShow;

Advertised Subwidgets
=====================

uframe
     uframe is a frame created between the two messages.  It may be used
     for anything the user has in mind... including exciting cycle wasting
     displays of sand dropping through an hour glass, Zippy riding either
     a Gnu or a bronc, et cetera.

     Assuming that the WaitBox is referenced by $w, the uframe may be
     addressed as $w->subwidget{'uframe'}.  Having gotten the address, you
     can do anything (I think) you would like with it

Author
======

   *Brent B. Powers, Merrill Lynch (B2Pi)*  powers@ml.com

   This code may be distributed under the same conditions as perl itself.

Base class of all widgets
*************************

NAME
====

   Tk::Widget - Base class of all widgets

SYNOPSIS
========

     package Tk::Whatever;
     require Tk::Widget;
     @ISA = qw(Tk::Widget);
     Construct Tk::Widget 'Whatever';

     sub Tk_cmd { \&Tk::whatever }

      $widget->method(?*arg, arg, ...*?)

DESCRIPTION
===========

   The *Tk::Widget* is an abstract base class for all Tk widgets.

   Generic methods available to all widgets include the methods based on
core `winfo' mechanism and are used to retrieve information about windows
managed by Tk. They can take any of a number of different forms, depending
on the method.  The legal forms are:

$widget->*appname*?(*newName*)?
     If *newName* isn't specified, this method returns the name of the
     application (the name that may be used in send commands to
     communicate with the application).  If *newName* is specified, then
     the name of the application is changed to *newName*.  If the given
     name is already in use, then a suffix of the form "* #2*" or "* #3*"
     is appended in order to make the name unique.  The method's result is
     the name actually chosen.  *newName* should not start with a capital
     letter.  This will interfere with `option|Tk::option' in this node
     processing, since names starting with capitals are assumed to be
     classes;  as a result, Tk may not be able to find some options for
     the application.  If sends have been disabled by deleting the send
     command, this command will reenable them and recreate the send
     command.

$widget->atom(name)
     Returns a decimal string giving the integer identifier for the atom
     whose name is name.  If no atom exists with the name name then a new
     one is created.

$widget->*atomname*(id)
     Returns the textual name for the atom whose integer identifier is id.
     This command is the inverse of the $widget->atom command.  It
     generates an error if no such atom exists.

$widget->*bell*
     This command rings the bell on the display for $widget and returns an
     empty string.  The command uses the current bell-related settings for
     the display, which may be modified with programs such as *xset*.

     This command also resets the screen saver for the screen.  Some
     screen savers will ignore this, but others will reset so that the
     screen becomes visible again.

$widget->*Busy*?(?-recurse => 1?*-option =* value>?)?
     This method configures a *-cursor* option for $widget and (if
     *-recurse =* 1> is specified) all its descendants. The cursor to be
     set may be passed as *-cursor* = cursor> or defaults to 'watch'.
     Additional configure options are applied to $widget only.  It also
     adds a special tag *'Busy'* to the *bindtags* of the widgets so
     configured so that  *KeyPress*, *KeyRelease*, *ButtonPress* and
     ButtonRelease events are ignored (with press events generating a call
     to *bell*). It then acquires a local *grab* for $widget.  The state
     of the widgets and the grab is restored by a call to
     $widget->*Unbusy*.

$widget->*cells*
     Returns a decimal string giving the number of cells in the color map
     for $widget.

$widget->children
     *$widget-*>children Returns a list containing all the children of
     $widget.  The list is in stacking order, with the lowest window
     first.  Top-level windows are returned as children of their logical
     parents.

$widget->class
     Returns the class name for $widget.

$widget->*colormapfull*
     Returns 1 if the colormap for $widget is known to be full, 0
     otherwise.  The colormap for a window is "known" to be full if the
     last attempt to allocate a new color on that window failed and this
     application hasn't freed any colors in the colormap since the failed
     allocation.

$widget->*containing*(*rootX,rootY*)
     Returns the window containing the point given by *rootX* and *rootY*.
     *RootX* and *rootY* are specified in screen units (i.e.  any form
     acceptable to *Tk_GetPixels*) in the coordinate system of the root
     window (if a virtual-root window manager is in use then the
     coordinate system of the virtual root window is used).  If no window
     in this application contains the point then an empty string is
     returned.  In selecting the containing window, children are given
     higher priority than parents and among siblings the highest one in
     the stacking order is chosen.

$widget->depth
     Returns a decimal string giving the depth of $widget (number of bits
     per pixel).

$widget->destroy
     This command deletes the window related to $widget, plus all its
     descendants.  If all the *MainWindows* are deleted then the entire
     application will be destroyed.

     The perl object $widget continues to exist while references to it
     still exist, e.g. until variable goes out of scope.  However any
     attempt to use Tk methods on the object will fail.  Exists($widget)
     will return false on such objects.

     Note however that while a window exists for $widget the perl object
     is maintained (due to "references" in perl/Tk internals) even though
     original variables may have gone out of scope.  (Normally this is
     intuitive.)

Exists($widget)
     Returns 1 if there exists a window for $widget, 0 if no such window
     exists.

$widget->font(option?, *arg, arg, ...*?)
     Create and inspect fonts. See Tk/Font, for further
     details.

$widget->*fpixels*(number)
     Returns a floating-point value giving the number of pixels in $widget
     corresponding to the distance given by number.  Number may be
     specified in any of the forms acceptable to *Tk_GetScreenMM*, such as
     "2.0c" or "1i".  The return value may be fractional;  for an integer
     value, use $widget->*pixels*.

$widget->*Getimage*(name)
     Given name, look for an image file with that base name and return a
     Tk/Image.  File extensions are tried in this order:
     `xpm', gif, `ppm', `xbm' until a valid iamge is found.  If no image is
     found, try a builtin image with that name.

$widget->*geometry*
     Returns the geometry for $widget, in the form widthxheight+x+y.  All
     dimensions are in pixels.

$widget->height
     Returns a decimal string giving $widget's height in pixels.  When a
     window is first created its height will be 1 pixel;  the height will
     eventually be changed by a geometry manager to fulfill the window's
     needs.  If you need the true height immediately after creating a
     widget, invoke update to force the geometry manager to arrange it, or
     use $widget->*reqheight* to get the window's requested height instead
     of its actual height.

$widget->id
     Returns a hexadecimal string giving a low-level platform-specific
     identifier for $widget.  On Unix platforms, this is the X window
     identifier.  Under Windows, this is the Windows HWND.  On the
     Macintosh the value has no meaning outside Tk.

$widget->*idletasks*
     One of two methods which are used to bring the application "up to
     date" by entering the event loop repeated until all pending events
     (including idle callbacks) have been processed.

     If the *idletasks* method is specified, then no new events or errors
     are processed; only idle callbacks are invoked. This causes operations
     that are normally deferred, such as display updates and window layout
     calculations, to be performed immediately.

     The *idletasks* command is useful in scripts where changes have been
     made to the application's state and you want those changes to appear
     on the display immediately, rather than waiting for the script to
     complete. Most display updates are performed as idle callbacks, so
     *idletasks* will cause them to run. However, there are some kinds of
     updates that only happen in response to events, such as those
     triggered by window size changes; these updates will not occur in
     *idletasks*.

$widget->*interps*
     Returns a list whose members are the names of all Tcl interpreters
     (e.g. all Tk-based applications) currently registered for a
     particular display.  The return value refers to the display of
     $widget.

$widget->*ismapped*
     Returns 1 if $widget is currently mapped, 0 otherwise.

*$widget-*>*lower*(?*belowThis*?)
     If the *belowThis* argument is omitted then the command lowers
     $widget so that it is below all of its siblings in the stacking order
     (it will be obscured by any siblings that overlap it and will not
     obscure any siblings).  If *belowThis* is specified then it must be
     the path name of a window that is either a sibling of $widget or the
     descendant of a sibling of $widget.  In this case the *lower* command
     will insert $widget into the stacking order just below *belowThis*
     (or the ancestor of *belowThis* that is a sibling of $widget); this
     could end up either raising or lowering $widget.

$widget->*MapWindow*
     Cause $widget to be "mapped" i.e. made visible on the display.  May
     confuse the geometry manager (pack, grid, place, ...)  that thinks it
     is managing the widget.

$widget->manager
     Returns the name of the geometry manager currently responsible for
     $widget, or an empty string if $widget isn't managed by any geometry
     manager.  The name is usually the name of the method for the geometry
     manager, such as pack or *place*.  If the geometry manager is a
     widget, such as canvases or text, the name is the widget's class
     command, such as canvas.

$widget->name
     Returns $widget's name (i.e. its name within its parent, as opposed
     to its full path name).  The command *$mainwin*->name will return the
     name of the application.

$widget->OnDestroy(callback);
     OnDestroy accepts a standard perl/Tk callback.  When the window
     associated with $widget is destroyed then the callback is invoked.
     Unlike *$widget-*>bind('<Destroy>',...)  the widgets methods are
     still available when callback is executed, so (for example) a Text
     widget can save its contents to a file.

     OnDestroy was required for new after mechanism.

$widget->parent
     Returns $widget's parent, or an empty string if $widget is the main
     window of the application.

$widget->*PathName*
     Returns the tk path name of $widget. (This is an import from the C
     interface.)

$widget->*pathname*(id)
     Returns an object whose X identifier is id.  The identifier is looked
     up on the display of $widget.  Id must be a decimal, hexadecimal, or
     octal integer and must correspond to a window in the invoking
     application, or an error occurs which can be trapped with `eval { }'
     or `Tk::catch { }'.  If the window belongs to the application, but is
     not an object (for example wrapper windows, HList header, etc.) then
     undef is returned.

$widget->*pixels*(number)
     Returns the number of pixels in $widget corresponding to the distance
     given by number.  Number may be specified in any of the forms
     acceptable to *Tk_GetPixels*, such as "2.0c" or "1i".  The result is
     rounded to the nearest integer value;  for a fractional result, use
     $widget->*fpixels*.

$widget->*pointerx*
     If the mouse pointer is on the same screen as $widget, returns the
     pointer's x coordinate, measured in pixels in the screen's root
     window.  If a virtual root window is in use on the screen, the
     position is measured in the virtual root.  If the mouse pointer isn't
     on the same screen as $widget then -1 is returned.

$widget->*pointerxy*
     If the mouse pointer is on the same screen as $widget, returns a list
     with two elements, which are the pointer's x and y coordinates
     measured in pixels in the screen's root window.  If a virtual root
     window is in use on the screen, the position is computed in the
     virtual root.  If the mouse pointer isn't on the same screen as
     $widget then both of the returned coordinates are -1.

$widget->*pointery*
     If the mouse pointer is on the same screen as $widget, returns the
     pointer's y coordinate, measured in pixels in the screen's root
     window.  If a virtual root window is in use on the screen, the
     position is computed in the virtual root.  If the mouse pointer isn't
     on the same screen as $widget then -1 is returned.

$widget->raise(?*aboveThis*?)
     If the *aboveThis* argument is omitted then the command raises
     $widget so that it is above all of its siblings in the stacking order
     (it will not be obscured by any siblings and will obscure any
     siblings that overlap it).  If *aboveThis* is specified then it must
     be the path name of a window that is either a sibling of $widget or
     the descendant of a sibling of $widget.  In this case the raise
     command will insert $widget into the stacking order just above
     *aboveThis* (or the ancestor of *aboveThis* that is a sibling of
     $widget); this could end up either raising or lowering $widget.

$widget->*reqheight*
     Returns a decimal string giving $widget's requested height, in
     pixels.  This is the value used by $widget's geometry manager to
     compute its geometry.

$widget->*reqwidth*
     Returns a decimal string giving $widget's requested width, in pixels.
     This is the value used by $widget's geometry manager to compute its
     geometry.

$widget->*rgb*(color)
     Returns a list containing three decimal values, which are the red,
     green, and blue intensities that correspond to color in the window
     given by $widget.  Color may be specified in any of the forms
     acceptable for a color option.

$widget->*rootx*
     Returns a decimal string giving the x-coordinate, in the root window
     of the screen, of the upper-left corner of $widget's border (or
     $widget if it has no border).

$widget->*rooty*
     Returns a decimal string giving the y-coordinate, in the root window
     of the screen, of the upper-left corner of $widget's border (or
     $widget if it has no border).

scaling
$widget->scaling?(number)?
     Sets and queries the current scaling factor used by Tk to convert
     between physical units (for example, points, inches, or millimeters)
     and pixels.  The number argument is a floating point number that
     specifies the number of pixels per point on $widget's display. If the
     number argument is omitted, the current value of the scaling factor
     is returned.

     A "point" is a unit of measurement equal to 1/72 inch.  A scaling
     factor of 1.0 corresponds to 1 pixel per point, which is equivalent
     to a standard 72 dpi monitor.  A scaling factor of 1.25 would mean
     1.25 pixels per point, which is the setting for a 90 dpi monitor;
     setting the scaling factor to 1.25 on a 72 dpi monitor would cause
     everything in the application to be displayed 1.25 times as large as
     normal.  The initial value for the scaling factor is set when the
     application starts, based on properties of the installed monitor (as
     reported via the window system), but it can be changed at any time.
     Measurements made after the scaling factor is changed will use the
     new scaling factor, but it is undefined whether existing widgets will
     resize themselves dynamically to accomodate the new scaling factor.

$widget->*screen*
     Returns the name of the screen associated with $widget, in the form
     *displayName*.*screenIndex*.

$widget->*screencells*
     Returns a decimal string giving the number of cells in the default
     color map for $widget's screen.

$widget->*screendepth*
     Returns a decimal string giving the depth of the root window of
     $widget's screen (number of bits per pixel).

$widget->*screenheight*
     Returns a decimal string giving the height of $widget's screen, in
     pixels.

$widget->*screenmmheight*
     Returns a decimal string giving the height of $widget's screen, in
     millimeters.

$widget->*screenmmwidth*
     Returns a decimal string giving the width of $widget's screen, in
     millimeters.

$widget->*screenvisual*
     Returns one of the following strings to indicate the default visual
     class for $widget's screen: *directcolor*, *grayscale*,
     *pseudocolor*, *staticcolor*, *staticgray*, or *truecolor*.

$widget->*screenwidth*
     Returns a decimal string giving the width of $widget's screen, in
     pixels.

$widget->server
     Returns a string containing information about the server for
     $widget's display.  The exact format of this string may vary from
     platform to platform.  For X servers the string has the form
     "X*major*R*minor vendor vendorVersion*" where *major* and *minor* are
     the version and revision numbers provided by the server (e.g.,
     *X11R5*), *vendor* is the name of the vendor for the server, and
     *vendorRelease* is an integer release number provided by the server.

$widget->toplevel
     Returns the reference of the top-level window containing $widget.

$widget->*UnmapWindow*
     Cause $widget to be "unmapped" i.e. removed from the display.  This
     does for any widget what $widget->withdraw does for toplevel widgets.
     May confuse the geometry manager (pack, grid, place, ...)  that
     thinks it is managing the widget.

$widget->update
     One of two methods which are used to bring the application "up to
     date" by entering the event loop repeated until all pending events
     (including idle callbacks) have been processed.

     The update method is useful in scripts where you are performing a
     long-running computation but you still want the application to respond
     to events such as user interactions; if you occasionally call update
     then user input will be processed during the next call to update.

$widget->*Unbusy*
     Restores widget state after a call to  $widget->*Busy*.

$widget->*viewable*
     Returns 1 if $widget and all of its ancestors up through the nearest
     toplevel window are mapped.  Returns 0 if any of these windows are
     not mapped.

$widget->*visual*
     Returns one of the following strings to indicate the visual class for
     $widget: *directcolor*, *grayscale*, *pseudocolor*, *staticcolor*,
     *staticgray*, or *truecolor*.

$widget->*visualid*
     Returns the X identifier for the visual for $widget.

$widget->*visualsavailable*(?*includeids*?)
     Returns a list whose elements describe the visuals available for
     $widget's screen.  Each element consists of a visual class followed
     by an integer depth.  The class has the same form as returned by
     $widget->*visual*.  The depth gives the number of bits per pixel in
     the visual.  In addition, if the *includeids* argument is provided,
     then the depth is followed by the X identifier for the visual.

$widget->*vrootheight*
     Returns the height of the virtual root window associated with $widget
     if there is one;  otherwise returns the height of $widget's screen.

$widget->*vrootwidth*
     Returns the width of the virtual root window associated with $widget
     if there is one;  otherwise returns the width of $widget's screen.

$widget->*vrootx*
     Returns the x-offset of the virtual root window associated with
     $widget, relative to the root window of its screen.  This is normally
     either zero or negative.  Returns 0 if there is no virtual root
     window for $widget.

$widget->*vrooty*
     Returns the y-offset of the virtual root window associated with
     $widget, relative to the root window of its screen.  This is normally
     either zero or negative.  Returns 0 if there is no virtual root
     window for $widget.

*$widget-*>*waitVariable*(\$name)
*$widget-*>*waitVisibility*
*$widget-*>*waitWindow*
     The *tk wait* methods wait for one of several things to happen, then
     it returns without taking any other actions.  The return value is
     always an empty string.  *waitVariable* expects a reference to a perl
     variable and the command waits for that variable to be modified.
     This form is typically used to wait for a user to finish interacting
     with a dialog which sets the variable as part (possibly final) part
     of the interaction.  *waitVisibility* waits for a change in $widget's
     visibility state (as indicated by the arrival of a VisibilityNotify
     event).  This form is typically used to wait for a newly-created
     window to appear on the screen before taking some action.
     *waitWindow* waits for $widget to be destroyed.  This form is
     typically used to wait for a user to finish interacting with a dialog
     box before using the result of that interaction.  Note that creating
     and destroying the window each time a dialog is required makes code
     modular but imposes overhead which can be avoided by *withdrawing*
     the window instead and using *waitVisibility*.

     While the *tk wait* methods are waiting they processes events in the
     normal fashion, so the application will continue to respond to user
     interactions.  If an event handler invokes *tkwait* again, the nested
     call to *tkwait* must complete before the outer call can complete.

$widget->width
     Returns a decimal string giving $widget's width in pixels.  When a
     window is first created its width will be 1 pixel;  the width will
     eventually be changed by a geometry manager to fulfill the window's
     needs.  If you need the true width immediately after creating a
     widget, invoke update to force the geometry manager to arrange it, or
     use $widget->*reqwidth* to get the window's requested width instead
     of its actual width.

$widget->x
     Returns a decimal string giving the x-coordinate, in $widget's
     parent, of the upper-left corner of $widget's border (or $widget if
     it has no border).

$widget->y
     Returns a decimal string giving the y-coordinate, in $widget's
     parent, of the upper-left corner of $widget's border (or $widget if it
     has no border).

CAVEATS
=======

   The above documentaion on generic methods is incomplete.

KEYWORDS
========

   atom, children, class, geometry, height, identifier, information,
interpreters, mapped, parent, path name, screen, virtual root, width,
window

create a standard widget demonstration window.
**********************************************

NAME
====

   WidgetDemo() - create a standard widget demonstration window.

SYNOPSIS
========

     use WidgetDemo;
     my $TOP = $MW->WidgetDemo(
         -name             => $demo,
         -text             => 'Learn how to write a widget demonstration!',
         -title            => 'WidgetDemo Demonstration',
         -iconname         => 'WidgetDemo',
         -geometry_manager => 'grid',
         -font             => $FONT,
     );

DESCRIPTION
===========

   This constructor builds a standard widget demonstration window,
composed of three frames.  The top frame contains descriptive
demonstration text.  The bottom frame contains the "Dismiss" and "See
Code" buttons.  The middle frame is demonstration container, which came be
managed by either the pack or grid geometry manager.

   The -text attribute is supplied to a Label widget, which is
left-adjusted with -wraplength set to 4 inches.  If you require different
specifications then pass an array to -text; the first element is the text
string and the remaining array elements are standard Label widget
attributes - WidgetDemo will rearrange things as required..

     -text => ['Hello World!', qw/-wraplength 6i/],

AUTHOR
======

   Steve Lidie <Stephen.O.Lidie@Lehigh.EDU>

HISTORY
=======

   lusol@Lehigh.EDU, LUCC, 97/02/11 lusol@Lehigh.EDU, LUCC, 97/06/07
Stephen.O.Lidie@Lehigh.EDU, LUCC, 97/06/07  . Add Delegates() call that
obviates the need for Top().  Many thanks to    Achim Bohnet for this
patch.   . Fix -title so that it works.

COPYRIGHT
=========

   Copyright (C) 1997 - 1998 Stephen O. Lidie. All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Load a Photo image from a window
********************************

NAME
====

   Tk::WinPhoto - Load a Photo image from a window

     use Tk;
     use Tk::WinPhoto;

     my $image = $mw->Photo(-format => 'Window', -data => oct($mw->id));
     $image->write($path_name, -format => 'BMP|PPM|XPM');

DESCRIPTION
===========

   This is an extension for Tk800.* which will load a Photo image from a
snapshot of an X window specified by the -data option.

   The window must exist and be visible. Because the code allows you to
capture windows not owned by Tk it does not attempt to enforce this. If
you are capturing one of Tk's windows then use `$w->update'.

   If window is mapped, but obscured by other windows then what is
captured is the rectangle the window would occupy. This can be considered
a feature.  For Tk-owned windows `$w->raise' can used to bring window
forward.

   Once the Photo is loaded it can be saved using `$image->write(-format
=> ...)' using any of formats which support writing.

AUTHOR
======

   Nick Ing-Simmons <nick@ni-s.u-net.com>

Communicate with window manager
*******************************

NAME
====

   Tk::Wm - Communicate with window manager

       *$toplevel*->method(?args?)

DESCRIPTION
===========

   The *wm* methods are used to interact with window managers in order to
control such things as the title for a window, its geometry, or the
increments in terms of which it may be resized.  The *wm* methods can take
any of a number of different forms, depending on the particular method
argument.  All of the forms expect *$toplevel*, which must be a top-level
window object.

   The legal forms for the *wm* methods are:

*$toplevel*->*aspect*(?*minNumer minDenom maxNumer maxDenom*?)
     If *minNumer*, *minDenom*, *maxNumer*, and *maxDenom* are all
     specified, then they will be passed to the window manager and the
     window manager should use them to enforce a range of acceptable
     aspect ratios for *$toplevel*.  The aspect ratio of *$toplevel*
     (width/length) will be constrained to lie between
     *minNumer*/*minDenom* and *maxNumer*/*maxDenom*.  If *minNumer* etc.
     are all specified as empty strings, then any existing aspect ratio
     restrictions are removed.  If *minNumer* etc. are specified, then the
     method returns an empty string.  Otherwise, it returns a array
     containing four elements, which are the current values of *minNumer*,
     *minDenom*, *maxNumer*, and *maxDenom* (if no aspect restrictions are
     in effect, then an empty string is returned).

*$toplevel*->client(?name?)
     If name is specified, this method stores name (which should be the
     name of the host on which the application is executing) in
     *$toplevel*'s *WM_CLIENT_MACHINE* property for use by the window
     manager or session manager.  The method returns an empty string in
     this case.  If name isn't specified, the method returns the last name
     set in a client method for *$toplevel*.  If name is specified as an
     empty string, the method deletes the *WM_CLIENT_MACHINE* property
     from *$toplevel*.

*$toplevel*->*colormapwindows*(?*windowList*?)
     This method is used to manipulate the *WM_COLORMAP_WINDOWS* property,
     which provides information to the window managers about windows that
     have private colormaps.  If *windowList* isn't specified, the method
     returns a list whose elements are the names of the windows in the
     *WM_COLORMAP_WINDOWS* property.  If *windowList* is specified, it
     consists of a list of widgets; the method overwrites the
     *WM_COLORMAP_WINDOWS* property with the given windows and returns an
     empty string.  The *WM_COLORMAP_WINDOWS* property should normally
     contain a list of the internal windows within *$toplevel* whose
     colormaps differ from their parents.  The order of the windows in the
     property indicates a priority order: the window manager will attempt
     to install as many colormaps as possible from the head of this list
     when $widget gets the colormap focus.  If $widget is not included
     among the windows in *windowList*, Tk implicitly adds it at the end
     of the *WM_COLORMAP_WINDOWS* property, so that its colormap is lowest
     in priority.  If $widget->colormapwindows is not invoked, Tk will
     automatically set the property for each top-level window to all the
     internal windows whose colormaps differ from their parents, followed
     by the top-level itself;  the order of the internal windows is
     undefined.  See the ICCCM documentation for more information on the
     *WM_COLORMAP_WINDOWS* property.

*$toplevel*->command(?value?)
     If value is specified, this method stores value in *$toplevel*'s
     *WM_COMMAND* property for use by the window manager or session
     manager and returns an empty string.  Value must have proper list
     structure;  the elements should contain the words of the command used
     to invoke the application.  If value isn't specified then the method
     returns the last value set in a command method for *$toplevel*.  If
     value is specified as an empty string, the method deletes the
     *WM_COMMAND* property from *$toplevel*.

*$toplevel*->*deiconify*
     Arrange for *$toplevel* to be displayed in normal (non-iconified)
     form.  This is done by mapping the window.  If the window has never
     been mapped then this method will not map the window, but it will
     ensure that when the window is first mapped it will be displayed in
     de-iconified form.  Returns an empty string.

*$toplevel*->*focusmodel*(?active|*passive*?)
     If active or *passive* is supplied as an optional argument to the
     method, then it specifies the focus model for *$toplevel*.  In this
     case the method returns an empty string.  If no additional argument
     is supplied, then the method returns the current focus model for
     *$toplevel*.  An active focus model means that *$toplevel* will claim
     the input focus for itself or its descendants, even at times when the
     focus is currently in some other application.  Passive means that
     *$toplevel* will never claim the focus for itself:  the window manager
     should give the focus to *$toplevel* at appropriate times.  However,
     once the focus has been given to *$toplevel* or one of its
     descendants, the application may re-assign the focus among
     *$toplevel*'s descendants.  The focus model defaults to *passive*,
     and Tk's focus method assumes a passive model of focusing.

*$toplevel*->frame
     If $widget has been reparented by the window manager into a
     decorative frame, the method returns the platform specific window
     identifier for the outermost frame that contains *$toplevel* (the
     window whose parent is the root or virtual root).  If *$toplevel*
     hasn't been reparented by the window manager then the method returns
     the platform specific window identifier for *$toplevel*.

*$toplevel*->*geometry*(?*newGeometry*?)
     If *newGeometry* is specified, then the geometry of *$toplevel* is
     changed and an empty string is returned.  Otherwise the current
     geometry for *$toplevel* is returned (this is the most recent
     geometry specified either by manual resizing or in a *geometry*
     method).  *NewGeometry* has the form =widthxheight*+-*x*+-*y, where
     any of =, widthxheight, or *+-*x*+-*y may be omitted.  Width and
     height are positive integers specifying the desired dimensions of
     *$toplevel*.  If *$toplevel* is gridded (see `"GRIDDED GEOMETRY
     MANAGEMENT"' in this node below) then the dimensions are specified in
     grid units;  otherwise they are specified in pixel units.  X and y
     specify the desired location of *$toplevel* on the screen, in pixels.
     If x is preceded by +, it specifies the number of pixels between the
     left edge of the screen and the left edge of *$toplevel*'s border;
     if preceded by - then x specifies the number of pixels between the
     right edge of the screen and the right edge of *$toplevel*'s border.
     If y is preceded by + then it specifies the number of pixels between
     the top of the screen and the top of *$toplevel*'s border;  if y is
     preceded by - then it specifies the number of pixels between the
     bottom of *$toplevel*'s border and the bottom of the screen.  If
     *newGeometry* is specified as an empty string then any existing
     user-specified geometry for *$toplevel* is cancelled, and the window
     will revert to the size requested internally by its widgets.

*$toplevel*->*wmGrid*(?*baseWidth,baseHeight,widthInc,heightInc*?)
     This method indicates that *$toplevel* is to be managed as a gridded
     window.  It also specifies the relationship between grid units and
     pixel units.  *BaseWidth* and *baseHeight* specify the number of grid
     units corresponding to the pixel dimensions requested internally by
     *$toplevel* using *Tk_GeometryRequest*.  *WidthInc* and *heightInc*
     specify the number of pixels in each horizontal and vertical grid
     unit.  These four values determine a range of acceptable sizes for
     *$toplevel*, corresponding to grid-based widths and heights that are
     non-negative integers.  Tk will pass this information to the window
     manager;  during manual resizing, the window manager will restrict
     the window's size to one of these acceptable sizes.  Furthermore,
     during manual resizing the window manager will display the window's
     current size in terms of grid units rather than pixels.  If
     *baseWidth* etc. are all specified as empty strings, then *$toplevel*
     will no longer be managed as a gridded window.  If *baseWidth* etc.
     are specified then the return value is an empty string.  Otherwise
     the return value is a array containing four elements corresponding to
     the current *baseWidth*, *baseHeight*, *widthInc*, and *heightInc*;
     if *$toplevel* is not currently gridded, then an empty string is
     returned.  Note: this command should not be needed very often, since
     the *Tk_SetGrid* library procedure and the *-setgrid* option provide
     easier access to the same functionality.

*$toplevel*->group(?$widget?)
     If $widget is specified, it is the the leader of a group of related
     windows.  The window manager may use this information, for example,
     to unmap all of the windows in a group when the group's leader is
     iconified.  $widget may be specified as an empty string to remove
     *$toplevel* from any group association.  If $widget is specified then
     the method returns an empty string;  otherwise it returns the
     *$toplevel*'s current group leader, or an empty string if *$toplevel*
     isn't part of any group.

*$toplevel*->*iconbitmap*(?bitmap?)
     If bitmap is specified, then it names a bitmap in the standard forms
     accepted by Tk (see the *Tk_GetBitmap* documentation for details).
     This *black and white* bitmap is passed to the window manager to be
     displayed in *$toplevel*'s icon, and the method returns an empty
     string.  If an empty string is specified for bitmap, then any current
     icon bitmap or image is cancelled for *$toplevel*.  If bitmap is
     specified then the method returns an empty string.  Otherwise it
     returns the name of the current icon bitmap associated with
     *$toplevel*, or an empty string if *$toplevel* has no icon bitmap.

*$toplevel*->iconify
     Arrange for *$toplevel* to be iconified.  It *$toplevel* hasn't yet
     been mapped for the first time, this method will arrange for it to
     appear in the iconified state when it is eventually mapped.

*$toplevel*->*iconimage*(?image?)
     If image is specified, then it names a normal Tk image.  This image
     is rendered into a private *coloured* bitmap which is passed to the
     window manager to be displayed in *$toplevel*'s icon, and the method
     returns an empty string. If an empty string is specified for image,
     then any current icon bitmap or image is cancelled for *$toplevel*.
     If image is specified then the method returns an empty string.
     Otherwise it returns the name of the current icon image associated
     with *$toplevel*, or an empty string if *$toplevel* has no icon image.
     The private pixmap is not pre-cleared so images which are partly
     "transparent" display rubbish in their transparent parts.

     The sizes of images that can be used as icons in this manner are
     platform dependant. On Win32 this sets the "large" icon, which should
     be 32x32, it will automatically be scaled down to 16x16 for use as a
     small icon.

*$toplevel*->*iconmask*(?bitmap?)
     If bitmap is specified, then it names a bitmap in the standard forms
     accepted by Tk (see the *Tk_GetBitmap* documentation for details).
     This bitmap is passed to the window manager to be used as a mask in
     conjunction with the *iconbitmap* option:  where the mask has zeroes
     no icon will be displayed;  where it has ones, the bits from the icon
     bitmap will be displayed.  If an empty string is specified for bitmap
     then any current icon mask is cancelled for *$toplevel* (this is
     equivalent to specifying a bitmap of all ones).  If bitmap is
     specified then the method returns an empty string.  Otherwise it
     returns the name of the current icon mask associated with
     *$toplevel*, or an empty string if no mask is in effect.

*$toplevel*->*iconname*(?*newName*?)
     If *newName* is specified, then it is passed to the window manager;
     the window manager should display *newName* inside the icon
     associated with *$toplevel*.  In this case an empty string is
     returned as result.  If *newName* isn't specified then the method
     returns the current icon name for *$toplevel*, or an empty string if
     no icon name has been specified (in this case the window manager will
     normally display the window's title, as specified with the title
     method).

*$toplevel*->*iconposition*(?*x y*?)
     If x and y are specified, they are passed to the window manager as a
     hint about where to position the icon for *$toplevel*.  In this case
     an empty string is returned.  If x and y are specified as empty
     strings then any existing icon position hint is cancelled.  If
     neither x nor y is specified, then the method returns a array
     containing two values, which are the current icon position hints (if
     no hints are in effect then an empty string is returned).

*$toplevel*->*iconwindow*(?$widget?)
     If $widget is specified, it is a window to use as icon for
     *$toplevel*: when *$toplevel* is iconified then $widget will be
     mapped to serve as icon, and when *$toplevel* is de-iconified then
     $widget will be unmapped again.  If $widget is specified as an empty
     string then any existing icon window association for *$toplevel* will
     be cancelled.  If the $widget argument is specified then an empty
     string is returned.  Otherwise the method returns the current icon
     window for *$toplevel*, or an empty string if there is no icon window
     currently specified for *$toplevel*.  Button press events are
     disabled for *$toplevel* as long as it is an icon window;  this is
     needed in order to allow window managers to "own" those events.
     Note: not all window managers support the notion of an icon window.

*$toplevel*->*maxsize*(?*width,height*?)
     If width and height are specified, they give the maximum permissible
     dimensions for *$toplevel*.  For gridded windows the dimensions are
     specified in grid units;  otherwise they are specified in pixel units.
     The window manager will restrict the window's dimensions to be less
     than or equal to width and height.  If width and height are
     specified, then the method returns an empty string.  Otherwise it
     returns a array with two elements, which are the maximum width and
     height currently in effect.  The maximum size defaults to the size of
     the screen.  If resizing has been disabled with the *resizable*
     method, then this method has no effect.  See the sections on geometry
     management below for more information.

*$toplevel*->*minsize*(?*width,height*?)
     If width and height are specified, they give the minimum permissible
     dimensions for *$toplevel*.  For gridded windows the dimensions are
     specified in grid units;  otherwise they are specified in pixel units.
     The window manager will restrict the window's dimensions to be
     greater than or equal to width and height.  If width and height are
     specified, then the method returns an empty string.  Otherwise it
     returns a array with two elements, which are the minimum width and
     height currently in effect.  The minimum size defaults to one pixel
     in each dimension.  If resizing has been disabled with the
     *resizable* method, then this method has no effect.  See the sections
     on geometry management below for more information.

*$toplevel*->*overrideredirect(?*boolean?)
     If boolean is specified, it must have a proper boolean form and the
     override-redirect flag for *$toplevel* is set to that value.  If
     boolean is not specified then 1 or 0 is returned to indicate whether
     or not the override-redirect flag is currently set for *$toplevel*.
     Setting the override-redirect flag for a window causes it to be
     ignored by the window manager;  among other things, this means that
     the window will not be reparented from the root window into a
     decorative frame and the user will not be able to manipulate the
     window using the normal window manager mechanisms.

*$toplevel*->*positionfrom*(?who?)
     If who is specified, it must be either program or user, or an
     abbreviation of one of these two.  It indicates whether *$toplevel*'s
     current position was requested by the program or by the user.  Many
     window managers ignore program-requested initial positions and ask
     the user to manually position the window;  if user is specified then
     the window manager should position the window at the given place
     without asking the user for assistance.  If who is specified as an
     empty string, then the current position source is cancelled.  If who
     is specified, then the method returns an empty string.  Otherwise it
     returns user or $widget to indicate the source of the window's
     current position, or an empty string if no source has been specified
     yet.  Most window managers interpret "no source" as equivalent to
     program.  Tk will automatically set the position source to user when
     a *geometry* method is invoked, unless the source has been set
     explicitly to program.

*$toplevel*->protocol(?name?,?callback?)
     This method is used to manage window manager protocols such as
     *WM_DELETE_WINDOW*.  Name is the name of an atom corresponding to a
     window manager protocol, such as *WM_DELETE_WINDOW* or
     *WM_SAVE_YOURSELF* or *WM_TAKE_FOCUS*.  If both name and callback are
     specified, then callback is associated with the protocol specified by
     name.  Name will be added to *$toplevel*'s *WM_PROTOCOLS* property to
     tell the window manager that the application has a protocol handler
     for name, and callback will be invoked in the future whenever the
     window manager sends a message to the client for that protocol.  In
     this case the method returns an empty string.  If name is specified
     but callback isn't, then the current callback for name is returned,
     or an empty string if there is no handler defined for name.  If
     callback is specified as an empty string then the current handler for
     name is deleted and it is removed from the *WM_PROTOCOLS* property on
     *$toplevel*;  an empty string is returned.  Lastly, if neither name
     nor callback is specified, the method returns a list of all the
     protocols for which handlers are currently defined for *$toplevel*.

     Tk always defines a protocol handler for *WM_DELETE_WINDOW*, even if
     you haven't asked for one with protocol.  If a *WM_DELETE_WINDOW*
     message arrives when you haven't defined a handler, then Tk handles
     the message by destroying the window for which it was received.

*$toplevel*->*resizable*(?*width,height*?)
     This method controls whether or not the user may interactively resize
     a top-level window.  If width and height are specified, they are
     boolean values that determine whether the width and height of
     *$toplevel* may be modified by the user.  In this case the method
     returns an empty string.  If width and height are omitted then the
     method returns a list with two 0/1 elements that indicate whether the
     width and height of *$toplevel* are currently resizable.  By default,
     windows are resizable in both dimensions.  If resizing is disabled,
     then the window's size will be the size from the most recent
     interactive resize or *geometry* method.  If there has been no such
     operation then the window's natural size will be used.

*$toplevel*->*sizefrom*(?who?)
     If who is specified, it must be either program or user, or an
     abbreviation of one of these two.  It indicates whether *$toplevel*'s
     current size was requested by the program or by the user.  Some
     window managers ignore program-requested sizes and ask the user to
     manually size the window;  if user is specified then the window
     manager should give the window its specified size without asking the
     user for assistance.  If who is specified as an empty string, then
     the current size source is cancelled.  If who is specified, then the
     method returns an empty string.  Otherwise it returns user or $widget
     to indicate the source of the window's current size, or an empty
     string if no source has been specified yet.  Most window managers
     interpret "no source" as equivalent to program.

*$toplevel*->state
     Returns the current state of $widget:  either normal, *iconic*,
     *withdrawn*, or icon.  The difference between *iconic* and icon is
     that *iconic* refers to a window that has been iconified (e.g., with
     the iconify method) while icon refers to a window whose only purpose
     is to serve as the icon for some other window (via the *iconwindow*
     method).

*$toplevel*->title(?string?)
     If string is specified, then it will be passed to the window manager
     for use as the title for *$toplevel* (the window manager should
     display this string in *$toplevel*'s title bar).  In this case the
     method returns an empty string.  If string isn't specified then the
     method returns the current title for the *$toplevel*.  The title for
     a window defaults to its name.

*$toplevel*->*transient*(?master?)
     If master is specified, then the window manager is informed that
     *$toplevel* is a transient window (e.g. pull-down menu) working on
     behalf of master (where master is a top-level window).  Some window
     managers will use this information to manage *$toplevel* specially.
     If master is specified as an empty string then *$toplevel* is marked
     as not being a transient window any more.  If master is specified,
     then the method returns an empty string.  Otherwise the method
     returns the path name of *$toplevel*'s current master, or an empty
     string if *$toplevel* isn't currently a transient window.

*$toplevel*->*withdraw*
     Arranges for *$toplevel* to be withdrawn from the screen.  This
     causes the window to be unmapped and forgotten about by the window
     manager.  If the window has never been mapped, then this method
     causes the window to be mapped in the withdrawn state.  Not all
     window managers appear to know how to handle windows that are mapped
     in the withdrawn state.  Note: it sometimes seems to be necessary to
     withdraw a window and then re-map it (e.g. with *deiconify*) to get
     some window managers to pay attention to changes in window attributes
     such as group.

*$toplevel*->*wrapper*
     Returns the window id of the wrapper window in which Tk has placed
     *$toplevel*. This is the id by which window manager will know
     *$toplevel*, and so is appropriate place to add X properties.

ICON SIZES
==========

   The sizes of bitmaps/images that can be used as icons in this manner
are platform and window manager dependant. Unix window managers are
typically more tolerant than Win32. It is possible that coloured
`iconimage' icons may cause problems on some X window managers.

   * Win32

     `iconimage' and `iconbitmap' set the "large" icon, which should be
     32x32, it will automatically be scaled down to 16x16 for use as a
     small icon.  Win32 ignores `iconwin' requests.

   * KDE's "kwm"                   Accepts coloured `iconimage' and black
     and white `iconbitmap' but  will scale either to a small (14x14?)
     icon. Kwm ignores `iconwin'.

   * Sun's "olwm" or "olvwm"

     Honours `iconwin' which will override `iconimage' or `iconbitmap'.
     Coloured images work.

   * Sun's CDE window manager

     Coloured images work. ...

GEOMETRY MANAGEMENT
===================

   By default a top-level window appears on the screen in its *natural
size*, which is the one determined internally by its widgets and geometry
managers.  If the natural size of a top-level window changes, then the
window's size changes to match.  A top-level window can be given a size
other than its natural size in two ways.  First, the user can resize the
window manually using the facilities of the window manager, such as resize
handles.  Second, the application can request a particular size for a
top-level window using the *geometry* method.  These two cases are handled
identically by Tk;  in either case, the requested size overrides the
natural size.  You can return the window to its natural by invoking
*geometry* with an empty *geometry* string.

   Normally a top-level window can have any size from one pixel in each
dimension up to the size of its screen.  However, you can use the
*minsize* and *maxsize* methods to limit the range of allowable sizes.
The range set by *minsize* and *maxsize* applies to all forms of resizing,
including the window's natural size as well as manual resizes and the
*geometry* method.  You can also use the method *resizable* to completely
disable interactive resizing in one or both dimensions.

GRIDDED GEOMETRY MANAGEMENT
===========================

   Gridded geometry management occurs when one of the widgets of an
application supports a range of useful sizes.  This occurs, for example,
in a text editor where the scrollbars, menus, and other adornments are
fixed in size but the edit widget can support any number of lines of text
or characters per line.  In this case, it is usually desirable to let the
user specify the number of lines or characters-per-line, either with the
*geometry* method or by interactively resizing the window.  In the case of
text, and in other interesting cases also, only discrete sizes of the
window make sense, such as integral numbers of lines and
characters-per-line;  arbitrary pixel sizes are not useful.

   Gridded geometry management provides support for this kind of
application.  Tk (and the window manager) assume that there is a grid of
some sort within the application and that the application should be
resized in terms of *grid units* rather than pixels.  Gridded geometry
management is typically invoked by turning on the *setGrid* option for a
widget;  it can also be invoked with the *wmGrid* method or by calling
*Tk_SetGrid*.  In each of these approaches the particular widget (or
sometimes code in the application as a whole) specifies the relationship
between integral grid sizes for the window and pixel sizes.  To return to
non-gridded geometry management, invoke grid with empty argument strings.

   When gridded geometry management is enabled then all the dimensions
specified in *minsize*, *maxsize*, and *geometry* methods are treated as
grid units rather than pixel units.  Interactive resizing is also carried
out in even numbers of grid units rather than pixels.

BUGS
====

   Most existing window managers appear to have bugs that affect the
operation of the *wm* methods.  For example, some changes won't take
effect if the window is already active:  the window will have to be
withdrawn and de-iconified in order to make the change happen.

SEE ALSO
========

   `Tk::Widget|Tk::Widget' in this node `Tk::tixWm|Tk::tixWm' in this node
`Tk::Mwm|Tk::Mwm' in this node

KEYWORDS
========

   aspect ratio, deiconify, focus model, geometry, grid, group, icon,
iconify, increments, position, size, title, top-level window, units,
window manager

Persistent, multi-purpose text processor.   (File browser, shell, editor) script.   Requires Perl/Tk; optionally Net::FTP.
**************************************************************************************************************************

NAME
====

     Workspace.pm--Persistent, multi-purpose text processor.
     (File browser, shell, editor) script.
     Requires Perl/Tk; optionally Net::FTP.

SYNOPSIS
========

     # Create a workspace from the shell prompt:

     mkws "workspace"

     # Open an existing workspace from the shell prompt:

     workspace [-background | -bg <color>] [-textbackground <color>]
               [-foreground | -fg <color>] [-textforeground <color>]
               [-font | -fn <fontdesc>] [-importfile <filename>]
               [-exportfile <filename>] [-dump] [-xrm <pattern>]
               [-class <Classname>] [-display | -screen <dpyname>]
               [-title <workspacename>] [-help] [-iconic]
               [-motif] [-synchronous] [-write] [-quit]

     # Open from a Perl script:

     use Tk;
     use Tk::Workspace;

     Tk::Workspace::open(Tk::Workspace::create("workspace"));

     # Create workspace object within a Perl script:

     $w = Tk::Workspace -> new( x => 100,
                                y => 100,
                                width => 300,
                                height => 250,
     				 textfont => "*-courier-medium-r-*-*-12-*",
                                foreground => 'white',
                                background => 'black',
                                menuvisible => 'true',
                                scroll => 'se',
                                insert => '1.0',
                                menubarvisible => 'True',
                                text => 'Text to be inserted',
                                name => 'workspace' );

DESCRIPTION
===========

   Workspace uses the Tk::TextUndo widget to create an embedded Perl text
editor.  The resulting file can be run as a standalone program.

OPTIONS
=======

   In normal use, common X toolkit options apply to non-text areas, like
the window border and menus. Text resources can also be specified, but
they often have a lower priority than the Workspace's saved values and
user selections.  Refer to the section: X RESOURCES, below.

   Command line options are described more fully in the Tk::CmdLine manual
page.

X Toolkit Options
-----------------

-foreground | -fg <color>
     Foreground color of widgets.  -fg is a synonym for -foreground.

-background | -bg <color>
     Background color of widgets.  -bg is a synonym for -background.

-class <classname>
     Name of X Window resource class.  In normal use, this is overriden by
     the Workspace name.

-display | -screen <displayname>
     Name of X display.  -screen is a synonym for -display.

-font | -fn <fontname>
     Font descriptor for widgets.  -fn is a synonym for -font.

-iconic
     Start with the window iconfied.

-motif
     Adhere as closely as possible to Motif look-and-feel standards.

-name <resourcename>
     Specifies the name under which X resources can be found.  Refer to
     the section: X RESOURCES, below.

-synchronous
     Requests should be sent to the X server synchronously.  Mainly useful
     for debugging.

-title <windowtitle>
     Title of the window.  This is overridden by the Workspace.

-xrm <resourcestring>
     Specifies a resource pattern to override defaults.  Refer to the
     section: X RESOURCES, below.

Workspace Specific Options
--------------------------

-textforeground <color>
     Set the color of the text foreground.  Overrides the Workspace's own
     setting.

-textbackground <color>
     Set the color of the text background.  Overrides the Workspace's own
     setting.

-importfile <filename>
     At startup, import <filename> into the workspace at the cursor
     position.

-exportfile <filename>
     Export the text of the workspace to <filename>.

-title <workspacename>
     Set the window title and workspace name.

-write
     Save the workspace in its current state.  If the window is not yet
     drawn, use the default geometry of 565x351+100+100 and insertion
     cursor index of 1.0.

-dump
     Print the Workspace text to standard output.

-quit
     Close the Workspace without saving.

X RESOURCES
===========

   In normal use, a workspace's Xresources begin with its name in
lower-case letters.

     myworkspace*borderwidth:       3
     myworkspace*relief:            sunken
     myworkspace*takefocus:         true

   Top-level options are described in the Tk::Toplevel and Tk::options
manual pages.

   In addition, several subwidgets have standard names, so properties can
easily apply to all Workspaces:

     Widget             Resource Name
     ------             -------------
     Text Editor        workspaceText
     Menu Bar Menus     workspaceMenuBar
     Popup Menus        workspacePopupMenu

   Examples of resource settings that apply to all Workspaces:

     *workspaceText*insertwidth:         5
     *workspaceText*spacing1:            20
     *workspaceMenuBar*foreground:       white
     *workspaceMenuBar*background:       darkslategray
     *workspacePopupMenu*foreground:     white
     *workspacePopupMenu*background:     mediumgray

   Complete descriptions of the options that each widget recognizes are
given in the Tk::Text, Tk::TextUndo, and Tk::Menu manual pages.

MENU FUNCTIONS
==============

   A workspace contains a menu bar with File, Edit, Options, and Help
menus.

   The menus also pop up by pressing the right mouse button (Button-3)
over the text area, whether the menu bar is visible or not.

   The menu functions are provided by the Tk::Workspace, Tk::TextUndo,
Tk::Text, and Tk::Widget modules.

File Menu
---------

   Import Text - Insert the contents of a selected text file at the
insertion point.

   Export Text - Write the contents of the workspace to a text file.

   The Import and Export Text functions allow saving to files on remote
hosts using FTP, if the Perl Net::FTP module is installed.  Please refer
to the file INSTALL in the distribution archive and the
Tk::RemoteFileSelect manual page.

   System Command - Prompts for the name of a command to be executed by
the shell, /bin/sh.  The output is inserted into the workspace.

   For example, to insert a manual page into the workspace, enter:

     man <programname> | colcrt - | col -b

   Shell - Starts an interactive shell.  The prompt is the PS1 prompt of
the environment where the workspace was started.  At present the workspace
shell recognizes only a subset of the bash prompt variables, and does not
implement command history or setting of environment variables in the
subshell.

   Due to I/O blocking, results can be unpredictable, especially if the
called program causes an eof condition on STDERR.  For details refer to
the Tk::Shell POD documentation.

   Refer to the bash(1) manual page for further information.

   Typing 'exit' leaves the shell and returns the workspace to normal text
editing mode.

   Filter - Specify a filter and output destination for the text in the
Workspace.  A "filter" is defined as a program that takes its input from
standard input, STDIN, and sends its output to standard output, STDOUT.
By default, output is inserted into the Workspace at the cursor position.
Other destinations are:

     - File--Write output to the file name specified.
     - Terminal--Write output to the Workspace's STDOUT or to a
       character device specified as the output file.
     - New Workspace--Write output to a new Workspace with the
       name specified.

   If the Perl Net::FTP module is installed, filter output can be sent to
a remote host, using the pathname syntax, hostname:/filepathname .

   Save - Save the workspace to disk.

   Quit - Close the workspace window, optionally saving to disk.

   Workspaces are saved with file mode permissions 0700 (read, write, and
execute for the owner of the file).

Edit Menu
---------

   Undo - Reverse the next previous change to the text.

   Cut - Delete the selected text and place it on the X clipboard.

   Copy - Copy the selected text to the X clipboard.

   Paste - Insert text from the X clipboard at the insertion point.

   Evaluate Selection - Interpret the selected text as Perl code.

   Search & Replace - Open a dialog box to enter search and/or replace
strings.  Users can select options for exact upper/lower case matching,
regular expression searches, forward or backward searches, and no query on
replace.  If "Replace without Asking" is selected, then all search matches
will be replaced.  The default is to prompt before the replacement.
Replacements for regular expression matches are not supported.

   Goto Line - Go to the line entered by the user.

   Which Line - Report the line and column position of the insertion point.

Options Menu
------------

   Wrap - Select how the text should wrap at the right margin.

   Scroll Bars - Select from scroll bars at right or left, top or bottom of
the text area.

   Encoding - Select the encoding to use when exporting text.  Does not
affect the Workspace text itself.  When importing, the text is mapped into
ISO-8859-1, regardless of encoding.  This option is only available if the
UTF16 libraries are installed on the system.  If they aren't, then the
Workspace uses the default ISO 8859-1 encoding.  Refer to the file INSTALL
in the distribution archive for information about the required libraries.

   Show/Hide Menubar - Toggle whether the menubar is visible.  A popup
version of the menus is always available by pressing the right mouse
button (Button 3) over the text area.

   Color Editor - Pops up a Color Editor window.  You can select the text
attribute that you want to change from the Colors -> Color Attributes
menu.  If your system libraries have an rgb.txt file, a list of the
available colors is displayed on the left-hand side of the window.
Double-clicking on a color name, or selecting its color space parameters
from the sliders in the middle of the ColorEditor, displays that color in
the swatch on the right-hand side of the window.  Pressing the Apply...
button at the bottom of the Color Editor applies the color selection to
the text.  The most useful attributes for Workspace text are foreground,
background, and insertBackground.

   Text Font - Select text font from list of system fonts.

Help Menu
---------

   About - Report name of workspace and modification time, and version of
Workspace.pm library.

   Help - Display the Workspace.pm POD documentation in a text window
formatted by pod2text.

KEY BINDINGS
============

   For further information, please refer to the Tk::Text and Tk::bind man
pages.

     Alt-Q                 Quit, Optionally Saving Text
     Alt-S                 Save Workspace to Disk
     Alt-I                 Import Text
     Alt-W                 Export Text
     Alt-U                 Undo
     Alt-X                 Copy Selection to Clipboard and Delete
     Alt-C                 Copy Selection to Clipboard
     Alt-V                 Insert Clipboard Contents at Cursor
     Alt-F                 Search & Replace

     Right, Ctrl-F         Forward Character
     Left, Ctrl-B          Backward Character
     Up, Ctrl-P            Up One Line
     Down, Ctrl-N          Down One Line
     Shift-Right           Forward Character Extend Selection
     Shift-Left            Backward Character Extend Selection
     Shift-Up              Up One Line, Extend Selection
     Shift-Down            Down One Line, Extend Selection
     Ctrl-Right, Meta-F    Forward Word
     Ctrl-Left, Meta-B     Backward Word
     Ctrl-Up               Up One Paragraph
     Ctrl-Down             Down One Paragraph
     PgUp                  Scroll View Up One Screen
     PgDn                  Scroll View Down One Screen
     Ctrl-PgUp             Scroll View Right
     Ctrl-PgDn             Scroll View Left
     Home, Ctrl-A          Beginning of Line
     End, Ctrl-E           End of Line
     Ctrl-Home, Meta-<     Beginning of Text
     Ctrl-End, Meta->      End of Text
     Ctrl-/                Select All
     Ctrl-\                Clear Selection
     F16, Copy, Meta-W     Copy Selection to Clipboard
     F20, Cut, Ctrl-W      Copy Selection to Clipboard and Delete
     F18, Paste, Ctrl-Y    Paste Clipboard Text at Insertion Point
     Delete, Ctrl-D        Delete Character to Right, or Selection
     Backspace, Ctrl-H     Delete Character to Left, or Selection
     Meta-D                Delete Word to Right
     Meta-Backspace, Meta-Delete
                           Delete Word to Left
     Ctrl-K                Delete from Cursor to End of Line
     Ctrl-O                Open a Blank Line
     Ctrl-X                Clear Selection
     Ctrl-T                Reverse Order of Characters on Either Side
                           of the Cursor
     Mouse Button 1:
     Single Click: Set Insertion Cursor at Mouse Pointer
     Double Click: Select Word Under the Mouse Pointer and Position
     Cursor at the Beginning of the Word
     Triple Click: Select Line Under the Mouse Pointer and Position
     Cursor at the Beginning of the Line
     Drag: Define Selection from Insertion Cursor
     Shift-Drag: Extend Selection
     Double Click, Shift-Drag: Extend Selection by Whole Words
     Triple Click, Shift-Drag: Extend Selection by Whole Lines
     Ctrl: Position Insertion Cursor without Affecting Selection

     Mouse Button 2:
     Click: Copy Selection into Text at the Mouse Pointer
     Drag:Shift View

     Mouse Button 3:
     Pop Up Menu Bar

     Meta                  Escape

METHODS
=======

   There is no actual API specification, but Workspaces recognize the
following instance methods:

   about, bind, close_dialog, cmd_import, commandline, create,
custom_args, defaultcursor, do_win_signal_event, dump, editmenu,
elementColor, evalselection, exportfile, filemenu, filenotfound, filter,
filter_dialog, filter_text, fontdialogaccept, fontdialogapply,
fontdialogclose, geometry, goto_line, havenet, height, helpmenu,
importfile, insertionpoint, libname, menubar, menubarvisible, menus,
mktmpfile, my_directory, name, new, open, optionsmenu, outputfile,
outputmode, parent_ws, popupmenu, postpopupmenu, quit, requirecond,
scroll, scrollbar, self_help, set_scroll, text, textbackground, textfont,
textforeground, title, togglemenubar, user_import, watchcursor, what_line,
width, window, wmgeometry, workspaceobject, wrap, write, write_to_disk,
ws_copy, ws_cut, ws_export, ws_font, ws_paste, ws_undo, x, y

   The following class methods are available:

   new, ScrollMenuItems, WrapMenuItems, workspaceobject.

   The 'new' constructor recognizes the settings of the following options,
which are used by the Workspace.pm :

   window, name, textfont, width, height, x, y, foreground, background,
textfont, filemenu, editmenu, optionsmenu, wrapmenu, scrollmenu, modemenu,
helpmenu, menubar, popupmenu, menubarvisible, scroll, scrollbuttons,
insertionpoint, text

CREDITS
=======

   Tk::Workspace by rkiesling@mainmatter.com (Robert Kiesling)

   Perl/Tk by Nick Ing-Simmons.  Tk::ColorEditor widget by Steven Lidie.
Perl by Larry Wall and many others.

REVISION
========

   $Id: Workspace.pm,v 1.63 2000/12/30 12:15:32 kiesling Exp $

SEE ALSO:
=========

   Tk::overview(1), Tk::ColorEditor(1), perl(1) manual pages.

Perl extension for Xlib constants.
**********************************

NAME
====

   Tk::X - Perl extension for Xlib constants.

SYNOPSIS
========

     use Tk::X;

DESCRIPTION
===========

   A module generated by h2xs. It exists to export Xlib #define type
constants for possible use with Tk::Xlib.

Exported constants
==================

     Above
     AllTemporary
     AllocAll
     AllocNone
     AllowExposures
     AlreadyGrabbed
     Always
     AnyButton
     AnyKey
     AnyModifier
     AnyPropertyType
     ArcChord
     ArcPieSlice
     AsyncBoth
     AsyncKeyboard
     AsyncPointer
     AutoRepeatModeDefault
     AutoRepeatModeOff
     AutoRepeatModeOn
     BadAccess
     BadAlloc
     BadAtom
     BadColor
     BadCursor
     BadDrawable
     BadFont
     BadGC
     BadIDChoice
     BadImplementation
     BadLength
     BadMatch
     BadName
     BadPixmap
     BadRequest
     BadValue
     BadWindow
     Below
     BottomIf
     Button1
     Button1Mask
     Button1MotionMask
     Button2
     Button2Mask
     Button2MotionMask
     Button3
     Button3Mask
     Button3MotionMask
     Button4
     Button4Mask
     Button4MotionMask
     Button5
     Button5Mask
     Button5MotionMask
     ButtonMotionMask
     ButtonPress
     ButtonPressMask
     ButtonRelease
     ButtonReleaseMask
     CWBackPixel
     CWBackPixmap
     CWBackingPixel
     CWBackingPlanes
     CWBackingStore
     CWBitGravity
     CWBorderPixel
     CWBorderPixmap
     CWBorderWidth
     CWColormap
     CWCursor
     CWDontPropagate
     CWEventMask
     CWHeight
     CWOverrideRedirect
     CWSaveUnder
     CWSibling
     CWStackMode
     CWWidth
     CWWinGravity
     CWX
     CWY
     CapButt
     CapNotLast
     CapProjecting
     CapRound
     CenterGravity
     CirculateNotify
     CirculateRequest
     ClientMessage
     ClipByChildren
     ColormapChangeMask
     ColormapInstalled
     ColormapNotify
     ColormapUninstalled
     Complex
     ConfigureNotify
     ConfigureRequest
     ControlMapIndex
     ControlMask
     Convex
     CoordModeOrigin
     CoordModePrevious
     CopyFromParent
     CreateNotify
     CurrentTime
     CursorShape
     DefaultBlanking
     DefaultExposures
     DestroyAll
     DestroyNotify
     DirectColor
     DisableAccess
     DisableScreenInterval
     DisableScreenSaver
     DoBlue
     DoGreen
     DoRed
     DontAllowExposures
     DontPreferBlanking
     EastGravity
     EnableAccess
     EnterNotify
     EnterWindowMask
     EvenOddRule
     Expose
     ExposureMask
     FamilyChaos
     FamilyDECnet
     FamilyInternet
     FillOpaqueStippled
     FillSolid
     FillStippled
     FillTiled
     FirstExtensionError
     FocusChangeMask
     FocusIn
     FocusOut
     FontChange
     FontLeftToRight
     FontRightToLeft
     ForgetGravity
     GCArcMode
     GCBackground
     GCCapStyle
     GCClipMask
     GCClipXOrigin
     GCClipYOrigin
     GCDashList
     GCDashOffset
     GCFillRule
     GCFillStyle
     GCFont
     GCForeground
     GCFunction
     GCGraphicsExposures
     GCJoinStyle
     GCLastBit
     GCLineStyle
     GCLineWidth
     GCPlaneMask
     GCStipple
     GCSubwindowMode
     GCTile
     GCTileStipXOrigin
     GCTileStipYOrigin
     GXand
     GXandInverted
     GXandReverse
     GXclear
     GXcopy
     GXcopyInverted
     GXequiv
     GXinvert
     GXnand
     GXnoop
     GXnor
     GXor
     GXorInverted
     GXorReverse
     GXset
     GXxor
     GrabFrozen
     GrabInvalidTime
     GrabModeAsync
     GrabModeSync
     GrabNotViewable
     GrabSuccess
     GraphicsExpose
     GravityNotify
     GrayScale
     HostDelete
     HostInsert
     IncludeInferiors
     InputFocus
     InputOnly
     InputOutput
     IsUnmapped
     IsUnviewable
     IsViewable
     JoinBevel
     JoinMiter
     JoinRound
     KBAutoRepeatMode
     KBBellDuration
     KBBellPercent
     KBBellPitch
     KBKey
     KBKeyClickPercent
     KBLed
     KBLedMode
     KeyPress
     KeyPressMask
     KeyRelease
     KeyReleaseMask
     KeymapNotify
     KeymapStateMask
     LASTEvent
     LSBFirst
     LastExtensionError
     LeaveNotify
     LeaveWindowMask
     LedModeOff
     LedModeOn
     LineDoubleDash
     LineOnOffDash
     LineSolid
     LockMapIndex
     LockMask
     LowerHighest
     MSBFirst
     MapNotify
     MapRequest
     MappingBusy
     MappingFailed
     MappingKeyboard
     MappingModifier
     MappingNotify
     MappingPointer
     MappingSuccess
     Mod1MapIndex
     Mod1Mask
     Mod2MapIndex
     Mod2Mask
     Mod3MapIndex
     Mod3Mask
     Mod4MapIndex
     Mod4Mask
     Mod5MapIndex
     Mod5Mask
     MotionNotify
     NoEventMask
     NoExpose
     NoSymbol
     Nonconvex
     None
     NorthEastGravity
     NorthGravity
     NorthWestGravity
     NotUseful
     NotifyAncestor
     NotifyDetailNone
     NotifyGrab
     NotifyHint
     NotifyInferior
     NotifyNonlinear
     NotifyNonlinearVirtual
     NotifyNormal
     NotifyPointer
     NotifyPointerRoot
     NotifyUngrab
     NotifyVirtual
     NotifyWhileGrabbed
     Opposite
     OwnerGrabButtonMask
     ParentRelative
     PlaceOnBottom
     PlaceOnTop
     PointerMotionHintMask
     PointerMotionMask
     PointerRoot
     PointerWindow
     PreferBlanking
     PropModeAppend
     PropModePrepend
     PropModeReplace
     PropertyChangeMask
     PropertyDelete
     PropertyNewValue
     PropertyNotify
     PseudoColor
     RaiseLowest
     ReparentNotify
     ReplayKeyboard
     ReplayPointer
     ResizeRedirectMask
     ResizeRequest
     RetainPermanent
     RetainTemporary
     RevertToNone
     RevertToParent
     RevertToPointerRoot
     ScreenSaverActive
     ScreenSaverReset
     SelectionClear
     SelectionNotify
     SelectionRequest
     SetModeDelete
     SetModeInsert
     ShiftMapIndex
     ShiftMask
     SouthEastGravity
     SouthGravity
     SouthWestGravity
     StaticColor
     StaticGravity
     StaticGray
     StippleShape
     StructureNotifyMask
     SubstructureNotifyMask
     SubstructureRedirectMask
     Success
     SyncBoth
     SyncKeyboard
     SyncPointer
     TileShape
     TopIf
     TrueColor
     UnmapGravity
     UnmapNotify
     Unsorted
     VisibilityChangeMask
     VisibilityFullyObscured
     VisibilityNotify
     VisibilityPartiallyObscured
     VisibilityUnobscured
     WestGravity
     WhenMapped
     WindingRule
     XYBitmap
     XYPixmap
     X_H
     X_PROTOCOL
     X_PROTOCOL_REVISION
     YSorted
     YXBanded
     YXSorted
     ZPixmap

AUTHOR
======

   Nick Ing-Simmons ran h2xs ...

a class for finding X Fonts
***************************

NAME
====

   Tk::Font - a class for finding X Fonts

SYNOPSIS
========

     use Tk::X11Font;

     $font = $widget->X11Font(foundry => 'adobe',
                           family  => 'times',
                           point   => 120
                          );

     $font = $widget->X11Font('*-courier-medium-r-normal-*-*');

DESCRIPTION
===========

     This module can be use to interrogate the X server what fonts are
     avaliable.

METHODS
=======

Foundry( [ $val ] )
-------------------

Family( [ $val ] )
------------------

Weight( [ $val ] )
------------------

Slant( [ $val ] )
-----------------

Swidth( [ $val ] )
------------------

Adstyle( [ $val ] )
-------------------

Pixel( [ $val ] )
-----------------

Point( [ $val ] )
-----------------

Xres( [ $val ] )
----------------

Yres( [ $val ] )
----------------

Space( [ $val ] )
-----------------

Avgwidth( [ $val ] )
--------------------

Registry( [ $val ] )
--------------------

Encoding( [ $val ] )
--------------------

   Set the given field in the font name to $val if given and return the
current or previous value

Name( [ $max ] )
----------------

   In a list context it returns a list of all font names that match the
fields given. It will return a maximum of `$max' names, or 128 if $max is
not given.

   In a scalar contex it returns the first matching name or undef

Clone( [ key => value, [ ...]] )
--------------------------------

   Create a duplicate of the curent font object and modify the given fields

AUTHOR
======

   Graham Barr <Graham.Barr@tiuk.ti.com>

HISTORY
=======

   11-Jan-96 Initial version

   08-Nov-98 Renamed for Tk800.012

COPYRIGHT
=========

   Copyright (c) 1995-1996 Graham Barr. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

X11 Font Selection Dialog.
**************************

NAME
====

     Tk::XFontSelect.pm--X11 Font Selection Dialog.

SYNOPSIS
========

     use Tk;
     use Tk::XFontSelect;

     my $fontdialog = $mw -> FontSelect;
     my $font = $fontdialog -> Show;

DESCRIPTION
===========

   The Tk::XFontSelect widget displays a dialog box that lists the
descriptors of all of the fonts that are present on the system.  Selecting
a font descriptor and pressing the "Accept" button returns to the main
application a string containing that font descriptor.

   The list of font descriptors is generated by the xlsfonts command, a
standard utility of the XFree86 Rev. 3.3.2 distribution.

SEE ALSO
========

   xlsfonts(1) man page.

VERSION INFO
============

   First Release Version

   $Revision: 0.42 $

Tk widget to display XML
************************

NAME
====

   Tk::XMLViewer - Tk widget to display XML

SYNOPSIS
========

     use Tk::XMLViewer;
     $xmlviewer = $top->XMLViewer->pack;
     $xmlviewer->insertXML(-file => "test.xml");
     $xmlviewer->insertXML(-text => "<?xml?><a><bla /><foo>bar</foo></a>");

DESCRIPTION
===========

   Tk::XMLViewer is an widget inherited from Tk::Text which displays XML
in a hierarchical tree. You can use the plus and minus buttons to
hide/show parts of the tree.

METHODS
=======

insertXML
     Insert XML into the XMLViewer widget. Use the -file argument to insert
     a file and -text to insert an XML string.

DumpXML
     Dump the contents of an Tk::Text widget into an XML string, which can
     be used as input for the XMLViewer widget. Use the static variant for
     Tk::Text widgets and the method for XMLViewer widgets.

          $xml_string1 = Tk::XMLViewer::DumpXML($text_widget);
          $xml_string2 = $xmlviewer->DumpXML;

SetIndent
     Set indent with for XML tags

          $xmlviewer->SetIndent(width);

XMLMenu
     Insert XML Menu into Text widget menu.

          $xmlviewer->XMLMenu;

SourceType
     Returns type of source used for last insertXML (-file or -text)

SourceContent
     Returns filename (source type -file) or XML text (source type -text)
     used for last insertXML.

GetInfo
     Returns hash of standard XML decl and DOCTYPE elements:

          my %xmlheader = $xmlviewer->GetInfo;

     Elements for XMLdecl: Version Encoding Standalone Elements for
     DOCTYPE: Name Sysid Pubid Internal

BUGS
====

   Perl/Tk does not support Unicode, yet. For perl 5.6.0 and newer,
unicode characters are translated to ISO-8859-1 chars, if possible.  For
older perls, there is no conversion (unless Unicode::String is installed),
so unicode characters will show as binary values.

   DumpXML will not work with nested text tags.

   There should be only one insertXML operation at one time (these is
probably only an issue with threaded operations, which do not work in
Perl/Tk anyway).

   Viewing of large XML files is slow.

   head1 TODO

     - show to depth n: close everything from depth n+1
     - create menu item "close selected region"
     - DTD validation (is this possible with XML::Parser?)

AUTHOR
======

   Slaven Rezic, <eserte@cs.tu-berlin.de>

   Some additions by Jerry Geiger <jgeiger@rios.de>.

SEE ALSO
========

   See XML/Parser,(3), see Tk/Text,(3).

X Resource/Defaults/Options routines that obey the rules.
*********************************************************

NAME
====

   Tk::Xrm - X Resource/Defaults/Options routines that obey the rules.

SYNOPSIS
========

     use Tk;
     use Tk::Xrm;

DESCRIPTION
===========

   Using this modules causes Tk's Option code to be replaced by versions
which use routines from <X11/Xresource.h> - i.e. same ones every other X
toolkit uses.

   Result is that "matching" of name/Class with the options database
follows the same rules as other X toolkits. This makes it more predictable,
and makes it easier to have a single ~/.Xdefaults file which gives sensible
results for both Tk and (say) Motif applications.

BUGS
====

   Currently *optionAdd*(key => value?, priority?) ignores optional
priority completely and just does XrmPutStringResource().  Perhaps it
should be more subtle and do XrmMergeDatabases() or XrmCombineDatabase().

   This version is a little slower than Tk's re-invention but there is
more optimization that can be done.

SEE ALSO
========

   `Tk::option|Tk::option' in this node

KEYWORDS
========

   database, option, priority, retrieve

Execute a command after a time delay
************************************

NAME
====

   Tk::after - Execute a command after a time delay

     $widget->after(*ms*)

     $id = $widget->after(*ms*?,callback?)

     $id = $widget->repeat(*ms*?,callback?)

     $widget->*afterCancel*($id)

     $id = $widget->*afterIdle*(callback)

     $widget->*afterInfo*?($id)?

DESCRIPTION
===========

   This method is used to delay execution of the program or to execute a
callback in background sometime in the future.

   In perl/Tk $widget->after is implemented via the class `Tk::After', and
callbacks are associated with $widget, and are automatically cancelled
when the widget is destroyed. An almost identical interface, but without
automatic cancel, and without repeat is provided via Tk::after method.

   The internal Tk::After class has the following synopsis:

     $id = Tk::After->new($widget,$time,'once',callback);
     $id = Tk::After->new($widget,$time,'repeat',callback);
     $id->cancel;

   The after method has several forms as follows:

$widget->after(*ms*)
     The value *ms* must be an integer giving a time in milliseconds.  The
     command sleeps for *ms* milliseconds and then returns.  While the
     command is sleeping the application does not respond to events.

$widget->after(*ms*,callback)
     In this form the command returns immediately, but it arranges for
     callback be executed *ms* milliseconds later as an event handler.
     The callback will be executed exactly once, at the given time.  The
     command will be executed in context of $widget.  If an error occurs
     while executing the delayed command then the `Tk::Error|Tk::Error' in
     this node mechanism is used to report the error.  The after command
     returns an identifier (an object in the perl/Tk case) that can be
     used to cancel the delayed command using *afterCancel*.

$widget->repeat(*ms*,callback)
     In this form the command returns immediately, but it arranges for
     callback be executed *ms* milliseconds later as an event handler.
     After callback has executed it is re-scheduled, to be executed in a
     futher *ms*, and so on until it is cancelled.

$widget->*afterCancel*($id)
$id->cancel
     Cancels the execution of a delayed command that was previously
     scheduled.  $id indicates which command should be canceled;  it must
     have been the return value from a previous after command.  If the
     command given by $id has already been executed (and is not scheduled
     to be executed again) then *afterCancel* has no effect.

$widget->*afterCancel*(callback)
     *This form is not robust in perl/Tk - its use is deprecated.* This
     command should also cancel the execution of a delayed command.  The
     callback argument is compared with pending callbacks, if a match is
     found, that callback is cancelled and will never be executed;  if no
     such callback is currently pending then the *afterCancel* has no
     effect.

$widget->*afterIdle*(callback)
     Arranges for callback to be evaluated later as an idle callback.  The
     script will be run exactly once, the next time the event loop is
     entered and there are no events to process.  The command returns an
     identifier that can be used to cancel the delayed command using
     *afterCancel*.  If an error occurs while executing the script then the
     `Tk::Error|Tk::Error' in this node mechanism is used to report the
     error.

$widget->*afterInfo*?($id)?
     This command returns information about existing event handlers.  If
     no $id argument is supplied, the command returns a list of the
     identifiers for all existing  event handlers created by the after
     command for this MainWindow. If $id is supplied, it specifies an
     existing handler; $id must have been the return value from some
     previous call to after and it must not have triggered yet or been
     cancelled. In this case the command returns a list with two elements.
     The first element of the list is the callback associated  with $id,
     and the second element is either idle or timer to indicate what kind
     of event handler it is.

   The after(*ms*) and *afterIdle* forms of the command assume that the
application is event driven:  the delayed commands will not be executed
unless the application enters the event loop.  In applications that are
not normally event-driven, the event loop can be entered with the *vwait*
and update commands.

SEE ALSO
========

   `Tk::Error|Tk::Error' in this node `Tk::callbacks|Tk::callbacks' in
this node

KEYWORDS
========

   cancel, delay, idle callback, sleep, time

Arrange for X events to invoke callbacks
****************************************

NAME
====

   Tk::bind - Arrange for X events to invoke callbacks

   Retrieve bindings:

       $widget->bind

       $widget->bind(tag)

       $widget->bind(sequence)

       $widget->bind(tag,sequence)

   Associate and destroy bindings:

       $widget->bind(sequence,callback)

       $widget->bind(tag,sequence,callback)

DESCRIPTION
===========

   The bind method associates callbacks with X events.  If callback is
specified, bind will arrange for callback to be evaluated whenever the
event(s) given by sequence occur in the window(s) identified by $widget or
tag.  If callback is an empty string then the current binding for sequence
is destroyed, leaving sequence unbound.  In all of the cases where a
callback argument is provided, bind returns an empty string.

   If sequence is specified without a callback, then the callback
currently bound to sequence is returned, or undef is returned if there is
no binding for sequence.  If neither sequence nor callback is specified,
then the return value is a list whose elements are all the sequences for
which there exist bindings for tag.

   If no tag is specified then the bind refers to $widget.  If tag is
specified then it is typically a class name and the bind refers to all
instances of the class on the *MainWindow* associated with $widget. (It is
possible for tag to be another "widget object" but this practice is
deprecated.) Perl's ref($object) can be used to get the class name of any
object.  Each window has an associated list of tags, and a binding applies
to a particular window if its tag is among those specified for the window.
Although the *bindtags* method may be used to assign an arbitrary set of
binding tags to a window, the default binding tags provide the following
behavior:

   If a tag is the name of an internal window the binding applies to that
window.

   If the tag is the name of a toplevel window the binding applies to the
toplevel window and all its internal windows.

   If the tag is the name of a class of widgets, such as *Tk::Button*, the
binding applies to all widgets in that class;

   If tag has the value all, the binding applies to all windows descended
from the MainWindow of the application.

EVENT PATTERNS
==============

   The sequence argument specifies a sequence of one or more event
patterns, with optional white space between the patterns.  Each event
pattern has the following syntax:

       '<modifier-modifier-type-detail>'

   The entire event pattern is surrounded by angle brackets, and normally
needs to be quoted, as angle brackets are special to perl.  Inside the
angle brackets are zero or more modifiers, an event type, and an extra
piece of information (detail) identifying a particular button or keysym.
Any of the fields may be omitted, as long as at least one of type and
detail is present.  The fields must be separated by white space or dashes.

   A second form of pattern is used to specify a user-defined, named
virtual event; see Tk/event, for details.  It has the
following syntax:

       <<name>>

   The entire virtual event pattern is surrounded by double angle brackets.
Inside the angle brackets is the user-defined name of the virtual event.
Modifiers, such as Shift or Control, may not be combined with a virtual
event to modify it.  Bindings on a virtual event may be created before the
virtual event is defined, and if the definition of a virtual event changes
dynamically, all windows bound to that virtual event will respond
immediately to the new definition.

MODIFIERS
=========

   Modifiers consist of any of the following values:

     Control	Mod2, M2
     Shift          Mod3, M3
     Lock          	Mod4, M4
     Button1, B1	Mod5, M5
     Button2, B2	Meta, M
     Button3, B3	Alt
     Button4, B4	Double
     Button5, B5	Triple
     Mod1,    M1

   Where more than one value is listed, separated by commas, the values
are equivalent.  Most of the modifiers have the obvious X meanings.  For
example, *Button1* requires that button 1 be depressed when the event
occurs.  For a binding to match a given event, the modifiers in the event
must include all of those specified in the event pattern.  An event may
also contain additional modifiers not specified in the binding.  For
example, if button 1 is pressed while the shift and control keys are down,
the pattern *<Control-Button-1>* will match the event, but
*<Mod1-Button-1>* will not.  If no modifiers are specified, then any
combination of modifiers may be present in the event.

   Meta and M refer to whichever of the *M1* through *M5* modifiers is
associated with the meta key(s) on the keyboard (keysyms *Meta_R* and
*Meta_L*).  If there are no meta keys, or if they are not associated with
any modifiers, then Meta and M will not match any events.  Similarly, the
*Alt* modifier refers to whichever modifier is associated with the alt
key(s) on the keyboard (keysyms *Alt_L* and *Alt_R*).

   The Double and Triple modifiers are a convenience for specifying double
mouse clicks and other repeated events. They cause a particular event
pattern to be repeated 2 or 3 times, and also place a time and space
requirement on the sequence:  for a sequence of events to match a Double
or Triple pattern, all of the events must occur close together in time and
without substantial mouse motion in between.  For example,
*<Double-Button-1>* is equivalent to *<Button-1><Button-1>* with the extra
time and space requirement.

EVENT TYPES
===========

   The type field may be any of the standard X event types, with a few
extra abbreviations.  Below is a list of all the valid types; where two
names appear together, they are synonyms.

     ButtonPress, Button	Expose	Map
     ButtonRelease	FocusIn	Motion
     Circulate	FocusOut	Property
     Colormap	Gravity	Reparent
     Configure	KeyPress, Key	Unmap
     Destroy	KeyRelease	Visibility
     Enter	Leave	Activate
     Deactivate

   The last part of a long event specification is detail.  In the case of
a *ButtonPress* or ButtonRelease event, it is the number of a button
(1-5).  If a button number is given, then only an event on that particular
button will match;  if no button number is given, then an event on any
button will match.  Note:  giving a specific button number is different
than specifying a button modifier; in the first case, it refers to a
button being pressed or released, while in the second it refers to some
other button that is already depressed when the matching event occurs.  If
a button number is given then type may be omitted:  if will default to
*ButtonPress*.  For example, the specifier *<1>* is equivalent to
*<ButtonPress-1>*.

   If the event type is *KeyPress* or *KeyRelease*, then detail may be
specified in the form of an X keysym.  Keysyms are textual specifications
for particular keys on the keyboard; they include all the alphanumeric
ASCII characters (e.g. "a" is the keysym for the ASCII character "a"),
plus descriptions for non-alphanumeric characters ("comma" is the keysym
for the comma character), plus descriptions for all the non-ASCII keys on
the keyboard ("Shift_L" is the keysm for the left shift key, and "F1" is
the keysym for the F1 function key, if it exists).  The complete list of
keysyms is not presented here;  it is available in other X documentation
and may vary from system to system.  If necessary, you can use the 'K'
notation described below to print out the keysym name for a particular key.
If a keysym detail is given, then the type field may be omitted;  it will
default to *KeyPress*.  For example, *<Control-comma>* is equivalent to
*<Control-KeyPress-comma>*.

BINDING CALLBACKS AND SUBSTITUTIONS
===================================

   The callback argument to bind is a perl/Tk callback.  which will be
executed whenever the given event sequence occurs.  (See
Tk/callbacks, for description of the possible forms.)
Callback will be associated with the same *MainWindow* that is associated
with the $widget that was used to invoke the bind method, and it will run
as though called from MainLoop.  If callback contains any *Ev*(%) calls,
then each "nested" *Ev*(%) "callback" will be evaluated when the event
occurs to form arguments to be passed to the main callback.  The
replacement depends on the character %, as defined in the list below.
Unless otherwise indicated, the replacement string is the numeric
(decimal) value of the given field from the current event. Perl/Tk has
enhanced this mechanism slightly compared to the comparable Tcl/Tk
mechanism. The enhancements are not yet all reflected in the list below.
Some of the substitutions are only valid for certain types of events;  if
they are used for other types of events the value substituted is undefined
(not the same as undef!).

'#'
     The number of the last client request processed by the server (the
     serial field from the event).  Valid for all event types.

'a'
     The above field from the event, formatted as a hexadecimal number.
     Valid only for Configure events.

'b'
     The number of the button that was pressed or released.  Valid only
     for *ButtonPress* and ButtonRelease events.

'c'
     The count field from the event.  Valid only for *Expose* events.

'd'
     The detail field from the event.  The 'd' is replaced by a string
     identifying the detail.  For Enter, *Leave*, *FocusIn*, and
     *FocusOut* events, the string will be one of the following:

          NotifyAncestor	NotifyNonlinearVirtual
          NotifyDetailNone	NotifyPointer
          NotifyInferior	NotifyPointerRoot
          NotifyNonlinear	NotifyVirtual

     For events other than these, the substituted string is undefined.
     (Note that this is not the same as Detail part of sequence use to
     specify the event.)

'f'
     The focus field from the event (0 or 1).  Valid only for Enter and
     *Leave* events.

'h'
     The height field from the event.  Valid only for Configure, *Expose*,
     and *GraphicsExpose* events.

'k'
     The *keycode* field from the event.  Valid only for *KeyPress* and
     *KeyRelease* events.

'm'
     The mode field from the event.  The substituted string is one of
     *NotifyNormal*, *NotifyGrab*, *NotifyUngrab*, or
     *NotifyWhileGrabbed*.  Valid only for *EnterWindow*, *FocusIn*,
     *FocusOut*, and *LeaveWindow* events.

'o'
     The *override_redirect* field from the event.  Valid only for Map,
     *Reparent*, and Configure events.

'p'
     The *place* field from the event, substituted as one of the strings
     *PlaceOnTop* or *PlaceOnBottom*.  Valid only for *Circulate* events.

's'
     The state field from the event.  For *ButtonPress*, ButtonRelease,
     Enter, *KeyPress*, *KeyRelease*, *Leave*, and *Motion* events, a
     decimal string is substituted.  For *Visibility*, one of the strings
     *VisibilityUnobscured*, *VisibilityPartiallyObscured*, and
     *VisibilityFullyObscured* is substituted.

't'
     The time field from the event.  Valid only for events that contain a
     time field.

'w'
     The width field from the event.  Valid only for Configure, *Expose*,
     and *GraphicsExpose* events.

'x'
     The x field from the event.  Valid only for events containing an x
     field.

'y'
     The y field from the event.  Valid only for events containing a y
     field.

*'@'*
     The string "@*x,y*" where x and y are as above.  Valid only for
     events containing x and y fields.  This format is used my methods of
     *Tk::Text* and similar widgets.

'A'
     Substitutes the ASCII character corresponding to the event, or the
     empty string if the event doesn't correspond to an ASCII character
     (e.g. the shift key was pressed).  *XLookupString* does all the work
     of translating from the event to an ASCII character.  Valid only for
     *KeyPress* and *KeyRelease* events.

'B'
     The *border_width* field from the event.  Valid only for Configure
     events.

'E'
     The *send_event* field from the event.  Valid for all event types.

'K'
     The keysym corresponding to the event, substituted as a textual
     string.  Valid only for *KeyPress* and *KeyRelease* events.

'N'
     The keysym corresponding to the event, substituted as a decimal
     number.  Valid only for *KeyPress* and *KeyRelease* events.

'R'
     The root window identifier from the event.  Valid only for events
     containing a root field.

'S'
     The *subwindow* window identifier from the event, as an object if it
     is one otherwise as a hexadecimal number.  Valid only for events
     containing a *subwindow* field.

'T'
     The type field from the event.  Valid for all event types.

'W'
     The window to which the event was reported (the $widget field from
     the event) - as an perl/Tk object.  Valid for all event types.

'X'
     The *x_root* field from the event.  If a virtual-root window manager
     is being used then the substituted value is the corresponding
     x-coordinate in the virtual root.  Valid only for *ButtonPress*,
     ButtonRelease, *KeyPress*, *KeyRelease*, and *Motion* events.

'Y'
     The *y_root* field from the event.  If a virtual-root window manager
     is being used then the substituted value is the corresponding
     y-coordinate in the virtual root.  Valid only for *ButtonPress*,
     ButtonRelease, *KeyPress*, *KeyRelease*, and *Motion* events.

MULTIPLE MATCHES
================

   It is possible for several bindings to match a given X event.  If the
bindings are associated with different tag's, then each of the bindings
will be executed, in order.  By default, a class binding will be executed
first, followed by a binding for the widget, a binding for its toplevel,
and an all binding.  The *bindtags* method may be used to change this
order for a particular window or to associate additional binding tags with
the window.

   return and *Tk->break* may be used inside a callback to control the
processing of matching callbacks.  If return is invoked, then the current
callback is terminated but Tk will continue processing callbacks
associated with other tag's.  If *Tk->break* is invoked within a callback,
then that callback terminates and no other callbacks will be invoked for
the event.  (*Tk->break* is implemented via perl's die with a special value
which is "caught" by the perl/Tk "glue" code.)

   If more than one binding matches a particular event and they have the
same tag, then the most specific binding is chosen and its callback is
evaluated.  The following tests are applied, in order, to determine which
of several matching sequences is more specific: (a) an event pattern that
specifies a specific button or key is more specific than one that doesn't;
(b) a longer sequence (in terms of number of events matched) is more
specific than a shorter sequence; (c) if the modifiers specified in one
pattern are a subset of the modifiers in another pattern, then the pattern
with more modifiers is more specific.  (d) a virtual event whose physical
pattern matches the sequence is less specific than the same physical
pattern that is not associated with a virtual event.  (e) given a sequence
that matches two or more virtual events, one of the virtual events will be
chosen, but the order is undefined.

   If the matching sequences contain more than one event, then tests
(c)-(e) are applied in order from the most recent event to the least recent
event in the sequences.  If these tests fail to determine a winner, then
the most recently registered sequence is the winner.

   If there are two (or more) virtual events that are both triggered by the
same sequence, and both of those virtual events are bound to the same
window tag, then only one of the virtual events will be triggered, and it
will be picked at random:

     $widget->eventAdd('<<Paste>>' => '<Control-y>');
     $widget->eventAdd('<<Paste>>' => '<Button-2>');
     $widget->eventAdd <<Scroll>>' => '<Button-2>');
     $widget->bind('Tk::Entry','<<Paste>>',sub { print 'Paste'});
     $widget->bind('Tk::Entry','<<Scroll>>', sub {print 'Scroll'});

   If the user types Control-y, the *<<Paste>>* binding will be invoked,
but if the user presses button 2 then one of either the *<<Paste>>* or the
*<<Scroll>>* bindings will be invoked, but exactly which one gets invoked
is undefined.

   If an X event does not match any of the existing bindings, then the
event is ignored.  An unbound event is not considered to be an error.

MULTI-EVENT SEQUENCES AND IGNORED EVENTS
========================================

   When a sequence specified in a bind method contains more than one event
pattern, then its callback is executed whenever the recent events (leading
up to and including the current event) match the given sequence.  This
means, for example, that if button 1 is clicked repeatedly the sequence
*<Double-ButtonPress-1>* will match each button press but the first.  If
extraneous events that would prevent a match occur in the middle of an
event sequence then the extraneous events are ignored unless they are
*KeyPress* or *ButtonPress* events.  For example, *<Double-ButtonPress-1>*
will match a sequence of presses of button 1, even though there will be
ButtonRelease events (and possibly *Motion* events) between the
*ButtonPress* events.  Furthermore, a *KeyPress* event may be preceded by
any number of other *KeyPress* events for modifier keys without the
modifier keys preventing a match.  For example, the event sequence *aB*
will match a press of the a key, a release of the a key, a press of the
Shift key, and a press of the b key:  the press of Shift is ignored
because it is a modifier key.  Finally, if several *Motion* events occur
in a row, only the last one is used for purposes of matching binding
sequences.

ERRORS
======

   If an error occurs in executing the callback for a binding then the
*Tk::Error* mechanism is used to report the error.  The *Tk::Error*
mechanism will be executed at same call level, and associated with the
same *MainWindow* as as the callback was invoked.

CAVEATS
=======

   Note that for the Canvas widget, the call to bind has to be fully
qualified. This is because there is already a bind method for the Canvas
widget, which binds individual canvas tags.

       *$canvas*->*Tk::bind*

SEE ALSO
========

   `Tk::Error|Tk::Error' in this node `Tk::callbacks|Tk::callbacks' in
this node `Tk::bindtags|Tk::bindtags' in this node

KEYWORDS
========

   Event, binding

Determine which bindings apply to a window, and order of evaluation
*******************************************************************

NAME
====

   Tk::bindtags - Determine which bindings apply to a window, and order of
evaluation

   $widget->*bindtags*([*tagList*]); *@tags* = $widget->*bindtags*;

DESCRIPTION
===========

   When a binding is created with the bind command, it is associated
either with a particular window such as $widget, a class name such as
*Tk::Button*, the keyword all, or any other string.  All of these forms
are called *binding tags*.  Each window has a list of binding tags that
determine how events are processed for the window.  When an event occurs
in a window, it is applied to each of the window's tags in order:  for
each tag, the most specific binding that matches the given tag and event
is executed.  See the Tk/bind, documentation for more
information on the matching process.

   By default, each window has four binding tags consisting of the the
window's class name, name of the window, the name of the window's nearest
toplevel ancestor, and all, in that order.  Toplevel windows have only
three tags by default, since the toplevel name is the same as that of the
window.

   Note that this order is *different* from order used by Tcl/Tk.  Tcl/Tk
has the window ahead of the class name in the binding order.  This is
because Tcl is procedural rather than object oriented and the normal way
for Tcl/Tk applications to override class bindings is with an instance
binding. However, with perl/Tk the normal way to override a class binding
is to derive a class. The perl/Tk order causes instance bindings to
execute after the class binding, and so instance bind callbacks can make
use of state changes (e.g. changes to the selection) than the class
bindings have made.

   The *bindtags* command allows the binding tags for a window to be read
and modified.

   If $widget->*bindtags* is invoked without an argument, then the current
set of binding tags for $widget is returned as a list.  If the *tagList*
argument is specified to *bindtags*, then it must be a reference to and
array; the tags for $widget are changed to the elements of the array. (A
reference to an anonymous array can be created by enclosin the elements in
*[ ]*.)  The elements of *tagList* may be arbitrary strings or widget
objects, if no window exists for an object at the time an event is
processed, then the tag is ignored for that event.  The order of the
elements in *tagList* determines the order in which binding callbacks are
executed in response to events.  For example, the command

     $b->bindtags([$b,ref($b),$b->toplevel,'all'])

   applies the Tcl/Tk binding order which binding callbacks will be
evaluated for a button (say) $b so that $b's instance bindings are invoked
first, following by bindings for $b's class, followed by bindings for $b's
toplevel, followed by 'all' bindings.

   If *tagList* is an empty list i.e. [], then the binding tags for
$widget are returned to the perl/Tk default state described above.

   The *bindtags* command may be used to introduce arbitrary additional
binding tags for a window, or to remove standard tags.  For example, the
command

     $b->bindtags(['TrickyButton',$b->toplevel,'all'])

   replaces the (say) *Tk::Button* tag for $b with *TrickyButton*.  This
means that the default widget bindings for buttons, which are associated
with the *Tk::Button* tag, will no longer apply to $b, but any bindings
associated with *TrickyButton* (perhaps some new button behavior) will
apply.

BUGS
====

   The current mapping of the 'native' Tk behaviour of this method i.e.
returning a list but only accepting a reference to an array is counter
intuitive. The perl/Tk interface  may be tidied up, returning a list is
sensible so, most likely fix will be to allow a list to be passed to
/fIset/fR the bindtags.

SEE ALSO
========

   `Tk::bind|Tk::bind' in this node `Tk::callbacks|Tk::callbacks' in this
node

KEYWORDS
========

   binding, event, tag

Specifying code for Tk to call.
*******************************

NAME
====

   Tk::callbacks - Specifying code for Tk to call.

   One can specify a callback in one of the following ways:

   Without arguments:

     ... => \&subname, ...
     ... => sub { ... }, ...
     ... => 'methodname', ...

   or with arguments:

     ... => [ \&subname ?, args ...? ], ...
     ... => [ sub { ... } ?, args...? ], ...
     ... => [ 'methodname' ?, args...?], ...

DESCRIPTION
===========

   Perl/Tk has a callback, where Tcl/Tk has a command string (i.e. a
fragment of Tcl to be executed).  A perl/Tk callback can take one of the
following basic forms:

   * Reference to a subroutine `\E<amp'subname>

   * Anonymous subroutine (closure) `sub { ... }'

   * A method name `'methodname''

   Any of these can be provided with arguments by enclosing them and the
arguments in []. Here are some examples:

   *$mw*->bind(*$class,* *"<Delete>" => 'Delete'*);

   This will call $widget->Delete, the $widget being provided (by bind) as
the one where the Delete key was pressed.

   While having bind provide a widget object for you is ideal in many cases
it can be irritating in others. Using the list form this behaviour can be
modified:

   *$a*->bind(*"<Delete>"*,[$b => 'Delete']);

   because the first element $b is an object bind will call $b->Delete.

   Note that method/object ordering only matters for bind callbacks, the
auto-quoting in perl5.001 makes the first of these a little more readable:

   $w->configure(-yscrollcommand => [ set => $ysb]);

   $w->configure(-yscrollcommand => [ $ysb => 'set' ]);

   but both will call `$ysb'->set(args provided by Tk)

   Another use of arguments allows you to write generalized methods which
are easier to re-use:

   $a->bind("<Next>",['Next','Page']);

   $a->bind("<Down>",['Next','Line']);

   This will call `$a'->Next('Page') or `$a'->Next('Line') respectively.

   Note that the contents of the [] are evaluated by perl when the
callback is created. It is often desirable for the arguments provided to
the callback to depend on the details of the event which caused it to be
executed. To allow for this callbacks can be nested using the `Ev(...)'
"constructor".  `Ev(...)' inserts callback objects into the argument list.
When perl/Tk glue code is preparing the argument list for the callback it
is about to call it spots these special objects and recursively applies
the callback process to them.

EXAMPLES
========

     $entry->bind('<Return>' => [$w , 'validate', Ev(['get'])]);

     $toplevel->bind('all', '<Visibility>', [\&unobscure, Ev('s')]);

     $mw->bind($class, '<Down>', ['SetCursor', Ev('UpDownLine',1)]);

SEE ALSO
========

   `Tk::bind|Tk::bind' in this node `Tk::after|Tk::after' in this node
`Tk::options|Tk::options' in this node `Tk::fileevent|Tk::fileevent' in
this node

KEYWORDS
========

   callback, closure, anonymous subroutine, bind

pops up a dialog box for the user to select a color.
****************************************************

NAME
====

   chooseColor - pops up a dialog box for the user to select a color.

       $color = $widget->*chooseColor*?(*-option*=>value, ...)?;

DESCRIPTION
===========

   The method *chooseColor* is implemented as a perl wrapper on the core
tk "command" *tk_chooseColor*. The $widget is passed as the argument to
*-parent* described below.  The implementation of internal
*tk_chooseColor* is platform specific, on Win32 it is a native dialog, and
on UNIX/X it is implemented in terms of `Tk::ColorEditor|Tk::ColorEditor'
in this node.

   The core tk command *tk_chooseColor* pops up a dialog box for the user
to select a color. The following *option-value* pairs are possible as
command line arguments:

*-initialcolor*=>color
     Specifies the color to display in the color dialog when it pops up.
     color must be in a form acceptable to the *Tk_GetColor* function.

*-parent*=>$widget
     Makes $widget the logical parent of the color dialog. The color
     dialog is displayed on top of its parent window.

*-title*=>*titleString*
     Specifies a string to display as the title of the dialog box. If this
     option is not specified, then a default title will be displayed.

   If the user selects a color, *tk_chooseColor* will return the name of
the color in a form acceptable to *Tk_GetColor*.  If the user cancels the
operation, the command will return undef.

EXAMPLE
=======

     $widget->configure(-fg => $parent->chooseColor(-initialcolor => 'gray',
                     -title => "Choose color"));

KEYWORDS
========

   color selection dialog

Defining a new composite widget class
*************************************

NAME
====

   Tk::composite - Defining a new composite widget class

     package Tk::Whatever;

     require Tk::Derived;
     require Tk::Frame;                    # or Tk::Toplevel
     @ISA = qw(Tk::Derived Tk::Frame)';    # or Tk::Toplevel

     Construct Tk::Widget 'Whatever';

     sub ClassInit
     {
      my ($class,$mw) = @_;

     #... e.g., class bindings here ...
     $class->SUPER::ClassInit($mw);
         }

     sub Populate
     {
      my ($cw,$args) = @_;

     my $flag = delete $args->{-flag};
     if (defined $flag)
      {
       # handle -flag => xxx which can only be done at create
       # time the delete above ensures that new() does not try
       # and do  $cw->configure(-flag => xxx);
      }

     $cw->SUPER::Populate($args);

     $w = $cw->Component(...);

     $cw->Delegates(...);

     $cw->ConfigSpecs(
     		'-cursor'    => [SELF,'cursor','Cursor',undef],
                '-something' => [METHOD,dbName,dbClass,'default'],
                '-text'      => [$label,dbName,dbClass,'default'],
                '-heading'   => [{-text=>$head},
                                 heading,Heading,'My Heading'],
                );
        }

     sub something
     {
      my ($cw,$value) = @_;
      if (@_ > 1)
       {
        # set it
       }
      return # current value
     }

     1;

     __END__

     # Anything not documented is *private* - your POD is god, so to speak.

     =head1 NAME

     Tk::Whatever - a whatever widget

     =head1 SYNOPSIS

     use Tk::Whatever;

     $widget = $parent->Whatever(...);

     =head1 DESCRIPTION

     You forgot to document your widget, didn't you? :-)

     ...

DESCRIPTION
===========

   The intention behind a composite is to create a higher-level widget,
sometimes called a "super-widget" or "meta-widget".  Most often, a
composite will be built upon other widgets by using them, as opposed to
specializing on them.  For example, the supplied composite widget
*LabEntry* is *made of* an Entry and a Label; it is neither a *kind-of*
Label nor is it a *kind-of* Entry.

   Most of the work of a composite widget consist in creating subwidgets,
arrange to dispatch configure options to the proper subwidgets and manage
composite-specific configure options.

GLORY DETAILS
=============

   Depending on your perl/Tk knowledget this section may be enlighting or
confusing.

Composite Widget
----------------

   Since perl/Tk is heavilly using an object-oriented approach, it is no
suprise that creating a composite goes through a new() method.  However,
the composite does not normally define a new() method itself: it is
usually sufficient to simply inherit it from *Tk::Widget*.

   This is what happens when the composite use

     @ISA = qw(Tk::Frame);  # or Tk::Toplevel

   to specify its inheritance chain.  To complete the initialisation of the
widget, it must call the Construct method from class *Widget*.  That
method accepts the name of the new class to create, i.e. the package name
of your composite widget:

     Construct Tk::Widget 'Whatever';

   Here, *Whatever* is the package name (aka the widget's class).  This
will define a constructor method for *Whatever*, normally named after the
widget's class.  Instanciating that composite in client code would the
look like:

     $mw = MainWindow->new();   # Creates a top-level main window

     $cw = $mw->Whatever();     # Creates an instance of the
                                # composite widget Whatever

   Whenever a composite is instanciated in client code,
`Tk::Widget::new()' will be invoked via the widget's class constructor.
That new method will call

     $cw->InitObject(\%args);

   where *%args* is the arguments passed to the widget's constructor.  Note
that InitObject receives a reference to the hash array containing all
arguments.

   For composite widgets that needs an underlying frame, InitObject will
typically be inherited from *Tk::Frame*, that is, no method of this name
will appear in the composite package.  For composites that don't need a
frame, InitObject will typically be defined in the composite class
(package).  Compare the *LabEntry* composite with *Optionmenu*: the former
is Frame based while the latter is *Widget* based.

   In Frame based composites, *Tk::Frame::InitObject()* will call
*Populate()*, which should be defined to create the characteristic
subwidgets of the class.

   *Widget* based composites don't need an extra Populate layer; they
typically have their own InitObject method that will create subwidgets.

Creating Subwidgets
-------------------

   Subwidget creation happens usually in *Populate()* (Frame based) or
*InitObject()* (*Widget* based).  The composite usually calls the
subwidget's constructor method either directly, for "private" subwidgets,
or indirectly through the Component method for subwidgets that should be
advertised to clients.

   Populate may call Delegates to direct calls to methods of chosen
subwidgets. For simple composites, typically most if not all methods are
directed to a single subwidget - e.g. *ScrListbox* directs all methods to
the core Listbox so that *$composite*->get(...) calls *$listbox*->get(...).

Further steps for Frame based composites
----------------------------------------

   Populate should also call *ConfigSpecs()* to specify the way that
configure-like options should be handled in the composite.  Once Populate
returns, method *Tk::Frame::ConfigDefault* walks through the ConfigSpecs
entries and populates %$args hash with defaults for options from X
resources (`.Xdefaults', etc).

   When  *InitObject()* returns to *Tk::Widget::new()*, a call to
*$cw*->configure(%$args) is made which sets *all* the options.

SEE ALSO
========

   `Tk::ConfigSpecs|Tk::ConfigSpecs' in this node
`Tk::Derived|Tk::Derived' in this node

Defining behaviour of 'configure' for composite widgets.
********************************************************

NAME
====

   Tk::ConfigSpecs - Defining behaviour of 'configure' for composite
widgets.

     sub Populate
     {
      my ($composite,$args) = @_;
      ...
      $composite->ConfigSpecs('-attribute' => [ where,dbName,dbClass,default ]);
      $composite->ConfigSpecs('-alias' => '-otherattribute');
      $composite->ConfigSpecs('DEFAULT' => [ where ]);
      ...
     }

     $composite->configure(-attribute => value);

DESCRIPTION
===========

   The aim is to make the composite widget configure method look as much
like a regular Tk widget's configure as possible.  (See Tk/options,
for a description of this behaviour.)  To enable this the
attributes that the composite as a whole accepts needs to be defined.

Defining the ConfigSpecs for a class.
-------------------------------------

   Typically a widget will have one or more calls like the following

     $composite->ConfigSpecs(-attribute => [where,dbName,dbClass,default]);

   in its Populate method. When ConfigSpecs is called this way (with
arguments) the arguments are used to construct or augment/replace a hash
table for the widget. (More than one *-option*=>value pair can be
specified to a single call.)

   *dbName*, *dbClass* and default are only used by *ConfigDefault*
described below, or to respond to 'inquiry' configure commands.

   It may be either one of the values below, or a list of such values
enclosed in [].

   The currently permitted values of where are:

'ADVERTISED'
     apply configure to *advertised* subwidgets.

'DESCENDANTS'
     apply configure recursively to all descendants.

'CALLBACK'
     Setting the attribute does `Tk::Callback->new($value)' before storing
     in `$composite->{Configure}{-attribute}'. This is appropriate for
     `-command => ...' attributes that are handled by the composite and not
     forwarded to a subwidget. (E.g. *Tk::Tiler* has `-yscrollcommand' to
     allow it to have scrollbar attached.)

     This may be the first of several 'validating' keywords (e.g. font,
     cursor, anchor etc.) that core Tk makes special for C code.

'CHILDREN'
     apply configure to all children.  (Children are the immediate
     descendants of a widget.)

'METHOD'
     Call `$cw->attribute(value)'

     This is the most general case. Simply have a method of the composite
     class with the same name as the attribute.  The method may do any
     validation and have whatever side-effects you like.  (It is probably
     worth 'queueing' using *afterIdle* for more complex side-effects.)

'PASSIVE'
     Simply store value in `$composite->{Configure}{-attribute}'.

     This form is also a useful placeholder for attributes which you
     currently only handle at create time.

'SELF'
     Apply configure to the core widget (e.g. Frame) that is the basis of
     the composite. (This is the default behaviour for most attributes
     which makes a simple Frame behave the way you would expect.) Note
     that once you have specified ConfigSpecs for an attribute you must
     explicitly include 'SELF' in the list if you want the attribute to
     apply to the composite itself (this avoids nasty infinite recursion
     problems).

$reference (blessed)
     Call $reference->configure(-attribute => value)

     A common case is where $reference is a subwidget.

     $reference may also be result of

          Tk::Config->new(setmethod,getmethod,args,...);

     *Tk::Config* class is used to implement all the above keyword types.
     The class has configure and cget methods so allows higher level code
     to always just call one of those methods on an object of some kind.

*hash reference*
     Defining:

          $cw->ConfigSpecs(
          	...
          	-option => [ { -optionX=>$w1, -optionY=>[$w2, $w3] },
          			dbname dbclass default ],
          	...
          	);

     So `$cw->configure(-option => value)' actually does

          $w1->configure(-optionX => value);
          $w2->configure(-optionY => value);
          $w3->configure(-optionY => value);

'otherstring'
     Call

          $composite->Subwidget('otherstring')->configure( -attribute => value );

     While this is here for backward compatibility with Tk-b5, it is
     probably better just to use the subwidget reference directly.  The
     only case for retaining this form is to allow an additional layer of
     abstraction - perhaps having a 'current' subwidget - this is unproven.

Aliases
     `ConfigSpecs( -alias => '-otherattribute' )' is used to make `-alias'
     equivalent to `-otherattribute'. For example the aliases

          -fg => '-foreground',
          -bg => '-background'

     are provided automatically (if not already specified).

Default Values
--------------

   When the Populate method returns *ConfigDefault* is called.  This calls

     $composite->ConfigSpecs;

   (with no arguments) to return a reference to a hash. Entries in the hash
take the form:

     '-attribute' => [ where, dbName, dbClass, default ]

   *ConfigDefault* ignores 'where' completely (and also the DEFAULT entry)
and checks the 'options' database on the widget's behalf, and if an entry
is present matching dbName/dbClass

     -attribute => value

   is added to the list of options that new will eventually apply to the
widget. Likewise if there is not a match and default is defined this
default value will be added.

   Alias entries in the hash are used to convert user-specified values for
the alias into values for the real attribute.

New()-time Configure
--------------------

   Once control returns to new, the list of user-supplied options
augmented by those from *ConfigDefault* are applied to the widget using the
configure method below.

   Widgets are most flexible and most Tk-like if they handle the majority
of their attributes this way.

Configuring composites
----------------------

   Once the above have occurred calls of the form:

     $composite->configure( -attribute => value );

   should behave like any other widget as far as end-user code is
concerned.  configure will be handled by *Tk::Derived::configure* as
follows:

     $composite->ConfigSpecs;

   is called (with no arguments) to return a reference to a hash
*-attribute* is looked up in this hash, if *-attribute* is not present in
the hash then *'DEFAULT'* is looked for instead.  (Aliases are tried as
well and cause redirection to the aliased attribute).  The result should
be a reference to a list like:

     [ where, dbName, dbClass, default ]

   at this stage only where is of interest, it maps to a list of object
references (maybe only one) foreach one

     $object->configure( -attribute => value );

   is evaled.

Inquiring attributes of composites
----------------------------------

     $composite->cget( '-attribute' );

   This is handled by  *Tk::Derived::cget* in a similar manner to
configure. At present if where is a list of more than one object it is
ignored completely and the "cached" value in

     $composite->{Configure}{-attribute}.

   is returned.

CAVEATS
=======

   It is the author's intention to port as many of the "Tix" composite
widgets as make sense. The mechanism described above may have to evolve in
order to make this possible, although now aliases are handled I think the
above is sufficient.

SEE ALSO
========

   `Tk::composite|Tk::composite' in this node, `Tk::options|Tk::options'
in this node

create a standard widget demonstration window.
**********************************************

NAME
====

   WidgetDemo() - create a standard widget demonstration window.

SYNOPSIS
========

     use WidgetDemo;
     my $demo_widget = $MW->WidgetDemo(
         -name             => $demo,
         -text             => 'Learn how to write a widget demonstration!',
         -title            => 'WidgetDemo Demonstration',
         -iconname         => 'WidgetDemo',
         -geometry_manager => 'grid',
         -font             => $FONT,
     );
     $TOP = $demo_widget->Top;	# get grid master

DESCRIPTION
===========

   This constructor builds a standard widget demonstration window,
composed of three frames.  The top frame contains descriptive
demonstration text.  The bottom frame contains the "Dismiss" and "See
Code" buttons.  The middle frame is demonstration container, which came be
managed by either the pack or grid geometry manager.

   The -text attribute is supplied to a Label widget, which is
left-adjusted with -wraplength set to 4 inches.  If you require different
specifications then pass an array to -text; the first element is the text
string and the remaining array elements are standard Label widget
attributes - WidgetDemo will rearrange things as required..

     -text => ['Hello World!', qw/-wraplength 6i/],

METHODS
=======

$demo_widget->Top;
------------------

   Returns the frame container reference for the demonstration.  Treat
this as the top of your window hierarchy, a "main window".

AUTHOR
======

   Stephen O. Lidie <lusol@Lehigh.EDU>

HISTORY
=======

   lusol@Lehigh.EDU, LUCC, 97/02/11 lusol@Lehigh.EDU, LUCC, 97/06/07

COPYRIGHT
=========

   Copyright (C) 1997 - 1997 Stephen O. Lidie. All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Miscellaneous event facilities: define virtual events and generate events
*************************************************************************

NAME
====

   Tk::event - Miscellaneous event facilities: define virtual events and
generate events

   $widget->eventAction(?*arg, arg, ...*?);

DESCRIPTION
===========

   The eventAction methods provides several facilities for dealing with
window system events, such as defining virtual events and synthesizing
events.  Virtual events are shared by all widgets of the same
*MainWindow*.  Different `MainWindow|Tk::MainWindow' in this nodes can
have different virtual event.

   The following methods are currently supported:

$widget->*eventAdd*(*'<<**virtual**>>'**, sequence *?,*sequence, ...*?)
     Associates the virtual event *virtual* with the physical event
     sequence(s) given by the sequence arguments, so that the virtual
     event will trigger whenever any one of the sequences occurs.  Virtual
     may be any string value and sequence may have any of the values
     allowed for the sequence argument to the `bind|Tk::bind' in this node
     method.  If *virtual* is already defined, the new physical event
     sequences add to the existing sequences for the event.

$widget->*eventDelete*(*'<<**virtual**>>'* ?,*sequence,* *sequence, ...*?)
     Deletes each of the sequences from those associated with the virtual
     event given by *virtual*.  Virtual may be any string value and
     sequence may have any of the values allowed for the sequence argument
     to the `bind|Tk::bind' in this node method.  Any sequences not
     currently associated with *virtual* are ignored.  If no sequence
     argument is provided, all physical event sequences are removed for
     *virtual*, so that the virtual event will not trigger anymore.

$widget->*eventGenerate*(event ?,*option => value, option => value, ...*?)
     Generates a window event and arranges for it to be processed just as
     if it had come from the window system.  *$window* is a reference to
     the window for which the event will be generated.  Event provides a
     basic description of the event, such as *<Shift-Button-2>* or
     *<<Paste>>*.  If Window is empty the whole screen is meant, and
     coordinates are relative to the screen.  Event may have any of the
     forms allowed for the sequence argument of the `bind|Tk::bind' in
     this node method except that it must consist of a single event
     pattern, not a sequence.  *Option-value* pairs may be used to specify
     additional attributes of the event, such as the x and y mouse
     position; see `"EVENT FIELDS"' in this node below.  If the *-when*
     option is not specified, the event is processed immediately:  all of
     the handlers for the event will complete before the *eventGenerate*
     method returns.  If the *-when* option is specified then it
     determines when the event is processed.

$widget->*eventInfo*(?'*<<**virtual**>>'*?)
     Returns information about virtual events.  If the *<<**virtual**>>*
     argument is omitted, the return value is a list of all the virtual
     events that are currently defined.  If *<<**virtual**>>* is specified
     then the return value is a list whose elements are the physical event
     sequences currently defined for the given virtual event;  if the
     virtual event is not defined then undef is returned.

EVENT FIELDS
============

   The following options are supported for the *eventGenerate* method.
These correspond to the "%" expansions allowed in binding callback for the
`bind|Tk::bind' in this node method.

*-above* => window
     Window specifies the above field for the event, either as a window
     path name or as an integer window id.  Valid for Configure events.
     Corresponds to the `%a|Tk::bind' in this node substitution for
     binding scripts.

*-borderwidth* => size
     Size must be a screen distance;  it specifies the *border_width*
     field for the event.  Valid for Configure events.  Corresponds to the
     `%B|Tk::bind' in this node substitution for binding scripts.

*-button* => number
     Number must be an integer;  it specifies the detail field for a
     *ButtonPress* or ButtonRelease event, overriding any button  number
     provided in the base event argument.  Corresponds to the
     `%b|Tk::bind' in this node substitution for binding scripts.

*-count* => number
     Number must be an integer;  it specifies the count field for the
     event.  Valid for *Expose* events.  Corresponds to the `%c|Tk::bind'
     in this node substitution for binding scripts.

*-detail* => detail
     *Detail* specifies the detail field for the event and must be one of
     the following:

          NotifyAncestor	NotifyNonlinearVirtual
          NotifyDetailNone	NotifyPointer
          NotifyInferior	NotifyPointerRoot
          NotifyNonlinear	NotifyVirtual

     Valid for Enter, *Leave*, *FocusIn* and *FocusOut* events.
     Corresponds to the `%d|Tk::bind' in this node substitution for
     binding scripts.

*-focus** boolean*
     Boolean must be a boolean value;  it specifies the focus field for
     the event.  Valid for Enter and *Leave* events.  Corresponds to the
     `%f|Tk::bind' in this node substitution for binding scripts.

*-height** size*
     Size must be a screen distance;  it specifies the height field for
     the event.  Valid for Configure events.  Corresponds to the
     `%h|Tk::bind' in this node substitution for binding scripts.

*-keycode** number*
     Number  must be an integer;  it specifies the *keycode* field for the
     event.  Valid for *KeyPress* and *KeyRelease* events.  Corresponds to
     the `%k|Tk::bind' in this node substitution for binding scripts.

*-keysym** name*
     Name must be the name of a valid keysym, such as g, space, or Return;
     its corresponding keycode value is used as the *keycode* field for
     event, overriding any detail specified in the base event argument.
     Valid for *KeyPress* and *KeyRelease* events.  Corresponds to the
     `%K|Tk::bind' in this node substitution for binding scripts.

*-mode** notify*
     *Notify* specifies the mode field for the event and must be one of
     *NotifyNormal*, *NotifyGrab*, *NotifyUngrab*, or *NotifyWhileGrabbed*.
     Valid for Enter, *Leave*, *FocusIn*, and *FocusOut* events.
     Corresponds to the `%m|Tk::bind' in this node substitution for
     binding scripts.

*-override** boolean*
     Boolean must be a boolean value;  it specifies the
     *override_redirect* field for the event.  Valid for Map, *Reparent*,
     and Configure events.  Corresponds to the `%o|Tk::bind' in this node
     substitution for binding scripts.

*-place** where*
     Where specifies the *place* field for the event;  it must be either
     *PlaceOnTop* or *PlaceOnBottom*.  Valid for *Circulate* events.
     Corresponds to the `%p|Tk::bind' in this node substitution for
     binding scripts.

*-root** window*
     Window must be either a window path name or an integer window
     identifier;  it specifies the root field for the event.  Valid for
     *KeyPress*, *KeyRelease*, *ButtonPress*, ButtonRelease, Enter,
     *Leave*, and *Motion* events.  Corresponds to the `%R|Tk::bind' in
     this node substitution for binding scripts.

*-rootx** coord*
     *Coord* must be a screen distance;  it specifies the *x_root* field
     for the event.  Valid for *KeyPress*, *KeyRelease*, *ButtonPress*,
     ButtonRelease, Enter, *Leave*, and *Motion* events.  Corresponds to
     the `%X|Tk::bind' in this node substitution for binding scripts.

*-rooty** coord*
     *Coord* must be a screen distance;  it specifies the *y_root* field
     for the event.  Valid for *KeyPress*, *KeyRelease*, *ButtonPress*,
     ButtonRelease, Enter, *Leave*, and *Motion* events.  Corresponds to
     the `%Y|Tk::bind' in this node substitution for binding scripts.

*-sendevent** boolean*
     Boolean must be a boolean value;  it specifies the *send_event* field
     for the event.  Valid for all events.  Corresponds to the
     `%E|Tk::bind' in this node substitution for binding scripts.

*-serial** number*
     Number must be an integer;  it specifies the serial field for the
     event.  Valid for all events.  Corresponds to the `%#|Tk::bind' in
     this node substitution for binding scripts.

*-state** state*
     State specifies the state field for the event.  For *KeyPress*,
     *KeyRelease*, *ButtonPress*, ButtonRelease, Enter, *Leave*, and
     *Motion* events it must be an integer value.  For *Visibility* events
     it must be one of *VisibilityUnobscured*,
     *VisibilityPartiallyObscured*, or *VisibilityFullyObscured*.  This
     option overrides any modifiers such as Meta or Control specified in
     the base event.  Corresponds to the `%s|Tk::bind' in this node
     substitution for binding scripts.

*-subwindow** window*
     Window specifies the *subwindow* field for the event, either as a
     path name for a Tk widget or as an integer window identifier.  Valid
     for *KeyPress*, *KeyRelease*, *ButtonPress*, ButtonRelease, Enter,
     *Leave*, and *Motion* events.  Similar to `%S|Tk::bind' in this node
     substitution for binding scripts.

*-time** integer*
     Integer must be an integer value;  it specifies the time field for
     the event.  Valid for *KeyPress*, *KeyRelease*, *ButtonPress*,
     ButtonRelease, Enter, *Leave*, *Motion*, and Property events.
     Corresponds to the `%t|Tk::bind' in this node substitution for
     binding scripts.

*-warp** boolean*
     boolean must be a boolean value;  it specifies whether the screen
     pointer should be warped as well.  Valid for *KeyPress*,
     *KeyRelease*, *ButtonPress*, ButtonRelease, and *Motion* events.

*-width** size*
     Size must be a screen distance;  it specifies the width field for the
     event.  Valid for Configure events.  Corresponds to the `%w|Tk::bind'
     in this node substitution for binding scripts.

*-when** when*
     When determines when the event will be processed;  it must have one
     of the following values:

    now
          Process the event immediately, before the command returns.  This
          also happens if the *-when* option is omitted.

    tail
          Place the event on perl/Tk's event queue behind any events
          already queued for this application.

    head
          Place the event at the front of perl/Tk's event queue, so that it
          will be handled before any other events already queued.

    mark
          Place the event at the front of perl/Tk's event queue but behind
          any other events already queued with *-when mark*.  This option
          is useful when generating a series of events that should be
          processed in order but at the front of the queue.

-x* coord*
     *Coord* must be a screen distance;  it specifies the x field for the
     event.  Valid for *KeyPress*, *KeyRelease*, *ButtonPress*,
     ButtonRelease, *Motion*, Enter, *Leave*, *Expose*, Configure,
     *Gravity*, and *Reparent* events.  Corresponds to the the
     `%x|Tk::bind' in this node substitution for binding scripts.  If
     Window is empty the coordinate is relative to the screen, and this
     option corresponds to the `%X|Tk::bind' in this node substitution for
     binding scripts.

-y* coord*
     *Coord* must be a screen distance;  it specifies the y field for the
     event.  Valid for *KeyPress*, *KeyRelease*, *ButtonPress*,
     ButtonRelease, *Motion*, Enter, *Leave*, *Expose*, Configure,
     *Gravity*, and *Reparent* events.  Corresponds to the the
     `%y|Tk::bind' in this node substitution for binding scripts.  If
     Window is empty the coordinate is relative to the screen, and this
     option corresponds to the `%Y|Tk::bind' in this node substitution for
     binding scripts.

     Any options that are not specified when generating an event are filled
     with the value 0, except for serial, which is filled with the next X
     event serial number.

VIRTUAL EVENT EXAMPLES
======================

   In order for a virtual event binding to trigger, two things must
happen.  First, the virtual event must be defined with the *eventAdd*
method.  Second, a binding must be created for the virtual event with the
bind method.  Consider the following virtual event definitions:

     $widget->eventAdd('<<Paste>>' => '<Control-y>');
     $widget->eventAdd('<<Paste>>' => '<Button-2>');
     $widget->eventAdd('<<Save>>' => '<Control-X><Control-S>');
     $widget->eventAdd('<<Save>>' => '<Shift-F12>');

   In the bind method, a virtual event can be bound like any other builtin
event type as follows:

     $entry->bind('Tk::Entry', '<<Paste>>' => sub {
     		$entry->Insert($entry->selectionGet) });

   The double angle brackets are used to specify that a virtual event is
being bound.  If the user types Control-y or presses button 2, or if a
*<<Paste>>* virtual event is synthesized with *eventGenerate*, then the
*<<Paste>>* binding will be invoked.

   If a virtual binding has the exact same sequence as a separate physical
binding, then the physical binding will take precedence.  Consider the
following example:

     $mw->eventAdd('<<Paste>>' => '<Control-y>','<Meta-Control-y>');
     $mw->bind('Tk::Entry', '<Control-y>' => sub{print 'Control-y'});
     $mw->bind('Tk::Entry', '<<Paste>>'   => sub{print 'Paste'});

   When the user types Control-y the *<Control-y>* binding will be
invoked, because a physical event is considered more specific than a
virtual event, all other things being equal.  However, when the user types
Meta-Control-y the *<<Paste>>* binding will be invoked, because the Meta
modifier in the physical pattern associated with the virtual binding is
more specific than the *<Control-y*> sequence for the physical event.

   Bindings on a virtual event may be created before the virtual event
exists.  Indeed, the virtual event never actually needs to be defined, for
instance, on platforms where the specific virtual event would meaningless
or ungeneratable.

   When a definition of a virtual event changes at run time, all windows
will respond immediately to the new definition.  Starting from the
preceding example, if the following code is executed:

     $entry->bind(ref($entry), '<Control-y>' => undef);
     $entry->eventAdd('<<Paste>>' => '<Key-F6>');

   the behavior will change such in two ways.  First, the shadowed
*<<Paste>>* binding will emerge.  Typing Control-y will no longer invoke
the *<Control-y>* binding, but instead invoke the virtual event
*<<Paste>>*.  Second, pressing the F6 key will now also invoke the
*<<Paste>>* binding.

SEE ALSO
========

   `Tk::bind|Tk::bind' in this node `Tk::callbacks|Tk::callbacks' in this
node

KEYWORDS
========

   event, binding, define, handle, virtual event

End the application
*******************

NAME
====

   Tk::exit - End the application

     use Tk qw(exit);
     ...
     B<exit>?(I<returnCode>)?;

DESCRIPTION
===========

   Terminate the process, returning *returnCode* to the system as the exit
status.  If *returnCode* isn't specified then it defaults to 0.

   If calling exit from code invoked via a Tk callback then this Tk
version of exit cleans up more reliably than using the perl exit.

KEYWORDS
========

   exit, process

Execute a callback when a filehandle becomes readable or writable
*****************************************************************

NAME
====

   Tk::fileevent - Execute a callback when a filehandle becomes readable
or writable

   $widget->*fileevent*(*fileHandle*,readable?,callback?)

   $widget->*fileevent*(*fileHandle*,writable?,callback?)

DESCRIPTION
===========

   This command is used to create *file event handlers*.  A file event
handler is a binding between a filehandle and a callback, such that the
callback is evaluated whenever the filehandle becomes readable or
writable.  File event handlers are most commonly used to allow data to be
received from another process on an event-driven basis, so that the
receiver can continue to interact with the user while waiting for the data
to arrive.  If an application invokes `<>', sysread or read on a blocking
filehandle when there is no input data available, the process will block;
until the input data arrives, it will not be able to service other events,
so it will appear to the user to "freeze up".  With *fileevent*, the
process can tell when data is present and only invoke gets or read when
they won't block.

   The *fileHandle* argument to *fileevent* refers to an open filehandle,
such as the return value from a previous open or socket command.  If the
callback argument is specified, then *fileevent* creates a new event
handler:  callback will be evaluated whenever the filehandle becomes
readable or writable (depending on the argument to *fileevent*).  In this
case *fileevent* returns an empty string.  The readable and writable event
handlers for a file are independent, and may be created and deleted
separately.  However, there may be at most one readable and one writable
handler for a file at a given time in a given interpreter.  If *fileevent*
is called when the specified handler already exists in the invoking
interpreter, the new callback replaces the old one.

   If the callback argument is not specified, *fileevent* returns the
current callback for *fileHandle*, or an empty string if there is none.
If the callback argument is specified as an empty string then the event
handler is deleted, so that no callback will be invoked.  A file event
handler is also deleted automatically whenever its filehandle is closed or
its interpreter is deleted.

   A filehandle is considered to be readable if there is unread data
available on the underlying device.  A filehandle is also considered to be
readable if an end of file or error condition is present on the underlying
file or device.  It is important for callback to check for these conditions
and handle them appropriately;  for example, if there is no special check
for end of file, an infinite loop may occur where callback reads no data,
returns, and is immediately invoked again.

   A filehandle is considered to be writable if at least one byte of data
can be written to the underlying file or device without blocking, or if an
error condition is present on the underlying file or device.

   Event-driven I/O works best for filehandles that have been placed into
nonblocking mode.  In blocking mode, a print command may block if you give
it more data than the underlying file or device can accept, and a `<>',
sysread or read command will block if you attempt to read more data than
is ready;  no events will be processed while the commands block.  In
nonblocking mode print, `<>', sysread and read never block.  See the
documentation for the individual commands for information on how they
handle blocking and nonblocking filehandles.

   The callback for a file event is executed in the context of $widget
with which *fileevent* was invoked.  If an error occurs while executing
the callback then the Tk/Error, mechanism is used to
report the error.  In addition, the file event handler is deleted if it
ever returns an error;  this is done in order to prevent infinite loops
due to buggy handlers.

BUGS
====

   On windows platforms *fileevent* is limited in the types of filehandles
that behave correctly. Making filefhandles non-blocking is only implemented
on a subset of UNIX platforms (see Tk/IO).

CREDITS
=======

   *fileevent* is based on the *addinput* command created by Mark Diekhans.

SEE ALSO
========

   `Tk::IO|Tk::IO' in this node `Tk::callbacks|Tk::callbacks' in this node

KEYWORDS
========

   asynchronous I/O, blocking, filehandle, event handler, nonblocking,
readable, callback, writable.

Manage the input focus
**********************

NAME
====

   focus - Manage the input focus

      $widget->focus

      $widget->focusOption

      $widget->*focusNext*

      $widget->*focusPrev*

      $widget->*focusFollowsMouse*

DESCRIPTION
===========

   The focus methods are used to manage the Tk input focus.  At any given
time, one window on each display is designated as the *focus window*;  any
key press or key release events for the display are sent to that window.
It is normally up to the window manager to redirect the focus among the
top-level windows of a display.  For example, some window managers
automatically set the input focus to a top-level window whenever the mouse
enters it;  others redirect the input focus only when the user clicks on a
window.  Usually the window manager will set the focus only to top-level
windows, leaving it up to the application to redirect the focus among the
children of the top-level.

   Tk remembers one focus window for each top-level (the most recent
descendant of that top-level to receive the focus);  when the window
manager gives the focus to a top-level, Tk automatically redirects it to
the remembered window.  Within a top-level Tk uses an explicit focus model
by default.  Moving the mouse within a top-level does not normally change
the focus;  the focus changes only when a widget decides explicitly to
claim the focus (e.g., because of a button click), or when the user types
a key such as Tab that moves the focus.

   The method *focusFollowsMouse* may be invoked to create an *implicit*
focus model:  it reconfigures Tk so that the focus is set to a window
whenever the mouse enters it.  The methods *focusNext* and *focusPrev*
implement a focus order among the windows of a top-level;  they are used
in the default bindings for Tab and Shift-Tab, among other things.

   The focus methods can take any of the following forms:

$widget->*focusCurrent*
     Returns the focus window on the display containing the $widget,  or
     an empty string if no window in this application has the focus on
     that display.

$widget->focus
     If the application currently has the input focus on $widget's
     display, this command resets the input focus for $widget's display to
     $widget and returns an empty string.  If the application doesn't
     currently have the  input focus on $widget's display, $widget will be
     remembered as the focus for its top-level;  the next time the focus
     arrives at the top-level, Tk will redirect it to $widget.

$widget->*focusForce*
     Sets the focus of $widget's display to $widget, even if the
     application doesn't currently have the input focus for the display.
     This command should be used sparingly, if at all.  In normal usage,
     an application should not claim the focus for itself;  instead, it
     should wait for the window manager to give it the focus.

$widget->*focusLast*
     Returns the name of the most recent window to have the input focus
     among all the windows in the same top-level as $widget.  If no window
     in that top-level has ever had the input focus, or if the most recent
     focus window has been deleted, then the top-level is returned.  The
     return value is the window that will receive the input focus the next
     time the window manager gives the focus to the top-level.

$widget->*focusNext*
$widget->*focusPrev*
     *focusNext* is a utility method used for keyboard traversal, but can
     be useful in other contexts.  It sets the focus to the "next" window
     after $widget in focus order.  The focus order is determined by the
     stacking order of windows and the structure of the window hierarchy.
     Among siblings, the focus order is the same as the stacking order,
     with the lowest window being first.  If a window has children, the
     window is visited first, followed by its children (recursively),
     followed by its next sibling.  Top-level windows other than $widget
     are skipped, so that *focusNext* never returns a window in a
     different top-level from $widget.

     After computing the next window, *focusNext* examines the window's
     *-takefocus* option to see whether it should be skipped.  If so,
     *focusNext* continues on to the next window in the focus order, until
     it eventually finds a window that will accept the focus or returns
     back to $widget.

     *focusPrev* is similar to *focusNext* except that it sets the focus
     to the window just before $widget in the focus order.

$widget->*focusFollowsMouse*
     *focusFollowsMouse* changes the focus model for the application to an
     implicit one where the window under the mouse gets the focus.  After
     this procedure is called, whenever the mouse enters a window Tk will
     automatically give it the input focus.  The focus command may be used
     to move the focus to a window other than the one under the mouse, but
     as soon as the mouse moves into a new window the focus will jump to
     that window.  Note: at present there is no built-in support for
     returning the application to an explicit focus model;  to do this
     you'll have to write a script that deletes the bindings created by
     *focusFollowsMouse*.

QUIRKS
======

   When an internal window receives the input focus, Tk doesn't actually
set the X focus to that window;  as far as X is concerned, the focus will
stay on the top-level window containing the window with the focus.
However, Tk generates FocusIn and FocusOut events just as if the X focus
were on the internal window.   This approach gets around a number of
problems that would occur if the X focus were actually moved; the fact
that the X focus is on the top-level is invisible unless you use C code to
query the X server directly.

CAVEATS
=======

   Note that for the Canvas widget, the call to focus has to be fully
qualified. This is because there is already a focus method for the Canvas
widget, which sets the focus on individual canvas tags.

       *$canvas*->*Tk::focus*

KEYWORDS
========

   events, focus, keyboard, top-level, window manager

Geometry manager based on attachment rules
******************************************

NAME
====

   Tk::form - Geometry manager based on attachment rules

       $widget->form?(args)?

       $widget->formOption?(args)?

DESCRIPTION
===========

   The form method is used to communicate with the form Geometry Manager,
a geometry manager that arranges the geometry of the children in a parent
window according to attachment rules. The form geometry manager is very
flexible and powerful; it can be used to emulate all the existing features
of the Tk packer and placer geometry managers (see `pack|Tk::pack' in this
node, `place|Tk::place' in this node).  The form method can have any of
several forms, depending on Option:

*$slave*->form?(options)?
     Sets or adjusts the attachment values of the slave window according
     to the *-option*=>value argument pairs.

    -b => attachment
          Abbreviation for the *-bottom* option.

    *-bottom* => attachment
          Specifies an attachment for the bottom edge of the slave window.
          The attachment must specified according to `"SPECIFYING
          ATTACHMENTS"' in this node below.

    *-bottomspring* => weight
          Specifies the weight of the spring at the bottom edge of the
          slave window. See `"USING SPRINGS"' in this node below.

    *-bp* => value
          Abbreviation for the *-padbottom* option.

    *-bs* => weight
          Abbreviation for the *-bottomspring* option.

    *-fill* => style
          Specifies the fillings when springs are used for this widget. The
          value must be x, y, both or none.

    *-in* => *$master*
          Places the slave window into the specified *$master* window. If
          the slave was originally in another master window, all
          attachment values with respect to the original master window are
          discarded. Even if the attachment values are the same as in the
          original master window, they need to be specified again.  The
          *-in* flag, when needed, must appear as the first flag of
          options. Otherwise an error is generated.

    -l => attachment
          Abbreviation for the *-left* option.

    *-left* => attachment
          Specifies an attachment for the left edge of the slave window.
          The attachment must specified according to `"SPECIFYING
          ATTACHMENTS"' in this node below.

    *-leftspring* => weight
          Specifies the weight of the spring at the left edge of the slave
          window. See `"USING SPRINGS"' in this node below.

    *-lp* => value
          Abbreviation for the *-padleft* option.

    *-ls* => weight
          Abbreviation for the *-leftspring* option.

    *-padbottom* => value
          Specifies the amount of external padding to leave on the bottom
          side of the slave. The value may have any of the forms
          acceptable to *Tk_GetPixels*.

    *-padleft* => value
          Specifies the amount of external padding to leave on the left
          side of the slave.

    *-padright* => value
          Specifies the amount of external padding to leave on the right
          side of the slave.

    *-padtop* => value
          Specifies the amount of external padding to leave on the top
          side of the slave.

    *-padx* => value
          Specifies the amount of external padding to leave on both the
          left and the right sides of the slave.

    *-pady* => value
          Specifies the amount of external padding to leave on both the
          top and the bottom sides of the slave.

    -r => attachment
          Abbreviation for the *-right* option.

    *-right* => attachment
          Specifies an attachment for the right edge of the slave window.
          The attachment must specified according to `"SPECIFYING
          ATTACHMENTS"' in this node below.

    *-rightspring* => weight
          Specifies the weight of the spring at the right edge of the slave
          window. See `"USING SPRINGS"' in this node below.

    *-rp*  => value
          Abbreviation for the *-padright* option.

    *-rs* => weight
          Abbreviation for the *-rightspring* option.

    -t => attachment
          Abbreviation for the *-top* option.

    *-top* => attachment
          Specifies an attachment for the top edge of the slave window. The
          attachment must specified according to `"SPECIFYING
          ATTACHMENTS"' in this node below.

    *-topspring* => weight
          Specifies the weight of the spring at the top edge of the slave
          window. See `"USING SPRINGS"' in this node below.

    *-tp* => value
          Abbreviation for the *-padtop* option.

    *-ts* => weight
          Abbreviation for the *-topspring* option.

*$master*->*formCheck*
     This method checks whether there is circular dependency in the
     attachments of the master's slaves (see `"CIRCULAR DEPENDENCY"' in
     this node below).  It returns the Boolean value TRUE if it discover
     circular dependency and FALSE otherwise.

*$slave*->*formForget*
     Removes the slave from its master and unmaps its window.  The slave
     will no longer be managed by form. All attachment values with respect
     to its master window are discarded. If another slave is attached to
     this slave, then the attachment of the other slave will be changed to
     grid attachment based on its geometry.

*$master*->*formGrid*?(*x_size, y_size*)?
     When *x_size* and *y_size* are given, this method returns the number
     of grids of the *$master* window in a pair of integers of the form
     (*x_size, y_size*). When both *x_size* and *y_size* are given, this
     method changes the number of horizontal and vertical grids on the
     master window.

*$slave*->*formInfo*?(*-option)*?
     Queries the attachment options of a slave window. *-option* can be
     any of the options accepted by the form method. If *-option* is
     given, only the value of that option is returned.  Otherwise, this
     method returns a list whose elements are the current configuration
     state of the slave given in the same *option-value* form that might
     be specified to form. The first two elements in this list list are
     "*-in*=>*$master*" where *$master* is the slave's master window.

*$master*->*formSlaves*
     Returns a list of all of the slaves for the master window. The order
     of the slaves in the list is the same as their order in the packing
     order. If master has no slaves then an empty string is returned.

SPECIFYING ATTACHMENTS
======================

   One can specify an attachment for each side of a slave window managed
by form. An attachment is specified in the the form "-*side* =>
[*anchor_point*, offset]". -*side* can be one of *-top*, *-bottom*,
*-left* or *-right*.

   Offset is given in screen units (i.e. any of the forms acceptable to
*Tk_GetPixels*).  A positive offset indicates shifting to a position to
the right or bottom of an anchor point. A negative offset indicates
shifting to a position to the left or top of an anchor point.

   *Anchor_point* can be given in one of the following forms:

*Grid Attachment*
     The master window is divided into a number of horizontal and vertical
     grids. By default the master window is divided into 100x100 grids; the
     number of grids can be adjusted by the *formGrid* method. A grid
     attachment anchor point is given by a % sign followed by an integer
     value. For example, *'%0'* specifies the first grid line (the top or
     left edge of the master window). *'%100'* specifies the last grid
     line (the bottom or right edge of the master window).

*Opposite Side Attachment*
     Opposite attachment specifies an anchor point located on the
     *opposite* side of another slave widget, which must be managed by
     form in the same master window. An opposite attachment anchor point
     is given by the name of another widget. For example,
     "$b->form(*-top*=>[*$a*,0])" attaches the top side of the widget $b
     to the bottom of the widget *$a*.

*Parallel Side Attachment*
     Opposite attachment specifies an anchor point located on the *same*
     side of another slave widget, which must be managed by form in the
     same master window. An parallel attachment anchor point is given by
     the sign *E<amp*> follwed by the name of another widget.  For
     example, "$b->form(*-top*=>['&',*$a*,0])" attaches the top side of
     the widget $b to the top of the widget *$a*, making the top sides of
     these two widgets at the same vertical position in their parent
     window.

*No Attachment*
     Specifies a side of the slave to be attached to nothing, indicated by
     the keyword none. When the none anchor point is given, the offset
     must be zero (or not present).  When a side of a slave is attached to
     *['none', 0]*, the position of this side is calculated by the
     position of the other side and the natural size of the slave. For
     example, if a the left side of a widget is attached to *['%0', 100]*,
     its right side attached to *['none', 0]*, and the natural size of the
     widget is 50 pixels, the right side of the widget will be positioned
     at pixel *['%0', 149]*.  When both *-top* and *-bottom* are attached
     to none, then by default *-top* will be attached to *['%0', 0]*. When
     both *-left* and *-right* are attached to none, then by default
     *-left* will be attached to *['%0', 0]*.

   Shifting effects can be achieved by specifying a non-zero offset with
an anchor point. In the following example, the top side of widget *\$b* is
attached to the bottom of *\$a*; hence *\$b* always appears below *\$a*.
Also, the left edge of *\$b* is attached to the left side of *\$a* with a
10 pixel offest.  Therefore, the left edge of *\$b* is always shifted 10
pixels to the right of *\$a*'s left edge:

       $b->form(*-left*=>[*$a*,10], *-top*=>[*$a*,0]);

ABBREVIATIONS:
--------------

   Certain abbreviations can be made on the attachment specifications:
First an offset of zero can be omitted.  Thus, the following two lines are
equivalent:

       $b->form(*-top*=>[*$a*,0], *-right*=>['%100',0]);

       $b->form(*-top*=>[*$a*], *-right*=>'%100');

   In the second case, when the anchor point is omitted, the offset must
be given. A default anchor point is chosen according to the value of the
offset. If the anchor point is 0 or positive, the default anchor point %0
is used; thus, "$b->form(*-top*=>15)" attaches the top edge of $b to a
position 15 pixels below the top edge of the master window. If the anchor
point is "-0" or negative, the default anchor point *%100* is used; thus,
"*$a*->form(*-right*=>-2)" attaches the right edge of *\$a* to a position
2 pixels to the left of the master window's right edge.  An further example
below shows a method with its equivalent abbreviation.

       $b->form(*-top*=>['%0',10], *-bottom*=>['%100',0]);

       $b->form(*-top*=>10, *-bottom*=>-0);

USING SPRINGS
=============

   To be written.

ALGORITHM OF FORM
=================

   form starts with any slave in the list of slaves of the master window.
Then it tries to determine the position of each side of the slave.

   If the attachment of a side of the slave is grid attachment, the
position of the side is readily determined.

   If the attachment of this side is none, then form tries to determine
the position of the opposite side first, and then use the position of the
opposite side and the natural size of the slave to determine the position
of this side.

   If the attachment is opposite or parallel widget attachments, then form
tries to determine the positions of the other widget first, and then use
the positions of the other widget and the natural size of the slave
determine the position of this side. This recursive algorithmis carried on
until the positions of all slaves are determined.

CIRCULAR DEPENDENCY
===================

   The algorithm of form will fail if a circular dependency exists in the
attachments of the slaves. For example:

       $c->form(*-left*=>$b);

       $b->form(*-right*=>$c);

   In this example, the position of the left side of $b depends on the
right side of $c, which in turn depends on the left side of $b.

   When a circular dependency is discovered during the execution of the
form algorithm, form will generate a background error and the geometry of
the slaves are undefined (and will be arbitrary). Notice that form only
executes the algorithm when the specification of the slaves' attachments
is complete.  Therefore, it allows intermediate states of circular
dependency during the specification of the slaves' attachments.  Also,
unlike the Motif Form manager widget, form defines circular dependency as
"*dependency in the same dimension*".  Therefore, the following code
fragment will does not have circular dependency because the two widgets do
not depend on each other in the same dimension ($b depends $c in the
horizontal dimension and $c depends on $b in the vertical dimension):

       $b->form(*-left*=>$c);

       $c->form(*-top*=>$b);

BUGS
====

   Springs have not been fully implemented yet.

SEE ALSO
========

   `Tk::grid|Tk::grid' in this node `Tk::pack|Tk::pack' in this node
`Tk::place|Tk::place' in this node

KEYWORDS
========

   geometry manager, form, attachment, spring, propagation, size, pack,
tix, master, slave

pop up a dialog box for the user to select a file to open or save.
******************************************************************

NAME
====

   getOpenFile, getSaveFile - pop up a dialog box for the user to select a
file to open or save.

       $widget->*getOpenFile*(?*-option*=>value, ...>?)

       $widget->*getSaveFile*(?*-option*=>value, ...>?)

DESCRIPTION
===========

   The methods *getOpenFile* and *getSaveFile* pop up a dialog box for the
user to select a file to open or save.

   The *getOpenFile* method is usually associated with the Open command in
the File menu.  Its purpose is for the user to select an existing file
*only*.  If the user enters an non-existent file, the dialog box gives the
user an error prompt and requires the user to give an alternative
selection. If an application allows the user to create new files, it
should do so by providing a separate New menu command.

   The *getSaveFile* method is usually associated with the Save as command
in the File menu. If the user enters a file that already exists, the
dialog box prompts the user for confirmation whether the existing file
should be overwritten or not.

   If the user selects a file, both *getOpenFile* and *getSaveFile* return
the full pathname of this file. If the user cancels the operation, both
commands return an undefined value.

   The following *option-value* pairs are possible as command line
arguments to these two commands:

*-defaultextension* => *extension*
     Specifies a string that will be appended to the filename if the user
     enters a filename without an extension. The default value is the empty
     string, which means no extension will be appended to the filename in
     any case. This option is ignored on the Macintosh platform, which
     does not require extensions to filenames.

*-filetypes* => [*filePattern* ?, ...?]
     If a File types listbox exists in the file dialog on the particular
     platform, this option gives the filetypes in this listbox. When the
     user choose a filetype in the listbox, only the files of that type
     are listed. If this option is unspecified, or if it is set to the
     empty list, or if the File types listbox is not supported by the
     particular platform then all files are listed regardless of their
     types. See `"SPECIFYING FILE PATTERNS"' in this node below for a
     discussion on the contents of *filePattern*s.

*-initialdir* => directory
     Specifies that the files in directory should be displayed when the
     dialog pops up. If this parameter is not specified, then the files in
     the current working directory are displayed.  This option may not
     always work on the Macintosh.  This is not a bug.  Rather, the
     *General Controls* control panel on the Mac allows the end user to
     override the application default directory.

*-initialfile* => filename
     Specifies a filename to be displayed in the dialog when it pops up.
     This option is ignored by the *getOpenFile* method.

*-title* => *titleString*
     Specifies a string to display as the title of the dialog box. If this
     option is not specified, then a default title is displayed. This
     option is ignored on the Macintosh platform.

SPECIFYING FILE PATTERNS
========================

   The *filePattern*s given by the *-filetypes* option are a list of file
patterns. Each file pattern is a list of the form

     typeName [extension ?extension ...?] ?[macType ?macType ...?]?

   *typeName* is the name of the file type described by this file pattern
and is the text string that appears in the File types listbox. *extension*
is a file extension for this file pattern.  *macType* is a four-character
Macintosh file type. The list of *macType*s is optional and may be omitted
for applications that do not need to execute on the Macintosh platform.

   Several file patterns may have the same *typeName,* in which case they
refer to the same file type and share the same entry in the listbox. When
the user selects an entry in the listbox, all the files that match at
least one of the file patterns corresponding to that entry are listed.
Usually, each file pattern corresponds to a distinct type of file. The use
of more than one file patterns for one type of file is necessary on the
Macintosh platform only.

   On the Macintosh platform, a file matches a file pattern if its name
matches at least one of the *extension*(s) AND it belongs to at least one
of the *macType*(s) of the file pattern. For example, the *C Source Files*
file pattern in the sample code matches with files that have a *\.c*
extension AND belong to the *macType* TEXT. To use the OR rule instead,
you can use two file patterns, one with the *extensions* only and the
other with the *macType* only. The *GIF Files* file type in the sample
code matches files that EITHER have a *\.gif* extension OR belong to the
*macType* *GIFF*.

   On the Unix and Windows platforms, a file matches a file pattern if its
name matches at at least one of the *extension*(s) of the file pattern.
The *macType*s are ignored.

SPECIFYING EXTENSIONS
=====================

   On the Unix and Macintosh platforms, extensions are matched using
glob-style pattern matching. On the Windows platforms, extensions are
matched by the underlying operating system. The types of possible
extensions are: (1) the special extension * matches any file; (2) the
special extension "" matches any files that do not have an extension
(i.e., the filename contains no full stop character); (3) any character
string that does not contain any wild card characters (* and ?).

   Due to the different pattern matching rules on the various platforms,
to ensure portability, wild card characters are not allowed in the
extensions, except as in the special extension *. Extensions without a
full stop character (e.g, ~) are allowed but may not work on all platforms.

EXAMPLE
=======

     my $types = [
         ['Text Files',       ['.txt', '.text']],
         ['TCL Scripts',      '.tcl'           ],
         ['C Source Files',   '.c',      'TEXT'],
         ['GIF Files',        '.gif',          ],
         ['GIF Files',        '',        'GIFF'],
         ['All Files',        '*',             ],
     ];
     my $filename = $widget->getOpenFile(-filetypes=>$types);

     if ($filename ne "") {
         # Open the file ...
     }

SEE ALSO
========

   `Tk::FBox|Tk::FBox' in this node, `Tk::FileSelect|Tk::FileSelect' in
this node

KEYWORDS
========

   file selection dialog

Confine pointer and keyboard events to a window sub-tree
********************************************************

NAME
====

   grab - Confine pointer and keyboard events to a window sub-tree

   $widget->*grab*

   $widget->*grab*Option

DESCRIPTION
===========

   This set of methods implement simple pointer and keyboard grabs for Tk.
Tk's grabs are different than the grabs described in the Xlib
documentation.  When a grab is set for a particular window, Tk restricts
all pointer events to the grab window and its descendants in Tk's window
hierarchy.  Whenever the pointer is within the grab window's subtree, the
pointer will behave exactly the same as if there had been no grab at all
and all events will be reported in the normal fashion.  When the pointer
is outside $widget's tree, button presses and releases and mouse motion
events are reported to $widget, and window entry and window exit events
are ignored.  The grab subtree "owns" the pointer: windows outside the
grab subtree will be visible on the screen but they will be insensitive
until the grab is released.  The tree of windows underneath the grab
window can include top-level windows, in which case all of those top-level
windows and their descendants will continue to receive mouse events during
the grab.

   Two forms of grabs are possible:  local and global.  A local grab
affects only the grabbing application:  events will be reported to other
applications as if the grab had never occurred.  Grabs are local by
default.  A global grab locks out all applications on the screen, so that
only the given subtree of the grabbing application will be sensitive to
pointer events (mouse button presses, mouse button releases, pointer
motions, window entries, and window exits).  During global grabs the
window manager will not receive pointer events either.

   During local grabs, keyboard events (key presses and key releases) are
delivered as usual:  the window manager controls which application
receives keyboard events, and if they are sent to any window in the
grabbing application then they are redirected to the focus window.  During
a global grab Tk grabs the keyboard so that all keyboard events are always
sent to the grabbing application.  The focus method is still used to
determine which window in the application receives the keyboard events.
The keyboard grab is released when the grab is released.

   Grabs apply to particular displays.  If an application has windows on
multiple displays then it can establish a separate grab on each display.
The grab on a particular display affects only the windows on that display.
It is possible for different applications on a single display to have
simultaneous local grabs, but only one application can have a global grab
on a given display at once.

   The *grab* methods take any of the following forms:

$widget->*grabCurrent*
     Returns the current grab window in this application for $widget's
     display, or an empty string if there is no such window.

$widget->*grabs*
     Returns a list whose elements are all of the windows grabbed by this
     application for all displays, or an empty string if the application
     has no grabs.

     *Not implemented yet!*

$widget->*grabRelease*
     Releases the grab on $widget if there is one, otherwise does nothing.
     Returns an empty string.

$widget->*grab*
     Sets a local grab on $widget.  If a grab was already in effect for
     this application on $widget's display then it is automatically
     released.  If there is already a local grab on $widget, then the
     command does nothing.  Returns an empty string.

$widget->*grabGlobal*
     Sets a global grab on $widget.  If a grab was already in effect for
     this application on $widget's display then it is automatically
     released.  If there is already a global grab on $widget, then the
     command does nothing.  Returns an empty string.

$widget->*grabStatus*
     Returns none if no grab is currently set on $widget, local if a local
     grab is set on $widget, and global if a global grab is set.

BUGS
====

   It took an incredibly complex and gross implementation to produce the
simple grab effect described above.  Given the current implementation, it
isn't safe for applications to use the Xlib grab facilities at all except
through the Tk grab procedures.  If applications try to manipulate X's
grab mechanisms directly, things will probably break.

   If a single process is managing several different Tk applications, only
one of those applications can have a local grab for a given display at any
given time.  If the applications are in different processes, this
restriction doesn't exist.

KEYWORDS
========

   grab, keyboard events, pointer events, window

Geometry manager that arranges widgets in a grid
************************************************

NAME
====

   Tk::grid - Geometry manager that arranges widgets in a grid

       $widget->grid?(?widget ...,? ?*arg* ?...>?)?

       $widget->gridOption?(*arg* ?,*arg* ...?)?

DESCRIPTION
===========

   The grid method is used to communicate with the grid geometry manager
that arranges widgets in rows and columns inside of another window, called
the geometry master (or master window).  The grid method can have any of
several forms, depending on the option argument:

*$slave*->grid(?*$slave, ...*??, options?)
     The arguments consist of the optional references to more slave windows
     followed by pairs of arguments that specify how to manage the slaves.
     The characters -,  x and ^, can be specified instead of a window
     reference to alter the default location of a *$slave*, as described
     in `"RELATIVE PLACEMENT"' in this node, below.

     If any of the slaves are already managed by the geometry manager then
     any unspecified options for them retain their previous values rather
     than receiving default values.

     The following options are supported:

    *-column* => n
          Insert the *$slave* so that it occupies the nth column in the
          grid.  Column numbers start with 0.  If this option is not
          supplied, then the *$slave* is arranged just to the right of
          previous slave specified on this call to grid, or column "0" if
          it is the first slave.  For each x that immediately precedes the
          *$slave*, the column position is incremented by one.  Thus the x
          represents a blank column for this row in the grid.

    *-columnspan* => n
          Insert the slave so that it occupies n columns in the grid.  The
          default is one column, unless the window name is followed by a
          -, in which case the columnspan is incremented once for each
          immediately following -.

    *-in* => *$other*
          Insert the slave(s) in the master window given by *$other*.  The
          default is the first slave's parent window.

    *-ipadx* => *amount*
          The *amount* specifies how much horizontal internal padding to
          leave on each side of the slave(s).  This is space is added
          inside the slave(s) border.  The *amount* must be a valid screen
          distance, such as 2 or *'.5c'*.  It defaults to 0.

    *-ipady* => *amount*
          The *amount* specifies how much vertical internal padding to
          leave on on the top and bottom of the slave(s).  This space is
          added inside the slave(s) border.  The *amount*  defaults to 0.

    *-padx* => *amount*
          The *amount* specifies how much horizontal external padding to
          leave on each side of the slave(s), in screen units.  The
          *amount* defaults to 0.  This space is added outside the
          slave(s) border.

    *-pady* => *amount*
          The *amount* specifies how much vertical external padding to
          leave on the top and bottom of the slave(s), in screen units.
          The *amount* defaults to 0.  This space is added outside the
          slave(s) border.

    *-row* => n
          Insert the slave so that it occupies the nth row in the grid.
          Row numbers start with 0.  If this option is not supplied, then
          the slave is arranged on the same row as the previous slave
          specified on this call to grid, or the first unoccupied row if
          this is the first slave.

    *-rowspan* => n
          Insert the slave so that it occupies n rows in the grid.  The
          default is one row.  If the next grid method contains ^
          characters instead of *$slave*s that line up with the columns of
          this *$slave*, then the *rowspan* of this *$slave* is extended
          by one.

    *-sticky* => style
          If a slave's cell is larger than its requested dimensions, this
          option may be used to position (or stretch) the slave within its
          cell.  Style  is a string that contains zero or more of the
          characters n, s, e or w.  The string can optionally contain
          spaces or commas, but they are ignored.  Each letter refers to a
          side (north, south, east, or west) that the slave will "stick"
          to.  If both n and s (or e and w) are specified, the slave will
          be stretched to fill the entire height (or width) of its cavity.
          The *sticky* option subsumes the combination of *-anchor* and
          *-fill* that is used by `pack|Tk::pack' in this node.  The
          default is ", which causes the slave to be centered in its
          cavity, at its requested size.

*$master*->*gridBbox*(?*column, row*,? ?*column2, row2*?)
     With no arguments, the bounding box (in pixels) of the grid is
     returned.  The return value consists of 4 integers.  The first two
     are the pixel offset from the master window (x then y) of the
     top-left corner of the grid, and the second two integers are the
     width and height of the grid, also in pixels.  If a single column and
     row is specified on the command line, then the bounding box for that
     cell is returned, where the top left cell is numbered from zero.  If
     both column and row arguments are specified, then the bounding box
     spanning the rows and columns indicated is returned.

*$master*->*gridColumnconfigure*(index?, *-option*=>*value, ...*?)
     Query or set the column properties of the index column of the
     geometry master, *$master*.  The valid options are *-minsize*,
     *-weight* and *-pad*.  If one or more options are provided, then
     index may be given as a list of column indices to which the
     configuration options will operate on.  The *-minsize* option sets
     the minimum size, in screen units, that will be permitted for this
     column.  The *-weight* option (an integer value) sets the relative
     weight for apportioning any extra spaces among columns.  A weight of
     zero (0) indicates the column will not deviate from its requested
     size.  A column whose weight is two will grow at twice the rate as a
     column of weight one when extra space is allocated to the layout.
     The *-pad* option specifies the number of screen units that will be
     added to the largest window contained completely in that column when
     the grid geometry manager requests a size from the containing window.
     If only an option is specified, with no value, the current value of
     that option is returned.  If only the master window and index is
     specified, all the current settings are returned in an list of
     "-option value" pairs.

*$slave*->*gridConfigure*(?*$slave, ...*?, options?)
     The same as grid method.

*$slave*->*gridForget*?(*$slave, ...*)?
     Removes each of the *$slave*s from grid for its master and unmaps
     their windows.  The slaves will no longer be managed by the grid
     geometry manager.  The configuration options for that window are
     forgotten, so that if the slave is managed once more by the grid
     geometry manager, the initial default settings are used.

*$slave*->*gridInfo*
     Returns a list whose elements are the current configuration state of
     the slave given by *$slave* in the same option-value form that might
     be specified to *gridConfigure*.  The first two elements of the list
     are "*-in*=>*$master*" where *$master* is the slave's master.

*$master*->*gridLocation*(*x, y*)
     Given  x and y values in screen units relative to the master window,
     the column and row number at that x and y location is returned.  For
     locations that are above or to the left of the grid, *-1* is returned.

*$master*->*gridPropagate*?(boolean)?
     If boolean has a true boolean value such as 1 or *on* then
     propagation is enabled for *$master*, which must be a window name
     (see `"GEOMETRY PROPAGATION"' in this node below).  If boolean has a
     false boolean value then propagation is disabled for *$master*.  In
     either of these cases an empty string is returned.  If boolean is
     omitted then the method returns 0 or 1 to indicate whether
     propagation is currently enabled for *$master*.  Propagation is
     enabled by default.

*$master*->*gridRowconfigure*(index?, *-option*=>*value, ...*?)
     Query or set the row properties of the index row of the geometry
     master, *$master*.  The valid options are *-minsize*, *-weight* and
     *-pad*.  If one or more options are provided, then index may be given
     as a list of row indeces to which the configuration options will
     operate on.  The *-minsize* option sets the minimum size, in screen
     units, that will be permitted for this row.  The *-weight* option (an
     integer value) sets the relative weight for apportioning any extra
     spaces among rows.  A weight of zero (0) indicates the row will not
     deviate from its requested size.  A row whose weight is two will grow
     at twice the rate as a row of weight one when extra space is
     allocated to the layout.  The *-pad* option specifies the number of
     screen units that will be added to the largest window contained
     completely in that row when the grid geometry manager requests a size
     from the containing window.  If only an option is specified, with no
     value, the current value of that option is returned.  If only the
     master window and index is specified, all the current settings are
     returned in an list of "option-value" pairs.

*$slave*->*gridRemove*?(*$slave, ...*)?
     Removes each of the *$slave*s from grid for its master and unmaps
     their windows.  The slaves will no longer be managed by the grid
     geometry manager.  However, the configuration options for that window
     are remembered, so that if the slave is managed once more by the grid
     geometry manager, the previous values are retained.

*$master*->*gridSize*
     Returns the size of the grid (in columns then rows) for *$master*.
     The size is determined either by the *$slave* occupying the largest
     row or column, or the largest column or row with a *-minsize*,
     *-weight*, or *-pad* that is non-zero.

*$master*->*gridSlaves*?(*-option*=>value)?
     If no options are supplied, a list of all of the slaves in *$master*
     are returned, most recently manages first.  *-option* can be either
     *-row* or *-column* which causes only the slaves in the row (or
     column) specified by value to be returned.

RELATIVE PLACEMENT
==================

   The grid method contains a limited set of capabilities that permit
layouts to be created without specifying the row and column information
for each slave.  This permits slaves to be rearranged, added, or removed
without the need to explicitly specify row and column information.  When
no column or row information is specified for a *$slave*, default values
are chosen for *-column*, *-row*, *-columnspan* and *-rowspan* at the time
the *$slave* is managed. The values are chosen based upon the current
layout of the grid, the position of the *$slave* relative to other
*$slave*s in the same grid method, and the presence of the characters -,
^, and ^ in grid method where *$slave* names are normally expected.

-
     This increases the columnspan of the *$slave* to the left.  Several
     -'s in a row will successively increase the columnspan. A - may not
     follow a ^ or a x.

x
     This leaves an empty column between the *$slave* on the left and the
     *$slave* on the right.

^
     This extends the *-rowspan* of the *$slave* above the ^'s in the
     grid.  The number of ^'s in a row must match the number of columns
     spanned by the *$slave* above it.

THE GRID ALGORITHM
==================

   The grid geometry manager lays out its slaves in three steps.  In the
first step, the minimum size needed to fit all of the slaves is computed,
then (if propagation is turned on), a request is made of the master window
to become that size.  In the second step, the requested size is compared
against the actual size of the master.  If the sizes are different, then
space is added to or taken away from the layout as needed.  For the final
step, each slave is positioned in its row(s) and column(s) based on the
setting of its *sticky* flag.

   To compute the minimum size of a layout, the grid geometry manager
first looks at all slaves whose columnspan and rowspan values are one, and
computes the nominal size of each row or column to be either the *minsize*
for that row or column, or the sum of the padding plus the size of the
largest slave, whichever is greater.  Then the slaves whose rowspans or
columnspans are greater than one are examined.  If a group of rows or
columns need to be increased in size in order to accommodate these slaves,
then extra space is added to each row or column in the group according to
its weight.  For each group whose weights are all zero, the additional
space is apportioned equally.

   For masters whose size is larger than the requested layout, the
additional space is apportioned according to the row and column weights.
If all of the weights are zero, the layout is centered within its master.
For masters whose size is smaller than the requested layout, space is taken
away from columns and rows according to their weights.  However, once a
column or row shrinks to its minsize, its weight is taken to be zero.  If
more space needs to be removed from a layout than would be permitted, as
when all the rows or columns are at there minimum sizes, the layout is
clipped on the bottom and right.

GEOMETRY PROPAGATION
====================

   The grid geometry manager normally computes how large a master must be
to just exactly meet the needs of its slaves, and it sets the requested
width and height of the master to these dimensions.  This causes geometry
information to propagate up through a window hierarchy to a top-level
window so that the entire sub-tree sizes itself to fit the needs of the
leaf windows.  However, the *gridPropagate* method may be used to turn off
propagation for one or more masters.  If propagation is disabled then grid
will not set the requested width and height of the master window.  This
may be useful if, for example, you wish for a master window to have a
fixed size that you specify.

RESTRICTIONS ON MASTER WINDOWS
==============================

   The master for each slave must either be the slave's parent (the
default) or a descendant of the slave's parent.  This restriction is
necessary to guarantee that the slave can be placed over any part of its
master that is visible without danger of the slave being clipped by its
parent.  In addition, all slaves in one call to grid must have the same
master.

STACKING ORDER
==============

   If the master for a slave is not its parent then you must make sure
that the slave is higher in the stacking order than the master.  Otherwise
the master will obscure the slave and it will appear as if the slave
hasn't been managed correctly.  The easiest way to make sure the slave is
higher than the master is to create the master window first:  the most
recently created window will be highest in the stacking order.

CREDITS
=======

   The grid method is based on ideas taken from the *GridBag* geometry
manager written by Doug. Stein, and the *blt_table* geometry manager,
written by George Howlett.

SEE ALSO
========

   `Tk::form|Tk::form' in this node `Tk::pack|Tk::pack' in this node
`Tk::place|Tk::place' in this node

KEYWORDS
========

   geometry manager, location, grid, cell, propagation, size, pack,
master, slave

perl/Tk support to write widgets in perl
****************************************

NAME
====

   Tk::mega - perl/Tk support to write widgets in perl

       *package Tk::**Whatever*;

       *Construct Tk::**ValidFor* *'Whatever'*;

       *sub ClassInit* { *my ($mega, $args) = @_; ...* }

   For composite widget classes:

       *sub Populate* { *my ($composite, $args) = @_; ...* }

   For derived widget classes:

       *sub InitObject* { *my ($derived, $args) = @_; ...* }

DESCRIPTION
===========

   The goal of the mega widget support of perl/Tk is to make it easy to
write mega widgets that obey the same protocol and interface that the Tk
core widgets support.  There are two kinds of mega widgets:

   * Composite Widgets

     A composite widget is composed with one or more existing widgets.
     The composite widget looks to the user like a simple single widget.
     A well known example is the file selection box.

   * Derived Widgets

     A derived widget adds/modifies/removes properties and methods from a
     single widget (this widget may itself be a mega widget).

MEGA WIDGET SUPPORT
===================

Advertise
---------

   Give a subwidget a symbolic name.

   Usage:

       *$cw*->Advertise(name=>$widget);

   Gives a subwidget $widget of the composite widget *$cw* the name name.
One can retrieve the reference of an advertised subwidget with the
`Subwidget|"Subwidget"' in this node method.

   Comment: Mega Widget Writers: Please make sure to document the
advertised widgets that are intended for *public* use.  If there are none,
document this fact, e.g.:

     =head1 ADVERTISED WIDGETS

     None.

Callback
--------

   Invoke a callback specified with an option.

   Usage:

       *$mega*->Callback(*-option* ?,args ...?);

   Callback executes the `callback|Tk::callbacks' in this node defined with
*$mega*->ConfigSpecs(*-option*, [*CALLBACK*, ...]); If args are given they
are passed to the callback. If *-option* is not defined it does nothing.

ClassInit
---------

   Initialization of the mega widget class.

   Usage:

       *sub ClassInit* { *my ($class, $mw) = @_;* ...  }

   ClassInit is called once for each `MainWindow|Tk::MainWindow' in this
node just before the first widget instance of a class is created in the
widget tree of *MainWindow*.

   ClassInit is often used to define bindings and/or other resources
shared by all instances, e.g., images.

   Examples:

     $mw->bind($class,"<Tab>", sub { my $w = shift; $w->Insert("\t"); $w->focus; $w->break});
     $mw->bind($class,"<Return>", ['Insert',"\n"]);
     $mw->bind($class,"<Delete>",'Delete');

   Notice that $class is the class name (e.g. *Tk::MyText*) and *$mw* is
the mainwindow.

   Don't forget to call $class->*SUPER::ClassInit($mw)* in ClassInit.

Component
---------

   Convenience function to create subwidgets.

   Usage:

     $cw->Component('Whatever', 'AdvertisedName',
     		   -delegate => ['method1', 'method2', ...],
     		   ... Whatever widget options ...,
     		  );

   Component does several things for you with one call:

   o Creates the widget

   o Advertises it with a given name (overridden by 'Name' option)

   o Delegates a set of methods to this widget (optional)

   Example:

     $cw->Component('Button', 'quitButton', -command => sub{$mw->'destroy'});

ConfigSpecs
-----------

   Defines options and their treatment

   Usage:

     $cw->ConfigSpecs(
     	    -option => [ where, dbname, dbclass, default],
     	    ...,
     	    DEFAULT => [where],
     	    );

   Defines the options of a mega widget and what actions are triggered by
configure/cget of an option (see Tk/ConfigSpecs, and
Tk/Derived, for details).

Construct
---------

   Make the new mega widget known to Tk.

   Usage:

       Construct *baseclass* *'Name'*;

   Construct declares the new widget class so that your mega widget works
like normal Perl/Tk widgets.

   Examples:

       *Construct Tk::Widget* *'Whatever'*;     *Construct Tk::Menu*
*'MyItem'*;

   First example lets one use $widget->*Whatever* to create new *Whatever*
widget.

   The second example restricts the usage of the *MyItem* constructor
method to widgets that are derived from Menu: *$isamenu*->*MyItem*.

CreateArgs
----------

   Mess with options before any widget is created

       *sub CreateArgs* { *my ($package, $parent, $args) = @_; ...; return
@newargs;* }

   *$package* is the package of the mega widget (e.g., *Tk::MyText*,
*$parent* the parent of the widget to be created and $args the hash
reference to the options specified in the widget constructor call.

   Don't forget to call *$package*->*SUPER::CreateArgs*(*$parent*, $args)
in CreateArgs.

Delegates
---------

   Redirect a method of the mega widget to a subwidget of the composite
widget

   Usage:

     $cw->Delegates(
     		'method1' => $subwidget1,
     		'method2' => 'advertived_name',
     		...,
     		'Construct' => $subwidget2,
     		'DEFAULT'   => $subwidget3,
     		);

   The *'Construct'* delegation has a special meaning.  After 'Construct'
is delegated all Widget constructors are redirected.  E.g. after

       *$mega*->Delegates(*'Construct'*=>*$subframe*);

   a *$mega*->Button does really a *$subframe*->Button so the created
button is a child of *$subframe* and not *$mega*.

   Comment: Delegates works only with methods that *$cw* does not have
itself.

InitObject
----------

   Defines construction and interface of derived widgets.

   Usage:

     sub InitObject {
     	my ($derived, $args) = @_;
     	...
     }

   where *$derived* is the widget reference of the already created
baseclass widget and $args is the reference to a hash of *-option-value*
pairs.

   InitObject is almost identical to `Populate|"Populate"' in this node
method.  Populate does some more 'magic' things useful for mega widgets
with several widgets.

   Don't forget to call *$derived*->*SUPER::InitObject*($args) in
InitObject.

OnDestroy
---------

   Define callback invoked when widget is destroyed.

   Usage:

       $widget->OnDestroy(callback);

   OnDestroy installs a `callback|Tk::callbacks' in this node that's called
when a widget is going to to be destroyed.  Useful for special cleanup
actions.  It differs from a normal destroy in that all the widget's data
structures are still intact.

   Comment: This method could be used with any widgets not just for mega
widgets.  It's listed here because of it's usefulness.

Populate
--------

   Defines construction and interface of the composite widget.

   Usage:

     sub Populate {
     	my ($mega, $args) = @_;
     	...
     }

   where *$mega* is the widget reference of the already created baseclass
widget and $args is the reference to a hash of *-option-value* pairs.

   Most the other support function are normally used inside the Populate
subroutine.

   Don't forget to call *$cw*->*SUPER::Populate*($args) in Populate.

privateData
-----------

   Set/get a private hash of a widget to storage composite internal data

   Usage:

       $hashref = *$mega*->privateData();

       *$another* = *$mega*->privateData(*unique_key*|package);

Subwidget
---------

   Get the widget reference of an advertised subwidget.

       *$subwidget* = *$cw*->Subwidget(name);

       *@subwidget* = *$cw*->Subwidget(name ?,...?);

   Returns the widget reference(s) of the subwidget known under the name
name.  See `Advertise|"Advertise"' in this node method how to define name
for a subwidget.

   Comment: Mega Widget Users: Use Subwidget to get *only* documented
subwidgets.

PITFALLS
========

   * Resource DB class name

     Some of the standard options use a resource date base class that is
     not equal to the resource database name.  E.g.,

          Switch:            Name:             Class:

          -padx              padX              Pad
          -activerelief      activeRelief      Relief
          -activebackground  activeBackground  Foreground
          -status            undef             undef

     One should do the same when one defines one of these options via
     ConfigSpecs.

   * Method delegation

     Redirecting methods to a subwidget with *Delegate* can only work if
     the base widget itself does have a method with this name.  Therefore
     one can't "delegate" any of the methods listed in
     `Tk::Widget|Tk::Widget' in this node.  A common problematic method is
     bind.  In this case one as to explicitely redirect the method.

          sub bind
            {
              my $mega = shift;
              my $to = $mega->privateData->{'my_bind_target'};
              $to->bind(@_);
            }

   * privateData

     Graham Barr wrote: ... It is probably more private than most people
     think. Not all calls to privateData will return that same HASH
     reference. The HASH reference that is returned depends on the package
     it was called from, a different HASH is returned for each package.
     This allows a widget to hold private data, but then if it is
     sub-classed the sub-class will get a different HASH and so not cause
     duplicate name clashes.

     But privateData does take an optional argument if you want to force
     which HASH is returned.

   * Scrolled and Composite

     *Scrolled*(*Kind*,...) constructor can not be used with Composite.
     One has to use $cw->Composite(*Scrl**Kind* => *'name'*, ...);

MISSING
=======

   Of course perl/Tk does not define support function for all necessities.
Here's a short list of things you have to handle yourself:

   * no support to define construction-time only options.

   * no support to remove an option that is known to the base widget.

   * it's hard to define undef as fallback for an widget option that is
     not already undef.

   * Frame in perl/Tk carries magic and overhead not needed for composite
     widget class definition.

   * No support methods for bindings that are shared between all widgets
     of a composite widget (makes sense at all?)

KEYWORDS
========

   mega, composite, derived, widget

SEE ALSO
========

   `Tk::composite|Tk::composite' in this node
`Tk::ConfigSpecs|Tk::ConfigSpecs' in this node `Tk::option|Tk::option' in
this node `Tk::callbacks|Tk::callbacks' in this node `Tk::bind|Tk::bind'
in this node

pop up a message window and wait for user response.
***************************************************

NAME
====

   messageBox  -  pop up a message window and wait for user response.

       *$response* = $widget->*messageBox*(*-option* => value, ... );

DESCRIPTION
===========

   This method uses `Tk::Dialog|Tk::Dialog' in this node to quickly create
several common dialog boxes.  A dialog widget consists of a message, an
icon and a set of buttons (see the *-type* option).  After the message
window is popped up,  *messageBox* waits  for the user to select one of
the buttons and return the button text.  NOTE:  unlike *Tk::Dialog* which
creates its widget once and can be used many times, the *messageBox*
window is created every time it's used.

   The following option/value pairs are supported:

*-default*
     The case-sensitive symbolic name of the default button for this
     message window  ('OK',  'Cancel'  and  so on).  See  *-type*  for a
     list of the symbolic names.  If the message box has  just  one
     button  it  will automatically  be  made  the  default, otherwise if
     this option is not specified, there  won't  be  any default button.

*-icon*
     Specifies an icon to display. Any of the builtin Tk bitmaps can
     specified.

*-message*
     Specifies the message to display.

*-title*
     Specifies  a  string to display as the title.

*-type*
     Specifies a predefined set of buttons to be displayed. The following
     values are possible: 'AbortRetryIgnore', 'OK', 'OKCancel',
     'RetryCancel', 'YesNo' or 'YesNoCancel'.

EXAMPLE
=======

   *$repsonse* = *$mw*->*messageBox*(-icon => 'questhead', -message =>
'Hello World!', -title => 'My title', -type => 'AbortRetryIgnore',
-default => 'Retry');

AUTHOR
======

   Stephen.O.Lidie@Lehigh.EDU.  98/05/25

Using the option database in Perl/Tk
************************************

NAME
====

   option - Using the option database in Perl/Tk

       $widget->*widgetClass*(Name=>name, *-class*=>class);

       $widget->*PathName*;

       $widget->*optionAdd*(pattern=>*value * ?,priority?);

       $widget->*optionClear*;

       $widget->*optionGet*(*name, class*);

       $widget->*optionReadfile*(*fileName* ?,priority?);

DESCRIPTION
===========

   The option database (also known as the *resource database* or the
*application defaults database*) is a set of rules for applying default
options to widgets.  Users and system administrators can set up these
rules to customize the appearance of applications without changing any
application code; for example, a user might set up personal foreground and
background colors, or a site might use fonts associated with visual or
language preferences.  Different window managers (and implementations of
them) have implemented the database differently, but most Xt-based window
managers use the *.Xdefaults* file or the *xrdb* utility to manage user
preferences; some use both, and/or implement a more complex set of site,
user and application databases.  Check your site documentation for these
topics or your window manager's *RESOURCE_MANAGER* property.

Being a good citizen
--------------------

   For most applications, the option database "just works."  The
*option...* methods are for applications that need to do something
unusual, such as add new rules or test an option's default.  Even in such
cases, the application should provide for user preferences.  Do not
hardcode widget options without a *very* good reason.  All users have
their own tastes and they are all different.  They choose a special font
in a special size and have often spend a lot of time working out a color
scheme that they will love until death.  When you respect their choices
they will enjoy working with your applications much more.  Don't destroy
the common look and feel of a personal desktop.

Option rules and widget identification
--------------------------------------

   All widgets in an application are identified hierarchically by
*pathname*, starting from the *MainWindow* and passing through each widget
used to create the endpoint.  The path elements are *widget names*, much
like the elements of a file path from the root directory to a file.  The
rules in the option database are patterns that are matched against a
widget's *pathname* to determine which defaults apply.  When a widget is
created, the Name option can be used to assign the widget's name and thus
create a distinctive path for widgets in an application.  If the Name
option isn't given, Perl/Tk assigns a default name based on the type of
widget; a *MainWindow*'s default name is the *appname*.  These defaults
are fine for most widgets, so don't feel you need to find a meaningful
name for every widget you create.  A widget must have a distinctive name
to allow users to tailor its options independently of other widgets in an
application.  For instance, to create a Text widget that will have special
options assigned to it, give it a name such as:

     $text = $mw->Text(Name => 'importantText');

   You can then tailor the widget's attributes with a rule in the option
database such as:

     *importantText*foreground: red

   The class attribute identifies groups of widgets, usually within an
application but also to group similar widgets among different applications.
One typically assigns a class to a *TopLevel* or Frame so that the class
will apply to all of that widget's children.  To extend the example, we
could be more specific about the importantText widget by giving its frame
a class:

     $frame = $mw->Frame(-class => 'Urgent');
     $text = $frame->Text(Name => 'importantText');

   Then the resource pattern can be specified as so:

     *Urgent*importantText*foreground: red

   Similarly, the pattern `*Urgent*background: cyan' would apply to all
widgets in the frame.

METHODS
=======

$widget->*widgetClass*(Name=>name, *-class*=>class);
     Identify a new widget with name and/or class.  Name specifies the
     path element for the widget; names generally begin with a lowercase
     letter.  *-class* specifies the class for the widget and its
     children; classes generally begin with an uppercase letter.  If not
     specified, Perl/Tk will assign a unique default name to each widget.
     Only *MainWindow* widgets have a default class, made by uppercasing
     the first letter of the application name.

$widget->*PathName*;
     The *PathName* method returns the widget's *pathname*, which uniquely
     identifies the widget within the application.

$widget->*optionAdd*(pattern=>*value *?, priority?);
     The *optionAdd* method adds a new option to the database.  Pattern
     contains the option being specified, and consists of names and/or
     classes separated by asterisks or dots, in the usual X format.  Value
     contains a text string to associate with pattern; this is the value
     that will be returned in calls to the *optionGet* method.  If
     priority is specified, it indicates the priority level for this
     option (see below for legal values); it defaults to interactive. This
     method always returns an empty string.

$widget->*optionClear*;
     The *optionClear* method clears the option database.  Default options
     (from the *RESOURCE_MANAGER* property or the *.Xdefaults* file) will
     be reloaded automatically the next time an option is added to the
     database or removed from it.  This method always returns an empty
     string.

$widget->*optionGet*(*name,class*);
     The *optionGet* method returns the value of the option specified for
     $widget under name and class.  To look up the option, *optionGet*
     matches the patterns in the resource database against $widget's
     *pathname* along with the class of $widget (or its parent if $widget
     has no class specified).  The widget's class and name are options set
     when the widget is created (not related to class in the sense of
     `bless' in this node); the *MainWindow*'s name is the *appname* and
     its class is (by default) derived from the name of the script.

     If several entries in the option database match $widget's *pathname*,
     name, and class, then the method returns whichever was created with
     highest priority level.  If there are several matching entries at the
     same priority level, then it returns whichever entry was *most
     recently entered* into the option database.  If there are no matching
     entries, then the empty string is returned.

$widget->*optionReadfile*(*fileName*?,priority?);
     The *optionReadfile* method reads *fileName*, which should have the
     standard format for an X resource database such as *.Xdefaults*, and
     adds all the options specified in that file to the option database.
     If priority is specified, it indicates the priority level at which to
     enter the options;  priority defaults to interactive.

     The priority arguments to the option methods are normally specified
     symbolically using one of the following values:

    widgetDefault
          Level 20.  Used for default values hard-coded into widgets.

    startupFile
          Level 40.  Used for options specified in application-specific
          startup files.

    userDefault
          Level 60.  Used for options specified in user-specific defaults
          files, such as *.Xdefaults*, resource databases loaded into the
          X server, or user-specific startup files.

    interactive
          Level 80.  Used for options specified interactively after the
          application starts running.  If priority isn't specified, it
          defaults to this level.

     Any of the above keywords may be abbreviated.  In addition, priorities
     may be specified numerically using integers between 0 and 100,
     inclusive.  The numeric form is probably a bad idea except for new
     priority levels other than the ones given above.

BUGS
====

   The priority scheme used by core Tk is not the same as used by normal
Xlib routines. In particular is assumes that the order of the entries is
defined, but user commands like *xrdb -merge* can change the order.

SEE ALSO
========

   `Tk::Xrm|Tk::Xrm' in this node

KEYWORDS
========

   database, option, priority, retrieve

Standard options supported by widgets and their manipulation
************************************************************

NAME
====

   Tk::options - Standard options supported by widgets and their
manipulation

       $value = $widget->cget('*-option*');

       $widget->configure(*-option*=>value ?,*-option*=>value ...?);

       *@list* = $widget->configure('*-option*');

       *@lol* = $widget->configure;

DESCRIPTION
===========

   All widgets, and images have a standard mechanism for setting and
querying attibutes or options. The mechanism is based on two methods
configure and cget. The behaviour of these methods is as follows:

$widget->configure(*-option*=>value ?,*-option*=>value ...?);
     Sets the values of *-option* to value for each *-option*=>value pair.
     The internal new method does an implicit configure in this form with
     options passed in at widget create time.

$widget->configure('*-option*')
     In array context returns a list of five or two elements.  If *-option*
     is an alias for another options it return a list consisting of the
     alias option and the name for the option is is an alias for, e.g.,
     `('-bg', 'background')'.  If *-option* is not an alias the returned
     list has the following five elements:

    *Option Name*
          The value of *-option*, e.g., *-background*.

    Name
          The option's name in the option database, e.g., background.

    Class
          The option's class value in the option database, e.g.,
          Background.

    Default
          The default value for the option if not specified or in the
          option database, e.g., `grey'.

    Value
          The current value (as returned by cget), e.g., `white'.

$widget->configure
     Returns a list of lists for all the options supported by $widget.
     Each sub-list is in the form returned by configure('*-option*').
     (This mechanism is used by the *Tk::Derived* class to determine the
     options available from base class.)

$widget->cget('*-option*')
     Returns the current value of *-option* for $widget.

     cget('*-option*') is clumsy with the need for " due to perl's parsing
     rules. Something more subtle using `tie|perlfunc' in this node might
     look better.

   The following paragraphs describe the common configuration options
supported by widgets in the Tk toolkit.  Every widget does not necessarily
support every option (see the the documentation entries for individual
widgets for a list of the standard options supported by that widget), but
if a widget does support an option with one of the names listed below,
then the option has exactly the effect described below.

   In the descriptions below, "Name" refers to the option's name in the
option database.  "Class" refers to the option's class value in the option
database.  "Switch" refers to the switch used in widget-creation and
configure widget methods to set this value. For example, if an option's
configure option is *-foreground* and there exists a widget $widget, then
the call:

       $widget->configure(*-foreground*=>*'black'*)

   may be used to specify the value *black* for the option in the widget
$widget.  Configure options may be abbreviated, as long as the
abbreviation is unambiguous (abbreviation is deprecated in perl/Tk).

Creation options: Widget Name and Class
---------------------------------------

   The Name and *-class* options can only be specified when a widget is
created, and cannot be changed with configure.  These options determine
the widget's identity and how Tk applies resource values from the option
database (see Tk/option) and so they cannot be assigned
by the options database.

Name:	name
Switch:	Name
     Specifies the path element for the widget.  Names generally begin
     with a lowercase letter.

     Each widget has a unique *pathname* that follows the hierarchy from
     the *MainWindow* to the widget itself.  Since the widget's *PathName*
     is used to assign options from the options database, it is important
     to specify a distinctive Name for any widget that will have
     non-default options.  See Tk/option, for details.

Name:	class
Switch:	*-class*
     Specifies a class for the window.  Classes generally begin with an
     uppercase letter.

     This class will be used when querying the option database for the
     window's other options (see Tk::options), and it will also be used
     later for other purposes such as bindings.  One typically assigns a
     class to a *TopLevel* or Frame so that the class will apply to all of
     that widget's children.

Reconfigurable options
----------------------

   These options can be set at widget creation or changed later via
configure.

Name:	*activeBackground*
Class:	*Foreground*
Switch:	*-activebackground*
     Specifies background color to use when drawing active elements.  An
     element (a widget or portion of a widget) is active if the mouse
     cursor is positioned over the element and pressing a mouse button
     will cause some action to occur.  If strict Motif compliance has been
     requested by setting the $Tk::strictMotif variable, this option will
     normally be ignored;  the normal background color will be used
     instead.  For some elements on Windows and Macintosh systems, the
     active color will only be used while mouse button 1 is pressed over
     the element.

Name:	*activeBorderWidth*
Class:	*BorderWidth*
Switch:	*-activeborderwidth*
     Specifies a non-negative value indicating the width of the 3-D border
     drawn around active elements.  See above for definition of active
     elements.  The value may have any of the forms acceptable to
     *Tk_GetPixels*.  This option is typically only available in widgets
     displaying more than one element at a time (e.g. menus but not
     buttons).

Name:	*activeForeground*
Class:	Background
Switch:	*-activeforeground*
     Specifies foreground color to use when drawing active elements.  See
     above for definition of active elements.

Name:	*activetile*
Class:	*Tile*
Switch:	*-activetile*
     Specifies image used to display inside active elements of the widget.
     See above for definition of active elements.

Name:	anchor
Class:	Anchor
Switch:	*-anchor*
     Specifies how the information in a widget (e.g. text or a bitmap) is
     to be displayed in the widget.  Must be one of the values n, ne, e,
     *se*, s, sw, w, *nw*, or center.  For example, *nw* means display the
     information such that its top-left corner is at the top-left corner
     of the widget.

Name:	background
Class:	Background
Switch:	*-background*
Alias:	*-bg*
     Specifies the normal background color to use when displaying the
     widget.

Name:	bitmap
Class:	Bitmap
Switch:	*-bitmap*
     Specifies a bitmap to display in the widget, in any of the forms
     acceptable to *Tk_GetBitmap*.  The exact way in which the bitmap is
     displayed may be affected by other options such as *-anchor* or
     -justify.  Typically, if this option is specified then it overrides
     other options that specify a textual value to display in the widget;
     the *-bitmap* option may be reset to an empty string to re-enable a
     text display.  In widgets that support both *-bitmap* and *-image*
     options, *-image* will usually override *-bitmap*.

Name:	*borderWidth*
Class:	*BorderWidth*
Switch:	*-borderwidth*
Alias:	*-bd*
     Specifies a non-negative value indicating the width of the 3-D border
     to draw around the outside of the widget (if such a border is being
     drawn;  the *relief* option typically determines this).  The value
     may also be used when drawing 3-D effects in the interior of the
     widget.  The value may have any of the forms acceptable to
     *Tk_GetPixels*.

Name:	cursor
Class:	Cursor
Switch:	*-cursor*
     Specifies the mouse cursor to be used for the widget.  The value may
     have any of the forms acceptable to *Tk_GetCursor*.

Name:	*dash*
Class:	*Dash*
Switch:	*-dash*
     The value may have any of the forms accepted by *Tk_GetDash*, such as
     4, *[6,4]*, ., -, *-.*, or *-..*.

Name:	*dashoffset*
Class:	*Dashoffset*
Switch:	*-dashoffset*
     Specifies the offset in the dash list where the drawing starts.

Name:	*disabledForeground*
Class:	*DisabledForeground*
Switch:	*-disabledforeground*
     Specifies foreground color to use when drawing a disabled element.
     If the option is specified as an empty string (which is typically the
     case on monochrome displays), disabled elements are drawn with the
     normal foreground color but they are dimmed by drawing them with a
     stippled fill pattern.

Name:	*disabledtile*
Class:	*Tile*
Switch:	*-disabledtile*
     Specifies image to use when drawing a disabled element.

Name:	*exportSelection*
Class:	*ExportSelection*
Switch:	*-exportselection*
     Specifies whether or not a selection in the widget should also be the
     X selection.  The value may have any of the forms accepted by
     *Tcl_GetBoolean*, such as *true*, false, 0, 1, *yes*, or no.  If the
     selection is exported, then selecting in the widget deselects the
     current X selection, selecting outside the widget deselects any
     widget selection, and the widget will respond to selection retrieval
     requests when it has a selection.  The default is usually for widgets
     to export selections.

Name:	font
Class:	*Font*
Switch:	*-font*
     Specifies the font to use when drawing text inside the widget.

Name:	*foreground*
Class:	*Foreground*
Switch:	*-foreground*
Alias:	*-fg*
     Specifies the normal foreground color to use when displaying the
     widget.

Name:	*highlightBackground*
Class:	*HighlightBackground*
Switch:	*-highlightbackground*
     Specifies the color to display in the traversal highlight region when
     the widget does not have the input focus.

Name:	*highlightColor*
Class:	*HighlightColor*
Switch:	*-highlightcolor*
     Specifies the color to use for the traversal highlight rectangle that
     is drawn around the widget when it has the input focus.

Name:	*highlightThickness*
Class:	*HighlightThickness*
Switch:	*-highlightthickness*
     Specifies a non-negative value indicating the width of the highlight
     rectangle to draw around the outside of the widget when it has the
     input focus.  The value may have any of the forms acceptable to
     *Tk_GetPixels*.  If the value is zero, no focus highlight is drawn
     around the widget.

Name:	image
Class:	Image
Switch:	*-image*
     Specifies an image to display in the widget, which must have been
     created with an image create. (See Tk/Image, for
     details of image creation.)  Typically, if the *-image* option is
     specified then it overrides other options that specify a bitmap or
     textual value to display in the widget; the *-image* option may be
     reset to an empty string to re-enable a bitmap or text display.

Name:	*insertBackground*
Class:	*Foreground*
Switch:	*-insertbackground*
     Specifies the color to use as background in the area covered by the
     insertion cursor.  This color will normally override either the normal
     background for the widget (or the selection background if the
     insertion cursor happens to fall in the selection).

Name:	*insertBorderWidth*
Class:	*BorderWidth*
Switch:	*-insertborderwidth*
     Specifies a non-negative value indicating the width of the 3-D border
     to draw around the insertion cursor.  The value may have any of the
     forms acceptable to *Tk_GetPixels*.

Name:	*insertOffTime*
Class:	*OffTime*
Switch:	*-insertofftime*
     Specifies a non-negative integer value indicating the number of
     milliseconds the insertion cursor should remain "off" in each blink
     cycle.  If this option is zero then the cursor doesn't blink:  it is
     on all the time.

Name:	*insertOnTime*
Class:	*OnTime*
Switch:	*-insertontime*
     Specifies a non-negative integer value indicating the number of
     milliseconds the insertion cursor should remain "on" in each blink
     cycle.

Name:	*insertWidth*
Class:	*InsertWidth*
Switch:	*-insertwidth*
     Specifies a  value indicating the total width of the insertion cursor.
     The value may have any of the forms acceptable to *Tk_GetPixels*.  If
     a border has been specified for the insertion cursor (using the
     *insertBorderWidth* option), the border will be drawn inside the
     width specified by the *insertWidth* option.

Name:	jump
Class:	*Jump*
Switch:	*-jump*
     For widgets with a slider that can be dragged to adjust a value, such
     as scrollbars, this option determines when notifications are made
     about changes in the value.  The option's value must be a boolean of
     the form accepted by *Tcl_GetBoolean*.  If the value is false,
     updates are made continuously as the slider is dragged.  If the value
     is true, updates are delayed until the mouse button is released to
     end the drag;  at that point a single notification is made (the value
     "jumps" rather than changing smoothly).

Name:	justify
Class:	Justify
Switch:	-justify
     When there are multiple lines of text displayed in a widget, this
     option determines how the lines line up with each other.  Must be one
     of left, center, or right.  *Left* means that the lines' left edges
     all line up, center means that the lines' centers are aligned, and
     right means that the lines' right edges line up.

Name:	offset
Class:	Offset
Switch:	*-offset*
     Specifies the offset of tiles (see also *-tile* option). It can have
     two different formats *-offset x,y* or *-offset side*, where side can
     be n, ne, e, *se*, s, sw, w, *nw*, or center. In the first case the
     origin is the origin of the toplevel of the current window.  For the
     canvas itself and canvas objects the origin is the canvas origin, but
     putting *#* in front of the coordinate pair indicates using the
     toplevel origin in stead. For canvas objects, the *-offset* option is
     used for stippling as well.  For the line and polygon canvas items
     you can also specify an index as argument, which connects the stipple
     or tile origin to one of the coordinate points of the line/polygon.

Name:	orient
Class:	*Orient*
Switch:	*-orient*
     For widgets that can lay themselves out with either a horizontal or
     vertical orientation, such as scrollbars, this option specifies which
     orientation should be used.  Must be either *horizontal* or
     *vertical* or an abbreviation of one of these.

Name:	*padX*
Class:	*Pad*
Switch:	*-padx*
     Specifies a non-negative value indicating how much extra space to
     request for the widget in the X-direction.  The value may have any of
     the forms acceptable to *Tk_GetPixels*.  When computing how large a
     window it needs, the widget will add this amount to the width it
     would normally need (as determined by the width of the things
     displayed in the widget);  if the geometry manager can satisfy this
     request, the widget will end up with extra internal space to the left
     and/or right of what it displays inside.  Most widgets only use this
     option for padding text:  if they are displaying a bitmap or image,
     then they usually ignore padding options.

Name:	*padY*
Class:	*Pad*
Switch:	*-pady*
     Specifies a non-negative value indicating how much extra space to
     request for the widget in the Y-direction.  The value may have any of
     the forms acceptable to *Tk_GetPixels*.  When computing how large a
     window it needs, the widget will add this amount to the height it
     would normally need (as determined by the height of the things
     displayed in the widget);  if the geometry manager can satisfy this
     request, the widget will end up with extra internal space above
     and/or below what it displays inside.  Most widgets only use this
     option for padding text:  if they are displaying a bitmap or image,
     then they usually ignore padding options.

Name:	*relief*
Class:	*Relief*
Switch:	*-relief*
     Specifies the 3-D effect desired for the widget.  Acceptable values
     are *raised*, *sunken*, flat, *ridge*, solid, and *groove*.  The value
     indicates how the interior of the widget should appear relative to
     its exterior;  for example, *raised* means the interior of the widget
     should appear to protrude from the screen, relative to the exterior
     of the widget.

Name:	*repeatDelay*
Class:	*RepeatDelay*
Switch:	*-repeatdelay*
     Specifies the number of milliseconds a button or key must be held
     down before it begins to auto-repeat.  Used, for example, on the up-
     and down-arrows in scrollbars.

Name:	*repeatInterval*
Class:	*RepeatInterval*
Switch:	*-repeatinterval*
     Used in conjunction with *repeatDelay*:  once auto-repeat begins,
     this option determines the number of milliseconds between
     auto-repeats.

Name:	*selectBackground*
Class:	*Foreground*
Switch:	*-selectbackground*
     Specifies the background color to use when displaying selected items.

Name:	*selectBorderWidth*
Class:	*BorderWidth*
Switch:	*-selectborderwidth*
     Specifies a non-negative value indicating the width of the 3-D border
     to draw around selected items.  The value may have any of the forms
     acceptable to *Tk_GetPixels*.

Name:	*selectForeground*
Class:	Background
Switch:	*-selectforeground*
     Specifies the foreground color to use when displaying selected items.

Name:	*setGrid*
Class:	*SetGrid*
Switch:	*-setgrid*
     Specifies a boolean value that determines whether this widget
     controls the resizing grid for its top-level window.  This option is
     typically used in text widgets, where the information in the widget
     has a natural size (the size of a character) and it makes sense for
     the window's dimensions to be integral numbers of these units.  These
     natural window sizes form a grid.  If the *setGrid* option is set to
     true then the widget will communicate with the window manager so that
     when the user interactively resizes the top-level window that
     contains the widget, the dimensions of the window will be displayed
     to the user in grid units and the window size will be constrained to
     integral numbers of grid units.  See `"GRIDDED GEOMETRY MANAGEMENT"',
     see Tk/Wm, for more details.

Name:	*takeFocus*
Class:	*TakeFocus*
Switch:	*-takefocus*
     Determines whether the window accepts the focus during keyboard
     traversal (e.g., Tab and Shift-Tab).  Before setting the focus to a
     window, the traversal scripts consult the value of the *takeFocus*
     option.  A value of 0 means that the window should be skipped entirely
     during keyboard traversal.  1 means that the window should receive
     the input focus as long as it is viewable (it and all of its
     ancestors are mapped).  An empty value for the option means that the
     traversal scripts make the decision about whether or not to focus on
     the window:  the current algorithm is to skip the window if it is
     disabled, if it has no key bindings, or if it is not viewable.  If
     the value has any other form, then the traversal scripts take the
     value, append the name of the window to it (with a separator space),
     and evaluate the resulting string as a Callback.  The script must
     return 0, 1, or an empty string:  a 0 or 1 value specifies whether
     the window will receive the input focus, and an empty string results
     in the default decision described above.  Note: this interpretation
     of the option is defined entirely by the Callbacks that implement
     traversal:  the widget implementations ignore the option entirely, so
     you can change its meaning if you redefine the keyboard traversal
     scripts.

Name:	text
Class:	Text
Switch:	*-text*
     Specifies a string to be displayed inside the widget.  The way in
     which the string is displayed depends on the particular widget and
     may be determined by other options, such as anchor or justify.

Name:	*textVariable*
Class:	Variable
Switch:	*-textvariable*
     Specifies the name of a variable.  The value of the variable is a text
     string to be displayed inside the widget;  if the variable value
     changes then the widget will automatically update itself to reflect
     the new value.  The way in which the string is displayed in the
     widget depends on the particular widget and may be determined by
     other options, such as anchor or justify.

Name:	*troughColor*
Class:	Background
Switch:	*-troughcolor*
     Specifies the color to use for the rectangular trough areas in
     widgets such as scrollbars and scales.

Name:	*troughTile*
Class:	*Tile*
Switch:	*-troughtile*
     Specifies image used to display in the rectangular trough areas in
     widgets such as scrollbars and scales.

Name:	underline
Class:	*Underline*
Switch:	*-underline*
     Specifies the integer index of a character to underline in the widget.
     This option is used by the default bindings to implement keyboard
     traversal for menu buttons and menu entries.  0 corresponds to the
     first character of the text displayed in the widget, 1 to the next
     character, and so on.

Name:	*wrapLength*
Class:	*WrapLength*
Switch:	*-wraplength*
     For widgets that can perform word-wrapping, this option specifies the
     maximum line length.  Lines that would exceed this length are wrapped
     onto the next line, so that no line is longer than the specified
     length.  The value may be specified in any of the standard forms for
     screen distances.  If this value is less than or equal to 0 then no
     wrapping is done:  lines will break only at newline characters in the
     text.

Name:	*xScrollCommand*
Class:	*ScrollCommand*
Switch:	*-xscrollcommand*
     Specifies a callback used to communicate with horizontal scrollbars.
     When the view in the widget's window changes (or whenever anything
     else occurs that could change the display in a scrollbar, such as a
     change in the total size of the widget's contents), the widget will
     make a callback passing two numeric arguments in addition to any
     specified in the callback.  Each of the numbers is a fraction between
     0 and 1, which indicates a position in the document.  0 indicates the
     beginning of the document, 1 indicates the end, .333 indicates a
     position one third the way through the document, and so on.  The
     first fraction indicates the first information in the document that
     is visible in the window, and the second fraction indicates the
     information just after the last portion that is visible.  Typically
     the *xScrollCommand* option consists of the scrollbar widget object
     and the method "set" i.e. [set => *$sb*]: this will cause the
     scrollbar to be updated whenever the view in the window changes.  If
     this option is not specified, then no command will be executed.

Name:	*yScrollCommand*
Class:	*ScrollCommand*
Switch:	*-yscrollcommand*
     Specifies a calback used to communicate with vertical scrollbars.
     This option is treated in the same way as the *xScrollCommand*
     option, except that it is used for vertical scrollbars and is
     provided by widgets that support vertical scrolling.  See the
     description of *xScrollCommand* for details on how this option is
     used.

SEE ALSO
========

   `Tk::option|Tk::option' in this node `Tk::callbacks|Tk::callbacks' in
this node `Tk::configspec|Tk::configspec' in this node
`Tk_GetPixels|Tk::pTk::GetPixels' in this node

KEYWORDS
========

   class, name, standard option, switch

An overview of an Object Oriented Tk8.0 extension for perl5
***********************************************************

NAME
====

   Tk - An overview of an Object Oriented Tk8.0 extension for perl5

   use Tk;

   $main = MainWindow->new();

   $widget = $main->*Widget*(...);

   $widget->pack(...);

   ...

   MainLoop;

DESCRIPTION
===========

   In writing the perl Tk extension, the goals were to provide a complete
interface to the latest production version of John Ousterhout's Tk, while
providing an Object Oriented interface to perl code.

CONTENTS
========

   The package is composed of three loosely connected parts:

pTk - Converted Tk source
     The pTk sub-directory is a copy of the C code of Tk4.0, modified to
     allow use by languages other than the original Tcl.  (The pTk can be
     read as 'perl' Tk or 'portable' Tk, depending on your sensibilities.)

Tk to Perl 'Glue'
     The top level directory provides *Tk.xs* and *tkGlue.c* which provide
     the perl-callable interfaces to pTk

Perl code for 'Widget' Classes
     The *Tk/Tk* sub-directory contains the various perl modules that
     comprise the "Classes" that are visible to Tk applications.

     The "major" widgets such as *Tk::Text* are actually in separate
     directories at the top level (e.g. *Text/** for *Tk::Text*) and are
     dynamically loaded as needed on platforms which support perl5's
     DynaLoader.

CLASS HIERARCHY
===============

*package Tk;* - the 'base class'
     All the "command names" documented in Tcl/Tk are made to look like
     perl sub's and reside in the Tk package. Their names are all lower
     case.  Typically there are very few commands at this level which are
     called directly by applications.

*package Tk::Widget;* - the 'Widget class'
     There are no actual objects of the *Tk::Widget* class; however all
     the various Tk window "widgets" inherit from it, and it in turn
     inherits all the core Tk functions from Tk.

     *Tk::Widget* provides various functions and interfaces which are
     common to all Widgets.

     A widget is represented to perl as a blessed reference to a hash.
     There are some members of the hash which are private to Tk and its
     tkGlue code.  Keys starting with *'.'* and of the form
     */_[A-Z][A-Za-z_]+_/* (i.e. starting and ending in _ and with  first
     char after _ being upper case) should be considered reserved to Tk.

*Tk::Button*, *Tk::Entry*, *Tk::Text* ...
     There is one class for each of the "Tk" widget item types.  Some of
     them like *Tk::Frame* do very little indeed, and really only exist so
     that they can be derived from or so that focus or menu traversal can
     discover the "kind" of window being processed.

     Other classes, *Tk::Text* for example, provide a lot of methods used
     with Tk's "bind" to provide a rich keyboard/mouse interface to the
     widgets' data.

     These widget classes also include conversions of the Tcl code for
     event bindings, keyboard focus traversal, menu bars, and menu keyboard
     traversal. All the Tcl functions have been converted, but the names
     have changed (systematically) and they have been split up between the
     various classes in what I hope is an appropriate manner.  Name
     changes are normally: dropping initial tk_ as the Tk-ness is implicit
     in the *Tk::* prefix, and similarly dropping say Menu from the name
     if it has been moved the Tk::Menu class.  Thus 'proc tkMenuNextEntry'
     becomes 'sub NextEntry' in the Tk::Menu package.

Tk::Image
     This does for Tk4.0's "images" what *Tk::Widget* does for widgets.
     Images are new to Tk4.0 and the class structure is not mature either.

     There are three sub-classes *Tk::Bitmap*, *Tk::Pixmap* and
     *Tk::Photo*.

     It is expected that Tk::Image hierarchy will evolve during the "beta"
     phase of Tk to allow dynamic or auto-loaded image types or photo
     formats (e.g. support for JPEG format for photos).

Composite Widgets
     A composite is some kind of 'frame' with subwidgets which give it
     useful behaviour.  *Tk::Dialog* is an example of a composite widget
     classes built from the basic Tk ones.  It is intended that user code
     should not need to be aware that a particular class is a composite,
     and create and configure such widgets in the same manner as any other
     kind. The configure mechanism and the methods of the class manipulate
     the subwidgets as required.

     Composite widgets are implemented via *Tk::Frame* and multiple
     inheritance.  The two 'frame' base classes *Tk::Frame* and
     *Tk::Toplevel* include the additional class *Tk::Derived* in their
     inheritance. *Tk::Derived* provides methods to allow additional
     configure options to be defined for a widget.

     A Composite widget is typically defined as derived from *Tk::Frame*
     or *Tk::Toplevel* (e.g. *Tk::Dialog*).

how to make your Tk source portable to other interpreted languages.
*******************************************************************

NAME
====

   Tk2portableTk - how to make your Tk source portable to other
interpreted languages.

   Ilya Zakharevich <ilya@math.ohio-state.edu>  has contributed most of
this document. Many thanks.

DESCRIPTION
===========

   *PortableTk* is an attempt to make Tk useful from other languages.
Currently tk4.0 runs under Perl using this approach. Below, *Lang* is the
notation for an external language to which *PortableTk* glues Tk code.

   The main problem with using the code developed for *TCL* with different
languages is the absence of data types: almost anything is `char*'. It
makes automatic translation hopeless. However, if you `typedef' several
new symbols to be `char*', you can still use your code in *TCL*, and it
will make the automatic translation possible.

   Another problem with the approach that "everything is a string" is
impossibility to have a result that says "NotApplicable" without setting
an error. Thus different Tk command return different string values that
mean "error happened", like "", `" "' or `"??"'. Other languages can be
more flexible, so in *portableTk* you should inform the compiler that what
you want to return means "error" (see `Setting variables' in this node).

   Currently *PortableTk* uses several different approachs to simplify
translation: several *TCL* functions that are especially dangerous to use
are undefined, so you can easily find places that need to be updated to
use Language-independent functions based on compiler warnings.  Eventually
a way to use these Language-independent functions under proper *TCL* will
be also provided.  The end of this document provides a starting point for
such a project.

Structure of pTk, porting your code
===================================

   pTk, that is a port of Tk, is very special with respect to porting of
other code to *portableTk*. The problem is that currently there is very
little hope to merge the modifications back into Tk, so a special strategy
is needed to maintain this port. Do not use this strategy to port your own
code.

   pTk is produced from Tk via a two-step process: first, some manual
editing (the result is in the subdirectory `mTk'), and second, automatic
conversion by the munge script (written in Perl). Thus the subdirectory
`pTk/mTk' contains code with minimal possible difference from the virgin
Tk code, so it is easier to merge(1) the differences between Tk versions
into modified code.

   It looks like the strategy for a portable code should be exactly
opposite: starting from *TCL*-based code, apply munge, and then hand-edit
the resulting code. Probably it is also possible to target your code to
*portableTk* from scratch, since this will make it possible to run it
under a lot of *Lang*uages.

   The only reason anyone would like to look into contents of `pTk/mTk'
directory is to find out which constructs are not supported by munge. On
the other hand, pTk directory contains code that is conformant to
*portableTk*, so you can look there to find example code.

   munge is the script that converts most common Tk constructs to their
`portableTk' equivalent. For your code to qualify, you should follow Tk
conventions on indentation and names of variables, in particular, the
array of arguments for the `...CmdProc' should be called `argv'.

   For details on what munge can do, see `Translation of some TCL
functions' in this node.

*PortableTk* API
================

Checking what you are running under
-----------------------------------

   *PortableTk* provides a symbol `????'. If this symbol is defined, your
source is compiled with it.

New types of configuration options
----------------------------------

   *PortableTk* defines several new types of configuration options:

     TK_CONFIG_CALLBACK
     TK_CONFIG_LANGARG
     TK_CONFIG_SCALARVAR
     TK_CONFIG_HASHVAR
     TK_CONFIG_ARRAYVAR
     TK_CONFIG_IMAGE

   You should use them instead of TK_CONFIG_STRING whenever appropriate.
This allows your application to receive a direct representation of the
corresponding resource instead of the string representation, if this is
possible under given language.

   ???? It looks like `TK_CONFIG_IMAGE' and `TK_CONFIG_SCALARVAR' set
variables of type `char*'.

Language data
-------------

   The following data types are defined:

Arg
     is the main datatype of the language.  This is a type that your C
     function gets pointers to for arguments when the corresponding *Lang*
     function is called.  The corresponding config type is
     `TK_CONFIG_LANGARG'.

     This is also a type that keeps information about contents of *Lang*
     variable.

Var
     Is a substitute for a `char *' that contains name of variable. In
     *Lang* it is an object that contains reference to another *Lang*
     variable.

`LangResultSave'
     ????

`LangCallback'
     `LangCallback*' a substitute for a `char *' that contains command to
     call. The corresponding config type is `TK_CONFIG_CALLBACK'.

`LangFreeProc'
     It is the type that the `Lang_SplitList' sets. Before you call it,
     declare

          Args *args;
          LangFreeProc *freeProc = NULL;
          ...
          code = Lang_SplitList(interp, value,
          	&argc, &args, &freeProc);

     After you use the split values, call

          if (args != NULL && freeProc) (*freeProc)(argc,args);

     It is not guaranteed that the args can survive deletion of value.

Conversion
----------

   The following macros and functions are used for conversion between
strings and the additional types:

     LangCallback * LangMakeCallback(Arg)
     Arg LangCallbackArg(LangCallback *)
     char * LangString(Arg)

   After you use the result of LangCallbackArg(), you should free it with
`freeProc' `LANG_DYNAMIC' (it is not guaranteed that any change of Arg
will not be reflected in <LangCallback>, so you cannot do LangSet...() in
between, and you should reset it to NULL if you want to do any further
assignments to this Arg).

   The following function returns the Arg that is a reference to Var:

     Arg LangVarArg(Var)

   ???? It is very anti-intuitive, I hope the name is changed.

     int LangCmpCallback(LangCallback *a,Arg b)

   (currently only a stub), and, at last,

     LangCallback * LangCopyCallback(LangCallback *)

Callbacks
---------

   Above we have seen the new datatype `LangCallback' and the
corresponding *Config option*  `TK_CONFIG_CALLBACK'. The following
functions are provided for manipulation of `LangCallback's:

     void LangFreeCallback(LangCallback *)
     int LangDoCallback(Tcl_Interp *,LangCallback *,
     	int result,int argc, char *format,...)

   The argument format of `LangDoCallback' should contain a string that is
suitable for sprintf with optional arguments of `LangDoCallback'.  result
should be false if result of callback is not needed.

     int LangMethodCall(Tcl_Interp *,Arg,char *method,
     	int result,int argc,...)

   ????

   Conceptually, `LangCallback*' is a substitute for ubiquitous `char *'
in *TCL*. So you should use `LangFreeCallback' instead of `ckfree' or free
if appropriate.

Setting variables
-----------------

     void LangFreeArg (Arg, Tcl_FreeProc *freeProc)
     Arg  LangCopyArg (Arg);
     void Tcl_AppendArg (Tcl_Interp *interp, Arg)
     void LangSetString(Arg *, char *s)
     void LangSetDefault(Arg *, char *s)

   These two are equivalent unless s is an empty string. In this case
`LangSetDefault' behaves like `LangSetString' with `s==NULL', i.e., it
sets the current value of the *Lang* variable to be false.

     void LangSetInt(Arg *,int)
     void LangSetDouble(Arg *,double)

   The *Lang* functions separate uninitialized and initialized data
comparing data with NULL. So the declaration for an Arg should look like

     Arg arg = NULL;

   if you want to use this `arg' with the above functions. After you are
done, you should use `LangFreeArg' with `TCL_DYNAMIC' as `freeProc'.

Language functions
------------------

   Use

`int  LangNull(Arg)'
     to check that an object is false;

`int  LangStringMatch(char *string, Arg match)'
     ????

`void LangExit(int)'
     to make a proper shutdown;

`int LangEval(Tcl_Interp *interp, char *cmd, int global)'
     to call *Lang* eval;

`void Lang_SetErrorCode(Tcl_Interp *interp,char *code)'
`char *Lang_GetErrorCode(Tcl_Interp *interp)'
`char *Lang_GetErrorInfo(Tcl_Interp *interp)'
`void LangCloseHandler(Tcl_Interp *interp,Arg arg,FILE *f,Lang_FileCloseProc *proc)'
     currently stubs only;

`int LangSaveVar(Tcl_Interp *,Arg arg,Var *varPtr,int type)'
     to save the structure `arg' into *Lang* variable `*varPtr';

`void LangFreeVar(Var var)'
     to free the result;

`int LangEventCallback(Tcl_Interp *,LangCallback *,XEvent *,KeySym)'
     ????

`int LangEventHook(int flags)'
`void LangBadFile(int fd)'
`int LangCmpConfig(char *spec, char *arg, size_t length)'
     unsupported????;

`void Tcl_AppendArg (Tcl_Interp *interp, Arg)'
   Another useful construction is

     Arg variable = LangFindVar(interp, Tk_Window tkwin, char *name);

   After using the above function, you should call

     LangFreeVar(Var variable);

   ???? Note discrepancy in types!

   If you want to find the value of a variable (of type Arg) given the
variable name, use `Tcl_GetVar(interp, varName, flags)'. If you are
interested in the string value of this variable, use
`LangString(Tcl_GetVar(...))'.

   To get a C array of Arg of length n, use

     Arg *args = LangAllocVec(n);
     ...
     LangFreeVec(n,args);

   You can set the values of the Args using `LangSet...' functions, and
get string value using `LangString'.

   If you want to merge an array of Args into one Arg (that will be an
array variable), use

     result = Tcl_Merge(listLength, list);

Translation of some TCL functions
---------------------------------

   We mark items that can be dealt with by munge by *Autoconverted*.

`Tcl_AppendResult'
     does not take `(char*)NULL', but NULL as delimiter. *Autoconverted*.

`Tcl_CreateCommand', `Tcl_DeleteCommand'
     `Tk_CreateWidget', `Tk_DeleteWidget', the second argument is the
     window itself, not the pathname. *Autoconverted*.

`sprintf(interp->result, "%d %d %d %d",...)'
     `Tcl_IntResults(interp,4,0,...)'. *Autoconverted*.

`interp->result = "1";'
     `Tcl_SetResult(interp,"1", TCL_STATIC)'. *Autoconverted*.

Reading `interp->result'
     `Tcl_GetResult(interp)'. *Autoconverted*.

`interp->result = Tk_PathName(textPtr->tkwin);'
     `Tk_WidgetResult(interp,textPtr->tkwin)'. *Autoconverted*.

Sequence `Tcl_PrintDouble, Tcl_PrintDouble, ..., Tcl_AppendResult'
     Use a single command

          void Tcl_DoubleResults(Tcl_Interp *interp, int append,
          	int argc,...);

     append governs whether it is required to clear the result first.

     A similar command for int arguments is `Tcl_IntResults'.

`Tcl_SplitList'
     Use `Lang_SplitList' (see the description above).

Translation back to TCL
=======================

   To use your *portableTk* program with *TCL*, put

     #include "ptcl.h"

   before inclusion of `tk.h', and link the resulting code with
`ptclGlue.c'.

   These files currently implement the following:

Additional config types:
          TK_CONFIG_CALLBACK
          TK_CONFIG_LANGARG
          TK_CONFIG_SCALARVAR
          TK_CONFIG_HASHVAR
          TK_CONFIG_ARRAYVAR
          TK_CONFIG_IMAGE

Types:
          Var, Arg, LangCallback, LangFreeProc.

Functions and macros:
          Lang_SplitList, LangString, LangSetString, LangSetDefault,
          LangSetInt, LangSetDouble Tcl_ArgResult, LangCallbackArg,
          LangSaveVar, LangFreeVar,
          LangFreeSplitProc, LangFreeArg, Tcl_DoubleResults, Tcl_IntResults,
          LangDoCallback, Tk_WidgetResult, Tcl_CreateCommand,
          Tcl_DeleteCommand, Tcl_GetResult.

   Current implementation contains enough to make it possible to compile
`mTk/tkText*.[ch]' with the virgin Tk.

New types of events ????
------------------------

   PortableTk defines following new types of events:

     TK_EVENTTYPE_NONE
     TK_EVENTTYPE_STRING
     TK_EVENTTYPE_NUMBER
     TK_EVENTTYPE_WINDOW
     TK_EVENTTYPE_ATOM
     TK_EVENTTYPE_DISPLAY
     TK_EVENTTYPE_DATA

   and a function

     char *	Tk_EventInfo(int letter,
     	    Tk_Window tkwin, XEvent *eventPtr,
     	    KeySym keySym, int *numPtr, int *isNum, int *type,
                int num_size, char *numStorage)

Checking for trouble
====================

   If you start with working TCL code, you can start convertion using the
above hints. Good indication that you are doing is OK is absence of
sprintf and sscanf in your code (at least in the part that is working with
interpreter).

Additional API
==============

   What is described here is not included into base *portableTk*
distribution. Currently it is coded in *TCL* and as Perl macros (core is
coded as functions, so theoretically you can use the same object files
with different interpreted languages).

`ListFactory'
-------------

   Dynamic arrays in *TCL* are used for two different purposes: to
construct strings, and to construct lists. These two usages will have
separate interfaces in other languages (since list is a different type
from a string), so you should use a different interface in your code.

   The type for construction of dynamic lists is `ListFactory'. The API
below is a counterpart of the API for construction of dynamic lists in
*TCL*:

     void ListFactoryInit(ListFactory *)
     void ListFactoryFinish(ListFactory *)
     void ListFactoryFree(ListFactory *)
     Arg * ListFactoryArg(ListFactory *)
     void ListFactoryAppend(ListFactory *, Arg *arg)
     void ListFactoryAppendCopy(ListFactory *, Arg *arg)
     ListFactory * ListFactoryNewLevel(ListFactory *)
     ListFactory * ListFactoryEndLevel(ListFactory *)
     void ListFactoryResult(Tcl_Interp *, ListFactory *)

   The difference is that a call to `ListFactoryFinish' should precede the
actual usage of the value of `ListFactory', and there are two different
ways to append an Arg to a `ListFactory': ListFactoryAppendCopy()
guarantees that the value of `arg' is copied to the list, but
ListFactoryAppend() may append to the list a reference to the current
value of `arg'. If you are not going to change the value of `arg' after
appending, the call to ListFactoryAppend may be quicker.

   As in *TCL*, the call to ListFactoryFree() does not free the
`ListFactory', only the objects it references.

   The functions ListFactoryNewLevel() and ListFactoryEndLevel() return a
pointer to a `ListFactory' to fill. The argument of ListFactoryEndLevel()
cannot be used after a call to this function.

DStrings
--------

   Production of strings are still supported in *portableTk*.

Accessing Args
--------------

   The following functions for getting a value of an Arg may be provided:

     double LangDouble(Arg)
     int LangInt(Arg)
     long LangLong(Arg)
     int LangIsList(Arg arg)

   The function LangIsList() is supported only partially under *TCL*,
since there is no data types. It checks whether there is a space inside
the string `arg'.

Assigning numbers to Args
-------------------------

   While LangSetDouble() and LangSetInt() are supported ways to assign
numbers to assign an integer value to a variable, for the sake of
efficiency under *TCL* it is supposed that the destination of these
commands was massaged before the call so it contains a long enough string
to sprintf() the numbers inside it. If you are going to immediately use
the resulting Arg, the best way to do this is to declare a buffer in the
beginning of a block by

     dArgBuffer;

   and assign this buffer to the Arg by

     void LangSetDefaultBuffer(Arg *)

   You can also create the buffer(s) manually and assign them using

     void LangSetBuffer(Arg *, char *)

   This is the only choice if you need to assign numeric values to several
Args simultaneously. The advantage of the first approach is that the above
declarations can be made nops in different languages.

   Note that if you apply `LangSetDefaultBuffer' to an Arg that contains
some value, you can create a leak if you do not free that Arg first. This
is a non-problem in real languages, but can be a trouble in `TCL', unless
you use only the above API.

Creating new Args
-----------------

   The API for creating a new Arg is

     void LangNewArg(Arg *, LangFreeProc *)

   The API for creating a new Arg is absent. Just initialize Arg to be
NULL, and apply one of `LangSet...' methods.

   After you use this Arg, it should be freed thusly:

   `LangFreeArg(arg, freeProc)'.

Evaluating a list
-----------------

   Use

     int LangArgEval(Tcl_Interp *, Arg arg)

   Here `arg' should be a list to evaluate, in particular, the first
element should be a `LangCallback' massaged to be an Arg. The arguments
can be send to the subroutine by reference or by value in different
languages.

Getting result as Arg
---------------------

   Use `Tcl_ArgResult'. It is not guaranteed that result survives this
operation, so the Arg you get should be the only mean to access the data
from this moment on. After you use this Arg, you should free it with
`freeProc' `LANG_DYNAMIC' (you can do LangSet...() in between).

Geometry manager that packs around edges of cavity
**************************************************

NAME
====

   Tk::pack - Geometry manager that packs around edges of cavity

       $widget->pack?(args)?

       $widget->packOption?(args)?

DESCRIPTION
===========

   The pack method is used to communicate with the packer, a geometry
manager that arranges the children of a parent by packing them in order
around the edges of the parent.

   In this *perl* port of Tk it is normal to pack widgets one-at-a-time
using the widget object to be packed to invoke a method call.  This is a
slight distortion of underlying Tk interface (which can handle lists of
windows to one pack method call) but has proven effective in practice.

   The pack method can have any of several forms, depending on Option:

*$slave*->pack?(options)?
     The options consist of pairs of arguments that specify how to manage
     the slave.  See `"THE PACKER ALGORITHM"' in this node below for
     details on how the options are used by the packer.  The following
     options are supported:

    *-after* => *$other*
          *$other* must be another window.  Use its master as the master
          for the slave, and insert the slave just after *$other* in the
          packing order.

    *-anchor* => anchor
          Anchor must be a valid anchor position such as n or sw; it
          specifies where to position each slave in its parcel.  Defaults
          to center.

    *-before* => *$other*
          *$other* must be another window.  Use its master as the master
          for the slave, and insert the slave just before *$other* in the
          packing order.

    *-expand* => boolean
          Specifies whether the slave should be expanded to consume extra
          space in their master.  Boolean may have any proper boolean
          value, such as 1 or no.  Defaults to 0.

    *-fill* => style
          If a slave's parcel is larger than its requested dimensions, this
          option may be used to stretch the slave.  Style must have one of
          the following values:

         none
               Give the slave its requested dimensions plus any internal
               padding requested with *-ipadx* or *-ipady*.  This is the
               default.

         x
               Stretch the slave horizontally to fill the entire width of
               its parcel (except leave external padding as specified by
               *-padx*).

         y
               Stretch the slave vertically to fill the entire height of
               its parcel (except leave external padding as specified by
               *-pady*).

         both
               Stretch the slave both horizontally and vertically.

    *-in* => *$master*
          Insert the slave(s) at the end of the packing order for the
          master window given by *$master*.

    *-ipadx* => *amount*
          *Amount* specifies how much horizontal internal padding to leave
          on each side of the slave(s).  *Amount* must be a valid screen
          distance, such as 2 or *.5c*.  It defaults to 0.

    *-ipady* => *amount*
          *Amount* specifies how much vertical internal padding to leave
          on each side of the slave(s).  *Amount*  defaults to 0.

    *-padx* => *amount*
          *Amount* specifies how much horizontal external padding to leave
          on each side of the slave(s).  *Amount* defaults to 0.

    *-pady* => *amount*
          *Amount* specifies how much vertical external padding to leave
          on each side of the slave(s).  *Amount* defaults to 0.

    *-side* => *side*
          Specifies which side of the master the slave(s) will be packed
          against.  Must be left, right, top, or *bottom*.  Defaults to
          top.

   If no *-in*, *-after* or *-before* option is specified then slave will
be inserted at the end of the packing list for its parent unless it is
already managed by the packer (in which case it will be left where it is).
If one of these options is specified then slave will be inserted at the
specified point.  If the slave are already managed by the geometry manager
then any unspecified options for them retain their previous values rather
than receiving default values.

*$slave*->*packForget*
     Removes slave from the packing order for its master and unmaps its
     window.  The slave will no longer be managed by the packer.

*$slave*->*packInfo*
     Returns a list whose elements are the current configuration state of
     the slave given by *$slave* in the same option-value form that might
     be specified to *packConfigure*.  The first two elements of the list
     are "*-in*=>*$master*" where *$master* is the slave's master.

*$master*->*packPropagate*?(boolean)?
     If boolean has a true boolean value such as 1 or *on* then
     propagation is enabled for *$master*, (see `"GEOMETRY PROPAGATION"'
     in this node below).  If boolean has a false boolean value then
     propagation is disabled for *$master*.  In either of these cases an
     empty string is returned.  If boolean is omitted then the method
     returns 0 or 1 to indicate whether propagation is currently enabled
     for *$master*.  Propagation is enabled by default.

*$master*->*packSlaves*
     Returns a list of all of the slaves in the packing order for
     *$master*.  The order of the slaves in the list is the same as their
     order in the packing order.  If *$master* has no slaves then an empty
     list/string is returned in array/scalar context, respectively

THE PACKER ALGORITHM
====================

   For each master the packer maintains an ordered list of slaves called
the *packing list*.  The *-in*, *-after*, and *-before* configuration
options are used to specify the master for each slave and the slave's
position in the packing list.  If none of these options is given for a
slave then the slave is added to the end of the packing list for its
parent.

   The packer arranges the slaves for a master by scanning the packing
list in order.  At the time it processes each slave, a rectangular area
within the master is still unallocated.  This area is called the *cavity*;
for the first slave it is the entire area of the master.

   For each slave the packer carries out the following steps:

[1]
     The packer allocates a rectangular *parcel* for the slave along the
     side of the cavity given by the slave's *-side* option.  If the side
     is top or bottom then the width of the parcel is the width of the
     cavity and its height is the requested height of the slave plus the
     *-ipady* and *-pady* options.  For the left or right side the height
     of the parcel is the height of the cavity and the width is the
     requested width of the slave plus the *-ipadx* and *-padx* options.
     The parcel may be enlarged further because of the *-expand* option
     (see `"EXPANSION"' in this node below)

[2]
     The packer chooses the dimensions of the slave.  The width will
     normally be the slave's requested width plus twice its *-ipadx*
     option and the height will normally be the slave's requested height
     plus twice its *-ipady* option.  However, if the *-fill* option is x
     or both then the width of the slave is expanded to fill the width of
     the parcel, minus twice the *-padx* option.  If the *-fill* option is
     y or both then the height of the slave is expanded to fill the width
     of the parcel, minus twice the *-pady* option.

[3]
     The packer positions the slave over its parcel.  If the slave is
     smaller than the parcel then the *-anchor* option determines where in
     the parcel the slave will be placed.  If *-padx* or *-pady* is
     non-zero, then the given amount of external padding will always be
     left between the slave and the edges of the parcel.

     Once a given slave has been packed, the area of its parcel is
     subtracted from the cavity, leaving a smaller rectangular cavity for
     the next slave.  If a slave doesn't use all of its parcel, the unused
     space in the parcel will not be used by subsequent slaves.  If the
     cavity should become too small to meet the needs of a slave then the
     slave will be given whatever space is left in the cavity.  If the
     cavity shrinks to zero size, then all remaining slaves on the packing
     list will be unmapped from the screen until the master window becomes
     large enough to hold them again.

EXPANSION
=========

   If a master window is so large that there will be extra space left over
after all of its slaves have been packed, then the extra space is
distributed uniformly among all of the slaves for which the *-expand*
option is set.  Extra horizontal space is distributed among the expandable
slaves whose *-side* is left or right, and extra vertical space is
distributed among the expandable slaves whose *-side* is top or *bottom*.

GEOMETRY PROPAGATION
====================

   The packer normally computes how large a master must be to just exactly
meet the needs of its slaves, and it sets the requested width and height
of the master to these dimensions.  This causes geometry information to
propagate up through a window hierarchy to a top-level window so that the
entire sub-tree sizes itself to fit the needs of the leaf windows.
However, the *packPropagate* method may be used to turn off propagation
for one or more masters.  If propagation is disabled then the packer will
not set the requested width and height of the packer.  This may be useful
if, for example, you wish for a master window to have a fixed size that
you specify.

RESTRICTIONS ON MASTER WINDOWS
==============================

   The master for each slave must either be the slave's parent (the
default) or a descendant of the slave's parent.  This restriction is
necessary to guarantee that the slave can be placed over any part of its
master that is visible without danger of the slave being clipped by its
parent.

PACKING ORDER
=============

   If the master for a slave is not its parent then you must make sure
that the slave is higher in the stacking order than the master.  Otherwise
the master will obscure the slave and it will appear as if the slave
hasn't been packed correctly.  The easiest way to make sure the slave is
higher than the master is to create the master window first:  the most
recently created window will be highest in the stacking order.  Or, you
can use the raise and *lower* methods to change the stacking order of
either the master or the slave.

SEE ALSO
========

   `Tk::form|Tk::form' in this node `Tk::grid|Tk::grid' in this node
`Tk::place|Tk::place' in this node

KEYWORDS
========

   geometry manager, location, packer, parcel, propagation, size

Modify the Tk color palette
***************************

NAME
====

   setPalette, bisque - Modify the Tk color palette

   $widget->*setPalette*(background)

   $widget->*setPalette(*name=>value?,name=>*value ...*?)

   $widget->*bisque*

DESCRIPTION
===========

   The *setPalette* method changes the color scheme for Tk.  It does this
by modifying the colors of existing widgets and by changing the option
database so that future widgets will use the new color scheme.  If
*setPalette* is invoked with a single argument, the argument is the name
of a color to use as the normal background color;  *setPalette* will
compute a complete color palette from this background color.
Alternatively, the arguments to *setPalette* may consist of any number of
name-value pairs, where the first argument of the pair is the name of an
option in the Tk option database and the second argument is the new value
to use for that option.  The following database names are currently
supported:

     activeBackground	foreground	selectColor
     activeForeground	highlightBackground	selectBackground
     background	highlightColor	selectForeground
     disabledForeground	insertBackground	troughColor

   *setPalette* tries to compute reasonable defaults for any options that
you don't specify.  You can specify options other than the above ones and
Tk will change those options on widgets as well.  This feature may be
useful if you are using custom widgets with additional color options.

   Once it has computed the new value to use for each of the color options,
*setPalette* scans the widget hierarchy to modify the options of all
existing widgets.  For each widget, it checks to see if any of the above
options is defined for the widget.  If so, and if the option's current
value is the default, then the value is changed;  if the option has a
value other than the default, *setPalette* will not change it.  The
default for an option is the one provided by the widget
(*($w->configure('option'))[3]*) unless *setPalette* has been run
previously, in which case it is the value specified in the previous
invocation of *setPalette*.

   After modifying all the widgets in the application, *setPalette* adds
options to the option database to change the defaults for widgets created
in the future.  The new options are added at priority widgetDefault, so
they will be overridden by options from the .Xdefaults file or options
specified on the command-line that creates a widget.

   The method *bisque* is provided for backward compatibility: it restores
the application's colors to the light brown ("bisque") color scheme used
in Tk 3.6 and earlier versions.

BUGS
====

   The use of option database names rather than the configure names is
understandable given the mechanism (copied from Tcl/Tk), but is
potentially confusing.

   The interpolation of different 'shades' of color used for 3D effects in
'RGB' space can lead to undesirable changes in 'hue'.  Interpolation in
'HSV' (as used in *Tk::ColorEditor*) would be more robust and X11R5's
color support probably even more so.

SEE ALSO
========

   `Tk::options|Tk::options' in this node

KEYWORDS
========

   bisque, color, palette

Geometry manager for fixed or rubber-sheet placement
****************************************************

NAME
====

   Tk::place - Geometry manager for fixed or rubber-sheet placement

      $widget->*place*?(*-option*=>value?, *-option*=>value, ...)?

      $widget->*placeForget*

      $widget->*placeInfo*

      *$master*->*placeSlaves*

DESCRIPTION
===========

   The placer is a geometry manager for Tk.  It provides simple fixed
placement of windows, where you specify the exact size and location of one
window, called the slave, within another window, called the *$master*.
The placer also provides rubber-sheet placement, where you specify the
size and location of the slave in terms of the dimensions of the master,
so that the slave changes size and location in response to changes in the
size of the master.  Lastly, the placer allows you to mix these styles of
placement so that, for example, the slave has a fixed width and height but
is centered inside the master.

*$slave*->*place*?(*-option*=>value?, *-option*=>value, ...?)?
     The *place* method arranges for the placer to manage the geometry of
     *$slave*.  The remaining arguments consist of one or more
     *-option*=>value pairs that specify the way in which *$slave*'s
     geometry is managed.  If the placer is already managing *$slave*,
     then the *-option*=>value pairs modify the configuration for *$slave*.
     The *place* method returns an empty string as result.  The following
     *-option*=>value pairs are supported:

    *-in* => *$master*
          *$master* is the reference to the window relative to which
          *$slave* is to be placed.  *$master* must either be *$slave*'s
          parent or a descendant of *$slave*'s parent.  In addition,
          *$master* and *$slave* must both be descendants of the same
          top-level window.  These restrictions are necessary to guarantee
          that *$slave* is visible whenever *$master* is visible.  If this
          option isn't specified then the master defaults to *$slave*'s
          parent.

    -x => location
          Location specifies the x-coordinate within the master window of
          the anchor point for *$slave* widget.  The location is specified
          in screen units (i.e. any of the forms accepted by
          *Tk_GetPixels*) and need not lie within the bounds of the master
          window.

    *-relx* => location
          Location specifies the x-coordinate within the master window of
          the anchor point for *$slave* widget.  In this case the location
          is specified in a relative fashion as a floating-point number:
          0.0 corresponds to the left edge of the master and 1.0
          corresponds to the right edge of the master.  Location need not
          be in the range 0.0-1.0.  If both -x and *-relx* are specified
          for a slave then their values are summed.  For example,
          "*-relx*=>0.5, -x=-2" positions the left edge of the slave 2
          pixels to the left of the center of its master.

    -y => location
          Location specifies the y-coordinate within the master window of
          the anchor point for *$slave* widget.  The location is specified
          in screen units (i.e. any of the forms accepted by
          *Tk_GetPixels*) and need not lie within the bounds of the master
          window.

    *-rely* => location
          Location specifies the y-coordinate within the master window of
          the anchor point for *$slave* widget.  In this case the value is
          specified in a relative fashion as a floating-point number:  0.0
          corresponds to the top edge of the master and 1.0 corresponds to
          the bottom edge of the master.  Location need not be in the
          range 0.0-1.0.  If both -y and *-rely* are specified for a slave
          then their values are summed.  For example, *-rely*=>0.5, -x=>3
          positions the top edge of the slave 3 pixels below the center of
          its master.

    *-anchor* => where
          Where specifies which point of *$slave* is to be positioned at
          the (x,y) location selected by the -x, -y, *-relx*, and *-rely*
          options.  The anchor point is in terms of the outer area of
          *$slave* including its border, if any.  Thus if where is *se*
          then the lower-right corner of *$slave*'s border will appear at
          the given (x,y) location in the master.  The anchor position
          defaults to *nw*.

    *-width* => size
          Size specifies the width for *$slave* in screen units (i.e. any
          of the forms accepted by *Tk_GetPixels*).  The width will be the
          outer width of *$slave* including its border, if any.  If size
          is an empty string, or if no *-width* or *-relwidth* option is
          specified, then the width requested internally by the window
          will be used.

    *-relwidth* => size
          Size specifies the width for *$slave*.  In this case the width
          is specified as a floating-point number relative to the width of
          the master: 0.5 means *$slave* will be half as wide as the
          master, 1.0 means *$slave* will have the same width as the
          master, and so on.  If both *-width* and *-relwidth* are
          specified for a slave, their values are summed.  For example,
          *-relwidth*=>1.0, *-width*=>5 makes the slave 5 pixels wider
          than the master.

    *-height* => size
          Size specifies the height for *$slave* in screen units (i.e. any
          of the forms accepted by *Tk_GetPixels*).  The height will be
          the outer dimension of *$slave* including its border, if any.
          If size is an empty string, or if no *-height* or *-relheight*
          option is specified, then the height requested internally by the
          window will be used.

    *-relheight* => size
          Size specifies the height for *$slave*.  In this case the height
          is specified as a floating-point number relative to the height
          of the master: 0.5 means *$slave* will be half as high as the
          master, 1.0 means *$slave* will have the same height as the
          master, and so on.  If both *-height* and *-relheight* are
          specified for a slave, their values are summed.  For example,
          *-relheight*=>1.0, *-height*=>-2 makes the slave 2 pixels
          shorter than the master.

    *-bordermode* => mode
          Mode determines the degree to which borders within the master
          are used in determining the placement of the slave.  The default
          and most common value is *inside*.  In this case the placer
          considers the area of the master to be the innermost area of the
          master, inside any border: an option of -x=>0 corresponds to an
          x-coordinate just inside the border and an option of
          *-relwidth*=>1.0 means *$slave* will fill the area inside the
          master's border.  If mode is *outside* then the placer considers
          the area of the master to include its border; this mode is
          typically used when placing *$slave* outside its master, as with
          the options -x=>0, -y=>0, *-anchor*=>ne.  Lastly, mode may be
          specified as *ignore*, in which case borders are ignored:  the
          area of the master is considered to be its official X area,
          which includes any internal border but no external border.  A
          bordermode of *ignore* is probably not very useful.

          If the same value is specified separately with two different
          options, such as -x and *-relx*, then the most recent option is
          used and the older one is ignored.

*$slave*->*placeSlaves*
     The *placeSlaves* method returns a list of all the slave windows for
     which *$master* is the master.  If there are no slaves for *$master*
     then an empty list is returned.

*$slave*->*placeForget*
     The *placeForget* method causes the placer to stop managing the
     geometry of *$slave*.  As a side effect of this method call *$slave*
     will be unmapped so that it doesn't appear on the screen.  If
     *$slave* isn't currently managed by the placer then the method call
     has no effect.  *placeForget* returns an empty string as result.

*$slave*->*placeInfo*
     The *placeInfo* method returns a list giving the current
     configuration of *$slave*.  The list consists of *-option*=>value
     pairs in exactly the same form as might be specified to the *place*
     method.  If the configuration of a window has been retrieved with
     *placeInfo*, that configuration can be restored later by first using
     *placeForget* to erase any existing information for the window and
     then invoking *place* with the saved information.

FINE POINTS
===========

   It is not necessary for the master window to be the parent of the slave
window.  This feature is useful in at least two situations.  First, for
complex window layouts it means you can create a hierarchy of subwindows
whose only purpose is to assist in the layout of the parent.  The "*real
children*" of the parent (i.e. the windows that are significant for the
application's user interface) can be children of the parent yet be placed
inside the windows of the geometry-management hierarchy.  This means that
the path names of the "*real children*" don't reflect the
geometry-management hierarchy and users can specify options for the real
children without being aware of the structure of the geometry-management
hierarchy.

   A second reason for having a master different than the slave's parent
is to tie two siblings together.  For example, the placer can be used to
force a window always to be positioned centered just below one of its
siblings by specifying the configuration

       *-in*=>*$sibling*, *-relx*=>0.5, *-rely*=>1.0, *-anchor*=>'n',
*-bordermode*=>'outside'

   Whenever the *$sibling* widget is repositioned in the future, the slave
will be repositioned as well.

   Unlike many other geometry managers (such as the packer) the placer
does not make any attempt to manipulate the geometry of the master windows
or the parents of slave windows (i.e. it doesn't set their requested
sizes).  To control the sizes of these windows, make them windows like
frames and canvases that provide configuration options for this purpose.

SEE ALSO
========

   `Tk::form|Tk::form' in this node `Tk::grid|Tk::grid' in this node
`Tk::pack|Tk::pack' in this node

KEYWORDS
========

   geometry manager, height, location, master, place, rubber sheet, slave,
width

Manipulate the X selection
**************************

NAME
====

   Tk::Selection - Manipulate the X selection

   $widget->SelectionOption?(args)?

DESCRIPTION
===========

   This command provides an interface to the X selection mechanism and
implements the full selection functionality described in the X
Inter-Client Communication Conventions Manual (ICCCM).

   The widget object used to invoke the methods below determines which
display is used to access the selection.  In order to avoid conflicts with
selection methods of widget classes (e.g. Text) this set of methods uses
the prefix Selection.  The following methods are currently supported:

$widget->*SelectionClear*?(*-selection*=>selection)?
     If selection exists anywhere on $widget's display, clear it so that
     no window owns the selection anymore.  Selection specifies the X
     selection that should be cleared, and should be an atom name such as
     PRIMARY or CLIPBOARD; see the Inter-Client Communication Conventions
     Manual for complete details.  Selection defaults to PRIMARY.  Returns
     an empty string.

$widget->*SelectionGet*?(?*-selection*=>selection?,?*-type*=>type?)?
     Retrieves the value of selection from $widget's display and returns
     it as a result.  Selection defaults to PRIMARY.

     Type specifies the form in which the selection is to be returned (the
     desired "target" for conversion, in ICCCM terminology), and should be
     an atom name such as STRING or FILE_NAME; see the Inter-Client
     Communication Conventions Manual for complete details.  Type defaults
     to STRING.  The selection owner may choose to return the selection in
     any of several different representation formats, such as STRING,
     ATOM, INTEGER, etc. (this format is different than the selection
     type; see the ICCCM for all the confusing details).

     If format is not STRING then things get messy, the following
     description is from the Tcl/Tk man page as yet incompetely translated
     for the perl version - it is misleading at best.

     If the selection is returned in a non-string format, such as INTEGER
     or ATOM, the *SelectionGet* converts it to a list of perl values:
     atoms are converted to their textual names, and anything else is
     converted integers.

     A goal of the perl port is to provide better handling of different
     formats than Tcl/Tk does, which should be possible given perl's wider
     range of "types". Although some thought went into this in very early
     days of perl/Tk what exactly happens is still "not quite right" and
     subject to change.

$widget->*SelectionHandle*(?*-selection*=>selection?,?*-type*=>type?,?*-format*=>format? callback)
     Creates a handler for selection requests, such that callback will be
     executed whenever selection is owned by $widget and someone attempts
     to retrieve it in the form given by type (e.g. type is specified in
     the *selection get* command).  Selection defaults to PRIMARY, type
     defaults to STRING, and format defaults to STRING.  If callback is an
     empty string then any existing handler for $widget, type, and
     selection is removed.

     When selection is requested, $widget is the selection owner, and type
     is the requested type, callback will be executed with two additional
     arguments.  The two additional arguments are offset and *maxBytes*:
     offset specifies a starting character position in the selection and
     *maxBytes* gives the maximum number of bytes to retrieve.  The
     command should return a value consisting of at most *maxBytes* of the
     selection, starting at position offset.  For very large selections
     (larger than *maxBytes*) the selection will be retrieved using
     several invocations of callback with increasing offset values.  If
     callback returns a string whose length is less than *maxBytes*, the
     return value is assumed to include all of the remainder of the
     selection;  if the length of callback's result is equal to *maxBytes*
     then callback will be invoked again, until it eventually returns a
     result shorter than *maxBytes*.  The value of *maxBytes* will always
     be relatively large (thousands of bytes).

     If callback returns an error (e.g. via die) then the selection
     retrieval is rejected just as if the selection didn't exist at all.

     The format argument specifies the representation that should be used
     to transmit the selection to the requester (the second column of
     Table 2 of the ICCCM), and defaults to STRING.  If format is STRING,
     the selection is transmitted as 8-bit ASCII characters (i.e.  just in
     the form returned by command).

     If format is not STRING then things get messy, the following
     description is from the Tcl/Tk man page as yet untranslated for the
     perl version - it is misleading at best.

     If format is ATOM, then the return value from command is divided into
     fields separated by white space;  each field is converted to its atom
     value, and the 32-bit atom value is transmitted instead of the atom
     name.  For any other format, the return value from command is divided
     into fields separated by white space and each field is converted to a
     32-bit integer;  an array of integers is transmitted to the selection
     requester.

     The format argument is needed only for compatibility with many
     selection requesters, except Tcl/Tk.  If Tcl/Tk is being used to
     retrieve the selection then the value is converted back to a string
     at the requesting end, so format is irrelevant.

     A goal of the perl port is to provide better handling of different
     formats than Tcl/Tk does, which should be possible given perl's wider
     range of "types". Although some thought went into this in very early
     days of perl/Tk what exactly happens is still "not quite right" and
     subject to change.

    $widget->*SelectionOwner*?(*-selection*=>selection)?
          *SelectionOwner* returns the window in this application that
          owns selection on the display containing $widget, or an empty
          string if no window in this application owns the selection.
          Selection defaults to PRIMARY.

    $widget->*SelectionOwn*?(?*-command*=>callback?,?*-selection*=>selection?)?
          *SelectionOwn* causes $widget to become the new owner of
          selection on $widget's display, returning an empty string as
          result. The existing owner, if any, is notified that it has lost
          the selection.  If callback is specified, it will be executed
          when some other window claims ownership of the selection away
          from $widget.  Selection defaults to PRIMARY.

KEYWORDS
========

   clear, format, handler, ICCCM, own, selection, target, type

Execute a command in a different application
********************************************

NAME
====

   send - Execute a command in a different application

       $result = $widget->send(?options,?app=>cmd?*arg arg ...*?)

DESCRIPTION
===========

   This method arranges for cmd (and *arg*s) to be 'sent' to the
application named by app.  It returns the result or an error (hence above
should probably be 'wrapped' in *eval{}* and $@ tested).  *App* may be the
name of any application whose main window is on the display containing the
sender's main window;  it need not be within the same process.  If no
*arg* arguments are present, then the string to be sent is contained
entirely within the cmd argument.  If one or more *arg*s are present, they
are concatenated separated by white space to form the string to be sent.

   If the initial arguments of the call begin with "-" they are treated as
options.  The following options are currently defined:

*-async*
     Requests asynchronous invocation.  In this case the send command will
     complete immediately without waiting for cmd to complete in the
     target application;  no result will be available and errors in the
     sent command will be ignored.  If the target application is in the
     same process as the sending application then the *-async* option is
     ignored.

-
     Serves no purpose except to terminate the list of options.  This
     option is needed only if app could contain a leading "-" character.

APPLICATION NAMES
=================

   The name of an application is set initially from the name of the
program or script that created the application.  You can query and change
the name of an application with the *appname* method.

WHAT IS A SEND
==============

   The send mechanism was designed to allow Tcl/Tk applications to send
Tcl Scripts to each other. This does not map very well onto perl/Tk.
Perl/Tk "sends" a string to app, what happens as a result of this depends
on the receiving application. If the other application is a Tcl/Tk4.*
application it will be treated as a Tcl Script. If the "other" application
is perl/Tk application (including sends to self) then the string is passed
as an argument to a method call of the following form:

   *$mainwindow*->*Receive(*string);

   There is a default (AutoLoaded) *Tk::Receive* which returns an error to
the sending application. A particular application may define its own
*Receive* method in any class in *MainWindow*'s inheritance tree to do
whatever it sees fit. For example it could eval the string, possibly in a
Safe "compartment".

   If a Tcl/Tk application "sends" anything to a perl/Tk application then
the perl/Tk application would have to attempt to interpret the incoming
string as a Tcl Script. Simple cases are should not be too hard to emulate
(split on white space and treat first element as "command" and other
elements as arguments).

SECURITY
========

   The send command is potentially a serious security loophole, since any
application that can connect to your X server can send scripts to your
applications. Hence the default behaviour outlined above.  (With the
availability of Safe it may make sense to relax default behaviour a
little.)

   Unmonitored eval'ing of these incoming "scripts" can cause perl to read
and write files and invoke subprocesses under your name.  Host-based
access control such as that provided by *xhost* is particularly insecure,
since it allows anyone with an account on particular hosts to connect to
your server, and if disabled it allows anyone anywhere to connect to your
server.  In order to provide at least a small amount of security, core Tk
checks the access control being used by the server and rejects incoming
sends unless (a) *xhost*-style access control is enabled (i.e. only
certain hosts can establish connections) and (b) the list of enabled hosts
is empty.  This means that applications cannot connect to your server
unless they use some other form of authorization such as that provide by
*xauth*.

SEE ALSO
========

   Perl's eval perl's Safe Module system's administrator/corporate
security guidelines etc.

KEYWORDS
========

   application, name, remote execution, security, send

Tix's addition to the standard TK wm command.
*********************************************

NAME
====

   Tk::tixWm - Tix's addition to the standard TK wm command.

       $widget->*wmCapture*

       $widget->*wmRelease*

DESCRIPTION
===========

   The *wmCapture* and the *wmRelease* methods change the toplevel
attribute of Tk widgets.

METHODS
=======

$widget->*wmCapture*
     Converts the toplevel window specified by $widget into a non-toplevel
     widget. Normally this command is called to convert a
     `Toplevel|Tk::Toplevel' in this node widget into a `Frame|Tk::Frame'
     in this node widget. The newly-converted frame widget is un-mapped
     from the screen. To make it appear inside its parent, you must call a
     geometry manager (e.g. grid or pack) explictly.

$widget->*wmRelease*
     Makes the non-toplevel window specified by $widget into a toplevel
     widget. Normally this command is called to convert a
     `Frame|Tk::Frame' in this node widget into a `Toplevel|Tk::Toplevel'
     in this node widget, but it can also be used on any non-toplevel
     widget (e.g, label). The newly-converted toplevel window is in a
     *withdrawn* state. To make it appear on the screen, you must call
     *deiconify* after calling *wmRelease*.

     Any data associated with $widget via *wm* methods (icon, protocol,
     command etc.) are released, and must be re-established if window is
     later re-captured.

BUGS
====

   *wmCapture* does not exist in the Win32 window manager code.

   How these methods interact with perl/Tk's class hierarchy is not yet
clear.  In particular a *wmRelease*d window will not automatically
"*inherit*" the *Tk::Wm* methods, however a *wmCapture*d window still will.
(A released Label might make a good candidate for an Icon.)

AUTHORS
=======

   Ioi Kim Lam - ioi@graphics.cis.upenn.edu wrote original Tix version.
Updated for tk8.0, Win32 and perl by Nick Ing-Simmons.

SEE ALSO
========

   `Tk::Wm|Tk::Wm' in this node `Tk::Mwm|Tk::Mwm' in this node
`Tk::Frame|Tk::Frame' in this node `Tk::Toplevel|Tk::Toplevel' in this node

KEYWORDS
========

   window manager, wm, TIX

Variables used or set by Tk
***************************

NAME
====

   tkvars - Variables used or set by Tk

   The following perl variables are either set or used by Tk at various
times in its execution. (For a list of variables used by perl see
Perlvar (perl.info).)

$Tk::library
     This variable holds the file name for a directory containing the
     modules related to Tk.  These modules include an initialization file
     that is normally processed whenever a Tk application starts up, plus
     other files containing procedures that implement default behaviors
     for widgets.  The initial value of $Tk::library is set when Tk is
     added to an interpreter;  this is done by searching searching for a
     directory named Tk in the directory where the file `Tk.pm', or the
     first directory Tk in `@INC'.

     The *TK_LIBRARY* environment variable used by Tcl/Tk is not supported
     by perl/Tk.  Please use `@INC|perlvar' in this node to change where
     modules are searched.

     Note: This is Tcl remnant. With perl it makes more sense to use
     `@INC' and %INC).

$Tk::patchLevel
     Contains a decimal integer giving the current patch level for Tk.
     The patch level is incremented for each new release or patch, and it
     uniquely identifies an official version of Tk.

     Note: this is Tcl remnant. With perl it makes more sense to use
     $Tk::VERSION described below.

$Tk::strictMotif
     This variable is set to zero by default.  If an application sets it
     to one, then Tk attempts to adhere as closely as possible to Motif
     look-and-feel standards.  For example, active elements such as
     buttons and scrollbar sliders will not change color when the pointer
     passes over them.

$Tk::VERSION
     The variable holds the current version number of the perl/Tk release
     in the form *major*.*minor*.  *Major* and *minor* are integers.

     The *major* version number shows on which Tcl/Tk release perl/Tk is
     based.  E.g., *402* means based on Tcls Tk 4.2.  (Patchlevel of Tcls
     Tk are not incorporated because perl/Tk tended  to be "*ahead*" of
     them on some fixes and behind on others.  The first digest of the
     major version number increases in any Tk release that includes
     changes that are not backward compatible (i.e. whenever existing
     perl/Tk applications and scripts may have to change to work with the
     new release).

     The *minor* version depends on perl/Tk only. It uses the
     'even'='stable', 'odd'='experimental' scheme that linux uses:

          .0xx  - inherently 'alpha'
          .1xx  - experimental 'beta'
          .2xx  - stable
          .3xx  - experimental
          .4xx  - stable
          ...

     The minor version number increases with each new release of Tk,
     except that it resets to zero whenever the major version number
     changes.

$Tk::version
     The variable holds the current version number of the Tk library in
     the form *major*.*minor*.  *Major* and *minor* are integers.  The
     major version number increases in any Tk release that includes
     changes that are not backward compatible (i.e. whenever existing Tk
     applications and scripts may have to change to work with the new
     release).  The minor version number increases with each new release
     of Tk, except that it resets to zero whenever the major version
     number changes.

     Note: this is Tcl remnant.  With perl it makes more sense to use
     $Tk::VERSION described above.

KEYWORDS
========

   variables, version

preload widget classes
**********************

NAME
====

   Tk::widgets - preload widget classes

SYNOPSIS
========

     use Tk::widgets qw(Button Label Frame);

DESCRIPTION
===========

   Does a 'require Tk::Foo' for each 'Foo' in the list.  May speed startup
by avoiding AUTOLOADs.

(super)class for representing nodes in a tree
*********************************************

NAME
====

   Tree::DAG_Node - (super)class for representing nodes in a tree

SYNOPSIS
========

   Using as a base class:

     package Game::Tree::Node; # or whatever you're doing
     use Tree::DAG_Node;
     @ISA = qw(Tree::DAG_Node);
     ...your own methods overriding/extending
       the methods in Tree::DAG_Node...

   Using as a class of its own:

     use Tree::DAG_Node;
     my $root = Tree::DAG_Node->new();
     $root->name("I'm the tops");
     my $new_daughter = $root->new_daughter;
     $new_daughter->name("More");
     ...

DESCRIPTION
===========

   This class encapsulates/makes/manipulates objects that represent nodes
in a tree structure. The tree structure is not an object itself, but is
emergent from the linkages you create between nodes.  This class provides
the methods for making linkages that can be used to build up a tree, while
preventing you from ever making any kinds of linkages which are not
allowed in a tree (such as having a node be its own mother or ancestor, or
having a node have two mothers).

   This is what I mean by a "tree structure", a bit redundantly stated:

   * A tree is a special case of an acyclic directed graph.

   * A tree is a network of nodes where there's exactly one root node
(i.e., 'the top'), and the only primary relationship between nodes is the
mother-daugher relationship.

   * No node can be its own mother, or its mother's mother, etc.

   * Each node in the tree has exactly one "parent" (node in the "up"
direction) - except the root, which is parentless.

   * Each node can have any number (0 to any finite number) of daughter
nodes.  A given node's daughter nodes constitute an ordered list.
(However, you are free to consider this ordering irrelevant.  Some
applications do need daughters to be ordered, so I chose to consider this
the general case.)

   * A node can appear in only one tree, and only once in that tree.
Notably (notable because it doesn't follow from the two above points), a
node cannot appear twice in its mother's daughter list.

   * In other words, there's an idea of up (toward the root) versus down
(away from the root), and left (i.e., toward the start (index 0) of a
given node's daughter list) versus right (toward the end of a given node's
daughter list).

   Trees as described above have various applications, among them:
representing syntactic constituency, in formal linguistics; representing
contingencies in a game tree; representing abstract syntax in the parsing
of any computer language - whether in expression trees for programming
languages, or constituency in the parse of a markup language document.
(Some of these might not use the fact that daughters are ordered.)

   (Note: B-Trees are a very special case of the above kinds of trees, and
are best treated with their own class.  Check CPAN for modules
encapsulating B-Trees; or if you actually want a database, and for some
reason ended up looking here, go look at AnyDBM_File.)

   Many base classes are not usable except as such - but Tree::DAG_Node
can be used as a normal class.  You can go ahead and say:

     use Tree::DAG_Node;
     my $root = Tree::DAG_Node->new();
     $root->name("I'm the tops");
     $new_daughter = Tree::DAG_Node->new();
     $new_daughter->name("More");
     $root->add_daughter($new_daughter);

   and so on, constructing and linking objects from Tree::DAG_Node and
making useful tree structures out of them.

A NOTE TO THE READER
====================

   This class is big and provides lots of methods.  If your problem is
simple (say, just representing a simple parse tree), this class might seem
like using an atomic sledgehammer to swat a fly.  But the complexity of
this module's bells and whistles shouldn't detract from the efficiency of
using this class for a simple purpose.  In fact, I'd be very surprised if
any one user ever had use for more that even a third of the methods in
this class.  And remember: an atomic sledgehammer *will* kill that fly.

OBJECT CONTENTS
===============

   Implementationally, each node in a tree is an object, in the sense of
being an arbitrarily complex data structure that belongs to a class
(presumably Tree::DAG_Node, or ones derived from it) that provides methods.

   The attributes of a node-object are:

mother - this node's mother.  undef if this is a root.
daughters - the (possibly empty) list of daughters of this node.
name - the name for this node.
     Need not be unique, or even printable.  This is printed in some of the
     various dumper methods, but it's up to you if you don't put anything
     meaningful or printable here.

attributes - whatever the user wants to use it for.
     Presumably a hashref to whatever other attributes the user wants to
     store without risk of colliding with the object's real attributes.
     (Example usage: attributes to an SGML tag - you definitely wouldn't
     want the existence of a "mother=foo" pair in such a tag to collide
     with a node object's 'mother' attribute.)

     Aside from (by default) initializing it to {}, and having the access
     method called "attributes" (described a ways below), I don't do
     anything with the "attributes" in this module.  I basically intended
     this so that users who don't want/need to bother deriving a class
     from Tree::DAG_Node, could still attach whatever data they wanted in a
     node.

   "mother" and "daughters" are attributes that relate to linkage - they
are never written to directly, but are changed as appropriate by the
"linkage methods", discussed below.

   The other two (and whatever others you may add in derived classes) are
simply accessed thru the same-named methods, discussed further below.

ABOUT THE DOCUMENTED INTERFACE
------------------------------

   Stick to the documented interface (and comments in the source -
especially ones saying "undocumented!" and/or "disfavored!" - do not count
as documentation!), and don't rely on any behavior that's not in the
documented interface.

   Specifically, unless the documentation for a particular method says
"this method returns thus-and-such a value", then you should not rely on
it returning anything meaningful.

   A *passing* acquintance with at least the broader details of the source
code for this class is assumed for anyone using this class as a base class
- especially if you're overriding existing methods, and *definitely* if
you're overriding linkage methods.

MAIN CONSTRUCTOR, AND INITIALIZER
=================================

the constructor CLASS->new() or CLASS->new({...options...})
     This creates a new node object, calls $object->_init({...options...})
     to provide it sane defaults (like: undef name, undef mother, no
     daughters, 'attributes' setting of a new empty hashref), and returns
     the object created.  (If you just said "CLASS->new()" or "CLASS->new",
     then it pretends you called "CLASS->new({})".)

     Currently no options for putting in {...options...} are part of the
     documented interface, but the options is here in case you want to add
     such behavior in a derived class.

     Read on if you plan on using Tree::DAG_New as a base class.
     (Otherwise feel free to skip to the description of _init.)

     There are, in my mind, two ways to do object construction:

     Way 1: create an object, knowing that it'll have certain uninteresting
     sane default values, and then call methods to change those values to
     what you want.  Example:

          $node = Tree::DAG_Node->new;
          $node->name('Supahnode!');
          $root->add_daughter($node);
          $node->add_daughters(@some_others)

     Way 2: be able to specify some/most/all the object's attributes in
     the call to the constructor.  Something like:

          $node = Tree::DAG_Node->new({
            name => 'Supahnode!',
            mother => $root,
            daughters => \@some_others
          });

     After some deliberation, I've decided that the second way is a Bad
     Thing.  First off, it is not markedly more concise than the first
     way.  Second off, it often requires subtly different syntax (e.g.,
     \@some_others vs @some_others).  It just complicates things for the
     programmer and the user, without making either appreciably happier.

     (This is not to say that options in general for a constructor are bad
     - `random_network', discussed far below, necessarily takes options.
     But note that those are not options for the default values of
     attributes.)

     Anyway, if you use Tree::DAG_Node as a superclass, and you add
     attributes that need to be initialized, what you need to do is provide
     an _init method that calls $this->SUPER::_init($options) to use its
     superclass's _init method, and then initializes the new attributes:

          sub _init {
            my($this, $options) = @_[0,1];
            $this->SUPER::_init($options); # call my superclass's _init to
              # init all the attributes I'm inheriting

            # Now init /my/ new attributes:
            $this->{'amigos'} = []; # for example
          }

     ...or, as I prefer when I'm being a neat freak:

          sub _init {
            my($this, $options) = @_[0,1];
            $this->SUPER::_init($options);

            $this->_init_amigos($options);
          }

          sub _init_amigos {
            my $this = $_[0];
            # Or my($this,$options) = @_[0,1]; if I'm using $options
            $this->{'amigos'} = [];
          }

     In other words, I like to have each attribute initialized thru a
     method named _init_[attribute], which should expect the object as
     $_[0] and the the options hashref (or {} if none was given) as $_[1].
     If you insist on having your _init recognize options for setting
     attributes, you might as well have them dealt with by the appropriate
     _init_[attribute] method, like this:

          sub _init {
            my($this, $options) = @_[0,1];
            $this->SUPER::_init($options);

            $this->_init_amigos($options);
          }

          sub _init_amigos {
            my($this,$options) = @_[0,1]; # I need options this time
            $this->{'amigos'} = [];
            $this->amigos(@{$options->{'amigos'}}) if $options->{'amigos'};
          }

     All this bookkeeping looks silly with just one new attribute in a
     class derived straight from Tree::DAG_Node, but if there's lots of new
     attributes running around, and if you're deriving from a class derived
     from a class derived from Tree::DAG_Node, then tidy
     stratification/modularization like this can keep you sane.

the constructor $obj->new() or $obj->new({...options...})
     Just another way to get at the new method. This *does not copy* $obj,
     but merely constructs a new object of the same class as it.  Saves
     you the bother of going $class = ref $obj; $obj2 = $class->new;

the method $node->_init({...options...})
     Initialize the object's attribute values.  See the discussion above.
     Presumably this should be called only by the guts of the new
     constructor - never by the end user.

     Currently there are no documented options for putting in
     {...options...}, but (in case you want to disregard the above rant)
     the option exists for you to use {...options...} for something useful
     in a derived class.

     Please see the source for more information.

see also (below) the constructors "new_daughter" and "new_daughter_left"
LINKAGE-RELATED METHODS
=======================

$node->daughters
     This returns the (possibly empty) list of daughters for $node.

$node->mother
     This returns what node is $node's mother.  This is undef if $node has
     no mother - i.e., if it is a root.

$mother->add_daughters( LIST )
     This method adds the node objects in LIST to the (right) end of
     $mother's `daughter' list.  Making a node N1 the daughter of another
     node N2 also means that N1's mother attribute is "automatically" set
     to N2; it also means that N1 stops being anything else's daughter as
     it becomes N2's daughter.

     If you try to make a node its own mother, a fatal error results.  If
     you try to take one of a a node N1's ancestors and make it also a
     daughter of N1, a fatal error results.  A fatal error results if
     anything in LIST isn't a node object.

     If you try to make N1 a daughter of N2, but it's *already* a daughter
     of N2, then this is a no-operation - it won't move such nodes to the
     end of the list or anything; it just skips doing anything with them.

$node->add_daughter( LIST )
     An exact synonym for $node->add_daughters(LIST)

$mother->add_daughters_left( LIST )
     This method is just like `add_daughters', except that it adds the
     node objects in LIST to the (left) beginning of $mother's daughter
     list, instead of the (right) end of it.

$node->add_daughter_left( LIST )
     An exact synonym for $node->add_daughters_left( LIST )

Note:
     The above link-making methods perform basically an unshift or push on
     the mother node's daughter list.  To get the full range of
     list-handling functionality, copy the daughter list, and change it,
     and then call `set_daughters' on the result:

          @them = $mother->daughters;
          @removed = splice(@them, 0,2, @new_nodes);
          $mother->set_daughters(@them);

     Or consider a structure like:

          $mother->set_daughters(
                                 grep($_->name =~ /NP/ ,
                                      $mother->daughters
                                     )
                                );

the constructor $daughter = $mother->new_daughter, or
the constructor $daughter = $mother->new_daughter({...options...})
     This *constructs* a new node (of the same class as $mother), and adds
     it to the (right) end of the daughter list of $mother. This is
     essentially the same as going

          $daughter = $mother->new;
          $mother->add_daughter($daughter);

     but is rather more efficient because (since $daughter is guaranteed
     new and isn't linked to/from anything), it doesn't have to check that
     $daughter isn't an ancestor of $mother, isn't already daughter to a
     mother it needs to be unlinked from, isn't already in $mother's
     daughter list, etc.

     As you'd expect for a constructor, it returns the node-object created.

the constructor $mother->new_daughter_left, or
$mother->new_daughter_left({...options...})
     This is just like $mother->new_daughter, but adds the new daughter to
     the left (start) of $mother's daughter list.

$mother->remove_daughters( LIST )
     This removes the nodes listed in LIST from $mother's daughter list.
     This is a no-operation if LIST is empty.  If there are things in LIST
     that aren't a current daughter of $mother, they are ignored.

     Not to be confused with $mother->clear_daughters.

$node->remove_daughter( LIST )
     An exact synonym for $node->remove_daughters( LIST )

$node->unlink_from_mother
     This removes node from the daughter list of its mother.  If it has no
     mother, this is a no-operation.

     Returns the mother unlinked from (if any).

$mother->clear_daughters
     This unlinks all $mother's daughters.  Returns the the list of what
     used to be $mother's daughters.

     Not to be confused with $mother->remove_daughters( LIST ).

$mother->set_daughters( LIST )
     This unlinks all $mother's daughters, and replaces them with the
     daughters in LIST.

     Currently implemented as just $mother->clear_daughters followed by
     $mother->add_daughters( LIST ).

$node->replace_with( LIST )
     This replaces $node in its mother's daughter list, by unlinking $node
     and replacing it with the items in LIST.  This returns a list
     consisting of $node followed by LIST, i.e., the nodes that replaced
     it.

     LIST can include $node itself (presumably at most once).  LIST can
     also be empty-list.  However, if any items in LIST are sisters to
     $node, they are ignored, and are not in the copy of LIST passed as the
     return value.

     As you might expect for any linking operation, the items in LIST
     cannot be $node's mother, or any ancestor to it; and items in LIST
     are, of course, unlinked from their mothers (if they have any) as
     they're linked to $node's mother.

     (In the special (and bizarre) case where $node is root, this simply
     calls $this->unlink_from_mother on all the items in LIST, making them
     roots of their own trees.)

     Note that the daughter-list of $node is not necessarily affected; nor
     are the daughter-lists of the items in LIST.  I mention this in case
     you think replace_with switches one node for another, with respect to
     its mother list and its daughter list, leaving the rest of the tree
     unchanged. If that's what you want, replacing $Old with $New, then you
     want:

          $New->set_daughters($Old->clear_daughters);
          $Old->replace_with($New);

     (I can't say $node's and LIST-items' daughter lists are never
     affected my replace_with - they can be affected in this case:

          $N1 = ($node->daughters)[0]; # first daughter of $node
          $N2 = ($N1->daughters)[0];   # first daughter of $N1;
          $N3 = Tree::DAG_Node->random_network; # or whatever
          $node->replace_with($N1, $N2, $N3);

     As a side affect of attaching $N1 and $N2 to $node's mother, they're
     unlinked from their parents ($node, and $N1, replectively).  But N3's
     daughter list is unaffected.

     In other words, this method does what it has to, as you'd expect it
     to.

$node->replace_with_daughters
     This replaces $node in its mother's daughter list, by unlinking $node
     and replacing it with its daughters.  In other words, $node becomes
     motherless and daughterless as its daughters move up and take its
     place.  This returns a list consisting of $node followed by the nodes
     that were its daughters.

     In the special (and bizarre) case where $node is root, this simply
     unlinks its daughters from it, making them roots of their own trees.

     Effectively the same as $node->replace_with($node->daughters), but
     more efficient, since less checking has to be done.  (And I also think
     $node->replace_with_daughters is a more common operation in
     tree-wrangling than $node->replace_with(LIST), so deserves a named
     method of its own, but that's just me.)

$node->add_left_sisters( LIST )
     This adds the elements in LIST (in that order) as immediate left
     sisters of $node.  In other words, given that B's mother's
     daughter-list is (A,B,C,D), calling B->add_left_sisters(X,Y) makes
     B's mother's daughter-list (A,X,Y,B,C,D).

     If LIST is empty, this is a no-op, and returns empty-list.

     This is basically implemented as a call to $node->replace_with(LIST,
     $node), and so all replace_with's limitations and caveats apply.

     The return value of $node->add_left_sisters( LIST ) is the elements of
     LIST that got added, as returned by replace_with - minus the copies
     of $node you'd get from a straight call to $node->replace_with(LIST,
     $node).

$node->add_left_sister( LIST )
     An exact synonym for $node->add_left_sisters(LIST)

$node->add_right_sisters( LIST )
     Just like add_left_sisters (which see), except that the the elements
     in LIST (in that order) as immediate right sisters of $node;

     In other words, given that B's mother's daughter-list is (A,B,C,D),
     calling B->add_right_sisters(X,Y) makes B's mother's daughter-list
     (A,B,X,Y,C,D).

$node->add_right_sister( LIST )
     An exact synonym for $node->add_right_sisters(LIST)

OTHER ATTRIBUTE METHODS
=======================

$node->name or $node->name(SCALAR)
     In the first form, returns the value of the node object's "name"
     attribute.  In the second form, sets it to the value of SCALAR.

$node->attributes or $node->attributes(SCALAR)
     In the first form, returns the value of the node object's "attributes"
     attribute.  In the second form, sets it to the value of SCALAR.  I
     intend this to be used to store a reference to a (presumably
     anonymous) hash the user can use to store whatever attributes he
     doesn't want to have to store as object attributes.  In this case, you
     needn't ever set the value of this.  (_init has already initialized it
     to {}.)  Instead you can just do...

          $node->attributes->{'foo'} = 'bar';

     ...to write foo => bar.

$node->attribute or $node->attribute(SCALAR)
     An exact synonym for $node->attributes or $node->attributes(SCALAR)

OTHER METHODS TO DO WITH RELATIONSHIPS
======================================

$node->is_node
     This always returns true.  More pertinently, $object->can('is_node')
     is true (regardless of what `is_node' would do if called) for objects
     belonging to this class or for any class derived from it.

$node->ancestors
     Returns the list of this node's ancestors, starting with its mother,
     then grandmother, and ending at the root.  It does this by simply
     following the 'mother' attributes up as far as it can.  So if $item IS
     the root, this returns an empty list.

     Consider that scalar($node->ancestors) returns the ply of this node
     within the tree - 2 for a granddaughter of the root, etc., and 0 for
     root itself.

$node->root
     Returns the root of whatever tree $node is a member of.  If $node is
     the root, then the result is $node itself.

$node->is_daughter_of($node2)
     Returns true iff $node is a daughter of $node2.  Currently
     implemented as just a test of ($it->mother eq $node2).

$node->self_and_descendants
     Returns a list consisting of itself (as element 0) and all the
     descendants of $node.  Returns just itself if $node is a
     terminal_node.

     (Note that it's spelled "descendants", not "descendents".)

$node->descendants
     Returns a list consisting of all the descendants of $node.  Returns
     empty-list if $node is a terminal_node.

     (Note that it's spelled "descendants", not "descendents".)

$node->leaves_under
     Returns a list (going left-to-right) of all the leaf nodes under
     $node.  ("Leaf nodes" are also called "terminal nodes" - i.e., nodes
     that have no daughters.)  Returns $node in the degenerate case of
     $node being a leaf itself.

$node->depth_under
     Returns an integer representing the number of branches between this
     $node and the most distant leaf under it.  (In other words, this
     returns the ply of subtree starting of $node.  Consider
     scalar($it->ancestors) if you want the ply of a node within the whole
     tree.)

$node->generation
     Returns a list of all nodes (going left-to-right) that are in $node's
     generation - i.e., that are the some number of nodes down from the
     root.  $root->generation is just $root.

     Of course, $node is always in its own generation.

$node->generation_under(NODE2)
     Like $node->generation, but returns only the nodes in $node's
     generation that are also descendants of NODE2 - in other words,

          @us = $node->generation_under( $node->mother->mother );

     is all $node's first cousins (to borrow yet more kinship terminology)
     - assuming $node does indeed have a grandmother.  Actually "cousins"
     isn't quite an apt word, because `@us' ends up including $node's
     siblings and $node.

     Actually, `generation_under' is just an alias to `generation', but I
     figure that this:

          @us = $node->generation_under($way_upline);

     is a bit more readable than this:

          @us = $node->generation($way_upline);

     But it's up to you.

     $node->generation_under($node) returns just $node.

     If you call $node->generation_under($node) but NODE2 is not $node or
     an ancestor of $node, it behaves as if you called just
     $node->generation().

$node->self_and_sisters
     Returns a list of all nodes (going left-to-right) that have the same
     mother as $node - including $node itself. This is just like
     $node->mother->daughters, except that that fails where $node is root,
     whereas $root->self_and_siblings, as a special case, returns $root.

     (Contrary to how you may interpret how this method is named, "self" is
     not (necessarily) the first element of what's returned.)

$node->sisters
     Returns a list of all nodes (going left-to-right) that have the same
     mother as $node - *not including* $node itself.  If $node is root,
     this returns empty-list.

$node->left_sister
     Returns the node that's the immediate left sister of $node.  If $node
     is the leftmost (or only) daughter of its mother (or has no mother),
     then this returns undef.

     (See also $node->add_left_sisters(LIST).)

$node->left_sisters
     Returns a list of nodes that're sisters to the left of $node.  If
     $node is the leftmost (or only) daughter of its mother (or has no
     mother), then this returns an empty list.

     (See also $node->add_left_sisters(LIST).)

$node->right_sister
     Returns the node that's the immediate right sister of $node.  If $node
     is the rightmost (or only) daughter of its mother (or has no mother),
     then this returns undef.

     (See also $node->add_right_sisters(LIST).)

$node->right_sisters
     Returns a list of nodes that're sisters to the right of $node. If
     $node is the rightmost (or only) daughter of its mother (or has no
     mother), then this returns an empty list.

     (See also $node->add_right_sisters(LIST).)

$node->my_daughter_index
     Returns what index this daughter is, in its mother's `daughter' list.
     In other words, if $node is ($node->mother->daughters)[3], then
     $node->my_daughter_index returns 3.

     As a special case, returns 0 if $node has no mother.

$node->address or $anynode->address(ADDRESS)
     With the first syntax, returns the address of $node within its tree,
     based on its position within the tree.  An address is formed by noting
     the path between the root and $node, and concatenating the
     daughter-indices of the nodes this passes thru (starting with 0 for
     the root, and ending with $node).

     For example, if to get from node ROOT to node $node, you pass thru
     ROOT, A, B, and $node, then the address is determined as:

     * ROOT's my_daughter_index is 0.

     * A's my_daughter_index is, suppose, 2. (A is index 2 in ROOT's
     daughter list.)

     * B's my_daughter_index is, suppose, 0. (B is index 0 in A's daughter
     list.)

     * $node's my_daughter_index is, suppose, 4. ($node is index 4 in B's
     daughter list.)

     The address of the above-described $node is, therefore, "0:2:0:4".

     (As a somewhat special case, the address of the root is always "0";
     and since addresses start from the root, all addresses start with a
     "0".)

     The second syntax, where you provide an address, starts from the root
     of the tree $anynode belongs to, and returns the node corresponding to
     that address.  Returns undef if no node corresponds to that address.
     Note that this routine may be somewhat liberal in its interpretation
     of what can constitute an address; i.e., it accepts "0.2.0.4", besides
     "0:2:0:4".

     Also note that the address of a node in a tree is meaningful only in
     that tree as currently structured.

     (Consider how ($address1 cmp $address2) may be magically meaningful
     to you, if you mant to figure out what nodes are to the right of what
     other nodes.)

$node->common(LIST)
     Returns the lowest node in the tree that is ancestor-or-self to the
     nodes $node and LIST.

     If the nodes are far enough apart in the tree, the answer is just the
     root.

     If the nodes aren't all in the same tree, the answer is undef.

     As a degenerate case, if LIST is empty, returns $node.

$node->common_ancestor(LIST)
     Returns the lowest node that is ancestor to all the nodes given (in
     nodes $node and LIST).  In other words, it answers the question: "What
     node in the tree, as low as possible, is ancestor to the nodes given
     ($node and LIST)?"

     If the nodes are far enough apart, the answer is just the root -
     except if any of the nodes are the root itself, in which case the
     answer is undef (since the root has no ancestor).

     If the nodes aren't all in the same tree, the answer is undef.

     As a degenerate case, if LIST is empty, returns $node's mother;
     that'll be undef if $node is root.

YET MORE METHODS
================

$node->walk_down({ callback => \&foo, callbackback => \&foo, ... })
     Performs a depth-first traversal of the structure at and under $node.
     What it does at each node depends on the value of the options hashref,
     which you must provide.  There are three options, "callback" and
     "callbackback" (at least one of which must be defined, as a sub
     reference), and "_depth".  This is what `walk_down' does, in
     pseudocode form:

     * Start at the $node given.

     * If there's a callback, call it with $node as the first argument,
     and the options hashref as the second argument (which contains the
     potentially useful `_depth', remember).  This function must return
     true or false - if false, it will block the next step:

     * If $node has any daughter nodes, increment `_depth', and call
     $daughter->walk_down(options_hashref) for each daughter (in order, of
     course), where options_hashref is the same hashref it was called with.
     When this returns, decrements `_depth'.

     * If there's a `callbackback', call just it as with callback (but
     tossing out the return value).  Note that callback returning false
     blocks traversal below $node, but doesn't block calling callbackback
     for $node.  (Incidentally, in the unlikely case that $node has stopped
     being a node object, `callbackback' won't get called.)

     * Return.

     $node->walk_down is the way to recursively do things to a tree (if you
     start at the root) or part of a tree; if what you're doing is best
     done via pre-pre order traversal, use callback; if what you're doing
     is best done with post-order traversal, use `callbackback'.
     `walk_down' is even the basis for plenty of the methods in this
     class.  See the source code for examples both simple and horrific.

     Note that if you don't specify `_depth', it effectively defaults to
     0.  You should set it to scalar($node->ancestors) if you want
     `_depth' to reflect the true depth-in-the-tree for the nodes called,
     instead of just the depth below $node.  (If $node is the root, there's
     difference, of course.)

     And *by the way*, it's a bad idea to modify the tree from the
     callback.  Unpredictable things may happen.  I instead suggest having
     your callback add to a stack of things that need changing, and then,
     once `walk_down' is all finished, changing those nodes from that
     stack.

     Note that the existence of `walk_down' doesn't mean you can't write
     you own special-use traversers.

@lines = $node->dump_names({ ...options... });
     Dumps, as an indented list, the names of the nodes starting at $node,
     and continuing under it.  Options are:

     * _depth - A nonnegative number.  Indicating the depth to consider
     $node as being at (and so the generation under that is that plus one,
     etc.).  Defaults to 0.  You may choose to use set _depth =>
     scalar($node->ancestors).

     * tick - a string to preface each entry with, between the
     indenting-spacing and the node's name.  Defaults to empty-string.  You
     may prefer "*" or "-> " or someting.

     * indent - the string used to indent with.  Defaults to "  " (two
     spaces).  Another sane value might be ". " (period, space).  Setting
     it to empty-string suppresses indenting.

     The dump is not printed, but is returned as a list, where each item
     is a line, with a "\n" at the end.

the constructor CLASS->random_network({...options...})
the method $node->random_network({...options...})
     In the first case, constructs a randomly arranged network under a new
     node, and returns the root node of that tree.  In the latter case,
     constructs the network under $node.

     Currently, this is implemented a bit half-heartedly, and
     half-wittedly.  I basically needed to make up random-looking networks
     to stress-test the various tree-dumper methods, and so wrote this.  If
     you actually want to rely on this for any application more serious
     than that, I suggest examining the source code and seeing if this
     does really what you need (say, in reliability of randomness); and
     feel totally free to suggest changes to me (especially in the form of
     "I rewrote `random_network', here's the code...")

     It takes four options:

     * max_node_count - maximum number of nodes this tree will be allowed
     to have (counting the root).  Defaults to 25.

     * min_depth - minimum depth for the tree.  Defaults to 2.  Leaves can
     be generated only after this depth is reached, so the tree will be at
     least this deep - unless max_node_count is hit first.

     * max_depth - maximum depth for the tree.  Defaults to 3 plus
     min_depth.  The tree will not be deeper than this.

     * max_children - maximum number of children any mother in the tree
     can have.  Defaults to 4.

the constructor CLASS->lol_to_tree($lol);
     Converts something like bracket-notation for "Chomsky trees" (or
     rather, the closest you can come with Perl
     list-of-lists(-of-lists(-of-lists))) into a tree structure.  Returns
     the root of the tree converted.

     The conversion rules are that:  1) if the last (possibly the only)
     item in a given list is a scalar, then that is used as the "name"
     attribute for the node based on this list.  2) All other items in the
     list represent daughter nodes of the current node - recursively so, if
     they are list references; otherwise, (non-terminal) scalars are
     considered to denote nodes with that name.  So ['Foo', 'Bar', 'N'] is
     an alternate way to represent [['Foo'], ['Bar'], 'N'].

     An example will illustrate:

          use Tree::DAG_Node;
          $lol =
            [
              [
                [ [ 'Det:The' ],
                  [ [ 'dog' ], 'N'], 'NP'],
                [ '/with rabies\\', 'PP'],
                'NP'
              ],
              [ 'died', 'VP'],
              'S'
            ];
           $tree = Tree::DAG_Node->lol_to_tree($lol);
           $diagram = $tree->draw_ascii_tree;
           print map "$_\n", @$diagram;

     ...returns this tree:

          |
                            <S>
          |
                          /------------------\
                          |                  |
                        <NP>                <VP>
                          |                  |
                  /---------------\        <died>
                  |               |
                <NP>            <PP>
                  |               |
               /-------\   </with rabies\>
               |       |
           <Det:The>  <N>
                       |
                     <dog>

     By the way (and this rather follows from the above rules), when
     denoting a LoL tree consisting of just one node, this:

          $tree = Tree::DAG_Node->lol_to_tree( 'Lonely' );

     is okay, although it'd probably occur to you to denote it only as:

          $tree = Tree::DAG_Node->lol_to_tree( ['Lonely'] );

     which is of course fine, too.

$node->tree_to_lol_notation({...options...})
     Dumps a tree (starting at $node) as the sort of LoL-like bracket
     notation you see in the above example code.  Returns just one big
     block of text.  The only option is "multiline" - if true, it dumps
     the text as the sort of indented structure as seen above; if false
     (and it defaults to false), dumps it all on one line (with no
     indenting, of course).

     For example, starting with the tree from the above example, this:

          print $tree->tree_to_lol_notation, "\n";

     prints the following (which I've broken over two lines for sake of
     printablitity of documentation):

          [[[['Det:The'], [['dog'], 'N'], 'NP'], [["/with rabies\x5c"],
          'PP'], 'NP'], [['died'], 'VP'], 'S'],

     Doing this:

          print $tree->tree_to_lol_notation({ multiline => 1 });

     prints the same content, just spread over many lines, and prettily
     indented.

$node->tree_to_lol
     Returns that tree (starting at $node) represented as a LoL, like what
     $lol, above, holds.  (This is as opposed to `tree_to_lol_notation',
     which returns the viewable code like what gets evaluated and stored in
     $lol, above.)

     Lord only knows what you use this for - maybe for feeding to
     Data::Dumper, in case `tree_to_lol_notation' doesn't do just what you
     want?

the constructor CLASS->simple_lol_to_tree($simple_lol);
     This is like lol_to_tree, except that rule 1 doesn't apply - i.e.,
     all scalars (or really, anything not a listref) in the LoL-structure
     end up as named terminal nodes, and only terminal nodes get names
     (and, of course, that name comes from that scalar value).  This method
     is useful for making things like expression trees, or at least
     starting them off.  Consider that this:

          $tree = Tree::DAG_Node->simple_lol_to_tree(
            [ 'foo', ['bar', ['baz'], 'quux'], 'zaz', 'pati' ]
          );

     converts from something like a Lispish or Iconish tree, if you pretend
     the brackets are parentheses.

     Note that there is a (possibly surprising) degenerate case of what I'm
     calling a "simple-LoL", and it's like this:

          $tree = Tree::DAG_Node->simple_lol_to_tree('Lonely');

     This is the (only) way you can specify a tree consisting of only a
     single node, which here gets the name 'Lonely'.

$node->tree_to_simple_lol
     Returns that tree (starting at $node) represented as a simple-LoL -
     i.e., one where non-terminal nodes are represented as listrefs, and
     terminal nodes are gotten from the contents of those nodes' "name'
     attributes.

     Note that in the case of $node being terminal, what you get back is
     the same as $node->name.

     Compare to tree_to_simple_lol_notation.

$node->tree_to_simple_lol_notation({...options...})
     A simple-LoL version of tree_to_lol_notation (which see); takes the
     same options.

$list_r = $node->draw_ascii_tree({ ... options ... })
     Draws a nice ASCII-art representation of the tree structure
     at-and-under $node, with $node at the top.  Returns a reference to the
     list of lines (with no "\n"s or anything at the end of them) that make
     up the picture.

     Example usage:

          print map("$_\n", @{$tree->draw_ascii_tree});

     draw_ascii_tree takes parameters you set in the options hashref:

     * "no_name" - if true, `draw_ascii_tree' doesn't print the name of
     the node; simply prints a "*".  Defaults to 0 (i.e., print the node
     name.)

     * "h_spacing" - number 0 or greater.  Sets the number of spaces
     inserted horizontally between nodes (and groups of nodes) in a tree.
     Defaults to 1.

     * "h_compact" - number 0 or 1.  Sets the extent to which
     `draw_ascii_tree' tries to save horizontal space.  Defaults to 1.  If
     I think of a better scrunching algorithm, there'll be a "2" setting
     for this.

     * "v_compact" - number 0, 1, or 2.  Sets the degree to which
     `draw_ascii_tree' tries to save vertical space.  Defaults to 1.

     This occasionally returns trees that are a bit cock-eyed in parts; if
     anyone can suggest a better drawing algorithm, I'd be appreciative.

$node->copy_tree or $node->copy_tree({...options...})
     This returns the root of a copy of the tree that $node is a member of.
     If you pass no options, copy_tree pretends you've passed {}.

     This method is currently implemented as just a call to
     $this->root->copy_at_and_under({...options...}), but magic may be
     added in the future.

     Options you specify are passed down to calls to $node->copy.

$node->copy_at_and_under or $node->copy_at_and_under({...options...})
     This returns a copy of the subtree consisting of $node and everything
     under it.

     If you pass no options, copy_at_and_under pretends you've passed {}.

     This works by recursively building up the new tree from the leaves,
     duplicating nodes using $orig_node->copy($options_ref) and then
     linking them up into a new tree of the same shape.

     Options you specify are passed down to calls to $node->copy.

the constructor $node->copy or $node->copy({...options...})
     Returns a copy of $node, minus its daughter or mother attributes
     (which are set back to default values).

     If you pass no options, copy pretends you've passed {}.

     Magic happens with the 'attributes' attribute: if it's a hashref (and
     it usually is), the new node doesn't end up with the same hashref, but
     with ref to a hash with the content duplicated from the original's
     hashref.  If 'attributes' is not a hashref, but instead an object that
     belongs to a class that provides a method called "copy", then that
     method is called, and the result saved in the clone's 'attribute'
     attribute.  Both of these kinds of magic are disabled if the options
     you pass to copy (maybe via `copy_tree', or `copy_at_and_under')
     includes (`no_attribute_copy' => 1).

     The options hashref you pass to copy (derictly or indirectly) gets
     changed slightly after you call copy - it gets an entry called
     "from_to" added to it.  Chances are you would never know nor care, but
     this is reserved for possible future use.  See the source if you are
     wildly curious.

     Note that if you are using $node->copy (whether directly or via
     $node->copy_tree or $node->copy_at_or_under), and it's not properly
     copying object attributes containing references, you probably
     shouldn't fight it or try to fix it - simply override copy_tree with:

          sub copy_tree {
            use Storable qw(dclone);
            my $this = $_[0];
            return dclone($this->root);
             # d for "deep"
          }

     or

          sub copy_tree {
            use Data::Dumper;
            my $this = $_[0];
            $Data::Dumper::Purity = 1;
            return eval(Dumper($this->root));
          }

     Both of these avoid you having to reinvent the wheel.

     How to override copy_at_or_under with something that uses Storable or
     Data::Dumper is left as an exercise to the reader.

     Consider that if in a derived class, you add attributes with really
     bizarre contents (like a unique-for-all-time-ID), you may need to
     override copy.  Consider:

          sub copy {
            my($it, @etc) = @_;
            $it->SUPER::copy(@etc);
            $it->{'UID'} = &get_new_UID;
          }

     ...or the like.  See the source of Tree::DAG_Node::copy for
     inspiration.

$node->delete_tree
     Destroys the entire tree that $node is a member of (starting at the
     root), by nulling out each node-object's attributes (including, most
     importantly, its linkage attributes - hopefully this is more than
     sufficient to eliminate all circularity in the data structure), and
     then moving it into the class DEADNODE.

     Use this when you're finished with the tree in question, and want to
     free up its memory.  (If you don't do this, it'll get freed up anyway
     when your program ends.)

     If you try calling any methods on any of the node objects in the tree
     you've destroyed, you'll get an error like:

          Can't locate object method "leaves_under"
            via package "DEADNODE".

     So if you see that, that's what you've done wrong.  (Actually, the
     class DEADNODE does provide one method: a no-op method "delete_tree".
     So if you want to delete a tree, but think you may have deleted it
     already, it's safe to call $node->delete_tree on it (again).)

     The `delete_tree' method is needed because Perl's garbage collector
     would never (as currently implemented) see that it was time to
     de-allocate the memory the tree uses - until either you call
     $node->delete_tree, or until the program stops (at "global
     destruction" time, when *everything* is unallocated).

     Incidentally, there are better ways to do garbage-collecting on a
     tree, ways which don't require the user to explicitly call a method
     like `delete_tree' - they involve dummy classes, as explained at
     `http://mox.perl.com/misc/circle-destroy.pod'

     However, introducing a dummy class concept into Tree::DAG_Node would
     be rather a distraction.  If you want to do this with your derived
     classes, via a DESTROY in a dummy class (or in a tree-metainformation
     class, maybe), then feel free to.

     The only case where I can imagine `delete_tree' failing to totally
     void the tree, is if you use the hashref in the "attributes" attribute
     to store (presumably among other things) references to other nodes'
     "attributes" hashrefs - which 1) is maybe a bit odd, and 2) is your
     problem, because it's your hash structure that's circular, not the
     tree's.  Anyway, consider:

          # null out all my "attributes" hashes
          $anywhere->root->walk_down({
            'callback' => sub {
              $hr = $_[0]->attributes; %$hr = (); return 1;
            }
          });
          # And then:
          $anywhere->delete_tree;

     (I suppose `delete_tree' is a "destructor", or as close as you can
     meaningfully come for a circularity-rich data structure in Perl.)

When and How to Destroy
-----------------------

   It should be clear to you that if you've built a big parse tree or
something, and then you're finished with it, you should call
$some_node->delete_tree on it if you want the memory back.

   But consider this case:  you've got this tree:

     A
         / | \
        B  C  D
        |     | \
        E     X  Y

   Let's say you decide you don't want D or any of its descendants in the
tree, so you call D->unlink_from_mother.  This does NOT automagically
destroy the tree D-X-Y.  Instead it merely splits the tree into two:

     A                        D
         / \                      / \
        B   C                    X   Y
        |
        E

   To destroy D and its little tree, you have to explicitly call
delete_tree on it.

   Note, however, that if you call C->unlink_from_mother, and if you don't
have a link to C anywhere, then it *does* magically go away.  This is
because nothing links to C - whereas with the D-X-Y tree, D links to X and
Y, and X and Y each link back to D. Note that calling C->delete_tree is
harmless - after all, a tree of only one node is still a tree.

   So, this is a surefire way of getting rid of all $node's children and
freeing up the memory associated with them and their descendants:

     foreach my $it ($node->clear_daughters) { $it->delete_tree }

   Just be sure not to do this:

     foreach my $it ($node->daughters) { $it->delete_tree }
     $node->clear_daughters;

   That's bad; the first call to $_->delete_tree will climb to the root of
$node's tree, and nuke the whole tree, not just the bits under $node.  You
might as well have just called $node->delete_tree.  (Moreavor, once $node
is dead, you can't call clear_daughters on it, so you'll get an error
there.)

BUG REPORTS
===========

   If you find a bug in this library, report it to me as soon as possible,
at the address listed in the AUTHOR section, below.  Please try to be as
specific as possible about how you got the bug to occur.

HELP!
=====

   If you develop a given routine for dealing with trees in some way, and
use it a lot, then if you think it'd be of use to anyone else, do email me
about it; it might be helpful to others to include that routine, or
something based on it, in a later version of this module.

   It's occurred to me that you might like to (and might yourself develop
routines to) draw trees in something other than ASCII art.  If you do so -
say, for PostScript output, or for output interpretable by some external
plotting program -  I'd be most interested in the results.

RAMBLINGS
=========

   This module uses "strict", but I never wrote it with -w warnings in
mind - so if you use -w, do not be surprised if you see complaints from
the guts of DAG_Node.  As long as there is no way to turn off -w for a
given module (instead of having to do it in every single subroutine with a
"local $^W"), I'm not going to change this. However, I do, at points, get
bursts of ambition, and I try to fix code in DAG_Node that generates
warnings, *as I come across them* - which is only occasionally.  Feel free
to email me any patches for any such fixes you come up with, tho.

   Currently I don't assume (or enforce) anything about the class
membership of nodes being manipulated, other than by testing whether each
one provides a method `is_node', a la:

     die "Not a node!!!" unless UNIVERSAL::can($node, "is_node");

   So, as far as I'm concerned, a given tree's nodes are free to belong to
different classes, just so long as they provide/inherit `is_node', the few
methods that this class relies on to navigate the tree, and have the same
internal object structure, or a superset of it. Presumably this would be
the case for any object belonging to a class derived from
`Tree::DAG_Node', or belonging to `Tree::DAG_Node' itself.

   When routines in this class access a node's "mother" attribute, or its
"daughters" attribute, they (generally) do so directly (via
$node->{'mother'}, etc.), for sake of efficiency.  But classes derived
from this class should probably do this instead thru a method (via
$node->mother, etc.), for sake of portability, abstraction, and general
goodness.

   However, no routines in this class (aside from, necessarily, _init,
`_init_name', and name) access the "name" attribute directly; routines
(like the various tree draw/dump methods) get the "name" value thru a call
to $obj->name().  So if you want the object's name to not be a real
attribute, but instead have it derived dynamically from some feature of
the object (say, based on some of its other attributes, or based on its
address), you can to override the name method, without causing problems.
(Be sure to consider the case of $obj->name as a write method, as it's
used in `lol_to_tree' and `random_network'.)

SEE ALSO
========

   See HTML/Element,

   Wirth, Niklaus.  1976.  *Algorithms + Data Structures = Programs*
Prentice-Hall, Englewood Cliffs, NJ.

   Knuth, Donald Ervin.  1997.  *Art of Computer Programming, Volume 1,
Third Edition: Fundamental Algorithms*.  Addison-Wesley,  Reading, MA.

   Wirth's classic, currently and lamentably out of print, has a good
section on trees.  I find it clearer than Knuth's (if not quite as
encyclopedic), probably because Wirth's example code is in a
block-structured high-level language (basically Pascal), instead of in
assembler (MIX).

   Until some kind publisher brings out a new printing of Wirth's book,
try poking around used bookstores (or `www.abebooks.com') for a copy.  I
think it was also republished in the 1980s under the title *Algorithms and
Data Structures*, and in a German edition called *Algorithmen und
Datenstrukturen*.  (That is, I'm sure books by Knuth were published under
those titles, but I'm *assuming* that they're just later
printings/editions of *Algorithms + Data Structures = Programs*.)

COPYRIGHT AND DISCLAIMER
========================

   Copyright 1998,1999,2000,2001 by Sean M. Burke `sburke@cpan.org', all
rights reserved.  This program is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

   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.

AUTHOR
======

   Sean M. Burke `sburke@cpan.org'

Perl Extension to Implement Fat-Node Trees
******************************************

NAME
====

   Tree::Fat - Perl Extension to Implement Fat-Node Trees

SYNOPSIS
========

   This is not a plug-and-play perl extension.  This module is designed
for embedding (and there is no default embedding).

     1. tvgen.pl -p PREFIX

     2. Edit PREFIXtv.tmpl

     3. Compile and link into your own application!

DESCRIPTION
===========

   Implements object-oriented trees using algorithms adapted from b-trees
and AVL trees (without resorting to yucky C++).  Fat-node trees are not
the best for many niche applications but they do have excellent
all-terrain performance.

     TYPE       Speed       Flexibility  Scales     Memory   Keeps-Order
     ---------- ----------- ------------ ---------- -------- ------------
     Arrays     fastest     so-so        not good   MIN      yes
     Hashes     fast        good         so-so      so-so    no
     Fat-Trees  medium      silly        big        good     yes

WHAT IS A FAT-TREE?
===================

   It's a cross between a tree and an array.  Each tree node contains a
fixed length array of slots.  Tree performance is enhanced by balancing
array operations with tree operations.  Moreover, tree operations are
better optimized by taking the arrays into account.

HOW ABOUT PERSISTANCE?
======================

   F-Trees are designed for embedding.  (If you want *persistent* F-Trees
without the work, then check out the `ObjStore' extension by the same
author.  F-Trees are already integrated into the ObjectStore database,
right now!)

CURSOR BEHAVIOR
===============

   The only way to access a tree is via a cursor.  Cursors behavior is
derived from the principle of least-surprise (rather than greatest
efficiency).  More documentation there isn't.  Please read the source code
for more information.

   * Both cursors and trees store a version number.  If you modify the same
     tree with more than one cursor, you can get mismatched versions.  If
     there is a mismatch, an exception is thrown.

   * If you allow duplicate keys, seek always returns the first key that
     matches.  For example, the cursor will always match at the first
     instance of 'c': (a,b,*c,c,c,d,e).

EMBEDDING API
=============

   Flexibility is paramount.  The embedding API is much more flexible than
would be possible with C++ templates.  See `tvcommon.*' & `tv.*'.

PERFORMANCE
===========

   * Average Fill

     The number elements in the collection divided by the number of
     available slots.  Higher is better.  (Perl built-in hashes max out
     around 50-60%.  Hash tables generally max out at around 70%.)

   * Average Depth

     The average number of nodes to be inspected during a search.  Lower is
     better.

   * Average Centering

     Each fat-node is essentially an array of elements.  This array is
     allocated contiguously from the available slots.  The best arrangement
     (for insertions & deletions) is if the block of filled slots is
     centered.

REFERENCES
==========

   * http://paris.lcs.mit.edu/~bvelez/std-colls/cacm/cacm-2455.html

     Author: Foster, C. C.

     A generalization of AVL trees is proposed in which imbalances up to
     (triangle shape) is a small integer. An experiment is performed to
     compare these trees with standard AVL trees and with balanced trees on
     the basis of mean retrieval time, of amount of restructuring expected,
     and on the worst case of retrieval time. It is shown that, by
     permitting imbalances of up to five units, the retrieval time is
     increased a small amount while the amount of restructuring required is
     decreased by a factor of ten. A few theoretical results are derived,
     including the correction of an earlier paper, and are duly compared
     with the experimental data. Reasonably good correspondence is found.

     CACM August, 1973

   * http://www.imada.ou.dk/~kslarsen/Papers/AVL.html
          AVL Trees with Relaxed Balance
          Kim S. Larsen
          Proceedings of the 8th International Parallel Processing Symposium,
          pp. 888-893, IEEE Computer Society Press, 1994.

     AVL trees with relaxed balance were introduced with the aim of
     improving runtime performance by allowing a greater degree of
     concurrency. This is obtained by uncoupling updating from
     rebalancing. An additional benefit is that rebalancing can be
     controlled separately. In particular, it can be postponed completely
     or partially until after peak working hours.

     We define a new collection of rebalancing operations which allows for
     a significantly greater degree of concurrency than the original
     proposal. Additionally, in contrast to the original proposal, we prove
     the complexity of our algorithm.  If N is the maximum size the tree
     could ever have, we prove that each insertion gives rise to at most
     floor(log_phi(N + 3/2) + log_phi(sqrt(5)) - 3) rebalancing operations
     and that each deletion gives rise to at most floor(log_phi(N + 3/2) +
     log_phi(sqrt(5)) - 4) rebalancing operations, where phi is the golden
     ratio.

PUBLIC SOURCE CODE
==================

   The source code is being released in a malleable form to encourage as
much testing as possible.  Bugs in fundemental collections are simply
UNACCEPTABLE and it is hard to trust a single vendor to debug their code
properly.

   Get it via http://www.perl.com/CPAN/authors/id/JPRIT/ !

TODO
====

   Optimize more!

   Clean up refcnts in test scripts.

   More documentation.

AUTHOR
======

   Copyright © 1997-1999 Joshua Nathaniel Pritikin.  All rights reserved.

   This package is free software and is provided "as is" without express
or implied warranty.  It may be used, redistributed and/or modified under
the terms of the Perl Artistic License (see
http://www.perl.com/perl/misc/Artistic.html)

a multi node tree object.  Most useful for  modeling heirarchial data structures.
*********************************************************************************

NAME
====

   MultiNode.pm  - a multi node tree object.  Most useful for modeling
heirarchial data structures.

SYNOPSIS
========

     use Tree::MultiNode;
     my $tree   = new Tree::MultiNode;
     my $handle = new Tree::MultiNode::Handle($tree);

     $handle->set_key("top");
     $handle->set_key("level");

     $handle->add_child("child","1");
     $handle->add_child("child","2");

     $handle->first();
     $handle->down();

     $handle->add_child("grandchild","1-1");
     $handle->up();

     $handle->last();
     $handle->down();

     $handle->add_child("grandchild","2-1");
     $handle->up();

     $handle->top();
     &dump_tree($handle);

     sub dump_tree
     {
       ++$depth;
       my $handle = shift;
       my $lead = ' ' x ($depth*2);
       my($key,$val);

       ($key,$val) = $handle->get_data();

     print $lead, "key:   $key\n";
     print $lead, "val:   $val\n";
     print $lead, "depth: $depth\n";

     my $i;
     for( $i = 0; $i < scalar($handle->children); ++$i ) {
       $handle->down($i);
         &dump_tree($handle);
       $handle->up();
     }
     --$depth;
       }

DESCRIPTION
===========

   Tree::MultiNode, Tree::MultiNode::Node, and MultiNode::Handle are
objects modeled after C++ classes that I had written to help me model
heirarchical information as datastructures (such as the relationships
between records in an RDBMS).  The tree is basicly a list of lists type
data structure, where each node has a key, a value, and a list of
children.  The tree has no internal sorting, though all operations
perserve the order of the child nodes.

Creating a Tree
---------------

   The concept of creating a handle based on a tree lets you have multiple
handles into a single tree without having to copy the tree.  You have to
use a handle for all operations on the tree (other than construction).

   When you first construct a tree, it will have a single empty node.
When you construct a handle into that tree, it will set the top node in
the tree as it's current node.

     my $tree   = new Tree::MultiNode;
     my $handle = new Tree::MultiNode::Handle($tree);

Using a Handle to Manipulate the Tree
-------------------------------------

   At this point, you can set the key/value in the top node, or start
adding child nodes.

     $handle->set_key("blah");
     $handle->set_value("foo");

     $handle->add_child("quz","baz");
     # or
     $handle->add_child();

   add_child can take 3 paramters - a key, a value, and a position.  The
key and value will set the key/value of the child on construction.  If pos
is passed, the new child will be inserted into the list of children.

   To move the handle so it points at a child (so you can start
manipulating that child), there are a series of methods to call:

     $handle->first();   # sets the current child to the first in the list
     $handle->next();    # sets the next, or first if there was no next
     $handle->prev();    # sets the previous, or last if there was no next
     $handle->last();    # sets to the last child
     $handle->down();    # positions the handle's current node to the
                         # current child

   To move back up, you can call the method up:

     $handle->up();      # moves to this node's parent

   up() will fail if the current node has no parent node.  Most of the
member functions return either undef to indicate failure, or some other
value to indicate success.

$Tree::MultiNode::debug
-----------------------

   If set to a true value, it enables debugging output in the code.  This
will likely be removed in future versions as the code becomes more stable.

API REFERENCE
=============

Tree::MultiNode
---------------

   The tree object.

Tree::MultiNode::new
--------------------

   Creates a new Tree.  The tree will have a single top level node when
created.  The first node will have no value (undef) in either it's key or
it's value.

     my $tree = new Tree::MultiNode;

Tree::MultiNode::Node
---------------------

   Please note that the Node object is used internaly by the MultiNode
object.  Though you have the ability to interact with the nodes, it is
unlikely that you should need to.  That being said, the interface is
documented here anyway.

Tree::MultiNode::Node::new
--------------------------

   Creates a new Node.  There are two optional arguments.  If passed, the
first is stored as the key, and the second is stored as the value.

     my $node1 = new Tree::MultiNode::Node;
     my $node2 = new Tree::MultiNode::Node("fname");
     my $node3 = new Tree::MultiNode::Node("fname","Larry");

Tree::MultiNode::Node::key
--------------------------

   Used to set, or retreive the key for a node.  If a parameter is passed,
it sets the key for the node.  The value of the key member is alwyays
returned.

     print $node3->key(), "\n";    # 'fname'

Tree::MultiNode::Node::value
----------------------------

   Used to set, or retreive the value for a node.  If a parameter is
passed, it sets the value for the node.  The value of the value member is
alwyays returned.

     print $node3->value(), "\n";   # 'Larry'

Tree::MultiNode::Node::clear_key
--------------------------------

   Clears the key member bu deleting it.

     $node3->clear_key();

Tree::MultiNode::Node::clear_value
----------------------------------

   Clears the value member bu deleting it.

     $node3->clear_value();

Tree::MultiNode::Node::children
-------------------------------

   Returns a refrence to the array that contains the children of the node
object.

     $array_ref = $node3->children();

Tree::MultiNode::Node::child_keys   Tree::MultiNode::Node::child_values Tree::MultiNode::Node::child_kv_pairs
-------------------------------------------------------------------------------------------------------------

   These functions return arrays consisting of the appropriate data from
the child nodes.

     my @keys     = $handle->child_keys();
     my @vals     = $handle->child_values();
     my %kv_pairs = $handle->child_kv_pairs();

Tree::MultiNode::Node::child_key_positions
------------------------------------------

   This function returns a hashtable that consists of the child keys as
the hash keys, and the position in the child array as the value.  This
allows for a quick and dirty way of looking up the position of a given key
in the child list.

     my %h = $node->child_key_positions();

Tree::MultiNode::Node::parent
-----------------------------

   Returns a refrence to the parent node of the current node.

     $node_parent = $node3->parent();

Tree::MultiNode::Node::dump
---------------------------

   Used for diagnostics, it prints out the members of the node.

     $node3->dump();

Tree::MultiNode::Handle
-----------------------

   Handle is used as a 'pointer' into the tree.  It has a few attributes
that it keeps track of.  These are:

     1. the top of the tree
     2. the current node
     3. the current child node
     4. the depth of the current node

   The top of the tree never changes, and you can reset the handle to
point back at the top of the tree by calling the top() method.

   The current node is where the handle is 'pointing' in the tree.  The
current node is changed with functions like top(), down(), and up().

   The current child node is used for traversing downward into the tree.
The members first(), next(), prev(), last(), and position() can be used to
set the current child, and then traverse down into it.

   The depth of the current node is a measure of the length of the path
from the top of the tree to the current node, i.e. the top of the node has
a depth of 0, each of its children has a depth of 1, etc.

Tree::MultiNode::Handle::New
----------------------------

   Constructs a new handle.  You must pass a tree object to Handle::New.

     my $tree   = new Tree::MultiNode;
     my $handle = new Tree::MultiNode::Handle($tree);

Tree::MultiNode::Handle::tree
-----------------------------

   Returns the tree that was used to construct the node.  Useful if you're
trying to create another node into the tree.

     my $handle2 = new Tree::MultiNode::Handle($handle->tree());

Tree::MultiNode::Handle::get_data
---------------------------------

   Retrieves both the key, and value (as an array) for the current node.

     my ($key,$val) = $handle->get_data();

Tree::MultiNode::Handle::get_key
--------------------------------

   Retrieves the key for the current node.

     $key = $handle->get_key();

Tree::MultiNode::Handle::set_key
--------------------------------

   Sets the key for the current node.

     $handle->set_key("lname");

Tree::MultiNode::Handle::get_value
----------------------------------

   Retreives the value for the current node.

     $val = $handle->get_value();

Tree::MultiNode::Handle::set_value
----------------------------------

   Sets the value for the current node.

     $handle->set_value("Wall");

Tree::MultiNode::Handle::get_child
----------------------------------

   get_child takes an optional paramater which is the position of the child
that is to be retreived.  If this position is not specified, get_child
attempts to return the current child.  get_child returns a Node object.

     my $child_node = $handle->get_child();

Tree::MultiNode::Handle::add_child
----------------------------------

   This member adds a new child node to the end of the array of children
for the current node.  There are three optional parameters:

     - a key
     - a vlaue
     - a position

   If passed, the key and value will be set in the new child.  If a
position is passed, the new child will be inserted into the current array
of children at the position specified.

     $handle->add_child();                    # adds a blank child
     $handle->add_child("language","perl");   # adds a child to the end
     $handle->add_child("language","C++",0);  # adds a child to the front

Tree::MultiNode::Handle::depth
------------------------------

   Gets the depth for the current node.

     my $depth = $handle->depth();

Tree::MultiNode::Handle::select
-------------------------------

   Sets the current child via a specified value - basicly it iterates
through the array of children, looking for a match.  You have to supply
the key to look for, and optionaly a sub ref to find it.  The default for
this sub is

     sub { return shift eq shift; }

   Which is sufficient for testing the equality of strings (the most common
thing that I think will get stored in the tree).  If you're storing
multiple datatypes as keys, you'll have to write a sub that figures out
how to perform the comparisions in a sane manner.

   The sub ref should take 2 args, and compare them - return false if they
don't match, and true if they do.

     $handle->select('lname', sub { return shift eq shift; } );

Tree::MultiNode::Handle::position
---------------------------------

   Sets, or retreives the current child position.

     print "curr child pos is: ", $handle->position(), "\n";
     $handle->position(5);    # sets the 6th child as the current child

Tree::MultiNode::Handle::first Tree::MultiNode::Handle::next Tree::MultiNode::Handle::prev Tree::MultiNode::Handle::last
------------------------------------------------------------------------------------------------------------------------

   These functions manipulate the current child member.  first() sets the
first child as the current child, while last() sets the last.  next(), and
prev() will move to the next/prev child respectivly.  If there is no
current child node, next() will have the same effect as first(), and
prev() will operate as last().  prev() fails if the current child is the
first child, and next() fails if the current child is the last child -
i.e. they do not wrap around.

   These functions will fail if there are no children for the current node.

     $handle->first();  # sets to the 0th child
     $handle->next();   # to the 1st child
     $handle->prev();   # back to the 0th child
     $handle->last();   # go straight to the last child.

Tree::MultiNode::Handle::down
-----------------------------

   down() moves the handle to point at the current child node.  It fails
if there is no current child node.  When down() is called, the current
child becomes invalid (undef).

     $handle->down();

Tree::MultiNode::Handle::up
---------------------------

   down() moves the handle to point at the parent of the current node.  It
fails if there is no parent node.  When up() is called, the current child
becomes invalid (undef).

     $handle->up();

Tree::MultiNode::Handle::top
----------------------------

   Resets the handle to point back at the top of the tree.  When top() is
called, the current child becomes invalid (undef).

     $handle->top();

Tree::MultiNode::Handle::children
---------------------------------

   This returns an array of Node objects that represents the children of
the current Node.  Unlike Node::children(), the array Handle::children()
is not a refrnece to an array, but an array.  Useful if you need to
iterate through the children of the current node.

     print "There are: ", scalar($handle->children()), " children\n";
     foreach $child ($handle->children()) {
       print $child->key(), " : ", $child->value(), "\n";
     }

Tree::MultiNode::Handle::child_key_positions
--------------------------------------------

   This function returns a hashtable that consists of the child keys as
the hash keys, and the position in the child array as the value.  This
allows for a quick and dirty way of looking up the position of a given key
in the child list.

     my %h = $handle->child_key_positions();

Tree::MultiNode::Handle::get_child_key
--------------------------------------

   Returns the key at the specified position, or from the corresponding
child node.

     my $key = $handle->get_child_key();

Tree::MultiNode::Handle::get_child_value
----------------------------------------

   Returns the value at the specified position, or from the corresponding
child node.

     my $value = $handle->get_child_value();

Tree::MultiNode::Handle::remove_child
-------------------------------------

   Returns Tree::MultiNode::Node::child_kv_paris() for the current node
for this handle.

     my %pairs = $handle->kv_pairs();

Tree::MultiNode::Handle::remove_child
-------------------------------------

Tree::MultiNode::Handle::child_keys
-----------------------------------

   Returns the keys from the current node's children.  Returns undef if
there is no currnet node.

Tree::MultiNode::Handle::traverse
---------------------------------

     $handle->traverse(sub {
       my $h = shift;
       printf "%sk: %s v: %s\n",('  ' x $handle->depth()),$h->get_data();
     });

   Traverse takes a subroutine reference, and will visit each node of the
tree, starting with the node the handle currently points to, recrusivly
down from the current position of the handle.  Each time the subroutine is
called, it will be passed a handle which points to the node to be visited.
The handle passed to the subroutine is a copy of the handle that is used
to traverse the tree, so it's ok to change which node it points to.  Any
additional arguments after the sub ref will be passed to the traverse
function _before_ the handle is passed.  This should allow you to pass
constant arguments to the sub ref, or to have the subref to be a method on
an object (and still pass the object's 'self' to the method).

     $handle->traverse( \&Some::Object::method, $obj, $const1, \%const2 );

     ...
     sub method
     {
       my $handle = pop;
       my $self   = shift;
       my $const1 = shift;
       my $const2 = shift;
       # do something
     }

SEE ALSO
========

   Algorithms in C++    Robert Sedgwick    Addison Wesley 1992    ISBN
0201510596

   The Art of Computer Programming  Volume 1 Fundamental Algorithms
third edition, Donald E. Knuth

AUTHORS
=======

   Kyle R. Burton mortis@voicenet.com (initial version, and maintenence)
Daniel X. Pape dpape@canis.uiuc.edu (see Changes file from the source
archive) Eric Joanis <joanis@cs.toronto.edu>

BUGS
====

   - There is currently no way to remove a child node.

Perl implementation of N-ary search trees.
******************************************

NAME
====

   Tree::Nary - Perl implementation of N-ary search trees.

SYNOPSIS
========

     use Tree::Nary;

     $node = new Tree::Nary;

     $inserted_node = $node->insert($parent, $position, $node);
     $inserted_node = $node->insert_before($parent, $sibling, $node);
     $inserted_node = $node->append($parent, $node);
     $inserted_node = $node->prepend($parent, $node);
     $inserted_node = $node->insert_data($parent, $position, $data);
     $inserted_node = $node->insert_data_before($parent, $sibling, $data);
     $inserted_node = $node->append_data($parent, $data);
     $inserted_node = $node->prepend_data($parent, $data);

     $node->reverse_children($node);

     $node->traverse($node, $order, $flags, $maxdepth, $funcref, $argref);

     $node->children_foreach($node, $flags, $funcref, $argref);

     $root_node = $obj->get_root($node);

     $found_node = $node->find($node, $order, $flags, $data);
     $found_child_node = $node->find_child($node, $flags, $data);

     $index = $node->child_index($node, $data);
     $position = $node->child_position($node, $child);

     $first_child_node = $node->first_child($node);
     $last_child_node = $node->last_child($node);

     $nth_child_node = $node->nth_child($node, $index);

     $first_sibling = $node->first_sibling($node);
     $next_sibling = $node->next_sibling($node);
     $prev_sibling = $node->prev_sibling($node);
     $last_sibling = $node->last_sibling($node);

     $bool = $node->is_leaf($node);
     $bool = $node->is_root($node);

     $cnt = $node->depth($node);

     $cnt = $node->n_nodes($node);
     $cnt = $node->n_children($node);

     $bool = $node->is_ancestor($node);

     $cnt = $obj->max_height($node);

     $node->unlink($node);

DESCRIPTION
===========

   The *Tree::Nary* class implements N-ary trees (trees of data with any
number of branches), providing the organizational structure for a tree
(collection) of any number of nodes, but knowing nothing about the
specific type of node used.  It can be used to display hierarchical
database entries in an internal application (the NIS netgroup file is an
example of such a database). It offers the capability to select nodes on
the tree, and attachment points for nodes on the tree. Each attachment
point can support multiple child nodes.

   The data field contains the actual data of the node. The next and
previous fields point to the node's siblings (a sibling is another node
with the same parent). The parent field points to the parent of the node,
or is undef if the node is the root of the tree. The children field points
to the first child of the node. The other children are accessed by using
the next pointer of each child.

   This module is a translation (albeit not a direct one) from the C
implementation of N-ary trees, available in the *GLIB distribution* (see
SEE ALSO).

GLOBAL VARIABLES
================

BOOLEANS
--------

TRUE
FALSE
TRAVERSE FLAGS
--------------

   Specifies which nodes are visited during several of the tree functions,
including traverse() and find().

TRAVERSE_LEAFS
     Specifies that only leaf nodes should be visited.

TRAVERSE_NON_LEAFS
     Specifies that only non-leaf nodes should be visited.

TRAVERSE_ALL
     Specifies that all nodes should be visited.

TRAVERSE_MASK
     Combination of multiple traverse flags.

ORDER FLAGS
-----------

   Specifies the type of traversal performed by traverse() and find().

PRE_ORDER
     Visits a node, then its children.

IN_ORDER
     Visits a node's left child first, then the node itself, then its
     right child.  This is the one to use if you want the output sorted
     according to the compare function.

POST_ORDER
     Visits the node's children, then the node itself.

LEVEL_ORDER
     Calls the function for each child of the node, then recursively
     visits each child.

METHODS
=======

new( [DATA] )
-------------

   Creates a new Tree::Nary object. Used to create the first node in a
tree.  Insert optional DATA into new created node.

insert( PARENT, POSITION, NODE )
--------------------------------

   Inserts a NODE beneath the PARENT at the given POSITION, returning
inserted NODE. If POSITION is -1, NODE is inserted as the last child of
PARENT.

insert_before( PARENT, SIBLING, NODE )
--------------------------------------

   Inserts a NODE beneath the PARENT before the given SIBLING, returning
inserted NODE. If SIBLING is undef, the NODE is inserted as the last child
of PARENT.

append( PARENT, NODE )
----------------------

   Inserts a NODE as the last child of the given PARENT, returning
inserted NODE.

prepend( PARENT, NODE )
-----------------------

   Inserts a NODE as the first child of the given PARENT, returning
inserted NODE.

insert_data( PARENT, POSITION, DATA )
-------------------------------------

   Inserts a new node containing DATA, beneath the PARENT at the given
POSITION.  Returns the new inserted node.

insert_data_before( PARENT, SIBLING, DATA )
-------------------------------------------

   Inserts a new node containing DATA, beneath the PARENT, before the given
SIBLING. Returns the new inserted node.

append_data( PARENT, DATA )
---------------------------

   Inserts a new node containing DATA as the last child of the given
PARENT.  Returns the new inserted node.

prepend_data( PARENT, DATA )
----------------------------

   Inserts a new node containing DATA as the first child of the given
PARENT.  Returns the new inserted node.

reverse_children( NODE )
------------------------

   Reverses the order of the children of NODE.  It doesn't change the
order of the grandchildren.

traverse( NODE, ORDER, FLAGS, MAXDEPTH, FUNCTION, DATA )
--------------------------------------------------------

   Traverses a tree starting at the given root NODE. It calls the given
FUNCTION (with optional user DATA to pass to the FUNCTION) for each node
visited.

   The traversal can be halted at any point by returning TRUE from
FUNCTION.

   The ORDER in which nodes are visited is one of IN_ORDER, PRE_ORDER,
POST_ORDER and LEVEL_ORDER.

   FLAGS specifies which types of children are to be visited, one of
TRAVERSE_ALL, TRAVERSE_LEAFS and TRAVERSE_NON_LEAFS.

   MAXDEPTH is the maximum depth of the traversal. Nodes below this depth
will not be visited. If MAXDEPTH is -1, all nodes in the tree are visited.
If MAXDEPTH is 1, only the root is visited. If MAXDEPTH is 2, the root and
its children are visited. And so on.

children_foreach( NODE, FLAGS, FUNCTION, DATA )
-----------------------------------------------

   Calls a FUNCTION (with optional user DATA to pass to the FUNCTION) for
each of the children of a NODE. Note that it doesn't descend beneath the
child nodes.  FLAGS specifies which types of children are to be visited,
one of TRAVERSE_ALL, TRAVERSE_LEAFS and TRAVERSE_NON_LEAFS.

get_root( NODE )
----------------

   Gets the root node of a tree, starting from NODE.

find( NODE, ORDER, FLAGS, DATA )
--------------------------------

   Finds a NODE in a tree with the given DATA.

   The ORDER in which nodes are visited is one of IN_ORDER, PRE_ORDER,
POST_ORDER and LEVEL_ORDER.

   FLAGS specifies which types of children are to be searched, one of
TRAVERSE_ALL, TRAVERSE_LEAFS and TRAVERSE_NON_LEAFS.

   Returns the found node, or undef if the DATA is not found.

find_child( NODE, FLAGS, DATA )
-------------------------------

   Finds the first child of a NODE with the given DATA.

   FLAGS specifies which types of children are to be searched, one of
TRAVERSE_ALL, TRAVERSE_LEAFS and TRAVERSE_NON_LEAFS.

   Returns the found child node, or undef if the DATA is not found.

child_index( NODE, DATA )
-------------------------

   Gets the position of the first child of a NODE which contains the given
DATA.  Returns the index of the child of node which contains data, or -1
if DATA is not found.

child_position( NODE, CHILD )
-----------------------------

   Gets the position of a NODE with respect to its siblings. CHILD must be
a child of NODE. The first child is numbered 0, the second 1, and so on.
Returns the position of CHILD with respect to its siblings.

first_child( NODE )
-------------------

   Returns the first child of a NODE. Returns undef if NODE is undef or has
no children.

last_child( NODE )
------------------

   Returns the last child of a NODE. Returns undef if NODE is undef or has
no children.

nth_child( NODE, INDEX )
------------------------

   Gets a child of a NODE, using the given INDEX. The first child is at
INDEX 0.  If the INDEX is too big, undef is returned. Returns the child of
NODE at INDEX.

first_sibling( NODE )
---------------------

   Returns the first sibling of a NODE. This could possibly be the NODE
itself.

prev_sibling( NODE )
--------------------

   Returns the previous sibling of a NODE.

next_sibling( NODE )
--------------------

   Returns the next sibling of a NODE.

last_sibling( NODE )
--------------------

   Returns the last sibling of a NODE. This could possibly be the NODE
itself.

is_leaf( NODE )
---------------

   Returns TRUE if NODE is a leaf node (no children).

is_root( NODE )
---------------

   Returns TRUE if NODE is a root node (no parent nor siblings).

depth( NODE )
-------------

   Returns the depth of NODE. If NODE is undef, the depth is 0. The root
node has a depth of 1. For the children of the root node, the depth is 2.
And so on.

n_nodes( NODE, FLAGS )
----------------------

   Returns the number of nodes in a tree.

   FLAGS specifies which types of children are to be counted, one of
TRAVERSE_ALL, TRAVERSE_LEAFS and TRAVERSE_NON_LEAFS.

n_children( NODE )
------------------

   Returns the number of children of NODE.

is_ancestor( NODE, DESCENDANT )
-------------------------------

   Returns TRUE if NODE is an ancestor of DESCENDANT. This is true if NODE
is the parent of DESCENDANT, or if NODE is the grandparent of DESCENDANT,
etc.

max_height( NODE )
------------------

   Returns the maximum height of all branches beneath NODE. This is the
maximum distance from NODE to all leaf nodes.

   If NODE is undef, 0 is returned. If NODE has no children, 1 is returned.
If NODE has children, 2 is returned. And so on.

unlink( NODE )
--------------

   Unlinks NODE from a tree, resulting in two separate trees.  The NODE to
unlink becomes the root of a new tree.

EXAMPLES
========

   An example for each function can be found in the test script test.pl.

AUTHOR
======

   Frederic Soriano, <frederic.soriano@alcatel.fr>

COPYRIGHT
=========

   This package is free software and is provided "as is" without express or
implied warranty.  It may be used, redistributed and/or modified under the
same terms as Perl itself.

SEE ALSO
========

   API from the GLIB project,
http://developer.gnome.org/doc/API/glib/glib-n-ary-trees.html.

Perl implementation of Red/Black tree, a type of balanced tree.
***************************************************************

NAME
====

   Tree::RedBlack - Perl implementation of Red/Black tree, a type of
balanced tree.

SYNOPSIS
========

     use Tree::RedBlack;

     my $t = new Tree::RedBlack;
     $t->insert(3, 'cat');
     $t->insert(4, 'dog');
     my $v = $t->find(4);
     my $min = $t->min;
     my $max = $t->max;
     $t->delete(3);
     $t->print;

DESCRIPTION
===========

   This is a perl implementation of the Red/Black tree algorithm found in
the book "Algorithms", by Cormen, Leiserson & Rivest (more commonly known
as "CLR" or "The White Book").  A Red/Black tree is a binary tree which
remains "balanced"- that is, the longest length from root to a node is at
most one more than the shortest such length.  It is fairly efficient; no
operation takes more than O(lg(n)) time.

   A Tree::RedBlack object supports the following methods:

new ()
     Creates a new RedBlack tree object.

root ()
     Returns the root node of the tree.  Note that this will either be
     undef if no nodes have been added to the tree, or a
     Tree::RedBlack::Node object.  See the Tree/RedBlack/Node,
     manual page for details on the Node object.

cmp (&)
     Use this method to set a comparator subroutine.  The tree defaults to
     lexical comparisons.  This subroutine should be just like a
     comparator subroutine to sort, except that it doesn't do the $a, $b
     trick; the two elements to compare will just be the first two items
     on the stack.

insert ($;$)
     Adds a new node to the tree.  The first argument is the key of the
     node, the second is its value.  If a node with that key already
     exists, its value is replaced with the given value and the old value
     is returned.  Otherwise, undef is returned.

delete ($)
     The argument should be either a node object to delete or the key of a
     node object to delete. WARNING!!! THIS STILL HAS BUGS!!!

find ($)
     Searches the tree to find the node with the given key.  Returns the
     value of that node, or undef if a node with that key isn't found.
     Note, in particular, that you can't tell the difference between
     finding a node with value undef and not finding a node at all.  If
     you want to determine if a node with a given key exists, use the node
     method, below.

node ($)
     Searches the tree to find the node with the given key.  Returns that
     node object if it is found, undef otherwise.  The node object is a
     Tree::RedBlack::Node object.

min ()
     Returns the node with the minimal key.

max ()
     Returns the node with the maximal key.

AUTHOR
======

   Benjamin Holzman <bholzman@earthlink.net>

SEE ALSO
========

   Tree::RedBlack::Node

Node class for Perl implementation of Red/Black tree
****************************************************

NAME
====

   Tree::RedBlack::Node - Node class for Perl implementation of Red/Black
tree

SYNOPSIS
========

   use Tree::RedBlack; my $t = new Tree::RedBlack; $t->insert(3, 'dog');
my $node = $t->node(3); $animal = $node->val;

DESCRIPTION
===========

   A Tree::RedBlack::Node object supports the following methods:

key ()
     Key of the node.  This is what the nodes are sorted by in the tree.

val ($)
     Value of the node.  Can be any perl scalar, so it could be a hash-ref,
     f'rinstance.  This can be set directly.

color ()
     Color of the node.  1 for "red", 0 or undef for "black".

parent ()
     Parent node of this one.  Returns undef for root node.

left ()
     Left child node of this one.  Returns undef for leaf nodes.

right ()
     Right child node of this one.  Returns undef for leaf nodes.

min ()
     Returns the node with the minimal key starting from this node.

max ()
     Returns the node with the maximal key starting from this node.

successor ()
     Returns the node with the smallest key larger than this node's key,
     or this node if it is the node with the maximal key.

predecessor ()
     Similar to successor. WARNING: NOT YET IMPLEMENTED!!

   You can use these methods to write utility routines for actions on
red/black trees.  For instance, here's a routine which writes a tree out
to disk, putting the byte offsets of the left and right child records in
the record for each node.

     sub dump {
       my($node, $fh) = @_;
       my($left, $right);
       my $pos = tell $fh;
       print $fh $node->color ? 'R' : 'B';
       seek($fh, 8, 1);
       print $fh $node->val;
       if ($node->left) {
         $left = dump($node->left,$fh);
       }
       if ($node->right) {
         $right = dump($node->right,$fh);
       }
       my $end = tell $fh;
       seek($fh, $pos+1, 0);
       print $fh pack('NN', $left, $right);
       seek($fh, $end, 0);
       $pos;
     }

   You would call it like this:

     my $t = new Tree::RedBlack;
     ...
     open(FILE, ">tree.dump");
     dump($t->root,\*FILE);
     close FILE;

   As another example, here's a simple routine to print a human-readable
dump of the tree:

     sub pretty_print {
       my($node, $fh, $lvl) = @_;
       if ($node->right) {
         pretty_print($node->right, $fh, $lvl+1);
       }
       print $fh ' 'x($lvl*3),'[', $node->color ? 'R' : 'B', ']', $node->key, "\n";
       if ($node->left) {
         pretty_print($this->left, $fh, $lvl+1);
       }
     }

   A cleaner way of doing this kind of thing is probably to allow
sub-classing of Tree::RedBlack::Node, and then allow the Tree::RedBlack
constructor to take an argument saying what class of node it should be
made up out of. Hmmm...

AUTHOR
======

   Benjamin Holzman <bholzman@earthlink.net>

SEE ALSO
========

   Tree::RedBlack

Perl implementation of ternary search trees.
********************************************

NAME
====

   Tree::Ternary - Perl implementation of ternary search trees.

SYNOPSIS
========

     use Tree::Ternary;

     $obj = new Tree::Ternary;

     $ref = $obj->insert($str);
     $ref = $obj->rinsert($str);

     $ref = $obj->search($str);
     $ref = $obj->rsearch($str);

     $cnt = $obj->nodes();
     $cnt = $obj->terminals();

     $cnt = $obj->pmsearch($char, $str);
     @list = $obj->pmsearch($char, $str);

     $cnt = $obj->nearsearch($dist, $str);
     @list = $obj->nearsearch($dist, $str);

     @list = $obj->traverse();

DESCRIPTION
===========

   Tree::Ternary is a Perl implementation of ternary search trees as
described by Jon Bentley and Robert Sedgewick.  Ternary search trees are
interesting data structures that provide a means of storing and accessing
strings.  They combine the time efficiency of digital tries with the space
efficiency of binary search trees.  Unlike a hash, they also maintain
information about relative order.

   This module is a translation (albeit not a direct one) from the C
implementation published in Bentley and Sedgewick's article in the April
1998 issue of Dr. Dobb's Journal (see SEE ALSO).

METHODS
=======

new()
-----

   Creates a new Tree::Ternary object.

insert( STRING )
----------------

   Inserts STRING into the tree.  When a string is inserted, a scalar
variable is created to hold whatever data you may wish to associate with
the string.  A reference to this scalar is returned on a successful
insert.  If the string is already in the tree, undef is returned.

rinsert( STRING )
-----------------

   This is a recursive implementation of the insert function.  It behaves
the same as insert(), except it is slower and will carp about deep
recursion for strings near 100 characters in length.

   This is included for reference purposes only and may eventually
deprecated as an alias for insert().

search( STRING )
----------------

   Searches for the presence of STRING in the tree.  If the string is
found, a reference to the associated scalar is returned, otherwise undef
is returned.

rsearch( STRING )
-----------------

   A recursive implementation of search(), suffers the same drawbacks as
rinsert().

   This is included for reference purposes only and may eventually
deprecated as an alias for search().

nodes()
-------

   Returns the total number of nodes in the tree.  This count does not
include terminal nodes.

terminals()
-----------

   Returns the total number of terminal nodes in the tree.

pmsearch( CHAR, STRING )
------------------------

   Performs a pattern match for STRING against the tree, using CHAR as a
wildcard character.  The wildcard will match any characters.  For example,
if '.' was specified as the wildcard, and STRING was the pattern ".a.a.a."
would match "bananas" and "pajamas" (if they were both stored in the
tree).  In a scalar context, returns the count of matches found.  In an
array context, returns a list of the matched strings.

nearsearch( DISTANCE, STRING )
------------------------------

   Searches for all strings in a tree that differ from STRING by DISTANCE
or fewer characters.  In a scalar context, returns the count of matches
found.  In an array context, returns a list of the matched strings.

traverse()
----------

   Simply returns a sorted list of the strings stored in the tree.  This
method will do more tricks in the future.

NOTES
=====

Character Set
-------------

   Tree::Ternary currently only has support for strings of 8-bit
characters.  Since it uses a 2 character string to represent termination
of the input strings, it will handle any 8-bit character properly.

   In the future, I plan to expand the scope of its character handling, and
even include Unicode support.

Attributes
----------

   Specifying the :attrib tag as an argument to the use statement will
export the following internal constants for debugging purposes.
Tree::Ternary was built using Greg Bacon's array-based object design, and
these constants are used as attribute indices.

     SPLIT_CHAR
     LO_KID
     EQ_KID
     HI_KID
     PAYLOAD
     NODE_COUNT
     TERMINAL_COUNT

AUTHOR
======

   Mark Rogaski, wendigo@pobox.com

CREDITS
=======

   Many thanks to Tom Phoenix for his invaluable advice and critique.

COPYRIGHT
=========

   Copyright 1999, Mark Rogaski, wendigo@pobox.com, all rights reserved.

   This package is free software and is provided "as is" without express or
implied warranty.  It may be used, redistributed and/or modified under the
same terms as Perl itself.

SEE ALSO
========

   Bentley, Jon and Sedgewick, Robert.  "Ternary Search Trees".  Dr. Dobbs
Journal, April 1998.  http://www.ddj.com/articles/1998/9804/9804a/9804a.htm

   Bentley, Jon and Sedgewick, Robert.  "Fast Algorithms for Sorting and
Searching Strings".  Eighth Annual ACM-SIAM Symposium on Discrete
Algorithms New Orleans, January, 1997.
http://www.cs.princeton.edu/~rs/strings/

Perl extension implementing ternary search trees.
*************************************************

NAME
====

   Ternary_XS - Perl extension implementing ternary search trees.

SYNOPSIS
========

     use Tree::Ternary_XS;
     $obj = new Tree::Ternary_XS;

     $obj->insert($str);

     $obj->search($str);

     $obj->nodes();
     $obj->terminals();

     $cnt = $obj->pmsearch($char, $str);
     @list = $obj->pmsearch($char, $str);

     $cnt = $obj->nearsearch($dist, $str);
     @list = $obj->nearsearch($dist, $str);

     @list = $obj->traverse();

DESCRIPTION
===========

   Tree::Ternary_XS is a Perl interface to a C implementation of ternary
search trees as described by Jon Bentley and Robert Sedgewick.  Ternary
search trees are interesting data structures that provide a means of
storing and accessing strings. They combine the time efficiency of digital
tries with the space efficiency of binary search trees. Unlike a hash,
they also maintain information about relative order.

   This module is an adaptation from the C implementation published in
Bentley and Sedgewick's article in the April 1998 issue of Dr. Dobb's
Journal (see SEE ALSO). This module attempts to recreate the interface as
much as possible of Mark Rogaski's Tree::Ternary, a pure Perl
implementation. As Tree::Ternary_XS uses C code, it has important space
and speed advantages over Tree::Ternary.

METHODS
=======

new()
-----

   Creates a new Tree::Ternary object.

insert( STRING )
----------------

   Inserts STRING into the tree. When a string is inserted, a scalar
variable is created to hold whatever data you may wish to associate with
the string.  A reference to this scalar is returned on a successful
insert. If the string is already in the tree, undef is returned.

search( STRING )
----------------

   Searches for the presence of STRING in the tree. If the string is
found, a reference to the associated scalar is returned, otherwise undef
is returned.

nodes()
-------

   Returns the total number of nodes in the tree. This count does not
include terminal nodes.

terminals()
-----------

   Returns the total number of terminal nodes in the tree.

pmsearch( CHAR, STRING )
------------------------

   Performs a pattern match for STRING against the tree, using CHAR as a
wildcard character. The wildcard will match any characters. For example,
if '.' was specified as the wildcard, and STRING was the pattern ".a.a.a."
would match "bananas" and "pajamas" (if they were both stored in the
tree). In a scalar context, returns the count of matches found. In an
array context, returns a list of the matched strings.

nearsearch( DISTANCE, STRING )
------------------------------

   Searches for all strings in a tree that differ from STRING by DISTANCE
or fewer characters. In a scalar context, returns the count of matches
found. In an array context, returns a list of the matched strings.

traverse()
----------

   Simply returns a sorted list of the strings stored in the tree. This
method will do more tricks in the future.

NOTES
=====

Character Set
-------------

   Tree::Ternary_XS currently only has support for strings not containing
the null character.

Incompatibilities
-----------------

   There are a number of differences between Tree::Ternary and
Tree::Ternary_XS:

   The rinsert() and rsearch() methods are not supported. Use insert() and
search() instead.

   The insert and search methods do not return a reference to a scalar.
This limits the possibilities of the module somewhat, but is expected to
be rectified (with a different interface) in a later version.

Performance
-----------

   Tree::Ternary_XS has been benchmarked at about 50 times faster than
Tree::Ternary, with a great reduction in memory usage.

AUTHOR
======

   Leon Brocard, leon@astray.com

CREDITS
=======

   Thanks to Mark Rogaski for the pure Perl interface. Most of the
documentation and test scripts are simply copies from Tree::Ternary.

COPYRIGHT
=========

   Copyright (c) 2000 Leon Brocard. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   Bentley, Jon and Sedgewick, Robert. "Ternary Search Trees". Dr. Dobbs
Journal, April 1998. http://www.ddj.com/articles/1998/9804/9804a/9804a.htm

   Bentley, Jon and Sedgewick, Robert. "Fast Algorithms for Sorting and
Searching Strings". Eighth Annual ACM-SIAM Symposium on Discrete
Algorithms New Orleans, January, 1997.
http://www.cs.princeton.edu/~rs/strings/

An implementation of the Trie data structure in Perl
****************************************************

NAME
====

   Tree::Trie - An implementation of the Trie data structure in Perl

SYNOPSIS
========

     use Tree::Trie;
     use strict;

     my($trie) = new Tree::Trie;
     $trie->add(qw[aeode calliope clio erato euterpe melete melpomene mneme
       polymnia terpsichore thalia urania]);
     my(@all) = $trie->lookup("");
     my(@ms)  = $trie->lookup("m");
     $" = "--";
     print "All muses: @all\nMuses beginning with 'm': @ms\n";
     my(@deleted) = $trie->remove(qw[calliope thalia doc]);
     print "Deleted muses: @deleted\n";

DESCRIPTION
===========

   This module implements a trie data structure.  The term "trie" comes
from the word re*trie*val, but is generally pronounced like "try".  A trie
is a tree structure (or directed acyclic graph), the nodes of which
represent letters in a word.  For example, the final lookup for the word
'bob' would look something like `$ref->{'b'}{'o'}{'b'}{HASH(0x80c6bbc)}'
(the HASH being an end marker).  Only nodes which would represent words in
the trie exist, making the structure slightly smaller than a hash of the
same data set.

   The advantages of the trie over other data storage methods is that
lookup times are O(1) WRT the size of the index.  For sparse data sets, it
is probably not as efficient as performing a binary search on a sorted
list, and for small files, it has a lot of overhead.  The main advantage
(at least from my perspective) is that it provides a relatively cheap
method for finding a list of words in a large, dense data set which begin
with a certain string.

METHODS
=======

new([\%options])
     This is the constructor method for the class.  You may optionally
     pass it a hash reference with a set of option => value pairs.
     Currently, the only option available is 'deepsearch' and its valid
     values are 'boolean', 'choose' or 'count'.  The documentation on the
     'lookup' method describes the effects of these different values.

add(word0 [, word1...wordN])
     This method attempts to add words 0 through N to the trie.  Returns,
     in list context, the words successfully added to the trie.  In scalar
     context, returns the number of words successfully added.  As of this
     release, the only reason a word would fail to be added is if it is
     already in the trie.

remove(word0 [, word1...wordN])
     This method attempts to remove words 0 through N from the trie.
     Returns, in list context, the words successfully removed from the
     trie.  In scalar context, returns the number of words successfully
     removed.  As of this release, the only reason a word would fail to be
     removed is if it is not already in the trie.

lookup(word0)
     This method performs lookups on the trie.  In list context, it
     returns a complete list of words in the trie which begin with word0.
     In scalar context, the value returned depends on the setting of the
     'deepsearch' option.  You can set this option while creating your
     Trie object, or by using the deepsearch method.  If deepsearch is set
     to 'boolean', it will return a true value if any word in the trie
     begins with word0.  This setting is the fastest.  If deepsearch is
     'choose', it will return one word in the trie that begins with word0,
     or undef if nothing is found.  If word0 exists in the trie exactly,
     it will be returned.  Finally, if deepsearch is set to 'count', it
     will return a count of the words in the trie that begin with word0.
     This operation requires walking the entire tree, so can possibly be
     significantly slower than the other two options.  For reasons of
     backwards compatibilty, 'choose' is the default value of this option.

     To get a list of all words in the trie, use `lookup("")' in list
     context.

deepsearch([option])
     If option os specified, sets the deepsearch parameter.  Option may be
     one of: 'boolean', 'choose', 'count'.  Please see the documentation
     for the lookup method for the details of what these options mean.
     Returns the current value of the deepsearch parameter.

Future Work
===========

   * The ability to associate data with each word in a trie will be added,
     eventually.

   * There are a few methods of compression that allow you same some
     amount of space in the trie.  I have to figure out which ones are
     worth implemeting.  I may end up making the different compression
     methods configurable.

     I have now made one of them the default.

   * The ability to have Tree::Trie store its internal hash as a TIEd
     object of some sort.

AUTHOR
======

   Copyright 2000 Avi Finkel <`avi@finkel.org'>

   This package is free software and is provided "as is" without express
or implied warranty.  It may be used, redistributed and/or modified under
the terms of the Perl Artistic License (see
http://www.perl.com/perl/misc/Artistic.html)

UDDI client interface
*********************

NAME
====

   UDDI - UDDI client interface

SYNOPSIS
========

     use UDDI;

     my $list = UDDI::find_business(name => "a");
     my $bis = $list->businessInfos;
     for my $b ($bis->businessInfo) {
         print $b->name, "\n";
     }

DESCRIPTION
===========

   This module provide functions to interact with UDDI registry servers.
UDDI (*Universal Description, Discovery and Integration*) is the name of a
group of web-based registries that expose information about businesses and
their technical interfaces (APIs).  Learn more about UDDI at
*www.uddi.org*.

   The interface exposed comply with the "UDDI Programmer's API
Specification". Currently only the UDDI inquiry interface is provided.

FUNCTIONS
=========

   The following functions are provided.  None of them are exported by
default.  A successful invocation will return some UDDI object.  On error
undef is returned and the global variable %UDDI::err is set.

   All the find_xxx() functions take key/value pairs as arguments.  All
they get_xxx() functions simply take one or more keys as argument.

find_binding( serviceKey => $key, ... )
     This function will find binding details for a specific service.  On
     success a UDDI::bindingDetails object is returned.  Optional
     arguments are `maxRows', `findQualifiers' and `tModelBag'.

find_business( ... )
     This function will return businesses that fullfil the search criteria
     given.  On success a UDDI::businessList object is returned.  The
     returned businessList might be empty.  Arguments are `maxRows',
     `findQualifiers', name, `identiferBag', `categoryBag', `tModelBag'
     are `discoveryURLs'.

find_service( businessKey => $key, ... )
     This function will find services for a specific business.  On success
     a UDDI::serviceList object is returned.  Optional arguments are
     `maxRows', `findQualifiers', name, `categoryBag' and `tModelBag'.

find_tModel( ... )
     This function will return tModels that fullfil the search criteria
     given.  On success a UDDI::tModelList object is returned.  The
     returned tModelList might be empty.  Arguments are `maxRows',
     `findQualifiers', name, `identiferBag' and `categoryBag'.

get_bindingDetail( $bindingKey, ... )
     This function will return a UDDI::bindingDetail object containing a
     UDDI::bindingTemplate for each binding key given as argument.

get_businessDetail( $businessKey, ... )
     This function will return a UDDI::businessDetail object containing a
     UDDI::businessEntity for each business key given as argument.

get_businessDetailExt( $businessKey, ... )
     This function will return a UDDI::businessDetailExt object containing
     a UDDI::businessEntityExt for each business key given as argument.

get_serviceDetail( $serviceKey, ... )
     This function will return a UDDI::serviceDetail object containing a
     UDDI::businessService for each service key given as argument.

get_tModelDetail( $tModelKey, ... )
     This function will return a UDDI::tModelDetail object containing a
     UDDI::tModel for each tModel key given as argument.

GLOBALS
=======

%UDDI::err
----------

   In case of errors the functions above will return undef and the
%UDDI::err hash will be filled with the following values:

type
     A short string giving the overall type of the failure.  It can be
     either "HTTP" or "SOAP".

code
     Error code.  For HTTP it is a 3 digit number.  For UDDI failures it is
     some string prefixed with "E_".  For general SOAP failures it is a
     short string like "VersionMismatch", "MustUnderstand", "Client",
     "Server" (defined in section 4.4.1 in the SOAP spec.)

message
     A short human readable (English) message describing the error.

detail
     A reference to the corresponing error object.

   The hash will be empty after a successful function call.

$UDDI::registry
---------------

   The $UDDI::registry variable contains the URL to the registry server to
use for the calls.  Currently it defaults to Microsoft's test server.

$UDDI::TRACE
------------

   For debugging you might assign a file handle to the $UDDI::TRACE
variable.  Trace logs of the SOAP messages are then written to this file.

SEE ALSO
========

   http://www.uddi.org, see SOAP, SOAP/Lite,

AUTHOR
======

   Gisle Aas <gisle@ActiveState.com>

   Copyright 2000 ActiveState Tool Corp.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Library for UDDI clients in Perl
********************************

NAME
====

   UDDI::Lite - Library for UDDI clients in Perl

SYNOPSIS
========

     use UDDI::Lite;
     print UDDI::Lite
       -> proxy('http://uddi.microsoft.com/inquire')
       -> find_business(name => 'old')
       -> result
       -> businessInfos->businessInfo->serviceInfos->serviceInfo->name;

   The same code with autodispatch:

     use UDDI::Lite +autodispatch =>
       proxy => 'http://uddi.microsoft.com/inquire'
     ;

     print find_business(name => 'old')
       -> businessInfos->businessInfo->serviceInfos->serviceInfo->name;

   Or with importing:

     use UDDI::Lite
       'UDDI::Lite' => [':inquire'],
       proxy => 'http://uddi.microsoft.com/inquire'
     ;

     print find_business(name => 'old')
       -> businessInfos->businessInfo->serviceInfos->serviceInfo->name;

   Publishing API:

     use UDDI::Lite
       import => ['UDDI::Data'],
       import => ['UDDI::Lite'],
       proxy => "https://some.server.com/endpoint_fot_publishing_API";

     my $auth = get_authToken({userID => 'USERID', cred => 'CRED'})->authInfo;
     my $busent = with businessEntity =>
       name("Contoso Manufacturing"),
       description("We make components for business"),
       businessKey(''),
       businessServices with businessService =>
         name("Buy components"),
         description("Bindings for buying our components"),
         serviceKey(''),
         bindingTemplates with bindingTemplate =>
           description("BASDA invoices over HTTP post"),
           accessPoint('http://www.contoso.com/buy.asp'),
           bindingKey(''),
           tModelInstanceDetails with tModelInstanceInfo =>
             description('some tModel'),
             tModelKey('UUID:C1ACF26D-9672-4404-9D70-39B756E62AB4')
     ;
     print save_business($auth, $busent)->businessEntity->businessKey;

DESCRIPTION
===========

   UDDI::Lite for Perl is a collection of Perl modules which provides a
simple and lightweight interface to the Universal Description, Discovery
and Integration (UDDI) server.

   To learn more about UDDI, visit http://www.uddi.org/.

   The main features of the library are:

   * Supports both inquiry and publishing API

   * Builded on top of SOAP::Lite module, hence inherited syntax and
     features

   * Supports easy-to-use interface with convinient access to (sub)elements
     and attributes

   * Supports HTTPS protocol

   * Supports SMTP protocol

   * Supports Basic/Digest server authentication

OVERVIEW OF CLASSES AND PACKAGES
================================

   This table should give you a quick overview of the classes provided by
the library.

     UDDI::Lite.pm
     -- UDDI::Lite         -- Main class provides all logic
     -- UDDI::Data         -- Provides extensions for serialization architecture
     -- UDDI::Serializer   -- Serializes data structures to UDDI/SOAP package
     -- UDDI::Deserializer -- Deserializes result into objects
     -- UDDI::SOM          -- Provides access to deserialized object tree

UDDI::Lite
----------

   All methods that UDDI::Lite gives you access to can be used for both
setting and retrieving values. If you provide no parameters, you'll get
current value, and if you'll provide parameter(s), new value will be
assigned and method will return object (if not stated something else).
This is suitable for stacking these calls like:

     $uddi = UDDI::Lite
       -> on_debug(sub{print@_})
       -> proxy('http://uddi.microsoft.com/inquire')
     ;

   Order is insignificant and you may call new() method first. If you
don't do it, UDDI::Lite will do it for you. However, new() method gives
you additional syntax:

     $uddi = new UDDI::Lite
       on_debug => sub {print@_},
       proxy => 'http://uddi.microsoft.com/inquire'
     ;

   new() accepts hash with method names and values, and will call
appropriate method with passed value.

   Since new() is optional it won't be mentioned anymore.

   Other available methods inherited from SOAP::Lite and most usable are:

proxy()
     Shortcut for `transport->proxy()'. This lets you specify an endpoint
     and also loads the required module at the same time. It is required
     for dispatching SOAP calls. The name of the module will be defined
     depending on the protocol specific for the endpoint. SOAP::Lite will
     do the rest work.

namespace()
     Shortcut for `serializer->namespace()'. Lets you specify default
     namespace for generated envelope. 'SOAP-ENV' by default.

on_fault()
     Lets you specify handler for on_fault event. Default behavior is die
     on transport error and does nothing on others. You can change this
     behavior globally or locally, for particular object.

on_debug()
     Lets you specify handler for on_debug event. Default behavior is do
     nothing. Use +trace/+debug option for UDDI::Lite instead.

UDDI::Data
----------

   You can use this class if you want to specify value and name for UDDI
elements.  For example, `UDDI::Data->name('businessInfo')->value(123)' will
be serialized to `<businessInfo>123</businessInfo>', as well as
`UDDI::Data-'name(businessInfo => 123)>.

   If you want to provide names for your parameters you can either specify

     find_business(name => 'old')

   or do it with UDDI::Data:

     find_business(UDDI::Data->name(name => 'old'))

   Later has some advantages: it'll work on any level, so you can do:

     find_business(UDDI::Data->name(name => UDDI::Data->name(subname => 'old')))

   and also you can create arrays with this syntax:

   find_business(UDDI::Data->name(name =>     [UDDI::Data->name(subname1
=> 'name1'),      UDDI::Data->name(subname2 => 'name2')]))

   will be serialized into:

     <find_business xmlns="urn:uddi-org:api" generic="1.0">
       <name>
         <subname1>name1</subname1>
         <subname2>name2</subname2>
       </name>
     </find_business>

   For standard elements more convinient syntax is available:

     find_business(
       findQualifiers(findQualifier('sortByNameAsc',
                                    'caseSensitiveMatch')),
       name('M')
     )

   and

   find_business(     findQualifiers([findQualifier('sortByNameAsc'),
              findQualifier('caseSensitiveMatch')]),     name('M')   )

   both will generate:

     <SOAP-ENV:Envelope
       xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
       <SOAP-ENV:Body>
         <find_business xmlns="urn:uddi-org:api" generic="1.0">
           <findQualifiers>
             <findQualifier>sortByNameAsc</findQualifier>
             <findQualifier>caseSensitiveMatch</findQualifier>
           </findQualifiers>
           <name>M</name>
         </find_business>
       </SOAP-ENV:Body>
     </SOAP-ENV:Envelope>

   You can use ANY valid combinations (according to "UDDI Programmer's API
Specification"). If you try to generate something unusual, like
`name(name('myname'))', you'll get:

     Don't know what to do with 'name' and 'name' elements ....

   If you REALLY need to do it, use UDDI::Data syntax described above.

   As special case you can pass hash as the first parameter of method call
and values of this hash will be added as attributes to top element:

     find_business({maxRows => 10}, UDDI::Data->name(name => old))

   gives you

     <find_business xmlns="urn:uddi-org:api" generic="1.0" maxRows="10">
       ....
     </find_business>

   You can also pass back parameters exactly as you get it from method call
(like you probably want to do with authInfo).

   You can get access to attributes and elements through the same
interface:

     my $list = find_business(name => old);
     my $bis = $list->businessInfos;
     for ($bis->businessInfo) {
       my $s = $_->serviceInfos->serviceInfo;
       print $s->name,        # element
             $s->businessKey, # attribute
             "\n";
     }

   To match advantages provided by with operator available in other
languages (like VB) we provide similar functionality that adds you
flexibility:

     with findQualifiers =>
       findQualifier => 'sortByNameAsc',
       findQualifier => 'caseSensitiveMatch'

   is the same as:

     with(findQualifiers =>
       findQualifier('sortByNameAsc'),
       findQualifier('caseSensitiveMatch'),
     )

   and:

     findQualifiers->with(
       findQualifier('sortByNameAsc'),
       findQualifier('caseSensitiveMatch'),
     )

   will all generate the same code as mentioned above:

     findQualifiers(findQualifier('sortByNameAsc',
                                  'caseSensitiveMatch')),

   Advantage of with syntax is the you can specify both attributes and
elements through the same interface. First argument is element where all
other elements and attributes will be attached. Provided examples and
tests cover different syntaxes.

AUTODISPATCHING
---------------

   UDDI::Lite provides autodispatching feature that lets you create code
that looks similar for local and remote access.

   For example:

     use UDDI::Lite +autodispatch =>
       proxy => 'http://uddi.microsoft.com/inquire';

   tells autodispatch all UDDI calls to
'http://uddi.microsoft.com/inquire'. All subsequent calls can look like:

     find_business(name => 'old');
     find_business(UDDI::Data->name(name => 'old'));
     find_business(name('old'));

BUGS AND LIMITATIONS
====================

   * Interface is still subject to change.

   * Though HTTPS/SSL is supported you should specify it yourself (with
     proxy or `endpoint') for publishing API calls.

AVAILABILITY
============

   For now UDDI::Lite is distributed as part of SOAP::Lite package.  You
can download it from ( http://soaplite.com/ ) or from CPAN (
http://search.cpan.org/search?dist=SOAP-Lite ).

SEE ALSO
========

   See SOAP/Lite, (
http://search.cpan.org/search?dist=SOAP-Lite ) UDDI, (
http://search.cpan.org/search?dist=UDDI )

COPYRIGHT
=========

   Copyright (C) 2000-2001 Paul Kulchenko. All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Paul Kulchenko (paulclinger@yahoo.com)

base class for ALL classes (blessed references)
***********************************************

NAME
====

   UNIVERSAL - base class for ALL classes (blessed references)

SYNOPSIS
========

     $io = $fd->isa("IO::Handle");
     $sub = $obj->can('print');

     $yes = UNIVERSAL::isa($ref, "HASH");

DESCRIPTION
===========

   UNIVERSAL is the base class which all bless references will inherit
from, see Perlobj (perl.info),

   UNIVERSAL provides the following methods

isa ( TYPE )
     isa returns *true* if `REF' is blessed into package TYPE or inherits
     from package TYPE.

     isa can be called as either a static or object method call.

can ( METHOD )
     can checks if the object has a method called METHOD. If it does then
     a reference to the sub is returned. If it does not then undef is
     returned.

     can can be called as either a static or object method call.

VERSION ( [ REQUIRE ] )
     VERSION will return the value of the variable $VERSION in the package
     the object is blessed into. If REQUIRE is given then it will do a
     comparison and die if the package version is not greater than or
     equal to REQUIRE.

     VERSION can be called as either a static or object method call.

   The isa and can methods can also be called as subroutines

UNIVERSAL::isa ( VAL, TYPE )
     isa returns *true* if one of the following statements is true.

        * `VAL' is a reference blessed into either package TYPE or a
          package which inherits from package TYPE.

        * `VAL' is a reference to a TYPE of Perl variable (e.g. 'HASH').

        * `VAL' is the name of a package that inherits from (or is itself)
          package TYPE.

UNIVERSAL::can ( VAL, METHOD )
     If `VAL' is a blessed reference which has a method called METHOD, can
     returns a reference to the subroutine.   If `VAL' is not a blessed
     reference, or if it does not have a method METHOD, undef is returned.

   These subroutines should not be imported via `use UNIVERSAL qw(...)'.
If you want simple local access to them you can do

     *isa = \&UNIVERSAL::isa;

   to import isa into your package.

Lightweight, universal exporting of variables
*********************************************

NAME
====

   UNIVERSAL::exports - Lightweight, universal exporting of variables

SYNOPSIS
========

     package Foo;
     use UNIVERSAL::exports;

     # Just like Exporter.
     @EXPORT       = qw($This &That);
     @EXPORT_OK    = qw(@Left %Right);

     # Meanwhile, in another piece of code!
     package Bar;
     use Foo;  # exports $This and &That.

DESCRIPTION
===========

   This is an alternative to Exporter intended to provide a universal,
lightweight subset of its functionality.  It supports import, `@EXPORT'
and `@EXPORT_OK' and not a whole lot else.

   Additionally, `exports()' is provided to find out what symbols a module
exports.

   UNIVERSAL::exports places its methods in the UNIVERSAL namespace, so
there is no need to subclass from it.

Methods
=======

   UNIVERSAL::exports has two public methods...

import
          Some::Module->import;
          Some::Module->import(@symbols);

     Works just like `Exporter::import()' excepting it only honors
     @Some::Module::EXPORT and @Some::Module::EXPORT_OK.

     The given @symbols are exported to the current package provided they
     are in @Some::Module::EXPORT or @Some::Module::EXPORT_OK.  Otherwise
     an exception is thrown (ie. the program dies).

     If @symbols is not given, everything in @Some::Module::EXPORT is
     exported.

exports
          @exported_symbols = Some::Module->exports;
          Some::Module->exports($symbol);

     Reports what symbols are exported by Some::Module.  With no arguments,
     it simply returns a list of all exportable symbols.  Otherwise, it
     reports if it will export a given $symbol.

DIAGNOSTICS
===========

'"%s" is not exported by the %s module'
     Attempted to import a symbol which is not in @EXPORT or @EXPORT_OK.

'Can\'t export symbol: %s'
     Attempted to import a symbol of an unknown type (ie. the leading $@%
     salad wasn't recognized).

AUTHORS
=======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Exporter, UNIVERSAL/require,
http://dev.perl.org/rfc/257.pod

require() modules from a variable
*********************************

NAME
====

     UNIVERSAL::require - require() modules from a variable

SYNOPSIS
========

     # This only needs to be said once in your program.
     require UNIVERSAL::require;

     # Same as "require Some::Module;"
     Some::Module->require;

     # Ditto
     my $module = 'Some::Module';
     $module->require;

DESCRIPTION
===========

   If you've ever had to do this...

     eval "require $module";

   to get around the bareword caveats on require(), this module is for
you.  It creates a universal require() class method that will work with
every Perl module.  So instead of doing some arcane eval() work, you can
do this:

     $module->require;

   And `use Some::Module' can be done dynamically like so:

     BEGIN {
         $module->require;
         $module->import;
     }

   It doesn't save you much typing, but it'll make alot more sense to
someone who's not a ninth level Perl acolyte.

Methods
=======

require
          $module->require;
          $module->require($version);

     This works exactly like Perl's require, except without the bareword
     restriction.  Since require() is placed in the UNIVERSAL namespace, it
     will work on any module.  You just have to use UNIVERSAL::require
     somewhere in your code.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See UNIVERSAL/exports, `require', see Perlfunc (perl.info),
http://dev.perl.org/rfc/253.pod

Uniform Resource Identifiers (absolute and relative)
****************************************************

NAME
====

   URI - Uniform Resource Identifiers (absolute and relative)

SYNOPSIS
========

     $u1 = URI->new("http://www.perl.com");
     $u2 = URI->new("foo", "http");
     $u3 = $u2->abs($u1);
     $u4 = $u3->clone;
     $u5 = URI->new("HTTP://WWW.perl.com:80")->canonical;

     $str = $u->as_string;
     $str = "$u";

     $scheme = $u->scheme;
     $opaque = $u->opaque;
     $path   = $u->path;
     $frag   = $u->fragment;

     $u->scheme("ftp");
     $u->host("ftp.perl.com");
     $u->path("cpan/");

DESCRIPTION
===========

   This module implements the `URI' class.  Objects of this class
represent "Uniform Resource Identifier references" as specified in RFC
2396.

   A Uniform Resource Identifier is a compact string of characters for
identifying an abstract or physical resource.  A Uniform Resource
Identifier can be further classified either a Uniform Resource Locator
(URL) or a Uniform Resource Name (URN).  The distinction between URL and
URN does not matter to the `URI' class interface. A "URI-reference" is a
URI that may have additional information attached in the form of a
fragment identifier.

   An absolute URI reference consists of three parts.  A scheme, a *scheme
specific part* and a fragment identifier.  A subset of URI references
share a common syntax for hierarchical namespaces.  For these the scheme
specific part is further broken down into *authority*, path and query
components.  These URI can also take the form of relative URI references,
where the scheme (and usually also the authority) component is missing,
but implied by the context of the URI reference.  The three forms of URI
reference syntax are summarized as follows:

     <scheme>:<scheme-specific-part>#<fragment>
     <scheme>://<authority><path>?<query>#<fragment>
     <path>?<query>#<fragment>

   The components that a URI reference can be divided into depend on the
scheme.  The `URI' class provides methods to get and set the individual
components.  The methods available for a specific `URI' object depend on
the scheme.

CONSTRUCTORS
============

   The following methods construct new `URI' objects:

$uri = URI->new( $str, [$scheme] )
     This class method constructs a new URI object.  The string
     representation of a URI is given as argument together with an optional
     scheme specification.  Common URI wrappers like "" and <>, as well as
     leading and trailing white space, are automatically removed from the
     $str argument before it is processed further.

     The constructor determines the scheme, maps this to an appropriate
     URI subclass, constructs a new object of that class and returns it.

     The $scheme argument is only used when $str is a relative URI.  It
     can either be a simple string that denotes the scheme, a string
     containing an absolute URI reference or an absolute `URI' object.  If
     no $scheme is specified for a relative URI $str, then $str is simply
     treated as a generic URI (no scheme specific methods available).

     The set of characters available for building URI references is
     restricted (see URI/Escape).  Characters outside
     this set are automatically escaped by the URI constructor.

$uri = URI->new_abs( $str, $base_uri )
     This constructs a new absolute URI object.  The $str argument can
     denote a relative or absolute URI.  If relative, then it will be
     absolutized using $base_uri as base. The $base_uri must be an absolute
     URI.

$uri = URI::file->new( $filename, [$os] )
     This constructs a new file URI from a file name.  See URI/file.

$uri = URI::file->new_abs( $filename, [$os] )
     This constructs a new absolute file URI from a file name.  See
     URI/file.

$uri = URI::file->cwd
     This returns the current working directory as a file URI.  See
     URI/file.

$uri->clone
     This method returns a copy of the $uri.

COMMON METHODS
==============

   The methods described in this section are available for all `URI'
objects.

   Methods that give access to components of a URI will always return the
old value of the component.  The value returned will be undef if the
component was not present.  There is generally a difference between a
component that is empty (represented as "") and a component that is
missing (represented as undef).  If an accessor method is given an
argument it will update the corresponding component in addition to
returning the old value of the component.  Passing an undefined argument
will remove the component (if possible).  The description of the various
accessor methods will tell if the component is passed as an escaped or an
unescaped string.  Components that can be futher divided into sub-parts
are usually passed escaped, as unescaping might change its semantics.

   The common methods available for all URI are:

$uri->scheme( [$new_scheme] )
     This method sets and returns the scheme part of the $uri.  If the
     $uri is relative, then $uri->scheme returns undef.  If called with an
     argument, it will update the scheme of $uri, possibly changing the
     class of $uri, and return the old scheme value.  The method croaks if
     the new scheme name is illegal; scheme names must begin with a letter
     and must consist of only US-ASCII letters, numbers, and a few special
     marks: ".", "+", "-".  This restriction effectively means that scheme
     have to be passed unescaped.  Passing an undefined argument to the
     scheme method will make the URI relative (if possible).

     Letter case does not matter for scheme names.  The string returned by
     $uri->scheme is always lowercase.  If you want the scheme just as it
     was written in the URI in its original case, you can use the
     $uri->_scheme method instead.

$uri->opaque( [$new_opaque] )
     This method sets and returns the scheme specific part of the $uri
     (everything between the scheme and the fragment) as an escaped string.

$uri->path( [$new_path] )
     This method sets and returns the same value as $uri->opaque unless
     the URI supports the generic syntax for hierarchical namespaces.  In
     that case the generic method is overridden to set and return the part
     of the URI between the *host name* and the fragment.

$uri->fragment( [$new_frag] )
     This method returns the fragment identifier of a URI reference as an
     escaped string.

$uri->as_string
     This method returns a URI object to a plain string.  URI objects are
     also converted to plain strings automatically by overloading.  This
     means that $uri objects can be used as plain strings in most Perl
     constructs.

$uri->canonical
     This method will return a normalized version of the URI.  The rules
     for normalization are scheme dependent.  It usually involves
     lowercasing of the scheme and the Internet host name components,
     removing the explicit port specification if it matches the default
     port, uppercasing all escape sequences, and unescaping octets that
     can be better represented as plain characters.

     For efficiency reasons, if the $uri already was in normalized form,
     then a reference to it is returned instead of a copy.

$uri->eq( $other_uri )
URI::eq( $first_uri, $other_uri )
     This method tests whether two URI references are equal.  URI
     references that normalize to the same string are considered equal.
     The method can also be used as a plain function which can also test
     two string arguments.

     If you need to test whether two `URI' object references denote the
     same object, use the '==' operator.

$uri->abs( $base_uri )
     This method returns an absolute URI reference.  If $uri already is
     absolute, then a reference to it is simply returned.  If the $uri is
     relative, then a new absolute URI is constructed by combining the
     $uri and the $base_uri, and returned.

$uri->rel( $base_uri )
     This method returns a relative URI reference if it is possible to
     make one that denotes the same resource relative to $base_uri.  If
     not, then $uri is simply returned.

GENERIC METHODS
===============

   The following methods are available to schemes that use the
common/generic syntax for hierarchical namespaces.  The description of
schemes below will tell which one these are.  Unknown schemes are assumed
to support the generic syntax, and therefore the following methods:

$uri->authority( [$new_authority] )
     This method sets and returns the escaped authority component of the
     $uri.

$uri->path( [$new_path] )
     This method sets and returns the escaped path component of the $uri
     (the part between the host name and the query or fragment).  The path
     will never be undefined, but it can be the empty string.

$uri->path_query( [$new_path_query] )
     This method sets and returns the escaped path and query components as
     a single entity.  The path and the query are separated by a "?"
     character, but the query can itself contain "?".

$uri->path_segments( [$segment,...] )
     This method sets and returns the path.  In scalar context it returns
     the same value as $uri->path.  In list context it will return the
     unescaped path segments that make up the path.  Path segments that
     have parameters are returned as an anonymous array.  The first element
     is the unescaped path segment proper.  Subsequent elements are escaped
     parameter strings.  Such an anonymous array uses overloading so it can
     be treated as a string too, but this string does not include the
     parameters.

$uri->query( [$new_query] )
     This method sets and returns the escaped query component of the $uri.

$uri->query_form( [$key => $value,...] )
     This method sets and returns query components that use the
     *application/x-www-form-urlencoded* format.  Key/value pairs are
     separated by "&" and the key is separated from the value with a "="
     character.

$uri->query_keywords( [$keywords,...] )
     This method sets and returns query components that use the keywords
     separated by "+" format.

SERVER METHODS
==============

   Schemes where the *authority* component denotes a Internet host will
have the following methods available in addition to the generic methods.

$uri->userinfo( [$new_userinfo] )
     This method sets and returns the escaped userinfo part of the
     authority componenent.

     For some schemes this will be a user name and a password separated by
     a colon.  This practice is not recommended. Embedding passwords in
     clear text (such as URI) has proven to be a security risk in almost
     every case where it has been used.

$uri->host( [$new_host] )
     This method sets and returns the unescaped hostname.

     If the $new_host string ends with a colon and a number, then this
     number will also set the port.

$uri->port( [ $new_port] )
     This method sets and returns the port.  The port is simple integer
     that should be greater than 0.

     If no explicit port is specified in the URI, then the default port of
     the URI scheme is returned. If you don't want the default port
     substituted, then you can use the $uri->_port method instead.

$uri->host_port( [ $new_host_port ] )
     This method sets and returns the host and port as a single unit.  The
     returned value will include a port, even if it matches the default
     port.  The host part and the port part is separated with a colon; ":".

$uri->default_port
     This method returns the default port of the URI scheme that $uri
     belongs to.  For http this will be the number 80, for ftp this will
     be the number 21, etc.  The default port for a scheme can not be
     changed.

SCHEME SPECIFIC SUPPORT
=======================

   The following URI schemes are specifically supported.  For `URI'
objects not belonging to one of these you can only use the common and
generic methods.

data:
     The data URI scheme is specified in RFC 2397.  It allows inclusion of
     small data items as "immediate" data, as if it had been included
     externally.

     `URI' objects belonging to the data scheme support the common methods
     and two new methods to access their scheme specific components;
     $uri->media_type and $uri->data.  See URI/data, for
     details.

file:
     An old specification of the file URI scheme is found in RFC 1738.  A
     new RFC 2396 based specification in not available yet, but file URI
     references are in common use.

     `URI' objects belonging to the file scheme support the common and
     generic methods.  In addition they provide two methods to map file URI
     back to local file names; $uri->file and $uri->dir.  See
     URI/file, for details.

ftp:
     An old specification of the ftp URI scheme is found in RFC 1738.  A
     new RFC 2396 based specification in not available yet, but ftp URI
     references are in common use.

     `URI' objects belonging to the ftp scheme support the common, generic
     and server methods.  In addition they provide two methods to access
     the userinfo sub-components: $uri->user and $uri->password.

*gopher*:
     The *gopher* URI scheme is specified in
     <draft-murali-url-gopher-1996-12-04> and will hopefully be available
     as a RFC 2396 based specification.

     `URI' objects belonging to the gopher scheme support the common,
     generic and server methods. In addition they support some methods to
     access gopher specific path components: $uri->gopher_type,
     $uri->selector, $uri->search, $uri->string.

http:
     The http URI scheme is specified in <draft-ietf-http-v11-spec-rev-06>
     (which will become an RFC soon).  The scheme is used to reference
     resources hosted by HTTP servers.

     `URI' objects belonging to the http scheme support the common,
     generic and server methods.

*https*:
     The *https* URI scheme is a Netscape invention which is commonly
     implemented.  The scheme is used to reference HTTP servers through SSL
     connections.  It's syntax is the same as http, but the default port
     is different.

*ldap*:
     The *ldap* URI scheme is specified in RFC 2255.  LDAP is the
     Lightweight Directory Access Protocol.  A ldap URI describes an LDAP
     search operation to perform to retrieve information from an LDAP
     directory.

     `URI' objects belonging to the ldap scheme support the common,
     generic and server methods as well as specific ldap methods; $uri->dn,
     $uri->attributes, $uri->scope, $uri->filter, $uri->extensions.  See
     URI/ldap, for details.

mailto:
     The mailto URI scheme is specified in RFC 2368.  The scheme was
     originally used to designate the Internet mailing address of an
     individual or service.  It has (in RFC 2368) been extended to allow
     setting of other mail header fields and the message body.

     `URI' objects belonging to the mailto scheme support the common
     methods and the generic query methods.  In addition they support the
     following mailto specific methods: $uri->to, $uri->headers.

news:
     The news, *nntp* and *snews* URI schemes are specified in
     <draft-gilman-news-url-01> and will hopefully be available as a RFC
     2396 based specification soon.

     `URI' objects belonging to the news scheme support the common,
     generic and server methods.  In addition they provide some methods to
     access the path: $uri->group and $uri->message.

*nntp*:
     See news scheme.

pop:
     The pop URI scheme is specified in RFC 2384. The scheme is used to
     reference a POP3 mailbox.

     `URI' objects belonging to the pop scheme support the common, generic
     and server methods.  In addition they provide two methods to access
     the userinfo components: $uri->user and $uri->auth

*rlogin*:
     An old speficication of the *rlogin* URI scheme is found in RFC 1738.
     `URI' objects belonging to the rlogin scheme support the common,
     generic and server methods.

*rsync*:
     Information about rsync is available from http://rsync.samba.org.
     `URI' objects belonging to the rsync scheme support the common,
     generic and server methods.  In addition they provide methods to
     access the userinfo sub-components: $uri->user and $uri->password.

*snews*:
     See news scheme.  It's syntax is the same as news, but the default
     port is different.

*telnet*:
     An old speficication of the *telnet* URI scheme is found in RFC 1738.
     `URI' objects belonging to the telnet scheme support the common,
     generic and server methods.

CONFIGURATION VARIABLES
=======================

   The following configuration variables influence how the class and it's
methods behave:

$URI::ABS_ALLOW_RELATIVE_SCHEME
     Some older parsers used to allow the scheme name to be present in the
     relative URL if it was the same as the base URL scheme.  RFC 2396 says
     that this should be avoided, but you can enable this old behaviour by
     setting the $URI::ABS_ALLOW_RELATIVE_SCHEME variable to a TRUE value.
     The difference is demonstrated by the following examples:

          URI->new("http:foo")->abs("http://host/a/b")
              ==>  "http:foo"

          local $URI::ABS_ALLOW_RELATIVE_SCHEME = 1;
          URI->new("http:foo")->abs("http://host/a/b")
              ==>  "http:/host/a/foo"

$URI::ABS_REMOTE_LEADING_DOTS
     You can also have the abs() method ignore excess ".."  segments in
     the relative URI by setting $URI::ABS_REMOTE_LEADING_DOTS to a TRUE
     value.  The difference is demonstrated by the following examples:

          URI->new("../../../foo")->abs("http://host/a/b")
              ==> "http://host/../../foo"

          local $URI::URL::ABS_REMOTE_LEADING_DOTS = 1;
          URI->new("../../../foo")->abs("http://host/a/b")
              ==> "http://host/foo"

BUGS
====

   Using regexp variables like $1 directly as argument to the URI methods
do not work too well with current perl implementations.  I would argue
that this is actually a bug in perl.  The workaround is to quote them.
E.g.:

     /(...)/ || die;
     $u->query("$1");

SEE ALSO
========

   See URI/file, URI/WithBase,
URI/Escape, URI/Heuristic,

   RFC 2396: "Uniform Resource Identifiers (URI): Generic Syntax",
Berners-Lee, Fielding, Masinter, August 1998.

COPYRIGHT
=========

   Copyright 1995-2001 Gisle Aas.

   Copyright 1995 Martijn Koster.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHORS / ACKNOWLEDGMENTS
=========================

   This module is based on the URI::URL module, which in turn was
(distantly) based on the `wwwurl.pl' code in the libwww-perl for perl4
developed by Roy Fielding, as part of the Arcadia project at the
University of California, Irvine, with contributions from Brooks Cutter.

   URI::URL was developed by Gisle Aas, Tim Bunce, Roy Fielding and
Martijn Koster with input from other people on the libwww-perl mailing
list.

   `URI' and related subclasses was developed by Gisle Aas.

Expand URL using heuristics
***************************

NAME
====

   uf_urlstr - Expand URL using heuristics

SYNOPSIS
========

     use URI2::Heuristic qw(uf_urlstr);
     $url = uf_urlstr("perl");             # http://www.perl.com
     $url = uf_urlstr("www.sol.no/sol");   # http://www.sol.no/sol
     $url = uf_urlstr("aas");              # http://www.aas.no
     $url = uf_urlstr("ftp.funet.fi");     # ftp://ftp.funet.fi
     $url = uf_urlstr("/etc/passwd");      # file:/etc/passwd

DESCRIPTION
===========

   This module provide functions that expand strings into real absolute
URLs using some builtin heuristics.  Strings that already represent
absolute URLs (i.e. start with a `scheme:' part) are never modified and
are returned unchanged.  The main use of these functions are to allow
abbreviated URLs similar to what many web browsers allow for URLs typed in
by the user.

   The following functions are provided:

uf_urlstr($str)
     The uf_urlstr() function will try to make the string passed as
     argument into a proper absolute URL string.  The "uf_" prefix stands
     for "User Friendly".

uf_url($str)
     This functions work the same way as uf_urlstr() but it will return a
     `URI2::URL' object.

ENVIRONMENT
===========

   If the hostname portion of a URL does not contain any dots, then
certain qualified guesses will be made.  These guesses are governed be the
following two environment variables.

COUNTRY
     This is the two letter country code (ISO 3166) for your location.  If
     the domain name of your host ends with two letters, then it is taken
     to be the default country. See also Locale/Country.

URL_GUESS_PATTERN
     Contain a space separated list of URL patterns to try.  The string
     "ACME" is for some reason used as a placeholder for the host name in
     the URL provided.  Example:

          URL_GUESS_PATTERN="www.ACME.no www.ACME.se www.ACME.com"
          export URL_GUESS_PATTERN

     Specifying URL_GUESS_PATTERN disables any guessing rules based on
     country.  An empty URL_GUESS_PATTERN disables any guessing that
     involves host name lookups.

COPYRIGHT
=========

   Copyright 1997-1998, Gisle Aas

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

associate attributes with the URI name space
********************************************

NAME
====

   URI::Attr - associate attributes with the URI name space

SYNOPSIS
========

     use URI::Attr;
     $attr = URI::Attr->new;
     $attr->attr_update(SERVER => "http://www.perl.com")->{visit} = "yes";
     if ($attr->attr_plain($url, "visit")) {
         #...
     }

DESCRIPTION
===========

   Instances of the *URI::Attr* class is able to associate attributes with
"places" in the URI name space.  The main idea is to be able to look up
all attributes that are relevant to a specific absolute URI efficiently
and to be able to override attributes at different hierarchal levels of
the URI namespace.

   The levels of the URI namespace is given the following names:

     GLOBAL  - affect all URIs
     SCHEME  - affect all URIs of the given scheme
     DOMAIN  - affect all URIs within the given domain (domains nest)
     HOST    - a given host
     SERVER  - a specific server (port) on the host
     DIR     - a directory component (nestable)
     PATH    - the final path component

   GLOBAL and SCHEME are the only levels available for all URIs.  The other
levels only make sense for URIs that follow the generic URL pattern (like
http: and ftp: schemes).  Other level names can be used for specific
schemes.

   Lets take a look at an example.  Consider the following URL:

     http://www.perl.com/cgi-bin/cpan_mod?module=LWP

   This URL can be broken up into the following hierarchal levels:

     SCHEME  http
     DOMAIN  .com
     DOMAIN  .perl
     HOST    www
     SERVER  80        (implicit port)
     DIR     cgi-bin
     PATH    cpan-mod

METHODS
=======

   The following methods are provided by this class:

$db = URI::Attr->new
     The constructor takes now arguments.  It returns a newly allocated
     *URI::Attr* object.

$db->attr($uri, [$attr_name])
     Look up all attributes that are relevant to the given $uri.  In scalar
     context only the most specific attribute is returned.  In list context
     all attributes are returned, with the most specific first.  Each
     attribute is represented by a reference to a 2 element array.  The
     first element is the name of the level.  The second element is the
     attribute(s).

     If the optional $attr_name is given, only the attribute with the given
     name is considered.  If no $attr_name is given, then the attributes
     are returned as a hash reference.

$db->attr_plain($uri, [$attr_name])
     Same as attr() but only return the attribute(s), not the associated
     level names.

$db->attr_update($level, $uri)
     Returns a hash reference associated with $uri at the given $level.  If
     the given $level name does not make sense for the given $uri return
     <undef>.  If the $level is nestable, then the most specific instance
     related to the $uri is used.

     The hash returned can then be updated in order to assign attributes to
     the given place in the URI name space.

$db->as_string
     Dump the content of the *URI::Attr* object.  Mainly useful for
     debugging.

BUGS
====

   There ought to be a way to associate attributes with domains/hosts
without regard to scheme (and for several schemes and several
domain/hosts).  Think, think,...

   Perhaps there should be defined relationships between schemes, so that
for instace everything that is valid for http is also valid for *https*,
but not the other way around.  Same goes for *nntp* and news which should
be treated as the same thing and their relation to *snews*.

   A similar concept is present in w3c-libwww under the name *URL Tree*.
The scheme is simply ignored here and the root of the tree is the hostname
part of the URL.

   A totally different approach would be associate attributes with regular
expressions that are matched against URLs.  Perhaps this would have been a
better way?

SEE ALSO
========

   See URI,

COPYRIGHT
=========

   Copyright 1998, Gisle Aas

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl module class encapsulating an entry in a typical bookmark file.
********************************************************************

NAME
====

   URI::Bookmark - Perl module class encapsulating an entry in a typical
bookmark file.

SYNOPSIS
========

   See URI/Bookmarks.

DESCRIPTION
===========

   URI::Bookmark is a subclass of Tree::DAG_Node, so that each entry in
the bookmark collection is a node in a directed acyclic graph.

   All methods from Tree::DAG_Node are available.

   Each instance has a type, which can be:

     `root'       --  the root of the bookmark tree (this is also a folder)
     `folder'     --  a folder containing more entries
     `bookmark'   --  a bookmark (duh)
     `rule'       --  a horizontal rule separating entries

METHODS
-------

   * *set_attribs*
          $bookmark->set_attribs(name => 'Slashdot',
                                 type => bookmark,
                                 HREF => 'http://slashdot.org');

     This method should be self-explanatory.  The allowed attributes are:
     `name', `type', `HREF', `ADD_DATE', `LAST_MODIFIED', `LAST_VISIT',
     `ALIASOF', `ALIASID', `description'.  Attempts to set any others will
     be ignored and generate a warning.

   * *dump_attribs*
          $bookmark->dump_attribs();

     Dumps all attribute (key, value) pairs for this node, one per line.
     This is only really for debugging.

   * type
          my $type = $bookmark->type();

          $bookmark->type($new_type);

     If a parameter is specified, sets the bookmark to the type given by
     it.  Generates a warning if the type given isn't valid.

     Returns the current type of the bookmark.

AUTHOR
======

   Adam Spiers <adam@spiers.net>

SEE ALSO
========

   See URI/Bookmarks, `URI::Bookmarks::*' in this node,
`URI::Bookmark::*' in this node, `perl(1)' in this node.

Perl module containing routines for individual Netscape bookmarks
*****************************************************************

NAME
====

   URI::Bookmarks::Netscape - Perl module containing routines for
individual Netscape bookmarks

SYNOPSIS
========

   See URI/Bookmarks.

DESCRIPTION
===========

   URI::Bookmark::Netscape contains some helper routines specifically for
URI::Bookmark objects which were originally from Netscape bookmark files.

AUTHOR
======

   Adam Spiers <adam@spiers.net>

SEE ALSO
========

   See URI/Bookmarks, `URI::Bookmarks::*' in this node,
see URI/Bookmark, `perl(1)' in this node.

Perl module class encapsulating bookmark files
**********************************************

NAME
====

   URI::Bookmarks - Perl module class encapsulating bookmark files

SYNOPSIS
========

     use URI::Bookmarks;

     # URI::Bookmarks automagically detects that we're dealing with a
     # collection of Netscape bookmarks

     my $bookmarks =
       new URI::Bookmarks(file => "$ENV{HOME}/.netscape/bookmarks.html");

     my $bookmarks = new URI::Bookmarks(handle => $fh);

     my $bookmarks = new URI::Bookmarks(array => \@lines);

     # Manipulate $bookmarks using nice tree methods from Tree::DAG_Node,
     # e.g. delete all bookmarks under $folder:
     ($bookmarks->name_to_nodes($folder))[0]->unlink_from_mother();

     # Then output the new file.
     print $bookmarks->export('Netscape array');

DESCRIPTION
===========

   URI::Bookmarks provides a class for manipulating hierarchical
collections of bookmarks.  Each entry in the collection is an object of
type URI::Bookmark, which is in turn a subclass of Tree::DAG_Node, and
hence all standard tree manipulation methods are available (see the
documentation for Tree::DAG_Node).

   * *build_name_lookup*
          $bookmarks->build_name_lookup();

     This method builds an internal hash which maps node names to arrays of
     nodes which have the corresponding key as their name.

     It only needs to be called if you want to rebuild the hash after
     modifying the bookmark collection in some way; if the hash is needed
     and has not been built, it will be built automatically.

   * *tree_root*
          my $tree_root_node = $bookmarks->tree_root();

          $bookmarks->tree_root($new_root);

     Returns the current root node of the tree of bookmarks.  If the
     optional parameter is provided, the root node is changed to it.

   * *name_to_nodes*
          my @nodes = $bookmarks->name_to_nodes('Cinemas');

     Returns an array of all nodes matching the given name.

   * title
          my $title = $bookmarks->title();

          $bookmarks->title($new_title);

     Returns the current title of the collection of bookmarks.  If the
     optional parameter is provided, the title is changed to it.

   * origin
          my $origin = $bookmarks->origin();
          my $origin_type = $origin{type};

     Returns a hash containing information about the origin of the
     collection of bookmarks.

   * export
          my @lines = $bookmarks->export('Netscape array');

     The interface to the export routines.  The examples above show the
     currently available export types.

   * *all_URLs*
          $bookmarks->all_URLs();

     This method simply returns an array of all the URLs in the collection
     of bookmarks.

BUGS
====

   The file key of new() might not be safe.

AUTHOR
======

   Adam Spiers <adam@spiers.net>

SEE ALSO
========

   `URI::Bookmarks::*' in this node, see URI/Bookmark,
`URI::Bookmark::*' in this node, `perl(1)' in this node.

Perl module containing routines for Netscape bookmark files
***********************************************************

NAME
====

   URI::Bookmarks::Netscape - Perl module containing routines for Netscape
bookmark files

SYNOPSIS
========

     See L<URI::Bookmarks>.

DESCRIPTION
===========

   URI::Bookmarks::Netscape contains some helper routines specifically for
URI::Bookmarks objects which were originally Netscape bookmark files.

AUTHOR
======

   Adam Spiers <adam@spiers.net>

SEE ALSO
========

   See URI/Bookmarks, `URI::Bookmarks::*' in this node,
see URI/Bookmark, `URI::Bookmark::*' in this node,
`perl(1)' in this node.

Escape and unescape unsafe characters
*************************************

NAME
====

   URI::Escape - Escape and unescape unsafe characters

SYNOPSIS
========

     use URI::Escape;
     $safe = uri_escape("10% is enough\n");
     $verysafe = uri_escape("foo", "\0-\377");
     $str  = uri_unescape($safe);

DESCRIPTION
===========

   This module provides functions to escape and unescape URI strings as
defined by RFC 2396.  URIs consist of a restricted set of characters,
denoted as `uric' in RFC 2396.  The restricted set of characters consists
of digits, letters, and a few graphic symbols chosen from those common to
most of the character encodings and input facilities available to Internet
users:

     "A" .. "Z", "a" .. "z", "0" .. "9",
     ";", "/", "?", ":", "@", "&", "=", "+", "$", ",",   # reserved
     "-", "_", ".", "!", "~", "*", "'", "(", ")"

   In addition any byte (octet) can be represented in a URI by an escape
sequence; a triplet consisting of the character "%" followed by two
hexadecimal digits.  Bytes can also be represented directly by a character
using the US-ASCII character for that octet (iff the character is part of
`uric').

   Some of the `uric' characters are reserved for use as delimiters or as
part of certain URI components.  These must be escaped if they are to be
treated as ordinary data.  Read RFC 2396 for further details.

   The functions provided (and exported by default) from this module are:

uri_escape($string, [$unsafe])
     This function replaces all unsafe characters in the $string with their
     escape sequences and returns the result.

     The uri_escape() function takes an optional second argument that
     overrides the set of characters that are to be escaped.  The set is
     specified as a string that can be used in a regular expression
     character class (between [ ]).  E.g.:

          "\x00-\x1f\x7f-\xff"          # all control and hi-bit characters
          "a-z"                         # all lower case characters
          "^A-Za-z"                     # everything not a letter

     The default set of characters to be escaped is all those which are
     not part of the `uric' character class shown above.

uri_unescape($string,...)
     Returns a string with all %XX sequences replaced with the actual byte
     (octet).

     This does the same as:

          $string =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;

     but does not modify the string in-place as this RE would.  Using the
     uri_unescape() function instead of the RE might make the code look
     cleaner and is a few characters less to type.

     In a simple benchmark test I made I got something like 40% slowdown by
     calling the function (instead of the inline RE above) if a few chars
     where unescaped and something like 700% slowdown if none where.  If
     you are going to unescape a lot of times it might be a good idea to
     inline the RE.

     If the uri_unescape() function is passed multiple strings, then each
     one is unescaped returned.

   The module can also export the `%escapes' hash which contains the
mapping from all 256 bytes to the corresponding escape code.  Lookup in
this hash is faster than evaluating `sprintf("%%%02X", ord($byte))' each
time.

SEE ALSO
========

   See URI,

COPYRIGHT
=========

   Copyright 1995-2000 Gisle Aas.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Find URIs in arbitrary text
***************************

NAME
====

     URI::Find - Find URIs in arbitrary text

SYNOPSIS
========

     use URI::Find;

     $how_many_found = find_uris($text, \&callback);

DESCRIPTION
===========

   This module does one thing: Finds URIs and URLs in plain text.  It
finds them quickly and it finds them all (or what URI::URL considers a URI
to be.)  It employs a series of heuristics to:

Find schemeless URIs (ie. www.foo.com)
Avoid picking up trailing characters from the text
Avoid picking up URL-like things such as perl module names.
Functions
---------

   URI::Find exports one function, find_uris().  It takes two arguments,
the first is a text string to search, the second is a function reference.

   The function is a callback which is called on each URI found.  It is
passed two arguments, the first is a URI::URL object representing the URI
found.  The second is the original text of the URI found.  The return
value of the callback will replace the original URI in the text.

EXAMPLES
========

   Simply print the original URI text found and the normalized
representation.

     find_uris($text,
               sub {
                   my($uri, $orig_uri) = @_;
                   print "The text '$orig_uri' represents '$uri'\n";
                   return $orig_uri;
               });

   Check each URI in document to see if it exists.

     use LWP::Simple;
     find_uris($text,
               sub {
                   my($uri, $orig_uri) = @_;
                   if( head $uri ) {
                       print "$orig_uri is okay\n";
                   }
                   else {
                       print "$orig_uri cannot be found\n";
                   }
                   return $orig_uri;
               });

   Wrap each URI found in an HTML anchor.

     find_uris($text,
               sub {
                   my($uri, $orig_uri) = @_;
                   return qq|<a href="$uri">$orig_uri</a>|;
               });

CAVEATS, BUGS, ETC...
=====================

   RFC 2396 Appendix E suggests using the form '<http://www.foo.com>' or
'<URL:http://www.foo.com>' when putting URLs in plain text.  URI::Find
accomidates this suggestion and considers the entire thing (brackets and
all) to be part of the URL found.  This means that when find_uris() sees
'<URL:http://www.foo.com>' it will hand that entire string to your
callback, not just the URL.

   NOTE:  The prototype on find_uris() is already getting annoying to me.
I might remove it in a future version.

SEE ALSO
========

     L<URI::URL>, L<URI>, RFC 2396 (especially Appendix E)

AUTHOR
======

   Michael G Schwern <schwern@pobox.com> with insight from Uri Gutman,
Greg Bacon and Jeff Pinyan.

Expand URI using heuristics
***************************

NAME
====

   uf_uristr - Expand URI using heuristics

SYNOPSIS
========

     use URI::Heuristic qw(uf_uristr);
     $u = uf_uristr("perl");             # http://www.perl.com
     $u = uf_uristr("www.sol.no/sol");   # http://www.sol.no/sol
     $u = uf_uristr("aas");              # http://www.aas.no
     $u = uf_uristr("ftp.funet.fi");     # ftp://ftp.funet.fi
     $u = uf_uristr("/etc/passwd");      # file:/etc/passwd

DESCRIPTION
===========

   This module provides functions that expand strings into real absolute
URIs using some builtin heuristics.  Strings that already represent
absolute URIs (i.e. start with a `scheme:' part) are never modified and
are returned unchanged.  The main use of these functions are to allow
abbreviated URIs similar to what many web browsers allow for URIs typed in
by the user.

   The following functions are provided:

uf_uristr($str)
     The uf_uristr() function will try to make the string passed as
     argument into a proper absolute URI string.  The "uf_" prefix stands
     for "User Friendly".  Under MacOS, it assumes that any string with a
     common URL scheme (http, ftp, etc.) is a URL rather than a local
     path.  So don't name your volumes after common URL schemes and expect
     uf_uristr() to construct valid file: URL's on those volumes for you,
     because it won't.

uf_uri($str)
     This functions work the same way as uf_uristr() but it will return a
     `URI' object.

ENVIRONMENT
===========

   If the hostname portion of a URI does not contain any dots, then
certain qualified guesses will be made.  These guesses are governed be the
following two environment variables.

COUNTRY
     This is the two letter country code (ISO 3166) for your location.  If
     the domain name of your host ends with two letters, then it is taken
     to be the default country. See also Locale/Country.

URL_GUESS_PATTERN
     Contain a space separated list of URL patterns to try.  The string
     "ACME" is for some reason used as a placeholder for the host name in
     the URL provided.  Example:

          URL_GUESS_PATTERN="www.ACME.no www.ACME.se www.ACME.com"
          export URL_GUESS_PATTERN

     Specifying URL_GUESS_PATTERN disables any guessing rules based on
     country.  An empty URL_GUESS_PATTERN disables any guessing that
     involves host name lookups.

COPYRIGHT
=========

   Copyright 1997-1998, Gisle Aas

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Extract information from the URLs of Search-Engines
***************************************************

NAME
====

   URI::Sequin - Extract information from the URLs of Search-Engines

SYNOPSIS
========

     use URI::Sequin qw/se_extract key_extract log_extract %log_types/;

     $url = &log_extract($line_from_log_file, 'NCSA');

     $log_types{'MyLogType'} = '^(.+?) -> .+$';
     $url = &log_extract($line_from_log_file, 'MyLogType');

     $keyword_string = &key_extract($url);

     ($search_engine_name, $search_engine_url) = @{&se_extract($url)};

DESCRIPTION
===========

   This module provides three tools to aid people trying to analyse
Search-Engine URLs. It’s meant mainly for those who want to analyse
referrer logs and pick out key information about site visitors, such as
which Search-Engine and keywords they used to find the site.

   The functions and globals provided (and exported by default) from this
module are:

log_extract($log_line, 'Type')
     This will pick out the referring URL from a line of a logfile. The
     'type' can be one of the built in types or can be a user-created one.
     For more information, see %log_types below. This subroutine accepts a
     scalar, and returns a scalar.

key_extract($url)
     This will try and determine the keywords used in $url. It accepts a
     scalar and returns a scalar. Should nothing be found, it returns an
     undefined value.

se_extract($url)
     This will try and determine the name of the Search-Engine used and
     its URL.  It accepts a scalar, and returns an array containing
     firstly the Search- Engine’s name and secondly the Search-Engine’s
     URL. Should the URL appear not to be from a Search Query, it returns
     a reference to an empty array.

%log_types
     There are five built-in logfile types already in this hash. They are:

        * IIS1 - Microsoft IIS 3.0 and 2.0

        * IIS2 - Microsoft IIS4.0 (W3SVC format)

        * NCSA - For APACHE, NETSCAPE and any other NCSA format logs

        * ORW - O'Reilly WebSite format

        * General - A generalised one that will work with most logfiles

     It’s easy to add another one. Simply add a key to the hash, with a
     value that is a regex. Parenthesise the part that is the referring
     URL, as the script uses $1 to obtain the URL. (see the example in the
     Synopsis section).

AUTHOR
======

   Peter Sergeant <pete_sergeant@hotmail.com>

COPYRIGHT
=========

   Copyright 2001 Peter Sergeant.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Uniform Resource Locators
*************************

NAME
====

   URI::URL - Uniform Resource Locators

SYNOPSIS
========

     $u1 = URI::URL->new($str, $base);
     $u2 = $u1->abs;

DESCRIPTION
===========

   This module is provided for backwards compatibility with modules that
depend on the interface provided by the URI::URL class that used to be
distributed with the libwww-perl library.

   The following differences compared to the `URI' class interface exist:

   * The URI::URL module exports the url() function as an alternate
     constructor interface.

   * The constructor takes an optional $base argument.  See
     URI/WithBase.

   * The URI::URL->newlocal class method is the same as URI::file->new_abs

   * URI::URL::strict(1)

   * $url->print_on method

   * $url->crack method

   * $url->full_path; same as ($uri->abs_path || "/")

   * $url->netloc; same as $uri->authority

   * $url->epath, $url->equery; same as $uri->path, $uri->query

   * $url->path and $url->query pass unescaped strings.

   * $url->path_components; same as $uri->path_segments (if you don't
     consider path segment parameters).

   * $url->params and $url->eparams methods.

   * $url->base method.  See URI/WithBase.

   * $url->abs and $url->rel have an optional $base argument.  See
     URI/WithBase.

   * $url->frag; same as $uri->fragment

   * $url->keywords; same as $uri->query_keywords;

   * $url->localpath with friends map to $uri->file

   * $url->address and $url->encoded822addr; same as $uri->to for mailto
     URI.

   * $url->groupart method for news URI.

   * $url->article; same as $uri->message

SEE ALSO
========

   See URI, URI/WithBase,

COPYRIGHT
=========

   Copyright 1998-2000 Gisle Aas.

URI which remember their base
*****************************

NAME
====

   URI::WithBase - URI which remember their base

SYNOPSIS
========

     $u1 = URI::WithBase->new($str, $base);
     $u2 = $u1->abs;

     $base = $u1->base;
     $u1->base( $new_base )

DESCRIPTION
===========

   This module provide the `URI::WithBase' class.  Objects of this class
are like `URI' objects, but can keep their base too.

   The methods provided in addition to or modified from those of `URI' are:

$uri = URI::WithBase->new($str, [$base])
     The constructor takes a an optional base URI as the second argument.

$uri->base( [$new_base] )
     This method can be used to get or set the value of the base attribute.

$uri->abs( [$base_uri] )
     The $base_uri argument is now made optional as the object carries it's
     base with it.

$uri->rel( [$base_uri] )
     The $base_uri argument is now made optional as the object carries it's
     base with it.

SEE ALSO
========

   See URI,

COPYRIGHT
=========

   Copyright 1998-2000 Gisle Aas.

URI that contain immediate data
*******************************

NAME
====

   URI::data - URI that contain immediate data

SYNOPSIS
========

     use URI;

     $u = URI->new("data:");
     $u->media_type("image/gif");
     $u->data(scalar(`cat camel.gif`));
     print "$u\n";
     open(XV, "|xv -") and print XV $u->data;

DESCRIPTION
===========

   The `URI::data' class supports `URI' objects belonging to the data URI
scheme.  The data URI scheme is specified in RFC 2397.  It allows
inclusion of small data items as "immediate" data, as if it had been
included externally.  Examples:

     data:,Perl%20is%20good

     data:image/gif;base64,R0lGODdhIAAgAIAAAAAAAPj8+CwAAAAAI
       AAgAAAClYyPqcu9AJyCjtIKc5w5xP14xgeO2tlY3nWcajmZZdeJcG
       Kxrmimms1KMTa1Wg8UROx4MNUq1HrycMjHT9b6xKxaFLM6VRKzI+p
       KS9XtXpcbdun6uWVxJXA8pNPkdkkxhxc21LZHFOgD2KMoQXa2KMWI
       JtnE2KizVUkYJVZZ1nczBxXlFopZBtoJ2diXGdNUymmJdFMAADs=

   `URI' objects belonging to the data scheme support the common methods
(described in URI) and the following two scheme specific
methods:

$uri->media_type( [$new_media_type] )
     This method can be used to get or set the media type specified in the
     URI.  If no media type is specified, then the default
     `"text/plain;charset=US-ASCII"' is returned.

$uri->data( [$new_data] )
     This method can be used to get or set the data contained in the URI.
     The data is passed unescaped (in binary form).  The decision about
     whether to base64 encode the data in the URI is taken automatically
     based on what encoding produces the shortest URI string.

SEE ALSO
========

   See URI,

COPYRIGHT
=========

   Copyright 1995-1998 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

URI that map to local file names
********************************

NAME
====

   URI::file - URI that map to local file names

SYNOPSIS
========

     use URI::file;

     $u1 = URI->new("file:/foo/bar");
     $u2 = URI->new("foo/bar", "file");

     $u3 = URI::file->new($path);
     $u4 = URI::file->new("c:\\windows\\", "win32");

     $u1->file;
     $u1->file("mac");

DESCRIPTION
===========

   The `URI::file' class supports `URI' objects belonging to the file URI
scheme.  This scheme allows us to map the conventional file names found on
various computer systems to the URI name space.  An old specification of
the file URI scheme is found in RFC 1738.  Some older background
information is also in RFC 1630. There are no newer specifications as far
as I know.

   If you want simply to construct file URI objects from URI strings, use
the normal `URI' constructor.  If you want to construct file URI objects
from the actual file names used by various systems, then use one of the
following `URI::file' constructors:

$u = URI::file->new( $filename, [$os] )
     Maps a file name to the file: URI name space, creates an URI object
     and returns it.  The $filename is interpreted as one belonging to the
     indicated operating system ($os), which defaults to the value of the
     $^O variable.  The $filename can be either absolute or relative, and
     the corresponding type of URI object for $os is returned.

$u = URI::file->new_abs( $filename, [$os] )
     Same as URI::file->new, but will make sure that the URI returned
     represents an absolute file name.  If the $filename argument is
     relative, then the name is resolved relative to the current directory,
     i.e. this constructor is really the same as:

          URI::file->new($filename)->abs(URI::file->cwd);

$u = URI::file->cwd
     Returns a file URI that represents the current working directory.
     See Cwd.

   The following methods are supported for file URI (in addition to the
common and generic methods described in URI):

$u->file( [$os] )
     This method return a file name.  It maps from the URI name space to
     the file name space of the indicated operating system.

     It might return undef if the name can not be represented in the
     indicated file system.

$u->dir( [$os] )
     Some systems use a different form for names of directories than for
     plain files.  Use this method if you know you want to use the name for
     a directory.

   The `URI::file' module can be used to map generic file names to names
suitable for the current system.  As such, it can work as a nice
replacement for the File::Spec module.  For instance the following code
will translate the Unix style file name `Foo/Bar.pm' to a name suitable
for the local system.

     $file = URI::file->new("Foo/Bar.pm", "unix")->file;
     die "Can't map filename Foo/Bar.pm for $^O" unless defined $file;
     open(FILE, $file) || die "Can't open '$file': $!";
     # do something with FILE

MAPPING NOTES
=============

   Most computer systems today have hierarchically organized file systems.
Mapping the names used in these systems to the generic URI syntax allows
us to work with relative file URIs that behave as they should when
resolved using the generic algorithm for URIs (specified in RFC 2396).
Mapping a file name to the generic URI syntax involves mapping the path
separator character to "/" and encoding of any reserved characters that
appear in the path segments of the file names.  If path segments
consisting of the strings "." or ".." have a different meaning than what
is specified for generic URIs, then these must be encoded as well.

   If the file system has device, volume or drive specifications as the
root of the name space, then it makes sense to map them to the authority
field of the generic URI syntax.  This makes sure that relative URI can
not be resolved "above" them , i.e. generally how relative file names work
in those systems.

   Another common use of the authority field is to encode the host that
this file name is valid on.  The host name "localhost" is special and
generally have the same meaning as an missing or empty authority field.
This use will be in conflict with using it as a device specification, but
can often be resolved for device specifications having characters not
legal in plain host names.

   File name to URI mapping in normally not one-to-one.  There are usually
many URI that map to the same file name.  For instance an authority of
"localhost" maps the same as a URI with a missing or empty authority.

   Example 1: The Mac use ":" as path separator, but not in the same way
as generic URI. ":foo" is a relative name.  "foo:bar" is an absolute name.
Also path segments can contain the "/" character as well as be literal
"." or "..".  It means that we will map like this:

     Mac                   URI
     ----------            -------------------
     :foo:bar     <==>     foo/bar
     :            <==>     ./
     ::foo:bar    <==>     ../foo/bar
     :::          <==>     ../../
     foo:bar      <==>     file:/foo/bar
     foo:bar:     <==>     file:/foo/bar/
     ..           <==>     %2E%2E
     <undef>      <==      /
     foo/         <==      file:/foo%2F
     ./foo.txt    <==      file:/.%2Ffoo.txt

     Note that if you want a relative URL, you *must* begin the path with a :.  Any
     path that begins with [^:] will be treated as absolute.

   Example 2: The Unix file system is easy to map as it use the same path
separator as URIs, have a single root, and segments of "." and ".."  have
the same meaning.  URIs that have the character "\0" or "/" as part of any
path segment can not be turned into valid Unix file names.

     Unix                  URI
     ----------            ------------------
     foo/bar      <==>     foo/bar
     /foo/bar     <==>     file:/foo/bar
     /foo/bar     <==      file://localhost/foo/bar
     file:         ==>     ./file:
     <undef>      <==      file:/fo%00/bar
     /            <==>     file:/

SEE ALSO
========

   See URI, File/Spec, Perlport (perl.info),

COPYRIGHT
=========

   Copyright 1995-1998 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

LDAP Uniform Resource Locators
******************************

NAME
====

   URI::ldap - LDAP Uniform Resource Locators

SYNOPSIS
========

     use URI;

     $uri = URI->new("ldap:$uri_string");
     $dn     = $uri->dn;
     $filter = $uri->filter;
     @attr   = $uri->attributes;
     $scope  = $uri->scope;
     %extn   = $uri->extensions;

     $uri = URI->new("ldap:");  # start empty
     $uri->host("ldap.itd.umich.edu");
     $uri->dn("o=University of Michigan,c=US");
     $uri->attributes(qw(postalAddress));
     $uri->scope('sub');
     $uri->filter('(cn=Babs Jensen)');
     print $uri->as_string,"\n";

DESCRIPTION
===========

   URI::ldap provides an interface to parse an LDAP URI in its constituent
parts and also build a URI as described in RFC 2255.

METHODS
=======

   URI::ldap support all the generic and server methods defined by
URI, plus the following.

   Each of the following methods can be used to set or get the value in
the URI. The values are passed in unescaped form.  None of these will
return undefined values, but elements without a default can be empty.  If
arguments are given then a new value will be set for the given part of the
URI.

$uri->dn( [$new_dn] )
     Set or get the *Distinguised Name* part of the URI.  The DN
     identifies the base object of the LDAP search.

$uri->attributes( [@new_attrs] )
     Set or get the list of attribute names which will be returned by the
     search.

$uri->scope( [$new_scope] )
     Set or get the scope that the search will use. The value can be one of
     `"base"', `"one"' or `"sub"'. If none is given in the URI then the
     return value will default to `"base"'.

$uri->_scope( [$new_scope] )
     Same as scope(), but does not default to anything.

$uri->filter( [$new_filter] )
     Set or get the filter that the search will use. If none is given in
     the URI then the return value will default to `"(objectClass=*)"'.

$uri->_filter( [$new_filter] )
     Same as filter(), but does not default to anything.

$uri->extensions( [$etype => $evalue,...] )
     Set or get the extensions used for the search. The list passed should
     be in the form etype1 => evalue1, etype2 => evalue2,... This is also
     the form of list that will be returned.

SEE ALSO
========

   `RFC-2255|http:' in this node

AUTHOR
======

   Graham Barr <`gbarr@pobox.com'>

   Slightly modified by Gisle Aas to fit into the URI distribution.

COPYRIGHT
=========

   Copyright (c) 1998 Graham Barr. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Look up Unicode character names
*******************************

NAME
====

   Unicode::CharName - Look up Unicode character names

SYNOPSIS
========

     use Unicode::CharName qw(uname ublock);
     print uname(ord('%')), "\n";
     print ublock(0x0300), "\n";

DESCRIPTION
===========

   This module provide a two functions named uname() and ublock().  The
uname() function will return the Unicode character name for the given code
(a number between 0 and 0x10FFFF).  Unicode character names are written in
upper-case ASCII letters, and are strings like:

     LATIN CAPITAL LETTER A
     LATIN SMALL LETTER A WITH RING ABOVE
     CJK UNIFIED IDEOGRAPH 7C80
     HANGUL SYLLABLE PWILH

   The ublock() will return the name of the Unicode character block that
the given character belongs to.

SEE ALSO
========

   See Unicode/String,

COPYRIGHT
=========

   Copyright 1997 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Name table extracted from the Unicode 2.0 Character Database. Copyright
(c) 1991-1996 Unicode, Inc. All Rights reserved.

maps charsets from and to utf16 unicode
***************************************

NAME
====

   Unicode::Map V0.108 - maps charsets from and to utf16 unicode

SYNOPSIS
========

   use Unicode::Map();

   *$Map* = new Unicode::Map("ISO-8859-1");

   *$utf16* = *$Map* -> to_unicode ("Hello world!");   => $utf16 ==
"\0H\0e\0l\0l\0o\0 \0w\0o\0r\0l\0d\0!"

   *$locale* = *$Map* -> from_unicode (*$utf16*);   => $locale == "Hello
world!"

   A more detailed description below.

   2do: short note about perl's Unicode perspectives.

DESCRIPTION
===========

   This module converts strings from and to 2-byte Unicode UCS2 format.
All mappings happen via 2 byte UTF16 encodings, not via 1 byte UTF8
encoding. To transform these use Unicode::String.

   For historical reasons this module coexists with Unicode::Map8.  Please
use Unicode::Map8 unless you need to care for two byte character sets,
e.g. chinese GB2312. Anyway, if you stick to the basic functionality (see
documentation) you can use both modules equivalently.

   Practically this module will disappear from earth sooner or later as
Unicode mapping support needs somehow to get into perl's core. If you like
to work on this field please don't hesitate contacting Gisle Aas!

   This module can't deal directly with utf8. Use Unicode::String to
convert utf8 to utf16 and vice versa.

   Character mapping is according to the data of binary mapfiles in
Unicode::Map hierarchy. Binary mapfiles can also be created with this
module, enabling you to install own specific character sets. Refer to
mkmapfile or file REGISTRY in the Unicode::Map hierarchy.

CONVERSION METHODS
==================

   Probably these are the only methods you will need from this module.
Their usage is compatible with Unicode::Map8.

new
     *$Map* = new Unicode::Map("GB2312-80")

     Returns a new Map object for GB2312-80 encoding.

from_unicode
     $dest = *$Map* -> from_unicode ($src)

     Creates a string in locale charset representation from utf16 encoded
     string $src.

to_unicode
     $dest   = *$Map* -> to_unicode ($src)

     Creates a string in utf16 representation from $src.

to8
     Alias for from_unicode. For compatibility with Unicode::Map8

to16
     Alias for to_unicode. For compatibility with Unicode::Map8

WARNINGS
========

   You can demand Unicode::Map to issue warnings at deprecated or
incompatible usage with the constants WARN_DEFAULT, WARN_DEPRECATION or
WARN_COMPATIBILITY.  The latter both can be ored together.

No special warnings:
     $Unicode::Map::WARNINGS = Unicode::Map::WARN_DEFAULT

Warnings for deprecated usage:
     $Unicode::Map::WARNINGS = Unicode::Map::WARN_DEPRECATION

Warnings for incompatible usage:
     $Unicode::Map::WARNINGS = Unicode::Map::WARN_COMPATIBILITY

MAINTAINANCE METHODS
====================

   Note: These methods are solely for the maintainance of Unicode::Map.
Using any of these methods will lead to programs incompatible with
Unicode::Map8.

alias
     *@list* = *$Map* -> alias (*$csid*)

     Returns a list of alias names of character set *$csid*.

mapping
     $path = *$Map* -> mapping (*$csid*)

     Returns the absolute path of binary character mapping for character
     set *$csid* according to REGISTRY file of Unicode::Map.

id
     *$real_id*||"" = *$Map* -> id (*$test_id*)

     Returns a valid character set identifier *$real_id*, if *$test_id* is
     a valid character set name or alias name according to REGISTRY file of
     Unicode::Map.

ids
     *@ids* = *$Map* -> ids()

     Returns a list of all character set names defined in REGISTRY file.

read_text_mapping
     1||0 = *$Map* -> read_text_mapping (*$csid*, $path, $style)

     Read a text mapping of style $style named *$csid* from filename $path.
     The mapping then can be saved to a file with method:
     write_binary_mapping.  <$style> can be:

          style          description

          "unicode"    A text mapping as of ftp://ftp.unicode.org/MAPPINGS/
          ""           Same as "unicode"
          "reverse"    Similar to unicode, but both columns are switched
          "keld"       A text mapping as of ftp://dkuug.dk/i18n/charmaps/

src
     $path = *$Map* -> src (*$csid*)

     Returns the path of textual character mapping for character set
     *$csid* according to REGISTRY file of Unicode::Map.

style
     $path = *$Map* -> style (*$csid*)

     Returns the style of textual character mapping for character set
     *$csid* according to REGISTRY file of Unicode::Map.

write_binary_mapping
     1||0 = *$Map* -> write_binary_mapping (*$csid*, $path)

     Stores a mapping that has been loaded via method read_text_mapping in
     file $path.

DEPRECATED METHODS
==================

   Some functionality is no longer promoted.

noise
     Deprecated! Don't use any longer.

reverse_unicode
     Deprecated! Use Unicode::String::byteswap instead.

BINARY MAPPINGS
===============

   Structure of binary Mapfiles

   Unicode character mapping tables have sequences of sequential key and
sequential value codes. This property is used to crunch the maps easily.
n (0<n<256) sequential characters are represented as a bytecount n and the
first character code key_start. For these subsequences the according value
sequences are crunched together, also. The value 0 is used to start an
extended information block (that is just partially implemented, though).

   One could think of two ways to make a binary mapfile. First method would
be first to write a list of all key codes, and then to write a list of all
value codes. Second method, used here, appends to all partial key code
lists the according crunched value code lists. This makes value codes a
little bit closer to key codes.

   *Note: the file format is still in a very liquid state. Neither rely on
that it will stay as this, nor that the description is bugless, nor that
all features are implemented.*

   STRUCTURE:

<main>:
          offset  structure     value

          0x00    word          0x27b8   (magic)
          0x02    @(<extended> || <submapping>)

     The mapfile ends with extended mode <end> in main stream.

<submapping>:
          0x00    byte != 0     charsize1 (bits)
          0x01    byte          n1 number of chars for one entry
          0x02    byte          charsize2 (bits)
          0x03    byte          n2 number of chars for one entry
          0x04    @(<extended> || <key_seq> || <key_val_seq)

          bs1=int((charsize1+7)/8), bs2=int((charsize2+7)/8)

     One submapping ends when <mapend> entry occurs.

<key_val_seq>:
          0x00    size=0|1|2|4  n, number of sequential characters
          size    bs1           key1
          +bs1    bs2           value1
          +bs2    bs1           key2
          +bs1    bs2           value2
          ...

     key_val_seq ends, if either file ends (n = infinite mode) or n pairs
     are read.

<key_seq>:
          0x00    byte          n, number of sequential characters
          0x01    bs1           key_start, first character of sequence
          1+bs1   @(<extended> || <val_seq>)

     A key sequence starts with a byte count telling how long the sequence
     is. It is followed by the key start code. After this comes a list of
     value sequences. The list of value sequences ends, if sum(m) equals n.

<val_seq>:
          0x00    byte          m, number of sequential characters
          0x01    bs2           val_start, first character of sequence

<extended>:
          0x00    byte          0
          0x01    byte          ftype
          0x02    byte          fsize, size of following structure
          0x03    fsize bytes   something

     For future extensions or private use one can insert here 1..255 byte
     long streams. ftype can have values 30..255, values 0..29 are
     reserved. Modi are not fully defined now and could change. They will
     be explained later.

TO BE DONE
==========

-
     Something clever, when a character has no translation.

-
     Direct charset -> charset mapping.

-
     Better performance.

-
     Support for mappings according to RFC 1345.

SEE ALSO
========

-
     File `REGISTRY' and binary mappings in directory `Unicode/Map' of your
     perl library path

-
     recode(1), map(1), mkmapfile(1), Unicode::Map(3), Unicode::Map8(3),
     Unicode::String(3), Unicode::CharName(3), mirrorMappings(1)

-
     RFC 1345

-
     Mappings at Unicode consortium ftp://ftp.unicode.org/MAPPINGS/

-
     Registrated Internet character sets ftp://dkuug.dk/i18n/charmaps/

-
     2do: more references

AUTHOR
======

   Martin Schwartz <`martin@nacho.de'>

Mapping table between 8-bit chars and Unicode
*********************************************

NAME
====

   Unicode::Map8 - Mapping table between 8-bit chars and Unicode

SYNOPSIS
========

     require Unicode::Map8;
     my $no_map = Unicode::Map8->new("ISO646-NO") || die;
     my $l1_map = Unicode::Map8->new("latin1")    || die;

     my $ustr = $no_map->to16("V}re norske tegn b|r {res\n");
     my $lstr = $l1_map->to8($ustr);
     print $lstr;

     print $no_map->tou("V}re norske tegn b|r {res\n")->utf8

DESCRIPTION
===========

   The Unicode::Map8 class implement efficient mapping tables between
8-bit character sets and 16 bit character sets like Unicode.  The tables
are efficient both in terms of space allocated and translation speed.  The
16-bit strings is assumed to use network byte order.

   The following methods are available:

$m = Unicode::Map8->new( [$charset] )
     The object constructor creates new instances of the Unicode::Map8
     class.  I takes an optional argument that specify then name of a 8-bit
     character set to initialize mappings from.  The argument can also be a
     the name of a mapping file.  If the charset/file can not be located,
     then the constructor returns undef.

     If you omit the argument, then an empty mapping table is constructed.
     You must then add mapping pairs to it using the addpair() method
     described below.

$m->addpair( $u8, $u16 );
     Adds a new mapping pair to the mapping object.  It takes two
     arguments.  The first is the code value in the 8-bit character set and
     the second is the corresponding code value in the 16-bit character
     set.  The same codes can be used multiple times (but using the same
     pair has no effect).  The first definition for a code is the one that
     is used.

     Consider the following example:

          $m->addpair(0x20, 0x0020);
          $m->addpair(0x20, 0x00A0);
          $m->addpair(0xA0, 0x00A0);

     It means that the character 0x20 and 0xA0 in the 8-bit charset maps to
     themselves in the 16-bit set, but in the 16-bit character set 0x0A0
     maps to 0x20.

$m->default_to8( $u8 )
     Set the code of the default character to use when mapping from 16-bit
     to 8-bit strings.  If there is no mapping pair defined for a character
     then this default is substituted by to8() and recode8().

$m->default_to16( $u16 )
     Set the code of the default character to use when mapping from 8-bit
     to 16-bit strings. If there is no mapping pair defined for a character
     then this default is used by to16(), tou() and recode8().

$m->nostrict;
     All undefined mappings are replaced with the identity mapping.
     Undefined character are normally just removed (or replaced with the
     default if defined) when converting between character sets.

$m->to8( $ustr );
     Converts a 16-bit character string to the corresponding string in the
     8-bit character set.

$m->to16( $str );
     Converts a 8-bit character string to the corresponding string in the
     16-bit character set.

$m->tou( $str );
     Same an to16() but return a Unicode::String object instead of a plain
     UCS2 string.

$m->recode8($m2, $str);
     Map the string $str from one 8-bit character set ($m) to another one
     ($m2).  Since we assume we know the mappings towards the common 16-bit
     encoding we can use this to convert between any of the 8-bit character
     sets.

$m->to_char16( $u8 )
     Maps a single 8-bit character code to an 16-bit code.  If the 8-bit
     character is unmapped then the constant NOCHAR is returned.  The
     default is not used and the callback method is not invoked.

$m->to_char8( $u16 )
     Maps a single 16-bit character code to an 8-bit code. If the 16-bit
     character is unmapped then the constant NOCHAR is returned.  The
     default is not used and the callback method is not invoked.

   The following callback methods are available.  You can override these
methods by creating a subclass of Unicode::Map8.

$m->unmapped_to8
     When mapping to 8-bit character string and there is no mapping defined
     (and no default either), then this method is called as the last
     resort.  It is called with a single integer argument which is the code
     of the unmapped 16-bit character.  It is expected to return a string
     that will be incorporated in the 8-bit string.  The default version of
     this method always returns an empty string.

     Example:

          package MyMapper;
          @ISA=qw(Unicode::Map8);

          sub unmapped_to8
          {
             my($self, $code) = @_;
             require Unicode::CharName;
             "<" . Unicode::CharName::uname($code) . ">";
          }

$m->unmapped_to16
     Likewise when mapping to 16-bit character string and no mapping is
     defined then this method is called.  It should return a 16-bit string
     with the bytes in network byte order.  The default version of this
     method always returns an empty string.

FILES
=====

   The Unicode::Map8 constructor can parse two different file formats; a
binary format and a textual format.

   The binary format is simple.  It consist of a sequence of 16-bit
integer pairs in network byte order.  The first pair should contain the
magic value 0xFFFE, 0x0001.  Of each pair, the first value is the code of
an 8-bit character and the second is the code of the 16-bit character.  If
follows from this that the first value should be less than 256.

   The textual format consist of lines that is either a comment (first
non-blank character is '#'), a completely blank line or a line with two
hexadecimal numbers.  The hexadecimal numbers must be preceded by "0x" as
in C and Perl.  This is the same format used by the Unicode mapping files
available from <URL:ftp://ftp.unicode.org/Public>.

   The mapping table files are installed in the `Unicode/Map8/maps'
directory somewhere in the Perl @INC path.  The variable
$Unicode::Map8::MAPS_DIR is the complete path name to this directory.
Binary mapping files are stored within this directory with the suffix
*.bin*.  Textual mapping files are stored with the suffix *.txt*.

   The scripts *map8_bin2txt* and *map8_txt2bin* can translate between
these mapping file formats.

   A special file called aliases within $MAPS_DIR specify all the alias
names that can be used to denote the various character sets.  The first
name of each line is the real file name and the rest is alias names
separated by space.

   The ``umap --list'' command be used to list the character sets
supported.

BUGS
====

   Does not handle Unicode surrogate pairs as a single character.

SEE ALSO
========

   `umap(1)' in this node, see Unicode/String,

COPYRIGHT
=========

   Copyright 1998 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Conversions to and from arbitrary character sets and UTF8
*********************************************************

NAME
====

   Unicode::MapUTF8 - Conversions to and from arbitrary character sets and
UTF8

SYNOPSIS
========

     use Unicode::MapUTF8 qw(to_utf8 from_utf8 utf8_supported_charset);

     # Convert a string in 'ISO-8859-1' to 'UTF8'
     my $output = to_utf8({ -string => 'An example', -charset => 'ISO-8859-1' });

     # Convert a string in 'UTF8' encoding to encoding 'ISO-8859-1'
     my $other  = from_utf8({ -string => 'Other text', -charset => 'ISO-8859-1' });

     # List available character set encodings
     my @character_sets = utf8_supported_charset;

     # Add a character set alias
     utf8_charset_alias({ 'ms-japanese' => 'sjis' });

     # Convert between two arbitrary (but largely compatible) charset encodings
     # (SJIS to EUC-JP)
     my $utf8_string   = to_utf8({ -string =>$sjis_string, -charset => 'sjis'});
     my $euc_jp_string = from_utf8({ -string => $utf8_string, -charset => 'euc-jp' })

     # Verify that a specific character set is supported
     if (utf8_supported_charset('ISO-8859-1') {
         # Yes
     }

DESCRIPTION
===========

   Provides an adapter layer between core routines for converting to and
from UTF8 and other encodings. In essence, a way to give multiple existing
Unicode modules a single common interface so you don't have to know the
underlaying implementations to do simple UTF8 to-from other character set
encoding conversions. As such, it wraps the Unicode::String, Unicode::Map8,
Unicode::Map and Jcode modules in a standardized and simple API.

   This also provides general character set conversion operation based on
UTF8 - it is possible to convert between any two compatible and supported
character sets via a simple two step chaining of conversions.

   As with most things Perlish - if you give it a few big chunks of text
to chew on instead of lots of small ones it will handle many more
characters per second.

   By design, it can be easily extended to encompass any new charset
encoding conversion modules that arrive on the scene.

CHANGES
=======

   1.08 2000.11.06 - Added 'utf8_charset_alias' function to
  allow for runtime setting of character                   set aliases.
Added several alternate                   names for 'sjis' (shiftjis,
shift-jis,                   shift_jis, s-jis, and s_jis).

     Corrected 'croak' messages for
     'from_utf8' functions to appropriate
     function name.

     Tightened up initialization encapsulation

     Corrected fatal problem in jcode from
     unicode internals. Problem and fix
     found by Brian Wisti <wbrian2@uswest.net>.

   1.07 2000.11.01 - Added 'croak' to use Carp declaration to
    fix error messages.  Problem and fix                   found by Brian
Wisti                   <wbrian2@uswest.net>.

   1.06 2000.10.30 - Fix to handle change in stringification
   of overloaded objects between Perl 5.005                   and 5.6.
Problem noticed by Brian Wisti                   <wbrian2@uswest.net>.

   1.05 2000.10.23 - Error in conversions from UTF8 to
multibyte encodings corrected

   1.04 2000.10.23 - Additional diagnostic messages added
for internal error conditions

   1.03 2000.10.22 - Bug fix for load time autodetction of
 Unicode::Map8 encodings

   1.02 2000.10.22 - Added load time autodetection of
Unicode::Map8 supported character set                   encodings.

     Fixed internal calling error for some
     character sets with 'from_utf8'. Thanks
     goes to Ilia Lobsanov
     <ilia@lobsanov.com> for reporting this
     problem.

   1.01 2000.10.02 - Fixed handling of empty strings and
added more identification for error                   messages.

   1.00 2000.09.29 - Pre-release version

FUNCTIONS
=========

utf8_charset_alias({ $alias => $charset });
     Used for runtime assignment of character set aliases.

     Called with no parameters, returns a hash of defined aliases and the
     character sets they map to.

     Example:

          my $aliases     = utf8_charset_alias;
          my @alias_names = keys %$aliases;

     If called with ONE parameter, returns the name of the 'real' charset
     if the alias is defined. Returns undef if it is not found in the
     aliases.

     Example:

          if (! utf8_charset_alias('VISCII')) {
              # No alias for this
          }

     If called with a list of 'alias' => 'charset' pairs, defines those
     aliases for use.

     Example:

          utf8_charset_alias({ 'japanese' => 'sjis', 'japan' => 'sjis' });

     Note: It will croak if a passed pair does not map to a character set
     defined in the predefined set of character encoding. It is NOT
     allowed to alias something to another alias.

     Multiple character set aliases can be set with a single call.

     To clear an alias, pass a character set mapping of undef.

     Example:

          utf8_charset_alias({ 'japanese' => undef });

     While an alias is set, the 'utf8_supported_charset' function will
     return the alias as if it were a predefined charset.

     Overriding a base defined character encoding with an alias will
     generate a warning message to STDERR.

utf8_supported_charset($charset_name);
     Returns true if the named charset is supported (including user
     defiend aliases).

     Returns false if it is not.

     Example:

          if (! utf8_supported_charset('VISCII')) {
              # No support yet
          }

     If called in a list context with no parameters, it will return a list
     of all supported character set names (including user defined aliases).

     Example:

          my @charsets = utf8_supported_charset;

to_utf8({ -string => $string, -charset => $source_charset });
     Returns the string converted to UTF8 from the specified source
     charset.

from_utf8({ -string => $string, -charset => $target_charset});
     Returns the string converted from UTF8 to the specified target
     charset.

VERSION
=======

   1.08 2000.11.06

COPYRIGHT
=========

   Copyright September, 2000 Benjamin Franz. All rights reserved.

   This software is free software.  You can redistribute it and/or modify
it under the same terms as Perl itself.

AUTHOR
======

   Benjamin Franz <snowhare@nihongo.org>

TODO
====

   Regression tests for Jcode, 2-byte encodings and encoding aliases

SEE ALSO
========

   Unicode::String Unicode::Map8 Unicode::Map Jcode

String of Unicode characters (UCS2/UTF16)
*****************************************

NAME
====

   Unicode::String - String of Unicode characters (UCS2/UTF16)

SYNOPSIS
========

     use Unicode::String qw(utf8 latin1 utf16);
     $u = utf8("The Unicode Standard is a fixed-width, uniform ");
     $u .= utf8("encoding scheme for written characters and text");

     # convert to various external formats
     print $u->ucs4;      # 4 byte characters
     print $u->utf16;     # 2 byte characters + surrogates
     print $u->utf8;      # 1-4 byte characters
     print $u->utf7;      # 7-bit clean format
     print $u->latin1;    # lossy
     print $u->hex;       # a hexadecimal string

     # all these can be used to set string value or as constructor
     $u->latin1("Å være eller å ikke være");
     $u = utf16("\0Å\0 \0v\0æ\0r\0e");

     # string operations
     $u2 = $u->copy;
     $u->append($u2);
     $u->repeat(2);
     $u->chop;

     $u->length;
     $u->index($other);
     $u->index($other, $pos);

     $u->substr($offset);
     $u->substr($offset, $length);
     $u->substr($offset, $length, $substitute);

     # overloading
     $u .= "more";
     $u = $u x 100;
     print "$u\n";

     # string <--> array of numbers
     @array = $u->unpack;
     $u->pack(@array);

     # misc
     $u->ord;
     $u = uchr($num);

DESCRIPTION
===========

   A *Unicode::String* object represents a sequence of Unicode characters.
The Unicode Standard is a fixed-width, uniform encoding scheme for
written characters and text.  This encoding treats alphabetic characters,
ideographic characters, and symbols identically, which means that they can
be used in any mixture and with equal facility.  Unicode is modeled on the
ASCII character set, but uses a 16-bit encoding to support full
multilingual text.

   Internally a *Unicode::String* object is a string of 2 byte values in
network byte order (big-endian).  The class provide various methods to
convert from and to various external formats, and all string manipulations
are made on strings in this the internal 16-bit format.

   The functions utf16(), utf8(), utf7(), ucs2(), ucs4(), latin1(), uchr()
can be imported from the *Unicode::String* module and will work as
constructors initializing strings of the corresponding encoding.  The
ucs2() and utf16() are really aliases for the same function.

   The *Unicode::String* objects overload various operators, so they will
normally work like plain 8-bit strings in Perl.  This includes conversions
to strings, numbers and booleans as well as assignment, concatenation and
repetition.

METHODS
=======

   The following methods are available:

Unicode::String->stringify_as( [$enc] )
     This class method specify which encoding will be used when
     *Unicode::String* objects are implicitly converted to and from plain
     strings.  It define which encoding to assume for the argument of the
     *Unicode::String* constructor new().  Without an encoding argument,
     stringify_as() returns the current encoding ctor function.  The
     encoding argument ($enc) is a string with one of the following values:
     "ucs4", "ucs2", "utf16", "utf8", "utf7", "latin1", "hex".  The default
     is "utf8".

$us = Unicode::String->new( [$initial_value] )
     This is the customary object constructor.  Without argument, it
     creates an empty *Unicode::String* object.  If an $initial_value
     argument is given, it is decoded according to the specified
     stringify_as() encoding and used to initialize the newly created
     object.

     Normally you create *Unicode::String* objects by importing some of
     the encoding methods below as functions into your namespace and
     calling them with an appropriate encoded argument.

$us->ucs4( [$newval] )
     The UCS-4 encoding use 32 bits per character.  The main benefit of
     this encoding is that you don't have to deal with surrogate pairs.
     Encoded as a Perl string we use 4-bytes in network byte order for each
     character.

     The ucs4() method always return the old value of $us and if given an
     argument decodes the UCS-4 string and set this as the new value of
     $us.  The characters in $newval must be in the range 0x0 .. 0x10FFFF.
     Characters outside this range is ignored.

$us->ucs2( [$newval] )

$us->utf16( [$newval] )
     The ucs2() and utf16() are really just different names for the same
     method.  The UCS-2 encoding use 16 bits per character.  The UTF-16
     encoding is identical to UCS-2, but includes the use of surrogate
     pairs.  Surrogates make it possible to encode characters in the range
     0x010000 .. 0x10FFFF with the use of two consecutive 16-bit chars.
     Encoded as a Perl string we use 2-bytes in network byte order for each
     character (or surrogate code).

     The ucs2() method always return the old value of $us and if given an
     argument set this as the new value of $us.

$us->utf8( [$newval] )
     The UTF-8 encoding use 8-bit for the encoding of characters in the
     range 0x0 .. 0x7F, 16-bit for the encoding of characters in the range
     0x80 .. 0x7FF, 24-bit for the encoding of characters in the range
     0x800 .. 0xFFFF and 32-bit for characters in the range 0x01000 ..
     0x10FFFF.  Americans like this encoding, because plain US-ASCII
     characters are still US-ASCII.  Another benefit is that the character
     '\0' only occurs as the encoding of 0x0, thus the normal
     NUL-terminated strings (popular in the C programming language) can
     still be used.

     The utf8() method always return the old value of $us encoded using
     UTF-8 and if given an argument decodes the UTF-8 string and set this
     as the new value of $us.

$us->utf7( [$newval] )
     The UTF-7 encoding only use plain US-ASCII characters for the
     encoding.  This makes it safe for transport through 8-bit stripping
     protocols.  Characters outside the US-ASCII range are base64-encoded
     and '+' is used as an escape character.  The UTF-7 encoding is
     described in RFC1642.

     The utf7() method always return the old value of $us encoded using
     UTF-7 and if given an argument decodes the UTF-7 string and set this
     as the new value of $us.

     If the (global) variable $Unicode::String::UTF7_OPTIONAL_DIRECT_CHARS
     is TRUE, then a wider range of characters are encoded as themselves.
     It is even TRUE by default.  The characters affected by this are:

          ! " # $ % & * ; < = > @ [ ] ^ _ ` { | }

$us->latin1( [$newval] )
     The first 256 codes of Unicode is identical to the ISO-8859-1 8-bit
     encoding, also known as Latin-1.  The latin1() method always return
     the old value of $us and if given an argument set this as the new
     value of $us.  Characters outside the 0x0 .. 0xFF range are ignored
     when returning a Latin-1 string.  If you want more control over the
     mapping from Unicode to Latin-1, use the Unicode::Map8 class.  This
     is also the way to deal with other 8-bit character sets.

$us->hex( [$newval] )
     This method() return a plain ASCII string where each Unicode character
     is represented by the "U+XXXX" string and separated by a single space
     character.  This format can also be used to set the value of $us (in
     which case the "U+" is optional).

$us->as_string;
     Converts a *Unicode::String* to a plain string according to the
     setting of stringify_as().  The default stringify_as() method is
     "utf8".

$us->as_num;
     Converts a *Unicode::String* to a number.  Currently only the digits
     in the range 0x30 .. 0x39 are recognized.  The plan is to eventually
     support all Unicode digit characters.

$us->as_bool;
     Converts a *Unicode::String* to a boolean value.  Only the empty
     string is FALSE.  A string consisting of only the character U+0030 is
     considered TRUE, even if Perl consider "0" to be FALSE.

$us->repeat( $count );
     Returns a new *Unicode::String* where the content of $us is repeated
     $count times.  This operation is also overloaded as:

          $us x $count

$us->concat( $other_string );
     Concatenates the string $us and the string $other_string.  If
     $other_string is not an *Unicode::String* object, then it is first
     passed to the Unicode::String->new constructor function.  This
     operation is also overloaded as:

          $us . $other_string

$us->append( $other_string );
     Appends the string $other_string to the value of $us.  If
     $other_string is not an *Unicode::String* object, then it is first
     passed to the Unicode::String->new constructor function.  This
     operation is also overloaded as:

          $us .= $other_string

$us->copy;
     Returns a copy of the current *Unicode::String* object.  This
     operation is overloaded as the assignment operator.

$us->length;
     Returns the length of the *Unicode::String*.  Surrogate pairs are
     still counted as 2.

$us->byteswap;
     This method will swap the bytes in the internal representation of the
     *Unicode::String* object.

     Unicode reserve the character U+FEFF character as a byte order mark.
     This works because the swapped character, U+FFFE, is reserved to not
     be valid.  For strings that have the byte order mark as the first
     character, we can guaranty to get the byte order right with the
     following code:

          $ustr->byteswap if $ustr->ord == 0xFFFE;

$us->unpack;
     Returns a list of integers each representing an UTF-16 character code.

$us->pack( @uchr );
     Sets the value of $us as a sequence of UTF-16 characters with the
     characters codes given as parameter.

$us->ord;
     Returns the character code of the first character in $us.  The ord()
     method deals with surrogate pairs, which gives us a result-range of
     0x0 .. 0x10FFFF.  If the $us string is empty, undef is returned.

$us->chr( $code );
     Sets the value of $us to be a string containing the character assigned
     code $code.  The argument $code must be an integer in the range 0x0
     .. 0x10FFFF.  If the code is greater than 0xFFFF then a surrogate pair
     created.

$us->name
     In scalar context returns the official Unicode name of the first
     character in $us.  In array context returns the name of all characters
     in $us.  Also see Unicode/CharName.

$us->substr( $offset, [$length, [$subst]] )
     Returns a sub-string of $us.  Works similar to the builtin substr
     function, but because we can't make LVALUE subs yet, you have to pass
     the string you want to assign to the sub-string as the 3rd parameter.

$us->index( $other, [$pos] );
     Locates the position of $other within $us, possibly starting the
     search at position $pos.

$us->chop;
     Chops off the last character of $us and returns it (as a
     *Unicode::String* object).

FUNCTIONS
=========

   The following utility functions are provided.  They will be exported on
request.

byteswap2($str, ...)
     This function will swap 2 and 2 bytes in the strings passed as
     arguments.  This can be used to fix up UTF-16 or UCS-2 strings from
     litle-endian systems.  If this function is called in void context,
     then it will modify its arguments in-place.  Otherwise, then swapped
     strings are returned.

byteswap4($str, ...)
     The byteswap4 function works similar to byteswap2, but will reverse
     the order of 4 and 4 bytes.  Can be used to fix litle-endian UCS-4
     strings.

SEE ALSO
========

   See Unicode/CharName, Unicode/Map8,
http://www.unicode.org/

COPYRIGHT
=========

   Copyright 1997-2000 Gisle Aas.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl interface to /etc/aliases format files
*******************************************

NAME
====

   Unix::AliasFile - Perl interface to /etc/aliases format files

SYNOPSIS
========

     use Unix::AliasFile;

     $al = new Unix::AliasFile "/etc/aliases";
     $al->alias("bozos", @members);
     $al->delete("deadlist");
     $al->remove_user("coolmail", "bgates", "badguy");
     $al->add_user("coolmail", "joecool", "goodguy");
     $al->remove_user("*", "deadguy");
     $al->commit();
     undef $al;

DESCRIPTION
===========

   The Unix::AliasFile module provides an abstract interface to Unix alias
files.  It automatically handles file locking, getting colons and commas
in the right places, and all the other niggling details.

   Unlike some of the other Unix::*File modules, this module will preserve
the order of your alias file, with a few exceptions.  Comments and aliases
will appear in the file in the same order that they started in, unless you
have comment lines interspersed between the beginning of an alias and
continuation lines for that same alias.  In this case, those comments will
appear after the alias that contains them.

METHODS
=======

add_user( ALIAS, @USERS )
-------------------------

   This method will add the list of users to an existing alias.  Users
that are already members of the alias are silently ignored.  The special
alias name * will add the users to every alias.  Returns 1 on success or 0
on failure.

alias( ALIAS [,@USERS] )
------------------------

   This method can add, modify, or return information about an alias.
Supplied with a single alias parameter, it will return a list consisting
of the members of that alias, or undef if no such alias exists.  If you
supply more parameters, the named alias will be created or modified if it
already exists.  The member list is also returned to you in this case.

aliases( )
----------

   This method returns a list of all existing aliases.  The list will be
sorted in alphabetical order.  In scalar context, this method returns the
total number of aliases.

comment( ALIAS, COMMENT )
-------------------------

   This method inserts a comment line before the specified alias.  You must
supply your own comment marker (#) but a newline will be automatically
appended to the comment unless it already has one.  Returns 1 on success
and 0 on failure.

commit( [BACKUPEXT] )
---------------------

   See the Unix::ConfigFile documentation for a description of this method.

delempty( )
-----------

   This method will delete all existing aliases that have no members.  It
returns a count of how many aliases were deleted.

delete( ALIAS )
---------------

   This method will delete the named alias.  It has no effect if the
supplied alias does not exist.

new( FILENAME [,OPTIONS] )
--------------------------

   See the Unix::ConfigFile documentation for a description of this method.

remove_user( ALIAS, @USERS )
----------------------------

   This method will remove the list of users from an existing alias.
Users that are not members of the alias are silently ignored.  The special
alias name * will remove the users from every alias.  Returns 1 on success
or 0 on failure.

rename_user( OLDNAME, NEWNAME )
-------------------------------

   This method will change one username to another in every alias.
Returns the number of aliases affected.

uncomment( COMMENT )
--------------------

   Remove the comment from the file that matches the supplied text.  The
match must be exact.  Returns 1 on success and 0 on failure.

BUGS
====

   While the Unix::AliasFile module will work with Perl versions prior to
5.005, it may exhibit a minor bug under those versions.  The bug will
cause program aliases with embedded comma characters to be broken apart.
This will not happen under 5.005 and up, due to the use of the
Text::ParseWords module, which changed significantly with the 5.005
release.

AUTHOR
======

   Steve Snodgrass, ssnodgra@fore.com

SEE ALSO
========

   Unix::AutomountFile, Unix::ConfigFile, Unix::GroupFile, Unix::PasswdFile

Perl interface to automounter files
***********************************

NAME
====

   Unix::AutomountFile - Perl interface to automounter files

SYNOPSIS
========

     use Unix::AutomountFile;

     $am = new Unix::AutomountFile "/etc/auto_home";
     $am->automount("newuser", "fileserver:/export/home/&");
     $am->options("newuser", "-rw,nosuid");
     $am->delete("olduser");
     $am->commit();
     undef $am;

DESCRIPTION
===========

   The Unix::AutomountFile module provides an abstract interface to
automounter files.  It automatically handles file locking, getting colons
and commas in the right places, and all the other niggling details.
WARNING: This module is probably Solaris specific at this point.  I have
only looked at Solaris format automount files thus far.  Also, you cannot
edit /etc/auto_master with this module, since it is in a different format
than the other automount files.

METHODS
=======

add_server( MOUNT, @SERVERS )
-----------------------------

   This method will add additional servers to an existing automount point.
It returns 1 on success and 0 on failure.

automount( MOUNT [,@SERVERS] )
------------------------------

   This method can add, modify, or return information about a mount point.
Supplied with a single mount parameter, it will return a list of the server
entries for that mount point, or undef if no such mount exists.  If you
supply more than one parameter, the mount point will be created or
modified if it already exists.  The list is also returned to you in this
case.

automounts( )
-------------

   This method returns a list of all existing mount points, sorted
alphabetically.  In scalar context, this method returns the total number of
mount points.

commit( [BACKUPEXT] )
---------------------

   See the Unix::ConfigFile documentation for a description of this method.

delete( MOUNT )
---------------

   This method will delete the named mount point.  It has no effect if the
supplied mount point does not exist.

new( FILENAME [,OPTIONS] )
--------------------------

   See the Unix::ConfigFile documentation for a description of this method.

options( MOUNT [,OPTIONS] )
---------------------------

   Read or modify the mount options associated with a mount point.
Returns the options in either case.

rename( OLDNAME, NEWNAME )
--------------------------

   Renames a mount point.  If NEWNAME corresponds to an existing mount
point, that mount point is overwritten.  Returns 0 on failure and 1 on
success.

AUTHOR
======

   Steve Snodgrass, ssnodgra@fore.com

SEE ALSO
========

   Unix::AliasFile, Unix::ConfigFile, Unix::GroupFile, Unix::PasswdFile

Perl interface to various Unix configuration files
**************************************************

NAME
====

   Unix::ConfigFile - Perl interface to various Unix configuration files

SYNOPSIS
========

     use Unix::ConfigFile;

DESCRIPTION
===========

   The Unix::ConfigFile module provides a base class from which the other
Unix::*File modules are derived.  It provides some basic facilities like
file opening, locking, and closing.  You do not need to use this module
directly unless you are developing a derived module for an unsupported
configuration file.  However, some of the methods documented here are
intended for public use by users of Unix::ConfigFile submodules, so you
may find this documentation useful even if you are not developing your own
module.

   The ConfigFile object also provides a sequencing API for modules that
wish to preserve the order of the configuration file they read and write.
The sequencer maintains a list of arbitrary data that a submodule may
append, insert, and delete from.  Use of the sequencer is completely
optional.

   A module that subclasses from Unix::ConfigFile must, at a minimum,
provide two methods, called "read" and "write".  Both methods will receive
a filehandle as a parameter (besides the regular object parameter).  The
read method is called after the file is opened.  It is expected to read in
the configuration file and initialize the subclass-specific data
structures associated with the object.  The write method is called when an
object is committed and is expected to write out the new configuration to
the supplied filehandle.

USER METHODS
============

commit( [%OPTIONS] )
--------------------

   This writes any changes you have made to the object back to disk.  If
you do not call commit, none of your changes will be reflected in the file
you are modifying.  Commit may not be called on files opened in read-only
mode.  There are some optional parameters that may be provided; these are
passed in the form of key => value pairs.  The "backup" option allows you
to specify a file extension that will be used to save a backup of the
original file.  The "writeopts" option passes module-specific options
through to the write method.  It will accept any scalar for its value;
typically this will be a list or hash reference.  Commit returns 1 on
success and 0 on failure.

encpass( PASSWORD )
-------------------

   This method encrypts the supplied plaintext password using a random
salt and returns the encrypted password.  Note that this method does not
actually make any use of the object that it is invoked on, and could be
called as a class method.

new( FILENAME [,%OPTIONS] )
---------------------------

   The new method constructs a new ConfigFile (or subclass) object using
the specified FILENAME.  There are several optional parameters that may be
specified.  Options must be passed as keyed pairs in the form of option =>
value.  Valid options are "locking", "lockfile", "mode", and "readopts".
The locking option determines what style of file locking is used;
available styles are "dotlock", "flock", and "none".  The default locking
style is "dotlock".  The "none" locking style causes no locking to be
done, and all lock and unlock requests will return success.  The lockfile
option can be used to specify the lock filename used with dotlocking.  The
default is "FILENAME.lock", where FILENAME is the name of the file being
opened.  The mode option allows the file open mode to be specified.  The
default mode is "r+" (read/write), but "r" and "w" are accepted as well.
Finally, the readopts option allows module-specific options to be passed
through to the read method.  It will accept any scalar for its value;
typically this will be a list or hash reference.

DEVELOPER METHODS
=================

joinwrap( LENGTH, HEAD, INDENT, DELIM, TAIL, @LIST )
----------------------------------------------------

   This is a utility function that may be called as an object or class
method.  As the name suggests, this method is basically a version of the
join function that incorporates line wrapping.  The specified list will be
joined together, with each list element separated by the specified
delimiter.  The first line of output will be prefixed with the HEAD
parameter.  If a line exceeds the length parameter, output is wrapped to
the next line and the INDENT parameter is used to prefix the line.  In
addition, the TAIL parameter will be added to the end of every line
generated except the final one.  There is one case where the resulting
string can exceed the specified line length - if a single list element,
plus HEAD or INDENT, exceeds that length.  One final feature is that if
the HEAD or INDENT parameters contain the text '%n', it will be replaced
with the current line number, beginning at 0.

sequence( )
-----------

   Returns the current sequence list associated with the object.  This is
a list of arbitrary data maintained by a ConfigFile submodule.  The
ConfigFile module does not care what is contained in the list.

seq_append( @DATA )
-------------------

   Appends that specified data to the end of the sequence list.

seq_insert( KEY, @DATA )
------------------------

   Inserts the data into the sequence list before the data that matches the
specified key.

seq_remove( KEY )
-----------------

   Removes the data from the sequence list that matches the specified key.

AUTHOR
======

   Steve Snodgrass, ssnodgra@fore.com

SEE ALSO
========

   Unix::AliasFile, Unix::AutomountFile, Unix::GroupFile, Unix::PasswdFile

Perl interface to /etc/group format files
*****************************************

NAME
====

   Unix::GroupFile - Perl interface to /etc/group format files

SYNOPSIS
========

     use Unix::GroupFile;

     $grp = new Unix::GroupFile "/etc/group";
     $grp->group("bozos", "*", $grp->maxgid + 1, @members);
     $grp->remove_user("coolgrp", "bgates", "badguy");
     $grp->add_user("coolgrp", "joecool", "goodguy");
     $grp->remove_user("*", "deadguy");
     $grp->passwd("bozos", $grp->encpass("newpass"));
     $grp->commit();
     undef $grp;

DESCRIPTION
===========

   The Unix::GroupFile module provides an abstract interface to /etc/group
format files.  It automatically handles file locking, getting colons and
commas in the right places, and all the other niggling details.

   This module also handles the annoying problem (at least on some
systems) of trying to create a group line longer than 512 characters.
Typically this is done by creating multiple lines of groups with the same
GID.  When a new GroupFile object is created, all members of groups with
the same GID are merged into a single group with a name corresponding to
the first name found in the file for that GID.  When the file is
committed, long groups are written out as multiple lines of no more than
512 characters, with numbers appended to the group name for the extra
lines.

METHODS
=======

add_user( GROUP, @USERS )
-------------------------

   This method will add the list of users to an existing group.  Users
that are already members of the group are silently ignored.  The special
group name * will add the users to every group.  Returns 1 on success or 0
on failure.

commit( [BACKUPEXT] )
---------------------

   See the Unix::ConfigFile documentation for a description of this method.

delete( GROUP )
---------------

   This method will delete the named group.  It has no effect if the
supplied group does not exist.

encpass( PASSWORD )
-------------------

   See the Unix::ConfigFile documentation for a description of this method.

gid( GROUP [,GID] )
-------------------

   Read or modify a group's GID.  Returns the GID in either case.  Note
that it is illegal to change a group's GID to a GID that is already in use
by another group.  In this case, the method returns undef.

group( GROUP [,PASSWD, GID, @USERS] )
-------------------------------------

   This method can add, modify, or return information about a group.
Supplied with a single group parameter, it will return a list consisting
of (PASSWORD, GID, @MEMBERS), or undef if no such group exists.  If you
supply at least three parameters, the named group will be created or
modified if it already exists.  The list is also returned to you in this
case.  Note that it is illegal to specify a GID that is already in use by
another group.  In this case, the method returns undef.

groups( [SORTBY] )
------------------

   This method returns a list of all existing groups.  By default the list
will be sorted in order of the GIDs of the groups.  You may also supply
"name" as a parameter to the method to get the list sorted by group name.
In scalar context, this method returns the total number of groups.

maxgid( )
---------

   This method returns the maximum GID in use by all groups.

members( GROUP [,@USERS] )
--------------------------

   Read or modify the list of members associated with a group.  If you
specify any users when you call the method, all existing members of the
group are removed and your list becomes the new set of members.  In scalar
context, this method returns the total number of members in the group.

new( FILENAME [,OPTIONS] )
--------------------------

   See the Unix::ConfigFile documentation for a description of this method.

passwd( GROUP [,PASSWD] )
-------------------------

   Read or modify a group's password.  Returns the encrypted password in
either case.  If you have a plaintext password, use the encpass method to
encrypt it before passing it to this method.

remove_user( GROUP, @USERS )
----------------------------

   This method will remove the list of users from an existing group.
Users that are not members of the group are silently ignored.  The special
group name * will remove the users from every group.  Returns 1 on success
or 0 on failure.

rename_user( OLDNAME, NEWNAME )
-------------------------------

   This method will change one username to another in every group.
Returns the number of groups affected.

AUTHOR
======

   Steve Snodgrass, ssnodgra@fore.com

SEE ALSO
========

   Unix::AliasFile, Unix::AutomountFile, Unix::ConfigFile, Unix::PasswdFile

Perl interface to /etc/passwd format files
******************************************

NAME
====

   Unix::PasswdFile - Perl interface to /etc/passwd format files

SYNOPSIS
========

     use Unix::PasswdFile;

     $pw = new Unix::PasswdFile "/etc/passwd";
     $pw->user("joeblow", $pw->encpass("secret"), $pw->maxuid + 1, 10,
     	    "Joe Blow", "/export/home/joeblow", "/bin/ksh");
     $pw->delete("deadguy");
     $pw->passwd("johndoe", $pw->encpass("newpass"));
     foreach $user ($pw->users) {
         print "Username: $user, Full Name: ", $pw->gecos($user), "\n";
     }
     $pw->commit();
     undef $pw;

DESCRIPTION
===========

   The Unix::PasswdFile module provides an abstract interface to
/etc/passwd format files.  It automatically handles file locking, getting
colons in the right places, and all the other niggling details.

METHODS
=======

commit( [BACKUPEXT] )
---------------------

   See the Unix::ConfigFile documentation for a description of this method.

delete( USERNAME )
------------------

   This method will delete the named user.  It has no effect if the
supplied user does not exist.

encpass( PASSWORD )
-------------------

   See the Unix::ConfigFile documentation for a description of this method.

gecos( USERNAME [,GECOS] )
--------------------------

   Read or modify a user's GECOS string (typically their full name).
Returns the GECOS string in either case.

gid( USERNAME [,GID] )
----------------------

   Read or modify a user's GID.  Returns the GID in either case.

home( USERNAME [,HOMEDIR] )
---------------------------

   Read or modify a user's home directory.  Returns the home directory in
either case.

maxuid( [IGNORE] )
------------------

   This method returns the maximum UID in use by all users.  If you pass
in the optional IGNORE parameter, it will ignore all UIDs greater or equal
to IGNORE when doing this calculation.  This is useful for excluding
accounts like nobody.

new( FILENAME [,OPTIONS] )
--------------------------

   See the Unix::ConfigFile documentation for a description of this method.

passwd( USERNAME [,PASSWD] )
----------------------------

   Read or modify a user's password.  Returns the encrypted password in
either case.  If you have a plaintext password, use the encpass method to
encrypt it before passing it to this method.

rename( OLDNAME, NEWNAME )
--------------------------

   This method changes the username for a user.  If NEWNAME corresponds to
an existing user, that user will be overwritten.  It returns 0 on failure
and 1 on success.

shell( USERNAME [,SHELL] )
--------------------------

   Read or modify a user's shell.  Returns the shell in either case.

uid( USERNAME [,UID] )
----------------------

   Read or modify a user's UID.  Returns the UID in either case.

user( USERNAME [,PASSWD, UID, GID, GECOS, HOMEDIR, SHELL] )
-----------------------------------------------------------

   This method can add, modify, or return information about a user.
Supplied with a single username parameter, it will return a six element
list consisting of (PASSWORD, UID, GID, GECOS, HOMEDIR, SHELL), or undef
if no such user exists.  If you supply all seven parameters, the named
user will be created or modified if it already exists.  The six element
list is also returned to you in this case.

users( [SORTBY] )
-----------------

   This method returns a list of all existing usernames.  By default the
list will be sorted in order of the UIDs of the users.  You may also
supply "name" as a parameter to the method to get the list sorted by
username.  In scalar context, this method returns the total number of
users.

AUTHOR
======

   Steve Snodgrass, ssnodgra@fore.com

SEE ALSO
========

   Unix::AliasFile, Unix::AutomountFile, Unix::ConfigFile, Unix::GroupFile

Interface to processor (CPU) information
****************************************

NAME
====

   Unix::Processors - Interface to processor (CPU) information

SYNOPSIS
========

     use Unix::Processors;

     my $procs = new Unix::Processors;
     print "There are ", $procs->max_online, " CPUs at ", $procs->max_clock, "\n";
     (my $FORMAT =   "%2s  %-8s     %4s    \n") =~ s/\s\s+/ /g;
     printf($FORMAT, "#", "STATE", "CLOCK",  "TYPE", );
     foreach my $proc (@{$procs->processors}) {
         printf ($FORMAT, $proc->id, $proc->state, $proc->clock, $proc->type);
     }

DESCRIPTION
===========

     This package provides accessors to per-processor (CPU) information.
     The object is obtained with the Unix::Processors::processors call.
     the operating system in a OS independent manner.

max_online   Return number of processors currently online.
max_clock   Return the maximum clock speed across all online processors.    =item processors   Return a array or processor references.  See the Unix::Processors::Info   manual page.  Not all OSes support this call.
SEE ALSO
========

   `Unix::Processors::Info', `Sys::Sysconf',

DISTRIBUTION
============

   The latest version is available from CPAN.

AUTHORS
=======

   Wilson Snyder <wsnyder@wsnyder.org>

Interface to processor (CPU) information
****************************************

NAME
====

   Unix::Processors::Info - Interface to processor (CPU) information

SYNOPSIS
========

     use Unix::Processors;

     ...
     $aproc = $proc->processors[0];
         print ($aproc->id, $aproc->state, $aproc->clock);
     }

DESCRIPTION
===========

     This package provides access to per-processor (CPU) information from
     the operating system in a OS independent manner.

id   Return the cpu number of this processor.
clock   Return the clock frequency in MHz.    =item state   Return the cpu state as "online", "offline", or "poweroff".
type   Return the cpu type.
SEE ALSO
========

   `Unix::Processors',

DISTRIBUTION
============

   The latest version is available from CPAN.

AUTHORS
=======

   Wilson Snyder <wsnyder@wsnyder.org>

Perl interface to the UNIX syslog(3) calls
******************************************

NAME
====

   Unix::Syslog - Perl interface to the UNIX syslog(3) calls

SYNOPSIS
========

     use Unix::Syslog qw(:macros);  # Syslog macros
     use Unix::Syslog qw(:subs);    # Syslog functions

     openlog $ident, $option, $facility;
     syslog $priority, $format, @formatargs;
     closelog;
     $oldmask = setlogmask $mask_priority;

DESCRIPTION
===========

   This module provides an interface to the system logger *syslogd*(8) via
Perl's XSUBs. The implementation attempts to resemble the native
libc-functions of your system, so that anyone being familiar with
`syslog.h' should be able to use this module right away.

   In contrary to Sys::Syslog(3), this modules does not open a network
connection to send the messages. This can help you to avoid opening
security holes in your computer (see `"FAQ"' in this node).

   The subs imported by the tag macros are simply wrappers around the most
important `#defines' in your system's C header file `syslog.h'. The macros
return integer values that are used to specify options, facilities and
priorities in a more or less portable way. They also provide general
information about your local syslog mechanism. Check syslog(3) and your
local `syslog.h' for information about the macros, options and facilities
available on your system.

   The following functions are provided:

openlog $ident, $option, $facility
     opens a connection to the system logger.  *$ident* is an identifier
     string that *syslogd*(8) prints into every message. It usually equals
     the process name. $option is an integer value that is the result of
     ORed options. *$facility* is an integer value that specifies the part
     of the system the message should be associated with (e.g. kernel
     message, mail subsystem).

syslog $priority, $format, @formatargs
     Generates a log message and passes it to the system logger. If
     `syslog()' is called without calling `openlog()' first, probably
     system dependent default values will be used as arguments for an
     implicit call to `openlog()'.

     *$priority* is an integer value that specifies the priority of the
     message. Alternatively *$priority* can be the ORed value of a
     priority and a facility. In that case a previously selected facility
     will be overridden.

     In the case that `syslog()' is called without calling `openlog()'
     first and priority does not specify both a priority and a facility, a
     default facility will be used. This behaviour is most likely system
     dependent and the user should not rely on any particular value in
     that case.

     *$format* is a format string in the style of printf(3). Additionally
     to the usual printf directives `%m' can be specified in the string.
     It will be replaced implicitly by the contents of the Perl variable
     $! ($ERRNO). *@formatargs* is a list of values that the format
     directives will be replaced with subsequently.

closelog
     closes the connection to the system logger.

setlogmask $mask_priority
     sets the priority mask and returns the old mask. Logging is enabled
     for the priorities indicated by the bits in the mask that are set and
     is disabled where the bits are not set. Macros are provided to specify
     valid and portable arguments to `setlogmask()'. Usually the default
     log mask allows all messages to be logged.

   NOTE: The behaviour of this module is system dependent. It is highly
recommended to consult your system manual for available macros and the
behaviour of the provided functions.

RETURN VALUES
=============

   The functions openlog(), syslog() and closelog() return the undefined
value. The function setlogmask returns the previous mask value.

EXAMPLES
========

   Open a channel to syslogd specifying an identifier (usually the process
name) some options and the facility:   `openlog "test.pl", LOG_PID |
LOG_PERROR, LOG_LOCAL7;'

   Generate log message of specified priority using a printf-type formatted
string:   `syslog LOG_INFO, "This is message number %d", 42;'

   Set log priority mask to block all messages but those of priority
`LOG_DEBUG':   `$oldmask = setlogmask(LOG_MASK(LOG_DEBUG))'

   Set log priority mask to block all messages with a higher priority than
`LOG_ERR':   `$oldmask = setlogmask(LOG_UPTO(LOG_ERR))'

   Close channel to syslogd:   `closelog;'

FAQ
===

  1. What is the benefit of using this module instead of Sys::Syslog?

     Sys::Syslog always opens a network connection to the syslog service.
     At least on Linux systems this may lead to some trouble, because

        * Linux syslogd (from package sysklogd) does not listen to the
          network by default. Most people working on stand-alone machines
          (including me) didn't see any reason why to enable this option.
          Others didn't enable it for security reasons.

          OS-independent, some sysadmins may run a firewall on their
          network that blocks connections to port 514/udp.

        * By default Linux syslogd doesn't forward messages which have
          already already received from the network to other log hosts.
          There are reasons not to enable this option unless it is really
          necessary. Looping messages resulting from a misconfiguration may
          break down your (log-)system.

     Peter Stamfest <peter.stamfest@eunet.at> pointed out some other
     advantages of Unix::Syslog, I didn't came across my self.

        * LOG_PERROR works.

        * works with perl -Tw without warnings and problems due to tainted
          data as it is the case for Sys::Syslog in some special
          applications. [Especially when running a script as root]

  2. Well, is there any reason to use Sys::Syslog any longer?

     Yes! In contrary to Unix::Syslog, Sys::Syslog works even if you don't
     have a syslog daemon running on your system as long as you are
     connected to a log host via a network and have access to the
     `syslog.h' header file of your log host to generate the initial files
     for Sys::Syslog (see Sys::Syslog(3) for details). Unix::Syslog only
     logs to your local syslog daemon which in turn may be configured to
     distribute the message over the network.

  3. Are calls to the functions provided by Unix::Syslog compatible to
     those of Sys::Syslog?

     Currently not. Sys::Syslog requires strings to specify many of the
     arguments to the functions, while Unix::Syslog uses numeric constants
     accessed via macros as defined in `syslog.h'. Although the strings
     used by Sys::Syslog are also defined in `syslog.h', it seems that most
     people got used to the numeric arguments. I will implement the string
     based calls if there are enough people (*$min_people* > 10**40)
     complaining about the lack of compatibility.

SEE ALSO
========

   syslog(3), Sys::Syslog(3), syslogd(8), perl(1)

AUTHOR
======

   Marcus Harnisch <marcus.harnisch@gmx.net>

Module for laundering tainted data.
***********************************

NAME
====

   Untaint - Module for laundering tainted data.

SYNOPSIS
========

     use Untaint;

     my $pattern = qr(^k\w+);

     my $foo = $ARGV[0];

     # Untaint a scalar
     if (is_tainted($foo)) {
            		print "\$foo is tainted. Attempting to launder\n";
            	$foo = untaint($pattern, $foo);
     }else{
            		print "\$foo is not tainted!!\n";
     }

     # Untaint an array
     my @foo = @ARGV;

     push @foo, "not tainted";

     if (is_tainted(@foo)) {
             	print "\@foo is tainted. Attempting to launder\n";
             my @new = untaint($pattern, @foo);
     }else{
             	print "\@foo is not tainted!!\n";
     }

     # Another way for an list
     ($a, $b, $c) = untaint(qr(^\d+$), ($a, $b , $c));

     # Untaint a hash
     my $test = {'name' => $ARGV[0],
                 'age' => $ARGV[1],
                 'gender' => $ARGV[2],
     	    'time' => 'late'
             	   };

     my $patterns = {'name' => qr(^k\w+),
            		        'age' => qr(^\d+),
                     	'gender' => qr(^\w$)
                            };

     $UNTAINT_ALLOW_HASH++;

     my %new = untaint_hash($patterns, %{$test});

DESCRIPTION
===========

   This module is used to launder data which has been tainted by using the
-T switch to be in taint mode. This can be used for CGI scripts as well as
command line scripts.

   The module will untaint scalars, arrays, and hashes. When laundering an
array, only array elements which are tainted will be laundered.

FUNCTIONS
---------

is_tainted(<scalar or array>);
     You can use this to check the taintedness of data if you wish, but it
     is also used internally by Untaint.pm to do this when untaint() is
     called. This method returns 1 if tainted, 0 if not. This is actually
     a pass-through to Taint.pm's is_tainted method, since that already
     accomplishes this task.

newvar = untaint(<pattern>, <scalar or array/list>);
     This method will launder the data (if it can) and return the newly
     laundered variable. It should be passed either a scalar, or an array
     reference.  This will return either an array, or a scalar depending
     on which you want returned.  The pattern should be a regular
     expression pattern to match the data against.

     If this method can not launder a variable, it will croak().

untaint_hash(<hashref of patterns>, hash)
     When laundering a hash, a hash of patterns can be passed. This allows
     you to define a different pattern for each element of the hash. If
     there is no pattern for an element in the hash, the value itself will
     be used as the pattern (therefore untainting itself).  This behavior
     isn't really safe, so you need to specify that you want to do this by
     setting a special variable to a true value like this:

          $UNTAINT_ALLOW_HASH++;

     That scalar is exported so you need to specifically say it is ok to
     do this.

     If this is not done, any key/value pair which does not have a pattern
     will not be laundered and the returned hash will only contain the
     key/value pairs which had a corresponding pattern.

     It appears that whenever there is one value in a hash that is
     tainted, ALL values in that hash are tainted. This is a bug in Perl
     versions which are pre-5.6. This is somewhat of a quagmire since
     key/value pairs you actually set are now tainted, and need
     laundering. That's all well and good, but now there is the chance
     that when you pass the hash ref, you pass something without a pattern
     unknowingly, and data you don't want untainted is then laundered.
     Another current bug is that all hash keys are not considered tainted.
     So, be wary of using hash keys which come from unknown sources in Bad
     ways. But, if you are trying to use a hash key which you do not know
     where it's name is from in a dangerous manner, there may be other
     problems!

$UNTAINT_ALLOW_HASH
     This variable must be set to a true value of you wish to allow hash
     values to be untainted based on their own value as a pattern. In
     other words, the pattern that will be matched to untaint it, will be
     itself, hence always being untainted.  USE THIS WITH CAUTION.

INSTALLATION
============

   perl Makefile.PL make make test make install make clean

   Look at the test scripts to see how this can be implemented.

BUGS
====

   None known at this time. PATCHES WELCOME.

COPYRIGHT
=========

   Copyright (c) 2000 Kevin Meltzer. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

AUTHOR
======

   Kevin Meltzer, <`perlguy@perlguy.com'>

CREDITS
=======

   Tom Phoenix, <`rootbeer@teleport.com'>

SEE ALSO
========

   See Perlsec (perl.info), Perlrun (perl.info),

API for locating user information regardless of OS
**************************************************

NAME
====

   User - API for locating user information regardless of OS

SYNOPSIS
========

     use User;

     my $cfg = Config::IniFiles->new
           (
             -file    => sprintf("%s/%s", User->Home, ".ncfg"),
             -default => 'Default'
           );

DESCRIPTION
===========

   This module is allows applications to retrieve per-user
characteristics. At present, it contains only one method, Home(), which is
used to return a location that can be expected to be a users "Home"
directory on either Windows or Unix.

   While one way of writing this would be to check for operating system
and then check the expected location for an operation system of that type,
I chose to do the following:

     sub Home {

     return $ENV{HOME}        if $ENV{HOME};
     return $ENV{USERPROFILE} if $ENV{USERPROFILE};
     return  "";

     }

   In other words, if $HOME is defined in the user's environment, then
that is used. Otherwise $USERPROFILE is used. Otherwise "" is returned.

   A contribution for Macintosh (or any other number of OS/arch
combinations) is greatly solicited.

EXPORT
------

   None by default.

AUTHOR
======

   T.M. Brannon, tbone@cpan.org

ACKNOWLEDGEMENTS
================

   I would like to offer profuse thanks to my fellow perl monk at
www.perlmonks.org, the_slycer, who told me where HOME could be found on
Windows machines.

   perl(1).

Perl access to utmp- and utmpx-style databases
**********************************************

NAME
====

   User::Utmp - Perl access to utmp- and utmpx-style databases

SYNOPSIS
========

     use User::Utmp qw(utmpname getut putut);
     utmpname("file");
     @utmp = getut();
     putut(\%entry);

   or, on systems supporting utmpx:

     use User::Utmp qw(utmpname getutx putut);
     utmpname("file");
     @utmp = getutx();
     putut(\%entry);

DESCRIPTION
===========

   The User::Utmp modules provides functions for reading utmp and utmpx
files, and experimental support for writing utmp files.  The following
functions are provided:

getut()
     Reads a utmp-like file and converts it to a Perl array of hashes.
     Each array element (a reference to a hash) represents one utmp record.
     The hash keys are the names of the elements of the utmp structure as
     described in utmp(4).  The hash values are the same as in C.

     Note that even if `ut_addr' (if provided by the utmp implementation)
     is declared as long, it contains an Internet address (four bytes in
     network order), not a number.  It is therefore converted to a string
     suitable as parameter to gethostbyname().  If the record doesn't
     describe a remote login `ut_addr' is the empty string.

getutx()
     Reads a utmpx-like file and converts it to a Perl array of hashes.
     Each array element (a reference to a hash) represents one utmp record.
     The hash keys are the names of the elements of the utmpx structure as
     described in utmpx(4) or getutx(3).  The hash values are the same as
     in C.

     Note that even if `ut_addr' (if provided by the utmpx implementation)
     is declared as long, it contains an Internet address (four bytes in
     network order), not a number.  It is therefore converted to a string
     suitable as parameter to gethostbyname().  If the record doesn't
     describe a remote login `ut_addr' is the empty string.

putut()
     Writes out the supplied utmp record into the utmp file.  putut() takes
     a reference to a hash which has the same structure and contents as the
     elements of the array returned by getut().  Whether or not putut()
     creates the utmp file if it doesn't exist is implementation-dependent.

utmpname()
     Allows the user to change the name of the file being examined from the
     default file (typically /etc/utmp or, for utmpx, /etc/utmpx) to any
     other file.  In this case, the name provided to utmpname() will be
     used for the getut(), getutx(), and putut() functions.

   User::Utmp also provides the following utmp constants as functions:

   BOOT_TIME DEAD_PROCESS EMPTY INIT_PROCESS LOGIN_PROCESS NEW_TIME
OLD_TIME RUN_LVL USER_PROCESS

   EMPTY is also use on Linux (instead of the non-standard UT_UNKNOWN).

RESTRICTIONS
============

   Reading the whole file into an array might not be the most efficient
approach for potentially large files like /etc/wtmp.

   This module is based on the traditional, non-reentrant utmp functions;
it is therefore not thread-safe.

AUTHOR
======

   Michael Piotrowski <mxp@dynalabs.de>

SEE ALSO
========

   utmp(4), getut(3), utmpx(4), getutx(3)

by-name interface to Perl's built-in getgr*() functions
*******************************************************

NAME
====

   User::grent - by-name interface to Perl's built-in getgr*() functions

SYNOPSIS
========

     use User::grent;
     $gr = getgrgid(0) or die "No group zero";
     if ( $gr->name eq 'wheel' && @{$gr->members} > 1 ) {
         print "gid zero name wheel, with other members";
     }

     use User::grent qw(:FIELDS;
     getgrgid(0) or die "No group zero";
     if ( $gr_name eq 'wheel' && @gr_members > 1 ) {
         print "gid zero name wheel, with other members";
     }

     $gr = getgr($whoever);

DESCRIPTION
===========

   This module's default exports override the core getgrent(), getgruid(),
and getgrnam() functions, replacing them with versions that return
"User::grent" objects.  This object has methods that return the similarly
named structure field name from the C's passwd structure from `grp.h';
namely name, passwd, gid, and members (not mem).  The first three return
scalars, the last an array reference.

   You may also import all the structure fields directly into your
namespace as regular variables using the :FIELDS import tag.  (Note that
this still overrides your core functions.)  Access these fields as
variables named with a preceding `gr_'.  Thus, `$group_obj->gid()'
corresponds to $gr_gid if you import the fields.  Array references are
available as regular array variables, so `@{ $group_obj->members() }'
would be simply @gr_members.

   The getpw() function is a simple front-end that forwards a numeric
argument to getpwuid() and the rest to getpwnam().

   To access this functionality without the core overrides, pass the use
an empty import list, and then access function functions with their full
qualified names.  On the other hand, the built-ins are still available via
the `CORE::' pseudo-package.

NOTE
====

   While this class is currently implemented using the Class::Struct
module to build a struct-like class, you shouldn't rely upon this.

AUTHOR
======

   Tom Christiansen

by-name interface to Perl's built-in getpw*() functions
*******************************************************

NAME
====

   User::pwent - by-name interface to Perl's built-in getpw*() functions

SYNOPSIS
========

     use User::pwent;
     $pw = getpwnam('daemon')       || die "No daemon user";
     if ( $pw->uid == 1 && $pw->dir =~ m#^/(bin|tmp)?\z#s ) {
         print "gid 1 on root dir";
     }

     $real_shell = $pw->shell || '/bin/sh';

     for (($fullname, $office, $workphone, $homephone) =
            split /\s*,\s*/, $pw->gecos)
     {
        s/&/ucfirst(lc($pw->name))/ge;
     }

     use User::pwent qw(:FIELDS);
     getpwnam('daemon')             || die "No daemon user";
     if ( $pw_uid == 1 && $pw_dir =~ m#^/(bin|tmp)?\z#s ) {
         print "gid 1 on root dir";
     }

     $pw = getpw($whoever);

     use User::pwent qw/:DEFAULT pw_has/;
     if (pw_has(qw[gecos expire quota])) { .... }
     if (pw_has("name uid gid passwd"))  { .... }
     print "Your struct pwd has: ", scalar pw_has(), "\n";

DESCRIPTION
===========

   This module's default exports override the core getpwent(), getpwuid(),
and getpwnam() functions, replacing them with versions that return
User::pwent objects.  This object has methods that return the similarly
named structure field name from the C's passwd structure from `pwd.h',
stripped of their leading "pw_" parts, namely name, `passwd', uid, gid,
change, age, `quota', comment, class, `gecos', dir, `shell', and expire.
The `passwd', `gecos', and `shell' fields are tainted when running in
taint mode.

   You may also import all the structure fields directly into your
namespace as regular variables using the :FIELDS import tag.  (Note that
this still overrides your core functions.)  Access these fields as
variables named with a preceding `pw_' in front their method names.  Thus,
`< $passwd_obj-'shell >> corresponds to $pw_shell if you import the fields.

   The getpw() function is a simple front-end that forwards a numeric
argument to getpwuid() and the rest to getpwnam().

   To access this functionality without the core overrides, pass the use
an empty import list, and then access function functions with their full
qualified names.  The built-ins are always still available via the
`CORE::' pseudo-package.

System Specifics
----------------

   Perl believes that no machine ever has more than one of change, age, or
`quota' implemented, nor more than one of either comment or class.  Some
machines do not support expire, `gecos', or allegedly, `passwd'.  You may
call these methods no matter what machine you're on, but they return undef
if unimplemented.

   You may ask whether one of these was implemented on the system Perl was
built on by asking the importable `pw_has' function about them.  This
function returns true if all parameters are supported fields on the build
platform, false if one or more were not, and raises an exception if you
asked about a field that Perl never knows how to provide.  Parameters may
be in a space-separated string, or as separate arguments.  If you pass no
parameters, the function returns the list of `struct pwd' fields supported
by your build platform's C library, as a list in list context, or a
space-separated string in scalar context.  Note that just because your C
library had a field doesn't necessarily mean that it's fully implemented on
that system.

   Interpretation of the `gecos' field varies between systems, but
traditionally holds 4 comma-separated fields containing the user's full
name, office location, work phone number, and home phone number.  An & in
the gecos field should be replaced by the user's properly capitalized
login name.  The `shell' field, if blank, must be assumed to be `/bin/sh'.
Perl does not do this for you.  The `passwd' is one-way hashed garble,
not clear text, and may not be unhashed save by brute-force guessing.
Secure systems use more a more secure hashing than DES.  On systems
supporting shadow password systems, Perl automatically returns the shadow
password entry when called by a suitably empowered user, even if your
underlying vendor-provided C library was too short-sighted to realize it
should do this.

   See passwd(5) and getpwent(3) for details.

NOTE
====

   While this class is currently implemented using the Class::Struct
module to build a struct-like class, you shouldn't rely upon this.

AUTHOR
======

   Tom Christiansen

HISTORY
=======

March 18th, 2000
     Reworked internals to support better interface to dodgey fields than
     normal Perl function provides.  Added pw_has() field.  Improved
     documentation.

Versioned Copy, copying hierarchies of versioned files
******************************************************

NAME
====

   VCP - Versioned Copy, copying hierarchies of versioned files

SYNOPSIS
========

DESCRIPTION
===========

   This module copies hierarchies of versioned files between repositories,
and between repositories and RevML (.revml) files.

   Stay tuned for more documentation.

EXPORTS
=======

   The following functions may be exported: `' in this node, `' in this
node, `' in this node, along with the tags ':all' and ':debug'.  Use the
latter to head off future namespace pollution in case :all gets expanded
in the future..

METHODS
=======

new
          $ex = VCP->new( $source, $dest ) ;

     where

          $source  is an instance of VCP::Source
          $dest    is an instance of VCP::Dest

dest
          $dest = $vcp->dest ;

     Gets the dest object.  This object is set by passing it to new(), so
     there's no need to set it.

copy_all
          $vcp->copy_all( $header, $footer ) ;

     Calls $source->handle_header, $source->copy_revs, and
     $source->handle_footer.

source
          $source = $vcp->source ;

     Gets the source object.  This object is set by passing it to new(),
     so there's no need to set it.

COPYRIGHT
=========

   Copyright 2000, Perforce Software, Inc.  All Rights Reserved.

   This will be licensed under a suitable license at a future date.  Until
then, you may only use this for evaluation purposes.  Besides which, it's
in an early alpha state, so you shouldn't depend on it anyway.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

debugging support for VCP
*************************

NAME
====

   VCP::Debug - debugging support for VCP

SYNOPSIS
========

DESCRIPTION
===========

EXPORTS
=======

   The following functions may be exported: `' in this node, `' in this
node, `' in this node `' in this node, along with the tags ':all' and
':debug'.  Use the latter to head off future namespace pollution in case
:all gets expanded in the future..

   A warning will be emitted on program exit for any specs that aren't
used, to help you make sure that you are using sensible specs.

debug
          debug $foo if debugging $self ;

     Emits a line of debugging (a "\n" will be appended).  Use debug_some
     to avoid the "\n".  Any undefined parameters will be displayed as
     `<undef>'.

debugging
          debugging ;

     Returns TRUE if the caller's module is being debugged

          debugging $self ;
          debugging $other, $self ; ## ORs the arguments together

     Returns TRUE if any of the arguments are being debugged.  Plain
     strings can be passed or blessed references.

disable_debug
     Disable all debugging.

enable_debug
          enable_debug ;
          enable_debug( ...debug specs... ) ;

     A debug spec is the name of a module (or a part of it) to be used as a
     perl5 regular expression.

COPYRIGHT
=========

   Copyright 2000, Perforce Software, Inc.  All Rights Reserved.

   This will be licensed under a suitable license at a future date.  Until
then, you may only use this for evaluation purposes.  Besides which, it's
in an early alpha state, so you shouldn't depend on it anyway.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

A base class for VCP destinations
*********************************

NAME
====

   VCP::Dest - A base class for VCP destinations

SYNOPSIS
========

DESCRIPTION
===========

EXTERNAL METHODS
================

new
     Creates an instance, see subclasses for options.  The options passed
     are usually native command-line options for the underlying
     repository's client.  These are usually parsed and, perhaps, checked
     for validity by calling the underlying command line.

SUBCLASSING
===========

   This class uses the fields pragma, so you'll need to use base and
possibly fields in any subclasses.

SUBCLASS API
------------

   These methods are intended to support subclasses.

header
     Gets/sets the $header passed to handle_header().

     Generally not overridden: all error checking is done in new(), and no
     output should be generated until output() is called.

SUBCLASS OVERLOADS
------------------

   These methods are overloaded by subclasses.

backfill
          $dest->backfill( $rev ) ;

     Checks the file indicated by VCP::Rev $rev out of the target
     repository if this destination supports backfilling.  Currently, only
     the revml destination does not support backfilling.

     The $rev->{workpath} must be set to the filename the backfill was put
     in.

     This is used when doing an incremental update, where the first
     revision of a file in the update is encoded as a delta from the prior
     version.  A digest of the prior version is sent along before the
     first version delta to verify it's presence in the database.

     So, the source calls backfill(), which returns TRUE on success, FALSE
     if the destination doesn't support backfilling, and dies if there's
     an error in procuring the right revision.

     If FALSE is returned, then the revisions will be sent through with no
     working path, but will have a delta record.

     MUST BE OVERRIDDEN.

handle_footer
          $dest->handle_footer( $footer ) ;

     Does any cleanup necessary.  Not required.  Don't call this from the
     override.

handle_header
          $dest->handle_header( $header ) ;

     Stows $header in $self->header.  This should only rarely be
     overridden, since the first call to handle_rev() should output any
     header info.

rev_cmp_sub
     Returns a subroutine reference to a sorting function.  See `' in this
     node.

     Returns -1, 0, or 1 depending on the relative order between $rev_a
     and $rev_b.  This may be overridded.

     Default ordering is by

          - change_id    (compared numerically using <=>, for now)
          - time         (commit time: simple numeric, since this is a simple number)
          - comment      (alphabetically, case sensitive)
          - name         (path-component-wise alphabetically case sensitive)

     This ordering benefits change number oriented systems while preserving
     commit order for non-change number oriented systems.

     If change_id is undefined in either rev, it is not used.

     If time is undefined in a rev, the value "-1" is used.  This causes
     base revisions (ie digest-only) to precede real revisions.

     That's not always good, though: one of commit time or change number
     should be defined!

     Change ids are compared numerically, times by date order (ie by
     alphabetic, since ISO8601 dates are used internally).  Comment is
     compared alphabetically, and name is compared piecewise alphabetically
     after splitting both names on '/' ('//', '///', etc, are treated like
     '/').

     This will confess a problem if none of the above are defined, since I
     can't think of any other rational sorting basis in the general case.

sort_revs
          $source->dest->sort_revs( $source->revs ) ;

     This sorts the revisions that the source has identified in to
     whatever order is needed by the destination.  The default ordering is
     set by `' in this node.

handle_rev
          $dest->handle_rev( $rev ) ;

     Outputs the item referred to by VCP::Rev $rev.  If this is the first
     call, then $self->none_seen will be TRUE and any preamble should be
     emitted.

     MUST BE OVERRIDDEN.  Don't call this from the override.

COPYRIGHT
=========

   Copyright 2000, Perforce Software, Inc.  All Rights Reserved.

   This will be licensed under a suitable license at a future date.  Until
then, you may only use this for evaluation purposes.  Besides which, it's
in an early alpha state, so you shouldn't depend on it anyway.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

cvs destination driver
**********************

NAME
====

   VCP::Dest::cvs - cvs destination driver

SYNOPSIS
========

     vcp <source> cvs:module
     vcp <source> cvs:CVSROOT:module

   where module is a module or directory that already exists within CVS.

   This destination driver will check out the indicated destination in a
temporary directory and use it to add, delete, and alter files.

DESCRIPTION
===========

METHODS
=======

new
     Creates a new instance of a VCP::Dest::cvs.  Contacts the cvsd using
     the cvs command and gets some initial information ('cvs info' and
     'cvs labels').

SUBCLASSING
===========

   This class uses the fields pragma, so you'll need to use base and
possibly fields in any subclasses.

COPYRIGHT
=========

   Copyright 2000, Perforce Software, Inc.  All Rights Reserved.

   This will be licensed under a suitable license at a future date.  Until
then, you may only use this for evaluation purposes.  Besides which, it's
in an early alpha state, so you shouldn't depend on it anyway.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

p4 destination driver
*********************

NAME
====

   VCP::Dest::p4 - p4 destination driver

SYNOPSIS
========

     vcp <source> p4[:<dest>]

   where <dest> is an already created directory in the p4 repository.

   This destination driver will check out the indicated destination in a
temporary directory and use it to add, edit, and delete files.

   At this time, each file being changed is submitted and gets it's own
change number unless change numbers are assigned by the source.

   Also for now, you must take care to cd to the working directory that
the current client's view point to.

DESCRIPTION
===========

METHODS
=======

new
     Creates a new instance of a VCP::Dest::p4.  Contacts the p4d using
     the p4 command and gets some initial information ('p4 info' and 'p4
     labels').

SUBCLASSING
===========

   This class uses the fields pragma, so you'll need to use base and
possibly fields in any subclasses.

COPYRIGHT
=========

   Copyright 2000, Perforce Software, Inc.  All Rights Reserved.

   This will be licensed under a suitable license at a future date.  Until
then, you may only use this for evaluation purposes.  Besides which, it's
in an early alpha state, so you shouldn't depend on it anyway.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

Outputs versioned files to a revml file
***************************************

NAME
====

   VCP::Dest::revml - Outputs versioned files to a revml file

SYNOPSIS
========

   ## revml output class:

     revml:[<output-file>]
     revml:[<output-file>] -dtd <revml.dtd>
     revml:[<output-file>] -dtd <version>

DESCRIPTION
===========

EXTERNAL METHODS
================

new
     Creates a new instance.  The only parameter is '-dtd', which overrides
     the default DTD found by searching for modules matching
     RevML::DTD:v*.pm.

     Attempts to create the output file if one is specified.

COPYRIGHT
=========

   Copyright 2000, Perforce Software, Inc.  All Rights Reserved.

   This will be licensed under a suitable license at a future date.  Until
then, you may only use this for evaluation purposes.  Besides which, it's
in an early alpha state, so you shouldn't depend on it anyway.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

A base class for VCP::Source and VCP::Dest
******************************************

NAME
====

   VCP::Plugin - A base class for VCP::Source and VCP::Dest

SYNOPSIS
========

DESCRIPTION
===========

   Some functionality is common to sources and destinations, such as cache
access, Pod::Usage conversion, command-line access shortcut member, etc.

EXTERNAL METHODS
================

new
     Creates an instance, see subclasses for options.  The options passed
     are usually native command-line options for the underlying
     repository's client.  These are usually parsed and, perhaps, checked
     for validity by calling the underlying command line.

SUBCLASSING
===========

   This class uses the fields pragma, so you'll need to use base and
possibly fields in any subclasses.

SUBCLASS API
------------

   These methods are intended to support subclasses.

seen
          $old_rev = $self->seen( $new_rev ) ;
          $old_r = $self->seen( $name ) ;

     Called to register the fact that $new_rev has been seen, and to
     return the last request for the same resource, which refers to the
     previous version of the resource.  If a plain scalar is passed, simply
     returns the last rev structure that was seen for that filename (but
     does not mark that filename as having been seen if it hasn't).

     This is one of the few accessor methods in VCP's implementation that
     returns the previous value.

none_seen
     Returns TRUE if $dest->seen( $r ) has not yet been called.

parse_repo_spec
          my $spec = $self->split_repo_spec( $spec ) ;

     This splits a repository spec in one of the following formats:

          scheme:user:passwd@server:file_spec
          scheme:user@server:file_spec
          scheme::passwd@server:file_spec
          scheme:server:file_spec
          scheme:file_spec

     in to a HASH reference like

          $hash = {
             SCHEME    => 'scheme',
             USER      => 'user',
             PASSWORD  => 'password',
             SERVER    => 'server',
             FILES     => 'file_spec',
          } ;

     .  The spec is parsed from the edges in in this order:

          1. SCHEME (up to first ':')
          2. FILES  (after last ':')
          3. USER, PASSWORD (before first '@')
          4. SERVER (everything left.

     This approach allows the FILES string to contain '@', and the SERVER
     string to contain ':' and '@'.  USER can contain ':'.  Funky, but this
     works well, at least for cvs and p4.

     If a section of the repo spec is not present, the corresponding entry
     in $hash will not exist.

     The attributes repo_user, repo_password and repo_server are set
     automatically by this method.  It does not store the SCHEME anyware
     since the SCHEME is usually ignored by the plugin (the plugin is
     selected using the scheme, so it knows the scheme implicitly), and
     the FILES setting often needs extra manipulation, so there's no point
     in storing it.

usage_and_exit
          GetOptions( ... ) or $self->usage_and_exit ;

     Used by subclasses to die if unknown options are passed in.

     Requires Pod::Usage when called.

work_path
          $full_path = $self->work_path( $filename, $rev ) ;

     Returns the full path to the working copy of the local filename.

     Each VCP::Plugin gets thier own hierarchy to use, usually rooted at a
     directory named /tmp/vcp$$/plugin-source-foo/ for a module
     VCP::Plugin::Source::foo.  $$ is vcp's process ID.

     This is typically $work_root/$filename/$rev, but this may change.
     $rev is put last instead of first in order to minimize the overhead of
     creating lots of directories.

     It *must* be under $work_root in order for rm_work_path() to fully
     clean.

     All directories will be created as needed, so you should be able to
     create the file easily after calling this.  This is only called by
     subclasses, and is optional: a subclass could create it's own caching
     system.

     Directories are created mode 0775 (rwxrwxr-x), subject to modification
     by umask or your local operating system.  This will be modifiable in
     the future.

mkdir
          $self->mkdir( $filename ) ;
          $self->mkdir( $filename, $mode ) ;

     Makes a directory and any necessary parent directories.

     The default mode is 770.  Does some debug logging if any directories
     are created.

mkpdir
          $self->mkpdir( $filename ) ;
          $self->mkpdir( $filename, $mode ) ;

     Makes the parent directory of a filename and all directories down to
     it.

     The default mode is 770.  Does some debug logging if any directories
     are created.

rm_work_path
          $self->rm_work_path( $filename, $rev ) ;
          $self->rm_work_path( $dirname ) ;

     Removes a directory or file from the work.  Also removes any and all
     directories that become empty as a result up to the work root (/tmp
     on Unix).

work_root
          $root = $self->work_root ;
          $self->work_root( $new_root ) ;
          $self->work_root( $new_root, $dir1, $dir2, .... ) ;

     Gets/sets the work root.  This defaults to

          File::Spec->tmpdir . "/vcp$$/" . $plugin_name

     but may be altered.  If set to a relative path, the current working
     directory is prepended.  The returned value is always absolute, and
     will not change if you chdir().  Depending on the operating system,
     however, it might not be located on to the current volume.  If not,
     it's a bug, please patch away.

command
          $self->command( 'p4' ) ;
          $self->command( 'cvs' ) ;

          $path_to_command = $self->command ;

     This sets the name of the primary command name that is to be used.  A
     search of the PATH environment variable is then done if the path is
     relative to see if the command can be found.

     This method croaks if the command can not be found.

     This is usually called by new().

     Once this is set, the command may be executed by doing something like

          $self->p4( [qw( counters )], \$out )
             or die "Process failed".

     , which runs a 'p4 counters' and pipes the output in to the \$out
     variable.

     See IPC/Run, for details on the additional parameters
     after the command.

command_chdir
     Sets/gets the directory to chdir into before running the default
     command.

command_stderr_filter
          $self->command_stderr_filter( qr/^cvs add: use 'cvs commit'.*\n/m ) ;
          $self->command_stderr_filter( sub { my $t = shift ; $$t =~ ... } ) ;

     Some commands-cough*cvs*cough-just don't seem to be able to shut up
     on stderr.  Other times we need to watch stderr for some meaningful
     output.

     This allows you to filter out expected whinging on stderr so that the
     command appears to run cleanly and doesn't cause $self->cmd(...) to
     barf when it sees expected output on stderr.

     This can also be used to filter out intermittent expected errors that
     aren't errors in all contexts when they aren't actually errors.

command_ok_result_codes
          $self->command_ok_result_codes( 0, 1 ) ;

     Occasionally, a non-zero result is Ok.  this method lets you set a
     list of acceptable result codes.

repo_user
          $self->repo_user( $user_name ) ;
          $user_name = $self->repo_user ;

     Sets/gets the user name to log in to the repository with.  Some
     plugins ignore this, like revml, while others, like p4, use it.

     This is usually set automatically by `' in this node.

repo_password
          $self->repo_password( $password ) ;
          $password = $self->repo_password ;

     Sets/gets the password to log in to the repository with.  Some plugins
     ignore this, like revml, while others, like p4, use it.

     This is usually set automatically by `' in this node.

repo_server
          $self->repo_server( $server ) ;
          $server = $self->repo_server ;

     Sets/gets the repository to log in to.  Some plugins ignore this,
     like revml, while others, like p4, use it.

     This is usually set automatically by `' in this node.

rev_root
          $self->rev_root( 'depot' ) ;
          $rr = $self->rev_root ;

     The rev_root is the root of the tree being sourced. See `' in this
     node for automated extraction.

     Root values should have neither a leading or trailing directory
     separator.

     '/' and '\' are recognized as directory separators and runs of these
     are converted to single '/' characters.  Leading and trailing '/'
     characters are then removed.

deduce_rev_root
          $self->deduce_rev_root ;
          print $self->rev_root ;

     If the user did not specify a rev_root, passing the filespec to this
     will do it.

     '/' and '\' are recognized as directory separators, and '*', '?', and
     '...'  as wildcard sequences.  Runs of '/' and '\' characters are
     reduced to single '/' characters.

     If no wildcards are used in the filespec, then the dirname is used.

     If there is only a single name component, it is assumed to be a
     directory name.

normalize_name
          $fn = $self->normalize_name( $fn ) ;

     Normalizes the filename by converting runs of '\' and '/' to '/',
     removing leading '/' characters, and removing a leading rev_root.
     Dies if the name does not begin with rev_root.

denormalize_name
          $fn = $self->denormalize_name( $fn ) ;

     Denormalizes the filename by prepending the rev_root.  May do more in
     subclass overloads.  For instance, does not prepend a '//' by default
     for instance, but p4 overloads do that.

run
          $self->run( [@cmd_and_args], \$stdout, \$stderr ) ;

     A wrapper around `run', see IPC/Run, which integrates
     debuggins support and disables stdin by default.

COPYRIGHT
=========

   Copyright 2000, Perforce Software, Inc.  All Rights Reserved.

   This will be licensed under a suitable license at a future date.  Until
then, you may only use this for evaluation purposes.  Besides which, it's
in an early alpha state, so you shouldn't depend on it anyway.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

VCP's concept of a revision
***************************

NAME
====

   VCP::Rev - VCP's concept of a revision

SYNOPSIS
========

DESCRIPTION
===========

METHODS
=======

new
     Creates an instance, see subclasses for options.

          my VCP::Rev $rev = VCP::Rev->new(
             name => 'foo',
             time => $commit_time,
             ...
          ) ;

is_base_rev
     Returns TRUE if this is a base revision.  This is the case if no
     action is defined.  A base revision is a revision that is being
     transferred merely to check it's contents against the destination
     repository's contents.  It's usually a digest and the actual bosy of
     the revision is 'backfilled' from the destination repository and
     checked against the digest.  This cuts down on transfer size, since
     the full body of the file never need be sent with incremental updates.

     See `backfill', see VCP/Dest, as well.

work_path, dest_work_path
     These set/get the name of the working file for sources and
     destinations, respectively.  These files are automatically cleaned up
     when all VCP::Rev instances that refer to them are DESTROYED or have
     their work_path or dest_work_path set to other files or undef.

labels
          $r->labels( @labels ) ;
          @labels = $r->labels ;

     Sets/gets labels associated with a revision.  If a label is applied
     multiple times, it will only be returned once.  This feature means
     that the automatic label generation code for r_... revision and
     ch_... change labels won't add additional copies of labels that were
     already applied to this revision in the source repository.

     Returns labels in an unpredictible order, which happens to be sorted
     for now.  This sorting is purely for logging purposes and may
     disappear at any moment.

add_label
          $r->add_label( $label ) ;
          $r->add_label( @labels ) ;

     Marks one or more labels as being associated with this revision of a
     file.

SUBCLASSING
===========

   This class uses the fields pragma, so you'll need to use base and
possibly fields in any subclasses.

COPYRIGHT
=========

   Copyright 2000, Perforce Software, Inc.  All Rights Reserved.

   This will be licensed under a suitable license at a future date.  Until
then, you may only use this for evaluation purposes.  Besides which, it's
in an early alpha state, so you shouldn't depend on it anyway.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

A collection of VCP::Rev objects.
*********************************

NAME
====

   VCP::Revs - A collection of VCP::Rev objects.

SYNOPSIS
========

DESCRIPTION
===========

   Right now, all revs are kept in memory, but we will enable storing them
to disk and recovering them at some point so that we don't gobble huge
tracts of RAM.

METHODS
=======

new
add
          $revs->add( $rev ) ;
          $revs->add( $rev1, $rev2, ... ) ;

     Adds a revision or revisions to the collection.

set
          $revs->set( $rev ) ;
          $revs->set( $rev1, $rev2, ... ) ;

     Sets the list of revs.

get
          @revs = $revs->get ;

     Gets the list of revs.

sort
          # Using a custom sort function:
          $revs->sort( sub { my ( $rev_a, $rev_b ) = @_ ; ... } ) ;

     Note: Don't use $a and $b in your sort function.  They're package
     globals and that's not your package.  See `rev_cmp_sub', see
     VCP/Dest, for more details.

shift
          while ( $r = $revs->shift ) {
             ...
          }

     Call `' in this node before calling this :-).

as_array_ref
     Returns an ARRAY ref of all revs.

SUBCLASSING
===========

   This class uses the fields pragma, so you'll need to use base and
possibly fields in any subclasses.

COPYRIGHT
=========

   Copyright 2000, Perforce Software, Inc.  All Rights Reserved.

   This will be licensed under a suitable license at a future date.  Until
then, you may only use this for evaluation purposes.  Besides which, it's
in an early alpha state, so you shouldn't depend on it anyway.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

A base class for repository sources
***********************************

NAME
====

   VCP::Source - A base class for repository sources

SYNOPSIS
========

DESCRIPTION
===========

EXTERNAL METHODS
================

new
     Creates an instance, see subclasses for options.  The options passed
     are usually native command-line options for the underlying
     repository's client.  These are usually parsed and, perhaps, checked
     for validity by calling the underlying command line.

SUBCLASSING
===========

   This class uses the fields pragma, so you'll need to use base and
possibly fields in any subclasses.  See VCP/Plugin, for
methods often needed in subclasses.

Subclass utility API
--------------------

dest
     Sets/Gets a reference to the VCP::Dest object.  The source uses this
     to call handle_header(), handle_rev(), and handle_end() methods.

SUBCLASS OVERLOADS
==================

   These methods should be overridded in any subclasses.

dest_expected
     Returns TRUE if a destination is expected given the parameters passed
     to new().

     Some sources can have configuration options that cause side effects.
     The only one that does this so far is the revml source, which can
     output the RevML doctype as a .pm file.

copy
     REQUIRED OVERLOAD.

          $source->copy_revs() ;

     Called by `copy', see VCP, to do the entire export process.
     This is passed a partially filled-in header structure.

     The subclass should call

          $self->dest->handle_rev( $rev_meta ) ;

     The subclass needs to make sure the $rev_meta hash contains the
     metadata for the file and a work_path that points to the work
     location of the file:

          $rev_meta = VCP::Rev->new(
             work_path  => '/tmp/revex/4/depot/perl/perl.c',
             name       => 'depot/perl/perl.c',
             rev_id     => '4',
             change_id  => '22',
             labels     => [ 'v0_003', 'v0_004' ],
          ) ;

handle_header
     REQUIRED OVERLOAD.

     Subclasses must add all repository-specific info to the $header, at
     least including rep_type and rep_desc.

          $header->{rep_type} => 'p4',
          $self->p4( ['info'], \$header->{rep_desc} ) ;

     The subclass must call the superclass method to pass the $header on to
     the dest:

          $self->SUPER::handle_header( $header ) ;

handle_footer
     Not a required overload, as the footer carries no useful information
     at this time.  Overriding methods must call this method to pass the
     $footer on:

          $self->SUPER::handle_footer( $footer ) ;

parse_time
          $time = $self->parse_time( $timestr ) ;

     Parses "[cc]YY/MM/DD[ HH[:MM[:SS]]]".

     Will add ability to use format strings in future.  HH, MM, and SS are
     assumed to be 0 if not present.

     Returns a time suitable for feeding to localtime or gmtime.

     Assumes local system time, so no good for parsing times in revml, but
     that's not a common thing to need to do, so it's in
     VCP::Source::revml.pm.

revs
          $self->revs( VCP::Revs->new ) ;
          $self->revs->add( $r ) ; # Many times
          $self->dest->sort_revs( $self->revs ) ;
          my VCP::Rev $r ;
          while ( $r = $self->revs->pop ) {
             ## ...checkout the source reve & set $r->work_path() to refer to it's loc.
             $self->dest->handle_rev( $r ) ;
          }

     Sets/gets the revisions member.  This is used by most sources to
     accumulate the set of revisions to be copied.

     This member should be set by the child in copy_revs().  It should
     then be passed to the destination

bootstrap
     Usually called from within call to GetOptions in subclass' new():

          GetOptions(
             'b|bootstrap:s'   => sub {
          	 my ( $name, $val ) = @_ ;
          	 $self->bootstrap( $val ) ;
             },
             'r|rev-root'      => \$rev_root,
             ) or $self->usage_and_exit ;

     Can be called plain:

          $self->bootstrap( $bootstrap_spec ) ;

     See the command line documentation for the format of $bootstrap_spec.

     Returns nothing useful, but `' in this node does.

COPYRIGHT
=========

   Copyright 2000, Perforce Software, Inc.  All Rights Reserved.

   This will be licensed under a suitable license at a future date.  Until
then, you may only use this for evaluation purposes.  Besides which, it's
in an early alpha state, so you shouldn't depend on it anyway.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

A CVS repository source
***********************

NAME
====

   VCP::Source::cvs - A CVS repository source

SYNOPSIS
========

     vcp cvs:path/... -r foo        # all files in path and below labelled foo
     vcp cvs:path/... -r foo:       # All revs of files labelled foo and newer
     vcp cvs:path/... -r foo: -f    # All revs of files labelled foo and newer,
                                    # including files not tagged with foo.
     vcp cvs:path/... -r 1.1:1.10   # revs 1.1..1.10
     vcp cvs:path/... -r 1.1:       # revs 1.1 and up

     vcp cvs:path/... -D ">=2000-11-18 5:26:30"
                                    # All file revs newer than a date/time

     ## cvs -D and -f also supported

DESCRIPTION
===========

   Reads a CVS repository.  You must check out the files of interest in to
a local working directory and run the cvs command from within that
directory.  This is because the "cvs log" and "cvs checkout" commands need
to have a working directory to play in.

   This module in alpha.  For instance, it may be better to use a more
cvs-like set of options to specify revision ranges.  So please don't be
offended if the CLI changes.  Certainly labels containing '-' will throw
us off.

   Note for p4 users (and other change-number or change-set oriented
destinations): this source does not do change-number extraction /
aggregation.  This should be done by the destination, as it is
destination-specific.

   This module does sort the revisions it outputs so that such extraction
can be less painful.  Revisions are sorted in increasing date order.

   This doesn't deal with branches yet (at least not intentionally).  That
will require a bit of Deep Thought.

   This only deals with filespecs spelled like "/a/b/c" or "a/b/..." for
now.

   Later, we can handle other filespecs by reading the entire log output.

OPTIONS
=======

-b, -bootstrap
          -b '**'
          --bootstrap='**'
          -b file1[,file2[,...]]
          --bootstrap=file1[,file2[,...]]

     Forces bootstrap mode for an entire export (-b '**') or for certain
     files.  Filenames may contain wildcards, see Regexp/Shellish,
     for details on what wildcards are accepted.  For
     now, one thing to remember is to use '**' instead of p4's '...'
     wildcard.

     Controls how the first revision of a file is exported.  A bootstrap
     export contains the entire contents of the first revision in the
     revision range.  This should only be used when exporting for the
     first time.

     An incremental export contains a digest of the revision preceding the
     first revision in the revision range, followed by a delta record
     between that revision and the first revision in the range.  This
     allows the destination import function to make sure that the
     incremental export begins where the last export left off.

     The default is decided on a per-file basis: if the first revision in
     the range is revision #1, the full contents are exported.  Otherwise
     an incremental export is done for that file.

     This option is necessary when exporting only more recent revisions
     from a repository.

-cd
     Used to set the CVS root directory, overriding the value of the
     CVSROOT environment vairable.  Using this and -cd it is possible to
     export from one CVS repository and import to another.

-rev-root
     *experimental*

     Sets the root of the source tree to export.  All files to be exported
     must be under this root directory.  The default rev-root is all of the
     leading non-wildcard directory names.  This can be useful in the
     unusual case of exporting a sub-tree of a larger project.  I think.

-r
          -r v_0_001:v_0_002 -f
          -r v_0_002:-f

     Passed to 'cvs log' as a '-r' revision specification.

     WARNING: if this string doesn't contain a ':', you're probably doing
     something wrong, since you're not specifying a revision range.  vcp
     may wanr about this in the future.

     This will normally only replicate files which are tagged.  This means
     that files that have been added since, or which are missing the tag
     for some reason, are ignored.

     Use the `' in this node option to force files that don't contain the
     tag to be exported.  This is probably what is expected.

     One of -r or `' in this node must be specified.

-d
          -d "2000-11-18 5:26:30<="

     Passed to 'cvs log' as a '-d' date specification.

     WARNING: if this string doesn't contain a '>' or '<', you're probably
     doing something wrong, since you're not specifying a range.  vcp may
     warn about this in the future.

     One of `' in this node or -D must be specified.

-f
     Not implemented yet.

     This option causes vcp to attempt to export files that don't contain a
     particular tag.

     It is an error to specify -f without -r.

     It does this by exporting all revisions of files between the oldest
     and newest files that the -r specified.  Without -f, these would be
     ignored.

SUBCLASSING
===========

   This class uses the fields pragma, so you'll need to use base and
possibly fields in any subclasses.

COPYRIGHT
=========

   Mostly copyright 2000, Perforce Software, Inc.  All Rights Reserved,
except for marked portions (ie the CVS log file parsing), which are
Copyright 2000, Barrie Slaymaker, Inc.  All Rights Reserved.

   This will be licensed under a suitable license at a future date.  Until
then, you may only use this for evaluation purposes.  Besides which, it's
in an early alpha state, so you shouldn't depend on it anyway.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

A Perforce p4 repository source
*******************************

NAME
====

   VCP::Source::p4 - A Perforce p4 repository source

SYNOPSIS
========

     vcp p4://depot/...@10          # all files after change 10 applied
     vcp p4://depot/...@1,10        # changes 1..10
     vcp p4://depot/...@-2,10       # changes 8..10
     vcp p4://depot/...@1,#head     # changes 1..#head
     vcp p4://depot/...@-2,#head    # changes 8..10
     vcp p4:...@-2,#head            # changes 8..10, if only one depot

   To specify a user name of 'user', P4PASSWD 'pass', and port 'port:1666',
use this syntax:

     vcp p4:user:client:pass@port:1666:files

   Note: the password will be passed in the environment variable P4PASSWD
so it shouldn't show up in error messages.  User, client and the server
string will be passed as command line options to make them show up in
error output.

   You may use the P4... environment variables instead of any or all of
the fields in the p4: repository specification.  The repository spec
overrides the environment variables.

DESCRIPTION
===========

   Reads a p4d.

   Note that not all metadata is exported: labels and users are not
exported as of yet.  This stuff will go in to the RevML at some point.

   Also, the 'time' and 'mod_time' attributes will lose precision, since
p4 doesn't report them down to the minute.  Hmmm, seems like p4 never sets
a true mod_time.  It gets set to either the submit time or the sync time.
From ``p4 help client'`:

     modtime         Causes 'p4 sync' to force modification time
     		    to when the file was submitted.

     nomodtime *     Leaves modification time set to when the
     		    file was fetched.

OPTIONS
=======

-b, -bootstrap
          -b '**'
          --bootstrap='**'
          -b file1[,file2[,...]]
          --bootstrap=file1[,file2[,...]]

     Forces bootstrap mode for an entire export (-b '**') or for certain
     files.  Filenames may contain wildcards, see Regexp/Shellish,
     for details on what wildcards are accepted.  For
     now, one thing to remember is to use '**' instead of p4's '...'
     wildcard.

     Controls how the first revision of a file is exported.  A bootstrap
     export contains the entire contents of the first revision in the
     revision range.  This should only be used when exporting for the
     first time.

     An incremental export contains a digest of the revision preceding the
     first revision in the revision range, followed by a delta record
     between that revision and the first revision in the range.  This
     allows the destination import function to make sure that the
     incremental export begins where the last export left off.

     The default is decided on a per-file basis: if the first revision in
     the range is revision #1, the full contents are exported.  Otherwise
     an incremental export is done for that file.

     This option is necessary when exporting only more recent revisions
     from a repository.

-r, -rev-root
     Sets the root of the source tree to export.  All files to be exported
     must be under this root directory.  The default rev-root is all of the
     leading non-wildcard directory names.  This can be useful in the
     unusual case of exporting a sub-tree of a larger project.  I think.

METHODS
=======

new
     Creates a new instance of a VCP::Source::p4.  Contacts the p4d using
     the p4 command and gets some initial information ('p4 info' and 'p4
     labels').

SUBCLASSING
===========

   This class uses the fields pragma, so you'll need to use base and
possibly fields in any subclasses.

COPYRIGHT
=========

   Copyright 2000, Perforce Software, Inc.  All Rights Reserved.

   This will be licensed under a suitable license at a future date.  Until
then, you may only use this for evaluation purposes.  Besides which, it's
in an early alpha state, so you shouldn't depend on it anyway.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

Outputs versioned files to a revml file
***************************************

NAME
====

   VCP::Source::revml - Outputs versioned files to a revml file

SYNOPSIS
========

     vcp revml[:<source>]
     vcp revml[:<source>] --dtd <dtd>

   Where <source> is a filename for input; or missing or '-' for STDIN.

   To compile a DTD in to a perl module:

     revml: --dtd <dtd> --save-doctype

DESCRIPTION
===========

   This reads a revml file and reconstitutes every revision of every file
fond therein on the disk and then submits them to the destination.

   This can require a huge amount of disk space, but it works.  Disk usage
can be optimised later by only reconstituting the files two revisions at a
time (the previous revision is needed to generate the current one) as the
revs are submitted to the destination after they are sorted (by the dest).

   When that happens, we need to bear in mind that the revml file will be
in the default sort order defined by VCP/Dest, and this
may be changed by other destinations, particularly the change set oriented
ones like p4.  As an example, imagine the following process:

     cvs -> vcp -> foo.revml -> vcp -> p4

   There is some chance that VCP/Dest/p4, will want to
reorder the revisions in foo.revml in order to attemp change set
aggregation.  This means that it may ask for the revs in a different order
than they are found in the file.  Since the default sort order *should*
put the foo.revml file in (roughly) change set order.  This is a bad
example, I guess, but hey, just watch out when optimizing for disk space.

EXTERNAL METHODS
================

new
     Creates a new instance.  The only parameter is '-dtd', which overrides
     the default DTD found by searching for modules matching
     RevML::DTD:v*.pm.

     Attempts to open the input file if one is specified.

     If the option '-save-doctype' is passed, then no copying of resources
     is done (queue_all returns nothing to copy) and the doctype is saved
     as a .pm file.  See RevML/Doctype, for details.

COPYRIGHT
=========

   Copyright 2000, Perforce Software, Inc.  All Rights Reserved.

   This will be licensed under a suitable license at a future date.  Until
then, you may only use this for evaluation purposes.  Besides which, it's
in an early alpha state, so you shouldn't depend on it anyway.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

Library for generic Version Control System access in Perl
*********************************************************

NAME
====

   VCS - Library for generic Version Control System access in Perl

SYNOPSIS
========

     use VCS;
     $file = VCS::File->new($ARGV[0]);
     print $file->name, ":\n";
     for $version ($file->versions) {
         print
             $version->version,
             ' was checked in by ',
             $version->author,
             "\n",
             ;
     }

DESCRIPTION
===========

   `VCS' is an API for abstracting access to all version control systems
from Perl code. This is achieved in a similar fashion to the DBI suite of
modules. There are "container" classes, `VCS::Dir', `VCS::File', and
`VCS::Version', and "implementation" classes, such as `VCS::Cvs::Dir',
`VCS::Cvs::File', and `VCS::Cvs::Version', which are subclasses of their
respective "container" classes.

   The "container" classes work as follows: when the new method of a
container class is called, it will cycle through each of the known
implementation classes, trying its new method with the given arguments
until one returns a defined result, which will then be returned.

   An implementation class is recognised as follows: its name starts with
`VCS::', and `require "VCS/Classname.pm"' will load the appropriate
implementation classes corresponding to the container classes.

   In general, implementation classes' new methods must be careful not to
return "false positives", by rigorously checking if their arguments
conform to their particular version control system.

   Implementation classes must include documentation for their special
requirements, such as mandatory environment variables. See VCS/Cvs,
for an example.

   If a method, or an argument to a method makes no sense for a particular
implementation, then the implementation may ignore it, but must do so
quietly.

METHODS
=======

VCS->implementations
--------------------

   Returns a list of the implementations, in the order in which they will
be tried by the container classes. The first time it is called (as
determined by whether there are any implementations known), it will search
@INC for all compliant implementations.

VCS->add_implementations(@implementations)
------------------------------------------

   `@implementations' is moved/added to the front of the list, so use this
also to set the default or control the order of implementations tried.

AVAILABILITY
============

   VCS.pm and its friends will be available from CPAN.

MAILING LIST
============

   There is currently a mailing list about VCS.

   To subscribe, send a blank message to: vcs-subscribe@astray.com.  To
talk, send a message to: vcs@astray.com.  To unsubscribe, send a blank
message to: vcs-unsubscribe@astray.com.

   General queries should be made directly to the mailing list.

COPYRIGHT
=========

   Copyright (c) 1998/9 Leon Brocard. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   See VCS/Cvs, VCS/Dir, VCS/File,
`VCS::Rcs' in this node, see VCS/Version.

Provide a simple interface to CVS (the Concurrent Versions System).
*******************************************************************

NAME
====

   `VCS::CVS' - Provide a simple interface to CVS (the Concurrent Versions
System).

   You need to be clear in your mind about the 4 directories involved:

   * The directory where your source code resides before you import it
     into CVS.  It is used only once - during the import phase. Call this
     $projectSource.

   * The directory into which you check out a read-write copy of the
     repository, in order to edit that copy. Call this $project. You will
     spend up to 100% of your time working within this directory structure.

   * The directory in which the repository resides. This is $CVSROOT. Thus
     $projectSource will be imported into $CVSROOT/$project.

   * The directory into which you get a read-only copy of the repository,
     in order to, say, make and ship that copy. Call this $someDir. It
     must not be $project.

   Note: You cannot have a directory called CVS in your home directory.
That's just asking for trouble.

SYNOPSIS
========

     #!/usr/gnu/bin/perl -w

     use integer;
     use strict;

     use VCS::CVS;

     my($history)        = 1;
     my($initialMsg)     = 'Initial version';
     my($noChange)       = 1;
     my($nullTag)        = '';
     my($permissions)    = 0775;	# But not '0775'!
     my($project)        = 'project';
     my($projectSource)  = 'projectSource';
     my($raw)            = 0;
     my($readOnly)       = 0;
     my($releaseTag)     = 'release_0.00';
     my($vendorTag)      = 'vendorTag';
     my($verbose)        = 1;

     # Note the anonymous hash in the next line, new as of V 1.10.

     my($cvs)            = VCS::CVS -> new({
     			'project' => $project,
     			'raw' => $raw,
     			'verbose' => $verbose,
     			'permissions' => $permissions,
     			'history' => $history});

     $cvs -> createRepository();
     $cvs -> populate($projectSource, $vendorTag, $releaseTag, $initialMsg);
     $cvs -> checkOut($readOnly, $nullTag, $project);

     print join("\n", @{$cvs -> update($noChange)});
     print "\n";
     print join("\n", @{$cvs -> history()});

     exit(0);

DESCRIPTION
===========

   The `VCS::CVS' module provides an OO interface to CVS.

   VCS - Version Control System - is the prefix given to each Perl module
which deals with some sort of source code control system.

   I have seen CVS corrupt binary files, even when run with CVS's binary
option -kb.  So, since CVS doesn't support binary files, neither does
VCS::CVS.

   Stop press: CVS V 1.10 (with RCS 5.7) supports binary files.

   Subroutines whose names start with a '_' are not normally called by you.

   There is a test program included, but I have not yet worked out exactly
how to set it up for make test. Stay tuned.

INSTALLATION
============

   You install `VCS::CVS', as you would install any perl module library,
by running these commands:

     perl Makefile.PL
     make
     make test
     make install

   If you want to install a private copy of `VCS::CVS' in your home
directory, then you should try to produce the initial Makefile with
something like this command:

     perl Makefile.PL LIB=~/perl
     	or
     perl Makefile.PL LIB=C:/Perl/Site/Lib

   If, like me, you don't have permission to write man pages into unix
system directories, use:

     make pure_install

   instead of make install. This option is secreted in the middle of p 414
of the second edition of the dromedary book.

WARNING re CVS bugs
===================

   The following are my ideas as to what constitutes a bug in CVS:

   * The initial revision tag, supplied when populating the repository with
     'cvs import', is not saved into $CVSROOT/CVSROOT/val-tags.

   * The 'cvs tag' command does not always put the tag into 'val-tags'.

   * `'cvs checkout -dNameOfDir'' fails if NameOfDir =~ /\/$/.

   * `'cvs checkout -d NameOfDir'' inserts a leading space into the name of
     the directory it creates.

WARNING re test environment
===========================

   This code has only been tested under Unix. Sorry.

WARNING re project names 'v' directory names
============================================

   I assume your copy of the repository was checked out into a directory
with the same name as the project, since I do a 'cd $HOME/$project' before
running 'cvs status', to see if your copy is up-to-date. This is because
some activity is forbibben unless your copy is up-to-date. Typical cases
of this include:

   * `checkOut'

   * `removeDirectory'

   * `setTag'

WARNING re shell intervention
=============================

   Some commands cause the shell to become involved, which, under Unix,
will read your .cshrc or whatever, which in turn may set CVSROOT to
something other than what you set it to before running your script. If
this happens, panic...

   Actually, I think I've eliminated such cases. You hope so.

WARNING re Perl bug
===================

   As always, be aware that these 2 lines mean the same thing, sometimes:

   * $self -> {'thing'}

   * $self->{'thing'}

   The problem is the spaces around the ->. Inside double quotes, "...",
the first space stops the dereference taking place. Outside double quotes
the scanner correctly associates the $self token with the {'thing'} token.

   I regard this as a bug.

addDirectory($dir, $subDir, $message)
=====================================

   Add an existing directory to the project.

   $dir can be a full path, or relative to the CWD.

addFile($dir, $file, $message)
==============================

   Add an existing file to the project.

   $dir can be a full path, or relative to the CWD.

checkOut($readOnly, $tag, $dir)
===============================

   Prepare & perform 'cvs checkout'.

   You call checkOut, and it calls _checkOutDontCallMe.

   * $readOnly == 0 -> Check out files as read-write.

   * $readOnly == 1 -> Check out files as read-only.

   * $tag is Null -> Do not call upToDate; ie check out repository as is.

   * $tag is not Null -> Call upToDate; Croak if repository is not
     up-to-date.

   The value of $raw used in the call to new influences the handling of
$tag:

   * $raw == 1 -> Your tag is passed as is to CVS.

   * $raw == 0 -> Your tag is assumed to be of the form release_1.23, and
     is converted to CVS's form release_1_23.

   $dir can be a full path, or relative to the CWD.

commit($message)
================

   Commit changes.

   Called as appropriate by addFile, removeFile and removeDirectory, so
you don't need to call it.

createRepository()
==================

   Create a repository, using the current $CVSROOT.

   This involves creating these files:

   * $ENV{'CVSROOT'}/CVSROOT/modules

   * $ENV{'CVSROOT'}/CVSROOT/val-tags

   * $ENV{'CVSROOT'}/CVSROOT/history

   Notes:

   * The 'modules' file contains these lines:

          CVSROOT  CVSROOT
          modules  CVSROOT  modules
          $self -> {'project'}  $self -> {'project'}

     where $self -> {'project'} comes from the 'project' parameter to new()

   * The 'val-tags' file is initially empty

   * The 'history' file is only created if the 'history' parameter to
     new() is set.  The file is initially empty

getTags()
=========

   Return a reference to a list of tags.

   See also: the $raw option to new().

   `getTags' does not take a project name because tags belong to the
repository as a whole, not to a project.

history({})
===========

   Report details from the history log, $CVSROOT/CVSROOT/history.

   You must have used new({'history' => 1}), or some other mechanism, to
create the history file, before CVS starts logging changes into the
history file.

   The anonymous hash takes any parameters 'cvs history' takes, and joins
them with a single space. Eg:

     $cvs -> history();

     $cvs -> history({'-e' => ''});

     $cvs -> history({'-xARM' => ''});

     $cvs -> history({'-u' => $ENV{'LOGNAME'}, '-x' => 'A'});

   but not

     $cvs -> history({'-xA' => 'M'});

   because it doesn't work.

new({})
=======

   Create a new object. See the synopsis.

   The anonymous hash takes these parameters, of which 'project' is the
only required one.

   * 'project' => 'killerApp'. The required name of the project. No default

   * 'permissions' => 0775. Unix-specific stuff. Default. Do not use
     '0775'.

   * 'history' => 0. Do not create $CVSROOT/CVSROOT/history when
     createRepository() is called. Default

   * 'history' => 1. Create $CVSROOT/CVSROOT/history, which initiates 'cvs
     history' stuff

   * 'raw' => 0. Convert tags from CVS format to real format. Eg:
     release_1.23. Default.

   * 'raw' => 1. Return tags in raw CVS format. Eg: release_1_23.

   * 'verbose' => 0. Do not report on the progress of mkpath/rmtree

   * 'verbose' => 1. Report on the progress of mkpath/rmtree. Default

populate($sourceDir, $vendorTag, $releaseTag, $message)
=======================================================

   Import an existing directory structure. But, (sub) import is a reserved
word.

   Use this to populate a repository for the first time.

   The value used for $vendorTag is not important; CVS discards it.

   The value used to $releaseTag is important; CVS discards it (why?) but I
force it to be the first tag in $CVSROOT/CVSROOT/val-tags. Thus you should
supply a meaningful value. Thus 'release_0_00' is strongly, repeat
strongly, recommended.

   The value of $raw used in the call to new influences the handling of
$tag:

   * $raw == 1 -> Your tag is passed as is to CVS.

   * $raw == 0 -> Your tag is assumed to be of the form release_1.23, and
     is converted to CVS's form release_1_23.

removeDirectory($dir)
=====================

   Remove a directory from the project.

   This deletes the directory (and all its files) from your working copy
of the repository, as well as deleting them from the repository.

   Warning: $dir will have $CVSROOT and $HOME prepended by this code.  Ie:
$dir starts from - but excludes - your home directory (assuming, of
course, you've checked out into your home directory...).

   You can't remove the current directory, or a parent.

removeFile($dir, $file, $message)
=================================

   Remove a file from the project.

   This deletes the file from your working copy of the repository, as well
as deleting it from the repository.

   $dir can be a full path, or relative to the CWD.  $file is relative to
$dir.

runOrCroak()
============

   The standard way to run a system command and report on the result.

setTag($tag)
============

   Tag the repository.

   You call setTag, and it calls _setTag.

   The value of $raw used in the call to new influences the handling of
$tag:

   * $raw == 1 -> Your tag is passed as is to CVS.

   * $raw == 0 -> Your tag is assumed to be of the form release_1.23, and
     is converted to CVS's form release_1_23.

stripCVSDirs($dir)
==================

   Delete all CVS directories and files from a copy of the repository.

   Each user directory contains a CVS sub-directory, which holds 3 files:

   * Entries

   * Repository

   * Root

   Zap 'em.

status()
========

   Run cvs status.

   Return a reference to a list of lines.

   Only called by upToDate(), but you may call it.

update($noChange)
=================

   Run 'cvs -q [-n] update', returning a reference to a list of lines.
Each line will start with one of [UARMC?], as per the CVS docs.

   $cvs -> update(1) is a good way to get a list of uncommited changes,
etc.

   * $noChange == 0 -> Do not add -n to the cvs command. Ie update your
     working copy

   * $noChange == 1 -> Add -n to the cvs command. Do not change any files

upToDate()
==========

   * return == 0 -> Repository not up-to-date.

   * return == 1 -> Up-to-date.

_checkOutDontCallMe($readOnly, $tag, $dir)
==========================================

   Checkout a current copy of the project.

   You call checkOut, and it calls this.

   * $readOnly == 0 -> Check out files as read-write.

   * $readOnly == 1 -> Check out files as read-only.

_fixTag($tag)
=============

   Fix a tag which CVS failed to add.

   Warning: $tag must be in CVS format: release_1_23, not release_1.23.

_mkpathOrCroak($self, $dir)
===========================

   There is no need for you to call this.

_readFile($file)
================

   Return a reference to a list of lines.

   There is no need for you to call this.

_setTag($tag)
=============

   Tag the current version of the project.

   Warning: $tag must be in CVS format: release_1_23, not release_1.23.

   You call setTag and it calls this.

_validateObject($tag, $file, $mustBeAbsent)
===========================================

   Validate an entry in one of the CVS files 'module' or 'val-tags'.

   Warning: $tag must be in CVS format: release_1_23, not release_1.23.

AUTHOR
======

   `VCS::CVS' was written by Ron Savage *<rpsavage@ozemail.com.au>* in
1998.

LICENCE
=======

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

implementation notes for CVS implementation
*******************************************

NAME
====

   VCS::Cvs - implementation notes for CVS implementation

SYNOPSIS
========

     $ENV{CVSROOT} = '/cvsroot';
     use VCS;
     $file = VCS::File->new('/source/cvsrepos/project/Makefile');

DESCRIPTION
===========

   Currently, the user needs to ensure that the environmental requirements
for CVS command line tools are satisfied.

AVAILABILITY
============

   VCS::Cvs is currently part of the main VCS distribution.

COPYRIGHT
=========

   Copyright (c) 1998-9 Leon Brocard. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   See VCS.

module for access to a VCS directory
************************************

NAME
====

   VCS::Dir - module for access to a VCS directory

SYNOPSIS
========

     use VCS;
     my $d = VCS::Dir->new($dir);
     print $d->name . "\n";
     foreach my $x ($d->content) {
         print "\t" . $x->name . "\t" . ref($x) . "\n";
     }

DESCRIPTION
===========

   `VCS::Dir' abstracts access to a directory under version control.

METHODS
=======

   Methods marked with a "*" are not yet finalised/implemented.

VCS::Dir->create_new($dir) *
----------------------------

   $dir is a directory name, absolute or relative.  Creates data as
appropriate to convince the VCS that there is a file-container, and
returns an object of class `VCS::Dir', or undef if it fails. This is a
pure virtual method, which must be over-ridden, and cannot be called
directly in this class (a die will result).

VCS::Dir->introduce($name, $create_class) *
-------------------------------------------

   $name is a file or directory name, absolute or relative.
`$create_class' is either File or Dir, and implementation classes are
expected to use something similar to this code, to call the appropriate
create_new:

     sub introduce {
         my ($class, $name, $create_class) = @_;
         my $call_class = $class;
         $call_class =~ s/[^:]+$/$create_class/;
         return $call_class->create_new($name);
     }

   This is a pure virtual method, which must be over-ridden, and cannot be
called directly in this class (a die will result).

VCS::Dir->new($dir)
-------------------

   $dir is a directory name, absolute or relative.  Returns an object of
class `VCS::Dir', or undef if it fails.

$dir->name
----------

   Returns the $dir argument to new.

$dir->content
-------------

   Returns a list of objects, either of class `VCS::Dir' or `VCS::File',
corresponding to files and directories within this directory.

SEE ALSO
========

   See VCS.

COPYRIGHT
=========

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

module for access to a file under version control
*************************************************

NAME
====

   VCS::File - module for access to a file under version control

SYNOPSIS
========

     use VCS;
     my $f = VCS::File->new($file);
     print $f->name . "\n";
     foreach my $v ($f->versions) {
         print "\tversion: " . $v->version . "\t" . ref($v) . "\n";
     }

DESCRIPTION
===========

   `VCS::File' abstracts access to a file under version control.

METHODS
=======

   Methods marked with a "*" are not yet finalised/implemented.

VCS::File->create_new($name) *
------------------------------

   $name is a file name, absolute or relative.  Creates data as
appropriate to convince the VCS that there is a file, and returns an
object of class `VCS::File', or undef if it fails. This is a pure virtual
method, which must be over-ridden, and cannot be called directly in this
class (a die will result).

VCS::File->introduce($version_args) *
-------------------------------------

   `$version_args' is a hash-ref, see VCS/Version, for
details.  Implementation classes are expected to use something similar to
this code, to call create_new in the right `VCS::Version' subclass:

     sub introduce {
         my ($class, $version_args) = @_;
         my $call_class = $class;
         $call_class =~ s/[^:]+$/Version/;
         return $call_class->create_new($version_args);
     }

   This is a pure virtual method, which must be over-ridden, and cannot be
called directly in this class (a die will result).

VCS::File->new($file)
---------------------

   $file is a file name, absolute or relative.  Returns an object of class
`VCS::File', or undef if it fails.

$file->name
-----------

   Returns the $file argument to new.

$file->versions
---------------

   Returns a list of objects of class `VCS::Version', in order of ascending
revision number. If it is passed an extra (defined) argument, it only
returns the last version as a `VCS::Version'.

SEE ALSO
========

   See VCS.

COPYRIGHT
=========

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Global configuration class for for VCS::PVCS::*.
************************************************

NAME
====

   VCS::PVCS - Global configuration class for for VCS::PVCS::*.

SYNOPSIS
========

     use VCS::PVCS::Project;  # preferred
     $project = new VCS::PVCS::Project("ProjectName");

DESCRIPTION
===========

   The VCS::PVCS class simply parses the PVCS global configuration files,
including pvcsproj.pub and MASTER.CFG, found in PVCSPROJ.  The resulting
object is then included in the VCS::PVCS::Project object as it's "CONFIG".
The class members are used at various times in other subclasses, as
needed.

   NOTE: This module may require some configuration.  If your scripts wont
run, you may need to hardwire some of the global parameters, including
$ISLVINI, $PVCSPROJ, $NFSMAP, $PVCS_BINDIR and possibly others.  You
should inspect the module before installing it, to verify the settings
will work.

   This module also exports several GLOBAL variables, which are used in
various places throughout it's children, and can be used in scripts which
load the *VCS::PVCS::Project* class.  These variables include, but may not
always be limited to:

$PVCSERR
     PVCSERR is set to the current value of $? after each command.

$PVCSDEBUG
     PVCSDEBUG can be turned on to see copious (sometimes useful) debugging
     output as the module is configuring itself, and running.

$PVCSOUTPUT
     PVCSOUTPUT is all of the output from the current method, when it
     executes a pvcs command.  If the command was executed on a folder or
     project-wide basis, then PVCSOUTPUT contains ALL of the output for
     all archives.

$PVCSCURROUTPUT
     PVCSCURROUTPUT is ONLY the output for the most recent command sent to
     the shell.

$PVCSSHOWMODE
     PVCSSHOWMODE is turned on to see, and not execute, commands.

$PVCS_BINDIR
     PVCS_BINDIR is set in the environment or in VCS::PVCS.pm to be the
     location of the PVCS binaries, get, put, vlog, vcs, vdiff, etc.

$PVCSMASTERCFG
     PVCSMASTERCFG is the path to the master configuration file.  This
     variable is not exported to the world through VCS::PVCS::Project, but
     only intended for internal use.

$PVCSCURRPROJCFG
     PVCSCURRPROJCFG is the location of the current projects' Config file.
     This variable is not exported to the world through VCS::PVCS::Project,
     but only intended for internal use.

$PVCSMULTIPLATFORM
     PVCSMULTIPLATFORM tells the modules whether to make certain path
     translations when operating on something other than WIN.  Turn this
     on if you are using PVCS in a multiplatform environment.

     *This variable is turned on automatically if an NFSMAP is found*

$PVCSPROJ
     PVCSPROJ is the base directory for all PVCS control files.

   Ordinarily, this class wont be used directly.  Rather, it is in the
@ISA for VCS::PVCS::Project.  When creating a new VCS::PVCS::Project
object, this module's new() method is invoked automatically.

AUTHOR
======

   Bill Middleton, wjm@metronet.com

COPYRIGHT
=========

   The PVCS module is Copyright (c) 1998 Bill Middleton.  All rights
reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SUPPORT / WARRANTY
==================

   The VCS::PVCS modules are free software.

   *THEY COME WITHOUT WARRANTY OF ANY KIND.*

   Commercial support agreements for Perl can be arranged via The Perl
Clinic. See http://www.perl.co.uk/tpc for more details.

SEE ALSO
========

   perl(1), VCS::PVCS::Project

Archive class for for VCS::PVCS.
********************************

NAME
====

   VCS::PVCS::Archive - Archive class for for VCS::PVCS.

SYNOPSIS
========

     use VCS::PVCS::Project;

     $project = new VCS::PVCS::Project("ProjectName");

   # return ref to array of all folders in the project with SCRIPTS in the
name

     $folds = $project->openFolders("SCRIPTS");
     foreach $folder (@$folds){
     	@archives = $folder->Members(); # array of blessed Archive objects
     	foreach $archive(@archives){
     	    $archive->checkout;  # Checkout single archive to folder's WD
     	}
     }

DESCRIPTION
===========

   This class provides methods for use by Archive objects in the PVCS
model.

   Ordinarily, this class won't be included in your programs, as it is
part of the ISA for the master class VCS::PVCS::Project, which should
ordinarily be used, as shown above.

METHODS
=======

new
          VCS::PVCS::Archive::new(archivedir,
          	workdir,workfile,"checkin comment","workfile comment");

     Open an existing archive or create a new one.

workfile
          $workfile = $Archive->Workfile;

     Return the default workfile for this archive object.  Use opts to
     change default actions.

get
          $Archive->get([get opts]);

     Checkout the archive to the CWD.  Use opts to change default actions.

checkout
          Convenience routine calls get()

co
          Convenience routine calls get()

put
          $Archive->put([put opts]);

     Checkin the workfile in CWD to archive.  Use opts to change default
     actions.

checkin
          Convenience routine calls put()

ci
          Convenience routine calls put()

vdiff
          $Archive->vdiff([vdiff opts]);

     Takes a diff on the archive and workfile.  Use opts to change default
     actions.

vlog
          $Archive->vlog([vlog opts]);

     Takes a full vlog on the archive.  Use opts to change default actions.

log
          Convenience routine calls vlog()

history
          Convenience routine calls vlog()

lock
          $Archive->lock($label|$version,[vcs opts]);

     Locks the named revision (or rev spec'd by label).  Use opts to
     change default action.

unlock
          $Archive->unlock($label|$version,[vcs opts]);

     unlocks the named revision (or rev spec'd by label).  Use opts to
     change default action.

addVersionLabel
          $Archive->addVersionLabel($label,[vcs opts]);

     Create a new sticky version label for the archive (optionally with
     :<rev>.

deleteVersionLabel
          $Archive->deleteVersionLabel($label,[vcs opts]);

     Delete a version label from the archive.

replaceVersionLabel
          $Archive->replaceVersionLabel($newlabel,$oldlabel,[vcs opts]);

     Rename a version label in the archive

addFloatingVersionLabel
          $Archive->addFloatingVersionLabel($label,[vcs opts]);

     Create a floating version label for the archive.

transformVersionLabel
          $Archive->transformVersionLabel($label,[vcs opts])';

     Transform a specified version label to a floating version label.

deletePromoGroup
          $Archive->deletePromoGroup($group,[vcs opts]);

     Delete the promotion group from the archive.

addPromoGroup
          $Archive->deletePromoGroup($group:$rev,[vcs opts])';

     Add the archive, or promote it to, the named promotion group.

     Create a new archive

vcs
          $archive->vcs([opts][files]);

     Runs the VCS command against the archive, with opts as specified.

getAttributes
          $archive->getAttributes(@_);

     Populates and returns the archive object associated with the archive.
     This object is blessed into the VCS::PVCS::Attributes class.

attributes
          $archive->attributes;

     Returns the attributes object associated with the archive

COPYRIGHT
=========

   The PVCS module is Copyright (c) 1998 Bill Middleton.  All rights
reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

AUTHOR
======

   Bill Middleton, wjm@metronet.com

SUPPORT / WARRANTY
==================

   The VCS::PVCS modules are free software.

   *THEY COME WITHOUT WARRANTY OF ANY KIND.*

   Commercial support agreements for Perl can be arranged via The Perl
Clinic. See http://www.perl.co.uk/tpc for more details.

SEE ALSO
========

   VCS::PVCS::Project

Attributes class for for VCS::PVCS
**********************************

NAME
====

   VCS::PVCS::Attributes - Attributes class for for VCS::PVCS

SYNOPSIS
========

     use VCS::PVCS::Project;

     $proj = new VCS::PVCS::Project("ProjectName");

     $members = $proj->members(".*");

     foreach $f (@$members){
       $attrs = $f->getAttributes();
       print $attrs->Archive; # Archive name
       print $attrs->Workfile; # Workfile name
       print $attrs->Owner; # Owner of archive
       print $attrs->Archive_created; # Date archive created
       print $attrs->Last_trunk_rev; # Most recent trunk rev
       print $attrs->Locks; # current locks on all versions
       print $attrs->Groups; # current groups assoc with this archive
       print $attrs->Rev_count; # number of revisions
       print $attrs->Attributes; # attributes
       print $attrs->Version_labels; # version labels on this archive
       print $attrs->Description;  # checkin description
       print $attrs->history;      # history and comments

     }

DESCRIPTION
===========

   This class is intended for use as an companion to the VCS::PVCS::*
classes.  The Archive objects inherits Attribute methods, and augment them.

METHODS
=======

getAttributes
          print $attrs->getAttributes(1);

     repopulate the attibutes object

Archive
          print $attrs->Archive; # Archive name

B<Workfile
          print $attrs->Workfile; # Workfile name

B<Owner
          print $attrs->Owner; # Owner of archive

B<Archive_created
          print $attrs->Archive_created; # Date archive created

B<Last_trunk_rev
          print $attrs->Last_trunk_rev; # Most recent trunk rev

B<Locks
          print $attrs->Locks; # current locks on all versions

B<Groups
          print $attrs->Groups; # current groups assoc with this archive

B<Rev_count
          print $attrs->Rev_count; # number of revisions

B<Attributes
          print $attrs->Attributes; # attributes

B<Version_labels
          print $attrs->Version_labels; # version labels on this archive

B<Description
          print $attrs->Description;  # checkin description

B<history
          print $attrs->history;      # history and comments

COPYRIGHT
=========

   The PVCS module is Copyright (c) 1998 Bill Middleton.  All rights
reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

AUTHOR
======

   Bill Middleton, wjm@metronet.com

SUPPORT / WARRANTY
==================

   The VCS::PVCS modules are free software.

   *THEY COME WITHOUT WARRANTY OF ANY KIND.*

   Commercial support agreements for Perl can be arranged via The Perl
Clinic. See http://www.perl.co.uk/tpc for more details.

SEE ALSO
========

   VCS::PVCS::Project

Command class for for VCS::PVCS
*******************************

NAME
====

   VCS::PVCS::Commands - Command class for for VCS::PVCS

SYNOPSIS
========

     use VCS::PVCS::Project;

     $proj = new VCS::PVCS::Project("ProjectName");

   # Operate on every member in the project

     $proj->checkout("-V 1.7 -Y");
     $proj->checkin("-A foo,bar,baz -V 1.7");
     $proj->vlog("-BG foo");
     $proj->lock("mylabel");
     $proj->addFloatingVersionLabel("mylabel6");

   # OR

   # Operate on every archive in each folder

     $proj = new VCS::PVCS::Project("ProjectName");
     $folds = $proj->openFolders(".*");

     foreach $f (@$folds){
       $f->co("-Y -P -V 1.7");
       if(! $PVCSERR){
        $f->put("-A foo,bar,baz -V 1.7");
       }
       else{
         print $PVCSOUTPUT;
       }
       $f->put("-A foo,bar,baz -V 1.7");
       $f->history("-D 071363-091298");
       $f->unlock("1.7" );
       $f->addVersionLabel("mylabel2");
     }

   # OR

   # Operate on the projects archive objects separately

     $proj = new VCS::PVCS::Project("ProjectName");
     $members = $proj->members(".*");

     foreach $f (@$members){
       $f->co("-Y -P -V 1.7",$f->archive());

     if(! $PVCSERR){
       $f->put("-A foo,bar,baz -V 1.7 /path/to/archive.c_v");
     }
     else{
       print $PVCSOUTPUT;
     }
     $f->put("-A foo,bar,baz -V 1.7",$f->archive());
     $f->history("-D 071363-091298",$f->archive());
     $f->unlock("1.7" ,$f->archive());
     $f->addVersionLabel("mylabel2",$f->archive());
       }

   # OR

   # Operate on the folder's archive objects separately

     $folds = $proj->openFolders(".*");

     foreach $folder (@$folds){
       $members = $folder->members(".*");
       foreach $f (@$members){
         $f->co("-Y -P -V 1.7",$f->archive());
         if(! $PVCSERR){
           put("-A foo,bar,baz -V 1.7 /path/to/archive.c_v");
         }
         else{
           print $PVCSOUTPUT;
         }
         $f->co("-Y -P -V 1.7",$f->archive());
         $f->put("-A foo,bar,baz -V 1.7",$f->archive());
         $f->history("-D 071363-091298",$f->archive());
         $f->unlock("1.7" ,$f->archive());
         $f->addVersionLabel("mylabel2",$f->archive());
       }
     }

   # OR

   # Simple use of only this module

     use VCS::PVCS;   # You must still use the master module
     use VCS::PVCS::Commands qw(:all);

   # You MUST set these when using Commands by itself
$VCS::PVCS::PVCSMASTERCFG = "../../MASTER.CFG";
$VCS::PVCS::PVCSCURRPROJCFG = "../../examples.cfg";

   # Note the arguments may be all in one string, or separated by quotes

     checkout("-L","-V 1.7","-Y", "/path/to/archive.c_v");
     if(! $PVCSERR){
       put("-A foo,bar,baz -V 1.7 /path/to/archive.c_v");
     }
     else{
       print $PVCSOUTPUT;
     }

DESCRIPTION
===========

   Each time a command is run, the global values $PVCSERR and $PVCSOUTPUT
get set to errno and output respectively.

   This class can be used directly.  But it is intended for use as an ISA
for VCS::PVCS::* classes.  Folder, Project, and Archive objects inherit
Command methods, and augment them, to implement the appropriate actions on
each type of object.

   You *MUST *set the `$VCS::PVCS::PVCSMASTERCFG' and the
`$VCS::PVCS::PVCSCURRPROJCFG' to be the master configuration file, and the
project configuration file, respectively, when using this module by itself.

   If you wish to use this module directly, the Exporter makes most of the
symbols available when you `use VCS::PVCS'.  You should see the test cases
and the sample code above for more details.

METHODS
=======

get
          get([get opts] file(s));

checkout
     Convenience routine calls get();

co
     Convenience routine calls get();

put
          put([put opts] file(s));

     Checkin the named file.

checkin
     Convenience routine calls put();

ci
     Convenience routine calls put();

vdiff
          vdiff([vdiff opts]);

vlog
          vlog([vlog opts]);

log
     Convenience routine calls vlog();

history
     Convenience routine calls vlog();

lock
          lock([vcs opts] files)';

     Lock the named archive file(s).

unlock
          unlock([$label | $version],[vcs opts],file(s));

     Unlock the named files.

addVersionLabel
          addVersionLabel(label,[vcs opts],file(s));

     Add a version label to the named archive file(s).

deleteVersionLabel
          deleteVersionLabel(label,[vcs opts],file(s));

     Delete a version label to the named archive file(s).

replaceVersionLabel
          replaceVersionLabel($newlabel,$oldlabel,[vcs opts],files);

     Delete a version label to the named archive file(s).

transformVersionLabel
          transformVersionLabel(label,[vcs opts],file(s));

     Transform a version label to floating for the named archive file(s).

addFloatingVersionLabel
          addFloatingVersionLabel(label,[vcs opts],file(s));

     Create a floating version label for the named archive file(s).

deletePromoGroup
          deletePromoGroup($group,[vcs opts],file(s))';

     Delete the promotion group from the archive

addPromoGroup
          addPromoGroup(group:$rev,[vcs opts],files(s))';

     Add the promotion group to the archive (at rev)

createArchive
          createArchive([vcs opts],file(s))';

     Create a new archive in $file.

vcs
          vcs([opts][files])';

     Run vcs by itself.

AUTHOR
======

   Bill Middleton, wjm@metronet.com

COPYRIGHT
=========

   The PVCS module is Copyright (c) 1998 Bill Middleton.  All rights
reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SUPPORT / WARRANTY
==================

   The VCS::PVCS modules are free software.

   *THEY COME WITHOUT WARRANTY OF ANY KIND.*

   Commercial support agreements for Perl can be arranged via The Perl
Clinic. See http://www.perl.co.uk/tpc for more details.

SEE ALSO
========

   VCS::PVCS::Project

Folder class for for VCS::PVCS.
*******************************

NAME
====

   VCS::PVCS::Folder - Folder class for for VCS::PVCS.

SYNOPSIS
========

     use VCS::PVCS::Project;

     $project = new VCS::PVCS::Project("ProjectName");

   # return ref to array of all folders in the project with SCRIPTS in the
name

     $folds = $project->openFolders("SCRIPTS");
     foreach $folder (@$folds){
     	$folder->checkout;  # Checkout all files in the folder to the WD
     }

DESCRIPTION
===========

   This class implements a set of methods for operating on the
directories, archive files, and workfiles which correspond to PVCS
folders.  It should not ordinarily be loaded directly, but rather, is an
ISA to the VCS::PVCS::Project class, as shown above.

METHODS
=======

openFolders
          $folds = $project->openFolders("FOO"); # folders with FOO in the name
          @folds = $project->openFolders(".*");   # ALL folders in the project
          $folds = $project->openFolders("New Folder");  # create the folder

     Return a ref to array (or an array) of all folders in the project with
     FOO in the name.  If no match is found, the folder is created.  The
     objects in this array are blessed into the VCS::PVCS::Folder class.
     openFolders() accepts partial name matches in the single argument.
     (Names are matched with grep(//))

members
          @members = $folder->members("regexp");

     Return an array (or ref to array) of blessed Archive objects which
     reside within the folder, and match the regexp.  If no regexp is
     passed in, then return all of the archives in the project.  These
     objects can then call the methods in the VCS::PVCS::Archive class.

*newArchive *
          $Folder->newArchive($file,$archivedir);

     Create a new archive and place a copy into the folder.

getWD
          $WorkingDir =  $folder->getWD;

     Return the working directory for the folder.

getAttributes
          $Folder->getAttributes([vcs opts])';

     Populate the attributes object for each archive object member of the
     folder.

get
          $Folder->get([get opts]);

     Checkout all of the archive members in the folder to the the folders'
     working directory.  Use opts to change default actions.

checkout
          Convenience routine calls $folder->get()

co
          Convenience routine calls $folder->get()

put
          $Folder->put([put opts]);

     Checkin all of the archive members of the folder.  Use opts to change
     default actions.

checkin
          Convenience routine calls put()

ci
          Convenience routine calls put()

vlog
          $Folder->vlog([vlog opts]);

     Takes a full vlog on all of the archive members in the folder.  Use
     opts to change default actions.  Result in $PVCSOUTPUT.

log
          Convenience routine calls vlog()

history
          Convenience routine calls vlog()

lock
          $Folder->lock($label|$version,[vcs opts]);

     Locks the named revision (or rev spec'd by label) for all archive
     members in the folder.  Use opts to change default action.

unlock
          $Folder->unlock($label|$version,[vcs opts]);

     unlocks the named revision (or rev spec'd by label) for all archive
     members of the folder.  Use opts to change default action.

addVersionLabel
          $Folder->addVersionLabel($label,[vcs opts]);

     Create a new sticky version label for the all of the archive members
     of the folder (optionally with :<rev>).  Use opts for additonal
     params.

deleteVersionLabel
          $Folder->deleteVersionLabel($label,[vcs opts]);

     Delete a version label from all of the archive members of the folder.

replaceVersionLabel
          $Folder->replaceVersionLabel($newlabel,$oldlabel,[vcs opts]);

     Rename a version label in all of the archive members of the folder.

addFloatingVersionLabel
          $Folder->addFloatingVersionLabel($label,[vcs opts]);

     Create a floating version label for all of the archive members of the
     folder.

transformVersionLabel
          $Folder->transformVersionLabel($label,[vcs opts])';

     Transform a specified version label to a floating version label for
     all of  the archive members of the folder.

deletePromoGroup
          $Folder->deletePromoGroup($group,[vcs opts]);

     Delete the promotion group from the archive for all archive members
     in the folder.

addPromoGroup
          $Folder->deletePromoGroup($group:$rev,[vcs opts])';

     Add the archive, or promote it to, the named promotion group.  For
     all of the archive members in the folder.

     Create a new archive

vcs
          $Folder->vcs([opts][files]);

     Run vcs in the folder's CWD, with opts.

getAttributes
          $Folder->getAttributes(@_);

     Populates and returns the archive object associated with the archive
     for all archives in the folder.

     This object is blessed into the VCS::PVCS::Attributes class.

COPYRIGHT
=========

   The PVCS module is Copyright (c) 1998 Bill Middleton.  All rights
reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

AUTHOR
======

   Bill Middleton, wjm@metronet.com

SUPPORT / WARRANTY
==================

   The VCS::PVCS modules are free software.

   *THEY COME WITHOUT WARRANTY OF ANY KIND.*

   Commercial support agreements for Perl can be arranged via The Perl
Clinic. See http://www.perl.co.uk/tpc for more details.

SEE ALSO
========

   VCS::PVCS::Project

Standard PVCS Project class for for VCS::PVCS
*********************************************

NAME
====

   VCS::PVCS::Project - Standard PVCS Project class for for VCS::PVCS

SYNOPSIS
========

     use VCS::PVCS::Project;
     $project = new VCS::PVCS::Project("Project Name");

     $folds = $project->openFolders("SCRIPTS");
     foreach $folder (@$folds){
           $folder->checkout;  # Checkout all files in the folder to the WD
     }

DESCRIPTION
===========

   Inherit from VCS::PVCS::* to get all necessary methods to parse master
config file, as well as the master pvcsproj.pub to learn about all
projects in the PVCSROOT.

   Provides methods to operate on an entire project's files all\ at once.
You can checkout, checkin, get history, or use the VCS command to perform
many different archive operations on all the files in the project.

METHODS
=======

new
          new VCS::PVCS::Project("NAME", {'WKDIR' => $wdir });

     Open an project in PVCS.  If the project doesn't exist, an attempt is
     made to create it.  If an VCS::PVCS object is not passed in, then the
     superclass routines from VCS::PVCS are called to parse ISLVINI,
     PVCSPROJ files, and store global information, relevant to all
     projects, from MASTER.CFG. Then open and parse project-specific files
     (pvcsfold.pub) to learn about all folders and documents within the
     project.

     Pass the hashref with WKDIR to specify a working directory for the
     entire project.  This method also creates the projects' control
     files, project.cfg, and control directory.

     Returns a project object.

members
          @members = $project->members("regexp");

     Return an array (or ref to array) of blessed Archive objects which
     match the regexp.  If no regexp is passed in, then return all of the
     archives in the project.  These objects can then call the methods in
     the VCS::PVCS::Archive class.

DESTROY
     When the Project object goes out of scope (e.g. when the program
     finishes), the destroyer checks the list of archive directories which
     have been added to the project, and saves a new config file if
     appropriate.

     *NOTE!  YOU SHOULD DISABLE THIS FEATURE IF YOU ARE USING CONDITIONAL
     CONFIGURATION OPTIONS IN THE PROJECT CONFIG FILES AROUND VCSDIR.
     THIS FEATURE MAY BE DISABLED BY TURNING ON $PVCSDONTSAVE in
     VCS::PVCS.pm.*

newArchive
          $project->newArchive()

     Create a new archive in the project. Normally, this method is called
     by $Folder->newArchive, but if you, for some reason, dont use PVCS
     folders, then you'll need to call this directly to create a new
     archive.

     =item *copyProject*

     Sorry, not copying projects in this release

deleteProject
     Sorry, not deleting projects in this release

lockProject
     Sorry, not locking projects in this release

get
          $Project->get([get opts]);

     Checkout all of the archive members in the project to the the
     project's working directory, or CWD if WD is not specified in
     pvcsproj.pub.  Use opts to change default actions.

checkout
          Convenience routine calls $Project->get()

co
          Convenience routine calls $Project->get()

put
          $Project->put([put opts]);

     Checkin all of the archive members of the project from the projects'
     WD or CWD.  Use opts to change default actions.

checkin
          Convenience routine calls put()

ci
          Convenience routine calls put()

vlog
          $Project->vlog([vlog opts]);

     Takes a full vlog on all of the archive members in the project.  Use
     opts to change default actions.  Result in $PVCSOUTPUT.

log
          Convenience routine calls vlog()

history
          Convenience routine calls vlog()

lock
          $Project->lock($label|$version,[vcs opts]);

     Locks the named revision (or rev spec'd by label) for all archive
     members in the project.  Use opts to change default action.

unlock
          $Project->unlock($label|$version,[vcs opts]);

     unlocks the named revision (or rev spec'd by label) for all archive
     members of the project.  Use opts to change default action.

addVersionLabel
          $Project->addVersionLabel($label,[vcs opts]);

     Create a new sticky version label for the all of the archive members
     of the project (optionally with :<rev>).  Use opts for additonal
     params.

deleteVersionLabel
          $Project->deleteVersionLabel($label,[vcs opts]);

     Delete a version label from all of the archive members of the project.

replaceVersionLabel
          $Project->replaceVersionLabel($newlabel,$oldlabel,[vcs opts]);

     Rename a version label in all of the archive members of the project.

addFloatingVersionLabel
          $Project->addFloatingVersionLabel($label,[vcs opts]);

     Create a floating version label for all of the archive members of the
     project.

transformVersionLabel
          $Project->transformVersionLabel($label,[vcs opts])';

     Transform a specified version label to a floating version label for
     all of  the archive members of the project.

deletePromoGroup
          $Project->deletePromoGroup($group,[vcs opts]);

     Delete the promotion group from the archive for all archive members
     in the project.

addPromoGroup
          $Project->deletePromoGroup($group:$rev,[vcs opts])';

     Add the archive, or promote it to, the named promotion group, for all
     of the archive members in the project.

     Create a new archive

vcs
          $Project->vcs([opts][files]);

     Run vcs in the project's WD, with opts.

getAttributes
          $Project->getAttributes(@_);

     Populates and returns the archive object associated with the archive
     for all archives in the project.

     This object is blessed into the VCS::PVCS::Attributes class.

AUTHOR
======

   Bill Middleton, wjm@metronet.com

COPYRIGHT
=========

   The PVCS module is Copyright (c) 1998 Bill Middleton.  All rights
reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SUPPORT / WARRANTY
==================

   The VCS::PVCS modules are free software.

   *THEY COME WITHOUT WARRANTY OF ANY KIND.*

   Commercial support agreements for Perl can be arranged via The Perl
Clinic. See http://www.perl.co.uk/tpc for more details.

SEE ALSO
========

   perl(1).

module for access to a VCS version
**********************************

NAME
====

   VCS::Version - module for access to a VCS version

SYNOPSIS
========

     use VCS;
     die "Usage: $0 file version\n" unless @ARGV == 2;
     my $version = VCS::Version->new(@ARGV);
     print "Methods of \$version:\n",
         "name: ", $version->name, "\n",
         "author: ", $version->author, "\n",
         "version: ", $version->version, "\n",
         ;

DESCRIPTION
===========

   VCS::Version abstracts a single revision of a file under version
control.

METHODS
=======

   Methods marked with a "*" are not yet finalised/implemented.

VCS::Version->create_new(@version_args) *
-----------------------------------------

   `@version_args' is a list which will be treated as a hash, with
contents as follow:

     @version_args = (
         name    => 'a file name',
         version => 'an appropriate version identifier',
         tags    => [ 'A_TAG_NAME', 'SECOND_TAG' ],
         author  => 'the author name',
         reason  => 'the reason for the checkin',
         text    => 'either literal text, or a ref to the filename',
     );

   This is a pure virtual method, which must be over-ridden, and cannot be
called directly in this class (a die will result).

VCS::Version->new($file, $version)
----------------------------------

   $file is a filename, absolute or relative. `$version' is a version
number, or tag. Returns an object of class `VCS::Version', or undef if it
fails. Implementation classes must be careful not to return an object
unless they mean it.

$version->name
--------------

   Returns the $file argument to new.

$version->version
-----------------

   Returns the `$version' argument to new.

$version->tags
--------------

   Returns a list of tags applied to this version.

$version->text
--------------

   Returns the text of this version of the file.

$version->diff($other_version)
------------------------------

   Returns the differences (in `diff -u' format) between this version and
the other version. Currently, the other version must also be a
`VCS::Version' object.

$version->author
----------------

   Returns the name of the user who checked in this version.

$version->date
--------------

   Returns the date this version was checked in.

$version->reason
----------------

   Returns the reason given on checking in this version.

SEE ALSO
========

   See VCS.

COPYRIGHT
=========

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

read and write hashes with VMS::IndexedFile.
********************************************

NAME
====

   VMS::FlatFile - read and write hashes with VMS::IndexedFile.

SYNOPSIS
========

Standalone
----------

     # Load the module
     use VMS::FlatFile;

     # Create an instance
     # args - file name, access (ro=0, rw=1), format, key number
     my $file = new VMS::FlatFile 'disk$user01:[user]file.dat', 0,
     			    [ 'field1:a10', 'field2:a16' ], 0;

     # Read a hash
     my $hashref = $file->get($key);
     # Write a hash
     my $sts = $file->put($hashref);
     # Delete a record
     $sts = $file->delete($key);

As a Base Class
---------------

     # name your derived class
     package MyFile;

     # Load the module and derive
     use VMS::FlatFile;
     use var qw(@ISA);
     @ISA = qw(VMS::FlatFile);
     1;

     # override new
     sub new {
         my $class = shift;
     	my $self = {};
     	bless $self,$class;
     	# default to read only
     	my $access = shift || 0;
     	# use key 0
     	my $krf = shift || 0;
     	$self->_initialize('disk:[dir]filename.type', $access,
     		[ 'field1:a10', 'field2:a16' ], $krf);
     	return $self;
     }

     package main;

     # create an instance
     my $file = new MyFile;
     my $hashref = $file->get('keyvalue');

DESCRIPTION
===========

   VMS::FlatFile combines VMS::IndexedFile and Data::FixedFormat to make
it possible to read and write hashes to VMS indexed files.

   First, load the module:

     use VMS::FlatFile;

   Next, create an instance:

     my $file = new VMS::FlatFile 'disk$user01:[user]file.dat', 0,
     			    [ 'field1:a10', 'field2:a16' ], 0;

   The new method accepts four arguments:

filename
     The filename argument is passed directly to VMS::IndexedFile.

access
     If access is true, the file is opened read/write.  If false the file
     is opened read only.

format
     The format argument is used to construct a Data::FixedFormat instance
     for the file.  This argument is passed directly to
     Data::FixedFormat::new.

key of reference
     This argument is passed to VMS::IndexedFile to select a key of
     reference.  If not specified or if specified as 0, the file's primary
     key is used.  Specify 1 for the first alternate key, etc.

   To read records, use the get method:

     my $hashref = $file->get($key);

   get returns a reference to a hash created by
Data::FixedFormat::unformat.

   get accepts one argument which is the key of the record to be read.  If
specified as the null string, the next sequential record is read from the
file.

   To write records, use the put method:

     my $sts = $file->put($hashref);

   The status returned by put comes from VMS::IndexedFile::store.  The
lone argument is a reference to a hash which is converted into a file
buffer with Data::FixedFormat::format and written to the file.

   To delete records, use the delete method:

     my $sts = $file->delete($key);

   The record with the specified key value will be deleted from the file.

   The easiest way to use VMS::FlatFile as a base class would be to write a
derived module that provides the filename and format arguments for each
file you need to access.  To do this, override the new method with a
routine like the following:

     package MyFile;
     use VMS::FlatFile;
     use vars qw(@ISA);
     @ISA = qw(VMS::FlatFile);

     sub new {
         my $class = shift;
     	my $self = {};
     	bless $self,$class;
     	# default to read only
     	my $access = shift || 0;
     	# use key 0
     	my $krf = shift || 0;
     	$self->_initialize('disk:[dir]filename.type', $access,
     		[ 'field1:a10', 'field2:a16' ], $krf);
     	return $self;
     }

   The _initialize routine takes the same arguments as new.  This new
constructor takes two arguments; the access mode (true for read/write) and
the key of reference.

   VMS::FlatFile instances contain the attributes:

File
     This is the hash bound to the file with tie.  Records are read from
     the file by reading attributes (i.e., file keys) from this hash.

Handle
     This attribute receives the result from the call to tie which
     connects the VMS file to the hash.

Formatter
     The Formatter attribute is an instance of a Data::FixedFormat which is
     used for converting between file records and hashes.

AUTHOR
======

   VMS::FlatFile was written by Thomas Pfau <pfau@eclipse.net>
http://www.eclipse.net/~pfau/.

COPYRIGHT
=========

   Copyright (C) 2000 Thomas Pfau.  All rights reserved.

   This module 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 library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
License for more details.

   You should have received a copy of the GNU General Public License along
with this progam; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.

Specification independent VRML methods (1.0, 2.0, 97)
*****************************************************

NAME
====

   VRML - Specification independent VRML methods (1.0, 2.0, 97)

SYNOPSIS
========

     use VRML;

     $vrml = new VRML(2);
     $vrml->browser('Cosmo Player 2.0','Netscape');
     $vrml->at('-15 0 20');
     $vrml->box('5 3 1','yellow');
     $vrml->back;
     $vrml->print;
     $vrml->save;

     OR with the same result

     use VRML;

     VRML->new(2)
     ->browser('Cosmo Player 2.0','Netscape')
     ->at('-15 0 20')->box('5 3 1','yellow')->back
     ->print->save;

DESCRIPTION
===========

   These modules were conceived for the production of VRML worlds on WWW
servers via GCI and/or for generating abstract worlds. They are the
clarity of Perl scripts with VRML code to increase and (hopefully) for
VRML beginners the entrance in VRML facilitate. In the following the
modules are described briefly.

VRML::Base
     contains base functionality such as a producing, an outputting and
     saving. It represents the base class for all other modules

VRML::VRML1
     combines several VRML 1.0 nodes into complex methods - e.g. geometric
     shapes inclusive there material. This module accepts angle data in
     degrees and as material color names. The methods have the same names
     as in the VRML specification (if meaningfully), are however in lower
     case.

VRML::VRML1::Standard
     implemented only the VRML 1.0 nodes. All method names are identical
     (in the way of writing) with those of the VRML specification. The
     parameters are arranged after the frequency of their use (subjective
     estimate). This module is possibly omitted in the next version. The
     production of the VRML nodes takes over then VRML::Base.

VRML::VRML2
     combines several VRML 2.0 nodes into complex methods - e.g. geometric
     shapes inclusive there material. This module accepts angle data in
     degrees and as material color names. The methods have the same names
     as in the VRML specification (if meaningfully), are however in lower
     case. The names are also as far as possible identical to those of the
     module VRML::VRML1. Thus the user between the VRML versions which can
     be produced can switch.

     Contains for example $in{VRML} '1' or '2' (e.g. via CGI), then only
     the following line at the start of the Perl script must be inserted.

          new VRML($in{'VRML'})

VRML::VRML2::Standard
     implemented only the VRML 2.0 nodes. All method names are identical
     (in the way of writing) with those the VRML specification. The
     parameters are arranged after the frequency of their use (subjective
     estimate) This module is possibly omitted in the next version. The
     production of the VRML nodes takes over then VRML::Base.

VRML::Color
     contains the color names and conversion functions.

   The VRML methods are at present identically in the modules
VRML::VRML1.pm and VRML::VRML2.pm implemented. The basic methods like new,
print or save are in the module VRML::Base described.

DESCRIPTION
===========

   The methods of this module are easier to use than the VRML::*::Standard
methods because the methods are on a higher level. For example you can use
X11 color names and it's simple to apply textures to an object. All angles
could be assigned in degrees.

   If a method does the same like its VRML pedant then it has the same
name but in lowercase (e.g. box). The open part of a group method ends
with a _begin (e.g. anchor_begin). The closing part ends with an _end (e.g.
anchor_end). For a detailed description how the generated node works, take
a look at the VRML 2.0 specification on VAG.

   Following methods are currently implemented. (Values in '...' must be
strings!)

Groups
------

begin
     `begin('comment')'

     Before you use an geometry or transform method please call this
     method.  It's necessary to calculate something at the end.

     Example:

          new VRML
          ->begin
            ->at('0 0.1 -0.3')
          	->sphere(1,'red')
            ->back
          ->end
          ->print;

end
     `end('comment')'

     After end there should no geometry or transformation. This method
     completes the calculations of viewpoints etc.

at('type=value','type=value', ...)
     is the short version of the method transform_begin. It has the same
     parameters as transform_begin.

     Example:

          $vrml
          ->at('0 2 0')
            ->sphere(0.5,'red')
          ->back

back
     is the short version of the method transform_end.

anchor_begin
     `anchor_begin('url', 'description', 'parameter', 'bboxSize',
     'bboxCenter')'

          url         MFString []
          description SFString ""
          parameter   MFString []
          bboxSize    SFVec3f  undef
          bboxCenter  SFVec3f  '0 0 0'

     Example:

          $vrml
          ->anchor_begin('http://www.gfz-potsdam.de/~palm/vrmlperl/',
            'VRML-Perl Moduls', 'target=_blank')
            ->sphere(1,'blue')
          ->anchor_end;

anchor_end
     close anchor_begin.

billboard_begin
     `billboard_begin('axisOfRotation', 'bboxSize', 'bboxCenter')'

          axisOfRotation  SFVec3f  '0 1 0'
          bboxSize        SFVec3f  undef
          bboxCenter      SFVec3f  '0 0 0'

billboard_end
     close billboard_begin.

collision_begin
     `collision_begin(collide, proxy, 'bboxSize', 'bboxCenter')'

          collide    SFBool  1
          proxy      SFNode  NULL
          bboxSize   SFVec3f undef
          bboxCenter SFVec3f '0 0 0'

     Example:

          $vrml
          ->collision_begin(1, sub{$vrml->box('5 1 0.01')})
            ->text('collide','yellow',1,'MIDDLE')
          ->collision_end

collision_end
     close collision_begin.

group_begin('comment')
     Example:

          $vrml
          ->group_begin
            ->sphere(1,'red')
          ->group_end

group_end
     close `group_begin'.

lod_begin
     `lod_begin('range', 'center')'

          range  MFFloat []
          center SFVec3f '0 0 0'

     Example:

          $vrml
          ->lod_begin('30')
            ->text('gut lesbar')
            ->group_begin->group_end # leere Gruppe
          ->lod_end

lod_end
     close lod_begin.

switch_begin
     `switch_begin(whichChoice)'

          whichChoice SFInt32 -1

switch_end
     close switch_begin.

transform_begin
     F<transform_begin('type=value','type=value', ...)

     *Where type can be:*

          t = translation
          r = rotation
          c = center
          s = scale
          so = scaleOrientation
          bbs = bboxSize
          bbc = bboxCenter

     Example:

          $vrml
          ->transform_begin('t=0 1 0','r=180')
            ->cone('0.5 2','red')
          ->transform_end

transform_end
     close transform_begin.

inline
     `inline('url', 'bboxSize', 'bboxCenter')'

          url        MFString []
          bboxSize   SFVec3f  undef
          bboxCenter SFVec3f  '0 0 0'

Independent Methods
-------------------

background
     `background( frontUrl => '...', leftUrl => '...', rightUrl => '...',
     backUrl => '...', bottomUrl => '...', topUrl => '...', skyColor =>
     '...', skyAngle => '...', groundColor => '...', groundAngle => '...'
     )'

          frontUrl    MFString []
          leftUrl     MFString []
          rightUrl    MFString []
          backUrl     MFString []
          bottomUrl   MFString []
          topUrl      MFString []
          skyColor    MFColor  ['0 0 0']
          skyAngle    MFFloat  []
          groundColor MFColor  []
          groundAngle MFFloat  []

     This is a parameter hash. Only use the parts you need.

     Example:

          $vrml->background(skyColor => 'lightblue',
                            frontUrl => 'http://www.yourdomain.de/bg/berge.gif');

backgroundcolor
     `backgroundcolor('skyColor', 'groundColor')'

          skyColor     SFColor  '0 0 0'
          groundColor  SFColor  '0 0 0'

     is the short version of background. It specifies only colors.

     Example:

          $vrml->backgroundcolor('lightblue');

backgroundimage
     `backgroundimage('url')'

          url SFString ""

     is the short version of background. It needs only one image. The
     given Url will assigned to all parts of the background cube.

     Example:

          $vrml->backgroundimage('http://www.yourdomain.de/bg/sterne.gif');

title
     `title('string')'

          string SFString ""

     Example:

          $vrml->title('Meine virtuelle Welt');

info
     `info('string')'

          string MFString []

     Example:

          $vrml->info('letzte Änderung: 8.05.1997');

worldinfo
     `worldinfo('title', 'info')'

          title  SFString ""
          info   MFString []

     combines title and info.

navigationinfo
     `navigationinfo('type', speed, headlight, visibilityLimit,
     avatarSize)'

          type         MFEnum     ['WALK', 'ANY'] # ANY, WALK, FLY, EXAMINE, NONE
          speed        SFFloat    1.0
          headlight    SFBool     1
          visibilityLimit SFFloat 0.0
          avatarSize   MFFloat    [0.25, 1.6, 0.75]

     Example:

          $vrml->navigationinfo('WALK', 1.5, 0, 1000);

viewpoint_begin
     starts the hidden calculation of viewpoint center and distance for the
     method `viewpoint_auto_set()'. It collects also the viepoints to place
     they in the first part of the VRML source.

viewpoint
     `viewpoint('description', 'position', 'orientation', fieldOfView,
     jump)'

          description SFString          ""
          position    SFVec3f           0 0 10
          orientation SFRotation/SFEnum 0 0 1 0 # FRONT, LEFT, BACK, RIGHT, TOP, BOTTOM
          fieldOfView SFFloat           45 # Grad
          jump        SFBool            1

     Example:

          $vrml->viewpoint('Start','0 0 0','0 0 -1 0',60);

     is the same like

          $vrml->viewpoint('Start',undef,'FRONT',60);

viewpoint_set
     `viewpoint_set('center', distance, fieldOfView, avatarSize)'

          center       SFVec3f '0 0 0'
          distance     SFFloat 10
          fieldOfView  SFFloat 45 # Grad
          avatarSize   MFFloat [0.25, 1.6, 0.75]

     places six viewpoints around the center.

viewpoint_auto_set
     sets all parameters of viewpoint_set automatically.

viewpoint_end
     close viewpoint_begin.

Shapes
------

box
     `box('size', 'appearance')'

          size       SFVec3f  '2 2 2' # width height depth
          appearance SFString ""      # see Appearance

cone
     `cone('bottomRadius height', 'appearance')'

          bottomRadius height SFVec2f '1 2'
          appearance          SFString "" # see Appearance

cylinder
     `cylinder('radius height', 'appearance')'

          radius height SFVec2f  '1 2'
          appearance    SFString "" # see Appearance

line
     `line('from', 'to', radius, 'appearance', 'path')'

          from        SFVec3f   ""
          to          SFVec3f   ""
          radius      SFFloat   0 # 0 = haarline
          appearance  SFString  ""
          path        SFEnum    "" # XYZ, XZY, YXZ, YZX, ZXY, ZYX

     draws a line (cylinder) between two points with a given radius. If
     radius is '0' only a hairline will be printed. The last parameter
     specifies the devolution along the axes. An empty stands for direct
     connection.

     Example:

          new VRML(2)
          ->begin
            ->line('1 -1 1', '-3 2 2', 0.03, 'red', 'XZY')
            ->line('1 -1 1', '-3 2 2', 0.03, 'white')
          ->end
          ->print;

pyramid
     `pyramid('size', 'appearance')'

          size       SFVec3f  '2 2 2' # width height depth
          appearance SFString ""      # see Appearance

     Example:

          $vrml->pyramid('1 1 1','blue,green,red,yellow,white');

sphere
     `sphere(radius, 'appearance')'

          radius     SFFloat  1
          appearance SFString "" # see Appearance

elevationgrid
     `elevationgrid(height, color, xDimension, zDimension, xSpacing,
     zSpacing, creaseAngle, colorPerVertex, solid)'

          height          MFFloat  []
          color           MFColor  [] # resp. material and color
          xDimension      SFInt32  0
          zDimension      SFInt32  0
          xSpacing        SFFloat  1.0
          zSpacing        SFFloat  1.0
          creaseAngle     SFFloat  0
          colorPerVertex	 SFBool   1
          solid           SFBool   0

     If color is not a reference of an ARRAY it would be assumed that color
     is the appearance.

     Example:

          open(FILE,"<height.txt");
          my @height = <FILE>;
          open(COL,"<color.txt");
          my @color = <COL>;
          $vrml->navigationinfo(["EXAMINE","FLY"],200)
               ->viewpoint("Top","1900 6000 1900","TOP")
               ->elevationgrid(\@height, \@color, undef, undef, 250, undef, 0)
          	 ->print;

text
     `text('string', 'appearance', 'font', 'align')'

          string     MFString []
          appearance SFString "" # see Appearance
          font       SFString '1 SERIF PLAIN'
          align      SFEnum   'BEGIN' # BEGIN, MIDDLE, END

billtext
     `billtext('string', 'appearance', 'font', 'align')'

          string     MFString []
          appearance SFString "" # see Appearance
          font       SFString '1 SERIF PLAIN'
          align      SFEnum   'BEGIN' # BEGIN, MIDDLE, END

     does the same like method text, but the text better readable.

Appearance
     `appearance('type=value1,value2 ; type=...')'

     The appearance method specifies the visual properties of geometry by
     defining the material and texture. If more than one type is needed
     separate the types by semicolon. The types can choosen from the
     following list.

     Note: one character mnemonic are colors       two characters mnemonic
     are values in range of [0..1]       more characters are strings like
     file names or labels

          d = diffuseColor
          e = emissiveColor
          s = specularColor
          ai = ambientIntensity
          sh = shininess
          tr = transparency
          tex = texture filename,wrapS,wrapT
          name = names the MovieTexture node (for a later route)

     The color values can be strings (X11 color names) or RGB-triples. It
     is possible to reduce the intensity of colors (names) by appending a
     two digit value (percent). This value must be separated by an
     underscore (_) or a percent symbol (%). Note: Do not use a percent
     symbol in URL's. It would be decoded in an ascii character.

     Sample (valid color values): 	'1 1 0' # VRML standard 	'FFFF00'
     or 'ffff00', '255 255 0', 'yellow'

     or reduced to 50% 	'.5 .5 .5' # VRML standard 	'808080', '128 128 0',
     'yellow%50' or 'yellow_50'

     For a list of *X11 color names* take a look at VRML::Color

Misc
----

directionallight
     `directionallight('direction', intensity, ambientIntensity, 'color',
     on)'

          direction         SFVec3f  '0 0 -1'
          intensity         SFFloat  1
          ambientIntensity  SFFloat  1
          color             SFColor  '1 1 1' #weiß
          on                SFBool   1

     Example:

          $vrml->directionallight("0 0 -1", 0.3);

sound
     `sound('url','description', 'location', 'direction', intensity, loop,
     pitch)'

          url         MFString []
          description SFString ""
          location    SFVec3f  '0 0 0'
          direction   SFVec3f  '0 0 1'
          intensity   SFFloat  1.0
          loop        SFBool   0
          pitch       SFFloat  1.0

def
     `def('name')'

          name SFString ""

     Example:

          $vrml->def('RedSphere')->sphere(1,'red')

use
     `use('name')'

          name SFString ""

     Example:

          $vrml->use('RedSphere')

route
     `route('from','to')'

          FROM.feldname SFString ""
          TO.feldname   SFString ""

Interpolators
-------------

interpolator
     `interpolator('name','type',[keys],[keyValues])'

          name      SFString ""
          type      SFEnum   "" # Color, Coordinate, Normal, Orientation,
                                # Position und Scalar
          keys      MFFloat  [] # [0,1]
          keyValues MF...    [] # Type of Interpolator

Sensors
-------

cylindersensor

     `cylindersensor('name',maxAngle,minAngle,diskAngle,offset,autoOffset,enabled)'

          name       SFString ""
          maxAngle   SFFloat  undef
          minAngle   SFFloat  0
          diskAngle  SFFloat  15
          offset     SFFloat  0
          autoOffset SFBool   1
          enabled    SFBool   1

planesensor

     `planesensor('name',maxPosition,minPosition,offset,autoOffset,enabled)'

          name         SFString  ""
          maxPosition  SFVec2f  undef
          minPosition  SFVec2f  '0 0'
          offset       SFVec3f  '0 0 0'
          autoOffset   SFBool  1
          enabled      SFBool  1

proximitysensor
     `proximitysensor('name',size,center,enabled)'

          name    SFString ""
          size    SFVec3f  '0 0 0'
          center  SFVec3f  '0 0 0'
          enabled SFBool   1

spheresensor
     `spheresensor('name',offset,autoOffset,enabled)'

          name       SFString   ""
          offset     SFRotation '0 1 0 0'
          autoOffset SFBool     1
          enabled    SFBool     1

timesensor
     `timesensor('name',cycleInterval,loop,startTime,stopTime,enabled)'

          name          SFString ""
          cycleInterval SFFloat  1
          loop          SFBool   0
          startTime     SFFloat  0
          stopTime      SFFloat  0
          enabled       SFBool   1

touchsensor
     `touchsensor('name',enabled)'

          name    SFString ""
          enabled SFBool   1

     Example:

          $vrml
          ->begin
          	->touchsensor('Switch')
          	->sphere(1,'white')
          	->def('Light')->directionallight("", 1, 0, 'red', 0)
          	->route('Switch.isActive', 'Light.on')
          ->end
          ->print->save;

visibitysensor
     `visibitysensor('name',size,center,enabled)'

          name    SFString ""
          size    SFVec3f  '0 0 0'
          center  SFVec3f  '0 0 0'
          enabled SFBool   1

SEE ALSO
========

   VRML

   VRML::VRML2::Standard

   VRML::Base

   http://www.gfz-potsdam.de/~palm/vrmlperl/ for a description of
`VRML-modules' and how to obtain it.

AUTHOR
======

   Hartmut Palm `<palm@gfz-potsdam.de>'

   Homepage http://www.gfz-potsdam.de/~palm/

common basic methods for VRML in/output
***************************************

NAME
====

   VRML::Base.pm - common basic methods for VRML in/output

SYNOPSIS
========

     use VRML::Base;

DESCRIPTION
===========

   Following methods are implemented.

new
     new

     Creates a new VRML scene object.

comment
     `comment('string')'

     Inserts a single comment line at the current position.  You don't
     need to write the # in front. If no string is given, the method
     inserts only a #.

insert
     `insert('string')'

     Inserts the string at the current position in the VRML scene.

insert__DATA__
     `insert__DATA__()'

     Inserts the text block after __DATA__ of the current perl script in
     the VRML scene. Remember there are two underscores in front and at
     the end of the word DATA.

include
     `include('filename')'

     Inserts the VRML code of the specified file in the current scene.

print
     `print('mime', 'pipe')'

     Prints the VRML scene to STDOUT. If *mime* (bool) is given, this
     method prints the scene to STDOUT with the Content-type of the
     current scene. If pipe is given, then first the stream is send to the
     pipe and after that to STDOUT. This is usefull to compress the VRML
     code with GNU-ZIP.

     Example:

     1.  *$vrml->print*

     2.  *$vrml->print(1, 'gzip -f9')*

save
     `save('filename', 'pipe')'

     Saves the VRML code to the specified name in filename. If no filename
     is given, this method uses the name of the perl script and changes
     the extension against `.wrl'. If pipe is given, then first the stream
     is send to the pipe and after that to STDOUT. This is usefull to
     compress the VRML code with GNU-ZIP.

     Example:

     1.  *$vrml->save*

     2.  *$vrml->save(undef, 'gzip -f9')*

     3.  *$vrml->save('myScene.wrl')*

as_string
     as_string

     Returns the VRML scene as string. Possible it uses too much memory to
     build the string.

Internals
=========

   You don't need the following 'native' methods.  If yet, tell it me and
I'll describe it in the next version.

debug
     debug

_init
     `_init('VRML')'

_add
     _add

_trim
     _trim

_swap
     _swap

_put
     _put

_row
     _row

_pos
     _pos

_format
     _format

AUTHOR
======

   Hartmut Palm `<palm@gfz-potsdam.de>'

perl module to implement a VRML97 browser
*****************************************

NAME
====

   VRML::Browser - perl module to implement a VRML97 browser

SYNOPSIS
========

   Use the command-line interface (`freewrl' in this node), or inside Perl:

     use VRML::Browser;

     $b = VRML::Browser->new();

     $b->load_file($url);
     $b->load_file($url,$base_url);
     $b->load_string("Shape { geometry ....", $base_url);

     $b->eventloop();

     # VRML Browser API
     $name = 	$b->getName();
     $version = 	$b->getVersion();
     $speed =	$b->getCurrentSpeed();
     ...

     # The rest of the API may still change and is not documented
     # here. If you need to know, check the file Browser.pm

DESCRIPTION
===========

   This module implements a VRML browser. The actual module is of interest
only if you are planning to use the code from Perl.

   For information on the user interface, see VRML/Viewer.

AUTHOR
======

   See `freewrl' in this node.

color functions and X11 color names
***********************************

NAME
====

   Color.pm - color functions and X11 color names

SYNOPSIS
========

     use VRML::Color;

     my $color = rgb_color('red');

     or with the same result

     my $color = rgb_color('FF0000');

     or with the same result

     my $color = rgb_color('255 0 0');

     naturally works

     my $color = rgb_color('1 0 0');

DESCRIPTION
===========

   *X11 colornames are:*

     aliceblue
     antiquewhite
     aqua
     aquamarine
     azure
     beige
     bisque
     black
     blanchedalmond
     blue
     blueviolet
     brown
     burlywood
     cadetblue
     chartreuse
     chocolate
     coral
     cornflowerblue
     cornsilk
     crimson
     cyan
     darkblue
     darkcyan
     darkgoldenrod
     darkgray
     darkgreen
     darkkhaki
     darkmagenta
     darkolivegreen
     darkorange
     darkorchid
     darkred
     darksalmon
     darkseagreen
     darkslateblue
     darkslategray
     darkturquoise
     darkviolet
     deeppink
     deepskyblue
     dimgray
     dodgerblue
     firebrick
     floralwhite
     forestgreen
     fuchsia
     gainsboro
     ghostwhite
     gold
     goldenrod
     gray
     green
     greenyellow
     honeydew
     hotpink
     indianred
     indigo
     ivory
     khaki
     lavender
     lavenderblush
     lawngreen
     lemonchiffon
     lightblue
     lightcoral
     lightcyan
     lightgoldenrodyellow
     lightgreen
     lightgrey
     lightpink
     lightsalmon
     lightseagreen
     lightskyblue
     lightslategray
     lightsteelblue
     lightyellow
     lime
     limegreen
     linen
     magenta
     maroon
     mediumaquamarine
     mediumblue
     mediumorchid
     mediumpurple
     mediumseagreen
     mediumslateblue
     mediumspringgreen
     mediumturquoise
     mediumvioletred
     midnightblue
     mintcream
     mistyrose
     moccasin
     navajowhite
     navy
     oldlace
     olive
     olivedrab
     orange
     orangered
     orchid
     palegoldenrod
     palegreen
     paleturquoise
     palevioletred
     papayawhip
     peachpuff
     peru
     pink
     plum
     powderblue
     purple
     red
     rosybrown
     royalblue
     saddlebrown
     salmon
     sandybrown
     seagreen
     seashell
     sienna
     silver
     skyblue
     slateblue
     slategray
     snow
     springgreen
     steelblue
     tan
     teal
     thistle
     tomato
     turquoise
     violet
     wheat
     white
     whitesmoke
     yellow
     yellowgreen

   You can also use

     red_40 = '0.4 0 0'
     yellow%30 = '0.3 0.3 0'
     gray%30 = '0.7 0.7 0.7' !!!

BUGS
====

   X11-green is 0x008000. In VRML it should be 0x00FF00.  This module will
set 'green' to '0 1 0' instead of '0 0.5 0'.

SEE ALSO
========

   http://www.gfz-potsdam.de/~palm/vrmlperl/ for a description of
`VRML-modules' and how to obtain it.

AUTHOR
======

   Hartmut Palm `<palm@gfz-potsdam.de>'

   Homepage http://www.gfz-potsdam.de/~palm/

VRML methods with the VRML 1.0 standard
***************************************

NAME
====

   VRML::VRML1.pm - VRML methods with the VRML 1.0 standard

SYNOPSIS
========

     use VRML::VRML1;

     $vrml = new VRML::VRML1;
     $vrml->browser('Cosmo Player 2.0','Netscape');
     $vrml->at('-15 0 20');
     $vrml->box('5 3 1','yellow');
     $vrml->back;
     $vrml->print;
     $vrml->save;

     OR with the same result

     use VRML::VRML1;

     VRML::VRML1->new
     ->browser('Cosmo Player 2.0','Netscape')
     ->at('-15 0 20')->box('5 3 1','yellow')->back
     ->print->save;

DESCRIPTION
===========

   The methods are identically implemented in VRML::VRML1 and VRML::VRML2.
They described in modul VRML.

SEE ALSO
========

   VRML

   VRML::Base

   VRML::Color

   http://www.gfz-potsdam.de/~palm/vrmlperl/ for a description of
`VRML-modules' and how to obtain it.

AUTHOR
======

   Hartmut Palm `<palm@gfz-potsdam.de>'

   Homepage http://www.gfz-potsdam.de/~palm/

implements the VRML 1.x standard nodes
**************************************

NAME
====

   VRML::VRML1::Standard.pm - implements the VRML 1.x standard nodes

SYNOPSIS
========

     use VRML::VRML1::Standard;

DESCRIPTION
===========

   Following nodes are currently implemented.

   [Group Nodes] [Geometry Nodes] [Property Nodes]

   [Appearance Nodes] [Transform Nodes] [Common Nodes]

Group Nodes
-----------

   *These nodes NEED* End !

Group
     `Group()'

Separator
     `Separator()'

Switch
     `Switch($whichChild)'

WWWAnchor
     `WWWAnchor($url, $description, $target)'

     $target works only with some browsers

LOD
     `LOD($range, $center)'

     $range  = MFFloat

     $center = SFVec3f

     example: `LOD([1, 2, 5], '0 0 0')'

SpinGroup
     `SpinGroup($rotation, $local)' is supported only by some browsers

Geometry Nodes
--------------

AsciiText
     `AsciiText($string, $width, $justification, $spacing)'

     $justification is a string ('LEFT','CENTER','RIGHT')

Cone
     `Cone($radius, $height, @parts)'

     @parts is an array of strings ('SIDES', 'BOTTOM', 'ALL')

Cube
     `Cube($width, $height, $depth)'

Cylinder
     `Cylinder($radius, $height, @parts)'

     @parts is a list of strings ('SIDES', 'TOP', 'BOTTOM', 'ALL')

IndexedFaceSet
     `IndexedFaceSet($coordIndex_ref, $materialIndex_ref,
     $normalIndex_ref, $textureCoordIndex_ref)'

     $coordIndex_ref is a reference of a list of point index strings like
     `['0 1 3 2', '2 3 5 4', ...]'

     $materialIndex_ref is a reference of a list of materials

     $normalIndex_ref is a reference of a list of normals

     $textureCoordIndex_ref is a reference of a list of textures

IndexedLineSet
     `IndexedLineSet($coordIndex_ref, $materialIndex_ref,
     $normalIndex_ref, $textureCoordIndex_ref)'

     $coordIndex_ref is a reference of a list of point index strings like
     `['0 1 3 2', '2 3 5 4', ...]'

     $materialIndex_ref is a reference of a list of materials

     $normalIndex_ref is a reference of a list of normals

     $textureCoordIndex_ref is a reference of a list of textures

PointSet
     `PointSet($numPoints, $startIndex)'

Sphere
     `Sphere($radius)'

     $radius have to be > 0

Property Nodes
--------------

Coordinate3
     `Coordinate3(@points)'

     @points is a list of points with strings like `'1.0 0.0 0.0', '-1 2
     0''

Fontstyle
     `FontStyle($size, $family, $style)' defines the current font style
     for all subsequent AsciiText Nodes

     $familiy can be 'SERIF','SANS','TYPEWRITER'

     $style can be 'NONE','BOLD','ITALIC'

Appearance Nodes
----------------

Material
     `Material(%materials)'

MaterialBinding
     `MaterialBinding($value)'

     $value can be

          DEFAULT	Use default bindng
          OVERALL	Whole object has same material
          PER_PART	One material for each part of object
          PER_PART_INDEXED	One material for each part, indexed
          PER_FACE	One material for each face of object
          PER_FACE_INDEXED	One material for each face, indexed
          PER_VERTEX	One material for each vertex of object
          PER_VERTEX_INDEXED	One material for each vertex, indexed

Normal
     `Normal(@vector)'

     @vector is a list of vectors with strings like `'1.0 0.0 0.0', '.5 .2
     0''

NormalBinding
     `NormalBinding($value)'

     $value is the same as MaterialBinding

Texture2
     `Texture2($value)'

Transform Nodes
---------------

Transform
     `Transform($translation, $rotation, $scaleFactor, $scaleOrientation,
     $center)'

     $translation is a string like "0 1 -2"

     $rotation is a string like "0 0 1 1.57"

     $scaleFactor is a string like "1 1 1"

     $scaleOrientation is a string like "0 0 1 0"

     $center is a string like "0 0 0"

Rotation
     `Rotation($rotation)'

     $rotation is a string like "0 0 1 1.57"

     `This node is not supported under VRML 2.0. Use Transform'

Scale
     `Scale($scaleFactor)'

     $scaleFactor is a string like "1 1 1"

     `This node is not supported under VRML 2.0. Use Transform'

Translation
     `Translation($translation)'

     $translation is a string like "0 1 -2"

     `This node is not supported under VRML 2.0. Use Transform'

Common Nodes
------------

PerspectiveCamera
     `PerspectiveCamera($position, $orientation, $heightAngle,
     $focalDistance, $nearDistance, $farDistance)'

OrthographicCamera
     `OrthographicCamera($position, $orientation, $height, $focalDistance,
     $nearDistance, $farDistance)'

DirectionalLight
     `DirectionalLight($direction, $intensity, $color, $on)'

PointLight
     `PointLight($location, $intensity, $color, $on)'

SpotLight
     `SpotLight($location, $direction, $intensity, $color, $on)'

DirectedSound
     `DirectedSound($name, $description, $location, $direction,
     $intensity, $maxFrontRange, $maxBackRange, $minFrontRange,
     $minBackRange, $loop, $pause)'

other
-----

WWWInline
     `WWWInline($name, $bboxSize, $bboxCenter)'

Info
     `Info($string)'

NavigationInfo
     `NavigationInfo($type, $speed, $headlight)'

     Works only with Live3D and WebFX

USE
     `USE($name)'

DEF
     `DEF($name)'

SEE ALSO
========

   VRML::VRML1::Standard

   VRML::Base

   http://www.gfz-potsdam.de/~palm/vrmlperl/ for a description of
`VRML-modules' and how to obtain it.

AUTHOR
======

   Hartmut Palm `<palm@gfz-potsdam.de>'

   Homepage http://www.gfz-potsdam.de/~palm/

VRML methods with the VRML 2.0/97 standard
******************************************

NAME
====

   VRML::VRML2 - VRML methods with the VRML 2.0/97 standard

SYNOPSIS
========

     use VRML::VRML2;

     $vrml = new VRML::VRML2;
     $vrml->browser('Cosmo Player 2.0','Netscape');
     $vrml->at('-15 0 20');
     $vrml->box('5 3 1','yellow');
     $vrml->back;
     $vrml->print;
     $vrml->save;

     OR with the same result

     use VRML::VRML2;

     VRML::VRML2->new
     ->browser('Cosmo Player 2.0','Netscape')
     ->at('-15 0 20')->box('5 3 1','yellow')->back
     ->print->save;

DESCRIPTION
===========

   The methods are identically implemented in VRML::VRML1 and VRML::VRML2.
They described in modul VRML.

SEE ALSO
========

   VRML

   VRML::Base

   VRML::Color

   http://www.gfz-potsdam.de/~palm/vrmlperl/ for a description of
`VRML-modules' and how to obtain it.

AUTHOR
======

   Hartmut Palm `<palm@gfz-potsdam.de>'

   Homepage http://www.gfz-potsdam.de/~palm/

implements VRML 2.0/97 standard nodes
*************************************

NAME
====

   VRML::VRML2::Standard.pm - implements VRML 2.0/97 standard nodes

SYNOPSIS
========

     use VRML::VRML2::Standard;

DESCRIPTION
===========

   Following nodes are currently implemented.

   [Grouping Nodes] [Special Groups] [Common Nodes]

   [Geometry] [Geometric Properties] [Appearance]

   [Sensors] [Interpolators] [Bindable Nodes]

Grouping Nodes
--------------

   These nodes *NEED* End if the $children parameter is empty !

Anchor
     `Anchor($url, $description, $parameter, $bboxSize, $bboxCenter,
     $children)'

     Currently only the first part of *$parameter* is supported.

Billboard
     `Billboard($axisOfRotation, $children)'

Collision
     `Collision($collide, $proxy, $children)'

Group
     `Group($bboxSize, $bboxCenter)'

Transform
     `Transform($translation, $rotation, $scale, $scaleOrientation,
     $center, $bboxSize, $bboxCenter)'

     $translation is a SFVec3f

     $rotation is a SFRotation

     $scale is a SFVec3f

     $scaleOrientation is a SFRotation

     $center is a SFVec3f

Special Groups
--------------

Inline
     `Inline($url, $bboxSize, $bboxCenter)'

LOD
     `LOD($range, $center)'

     $range is a MFFloat

     $center is a SFVec3f

     Example: `LOD([1, 2, 5], '0 0 0')'

Switch
     `Switch($whichChoice)'

Common Nodes
------------

DirectionalLight
     `DirectionalLight($direction, $intensity, $ambientIntensity, $color,
     $on)'

PointLight
     `PointLight($location, $intensity, $ambientIntensity, $color, $on)'

SpotLight
     `SpotLight($location, $direction, $intensity, $color, $on)'

Sound
     `Sound($source, $location, $direction, $intensity, $maxFront,
     $maxBack, $minFront, $minBack, $priority, $spatialize)'

AudioClip
     `AudioClip($url, $description, $loop, $pitch, $startTime, $stopTime)'

WorldInfo
     `WorldInfo($title, $info)'

Shape
     `Shape($geometry, $appearance)'

Geometry
--------

Box
     `Box($size)'

Cone
     `Cone($radius, $height, $side, $bottom)'

Cylinder
     `Cylinder($radius, $height, $top, $side, $bottom)'

ElevationGrid
     `ElevationGrid($xDimension, $zDimension, $xSpacing, $zSpacing,
     $height, $creaseAngle, $color, $colorPerVertex, $solid)'

     $height should be a reference of a list of height values like `['0 1
     3 2', '2 3 5 4', ...]'

     $color should be a reference to a subroutine or list of color values

Extrusion
     `Extrusion($crossSection, $spine, $scale, $orientation, $beginCap,
     $endCap, $creaseAngle, $solid, $convex, $ccw)'

     $spine should be a reference of a list of spine values like `['0 0
     0', '0 1 0', ...]'

IndexedFaceSet
     `IndexedFaceSet($coord, $coordIndex, $color, $coordIndex,
     $colorPerVertex, $normal, $normalIndex_ref, $texCoord,
     $texCoordIndex_ref)'

     $coordIndex should be a list of point index strings or a reference
     like `'0 1 3 2', '2 3 5 4', ...'

     $coordIndex should be a reference of a list of colors

     $normalIndex_ref should be a reference of a list of normals

     $texCoordIndex_ref should be a reference of a list of textures

IndexedLineSet
     `IndexedLineSet($coord, $coordIndex, $color, $colorIndex,
     $colorPerVertex)'

     $coord should be a reference to a Coordinate method or a string with a
     Coordinate node.

     $coordIndex should be a reference of a list of point index strings
     like `'0, 1, 3, 2', '2, 3, 5, 4', ...'

     $colorIndex should be a reference of a list of colors

PointSet
     `PointSet($coord, $color)'

Sphere
     `Sphere($radius)'

     $radius have to be > 0

Text
     `Text($string, $fontStyle, $length, $maxExtent)'

Geometric Properties
--------------------

Coordinate
     `Coordinate(@point)'

     @point should be a list of points with strings like `'1.0 0.0 0.0',
     '-1 2 0''

Color
     `Color(@color)'

     @color should be a list of colors with strings like `'1.0 0.0 0.0',
     '.3 .2 .1''

Normal
     `Normal(@vector)'

     @vector should be a list of vectors with strings like `'1.0 0.0 0.0',
     '.4 .2 0''

Appearance
----------

Appearance
     Appearance

Fontstyle
     `FontStyle($size, $family, $style, $justify)' defines the current
     font style for the current Text Nodes

     $style can be 'PLAIN','BOLD','ITALIC','BOLD ITALIC'

     $familiy can be 'SERIF','SANS','TYPEWRITER'

     $justify can be 'BEGIN', 'MIDDLE', 'END'

Material
     `Material(%materials)'

ImageTexture
     `ImageTexture($url)'

MovieTexture
     `MovieTexture($url)'

Sensors
-------

CylinderSensor
     `CylinderSensor($maxAngle, $minAngle, $diskAngle, $offset,
     $autoOffset, $enabled)'

PlaneSensor
     `PlaneSensor($maxPosition, $minPosition, $offset, $autoOffset,
     $enabled)'

ProximitySensor
     `ProximitySensor($size, $center, $enabled)'

SphereSensor
     `SphereSensor($offset, $autoOffset, $enabled)'

TimeSensor
     `TimeSensor($cycleInterval, $loop, $startTime, $stopTime, $enabled)'

TouchSensor
     `TouchSensor($enabled)'

VisibilitySensor
     `VisibilitySensor($size, $center, $enabled)'

Interpolators
-------------

ColorInterpolator
     `ColorInterpolator($key, $keyValue)'

CoordinateInterpolator
     `CoordinateInterpolator($key, $keyValue)'

OrientationInterpolator
     `OrientationInterpolator($key, $keyValue)'

NormalInterpolator
     `NormalInterpolator($key, $keyValue)'

PositionInterpolator
     `PositionInterpolator($key, $keyValue)'

ScalarInterpolator
     `ScalarInterpolator($key, $keyValue)'

     $key	MFFloat $keyValue	MFFloat

Bindable Nodes
--------------

Background
     `Background($hash)'

     You only can use a hash. Parameter see VRML Spec

NavigationInfo
     `NavigationInfo($type, $speed, $headlight, $visibilityLimit,
     $avatarSize)'

     You can use a hash reference or all parameter in the same order above

Viewpoint
     `Viewpoint($description, $position, $orientation, $fieldOfView,
     $jump)'

PROTO
     `PROTO($name, $declaration, $definition)'

other
-----

USE
     `USE($name)'

DEF
     `DEF($name)'

ROUTE
     `ROUTE($from, $to)'

End
     `End($comment)'

     Close an open node with }

EndChildren
     `EndChildren($comment)'

     Close an open children part with ]

EndTransform
     `EndTransform($comment)'

     Close an open children part with ] and the node with }

SEE ALSO
========

   VRML::VRML2::Standard

   VRML::Base

   http://www.gfz-potsdam.de/~palm/vrmlperl/ for a description of
`VRML-modules' and how to obtain it.

AUTHOR
======

   Hartmut Palm `<palm@gfz-potsdam.de>'

   Homepage http://www.gfz-potsdam.de/~palm/

navigation modes of FreeWRL
***************************

NAME
====

   VRML::Viewer - navigation modes of FreeWRL

SYNOPSIS
========

   (used internally by FreeWRL)

DESCRIPTION
===========

   This module implements the various navigation modes for the FreeWRL
VRML browser (see VRML/Browser, `freewrl' in this
node).  `freewrl' in this node explains how to use the navigation modes.

AUTHOR
======

   Tuomas J. Lukka, with help from John Breen.

Hp Tnd custom data for HMS logs
*******************************

NAME
====

   VcsTools::DataSpec::HpTnd - Hp Tnd custom data for HMS logs

SYNOPSIS
========

     use VcsTools::DataSpec::HpTnd qw($description readHook);
     use VcsTools::LogParser ;

     my $ds = new VcsTools::LogParser
      (
       readHook => \&readHook,
       description => $description
      ) ;

DESCRIPTION
===========

   This class contains all the custom information needed to retrieve our
data from our database using the generic VcsTools/LogParser,
class.

   The $description hash ref defines the informations that are contained
in the log of each version of the HMS file.

   Needless to say this file is tailored for HP Tnd needs and HMS keywords.
Nevertheless, it can be used as a template for other VCS systems and other
needs.

HP TND DATA DESCRIPTION
=======================

state
-----

   Taken from 'state' HMS field. It can be either Dead Exp Team Lab
Special or Product according to the level of confidence.

branches
--------

   Taken from 'branches' HMS field. List the branches of a version.
read-only value.

author
------

   Taken from 'Author' HMS field. Name of the author of the revision or
the name of the last guy who modified the HMS log.

date
----

   Date of the archive. Set by HMS. read-only value.

merged from
-----------

   Specifies if this version is a merge between the parent revision and
another revision.

comes from
----------

   Explicitely specifies the parent revision. Use this field when the
parent cannot be infered. For instance, when the revision number jump from
1.19 to 2.1, set the 'comes from' field of the revision '2.1' to '1.19'.

writer
------

   The original writer of this version. Since HMS changes the 'Author'
field whenever you edit the history of a version, this field keeps track
of the guy who actually archived this version.

keywords
--------

   Keyword which refers to the functionnality added in this version.
(could be 'ANSI', 'cosmetic', 'doc_update' ...).

fix
---

   Official names of the bugs fixed in this version (a la 'GREhp01234').

misc
----

   Miscellaneous comments about this version.

CHANGE MODEL
============

   The 3 following keywords try to provide a model for changes introduced
with each revision of a file.

behavior change
---------------

   Specify whether this code can smoothly replace the previous revision.
Can be 'none', 'cosmetic', 'minor','major'

   Still need a clear definition of what it means.

interface change
----------------

   Specify the amount of change seen from the compiler's point of view. For
a header file, for instance, 'cosmetic' might mean 're-compilation needed',
'major' might mean 'code change needed in user code'.

   Can be 'none', 'cosmetic', 'major'

inter-peer change
-----------------

   Specify whether this code can inter-work with the previous revision.

   Can be 'none', 'cosmetic', 'major'

HOOKS
=====

readHook(hash ref)
------------------

   This method will try to get more information from the log of each
revision.

   If the 'fix' field is empty, readHook will look for GREhpxxxx keywords
in the log to guess what was fixed in this revision. Of course, it may
guess wrong if the log contains "*Gee I forgot to fix GREhp00007*".

   If the 'keywords' field is empty, readHook will look for keywords
matching `/\b([A-Z\d]{2,})\b/' in the log to guess what was added in this
revision.  The result is often relevant, but is sometime silly.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998-1999 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1)

Rcs data description
********************

NAME
====

   VcsTools::DataSpec::Rcs - Rcs data description

SYNOPSIS
========

     use VcsTools::DataSpec::Rcs qw($description readHook);
     use VcsTools::LogParser ;

     my $ds = new VcsTools::LogParser
      (
       readHook => \&readHook,
       description => $description
      ) ;

DESCRIPTION
===========

   This class contains all the custom information needed to retrieve data
from an RCS log using the generic VcsTools/LogParser,
class.

   The $description hash ref defines the informations that are contained
in the log of each version of the RCS file.

   This class can be used as a template for other VCS systems and other
needs.

   The readHook is used to find the first revision of a branch. For
instance a branch is named 1.5.1 in the VCS history, the readHook will
find that the actual first revision of the branch is 1.5.1.1.

RCS DATA DESCRIPTION
====================

state
-----

   Taken from 'state' RCS field. It can be either Dead Exp or Product
according to the level of confidence.

branches
--------

   Taken from 'branches' RCS field. List the branches of a version.
read-only value.

author
------

   Taken from 'author' RCS field. Name of the author of the revision or
the name of the last guy who modified the RCS log.

date
----

   Date of the archive. Set by RCS. read-only value.

misc
----

   Miscellaneous comments about this version.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998-1999 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1)

Perl class to manage a VCS file.
********************************

NAME
====

   VcsTools::File - Perl class to manage a VCS file.

SYNOPSIS
========

     my %dbhash; # may be tied to a MLDBM

     use VcsTools::LogParser ;
     use VcsTools::DataSpec::HpTnd qw($description readHook);
     use Puppet::Storage ;
     use VcsTools::HmsAgent ; # could be also RcsAgent
     my $ds = new VcsTools::DataSpec::HpTnd ;

     my $ds = new VcsTools::LogParser
      (
       description => $description,
       readHook => \&readHook
      ) ;

     Puppet::Storage->dbHash(\%dbhash);
     Puppet::Storage->keyRoot('root');

     my $storage= new Puppet::Storage(name => 'dummy.txt') ;

     VcsTools::HmsAgent->hmsBase('test');
     VcsTools::HmsAgent->hmsHost('a_host');

     my $agent = VcsTools::HmsAgent->new
      (
       name => 'dummy.txt',
       workDir => cwd().'/'.$dir
      );

     my $vf = new VcsTools::File
      (
       storage => $storage ,
       vcsAgent => $agent,
       name => 'dummy.txt',
       workDir => $some_dir,
       dataScanner => $ds
      );

     $vf -> createArchive();
     $vf -> checkOut(revision => '1.1', lock => 1) ;
     $vf -> archiveFile(info =>{log => 'dummy log for 1.2'});
     $vf -> showDiff(rev1 => '1.1', rev2 => '1.2');
     $vf -> setUpMerge(ancestor => '1.1', below => '1.2', other => '1.1.1.1');

DESCRIPTION
===========

   This class represents a VCS file. It holds all the interfaces to the
"real" world and the history object (See VcsTools/History)).

   Firthermore, this class will store the file and archive properties (like
s the file readable, does the archive exists, is it locked...) in a
Storable, file (within a .store directory)

CAVEATS
=======

   The file must contain the `$Revision: 1.5 $' VCS keyword.

   The VCS agent (hmsAgent) creation is clumsy. I should use translucent
attributes or stuff like that like Tom Christiansen described. In other
words, let the user create its agent object and clone it for File usage.
This part is subject to change sooner of later. Only the constructors
should be impacted.

CONVENTION
==========

   The following words may be non ambiguous for native english speakers,
but it is not so with us french people. So I prefer clarify these words:

   * Log: Refers to the information stored with one version.

   * History: Refers to a collection of all logs of all versions stored in
     the VCS base.

Constructor
===========

new(...)
--------

   Will create a new File object.

   Parameters are those of `"new(...)"', see Puppet/Body,
plus :

   * dataScanner : VcsTools/LogParser, (or
     equivalent) object reference.

   * workDir : Absolute directory where the file is.

   * vcsAgent : VCS interface object (e.g. See VcsTools/HmsAgent).

Generic methods
===============

check()
-------

   See `"check()', see VcsTools/Source,

History handling methods
========================

createHistory()
---------------

   Will returns the VcsTools/History, object for
this file and create it if necessary.

updateHistory()
---------------

   Extract the history information from the VCS base and update the
VcsTools::History objbect (by calling `"update(...)"', see
VcsTools/History).

   This function must be called to re-synchronize your application if the
VCS base was changed by someone else.

Handling the real file
======================

createLocalAgent()
------------------

   Create the file Agent class.

getTimeStamp()
--------------

   Returns the last modification time of the file. (See stat function in
Perlfunc (perl.info))

edit()
------

   Will launch a window editor though the file agent (`"edit()"', see
VcsTools/FileAgent)

getRevision()
-------------

   See `"getRevision()', see VcsTools/Source,

checkWritable()
---------------

   Will return 1 if the file is writable, 0 if not. Will return undef in
case of problems.

checkExist()
------------

   Will return 1 if the file exists, 0 if not. Will return undef in case
of problems.

chmodFile(...)
--------------

   Will change  the file mode to writable or not.

   Parameters are :

   * writable: 1 or 0

   Returns 1 if chmod was done and undef in case of problems.

writeFile(...)
--------------

   Write the passed content into the actual VCS file..

   Parameters are :

   content: String or hash ref (See `"writeFile(...)"', see
VcsTools/FileAgent) that will be written.

   Returns 1 if the file was written and undef in case of problems.

writeRevContent(...)
--------------------

   Write the content of a specific version of the VCS file in the passed
file name. This method is handy when you want to compare several revisions
of a VCS file with a tool which does not support directly your VCS system.

   For instance to compare 2 versions of foo.c you may call:

     # creates a v1.2_foo.c file
     $foo->writeRevContent(revision => 1.2);
     # creates a v1.3_foo.c file
     $foo->writeRevContent(revision => 1.3);

   Then you may call xdiff on v1.2_foo.c and v1.3_foo.c.

   Parameters are :

   * revision: writeFile will retrieve this revision of the VCS file and
     write it to the passed file name.

   * fileName: file name to write to (default to "v<rev>_<VCS_file_name>",
     e.g.  v1.13_bar.c for version 1.13 of the bar.c VCS file)

   Returns the name of the written file if the file was actually written
and undef in case of problems.

remove()
--------

   Unlink the VCS file.

Handling the VCS part
=====================

   Before invoking any VCS functions, the File object will check whether
the function can be performed. (For instance, it will not try to perform a
check out if the local file is writable.)

createVcsAgent()
----------------

   Create the VCS interface class.

checkArchive()
--------------

   Calls checkArchive of the VCS interface class. (E.g.
`"checkArchive()"', see VcsTools/HmsAgent) with the
working revision as the revision parameter..

changeLock(...)
---------------

   Delegated to the VCS interface class. E.g. `"changeLock(...)"', see
VcsTools/HmsAgent,

checkOut(...)
-------------

   Delegated to the VCS interface class. E.g.  `"checkOut(...)"', see
VcsTools/HmsAgent,

getContent(...)
---------------

   Delegated to the VCS interface class. E.g. `"getContent(...)"', see
VcsTools/HmsAgent,

archiveLog(...)
---------------

   See `"archiveLog()"', see VcsTools/Source,

getHistory()
------------

   Delegated to the VCS interface class. E.g. `"getHistory()"', see
VcsTools/HmsAgent,

showDiff(...)
-------------

   Delegated to the VCS interface class. E.g. `"showDiff(...)"', see
VcsTools/HmsAgent,

archiveFile(...)
----------------

   Will archive the current file.

   Parameters are:

   * revision: revision number for this new version of the file. Defaults
     to a number computed by `"guessNewRev(revision)"', see
     VcsTools/History,

   * info: Hash ref holding relevant informations for this new archive.
     (See VcsTools/LogParser, for the hash
     content). Defaults to a hash containing 'auto archive' as log
     information, the current date and the name of the user performing the
     archive.

   Note that before performing the archive, the program will check the
timestamp of the archive base and will upload its history informations if
the archive has been changed since the last upload. This way the archive
number decided by the history object will always be correct.

TO DO
=====

   A merge() method which will find the common ancestor of the passed
revisions, perform a merge using merge(1) and write the result in the
local file.

   A patch() method which will report the modif made from one revision to
an other revision on a branch. This can be handy to report a bug fix on a
branch under change control.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998-1999 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1), Tk(3), Puppet::Any(3), VcsTools::DataSpec::HpTnd(3),
VcsTools::Version(3), VcsTools::File(3)

Perl class to handle a file
***************************

NAME
====

   VcsTools::FileAgent - Perl class to handle a file

SYNOPSIS
========

     my $agent = "VcsTools::FileAgent" ;

     my $fa = new $agent(name => 'test.txt',
                         workDir => $some_dir);

     $fa->writeFile(content => "dummy content\n") ;

     $fa->readFile() ;

     $fa->stat() ;

DESCRIPTION
===========

   This class is used as a file agent to perform some operation such as
pipe, stat, read, write. This class will take care of going in and out of
the directory where the file is and will perform basic error handling.

   This class will use VcsTools/Process, to launch
child processes.

   Note that one FileAgent class must be created for one file.

Constructor
===========

new(...)
--------

   Creates a new  class.

   Parameters are :

   * name: file name (mandatory)

   * workDir: local directory where the file is.

   * trace: If set to 1, debug information are printed.

   Will create a FileAgent for file 'a_name' in directory 'workDir'. Note
that new will create the 'workDir' if it does not exist.

Methods
=======

edit()
------

   Will run a non-blocking gnuclient session to edit the file.

merge(...)
----------

   Will connect to xemacs (with gnudoit) and will run a non-blocking ediff
session. See the ediff documentation.

   Parameters are :

   * ancestor: the file name which contains the ancestor of the 2 files to
     merge

   * below:  the file name which contains one of the revision to merge.

   * other: the file name which contains the other revision to merge.

   Returns 1 when the ediff is launched. Returns undef in case of problems.
Note that merge will return once ediff is luanched, not when the ediff
session is done.

writeFile(...)
--------------

   Will write a string (or an array joined with "\n") into the file.

   parameters are :

   * content: string | ref_to_string_array

   * name: optional file name that will be written to (defaults to the name
     passed to the constructor).

readFile()
----------

   Will read the content of the file. Returns a ref to an array containing
the file lines

getRevision()
-------------

   Will read the content of the file and return the revision number.
Return 0 of the $Revision: 1.6 $ keyword is present in the file but not
set by the VCS system.

stat()
------

   Will perform a stat (see perlfunc(3)) on the file and return the stat
array.

exist()
-------

   Will return '1' or '0' if the file exists or not. ('-e' test).

changeMode(...)
---------------

   Will perform a chmod (see perlfunc(3)) on the file.

   Parameters are :

   * mode: 0xxx mode

remove()
--------

   Will unlink (see perlfunc(3))  the file .

   parameters are :

   * name: optional file name that will be written to (defaults to the name
     passed to the constructor).

Error handling
==============

   In case of problems, all function will return undef.

   In this case of problem, you can call the error() method to get a string
describing the problem of the last command.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998-1999 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1), VcsTools::Process(3)

Perl class to manage a VCS history.
***********************************

NAME
====

   VcsTools::History - Perl class to manage a VCS history.

SYNOPSIS
========

     require VcsTools::DataSpec::HpTnd ; # for instance
     my $ds = new VcsTools::DataSpec::HpTnd ;
     my $hist = new VcsTools::History
      (
       keyRoot => 'history root',
       name => 'History test',
       dataScanner => $ds
      );

DESCRIPTION
===========

   This class represents a whole history of a VCS file. It holds all the
necessary VcsTools/Version, objects that makes the
complete history of the file.

   Generally, RCS based systems such as VCS or HMS store a few information
with each revision. These information are generally 'Author', 'date',
'branches', 'log'. On top of the common informations, you can specify your
own set of information (for instance, 'merged from', 'bug fixed')
according to the policies defined on your work place.

   On top of the functionnality of the Version object (See
`"DESCRIPTION"', see VcsTools/Version), you can
perform various queries related to the history such as :

   * Sort revisions: it will return a pair of revisions sorted by age.
     Oldest and child. But it will return an error if these two versions
     are not parents of each others.

   * List a genealogy of versions between 2 revisions of a file. This will
     take into account the branches. For instance between 1.1 and 1.2.1.2,
     it will return 1.1 1.2 1.2.1.1 1.2.1.2), but between 1.3 and 1.2.1.2
     it will return an error, since these two versions are not parents of
     each others.

   * Build a cumulated log of several revisions. I.e a log description of
     all changes made to several consecutive versions (which is handy to
     build a log of a merge). This function will return an if these two
     versions are not parents of each others.

   Furthermore, this class can be used with a GUI by using
Puppet/VcsTools/History, instead.

CONVENTION
==========

   The following words may be non ambiguous for native english speakers,
but it is not so with us french people. So I prefer clarify these words:

   * Log: Refers to the information stored with one version.

   * History: Refers to a collection of all logs of all versions stored in
     the VCS base.

Constructor
===========

new(...)
--------

   Will create a new history object.

   Parameters are those of Puppet/Body, plus :

   * revision : revision number of this version

   * dataScanner : VcsTools/DataSpec/Rcs, or
     VcsTools/DataSpec/HpTnd, (or
     equivalent) object reference

Methods
=======

update(...)
-----------

   Parameters are:

   * history: huge string or array ref of all VCS logs, or history hash
     ref using the format described in data scanner

   This method will:

   * Parse the content of the history.

   * Create all Version objects found in the history

   * Update all Version objects with the informations found in each log.

   Note that calling this method will clobber all informations previously
stored in the Version objects.

hasVersion(revision)
--------------------

   Returns 1 if the VCS file contains this revision of the file.

guessNewRev(revision)
---------------------

   Returns a fitting revision number to follow the passed revision.

   For instance :

   * guessNewRev(1.2) returns 1.3 if 1.3 does not exist

   * guessNewRev(1.2) returns 1.2.1.1 if 1.3 already exists

   * guessNewRev(1.2) returns 1.2.2.1 if 1.3 and branch 1.2.1 already exist

sortRevisions($rev1, $rev2)
---------------------------

   Returns ($rev1, $rev2) if $rev1 is the ancestor of $rev2, ($rev2,
$rev1) in the other case.

   Returns undef if the revisions are not parents.

listGenealogy($rev1, $rev2)
---------------------------

   Returns a list of all revision between $rev1 and $rev2. Include the
youngest revision in the list, but not the older.

   Croaks if the revision are not parents.

getInfo($rev)
-------------

   Returns an info array containing all informations relevant to $rev.

buildCumulatedInfo($rev1, $rev2)
--------------------------------

   Returns an info array made of a concatenation of all revision  between
$rev1 and $rev2.

   Croaks if the revisions are not parents.

addNewVersion(...)
------------------

   Parameters are:

   * revision: revision to add (e.g. '1.2.1.1')

   * info: hash ref containing the informations related to this revision.

   This method will add a new version in this history. Do not call this
method unless the VCS system actually has a new version, i.e. the user just
performed an archive.

getVersionObj(revision)
-----------------------

   Returns the object ref of the Version object representing the passed
revision. Will create the objects as necessary.

   Returns undef if the asked revision does not exist.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998-1999 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1), VcsTools::DataSpec::HpTnd(3), VcsTools::DataSpec::Rcs(3)
VcsTools::Version(3), Puppet::VcsTools::History(3)

Perl class to manage ONE HMS files..
************************************

NAME
====

   VcsTools::HmsAgent - Perl class to manage ONE HMS files..

SYNOPSIS
========

     VcsTools::HmsAgent->hmsHost ('a_host') ;
     VcsTools::HmsAgent->hmsBase ('a_base') ;

     my $h = new VcsTools::HmsAgent
      (
       name => $file,
       workDir => $some_dir
      );

     $h -> getHistory() ;

     $h -> checkOut(revision => '1.51.1.1', lock => 1) ;

     $h -> getContent(revision => '1.52') ;

     $h -> checkArchive() ;

     $h -> changeLock(lock => 1,revision => '1.51.1.1' ) ;

     $h -> archiveLog(log => "new dummy\nhistory\n",
                         state => 'Dummy', revision => '1.52') ;

     $h -> showDiff(rev1 => '1.41') ;

     $h -> showDiff(rev1 => '1.41', rev2 => '1.43') ;

     $h -> checkIn(revision => '1.52',
                  'log' => "dummy log\Nof a file\n") ;

DESCRIPTION
===========

   This class is used to manage a HMS file. All functions are executed in
blocking mode.

   If you want to use other VCS system than HMS, you should copy or
inherit this file to implement your own new class.

HMS
===

   HMS is Hewlett-Packard proprietary VCS system based on RCS. This product
is part of HP SoftCM.

Class data
==========

   These items are translucent attributes (See Perltootc (perl.info),
by Tom Christiansen).

   Using the following method, you may set or query the value for the data
class.

   * hmsHost: The HMS server name.

   * hmsBase: The HMS base name.

   * hmsDir: The directory relative to the HMS base where the file is
     archived.

   * trace: If set to 1, debug information are printed. (default 0)

   * test: If set to 1, each command will return the command to be executed
     instead of the command result.(default 0)

   These parameters may be overridden for an object by

   * Passing a named parameters to the constructor (eg. `hmsHost =>
     'tralfamadore'')

   * By invoking the corresponding object method (eg.
     `$obj->hmsHost('tralfamadore')').

Contructor
==========

new(...)
--------

   Creates a new HMS agent object. Note that one HmsAgent must be created
for each HMS file.

   Parameters are (not including the class data):

   * name: file name (mandatory)

   * workDir: local directory where the file is.

   If 'hmsHost' or 'hmsBase' parameters are not provided, HMS will rely on
the system or user .fmrc file. See fci(1) for more details.

Methods
=======

spawn(...)
----------

   Spawn a new HMS agent object inheriting the attributes of the spawner
object.

   Parameters are :

   * name: file name (mandatory)

   * subDir: Specify the directory of the spawned object relative to the
     directory of the spawner object. Both hmsDir and workDir of the
     spawned object will be set.

checkOut(...)
-------------

   Parameters are :

   * revision: file revision to check out. If not specified, the VCS
     system will decide itself which revision to check out.

   * lock: boolean. whether to lock the file or not.

   Checks out revision x.y and lock it if desired.

   Returns an array ref containing the output of the 'fci' in case of
success, undef in case of problems.

   In case of problem, you can call the error() method to get the STDOUT
of the command.

getContent(...)
---------------

   Parameters are :

   * revision: file revision to check out.

   Get the content of file revision x.y.

   Returns an array ref of the file content in case of success, undef in
case of problems.

   In case of problem, you can call the error() method to get the STDOUT
of the command.

checkArchive()
--------------

   Check the state of the archive with respect to the passed revision.

   Parameters are :

   * revision: revision number of the user's working file. May be undef.

   Returns an array ref made of [$rev,$locker,$time] or undef in case of
problems.

   * $time is the time of the last modification of the archive (in epoch,
     decimal time)

   * if the revision the the user is working on is locked, $locker returns
     the name of the locker, 'unlocked' otherwise.

   * $revision is there for historical reasons. It is set to the revision
     number of the user's working file if this revision is locked. set to
     undef otherwise.

changeLock(...)
---------------

   Parameters are :

   * revision: file revision to check out.

   * lock: whether to lock the file or not.

   Change the lock of the file for revision x.y.

   Returns an array ref containing the output of the 'futil' in case of
success, undef in case of problems.

   In case of problem, you can call the error() method to get the STDOUT
of the command.

archiveLog(...)
---------------

   Will modify the log (not the file) of a specified revision of the file.

   Parameters are :

   * revision

   * log: log to store in the history of revision

   * state: new state to store

   Returns an array ref containing the output of the 'futil' in case of
success, undef in case of problems.

   In case of problem, you can call the error() method to get the STDOUT
of the command.

getHistory()
------------

   Gets the complete history of file.

   Returns an array ref containing the history in case of success, undef
in case of problems.

   In case of problem, you can call the error() method to get the STDOUT
of the command.

showDiff(...)
-------------

   Parameters are :

   * rev1: first revision to compare

   * rev2: 2nd revision to compare. If not specified, the comparison is
     made between the local file and revision 'rev1'.

   Gets the diff between current file and revision rev1 or between rev1 and
rev2 if rev2 is specified.

   Returns an array ref containing the diff output in case of success,
undef in case of problems.

   In case of problem, you can call the error() method to get the STDOUT
of the command.

create()
--------

   Create the HMS file. If needed this method will also create the HMS path
in the HMS base.

   Returns an array ref containing the output of the 'fci' commmand in
case of success, undef in case of problems.

   In case of problem, you can call the error() method to get the STDOUT
of the command.

checkIn(...)
------------

   Archive (check in) the current file. Parameters are :

   * revision

   * log: log to store in the history of revision

   Returns an array ref containing the output of the 'fci' commmand in
case of success, undef in case of problems.

   In case of problem, you can call the error() method to get the STDOUT
of the command.

list()
------

   Returns a hash reference containing all HMS files found in the HMS base
in the directory of this file and all sub-directories (i.e list
recursively all files found in and below /hmsBase/hmsDir).

   The hash will contains the locker and locked revision (if any) and the
last modification time of the HMS archive.

   For instance, list will return :  {'foo' => {rev => '1.0', locker =>
'bob', time => '935143309'},   'subdir/bar' => {rev => undef , locker =>
undef, time => '935143305'}}

   Returns undef in case of problem.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998-1999 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1), VcsTools::Process(3)

Perl class to translate RCS based log to info hash
**************************************************

NAME
====

   VcsTools::LogParser - Perl class to translate RCS based log to info hash

SYNOPSIS
========

     my $ds = new VcsTools::LogParser (description => $big_hash);

     my @log = <DATA>;
     my $info = $ds->scanHistory(\@log) ;

     my $piledInfo = $ds->pileLog
      (
       'pile_test',
       [
        [ '3.10', $info->{'3.10'}],
        ['3.11', $info->{'3.11'}],
        ['3.12', $info->{'3.12'}],
        ['3.13', $info->{'3.13'}],
       ]
      ) ;

     print $ds->buildLogString ($piledInfo);

DESCRIPTION
===========

   This class is used to translate the log of a VCS file into a hash
containing all relevant informations and vice-versa.

   Currently, LogParser should work on all RCS based VCS systems. It has
been tested with RCS and HP HMS.

   The description hash ref defines the informations that are contained in
the log of each version of the VCS file.

   LogParser can also concatenate several logs into one according to the
rules defined in the description hash.

Contructor
==========

new(...)
--------

   * description: has ref containing the description of the fields that
     can be found in the VCS log.

   * readHook: Sub ref. See scanHistory method.

Methods
=======

scanHistory(log)
----------------

   Analyse the history of a file and returns a hash ref containing all
relevant informations. The keys of the hash are made from the revision
numbers found in the history log.

   The log can be either a string or an array ref.

   Once the log has been analysed and the informations have been stored in
the info hash according to the description, the 'readHook' passed to the
constructor will be called with the info hash ref as parameter. This gives
user the possibility to add its custom treatments to get more informations
from the log.

getDescription()
----------------

   Return the hash ref describing the VCS log.

buildLogString(info_hash_ref)
-----------------------------

   Returns a log string from the info hash. The log string may be archived
as is in the VCS base.

pileLog(...)
------------

   Returns an info hash made of all informations about revision passed in
the array ref.

   Parameters are:

   * The first parameter is the name of the concerned Vcs file. This field
     is necessary to build a readable cumulated log.

   * The second parameter is an array ref made where each element is an
     array ref made of the version number and the info hash ref of this
     revision.  (See example below)

DESCRIPTION FORMAT
==================

   Each element of the array is a hash ref. This hash ref contains :

   * name : name of the field as seen by the user or by the VCS system.

   * var : variable name used in internal hash (default = name), and
     through the VcsTools objects.

   * type : is either line, enum or array or text (see below)

   * values : array ref containing the possible values of enum type
     (ignored for other types)

   * mode : specifies if the value must be hidden (h) from the user or if
     it can be only read or also modified by the user (h|r|w) (default 'w')

   * pile: specify how the information are cumulated. (optional)

     For array data type, it can be 'push'. In this case, the array
     elements are pushed, then sorted and redundant infos are discarded.

     For text data type, is can be 'concat'. In this case, the text
     strings are concatenated together and with each file name and
     revision number.

   * vcs_mode: if 'r', the info is read from the VCS system but not
     written to (ex: the archival date) (optional, defaults to 'w')

   * help : The help information can either be a string that will be
     displayed with a Tk::Dialog or a pointer to a Pod file that will be
     displayed with a Tk::pod window.

     In case of pod information, the help hash must be like :

          {
            'class' => 'Your::Class',
            'section' => 'DECRIPTION' # optionnal
          }

EXAMPLE
=======

   Here's an example of a cumulated log :

     From pile_test v3.12:
       - coupled with tcapIncludes
       - does not compile in ANSI

     From pile_test v3.11:
     bugs fixed :

     - GREhp10971   :  TC_P_ABORT address format doesn't respect addr option.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998-1999 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1)

Perl functions to handle child process (blocking mode)
******************************************************

NAME
====

   VcsTools::Process - Perl functions to handle child process (blocking
mode)

SYNOPSIS
========

     my $res = openPipe
      (
       command => 'll',
       trace => $trace
      ) ;

     $res = pipeIn (command => 'bc',
                   trace => $trace,
                   input => "3+4+2\nquit\n"
                  );

     $res = mySystem
       (
        command => 'echo ^G>/dev/console',
        trace => $trace,
       );

DESCRIPTION
===========

   This package provides functions which are the standard perl functions
(system, open, and open2) with some sugar coating to avoid duplicated code.

Common parameters
=================

   The functions mySystem, openPipe and pipeIn accepts these parameters:

   * command: the command to run

   * trace: If set to 1, the command will be printed on STDERR before
     execution.

   * expect: hash ref specifying how the process exit code must be
     interpreted.  Defaults to ( 0 => 1, 255 => 0 ).

   * workDir: where to run the command (defaults to the current
     directory). If specified all functions will perform a chdir to
     'workDir' before executing the command and will chdir back before
     returning.

Error checking
==============

   In case of errors all functions returns undef. In this case you can get
the error cause by calling the getError function.

Functions
=========

mySystem(...)
-------------

   Will run a system() call. Returns 1 in case of succes, undef in case of
problems.

openPipe(...)
-------------

   Will open a pipe on command and read its STDOUT. Returns an array ref
in case of succes, undef in case of problems.

   The array will contain chomped lines of the STDOUT of the command.

pipeIn(...)
-----------

   Will open a pipe on the STDIN and STDOUT of command (see open2), send
the content of the 'input' parameter to the process and read its STDOUT.

   Returns an array ref in case of succes, undef in case of problems.

   The array will contain chomped lines of the STDOUT of the command.

   Parameters are:

   * input: string to send to the command

getError()
----------

   Return a string containing the error message of the last command which
had some problem. It works a bit like the errno variable.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998-1999 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1)

Perl class to manage ONE RCS files..
************************************

NAME
====

   VcsTools::RcsAgent - Perl class to manage ONE RCS files..

SYNOPSIS
========

     my $h = new VcsTools::RcsAgent
      (
       name => $file,
       workDir => $some_dir
      );

     $h -> getHistory() ;

     $h -> checkOut(revision => '1.51.1.1', lock => 1) ;

     $h -> getContent(revision => '1.52') ;

     $h -> checkArchive() ;

     $h -> changeLock(lock => 1,revision => '1.51.1.1' ) ;

     $h -> archiveLog(log => "new dummy\nhistory\n",
                         state => 'Dummy', revision => '1.52') ;

     $h -> showDiff(rev1 => '1.41') ;

     $h -> showDiff(rev1 => '1.41', rev2 => '1.43') ;

     $h -> checkIn(revision => '1.52',
                  'log' => "dummy log\Nof a file\n") ;

DESCRIPTION
===========

   This class is used to manage a RCS file. All functions are executed in
blocking mode.

   If you want to use other VCS system than RCS, you should copy or
inherit this file to implement your own new class.

Class data
==========

   These items are translucent attributes (See Perltootc (perl.info),
by Tom Christiansen).

   Using the following method, you may set or query the value for the data
class.

   * trace: If set to 1, debug information are printed. (default 0)

   * test: If set to 1, each command will return the command to be executed
     instead of the command result.(default 0)

   These parameters may be overridden for an object by

   * Passing a named parameters to the constructor (eg. `trace => 1')

   * By invoking the corresponding object method (eg. `$obj->trace(1)').

Contructor
==========

new(...)
--------

   Creates a new RCS agent class. Note that one RcsAgent must be created
for each RCS file.

   Parameters are (not including the class data):

   * name: file name (mandatory)

   * workDir: local directory where the file is.

   * trace: If set to 1, debug information are printed.

   * test: each command will return the command to be executed instead of
     the command result.

Methods
=======

spawn(...)
----------

   Spawn a new RCS agent object inheriting the attributes of the spawner
object.

   Parameters are :

   * name: file name (mandatory)

   * subDir: Specify the directory of the spawned object relative to the
     directory of the spawner object. Note that the workDir of the spawned
     object will be set.

create()
--------

   Create a new archive. If the RCS sub-directory is not present, it will
also be created.

   Returns undef in case of problems.

checkOut(...)
-------------

   Parameters are :

   * revision: file revision to check out.

   * lock: boolean. whether to lock the file or not.

   Checks out revision x.y and lock it if desired.

   Returns an array ref containing the output of the 'ci' in case of
success, undef in case of problems.

   In case of problem, you can call the error() method to get the STDOUT
of the command.

getContent(...)
---------------

   Parameters are :

   * revision: file revision to check out.

   Get the content of file revision x.y.

   Returns an array ref of the file content in case of success, undef in
case of problems.

   In case of problem, you can call the error() method to get the STDOUT
of the command.

checkArchive()
--------------

   Check the state of the archive with respect to the passed revision.

   Parameters are :

   * revision: revision number of the user's working file. May be undef.

   Returns an array ref made of [$rev,$locker,$time] or undef in case of
problems.

   * $time is the time of the last modification of the archive (in epoch,
     decimal time)

   * if the revision the the user is working is locked, $locker returns the
     name of the locker, 'unlocked' otherwise.

   * $revision is there for historical reasons. It returns the revision
     number of the user's working file if this rev is locked. Is undef
     otherwise.

changeLock(...)
---------------

   Parameters are :

   * revision: file revision to check out.

   * lock: whether to lock the file or not.

   Change the lock of the file for revision x.y.

   Returns an array ref containing the output of the 'rcs' in case of
success, undef in case of problems.

   In case of problem, you can call the error() method to get the STDOUT
of the command.

archiveLog(...)
---------------

   Will modify the log (not the file) of a specified revision of the file.

   Parameters are :

   * revision

   * log: log to store in the history of revision

   * state: new state to store

   Returns an array ref containing the output of the 'futil' in case of
success, undef in case of problems.

   In case of problem, you can call the error() method to get the STDOUT
of the command.

getHistory()
------------

   Gets the complete history of file.

   Returns an array ref containing the history in case of success, undef
in case of problems.

   In case of problem, you can call the error() method to get the STDOUT
of the command.

showDiff(...)
-------------

   Parameters are :

   * rev1: first revision to compare

   * rev2: 2nd revision to compare. If not specified, the comparison is
     made between the local file and revision 'rev1'.

   Gets the diff between current file and revision rev1 or between rev1 and
rev2 if rev2 is specified.

   Returns an array ref containing the diff output in case of success,
undef in case of problems.

   In case of problem, you can call the error() method to get the STDOUT
of the command.

create()
--------

   Create the RCS file.

   Returns an array ref containing the output of the 'ci' commmand in case
of success, undef in case of problems.

   In case of problem, you can call the error() method to get the STDOUT
of the command.

checkIn(...)
------------

   Archive (check in) the current file. Parameters are :

   * revision

   * log: log to store in the history of revision

   Returns an array ref containing the output of the 'ci' commmand in case
of success, undef in case of problems.

   In case of problem, you can call the error() method to get the STDOUT
of the command.

list()
------

   Returns an array reference containing all RCS files found in the RCS
directory of this file

   For instance, list will return ['foo','bar'] if the RCS subdir contains
foo,v and bar,v.

   Returns undef in case of problem.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998-1999 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1), VcsTools::Process(3)

Perl base class for some VcsTools components
********************************************

NAME
====

   VcsTools::Source - Perl base class for some VcsTools components

SYNOPSIS
========

   No synopsis given. Virtual class.

DESCRIPTION
===========

   This class is just a way not to duplicate functions.

Generic methods
===============

check()
-------

   Checks r/w permission of the local file, the revision of the local file
and lock state of the file.

   The file must contain the `$Revision: 1.1 $' keyword.

getRevision()
-------------

   Will return the revision of the local file. Will return undef in case
of problems.

Handling the VCS part
=====================

archiveLog(...)
---------------

   Will modify the log (not the file) of a specified revision of the file
in the VCS base.

   Parameters are :

   * info: info hash that contains the new informations to update the log
     in the VCS base

   * revision: revision number of the log to update.

   Returns an array ref containing the output of the VCS command in case
of success, undef in case of problems.

Perl class to manage VCS revision.
**********************************

NAME
====

   VcsTools::Version - Perl class to manage VCS revision.

SYNOPSIS
========

   No synopsis given. This object is better used with the History module.

DESCRIPTION
===========

   This class represents one version of a VCS file. It holds all the
information relevant to this version including the parent revision, child
revision, branches revisions and do on.

   Its main function is to provides the functionnality to manage versions
(inluding branches and merges) of a Vcs file:

   * Find the common ancestor of 2 revisions (but this does not yet take
     merges into account)

   * Find the oldest parent of a revision

   * Find all children of a revision (taking merges into account)

   All these information can be stored in a database. See
Puppet/Body, for more details.

CONVENTION
==========

   The following words may be non ambiguous for native english speakers,
but it is not so with us french people. So I prefer clarify these words:

   * Log: Refers to the information stored with one version.

   * History: Refers to a collection of all logs of all versions stored in
     the VCS base.

Constructor
===========

new(...)
--------

   Parameters are :

   * All parameter of `"Constructor"', see Puppet/Body,

   * revision : revision number of this version

   * manager: the ref of the history object.

Methods
=======

update(...)
-----------

   Parameters are:

   * info: hash ref of log informations

   This methods takes a hash reference containing all informations
extracted from the VCS log of this version. Then all other complementary
informations (such as upper revision, branches revisions, revision that
were eventually merged in this one) are computed and stored in the
database.

getRevision()
=============

   Returns the revision number of this object.

getUpperRev()
=============

   Returns the revision number of the "parent" of this object.

hasParent()
===========

   Returns true if this version has a "parent" object.

findAncestor(other_revision_number)
===================================

   Returns the ancestor number of this revision and the other.

   Returns undef in case of problems.

findOldest()
============

   Returns the version number of the oldest parent in the revision tree
that it can find.

getLog()
========

   Returns the log of this version object.

AUTHOR
======

   Dominique Dumont, Dominique_Dumont@grenoble.hp.com

   Copyright (c) 1998-1999 Dominique Dumont. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   perl(1), Puppet:Body:(3), VcsTools::History(3)

Verilog language utilities
**************************

NAME
====

   Verilog::Language - Verilog language utilities

SYNOPSIS
========

     use Verilog::Language;

     $result = Verilog::Language::is_keyword ($symbol_string)
     $result = Verilog::Language::is_compdirect ($symbol_string)
     $result = Verilog::Language::number_value ($number_string)
     $result = Verilog::Language::number_bits  ($number_string)
     @vec    = Verilog::Language::split_bus ($bus)

DESCRIPTION
===========

   This package provides useful utilities for general use with the Verilog
Language.  General functions will be added as needed.

Verilog::Language::is_keyword ($symbol_string)
     Return true if the given symbol string is a Verilog reserved keyword.

EXAMPLE
=======

     print Verilog::Language::is_keyword ("module");
        1
     print Verilog::Language::is_keyword ("signalname");
        undef

Verilog::Language::is_compdirect ($symbol_string)
     Return true if the given symbol string is a Verilog compiler
     directive.

EXAMPLE
=======

     print Verilog::Language::is_compdirect ("`include");
        1
     print Verilog::Language::is_compdirect ("`MYDEFINE");
        undef

Verilog::Language::number_value ($number_string)
     Return the numeric value of a Verilog value, or undef if incorrectly
     formed.  Since it is returned as a signed integer, it may fail for
     over 31 bit integers.

EXAMPLE
=======

     print Verilog::Language::number_value ("32'h13");
        19
     print Verilog::Language::number_value ("32'p2");
        undef

Verilog::Language::number_bits ($number_string)
     Return the number of bits in a value string, or undef if incorrectly
     formed, _or_ not specified.

EXAMPLE
=======

     print Verilog::Language::number_bits ("32'h13");
        32

Verilog::Language::split_bus ($bus)
     Return a list of expanded arrays.  When passed a string like
     "foo[5:1:2,10:9]", it will return a array with ("foo[5]", "foo[3]",
     ...).  It correctly handles connectivity expansion also, so that
     "x[1:0] = y[3:0]" will get intuitive results.

DISTRIBUTION
============

   The latest version is available from
`http://www.ultranet.com/~wsnyder/verilog-perl'.

AUTHORS
=======

   Wilson Snyder <wsnyder@wsnyder.org>

parse Verilog language files
****************************

NAME
====

   Verilog::Parse - parse Verilog language files

WARNING
=======

   This module is no longer supported.  Use Verilog::Parser instead.

SYNOPSIS
========

     use Verilog::Parse;

     $parser = new Verilog::Parse;

     sub function {my ($parser, $what, $info) = @_; ...}
     $parser->callback ("xxx", \&function)

     $string = $parser->unreadback ();

     $parser->Verilog::Parse::parse ($FileHandle)

DESCRIPTION
===========

   This package implements parsing of the Verilog language.  A file is
parsed and callbacks are called for various entities in the file, as they
occur.

WARNING
=======

   This module is no longer supported.  Use Verilog::Parser instead.

$parser->new
     Create a new parser.

$parser->callback ("token", \&function)
     Request that when the parser hits the given token, function will be
     called.  The tokens that may be parsed are:

          "COMMENT"	Any text in // or /**/ comments.
          "STRING"	Any quoted string, including the quotes.
          "KEYWORD"	A Verilog keyword.  (See C<Verilog::Language>)
          "SYMBOL"	A textual non-keyword
          "OPERATOR"	A non-alphanumeric operator.
          "NUMBER"	A number.

     The callback will get three arguments.  The first is the parser
     (self).  The second is the exact type of token, one of those listed
     above.  Third is a string with the symbol, number, etc.

$parser->parse ($FileHandle)
     Read input from the filehandle, and perform callbacks as needed.

$parser->unreadback ()
     Return any input string from the file that has not been sent to the
     callback.  This will include whitespace and tokens which did not have
     a callback.  (For example comments, if there is no comment callback.)
     This is useful for recording the entire contents of the input, for
     preprocessors, pretty-printers, and such.

EXAMPLE
=======

   Here\'s a simple example which will print every symbol in a verilog
file.  We also remember what line it occured on, just for the heck of it.

   sub symbol_cb {     # Callback from parser when a symbol occurs     sub
function (my ($parser, $what, $info) = @_; ...)
$signals_and_symbols{$info} = $.; }

   sub verilog_read_symbols {     my $filename = shift;

     local %signals_and_symbols = ();	# Signals already found in module

     my $fh = new FileHandle;
     my $parser = new Verilog::Parse;
     $parser->callback ("SYMBOL", \&symbol_cb);
     $fh->open("<$filename") or die "Can't read $filename.";
     $parser->Verilog::Parse::parse ($fh);
     $fh->close;

     foreach $sym (sort (keys %signals_and_symbols)) {
     	print "Symbol $sym\n";
     }
     }

SEE ALSO
========

   `Verilog::ParseSig', `Verilog::Language', FileHandle,

BUGS
====

   This is being distributed as a baseline for future contributions.
Don\'t expect a lot, the parser is still nieve, and there are many awkward
cases that aren\'t covered.

DISTRIBUTION
============

   The latest version is available from
`http://www.ultranet.com/~wsnyder/verilog-perl'.

AUTHORS
=======

   Wilson Snyder <wsnyder@wsnyder.org>

Parse Verilog language files
****************************

NAME
====

   Verilog::Parser - Parse Verilog language files

SYNOPSIS
========

     use Verilog::Parser;

     my $parser = new Verilog::Parser;
     $string = $parser->unreadback ();
     $line   = $parser->line ();
     $parser->parse ($text)
     $parser->parse_file ($filename)

DESCRIPTION
===========

   The `Verilog::Parser' package will tokenize a Verilog file when the
parse() method is called and invoke various callback methods.

   The external interface to Verilog::Parser is:

$parser = Verilog::Parser->new
     Create a new Parser.

$parser->parse ($string)
     Parse the $string as a verilog file.  Can be called multiple times.
     The return value is a reference to the parser object.

$parser->parse_file ($filename);
     This method can be called to parse text from a file.  The argument can
     be a filename or an already opened file handle. The return value from
     parse_file() is a reference to the parser object.

$parser->unreadback ()
     Return any input string from the file that has not been sent to the
     callback.  This will include whitespace and tokens which did not have
     a callback.  (For example comments, if there is no comment callback.)
     This is useful for recording the entire contents of the input, for
     preprocessors, pretty-printers, and such.

$parser->line ($set)
     Return (if $set is undefined) or set current line number.

$parser->filename ($set)
     Return (if $set is undefined) or set current filename.

   In order to make the parser do anything interesting, you must make a
subclass where you override one or more of the following methods as
appropriate:

$self->comment ( $token )
     This method is called when any text in // or /**/ comments are
     recognized.  The first argument, $token, is the contents of the
     comment excluding the comment delimiters.

$self->string ( $token )
     This method is called when any text in double quotes are recognized.
     The first argument, $token, is the contents of the string including
     the quotes.

$self->keyword ( $token )
     This method is called when any Verilog keyword is recognized.  The
     first argument, $token, is the keyword.

$self->symbol ( $token )
     This method is called when any Verilog symbol is recognized.  A
     symbol is considered a non-keyword bareword.  The first argument,
     $token, is the symbol.

$self->operator ( $token )
     This method is called when any symbolic operator (+, -, etc) is
     recognized.  The first argument, $token, is the operator.

$self->number ( $token )
     This method is called when any number is recognized.  The first
     argument, $token, is the number.  The Verilog::Language::number_value
     function may be useful for converting a Verilog value to a perl
     integer.

EXAMPLE
=======

   Here\'s a simple example which will print every symbol in a verilog
file.

   package MyParser; use Verilog::Parser;  @ISA = qw(Verilog::Parser);

   # parse, parse_file, etc are inherited from Verilog::Parser sub new {
 my $class = shift;     #print "Class $class\n";     my $self =
$class->SUPER::new();     # we could have inherited new, but we want to
initialize symbols     %{$self->{symbols}} = ();     bless $self, $class;
  return $self; }

   sub symbol {     my $self = shift;     my $token = shift;

   $self->{symbols}{$token}++; }

   sub report {     my $self = shift;

     foreach my $sym (sort keys %{$self->{symbols}}) {
     	 printf "Symbol %-30s occurs %4d times\n",
     	 $sym, $self->{symbols}{$sym};
     }
     }

   package main;

   my $parser = MyParser->new(); $parser->parse_file (shift);
$parser->report();

SEE ALSO
========

   `Verilog::ParserSig', `Verilog::Language', `vrename'

BUGS
====

   This is being distributed as a baseline for future contributions.
Don\'t expect a lot, the Parser is still nieve, and there are many awkward
cases that aren\'t covered.

   The parser currently assumes the string it is passed ends on a newline
boundary.  It should be changed to allow arbitrary chunks.

DISTRIBUTION
============

   The latest version is available from
`http://www.ultranet.com/~wsnyder/verilog-perl'.

AUTHORS
=======

   Wilson Snyder <wsnyder@wsnyder.org>

Signal Parsing for Verilog language files
*****************************************

NAME
====

   Verilog::SigParser - Signal Parsing for Verilog language files

SYNOPSIS
========

     use Verilog::SigParser;

     my $parser = new Verilog::SigParser;
     $string = $parser->unreadback ();
     $line   = $parser->line ();
     $parser->parse ($text)
     $parser->parse_file ($filename)

DESCRIPTION
===========

   The `Verilog::SigParser' package builds upon the Verilog::Parse function
to provide callbacks for when a signal is declared, a module instantiated,
or a module defined.

   The external interface to Verilog::SigParser is described in the
Verilog::Parser module.

   In order to make the parser do anything interesting, you must make a
subclass where you override one or more of the following methods as
appropriate:

$self->module ( $keyword, $name )
     This method is called when a module is defined.

$self->task ( $keyword, $name )
     This method is called when a module is defined.

$self->function ( $keyword, $name )
     This method is called when a function is defined.

$self->signal_decl ( $keyword, $signame, $vector, $mem )
     This method is called when a signal is declared.  The first argument,
     $keyword is ('input', 'output', etc), the second argument is the name
     of the signal.  The third argument is the vector bits or "".  The
     fourth argument is the memory bits or "".

$self->instant ( $module, $cell )
     This method is called when a instantantiation is defined.  The first
     parameter is the name of the module being instantiated, and the second
     parameter is the name of the cell.

SEE ALSO
========

   `Verilog::Parser', `Verilog::Language',

BUGS
====

   This is being distributed as a baseline for future contributions.
Don\'t expect a lot, the Parser is still nieve, and there are many awkward
cases that aren\'t covered.

DISTRIBUTION
============

   The latest version is available from
`http://www.ultranet.com/~wsnyder/verilog-perl'.

AUTHORS
=======

   Wilson Snyder <wsnyder@wsnyder.org>

Perl interface to the Video4linux framegrabber interface.
*********************************************************

NAME
====

   Video::Capture::V4l - Perl interface to the Video4linux framegrabber
interface.

SYNOPSIS
========

     use Video::Capture::V4l;

DESCRIPTION
===========

   Not documentation AGAIN! Please see the scripts grab, inexer or vbi that
are packaged in the distribution and direct any question and feature
requests (as well as bug reports) to the author.

Exported constants
==================

   The following hideous constants are defined in the
`Video::Capture::V4l' package, but you seldom need to use them.

     AUDIO_BASS
     AUDIO_MUTABLE
     AUDIO_MUTE
     AUDIO_TREBLE
     AUDIO_VOLUME
     CAPTURE_EVEN
     CAPTURE_ODD
     MAX_FRAME
     MODE_AUTO
     MODE_NTSC
     MODE_PAL
     MODE_SECAM
     PALETTE_COMPONENT
     PALETTE_GREY
     PALETTE_HI240
     PALETTE_PLANAR
     PALETTE_RAW
     PALETTE_RGB24
     PALETTE_RGB32
     PALETTE_RGB555
     PALETTE_RGB565
     PALETTE_UYVY
     PALETTE_YUV410P
     PALETTE_YUV411
     PALETTE_YUV411P
     PALETTE_YUV420
     PALETTE_YUV420P
     PALETTE_YUV422
     PALETTE_YUV422P
     PALETTE_YUYV
     SOUND_LANG1
     SOUND_LANG2
     SOUND_MONO
     SOUND_STEREO
     TUNER_LOW
     TUNER_MBS_ON
     TUNER_NORM
     TUNER_NTSC
     TUNER_PAL
     TUNER_RDS_ON
     TUNER_SECAM
     TUNER_STEREO_ON
     TYPE_CAMERA
     TYPE_TV
     VC_AUDIO
     VC_TUNER
     TYPE_CAPTURE
     TYPE_CHROMAKEY
     TYPE_CLIPPING
     TYPE_FRAMERAM
     TYPE_MONOCHROME
     TYPE_OVERLAY
     TYPE_SCALES
     TYPE_SUBCAPTURE
     TYPE_TELETEXT
     TYPE_TUNER

AUTHOR
======

   Marc Lehmann <pcg@goof.com>

LICENSE
=======

   This module is available under GPL only (see the file COPYING for
details), if you want an exception please contact the author, who might
grant exceptions freely ;)

SEE ALSO
========

   perl(1).

Functions to manipulate vbi fields & lines.
*******************************************

NAME
====

   Video::Capture::VBI - Functions to manipulate vbi fields & lines.

SYNOPSIS
========

     use Video::Capture::VBI;

DESCRIPTION
===========

new
     Create a new VBI decoder object. VBI decoding often requires state,
     which this object represents

reset
     Reset the state (e.g. after switching a channel).

Many, many frequency constants and lists.
*****************************************

NAME
====

   Video::Frequencies - Many, many frequency constants and lists.

SYNOPSIS
========

     use Video::Frequencies;

     while (my($name,$list) = each %CHANLIST) {
        print "$name\n";
        while (my($channel,$freq) = each %$list) {
           printf "   %-4s %9d\n", $channel, $freq;
        }
        print "\n";
     }

DESCRIPTION
===========

   This module exports (yes, exports!) frequency constants as well as
hashes with channel => frequency relations for digital and analog video
and audio broadcast. Another, shorter way to put it is "worldwide
channel/frequency list". All frequencies are given in kHz.

   It's a good idea to use `perldoc -m Video::Frequencies' to get an idea
on how the various constants and lists look like.

Exported Audio Carrier Frequencies
==================================

     NTSC_AUDIO_CARRIER
     PAL_AUDIO_CARRIER_I
     PAL_AUDIO_CARRIER_BGHN
     PAL_AUDIO_CARRIER_MN
     PAL_AUDIO_CARRIER_D
     SEACAM_AUDIO_DKK1L
     SEACAM_AUDIO_BG
     NICAM728_PAL_BGH
     NICAM728_PAL_I

   NICAM 728 32-kHz, 14-bit digital stereo audio is transmitted in 1ms
frames containing 8 bits frame sync, 5 bits control, 11 bits additional
data, and 704 bits audio data.  The bit rate is reduced by transmitting
only 10 bits plus parity of each 14 bit sample, the largest sample in a
frame determines which 10 bits are transmitted.  The parity bits for audio
samples also specify the scaling factor used for that channel during that
frame.  The companeded audio data is interleaved to reduce the influence
of dropouts and the whole frame except for sync bits is scrambled for
spectrum shaping.  Data is modulated using QPSK, at below following
subcarrier freqs

Broadcast Format by Country
===========================

(M) NTSC
     Antigua, Aruba, Bahamas, Barbados, Belize, Bermuda, Bolivia, Burma,
     Canada, Chile, Colombia, Costa Rica, Cuba, Curacao, Dominican
     Republic, Ecuador, El Salvador, Guam Guatemala, Honduras, Jamaica,
     Japan, South Korea, Mexico, Montserrat, Myanmar, Nicaragua, Panama,
     Peru, Philippines, Puerto Rico, St Christopher and Nevis, Samoa,
     Suriname, Taiwan, Trinidad/Tobago, United States, Venezuela, Virgin
     Islands

(B) PAL
     Albania, Algeria, Australia, Austria, Bahrain, Bangladesh, Belgium,
     Bosnia-Herzegovinia, Brunei Darussalam, Cambodia, Cameroon, Croatia,
     Cyprus, Denmark, Egypt, Ethiopia, Equatorial Guinea, Finland, Germany,
     Ghana, Gibraltar, Greenland, Iceland, India, Indonesia, Israel, Italy,
     Jordan, Kenya, Kuwait, Liberia, Libya, Luxembourg, Malaysa, Maldives,
     Malta, Nepal, Netherlands, New Zeland, Nigeria, Norway, Oman,
     Pakistan, Papua New Guinea, Portugal, Qatar, Sao Tome and Principe,
     Saudi Arabia, Seychelles, Sierra Leone, Singapore, Slovenia, Somali,
     Spain, Sri Lanka, Sudan, Swaziland, Sweden, Switzeland, Syria,
     Thailand, Tunisia, Turkey, Uganda, United Arab Emirates, Yemen

(N) PAL
     Argentina (Combination N), Paraguay, Uruguay

(M) PAL (525/60, 3.57MHz burst)
     Brazil

(G) PAL
     Albania, Algeria, Austria, Bahrain, Bosnia/Herzegovinia, Cambodia,
     Cameroon, Croatia, Cyprus, Denmark, Egypt, Ethiopia, Equatorial
     Guinea, Finland, Germany, Gibraltar, Greenland, Iceland, Israel,
     Italy, Jordan, Kenya, Kuwait, Liberia, Libya, Luxembourg, Malaysia,
     Monaco, Mozambique, Netherlands, New Zealand, Norway, Oman, Pakistan,
     Papa New Guinea, Portugal, Qatar, Romania, Sierra Leone, Singapore,
     Slovenia, Somalia, Spain, Sri Lanka, Sudan, Swaziland, Sweeden,
     Switzerland, Syria, Thailand, Tunisia, Turkey, United Arab Emirates,
     Yemen, Zambia, Zimbabwe

(D) PAL
     China, North Korea, Romania, Czech Republic

(H) PAL
     Belgium

(I) PAL
     Angola, Botswana, Gambia, Guinea-Bissau, Hong Kong, Ireland, Lesotho,
     Malawi, Nambia, Nigeria, South Africa, Tanzania, United Kingdom,
     Zanzibar

(B) SECAM
     Djibouti, Greece, Iran, Iraq, Lebanon, Mali, Mauritania, Mauritus,
     Morocco

(D) SECAM
     Afghanistan, Armenia, Azerbaijan, Belarus, Bulgaria, Estonia, Georgia,
     Hungary, Zazakhstan, Lithuania, Mongolia, Moldova, Poland, Russia,
     Slovak Republic, Ukraine, Vietnam

(G) SECAM
     Greece, Iran, Iraq, Mali, Mauritus, Morocco, Saudi Arabia

(K) SECAM
     Armenia, Azerbaijan, Bulgaria, Estonia, Georgia, Hungary, Kazakhstan,
     Lithuania, Madagascar, Moldova, Poland, Russia, Slovak Republic,
     Ukraine, Vietnam

(K1) SECAM
     Benin, Burkina Faso, Burundi, Chad, Cape Verde, Central African
     Republic, Comoros, Congo, Gabon, Madagascar, Niger, Rwanda, Senegal,
     Togo, Zaire

(L) SECAM
     France

Channel->Frequency Relations
============================

   The Channel->Frequency relations are stored in the following hashes. The
keys are the Channel names, the values are the corresponding frequency in
kHz. For example, "arte" is channel "SE6" in the town in Germany I live
in, so, consequently, $PAL_EUROPE{SE6} equals 140250, the frequency I have
to tune my receiver.

     US broadcast          %NTSC_BCAST
     US cable              %NTSC_CABLE
     US HRC                %NTSC_HRC
     JP broadcast          %NTSC_BCAST_JP
     JP cable              %NTSC_CABLE_JP
     Australia             %PAL_AUSTRALIA
     Europe                %PAL_EUROPE
     Europe East           %PAL_EUROPE_EAST
     Italy                 %PAL_ITALY
     Ireland               %PAL_IRELAND
     Newzealand            %PAL_NEWZEALAND

     CCIR frequencies      %FREQ_CCIR_I_III
                           %FREQ_CCIR_SL_SH
                           %FREQ_CCIR_H
     OIRT frequencies      %FREQ_OIRT_I_III
                           %FREQ_OIRT_SL_SH
                           %FREQ_UHF

The List of Lists
=================

   The hash %CHANLIST contains name => channel-list pairs, e.g.
$CHANLIST{"ntsc-bcast"} contains a reference to %NTSC_BCAST.

AUTHOR
======

   Nathan Laredo (laredo@broked.net), adapted to perl by Marc Lehmann
<pcg@goof.com>

Real time, jpeg-like video compression.
***************************************

NAME
====

   Video::RTjpeg - Real time, jpeg-like video compression.

SYNOPSIS
========

     use Video::RTjpeg;

DESCRIPTION
===========

read, create and edit .xawtvrc's.
*********************************

NAME
====

   Video::XawTV - read, create and edit .xawtvrc's.

SYNOPSIS
========

     use Video::XawTV;

     $rc = new Video::XawTV;
     # - or -
     $rc = new Video::XawTV "$HOME{ENV}/.xawtv";
     $rc->load("otherrcfile");
     $rc->save;
     $rc->save("filename");

     $source = $rc->opt('source');
     $rc->opt('source') = "Television";

     @channels = $rc->channels;
     $rc->channels(@channels);

     print $channels[0]{name};	# Arte
     print $channels[0]{channel};	# E4

DESCRIPTION
===========

   Pardon? Ha! Haa! Hahahahahaha!!!

An easy-to-use VoiceXML server class
************************************

NAME
====

   VoiceXML::Server - An easy-to-use VoiceXML server class

SYNOPSIS
========

     #!/usr/bin/perl -w
     use diagnostics;
     use strict;

     require VoiceXML::Server;
     my $server = VoiceXML::Server->new(avoidfirewall => 1);

     $server->Audio("Pick a number between 1 and 99.");

     my $num = int(rand(99)) + 1;

     while (1) {
         my $guess = $server->Listen(grammar => "NATURAL_NUMBER_THRU_99");
         if ($guess < $num) {
             $server->Audio("No, $guess is too low.  Try again.");
         } elsif ($guess > $num) {
             $server->Audio("No, $guess is too high.  Try again.");
         } else {
             $server->Audio("That's right, my number was $num.  OK, " .
                            "let's play again.  I'm thinking of a " .
                            "different number.");
             $num = int(rand(99)) + 1;
         }
     }

DESCRIPTION
===========

   `VoiceXML::Server' is a class implementing a simple server for VoiceXML
applications.  It was designed in particular to work with Tellme Studio (
http://studio.tellme.com/ ), although it should also work with other
VoiceXML products.

   Using this library, you can make programs that you interact with over
the phone.  Using Tellme Studio, you can develop and debug your program by
calling a toll-free number.  You can then publish your finished
application to be a part of the main Tellme service, at 1-800-555-TELL.

   Applications written using `VoiceXML::Server' install as a CGI scripts.
However, unlike most web server software, they do not get repeatedly
executed every time the user responds to an interaction.  Instead, the
script gets invoked only once per user, and it can remember the state of
the interaction on the stack and in local variables.  This is a much, much
easier way to code than traditional web solutions provide, as the above
example should illustrate.

   The disadvantage of this approach is that it can be more expensive to
support, and performance can suffer compared to hand-tuned VoiceXML code.

INSTALLATION
============

   The trickiest part of all this is setting up Tellme Studio and an
initial application and getting things up and limping.  Once you've done
that, it's easy to tweak the application to make it do virtually anything
you can think of.

   Here's the steps to get the above "guess a number" example code up and
running.

   First, get yourself a webserver where you can install CGI scripts.
Learning about that is beyond the scope of this document.

   Next, make sure that the version of perl on that server includes this
VoiceXML::Server module.  This is done by the usual CPAN method of
unpacking the tarball and running the following commands (you may have to
be root to do 'make install'):

     perl Makefile.PL
     make
     make test
     make install

   Next, cut and paste the above example code into a file on your server.
I'll assume that file is called "guessanumber.cgi".  You may need to
change the first line to point to your perl executable.

   Next, you can run the "guessanumber.cgi" executable on the command
line.  The VoiceXML::Server library will automatically detect that you are
running on the command line instead of being served from a webserver, and
will play the game in dumb terminal mode.  This is a very useful technique
for debugging the logic of your program without worrying about all the
telephony details.

   When you can run guessanumber.cgi on the command line, then you know
you have all the perl setup done properly.  Next, go to
http://studio.tellme.com/ and create an account by clicking the "join
studio" link.  This is all pretty self-explainatory.

   Once you're able to log into your Tellme Studio account, and have
accepted the terms of service, you need tell Studio where your application
lives.  Click on the "MyStudio" link at left of the screen.  Log in if
necessary.  Make sure the "Application URL" tab is selected; click on it
if it is not.  Then type the full URL to get to your guessanumber.cgi
script, and click the "Update" button.

   At this point, you should be able to call the toll-free number listed
on that page.  Enter your Studio Developer ID and PIN on the phone, and
you should find yourself playing the "guess a number" game.

METHODS
=======

   The following methods are available:

$server = VoiceXML::Server->new([name => value, ...]);
     Constructs the server object.  Can take the following named arguments:

    minport
          Specifies the smallest port number to try and use.  Defaults to
          7500.

    maxport
          Specifies the biggest port number to try and use.  Defaults to
          7550.

    avoidfirewall
          If set to 1 (as in the example at the top of this document), then
          extra stuff will be done to avoid firewalls.  VoiceXML::Server
          works by spawning off a new server process, speaking the HTTP
          protocol, usually on a port between 7500 and 7550.  Sometimes
          firewalls will get in the way and prevent the VoiceXML browser
          from reaching these ports.  If you turn on avoidfirewall, then
          things will always work, but there will be a noticable
          performance penalty.  If at all possible, don't use this.

          If all the ports in the designated range are already being used,
          it will continue to try and use a higher port number, but will
          turn on the avoidfirewall behavior.  So, you can just punch a
          few ports through your firewall, and have things work even if
          those get filled up.

    debug
          If you set debug to 1, then files will be created in /tmp
          containing debugging output.  This is very useful to determine
          what causes crashes or weird behaviors.  But remember, the first
          thing to try is just running your program on the command line.

$server->Audio([wav => 'file.wav'], [tts =>'text here']);
     The `Audio' method takes up to two named parameters, wav and tts.  At
     least one of these must be provided.

    wav
          wav specifies a .wav audio file.  This file will be played.

    tts
          tts specifies plain text.  (tts stands for Text To Speech.)  This
          will be read in a computerized voice over the phone if a .WAV
          file isn't specified or isn't found.

     You can also call `Audio' with one or two non-named parameters.  If
     you pass it only one parameter, it is assumed to be a tts value.  If
     you pass it two parameters, the first one is treated as a wav value,
     and the second as a tts value.

$server->Pause(milliseconds => $num)
     The Pause method introduces a pause of the given number of
     milliseconds. Use it between pieces of audio so that the audio sounds
     more natural.  It must be called using the named parameter syntax.

$server->Listen(grammar => $grammar, [nomatch => $nomatchstr],  [noinput => $noinputstr], [timeout => $seconds]);
     The Listen method will wait for the user to say something, and return
     that value.

    grammar => $grammar
          grammar specifies the set of valid expressions that a user can
          say at this point.  To learn more about grammars, please see the
          Tellme Studio documentation at
          http://studio.tellme.com/grammarref/.  You must specify either
          grammar or grammarsrc.

    grammarsrc => $grammarfile
          grammarsrc specifies a file containing a grammar.  The grammar
          file will be downloaded in a separate server transaction, much
          as audio files (or image files in the HTML world) get downloaded
          separately.  This is the right thing to do if your grammar is
          very big and does not dynamically change.

    nomatch => $nomatch
          nomatch specifies what value to return if the user says something
          that could not be matched by the grammar.  If you do not give
          this parameter, then the VoiceXML::Server library will
          automatically tell the user it didn't understand and will
          reprompt them.  This behavior does not always work out so well,
          though, and it is a good idea to provide your own nomatch
          handling.

    noinput => $noinput
          noinput specifies what value to return if the user does not say
          anything.  If you do not give this parameter, then the
          VoiceXML::Server library will automatically tell the user it
          didn't hear anything and will reprompt them.  This behavior does
          not always work out so well, though, and it is a good idea to
          provide your own noinput handling.

    timeout => $seconds
          timeout specifies how many seconds to wait before generating a
          noinput event.  If you do not specify one, a platform default
          value is used.

$server->GoToURL(url)
     `GoToURL' is used to exit your application.  It specifies a URL of
     another VoiceXML page that should be loaded.

CHANGE LOG
==========

     * $Log: Server.pm,v $
     * Revision 1.6  2000/10/03 22:07:08  weissman
     * Fixed minor typo.
     *
     * Revision 1.5  2000/10/03 19:17:25  weissman
     * Added "Cache-Control: no-cache" header.
     *
     * Revision 1.4  2000/09/29 22:35:54  weissman
     * Added 'grammarsrc' parameter to Listen(), so that you can now specify
     * a separate grammar file.
     *
     * Revision 1.3  2000/09/27 22:23:53  weissman
     * GoToURL() wasn't working if given a relative URL.
     *
     * Revision 1.2  2000/09/27 18:22:05  weissman
     * Allow specifying the range of ports to use.
     *
     * Revision 1.1  2000/09/26 23:26:53: weissman
     * Initial release of Server::VoiceXML module.

AUTHOR
======

   Terry Weissman <weissman@tellme.com>

   Web page: http://studio.tellme.com/downloads/VoiceXML-Server/

a module for reading and writing WDDX packets
*********************************************

NAME
====

   WDDX.pm - a module for reading and writing WDDX packets

SYNOPSIS
========

     use WDDX;
     my $wddx = new WDDX;

     ##########################
     ## Serialization example

     my $wddx_hash = $wddx->hash( {
             str     =>  $wddx->string( "Welcome to WDDX!\n" ),
             num     =>  $wddx->number( -12.456 ),
             date    =>  $wddx->datetime( date ),
             bool    =>  $wddx->boolean( 1 ),
             arr     =>  $wddx->array( [
                         $wddx->boolean( 0 ),
                         $wddx->number( 10 ),
                         $wddx->string( "third element" ),
                     ] ),
             rec     =>  $wddx->recordset(
                         [ "NAME", "AGE" ],
                         [ "string", "number" ],
                         [
                             [ "John Doe", 34 ],
                             [ "Jane Doe", 25 ],
                             [ "Fred Doe", 90 ],
                         ]
                     ),
             obj     =>  $wddx->hash( {
                         str => $wddx->string( "a string" ),
                         num => $wddx->number( 3.14159 ),
                     } ),
             bin     => $wddx->binary( $img_data ),
             null    => $wddx->null(),
         } );

     print $wddx->header;
     print $wddx->serialize( $wddx_hash );

     ##########################
     ## Deserialization example

     my $wddx_request = $wddx->deserialize( $packet );

     # Assume that our code expects an array
     $wddx_request->type eq "array" or die "Invalid request";
     my $array_ref = $wddx_request->as_arrayref;

DESCRIPTION
===========

About WDDX
----------

   This is from the WDDX.org web site: "The Web Distributed Data Exchange,
or WDDX, is a free, open XML-based technology that allows Web applications
created with any platform to easily exchange data with one another over
the Web."

   For more information about WDDX, visit http://www.wddx.org/. For
information about using Perl with WDDX (including examples) you can also
visit http://www.scripted.com/wddx/.

WDDX and Perl
-------------

   WDDX defines basic data types that mirror the data types available in
other common programming languages. Many of these data types don't have
corresponding data types in Perl. To Perl, strings, numbers, booleans, and
dates are just scalars. However, in order to communicate effectively with
other languages (and this is the point of WDDX), you do have to learn the
basic WDDX data types. Here is a table that maps the WDDX data type to
Perl, along with the intermediate object WDDX.pm represents it as:

     WDDX Type      WDDX.pm Data Object      Perl Type
     ---------      -------------------      ---------
     String         WDDX::String             Scalar
     Number         WDDX::Number             Scalar
     Boolean        WDDX::Boolean            Scalar (1 or "")
     Datetime       WDDX::Datetime           Scalar (seconds since epoch)
     Null           WDDX::Null               Scalar (undef)
     Binary         WDDX::Binary             Scalar
     Array          WDDX::Array              Array
     Struct         WDDX::Struct             Hash
     Recordset      WDDX::Recordset          WDDX::Recordset

   In languages that have data types similar to the WDDX data types, the
WDDX modules allow you to convert directly from a variable to a WDDX
packet and vice versa. This Perl implementation is different; here you
must always go through an intermediate stage where the data is represented
by an object with a corresponding data type. These objects can be
converted to a WDDX packet, converted to a basic Perl type, or converted
to JavaScript code (which will recreate the data for you in JavaScript).
We will refer to these objects as *data objects* throughout this
documentation.

Requirements
============

   This module requires XML/Parser, and
MIME/Base64, which are both available on CPAN at
http://www.cpan.org/. Windows users note: These modules use compiled code,
but I have been told that they are both included with recent distributions
of ActiveState Perl.

METHODS
=======

new
     This creates a new WDDX object. You need one of these to do pretty
     much anything else. It doesn't take any arguments.

$wddx->deserialize( $string_or_filehandle )
     This method deserializes a WDDX packet and returns a data object. Note
     that you can pass either a string or a reference to an open filehandle
     containing a packet (XML::Parser is flexible this way):

          $wddx_obj = $wddx->deserialize( $packet );     # OR
          $wddx_obj = $wddx->deserialize( \*HANDLE );

     If WDDX.pm or the underlying XML/Parser, finds any
     errors with the structure of the WDDX packet, then it will die with
     an error message that identifies the problem. If you don't want this
     to terminate your script, you will have to place this call within an
     eval block to trap the die.

$wddx->serialize( $wddx_obj )
     This accepts a data object as an argument and returns a WDDX packet.
     This method calls the as_packet() method on the data object it
     receives. However, this method does provide one feature that
     as_packet() does not. If `$WDDX::INDENT' is set to a defined value,
     then the generated WDDX packet is indented using `$WDDX::INDENT' as
     the unit of indentation. Otherwise packets are generated without extra
     whitespace.

     Note that the generated packet is not a valid XML document without
     the header, see below.

$wddx->header
     This returns a header that should accompany every serialized packet
     you send.

WDDX DATA OBJECTS
=================

Common Methods
--------------

   All of the WDDX data objects share the following common methods:

$wddx_obj->type
     This returns the data type of the object. It is lowercase and maps to
     the package name without the WDDX prefix. For example, type will
     return "string" for WDDX::String objects, "datetime" for
     WDDX::Datetime objects, etc.

$wddx_obj->as_packet
     This returns a WDDX packet for the object. You can also do this by
     passing the object to the `$wddx-'serialize> method. See the warning
     in `$wddx-'header>.

$wddx_obj->as_javascript( $js_varname )
     This method takes the name of a JavaScript variable and returns the
     actual JavaScript code to assign this data object to the given
     JavaScript variable. No temporary variables are created to avoid any
     danger of variable name collisions.

     Example:

          $options[0] = $wddx->string( "First Choice" );
          $options[1] = $wddx->string( "Second Choice" );
          $options[2] = $wddx->string( "Third Choice" );
          $w_array    = $wddx->array( \@options );
          print $w_array->as_javascript( "myArray" );

     This prints the text (new lines added for readability):

          myArray=new Array();
          myArray[0]="First Choice";
          myArray[1]="Second Choice";
          myArray[2]="Third Choice";

     All data types are supported, and arrays and hashes (structs) can nest
     to any level. Recordset and binary objects require the JavaScript
     WddxRecordset and WddxBinary constructors. The easiest way to include
     these is to add a reference to the wddx.js file:

          <SCRIPT NAME="javascript" SRC="wddx.js"></SCRIPT>

     wddx.js is the WDDX library for JavaScript. It is available as part of
     the WDDX SDK at http://www.wddx.org/.

WDDX::String
------------

$wddx->string( 'Just a bunch of text...' )
     This creates a WDDX string object. Strings contain 8 bit characters,
     can be any length, and should not include embedded nulls. However,
     control characters and characters that have special meaning for XML
     (like <, >, and E<amp>) are safely encoded for you.

$w_string->as_scalar
     This returns the value of the WDDX::String as a Perl scalar.

WDDX::Number
------------

$wddx->number( 3.14159 )
     This creates a WDDX number object. Numbers are restricted to
     +/-1.7e308 and if you exceed these bounds this method dies with an
     error. Floating point numbers are restricted to 15 digits of accuracy
     past the decimal. If you exceed this then the number is truncated to
     15 digits with a warning. If you pass a non-numeric scalar to this,
     then it is simply treated as a number: Perl will attempt to translate
     it, will probably use zero, and will issue a warning.

$w_number->as_scalar
     This returns the value of the WDDX::Number as a Perl scalar.

WDDX::Boolean
-------------

$wddx->boolean( 1 )
     This creates a WDDX boolean object. It simply tests the argument in a
     boolean context, so "0" and "" are false and anything else is true.

$w_boolean->as_scalar
     This returns the value of the WDDX::Boolean as a Perl scalar. True is
     represented by 1 and false is represented by an empty string.

WDDX::Datetime
--------------

$wddx->datetime
     This creates a WDDX Datetime object.

$w_datetime->use_timezone_info( 1 )
     This sets or reads the flag that says whether to include the timezone
     info (local hour and minute offset from UTC) in WDDX packets created
     from this object. By default this is turned on for new objects. You
     can turn it off by passing a false (but not undef) argument to this
     method.

     When a WDDX::Datetime object is deserialized from a packet, this
     method will indicate whether timezone information was present in that
     packet.

$w_datetime->as_scalar
     This returns the value of the WDDX::Datetime as a Perl scalar. It
     contains the number of seconds since the epoch localized for the
     current machine (like Perl's built-in time function). This number can
     be passed into Perl's localtime function.

WDDX::Null
----------

$wddx->null()
     This creates a WDDX null object. This is roughly the equivalent of
     undef in Perl. It takes no arguments.

$w_datetime->as_scalar
     This simply returns undef (this was a hard one to code :).

WDDX::Binary
------------

$wddx->binary( $binary_data )
     This creates a WDDX binary object. It takes a scalar containing any
     data, which will be base64 encoded before being serialized into the
     packet.

WDDX::Array
-----------

$wddx->array( [ $wddx_obj1, $wddx_obj2, ... ] )
     This creates a WDDX::Array object. It takes a reference to an array
     containing data objects. You must construct a WDDX data object for
     each element of an array before adding them to the array. WDDX::Arrays
     can contain any other WDDX data type and do not need to be of a
     uniform type, so one array can contain a WDDX::String, a
     WDDX::Number, and a WDDX::Struct, for example.

     If you need to create an array of uniform types, Perl's built-in map
     function makes this easy. If you have a standard Perl array called
     `@array', you can generate a WDDX::Array of WDDX::String objects like
     this:

          my @obj_array = map $wddx->number( $_ ), @array;
          my $wddx_array = $wddx->array( \@obj_array );

     If you need to serialize more complicated array structures, refer to
     `array2wddx' in the UTILITY METHODS section.

$wddx_array->as_arrayref()
     This returns a reference to a Perl array. Every element in the
     WDDX::Array is recursively deserialized to Perl data structures. Only
     WDDX::Recordsets remain as WDDX data objects.

$wddx_array->get_element( $i )
$wddx_array->get( $i )
     This allows you to get an element of a WDDX::Array as a data object
     instead of having it deserialized to Perl.

$wddx_array->set( $i => $wddx_obj );
     This allows you to set an element in a WDDX::Array. Note that
     `$wddx_obj' should be a WDDX data object of some type.

$wddx_array->splice( $offset, $length, $wddx_obj1, $wddx_obj2, ... );
$wddx_array->splice( $offset, $length );
$wddx_array->splice( $offset );
     This allows you to insert or delete elements in a WDDX::Array using
     the syntax of Perl's built-in splice function.

$wddx_array->length();
     This returns the number of elements in the WDDX::Array object.

$wddx_array->push( $wddx_obj1, $wddx_obj2, ... );
     This will push the given elements onto the WDDX::Array object.

$wddx_array->pop();
     This will pop the last element off the WDDX::Array object and return
     it.

$wddx_array->unshift( $wddx_obj1, $wddx_obj2, ... );
     This will unshift the given elements onto the WDDX::Array object.

$wddx_array->shift();
     This will shift the first element off the WDDX::Array object and
     return it.

WDDX::Struct
------------

$wddx->struct( { key1 => $wddx_obj1, key2 => $wddx_obj2, ... } )
$wddx->hash  ( { key1 => $wddx_obj1, key2 => $wddx_obj2, ... } )
     This creates a WDDX::Struct object. To WDDX, a struct is simply what
     Perl refers to as a hash (or associative array). These two methods are
     aliases so you can use whichever name you prefer.

     There are no restrictions on keys, but values must be WDDX data types.
     Just like with WDDX::Arrays, you have to create a WDDX data type for
     each value you want to insert into a WDDX::Struct.

     Here's how to use Perl's built-in map function to generate a
     WDDX::Struct if all of your values have the same data type.  If you
     have a standard Perl hash called `%hash', you can generate a
     WDDX::Struct of WDDX::String objects like this:

          my %obj_hash = map { $_ => $wddx->number( $hash{$_} } keys %hash;
          my $wddx_hash = $wddx->hash( \@obj_hash );

     If you need to serialize more complicated hash structures, refer to
     `hash2wddx' in the UTILITY METHODS section.

$wddx_array->as_hashref()
     This returns a reference to a Perl hash. Every element in the hash is
     recursively deserialized to Perl data structures. Only
     WDDX::Recordsets remain as data objects.

$wddx_hash->get_element( $key );
$wddx_hash->get( $key );
     This allows you to get an element of a WDDX::Struct as a data object
     instead of having it deserialized to Perl.

$wddx_hash->set( $key => $wddx_obj );
     This allows you to set a key/value pair in a WDDX::Struct. Note that
     `$wddx_obj' should be a WDDX data object of some type.

$wddx_hash->delete( $key );
     This allows you to delete a key from a WDDX::Struct.

$wddx_hash->keys();
     This will return a list of keys for the WDDX::Struct object or the
     number of keys (if called in a scalar context).

$wddx_hash->values();
     This will return a list of values for the WDDX::Struct object or the
     number of values (if called in a scalar context). Note that each one
     of these values should be a WDDX data object of some type.

WDDX::Recordset
---------------

$wddx->recordset( [ NAME_A, NAME_B, ... ], [ TYPE_A, TYPE_B, ... ], [ DATA ] )
     This creates a WDDX::Recordset object. Recordsets hold tabular data.
     There is no corresponding data type in Perl, but it corresponds with
     the type of output you would receive from a SQL query.

     The first argument when constructing a recordset should be a reference
     to an array containing the names of each of the fields. The second
     argument an reference to an array containing the types of each of the
     fields. Field types must be simple, so the valid types are "string",
     "number", "boolean", or "datetime". The last argument is an optional
     reference to an array of arrays - in other words a table of data.
     Note that this table of data contains plain old Perl scalars; you
     should not create WDDX objects for each value as you would for an
     array or a hash.

          $wddx_rec = $wddx->recordset( [ NAME_A, NAME_B, ... ],
                                        [ TYPE_A, TYPE_B, ... ],
                                        [ [ $val_a1, $val_b1, ... ],
                                          [ $val_b1, $val_b2, ... ],
                                          ...
                                        ] )

     This is simple to use with DBI:

     $data = $dbh->selectall_arrayref( "SELECT NAME, AGE FROM TABLE" ) or
       die $dbh->errstr;   $wddx_rec = $wddx->recordset( [ "NAME", "AGE"
     ],                                 [ "string", "number" ],
                         $data );

     Recordsets that are within arrays or hashes are not automatically
     deserialized for you when you deserialize the array or hash. They
     remain as recordset objects. You can use the methods below to access
     the data.

     Note: It is possible to receive a packet for a recordset that does not
     contain any records. In WDDX, the data type for each field is
     determined by looking at how the data in the field has been tagged;
     so if there is no data, then there is no data type information. Thus
     if you deserialize an empty recordset packet, add data to the
     resulting recordset object, and attempt to serialize it back into a
     packet, you will get an error because WDDX.pm will not know what data
     type to assign to the data you added. To avoid this, you should call
     the types() method to set the data types before you serialize a
     recordset object that was created by deserializing a packet. (If this
     explanation makes no sense, reread it a few times; if it still
     doesn't make sense, email me and let me know. :)

$wddx_rec->names
     Returns a reference to an array of the field names. You can also pass
     a reference to an array to set the names.

$wddx_rec->types
     Returns a reference to an array of the field data types. You can also
     pass a reference to an array to set the data types.

$wddx_rec->table
     Returns a reference to an array of rows, each containing an array of
     fields.  You can also pass a reference to an array to set all the
     data at once.

$wddx_rec->num_rows
     Returns the number of rows.

$wddx_rec->num_columns
     Returns the number of columns (or fields in a row).

$wddx_rec->get_row( $row_num )
     Takes an row index (0 base) and returns a reference to an array for
     that row.

$wddx_rec->add_row( [ ARRAY ] )
     Takes a reference to an array and adds this row to the bottom of the
     rows.

$wddx_rec->del_row( $row_num )
     Takes a row index and deletes that row.

$wddx_rec->set_row( $row_num, [ ARRAY ] )
     Takes a row index and a reference to an array. It replaces that row
     with this new array.

$wddx_rec->get_column( $col_name )
     Takes a column name or index (0 base) and returns a reference to an
     array for that column.

$wddx_rec->add_column( 'NAME', 'TYPE', [ ARRAY ] )
     Takes a column name, type, and a reference to an array and adds the
     column to the end of the columns.

$wddx_rec->set_column( 'NAME', [ ARRAY ] )
     Takes a column name or index (0 base) and a reference to an array.
     Replaces the column with the values from this array.

$wddx_rec->del_column( $name )
     Takes a column name or index (0 base) and deletes the column.

$wddx_rec->get_element( $col_name, $row_num )
     Takes a column name or index (0 base) and row number and returns the
     value of the intersecting cell.

$wddx_rec->set_element( $col_name, $row_num, 'New value' )
     Takes a row number, a column number, and a value and sets the value of
     the intersecting cell.

$wddx_rec->get_field( $row_num, $col_num )
     DEPRECATED! Takes a row number and column number and returns the value
     of the intersecting cell.

     This method is deprecated. Because WDDX often refers to columns in a
     recordset as fields, this method name may be confusing. It has been
     replaced by get_element() and will be removed in a future version.

$wddx_rec->set_field( $row_num, $col_num, 'New value' )
     DEPRECATED! Takes a row number, a column number, and a value and sets
     the value of the intersecting cell.

     This method is deprecated. Because WDDX often refers to columns in a
     recordset as fields, this method name may be confusing. It has been
     replaced by set_element() and will be removed in a future version.

Utility Methods
===============

   These methods make it easier to go from Perl to WDDX data objects and
vice versa.

$wddx->wddx2perl( $wddx_obj );
     This takes a WDDX data object and returns a scalar if it is a simple
     data type, an array reference if it is an array, a hash reference if
     it is a struct, and a WDDX::Recordset object if it is a recordset.

$wddx->scalar2wddx( $scalar, [ $type ] );
     This method takes a scalar and a data type and returns the scalar as a
     WDDX data object of the given type. Type should be one of the simple
     WDDX data types (i.e. string, number, boolean, datetime, null, or
     binary), and if it is not supplied, then string is assumed.

     This method is convenient if you have the type stored in a variable,
     since it avoids you having to do a bunch of if/else statements to
     call the corresponding data object constructor.

$wddx->array2wddx( $arrayref, [ $coderef ] );

$wddx->hash2wddx( $hashref, [ $coderef ] );
     These methods attempt to provide a way for you to generate complex
     WDDX data types from complicated Perl structures. In their simplest
     form, they will generate a corresponding WDDX data object by
     serializing all scalars as strings. This may be sufficient for your
     needs, but it likely will not. Thus, these methods also allow you to
     determine the type for each scalar. To do so, you must provide a
     reference to a sub.

     Your sub will be called for each value within the array or a hash you
     supply, as well as each value within any nested arrays or hashes.
     Thus your sub may need to support both hashes and arrays.

     If your sub is called within an array, it will receive the following
     arguments:

          1. the index of the current element
          2. the value of the current element
          3. the text "ARRAY"

          If your sub is called within a hash, it will receive the following
          arguments:

          1. the key of the current pair
          2. the value of the current pair
          3. the text "HASH"

     You must return the type of the data object to construct (e.g.
     "number") or a false value if you want to let the element continue to
     the next rule. The rules for converting elements into WDDX data
     objects are as follows:

     1. If the element is already a WDDX data object, then it is left
     alone.

     2. Your subroutine is called (if provided). If a true value is not
     returned, then we skip to rule 3. If you return an invalid data type,
     then this method dies with an error. If you return a valid data type
     then:

     a. If the current element is a scalar then this element is converted
     to a WDDX data object of the type you specified.

     b. If the current element is a reference to a hash or an array, then
     this hash or array is converted to a WDDX data object with each
     element having the type you specified (this applies to all nested
     arrays and hashes too).

   3. If the current element is a reference to a hash or an array then
`wddx2array' or `wddx2hash' is called on it and your sub (if provided)
propagates.

   4. Any scalars that have not been handled by a previous rule are
treated as strings.

   Here is an example. Assume that you have the following data structure
in Perl:

     $weather_data = {
        title       => "Weather Conditions",
        region      => "San Francisco Bay Area",
        current     => {
          temp      => 72,
          sky       => "mostly clear",
          precip    => undef,
          wind      => 12
        },
        tomorrow    => {
          temps     => [ 62 => 75 ],
          sky       => "partly cloudy",
          precip    => undef,
          winds     => [ 5  => 10 ]
        }
     };

   To convert this to a WDDX object you could create a handler and use it
to create a WDDX object like this:

   $type_sub = sub {     my( $name, $val, $mode ) = @_;     ! defined(
$val )   and return "null";     $name =~ /temp/     and return "number";
 $name =~ /wind/     and return "number";  };

   my $wddx_weather = $wddx->hash2wddx( $weather_data, $type_sub );

   Then you can easily serialize the WDDX object to a packet:

   $WDDX::INDENT = "   ";  print $wddx->serialize( $wddx_weather );

   This prints:

     <wddxPacket version='1.0'>
        <header/>
        <data>
           <struct>
              <var name='tomorrow'>
                 <struct>
                    <var name='temps'>
                       <array length='2'>
                          <number>0</number>
                          <number>1</number>
                       </array>
                    </var>
                    <var name='precip'>
                       <null/>
                    </var>
                    <var name='winds'>
                       <array length='2'>
                          <number>0</number>
                          <number>1</number>
                       </array>
                    </var>
                    <var name='sky'>
                       <string>partly cloudy</string>
                    </var>
                 </struct>
              </var>
              <var name='title'>
                 <string>Weather Conditions</string>
              </var>
              <var name='current'>
                 <struct>
                    <var name='wind'>
                       <number>12</number>
                    </var>
                    <var name='precip'>
                       <null/>
                    </var>
                    <var name='temp'>
                       <number>72</number>
                    </var>
                    <var name='sky'>
                       <string>mostly clear</string>
                    </var>
                 </struct>
              </var>
              <var name='region'>
                 <string>San Francisco Bay Area</string>
              </var>
           </struct>
        </data>
     </wddxPacket>

   Of course, the handler you construct will vary depending on each
particular data structure.

EXAMPLES
========

   I pulled the examples out of here when I realized that this POD was
over 50 screenfuls on a standard term! For more lengthy examples, please
visit http://www.scripted.com/wddx/ or http://www.wddx.org/.

BUGS
====

   WDDX does not support 16 bit character sets (at least not without
encoding them as binary objects).

   Every element of data must be encoded as an object. This increases
memory usage somewhat, and it also means any data you transfer must fit in
memory.

   This is actually a non-bug: XML::Parser untaints data as it parses it.
This is dangerous. WDDX.pm retaints the data it receives from XML::Parser
so you should be safe if you are running in taint mode. Note: WDDX.pm uses
$0 to retaint data, so if you untaint $0 then any subsequent WDDX.pm data
will be untainted too. Taint is explained Perlsec (perl.info).

CREDITS
=======

   Nate Weiss, the man behind the WDDX SDK, has been an especially huge
help.

   David Medinets started an earlier version of a Perl and WDDX module
available at http://www.codebits.com/wddx/.

   The following people have helped provide feedback, bug reports, etc.
for this module:

     Thomas R. Hall
     David J. MacKenzie
     Jon Sala
     Wolfgang ???
     James Ritter
     Miguel Marques
     Vadim Geshel
     Adolfo Garcia
     Sean McGeever
     Allie Rogers
     Ziying Sherwin

AUTHOR
======

   Scott Guelich <scott@scripted.com>

Perl extension for builiding WML Cards according to the browser being used.
***************************************************************************

NAME
====

   WML::Card - Perl extension for builiding WML Cards according to the
browser being used.

SYNOPSIS
========

   use WML::Card;

   my $options= [         ['Option 1', 'http://...'],         ['Option 2',
'http://...'], ];

   my $c = WML::Card->guess('index','Wap Site'); $c->link_list('indice',
undef,  0, $options,  $options); $c->print;

DESCRIPTION
===========

   This perl library simplifies the creation of  WML cards on the fly. It
produces the most suitable wml code for the browser requesting the card.
In this way the one building the cards does not have to worry about the
differences in how  each wap browser displays the wml code. In combination
wht WML::Deck it provides functionality to build WAP applications.

Methods
-------

$card = WML::Card->guess( $id, $title, [$user_agent] );
     This class method constructs a new WML::Card object.  The first
     argument defines the WML card's id and the second argument its title.
     The if the third argument is not defined, the value is obtained from
     $ENV{'HTTP_USER_AGENT'}.

$c->buttons($label, $type, $task, $href)
$c->table ($data,  $title, $offset, $pager, @headers)
$c->link_list($name, $listtitle, $offset, $pager, $data, $align)
$c->value_list($name, $listtitle, $offset,$pager,$data)
     The variable $data is an array reference like: my $menu_items= [
       ['Option 1', 'http://...'],         ['Option 2', 'http://...'], ];

     The variable $pager is the number of items wanted to be displayed in
     each card.

$c->print
$c->info($content)
$c->img($file, $alt)
$c->input($label, $text, $name, $format, $type, $size, $target, $arg);
$c->link($target, $text);
$c->br
AUTHOR
======

   Mariana Alvaro			mariana@alvaro.com.ar

   Copyright 2000 Mariana Alvaro. All rights reserved.  This library is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   WML::Deck

Perl extension for builiding WML Decks.
***************************************

NAME
====

   WML::Deck - Perl extension for builiding WML Decks.

SYNOPSIS
========

   use WML::Card;

   use WML::Deck;

   my @cards;

   my $options= [         ['Option 1', 'http://...'],         ['Option 2',
'http://...'],

   ];

   my $c = WML::Card->guess('index','Wap Site'); $c->link_list('indice',
undef,  0, $options,  $options); push @cards, $c;

   # Build the deck my $wml = WML::Deck->new(@cards); $wml->return_cgi;

DESCRIPTION
===========

   This perl library simplifies the creation of  WML decks on the fly. In
combination with WML::Card it provides functionality to build WML code for
cards and decks.

Methods
-------

$wml = WML::Deck->new(@cards);
     This class method constructs a new WML::Deck object.  The first
     argument is an array of WML::Card objects.

$wml->cache($n);
     This class methos specifies the max-age argument for Cache-Control

$wml->return_cgi;
     This method prints wml code and HTTP headers for the deck.

AUTHOR
======

   Mariana Alvaro			mariana@alvaro.com.ar

   Copyright 2000 Mariana Alvaro. All rights reserved.  This library is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   WML::Card

Send, via email, messages posted to a WWW bulletin board
********************************************************

NAME
====

   WWW::BBSWatch - Send, via email, messages posted to a WWW bulletin board

SYNOPSIS
========

     use WWW::BBSWatch; # should really be a subclass

     sub WWW::BBSWatch::article_list { # generates warning (rightly so)
       my $self = shift;
       my $content = shift;
       return ($$content =~ m%<A HREF="($self->{bbs_url}\?read=\d*)%gs);
     }

     BBSWatch->new(-MAIL => 'me',
       -BBS_URL => 'http://www.foo.org/cgi-bin/bbs.pl')->retrieve;

   See better, working examples below.

DESCRIPTION
===========

   There are many interesting discussions that take place on World Wide Web
Bulletin Boards, but I do not have the patience to browse to each article.
I can process email and newsgroups many times faster than a WWW bulletin
board because of the lag inherent in the web. Instead of ignoring this
wealth of information, *WWW::BBSWatch* was created. It will monitor a
World Wide Web Bulletin Board and email new postings to you. The email
headers are as correct as possible, including reasonable From, Subject,
Date, *Message-Id* and References entries.

   This module requires *LWP::UserAgent* and *MIME::Lite*.

INTERFACE
=========

$b = WWW::BBSWatch->new
     Arguments are:

     `-BBS_URL': The URL of the bulletin board's index page. This field is
     required.

     `-MAIL': The email address to send mail to

     `-DB': Basename of the database that keeps track of visited articles

     `-WARN_TIMEOUT': Number of seconds before warning message is sent
     proclaiming inability to contact BBS_URL page. Default is 10,800 (3
     hours).

     `-MAX_ARTICLES': Maximum number of articles to send in one batch.
     Default is essentially all articles.

     `-VERBOSE': Controls the amount of informative output. Useful values
     are 0, 1, 2. Default is 0 (completely silent).

$b->retrieve([$catchup])
     This method emails new bulletin board messages. If the optional
     parameter catchup is true, messages will be marked as read without
     being emailed. Nothing useful will happen unless the `article_list'
     method is defined to return the list of articles from the BBS's index
     page.

     *WWW::BBSWatch* uses the *LWP::UserAgent* module to retrieve the
     index and articles. It honors firewall proxies by calling the
     `LWP::UserAgent::env_proxy' method. So if you are behind a firewall,
     define the environment variable http_proxy and your firewall will be
     handled correctly.

USER-REFINABLE METHODS
======================

$b->article_list($content_ref)
     Method that returns a list of complete URLs for the articles on the
     bulletin board. It is passed a reference to the contents of the
     bbs_url page. The base version does not do anything.

$b->get_header_info($content_ref)
     Method that returns the header info for the message. It is passed a
     scalar reference to the entire HTML for the message. The method
     should return a list of

          * the poster's email address
          * the poster's name
          * the article's subject
          * the article's timestamp
          * any response-to message URL

     Any values in the return list can be undef, but the more info
     returned, the more useful the email headers will be. The base version
     of the method doesn't do anything.

$b->process_article($content_ref)
     Method that is used to process the article before it is mailed. It is
     passed a reference to the contents of the article. It should return a
     list of the MIME type of the article and a reference to the contents
     of the article. For example, you could refine this method to run the
     article through *HTML::FormatText* so that text messages are sent
     instead of HTML ones. The default method returns the list of
     `text/html' and its argument untouched.

PRACTICAL EXAMPLES
==================

   Here are examples of how I personally use *WWW::BBSWatch*. A useful
assumption is that WWW bulletin boards are programmatically generated so
the HTML of the articles tends to be very regular and predictable. This
allows regular expression matching when pulling header info or processing
articles instead of having to use HTML::Parser or HTML::TreeBuilder.

Monitoring the Perl Modules BBS
===============================

     package MyBBSWatch;

     use strict;
     use vars qw/@ISA/;
     use WWW::BBSWatch;
     @ISA = qw/WWW::BBSWatch/;

     sub get_header_info {
       my $self = shift;
       my $content_ref = shift;

     my ($name, $addr) =
       $$content_ref =~ m%<b>From</b>:\s*(.*) .*;<A HREF="mailto:(.*)">%m;
     $name =~ s/^"|"$//g;
     my ($subj) = $$content_ref =~ m%<H1>(.*)</H1>%m;
     my ($date) = $$content_ref =~ m%^<LI><b>Date</b>: (.*)</LI>$%m;
     $subj = "$subj [MODULES]"; # add tag for easy mail filtering
     return ($addr, $name, $subj, $date);
       }

     sub article_list {
       my $self = shift;
       my $content_ref = shift;

     my $base = $self->_base();
     return map { "$base/$_" }
       ($$content_ref =~ m%<A NAME="\d*" HREF="(msg\d*.html)">%sg);
       }

     # The index page of the Perl Modules list changes every month.
     # For everyone's benefit define a new method to figure out the index URL.
     sub _base {
       my ($y, $m) = (localtime)[5,4];
       return sprintf("http://www.xray.mpe.mpg.de/mailing-lists/modules/%4d-%02d",
                      $y+1900, $m+1);
     }

     package main;

     my $b = MyBBSWatch->new(
       -MAIL      =>'tayers',
       -BBS_URL   =>MyBBSWatch->_base()."/index.html",
       -DB        =>'/home/users/tayers/perl/.modules',
                            );

     $b->retrieve();

Monitoring two BBS's run from the same engine
=============================================

     package TheOakBBSWatch;

     # To watch multiple bulletin boards using the same engine requires
     # defining only one subclass of WWW::BBSWatch since the bulletin board
     # engine will generate the various boards in the same general format

     use vars qw/@ISA/;
     use WWW::BBSWatch;
     @ISA = qw/WWW::BBSWatch/;

     sub get_header_info {
       my $self = shift;
       my $content_ref = shift;

     my ($name) = $$content_ref =~ m%Posted By: <BIG>(.*)</BIG>%m;
     $name =~ s/^"|"$//g; # strip double-quotes

     my ($addr) = $$content_ref =~ m%<A HREF="mailto:.*subject.*>(.*)</A>%m;

     my ($subj) = $$content_ref =~ m%<H1 ALIGN=CENTER>(.*)</H1>%m;
     $subj = "$subj $self->{tag}"; # add a tag for filtering mail

     my ($date) = $$content_ref =~ /.*Date: (.*)$/m;

     my ($parent) = $$content_ref =~ m%In Response To: <A HREF="([^"]*)"%m;

     return ($addr, $name, $subj, $date, $parent);
       }

     sub article_list {
       my $self = shift;
       my $content_ref = shift;
       return ($$content_ref =~ m%<A HREF="($self->{bbs_url}\?read=\d*)%gs);
     }

     # Send articles from these bulletin boards as plain text. Hack the
     # HTML::FormatText to print out the href link as well as the "title". (Is
     # there a proper way to do this?) Changing the behavior this way works in
     # practice because the interesting links in BBS messages (the links that
     # people include in their message) are almost always fully specified. In
     # general this won't work since most links in documents are relative so
     # you need to keep track of the base.
     # Redefine the function in a backhanded way to suppress the "Subroutine
     # redefined" warning.
     use HTML::TreeBuilder;
     use HTML::FormatText;
     {
       local $^W = 0;
       *HTML::Formatter::a_start = sub {
         my ($self, $el) = @_;
         $self->out($el->attr('href')." - ");
         $self->{anchor}++;
         1;
       };
       *HTML::Formatter::img_start = sub {
         my ($self, $el) = @_;
         $self->out($el->attr('src')." - ".($el->attr('alt') || "[IMAGE]"));
       };
     }

     sub process_article {
       my $self = shift;
       my $content_ref = shift;

     $$content_ref =~ s%<H2 ALIGN=CENTER><A NAME="Responses">.*$%</BODY></HTML>%s;
     $$content_ref =~ s%<A NAME="PostResponse"></A>.*$%</BODY></HTML>%s;

     my $tree = HTML::TreeBuilder->new->parse($$content_ref);
     $tree->eof;
     my $text = HTML::FormatText->new(leftmargin=>0)->format($tree);
     $tree->delete;
     return ('text/plain', \$text);
       }

     package main;

     # Advertise the firewall
     $ENV{http_proxy} = 'http://httpproxy:411';

     # Grab the general list
     my $b = TheOakBBSWatch->new(
       -MAIL      =>'tayers',
       -BBS_URL   =>'http://theoak.com/cgi-bin/forum/general.pl',
       -DB        =>'/home/users/tayers/perl/general',
       -MAX_ARTICLES => 250,
       -VERBOSITY =>0,
                            );

     # Break OO design by using knowledge of the underlying data structure.
     # The correct way is to refine new() and pass in -TAG, but this is
     # SO MUCH easier. (Famous last words!) The 'tag' is used in the
     # get_header_info method.
     $b->{tag} = "[OAK-GEN]";

     $b->retrieve();

     # Grab the Tools list
     $b = TheOakBBSWatch->new(
       -MAIL      =>'tayers',
       -BBS_URL   =>'http://theoak.com/cgi-bin/tools1/tools1.pl',
       -DB        =>'/home/users/tayers/perl/tools',
       -MAX_ARTICLES => 250,
       -VERBOSITY =>0,
                            );

     $b->{tag} = "[OAK-TOOL]";

     $b->retrieve();

SEE ALSO
========

   See Perlre (perl.info). At least a passing knowledge of
regular expressions helps quite a bit.

AUTHOR
======

     This module was written by
     Tim Ayers (http://search.cpan.org/search?mode=author&query=tayers).

COPYRIGHT
=========

   Copyright (c) 2000 Tim R. Ayers.

   All rights reserved. This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

Perl extension for translation via babelfish
********************************************

NAME
====

   WWW::Babelfish - Perl extension for translation via babelfish

SYNOPSIS
========

     use WWW::Babelfish;
     $obj = new WWW::Babelfish( 'agent' => 'Mozilla/8.0', 'proxy' => 'myproxy' );
     die( "Babelfish server unavailable\n" ) unless defined($obj);

     $french_text = $obj->translate( 'source' => 'English',
                                     'destination' => 'French',
                                     'text' => 'My hovercraft is full of eels',
     				  'delimiter' => "\n\t",
     				  'ofh' => \*STDOUT );
     die("Could not translate: " . $obj->error) unless defined($french_text);

     @languages = $obj->languages;

DESCRIPTION
===========

   Perl interface to the WWW babelfish translation server.

METHODS
=======

new
     Creates a new WWW::Babelfish object. It can take a named argument for
     user agent.

languages
     Returns a plain array of the languages available for translation.

translate
     Translates some text using Babelfish.

     Parameters:

          source:      Source language
          destination: Destination language
          text:        If this is a reference, translate interprets it as an
                       open filehandle to read from. Otherwise, it is treated
                       as a string to translate.
          delimiter:   Paragraph delimiter for the text; the default is "\n\n".
                       Note that this is a string, not a regexp.
          ofh:         Output filehandle; if provided, the translation will be
                       written to this filehandle.

     If no ofh parameter is given, translate will return the text;
     otherwise it will return 1. On failure it returns undef.

error
     Returns a (hopefully) meaningful error string.

NOTES
=====

   Babelfish translates 1000 characters at a time. This module tries to
break the source text into reasonable logical chunks of less than 1000
characters, feeds them to Babelfish and then reassembles them. Formatting
may get lost in the process.

AUTHOR
======

   Dan Urist, durist@world.std.com

SEE ALSO
========

   perl(1).

Perl extension to build web polls
*********************************

NAME
====

   Poll - Perl extension to build web polls

DESCRIPTION
===========

     Perl module to build and run web polls with built-in administrative capabilities.

SYNOPSIS
========

     use Poll;
     my $poll = new Poll;
     $poll->path('/system/path/to/data/directory');

   # Voting and returning poll results

     $poll->vote($ans_key);
     $html = $poll->get_html();
     print "Content-type: text/html\n\n";
     print $html;

   #- Create a new Poll -#

   	$poll->question('Should Trent Lott change his barber?');
$poll->add_answers( "Yes", "No", "Who's Trent Lott?", etc );
$poll->create();

USAGE
=====

     $poll->path($directory);

   Above system directory must me chmod'ed 666.  Also, it needs to contain
the files qid.dat & questions.dat as world writable.   The graphic to
create the default percentage graph also goes in this directory.

   #- Retrieving Poll Data -#

   	$html = $poll->get_html(<pollid>);

   Returns default html of specific poll results.  With no parameter the
script returns the latest poll.

   -OR-

   	$poll_id = $poll->get(<pollid>);

   This command retrieve the specified poll but returns the poll id rather
than html. Using this method the poll objects can be accessed for
customized formatting of output.  Example below:

     $poll_id = $poll->get(<pollid>);
     print $poll->question();
     foreach ($poll->rkeys) {
     	print $poll->answers->{$_}." = ".$poll->votes->{$_}."<BR>";
     }

   #- Voting on Latest Poll -#

     $poll->vote($ans_key);

   Takes hash key for appropriate $poll->answers.  Keys can be gotten via
$poll->akeys.  Example below:

   	foreach ($poll->akeys) { 		print "Answer =
".$poll->answers->{$_}."\n"; 		print "Key = ".$_."\n"; 	}

   #- Create a new Poll -#

     $poll->question('Should Trent Lott change his barber?');
     $poll->add_answers( "Yes", "No", "Who's Trent Lott?", etc );
     $poll->create();

   This is pretty straight-forward.  There can be an infinite amount of
answers for any giver question but be aware of how it may look when
outputted to html.  The create() command builds the appropriate poll files
in the $poll->path() directory.

   #- To get a hash array of all polls to date -#

     my %all_polls = $poll->list();
     foreach (keys %polls) {
     	print qq|<A HREF="$ENV{SCRIPT_NAME}?poll_id=$_">$all_polls{$_}</A><BR>|;
     }

   This would print out a list of polls with links that could be followed
to view the results of that poll.

DOCUMENTATION
=============

   Documentation and code examples for Poll.pm can be located at
http://www.straphanger.org/~mgammon/poll

   The code examples located at the above url handle both administrative
and standard polling routines. There are currently no manpages for this
module but I will be working on them and post a revision when available.

PREREQUISITES
=============

   Perl 5.004

   May work with earlier versions but hasn't been tested.   Feel free to
email me if you find it does.

AUTHOR
======

   Mike Gammon <mgammon@straphanger.org>

   perl(1).

configurable web traversal engine (for web robots & agents)
***********************************************************

NAME
====

   WWW::Robot - configurable web traversal engine (for web robots & agents)

SYNOPSIS
========

     use WWW::Robot;

     $robot = new WWW::Robot(
         'NAME'     => 'MyRobot',
         'VERSION'  => '1.000',
         'EMAIL'    => 'fred@foobar.com'
     );

     # ... configure the robot's operation ...

     $robot->run( 'http://www.foobar.com/' );

DESCRIPTION
===========

   This module implements a configurable web traversal engine, for a
*robot* or other web agent.  Given an initial web page (URL), the Robot
will get the contents of that page, and extract all links on the page,
adding them to a list of URLs to visit.

   Features of the Robot module include:

   * Follows the *Robot Exclusion Protocol*.

   * Supports the META element proposed extensions to the Protocol.

   * Implements many of the *Guidelines for Robot Writers*.

   * Configurable.

   * Builds on standard Perl 5 modules for WWW, HTTP, HTML, etc.

   A particular application (robot instance) has to configure the engine
using *hooks*, which are perl functions invoked by the Robot engine at
specific points in the control loop.

   The robot engine obeys the Robot Exclusion protocol, as well as a
proposed addition.  See `SEE ALSO' in this node for references to
documents describing the Robot Exclusion protocol and web robots.

QUESTIONS
=========

   This section contains a number of questions. I'm interested in hearing
what people think, and what you've done faced with similar questions.

   * What style of API is preferable for setting attributes? Maybe
     something like the following:

          $robot->verbose(1);
          $traversal = $robot->traversal();

     I.e. a method for setting and getting each attribute, depending on
     whether you passed an argument?

   * Should the robot module support a standard logging mechanism?  For
     example, an LOGFILE attribute, which is set to either a filename, or
     a filehandle reference.  This would need a useful file format.

   * Should the module also support an ERRLOG attribute, with all warnings
     and error messages sent there?

   * At the moment the robot will print warnings and error messages to
     stderr, as well as returning error status. Should this behaviour be
     configurable?  I.e. the ability to turn off warnings.

   The basic architecture of the Robot is as follows:

     Hook: restore-state
     Get Next URL
         Hook: invoke-on-all-url
         Hook: follow-url-test
         Hook: invoke-on-followed-url
         Get contents of URL
         Hook: invoke-on-contents
         Skip if not HTML
         Foreach link on page:
             Hook: invoke-on-link
             Hook: add-url-test
             Add link to robot's queue
     Continue? Hook: continue-test
     Hook: save-state
     Hook: generate-report

   Each of the hook procedures and functions is described below.  A robot
must provide a follow-url-test hook, and at least one of the following:

   * invoke-on-all-url

   * invoke-on-followed-url

   * invoke-on-contents

   * invoke-on-link

CONSTRUCTOR
===========

     $robot = new WWW::Robot( <attribute-value-pairs> );

   Create a new robot engine instance.  If the constructor fails for any
reason, a warning message will be printed, and undef will be returned.

   Having created a new robot, it should be configured using the methods
described below.  Certain attributes of the Robot can be set during
creation; they can be (re)set after creation, using the `setAttribute()'
method.

   The attributes of the Robot are described below, in the *Robot
Attributes* section.

METHODS
=======

run
---

     $robot->run( @url_list );

   Invokes the robot, initially traversing the root URLs provided in
`@url_list', and any which have been provided with the `addUrl()' method
before invoking run().  If you have not correctly configured the robot,
the method will return undef.

   The initial set of URLs can either be passed as arguments to the run()
method, or with the *addUrl()* method before you invoke run().  Each URL
can be specified either as a string, or as a URI::URL object.

   Before invoking this method, you should have provided at least some of
the hook functions.  See the example given in the EXAMPLES section below.

   By default the run() method will iterate until there are no more URLs
in the queue.  You can override this behavior by providing a continue-test
hook function, which checks for the termination conditions.  This
particular hook function, and use of hook functions in general, are
described below.

setAttribute
------------

     $robot->setAttribute( ... attribute-value-pairs ... );

   Change the value of one or more robot attributes.  Attributes are
identified using a string, and take scalar values.  For example, to
specify the name of your robot, you set the NAME attribute:

     $robot->setAttribute( 'NAME' => 'WebStud' );

   The supported attributes for the Robot module are listed below, in the
*ROBOT ATTRIBUTES* section.

getAttribute
------------

     $value = $robot->getAttribute( 'attribute-name' );

   Queries a Robot for the value of an attribute.  For example, to query
the version number of your robot, you would get the VERSION attribute:

     $version = $robot->getAttribute( 'VERSION' );

   The supported attributes for the Robot module are listed below, in the
*ROBOT ATTRIBUTES* section.

getAgent
--------

     $agent = $robot->getAgent();

   Returns the agent that is being used by the robot.

addUrl
------

     $robot->addUrl( $url1, ..., $urlN );

   Used to add one or more URLs to the queue for the robot.  Each URL can
be passed as a simple string, or as a URI::URL object.

   Returns True (non-zero) if all URLs were successfully added, False
(zero) if at least one of the URLs could not be added.

unshiftUrl
----------

     $robot->unshiftUrl( $url1, ..., $urlN );

   Used to add one or more URLs to the queue for the robot.  Each URL can
be passed as a simple string, or as a URI::URL object.

   Returns True (non-zero) if all URLs were successfully added, False
(zero) if at least one of the URLs could not be added.

listUrls
--------

     $robot->listUrls( );

   Returns a list of the URLs currently in the robots list to be traversed.

addHook
-------

     $robot->addHook( $hook_name, \&hook_function );

     sub hook_function { ... }

   Register a *hook* function which should be invoked by the robot at a
specific point in the control flow. There are a number of *hook points* in
the robot, which are identified by a string.  For a list of hook points,
see the SUPPORTED HOOKS section below.

   If you provide more than one function for a particular hook, then the
hook functions will be invoked in the order they were added.  I.e. the
first hook function called will be the first hook function you added.

proxy, no_proxy, env_proxy
--------------------------

   These are convenience functions are setting proxy information on the
User agent being used to make the requests.

     $robot->proxy( protocol, proxy );

   Used to specify a proxy for the given scheme.  The protocol argument
can be a reference to a list of protocols.

     $robot->no_proxy(domain1, ... domainN);

   Specifies that proxies should not be used for the specified domains or
hosts.

     $robot->env_proxy();

   Load proxy settings from protocol*_proxy* environment variables:
`ftp_proxy', http_proxy, `no_proxy', etc.

ROBOT ATTRIBUTES
================

   This section lists the attributes used to configure a Robot object.
Attributes are set using the `setAttribute()' method, and queried using
the `getAttribute()' method.

   Some of the attributes must be set before you start the Robot (with the
run() method).  These are marked as *mandatory* in the list below.

NAME
     The name of the Robot.  This should be a sequence of alphanumeric
     characters, and is used to identify your Robot.  This is used to set
     the `User-Agent' field of HTTP requests, and so will appear in server
     logs.

     *mandatory*

VERSION
     The version number of your Robot.  This should be a floating point
     number, in the format *N.NNN*.

     *mandatory*

EMAIL
     A valid email address which can be used to contact the Robot's owner,
     for example by someone who wishes to complain about the behavior of
     your robot.

     *mandatory*

VERBOSE
     A boolean flag which specifies whether the Robot should display
     verbose status information as it runs.

     Default: 0 (false)

TRAVERSAL
     Specifies what traversal style should be adopted by the Robot.  Valid
     values are depth and *breadth*.

     Default: depth

IGNORE_TEXT
     Specifies whether the HTML structure passed to the invoke-on-contents
     hook function should include the textual content of the page, or just
     the HTML elements.

     Default: 1 (true)

IGNORE_UNKNOWN
     Specifies whether the HTML structure passed to the invoke-on-contents
     hook function should ignore unkonwn HTML elements.

     Default: 1 (true)

CHECK_MIME_TYPES
     This tells the robot that if it can't easily determine the MIME type
     of a link from its URL, to issue a HEAD request to check the MIME
     type directly, before adding the link.

     Default: 1 (true)

USERAGENT
     Allows the caller to specify its own user agent to make the HTTP
     requests.

     Default: LWP::RobotUA object created by the robot

ACCEPT_LANGUAGE
     Optionally allows the caller to specify the list of languages that
     the robot accepts. This is added as an "Accept-Language" header field
     in the HTTP request. Takes an array reference.

DELAY
     Optionally set the delay between requests for the user agent, in
     minutes. The default for this is 1 (see LWP::RobotUA).

SUPPORTED HOOKS
===============

   This section lists the hooks which are supported by the WWW::Robot
module.  The first two arguments passed to a hook function are always the
Robot object followed by the name of the hook being invoked. I.e. the
start of a hook function should look something like:

     sub my_hook_function
     {
         my $robot = shift;
         my $hook  = shift;
         # ... other, hook-specific, arguments

   Wherever a hook function is passed a `$url' argument, this will be a
URI::URL object, with the URL fully specified.  I.e. even if the URL was
seen in a relative link, it will be passed as an absolute URL.

restore-state
-------------

     sub hook { my($robot, $hook_name) = @_; }

   This hook is invoked just before entering the main iterative loop of
the robot.  The intention is that the hook will be used to restore state,
if such an operation is required.

   This can be helpful if the robot is running in an incremental mode,
where state is saved between each run of the robot.

invoke-on-all-url
-----------------

     sub hook { my($robot, $hook_name, $url) = @_; }

   This hook is invoked on all URLs seen by the robot, regardless of
whether the URL is actually traversed.  In addition to the standard
`$robot' and `$hook' arguments, the third argument is `$url', which is the
URL being travered by the robot.

   For a given URL, the hook function will be invoked at most once,
regardless of how many times the URL is seen by the Robot.  If you are
interested in seeing the URL every time, you can use the invoke-on-link
hook.

follow-url-test
---------------

     sub hook { my($robot, $hook_name, $url) = @_; return $boolean; }

   This hook is invoked to determine whether the robot should traverse the
given URL.  If the hook function returns 0 (zero), then the robot will do
nothing further with the URL.  If the hook function returns non-zero, then
the robot will get the contents of the URL, invoke further hooks, and
extract links if the contents are HTML.

invoke-on-followed-url
----------------------

     sub hook { my($robot, $hook_name, $url) = @_; }

   This hook is invoked on URLs which are about to be traversed by the
robot; i.e. URLs which have passed the follow-url-test hook.

invoke-on-get-error
-------------------

     sub hook { my($robot, $hook_name, $url, $response) = @_; }

   This hook is invoked if the Robot ever fails to get the contents of a
URL.  The `$response' argument is an object of type HTTP::Response.

invoke-on-contents
------------------

     sub hook { my($robot, $hook, $url, $response, $structure) = @_; }

   This hook function is invoked for all URLs for which the contents are
successfully retrieved.

   The `$url' argument is a URI::URL object for the URL currently being
processed by the Robot engine.

   The `$response' argument is an HTTP::Response object, the result of the
GET request on the URL.

   The `$structure' argument is an HTML::Element object which is the root
of a tree structure constructed from the contents of the URL.  You can set
the IGNORE_TEXT attribute to specify whether the structure passed includes
the textual content of the page, or just the HTML elements.  You can set
the IGNORE_UNKNOWN attribute to specify whether the structure passed
includes unkown HTML elements.

invoke-on-link
--------------

     sub hook { my($robot, $hook_name, $from_url, $to_url) = @_; }

   This hook function is invoked for all links seen as the robot traverses.
When the robot is parsing a page (*$from_url*) for links, for every link
seen the invoke-on-link hook is invoked with the URL of the source page,
and the destination URL.  The destination URL is in canonical form.

add-url-test
------------

     sub hook { my($robot, $hook_name, $url) = @_; }

   This hook function is invoked for all links seen as the robot traverses.
If the hook function returns non-zero, then the robot will add the URL
given by $url to its list of URLs to be traversed.

continue-test
-------------

     sub hook { my($robot) = @_; }

   This hook is invoked at the end of the robot's main iterative loop.  If
the hook function returns non-zero, then the robot will continue execution
with the next URL.  If the hook function returns zero, then the Robot will
terminate the main loop, and close down after invoking the following two
hooks.

   If no continue-test hook function is provided, then the robot will
always loop.

save-state
----------

     sub hook { my($robot) = @_; }

   This hook is used to save any state information required by the robot
application.

generate-report
---------------

     sub hook { my($robot) = @_; }

   This hook is used to generate a report for the run of the robot, if
such is desired.

modified-since
--------------

   If you provide this hook function, it will be invoked for each URL
before the robot actually requests it.  The function can return a time to
use with the If-Modified-Since HTTP header.  This can be used by a robot
to only process those pages which have changed since the last visit.

   Your hook function should be declared as follows:

     sub modifed_since_hook
     {
         my $robot = shift;        # instance of Robot module
         my $hook  = shift;        # name of hook invoked
         my $url   = shift;        # URI::URL for the url in question

         # ... calculate time ...
         return $time;
     }

   If your function returns anything other than undef, then a
*If-Modified-Since:* field will be added to the request header.

invoke-after-get
----------------

   This hook function is invoked immediately after the robot makes each
GET request.  This means your hook function will see every type of
response, not just successful GETs.  The hook function is passed two
arguments: the `$url' we tried to GET, and the `$response' which resulted.

   If you provided a modified-since hook, then provide an invoke-after-get
function, and look for error code 304 (or RC_NOT_MODIFIED if you are using
HTTP::Status, which you should be :-):

     sub after_get_hook
     {
         my($robot, $hook, $url, $response) = @_;

         if ($response->code == RC_NOT_MODIFIED)
         {
         }
     }

EXAMPLES
========

   This section illustrates use of the Robot module, with code snippets
from several sample Robot applications.  The code here is not intended to
show the right way to code a web robot, but just illustrates the API for
using the Robot.

Validating Robot
----------------

   This is a simple robot which you could use to validate your web site.
The robot uses *weblint* to check the contents of URLs of type *text/html*

     #!/usr/bin/perl
     require 5.002;
     use WWW::Robot;

     $rootDocument = $ARGV[0];

     $robot = new WWW::Robot('NAME'     =>  'Validator',
     			   'VERSION'  =>  1.000,
     			   'EMAIL'    =>  'fred@foobar.com');

     $robot->addHook('follow-url-test', \&follow_test);
     $robot->addHook('invoke-on-contents', \&validate_contents);

     $robot->run($rootDocument);

     #-------------------------------------------------------
     sub follow_test {
        my($robot, $hook, $url) = @_;

        return 0 unless $url->scheme eq 'http';
        return 0 if $url =~ /\.(gif|jpg|png|xbm|au|wav|mpg)$/;

        #---- we're only interested in pages on our site ----
        return $url =~ /^$rootDocument/;
     }

     #-------------------------------------------------------
     sub validate_contents {
        my($robot, $hook, $url, $response, $structure) = @_;

        return unless $response->content_type eq 'text/html';

     # some validation on $structure ...

        }

   If you are behind a firewall, then you will have to add something like
the following, just before calling the run() method:

     $robot->proxy(['ftp', 'http', 'wais', 'gopher'],
     		 'http://firewall:8080/');

MODULE DEPENDENCIES
===================

   The Robot.pm module builds on a lot of existing Net, WWW and other Perl
modules.  Some of the modules are part of the core Perl distribution, and
the latest versions of all modules are available from the Comprehensive
Perl Archive Network (CPAN).  The modules used are:

HTTP::Request
     This module is used to construct HTTP requests, when retrieving the
     contents of a URL, or using the HEAD request to see if a URL exists.

HTML::LinkExtor
     This is used to extract the URLs from the links on a page.

HTML::TreeBuilder
     This module builds a tree data structure from the contents of an HTML
     page.  This is also used to check for page-specific Robot exclusion
     commands, using the META element.

URI::URL
     This module implements a class for URL objects, providing resolution
     of relative URLs, and access to the different components of a URL.

LWP::RobotUA
     This is a wrapper around the LWP::UserAgent class.  A UserAgent is
     used to connect to servers over the network, and make requests.  The
     RobotUA module provides transparent compliance with the *Robot
     Exclusion Protocol*.

HTTP::Status
     This has definitions for HTTP response codes, so you can say
     RC_NOT_MODIFIED instead of 304.

   All of these modules are available as part of the libwww-perl5
distribution, which is also available from CPAN.

SEE ALSO
========

The SAS Group Home Page
     http://www.cre.canon.co.uk/sas.html

     This is the home page of the Group at Canon Research Centre Europe
     who are responsible for Robot.pm.

Robot Exclusion Protocol
     http://info.webcrawler.com/mak/projects/robots/norobots.html

     This is a *de facto* standard which defines how a `well behaved'
     Robot client should interact with web servers and web pages.

Guidelines for Robot Writers
     http://info.webcrawler.com/mak/projects/robots/guidelines.html

     Guidelines and suggestions for those who are (considering) developing
     a web robot.

Weblint Home Page
     http://www.cre.canon.co.uk/~neilb/weblint/

     Weblint is a perl script which is used to check HTML for syntax
     errors and stylistic problems, in the same way *lint* is used to
     check C.

Comprehensive Perl Archive Network (CPAN)
     http://www.perl.com/perl/CPAN/

     This is a well-organized collection of Perl resources, such as
     modules, documents, and scripts.  CPAN is mirrored at FTP sites
     around the world.

VERSION
=======

   This documentation describes version 0.021 of the Robot module.  The
module requires at least version 5.002 of Perl.

AUTHOR
======

     Neil Bowers <neilb@cre.canon.co.uk>
     Ave Wrigley <wrigley@cre.canon.co.uk>

     Web Department, Canon Research Centre Europe

COPYRIGHT
=========

   Copyright (C) 1997, Canon Research Centre Europe.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Parse robots.txt files
**********************

NAME
====

   WWW::RobotsRules - Parse robots.txt files

SYNOPSIS
========

     require WWW::RobotRules;
     my $robotsrules = new WWW::RobotRules 'MOMspider/1.0';

     use LWP::Simple qw(get);

     $url = "http://some.place/robots.txt";
     my $robots_txt = get $url;
     $robotsrules->parse($url, $robots_txt);

     $url = "http://some.other.place/robots.txt";
     my $robots_txt = get $url;
     $robotsrules->parse($url, $robots_txt);

     # Now we are able to check if a URL is valid for those servers that
     # we have obtained and parsed "robots.txt" files for.
     if($robotsrules->allowed($url)) {
         $c = get $url;
         ...
     }

DESCRIPTION
===========

   This module parses a `/robots.txt' file as specified in "A Standard for
Robot Exclusion", described in
<http://info.webcrawler.com/mak/projects/robots/norobots.html> Webmasters
can use the `/robots.txt' file to disallow conforming robots access to
parts of their web site.

   The parsed file is kept in the WWW::RobotRules object, and this object
provides methods to check if access to a given URL is prohibited.  The
same WWW::RobotRules object can parse multiple `/robots.txt' files.

   The following methods are provided:

$rules = WWW::RobotRules->new($robot_name)
     This is the constructor for WWW::RobotRules objects.  The first
     argument given to new() is the name of the robot.

$rules->parse($robot_txt_url, $content, $fresh_until)
     The parse() method takes as arguments the URL that was used to
     retrieve the `/robots.txt' file, and the contents of the file.

$rules->allowed($uri)
     Returns TRUE if this robot is allowed to retrieve this URL.

$rules->agent([$name])
     Get/set the agent name. NOTE: Changing the agent name will clear the
     robots.txt rules and expire times out of the cache.

ROBOTS.TXT
==========

   The format and semantics of the "/robots.txt" file are as follows (this
is an edited abstract of
<http://info.webcrawler.com/mak/projects/robots/norobots.html>):

   The file consists of one or more records separated by one or more blank
lines. Each record contains lines of the form

     <field-name>: <value>

   The field name is case insensitive.  Text after the '#' character on a
line is ignored during parsing.  This is used for comments.  The following
<field-names> can be used:

User-Agent
     The value of this field is the name of the robot the record is
     describing access policy for.  If more than one *User-Agent* field is
     present the record describes an identical access policy for more than
     one robot. At least one field needs to be present per record.  If the
     value is '*', the record describes the default access policy for any
     robot that has not not matched any of the other records.

Disallow
     The value of this field specifies a partial URL that is not to be
     visited. This can be a full path, or a partial path; any URL that
     starts with this value will not be retrieved

ROBOTS.TXT EXAMPLES
===================

   The following example "/robots.txt" file specifies that no robots
should visit any URL starting with "/cyberworld/map/" or "/tmp/":

     User-agent: *
     Disallow: /cyberworld/map/ # This is an infinite virtual URL space
     Disallow: /tmp/ # these will soon disappear

   This example "/robots.txt" file specifies that no robots should visit
any URL starting with "/cyberworld/map/", except the robot called
"cybermapper":

     User-agent: *
     Disallow: /cyberworld/map/ # This is an infinite virtual URL space

     # Cybermapper knows where to go.
     User-agent: cybermapper
     Disallow:

   This example indicates that no robots should visit this site further:

     # go away
     User-agent: *
     Disallow: /

SEE ALSO
========

   See LWP/RobotUA, WWW/RobotRules/AnyDBM_File,

Persistent RobotRules
*********************

NAME
====

   WWW::RobotRules::AnyDBM_File - Persistent RobotRules

SYNOPSIS
========

     require WWW::RobotRules::AnyDBM_File;
     require LWP::RobotUA;

     # Create a robot useragent that uses a diskcaching RobotRules
     my $rules = new WWW::RobotRules::AnyDBM_File 'my-robot/1.0', 'cachefile';
     my $ua = new WWW::RobotUA 'my-robot/1.0', 'me@foo.com', $rules;

     # Then just use $ua as usual
     $res = $ua->request($req);

DESCRIPTION
===========

   This is a subclass of *WWW::RobotRules* that uses the AnyDBM_File
package to implement persistent diskcaching of `robots.txt' and host visit
information.

   The constructor (the new() method) takes an extra argument specifying
the name of the DBM file to use.  If the DBM file already exists, then you
can specify undef as agent name as the name can be obtained from the DBM
database.

SEE ALSO
========

   See WWW/RobotRules, LWP/RobotUA,

AUTHORS
=======

   Hakan Ardo <hakan@munin.ub2.lu.se>, Gisle Aas <aas@sn.no>

Virtual base class for WWW searches
***********************************

NAME
====

   WWW::Search - Virtual base class for WWW searches

SYNOPSIS
========

     require WWW::Search;
     $search_engine = "AltaVista";
     $search = new WWW::Search($search_engine);

DESCRIPTION
===========

   This class is the parent for all access methods supported by the
`WWW::Search' library.  This library implements a Perl API to web-based
search engines.

   See README for a list of search engines currently supported.

   Search results can be limited, and there is a pause between each
request to avoid overloading either the client or the server.

Sample program
--------------

   Using the library should be straightforward.  Here is a sample program:

     my $search = new WWW::Search('AltaVista');
     $search->native_query(WWW::Search::escape_query($query));
     while (my $result = $search->next_result())
       {
       print $result->url, "\n";
       }

   Results are objects of type `WWW::SearchResult' (see
WWW/SearchResult, for details).  Note that different
backends support different result fields.  All backends are required to
support title and url.

SEE ALSO
========

   For specific search engines, see `WWW::Search::TheEngineName' in this
node (replacing TheEngineName with a particular search engine).

   For details about the results of a search, see WWW/SearchResult.

METHODS AND FUNCTIONS
=====================

new
---

   To create a new WWW::Search, call

     $search = new WWW::Search('SearchEngineName');

   where SearchEngineName is replaced with a particular search engine.
For example:

     $search = new WWW::Search('Google');

   If no search engine is specified a default (currently 'AltaVista') will
be chosen for you.  The next step is usually:

     $search->native_query('search-engine-specific+query+string');

reset_search (PRIVATE)
----------------------

   Resets internal data structures to start over with a new search.

version
-------

   Returns the value of the $VERSION variable of the backend engine, or
$WWW::Search::VERSION if the backend does not contain $VERSION.

maintainer
----------

   Returns the value of the $MAINTAINER variable of the backend engine, or
$WWW::Search::MAINTAINER if the backend does not contain $MAINTAINER.

gui_query
---------

   Specify a query to the current search object; the query will be
performed with the engine's default options, as if it were typed by a user
in a browser window.

   The query must be escaped; call `&WWW::Search::escape_query' in this
node to escape a plain query.  See native_query below for more information.

   Currently, this feature is supported by only a few backends; consult
the documentation for each backend to see if it is implemented.

native_query
------------

   Specify a query (and optional options) to the current search object.
Previous query (if any) and its cached results (if any) will be thrown
away.  The option values and the query must be escaped; call
`WWW::Search::escape_query()' in this node to escape a string.  The search
process is not actually begun until results or next_result is called
(lazy!), so native_query does not return anything.

   Example:

     $search->native_query('search-engine-specific+escaped+query+string',
                           { option1 => 'able', option2 => 'baker' } );

   The hash of options following the query string is optional.  The query
string is backend-specific.  There are two kinds of options: options
specific to the backend, and generic options applicable to multiple
backends.

   Generic options all begin with 'search_'.  Currently a few are
supported:

search_url
     Specifies the base URL for the search engine.

search_debug
     Enables backend debugging.  The default is 0 (no debugging).

search_parse_debug
     Enables backend parser debugging.  The default is 0 (no debugging).

search_method
     Specifies the HTTP method (GET or POST) for HTTP-based queries.  The
     default is GET

search_to_file FILE
     Causes the search results to be saved in a set of files prefixed by
     FILE.  (Used internally by the test-suite, not intended for general
     use.)

search_from_file FILE
     Reads a search from a set of files prefixed by FILE.  (Used
     internally by the test-suite, not intended for general use.)

   Some backends may not implement these generic options, but any which do
implement them must provide these semantics.

   Backend-specific options are described in the documentation for each
backend.  In most cases the options and their values are packed together
to create the query portion of the final URL.

   Details about how the search string and option hash are interpreted
might be found in the search-engine-specific manual pages
(WWW::Search::SearchEngineName).

   After native_query, the next step is usually:

     while ($result = $search->next_result())
       {
       # do_something;
       }

cookie_jar
----------

   Call this method (anytime before asking for results) if you want to
communicate cookie data with the search engine.  Takes one argument,
either a filename or an HTTP::Cookies object.  If you give a filename,
WWW::Search will attempt to read/store cookies there (by in turn passing
the filename to HTTP::Cookies::new).

     $oSearch->cookie_jar('/tmp/my_cookies');

   If you give an HTTP::Cookies object, it is up to you to save the
cookies if you wish.

     use HTTP::Cookies;
     my $oJar = HTTP::Cookies->new(...);
     $oSearch->cookie_jar($oJar);

approximate_result_count
------------------------

   Some backends indicate how many hits they have found.  Typically this
is an approximate value.

results
-------

   Return all the results of a query as a reference to array of
SearchResult objects.  Example:

     @results = $search->results();
     foreach $result (@results) {
         print $result->url(), "\n";
     };

   On error, results() will return undef and set response() to the HTTP
response code.

next_result
-----------

   Call this method repeatedly to return each result of a query as a
SearchResult object.  Example:

     while ($result = $search->next_result())
       {
       print $result->url(), "\n";
       }

   On error, next_result() will return undef and set response() to the
HTTP response code.

response
--------

   Return the HTTP Response code for the last query (see
HTTP/Response).  If the query returns undef, errors could
be reported like this:

     my $response = $search->response();
     if ($response->is_success) {
     	print "normal end of result list\n";
     } else {
     	print "error:  " . $response->as_string() . "\n";
     }

   Note: even if the backend does not involve the web, it should return
HTTP::Response-style codes.

seek_result($offset)
--------------------

   Set which result next_result should return (like lseek in Unix).
Results are zero-indexed.

   The only guaranteed valid offset is 0, which will replay the results
from the beginning.  In particular, seeking past the end of the current
cached results probably will not do what you might think it should.

   Results are cached, so this does not re-issue the query or cause IO
(unless you go off the end of the results).  To re-do the query, create a
new search object.

   Example:

     $search->seek_result(0);

maximum_to_retrieve
-------------------

   The maximum number of hits to return.  Queries resulting in more than
this many hits will return the first hits, up to this limit.  Although
this specifies a maximum limit, search engines might return less than this
number.

   Defaults to 500.

   Example:     $max = $search->maximum_to_retrieve(100);

timeout
-------

   The maximum length of time any portion of the query should take, in
seconds.

   Defaults to 60.

   Example:     $search->timeout(120);

opaque
------

   This function provides an application a place to store one opaque data
element (or many via a Perl reference).  This facility is useful to (for
example), maintain client-specific information in each active query when
you have multiple concurrent queries.

escape_query
------------

   Escape a query.  Before queries are made special characters must be
escaped so that a proper URL can be formed.  This is like escaping a URL,
but all non-alphanumeric characters are escaped and and spaces are
converted to "+"s.

   Example:     $escaped = WWW::Search::escape_query('+hi +mom');

     (Returns "%2Bhi+%2Bmom").

   See also unescape_query.  NOTE that this is not a method, it is a plain
function.

unescape_query
--------------

   Unescape a query.  See escape_query for details.

   Example:     $unescaped = WWW::Search::unescape_query('%22hi+mom%22');

     (Returns '"hi mom"').

   NOTE that this is not a method, it is a plain function.

strip_tags
----------

   Given a string, returns a copy of that string with HTML tags removed.
This should be used by each backend as they insert the title and
description values into the SearchResults.

hash_to_cgi_string (PRIVATE) (DEPRECATED)
-----------------------------------------

   Deprecated.

   Given a reference to a hash of string => string, constructs a CGI
parameter string that looks like 'key1=value1&key2=value2'.

   At one time, for testing purposes, we asked backends to use this
function rather than piecing the URL together by hand, to ensure that URLs
are identical across platforms and software versions.  But this is no
longer necessary.

   Example:

     $self->{_options} = {
                          'opt3' => 'val3',
                          'search_url' => 'http://www.deja.com/dnquery.xp',
                          'opt1' => 'val1',
                          'QRY' => $native_query,
                          'opt2' => 'val2',
                         };
     $self->{_next_url} = $self->{_options}{'search_url'} .'?'.
                          $self->hash_to_cgi_string($self->{_options});

http_proxy
----------

   Set-up an HTTP proxy (for connections from behind a firewall).

   This routine should be called before the first retrieval is attempted.

   Example:

     $search->http_proxy("http://gateway:8080");

user_agent($NON_ROBOT) (PRIVATE)
--------------------------------

   This internal routine creates a user-agent for derived classes that
query the web.  If non-empty argument $non_robot is given, a normal
user-agent (rather than a robot-style user-agent) is used.

   If a backend needs the low-level LWP::UserAgent or LWP::RobotUA to have
a particular name, $oSearch->{'agent_name'} (and possibly
$oSearch->{'agent_e_mail'}) should be set to the desired values before
calling $oSearch->user_agent():

     $oSearch = new WWW::Search('NewBackend');
     $oSearch->{'agent_e_mail'} = $oSearch->{'agent_name'};
     $oSearch->{'agent_name'} = 'Mozilla/5.5';
     $oSearch->user_agent('non-robot');

   Backends should use robot-style user-agents whenever possible.  Also,
backends should call `user_agent_delay' between every page retrieval to
avoid swamping search-engines.

http_request($method, $url)
---------------------------

   Return the response from an http request, handling debugging.  Requires
that user_agent already be set up.  For POST methods, query is split off
of the URL and passed in the request body.

split_lines (PRIVATE)
---------------------

   This internal routine splits data (typically the result of the web page
retrieval) into lines in a way that is OS independent.  If the first
argument is a reference to an array, that array is taken to be a list of
possible delimiters for this split.  For example, Yahoo.pm uses <p> and
<dd><li> as "line" delimiters for convenience.

generic_option (PRIVATE)
------------------------

   This internal routine checks if an option is generic or backend
specific.  Currently all generic options begin with 'search_'.  This
routine is not a method.

setup_search (PRIVATE)
----------------------

   This internal routine does generic Search setup.  It calls
`native_setup_search' to do backend specific setup.

user_agent_delay (PRIVATE)
--------------------------

   Derived classes should call this between requests to remote servers to
avoid overloading them with many, fast back-to-back requests.

absurl (PRIVATE)
----------------

   An internal routine to convert a relative URL into a absolute URL.  It
takes two arguments, the 'base' url (usually the search engine CGI URL)
and the URL to be converted.  Returns a URI::URL object.

retrieve_some (PRIVATE)
-----------------------

   An internal routine to interface with `native_retrieve_some'.  Checks
for overflow.

test_cases
----------

   Returns the value of the $TEST_CASES variable of the backend engine.
All backends should set $TEST_CASES to a string containing perl code which
will be eval-ed during 'make test'.  See Excite.pm for an example.

IMPLEMENTING NEW BACKENDS
=========================

   `WWW::Search' supports backends to separate search engines.  Each
backend is implemented as a subclass of `WWW::Search'.  See
WWW/Search/AltaVista, provides a good sample backend.

   A backend must have the two routines `native_retrieve_some' and
`native_setup_search'.

   `native_retrieve_some' is the core of a backend.  It will be called
periodically to fetch URLs.  It should retrieve several hits from the
search service and add them to the cache.  It should return the number of
hits found, or undef when there are no more hits.

   Internally, `native_retrieve_some' typically sends an HTTP request to
the search service, parse the HTML, extract the links and descriptions,
then save the URL for the next page of results.  See the code for the
AltaVista implementation for an example.

   `native_setup_search' is invoked before the search.  It is passed a
single argument:  the escaped, native version of the query.

   The front- and backends share a single object (a hash).  The backend
can change any hash element beginning with underscore, and `{response}'
(an `HTTP::Response' code) and `{cache}' (the array of `WWW::SearchResult'
objects caching all results).  Again, look at one of the existing web
search backends as an example.

   If you implement a new backend, please let the authors know.

BUGS AND DESIRED FEATURES
=========================

   The bugs are there for you to find (some people call them Easter Eggs).

   Desired features:

A portable query language.
     A portable language would easily allow you to move queries easily
     between different search engines.  A query abstraction is non-trivial
     and unfortunately will not be done anytime soon by the current
     maintainers.  If you want to take a shot at it, please let me know.

AUTHOR
======

   `WWW::Search' was written by John Heidemann, <johnh@isi.edu>.
`WWW::Search' is currently maintained by Martin Thurn,
<MartinThurn@iname.com>.

   backends and applications for WWW::Search were originally written by
John Heidemann, Wm. L. Scheding, Cesare Feroldi de Rosa, and GLen Pringle.

COPYRIGHT
=========

   Copyright (c) 1996 University of Southern California.  All rights
reserved.

   Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are duplicated
in all such forms and that any documentation, advertising materials, and
other materials related to such distribution and use acknowledge that the
software was developed by the University of Southern California,
Information Sciences Institute.  The name of the University may not be
used to endorse or promote products derived from this software without
specific prior written permission.

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

class for searching Jobs Classifieds on AOL
*******************************************

NAME
====

   WWW::Search::AOL::Classifieds::Employment - class for searching Jobs
Classifieds on AOL

SYNOPSIS
========

     use WWW::Search;
     my $oSearch = new WWW::Search('Aol');
     my $sQuery = WWW::Search::escape_query("unix c++ java");
     $oSearch->native_query($sQuery,
     			{'qcqs' => ':ca:'});
     while (my $res = $oSearch->next_result()) {
         print $res->company . "\t" . $res->title . "\t" . $res->change_date
     	 . "\t" . $res->location . "\n";
     }

DESCRIPTION
===========

   This class is a Aol specialization of WWW::Search.  It handles making
and interpreting Aol searches at `http://classifiedplus.aol.com' in
category employment->JobSearch.

   The returned WWW::SearchResult objects contain url, title, *company*,
location and change_date fields.

OPTIONS
=======

   The following search options can be activated by sending a hash as the
second argument to native_query().

Format / Treatment of Query Terms
---------------------------------

   The default is to match ALL keywords in your query.

{'QY' => 2} - to match at least one word
{'QY' => 5} - to match exact phrase
Restrict by Job Category
------------------------

   No restriction by default. To select jobs from a specific job category
use the following option:

{'QVSSCAT' => $job_category}
   Possible values of $job_category are the following:

   * 10   	Accounting/Finance/Banking/Insurance

   * 20   	Administrative/Clerical

   * 30   	Creative Arts/Media

   * 40   	Education/Training

   * 50   	Engineering/Architecture/Design

   * 60   	Human resources

   * 70   	Information Technology/Computer

   * 80   	Legal/Law Enforcement/Security

   * 90   	Marketing/Public relations/Advertising

   * 100   	Medical/Heath Care/Dental

   * 110   	Online/Internet/New Media

   * 120   	Sales/Customer Service/Sales Management

   * 130   	Sports

   * 140   	Travel/Hospitality/Restaurant/Transportation

   * 150   	Other

Restrict by Company Name
------------------------

{'QM' => $pattern}
     Display jobs where company name matches $pattern.

Restrict by Location
--------------------

   No preference by default. Several options can restrict your search.
Only one of the below listed options can be enabled at a time.

{'QREG' => $region} - to select a region
     Regions can be:

   * 1     Mid-Atl

   * 2     Midwest

   * 3     Northeast

   * 4     Northwest

   * 5     Southeast

   * 6     Southwest

   * 7     West

   * 8     Outside USA

   * 9999  National
{'qcqs' => $state_or_city} - more detailed selection
     There are too many possible values to be listed here. See
     `http://classifiedplus.aol.com' in category employment->JobSearch for
     a full list. Here are some examples from that list: to select jobs
     only from California use {'qcqs' => ':ca:'}, for jobs from San
     Fransisco use {'qcqs' => 'san francisco:ca:807'}.

{'QZ' => $zip_code} - restrict by zip code.
AUTHOR
======

   `WWW::Search::Aol' is written and maintained by Alexander Tkatchev
(Alexander.Tkatchev@cern.ch).

LEGALESE
========

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

class for searching AlltheWeb
*****************************

NAME
====

   WWW::Search::AlltheWeb - class for searching AlltheWeb

SYNOPSIS
========

   use WWW::Search; $query = "sprinkler system installation how to";
$search = new WWW::Search('AlltheWeb');
$search->native_query(WWW::Search::escape_query($query));
$search->maximum_to_retrieve(100); while (my $result =
$search->next_result()) {

   $url = $result->url; $title = $result->title; $desc =
$result->description;

   print "<a href=$url>$title</a> $source<br>$date<br>$desc<p>\n"; }

DESCRIPTION
===========

   AlltheWeb is a class specialization of WWW::Search.  It handles making
and interpreting AlltheWeb searches.  This is one of the fastest and
largest search engines around.  `http://www.alltheweb.com'.

   This class exports no public interface; all interaction should be done
through WWW/Search, objects. See SYNOPSIS.

AUTHOR
======

   `WWW::Search::AlltheWeb' is written by Jim Smyser Author e-mail
<jsmyser@bigfoot.com>

COPYRIGHT
=========

   Copyright (c) 1996-1999 University of Southern California.  All rights
reserved.

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

class for searching Alta Vista
******************************

NAME
====

   WWW::Search::AltaVista - class for searching Alta Vista

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('AltaVista');

DESCRIPTION
===========

   This class is an AltaVista specialization of WWW::Search.  It handles
making and interpreting AltaVista searches `http://www.altavista.com'.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

OPTIONS
=======

   The default is for simple web queries.  Specialized back-ends for
simple and advanced web and news searches are available (see
WWW/Search/AltaVista/Web,
WWW/Search/AltaVista/AdvancedWeb,
WWW/Search/AltaVista/News,
WWW/Search/AltaVista/AdvancedNews).
These back-ends set different combinations following options.

search_url=URL
     Specifies who to query with the AltaVista protocol.  The default is at
     `http://www.altavista.com/cgi-bin/query'; you may wish to retarget it
     to `http://www.altavista.telia.com/cgi-bin/query' or other hosts if
     you think that they're "closer".

search_debug, search_parse_debug, search_ref Specified at WWW/Search.
pg=aq
     Do advanced queries.  (It defaults to simple queries.)

what=news
     Search Usenet instead of the web.  (It defaults to search the web.)

SEE ALSO
========

   To make new back-ends, see WWW/Search, or the
specialized AltaVista searches described in options.

HOW DOES IT WORK?
=================

   `native_setup_search' is called before we do anything.  It initializes
our private variables (which all begin with underscores) and sets up a URL
to the first results page in `{_next_url}'.

   `native_retrieve_some' is called (from `WWW::Search::retrieve_some')
whenever more hits are needed.  It calls the LWP library to fetch the page
specified by `{_next_url}'.  It parses this page, appending any search
hits it finds to `{cache}'.  If it finds a "next" button in the text, it
sets `{_next_url}' to point to the page for the next set of results,
otherwise it sets it to undef to indicate we're done.

AUTHOR and CURRENT VERSION
==========================

   `WWW::Search::AltaVista' is written and maintained by John Heidemann,
<johnh@isi.edu>.

   The best place to obtain `WWW::Search::AltaVista' is from Martin
Thurn's WWW::Search releases on CPAN.  Because AltaVista sometimes changes
its format in between his releases, sometimes more up-to-date versions can
be found at
`http://www.isi.edu/~johnh/SOFTWARE/WWW_SEARCH_ALTAVISTA/index.html'.

COPYRIGHT
=========

   Copyright (c) 1996-1998 University of Southern California.  All rights
reserved.

   Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are duplicated
in all such forms and that any documentation, advertising materials, and
other materials related to such distribution and use acknowledge that the
software was developed by the University of Southern California,
Information Sciences Institute.  The name of the University may not be
used to endorse or promote products derived from this software without
specific prior written permission.

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

class for advanced Alta Vista news searching
********************************************

NAME
====

   WWW::Search::AltaVista::AdvancedNews - class for advanced Alta Vista
news searching

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('AltaVista::AdvancedNews');

DESCRIPTION
===========

   This class implements the advanced AltaVista news search (specializing
AltaVista and WWW::Search).  It handles making and interpreting AltaVista
web searches `http://www.altavista.com'.

   Details of AltaVista can be found at WWW/Search/AltaVista.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

AUTHOR
======

   `WWW::Search' is written by John Heidemann, <johnh@isi.edu>.

COPYRIGHT
=========

   Copyright (c) 1996 University of Southern California.  All rights
reserved.

   Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are duplicated
in all such forms and that any documentation, advertising materials, and
other materials related to such distribution and use acknowledge that the
software was developed by the University of Southern California,
Information Sciences Institute.  The name of the University may not be
used to endorse or promote products derived from this software without
specific prior written permission.

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

class for advanced Alta Vista web searching
*******************************************

NAME
====

   WWW::Search::AltaVista::AdvancedWeb - class for advanced Alta Vista web
searching

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('AltaVista::AdvancedWeb');

DESCRIPTION
===========

   Class hack for Advance AltaVista web search mode originally written by
John Heidemann `http://www.altavista.com'.

   This hack now allows for AltaVista AdvanceWeb search results to be
sorted and relevant results returned first. Initially, this class had
skiped the 'r' option which is used by AltaVista to sort search results
for relevancy. Sending advance query using the 'q' option resulted in
random returned search results which made it impossible to view best
scored results first.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

USAGE
=====

   Advanced AltaVista searching requires boolean operators: AND, OR, AND
NOT, NEAR in all uppercase. Phrases require to be enclosed in braces ( )'s
instead of double quotes. Some examples:

   (John Heidemann) AND (lsam OR replication) AND NOT (somestupiedword OR
thisone)

   (lsam OR replication) AND (John Heidemann) AND NOT (somestupiedword OR
thisone)

   Batman and Robin and not Joker

   Batman and Robin and not (joker or riddler)

   Comments: For ideal results start your query with the words that matter
most in being returned. This module will take those and apply them first
for sorting purposes.

   CASE doesnt matter anymore for the Boolean operators for 'and' will be
uppercased to 'AND'. This is to make constructing complex queries easier.

AUTHOR
======

   `WWW::Search' hack by Jim Smyser, <jsmyser@bigfoot.com>.

COPYRIGHT
=========

   Copyright (c) 1996 University of Southern California.  All rights
reserved.

   Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are duplicated
in all such forms and that any documentation, advertising materials, and
other materials related to such distribution and use acknowledge that the
software was developed by the University of Southern California,
Information Sciences Institute.  The name of the University may not be
used to endorse or promote products derived from this software without
specific prior written permission.

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

VERSION HISTORY
===============

   2.01 - Additional query modifiers added for even better results.

   2.0 - Minor change to set lowercase Boolean operators to uppercase.

   1.9 - First hack version release.

class for searching www.altavistacareers.com
********************************************

NAME
====

   WWW::Search::AltaVista::Careers - class for searching
www.altavistacareers.com

SYNOPSIS
========

     use WWW::Search;
     my $oSearch = new WWW::Search('AltaVista::Careers');
     my $sQuery = WWW::Search::escape_query("java c++)");
     $oSearch->native_query($sQuery,
     			{'state' => 'CA'});
     while (my $res = $oSearch->next_result()) {
         print $res->title . "\t" . $res->change_date
     	 . "\t" . $res->location . "\t" . $res->url . "\n";
     }

DESCRIPTION
===========

   This class is a AltaVistaCareers specialization of WWW::Search.  It
handles making and interpreting AltaVistaCareers searches
`http://careers.altavista.com'.

   The returned WWW::SearchResult objects contain url, title, location and
change_date fields.

OPTIONS
=======

   The following search options can be activated by sending a hash as the
second argument to native_query().

   The only available options are to select a specific location.  The
default is to search all locations. To change it use

{'state' => $state} - Only jobs in state $state.
{'city' => $city} - Only job in a specific $city
AUTHOR
======

   `WWW::Search::AltaVistaCareers' is written and maintained by Alexander
Tkatchev (Alexander.Tkatchev@cern.ch).

LEGALESE
========

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

class for searching via AltaVista Search Intranet 2.3
*****************************************************

NAME
====

   WWW::Search::AltaVista::Intranet - class for searching via AltaVista
Search Intranet 2.3

SYNOPSIS
========

     use WWW::Search;
     my $oSearch = new WWW::Search('AltaVista::Intranet',
                                   (_host => 'copper', _port => 9000),);
     my $sQuery = WWW::Search::escape_query("+investment +club");
     $oSearch->native_query($sQuery);
     while (my $oResult = $oSearch->next_result())
       { print $oResult->url, "\n"; }

DESCRIPTION
===========

   This class implements a search on AltaVista's Intranet ("AVI") Search.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

NOTES
=====

   If your query includes characters outside the 7-bit ascii, you must
tell AVI how to interpret 8-bit characters.  Add an option for 'enc' to
the native_query() call:

     $oSearch->native_query(WWW::Search::escape_query('Zürich'),
                            { 'enc' => 'iso88591'},
                           );

   Hopefully the correct values for various languages can be found in the
AVI documentation (sorry, I haven't looked).

TESTING
=======

   There is no standard built-in test mechanism for this module, because
very few users of WWW::Search will have AVI installed on their intranet.
(How's that for an excuse? ;-)

AUTHOR
======

   `WWW::Search::AltaVista::Intranet' was written by Martin Thurn
<MartinThurn@iname.com>

COPYRIGHT
=========

   Copyright (c) 1996 University of Southern California.  All rights
reserved.

   Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are duplicated
in all such forms and that any documentation, advertising materials, and
other materials related to such distribution and use acknowledge that the
software was developed by the University of Southern California,
Information Sciences Institute.  The name of the University may not be
used to endorse or promote products derived from this software without
specific prior written permission.

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

VERSION HISTORY
===============

   If it"s not listed here, then it wasn"t a meaningful nor released
revision.

2.04, 2000-03-09
----------------

   Added pod for selecting query language encoding

2.03, 2000-02-14
----------------

   Added support for score/rank (thanks to Peter bon Burg
<pvonburg@aspes.ch>)

2.02, 1999-11-29
----------------

   Fixed to work with latest version of AltaVista.pm

1.03, 1999-06-20
----------------

   First publicly-released version.

class for Alta Vista news searching
***********************************

NAME
====

   WWW::Search::AltaVista::News - class for Alta Vista news searching

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('AltaVista::News');

DESCRIPTION
===========

   This class implements the AltaVista news search (specializing AltaVista
and WWW::Search).  It handles making and interpreting AltaVista news
searches `http://www.altavista.com'.

   Details of AltaVista can be found at WWW/Search/AltaVista.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

AUTHOR
======

   `WWW::Search' is written by John Heidemann, <johnh@isi.edu>.

COPYRIGHT
=========

   Copyright (c) 1996 University of Southern California.  All rights
reserved.

   Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are duplicated
in all such forms and that any documentation, advertising materials, and
other materials related to such distribution and use acknowledge that the
software was developed by the University of Southern California,
Information Sciences Institute.  The name of the University may not be
used to endorse or promote products derived from this software without
specific prior written permission.

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

class for Alta Vista web searching
**********************************

NAME
====

   WWW::Search::AltaVista::Web - class for Alta Vista web searching

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('AltaVista::Web');

DESCRIPTION
===========

   This class implements the AltaVista web search (specializing AltaVista
and WWW::Search).  It handles making and interpreting AltaVista web
searches `http://www.altavista.com'.

   Details of AltaVista can be found at WWW/Search/AltaVista.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

AUTHOR
======

   `WWW::Search' is written by John Heidemann, <johnh@isi.edu>.

COPYRIGHT
=========

   Copyright (c) 1996 University of Southern California.  All rights
reserved.

   Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are duplicated
in all such forms and that any documentation, advertising materials, and
other materials related to such distribution and use acknowledge that the
software was developed by the University of Southern California,
Information Sciences Institute.  The name of the University may not be
used to endorse or promote products derived from this software without
specific prior written permission.

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

class for searching Crawler
***************************

NAME
====

   WWW::Search::Crawler - class for searching Crawler

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('Crawler');

DESCRIPTION
===========

   This class is an Crawler specialization of WWW::Search.  It handles
making and interpreting Fireball searches `http://www.crawler.de'.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

SEE ALSO
========

   To make new back-ends, see WWW/Search.

HOW DOES IT WORK?
=================

   `native_setup_search' is called before we do anything.  It initializes
our private variables (which all begin with underscores) and sets up a URL
to the first results page in `{_next_url}'.

   `native_retrieve_some' is called (from `WWW::Search::retrieve_some')
whenever more hits are needed.  It calls the LWP library to fetch the page
specified by `{_next_url}'.  It parses this page, appending any search
hits it finds to `{cache}'.  If it finds a "next" button in the text, it
sets `{_next_url}' to point to the page for the next set of results,
otherwise it sets it to undef to indicate we're done.

AUTHOR
======

   `WWW::Search::Crawler' has been shamelessly copied by Andreas Borchert,
<borchert@mathematik.uni-ulm.de> from `WWW::Search::AltaVista' by John
Heidemann, <johnh@isi.edu>.

COPYRIGHT
=========

   The original parts from John Heidemann are subject to following
copyright notice:

   Copyright (c) 1996-1998 University of Southern California.  All rights
reserved.

   Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are duplicated
in all such forms and that any documentation, advertising materials, and
other materials related to such distribution and use acknowledge that the
software was developed by the University of Southern California,
Information Sciences Institute.  The name of the University may not be
used to endorse or promote products derived from this software without
specific prior written permission.

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

class for searching Dice
************************

NAME
====

   WWW::Search::Dice - class for searching Dice

SYNOPSIS
========

     use WWW::Search;
     my $oSearch = new WWW::Search('Dice');
     my $sQuery = WWW::Search::escape_query("unix and (c++ or java)");
     $oSearch->native_query($sQuery,
     			{'method' => 'bool',
     		         'state' => 'CA',
     		         'daysback' => 14});
     while (my $res = $oSearch->next_result()) {
         if(isHitGood($res->url)) {
     	 my ($company,$title,$date,$location) =
     	     $oSearch->getMoreInfo($res->url);
     	 print "$company $title $date $location " . $res->url . "\n";
         }
     }

     sub isHitGood {return 1;}

DESCRIPTION
===========

   This class is a Dice specialization of WWW::Search.  It handles making
and interpreting Dice searches at `http://www.dice.com'.

   By default, returned WWW::SearchResult objects contain only url, title
and description which is a mixture of location and skills wanted.
Function *getMoreInfo( $url )* provides more specific info - it has to be
used as

     my ($company,$title,$date,$location) =
         $oSearch->getMoreInfo($res->url);

OPTIONS
=======

   The following search options can be activated by sending a hash as the
second argument to native_query().

Format / Treatment of Query Terms
---------------------------------

   The default is to treat entire query as a boolean expression with AND,
OR, NOT and parentheses

{'method' => 'and'}
     Logical AND of all the query terms.

{'method' => 'or'}
     Logical OR of all the query terms.

{'method' => 'bool'}
     treat entire query as a boolean expression with AND, OR, NOT and
     parentheses.  This is the default option.

Restrict by Date
----------------

   The default is to return jobs posted in last 30 days

{'daysback' => $number}
     Display jobs posted in last $number days

Restrict by Location
--------------------

   The default is "ALL" which means all US states

{'state' => $state} - Only jobs in state $state.
{'state' => 'CDA'} - Only jobs in Canada.
{'state' => 'INT'} - To select international jobs.
{'state' => 'TRV'} - Require travel.
{'state' => 'TEL'} - Display telecommute jobs.
   Multiple selections are possible. To do so, add a "+" sign between
desired states, e.g. {'state' => 'NY+NJ+CT'}

   You can also restrict by 3-digit area codes. The following option does
that:

{'acode' => $area_code}
   Multiple area codes (up to 5) are supported.

Restrict by Job Term
--------------------

   No restrictions by default.

{'term' => 'CON'} - contract jobs
{'term' => 'C/H'} - contract to hire
{'term' => 'FTE'} - full time
   Use a '+' sign for multiple selection.

   There is also a switch to select either W2 or Independent:

{'addterm' => 'W2ONLY'} - W2 only
{'addterm' => 'INDOK'} - Independent ok
Restrict by Job Type
--------------------

   No restriction by default. To select jobs with specific job type use the
following option:

{'jtype' => $jobtype}
   Here $jobtype (according to `http://www.dice.com') can be one or more
of the following:

   * ANL - Business Analyst/Modeler

   * COM - Communications Specialist

   * DBA - Data Base Administrator

   * ENG - Other types of Engineers

   * FIN - Finance / Accounting

   * GRA - Graphics/CAD/CAM

   * HWE - Hardware Engineer

   * INS - Instructor/Trainer

   * LAN - LAN/Network Administrator

   * MGR - Manager/Project leader

   * OPR - Data Processing Operator

   * PA - Application Programmer/Analyst

   * QA - Quality Assurance/Tester

   * REC - Recruiter

   * SLS - Sales/Marketing

   * SWE - Software Engineer

   * SYA - Systems Administrator

   * SYS - Systems Programmer/Support

   * TEC - Custom/Tech Support

   * TWR - Technical Writer

   * WEB - Web Developer / Webmaster

Limit total number of hits
--------------------------

   The default is to stop searching after 500 hits.

{'num_to_retrieve' => $num_to_retrieve}
     Changes the default to $num_to_retrieve.

AUTHOR
======

   `WWW::Search::Dice' is written and maintained by Alexander Tkatchev
(Alexander.Tkatchev@cern.ch).

LEGALESE
========

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

backend for searching www.excite.com
************************************

NAME
====

   WWW::Search::Excite - backend for searching www.excite.com

SYNOPSIS
========

     use WWW::Search;
     my $oSearch = new WWW::Search('Excite');
     my $sQuery = WWW::Search::escape_query("+sushi restaurant +Columbus Ohio");
     $oSearch->native_query($sQuery);
     while (my $oResult = $oSearch->next_result())
       { print $oResult->url, "\n"; }

DESCRIPTION
===========

   This class is a Excite specialization of WWW::Search.  It handles
making and interpreting Excite searches `http://www.excite.com'.

   This class exports no public interface; all interaction should be done
through WWW/Search, objects.

NOTES
=====

   www.excite.com does not report the approximate result count.

SEE ALSO
========

   To make new back-ends, see WWW/Search.

CAVEATS
=======

   Only returns results from Excite's "Web Results".  Ignores all other
sections of Excite's query results.

BUGS
====

   Please tell the author if you find any!

AUTHOR
======

   As of 1998-03-23, `WWW::Search::Excite' is maintained by Martin Thurn
(MartinThurn@iname.com).

   `WWW::Search::Excite' was originally written by Martin Thurn based on
`WWW::Search::HotBot'.

LEGALESE
========

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

VERSION HISTORY
===============

2.16, 2000-11-02
----------------

   No change in functionality, but parser was totally rewritten using
HTML::TreeBuilder

2.14, 2000-
-----------

   BUGFIX for missing result-count sometimes;

2.13, 2000-10-10
----------------

   BUGFIX for missing result-count sometimes; BUGFIX for missing END of
results; BUGFIX for mis-parsing URLs

2.12, 2000-09-18
----------------

   BUGFIX for still missing the result-count; BUGFIX for missing all
results sometimes

2.11, 2000-09-05
----------------

   BUGFIX for still missing some header formats

2.07, 2000-03-29
----------------

   BUGFIX for sometimes missing header (and getting NO results)

2.06, 2000-03-02
----------------

   BUGFIX for bungled next_url

2.05, 2000-02-08
----------------

   testing now uses WWW::Search::Test module; www.excite.com only allows
(up to) 50 per page (and no odd numbers)

2.04, 2000-01-28
----------------

   www.excite.com changed their output format slightly

2.03, 1999-10-20
----------------

   www.excite.com changed their output format slightly; use strip_tags()
on title and description results

2.02, 1999-10-05
----------------

   now uses hash_to_cgi_string()

1.12, 1999-06-29
----------------

   updated test cases

1.10, 1999-06-11
----------------

   fixed a BUG where returned URLs were garbled (maybe this was because
www.excite.com changed their links)

1.08, 1998-11-06
----------------

   www.excite.com changed their output format slightly (thank you Jim
(jsmyser@bigfoot.com) for pointing it out!)

1.7, 1998-10-09
---------------

   use new split_lines function

1.5
---

   \n changed to \012 for MacPerl compatibility

1.4
---

   Modified for new Excite output format.

1.2
---

   First publicly-released version.

class for searching ExciteNews
******************************

NAME
====

   WWW::Search::Excite::News - class for searching ExciteNews

SYNOPSIS
========

   require WWW::Search; $search = new WWW::Search('Excite::News');

DESCRIPTION
===========

   Class for searching Excite News `http://www.excite.com'.  Excite has
one of the best news bot on the web.

   Following results returned for printing are:

   $result->{'description'}  will return description if any
$result->{'source'} articles news source $result->{'date'} articles date

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

SEE ALSO
========

   To make new back-ends, see WWW/Search.

HOW DOES IT WORK?
=================

   `native_setup_search' is called before we do anything.  It initializes
our private variables (which all begin with underscores) and sets up a URL
to the first results page in `{_next_url}'.

   `native_retrieve_some' is called (from `WWW::Search::retrieve_some')
whenever more hits are needed.  It calls the LWP library to fetch the page
specified by `{_next_url}'.  It parses this page, appending any search
hits it finds to `{cache}'.  If it finds a "next" button in the text, it
sets `{_next_url}' to point to the page for the next set of results,
otherwise it sets it to undef to indicate we are done.

AUTHOR
======

   Maintained by Jim Smyser <jsmyser@bigfoot.com>

TESTING
=======

   This module adheres to the `WWW::Search' test suite mechanism.  See
$TEST_CASES below.

VERSION HISTORY
===============

2.03, 2000-03-21
----------------

   New format changes

2.02, 1999-10-5
---------------

   Misc. formatting changes

2.01, 1999-07-13
----------------

   New test mechanism

COPYRIGHT
=========

   The original parts from John Heidemann are subject to following
copyright notice:

   Copyright (c) 1996-1998 University of Southern California.  All rights
reserved.

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

class for searching ExciteforWeb engine
***************************************

NAME
====

   WWW::Search::ExciteForWebServers - class for searching ExciteforWeb
engine

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('ExciteForWebServers');

DESCRIPTION
===========

   This class is a specialization of WWW::Search for search indices built
using Excite for Web Servers (available from `http://www.excite.com').

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

   This object interprets the WWW::Search `search_how' in this node
attribute as follows:

     match_any    = concept search
     match_all    = keyword (simple) search
     match_phrase = error condition
     match_boolean= error condition

AUTHOR
======

   `WWW::Search::ExciteForWebServers' is written by Paul Lindner,
<lindner@itu.int>

COPYRIGHT
=========

   Copyright (c) 1997,98 by the United Nations Administrative Committee on
Coordination (ACC)

   All rights reserved.

class for searching Fireball
****************************

NAME
====

   WWW::Search::Fireball - class for searching Fireball

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('Fireball');

DESCRIPTION
===========

   This class is an Fireball specialization of WWW::Search.  It handles
making and interpreting Fireball searches `http://www.fireball.de'.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

SEE ALSO
========

   To make new back-ends, see WWW/Search.

HOW DOES IT WORK?
=================

   `native_setup_search' is called before we do anything.  It initializes
our private variables (which all begin with underscores) and sets up a URL
to the first results page in `{_next_url}'.

   `native_retrieve_some' is called (from `WWW::Search::retrieve_some')
whenever more hits are needed.  It calls the LWP library to fetch the page
specified by `{_next_url}'.  It parses this page, appending any search
hits it finds to `{cache}'.  If it finds a "next" button in the text, it
sets `{_next_url}' to point to the page for the next set of results,
otherwise it sets it to undef to indicate we're done.

AUTHOR
======

   `WWW::Search::Fireball' has been shamelessly copied by Andreas
Borchert, <borchert@mathematik.uni-ulm.de> from `WWW::Search::AltaVista'
by John Heidemann, <johnh@isi.edu>.

COPYRIGHT
=========

   The original parts from John Heidemann are subject to following
copyright notice:

   Copyright (c) 1996-1998 University of Southern California.  All rights
reserved.

   Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are duplicated
in all such forms and that any documentation, advertising materials, and
other materials related to such distribution and use acknowledge that the
software was developed by the University of Southern California,
Information Sciences Institute.  The name of the University may not be
used to endorse or promote products derived from this software without
specific prior written permission.

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

class for searching http://www.firstgov.gov
*******************************************

NAME
====

   WWW::Search::FirstGov - class for searching http://www.firstgov.gov

SYNOPSIS
========

     use WWW::Search;
     my $search = new WWW::Search('FirstGov'); # cAsE matters
     my $query = WWW::Search::escape_query("uncle sam");
     $search->native_query($query);
     while (my $result = $search->next_result()) {
       print $result->url, "\n";
     }

DESCRIPTION
===========

   Class specialization of WWW::Search for searching
`http://www.firstgov.gov'.

   FirstGov.gov can return up to 100 hits per page.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

OPTIONS
=======

   The following search options can be activated by sending a hash as the
second argument to native_query().

{ 'begin_at' => '100' }
     Retrieve results starting at 100th match.

{ 'pl' => 'domain', 'domain' => 'osec.doc.gov+itd.doc.gov' }
     The query is limited to searching the domains osec.doc.gov and
     itd.doc.gov.

SEE ALSO
========

   To make new back-ends, see WWW/Search, or the
specialized AltaVista searches described in options.

   See http://www.fed-search.org/specialized.html to learn more about
specialized FirstGov searches.

HOW DOES IT WORK?
=================

   `native_setup_search' is called before we do anything.  It initializes
our private variables (which all begin with underscores) and sets up a URL
to the first results page in `{_next_url}'.

   `native_retrieve_some' is called (from `WWW::Search::retrieve_some')
whenever more hits are needed.  It calls the LWP library to fetch the page
specified by `{_next_url}'.  It parses this page, appending any search
hits it finds to `{cache}'.  If it finds a "next" button in the text, it
sets `{_next_url}' to point to the page for the next set of results,
otherwise it sets it to undef to indicate we're done.

AUTHOR
======

   `WWW::Search::FirstGov' is written and maintained by Dennis Sutch -
<dsutch@doc.gov>.

LEGALESE
========

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

BUGS
====

   None reported.

VERSION HISTORY
===============

   1.03  2001-03-01 - Removed 'require 5.005_62;'.

   1.02  2001-03-01 - Removed 'my' declarations for package variables.

   1.01  2001-02-26 - Fixed problem with quoted sring on MSWin.
        Removed 'our' declarations.

   1.00  2001-02-23 - First publicly-released version.

class for searching Folio Views
*******************************

NAME
====

   WWW::Search:: FolioViews  -  class for searching Folio Views

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('FolioViews');

DESCRIPTION
===========

   This class is an Folio Views specialization of WWW::Search.  It queries
and interprets searches based on Folio Views, which is available at
`http://www.openmarket.com'

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

OPTIONS
=======

   This search supports sytandard WWW::Search arguments

search_url
     The Folio Views URL to search.  This usually looks like
     `http://somehost/.../cgi-bin/search2.pl'

search_args
     The arguments used for the search engine, separate them by &.

SEE ALSO
========

   To make new back-ends, see WWW/Search,

AUTHOR
======

   `WWW::Search::FolioViews' is written by Paul Lindner, <lindner@itu.int>,
Nicholas Sapirie <sapirie@unicc.org>

COPYRIGHT
=========

   Copyright (c) 1998 by the United Nations Administrative Committee on
Coordination (ACC)

   All rights reserved.

backend class for searching with go.com
***************************************

NAME
====

   WWW::Search::Go - backend class for searching with go.com

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('Go');

DESCRIPTION
===========

   This class is an Go specialization of WWW::Search.  It handles making
and interpreting Go searches `http://www.Go.com', older Infoseek search
engine.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

USAGE EXAMPLE
=============

     use WWW::Search;

     my $oSearch = new WWW::Search('Go');
     $oSearch->maximum_to_retrieve(100);

     #$oSearch ->{_debug}=1;

     my $sQuery = WWW::Search::escape_query("cgi");
     $oSearch->gui_query($sQuery);

     while (my $oResult = $oSearch->next_result())
     {
           print $oResult->url,"\t",$oResult->title,"\n";
     }

AUTHOR
======

   `WWW::Search::Go' is written by Alain BARBET, alian@alianwebserver.com

class for searching Gopher pages
********************************

NAME
====

   WWW::Search::Gopher - class for searching Gopher pages

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('Gopher');

DESCRIPTION
===========

   This class is a specialization of WWW::Search that searches Gopher
index items.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

AUTHOR
======

   `WWW::Search::NULL' is written by Paul Lindner, <lindner@itu.int>

COPYRIGHT
=========

   Copyright (c) 1997,98 by the United Nations Administrative Committee on
Coordination (ACC)

   All rights reserved.

class for searching HeadHunter
******************************

NAME
====

   WWW::Search::HeadHunter - class for searching HeadHunter

SYNOPSIS
========

     use WWW::Search;
     my $oSearch = new WWW::Search('HeadHunter');
     my $sQuery = WWW::Search::escape_query("unix and (c++ or java)");
     $oSearch->native_query($sQuery,
     			{'SID' => 'CA',
     		         'Freshness' => 14});
     while (my $res = $oSearch->next_result()) {
         print $res->company . "\t" . $res->title . "\t" . $res->change_date
     	 . "\t" . $res->location . "\t" . $res->url . "\n";
     }

DESCRIPTION
===========

   This class is a HeadHunter specialization of WWW::Search.  It handles
making and interpreting HeadHunter searches at
`http://www.HeadHunter.net'. HeadHunter supports Boolean logic with "and"s
"or"s. See `http://www.HeadHunter.net/Help/jobquerylang.htm' for a full
description of the query language.

   The returned WWW::SearchResult objects contain url, title, *company*,
location and change_date fields.

OPTIONS
=======

   The following search options can be activated by sending a hash as the
second argument to native_query().

Restrict by Date
----------------

   The default is to return jobs posted in last 30 days (internally done by
HeadHunter search engine).

{'Freshness' => $number}
     Display jobs posted in last $number days

Restrict by Location
--------------------

   No restriction by default.

{'Town' => $town}
     To select jobs from approximately 30 miles around the city.

{'SID' => $loc}
     Only jobs in state/province $loc (two letters only).

{'CID' => 'US'}
     To view only US jobs. To see jobs from other countries, check out the
     acceptable country list at `http://www.Headhunter.net/listcoun.htm'.

Restrict by Salary
------------------

   No restrictions by default.

{'Pay' => 'P1'} - less than $15,000 Per Year
{'Pay' => 'P2'} - $15,000 - $30,000 Per Year
{'Pay' => 'P3'} - $30,000 - $50,000 Per Year
{'Pay' => 'P4'} - $50,000 - $75,000 Per Year
{'Pay' => 'P4'} - $75,000 - $100,000 Per Year
{'Pay' => 'P6'} - more than $100,000 Per Year
   To select several pay ranges use a '+' sign, e.g. {'Pay' => 'P3+P4'}

Restrict by Employment Type
---------------------------

   No restrictions by default.

{'EmpType' => 'Typ1'} - Employee
{'EmpType' => 'Typ2'} - Contract
{'EmpType' => 'Typ3'} - Employee or Contract
{'EmpType' => 'Typ4'} - Intern
Restrict by Job Category
------------------------

   No restriction by default. To select jobs from a specific job category
use the following option:

{'Cats' => $job_category}
   See below the list of acceptable values of $job_category. Multiple
selections are possible (up to five) using a '+' sign, e.g. {'Cats' =>
'Cat001+Cat002'}.

   * Cat001 - Accounting

   * Cat002 - Activism

   * Cat003 - Administration

   * Cat004 - Advertising

   * Cat005 - Aerospace

   * Cat110 - Agriculture

   * Cat006 - Air Conditioning

   * Cat007 - Airlines

   * Cat008 - Apartment Management

   * Cat009 - Architecture

   * Cat010 - Art

   * Cat011 - Automotive

   * Cat012 - Aviation

   * Cat013 - Banking

   * Cat015 - Bilingual

   * Cat111 - Biotechnology

   * Cat016 - Bookkeeping

   * Cat017 - Broadcasting

   * Cat018 - Care Giving

   * Cat112 - Carpentry

   * Cat113 - Chemistry

   * Cat019 - Civil Service

   * Cat020 - Clerical

   * Cat021 - College

   * Cat114 - Communication

   * Cat022 - Computer

   * Cat023 - Construction

   * Cat125 - Consulting

   * Cat024 - Counseling

   * Cat025 - Customer Service

   * Cat026 - Decorating

   * Cat027 - Dental

   * Cat028 - Design

   * Cat029 - Driving

   * Cat030 - Education

   * Cat031 - Electronic

   * Cat032 - Emergency

   * Cat033 - Employment

   * Cat034 - Engineering

   * Cat035 - Entertainment

   * Cat036 - Environmental

   * Cat037 - Executive

   * Cat115 - Fabrication

   * Cat116 - Facilities

   * Cat038 - Fashion/Apparel

   * Cat039 - Financial

   * Cat040 - Food Services

   * Cat042 - Fundraising

   * Cat044 - General Office

   * Cat126 - Government

   * Cat045 - Graphics

   * Cat046 - Grocery

   * Cat047 - Health/Medical

   * Cat048 - Home Services

   * Cat049 - Hospital

   * Cat050 - Hotel/Motel

   * Cat052 - Human Resources

   * Cat053 - HVAC

   * Cat054 - Import/Export

   * Cat117 - Industrial

   * Cat055 - Installer

   * Cat056 - Insurance

   * Cat118 - Internet

   * Cat057 - Janitorial

   * Cat119 - Journalism

   * Cat058 - Law Enforcement

   * Cat059 - Legal

   * Cat060 - Maintenance

   * Cat061 - Management

   * Cat062 - Manufacturing

   * Cat063 - Marketing

   * Cat064 - Mechanical

   * Cat065 - Media

   * Cat066 - Merchandising

   * Cat127 - Military

   * Cat067 - Mining

   * Cat128 - Mortgage

   * Cat069 - Multimedia

   * Cat070 - Nursing

   * Cat071 - Nutrition

   * Cat121 - Packaging

   * Cat122 - Painting

   * Cat073 - Pest Control

   * Cat129 - Pharmaceutical

   * Cat075 - Photography

   * Cat076 - Plumbing

   * Cat077 - Printing

   * Cat078 - Professional

   * Cat079 - Property Management

   * Cat080 - Public Relations

   * Cat081 - Publishing

   * Cat082 - Purchasing

   * Cat083 - Quality Control

   * Cat123 - Radio

   * Cat084 - Real Estate

   * Cat085 - Recreation

   * Cat086 - Research

   * Cat087 - Restaurant

   * Cat088 - Retail

   * Cat089 - Sales

   * Cat090 - Science

   * Cat124 - Secretarial

   * Cat091 - Security

   * Cat092 - Services

   * Cat093 - Shipping/Receiving

   * Cat094 - Social Services

   * Cat130 - Supply Chain

   * Cat095 - Teaching

   * Cat096 - Technical

   * Cat097 - Telecommunications

   * Cat098 - Telemarketing

   * Cat099 - Television

   * Cat100 - Textile

   * Cat101 - Trades

   * Cat102 - Training

   * Cat103 - Transportation

   * Cat104 - Travel

   * Cat105 - Utilities

   * Cat106 - Warehouse

   * Cat107 - Waste Management

   * Cat108 - Word Processing

   * Cat109 - Work From Home

AUTHOR
======

   `WWW::Search::HeadHunter' is written and maintained by Alexander
Tkatchev (Alexander.Tkatchev@cern.ch).

LEGALESE
========

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

backend for searching hotbot.lycos.com
**************************************

NAME
====

   WWW::Search::HotBot - backend for searching hotbot.lycos.com

SYNOPSIS
========

     use WWW::Search;
     my $oSearch = new WWW::Search('HotBot');
     my $sQuery = WWW::Search::escape_query("+sushi restaurant +Columbus Ohio");
     $oSearch->native_query($sQuery);
     while (my $oResult = $oSearch->next_result())
       { print $oResult->url, "\n"; }

DESCRIPTION
===========

   This class is a HotBot specialization of WWW::Search.  It handles
making and interpreting HotBot searches `http://www.hotbot.com'.

   This class exports no public interface; all interaction should be done
through WWW/Search, objects.

   By default, WWW::Search::HotBot uses hotbot.com's text-only interface,
which can be found at http://hotbot.lycos.com/text .  If you want to
perform a query with the same default options as if a user typed it in the
browser window (i.e. at http://www.hotbot.com), call
$oSearch->gui_query($sQuery) instead of ->native_query().

   The default behavior is for HotBot to look for "any of" the query terms:

     $oSearch->native_query(escape_query('Dorothy Oz'));

   If you want "all of", call native_query like this:

     $oSearch->native_query(escape_query('Dorothy Oz'), {'SM' => 'MC'});

   If you want to send HotBot a boolean phrase, call native_query like
this:

     $oSearch->native_query(escape_query('Oz AND Dorothy NOT Australia'), {'SM' => 'B'});

   See below for other query-handling options.

OPTIONS
=======

   The following search options can be activated by sending a hash as the
second argument to native_query().

Format / Treatment of Query Terms
---------------------------------

   The default is logical OR of all the query terms.

{'SM' => 'MC'}
     "Must Contain": logical AND of all the query terms.

{'SM' => 'SC'}
     "Should Contain": logical OR of all the query terms.  This is the
     default.

{'SM' => 'B'}
     "Boolean": the entire query is treated as a boolean expression with
     AND, OR, NOT, and parentheses.

{'SM' => 'name'}
     The entire query is treated as a person's name.

{'SM' => 'phrase'}
     The entire query is treated as a phrase.

{'SM' => 'title'}
     The query is applied to the page title.  (I assume the logical OR of
     the query terms will be applied to the page title.)

{'SM' => 'url'}
     The query is assumed to be a URL, and the results will be pages that
     link to the query URL.

Restricting Search to a Date Range
----------------------------------

   The default is no date restrictions.

{'date' => 'within', 'DV' => 90}
     Only return pages updated within 90 days of today.  (Substitute any
     integer in place of 90.)

{'date' => 'range', 'DR' => 'newer', 'DY' => 97, 'DM' => 12, 'DD' => 25}
     Only return pages updated after Christmas 1997.  (Substitute any
     year, month, and day for 97, 12, 25.)

{'date' => 'range', 'DR' => 'older', 'DY' => 97, 'DM' => 12, 'DD' => 25}
     Only return pages updated before Christmas 1997.  (Substitute any
     year, month, and day for 97, 12, 25.)

Restricting Search to a Geographic Area
---------------------------------------

   The default is no restriction to geographic area.

{'RD' => 'AN'}
     Return pages from anywhere.  This is the default.

{'RD' => 'DM', 'Domain' => 'microsoft.com, .cz'}
     Restrict search to pages located in the listed domains.  (Substitute
     any list of domain substrings.)

{'RD' => 'RG', 'RG' => '.com'}
     Restrict search to North American commercial web sites.

{'RD' => 'RG', 'RG' => '.edu'}
     Restrict search to North American educational web sites.

{'RD' => 'RG', 'RG' => '.gov'}
     Restrict search to United Stated Government web sites.

{'RD' => 'RG', 'RG' => '.mil'}
     Restrict search to United States military commercial web sites.

{'RD' => 'RG', 'RG' => '.net'}
     Restrict search to North American '.net' web sites.

{'RD' => 'RG', 'RG' => '.org'}
     Restrict search to North American organizational web sites.

{'RD' => 'RG', 'RG' => 'NA'}
     "North America": Restrict search to all of the above types of web
     sites.

{'RD' => 'RG', 'RG' => 'AF'}
     Restrict search to web sites in Africa.

{'RD' => 'RG', 'RG' => 'AS'}
     Restrict search to web sites in India and Asia.

{'RD' => 'RG', 'RG' => 'CA'}
     Restrict search to web sites in Central America.

{'RD' => 'RG', 'RG' => 'DU'}
     Restrict search to web sites in Oceania.

{'RD' => 'RG', 'RG' => 'EU'}
     Restrict search to web sites in Europe.

{'RD' => 'RG', 'RG' => 'ME'}
     Restrict search to web sites in the Middle East.

{'RD' => 'RG', 'RG' => 'SE'}
     Restrict search to web sites in Southeast Asia.

Requesting Certain Multimedia Data Types
----------------------------------------

   The default is not specifically requesting any multimedia types
(presumably, this will NOT restrict the search to NON-multimedia pages).

{'FAC' => 1}
     Return pages which contain Adobe Acrobat PDF data.

{'FAX' => 1}
     Return pages which contain ActiveX.

{'FJA' => 1}
     Return pages which contain Java.

{'FJS' => 1}
     Return pages which contain JavaScript.

{'FRA' => 1}
     Return pages which contain audio.

{'FSU' => 1, 'FS' => '.txt, .doc'}
     Return pages which have one of the listed extensions.  (Substitute
     any list of DOS-like file extensions.)

{'FSW' => 1}
     Return pages which contain ShockWave.

{'FVI' => 1}
     Return pages which contain images.

{'FVR' => 1}
     Return pages which contain VRML.

{'FVS' => 1}
     Return pages which contain VB Script.

{'FVV' => 1}
     Return pages which contain video.

Requesting Pages at Certain Depths on Website
---------------------------------------------

   The default is pages at any level on their website.

{'PS'=>'A'}
     Return pages at any level on their website.  This is the default.

{'PS' => 'D', 'D' => 3 }
     Return pages within 3 links of "top" page of their website.
     (Substitute any integer in place of 3.)

{'PS' => 'F'}
     Only return pages that are the "top" page of their website.

SEE ALSO
========

   To make new back-ends, see WWW/Search.

CAVEATS
=======

   When www.hotbot.com reports a "Mirror" URL, WWW::Search::HotBot ignores
it.  Therefore, the number of URLs returned by WWW::Search::HotBot might
not agree with the value returned in approximate_result_count.

BUGS
====

   Please tell the author if you find any!

AUTHOR
======

   As of 1998-02-02, `WWW::Search::HotBot' is maintained by Martin Thurn
(MartinThurn@iname.com).

   `WWW::Search::HotBot' was originally written by Wm. L. Scheding, based
on `WWW::Search::AltaVista'.

LEGALESE
========

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

VERSION HISTORY
===============

   If it is not listed here, then it was not a meaningful nor released
revision.

2.21, 2000-12-11
----------------

   new URL for advanced search

2.19, 2000-10-11
----------------

   added AM1=MC to all URLs in GUI mode (hotbot.com seems to "randomly"
add this if you search manually at their site)

2.18, 2000-06-26
----------------

   fix for only one page of gui results; and "next" link in new place

2.17, 2000-05-24
----------------

   was still missing first URL of non-gui(?) results!

2.16, 2000-05-17
----------------

   was missing first URL of gui results

2.15, 2000-04-03
----------------

   fixed gui_query()

2.14, 2000-02-01
----------------

   testing now uses WWW::Search::Test module

2.13, 2000-01-31
----------------

   bugfix: was missing title

2.12, 2000-01-19
----------------

   new function gui_query(), and handle output from it

2.10, 1999-12-22
----------------

   handle new result format

2.09, 1999-12-15
----------------

   handle new result count format

2.08, 1999-12-10
----------------

   handle new output format

2.07, 1999-11-12
----------------

   BUGFIX for domain-limited URL parsing (thanks to Leon Brocard)

2.06, 1999-10-18
----------------

   www.hotbot.com changed their output format slightly; now uses
strip_tags() on title and description

2.05, 1999-10-05
----------------

   now uses hash_to_cgi_string(); new test cases

2.03, 1999-09-28
----------------

   BUGFIX: was missing the "Next page" link sometimes.

2.02, 1999-08-17
----------------

   Now is able to parse "URL-only" format (i.e. {'DE' => 0}) and "brief
description" format (i.e. {'DE' => 1}) if the user so desires.

1.34, 1999-07-01
----------------

   New test cases.

1.32, 1999-06-20
----------------

   Now unescapes the URLs before returning them.

1.31, 1999-06-11
----------------

   www.hotbot.com changed their output format ever so slightly.  (Thanks
to Jim jsmyser@bigfoot.com for pointing it out)

1.30, 1999-04-12
----------------

   BUG FIX: results for domain-limited search were not parsed.  (Thanks to
Christopher York yorkc@ccwf.cc.utexas.edu for pointing it out)

1.29, 1999-02-22
----------------

   www.hotbot.com changed their output format.  (Thanks to Tim Chklovski
timc@mit.edu for pointing it out)

1.27, 1998-11-06
----------------

   HotBot changed their output format(?).  HotBot.pm now uses hotbot.com's
text-only search results format.  Minor documentation changes.

1.25, 1998-09-11
----------------

   HotBot changed their output format ever so slightly.  Documentation
added for all known HotBot query options!

1.23
----

   Better documentation for boolean queries.  (Thanks to Jason Titus
jason_titus@odsnet.com)

1.22
----

   www.hotbot.com changed their output format.

1.21
----

   www.hotbot.com changed their output format.

1.17
----

   www.hotbot.com changed their search script location and output format
on 1998-05-21.  Also, as many as 6 fields of each SearchResult are now
filled in.

1.13
----

   Fixed the maximum_to_retrieve off-by-one problem.  Updated test cases.

1.12
----

   www.hotbot.com does not do truncation. Therefore, if the query contains
truncation characters (i.e. '*' at end of words), they are simply deleted
before the query is sent to www.hotbot.com.

1.11, 1998-02-05
----------------

   Fixed and revamped by Martin Thurn.

class for searching ZDnet HotFiles
**********************************

NAME
====

   WWW::Search::HotFiles - class for searching ZDnet HotFiles

SYNOPSIS
========

   require WWW::Search; $search = new WWW::Search('HotFiles');

DESCRIPTION
===========

   Class for searching ZDnet HotFiles (shareware, freeware) via Lycos.
`http://www.hotfiles.lycos.com'.

   If you use the raw method for this backend you will need to include a
"<p>" at end of your print statement, example:      print $result->raw(),
"<p>\n";

   This is so that each result returned will have a HTML break since the
HTML is being extracted from tables, and, there is no <p> or <br> trailing
returned HITS to properly format the results. No BIG deal really.

   Print optioins: Using score will return nice star images for rating
purposes at end of each description line for each HIT if desired.

   Using index_date will return the files date.

   Raw returns description, star rating image, date, downloads, OS version.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

USAGE EXAMPLE
=============

     One of several print samples for this backend (this is a WebSearch
     example):

     print <<END;

     <FONT SIZE=2><B>$count. <a href="$prefix$_">$result->{'title'}</A></B><BR>
     $result->{'description'}
     $result->{'index_date'} $result->{'score'}<P></SMALL></FONT>

     END

SEE ALSO
========

   To make new back-ends, see WWW/Search.

AUTHOR
======

   Maintained by Jim Smyser <jsmyser@bigfoot.com>

TESTING
=======

   HotFiles.pm adheres to the WWW::Search test mechanism.  See $TEST_CASES
below.

COPYRIGHT
=========

   The original parts from John Heidemann are subject to following
copyright notice:

   Copyright (c) 1996-1998 University of Southern California.  All rights
reserved.

   Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are duplicated
in all such forms and that any documentation, advertising materials, and
other materials related to such distribution and use acknowledge that the
software was developed by the University of Southern California,
Information Sciences Institute.  The name of the University may not be
used to endorse or promote products derived from this software without
specific prior written permission.

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

class for searching Infoseek
****************************

NAME
====

   WWW::Search::Infoseek - class for searching Infoseek

SYNOPSIS
========

     use WWW::Search;
     my $oSearch = new WWW::Search('Infoseek');
     my $sQuery = WWW::Search::escape_query("+sushi restaurant +Columbus Ohio");
     $oSearch->native_query($sQuery);
     while (my $oResult = $oSearch->next_result())
       { print $oResult->url, "\n"; }

DESCRIPTION
===========

   This class is a Infoseek specialization of WWW::Search.  It handles
making and interpreting Infoseek searches `http://www.infoseek.com'.

   This class exports no public interface; all interaction should be done
through WWW/Search, objects.

SEE ALSO
========

     L<WWW::Search::Infoseek::Companies>
     L<WWW::Search::Infoseek::Web>
     L<WWW::Search::Infoseek::News>

   To make new back-ends, see WWW/Search.

BUGS
====

   Please tell the author if you find any!

TESTING
=======

   This module adheres to the `WWW::Search' test suite mechanism.

   See `WWW::Search::Infoseek::Web' for test cases for the default usage.

AUTHOR
======

   `WWW::Search::Infoseek' is maintained by Martin Thurn
(MartinThurn@iname.com).

LEGALESE
========

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

VERSION HISTORY
===============

   If it is not listed here, then it was not a meaningful nor released
revision.

2.06, 1999-12-10
----------------

   handle infoseek.com's slight output format change

2.05, 1999-10-05
----------------

   BUGFIX: parser for ::Companies and ::News; now uses hash_to_cgi_string()

2.04, 1999-09-29
----------------

   BUGFIX: handle descriptions with embedded \n; ignore "company profile"
URLs during Web search

2.02, 1999-09-28
----------------

   BUGFIX: was going to the "previous" page instead of the "next" page!

2.01, 1999-07-13
----------------

1.18, 1999-07-09
----------------

   BUGFIX for not seeing all the URLs on a page, and fetching the first
page of results over and over(!).

1.16, 1999-06-30
----------------

   Now strips HTML tags from titles and descriptions.

1.14, 1999-06-29
----------------

   Companies and News searches now work!

1.13, 1999-06-28
----------------

   www.infoseek.com changed their output format ever so slightly.
Companies and News searches return URLs, but titles and descriptions are
unreliable.

1.12, 1999-05-21
----------------

   www.infoseek.com changed their output format.

1.11, 1999-04-27
----------------

   Fixed BUG in parsing of News search results.  Added version method.

1.08, 1999-02-09
----------------

   Fixed BUG in parsing of Companies search results.  Thanks to Jim Smyser
(jsmyser@bigfoot.com) for pointing it out.

1.7, 1998-10-05
---------------

   www.infoseek.com changed their output format.  Thanks to Andreas
Borchert (borchert@mathematik.uni-ulm.de) for patches.

1.6, 1998-09-18
---------------

   Fixed BUG where (apparently) no titles were retrieved.

1.5
---

   www.infoseek.com changed their output format ever-so-slightly.

1.3
---

   First publicly-released version.

class for Infoseek Companies searching
**************************************

NAME
====

   WWW::Search::Infoseek::Companies - class for Infoseek Companies
searching

SYNOPSIS
========

     use WWW::Search;
     my $oSearch = new WWW::Search('Infoseek::Companies');
     my $sQuery = WWW::Search::escape_query("+sushi restaurant +Columbus Ohio");
     $oSearch->native_query($sQuery);
     while (my $oResult = $oSearch->next_result())
       { print $oResult->url, "\n"; }

DESCRIPTION
===========

   This class implements the Infoseek Companies search (specializing
Infoseek and WWW::Search).  It handles making and interpreting Infoseek
Companies searches `http://www.infoseek.com'.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

TESTING
=======

   This module adheres to the WWW::Search test mechanism.  See $TEST_CASES
below.

AUTHOR
======

   `WWW::Search::Infoseek::Companies' was written by Martin Thurn
<MartinThurn@iname.com> based on AltaVista::Web by John Heidemann,
<johnh@isi.edu>.

COPYRIGHT
=========

   Copyright (c) 1996 University of Southern California.  All rights
reserved.

   Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are duplicated
in all such forms and that any documentation, advertising materials, and
other materials related to such distribution and use acknowledge that the
software was developed by the University of Southern California,
Information Sciences Institute.  The name of the University may not be
used to endorse or promote products derived from this software without
specific prior written permission.

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

class for searching for e-mail at Infoseek
******************************************

NAME
====

   WWW::Search::Infoseek::Email - class for searching for e-mail at
Infoseek

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('Infoseek::Email');

DESCRIPTION
===========

   Back-end for Infoseek search engine .

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

OPTIONS
=======

operator Ex. operator=>'AND' Values AND or OR (defaults to OR).
     If you want to use directly the native '+' and '-' operators than use
     the OR operator.

SEE ALSO
========

   To make new back-ends, see WWW/Search.

AUTHOR
======

   Cesare Feroldi de Rosa, <C.Feroldi@IT.net> 1996.  (Derived from
AltaVista.pm.)

COPYRIGHT
=========

   Copyright (c) 1996 University of Southern California.  All rights
reserved.

   Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are duplicated
in all such forms and that any documentation, advertising materials, and
other materials related to such distribution and use acknowledge that the
software was developed by the University of Southern California,
Information Sciences Institute.  The name of the University may not be
used to endorse or promote products derived from this software without
specific prior written permission.

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

class for Infoseek News searching
*********************************

NAME
====

   WWW::Search::Infoseek::News - class for Infoseek News searching

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('Infoseek::News');
     my $sQuery = WWW::Search::escape_query("plane crash airline disaster");
     $oSearch->native_query($sQuery);
     while (my $oResult = $oSearch->next_result())
       { print $oResult->url, "\n"; }

DESCRIPTION
===========

   This class implements the Infoseek News search (specializing Infoseek
and WWW::Search).  It handles making and interpreting Infoseek News
searches `http://www.infoseek.com'.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

TESTING
=======

   This module adheres to the `WWW::Search' test suite mechanism.  See the
value of $TEST_CASES below.

AUTHOR
======

   `WWW::Search::Infoseek::News' was written by Martin Thurn
<MartinThurn@iname.com>

class for Infoseek Web searching
********************************

NAME
====

   WWW::Search::Infoseek::Web - class for Infoseek Web searching

SYNOPSIS
========

     use WWW::Search;
     my $oSearch = new WWW::Search('Infoseek::Web');
     my $sQuery = WWW::Search::escape_query("+sushi restaurant +Columbus Ohio");
     $oSearch->native_query($sQuery);
     while (my $oResult = $oSearch->next_result())
       { print $oResult->url, "\n"; }

DESCRIPTION
===========

   This class implements the Infoseek Web search (specializing Infoseek
and WWW::Search).  It handles making and interpreting Infoseek Web searches
`http://www.infoseek.com'.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

TESTING
=======

   This module adheres to the WWW::Search test mechanism.  See $TEST_CASES
below.

AUTHOR
======

   `WWW::Search::Infoseek::Web' was written by Martin Thurn
<MartinThurn@iname.com>

class for searching Open Text Livelink Intranet search engine
*************************************************************

NAME
====

   WWW::Search::Livelink  -  class for searching Open Text Livelink
Intranet search engine

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('Livelink');

DESCRIPTION
===========

   This class is an Open Text Livelink Intranet specialization of
WWW::Search.  It queries and interprets searches based on Livelink
Intranet, which is available at `http://www.opentext.com'

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

OPTIONS
=======

   This search supports sytandard WWW::Search arguments

search_url
     The Livelink Intranet URL to search.  This usually looks like
     `http://somehost/otcgi/llscgi60.exe'

search_args
     The arguments used for the search engine, separate them by &.

SEE ALSO
========

   To make new back-ends, see WWW/Search,

AUTHOR
======

   `WWW::Search::Livelink' is written by Paul Lindner, <lindner@itu.int>,
Nicholas Sapirie <sapirie@unicc.org>

COPYRIGHT
=========

   Copyright (c) 1998 by the United Nations Administrative Committee on
Coordination (ACC)

   All rights reserved.

class for searching MSIndexServer search engine
***********************************************

NAME
====

   WWW::Search::MSIndexServer - class for searching MSIndexServer search
engine

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('MSIndexServer');

DESCRIPTION
===========

   This class is a MSIndexServer specialization of WWW::Search.  It
queries and interprets searches based on MSIndexServer, which is available
at `http://www.microsoft.com/'

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

OPTIONS
=======

   This search supports standard WWW::Search arguments

search_url
     The MSIndexServer URL to search.  This usually looks like
     `http://somehost/scripts/queryhit.idq'

search_args
     The arguments used for the search engine, separate them by &.

search_method
     POST or GET

search_debug
     Turn debugging on or off

search_how
     Possible values match_any, match_all, match_phrase

SEE ALSO
========

   To make new back-ends, see WWW/Search,

AUTHOR
======

   `WWW::Search::MSIndexServer' is written by Paul Lindner,
<lindner@itu.int>, Nicholas Sapirie <sapirie@unicc.org>

COPYRIGHT
=========

   Copyright (c) 1998 by the United Nations Administrative Committee on
Coordination (ACC)

   All rights reserved.

class for searching http://mc3.go2net.com!
******************************************

NAME
====

   WWW::Search::MetaCrawler - class for searching http://mc3.go2net.com!

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('MetaCrawler');

DESCRIPTION
===========

   Class specialization of WWW::Search for searching
`http://mc3.go2net.com'.  MetaCrawler.com can return up to 1000 hits.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

SEE ALSO
========

   To make new back-ends, see WWW/Search, or the
specialized AltaVista searches described in options.

HOW DOES IT WORK?
=================

   `native_setup_search' is called before we do anything.  It initializes
our private variables (which all begin with underscores) and sets up a URL
to the first results page in `{_next_url}'.

   `native_retrieve_some' is called (from `WWW::Search::retrieve_some')
whenever more hits are needed.  It calls the LWP library to fetch the page
specified by `{_next_url}'.  It parses this page, appending any search
hits it finds to `{cache}'.  If it finds a "next" button in the text, it
sets `{_next_url}' to point to the page for the next set of results,
otherwise it sets it to undef to indicate we're done.

AUTHOR
======

   `WWW::Search::MetaCrawler' is written and maintained by Jim Smyser -
<jsmyser@bigfoot.com>.

COPYRIGHT
=========

   Copyright (c) 1996-1998 University of Southern California.  All rights
reserved.

   Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are duplicated
in all such forms and that any documentation, advertising materials, and
other materials related to such distribution and use acknowledge that the
software was developed by the University of Southern California,
Information Sciences Institute.  The name of the University may not be
used to endorse or promote products derived from this software without
specific prior written permission.

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

class for searching online Encyclopedias
****************************************

NAME
====

   WWW::Search::Metapedia - class for searching online Encyclopedias

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('Metapedia');

DESCRIPTION
===========

   `http://www.savvysearch.com'.

   Silly class I made to sponge off a Encyclopedia meta search engine.
Searches multi online Encyclopedias.

   Covers:

   Encylopedia Britannica - paid subscription service Encarta Knowledge
Adventure Infoplease

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

SEE ALSO
========

   To make new back-ends, see WWW/Search.

HOW DOES IT WORK?
=================

   `native_setup_search' is called before we do anything.  It initializes
our private variables (which all begin with underscores) and sets up a URL
to the first results page in `{_next_url}'.

   `native_retrieve_some' is called (from `WWW::Search::retrieve_some')
whenever more hits are needed.  It calls the LWP library to fetch the page
specified by `{_next_url}'.  It parses this page, appending any search
hits it finds to `{cache}'.  If it finds a "next" button in the text, it
sets `{_next_url}' to point to the page for the next set of results,
otherwise it sets it to undef to indicate we're done.

AUTHOR
======

   Jim Smyser <jsmyser@bigfoot.com>

COPYRIGHT
=========

   Copyright (c) 1996-1998 University of Southern California.  All rights
reserved.

   Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are duplicated
in all such forms and that any documentation, advertising materials, and
other materials related to such distribution and use acknowledge that the
software was developed by the University of Southern California,
Information Sciences Institute.  The name of the University may not be
used to endorse or promote products derived from this software without
specific prior written permission.

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

class for searching Monster
***************************

NAME
====

   WWW::Search::Monster - class for searching Monster

SYNOPSIS
========

     use WWW::Search;
     my $oSearch = new WWW::Search('Monster');
     my $sQuery = WWW::Search::escape_query("unix and (c++ or java)");
     $oSearch->native_query($sQuery,
     			{'st' => 'CA',
     			 'tm' => '14d'});
     while (my $res = $oSearch->next_result()) {
         print $res->company . "\t" . $res->title . "\t" . $res->change_date
     	 . "\t" . $res->location . "\t" . $res->url . "\n";
     }

DESCRIPTION
===========

   This class is a Monster specialization of WWW::Search.  It handles
making and interpreting Monster searches at `http://www.monster.com'.
Monster supports Boolean logic with "and"s "or"s. See
`http://jobsearch.monster.com/jobsearch_tips.asp' for a full description
of the query language.

   The returned WWW::SearchResult objects contain url, title, *company*,
location and change_date fields.

OPTIONS
=======

   The following search options can be activated by sending a hash as the
second argument to native_query().

Restrict by Date
----------------

   The default is to return jobs posted in last 30 days.  An example below
changes the default to 14 days:

{'tm' => '14d'}
Restrict by Location
--------------------

   No restriction by default.

{'st' => $state}
     Only jobs in state $state. To select multiple states separate them
     with a "+", e.g. {'st' => 'NY+NJ+CT'}

{'lid' => $location_id}
     Only jobs in $location_id. To find out what $location_id you need
     please look at the source of `http://jobsearch.monster.com'. Note
     that $location_id does not mean the area telephone code.

Restrict by Job Category
------------------------

   Use {'fn' => $cat_id}  to select one or more job categories you want.
For multiple selection use a '+' sign, e.g. {'fn' => '1+2'}.  Possible
categories are:

   * 1	Accounting/Finance

   * 2	Administrative/Clerical

   * 12	Creative Arts/Media

   * 3	Education/Training

   * 4	Engineering/Architect/Design

   * 5	Human Resources

   * 6	Information Technology

   * 45	Insurance

   * 7	Legal/Law Enforcement/Security

   * 47	Manufacturing/Production

   * 8	Marketing/Advertising

   * 9	Medical/Healthcare

   * 11	Other

   * 44	Retail

   * 10	Sales/Sales Management

   * 46	Science/Bio-Pharmaceutical

   * 13	Travel/Hospitality/Restaurant

AUTHOR
======

   `WWW::Search::HeadHunter' is written and maintained by Alexander
Tkatchev (Alexander.Tkatchev@cern.ch).

LEGALESE
========

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

class for searching NetFind  Originally based on Google.pm. NetFind is the same as AOL search.
**********************************************************************************************

NAME
====

   WWW::Search::NetFind - class for searching NetFind Originally based on
Google.pm. NetFind is the same as AOL search.

SYNOPSIS
========

   use WWW::Search; my $Search = new WWW::Search('NetFind'); # cAsE matters
my $Query = WWW::Search::escape_query("search engine consultant");
$Search->native_query($Query); while (my $Result = $Search->next_result())
{ print $Result->url, "\n"; }

DESCRIPTION
===========

   This class is a NetFind (AOL) specialization of WWW::Search.  It
handles making and interpreting NetFind searches.  `http://search.aol.com'.

   NetFinds returns 100 Hits per page.

   This class exports no public interface; all interaction should be done
through WWW/Search, objects.

AOL SEARCH
==========

   Please note that searching at search.aol.com produces results from both
the Open Source Directory and the licensed Inktomi search engine. Results
from Open Source Directory are presented first followed by results from
Inktomi.

   If there are no results from the Open Source Directory, then results
are presented from Inktomi alone. Those results that start with "MATCHING
SITES" are from the Open Source Directory and those that start with
"MATCHING WEB PAGES" are from the Inktomi engine.

   If you are interested in results only from Inktomi, then force the
search to use the web.adp query like so:

     $search->native_query(WWW::Search::escape_query($query),{search_url=>'http://netfind.aol.com/web.adp'});

   If you are interested in results only from the Open Source Directory,
refer to the OpenDirectory.pm module.

SEE ALSO
========

   To make new back-ends, see WWW/Search.

HOW DOES IT WORK?
=================

   `native_setup_search' is called (from `WWW::Search::setup_search')
before we do anything.  It initializes our private variables (which all
begin with underscore) and sets up a URL to the first results page in
`{_next_url}'.

   `native_retrieve_some' is called (from `WWW::Search::retrieve_some')
whenever more hits are needed.  It calls `WWW::Search::http_request' to
fetch the page specified by `{_next_url}'.  It then parses this page,
appending any search hits it finds to `{cache}'.  If it finds a "next"
button in the text, it sets `{_next_url}' to point to the page for the next
set of results, otherwise it sets it to undef to indicate we"re done.

TESTING
=======

   This module adheres to the `WWW::Search' test suite mechanism.

AUTHOR
======

   This backend is maintained and supported by Gil Vidals.
<gil@positiongeek.com>

LEGALESE
========

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

BUGS
====

   Since this is a new Backend there are undoubtly one. Report any ASAP.

VERSION HISTORY 1.8 Changed the root search from netfind.aol.com to search.aol.com because netfind.aol.com seemed very unresponsive and the searches timed out frequently. Also changed to the new format using $self->hash_to_cgi_string($self->{_options});
=============================================================================================================================================================================================================================================================

   1.5 Formatting change 10/08/99

   0.7 First release  09/19/99

class for searching Nomade
**************************

NAME
====

   WWW::Search::Nomade - class for searching Nomade

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('Nomade');

DESCRIPTION
===========

   This class is an Nomade specialization of WWW::Search.  It handles
making and interpreting Nomade searches `http://www.Nomade.fr', a french
search engine.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

USAGE EXAMPLE
=============

     use WWW::Search;

     my $oSearch = new WWW::Search('Nomade');
     $oSearch->maximum_to_retrieve(100);

     #$oSearch ->{_debug}=1;

     my $sQuery = WWW::Search::escape_query("cgi");
     $oSearch->gui_query($sQuery);

     while (my $oResult = $oSearch->next_result())
     {
           print $oResult->url,"\t",$oResult->title,"\n";
     }

AUTHOR
======

   `WWW::Search::Nomade' is written by Alain BARBET,
alian@alianwebserver.com

class for searching any web site
********************************

NAME
====

   WWW::Search::NULL - class for searching any web site

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('Null');

DESCRIPTION
===========

   This class is a specialization of WWW::Search that only returns an
error message.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

   This modules is really a hack for systems that want to include indices
that have no corresponding WWW::Search module (like UNIONS)

AUTHOR
======

   `WWW::Search::Null' is written by Paul Lindner, <lindner@itu.int>

COPYRIGHT
=========

   Copyright (c) 1998 by the United Nations Administrative Committee on
Coordination (ACC)

   All rights reserved.

class for searching PLS PLweb search engine
*******************************************

NAME
====

   WWW::Search::PLweb - class for searching PLS PLweb search engine

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('PLweb');

DESCRIPTION
===========

   This class is a PLweb specialization of WWW::Search.  It queries and
interprets searches based on PLweb, by PLS `http://www.pls.com/'.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

   This software assumes that you're using the default output format for a
PLweb search.  It should look like this:

     VAL DOCUMENT DB SIZE
     ------------------------------------------------------------------
     388 Document1 foo 1122 ...

OPTIONS
=======

   This search supports standard WWW::Search arguments

search_url
     The PLweb URL to search.  On unix this usually looks like
     http://somehost/cgi-bin/iopcode.pl

search_args
     The arguments used for the search engine, separate them by &.

SEE ALSO
========

   To make new back-ends, see WWW/Search,

AUTHOR
======

   `WWW::Search::PLweb' is written by Paul Lindner, <lindner@itu.int>

BUGS
====

   Things not supported: $result->raw()

COPYRIGHT
=========

   Copyright (c) 1997, 98 by the United Nations Administrative Committee
on Coordination (ACC)

   All rights reserved.

class for searching SFgate/Wais search engine
*********************************************

NAME
====

   WWW::Search::SFgate - class for searching SFgate/Wais search engine

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('SFgate');

DESCRIPTION
===========

   This class is a SFgate specialization of WWW::Search.  It queries and
interprets searches based on SFgate, which is available at
`http://ls6-www.informatik.uni-dortmund.de/SFgate/welcome.html'

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

   This object rewrites URLs to use the preformatted, verbose output
format of SFgate.  This allows it to get the 'score' and 'size'
information easily.  The url portions it rewrites are 'verbose=1' and
'listenv=pre'.

OPTIONS
=======

   This search supports standard WWW::Search arguments

search_url
     The SFgate URL to search.  This usually looks like
     `http://somehost/cgi-bin/SFgate'

search_args
     The arguments used for the search engine, separate them by &.

SEE ALSO
========

   To make new back-ends, see WWW/Search,

AUTHOR
======

   `WWW::Search::SFgate' is written by Paul Lindner, <lindner@itu.int>

BUGS
====

   Things not supported: $result->raw()

COPYRIGHT
=========

   Copyright (c) 1997,98 by the United Nations Administrative Committee on
Coordination (ACC)

   All rights reserved.

class for searching Verity Search97 search engine
*************************************************

NAME
====

   WWW::Search::Search97  -  class for searching Verity Search97 search
engine

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('Search97');

DESCRIPTION
===========

   This class is a Verity Search97 specialization of WWW::Search.  It
queries and interprets searches based on Verity Search97, which is
available at `http://www.verity.com'

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

OPTIONS
=======

   This search supports sytandard WWW::Search arguments

search_url
     The Search97 URL to search.  This usually looks like
     `http://somehost/Search97cgi/s97_cgi.exe'

search_args
     The arguments used for the search engine, separate them by &.

SEE ALSO
========

   To make new back-ends, see WWW/Search,

AUTHOR
======

   `WWW::Search::Search97' is written by Paul Lindner, <lindner@itu.int>,
Nicholas Sapirie <sapirie@unicc.org>

COPYRIGHT
=========

   Copyright (c) 1998 by the United Nations Administrative Committee on
Coordination (ACC)

   All rights reserved.

class for searching any web site
********************************

NAME
====

   WWW::Search::Simple - class for searching any web site

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('Simple');

DESCRIPTION
===========

   This class is a specialization of WWW::Search for simple web based
search indices.  It extracts all links from a given page.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

   Note that this module will probably get a lot of false hits.

AUTHOR
======

   `WWW::Search::Simple' is written by Paul Lindner, <lindner@itu.int>

COPYRIGHT
=========

   Copyright (c) 1997,98 by the United Nations Administrative Committee on
Coordination (ACC)

   All rights reserved.

utilities to aid in testing WWW::Search backends
************************************************

NAME
====

   Test - utilities to aid in testing WWW::Search backends

SYNOPSIS
========

     $oTest = new WWW::Search::Test('HotBot,Yahoo,Excite');
     $oTest->test('HotBot', 'Kingpin', 'one', $sQuery, $TEST_RANGE, 1, 10);

DESCRIPTION
===========

   See file test.pl in the WWW-Search-HotBot distribution for a detailed
"real-world" example.

METHODS AND FUNCTIONS
=====================

new
---

   Create a new WWW::Search::Test object.  All arguments are strings,
names of backends that this object will be able to test.  If no arguments
are given, will be able to test all backends.

mode
----

   Set / get the test mode of this object.  If an argument is given, sets
the mode to that value.  Returns the current (or newly set) value.

   There are three test modes available.  They are:

     $MODE_INTERNAL: parse URLs out of saved pages (as a sanity check or regression test);
     $MODE_EXTERNAL: send the query to the search engine "live", parse the results, and compare them to the previously saved results;
     and
     $MODE_UPDATE: send the query to the search engine "live", parse the results, and save them for future testing.

relevant_test
-------------

   Given the name of a backend, returns true if this Test object is able
to test that backend.

eval_test
---------

   Given the name of a backend, grabs the $TEST_CASES variable from that
backend and evaluates it.

test
----

   Run test(s) for a backend.  Arguments are, in order: name of a backend
to test (string, required); name of backend maintainer (string, if undef
$backend::MAINTAINER will be used); filename for results
storage/comparison (string, required); query to be sent to backend
(string, required); test method (required, one of the following).

   Several test methods are possible:

     $TEST_EXACTLY: list of URLs must match exactly (line for line, in order);
     $TEST_BY_COUNTING: test passes if number of resulting URLs is equal;
     $TEST_GREATER_THAN: test passes if we get more than N result URLs;
     and
     $TEST_RANGE: like $TEST_GREATER_THAN but constrained on both ends.

no_test
-------

   Prints a message stating that this backend does not have a test suite.
Takes two arguments, the backend name and the name of the maintainer.

not_working
-----------

   Prints a message stating that this backend is known to be broken.
Takes two arguments, the backend name and the name of the maintainer.

not_working_with_tests
----------------------

   Prints a message stating that this backend is known to be broken even
though it has a test suite.  Takes two arguments, the backend name and the
name of the maintainer.

not_working_and_abandoned
-------------------------

   Prints a message stating that this backend is known to be broken and is
not being actively maintained.  Takes two arguments, the backend name and
the name of the maintainer.

wc_l (private, not a method)
----------------------------

   Given a filename, count the number of lines of text contained within
the file.  (I.e. simulate running UNIX command `wc -l' on a file)

diff (private, not a method)
----------------------------

   Given two files, returns TRUE if contents are line-by-line different,
or FALSE if contents are line-by-line same.  (I.e. like the UNIX command
diff, but just reports true or false)

class for Translating languages
*******************************

NAME
====

   WWW::Search::Translator - class for Translating languages

SYNOPSIS
========

     use WWW::Search;
     %opts = (
     lp => param(en_de),
     );
      $query = "a whole bunch of english text to be translated to german";
      my $search = new WWW::Search('Translator');
      $search->native_query(WWW::Search::escape_query($query),\%opts);
     while (my $result = $search->next_result())
       {
       $p = $result->raw;
       print "$p";
       }

DESCRIPTION
===========

   This is a simple no thrills class enabling users to translate text
through AV Translations `http://babel.altavista.com'.  This translating
via this method seems much faster than thru browser interface. Makes a
neat addition to any web page.  Translated text is returned thru
$result->raw, there is no url's or title $results like typical WWW::Search
results, just a stream of text that was translated from the query text
entered.

   SEE TRANSLATION OPTIONS and TIPS.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

TRANSLATION OPTIONS
===================

   Pass either of the below listed value options along with the query.
There is only one $result returnd by this backend: raw.  Thus, translated
text will be returnd via $result->raw

   <option value="en_fr" >English to French</option> <option value="en_de"
>English to German</option> <option value="en_it" >English to
Italian</option> <option value="en_pt" >English to Portuguese</option>
<option value="en_es" >English to Spanish</option> <option value="fr_en"
>French to English</option> <option value="de_en" >German to
English</option> <option value="it_en" >Italian to English</option>
<option value="pt_en" >Portuguese to English</option> <option
value="es_en" >Spanish to English</option> <option value="de_fr" >German
to French</option> <option value="fr_de" >French to German</option>
<option value="ru_en" >Russian to English</option>

TIPS
====

   I would use textarea for both user input and printing $result->url
into. This way users can scroll the returned text and have large area to
type/paste text for input.

CHANGES
=======

   VERSION 1.02

   Got time to go back and look at what was needed to parse multi lines of
the text area. Everything looks OK now and this backend will parse single
and multi lines of translated text.

AUTHOR
======

   `WWW::Search::Translator' is written and maintained by Jim Smyser -
<jsmyser@bigfoot.com>.

COPYRIGHT
=========

   WWW::Search Copyright (c) 1996-1998 University of Southern California.
All rights reserved.

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

class for searching Verity
**************************

NAME
====

   WWW::Search::Verity - class for searching Verity

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('Verity');

DESCRIPTION
===========

   Not documented.

class for searching voila.fr
****************************

NAME
====

   WWW::Search::VoilaFr - class for searching voila.fr

SYNOPSIS
========

     require WWW::Search;
     $search = new WWW::Search('VoilaFr');

DESCRIPTION
===========

   This class is a specialization of WWW::Search for voila.fr.  A french
search engine.  All searchs are based on and ONLY on gui_query function.

   This class exports no public interface; all interaction should be done
through WWW::Search objects.

USAGE EXAMPLE
=============

     use WWW::Search;

     my $oSearch = new WWW::Search('VoilaFr');
     $oSearch->maximum_to_retrieve(100);

     #$oSearch ->{_debug}=1;

     my $sQuery = WWW::Search::escape_query("bretagne");
     $oSearch->gui_query($sQuery);

     while (my $oResult = $oSearch->next_result())
     {
           print $oResult->url,"\t",$oResult->title,"\n";
     }

AUTHOR
======

   `WWW::Search::VoilaFr' is written by Mikou, mikou@spip.viewline.net

class for searching WebCrawler
******************************

NAME
====

   WWW::Search::WebCrawler - class for searching WebCrawler

SYNOPSIS
========

     use WWW::Search;
     my $oSearch = new WWW::Search('WebCrawler');
     my $sQuery = WWW::Search::escape_query("+sushi restaurant +Columbus Ohio");
     $oSearch->native_query($sQuery);
     while (my $oResult = $oSearch->next_result())
       print $oResult->url, "\n";

DESCRIPTION
===========

   This class is a WebCrawler specialization of WWW::Search.  It handles
making and interpreting WebCrawler searches `http://www.WebCrawler.com'.

   This class exports no public interface; all interaction should be done
through WWW/Search, objects.

SEE ALSO
========

   To make new back-ends, see WWW/Search.

HOW DOES IT WORK?
=================

   `native_setup_search' is called (from `WWW::Search::setup_search')
before we do anything.  It initializes our private variables (which all
begin with underscore) and sets up a URL to the first results page in
`{_next_url}'.

   `native_retrieve_some' is called (from `WWW::Search::retrieve_some')
whenever more hits are needed.  It calls `WWW::Search::http_request' to
fetch the page specified by `{_next_url}'.  It then parses this page,
appending any search hits it finds to `{cache}'.  If it finds a "next"
button in the text, it sets `{_next_url}' to point to the page for the next
set of results, otherwise it sets it to undef to indicate we"re done.

BUGS
====

   Please tell the author if you find any!

TESTING
=======

   This module adheres to the `WWW::Search' test suite mechanism.  See
$TEST_CASES below.

AUTHOR
======

   As of 1998-03-16, `WWW::Search::WebCrawler' is maintained by Martin
Thurn (MartinThurn@iname.com).

   `WWW::Search::WebCrawler' was originally written by Martin Thurn based
on `WWW::Search::HotBot'.

LEGALESE
========

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

VERSION HISTORY
===============

   If it's not listed here, then it wasn't a meaningful or released
version.

2.02, 1999-10-05
----------------

   now uses hash_to_cgi_string()

2.01, 1999-07-13
----------------

1.13, 1999-03-29
----------------

   Remove extraneous HTML from description (thanks to Jim Smyser
jsmyser@bigfoot.com)

1.11, 1998-10-09
----------------

   Now uses split_lines function

1.9
---

   1998-08-20: New format of www.webcrawler.com output.

1.7
---

   \n changed to \012 for MacPerl compatibility

1.5
---

   1998-05-29: New format of www.webcrawler.com output.

1.3
---

   First publicly-released version.

class for searching employment classifieds on Yahoo!
****************************************************

NAME
====

   WWW::Search::Yahoo::Classifieds::Employment - class for searching
employment classifieds on Yahoo!

SYNOPSIS
========

     use WWW::Search;
     my $oSearch = new WWW::Search('Yahoo::Classifieds::Employment');
     my $sQuery = WWW::Search::escape_query("unix c++ java");
     $oSearch->native_query($sQuery,
     			{'g' => 14,
     			 'cr' => 'California'});
     while (my $res = $oSearch->next_result()) {
         my $true_url = $oSearch->getMoreInfo($res->url);
         print $res->company . "\t" . $res->title . "\t" . $res->change_date
     	 . "\t" . $res->location . "\t" . $true_url . "\n";
     }

DESCRIPTION
===========

   This class is a YC specialization of WWW::Search.  It handles making
and interpreting YC searches at `http://careers.yahoo.com'

   The returned WWW::SearchResult objects contain url, title, *company*,
location and change_date fields.

   The returned url is the one found in the Yahoo! own database. However,
it quite often appears in other databases where this url was originally
taken from.  To retrieve this "true" url use the function *getMoreInfo* as
written in the above example.

OPTIONS
=======

   The following search options can be activated by sending a hash as the
second argument to native_query().

Format / Treatment of Query Terms
---------------------------------

   The default is to match ALL keywords in your query.  To match ANY
keywords use

{'za' => 'or'}
Restrict by Date
----------------

   The default is to return all ads in the Yahoo ! job database.  To
change it use

{'g' => $number} - displays jobs posted in last $number days
Restrict by Company Name
------------------------

{'cpo' => $pattern}
     Display jobs where company name matches $pattern.

Restrict by Job Title
---------------------

{'cpj' => $pattern}
     Display jobs where job title matches $pattern.

Restrict by Job Category
------------------------

   No preference by default. To select jobs from a specific job category
use the following option:

{'ce_f' => $job_category}
   Category can be one of the following:

   * "Administrative"

   * "Consulting"

   * "Creative"

   * "Education"

   * "Engineer"

   * "Finance"

   * "General Management"

   * "Health Care"

   * "Human Resources"

   * "Internships"

   * "Information Systems"

   * "Legal"

   * "Marketing"

   * "Operations"

   * "Sales"

   * "Scientific"

   * "Service"

   * "Training"

   * "Work at Home"

   * "Other / Not Specified"

Restrict by Industry
--------------------

   No restriction by default. The following option is used to select jobs
from a specific industry:

{'ce_i' => $desired_industry}
   Possible industries include:

   * "Advertising and Public Relations"

   * "Aerospace and Defense"

   * "Agriculture"

   * "Computer Hardware"

   * "Computer Software"

   * "Construction"

   * "Consumer Electronics"

   * "Consumer Products (Apperal, Household Products)"

   * "Education"

   * "Energy and Utilities"

   * "Entertainment and Sports (Media and Sports)"

   * "Financial Services (Brokerage, Real Estate, Banking)"

   * "Health Care (Pharmaceuticals, Biotech, Devices)"

   * "Heavy Manufacturing (Steel, Autos, Industrial) "

   * "Hospitality (Hotels, Casinos, Food Service, Travel) "

   * "Internet and New Media "

   * "Journalism and Publishing "

   * "Law"

   * "Light Manufacturing (Furniture, Office)"

   * "Non-Profit and Government "

   * "Professional Services (Consulting, Accounting) "

   * "Raw Materials "

   * "Retail and Wholesale (Food/Drug Stores, Retailers) "

   * "Telecommunications "

   * "Transportation (Airlines, Delivery, Trucking) "

   * "Other / Not Specified"

Restrict by Location
--------------------

   No preference by default. The following option restrict your search to
a desired location:

{'cr' => $desired_location}
   Location can be one of the following:

   * "Alabama"                   Alabama

   * "Alaska"                    Alaska

   * "Arizona"                   Arizona

   * "Phoenix"                   AZ - Phoenix

   * "Arkansas"                  Arkansas

   * "California"                California

   * "Los Angeles"               CA - Los Angeles

   * "Sacramento"                CA - Sacramento

   * "San Diego"                 CA - San Diego

   * "San Francisco Bay Area"    CA - San Francisco

   * "Colorado"                  Colorado

   * "Denver"                    CO - Denver

   * "Connecticut"               Connecticut

   * "Hartford"                  CT - Hartford

   * "Delaware"                  Delaware

   * "Florida"                   Florida

   * "Miami"                     FL - Miami

   * "Orlando"                   FL - Orlando

   * "Tampa Bay"                 FL - Tampa Bay

   * "West Palm Beach"           FL - West Palm Beach

   * "Georgia"                   Georgia

   * "Atlanta"                   GA - Atlanta

   * "Hawaii"                    Hawaii

   * "Idaho"                     Idaho

   * "Illinois"                  Illinois

   * "Chicago"                   IL - Chicago

   * "Indiana"                   Indiana

   * "Indianapolis"              IN - Indianapolis

   * "Iowa"                      Iowa

   * "Kansas"                    Kansas

   * "Kentucky"                  Kentucky

   * "Louisville"                KY - Louisville

   * "Louisiana"                 Louisiana

   * "New Orleans"               LA - New Orleans

   * "Maine"                     Maine

   * "Maryland"                  Maryland

   * "Baltimore"                 MD - Baltimore

   * "Massachusetts"             Massachusetts

   * "Boston"                    MA - Boston

   * "Michigan"                  Michigan

   * "Detroit"                   MI - Detroit

   * "Grand Rapids"              MI - Grand Rapids

   * "Minnesota"                 Minnesota

   * "Twin Cities"               MN - Minneapolis

   * "Mississippi"               Mississippi

   * "Missouri"                  Missouri

   * "Kansas City"               MO - Kansas City

   * "Saint Louis"               MO - St. Louis

   * "Montana"                   Montana

   * "Nebraska"                  Nebraska

   * "Nevada"                    Nevada

   * "Las Vegas"                 NV - Las Vegas

   * "New Hampshire"             New Hampshire

   * "New Jersey"                New Jersey

   * "New Mexico"                New Mexico

   * "Albuquerque"               NM - Albuquerque

   * "New York"                  New York

   * "New York City"             NY - New York City

   * "Buffalo"                   NY - Buffalo

   * "North Carolina"            North Carolina

   * "Charlotte"                 NC - Charlotte

   * "Greensboro"                NC - Greensboro

   * "Raleigh/Durham"            NC - Raleigh/Durham

   * "North Dakota"              North Dakota

   * "Ohio"                      Ohio

   * "Cincinnati"                OH - Cincinnati

   * "Cleveland"                 OH - Cleveland

   * "Columbus"                  OH - Columbus

   * "Oklahoma"                  Oklahoma

   * "Oklahoma City"             OK - Oklahoma City

   * "Oregon"                    Oregon

   * "Portland"                  OR - Portland

   * "Pennsylvania"              Pennsylvania

   * "Harrisburg"                PA - Harrisburg

   * "Philadelphia"              PA - Philadelphia

   * "Pittsburgh"                PA - Pittsburgh

   * "Wilkes Barre"              PA - Wilkes Barre

   * "Rhode Island"              Rhode Island

   * "Providence"                RI - Providence

   * "South Carolina"            South Carolina

   * "Greenville"                SC - Greenville

   * "South Dakota"              South Dakota

   * "Tennessee"                 Tennessee

   * "Memphis"                   TN - Memphis

   * "Nashville"                 TN - Nashville

   * "Texas"                     Texas

   * "Austin"                    TX - Austin

   * "Dallas/Fort Worth"         TX - Dallas/Fort Worth

   * "Houston"                   TX - Houston

   * "San Antonio"               TX - San Antonio

   * "Utah"                      Utah

   * "Salt Lake City"            UT - Salt Lake City

   * "Vermont"                   Vermont

   * "Virginia"                  Virginia

   * "Norfolk"                   VA - Norfolk

   * "Washington"                Washington

   * "Seattle"                   WA - Seattle

   * "Washington DC"             Washington D.C.

   * "West Virginia"             West Virginia

   * "Wisconsin"                 Wisconsin

   * "Milwaukee"                 WI - Milwaukee

   * "Wyoming"                   Wyoming

AUTHOR
======

   `WWW::Search::YC' is originally written by Alexander Tkatchev
(Alexander.Tkatchev@cern.ch).

VERSION HISTORY
===============

   1.02 - patches from Rick Myers (rik@sumthin.nu) that fixes important
changes in Yahoo! Classifieds search engine. Plus some fixes of my own...

   1.01 - original release

LEGALESE
========

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

backend for searching Yahoo News
********************************

NAME
====

   WWW::Search::YahooNews - backend for searching Yahoo News

SYNOPSIS
========

   use WWW::Search; $query = "Bob Hope"; $search = new
WWW::Search('YahooNews');
$search->native_query(WWW::Search::escape_query($query));
$search->maximum_to_retrieve(100); while (my $result =
$search->next_result()) {

   $url = $result->url; $title = $result->title; $desc =
$result->description;

   print "<a href=$url>$title</a><br>$desc<p>\n"; }

DESCRIPTION
===========

   This class is a Yahoo specialization of WWW::Search. It handles making
and interpreting Yahoo News Searches. Yahoo allows searching a wide
variety of news sources like SEC and PRWire to name a few.
`http://www.search.news.yahoo.com'.

HOW DOES IT WORK?
=================

   `native_setup_search' is called (from `WWW::Search::setup_search')
before we do anything.  It initializes our private variables (which all
begin with underscore) and sets up a URL to the first results page in
`{_next_url}'.

   `native_retrieve_some' is called (from `WWW::Search::retrieve_some')
whenever more hits are needed.  It calls `WWW::Search::http_request' to
fetch the page specified by `{_next_url}'.  It then parses this page,
appending any search hits it finds to `{cache}'.  If it finds a "next"
button in the text, it sets `{_next_url}' to point to the page for the next
set of results, otherwise it sets it to undef to indicate we"re done.

AUTHOR
======

   This Backend is will now be maintained and supported by Jim Smyser.
Flames to: <jsmyser@bigfoot.com>

LEGALESE
========

   THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

CHANGES
=======

   1.0 First release.

class for results returned from WWW::Search
*******************************************

NAME
====

   WWW::SearchResult - class for results returned from WWW::Search

SYNOPSIS
========

     require WWW::Search;
     require WWW::SearchResult;
     $search = new WWW::Search;
     $search->native_query(WWW::Search::escape_query($query));
     # get first result
     $result = $search->next_result();

DESCRIPTION
===========

   A framework for returning the results of `WWW::Search'.

SEE ALSO
========

   See WWW/Search,

REQUIRED RESULTS
================

   The particular fields returned in a result are backend- (search
engine-) dependent.  However, all search engines are required to return a
url and title.  (This list may grow in the future.)

METHODS AND FUNCTIONS
=====================

new
---

   To create a new WWW::SearchResult, call

     $result = new WWW::SearchResult();

url
---

   Returns the primary URL.  Note that there may be a list of urls, see
also methods urls and add_url.  Nothing special is guaranteed about the
primary URL other than that it is the first one returned by the back end.

   Every result is required to have at least one URL.

urls
----

   Return a reference to an array of urls.  There is also a primary URL
(url).  See also add_url.

add_url
-------

   Add a URL to the list.

related_urls, add_related_url, related_titles, add_related_title
----------------------------------------------------------------

   Analgous to urls, these functions provide lists of related URLs and
their titles.  These point to things the search engine thinks you might
want.

title, description, score, change_date, index_date, size, raw
-------------------------------------------------------------

   Set or get attributes of the result.

   None of these attributes is guaranteed to be provided by a given
backend.  If an attribute is not provided its method will return undef.

   Typical contents of these attributes:

title
     The title of the hit result (typically that provided by the 'TITLE'
     HTML tag).

description
     A brief description of the result, as provided (or not) by the search
     engine.  Often the first few sentences of the document.

source
     Source is either the base url for this result (as listed on the search
     engine's results page) or another copy of the full url path of the
     result.  It might also indicate the source site address where the
     resource was found, for example, 'http://www.cnn.com' if the search
     result page said "found at CNN.com".

     This value is backend-specific; in fact very few backends set this
     value.

score
     A backend specific, numeric score of the search result.  The exact
     range of scores is search-engine specific.  Usually larger scores are
     better, but this is no longer required.  See normalized_score for a
     backend independent score.

normalized_score
     SORRY, THIS IS NOT IMPLEMENTED.

     This is intended to be a backend-independent score of the search
     result.  The range of this score is between 0 and 1000.  Higher values
     indicate better quality results.

change_date
     When the result was last changed.

index_date
     When the search engine indexed the result.

size
     The approximate size of the result, in bytes.  This is only an
     approximation because search backends often report the size as
     "18.4K"; the best we can do with that number is return it as the value
     of 18.4 * 1024.

raw
     The raw HTML for the entire result.  Raw should be exactly the raw
     HTML for one entry.  It should not include list or table setup
     commands (like ul or table tags), but it may include list item or
     table data commands (like li, tr, or td).  Whether raw contains a list
     entry, table row, br-separated lines, or plain text is search-engine
     dependent.  In fact, many backends do not even return it at all.

company, location, source
-------------------------

   More attributes of the result.

functions for generating a site map for a given site URL.
*********************************************************

NAME
====

   WWW::Sitemap - functions for generating a site map for a given site URL.

SYNOPSIS
========

     use WWW::Sitemap;
     use LWP::UserAgent;

     my $ua = new LWP::UserAgent;
     my $sitemap = new WWW::Sitemap(
         EMAIL       => 'your@email.address',
         USERAGENT   => $ua,
         ROOT        => 'http://www.my.com/'
     );

     $sitemap->url_callback(
         sub {
             my ( $url, $depth, $title, $summary ) = @_;
             print STDERR "URL: $url\n";
             print STDERR "DEPTH: $depth\n";
             print STDERR "TITLE: $title\n";
             print STDERR "SUMMARY: $summary\n";
             print STDERR "\n";
         }
     );
     $sitemap->generate();
     $sitemap->option( 'VERBOSE' => 1 );
     my $len = $sitemap->option( 'SUMMARY_LENGTH' );

     my $root = $sitemap->root();
     for my $url ( $sitemap->urls() )
     {
         if ( $sitemap->is_internal_url( $url ) )
         {
             # do something ...
         }
         my @links = $sitemap->links( $url );
         my $title = $sitemap->title( $url );
         my $summary = $sitemap->summary( $url );
         my $depth = $sitemap->depth( $url );
     }
     $sitemap->traverse(
         sub {
             my ( $sitemap, $url, $depth, $flag ) = @_;
             if ( $flag == 0 )
             {
                 # do something at the start of a list of sub-pages ...
             }
             elsif( $flag == 1 )
             {
                 # do something for each page ...
             }
             elsif( $flag == 2 )
             {
                 # do something at the end of a list of sub-pages ...
             }
         }
     )

DESCRIPTION
===========

   The `WWW::Sitemap' module creates a sitemap for a site, by traversing
the site using the WWW::Robot module. The sitemap object has methods to
access a list of all the urls in the site, and a list of all the links for
each of these urls. It is also possible to access the title of each url,
and a summary generated from each url. The depth of each url can also be
accessed; the depth is the minimum number of links from the root URL to
that page.

CONSTRUCTOR
===========

WWW::Sitemap->new [ $option => $value ] ...
-------------------------------------------

   Possible option are:

USERAGENT
     User agent used to do the robot traversal. Defaults to LWP::UserAgent.

VERBOSE
     Verbose flag, for printing out useful messages during traversal
     [0|1]. Defaults to 0.

SUMMARY_LENGTH
     Maximum length of (automatically generated) summary.

EMAIL
     E-Mail address robot uses to identify itself with. This option is
     required.

DEPTH
     Maximum depth of traversal.

ROOT
     Root URL of the site for which the sitemap is being created. This
     option is required.

          my $sitemap = new WWW::Sitemap(
              EMAIL       => 'your@email.address',
              USERAGENT   => $ua,
              ROOT        => 'http://www.my.com/'
          );

METHODS
=======

generate( )
-----------

   Method for generating the sitemap, based on the constructor options.

     $sitemap->generate();

url_callback( sub { ... } )
---------------------------

   This method allows you to define a callback that will be invoked on
every URL that is traversed while generating the sitemap. This is
basically to allow bespoke verbose reporting. The callback should be of
the form:

     sub {
         my ( $url, $depth, $title, $summary ) = @_;

     # do something ...

     }

option( $option [ => $value ] )
-------------------------------

   Iterface to get / set options after object construction.

     $sitemap->option( 'VERBOSE' => 1 );
     my $len = $sitemap->option( 'SUMMARY_LENGTH' );

root()
------

   returns the root URL for the site.

     my $root = $sitemap->root();

urls()
------

   Returns a list of all the URLs on the sitemap.

     for my $url ( $sitemap->urls() )
     {
         # do something ...
     }

is_internal_url( $url )
-----------------------

   Returns 1 if $url is an internal URL (i.e. if `$url =~ /^$root/'.

     if ( $sitemap->is_internal_url( $url ) )
     {
         # do something ...
     }

links( $url )
-------------

   Returns a list of all the links from a given URL in the site map.

     my @links = $sitemap->links( $url );

title( $url )
-------------

   Returns the title of the URL.

     my $title = $sitemap->title( $url );

summary( $url )
---------------

   Returns a summary of the URL - either from the `<META
NAME=DESCRIPTION'> tag or generated automatically using HTML::Summary.

     my $summary = $sitemap->summary( $url );

     =head2 depth( $url )

   Returns the minimum number of links to traverse from the root URL of
the site to this URL.

     my $depth = $sitemap->depth( $url );

traverse( \&callback )
----------------------

   The travese method traverses the sitemap, starting at the root node, and
visiting each URL in the order that they would be displayed in a sequential
sitemap of the site. The callback is called in a number of places in the
traversal, indicated by the $flag argument to the callback:

$flag = 0
     Before each set of daughter URLs of a given URL.

$flag = 1
     For each URL.

$flag = 2
     After each set of daughter URLs of a given URL.

   See the sitemapper.pl script distributed with this module for an
example of the use of the traverse method.

     $sitemap->traverse(
         sub {
             my ( $sitemap, $url, $depth, $flag ) = @_;
             if ( $flag == 0 )
             {
                 # do something at the start of a list of sub-pages ...
             }
             elsif( $flag == 1 )
             {
                 # do something for each page ...
             }
             elsif( $flag == 2 )
             {
                 # do something at the end of a list of sub-pages ...
             }
         }
     );

SEE ALSO
========

     LWP::UserAgent
     HTML::Summary
     WWW::Robot

AUTHOR
======

   Ave Wrigley <Ave.Wrigley@itn.co.uk>

COPYRIGHT
=========

   Copyright (c) 1997 Canon Research Centre Europe (CRE). All rights
reserved.  This script and any associated documentation or files cannot be
distributed outside of CRE without express prior permission from CRE.

Watchdog base class
*******************

NAME
====

   Watchdog::Base - Watchdog base class

SYNOPSIS
========

     use Watchdog::Base;

DESCRIPTION
===========

   *Watchdog::Base* is the Watchdog base class.

CLASS METHODS
=============

new($name,$host,$port)
----------------------

   Returns a new *Watchdog::Base* object.  $name is a string which will
identify the service to a human.  $host is the name of the host providing
the service (default is 'localhost').  $port is the port on which the
service listens.

OBJECT METHODS
==============

id()
----

   Return a string describing the name of a service and the host (and
optionally the port) on which it runs.

AUTHOR
======

   Paul Sharpe <paul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1998 Paul Sharpe. England.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Test status of HTTP service
***************************

NAME
====

   Watchdog::HTTP - Test status of HTTP service

SYNOPSIS
========

     use Watchdog::HTTP;
     $h = new Watchdog::HTTP($name,$host,$port);
     print $h->id, $h->is_alive ? ' is alive' : ' is dead', "\n";

DESCRIPTION
===========

   *Watchdog::HTTP* is an extension for monitoring an HTTP server.

CLASS METHODS
=============

new($name,$host,$port)
----------------------

   Returns a new *Watchdog::HTTP* object.  $name is a string which will
identify the service to a human (default is 'httpd').  $host is the
hostname which is running the service (default is 'localhost').  $port is
the port on which the service listens (default is 80).

OBJECT METHODS
==============

is_alive()
----------

   Returns true if an HTTP GET method succeeds for the URL
*http://$host:$port/* or false if it doesn't.

SEE ALSO
========

   See Watchdog/Base,

AUTHOR
======

   Paul Sharpe <paul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1998 Paul Sharpe. England.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Test status of Mysql service
****************************

NAME
====

   Watchdog::Mysql - Test status of Mysql service

SYNOPSIS
========

     use Watchdog::Mysql;
     $h = new Watchdog::Mysql($name,$host,$port,$db);
     ($alive,$error) = $h->is_alive;
     print $h->id, $alive ? ' is alive' : " is dead: $error", "\n";

DESCRIPTION
===========

   *Watchdog::Mysql* is an extension for monitoring a Mysql server.

CLASS METHODS
=============

new($name,$host,$port,$db)
--------------------------

   Returns a new *Watchdog::Mysql* object.  $name is a string which will
identify the service to a human (default is 'mysql').  $host is the
hostname which is running the service (default is 'localhost').  $port is
the port on which the service listens (default is 3306).  $db is a
database with no access control (default is 'test').

OBJECT METHODS
==============

id()
----

   Return a string describing the Mysql service.

is_alive()
----------

   Returns (1,undef) if the mysql server can be 'pinged' or (0,$error)
where $error is a DBI error string if it can't.

SEE ALSO
========

   See Watchdog/Base,

   `DBI' in this node

AUTHOR
======

   Paul Sharpe <paul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1998 Paul Sharpe. England.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Check for process in process table
**********************************

NAME
====

   Watchdog::Process - Check for process in process table

SYNOPSIS
========

     use Watchdog::Process;
     $s = new Watchdog::Process($name,$pstring);
     print $s->id, $s->is_alive ? ' is alive' : ' is dead', "\n";

DESCRIPTION
===========

   *Watchdog::Process* is an extension for monitoring processes running on
a Unix host.  The class provides a trivial method for determining whether
a service is alive.  *This class has only been successfully tested on
Solaris 2.6*.

CLASS METHODS
=============

new($name,$pstring)
-------------------

   Returns a new *Watchdog::Process* object.  $name is a string which will
identify the service to a human.  *$pstring* is a string which can be used
to identify a process in the process table.

is_alive()
----------

   Returns true if the service is alive, else false.

BUGS
====

   This class is *unreliable* on Linux as
*Proc::ProcessTable::Process::cmndline()* sometimes returns undef.

SEE ALSO
========

   See Proc/ProcessTable,

AUTHOR
======

   Paul Sharpe <paul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1998 Paul Sharpe. England.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Watchdog utility functions
**************************

NAME
====

   Watchdog::Util - Watchdog utility functions

SYNOPSIS
========

     use Watchdog::Util;

DESCRIPTION
===========

AUTHOR
======

   Paul Sharpe ltpaul@miraclefish.com>

COPYRIGHT
=========

   Copyright (c) 1998 Paul Sharpe. England.  All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

an API to the Perl weak references
**********************************

NAME
====

   WeakRef - an API to the Perl weak references

SYNOPSIS
========

     use WeakRef;

     for($i=0; $i<100000; $i++) {
     	my $x = {};
     	my $y = {};
     	$x->{Y} = $y;
     	$y->{X} = $y;
     	weaken($x->{Y});
     } # no memory leak

     if(isweak($ref)) {
     }

DESCRIPTION
===========

   A patch to Perl 5.005_55 by the author implements a core API for weak
references. This module is a Perl-level interface to that API, allowing
weak references to be created in Perl.

   A weak reference is just like an ordinary Perl reference except that it
isn't included in the reference count of the thing referred to.  This
means that once all references to a particular piece of data are weak, the
piece of data is freed and all the weak references are set to undef. This
is particularly useful for implementing circular data structures without
memory leaks or caches of objects.

   The command

     use WeakRef;

   exports two symbols to the user's namespace by default: weaken and
isweak. weaken takes a single argument, the reference to be weakened, and
returns the same value.  The idiom

     weaken($this->{Thing}->{Parent} = $this);

   is useful.

   The isweak command takes a single parameter and returns true if the
parameter is a weak reference, undef otherwise.

BUGS
====

   None known.

AUTHOR
======

   Tuomas J. Lukka		lukka@iki.fi

   Copyright (c) 1999 Tuomas J. Lukka. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as perl itself.

BLATANT PLUG
============

   This module and the patch to the core Perl were written in connection
with the APress book `Tuomas J. Lukka's Definitive Guide to Object-Oriented
Programming in Perl', to avoid explaining why certain things would have to
be done in cumbersome ways.

NAME
====

   Weather::PIL -

DESCRIPTION
===========

EXAMPLE
=======

AUTHOR
======

   Robert Rothenberg <wlkngowl@unix.asb.com>

routines for parsing WMO-style weather products
***********************************************

NAME
====

   Weather::Product - routines for parsing WMO-style weather products

DESCRIPTION
===========

   Weather::Product is a base module for parsing World Meterological
Assication (WMO) standard weather products (as in forecasts, observations,
etc.) as might come from various weather services.

   More "sophisiticated" parsing of U.S. National Weather Service (NWS)
weather products (by AWIPS Product Identifiers or zones) is done in the
`Weather::Product::NWS' module (which inherits methods from this module).

EXAMPLE
=======

     use Weather::Product;

     $forecast = new Weather::Product 'data/text/FPUS61/KOKX.TXT';

     print $forecast->text{FPUS61);

METHODS
=======

new
---

   A new weather product may be constructed and initialized the usual
fashion:

     $obj = new Weather::Product

   or,

     $obj = new Weather::Product LIST

   where LIST contains file names or URLs of weather products to
*`"import"' in this node*.

initialize
----------

   An internal method called by *`"new"' in this node*.

import
------

     $obj->import LIST

   Imports  and parses files or URLs containing weather products. This is
used by the *`"new"' in this node* method if files or URLs are specified.

   import can be used to update the object with a newer weather product or
to merge additional parts, addendums, etc. (not implemented in this
version).

   Be aware that the *`"parse"' in this node* method called by import will
not allow incompatible (read: "different") weather products to be
imported. You should create a new object for each product.

   In other words, "FPUS51" and "FPUS61" are different products, requiring
different instances of `Weather::Product'.

parse
-----

     $obj->parse STRING

   Parses the weather product (contained in STRING) into a WMO header (see
`Weather::WMO') and associated text. Product names derived from the WMO
header are added to the *`"products"' in this node* list which link to the
associated text.

   Assumes STRING is a valid weather product (containing a valid WMO header
line). This is used by the *`"import"' in this node* method (and
indirectly by *`"new"' in this node*).

add
---

     $obj->add PRODUCT, LINK

   An internal method for adding pointers to products, used by *`"parse"'
in this node*.  For more information on the gory details, see *`"pointer"'
in this node*.

age
---

     $obj->age(PRODUCT)

   Returns the age (in hours) of the specified PRODUCT.

   See *`"max_age"' in this node* to set a maximum allowable age.

purge
-----

     $obj->purge()

   Purges "orphaned" weather products. In other words, garbage collection.
(See *`"pointer"' in this node* for information how data is stored.)

   Weather products older than *`"max_age"' in this node* are also removed.

   This will only occur when another weather product (presumably an
updated one) is imported into the object (using *`"import"' in this node*
and *`"parse"' in this node*).

     $obj->purge LIST

   Purges the weather products specified in LIST, if they exist. Orphaned
products will also be purged.

pointer
-------

     $obj->pointer PRODUCT, FIELD

   This is an internal method for returning a "pointer" to a PRODUCT (or
to a specified `FIELD' in that PRODUCT).

   Basically, all parsed products are stored in a hash called data. Another
hash called products contains pointers to the appropriate entry in data.

   While this structure may seem pointless (pun intended) for this module,
it is useful for the `Weather::Product::NWS module', where some of the
products (AWIPS IDs and individual zones) are linked to substrings of data.

products
--------

     LIST = $obj->products;

   Returns a list of available products (by name).

   The definition of a "product" is a bit loose in this module. The WMO
product identifier (ie, "FPUS51" or "FPCN55") is added.

   The reporting station (ie, "KNYC" or "CWNT") is also listed as a product
in cases where different stations may issue products with the same
identifier (such reports should really be handled with the
`Weather::Product::NWS' module and not this one).

time
----

     TIME = $obj->time PRODUCT

   For example,

     $time = localtime($forecast->time('FPUS81'));

   returns the timestamp of the parsed weather product.

   Now a note about these timestamps: they are converted to Perl-friendly
time from the WMO header (using *`"int_time"' in this node*). WMO
timestamps there are in the form of `DDHHMM', where `DD' is the day of the
month, and `HHMM' is the time, in UTC (we treat it as GMT here; the
difference between the two is academic).

   Why should you care? If for some strange reason you are parsing products
from a previous month, you'll get inaccurate timestamps.  The module may
even return a null.

   A future version of this module might attempt to fetch a "base time"
from local files or URLs.

int_time
--------

     TIME = Weather::Product::int_time WMO_TIME, BASE

   Attempts to convert WMO-style timestamps (found in WMO headers and UGC
lines) to something Perl-friendly. If no `BASE' is specified, the current
time (from the Perl function time) is used.

   See *`"time"' in this node* for a note about the limitations of
WMO-style timestamps.

WMO
---

     WMO = $obj->WMO(PRODUCT)

   Returns the WMO header of the specified product (as a `Weather::WMO'
object).  For example,

     $WMO = $forecast->WMO('FPUS41');
     print "This forecast comes from station ", $WMO->station, "\n";

text
----

     $text = $obj->text(PRODUCT)

   Perhaps the most important method. This returns the actual text of the
weather product. For example,

     print $forecast->text('FPUS41'), "\n";

   If text returns a null value, there is no product by that name. (It is
possible that the product has been `purged|"purge"' in this node.)

max_age
-------

   When called without arguments, returns the maximum allowable age (in
hours) for products. The default is 0.

   When called with an argument, sets the maximum allowable age. A useful
setting might be for 30 hours.

   The *`"purge"' in this node* method will remove weather products older
than the maximum allowable age.

   A potential pitfall for setting this property to too low a number is
that products will be removed as soon as they are parsed. This may or may
not be a good thing.

KNOWN BUGS
==========

   This version of the module does not (yet) handle addendums or multi-part
weather products.

   Other issues with returning the *`"time"' in this node* of a product
are explained above, are are a limitation of the WMO header format, not
this module.

SEE ALSO
========

   `Weather::WMO' and `Weather::Product::NWS'.

   Perusing documentation on the format of WMO-style weather products
online from the U.S. National Weather Service http://www.nws.noaa.gov may
also be of help.

DISCLAIMER
==========

   I am not a meteorologist nor am I associated with any weather service.
This module grew out of a hack which would fetch weather reports every
morning and send them to my pager. So I said to myself "Why not do this
the right way..." and spent a bit of time surfing around the web looking
for documentation about this stuff....

AUTHOR
======

   Robert Rothenberg <wlkngowl@unix.asb.com>

routines for parsing NWS weather products
*****************************************

NAME
====

   Weather::Product::NWS - routines for parsing NWS weather products

DESCRIPTION
===========

   Weather::Product::NWS is a module for parsing U.S. National Weather
Service (NWS) weather products. Products can be fetched from local files,
URLs, or parsed directly from pre-fetched data.

   Weather products are organized by zones and counties (as well as WMO and
AWIPS Product IDs) along with relevant timestamps and expiration dates.

EXAMPLE
=======

KNOWN BUGS
==========

   This version of the module does not (yet) handle addendums or multi-part
weather products.

   Other issues with returning the time are are a limitation of the WMO
header format, not this module.

SEE ALSO
========

   `Weather::WMO', `Weather::PIL', `Weather::UGC' and `Weather::Product'.

   Perusing documentation on the format of WMO-style weather products
online from the U.S. National Weather Service http://www.nws.noaa.gov may
also be of help.

DISCLAIMER
==========

   I am not a meteorologist nor am I associated with any weather service.
This module grew out of a hack which would fetch weather reports every
morning and send them to my pager. So I said to myself "Why not do this
the right way..." and spent a bit of time surfing around the web looking
for documentation about this stuff....

AUTHOR
======

   Robert Rothenberg <wlkngowl@unix.asb.com>

routines for parsing Universal Generic Code (UGC) lines
*******************************************************

NAME
====

   Weather::UGC - routines for parsing Universal Generic Code (UGC) lines

DESCRIPTION
===========

   Weather::UGC is a module for parsing Universal Generic Code (UGC) lines
in National Weather Service (NWS) products.

   For more information, see http://iwin.nws.noaa.gov/emwin/winugc.htm

EXAMPLE
=======

     require Weather::UGC;

     $line = "NYZ078>081-NJZ002>004-011-141200-";

     unless (Weather::UGC::valid($line)) {
         die "\'$line\' is not a valid UGC line.\n";
     }

     $ugc = new Weather::UGC($line);

     print $ugc->UGC, " refers to the following zones:\n";
     foreach ($ugc->zones) {
         print $_, (
          (Weather::UGC::valid ZONE, $_) ? "\n" : " (invalid zone name\?)\n"
         );
     }

AUTHOR
======

   Robert Rothenberg <wlkngowl@unix.asb.com>

routines for parsing WMO abbreviated header lines
*************************************************

NAME
====

   Weather::WMO - routines for parsing WMO abbreviated header lines

DESCRIPTION
===========

   Weather::WMO is a module for parsing WMO abbreviated header lines in
World Meterological Organization-formatted weather products.

EXAMPLE
=======

     require Weather::WMO;

     $line = "FPUS61 KOKX 171530";

     unless (Weather::WMO::valid($line)) {
         die "\'$line\' is not a valid header.\n";
     }

     $WMO = new Weather::WMO($line);

     print "WMO\t", $WMO->WMO, "\n";
     print "product\t", $WMO->product, "\n";     # FPUS61
     print "station\t", $WMO->station, "\n";     # KOKX
     print "time\t", $WMO->time, "\n";           # "171530"

     # other constructors
     $WMO = new Weather::WMO qw(FPUS51 KNYC 041200 PAA);

     $WMO = new Weather::WMO;
     $WMO->WMO="FPUS51 KNYC 041200 (PAA)";

METHODS
=======

PRODUCT
-------

   An exported text constant. `PRODUCT = 'PRODUCT''.

new
---

   The object constructor:

     $obj = new Weather::WMO SCALAR

   where SCALAR is the WMO header (without any trailing spaces, newlines or
carriage returns).

   An alternative constructor may be used:

     $obj = new Weather::WMO LIST

   where LIST contains the individual parts of the WMO header (see the
`examples|"EXAMPLE"' in this node above).

valid
-----

     Weather::WMO::valid SCALAR

   Returns `true' if the header specified in SCALAR looks like a valid WMO
header line. Otherwise false.

cmp
---

   Compares two WMO objects.

     $obj1->cmp $obj2

   Returns `true' if `obj2' is the same *`"product"' in this node* as
`obj1'.

WMO
---

   When called without arguments it returns the WMO header as a string.

   When called with arguments, it assigns a value to the WMO header (if
none has already been assigned).

product
-------

   Returns the "product" portion (`T1T2A1A2ii') of the WMO header.

station
-------

   Returns the "station" portion of the WMO header.

time
----

   Returns the timestamp of the WMO header, in WMO format (`DDHHMM' where
`DD' is the day of the month and `HHMM' is the time, in UGC).

   This time can be converted to a Perl-friendly format using the
*Weather::Product::int_time* function.

addendum
--------

   Returns the "addendum" (or `BBB') portion of the WMO header.

region
------

   Returns the geographical region code of the weather product, if
applicable.  Otherwise it returns undef.

T1, T2, T1T2, TT, A1, A2, A1A2, ii, BBB
---------------------------------------

   Returns the equivalent portion of the WMO header.

KNOWN BUGS
==========

   This module only performs simple string validation and parsing of WMO
header lines.  It does not check if the product or station is actually
valid, or if the timestamp is valid.

   "Non-standard" header lines used by a specific weather service may not
be handled properly.

SEE ALSO
========

   `Weather::Product' and `Weather::Product::NWS', which make use of this
module.

   For more information about what WMO heading lines are, see
http://www.nws.noaa.gov/oso/head.shtml

DISCLAIMER
==========

   I am not a meteorologist nor am I associated with any weather service.
This module grew out of a hack which would fetch weather reports every
morning and send them to my pager. So I said to myself "Why not do this
the right way..." and spent a bit of time surfing around the web looking
for documentation about this stuff....

AUTHOR
======

   Robert Rothenberg <wlkngowl@unix.asb.com>

a Cache Digest implementation in Perl
*************************************

NAME
====

   WebCache::Digest - a Cache Digest implementation in Perl

SYNOPSIS
========

     use WebCache::Digest;

     # fetching a digest via HTTP
     $d = new WebCache::Digest;
     $d->fetch("flibbertigibbet.swedish-chef.org", 3128);

     # dump header fields out for info
     print STDERR $d->dump_header();

     # saving a digest
     $d->save("flib");

     # loading a digest
     $e = new WebCache::Digest;
     $e->load("flib");

     # creating a new digests
     $f = new WebCache::Digest;
     $f->create; # defaults to a digest with 500 URL capacity

     # registering a URL and method in the digest
     $f->register("get", "http://www.kha0s.org/">;
     if ($f->lookup("get", "http://www.kha0s.org/">) {
       print "hit!\n";
     }

     # access to raw header and digest contents
     print "header: " . unpack("H*", $f->header) . "\n";
     print "digest: " . unpack("H*", $f->digest) . "\n";

     # access to digest header block elements
     print "Current version:      " . $f->current_version . "\n";
     print "Required version:     " . $f->required_version . "\n";
     print "Capacity:             " . $f->capacity . "\n";
     print "Count:                " . $f->count . "\n";
     print "Deletion count:       " . $f->del_count . "\n";
     print "Size in bytes:        " . $f->size_in_bytes . "\n";
     print "Bits per entry:       " . $f->bits_per_entry . "\n";

DESCRIPTION
===========

   This Perl module implements version 5 of the Cache Digest specification.
For more information about Cache Digests, check out the Squid FAQ:

     http://squid.nlanr.net/Squid/FAQ/FAQ-16.html

   A copy of the specification is included with this distribution as the
file `cache-digest-v5.txt'.

   This code has been benchmarked on a 400MHz PII running Linux at 1866
lookups per second (or 112000 per minute, 560000 in five minutes), with a
cache digest of 500000 URLs.

   Cache Digests are summaries of the contents of WWW cache servers, which
are made available to other WWW caches and may also be used internally
within the server which generates them.  They allow a WWW cache server
such as Squid to determine whether or not a particular Internet resource
(designated by its URL and the HTTP method which is being used to fetch
it) was cached at the time the digest was generated.  Unlike other
mechanisms such as the Internet Cache Protocol (ICP - see RFC 2186), Cache
Digests do not generate a continuous stream of request/response pairs, and
do not add latency to each URL which is looked up.

   Since we provide routines to both lookup URLs in Cache Digests and also
register them in Cache Digests, it should be trivial to use this code to
devise innovative applications which take advantage of Cache Digests to
fool genuine WWW caches into treating them like WWW caches.  For example,
mirror servers could register all the URLs which they're aware of for the
resources they mirror, so that cache servers which peer with them will
always get a cache 'hit' on the mirror server for any reference to any of
the mirrored resources.

   We also provide methods to store Cache Digests to disk and load them
back in again, in addition to creating new Digests and fetching them from
WWW caches which support the protocol.  This can be used to take a
'snapshot' of the state of a WWW cache at any particular point in time, or
for saving state if building a Cache Digest powered server.

METHODS
=======

   We only describe public methods and method arguments here.  Anything
else should be considered private, at least for now.

new
     Constructor function, creates a new WebCache::Digest object.  As yet
     this takes no arguments.

create
     Fills in the data structures for a WebCache::Digest object, given the
     number of lots to make available for URLs via the capacity parameter.

fetch
     Tries to fetch a Cache Digest from the machine whose domain name (or
     IP address) and port number are specified (in this order) in the first
     and second parameters.  Returns 0 on failure, and 1 on success.

dump_header
     Dump the fields in the Cache Digest header out as plain text to, e.g.
     for debugging purposes.

save
     Saves the WebCache::Digest object to the filename supplied as its
     parameter.  Returns 0 on failure, 1 on success.

load
     Populates the WebCache::Digest object with contents of the filename
     supplied as its parameter.  Returns 0 on failure, 1 on success.

lookup
     Given an HTTP method and URL (in that order) as parameters, try to
     look them up in the Cache Digest.  Returns 1 if the URL is a Cache
     Digest hit, or 0 otherwise.

register
     Given an HTTP method and URL (in that order) as parameters, register
     them in the Cache Digest.

header
     The raw Cache Digest header.

digest
     The raw Cache Digest object, sans header.

current_version
     The current version number from the Digest object.

required_version
     The required version number from the Digest object.  Implementations
     should support at least this version for interoperability.

capacity
     The number of 'slots' for URLs in the Digest.

count
     The number of slots which have been filled.

del_count
     The number of deletion attempts - Squid doesn't currently delete any
     URLs (e.g. on their becoming stale) but simply discards them the next
     time the Digest is rebuilt.  Deleting one URL's information without
     affecting others is impossible with Cache Digests as currently
     conceived - where a given bit of the Digest may be used in looking up
     multiple URLs.

size_in_bytes
     The size of the Digest in bytes when stored in transfer format.

bits_per_entry
     The number of bits in the Cache Digest consumed for each entry.

hash_func_count
     The number of times the Cache Digest hash function (see the
     specification for more information on this) is called for each URL.

BUGS
====

   This is a first release, and there are probably lots of hideous bugs
waiting to catch you out - consider it pre-alpha code!

   Something else to watch out for is that the name may well change -
depending on feedback from the *comp.lang.perl.modules* Usenet conference.

   We use far too much memory - a more efficient approach to processing
the Cache Digest needs to be hacked in.

   We should be consistent and always use one form of arguments - either
hash array or fixed position arguments.  Mixing the two is confusing.
However...  most methods don't need named (hash array) arguments, except
for create.

COPYRIGHT
=========

   Copyright (c) 1999, Martin Hamilton.  All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   It was developed by the JANET Web Cache Service, which is funded by the
Joint Information Systems Committee (JISC) of the UK Higher Education
Funding Councils.

AUTHOR
======

   Martin Hamilton <martinh@gnu.org>

Internet Cache Protocol client and server
*****************************************

NAME
====

   *WebCache::ICP* - Internet Cache Protocol client and server

SYNOPSIS
========

     use WebCache::ICP;

     $i = new WebCache::ICP;
     $i->opcode("OP_QUERY");
     $i->payload("http://www.w3.org/");
     $i->send(host => $host, port => $port);
     $i->recv;
     $i->dump;
     $i->hex_dump;

     $j = new WebCache::ICP($packet);
     $j->dump;

     $k = new WebCache::ICP;
     $k->server(callback => \&not_so_stubby);

     # sample callback, just prints URLs requested
     sub not_so_stubby {
       my ($self, $fd, $sin, $request) = @_;
       $self = $self->burst($request);
       print "url: " . $self->payload . "\n";
       $self->opcode("OP_MISS_NOFETCH");
       $self->send(fd => $fd, sin => $sin);
     }

DESCRIPTION
===========

   This Perl module implements client and server side support for the
Internet Cache Protocol, as defined in RFCs 2186 and 2187.  It provides
methods for creating ICP packets, breaking the contents of ICP packets out
into a Perl object, sending and receiving ICP packets, plus a simple ICP
server which you can bolt your own callback functions onto.

   NB This is just a first release, so expect the unexpected!  Many
features either don't work properly, or don't exist yet :-)

METHODS
=======

   ICP objects can either be created anew:

     $i = new WebCache::ICP;

   Or created based on the contents of a variable, which it's assumed is a
raw ICP packet, fresh off the wire:

     $i = new WebCache::ICP($packet);

   If you don't supply a variable from which the ICP object should be
created, we try to set you up with some sensible defaults - creating a
query packet (opcode 2 or "OP_QUERY"), protocol version 2, a sequence
number of 1, and no options.

   Note that you can re-use a WebCache::ICP object over and over again, so
as to avoid incurring the overheads of object creation and destruction
with high volume client/server applications.

   The following methods may be used on ICP objects to get or (with
optional parameter) set the corresponding fields in the ICP packet:

$i->opcode
     This method fetches the ICP opcode from the object.  This is normally
     a number between 0 and 23.  With a numeric parameter, the opcode for
     the object is set to this number.  You can also supply one of the
     following strings as an alternative to the numeric parameter:

          "OP_INVALID"
          "OP_QUERY"
          "OP_HIT"
          "OP_MISS"
          "OP_ERR"
          "UNUSED5"
          "UNUSED6"
          "UNUSED7"
          "UNUSED8"
          "UNUSED9"
          "OP_SECHO"
          "OP_DECHO"
          "UNUSED12"
          "UNUSED13"
          "UNUSED14"
          "UNUSED15"
          "UNUSED16"
          "UNUSED17"
          "UNUSED18"
          "UNUSED19"
          "UNUSED20"
          "OP_MISS_NOFETCH"
          "OP_DENIED"
          "OP_HIT_OBJ"

     Each of these will be interpolated into the appropriate ICP opcode
     internally by the WebCache::ICP module.  We don't check the opcode
     number is valid, so if you wanted to, you could put opcodes greater
     than 23 in here...

$i->version
     This method lets you set or fetch the ICP protocol version number.
     Currently this is set to 2 for most/all real world applications of
     ICP, but you could put the version number of your choice in here.

$i->length
     This method lets you fetch the packet length of an ICP object when
     it's expressed as an on-the-wire packet.  This may get a bit confused
     if you manipulate the contents of an ICP object, but it's 'guaranteed'
     to be correct if you create a new ICP object based on a raw packet.

$i->sequence
     This method lets you fetch (or, with an optional parameter: set), the
     ICP sequence number.

$i->options
     This method lets you fetch or set the options field for the ICP
     object.  At the moment we simply expect you to supply a plausible
     value for this.  In future there will probably be a more
     sophisticated way to set a particular option by name.

$i->option_data
     This method lets you fetch or set the supplementary data associated
     with the options set for the ICP object.  Again we assume that you
     know what you want to put in here!

$i->peer_addr
     This method lets you fetch or set the source address associated with
     the ICP packet once sent/received down the wire.  In practice this is
     normally set to all zeroes.

$i->payload
     This method lets you fetch or set the payload proper of the ICP
     packet.

$i->assemble
     This method turns an ICP object into an on-the-wire format packet,
     which is returned as its result.  Note that it adds a 4 byte null
     filled prefix to the payload of ICP query packets.  This is normally
     used in ICP to record the IP address of the machine which is causing
     the ICP query to be sent.

$i->burst
     This method takes a raw ICP packet and turns it into an ICP object.
     It's used behind the scenes by the 'new' method when constructing an
     ICP object from an on-the-wire packet, but you can also call it
     directly.

$i->dump
     This method dumps out the contents of the various ICP header fields
     and the payload, as interpreted by the WebCache::ICP module, to
     STDOUT.  It's intended for use in debugging.

$i->hex_dump
     This method tries to create an ICP on-the-wire format packet and then
     dump it out to STDOUT, based on the WebCache::ICP object being
     operated on.

$i->send
     This method causes an ICP wire format packet to be sent.  It can be
     used in a variety of ways depending on the options which it's called
     with, viz.

     If you already have the packet you want to send, you can supply the
     'packet' parameter:

          $i->send(packet => $p);

     If not, the packet will be generated from the WebCache::ICP object
     being operated on, using the 'assemble' method.

     If you already have an active socket for talking to the server, you
     can supply its file handle and packed IP address/port using the 'fd'
     and 'sin' parameters:

          $i->send(fd => \*SOCK, sin => $s);

     If not, you'll need to supply the 'host' and 'port' parameters - the
     socket will automatically be created, and then destroyed after the
     packet is sent.

$i->recv
     This method waits for an ICP packet to arrive, and then returns the
     raw packet for further processing.  You can either pass the file
     handle of a socket which is already bound to the port:

          $i->recv(fd => \*SOCK);

     or you can supply the port number yourself:

          $i->recv(port => 3131);

     in which case the 'recv' method will take care of getting you a socket
     and destroying it later.

$i->server
     This method uses pretty much all of the other code to implement a
     simple ICP server with user defined callbacks to be executed on
     receipt of an incoming ICP packet.  Once it is called, the flow of
     execution will pass here, and the program will block waiting for
     packets to arrive...

     You can either pass the file handle of a socket which is already bound
     to the port you want to listen on:

          $i->server(fd => \*SOCK);

     or you can supply the port number yourself:

          $i->server(port => 3131);

     in which case the 'server' method will take care of getting you a
     socket and destroying it later.

     The ICP server comes with a simple built-in callback function, which
     always returns an ICP hit ("OP_HIT") response using the 'send'
     method, and logs the packet received to STDOUT using the 'dump'
     method.  This default callback will be invoked if you run the server
     without nominating an alternative.

     If you supply a reference to a function in the 'callback' parameter,
     the 'server' method will try to pass this the packet contents and
     peer info on receipt of each packet, e.g.

          $i->server(callback => \&not_so_stubby);

     The return code from the callback function isn't used in the 'server'
     method.  The callback function will be supplied with three parameters:

          1) the file descriptor which the packet was received on
          2) the packed IP address/port number from which it was received
          3) the raw on-the-wire ICP packet which was received

TODO
====

   Need to factor in an opcode for ICP referrals.

   Should have ability to get/set options by name.

   Should be possible to run ICP over TCP - cf. HTCP, though.

   Should allow for holding connection open when running over TCP.

   Should be possible to have the ICP server running in non-blocking mode,
possibly as part of a larger set of file handles using select.

BUGS
====

   This is just a first release, so expect the unexpected!

   The hex_dump method doesn't take account of the 4 byte client IP address
prefix to the payload of ICP query packets.

   We currently bind to INADDR_ANY when listening for incoming ICP packets,
but we should probably let the luser choose which interface(s) to use.

   Timeouts and corrupted packets aren't handled gracefully yet.

   There's no way with the 'recv' method to find out the peer's IP address
and port number, since we only return the raw packet contents.

   Originally used IO::Socket, but stopped because it seemed to leak
memory.

COPYRIGHT
=========

   Copyright (c) 1999, Martin Hamilton <martinh@gnu.org>.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   It was developed by the JANET Web Cache Service, with funding from the
Joint Information Systems Committee (JISC) of the UK Higher Education
Funding Councils and TERENA, the Trans-European Research and Education
Networking Association.

AUTHOR
======

   Martin Hamilton <martinh@gnu.org>

Get, put, move, copy, and delete files located by URIs
******************************************************

NAME
====

   WebFS::FileCopy - Get, put, move, copy, and delete files located by URIs

SYNOPSIS
========

     use WebFS::FileCopy;

     my @res = get_urls('ftp://www.perl.com', 'http://www.netscape.com');
     print $res[0]->content if $res[0]->is_success;

     # Get content from pages requiring basic authentication.
     my $req = LWP::Request->new('GET' => 'http://www.dummy.com/');
     $req->authorization_basic('my_username', 'my_password');
     @res = get_urls($req);

     put_urls('put this text', 'ftp://ftp/incoming/new', 'file:/tmp/NEW');
     move_url('file:/tmp/NEW', 'ftp://ftp/incoming/NEW.1');
     delete_urls('ftp://ftp/incoming/NEW.1', 'file:/tmp/NEW');

     copy_url('http://www.perl.com/index.html', 'ftp://ftp.host/outgoing/SIG');

     copy_urls(['file:/tmp/file1', 'http://www.perl.com/index.html],
               ['file:/tmp/DIR1/', 'file:/tmp/DIR2', 'ftp://ftp/incoming/']);

     my @list1 = list_url('file:/tmp');
     my @list2 = list_url('ftp://ftp/outgoing/');

DESCRIPTION
===========

   This package provides some simple routines to read, move, copy, and
delete files as references by string URLs, URI objects or URIs embedded in
HTTP::Reqeust or LWP::Request objects.  All subroutines in this package
that expect a URI will accept a string, a URI object, or a HTTP::Reqeust
or LWP::Request with an embedded URI. If passed a HTTP::Request or
LWP::Request, then the method of the object is ignored and the proper
method will be used to either GET or PUT the requested UIR.

   The distinction between files and directories in a URI is tested by
looking for a trailing / in the path.  If a trailing / exists, then the
URI is considered to point to a directory, otherwise it is a file.

   All of the following subroutines are exported to the users namespace
automatically.  If you do not want this, then require this package instead
of useing it.

SUBROUTINES
===========

get_urls *uri* [*uri* [*uri* ...]]
     The get_urls function will fetch the documents identified by the
     given URIs and returns a list of *HTTP::Response*s.  You can test if
     the GET succeeded by using the *HTTP::Response* *is_success* method.
     If *is_success* returns 1, then use the content method to get the
     contents of the GET.

     Get_urls performs the GETs in parallel to speed execution and should
     be faster than performing individual gets.

     Example printing the success and the content from each URI:

          my @uris = ('http://perl.com/', 'file:/home/me/.sig');
          my @response = get_urls(@uris);
          foreach my $res (@response) {
            print "FOR URL ", $res->request->uri;
            if ($res->is_success) {
              print "SUCCESS.  CONTENT IS\n", $res->content, "\n";
            } else {
              print "FAILED BECAUSE ", $res->message, "\n";
            }
          }

put_urls string *uri* [*uri* [*uri* ...]]
put_urls *coderef* *uri* [*uri* [*uri* ...]]
     Put the contents of string or the return from &*coderef*() into the
     listed *uri*s.  The destination *uri*s must be either ftp: or file:
     and must specify a complete file; no directories are allowed.  If the
     first form is used with string then the contents of string will be
     sent.  If the second form is used, then *coderef* is a reference to a
     subroutine or anonymous CODE and &*coderef*() will be called
     repeatedly until it returns " or undef and all of the text it returns
     will be stored in the *uri*s.

     Upon return, put_urls returns an array, where each element contains a
     *HTTP::Response* object corresponding to the success or failure of
     transferring the data to the i-th *uri*.  This object can be tested
     for the success or failure of the PUT by using the *is_success*
     method on the element.  If the PUT was not successful, then the
     message method may be used to gather an error message explaining why
     the PUT failed.  If there is invalid input to put_urls then put_urls
     returns an empty list in a list context, an undefined value in a
     scalar context, or nothing in a void context, and $@ contains a
     message containing explaining the invalid input.

     For example, the following code, prints either YES or NO and a failure
     message if the put failed.

          @a = put_urls('text',
                        'http://www.perl.com/test.html',
                        'file://some.other.host/test',
                        'ftp://ftp.gps.caltech.edu/test');
          foreach $put_res (@a) {
            print $put_res->request->uri, ' ';
            if ($put_res->is_success) {
              print "YES\n";
            } else {
              print "NO ", $put_res->message, "\n";
            }
          }

copy_url *uri_from* *uri_to* [base]
     Copy the content contained in the URI *uri_from* to the location
     specified by the URI *uri_to*.  *uri_from* must contain the complete
     path to a file; no directories are allowed.  *uri_to* must be a file:
     or ftp: URI and may either be a directory or a file.

     If supplied, base may be used to convert *uri_from* and *uri_to* from
     relative URIs to absolute URIs.

     On return, copy_url returns 1 on success, 0 on otherwise.  On failure
     $@ contains a message explaining the failure.  See copy_urls if you
     want to quickly copy a single file to multiple places or copy multiple
     files to one directory or both.  copy_urls provides simultaneous file
     transfers and will do the task much faster than calling copy_url many
     times over.  If invalid input is given to copy_url, then it returns
     an empty list in a list context, an undefined value in a scalar
     context, or nothing in a void context and $@ contains a message
     explaining the invalid input.

copy_urls *uri_file_from* *uri_file_to* [base]
copy_urls *uri_file_from* *uri_dir_to* [base]
     Copy the content contained at the specified URIs to other locations
     also specified by URIs.  The first argument to copy_urls is either a
     single URI or a reference to an array of URIs to copy.  All of these
     URIs must contain the complete path to a file; no directories are
     allowed.  The second argument may be a single URI or a reference to
     an array of URIS.  If any of the destination URIs are a location of a
     file and not a directory, then only one URI can be passed as the
     first argument.  If a reference to an array of URIs is passed as the
     second argument, then all URIs must point to directories, not files.
     Only file: and ftp: URIs may be used as the destination of the copy.

     If supplied, base may be used to convert relative URIs to absolute
     URIs for all URIs supplied to copy_urls.

     The copy operations of the multiple URIs are done in parallel to speed
     execution.

     On return copy_urls returns a list of the *LWP::Response* from each
     GET performed on the from URIs.  If there is invalid input to
     copy_urls then copy_urls returns an empty list in a list context, an
     undefined value in a scalar context, or nothing in a void context and
     contains $@ a message explaining the error.  The success or failure
     of each GET may be tested by using *is_success* method on each
     element of the list.  If the GET succeeded (*is_success* returns
     TRUE), then hash element *'put_requests'* exists and is a reference
     to a list of *LWP::Response*s containing the response to the PUT.
     For example, the following code prints a message containing the
     results from copy_urls:

          my @get_res = copy_urls(......);
          foreach my $get_res (@get_res) {
            my $uri = $get_res->request->uri;
            print "GET from $uri ";
            unless ($get_res->is_success) {
              print "FAILED\n";
              next;
            }

            print "SUCCEEDED\n";
            foreach my $c (@{$get_res->{put_requests}}) {
              $uri = $c->request->uri;
              if ($c->is_success) {
                print "    to $uri succeeded\n"
              } else {
                print "    to $uri failed: ", $c->message, "\n";
              }
            }
          }

delete_urls *uri* [*uri* [*uri* ...]]
     Delete the files located by the *uri*s and return a *HTTP::Response*
     for each *uri*.  If the *uri* was successfully deleted, then the
     *is_success* method returns 1, otherwise it returns 0 and the message
     method contains the reason for the failure.

move_url *from_uri* *to_uri* [base]
     Move the contents of the *from_uri* URI to the *to_uri* URI.  If base
     is supplied, then the *from_uri* and *to_uri* URIs are converted from
     relative URIs to absolute URIs using base.  If the move was
     successful, then move_url returns 1, otherwise it returns 0 and $@
     contains a message explaining why the move failed.  If invalid input
     was given to move_url then it returns an empty list in a list context,
     an undefined value in a scalar context, or nothing in a void context
     and $@ contains a message explaining the invalid input.

list_url *uri*
     Return a list containing the filenames in the directory located at
     *uri*.  Only file and FTP directory URIs currently work.  If for any
     reason the list can not be obtained, then list_url returns an empty
     list in a list context, an undefined value in a scalar context, or
     nothing in a void context and $@ contains a message why list_url
     failed.

SEE ALSO
========

   See also the HTTP/Response, HTTP/Request,
`LWP::Request' in this node, and LWP/Simple.

AUTHOR
======

   Blair Zajac <blair@akamai.com>

COPYRIGHT
=========

   Copyright (C) 1998-2001 by Blair Zajac.  All rights reserved.  This
package is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Object for putting data to either file or ftp URI
*************************************************

NAME
====

   WebFS::FileCopy::Put - Object for putting data to either file or ftp URI

SYNOPSIS
========

     use WebFS::FileCopy::Put;

     my $req = HTTP::Request->new(PUT => 'file:/tmp/zzz');
     my $put = WebFS::FileCopy::Put->new($req);
     if ($put) {
       $put->print "Content goes here\n";
       my $res = $put->close;
       print $res->as_string, "\n";
     } else {
       my $res = $@;
       print $res->message, "\n";
     }

DESCRIPTION
===========

   An WebFS::FileCopy::Put object is used to put data to a remote file on
an FTP server or a local file.  The location is specified by using a
LWP::Request object.

METHODS
=======

   The following methods are available:

new request
     Returns either an *WebFS::FileCopy::Put::FTP* or
     *WebFS::FileCopy::PUT::File* object if a file or FTP put request is
     passed.  If invalid arguments are passed to new or if the put cannot
     be created, then undef is returned and $@ will contain a valid
     *HTTP::Response*.

print buffer
     Put the contents of buffer to the PUT file.

close
     Close the PUT file and return a *LWP::Response*, which can be used to
     test for the success or failure of the close using the *is_success*
     method.

SEE ALSO
========

   See also the WebFS/FileCopy, and
LWP/Simple, manual pages.

AUTHOR
======

   Blair Zajac <blair@akamai.com>

COPYRIGHT
=========

   Copyright (C) 1998-2001 by Blair Zajac.  All rights reserved.  This
package is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Perl module to download and save information from the Web
*********************************************************

NAME
====

   WebFetch - Perl module to download and save information from the Web

SYNOPSIS
========

     use WebFetch;

DESCRIPTION
===========

   The WebFetch module is a general framework for downloading and saving
information from the web, and for display on the web.  It requires another
module to inherit it and fill in the specifics of what and how to download.
WebFetch provides a generalized interface for saving to a file while
keeping the previous version as a backup.  This is expected to be used for
periodically-updated information which is run as a cron job.

INSTALLATION
============

   After unpacking and the module sources from the tar file, run

   `perl Makefile.PL'

   make

   make install

   Or from a CPAN shell you can simply type "`install WebFetch'" and it
will download, build and install it for you.

   If you need help setting up a separate area to install the modules
(i.e. if you don't have write permission where perl keeps its modules)
then see the Perl FAQ.

   To begin using the WebFetch modules, you will need to test your fetch
operations manually, put them into a crontab, and then use server-side
include (SSI) or a similar server configuration to include the files in a
live web page.

MANUALLY TESTING A FETCH OPERATION
----------------------------------

   Select a directory which will be the storage area for files created by
WebFetch.  This is an important administrative decision - keep the
volatile automatically-generated files in their own directory so they'll
be separated from manually-maintained files.

   Choose the specific WebFetch-derived modules that do the work you want.
See their particular manual/web pages for details on command-line
arguments.  Test run them first before committing to a crontab.

SETTING UP CRONTAB ENTRIES
--------------------------

   First of all, if you don't have crontab access or don't know what they
are, contact your site's system administrator(s).  Only local help will do
any good on local-configuration issues.  No one on the Internet can help.
(If you are the administrator for your system, see the crontab(1) and
crontab(5) manpages and nearly any book on Unix system administration.)

   Since the WebFetch command lines are usually very long, you may prefer
to make one or more scripts as front-ends so your crontab entries aren't
so huge.

   Do not run the crontab entries too often - be a good net.citizen and do
your updates no more often than necessary.  Popular sites need their users
to refrain from making automated requests too often because they add up on
an enormous scale on the Internet.  Some sites such as Freshmeat prefer no
shorter than hourly intervals.  Slashdot prefers no shorter than
half-hourly intervals.  When in doubt, ask the site maintainers what they
prefer.

   (Then again, there are a very few sites like Yahoo and CNN who don't
mind getting the extra hits if you're going to create links to them.  Even
so, more often than every 20 minutes would still be  excessive to the
biggest web sites.)

SETTING UP SERVER-SIDE INCLUDES
-------------------------------

   See the manual for your web server to make sure you have server-side
include (SSI) enabled for the files that need it.  (It's wasteful to
enable it for all your files so be careful.)

   When using Apache HTTPD, a line like this will include a
WebFetch-generated file:

   <!-#include file="fetch/slashdot.html"->

WebFetch FUNCTIONS
==================

   The following function definitions assume $obj is a blessed reference
to a module that is derived from (inherits from) WebFetch.

Do not use the new() function directly from WebFetch.
     *Use the new function from a derived class*, not directly from
     WebFetch.  The WebFetch module itself is just infrastructure for the
     other modules, and contains none of the details needed to complete
     any specific fetches.

$obj->init( ... )
     This is called from the new function of all WebFetch modules.  It
     takes "name" => "value" pairs which are all placed verbatim as
     attributes in $obj.

$obj->run
     This function is exported by standard WebFetch-derived modules as
     `fetch_main'.  This handles command-line processing for some standard
     options, calling the module-specific fetch function and WebFetch's
     $obj->save function to save the contents to one or more files.

     The command-line processing for some standard options are as follows:

    -dir directory
          (required) the directory in which to write output files

    -group group
          (optional) the group ID to set the output file(s) to

    -mode mode
          (optional) the file mode (permissions) to set the output file(s)
          to

    -export *export-file*
          (optional) save a portable WebFetch-export copy of the fetched
          info in the file named by this parameter.  The contents of this
          file can be read by the WebFetch::General module.  You may use
          this to export your own news to other WebFetch users.  (Exports
          may be explicitly disabled by some WebFetch-derived modules
          simply by omiting the export step from their fetch() functions.
          Though it works with all the modules that come included with the
          WebFetch package itself.)

    -xml_export *xml-export-file*
          (optional) save a generic XML copy of the fetched info into the
          file named by this parameter.  (A module to read this XML output
          will be included in a near-future version of WebFetch.)

    -ns_export *ns-export-file*
          (optional) save a MyNetscape export copy of the fetched info
          into the file named by this parameter.  If this optional
          parameter is used, three additional parameters become required:
          -ns_site_title, -ns_site_link, and -ns_site_desc.  If you want
          to include an icon in the channel display, you should also use
          -ns_image_title and -ns_image_url.  A URL Prefix must also be
          set for this to work correctly, which can be supplied via the
          the -url_prefix parameter or in the *url-prefix* line of the
          WebFetch::SiteNews news input file.

    -ns_site_title *site-title*
          (required if -ns_export is used) For exporting to MyNetscape,
          this sets the name of your site.  It cannot be more than 40
          characters

    -ns_site_link *site-link*
          (required if -ns_export is used) For exporting to MyNetscape,
          this is the full URL MyNetscape will use to link to your site.
          It cannot be more than 500 characters.

    -ns_site_desc *site-description*
          (required if -ns_export is used) For exporting to MyNetscape,
          this is a short description of your site.  It cannot be more
          than 500 characters.

    -ns_image_title *image-title*
          (optional) For exporting to MyNetscape, this is the title (alt)
          text for the icon image.

    -ns_image_url *image-url*
          (optional) For exporting to MyNetscape, this is the URL
          MyNetscpae will use for your icon image.  If this is present,
          the link on the image will be the same as your -ns_site_link
          parameter.

    -url_prefix *url-prefix*
          (optional) include a URL prefix to use on the saved URLs on
          -ns_export output files.  (It could also be used in the future
          by other output formats that need URL prefixes.)  This is
          considered optional by WebFetch though you will probably need it
          for MyNetscape to properly link to your site.  This information
          can also be supplied via the *url-prefix* line of the
          WebFetch::SiteNews news input file.  If it is set in the
          WebFetch::SiteNews, it will override the -url_prefix command
          line parameter.

    -font_size number
          (optional) choose a font size for generated HTML text.  This
          will be used in a font tag so it may be relative, like "-1" or
          "+1".

    -font_face string
          (optional) choose a font face for generated HTML text.  This
          will be used in a font tag so it may be any standard font name
          or a list.  For example, for a sans-serif font, use
          "`Helvetica,Arial,sans-serif'".

    -style *style-name-list*
          (optional) select from one or more of various HTML output styles
          for the generated HTML text.  If more than one style name is
          listed, they must be separated by commas (no spaces.)

         para
               use paragraph breaks between lines/links instead of
               unordered lists

         notable
               usually WebFetch modules generate HTML table-formatted
               output text but this option will disable the e of tables

         bullet
               use explicit bullet characters (HTML entity #149) and line
               breaks (br) to identify and separate each link

         ul
               (default) use an HTML unnumbered list (ul) block for the
               list of links

          The para, bullet and ul styles are mutually exclusive.  Others
          may be specified at the same time.

    -quiet
          (optional) suppress printed warnings for HTTP errors *(applies
          only to modules which use the WebFetch::get() function)* in case
          they are not desired for cron outputs

    -debug
          (optional) print verbose debugging outputs, only useful for
          developers adding new WebFetch-based modules or
          finding/reporting a bug in an existing module

     Modules derived from WebFetch may add their own command-line options
     that WebFetch::run() will use by defining a variable called
     *`@Options'* in the calling module, using the name/value pairs
     defined in Perl's Getopts::Long module.  Derived modules can also add
     to the command-line usage error message by defining a variable called
     *`$Usage'* with a string of the additional parameters, as they should
     appear in the usage message.

$obj->do_actions
     *`do_actions' was added in WebFetch 0.10 as part of the WebFetch
     Embedding API.* Upon entry to this function, $obj must contain the
     following attributes:

    data
          is a reference to a hash containing the following three
          (required) keys:

         fields
               is a reference to an array containing the names of the
               fetched data fields in the order they appear in the records
               of the data array.  This is necessary to define what each
               field is called because any kind of data can be fetched
               from the web.

         wk_names
               is a reference to a hash which maps from a key string with
               a "well-known" (to WebFetch) field type to a field name
               used in this table.  The well-known names are defined as
               follows:

              title
                    a one-liner banner or title text (plain text, no HTML
                    tags)

              url
                    URL/link to the news (fully-qualified URL only, no
                    HTML tags)

              date
                    a date stamp, which must be program-readable by Perl's
                    Date::Calc module in the Parse_Date() function in
                    order to support timestamp-related comparisons and
                    processing that some users have requested.  If the
                    date cannot be parsed by Date::Calc, either translate
                    it when your module captures it, or do not define this
                    "well-known" field because it wouldn't fit the
                    definition.  (plain text, no HTML tags)

              summary
                    a paragraph of summary text in HTML

              comments
                    number of comments/replies at the news site (plain
                    text, no HTML tags)

              author
                    a name, handle or login name representing the author
                    of the news item (plain text, no HTML tags)

              category
                    a word or short phrase representing the category,
                    topic or department of the news item (plain text, no
                    HTML tags)

              location
                    a location associated with the news item (plain text,
                    no HTML tags)

               The field names for this table are defined in the fields
               array.

               The hash only maps for the fields available in the table.
               If no field representing a given well-known name is present
               in the data fields, that well-known name key must not be
               defined in this hash.

         records
               an array containing the data records.  Each record is
               itself a reference to an array of strings which are the
               data fields.  This is effectively a two-dimensional array
               or a table.

               Only one table-type set of data is permitted per fetch
               operation.  If more are needed, they should be arranged as
               separate fetches with different parameters.

    actions
          is a reference to a hash.  The hash keys are names for handler
          functions.  The WebFetch core provides internal handler
          functions called *fmt_handler_html* (for HTML output),
          *fmt_handler_xml* (for XML output), *fmt_handler_wf* (for
          WebFetch::General format), *fmt_handler_rdf* (for MyNetscape RDF
          format).  However, WebFetch modules may provide additional
          format handler functions of their own by prepending
          "fmt_handler_" to the key string used in the actions array.

          The values are array references containing *"action specs"*,
          which are themselves arrays of parameters that will be passed to
          the handler functions for generating output in a specific format.
          There may be more than one entry for a given format if multiple
          outputs with different parameters are needed.

          The presence of values in this field mean that output is to be
          generated in the specified format.  The presence of these would
          have been chosed by the WebFetch module that created them -
          possibly by default settings or by a command-line argument that
          directed a specific output format to be used.

          For each valid action spec, a separate "savable" (contents to be
          placed in a file) will be generated from the contents of the
          data variable.

          The valid (but all optional) keys are

         html
               the value must be a reference to an array which specifies
               all the HTML generation (html_gen) operations that will
               take place upon the data.  Each entry in the array is
               itself an array reference, containing the following
               parameters for a call to html_gen():

              filename
                    a file name or path string (relative to the WebFetch
                    output directory unless a full path is given) for
                    output of HTML text.

              params
                    a hash reference containing optional name/value
                    parameters for the HTML format handler.

                   filter_func
                         (optional) a reference to code that, given a
                         reference to an entry in
                         @{$self->{data}{records}}, returns true (1) or
                         false (0) for whether it will be included in the
                         HTML output.  By default, all records are
                         included.

                   sort_func
                         (optional) a reference to code that, given
                         references to two entries in
                         @{$self->{data}{records}}, returns the sort
                         comparison value for the order they should be in.
                         By default, no sorting is done and all records
                         (subject to filtering) are accepted in order.

                   format_func
                         (optional) a refernce to code that, given a
                         reference to an entry in
                         @{$self->{data}{records}}, returns an HTML
                         representation of the string.  By default, a
                         standard HTML formatting is generated using the
                         well-known fields in the record.  (This default
                         generation fails if none of the title, url or text
                         names are defined in %{$self->{data}{wk_names}}.

         xml
               the value must be a reference to an array which specifies
               all the XML export (xml_export) operations that will take
               place upon the data.  Each entry in the array is itself an
               array reference, containing the following parameters for a
               call to xml_export():

              filename
                    a file name or path string (relative to the WebFetch
                    output directory unless a full path is given) for
                    output of XML text.

         wf
               the value must be a reference to an array which specifies
               all the WebFetch export (wf_export) operations that will
               take place upon the data.  Each entry in the array is
               itself an array reference, containing the following
               parameters for a call to wf_export():

              filename
                    a file name or path string (relative to the WebFetch
                    output directory unless a full path is given) for
                    output of the WebFetch::General export format.

         rdf
               the value must be a reference to an array which specifies
               all the Resource Description Framework (RDF) export
               (ns_export, used by MyNetscape) operations that will take
               place upon the data.  Each entry in the array is itself an
               array reference, containing the following parameters for a
               call to ns_export():

              filename
                    a file name or path string (relative to the WebFetch
                    output directory unless a full path is given) for
                    output of RDF format, for the MyNetscape portal or
                    other sites that can use RDF.

              site_title
                    For exporting to MyNetscape, this sets the name of
                    your site.  It cannot be more than 40 characters

              site_link
                    For exporting to MyNetscape, this is the full URL
                    MyNetscape will use to link to your site.  It cannot
                    be more than 500 characters.

              site_desc
                    For exporting to MyNetscape, this is a short
                    description of your site.  It cannot be more than 500
                    characters.

              image_title
                    (optional) For exporting to MyNetscape, this is the
                    title (alt) text for the icon image.

              image_url
                    (optional) For exporting to MyNetscape, this is the
                    URL MyNetscpae will use for your icon image.  If this
                    is present, the link on the image will be the same as
                    your $site_link parameter.

          Additional valid keys may be created by modules that inherit
          from WebFetch by supplying a method/function named with
          "fmt_handler_" preceding the string used for the key.  For
          example, for an "xyz" format, the handler function would be
          *fmt_handler_xyz*.  The value (the "action spec") of the hash
          entry must be an array reference.  Within that array are "action
          spec entries", each of which is a reference to an array
          containing the list of parameters that will be passed verbatim
          to the *fmt_handler_xyz* function.

          When the format handler function returns, it is expected to have
          created entries in the $obj->{savables} array (even if they only
          contain error messages explaining a failure), which will be used
          by $obj->save() to save the files and print the error messages.

          For coding examples, use the *fmt_handler_** functions in
          WebFetch.pm itself.

$obj->fetch
     *This function must be provided by each derived module to perform the
     fetch operaton specific to that module.* It will be called from new()
     so you should not call it directly.  Your fetch function should
     extract some data from somewhere and place of it in HTML or other
     meaningful form in the "savable" array.

     Upon entry to this function, $obj must contain the following
     attributes:

    dir
          The name of the directory to save in.  (If called from the
          command-line, this will already have been provided by the
          required `--dir' parameter.)

    savable
          a reference to an array where the "savable" items will be placed
          by the $obj->fetch function.  (You only need to provide an array
          reference - other WebFetch functions can write to it.)

          In WebFetch 0.10 and later, this parameter should no longer be
          supplied by the fetch function (unless you wish to use 0.09
          backward compatibility) because it is filled in by the
          *do_actions* after the fetch function is completed based on the
          data and actions variables that are set in the fetch function.
          (See below.)

          Each entry of the savable array is a hash reference with the
          following attributes:

         file
               file name to save in

         content
               scalar w/ entire text or raw content to write to the file

         group
               (optional) group setting to apply to file

         mode
               (optional) file permissions to apply to file

          Contents of savable items may be generated directly by derived
          modules or with WebFetch's `html_gen', `html_savable' or
          `raw_savable' functions.  These functions will set the group and
          mode parameters from the object's own settings, which in turn
          could have originated from the WebFetch command-line if this was
          called that way.

     Note that the fetch functions requirements changed in WebFetch 0.10.
     The old requirement (0.09 and earlier) is supported for backward
     compatibility.

     *In WebFetch 0.09 and earlier*, upon exit from this function, the
     $obj->savable array must contain one entry for each file to be saved.
     More than one array entry means more than one file to save.  The
     WebFetch infrastructure will save them, retaining backup copies and
     setting file modes as needed.

     *Beginning in WebFetch 0.10*, the "WebFetch embedding" capability was
     introduced.  In order to do this, the captured data of the fetch
     function had to be externalized where other Perl routines could
     access it.  So the fetch function now only populates data structures
     (including code references necessary to process the data.)

     Upon exit from the function, the following variables must be set in
     $obj:

    data
          is a reference to a hash which will be used by the *do_actions*
          function.  (See above.)

    actions
          is a reference to a hash which will be used by the *do_actions*
          function.  (See above.)

$obj->get
     This WebFetch utility function will get a URL and return a reference
     to a scalar with the retrieved contents.  Upon entry to this
     function, $obj must contain the following attributes:

    url
          the URL to get

    quiet
          a flag which, when set to a non-zero (true) value, suppresses
          printing of HTTP request errors on STDERR

$obj->wf_export ( $filename, $fields, $links, [ $comment, [ $param ]] )
     *In WebFetch 0.10 and later, this should be used only in format
     handler functions.  See do_handlers() for details.*

     This WebFetch utility function generates contents for a WebFetch
     export file, which can be placed on a web server to be read by other
     WebFetch sites.  The WebFetch::General module reads this format.
     $obj->wf_export has the following parameters:

    $filename
          the file to save the WebFetch export contents to; this will be
          placed in the savable record with the contents so the save
          function knows were to write them

    $fields
          a reference to an array containing a list of the names of the
          data fields (in each entry of the @$lines array)

    $lines
          a reference to an array of arrays; the outer array contains each
          line of the exported data; the inner array is a list of the
          fields within that line corresponding in index number to the
          field names in the @$fields array

    $comment
          (optional) a Human-readable string comment (probably describing
          the purpose of the format and the definitions of the fields
          used) to be placed at the top of the exported file

    $param
          (optional) a reference to a hash of global parameters for the
          exported data.  This is currently unused but reserved for future
          versions of WebFetch.

$obj->ns_export ( $filename, $lines, $site_title, $site_link, $site_desc, $image_title, $image_url)
     *In WebFetch 0.10 and later, this should be used only in format
     handler functions.  See do_handlers() for details.*

     This WebFetch utility function generates contents for a MyNetscape
     export file, which can be placed on a web server to be read by the
     MyNetscape site (my.netscape.com) if you create a "channel" for your
     site at MyNetscape.

     Of the modules included with WebFetch, only WebFetch::SiteNews and
     WebFetch::Genercal call $obj->ns_export().  The others will ignore it
     (because they're just obtaining data from other sites themselves.)
     You may use $obj->ns_export() in your own modules which inherit from
     WebFetch.

    $filename
          (required) the file to save the WebFetch export contents to;
          this will be placed in the savable record with the contents so
          the save function knows were to write them

    $lines
          (required) a reference to an array of arrays; the outer array
          contains each line of the exported data; the inner array is a
          list of two fields within that line consisting of a text title
          string in one entry and a URL in the second entry.

    $site_title
          (required) For exporting to MyNetscape, this sets the name of
          your site.  It cannot be more than 40 characters

    $site_link
          (required) For exporting to MyNetscape, this is the full URL
          MyNetscape will use to link to your site.  It cannot be more
          than 500 characters.

    $site_desc
          (required) For exporting to MyNetscape, this is a short
          description of your site.  It cannot be more than 500 characters.

    $image_title
          (optional) For exporting to MyNetscape, this is the title (alt)
          text for the icon image.

    $image_url
          (optional) For exporting to MyNetscape, this is the URL
          MyNetscpae will use for your icon image.  If this is present,
          the link on the image will be the same as your $site_link
          parameter.

$obj->html_gen( $filename, $format_func, $links )
     *In WebFetch 0.10 and later, this should be used only in format
     handler functions.  See do_handlers() for details.*

     This WebFetch utility function generates some common formats of HTML
     output used by WebFetch-derived modules.  The HTML output is stored
     in the $obj->{savable} array, for which all the files in that array
     can later be saved by the $obj->save function.  It has the following
     parameters:

    $filename
          the file name to save the generated contents to; this will be
          placed in the savable record with the contents so the save
          function knows were to write them

    $format_func
          a refernce to code that formats each entry in @$links into a
          line of HTML

    $links
          a reference to an array of arrays of parameters for
          `&$format_func'; each entry in the outer array is contents for a
          separate HTML line and a separate call to `&$format_func'

     Upon entry to this function, $obj must contain the following
     attributes:

    num_links
          number of lines/links to display

    savable
          reference to an array of hashes which this function will use as
          storage for filenames and contents to save (you only need to
          provide an array reference - the function will write to it)

          See $obj->fetch for details on the contents of the savable
          parameter

    table_sections
          (optional) if present, this specifies the number of table
          columns to use; the number of links from num_links will be
          divided evenly between the columns

    style
          (optional) a hash reference with style parameter names/values
          that can modify the behavior of the funciton to use different
          HTML styles.  The recognized values are enumerated with
          WebFetch's *-style* command line option.  (When they reach this
          point, they are no longer a comma-delimited string - WebFetch or
          another module has parsed them into a hash with the style name
          as the key and the integer 1 for the value.)

$obj->html_savable( $filename, $content )
     *In WebFetch 0.10 and later, this should be used only in format
     handler functions.  See do_handlers() for details.*

     This WebFetch utility function stores pre-generated HTML in a new
     entry in the $obj->{savable} array, for later writing to a file.
     It's basically a simple wrapper that puts HTML comments warning that
     it's machine-generated around the provided HTML text.  This is
     generally a good idea so that neophyte webmasters (and you know there
     are a lot of them in the world :-) will see the warning before trying
     to manually modify your automatically-generated text.

     See $obj->fetch for details on the contents of the savable parameter

$obj->raw_savable( $filename, $content )
     *In WebFetch 0.10 and later, this should be used only in format
     handler functions.  See do_handlers() for details.*

     This WebFetch utility function stores any raw content and a filename
     in the $obj->{savable} array, in preparation for writing to that file.
     (The actual save operation may also automatically include keeping
     backup files and setting the group and mode of the file.)

     See $obj->fetch for details on the contents of the savable parameter

$obj->save
     This WebFetch utility function goes through all the entries in the
     $obj->{savable} array and saves their contents, providing several
     services such as keeping backup copies, and setting the group and
     mode of the file, if requested to do so.

     If you call a WebFetch-derived module from the command-line run() or
     fetch_main() functions, this will already be done for you.  Otherwise
     you will need to call it after populating the savable array with one
     entry per file to save.

     Upon entry to this function, $obj must contain the following
     attributes:

    dir
          directory to save files in

    savable
          names and contents for files to save

     See $obj->fetch for details on the contents of the savable parameter

WRITING NEW WebFetch-DERIVED MODULES
------------------------------------

   The easiest way to make a new WebFetch-derived module is to start from
the module closest to your fetch operation and modify it.  Make sure to
change all of the following:

fetch function
     The fetch function is the meat of the operation.  Get the desired
     info from a local file or remote site and place the contents that
     need to be saved in the savable parameter.

module name
     Be sure to catch and change them all.

file names
     The code and documentation may refer to output files by name.

module parameters
     Change the URL, number of links, etc as necessary.

command-line parameters
     If you need to add command-line parameters, modify both the
     *`@Options'* and *`$Usage'* variables.  Don't forget to add
     documentation for your command-line options and remove old
     documentation for any you removed.

     When adding documentation, if the existing formatting isn't enough
     for your changes, there's more information about Perl's POD ("plain
     old documentation") embedded documentation format at
     http://www.cpan.org/doc/manual/html/pod/perlpod.html

authors
     Add yourself as an author if you added any significant functionality.
     But if you used anyone else's code, retain the existing author credits
     in any module you modify to make a new one.

export function
     If it's appropriate for users of your module to be able to export its
     data to other sites, add an export() function.  Use the one in
     WebFetch::SiteNews as an example if you need to.

   Please consider contributing any useful changes back to the WebFetch
project at `maint@webfetch.org'.

AUTHOR
======

   WebFetch was written by Ian Kluft for the Silicon Valley Linux User
Group (SVLUG).  Send patches, bug reports, suggestions and questions to
`maint@webfetch.org'.

   WebFetch is Open Source software distributed via the Comprehensive Perl
Archive Network (CPAN), a worldwide network of Perl web mirror sites.
WebFetch may be copied under the same terms and licensing as Perl itelf.

download and save 32BitsOnline headlines
****************************************

NAME
====

   WebFetch::32BitsOnline - download and save 32BitsOnline headlines

SYNOPSIS
========

   In perl scripts:

   `use WebFetch::32BitsOnline;'

   From the command line:

   `perl -w -MWebFetch::32BitsOnline -e "&fetch_main" -- --dir directory
[--features] '

DESCRIPTION
===========

   This module gets the current headlines from 32BitsOnline.

   After this runs, the file `32bitsonline.html' will be created or
replaced.  If there already was an `32bitsonline.html' file, it will be
moved to `O32bitsonline.html'.

   By default, *WebFetch::32BitsOnlin* fetches the news headlines from
32BitsOnline.  If the optional `--features' parameter is used, it will
fetch the latest feature articles from 32BitsOnline instead.

AUTHOR
======

   WebFetch was written by Ian Kluft for the Silicon Valley Linux User
Group (SVLUG).  Send patches, bug reports, suggestions and questions to
`maint@webfetch.org'.

SEE ALSO
========

download and save c|net news.com headlines or news search
*********************************************************

NAME
====

   WebFetch::CNETnews - download and save c|net news.com headlines or news
search

SYNOPSIS
========

   In perl scripts:

   `use WebFetch::CNETnews;'

   From the command line:

   `perl -w -MWebFetch::CNETnews -e "&fetch_main" -- --dir directory
[--alt_url url]  [--alt_file file] [--search search_string]'

DESCRIPTION
===========

   This module gets the current headlines from news.com.

   The optional `--alt_url' parameter allows you to select a different URL
to get the headlines from.

   After this runs, by default the file `cnet.html' will be created or
replaced.  If there already was an `cnet.html' file, it will be moved to
`Ocnet.html'.  These filenames can be overridden by the `--alt_file'
parameter.

   If the optional `--search' parameter is used, WebFetch::CNETnews will
search the c|net News.Com site for the search string instead of getting
the front-page headlines.

AUTHOR
======

   WebFetch was written by Ian Kluft for the Silicon Valley Linux User
Group (SVLUG).  The WebFetch::CNETnews module was contributed by Jamie
Heilman.  Send patches, bug reports, suggestions and questions to
`maint@webfetch.org'.

SEE ALSO
========

search for stories at CNN Interactive
*************************************

NAME
====

   WebFetch::CNNsearch - search for stories at CNN Interactive

SYNOPSIS
========

   In perl scripts:

   `use WebFetch::CNNsearch;'

   From the command line:

   `perl -w -MWebFetch::CNNsearch -e "&fetch_main" -- --dir directory
--search search-string [--pagesize search-page-size]      [--use_keyword]'

DESCRIPTION
===========

   This module gets the stories by searching CNN Interactive.

   The required *-search* parameter specifies a string to search for in
CNN's news.  The optional *-pagesize* parameter can be used to have the
search engine return more entries per page if not enough are obtained for
your use.

   The optional *-use_keyword* parameter causes a search by keyword
instead of by just any occurrence in the text.  This parameter was added
in WebFetch 0.07 because previous searches by body text only for "Linux"
began to fail when a Linux story became listed in the "in other news"
links on every page at CNN.  Using a keyword-only search gets around this
problem, returning only pages which have the string among their keywords.
But this only works if the writers at CNN used the keyword you're
interested in - do some searches either way to try it out first.

   After this runs, the file `cnnsearch.html' will be created or replaced.
If there already was an `cnnsearch.html' file, it will be moved to
`Ocnnsearch.html'.

AUTHOR
======

   WebFetch was written by Ian Kluft for the Silicon Valley Linux User
Group (SVLUG).  Send patches, bug reports, suggestions and questions to
`maint@webfetch.org'.

SEE ALSO
========

news from the comp.os.linux.announce ("cola") newsgroup
*******************************************************

NAME
====

   WebFetch::COLA - news from the comp.os.linux.announce ("cola") newsgroup

SYNOPSIS
========

   In perl scripts:

   `use WebFetch::COLA;'

   From the command line:

   `perl -w -MWebFetch::COLA -e "&fetch_main" -- --dir directory
[--noshuffle]'

DESCRIPTION
===========

   This module downloads news from the comp.os.linux.announce ("c.o.l.a")
moderator's archive.

   After this runs, the file `cola.html' will be created or replaced.  If
there already was an `cola.html' file, it will be moved to `Ocola.html'.

   The c.o.l.a archive is bursty, with many news items showing up at once,
but only updated every few days.  In order to present many current items,
WebFetch::COLA sorts by date but shuffles items which are listed as being
on the same date.  The webmaster is advised to include a link to the COLA
archive near the headline list so readers can peruse it if anything listed
gets their attention.

   If the shuffle feature is not desired, use the "-noshuffle" command-line
option to disable it.

AUTHOR
======

   WebFetch was written by Ian Kluft for the Silicon Valley Linux User
Group (SVLUG).  Send patches, bug reports, suggestions and questions to
`maint@webfetch.org'.

SEE ALSO
========

download and save Debian News headlines
***************************************

NAME
====

   WebFetch::DebianNews - download and save Debian News headlines

SYNOPSIS
========

   In perl scripts:

   `use WebFetch::DebianNews'

   >From the command line:

   `perl -w -MWebFetch::DebianNews -e "&fetch_main" -- --dir directory'

DESCRIPTION
===========

   This module gets the current headlines from the Debian Linux
organization.

   After this runs, the file `debiannews.html' will be created or replaced.
If there already was an `debiannews.html' file, it will be moved to
`Odebiannews.html'.

AUTHOR
======

   WebFetch was written by Ian Kluft for the Silicon Valley Linux User
Group (SVLUG).  The WebFetch::DebianNews module was written by Chuck
Ritter.  Send patches or maintenance requests for this module to
`critter@roadport.com'.  Send general patches, bug reports, suggestions
and questions to `maint@webfetch.org'.

SEE ALSO
========

download and save Freshmeat headlines
*************************************

NAME
====

   WebFetch::Freshmeat - download and save Freshmeat headlines

SYNOPSIS
========

   In perl scripts:

   `use WebFetch::Freshmeat;'

   From the command line:

   `perl -w -MWebFetch::Freshmeat -e "&fetch_main" -- --dir directory'

DESCRIPTION
===========

   This module gets the current headlines from Freshmeat.

   After this runs, the file `freshmeat.html' will be created or replaced.
If there already was an `freshmeat.html' file, it will be moved to
`Ofreshmeat.html'.

AUTHOR
======

   WebFetch was written by Ian Kluft for the Silicon Valley Linux User
Group (SVLUG).  Send patches, bug reports, suggestions and questions to
`maint@webfetch.org'.

SEE ALSO
========

download and save headlines from other WebFetch sites
*****************************************************

NAME
====

   WebFetch::General - download and save headlines from other WebFetch
sites

SYNOPSIS
========

   In perl scripts:

   `use WebFetch::General;'

   From the command line:

   `perl -w -MWebFetch::General -e "&fetch_main" -- --dir directory
--file output-filename --url source-url [--format format]'

DESCRIPTION
===========

   This module gets the current headlines from any WebFetch site that
exports its news with the "WebFetch Export" format.  You can do this with
the -export command-line parameter.  It works for any WebFetch module that
defines the *export()* function, which includes all the modules that come
packaged with WebFetch.

   The webmaster of a remote site only needs to arrange for a cron job to
update a WebFetch Export file, and let others know the URL to reach that
file.  (On the exporting site, it is most likely they'll use
WebFetch::SiteNews to export their own news.)  Then you can use the
WebFetch::General module to read the remote file and generate and HTML
summary of the news.

   After WebFetch::General runs, the file specified in the -file parameter
will be created or replaced.  If there already was a file by that name, it
will be moved to a filename with "O" (for old) prepended to the file name.

FORMAT STRINGS
==============

   WebFetch::General uses a format string to generate HTML from the
incoming data.  The default format for retrieved data is

   <a href="%url%">%title%</a>

   This means that fields named "url" and "title" must exist in the
incoming WebFetch-exported data, and will be used to fill in the *%url%*
and *%title%* strings, respectively.  You may use the -format parameter to
specify any format you wish.  But the field names you choose in the format
must match fields defined in the input stream.  Otherwise they will fail
to be expanded.

THE "WebFetch Export" FILE FORMAT
=================================

   This is an example WebFetch Export file generated by WebFetch::SiteNews:

     [WebFetch export]
     Version: 0.09
     # This was generated by the Perl5 WebFetch 0.09 module.
     # WebFetch info can be found at http://www.webfetch.org/
     #
     # Exported from WebFetch::SiteNews
     # "date" is the date of the news
     # "title" is a one-liner title
     # "url" is url to the news source
     # "text" is the news text

     date: August 15, 1999
     title: WebFetch 0.09 released
     url: http://www.webfetch.org/news.shtml#19990815-000
     text:   <a href="dist/WebFetch-0.09.tar.Z">WebFetch 0.09 beta</a> adds\
             a new LinuxTelephony module, contributed by Greg Youngblood\
             as well as modules for Linux Dev.Net, 32BitsOnline\
             and <a href="dist/Changes">other updates</a>

     date: August 1, 1999
     title: WebFetch 0.08 released
     url: http://www.webfetch.org/news.shtml#19990801-000
     text:   <a href="dist/WebFetch-0.08.tar.Z">WebFetch 0.08 beta</a>\
             adds a new DebianNews module contributed by Chuck Ritter,\
             as well as <a href="dist/Changes">other updates</a>

     date: August 1, 1999
     title: Slashdot lists Webfetch first among headlines tools
     url: http://www.webfetch.org/news.shtml#19990801-001
     text:   Many thanks to <a href="http://slashdot.org/">Slashdot</a>\
             for listing WebFetch <i>first</i> among the\
             <a href="http://slashdot.org/code.shtml">tools that can\
             display headlines from their site</a>.

   Each news item is separated by a blank line.

   Within each news item, the fields use a "name: value" format, similar
to RFC822 headers (i.e. as in e-mail and news.)

   The names of the fields are chosen by the exporting module.  Though for
the convenience of the user, the author of an exporting module should keep
in mind the default WebFetch::General format uses fields called "url" and
"title".  If you use fields by different names, warn your receiving users
that they will need to make a format to use with WebFetch::General, though
you may provide them with one in their setup instructions.

AUTHOR
======

   WebFetch was written by Ian Kluft for the Silicon Valley Linux User
Group (SVLUG).  Send patches, bug reports, suggestions and questions to
`maint@webfetch.org'.

SEE ALSO
========

download and save Linux Dev.Net headlines
*****************************************

NAME
====

   WebFetch::LinuxDevNet - download and save Linux Dev.Net headlines

SYNOPSIS
========

   In perl scripts:

   `use WebFetch::LinuxDevNet;'

   From the command line:

   `perl -w -MWebFetch::LinuxDevNet -e "&fetch_main" -- --dir directory'

DESCRIPTION
===========

   This module gets the current headlines from Linux Dev.Net
(linuxdev.net).

   After this runs, the file `linuxdevnet.html' will be created or
replaced.  If there already was an `linuxdevnet.html' file, it will be
moved to `Olinuxdevnet.html'.

AUTHOR
======

   WebFetch was written by Ian Kluft for the Silicon Valley Linux User
Group (SVLUG).  Send patches, bug reports, suggestions and questions to
`maint@webfetch.org'.

SEE ALSO
========

download and save LinuxTelephony headlines
******************************************

NAME
====

   WebFetch::LinuxTelephony - download and save LinuxTelephony headlines

SYNOPSIS
========

   In perl scripts:

   `use WebFetch::LinuxTelephony;'

   >From the command line:

   `perl -w -MWebFetch::LinuxTelephony -e "&fetch_main" -- --dir directory'

DESCRIPTION
===========

   This module gets the current headlines from LinuxTelephony.

   After this runs, the file `linuxtelephony.html' will be created or
replaced.  If there already was an `linuxtelephony.html' file, it will be
moved to `Olinuxtelephony.html'.

AUTHOR
======

   WebFetch was written by Ian Kluft for the Silicon Valley Linux User
Group (SVLUG).  Send patches, bug reports, suggestions and questions to
`maint@webfetch.org'.

   WebFetch::LinuxTelephony is based on WebFetch::LinuxToday.
Modifications made for WebFetch::LinuxTelephony by Gregory S. Youngblood,
`greg@tcscs.com'.

SEE ALSO
========

download and save LinuxToday headlines
**************************************

NAME
====

   WebFetch::LinuxToday - download and save LinuxToday headlines

SYNOPSIS
========

   In perl scripts:

   `use WebFetch::LinuxToday;'

   From the command line:

   `perl -w -MWebFetch::LinuxToday -e "&fetch_main" -- --dir directory'

DESCRIPTION
===========

   This module gets the current headlines from LinuxToday.

   After this runs, the file `linuxtoday.html' will be created or replaced.
If there already was an `linuxtoday.html' file, it will be moved to
`Olinuxtoday.html'.

AUTHOR
======

   WebFetch was written by Ian Kluft for the Silicon Valley Linux User
Group (SVLUG).  Send patches, bug reports, suggestions and questions to
`maint@webfetch.org'.

SEE ALSO
========

summarize mail list subscriptions
*********************************

NAME
====

   WebFetch::ListSubs - summarize mail list subscriptions

SYNOPSIS
========

   In perl scripts:

   `use WebFetch::ListSubs;'

   From the command line:

   `perl -w -MWebFetch::ListSubs -e "&fetch_main" -- --dir directory
--list mail-list-file --out output-file [--title table-title]'

DESCRIPTION
===========

   This module gets the current subscriptions from a mail list file (used
by a mail list server on the same machine) and summarizes the
subscriptions by top-level domain.  The mail list file is in a format used
by Majordomo, SmartList, Smail, Exim and many others - one address per
line.  Comments (beginning with "#") and blank lines are allowed but
ignored.

   The contents of the mail list are read from the file named in the
`--list' parameter.  The summary as an HTML table is written to the file
named by the `--out' parameter.  The optional `--title' parameter may be
used to put a title on the HTML table produced by this fetch operation.

AUTHOR
======

   WebFetch was written by Ian Kluft for the Silicon Valley Linux User
Group (SVLUG).  Send patches, bug reports, suggestions and questions to
`maint@webfetch.org'.

SEE ALSO
========

accepts a Perl structure with pre-parsed news
*********************************************

NAME
====

   WebFetch::PerlStruct - accepts a Perl structure with pre-parsed news

SYNOPSIS
========

   In perl scripts:

   `use WebFetch::PerlStruct;'

   `$obj = new WebFetch::PerlStruct ( 	"content" =' content_struct, 	"dir"
=> output_dir, 	"file" => output_file, 	[ "format" =>
format_string, ] 	[ "export" => wf_export_filename, ] 	[ "ns_export" =>
ns_export_filename, ] 	[ "ns_export" => ns_export_filename, ] 	[
"ns_export" => ns_export_filename, ] 	[ "ns_site_title" =>
ns_export_site_title, ] 	[ "ns_site_link" => ns_export_site_link, ]
[ "ns_site_desc" => ns_export_site_desc, ] 	[ "ns_image_title" =>
ns_export_image_title, ] 	[ "ns_image_url" => ns_export_image_url, ]
[ "font_size" => font_size, ] 	[ "font_face" => font_face, ] 	[
"group" => file_group_id, ] 	[ "mode" => file_mode_perms, ] 	[
"quiet" => 1 ]);>

   *Note: WebFetch::PerlStruct is a Perl interface only.  It does not
support usage from the command-line.*

DESCRIPTION
===========

   This module accepts a perl structure with pre-parsed news and pushes it
into the WebFetch infrastructure.

   The webmaster of a remote site only needs to arrange for a cron job to
update a WebFetch Export file, and let others know the URL to reach that
file.  (On the exporting site, it is most likely they'll use
WebFetch::SiteNews to export their own news.)  Then you can use the
WebFetch::PerlStruct module to read the remote file and generate and HTML
summary of the news.

   After WebFetch::PerlStruct runs, the file specified in the -file
parameter will be created or replaced.  If there already was a file by
that name, it will be moved to a filename with "O" (for old) prepended to
the file name.

   Most of the parameters listed are inherited from WebFetch.  See the
WebFetch module documentation for details.

THE CONTENT STRUCTURE
=====================

   The $content_struct parameter must be a reference to an array of hashes.
Each of the hashes represents a separate news item, in the order they
should be displayed.  The fields of each has entry must provide enough
information to match field names in all the the output formats you're
using.  Output formats include the following:

HTML output file
     All the fields used in the $format_string (see below) must be present
     for generation of the HTML output.

WebFetch export
     The $format_string also determines the fields that will be used for
     WebFetch export.  Note that the WebFetch::General module expects by
     default to find fields called "url" and "title".  So if you use
     something different from the default, you must provide your format
     string in the instructions for sites that fetch news from you.
     (Otherwise their WebFetch::General won't be looking for the fields
     you're providing.)

MyNetscape export
     The MyNetscape export function expects to find fields called "title"
     and "url", and will skip any hash entry which is missing either of
     them.

FORMAT STRINGS
==============

   WebFetch::PerlStruct uses a format string identical to
WebFetch::General.  The default format for retrieved data is

   <a href="%url%">%title%</a>

   See the WebFetch::General documentation for more details.

   The names of the fields are chosen by the calling function.  Though for
the convenience of the user, the author of an exporting module should keep
in mind the default WebFetch::PerlStruct format uses fields called "url"
and "title".  If you use fields by different names, make sure your code
provides those fields in the $content_struct parameter.

AUTHOR
======

   WebFetch was written by Ian Kluft for the Silicon Valley Linux User
Group (SVLUG).  Send patches, bug reports, suggestions and questions to
`maint@webfetch.org'.

SEE ALSO
========

download and save SiteNews headlines
************************************

NAME
====

   WebFetch::SiteNews - download and save SiteNews headlines

SYNOPSIS
========

   In perl scripts:

   `use WebFetch::SiteNews;'

   From the command line:

   `perl -w -MWebFetch::SiteNews -e "&fetch_main" -- --dir directory
--input news-file --short short-form-output-file      --long
long-form-output-file'

DESCRIPTION
===========

   This module gets the current headlines from a site-local file.

   The *-input* parameter specifies a file name which contains news to be
posted.  See `"FILE FORMAT"' in this node below for details on contents to
put in the file.  *-input* may be specified more than once, allowing a
single news output to come from more than one input.  For example, one
file could be manually maintained in CVS or RCS and another could be
entered from a web form.

   After this runs, the file `site_news.html' will be created or replaced.
If there already was a `site_news.html' file, it will be moved to
`Osite_news.html'.

FILE FORMAT
===========

   The WebFetch::SiteNews data format is used to set up news for the local
web site and allow other sites to import it via WebFetch.  The file is
plain text containing comments and the news items.

   There are three forms of outputs generated from these news files.

   The *"short news" output* is a small number (5 by default) of HTML text
and links used for display in a small news window.  And example of this
can be seen in the "SVLUG News" box on SVLUG's home page.  This list takes
into account expiration dates and priorities to pick which news entries
are displayed and in what order.

   The *"long news" output* lists all the news entries chronologically.
It does not take expiration or priority into account.  It is intended for
a comprehensive site news list.  An example can be found on SVLUG's news
page.

   The *export modes* make news items available in formats other web sites
can retrieve to post news about your site.  They are chronological
listings that omit expired items.  They do not take priorities into
account.

global parameters
     Lines coming before the first news item can set global parameters.

    categories
          A line before the first news item beginning with "categories:"
          contains a whitespace-delimited list of news category names in
          order from highest to lowest priority.  These priority names are
          used by the news item attributes and then for sorting "short
          news" list items.

    url-prefix
          A global parameter line beginning with "url-prefix:" will
          override the -url_prefix command line parameter with a URL
          prefix to use when exporting news items via the WebFetch Export
          format (see -export) or by MyNetscape's RDF export format (via
          -ns_export).

data lines
     Non-blank non-indented non-comment lines are *data lines*.  Each data
     line contains a *name=value* pair.  Each group of consecutive data
     lines is followed by an arbitrary number of indented lines which
     contain HTML text for the news entry.

     The recognized attributes are as follows:

    category
          used for prioritization, values are set by the categories global
          parameter (required)

    posted
          date posted, format is a numerical date YYYYMMDD (required)

    expires
          expiration date, format is a numerical date YYYYMMDD (optional)

    title
          shorter title for use in news exports to other sites, otherwise
          the whole news text will be used (optional)

text lines
     Intended lines are HTML text for the news item.

comments
     Comments are lines beginning with "#".  They are ignored so they can
     be used for human-readable information.

   Note that the "short news" list has some modifications to priorities
based on the age of the news item, so that the short list will favor newer
items when they're the same priority.  There is a sorting "priority bonus"
for items less than a day old, which increases their priority by two
priority levels.  Day-old news items get a bonus of one priority level.
All news items also "decay" in priority slightly every day, dropping a
whole priority level every 40 days.

AUTHOR
======

   WebFetch was written by Ian Kluft for the Silicon Valley Linux User
Group (SVLUG).  Send patches, bug reports, suggestions and questions to
`maint@webfetch.org'.

SEE ALSO
========

download and save Slashdot (or any Slashdot-compatible) headlines
*****************************************************************

NAME
====

   WebFetch::Slashdot - download and save Slashdot (or any
Slashdot-compatible) headlines

SYNOPSIS
========

   In perl scripts:

   `use WebFetch::Slashdot;'

   From the command line:

   `perl -w -MWebFetch::Slashdot -e "&fetch_main" -- --dir directory
[--alt_url url  [--alt_file file]'

   Alternative command line to filter out specific authors:

   `perl -w -MWebFetch::Slashdot -e "&fetch_main" -- --dir directory
--filter author [--alt_url url]  [--alt_file file]'

DESCRIPTION
===========

   This module gets the current headlines from Slashdot.org via their XML
interface.

   The optional `--alt_url' parameter allows you to select a different URL
to get the headlines from.

   An optional command-line argument of `--filter' may be used to filter
out specific authors.  This is not necessarily recommended but it was in
use at SVLUG when this module was first developed.

   After this runs, by default the file `sdot.html' will be created or
replaced.  If there already was an `sdot.html' file, it will be moved to
`Osdot.html'.  These filenames can be overridden by the `--alt_file'
parameter.

AUTHOR
======

   WebFetch was written by Ian Kluft for the Silicon Valley Linux User
Group (SVLUG).  Send patches, bug reports, suggestions and questions to
`maint@webfetch.org'.

SEE ALSO
========

download and save YahooBiz headlines
************************************

NAME
====

   WebFetch::YahooBiz - download and save YahooBiz headlines

SYNOPSIS
========

   In perl scripts:

   `use WebFetch::YahooBiz;'

   From the command line:

   `perl -w -MWebFetch::YahooBiz -e "&fetch_main" -- --dir directory
--search search-string --days search-days      --pagesize search-page-size'

DESCRIPTION
===========

   This module gets the current headlines from Yahoo Business News.

   After this runs, the file `yahoo_biz.html' will be created or replaced.
If there already was an `yahoo_biz.html' file, it will be moved to
`Oyahoo_biz.html'.

AUTHOR
======

   WebFetch was written by Ian Kluft for the Silicon Valley Linux User
Group (SVLUG).  Send patches, bug reports, suggestions and questions to
`maint@webfetch.org'.

SEE ALSO
========

Perl extension for doing Wharf or Window Maker dockapps.
********************************************************

NAME
====

   JDockApp - Perl extension for doing Wharf or Window Maker dockapps.

SYNOPSIS
========

     use Wharf::JDockApp;

     SetSetup( \&some_func);
     SetExpose(\&some_func);
     SetUpdate(\&some_func);
     SetButton(\&some_func);

     SetDelay($delay)

     StartApp;
     ClearWindow;

     also:

     jpprint($x, $y, COLOR, "stuff");
     jprint(         COLOR, "stuff");

DESCRIPTION
===========

     SetSetup  - called when the JDockApp starts
     SetExpose - called when the JDockApp is uncovered
                 (it's uncovered when the app starts btw)
     SetUpdate - called every $delay seconds
     SetButton - called whenever someone clicks the JDockApp

     SetDelay  - You must give this function a number of
                 seconds--or an Illithid will eat your brain.

     When all your /Sets[SEB]/ are set, call StartApp.

     ClearWindow - This is a secret function.  Only use it
                   if you are in the know.  I'll not
                   be held responsible if your dockapp
                   window is clear'd.  I simply will not.

     Brought with us from Wharf::JDockApp::jtools:

     jpprint - print some text at ($x, $y).
     jprint  - print some text ... starting where we left off.

     for both jprint and jpprint, COLOR is a constant

Exported constants
==================

   The number of colors for jprintf is quite limited.  The reason?  The
XPM 'code' is compiled into the binary.

     BLUE    - the color blue
     CYAN    - the color cyan
     GREEN   - the color green
     INDIGO  - the color indigo
     ORANGE  - the color orange
     PINK    - the color pink
     RED     - the color red
     VIOLET  - the color violet
     YELLOW  - the color yellow

EXAMPLES
========

     There is an examples directory that comes with the distribution.
     In it is a copy of the wmjmail program.  It'll parse your mailbox
     (rather stupidly) to determin how many messages you have, and
     of them how many are new.  I couldn't figure out how to get the
     Makefile.PL -- without resorting to a total hack -- to install
     the wmjmail script. If you can tell me how, please e-mail me
     and I'll alter the next distribution.

AUTHOR
======

     Jettero Heller <jettero@voltar.org>

SEE ALSO
========

   perl(1), Wharf::JDockApp(3), Wharf::JDockApp::jtools(3).

Perl extension for JDockApp.  It's the tools, man.
**************************************************

NAME
====

   jtools - Perl extension for JDockApp.  It's the tools, man.

SYNOPSIS
========

     use Wharf::JDockApp::jtools;

     Wharf::JDockApp::jtools::jpprint($x, $y, COLOR, "text");
     Wharf::JDockApp::jtools::jprint(COLOR, "text");

     Wharf::JDockApp::jtools::set_setup(\&func);
     Wharf::JDockApp::jtools::set_expose(\&func);
     Wharf::JDockApp::jtools::set_update(\&func);
     Wharf::JDockApp::jtools::set_button(\&func);

     Wharf::JDockApp::jtools::clear_window;
     Wharf::JDockApp::jtools::start_app;

     Wharf::JDockApp::jtools::set_update_delay($seconds);
     Wharf::JDockApp::jtools::set_loop_delay(1000);

DESCRIPTION
===========

     You don't want to use this module.  It's the support module for JDockApp.
     I drain'd these functions and constants out of JDockApp, because I wanted
     whatever tools that may come next to be separate from these.

     Later there may be some tools for clearing the white grey line,
     adding little pictures and buttons, n' doing lines and circles;
     but those would come in like Wharf::JDockApp::geom_tools and
     Wharf::JDockApp::buttons.  These docs are, therefore, basically just
     for completeness.  Well, and so if you follow the SEE ALSO white
     rabbit, you find something worth reading.  ;)

Exported constants
==================

   The number of colors for jprintf is quite limited.  The reason?  The
XPM 'code' is compiled into the binary.

     BLUE    - the color blue
     CYAN    - the color cyan
     GREEN   - the color green
     INDIGO  - the color indigo
     ORANGE  - the color orange
     PINK    - the color pink
     RED     - the color red
     VIOLET  - the color violet
     YELLOW  - the color yellow

AUTHOR
======

     Jettero Heller <jettero@voltar.org>

SEE ALSO
========

   perl(1), Wharf::JDockApp(3), Wharf::JDockApp::jtools(3).

Interfaces to some Win32 API Functions
**************************************

NAME
====

   Win32 - Interfaces to some Win32 API Functions

DESCRIPTION
===========

   Perl on Win32 contains several functions to access Win32 APIs. Some are
included in Perl itself (on Win32) and some are only available after
explicitly requesting the Win32 module with:

     use Win32;

   The builtin functions are marked as [CORE] and the other ones as [EXT]
in the following alphabetical listing. The Win32 module is not part of the
Perl source distribution; it is distributed in the libwin32 bundle of
Win32::* modules on CPAN. The module is already preinstalled in binary
distributions like ActivePerl.

Alphabetical Listing of Win32 Functions
---------------------------------------

Win32::AbortSystemShutdown(MACHINE)
     [EXT] Aborts a system shutdown (started by the InitiateSystemShutdown
     function) on the specified MACHINE.

Win32::BuildNumber()
     [CORE] Returns the ActivePerl build number. This function is only
     available in the ActivePerl binary distribution.

Win32::CopyFile(FROM, TO, OVERWRITE)
     [CORE] The Win32::CopyFile() function copies an existing file to a new
     file. All file information like creation time and file attributes will
     be copied to the new file. However it will not copy the security
     information. If the destination file already exists it will only be
     overwritten when the OVERWRITE parameter is true. But even this will
     not overwrite a read-only file; you have to unlink() it first
     yourself.

Win32::DomainName()
     [CORE] Returns the name of the Microsoft Network domain that the
     owner of the current perl process is logged into.

Win32::ExpandEnvironmentStrings(STRING)
     [EXT] Takes STRING and replaces all referenced environment variable
     names with their defined values. References to environment variables
     take the form `%VariableName%'. Case is ignored when looking up the
     VariableName in the environment. If the variable is not found then the
     original `%VariableName%' text is retained.  Has the same effect as
     the following:

          $string =~ s/%([^%]*)%/$ENV{$1} || "%$1%"/eg

Win32::FormatMessage(ERRORCODE)
     [CORE] Converts the supplied Win32 error number (e.g. returned by
     Win32::GetLastError()) to a descriptive string.  Analogous to the
     perror() standard-C library function.  Note that $^E used in a string
     context has much the same effect.

          C:\> perl -e "$^E = 26; print $^E;"
          The specified disk or diskette cannot be accessed

Win32::FsType()
     [CORE] Returns the name of the filesystem of the currently active
     drive (like 'FAT' or 'NTFS'). In list context it returns three values:
     (FSTYPE, FLAGS, MAXCOMPLEN). FSTYPE is the filesystem type as before.
     FLAGS is a combination of values of the following table:

          0x00000001  supports case-sensitive filenames
          0x00000002  preserves the case of filenames
          0x00000004  supports Unicode in filenames
          0x00000008  preserves and enforces ACLs
          0x00000010  supports file-based compression
          0x00000020  supports disk quotas
          0x00000040  supports sparse files
          0x00000080  supports reparse points
          0x00000100  supports remote storage
          0x00008000  is a compressed volume (e.g. DoubleSpace)
          0x00010000  supports object identifiers
          0x00020000  supports the Encrypted File System (EFS)

     MAXCOMPLEN is the maximum length of a filename component (the part
     between two backslashes) on this file system.

Win32::FreeLibrary(HANDLE)
     [EXT] Unloads a previously loaded dynamic-link library. The HANDLE is
     no longer valid after this call. See
     `LoadLibrary|Win32::LoadLibrary(LIBNAME)' in this node for
     information on dynamically loading a library.

Win32::GetArchName()
     [EXT] Use of this function is deprecated. It is equivalent with
     $ENV{PROCESSOR_ARCHITECTURE}. This might not work on Win9X.

Win32::GetChipName()
     [EXT] Returns the processor type: 386, 486 or 586 for Intel
     processors, 21064 for the Alpha chip.

Win32::GetCwd()
     [CORE] Returns the current active drive and directory. This function
     does not return a UNC path, since the functionality required for such
     a feature is not available under Windows 95.

Win32::GetFullPathName(FILENAME)
     [CORE] GetFullPathName combines the FILENAME with the current drive
     and directory name and returns a fully qualified (aka, absolute) path
     name. In list context it returns two elements: (PATH, FILE) where
     PATH is the complete pathname component (including trailing backslash)
     and FILE is just the filename part.  Note that no attempt is made to
     convert 8.3 components in the supplied FILENAME to longnames or
     vice-versa.  Compare with Win32::GetShortPathName and
     Win32::GetLongPathName.

     This function has been added for Perl 5.6.

Win32::GetLastError()
     [CORE] Returns the last error value generated by a call to a Win32 API
     function.  Note that $^E used in a numeric context amounts to the
     same value.

Win32::GetLongPathName(PATHNAME)
     [CORE] Returns a representaion of PATHNAME composed of longname
     components (if any).  The result may not necessarily be longer than
     PATHNAME.  No attempt is made to convert PATHNAME to the absolute
     path.  Compare with Win32::GetShortPathName and
     Win32::GetFullPathName.

     This function has been added for Perl 5.6.

Win32::GetNextAvailDrive()
     [CORE] Returns a string in the form of "<d>:" where <d> is the first
     available drive letter.

Win32::GetOSVersion()
     [CORE] Returns the array (STRING, MAJOR, MINOR, BUILD, ID), where the
     elements are, respectively: An arbitrary descriptive string, the
     major version number of the operating system, the minor version
     number, the build number, and a digit indicating the actual operating
     system. For ID, the values are 0 for Win32s, 1 for Windows 9X and 2
     for Windows NT. In scalar context it returns just the ID.

Win32::GetShortPathName(PATHNAME)
     [CORE] Returns a representation of PATHNAME composed only of short
     (8.3) path components.  The result may not necessarily be shorter
     than PATHNAME.  Compare with Win32::GetFullPathName and
     Win32::GetLongPathName.

Win32::GetProcAddress(INSTANCE, PROCNAME)
     [EXT] Returns the address of a function inside a loaded library. The
     information about what you can do with this address has been lost in
     the mist of time. Use the Win32::API module instead of this deprecated
     function.

Win32::GetTickCount()
     [CORE] Returns the number of milliseconds elapsed since the last
     system boot. Resolution is limited to system timer ticks (about 10ms
     on WinNT and 55ms on Win9X).

Win32::InitiateSystemShutdown(MACHINE, MESSAGE, TIMEOUT, FORCECLOSE, REBOOT)
     [EXT] Shutsdown the specified MACHINE, notifying users with the
     supplied MESSAGE, within the specified TIMEOUT interval. Forces
     closing of all documents without prompting the user if FORCECLOSE is
     true, and reboots the machine if REBOOT is true. This function works
     only on WinNT.

Win32::IsWinNT()
     [CORE] Returns non zero if the Win32 subsystem is Windows NT.

Win32::IsWin95()
     [CORE] Returns non zero if the Win32 subsystem is Windows 95.

Win32::LoadLibrary(LIBNAME)
     [EXT] Loads a dynamic link library into memory and returns its module
     handle. This handle can be used with Win32::GetProcAddress and
     Win32::FreeLibrary. This function is deprecated. Use the Win32::API
     module instead.

Win32::LoginName()
     [CORE] Returns the username of the owner of the current perl process.

Win32::LookupAccountName(SYSTEM, ACCOUNT, DOMAIN, SID, SIDTYPE)
     [EXT] Looks up ACCOUNT on SYSTEM and returns the domain name the SID
     and the SID type.

Win32::LookupAccountSID(SYSTEM, SID, ACCOUNT, DOMAIN, SIDTYPE)
     [EXT] Looks up SID on SYSTEM and returns the account name, domain
     name, and the SID type.

Win32::MsgBox(MESSAGE [, FLAGS [, TITLE]])
     [EXT] Create a dialogbox containing MESSAGE. FLAGS specifies the
     required icon and buttons according to the following table:

          0 = OK
          1 = OK and Cancel
          2 = Abort, Retry, and Ignore
          3 = Yes, No and Cancel
          4 = Yes and No
          5 = Retry and Cancel

          MB_ICONSTOP          "X" in a red circle
          MB_ICONQUESTION      question mark in a bubble
          MB_ICONEXCLAMATION   exclamation mark in a yellow triangle
          MB_ICONINFORMATION   "i" in a bubble

     TITLE specifies an optional window title. The default is "Perl".

     The function returns the menu id of the selected push button:

          0  Error

          1  OK
          2  Cancel
          3  Abort
          4  Retry
          5  Ignore
          6  Yes
          7  No

Win32::NodeName()
     [CORE] Returns the Microsoft Network node-name of the current machine.

Win32::RegisterServer(LIBRARYNAME)
     [EXT] Loads the DLL LIBRARYNAME and calls the function
     DllRegisterServer.

Win32::SetCwd(NEWDIRECTORY)
     [CORE] Sets the current active drive and directory. This function
     does not work with UNC paths, since the functionality required to
     required for such a feature is not available under Windows 95.

Win32::SetLastError(ERROR)
     [CORE] Sets the value of the last error encountered to ERROR. This is
     that value that will be returned by the Win32::GetLastError()
     function. This functions has been added for Perl 5.6.

Win32::Sleep(TIME)
     [CORE] Pauses for TIME milliseconds. The timeslices are made available
     to other processes and threads.

Win32::Spawn(COMMAND, ARGS, PID)
     [CORE] Spawns a new process using the supplied COMMAND, passing in
     arguments in the string ARGS. The pid of the new process is stored in
     PID. This function is deprecated. Please use the Win32::Process module
     instead.

Win32::UnregisterServer(LIBRARYNAME)
     [EXT] Loads the DLL LIBRARYNAME and calls the function
     DllUnregisterServer.

ADO Constants and a couple of helper functions
**********************************************

NAME
====

   Win32::ADO - ADO Constants and a couple of helper functions

SYNOPSIS
========

     use Win32::ADO qw/CheckDBErrors/;

DESCRIPTION
===========

   Not much to say. Simply provides all the ADO constants for your use,
like in VBScript (or JavaScript). This module is really deprecated in
favour of Win32::OLE::Const, and the proper ADO constants. Use that with
the following syntax:

     use Win32::OLE::Const;
     my $name = "Microsoft ActiveX Data Objects 2\\.0 Library";
     $ado_consts = Win32::OLE::Const->Load($name)
     || die "Unable to load Win32::OLE::Const ``$name'' ".Win32::OLE->LastError;

   And then use $ado_consts as a hash ref with the keys being the constant
names.

   Also contains CheckDBErrors, for doing ADO error checking. Pass it the
connection object and an empty array ref, as follows:

     CheckDBErrors($Conn, \@DBErrors) or die @DBErrors;

   Have fun...

AUTHOR
======

   Matt Sergeant, matt@sergeant.org

Perl Win32 API Import Facility
******************************

NAME
====

   Win32::API - Perl Win32 API Import Facility

SYNOPSIS
========

     use Win32::API;
     $function = new Win32::API(
         $library, $functionname, \@argumenttypes, $returntype,
     );
     $return = $function->Call(@arguments);

ABSTRACT
========

   With this module you can import and call arbitrary functions from
Win32's Dynamic Link Libraries (DLL), without having to write an XS
extension. Note, however, that this module can't do anything (parameters
input and output is limited to simpler cases), and anyway a regular XS
extension is always safer and faster.

   The current version of Win32::API is available at my website:

     http://dada.perl.it/

   It's also available on your nearest CPAN mirror (but allow a few days
for worldwide spreading of the latest version) reachable at:

     http://www.perl.com/CPAN/authors/Aldo_Calpini/

   A short example of how you can use this module (it just gets the PID of
the current process, eg. same as Perl's internal $$):

     use Win32::API;
     $GetPID = new Win32::API("kernel32", "GetCurrentProcessId", '', 'N');
     $PID = $GetPID->Call();

   The possibilities are nearly infinite (but not all are good :-).  Enjoy
it.

CREDITS
=======

   All the credits go to Andrea Frosini for the neat assembler trick that
makes this thing work.  A big thank you also to Gurusamy Sarathy for his
unvaluable help in XS development, and to all the Perl community for being
what it is.

DESCRIPTION
===========

   To use this module put the following line at the beginning of your
script:

     use Win32::API;

   You can now use the new() function of the Win32::API module to create a
new API object (see `IMPORTING A FUNCTION' in this node) and then invoke
the `Call()' method on this object to perform a call to the imported API
(see `CALLING AN IMPORTED FUNCTION' in this node).

IMPORTING A FUNCTION
--------------------

   You can import a function from a 32 bit Dynamic Link Library (DLL) file
with the new() function. This will create a Perl object that contains the
reference to that function, which you can later `Call()'.  You need to
pass 4 parameters:

  1. The name of the library from which you want to import the function.

  2. The name of the function (as exported by the library).

  3. The number and types of the arguments the function expects as input.

  4. The type of the value returned by the function.
        To better explain their meaning, let's suppose that we want to
import and call the Win32 API `GetTempPath()'.  This function is defined
in C as:

     DWORD WINAPI GetTempPathA( DWORD nBufferLength, LPSTR lpBuffer );

   This is documented in the *Win32 SDK Reference*; you can look for it on
the Microsoft's WWW site, or in your C compiler's documentation, if you
own one.

  1. The first parameter is the name of the library file that exports this
     function; our function resides in the `KERNEL32.DLL' system file.
     When specifying this name as parameter, the `.DLL' extension is
     implicit, and if no path is given, the file is searched through a
     couple of directories, including:

       1. The directory from which the application loaded.

       2. The current directory.

       3. The Windows system directory (eg. c:\windows\system or system32).

       4. The Windows directory (eg. c:\windows).

       5. The directories that are listed in the PATH environment variable.
          So, you don't have to write `C:\windows\system\kernel32.dll';
     only `kernel32' is enough:

          $GetTempPath = new Win32::API('kernel32', ...

  2. Now for the second parameter: the name of the function.  It must be
     written exactly as it is exported by the library (case is significant
     here).  If you are using Windows 95 or NT 4.0, you can use the *Quick
     View* command on the DLL file to see the function it exports.
     Remember that you can only import functions from 32 bit DLLs: in
     Quick View, the file's characteristics should report somewhere "32
     bit word machine"; as a rule of thumb, when you see that all the
     exported functions are in upper case, the DLL is a 16 bit one and you
     can't use it.  If their capitalization looks correct, then it's
     probably a 32 bit DLL.

     Also note that many Win32 APIs are exported twice, with the addition
     of a final A or W to their name, for - respectively - the ASCII and
     the Unicode version.  When a function name is not found, Win32::API
     will actually append an A to the name and try again; if the extension
     is built on a Unicode system, then it will try with the W instead.
     So our function name will be:

          $GetTempPath = new Win32::API('kernel32', 'GetTempPath', ...

     In our case `GetTempPath' is really loaded as `GetTempPathA'.

  3. The third parameter, the input parameter list, specifies how many
     arguments the function wants, and their types. It can be passed as a
     single string, in which each character represents one parameter, or
     as a list reference. The following forms are valid:

          "abcd"
          [a, b, c, d]
          \@LIST

     But those are not:

          (a, b, c, d)
          @LIST

     The number of characters, or elements in the list, specifies the
     number of parameters, and each character or element specifies the
     type of an argument; allowed types are:

    I:  value is an integer
    N:  value is a number (long)
    F:  value is a floating point number (float)
    D:  value is a double precision number (double)
    P:  value is a pointer (to a string, structure, etc...)
     Our function needs two parameters: a number (`DWORD') and a pointer
     to a string (`LPSTR'):

          $GetTempPath = new Win32::API('kernel32', 'GetTempPath', 'NP', ...

  4. The fourth and final parameter is the type of the value returned by
     the function. It can be one of the types seen above, plus another
     type named V (for void), used for functions that do not return a
     value.  In our example the value returned by GetTempPath() is a
     `DWORD', so our return type will be N:

          $GetTempPath = new Win32::API('kernel32', 'GetTempPath', 'NP', 'N');

     Now the line is complete, and the GetTempPath() API is ready to be
     used in Perl. Before calling it, you should test that $GetTempPath is
     defined, otherwise either the function or the library could not be
     loaded; in this case, $! will be set to the error message reported by
     Windows.  Our definition, with error checking added, should then look
     like this:

          $GetTempPath = new Win32::API('kernel32', 'GetTempPath', 'NP', 'N');
          if(not defined $GetTempPath) {
              die "Can't import API GetTempPath: $!\n";
          }

CALLING AN IMPORTED FUNCTION
----------------------------

   To effectively make a call to an imported function you must use the
Call() method on the Win32::API object you created.  Continuing with the
example from the previous paragraph, the GetTempPath() API can be called
using the method:

     $GetTempPath->Call(...

   Of course, parameters have to be passed as defined in the import phase.
In particular, if the number of parameters does not match (in the example,
if GetTempPath() is called with more or less than two parameters), Perl
will croak an error message and die.

   The two parameters needed here are the length of the buffer that will
hold the returned temporary path, and a pointer to the buffer itself.  For
numerical parameters, you can use either a constant expression or a
variable, while *for pointers you must use a variable name* (no Perl
references, just a plain variable name).  Also note that *memory must be
allocated before calling the function*, just like in C.  For example, to
pass a buffer of 80 characters to GetTempPath(), it must be initialized
before with:

     $lpBuffer = " " x 80;

   This allocates a string of 80 characters. If you don't do so, you'll
probably get `Runtime exception' errors, and generally nothing will work.
The call should therefore include:

     $lpBuffer = " " x 80;
     $GetTempPath->Call(80, $lpBuffer);

   And the result will be stored in the $lpBuffer variable.  Note that you
don't need to pass a reference to the variable (eg. you *don't need*
`\$lpBuffer'), even if its value will be set by the function.

   A little problem here is that Perl does not trim the variable, so
$lpBuffer will still contain 80 characters in return; the exceeding
characters will be spaces, because we said `" " x 80'.

   In this case we're lucky enough, because the value returned by the
GetTempPath() function is the length of the string, so to get the actual
temporary path we can write:

     $lpBuffer = " " x 80;
     $return = $GetTempPath->Call(80, $lpBuffer);
     $TempPath = substr($lpBuffer, 0, $return);

   If you don't know the length of the string, you can usually cut it at
the `\0' (ASCII zero) character, which is the string delimiter in C:

     $TempPath = ((split(/\0/, $lpBuffer))[0];

     # or

     $lpBuffer =~ s/\0.*$//;

   Another note: to pass a pointer to a structure in C, you have to pack()
the required elements in a variable. And of course, to access the values
stored in a structure, unpack() it as required.  A short example of how it
works: the `POINT' structure is defined in C as:

     typedef struct {
         LONG  x;
         LONG  y;
     } POINT;

   Thus, to call a function that uses a `POINT' structure you need the
following lines:

     $GetCursorPos = new Win32::API('user32', 'GetCursorPos', 'P', 'V');

     $lpPoint = pack('LL', 0, 0); # store two LONGs
     $GetCursorPos->Call($lpPoint);
     ($x, $y) = unpack('LL', $lpPoint); # get the actual values

   The rest is left as an exercise to the reader...

AUTHOR
======

   Aldo Calpini ( *dada@perl.it* ).

a Module for ASP (PerlScript) Programming
*****************************************

NAME
====

   Win32::ASP - a Module for ASP (PerlScript) Programming

SYNOPSIS
========

     use Win32::ASP;

     print "This is a test<BR><BR>";

     $PageName = GetFormValue('PageName');
     if($PageName eq 'Select a page...') {
     	die "Please go back and select a value from the Pages list";
     }

     print "You selected the ", $PageName, " page";
     exit;

DESCRIPTION
===========

   These routines are some I knocked together one day when I was saying the
following: "Why don't my "print" statements output to the browser?" and
"Why doesn't exit and die end my script?". So I started investigating how
I could overload the core functions. "print" is overloaded via the tie
mechanism (thanks to Eryq (`eryq@zeegee.com'), Zero G Inc. for the code
which I ripped from IO::Scalar). You can also get at print using the OO
mechanism with $Win32::ASP::SH->print(). Also added recently was code that
allowed cleanup stuff to be executed when you exit() or die(), this comes
in the form of the `AddDeathHook' function. The `BinaryWrite' function
simply wraps up unicode conversion and BinaryWrite in one call. Finally I
was annoyed that I couldn't just develop a script using GET and then
change to POST for release because of the difference in how the ASP code
handles the different formats, GetFormValue solves that one.

Installation instructions
-------------------------

   Usually ActiveState are pretty "on the ball" with CPAN archives, so it
should just be a matter of typing:

     ppm install Win32-ASP

   on the command line. Make sure you're connected to the internet first.

Function Reference
==================

Print LIST
----------

   Prints a string or comma separated list of strings to the browser. Use
as if you were using print in a CGI application. Print gets around ASP's
limitations of 128k in a single Response->Write call.

   Obsolete - use print instead.

   NB: print calls Print, so you could use either, but print is more
integrated with "the perl way".

DebugPrint LIST
---------------

   The same as Print except the output is between HTML comments so that
you can only see it with "view source". DebugPrint is not exported so you
have to use it as Win32::ASP::DebugPrint()

   This function is useful to debug your application. For example I use it
to print out SQL before it is executed.

HTMLPrint LIST
--------------

   The same as Print except the output is taken and encoded so that any
html tags appear as sent, i.e. < becomes &lt;, > becomes &gt; etc.
HTMLPrint is not exported, so use it like Win32::ASP::HTMLPrint.

   This function is useful for printing output that comes from a database
or a file, where you don't have total control over the input.

wprint LIST
-----------

   Obsolete: Use Print instead

die LIST
--------

   Prints the contents of LIST to the browser and then exits. die
automatically calls $Response->End for you, it also executes any cleanup
code you have added with `AddDeathHook'.

exit
----

   Exits the current script. $Response->End is called automatically for
you, and any cleanup code added with `AddDeathHook' is also called.

HTMLEncode LIST
---------------

   The same as HTMLPrint except the output is not printed but returned as
a scalar instead.  HTMLEncode is not exported, so use it like
Win32::ASP::HTMLEncode.

   This function is useful to handle output that comes from a database or
a file, where you don't have total control over the input.

   If an array ref is passed it uses the ref, otherwise it assumes an
array of scalars is used. Using a ref makes for less time spent passing
values back and forth, and is the prefered method.

GetFormValue EXPR [, EXPR]
--------------------------

   returns the value passed from a form (or non-form GET request). Use this
method if you want to be able to develop in GET mode (for ease of
debugging) and move to POST mode for release. The second (optional)
parameter is for getting multiple parameters as in:

     http://localhost/scripts/test.asp?Q=a&Q=b

   In the above GetFormValue("Q", 1) returns "a" and GetFormValue("Q", 2)
returns "b".

   GetFormValue will work in an array context too, returning all the values
for a particular parameter. For example with the above url:

     my @AllQs = GetFormValue('Q');

   will return an array: @AllQs = ('a', 'b')

   Also just added: If you call GetFormValue without any parameters it will
return a list of Form parameters in the same way that CGI.pm's param()
function does. This allows easy iteration over the form elements:

     foreach my $key (GetFormValue()) {
     	print "$key = ", GetFormValue($key), "<br>\n";
     }

   Also added a param() function which works exactly as GetFormValue does,
for compatibility with CGI.pm.

GetFormCount EXPR
-----------------

   returns the number of times EXPR appears in the request (Form or
QueryString).  Use this value as $i to iterate over GetFormValue(EXPR, $i).

   For example, url is:

     http://localhost/scripts/myscript.asp?Q=a&Q=b

   And code is:

     my $numQs = GetFormCount('Q');

   gives $numQs = 2

AddDeathHook LIST
-----------------

   This frightening sounding function allows you to have cleanup code
executed when you die or exit. For example you may want to disconnect from
your database if there is a problem:

     <%
     	my $Conn = $Server->CreateObject('ADODB.Connection');
     	$Conn->Open( "DSN=BADEV1;UID=sa;DATABASE=ProjAlloc" );
     	$Conn->BeginTrans();

     Win32::ASP::AddDeathHook( sub { $Conn->Close if $Conn; } );
     	%>

   Now when you die because of an error, your database connection will
close gracefully, instead of you having loads of rogue connections that
you have to kill by hand, or restart your database once a day.

   Death hooks should be executed on a graceful exit of the script too,
but I've been unable to confirm this. If anyone has any luck, let me know.

BinaryWrite LIST
----------------

   Performs the same function as `$Response->'`BinaryWrite()' but gets
around Perl's lack of unicode support, and the null padding it uses to get
around this.

   Example:

     Win32::ASP::BinaryWrite($val);

SetCookie Name, Value [, HASH]
------------------------------

   Sets the cookie Name with the value Value. HASH is option, and contains
any of the following optional parameters:

   * -expires => A CGI.pm style expires value (see the CGI.pm docs for
     header() for this).

   * -domain => a domain in the style ".matt.com" that the cookie is
     returned to.

   * -path => a path that the cookie is returned to.

   * -secure => cookie only gets returned under SSL if this is true.

   If Value is a hash ref, then it creates a cookie dictionary. (see either
the ASP docs, or my Introduction to PerlScript for more info on Cookie
Dictionaries).

   Example:

     Win32::ASP::SetCookie("Matt", "Sergeant", ( -expires => "+3h",
     	-domain => ".matt.com",
     	-path => "/users/matt",
     	-secure => 0 ));

Experimental STDIN support
==========================

   Version 2.10 adds experimental support for STDIN processing. You should
be able to go `while(<STDIN') {...}> now. However, I don't have an NT
machine to test this on (I dumped NT in favour of Linux a while back), so
it's caveat emptor - and feed me with bug reports if you want it to work.
The idea is that now CGI.pm should be able to read form data and file
uploads appropriately. If it works, let me know. If it doesn't, let me
know too :)

an abstract parent class for representing database records
**********************************************************

NAME
====

   Win32::ASP::DBRecord - an abstract parent class for representing
database records

SYNOPSIS
========

DESCRIPTION
===========

   The main purpose of `Win32::ASP::DBRecord'is to be subclassed.  It
implements a generic set of default behavior for the purpose of reading a
record from a table, displaying that record in HTML, allowing edits to it,
and writing that record back to the table.  It relies heavily upon
Win32::ASP::Field objects, which are used to provide an object-oriented
interface to the most important class data for a `Win32::ASP::DBRecord'
subclass - the fields possessed by the record represented by the class.

Internal Data Structure
-----------------------

   The internal data structure of a instance of `Win32::ASP::DBRecord'
consists of the following elements, all optional:

orig
     This is a reference to a hash indexed on field names and storing data
     read from the database.

edit
     This is a reference to a hash indexed on field names and storing the
     currently modified data.

child_dbgroup
     There can be any number of child groups and these are stored at the
     root of the `Win32::ASP::DBRecord' object, not within orig or edit.
     See _CHILDREN for more information.

Class Methods
-------------

   Class methods were used to implement access to class properties.  Since
Perl doesn't enforce a distinction between class and instance methods,
these methods can be called on both class names and on instances of the
class, which ends up being incredibly useful.  I strongly recommend against
ever calling these methods using subroutine notation (i.e. `&amp;_DB' or
`&amp;_PRIMARY_KEY').  Perl methods execute in the namespace in which they
were defined, which means that if you further subclass and define a new
implementation of those methods, any methods you don't override that were
in the parent class will call the parent class's versions of those
methods.  That's bad.  Always call these methods with the arrow notation
and you'll be safe.

Mandatory Class Methods
.......................

   These class methods will be overridden in every child class.

_DB
     The _DB method should return the `Win32::ASP::DB' (or subclass
     there-of) object that is used for database access.  A frequent
     implementation looks like this:

          sub _DB {
            return $main::TheDB;
          }

_FRIENDLY
     The _FRIENDLY method should return a friendly name expressing what
     sorts of things these records are.  This friendly name may get used
     in certain error messages (in particular,
     `Win32::ASP::Error::Field::group_wrapper').  For instance, the
     _FRIENDLY method for line items on an invoice might return "Line
     Item".  An error message could then say, "There was an error in Line
     Item 4.  The error was . . ."

_READ_SRC
     The _READ_SRC method should return the name of the table or view that
     should be used to read records from the database.  Frequently a view
     will be defined on the SQL Server to include information from various
     lookup tables.

_WRITE_SRC
     The _WRITE_SRC method should return the name of the table that should
     be used to write records to the database.

_PRIMARY_KEY
     The _PRIMARY_KEY method should return a list of the field names in
     the Primary Key for the table.  Of note, this returns a list, not a
     *reference to an array*.  The order that the fields are in
     _PRIMARY_KEY is also the order in which the values will be specified
     for identifying records for reading them from the database.

_FIELDS
     The _FIELDS method should return a reference to a hash of
     `Win32::ASP::Field' objects, indexed on the field names.  Of note,
     for performance reasons the method is usually implemented like so:

          sub _FIELDS {
            return $MyStuff::MyRecord::fields;
          }

          $MyStuff::MyRecord::fields = {

          Win32::ASP::Field->new(
          			name => 'RecordID',
          			sec  => 'ro',
          			type => 'int',
          			desc => 'Record ID',
          		),

          Win32::ASP::Field->new(
            name => 'RecordRemarks',
            sec  => 'rw',
            type => 'text',
          ),

          };

Optional Class Methods
......................

   These class methods can be overriden in a child class.

_ACTIONS
     The _ACTIONS method should return a reference to a hash of
     `Win32::ASP::Action' objects, indexed on the action names.  Actions
     are used to implement things that users do to records.  For instance,
     a user might want to Edit a record.  Some users might not have
     permissions to edit some records though, and so it makes sense to
     implement an object that is responsible for determining whether a
     given user is able to execute a given action in a given circumstance.
     The action is also responsible for displaying the appropriate HTML
     for a link that implements the action, knowing how to warn a user
     before the action is carried out, etc.  For more information, see the
     `Win32::ASP::Action' class and its various sub-classes.

     Of note, for performance reasons the method is usually implemented
     like so:

          sub _ACTIONS {
            return $MyStuff::MyRecord::actions;
          }

          $MyStuff::MyRecord::actions = {

          Win32::ASP::Action::Edit->new,

          Win32::ASP::Action::Delete->new,

          Win32::ASP::Action->new(
            name   => 'cancel',
            label  => 'Cancel',
            . . .
          ),

          };

_CHILDREN
     Some records quite logically have child records.  For instance, a
     Purchase Order generally has a number of line-items on it, and this
     are usually implemented using a table that is 1:M linked to the
     Purchase Order table.  Within `Win32::ASP::DBRecord' class objects,
     this is implemented through a reference to a
     `Win32::ASP::DBRecordGroup' class object that contains the child
     records.

     The implementation normally looks something like this:

          sub _CHILDREN {
            return $MyStuff::MyRecord::children;
          }

          $MyStuff::MyRecord::children = {

          child_records => {
            type  => 'MyStuff::MyChildRecordGroup',
            pkext => 'ChildID',
          },

          };

     The implication of the above is that `MyStuff::MyRecord' objects have
     a group of associated `MyStuff::MyChildRecord' objects, which are
     accessed through a `MyStuff::MyChildRecordGroup' object.  The
     reference to that object will be stored in
     `$self-&gt;{child_records}'.  The primary key of the
     `MyStuff::MyChildRecord' objects will be the primary key for the
     `MyStuff::MyRecord' objects plus the added field '`ChildID''.  The
     index on the hash is referred to hereafter as the 'child group name'.

Class Methods you probably won't override
.........................................

   There is only one of these.

ADD_FIELDS
     This method is called on the class in order to add new fields.  This
     is usually used by `Win32::ASP::DBRecordGroup' objects to add
     `Win32::ASP::Field::dispmeta' objects to the underlying
     `Win32::ASP::DBRecord' object.  `Win32::ASP::Field::dispmeta' objects
     are frequently used to display more than one field in a column when
     displaying a table of records (i.e. one field above the other).

Instance Methods
----------------

new
...

   This is a basic new method.  Simply creates an anonymous hash and
returns a reference.  The new method is not responsible for reading data
or anything else.  Just creating a new record object.  You will probably
not need to override this method.

init
....

   This is used for initializing new records prior to being edited.  The
code in ASP land for throwing up the edit screen when creating a new
record looks something like this:

     use MyStuff::MyRecord;

     $record = MyStuff::MyRecord->new;
     $record->init;
     $record->edit;
     $data = 'edit';
     $viewtype = 'edit';

   This is then followed by the <FORM> section.

   Note that init modifies orig, not edit.  Once orig is modified, the
edit method is used to place the record in edit mode.

read
....

   The read method is used, coincidentally, to read a record from the
database.  It should be passed an array comprised of the primary key
values for the record desired.

   The read method is responsible for reading all appropriate values for
the record, and for reading any child records for which the child group
name shows up in `$self'.  The implications of this are important for
providing appropriate behavior when update is called.

   The actual reading in of data from the ADO Recordset object is
implemented by _read.  This is done so that `Win32::ASP::DBRecordGroup'
object can execute a query and then make calls to _read for each record
returned.

_read
.....

   The _read method is responsible for reading the data from the ADO
Recordset object ($result) and entering it into the object.  It does this
by looping over the fields in _FIELDS and calling read on each of them
with the appropriate parameters.  Note that _read accepts the optional
parameter $columns and passes this along in the call to read on the
`Win32::ASP::Field' objects.  This is to minimize unneeded value retrieval
calls when `Win32::ASP::DBRecordGroup' objects are only interested in a
few fields.  If $columns is a reference to a hash, it will be interpreted
as a list of the fieldnames of note.  However, to allow for more
flexibility in implementation, the decision as to whether or not the field
will actually be read is still left up to the `Win32::ASP::Field' object.

   In addition, _read is responsible for calling can_view on the resultant
record object to see whether the user is allowed to view this record.  If
can_view returns false, _read throws a
`Win32::ASP::Error::DBRecord::no_permission' exception

read_deep
.........

   Since the read method is responsible for reading in all child records
for which there is an entry in `$self', the read_deep method simply
creates an entry in the `$self' hash for each key in the hash returned
from _CHILDREN.

post
....

   The post method takes data returned from a POST action and enters it
into the `Win32::ASP::DBRecord' object.  Of note, post takes a `$row' as a
parameter.  This is used to identify which row of a table is of interest
when being used for editing `Win32::ASP::DBRecordGroup' objects.

   The method simply calls post on each of the `Win32::ASP::Field' objects.

   It also posts the data for all of the child records.  The presumption
is that if the records are really child records, one would generally edit
the whole mess at one time and that they will then want to be posted.  So
it creates new child objects of the appropriate
`Win32::ASP::DBRecordGroup' classes and calls post on them.

insert
......

   The insert method is responsible for taking the data and writing it to
the database.  If there are child records associated with object, those
are written as well.  Everything is wrapped in a transaction so that a
failure to write child records for any reason will roll back the
transaction.

   The insert method is passed a list of fields that should always be
written.  By default, the insert method will only write values that are
considered editable (as determined by calling can_edit on the field
object) <Bor> that show up in the passed list of fields.  This enables one
to define certain fields as read only, but still modify them within the
context of actions or other code.  Also, values are only written if they
are defined in the `$self-&gt;{edit}' hash.  It is generally considered
poor form to write NULL values to the database (especially in SQL Server
6.5 as this results in a 2K page being allocated for NULL text objects:).

   The values are prepared for inserting by calling as_write_pair on the
`Win32::ASP::Field' objects.  The array of write pairs is then passed to
the insert method on the `Win32::DB' object.  The return from that call is
the ADO Recordset object, which is then passed to set_inserted so that
auto generated Primary Key values can be retrieved

   It then deals with the child record groups as needed.  The defined
objects have set_prop used to propagate the primary key values onto the
child objects.  The insert method can then be called to insert the entire
group.

   The insert method returns a list of all write pairs that were inserted.
This so that implementations that override insert can make use of that
information (this is most commonly done for logging purposes - other
records are inserted into logging tables to indicate who did what when,
and having insert return the information makes that much easier.).

set_inserted
............

   This method is responsible for retrieving the Primary Key values on
newly inserted records.  Most useful when one of those Primary Key values
is an autonumber field.

update
......

   This is the single largest, ugliest morass of code in
`Win32::ASP::DBRecord'.  Yeach.  Think of it as a slightly uglier insert,
though, and it's a little easier to understand.

   First we start a transaction and call can_update.  The can_update
method will call read in turn (no way to know if we can update a record if
we don't know what was in it).

   If can_update returns false, we throw a
`Win32::ASP::Error::DBRecord::no_permission' exception and get out of
here.  Otherwise, we procede to call `verify_record' and
`verify_timestamp'.  If neither of those throw exceptions, we continue on.

   The method then creates <C$constraint>, a SQL WHERE condition suitable
for indentifying the record of interest based on the Primary Key.

   It then starts building a list of write pairs.  It also adds those
pairs to `@retvals', which will contain a list of fields, new values, and
old values for any field that changed.  Note that we only update fields
for which can_edit returns true and that have changed, or that are
mentioned in `@ext_fields', the passed parameter list.  Fields updated as
a result of being in `@ext_fields' are not mentioned in the list of
changed fields that is returned.

BUGS
====

Triple level children
     The implementation of child records does not deal properly with
     situation in which the child records have children themselves.  This
     issue will be resolved when I have time.

an abstract parent class for representing groups of database records
********************************************************************

NAME
====

   Win32::ASP::DBRecordGroup - an abstract parent class for representing
groups of database records

SYNOPSIS
========

DESCRIPTION
===========

   The main purpose of `Win32::ASP::DBRecordGroup'is to be subclassed.  It
implements a generic set of default behavior for the purpose of reading a
group of records from a table, displaying that group of records in an HTML
table, and allowing edits to that group if applicable.  All
`Win32::ASP::DBRecordGroup' classes rely upon a `Win32::ASP::DBRecord'
class that implements the underlying record.

Internal Data Structure
-----------------------

   The internal data structure of a instance of
`Win32::ASP::DBRecordGroup' consists of the following elements, all
optional:

orig
     This is a reference to an array of DBRecord objects storing data read
     from the database.

edit
     This is a reference to an array of DBRecord objects storing the
     currently modified data.

Class Methods
-------------

   Class methods were used to implement access to class properties.  Since
Perl doesn't enforce a distinction between class and instance methods,
these methods can be called on both class names and on instances of the
class, which ends up being incredibly useful.  I strongly recommend against
ever calling these methods using subroutine notation (i.e. `&amp;_DB' or
`&amp;_PRIMARY_KEY').  Perl methods execute in the namespace in which they
were defined, which means that if you further subclass and define a new
implementation of those methods, any methods you don't override that were
in the parent class will call the parent class's versions of those
methods.  That's bad.  Always call these methods with the arrow notation
and you'll be safe.

Mandatory Class Methods
.......................

   These class methods will be overridden in every child class.

_DB
     The _DB method should return the `Win32::ASP::DB' (or subclass
     there-of) object that is used for database access.  A frequent
     implementation looks like this:

          sub _DB {
            return $main::TheDB;
          }

_TYPE
     The _TYPE method should return the name of the `Win32::ASP::DBRecord'
     subclass that implements the underlying records for this
     DBRecordGroup object.

_QUERY_METAS
     The _QUERY_METAS method should return a reference to a hash of
     subroutines that implement more complicated querying behavior.  The
     subroutines will be passed the appropriate query specification and
     should return legal SQL for inclusion within a query.  Of note, for
     performance reasons the method is usually implemented like so:

          sub _QUERY_METAS {
            return $MyStuff::MyRecordGroup::query_metas;
          }

          $MyStuff::MyRecordGroup::query_metas = {

          Status => sub {
            my($values) = @_;
            $values or return;
            return "Status LIKE '[$values]'";
          },

          };

     The above Status query_meta presumes a single character status field
     and that the passed value indicates a list of desired status values.
     For instance, the status values might be N for new records, P for in
     process records, and F for finished records.  Using the above
     query_meta, a user could query for `Status=NP', which would indicate
     they desired new and in process records.  They could get the same
     results by querying for `!F'.

     Note that there is a security hole in the above code - if a user
     queries for `Status=N] GO do_something_ugly_here', they will
     effectively "jump" out of the LIKE statement and may be able to
     execute arbitrary SQL code.  Defending against this possibility is
     left as an excercise for the reader.

Optional Class Methods
......................

   These class methods can be overriden in a child class.

_MIN_COUNT
     The _MIN_COUNT method defines the minimum number of records to
     display when allowing the user to edit a group of records.

_NEW_COUNT
     The _NEW_COUNT method defines the minimum number of blank records to
     display when allowing the user to edit a group of records.

Instance Methods
----------------

new
...

   This is a basic new method.  It simply creates an anonymous hash and
returns a reference.  The new method is not responsible for reading data
or anything else.  Just creating a new record group object.  You will
probably not need to override this method.

query
.....

   This is the heart of the DBRecordGroup class.  The method is passed
three parameters: a reference to a hash of constraints, a string
specifying how to order the results, and a string specifying a list of
columns to retrieve.

   The hash of constraints should be indexed on the field name (or
query_meta name).  If the index references a query_meta, the value will be
passed to the query_meta subroutine.  If the index doesn't reference a
query_meta, the field will be tested for equality with the specified value.
The specified value will be formatted by the field's as_sql method before
being included in the SQL.  All of the constraints will be ANDed together
to form the WHERE clause in the SQL.

   The order string should be a comma separated list of field names.  Bare
field names will be sorted in ascending order; field names preceded by a
minus sign will be sorted in descending order.

   The columns string should be one of three things: empty, an asterisk,
or a comma separated list of field names.  If the string is absent or an
asterisk, the query will retrieve all the columns  If a comma separated
list is specified, the query will only retrieve those columns.  The
advantage of this is that queries can be optimized to return only the
information that will be displayed to the user.  Keep in mind, however,
that if the DBRecord object requires specific fields in order to make
determinations about viewability or the like, those columns need to be
specified in the column list.  As a result, query is frequently overriden
to automatically append those columns to the column list before call
`SUPER::query'.

   After setting up the SQL for the query, query calls `exec_sql' on the
appropriate Win32::ASP::DB object (determined by calling `< $self-'_DB
>>).  It then iterates over the result set returned, creating new DBRecord
objects of the appropriate class and calling _read on them.  The call to
_read is wrapped in a try block - if the user doesn't have rights to view
the record, _read will throw an exception.  That exception will be trapped
and the record won't be be appended to the array of DBRecord objects.

   Another common modification to query involves adding constraints to all
queries to explicitly call query_metas that are responsible for
ascertaining viewability.  This can greatly improve performance - if the
user asks for every record in the system, the query handles the weeding out
of those records that are not viewable, rather than reading the data and
letting _read throw an exception.  Again, this can be easily handled by
overriding the method and then calling `SUPER::query'.

query_deep
..........

index_hash
..........

insert
......

delete
......

should_update
.............

update
......

edit
....

merge_inner
...........

split_inner
...........

post
....

add_extras
..........

set_prop
........

gen_table
.........

get_QS_constraints
..................

make_QS_constraints
...................

debug_dump
..........

an abstract parent class for implementing exceptions in Win32::ASP::DB
**********************************************************************

NAME
====

   Win32::ASP::Error - an abstract parent class for implementing
exceptions in Win32::ASP::DB

SYNOPSIS
========

     use Win32::ASP::Error;

     package Win32::ASP::Error::DBRecord;
     @Win32::ASP::Error::DBRecord::ISA = qw/Win32::ASP::Error/;

     package Win32::ASP::Error::DBRecord::no_permission;
     @Win32::ASP::Error::DBRecord::no_permission::ISA = qw/Win32::ASP::Error::DBRecord/;

     #Parameters:  action, identifier

     sub _as_html {
       my $self = shift;

     my $action = $self->action;
     my $identifier = $self->identifier;
     return <<ENDHTML;
       You are not allowed to $action $identifier.<P>
       ENDHTML
       }

     throw Win32::ASP::Error::DBRecord::no_permission (action => 'view', identifier => $identifier);

DESCRIPTION
===========

Overview
--------

   `Win32::ASP::Error' is the abstract parent class used for implementing
exceptions in the Win32::ASP::DB system.  It inherits from
`Error::Unhandled', which allows exceptions to handle themselves if the
calling program leaves the exception unhandled, and `Class::SelfMethods',
which allows instances to override methods and provides for
method/attribute calling equivalence.

Utilization
-----------

   In general, subclasses of `Win32::ASP::Error' implement the as_html
method (properly implemented as `_as_html' so that instances can override
it if necessary - see the `Class::SelfMethods' documentation for more
explanation).  This method should return properly formatted HTML that
describes the condition that led to the exception and, if applicable,
provides instruction to the user about how to rectify the problem.

   The return value from the title method is used for the <TITLE> block in
the returned web page.

a extension to Win32::ASP that provides more methods
****************************************************

NAME
====

   Win32::ASP::Extras - a extension to Win32::ASP that provides more
methods

SYNOPSIS
========

     use Win32::ASP::Extras;

     Win32::ASP::Set('my_hash',
         { fullname => 'Toby Everett',
           username => 'EverettT',
           role => 'Editor'
         } );

     Win32::ASP::Redirect('userinfo.asp', reason => "I just feel like redirecting.");

     exit;

     use Win32::ASP::Extras;

     my $userinfo = Win32::ASP::Get('my_hash');

     foreach my $i (sort keys %{$userinfo}) {
       $main::Response->Write("$i $userinfo->{$i}<P>\n");
     }

     exit;

DESCRIPTION
===========

Installation instructions
-------------------------

   This installs with MakeMaker.

   To install via MakeMaker, it's the usual procedure - download from CPAN,
extract, type "perl Makefile.PL", "nmake" then "nmake install". Don't do
an "nmake test" because the ASP objects won't be available and so won't
work properly.

Function Reference
==================

use Win32::ASP::Extras;
-----------------------

   This imports the following methods into the Win32::ASP namespace.
There is no need to `use Win32::ASP;' in order to use Win32::ASP::Extras;.
The modules are independent of each other and only share a namespace.

   To be more precise, `use Win32::ASP::Extras'' loads everything into
`Win32::ASP::Extras' and then aliases the symbol table entries over into
`Win32::ASP'.  This is to avoid any weirdness with respect to AutoLoader.

FormatURL Url [, HASH]
----------------------

   This is designed to take a base URL and a hash of parameters and return
the properly assembled URL.  It does, however, have some weird behavior.

   If the first character of the URL *is not* a forward slash and
`$main::WEBROOT' is defined, the function will automatically prepend
`$main::WEBROOT/' to the URL.  This has the side effect of making 95% of
URLs *absolute* relative to `$main::WEBROOT', if it is defined.  This
makes it easier to move Webs around just by changing `$main::WEBROOT'.

   If the first character of the URL *is* a forward slash, the URL is left
unchanged.

   If the first characters are "`./'", the "`./'" is stripped off and the
URL left unchanged.  This allows one to specify relative URLs - just put a
"`./'" in front of it.

   The parameters are URLEncoded, but the keys for them are not.  The
resultant parameter list is HTML encoded so that `&timestamp' doesn't
become `xtamp' (`&times;' encodes a multiplication symbol).

QueryStringList
---------------

   This returns a list of QueryString keys and values.  It does not deal
with multi-valued parameters.

Redirect Url [, HASH]
---------------------

   A safe redirect that redirects and then absolutely and positively
terminates your program.  If you thought `$Response-'Redirect> behaved
liked die and were disappointed to discover it didn't, mourn no longer.

   It takes a base URL and a hash of parameters.  The URL will be built
using `FormatURL'.

MyURL
-----

   This return the URL used to access the current page, including its
QueryString.  Because it uses QueryStringList, it doesn't properly deal
with multi-valued parameters.

CreatePassURLPair
-----------------

   The function returns both `passurl' and the result from calling MyURL.
The return values are suitable for inclusion in a hash for passing to
`FormatURL'.  The PassURL functions are generally used for dealing with
expired sessions.  If the session expires, the `Redirect' is passed
CreatePassURLPair for the parameters.  That page then explains to the user
what is going on and has a link back to the login page along with
PassURLPair.  The login page can then use GetPassURL to extract the URL
from the QueryString and redirect to that URL.

GetPassURL
----------

   This extracts the `passurl' value from the QueryString.

PassURLPair
-----------

   This returns `passurl' along with the result from calling GetPassURL.
The return values are suitable for inclusion in a hash for passing to
`FormatURL'.

StampPage
---------

   This returns HTML that says:

     Refresh this page.

   The text `this page' is a link to the results of MyURL.

Set
---

   Set and Get can be used to store arbitrary Perl objects in `$Session'.
It uses Data::Dumper to store things and eval to retrieve them.  Notice
that this is safe *only* because *we* are the only ones who can store
stuff in `$Session'.

   <LECTURE_MODE>

   Do *NOT*, I repeat, do *NOT* use Data::Dumper to serialize a Perl
object and then stuff it in a user's cookie, presuming that you can then
use eval to extract it when they pass it back to you. If you do, you
deserve to have someone stuff `system("del /s *.*")' or some such funny
Perl code in that cookie and then visit your web site.  Never, ever, ever
use eval on code that comes from an untrusted source.  If you need to do
so for some strange reason, take a look at the Safe module, but be careful.

   </LECTURE_MODE>

   Oh, the call takes two parameters, the name to store it under and the
thing to store (can be a reference to a hash or some other neat goodie).
Keep in mind that references to CODE objects (i.e. anonymous subroutines)
or `Win32::OLE' objects or anything like that will not make it.

Get
---

   Takes a parameter and returns the thing.  Both Set and Get use the same
memoization cache to improve performance.  Take care if you modify the
thing you get back from Get - future calls to Get will return the modified
thing (even though it hasn't been changed in `$Session').  Calls to Set
empty the memoization cache so that the next call to Get will reload it
from `$Session' and add it to the cache.

an abstract parent class for representing database fields, used by Win32::ASP::DBRecord
***************************************************************************************

NAME
====

   Win32::ASP::Field - an abstract parent class for representing database
fields, used by Win32::ASP::DBRecord

SYNOPSIS
========

     use Win32::ASP::Field;

     %hash = (
         Win32::ASP::Field->new(
     		name => 'RecordID',
     		sec  => 'ro',
     		type => 'int',
     		desc => 'Record ID',
     	),

     Win32::ASP::Field->new(
     			name => 'SemiSecureField',
     			sec  => sub {
     				my $self = shift;
     				my($record) = @_;

     return $record->role eq 'admin' ? 'rw' : 'ro';
     			},
     			type => 'varchar',
     			desc => 'Semi Secure Field',
     		),

     Win32::ASP::Field->new(
     			name => 'Remarks',
     			sec  => 'rw',
     			type => 'text',
     		),
     	);

DESCRIPTION
===========

Background
----------

   Field objects are very strange Perl objects.  Perl is class based, not
prototype based.  Unfortunately, unless you want to create a separate
class for every mildly wierd field in your database, a class based system
is sub-optimal for our purposes.  To get around this I implemented a
"weak" form of a prototype based language.

   The major parent is `Class::SelfMethods'.  It provides an AUTOLOAD that
implements the desired behavior.  In a nutshell, when asked to resolve a
method it does the following:

   * First it checks for whether the object has a property with that name.
     If it does and the property is not a code reference, it returns the
     value.

   * If the property is a code reference, it evaluates the code reference
     on the object with the passed parameters.  This means that you can
     define "instance" (not class) methods by placing anonymous
     subroutines in the instance.  These override the class method. If you
     need to call the equivalent of `SUPER::', call `_method' on the
     object.

   * If the property does not exist, it attempts to call `_method' on the
     object.  Thus, calling read on an instance calls the _read method in
     the class definition if there is no matching property.  If the _read
     method exists, AUTOLOAD will not get called again.  On the other hand
     if it does not exist, rather than call `__read', the AUTOLOAD
     subroutine will return empty-handed. This way, if the desired
     property is not defined for the object, undef will be the default
     behavior.

   It is important to understand the above "hierarchy of behavior" if you
are to make full use of the customizability of Field objects.  In a
nutshell, when creating new proper classes all methods should be defined
with a leading underscore, but called without the leading underscore, so
that they can be over-ridden as needed.  One should never directly access
the hash `$self', but always let AUTOLOAD access it by calling the method
with that name.  That way instance variables can be implemented as
subroutines if need be.  It also makes it easy to provide "default"
behavior by implementing a method.  The only time a method should be
called with a leading underscore is when an instance-defined method needs
to call the method it is over-riding.

Methods
-------

   Except for new, which is discussed here, the majority of these are
farther down under `' in this node.

new
...

   The new method for `Win32::ASP::Field' is rather strange.  It returns
two values - the name along with the `Win32::ASP::Field' object.  This
makes it much easier to create hashes of `Win32::ASP::Field' objects.  The
parameters passed to the new method should be the desired properties for
the new object.

   One oddity is that the type property will be used to autoload
`Win32::ASP::Field::'type and the returned object will be of that class.
This makes it possible to create arbitrary `Win32::ASP::Field' objects
without an explicit list of use statements at the top.

   For an example of how to use new, see the `' in this node at the top of
the POD.

   For a discussion of how new treats passed parameters that have a name
that starts with an underscore, see `Meta properties|' in this node.

Properties
----------

Required
........

name
     This is the name of the field.  Unlike the other properties, it is
     not passed the `$record' in question.

sec
     This specified whether the field is read-write (`'rw'') or read-only
     (`'ro'').  Note, you can implement this as a subroutine and it gets
     passed `$record'.  If it is not implemented or returns a value not
     equal to one of the above, it is presumed that the value is not
     accessible.  Note that `$record' may not be fully formed when seq is
     called in _read.  You may wish to return `'ro'' if in doubt.

Optional
........

reqd
     If this returns true than the field is required to be filled out when
     writing.

desc
     This is the friendly description for the object.  This gets used for
     column headings in tables.  If not specified, it defaults to name.

help
     This is the text that displays in the browser status area when the
     mouse is placed over the edit area in edit mode

size
     This is used for TEXT and TEXTAREA form fields to define their width.

maxl
     This is used to specify the maximum length of a varchar field.

textrows
     This is used to specify the number of rows for a TEXTAREA form field.

formname
     This is used to deal with situations where a field in a child record
     has the same name as a field in a parent record.  This would, of
     course, complicate the resultant HTML form.  To deal with this
     situation, specify formname.  If not specified, the default method
     will return name.

writename
     This is used to indicate the actual SQL field used for recording. It
     is frequently used in conjunction with as_write.  It can sometimes be
     very handy to use a subroutine for writename.  As a subroutine, it
     gets passed $value.  If it needs the whole record to make its
     decision, you will need to intercept the as_write_pair method.

     Say, for instance, that you have a logging record with a `SmallValue'
     field that is a 50 character `varchar' and a `LargeValue' field that
     is a text field.  The idea is that for short strings you won't incur
     much cost from the `LargeValue' field because uninitialized text
     fields don't create a 2K page.  If the string is longer, however, you
     want to write to the LargeValue field.  If the percentage of short
     strings is 50%, the solution would save ~49.7% on space requirements.
     The penalty of the unused `varchar' for the long strings is small
     contrasted with the savings by not using the text field on the short
     ones.

     In that situation, one might implement writename like this:

          writename => sub {
          	my $self = shift;
              my($value) = @_;

          return length($value) > 50 ? 'LargeValue' : 'SmallValue';
          	}

     The discussion of read includes an appropriate instance level method
     to round out this demonstration. No implementation of as_write is
     required because the formatting for `varchar' and text fields is the
     same.

option_list
     This should return an anonymous array of options that will be
     provided to the user when editing the field.  Its presence indicates
     to as_html_edit_rw the intention to use as_html_options.

Meta
....

   Meta properties are a funky way of executing additional code at the
time of object creation.  The new method accepts a parameter list and
returns two values - the name of the field and the field object itself.
The advantage of this is that it makes creating a hash of field object much
easier.  On the other hand, it requires some excessively fancy notation to
make method calls on the newly created object while in the hash specifier.
However, there's any easy way to indicate when you want a parameter to be
a method call.  Since parameters don't start with underscores and all
actual implementations in class code do, it makes sense to start meta
properties with an underscore.  The new method simply scans the list of
parameters for those that start with an underscore and strips them out of
the parameter hash for later use.  The value of the parameter should be an
anonymous array of parameters to the method.

   Typical use of meta properties is to provide code for creating commonly
used instance methods.

_standard_option_list
     This meta property sets up writename, as_write, and option_list for
     use with a fairly standard option list that uses a "hidden" code
     field and a lookup table that has friendly descriptions.  Example
     usage might look like so:

          _standard_option_list => [
          	class     => 'MyDatabase::MyRecord',
          	writename => 'LookupCode',
          	table     => 'LookupCodes',
          	field     => 'LookupCode',
          	desc      => 'Description'
          ],

     Note that although the method is expecting a hash of properties, the
     parameter list is stored in an anonymous array when passed in during
     the new method.

     Of note, the as_write and option_list methods are implemented to help
     minimize SQL traffic. The first call to the option_list method will
     result in setting `$self->{option_list}' to a reference to the
     anonymous array before returning that array.  Further calls will
     automatically return that array based on the behavior of the AUTOLOAD
     method in `Class::SelfMethods'.  See the entry for group for a
     discussion of the behavior for as_write.

    class
          This specifies the `Win32::ASP::DBRecord' subclass to which this
          field belongs.  This will be used later to access the _FIELDS
          hash and the _DB object.

    writename
          This specifies the field within the record object that will be
          written.

    table
          This specifies the name of the table that contains the list of
          codes and the friendly descriptions.

    field
          This specifies the name of the field within that table that
          contains the code.  Frequently, but not always, this will be the
          same as writename.

    desc
          This specifies the name of the description field in the lookup
          table.

    group
          This specifies whether there are likely to be multiple calls to
          as_write.  If not present or set to a false value, as_write will
          only lookup the passed value.  If set to a true value, the first
          call to as_write will lookup all the codes and store them in a
          hash for further reference.  This will reduce SQL traffic in
          situations where an `Win32::ASP::DBRecord' object is used within
          a `Win32::ASP::DBRecordGroup' for editing records.
          Unfortunately, the code isn't smart enough to know whether it is
          being used in a group or on its own, so you have to hard code
          it.  On the other hand, if you need that level of flexibility,
          you can roll your own methods.

INTERNALS
---------

   This is where internal methods are discussed with an eye towards
over-riding them if need be.

Checkers
........

   These are quick little methods to provided standardized ways of
checking certain boolean "properties"

can_view
     The can_view method is used to determine if someone has view
     privileges on a given field. The default implementation, `_can_view',
     tests `$self->sec($record)' for equivalence with '`ro'' or 'rw'.

     Implementations can expect the $record as a parameter and should
     return 1 or 0 as appropriate.

can_edit
     The can_edit method is used to determine if someone has edit
     privileges on a given field. The default implementation, `_can_edit',
     tests `$self->sec($record)' for equivalence with 'rw'.

     Implementations can expect the $record as a parameter and should
     return 1 or 0 as appropriate.

is_option_list
     The is_option_list method is used to determine if a field should be
     displayed using an option list.  The default implementation,
     `_is_option_list', tests for the existence of `$self->{option_list}'.
     This is technically verboten, but it's a performance improvement
     over returning the full option_list in order to test for it.  If you
     implement a subclass that implements option_list, you should also
     implement `_is_option_list'.

     Implementations can expect $record and $data as a parameter and
     should return 1 or 0 as appropriate.

Loaders
.......

   These methods are used to load a record with a given field.

read
     The read method is used to read a specific field out of `$results'
     into `$record'.  The default implementation, _read, first calls
     `$self->can_view' and then retrieves the appropriate value (if
     present) from the results set and places it in `$record->{orig}' as
     appropriate.

     In addition to the parameters `$record', the `Win32::ASP::DBRecord'
     that will receive the data, and `$results', the ADO Recordset object
     containing the data, the read method is passed the parameter
     $columns.  If $columns contains a reference to a hash and
     <$self-&gt;name> doesn't return a true value, the data should not be
     read.  This improves performance when the `Win32::ASP::DBRecord'
     object is part of a `Win32::ASP::DBRecordGroup' that is being used to
     retrieve data from a query where only some of the fields will be
     displayed.

     The properly written read for the writename function displayed long
     ago would be:

          read => sub {
          	my $self = shift;
              my($record, $results, $columns) = @_;

          my $name = $self->name;
              ref($columns) and !$columns->{$name} and return;
              $self->can_view($record) or return;

          $record->{orig}->{$name} = undef;
              $results->Fields->Item('SmallValue') and $record->{orig}->{$name} = $results->Fields->Item('SmallValue')->Value;
          if ($record->{orig}->{$name} eq '') {
                $results->Fields->Item('LargeValue') and $record->{orig}->{$name} = $results->Fields->Item('LargeValue')->Value;
          }
          	},

post
     The post method is used to read a specific field into `$results' from
     the POST data.  It also takes `$row' as a parameter.  If `$row' is
     defined, it presumes that it is dealing with a DBRecord that is a
     member of a DBRecordGroup and should retrieve the appropriately
     indexed value from the multi-valued POST data.  If it is not defined,
     it presumes that it is dealing with single-valued POST data.

     It assigns the value into `$record->{edit}' as appropriate.  It also
     tests for whether the POST data contains any non-whitespace
     characters and assigns undef if it does not.

HTML Formatters
...............

   These methods are used to format a given value as HTML.

as_html
     The as_html method is the accepted external interface for displaying
     a field in HTML.  It takes three parameters, `$record', $data, and
     `$viewtype', and returns the appropriate HTML.

     The default implementation, `_as_html', first checks for whether the
     `$record' is viewable.  If it is not, it simply returns.  It then
     checks to see if `$viewtype' is 'edit'.  If it is, it calls
     `$self->can_edit($record)' to determine if the field is editable.  If
     it is, it calls as_html_edit_rw or as_html_options based on
     is_option_list.  If it isn't editable but `$viewtype' is 'edit', it
     calls as_html_edit_ro.  Finally, if we aren't in 'edit' mode, it
     calls as_html_view.

as_html_view
     The as_html_view method takes two parameters, `$record' and $data,
     and returns the appropriate HTML.

     The default implementation, `_as_html_view', first extracts $value
     from `$record' using $data and `$self->name'.  If it is defined, it
     returns it, otherwise it returns '`&nbsp;''.  It runs the string
     through HTMLEncode to enable it to pass HTML meta-characters.

     This is over-ridden in `Win32::ASP::Field::bit' to return '`Yes'' or
     'No' and in `Win32::ASP::Field::timestamp' to return nothing
     (timestamp is not the same as `datetime').

as_html_edit_ro
     The as_html_edit_ro method takes two parameters, `$record' and $data,
     and returns the appropriate HTML.

     The default implementation, `_as_html_edit_ro', first extracts $value
     from `$record' using $data and `$self->name'.  It concatenates a
     HIDDEN INPUT field with the results of `$self->as_html_view($record,
     $data)'.

     This method is over-riden in `Win32::ASP::Field::timestamp' to encode
     $value as hex (since timestamp values are binary and thus not healthy
     HTML).

as_html_edit_rw
     The as_html_edit_rw method takes two parameters, `$record' and $data,
     and returns the appropriate HTML.

     The default implementation, `_as_html_edit_rw', first extracts $value
     from `$record' using $data and `$self->name'.  It then creates an
     appropriate TEXT INPUT field. Note the call to
     `$self-'as_html_mouseover>, which returns the appropriate parameters
     to implement the help support.

     The method is over-ridden by `Win32::ASP::Field::bit' to display a
     Yes/No radio pair and by `Win32::ASP::Field::text' to display a
     TEXTAREA.

as_html_options
     The as_html_options method takes two parameters, `$record' and $data,
     and returns the appropriate HTML.

     The default implementation, `_as_html_options', first extracts $value
     from `$record' using $data and `$self->name'.  It then loops over the
     values returned from `$self->option_list' and creates a SELECT
     structure with the appropriate OPTION entries.  It specified SELECTED
     for the appropriate one based on $value.

as_html_mouseover
     The as_html_mouseover method takes two parameters, `$record' and
     $data, and returns the appropriate string with `onMouseOver' and
     `onMouseOut' method for inclusion into HTML.

     The default implementation, `_as_html_mouseover', ignores the passed
     parameters and builds JavaScript for setting `window.status' to
     `$self->help'.

SQL Formatters
..............

   Values need to be formatted as legal SQL for the purposes of being
included in query strings.

check_value
     The check_value method is responsible for field level checking of
     $value.  Note that this code does not have access to the entire
     record, and so record-based checking should be left to the
     check_value_write method discussed later.  If the check fails,
     check_value should throw an error. Ideally, the error will either be
     of class `Win32::ASP::Error::Field::bad_value' or a subclass thereof.
     There should be no checking for "requiredness" at this level (simply
     because in many situations it wouldn't be called and so putting it
     here lends false hope).  The default implementation in
     `Win32::ASP::Field' does no checking what-so-ever and is merely
     provided as a prototype.

     The method is over-ridden by `Win32::ASP::Field::bit' to verify that
     the value is a 0 or 1 (bit fields never allow NULLs), by
     `Win32::ASP::Field::datetime' to use
     `Win32::ASP::Field::_clean_datetime' which use OLE to verify a
     datetime value, by `Win32::ASP::Field::int' to verify that the value
     is an integer, and by `Win32::ASP::Field::varchar' to verify that it
     doesn't exceed the maximum length.

as_sql
     The as_sql method is responsible for formatting of $value for
     inclusion in SQL.  Since this code will be called during the query
     phase, it doesn't have access to an entire record.  The default
     implementation in `Win32::ASP::Field' does nothing at all and is
     merely provided as a prototype.

     The method is, therefore, implemented by almost every subclass of
     `Win32::ASP::Field', with the exception of
     `Win32::ASP::Field::dispmeta' and `Win32::ASP::Field::timestamp',
     which are never used to query or write to the database.

Writing Formatters
..................

   The writing formatters are responsible for preparing the output for
updating or inserting records.  Some of these have access to the full
`$record' object, and others only have access to the $value.  In order to
decentralize management of the constraint checking, it would be useful if
some `$record' object checking could be pushed out to the field objects.
At the same time, there are situations where a fully formed `$record'
object is not available for field level checking.  As a result, there is a
profusion of the various formatters and checkers.  Rather than discussing
them in a top-down fashion, I will start from the bottom as things may
make more sense that way.

as_write
     The as_write method gets passed $value and returns the value that
     will be paired with writename for writing to the database.  Note that
     it does not get passed the full record - otherwise it would be
     difficult to call as_write from an overridden as_write.

     For example, to implement as_write for looking up a value in a
     database (obviously just for demonstration purposes - normally you
     would use _standard_option_list), one might use:

          as_write => sub {
          		my $self = shift;
            my($value) = @_;

          my $results = MyDatabase::MyRecord->_DB->exec_sql(<<ENDSQL, error_no_records => 1);
          	SELECT LookupCode FROM LookupCodes WHERE Description = '$value'
          	ENDSQL
              return MyDatabase::MyRecord->_FIELDS->{$self->writename($value)}->as_write($results->Fields->('LookupCode')->Value);
          	},

     That last return line is rather ugly, so let me dissect it:

        * `$self->writename' returns the fieldname to which the return
          value will actually get written.

        * `MyDatabase::MyRecord->_FIELDS' returns the hash of field
          objects for whatever class is involved.

        * `MyDatabase::MyRecord->_FIELDS->{$self->writename}' returns the
          actual field object of interest.

        * as_write is then called on that object with the value returned
          by looking up the appropriate result in the database.

     The main reason for the last line is so that it will properly format
     the return value using whatever type of field the writename is.  This
     shouldn't be an issue for common fields, but it could be for
     date/time values in some circumstances.

check_value_write
     This is the first of the methods that have access to a full
     `$record'.  It gets passed both `$record' and $data and as such can
     check a given field against other fields in the record.  The default
     implementation calls check_value on the appropriate $value.  If the
     check fails for whatever reason, check_value_write should throw an
     exception.

as_write_pair
     The method as_write_pair is the accepted entry point for formatting a
     value for writing to the database.  It accepts `$record' and $data,
     so it can call check_value_write to perform record-dependent field
     validation.  It returns a hash composed of two key/value pairs: field
     should supply the fieldname to write to and value should supply the
     properly formatted data for inclusion into SQL.  Note that if, for
     some reason, the functionality usually supplied by writename requires
     knowledge of the entire record, that functionality should be subsumed
     into as_write_pair.

provides quick and dirty profiling for web performance testing
**************************************************************

NAME
====

   Win32::ASP::Profile - provides quick and dirty profiling for web
performance testing

SYNOPSIS
========

     use Win32::ASP::Profile;

DESCRIPTION
===========

   `Win32::ASP::Profile' outputs rudimentary profiling information at the
end of each web page through the use of BEGIN and END.  The BEGIN
subroutine initializes some information when the web page is first created
and the END subroutine computes the time it took for the web page to be
create and appends that to the end of the web page.

   To use, simply include the line

     use Win32::ASP::Profile;

   on any web page you want to profile.  If you are using a default
`*.INC' file, you can stick that line in the include file and thus garner
profiling information on all your ASP pages.

Monitor events related to files and directories
***********************************************

NAME
====

   Win32::ChangeNotify - Monitor events related to files and directories

SYNOPSIS
========

     require Win32::ChangeNotify;

     $notify = Win32::ChangeNotify->new($Path,$WatchSubTree,$Events);
     $notify->wait or warn "Something failed: $!\n";
     # There has been a change.

DESCRIPTION
===========

   This module allows the user to use a Win32 change notification event
object from Perl.  This allows the Perl program to monitor events relating
to files and directory trees.

   The wait method and `wait_all' & `wait_any' functions are inherited
from the `"Win32::IPC"' in this node module.

Methods
-------

$notify = Win32::ChangeNotify->new($path, $subtree, $filter)
     Constructor for a new ChangeNotification object.  $path is the
     directory to monitor.  If `$subtree' is true, then all directories
     under $path will be monitored.  `$filter' indicates what events
     should trigger a notification.  It should be a string containing any
     of the following flags (separated by whitespace and/or |).

          ATTRIBUTES	Any attribute change
          DIR_NAME     Any directory name change
          FILE_NAME    Any file name change (creating/deleting/renaming)
          LAST_WRITE   Any change to a file's last write time
          SECURITY     Any security descriptor change
          SIZE         Any change in a file's size

     (`$filter' can also be an integer composed from the
     `FILE_NOTIFY_CHANGE_*' constants.)

$notify->close
     Shut down monitoring.  You could just `undef $notify' instead (but
     close works even if there are other copies of the object).  This
     happens automatically when your program exits.

$notify->reset
     Resets the ChangeNotification object after a change has been detected.
     The object will become signalled again after the next change.  (It is
     OK to call this immediately after new, but it is not required.)

$notify->wait
     See `"Win32::IPC"' in this node.  Remember to call reset afterwards
     if you want to continue monitoring.

Deprecated Functions and Methods
--------------------------------

   *Win32::ChangeNotify* still supports the ActiveWare syntax, but its use
is deprecated.

FindFirst($Obj,$PathName,$WatchSubTree,$Filter)
     Use

          $Obj = Win32::ChangeNotify->new($PathName,$WatchSubTree,$Filter)

     instead.

$obj->FindNext()
     Use `$obj->reset' instead.

$obj->Close()
     Use `$obj->close' instead.

AUTHOR
======

   Christopher J. Madsen <`chris_madsen@geocities.com'>

   Loosely based on the original module by ActiveWare Internet Corp.,
`http://www.ActiveWare.com'

Win32 Console and Character Mode Functions
******************************************

NAME
====

   Win32::Console - Win32 Console and Character Mode Functions

DESCRIPTION
===========

   This module implements the Win32 console and character mode functions.
They give you full control on the console input and output, including:
support of off-screen console buffers (eg. multiple screen pages)

   * reading and writing of characters, attributes and whole portions of
     the screen

   * complete processing of keyboard and mouse events

   * some very funny additional features :)

   Those functions should also make possible a port of the Unix's curses
library; if there is anyone interested (and/or willing to contribute) to
this project, e-mail me.  Thank you.

REFERENCE
=========

Methods
-------

Alloc
     Allocates a new console for the process.  Returns undef on errors, a
     nonzero value on success.  A process cannot be associated with more
     than one console, so this method will fail if there is already an
     allocated console.  Use Free to detach the process from the console,
     and then call Alloc to create a new console.  See also: Free

     Example:

          $CONSOLE->Alloc();

Attr [attr]
     Gets or sets the current console attribute.  This attribute is used by
     the Write method.

     Example:

          $attr = $CONSOLE->Attr();
          $CONSOLE->Attr($FG_YELLOW | $BG_BLUE);

Close
     Closes a shortcut object.  Note that it is not "strictly" required to
     close the objects you created, since the Win32::Shortcut objects are
     automatically closed when the program ends (or when you elsehow
     destroy such an object).

     Example:

          $LINK->Close();

Cls [attr]
     Clear the console, with the specified attr if given, or using
     ATTR_NORMAL otherwise.

     Example:

          $CONSOLE->Cls();
          $CONSOLE->Cls($FG_WHITE | $BG_GREEN);

Cursor [x, y, size, visible]
     Gets or sets cursor position and appearance.  Returns undef on
     errors, or a 4-element list containing: x, y, size, *visible*.  x and
     y are the current cursor position; ...

     Example:

          ($x, $y, $size, $visible) = $CONSOLE->Cursor();

          # Get position only
          ($x, $y) = $CONSOLE->Cursor();

          $CONSOLE->Cursor(40, 13, 50, 1);

          # Set position only
          $CONSOLE->Cursor(40, 13);

          # Set size and visibility without affecting position
          $CONSOLE->Cursor(-1, -1, 50, 1);

Display
     Displays the specified console on the screen.  Returns undef on
     errors, a nonzero value on success.

     Example:

          $CONSOLE->Display();

FillAttr [attribute, number, col, row]
     Fills the specified number of consecutive attributes, beginning at
     *col*, row, with the value specified in *attribute*.  Returns the
     number of attributes filled, or undef on errors.  See also: FillChar.

     Example:

          $CONSOLE->FillAttr($FG_BLACK | $BG_BLACK, 80*25, 0, 0);

FillChar char, number, col, row
     Fills the specified number of consecutive characters, beginning at
     *col*, row, with the character specified in *char*.  Returns the
     number of characters filled, or undef on errors.  See also: FillAttr.

     Example:

          $CONSOLE->FillChar("X", 80*25, 0, 0);

Flush
     Flushes the console input buffer.  All the events in the buffer are
     discarded.  Returns undef on errors, a nonzero value on success.

     Example:

          $CONSOLE->Flush();

Free
     Detaches the process from the console.  Returns undef on errors, a
     nonzero value on success.  See also: Alloc.

     Example:

          $CONSOLE->Free();

GenerateCtrlEvent [type, processgroup]
     Sends a break signal of the specified type to the specified
     *processgroup*.  type can be one of the following constants:

          CTRL_BREAK_EVENT
          CTRL_C_EVENT

     they signal, respectively, the pressing of Control + Break and of
     Control + C; if not specified, it defaults to CTRL_C_EVENT.
     *processgroup* is the pid of a process sharing the same console.  If
     omitted, it defaults to 0 (the current process), which is also the
     only meaningful value that you can pass to this function.  Returns
     undef on errors, a nonzero value on success.

     Example:

          # break this script now
          $CONSOLE->GenerateCtrlEvent();

GetEvents
     Returns the number of unread input events in the console's input
     buffer, or undef on errors.  See also: Input, InputChar, PeekInput,
     WriteInput.

     Example:

          $events = $CONSOLE->GetEvents();

Info
     Returns an array of informations about the console (or undef on
     errors), which contains:

        * columns (X size) of the console buffer.

        * rows (Y size) of the console buffer.

        * current column (X position) of the cursor.

        * current row (Y position) of the cursor.

        * current attribute used for Write.

        * left column (X of the starting point) of the current console
          window.

        * top row (Y of the starting point) of the current console window.

        * right column (X of the final point) of the current console
          window.

        * bottom row (Y of the final point) of the current console window.

        * maximum number of columns for the console window, given the
          current buffer size, font and the screen size.

        * maximum number of rows for the console window, given the current
          buffer size, font and the screen size.

     See also: Attr, Cursor, Size, Window, MaxWindow.

     Example:

          @info = $CONSOLE->Info();
          print "Cursor at $info[3], $info[4].\n";

Input
     Reads an event from the input buffer.  Returns a list of values, which
     depending on the event's nature are:

    keyboard event
          The list will contain:

             * event type: 1 for keyboard

             * key down: TRUE if the key is being pressed, FALSE if the
               key is being released

             * repeat count: the number of times the key is being held down

             * virtual keycode: the virtual key code of the key

             * virtual scancode: the virtual scan code of the key

             * char: the ASCII code of the character (if the key is a
               character key, 0 otherwise)

             * control key state: the state of the control keys (SHIFTs,
               CTRLs, ALTs, etc.)

    mouse event
          The list will contain:

             * event type: 2 for mouse

             * mouse pos. X: X coordinate (column) of the mouse location

             * mouse pos. Y: Y coordinate (row) of the mouse location

             * button state: the mouse button(s) which are pressed

             * control key state: the state of the control keys (SHIFTs,
               CTRLs, ALTs, etc.)

             * event flags: the type of the mouse event

     This method will return undef on errors.  Note that the events
     returned are depending on the input Mode of the console; for example,
     mouse events are not intercepted unless ENABLE_MOUSE_INPUT is
     specified.  See also: GetEvents, InputChar, Mode, PeekInput,
     WriteInput.

     Example:

          @event = $CONSOLE->Input();

InputChar number
     Reads and returns number characters from the console input buffer, or
     undef on errors.  See also: Input, Mode.

     Example:

          $key = $CONSOLE->InputChar(1);

InputCP [codepage]
     Gets or sets the input code page used by the console.  Note that this
     doesn't apply to a console object, but to the standard input console.
     This attribute is used by the Write method.  See also: OutputCP.

     Example:

          $codepage = $CONSOLE->InputCP();
          $CONSOLE->InputCP(437);

          # you may want to use the non-instanciated form to avoid confuzion :)
          $codepage = Win32::Console::InputCP();
          Win32::Console::InputCP(437);

MaxWindow
     Returns the size of the largest possible console window, based on the
     current font and the size of the display.  The result is undef on
     errors, otherwise a 2-element list containing col, row.

     Example:

          ($maxCol, $maxRow) = $CONSOLE->MaxWindow();

Mode [flags]
     Gets or sets the input or output mode of a console.  flags can be a
     combination of the following constants:

          ENABLE_LINE_INPUT
          ENABLE_ECHO_INPUT
          ENABLE_PROCESSED_INPUT
          ENABLE_WINDOW_INPUT
          ENABLE_MOUSE_INPUT
          ENABLE_PROCESSED_OUTPUT
          ENABLE_WRAP_AT_EOL_OUTPUT

     For more informations on the meaning of those flags, please refer to
     the `"Microsoft's Documentation"' in this node.

     Example:

          $mode = $CONSOLE->Mode();
          $CONSOLE->Mode(ENABLE_MOUSE_INPUT | ENABLE_PROCESSED_INPUT);

MouseButtons
     Returns the number of the buttons on your mouse, or undef on errors.

     Example:

          print "Your mouse has ", $CONSOLE->MouseButtons(), " buttons.\n";

new Win32::Console standard_handle
new Win32::Console [accessmode, sharemode]
     Creates a new console object.  The first form creates a handle to a
     standard channel, *standard_handle* can be one of the following:

          STD_OUTPUT_HANDLE
          STD_ERROR_HANDLE
          STD_INPUT_HANDLE

     The second form, instead, creates a console screen buffer in memory,
     which you can access for reading and writing as a normal console, and
     then redirect on the standard output (the screen) with Display.  In
     this case, you can specify one or both of the following values for
     *accessmode*:

          GENERIC_READ
          GENERIC_WRITE

     which are the permissions you will have on the created buffer, and one
     or both of the following values for *sharemode*:

          FILE_SHARE_READ
          FILE_SHARE_WRITE

     which affect the way the console can be shared.  If you don't specify
     any of those parameters, all 4 flags will be used.

     Example:

          $STDOUT = new Win32::Console(STD_OUTPUT_HANDLE);
          $STDERR = new Win32::Console(STD_ERROR_HANDLE);
          $STDIN  = new Win32::Console(STD_INPUT_HANDLE);

          $BUFFER = new Win32::Console();
          $BUFFER = new Win32::Console(GENERIC_READ | GENERIC_WRITE);

OutputCP [codepage]
     Gets or sets the output code page used by the console.  Note that this
     doesn't apply to a console object, but to the standard output console.
     See also: InputCP.

     Example:

          $codepage = $CONSOLE->OutputCP();
          $CONSOLE->OutputCP(437);

          # you may want to use the non-instanciated form to avoid confuzion :)
          $codepage = Win32::Console::OutputCP();
          Win32::Console::OutputCP(437);

PeekInput
     Does exactly the same as Input, except that the event read is not
     removed from the input buffer.  See also: GetEvents, Input,
     InputChar, Mode, WriteInput.

     Example:

          @event = $CONSOLE->PeekInput();

ReadAttr [number, col, row]
     Reads the specified number of consecutive attributes, beginning at
     *col*, row, from the console.  Returns the attributes read (a
     variable containing one character for each attribute), or undef on
     errors.  You can then pass the returned variable to WriteAttr to
     restore the saved attributes on screen.  See also: ReadChar, ReadRect.

     Example:

          $colors = $CONSOLE->ReadAttr(80*25, 0, 0);

ReadChar [number, col, row]
     Reads the specified number of consecutive characters, beginning at
     *col*, row, from the console.  Returns a string containing the
     characters read, or undef on errors.  You can then pass the returned
     variable to WriteChar to restore the saved characters on screen.  See
     also: ReadAttr, ReadRect.

     Example:

          $chars = $CONSOLE->ReadChar(80*25, 0, 0);

ReadRect left, top, right, bottom
     Reads the content (characters and attributes) of the rectangle
     specified by left, top, right, *bottom* from the console.  Returns a
     string containing the rectangle read, or undef on errors.  You can
     then pass the returned variable to WriteRect to restore the saved
     rectangle on screen (or on another console).  See also: ReadAttr,
     ReadChar.

     Example:

          $rect = $CONSOLE->ReadRect(0, 0, 80, 25);

Scroll left, top, right, bottom, col, row, char, attr,              [cleft, ctop, cright, cbottom]
     Moves a block of data in a console buffer; the block is identified by
     left, top, right, *bottom*, while row, *col* identify the new
     location of the block.  The cells left empty as a result of the move
     are filled with the character *char* and attribute attr.  Optionally
     you can specify a clipping region with *cleft*, *ctop*, *cright*,
     *cbottom*, so that the content of the console outside this rectangle
     are unchanged.  Returns undef on errors, a nonzero value on success.

     Example:

          # scrolls the screen 10 lines down, filling with black spaces
          $CONSOLE->Scroll(0, 0, 80, 25, 0, 10, " ", $FG_BLACK | $BG_BLACK);

Select standard_handle
     Redirects a standard handle to the specified console.
     *standard_handle* can have one of the following values:

          STD_INPUT_HANDLE
          STD_OUTPUT_HANDLE
          STD_ERROR_HANDLE

     Returns undef on errors, a nonzero value on success.

     Example:

          $CONSOLE->Select(STD_OUTPUT_HANDLE);

Size [col, row]
     Gets or sets the console buffer size.

     Example:

          ($x, $y) = $CONSOLE->Size();
          $CONSOLE->Size(80, 25);

Title [title]
     Gets or sets the title bar the string of the current console window.

     Example:

          $title = $CONSOLE->Title();
          $CONSOLE->Title("This is a title");

Window [flag, left, top, right, bottom]
     Gets or sets the current console window size.  If called without
     arguments, returns a 4-element list containing the current window
     coordinates in the form of left, top, right, *bottom*.  To set the
     window size, you have to specify an additional flag parameter: if it
     is 0 (zero), coordinates are considered relative to the current
     coordinates; if it is non-zero, coordinates are absolute.

     Example:

          ($left, $top, $right, $bottom) = $CONSOLE->Window();
          $CONSOLE->Window(1, 0, 0, 80, 50);

Write string
     Writes string on the console, using the current attribute, that you
     can set with Attr, and advancing the cursor as needed.  This isn't so
     different from Perl's "print" statement.  Returns the number of
     characters written or undef on errors.  See also: WriteAttr,
     WriteChar, WriteRect.

     Example:

          $CONSOLE->Write("Hello, world!");

WriteAttr attrs, col, row
     Writes the attributes in the string attrs, beginning at *col*, row,
     without affecting the characters that are on screen.  The string
     attrs can be the result of a ReadAttr function, or you can build your
     own attribute string; in this case, keep in mind that every attribute
     is treated as a character, not a number (see example).  Returns the
     number of attributes written or undef on errors.  See also: Write,
     WriteChar, WriteRect.

     Example:

          $CONSOLE->WriteAttr($attrs, 0, 0);

          # note the use of chr()...
          $attrs = chr($FG_BLACK | $BG_WHITE) x 80;
          $CONSOLE->WriteAttr($attrs, 0, 0);

WriteChar chars, col, row
     Writes the characters in the string attr, beginning at *col*, row,
     without affecting the attributes that are on screen.  The string chars
     can be the result of a ReadChar function, or a normal string.  Returns
     the number of characters written or undef on errors.  See also:
     Write, WriteAttr, WriteRect.

     Example:

          $CONSOLE->WriteChar("Hello, worlds!", 0, 0);

WriteInput (event)
     Pushes data in the console input buffer.  *(event)* is a list of
     values, for more information see Input.  The string chars can be the
     result of a ReadChar function, or a normal string.  Returns the
     number of characters written or undef on errors.  See also: Write,
     WriteAttr, WriteRect.

     Example:

          $CONSOLE->WriteInput(@event);

WriteRect rect, left, top, right, bottom
     Writes a rectangle of characters and attributes (contained in *rect*)
     on the console at the coordinates specified by left, top, right,
     *bottom*.  *rect* can be the result of a ReadRect function.  Returns
     undef on errors, otherwise a 4-element list containing the
     coordinates of the affected rectangle, in the format left, top,
     right, *bottom*.  See also: Write, WriteAttr, WriteChar.

     Example:

          $CONSOLE->WriteRect($rect, 0, 0, 80, 25);

Constants
---------

   The following constants are exported in the main namespace of your
script using Win32::Console:

     BACKGROUND_BLUE
     BACKGROUND_GREEN
     BACKGROUND_INTENSITY
     BACKGROUND_RED
     CAPSLOCK_ON
     CONSOLE_TEXTMODE_BUFFER
     ENABLE_ECHO_INPUT
     ENABLE_LINE_INPUT
     ENABLE_MOUSE_INPUT
     ENABLE_PROCESSED_INPUT
     ENABLE_PROCESSED_OUTPUT
     ENABLE_WINDOW_INPUT
     ENABLE_WRAP_AT_EOL_OUTPUT
     ENHANCED_KEY
     FILE_SHARE_READ
     FILE_SHARE_WRITE
     FOREGROUND_BLUE
     FOREGROUND_GREEN
     FOREGROUND_INTENSITY
     FOREGROUND_RED
     LEFT_ALT_PRESSED
     LEFT_CTRL_PRESSED
     NUMLOCK_ON
     GENERIC_READ
     GENERIC_WRITE
     RIGHT_ALT_PRESSED
     RIGHT_CTRL_PRESSED
     SCROLLLOCK_ON
     SHIFT_PRESSED
     STD_INPUT_HANDLE
     STD_OUTPUT_HANDLE
     STD_ERROR_HANDLE

   Additionally, the following variables can be used:

     $FG_BLACK
     $FG_BLUE
     $FG_LIGHTBLUE
     $FG_RED
     $FG_LIGHTRED
     $FG_GREEN
     $FG_LIGHTGREEN
     $FG_MAGENTA
     $FG_LIGHTMAGENTA
     $FG_CYAN
     $FG_LIGHTCYAN
     $FG_BROWN
     $FG_YELLOW
     $FG_GRAY
     $FG_WHITE

     $BG_BLACK
     $BG_BLUE
     $BG_LIGHTBLUE
     $BG_RED
     $BG_LIGHTRED
     $BG_GREEN
     $BG_LIGHTGREEN
     $BG_MAGENTA
     $BG_LIGHTMAGENTA
     $BG_CYAN
     $BG_LIGHTCYAN
     $BG_BROWN
     $BG_YELLOW
     $BG_GRAY
     $BG_WHITE

     $ATTR_NORMAL
     $ATTR_INVERSE

   ATTR_NORMAL is set to gray foreground on black background (DOS's
standard colors).

Microsoft's Documentation
-------------------------

   Documentation for the Win32 Console and Character mode Functions can be
found on Microsoft's site at this URL:

http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/sys/src/conchar.htm

   A reference of the available functions is at:

http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/sys/src/conchar_34.htm

VERSION HISTORY
===============

   * 0.031 (24 Sep 1999)
        *  Fixed typo in GenerateCtrlEvent().

        * Converted and added pod documentation (from Jan Dubois
          <jand@activestate.com>).

   * 0.03 (07 Apr 1997)
        *  Added "GenerateCtrlEvent" method.

        * The PLL file now comes in 2 versions, one for Perl version 5.001
          (build 110) and one for Perl version 5.003 (build 300 and higher,
          EXCEPT 304).

        * added an installation program that will automatically copy the
          right version in the right place.

   * 0.01 (09 Feb 1997)
        *  First public release.

AUTHOR
======

   Aldo Calpini <a.calpini@romagiubileo.it>

CREDITS
=======

   Thanks to: Jesse Dougherty, Dave Roth, ActiveWare, and the
Perl-Win32-Users community.

DISCLAIMER
==========

   This program is FREE; you can redistribute, modify, disassemble, or
even reverse engineer this software at your will.  Keep in mind, however,
that NOTHING IS GUARANTEED to work and everything you do is AT YOUR OWN
RISK - I will not take responsibility for any damage, loss of money and/or
health that may arise from the use of this program!

   This is distributed under the terms of Larry Wall's Artistic License.

drives on Win32 systems
***********************

NAME
====

   Win32::DriveInfo - drives on Win32 systems

SYNOPSIS
========

     use Win32::DriveInfo;

     ($SectorsPerCluster,
      $BytesPerSector,
      $NumberOfFreeClusters,
      $TotalNumberOfClusters,
      $FreeBytesAvailableToCaller,
      $TotalNumberOfBytes,
      $TotalNumberOfFreeBytes) = Win32::DriveInfo::DriveSpace('f');

     $TotalNumberOfFreeBytes = (Win32::DriveInfo::DriveSpace('c:'))[6];

     $TotalNumberOfBytes = (Win32::DriveInfo::DriveSpace("\\\\serv\\share"))[5];

     @drives = Win32::DriveInfo::DrivesInUse();

     @freelet = Win32::DriveInfo::FreeDriveLetters();

     $type = Win32::DriveInfo::DriveType('a');

     ($VolumeName,
      $VolumeSerialNumber,
      $MaximumComponentLength,
      $FileSystemName, @attr) = Win32::DriveInfo::VolumeInfo('g');

     ($MajorVersion, $MinorVersion, $BuildNumber,
      $PlatformId, $BuildStr) = Win32::DriveInfo::GetVersionEx();

     # check is your CD-ROM loaded
     $CDROM = ( grep { Win32::DriveInfo::DriveType($_) == 5 }
     	Win32::DriveInfo::DrivesInUse() )[0];
     $CD_inside = Win32::DriveInfo::IsReady($CDROM);

ABSTRACT
========

   With this module you can get total/free space on Win32 drives, volume
names, architecture, filesystem type, drive attributes, list of all
available drives and free drive-letters. Additional function to determine
Windows version info.

   The intention was to have a part of Dave Roth's Win32::AdminMisc
functionality on Win95/98.

   The current version of Win32::DriveInfo is available at:

     http://base.dux.ru/guest/fno/perl/

DESCRIPTION
===========

   Module provides few functions:

DriveSpace ( drive )
     `($SectorsPerCluster, $BytesPerSector, $NumberOfFreeClusters,'
     `$TotalNumberOfClusters, $FreeBytesAvailableToCaller,'
     `$TotalNumberOfBytes, $TotalNumberOfFreeBytes) ='
     *Win32::DriveInfo::DriveSpace*( drive );

          drive - drive-letter in either 'c' or 'c:' or 'c:\\' form or UNC path
                  in either "\\\\server\\share" or "\\\\server\\share\\" form.
          $SectorsPerCluster          - number of sectors per cluster.
          $BytesPerSector             - number of bytes per sector.
          $NumberOfFreeClusters       - total number of free clusters on the disk.
          $TotalNumberOfClusters      - total number of clusters on the disk.
          $FreeBytesAvailableToCaller - total number of free bytes on the disk that
                                        are available to the user associated with the
                                        calling thread, b.
          $TotalNumberOfBytes         - total number of bytes on the disk, b.
          $TotalNumberOfFreeBytes     - total number of free bytes on the disk, b.

     Note: in case that UNC path was given first 4 values are undef.

     *Win 95 note:* Win32 API `GetDiskFreeSpaceEx()' function that is
     realized by internal (not intended for users) `GetDiskFreeSpaceEx()'
     subroutine is available on Windows 95 OSR2 (OEM Service Release 2)
     only. This means build numbers (`$BuildNumber' in `GetVersionEx ( )'
     function, described here later) greater then 1000.

     On lower Win95 builds `$FreeBytesAvailableToCaller,
     $TotalNumberOfBytes, $TotalNumberOfFreeBytes' are realized through
     the internal `GetDiskFreeSpace()' function that is claimed less
     trustworthy in Win32 SDK documentation.

     That's why on lower Win 95 builds this function will return 7 undef's
     for UNC drives.

     To say in short: *don't use `DriveSpace ( )' for UNC paths on early
     Win 95!* Where possible use

          net use * \\server\share

     and then usual '\w:' syntax.

DrivesInUse ( )
     Returns sorted array of all drive-letters in use.

FreeDriveLetters ( )
     Returns sorted array of all drive-letters that are available for
     allocation.

DriveType ( drive )
     Returns integer value:

          0     - the drive type cannot be determined.
          1     - the root directory does not exist.
          2     - the drive can be removed from the drive (removable).
          3     - the disk cannot be removed from the drive (fixed).
          4     - the drive is a remote (network) drive.
          5     - the drive is a CD-ROM drive.
          6     - the drive is a RAM disk.

          drive - drive-letter in either 'c' or 'c:' or 'c:\\' form or UNC path
                  in either "\\\\server\\share" or "\\\\server\\share\\" form.

     In case of UNC path 4 will be returned that means that networked
     drive is available (1 - if not available).

IsReady ( drive )
     Returns TRUE if root of the `drive' is accessible, otherwise FALSE.
     This one isn't really something cool - the function just tries to
     chdir to the `drive''s root. This takes time and produces unpleasant
     sound in case the removable drive is not loaded. If somebody knows
     some better way to determine is there something inside your CD-ROM or
     FDD - please let me know (in fact CD-ROMs, RAM drives and network
     drives return their status fast, may be some other devices make
     problem, dunno).

          drive - drive-letter in either 'c' or 'c:' or 'c:\\' form or UNC path
                  in either "\\\\server\\share" or "\\\\server\\share\\" form.

VolumeInfo ( drive )
     `($VolumeName, $VolumeSerialNumber, $MaximumComponentLength,'
     `$FileSystemName, @attr) =' *Win32::DriveInfo::VolumeInfo* ( drive );

          drive - drive-letter in either 'c' or 'c:' or 'c:\\' form.

          $VolumeName             - name of the specified volume.
          $VolumeSerialNumber     - volume serial number.
          $MaximumComponentLength -
               filename component supported by the specified file system.
               A filename component is that portion of a filename between backslashes.
               Indicate that long names are supported by the specified file system.
               For a FAT file system supporting long names, the function stores
               the value 255, rather than the previous 8.3 indicator. Long names can
               also be supported on systems that use the New Technology file system
               (NTFS).
          $FileSystemName         - name of the file system (such as FAT, FAT32, CDFS or NTFS).
          @attr                   - array of integers 1-6
            1 - file system preserves the case of filenames
            2 - file system supports case-sensitive filenames
            3 - file system supports Unicode in filenames as they appear on disk
            4 - file system preserves and enforces ACLs (access-control lists).
                For example, NTFS preserves and enforces ACLs, and FAT does not.
            5 - file system supports file-based compression
            6 - specified volume is a compressed volume; for ex., a DoubleSpace volume

GetVersionEx ( )
     This function provides version of the OS in use.

     `($MajorVersion, $MinorVersion, $BuildNumber, $PlatformId, $BuildStr)
     =' *Win32::DriveInfo::GetVersionEx* ( );

          $MajorVersion - major version number of the operating system. For Windows NT
                          version 3.51, it's 3; for Windows NT version 4.0, it's 4.

          $MinorVersion - minor version number of the operating system. For Windows NT
                          version 3.51, it's 51; for Windows NT version 4.0, it's 0.
          $BuildNumber  - build number of the operating system.
          $PlatformId   - 0 for Win32s, 1 for Win95/98, 2 for Win NT
          $BuildStr     - Windows NT: Contains string, such as "Service Pack 3".
                          Indicates the latest Service Pack installed on the system.
                          If no Service Pack has been installed, the string is empty.
                          Windows 95: Contains a null-terminated string that provides
                          arbitrary additional information about the operating system.

   Nothing is exported by default. All functions return undef on errors.

INSTALLATION
============

   As this is just a plain module no special installation is needed. Just
put it into /Win32 subdir somewhere in your @INC.  The standard

     Makefile.PL
     make
     make test
     make install

   installation procedure is provided. In addition

     make html

   will produce the HTML-docs.

   This module requires

   Win32::API module by Aldo Calpini

CAVEATS
=======

   This module has been created and tested in a Win95 environment on GS
port of Perl 5.004_02. As it uses Win32::API module I expect it would work
fine with other ports like ActiveState if Win32::API (API.dll) is compiled
for this port.

CHANGES
=======

     0.02 - Austin Durbin <adurbin@earthlink.net> tested module on Win NT
            and discovered small bug in UNC paths handling. Fixed.
            Thanks Austin!

     0.03 - fixed bug that returned incorrect values for volumes that are
            larger than 0x7fffffff bytes (2 GB). Approved on Win98 with FAT32.

     0.04 - added IsReady() function and MakeMaker compartible distribution.
            Empty SerialNumber fixed. Now it's empty string, previously it
     	was evaluated to 0000:0000.
     	Minor enhancements.

     0.05 - test.pl fixed, other minor fixes.
     	The last 0.0x version before the major update (soon!)

     0.06 - test.pl fixed more ;-)

BUGS
====

   `DriveSpace ( )' returns incorrect $NumberOfFreeClusters,
$TotalNumberOfClusters values on the large ( >2M ) drives.  Dunno whether
somebody use these values or not but I'll try to fix this in the next
release.

   Please report if any bugs.

VERSION
=======

   This man page documents Win32::DriveInfo version 0.06

   February 19, 2001

AUTHOR
======

   Mike Blazer <blazer@mail.nevalink.ru>

COPYRIGHT
=========

   Copyright (C) 1998-2001 by Mike Blazer. All rights reserved.

LICENSE
=======

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Use Win32 event objects from Perl
*********************************

NAME
====

   Win32::Event - Use Win32 event objects from Perl

SYNOPSIS
========

     use Win32::Event;

     $event = Win32::Event->new($manual,$initial,$name);
     $event->wait();

DESCRIPTION
===========

   This module allows access to the Win32 event objects.  The wait method
and `wait_all' & `wait_any' functions are inherited from the
`"Win32::IPC"' in this node module.

Methods
-------

$event = Win32::Event->new([$manual, [$initial, [$name]]])
     Constructor for a new event object.  If `$manual' is true, you must
     manually reset the event after it is signalled (the default is false).
     If `$initial' is true, the initial state of the object is signalled
     (default false).  If $name is omitted, creates an unnamed event
     object.

     If $name signifies an existing event object, then `$manual' and
     `$initial' are ignored and the object is opened.

$event = Win32::Event->open($name)
     Constructor for opening an existing event object.

$event->pulse
     Signal the $event and then immediately reset it.  If $event is a
     manual-reset event, releases all threads currently blocking on it.  If
     it's an auto-reset event, releases just one thread.

     If no threads are waiting, just resets the event.

$event->reset
     Reset the $event to nonsignalled.

$event->set
     Set the $event to signalled.

$event->wait([$timeout])
     Wait for $event to be signalled.  See `"Win32::IPC"' in this node.

AUTHOR
======

   Christopher J. Madsen <`chris_madsen@geocities.com'>

Process Win32 Event Logs from Perl
**********************************

NAME
====

   Win32::EventLog - Process Win32 Event Logs from Perl

SYNOPSIS
========

     use Win32::EventLog
     $handle=Win32::EventLog->new("Application");

DESCRIPTION
===========

   This module implements most of the functionality available from the
Win32 API for accessing and manipulating Win32 Event Logs. The access to
the EventLog routines is divided into those that relate to an EventLog
object and its associated methods and those that relate other EventLog
tasks (like adding an EventLog record).

The EventLog Object and its Methods
===================================

   The following methods are available to open, read, close and backup
EventLogs.

Win32::EventLog->new(SOURCENAME [,SERVERNAME]);
     The new() method creates a new EventLog object and returns a handle
     to it. This hande is then used to call the methods below.

     The method is overloaded in that if the supplied SOURCENAME argument
     contains one or more literal '\' characters (an illegal character in
     a SOURCENAME), it assumes that you are trying to open a backup
     eventlog and uses SOURCENAME as the backup eventlog to open. Note
     that when opening a backup eventlog, the SERVERNAME argument is
     ignored (as it is in the underlying Win32 API). For EventLogs on
     remote machines, the SOURCENAME parameter must therefore be specified
     as a UNC path.

$handle->Backup(FILENAME);
     The Backup() method backs up the EventLog represented by $handle. It
     takes a single arguemt, FILENAME. When $handle represents an EventLog
     on a remote machine, FILENAME is filename on the remote machine and
     cannot be a UNC path (i.e you must use `C:\TEMP\App.EVT').  The
     method will fail if the log file already exists.

$handle->Read(FLAGS, OFFSET, HASHREF);
     The Read() method read an EventLog entry from the EventLog represented
     by $handle.

$handle->Close();
     The Close() method closes the EventLog represented by $handle. After
     Close() has been called, any further attempt to use the EventLog
     represented by $handle will fail.

$handle->GetOldest(SCALARREF);
     The GetOldest() method number of the the oldest EventLog record in
     the EventLog represented by $handle. This is required to correctly
     compute the OFFSET required by the Read() method.

$handle->GetNumber(SCALARREF);
     The GetNumber() method returns the number of EventLog records in the
     EventLog represented by $handle. The number of the most recent record
     in the EventLog is therefore computed by

          $handle->GetOldest($oldest);
          $handle->GetNumber($lastRec);
          $lastRecOffset=$oldest+$lastRec;

$handle->Clear(FILENAME);
     The Clear() method clears the EventLog represented by $handle.  If
     you provide a non-null FILENAME, the EventLog will be backed up into
     FILENAME before the EventLog is cleared. The method will fail if
     FILENAME is specified and the file refered to exists. Note also that
     FILENAME specifies a file local to the machine on which the EventLog
     resides and cannot be specified as a UNC name.

$handle->Report(HASHREF);
     The Report() method generates an EventLog entry. The HASHREF should
     contain the following keys:

    `Computer'
          The `Computer' field specfies which computer you want the
          EventLog entry recorded.  If this key doesn't exist, the server
          name used to create the $handle is used.

    Source
          The Source field specifies the source that generated the EventLog
          entry.  If this key doesn't exist, the source name used to
          create the $handle is used.

    `EventType'
          The `EventType' field should be one of the constants

         `EVENTLOG_ERROR_TYPE'
               An Error event is being logged.

         `EVENTLOG_WARNING_TYPE'
               A Warning event is being logged.

         `EVENTLOG_INFORMATION_TYPE'
               An Information event is being logged.

         `EVENTLOG_AUDIT_SUCCESS'
               A Success Audit event is being logged (typically in the
               Security EventLog).

         `EVENTLOG_AUDIT_FAILURE'
               A Failure Audit event is being logged (typically in the
               Security EventLog).

          These constants are exported into the main namespace by default.

    Category
          The Category field can have any value you want. It is specific to
          the particular Source.

    `EventID'
          The `EventID' field should contain the ID of the message that
          this event pertains too. This assumes that you have an
          associated message file (indirectly referenced by the field
          Source).

    Data
          The Data field contains raw data associated with this event.

    Strings
          The Strings field contains the single string that itself contains
          NUL terminated sub-strings. This are used with the EventID to
          generate the message as seen from (for example) the Event Viewer
          application.

Other Win32::EventLog functions.
================================

   The following functions are part of the Win32::EventLog package but are
not callable from an EventLog object.

GetMessageText(HASHREF);
     The GetMessageText() function assumes that HASHREF was obtained by a
     call to `$handle->Read()'. It returns the formatted string that
     represents the fully resolved text of the EventLog message (such as
     would be seen in the Windows NT Event Viewer). For convenience, the
     key 'Message' in the supplied HASHREF is also set to the return value
     of this function.

     If you set the variable $Win32::EventLog::GetMessageText to 1 then
     each call to `$handle->Read()' will call this function automatically.

Example 1
=========

   The following example illustrates the way in which the EventLog module
can be used. It opens the System EventLog and reads through it from oldest
to newest records. For each record from the Source EventLog it extracts
the full text of the Entry and prints the EventLog message text out.

     use Win32::EventLog;

     $handle=Win32::EventLog->new("System", $ENV{ComputerName})
     	or die "Can't open Application EventLog\n";
     $handle->GetNumber($recs)
     	or die "Can't get number of EventLog records\n";
     $handle->GetOldest($base)
     	or die "Can't get number of oldest EventLog record\n";

     while ($x < $recs) {
     	$handle->Read(EVENTLOG_FORWARDS_READ|EVENTLOG_SEEK_READ,
     				  $base+$x,
     				  $hashRef)
     		or die "Can't read EventLog entry #$x\n";
     	if ($hashRef->{Source} eq "EventLog") {
     		Win32::EventLog::GetMessageText($hashRef);
     		print "Entry $x: $hashRef->{Message}\n";
     	}
     	$x++;
     }

Example 2
=========

   To backup and clear the EventLogs on a remote machine, do the following
:-

     use Win32::EventLog;

     $myServer="\\\\my-server";	# your servername here.
     my($date)=join("-", ((split(/\s+/, scalar(localtime)))[0,1,2,4]));
     my($dest);

     for my $eventLog ("Application", "System", "Security") {
     	$handle=Win32::EventLog->new($eventLog, $myServer)
     		or die "Can't open Application EventLog on $myServer\n";

     $dest="C:\\BackupEventLogs\\$eventLog\\$date.evt";
     	$handle->Backup($dest)
     		or warn "Could not backup and clear the $eventLog EventLog on $myServer ($^E)\n";

     $handle->Close;
      }

   Note that only the Clear method is required. Note also that if the file
$dest exists, the function will fail.

BUGS
====

   None currently known.

   The test script for 'make test' should be re-written to use the
EventLog object.

AUTHOR
======

   Original code by Jesse Dougherty for HiP Communications. Additional
fixes and updates attributed to Martin Pauley
<martin.pauley@ulsterbank.ltd.uk>) and Bret Giddings (bret@essex.ac.uk).

for carping in the Windows NT Event Log
***************************************

NAME
====

   Win32::EventLog::Carp - for carping in the Windows NT Event Log

REQUIREMENTS
============

     Carp
     Win32::EventLog

SYNOPSIS
========

     use Win32::EventLog::Carp;
     croak "We're outta here!";

     use Win32::EventLog::Carp qw(cluck);
     cluck "This is how we got here!";

DESCRIPTION
===========

   `Win32::EventLog::Carp' traps warnings and fatal errors in Perl and
reports these errors in the Windows NT Event Log. This is useful for
scripts which run as services or through the scheduler, and for CGI/ISAPI
scripts.

   The interface is similar to Carp: the carp, croak and `confess'
functions are exported (with `cluck' being optional).  You need only change
references of "Carp" to "Win32::EventLog::Carp" to begin using this module.

   One notable exception is the addition of the `click' function:

     Win32::EventLog::Carp::click "Hello!\n";

   This outouts a message to STDERR with a short stack trace and allows
scripts to post a simple "I have started" or "I am doing XYZ now" message
to the log.  To avoid the stack trace, end the message with a newline
(which is what happens with the Carp module).

   All messages are posted the the Application Log we well as to STDERR.

Using Win32::EventLog::Carp with CGI::Carp
------------------------------------------

   Some modules which trap the `__WARN__' and __DIE__ signals are not very
friendly, and will cancel out existing traps. The solution is to use this
module after using other modules:

     use CGI::Carp;
     use Win32::EventLog::Carp

   or

     BEGIN
       {
         $SIG{__WARN__} = \&my_handler;
       }

     use Win32::EventLog::Carp

   It is assumed that the previous handler will properly warn or die as
appropriate. This module will instead report these events to the NT event
log.

eval and die
------------

   This module *will* log errors in the event log when something dies in an
eval.  This is a feature, not a bug.

BUGS
====

   Bugs in `Win32::EventLog' and Carp may lead to bugs with this module.

SEE ALSO
========

     Carp
     CGI::Carp
     Win32::EventLog

AUTHOR
======

   Robert Rothenberg <rrwo@cpan.org>

LICENSE
=======

   Copyright (c) 2000-2001 Robert Rothenberg. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

manage file attributes in perl
******************************

NAME
====

   Win32::File - manage file attributes in perl

SYNOPSIS
========

     use Win32::File;

DESCRIPTION
===========

   This module offers the retrieval and setting of file attributes.

Functions
=========

NOTE
----

   All of the functions return FALSE (0) if they fail, unless otherwise
noted.  The function names are exported into the caller's namespace by
request.

GetAttributes(filename, returnedAttributes)
     Gets the attributes of a file or directory. returnedAttributes will
     be set to the OR-ed combination of the filename attributes.

SetAttributes(filename, newAttributes)
     Sets the attributes of a file or directory. newAttributes must be an
     OR-ed combination of the attributes.

Constants
=========

   The following constants are exported by default.

ARCHIVE
COMPRESSED
DIRECTORY
HIDDEN
NORMAL
OFFLINE
READONLY
SYSTEM
TEMPORARY

0.10.3
******

NAME
====

     Win32::FileOp - 0.10.3

DESCRIPTION
===========

   Module for file operations with fancy dialog boxes, for moving files to
recycle bin, reading and updating INI files and file operations in general.

   Unless mentioned otherwise all functions work both under WinNT and
Win95.

   Version 0.10.3

Functions
---------

   GetDesktopHandle GetWindowHandle

   Copy CopyConfirm CopyConfirmEach CopyEx

   Move MoveConfirm MoveConfirmEach MoveEx

   MoveFile MoveFileEx CopyFile MoveAtReboot

   Recycle RecycleConfirm RecycleConfirmEach RecycleEx

   Delete DeleteConfirm DeleteConfirmEach DeleteEx DeleteAtReboot

   UpdateDir FillInDir

   Compress Uncompress Compressed SetCompression GetCompression
CompressDir UncompressDir

   AddToRecentDocs EmptyRecentDocs

   WriteToINI WriteToWININI ReadINI ReadWININI

   DeleteFromINI DeleteFromWININI

   OpenDialog SaveAsDialog BrowseForFolder

   Map Unmap Disconnect Mapped

GetDesktopHandle
          use Win32::FileOp
          $handle = GetDesktopHandle()

     Same as: $handle = $Win32::FileOp::DesktopHandle

     Used to get desktop window handle when confirmation is used.  The
     value of the handle can be gotten from $Win32::FileOp::DesktopHandle.

     Returns the Desktop Window handle.

GetWindowHandle
          use Win32::FileOp
          $handle = GetWindowHandle()

     Same as: $handle = $Win32::FileOp::WindowHandle

     Used to get the console window handle when confirmation is used.  The
     value of the handle can be gotten from $Win32::FileOp::WindowHandle.

     Returns the Console Window handle.

Copy
          Copy ($FileName => $FileOrDirectoryName [, ...])
          Copy (\@FileNames => $DirectoryName [, ...] )
          Copy (\@FileNames => \@FileOrDirectoryNames [, ...])

     Copies the specified files. Doesn't show any confirmation nor
     progress dialogs.

     It may show an error message dialog, because I had to omit
     FOF_NOERRORUI from its call to allow for autocreating directories.

     You should end the directory names by backslash so that they are not
     mistaken for filenames. It is not necessary if the directory already
     exists or if you use Copy \@filenames => $dirname.

     Returns true if successful.

     Rem: Together with Delete, Move, DeleteConfirm, CopyConfirm,
     MoveConfirm, CopyEx, MoveEx, DeleteEx and Recycle based on Win32 API
     function SHFileOperation().

CopyConfirm
          CopyConfirm ($FileName => $FileOrDirectoryName [, ...])
          CopyConfirm (\@FileNames => $DirectoryName [, ...] )
          CopyConfirm (\@FileNames => \@FileOrDirectoryNames [, ...])

     Copies the specified files. In case of a collision, shows a
     confirmation dialog.  Shows progress dialogs.

     Returns true if successful.

CopyConfirmEach
     The same as CopyConfirm.

CopyEx
          CopyEx ($FileName => $FileOrDirectoryName, [...], $options)
          CopyEx (\@FileNames => $DirectoryName, [...], $options)
          CopyEx (\@FileNames => \@FileOrDirectoryNames, [...], $options)

     Copies the specified files. See below for the available options (FOF_
     constants).

     Returns true if successful.

Move
     Moves the specified files. Parameters as Copy

     It may show an error message dialog, because I had to omit
     FOF_NOERRORUI from its call to allow for autocreating directories.

MoveConfirm
     Moves the specified files. Parameters as CopyConfirm

MoveConfirmEach
     The same as MoveConfirm

MoveEx
     Moves the specified files. Parameters as CopyEx

MoveAtReboot
          MoveAtReboot ($FileName => $DestFileName, [...])

     This function moves the file during the next start of the system.

MoveFile
          MoveFile ($FileName => $DestFileName [, ...])

     Move files. This function uses API function MoveFileEx as well as
     MoveAtReboot. It may be a little quicker than Move, but it doesn't
     understand wildcards and the $DestFileName may not be a directory.

     REM: Based on Win32 API function MoveFileEx().

MoveFileEx
          MoveFileEx ($FileName => $DestFileName [, ...], $options)

     This is a simple wrapper around the API function MoveFileEx, it calls
     the function for every pair of files with the $options you specify.
     See below for the available options (FOF_... constants).

     REM: Based on Win32 API function MoveFileEx().

CopyFile
          CopyFile ($FileName => $DestFileName [, $FileName2 => $DestFileName2 [, ...]])

     Copy a file somewhere. This function is not able to copy directories!

     REM: Based on Win32 API function CopyFile().

Recycle
          Recycle @filenames

     Send the files into the recycle bin. You will not get any
     confirmation dialogs.

     Returns true if successful.

RecycleConfirm
          RecycleConfirm @filenames

     Send the files into the recycle bin. You will get a confirmation
     dialog if you have "Display delete confirmation dialog" turned on in
     your recycle bin. You will confirm the deletion of all the files at
     once.

     Returns true if successful. Please remember that this function is
     successful even if the user chose [No] on the confirmation dialog!

RecycleConfirmEach
          RecycleConfirmEach @filenames

     Send the files into the recycle bin. You will get a separate
     confirmation dialog for each file if you have "Display delete
     confirmation dialog" turned on in your recycle bin. You will confirm
     the deletion of all the files at once.

     Returns the number of files that were successfully deleted.

RecycleEx
          RecycleEx @filenames, $options

     Send the files into the recycle bin. You may specify the options for
     deleting, see below.  You may get a confirmation dialog if you have
     "Display delete confirmation dialog" turned on in your recycle bin,
     if so, you will confirm the deletion of all the files at once.

     Returns true if successful. Please remember that this function is
     successful even if the user chose [No] on the confirmation dialog!

     The $options may be constructed from FOF_... constants.

Delete
          Delete @filenames

     Deletes the files. You will not get any confirmation dialogs.

     Returns true if successful.

DeleteConfirm
          DeleteConfirm @filenames

     Deletes the the files. You will get a confirmation dialog to confirm
     the deletion of all the files at once.

     Returns true if successful. Please remember that this function is
     successful even if the user selected [No] on the confirmation dialog!

DeleteConfirmEach
          DeleteConfirmEach @filenames

     Deletes the files. You will get a separate confirmation dialog for
     each file.

     Returns the number of files that were successfully deleted.

DeleteEx
          DeleteEx @filenames, $options

     Deletes the files. You may specify the options for deleting, see
     below.  You may get a confirmation dialog if you have "Display delete
     confirmation dialog" turned on in your recycle bin.

     Returns true if successful. Please remember that this function is
     successful even if the user selected [No] on the confirmation dialog!

DeleteAtReboot
          DeleteAtReboot @files

     This function moves the file during the next start of the system.

UpdateDir
          UpdateDir $SourceDirectory, $DestDirectory [, \&callback]

     Copy the newer or updated files from $SourceDir to $DestDir.
     Processes subdirectories!  The &callback function is called for each
     file to be copied.  The parameters it gets are exactly the same as
     the callback function in File::Find. That is $_, $File::Find::dir and
     $File::Find::name.

     If this function returns a false value, the file is skipped.

          Ex.

          UpdateDir 'c:\dir' => 'e:\dir', sub {print '.'};
          UpdateDir 'c:\dir' => 'e:\dir', sub {if (/^s/i) {print '.'}};

FillInDir
          FillInDir $SourceDirectory, $DestDirectory [, \&callback]

     Copy the files from $SourceDir not present in $DestDir. Processes
     subdirectories!  The &callback works the same as in UpdateDir.

Compress
          Compress $filename [, ...]

     Compresses the file(s) or directories using the transparent WinNT
     compression (The same as checking the "Compressed" checkbox in
     Explorer properties fo the file).

     It doesn't compress all files and subdirectories in a directory you
     specify. Use ComressDir for that. Compress($directory) only sets the
     compression flag for the directory so that the new files are
     compressed by default.

     WinNT only!

     REM: Together with other compression related functions based on
     DeviceIoControl() Win32 API function.

Uncompress
          Uncompress $filename [, ...]

     Uncompresses the file(s) using the transparent WinNT compression (The
     same as unchecking the "Compressed" checkbox in Explorer properties
     fo the file).

     WinNT only!

Compressed
          Compressed $filename

     Checks the compression status for a file.

SetCompression
          SetCompression $filename [, $filename], $value

     Sets the compression status for file(s). The $value should be either
     1 or 0.

GetCompression
          GetCompression $filename

     Checks the compression status for a file.

CompressDir
          CompressDir $directory, ... [, \&callback]

     Recursively descends the directory(ies) specified and compresses all
     files and directories within. If you specify the \&callback, the
     specified function gets executed for each of the files and
     directories. If the callback returns false, no compression is done on
     the file/directory.

     The parameters the callback gets are exactly the same as the callback
     function in File::Find. That is $_, $File::Find::dir and
     $File::Find::name.

UncompressDir
          UncompressDir $directory, ... [, \&callback]

     The counterpart of CompressDir.

AddToRecentDocs
          AddToRecentDocs $filename [, ...]

     Add a shortcut(s) to the file(s) into the Recent Documents folder.
     The shortcuts will appear in the Documents submenu of Start Menu.

     The paths may be relative.

     REM: Based on Win32 API function SHAddToRecentDocs().

EmptyRecentDocs
          EmptyRecentDocs;

     Deletes all shortcuts from the Recent Documents folder.

     REM: Based on Win32 API function SHAddToRecentDocs(). Strange huh?

WriteToINI
          WriteToINI $INIfile, $section, $name1 => $value [, $name2 => $value2 [, ...]]

     Copies a string into the specified section of the specified
     initialization file.  You may pass several name/value pairs at once.

     Returns 1 if successful, undef otherwise. See Win32::GetLastError &
     Win32::FormatMessage(Win32::GetLastError) if failed for the error
     code and message.

     REM: Based on Win32 API function WritePrivateProfileString().

WriteToWININI
          WriteToWININI $section, $name1 => $value1 [, $name2 => $value2 [, ...]]

     Copies a string into the specified section of WIN.INI.  You may pass
     several name/value pairs at once.

     Please note that some values or sections of WIN.INI and some other INI
     files are mapped to registry so they do not show up in the INI file
     even if they were successfully written!

     REM: Based on Win32 API function WriteProfileString().

ReadINI
          $value = ReadINI $INIfile, $section, $name [, $defaultvalue]

     Reads a value from an INI file. If you do not specify the default and
     the value is not found you'll get undef.

     REM: Based on Win32 API function GetPrivateProfileString().

ReadWININI
          $value = ReadWININI $section, $name [, $defaultvalue]

     Reads a value from WIN.INI file. If you do not specify the default
     and the value is not found you'll get undef.

     Please note that some values or sections of WIN.INI and some other INI
     files are mapped to registry so even that they do not show up in the
     INI file this function will find and read them!

     REM: Based on Win32 API function GetProfileString().

DeleteFromINI
          DeleteFromINI $INIfile, $section, @names_to_delete

     Delete a value from an INI file.

     REM: Based on Win32 API function WritePrivateProfileString().

DeleteFromWININI
          DeleteFromWININI $section, @names_to_delete

     Delete a value from WIN.INI.

     REM: Based on Win32 API function WriteProfileString().

ReadINISections
          @sections = ReadINISections($inifile);
          \@sections = ReadINISections($inifile);
          ReadINISections($inifile,\@sections);

     Enumerate the sections in a INI file. If you do not specify the INI
     file, it enumerates the contents of win.ini.

     REM: Based on Win32 API function GetPrivateProfileString().

ReadINISectionKeys
          @sections = ReadINISectionKeys($inifile, $section);
          \@sections = ReadINISectionKeys($inifile, $section);
          ReadINISectionKeys($inifile, $section, \@sections);

     Enumerate the keys in a section of a INI file. If you do not specify
     the INI file, it enumerates the contents of win.ini.

     REM: Based on Win32 API function GetPrivateProfileString().

OpenDialog
          $filename = OpenDialog \%parameters [, $defaultfilename]
          @filenames = OpenDialog \%parameters [, $defaultfilename]

          $filename = OpenDialog %parameters [, $defaultfilename]
          @filenames = OpenDialog %parameters [, $defaultfilename]

     Creates the standard Open dialog allowing you to select some files.

     Returns a list of selected files or undef if the user pressed
     [Escape].  It also sets two global variables :

          $Win32::FileOp::ReadOnly = the user requested a readonly access.
          $Win32::FileOp::SelectedFilter = the id of filter selected in the dialogbox

          %parameters
           title => the title for the dialog, default is 'Open'
                 'Open file'
           filters => definition of file filters
                 { 'Filter 1' => '*.txt;*.doc', 'Filter 2' => '*.pl;*.pm'}
                 [ 'Filter 1' => '*.txt;*.doc', 'Filter 2' => '*.pl;*.pm']
                 [ 'Filter 1' => '*.txt;*.doc', 'Filter 2' => '*.pl;*.pm' , $default]
                 "Filter 1\0*.txt;*.doc\0Filter 2\0*.pl;*.pm"
           defaultfilter => the number of the default filter counting from 1.
                            Please keep in mind that hashes do not preserve
                            ordering!
           dir => the initial directory for the dialog, default is the current directory
           filename => the default filename to be showed in the dialog
           extension => the default extension, this function appends this extension to
                        the filename if the user fails to type an extension. This
                        string can be any length, but only the first three characters
                        are appended. The string should not contain a period (.).
           handle => the handle to the window which will own this dialog
                     Default is the console of the perl script.
                     If you do not want to tie the dialog to any window use
                     handle => 0
           options => options for the dialog, see bellow OFN_... constants

     There is a little problem with the underlying function. You have to
     preallocate a buffer for the selected filenames and if the buffer is
     too smallyou will not get any results. I've consulted this with the
     guys on Perl-Win32-Users and there is not any nice solution. The
     defalut size of buffer is 256B if the options do not include
     OFN_ALLOWMULTISELECT and 64KB if they do. You may change the later
     via variable $Win32::FileOp::BufferSize.

     REM: Based on Win32 API function GetOpenFileName().

SaveAsDialog
     Creates the Save As dialog box, parameters are the same as for
     OpenDialog.

BrowseForFolder
          BrowseForFolder [$title [, $rootFolder [, $options]]]

     Creates the standard "Browse For Folder" dialog.  The $title
     specifies the text to be displayed below the title of the dialog.
     The $rootFolder may be one of the CSIDL_... constants.  For $options
     you should use the BIF_... constants. Description of the constants is
     bellow.

     REM: Based on Win32 API function GetSaveFileName().

Map
          Map $drive => $share;
          $drive = Map $share;
          Map $drive => $share, \%options;
          $drive = Map $share, \%options;

     Map a drive letter or LTPx to a network resource. If successfull
     returns the drive letter/LPTx.

     If you do not specify the drive letter, the function uses the last
     free letter. Since the function doesn't require the ':' in the drive
     name you may use the function like this:

          Map H => '\\\\server\share';
          as well as
          Map 'H:' => '\\\\server\share';

          Options:
           persistent = 0/1, should the connection be restored on next logon?
           user       = username to be used to connect the device
           passwd     = password to be used to connect the device
           overwrite  = 0/1, should the drive be remapped if it was already connected?

          Example:
           Map I => '\\\\servername\share', {persistent=>1,overwrite=>1};

     REM: Based on Win32 API function WNetAddConnection3().

Disconnect
          Disconnect $drive_or_share;
          Disconnect $drive_or_share, \%options;

     Breaks an existing network connection. It can also be used to remove
     remembered network connections that are not currently connected.

     $drive_or_share specifies the name of either the redirected local
     device or the remote network resource to disconnect from. If this
     parameter specifies a redirected local resource, only the specified
     redirection is broken; otherwise, all connections to the remote
     network resource are broken.

          Options:
           persistent = 0/1, if you do not use persistent=>1, the connection will be closed, but
                        the drive letter will still be mapped to the device
           force      = 0/1, disconnect even if there are some open files

          See also: Unmap

     REM: Based on Win32 API function WNetCancelConnection2().

Unmap
          Unmap $drive_or_share;
          Unmap $drive_or_share, \%options;

     The only difference from Disconnect is that persistent=>1 is the
     default.

     REM: Based on Win32 API function WNetCancelConnection2().

Mapped
          %drives = Mapped;
          $share = Mapped $drive;
          $drive = Mapped $share; # currently not implemented !!!

     This function retrieves the name of the network resource associated
     with a local device.  Or vice versa.

     If you do not specify any parameter, you get a hash of drives and
     shares.

     To get the error message from most of these functions, you should not
     use $!, but Win32::FormatMessage(Win32::GetLastError())!

     REM: Based on Win32 API function WNetGetConnection().

Options
-------

FOF_
          FOF_SILENT = do not show the progress dialog
          FOF_RENAMEONCOLLISION = rename the file in case of collision
                     ('file.txt' -> 'Copy of file.txt')
          FOF_NOCONFIRMATION = do not show the confirmation dialog
          FOF_ALLOWUNDO = send file(s) to RecycleBin instead of deleting
          FOF_FILESONLY = skip directories
          FOF_SIMPLEPROGRESS = do not show the filenames in the process dialog
          FOF_NOCONFIRMMKDIR = do not confirm creating directories
          FOF_NOERRORUI = do not report errors
          FOF_NOCOPYSECURITYATTRIBS = do not copy security attributes

OFN_
          OFN_ALLOWMULTISELECT

     Specifies that the File Name list box allows multiple selections. If
     you also set the OFN_EXPLORER flag, the dialog box uses the
     Explorer-style user interface; otherwise, it uses the old-style user
     interface.

          OFN_CREATEPROMPT

     If the user specifies a file that does not exist, this flag causes the
     dialog box to prompt the user for permission to create the file. If
     the user chooses to create the file, the dialog box closes and the
     function returns the specified name; otherwise, the dialog box
     remains open.

          OFN_EXPLORER

     Since I cannot implement hook procedures through Win32::API (AFAIK),
     this option in not necessary.

          OFN_FILEMUSTEXIST

     Specifies that the user can type only names of existing files in the
     File Name entry field. If this flag is specified and the user enters
     an invalid name, the dialog box procedure displays a warning in a
     message box. If this flag is specified, the OFN_PATHMUSTEXIST flag is
     also used.

          OFN_HIDEREADONLY

     Hides the Read Only check box.

          OFN_LONGNAMES

     For old-style dialog boxes, this flag causes the dialog box to use
     long filenames. If this flag is not specified, or if the
     OFN_ALLOWMULTISELECT flag is also set, old-style dialog boxes use
     short filenames (8.3 format) for filenames with spaces.
     Explorer-style dialog boxes ignore this flag and always display long
     filenames.

          OFN_NOCHANGEDIR

     Restores the current directory to its original value if the user
     changed the directory while searching for files.

          OFN_NODEREFERENCELINKS

     Directs the dialog box to return the path and filename of the selected
     shortcut (.LNK) file. If this value is not given, the dialog box
     returns the path and filename of the file referenced by the shortcut

          OFN_NOLONGNAMES

     For old-style dialog boxes, this flag causes the dialog box to use
     short filenames (8.3 format). Explorer-style dialog boxes ignore this
     flag and always display long filenames.

          OFN_NONETWORKBUTTON

     Hides and disables the Network button.

          OFN_NOREADONLYRETURN

     Specifies that the returned file does not have the Read Only check box
     checked and is not in a write-protected directory.

          OFN_NOTESTFILECREATE

     Specifies that the file is not created before the dialog box is
     closed.  This flag should be specified if the application saves the
     file on a create-nonmodify network sharepoint. When an application
     specifies this flag, the library does not check for write protection,
     a full disk, an open drive door, or network protection. Applications
     using this flag must perform file operations carefully, because a
     file cannot be reopened once it is closed.

          OFN_NOVALIDATE

     Specifies that the dialog boxes allow invalid characters in the
     returned filename.

          OFN_OVERWRITEPROMPT

     Causes the Save As dialog box to generate a message box if the
     selected file already exists. The user must confirm whether to
     overwrite the file.

          OFN_PATHMUSTEXIST

     Specifies that the user can type only valid paths and filenames. If
     this flag is used and the user types an invalid path and filename in
     the File Name entry field, the dialog box function displays a warning
     in a message box.

          OFN_READONLY

     Causes the Read Only check box to be checked initially when the dialog
     box is created. If the check box is checked when the dialog box is
     closed $Win32::FileOp::ReadOnly is set to true.

          OFN_SHAREAWARE

     Specifies that if a call to the OpenFile function fails because of a
     network sharing violation, the error is ignored and the dialog box
     returns the selected filename.

          OFN_SHOWHELP

     Causes the dialog box to display the Help button. The hwndOwner member
     must specify the window to receive the HELPMSGSTRING registered
     messages that the dialog box sends when the user clicks the Help
     button.

BIF_
          BIF_DONTGOBELOWDOMAIN

     Does not include network folders below the domain level in the tree
     view control.

          BIF_RETURNONLYFSDIRS

     Only returns file system directories. If the user selects folders that
     are not part of the file system, the OK button is grayed.

          BIF_RETURNFSANCESTORS

     Only returns file system ancestors. If the user selects anything other
     than a file system ancestor, the OK button is grayed.

     This option is strange, cause it seems to allow you to select only
     computers.  I don't know the definition of a filesystem ancestor, but
     I didn't think it would be a computer. ?-|

          BIF_BROWSEFORCOMPUTER

     Only returns computers. If the user selects anything other than a
     computer, the OK button is grayed.

          BIF_BROWSEFORPRINTER

     Only returns printers. If the user selects anything other than a
     printer, the OK button is grayed.

          BIF_STATUSTEXT

     Since it is currently impossible to define callbacks, this options is
     useless.

CSIDL_
     This is a list of available options for BrowseForFolder().

     CSIDL_BITBUCKET

     Recycle bin -- file system directory containing file objects in the
     user's recycle bin. The location of this directory is not in the
     registry; it is marked with the hidden and system attributes to
     prevent the user from moving or deleting it.

     CSIDL_CONTROLS

     Control Panel -- virtual folder containing icons for the control panel
     applications.

     CSIDL_DESKTOP

     Windows desktop -- virtual folder at the root of the name space.

     CSIDL_DESKTOPDIRECTORY

     File system directory used to physically store file objects on the
     desktop (not to be confused with the desktop folder itself).

     CSIDL_DRIVES

     My Computer -- virtual folder containing everything on the local
     computer: storage devices, printers, and Control Panel. The folder may
     also contain mapped network drives.

     CSIDL_FONTS

     Virtual folder containing fonts.

     CSIDL_NETHOOD

     File system directory containing objects that appear in the network
     neighborhood.

     CSIDL_NETWORK

     Network Neighborhood -- virtual folder representing the top level of
     the network hierarchy.

     CSIDL_PERSONAL

     File system directory that serves as a common repository for
     documents.

     CSIDL_PRINTERS

     Printers folder -- virtual folder containing installed printers.

     CSIDL_PROGRAMS

     File system directory that contains the user's program groups (which
     are also file system directories).

     CSIDL_RECENT

     File system directory that contains the user's most recently used
     documents.

     CSIDL_SENDTO

     File system directory that contains Send To menu items.

     CSIDL_STARTMENU

     File system directory containing Start menu items.

     CSIDL_STARTUP

     File system directory that corresponds to the user's Startup program
     group.

     CSIDL_TEMPLATES

     File system directory that serves as a common repository for document
     templates.

     Not all options make sense in all functions!

Variables
---------

     $Win32::FileOp::ProgressTitle

   This variable (if defined) contains the text to be displayed on the
progress dialog if using FOF_SIMPLEPROGRESS. This allows you to present
the user with your own message about what is happening to his computer.

   If the options for the call do not contain FOF_SIMPLEPROGRESS, this
variable is ignored.

Examples
--------

     use Win32::FileOp;

     CopyConfirm ('c:\temp\kinter.pl' => 'c:\temp\copy\\',
                  ['\temp\kinter1.pl', 'temp\kinter2.pl']
                  => ['c:\temp\copy1.pl', 'c:\temp\copy2.pl']);

     $Win32::FileOp::ProgressTitle = "Moving the temporary files ...";
     MoveEx 'c:\temp\file.txt' => 'd:\temp\\',
            ['c:\temp\file1.txt','c:\temp\file2.txt'] => 'd:\temp',
            FOF_RENAMEONCOLLISION | FOF_SIMPLEPROGRESS;
     undef $Win32::FileOp::ProgressTitle;

     Recycle 'c:\temp\kinter.pl';

Handles
-------

   All the functions keep Win32::API handles between calls. If you want to
free the handles you may undefine them, but NEVER EVER set them to
anything else than undef !!!  Even  "$handlename = $handlename;" would
destroy the handle without repair!  See docs for Lazy.pm for explanation.

   List of handles and functions that use them:

     $Win32::FileOp::fileop : Copy, CopyEx, CopyConfirm, Move, MoveEx, MoveConfirm
      Delete, DeleteEx, DeleteConfirm, Recycle, RecycleEx, RecycleConfirm
     $Win32::FileOp::movefileex : MoveFileEx MoveFile MoveAtReboot
     $Win32::FileOp::movefileexDel : DeleteAtReboot
     $Win32::FileOp::copyfile : CopyFile
     $Win32::FileOp::writeINI : WriteToINI MoveAtReboot DeleteAtReboot
     $Win32::FileOp::writeWININI : WriteToWININI
     $Win32::FileOp::deleteINI : DeleteFromINI
     $Win32::FileOp::deleteWININI : DeleteFromWININI
     $Win32::FileOp::readINI : ReadINI
     $Win32::FileOp::readWININI : ReadWININI
     $Win32::FileOp::GetOpenFileName : OpenDialog
     $Win32::FileOp::GetSaveFileName : SaveAsDialog
     $Win32::FileOp::SHAddToRecentDocs : AddToRecentDocs EmptyRecentDocs
     $Win32::FileOp::DesktopHandle
     $Win32::FileOp::WindowHandle : OpenDialog SaveDialog
     $Win32::FileOp::WNetAddConnection3 : Map
     $Win32::FileOp::WNetGetConnection : Mapped
     $Win32::FileOp::WNetCancelConnection2 : Unmap Disconnect Map
     $Win32::FileOp::GetLogicalDrives : FreeDriveLetters Map

Notes
-----

   By default all functions are exported! If you do not want to polute your
namespace too much import only the functions you need.  You may import
either single functions or whole groups.

   The available groups are :

     BASIC = Move..., Copy..., Recycle... and Delete... functions plus constants
     _BASIC = FOF_... constants only
     HANDLES = DesktopHandle GetDesktopHandle WindowHandle GetWindowHandle
     INI = WriteToINI WriteToWININI ReadINI ReadWININI ReadINISectionKeys DeleteFromINI DeleteFromWININI
     DIALOGS = OpenDialog SaveAsDialog plus OFN_... constants
     _DIALOGS = only OFN_... constants
     RECENT = AddToRecentDocs, EmptyRecentDocs
     DIRECTORY = UpdateDir, FillInDir
     COMPRESS => Compress Uncompress Compressed SetCompression GetCompression
     MAP => Map Unmap Disconnect Mapped

   Examples:

     use Win32::FileOp qw(:BASIC GetDesktopHandle);
     use Win32::FileOp qw(:_BASIC MoveEx CopyEx);
     use Win32::FileOp qw(:INI :_DIALOGS SaveAsDialog);

   This module contains all methods from Win32::RecycleBin. The only change
you have to do is to use this module instead of the old Win32::RecycleBin.
Win32:RecycleBin is not supported anymore!

TO-DO
-----

   WNetConnectionDialog, WNetDisconnectDialog

AUTHORS
-------

     Module built by :
      Jan Krynicky <Jenda@Krynicky.cz>
      $Bill Luebkert <dbe@wgn.net>
      Mike Blazer <blazer@mail.nevalink.ru>
      Aldo Calpini <a.calpini@romagiubileo.it>
      Michael Yamada <myamada@gj.com>

manage FileSecurity Discretionary Access Control Lists in perl
**************************************************************

NAME
====

   Win32::FileSecurity - manage FileSecurity Discretionary Access Control
Lists in perl

SYNOPSIS
========

     use Win32::FileSecurity;

DESCRIPTION
===========

   This module offers control over the administration of system
FileSecurity DACLs.  You may want to use Get and EnumerateRights to get an
idea of what mask values correspond to what rights as viewed from File
Manager.

CONSTANTS
=========

     DELETE, READ_CONTROL, WRITE_DAC, WRITE_OWNER,
     SYNCHRONIZE, STANDARD_RIGHTS_REQUIRED,
     STANDARD_RIGHTS_READ, STANDARD_RIGHTS_WRITE,
     STANDARD_RIGHTS_EXECUTE, STANDARD_RIGHTS_ALL,
     SPECIFIC_RIGHTS_ALL, ACCESS_SYSTEM_SECURITY,
     MAXIMUM_ALLOWED, GENERIC_READ, GENERIC_WRITE,
     GENERIC_EXECUTE, GENERIC_ALL, F, FULL, R, READ,
     C, CHANGE

FUNCTIONS
=========

NOTE:
-----

   All of the functions return FALSE (0) if they fail, unless otherwise
noted.  Errors returned via $! containing both Win32 GetLastError() and a
text message indicating Win32 function that failed.

constant( $name, $set )
     Stores the value of named constant $name into $set.  Same as `$set =
     Win32::FileSecurity::NAME_OF_CONSTANT();'.

Get( $filename, \%permisshash )
     Gets the DACLs of a file or directory.

Set( $filename, \%permisshash )
     Sets the DACL for a file or directory.

EnumerateRights( $mask, \@rightslist )
     Turns the bitmask in $mask into a list of strings in @rightslist.

MakeMask( qw( DELETE READ_CONTROL ) )
     Takes a list of strings representing constants and returns a bitmasked
     integer value.

%permisshash
------------

   Entries take the form $permisshash{USERNAME} = $mask ;

EXAMPLE1
========

     # Gets the rights for all files listed on the command line.
     use Win32::FileSecurity qw(Get EnumerateRights);

     foreach( @ARGV ) {
     	next unless -e $_ ;
     	if ( Get( $_, \%hash ) ) {
     	    while( ($name, $mask) = each %hash ) {
     		print "$name:\n\t";
     		EnumerateRights( $mask, \@happy ) ;
     		print join( "\n\t", @happy ), "\n";
     	    }
     	}
     	else {
     	    print( "Error #", int( $! ), ": $!" ) ;
     	}
     }

EXAMPLE2
========

     # Gets existing DACL and modifies Administrator rights
     use Win32::FileSecurity qw(MakeMask Get Set);

     # These masks show up as Full Control in File Manager
     $file = MakeMask( qw( FULL ) );

     $dir = MakeMask( qw(
     	    FULL
     	GENERIC_ALL
     ) );

     foreach( @ARGV ) {
     	s/\\$//;
     	next unless -e;
     	Get( $_, \%hash ) ;
     	$hash{Administrator} = ( -d ) ? $dir : $file ;
     	Set( $_, \%hash ) ;
     }

COMMON MASKS FROM CACLS AND WINFILE
===================================

READ
----

     MakeMask( qw( FULL ) ); # for files
     MakeMask( qw( READ GENERIC_READ GENERIC_EXECUTE ) ); # for directories

CHANGE
------

     MakeMask( qw( CHANGE ) ); # for files
     MakeMask( qw( CHANGE GENERIC_WRITE GENERIC_READ GENERIC_EXECUTE ) ); # for directories

ADD & READ
----------

     MakeMask( qw( ADD GENERIC_READ GENERIC_EXECUTE ) ); # for directories only!

FULL
----

     MakeMask( qw( FULL ) ); # for files
     MakeMask( qw( FULL  GENERIC_ALL ) ); # for directories

RESOURCES
=========

   From Microsoft: check_sd
http://premium.microsoft.com/download/msdn/samples/2760.exe

   (thanks to Guert Schimmel at Sybase for turning me on to this one)

VERSION
=======

   1.03 ALPHA	97-12-14

REVISION NOTES
==============

  1. ALPHA 1998.01.11 Imported diffs from 0.67 (parent) version

  2. ALPHA 1997.12.14 Pod fixes, @EXPORT list additions
     <gsar@activestate.com>

     Fix unitialized vars on unknown ACLs <jmk@exc.bybyte.de>

  3. ALPHA 1997.04.25 CORE Win32 version imported from 0.66
     <gsar@activestate.com>

  4. ALPHA 1997.07.07 Kludged bug in mapping bits to separate ACE's.
     Notably, this screwed up CHANGE access by leaving out a delete bit in
     the `INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE' Access Control Entry.

     May need to rethink...

  5. ALPHA 1997.03.13 Fixed bug in memory allocation check

  6. ALPHA 1997.02.25 Tested with 5.003 build 303

     Added ISA exporter, and @EXPORT_OK

     Added F, FULL, R, READ, C, CHANGE as composite pre-built mask names.

     Added server\ to keys returned in hash from Get

     Made constants and MakeMask case insensitive (I don't know why I did
     that)

     Fixed mask comparison in ListDacl and Enumerate Rights from simple &
     mask to exact bit match ! ( ( x & y ) ^ x ) makes sure all bits in x
     are set in y

     Fixed some "wild" pointers

  7. ALPHA 1996.07.31 Now suitable for file and directory permissions

     Included ListDacl.exe in bundle for debugging

     Added "intuitive" inheritance for directories, basically functions
     like FM triggered by presence of GENERIC_ rights this may need to
     change

     see EXAMPLE2

     Changed from AddAccessAllowedAce to AddAce for control over
     inheritance

  8. ALPHA 1996.07.20 Fixed memory allocation bug

  9. ALPHA 1996.07.29 Base functionality

     Using AddAccessAllowedAce

     Suitable for file permissions

KNOWN ISSUES / BUGS
===================

  1. May not work on remote drives.

  2. Errors croak, don't return via $! as documented.

Inline bitmap support for Win32::GUI
************************************

NAME
====

   Win32::GUI::BitmapInline - Inline bitmap support for Win32::GUI

SYNOPSIS
========

   To create a BitmapInline:

     perl -MWin32::GUI::BitmapInline -e inline('image.bmp') >>script.pl

   To use a BitmapInline (in script.pl):

     use Win32::GUI;
     use Win32::GUI::BitmapInline ();

     $Bitmap1 = new Win32::GUI::BitmapInline( q(
     Qk32AAAAAAAAAHYAAAAoAAAAEAAAABAAAAABAAQAAAAAAIAAAAAAAAAAAAAAABAAAAAQAAAAAAAA
     AACcnABjzs4A9/f3AJzO/wCc//8Azv//AP///wD///8A////AP///wD///8A////AP///wD///8A
     ////AHd3d3d3d3d3d3d3d3d3d3dwAAAAAAAABxIiIiIiIiIHFkVFRUVEQgcWVVRUVFRCBxZVVVVF
     RUIHFlVVVFRUUgcWVVVVVUVCBxZVVVVUVFIHFlVVVVVVQgcWZmZmZmZSBxIiIiIRERF3cTZlUQd3
     d3d3EREQd3d3d3d3d3d3d3d3
     ) );

DESCRIPTION
===========

   This module can be used to "inline" a bitmap file in your script, so
that it doesn't need to be accompained by several external files (less
hassle when you need to redistribute your script or move it to another
location).

   The inline function is used to create an inlined bitmap resource; it
will print on STDOUT the packed data including the lines of Perl needed to
use the inlined bitmap resource; it is intended to be used as a one-liner
whose output is appended to your script.

   The function takes the name of the bitmap file to inline as its first
parameter; an additional, optional parameter can be given which will be
the name of the bitmap object in the resulting scriptlet, eg:

     perl -MWin32::GUI::BitmapInline -e inline('image.bmp','IMAGE')

     $IMAGE = new Win32::GUI::BitmapInline( q( ...

   If no name is given, the resulting object name will be $Bitmap1 (the
next ones $Bitmap2 , $Bitmap3 and so on).

   Note that the object returned by `new Win32::GUI::BitmapInline' is a
regular Win32::GUI::Bitmap object.

WARNINGS
========

   * *Requires MIME::Base64*

     ...and, of course, Win32::GUI :-)

     *Don't use it on large bitmap files!*

     BitmapInline was designed for small bitmaps, such as toolbar items,
     icons, et alia; it is not at all performant.  Inlined data takes
     approximatively the size of your bitmap file plus a 30%; thus, if you
     inline a 100k bitmap you're adding about 130k of bad-looking data to
     your script...

     *Your script must have write access to its current directory*

     When inlined data are used in your script (with `new
     Win32::GUI::BitmapInline...')  a temporary file is created, then
     loaded as a regular bitmap and then immediately deleted.  This will
     fail if your script is not able to create and delete files in the
     current directory at the moment of the call.  One workaround could be
     to change directory to a safer place before constructing the bitmap:

          chdir("c:\\temp");
          $Bitmap1 = new Win32::GUI::BitmapInline( ... );

     A better solution could pop up in some future release...

     *The package exports inline by default*

     For practical reasons (see one-liners above), inline is exported by
     default into your main namespace; to avoid this side-effect is
     recommended to use the module in your production scripts as follows:

          use Win32::GUI::BitmapInline ();

VERSION
=======

   Win32::GUI::BitmapInline version 0.01, 02 April 1999.

AUTHOR
======

   Aldo Calpini ( `dada@divinf.it' ).

Grid layout support for Win32::GUI
**********************************

NAME
====

   Win32::GUI::GridLayout - Grid layout support for Win32::GUI

SYNOPSIS
========

     use Win32::GUI::
     use Win32::GUI::GridLayout;

     # 1. make a "static" grid
     $grid = new Win32::GUI::GridLayout(400, 300, 3, 3, 0, 0);

     $win = new Win32::GUI::Window(

     $win->AddLabel(
         -name => "label1",
         -text => "Label 1",
         -width  => $grid->width(35),
         -height => $grid->height(11),
         -left   => $grid->col(1, "left"),
         -top    => $grid->row(1, "top"),
     );

     # 2. make a "dynamic" grid
     $grid = apply Win32::GUI::GridLayout($win, 3, 3, 0, 0);

     $win->AddLabel(
         -name => "label1",
         -text => "Label 1",
     );
     $grid->add($win->label1, 1, 1, "left top");

     $grid->recalc();

DESCRIPTION
===========

Constructors
------------

new Win32::GUI::GridLayout(WIDTH, HEIGHT, COLS, ROWS, XPAD, YPAD)
apply Win32::GUI::GridLayout(WINDOW, COLS, ROWS, XPAD, YPAD)
Methods
-------

add(CONTROL, COL, ROW, ALIGN)
     Adds CONTROL to the grid at (COL, ROW).  ALIGN can specify both
     horizontal and vertical alignment (see the col() and row() methods),
     separated by at least one blank and/or a comma.

     Example:

          $grid->add($win->label1, 1, 1, "left top");

col(N, ALIGN)
     Positions the control at the Nth column in the grid, optionally with
     an ALIGN; this can be feed to a `-left' option when creating a
     control.

     ALIGN can be left, center or right (can be shortened to l, c, r);
     default is left.

     Note that for alignment to work properly, the width() and height()
     methods must have been previously called.

     Example:

          $win->AddLabel(
              -name => "label1",
              -text => "Label 1",
              -width  => $grid->width(35),
              -height => $grid->height(11),
              -left   => $grid->col(1, "left"),
              -top    => $grid->row(1, "top"),
          );

draw()
     Draws the GridLayout in the associated window (may be useful for
     debugging); is only meaningful if the GridLayout was created with the
     apply() constructor.

height(N)
     Sets the height of the control for subsequent alignment; this can be
     feed to a `-height' option when creating a control.

     Example: see col().

recalc()
     Recalculates the grid and repositions all the add()ed controls,
     taking into account the actual window and controls sizes; is only
     meaningful if the GridLayout was created with the apply() constructor.

     Example:

          sub Window_Resize {
              $grid->recalc();
          }

row(N, ALIGN)
     Positions the control at the Nth row in the grid, optionally with an
     ALIGN; this can be feed to a `-top' option when creating a control.

     ALIGN can be top, center or `bottom' (can be shortened to t, c, b);
     default is top.

     Note that for alignment to work properly, the width() and height()
     methods must have been previously called.

     Example: see col().

width(N)
     Sets the width of the control for subsequent alignment; this can be
     feed to a `-width' option when creating a control.

     Example: see col().

VERSION
=======

   Win32::GUI::GridLayout version 0.03, 13 April 1999.

AUTHOR
======

   Mike Kangas ( `kangas@anlon.com' ); additional coding by Aldo Calpini (
`dada@divinf.it' ).

Perl GUI Test Utilities
***********************

NAME
====

   Win32::GuiTest - Perl GUI Test Utilities

SYNOPSIS
========

     use Win32::GuiTest qw(FindWindowLike GetWindowText
       SetForegroundWindow SendKeys);

     $Win32::GuiTest::debug = 0; # Set to "1" to enable verbose mode

     my @windows = FindWindowLike(0, "^Microsoft Excel", "^XLMAIN\$");
     for (@windows) {
         print "$_>\t'", GetWindowText($_), "'\n";
         SetForegroundWindow($_);
         SendKeys("%fn~a{TAB}b{TAB}{BS}{DOWN}");
     }

INSTALLATION
============

     perl makefile.pl
     nmake
     nmake test
     nmake install

   If you're using ActivePerl 5.6
(http://www.activestate.com/Products/ActivePerl/index.html) you can
install the binary package I'm including instead. You'll need to enter PPM
(Perl Package Manager) from the command-line. Once you have extracted the
files I send you to a directory of your machine, enter PPM and do like
this:

     C:\TEMP>ppm
     PPM interactive shell (2.0) - type 'help' for available commands.
     PPM> install C:\temp\win32-guitest.ppd
     Install package 'C:\temp\win32-guitest.ppd?' (y/N): Y
     Retrieving package 'C:\temp\win32-guitest.ppd'...
     Writing C:\Perl\site\lib\auto\Win32\GuiTest\.packlist
     PPM>

   I extracted them to 'c:\temp', please use the directory where you
extracted the files instead.

DESCRIPTION
===========

   Most GUI test scripts I have seen/written for Win32 use some variant of
Visual Basic (e.g. MS-VB or MS-Visual Test). The main reason is the
availability of the SendKeys function.

   A nice way to drive Win32 programs from a test script is to use OLE
Automation (ActiveX Scripting), but not all Win32 programs support this
interface. That's where SendKeys comes handy.

   Some time ago Al Williams published a Delphi version in Dr. Dobb's
(http://www.ddj.com/ddj/1997/careers1/wil2.htm). I ported it to C and
packaged it using h2xs...

   The tentative name for this module is Win32::GuiTest (mostly because I
plan to include more GUI testing functions).

VERSION
=======

     0.09

CHANGES
=======

   0.01  Wed Aug 12 21:58:13 1998

     - original version; created by h2xs 1.18

   0.02  Sun Oct 25 20:18:17 1998

     - Added several Win32 API functions (typemap courtesy
       of Win32::APIRegistry):
     	SetForegroundWindow
     	GetDesktopWindow
     	GetWindow
     	GetWindowText
     	GetClassName
     	GetParent
     	GetWindowLong
     	SetFocus

     - Ported FindWindowLike (MS-KB, Article ID: Q147659) from VB to
       Perl. Instead of using "like", I used Perl regexps. Why
       didn't Jeffrey Friedl include VB in "Mastering Regular
       Expressions"? ;-).

     0.03  Sun Oct 31 18:31:52 1999

     - Perhaps first version released thru CPAN (user: erngui).

     - Changed name from Win32::Test to Win32::GuiTest

     - Fixed bug: using strdup resulted in using system malloc and
       perl's free, resulting in a runtime error.
       This way we always use perl's malloc. Got the idea from
       'ext\Dynaloader\dl_aix.xs:calloc'.

   0.04  Fri Jan 7 17:44:00 2000

     - Fixed Compatibility with ActivePerl 522. Thanks to
       Johannes Maehner <johanm@camline.com> for the initial patch.
       There were two main issues:
         /1/ ActivePerl (without CAPI=TRUE) compiles extensions in C++ mode
             (some casts from void*, etc.. were needed).
         /2/ The old typemap + buffers.h I was using had been rendered
             incompatible by changes in ActivePerl. As the incompatible typemaps
             were redundant, I deleted them.
       Now it works on ActivePerl (both using 'perl makefile.pl'
       and 'perl makefile.pl CAPI=TRUE') and on CPAN perl
       (http://www.perl.com/CPAN/src/stable.zip).

     - As requests for changes keep comming in, I've decided to put it all
       under version control (cvs if you're curious about it).

   0.05 Sat Mar 11 23:11:42 2000

     - Added support for sending function keys (e.g. "%{F4}"). A new test
       script is added to the distribution (eg\notepad.pl) to test
       this functionality.

     - Code cleanup to make adding new keywords easier.

   0.06 Sun Mar 12 01:51:18 2000

     - Added support for sending mouse events.
       Thanks to Ben Shern <shernbj@louisville.stortek.com> for the idea
       and original code. Also added 'eg\paint.pl' to the distribution to
       test this functionality.

     - Code cleanup.

   0.07 Sun Nov 19 13:02:00 2000

     - Added MouseMoveAbsPix to allow moving the mouse to an absolute pixel
       coordinate instead of using mouse_event's (0, 0) to (65535, 65535)
       coordinates.
       Thanks to Phill Wolf <pbwolf@bellatlantic.net> for the idea
       and original code. Also added 'eg\paint_abs.pl' to the distribution
       to test this functionality.

     - Added binaries for the ActivePerl distribution.

   0.08 Sun Dec 17 19:33:07 2000

     - Added WMGetText to allow getting the content of an EDIT window. See
       'eg\notepad_text.pl' for more details.
       Thanks to Mauro <m_servizi@yahoo.it> from Italy for the idea.

   0.09 Thu Jan 4 22:30:50 2001

     - Added {SPC} action to sendkeys to simulate hitting the spacebar.
       Thanks to Sohrab Niramwalla <sohrab.niramwalla@utoronto.ca> for the
       idea.

     =cut

   package Win32::GuiTest;

   use strict; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $debug);

   require Exporter; require DynaLoader; require AutoLoader;

   @ISA = qw(Exporter DynaLoader); # Items to export into callers
namespace by default. Note: do not export # names by default without a
very good reason. Use EXPORT_OK instead.  # Do not simply export all your
public functions/methods/constants.   @EXPORT = qw(

   );

   @EXPORT_OK = qw(SendKeys FindWindowLike SetForegroundWindow
GetDesktopWindow GetWindow GetWindowText GetClassName GetParent
GetWindowID GetWindowLong $debug SendMouse         SendLButtonUp
SendLButtonDown         SendMButtonUp SendMButtonDown
SendRButtonUp SendRButtonDown         SendMouseMoveAbs MouseMoveAbsPix
SendMouseMoveRel WMGetKey);

   $VERSION = '0.9';

   $debug = 0;

   bootstrap Win32::GuiTest $VERSION;

   sub GWL_ID      { -12;  } sub GW_HWNDNEXT { 2;    } sub GW_CHILD    {
5;    }

FUNCTIONS
=========

$debug
     When set enables the verbose mode.

SendKeys KEYS
     Sends keystrokes to the active window as if typed at the keyboard.
     The keystrokes to send are specified in KEYS. There are several
     characters that have special meaning. This allows sending control
     codes and modifiers:

     	~ means ENTER 	+ means SHIFT 	^ means CTRL 	% means ALT

     The parens allow character grouping. You may group several
     characters, so that a specific keyboard modifier applies to all of
     them.

     E.g. SendKeys("ABC") <=> SendKeys("+(abc)")

     The curly braces are used to quote special characters
     (SendKeys("{+}{{}") sends a '+' and a '{'). You can also use them to
     specify certain named actions:

          Name              Action

          {BACKSPACE}       Backspace
          {BS}              Backspace
          {BKSP}            Backspace
          {BREAK}           Break
          {CAPS}            Caps Lock
          {DELETE}          Delete
          {DOWN}            Down arrow
          {END}             End
          {ENTER}           Enter (same as ~)
          {ESCAPE}          Escape
          {HELP}            Help key
          {HOME}            Home
          {INSERT}          Insert
          {LEFT}            Left arrow
          {NUMLOCK}         Num lock
          {PGDN}            Page down
          {PGUP}            Page up
          {PRTSCR}          Print screen
          {RIGHT}           Right arrow
          {SCROLL}          Scroll lock
          {TAB}             Tab
          {UP}              Up arrow
          {PAUSE}           Pause
              {F1}              Function Key 1
              ...               ...
              {F24}             Function Key 24
              {SPC}             Spacebar
              {SPACE}           Spacebar
              {SPACEBAR}        Spacebar

     All these named actions take an optional integer argument, like in
     {RIGHT 5}.  For all of them, except PAUSE, the argument means a
     repeat count. For PAUSE it means the number of milliseconds SendKeys
     should pause before proceding.

     In this implementation, SendKeys always returns after sending the
     keystrokes. There is no way to tell if an application has processed
     those keys when the function returns.

SendMouse COMMAND
     This function emulates mouse input.  The COMMAND parameter is a string
     containing one or more of the following substrings:
     {LEFTDOWN}        left button down 	{LEFTUP}          left
     button up 	{MIDDLEDOWN}      middle button down
     {MIDDLEUP}        middle button up 	{RIGHTDOWN}       right
     button down 	{RIGHTUP}         right button up 	{LEFTCLICK}       left
     button single click 	{MIDDLECLICK}     middle button single
     click 	{RIGHTCLICK}      right button single click
     {ABSx,y}          move to absolute coordinate ( x, y )
     {RELx,y}     	  move to relative coordinate ( x, y )

     Note: Absolute mouse coordinates range from 0 to 65535.
     Relative coordinates can be positive or negative.        If you need
     pixel coordinates you can use MouseMoveAbsPix.

     Also equivalent low-level functions are available:

          SendLButtonUp()
          	SendLButtonDown()
          	SendMButtonUp()
          	SendMButtonDown()
          	SendRButtonUp()
          	SendRButtonDown()
          	SendMouseMoveRel(x,y)
          SendMouseMoveAbs(x,y)

          =back

    MouseMoveAbsPix(X,Y)
          Move the mouse cursor to the screen pixel indicated as parameter.

               # Moves to x=200, y=100 in pixel coordinates.
               MouseMoveAbsPix(200, 100);

    FindWindowLike WINDOW, TITLEPATTERN, CLASSPATTERN, CHILDID
          Finds the window handles of the windows matching the specified
          parameters and returns them as a list.

          You may specify the handle of the window to search under. The
          routine searches through all of this windows children and their
          children recursively.  If 'undef' then the routine searches
          through all windows. There is also a regexp used to match
          against the text in the window caption and another regexp used
          to match against the text in the window class. If you pass a
          child ID number, the functions will only match windows with this
          id. In each case undef matches everything.

COPYRIGHT
=========

   The SendKeys function is based on the Delphi sourcecode published by Al
Williams (http://www.al-williams.com/awc/) in Dr.Dobbs
(http://www.ddj.com/ddj/1997/careers1/wil2.htm).

   Copyright (c) 1998-2001 Ernesto Guisado. All rights reserved. This
program is free software; You may distribute it and/or modify it under the
same terms as Perl itself.

AUTHOR
======

   Ernesto Guisado <erngui@acm.org>, <http://www.geocities.com/erngui>

Base class for Win32 synchronization objects
********************************************

NAME
====

   Win32::IPC - Base class for Win32 synchronization objects

SYNOPSIS
========

     use Win32::Event 1.00 qw(wait_any);
     #Create objects.

     wait_any(@ListOfObjects,$timeout);

DESCRIPTION
===========

   This module is loaded by the other Win32 synchronization modules.  You
shouldn't need to load it yourself.  It supplies the wait functions to
those modules.

   The synchronization modules are `"Win32::ChangeNotify"' in this node,
`"Win32::Event"' in this node, `"Win32::Mutex"' in this node, &
`"Win32::Semaphore"' in this node.

Methods
-------

   *Win32::IPC* supplies one method to all synchronization objects.

$obj->wait([$timeout])
     Waits for $obj to become signalled.  $timeout is the maximum time to
     wait (in milliseconds).  If $timeout is omitted, waits forever.  If
     $timeout is 0, returns immediately.

     Returns:

          +1    The object is signalled
          -1    The object is an abandoned mutex
           0    Timed out
            undef  An error occurred

Functions
---------

wait_any(@objects, [$timeout])
     Waits for at least one of the `@objects' to become signalled.
     $timeout is the maximum time to wait (in milliseconds).  If $timeout
     is omitted, waits forever.  If $timeout is 0, returns immediately.

     The return value indicates which object ended the wait:

          +N    $object[N-1] is signalled
          -N    $object[N-1] is an abandoned mutex
           0    Timed out
            undef  An error occurred

     If more than one object became signalled, the one with the lowest
     index is used.

wait_all(@objects, [$timeout])
     This is the same as `wait_any', but it waits for all the `@objects'
     to become signalled.  The return value indicates the last object to
     become signalled, and is negative if at least one of the `@objects'
     is an abandoned mutex.

Deprecated Functions and Methods
--------------------------------

   *Win32::IPC* still supports the ActiveWare syntax, but its use is
deprecated.

INFINITE
     Constant value for an infinite timeout.  Omit the $timeout argument
     instead.

WaitForMultipleObjects(\@objects, $wait_all, $timeout)
     Warning: `WaitForMultipleObjects' erases `@objects'!  Use `wait_all'
     or `wait_any' instead.

$obj->Wait($timeout)
     Similar to `not $obj->wait($timeout)'.

AUTHOR
======

   Christopher J. Madsen <`chris_madsen@geocities.com'>

   Loosely based on the original module by ActiveWare Internet Corp.,
`http://www.ActiveWare.com'

Access to WININET.DLL functions
*******************************

NAME
====

   Win32::Internet - Access to WININET.DLL functions

INTRODUCTION
============

   This extension to Perl implements the Win32 Internet APIs (found in
`WININET.DLL'). They give a complete support for HTTP, FTP and GOPHER
connections.

   See the `"Version History"' in this node and the `"Functions Table"' in
this node for a list of the currently supported features. You should also
get a copy of the `"Microsoft Win32 Internet Functions"' in this node
documentation.

REFERENCE
=========

   To use this module, first add the following line at the beginning of
your script:

     use Win32::Internet;

   Then you have to open an Internet connection with this command:

     $Connection = new Win32::Internet();

   This is required to use any of the function of this module.  It will
create an Internet object in Perl on which you can act upon with the
`"General Internet Functions"' in this node explained later.

   The objects available are:

   * Internet connections (the main object, see new)

   * URLs (see OpenURL)

   * FTP sessions (see FTP)

   * HTTP sessions (see HTTP)

   * HTTP requests (see OpenRequest)

   As in the good Perl tradition, there are in this extension different
ways to do the same thing; there are, in fact, different levels of
implementation of the Win32 Internet Functions.  Some routines use several
Win32 API functions to perform a complex task in a single call; they are
simpler to use, but of course less powerful.

   There are then other functions that implement nothing more and nothing
less than the corresponding API function, so you can use all of their
power, but with some additional programming steps.

   To make an example, there is a function called FetchURL that you can
use to fetch the content of any HTTP, FTP or GOPHER URL with this simple
commands:

     $INET = new Win32::Internet();
     $file = $INET->FetchURL("http://www.yahoo.com");

   You can have the same result (and this is actually what is done by
FetchURL) this way:

     $INET = new Win32::Internet();
     $URL = $INET->OpenURL("http://www.yahoo.com");
     $file = $URL->ReadFile();
     $URL->Close();

   Or, you can open a complete HTTP session:

     $INET = new Win32::Internet();
     $HTTP = $INET->HTTP("www.yahoo.com", "anonymous", "dada@divinf.it");
     ($statuscode, $headers, $file) = $HTTP->Request("/");
     $HTTP->Close();

   Finally, you can choose to manage even the HTTP request:

     $INET = new Win32::Internet();
     $HTTP = $INET->HTTP("www.yahoo.com", "anonymous", "dada@divinf.it");
     $HTTP->OpenRequest($REQ, "/");
     $REQ->AddHeader("If-Modified-Since: Saturday, 16-Nov-96 15:58:50 GMT");
     $REQ->SendRequest();
     $statuscode = $REQ->QueryInfo("",HTTP_QUERY_STATUS_CODE);
     $lastmodified = $REQ->QueryInfo("Last-Modified");
     $file = $REQ->ReadEntireFile();
     $REQ->Close();
     $HTTP->Close();

   To open and control a complete FTP session, type:

     $Connection->FTP($Session, "ftp://ftp.activeware.com", "anonymous", "dada\@divinf.it");

   This will create an FTP object in Perl to which you can apply the `"FTP
functions"' in this node provided by the package:

     $Session->Cd("/ntperl/perl5.001m/CurrentBuild");
     $Session->Ascii();
     $Session->Get("110-i86.zip");
     $Session->Close();

   For a more complete example, see the TEST.PL file that comes with the
package.

General Internet Functions
--------------------------

   *General Note*

   All methods assume that you have the line:

     use Win32::Internet;

   somewhere before the method calls, and that you have an Internet object
called $INET which was created using this call:

     $INET = new Win32::Internet();

   See new for more information.

   Methods

CanonicalizeURL URL, [flags]
     Converts a URL to a canonical format, which includes converting unsafe
     characters to escape sequences.  Returns the canonicalized URL or
     undef on errors.  For the possible values of flags, refer to the
     `"Microsoft Win32 Internet Functions"' in this node document.  See
     also CombineURL and OpenURL.

     Example:

          $cURL = $INET->CanonicalizeURL($URL);
          $URL = $INET->CanonicalizeURL($cURL, ICU_DECODE);

Close
Close object
     Closes an Internet connection.  This can be applied to any
     Win32::Internet object (Internet connections, URLs, FTP sessions,
     etc.).  Note that it is not "strictly" required to close the
     connections you create, since the Win32::Internet objects are
     automatically closed when the program ends (or when you elsehow
     destroy such an object).

     Example:

          $INET->Close();
          $FTP->Close();
          $INET->Close($FTP); # same as above...

CombineURL baseURL, relativeURL, [flags]
     Combines a base and relative URL into a single URL.  Returns the
     (canonicalized) combined URL or undef on errors.  For the possible
     values of flags, refer to the `"Microsoft Win32 Internet Functions"'
     in this node document.  See also CombineURL and OpenURL.

     Example:

          $URL = $INET->CombineURL("http://www.divinf.it/dada/perl/internet", "..");

ConnectBackoff [value]
     Reads or sets the delay value, in milliseconds, to wait between
     connection retries.  If no value parameter is specified, the current
     value is returned; otherwise, the delay between retries is set to
     value.  See also ConnectTimeout, ConnectRetries, QueryOption and
     SetOption.

     Example:

          $HTTP->ConnectBackoff(2000);
          $backoff = $HTTP->ConnectBackoff();

ConnectRetries [value]
     Reads or sets the number of times a connection is retried before
     considering it failed.  If no value parameter is specified, the
     current value is returned; otherwise, the number of retries is set to
     value.  The default value for ConnectRetries is 5.  See also
     ConnectBackoff, ConnectTimeout, QueryOption and SetOption.

     Example:

          $HTTP->ConnectRetries(20);
          $retries = $HTTP->ConnectRetries();

ConnectTimeout [value]
     Reads or sets the timeout value (in milliseconds) before a connection
     is considered failed.  If no value parameter is specified, the
     current value is returned; otherwise, the timeout is set to value.
     The default value for ConnectTimeout is infinite.  See also
     ConnectBackoff, ConnectRetries, QueryOption and SetOption.

     Example:

          $HTTP->ConnectTimeout(10000);
          $timeout = $HTTP->ConnectTimeout();

ControlReceiveTimeout [value]
     Reads or sets the timeout value (in milliseconds) to use for non-data
     (control) receive requests before they are canceled.  Currently, this
     value has meaning only for FTP sessions.  If no value parameter is
     specified, the current value is returned; otherwise, the timeout is
     set to value.  The default value for ControlReceiveTimeout is
     infinite.  See also ControlSendTimeout, QueryOption and SetOption.

     Example:

          $HTTP->ControlReceiveTimeout(10000);
          $timeout = $HTTP->ControlReceiveTimeout();

ControlSendTimeout [value]
     Reads or sets the timeout value (in milliseconds) to use for non-data
     (control) send requests before they are canceled.  Currently, this
     value has meaning only for FTP sessions.  If no value parameter is
     specified, the current value is returned; otherwise, the timeout is
     set to value.  The default value for ControlSendTimeout is infinite.
     See also ControlReceiveTimeout, QueryOption and SetOption.

     Example:

          $HTTP->ControlSendTimeout(10000);
          $timeout = $HTTP->ControlSendTimeout();

CrackURL URL, [flags]
     Splits an URL into its component parts and returns them in an array.
     Returns undef on errors, otherwise the array will contain the
     following values: *scheme, host, port, username, password, path,
     extrainfo*.

     For example, the URL "http://www.divinf.it/index.html#top" can be
     splitted in:

          http, www.divinf.it, 80, anonymous, dada@divinf.it, /index.html, #top

     If you don't specify a flags parameter, ICU_ESCAPE will be used by
     default; for the possible values of flags refer to the `"Microsoft
     Win32 Internet Functions"' in this node documentation.  See also
     CreateURL.

     Example:

          @parts=$INET->CrackURL("http://www.activeware.com");
          ($scheme, $host, $port, $user, $pass, $path, $extra) =
               $INET->CrackURL("http://www.divinf.it:80/perl-win32/index.sht#feedback");

CreateURL scheme, hostname, port, username, password, path, extrainfo, [flags]
CreateURL hashref, [flags]
     Creates a URL from its component parts.  Returns undef on errors,
     otherwise the created URL.

     If you pass *hashref* (a reference to an hash array), the following
     values are taken from the array:

          %hash=(
            "scheme"    => "scheme",
            "hostname"  => "hostname",
            "port"      => port,
            "username"  => "username",
            "password"  => "password",
            "path"      => "path",
            "extrainfo" => "extrainfo",
          );

     If you don't specify a flags parameter, ICU_ESCAPE will be used by
     default; for the other possible values of flags refer to the
     `"Microsoft Win32 Internet Functions"' in this node documentation.
     See also CrackURL.

     Example:

          $URL=$I->CreateURL("http", "www.divinf.it", 80, "", "", "/perl-win32/index.sht", "#feedback");
          $URL=$I->CreateURL(\%params);

DataReceiveTimeout [value]
     Reads or sets the timeout value (in milliseconds) to use for data
     receive requests before they are canceled.  If no value parameter is
     specified, the current value is returned; otherwise, the timeout is
     set to value.  The default value for DataReceiveTimeout is infinite.
     See also DataSendTimeout, QueryOption and SetOption.

     Example:

          $HTTP->DataReceiveTimeout(10000);
          $timeout = $HTTP->DataReceiveTimeout();

DataSendTimeout [value]
     Reads or sets the timeout value (in milliseconds) to use for data send
     requests before they are canceled.  If no value parameter is
     specified, the current value is returned; otherwise, the timeout is
     set to value.  The default value for DataSendTimeout is infinite.
     See also DataReceiveTimeout, QueryOption and SetOption.

     Example:

          $HTTP->DataSendTimeout(10000);
          $timeout = $HTTP->DataSendTimeout();

Error
     Returns the last recorded error in the form of an array or string
     (depending upon the context) containing the error number and an error
     description.  Can be applied on any Win32::Internet object (FTP
     sessions, etc.).  There are 3 types of error you can encounter; they
     are recognizable by the error number returned:

        * -1

          A "trivial" error has occurred in the package.  For example, you
          tried to use a method on the wrong type of object.

        * 1 .. 11999

          A generic error has occurred and the Win32::GetLastError error
          message is returned.

        * 12000 and higher

          An Internet error has occurred; the extended Win32 Internet API
          error message is returned.

     See also GetResponse.

     Example:

          die $INET->Error(), qq(\n);
          ($ErrNum, $ErrText) = $INET->Error();

FetchURL URL
     Fetch the content of an HTTP, FTP or GOPHER URL.  Returns the content
     of the file read (or undef if there was an error and nothing was
     read).  See also OpenURL and ReadFile.

     Example:

          $file = $INET->FetchURL("http://www.yahoo.com/");
          $file = $INET->FetchURL("ftp://www.activeware.com/contrib/internet.zip");

FTP ftpobject, server, username, password, [port, pasv, context]
FTP ftpobject, hashref
     Opens an FTP connection to server logging in with the given username
     and password.

     The parameters and their values are:

        * server

          The server to connect to.  Default: none.

        * username

          The username used to login to the server.  Default: anonymous.

        * password

          The password used to login to the server.  Default: none.

        * port

          The port of the FTP service on the server.  Default: 21.

        * pasv

          If it is a value other than 0, use passive transfer mode.
          Default is taken from the parent Internet connection object; you
          can set this value with the Pasv method.

        * context

          A number to identify this operation if it is asynchronous.  See
          SetStatusCallback and GetStatusCallback for more info on
          asynchronous operations.  Default: none.

     If you pass *hashref* (a reference to an hash array), the following
     values are taken from the array:

          %hash=(
            "server"   => "server",
            "username" => "username",
            "password" => "password",
            "port"     => port,
            "pasv"     => pasv,
            "context"  => context,
          );

     This method returns undef if the connection failed, a number
     otherwise.  You can then call any of the `"FTP functions"' in this
     node as methods of the newly created *ftpobject*.

     Example:

          $result = $INET->FTP($FTP, "ftp.activeware.com", "anonymous", "dada\@divinf.it");
          # and then for example...
          $FTP->Cd("/ntperl/perl5.001m/CurrentBuild");

          $params{"server"} = "ftp.activeware.com";
          $params{"password"} = "dada\@divinf.it";
          $params{"pasv"} = 0;
          $result = $INET->FTP($FTP,\%params);

GetResponse
     Returns the text sent by a remote server in response to the last
     function executed.  It applies on any Win32::Internet object,
     particularly of course on `FTP sessions|"FTP functions"' in this
     node.  See also the Error function.

     Example:

          print $INET->GetResponse();
          $INET->FTP($FTP, "ftp.activeware.com", "anonymous", "dada\@divinf.it");
          print $FTP->GetResponse();

GetStatusCallback context
     Returns information about the progress of the asynchronous operation
     identified by context; those informations consist of two values: a
     status code (one of the INTERNET_STATUS_* `"Constants"' in this node)
     and an additional value depending on the status code; for example, if
     the status code returned is INTERNET_STATUS_HANDLE_CREATED, the second
     value will hold the handle just created.  For more informations on
     those values, please refer to the `"Microsoft Win32 Internet
     Functions"' in this node documentation.  See also SetStatusCallback.

     Example:

          ($status, $info) = $INET->GetStatusCallback(1);

HTTP httpobject, server, username, password, [port, flags, context]
HTTP httpobject, hashref
     Opens an HTTP connection to server logging in with the given username
     and password.

     The parameters and their values are:

        * server

          The server to connect to.  Default: none.

        * username

          The username used to login to the server.  Default: anonymous.

        * password

          The password used to login to the server.  Default: none.

        * port

          The port of the HTTP service on the server.  Default: 80.

        * flags

          Additional flags affecting the behavior of the function.
          Default: none.

        * context

          A number to identify this operation if it is asynchronous.  See
          SetStatusCallback and GetStatusCallback for more info on
          asynchronous operations.  Default: none.

     Refer to the `"Microsoft Win32 Internet Functions"' in this node
     documentation for more details on those parameters.

     If you pass *hashref* (a reference to an hash array), the following
     values are taken from the array:

          %hash=(
            "server"   => "server",
            "username" => "username",
            "password" => "password",
            "port"     => port,
            "flags"    => flags,
            "context"  => context,
          );

     This method returns undef if the connection failed, a number
     otherwise.  You can then call any of the `"HTTP functions"' in this
     node as methods of the newly created *httpobject*.

     Example:

          $result = $INET->HTTP($HTTP,"www.activeware.com","anonymous","dada\@divinf.it");
          # and then for example...
          ($statuscode, $headers, $file) = $HTTP->Request("/gifs/camel.gif");

          $params{"server"} = "www.activeware.com";
          $params{"password"} = "dada\@divinf.it";
          $params{"flags"} = INTERNET_FLAG_RELOAD;
          $result = $INET->HTTP($HTTP,\%params);

new Win32::Internet [useragent, opentype, proxy, proxybypass, flags]
new Win32::Internet [hashref]
     Creates a new Internet object and initializes the use of the Internet
     functions; this is required before any of the functions of this
     package can be used.  Returns undef if the connection fails, a number
     otherwise.  The parameters and their values are:

        * useragent

          The user agent passed to HTTP requests.  See OpenRequest.
          Default: Perl-Win32::Internet/version.

        * opentype

          How to access to the Internet (eg. directly or using a proxy).
          Default: INTERNET_OPEN_TYPE_DIRECT.

        * proxy

          Name of the proxy server (or servers) to use.  Default: none.

        * proxybypass

          Optional list of host names or IP addresses, or both, that are
          known locally.  Default: none.

        * flags

          Additional flags affecting the behavior of the function.
          Default: none.

     Refer to the `"Microsoft Win32 Internet Functions"' in this node
     documentation for more details on those parameters.  If you pass
     *hashref* (a reference to an hash array), the following values are
     taken from the array:

          %hash=(
            "useragent"   => "useragent",
            "opentype"    => "opentype",
            "proxy"       => "proxy",
            "proxybypass" => "proxybypass",
            "flags"       => flags,
          );

     Example:

          $INET = new Win32::Internet();
          die qq(Cannot connect to Internet...\n) if ! $INET;

          $INET = new Win32::Internet("Mozilla/3.0", INTERNET_OPEN_TYPE_PROXY, "www.microsoft.com", "");

          $params{"flags"} = INTERNET_FLAG_ASYNC;
          $INET = new Win32::Internet(\%params);

OpenURL urlobject, URL
     Opens a connection to an HTTP, FTP or GOPHER Uniform Resource Location
     (URL).  Returns undef on errors or a number if the connection was
     succesful.  You can then retrieve the URL content by applying the
     methods QueryDataAvailable and ReadFile on the newly created
     *urlobject*.  See also FetchURL.

     Example:

          $INET->OpenURL($URL, "http://www.yahoo.com/");
          $bytes = $URL->QueryDataAvailable();
          $file = $URL->ReadEntireFile();
          $URL->Close();

Password [password]
     Reads or sets the password used for an FTP or HTTP connection.  If no
     password parameter is specified, the current value is returned;
     otherwise, the password is set to password.  See also Username,
     QueryOption and SetOption.

     Example:

          $HTTP->Password("splurfgnagbxam");
          $password = $HTTP->Password();

QueryDataAvailable
     Returns the number of bytes of data that are available to be read
     immediately by a subsequent call to ReadFile (or undef on errors).
     Can be applied to URL or HTTP request objects.  See OpenURL or
     OpenRequest.

     Example:

          $INET->OpenURL($URL, "http://www.yahoo.com/");
          $bytes = $URL->QueryDataAvailable();

QueryOption option
     Queries an Internet option.  For the possible values of option, refer
     to the `"Microsoft Win32 Internet Functions"' in this node document.
     See also SetOption.

     Example:

          $value = $INET->QueryOption(INTERNET_OPTION_CONNECT_TIMEOUT);
          $value = $HTTP->QueryOption(INTERNET_OPTION_USERNAME);

ReadEntireFile
     Reads all the data available from an opened URL or HTTP request
     object.  Returns what have been read or undef on errors.  See also
     OpenURL, OpenRequest and ReadFile.

     Example:

          $INET->OpenURL($URL, "http://www.yahoo.com/");
          $file = $URL->ReadEntireFile();

ReadFile bytes
     Reads bytes bytes of data from an opened URL or HTTP request object.
     Returns what have been read or undef on errors.  See also OpenURL,
     OpenRequest, QueryDataAvailable and ReadEntireFile.

     Note: be careful to keep bytes to an acceptable value (eg.  don't
     tell him to swallow megabytes at once...).  ReadEntireFile in fact
     uses QueryDataAvailable and ReadFile in a loop to read no more than
     16k at a time.

     Example:

          $INET->OpenURL($URL, "http://www.yahoo.com/");
          $chunk = $URL->ReadFile(16000);

SetOption option, value
     Sets an Internet option.  For the possible values of option, refer to
     the `"Microsoft Win32 Internet Functions"' in this node document.
     See also QueryOption.

     Example:

          $INET->SetOption(INTERNET_OPTION_CONNECT_TIMEOUT,10000);
          $HTTP->SetOption(INTERNET_OPTION_USERNAME,"dada");

SetStatusCallback
     Initializes the callback routine used to return data about the
     progress of an asynchronous operation.

     Example:

          $INET->SetStatusCallback();

     This is one of the step required to perform asynchronous operations;
     the complete procedure is:

          # use the INTERNET_FLAG_ASYNC when initializing
          $params{'flags'}=INTERNET_FLAG_ASYNC;
          $INET = new Win32::Internet(\%params);

          # initialize the callback routine
          $INET->SetStatusCallback();

          # specify the context parameter (the last 1 in this case)
          $INET->HTTP($HTTP, "www.yahoo.com", "anonymous", "dada\@divinf.it", 80, 0, 1);

     At this point, control returns immediately to Perl and $INET->Error()
     will return 997, which means an asynchronous I/O operation is
     pending.  Now, you can call

          $HTTP->GetStatusCallback(1);

     in a loop to verify what's happening; see also GetStatusCallback.

TimeConvert time
TimeConvert seconds, minute, hours, day, month, year,                   day_of_week, RFC
     The first form takes a HTTP date/time string and returns the date/time
     converted in the following array: *seconds, minute, hours, day,
     month, year, day_of_week*.

     The second form does the opposite (or at least it should, because
     actually seems to be malfunctioning): it takes the values and returns
     an HTTP date/time string, in the RFC format specified by the RFC
     parameter (OK, I didn't find yet any accepted value in the range
     0..2000, let me know if you have more luck with it).

     Example:

          ($sec, $min, $hour, $day, $mday, $year, $wday) =
             $INET->TimeConvert("Sun, 26 Jan 1997 20:01:52 GMT");

          # the opposite DOESN'T WORK! which value should $RFC have???
          $time = $INET->TimeConvert(52, 1, 20, 26, 1, 1997, 0, $RFC);

UserAgent [name]
     Reads or sets the user agent used for HTTP requests.  If no name
     parameter is specified, the current value is returned; otherwise, the
     user agent is set to name.  See also QueryOption and SetOption.

     Example:

          $INET->UserAgent("Mozilla/3.0");
          $useragent = $INET->UserAgent();

Username [name]
     Reads or sets the username used for an FTP or HTTP connection.  If no
     name parameter is specified, the current value is returned;
     otherwise, the username is set to name.  See also Password,
     QueryOption and SetOption.

     Example:

          $HTTP->Username("dada");
          $username = $HTTP->Username();

Version
     Returns the version numbers for the Win32::Internet package and the
     WININET.DLL version, as an array or string, depending on the context.
     The string returned will contain "package_version/DLL_version", while
     the array will contain: "package_version", "DLL_version".

     Example:

          $version = $INET->Version(); # should return "0.06/4.70.1215"
          @version = $INET->Version(); # should return ("0.06", "4.70.1215")

FTP Functions
-------------

   *General Note*

   All methods assume that you have the following lines:

     use Win32::Internet;
     $INET = new Win32::Internet();
     $INET->FTP($FTP, "hostname", "username", "password");

   somewhere before the method calls; in other words, we assume that you
have an Internet object called $INET and an open FTP session called $FTP.

   See new and FTP for more information.

   Methods

Ascii
Asc
     Sets the ASCII transfer mode for this FTP session.  It will be applied
     to the subsequent Get functions.  See also the Binary and Mode
     function.

     Example:

          $FTP->Ascii();

Binary
Bin
     Sets the binary transfer mode for this FTP session.  It will be
     applied to the subsequent Get functions.  See also the Ascii and Mode
     function.

     Example:

          $FTP->Binary();

Cd path
Cwd path
Chdir path
     Changes the current directory on the FTP remote host.  Returns path
     or undef on error.

     Example:

          $FTP->Cd("/pub");

Delete file
Del file
     Deletes a file on the FTP remote host.  Returns undef on error.

     Example:

          $FTP->Delete("110-i86.zip");

Get remote, [local, overwrite, flags, context]
     Gets the remote FTP file and saves it locally in local.  If local is
     not specified, it will be the same name as remote.  Returns undef on
     error.  The parameters and their values are:

        * remote

          The name of the remote file on the FTP server.  Default: none.

        * local

          The name of the local file to create.  Default: remote.

        * overwrite

          If 0, overwrites local if it exists; with any other value, the
          function fails if the local file already exists.  Default: 0.

        * flags

          Additional flags affecting the behavior of the function.
          Default: none.

        * context

          A number to identify this operation if it is asynchronous.  See
          SetStatusCallback and GetStatusCallback for more info on
          asynchronous operations.  Default: none.

     Refer to the `"Microsoft Win32 Internet Functions"' in this node
     documentation for more details on those parameters.

     Example:

          $FTP->Get("110-i86.zip");
          $FTP->Get("/pub/perl/languages/CPAN/00index.html", "CPAN_index.html");

List [pattern, listmode]
Ls [pattern, listmode]
Dir [pattern, listmode]
     Returns a list containing the files found in this directory,
     eventually matching the given pattern (which, if omitted, is
     considered "*.*").  The content of the returned list depends on the
     *listmode* parameter, which can have the following values:

        * listmode=1 (or omitted)

          the list contains the names of the files found.  Example:

               @files = $FTP->List();
               @textfiles = $FTP->List("*.txt");
               foreach $file (@textfiles) {
                 print "Name: ", $file, "\n";
               }

        * listmode=2

          the list contains 7 values for each file, which respectively are:

             * the file name

             * the DOS short file name, aka 8.3

             * the size

             * the attributes

             * the creation time

             * the last access time

             * the last modified time

          Example:

               @files = $FTP->List("*.*", 2);
               for($i=0; $i<=$#files; $i+=7) {
                 print "Name: ", @files[$i], "\n";
                 print "Size: ", @files[$i+2], "\n";
                 print "Attr: ", @files[$i+3], "\n";
               }

        * listmode=3

          the list contains a reference to an hash array for each found
          file; each hash contains:

             * name => the file name

             * altname => the DOS short file name, aka 8.3

             * size => the size

             * attr => the attributes

             * ctime => the creation time

             * atime => the last access time

             * mtime => the last modified time

          Example:

               @files = $FTP->List("*.*", 3);
               foreach $file (@files) {
                 print $file->{'name'}, " ", $file->{'size'}, " ", $file->{'attr'}, "\n";
               }

          Note: all times are reported as strings of the following format:
          *second, hour, minute, day, month, year*.

          Example:

               $file->{'mtime'} == "0,10,58,9,12,1996" stands for 09 Dec 1996 at 10:58:00

Mkdir name
Md name
     Creates a directory on the FTP remote host.  Returns undef on error.

     Example:

          $FTP->Mkdir("NextBuild");

Mode [mode]
     If called with no arguments, returns the current transfer mode for
     this FTP session ("asc" for ASCII or "bin" for binary).  The mode
     argument can be "asc" or "bin", in which case the appropriate transfer
     mode is selected.  See also the Ascii and Binary functions.  Returns
     undef on errors.

     Example:

          print "Current mode is: ", $FTP->Mode();
          $FTP->Mode("asc"); # ...  same as $FTP->Ascii();

Pasv [mode]
     If called with no arguments, returns 1 if the current FTP session has
     passive transfer mode enabled, 0 if not.

     You can call it with a mode parameter (0/1) only as a method of a
     Internet object (see new), in which case it will set the default
     value for the next FTP objects you create (read: set it before,
     because you can't change this value once you opened the FTP session).

     Example:

          print "Pasv is: ", $FTP->Pasv();

          $INET->Pasv(1);
          $INET->FTP($FTP,"ftp.activeware.com", "anonymous", "dada\@divinf.it");
          $FTP->Pasv(0); # this will be ignored...

Put local, [remote, context]
     Upload the local file to the FTP server saving it under the name
     remote, which if if omitted is the same name as local.  Returns undef
     on error.

     context is a number to identify this operation if it is asynchronous.
     See SetStatusCallback and GetStatusCallback for more info on
     asynchronous operations.

     Example:

          $FTP->Put("internet.zip");
          $FTP->Put("d:/users/dada/temp.zip", "/temp/dada.zip");

Pwd
     Returns the current directory on the FTP server or undef on errors.

     Example:

          $path = $FTP->Pwd();

Rename oldfile, newfile
Ren oldfile, newfile
     Renames a file on the FTP remote host.  Returns undef on error.

     Example:

          $FTP->Rename("110-i86.zip", "68i-011.zip");

Rmdir name
Rd name
     Removes a directory on the FTP remote host.  Returns undef on error.

     Example:

          $FTP->Rmdir("CurrentBuild");

HTTP Functions
--------------

   *General Note*

   All methods assume that you have the following lines:

     use Win32::Internet;
     $INET = new Win32::Internet();
     $INET->HTTP($HTTP, "hostname", "username", "password");

   somewhere before the method calls; in other words, we assume that you
have an Internet object called $INET and an open HTTP session called $HTTP.

   See new and HTTP for more information.

   Methods

AddHeader header, [flags]
     Adds HTTP request headers to an HTTP request object created with
     OpenRequest.  For the possible values of flags refer to the
     `"Microsoft Win32 Internet Functions"' in this node document.

     Example:

          $HTTP->OpenRequest($REQUEST,"/index.html");
          $REQUEST->AddHeader("If-Modified-Since:  Sunday, 17-Nov-96 11:40:03 GMT");
          $REQUEST->AddHeader("Accept: text/html\r\n", HTTP_ADDREQ_FLAG_REPLACE);

OpenRequest requestobject, [path, method, version, referer, accept, flags, context]
OpenRequest requestobject, hashref
     Opens an HTTP request.  Returns undef on errors or a number if the
     connection was succesful.  You can then use one of the AddHeader,
     SendRequest, QueryInfo, QueryDataAvailable and ReadFile methods on
     the newly created *requestobject*.  The parameters and their values
     are:

        * path

          The object to request.  This is generally a file name, an
          executable module, etc.  Default: /

        * method

          The method to use; can actually be GET, POST, HEAD or PUT.
          Default: GET

        * version

          The HTTP version.  Default: HTTP/1.0

        * referer

          The URL of the document from which the URL in the request was
          obtained.  Default: none

        * accept

          The content types accepted.  They must be separated by a "\0"
          (ASCII zero).  Default: text/* image/gif image/jpeg

        * flags

          Additional flags affecting the behavior of the function.
          Default: none

        * context

          A number to identify this operation if it is asynchronous.  See
          SetStatusCallback and GetStatusCallback for more info on
          asynchronous operations.  Default: none

     Refer to the `"Microsoft Win32 Internet Functions"' in this node
     documentation for more details on those parameters.  If you pass
     *hashref* (a reference to an hash array), the following values are
     taken from the array:

          %hash=(
            "path"        => "path",
            "method"      => "method",
            "version"     => "version",
            "referer"     => "referer",
            "accept"      => "accept",
            "flags"       => flags,
            "context"     => context,
          );

     See also Request.

     Example:

          $HTTP->OpenRequest($REQUEST, "/index.html");
          $HTTP->OpenRequest($REQUEST, "/index.html", "GET", "HTTP/0.9");

          $params{"path"} = "/index.html";
          $params{"flags"} = "
          $HTTP->OpenRequest($REQUEST, \%params);

QueryInfo header, [flags]
     Queries information about an HTTP request object created with
     OpenRequest.  You can specify an header (for example, "Content-type")
     and/or one or more flags.  If you don't specify flags,
     HTTP_QUERY_CUSTOM will be used by default; this means that header
     should contain a valid HTTP header name.  For the possible values of
     flags refer to the `"Microsoft Win32 Internet Functions"' in this
     node document.

     Example:

          $HTTP->OpenRequest($REQUEST,"/index.html");
          $statuscode = $REQUEST->QueryInfo("", HTTP_QUERY_STATUS_CODE);
          $headers = $REQUEST->QueryInfo("", HTTP_QUERY_RAW_HEADERS_CRLF); # will get all the headers
          $length = $REQUEST->QueryInfo("Content-length");

Request [path, method, version, referer, accept, flags]
Request hashref
     Performs an HTTP request and returns an array containing the status
     code, the headers and the content of the file.  It is a one-step
     procedure that makes an OpenRequest, a SendRequest, some QueryInfo,
     ReadFile and finally Close.  For a description of the parameters, see
     OpenRequest.

     Example:

          ($statuscode, $headers, $file) = $HTTP->Request("/index.html");
          ($s, $h, $f) = $HTTP->Request("/index.html", "GET", "HTTP/1.0");

SendRequest [postdata]
     Send an HTTP request to the destination server.  *postdata* are any
     optional data to send immediately after the request header; this is
     generally used for POST or PUT requests.  See also OpenRequest.

     Example:

          $HTTP->OpenRequest($REQUEST, "/index.html");
          $REQUEST->SendRequest();

          # A POST request...
          $HTTP->OpenRequest($REQUEST, "/cgi-bin/somescript.pl", "POST");

          #This line is a must -> (thanks Philip :)
          $REQUEST->AddHeader("Content-Type: application/x-www-form-urlencoded");

          $REQUEST->SendRequest("key1=value1&key2=value2&key3=value3");

APPENDIX
========

Microsoft Win32 Internet Functions
----------------------------------

   Complete documentation for the Microsoft Win32 Internet Functions can
be found, in both HTML and zipped Word format, at this address:

     http://www.microsoft.com/intdev/sdk/docs/wininet/

Functions Table
---------------

   This table reports the correspondence between the functions offered by
WININET.DLL and their implementation in the Win32::Internet extension.
Functions showing a "--" are not currently implemented. Functions enclosed
in parens ( ) aren't implemented straightforwardly, but in a higher-level
routine, eg. together with other functions.

     WININET.DLL                     Win32::Internet

     InternetOpen                    new Win32::Internet
     InternetConnect                 FTP / HTTP
     InternetCloseHandle             Close
     InternetQueryOption             QueryOption
     InternetSetOption               SetOption
     InternetSetOptionEx             ---
     InternetSetStatusCallback       SetStatusCallback
     InternetStatusCallback          GetStatusCallback
     InternetConfirmZoneCrossing     ---
     InternetTimeFromSystemTime      TimeConvert
     InternetTimeToSystemTime        TimeConvert
     InternetAttemptConnect          ---
     InternetReadFile                ReadFile
     InternetSetFilePointer          ---
     InternetFindNextFile            (List)
     InternetQueryDataAvailable      QueryDataAvailable
     InternetGetLastResponseInfo     GetResponse
     InternetWriteFile               ---
     InternetCrackUrl                CrackURL
     InternetCreateUrl               CreateURL
     InternetCanonicalizeUrl         CanonicalizeURL
     InternetCombineUrl              CombineURL
     InternetOpenUrl                 OpenURL
     FtpFindFirstFile                (List)
     FtpGetFile                      Get
     FtpPutFile                      Put
     FtpDeleteFile                   Delete
     FtpRenameFile                   Rename
     FtpOpenFile                     ---
     FtpCreateDirectory              Mkdir
     FtpRemoveDirectory              Rmdir
     FtpSetCurrentDirectory          Cd
     FtpGetCurrentDirectory          Pwd
     HttpOpenRequest                 OpenRequest
     HttpAddRequestHeaders           AddHeader
     HttpSendRequest                 SendRequest
     HttpQueryInfo                   QueryInfo
     InternetErrorDlg                ---

   Actually, I don't plan to add support for Gopher, Cookie and Cache
functions. I will if there will be consistent requests to do so.

   There are a number of higher-level functions in the Win32::Internet
that simplify some usual procedures, calling more that one WININET API
function. This table reports those functions and the relative WININET
functions they use.

     Win32::Internet                 WININET.DLL

     FetchURL                        InternetOpenUrl
                                     InternetQueryDataAvailable
                                     InternetReadFile
                                     InternetCloseHandle

     ReadEntireFile                  InternetQueryDataAvailable
                                     InternetReadFile

     Request                         HttpOpenRequest
                                     HttpSendRequest
                                     HttpQueryInfo
                                     InternetQueryDataAvailable
                                     InternetReadFile
                                     InternetCloseHandle

     List                            FtpFindFirstFile
                                     InternetFindNextFile

Constants
---------

   Those are the constants exported by the package in the main namespace
(eg. you can use them in your scripts); for their meaning and proper use,
refer to the Microsoft Win32 Internet Functions document.

     HTTP_ADDREQ_FLAG_ADD
     HTTP_ADDREQ_FLAG_REPLACE
     HTTP_QUERY_ALLOW
     HTTP_QUERY_CONTENT_DESCRIPTION
     HTTP_QUERY_CONTENT_ID
     HTTP_QUERY_CONTENT_LENGTH
     HTTP_QUERY_CONTENT_TRANSFER_ENCODING
     HTTP_QUERY_CONTENT_TYPE
     HTTP_QUERY_COST
     HTTP_QUERY_CUSTOM
     HTTP_QUERY_DATE
     HTTP_QUERY_DERIVED_FROM
     HTTP_QUERY_EXPIRES
     HTTP_QUERY_FLAG_REQUEST_HEADERS
     HTTP_QUERY_FLAG_SYSTEMTIME
     HTTP_QUERY_LANGUAGE
     HTTP_QUERY_LAST_MODIFIED
     HTTP_QUERY_MESSAGE_ID
     HTTP_QUERY_MIME_VERSION
     HTTP_QUERY_PRAGMA
     HTTP_QUERY_PUBLIC
     HTTP_QUERY_RAW_HEADERS
     HTTP_QUERY_RAW_HEADERS_CRLF
     HTTP_QUERY_REQUEST_METHOD
     HTTP_QUERY_SERVER
     HTTP_QUERY_STATUS_CODE
     HTTP_QUERY_STATUS_TEXT
     HTTP_QUERY_URI
     HTTP_QUERY_USER_AGENT
     HTTP_QUERY_VERSION
     HTTP_QUERY_WWW_LINK
     ICU_BROWSER_MODE
     ICU_DECODE
     ICU_ENCODE_SPACES_ONLY
     ICU_ESCAPE
     ICU_NO_ENCODE
     ICU_NO_META
     ICU_USERNAME
     INTERNET_CONNECT_FLAG_PASSIVE
     INTERNET_FLAG_ASYNC
     INTERNET_FLAG_HYPERLINK
     INTERNET_FLAG_KEEP_CONNECTION
     INTERNET_FLAG_MAKE_PERSISTENT
     INTERNET_FLAG_NO_AUTH
     INTERNET_FLAG_NO_AUTO_REDIRECT
     INTERNET_FLAG_NO_CACHE_WRITE
     INTERNET_FLAG_NO_COOKIES
     INTERNET_FLAG_READ_PREFETCH
     INTERNET_FLAG_RELOAD
     INTERNET_FLAG_RESYNCHRONIZE
     INTERNET_FLAG_TRANSFER_ASCII
     INTERNET_FLAG_TRANSFER_BINARY
     INTERNET_INVALID_PORT_NUMBER
     INTERNET_INVALID_STATUS_CALLBACK
     INTERNET_OPEN_TYPE_DIRECT
     INTERNET_OPEN_TYPE_PROXY
     INTERNET_OPEN_TYPE_PROXY_PRECONFIG
     INTERNET_OPTION_CONNECT_BACKOFF
     INTERNET_OPTION_CONNECT_RETRIES
     INTERNET_OPTION_CONNECT_TIMEOUT
     INTERNET_OPTION_CONTROL_SEND_TIMEOUT
     INTERNET_OPTION_CONTROL_RECEIVE_TIMEOUT
     INTERNET_OPTION_DATA_SEND_TIMEOUT
     INTERNET_OPTION_DATA_RECEIVE_TIMEOUT
     INTERNET_OPTION_HANDLE_TYPE
     INTERNET_OPTION_LISTEN_TIMEOUT
     INTERNET_OPTION_PASSWORD
     INTERNET_OPTION_READ_BUFFER_SIZE
     INTERNET_OPTION_USER_AGENT
     INTERNET_OPTION_USERNAME
     INTERNET_OPTION_VERSION
     INTERNET_OPTION_WRITE_BUFFER_SIZE
     INTERNET_SERVICE_FTP
     INTERNET_SERVICE_GOPHER
     INTERNET_SERVICE_HTTP
     INTERNET_STATUS_CLOSING_CONNECTION
     INTERNET_STATUS_CONNECTED_TO_SERVER
     INTERNET_STATUS_CONNECTING_TO_SERVER
     INTERNET_STATUS_CONNECTION_CLOSED
     INTERNET_STATUS_HANDLE_CLOSING
     INTERNET_STATUS_HANDLE_CREATED
     INTERNET_STATUS_NAME_RESOLVED
     INTERNET_STATUS_RECEIVING_RESPONSE
     INTERNET_STATUS_REDIRECT
     INTERNET_STATUS_REQUEST_COMPLETE
     INTERNET_STATUS_REQUEST_SENT
     INTERNET_STATUS_RESOLVING_NAME
     INTERNET_STATUS_RESPONSE_RECEIVED
     INTERNET_STATUS_SENDING_REQUEST

VERSION HISTORY
===============

   * 0.081 (25 Sep 1999)
        *  Documentation converted to pod format by Jan Dubois
          <jand@activestate.com>.

        * Minor changes from Perl 5.005xx compatibility.

   * 0.08 (14 Feb 1997)
        *  fixed 2 more bugs in Option(s) related subs (thanks to Brian
          Helterline!).

        * Error() now gets error messages directly from WININET.DLL.

        * The PLL file now comes in 2 versions, one for Perl version 5.001
          (build 100) and one for Perl version 5.003 (build 300 and
          higher). Everybody should be happy now :)

        * added an installation program.

   * 0.07 (10 Feb 1997)
        *  fixed a bug in Version() introduced with 0.06...

        * completely reworked PM file, fixed *lots* of minor bugs, and
          removed almost all the warnings with "perl -w".

   * 0.06 (26 Jan 1997)
        *  fixed another hideous bug in "new" (the 'class' parameter was
          still missing).

        * added support for asynchronous operations (work still in embryo).

        * removed the ending \0 (ASCII zero) from the DLL version returned
          by "Version".

        * added a lot of constants.

        * added safefree() after every safemalloc() in C... wonder why I
          didn't it before :)

        * added TimeConvert, which actually works one way only.

   * 0.05f (29 Nov 1996)
        *  fixed a bug in "new" (parameters passed were simply ignored).

        * fixed another bug: "Chdir" and "Cwd" were aliases of RMDIR
          instead of CD..

   * 0.05 (29 Nov 1996)
        *  added "CrackURL" and "CreateURL".

        * corrected an error in TEST.PL (there was a GetUserAgent instead
          of UserAgent).

   * 0.04 (25 Nov 1996)
        *  added "Version" to retrieve package and DLL versions.

        * added proxies and other options to "new".

        * changed "OpenRequest" and "Request" to read parameters from a
          hash.

        * added "SetOption/QueryOption" and a lot of relative functions
          (connect, username, password, useragent, etc.).

        * added "CanonicalizeURL" and "CombineURL".

        * "Error" covers a wider spectrum of errors.

   * 0.02 (18 Nov 1996)
        *  added support for HTTP sessions and requests.

   * 0.01 (11 Nov 1996)
        *  fetching of HTTP, FTP and GOPHER URLs.

        * complete set of commands to manage an FTP session.

AUTHOR
======

   Version 0.08 (14 Feb 1997) by Aldo Calpini <a.calpini@romagiubileo.it>

CREDITS
=======

   Win32::Internet is based on the Win32::Registry code written by Jesse
Dougherty.

   Additional thanks to: Carl Tichler for his help in the initial
development; Tore Haraldsen, Brian Helterline for the bugfixes; Dave Roth
for his great source code examples.

DISCLAIMER
==========

   This program is FREE; you can redistribute, modify, disassemble, or
even reverse engineer this software at your will. Keep in mind, however,
that NOTHING IS GUARANTEED to work and everything you do is AT YOUR OWN
RISK - I will not take responsability for any damage, loss of money and/or
health that may arise from the use of this program!

   This is distributed under the terms of Larry Wall's Artistic License.

Use Win32 mutex objects from Perl
*********************************

NAME
====

   Win32::Mutex - Use Win32 mutex objects from Perl

SYNOPSIS
========

     require Win32::Mutex;

     $mutex = Win32::Mutex->new($initial,$name);
     $mutex->wait;

DESCRIPTION
===========

   This module allows access to the Win32 mutex objects.  The wait method
and `wait_all' & `wait_any' functions are inherited from the
`"Win32::IPC"' in this node module.

Methods
-------

$mutex = Win32::Mutex->new([$initial, [$name]])
     Constructor for a new mutex object.  If `$initial' is true, requests
     immediate ownership of the mutex (default false).  If $name is
     omitted, creates an unnamed mutex object.

     If $name signifies an existing mutex object, then `$initial' is
     ignored and the object is opened.

$mutex = Win32::Mutex->open($name)
     Constructor for opening an existing mutex object.

$mutex->release
     Release ownership of a $mutex.  You should have obtained ownership of
     the mutex through new or one of the wait functions.  Returns true if
     successful.

$mutex->wait([$timeout])
     Wait for ownership of $mutex.  See `"Win32::IPC"' in this node.

Deprecated Functions and Methods
--------------------------------

   *Win32::Mutex* still supports the ActiveWare syntax, but its use is
deprecated.

Create($MutObj,$Initial,$Name)
     Use `$MutObj = Win32::Mutex->new($Initial,$Name)' instead.

Open($MutObj,$Name)
     Use `$MutObj = Win32::Mutex->open($Name)' instead.

$MutObj->Release()
     Use `$MutObj->release' instead.

AUTHOR
======

   Christopher J. Madsen <`chris_madsen@geocities.com'>

   Loosely based on the original module by ActiveWare Internet Corp.,
`http://www.ActiveWare.com'

manage network groups and users in perl
***************************************

NAME
====

   Win32::NetAdmin - manage network groups and users in perl

SYNOPSIS
========

     use Win32::NetAdmin;

DESCRIPTION
===========

   This module offers control over the administration of groups and users
over a network.

FUNCTIONS
=========

NOTE
----

   All of the functions return FALSE (0) if they fail, unless otherwise
noted.  server is optional for all the calls below. If not given the local
machine is assumed.

GetDomainController(server, domain, returnedName)
     Returns the name of the domain controller for server.

GetAnyDomainController(server, domain, returnedName)
     Returns the name of any domain controller for a domain that is
     directly trusted by the server.

UserCreate(server, userName, password, passwordAge, privilege, homeDir, comment, flags, scriptPath)
     Creates a user on server with password, passwordAge, privilege,
     homeDir, comment, flags, and scriptPath.

UserDelete(server, user)
     Deletes a user from server.

UserGetAttributes(server, userName, password, passwordAge, privilege, homeDir, comment, flags, scriptPath)
     Gets password, passwordAge, privilege, homeDir, comment, flags, and
     scriptPath for user.

UserSetAttributes(server, userName, password, passwordAge, privilege, homeDir, comment, flags, scriptPath)
     Sets password, passwordAge, privilege, homeDir, comment, flags, and
     scriptPath for user.

UserChangePassword(domainname, username, oldpassword, newpassword)
     Changes a users password. Can be run under any account.

UsersExist(server, userName)
     Checks if a user exists.

GetUsers(server, filter, userRef)
     Fills userRef with user names if it is an array reference and with
     the user names and the full names if it is a hash reference.

GroupCreate(server, group, comment)
     Creates a group.

GroupDelete(server, group)
     Deletes a group.

GroupGetAttributes(server, groupName, comment)
     Gets the comment.

GroupSetAttributes(server, groupName, comment)
     Sets the comment.

GroupAddUsers(server, groupName, users)
     Adds a user to a group.

GroupDeleteUsers(server, groupName, users)
     Deletes a users from a group.

GroupIsMember(server, groupName, user)
     Returns TRUE if user is a member of groupName.

GroupGetMembers(server, groupName, userArrayRef)
     Fills userArrayRef with the members of groupName.

LocalGroupCreate(server, group, comment)
     Creates a local group.

LocalGroupDelete(server, group)
     Deletes a local group.

LocalGroupGetAttributes(server, groupName, comment)
     Gets the comment.

LocalGroupSetAttributes(server, groupName, comment)
     Sets the comment.

LocalGroupIsMember(server, groupName, user)
     Returns TRUE if user is a member of groupName.

LocalGroupGetMembers(server, groupName, userArrayRef)
     Fills userArrayRef with the members of groupName.

LocalGroupGetMembersWithDomain(server, groupName, userRef)
     This function is similar LocalGroupGetMembers but accepts an array or
     a hash reference. Unlike LocalGroupGetMembers it returns each user
     name as `DOMAIN\USERNAME'. If a hash reference is given, the function
     returns to each user or group name the type (group, user, alias etc.).
     The possible types are as follows:

          $SidTypeUser = 1;
          $SidTypeGroup = 2;
          $SidTypeDomain = 3;
          $SidTypeAlias = 4;
          $SidTypeWellKnownGroup = 5;
          $SidTypeDeletedAccount = 6;
          $SidTypeInvalid = 7;
          $SidTypeUnknown = 8;

LocalGroupAddUsers(server, groupName, users)
     Adds a user to a group.

LocalGroupDeleteUsers(server, groupName, users)
     Deletes a users from a group.

GetServers(server, domain, flags, serverRef)
     Gets an array of server names or an hash with the server names and the
     comments as seen in the Network Neighborhood or the server manager.
     For flags, see SV_TYPE_* constants.

GetTransports(server, transportRef)
     Enumerates the network transports of a computer. If transportRef is
     an array reference, it is filled with the transport names. If
     transportRef is a hash reference then a hash of hashes is filled with
     the data for the transports.

LoggedOnUsers(server, userRef)
     Gets an array or hash with the users logged on at the specified
     computer. If userRef is a hash reference, the value is a semikolon
     separated string of username, logon domain and logon server.

GetAliasFromRID(server, RID, returnedName)
GetUserGroupFromRID(server, RID, returnedName)
     Retrieves the name of an alias (i.e local group) or a user group for
     a RID from the specified server. These functions can be used for
     example to get the account name for the administrator account if it
     is renamed or localized.

     Possible values for `RID':

          DOMAIN_ALIAS_RID_ACCOUNT_OPS
          DOMAIN_ALIAS_RID_ADMINS
          DOMAIN_ALIAS_RID_BACKUP_OPS
          DOMAIN_ALIAS_RID_GUESTS
          DOMAIN_ALIAS_RID_POWER_USERS
          DOMAIN_ALIAS_RID_PRINT_OPS
          DOMAIN_ALIAS_RID_REPLICATOR
          DOMAIN_ALIAS_RID_SYSTEM_OPS
          DOMAIN_ALIAS_RID_USERS
          DOMAIN_GROUP_RID_ADMINS
          DOMAIN_GROUP_RID_GUESTS
          DOMAIN_GROUP_RID_USERS
          DOMAIN_USER_RID_ADMIN
          DOMAIN_USER_RID_GUEST

GetServerDisks(server, arrayRef)
     Returns an array with the disk drives of the specified server. The
     array contains two-character strings (drive letter followed by a
     colon).

EXAMPLE
=======

     # Simple script using Win32::NetAdmin to set the login script for
     # all members of the NT group "Domain Users".  Only works if you
     # run it on the PDC. (From Robert Spier <rspier@seas.upenn.edu>)
     #
     # FILTER_TEMP_DUPLICATE_ACCOUNTS
     #	Enumerates local user account data on a domain controller.
     #
     # FILTER_NORMAL_ACCOUNT
     #	Enumerates global user account data on a computer.
     #
     # FILTER_INTERDOMAIN_TRUST_ACCOUNT
     #	Enumerates domain trust account data on a domain controller.
     #
     # FILTER_WORKSTATION_TRUST_ACCOUNT
     #	Enumerates workstation or member server account data on a domain
     #	controller.
     #
     # FILTER_SERVER_TRUST_ACCOUNT
     #	Enumerates domain controller account data on a domain controller.

     use Win32::NetAdmin qw(GetUsers GroupIsMember
     			   UserGetAttributes UserSetAttributes);

     my %hash;
     GetUsers("", FILTER_NORMAL_ACCOUNT , \%hash)
     	or die "GetUsers() failed: $^E";

     foreach (keys %hash) {
     	my ($password, $passwordAge, $privilege,
     	    $homeDir, $comment, $flags, $scriptPath);
     	if (GroupIsMember("", "Domain Users", $_)) {
     	    print "Updating $_ ($hash{$_})\n";
     	    UserGetAttributes("", $_, $password, $passwordAge, $privilege,
     			      $homeDir, $comment, $flags, $scriptPath)
     		or die "UserGetAttributes() failed: $^E";
     	    $scriptPath = "dnx_login.bat"; # this is the new login script
     	    UserSetAttributes("", $_, $password, $passwordAge, $privilege,
     			      $homeDir, $comment, $flags, $scriptPath)
     		or die "UserSetAttributes() failed: $^E";
     	}
     }

manage network resources in perl
********************************

NAME
====

   Win32::NetResource - manage network resources in perl

SYNOPSIS
========

     use Win32::NetResource;

     $ShareInfo = {
                     'path' => "C:\\MyShareDir",
                     'netname' => "MyShare",
                     'remark' => "It is good to share",
                     'passwd' => "",
                     'current-users' =>0,
                     'permissions' => 0,
                     'maxusers' => -1,
                     'type'  => 0,
                     };

     Win32::NetResource::NetShareAdd( $ShareInfo,$parm )
         or die "unable to add share";

DESCRIPTION
===========

   This module offers control over the network resources of Win32.Disks,
printers etc can be shared over a network.

DATA TYPES
==========

   There are two main data types required to control network resources.
In Perl these are represented by hash types.

%NETRESOURCE
          KEY                    VALUE

          'Scope'         =>  Scope of an Enumeration
                              RESOURCE_CONNECTED,
                              RESOURCE_GLOBALNET,
                              RESOURCE_REMEMBERED.

          'Type'          =>  The type of resource to Enum
                              RESOURCETYPE_ANY    All resources
                              RESOURCETYPE_DISK    Disk resources
                              RESOURCETYPE_PRINT    Print resources

          'DisplayType'   =>  The way the resource should be displayed.
                              RESOURCEDISPLAYTYPE_DOMAIN
                              The object should be displayed as a domain.
                              RESOURCEDISPLAYTYPE_GENERIC
                              The method used to display the object does not matter.
                              RESOURCEDISPLAYTYPE_SERVER
                              The object should be displayed as a server.
                              RESOURCEDISPLAYTYPE_SHARE
                              The object should be displayed as a sharepoint.

          'Usage'         =>  Specifies the Resources usage:
                              RESOURCEUSAGE_CONNECTABLE
                              RESOURCEUSAGE_CONTAINER.

          'LocalName'     =>  Name of the local device the resource is
                              connected to.

          'RemoteName'    =>  The network name of the resource.

          'Comment'       =>  A string comment.

          'Provider'      =>  Name of the provider of the resource.

%SHARE_INFO
     This hash represents the SHARE_INFO_502 struct.

          KEY                    VALUE
          'netname'        =>    Name of the share.
          'type'           =>    type of share.
          'remark'         =>    A string comment.
          'permissions'    =>    Permissions value
          'maxusers'       =>    the max # of users.
          'current-users'  =>    the current # of users.
          'path'           =>    The path of the share.
          'passwd'         =>    A password if one is req'd

FUNCTIONS
=========

NOTE
----

   All of the functions return FALSE (0) if they fail.

GetSharedResources(\@Resources,dwType)
     Creates a list in @Resources of %NETRESOURCE hash references.

     The return value indicates whether there was an error in accessing
     any of the shared resources.  All the shared resources that were
     encountered (until the point of an error, if any) are pushed into
     @Resources as references to %NETRESOURCE hashes.  See example below.

AddConnection(\%NETRESOURCE,$Password,$UserName,$Connection)
     Makes a connection to a network resource specified by %NETRESOURCE

CancelConnection($Name,$Connection,$Force)
     Cancels a connection to a network resource connected to local device
     $name.$Connection is either 1 - persistent connection or 0,
     non-persistent.

WNetGetLastError($ErrorCode,$Description,$Name)
     Gets the Extended Network Error.

GetError( $ErrorCode )
     Gets the last Error for a Win32::NetResource call.

GetUNCName( $UNCName, $LocalPath );
     Returns the UNC name of the disk share connected to $LocalPath in
     $UNCName.

NOTE
----

   $servername is optional for all the calls below. (if not given the
local machine is assumed.)

NetShareAdd(\%SHARE,$parm_err,$servername = NULL )
     Add a share for sharing.

NetShareCheck($device,$type,$servername = NULL )
     Check if a share is available for connection.

NetShareDel( $netname, $servername = NULL )
     Remove a share from a machines list of shares.

NetShareGetInfo( $netname, \%SHARE,$servername=NULL )
     Get the %SHARE_INFO information about the share $netname on the
     server $servername.

NetShareSetInfo( $netname,\%SHARE,$parm_err,$servername=NULL)
     Set the information for share $netname.

EXAMPLE
=======

     #
     # This example displays all the share points in the entire
     # visible part of the network.
     #

     use strict;
     use Win32::NetResource qw(:DEFAULT GetSharedResources GetError);
     my $resources = [];
     unless(GetSharedResources($resources, RESOURCETYPE_ANY)) {
     	my $err = undef;
     	GetError($err);
     	warn Win32::FormatMessage($err);
     }

     foreach my $href (@$resources) {
     	next if ($$href{DisplayType} != RESOURCEDISPLAYTYPE_SHARE);
     	print "-----\n";
     	foreach( keys %$href){
     	    print "$_: $href->{$_}\n";
     	}
     }

AUTHOR
======

   Jesse Dougherty for Hip Communications.

   Additional general cleanups and bug fixes by Gurusamy Sarathy
<gsar@activestate.com>.

accessing the Windows NT Performance Counter
********************************************

NAME
====

   Win32::PerfLib - accessing the Windows NT Performance Counter

SYNOPSIS
========

     use Win32::PerfLib;
     my $server = "";
     Win32::PerfLib::GetCounterNames($server, \%counter);
     %r_counter = map { $counter{$_} => $_ } keys %counter;
     # retrieve the id for process object
     $process_obj = $r_counter{Process};
     # retrieve the id for the process ID counter
     $process_id = $r_counter{'ID Process'};

     # create connection to $server
     $perflib = new Win32::PerfLib($server);
     $proc_ref = {};
     # get the performance data for the process object
     $perflib->GetObjectList($process_obj, $proc_ref);
     $perflib->Close();
     $instance_ref = $proc_ref->{Objects}->{$process_obj}->{Instances};
     foreach $p (sort keys %{$instance_ref})
     {
         $counter_ref = $instance_ref->{$p}->{Counters};
         foreach $i (keys %{$counter_ref})
         {
     	  if($counter_ref->{$i}->{CounterNameTitleIndex} == $process_id)
     	  {
     	      printf( "% 6d %s\n", $counter_ref->{$i}->{Counter},
     		      $instance_ref->{$p}->{Name}
     		    );
     	  }
         }
     }

DESCRIPTION
===========

   This module allows to retrieve the performance counter of any computer
(running Windows NT) in the network.

FUNCTIONS
=========

NOTE
----

   All of the functions return FALSE (0) if they fail, unless otherwise
noted.  If the $server argument is undef the local machine is assumed.

Win32::PerfLib::GetCounterNames($server,$hashref)
     Retrieves the counter names and their indices from the registry and
     stores them in the hash reference

Win32::PerfLib::GetCounterHelp($server,$hashref)
     Retrieves the counter help strings and their indices from the
     registry and stores them in the hash reference

$perflib = Win32::PerfLib->new ($server)
     Creates a connection to the performance counters of the given server

$perflib->GetObjectList($objectid,$hashref)
     retrieves the object and counter list of the given performance object.

$perflib->Close($hashref)
     closes the connection to the performance counters

Win32::PerfLib::GetCounterType(countertype)
     converts the counter type to readable string as referenced in
     `calc.html' in this node so that it is easier to find the appropriate
     formula to calculate the raw counter data.

Datastructures
==============

   The performance data is returned in the following data structure:

Level 1
          $hashref = {
              'NumObjectTypes'   => VALUE
              'Objects'          => HASHREF
              'PerfFreq'         => VALUE
              'PerfTime'         => VALUE
              'PerfTime100nSec'  => VALUE
              'SystemName'       => STRING
              'SystemTime'       => VALUE
          }

Level 2
     The hash reference $hashref->{Objects} has the returned object ID(s)
     as keys and a hash reference to the object counter data as value.
     Even there is only one object requested in the call to GetObjectList
     there may be more than one object in the result.

          $hashref->{Objects} = {
              <object1>  => HASHREF
              <object2>  => HASHREF
              ...
          }

Level 3
     Each returned object ID has object-specific performance information.
     If an object has instances like the process object there is also a
     reference to the instance information.

          $hashref->{Objects}->{<object1>} = {
              'DetailLevel'           => VALUE
              'Instances'             => HASHREF
              'Counters'              => HASHREF
              'NumCounters'           => VALUE
              'NumInstances'          => VALUE
              'ObjectHelpTitleIndex'  => VALUE
              'ObjectNameTitleIndex'  => VALUE
              'PerfFreq'              => VALUE
              'PerfTime'              => VALUE
          }

Level 4
     If there are instance information for the object available they are
     stored in the 'Instances' hashref. If the object has no instances
     there is an 'Counters' key instead. The instances or counters are
     numbered.

          $hashref->{Objects}->{<object1>}->{Instances} = {
              <1>     => HASHREF
              <2>     => HASHREF
              ...
              <n>     => HASHREF
          }
          or
          $hashref->{Objects}->{<object1>}->{Counters} = {
              <1>     => HASHREF
              <2>     => HASHREF
              ...
              <n>     => HASHREF
          }

Level 5
          $hashref->{Objects}->{<object1>}->{Instances}->{<1>} = {
              Counters               => HASHREF
              Name                   => STRING
              ParentObjectInstance   => VALUE
              ParentObjectTitleIndex => VALUE
          }
          or
          $hashref->{Objects}->{<object1>}->{Counters}->{<1>} = {
              Counter               => VALUE
              CounterHelpTitleIndex => VALUE
              CounterNameTitleIndex => VALUE
              CounterSize           => VALUE
              CounterType           => VALUE
              DefaultScale          => VALUE
              DetailLevel           => VALUE
              Display               => STRING
          }

Level 6
          $hashref->{Objects}->{<object1>}->{Instances}->{<1>}->{Counters} = {
              <1>     => HASHREF
              <2>     => HASHREF
              ...
              <n>     => HASHREF
          }

Level 7
          $hashref->{Objects}->{<object1>}->{Instances}->{<1>}->{Counters}->{<1>} = {
              Counter               => VALUE
              CounterHelpTitleIndex => VALUE
              CounterNameTitleIndex => VALUE
              CounterSize           => VALUE
              CounterType           => VALUE
              DefaultScale          => VALUE
              DetailLevel           => VALUE
              Display               => STRING
          }

     Depending on the *CounterType* there are calculations to do (see
     calc.html).

AUTHOR
======

   Jutta M. Klebe, jmk@bybyte.de

SEE ALSO
========

   perl(1).

stand-in for child process in ProcFarm RPC system
*************************************************

NAME
====

   Win32::ProcFarm::Parent - stand-in for child process in ProcFarm RPC
system

SYNOPSIS
========

     use Win32::ProcFarm::Parent;
     use Win32::ProcFarm::Port;

     $port_obj = Win32::ProcFarm::Port->new(9000, 1);

     $iface = Win32::ProcFarm::Parent->new_async($port_obj, 'Child.pl', Win32::GetCwd);

     $iface->connect;

     $iface->execute('child_sub', @params);

     until($iface->get_state eq 'fin') {
       print "Waiting for ReturnValue.\n";
       sleep(1);
     }
     print "GotReturnValue.\n";
     print $iface->get_retval;

DESCRIPTION
===========

Installation instructions
-------------------------

   This installs with MakeMaker as part of Win32::ProcFarm.

   To install via MakeMaker, it's the usual procedure - download from CPAN,
extract, type "perl Makefile.PL", "nmake" then "nmake install". Don't do
an "nmake test" because the I haven't written a test suite yet.

State Diagram
-------------

   `Win32::ProcFarm::Parent' is designed to provide support for
asynchronous subroutine calls against the child process.  To support this,
the `Win32::ProcFarm::Parent' object can be in one of four states.

init
     In the init state, the `Win32::ProcFarm::Parent' object has been
     asynchronously spun off, but has yet to establish a communications
     channel via the `Win32::ProcFarm::Port' object.  A call to the
     connect method will rectify this situation and move the object into
     the idle state.

idle
     In the idle state, the child process has yet to be assigned a task
     and is waiting for one to be assigned.  A call to the execute method
     will assign the child process a task and move the
     `Win32::ProcFarm::Parent' object into the wait state.

wait
     In the wait state, the child process has been assigned a task and is
     busy executing it.  Calls to the get_state method will check to see
     if the task has finished executing.  If it has, the
     `Win32::ProcFarm::Parent' object will retrieve the return values,
     store them internally, and move the object into the `fin' state.

`fin'
     In the `fin' state, the `Win32::ProcFarm::Parent' object is waiting
     for the return values to be retrieved by the get_retval method.  A
     call to that method will return the values and move the object back
     into the idle state.

METHODS
=======

new_async
---------

   The new_async method creates a new `Win32::ProcFarm::Parent' object and
spins off the child process, but does not initiate communication with it.
The `Win32::ProcFarm::Parent' object is left in the init state.

   The parameters are:

$port_obj
     A `Win32::ProcFarm::Port' object that will be connected to by the
     child processes.

$script
     The script name to execute for the child processes.

$curdir
     The working directory to use when running the script.  If this is the
     same directory the script is in, the script name can be specified
     without a path.

$timeout
     An optional value indicating how long jobs should be allowed to
     execute before they are deemed to have blocked.  Blocked jobs will be
     terminated and a new process created to take their place.

connect
-------

   The connect method initiates communication with a child process.  Note
that we cannot presume that the order in which the child processes connect
to the TCP port is the same order in which they were started.  The first
thing the child process does upon the TCP connection being accepted is to
send its unique identifier, which the `Win32::ProcFarm::Parent' object
uses to retrieve the appropriate `Win32::Process' from the class hash of
those objects.

   The connect call moves the `Win32::ProcFarm::Parent' object into the
idle state.

execute
-------

   The execute command instructs the child process to start executing a
given subroutine with a list of passed parameters.  The data is send over
the socket connection and the `Win32::ProcFarm::Parent' object moved into
the wait state.

get_state
---------

   The get_state method returns the current state.  If the current state
is wait, the method first checks to see if the child process has finished
executing the subrouting call.  If it has, the method retrieves the return
data and moves the `Win32::ProcFarm::Parent' object into the `fin' state.

   The get_state method is also responsible for dealing with timeout
scenarios where the child process has exceeded the time allowed to execute
the subroutine.  In that situation, the child process is terminated and a
new child process initiated, connected to, and the
`Win32::ProcFarm::Parent' object placed in the `fin' state.

get_retval
----------

   The get_retval method returns the list of return values returned by the
child process and moves the `Win32::ProcFarm::Parent' object into the idle
state.

manages a pool of child processes for perpetual jobs
****************************************************

NAME
====

   Win32::ProcFarm::PerpetualPool - manages a pool of child processes for
perpetual jobs

SYNOPSIS
========

     use Win32::ProcFarm::PerpetualPool;

     $Pool = Win32::ProcFarm::PerpetualPool->new($poolsize, $portnum, $scriptname, Win32::GetCwd,
       command => 'whatever',
       list_check_intvl => 30,
       exit_check_intvl => 5,
       list_sub => sub { return ('Fred', 'Julie', 'Joe') },
       exit_sub => sub { return -e 'killme'; },
       result_sub => sub { print join(', ' @_)."\n"; },
     );

     $Pool->start_pool(0.1);

DESCRIPTION
===========

Installation instructions
-------------------------

   This installs with MakeMaker as part of Win32::ProcFarm.

   To install via MakeMaker, it's the usual procedure - download from CPAN,
extract, type "perl Makefile.PL", "nmake" then "nmake install". Don't do
an "nmake test" because the I haven't written a test suite yet.

More usage instructions
-----------------------

   This is a version of Win32::ProcFarm::Pool designed for continuous
operation.  You supply a single command name and a subroutine that returns
a list of keys.  The keys are passed as the sole parameter to the command
(it is presumed that the child process can do whatever needs to be done
based on that single key).  The subroutine that returns the list of keys
will be periodically executed (every 120 seconds by default, but
adjustable via list_intvl) and the running list updated as needed.
Whenever a job finishes, that key is added back onto the end of the waiting
pool.

METHODS
=======

manages a pool of child processes
*********************************

NAME
====

   Win32::ProcFarm::Pool - manages a pool of child processes

SYNOPSIS
========

     use Win32::ProcFarm::Pool;

     $Pool = Win32::ProcFarm::Pool->new($poolsize, $portnum, $scriptname, Win32::GetCwd);

     foreach $i (@list) {
       $Pool->add_waiting_job($i, 'child_sub', $i);
     }

     $Pool->do_all_jobs(0.1);

     %ping_data = $Pool->get_return_data;
     $Pool->clear_return_data;

     foreach $i (@list) {
       print "$i:\t$ping_data{$i}->[0]\n";
     }

DESCRIPTION
===========

Installation instructions
-------------------------

   This installs with MakeMaker as part of Win32::ProcFarm.

   To install via MakeMaker, it's the usual procedure - download from CPAN,
extract, type "perl Makefile.PL", "nmake" then "nmake install". Don't do
an "nmake test" because the I haven't written a test suite yet.

More usage instructions
-----------------------

   See `Docs/tutorial.pod' for more information.

METHODS
=======

new
---

   The new method creates a new `Win32::ProcFarm::Pool' object (amazing,
eh!).  It takes 5 parameters:

$num_threads
     This indicates the number of threads that should be created.

$port_num
     This indicates the port number to use for the listener.

$script
     The script name to execute for the child processes.

$curdir
     The working directory to use when running the script.  If this is the
     same directory the script is in, the script name can be specified
     without a path.

%options
     A hash of options.  The current options are:

    timeout
          Indicates how long jobs should be allowed to execute before they
          are deemed to have blocked.  Blocked jobs will be terminated and
          a new process created to take their place.

add_waiting_job
---------------

   The add_waiting_job method adds a job to the waiting pool.  It takes
three parameters:

$key
     This should be a unique identifier that will be used to retrieve the
     return values from the return data hash.

$command
     The name of the subroutine that the child process will execute.

@params
     A list of parameters for that subroutine.

do_all_jobs
-----------

   The do_all_jobs command will execute all the jobs in the waiting pool.
The single passed parameter specifies the number of seconds to wait
between sweeps through the thread pool to check for completed jobs.  The
number of seconds can be fractional (i.e. 0.1 for a tenth of a second).

get_return_data
---------------

   Return the return_data hash, indexed on the unique key passed initially.

clear_return_data
-----------------

   Clears out the return_data hash.

INTERNAL METHODS
================

   These methods are considered internal methods.  Child classes of
Win32::ProcFarm::Pool may modify these methods in order to change the
behavior of the resultant Pool object.

manages access to the TCP port for ProcFarm system
**************************************************

NAME
====

   Win32::ProcFarm::Port - manages access to the TCP port for ProcFarm
system

SYNOPSIS
========

     use Win32::ProcFarm::Port;

     $port_obj = Win32::ProcFarm::Port->new(9000, 1);

     print $port_obj->get_port_num;

     $socket = $port_obj->get_next_connection;

DESCRIPTION
===========

Installation instructions
-------------------------

   This installs with MakeMaker as part of Win32::ProcFarm.

   To install via MakeMaker, it's the usual procedure - download from CPAN,
extract, type "perl Makefile.PL", "nmake" then "nmake install". Don't do
an "nmake test" because the I haven't written a test suite yet.

METHODS
=======

new
---

   The new method creates a new `Win32::ProcFarm::Port' object (fancy
that!).  It takes two parameters - the first is the port number to listen
on, and the second is the number of listeners to create - this will
specify the number of "hold lines" for the port object.

get_port_num
------------

   This returns the port number passed in the new method.

get_next_connection
-------------------

   This accepts an inbound connection and returns the socket object.  If
the inbound connection is not from 127.0.0.1, the method calls die as this
indicates an attempt to hack the system by an external host.

managing dialup entries and network connections on Win32
********************************************************

NAME
====

   Win32::RASE - managing dialup entries and network connections on Win32

SYNOPSIS
========

     use Win32::RASE;

ABSTRACT
========

   This module implements the client part of Win32 RAS API.

   It is named RASE(RAS-entry) because it was originally designed to
create/delete/change/manage RAS/DUN entries. Now it implements synchronous
dialing, hang up and the wide range of RAS/DUN entry manipulations.

   The current version of Win32::RASE is available at:

     http://www.dux.ru/guest/fno/perl/

DESCRIPTION
===========

   This module is a collection of subroutines. As their names are very long
and specific and almost each corresponds to a Win32 API call I decided to
export a lot of them by default. Everything is exported except those subs
that are claimed as non-exported.

   OK, you can require it instead of use.

   *!!! IMPORTANT !!!* All functions (if the other behavior is not stated
explicitly) return TRUE on success, FALSE on error to conform the handy
calling rule

     RESULT = function(PARAMS) or die MESSAGE;

   where RESULT could be scalar or list either. Note that "||" is not the
same thing as "or".

   The following logic is used: almost all functions croak on obvious
programmer's errors like invalid entry-name or such.  But they return
FALSE and set LastError on internal API errors.  It is made to give the
programmer a chance to complete all actions and may be to trap some errors
without exiting the program.

   For example if some phonebook file is corrupted you have a chance to
try another one etc.

   The following two functions are available after any other function was
executed.  They are both non-exported to provide feel and look of
Win32-Perl built-in functions with the same names.

GetLastError ( )
     Returns 0 or the last encountered RAS, TAPI or Windows error number.

          $lastErr = Win32::RASE::GetLastError();

     Usually you should call this function after some other function
     returned undef. In case of Windows error it returns the same value as
     `Win32::GetLastError'. Unlike the built-in one it always returns 0 if
     the last called function finished successfully.

     You can use it for example like this:

          some_function();
          Win32::RASE::GetLastError and die Win32::RASE::FormatMessage;

     or implicitly

          some_function() or die Win32::RASE::FormatMessage;

FormatMessage ( )
     Converts the supplied RAS, TAPI or Win32 error number (e.g.  returned
     by `Win32::RASE::GetLastError()') to a descriptive string.

          $message = Win32::RASE::FormatMessage($err_num);

     Without the parameter assumes that the result of
     `Win32::RASE::GetLastError()' was sent.

IsWindow ( )
     This function is non-exported for not to corrupt some other GUI
     related synonym.

          Win32::RASE::IsWindow( $hwnd );

     Returns TRUE if $hwnd identifies an existing window, otherwise FALSE.

     This function is handy to use before the functions that display a
     dialog box - to verify the parent window.

   * =====================================*

   * PHONEBOOK RELATED FUNCTIONS*

   * =====================================*

   Note that by default all functions in this section work with the
default phonebook (on Windows NT).

   The registry key `"HKEY_CURRENT_USER\Software\Microsoft\RAS Phonebook"'
has a dword subkey "PhonebookMode" which could have 3 values:

     0 - the "system" phonebook is in use.
         This is probably %SYSTEMROOT%\system32\ras\rasphone.pbk
     1 - the "user" phonebook is in use.
         This one is located in  %SYSTEMROOT%\system32\ras\<filename>
         <filename> here is the value of "PersonalPhonebookFile" subkey
         that is located under the same key.
     2 - the "alternate" phonebook is in use.
         The full path to the alternate phonebook could be found in the
         "AlternatePhonebookPath" subkey under the same key.

   This version of `Win32::RASE' provides no way to change these registry
settings. If `"HKEY_CURRENT_USER\Software\Microsoft\RAS
Phonebook\PhonebookMode"' is equal to 0 `Win32::RASE' will use the
"system" phonebook, in case 1 - the "user" phonebook, in case 2 - the
"alternate" phonebook.

   The user can use the main Dial-Up Networking dialog box to create
personal phonebook files or change defaults (registry settings). The Win32
API does not currently provide support for creating a phonebook file.

   *IMPORTANT:*

   At any time you can set a global variable *$Win32::RASE::PHONEBOOK* to
the full path of your phonebook file, and this phonebook will be in use
until *$Win32::RASE::PHONEBOOK* is changed. Setting this variable to 0 or
undef returns us to registry defined phonebook(s).

   *Windows 95/98:* Dial-up networking stores phonebook entries in the
registry rather than in a phonebook file. Windows 9x does not support
personal phonebook files. So *$Win32::RASE::PHONEBOOK* has no meaning and
must always be undef.

   All functions treat entry-names as case-sensitive because RAS functions
are kinda semi-case-sensitive. Some of them fail when entry was given with
case-changes. But at the same time RasSetEntryProperties API call (in
`RasCopyEntry()') fails to create both QWERTY and QwErTy, it renames
instead. Ou-h-h MS, MS...

   The moral is: don't use names that differ only in upper/lower case.

   There also is a danger in using multiple processes that are calling RAS
APIs that update the phonebook. Microsoft reported this problem has been
corrected in Service Pack 3.

http://support.microsoft.com/support/ntserver/serviceware/nts40/E9MSKWBJI.ASP

   *A note on multilink functionality*: there are no ways to use Multilink
programmatically on Win95/98. So, the current version of the module does
not support it for WinNT also. For more info read:

   http://support.microsoft.com/support/kb/articles/q198/7/77.asp

   Entry names for Windows CE cannot exceed 20 characters.
http://msdn.microsoft.com/library/wincesdk/wcecomm/ras_24.htm

   A similiar problem is reported for the InternetMail Service (IMS) on MS
BackOffice Small Business Server version 4.5 and Windows NT Server version
4.0 http://support.microsoft.com/support/kb/articles/Q217/9/37.asp

   So, the entries with long names may be unusable by the other
applications.

RasCreateEntryDlg ( )
     This function displays a dialog box in which the user types
     information about the phonebook entry.

          RasCreateEntryDlg( [$hwnd] );

          $hwnd  - handle to the parent window of the dialog box. Optional.
                   If you are using Win32::GUI this would be $Window->{handle}

     As this is a synchronous operation and waits for user input it
     provides no way to find out whether the new entry was created or not.
     You should use `RasEnumEntries()' to understand what has happened.

     Here and everywhere in the functions that display a dialog box - if
     `$hwnd' is omitted or does not identify an existing window a dialog
     box is centered on the screen.

RasEditEntryDlg ( )
     This function displays a dialog box in which the user types
     information about the phonebook entry. For a programmatical way to
     edit an existing entry take a look at `RasSetEntryProperties()'.

          RasEditEntryDlg( $entry [, $hwnd] );

          $entry - existing phonebook entry to edit.

          $hwnd  - handle to the parent window of the dialog box. Optional.
                   If you are using Win32::GUI this would be $Window->{handle}

     This is a synchronous operation and waits for user input.

     Croaks if $entry does not exist.  You should call `IsEntry()' before
     to verify $entry.

RasRenameEntry ( )
          RasRenameEntry( $oldname, $newname );

     Croaks if `$oldname' does not exist or `$newname' already exists.
     You should call `IsEntry()' or `RasEnumEntries()' before to verify
     both.

RasDeleteEntry ( )
          RasDeleteEntry( $entry );

     Croaks if $entry does not exist.  You should call `IsEntry()' or
     `RasEnumEntries()' before to verify $entry.

RasEnumEntries ( )
          @entries = RasEnumEntries();

     This function lists all entry names in the phonebook.

     As this function is heavily used internally it croaks on errors - for
     example if non-existing phonebook name is given. So, FALSE result
     means that the selected phonebook is empty.

     Command line syntax:

          perl -MWin32::RASE -e "$,=q{, };print RasEnumEntries"

IsEntry ( )
          IsEntry ( $entry );

          $entry  - name of the RAS/DUN entry

     Returns TRUE if $entry was found in the phonebook, otherwise FALSE.

     *NOTE!* It treats entry-names as case-sensitive (see above).

RasGetEntryDialParams ( )
     This function retrieves the connection information saved by the last
     successful call to the `RasDial()' or `RasSetEntryDialParams()'
     function for a specified phonebook entry.

          ($UserName, $Password, $Domain, $CallbackNumber) =
                                     RasGetEntryDialParams($entry);

          $entry          - name of RAS/DUN entry
          $UserName       - user's user name ;-)
          $Password       - yes, it's that secure
          $Domain         - domain on which authentication is to occur
          $CallbackNumber - callback phone number

     Croaks if $entry does not exist.

RasGetUserPwd ( )
     The short variant of previous.

          ($UserName, $Password) = RasGetUserPwd($entry);

     Croaks if $entry does not exist.

     Command line syntax:

          perl -MWin32::RASE -e "print ((RasGetUserPwd('NEV1'))[0])"
          perl -MWin32::RASE -e "@_=RasGetUserPwd('NEV1');print qq{@_}"

RasSetEntryDialParams ( )
     This function changes the connection information for a specified
     phonebook entry.

          RasSetEntryDialParams($entry, $UserName, $Password, $Domain,
                                $CallbackNumber, $fRemovePassword);

     All parameters except $entry are optional. undef or omitted
     parameters are considered to be "" - this means that no changes will
     be made to this parameter.

          $entry           - name of RAS/DUN entry
          $UserName        - user name
          $Password        - password for the user specified by $UserName.
               If $UserName is an empty string, the password is not changed.
               If $Password is an empty string and $fRemovePassword is FALSE,
               the password is set to the empty string. If $fRemovePassword is
               TRUE, the password stored in this phonebook entry for the user
               specified by $UserName is removed regardless of the contents
               of the $Password string.
          $Domain          - domain on which authentication is to occur.
                             15 chars limitation.
          $CallbackNumber  - callback phone number
          $fRemovePassword - (above) 0 if undefined/omitted

     This is another excerpt from the API docs:

     *Windows NT:* You can use $Password to send a new password to the
     remote server when you restart a RasDial() connection from a
     RASCS_PasswordExpired paused state.  When changing a password on an
     entry that calls Microsoft Networks, you should limit the new
     password to 14 characters in length to avoid down-level compatibility
     problems.

     Croaks if $entry does not exist.

RasGetEntryProperties ( )
     This function retrieves the properties of a phonebook entry.

          $props = RasGetEntryProperties($entry);

          $entry          - name of RAS/DUN entry
          $props          - pointer to hash

     The description of the %$props hash is common for this function and
     `RasSetEntryProperties()'.

          KEY                         VALUE

          name           - copy of $entry
          Flags          - numeric flag value, combination of RASEO_* flags.
                           You don't need to use it directly, it's here for
                           information purpose only. In RasSetEntryProperties()
                           it is ignored if present, you should manipulate
                           mnemonic flags as described below, with the
                           'newFlags' key.
          FlagsReadable  - $props->{FlagsReadable} refers to array of
                           "mnemonic flags" that are affecting the behavior
                           of the other properties.
                           Not used by RasSetEntryProperties().

     Manipulating these flags is described in `RasSetEntryProperties()'
     section.

          ipaddr         - constant ip-address, ignored unless "SpecificIpAddr"
                           is present in the array of "mnemonic flags"
          ipaddrDns      - primary DNS server
          ipaddrDnsAlt   - secondary(backup) DNS server
          ipaddrWins     - IP address of the primary WINS server
          ipaddrWinsAlt  - secondary WINS server

     `ipaddrDns', `ipaddrDnsAlt', `ipaddrWins', `ipaddrWinsAlt' are
     ignored unless "SpecificNameServers" is present in the array of
     "mnemonic flags"

     All IP-addresses are in xxx.xxx.xxx.xxx decimal form without leading
     zeros in each part(octet). For example: 195.100.0.28

     The common rule here is that empty or blank values will produce
     0.0.0.0 (as well as "0.0.0.0" itself).

          CountryID        -
          CountryName      -
          CountryCode      -
          AreaCode         -

     (Country ID-Name-Code and AreaCode are described in the
     `TAPIlineGetTranslateCaps()' section except that here they are
     describing the computer you want to dial to.)

     In `RasSetEntryProperties()' `CountryName' would be ignored.
     `CountryID' not matching `CountryCode' would give error. You could
     easily give only one of these two values. `CountryCode' would be
     counted properly if `CountryID' is given (described in
     `TAPIlineGetTranslateCaps()' section). But if you'll give
     `CountryCode' `CountryID' would be set equal to `CountryCode' that is
     sometimes incorrect but does not affect the dialup connection.

     You can also check the correctness of the `CountryID' with the
     `IsCountryID()' function.

          LocalPhoneNumber - phone number without country/area parts

          Script           - script file's path.
                             On Win95 this is DialUp Scripting Tool script.

     Windows NT: To indicate a SWITCH.INF script name, set the first
     character of the name to "[".

     `RasSetEntryProperties()' function may have a problem saving the full
     script path (NT, fixed in the Service Pack 4).
     http://support.microsoft.com/support/kb/articles/Q160/1/90.asp

          DeviceType     - one of the following string constants
                           (case-insensitive):
            "modem"    A modem accessed through a COM port
            "isdn"     An ISDN card with corresponding NDISWAN driver installed
            "x25"      An X.25 card with corresponding NDISWAN driver installed
                       "x25" type is not implemented in RasSetEntryProperties()
                       in this version of the module
            "vpn"      A Microsoft VPN Adapter

     You can read a note about VPN and PPTP in the
     `RasSetEntryProperties()' section.

          DeviceName    - name of a TAPI device to use with this phonebook entry

          NetProtocols  - network protocols to negotiate.
                          $props->{NetProtocols} refers to the array that can
                          contain one or more of the strings
                          (case insensitive in RasSetEntryProperties()):
            "NetBEUI"  NetBIOS End User Interface standard
            "Ipx"      IPX/SPX Compartible
            "Ip"       TCP/IP

          FramingProtocol  - framing protocol used by the server.
                             One of the following strings:
                             "PPP", "Slip", "RAS"
                             (case insensitive in RasSetEntryProperties())

     *Limitations:*

     Subentries(multilink dialing) are currently not supported as well as
     X.25-related parameters. Current version of Win32::RASE also does not
     allow you to change 'DeviceType' and 'DeviceName' elements. This will
     be added in some future.  Right now any changes in these fields will
     not affect the `RasSetEntryProperties()' execution.

     Note: don't misuse this function, in list context it returns
     unreadable things for internal needs.

     Croaks if $entry does not exist.

     For an easy way to change just the phone-number take a look at the
     `RasChangePhoneNumber()' section.

RasPrintEntryProperties ( )
     This function provides nice printing of a phonebook entry properties.
     For debugging, for fun etc.

          RasPrintEntryProperties( $entry );

          $entry          - name of RAS/DUN entry

     Croaks if $entry does not exist.

RasGetEntryDevProperties ( )
     This function retrieves the properties of a device used by the
     phonebook entry if this entry uses MS Unimodem compartible TSP
     (Telephone Service Provider) or in other words - Unimodem compartible
     driver, on Win95 - always.

          $props = RasGetEntryDevProperties($entry);

          $entry          - name of RAS/DUN entry
          $props          - pointer to hash

     (Sorry, the description might not be clear enough, just print your
     properties with the `RasPrintEntryDevProperties()' and it'd be much
     easier.)

     The description of the `%$props' hash is common for this function and
     `RasSetEntryDevProperties()' (not implemented yet).

     It's much likely that only a small part of the described data is
     really usefull. Look at the Win32 SDK/MS Platform SDK (TAPI
     Prorammer's Reference - "comm/datamodem", "COMMCONFIG", "DCB",
     "MODEMSETTINGS" sections) for more info.

          KEY                         VALUE

          name         - copy of $entry
          DeviceName   - name of a TAPI device to use with this phonebook entry
          DeviceType   - described in the RasGetEntryProperties() section

          Options      - numeric flag value, combination of the Option flags
                         that appear on the Unimodem Option page.
                         This member can be a combination of these values:

          TERMINAL_PRE  (1) - Displays the pre-terminal screen.
          TERMINAL_POST (2) - Displays the post-terminal screen.
          MANUAL_DIAL   (4) - Dials the phone manually, if capable of doing so
          LAUNCH_LIGHTS (8) - Displays the modem tray icon.

          Only the LAUNCH_LIGHTS value is set by default

          OptionsReadable  - an array ref, a readable representation of those
                Options, that are switched on. The array consists of zero or more
                strings
                "TERMINAL_PRE", "TERMINAL_POST", "MANUAL_DIAL", "LAUNCH_LIGHTS"

          WaitBong         - Number of seconds (in two seconds granularity) to
                             replace the wait for credit tone (default - 10 s)

          CallSetupFailTimer - the maximum number of seconds the modem should
                wait, after dialing is completed, for an indication that a
                modem-to-modem connection has been established. If a connection
                is not established in this interval, the call is assumed to have
                failed. This member is equivalent to register S7 in Hayes
                compatible modems.

          InactivityTimeout  - the maximum number of seconds of inactivity
                allowed after a connection is established. If no data is either
                transmitted or received for this period of time, the call is
                automatically terminated.
                This time-out is used to avoid excessive long distance charges
                or online service charges if an application unexpectedly locks up
                or the user leaves.

          SpeakerVolume    - one of the following values: "LOW", "MEDIUM", "HIGH"
                Note that actual volumes are hardware-specific.

          SpeakerMode      - one of the following values:
               "OFF"       - The speaker is always off
               "CALLSETUP" - The speaker is on until a connection is established
               "ON"        - The speaker is always on
               "DIAL"      - The speaker is on until a connection is established,
                        except that it is off while the modem is actually dialing

          PreferredModemOptions - a numeric flag value. Specifies the modem
               options requested by the application. The local and remote modems
               negotiate modem options during call setup; this member specifies
               the initial negotiating position of the local modem. A combination
               of bit flags.

          PreferredModemOptionsReadable - refers to array of strings that
               represent bit flags of the previous. Contains zero or more of the
               following strings:
               "COMPRESSION", "ERROR_CONTROL", "FORCED_EC",
               "CELLULAR", "FLOWCONTROL_HARD", "FLOWCONTROL_SOFT",
               "CCITT_OVERRIDE", "SPEED_ADJUST",
               "TONE_DIAL", "BLIND_DIAL", "V23_OVERRIDE"

          Comments:
          CCITT_OVERRIDE - When set, CCITT modulations are enabled for V.21
                           and V.22 or V.23.When clear, bell modulations
                           are enabled for 103 and 212A.
          V23_OVERRIDE   - When set, CCITT modulations are enabled for V.23.
                           When clear, CCITT modulations are enabled for
                           V.21 and V.22.

     For V.23 to be set, both CCITT_OVERRIDE and V23_OVERRIDE must be set.

          NegotiatedModemOptions - a numeric flag value. Specifies the modem
               options that are actually in effect. This member is filled in
               after a connection is established and the local and remote
               modems negotiate modem options. This value is read only.
               (On my Win95 - always 0).

          NegotiatedModemOptionsReadable - the same ref to array of the readable
               strings as PreferredModemOptionsReadable,
               but for NegotiatedModemOptions.

          NegotiatedDCERate - Specifies the DCE rate that is in effect.
               This member is filled in after a connection is established and
               the local and remote modems negotiate modem modulations.
               Also read-only.

          DCE - Open Software Foundation (OSF) Distributed Computing Environment.

     The DCB structure defines the control setting for a serial
     communications device.  The following keys are members of the DCB
     structure.

          DCB_BaudRate     - Specifies the baud rate at which the communications
               device operates. This member can be one of the following values:
               110, 300, 600, 1200, 2400, 4800, 9600, 14400, 38400,
               56000, 57600, 115200, 128000, 256000

          DCB_Flags        - numeric flag value, concatenation of many DCB flags.
                             You don't need to use it directly, it's here for
                             information purpose only.

          DCB_FlagsReadable - an array ref. The array consists of the 13 string
               values. Each string is in the form "flagname:value".
               The values are in most cases 0/1. The flags names are:

          fBinary          - Specifies whether binary mode is enabled.
              The Win32 API does not support nonbinary mode transfers, so this
              member should be 1. Trying to use 0 will not work.
              Under Windows 3.1, if this member is 0, nonbinary mode is
              enabled, and the character specified by the DBC_EofChar member
              is recognized on input and remembered as the end of data. (0/1)

          fParity          - Specifies whether parity checking is enabled (0/1)

          fOutxCtsFlow     - Specifies whether the CTS (clear-to-send) signal
              is monitored for output flow control. If this member is 1 and CTS
              is turned off, output is suspended until CTS is sent again. (0/1)

          fOutxDsrFlow     - Specifies whether the DSR (data-set-ready) signal
              is monitored for output flow control. If this member is 1 and DSR
              is turned off, output is suspended until DSR is sent again. (0/1)

          fDtrControl      - Specifies the DTR (data-terminal-ready)
                             flow control.
            This member can be one of the following values:
            0 - Disables the DTR line when the device is opened and leaves it
                disabled
            1 - Enables the DTR line when the device is opened and leaves it on
            2 - Enables DTR handshaking

          fDsrSensitivity  - Specifies whether the communications driver is
              sensitive to the state of the DSR signal. If this member is 1,
              the driver ignores any bytes received, unless the DSR modem input
              line is high. (0/1)

          fTXContinueOnXoff - Specifies whether transmission stops when the
              input buffer is full and the driver has transmitted the
              DCB_XoffChar character.
              If this member is 1, transmission continues after the input
              buffer has come within DCB_XoffLim bytes of being full and the
              driver has transmitted the DCB_XoffChar character to stop
              receiving bytes.
              If this member is 0, transmission does not continue until the
              input buffer is within DCB_XonLim bytes of being empty and the
              driver has transmitted the DCB_XonChar character to resume
              reception. (0/1)

          fOutX            - Specifies whether XON/XOFF flow control is used
              during transmission. If this member is 1, transmission stops when
              the DCB_XoffChar character is received and starts again when the
              DCB_XonChar character is received. (0/1)

          fInX              - Specifies whether XON/XOFF flow control is used
              during reception. If this member is 1, the DCB_XoffChar character
              is sent when the input buffer comes within DCB_XoffLim bytes of
              being full, and the DCB_XonChar character is sent when the input
              buffer comes within DCB_XonLim bytes of being empty. (0/1)

          fErrorChar        - Specifies whether bytes received with parity
              errors are replaced with the character specified by the
              DCB_ErrorChar member.
              If this member is 1 and the fParity member is 1, replacement
              occurs. (0/1)

          fNull             - pecifies whether null bytes are discarded.
              If this member is 1, null bytes are discarded when received.(0/1)

          fRtsControl       - Specifies the RTS (request-to-send) flow control.
              This member can be one of the following values:
              0 - Disables the RTS line when the device is opened and leaves
                  it disabled.
              1 - Enables the RTS line when the device is opened and leaves
                  it on.
              2 - Enables RTS handshaking. The driver raises the RTS line when
                  the "type-ahead" (input) buffer is less than one-half full
                  and lowers the RTS line when the buffer is more than
                  three-quarters full.
              3 - Specifies that the RTS line will be high if bytes are
                  available for transmission. After all buffered bytes have
                  been sent, the RTS line will be low.

          fAbortOnError    - Specifies whether read and write operations are
              terminated if an error occurs. If this member is 1, the driver
              terminates all read and write operations with an error status if
              an error occurs. (0/1)

          DCB_XonLim      - Specifies the minimum number of bytes allowed in the
                input buffer before the XON character is sent.

          DCB_XoffLim     - Specifies the maximum number of bytes allowed in the
                input buffer before the XOFF character is sent. The maximum
                number of bytes allowed is calculated by subtracting this value
                from the size, in bytes, of the input buffer.

          DCB_ByteSize    - Specifies the number of bits in the bytes transmitted
                            and received.

          DCB_Parity      - Specifies the parity scheme to be used. This member
                            can be one of the following values:
                            "No parity", "Odd", "Even", "Mark", "Space"

          DCB_StopBits    - Specifies the number of stop bits to be used.
                            This member can be one of the following values:
                0 - 1 stop bit
                1 - 1.5 stop bits
                2 - 2 stop bits

          DCB_XonChar     - Specifies the value of the XON character for both
                            transmission and reception.

          DCB_XoffChar    - Specifies the value of the XOFF character for both
                            transmission and reception.

          DCB_ErrorChar   - Specifies the value of the character used to replace
                            bytes received with a parity error.

          DCB_EofChar     - Specifies the value of the character used to signal
                            the end of data.

          DCB_EvtChar     - Specifies the value of the character used to signal
                            an event.

     Manipulating these flags is described in `RasSetEntryDevProperties()'
     section.  (not implemented yet).

     The function croaks if $entry does not exist.

RasPrintEntryDevProperties ( )
     This function provides nice printing of a phonebook entry device
     properties if this entry uses MS Unimodem compartible TSP (Telephone
     Service Provider) or in other words - Unimodem compartible driver, on
     Win95 - always.

     Look at the `RasGetEntryDevProperties()' section and Win32 SDK for
     more info.

     Char values (XonChar, XoffChar, ErrorChar, EofChar, EvtChar) are
     printed in hexadecimal form like 0x13.

     For debugging, for fun etc.

          RasPrintEntryDevProperties( $entry );

          $entry          - name of RAS/DUN entry

     Croaks if $entry does not exist. Silently returns if the device is not
     Unimodem-compartible.

RasCopyEntry ( )
     This function makes a copy of the existing RAS entry.  Some
     properties of this newly created entry could then be changed with the
     use of `RasSetEntryProperties()'. In previous versions of the module
     it was the only way to create a new entry silently, programmatically.
     But as of 0.07 we have full featured `RasCreateEntry()'.

     You can also create new entry via dialog, see `RasCreateEntryDlg()'.

          RasCopyEntry( $oldname, $newname );

     Croaks if `$oldname' does not exist or `$newname' already exists.
     You should call `IsEntry()' or `RasEnumEntries()' before to verify
     both.

     `$newname' must contain at least one non-white-space alphanumeric
     character and cannot begin with a period (".").

     Username, password etc. (see `RasGetEntryDialParams()' and
     `RasSetEntryDialParams()') are not copied to the newly created entry.

RasSetEntryProperties ( )
     This function changes the connection information for an existing
     entry.

          RasSetEntryProperties( $props );

          $props          - reference to hash with replacing properties

     Mainly keys/values of the %$props hash are described in the
     `RasGetEntryProperties()' section. But here we can use just part of
     the full hash - if keys are undefined no changes will be made to the
     corresponding properties. Only $props->{name} has to contain a name
     of the existing phonebook entry, all other keys are optional.

     Those properties that do exist in %$props will replace current
     properties.  If $props->{some-key} is defined and empty ("") the
     corresponding property will be empty.

     `DeviceType', `CountryName', Flags and `FlagsReadable' keys are not
     used by this function. Anyway, all unneeded keys will be ignored
     without any errors.

     As of the version 0.07 you can change the RAS device using with the
     entry by specifying the new device name in $props->{DeviceName}.  The
     function finds the device type internally, so $props->{DeviceType} is
     ignored if specified.

     If "DeviceName" key is present in the `%$props' the function resets
     device properties for `$props-'{name}> entry to the default values
     (for the list of device properties see `RasGetEntryDevProperties()').
     `RasEnumDevices()' function gives the RAS-capable devices enumeration.

     *Microsoft has confirmed a possible problem*: With multiple modems
     installed under Windows NT 4.0, the RasSetEntryProperties API
     function calls will reset the selected modem to the first available
     modem.  This problem has been corrected in the latest U.S. Service
     Pack (4).

     Print the whole enumeraton like this:

          %devices = RasEnumDevices() or die "Error";
          print map "\"$_\" of type \"$devices{$_}\"\n", keys %devices;

     In addition to the keys decribed in the `RasGetEntryProperties()'
     section the string value $props->{newFlags} can be used for
     adding/removing the existing flags within the RAS-entry.

     This string has the format: "<token1> <token2>..." (any `\s'
     separators are possible)

     Each token can be one of the following values (same as mnemonic flags
     described in the `RasGetEntryProperties()' section):

          UseCountryAndAreaCodes
          SpecificIpAddr
          SpecificNameServers
          IpHeaderCompression
          RemoteDefaultGateway
          DisableLcpExtensions
          TerminalBeforeDial
          TerminalAfterDial
          ModemLights
          SwCompression
          RequireEncryptedPw
          RequireMsEncryptedPw
          RequireDataEncryption
          NetworkLogon
          UseLogonCredentials
          PromoteAlternates
          SecureLocalFiles

     These strings are just the meaningful parts of `RASEO_*' constants'
     names (from "ras.h" file). They are rather descriptive, you can
     easily find their meaning by changing and printing an existing RAS
     entry. Not all of them will work in this version of the module.

     Each of these flags could be used with or without the "RASEO_" prefix.
     With or without `+' or `-' prefix (no blanks between [+-] and
     "mnemonic flag") - this is the token mentioned above.

     Additional token that can't be prefixed with `+' or `-' is
     "KeepOldFlags", it still can be prefixed with "RASEO_".

     If this new flag-string ($props->{newFlags}) is defined the default
     action is to reset all old flags. "KeepOldFlags" prevents from this
     cleanup.

     The token with `-' will reset the corresponding flag if it was set,
     otherwise - no effect. The token with `+' will set the corresponding
     flag if it was not set, otherwise - no effect. The order of tokens is
     not important, tokens are separated by any number of blanks. Token
     without `+' or `-' means `+'.

     Examples:

     `"NetworkLogon +SwCompression"' - reset old flags and add these two.

     `"-NetworkLogon -SwCompression KeepOldFlags"' - keep old flags and
     clean these two.

     The function croaks if $entry does not exist and on some impossible
     values of the parameters.

     *PPTP note* (Point to Point Tunneling Protocol): You can use an
     ip-address in place of LocalPhoneNumber if your DUN/RAS entry is
     configured to work with VPN (Virtual Private Networking) via PPTP.
     PPTP appears as a new modem type that can be selected in DUN entry
     only manually.  It DeviceName is "Microsoft VPN Adapter" and
     DeviceType is "vpn".  In this case you can change the ip-address of
     the VPN-host as if it were local phone number. For example

          RasSetEntryProperties({
                name=>"NEV5",
                LocalPhoneNumber=>"21.100.14.12",
          });

     You can get info about VPN and PPTP at

     http://support.microsoft.com/support/kb/articles/q154/0/91.asp

     DUN 1.3 that supports VPN is downloadable from

     http://support.microsoft.com/download/support/mslfiles/MSDUN13.EXE

     and is described here

     http://support.microsoft.com/support/kb/articles/q194/4/77.asp

     Thanks to Carl Sewell <csewell@hiwaay.net> for his explanations and
     testing of VPN features.

     *Microsoft has confirmed the possible problem:* After applying
     Service Pack 2, the RasSetEntryProperties flags for
     RASEO_TerminalAfterDial and RASEO_TerminalBeforeDial specified in the
     Win32 function call are not set. This problem occurs because Service
     Pack 2 causes the parameters to be ignored.  This problem has been
     corrected in Service Pack 3.

     http://support.microsoft.com/support/ntserver/serviceware/nts40/E9MSL2CSA.ASP

     *Microsoft:* When using the RasSetEntryProperties API call to change
     the connection information for an entry in the phone book or create a
     new phone-book entry, the szScript (`$props-'{Script}> in
     `Win32::RASE') parameter of the RASENTRY structure is not always
     preserved.

     http://support.microsoft.com/support/kb/articles/q160/1/90.asp

     This problem applies to WinNT 4.0 and was corrected in the latest
     Microsoft Windows NT 4.0 U.S. Service Pack (4).

     The function croaks if the specfied device is not found.

RasCreateEntry ( )
     This function creates RAS/DUN entry programmatically (note that
     `RasCreateEntryDlg()' displays dialo boxes).

          RasCreateEntry( $props );

     `Win32::RASE::PHONEBOOK' defines the phonebook in which the new entry
     will be created (WinNT).

     For the explanation of the `%$props' hash see the previous
     `RasSetEntryProperties()' function. The main difference is that these
     keys

          name, LocalPhoneNumber, NetProtocols, FramingProtocol, DeviceName

     are mandatory in this hash.

     You have to specify at least one of CountryID and CountryCode keys
     and AreaCode key if `$props-'{newFlags}> contains
     "+UseCountryAndAreaCodes".

     All ip-addresses if omitted are assumed to be "0.0.0.0". Empty or
     non-existing `$props-'{newFlags}> gives zero numeric flag which means
     that none of the `RASEO_*' options are in use. Flag "KeepOldFlags"
     has no meaning but makes no error.

     Note that the device settings would be copied from your system
     defaults and some minor features still could not be customized (see
     `RasGetEntryDevProperties()').

RasChangePhoneNumber ( )
     This is a simplified version of the `RasSetEntryProperties()'.

          RasChangePhoneNumber($entry, $new_phone_number);

          $entry             - name of RAS/DUN entry
          $new_phone_number  - fully qualified phone number of the remote
                               computer in almost any human-readable form.

     For example:

          '7-095-5555555' or '7(095)5555555' or '7 -( 095)-555-5555'
          or '+7 (095) - 5-5-5-5-5-5-5' or '7 095 5555555'

     It is smart enough to adjust entry flags to avoid long distance
     dialing if country and area codes are the same as in Dialing
     Properties/Default Location.  All other flags are kept unchanged.

     *Note!* country code here is not TAPI `countryID'.

   * =====================================*

   * CONNECTION RELATED FUNCTIONS*

   * =====================================*

RasEnumConnections ( )
          %connections = RasEnumConnections ( );  or as list

          ($entry1, $hrasconn1, ...) = RasEnumConnections ( );

     Returns handles for each active RAS/DUN connection. $entry is
     entry-name.  `$hrasconn' is a numeric handle that might be used in
     `RasHangUp()' to hang up the active connection or in
     `RasGetConnectStatus()' or in `RasGetProjectionInfo()'.

     Croaks on errors. Returns FALSE if no one active connection was found.

     Note that `RasDial()' also returns $hrasconn on success.

RasGetProjectionInfo ( )
     In the current version projection info is implemented for IP protocol
     only.  This is a subject to change.

          ($ip, $server_ip) = RasGetProjectionInfo ( $hrasconn );

          $hrasconn  - handle of the active connection returned by either
                       RasDial() or RasEnumConnections().
          $ip        - the client's IP address on the RAS connection
          $server_ip - the IP address of the remote PPP peer (that is, the
                       server's IP address)

     Both IP addrs are in "nnn.nnn.nnn.nnn" form.

     *From the API docs:*

     Remote access projection is the process whereby a remote access server
     and a remote client negotiate network protocol-specific information.
     A remote access server uses this network protocol-specific information
     to represent a remote client on the network.

     *Windows NT:* Remote access projection information is not available
     until the operating system has executed the RasDial `RASCS_Projected'
     state on the remote access connection. If `RasGetProjectionInfo()' is
     called prior to the `RASCS_Projected' state, it returns
     `ERROR_PROJECTION_NOT_COMPLETE'.

     *Windows 95:* Windows 95 Dial-Up Networking does not support the
     `RASCS_Projected' state. The projection phase may be done during the
     `RASCS_Authenticate' state. If the authentication is successful, the
     connection operation proceeds to the `RASCS_Authenticated' state, and
     projection information is available for successfully configured
     protocols. If `RasGetProjectionInfo()' is called prior to the
     `RASCS_Authenticated' state, it returns
     `ERROR_PROTOCOL_NOT_CONFIGURED'.

     PPP does not require that servers provide this address, but Windows NT
     servers will consistently return the address anyway. Other PPP vendors
     may not provide the address. If the address is not available, this
     member returns an empty string ("").

     I guess the last note is probably outdated because my Advanced Dialer
     has a field for "Server's IP address" - so, it expects that it's
     always available.

     If you are using `Win32::RASE' in a single process application you
     can't monitor `RASCS_*' states (for more info look at
     `RasGetConnectStatus()').  So, the rule is: use this function after
     `RasDial()' successfully returned `$hrasconn'.

     The typical usage if you have only one connection is:

          unless ( $hrasconn = (RasEnumConnections())[1] ) {
          	 print "Dialing sequence not started\n";

          } elsif ( ($ip, $server_ip) = RasGetProjectionInfo( $hrasconn ) ) {
          	 print "LOCAL:$ip  SERVER:$server_ip\n";

          } elsif ( Win32::RASE::GetLastError == 731 ) {
          	 print "Protocol not configured yet\n";

          } else {
          	 die Win32::RASE::FormatMessage();
          }

     Note also that LastError=6  means that `$hrasconn' is an invalid
     handle.

     Command line syntax:

          perl -MWin32::RASE -e "$,=', ';print RasGetProjectionInfo((RasEnumConnections)[1])"

RasHangUp ( )
          RasHangUp($hrasconn [, $timeout]);

          $hrasconn  - handle of the active connection returned by either
                       RasDial() or RasEnumConnections().

          $timeout   - in sec, optional (3 sec by default). Maximum time to wait
                       for graceful disconnection. You can use float values if
          	      Time::HiRes is installed. Otherwise cycle uses sleep(1)
                       and thus wastes some additional time.

     This function gracefully terminates the connection. You don't need to
     add any sleep after it.

     The connection is terminated even if the `RasDial()' call has not yet
     been completed.

     After this call, the $hrasconn handle can no longer be used.

     Returns FALSE if invalid handle was given but this is harmless most
     of the time. Probably the connection failed itself and `$hrasconn' is
     not valid any more. So, you don't have to trap this error.

     Returns FALSE on timeout also (connection might be still active).
     LastError is 0 in this case. So the exact logic is:

          if ( RasHangUp($hrasconn, $timeout) ) {
          	 print "Connection is terminated successfully.\n";

          } elsif ( !Win32::RASE::GetLastError ) {
          	 print "Timeout. Connection is still active.\n";

          } else {
          	 # we don't have to die here
          	 warn Win32::RASE::FormatMessage(), "\n";
          }

     For more take a look at the API docs.

HangUp ( )
     This is the easier version of previous.

     Without parameters it will terminate all active connections, otherwise
     terminates connections by *entry-names* given as parameters. Note that
     this function uses entry-names, not handles.

          $code = HangUp ( [$entry1, ...] );

     Returns FALSE if at least one connection was not terminated
     gracefully, otherwise TRUE even if no one active connecton was found.

     Command line syntax:

          perl -MWin32::RASE -e HangUp

RasGetConnectStatus ( )
     This function is used to monitor active connection in progress. In
     most cases it's good to cycle calls to this function after a very
     small interval, say 0.1 sec or less - at least at the dialing time.
     It's possible in multithreading process (thread safety is not
     verified in this version) or one process can monitor another, which
     is closer to perl practice.

          $status = RasGetConnectStatus($hrasconn);

     or

          ($status, $status_text) = RasGetConnectStatus($hrasconn);

          $hrasconn - handle to active RAS/DUN connection

     In scalar context returns numeric status (RASCS_* enumerator values)
     or FALSE if `$hrasconn' is not a valid handle (LastError is set to 6).

     In list context returns numeric status and the string that
     characterizes this status in short (the descriptive part of the
     corresponding RASCS_ constant's name, like "OpenPort") or FALSE if
     handle is invalid.

     FALSE is also returned if handle is "not valid any more", i.e.
     connection is terminated.

     These string constants ("PortOpened" etc.) are stored in a
     non-exported hash *%Win32::RASE::RASCS* where the keys are numeric
     values of the corresponding RASCS_* constants. So

          $Win32::RASE::RASCS{1} eq "PortOpened"

     You can check status yourself against exported RASCS_* constants:

          RASCS_OpenPort
          RASCS_PortOpened
          RASCS_ConnectDevice
          RASCS_DeviceConnected
          RASCS_AllDevicesConnected
          RASCS_Authenticate
          RASCS_AuthNotify
          RASCS_AuthRetry
          RASCS_AuthCallback
          RASCS_AuthChangePassword
          RASCS_AuthProject
          RASCS_AuthLinkSpeed
          RASCS_AuthAck
          RASCS_ReAuthenticate
          RASCS_Authenticated
          RASCS_PrepareForCallback
          RASCS_WaitForModemReset
          RASCS_WaitForCallback
          RASCS_Projected
          RASCS_StartAuthentication    // Windows 95 only
          RASCS_CallbackComplete       // Windows 95 only
          RASCS_LogonNetwork           // Windows 95 only
          RASCS_SubEntryConnected
          RASCS_SubEntryDisconnected
          RASCS_Interactive  =  RASCS_PAUSED
          RASCS_RetryAuthentication
          RASCS_CallbackSetByCaller
          RASCS_PasswordExpired
          RASCS_Connected  = RASCS_DONE
          RASCS_Disconnected

     *From the API docs:*

     The connection process states are divided into three classes: running
     states, paused states, and terminal states. An application can easily
     determine the class of a specific state by performing Boolean bit
     operations with the RASCS_PAUSED and RASCS_DONE bitmasks. Here are
     some examples:

          $fDoneState = $status & RASCS_DONE;
          $fPausedState = $status & RASCS_PAUSED;
          $fRunState = !($fDoneState || $fPausedState);

RasDialDlg ( )
     This function tries to establish a RAS connection using a specified
     phonebook entry and the credentials of the logged-on user.  It
     displays a stream of dialog boxes that indicate the state of the
     connection operation and returns when the connection is established,
     or when the user cancels the operation. *Windows NT only.*

          RasDialDlg( $EntryName [, $hwnd, $PhoneNumber] );

          $EntryName    - RAS/DUN entry, the only mandatory parameter
          $hwnd         - Identifies the window that owns the modal RasDialDlg
                          dialog boxes.
                          This member can be any valid window handle, or it can
                          be 0, undef (or omitted) if the dialog box has no owner

     The dialog box is centered on the owner window unless `$hwnd' is FALSE
     or invalid handle, in which case the dialog box is centered on the
     screen.

          $PhoneNumber  - an overriding phone number (if not needed - use "" or
                          undef).

     It does not inherit anything from phonebook if specified - no prefix,
     no callin card, no waiting.  You should even add DP before the number
     for pulse dialing.

     Returns TRUE on success, FALSE if user selects "Cancel" button or an
     error occurs.  You can check the last case with
     `Win32::RASE::GetLastError()'.

          if ( RasDialDlg("NEV4") ) {
          	 print "Connection established\n";
          } elsif ( !Win32::RASE::GetLastError ) {
          	 print "User selected <Cancel>\n";
          } else {
          	 warn Win32::RASE::FormatMessage(), "\n";
          }

RasDial ( )
     This function establishes a RAS/DUN connection. The connection data
     includes callback and user authentication information.

          $hrasconn = RasDial($EntryName, $PhoneNumber, $UserName, $Password,
                               $Domain, $CallbackNumber);

          $EntryName   - RAS/DUN entry, the only mandatory parameter
          $PhoneNumber - an overriding phone number (if not needed - use "" or
                         undef).

          It does not inherit anything from the phonebook if specified -
          no prefix, no calling card, no waiting.
          You should add DP before the number for pulse dialing.

          $UserName    - user's user name (look below)
          $Password    - user's password
          $Domain      - domain on which authentication is to occur. An empty
               string ("" or undef) specifies the domain in which the remote
               access server is a member (NT only). An asterisk specifies the
               domain stored in the phonebook for the entry.
               It's in addr form (size is limited to 15 chars).
          $CallbackNumber - a callback phone number. An empty string ("") or
               undef indicates that callback should not be used. This string is
               ignored unless the user has "Set By Caller" callback permission
               on the RAS server (NT only). An asterisk indicates that the number
               stored in the phonebook should be used for callback.

     *Windows NT:* [These 2 paragraphs are copied from the API docs. I
     wanted to add this for some completeness but I was told that probably
     this is not truth and if Username or Password are empty user will get
     a dialog box with Username/Password prompts.]

     RAS does not actually log the user onto the network. The user does
     this in the usual manner, for example, by logging on with cached
     credentials prior to making the connection or by using CTRL+ALT+DEL,
     after the RAS connection is established.

     If both the UserName and Password members are empty strings (""), RAS
     uses the user name and password of the current logon context for
     authentication. For a user mode application, RAS uses the credentials
     of the currently logged-on interactive user.  For a Win32 service
     process, RAS uses the credentials associated with the service.

     *Windows 95:*

     RAS uses the UserName and Password strings to log the user onto the
     network.  Windows 95 cannot get the password of the currently
     logged-on user, so if both the UserName and the Password members are
     empty strings ("" or undef), RAS leaves the user name and password
     empty during authentication. I.e. it provides no additional search
     (look at `RasGetEntryDialParams()' for that).

     Note: It seems that overriding phone number is being dialed "as is" -
     without using any long-distance/international phone settings. So you
     have to provide this number with all prefixes and waitings (W etc.)
     if needed. Additional dashes, blanks and brackets are OK.

          $hrasconn  - on success - handle to active RAS/DUN connection,
                       otherwise undef

     You can use `$hrasconn' in `RasGetConnectStatus()' or `RasHangUp()'.
     Note that this function calls `RasHangUp()' internally on error, so
     after that, the handle of the failed connection is not available and
     the port is ready for the next try.

     Example:

          ($err, $errtext) = RasDial("CLICK",undef,"ppblazer","qwerty");
          if ($err) {
             print "$err, $errtext\n"; exit;
          } else {
             ... your work here ...
          }

     *Last note:* this is the *synchronous* operation. Nobody knows if it
     could really hang fast enough if the line is busy (for ex.) The best
     way would be to run `RasDial()' in the separate process or thread. In
     most cases you don't really need `$hrasconn' in the main process -
     you can terminate the connection at any time with `HangUp()'.  Or you
     can easily get `$hrasconn' with the use of `RasEnumConnections()'.

     If you run `RasDial()' in a child-process and terminate dialing in
     progress (for ex.  on timeout) you have to free the port yourself
     (`RasHangUp()' or `HangUp()').

     For more info take a look at Win32 API docs (RASDIALPARAMS etc).

     Command line syntax:

          perl -MWin32::RASE -e RasDial(NEV1,undef,ppblazer,'6hTR7dwA')
          perl -MWin32::RASE -e "RasDial(NEV1,undef,ppblazer,'6hTR7dwA') or print Win32::RASE::FormatMessage"
          perl -MWin32::RASE -e "print RasDial(NEV1,undef,ppblazer,'6hTR7dwA')||Win32::RASE::FormatMessage"

   * =====================================*

   * TAPI RELATED FUNCTIONS*

   * =====================================*

RasEnumDevices ( )
          %devices = RasEnumDevices();

     This function returns the name and type of all available RAS-capable
     devices.  In the `%devices' hash device names are keys and types are
     values. Common device types are "modem", "x25", "vpn", "isdn",
     "rastapi" etc.

     Croaks on errors. Returns FALSE if no one RAS capable device was
     found.

     For example the first RAS-capable device name is

          $DeviceName = (RasEnumDevices())[0];

     This function fills out a non-exported hash
     `%Win32::RASE::RasDevEnumeration' of the same structure as
     `%devices', so in most cases there is no need to call this function
     more then once.

     Command line syntax:

          perl -MWin32::RASE -e "print ((RasEnumDevices)[0])"

RasEnumDevicesByType ( )
     The easier version of previous.

          @DevNames = RasEnumDevicesByType( $devtype );

     Returns names of RAS-capable devices of type `$devtype'. For example
     the first modem's name

          $ModemName = (RasEnumDevicesByType("modem"))[0];

     `$devtype' is case insensitive.

TAPIlineGetTranslateCaps ( )
     This function is not exported and is not intended for public use.  It
     is called each time you load Win32::RASE and fills out 3 global
     variables and global hash (below).

     It takes local information from your dialup settings.

          ($countryID, $countryCode, $areaCode) =
             Win32::RASE::TAPIlineGetTranslateCaps ();

     The return values are describing the *Current Location* that is
     selected in you dialing properties.

          $countryID  -  the unique number that TAPI assigns to each country.
                         It is not what you are typing on your phone, though it
                         sometimes has the same value. Different countries always
                         have different countryID. This allows multiple entries
                         to exist in the country list with the same country code
                         (for example, all countries in North America and the
                         Caribbean share country code 1, but require separate
                         entries in the list).

          $countryCode - this really is the code that would be dialed in an
          	        international call to your computer's location.

          $areaCode    - city or area code (local).

     These 3 values are copied to non-exported global variables
     *$Win32::RASE::LOCAL_ID*, *$Win32::RASE::LOCAL_CODE* and
     *$Win32::RASE::LOCAL_AREA*.

     They are mainly for internal use, just note that they are here.

     The complete TAPI countries list is being copied to non-exported
     global hash *%Win32::RASE::TAPIEnumeration*. Keys are countryID's,
     each value points to 3-element array: [0] is country-name, [1] is
     countryCode described above, [2] is NextCountryID in TAPI-enumeration
     (TAPI docs, but in most cases you don't need to use this hash
     explicitly).

     Use `TAPIEnumerationPrint()' to print this hash (for fun ;)

TAPIEnumLocations ( )
     Just a handy function (non-exported) to enumerate locations in your
     Dialing Properties.  It's being executed internally when Win32::RASE
     needs it, so in most cases you don't need to use it explicitly.

          ($CurrentLocation, %locations) = Win32::RASE::TAPIEnumLocations;

          $CurrentLocation   - current dialing location's name
          %locations         - keys are location-names, values are anonymous
                               arrays that are filled out like:
             [$CountryID, $CountryCode, $CityCode, $Options, $LocalAccessCode,
              $LongDistanceAccessCode, $TollPrefixList, $PermanentLocationID]

          $Options                - 0/1 tone/pulse dialing, this value could be
                                    used to define good timeout for RasDial()
          $LocalAccessCode        - the access code to be dialed before calls to
                                    addresses in the local calling area
          $LongDistanceAccessCode - the access code to be dialed before calls to
                                    addresses outside the local calling area
          $TollPrefixList         - the toll prefix list for the location. The
                                    string will contain only prefixes consisting
                                    of the digits "0" through "9", separated
                                    from each other by a single comma
          $PermanentLocationID    - internal unique identifier of the location

     Other values in array are described in `TAPIlineGetTranslateCaps()'.

     Example:

          ($CurrentLocation, %locations) = Win32::RASE::TAPIEnumLocations;
          print "$CurrentLocation\n";
          print map "$_ => [".(join", ",@{$locations{$_}})."]\n",
              keys %locations;

TAPISetCurrentLocation ( )
          TAPISetCurrentLocation( $location );

          $location   - optional, the name of the location that is configured
                        in the Dialing Properies.
                        If omitted the "Default Location" is used.

     Returns TRUE on success, FALSE if `$location' was not found in the
     Dialing Properties, croaks on TAPI errors.

TAPIEnumerationPrint ( )
     This function prints nicely formatted TAPI countries table that is
     stored in the *%Win32::RASE::TAPIEnumeration* (see above). Not
     exported by default;

          Win32::RASE::TAPIEnumerationPrint();

     Columns: CountryID, CountryName, CountryCode, NextCountryID

     For more: `TAPIlineGetTranslateCaps()' and TAPI docs.

     Always returns TRUE.

TAPICountryName ( )
     Returns CountryName by CountryID or FALSE if given CountryID does not
     exist in TAPI-table.

          $CountryName = TAPICountryName($CountryID);

     Command line syntax:

          perl -MWin32::RASE -e "print TAPICountryName(1)"

TAPICountryCode ( )
     Returns CountryCode by CountryID or FALSE if given CountryID does not
     exist in TAPI-table.

          $CountryCode = TAPICountryCode($CountryID);

IsCountryID ( )
     Returns TRUE if given $CountryID exist in TAPI-table, otherwise FALSE.

          IsCountryID($CountryID);

     Just to have such a pretty name ;)

TAPIlineInitialize ( )
     This is a non-exported function mainly for internal use. It could be
     handy only if you'd start writing your own TAPI-related functions.

          ($hLineApp, $dwNumDevs) = Win32::RASE::TAPIlineInitialize();

     or in scalar context

          $hLineApp = Win32::RASE::TAPIlineInitialize();

          $hLineApp  - the application's usage non-zero handle for TAPI
          $dwNumDevs - number of line devices available to the TAPI application

     Croaks on TAPI errors.

     The applicaton should always call `TAPIlineShutdown()' to release
     memory resources allocated by TAPI.DLL.

TAPIlineShutdown ( )
     This is a non-exported function mainly for internal use. It could be
     handy only if you'd start writing your own TAPI-related functions.

          Win32::RASE::TAPIlineShutdown($hLineApp);

          $hLineApp  - the application's usage handle for TAPI

     Returns zero if the request is successful or a negative error number
     if an error has occurred.

INSTALLATION
============

   As this is just a plain module no special installation is needed. Put it
into the Win32 subdirectory somewhere in your @INC.

   This module needs Windows Remote Access Service (RAS) or DialUp
Networking (DUN) to be properly installed including dialing properties.

   rasapi32.dll, tapi32.dll

   Win32::API module by Aldo Calpini.

   enum.pm (1.014 or later, no compilations) by Byron Brummer (aka Zenin)

   Time::HiRes (0.18 or later) by Douglas E. Wegscheid makes work more
precise.

CAVEATS
=======

   This module has been created and tested in a Win95 environment.
Although I expect it to function correctly on any version of Windows NT,
that fact has been confirmed for NT 4.0 build 1381 only.

   Some of the RAS APIs were not included in the RasAPI32.dll that was
shipped with the old releases of Windows 95. To use the RAS APIs mentioned
here, you need to install the at least Dial Up Networking (DUN) 1.2b
upgrade.  This upgrade is available for download on:

http://www.microsoft.com/windows/downloads/contents/Updates/W95DialUpNetw/default.asp

   This upgrade was incorporated in Win95 OSR.

   From the *MS KB# Q157765*: Early releases of Windows 95 may require an
additional RNAPH.DLL that contains some of new phonebook manipulation
APIs. There currently is no workaround for this situation in this version
of the module.

   Some APIs may also not work properly on WinNT with old Service Packs.
Make sure that you are using the last Service Pack available.  List of
Bugs Fixed in Windows NT 4.0 Service Pack 1, 2, and 3 is available at

   http://support.microsoft.com/support/kb/articles/q224/7/92.asp

   What can we do here, guys? That's how it goes...

CHANGES
=======

     1.00  First public release
     1.01  The only thing touched is Makefile.PL. The distribution is packed
           now using UNIX conventions (LF only, unlike the 1.00 dist)

TODO
====

   NT-only API: RasGetCredentials, RasSetCredentials, RasMonitorDlg,
RasPhonebookDlg.

   Any suggestions are much appreciated.

BUGS
====

   Please report.

VERSION
=======

   This man page documents "Win32::RASE" version 1.01.

   January 19, 2000.

CREDITS
=======

   Thanks to Carl Sewell <csewell@hiwaay.net> for his great help and
patience in testing on NT. If these docs are more or less readable - it's
due to his corrections and improvement.

   Thanks to Jan Dubois <jan.dubois@ibm.net> for numerous great tips and
explanations.

   Guys, you are cool! ;)

AUTHOR
======

   Mike Blazer, blazer@mail.nevalink.ru

   http://www.dux.ru/guest/fno/perl/

SEE ALSO
========

   Win32 SDK, TAPI docs.

COPYRIGHT
=========

   Copyright (C) 1999 Mike Blazer.

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Use Win32 semaphore objects from Perl
*************************************

NAME
====

   Win32::Semaphore - Use Win32 semaphore objects from Perl

SYNOPSIS 	require Win32::Semaphore;
===================================

     $sem = Win32::Semaphore->new($initial,$maximum,$name);
     $sem->wait;

DESCRIPTION
===========

   This module allows access to Win32 semaphore objects.  The wait method
and `wait_all' & `wait_any' functions are inherited from the
`"Win32::IPC"' in this node module.

Methods
-------

$semaphore = Win32::Semaphore->new($initial, $maximum, [$name])
     Constructor for a new semaphore object.  `$initial' is the initial
     count, and `$maximum' is the maximum count for the semaphore.  If
     $name is omitted, creates an unnamed semaphore object.

     If $name signifies an existing semaphore object, then `$initial' and
     `$maximum' are ignored and the object is opened.

$semaphore = Win32::Semaphore->open($name)
     Constructor for opening an existing semaphore object.

$semaphore->release([$increment, [$previous]])
     Increment the count of $semaphore by `$increment' (default 1).  If
     `$increment' plus the semaphore's current count is more than its
     maximum count, the count is not changed.  Returns true if the
     increment is successful.

     The semaphore's count (before incrementing) is stored in the second
     argument (if any).

     It is not necessary to wait on a semaphore before calling release,
     but you'd better know what you're doing.

$semaphore->wait([$timeout])
     Wait for $semaphore's count to be nonzero, then decrement it by 1.
     See `"Win32::IPC"' in this node.

Deprecated Functions and Methods
--------------------------------

   *Win32::Semaphore* still supports the ActiveWare syntax, but its use is
deprecated.

Win32::Semaphore::Create($SemObject,$Initial,$Max,$Name)
     Use `$SemObject = Win32::Semaphore->new($Initial,$Max,$Name)' instead.

Win32::Semaphore::Open($SemObject, $Name)
     Use `$SemObject = Win32::Semaphore->open($Name)' instead.

$SemObj->Release($Count,$LastVal)
     Use `$SemObj->release($Count,$LastVal)' instead.

AUTHOR
======

   Christopher J. Madsen <`chris_madsen@geocities.com'>

   Loosely based on the original module by ActiveWare Internet Corp.,
`http://www.ActiveWare.com'

manage system services in perl
******************************

NAME
====

   Win32::Service - manage system services in perl

SYNOPSIS
========

     use Win32::Service;

DESCRIPTION
===========

   This module offers control over the administration of system services.

FUNCTIONS
=========

NOTE:
-----

   All of the functions return FALSE (0) if they fail, unless otherwise
noted.  If hostName is an empty string, the local machine is assumed.

StartService(hostName, serviceName)
     Start the service serviceName on machine hostName.

StopService(hostName, serviceName)
     Stop the service serviceName on the machine hostName.

GetStatus(hostName, serviceName, status)
     Get the status of a service.  The third argument must be a hash
     reference that will be populated with entries corresponding to the
     SERVICE_STATUS structure of the Win32 API.  See the Win32 Platform
     SDK documentation for details of this structure.

PauseService(hostName, serviceName)
ResumeService(hostName, serviceName)
GetServices(hostName, hashref)
     Enumerates both active and inactive Win32 services at the specified
     host.  The hashref is populated with the descriptive service names as
     keys and the short names as the values.

An extension to play with Windows sounds
****************************************

NAME
====

   Win32::Sound - An extension to play with Windows sounds

SYNOPSIS
========

     use Win32::Sound;
     Win32::Sound::Volume('100%');
     Win32::Sound::Play("file.wav");
     Win32::Sound::Stop();

     # ...and read on for more fun ;-)

FUNCTIONS
=========

*Win32::Sound::Play(SOUND, [FLAGS])*
     Plays the specified sound: SOUND can the be name of a WAV file or one
     of the following predefined sound names:

          SystemDefault
          SystemAsterisk
          SystemExclamation
          SystemExit
          SystemHand
          SystemQuestion
          SystemStart

     Additionally, if the named sound could not be found, the function
     plays the system default sound (unless you specify the
     `SND_NODEFAULT' flag). If no parameters are given, this function
     stops the sound actually playing (see also Win32::Sound::Stop).

     FLAGS can be a combination of the following constants:

    `SND_ASYNC'
          The sound is played asynchronously and the function returns
          immediately after beginning the sound (if this flag is not
          specified, the sound is played synchronously and the function
          returns when the sound ends).

    `SND_LOOP'
          The sound plays repeatedly until it is stopped.  You must also
          specify `SND_ASYNC' flag.

    `SND_NODEFAULT'
          No default sound is used. If the specified sound cannot be
          found, the function returns without playing anything.

    `SND_NOSTOP'
          If a sound is already playing, the function fails.  By default,
          any new call to the function will stop previously playing sounds.

Win32::Sound::Stop()
     Stops the sound currently playing.

Win32::Sound::Volume()
     Returns the wave device volume; if called in an array context,
     returns left and right values. Otherwise, returns a single 32 bit
     value (left in the low word, right in the high word).  In case of
     error, returns undef and sets $!.

     Examples:

          ($L, $R) = Win32::Sound::Volume();
          if( not defined Win32::Sound::Volume() ) {
              die "Can't get volume: $!";
          }

*Win32::Sound::Volume(LEFT, [RIGHT])*
     Sets the wave device volume; if two arguments are given, sets left
     and right channels independently, otherwise sets them both to LEFT
     (eg. RIGHT=LEFT). Values range from 0 to 65535 (0xFFFF), but they can
     also be given as percentage (use a string containing a number
     followed by a percent sign).

     Returns undef and sets $! in case of error, a true value if
     successful.

     Examples:

          Win32::Sound::Volume('50%');
          Win32::Sound::Volume(0xFFFF, 0x7FFF);
          Win32::Sound::Volume('100%', '50%');
          Win32::Sound::Volume(0);

Win32::Sound::Format(filename)
     Returns information about the specified WAV file format; the array
     contains:

        * sample rate (in Hz)

        * bits per sample (8 or 16)

        * channels (1 for mono, 2 for stereo)

     Example:

          ($hz, $bits, $channels)
              = Win32::Sound::Format("file.wav");

Win32::Sound::Devices()
     Returns all the available sound devices; their names contain the type
     of the device (WAVEOUT, WAVEIN, MIDIOUT, MIDIIN, AUX or MIXER) and a
     zero-based ID number: valid devices names are for example:

          WAVEOUT0
          WAVEOUT1
          WAVEIN0
          MIDIOUT0
          MIDIIN0
          AUX0
          AUX1
          AUX2

     There are also two special device names, `WAVE_MAPPER' and
     `MIDI_MAPPER' (the default devices for wave output and midi output).

     Example:

          @devices = Win32::Sound::Devices();

Win32::Sound::DeviceInfo(DEVICE)
     Returns an associative array of information about the sound device
     named DEVICE (the same format of Win32::Sound::Devices).

     The content of the array depends on the device type queried. Each
     device type returns *at least* the following information:

          manufacturer_id
          product_id
          name
          driver_version

     For additional data refer to the following table:

          WAVEIN..... formats
                      channels

          WAVEOUT.... formats
                      channels
                      support

          MIDIOUT.... technology
                      voices
                      notes
                      channels
                      support

          AUX........ technology
                      support

          MIXER...... destinations
                      support

     The meaning of the fields, where not obvious, can be evinced from the
     Microsoft SDK documentation (too long to report here, maybe one
     day... :-).

     Example:

          %info = Win32::Sound::DeviceInfo('WAVE_MAPPER');
          print "$info{name} version $info{driver_version}\n";

THE WaveOut PACKAGE
===================

   Win32::Sound also provides a different, more powerful approach to wave
audio data with its `WaveOut' package. It has methods to load and then
play WAV files, with the additional feature of specifying the start and
end range, so you can play only a portion of an audio file.

   Furthermore, it is possible to load arbitrary binary data to the
soundcard to let it play and save them back into WAV files; in a few words,
you can do some sound synthesis work.

FUNCTIONS
---------

new Win32::Sound::WaveOut(FILENAME)
new Win32::Sound::WaveOut(SAMPLERATE, BITS, CHANNELS)
new Win32::Sound::WaveOut()
     This function creates a `WaveOut' object; the first form opens the
     specified wave file (see also `Open()' ), so you can directly
     `Play()' it.

     The second (and third) form opens the wave output device with the
     format given (or if none given, defaults to 44.1kHz, 16 bits,
     stereo); to produce something audible you can either `Open()' a wave
     file or `Load()' binary data to the soundcard and then Write() it.

Close()
     Closes the wave file currently opened.

CloseDevice()
     Closes the wave output device; you can change format and reopen it
     with OpenDevice().

GetErrorText(ERROR)
     Returns the error text associated with the specified ERROR number;
     note it only works for wave-output-specific errors.

Load(DATA)
     Loads the DATA buffer in the soundcard.  The format of the data
     buffer depends on the format used; for example, with 8 bit mono each
     sample is one character, while with 16 bit stereo each sample is four
     characters long (two 16 bit values for left and right channels). The
     sample rate defines how much samples are in one second of sound. For
     example, to fit one second at 44.1kHz 16 bit stereo your buffer must
     contain 176400 bytes (44100 * 4).

Open(FILE)
     Opens the specified wave FILE.

OpenDevice()
     Opens the wave output device with the current sound format (not
     needed unless you used CloseDevice()).

Pause()
     Pauses the sound currently playing; use Restart() to continue playing.

Play( [FROM, TO] )
     Plays the opened wave file. You can optionally specify a FROM - TO
     range, where FROM and TO are expressed in samples (or use FROM=0 for
     the first sample and TO=-1 for the last sample).  Playback happens
     always asynchronously, eg. in the background.

Position()
     Returns the sample number currently playing; note that the play
     position is not zeroed when the sound ends, so you have to call a
     Reset() between plays to receive the correct position in the current
     sound.

Reset()
     Stops playing and resets the play position (see Position()).

Restart()
     Continues playing the sound paused by Pause().

Save(FILE, [DATA])
     Writes the DATA buffer (if not given, uses the buffer currently
     loaded in the soundcard) to the specified wave FILE.

Status()
     Returns 0 if the soundcard is currently playing, 1 if it's free, or
     undef on errors.

Unload()
     Frees the soundcard from the loaded data.

Volume( [LEFT, RIGHT] )
     Gets or sets the volume for the wave output device.  It works the
     same way as Win32::Sound::Volume.

Write()
     Plays the data currently loaded in the soundcard; playback happens
     always asynchronously, eg. in the background.

THE SOUND FORMAT
----------------

   The sound format is stored in three properties of the `WaveOut' object:
`samplerate', bits and channels.  If you need to change them without
creating a new object, you should close before and reopen afterwards the
device.

     $WAV->CloseDevice();
     $WAV->{samplerate} = 44100; # 44.1kHz
     $WAV->{bits}       = 8;     # 8 bit
     $WAV->{channels}   = 1;     # mono
     $WAV->OpenDevice();

   You can also use the properties to query the sound format currently
used.

EXAMPLE
-------

   This small example produces a 1 second sinusoidal wave at 440Hz and
saves it in `sinus.wav':

     use Win32::Sound;

     # Create the object
     $WAV = new Win32::Sound::WaveOut(44100, 8, 2);

     $data = "";
     $counter = 0;
     $increment = 440/44100;

     # Generate 44100 samples ( = 1 second)
     for $i (1..44100) {

     # Calculate the pitch
     # (range 0..255 for 8 bits)
     $v = sin($counter/2*3.14) * 128 + 128;

     # "pack" it twice for left and right
     $data .= pack("cc", $v, $v);

     $counter += $increment;
         }

         $WAV->Load($data);       # get it
         $WAV->Write();           # hear it
         1 until $WAV->Status();  # wait for completion
         $WAV->Save("sinus.wav"); # write to disk
         $WAV->Unload();          # drop it

VERSION
=======

   Win32::Sound version 0.45, 09 Apr 1999.

AUTHOR
======

   Aldo Calpini, `dada@divinf.it'

   Parts of the code provided and/or suggested by Dave Roth.

Memory and Processor information on Win32 systems
*************************************************

NAME
====

   Win32::SystemInfo - Memory and Processor information on Win32 systems

SYNOPSIS
========

     use Win32::SystemInfo;

   # Get Memory Information

   my %mHash; 	if (Win32::SystemInfo::MemoryStatus(%mHash)) 	{
...process results...  	}

   	To get specific values:     my %mHash = (TotalPhys => 0, AvailPhys =>
0); 	if (Win32::SystemInfo::MemoryStatus(%mHash)) 	{ 	 ...mHash contains only
TotalPhys and AvailPhys values...  	}

   Change the default return value:
Win32::SystemInfo::MemoryStatus(%mHash,"MB");

   # Get Processor Information

     my $proc = Win32::SystemInfo::ProcessorInfo();
     	if ($proc >= 586) { ... }

     	my %phash;
     	Win32::SystemInfo::ProcessorInfo(%phash);
     	for (my $i = 0; $i < $phash{NumProcessors}; $i++) {
     	 print "Speed of processor $i: " . $phash{"Processor$i"}{MHZ} . "MHz\n";
     	}

ABSTRACT
========

   With this module you can get total/free memory on Win32 systems,
including installed RAM (physical memory) and page file. This module will
also let you access processor information, including processor family
(386,486,etc), speed, vendor, and revision information.

DESCRIPTION
===========

   Module provides two functions:

MemoryStatus
     *Win32::SystemInfo::MemoryStatus*(%mHash,[$format]);

          %mHash                      - The hash that will receive the results.
                                        Certain values can be set prior to the
                                        call to retrieve a subset. (See below)
          $format                     - Optional parameter. Used to set the order
                                        of magnitude of the results. (See below)

          Determines the current memory status of a Win32 machine. Populates
          %mHash with the results. Function returns undef on failure.

          Values returned through the hash:
          MemLoad                     - Windows NT 3.1 to 4.0: The percentage of
                                        approximately the last 1000 pages of physical
                                        memory that is in use.
                                      - Windows 2000: The approximate percentage of
                                        total physical memory that is in use.
          TotalPhys                   - Total amount of physical memory (RAM).
          AvailPhys                   - Available physical memory (RAM).
          TotalPage                   - Allocated size of page (swap) file.
          AvailPage                   - Available page file memory.
          TotalVirtual                - Total physical + maximum page file.
          AvailVirtual                - Total amount of available memory.

          Values returned through the hash can also be specified by setting
          them before the function is called.
              my %mHash = (TotalPhys => 0);
              Win32::MemoryInfo::MemoryStatus(%mHash);

          Will return only the total physical memory.

          MemoryStatus return values in bytes by default. This can be changed with
          the $format parameter. Valid values for $format are:
              B        -  Bytes (default)
              KB       -  Kilobytes
              MB       -  Megabytes
              GB       -  Gigabytes

ProcessorInfo
     $proc = *Win32::SystemInfo::ProcessorInfo*([%pHash]);

          Determines the processor information of a Win32 computer. Returns a "quick"
          value or undef on failure. Can also populate %pHash with detailed information
          on all processors present in the system.

          $proc                        - Contains a numerical representation of the
                                       - processor level for Intel machines. For
                                       - example, a Pentium will return 586.
                                       - For non-Intel Windows NT systems, the
                                       - possible return values are:
                                       - PPC: PowerPC
                                       - MIPS: MIPS architecture
                                       - ALPHA: Alpha architecture
                                       - UNKNOWN: Unknown architecture

          %pHash                       - Optional parameter. Will be filled with
                                       - information about all processors.

          Values returned through hash:
          NumProcessors                - The number of processors installed
          ProcessorN                   - A hash containing all info for processor N

          Each ProcessorN hash contains the values:
          Identifier                   - The identifier string for the processor
                                       - as found in the registry. The computer I'm
                                       - currently using returns the string
                                       - "x86 Family 6 Model 7 Stepping 3"
          VendorIdentifier             - The vendor name of the processor
          MHZ                          - The speed in MHz of the processor
                                       - Returns -1 if unable to determine.

          PLEASE read the note about the MHz value in Caveats, below.

   No functions are exported.

INSTALLATION
============

   Installation is simple. Follow these steps:

   perl makefile.pl nmake nmake test nmake install

   Copy the SystemInfo.html file into whatever directory you keep your
documentation in. I haven't figured out yet how to automatically copy it
over, sorry.

   I've noticed that ActiveState can give an error about not being able to
find perl when processing the makefile.pl file on Win9x.  To get around
this, open makefile.pl and add another key/value pair into WriteMakefile()
that looks like this: 'PERL'	=> 'full/path/to/your/perl.exe', That
should do the trick!

   This module can also be used by simply placing it and the included DLL
in your /Win32 directory somewhere in @INC.

   This module requires Win32::API module by Aldo Calpini
Win32::TieRegistry by Tye McQueen

CAVEATS
=======

   The information returned by the MemoryStatus function is volatile.
There is no guarantee that two sequential calls to this function will
return the same information.

   On computers with more than 4 GB of memory, the MemoryStatus function
can return incorrect information. Windows 2000 reports a value of -1 to
indicate an overflow. Earlier versions of Windows NT report a value that
is the real amount of memory, modulo 4 GB.

   On Intel x86 computers with more than 2 GB and less than 4 GB of memory,
the MemoryStatus function will always return 2 GB for TotalPhys.
Similarly, if the total available memory is between 2 and 4 GB, AvailPhys
will be rounded down to 2 GB.

   ProcessorInfo will only reliably return CPU speed for Intel chips, and
AMD chips that support the time stamp counter. (This appears to be K6-2,
K6-III, all Athlons, and Duron.) The return value for MHz should always be
checked in a Win9x environment to verify that it is valid. (Invalid
processors, or other errors will return a -1.)

   The ProcessorInfo function has been only tested in these environments:
Windows 98, Single Pentium II processor Windows NT 4.0, Single Pentium III
processor

   All feedback on other configurations is greatly welcomed.

   This module has been created and tested on Windows 98 and WinNT 4.0 on
ActiveState port of Perl 5.6. It has not been tested on Windows 2000 yet.

CHANGES
=======

     0.01 - Initial Release
     0.02 - Fixed CPU speed reporting for Win9x. Module now includes a DLL that
            performs the Win9x CPU speed determination.
     0.03 - Fixed warning "use of uninitialized value" when calling MemoryStatus
            with no size argument.
     0.04 - Fixed "GetValue" error when calling ProcessorInfo as non-admin user
            on Windows NT
          - Fixed documentation bug: "AvailableVirtual" to "AvailVirtual"
     0.05 - Fixed bug introduced in 0.03 where $format was ignored in
            MemoryStatus. All results were returned in bytes regardless of
            $format parameter.

BUGS
====

   Please report.

VERSION
=======

   This man page documents Win32::SystemInfo version 0.05

   February 6, 2001.

AUTHOR
======

   Chad Johnston <cjohnston@rockstardevelopment.com>

COPYRIGHT
=========

   Copyright (C) 2001 by Chad Johnston. All rights reserved.

LICENSE
=======

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1).

   Win32 Win32/Utilities

Powerful and easy ways to manipulate a registry [on Win32 for now].
*******************************************************************

NAME
====

   Win32::TieRegistry - Powerful and easy ways to manipulate a registry
[on Win32 for now].

SYNOPSIS
========

     use Win32::TieRegistry 0.20 ( UseOptionName=>UseOptionValue[,...] );

     $Registry->SomeMethodCall(arg1,...);

     $subKey= $Registry->{"Key\\SubKey\\"};
     $valueData= $Registry->{"Key\\SubKey\\\\ValueName"};
     $Registry->{"Key\\SubKey\\"}= { "NewSubKey" => {...} };
     $Registry->{"Key\\SubKey\\\\ValueName"}= "NewValueData";
     $Registry->{"\\ValueName"}= [ pack("fmt",$data), REG_DATATYPE ];

EXAMPLES
========

     use Win32::TieRegistry( Delimiter=>"#", ArrayValues=>0 );
     $pound= $Registry->Delimiter("/");
     $diskKey= $Registry->{"LMachine/System/Disk/"}
       or  die "Can't read LMachine/System/Disk key: $^E\n";
     $data= $key->{"/Information"}
       or  die "Can't read LMachine/System/Disk//Information value: $^E\n";
     $remoteKey= $Registry->{"//ServerA/LMachine/System/"}
       or  die "Can't read //ServerA/LMachine/System/ key: $^E\n";
     $remoteData= $remoteKey->{"Disk//Information"}
       or  die "Can't read ServerA's System/Disk//Information value: $^E\n";
     foreach $entry (  keys(%$diskKey)  ) {
         ...
     }
     foreach $subKey (  $diskKey->SubKeyNames  ) {
         ...
     }
     $diskKey->AllowSave( 1 );
     $diskKey->RegSaveKey( "C:/TEMP/DiskReg", [] );

DESCRIPTION
===========

   The *Win32::TieRegistry* module lets you manipulate the Registry via
objects [as in "object oriented"] or via tied hashes.  But you will
probably mostly use a combination reference, that is, a reference to a
tied hash that has also been made an object so that you can mix both
access methods [as shown above].

   If you did not get this module as part of `libwin32' in this node, you
might want to get a recent version of `libwin32' in this node from CPAN
which should include this module and the *Win32API::Registry* module that
it uses.

   Skip to the `SUMMARY' in this node section if you just want to dive in
and start using the Registry from Perl.

   Accessing and manipulating the registry is extremely simple using
*Win32::TieRegistry*.  A single, simple expression can return you almost
any bit of information stored in the Registry.  *Win32::TieRegistry* also
gives you full access to the "raw" underlying API calls so that you can do
anything with the Registry in Perl that you could do in C.  But the
"simple" interface has been carefully designed to handle almost all
operations itself without imposing arbitrary limits while providing
sensible defaults so you can list only the parameters you care about.

   But first, an overview of the Registry itself.

The Registry
------------

   The Registry is a forest:  a collection of several tree structures.
The root of each tree is a key.  These root keys are identified by
predefined constants whose names start with "HKEY_".  Although all keys
have a few attributes associated with each [a class, a time stamp, and
security information], the most important aspect of keys is that each can
contain subkeys and can contain values.

   Each subkey has a name:  a string which cannot be blank and cannot
contain the delimiter character [backslash: `'\\''] nor nul [`'\0''].
Each subkey is also a key and so can contain subkeys and values [and has a
class, time stamp, and security information].

   Each value has a name:  a string which E<can> be blank and E<can>
contain the delimiter character [backslash: `'\\''] and any character
except for null, `'\0''.  Each value also has data associated with it.
Each value's data is a contiguous chunk of bytes, which is exactly what a
Perl string value is so Perl strings will usually be used to represent
value data.

   Each value also has a data type which says how to interpret the value
data.  The primary data types are:

REG_SZ
     A null-terminated string.

REG_EXPAND_SZ
     A null-terminated string which contains substrings consisting of a
     percent sign [`'%''], an environment variable name, then a percent
     sign, that should be replaced with the value associate with that
     environment variable.  The system does not automatically do this
     substitution.

REG_BINARY
     Some arbitrary binary value.  You can think of these as being
     "packed" into a string.

     If your system has the `SetDualVar' in this node module installed,
     the `DualBinVals()' option wasn't turned off, and you fetch a
     REG_BINARY value of 4 bytes or fewer, then you can use the returned
     value in a numeric context to get at the "unpacked" numeric value.
     See `GetValue()' for more information.

REG_MULTI_SZ
     Several null-terminated strings concatenated together with an extra
     trailing `'\0'' at the end of the list.  Note that the list can
     include empty strings so use the value's length to determine the end
     of the list, not the first occurrence of `'\0\0''.  It is best to set
     the `SplitMultis()' option so *Win32::TieRegistry* will split these
     values into an array of strings for you.

REG_DWORD
     A long [4-byte] integer value.  These values are expected either
     packed into a 4-character string or as a hex string of E<more than> 4
     characters [but not as a numeric value, unfortunately, as there is no
     sure way to tell a numeric value from a packed 4-byte string that
     just happens to be a string containing a valid numeric value].

     How such values are returned depends on the `DualBinVals()' and
     `DWordsToHex()' options.  See `GetValue()' for details.

   In the underlying Registry calls, most places which take a subkey name
also allow you to pass in a subkey "path" - a string of several subkey
names separated by the delimiter character, backslash [`'\\''].  For
example, doing `RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SYSTEM\\DISK",...)' is
much like opening the `"SYSTEM"' subkey of `HKEY_LOCAL_MACHINE', then
opening its `"DISK"' subkey, then closing the `"SYSTEM"' subkey.

   All of the *Win32::TieRegistry* features allow you to use your own
delimiter in place of the system's delimiter, [`'\\''].  In most of our
examples we will use a forward slash [`'/''] as our delimiter as it is
easier to read and less error prone to use when writing Perl code since
you have to type two backslashes for each backslash you want in a string.
Note that this is true even when using single quotes -
`'\\HostName\LMachine\'' is an invalid string and must be written as
`'\\\\HostName\\LMachine\\''.

   You can also connect to the registry of other computers on your
network.  This will be discussed more later.

   Although the Registry does not have a single root key, the
*Win32::TieRegistry* module creates a virtual root key for you which has
all of the *HKEY_** keys as subkeys.

Tied Hashes Documentation
-------------------------

   Before you can use a tied hash, you must create one.  One way to do
that is via:

     use Win32::TieRegistry ( TiedHash => '%RegHash' );

   which exports a `%RegHash' variable into your package and ties it to
the virtual root key of the Registry.  An alternate method is:

     my %RegHash;
     use Win32::TieRegistry ( TiedHash => \%RegHash );

   There are also several ways you can tie a hash variable to any other
key of the Registry, which are discussed later.

   Note that you will most likely use `$Registry' instead of using a tied
hash.  `$Registry' is a reference to a hash that has been tied to the
virtual root of your computer's Registry [as if, `$Registry= \%RegHash'].
So you would use `$Registry->{Key}' rather than `$RegHash{Key}' and use
`keys %{$Registry}' rather than `keys %RegHash', for example.

   For each hash which has been tied to a Registry key, the Perl keys
function will return a list containing the name of each of the key's
subkeys with a delimiter character appended to it and containing the name
of each of the key's values with a delimiter prepended to it.  For example:

     keys( %{ $Registry->{"HKEY_CLASSES_ROOT\\batfile\\"} } )

   might yield the following list value:

     ( "DefaultIcon\\",  # The subkey named "DefaultIcon"
       "shell\\",        # The subkey named "shell"
       "shellex\\",      # The subkey named "shellex"
       "\\",             # The default value [named ""]
       "\\EditFlags" )   # The value named "EditFlags"

   For the virtual root key, short-hand subkey names are used as shown
below.  You can use the short-hand name, the regular *HKEY_** name, or any
numeric value to access these keys, but the short-hand names are all that
will be returned by the keys function.

"Classes" for HKEY_CLASSES_ROOT
     Contains mappings between file name extensions and the uses for such
     files along with configuration information for COM [MicroSoft's
     Common Object Model] objects.  Usually a link to the
     `"SOFTWARE\\Classes"' subkey of the `HKEY_LOCAL_MACHINE' key.

"CUser" for HKEY_CURRENT_USER
     Contains information specific to the currently logged-in user.
     Mostly software configuration information.  Usually a link to a
     subkey of the `HKEY_USERS' key.

"LMachine" for HKEY_LOCAL_MACHINE
     Contains all manner of information about the computer.

"Users" for HKEY_USERS
     Contains one subkey, `".DEFAULT"', which gets copied to a new subkey
     whenever a new user is added.  Also contains a subkey for each user
     of the system, though only those for active users [usually only one]
     are loaded at any given time.

"PerfData" for HKEY_PERFORMANCE_DATA
     Used to access data about system performance.  Access via this key is
     "special" and all but the most carefully constructed calls will fail,
     usually with `ERROR_INSUFFICIENT_BUFFER'.  For example, you can't
     enumerate key names without also enumerating values which require
     huge buffers but the exact buffer size required cannot be determined
     beforehand because `RegQueryInfoKey()' E<always> fails with
     `ERROR_INSUFFICIENT_BUFFER' for `HKEY_PERFORMANCE_DATA' no matter how
     it is called.  So it is currently not very useful to tie a hash to
     this key.  You can use it to create an object to use for making
     carefully constructed calls to the underlying Reg*() routines.

"CConfig" for HKEY_CURRENT_CONFIG
     Contains minimal information about the computer's current
     configuration that is required very early in the boot process.  For
     example, setting for the display adapter such as screen resolution
     and refresh rate are found in here.

"DynData" for HKEY_DYN_DATA
     Dynamic data.  We have found no documentation for this key.

   A tied hash is much like a regular hash variable in Perl - you give it
a key string inside braces, [`{' and `}'], and it gives you back a value
[or lets you set a value].  For *Win32::TieRegistry* hashes, there are two
types of values that will be returned.

SubKeys
     If you give it a string which represents a subkey, then it will give
     you back a reference to a hash which has been tied to that subkey.
     It can't return the hash itself, so it returns a reference to it.  It
     also blesses that reference so that it is also an object so you can
     use it to call method functions.

Values
     If you give it a string which is a value name, then it will give you
     back a string which is the data for that value.  Alternately, you can
     request that it give you both the data value string and the data
     value type [we discuss how to request this later].  In this case, it
     would return a reference to an array where the value data string is
     element [0] and the value data type is element [1].

   The key string which you use in the tied hash must be interpreted to
determine whether it is a value name or a key name or a path that combines
several of these or even other things.  There are two simple rules that
make this interpretation easy and unambiguous:

     Put a delimiter after each key name.
     Put a delimiter in front of each value name.

   Exactly how the key string will be intepreted is governed by the
following cases, in the order listed.  These cases are designed to "do
what you mean".  Most of the time you won't have to think about them,
especially if you follow the two simple rules above.  After the list of
cases we give several examples which should be clear enough so feel free
to skip to them unless you are worried about the details.

Remote machines
     If the hash is tied to the virtual root of the registry [or the
     virtual root of a remote machine's registry], then we treat hash key
     strings which start with the delimiter character specially.

     If the hash key string starts with two delimiters in a row, then
     those should be immediately followed by the name of a remote machine
     whose registry we wish to connect to.  That can be followed by a
     delimiter and more subkey names, etc.  If the machine name is not
     following by anything, then a virtual root for the remote machine's
     registry is created, a hash is tied to it, and a reference to that
     hash it is returned.

Hash key string starts with the delimiter
     If the hash is tied to a virtual root key, then the leading delimiter
     is ignored.  It should be followed by a valid Registry root key name
     [either a short-hand name like "LMachine", an *HKEY_** value, or a
     numeric value].   This alternate notation is allowed in order to be
     more consistant with the `Open()' method function.

     For all other Registry keys, the leading delimiter indicates that the
     rest of the string is a value name.  The leading delimiter is
     stripped and the rest of the string [which can be empty and can
     contain more delimiters] is used as a value name with no further
     parsing.

Exact match with direct subkey name followed by delimiter
     If you have already called the Perl keys function on the tied hash
     [or have already called MemberNames on the object] and the hash key
     string exactly matches one of the strings returned, then no further
     parsing is done.  In other words, if the key string exactly matches
     the name of a direct subkey with a delimiter appended, then a
     reference to a hash tied to that subkey is returned [but only if keys
     or MemberNames has already been called for that tied hash].

     This is only important if you have selected a delimiter other than
     the system default delimiter and one of the subkey names contains the
     delimiter you have chosen.  This rule allows you to deal with subkeys
     which contain your chosen delimiter in their name as long as you only
     traverse subkeys one level at a time and always enumerate the list of
     members before doing so.

     The main advantage of this is that Perl code which recursively
     traverses a hash will work on hashes tied to Registry keys even if a
     non-default delimiter has been selected.

Hash key string contains two delimiters in a row
     If the hash key string contains two [or more] delimiters in a row,
     then the string is split between the first pair of delimiters.  The
     first part is interpreted as a subkey name or a path of subkey names
     separated by delimiters and with a trailing delimiter.  The second
     part is interpreted as a value name with one leading delimiter [any
     extra delimiters are considered part of the value name].

Hash key string ends with a delimiter
     If the key string ends with a delimiter, then it is treated as a
     subkey name or path of subkey names separated by delimiters.

Hash key string contains a delimiter
     If the key string contains a delimiter, then it is split after the
     last delimiter.  The first part is treated as a subkey name or path
     of subkey names separated by delimiters.  The second part is
     ambiguous and is treated as outlined in the next item.

Hash key string contains no delimiters
     If the hash key string contains no delimiters, then it is ambiguous.

     If you are reading from the hash [fetching], then we first use the
     key string as a value name.  If there is a value with a matching name
     in the Registry key which the hash is tied to, then the value data
     string [and possibly the value data type] is returned.  Otherwise, we
     retry by using the hash key string as a subkey name.  If there is a
     subkey with a matching name, then we return a reference to a hash
     tied to that subkey.  Otherwise we return undef.

     If you are writing to the hash [storing], then we use the key string
     as a subkey name only if the value you are storing is a reference to
     a hash value.  Otherwise we use the key string as a value name.

Examples
........

   Here are some examples showing different ways of accessing Registry
information using references to tied hashes:

Canonical value fetch
          $tip18= $Registry->{"HKEY_LOCAL_MACHINE\\Software\\Microsoft\\"
                     . 'Windows\\CurrentVersion\\Explorer\\Tips\\\\18'};

     Should return the text of important tip number 18.  Note that two
     backslashes, `"\\"', are required to get a single backslash into a
     Perl double-quoted or single-qouted string.  Note that `"\\"' is
     appended to each key name [`"HKEY_LOCAL_MACHINE"' through `"Tips"']
     and `"\\"' is prepended to the value name, `"18"'.

Changing your delimiter
          $Registry->Delimiter("/");
          $tip18= $Registry->{"HKEY_LOCAL_MACHINE/Software/Microsoft/"
                     . 'Windows/CurrentVersion/Explorer/Tips//18'};

     This usually makes things easier to read when working in Perl.  All
     remaining examples will assume the delimiter has been changed as
     above.

Using intermediate keys
          $ms= $Registry->{"LMachine/Software/Microsoft/"};
          $tips= $ms->{"Windows/CurrentVersion/Explorer/Tips/"};
          $tip18= $winlogon->{"/18"};

     Same as above but opens more keys into the Registry which lets you
     efficiently re-access those intermediate keys.  This is slightly less
     efficient if you never reuse those intermediate keys.

Chaining in a single statement
          $tip18= $Registry->{"LMachine/Software/Microsoft/"}->
                    {"Windows/CurrentVersion/Explorer/Tips/"}->{"/18"};

     Like above, this creates intermediate key objects then uses them to
     access other data.  Once this statement finishes, the intermediate
     key objects are destroyed.  Several handles into the Registry are
     opened and closed by this statement so it is less efficient but there
     are times when this will be useful.

Even less efficient example of chaining
          $tip18= $Registry->{"LMachine/Software/Microsoft"}->
                    {"Windows/CurrentVersion/Explorer/Tips"}->{"/18"};

     Because we left off the trailing delimiters, *Win32::TieRegistry*
     doesn't know whether final names, `"Microsoft"' and `"Tips"', are
     subkey names or value names.  So this statement ends up executing the
     same code as the next one.

What the above really does
          $tip18= $Registry->{"LMachine/Software/"}->{"Microsoft"}->
                    {"Windows/CurrentVersion/Explorer/"}->{"Tips"}->{"/18"};

     With more chains to go through, more temporary objects are created
     and later destroyed than in our first chaining example.  Also, when
     `"Microsoft"' is looked up, *Win32::TieRegistry* first tries to open
     it as a value and fails then tries it as a subkey.  The same is true
     for when it looks up `"Tips"'.

Getting all of the tips
          $tips= $Registry->{"LMachine/Software/Microsoft/"}->
                    {"Windows/CurrentVersion/Explorer/Tips/"}
            or  die "Can't find the Windows tips: $^E\n";
          foreach(  keys %$tips  ) {
              print "$_: ", $tips->{$_}, "\n";
          }

     First notice that we actually check for failure for the first time.
     We are assuming that the `"Tips"' key contains no subkeys.  Otherwise
     the print statement would show something like
     `"Win32::TieRegistry=HASH(0xc03ebc)"' for each subkey.

     The output from the above code will start something like:

          /0: If you don't know how to do something,[...]

Deleting items
..............

   You can use the Perl delete function to delete a value from a Registry
key or to delete a subkey as long that subkey contains no subkeys of its
own.  See `More Examples' in this node, below, for more information.

Storing items
.............

   You can use the Perl assignment operator [=] to create new keys, create
new values, or replace values.  The values you store should be in the same
format as the values you would fetch from a tied hash.  For example, you
can use a single assignment statement to copy an entire Registry tree.
The following statement:

     $Registry->{"LMachine/Software/Classes/Tie_Registry/"}=
       $Registry->{"LMachine/Software/Classes/batfile/"};

   creates a `"Tie_Registry"' subkey under the `"Software\\Classes"'
subkey of the `HKEY_LOCAL_MACHINE' key.  Then it populates it with copies
of all of the subkeys and values in the `"batfile"' subkey and all of its
subkeys.  Note that you need to have called `$Registry->ArrayValues(1)'
for the proper value data type information to be copied.  Note also that
this release of *Win32::TieRegistry* does not copy key attributes such as
class name and security information [this is planned for a future release].

   The following statement creates a whole subtree in the Registry:

     $Registry->{"LMachine/Software/FooCorp/"}= {
         "FooWriter/" => {
             "/Version" => "4.032",
             "Startup/" => {
                 "/Title" => "Foo Writer Deluxe ][",
                 "/WindowSize" => [ pack("LL",$wid,$ht), "REG_BINARY" ],
                 "/TaskBarIcon" => [ "0x0001", "REG_DWORD" ],
             },
             "Compatibility/" => {
                 "/AutoConvert" => "Always",
                 "/Default Palette" => "Windows Colors",
             },
         },
         "/License", => "0123-9C8EF1-09-FC",
     };

   Note that all but the last Registry key used on the left-hand side of
the assignment [that is, "LMachine/Software/" but not "FooCorp/"] must
already exist for this statement to succeed.

   By using the leading a trailing delimiters on each subkey name and
value name, *Win32::TieRegistry* will tell you if you try to assign subkey
information to a value or visa-versa.

More examples
.............

Adding a new tip
          $tips= $Registry->{"LMachine/Software/Microsoft/"}->
                    {"Windows/CurrentVersion/Explorer/Tips/"}
            or  die "Can't find the Windows tips: $^E\n";
          $tips{'/186'}= "Be very careful when making changes to the Registry!";

Deleting our new tip
          $tips= $Registry->{"LMachine/Software/Microsoft/"}->
                    {"Windows/CurrentVersion/Explorer/Tips/"}
            or  die "Can't find the Windows tips: $^E\n";
          $tip186= delete $tips{'/186'};

     Note that Perl's delete function returns the value that was deleted.

Adding a new tip differently
          $Registry->{"LMachine/Software/Microsoft/" .
                      "Windows/CurrentVersion/Explorer/Tips//186"}=
            "Be very careful when making changes to the Registry!";

Deleting differently
          $tip186= delete $Registry->{"LMachine/Software/Microsoft/Windows/" .
                                      "CurrentVersion/Explorer/Tips//186"};

     Note that this only deletes the tail of what we looked up, the
     `"186"' value, not any of the keys listed.

Deleting a key
     WARNING:  The following code will delete all information about the
     current user's tip preferences.  Actually executing this command
     would probably cause the user to see the Welcome screen the next time
     they log in and may cause more serious problems.  This statement is
     shown as an example only and should not be used when experimenting.

          $tips= delete $Registry->{"CUser/Software/Microsoft/Windows/" .
                                    "CurrentVersion/Explorer/Tips/"};

     This deletes the `"Tips"' key and the values it contains.  The delete
     function will return a reference to a hash [not a tied hash]
     containing the value names and value data that were deleted.

     The information to be returned is copied from the Registry into a
     regular Perl hash before the key is deleted.  If the key has many
     subkeys, this copying could take a significant amount of memory
     and/or processor time.  So you can disable this process by calling
     the FastDelete member function:

          $prevSetting= $regKey->FastDelete(1);

     which will cause all subsequent delete operations via `$regKey' to
     simply return a true value if they succeed.  This optimization is
     automatically done if you use delete in a void context.

Technical notes on deleting
     If you use delete to delete a Registry key or value and use the
     return value, then *Win32::TieRegistry* usually looks up the current
     contents of that key or value so they can be returned if the deletion
     is successful.  If the deletion succeeds but the attempt to lookup
     the old contents failed, then the return value of delete will be $^E
     from the failed part of the operation.

Undeleting a key
          $Registry->{"LMachine/Software/Microsoft/Windows/" .
                      "CurrentVersion/Explorer/Tips/"}= $tips;

     This adds back what we just deleted.  Note that this version of
     *Win32::TieRegistry* will use defaults for the key attributes [such
     as class name and security] and will not restore the previous
     attributes.

Not deleting a key
     WARNING:  Actually executing the following code could cause serious
     problems.  This statement is shown as an example only and should not
     be used when experimenting.

          $res= delete $Registry->{"CUser/Software/Microsoft/Windows/"}
          defined($res)  ||  die "Can't delete URL key: $^E\n";

     Since the "Windows" key should contain subkeys, that delete statement
     should make no changes to the Registry, return undef, and set $^E to
     "Access is denied".

Not deleting again
          $tips= $Registry->{"CUser/Software/Microsoft/Windows/" .
                             "CurrentVersion/Explorer/Tips/"};
          delete $tips;

     The Perl delete function requires that its argument be an expression
     that ends in a hash element lookup [or hash slice], which is not the
     case here.  The delete function doesn't know which hash $tips came
     from and so can't delete it.

Objects Documentation
---------------------

   The following member functions are defined for use on
*Win32::TieRegistry* objects:

new
     The new method creates a new *Win32::TieRegistry* object.  new is
     mostly a synonym for `Open()' so see `Open()' below for information
     on what arguments to pass in.  Examples:

          $machKey= new Win32::TieRegistry "LMachine"
            or  die "Can't access HKEY_LOCAL_MACHINE key: $^E\n";
          $userKey= Win32::TieRegistry->new("CUser")
            or  die "Can't access HKEY_CURRENT_USER key: $^E\n";

     Note that calling new via a reference to a tied hash returns a simple
     object, not a reference to a tied hash.

Open
$subKey= $key->Open( $sSubKey, $rhOptions )
     The Open method opens a Registry key and returns a new
     *Win32::TieRegistry* object associated with that Registry key.  If
     Open is called via a reference to a tied hash, then Open returns
     another reference to a tied hash.  Otherwise Open returns a simple
     object and you should then use TiedRef to get a reference to a tied
     hash.

     `$sSubKey' is a string specifying a subkey to be opened.  Alternately
     `$sSubKey' can be a reference to an array value containing the list
     of increasingly deep subkeys specifying the path to the subkey to be
     opened.

     `$rhOptions' is an optional reference to a hash containing extra
     options.  The Open method supports two options, `"Delimiter"' and
     `"Access"', and `$rhOptions' should have only have zero or more of
     these strings as keys.  See the "Examples" section below for more
     information.

     The `"Delimiter"' option specifies what string [usually a single
     character] will be used as the delimiter to be appended to subkey
     names and prepended to value names.  If this option is not specified,
     the new key [`$subKey'] inherits the delimiter of the old key [$key].

     The `"Access"' option specifies what level of access to the Registry
     key you wish to have once it has been opened.  If this option is not
     specified, the new key [`$subKey'] is opened with the same access
     level used when the old key [$key] was opened.  The virtual root of
     the Registry pretends it was opened with access
     `KEY_READ()|KEY_WRITE()' so this is the default access when opening
     keys directory via `$Registry'.  If you don't plan on modifying a
     key, you should open it with `KEY_READ' access as you may not have
     `KEY_WRITE' access to it or some of its subkeys.

     If the `"Access"' option value is a string that starts with `"KEY_"',
     then it should match E<one> of the predefined access levels [probably
     `"KEY_READ"', `"KEY_WRITE"', or `"KEY_ALL_ACCESS"'] exported by the
     *Win32API::Registry* module.  Otherwise, a numeric value is expected.
     For maximum flexibility, include `use Win32::TieRegistry
     qw(:KEY_);', for example, near the top of your script so you can
     specify more complicated access levels such as
     `KEY_READ()|KEY_WRITE()'.

     If `$sSubKey' does not begin with the delimiter [or `$sSubKey' is an
     array reference], then the path to the subkey to be opened will be
     relative to the path of the original key [$key].  If `$sSubKey'
     begins with a single delimiter, then the path to the subkey to be
     opened will be relative to the virtual root of the Registry on
     whichever machine the original key resides.  If `$sSubKey' begins
     with two consectutive delimiters, then those must be followed by a
     machine name which causes the `Connect()' method function to be
     called.

     Examples:

          $machKey= $Registry->Open( "LMachine", {Access=>KEY_READ(),Delimiter=>"/"} )
            or  die "Can't open HKEY_LOCAL_MACHINE key: $^E\n";
          $swKey= $machKey->Open( "Software" );
          $logonKey= $swKey->Open( "Microsoft/Windows NT/CurrentVersion/Winlogon/" );
          $NTversKey= $swKey->Open( ["Microsoft","Windows NT","CurrentVersion"] );
          $versKey= $swKey->Open( qw(Microsoft Windows CurrentVersion) );

          $remoteKey= $Registry->Open( "//HostA/LMachine/System/", {Delimiter=>"/"} )
            or  die "Can't connect to HostA or can't open subkey: $^E\n";

Clone
$copy= $key->Clone
     Creates a new object that is associated with the same Registry key as
     the invoking object.

Connect
$remoteKey= $Registry->Connect( $sMachineName, $sKeyPath, $rhOptions )
     The Connect method connects to the Registry of a remote machine, and
     opens a key within it, then returns a new *Win32::TieRegistry* object
     associated with that remote Registry key.  If Connect was called
     using a reference to a tied hash, then the return value will also be
     a reference to a tied hash [or undef].  Otherwise, if you wish to use
     the returned object as a tied hash [not just as an object], then use
     the TiedRef method function after Connect.

     `$sMachineName' is the name of the remote machine.  You don't have to
     preceed the machine name with two delimiter characters.

     `$sKeyPath' is a string specifying the remote key to be opened.
     Alternately `$sKeyPath' can be a reference to an array value
     containing the list of increasingly deep keys specifying the path to
     the key to be opened.

     `$rhOptions' is an optional reference to a hash containing extra
     options.  The Connect method supports two options, `"Delimiter"' and
     `"Access"'.  See the Open method documentation for more information
     on these options.

     `$sKeyPath' is already relative to the virtual root of the Registry
     of the remote machine.  A single leading delimiter on `sKeyPath' will
     be ignored and is not required.

     `$sKeyPath' can be empty in which case Connect will return an object
     representing the virtual root key of the remote Registry.  Each
     subsequent use of Open on this virtual root key will call the system
     RegConnectRegistry function.

     The Connect method can be called via any *Win32::TieRegistry* object,
     not just `$Registry'.  Attributes such as the desired level of access
     and the delimiter will be inherited from the object used but the
     `$sKeyPath' will always be relative to the virtual root of the remote
     machine's registry.

     Examples:

          $remMachKey= $Registry->Connect( "HostA", "LMachine", {Delimiter->"/"} )
            or  die "Can't connect to HostA's HKEY_LOCAL_MACHINE key: $^E\n";

          $remVersKey= $remMachKey->Connect( "www.microsoft.com",
                         "LMachine/Software/Microsoft/Inetsrv/CurrentVersion/",
                         { Access=>KEY_READ, Delimiter=>"/" } )
            or  die "Can't check what version of IIS Microsoft is running: $^E\n";

          $remVersKey= $remMachKey->Connect( "www",
                         qw(LMachine Software Microsoft Inetsrv CurrentVersion) )
            or  die "Can't check what version of IIS we are running: $^E\n";

ObjectRef
$object_ref= $obj_or_hash_ref->ObjectRef
     For a simple object, just returns itself [`$obj == $obj-'ObjectRef>].

     For a reference to a tied hash [if it is also an object], ObjectRef
     returns the simple object that the hash is tied to.

     This is primarilly useful when debugging since typing `x $Registry'
     will try to display your *entire* registry contents to your screen.
     But the debugger command `x $Registry-'ObjectRef> will just dump the
     implementation details of the underlying object to your screen.

Flush( $bFlush )
     Flushes all cached information about the Registry key so that future
     uses will get fresh data from the Registry.

     If the optional `$bFlush' is specified and a true value, then
     `RegFlushKey()' will be called, which is almost never necessary.

GetValue
$ValueData= $key->GetValue( $sValueName )
($ValueData,$ValueType)= $key->GetValue( $sValueName )
     Gets a Registry value's data and data type.

     `$ValueData' is usually just a Perl string that contains the value
     data [packed into it].  For certain types of data, however,
     `$ValueData' may be processed as described below.

     `$ValueType' is the `REG_*' constant describing the type of value
     data stored in `$ValueData'.  If the `DualTypes()' option is on, then
     `$ValueType' will be a dual value.  That is, when used in a numeric
     context, `$ValueType' will give the numeric value of a `REG_*'
     constant.  However, when used in a non-numeric context, `$ValueType'
     will return the name of the `REG_*' constant, for example `"REG_SZ"'
     [note the quotes].  So both of the following can be true at the same
     time:

          $ValueType == REG_SZ()
          $ValueType eq "REG_SZ"

    REG_SZ and REG_EXPAND_SZ
          If the `FixSzNulls()' option is on, then the trailing `'\0''
          will be stripped [unless there isn't one] before values of type
          REG_SZ and REG_EXPAND_SZ are returned.  Note that `SetValue()'
          will add a trailing `'\0'' under similar circumstances.

    REG_MULTI_SZ
          If the `SplitMultis()' option is on, then values of this type are
          returned as a reference to an array containing the strings.  For
          example, a value that, with `SplitMultis()' off, would be
          returned as:

               "Value1\000Value2\000\000"

          would be returned, with `SplitMultis()' on, as:

               [ "Value1", "Value2" ]

    REG_DWORD
          If the `DualBinVals()' option is on, then the value is returned
          as a scalar containing both a string and a number [much like the
          $! variable - see the `SetDualVar' in this node module for more
          information] where the number part is the "unpacked" value.  Use
          the returned value in a numeric context to access this part of
          the value.  For example:

               $num= 0 + $Registry->{"CUser/Console//ColorTable01"};

          If the `DWordsToHex()' option is off, the string part of the
          returned value is a packed, 4-byte string [use
          `unpack("L",$value)' to get the numeric value.

          If `DWordsToHex()' is on, the string part of the returned value
          is a 10-character hex strings [with leading "0x"].  You can use
          `hex($value)' to get the numeric value.

          Note that `SetValue()' will properly understand each of these
          returned value formats no matter how `DualBinVals()' is set.

ValueNames
@names= $key->ValueNames
     Returns the list of value names stored directly in a Registry key.
     Note that the names returned do not have a delimiter prepended to
     them like with `MemberNames()' and tied hashes.

     Once you request this information, it is cached in the object and
     future requests will always return the same list unless `Flush()' has
     been called.

SubKeyNames
@key_names= $key->SubKeyNames
     Returns the list of subkey names stored directly in a Registry key.
     Note that the names returned do not have a delimiter appended to them
     like with `MemberNames()' and tied hashes.

     Once you request this information, it is cached in the object and
     future requests will always return the same list unless `Flush()' has
     been called.

SubKeyClasses
@classes= $key->SubKeyClasses
     Returns the list of classes for subkeys stored directly in a Registry
     key.  The classes are returned in the same order as the subkey names
     returned by `SubKeyNames()'.

SubKeyTimes
@times= $key->SubKeyTimes
     Returns the list of last-modified times for subkeys stored directly
     in a Registry key.  The times are returned in the same order as the
     subkey names returned by `SubKeyNames()'.  Each time is a `FILETIME'
     structure packed into a Perl string.

     Once you request this information, it is cached in the object and
     future requests will always return the same list unless `Flush()' has
     been called.

MemberNames
@members= $key->MemberNames
     Returns the list of subkey names and value names stored directly in a
     Registry key.  Subkey names have a delimiter appended to the end and
     value names have a delimiter prepended to the front.

     Note that a value name could end in a delimiter [or could be "" so
     that the member name returned is just a delimiter] so the presence or
     absence of the leading delimiter is what should be used to determine
     whether a particular name is for a subkey or a value, not the
     presence or absence of a trailing delimiter.

     Once you request this information, it is cached in the object and
     future requests will always return the same list unless `Flush()' has
     been called.

Information
%info= $key->Information
@items= $key->Information( @itemNames );
     Returns the following information about a Registry key:

    LastWrite
          A `FILETIME' structure indicating when the key was last modified
          and packed into a Perl string.

    CntSubKeys
          The number of subkeys stored directly in this key.

    CntValues
          The number of values stored directly in this key.

    SecurityLen
          The length [in bytes] of the largest[?] `SECURITY_DESCRIPTOR'
          associated with the Registry key.

    MaxValDataLen
          The length [in bytes] of the longest value data associated with
          a value stored in this key.

    MaxSubKeyLen
          The length [in chars] of the longest subkey name associated with
          a subkey stored in this key.

    MaxSubClassLen
          The length [in chars] of the longest class name associated with
          a subkey stored directly in this key.

    MaxValNameLen
          The length [in chars] of the longest value name associated with
          a value stored in this key.

     With no arguments, returns a hash [not a reference to a hash] where
     the keys are the names for the items given above and the values are
     the information describe above.  For example:

          %info= ( "CntValues" => 25,         # Key contains 25 values.
                   "MaxValNameLen" => 20,     # One of which has a 20-char name.
                   "MaxValDataLen" => 42,     # One of which has a 42-byte value.
                   "CntSubKeys" => 1,         # Key has 1 immediate subkey.
                   "MaxSubKeyLen" => 13,      # One of which has a 12-char name.
                   "MaxSubClassLen" => 0,     # All of which have class names of "".
                   "SecurityLen" => 232,      # One SECURITY_DESCRIPTOR is 232 bytes.
                   "LastWrite" => "\x90mZ\cX{\xA3\xBD\cA\c@\cA"
                                 # Key was last modifed 1998/06/01 16:29:32 GMT
                 );

     With arguments, each one must be the name of a item given above.  The
     return value is the information associated with the listed names.  In
     other words:

          return $key->Information( @names );

     returns the same list as:

          %info= $key->Information;
          return @info{@names};

Delimiter
$oldDelim= $key->Delimiter
$oldDelim= $key->Delimiter( $newDelim )
     Gets and possibly changes the delimiter used for this object.  The
     delimiter is appended to subkey names and prepended to value names in
     many return values.  It is also used when parsing keys passed to tied
     hashes.

     The delimiter defaults to backslash (`'\\'') but is inherited from
     the object used to create a new object and can be specified by an
     option when a new object is created.

Handle
$handle= $key->Handle
     Returns the raw `HKEY' handle for the associated Registry key as an
     integer value.  This value can then be used to Reg*() calls from
     *Win32API::Registry*.  However, it is usually easier to just call the
     *Win32API::Registry* calls directly via:

          $key->RegNotifyChangeKeyValue( ... );

     For the virtual root of the local or a remote Registry, `Handle()'
     return `"NONE"'.

Path
$path= $key->Path
     Returns a string describing the path of key names to this Registry
     key.  The string is built so that if it were passed to
     `$Registry-'Open()>, it would reopen the same Registry key [except in
     the rare case where one of the key names contains `$key-'Delimiter>].

Machine
$computerName= $key->Machine
     Returns the name of the computer [or "machine"] on which this Registry
     key resides.  Returns "" for local Registry keys.

Access
     Returns the numeric value of the bit mask used to specify the types
     of access requested when this Registry key was opened.  Can be
     compared to `KEY_*' values.

OS_Delimiter
     Returns the delimiter used by the operating system's RegOpenKeyEx()
     call.  For Win32, this is always backslash (`"\\"').

Roots
     Returns the mapping from root key names like "LMachine" to their
     associated `HKEY_*' constants.  Primarily for internal use and
     subject to change.

Tie
$key->Tie( \%hash );
     Ties the referenced hash to that Registry key.  Pretty much the same
     as

          tie %hash, ref($key), $key;

     Since `ref($key)' is the class [package] to tie the hash to and
     `TIEHASH()' just returns its argument, $key, [without calling new()]
     when it sees that it is already a blessed object.

TiedRef
$TiedHashRef= $hash_or_obj_ref->TiedRef
     For a simple object, returns a reference to a hash tied to the
     object.  Used to promote a simple object into a combined object and
     hash ref.

     If already a reference to a tied hash [that is also an object], it
     just returns itself [`$ref == $ref-'TiedRef>].

     Mostly used internally.

ArrayValues
$oldBool= $key->ArrayValues
$oldBool= $key->ArrayValues( $newBool )
     Gets the current setting of the ArrayValues option and possibly turns
     it on or off.

     When off, Registry values fetched via a tied hash are returned as
     just a value scalar [the same as `GetValue()' in a scalar context].
     When on, they are returned as a reference to an array containing the
     value data as the [0] element and the data type as the [1] element.

TieValues
$oldBool= TieValues
$oldBool= TieValues( $newBool )
     Gets the current setting of the TieValues option and possibly turns
     it on or off.

     Turning this option on is not yet supported in this release of
     *Win32::TieRegistry*.  In a future release, turning this option on
     will cause Registry values returned from a tied hash to be a tied
     array that you can use to modify the value in the Registry.

FastDelete
$oldBool= $key->FastDelete
$oldBool= $key->FastDelete( $newBool )
     Gets the current setting of the FastDelete option and possibly turns
     it on or off.

     When on, successfully deleting a Registry key [via a tied hash]
     simply returns 1.

     When off, successfully deleting a Registry key [via a tied hash and
     not in a void context] returns a reference to a hash that contains
     the values present in the key when it was deleted.  This hash is just
     like that returned when referencing the key before it was deleted
     except that it is an ordinary hash, not one tied to the
     *Win32::TieRegistry* package.

     Note that deleting either a Registry key or value via a tied hash *in
     a void context* prevents any overhead in trying to build an
     appropriate return value.

     Note that deleting a Registry value via a tied hash [not in a void
     context] returns the value data even if <FastDelete> is on.

SplitMultis
$oldBool= $key->SplitMultis
$oldBool= $key->SplitMultis( $newBool )
     Gets the current setting of the SplitMultis option and possibly turns
     it on or off.

     If on, Registry values of type REG_MULTI_SZ are returned as a
     reference to an array of strings.  See `GetValue()' for more
     information.

DWordsToHex
$oldBool= $key->DWordsToHex
$oldBool= $key->DWordsToHex( $newBool )
     Gets the current setting of the DWordsToHex option and possibly turns
     it on or off.

     If on, Registry values of type REG_DWORD are returned as a hex string
     with leading `"0x"' and longer than 4 characters.  See `GetValue()'
     for more information.

FixSzNulls
$oldBool= $key->FixSzNulls
$oldBool= $key->FixSzNulls( $newBool )
     Gets the current setting of the FixSzNulls option and possibly turns
     it on or off.

     If on, Registry values of type REG_SZ and REG_EXPAND_SZ have trailing
     `'\0''s added before they are set and stripped before they are
     returned.  See `GetValue()' and `SetValue()' for more information.

DualTypes
$oldBool= $key->DualTypes
$oldBool= $key->DualTypes( $newBool )
     Gets the current setting of the DualTypes option and possibly turns
     it on or off.

     If on, data types are returned as a combined numeric/string value
     holding both the numeric value of a `REG_*' constant and the string
     value of the constant's name.  See `GetValue()' for more information.

DualBinVals
$oldBool= $key->DualBinVals
$oldBool= $key->DualBinVals( $newBool )
     Gets the current setting of the DualBinVals option and possibly turns
     it on or off.

     If on, Registry value data of type REG_BINARY and no more than 4
     bytes long and Registry values of type REG_DWORD are returned as a
     combined numeric/string value where the numeric value is the
     "unpacked" binary value as returned by:

          hex reverse unpack( "h*", $valData )

     on a "little-endian" computer.  [Would be `hex unpack("H*",$valData)'
     on a "big-endian" computer if this module is ever ported to one.]

     See `GetValue()' for more information.

GetOptions
@oldOptValues= $key->GetOptions( @optionNames )
$refHashOfOldOpts= $key->GetOptions()
$key->GetOptions( \%hashForOldOpts )
     Returns the current setting of any of the following options:

          Delimiter     FixSzNulls    DWordsToHex
          ArrayValues   SplitMultis   DualBinVals
          TieValues     FastDelete    DualTypes

     Pass in one or more of the above names (as strings) to get back an
     array of the corresponding current settings in the same order:

          my( $fastDel, $delim )= $key->GetOptions("FastDelete","Delimiter");

     Pass in no arguments to get back a reference to a hash where the
     above option names are the keys and the values are the corresponding
     current settings for each option:

          my $href= $key->GetOptions();
          my $delim= $href->{Delimiter};

     Pass in a single reference to a hash to have the above key/value
     pairs added to the referenced hash.  For this case, the return value
     is the original object so further methods can be chained after the
     call to GetOptions:

          my %oldOpts;
          $key->GetOptions( \%oldOpts )->SetOptions( Delimiter => "/" );

SetOptions
@oldOpts= $key->SetOptions( optNames=>$optValue,... )
     Changes the current setting of any of the following options,
     returning the previous setting(s):

          Delimiter     FixSzNulls    DWordsToHex   AllowLoad
          ArrayValues   SplitMultis   DualBinVals   AllowSave
          TieValues     FastDelete    DualTypes

     For AllowLoad and AllowSave, instead of the previous setting,
     SetOptions returns whether or not the change was successful.

     In a scalar context, returns only the last item.  The last option can
     also be specified as `"ref"' or `"r"' [which doesn't need to be
     followed by a value] to allow chaining:

          $key->SetOptions(AllowSave=>1,"ref")->RegSaveKey(...)

SetValue
$okay= $key->SetValue( $ValueName, $ValueData );
$okay= $key->SetValue( $ValueName, $ValueData, $ValueType );
     Adds or replaces a Registry value.  Returns a true value if
     successfully, false otherwise.

     `$ValueName' is the name of the value to add or replace and should
     not have a delimiter prepended to it.  Case is ignored.

     `$ValueType' is assumed to be REG_SZ if it is omitted.  Otherwise, it
     should be one the `REG_*' constants.

     `$ValueData' is the data to be stored in the value, probably packed
     into a Perl string.  Other supported formats for value data are
     listed below for each posible `$ValueType'.

    REG_SZ or REG_EXPAND_SZ
          The only special processing for these values is the addition of
          the required trailing `'\0'' if it is missing.  This can be
          turned off by disabling the FixSzNulls option.

    REG_MULTI_SZ
          These values can also be specified as a reference to a list of
          strings.  For example, the following two lines are equivalent:

               $key->SetValue( "Val1\000Value2\000LastVal\000\000", "REG_MULTI_SZ" );
               $key->SetValue( ["Val1","Value2","LastVal"], "REG_MULTI_SZ" );

          Note that if the required two trailing nulls (`"\000\000"') are
          missing, then this release of `SetValue()' will not add them.

    REG_DWORD
          These values can also be specified as a hex value with the
          leading `"0x"' included and totaling *more than* 4 bytes.  These
          will be packed into a 4-byte string via:

               $data= pack( "L", hex($data) );

    REG_BINARY
          This value type is listed just to emphasize that no alternate
          format is supported for it.  In particular, you should not pass
          in a numeric value for this type of data.  `SetValue()' cannot
          distinguish such from a packed string that just happens to match
          a numeric value and so will treat it as a packed string.

     An alternate calling format:

          $okay= $key->SetValue( $ValueName, [ $ValueData, $ValueType ] );

     [two arguments, the second of which is a reference to an array
     containing the value data and value type] is supported to ease using
     tied hashes with `SetValue()'.

CreateKey
$newKey= $key->CreateKey( $subKey );
$newKey= $key->CreateKey( $subKey, { Option=>OptVal,... } );
     Creates a Registry key or just updates attributes of one.  Calls
     `RegCreateKeyEx()' then, if it succeeded, creates an object
     associated with the [possibly new] subkey.

     `$subKey' is the name of a subkey [or a path to one] to be created or
     updated.  It can also be a reference to an array containing a list of
     subkey names.

     The second argument, if it exists, should be a reference to a hash
     specifying options either to be passed to `RegCreateKeyEx()' or to be
     used when creating the associated object.  The following items are
     the supported keys for this options hash:

    Delimiter
          Specifies the delimiter to be used to parse `$subKey' and to be
          used in the new object.  Defaults to `$key-'Delimiter>.

    Access
          Specifies the types of access requested when the subkey is
          opened.  Should be a numeric bit mask that combines one or more
          `KEY_*' constant values.

    Class
          The name to assign as the class of the new or updated subkey.
          Defaults to "" as we have never seen a use for this information.

    Disposition
          Lets you specify a reference to a scalar where, upon success,
          will be stored either `REG_CREATED_NEW_KEY()' or
          `REG_OPENED_EXISTING_KEY()' depending on whether a new key was
          created or an existing key was opened.

          If you, for example, did `use Win32::TieRegistry
          qw(REG_CREATED_NEW_KEY)' then you can use
          `REG_CREATED_NEW_KEY()' to compare against the numeric value
          stored in the referenced scalar.

          If the DualTypes option is enabled, then in addition to the
          numeric value described above, the referenced scalar will also
          have a string value equal to either `"REG_CREATED_NEW_KEY"' or
          `"REG_OPENED_EXISTING_KEY"', as appropriate.

    Security
          Lets you specify a `SECURITY_ATTRIBUTES' structure packed into a
          Perl string.  See `Win32API::Registry::RegCreateKeyEx()' for more
          information.

    Volatile
          If true, specifies that the new key should be volatile, that is,
          stored only in memory and not backed by a hive file [and not
          saved if the computer is rebooted].  This option is ignored under
          Windows 95.  Specifying `Volatile=E<GT'1>  is the same as
          specifying `Options=E<GT'REG_OPTION_VOLATILE>.

    Backup
          If true, specifies that the new key should be opened for
          backup/restore access.  The Access option is ignored.  If the
          calling process has enabled `"SeBackupPrivilege"', then the
          subkey is opened with `KEY_READ' access as the `"LocalSystem"'
          user which should have access to all subkeys.  If the calling
          process has enabled `"SeRestorePrivilege"', then the subkey is
          opened with `KEY_WRITE' access as the `"LocalSystem"' user which
          should have access to all subkeys.

          This option is ignored under Windows 95.  Specifying
          `Backup=E<GT'1> is the same as specifying
          `Options=E<GT'REG_OPTION_BACKUP_RESTORE>.

    Options
          Lets you specify options to the `RegOpenKeyEx()' call.  The value
          for this option should be a numeric value combining zero or more
          of the `REG_OPTION_*' bit masks.  You may with to used the
          Volatile and/or Backup options instead of this one.

StoreKey
$newKey= $key->StoreKey( $subKey, \%Contents );
     Primarily for internal use.

     Used to create or update a Registry key and any number of subkeys or
     values under it or its subkeys.

     `$subKey' is the name of a subkey to be created [or a path of subkey
     names separated by delimiters].  If that subkey already exists, then
     it is updated.

     `\%Contents' is a reference to a hash containing pairs of value names
     with value data and/or subkey names with hash references similar to
     `\%Contents'.  Each of these cause a value or subkey of `$subKey' to
     be created or updated.

     If `$Contents{""}' exists and is a reference to a hash, then it used
     as the options argument when `CreateKey()' is called for `$subKey'.
     This allows you to specify ...

          if(  defined( $$data{""} )  &&  "HASH" eq ref($$data{""})  ) {
              $self= $this->CreateKey( $subKey, delete $$data{""} );

Load
$newKey= $key->Load( $file )
$newKey= $key->Load( $file, $newSubKey )
$newKey= $key->Load( $file, $newSubKey, { Option=>OptVal... } )
$newKey= $key->Load( $file, { Option=>OptVal... } )
     Loads a hive file into a Registry.  That is, creates a new subkey and
     associates a hive file with it.

     $file is a hive file, that is a file created by calling
     `RegSaveKey()'.  The $file path is interpreted relative to
     `%SystemRoot%/System32/config' on the machine where $key resides.

     `$newSubKey' is the name to be given to the new subkey.  If
     `$newSubKey' is specified, then $key must be `HKEY_LOCAL_MACHINE' or
     `HKEY_USERS' of the local computer or a remote computer and
     `$newSubKey' should not contain any occurrences of either the
     delimiter or the OS delimiter.

     If `$newSubKey' is not specified, then it is as if $key was
     `$Registry-E<GT'{LMachine}> and `$newSubKey' is `"PerlTie:999"' where
     `"999"' is actually a sequence number incremented each time this
     process calls `Load()'.

     You can specify as the last argument a reference to a hash containing
     options.  You can specify the same options that you can specify to
     `Open()'.  See `Open()' for more information on those.  In addition,
     you can specify the option `"NewSubKey"'.  The value of this option
     is interpretted exactly as if it was specified as the `$newSubKey'
     parameter and overrides the `$newSubKey' if one was specified.

     The hive is automatically unloaded when the returned object
     [`$newKey'] is destroyed.  Registry key objects opened within the
     hive will keep a reference to the `$newKey' object so that it will
     not be destroyed before these keys are closed.

UnLoad
$okay= $key->UnLoad
     Unloads a hive that was loaded via `Load()'.  Cannot unload other
     hives.  $key must be the return from a previous call to `Load()'.
     $key is closed and then the hive is unloaded.

AllowSave
$okay= AllowSave( $bool )
     Enables or disables the `"ReBackupPrivilege"' privilege for the
     current process.  You will probably have to enable this privilege
     before you can use `RegSaveKey()'.

     The return value indicates whether the operation succeeded, not
     whether the privilege was previously enabled.

AllowLoad
$okay= AllowLoad( $bool )
     Enables or disables the `"ReRestorePrivilege"' privilege for the
     current process.  You will probably have to enable this privilege
     before you can use `RegLoadKey()', `RegUnLoadKey()',
     `RegReplaceKey()', or RegRestoreKey and thus `Load()' and `UnLoad()'.

     The return value indicates whether the operation succeeded, not
     whether the privilege was previously enabled.

Exports [use and import()]
--------------------------

   To have nothing imported into your package, use something like:

     use Win32::TieRegistry 0.20 ();

   which would verify that you have at least version 0.20 but wouldn't
call import().  The Changes file can be useful in figuring out which, if
any, prior versions of *Win32::TieRegistry* you want to support in your
script.

   The code

     use Win32::TieRegistry;

   imports the variable `$Registry' into your package and sets it to be a
reference to a hash tied to a copy of the master Registry virtual root
object with the default options.  One disadvantage to this "default" usage
is that Perl does not support checking the module version when you use it.

   Alternately, you can specify a list of arguments on the use line that
will be passed to the `Win32::TieRegistry-'import()> method to control
what items to import into your package.  These arguments fall into the
following broad categories:

Import a reference to a hash tied to a Registry virtual root
     You can request that a scalar variable be imported (possibly) and set
     to be a reference to a hash tied to a Registry virtual root using any
     of the following types of arguments or argument pairs:

    "TiedRef", '$scalar'
    "TiedRef", '$pack::scalar'
    "TiedRef", 'scalar'
    "TiedRef", 'pack::scalar'
          All of the above import a scalar named $scalar into your package
          (or the package named "pack") and then sets it.

    '$scalar'
    '$pack::scalar'
          These are equivalent to the previous items to support a more
          traditional appearance to the list of exports.  Note that the
          scalar name cannot be "RegObj" here.

    "TiedRef", \$scalar
    \$scalar
          These versions don't import anything but set the referenced
          $scalar.

Import a hash tied to the Registry virtual root
     You can request that a hash variable be imported (possibly) and tied
     to a Registry virtual root using any of the following types of
     arguments or argument pairs:

    "TiedHash", '%hash'
    "TiedHash", '%pack::hash'
    "TiedHash", 'hash'
    "TiedHash", 'pack::hash'
          All of the above import a hash named `%hash' into your package
          (or the package named "pack") and then sets it.

    '%hash'
    '%pack::hash'
          These are equivalent to the previous items to support a more
          traditional appearance to the list of exports.

    "TiedHash", \%hash
    \%hash
          These versions don't import anything but set the referenced
          `%hash'.

Import a Registry virtual root object
     You can request that a scalar variable be imported (possibly) and set
     to be a Registry virtual root object using any of the following types
     of arguments or argument pairs:

    "ObjectRef", '$scalar'
    "ObjectRef", '$pack::scalar'
    "ObjectRef", 'scalar'
    "ObjectRef", 'pack::scalar'
          All of the above import a scalar named $scalar into your package
          (or the package named "pack") and then sets it.

    '$RegObj'
          This is equivalent to the previous items for backward
          compatibility.

    "ObjectRef", \$scalar
          This version doesn't import anything but sets the referenced
          $scalar.

Import constant(s) exported by *Win32API::Registry*
     You can list any constants that are exported by *Win32API::Registry*
     to have them imported into your package.  These constants have names
     starting with "KEY_" or "REG_" (or even "HKEY_").

     You can also specify `":KEY_"', `":REG_"', and even `":HKEY_"' to
     import a whole set of constants.

     See *Win32API::Registry* documentation for more information.

Options
     You can list any option names that can be listed in the `SetOptions()'
     method call, each folowed by the value to use for that option.  A
     Registry virtual root object is created, all of these options are set
     for it, then each variable to be imported/set is associated with this
     object.

     In addition, the following special options are supported:

    ExportLevel
          Whether to import variables into your package or some package
          that uses your package.  Defaults to the value of
          `$Exporter::ExportLevel' and has the same meaning.  See the
          Exporter, module for more information.

    ExportTo
          The name of the package to import variables and constants into.
          Overrides ExportLevel.

Specifying constants in your Perl code
......................................

   This module was written with a strong emphasis on the convenience of
the module user.  Therefore, most places where you can specify a constant
like `REG_SZ()' also allow you to specify a string containing the name of
the constant, `"REG_SZ"'.  This is convenient because you may not have
imported that symbolic constant.

   Perl also emphasizes programmer convenience so the code REG_SZ can be
used to mean `REG_SZ()' or `"REG_SZ"' or be illegal.  Note that using
`&REG_SZ' (as we've seen in much Win32 Perl code) is not a good idea since
it passes the current `@_' to the `constant()' routine of the module
which, at the least, can give you a warning under -w.

   Although greatly a matter of style, the "safest" practice is probably
to specifically list all constants in the `use Win32::TieRegistry'
statement, specify `use strict' [or at least `use strict qw(subs)'], and
use bare constant names when you want the numeric value.  This will detect
mispelled constant names at compile time.

     use strict;
     my $Registry;
     use Win32::TieRegistry 0.20 (
         TiedRef => \$Registry,  Delimiter => "/",  ArrayValues => 1,
     	SplitMultis => 1,  AllowLoad => 1,
         qw( REG_SZ REG_EXPAND_SZ REG_DWORD REG_BINARY REG_MULTI_SZ
     	    KEY_READ KEY_WRITE KEY_ALL_ACCESS ),
     );
     $Registry->{"LMachine/Software/FooCorp/"}= {
         "FooWriter/" => {
             "/Fonts" => [ ["Times","Courier","Lucinda"], REG_MULTI_SZ ],
     	    "/WindowSize" => [ pack("LL",24,80), REG_BINARY ],
     	    "/TaskBarIcon" => [ "0x0001", REG_DWORD ],
     	},
     }  or  die "Can't create Software/FooCorp/: $^E\n";

   If you don't want to `use strict qw(subs)', the second safest practice
is similar to the above but use the `REG_SZ()' form for constants when
possible and quoted constant names when required.  Note that `qw()' is a
form of quoting.

     use Win32::TieRegistry 0.20 qw(
         TiedRef $Registry
         Delimiter /  ArrayValues 1  SplitMultis 1  AllowLoad 1
         REG_SZ REG_EXPAND_SZ REG_DWORD REG_BINARY REG_MULTI_SZ
         KEY_READ KEY_WRITE KEY_ALL_ACCESS
     );
     $Registry->{"LMachine/Software/FooCorp/"}= {
         "FooWriter/" => {
             "/Fonts" => [ ["Times","Courier","Lucinda"], REG_MULTI_SZ() ],
     	    "/WindowSize" => [ pack("LL",24,80), REG_BINARY() ],
     	    "/TaskBarIcon" => [ "0x0001", REG_DWORD() ],
     	},
     }  or  die "Can't create Software/FooCorp/: $^E\n";

   The examples in this document mostly use quoted constant names
(`"REG_SZ"') since that works regardless of which constants you imported
and whether or not you have `use strict' in your script.  It is not the
best choice for you to use for real scripts (vs. examples) because it is
less efficient and is not supported by most other similar modules.

SUMMARY
=======

   Most things can be done most easily via tied hashes.  Skip down to the
the `Tied Hashes Summary' in this node to get started quickly.

Objects Summary
---------------

   Here are quick examples that document the most common functionality of
all of the method functions [except for a few almost useless ones].

     # Just another way of saying Open():
     $key= new Win32::TieRegistry "LMachine\\Software\\",
       { Access=>KEY_READ()|KEY_WRITE(), Delimiter=>"\\" };

     # Open a Registry key:
     $subKey= $key->Open( "SubKey/SubSubKey/",
       { Access=>KEY_ALL_ACCESS, Delimiter=>"/" } );

     # Connect to a remote Registry key:
     $remKey= $Registry->Connect( "MachineName", "LMachine/",
       { Access=>KEY_READ, Delimiter=>"/" } );

     # Get value data:
     $valueString= $key->GetValue("ValueName");
     ( $valueString, $valueType )= $key->GetValue("ValueName");

     # Get list of value names:
     @valueNames= $key->ValueNames;

     # Get list of subkey names:
     @subKeyNames= $key->SubKeyNames;

     # Get combined list of value names (with leading delimiters)
     # and subkey names (with trailing delimiters):
     @memberNames= $key->MemberNames;

     # Get all information about a key:
     %keyInfo= $key->Information;
     # keys(%keyInfo)= qw( Class LastWrite SecurityLen
     #   CntSubKeys MaxSubKeyLen MaxSubClassLen
     #   CntValues MaxValNameLen MaxValDataLen );

     # Get selected information about a key:
     ( $class, $cntSubKeys )= $key->Information( "Class", "CntSubKeys" );

     # Get and/or set delimiter:
     $delim= $key->Delimiter;
     $oldDelim= $key->Delimiter( $newDelim );

     # Get "path" for an open key:
     $path= $key->Path;
     # For example, "/CUser/Control Panel/Mouse/"
     # or "//HostName/LMachine/System/DISK/".

     # Get name of machine where key is from:
     $mach= $key->Machine;
     # Will usually be "" indicating key is on local machine.

     # Control different options (see main documentation for descriptions):
     $oldBool= $key->ArrayValues( $newBool );
     $oldBool= $key->FastDelete( $newBool );
     $oldBool= $key->FixSzNulls( $newBool );
     $oldBool= $key->SplitMultis( $newBool );
     $oldBool= $key->DWordsToHex( $newBool );
     $oldBool= $key->DualBinVals( $newBool );
     $oldBool= $key->DualTypes( $newBool );
     @oldBools= $key->SetOptions( ArrayValues=>1, FastDelete=>1, FixSzNulls=>0,
       Delimiter=>"/", AllowLoad=>1, AllowSave=>1 );
     @oldBools= $key->GetOptions( ArrayValues, FastDelete, FixSzNulls );

     # Add or set a value:
     $key->SetValue( "ValueName", $valueDataString );
     $key->SetValue( "ValueName", pack($format,$valueData), "REG_BINARY" );

     # Add or set a key:
     $key->CreateKey( "SubKeyName" );
     $key->CreateKey( "SubKeyName",
       { Access=>"KEY_ALL_ACCESS", Class=>"ClassName",
         Delimiter=>"/", Volatile=>1, Backup=>1 } );

     # Load an off-line Registry hive file into the on-line Registry:
     $newKey= $Registry->Load( "C:/Path/To/Hive/FileName" );
     $newKey= $key->Load( "C:/Path/To/Hive/FileName", "NewSubKeyName",
                      { Access=>"KEY_READ" } );
     # Unload a Registry hive file loaded via the Load() method:
     $newKey->UnLoad;

     # (Dis)Allow yourself to load Registry hive files:
     $success= $Registry->AllowLoad( $bool );

     # (Dis)Allow yourself to save a Registry key to a hive file:
     $success= $Registry->AllowSave( $bool );

     # Save a Registry key to a new hive file:
     $key->RegSaveKey( "C:/Path/To/Hive/FileName", [] );

Other Useful Methods
....................

   See *Win32API::Registry* for more information on these methods.  These
methods are provided for coding convenience and are identical to the
*Win32API::Registry* functions except that these don't take a handle to a
Registry key, instead getting the handle from the invoking object [$key].

     $key->RegGetKeySecurity( $iSecInfo, $sSecDesc, $lenSecDesc );
     $key->RegLoadKey( $sSubKeyName, $sPathToFile );
     $key->RegNotifyChangeKeyValue(
       $bWatchSubtree, $iNotifyFilter, $hEvent, $bAsync );
     $key->RegQueryMultipleValues(
       $structValueEnts, $cntValueEnts, $Buffer, $lenBuffer );
     $key->RegReplaceKey( $sSubKeyName, $sPathToNewFile, $sPathToBackupFile );
     $key->RegRestoreKey( $sPathToFile, $iFlags );
     $key->RegSetKeySecurity( $iSecInfo, $sSecDesc );
     $key->RegUnLoadKey( $sSubKeyName );

Tied Hashes Summary
-------------------

   For fast learners, this may be the only section you need to read.
Always append one delimiter to the end of each Registry key name and
prepend one delimiter to the front of each Registry value name.

Opening keys
............

     use Win32::TieRegistry ( Delimiter=>"/", ArrayValues=>1 );
     $Registry->Delimiter("/");                  # Set delimiter to "/".
     $swKey= $Registry->{"LMachine/Software/"};
     $winKey= $swKey->{"Microsoft/Windows/CurrentVersion/"};
     $userKey= $Registry->
       {"CUser/Software/Microsoft/Windows/CurrentVersion/"};
     $remoteKey= $Registry->{"//HostName/LMachine/"};

Reading values
..............

     $progDir= $winKey->{"/ProgramFilesDir"};    # "C:\\Program Files"
     $tip21= $winKey->{"Explorer/Tips//21"};     # Text of tip #21.

     $winKey->ArrayValues(1);
     ( $devPath, $type )= $winKey->{"/DevicePath"};
     # $devPath eq "%SystemRoot%\\inf"
     # $type eq "REG_EXPAND_SZ"  [if you have SetDualVar.pm installed]
     # $type == REG_EXPAND_SZ()  [if did C<use Win32::TieRegistry qw(:REG_)>]

Setting values
..............

     $winKey->{"Setup//SourcePath"}= "\\\\SwServer\\SwShare\\Windows";
     # Simple.  Assumes data type of REG_SZ.

     $winKey->{"Setup//Installation Sources"}=
       [ "D:\x00\\\\SwServer\\SwShare\\Windows\0\0", "REG_MULTI_SZ" ];
     # "\x00" and "\0" used to mark ends of each string and end of list.

     $winKey->{"Setup//Installation Sources"}=
       [ ["D:","\\\\SwServer\\SwShare\\Windows"], "REG_MULTI_SZ" ];
     # Alternate method that is easier to read.

     $userKey->{"Explorer/Tips//DisplayInitialTipWindow"}=
       [ pack("L",0), "REG_DWORD" ];
     $userKey->{"Explorer/Tips//Next"}= [ pack("S",3), "REG_BINARY" ];
     $userKey->{"Explorer/Tips//Show"}= [ pack("L",0), "REG_BINARY" ];

Adding keys
...........

     $swKey->{"FooCorp/"}= {
         "FooWriter/" => {
             "/Version" => "4.032",
             "Startup/" => {
                 "/Title" => "Foo Writer Deluxe ][",
                 "/WindowSize" => [ pack("LL",$wid,$ht), "REG_BINARY" ],
                 "/TaskBarIcon" => [ "0x0001", "REG_DWORD" ],
             },
             "Compatibility/" => {
                 "/AutoConvert" => "Always",
                 "/Default Palette" => "Windows Colors",
             },
         },
         "/License", => "0123-9C8EF1-09-FC",
     };

Listing all subkeys and values
..............................

     @members= keys( %{$swKey} );
     @subKeys= grep(  m#^/#,  keys( %{$swKey->{"Classes/batfile/"}} )  );
     # @subKeys= ( "/", "/EditFlags" );
     @valueNames= grep(  ! m#^/#,  keys( %{$swKey->{"Classes/batfile/"}} )  );
     # @valueNames= ( "DefaultIcon/", "shell/", "shellex/" );

Deleting values or keys with no subkeys
.......................................

     $oldValue= delete $userKey->{"Explorer/Tips//Next"};

     $oldValues= delete $userKey->{"Explorer/Tips/"};
     # $oldValues will be reference to hash containing deleted keys values.

Closing keys
............

     undef $swKey;               # Explicit way to close a key.
     $winKey= "Anything else";   # Implicitly closes a key.
     exit 0;                     # Implicitly closes all keys.

Tie::Registry
-------------

   This module was originally called Tie::Registry.  Changing code that
used Tie::Registry over to *Win32::TieRegistry* is trivial as the module
name should only be mentioned once, in the use line.  However, finding all
of the places that used Tie::Registry may not be completely trivial so we
have included `Tie/Registry.pm' which you can install to provide backward
compatibility.

AUTHOR
======

   Tye McQueen.  See http://www.metronet.com/~tye/ or e-mail
tye@metronet.com with bug reports.

SEE ALSO
========

   *Win32API::Registry* - Provides access to `Reg*()', `HKEY_*', `KEY_*',
`REG_*' [required].

   *Win32::WinError* - Defines `ERROR_*' values [optional].

   `SetDualVar' in this node - For returning `REG_*' values as combined
string/integer values [optional].

BUGS
====

   Perl5.004_02 has bugs that make *Win32::TieRegistry* fail in strange
and subtle ways.

   Using *Win32::TieRegistry* with versions of Perl prior to 5.005 can be
tricky or impossible.  Most notes about this have been removed from the
documentation (they get rather complicated and confusing).  This includes
references to $^E perhaps not being meaningful.

   Because Perl hashes are case sensitive, certain lookups are also case
sensistive.  In particular, the root keys ("Classes", "CUser", "LMachine",
"Users", "PerfData", "CConfig", "DynData", and HKEY_*) must always be
entered without changing between upper and lower case letters.  Also, the
special rule for matching subkey names that contain the user-selected
delimiter only works if case is matched.  All other key name and value
name lookups should be case insensitive because the underlying Reg*()
calls ignore case.

   Information about each key is cached when using a tied hash.  This
cache is not flushed nor updated when changes are made, *even when the
same tied hash is used* to make the changes.

   Current implementations of Perl's "global destruction" phase can cause
objects returned by `Load()' to be destroyed while keys within the hive
are still open, if the objects still exist when the script starts to exit.
When this happens, the automatic `UnLoad()' will report a failure and the
hive will remain loaded in the Registry.

   Trying to `Load()' a hive file that is located on a remote network
share may silently delete all data from the hive.  This is a bug in the
Win32 APIs, not any Perl code or modules.  This module does not try to
protect you from this bug.

   There is no test suite.

FUTURE DIRECTIONS
=================

   The following items are desired by the author and may appear in a
future release of this module.

TieValues option
     Currently described in main documentation but no yet implemented.

AutoRefresh option
     Trigger use of `RegNotifyChangeKeyValue()' to keep tied hash caches
     up-to-date even when other programs make changes.

Error options
     Allow the user to have unchecked calls (calls in a "void context") to
     automatically report errors via warn or die.

     For complex operations, such a copying an entire subtree, provide
     access to detailed information about errors (and perhaps some
     warnings) that were encountered.  Let the user control whether the
     complex operation continues in spite of errors.

Access Win32 constants such as WM_CLOSE, HELP_CONTENTS, etc.
************************************************************

NAME
====

   Win32API::Const - Access Win32 constants such as WM_CLOSE,
HELP_CONTENTS, etc.

SYNOPSIS
========

     #
     # Access value of WM_CLOSE without importing it
     #
     use Win32API::Const;
     print "WM_CLOSE         = ", Win32API::Const::WM_CLOSE(), "\n";

     #
     # Import and access values of WM_CLOSE and HELP_CONTENTS
     #
     use Win32API::Const qw(WM_CLOSE HELP_CONTENTS);
     print "WM_CLOSE         = ", WM_CLOSE(),      "\n";
     print "HELP_CONTENTS    = ", HELP_CONTENTS(), "\n";

     #
     # Import WM_CLOSE, along with all constants whose names start with WS_ or SE_
     #
     use Win32API::Const qw(:WS_ WM_CLOSE :SE_);
     print "WM_CLOSE         = ", WM_CLOSE(),         "\n";
     print "WS_MAXIMIZE      = ", WS_MAXIMIZE(),      "\n";
     print "WS_MINIMIZE      = ", WS_MINIMIZE(),      "\n";
     print "WS_OVERLAPPED    = ", WS_OVERLAPPED(),    "\n";
     print "SE_SHUTDOWN_NAME = ", SE_SHUTDOWN_NAME(), "\n";

DESCRIPTION
===========

   The Win32API::Const module allows you to access the values of Win32
constants by name. Almost 6,000 constants are included - these were parsed
from the egcs 1.1 header files: Defines.h, Messages.h, Errors.h, Base.h,
and Sockets.h.

   Constant names and values were parsed from the egcs 1.1 Win32 header
files (egcs is the free GNU C/C++ compiler). You can download the Win32
version of egcs from <ftp://ftp.xraylith.wisc.edu/pub/khan/gnu-win32/>.

   A full list of Win32 constants and their meanings can be found in the
documentation for your Win32 C/C++ compiler or in the Microsoft Developer
Network (MSDN).

IMPORT A CONSTANT
-----------------

   To import a constant, specify its name on the use line. For example, to
import the constants `WM_CLOSE' and `SE_SHUTDOWN_NAME', do this:

     use Win32API::Const qw(WM_CLOSE SE_SHUTDOWN_NAME);

   Then, you can get the value of the constant by calling it like a
subroutine.

     my $value = WM_CLOSE();
     print "The value of WM_CLOSE is: $value\n";

IMPORT A RANGE OF CONSTANTS
---------------------------

   If you want to import all Win32 constants that start with, let's say,
"WM_", then place ":WM_" in the import list. For example:

     use Win32API::Const qw(:WM_);
     print "The value of WM_CLOSE is: ", WM_CLOSE(), "\n";
     print "The value of WM_HELP is:  ", WM_HELP(),  "\n";

   You can import an individual constant and a range of constants on the
same line. For example, let's say you wan to import all the constants that
start with `WM_' and `HELP_', along with the constant named
`SE_SHUTDOWN_NAME'.

     use Win32API::Const qw(:WM_ SE_SHUTDOWN_NAME :HELP_);

   The order you list stuff in the import list does not matter.

   Note that importing `:WM' is different than importing `:WM_' (note the
trailing underscore).  The former imports constants such as `WMSZ_BOTTOM',
whereas the latter does not. It's up to you what you want to do.

USE A CONSTANT WITHOUT IMPORTING IT
-----------------------------------

   You can still use a constant, even if you do not import it into your
namespace - heck, even if you do not import any constants into your
namespace. Just call it like you would any subroutine, and specify the
full Win32API::Const package name.

     use Win32API::Const;

     print "WM_CLOSE = ", Win32API::Const::WM_CLOSE(), "\n";

COPYRIGHT
=========

   Win32API::Const - Basic API Constants Copyright (C) 1998 Brian Dellert:
<aspider@pobox.com>, 206/689-6828, <http://www.applespider.com>

   Constants parsed from the egcs 1.1 header files Defines.h, Messages.h,
Errors.h, Base.h, & Sockets.h

   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 (gpl.license.txt); if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

SEE ALSO
========

Low-level access to Win32 system API calls for files/dirs.
**********************************************************

NAME
====

   Win32API::File - Low-level access to Win32 system API calls for
files/dirs.

SYNOPSIS
========

     use Win32API::File 0.08 qw( :ALL );

     MoveFile( $Source, $Destination )
       or  die "Can't move $Source to $Destination: ",fileLastError(),"\n";
     MoveFileEx( $Source, $Destination, MOVEFILE_REPLACE_EXISTING() )
       or  die "Can't move $Source to $Destination: ",fileLastError(),"\n";
     [...]

DESCRIPTION
===========

   This provides fairly low-level access to the Win32 System API calls
dealing with files and directories.

   To pass in NULL as the pointer to an optional buffer, pass in an empty
list reference, [].

   Beyond raw access to the API calls and related constants, this module
handles smart buffer allocation and translation of return codes.

   All functions, unless otherwise noted, return a true value for success
and a false value for failure and set $^E on failure.

Exports
-------

   Nothing is exported by default.  The following tags can be used to have
large sets of symbols exported:  `":Func"', `":FuncA"', `":FuncW"',
`":Misc"', `":DDD_"', `":DRIVE_"', `":FILE_"', `":FILE_ATTRIBUTE_"',
`":FILE_FLAG_"', `":FILE_SHARE_"', `":FILE_TYPE_"', `":FS_"',
`":HANDLE_FLAG_"', `":IOCTL_STORAGE_"', `":IOCTL_DISK_"', `":GENERIC_"',
`":MEDIA_TYPE"', `":MOVEFILE_"', `":SECURITY_"', `":SEM_"', and
`":PARTITION_"'.

`":Func"'
     The basic function names: attrLetsToBits,       createFile,
     fileConstant,          fileLastError,        getLogicalDrives,
     CloseHandle,           CopyFile,             CreateFile,
     DefineDosDevice,       DeleteFile,           DeviceIoControl,
     FdGetOsFHandle,        GetDriveType,         GetFileType,
     GetHandleInformation,  GetLogicalDrives,     GetLogicalDriveStrings,
     GetOsFHandle,          GetVolumeInformation, IsRecognizedPartition,
     IsContainerPartition,  MoveFile,             MoveFileEx,
     OsFHandleOpen,         OsFHandleOpenFd,      QueryDosDevice,
     ReadFile,              SetErrorMode,         SetFilePointer,
     SetHandleInformation,  and                      WriteFile.

    attrLetsToBits
    `$uBits= attrLetsToBits( $sAttributeLetters )'
          Converts a string of file attribute letters into an unsigned
          value with the corresponding bits set.  `$sAttributeLetters'
          should contain zero or more letters from `"achorst"':

         `"a"'
               `FILE_ATTRIBUTE_ARCHIVE'

         `"c"'
               `FILE_ATTRIBUTE_COMPRESSED'

         `"h"'
               `FILE_ATTRIBUTE_HIDDEN'

         `"o"'
               `FILE_ATTRIBUTE_OFFLINE'

         `"r"'
               `FILE_ATTRIBUTE_READONLY'

         `"s"'
               `FILE_ATTRIBUTE_SYSTEM'

         `"t"'
               `FILE_ATTRIBUTE_TEMPORARY'

    createFile
    `$hObject= createFile( $sPath )'
    `$hObject= createFile( $sPath, $rvhvOptions )'
    `$hObject= createFile( $sPath, $svAccess )'
    `$hObject= createFile( $sPath, $svAccess, $rvhvOptions )'
    `$hObject= createFile( $sPath, $svAccess, $svShare )'
    `$hObject= createFile( $sPath, $svAccess, $svShare, $rvhvOptions )'
          This is a Perl-friendly wrapper around CreateFile.

          On failure, `$hObject' gets set to a false value and
          `regLastError()' and $^E are set to the reason for the failure.
          Otherwise, `$hObject' gets set to a Win32 native file handle
          which is alwasy a true value [returns `"0 but true"' in the
          impossible(?) case of the handle having a value of 0].

          `$sPath' is the path to the file [or device, etc.] to be opened.
          See CreateFile for more information on possible special values
          for `$sPath'.

          `$svAccess' can be a number containing the bit mask representing
          the specific type(s) of access to the file that you desire.  See
          the `$uAccess' parameter to CreateFile for more information on
          these values.

          More likely, `$svAccess' is a string describing the generic type
          of access you desire and possibly the file creation options to
          use.  In this case, `$svAccess' should contain zero or more
          characters from `"qrw"' [access desired], zero or one character
          each from `"ktn"' and `"ce"', and optional white space.  These
          letters stand for, respectively, "Query access", "Read access",
          "Write access", "Keep if exists", "Truncate if exists", "New
          file only", "Create if none", and "Existing file only".  Case is
          ignored.

          You can pass in `"?"' for `$svAccess' to have an error message
          displayed summarizing its possible values.  This is very handy
          when doing on-the-fly programming using the Perl debugger:

               Win32API::File::createFile:  $svAccess can use the following:
               	One or more of the following:
               	    q -- Query access (same as 0)
               	    r -- Read access (GENERIC_READ)
               	    w -- Write access (GENERIC_WRITE)
               	At most one of the following:
               	    k -- Keep if exists
               	    t -- Truncate if exists
               	    n -- New file only (fail if file already exists)
               	At most one of the following:
               	    c -- Create if doesn't exist
               	    e -- Existing file only (fail if doesn't exist)
                 ''   is the same as 'q  k e'
                 'r'  is the same as 'r  k e'
                 'w'  is the same as 'w  t c'
                 'rw' is the same as 'rw k c'
                 'rt' or 'rn' implies 'c'.
                 Or $access can be numeric.

          `$svAccess' is designed to be "do what I mean", so you can skip
          the rest of its explanation unless you are interested in the
          complex details.  Note that, if you want write access to a
          device, you need to specify `"k"' [and perhaps `"e"', as in `"w
          ke"' or `"rw ke"'] since Win32 suggests `OPEN_EXISTING' be used
          when opening a device.

         `"q"'
               Stands for "Query access".  This is really a no-op since
               you always have query access when you open a file.  You can
               specify `"q"' to document that you plan to query the file
               [or device, etc.].  This is especially helpful when you
               don't want read nor write access since something like `"q"'
               or `"q ke"' may be easier to understand than just "" or
               `"ke"'.

         `"r"'
               Stands for "Read access".  Sets the `GENERIC_READ' bit(s)
               in the `$uAccess' that is passed to CreateFile.  This is
               the default access if the `$svAccess' parameter is missing
               [or if it is undef and `$rvhvOptions' doesn't specify an
               `"Access"' option].

         `"w"'
               Stands for "Write access".  Sets the `GENERIC_WRITE' bit(s)
               in the `$uAccess' that is passed to CreateFile.

         `"k"'
               Stands for "Keep if exists".  If the requested file exists,
               then it is opened.  This is the default unless
               `GENERIC_WRITE' access has been requested but
               `GENERIC_READ' access has not been requested.   Contrast
               with `"t"' and `"n"'.

         `"t"'
               Stands for "Truncate if exists".  If the requested file
               exists, then it is truncated to zero length and then
               opened.  This is the default if `GENERIC_WRITE' access has
               been requested and `GENERIC_READ' access has not been
               requested.  Contrast with `"k"' and `"n"'.

         `"n"'
               Stands for "New file only".  If the requested file exists,
               then it is not opened and the createFile call fails.
               Contrast with `"k"' and `"t"'.  Can't be used with `"e"'.

         `"c"'
               Stands for "Create if none".  If the requested file does not
               exist, then it is created and then opened.  This is the
               default if `GENERIC_WRITE' access has been requested or if
               `"t"' or `"n"' was specified.  Contrast with `"e"'.

         `"e"'
               Stands for "Existing file only".  If the requested file
               does not exist, then nothing is opened and the createFile
               call fails.  This is the default unless `GENERIC_WRITE'
               access has been requested or `"t"' or `"n"' was specified.
               Contrast with `"c"'.   Can't be used with `"n"'.

          The characters from `"ktn"' and `"ce"' are combined to determine
          the what value for `$uCreate' to pass to CreateFile [unless
          overridden by `$rvhvOptions']:

         `"kc"'
               `OPEN_ALWAYS'

         `"ke"'
               `OPEN_EXISTING'

         `"tc"'
               `TRUNCATE_EXISTING'

         `"te"'
               `CREATE_ALWAYS'

         `"nc"'
               `CREATE_NEW'

         `"ne"'
               Illegal.

          `$svShare' controls how the file is shared, that is, whether
          other processes can have read, write, and/or delete access to
          the file while we have it opened.  `$svShare' will usually be a
          string containing zero or more characters from `"rwd"' but can
          also be a numeric bit mask.

          `"r"' sets the `FILE_SHARE_READ' bit which allows other
          processes to have read access to the file.  `"w"' sets the
          `FILE_SHARE_WRITE' bit which allows other processes to have
          write access to the file.  `"d"' sets the `FILE_SHARE_DELETE'
          bit which allows other processes to have delete access to the
          file [ignored under Windows 95].

          The default for `$svShare' is `"rw"' which provides the same
          sharing as using regular perl open().

          If another process currently has read, write, and/or delete
          access to the file and you don't allow that level of sharing,
          then your call to createFile will fail.  If you requested read,
          write, and/or delete access and another process already has the
          file open but doesn't allow that level of sharing, then your
          call to createFile will fail.  Once you have the file open, if
          another process tries to open it with read, write, and/or delete
          access and you don't allow that level of sharing, then that
          process won't be allowed to open the file.

          `$rvhvOptions' is a reference to a hash where any keys must be
          from the list `qw( Access Create Share Attributes Flags Security
          Model )'.  The meaning of the value depends on the key name, as
          described below.  Any option values in `$rvhvOptions' override
          the settings from `$svAccess' and `$svShare' if they conflict.

         Flags => $uFlags
               `$uFlags' is an unsigned value having any of the
               `FILE_FLAG_*' or `FILE_ATTRIBUTE_*' bits set.  Any
               `FILE_ATTRIBUTE_*' bits set via the Attributes option are
               logically ored with these bits.  Defaults to 0.

               If opening the client side of a named pipe, then you can
               also specify `SECURITY_SQOS_PRESENT' along with one of the
               other `SECURITY_*' constants to specify the security
               quality of service to be used.

         Attributes => $sAttributes
               A string of zero or more characters from `"achorst"' [see
               attrLetsToBits for more information] which are converted to
               `FILE_ATTRIBUTE_*' bits to be set in the `$uFlags' argument
               passed to CreateFile.

         Security => $pSecurityAttributes
               `$pSecurityAttributes' should contain a
               `SECURITY_ATTRIBUTES' structure packed into a string or []
               [the default].

         Model => $hModelFile
               `$hModelFile' should contain a handle opened with
               `GENERIC_READ' access to a model file from which file
               attributes and extended attributes are to be copied.  Or
               `$hModelFile' can be 0 [the default].

         Access => $sAccess
         Access => $uAccess
               `$sAccess' should be a string of zero or more characters
               from `"qrw"' specifying the type of access desired:
               "query" or 0, "read" or `GENERIC_READ' [the default], or
               "write" or `GENERIC_WRITE'.

               `$uAccess' should be an unsigned value containing bits set
               to indicate the type of access desired.  `GENERIC_READ' is
               the default.

         Create => $sCreate
         Create => $uCreate
               `$sCreate' should be a string constaing zero or one
               character from `"ktn"' and zero or one character from
               `"ce"'.  These stand for "Keep if exists", "Truncate if
               exists", "New file only", "Create if none", and "Existing
               file only".  These are translated into a `$uCreate' value.

               `$uCreate' should be one of `OPEN_ALWAYS', `OPEN_EXISTING',
               `TRUNCATE_EXISTING', `CREATE_ALWAYS', or `CREATE_NEW'.

         Share => $sShare
         Share => $uShare
               `$sShare' should be a string with zero or more characters
               from `"rwd"' that is translated into a `$uShare' value.
               `"rw"' is the default.

               `$uShare' should be an unsigned value having zero or more
               of the following bits set:  `FILE_SHARE_READ',
               `FILE_SHARE_WRITE', and `FILE_SHARE_DELETE'.
               `FILE_SHARE_READ|FILE_SHARE_WRITE' is the default.

          Examples:

               $hFlop= createFile( "//./A:", "r", "r" )
                 or  die "Can't prevent others from writing to floppy: $^E\n";
               $hDisk= createFile( "//./C:", "rw ke", "" )
                 or  die "Can't get exclusive access to C: $^E\n";
               $hDisk= createFile( $sFilePath, "ke",
                 { Access=>FILE_READ_ATTRIBUTES } )
                 or  die "Can't read attributes of $sFilePath: $^E\n";
               $hTemp= createFile( "$ENV{Temp}/temp.$$", "wn", "",
                 { Attributes=>"hst", Flags=>FILE_FLAG_DELETE_ON_CLOSE() } )
                 or  die "Can't create temporary file, temp.$$: $^E\n";

    getLogicalDrives
    `@roots= getLogicalDrives()'
          Returns the paths to the root directories of all logical drives
          currently defined.  This includes all types of drive lettters,
          such as floppies, CD-ROMs, hard disks, and network shares.  A
          typical return value on a poorly equipped computer would be
          `("A:\\","C:\\")'.

    CloseHandle
    `CloseHandle( $hObject )'
          Closes a Win32 native handle, such as one opened via CreateFile.
          Like most routines, returns a true value if successful and a
          false value [and sets $^E and `regLastError()'] on failure.

    CopyFile
    `CopyFile( $sOldFileName, $sNewFileName, $bFailIfExists )'
          `$sOldFileName' is the path to the file to be copied.
          `$sNewFileName' is the path to where the file should be copied.
          Note that you can E<NOT> just specify a path to a directory in
          `$sNewFileName' to copy the file to that directory using the
          same file name.

          If `$bFailIfExists' is true and `$sNewFileName' is the path to a
          file that already exists, then CopyFile will fail.  If
          `$bFailIfExists' is falsea, then the copy of the `$sOldFileNmae'
          file will overwrite the `$sNewFileName' file if it already
          exists.

          Like most routines, returns a true value if successful and a
          false value [and sets $^E and `regLastError()'] on failure.

    CreateFile
    `$hObject= CreateFile( $sPath, $uAccess, $uShare, $pSecAttr, $uCreate, $uFlags, $hModel )'
          On failure, `$hObject' gets set to a false value and $^E and
          `fileLastError()' are set to the reason for the failure.
          Otherwise, `$hObject' gets set to a Win32 native file handle
          which is always a true value [returns `"0 but true"' in the
          impossible(?) case of the handle having a value of 0].

          `$sPath' is the path to the file [or device, etc.] to be opened.

          `$sPath' can use `"/"' or `"\\"' as path delimiters and can even
          mix the two.  We will usually only use `"/"' in our examples
          since using `"\\"' is usually harder to read.

          Under Windows NT, `$sPath' can start with `"//?/"' to allow the
          use of paths longer than `MAX_PATH' [for UNC paths, replace the
          leading `"//"' with `"//?/UNC/"', as in
          `"//?/UNC/Server/Share/Dir/File.Ext"'].

          `$sPath' can start with `"//./"' to indicate that the rest of the
          path is the name of a "DOS device."  You can use QueryDosDevice
          to list all current DOS devices and can add or delete them with
          DefineDosDevice.  If you get the source-code distribution of this
          module from CPAN, then it includes an example script,
          `ex/ListDevs.plx' that will list all current DOS devices and
          their "native" definition.  Again, note that this doesn't work
          under Win95 nor Win98.

          The most common such DOS devices include:

         `"//./PhysicalDrive0"'
               Your entire first hard disk.  Doesn't work under Windows
               95.  This allows you to read or write raw sectors of your
               hard disk and to use DeviceIoControl to perform
               miscellaneous queries and operations to the hard disk.
               Writing raw sectors and certain other operations can
               seriously damage your files or the function of your
               computer.

               Locking this for exclusive access [by specifying 0 for
               `$uShare'] doesn't prevent access to the partitions on the
               disk nor their file systems.  So other processes can still
               access any raw sectors within a partition and can use the
               file system on the disk as usual.

         `"//./C:"'
               Your `C:' partition.  Doesn't work under Windows 95.  This
               allows you to read or write raw sectors of that partition
               and to use DeviceIoControl to perform miscellaneous queries
               and operations to the partition.  Writing raw sectors and
               certain other operations can seriously damage your files or
               the function of your computer.

               Locking this for exclusive access doesn't prevent access to
               the physical drive that the partition is on so other
               processes can still access the raw sectors that way.
               Locking this for exclusive access E<does> prevent other
               processes from opening the same raw partition and E<does>
               prevent access to the file system on it.  It even prevents
               the current process from accessing the file system on that
               partition.

         `"//./A:"'
               The raw floppy disk.  Doesn't work under Windows 95.  This
               allows you to read or write raw sectors of the floppy disk
               and to use DeviceIoControl to perform miscellaneous queries
               and operations to the floopy disk or drive.

               Locking this for exclusive access prevents all access to
               the floppy.

         `"//./PIPE/PipeName"'
               A named pipe, created via `CreateNamedPipe'.

          `$uAccess' is an unsigned value with bits set indicating the
          type of access desired.  Usually either 0 ["query" access],
          `GENERIC_READ', `GENERIC_WRITE', `GENERIC_READ|GENERIC_WRITE',
          or `GENERIC_ALL'.  More specific types of access can be
          specified, such as `FILE_APPEND_DATA' or `FILE_READ_EA'.

          `$uShare' controls how the file is shared, that is, whether other
          processes can have read, write, and/or delete access to the file
          while we have it opened.  `$uShare' is an unsigned value with
          zero or more of these bits set:  `FILE_SHARE_READ',
          `FILE_SHARE_WRITE', and `FILE_SHARE_DELETE'.

          If another process currently has read, write, and/or delete
          access to the file and you don't allow that level of sharing,
          then your call to CreateFile will fail.  If you requested read,
          write, and/or delete access and another process already has the
          file open but doesn't allow that level of sharing, thenn your
          call to createFile will fail.  Once you have the file open, if
          another process tries to open it with read, write, and/or delete
          access and you don't allow that level of sharing, then that
          process won't be allowed to open the file.

          `$pSecAttr' should either be [] [for NULL] or a
          `SECURITY_ATTRIBUTES' data structure packed into a string.  For
          example, if `$pSecDesc' contains a `SECURITY_DESCRIPTOR'
          structure packed into a string, perhaps via:

               RegGetKeySecurity( $key, 4, $pSecDesc, 1024 );

          then you can set `$pSecAttr' via:

               $pSecAttr= pack( "L P i", 12, $pSecDesc, $bInheritHandle );

          `$uCreate' is one of the following values:  `OPEN_ALWAYS',
          `OPEN_EXISTING', `TRUNCATE_EXISTING', `CREATE_ALWAYS', and
          `CREATE_NEW'.

          `$uFlags' is an unsigned value with zero or more bits set
          indicating attributes to associate with the file
          [`FILE_ATTRIBUTE_*' values] or special options [`FILE_FLAG_*'
          values].

          If opening the client side of a named pipe, then you can also set
          `$uFlags' to include `SECURITY_SQOS_PRESENT' along with one of
          the other `SECURITY_*' constants to specify the security quality
          of service to be used.

          `$hModel' is 0 [or [], both of which mean NULL] or a Win32
          native handle opened with `GENERIC_READ' access to a model file
          from which file attributes and extended attributes are to be
          copied if a new file gets created.

          Examples:

               $hFlop= CreateFile( "//./A:", GENERIC_READ(),
                 FILE_SHARE_READ(), [], OPEN_EXISTING(), 0, [] )
                 or  die "Can't prevent others from writing to floppy: $^E\n";
               $hDisk= createFile( $sFilePath, FILE_READ_ATTRIBUTES(),
                 FILE_SHARE_READ()|FILE_SHARE_WRITE(), [], OPEN_EXISTING(), 0, [] )
                 or  die "Can't read attributes of $sFilePath: $^E\n";
               $hTemp= createFile( "$ENV{Temp}/temp.$$", GENERIC_WRITE(), 0,
                 CREATE_NEW(), FILE_FLAG_DELETE_ON_CLOSE()|attrLetsToBits("hst"), [] )
                 or  die "Can't create temporary file, temp.$$: $^E\n";

    DefineDosDevice
    `DefineDosDevice( $uFlags, $sDosDeviceName, $sTargetPath )'
          Defines a new DOS device, overrides the current definition of a
          DOS device, or deletes a definition of a DOS device.  Like most
          routines, returns a true value if successful and a false value
          [and sets $^E and `regLastError()'] on failure.

          `$sDosDeviceName' is the name of a DOS device for which we'd like
          to add or delete a definition.

          `$uFlags' is an unsigned value with zero or more of the following
          bits set:

         `DDD_RAW_TARGET_PATH'
               Indicates that `$sTargetPath' will be a raw Windows NT
               object name.  This usually means that `$sTargetPath' starts
               with `"\\Device\\"'.  Note that you cannot use `"/"' in
               place of `"\\"' in raw target path names.

         `DDD_REMOVE_DEFINITION'
               Requests that a definition be deleted.  If `$sTargetPath' is
               [] [for NULL], then the most recently added definition for
               `$sDosDeviceName' is removed.  Otherwise the most recently
               added definition matching `$sTargetPath' is removed.

               If the last definition is removed, then the DOS device name
               is also deleted.

         `DDD_EXACT_MATCH_ON_REMOVE'
               When deleting a definition, this bit causes each
               `$sTargetPath' to be compared to the full-length definition
               when searching for the most recently added match.  If this
               bit is not set, then `$sTargetPath' only needs to match a
               prefix of the definition.

          `$sTargetPath' is the DOS device's specific definition that you
          wish to add or delete.  For `DDD_RAW_TARGET_PATH', these usually
          start with `"\\Device\\"'.  If the `DDD_RAW_TARGET_PATH' bit is
          not set, then `$sTargetPath' is just an ordinary path to some
          file or directory, providing the functionality of the *subst*
          command.

    DeleteFile
    `DeleteFile( $sFileName )'
          Deletes the named file.  Compared to Perl's unlink, DeleteFile
          has the advantage of not deleting read-only files.  For E<some>
          versions of Perl, unlink silently calls chmod whether it needs
          to or not before deleting the file so that files that you have
          protected by marking them as read-only are not always protected
          from Perl's unlink.

          Like most routines, returns a true value if successful and a
          false value [and sets $^E and `regLastError()'] on failure.

    DeviceIoControl
    `DeviceIoControl( $hDevice, $uIoControlCode, $pInBuf, $lInBuf, $opOutBuf, $lOutBuf, $olRetBytes, $pOverlapped )'
          Requests a special operation on an I/O [input/output] device,
          such as ejecting a tape or formatting a disk.  Like most
          routines, returns a true value if successful and a false value
          [and sets $^E and `regLastError()'] on failure.

          `$hDevice' is a Win32 native file handle to a device [return
          value from CreateFile].

          `$uIoControlCode' is an unsigned value [a `IOCTL_*' constant]
          indicating the type query or other operation to be performed.

          `$pInBuf' is [] [for NULL] or a data structure packed into a
          string.  The type of data structure depends on the
          `$uIoControlCode' value.  `$lInBuf' is 0 or the length of the
          structure in `$pInBuf'.  If `$pInBuf' is not [] and `$lInBuf' is
          0, then `$lInBuf' will automatically be set to `length($pInBuf)'
          for you.

          `$opOutBuf' is [] [for NULL] or will be set to contain a
          returned data structure packed into a string.  `$lOutBuf'
          indicates how much space to allocate in `$opOutBuf' for
          DeviceIoControl to store the data structure.  If `$lOutBuf' is a
          number and `$opOutBuf' already has a buffer allocated for it
          that is larger than `$lOutBuf' bytes, then this larger buffer
          size will be passed to DeviceIoControl.  However, you can force
          a specific buffer size to be passed to DeviceIoControl by
          prepending a `"="' to the front of `$lOutBuf'.

          `$olRetBytes' is [] or is a scalar to receive the number of bytes
          written to `$opOutBuf'.  Even when `$olRetBytes' is [], a valid
          pointer to a `DWORD' [and not NULL] is passed to DeviceIoControl.
          In this case, [] just means that you don't care about the value
          that might be written to `$olRetBytes', which is usually the case
          since you can usually use `length($opOutBuf)' instead.

          `$pOverlapped' is [] or is a `OVERLAPPED' structure packed into
          a string.  This is only useful if `$hDevice' was opened with the
          `FILE_FLAG_OVERLAPPED' flag set.

    FdGetOsFHandle
    `$hNativeHandle= FdGetOsFHandle( $ivFd )'
          FdGetOsFHandle simply calls `_get_osfhandle()'.  It was renamed
          to better fit in with the rest the function names of this module,
          in particular to distinguish it from GetOsFHandle.  It takes an
          integer file descriptor [as from Perl's fileno] and returns the
          Win32 native file handle associated with that file descriptor or
          `INVALID_HANDLE_VALUE' if `$ivFd' is not an open file descriptor.

          When you call Perl's open to set a Perl file handle [like
          STDOUT], Perl calls C's fopen to set a stdio `FILE *'.  C's
          fopen calls something like Unix's open, that is, Win32's
          `_sopen', to get an integer file descriptor [where 0 is for
          STDIN, 1 for STDOUT, etc.].  Win32's `_sopen' calls CreateFile
          to set a `HANDLE', a Win32 native file handle.  So every Perl
          file handle [like STDOUT] has an integer file descriptor
          associated with it that you can get via fileno.  And, under
          Win32, every file descriptor has a Win32 native file handle
          associated with it.  FdGetOsFHandle lets you get access to that.

          `$hNativeHandle' is set to `INVALID_HANDLE_VALUE' [and
          `lastFileError()' and $^E are set] if FdGetOsFHandle fails.  See
          also GetOsFHandle which provides a friendlier interface.

    fileConstant
    `$value= fileConstant( $sConstantName )'
          Fetch the value of a constant.  Returns undef if `$sConstantName'
          is not the name of a constant supported by this module.  Never
          sets $! nor $^E.

          This function is rarely used since you will usually get the
          value of a constant by having that constant imported into your
          package by listing the constant name in the `use Win32API::File'
          statement and then simply using the constant name in your code
          [perhaps followed by `()'].  This function is useful for
          verifying constant names not in Perl code, for example, after
          prompting a user to type in a constant name.

    fileLastError
    `$svError= fileLastError();'
    `fileLastError( $uError );'
          Returns the last error encountered by a routine from this module.
          It is just like $^E except it isn't changed by anything except
          routines from this module.  Ideally you could just use $^E, but
          current versions of Perl often overwrite $^E before you get a
          chance to check it and really old versions of Perl don't really
          support $^E under Win32.

          Just like $^E, in a numeric context `fileLastError()' returns
          the numeric error value while in a string context it returns a
          text description of the error [actually it returns a Perl scalar
          that contains both values so `$x= fileLastError()' causes $x to
          give different values in string vs. numeric contexts].  On old
          versions of Perl where $^E isn't tied to `GetLastError()',
          fileLastError simply returns the number of the error and you'll
          need to use <Win32::FormatMessage> to get the error string.

          The last form sets the error returned by future calls to
          `fileLastError()' and should not be used often.  `$uError' must
          be a numeric error code.  Also returns the dual-valued version
          of `$uError'.

    GetDriveType
    `$uDriveType= GetDriveType( $sRootPath )'
          Takes a string giving the path to the root directory of a file
          system [called a "drive" because every file system is assigned a
          "drive letter"] and returns an unsigned value indicating the
          type of drive the file system is on.  The return value should be
          one of:

         `DRIVE_UNKNOWN'
               None of the following.

         `DRIVE_NO_ROOT_DIR'
               A "drive" that does not have a file system.  This can be a
               drive letter that hasn't been defined or a drive letter
               assigned to a partition that hasn't been formatted yet.

         `DRIVE_REMOVABLE'
               A floppy diskette drive or other removable media drive, but
               not a CD-ROM drive.

         `DRIVE_FIXED'
               An ordinary hard disk partition.

         `DRIVE_REMOTE'
               A network share.

         `DRIVE_CDROM'
               A CD-ROM drive.

         `DRIVE_RAMDISK'
               A "ram disk" or memory-resident virtual file system used
               for high-speed access to small amounts of temporary file
               space.

    GetFileType
    `$uFileType= GetFileType( $hFile )'
          Takes a Win32 native file handle and returns a `FILE_TYPE_*'
          constant indicating the type of the file opened on that handle:

         `FILE_TYPE_UNKNOWN'
               None of the below.  Often a special device.

         `FILE_TYPE_DISK'
               An ordinary disk file.

         `FILE_TYPE_CHAR'
               What Unix would call a "character special file", that is, a
               device that works on character streams such as a printer
               port or a console.

         `FILE_TYPE_PIPE'
               Either a named or anonymous pipe.

    GetLogicalDrives
    `$uDriveBits= GetLogicalDrives()'
          Returns an unsigned value with one bit set for each drive letter
          currently defined.  If "A:" is currently a valid drive letter,
          then the 1 bit will be set in `$uDriveBits'.  If "B:" is valid,
          then the 2 bit will be set.  If "Z:" is valid, then the `2**26'
          [`0x4000000'] bit will be set.

    GetLogicalDriveStrings
    `$olOutLength= GetLogicalDriveStrings( $lBufSize, $osBuffer )'
          For each currently defined drive letter, a `'\0''-terminated
          string of the path to the root of its file system is
          constructed.  All of these strings are concatenated into a
          single larger string and an extra terminating `'\0'' is added.
          This larger string is returned in `$osBuffer'.  Note that this
          includes drive letters that have been defined but that have no
          file system, such as drive letters assigned to unformatted
          partitions.

          `$lBufSize' is the size of the buffer to allocate to store this
          list of strings.  `26*4+1' is always sufficient and should
          usually be used.

          `$osBuffer' is a scalar to be set to contain the constructed
          string.

          `$olOutLength' is the number of bytes actually written to
          `$osBuffer' but `length($osBuffer)' can also be used to
          determine this.

          For example, on a poorly equipped computer,

               GetLogicalDriveStrings( 4*26+1, $osBuffer );

          might set `$osBuffer' to the 9-character string,
          `"A:\\\0C:\\\0\0"'.

    GetHandleInformation
    `GetHandleInformation( $hObject, $ouFlags )'
          Retrieves the flags associated with a Win32 native file handle
          or object handle.

          `$hObject' is an open Win32 native file handle or an open Win32
          native handle to some other type of object.

          `$ouFlags' will be set to an unsigned value having zero or more
          of the bits HANDLE_FLAG_INHERIT and
          HANDLE_FLAG_PROTECT_FROM_CLOSE set.  See the `":HANDLE_FLAG_"'
          export class for the meanings of these bits.

    GetOsFHandle
    `$hNativeHandle= GetOsFHandle( FILE )'
          Takes a Perl file handle [like STDIN] and returns the Win32
          native file handle associated with it.  See FdGetOsFHandle for
          more information about Win32 native file handles.

          `$hNativeHandle' is set to a false value [and `lastFileError()'
          and $^E are set] if GetOsFHandle fails.    GetOsFHandle returns
          `"0 but true"' in the impossible(?) case of the handle having a
          value of 0.

    GetVolumeInformation
    `GetVolumeInformation( $sRootPath, $osVolName, $lVolName, $ouSerialNum, $ouMaxNameLen, $ouFsFlags, $osFsType, $lFsType )'
          Gets information about a file system volume, returning a true
          value if successful.  On failure, returns a false value and sets
          `fileLastError()' and $^E.

          `$sRootPath' is a string specifying the path to the root of the
          file system, for example, `"C:/"'.

          `$osVolName' is a scalar to be set to the string representing the
          volume name, also called the file system label.  `$lVolName' is
          the number of bytes to allocate for the `$osVolName' buffer [see
          `Buffer Sizes' in this node for more information].

          `$ouSerialNum' is [] [for NULL] or will be set to the numeric
          value of the volume's serial number.

          `$ouMaxNameLen' is [] [for NULL] or will be set to the maximum
          length allowed for a file name or directory name within the file
          system.

          `$osFsType' is a scalar to be set to the string representing the
          file system type, such as `"FAT"' or `"NTFS"'.  `$lFsType' is the
          number of bytes to allocate for the `$osFsType' buffer [see
          `Buffer Sizes' in this node for more information].

          `$ouFsFlags' is [] [for NULL] or will be set to an unsigned
          integer with bits set indicating properties of the file system:

         `FS_CASE_IS_PRESERVED'
               The file system preserves the case of file names [usually
               true].  That is, it doesn't change the case of file names
               such as forcing them to upper- or lower-case.

         `FS_CASE_SENSITIVE'
               The file system supports the ability to not ignore the case
               of file names [but might ignore case the way you are using
               it].  That is, the file system has the ability to force you
               to get the letter case of a file's name exactly right to be
               able to open it.  This is true for "NTFS" file systems,
               even though case in file names is usually still ignored.

         `FS_UNICODE_STORED_ON_DISK'
               The file system preserves Unicode in file names [true for
               "NTFS"].

         `FS_PERSISTENT_ACLS'
               The file system supports setting Access Control Lists on
               files [true for "NTFS"].

         `FS_FILE_COMPRESSION'
               The file system supports compression on a per-file basis
               [true for "NTFS"].

         `FS_VOL_IS_COMPRESSED'
               The entire file system is compressed such as via
               "DoubleSpace".

    IsRecognizedPartition
    `IsRecognizedPartition( $ivPartitionType )'
          Takes a partition type and returns whether that partition type is
          supported under Win32.  `$ivPartitonType' is an integer value as
          from the operating system byte of a hard disk's DOS-compatible
          partition table [that is, a partition table for x86-based Win32,
          not, for example, one used with Windows NT for Alpha
          processors].  For example, the `PartitionType' member of the
          `PARTITION_INFORMATION' structure.

          Common values for `$ivPartitionType' include
          `PARTITION_FAT_12==1', `PARTITION_FAT_16==4',
          `PARTITION_EXTENDED==5', `PARTITION_FAT32==0xB'.

    IsContainerPartition
    `IsContainerPartition( $ivPartitionType )'
          Takes a partition type and returns whether that partition is a
          "container" partition that is supported under Win32, that is,
          whether it is an "extended" partition that can contain "logical"
          partitions.  `$ivPartitonType' is as for IsRecognizedPartition.

    MoveFile
    `MoveFile( $sOldName, $sNewName )'
          Renames a file or directory.  `$sOldName' is the name of the
          existing file or directory that is to be renamed.  `$sNewName'
          is the new name to give the file or directory.  Returns a true
          value if the move succeeds.  For failure, returns a false value
          and sets `fileLastErorr()' and $^E to the reason for the failure.

          Files can be "renamed" between file systems and the file
          contents and some attributes will be moved.  Directories can
          only be renamed within one file system.  If there is already a
          file or directory named `$sNewName', then MoveFile will fail.

    MoveFileEx
    `MoveFileEx( $sOldName, $sNewName, $uFlags )'
          Renames a file or directory.  `$sOldName' is the name of the
          existing file or directory that is to be renamed.  `$sNewName'
          is the new name to give the file or directory.  Returns a true
          value if the move succeeds.  For failure, returns a false value
          and sets `fileLastErorr()' and $^E to the reason for the failure.

          `$uFlags' is an unsigned value with zero or more of the
          following bits set:

         `MOVEFILE_REPLACE_EXISTING'
               If this bit is set and a file [but not a directory] named
               `$sNewName' already exists, then it will be replaced by
               `$sOldName'.  If this bit is not set then MoveFileEx will
               fail rather than replace an existing `$sNewName'.

         `MOVEFILE_COPY_ALLOWED'
               Allows files [but not directories] to be moved between file
               systems by copying the `$sOldName' file data and some
               attributes to `$sNewName' and then deleting `$sOldName'.
               If this bit is not set [or if `$sOldName' denotes a
               directory] and `$sNewName' refers to a different file
               system than `$sOldName', then MoveFileEx will fail.

         `MOVEFILE_DELAY_UNTIL_REBOOT'
               Preliminary verifications are made and then an entry is
               added to the Registry to cause the rename [or delete]
               operation to be done the next time this copy of the
               operating system is booted [right after any automatic file
               system checks have completed].  This is not supported under
               Windows 95.

               When this bit is set, `$sNewName' can be [] [for NULL] to
               indicate that `$sOldName' should be deleted during the next
               boot rather than renamed.

               Setting both the `MOVEFILE_COPY_ALLOWED' and
               `MOVEFILE_DELAY_UNTIL_REBOOT' bits will cause MoveFileEx to
               fail.

         `MOVEFILE_WRITE_THROUGH'
               Ensures that MoveFileEx won't return until the operation has
               finished and been flushed to disk.   This is not supported
               under Windows 95.  Only affects file renames to another
               file system, forcing a buffer flush at the end of the copy
               operation.

    OsFHandleOpen
    `OsFHandleOpen( FILE, $hNativeHandle, $sMode )'
          Opens a Perl file handle based on an already open Win32 native
          file handle [much like C's `fdopen()' does with a file
          descriptor].  Returns a true value if the open operation
          succeeded.  For failure, returns a false value and sets $! [and
          possibly `fileLastError()' and $^E] to the reason for the
          failure.

          FILE is a Perl file handle [in any of the supported forms, a
          bareword, a string, a typeglob, or a reference to a typeglob]
          that will be opened.  If FILE is already open, it will
          automatically be closed before it is reopened.

          `$hNativeHandle' is an open Win32 native file handle, probably
          the return value from CreateFile or createFile.

          `$sMode' is string of zero or more letters from `"rwatb"'.  These
          are translated into a combination `O_RDONLY' [`"r"'], `O_WRONLY'
          [`"w"'], `O_RDWR' [`"rw"'], `O_APPEND' [`"a"'], `O_TEXT'
          [`"t"'], and `O_BINARY' [`"b"'] flags [see the Fcntl,
          module] that is passed to OsFHandleOpenFd.   Currently
          only `O_APPEND' and `O_TEXT' have any significance.

          Also, a `"r"' and/or `"w"' in `$sMode' is used to decide how the
          file descriptor is converted into a Perl file handle, even
          though this doesn't appear to make a difference.  One of the
          following is used:

               open( FILE, "<&=".$ivFd )	# "r" w/o "w"
               open( FILE, ">&=".$ivFd )	# "w" w/o "r"
               open( FILE, "+<&=".$ivFd )	# both "r" and "w"

          OsFHandleOpen eventually calls the Win32-specific C routine
          `_open_osfhandle()' or Perl's "improved" version called
          `win32_open_osfhandle()'.  Prior to Perl5.005, C's
          `_open_osfhandle()' is called which will fail if
          `GetFileType($hNativeHandle)' would return `FILE_TYPE_UNKNOWN'.
          For Perl5.005 and later, OsFHandleOpen calls
          `win32_open_osfhandle()' from the Perl DLL which doesn't have
          this restriction.

    OsFHandleOpenFd
    `$ivFD= OsFHandleOpenFd( $hNativeHandle, $uMode )'
          Opens a file descriptor [`$ivFD'] based on an already open Win32
          native file handle, `$hNativeHandle'.  This just calls the
          Win32-specific C routine `_open_osfhandle()' or Perl's "improved"
          version called `win32_open_osfhandle()'.  Prior to Perl5.005, C's
          `_open_osfhandle()' is called which will fail if
          `GetFileType($hNativeHandle)' would return `FILE_TYPE_UNKNOWN'.
          For Perl5.005 and later, OsFHandleOpenFd calls
          `win32_open_osfhandle()' from the Perl DLL which doesn't have
          this restriction.

          `$uMode' the logical combination of zero or more `O_*' constants
          exported by the Fcntl module.  Currently only `O_APPEND' and
          `O_TEXT' have any significance.

          `$ivFD' will be non-negative if the open operation was
          successful.  For failure, `-1' is returned and $! [and possibly
          `fileLastError()' and $^E] is set to the reason for the failure.

    QueryDosDevice
    `$olTargetLen= QueryDosDevice( $sDosDeviceName, $osTargetPath, $lTargetBuf )'
          Looks up the definition of a given "DOS" device name, yielding
          the active Windows NT native device name along with any
          currently dormant definitions.

          `$sDosDeviceName' is the name of the "DOS" device whose
          definitions we want.  For example, `"C:"', `"COM1"', or
          `"PhysicalDrive0"'.  If `$sDosDeviceName' is [] [for NULL], the
          list of all DOS device names is returned instead.

          `$osTargetPath' will be assigned a string containing the list of
          definitions.  The definitions are each `'\0''-terminate and are
          concatenated into the string, most recent first, with an extra
          `'\0'' at the end of the whole string [see
          GetLogicalDriveStrings for a sample of this format].

          `$lTargetBuf' is the size [in bytes] of the buffer to allocate
          for `$osTargetPath'.  See `Buffers Sizes' in this node for more
          information.

          `$olTargetLen' is set to the number of bytes written to
          `$osTargetPath' but you can also use `length($osTargetPath)' to
          determine this.

          For failure, 0 is returned and `fileLastError()' and $^E are set
          to the reason for the failure.

    ReadFile
    `ReadFile( $hFile, $opBuffer, $lBytes, $olBytesRead, $pOverlapped )'
          Reads bytes from a file or file-like device.  Returns a true
          value if the read operation was successful.  For failure,
          returns a false value and sets `fileLastError()' and $^E for the
          reason for the failure.

          `$hFile' is a Win32 native file handle that is already open to
          the file or device to read from.

          `$opBuffer' will be set to a string containing the bytes read.

          `$lBytes' is the number of bytes you would like to read.
          `$opBuffer' is automatically initialized to have a buffer large
          enough to hold that many bytes.  Unlike other buffer sizes,
          `$lBytes' does not need to have a `"="' prepended to it to
          prevent a larger value to be passed to the underlying Win32
          ReadFile API.  However, a leading `"="' will be silently
          ignored, even if Perl warnings are enabled.

          If `$olBytesRead' is not [], it will be set to the actual number
          of bytes read, though `length($opBuffer)' can also be used to
          determine this.

          `$pOverlapped' is [] or is a `OVERLAPPED' structure packed into
          a string.  This is only useful if `$hFile' was opened with the
          `FILE_FLAG_OVERLAPPED' flag set.

    SetErrorMode
    `$uOldMode= SetErrorMode( $uNewMode )'
          Sets the mode controlling system error handling E<and> returns
          the previous mode value.  Both `$uOldMode' and `$uNewMode' will
          have zero or more of the following bits set:

         `SEM_FAILCRITICALERRORS'
               If set, indicates that when a critical error is
               encountered, the call that triggered the error fails
               immediately.  Normally this bit is not set, which means
               that a critical error causes a dialogue box to appear
               notifying the desktop user that some application has
               triggered a critical error.   The dialogue box allows the
               desktop user to decide whether the critical error is
               returned to the process, is ignored, or the offending
               operation is retried.

               This affects the CreateFile and GetVolumeInformation calls.

               Setting this bit is useful for allowing you to check
               whether a floppy diskette is in the floppy drive.

         `SEM_NOALIGNMENTFAULTEXCEPT'
               If set, this causes memory access misalignment faults to be
               automatically fixed in a manner invisible to the process.
               This flag is ignored on x86-based versions of Windows NT.
               This flag is not supported on Windows 95.

         `SEM_NOGPFAULTERRORBOX'
               If set, general protection faults do not generate a
               dialogue box but can instead be handled by the process via
               an exception handler.  This bit should not be set by
               programs that don't know how to handle such faults.

         `SEM_NOOPENFILEERRORBOX'
               If set, then when an attempt to continue reading from or
               writing to an already open file [usually on a removable
               medium like a floppy diskette] finds the file no longer
               available, the call will immediately fail.  Normally this
               bit is not set, which means that instead a dialogue box
               will appear notifying the desktop user that some
               application has run into this problem.   The dialogue box
               allows the desktop user to decide whether the failure is
               returned to the process, is ignored, or the offending
               operation is retried.

               This affects the ReadFile and WriteFile calls.

    SetFilePointer
    `$uNewPos= SetFilePointer( $hFile, $ivOffset, $ioivOffsetHigh, $uFromWhere )'
          The native Win32 version of `seek()'.  SetFilePointer sets the
          position within a file where the next read or write operation
          will start from.

          `$hFile' is a Win32 native file handle.

          `$uFromWhere' is either `FILE_BEGIN', `FILE_CURRENT', or
          `FILE_END', indicating that the new file position is being
          specified relative to the beginning of the file, the current
          file pointer, or the end of the file, respectively.

          `$ivOffset' is [if `$ioivOffsetHigh' is []] the offset [in bytes]
          to the new file position from the position specified via
          `$uFromWhere'.  If `$ioivOffsetHigh' is not [], then `$ivOffset'
          is converted to an unsigned value to be used as the low-order 4
          bytes of the offset.

          `$ioivOffsetHigh' can be [] [for NULL] to indicate that you are
          only specifying a 4-byte offset and the resulting file position
          will be 0xFFFFFFFE or less [just under 4GB].  Otherwise
          `$ioivOfffsetHigh' starts out with the high-order 4 bytes
          [signed] of the offset and gets set to the [unsigned] high-order
          4 bytes of the resulting file position.

          The underlying SetFilePointer returns `0xFFFFFFFF' to indicate
          failure, but if `$ioivOffsetHigh' is not [], you would also have
          to check $^E to determine whether `0xFFFFFFFF' indicates an error
          or not.  `Win32API::File::SetFilePointer' does this checking for
          you and returns a false value if and only if the underlying
          SetFilePointer failed.  For this reason, `$uNewPos' is set to
          `"0 but true"' if you set the file pointer to the beginning of
          the file [or any position with 0 for the low-order 4 bytes].

          So the return value will be true if the seek operation was
          successful.  For failure, a false value is returned and
          `fileLastError()' and $^E are set to the reason for the failure.

    SetHandleInformation
    `SetHandleInformation( $hObject, $uMask, $uFlags )'
          Sets the flags associated with a Win32 native file handle or
          object handle.  Returns a true value if the operation was
          successful.  For failure, returns a false value and sets
          `fileLastError()' and $^E for the reason for the failure.

          `$hObject' is an open Win32 native file handle or an open Win32
          native handle to some other type of object.

          `$uMask' is an unsigned value having one or more of the bits
          HANDLE_FLAG_INHERIT and HANDLE_FLAG_PROTECT_FROM_CLOSE set.
          Only bits set in `$uMask' will be modified by
          SetHandleInformation.

          `$uFlags' is an unsigned value having zero or more of the bits
          HANDLE_FLAG_INHERIT and HANDLE_FLAG_PROTECT_FROM_CLOSE set.  For
          each bit set in `$uMask', the cooresponding bit in the handle's
          flags is set to the value of the cooresponding bit in `$uFlags'.

          If `$uOldFlags' were the value of the handle's flags before the
          call to SetHandleInformation, then the value of the handle's
          flags afterward would be:

               ( $uOldFlags & ~$uMask ) | ( $uFlags & $uMask )

          [at least as far as the HANDLE_FLAG_INHERIT and
          HANDLE_FLAG_PROTECT_FROM_CLOSE bits are concerned.]

          See the `":HANDLE_FLAG_"' export class for the meanings of these
          bits.

    WriteFile
    `WriteFile( $hFile, $pBuffer, $lBytes, $ouBytesWritten, $pOverlapped )'
          Write bytes to a file or file-like device.  Returns a true value
          if the operation was successful.  For failure, returns a false
          value and sets `fileLastError()' and $^E for the reason for the
          failure.

          `$hFile' is a Win32 native file handle that is already open to
          the file or device to be written to.

          `$pBuffer' is a string containing the bytes to be written.

          `$lBytes' is the number of bytes you would like to write.  If
          `$pBuffer' is not at least `$lBytes' long, WriteFile croaks.  You
          can specify 0 for `$lBytes' to write `length($pBuffer)' bytes.
          A leading `"="' on `$lBytes' will be silently ignored, even if
          Perl warnings are enabled.

          `$ouBytesWritten' will be set to the actual number of bytes
          written unless you specify it as [].

          `$pOverlapped' is [] or is an `OVERLAPPED' structure packed into
          a string.  This is only useful if `$hFile' was opened with the
          `FILE_FLAG_OVERLAPPED' flag set.

`":FuncA"'
     The ASCII-specific functions.  Each of these is just the same as the
     version without the trailing "A".

          CopyFileA
          CreateFileA
          DefineDosDeviceA
          DeleteFileA
          GetDriveTypeA
          GetLogicalDriveStringsA
          GetVolumeInformationA
          MoveFileA
          MoveFileExA
          QueryDosDeviceA

`":FuncW"'
     The wide-character-specific (Unicode) functions.  Each of these is
     just the same as the version without the trailing "W" except that
     strings are expected in Unicode and some lengths are measured as
     number of `WCHAR's instead of number of bytes, as indicated below.

    CopyFileW
    `CopyFileW( $swOldFileName, $swNewFileName, $bFailIfExists )'
          `$swOldFileName' and `$swNewFileName' are Unicode strings.

    CreateFileW
    `$hObject= CreateFileW( $swPath, $uAccess, $uShare, $pSecAttr, $uCreate, $uFlags, $hModel )'
          `$swPath' is Unicode.

    DefineDosDeviceW
    `DefineDosDeviceW( $uFlags, $swDosDeviceName, $swTargetPath )'
          `$swDosDeviceName' and `$swTargetPath' are Unicode.

    DeleteFileW
    `DeleteFileW( $swFileName )'
          `$swFileName' is Unicode.

    GetDriveTypeW
    `$uDriveType= GetDriveTypeW( $swRootPath )'
          `$swRootPath' is Unicode.

    GetLogicalDriveStringsW
    `$olwOutLength= GetLogicalDriveStringsW( $lwBufSize, $oswBuffer )'
          Unicode is stored in `$oswBuffer'.  `$lwBufSize' and
          `$olwOutLength' are measured as number of `WCHAR's.

    GetVolumeInformationW
    `GetVolumeInformationW( $swRootPath, $oswVolName, $lwVolName, $ouSerialNum, $ouMaxNameLen, $ouFsFlags, $oswFsType, $lwFsType )'
          `$swRootPath' is Unicode and Unicode is written to `$oswVolName'
          and `$oswFsType'.  `$lwVolName' and `$lwFsType' are measures as
          number of `WCHAR's.

    MoveFileW
    `MoveFileW( $swOldName, $swNewName )'
          `$swOldName' and `$swNewName' are Unicode.

    MoveFileExW
    `MoveFileExW( $swOldName, $swNewName, $uFlags )'
          `$swOldName' and `$swNewName' are Unicode.

    QueryDosDeviceW
    `$olwTargetLen= QueryDosDeviceW( $swDeviceName, $oswTargetPath, $lwTargetBuf )'
          `$swDeviceName' is Unicode and Unicode is written to
          `$oswTargetPath'.  `$lwTargetBuf' and `$olwTargetLen' are
          measured as number of  `WCHAR's.

`":Misc"'
     Miscellaneous constants.  Used for the `$uCreate' argument of
     CreateFile or the `$uFromWhere' argument of SetFilePointer.  Plus
     `INVALID_HANDLE_VALUE', which you usually won't need to check for
     since most routines translate it into a false value.

          CREATE_ALWAYS		CREATE_NEW		OPEN_ALWAYS
          OPEN_EXISTING		TRUNCATE_EXISTING	INVALID_HANDLE_VALUE
          FILE_BEGIN		FILE_CURRENT		FILE_END

`":DDD_"'
     Constants for the `$uFlags' argument of DefineDosDevice.

          DDD_EXACT_MATCH_ON_REMOVE
          DDD_RAW_TARGET_PATH
          DDD_REMOVE_DEFINITION

`":DRIVE_"'
     Constants returned by GetDriveType.

          DRIVE_UNKNOWN		DRIVE_NO_ROOT_DIR	DRIVE_REMOVABLE
          DRIVE_FIXED		DRIVE_REMOTE		DRIVE_CDROM
          DRIVE_RAMDISK

`":FILE_"'
     Specific types of access to files that can be requested via the
     `$uAccess' argument to CreateFile.

          FILE_READ_DATA			FILE_LIST_DIRECTORY
          FILE_WRITE_DATA			FILE_ADD_FILE
          FILE_APPEND_DATA		FILE_ADD_SUBDIRECTORY
          FILE_CREATE_PIPE_INSTANCE	FILE_READ_EA
          FILE_WRITE_EA			FILE_EXECUTE
          FILE_TRAVERSE			FILE_DELETE_CHILD
          FILE_READ_ATTRIBUTES		FILE_WRITE_ATTRIBUTES
          FILE_ALL_ACCESS			FILE_GENERIC_READ
          FILE_GENERIC_WRITE		FILE_GENERIC_EXECUTE )],

`":FILE_ATTRIBUTE_"'
     File attribute constants.  Returned by attrLetsToBits and used in the
     `$uFlags' argument to CreateFile.

          FILE_ATTRIBUTE_ARCHIVE		FILE_ATTRIBUTE_COMPRESSED
          FILE_ATTRIBUTE_HIDDEN		FILE_ATTRIBUTE_NORMAL
          FILE_ATTRIBUTE_OFFLINE		FILE_ATTRIBUTE_READONLY
          FILE_ATTRIBUTE_SYSTEM		FILE_ATTRIBUTE_TEMPORARY

`":FILE_FLAG_"'
     File option flag constants.  Used in the `$uFlags' argument to
     CreateFile.

          FILE_FLAG_BACKUP_SEMANTICS	FILE_FLAG_DELETE_ON_CLOSE
          FILE_FLAG_NO_BUFFERING		FILE_FLAG_OVERLAPPED
          FILE_FLAG_POSIX_SEMANTICS	FILE_FLAG_RANDOM_ACCESS
          FILE_FLAG_SEQUENTIAL_SCAN	FILE_FLAG_WRITE_THROUGH

`":FILE_SHARE_"'
     File sharing constants.  Used in the `$uShare' argument to CreateFile.

          FILE_SHARE_DELETE	FILE_SHARE_READ		FILE_SHARE_WRITE

`":FILE_TYPE_"'
     File type constants.  Returned by GetFileType.

          FILE_TYPE_CHAR		FILE_TYPE_DISK
          FILE_TYPE_PIPE		FILE_TYPE_UNKNOWN

`":FS_"'
     File system characteristics constants.  Placed in the `$ouFsFlags'
     argument to GetVolumeInformation.

          FS_CASE_IS_PRESERVED		FS_CASE_SENSITIVE
          FS_UNICODE_STORED_ON_DISK	FS_PERSISTENT_ACLS
          FS_FILE_COMPRESSION		FS_VOL_IS_COMPRESSED

`":HANDLE_FLAG_"'
     Flag bits modifying the behavior of an object handle and accessed via
     GetHandleInformation and SetHandleInformation.

    HANDLE_FLAG_INHERIT
          If this bit is set, then children of this process who inherit
          handles [that is, processes created by calls to the Win32
          `CreateProcess' API with the `bInheritHandles' parameter
          specified as TRUE], will inherit this particular object handle.

    HANDLE_FLAG_PROTECT_FROM_CLOSE
          If this bit is set, then calls to CloseHandle against this handle
          will be ignored, leaving the handle open and usable.

`":IOCTL_STORAGE_"'
     I/O control operations for generic storage devices.  Used in the
     `$uIoControlCode' argument to DeviceIoControl.  Includes
     `IOCTL_STORAGE_CHECK_VERIFY', `IOCTL_STORAGE_MEDIA_REMOVAL',
     `IOCTL_STORAGE_EJECT_MEDIA', `IOCTL_STORAGE_LOAD_MEDIA',
     `IOCTL_STORAGE_RESERVE', `IOCTL_STORAGE_RELEASE',
     `IOCTL_STORAGE_FIND_NEW_DEVICES', and `IOCTL_STORAGE_GET_MEDIA_TYPES'.

    `IOCTL_STORAGE_CHECK_VERIFY'
          Verify that a device's media is accessible.  `$pInBuf' and
          `$opOutBuf' should both be [].  If DeviceIoControl returns a
          true value, then the media is currently accessible.

    `IOCTL_STORAGE_MEDIA_REMOVAL'
          Allows the device's media to be locked or unlocked.  `$opOutBuf'
          should be [].  `$pInBuf' should be a `PREVENT_MEDIA_REMOVAL'
          data structure, which is simply an interger containing a boolean
          value:

               $pInBuf= pack( "i", $bPreventMediaRemoval );

    `IOCTL_STORAGE_EJECT_MEDIA'
          Requests that the device eject the media.  `$pInBuf' and
          `$opOutBuf' should both be [].

    `IOCTL_STORAGE_LOAD_MEDIA'
          Requests that the device load the media.  `$pInBuf' and
          `$opOutBuf' should both be [].

    `IOCTL_STORAGE_RESERVE'
          Requests that the device be reserved.  `$pInBuf' and `$opOutBuf'
          should both be [].

    `IOCTL_STORAGE_RELEASE'
          Releases a previous device reservation.  `$pInBuf' and
          `$opOutBuf' should both be [].

    `IOCTL_STORAGE_FIND_NEW_DEVICES'
          No documentation on this IOCTL operation was found.

    `IOCTL_STORAGE_GET_MEDIA_TYPES'
          Requests information about the type of media supported by the
          device.  `$pInBuf' should be [].  `$opOutBuf' will be set to
          contain a vector of `DISK_GEOMETRY' data structures, which can
          be decoded via:

               # Calculate the number of DISK_GEOMETRY structures returned:
               my $cStructs= length($opOutBuf)/(4+4+4+4+4+4);
               my @fields= unpack( "L l I L L L" x $cStructs, $opOutBuf )
               my( @ucCylsLow, @ivcCylsHigh, @uMediaType, @uTracksPerCyl,
                 @uSectsPerTrack, @uBytesPerSect )= ();
               while(  @fields  ) {
               	push( @ucCylsLow, unshift @fields );
               	push( @ivcCylsHigh, unshift @fields );
               	push( @uMediaType, unshift @fields );
               	push( @uTracksPerCyl, unshift @fields );
               	push( @uSectsPerTrack, unshift @fields );
               	push( @uBytesPerSect, unshift @fields );
               }

          For the $ith type of supported media, the following variables
          will contain the following data.

         `$ucCylsLow[$i]'
               The low-order 4 bytes of the total number of cylinders.

         `$ivcCylsHigh[$i]'
               The high-order 4 bytes of the total number of cylinders.

         `$uMediaType[$i]'
               A code for the type of media.  See the `":MEDIA_TYPE"'
               export class.

         `$uTracksPerCyl[$i]'
               The number of tracks in each cylinder.

         `$uSectsPerTrack[$i]'
               The number of sectors in each track.

         `$uBytesPerSect[$i]'
               The number of bytes in each sector.

`":IOCTL_DISK_"'
     I/O control operations for disk devices.  Used in the
     `$uIoControlCode' argument to DeviceIoControl.  Most of these are to
     be used on physical drive devices like `"//./PhysicalDrive0"'.
     However, `IOCTL_DISK_GET_PARTITION_INFO' and
     `IOCTL_DISK_SET_PARTITION_INFO' should only be used on a
     single-partition device like `"//./C:"'.  Also,
     `IOCTL_DISK_GET_MEDIA_TYPES' is documented as having been superceded
     but is still useful when used on a floppy device like `"//./A:"'.

     Includes `IOCTL_DISK_FORMAT_TRACKS', `IOCTL_DISK_FORMAT_TRACKS_EX',
     `IOCTL_DISK_GET_DRIVE_GEOMETRY', `IOCTL_DISK_GET_DRIVE_LAYOUT',
     `IOCTL_DISK_GET_MEDIA_TYPES', `IOCTL_DISK_GET_PARTITION_INFO',
     `IOCTL_DISK_HISTOGRAM_DATA', `IOCTL_DISK_HISTOGRAM_RESET',
     `IOCTL_DISK_HISTOGRAM_STRUCTURE', `IOCTL_DISK_IS_WRITABLE',
     `IOCTL_DISK_LOGGING', `IOCTL_DISK_PERFORMANCE',
     `IOCTL_DISK_REASSIGN_BLOCKS', `IOCTL_DISK_REQUEST_DATA',
     `IOCTL_DISK_REQUEST_STRUCTURE', `IOCTL_DISK_SET_DRIVE_LAYOUT',
     `IOCTL_DISK_SET_PARTITION_INFO', and `IOCTL_DISK_VERIFY'.

    `IOCTL_DISK_GET_DRIVE_GEOMETRY'
          Request information about the size and geometry of the disk.
          `$pInBuf' should be [].  `$opOutBuf' will be set to a
          `DISK_GEOMETRY' data structure which can be decode via:

               ( $ucCylsLow, $ivcCylsHigh, $uMediaType, $uTracksPerCyl,
                 $uSectsPerTrack, $uBytesPerSect )= unpack( "L l I L L L", $opOutBuf );

         `$ucCylsLow'
               The low-order 4 bytes of the total number of cylinders.

         `$ivcCylsHigh'
               The high-order 4 bytes of the total number of cylinders.

         `$uMediaType'
               A code for the type of media.  See the `":MEDIA_TYPE"'
               export class.

         `$uTracksPerCyl'
               The number of tracks in each cylinder.

         `$uSectsPerTrack'
               The number of sectors in each track.

         `$uBytesPerSect'
               The number of bytes in each sector.

    `IOCTL_DISK_GET_PARTITION_INFO'
          Request information about the size and geometry of the partition.
          `$pInBuf' should be [].  `$opOutBuf' will be set to a
          `PARTITION_INFORMATION' data structure which can be decode via:

               ( $uStartLow, $ivStartHigh, $ucHiddenSects, $uPartitionSeqNumber,
                 $uPartitionType, $bActive, $bRecognized, $bToRewrite )=
                 unpack( "L l L L C c c c", $opOutBuf );

         `$uStartLow' and `$ivStartHigh'
               The low-order and high-order [respectively] 4 bytes of the
               starting offset of the partition, measured in bytes.

         `$ucHiddenSects'
               The number of "hidden" sectors for this partition.
               Actually this is the number of sectors found prior to this
               partiton, that is, the starting offset [as found in
               `$uStartLow' and `$ivStartHigh'] divided by the number of
               bytes per sector.

         `$uPartitionSeqNumber'
               The sequence number of this partition.  Partitions are
               numbered starting as 1 [with "partition 0" meaning the
               entire disk].  Sometimes this field may be 0 and you'll
               have to infer the partition sequence number from how many
               partitions preceed it on the disk.

         `$uPartitionType'
               The type of partition.  See the `":PARTITION_"' export
               class for a list of known types.  See also
               IsRecognizedPartition and IsContainerPartition.

         `$bActive'
               1 for the active [boot] partition, 0 otherwise.

         `$bRecognized'
               Whether this type of partition is support under Win32.

         `$bToRewrite'
               Whether to update this partition information.  This field
               is not used by `IOCTL_DISK_GET_PARTITION_INFO'.  For
               `IOCTL_DISK_SET_DRIVE_LAYOUT', you must set this field to a
               true value for any partitions you wish to have changed,
               added, or deleted.

    `IOCTL_DISK_SET_PARTITION_INFO'
          Change the type of the partition.  `$opOutBuf' should be [].
          `$pInBuf' should be a `SET_PARTITION_INFORMATION' data structure
          which is just a single byte containing the new parition type [see
          the `":PARTITION_"' export class for a list of known types]:

               $pInBuf= pack( "C", $uPartitionType );

    `IOCTL_DISK_GET_DRIVE_LAYOUT'
          Request information about the disk layout.  `$pInBuf' should be
          [].  `$opOutBuf' will be set to contain
          `DRIVE_LAYOUT_INFORMATION' structure including several
          `PARTITION_INFORMATION' structures:

               my( $cPartitions, $uDiskSignature )= unpack( "L L", $opOutBuf );
               my @fields= unpack( "x8" . ( "L l L L C c c c" x $cPartitions ),
               		        $opOutBuf );
               my( @uStartLow, @ivStartHigh, @ucHiddenSects,
                 @uPartitionSeqNumber, @uPartitionType, @bActive,
                 @bRecognized, @bToRewrite )= ();
               for(  1..$cPartition  ) {
               	push( @uStartLow, unshift @fields );
               	push( @ivStartHigh, unshift @fields );
               	push( @ucHiddenSects, unshift @fields );
               	push( @uPartitionSeqNumber, unshift @fields );
               	push( @uPartitionType, unshift @fields );
               	push( @bActive, unshift @fields );
               	push( @bRecognized, unshift @fields );
               	push( @bToRewrite, unshift @fields );
               }

         `$cPartitions'
               If the number of partitions on the disk.

         `$uDiskSignature'
               Is the disk signature, a unique number assigned by Disk
               Administrator [`WinDisk.exe'] and used to identify the
               disk.  This allows drive letters for partitions on that
               disk to remain constant even if the SCSI Target ID of the
               disk gets changed.

          See `IOCTL_DISK_GET_PARTITION_INFORMATION' for information on the
          remaining these fields.

    `IOCTL_DISK_GET_MEDIA_TYPES'
          Is supposed to be superseded by `IOCTL_STORAGE_GET_MEDIA_TYPES'
          but is still useful for determining the types of floppy diskette
          formats that can be produced by a given floppy drive.  See
          `ex/FormatFloppy.plx' for an example.

    `IOCTL_DISK_SET_DRIVE_LAYOUT'
          Change the partition layout of the disk.  `$pOutBuf' should be
          [].  `$pInBuf' should be a `DISK_LAYOUT_INFORMATION' data
          structure including several `PARTITION_INFORMATION' data
          structures.

               # Already set:  $cPartitions, $uDiskSignature, @uStartLow, @ivStartHigh,
               #   @ucHiddenSects, @uPartitionSeqNumber, @uPartitionType, @bActive,
               #   @bRecognized, and @bToRewrite.
               my( @fields, $prtn )= ();
               for $prtn (  1..$cPartition  ) {
               	push( @fields, $uStartLow[$prtn-1], $ivStartHigh[$prtn-1],
               	    $ucHiddenSects[$prtn-1], $uPartitionSeqNumber[$prtn-1],
               	    $uPartitionType[$prtn-1], $bActive[$prtn-1],
               	    $bRecognized[$prtn-1], $bToRewrite[$prtn-1] );
               }
               $pInBuf= pack( "L L" . ( "L l L L C c c c" x $cPartitions ),
               		   $cPartitions, $uDiskSignature, @fields );

          To delete a partition, zero out all fields except for
          `$bToRewrite' which should be set to 1.  To add a partition,
          increment `$cPartitions' and add the information for the new
          partition into the arrays, making sure that you insert 1 into
          @bToRewrite.

          See `IOCTL_DISK_GET_DRIVE_LAYOUT' and
          `IOCTL_DISK_GET_PARITITON_INFORMATION' for descriptions of the
          fields.

    `IOCTL_DISK_VERIFY'
          Performs a logical format of [part of] the disk.  `$opOutBuf'
          should be [].  `$pInBuf' should contain a `VERIFY_INFORMATION'
          data structure:

               $pInBuf= pack( "L l L",
               		   $uStartOffsetLow, $ivStartOffsetHigh, $uLength );

         `$uStartOffsetLow' and `$ivStartOffsetHigh'
               The low-order and high-order [respectively] 4 bytes of the
               offset [in bytes] where the formatting should begin.

         `$uLength'          The length [in bytes] of the section to be formatted.
    `IOCTL_DISK_FORMAT_TRACKS'
          Format a range of tracks on the disk.  `$opOutBuf' should be [].
          `$pInBuf' should contain a `FORMAT_PARAMETERS' data structure:

               $pInBuf= pack( "L L L L L", $uMediaType,
               		   $uStartCyl, $uEndCyl, $uStartHead, $uEndHead );

          `$uMediaType' if the type of media to be formatted.  Mostly used
          to specify the density to use when formatting a floppy diskette.
          See the `":MEDIA_TYPE"' export class for more information.

          The remaining fields specify the starting and ending cylinder and
          head of the range of tracks to be formatted.

    `IOCTL_DISK_REASSIGN_BLOCKS'
          Reassign a list of disk blocks to the disk's spare-block pool.
          `$opOutBuf' should be [].  `$pInBuf' should be a
          `REASSIGN_BLOCKS' data structure:

               $pInBuf= pack( "S S L*", 0, $cBlocks, @uBlockNumbers );

    `IOCTL_DISK_PERFORMANCE'
          Request information about disk performance.  `$pInBuf' should be
          [].  `$opOutBuf' will be set to contain a `DISK_PERFORMANCE'
          data structure:

               my( $ucBytesReadLow, $ivcBytesReadHigh,
               	$ucBytesWrittenLow, $ivcBytesWrittenHigh,
               	$uReadTimeLow, $ivReadTimeHigh,
               	$uWriteTimeLow, $ivWriteTimeHigh,
               	$ucReads, $ucWrites, $uQueueDepth )=
               	unpack( "L l L l L l L l L L L", $opOutBuf );

    `IOCTL_DISK_IS_WRITABLE'
          No documentation on this IOCTL operation was found.

    `IOCTL_DISK_LOGGING'
          Control disk logging.  Little documentation for this IOCTL
          operation was found.  It makes use of a `DISK_LOGGING' data
          structure:

         DISK_LOGGING_START
               Start logging each disk request in a buffer internal to the
               disk device driver of size `$uLogBufferSize':

                    $pInBuf= pack( "C L L", 0, 0, $uLogBufferSize );

         DISK_LOGGING_STOP
               Stop loggin each disk request:

                    $pInBuf= pack( "C L L", 1, 0, 0 );

         DISK_LOGGING_DUMP
               Copy the interal log into the supplied buffer:

                    $pLogBuffer= ' ' x $uLogBufferSize
                    $pInBuf= pack( "C P L", 2, $pLogBuffer, $uLogBufferSize );

                    ( $uByteOffsetLow[$i], $ivByteOffsetHigh[$i],
                      $uStartTimeLow[$i], $ivStartTimeHigh[$i],
                      $uEndTimeLog[$i], $ivEndTimeHigh[$i],
                      $hVirtualAddress[$i], $ucBytes[$i],
                      $uDeviceNumber[$i], $bWasReading[$i] )=
                      unpack( "x".(8+8+8+4+4+1+1+2)." L l L l L l L L C c x2", $pLogBuffer );

         DISK_LOGGING_BINNING
               Keep statics grouped into bins based on request sizes.

                    $pInBuf= pack( "C P L", 3, $pUnknown, $uUnknownSize );

    `IOCTL_DISK_FORMAT_TRACKS_EX'
          No documentation on this IOCTL is included.

    `IOCTL_DISK_HISTOGRAM_STRUCTURE'
          No documentation on this IOCTL is included.

    `IOCTL_DISK_HISTOGRAM_DATA'
          No documentation on this IOCTL is included.

    `IOCTL_DISK_HISTOGRAM_RESET'
          No documentation on this IOCTL is included.

    `IOCTL_DISK_REQUEST_STRUCTURE'
          No documentation on this IOCTL operation was found.

    `IOCTL_DISK_REQUEST_DATA'
          No documentation on this IOCTL operation was found.

`":GENERIC_"'
     Constants specifying generic access permissions that are not specific
     to one type of object.

          GENERIC_ALL			GENERIC_EXECUTE
          GENERIC_READ			GENERIC_WRITE

`":MEDIA_TYPE"'
     Different classes of media that a device can support.  Used in the
     `$uMediaType' field of a `DISK_GEOMETRY' structure.

    Unknown
          Format is unknown.

    `F5_1Pt2_512'
          5.25" floppy, 1.2MB [really 1,200KB] total space, 512
          bytes/sector.

    `F3_1Pt44_512'
          3.5" floppy, 1.44MB [really 1,440KB] total space, 512
          bytes/sector.

    `F3_2Pt88_512'
          3.5" floppy, 2.88MB [really 2,880KB] total space, 512
          bytes/sector.

    `F3_20Pt8_512'
          3.5" floppy, 20.8MB total space, 512 bytes/sector.

    `F3_720_512'
          3.5" floppy, 720KB total space, 512 bytes/sector.

    `F5_360_512'
          5.25" floppy, 360KB total space, 512 bytes/sector.

    `F5_320_512'
          5.25" floppy, 320KB total space, 512 bytes/sector.

    `F5_320_1024'
          5.25" floppy, 320KB total space, 1024 bytes/sector.

    `F5_180_512'
          5.25" floppy, 180KB total space, 512 bytes/sector.

    `F5_160_512'
          5.25" floppy, 160KB total space, 512 bytes/sector.

    `RemovableMedia'
          Some type of removable media other than a floppy diskette.

    `FixedMedia'
          A fixed hard disk.

    `F3_120M_512'
          3.5" floppy, 120MB total space.

`":MOVEFILE_"'
     Constants for use in `$uFlags' arguments to MoveFileEx.

          MOVEFILE_COPY_ALLOWED		MOVEFILE_DELAY_UNTIL_REBOOT
          MOVEFILE_REPLACE_EXISTING	MOVEFILE_WRITE_THROUGH

`":SECURITY_"'
     Security quality of service values that can be used in the `$uFlags'
     argument to CreateFile if opening the client side of a named pipe.

          SECURITY_ANONYMOUS		SECURITY_CONTEXT_TRACKING
          SECURITY_DELEGATION		SECURITY_EFFECTIVE_ONLY
          SECURITY_IDENTIFICATION		SECURITY_IMPERSONATION
          SECURITY_SQOS_PRESENT

`":SEM_"'
     Constants to be used with SetErrorMode.

          SEM_FAILCRITICALERRORS		SEM_NOGPFAULTERRORBOX
          SEM_NOALIGNMENTFAULTEXCEPT	SEM_NOOPENFILEERRORBOX

`":PARTITION_"'
     Constants describing partition types.

          PARTITION_ENTRY_UNUSED		PARTITION_FAT_12
          PARTITION_XENIX_1		PARTITION_XENIX_2
          PARTITION_FAT_16		PARTITION_EXTENDED
          PARTITION_HUGE			PARTITION_IFS
          PARTITION_FAT32			PARTITION_FAT32_XINT13
          PARTITION_XINT13		PARTITION_XINT13_EXTENDED
          PARTITION_PREP			PARTITION_UNIX
          VALID_NTFT			PARTITION_NTFT

`":ALL"'
     All of the above.

BUGS
====

   None known at this time.

AUTHOR
======

   Tye McQueen, tye@metronet.com, http://www.metronet.com/~tye/.

SEE ALSO
========

   The pyramids.

Perl interface to the Windows NT LanManager API account management functions.
*****************************************************************************

NAME
====

   Win32API::Net - Perl interface to the Windows NT LanManager API account
management functions.

SYNOPSIS
========

   use Win32API::Net;

NOTE ON VERSIONS PRIOR TO 0.08
==============================

   As of version 0.08 of this module, the behaviour relating to empty
strings in input hashes has changed. The old behaviour converted such
strings to the NULL pointer. The underlying API uses this value as an
indication to not change the value stored for a given field. This meant
that you were not able to clear (say) the logonScript field for a user
using UserSetInfo().

   The new behaviour is to leave the string as an empty C string which will
allow fields to be cleared.  To pass a NULL pointer to the underlying API
call (and thus, to leave the field as it was), you need to set the
corresponding field to undef.

   WARNING: *THIS IS AN INCOMPATIBLE CHANGE*.  *EXISTING SCRIPTS THAT
RELIED ON PRIOR BEHAVIOR MAY NEED TO BE MODIFIED*.

DESCRIPTION
===========

   Win32API::Net provides a more complete wrapper for the account
management parts of the NT LanManager API than do other similar packages.
Most of what you can achieve with the native C++ API is possible with this
package - albeit in a more Perl like manner by using references to pass
information to and from functions.

   For an understanding of the environment in which these functions
operate see `DATA STRUCTURES' in this node.

   The following groups of functions are available:

`NET USER FUNCTIONS' in this node
`NET GROUP FUNCTIONS' in this node
`NET LOCAL GROUP FUNCTIONS' in this node
`NET GET FUNCTIONS' in this node
   All functions return 0 on failure and 1 on success. Use the
Win32::GetLastError() function to find out more information on why a
function failed. In addition, some functions that take a hash reference to
pass information in (e.g. `UserAdd()') have a last argument that will
allow more detailed information on which key/value pair was not properly
specified.

Using References
----------------

   References to hashes and arrays are used throughout this package to pass
information into and out of functions.

Using Hash References
     Where a hash reference is required you can use anything that
     evaluates to a hash reference. e.g.

          $href = \%someHash;
          UserAdd(server, 2, $hRef);

     Or more directly:

          UserAdd(server, 2, \%someHash);

Using Array references
     Array references are used in a similar manner to hash references. e.g.

          $aref = \@someArray;
          UserEnum(server, $aref);

     Or more directly:

          UserEnum(server, \@someArray);

   Please note: Any `*Get*()' or `*Enum()' operation will first clear the
contents of the input hash or array being referenced.

   See `EXAMPLES' in this node and the test.pl script for examples of
usage.

DATA STRUCTURES
===============

   Most the the functions in the underlying API allow the programmer to
pass specify at runtime the amount of information that is supplied to the
function. For example, the `NetUserGetInfo()' call allows the programmer to
specify levels of 0, 1, 2, 3 (and others). Having specified this level, the
function returns a structure that will contain different fields. For a
level 0, the function returns a structure that has only one field. For a
supplied level of 1, the function returns a structure with 8 fields. The
programmer needs to know in advance what fields should be provided or will
be returned for a given level. This mechanism works very will since it
effectively overloads functions without having to use different function
prototypes. Perl provides better higher level data structures in the form
of arrays and hashes. This package uses hashes as the means to pass these
variable size structure into and out of functions.

   For any function that takes a reference to a hash as input, the
programmer is expected to provide appropriate keys and corresponding
values as well as the level parameter. The called function will then takes
the values out of the supplied hash and build the approprite structure to
pass to the underlying API function.

   For any function that takes a reference to a hash to recieve output, the
function will first clear any keys an corresponding values in the supplied
hash. It will call the underlying API call and will then return in the hash
any keys and values that are applicable at the requested level.

   Example:

   The `UserGetInfo()' can takes a number of levels. If called with level 0
the supplied hash will, on return from the function, contain a single key
and value - namely name/*requested-users-name*. If called with a level of
1 the supplied hash will, on return from the function, contain 8 keys and
values. The returned keys are `name, password', `passwordAge', `priv',
`homeDir', comment, flags, `scriptPath'. See `USER INFO FIELDS' in this
node for more information on what these represent.

Exports
=======

   By default, Win32API::Net exports no symbols into the callers namespace.
The following tags can be used to selectively import symbols into the main
namespace.

`:User'
     Exports all symbols needed for the `User*()' functions.  See `NET
     USER FUNCTIONS' in this node.

`:Get'
     Exports all symbols needed for the `Get*()' functions.  See `NET GET
     FUNCTIONS' in this node.

`:Group'
     Exports all symbols needed for the `Group*()' functions.  See `NET
     GROUP FUNCTIONS' in this node.

`:LocalGroup'
     Exports all symbols needed for the `LocalGroup*()' functions.  See
     `NET LOCAL GROUP FUNCTIONS' in this node.

NET USER FUNCTIONS
==================

   The `User*()' functions operate on NT user accounts.

   Administrator or Account Operator group membership is required to
successfully execute most of these functions on a remote server or on a
computer that has local security enabled. Administrator privileges are
required to add an Administrator Privilege account.  There are some
exceptions to this whereby a user can change some of their own settings
where these don't conflict with 'administrative information' (e.g. full
name).

   The server field can be the empty string, in which case the function
defaults to running on the local computer. If you leave this field blank
then you should ensure that you are running the function on a PDC or BDC
for your current domain. Use the support function `GetDCName()' to find out
what the domain controller is, should you not be running this on the PDC.

   All functions in this section are 'DOMAIN functions'. This means that,
for example, the `UserGetLocalGroups()' function actually lists the
domain's local groups of which the named user is a member.

   The following functions are available.

UserAdd(server, level, hash, error)
-----------------------------------

   Add a new user account. The user name is taken from the name-key's
value in the supplied hash.

server - Scalar String
     The server on which to add the account.

level - Scalar Int
     Level of information provided in hash. This can be either 1, 2 or 3.
     See `USER INFO LEVELS' in this node.

hash - Hash Reference
     The information to use to add this account. This should have all the
     appropriate keys and values required for level.

error - Scalar Int
     Provides information on which field in the hash was not properly
     specified.  See `USER FIELD ERRORS' in this node for more information
     about what values this can take.

UserChangePassword(server, user, old, new)
------------------------------------------

   Changes the password for user. If the policy of the machine/domain only
allows password changes if the user is logged on then the user must be
logged on to execute this function. With Administrator or Account Operator
privilege you can use this function to change anyone's password, so long
as you know the old password.

server - Scalar String
     The server on which to change the password.

user - Scalar String
     The name of the user whose password is being changed.

old - Scalar String
     The existing password for user.

new - Scalar String
     The new password for user.

UserDel(server, user)
---------------------

   Deletes the specified user account. Administrator or Account Operator
privilege is required to execute this function.

server - Scalar String
     The server on which to delete the user.

user - Scalar String
     The user account to delete.

UserEnum(server, array[, filter])
---------------------------------

   Enumerates all the accounts on server that satisfy filter. Unlike the
`NetUserEnum()' function in the API, this function does not allow you to
specify a level (internally it is hardcoded to 0). In Perl it is trivial
to implement the equivalent function (should you need it) - see `Example
1' in this node.

server - Scalar String
     The server on which to enumerate the accounts satisfying filter.

array - Array Reference
     The array that will hold the names of all users on server whose
     accounts match filter.

filter - Scalar Int (optional)
     The filter to apply (see `USER ENUM FILTER' in this node). This
     argument is optional and if not present a default of
     `FILTER_NORMAL_ACCOUNT' is used.

UserGetGroups(server, user, array)
----------------------------------

   Get the global groups for which user is a member. It returns the group
names in array. Unlike the `NetUserGetGroups()' function in the API, this
function does not allow you to specify a level (internally is hardcoded to
0). In Perl it is trivial to implement the equivalent function (in the
unlikely event that you might need it).

server - Scalar String
     The server from which to get the groups of which user is a member.

user - Scalar String
     The user whose group membership you wish to examine.

array - Scalar String
     The array that will contain the group names to which user belongs.

UserGetInfo(server, user, level, hash)
--------------------------------------

   Returns the information at the specified level for the named user in
hash.

server - Scalar String
     The server from which to get the requested information about user.

user - Scalar String
     The user whose information you want.

level - Scalar Int
     One of: 0, 1, 2, 3, 10, 11 and 20. See `USER INFO LEVELS' in this
     node.

hash - Hash Reference
     The hash that will contain the keys and values for the information
     requested. See `USER INFO FIELDS' in this node for information about
     which keys are present in a given level.

UserGetLocalGroups(server, user, array[, flags])
------------------------------------------------

   Gets the names of the local groups of which user is a member. Unlike
the `NetUserEnum()' function in the API, this function does not allow you
to specify a level. Since the underlying API restricts you to level 0 there
really isn't any need to include it...

server - Scalar String
     The server from which to get the local groups of which user is a
     member.

user - Scalar String
     The user whose local group membership you wish to enumerate.

array - Array Reference
     The array that will hold the names of the local groups to which user
     belongs.

flags - Scalar Int <em>(optional)</em>
     Either `Win32API::Net::LG_INCLUDE_INDIRECT()' or 0. if flags is
     omitted, the function internally uses 0. Specifying
     `LG_INCLUDE_INDIRECT()' will include in the list the names of the
     groups of which the user is indirectly a member (e.g. by being in a
     global group that is a member of a local group).

     This field can take no other values.

UserModalsGet()
---------------

   This function is not currently implemented.

UserModalsSet()
---------------

   This function is not currently implemented.

UserSetGroups(server, user, array)
----------------------------------

   Sets the (global) group membership for user to the specified groups.
Unlike the API function `NetUserSetGroups()', this function does not take a
level parameter (mainly because this option is largely redundant).

server - Scalar String
     The server on which you wish to set the group membership for user.

user - Scalar String
     The user whose group membership you wish to set.

array - Array Reference
     The array containing the (global) group names to set the users
     membership of.

   This function will fail if any of the group names specified do not
exist.

UserSetInfo(server, user, level, hash, error)
---------------------------------------------

   Sets the info for user according to the information contained in hash
for level (see `USER INFO LEVELS' in this node).

server - Scalar String
     The server on which you wish to change the info for user.

user - Scalar String
     The user whose info you wish to change.

level - Scalar Int
     One of 0, 1, 2, 3, or 20 (according to Microsoft documentation). In
     practice, you can use all the 10xx levels as well to change most of
     the individual properties of the named user - although this may not be
     supported in future...

hash - Hash Reference
     The hash that will contain the necessary key/value pairs required for
     level (see `USER INFO LEVELS' in this node).

error - Scalar Int
     Provides information on which field in hash were not properly
     specified. See `USER FIELD ERRORS' in this node for more information
     about what values can be returned in this field.

NET GROUP FUNCTIONS
===================

   The `Group*()' functions all operate only on global groups. To modify
local groups, use the corresponding `LocalGroup*()' functions.

   Administrator or Account Operator group membership is required to
successfully execute most of these functions on a remote server or on a
computer that has local security enabled.

   The server field can be the empty string, in which case the function
defaults to running on the local computer. If you leave this field blank
then you should ensure that you are running the function on a PDC or BDC
for your current domain. Use the support function `GetDCName()' to find out
what the domain controller is, should you not be running this on the PDC.

   The following functions are available.

GroupAdd(server, level, hash, error)
------------------------------------

   Adds the specified group.

server - Scalar String
     The server on which to add the group.

level - Scalar String
     The level of information contained in hash. This can be one of 0, 1
     or 2. See `GROUP INFO LEVELS' in this node.

hash - Hash Reference
     A hash containing the required key/value pairs for level.

error - Scalar Int
     Provides information on which field in hash was not properly
     specified.  See `GROUP FIELD ERRORS' in this node for more
     information about what values can be returned in this field.

GroupAddUser(server, group, user)
---------------------------------

   Adds the specified user to the specified group.

server - Scalar String
     The server on which to add the user to group.

group - Scalar String
     The group to add the user to.

user - Scalar String
     The user to add to group.

GroupDel(server, group)
-----------------------

   Deletes the specified global group.

server - Scalar String
     The server on which to delete the named group.

group -Scalar String
     The group to delete.

GroupDelUser(server, group, user)
---------------------------------

   Deletes the specified user from the specified group.

server - Scalar String
     The server on which to delete user from group.

group - Scalar String
     The group from which to delete user.

user - Scalar String
     The user to delete from group.

GroupEnum(server, array)
------------------------

   Enumerates all the global groups on the server. Unlike the API call
`NetGroupEnum()', this function does not allow you to specify a level
(internally it is hardcoded to 0). In Perl it is trivial to implement the
equivalent function (should you need it).

server - Scalar String
     The server on which to enumerate the (global) groups.

array - Array Reference
     An array that, on return, will contain the group names.

GroupGetInfo(server, group, level, hash)
----------------------------------------

   Retrieves level information for group returning information in hash.

server - Scalar String
     The server from which to get the group information.

group - Scalar String
     The group whose information you wish to obtain.

level - Scalar Int
     The level of information you wish to retrieve. This can be one of 1, 2
     or 3. See `GROUP INFO LEVELS' in this node.

hash - Hash Reference
     The hash that will contain the information.

GroupGetUsers(server, group, array)
-----------------------------------

   Returns (in array) the users belonging to group. Unlike the API call
`NetGroupGetUsers()', this function does not allow you to specify a level
(internally it is hardcoded to 0). In Perl it is trivial to implement the
equivalent function (should you need it).

server - Scalar String
     The server from which to get the group information.

group - Scalar String
     The group whose users you wish to obtain.

array - Array Reference
     The array to hold the user names retrieved.

GroupSetInfo(server, group, level, hash, error)
-----------------------------------------------

   Sets the information for group according to level.

server - Scalar String
     The server on which to set the group information.

group - Scalar String
     The group whose information you wish to set.

level - Scalar Int
     The level of information you are supplying in hash.  Level can be one
     of 0, 1 or 2. See `GROUP INFO LEVELS' in this node.

hash - Hash Reference
     The hash containing the required key/value pairs for level.

error - Scalar String
     On failure, the error parameter will contain a value which specifies
     which field caused the error. See `GROUP FIELD ERRORS' in this node.

GroupSetUsers(server, group, array)
-----------------------------------

   Sets the membership of group to contain only those users specified in
array. This function will fail if any user names contained in the array
are not valid users on server.  On successful completion group will
contain only the users specified in array.  Use the functions
`GroupAddUser()/GroupDelUser()' to add and delete individual users from a
group.

server - Scalar String
     The server on which to set the group membership.

group - Scalar String
     The group to set the membership of.

array - Array Reference
     The array containing the names of all users who will be members of
     group.

NET LOCAL GROUP FUNCTIONS
=========================

   The `LocalGroup*()' functions operate on local groups. If these
functions are run on a PDC then these functions operate on the domains
local groups.

   Administrator or Account Operator group membership is required to
successfully execute most of these functions on a remote server or on a
computer that has local security enabled.

   The server field can be the empty string, in which case the function
defaults to running on the local computer. If you leave this field blank
then you should ensure that you are running the function on a PDC or BDC
for your current domain. Use the support function `GetDCName()' to find
out what the domain controller is, should you not be running this on the
PDC.

   The following functions are available.

LocalGroupAdd(server, level, hash, error)
-----------------------------------------

   Adds the specified group. The name of the group is contained in the name
key of hash.

server - Scalar String
     The server on which to add the group.

level - Scalar String
     The level of information contained in hash. This can be one of 0 or 1.
     See `LOCAL GROUP INFO LEVELS' in this node.

hash - Hash Reference
     A hash containing the required key/value pairs for level.

error - Scalar Int
     Provides information on which field in hash wasn't properly specified.
     See `LOCAL GROUP FIELD ERRORS' in this node for more information
     about what values this can take.

LocalGroupAddMember()
---------------------

   This function is obselete in the underlying API and has therefore not
been implemented.  Use `LocalGroupAddMembers' instead.

LocalGroupAddMembers(server, group, array)
------------------------------------------

   Adds the specified users (members) to the local group. Unlike the API
function `NetLocalGroupAddMembers()', this function does not allow you to
specify a level (internally it is hardcoded to 3).  This was done to
simplify the implementation. To add a 'local' user, you need only specify
the name. You can also specify users using the `DOMAIN\user' syntax.

server - Scalar String
     The server on which to add the members to group.

group - Scalar String
     The group to add the members to.

array - Array Reference
     The array containing the members to add to group.

LocalGroupDel(server, group)
----------------------------

   Delete the specified local group.

server - Scalar String
     The server on which to delete the named group.

group -Scalar String
     The group to delete.

LocalGroupDelMember()
---------------------

   This function is obselete in the underlying API and has therefore not
been implemented.  Use `LocalGroupDelMembers()' instead.

LocalGroupDelMembers(server, group, array)
------------------------------------------

   Delete the specified users (members) of the local group. Unlike the API
function `NetLocalGroupDelMembers()', this function does not allow you to
specify a level (internally it is hardcoded to 3). This was done to
simplify the implementation. To delete a 'local' user, you need only
specify the name. You can also specify users using the `DOMAIN\user'
syntax.

server - Scalar String
     The server on which to delete the members from group.

group - Scalar String
     The group to delete the members from.

array - Array Reference
     The array containing the members to delete from group.

LocalGroupEnum(server, array)
-----------------------------

   Enumerates all the local groups on the server. Unlike the API call
`NetLocalGroupEnum()', this function does not allow you to specify a level
(internally it is hardcoded to 0). In Perl it is trivial to implement the
equivalent function (should you need it).

server - Scalar String
     The server on which to enumerate the (local) groups.

array - Array Reference
     The array to hold the group names.

LocalGroupGetInfo(server, group, level, hash)
---------------------------------------------

   Retrieves level information for group.

server - Scalar String
     The server from which to get the group information.

group - Scalar String
     The group whose information you wish to obtain.

level - Scalar Int
     The level of information you wish to retrieve. This can be 0 or 1.
     See `LOCAL GROUP INFO LEVELS' in this node.

hash - Hash Reference
     The hash that will contain the information.

LocalGroupGetMembers(server, group, hash)
-----------------------------------------

   Retrieves the users belonging to group. Unlike the API call
`NetLocalGroupGetUsers()', this function does not allow you to specify a
level (internally it is hardcoded to 0). In Perl it is trivial to
implement the equivalent function (should you need it).

server - Scalar String
     The server from which to retrieve the group information.

group - Scalar String
     The group whose users you wish to obtain.

array - Array Reference
     The array to hold the user names retrieved.

LocalGroupSetInfo(server, level, hash, error)
---------------------------------------------

   Sets the information for group according to level.

server - Scalar String
     The server on which to set the group information.

group - Scalar String
     The group whose information you wish to set.

level - Scalar Int
     The level of information you are supplying in hash.  Level can be one
     of 0 or 1. See `LOCAL GROUP INFO LEVELS' in this node.

hash - Hash Reference
     The hash containing the required key/value pairs for level.

error - Scalar String
     On failure, the error parameter will contain a value which specifies
     which field caused the error. See `LOCAL GROUP FIELD ERRORS' in this
     node.

LocalGroupSetMembers()
----------------------

   This function has not been implemented at present.

NET GET FUNCTIONS
=================

GetDCName(server, domain, domain-controller)
--------------------------------------------

   Gets the `domain-controllder' name for server and domain.

server - Scalar String
     The server whose domain controller you wish to locate.

domain - Scalar String
     The domain that server is a member of whose domain-controller you
     wish the locate.

`domain-controller' - Scalar String (output)
     The name of the `domain-controller' for the requested domain.

   Note: This module does not implement the `NetGetAnyDCName()'API function
as this is obsolete.

USER INFO LEVELS
================

   Most of the `User*()' functions take a level parameter. This level
specifies how much detail the corresponding hash should contain (or in the
case of a `UserGet*()' function, will contain after the call). The
following level descriptions provide information on what fields should be
present for a given level. See `USER INFO FIELDS' in this node for a
description of the fields.

Level 0
     name

Level 1
     name, password, passwordAge, priv, homeDir, comment, flags, scriptPath

Level 2
     name, password, passwordAge, priv, homeDir, comment, flags,
     scriptPath, authFlags, fullName, usrComment, parms, workstations,
     lastLogon, lastLogoff, acctExpires, maxStorage, unitsPerWeek,
     logonHours, badPwCount, numLogons, logonServer, countryCode, codePage

Level 3
     name, password, passwordAge, priv, homeDir, comment, flags,
     scriptPath, authFlags, fullName, usrComment, parms, workstations,
     lastLogon, lastLogoff, acctExpires, maxStorage, unitsPerWeek,
     logonHours, badPwCount, numLogons, logonServer, countryCode,
     codePage, userId, primaryGroupId, profile, homeDirDrive,
     passwordExpired

Level 10
     name, comment, usrComment, fullName

Level 11
     name, comment, usrComment, fullName, priv, authFlags, passwordAge,
     homeDir, parms, lastLogon, lastLogoff, badPwCount, numLogons,
     logonServer, countryCode, workstations, maxStorage, unitsPerWeek,
     logonHours, codePage

Level 20
     name, fullName, comment, flags, userId

Level 21
     *Not available in this implementation*

Level 22
     *Not available in this implementation*

Level 1003
     password

Level 1005
     priv

Level 1006
     homeDir

Level 1007
     comment

Level 1008
     flags

Level 1009
     scriptPath

Level 1010
     authFlags

Level 1011
     fullName

Level 1012
     usrComment

Level 1013
     parms

Level 1014
     workstations

Level 1017
     acctExpires

Level 1018
     maxStorage

Level 1020
     unitsPerWeek, logonHours

Level 1023
     logonServer

Level 1024
     countryCode

Level 1025
     codePage

Level 1051
     primaryGroupId

Level 1052
     profile

Level 1053
     homeDirDrive

USER INFO FIELDS
================

   The following is an alphabetical listing of each possible field,
together with the data type that the field is expected to contain.

`acctExpires' - Scalar Int (UTC)
     The time (as the number of seconds since 00:00:00, 1st January 1970)
     when the account expires. A -1 in this field specifies that the
     account never expires.

`authFlags' - Scalar Int (See USER_AUTH_FLAGS).
     The level of authority that this use has. The value this can take
     depends on the users group membership - this value is therefore read
     only and cannot be set using `UserAdd()' or `UserSetInfo()'. Its
     value can be one of:

     User belongs to group		Flag value
     ---------------------		----------
     Print Operators			Win32API::Net::AF_OP_PRINT()
     Server Operators		Win32API::Net::AF_OP_SERVER()
     Account Operators		Win32API::Net::AF_OP_ACCOUNTS()

`badPwCount' - Scalar Int
     The number of times that the user has failed to logon by specifying an
     incorrect password.

`codePage' - Scalar Int
     The code page that this user uses.

comment - Scalar String
     The comment associated with this user account. This can be any string
     (apparently of any length).

`countryCode' - Scalar Int
     The country code that this user uses.

flags - Scalar Int (Bitwise OR of USER_FLAGS)
     The flags for this user. See `USER FLAGS' in this node.

`fullName' - Scalar String
     The users' full name.

`homeDir' - Scalar String
     The home directory of the user. This can be either a UNC path or an
     absolute path (drive letter + path). Can be the empty string ("").

`homeDirDrive' - Scalar String
     The home directory drive that the users home directory is mapped to
     (assuming that the specified home directory is a UNC path).

`lastLogon' - Scalar Int (UTC)
     The time (as the number of seconds since 00:00:00, 1st January 1970)
     that the user last logged on.

`lastLogoff' - Scalar Int (UTC)
     The time (as the number of seconds since 00:00:00, 1st January 1970)
     that the user last logged off .

`logonHours' - Reference to Array of Integers (length 21 elements)
     The times at which the user can logon. This should be an integer array
     with 21 elements.  Each element represents an 8 hour period and each
     bit represents represents an hour. Only the lower byte of each
     integer is used. If this is left undefined then no restrictions are
     placed on the account.

`logonServer' - Scalar String
     The logon server for this user. Under Windows NT, this value cannot be
     set and will always have the value '\\*' when queried.

`maxStorage' - Scalar Int
     The current release of Windows NT does not implement disk quotas so
     it is believed that the value of this key is ignored.

name - Scalar String
     The user name that this request applies to. Most of the functions take
     the user name as a separate argument. In general, the user name
     provided should be the same as that in the one provided in the hash.

`numLogons' - Scalar Int
     The number of times that the named user has successfully logged on to
     this machine/domain.

`parms' - Scalar String
     The value of this key can be used by applications. There are none
     known to to author that use it, although it could be used to hold
     adminitrative information.

password - Scalar String
     The password to be set. The password is never returned in a
     `UserGet()' operation.

`passwordAge' - Scalar Int (UTC)
     The current age of the password (stored as the number of seconds since
     00:00:00, 1st January 1970).

`passwordExpired' - Scalar Int
     The value of this key is used in two different ways. When queried via
     `UserGetInfo()' the return value is 0 is the password has not expired
     and 1 if it has. When setting the value via `UserAdd()' or
     `UserSetInfo()' a value of 0 indicates that the users' password has
     not expired whereas a value of 1 will force the user to change their
     password at the next logon.

`primaryGroupId' - Scalar Int
     The id of the primary group that this user belongs to. When creating
     accounts with `UserAdd()' you should use a value of 0x201.

`priv' - Scalar Int (Bitwise OR of USER_PRIVILEGE_FLAGS)
     The privilege level that this user has. This is never returned from a
     `UserGet()' call. See `USER PRIVILEGE FLAGS' in this node.

profile - Scalar String
     The profile that is associated with the named user. This can be UNC
     path, a local path or undefined.

`scriptPath' - Scalar String
     The path to the logon script for this user. This should be specified
     as a relative path and will cause the logon script to be run from
     (relative location) in the logon servers export directory.

`unitsPerWeek' - Scalar Int
     The value of this key represents the granularity of the logonHours
     array.  Its use is beyond the scope of this package.

`usrComment' - Scalar String
     The user comment field (contrasted with the comment field ;-).

`workstations' - Scalar String
     A comma-separated string containing upto 8 workstation that the named
     user can login to.  Setting a value for this key will then allow the
     named user to login to only those computers named.

`userId' - Scalar Int
     The user id associated with this user This value is generated by the
     system and cannot be set or changed using the `UserAdd()' or
     `UserSetInfo()' calls.

USER FLAGS
==========

   The following is an alphabetical listing of the user flags.  The flags
key (see `USER INFO FIELDS' in this node) should be the bitwise OR of one
or more of these values.

`UF_ACCOUNTDISABLE()'
     This account has been disabled.

`UF_DONT_EXPIRE_PASSWD()'
     Never expire the password on this account.

`UF_HOMEDIR_REQUIRED()'
     A home directory must be specified (ignored for NT).

`UF_INTERDOMAIN_TRUST_ACCOUNT()'
     The account represents a interdomain trust account.

`UF_LOCKOUT()'
     Lock out this account (or this account has been locked out due to
     security policy - i.e.  badLogonCount is greater than your policy
     allows).  This value can be cleared but not set by a `UserSetInfo()'
     call.

`UF_NORMAL_ACCOUNT()'
     The account is a normal user account.

`UF_PASSWD_CANT_CHANGE()'
     The password for this account cannot be changed (execpt by an
     Administrator using one of the above calls).

`UF_PASSWD_NOTREQD()'
     A password is not required for this account.

`UF_SCRIPT()'
     This <strong>must be set when creating account on Windows NT.

`UF_SERVER_TRUST_ACCOUNT()'
     The account represents a Windows NT Backup Domain Controller account
     in the domain.

`UF_TEMP_DUPLICATE_ACCOUNT()'
     To quote the Microsoft Documentation <em>&quot;This is an account for
     users whose primary account is in another domain. This account
     provides user access to this domain, but not to any domain that
     trusts this domain.  The User Manager refers to this account type as
     a local user account.

`UF_WORKSTATION_TRUST_ACCOUNT()'
     The account represents a computer account for a workstation or server
     in the domain.

   Please note that these are implemented as functions and are therefore
called in the same way as other functions. You should typically use them
like:

     $ufScript = Win32API::Net::UF_SCRIPT();

USER PRIVILEGE FLAGS
====================

   These following values are used in the `priv' key. This field is never
initialised on a `UserGet*()' call and once set cannot be changed in a
`UserSetInfo()' call.

`USER_PRIV_ADMIN()'
     Account is an an administrative account.

`USER_PRIV_GUEST()'
     Account is a guest account.

`USER_PRIV_USER()'
     Account is a user account.

   Please note that these are implemented as functions and are therefore
called in the same way as other functions. You should typically use them
like:

     $userPrivUser = Win32API::Net::USER_PRIV_USER();

USER ENUM FILTER
================

   These flags are used in the `UserEnum()' function to specify which
accounts to retrieve. It should be a bitwise OR of some (or all) of the
following.

`FILTER_TEMP_DUPLICATE_ACCOUNT()'
     Show temporary duplicate account (one presumes).

`FILTER_NORMAL_ACCOUNT()'
     Show normal user account.

`FILTER_INTERDOMAIN_TRUST_ACCOUNT()'
     Show interdomain trust accounts.

`FILTER_WORKSTATION_TRUST_ACCOUNT()'
     Show workstation trust accounts.

`FILTER_SERVER_TRUST_ACCOUNT()'
     Show server trust accounts.

   Please note that these are implemented as functions and are therefore
called in the same way as other functions. You should typically use them
like:

     $filterNormalAccounts = Win32API::Net::FILTER_NORMAL_ACCOUNT();

USER FIELD ERRORS
=================

   For the `User*()' functions that take an error parameter this variable
will, on failure, contain one of the following constants. Note that the
function may fail because more than one key/value was missing from the
input hash. You will only find out about the first one that was incorrectly
specified. This is only really useful in debugging.

`USER_ACCT_EXPIRES_PARMNUM()'
     `acctExpires' field was absent or not correctly specified.

`USER_AUTH_FLAGS_PARMNUM()'
     `authFlags' field was absent or not correctly specified.

`USER_BAD_PW_COUNT_PARMNUM()'
     `badPasswordCount' field was absent or not correctly specified.

`USER_CODE_PAGE_PARMNUM()'
     `codePage' field was absent or not correctly specified.

`USER_COMMENT_PARMNUM()'
     comment field was absent or not correctly specified.

`USER_COUNTRY_CODE_PARMNUM()'
     `countryCode' field was absent or not correctly specified.

`USER_FLAGS_PARMNUM()'
     flags field was absent or not correctly specified.

`USER_FULL_NAME_PARMNUM()'
     `fullName' field was absent or not correctly specified.

`USER_HOME_DIR_DRIVE_PARMNUM()'
     `homeDirDrive' field was absent or not correctly specified.

`USER_HOME_DIR_PARMNUM()'
     `homeDir' field was absent or not correctly specified.

`USER_LAST_LOGOFF_PARMNUM()'
     `lastLogoff' field was absent or not correctly specified.

`USER_LAST_LOGON_PARMNUM()'
     `lastLogon' field was absent or not correctly specified.

`USER_LOGON_HOURS_PARMNUM()'
     `logonHours' field was absent or not correctly specified.

`USER_LOGON_SERVER_PARMNUM()'
     `logonServer' field was absent or not correctly specified.

`USER_MAX_STORAGE_PARMNUM()'
     `maxStorage' field was absent or not correctly specified.

`USER_NAME_PARMNUM()'
     name field was absent or not correctly specified.

`USER_NUM_LOGONS_PARMNUM()'
     `numLogons' field was absent or not correctly specified.

`USER_PARMS_PARMNUM()'
     `parms' field was absent or not correctly specified.

`USER_PASSWORD_AGE_PARMNUM()'
     `passwordAge' field was absent or not correctly specified.

`USER_PASSWORD_PARMNUM()'
     password field was absent or not correctly specified.

`USER_PRIMARY_GROUP_PARMNUM()'
     `primaryGroup' field was absent or not correctly specified.

`USER_PRIV_PARMNUM()'
     `priv' field was absent or not correctly specified.

`USER_PROFILE_PARMNUM()'
     profile field was absent or not correctly specified.

`USER_SCRIPT_PATH_PARMNUM()'
     `scriptPath' field was absent or not correctly specified.

`USER_UNITS_PER_WEEK_PARMNUM()'
     `unitPerWeek' field was absent or not correctly specified.

`USER_USR_COMMENT_PARMNUM()'
     `usrComment' field was absent or not correctly specified.

`USER_WORKSTATIONS_PARMNUM()'
     `workstations' field was absent or not correctly specified.

GROUP INFO LEVELS
=================

   Some of the `Group*()' functions take a level parameter. This level
specifies how much detail the corresponding hash should contain (or in the
case of a `GroupGetInfo()' function, will contain after the call).  The
following level descriptions provide information on what fields should be
present for a given level. See `GROUP INFO FIELDS' in this node for a
description of the fields.

`Level 0'
     name.

`Level 1'
     name, comment.

`Level 2'
     name, comment, groupId, attributes.

`Level 1002'
     comment.

`Level 1005'
     attributes.

GROUP INFO FIELDS
=================

attributes - Scalar Int
     The attributes of the group. These are no longer settable in Windows
     NT 4.0 and they are not currently supported in this package either.

comment - Scalar String
     The comment that applies to this group. This is the only value that
     can be set via a GroupSetInfo call.

`groupId' - Scalar Int
     The groups Id.

name - Scalar String
     The groups name.

GROUP FIELD ERRORS
==================

   For the `Group*()' functions that take an error parameter this variable
will, on failure, contain one of the following constants.  Note that the
function may fail because more than one key/value was missing from the
input hash. You will only find out about the first one that was
incorrectly specified. This is only really useful for debugging purposes.

`GROUP_ATTRIBUTES_PARMNUM()'
     attributes field was absent or not correctly specified.

`GROUP_COMMENT_PARMNUM()'
     comment field was absent or not correctly specified.

`GROUP_NAME_PARMNUM()'
     name field was absent or not correctly specified.

GROUP USERS INFO LEVELS
=======================

   The `GroupGetUsers()' function can take a level of 0 or 1. These will
return the following:

`Level 0'
     name.

`Level 1'
     name, attributes.

GROUP USERS INFO FIELDS
=======================

name - Scalar String
     The user's name.

attributes - Scalar Int
     The attributes of the group. These are no longer settable in Windows
     NT 4.0 and they are not currently supported in this package either.

LOCAL GROUP INFO LEVELS
=======================

`Level 0'
     name

`Level 1'
     name, comment

`Level 1002'
     comment

LOCAL GROUP INFO FIELDS
=======================

name - Scalar String
     The groups name

comment - Scalar String
     The groups 'comment'

LOCAL GROUP FIELD ERRORS
========================

   For the `LocalGroup*()' functions that take an error parameter this
variable will, on failure, contain one of the following constants. Note
that the function may fail because more than one key/value was missing or
incorrectly specified in the input hash. You will only find out about the
first one that was incorrectly specified. This is only really useful for
debugging purposes.

`LOCALGROUP_NAME_PARMNUM()'
     The name field was absent or not correctly specified.

`LOCALGROUP_COMMENT_PARMNUM()'
     The comment field wasabsent or not correctly specified.

EXAMPLES
========

   The following example shows how you can create a function in Perl that
has the same functionality as the `NetUserEnum()' API call. The Perl
version doesn't have the level parameter so you must first use the
`UserEnum()' function to retrieve all the account names and then iterate
through the returned array issuing `UserGetInfo()' calls.

     sub userEnumAtLevel {
        my($server, $level, $filter) = @_;
        my(@array);
        Win32API::Net::UserEnum($server, \@array, $filter);
        for $user (@array) {
     	  Win32API::Net::UserGetInfo($server, $user, $level, \%hash);
     	  print "This could access all level $level settings for $user - eg fullName $hash{fullName}\n";
        }
     }
     userEnumAtLevel("", 2, 0);

AUTHOR
======

   Bret Giddings, <bret@essex.ac.uk>

SEE ALSO
========

   `perl(1)'

ACKNOWEDGEMENTS
===============

   This work was built upon work done by HiP Communications along with
modifications to HiPs code by <michael@ecel.uwa.edu.au> and
<rothd@roth.net>.  In addition, I would like to thank Jenny Emby at GEC
Marconi, U.K. for proof reading this manual page and making many
suggestions that have led to its current layout. Last but not least I
would like to thank Larry Wall and all the other Perl contributors for
making this truly wonderful language.

Low-level access to Win32 system API calls from WINREG.H
********************************************************

NAME
====

   Win32API::Registry - Low-level access to Win32 system API calls from
WINREG.H

SYNOPSIS
========

     use Win32API::Registry 0.21 qw( :ALL );

     RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SYSTEM\\Disk", 0, KEY_READ, $key );
       or  die "Can't open HKEY_LOCAL_MACHINE\\SYSTEM\\Disk: ",
     	    regLastError(),"\n";
     RegQueryValueEx( $key, "Information", [], $type, $data, [] );
       or  die "Can't read HKEY_L*MACHINE\\SYSTEM\\Disk\\Information: ",
     	    regLastError(),"\n";
     [...]
     RegCloseKey( $key )
       or  die "Can't close HKEY_LOCAL_MACHINE\\SYSTEM\\Disk: ",
     	    regLastError(),"\n";

DESCRIPTION
===========

   This provides fairly low-level access to the Win32 System API calls
dealing with the Registry [mostly from WINREG.H].  This is mostly intended
to be used by other modules such as `Win32::TieRegistry' [which provides
an extremely Perl-friendly method for using the Registry].

   For a description of the logical structure of the Registry, see the
documentation for the `Win32::TieRegistry' module.

   To pass in NULL as the pointer to an optional buffer, pass in an empty
list reference, [].

   Beyond raw access to the API calls and related constants, this module
handles smart buffer allocation and translation of return codes.

   All calls return a true value for success and a false value for
failure.  After any failure, $^E should automatically be set to indicate
the reason.  However, current versions of Perl often overwrite $^E too
quickly, so you can use `regLastError()' instead, which is only set by
Win32API::Registry routines.  `regLastError()' is also good if you have a
really old version of Perl that does not connect $^E to `GetLastError()' on
Win32.

   Note that $! is not set by these routines except by
`Win32API::Registry::constant()' when a constant is not defined.

Exports
-------

   Nothing is exported by default.  The following tags can be used to have
sets of symbols exported.

   [Note that much of the following documentation refers to the behavior
of the underlying API calls which may vary in current and future versions
of the Win32 API without any changes to this module.  Therefore you should
check the Win32 API documentation directly when needed.]

:Func
     The basic function names:

    AllowPriv
    `AllowPriv( $sPrivName, $bEnable )'
          Not a Win32 API call.  Enables or disables a specific privilege
          for the current process.  Returns a true value if successful and
          a false value [and sets $^E/`regLastError()'] on failure.  This
          routine does not provide a way to tell if a privilege is
          currently enabled.

          `$sPrivname' is a Win32 privilege name [see `' in this node].
          For example, `"SeBackupPrivilege"' [a.k.a. `SE_BACKUP_NAME']
          controls whether you can use `RegSaveKey()' and
          `"SeRestorePrivilege"' [a.k.a.  `SE_RESTORE_NAME'] controls
          whether you can use `RegLoadKey()'.

          If `$bEnable' is true, then `AllowPriv()' tries to enable the
          privilege.  Otherwise it tries to disable the privilege.

    AbortSystemShutdown
    `AbortSystemShutdown( $sComputerName )'
          Tries to abort a remote shutdown request previously made via
          `InitiateSystemShutdown()'.  Returns a true value if successful
          and a false value [and sets $^E/`regLastError()'] on failure.

    InitiateSystemShutdown
    `InitiateSystemShutdown( $sComputer, $sMessage, $uTimeoutSecs, $bForce, $bReboot )'
          Requests that a [remote] computer be shutdown or rebooted.
          Returns a true value if successful and a false value [and sets
          $^E/`regLastError()'] on failure.

          `$sComputer' is the name [or address] of the computer to be
          shutdown or rebooted.  You can use [] [for NULL] or "" to
          indicate the local computer.

          `$sMessage' is the message to be displayed in a pop-up window on
          the desktop of the computer to be shutdown or rebooted until the
          timeout expires or the shutdown is aborted via
          `AbortSystemShutdown()'.  With `$iTimeoutSecs == 0', the message
          will never be visible.

          `$iTimeoutSecs' is the number of seconds to wait before starting
          the shutdown.

          If `$bForce' is false, then any applications running on the
          remote computer get a chance to prompt the remote user whether
          they want to save changes.  Also, for any applications that do
          not exit quickly enough, the operating system will prompt the
          user whether they wish to wait longer for the application to
          exit or force it to exit now.  At any of these prompts the user
          can press *CANCEL* to abort the shutdown but if no applications
          have unsaved data, they will likely all exit quickly and the
          shutdown will progress with the remote user having no option to
          cancel the shutdown.

          If `$bForce' is true, all applications are told to exit
          immediately and so will not prompt the user even if there is
          unsaved data.  Any applications that take too long to exit will
          be forcibly killed after a short time.  The only way to abort
          the shutdown is to call `AbortSystemShutdown()' before the
          timeout expires and there is no way to abort the shutdown once
          it has begun.

          If `$bReboot' is true, the computer will automatically reboot
          once the shutdown is complete.  If `$bReboot' is false, then
          when the shutdown is complete the computer will halt at a screen
          indicating that the shutdown is complete and offering a way for
          the user to start to boot the computer.

          You must have the `"SeRemoteShutdownPrivilege"' privilege on the
          remote computer for this call to succeed.  If shutting down the
          local computer, then the calling process must have the
          `"SeShutdownPrivilege"' privilege and have it enabled.

    RegCloseKey
    `RegCloseKey( $hKey )'
          Closes the handle to a Registry key returned by `RegOpenKeyEx()',
          `RegConnectRegistry()', `RegCreateKeyEx()', or a few other
          routines.  Returns a true value if successful and a false value
          [and sets $^E/`regLastError()'] on failure.

    RegConnectRegistry
    `RegConnectRegistry( $sComputer, $hRootKey, $ohKey )'
          Connects to one of the root Registry keys of a remote computer.
          Returns a true value if successful and a false value [and sets
          $^E/`regLastError()'] on failure.

          `$sComputer' is the name [or address] of a remote computer whose
          Registry you wish to access.

          `$hKey' must be either `HKEY_LOCAL_MACHINE' or `HKEY_USERS' and
          specifies which root Registry key on the remote computer you
          wish to have access to.

          `$phKey' will be set to the handle to be used to access the
          remote Registry key if the call succeeds.

    regConstant
    `$value= regConstant( $sConstantName )'
          Fetch the value of a constant.  Returns undef if `$sConstantName'
          is not the name of a constant supported by this module.  Never
          sets $! nor $^E.

          This function is rarely used since you will usually get the
          value of a constant by having that constant imported into your
          package by listing the constant name in the `use
          Win32API::Registry' statement and then simply using the constant
          name in your code [perhaps followed by `()'].  This function is
          useful for verifying constant names not in Perl code, for
          example, after prompting a user to type in a constant name.

    RegCreateKey
    `RegCreateKey( $hKey, $sSubKey, $ohSubKey )'
          This routine is meant only for compatibility with Windows version
          3.1.  Use `RegCreateKeyEx()' instead.

    RegCreateKeyEx
    `RegCreateKeyEx( $hKey, $sSubKey, $uZero, $sClass, $uOpts, $uAccess, $pSecAttr, $ohNewKey, $ouDisp )'
          Creates a new Registry subkey.  Returns a true value if
          successful and a false value [and sets $^E/`regLastError()'] on
          failure.

          `$hKey' is the handle to a Registry key [either `HKEY_*' or from
          a previous call].

          `$sSubKey' is the name of the new subkey to be created.

          `$iZero' is reserved for future use and should always be
          specified as 0.

          `$sClass' is a string to be used as the class for the new
          subkey.  We are not aware of any current use for Registry key
          class information so the empty string, "", should usually be
          used here.

          `$iOpts' is a numeric value containing bits that control options
          used while creating the new subkey.  `REG_OPTION_NON_VOLATILE'
          is the default.  `REG_OPTION_VOLATILE' [which is ignored on
          Windows 95] means the data stored under this key is not kept in
          a file and will not be preserved when the system reboots.
          `REG_OPTION_BACKUP_RESTORE' [also ignored on Windows 95] means
          ignore the `$iAccess' parameter and try to open the new key with
          the access required to backup or restore the key.

          `$iAccess' is a numeric mask of bits specifying what type of
          access is desired when opening the new subkey.  See
          `RegOpenKeyEx()'.

          `$pSecAttr' is a `SECURITY_ATTRIBUTES' structure packed into a
          Perl string which controls whether the returned handle can be
          inherited by child processes.  Normally you would pass [] for
          this parameter to have NULL passed to the underlying API
          indicating that the handle cannot be inherited.  If not under
          Windows95, then `$pSecAttr' also allows you to specify
          `SECURITY_DESCRIPTOR' that controls which users will have what
          type of access to the new key - otherwise the new key inherits
          its security from its parent key.

          `$phKey' will be set to the handle to be used to access the new
          subkey if the call succeeds.

          `$piDisp' will be set to either `REG_CREATED_NEW_KEY' or
          `REG_OPENED_EXISTING_KEY' to indicate for which reason the call
          succeeded.  Can be specified as [] if you don't care.

          If `$phKey' and `$piDisp' start out as integers, then they will
          probably remain unchanged if the call fails.

    RegDeleteKey
    `RegDeleteKey( $hKey, $sSubKey )'
          Deletes a subkey of an open Registry key provided that the subkey
          contains no subkeys of its own [but the subkey may contain
          values].  Returns a true value if successful and a false value
          [and sets $^E/`regLastError()'] on failure.

          `$hKey' is the handle to a Registry key [either `HKEY_*' or from
          a previous call].

          `$sSubKey' is the name of the subkey to be deleted.

    RegDeleteValue
    `RegDeleteValue( $hKey, $sValueName )'
          Deletes a value from an open Registry key.  Returns a true value
          if successful and a false value [and sets $^E/`regLastError()']
          on failure.

          `$hKey' is the handle to a Registry key [either `HKEY_*' or from
          a previous call].

          `$sValueKey' is the name of the value to be deleted.

    RegEnumKey
    `RegEnumKey( $hKey, $uIndex, $osName, $ilNameSize )'
          This routine is meant only for compatibility with Windows version
          3.1.  Use `RegEnumKeyEx()' instead.

    RegEnumKeyEx
    `RegEnumKeyEx( $hKey, $uIndex, $osName, $iolName, $pNull, $osClass, $iolClass, $opftLastWrite )'
          Lets you enumerate the names of all of the subkeys directly under
          an open Registry key.  Returns a true value if successful and a
          false value [and sets $^E/`regLastError()'] on failure.

          `$hKey' is the handle to a Registry key [either `HKEY_*' or from
          a previous call].

          `$iIndex' is the sequence number of the immediate subkey that
          you want information on.  Start with this value as 0 then repeat
          the call incrementing this value each time until the call fails
          with $^E/`regLastError()' numerically equal to
          `ERROR_NO_MORE_ITEMS'.

          `$sName' will be set to the name of the subkey.  Can be [] if
          you don't care about the name.

          `$plName' initially specifies the [minimum] buffer size to be
          allocated for `$sName'.  Will be set to the length of the subkey
          name if the requested subkey exists even if `$sName' isn't
          successfully set to the subkey name.  See `Buffer sizes' in this
          node for more information.

          `$pNull' is reserved for future used and should be passed as [].

          `$sClass' will be set to the class name for the subkey.  Can be
          [] if you don't care about the class.

          `$plClass' initially specifies the [minimum] buffer size to be
          allocated for `$sClass' and will be set to the length of the
          subkey class name if the requested subkey exists.  See `Buffer
          sizes' in this node for more information.

          `$pftLastWrite' will be set to a `FILETIME' structure packed
          into a Perl string and indicating when the subkey was last
          changed.  Can be [].

          You may omit both `$plName' and `$plClass' to get the same effect
          as passing in [] for each of them.

    RegEnumValue
    `RegEnumValue( $hKey, $uIndex, $osValName, $iolValName, $pNull, $ouType, $opValData, $iolValData )'
          Lets you enumerate the names of all of the values contained in an
          open Registry key.  Returns a true value if successful and a
          false value [and sets $^E/`regLastError()'] on failure.

          `$hKey' is the handle to a Registry key [either `HKEY_*' or from
          a previous call].

          `$iIndex' is the sequence number of the value that you want
          information on.  Start with this value as 0 then repeat the call
          incrementing this value each time until the call fails with
          `ERROR_NO_MORE_ITEMS'.

          `$sValName' will be set to the name of the value.  Can be [] if
          you don't care about the name.

          `$plValName' initially specifies the [minimum] buffer size to be
          allocated for `$sValName'.  Will be set to the length of the
          value name if the requested value exists even if `$sValName'
          isn't successfully set to the value name.  See `Buffer sizes' in
          this node for more information.

          `$pNull' is reserved for future used and should be passed as [].

          `$piType' will be set to the type of data stored in the value
          data.  If the call succeeds, it will be set to a `REG_*' value
          unless passed in as [].

          `$pValData' will be set to the data [packed into a Perl string]
          that is stored in the requested value.  Can be [] if you don't
          care about the value data.

          `$plValData' initially specifies the [minimum] buffer size to be
          allocated for `$sValData' and will be set to the length of the
          value data if the requested value exists.  See `Buffer sizes' in
          this node for more information.

          You may omit both `$plValName' and `$plValData' to get the same
          effect as passing in [] for each of them.

    RegFlushKey
    `RegFlushKey( $hKey )'
          Forces the data stored under an open Registry key to be flushed
          to the disk file where the data is preserved between reboots.
          Forced flushing is not guaranteed to be efficient so this routine
          should almost never be called.  Returns a true value if
          successful and a false value [and sets $^E/`regLastError()'] on
          failure.

          `$hKey' is the handle to a Registry key [either `HKEY_*' or from
          a previous call].

    RegGetKeySecurity
    `RegGetKeySecurity( $hKey, $uSecInfo, $opSecDesc, $iolSecDesc )'
          Retrieves one of the `SECURITY_DESCRIPTOR' structures describing
          part of the security for an open Registry key.  Returns a true
          value if successful and a false value [and sets
          $^E/`regLastError()'] on failure.

          `$hKey' is the handle to a Registry key [either `HKEY_*' or from
          a previous call].

          `$iSecInfo' is a numeric `SECURITY_INFORMATION' value that
          specifies which parts of the `SECURITY_DESCRIPTOR' structure to
          retrieve.  Should be `OWNER_SECURITY_INFORMATION',
          `GROUP_SECURITY_INFORMATION', `DACL_SECURITY_INFORMATION', or or
          `SACL_SECURITY_INFORMATION' or two or more of these bits
          combined using |.

          `$pSecDesc' will be set to the requested `SECURITY_DESCRIPTOR'
          structure [packed into a Perl string].

          `$plSecDesc' initially specifies the [minimum] buffer size to be
          allocated for `$sSecDesc' and will be set to the length of the
          security descriptor.  See `Buffer sizes' in this node for more
          information.  You may omit this parameter to get the same effect
          as passing in [] for it.

    regLastError
    `$svError= regLastError();'
    `regLastError( $uError );'
          Returns the last error encountered by a routine from this module.
          It is just like $^E except it isn't changed by anything except
          routines from this module.  Ideally you could just use $^E, but
          current versions of Perl often overwrite $^E before you get a
          chance to check it and really old versions of Perl don't really
          support $^E under Win32.

          Just like $^E, in a numeric context `regLastError()' returns the
          numeric error value while in a string context it returns a text
          description of the error [actually it returns a Perl scalar that
          contains both values so `$x= regLastError()' causes $x to give
          different values in string vs. numeric contexts].  On old
          versions of Perl where $^E isn't tied to `GetLastError()',
          regLastError simply returns the number of the error and you'll
          need to use <Win32::FormatMessage> to get the error string.

          The last form sets the error returned by future calls to
          `regLastError()' and should not be used often.  `$uError' must
          be a numeric error code.  Also returns the dual-valued version
          of `$uError'.

    RegLoadKey
    `RegLoadKey( $hKey, $sSubKey, $sFileName )'
          Loads a hive file.  That is, it creates a new subkey in the
          Registry and associates that subkey with a disk file that
          contains a Registry hive so that the new subkey can be used to
          access the keys and values stored in that hive.  Hives are
          usually created via `RegSaveKey()'.  Returns a true value if
          successful and a false value [and sets $^E/`regLastError()'] on
          failure.

          `$hKey' is the handle to a Registry key that can have hives
          loaded to it.  This must be `HKEY_LOCAL_MACHINE', `HKEY_USERS',
          or a remote version of one of these from a call to
          `RegConnectRegistry()'.

          `$sSubKey' is the name of the new subkey to created and
          associated with the hive file.

          $sFileName is the name of the hive file to be loaded.  This file
          name is interpretted relative to the
          `%SystemRoot%/System32/config' directory on the computer where
          the `$hKey' key resides.  If $sFileName is on a FAT file system,
          then its name must not have an extension.

          You must have the `SE_RESTORE_NAME' privilege to use this
          routine.

          WARNING:  Loading of hive files via a network share may silently
          corrupt the hive and so should not be attempted [this is a
          problem in at least some versions of the underlying API which
          this module does not try to fix or avoid].  To access a hive
          file located on a remote computer, connect to the remote
          computer's Registry and load the hive via that.

    RegNotifyChangeKeyValue
    `RegNotifyChangeKeyValue( $hKey, $bWatchSubtree, $uNotifyFilter, $hEvent, $bAsync )'
          Arranges for your process to be notified when part of the
          Registry is changed.  Returns a true value if successful and a
          false value [and sets $^E/`regLastError()'] on failure.

          `$hKey' is the handle to a Registry key [either `HKEY_*' or from
          a previous call] for which you wish to be notified when any
          changes are made to it.

          If `$bWatchSubtree' is true, then changes to any subkey or
          descendant of `$hKey' are also reported.

          `$iNotifyFilter' controllers what types of changes are reported.
          It is a numeric value containing one or more of the following
          bit masks:

         `REG_NOTIFY_CHANGE_NAME'
               Notify if a subkey is added or deleted to a monitored key.

         `REG_NOTIFY_CHANGE_LAST_SET'
               Notify if a value in a monitored key is added, deleted, or
               modified.

         `REG_NOTIFY_CHANGE_SECURITY'
               Notify if a security descriptor of a monitored key is
               changed.

         `REG_NOTIFY_CHANGE_ATTRIBUTES'
               Notify if any attributes of a monitored key are changed
               [class name or security descriptors].

          `$hEvent' is ignored unless `$bAsync' is true.  Otherwise,
          `$hEvent' is a handle to a Win32 event that will be signaled
          when changes are to be reported.

          If `$bAsync' is true, then `RegNotifyChangeKeyValue()' returns
          immediately and uses `$hEvent' to notify your process of changes.
          If `$bAsync' is false, then `RegNotifyChangeKeyValue()' does not
          return until there is a change to be notified of.

          This routine does not work with Registry keys on remote
          computers.

    RegOpenKey
    `RegOpenKey( $hKey, $sSubKey, $ohSubKey )'
          This routine is meant only for compatibility with Windows version
          3.1.  Use `RegOpenKeyEx()' instead.

    RegOpenKeyEx
    `RegOpenKeyEx( $hKey, $sSubKey, $uOptions, $uAccess, $ohSubKey )'
          Opens an existing Registry key.  Returns a true value if
          successful and a false value [and sets $^E/`regLastError()'] on
          failure.

          `$hKey' is the handle to a Registry key [either `HKEY_*' or from
          a previous call].

          `$sSubKey' is the name of an existing subkey to be opened.  Can
          be "" or [] to open an additional handle to the key specified by
          `$hKey'.

          `$iOptions' is a numeric value containing bits that control
          options used while opening the subkey.  There are currently no
          supported options so this parameter should be specified as 0.

          `$iAccess' is a numeric mask of bits specifying what type of
          access is desired when opening the new subkey.  Should be a
          combination of one or more of the following bit masks:

         `KEY_ALL_ACCESS'
                    KEY_READ | KEY_WRITE | KEY_CREATE_LINK

         `KEY_READ'
                    KEY_QUERY_VALUE | KEY_ENUMERATE_SUBKEYS | KEY_NOTIFY | STANDARD_RIGHTS_READ

         `KEY_WRITE'
                    KEY_SET_VALUE | KEY_CREATE_SUB_KEY | STANDARD_RIGHTS_WRITE

         `KEY_QUERY_VALUE'
         `KEY_SET_VALUE'
         `KEY_ENUMERATE_SUB_KEYS'
         `KEY_CREATE_SUB_KEY'
         `KEY_NOTIFY'
               Allows you to use `RegNotifyChangeKeyValue()' on the opened
               key.

         `KEY_EXECUTE'
               Same as `KEY_READ'.

         `KEY_CREATE_LINK'
               Gives you permission to create a symbolic link like
               `HKEY_CLASSES_ROOT' and `HKEY_CURRENT_USER', though the
               method for doing so is not documented [and probably
               requires use of the mostly undocumented "native" routines,
               `Nt*()' a.k.a. `Zw*()'].

          `$phKey' will be set to the handle to be used to access the new
          subkey if the call succeeds.

    RegQueryInfoKey
    `RegQueryInfoKey( $hKey, $osClass, $iolClass, $pNull, $ocSubKeys, $olSubKey, $olSubClass, $ocValues, $olValName, $olValData, $olSecDesc, $opftTime )'
          Gets miscellaneous information about an open Registry key.
          Returns a true value if successful and a false value [and sets
          $^E/`regLastError()'] on failure.

          `$hKey' is the handle to a Registry key [either `HKEY_*' or from
          a previous call].

          `$sClass' will be set to the class name for the key.  Can be []
          if you don't care about the class.

          `$plClass' initially specifies the [minimum] buffer size to be
          allocated for `$sClass' and will be set to the length of the
          key's class name.  See `Buffer sizes' in this node for more
          information.  You may omit this parameter to get the same effect
          as passing in [] for it.

          `$pNull' is reserved for future use and should be passed as [].

          `$pcSubKeys' will be set to the count of the number of subkeys
          directly under this key.  Can be [].

          `$plSubKey' will be set to the length of the longest subkey name.
          Can be [].

          `$plSubClass' will be set to the length of the longest class name
          used with an immediate subkey of this key.  Can be [].

          `$pcValues' will be set to the count of the number of values in
          this key.  Can be [].

          `$plValName' will be set to the length of the longest value name
          in this key.  Can be [].

          `$plValData' will be set to the length of the longest value data
          in this key.  Can be [].

          `$plSecDesc' will be set to the length of this key's full
          security descriptor.

          `$pftTime' will be set to a `FILETIME' structure packed into a
          Perl string and indicating when this key was last changed.  Can
          be [].

    RegQueryMultipleValues
    `RegQueryMultipleValues( $hKey, $ioarValueEnts, $icValueEnts, $opBuffer, $iolBuffer )'
          Allows you to use a single call to query several values from a
          single open Registry key to maximize efficiency.  Returns a true
          value if successful and a false value [and sets
          $^E/`regLastError()'] on failure.

          `$hKey' is the handle to a Registry key [either `HKEY_*' or from
          a previous call].

          `$pValueEnts' should contain a list of `VALENT' structures packed
          into a single Perl string.  Each `VALENT' structure should have
          the `ve_valuename' entry [the first 4 bytes] pointing to a string
          containing the name of a value stored in this key.  The remaining
          fields are set if the function succeeds.

          `$cValueEnts' should contain the count of the number of `VALENT'
          structures contained in `$pValueEnts'.

          `$pBuffer' will be set to the data from all of the requested
          values concatenated into a single Perl string.

          `$plBuffer' initially specifies the [minimum] buffer size to be
          allocated for `$sBuffer' and will be set to the total length of
          the data to be written to `$sBuffer'.  See `Buffer sizes' in
          this node for more information.  You may omit this parameter to
          get the same effect as passing in [] for it.

          Here is sample code to populate `$pValueEnts':

               # @ValueNames= ...list of value name strings...;
               $cValueEnts= @ValueNames;
               $pValueEnts= pack( " p x4 x4 x4 " x $cValueEnts, @ValueNames );

          Here is sample code to retrieve the data type and data length
          returned in `$pValueEnts':

               @Lengths= unpack( " x4 L x4 x4 " x $cValueEnts, $pValueEnts );
               @Types=   unpack( " x4 x4 x4 L " x $cValueEnts, $pValueEnts );

          Given the above, and assuming you haven't modified `$sBuffer'
          since the call, you can also extract the value data strings from
          `$sBuffer' by using the pointers returned in `$pValueEnts':

               @Data=    unpack(  join( "", map {" x4 x4 P$_ x4 "} @Lengths ),
               		$pValueEnts  );

          Much better is to use the lengths and extract directly from
          `$sBuffer' using `unpack()' [or `substr()']:

               @Data= unpack( join("",map("P$_",@Lengths)), $sBuffer );

    RegQueryValue
    `RegQueryValue( $hKey, $sSubKey, $osValueData, $iolValueData )'
          This routine is meant only for compatibility with Windows version
          3.1.  Use `RegQueryValueEx()' instead.  This routine can only
          query unamed values [a.k.a. "default values"], that is, values
          with a name of "".

    RegQueryValueEx
    `RegQueryValueEx( $hKey, $sValueName, $pNull, $ouType, $opValueData, $iolValueData )'
          Lets you look up value data stored in an open Registry key by
          specifying the value name.  Returns a true value if successful
          and a false value [and sets $^E/`regLastError()'] on failure.

          `$hKey' is the handle to a Registry key [either `HKEY_*' or from
          a previous call].

          `$sValueName' is the name of the value whose data you wish to
          retrieve.

          `$pNull' this parameter is reserved for future use and should be
          specified as [].

          `$piType' will be set to indicate what type of data is stored in
          the named value.  Will be set to a `REG_*' value if the function
          succeeds.

          `$pValueData' will be set to the value data [packed into a Perl
          string] that is stored in the named value.  Can be [] if you
          don't care about the value data.

          `$plValueData' initially specifies the [minimum] buffer size to
          be allocated for `$sValueData' and will be set to the size
          [always in bytes] of the data to be written to `$sValueData',
          even if `$sValueData' is not successfully written to.  See
          `Buffer sizes' in this node for more information.

    RegReplaceKey
    `RegReplaceKey( $hKey, $sSubKey, $sNewFile, $sOldFile )'
          Lets you replace an entire hive when the system is next booted.
          Returns a true value if successful and a false value [and sets
          $^E/`regLastError()'] on failure.

          `$hKey' is the handle to a Registry key that has hive(s) loaded
          in it.  This must be `HKEY_LOCAL_MACHINE', `HKEY_USERS', or a
          remote version of one of these from a call to
          `RegConnectRegistry()'.

          `$sSubKey' is the name of the subkey of `$hKey' whose hive you
          wish to have replaced on the next reboot.

          `$sNewFile' is the name of a file that will replace the existing
          hive file when the system reboots.

          `$sOldFile' is the file name to save the current hive file to
          when the system reboots.

          `$sNewFile' and `$sOldFile' are interpretted relative to the
          `%SystemRoot%/System32/config' directory on the computer where
          the `$hKey' key resides [I think].  If either file is [would be]
          on a FAT file system, then its name must not have an extension.

          You must have the `SE_RESTORE_NAME' privilege to use this
          routine.

    RegRestoreKey
    `RegRestoreKey( $hKey, $sFileName, $uFlags )'
          Reads in a hive file and copies its contents over an existing
          Registry tree.  Returns a true value if successful and a false
          value [and sets $^E/`regLastError()'] on failure.

          `$hKey' is the handle to a Registry key [either `HKEY_*' or from
          a previous call].

          $sFileName is the name of the hive file to be read.  For each
          value and subkey in this file, a value or subkey will be added
          or replaced in `$hKey'.

          `$uFlags' is usally 0.  It can also be `REG_WHOLE_HIVE_VOLATILE'
          which, rather than copying the hive over the existing key,
          replaces the existing key with a temporary, memory-only Registry
          key and then copies the hive contents into it.  This option only
          works if `$hKey' is `HKEY_LOCAL_MACHINE', `HKEY_USERS', or a
          remote version of one of these from a call to
          `RegConnectRegistry()'.

          RegRestoreKey does not delete values nor keys from the existing
          Registry tree when there is no corresponding value/key in the
          hive file.

    RegSaveKey
    `RegSaveKey( $hKey, $sFileName, $pSecAttr )'
          Dumps any open Registry key and all of its subkeys and values
          into a new hive file.  Returns a true value if successful and a
          false value [and sets $^E/`regLastError()'] on failure.

          `$hKey' is the handle to a Registry key [either `HKEY_*' or from
          a previous call].

          $sFileName is the name of the file that the Registry tree should
          be saved to.  It is interpretted relative to the
          `%SystemRoot%/System32/config' directory on the computer where
          the `$hKey' key resides.  If $sFileName is on a FAT file system,
          then it must not have an extension.

          `$pSecAttr' contains a `SECURITY_ATTRIBUTES' structure that
          specifies the permissions to be set on the new file that is
          created.  This can be [].

          You must have the `SE_RESTORE_NAME' privilege to use this
          routine.

    RegSetKeySecurity
    `RegSetKeySecurity( $hKey, $uSecInfo, $pSecDesc )'
          Sets [part of] the `SECURITY_DESCRIPTOR' structure describing
          part of the security for an open Registry key.  Returns a true
          value if successful and a false value [and sets
          $^E/`regLastError()'] on failure.

          `$hKey' is the handle to a Registry key [either `HKEY_*' or from
          a previous call].

          `$uSecInfo' is a numeric `SECURITY_INFORMATION' value that
          specifies which `SECURITY_DESCRIPTOR' structure to set.  Should
          be `OWNER_SECURITY_INFORMATION', `GROUP_SECURITY_INFORMATION',
          `DACL_SECURITY_INFORMATION', or `SACL_SECURITY_INFORMATION' or
          two or more of these bits combined using |.

          `$pSecDesc' contains the new `SECURITY_DESCRIPTOR' structure
          packed into a Perl string.

    RegSetValue
    `RegSetValue( $hKey, $sSubKey, $uType, $sValueData, $lValueData )'
          This routine is meant only for compatibility with Windows version
          3.1.  Use `RegSetValueEx()' instead.  This routine can only set
          unamed values [a.k.a. "default values"].

    RegSetValueEx
    `RegSetValueEx( $hKey, $sName, $uZero, $uType, $pData, $lData )'
          Adds or replaces a value in an open Registry key.  Returns a
          true value if successful and a false value [and sets
          $^E/`regLastError()'] on failure.

          `$hKey' is the handle to a Registry key [either `HKEY_*' or from
          a previous call].

          `$sName' is the name of the value to be set.

          `$uZero' is reserved for future use and should be specified as 0.

          `$uType' is the type of data stored in `$pData'.  It should be a
          `REG_*' value.

          `$pData' is the value data packed into a Perl string.

          `$lData' is the length of the value data that is stored in
          `$pData'.  You will usually omit this parameter or pass in 0 to
          have `length($pData)' used.  In both of these cases, if `$iType'
          is REG_SZ or REG_EXPAND_SZ, `RegSetValueEx()' will append a
          trailing `'\0'' to the end of `$pData' [unless there is already
          one].

    RegUnLoadKey
    `RegUnLoadKey( $hKey, $sSubKey )'
          Unloads a previously loaded hive file.  That is, closes the hive
          file then deletes the subkey that was providing access to it.
          Returns a true value if successful and a false value [and sets
          $^E/`regLastError()'] on failure.

          `$hKey' is the handle to a Registry key that has hives loaded in
          it.  This must be `HKEY_LOCAL_MACHINE', `HKEY_USERS', or a
          remote version of one of these from a call to
          `RegConnectRegistry()'.

          `$sSubKey' is the name of the subkey whose hive you wish to have
          unloaded.

    :FuncA
          The ASCII-specific function names.

          Each of these is identical to the version listed above without
          the trailing "A":

               AbortSystemShutdownA	InitiateSystemShutdownA
               RegConnectRegistryA	RegCreateKeyA		RegCreateKeyExA
               RegDeleteKeyA		RegDeleteValueA		RegEnumKeyA
               RegEnumKeyExA		RegEnumValueA		RegLoadKeyA
               RegOpenKeyA		RegOpenKeyExA		RegQueryInfoKeyA
               RegQueryMultipleValuesA	RegQueryValueA		RegQueryValueExA
               RegReplaceKeyA		RegRestoreKeyA		RegSaveKeyA
               RegSetValueA		RegSetValueExA		RegUnLoadKeyA

    :FuncW
          The UNICODE-specific function names.  These are the same as the
          versions listed above without the trailing "W" except that string
          parameters are UNICODE strings rather than ASCII strings, as
          indicated.

    AbortSystemShutdownW
    `AbortSystemShutdownW( $swComputerName )'
          `$swComputerName' is UNICODE.

    InitiateSystemShutdownW
    `InitiateSystemShutdownW( $swComputer, $swMessage, $uTimeoutSecs, $bForce, $bReboot )'
          `$swComputer' and `$swMessage' are UNICODE.

    RegConnectRegistryW
    `RegConnectRegistryW( $swComputer, $hRootKey, $ohKey )'
          `$swComputer' is UNICODE.

    RegCreateKeyW
    `RegCreateKeyW( $hKey, $swSubKey, $ohSubKey )'
          `$swSubKey' is UNICODE.

    RegCreateKeyExW
    `RegCreateKeyExW( $hKey, $swSubKey, $uZero, $swClass, $uOpts, $uAccess, $pSecAttr, $ohNewKey, $ouDisp )'
          `$swSubKey' and `$swClass' are UNICODE.

    RegDeleteKeyW
    `RegDeleteKeyW( $hKey, $swSubKey )'
          `$swSubKey' is UNICODE.

    RegDeleteValueW
    `RegDeleteValueW( $hKey, $swValueName )'
          `$swValueName' is UNICODE.

    RegEnumKeyW
    `RegEnumKeyW( $hKey, $uIndex, $oswName, $ilwNameSize )'
          `$oswName' is UNICODE and `$ilwNameSize' is measured as number of
          `WCHAR's.

    RegEnumKeyExW
    `RegEnumKeyExW( $hKey, $uIndex, $oswName, $iolwName, $pNull, $oswClass, $iolwClass, $opftLastWrite )'
          `$swName' and `$swClass' are UNICODE and `$iolwName' and
          `$iolwClass' are measured as number of `WCHAR's.

    RegEnumValueW
    `RegEnumValueW( $hKey, $uIndex, $oswName, $iolwName, $pNull, $ouType, $opData, $iolData )'
          `$oswName' is UNICODE and `$iolwName' is measured as number of
          `WCHAR's.

          `$opData' is UNICODE if `$piType' is REG_SZ, REG_EXPAND_SZ, or
          REG_MULTI_SZ.  Note that `$iolData' is measured as number of
          bytes even in these cases.

    RegLoadKeyW
    `RegLoadKeyW( $hKey, $swSubKey, $swFileName )'
          `$swSubKey' and `$swFileName' are UNICODE.

    RegOpenKeyW
    `RegOpenKeyW( $hKey, $swSubKey, $ohSubKey )'
          `$swSubKey' is UNICODE.

    RegOpenKeyExW
    `RegOpenKeyExW( $hKey, $swSubKey, $uOptions, $uAccess, $ohSubKey )'
          `$swSubKey' is UNICODE.

    RegQueryInfoKeyW
    `RegQueryInfoKeyW( $hKey, $oswClass, $iolwClass, $pNull, $ocSubKeys, $olwSubKey, $olwSubClass, $ocValues, $olwValName, $olValData, $olSecDesc, $opftTime )'
          `$swClass' is UNICODE.  `$iolwClass', `$olwSubKey',
          `$olwSubClass', and `$olwValName' are measured as number of
          `WCHAR's.  Note that `$olValData' is measured as number of bytes.

    RegQueryMultipleValuesW
    `RegQueryMultipleValuesW( $hKey, $ioarValueEnts, $icValueEnts, $opBuffer, $iolBuffer )'
          The `ve_valuename' fields of the `VALENT' [actually `VALENTW']
          structures in `$ioarValueEnts' are UNICODE.  Values of type
          REG_SZ, REG_EXPAND_SZ, and REG_MULTI_SZ are written to
          `$opBuffer' in UNICODE.  Note that `$iolBuffer' and the
          `ve_valuelen' fields of the `VALENT' [`VALENTW'] structures are
          measured as number of bytes.

    RegQueryValueW
    `RegQueryValueW( $hKey, $swSubKey, $oswValueData, $iolValueData )'
          `$swSubKey' and `$oswValueData' are UNICODE.  Note that
          `$iolValueData' is measured as number of bytes.

    RegQueryValueExW
    `RegQueryValueExW( $hKey, $swName, $pNull, $ouType, $opData, $iolData )'
          `$swName' is UNICODE.

          `$opData' is UNICODE if `$ouType' is REG_SZ, REG_EXPAND_SZ, or
          REG_MULTI_SZ.  Note that `$iolData' is measured as number of
          bytes even in these cases.

    RegReplaceKeyW
    `RegReplaceKeyW( $hKey, $swSubKey, $swNewFile, $swOldFile )'
          `$swSubKey', `$swNewFile', and `$swOldFile' are UNICODE.

    RegRestoreKeyW
    `RegRestoreKeyW( $hKey, $swFileName, $uFlags )'
          `$swFileName' is UNICODE.

    RegSaveKeyW
    `RegSaveKeyW( $hKey, $swFileName, $pSecAttr )'
          `$swFileName' is UNICODE.

    RegSetValueW
    `RegSetValueW( $hKey, $swSubKey, $uType, $swValueData, $lValueData )'
          `$swSubKey' and `$swValueData' are UNICODE.  Note that
          `$lValueData' is measured as number of bytes even though
          `$swValueData' is always UNICODE.

    RegSetValueExW
    `RegSetValueExW( $hKey, $swName, $uZero, $uType, $pData, $lData )'
          `$swName' is UNICODE.

          `$pData' is UNICODE if `$uType' is REG_SZ, REG_EXPAND_SZ, or
          REG_MULTI_SZ.  Note that `$lData' is measured as number of bytes
          even in these cases.

    RegUnLoadKeyW
    `RegUnLoadKeyW( $hKey, $swSubKey )'
          `$swSubKey' is UNICODE.

    :HKEY_
          All `HKEY_*' constants:

               HKEY_CLASSES_ROOT	HKEY_CURRENT_CONFIG	HKEY_CURRENT_USER
               HKEY_DYN_DATA		HKEY_LOCAL_MACHINE	HKEY_PERFORMANCE_DATA
               HKEY_USERS

    :KEY_
          All `KEY_*' constants:

               KEY_QUERY_VALUE		KEY_SET_VALUE		KEY_CREATE_SUB_KEY
               KEY_ENUMERATE_SUB_KEYS	KEY_NOTIFY		KEY_CREATE_LINK
               KEY_READ		KEY_WRITE		KEY_EXECUTE
               KEY_ALL_ACCESS

    :REG_
          All `REG_*' constants:

               REG_CREATED_NEW_KEY		REG_OPENED_EXISTING_KEY

               REG_LEGAL_CHANGE_FILTER		REG_NOTIFY_CHANGE_ATTRIBUTES
               REG_NOTIFY_CHANGE_NAME		REG_NOTIFY_CHANGE_LAST_SET
               REG_NOTIFY_CHANGE_SECURITY	REG_LEGAL_OPTION

               REG_OPTION_BACKUP_RESTORE	REG_OPTION_CREATE_LINK
               REG_OPTION_NON_VOLATILE		REG_OPTION_OPEN_LINK
               REG_OPTION_RESERVED		REG_OPTION_VOLATILE

               REG_WHOLE_HIVE_VOLATILE		REG_REFRESH_HIVE
               REG_NO_LAZY_FLUSH

               REG_NONE			REG_SZ
               REG_EXPAND_SZ			REG_BINARY
               REG_DWORD			REG_DWORD_LITTLE_ENDIAN
               REG_DWORD_BIG_ENDIAN		REG_LINK
               REG_MULTI_SZ			REG_RESOURCE_LIST
               REG_FULL_RESOURCE_DESCRIPTOR	REG_RESOURCE_REQUIREMENTS_LIST

    :ALL
          All of the above.

    :SE_
          The strings for the following privilege names:

               SE_ASSIGNPRIMARYTOKEN_NAME	SE_AUDIT_NAME
               SE_BACKUP_NAME			SE_CHANGE_NOTIFY_NAME
               SE_CREATE_PAGEFILE_NAME		SE_CREATE_PERMANENT_NAME
               SE_CREATE_TOKEN_NAME		SE_DEBUG_NAME
               SE_INCREASE_QUOTA_NAME		SE_INC_BASE_PRIORITY_NAME
               SE_LOAD_DRIVER_NAME		SE_LOCK_MEMORY_NAME
               SE_MACHINE_ACCOUNT_NAME		SE_PROF_SINGLE_PROCESS_NAME
               SE_REMOTE_SHUTDOWN_NAME		SE_RESTORE_NAME
               SE_SECURITY_NAME		SE_SHUTDOWN_NAME
               SE_SYSTEMTIME_NAME		SE_SYSTEM_ENVIRONMENT_NAME
               SE_SYSTEM_PROFILE_NAME		SE_TAKE_OWNERSHIP_NAME
               SE_TCB_NAME			SE_UNSOLICITED_INPUT_NAME

          It can be difficult to successfully build this module in a way
          that makes these constants available.  So some builds of this
          module may not make them available.  For such builds, trying to
          export any of these constants will cause a fatal error.  For
          this reason, none of these symbols are currently included in the
          `":ALL"' grouping.

The Win32API:: heirarchy
------------------------

   This and the other Win32API:: modules are meant to expose the nearly
raw API calls so they can be used from Perl code in any way they might be
used from C code.  This provides the following advantages:

Many modules can be written by people that don't have a C compiler.
Encourages more module code to be written in Perl [not C].
     Perl code is often much easier to inspect, debug, customize, and
     enhance than XS code.

Allows those already familiar with the Win32 API to get off to a quick start.
Provides an interactive tool for exploring even obscure details of the Win32 API.
     It can be very useful to interactively explore ad-hoc calls into
     parts of the Win32 API using:

          perl -de 0

Ensures that native Win32 data structures can be used.
     This allows maximum efficiency.  It also allows data from one module
     [for example, time or security information from the
     `Win32API::Registry' or `Win32API::File' modules] to be used with
     other modules [for example, `Win32API::Time' and `Win32API::SecDesc'].

Provides a single version of the XS interface to each API call where improvements can be collected.
Buffer sizes
------------

   For each parameter that specifies a buffer size, a value of 0 can be
passed.  For parameter that are pointers to buffer sizes, you can also
pass in NULL by specifying an empty list reference, [].  Both of these
cases will ensure that the variable has E<some> buffer space allocated to
it and pass in that buffer's allocated size.  Many of the calls indicate,
via `ERROR_MORE_DATA', that the buffer size was not sufficient and the
`Registry.xs' code will automatically enlarge the buffer to the required
size and repeat the call.

   Numeric buffer sizes are used as minimum initial sizes for the buffers.
The larger of this size and the size of space already allocated to the
scalar will be passed to the underlying routine.  If that size was
insufficient, and the underlying call provides an easy method for
determining the needed buffer size, then the buffer will be enlarged and
the call repeated as above.

   The underlying calls define buffer size parameter as unsigned, so
negative buffer sizes are treated as very large positive buffer sizes
which usually cause `malloc()' to fail.

   To force the `Registry.xs' code to pass in a specific value for a
buffer size, preceed the size with an equals sign via `"=".'.  Buffer
sizes that are passed in as strings starting with an equals sign will have
the equal sign stripped and the remainder of the string interpretted as a
number [via C's `strtoul()' using only base 10] which will be passed to
the underlying routine [even if the allocated buffer is actually larger].
The `Registry.xs' code will enlarge the buffer to the specified size, if
needed, but will not enlarge the buffer based on the underlying routine
requesting more space.

   Some Reg*() calls may not currently set the buffer size when they
return `ERROR_MORE_DATA'.  But some that are not documented as doing so,
currently do so anyway.  So the code assumes that any routine E<might> do
this and resizes any buffers and repeats the call.   We hope that
eventually all routines will provide this feature.

   When you use [] for a buffer size, you can still find the length of the
data returned by using `length($buffer)'.  Note that this length will be
in bytes while a few of the buffer sizes would have been in units of wide
characters.

   Note that the RegQueryValueEx*() and RegEnumValue*() calls will trim
the trailing `'\0'' [if present] from the returned data values of type
REG_SZ or REG_EXPAND_SZ but only if the value data length parameter is
omitted [or specified as []].

   The RegSetValueEx*() calls will add a trailing `'\0'' [if missing] to
the supplied data values of type REG_SZ and REG_EXPAND_SZ but only if the
value data length parameter is omitted [or specified as 0].

Hungarian Notation
------------------

   The following abbreviations are used at the start of each parameter
name to hint at aspects of how the parameter is used.  The prefix is
always in lower case and followed by a capital letter that starts the
descriptive part of the parameter name.  Several of the following
abbreviations can be combined into a single prefix.

   Probably not all of these prefix notations are used by this module.
This document section may be included in any `Win32API' module and so
covers some notations not used by this specific module.

s
     A string.  In C, a `'\0''-terminated `char *'.  In Perl, just a
     string except that it will be truncated at the first `"\0"', if it
     contains one.

sw
     A wide [UNICODE] string.  In C, a `L'\0''-terminated `WCHAR *'.  In
     Perl, a string that contains UNICODE data.  You can convert a string
     to UNICODE in Perl via:

          $string= "This is an example string";
          $unicode= pack( "S*", unpack("C*",$string), 0 );

     Note how `, 0' above causes an explicit `L'\0'' to be added since
     Perl's implicit `'\0'' that it puts after each of its strings is not
     wide enough to terminate a UNICODE string.  So UNICODE strings are
     different than regular strings in that the Perl version of a regular
     string will not include the trialing `'\0'' while the Perl version of
     a UNICODE string must include the trailing `L'\0''.

     If a UNICODE string contains no non-ASCII characters, then you can
     convert it back into a normal string via:

          $string= pack( "C*", unpack("S*",$unicode) );
          $string =~ s/\0$//;

p
     A pointer to some buffer [usually containing some `struct'].  In C, a
     `void *' or some other pointer type.  In Perl, a string that is
     usually manipulated using pack and unpack.  The "p" is usually
     followed by more prefix character(s) to indicate what type of data is
     stored in the bufffer.

a
     A packed array.  In C, an array [usually of `struct's].  In Perl, a
     string containing the packed data.  The "a" is usually followed by
     more prefix character(s) to indicate the data type of the elements.

     These packed arrays are also called "vectors" in places to avoid
     confusion with Perl arrays.

n
     A generic number.   In C, any of the integer or floating point data
     types.  In Perl, a number; either an integer, unsigned, or double
     [IV, UV, or NV, respectively].  Usually an integer.

iv
     A signed integral value.  In C, any of the signed integer data types.
     In Perl, an integer [IV].

u
     An unsigned integral value.  In C, any of the unsigned integer data
     types.  In Perl, an unsigned integer [UV].

d
     A floating-point number.  In C, a float or double or, perhaps, a
     `long double'.  In Perl, a double-precision floating-point number
     [NV].

b
     A Boolean value.  In C, any integer data type, though usually via a
     type alias of `bool' or `BOOL', containing either a 0 [false] or
     non-zero [true] value.  In Perl, a scalar containing a Boolean value
     [0, "", or undef for "false" and anything else for "true"].

c
     A count of items.  In C, any integer data type.  In Perl, an unsigned
     integer [UV].  Usually used in conjunction with a "vector" parameter
     [see `' in this node above] to indicate the number of elements.

l
     A length [in bytes].  In C, any integer data type.  In Perl, an
     unsigned integer [UV].  Usually used in conjunction with a "string"
     or "pointer" parameter [see `' in this node and `' in this node
     above] to indicate the buffer size or the size of the value stored in
     the buffer.

     For strings, there is no general rule as to whether the trailing
     `'\0'' is included in such sizes.  For this reason, the `Win32API'
     modules follow the Perl rule of always allocating one extra byte and
     reporting buffer sizes as being one smaller than allocated in case
     the `'\0'' is not included in the size.

lw
     A length measured as number of UNICODE characters.  In C, a count of
     `WCHAR's.  In Perl, an unsigned integer [UV] counting "shorts" [see
     "s" and "S" in pack and unpack].

     For UNICODE strings, the trailing `L'\0'' may or may not be included
     in a length so, again, we always allocate extra room for one and
     don't report that extra space.

h
     A handle.  In C, a `HANDLE' or more-specific handle data type.  In
     Perl, an unsigned integer [UV].  In C, these handles are often
     actually some type of pointer, but Perl just treats them as opaque
     numbers, as it should.  This prefix is also used for other pointers
     that are treated as integers in Perl code.

r
     A record.  In C, almost always a `struct' or perhaps union.  Note
     that C `struct's are rarely passed by value so the "r" is almost
     always preceeded by a "p" or "a" [see `' in this node and `' in this
     node above].  For the very rare unadorned "r", Perl stores the record
     in the same way as a "pr", that is, in a string.  For the very rare
     case where Perl explicitly stores a pointer to the `struct' rather
     than storing the `struct' directly in a Perl string, the prefix "pp"
     or "ppr" or even "par" is used.

sv
rv
hv
av
cv
     A Perl data type.  Respectively, a scalar value [SV], a reference
     [RV] [usually to a scalar], a hash [HV], a Perl array [AV], or a Perl
     code reference [PVCV].  For the "hv", "av", and "cv" prefixes, a
     leading "rv" is usually assumed.  For a parameter to an XS subroutine,
     a prefix of "sv" means the parameter is a scalar and so may be a
     string or a number [or undef] or even both at the same time.  So "sv"
     doesn't imply a leading "rv".

Input or Output
     Whether a parameter is for input data, output data, or both is usually
     not reflected by the data type prefix.  In cases where this is not
     obvious nor reflected in the parameter name proper, we may use the
     following in front of the data type prefix.

    i
          An input parameter given to the API [usually omitted].

    o
          An output-only parameter taken from the API.  You should not get
          a warning if such a parameter is undef when you pass it into the
          function.  You should get an error if such a parameter is
          read-only.  You can [usually] pass in [] for such a parameter to
          have the parameter silently ignored.

          The output may be written directly into the Perl variable passed
          to the subroutine, the same way the buffer parameter to Perl's
          `sysread()'.  This method is often avoided in Perl because the
          call then lacks any visual cue that some parameters are being
          overwritten.   But this method closely matches the C API which is
          what we are trying to do.

    io
          Input given to the API then overwritten with output taken from
          the API.  You should get a warning [if -w is in effect] if such a
          parameter is undef when you pass it into the function [unless it
          is a buffer or buffer length parameter].  If the value is
          read-only, then [for most parameters] the output is silently not
          written.  This is because it is often convenient to pass in
          read-only constants for many such parameters.  You can also
          usually pass in [] for such parameters.

pp
ppr
par
pap
     These are just unusual combinations of prefix characters described
     above.

     For each, a pointer is stored in a [4-byte] Perl string.  You can
     usually use `unpack "P"' to access the real data from Perl.

     For "ppr" [and often for "pp"], the pointer points directly at a C
     `struct'.  For "par", the pointer points to the first element of a C
     [packed] array of `struct's.  For "pap", the pointer points to a C
     [packed] array of pointers to other things.

ap
     Here we have a list of pointers packed into a single Perl string.

BUGS
====

   The old ActiveState ports of Perl for Win32 [but not, ActivePerl, the
ActiveState distributions of standard Perl 5.004 and beyond] do not support
the tools for building extensions and so do not support this extension.

   No routines are provided for using the data returned in the `FILETIME'
buffers.  Those are in the `Win32API::Time' module.

   No routines are provided for dealing with UNICODE data effectively.
See `' in this node above for some simple-minded UNICODE methods.

   Parts of the module test will fail if used on a version of Perl that
does not yet set $^E based on `GetLastError()'.

   On NT 4.0 [at least], the RegEnum*() calls do not set the required
buffer sizes when returning `ERROR_MORE_DATA' so this module will not grow
the buffers in such cases.  `Win32::TieRegistry' overcomes this by using
values from `RegQueryInfoKey()' for buffer sizes in RegEnum* calls.

   On NT 4.0 [at least], `RegQueryInfoKey()' on `HKEY_PERFORMANCE_DATA'
never succeeds.  Also, `RegQueryValueEx()' on `HKEY_PERFORMANCE_DATA'
never returns the required buffer size.  To access `HKEY_PERFORMANCE_DATA'
you will need to keep growing the data buffer until the call succeeds.

   Because `goto &subroutine' seems to be buggy under Win32 Perl, it is
not used in the stubs in `Registry.pm'.

AUTHOR
======

   Tye McQueen, tye@metronet.com, http://www.metronet.com/~tye/.

SEE ALSO
========

See Win32/TieRegistry,

`Win32::Registry' in this node

A framework for building wizard-style applications.
***************************************************

NAME
====

   Wizard - A framework for building wizard-style applications.

SYNOPSIS
========

     # Create a new Wizard
     use Wizard ();
     my $wiz = Wizard->new(%attr);

     # Let the wizard create a form
     my $form = $wiz->Form(%attr);

     # Start the wizard, by running the form
     $wiz->Run($form);

DESCRIPTION
===========

   The Wizard package enables you to create simple input forms in the
style of Windows wizards and combine them into a complete application,
typically for system administration. The users input form is handled in a
single sub, the so-called action. Any action consists of 3 phases:

  1. Processing the input data.

  2. Saving the input data.

  3. Returning data describing the next input form.

        You typically only need to setup the actions, the Wizard system
should do anything else for you.

   The framework is based on the wizard object. Different wizard classes
are available, for example Form::Wiz::Shell for running the wizard within
a shell or Form::Wiz::HTML for running within a web browser.  See also
`Wizard::Shell(3)' in this node and `Wizard::HTML(3)' in this node

CLASS INTERFACE
===============

   In all cases errors are handled by throwing Perl exceptions, thus we
won't talk about errors at all in what follows.

Creating a wizard
-----------------

     my $wiz = Wizard->new(\%attr);

   (Class method) The new method will create a wizard object for you.  It
receives a hash ref of attributes as arguments. Currently known attributes
are:

formClass
     The wizards form class. For example, the Wizard::Shell class will
     have Wizard::Form::Shell as form class. `Wizard::Form(3)' in this
     node.

Working with input forms
------------------------

     # Create a new form
     my $form = $wiz->Form(%attr);

     # Fetch the current form
     $form = $wiz->Form();

   (Instance methods) The Form method will create a new form for you. The
form is an instance of the wizards formClass, see above. There's always a
single form associated to the wizard: The previous form is removed by
creating the next one. The action returns a list of input elements that
will be used for creating the next form. `Wizard::Elem(3)' in this node.

Running the wizard
------------------

     $form = $wiz->Run($data);

   (Instance method) This method is running a single action. The action
will read input from $data (typically a CGI or Apache::Request object) by
calling its param method. The action returns a list of form elements that
will be used for creating the next form. This form will be methods return
value.

AUTHORS AND COPYRIGHT
=====================

   This module is

     Copyright (C) 1999     Jochen Wiedmann
                            Am Eisteich 9
                            72555 Metzingen
                            Germany

     Email: joe@ispsoft.de
     Phone: +49 7123 14887

     and     Amarendran R. Subramanian
             Grundstr. 32
             72810 Gomaringen
             Germany

     Email: amar@ispsoft.de
     Phone: +49 7072 920696

   All Rights Reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

Apache Menu
===========

   Beim Start des Apache Wizard Menues werden folgende Optionen zur
Verfuegung gestellt.

Host Menu
---------

   Hier werden Hosts konfiguriert (siehe Host Administration)

Apache Wizard Preferences
-------------------------

   Hier wird die globale Konfiguration mittels folgender Optionen
festgelegt:

apache_prefs_basedir Base Directory of Apache Wizard
     Verzeichnis in dem die Daten ueber Hosts, Server, etc...  abgelegt
     werden.

AUTHORS AND COPYRIGHT
=====================

   This module is

     Copyright (C) 1999     Jochen Wiedmann
                            Am Eisteich 9
                            72555 Metzingen
                            Germany

     Email: joe@ispsoft.de
     Phone: +49 7123 14887

     and     Amarendran R. Subramanian
             Grundstr. 32
             72810 Gomaringen
             Germany

     Email: amar@ispsoft.de
     Phone: +49 7072 920696

   All Rights Reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

Directory Menu
==============

   Hier werden die Verzeichnisse der virtuellen Webserver administriert.

Attribute eines Directory.
--------------------------

apache_directory_pathname Directory pathname
     Eindeutiger Pfad des Directory, relativ zum root Verzeichnis des
     dazugehoerigen virtuellen Webservers.

apache_directory_redirecturl Directory redirect url
     Falls das Verzeichnis ein redirect beschreiben soll, muessen Sie hier
     die Redirect-Url (Die Url worauf dieses Directory redirected wird)
     angeben.

apache_directory_user User who owns that directory
     Falls Sie keine Redirect-Url eingegeben haben, muessen Sie hier einen
     gueltigen User eingeben, der der Besitzer dieses Verzeichnis sein
     soll.

apache_directory_group Group that owns that directory
     Optionale Eingabe einer gueltigen Gruppe, der dieses Verzeichnis
     gehoert.

AUTHORS AND COPYRIGHT
=====================

   This module is

     Copyright (C) 1999     Jochen Wiedmann
                            Am Eisteich 9
                            72555 Metzingen
                            Germany

     Email: joe@ispsoft.de
     Phone: +49 7123 14887

     and     Amarendran R. Subramanian
             Grundstr. 32
             72810 Gomaringen
             Germany

     Email: amar@ispsoft.de
     Phone: +49 7072 920696

   All Rights Reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

Host Menu
=========

   Die Administration der Hosts ist vom gleichen Ablauf wie die
Administration weiterer Punkte.

CreateHost
----------

   Attribute fuer den neuen Host eingeben. Informationen ueber die
Attribute befinden sich weiter unten. Danach erhalten sie folgende Auswahl

HostSave Save these settings
     Den neuen Host abspeichern

EditHost
--------

ModifyHost
----------

   Hier muessen Sie zuerst einen vorhanden Host auswaehlen, der geaendert
werden soll. Danach wird dieser geladen und kann mittels der Eingabemaske,
die auch zum Anlegen von Hosts verwendet wird, abgeandert und
anschliessend gespeichert werden.  Hier verhaelt sich bis auf die
Hostauswahl alles genau wie beim Anlegen von Hosts.

DeleteHost
----------

   Hier werden Sie mittels einer Auswahlliste gebeten eine Host
auszuwaehlen. Anschliessend wird dieser geladen und dessen Daten werden
angezeigt. Nun gibt es drei Moeglichkeiten fortzufahren.

Yes, delete it
     Den Host loeschen, aber das Datenverzeichnis in dem sich die alle
     Daten die zu diesem Host gehoeren, nicht loeschen.

Yes, delete it, including data directory
     Dasselbe wie oben, wobei aber das Datenverzeichnis auch geloescht
     wird.

Return to Host Menu/Top Menu
     Zu dem  Host Menu bzw. zu dem Anfangsmenue zurueckkehren ohne den
     Host oder dessen Datenverzeichnis zu loeschen.

Attribute eines Hosts
---------------------

apache_host_name short descriptive name
     Eindeutiger Name, der dem Host zugeordnet ist. Falls Sie einen neuen
     Host anlegen wollen der den selben Namen hat wie ein bereits
     vorhandener, wird ein Fehler ausgeloest.  Beispiel: wwwhost1

apache_host_descr informative description
     Beschreibung des Hosts.  Beispiel: My webserver machine

apache_host_arch architecture
     Die Host Architektur.  Beispiel: linux-i586

apache_host_ip DNS name or ip address
     Gueltige IP Adresse oder DNS name des Hosts. Falls eine ungueltiger
     DNS Name oder IP Adresse eingegeben wird, wird ein Fehler ausgeloest.
     Beispiel: iss12.neckar-alb.de

AUTHORS AND COPYRIGHT
=====================

   This module is

     Copyright (C) 1999     Jochen Wiedmann
                            Am Eisteich 9
                            72555 Metzingen
                            Germany

     Email: joe@ispsoft.de
     Phone: +49 7123 14887

     and     Amarendran R. Subramanian
             Grundstr. 32
             72810 Gomaringen
             Germany

     Email: amar@ispsoft.de
     Phone: +49 7072 920696

   All Rights Reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

Server Menu
===========

   Hier werden die WWW server konfiguriert. Beim Anlegen eines neuen
Servers wird automatisch ein Virtueller Server angelegt der den angelegten
WWW server beschreibt.  Beim anlegen des Virtuellen Severs wird
automatisch ein Directory angelegt, dass das Root Verzeichnis des
virtuellen Servers beschreibt. Naeheres in der Sektion VirtualServer Menu
und Directory Menu.  Im folgenden werden nur noch die Attribute
beschrieben.  Die Menupunkte und deren Funktion ist analog zum Host Menu.

Attribute eines Servers
-----------------------

apache_server_name Server descriptive name.
     Eindeutiger Name des Servers (analog zu Hosts)

apache_server_ip Server DNS name or IP adress
     DNS Name oder IP Adresse des Servers, analog zu Hosts.

apache_server_vserver_root Default directory for VirtualServers
     Standardprefix fuer die Rootverzeichnisse der virtuellen Sever. Zum
     Beispiel '/usr/local/www'. Beim Anlegen eines virtuellen Servers
     'www.test.de' wird dann als root verzeichnis
     '/usr/local/www/www.test.de' vorgeschlagen..  Naeheres finden Sie in
     der Sektion VirtualServer Menue.

apache_server_admin Server Administrator
     Email adresse des Webmasters des Webservers.

apache_server_http_port HTTP
     Default HTTP port der als Standard fuer die virtuellen Server
     verwendet wird.

apache_server_https_port HTTP, HTTPS Port
     Default HTTPS Port der als Standard fuer die virtuellen Server
     verwendet wird.

AUTHORS AND COPYRIGHT
=====================

   This module is

     Copyright (C) 1999     Jochen Wiedmann
                            Am Eisteich 9
                            72555 Metzingen
                            Germany

     Email: joe@ispsoft.de
     Phone: +49 7123 14887

     and     Amarendran R. Subramanian
             Grundstr. 32
             72810 Gomaringen
             Germany

     Email: amar@ispsoft.de
     Phone: +49 7072 920696

   All Rights Reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

VirtualServer Menu
==================

   Hier werden die virtuellen Webserver administriert. Die Menuoptionen
und der Verlauf ist analog zu dem Server Menu. Lediglich die
Attributseingabe erfolgt in zwei Schritten, wobei nach dem ersten Schritt
abgebrochen werden kann. Beim Anlegen eines neuen virtuellen Webservers
wird automatisch ein Verzeichnis angelegt, dass das root Verzeichnis des
angelegten virtuellen Webservers entspricht, Naehres finden sie im
Abschnitt Directory Menu.

Attribute eines virtuellen Webservers
-------------------------------------

apache_virtualserver_name DNS name or IP address
     Gueltiger DNS name oder IP Adresse (siehe analoge Attribute fuer
     Hosts, Server)

apache_virtualserver_http_mode Server type
     Hier koennen Sie den Servertyp einstellen, die Auswahl besteht aus
     'http', 'https' oder 'both'. Falls 'https' oder 'both' ausgewaehlt
     wird, hat das zur Folge das als HTTP version HTTP/1.0 automatisch
     eingestellt wird. Falls 'http' ausgewaehlt wird hat man die
     Moeglichkeit zwischen HTTP/1.0 oder HTTP/1.1 auszuwaehlen.

apache_virtualserver_root Virtual WWW server root directory
     Das root Verzeichnis des virtuellen Webservers.

apache_virtualserver_admin Virtual WWW server admin
     Email adresse des Webmasters.

apache_virtualserver_http_port HTTP port
     HTTP Port auf den der virtuelle Server hoeren soll, falls nichts
     eingegeben wird, wird der des Servers, zu dem dieser virtuelle
     Webserver gehoert, verwendet.

apache_virtualserver_https_port HTTPS port
     Nur falls 'https' oder 'both' als 'Server type' ausgewaehlt wurde.
     Analog zu HTTP port.

apache_virtualserver_http_version HTTP version
     Nur falls 'http' als 'Server type' ausgewaehlt wurde.

apache_virtualserver_interface Virtual WWW server interface number
     Eine eindeutige interface Nummer (Ganzzahl) des virtuellen
     Webservers. Die Eingabe kann leergelassen werden falls 'http' als
     'Server type' und HTTP/1.1 als 'HTTP version' ausgwaehlt wurde.

apache_virtualserver_DirectoryIndex DirectoryIndex, Options
     Analog zu den entsprechenden Apache Konfigurationsoptionen (wird mit
     sinvollen defaults vorbelegt)

apache_virtualserver_enable_pcgi PCGI/EP/SSI
     Hier koennen Sie einstellen ob der virtuelle Webserver PCGI, EP oder
     SSI (Server Side Includes) unterstuetzen soll.

AUTHORS AND COPYRIGHT
=====================

   This module is

     Copyright (C) 1999     Jochen Wiedmann
                            Am Eisteich 9
                            72555 Metzingen
                            Germany

     Email: joe@ispsoft.de
     Phone: +49 7123 14887

     and     Amarendran R. Subramanian
             Grundstr. 32
             72810 Gomaringen
             Germany

     Email: amar@ispsoft.de
     Phone: +49 7072 920696

   All Rights Reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

A subclass for running Wizard applications in HTML::EP.
*******************************************************

NAME
====

   Wizard::HTML - A subclass for running Wizard applications in HTML::EP.

SYNOPSIS
========

     # Create a new HTML wizard
     use Wizard::HTML;
     my $wiz = Wizard::Shell->new('form' => $form, 'ep' => $ep)

DESCRIPTION
===========

   The HTML wizard is a subclass of Wizard, that is used by HTML::EP sites.
The input will be read from the associated CGI-Object and the output as
HTML code will be built by the elements of the form.

AUTHORS AND COPYRIGHT
=====================

   This module is

     Copyright (C) 1999     Jochen Wiedmann
                            Am Eisteich 9
                            72555 Metzingen
                            Germany

     Email: joe@ispsoft.de
     Phone: +49 7123 14887

     and     Amarendran R. Subramanian
             Grundstr. 32
             72810 Gomaringen
             Germany

     Email: amar@ispsoft.de
     Phone: +49 7072 920696

   All Rights Reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

Administration interface for your LDAP server
*********************************************

NAME
====

   Wizard::LDAP - Administration interface for your LDAP server

SYNOPSIS
========

     # From the shell:
     ldapWizard

     # Or, from the WWW:
     <a href="ldap.ep">LDAP administration</a>

DESCRIPTION
===========

   This is a package for administration of an LDAP server. It allows to
feed users, hosts and networks into the server.

INSTALLATION
============

   First of all, you have to install the prerequisites. There are lots of:

An LDAP Server
     You need some LDAP server. We are using the OpenLDAP server, see

          http://www.openldap.org/

     In theory any other LDAP server should do, but the servers
     configuration might be different.

     A source RPM for Red Hat Linux is available on demand.

     To configure the LDAP server, edit the file `topics.ldif' from the
     distribution. Currently it looks like

          dc=ispsoft, dc=de
          objectclass: organization
          o: My Organization Name

          dn: topic=user, dc=ispsoft, dc=de
          name: user
          objectclass: topic

          dn: topic=net, dc=ispsoft, dc=de
          name: net
          objectclass: topic

     Change "dc=ispsoft, dc=de" and the organization name to reflect your
     local settings. For example, if you are using the mail domain
     "mycompany.com", then you might choose

          dc=mycompany, dc=com

     Import the file into your LDAP server by using the command

          ldif2ldbm -i topics.ldif

     (The above command will trash an existing LDAP database! Use ldapadd
     if you want to avoid this.)

     Append the files `slapd.at.conf.APPEND' and `slapd.oc.conf.APPEND' to
     your `/etc/openldap/slapd.at.conf' and `/etc/openldap/slapd.oc.conf'
     and restart the OpenLDAP server.

IO::AtomicFile
     This is a Perl package for atomic operations on important files.

HTML::EP
     If you like to use the WWW administration interface, you need the
     embedded Perl system HTML::EP.

Wizard
     Another Perl module, available at the same place.

Convert::BER
Net::LDAP
     To talk to the LDAP server, we use Graham Barr's Net::LDAP package.
     It is written in 100% Perl, no underlying C library required.

Net::Netmask
     Used to determine conformance of host IP´s to a network.

   All the above packages are available on any CPAN mirror, for example

     ftp://ftp.funet.fi/pub/languages/perl/CPAN/authors/id

   or perhaps at the same place where you found this file. :-)

   Note that some of the packages have their own requirements. For
example, HTML::EP depends on libwww and the MailTools. If so, you will be
told while installing the modules. See below for the installation of the
Perl modules.

Installing the Perl modules
---------------------------

   Installing a Perl module is always the same:

     gzip -cd Wizard-LDAP-0.1005.tar.gz | tar xf -
     cd Wizard-LDAP-0.1005
     perl Makefile.PL
     make
     make test
     make install

   Alternatively you might try using the automatic installation that the
CPAN module offers you:

     perl -MCPAN -e shell
     install Bundle::Wizard::LDAP

   Note that some of the modules, in particular HTML::EP, need additional
configuration tasks, for example modifying the web servers configuration
files.

Some final tasks
----------------

   You have to create a directory `/etc/Wizard-LDAP' and make it owned by
the httpd user, so that CGI binaries can write into this directory.

   Copy the file `ldap.ep' and the file `gethelp.ep' from the Wizard
distribution into your web servers root directory. (I choose
`/home/httpd/html/admin/ldap.ep' on my Red Hat Linux box.)

   Point your browser too the corresponding location, for example

     http://localhost/admin/ldap.ep

   Start with modifying the preferences. See `THE LDAP-WIZARD PREFERENCES'
in this node.

THE LDAP-WIZARD PREFERENCES
===========================

   The system wide preferences are accessible via the web form ldap.ep.
The following items can be configured:

item_ldap_prefs_serverip
------------------------

   This is the IP address of the LDAP server being used, typically

     127.0.0.1.

   No default is set.

item_ldap_prefs_serverport
--------------------------

   Likewise, this is the LDAP servers port number. The default is

     389

item_ldap_prefs_adminDN
-----------------------

   This is the distinguished name to use for accessing the LDAP server as
root. No default is set. Example:

     cn=root, dc=ispsoft, dc=de

item_ldap_prefs_adminPassword
-----------------------------

   This is the password to use for binding to the LDAP server as root.
Currently the password *must* be stored in clear text. (This is subject to
change.)

item_ldap_prefs_nextuid
-----------------------

   This the next numeric UID, that will assigned to a new user. By default
the value

     500

   is choosen. The value is incremented with any new user, so after
inserting the next users it will be 501, 502, 503 and so on. You typically
should reserve some block of Unix UID's for users managed by the LDAP
server.

item_ldap_prefs_gid
-------------------

   This is the numeric GID, that your LDAP users will have under Unix.
The default is

     500

item_ldap_prefs_home
--------------------

   This is the prefix to use for the users home directories, for example

     /home

   (the default). The users login names will be appended.

item_ldap_prefs_userbase
------------------------

   This is a suffix for constructing the distinguished names of your
users. Example:

     dc=ispsoft, dc=de

item_ldap_prefs_netbase
-----------------------

   A similar suffix for constructing the distinguished names of nets.
Example:

     dc=ispsoft, dc=de

item_ldap_prefs_domain
----------------------

   The mail domain appended to unclassified email adresses. For example,
if you have a user "joe" and the domain is "ispsoft.de", then its email
adress will be joe@ispsoft.de.

item_ldap_prefs_prefschange
---------------------------

   If you enter a shell command here, then this command will be launched
after any change of the preferences. Example:

     /usr/bin/ldapAdmin --prefs

item_ldap_prefs_hostchange
--------------------------

   This is a similar shell command that will be called after hosts have
changed. Example:

     /usr/bin/ldapAdmin --hosts

item_ldap_prefs_netchange
-------------------------

   A shell command to issue after network definitions have changed.
Example:

     /usr/bin/ldapAdmin --nets

item_ldap_prefs_userchange_new
------------------------------

   This is a special case of the command for changing users. If defined, it
will be issued after a user was created. The users name will be appended
as the last argument. If not defined, the above and more generic command
will be executed.

item_ldap_prefs_userchange_modify
---------------------------------

   Similar to item_ldap_prefs_userchange_new, but for modified users.
Again, the users name will be appended as a last argument.

item_ldap_prefs_userchange_delete
---------------------------------

   Finally a shell command being executed after a user has been deleted.
The users name will be appended as a last argument.

AUTHORS AND COPYRIGHT
=====================

   This module is

     Copyright (C) 1999     Jochen Wiedmann
                            Am Eisteich 9
                            72555 Metzingen
                            Germany

     Email: joe@ispsoft.de

     and     Amarendran R. Subramanian
             Grundstr. 32
             72810 Gomaringen
             Germany

     Email: amar@ispsoft.de

   All Rights Reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SEE ALSO
========

   See Wizard, `ldapWizard' in this node, see HTML/EP,
see Net/LDAP,

A base class for implementing users in the LDAP wizard
******************************************************

NAME
====

   Wizard::LDAP::User - A base class for implementing users in the LDAP
wizard

SYNOPSIS
========

     # From the shell:
     ldapWizard

     # Or, from the WWW:
     <a href="ldap.ep">LDAP administration</a>

     # Follow the "User menu"

DESCRIPTION
===========

   This package implements the handling of user objects in the LDAP server.
It is part of the LDAP wizard.

CREATING OR EDITING USERS
=========================

   The following items can be edited in the user window:

item_ldap_user_uid
------------------

   This is the users login name, for example

     joe

   You should restrict login names to 8 characters.

item_ldap_user_userpassword
---------------------------

   This is the users password. You *must* fill in a password.

item_ldap_user_cn
-----------------

   This is the users real name, for example

     Jochen Wiedmann

item_ldap_user_description
--------------------------

   This is a single-line description of the user.

item_ldap_user_mail
-------------------

   This is the users email adress, for example

     joe@ispsoft.de

   You may omit the domain part in which case the default domain from the
preferences will automatically be added.

item_ldap_user_mailforward
--------------------------

   If mail for the user must not be stored locally, but forwarded to an
external email account, then you have to fill in this field, the external
email address.

item_ldap_user_mailforwardtype
------------------------------

   This select box determines, when email is being forwarded. It is
ignored, if the mailforward (see above) is empty.

   The default is to forward mails always (in other words: Immediately).
You may however choose to wait 1-5 days before forwarding email.  The
latter option requires support from your mailserver, for example by a cron
job that takes care of forwarding.

item_ldap_user_pop3box
----------------------

   If the user has an external POP3 boxes, you may insert them here, for
example

     username@my.pop3.server

   The attribute is used by a cron job that is regularly mail from the
remote box. The mail is then forwarded to the user.

   This option requires support from your mailserver, for example by a cron
job.

item_ldap_user_pop3password
---------------------------

   Likewise, this is the password being used to fetch mail from the remote
POP3 box, if any.

item_ldap_user_status
---------------------

   By default users have a status of "mail": In other words, they may read
mail only. They may also have a status of "ftp", in which case they are
accepted to login via FTP or "admin", in which case they have a regular
shell account.

   The users status determines its login shell. The possible shells are

     /bin/mailonly
     /bin/ftp_mail
     /bin/bash

AUTHORS AND COPYRIGHT
=====================

   This module is

     Copyright (C) 1999     Jochen Wiedmann
                            Am Eisteich 9
                            72555 Metzingen
                            Germany

     Email: joe@ispsoft.de

     and     Amarendran R. Subramanian
             Grundstr. 32
             72810 Gomaringen
             Germany

     Email: amar@ispsoft.de

   All Rights Reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SEE ALSO
========

   See Wizard, `ldapWizard' in this node, see HTML/EP,
see Net/LDAP,

A package for automatically saved objects.
******************************************

NAME
====

     Wizard::SaveAble - A package for automatically saved objects.

SYNOPSIS
========

     # Tell a SaveAble object that it's modified
     $obj->Modified(1);

     # Tell the SaveAble object to store itself back to disk
     $obj->Store();

DESCRIPTION
===========

   An object of the class Wizard::SaveAble is something that knows whether
it has to be saved or not. To that end it offers methods like *Modified*
and Store.

CLASS INTERFACE
===============

   All methods are throwing a Perl exception in case of errors.

Constructors
------------

     # Create an empty SaveAble object and associate a file name to it.
     my $obj = Wizard::SaveAble->new('file' => $file);

     # Load a SaveAble object from a file.
     my $obj = Wizard::SaveAble->new($file);

     # Same thing, but creating an empty object if $file doesn't exist
     my $obj = Wizard::SaveAble->new('file' => $file, 'load' => 1);

   (Class method) There are two possible constructors for the
*Wizard::SaveAble* class: The first is creating an empty object, you
typically use a subclass of *Wizard::SaveAble* here. The most important
attribute is the file name where the object should later be stored.

   The other constructor is loading an already existing object from a file.
The object is automatically blessed into the same class again, typically a
subclass of Wizard::SaveAble.

Setting and Querying an objects status
--------------------------------------

     # Tell an object that it's modified
     $obj->Modified(1);
     # Query whether an object is modified
     $modified = $obj->Modified()

   (Instance methods) The *Modified* method is used to determine whether an
object needs to be saved or not.

Setting and Querying an objects file name
-----------------------------------------

     # Set the objects associated file
     $obj->File($file);
     # Query the objects associated file
     $file = $obj->File();

   (Instance methods) The *Modified* method is used to determine whether an
object needs to be saved or not.

Storing an object to disk
-------------------------

     $obj->Store();

   (Instance Method) The object is stored back to disk into the file that
was fixed within the constructor.

AUTHORS AND COPYRIGHT
=====================

   This module is

     Copyright (C) 1999     Jochen Wiedmann
                            Am Eisteich 9
                            72555 Metzingen
                            Germany

     Email: joe@ispsoft.de
     Phone: +49 7123 14887

     and     Amarendran R. Subramanian
             Grundstr. 32
             72810 Gomaringen
             Germany

     Email: amar@ispsoft.de
     Phone: +49 7072 920696

   All Rights Reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SEE ALSO
========

   `Wizard(3)' in this node, `Wizard::State(3)' in this node

A package for automatically saved objects,     that are stored in a LDAP server's directory structure.
******************************************************************************************************

NAME
====

     Wizard::SaveAble::LDAP - A package for automatically saved objects,
     that are stored in a LDAP server's directory structure.

SYNOPSIS
========

DESCRIPTION
===========

AUTHORS AND COPYRIGHT
=====================

   This module is

     Copyright (C) 1999     Jochen Wiedmann
                            Am Eisteich 9
                            72555 Metzingen
                            Germany

     Email: joe@ispsoft.de
     Phone: +49 7123 14887

     and     Amarendran R. Subramanian
             Grundstr. 32
             72810 Gomaringen
             Germany

     Email: amar@ispsoft.de
     Phone: +49 7072 920696

   All Rights Reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SEE ALSO
========

   `Wizard::SaveAble(3)' in this node, `Wizard(3)' in this node,
`Wizard::State(3)' in this node

AUTHORS AND COPYRIGHT
=====================

   This module is

     Copyright (C) 1999     Jochen Wiedmann
                            Am Eisteich 9
                            72555 Metzingen
                            Germany

     Email: joe@ispsoft.de
     Phone: +49 7123 14887

     and     Amarendran R. Subramanian
             Grundstr. 32
             72810 Gomaringen
             Germany

     Email: amar@ispsoft.de
     Phone: +49 7072 920696

   All Rights Reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

SEE ALSO
========

   `Wizard(3)' in this node, `Wizard::State(3)' in this node

A subclass for running Wizard applications in a shell.
******************************************************

NAME
====

   Wizard::Shell - A subclass for running Wizard applications in a shell.

SYNOPSIS
========

     # Create a new shell wizard
     use Wizard::Shell;
     my $wiz = Wizard::Shell->new('form' => $form)

DESCRIPTION
===========

   The Shell wizard is a subclass of Wizard, that will run in a shell. The
input elements are written to stdout and the application will query you
for input.

AUTHORS AND COPYRIGHT
=====================

   This module is

     Copyright (C) 1999     Jochen Wiedmann
                            Am Eisteich 9
                            72555 Metzingen
                            Germany

     Email: joe@ispsoft.de
     Phone: +49 7123 14887

     and     Amarendran R. Subramanian
             Grundstr. 32
             72810 Gomaringen
             Germany

     Email: amar@ispsoft.de
     Phone: +49 7072 920696

   All Rights Reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

A class for storing the Wizard state.
*************************************

NAME
====

   Wizard::State - A class for storing the Wizard state.

SYNOPSIS
========

     # Create a new state
     my $state = Wizard::State->new();

DESCRIPTION
===========

   A Wizard can be interpreted as a very simple finite state machine. The
state is stored in ab object of class Wizard::State.

   A wizard state is typically a collection of Wizard::SaveAble objects.
For example, while configuring an Apache webserver, the state might have
attributes *prefs* (global preferences), host (the machine where the
webserver is running on) and server (the web server), each of them being a
SaveAble object. If the state's Store method is called, then the Store
method is called for any of these objects, as if they were a single object.

CLASS INTERFACE
===============

Constructor
-----------

     my $state = Wizard::State->new(\%attr)

   (Class Method) A new object is generated by calling its new method.
The object attributes are passed as a hash ref.

Terminating the application
---------------------------

     # Stopping the application
     $state->Running(0);

     # Querying whether the application is running
     $is_running = $state->Running();

   (Instance method) The state's Running method can be used to set or get
its running attribute. This attribute will be set to 0 for stopping the
application.

Storing a state
---------------

     # Storing a state temporarily; real SaveAble objects won't be
     # changed
     $state->Store($wiz);

     # Storing a state, including the SaveAble objects.
     $state->Store($wiz, 1);

AUTHORS AND COPYRIGHT
=====================

   This module is

     Copyright (C) 1999     Jochen Wiedmann
                            Am Eisteich 9
                            72555 Metzingen
                            Germany

     Email: joe@ispsoft.de
     Phone: +49 7123 14887

     and     Amarendran R. Subramanian
             Grundstr. 32
             72810 Gomaringen
             Germany

     Email: amar@ispsoft.de
     Phone: +49 7072 920696

   All Rights Reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

perl interface for noun relations of WordNet
********************************************

NAME
====

   WordNet::Query - perl interface for noun relations of WordNet

SYNOPSIS
========

   use WordNet::Query;

   print "Definition: ", &gloss ("car\#1"), "\n"; print "Synset: ", join
(", ", &syns ("car\#1")), "\n"; print "Hypernyms: ", join (", ", &hype
("car\#1")), "\n"; my @hypes = &hype("car\#1"); print "Hype Synset: ",
join (", ", &syns ($hypes[0])), "\n"; print "Hype-Hypernyms: ", join (",
", &hype ($hypes[0])), "\n"; print "Hyponyms: ", join (", ", &hypo
("car\#1")), "\n"; print "Meronyms: ", join (", ", &mero ("car\#1")), "\n";
print "Holonyms: ", join (", ", &holo ("roof\#2")), "\n";

   my @sensearray = &syns ("car");

   print "Num Senses: ", scalar @sensearray, "\n"; for (my $i=0; $i <
scalar @sensearray; $i++)   {     print $i+1, ") ", join (", ",
@{$sensearray[$i]}), "\n";   }

DESCRIPTION
===========

   The WordNet::Query perl module uses the 'wn' command-line program to
give a more palatable interface to the WordNet system.  Before the WordNet
perl module can be used, the WordNet C code must be installed on your
system and the 'wn' executable must be located in a directory that is part
of your PATH variable.

   When a query is performed, the module gathers data from 'wn', caches it
in memory and returns the requested information.  This mechanism makes
accessing WordNet information both efficient and more natural.  The
WordNet module requires little effort to traverse the various graphs of
information that are available in the WordNet system.

USAGE
=====

   The WordNet::Query module includes six exported functions, each of
which operate in two different modes.  The functions are:

   syns - Returns the synonym set of the provided word

   gloss - Returns the glossary definition of the provided word

   hype - Returns all hypernyms one level above the provided word

   hypo - Returns all hyponyms one level below the provided word

   mero - Returns all meronyms (part/member/substance of parents) of the
provided word

   holo - Returns all holonyms (part/member/substance of children) of the
provided word

   Each word accepts a single string that is the word to be queried.  In
the case that the exact sense of the word is known, that may be provided
in the string using the #S notation (where 'S' is the sense number).  For
example, 'car#1' refers to the first sense of the word 'car'.

   The output of each of these function depends on the format of the input
and is probably best described by the examples provided in the SYNOPSIS
section (above).  Generally, if a specific sense is provided (e.g.
'window#2'), then a list of strings is returned, one for each found
instance of the requested object.  In the case of the 'gloss' function, a
single item is returned (the single definition of that word).  If no
specific sense is provided, then an array of references is returned.  Each
reference will point to a list of strings, corresponding to the list that
would have been returned given a specific sense query.  The array of
referneces is ordered according to sense number, with sense #1 coming
first and the largest sense coming last.  i.e. add one to the array index
to get the sense number.

NOTES
=====

   Requires existence of WordNet command line program, 'wn'.  Currently
only allows WordNet queries on noun forms.

COPYRIGHT
=========

   Copyright 1999 Jason Rennie <jrennie@ai.mit.edu>  All rights reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1)

   http://www.cogsci.princeton.edu/~wn/

   http://www.ai.mit.edu/~jrennie/WordNet/

LOG
===

   $Log: Query.pm,v $ Revision 1.2  1999/09/15 19:53:28  jrennie add URL

   Revision 1.1  1999/09/15 13:27:54  jrennie new Query directory

   Revision 1.3  1999/07/22 21:12:25  jrennie add lower; lowercase
everything; put all verbosity output on STDERR

   Revision 1.2  1999/07/22 18:54:24  jrennie add hype_set, level
functions; have all parse_* functions return -1 if nothing is found; have
export functions return empty list or undef if nothing is found

   Revision 1.1  1999/07/21 20:08:51  jrennie rename from WordNet.pm;
modify initialization code to allow direct access to findtheinfo function;
in future, plan to rely soley on findtheinfo (no more command-line 'wn'
execution)

   Revision 1.5  1999/07/20 16:17:09  jrennie missing '>' in hash
dereference

   Revision 1.4  1999/07/19 14:19:53  jrennie use CVS for versioning
($VERSION line taken from CPAN suggestion)

   Revision 1.3  1999/07/19 14:09:19  jrennie various fixes in parsing of
'wn' output - particularly for special cases ('wn' does not have the
requested information)

   Revision 1.2  1999/07/16 19:51:06  jrennie deal with empty holo or mero
wn output (different from other queries)

   Revision 1.1.1.1  1999/07/16 18:27:02  jrennie move WordNet to separate
directory

   Revision 1.9  1999/07/16 18:04:12  jrennie bug fix--forgot to convert
synlist to hash

   Revision 1.8  1999/07/16 14:55:48  jrennie various clean up to make
"use strict" happy; do the right thing for top and bottom of tree

   Revision 1.7  1999/07/15 16:41:09  jrennie updated documentation

   Revision 1.6  1999/07/15 15:27:42  jrennie allow arbitrary sense
querying

   Revision 1.5  1999/07/14 22:38:48  jrennie complete rewrite; created
separate function for each aspect of wordnet (gloss, synset, hype, hypo,
mero, holo); still need to allow for querying w/o a specific sense

   Revision 1.4  1999/07/13 15:28:22  jrennie add example for ambiguous
mode

   Revision 1.3  1999/07/13 15:16:50  jrennie Follow guidelines in perl FAQ

   Revision 1.2  1999/07/13 13:48:09  jrennie quote query words passed to
wn

direct perl interface to WordNet database
*****************************************

NAME
====

   WordNet::QueryData - direct perl interface to WordNet database

SYNOPSIS
========

     use WordNet::QueryData;

     # Load index, mophological exclusion files (time-consuming process)
     my $wn = WordNet::QueryData->new ("/usr/local/dict", 1);

     # Synset of cat, sense #7
     print "Cat#7-> ", join (", ", $wn->query ("cat#n#7", "syns")), "\n";

     # Hyponyms of cat, sense #1 (house cat)
     print "Cat#1-> ", join (", ", $wn->query ("cat#n#1", "hypo")), "\n";

     # Senses of run as a verb
     print "Run->", join (", ", $wn->query ("run#v")), "\n";

     # Base form(s) of the verb 'lay down'
     print "lay down-> ", join (", ", $wn->valid_forms ("lay down#v")), "\n";

DESCRIPTION
===========

   WordNet::QueryData provides a direct interface to the WordNet database
files.  It requires the WordNet package
(http://www.cogsci.princeton.edu/~wn/).  It allows the user direct access
to the full WordNet semantic lexicon.  All parts of speech are supported
and access is generally very efficient because the index and morphical
exclusion tables are loaded at initialization.  Things are more or less
optimized for long sessions of queries--the 'new' invocation load the
entire index table and all of the morphological exclusions.  My PII/400
takes about 15 seconds to do this.  Memory usage is on the order of 18
Megs.  If I get enough requests, I may work on making this a less
demanding step.  However, once the index and morph. exc. files are loaded,
queries are very fast.

USAGE
=====

   To use the WordNet::QueryData module, incorporate the package with "use
WordNet::QueryData;".  Then, establish an instance of the package with "my
$wn = new WordNet::QueryData ("/usr/local/dict");".  If the WordNet dict
is not located in /usr/local/dict on your system, pass the correct
directory as the first argument of the function call.  You may pass a
second argument of 1 if you wish the module to print out progress and
verbose error messages.

   WordNet::QueryData is object-oriented.  You can establish multiple
instances simply by using 'new' multiple times, however, the only
practical use I can see for this is comparing data from different WordNet
versions.  I did the module OO-style because I had never done an OO perl
module, figured it was time to learn and thought it might make the code a
bit cleaner.

   The WordNet::QueryData object has two object functions that you might
want to use, 'valid_forms' and 'query'.  'query' gives you direct access
to the large set of WordNet relations.  It accepts a query string and a
relation.  The query string may be at one of three specification levels:

     1) WORD (e.g. dog)
     2) WORD#POS (e.g. house#noun)
     3) WORD#POS#SENSE (e.g. ghostly#adj#1)

   WORD is simply an english word.  Spaces should be used to separate
tokens (not underscores as is used in the WordNet database).  Case does
not matter.  In order to get a meaningful result, the word must exactly
match one of the words in the WordNet database files.  Use 'valid_forms'
to determine the form in which WordNet stores the word.

   POS is the part of speech.  Use 'n' for noun, 'v' for verb, 'a' for
adjective and 'r' for adverb.  You may also use full names and some
abbreviations (as above and in test.pl).  POS is optional for calls to
'query', and required for calls to 'valid_forms'.  SENSE is a number that
uniquely identifies the word sense.  You can 'query' using a WORD#POS form
to get a list of the word's senses for that part of speech.

   Executing 'query' with only a WORD will return a list of WORD#POS
strings.  Passing 'query' a WORD#POS will return a list of WORD#POS#SENSE
strings.  'query' calls of these forms do not return any information about
WordNet relations pertaining to WORD.  The third format, WORD#POS#SENSE,
requires a second argument, RELATION, which may be any of the strings used
by WordNet to designate a relation.  Here is a list of most (if not all)
of them:

     syns - synset words
     ants - antonyms
     hype - hypernyms
     hypo - hyponyms
     mmem - member meronyms
     msub - substance meronyms
     mprt - part meronyms
     mero - all meronyms
     hmem - member holonyms
     hsub - substance holonyms
     hprt - part holonyms
     holo - all holonyms
     attr - attributes (?)
     enta - entailment (verbs only)
     caus - cause (verbs only)
     also - also see
     vgrp - verb group (verbs only)
     sim - similar to (adjectives only)
     part - participle of verb (adjectives only)
     pert - pertainym (pertains to noun) (adjectives only)
     glos - word definition

   Such queries return a list of corresponding strings in the
WORD#POS#SENSE format.  In the case of 'syns', one string is returned for
each word that is part of the synset.  For other relations, one
WORD#POS#SENSE string is returned for each synset (you can map 'syns' on
to the returned array to get a full list of the words for a relation).  In
the case of relations like 'hype' and 'hypo', query returns only the
immediate hypernyms or hyponyms.  You can use 'query' recursively to get a
full hyper/hyponym tree.

   While 'query' requires that WORD exactly matches an entry in WordNet,
QueryData has functionality for determining the WordNet baseforms to which
a particular WORD may correpsond.  This functionality is encapsulated in
'valid_forms'.  After suppling 'valid_forms' with QUERY, a string in the
form WORD#POS, 'valid_forms' will return a list of WORD#POS strings which
are existing WordNet entries that are base forms of QUERY.  Normally, one
string will be returned.  An empty list will be returned if QUERY is not a
word that WordNet knows about.

   QueryData also has functionality for retrieving WordNet datafile
offsets (the unique number that identifies a word sense).  The function
'offset' accepts a fully-qualified word sense in the form WORD#POS#SENSE
and returns the corresponding numerical offset.  See WordNet documentation
for more information about this quantity.

NOTES
=====

   Requires access to WordNet database files (data.noun, index.noun, etc.)

COPYRIGHT
=========

   Copyright 2000 Jason Rennie <jrennie@ai.mit.edu>  All rights reserved.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SEE ALSO
========

   perl(1)

   http://www.cogsci.princeton.edu/~wn/

   http://www.ai.mit.edu/~jrennie/WordNet/

Perl module to read X11 authority files
***************************************

NAME
====

   X11::Auth - Perl module to read X11 authority files

SYNOPSIS
========

     require X11::Auth;
     $a = new X11::Auth;
     ($auth_type, $auth_data) = $a->get_by_host($host, $disp_num);

DESCRIPTION
===========

   This module is an approximate perl replacement for the libXau C library
and the xauth(1) program. It reads and interprets the files (usually
'~/.Xauthority') that hold authorization data used in connecting to X
servers. Since it was written mainly for the use of X11::Protocol, its
functionality is currently restricted to reading, not writing, of these
files.

METHODS
=======

new
---

     $auth = X11::Auth->new;
     $auth = X11::Auth->open($filename);

   Open an authority file, and create an object to handle it. The filename
will be taken from the XAUTHORITY environment variable, if present, or
'.Xauthority' in the user's home directory, or it may be overridden by an
argument. 'open' may be used as a synonym.

get_one
-------

     ($family, $host_addr, $display_num, $auth_name, $auth_data)
        = $auth->get_one;

   Read one entry from the file. Returns a null list at end of file.
$family is usually 'Internet' or 'Local', and $display_num can be any
string.

get_all
-------

     @auth_data = $auth->get_all;

   Read all of the entries in the file. Each member of the array returned
is an array ref similar to the list returned by get_one().

get_by_host
-----------

     ($auth_name, $auth_data)
        = $auth->get_by_host($host, $family, $display_num);

   Get authentication data for a connection of type $family to display
$display_num on $host. If $family is 'Internet', the host will be
translated into an appropriate address by gethostbyname().

COMPATIBILITY
=============

   The following table shows the (rough) correspondence between libXau
calls and X11::Auth methods:

     libXau                     X11::Auth
     ------                     ---------
     XauFileName                $ENV{XAUTHORITY}
                                || "$ENV{HOME}/.Xauthority"
     fopen(XauFileName(), "rb") $auth = new X11::Auth
     XauReadAuth                $auth->get_one
     XauWriteAuth
     XauGetAuthByAddr           $auth->get_by_host
     XauGetBestAuthByAddr
     XauLockAuth
     XauUnlockAuth
     XauDisposeAuth

AUTHOR
======

   Stephen McCamant <alias@mcs.com>

SEE ALSO
========

   `perl(1)' in this node, see X11/Protocol, `Xau(3)' in
this node, `xauth(1)' in this node, lib/Xau/README in the X11 source
distribution.

Perl module for names of X11 keysyms
************************************

NAME
====

   X11::Keysyms - Perl module for names of X11 keysyms

SYNOPSIS
========

     use X11::Keysyms '%Keysyms', qw(MISCELLANY XKB_KEYS LATIN1);
     %Keysyms_name = reverse %Keysyms;
     $ks = $Keysyms{'BackSpace'};
     $name = $Keysysms_name{$ks};

DESCRIPTION
===========

   This module exports a hash mapping the names of X11 keysyms, such as
'A' or 'Linefeed' or 'Hangul_J_YeorinHieuh', onto the numbers that
represent them. The first argument to 'use' is the name of the variable
the hash should be exported into, and the rest are names of subsets of the
keysysms to export: one or more of

     'MISCELLANY', 'XKB_KEYS', '3270', 'LATIN1', 'LATIN2',
     'LATIN3', 'LATIN4', 'KATAKANA', 'ARABIC', 'CYRILLIC',
     'GREEK', 'TECHNICAL', 'SPECIAL', 'PUBLISHING', 'APL',
     'HEBREW', 'THAI', 'KOREAN'.

   If this list is omitted, the list

     'MISCELLANY', 'XKB_KEYS', 'LATIN1', 'LATIN2', 'LATIN3',
     'LATIN4', 'GREEK'

   is used.

AUTHOR
======

   This module was generated semi-automatically by Stephen McCamant
(<alias@mcs.com>) from the header file 'X11/keysymdef.h', distributed by
the X Consortium.

SEE ALSO
========

   `perl(1)' in this node, see X11/Protocol, *X Window
System Protocol (X Version 11)*.

Perl module for the X Window System Protocol, version 11
********************************************************

NAME
====

   X11::Protocol - Perl module for the X Window System Protocol, version 11

SYNOPSIS
========

     use X11::Protocol;
     $x = X11::Protocol->new();
     $win = $x->new_rsrc;
     $x->CreateWindow($win, $x->root, 'InputOutput',
     		   $x->root_depth, 'CopyFromParent',
     		   ($x_coord, $y_coord), $width,
     		   $height, $border_w);
     ...

DESCRIPTION
===========

   X11::Protocol is a client-side interface to the X11 Protocol (see X(1)
for information about X11), allowing perl programs to display windows and
graphics on X11 servers.

   A full description of the protocol is beyond the scope of this
documentation; for complete information, see the *X Window System
Protocol, X Version 11*, available as Postscript or *roff source from
`ftp://ftp.x.org', or *Volume 0: X Protocol Reference Manual* of O'Reilly
& Associates's series of books about X (ISBN 1-56592-083-X,
`http://www.oreilly.com'), which contains most of the same information.

DISCLAIMER
==========

   "The protocol contains many management mechanisms that are not intended
for normal applications.  Not all mechanisms are needed to build a
particular user interface.  It is important to keep in mind that the
protocol is intended to provide mechanism, not policy." - Robert W.
Scheifler

BASIC METHODS
=============

new
---

     $x = X11::Protocol->new();
     $x = X11::Protocol->new($display_name);
     $x = X11::Protocol->new($connection);
     $x = X11::Protocol->new($display_name, [$auth_type, $auth_data]);
     $x = X11::Protocol->new($connection, [$auth_type, $auth_data]);

   Open a connection to a server. $display_name should be an X display
name, of the form 'host:display_num.screen_num'; if no arguments are
supplied, the contents of the DISPLAY environment variable are used.
Alternatively, a pre-opened connection, of one of the
X11::Protocol::Connection classes (see X11/Protocol/Connection,
see X11/Protocol/Connection/FileHandle,
see X11/Protocol/Connection/Socket,
see X11/Protocol/Connection/UNIXFH,
see X11/Protocol/Connection/INETFH,
see X11/Protocol/Connection/UNIXSocket,
see
X11/Protocol/Connection/INETSocket)
can be given. The authorization data is obtained using X11::Auth or the
second argument. If the display is specified by $display_name, rather than
$connection, a choose_screen() is also performed, defaulting to screen 0
if the '.screen_num' of the display name is not present.  Returns the new
protocol object.

new_rsrc
--------

     $x->new_rsrc;

   Returns a new resource identifier. A unique resource ID is required for
every object that the server creates on behalf of the client: windows,
fonts, cursors, etc. (IDs are chosen by the client instead of the server
for efficiency - the client doesn't have to wait for the server to
acknowledge the creation before starting to use the object).

handle_input
------------

     $x->handle_input;

   Get one chunk of information from the server, and do something with it.
If it's an error, handle it using the protocol object's handler
('error_handler' - default is kill the program with an explanatory
message). If it's an event, pass it to the chosen event handler, or put it
in a queue if the handler is 'queue'. If it's a reply to a request, save
using the object's 'replies' hash for further processing.

atom_name
---------

     $name = $x->atom_name($atom);

   Return the string corresponding to the atom $atom. This is similar to
the GetAtomName request, but caches the result for efficiency.

atom
----

     $atom = $x->atom($name);

   The inverse operation; Return the (numeric) atom correspoding to $name.
This is similar to the InternAtom request, but caches the result.

choose_screen
-------------

     $x->choose_screen($screen_num);

   Indicate that you prefer to use a particular screen of the display.
Per-screen information, such as 'root', 'width_in_pixels', and
'white_pixel' will be made avaliable as

     $x->{'root'}

   instead of

     $x->{'screens'}[$screen_num]{'root'}

SYMBOLIC CONSTANTS
==================

   Generally, symbolic constants used by the protocol, like
'CopyFromParent' or 'PieSlice' are passed to methods as strings, and
converted into numbers by the module.  Their names are the same as those
in the protocol specification, including capitalization, but with hyphens
('-') changed to underscores ('_') to look more perl-ish. If you want to
do the conversion yourself for some reason, the following methods are
avaliable:

num
---

     $num = $x->num($type, $str)

   Given a string representing a constant and a string specifying what
type of constant it is, return the corresponding number. $type should be a
name like 'VisualClass' or 'GCLineStyle'. If the name is not recognized,
it is returned intact.

interp
------

     $name = $x->interp($type, $num)

   The inverse operation; given a number and string specifying its type,
return a string representing the constant.

   You can disable interp() and the module's internal interpretation of
numbers by setting $x->{'do_interp'} to zero. Of course, this isn't very
useful, unless you have you own definitions for all the constants.

   Here is a list of available constant types:

     AccessMode, AllowEventsMode, AutoRepeatMode, BackingStore,
     BitGravity, Bool, ChangePropertyMode, CirculateDirection,
     CirculatePlace, Class, ClipRectangleOrdering, CloseDownMode,
     ColormapNotifyState, CoordinateMode, CrossingNotifyDetail,
     CrossingNotifyMode, DeviceEvent, DrawDirection, Error, EventMask,
     Events, FocusDetail, FocusMode, GCArcMode, GCCapStyle, GCFillRule,
     GCFillStyle, GCFunction, GCJoinStyle, GCLineStyle, GCSubwindowMode,
     GrabStatus, HostChangeMode, HostFamily, ImageFormat,
     InputFocusRevertTo, KeyMask, LedMode, MapState, MappingChangeStatus,
     MappingNotifyRequest, PointerEvent, PolyShape, PropertyNotifyState,
     Request, ScreenSaver, ScreenSaverAction, Significance, SizeClass,
     StackMode, SyncMode, VisibilityState, VisualClass, WinGravity

SERVER INFORMATION
==================

   At connection time, the server sends a large amount of information about
itself to the client. This information is stored in the protocol object
for future reference. It can be read directly, like

     $x->{'release_number'}

   or, for object oriented True Believers, using a method:

     $x->release_number

   The method method also has a one argument form for setting variables,
but it isn't really useful for some of the more complex structures.

   Here is an example of what the object's information might look like:

     'connection' => X11::Connection::UNIXSocket(0x814526fd),
     'byte_order' => 'l',
     'protocol_major_version' => 11,
     'protocol_minor_version' => 0,
     'authorization_protocol_name' => 'MIT-MAGIC-COOKIE-1',
     'release_number' => 3110,
     'resource_id_base' => 0x1c000002,
     'motion_buffer_size' => 0,
     'maximum_request_length' => 65535, # units of 4 bytes
     'image_byte_order' => 'LeastSiginificant',
     'bitmap_bit_order' => 'LeastSiginificant',
     'bitmap_scanline_unit' => 32,
     'bitmap_scanline_pad' => 32,
     'min_keycode' => 8,
     'max_keycode' => 134,
     'vendor' => 'The XFree86 Project, Inc',
     'pixmap_formats' => {1 => {'bits_per_pixel' => 1,
     			     'scanline_pad' => 32},
                          8 => {'bits_per_pixel' => 8,
     			     'scanline_pad' => 32}},
     'screens' => [{'root' => 43, 'width_in_pixels' => 800,
                    'height_in_pixels' => 600,
                    'width_in_millimeters' => 271,
                    'height_in_millmerters' => 203,
                    'root_depth' => 8,
                    'root_visual' => 34,
                    'default_colormap' => 33,
                    'white_pixel' => 0, 'black_pixel' => 1,
                    'min_installed_maps' => 1,
                    'max_installed_maps' => 1,
                    'backing_stores' => 'Always',
                    'save_unders' => 1,
                    'current_input_masks' => 0x58003d,
                    'allowed_depths' =>
                       [{'depth' => 1, 'visuals' => []},
                        {'depth' => 8, 'visuals' => [
                           {'visual_id' => 34, 'blue_mask' => 0,
                            'green_mask' => 0, 'red_mask' => 0,
                            'class' => 'PseudoColor',
                            'bits_per_rgb_value' => 6,
                            'colormap_entries' => 256},
                           {'visual_id' => 35, 'blue_mask' => 0xc0,
                            'green_mask' => 0x38, 'red_mask' => 0x7,
                            'class' => 'DirectColor',
                            'bits_per_rgb_value' => 6,
                            'colormap_entries' => 8}, ...]}]],
     'visuals' => {34 => {'depth' => 8, 'class' => 'PseudoColor',
                          'red_mask' => 0, 'green_mask' => 0,
                          'blue_mask'=> 0, 'bits_per_rgb_value' => 6,
                          'colormap_entries' => 256},
                   35 => {'depth' => 8, 'class' => 'DirectColor',
                          'red_mask' => 0x7, 'green_mask' => 0x38,
                          'blue_mask'=> 0xc0, 'bits_per_rgb_value' => 6,
                          'colormap_entries' => 8}, ...}
     'error_handler' => &\X11::Protocol::default_error_handler,
     'event_handler' => sub {},
     'do_interp' => 1

REQUESTS
========

request
-------

     $x->request('CreateWindow', ...);
     $x->req('CreateWindow', ...);
     $x->CreateWindow(...);

   Send a protocol request to the server, and get the reply. For names of
and information about individual requests, see below and/or the protocol
reference manual.

add_reply
---------

     $x->add_reply($sequence_num, \$var);

   Add a stub for an expected reply to the object's 'replies' hash. When a
reply numbered $sequence_num comes, it will be stored in $var.

delete_reply
------------

     $x->delete_reply($sequence_num);

   Delete the entry in 'replies' for the specified reply. (This should be
done after the reply is recieved).

send
----

     $x->send('CreateWindow', ...);

   Send a request, but do not wait for a reply. You must handle the reply,
if any, yourself, using add_reply(), handle_input(), delete_reply(), and
unpack_reply(), generally in that order.

unpack_reply
------------

     $x->unpack_reply('GetWindowAttributes', $data);

   Interpret the raw reply data $data, according to the reply format for
the named request. Returns data in the same format as
`request($request_name, ...)'.

   This section includes only a short calling summary for each request; for
full descriptions, see the protocol standard. Argument order is usually the
same as listed in the spec, but you generally don't have to pass lengths of
strings or arrays, since perl keeps track. Symbolic constants are generally
passed as strings. Most replies are returned as lists, but when there are
many values, a hash is used. Lists usually come last; when there is more
than one, each is passed by reference. In lists of multi-part structures,
each element is a list ref. Parenthesis are inserted in arg lists for
clarity, but are optional. Requests are listed in order by major opcode,
so related requests are usually close together. Replies follow the '=>'.

     $x->CreateWindow($wid, $parent, $class, $depth, $visual, ($x, $y),
     		   $width, $height, $border_width,
      		   'attribute' => $value, ...)

     $x->ChangeWindowAttributes($window, 'attribute' => $value, ...)

     $x->GetWindowAttributes($window)
     =>
     ('backing_store' => $backing_store, ...)

   This is an example of a return value that is meant to be assigned to a
hash.

     $x->DestroyWindow($win)

     $x->DestroySubwindows($win)

     $x->ChangeSaveSet($window, $mode)

     $x->ReparentWindow($win, $parent, ($x, $y))

     $x->MapWindow($win)

     $x->MapSubwindows($win)

     $x->UnmapWindow($win)

     $x->UnmapSubwindows($win)

     $x->ConfigureWindow($win, 'attribute' => $value, ...)

     $x->CirculateWindow($win, $direction)

   Note that this request actually circulates the subwindows of $win, not
the window itself.

     $x->GetGeometry($drawable)
     =>
     ('root' => $root, ...)

     $x->QueryTree($win)
     =>
     ($root, $parent, @kids)

     $x->InternAtom($name, $only_if_exists)
     =>
     $atom

     $x->GetAtomName($atom)
     =>
     $name

     $x->ChangeProperty($window, $property, $type, $format, $mode, $data)

     $x->DeleteProperty($win, $atom)

     $x->GetProperty($window, $property, $type, $offset, $length, $delete)
     =>
     ($value, $type, $format, $bytes_after)

   Notice that the value comes first, so you can easily ignore the rest.

     $x->ListProperties($window)
     =>
     (@atoms)

     $x->SetSelectionOwner($selection, $owner, $time)

     $x->GetSelectionOwner($selection)
     =>
     $owner

     $x->ConvertSelection($selection, $target, $property, $requestor, $time)

     $x->SendEvent($destination, $propagate, $event_mask, $event)

   The $event argument should be the result of a pack_event() (see
`"EVENTS"' in this node)

     $x->GrabPointer($grab_window, $owner_events, $event_mask,
     		  $pointer_mode, $keyboard_mode, $confine_to,
     		  $cursor, $time)
     =>
     $status

     $x->UngrabPointer($time)

     $x->GrabButton($modifiers, $button, $grab_window, $owner_events,
     		 $event_mask, $pointer_mode, $keyboard_mode,
     		 $confine_to, $cursor)

     $x->UngrabButton($modifiers, $button, $grab_window)

     $x->ChangeActivePointerGrab($event_mask, $cursor, $time)

     $x->GrabKeyboard($grab_window, $owner_events, $pointer_mode,
     		   $keyboard_mode, $time)
     =>
     $status

     $x->UngrabKeyboard($time)

     $x->GrabKey($key, $modifiers, $grab_window, $owner_events,
     	      $pointer_mode, $keyboard_mode)

     $x->UngrabKey($key, $modifiers, $grab_window)

     $x->AllowEvents($mode, $time)

     $x->GrabServer

     $x->UngrabServer

     $x->QueryPointer($window)
     =>
     ('root' => $root, ...)

     $x->GetMotionEvents($start, $stop, $window)
     =>
     ([$time, ($x, $y)], [$time, ($x, $y)], ...)

     $x->TranslateCoordinates($src_window, $dst_window, $src_x, $src_y)
     =>
     ($same_screen, $child, $dst_x, $dst_y)

     $x->WarpPointer($src_window, $dst_window, $src_x, $src_y, $src_width,
     		  $src_height, $dst_x, $dst_y)

     $x->SetInputFocus($focus, $revert_to, $time)

     $x->GetInputFocus
     =>
     ($focus, $revert_to)

     $x->QueryKeymap
     =>
     $keys

   $keys is a bit vector, so you should use vec() to read it.

     $x->OpenFont($fid, $name)

     $x->CloseFont($font)

     $x->QueryFont($font)
     =>
     ('min_char_or_byte2' => $min_char_or_byte2,
      ...,
      'min_bounds' =>
      [$left_side_bearing, $right_side_bearing, $character_width, $ascent,
       $descent, $attributes],
      ...,
      'char_infos' =>
      [[$left_side_bearing, $right_side_bearing, $character_width, $ascent,
        $descent, $attributes],
       ...],
      'properties' => {$prop => $value, ...}
      )

     $x->QueryTextExtents($font, $string)
     =>
     ('draw_direction' => $draw_direction, ...)

     $x->ListFonts($pattern, $max_names)
     =>
     @names

     $x->ListFontsWithInfo($pattern, $max_names)
     =>
     ({'name' => $name, ...}, {'name' => $name, ...}, ...)

   The information in each hash is the same as the the information
returned by QueryFont, but without per-character size information. This
request is special in that it is the only request that can have more than
one reply.  This means you should probably only use request() with it, not
send(), as the reply counting is complicated. Luckily, you never need this
request anyway, as its function is completely duplicated by other requests.

     $x->SetFontPath(@strings)

     $x->GetFontPath
     =>
     @strings

     $x->CreatePixmap($pixmap, $drawable, $depth, $width, $height)

     $x->FreePixmap($pixmap)

     $x->CreateGC($cid, $drawable, 'attribute' => $value, ...)

     $x->ChangeGC($gc, 'attribute' => $value, ...)

     $x->CopyGC($src, $dest, 'attribute', 'attribute', ...)

     $x->SetDashes($gc, $dash_offset, (@dashes))

     $x->SetClipRectangles($gc, ($clip_x_origin, $clip_y_origin),
     			$ordering, [$x, $y, $width, $height], ...)

     $x->ClearArea($window, ($x, $y), $width, $height, $exposures)

     $x->CopyArea($src_drawable, $dst_drawable, $gc, ($src_x, $src_y),
     	       $width, $height, ($dst_x, $dst_y))

     $x->CopyPlane($src_drawable, $dst_drawable, $gc, ($src_x, $src_y),
     		$width, $height, ($dst_x, $dst_y), $bit_plane)

     $x->PolyPoint($drawable, $gc, $coordinate_mode,
     		($x, $y), ($x, $y), ...)

     $x->PolyLine($drawable, $gc, $coordinate_mode,
     	       ($x, $y), ($x, $y), ...)

     $x->PolySegment($drawable, $gc, ($x, $y) => ($x, $y),
     		  ($x, $y) => ($x, $y), ...)

     $x->PolyRectangle($drawable, $gc,
     		    [($x, $y), $width, $height], ...)

     $x->PolyArc($drawable, $gc,
     	      [($x, $y), $width, $height, $angle1, $angle2], ...)

     $x->FillPoly($drawable, $gc, $shape, $coordinate_mode,
     	       ($x, $y), ...)

     $x->PolyFillRectangle($drawable, $gc,
     			[($x, $y), $width, $height], ...)

     $x->PolyFillArc($drawable, $gc,
     		  [($x, $y), $width, $height, $angle1, $angle2], ...)

     $x->PutImage($drawable, $gc, $depth, $width, $height,
     	       ($dst_x, $dst_y), $left_pad, $format, $data)

   Currently, the module has no code to handle the various bitmap formats
that the server might specify. Therefore, this request will not work
portably without a lot of work.

     $x->GetImage($drawable, ($x, $y), $width, $height, $plane_mask,
     	       $format)

     $x->PolyText8($drawable, $gc, ($x, $y),
     		($font OR [$delta, $string]), ...)

     $x->PolyText16($drawable, $gc, ($x, $y),
     		 ($font OR [$delta, $string]), ...)

     $x->ImageText8($drawable, $gc, ($x, $y), $string)

     $x->ImageText16($drawable, $gc, ($x, $y), $string)

     $x->CreateColormap($mid, $visual, $window, $alloc)

     $x->FreeColormap($cmap)

     $x->CopyColormapAndFree($mid, $src_cmap)

     $x->InstallColormap($cmap)

     $x->UninstallColormap($cmap)

     $x->ListInstalledColormaps($window)
     =>
     @cmaps

     $x->AllocColor($cmap, ($red, $green, $blue))
     =>
     ($pixel, ($red, $green, $blue))

     $x->AllocNamedColor($cmap, $name)
     =>
     ($pixel, ($exact_red, $exact_green, $exact_blue),
      ($visual_red, $visual_green, $visual_blue))

     $x->AllocColorCells($cmap, $colors, $planes, $contiguous)
     =>
     ([@pixels], [@masks])

     $x->AllocColorPlanes($cmap, $colors, ($reds, $greens, $blues),
     		       $contiguous)
     =>
     (($red_mask, $green_mask, $blue_mask), @pixels)

     $x->FreeColors($cmap, $plane_mask, @pixels)

     $x->StoreColors($cmap, [$pixel, $red, $green, $blue, $do_mask], ...)

   The 1, 2, and 4 bits in $mask are do-red, do-green, and do-blue. $mask
can be omitted, defaulting to 7, the usual case - change the whole color.

     $x->StoreNamedColor($cmap, $pixel, $name, $do_mask)

   $do_mask has the same interpretation as above, but is mandatory.

     $x->QueryColors($cmap, @pixels)
     =>
     ([$red, $green, $blue], ...)

     $x->LookupColor($cmap, $name)
     =>
     (($exact_red, $exact_green, $exact_blue),
      ($visual_red, $visual_green, $visual_blue))

     $x->CreateCursor($cid, $source, $mask,
     		   ($fore_red, $fore_green, $fore_blue),
     		   ($back_red, $back_green, $back_blue),
     		   ($x, $y))

     $x->CreateGlyphCursor($cid, $source_font, $mask_font,
     			$source_char, $mask_char,
     			($fore_red, $fore_green, $fore_blue),
     			($back_red, $back_green, $back_blue))

     $x->FreeCursor($cursor)

     $x->RecolorCursor($cursor, ($fore_red, $fore_green, $fore_blue),
     		    ($back_red, $back_green, $back_blue))

     $x->QueryBestSize($class, $drawable, $width, $height)
     =>
     ($width, $height)

     $x->QueryExtension($name)
     =>
     ($major_opcode, $first_event, $first_error)

   If the extension is not present, an empty list is returned.

     $x->ListExtensions
     =>
     (@names)

     $x->ChangeModifierMapping($first_keycode, $keysysms_per_keycode,
     			    @keysyms)

     $x->GetKeyboardMapping($first_keycode, $count)
     =>
     ($keysysms_per_keycode, [$keysym, ...], [$keysym, ...], ...)

     $x->ChangeKeyboardControl('attribute' => $value, ...)

     $x->GetKeyboardControl
     =>
     ('global_auto_repeat' => $global_auto_repeat, ...)

     $x->Bell($percent)

     $x->ChangePointerControl($do_acceleration, $do_threshold,
     			   $acceleration_numerator,
     			   $acceleration_denominator, $threshold)

     $x->GetPointerControl
     =>
     ($accerleration_numerator, $acceleration_denominator, $threshold)

     $x->SetScreenSaver($timeout, $interval, $prefer_blanking,
     		     $allow_exposures)

     $x->GetScreenSaver
     =>
     ($timeout, $interval, $prefer_blanking, $allow_exposures)

     $x->ChangeHosts($mode, $host_family, $host_address)

     $x->ListHosts
     =>
     ($mode, [$family, $host], ...)

     $x->SetAccessControl($mode)

     $x->SetCloseDownMode($mode)

     $x->KillClient($resource)

     $x->RotateProperties($win, $delta, @props)

     $x->ForceScreenSaver($mode)

     $x->SetPointerMapping(@map)
     =>
     $status

     $x->GetPointerMapping
     =>
     @map

     $x->SetModifierMapping(@keycodes)
     =>
     $status

     $x->GetModiferMapping
     =>
     @keycodes

     $x->NoOperation($length)

   $length specifies the length of the entire useless request, in four
byte units, and is optional.

EVENTS
======

   To receive events, first set the 'event_mask' attribute on a window to
indicate what types of events you desire (see `"pack_event_mask"' in this
node). Then, set the protocol object's 'event_handler' to a subroutine
reference that will handle the events. Alternatively, set 'event_handler'
to 'queue', and retrieve events using dequeue_event(). In both cases,
events are returned as a hash. For instance, a typical MotionNotify event
might look like this:

     %event = ('name' => 'MotionNotify', 'sequence_number' => 12,
               'state' => 0, 'event' => 58720256, 'root' => 43,
               'child' => None, 'same_screen' => 1, 'time' => 966080746,
               'detail' => 'Normal', 'event_x' => 10, 'event_y' => 3,
               'code' => 6, 'root_x' => 319, 'root_y' => 235)

pack_event_mask
---------------

     $mask = $x->pack_event_mask('ButtonPress', 'KeyPress', 'Exposure');

   Make an event mask (suitable as the 'event_mask' of a window) from a
list of strings specifying event types.

unpack_event_mask
-----------------

     @event_types = $x->unpack_event_mask($mask);

   The inverse operation; convert an event mask obtained from the server
into a list of names of event categories.

dequeue_event
-------------

     %event = $x->dequeue_event;

   If there is an event waiting in the queue, return it.

next_event
----------

     %event = $x->next_event;

   Like Xlib's XNextEvent(), this function is equivalent to

     $x->handle_input until %event = dequeue_event;

pack_event
----------

     $data = $x->pack_event(%event);

   Given an event in hash form, pack it into a string. This is only useful
as an argument to SendEvent().

unpack_event
------------

     %event = $x->unpack_event($data);

   The inverse operation; given the raw data for an event (32 bytes),
unpack it into hash form. Normally, this is done automatically.

EXTENSIONS
==========

   Protocol extensions add new requests, event types, and error types to
the protocol. Support for them is compartmentalized in modules in the
X11::Protocol::Ext:: hierarchy. For an example, see
`X11::Protocol::Ext:SHAPE' in this node. You can tell if the module has
loaded an extension by looking at

     $x->{'ext'}{$extension_name}

   If the extension has been initialized, this value will be an array
reference, [$major_request_number, $first_event_number,
$first_error_number, $obj], where $obj is an object containing information
private to the extension.

init_extension
--------------

     $x->init_extension($name);

   Initialize an extension: query the server to find the extension's
request number, then load the corresponding module. Returns 0 if the
server does not support the named extension, or if no module to interface
with it exists.

init_extensions
---------------

     $x->init_extensions;

   Initialize protocol extensions. This does a ListExtensions request,
then calls init_extension() for each extension that the server supports.

WRITING EXTENSIONS
==================

   Internally, the X11::Protocol module is table driven. All an extension
has to do is to add new add entries to the protocol object's tables. An
extension module should `use X11::Protocol', and should define an new()
method

     X11::Protocol::Ext::NAME
       ->new($x, $request_num, $event_num, $error_num)

   where $x is the protocol object and $request_num, $event_num and
$error_num are the values returned by QueryExtension().

   The new() method should add new types of constant like

     $x->{'ext_const'}{'ConstantType'} = ['Constant', 'Constant', ...]

   and set up the corresponding name to number translation hashes like

     $x->{'ext_const_num'}{'ConstType'} =
       {make_num_hash($x->{'ext_const'}{'ConstType'})}

   Event names go in

     $x->{'ext_const'}{'Events'}[$event_number]

   while specifications for event contents go in

     $x->{'ext_event'}[$event_number]

   each element of which is either `[\&unpack_sub, \&pack_sub]' or
`[$pack_format, $field, $field, ...]', where each $field is `'name'',
`['name', 'const_type']', or `['name', ['special_name_for_zero',
'special_name_for_one']]', where `'special_name_for_one'' is optional.

   Finally,

     $x->{'ext_request'}{$major_request_number}

   should be an array of arrays, with each array either `[$name,
\&packit]' or `[$name, \&packit, \&unpackit]', and

     $x->{'ext_request_num'}{$request_name}

   should be initialized with `[$minor_num, $major_num]' for each request
the extension defines. For examples of code that does all of this, look at
X11::Protocol::Ext::SHAPE.

   X11::Protocol exports several functions that might be useful in
extensions (note that these are not methods).

padding
-------

     $p = padding $x;

   Given an integer, compute the number need to round it up to a multiple
of 4.  For instance, `padding(5)' is 3.

pad
---

     $p = pad $str;

   Given a string, return the number of extra bytes needed to make a
multiple of 4. Equivalent to `padding(length($str))'.

padded
------

     $data = pack(padded($str), $str);

   Return a format string, suitable for pack(), for a string padded to a
multiple of 4 bytes. For instance, `pack(padded('Hello'), 'Hello')' gives
`"Hello\0\0\0"'.

hexi
----

     $str = hexi $n;

   Format a number in hexidecimal, and add a "0x" to the front.

make_num_hash
-------------

     %hash = make_num_hash(['A', 'B', 'C']);

   Given a reference to a list of strings, return a hash mapping the
strings onto numbers representing their position in the list, as used by
`$x->{'ext_const_num'}'.

BUGS
====

   This module is too big (~2500 lines), too slow (10 sec to load on a slow
machine), too inefficient (request args are copied several times), and
takes up too much memory (3000K for basicwin).

   If you have more than 65535 replies outstanding at once, sequence
numbers can collide.

   The protocol is too complex.

AUTHOR
======

   Stephen McCamant <alias@mcs.com>.

SEE ALSO
========

   `perl(1)' in this node, `X(1)' in this node, see X11/Keysyms,
see X11/Protocol/Ext/SHAPE,
X11/Protocol/Ext/BIG_REQUESTS,
X11/Auth, *X Window System Protocol (X Version 11)*,
*Inter-Client Communications Conventions Manual*, *X Logical Font
Description Conventions*.

Perl module abstract base class for X11 client to server connections
********************************************************************

NAME
====

   X11::Protocol::Connection - Perl module abstract base class for X11
client to server connections

SYNOPSIS
========

     # In connection object module
     package X11::Protocol::Connection::CarrierPigeon;
     use X11::Protocol::Connection;
     @ISA = ('X11::Protocol::Connection');
     sub open { ... }
     sub give { ... }
     sub get { ... }
     sub fh { ... }
     ...

     # In program
     $connection = X11::Protocol::Connection::CarrierPigeon
       ->open($host, $display_number);
     $x = X11::Protocol->new($connection);

     $connection->give($data);

     $reply = unpack("I", $connection->get(4));

     use IO::Select;
     $sel = IO::select->new($connection->fh);
     if ($sel->can_read == $connection->fh) ...

DESCRIPTION
===========

   This module is an abstract base class for the various
X11::Protocol::Connection::* modules that provide connections to X servers
for the X11::Protocol module. It provides stubs for the following methods:

open
----

     $conn = X11::Protocol::Connection::Foo->open($host, $display_num)

   Open a connection to the specified display (numbered from 0) on the
specified $host.

give
----

     $conn->give($data)

   Send the given data to the server. Normally, this method is used only
by the protocol module itself.

get
---

     $data = $conn->get($n)

   Read $n bytes of data from the server. Normally, this method is used
only by the protocol module itself.

fh
--

     $filehandle = $conn->fh

   Return an object suitable for use as a filehandle. This is mainly
useful for doing select() and other such system calls.

AUTHOR
======

   Stephen McCamant <alias@mcs.com>.

SEE ALSO
========

   `perl(1)' in this node, see X11/Protocol,
X11/Protocol/Connection/Socket,
X11/Protocol/Connection/FileHandle,
X11/Protocol/Connection/INETSocket,
see
X11/Protocol/Connection/UNIXSocket,
X11/Protocol/Connection/INETFH,
X11/Protocol/Connection/UNIXFH.

Perl module base class for FileHandle-based X11 connections
***********************************************************

NAME
====

   X11::Protocol::Connection::FileHandle - Perl module base class for
FileHandle-based X11 connections

SYNOPSIS
========

     package X11::Protocol::Connection::WeirdFH;
     use X11::Protocol::Connection::FileHandle;
     @ISA = ('X11::Protocol::Connection::FileHandle')

DESCRIPTION
===========

   This module defines get(), give() and fh() methods common to
X11::Protocol::Connection types that are based on the FileHandle package.
They expect the object they are called with to be a reference to a
FileHandle.

AUTHOR
======

   Stephen McCamant <alias@mcs.com>.

SEE ALSO
========

   `perl(1)' in this node, see X11/Protocol,
X11/Protocol/Connection/INETFH,
X11/Protocol/Connection/UNIXFH,
FileHandle.

Perl module for FileHandle-based TCP/IP X11 connections
*******************************************************

NAME
====

   X11::Protocol::Connection::INETFH - Perl module for FileHandle-based
TCP/IP X11 connections

SYNOPSIS
========

     use X11::Protocol;
     use X11::Protocol::Connection::INETFH;
     $conn = X11::Protocol::Connection::INETFH
       ->open($host, $display_number);
     $x = X11::Protocol->new($conn);

DESCRIPTION
===========

   This module is used by X11::Protocol to establish a connection and
communicate with a server over an internet-type TCP/IP socket connection,
using the FileHandle module.

AUTHOR
======

   Stephen McCamant <alias@mcs.com>.

SEE ALSO
========

   `perl(1)' in this node, see X11/Protocol,
X11/Protocol/Connection/UNIXFH,
X11/Protocol/Connection/FileHandle,
FileHandle.

Perl module for IO::Socket::INET-based X11 connections
******************************************************

NAME
====

   X11::Protocol::Connection::INETSocket - Perl module for
IO::Socket::INET-based X11 connections

SYNOPSIS
========

     use X11::Protocol;
     use X11::Protocol::Connection::INETSocket;
     $conn = X11::Protocol::Connection::INETSocket
       ->open($host, $display_number);
     $x = X11::Protocol->new($conn);

DESCRIPTION
===========

   This module is used by X11::Protocol to establish a connection and
communicate with a server over a TCP/IP connection, using the
IO::Socket::INET module.

AUTHOR
======

   Stephen McCamant <alias@mcs.com>.

SEE ALSO
========

   `perl(1)' in this node, see X11/Protocol,
X11/Protocol/Connection/Socket,
X11/Protocol/Connection/UNIXSocket,
IO/Socket.

Perl module base class for IO::Socket-based X11 connections
***********************************************************

NAME
====

   X11::Protocol::Connection::Socket - Perl module base class for
IO::Socket-based X11 connections

SYNOPSIS
========

     package X11::Protocol::Connection::WeirdSocket;
     use X11::Protocol::Connection::Socket;
     @ISA = ('X11::Protocol::Connection::Socket')

DESCRIPTION
===========

   This module defines get(), give() and fh() methods common to
X11::Protocol::Connection types that are based on IO::Socket. They expect
the object they are called with to be a reference to an IO::Socket.

AUTHOR
======

   Stephen McCamant <alias@mcs.com>.

SEE ALSO
========

   `perl(1)' in this node, see X11/Protocol,
X11/Protocol/Connection/INETSocket,
X11/Protocol/Connection/UNIXSocket,
see IO/Socket.

Perl module for FileHandle-based Unix-domain X11 connections
************************************************************

NAME
====

   X11::Protocol::Connection::UNIXFH - Perl module for FileHandle-based
Unix-domain X11 connections

SYNOPSIS
========

     use X11::Protocol;
     use X11::Protocol::Connection::UNIXFH;
     $conn = X11::Protocol::Connection::UNIXFH
       ->open($host, $display_number);
     $x = X11::Protocol->new($conn);

DESCRIPTION
===========

   This module is used by X11::Protocol to establish a connection and
communicate with a server over a local Unix-domain socket connection,
using the FileHandle module. The host argument is ignored.

AUTHOR
======

   Stephen McCamant <alias@mcs.com>.

SEE ALSO
========

   `perl(1)' in this node, see X11/Protocol,
X11/Protocol/Connection/INETFH,
X11/Protocol/Connection/FileHandle,
FileHandle.

Perl module for IO::Socket::UNIX-based X11 connections
******************************************************

NAME
====

   X11::Protocol::Connection::UNIXSocket - Perl module for
IO::Socket::UNIX-based X11 connections

SYNOPSIS
========

     use X11::Protocol;
     use X11::Protocol::Connection::UNIXSocket;
     $conn = X11::Protocol::Connection::UNIXSocket
       ->open($host, $display_number);
     $x = X11::Protocol->new($conn);

DESCRIPTION
===========

   This module is used by X11::Protocol to establish a connection and
communicate with a server over a local Unix-domain socket connection,
using the IO::Socket::UNIX module. The host argument is ignored.

AUTHOR
======

   Stephen McCamant <alias@mcs.com>.

SEE ALSO
========

   `perl(1)' in this node, see X11/Protocol,
X11/Protocol/Connection/INETSocket,
X11/Protocol/Connection/Socket,
IO/Socket.

Perl module for the X11 protocol Big Requests extension
*******************************************************

NAME
====

   X11::Protocol::Ext::BIG_REQUESTS - Perl module for the X11 protocol Big
Requests extension

SYNOPSIS
========

     use X11::Protocol;
     $x = X11::Protocol->new($ENV{'DISPLAY'});
     $x->init_extension('BIG_REQUESTS') or die;

DESCRIPTION
===========

   This module is used by the X11::Protocol module to participate in the
'Big Requests' extension to the X protocol. Once initialized, it
transparently allows requests of more than 262140 (65535 * 4) bytes.  The
new maximum request length is avaliable as `$x->maximum_request_length'.

AUTHOR
======

   Stephen McCamant <alias@mcs.com>.

SEE ALSO
========

   `perl(1)' in this node, see X11/Protocol, *Big
Requests Extension (X Consortium Standard)*.

Perl module for the X11 Protocol Nonrectangular Window Shape Extension
**********************************************************************

NAME
====

   X11::Protocol::Ext::SHAPE - Perl module for the X11 Protocol
Nonrectangular Window Shape Extension

SYNOPSIS
========

     use X11::Protocol;
     $x = X11::Protocol->new($ENV{'DISPLAY'});
     $x->init_extension('SHAPE') or die;

DESCRIPTION
===========

   This module is used by the X11::Protocol module to participate in the
shaped window extension to the X protocol, allowing windows to be of any
shape, not just rectangles.

SYMBOLIC CONSTANTS
==================

   This extension adds the constant types 'ShapeKind' and 'ShapeOp', with
values as defined in the standard.

EVENTS
======

   This extension adds the event type 'ShapeNotify', with values as
specified in the standard. This event is selected using the
ShapeSelectInput() request.

REQUESTS
========

   This extension adds several requests, called as shown below:

     $x->ShapeQueryVersion
     =>
     ($major, $minor)

     $x->ShapeRectangles($dest, $destKind, $op, $xOff, $yOff,
     		      $ordering, @rectangles)

     $x->ShapeMask($dest, $destKind, $op, $xOff, $yOff, $source)

     $x->ShapeCombine($dest, $destKind, $op, $xOff, $yOff, $source,
     		   $sourceKind)

     $x->ShapeOffset($dest, $destKind, $xOff, $yOff)

     $x->ShapeQueryExtents($dest)
     =>
     ($boundingShaped, $clipShaped,
      ($xBoundingShape, $yBoundingShape,
       $widthBoundingShape, $heightBoundingShape)
      ($xClipShape, $yClipShape, $widthClipShape, $heightClipShape))

     $x->ShapeSelectInput($window, $enable)

     $x->ShapeInputSelected($window)
     =>
     $enable

     $x->ShapeGetRectangles($window, $kind)
     =>
     ($ordering, [$x, $y, $width, $height], ...)

AUTHOR
======

   Stephen McCamant <alias@mcs.com>.

SEE ALSO
========

   `perl(1)' in this node, see X11/Protocol,
*Nonrectangular Window Shape Extension (X Consortium Standard)*.

Parse X500 Distinguished Names
******************************

NAME
====

   `X500::DN::Parser' - Parse X500 Distinguished Names

SYNOPSIS
========

     use X500::DN::Parser;

     my($parser) = new X500::DN::Parser(\&errorInDN);

     my($dn, $genericDN, %RDN) =
     	$parser -> parse('c=au;o=MagicWare;cn=Ron Savage',
     			'c', '[l]', 'o', '[ou]', 'cn');

DESCRIPTION
===========

   Parse DNs where the caller knows the number of RDNs.

parse()
=======

   Input Parameters:

   * DN to be parsed

   * A list of the expected components of the DN.  Any component can be
     put in [] to indicate that that component is optional

   Output List:

   * $dn: The DN passed in

   * $genericDN:	A generic DN matching the given DN

   * %component:	The components of the DN and their values. Eg:

          If $dn = 'c=au;o=MagicWare', then these key/values appear:
          'c' => 'au',
          'o' => 'MagicWare'

INSTALLATION
============

   You install `X500::DN::Parser', as you would install any perl module
library, by running these commands:

     perl Makefile.PL
     make
     make test
     make install

   If you want to install a private copy of `X500::DN::Parser' in your home
directory, then you should try to produce the initial Makefile with
something like this command:

     perl Makefile.PL LIB=~/perl
     	or
     perl Makefile.PL LIB=C:/Perl/Site/Lib

   If, like me, you don't have permission to write man pages into unix
system directories, use:

     make pure_install

   instead of make install. This option is secreted in the middle of p 414
of the second edition of the dromedary book.

AUTHOR
======

   `X500::DN::Parser' was written by Ron Savage
*<rpsavage@ozemail.com.au>* in 1999.

LICENCE
=======

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl module for reading and writing the dbf files
*************************************************

NAME
====

   XBase - Perl module for reading and writing the dbf files

SYNOPSIS
========

     use XBase;
     my $table = new XBase "dbase.dbf" or die XBase->errstr;
     for (0 .. $table->last_record) {
     	my ($deleted, $id, $msg)
     		= $table->get_record($_, "ID", "MSG");
     	print "$id:\t$msg\n" unless $deleted;
     	}

DESCRIPTION
===========

   This module can read and write XBase database files, known as dbf in
dBase and FoxPro world. It also reads memo fields from the dbt and fpt
files, if needed. An alpha code of reading index support for ndx, ntx,
mdx, idx and cdx is available for testing - see the DBD::Index(3) man
page. Module XBase provides simple native interface to XBase files.  For
DBI compliant database access, see the DBD::XBase and DBI modules and
their man pages.

   The following methods are supported by XBase module:

General methods
---------------

new
     Creates the XBase object, loads the info about the table form the dbf
     file. The first parameter should be the name of existing dbf file
     (table, in fact) to read. A suffix .dbf will be appended if needed.
     This method creates and initializes new object, will also check for
     memo file, if needed.

     The parameters can also be specified in the form of hash: value of
     name is then the name of the table, other flags supported are:

     *memofile* specifies non standard name for the associated memo file.
     By default it's the name of the dbf file, with extension dbt or fpt.

     *ignorememo* ignore memo file at all. This is usefull if you've lost
     the dbt file and you do not need it. Default is false.

     *memosep* separator of memo records in the dBase III dbt files. The
     standard says it should be `"\x1a\x1a"'. There are however
     implamentations that only put in one `"\x1a"'. XBase.pm tries to
     guess which is valid for your dbt but if it fails, you can tell it
     yourself.

     *nolongchars* prevents XBase to treat the decimal value of character
     fields as high byte of the length - there are some broken products
     around producing character fields with decimal values set.

          my $table = new XBase "table.dbf" or die XBase->errstr;

          my $table = new XBase "name" => "table.dbf",
          					"ignorememo" => 1;

close
     Closes the object/file, no arguments.

create
     Creates new database file on disk and initializes it with 0 records.
     A dbt (memo) file will be also created if the table contains some memo
     fields. Parameters to create are passed as hash.

     You can call this method as method of another XBase object and then
     you only need to pass name value of the hash; the structure (fields)
     of the new file will be the same as of the original object.

     If you call create using class name (XBase), you have to (besides
     name) also specify another four values, each being a reference to
     list: *field_names*, *field_types*, *field_lengths* and
     *field_decimals*. The field types are specified by one letter strings
     (C, N, L, D, ...). If you set some value as undefined, create will
     make it into some reasonable default.

          my $newtable = $table->create("name" => "copy.dbf");

          my $newtable = XBase->create("name" => "copy.dbf",
          		"field_names" => [ "ID", "MSG" ],
          		"field_types" => [ "N", "C" ],
          		"field_lengths" => [ 6, 40 ],
          		"field_decimals" => [ 0, undef ]);

     Other attributes are *memofile* for non standard memo file location,
     version to force different version of the dbt (dbt) file. The default
     is the version of the object you create the new from, or 3 if you
     call this as class method (XBase->create).

     The new file mustn't exist yet - XBase will not allow you to
     overwrite existing table. Use drop (or unlink) to delete it first.

drop
     This method closes the table and deletes it on disk (including
     associated memo file, if there is any).

last_record
     Returns number of the last record in the file. The lines deleted but
     present in the file are included in this number.

last_field
     Returns number of the last field in the file, number of fields minus
     1.

field_names, field_types, field_lengths, field_decimals
     Return list of field names and so on for the dbf file.

field_type, field_length, field_decimal
     For a field name, returns the appropriate value. Returns undef if the
     field doesn't exist in the table.

Reading the data one by one
---------------------------

   When dealing with the records one by one, reading or writing (the
following six methods), you have to specify the number of the record in
the file as the first argument. The range is `0 .. $table->last_record'.

get_record
     Returns a list of data (field values) from the specified record (line
     of the table). The first parameter in the call is the number of the
     record. If you do not specify any other parameters, all fields are
     returned in the same order as they appear in the file. You can also
     put list of field names after the record number and then only those
     will be returned. The first value of the returned list is always the
     1/0 `_DELETED' value saying whether the record is deleted or not, so
     on success, get_record never returns empty list.

get_record_nf
     Instead if the names of the fields, you can pass list of numbers of
     the fields to read.

get_record_as_hash
     Returns hash (in list context) or reference to hash (in scalar
     context) containing field values indexed by field names. The name of
     the deleted flag is `_DELETED'. The only parameter in the call is the
     record number. The field names are returned as uppercase.

Writing the data
----------------

   All three writing methods always undelete the record. On success they
return true - the record number actually written.

set_record
     As parameters, takes the number of the record and the list of values
     of the fields. It writes the record to the file. Unspecified fields
     (if you pass less than you should) are set to undef/empty.

set_record_hash
     Takes number of the record and hash as parameters, sets the fields,
     unspecified are undefed/emptied.

update_record_hash
     Like set_record_hash but fields that do not have value specified in
     the hash retain their value.

   To explicitely delete/undelete a record, use methods delete_record or
*undelete_record* with record number as a parameter.

   Assorted examples of reading and writing:

     my @data = $table->get_record(3, "jezek", "krtek");
     my $hashref = $table->get_record_as_hash(38);
     $table->set_record_hash(8, "jezek" => "jezecek",
     					"krtek" => 5);
     $table->undelete_record(4);

   This is a code to update field MSG in record where ID is 123.

     use XBase;
     my $table = new XBase "test.dbf" or die XBase->errstr;
     for (0 .. $table->last_record) {
     	my ($deleted, $id) = $table->get_record($_, "ID")
     	die $table->errstr unless defined $deleted;
     	next if $deleted;
     	$table->update_record_hash($_, "MSG" => "New message")
     						if $id == 123;
     	}

Sequentially reading the file
-----------------------------

   If you plan to sequentially walk through the file, you can create a
cursor first and then repeatedly call fetch to get next record.

prepare_select
     As parameters, pass list of field names to return, if no parameters,
     the following fetch will return all fields.

prepare_select_with_index
     The first parameter is the file name of the index file, the rest is
     as above. For index types that can hold more index structures in on
     file, use arrayref instead of the file name and in that array include
     file name and the tag name, and optionaly the index type.  The fetch
     will then return records in the ascending order, according to the
     index.

   Prepare will return object cursor, the following method are methods of
the cursor, not of the table.

fetch
     Returns the fields of the next available undeleted record. The list
     thus doesn't contain the `_DELETED' flag since you are guaranteed
     that the record is not deleted.

fetch_hashref
     Returns a hash reference of fields for the next non deleted record.

last_fetched
     Returns the number of the record last fetched.

find_eq
     This only works with cursor created via prepare_select_with_index.
     Will roll to the first record what is equal to specified argument, or
     to the first greater if there is none equal. The following fetches
     then continue normally.

   Examples of using cursors:

     my $table = new XBase "names.dbf" or die XBase->errstr;
     my $cursor = $table->prepare_select("ID", "NAME", "STREET");
     while (my @data = $cursor->fetch)
     	{ ### do something here, like print "@data\n"; }

     my $table = new XBase "employ.dbf";
     my $cur = $table->prepare_select_with_index("empid.ndx");
     ## my $cur = $table->prepare_select_with_index(
     		["empid.cdx", "ADDRES"], "id", "address");
     $cur->find_eq(1097);
     while (my $hashref = $cur->fetch_hashref
     			and $hashref->{"ID"} == 1097)
     	{ ### do something here with $hashref }

   The second example shows that after you have done find_eq, the fetches
continue untill the end of the index, so you have to check whether you are
still on records with given value. And if there is no record with value
1097 in the indexed field, you will just get the next record in the order.

   The updating example can be rewritten to:

     use XBase;
     my $table = new XBase "test.dbf" or die XBase->errstr;
     my $cursor = $table->prepare_select("ID")
     while (my ($id) = $cursor->fetch) {
     	$table->update_record_hash($cursor->last_fetched,
     			"MSG" => "New message") if $id == 123
     	}

Dumping the content of the file
-------------------------------

   A method *get_all_records* returns reference to an array containing
array of values for each undeleted record at once. As parameters, pass
list of fields to return for each record.

   To print the content of the file in a readable form, use method
*dump_records*. It prints all not deleted records from the file. By
default, all fields are printed, separated by colons, one record on a row.
The method can have parameters in a form of a hash with the following keys:

rs
     Record separator, string, newline by default.

fs
     Field separator, string, one colon by default.

fields
     Reference to a list of names of the fields to print. By default it's
     undef, meaning all fields.

undef
     What to print for undefined (NULL) values, empty string by default.

   Example of use is

     use XBase;
     my $table = new XBase "table" or die XBase->errstr;
     $table->dump_records("fs" => " | ", "rs" => " <-+\n",
     			"fields" => [ "id", "msg" ]);'

   Also note that there is a script dbfdump(1) that does the printing.

Errors and debugging
--------------------

   If the method fails (returns false or null list), the error message can
be retrieved via *errstr* method. If the new or create method fails, you
have no object so you get the error message using class syntax
`XBase->errstr()'.

   The method *header_info* returns (not prints) string with information
about the file and about the fields.

   Module XBase::Base(3) defines some basic functions that are inherited
by both XBase and XBase::Memo(3) module.

DATA TYPES
==========

   The character fields are returned "as is". No charset or other
translation is done. The numbers are converted to Perl numbers. The date
fields are returned as 8 character string of the 'YYYYMMDD' form and when
inserting the date, you again have to provide it in this form. No checking
for the validity of the date is done. The datetime field is returned in
the number of seconds since 1970/1/1, possibly with decimal part (since it
allows precision up to 1/1000 s). To get the fields, use the gmtime (or
similar) Perl function.

   If there is a memo field in the dbf file, the module tries to open file
with the same name but extension dbt, fpt or smt. It uses module
XBase::Memo(3) for this. It reads and writes this memo field transparently
(you do not know about it) and returns the data as single scalar.

INDEX, LOCKS
============

   *New:* A support for ndx, ntx, mdx, idx and cdx index formats is
available with alpha status for testing. Some of the formats are already
rather stable (ndx). Please read the XBase::Index(3) man page and the
eg/use_index file in the distribution for examples and ideas.  Send me
examples of your data files and suggestions for interface if you need
indexes.

   General locking methods are *locksh*, *lockex* and unlock for shared
lock, exclusive lock and unlock. They call flock but you can redefine then
in XBase::Base package.

INFORMATION SOURCE
==================

   This module is built using information from and article XBase File
Format Description by Erik Bachmann, URL

     http://www.e-bachmann.dk/docs/xbase.htm

   Thanks a lot.

VERSION
=======

   0.173

AUTHOR
======

   (c) 1997-2001 Jan Pazdziora, adelton@fi.muni.cz,
http://www.fi.muni.cz/~adelton/ at Faculty of Informatics, Masaryk
University in Brno, Czech Republic

   All rights reserved. This package is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

THANKS
======

   Many people have provided information, test files, test results and
patches. This project would not be so great without them. See the Changes
file for (I hope) complete list. Thank you all, guys!

   Special thanks go to Erik Bachmann for his great page about the file
structures; to Frans van Loon, William McKee, Randy Kobes and Dan
Albertsson for longtime cooperation and many emails we've exchanged when
fixing and polishing the modules' behaviour; and to Dan Albertsson for
providing support for the project.

SEE ALSO
========

   perl(1); XBase::FAQ(3); DBD::XBase(3) and DBI(3) for DBI interface;
dbfdump(1)

Base input output module for XBase suite
****************************************

NAME
====

   XBase::Base - Base input output module for XBase suite

SYNOPSIS
========

   Used indirectly, via XBase or XBase::Memo.

DESCRIPTION
===========

   This module provides catch-all I/O methods for other XBase classes,
should be used by people creating additional XBase classes/methods.  There
is nothing interesting in here for users of the XBase(3) module.  Methods
in XBase::Base return nothing (undef) on error and the error message can
be retrieved using the *errstr* method.

   Methods are:

new
     Constructor. Creates the object and if the file name is specified,
     opens the file.

open
     Opens the file and using method read_header reads the header and sets
     the object's data structure. The read_header should be defined in the
     derived class, there is no default.

close
     Closes the file, doesn't destroy the object.

drop
     Unlinks the file.

create_file
     Creates file of given name. Second (optional) paramater is the
     permission specification for the file.

   The reading/writing methods assume that the file has got header of
length header_len bytes (possibly 0) and then records of length
record_len. These two values should be set by the read_header method.

seek_to, seek_to_record
     Seeks to absolute position or to the start of the record.

read_record, read_from
     Reads data from specified position (offset) or from the given record.
     The second parameter (optional for *read_record*) is the length to
     read. It can be negative, and at that case the read will not complain
     if the file is shorter than requested.

write_to, write_record
     Writes data to the absolute position or to specified record position.
     The data is not padded to record_len, just written out.

   General locking methods are *locksh*, *lockex* and unlock, they call
*_locksh*, *_lockex* and *_unlock* which can be redefined to allow any way
for locking (not only the default flock). The user is responsible for
calling the lock if he needs it.

   No more description - check the source code if you need to know more.

VERSION
=======

   0.129

AUTHOR
======

   (c) 1997-1999 Jan Pazdziora, adelton@fi.muni.cz

SEE ALSO
========

   perl(1), XBase(3)

Frequently asked questions about the XBase.pm/DBD::XBase modules
****************************************************************

NAME
====

   XBase::FAQ - Frequently asked questions about the XBase.pm/DBD::XBase
modules

DESCRIPTION
===========

   This is a list of questions people asked since the module has been
announced in fall 1997, and my answers to them.

AUTHOR
======

   *Jan Pazdziora*, adelton@fi.muni.cz

Questions and answers
=====================

What Perl version do I need? What other modules?
     You need perl at least 5.004. I test each new distribution agains
     5.005* and 5.004_04 version of perl. You need DBI module version 1.00
     or higher, if you want to use the DBD driver (which you should).

Can I use *XBase.pm* under Windows 95/NT?
     Yes. It's a standard Perl module so there is no reason it shouldn't.
     Or, actually, there are a lot of reasons why standard thing do not
     work on systems that are broken, but I'm trying hard to workaround
     these bugs. If you find a problem on these platform, send me a
     description and I'll try to find yet another workaround.

Is there a choice of the format of the date?
     The only possible format in which you can get the date and that the
     module expect for inserts and updates is a 8 char string 'YYYYMMDD'.
     It is not possible to change this format. I prefer to do the formating
     myself since you have more control over it.

With *XBase.pm*, the get_record also returns records marked as deleted. Why?
     Because. You get the _DELETED flag as the first value of the array.
     This gives you a possibility to decide what to do - undelete,
     ignore... It's a feature - you say you want a record of given number,
     you get it and get additional information, if the record is or isn't
     deleted.

However, when reading the same file using *DBD::XBase*, I do not see the deleted records.
     That's correct: *DBD::XBase* only gives you records that are
     positively in the file and not deleted. Which shows that *XBase.pm*
     is a lower level tool because you can touch records that are deleted,
     while *DBD::XBase* is higher level - it gives you SQL interface and
     let's you work with the file more naturaly (what is deleted should
     stay deleted).

I have this dbf/something file created with [your favorite] tool and *XBase.pm* cannot read it.
     Describe exactly, what you expect and what you get. Send me the file
     (I understand attachments, uuencode, tar, gzip and zip) so that I can
     check what it going on and make *XBase.pm* undestand your file.  A
     small sample (three rows, or so) are generally enough but you can
     send the whole file if it doesn't have megabytes.

I want to install the module but I do not have make on my [your damaged] system.
     On Win* platform and with ActiveState port, use ppm to install
     *DBD::XBase* from ActiveState's site. You can also just copy the files
     from the lib directory of the distribution to where perl can find
     them. See README.

I have make but I cannot install into default directory and my sysadmin doesn't want to do it for me.
     Fire the sysadmin. See README for how to install into and use
     nonstandard place for the module.

Can I access one dbf file both from Perl and (say) Clipper?
     For reading - yes. For writing - *XBase.pm* has a locksh and lockex
     method to lock the file. The question is to what extend Clipper (or
     Fox* or whatever) uses the same system calls. So the answer is that
     for multiple updates you should probably consider real RDBMS system
     (PostgreSQL, MySQL, Oracle, to name a few).

XBase.pm/DBD::XBase breaks my accented characters.
     No, it doesn't. The character data is returned exactly as it appears
     in the dbf/dbt file. You probably brought the file from differenct
     system that uses differend character encodings. So some bytes in the
     strings have different meaning on that system. You also probably have
     fonts in different encoding on that system. In the Czech language, we
     have about 6 different encoding that affect possition at which
     accented characters appear.

     So what you really want to do is to use some external utility to
     convert the strings to encoding you need - for example, when I bring
     the dbf from Win*, ot often is in the Windows-1250 or PC-Latin-2
     encoding, while the standard is ISO-8859-2. I use my utility
     *Cz::Cstocs* to do the conversion, you maight also try GNU program
     *recode*.

How do I access the fields in the memo file?
     Just read the memo field, it will fetch the data from the memo file
     for you transparently.

I try to use `select * from table where field = '%str%'' but it doesn't work. Why?
     If you want to match wildcards with *DBD::XBase*, you have to use
     like:

          select * from table where field like '%str%'

Can I sue you if I use XBase.pm/DBD::XBase and it corrupts my dbf's?
     No. At least, I hope no. The software is provided without any
     warranty, in a hope you might find is usefull. Which is by the way
     the same as with most other software, even if you pay for that. What
     is different with XBase.pm/DBD::XBase is the fact that if you find out
     that the results are different from those expected, you are welcome to
     contact me, describe the problem and send me the files that give the
     module troubles, and I'll try to find a reason and fix the module.

What dbf/other files standard does the module support?
     I try to support any file that looks reasonably as
     dbf/dbt/fpt/smt/ndx/ntx/mdx/idx/cdx. There are many clones of
     XBase-like software, each adding its own extension. The module tries
     to accept all different variations. To do that, I need your
     cooperation however - usually good description of the problem, file
     sample and expected results lead to rather fast patch.

What SQL standard does the *DBD::XBase* support?
     If supports a reasonable subset of the SQL syntax, IMHO. So you can do
     select, delete, insert and update, create and drop table. If there is
     something that should be added, let me know and I will consider it.
     Having said that, I do not expect to ever support joins, for example.
     This module is more a parser to read files from your legacy
     applications that a RDBMS - you can find plenty of them around - use
     them.

I downloaded you module to [fill your] system and I do not know how to install it.
     Did you follow the steps in the README? Where did it fail? This module
     uses a standard way modules in Perl are installed. If you've never
     installed a module on your system and you system is so unstandard that
     the general instrauction do not help, you should contact your system
     administrator or the support for your system.

Does the module allow for any aggregate functions in the select, like select max(field) from table?
     No, aggregate functions are not supported. It would probably be very
     slow, since the DBD doesn't make use of indexes at the moment. I do
     not have plans to add this support in some near future.

I try to `DBI->connect' on my [fill your favorite] system and it says that the directory doesn't exist. But it's there. Is *DBD::XBase* mad or what?
     The third part of the first parameter to the connect is the directory
     where *DBD::XBase* will look for the dbf files. During connect, the
     module checks `if -d $directory'. So if it says it's not there, it's
     not there and the only thing *DBD::XBase* can do about it is to
     report it to you. It might be that the directory is not mounted, you
     do not have permissions to it, the script is running under different
     UID than when you try it from command line... Anyway, add

          die "Error reading $dir: $!\n" unless -d $dir;

     to your script and you will see that it's not *DBD::XBase* problem.

The *XBase.pm/dbfdump* stops after reading n records. Why doesn't it read all *10 x n* records?
     Check if the file isn't truncated. `dbfdump -i file.dbf' will tell
     you the expected number of records and length of one record, like

          Filename:       file.dbf
          Version:        0x03 (ver. 3)
          Num of records: 65
          Header length:  1313
          Record length:  1117
          Last change:    1998/12/18
          Num fields:     40

     So the expected length of the file is at least *1313 + 65 * 1117*. If
     it's shorted, you've got damaged file and *XBase.pm/dbfdump* only
     reads as much rows as it can find in the dbf.

How is this *DBD::XBase* related to *DBD::ODBC*?
     *DBD::XBase* reads the dbf files directly, using the (included)
     *XBase.pm* module. So it will run on any platform with reasonable new
     perl. With *DBD::ODBC*, you need an ODBC server, or some program, that
     *DBD::ODBC* could talk to. Many proprietary software can serve as ODBC
     source for dbf files, it just doesn't seem to run on Un*x systems. And
     is also much more resource intensive, if you just need to read the
     file record by record and convert it to HTML page or do similary
     simple operation with it.

How do I pack the dbf file, after the records were deleted?
     *XBase.pm* doesn't support this directly. You'd probably want to
     create new table, copy the data and rename back. Patches are always
     welcome.

Foxpro doesn't see all fields in dbf created with *XBase.pm*.
     Put 'version' => 3 options in to the create call - that way we say
     that the dbf file is dBaseIII style.

base class for the index files for dbf
**************************************

NAME
====

   XBase::Index - base class for the index files for dbf

SYNOPSIS
========

     use XBase;
     my $table = new XBase "data.dbf";
     my $cur = $table->prepare_select_with_index("id.ndx",
     	"ID", "NAME);
     $cur->find_eq(1097);

     while (my @data = $cur->fetch()) {
     	last if $data[0] != 1097;
     	print "@data\n";
     }

   This is a snippet of code to print ID and NAME fields from dbf data.dbf
where ID equals 1097. Provided you have index on ID in file id.ndx. You
can use the same code for ntx and idx index files.  For the cdx and mdx,
the prepare_select call would be

     prepare_select_with_index(['rooms.cdx', 'ROOMNAME'])

   so instead of plain filename you specify an arrayref with filename and
an index tag in that file. The reason is that cdx and mdx can contain
multiple indexes in one file and you have to distinguish, which you want
to use.

DESCRIPTION
===========

   The module XBase::Index is a collection of packages to provide index
support for XBase-like dbf database files.

   An index file is generaly a file that holds values of certain database
field or expression in sorted order, together with the record number that
the record occupies in the dbf file. So when you search for a record with
some value, you first search in this sorted list and once you have the
record number in the dbf, you directly fetch the record from dbf.

What indexes do
---------------

   To make the searching in this ordered list fast, it's generally
organized as a tree - it starts with a root page with records that point to
pages at lower level, etc., until leaf pages where the pointer is no
longer a pointer to the index but to the dbf. When you search for a record
in the index file, you fetch the root page and scan it (lineary) until you
find key value that is equal or grater than that you are looking for. That
way you've avoided reading all pages describing the values that are lower.
Here you descend one level, fetch the page and again search the list of
keys in that page. And you repeat this process until you get to the leaf
(lowest) level and here you finaly find a pointer to the dbf. XBase::Index
does this for you.

   Some of the formats also support multiple indexes in one file - usually
there is one top level index that for different field values points to
different root pages in the index file (so called tags).

   XBase::Index supports (or aims to support) the following index formats:
ndx, ntx, mdx, cdx and idx. They differ in a way they store the keys and
pointers but the idea is always the same: make a tree of pages, where the
page contains keys and pointer either to pages at lower levels, or to dbf
(or both). XBase::Index only supports read only access to the index fields
at the moment (and if you need writing them as well, follow reading
because we need to have the reading support stable before I get to work on
updating the indexes).

Testing your index file (and XBase::Index)
------------------------------------------

   You can test your index using the indexdump script in the main
directory of the DBD::XBase distribution (I mean test XBase::Index on
correct index data, not testing corrupted index file, of course ;-) Just
run

     ./indexdump ~/path/index.ndx
     ./indexdump ~/path/index.cdx tag_name

   or

     perl -Ilib ./indexdump ~/path/index.cdx tag_name

   if you haven't installed this version of XBase.pm/DBD::XBase yet. You
should get the content of the index file. On each row, there is the key
value and a record number of the record in the dbf file. Let me know if
you get results different from those you expect. I'd probably ask you to
send me the index file (and possibly the dbf file as well), so that I can
debug the problem.

   The index file is (as already noted) a complement to a dbf file. Index
file without a dbf doesn't make much sense because the only thing that you
can get from it is the record number in the dbf file, not the actual data.
But it makes sense to test - dump the content of the index to see if the
sequence is OK.

   The index formats usually distinguish between numeric and character
data. Some of the file formats include the information about the type in
the index file, other depend on the dbf file. Since with indexdump we only
look at the index file, you may need to specify the -type option to
indexdump if it complains that it doesn't know the data type of the values
(this is the case with cdx at least). The possible values are num, char
and date and the call would be like

     ./indexdump -type=num ~/path/index.cdx tag_name

   (this -type option may not work with all index formats at the moment -
will be fixed and patches always welcome).

   You can use `-ddebug' option to indexdump to see how pages are fetched
and decoded, or run debugger to see the calls and parsing.

Using the index files to speed up searches in dbf
-------------------------------------------------

   The syntax for using the index files to access data in the dbf file is
generally

     my $table = new XBase "tablename";
     	# or any other arguments to get the XBase object
     	# see XBase(3)
     my $cur = $table->prepare_select_with_index("indexfile",
     	"list", "of", "fields", "to", "return");

   or

     my $cur = $table->prepare_select_with_index(
     	[ "indexfile_with_tags", "tag_name" ],
     	"list", "of", "fields", "to", "return");

   where we specify the tag in the index file (this is necessary with cdx
and mdx). After we have the cursor, we can search to given record and
start fetching the data:

     $cur->find_eq('jezek');
     while (my @data = $cur->fetch) { # do something

Supported index formats
-----------------------

   The following table summarizes which formats are supproted by
XBase::Index. If the field says something else that Yes, I welcome testers
and offers of example index files.

     Reading of index files -- types supported by XBase::Index

     type	string		numeric		date
     ----------------------------------------------------------
     ndx	Yes		Yes		Yes (you need to
     					convert to Julian)

     ntx	Yes		Yes		Untested

     idx	Untested	Untested	Untested
     	(but should be pretty usable)

     mdx	Untested	Untested	Untested

     cdx	Yes		Yes		Untested

     Writing of index files -- not supported untill the reading
     is stable enough.

   So if you have access to an index file that is untested or unsupported
and you care about support of these formats, contact me. If you are able
to actually generate those files on request, the better because I may need
specific file size or type to check something. If the file format you work
with is supported, I still appreciate a report that it really works for
you.

   *Please note* that there is very little documentation about the file
formats and the work on XBase::Index is heavilly based on making
assumption based on real life data. Also, the documentation is often wrong
or only describing some format variations but not the others.  I
personally do not need the index support but am more than happy to make it
a reality for you. So I need your help - contact me if it doesn't work for
you and offer me your files for testing. Mentioning word XBase somewhere
in the Subject line will get you (hopefully ;-) fast response. Mentioning
work Help or similar stupidity will probably make my filters to consider
your email as spam. Help yourself by making my life easier in helping you.

Programmer's notes
------------------

   Programmers might find the following information usefull when trying to
debug XBase::Index from their files:

   The XBase::Index module contains the basic XBase::Index package and
also packages XBase::ndx, XBase::ntx, XBase::idx, XBase::mdx and
XBase::cdx, and for each of these also a package XBase::index_type::Page.
Reading the file goes like this: you create as object calling either new
XBase::Index or new XBase::ndx (or whatever the index type is). This can
also be done behind the scenes, for example
XBase::prepare_select_with_index calls new XBase::Index.  The index file
is opened using the XBase::Base::new/open and then the
XBase::index_type::read_header is called. This function fills the basic
data fields of the object from the header of the file. The new method
returns the object corresponding to the index type.

   Then you probably want to do $index->prepare_select or
$index->prepare_select_eq, that would possition you just before record
equal or greater than the parameter (record in the index file, that is).
Then you do a series of fetch'es that return next pair of (key,
pointer_to_dbf). Behind the scenes, prepare_select_eq or fetch call
XBase::Index::get_record which in turn calls XBase::index_type::Page::new.
From the index file perspective, the atomic item in the file is one index
page (or block, or whatever you call it). The XBase::index_type::Page::new
reads the block of data from the file and parses the information in the
page - pages have more or less complex structures. Page::new fills the
structure, so that the fetch calls can easily check what values are in the
page.

   For some examples, please see eg/use_index in the distribution
directory.

VERSION
=======

   0.170

AUTHOR
======

   (c) 1998-2001 Jan Pazdziora, adelton@fi.muni.cz

SEE ALSO
========

   XBase(3), XBase::FAQ(3)

Generic support for various memo formats
****************************************

NAME
====

   XBase::Memo - Generic support for various memo formats

SYNOPSIS
========

   Used indirectly, via XBase. Users should check its man page.

DESCRIPTION
===========

   Objects of this class are created to deal with memo files, currently
.dbt, .fpt and .smt (code for this provided by Dirk Tostmann).  Package
XBase::Memo defines methods read_header to parse that header of the file
and set object's structures, *write_record* and last_record to write the
records properly formated and find the end of file.

   There are four separate subpackages in XBase::Memo, dBaseIII, dBaseIV,
Fox and Apollo. Memo objects are effectively of one of these types and
they override their specific record handling routines where appropriate.

VERSION
=======

   0.172

AUTHOR
======

   (c) 1997-2001 Jan Pazdziora, adelton@fi.muni.cz

SEE ALSO
========

   perl(1), XBase(3)

SDBM nonportable index support for dbf
**************************************

NAME
====

   XBase::SDBM - SDBM nonportable index support for dbf

VERSION
=======

   0.162

AUTHOR
======

   (c) 2001 Jan Pazdziora, adelton@fi.muni.cz,
http://www.fi.muni.cz/~adelton/ at Faculty of Informatics, Masaryk
University in Brno, Czech Republic

   All rights reserved. This package is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

DOCTYPE based XML output
************************

NAME
====

   XML::AutoWriter - DOCTYPE based XML output

SYNOPSIS
========

     use XML::Doctype         NAME => a, SYSTEM_ID => 'a.dtd' ;
     use XML::AutoWriter qw( :all :dtd_tags ) ;
     #
     # a.dtd contains:
     #
     #   <!ELEMENT a ( b1, b2?, b3* ) >
     #	  <!ATTLIST   a aa1 CDATA       #REQUIRED >
     #   <!ELEMENT b1 ( c1 ) >
     #   <!ELEMENT b2 ( c2 ) >
     #
     b1 ;                # Emits <a><b1>
     c2( attr=>"val" ) ; # Emits </b1><b2><c2 attr="val">
     endAllTags ;        # Emits </c2></b2></a>

     ## If you've got an XML::Doctype object handy:
     use XML::AutoWriter qw( :dtd_tags ), DOCTYPE => $doctype ;

     ## If you've saved a preparsed DTD as a perl module
     use FooML::Doctype::v1_0001 ;
     use XML::AutoWriter qw( :dtd_tags ) ;

     ## Or as a normal perl object:
     $writer = XML::AutoWriter->new( ... ) ;
     $writer->startTag( 'b1' ) ;
     $writer->startTag( 'c2' ) ;
     $writer->end ;

STATUS
======

   Alpha.  Use and patch, don't depend on things not changing drastically.

   Many methods supplied by XML::Writer are not yet supplied here.

DESCRIPTION
===========

   This module subclasses XML/ValidWriter, and
provides automatic start and end tag generation, allowing you to emit only
the 'important' tags.

   See XML::ValidWriter for the details on all functions not documented
here.

XML::Writer API compatibility
-----------------------------

   Much of the interface is patterned after XML::Writer so that it can
possibly be used as a drop-in replacement.  It will take awhile before
this module emulates enough of XML::Writer to be a drop-in replacement in
situations where the more advanced XML::Writer methods are used.

Automatic start tags
--------------------

   Automatic start tag creation is done when emitting a start tag that is
not allowed to be a child of the currently open tag but is allowed to be
contained in the currently open tag's subset.  In this case, the minimal
number of start tags necessary to allow All start tags between the current
tag and the desired tag are automatically emitted with no attributes.

Automatic end tags
------------------

   If start tag autogeneration fails, then end tag autogeneration is
attempted.  startTag() scans the stack of currently open tags trying to
close as few as possible before start tag autogeneration suceeds.

   Explicit end tags may be emitted to prevent unwanted automatic start
tags, and, in the future, warnings or errors will be available in place of
automatic start and end tag creation.

METHODS AND FUNCTIONS
=====================

   All of the routines in this module can be called as either functions or
methods unless otherwise noted.

   To call these routines as functions use either the DOCTYPE or :dtd_tags
options in the parameters to the use statement:

     use XML::AutoWriter DOCTYPE => XML::Doctype->new( ... ) ;
     use XML::AutoWriter qw( :dtd_tags ) ;

   This associates an XML::AutoWriter and an XML::Doctype with the
package.  These are used by the routines when called as functions.

new
          $writer = XML::AutoWriter->new( DTD => $dtd, OUTPUT => \*FH ) ;

     Creates an XML::AutoWriter.

     All other parameters are passed to the XML::ValidWriter base class
     constructor.

characters
          characters( 'yabba dabba dooo' ) ;
          $writer->characters( 'yabba dabba dooo' ) ;

     If the currently open tag cannot contain #PCDATA, then start tag
     autogeneration will be attempted, followed by end tag autogeneration.

     Start tag autogeneration takes place even if you pass in only ", or
     even (), the empty list.

endTag
          endTag ;
          endTag( 'a' ) ;
          $writer->endTag ;
          $writer->endTag( 'a' ) ;

     Prints one or more end tags.  The tag name is optional and defaults
     to the most recently emitted start tag if not present.

     This will emit as many close tags as necessary to close the supplied
     tag name, or will emit an error if the tag name specified is not open
     in the output document.

startTag
          startTag( 'a', attr => val ) ;  # use default XML::AutoWriter for
                                          # current package.
          $writer->startTag( 'a', attr => val ) ;

     Emits a named start tag with optional attributes.  If the named tag
     cannot be a child of the most recently started tag, then any tags
     that need to be opened between that one and the named tag are opened.

     If the named tag cannot be enclosed within the most recently opened
     tag, no matter how deep, then startTag() tries to end as few started
     tags as necessary to allow the named tag to be emitted within a tag
     already on the stack.

     This warns (once) if no <?xml?> declaration has been emitted.  It
     does not check to see if a <!DOCTYPE...> has been emitted.  It dies
     if an attempt is made to emit a second root element.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

COPYRIGHT
=========

   This module is Copyright 2000, Barrie Slaymaker.  All rights reserved.

   This module is licensed under the GPL, version 2.  Please contact me if
this does not suit your needs.

Resolve public identifiers and remap system identifiers
*******************************************************

NAME
====

   XML::Catalog - Resolve public identifiers and remap system identifiers

SYNOPSIS
========

     use XML::Catalog;
     my $catalog=XML::Catalog->new('/xml/catalog.cat');
     $catalog->add('http://www.w3.org/xcatalog/mastercat.xml');
     my $sysid=$catalog->resolve_public('-//John Cowan//LOC Diacritics');
     my $newsysid=$catalog->remap_system('http://www.w3.org');
     $parser->setHandlers(ExternEnt=>$catalog->get_handler($parser));

DESCRIPTION
===========

   This module implements draft 0.4 of John Cowan's XML Catalog (formerly
known as XCatalog) proposal
(<http://www.ccil.org/~cowan/XML/XCatalog.html>).  Catalogs may be written
in either SOCAT or XML syntax (see the proposal for syntax details);
XML::Catalog will assume SOCAT syntax if the catalog is not in well-formed
XML syntax.

CONSTRUCTOR
===========

new(URL [,URL]*)
     Read the catalog identified by URL and return a catalog object
     implementing it.  If more than one URL is given, chain the additional
     catalogs as extensions to the catalog (they will be searched before
     catalogs specified by EXTEND entries).

     All URLs must be absolute.  A URL with no protocol is treated as a
     filename.

METHODS
=======

add(URL [,URL]*)
     Chain the catalogs identified by the URL(s) to the current catalog.

resolve_public(PUBID)
     Translate the public identifier PUBID to a system identifier.  Returns
     undef if the identifier could not be translated.

remap_system(SYSID)
     Remap the system identifier SYSID as specified by the catalog.
     Returns SYSID unchanged if no remapping was found.

get_handler(PARSER)
     Returns a coderef to a resolver suitable for use as the ExternEnt
     handler for an XML::Parser object.  The resolver will first attempt
     to resolve a public identifier if supplied, and then attempt to remap
     the resulting system identifier (or the original system identifier if
     no public identifier was supplied).  It will then call the original
     ExternEnt handler associated with the parser object.  PARSER is the
     parser object; it is needed as an argument in order to obtain the
     original handler.

BUGS / TODO
===========

   Searching of chained catalogs is not purely depth-first (EXTEND items
in a chained catalog will be searched before EXTEND items in the original
catalog.

   Error checking leaves much to be desired.

AUTHOR
======

   Eric Bohlman (ebohlman@netcom.com)

COPYRIGHT
=========

   Copyright 1999-2000 Eric Bohlman.  All rights reserved.

   This program is free software; you can use/modify/redistribute it under
the same terms as Perl itself.

A perl module for validating XML
********************************

NAME
====

   XML::Checker - A perl module for validating XML

SYNOPSIS
========

   See XML/Checker/Parser, - an XML/Parser,
that validates at parse time

   See XML/DOM/ValParser, - an XML/DOM/Parser,
that validates at parse time

   (Some of the package names may change! This is only an alpha release...)

DESCRIPTION
===========

   XML::Checker can be used in different ways to validate XML. See the
manual pages of XML/Checker/Parser, and
XML/DOM/ValParser, for more information.

   This document only describes common topics like error handling and the
XML::Checker class itself.

   WARNING: Not all errors are currently checked. Almost everything is
subject to change. Some reported errors may not be real errors.

ERROR HANDLING
==============

   Whenever XML::Checker (or one of the packages that uses XML::Checker)
detects a potential error, the 'fail handler' is called. It is currently
also called to report information, like how many times an Entity was
referenced.  (The whole error handling mechanism is subject to change, I'm
afraid...)

   The default fail handler is XML::Checker::print_error(), which prints
an error message to STDERR. It does not stop the XML::Checker, so it will
continue looking for other errors.  The error message is created with
XML::Checker::error_string().

   You can define your own fail handler in two ways, locally and globally.
Use a local variable to temporarily override the fail handler. This way
the default fail handler is restored when the local variable goes out of
scope, esp. when exceptions are thrown e.g.

     # Using a local variable to temporarily override the fail handler (preferred)
     { # new block - start of local scope
       local $XML::Checker::FAIL = \&my_fail;
       ... your code here ...
     } # end of block - the previous fail handler is restored

   You can also set the error handler globally, risking that your code may
not be reusable or may clash with other modules that use XML::Checker.

     # Globally setting the fail handler (not recommended)
     $XML::Checker::FAIL = \&my_fail;
     ... rest of your code ...

   The fail handler is called with the following parameters ($code, $msg,
@context), where $code is the error code, $msg is the error description and
@context contains information on where the error occurred. The @context is
a (ordered) list of (key,value) pairs and can easily be turned into a hash.
It contains the following information:

     Element - tag name of Element node (if applicable)
     Attr - attribute name (if applicable)
     ChildElementIndex - if applicable (see error 157)
     line - only when parsing
     column - only when parsing
     byte - only when parsing (-1 means: end of file)

   Some examples of fail handlers:

     # Don't print info messages
     sub my_fail
     {
         my $code = shift;
         print STDERR XML::Checker::error_message ($code, @_)
             if $code < 300;
     }

     # Die when the first error is encountered - this will stop
     # the parsing process. Ignore information messages.
     sub my_fail
     {
         my $code = shift;
         die XML::Checker::error_message ($code, @_) if $code < 300;
     }

     # Count the number of undefined NOTATION references
     # and print the error as usual
     sub my_fail
     {
         my $code = shift;
         $count_undef_notations++ if $code == 100;
         XML::Checker::print_error ($code, @_);
     }

     # Die when an error is encountered.
     # Don't die if a warning or info message is encountered, just print a message.
     sub my_fail {
         my $code = shift;
         die XML::Checker::error_string ($code, @_) if $code < 200;
         XML::Checker::print_error ($code, @_);
     }

INSIGNIFICANT WHITESPACE
========================

   XML::Checker keeps track of whether whitespace found in character data
is significant or not. It is considered insignicant if it is found inside
an element that has a ELEMENT rule that is not of type Mixed or of type
ANY.  (A Mixed ELEMENT rule does contains the #PCDATA keyword.  An ANY
rule contains the ANY keyword. See the XML spec for more info.)

   XML::Checker can not determine whether whitespace is insignificant in
those two cases, because they both allow regular character data to appear
within XML elements and XML::Checker can therefore not deduce whether
whitespace is part of the actual data or was just added for readability of
the XML file.

   XML::Checker::Parser and XML::DOM::ValParser both have the option to
skip insignificant whitespace when setting SkipInsignifWS to 1 in their
constructor.  If set, they will not call the Char handler when
insignificant whitespace is encountered. This means that in
XML::DOM::ValParser no Text nodes are created for insignificant whitespace.

   Regardless of whether the SkipInsignifWS options is set, XML::Checker
always keeps track of whether whitespace is insignificant. After making a
call to XML::Checker's Char handler, you can find out if it was
insignificant whitespace by calling the isInsignifWS method.

   When using multiple (nested) XML::Checker instances or when using
XML::Checker without using XML::Checker::Parser or XML::DOM::ValParser
(which hardly anybody probably will), make sure to set a local variable in
the scope of your checking code, e.g.

     { # new block - start of local scope
       local $XML::Checker::INSIGNIF_WS = 0;
       ... insert your code here ...
     } # end of scope

ERROR CODES
===========

   There are 3 categories, errors, warnings and info messages.  (The codes
are still subject to change, as well the error descriptions.)

   Most errors have a link to the appropriate Validaty Constraint (*VC*)
or other section in the XML specification.

ERROR Messages
--------------

100 - 109
---------

   * 100 - undefined NOTATION [$notation] in ATTLIST

     The ATTLIST contained a Notation reference that was not defined in a
     NOTATION definition.  *VC:* `Notation Attributes|http:' in this node

   * 101 - undefined ELEMENT [$tagName]

     The specified Element was never defined in an ELEMENT definition.
     This is not an error according to the XML spec.  See `Element Type
     Declarations|http:' in this node

   * 102 - undefined unparsed ENTITY [$entity]

     The attribute value referenced an undefined unparsed entity.  *VC:*
     `Entity Name|http:' in this node

   * 103 - undefined attribute [$attrName]

     The specified attribute was not defined in an ATTLIST for that
     Element.  *VC:* `Attribute Value Type|http:' in this node

110 - 119
---------

   * 110 - attribute [$attrName] of element [$tagName] already defined

     The specified attribute was already defined in this ATTLIST
     definition or in a previous one.  This is not an error according to
     the XML spec.  See `Attribute-List Declarations|http:' in this node

   * 111 - ID [$value] already defined

     An ID with the specified value was already defined in an attribute
     within the same document.  *VC:* `ID|http:' in this node

   * 112 - unparsed ENTITY [$entity] already defined

     This is not an error according to the XML spec.  See `Entity
     Declarations|http:' in this node

   * 113 - NOTATION [$notation] already defined

   * 114 - ENTITY [$entity] already defined

     This is not an error according to the XML spec.  See `Entity
     Declarations|http:' in this node

   * 115 - ELEMENT [$name] already defined *VC:* `Unique Element Type
     Declaration|http:' in this node

120 - 129
---------

   * 120 - invalid default ENTITY [$default]

     (Or IDREF or NMTOKEN instead of ENTITY.)  The ENTITY, IDREF or
     NMTOKEN reference in the default attribute value for an attribute
     with types ENTITY, IDREF or NMTOKEN was not valid.  *VC:* `Attribute
     Default Legal|http:' in this node

   * 121 - invalid default [$token] in ENTITIES [$default]

     (Or IDREFS or NMTOKENS instead of ENTITIES) One of the ENTITY, IDREF
     or NMTOKEN references in the default attribute value for an attribute
     with types ENTITIES, IDREFS or NMTOKENS was not valid.  *VC:*
     `Attribute Default Legal|http:' in this node

   * 122 - invalid default attribute value [$default]

     The specified default attribute value is not a valid attribute value.
     *VC:* `Attribute Default Legal|http:' in this node

   * 123 - invalid default ID [$default], must be #REQUIRED or #IMPLIED

     The default attribute value for an attribute of type ID has to be
     #REQUIRED or #IMPLIED.  *VC:* `ID Attribute Default|http:' in this
     node

   * 124 - bad model [$model] for ELEMENT [$name]

     The model in the ELEMENT definition did not conform to the XML syntax
     for Mixed models.  See `Mixed Content|http:' in this node

130 - 139
---------

   * 130 - invalid NMTOKEN [$attrValue]

     The attribute value is not a valid NmToken token.  *VC:*
     `Enumeration|http:' in this node

   * 131 - invalid ID [$attrValue]

     The specified attribute value is not a valid Name token.  *VC:*
     `ID|http:' in this node

   * 132 - invalid IDREF [$value]

     The specified attribute value is not a valid Name token.  *VC:*
     `IDREF|http:' in this node

   * 133 - invalid ENTITY name [$name]

     The specified attribute value is not a valid Name token.  *VC:*
     `Entity Name|http:' in this node

   * 134 - invalid Enumeration value [$value] in ATTLIST

     The specified value is not a valid NmToken (see XML spec for def.)
     See definition of `NmToken|http:' in this node

   * 135 - empty NOTATION list in ATTLIST

     The NOTATION list of the ATTLIST definition did not contain any
     NOTATION references.  See definition of `NotationType|http:' in this
     node

   * 136 - empty Enumeration list in ATTLIST

     The ATTLIST definition of the attribute of type Enumeration did not
     contain any values.  See definition of `Enumeration|http:' in this
     node

   * 137 - invalid ATTLIST type [$type]

     The attribute type has to be one of: ID, IDREF, IDREFS, ENTITY,
     ENTITIES, NMTOKEN, NMTOKENS, CDATA, NOTATION or an Enumeration.  See
     definition of `AttType|http:' in this node

150 - 159
---------

   * *150* - bad #FIXED attribute value [$value], it should be [$default]

     The specified attribute was defined as #FIXED in the ATTLIST
     definition and the found attribute $value differs from the specified
     $default value.  *VC:* `Fixed Attribute Default|http:' in this node

   * *151* - only one ID allowed in ATTLIST per element first=[$attrName]

     The ATTLIST definitions for an Element may contain only one attribute
     with the type ID. The specified $attrName is the one that was found
     first.  *VC:* `One ID per Element Type|http:' in this node

   * *152* - Element should be EMPTY, found Element [$tagName]

     The ELEMENT definition for the specified Element said it should be
     EMPTY, but a child Element was found.  *VC:* `Element Valid
     (sub1)|http:' in this node

   * *153* - Element should be EMPTY, found text [$text]

     The ELEMENT definition for the specified Element said it should be
     EMPTY, but text was found. Currently, whitespace is not allowed
     between the open and close tag. (This may be wrong, please give
     feedback.)  To allow whitespace (subject to change), set:

          $XML::Checker::Context::EMPTY::ALLOW_WHITE_SPACE = 1;

     *VC:* `Element Valid (sub1)|http:' in this node

   * *154* - bad order of Elements Found=[$found] RE=[$re]

     The child elements of the specified Element did not match the regular
     expression found in the ELEMENT definition. $found contains a comma
     separated list of all the child element tag names that were found.
     $re contains the (decoded) regular expression that was used
     internally.  *VC:* `Element Valid|http:' in this node

   * *155* - more than one root Element [$tags]

     An XML Document may only contain one Element.  $tags is a comma
     separated list of element tag names encountered sofar.  See
     XML/Parser, (expat) throws 'no element found' exception.
     See two_roots.xml for an example.  See definition of `document|http:'
     in this node

   * *156* - unexpected root Element [$tagName], expected [$rootTagName]

     The tag name of the root Element of the XML Document differs from the
     name specified in the DOCTYPE section.  See XML/Parser,
     (expat) throws 'not well-formed' exception.  See bad_root.xml for an
     example.  *VC:* `Root Element Type|http:' in this node

   * *157* - unexpected Element [$tagName]

     The ELEMENT definition for the specified Element does not allow child
     Elements with the specified $tagName.  *VC:* `Element Valid|http:' in
     this node

     The error context contains ChildElementIndex which is the index within
     its parent Element (counting only Element nodes.)

   * *158* - unspecified value for #IMPLIED attribute [$attrName]

     The ATTLIST for the specified attribute said the attribute was
     #IMPLIED, which means the user application should supply a value, but
     the attribute value was not specified. (User applications should pass
     a value and set $specified to 1 in the Attr handler.)

   * *159* - unspecified value for #REQUIRED attribute [$attrName]

     The ATTLIST for the specified attribute said the attribute was
     #REQUIRED, which means that a value should have been specified.
     *VC:* `Required Attribute|http:' in this node

160 - 169
---------

   * *160* - invalid Enumeration value [$attrValue]

     The specified attribute value does not match one of the Enumeration
     values in the ATTLIST.  *VC:* `Enumeration|http:' in this node

   * *161* - invalid NOTATION value [$attrValue]

     The specifed attribute value was not found in the list of possible
     NOTATION references as found in the ATTLIST definition.  *VC:*
     `Notation Attributes|http:' in this node

   * *162* - undefined NOTATION [$attrValue]

     The NOTATION referenced by the specified attribute value was not
     defined.  *VC:* `Notation Attributes|http:' in this node

WARNING Messages (200 and up)
-----------------------------

   * *200* - undefined ID [$id] was referenced [$n] times

     The specified ID was referenced $n times, but never defined in an
     attribute value with type ID.  *VC:* `IDREF|http:' in this node

INFO Messages (300 and up)
--------------------------

   * *300* - [$n] references to ID [$id]

     The specified ID was referenced $n times.

Not checked
-----------

   The following errors are already checked by XML/Parser,
(expat) and are currently not checked by XML::Checker:

   (?? TODO - add more info)

root element is missing
     See XML/Parser, (expat) throws 'no element found'
     exception.  See no_root.xml for an example.

XML::Checker
============

   XML::Checker can be easily plugged into your application.  It uses
mostly the same style of event handlers (or callbacks) as
XML/Parser.  See XML/Parser, manual page
for descriptions of most handlers.

   It also implements PerlSAX style event handlers. See `PerlSAX
interface' in this node.

   Currently, the XML::Checker object is a blessed hash with the following
(potentially useful) entries:

     $checker->{RootElement} - root element name as found in the DOCTYPE
     $checker->{NOTATION}->{$notation} - is 1 if the NOTATION was defined
     $checker->{ENTITY}->{$name} - contains the (first) ENTITY value if defined
     $checker->{Unparsed}->{$entity} - is 1 if the unparsed ENTITY was defined
     $checker->{ID}->{$id} - is 1 if the ID was defined
     $checker->{IDREF}->{$id} - number of times the ID was referenced

     # Less useful:
     $checker->{ERule}->{$tag} - the ELEMENT rules by Element tag name
     $checker->{ARule}->{$tag} - the ATTLIST rules by Element tag name
     $checker->{Context} - context stack used internally
     $checker->{CurrARule} - current ATTLIST rule for the current Element

XML:Checker methods
-------------------

   This section is only interesting when using XML::Checker directly.
XML::Checker supports most event handlers that XML/Parser,
supports with minor differences. Note that the XML::Checker
event handler methods are instance methods and not static, so don't forget
to call them like this, without passing $expat (as in the
XML/Parser) handlers:

     $checker->Start($tagName);

Constructor
          $checker = new XML::Checker;
          $checker = new XML::Checker (%user_args);

     User data may be stored by client applications. Only $checker->{User}
     is guaranteed not to clash with internal hash keys.

getRootElement ()
          $tagName = $checker->getRootElement;

     Returns the root element name as found in the DOCTYPE

Expat interface
---------------

   XML::Checker supports what I call the *Expat* interface, which is the
collection of methods you normally specify as the callback handlers when
using XML::Parser.

   Only the following XML/Parser, handlers are currently
supported: Init, Final, Char, Start, End, Element, Attlist, Doctype,
Unparsed, Entity, Notation.

   I don't know how to correctly support the Default handler for all
XML/Parser, releases. The Start handler works a little
different (see below) and I added Attr, InitDomElem, FinalDomElem, CDATA
and EntityRef handlers.  See XML/Parser, for a
description of the handlers that are not listed below.

   Note that this interface may disappear, when the PerlSAX interface
stabilizes.

Start ($tag)
          $checker->Start($tag);

     Call this when an Element with the specified $tag name is encountered.
     Different from the Start handler in XML/Parser, in
     that no attributes are passed in (use the Attr handler for those.)

Attr ($tag, $attrName, $attrValue, $isSpecified)
          $checker->Attr($tag,$attrName,$attrValue,$spec);

     Checks an attribute with the specified $attrName and $attrValue
     against the ATTLIST definition of the element with the specified $tag
     name.  $isSpecified means whether the attribute was specified (1) or
     defaulted (0).

EndAttr ()
          $checker->EndAttr;

     This should be called after all attributes are passed with Attr().
     It will check which of the #REQUIRED attributes were not specified
     and generate the appropriate error (159) for each one that is missing.

CDATA ($text)
          $checker->CDATA($text);

     This should be called whenever CDATASections are encountered.
     Similar to Char handler (but might perform different checks later...)

EntityRef ($entity, $isParameterEntity)
          $checker->EntityRef($entity,$isParameterEntity);

     Checks the ENTITY reference. Set $isParameterEntity to 1 for entity
     references that start with '%'.

InitDomElem () and FinalDomElem ()
     Used by XML::DOM::Element::check() to initialize (and cleanup) the
     context stack when checking a single element.

PerlSAX interface
-----------------

   XML::Checker now also supports the PerlSAX interface, so you can use
XML::Checker wherever you use PerlSAX handlers.

   XML::Checker implements the following methods: start_document,
end_document, start_element, end_element, characters,
processing_instruction, comment, start_cdata, end_cdata, entity_reference,
notation_decl, unparsed_entity_decl, entity_decl, element_decl,
attlist_decl, doctype_decl, xml_decl

   Not implemented: set_document_locator, ignorable_whitespace

   See PerlSAX.pod for details. (It is called lib/PerlSAX.pod in the
libxml-perl distribution which can be found at CPAN.)

CAVEATS
=======

   This is an alpha release. Almost everything is subject to change.

AUTHOR
======

   Send bug reports, hints, tips, suggestions to Enno Derksen at
<`enno@att.com'>.

SEE ALSO
========

   The home page of XML::Checker at `http:' in this node

   The XML spec (Extensible Markup Language 1.0) at `http:' in this node

   The XML/Parser, and XML/Parser/Expat,
manual pages.

   The other packages that come with XML::Checker:
XML/Checker/Parser, XML/DOM/ValParser,

   The DOM Level 1 specification at `http:' in this node

   The PerlSAX specification. It is currently in lib/PerlSAX.pod in the
libxml-perl distribution by Ken MacLeod.

   The original SAX specification (Simple API for XML) can be found at
`http:' in this node and `http:' in this node

an XML::Parser that validates at parse time
*******************************************

NAME
====

   XML::Checker::Parser - an XML::Parser that validates at parse time

SYNOPSIS
========

     use XML::Checker::Parser;

     my %expat_options = (KeepCDATA => 1,
     		      Handlers => [ Unparsed => \&my_Unparsed_handler ]);
     my $parser = new XML::Checker::Parser (%expat_options);

     eval {
         local $XML::Checker::FAIL = \&my_fail;
         $parser->parsefile ("fail.xml");
     };
     if ($@) {
         # Either XML::Parser (expat) threw an exception or my_fail() died.
         ... your error handling code here ...
     }

     # Throws an exception (with die) when an error is encountered, this
     # will stop the parsing process.
     # Don't die if a warning or info message is encountered, just print a message.
     sub my_fail {
         my $code = shift;
         die XML::Checker::error_string ($code, @_) if $code < 200;
         XML::Checker::print_error ($code, @_);
     }

DESCRIPTION
===========

   XML::Checker::Parser extends XML/Parser,

   I hope the example in the SYNOPSIS says it all, just use
XML/Checker/Parser, as if it were an XML::Parser.  See
XML/Parser, for the supported (expat) options.

   You can also derive your parser from XML::Checker::Parser instead of
from XML::Parser. All you should have to do is replace:

     package MyParser;
     @ISA = qw( XML::Parser );

   with:

     package MyParser;
     @ISA = qw( XML::Checker::Parser );

XML::Checker::Parser constructor
================================

     $parser = new XML::Checker::Parser (SkipExternalDTD => 1, SkipInsignifWS => 1);

   The constructor takes the same parameters as XML/Parser,
with the following additions:

SkipExternalDTD
     By default, it will try to load external DTDs using LWP. You can
     disable this by setting SkipExternalDTD to 1. See `External
     DTDs|"External DTDs"' in this node for details.

SkipInsignifWS
     By default, it will treat insignificant whitespace as regular Char
     data.  By setting SkipInsignifWS to 1, the user Char handler will not
     be called if insignificant whitespace is encountered.  See
     `INSIGNIFICANT_WHITESPACE', see XML/Checker, for
     details.

LWP_UserAgent
     When calling parsefile() with a URL (instead of a filename) or when
     loading external DTDs, we use LWP to download the remote file. By
     default it will use a LWP/UserAgent, that is
     created as follows:

          use LWP::UserAgent;
          $LWP_USER_AGENT = LWP::UserAgent->new;
          $LWP_USER_AGENT->env_proxy;

     Note that `env_proxy' in this node reads proxy settings from your
     environment variables, which is what I need to do to get thru our
     firewall.  If you want to use a different LWP::UserAgent, you can
     either set it globally with:

          XML::Checker::Parser::set_LWP_UserAgent ($my_agent);

     or, you can specify it for a specific XML::Checker::Parser by passing
     it to the constructor:

          my $parser = new XML::Checker::Parser (LWP_UserAgent => $my_agent);

     Currently, LWP is used when the filename (passed to parsefile) starts
     with one of the following URL schemes: http, https, ftp, wais,
     gopher, or file (followed by a colon.) If I missed one, please let me
     know.

     The LWP modules are part of libwww-perl which is available at CPAN.

External DTDs
=============

   XML::Checker::Parser will try to load and parse external DTDs that are
referenced in DOCTYPE definitions unless you set the SkipExternalDTD
option to 1 (the default setting is 0.)  See `CAVEATS|"CAVEATS"' in this
node for details on what is not supported by XML::Checker::Parser.

   See XML/Parser, (version 2.27 and up) does a much better
job at reading external DTDs, because recently external DTD parsing was
added to expat.  Make sure you set the XML/Parser,
option ParseParamEnt to 1 and the XML::Checker::Parser option
SkipExternalDTD to 1.  (They can both be set in the XML::Checker::Parser
constructor.)

   When external DTDs are parsed by XML::Checker::Parser, they are located
in the following order:

   * With the %URI_MAP, which can be set using map_uri.  This hash maps
     external resource ids (like system ID's and public ID's) to full path
     URI's.  It was meant to aid in resolving PUBLIC IDs found in DOCTYPE
     declarations after the PUBLIC keyword, e.g.

          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">

     However, you can also use this to force XML/Checker,
     to read DTDs from a different URL than was specified
     (e.g. from the local file system for performance reasons.)

   * on the Internet, if their system identifier starts with a protocol
     (like http://...)

   * on the local disk, if their system identifier starts with a slash
     (absolute path)

   * in the SGML_SEARCH_PATH, if their system identifier is a relative
     file name. It will use @SGML_SEARCH_PATH if it was set with
     *set_sgml_search_path()*, or the colon-separated
     $ENV{SGML_SEARCH_PATH}, or (if that isn't set) the list (".",
     "$ENV{'HOME'}/.sgml", "/usr/lib/sgml", "/usr/share/sgml"), which
     includes the current directory, so it should do the right thing in
     most cases.

Static methods related to External DTDs
---------------------------------------

set_sgml_search_path (dir1, dir2, ...)
     External DTDs with relative file paths are looked up using the
     @SGML_SEARCH_PATH, which can be set with this method. If
     @SGML_SEARCH_PATH is never set, it will use the colon-separated
     $ENV{SGML_SEARCH_PATH} instead. If neither are set it uses the list:
     ".", "$ENV{'HOME'}/.sgml", "/usr/lib/sgml", "/usr/share/sgml".

     set_sgml_search_path is a static method.

map_uri (pubid => uri, ...)
     To define the location of PUBLIC ids, as found in DOCTYPE declarations
     after the PUBLIC keyword, e.g.

          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">

     call this method, e.g.

          XML::Checker::Parser::map_uri (
          	"-//W3C//DTD HTML 4.0//EN" => "file:/user/html.dtd");

     See `External DTDs|"External DTDs"' in this node for more info.

     XML::Checker::Parser::map_uri is a static method.

Switching user handlers at parse time
=====================================

   You should be able to use setHandlers() just as in XML/Parser.
(Using setHandlers has not been tested yet.)

Error handling
==============

   XML::Checker::Parser routes the fail handler through
XML::Checker::Parser::fail_add_context() before calling your fail handler
(i.e. the global fail handler: $XML::Checker::FAIL.  See `ERROR_HANDLING',
see XML/Checker.)  It adds the (line, column, byte)
information from `ERROR_HANDLING', see XML/Parser, to the
error context (unless it was the end of the XML document.)

Supported XML::Parser handlers
==============================

   Only the following XML/Parser, handlers are currently
routed through XML/Checker,: Init, Final, Char, Start,
End, Element, Attlist, Doctype, Unparsed, Notation.

CAVEATS
=======

   When using XML::Checker::Parser to parse external DTDs (i.e. with
SkipExternalDTD => 0), expect trouble when your external DTD contains
parameter entities inside declarations or conditional sections. The
external DTD should probably have the same encoding as the orignal XML
document.

AUTHOR
======

   Send bug reports, hints, tips, suggestions to Enno Derksen at
<`enno@att.com'>.

SEE ALSO
========

   See XML/Checker, (`SEE_ALSO', see XML/Checker),
`SEE_ALSO', see XML/Parser,

   Version: 0.1

   $Id: Config.pm,v 1.2 2000/05/21 23:41:03 matt Exp $

SYNOPSIS
========

   use XML::Config;

   my $cfg = new XML::Config; my %CONF =
$cfg->load_conf("path/to/file.xml");

     -OR-

   my %CONF = $cfg->load_conf("path/to/file.xml",\%your_local_config_hash);

     -OR-

   my %CONF = $cfg->load_conf("path/to/file.xml",\%your_local_config_hash,
\@do_not_overide_these);

DESCRIPTION
===========

   XML::Config is a simple shallow XML to hash converter.  Given a
configuration file in the form:

   <goxml_config process="spider"> 	<foo>Bar</foo> 	<bar>Foo</bar>
</goxml_config>

   ... XML::Config->load_conf returns:

   { 	foo => 'bar', 	bar => 'foo' }

   XML::Config will also try to load "path/to/file.xml.bak" in the case of
a non-file not found parse error.  if it does this, it will set the
err_str to "WARN: Loaded backup configuration\n";

   The second way of calling load_conf() with the hash reference allows
you to set defaults to your config hash, and have the XML overide some of
them.

   The third way makes it possible to disallow overwrites of certain
variables.  This is a good security measure.  =head1 METHODS

   load_conf($conf_file_path) err_str()

AUTHOR
======

   XML Global Technologies, Inc (Matthew MacKenzie)

COPYRIGHT
=========

   (c)2000 XML Global Technologies, Inc.

A perl module for building DOM Level 1 compliant document structures
********************************************************************

NAME
====

   XML::DOM - A perl module for building DOM Level 1 compliant document
structures

SYNOPSIS
========

     use XML::DOM;

     my $parser = new XML::DOM::Parser;
     my $doc = $parser->parsefile ("file.xml");

     # print all HREF attributes of all CODEBASE elements
     my $nodes = $doc->getElementsByTagName ("CODEBASE");
     my $n = $nodes->getLength;

     for (my $i = 0; $i < $n; $i++)
     {
         my $node = $nodes->item ($i);
         my $href = $node->getAttributeNode ("HREF");
         print $href->getValue . "\n";
     }

     # Print doc file
     $doc->printToFile ("out.xml");

     # Print to string
     print $doc->toString;

     # Avoid memory leaks - cleanup circular references for garbage collection
     $doc->dispose;

DESCRIPTION
===========

   This module extends the XML::Parser module by Clark Cooper.  The
XML::Parser module is built on top of XML::Parser::Expat, which is a lower
level interface to James Clark's expat library.

   XML::DOM::Parser is derived from XML::Parser. It parses XML strings or
files and builds a data structure that conforms to the API of the Document
Object Model as described at http://www.w3.org/TR/REC-DOM-Level-1.  See
the XML::Parser manpage for other available features of the
XML::DOM::Parser class.  Note that the 'Style' property should not be used
(it is set internally.)

   The XML::Parser *NoExpand* option is more or less supported, in that it
will generate EntityReference objects whenever an entity reference is
encountered in character data. I'm not sure how useful this is. Any
comments are welcome.

   As described in the synopsis, when you create an XML::DOM::Parser
object, the parse and parsefile methods create an *XML::DOM::Document*
object from the specified input. This Document object can then be
examined, modified and written back out to a file or converted to a string.

   When using XML::DOM with XML::Parser version 2.19 and up, setting the
XML::DOM::Parser option *KeepCDATA* to 1 will store CDATASections in
CDATASection nodes, instead of converting them to Text nodes.  Subsequent
CDATASection nodes will be merged into one. Let me know if this is a
problem.

   When using XML::Parser 2.27 and above, you can suppress expansion of
parameter entity references (e.g. %pent;) in the DTD, by setting
ParseParamEnt to 1 and *ExpandParamEnt* to 0. See `Hidden Nodes|' in this
node for details.

   A Document has a tree structure consisting of *Node* objects. A Node
may contain other nodes, depending on its type.  A Document may have
Element, Text, Comment, and CDATASection nodes.  Element nodes may have
Attr, Element, Text, Comment, and CDATASection nodes.  The other nodes may
not have any child nodes.

   This module adds several node types that are not part of the DOM spec
(yet.)  These are: ElementDecl (for <!ELEMENT ...> declarations),
AttlistDecl (for <!ATTLIST ...> declarations), XMLDecl (for <?xml ...?>
declarations) and AttDef (for attribute definitions in an AttlistDecl.)

XML::DOM Classes
================

   The XML::DOM module stores XML documents in a tree structure with a
root node of type XML::DOM::Document. Different nodes in tree represent
different parts of the XML file. The DOM Level 1 Specification defines the
following node types:

   * See XML/DOM/Node, - Super class of all node types

   * See XML/DOM/Document, - The root of the XML
     document

   * See XML/DOM/DocumentType, - Describes the
     document structure: <!DOCTYPE root [ ... ]>

   * See XML/DOM/Element, - An XML element: <elem
     attr="val"> ... </elem>

   * See XML/DOM/Attr, - An XML element attribute:
     name="value"

   * See XML/DOM/CharacterData, - Super class of
     Text, Comment and CDATASection

   * See XML/DOM/Text, - Text in an XML element

   * See XML/DOM/CDATASection, - Escaped block of
     text: <![CDATA[ text ]]>

   * See XML/DOM/Comment, - An XML comment: <!- comment
     ->

   * See XML/DOM/EntityReference, - Refers to
     an ENTITY: &ent; or %ent;

   * See XML/DOM/Entity, - An ENTITY definition:
     <!ENTITY ...>

   * See XML/DOM/ProcessingInstruction, -
     <?PI target>

   * See XML/DOM/DocumentFragment, -
     Lightweight node for cut & paste

   * See XML/DOM/Notation, - An NOTATION definition:
     <!NOTATION ...>

   In addition, the XML::DOM module contains the following nodes that are
not part of the DOM Level 1 Specification:

   * See XML/DOM/ElementDecl, - Defines an element:
     <!ELEMENT ...>

   * See XML/DOM/AttlistDecl, - Defines one or more
     attributes in an <!ATTLIST ...>

   * See XML/DOM/AttDef, - Defines one attribute in an
     <!ATTLIST ...>

   * See XML/DOM/XMLDecl, - An XML declaration: <?xml
     version="1.0" ...>

   Other classes that are part of the DOM Level 1 Spec:

   * `XML::DOM::Implementation' in this node - Provides information about
     this implementation. Currently it doesn't do much.

   * See XML/DOM/NodeList, - Used internally to store
     a node's child nodes. Also returned by getElementsByTagName.

   * See XML/DOM/NamedNodeMap, - Used internally
     to store an element's attributes.

   Other classes that are not part of the DOM Level 1 Spec:

   * See XML/DOM/Parser, - An non-validating XML parser
     that creates XML::DOM::Documents

   * See XML/DOM/ValParser, - A validating XML parser
     that creates XML::DOM::Documents. It uses XML/Checker,
     to check against the DocumentType (DTD)

   * See XML/Handler/BuildDOM, - A PerlSAX handler
     that creates XML::DOM::Documents.

XML::DOM package
================

Constant definitions
     The following predefined constants indicate which type of node it is.

     UNKNOWN_NODE (0)                The node type is unknown (not part of DOM)

     ELEMENT_NODE (1)                The node is an Element.
     ATTRIBUTE_NODE (2)              The node is an Attr.
     TEXT_NODE (3)                   The node is a Text node.
     CDATA_SECTION_NODE (4)          The node is a CDATASection.
     ENTITY_REFERENCE_NODE (5)       The node is an EntityReference.
     ENTITY_NODE (6)                 The node is an Entity.
     PROCESSING_INSTRUCTION_NODE (7) The node is a ProcessingInstruction.
     COMMENT_NODE (8)                The node is a Comment.
     DOCUMENT_NODE (9)               The node is a Document.
     DOCUMENT_TYPE_NODE (10)         The node is a DocumentType.
     DOCUMENT_FRAGMENT_NODE (11)     The node is a DocumentFragment.
     NOTATION_NODE (12)              The node is a Notation.

     ELEMENT_DECL_NODE (13)		 The node is an ElementDecl (not part of DOM)
     ATT_DEF_NODE (14)		 The node is an AttDef (not part of DOM)
     XML_DECL_NODE (15)		 The node is an XMLDecl (not part of DOM)
     ATTLIST_DECL_NODE (16)		 The node is an AttlistDecl (not part of DOM)

     Usage:

     if ($node->getNodeType == ELEMENT_NODE)
     {
         print "It's an Element";
     }

   *Not In DOM Spec*: The DOM Spec does not mention UNKNOWN_NODE and,
quite frankly, you should never encounter it. The last 4 node types were
added to support the 4 added node classes.

Global Variables
----------------

$VERSION
     The variable $XML::DOM::VERSION contains the version number of this
     implementation, e.g. "1.07".

METHODS
-------

   These methods are not part of the DOM Level 1 Specification.

getIgnoreReadOnly and ignoreReadOnly (readOnly)
     The DOM Level 1 Spec does not allow you to edit certain sections of
     the document, e.g. the DocumentType, so by default this
     implementation throws DOMExceptions (i.e.
     NO_MODIFICATION_ALLOWED_ERR) when you try to edit a readonly node.
     These readonly checks can be disabled by (temporarily) setting the
     global IgnoreReadOnly flag.

     The ignoreReadOnly method sets the global IgnoreReadOnly flag and
     returns its previous value. The getIgnoreReadOnly method simply
     returns its current value.

          my $oldIgnore = XML::DOM::ignoreReadOnly (1);
          eval {
          ... do whatever you want, catching any other exceptions ...
          };
          XML::DOM::ignoreReadOnly ($oldIgnore);     # restore previous value

     Another way to do it, using a local variable:

          { # start new scope
             local $XML::DOM::IgnoreReadOnly = 1;
             ... do whatever you want, don't worry about exceptions ...
          } # end of scope ($IgnoreReadOnly is set back to its previous value)

isValidName (name)
     Whether the specified name is a valid "Name" as specified in the XML
     spec.  Characters with Unicode values > 127 are now also supported.

getAllowReservedNames and allowReservedNames (boolean)
     The first method returns whether reserved names are allowed.  The
     second takes a boolean argument and sets whether reserved names are
     allowed.  The initial value is 1 (i.e. allow reserved names.)

     The XML spec states that "Names" starting with (X|x)(M|m)(L|l) are
     reserved for future use. (Amusingly enough, the XML version of the
     XML spec (REC-xml-19980210.xml) breaks that very rule by defining an
     ENTITY with the name 'xmlpio'.)  A "Name" in this context means the
     Name token as found in the BNF rules in the XML spec.

     XML::DOM only checks for errors when you modify the DOM tree, not
     when the DOM tree is built by the XML::DOM::Parser.

setTagCompression (funcref)
     There are 3 possible styles for printing empty Element tags:

    Style 0
               <empty/> or <empty attr="val"/>

          XML::DOM uses this style by default for all Elements.

    Style 1
               <empty></empty> or <empty attr="val"></empty>

    Style 2
               <empty /> or <empty attr="val" />

          This style is sometimes desired when using XHTML.  (Note the
          extra space before the slash "/") See `http:' in this node
          Appendix C for more details.

     By default XML::DOM compresses all empty Element tags (style 0.)  You
     can control which style is used for a particular Element by calling
     XML::DOM::setTagCompression with a reference to a function that takes
     2 arguments. The first is the tag name of the Element, the second is
     the XML::DOM::Element that is being printed.  The function should
     return 0, 1 or 2 to indicate which style should be used to print the
     empty tag. E.g.

          XML::DOM::setTagCompression (\&my_tag_compression);

          sub my_tag_compression
          {
             my ($tag, $elem) = @_;

          # Print empty br, hr and img tags like this: <br />
          return 2 if $tag =~ /^(br|hr|img)$/;

          # Print other empty tags like this: <empty></empty>
          return 1;
           }

IMPLEMENTATION DETAILS
======================

   * Perl Mappings

     The value undef was used when the DOM Spec said null.

     The DOM Spec says: Applications must encode DOMString using UTF-16
     (defined in Appendix C.3 of [UNICODE] and Amendment 1 of [ISO-10646]).
     In this implementation we use plain old Perl strings encoded in UTF-8
     instead of UTF-16.

   * Text and CDATASection nodes

     The Expat parser expands EntityReferences and CDataSection sections to
     raw strings and does not indicate where it was found.  This
     implementation does therefore convert both to Text nodes at parse
     time.  CDATASection and EntityReference nodes that are added to an
     existing Document (by the user) will be preserved.

     Also, subsequent Text nodes are always merged at parse time. Text
     nodes that are added later can be merged with the normalize method.
     Consider using the addText method when adding Text nodes.

   * Printing and toString

     When printing (and converting an XML Document to a string) the
     strings have to encoded differently depending on where they occur.
     E.g. in a CDATASection all substrings are allowed except for "]]>".
     In regular text, certain characters are not allowed, e.g. ">" has to
     be converted to "&gt;".  These routines should be verified by someone
     who knows the details.

   * Quotes

     Certain sections in XML are quoted, like attribute values in an
     Element.  XML::Parser strips these quotes and the print methods in
     this implementation always uses double quotes, so when parsing and
     printing a document, single quotes may be converted to double quotes.
     The default value of an attribute definition (AttDef) in an
     AttlistDecl, however, will maintain its quotes.

   * AttlistDecl

     Attribute declarations for a certain Element are always merged into a
     single AttlistDecl object.

   * Comments

     Comments in the DOCTYPE section are not kept in the right place. They
     will become child nodes of the Document.

   * Hidden Nodes

     Previous versions of XML::DOM would expand parameter entity references
     (like *%pent;*), so when printing the DTD, it would print the contents
     of the external entity, instead of the parameter entity reference.
     With this release (1.27), you can prevent this by setting the
     XML::DOM::Parser options ParseParamEnt => 1 and ExpandParamEnt => 0.

     When it is parsing the contents of the external entities, it *DOES*
     still add the nodes to the DocumentType, but it marks these nodes by
     setting the 'Hidden' property. In addition, it adds an
     EntityReference node to the DocumentType node.

     When printing the DocumentType node (or when using to_expat() or
     to_sax()), the 'Hidden' nodes are suppressed, so you will see the
     parameter entity reference instead of the contents of the external
     entities. See test case t/dom_extent.t for an example.

     The reason for adding the 'Hidden' nodes to the DocumentType node, is
     that the nodes may contain <!ENTITY> definitions that are referenced
     further in the document. (Simply not adding the nodes to the
     DocumentType could cause such entity references to be expanded
     incorrectly.)

     Note that you need XML::Parser 2.27 or higher for this to work
     correctly.

SEE ALSO
========

   The Japanese version of this document by Takanori Kawai (Hippo2000) at
`http:' in this node

   The DOM Level 1 specification at `http:' in this node

   The XML spec (Extensible Markup Language 1.0) at `http:' in this node

   The XML/Parser, and XML/Parser/Expat,
manual pages.

CAVEATS
=======

   The method getElementsByTagName() does not return a "live" NodeList.
Whether this is an actual caveat is debatable, but a few people on the
www-dom mailing list seemed to think so. I haven't decided yet. It's a pain
to implement, it slows things down and the benefits seem marginal.  Let me
know what you think.

   (To subscribe to the www-dom mailing list send an email with the subject
"subscribe" to www-dom-request@w3.org. I only look here occasionally, so
don't send bug reports or suggestions about XML::DOM to this list, send
them to enno@att.com instead.)

AUTHOR
======

   Send bug reports, hints, tips, suggestions to Enno Derksen at
<`enno@att.com'>.

   Thanks to Clark Cooper for his help with the initial version.

XML::Grove and DOM Level One
============================

   XML::Grove is similar in concept to the ECMA Script Language Binding to
DOM Level 1 Core (Appendix E of the DOM Recommendation).

   <http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html>

   The ECMA Script Language Binding presents DOM properties as ECMA Script
object properties.  The same is true for XML::Grove, XML::Grove presents
DOM properties as Perl blessed hashes.

   The biggest difference between the ECMA Script Language Binding and
XML::Grove is that XML::Grove uses a Perl hash for nodes, Perl arrays for
NodeLists, Perl hashes for NamedNodeLists so those object classes don't
exist in XML::Grove.  Because those classes don't exist, you use ordinary
Perl syntax for manipulating the DOM properties (lists and named node
lists) instead of methods like ``nextSibling()'' or ``replaceChild()''.
Element attributes in XML::Grove are stored in Perl hashes; attribute
types are available through the document object.

   Another difference is that XML::Grove attempts to marry the PerlSAX and
DOM naming so that less (no?) name-changing occurs between using PerlSAX
interfaces and filters and DOM modules.  Where conflicts occur, the
PerlSAX naming is used.

   XML::Grove uses a blessed hash for nodes, so the node type is available
using Perl's ``ref()'' instead of using a ``nodeType()'' method and all
class names are prefixed with ``XML::Grove::''.

   The following object descriptions are the most basic and common
provided by many PerlSAX parsers.  PerlSAX parsers often provide
additional properties or objects, refer to your PerlSAX parser
documentation for details.

Document Object Model Level 1 Core
==================================

Object XML::Grove::Document
---------------------------

Contents
     The children of this object.  This property is an array.

Entities
     The entities declared in this document.  This property is a hash of
     XML::Grove::Entity objects keyed by entity name.

Notations
     The notations declared in this document.  This property is a hash of
     XML::Grove::Notation objects keyed by notation name.

Object XML::Grove::Element
--------------------------

Name
     The tag type name for this element.  This property is a string.

Attributes
     The attributes for this element.  This property is a hash and it's
     hash values are strings (or arrays with some grove builders).

Contents
     The children of this object.  This property is an array of XML::Grove
     objects.

Object XML::Grove::Characters
-----------------------------

Data
     The text of the character data.  This property is a string.

Object XML::Grove::Comment
--------------------------

Data
     The text of the character data.  This property is a string.

Object XML::Grove::CData
------------------------

   The `CData' object is called a `CDATASection' in DOM.

Data
     The text of the character data.  This property is a string.

Object XML::Grove::Notation
---------------------------

Name
     The name of this notation.  This property is a string.

SystemId
     The system identifier of this notation.  This property is a string.

PublicId
     The public identifier of this notation.  This property is a string.

Object XML::Grove::Entity
-------------------------

Name
     The name of this entity.  This property is a string.

SystemId
     The system identifier of this notation.  This property is a string.

PublicId
     The public identifier of this notation.  This property is a string.

Notation
     The notation declared for this entity.  This property is either the
     name of the notation as a string or an `XML::Grove::Notation' object.

Object XML::Grove::PI
---------------------

   The PI object is called a `ProcessingInstruction' in DOM.

Target
     The target of the processing instruction.  This property is a string.

Data
     The text of the processing instruction.  This property is a string.

A single XML attribute definition in an ATTLIST in XML::DOM
***********************************************************

NAME
====

   XML::DOM::AttDef - A single XML attribute definition in an ATTLIST in
XML::DOM

DESCRIPTION
===========

   XML::DOM::AttDef extends XML/DOM/Node, but is not
part of the DOM Level 1 specification.

   Each object of this class represents one attribute definition in an
AttlistDecl.

METHODS
-------

getName
     Returns the attribute name.

getDefault
     Returns the default value, or undef.

isFixed
     Whether the attribute value is fixed (see #FIXED keyword.)

isRequired
     Whether the attribute value is required (see #REQUIRED keyword.)

isImplied
     Whether the attribute value is implied (see #IMPLIED keyword.)

An XML ATTLIST declaration in XML::DOM
**************************************

NAME
====

   XML::DOM::AttlistDecl - An XML ATTLIST declaration in XML::DOM

DESCRIPTION
===========

   XML::DOM::AttlistDecl extends XML/DOM/Node, but is
not part of the DOM Level 1 specification.

   This node represents an ATTLIST declaration, e.g.

     <!ATTLIST person
       sex      (male|female)  #REQUIRED
       hair     CDATA          "bold"
       eyes     (none|one|two) "two"
       species  (human)        #FIXED "human">

   Each attribute definition is stored a separate AttDef node. The AttDef
nodes can be retrieved with getAttDef and added with addAttDef.  (The
AttDef nodes are stored in a NamedNodeMap internally.)

METHODS
-------

getName
     Returns the Element tagName.

getAttDef (attrName)
     Returns the AttDef node for the attribute with the specified name.

addAttDef (attrName, type, default, [ fixed ])
     Adds a AttDef node for the attribute with the specified name.

     Parameters:  *attrName* the attribute name.   type     the attribute
     type (e.g. "CDATA" or "(male|female)".)   default  the default value
     enclosed in quotes (!), the string #IMPLIED or              the
     string #REQUIRED.   fixed    whether the attribute is '#FIXED'
     (default is 0.)

An XML attribute in XML::DOM
****************************

NAME
====

   XML::DOM::Attr - An XML attribute in XML::DOM

DESCRIPTION
===========

   XML::DOM::Attr extends XML/DOM/Node.

   The Attr nodes built by the XML::DOM::Parser always have one child node
which is a Text node containing the expanded string value (i.e.
EntityReferences are always expanded.) EntityReferences may be added when
modifying or creating a new Document.

   The Attr interface represents an attribute in an Element object.
Typically the allowable values for the attribute are defined in a document
type definition.

   Attr objects inherit the Node interface, but since they are not
actually child nodes of the element they describe, the DOM does not
consider them part of the document tree. Thus, the Node attributes
parentNode, previousSibling, and nextSibling have a undef value for Attr
objects. The DOM takes the view that attributes are properties of elements
rather than having a separate identity from the elements they are
associated with; this should make it more efficient to implement such
features as default attributes associated with all elements of a given
type. Furthermore, Attr nodes may not be immediate children of a
DocumentFragment. However, they can be associated with Element nodes
contained within a DocumentFragment. In short, users and implementors of
the DOM need to be aware that Attr nodes have some things in common with
other objects inheriting the Node interface, but they also are quite
distinct.

   The attribute's effective value is determined as follows: if this
attribute has been explicitly assigned any value, that value is the
attribute's effective value; otherwise, if there is a declaration for this
attribute, and that declaration includes a default value, then that
default value is the attribute's effective value; otherwise, the attribute
does not exist on this element in the structure model until it has been
explicitly added. Note that the nodeValue attribute on the Attr instance
can also be used to retrieve the string version of the attribute's
value(s).

   In XML, where the value of an attribute can contain entity references,
the child nodes of the Attr node provide a representation in which entity
references are not expanded. These child nodes may be either Text or
EntityReference nodes. Because the attribute type may be unknown, there
are no tokenized attribute values.

METHODS
-------

getValue
     On retrieval, the value of the attribute is returned as a string.
     Character and general entity references are replaced with their
     values.

setValue (str)
     DOM Spec: On setting, this creates a Text node with the unparsed
     contents of the string.

getName
     Returns the name of this attribute.

Escaping XML text blocks in XML::DOM
************************************

NAME
====

   XML::DOM::CDATASection - Escaping XML text blocks in XML::DOM

DESCRIPTION
===========

   XML::DOM::CDATASection extends XML/DOM/CharacterData,
which extends XML/DOM/Node.

   CDATA sections are used to escape blocks of text containing characters
that would otherwise be regarded as markup. The only delimiter that is
recognized in a CDATA section is the "]]>" string that ends the CDATA
section. CDATA sections can not be nested. The primary purpose is for
including material such as XML fragments, without needing to escape all
the delimiters.

   The DOMString attribute of the Text node holds the text that is
contained by the CDATA section. Note that this may contain characters that
need to be escaped outside of CDATA sections and that, depending on the
character encoding ("charset") chosen for serialization, it may be
impossible to write out some characters as part of a CDATA section.

   The CDATASection interface inherits the CharacterData interface through
the Text interface. Adjacent CDATASections nodes are not merged by use of
the Element.normalize() method.

   NOTE: XML::DOM::Parser and XML::DOM::ValParser convert all CDATASections
to regular text by default.  To preserve CDATASections, set the parser
option KeepCDATA to 1.

Common interface for Text, CDATASections and Comments
*****************************************************

NAME
====

   XML::DOM::CharacterData - Common interface for Text, CDATASections and
Comments

DESCRIPTION
===========

   XML::DOM::CharacterData extends XML/DOM/Node,

   The CharacterData interface extends Node with a set of attributes and
methods for accessing character data in the DOM. For clarity this set is
defined here rather than on each object that uses these attributes and
methods. No DOM objects correspond directly to CharacterData, though Text,
Comment and CDATASection do inherit the interface from it.  All offsets in
this interface start from 0.

METHODS
-------

getData and setData (data)
     The character data of the node that implements this interface. The
     DOM implementation may not put arbitrary limits on the amount of data
     that may be stored in a CharacterData node. However, implementation
     limits may mean that the entirety of a node's data may not fit into a
     single DOMString. In such cases, the user may call substringData to
     retrieve the data in appropriately sized pieces.

getLength
     The number of characters that are available through data and the
     substringData method below. This may have the value zero, i.e.,
     CharacterData nodes may be empty.

substringData (offset, count)
     Extracts a range of data from the node.

     Parameters:  offset  Start offset of substring to extract.   count
     The number of characters to extract.

     Return Value: The specified substring. If the sum of offset and count
     exceeds the length, then all characters to the end of the data are
     returned.

appendData (str)
     Appends the string to the end of the character data of the node. Upon
     success, data provides access to the concatenation of data and the
     DOMString specified.

insertData (offset, arg)
     Inserts a string at the specified character offset.

     Parameters:  offset  The character offset at which to insert.   *arg*
        The DOMString to insert.

deleteData (offset, count)
     Removes a range of characters from the node.  Upon success, data and
     length reflect the change.  If the sum of offset and count exceeds
     length then all characters from offset to the end of the data are
     deleted.

     Parameters:  offset  The offset from which to remove characters.
     count   The number of characters to delete.

replaceData (offset, count, arg)
     Replaces the characters starting at the specified character offset
     with the specified string.

     Parameters:  offset  The offset from which to start replacing.
     count   The number of characters to replace.   *arg*     The
     DOMString with which the range must be replaced.

     If the sum of offset and count exceeds length, then all characters to
     the end of the data are replaced (i.e., the effect is the same as a
     remove method call with the same range, followed by an append method
     invocation).

An XML comment in XML::DOM
**************************

NAME
====

   XML::DOM::Comment - An XML comment in XML::DOM

DESCRIPTION
===========

   XML::DOM::Comment extends XML/DOM/CharacterData,
which extends XML/DOM/Node.

   This node represents the content of a comment, i.e., all the characters
between the starting '<!-' and ending '->'. Note that this is the
definition of a comment in XML, and, in practice, HTML, although some HTML
tools may implement the full SGML comment structure.

Information about XML::DOM implementation
*****************************************

NAME
====

   XML::DOM::DOMImplementation - Information about XML::DOM implementation

DESCRIPTION
===========

   The DOMImplementation interface provides a number of methods for
performing operations that are independent of any particular instance of
the document object model.

   The DOM Level 1 does not specify a way of creating a document instance,
and hence document creation is an operation specific to an implementation.
Future Levels of the DOM specification are expected to provide methods for
creating documents directly.

METHODS
-------

hasFeature (feature, version)
     Returns 1 if and only if feature equals "XML" and version equals
     "1.0".

An XML document node in XML::DOM
********************************

NAME
====

   XML::DOM::Document - An XML document node in XML::DOM

DESCRIPTION
===========

   XML::DOM::Document extends XML/DOM/Node.

   It is the main root of the XML document structure as returned by
XML::DOM::Parser::parse and XML::DOM::Parser::parsefile.

   Since elements, text nodes, comments, processing instructions, etc.
cannot exist outside the context of a Document, the Document interface
also contains the factory methods needed to create these objects. The Node
objects created have a getOwnerDocument method which associates them with
the Document within whose context they were created.

METHODS
-------

getDocumentElement
     This is a convenience method that allows direct access to the child
     node that is the root Element of the document.

getDoctype
     The Document Type Declaration (see DocumentType) associated with this
     document. For HTML documents as well as XML documents without a
     document type declaration this returns undef. The DOM Level 1 does
     not support editing the Document Type Declaration.

     *Not In DOM Spec*: This implementation allows editing the doctype.
     See *XML::DOM::ignoreReadOnly* for details.

getImplementation
     The DOMImplementation object that handles this document. A DOM
     application may use objects from multiple implementations.

createElement (tagName)
     Creates an element of the type specified. Note that the instance
     returned implements the Element interface, so attributes can be
     specified directly on the returned object.

     DOMExceptions:

        * INVALID_CHARACTER_ERR

          Raised if the tagName does not conform to the XML spec.

createTextNode (data)
     Creates a Text node given the specified string.

createComment (data)
     Creates a Comment node given the specified string.

createCDATASection (data)
     Creates a CDATASection node given the specified string.

createAttribute (name [, value [, specified ]])
     Creates an Attr of the given name. Note that the Attr instance can
     then be set on an Element using the setAttribute method.

     *Not In DOM Spec*: The DOM Spec does not allow passing the value or
     the specified property in this method. In this implementation they
     are optional.

     Parameters:  value     The attribute's value. See Attr::setValue for
     details.                If the value is not supplied, the specified
     property is set to 0.   *specified* Whether the attribute value was
     specified or whether the default               value was used. If not
     supplied, it's assumed to be 1.

     DOMExceptions:

        * INVALID_CHARACTER_ERR

          Raised if the name does not conform to the XML spec.

createProcessingInstruction (target, data)
     Creates a ProcessingInstruction node given the specified name and
     data strings.

     Parameters:  target  The target part of the processing instruction.
     data    The data for the node.

     DOMExceptions:

        * INVALID_CHARACTER_ERR

          Raised if the target does not conform to the XML spec.

createDocumentFragment
     Creates an empty DocumentFragment object.

createEntityReference (name)
     Creates an EntityReference object.

Additional methods not in the DOM Spec
--------------------------------------

getXMLDecl and setXMLDecl (xmlDecl)
     Returns the XMLDecl for this Document or undef if none was specified.
     Note that XMLDecl is not part of the list of child nodes.

setDoctype (doctype)
     Sets or replaces the DocumentType.  NOTE: Don't use appendChild or
     insertBefore to set the DocumentType.  Even though doctype will be
     part of the list of child nodes, it is handled specially.

getDefaultAttrValue (elem, attr)
     Returns the default attribute value as a string or undef, if none is
     available.

     Parameters:  elem    The element tagName.   attr    The attribute
     name.

getEntity (name)
     Returns the Entity with the specified name.

createXMLDecl (version, encoding, standalone)
     Creates an XMLDecl object. All parameters may be undefined.

createDocumentType (name, sysId, pubId)
     Creates a DocumentType object. SysId and pubId may be undefined.

createNotation (name, base, sysId, pubId)
     Creates a new Notation object. Consider using
     XML::DOM::DocumentType::addNotation!

createEntity (parameter, notationName, value, sysId, pubId, ndata)
     Creates an Entity object. Consider using
     XML::DOM::DocumentType::addEntity!

createElementDecl (name, model)
     Creates an ElementDecl object.

     DOMExceptions:

        * INVALID_CHARACTER_ERR

          Raised if the element name (tagName) does not conform to the XML
          spec.

createAttlistDecl (name)
     Creates an AttlistDecl object.

     DOMExceptions:

        * INVALID_CHARACTER_ERR

          Raised if the element name (tagName) does not conform to the XML
          spec.

expandEntity (entity [, parameter])
     Expands the specified entity or parameter entity (if parameter=1) and
     returns its value as a string, or undef if the entity does not exist.
     (The entity name should not contain the '%', '&' or ';' delimiters.)

check ( [$checker] )
     Uses the specified XML/Checker, to validate the
     document.  If no XML::Checker is supplied, a new XML::Checker is
     created.  See XML/Checker, for details.

check_sax ( [$checker] )
     Similar to check() except it uses the SAX interface to XML::Checker
     instead of the expat interface. This method may disappear or replace
     check() at some time.

createChecker ()
     Creates an XML::Checker based on the document's DTD.  The $checker
     can be reused to check any elements within the document.  Create a
     new XML/Checker, whenever the DOCTYPE section of
     the document is altered!

Facilitates cut & paste in XML::DOM documents
*********************************************

NAME
====

   XML::DOM::DocumentFragment - Facilitates cut & paste in XML::DOM
documents

DESCRIPTION
===========

   XML::DOM::DocumentFragment extends XML/DOM/Node,

   DocumentFragment is a "lightweight" or "minimal" Document object. It is
very common to want to be able to extract a portion of a document's tree
or to create a new fragment of a document. Imagine implementing a user
command like cut or rearranging a document by moving fragments around. It
is desirable to have an object which can hold such fragments and it is
quite natural to use a Node for this purpose. While it is true that a
Document object could fulfil this role, a Document object can potentially
be a heavyweight object, depending on the underlying implementation. What
is really needed for this is a very lightweight object. DocumentFragment
is such an object.

   Furthermore, various operations - such as inserting nodes as children
of another Node - may take DocumentFragment objects as arguments; this
results in all the child nodes of the DocumentFragment being moved to the
child list of this node.

   The children of a DocumentFragment node are zero or more nodes
representing the tops of any sub-trees defining the structure of the
document. DocumentFragment nodes do not need to be well-formed XML
documents (although they do need to follow the rules imposed upon
well-formed XML parsed entities, which can have multiple top nodes).  For
example, a DocumentFragment might have only one child and that child node
could be a Text node. Such a structure model represents neither an HTML
document nor a well-formed XML document.

   When a DocumentFragment is inserted into a Document (or indeed any
other Node that may take children) the children of the DocumentFragment
and not the DocumentFragment itself are inserted into the Node. This makes
the DocumentFragment very useful when the user wishes to create nodes that
are siblings; the DocumentFragment acts as the parent of these nodes so
that the user can use the standard methods from the Node interface, such
as insertBefore() and appendChild().

An XML document type (DTD) in XML::DOM
**************************************

NAME
====

   XML::DOM::DocumentType - An XML document type (DTD) in XML::DOM

DESCRIPTION
===========

   XML::DOM::DocumentType extends XML/DOM/Node.

   Each Document has a doctype attribute whose value is either null or a
DocumentType object. The DocumentType interface in the DOM Level 1 Core
provides an interface to the list of entities that are defined for the
document, and little else because the effect of namespaces and the various
XML scheme efforts on DTD representation are not clearly understood as of
this writing.  The DOM Level 1 doesn't support editing DocumentType nodes.

   *Not In DOM Spec*: This implementation has added a lot of extra
functionality to the DOM Level 1 interface.  To allow editing of the
DocumentType nodes, see XML::DOM::ignoreReadOnly.

METHODS
-------

getName
     Returns the name of the DTD, i.e. the name immediately following the
     DOCTYPE keyword.

getEntities
     A NamedNodeMap containing the general entities, both external and
     internal, declared in the DTD. Duplicates are discarded.  For example
     in:

          <!DOCTYPE ex SYSTEM "ex.dtd" [
           <!ENTITY foo "foo">
           <!ENTITY bar "bar">
           <!ENTITY % baz "baz">
          ]>
          <ex/>

     the interface provides access to foo and bar but not baz.  Every node
     in this map also implements the Entity interface.

     The DOM Level 1 does not support editing entities, therefore entities
     cannot be altered in any way.

     *Not In DOM Spec*: See XML::DOM::ignoreReadOnly to edit the
     DocumentType etc.

getNotations
     A NamedNodeMap containing the notations declared in the DTD.
     Duplicates are discarded. Every node in this map also implements the
     Notation interface.

     The DOM Level 1 does not support editing notations, therefore
     notations cannot be altered in any way.

     *Not In DOM Spec*: See XML::DOM::ignoreReadOnly to edit the
     DocumentType etc.

Additional methods not in the DOM Spec
--------------------------------------

Creating and setting the DocumentType
     A new DocumentType can be created with:

          $doctype = $doc->createDocumentType ($name, $sysId, $pubId, $internal);

     To set (or replace) the DocumentType for a particular document, use:

          $doc->setDocType ($doctype);

getSysId and setSysId (sysId)
     Returns or sets the system id.

getPubId and setPubId (pudId)
     Returns or sets the public id.

setName (name)
     Sets the name of the DTD, i.e. the name immediately following the
     DOCTYPE keyword. Note that this should always be the same as the
     element tag name of the root element.

getAttlistDecl (elemName)
     Returns the AttlistDecl for the Element with the specified name, or
     undef.

getElementDecl (elemName)
     Returns the ElementDecl for the Element with the specified name, or
     undef.

getEntity (entityName)
     Returns the Entity with the specified name, or undef.

addAttlistDecl (elemName)
     Adds a new AttDecl node with the specified elemName if one doesn't
     exist yet.  Returns the AttlistDecl (new or existing) node.

addElementDecl (elemName, model)
     Adds a new ElementDecl node with the specified elemName and model if
     one doesn't exist yet.  Returns the AttlistDecl (new or existing)
     node. The model is ignored if one already existed.

addEntity (parameter, notationName, value, sysId, pubId, ndata)
     Adds a new Entity node. Don't use createEntity and appendChild,
     because it should be added to the internal NamedNodeMap containing
     the entities.

     Parameters:  parameter	 whether it is a parameter entity
     (%ent;) or not (&ent;).   *notationName* the entity name.   value
       the entity value.   *sysId*        the system id (if any.)
     *pubId*        the public id (if any.)   *ndata*        the NDATA
     declaration (if any, for general unparsed entities.)

     SysId, pubId and ndata may be undefined.

     DOMExceptions:

        * INVALID_CHARACTER_ERR

          Raised if the notationName does not conform to the XML spec.

addNotation (name, base, sysId, pubId)
     Adds a new Notation object.

     Parameters:  name   the notation name.   base   the base to be used
     for resolving a relative URI.   *sysId*  the system id.   *pubId*
     the public id.

     Base, sysId, and pubId may all be undefined.  (These parameters are
     passed by the XML::Parser Notation handler.)

     DOMExceptions:

        * INVALID_CHARACTER_ERR

          Raised if the notationName does not conform to the XML spec.

addAttDef (elemName, attrName, type, default, fixed)
     Adds a new attribute definition. It will add the AttDef node to the
     AttlistDecl if it exists. If an AttDef with the specified attrName
     already exists for the given elemName, this function only generates a
     warning.

     See XML::DOM::AttDef::new for the other parameters.

getDefaultAttrValue (elem, attr)
     Returns the default attribute value as a string or undef, if none is
     available.

     Parameters:  elem    The element tagName.   attr    The attribute
     name.

expandEntity (entity [, parameter])
     Expands the specified entity or parameter entity (if parameter=1) and
     returns its value as a string, or undef if the entity does not exist.
     (The entity name should not contain the '%', '&' or ';' delimiters.)

An XML element node in XML::DOM
*******************************

NAME
====

   XML::DOM::Element - An XML element node in XML::DOM

DESCRIPTION
===========

   XML::DOM::Element extends XML/DOM/Node.

   By far the vast majority of objects (apart from text) that authors
encounter when traversing a document are Element nodes. Assume the
following XML document:

     <elementExample id="demo">
       <subelement1/>
       <subelement2><subsubelement/></subelement2>
     </elementExample>

   When represented using DOM, the top node is an Element node for
"elementExample", which contains two child Element nodes, one for
"subelement1" and one for "subelement2". "subelement1" contains no child
nodes.

   Elements may have attributes associated with them; since the Element
interface inherits from Node, the generic Node interface method
getAttributes may be used to retrieve the set of all attributes for an
element. There are methods on the Element interface to retrieve either an
Attr object by name or an attribute value by name. In XML, where an
attribute value may contain entity references, an Attr object should be
retrieved to examine the possibly fairly complex sub-tree representing the
attribute value. On the other hand, in HTML, where all attributes have
simple string values, methods to directly access an attribute value can
safely be used as a convenience.

METHODS
-------

getTagName
     The name of the element. For example, in:

          <elementExample id="demo">
                  ...
          </elementExample>

     tagName has the value "elementExample". Note that this is
     case-preserving in XML, as are all of the operations of the DOM.

getAttribute (name)
     Retrieves an attribute value by name.

     Return Value: The Attr value as a string, or the empty string if that
     attribute does not have a specified or default value.

setAttribute (name, value)
     Adds a new attribute. If an attribute with that name is already
     present in the element, its value is changed to be that of the value
     parameter. This value is a simple string, it is not parsed as it is
     being set. So any markup (such as syntax to be recognized as an
     entity reference) is treated as literal text, and needs to be
     appropriately escaped by the implementation when it is written out.
     In order to assign an attribute value that contains entity
     references, the user must create an Attr node plus any Text and
     EntityReference nodes, build the appropriate subtree, and use
     setAttributeNode to assign it as the value of an attribute.

     DOMExceptions:

        * INVALID_CHARACTER_ERR

          Raised if the specified name contains an invalid character.

        * NO_MODIFICATION_ALLOWED_ERR

          Raised if this node is readonly.

removeAttribute (name)
     Removes an attribute by name. If the removed attribute has a default
     value it is immediately replaced.

     DOMExceptions:

        * NO_MODIFICATION_ALLOWED_ERR

          Raised if this node is readonly.

getAttributeNode
     Retrieves an Attr node by name.

     Return Value: The Attr node with the specified attribute name or undef
     if there is no such attribute.

setAttributeNode (attr)
     Adds a new attribute. If an attribute with that name is already
     present in the element, it is replaced by the new one.

     Return Value: If the newAttr attribute replaces an existing attribute
     with the same name, the previously existing Attr node is returned,
     otherwise undef is returned.

     DOMExceptions:

        * WRONG_DOCUMENT_ERR

          Raised if newAttr was created from a different document than the
          one that created the element.

        * NO_MODIFICATION_ALLOWED_ERR

          Raised if this node is readonly.

        * INUSE_ATTRIBUTE_ERR

          Raised if newAttr is already an attribute of another Element
          object. The DOM user must explicitly clone Attr nodes to re-use
          them in other elements.

removeAttributeNode (oldAttr)
     Removes the specified attribute. If the removed Attr has a default
     value it is immediately replaced. If the Attr already is the default
     value, nothing happens and nothing is returned.

     Parameters:  *oldAttr*  The Attr node to remove from the attribute
     list.

     Return Value: The Attr node that was removed.

     DOMExceptions:

        * NO_MODIFICATION_ALLOWED_ERR

          Raised if this node is readonly.

        * NOT_FOUND_ERR

          Raised if oldAttr is not an attribute of the element.

Additional methods not in the DOM Spec
--------------------------------------

setTagName (newTagName)
     Sets the tag name of the Element. Note that this method is not
     portable between DOM implementations.

     DOMExceptions:

        * INVALID_CHARACTER_ERR

          Raised if the specified name contains an invalid character.

check ($checker)
     Uses the specified XML/Checker, to validate the
     document.  NOTE: an XML::Checker must be supplied. The checker can be
     created in different ways, e.g. when parsing a document with
     XML::DOM::ValParser, or with XML::DOM::Document::createChecker().
     See XML/Checker, for more info.

An XML ELEMENT declaration in XML::DOM
**************************************

NAME
====

   XML::DOM::ElementDecl - An XML ELEMENT declaration in XML::DOM

DESCRIPTION
===========

   XML::DOM::ElementDecl extends XML/DOM/Node, but is
not part of the DOM Level 1 specification.

   This node represents an Element declaration, e.g.

     <!ELEMENT address (street+, city, state, zip, country?)>

METHODS
-------

getName
     Returns the Element tagName.

getModel and setModel (model)
     Returns and sets the model as a string, e.g.  "(street+, city, state,
     zip, country?)" in the above example.

An XML ENTITY in XML::DOM
*************************

NAME
====

   XML::DOM::Entity - An XML ENTITY in XML::DOM

DESCRIPTION
===========

   XML::DOM::Entity extends XML/DOM/Node.

   This node represents an Entity declaration, e.g.

     <!ENTITY % draft 'INCLUDE'>

     <!ENTITY hatch-pic SYSTEM "../grafix/OpenHatch.gif" NDATA gif>

   The first one is called a parameter entity and is referenced like this:
%draft; The 2nd is a (regular) entity and is referenced like this:
&hatch-pic;

METHODS
-------

getNotationName
     Returns the name of the notation for the entity.

     Not Implemented The DOM Spec says: For unparsed entities, the name of
     the notation for the entity. For parsed entities, this is null.
     (This implementation does not support unparsed entities.)

getSysId
     Returns the system id, or undef.

getPubId
     Returns the public id, or undef.

Additional methods not in the DOM Spec
--------------------------------------

isParameterEntity
     Whether it is a parameter entity (%ent;) or not (&ent;)

getValue
     Returns the entity value.

getNdata
     Returns the NDATA declaration (for general unparsed entities), or
     undef.

An XML ENTITY reference in XML::DOM
***********************************

NAME
====

   XML::DOM::EntityReference - An XML ENTITY reference in XML::DOM

DESCRIPTION
===========

   XML::DOM::EntityReference extends XML/DOM/Node.

   EntityReference objects may be inserted into the structure model when
an entity reference is in the source document, or when the user wishes to
insert an entity reference. Note that character references and references
to predefined entities are considered to be expanded by the HTML or XML
processor so that characters are represented by their Unicode equivalent
rather than by an entity reference. Moreover, the XML processor may
completely expand references to entities while building the structure
model, instead of providing EntityReference objects. If it does provide
such objects, then for a given EntityReference node, it may be that there
is no Entity node representing the referenced entity; but if such an
Entity exists, then the child list of the EntityReference node is the same
as that of the Entity node. As with the Entity node, all descendants of the
EntityReference are readonly.

   The resolution of the children of the EntityReference (the replacement
value of the referenced Entity) may be lazily evaluated; actions by the
user (such as calling the childNodes method on the EntityReference node)
are assumed to trigger the evaluation.

A hash table interface for XML::DOM
***********************************

NAME
====

   XML::DOM::NamedNodeMap - A hash table interface for XML::DOM

DESCRIPTION
===========

   Objects implementing the NamedNodeMap interface are used to represent
collections of nodes that can be accessed by name. Note that NamedNodeMap
does not inherit from NodeList; NamedNodeMaps are not maintained in any
particular order. Objects contained in an object implementing NamedNodeMap
may also be accessed by an ordinal index, but this is simply to allow
convenient enumeration of the contents of a NamedNodeMap, and does not
imply that the DOM specifies an order to these Nodes.

   Note that in this implementation, the objects added to a NamedNodeMap
are kept in order.

METHODS
-------

getNamedItem (name)
     Retrieves a node specified by name.

     Return Value: A Node (of any type) with the specified name, or undef
     if the specified name did not identify any node in the map.

setNamedItem (arg)
     Adds a node using its nodeName attribute.

     As the nodeName attribute is used to derive the name which the node
     must be stored under, multiple nodes of certain types (those that
     have a "special" string value) cannot be stored as the names would
     clash. This is seen as preferable to allowing nodes to be aliased.

     Parameters:  *arg*  A node to store in a named node map.

     The node will later be accessible using the value of the nodeName
     attribute of the node. If a node with that name is already present in
     the map, it is replaced by the new one.

     Return Value: If the new Node replaces an existing node with the same
     name the previously existing Node is returned, otherwise undef is
     returned.

     DOMExceptions:

        * WRONG_DOCUMENT_ERR

          Raised if arg was created from a different document than the one
          that created the NamedNodeMap.

        * NO_MODIFICATION_ALLOWED_ERR

          Raised if this NamedNodeMap is readonly.

        * INUSE_ATTRIBUTE_ERR

          Raised if arg is an Attr that is already an attribute of another
          Element object.  The DOM user must explicitly clone Attr nodes
          to re-use them in other elements.

removeNamedItem (name)
     Removes a node specified by name. If the removed node is an Attr with
     a default value it is immediately replaced.

     Return Value: The node removed from the map or undef if no node with
     such a name exists.

     DOMException:

        * NOT_FOUND_ERR

          Raised if there is no node named name in the map.

item (index)
     Returns the indexth item in the map. If index is greater than or
     equal to the number of nodes in the map, this returns undef.

     Return Value: The node at the indexth position in the NamedNodeMap, or
     undef if that is not a valid index.

getLength
     Returns the number of nodes in the map. The range of valid child node
     indices is 0 to length-1 inclusive.

Additional methods not in the DOM Spec
--------------------------------------

getValues
     Returns a NodeList with the nodes contained in the NamedNodeMap.  The
     NodeList is "live", in that it reflects changes made to the
     NamedNodeMap.

     When this method is called in a list context, it returns a regular
     perl list containing the values. Note that this list is not "live".
     E.g.

          @list = $map->getValues;	 # returns a perl list
          $nodelist = $map->getValues;    # returns a NodeList (object ref.)
          for my $val ($map->getValues)   # iterate over the values

getChildIndex (node)
     Returns the index of the node in the NodeList as returned by
     getValues, or -1 if the node is not in the NamedNodeMap.

dispose
     Removes all circular references in this NamedNodeMap and its
     descendants so the objects can be claimed for garbage collection. The
     objects should not be used afterwards.

Super class of all nodes in XML::DOM
************************************

NAME
====

   XML::DOM::Node - Super class of all nodes in XML::DOM

DESCRIPTION
===========

   XML::DOM::Node is the super class of all nodes in an XML::DOM document.
This means that all nodes that subclass XML::DOM::Node also inherit all
the methods that XML::DOM::Node implements.

GLOBAL VARIABLES
----------------

@NodeNames
     The variable @XML::DOM::Node::NodeNames maps the node type constants
     to strings.  It is used by XML::DOM::Node::getNodeTypeName.

METHODS
-------

getNodeType
     Return an integer indicating the node type. See XML::DOM constants.

getNodeName
     Return a property or a hardcoded string, depending on the node type.
     Here are the corresponding functions or values:

          Attr			getName
          AttDef			getName
          AttlistDecl		getName
          CDATASection		"#cdata-section"
          Comment		"#comment"
          Document		"#document"
          DocumentType		getNodeName
          DocumentFragment	"#document-fragment"
          Element		getTagName
          ElementDecl		getName
          EntityReference	getEntityName
          Entity			getNotationName
          Notation		getName
          ProcessingInstruction	getTarget
          Text			"#text"
          XMLDecl		"#xml-declaration"

     *Not In DOM Spec*: AttDef, AttlistDecl, ElementDecl and XMLDecl were
     added for completeness.

getNodeValue and setNodeValue (value)
     Returns a string or undef, depending on the node type. This method is
     provided for completeness. In other languages it saves the programmer
     an upcast.  The value is either available thru some other method
     defined in the subclass, or else undef is returned. Here are the
     corresponding methods: Attr::getValue, Text::getData,
     CDATASection::getData, Comment::getData,
     ProcessingInstruction::getData.

getParentNode and setParentNode (parentNode)
     The parent of this node. All nodes, except Document,
     DocumentFragment, and Attr may have a parent. However, if a node has
     just been created and not yet added to the tree, or if it has been
     removed from the tree, this is undef.

getChildNodes
     A NodeList that contains all children of this node. If there are no
     children, this is a NodeList containing no nodes. The content of the
     returned NodeList is "live" in the sense that, for instance, changes
     to the children of the node object that it was created from are
     immediately reflected in the nodes returned by the NodeList
     accessors; it is not a static snapshot of the content of the node.
     This is true for every NodeList, including the ones returned by the
     getElementsByTagName method.

     NOTE: this implementation does not return a "live" NodeList for
     getElementsByTagName. See `CAVEATS' in this node.

     When this method is called in a list context, it returns a regular
     perl list containing the child nodes. Note that this list is not
     "live". E.g.

          @list = $node->getChildNodes;	      # returns a perl list
          $nodelist = $node->getChildNodes;    # returns a NodeList (object reference)
          for my $kid ($node->getChildNodes)   # iterate over the children of $node

getFirstChild
     The first child of this node. If there is no such node, this returns
     undef.

getLastChild
     The last child of this node. If there is no such node, this returns
     undef.

getPreviousSibling
     The node immediately preceding this node. If there is no such node,
     this returns undef.

getNextSibling
     The node immediately following this node. If there is no such node,
     this returns undef.

getAttributes
     A NamedNodeMap containing the attributes (Attr nodes) of this node
     (if it is an Element) or undef otherwise.  Note that adding/removing
     attributes from the returned object, also adds/removes attributes
     from the Element node that the NamedNodeMap came from.

getOwnerDocument
     The Document object associated with this node. This is also the
     Document object used to create new nodes. When this node is a
     Document this is undef.

insertBefore (newChild, refChild)
     Inserts the node newChild before the existing child node refChild. If
     refChild is undef, insert newChild at the end of the list of children.

     If newChild is a DocumentFragment object, all of its children are
     inserted, in the same order, before refChild. If the newChild is
     already in the tree, it is first removed.

     Return Value: The node being inserted.

     DOMExceptions:

        * HIERARCHY_REQUEST_ERR

          Raised if this node is of a type that does not allow children of
          the type of the newChild node, or if the node to insert is one
          of this node's ancestors.

        * WRONG_DOCUMENT_ERR

          Raised if newChild was created from a different document than
          the one that created this node.

        * NO_MODIFICATION_ALLOWED_ERR

          Raised if this node is readonly.

        * NOT_FOUND_ERR

          Raised if refChild is not a child of this node.

replaceChild (newChild, oldChild)
     Replaces the child node oldChild with newChild in the list of
     children, and returns the oldChild node. If the newChild is already
     in the tree, it is first removed.

     Return Value: The node replaced.

     DOMExceptions:

        * HIERARCHY_REQUEST_ERR

          Raised if this node is of a type that does not allow children of
          the type of the newChild node, or it the node to put in is one
          of this node's ancestors.

        * WRONG_DOCUMENT_ERR

          Raised if newChild was created from a different document than
          the one that created this node.

        * NO_MODIFICATION_ALLOWED_ERR

          Raised if this node is readonly.

        * NOT_FOUND_ERR

          Raised if oldChild is not a child of this node.

removeChild (oldChild)
     Removes the child node indicated by oldChild from the list of
     children, and returns it.

     Return Value: The node removed.

     DOMExceptions:

        * NO_MODIFICATION_ALLOWED_ERR

          Raised if this node is readonly.

        * NOT_FOUND_ERR

          Raised if oldChild is not a child of this node.

appendChild (newChild)
     Adds the node newChild to the end of the list of children of this
     node. If the newChild is already in the tree, it is first removed. If
     it is a DocumentFragment object, the entire contents of the document
     fragment are moved into the child list of this node

     Return Value: The node added.

     DOMExceptions:

        * HIERARCHY_REQUEST_ERR

          Raised if this node is of a type that does not allow children of
          the type of the newChild node, or if the node to append is one
          of this node's ancestors.

        * WRONG_DOCUMENT_ERR

          Raised if newChild was created from a different document than
          the one that created this node.

        * NO_MODIFICATION_ALLOWED_ERR

          Raised if this node is readonly.

hasChildNodes
     This is a convenience method to allow easy determination of whether a
     node has any children.

     Return Value: 1 if the node has any children, 0 otherwise.

cloneNode (deep)
     Returns a duplicate of this node, i.e., serves as a generic copy
     constructor for nodes. The duplicate node has no parent (parentNode
     returns undef.).

     Cloning an Element copies all attributes and their values, including
     those generated by the XML processor to represent defaulted
     attributes, but this method does not copy any text it contains unless
     it is a deep clone, since the text is contained in a child Text node.
     Cloning any other type of node simply returns a copy of this node.

     Parameters:  *deep*   If true, recursively clone the subtree under
     the specified node.  If false, clone only the node itself (and its
     attributes, if it is an Element).

     Return Value: The duplicate node.

normalize
     Puts all Text nodes in the full depth of the sub-tree underneath this
     Element into a "normal" form where only markup (e.g., tags, comments,
     processing instructions, CDATA sections, and entity references)
     separates Text nodes, i.e., there are no adjacent Text nodes. This
     can be used to ensure that the DOM view of a document is the same as
     if it were saved and re-loaded, and is useful when operations (such as
     XPointer lookups) that depend on a particular document tree structure
     are to be used.

     *Not In DOM Spec*: In the DOM Spec this method is defined in the
     Element and Document class interfaces only, but it doesn't hurt to
     have it here...

getElementsByTagName (name [, recurse])
     Returns a NodeList of all descendant elements with a given tag name,
     in the order in which they would be encountered in a preorder
     traversal of the Element tree.

     Parameters:  name  The name of the tag to match on. The special value
     "*" matches all tags.   recurse  Whether it should return only direct
     child nodes (0) or any descendant that matches the tag name (1). This
     argument is optional and defaults to 1. It is not part of the DOM
     spec.

     Return Value: A list of matching Element nodes.

     NOTE: this implementation does not return a "live" NodeList for
     getElementsByTagName. See `CAVEATS' in this node.

     When this method is called in a list context, it returns a regular
     perl list containing the result nodes. E.g.

          @list = $node->getElementsByTagName("tag");       # returns a perl list
          $nodelist = $node->getElementsByTagName("tag");   # returns a NodeList (object ref.)
          for my $elem ($node->getElementsByTagName("tag")) # iterate over the result nodes

Additional methods not in the DOM Spec
--------------------------------------

getNodeTypeName
     Return the string describing the node type.  E.g. returns
     "ELEMENT_NODE" if getNodeType returns ELEMENT_NODE.  It uses
     @XML::DOM::Node::NodeNames.

toString
     Returns the entire subtree as a string.

printToFile (filename)
     Prints the entire subtree to the file with the specified filename.

     Croaks: if the file could not be opened for writing.

printToFileHandle (handle)
     Prints the entire subtree to the file handle.  E.g. to print to
     STDOUT:

          $node->printToFileHandle (\*STDOUT);

print (obj)
     Prints the entire subtree using the object's print method. E.g to
     print to a FileHandle object:

          $f = new FileHandle ("file.out", "w");
          $node->print ($f);

getChildIndex (child)
     Returns the index of the child node in the list returned by
     getChildNodes.

     Return Value: the index or -1 if the node is not found.

getChildAtIndex (index)
     Returns the child node at the specifed index or undef.

addText (text)
     Appends the specified string to the last child if it is a Text node,
     or else appends a new Text node (with the specified text.)

     Return Value: the last child if it was a Text node or else the new
     Text node.

dispose
     Removes all circular references in this node and its descendants so
     the objects can be claimed for garbage collection. The objects should
     not be used afterwards.

setOwnerDocument (doc)
     Sets the ownerDocument property of this node and all its children (and
     attributes etc.) to the specified document.  This allows the user to
     cut and paste document subtrees between different
     XML::DOM::Documents. The node should be removed from the original
     document first, before calling setOwnerDocument.

     This method does nothing when called on a Document node.

isAncestor (parent)
     Returns 1 if parent is an ancestor of this node or if it is this node
     itself.

expandEntityRefs (str)
     Expands all the entity references in the string and returns the
     result.  The entity references can be character references (e.g.
     "&#123;" or "&#x1fc2"), default entity references ("&quot;", "&gt;",
     "&lt;", "&apos;" and "&amp;") or entity references defined in Entity
     objects as part of the DocumentType of the owning Document. Character
     references are expanded into UTF-8.  Parameter entity references
     (e.g. %ent;) are not expanded.

to_sax ( %HANDLERS )
     E.g.

          $node->to_sax (DocumentHandler => $my_handler,
          		Handler => $handler2 );

     %HANDLERS may contain the following handlers:

        * DocumentHandler

        * DTDHandler

        * EntityResolver

        * Handler

          Default handler when one of the above is not specified

     Each XML::DOM::Node generates the appropriate SAX callbacks (for the
     appropriate SAX handler.) Different SAX handlers can be plugged in to
     accomplish different things, e.g. See XML/Checker,
     would check the node (currently only Document and Element nodes are
     supported), see XML/Handler/BuildDOM, would
     create a new DOM subtree (thereby, in essence, copying the Node) and
     in the near future, XML::Writer could print the node.  All Perl SAX
     related work is still in flux, so this interface may change a little.

     See PerlSAX for the description of the SAX interface.

check ( [$checker] )
     See descriptions for check() in XML/DOM/Document,
     and XML/DOM/Element.

xql ( @XQL_OPTIONS )
     To use the xql method, you must first use XML/XQL, and
     XML/XQL/DOM.  This method is basically a shortcut
     for:

          $query = new XML::XQL::Query ( @XQL_OPTIONS );
          return $query->solve ($node);

     If the first parameter in @XQL_OPTIONS is the XQL expression, you can
     leave off the 'Expr' keyword, so:

          $node->xql ("doc//elem1[@attr]", @other_options);

     is identical to:

          $node->xql (Expr => "doc//elem1[@attr]", @other_options);

     See XML/XQL/Query, for other available
     XQL_OPTIONS.  See XML/XQL, and XML/XQL/Tutorial,
     for more info.

isHidden ()
     Whether the node is hidden.  See `Hidden Nodes|XML::DOM' in this node
     for details.

A node list as used by XML::DOM
*******************************

NAME
====

   XML::DOM::NodeList - A node list as used by XML::DOM

DESCRIPTION
===========

   The NodeList interface provides the abstraction of an ordered
collection of nodes, without defining or constraining how this collection
is implemented.

   The items in the NodeList are accessible via an integral index,
starting from 0.

   Although the DOM spec states that all NodeLists are "live" in that they
allways reflect changes to the DOM tree, the NodeList returned by
getElementsByTagName is not live in this implementation. See `CAVEATS' in
this node for details.

METHODS
-------

item (index)
     Returns the indexth item in the collection. If index is greater than
     or equal to the number of nodes in the list, this returns undef.

getLength
     The number of nodes in the list. The range of valid child node
     indices is 0 to length-1 inclusive.

Additional methods not in the DOM Spec
--------------------------------------

dispose
     Removes all circular references in this NodeList and its descendants
     so the objects can be claimed for garbage collection. The objects
     should not be used afterwards.

An XML NOTATION in XML::DOM
***************************

NAME
====

   XML::DOM::Notation - An XML NOTATION in XML::DOM

DESCRIPTION
===========

   XML::DOM::Notation extends XML/DOM/Node.

   This node represents a Notation, e.g.

     <!NOTATION gs SYSTEM "GhostScript">

     <!NOTATION name PUBLIC "pubId">

     <!NOTATION name PUBLIC "pubId" "sysId">

     <!NOTATION name SYSTEM "sysId">

METHODS
-------

getName and setName (name)
     Returns (or sets) the Notation name, which is the first token after
     the NOTATION keyword.

getSysId and setSysId (sysId)
     Returns (or sets) the system ID, which is the token after the optional
     SYSTEM keyword.

getPubId and setPubId (pubId)
     Returns (or sets) the public ID, which is the token after the optional
     PUBLIC keyword.

getBase
     This is passed by XML::Parser in the Notation handler.  I don't know
     what it is yet.

getNodeName
     Returns the same as getName.

An XML::Parser that builds XML::DOM document structures
*******************************************************

NAME
====

   XML::DOM::Parser - An XML::Parser that builds XML::DOM document
structures

SYNOPSIS
========

     use XML::DOM;

     my $parser = new XML::DOM::Parser;
     my $doc = $parser->parsefile ("file.xml");

DESCRIPTION
===========

   XML::DOM::Parser extends XML/Parser,

   The XML::Parser module was written by Clark Cooper and is built on top
of XML::Parser::Expat, which is a lower level interface to James Clark's
expat library.

   XML::DOM::Parser parses XML strings or files and builds a data
structure that conforms to the API of the Document Object Model as
described at `http:' in this node.  See the XML/Parser,
manpage for other additional properties of the XML::DOM::Parser class.
Note that the 'Style' property should not be used (it is set internally.)

   The XML::Parser *NoExpand* option is more or less supported, in that it
will generate EntityReference objects whenever an entity reference is
encountered in character data. I'm not sure how useful this is. Any
comments are welcome.

   As described in the synopsis, when you create an XML::DOM::Parser
object, the parse and parsefile methods create an XML/DOM/Document,
object from the specified input. This Document object
can then be examined, modified and written back out to a file or converted
to a string.

   When using XML::DOM with XML::Parser version 2.19 and up, setting the
XML::DOM::Parser option *KeepCDATA* to 1 will store CDATASections in
CDATASection nodes, instead of converting them to Text nodes.  Subsequent
CDATASection nodes will be merged into one. Let me know if this is a
problem.

Using LWP to parse URLs
=======================

   The parsefile() method now also supports URLs, e.g.
*http://www.erols.com/enno/xsa.xml*.  It uses LWP to download the file and
then calls parse() on the resulting string.  By default it will use a
LWP/UserAgent, that is created as follows:

     use LWP::UserAgent;
     $LWP_USER_AGENT = LWP::UserAgent->new;
     $LWP_USER_AGENT->env_proxy;

   Note that env_proxy reads proxy settings from environment variables,
which is what I need to do to get thru our firewall. If you want to use a
different LWP::UserAgent, you can either set it globally with:

     XML::DOM::Parser::set_LWP_UserAgent ($my_agent);

   or, you can specify it for a specific XML::DOM::Parser by passing it to
the constructor:

     my $parser = new XML::DOM::Parser (LWP_UserAgent => $my_agent);

   Currently, LWP is used when the filename (passed to parsefile) starts
with one of the following URL schemes: http, https, ftp, wais, gopher, or
file (followed by a colon.)  If I missed one, please let me know.

   The LWP modules are part of libwww-perl which is available at CPAN.

Old name of XML/Handler/BuildDOM,
*************************************************************

NAME
====

   XML::DOM::PerlSAX - Old name of XML/Handler/BuildDOM,

SYNOPSIS
========

     See L<XML::DOM::BuildDOM>

DESCRIPTION
===========

   XML::DOM::PerlSAX was renamed to XML/Handler/BuildDOM,
to comply with naming conventions for PerlSAX
filters/handlers.

   For backward compatibility, this package will remain in existence (it
simply includes XML::Handler::BuildDOM), but it will print a warning when
running with *'perl -w'*.

AUTHOR
======

   Send bug reports, hints, tips, suggestions to Enno Derksen at
<`enno@att.com'>.

SEE ALSO
========

   See XML/Handler/BuildDOM, XML/DOM,

An XML processing instruction in XML::DOM
*****************************************

NAME
====

   XML::DOM::ProcessingInstruction - An XML processing instruction in
XML::DOM

DESCRIPTION
===========

   XML::DOM::ProcessingInstruction extends XML/DOM/Node.

   It represents a "processing instruction", used in XML as a way to keep
processor-specific information in the text of the document. An example:

     <?PI processing instruction?>

   Here, "PI" is the target and "processing instruction" is the data.

METHODS
-------

getTarget
     The target of this processing instruction. XML defines this as being
     the first token following the markup that begins the processing
     instruction.

getData and setData (data)
     The content of this processing instruction. This is from the first
     non white space character after the target to the character
     immediately preceding the ?>.

A piece of XML text in XML::DOM
*******************************

NAME
====

   XML::DOM::Text - A piece of XML text in XML::DOM

DESCRIPTION
===========

   XML::DOM::Text extends XML/DOM/CharacterData,
which extends XML/DOM/Node.

   The Text interface represents the textual content (termed character
data in XML) of an Element or Attr. If there is no markup inside an
element's content, the text is contained in a single object implementing
the Text interface that is the only child of the element.  If there is
markup, it is parsed into a list of elements and Text nodes that form the
list of children of the element.

   When a document is first made available via the DOM, there is only one
Text node for each block of text. Users may create adjacent Text nodes
that represent the contents of a given element without any intervening
markup, but should be aware that there is no way to represent the
separations between these nodes in XML or HTML, so they will not (in
general) persist between DOM editing sessions. The normalize() method on
Element merges any such adjacent Text objects into a single node for each
block of text; this is recommended before employing operations that depend
on a particular document structure, such as navigation with XPointers.

METHODS
-------

splitText (offset)
     Breaks this Text node into two Text nodes at the specified offset,
     keeping both in the tree as siblings. This node then only contains
     all the content up to the offset point. And a new Text node, which is
     inserted as the next sibling of this node, contains all the content
     at and after the offset point.

     Parameters:  offset  The offset at which to split, starting from 0.

     Return Value: The new Text node.

     DOMExceptions:

        * INDEX_SIZE_ERR

          Raised if the specified offset is negative or greater than the
          number of characters in data.

        * NO_MODIFICATION_ALLOWED_ERR

          Raised if this node is readonly.

an XML::DOM::Parser that validates at parse time
************************************************

NAME
====

   XML::DOM::ValParser - an XML::DOM::Parser that validates at parse time

SYNOPSIS
========

     use XML::DOM::ValParser;

     my %expat_options = (KeepCDATA => 1,
     		      Handlers => [ Unparsed => \&my_Unparsed_handler ]);
     my $parser = new XML::DOM::ValParser (%expat_options);

     eval {
         local $XML::Checker::FAIL = \&my_fail;
         my $doc = $parser->parsefile ("fail.xml");
         ... XML::DOM::Document was created sucessfully ...
     };
     if ($@) {
         # Either XML::Parser (expat) threw an exception or my_fail() died.
         ... your error handling code here ...
         # Note that the XML::DOM::Document is automatically disposed off and
         # will be garbage collected
     }

     # Throws an exception (with die) when an error is encountered, this
     # will stop the parsing process.
     # Don't die if a warning or info message is encountered, just print a message.
     sub my_fail {
         my $code = shift;
         die XML::Checker::error_string ($code, @_) if $code < 200;
         XML::Checker::print_error ($code, @_);
     }

DESCRIPTION
===========

   Use XML::DOM::ValParser wherever you would use XML/DOM/Parser,
and your XML will be checked using XML/Checker,
at parse time.

   See XML/DOM, for details on XML::DOM::Parser options.
See XML/Checker, for details on setting the fail
handler (my_fail.)

   The following handlers are currently supported, just like
XML::DOM::Parser: Init, Final, Char, Start, End, Default, Doctype,
CdataStart, CdataEnd, XMLDecl, Entity, Notation, Proc, Default, Comment,
Attlist, Element, Unparsed.

XML::DOM::ValParser
===================

   XML::DOM::ValParser extends from XML/Checker/Parser.
It creates an XML/Checker, object
and routes all event handlers through the checker, before processing the
events to create the XML::DOM::Document.

   Just like XML/Checker/Parser, the checker
object can be retrieved with the getChecker() method and can be reused
later on (provided that the DOCTYPE section of the XML::DOM::Document did
not change in the mean time.)

   You can control which errors are fatal (and therefore should stop
creation of the XML::DOM::Document) by filtering the appropriate error
codes in the global $XML::Checker::FAIL handler (see `ERROR_HANDLING',
see XML/Checker) and calling die or croak appropriately.

   Just like XML::Checker::Parser, XML::DOM::ValParser supports the
SkipExternalDTD and SkipInsignifWS options. See XML/Checker/Parser,
for details.

AUTHOR
======

   Send bug reports, hints, tips, suggestions to Enno Derksen at
<`enno@att.com'>.

SEE ALSO
========

   See XML/DOM, XML/Checker, (`SEE_ALSO',
see XML/Checker)

XML declaration in XML::DOM
***************************

NAME
====

   XML::DOM::XMLDecl - XML declaration in XML::DOM

DESCRIPTION
===========

   XML::DOM::XMLDecl extends XML/DOM/Node, but is not
part of the DOM Level 1 specification.

   It contains the XML declaration, e.g.

     <?xml version="1.0" encoding="UTF-16" standalone="yes"?>

   See also XML::DOM::Document::getXMLDecl.

METHODS
-------

getVersion and setVersion (version)
     Returns and sets the XML version. At the time of this writing the
     version should always be "1.0"

getEncoding and setEncoding (encoding)
     undef may be specified for the encoding value.

getStandalone and setStandalone (standalone)
     undef may be specified for the standalone value.

a package for down translation of XML to strings
************************************************

NAME
====

   XML::DT - a package for down translation of XML to strings

SYNOPSIS
========

     use XML::DT;

     %xml=( 'music'    => sub{"Music from: $c\n"},
            'lyrics'   => sub{"Lyrics from:$c\n (the value of attribute
                                IN is:$v{IN}\n)"},
            'title'    => sub{ uc($c) },
            '-default' => sub{"$q:$c"},
            '-outputenc' => 'ISO-8859-1');

     print dt($filename,%xml);

     print dtstring("<arq>
                     <title>Vejam Bem</title>
                     <music>Zeca Afonso</music>
                     </arq>",%xml);

     inctxt('music/lyrics')
     inctxt('music.*')

     ctxt(1)       /* the father element */

     mkdtskel($file)
     mkdtdskel($file)

DESCRIPTION
===========

   This module processes XML files with an approach similar to OMNIMARK.

   Down translation function `dt' receives a filename and a set of
expressions (functions) defining the processing and associated values for
each element.

   `dtstring' is similar but takes input from a string instead of a file.

`pathdt' function
-----------------

   The `pathdt' function uses a subset of XPath as key in the handler.
Example:

     %handler = (
          "article/title" => sub{ toxml("h1",{},$c) },
          "section/title" => sub{ toxml("h2",{},$c) },
          "title"         => sub{ $c },
          "//image[@type='jpg']" => sub{ "JPEG: <img src=\"$c\">" },
          "//image[@type='bmp']" => sub{ "BMP: sorry, no bitmaps on the web" },
          ...
       )

     pathdt($filename,%handler);

   Here are some examples of valid XPath expressions under XML::DT:

     /aaa
     /aaa/bbb
     //ccc                           - ccc somewhere (same as "ccc")
     /*/aaa/*
     //*                             - same as "-default"
     /aaa[@id]                       - aaa with an attribute id
     /*[@*]                          - root with an attribute
     /aaa[not(@name)]                - aaa with no attribute "name"
     //bbb[@name='foo']              - ... attribute "name" = "foo"
     /ccc[normalize-space(@name)='bbb']
     //*[name()='bbb']               - complex way of saying "//bbb"
     //*[starts-with(name(),'aa')]   - an element named "aa.*"
     //*[contains(name(),'c')]       - an element       ".*c.*"
     //aaa[string-length(name())=4]  -                  "...."
     //aaa[string-length(name())&lt;4]                  ".{1,4}"
     //aaa[string-length(name())&gt;5]                  ".{5,}"

   For more information, visit www.w3c.org or try a tutorial under
www.zvon.org

`inctxt' function
-----------------

   `inctxt(pattern)' is true if the actual element path matches the
provided pattern. This function is meant to be used in the element
functions in order to achieve context dependent processing.

User provided element processing functions
------------------------------------------

   The user must provide an HASH with a function for each element, that
computes element output. Functions can use the element name $q, the
element content $c and the attribute values hash `%v'.

   All those global variables are defined in `$CALLER::'.

   Each time an element is find the associated function is called.

   Content is calculated by concatenation of element contents strings and
interior elements return values.

`-default' function
-------------------

   When a element has no associated function, the function associated with
`-default' called. If no `-default' function is defined the default
function returns a XML like string for the element.

   When you use `/-type' definitions, you often need do set `-default'
function to return just the contents: `sub{$id}'.

`-outputenc' option
-------------------

   `-outputenc' defines the output encoding (default is Unicode UTF8).

`-inputenc' option
------------------

   `-inputenc' forces a input encoding type. Whenever that is possible,
define the input encoding in the XML file:

     <?xml version='1.0' encoding='ISO-8859-1'?>

`-pcdata' function
------------------

   `-pcdata' function is used to define transformation over the contents.
Typically this function should look at context (see `inctxt' function)

   The default `-pcdata' function is the identity

`-begin' function
-----------------

   Function to be executed before processing XML file.

   Example of use: initialization of side-effect variables

`-end' function
---------------

   Function to be executed after processing XML file.  I can use $c
content value.  The value returned by `-end' will be the `dt' return value.

   Example of use: post-processing of returned contents

`toxml' function
----------------

   This is the default "-default" function. It can be used to generate xml
based on $c $q and `%v' variables. Example: add a new attribute to element
`ele1' without changing it:

     %handler=( ...
                ele1 => sub { $v{at1} = "v1"; toxml(); },
              )

   `toxml' can also be used with 3 arguments: tag, attrigutes and contents

     toxml("a",{href=> "http://local/f.html"}, "example")

   returns:

     <a href='http://local/f.html'>example</a>

Elements with values other than strings (`-type')
=================================================

   By default all elements return strings, and contents ($c) is the
concatenation of the strings returned by the sub-elements.

   In some situations the XML text contains values that are better
processed as a structured type.

   The following types (functors) are available:

     STR  -> concatenates all the subelements returned values (DEFAULT)
          all the subelement should return strings to be concatenated
     SEQ  -> makes an ARRAY with all the sub elements contents; attributes are
          ignored (they should be processed in the subelement). (returns a ref)
     SEQH -> makes an ARRAY of HASH with all the sub elements (returns a ref);
          for each subelement:
                 -q  => element name
                 -c  => contents
                 at1 => at value1    for each attribute
     MAP  -> makes an HASH with the sub elements; keys are the sub-element
          names, values are their contents. Attributes are ignored. (they should
          be processed in the subelement) (returns a ref)
     MULTIMAP -> makes an HASH of ARRAY; keys are the sub-element names;
         values are lists of contents; attributes are ignored (they should be
         processed in the subelement); (returns a ref)
     MMAPON(elementlist) -> makes an HASH with the subelements;
          keys are the sub-element names, values are their contents;
          attributes are ignored (they should be processed in the subelement);
          for all the elements contained in the elementlist, it is created
          an ARRAY with their contents. (returns a ref)
     ZERO -> don't process the subelements; return ""

   When you use `/-type' definitions, you often need do set `-default'
function returning just the contents `sub{$id}'.

An example:
-----------

     use XML::DT;
     %handler = ( contacts => sub{ [ split(";",$c)] },
                  -default => sub{$c},
                  -type    => { institution => 'MAP',
                                degrees     =>  MMAPON('name')
                                tels        => 'SEQ' }
                );
     $a = dt ("f.xml", %handler);

   with the following f.xml

     <degrees>
      <institution>
       <id>U.M.</id>
       <name>University of Minho</name>
       <tels>
         <item>1111</item>
         <item>1112</item>
         <item>1113</item>
       </tels>
       <where>Portugal</where>
       <contacts>J.Joao; J.Rocha; J.Ramalho</contacts>
      </institution>
      <name>Computer science</name>
      <name>Informatica </name>
      <name> history </name>
     </degrees>

   would make $a

     { 'name' => [ 'Computer science',
                   'Informatica ',
                   ' history ' ],
       'institution' => { 'tels' => [ 1111,
                                      1112,
                                      1113 ],
                          'name' => 'University of Minho',
                          'where' => 'Portugal',
                          'id' => 'U.M.',
                          'contacts' => [ 'J.Joao',
                                          ' J.Rocha',
                                          ' J.Ramalho' ] } };

DT Skeleton generation
======================

   It is possible to build an initial processor program based on an example

   To do this use the function `mkdtskel(filename)'.

   Example:

     perl -MXML::DT -e 'mkdtskel "f.xml"' > f.pl

DTD skeleton generation
=======================

   It makes a naive DTD based on an example(s).

   To do this use the function `mkdtdskel(filename*)'.

   Example:

     perl -MXML::DT -e 'mkdtdskel "f.xml"' > f.dtd

BUGS
====

   This section is out of date...

Author
======

   Jose Joao, jj@di.uminho.pt

     http://natura.di.uminho.pt/~jj/perl/XML/

   Alberto Simoes <albie@alfarrabio.di.uminho.pt>

   thanks to

     Michel Rodriguez <mrodrigu@ieee.org>
     José Carlos Ramalho <jcr@di.uminho.pt>

module for unicode utf8 to latin1 translation
*********************************************

NAME
====

   `lat1.pm' - module for unicode utf8 to latin1 translation

SYNOPSIS
========

     $latin1string = lat1::utf8($utf8string)

Bugs
====

   Translating the latin1 subset of unicode utf8 is very simples and needs
no tables.

   If you need more complex translation, see the perl modules about unicode
and the `recode' command.

A DTD object class
******************

NAME
====

   XML::Doctype - A DTD object class

SYNOPSIS
========

     # To parse an external DTD at compile time, useful when
     # using XML::ValidWriter
     use XML::Doctype NAME => 'FooML', SYSTEM_ID => 'FooML.dtd' ;
     use XML::Doctype NAME => 'FooML', DTD_TEXT  => $dtd ;

     # Parsing at run-time
     $doctype = XML::Doctype->new( 'FooML', SYSTEM_ID => 'FooML.dtd' ) ;

     # or
     $doctype = XML::Doctype->new() ;
     $doctype->parse( 'FooML', 'FooML.dtd' ) ;

     # Saving the parsed object
     open( PM, ">FooML/DTD/v1_000.pm" ) or die $! ;
     print PM $doctype->as_pm( 'FooML::DTD::v1_000' ) ;

     # Using a saved parsed DTD
     use FooML::DTD::v1_000 ;

     $doctype = FooML::DTD::v1_000->new() ;

DESCRIPTION
===========

   This module parses DTDs and allows them to be saved as .pm files and
reloaded.  The ability to save and reload is intended to aid in packaging
parsed DTDs with XML tools so that XML::Parser need not be installed.

STATUS
======

   This module is alpha code.  It's developed enough to support
XML::ValidWriter, but need a lot of work.  Some big things that are
lacking are:

   * methods or objects to build / traverse the DTD

   * XML::Doctype::ELEMENT

   * XML::Doctype::ATTLIST

   * XML::Doctype::ENITITY

METHODS
=======

new
          $doctype = XML::Doctype->new() ;
          $doctype = XML::Doctype->new( 'FooML', DTD_TEXT => $doctype_text ) ;
          $doctype = XML::Doctype->new( 'FooML', SYSTEM_ID => 'FooML.dtd' ) ;

name
          $name = $doctype->name() ;

          Sets/gets the name.

parse_dtd
          $doctype->parse_dtd( $name, $doctype_text ) ;
          $doctype->parse_dtd( $name, $doctype_text, 'internal' ) ;

     Parses the text of a DTD from a scalar.  $name is used to indicate the
     name of the DOCTYPE, and thus the root node.

     The DTD is considered to be external unless the third parameter is
     TRUE.

parse_dtd_file
          $doctype->parse_dtd_file( $name, $system_id [, $public_id] ) ;
          $doctype->parse_dtd_file( $name, $system_id [, $public_id], 'internal' ) ;

     Parses a DTD from a file.  Eventually will support full URL syntax.

     $public_id is ignored for now, and $system_id is used to locate the
     DTD.

     This routine requires XML::Parser.  XML::Parser is not loaded at any
     other time and is not needed to use the resulting DTD object.

     The DTD is considered to be external unless the fourth parameter is
     TRUE.

          $doctype->parse_dtd_file( $name, $system_id, $p_id, 'internal' ) ;
          $doctype->parse_dtd_file( $name, $system_id, undef, 'internal' ) ;

system_id
          $system_id = $doctype->system_id() ;

          Sets/gets the system ID.

public_id
          $public_id = $doctype->public_id() ;

          Sets/gets the public_id.

element_decl
          $elt_decl = $doctype->element_decl( $name ) ;

     Returns the XML::Doctype:Element object associated with $name.  These
     can be defined by <!ELEMENT> tags or undefined, which can happen if
     they were just referred-to by <!ELEMENT> or <!ATTLIST> tags.

element_names
     Returns an unsorted list of element names.  This list includes names
     that are declared and undeclared (but referred to in element
     declarations or attribute definitions).

as_pm
          open( PM, "FooML/DTD/v1_001.pm" )            or die $! ;
          print PM $doctype->as_pm( 'FooML::DTD::v1_001' ) or die $! ;
          close PM                                     or die $! ;

     Then, later:

          use FooML::DTD::v1_001 ;   # Do *not* use () as a parameter list!

     Returns string containing the DTD as an independant module, allowing
     the DTD to be parsed in the development environment and shipped as
     Perl code, so that the target environment need not have XML::Parser
     installed.

     This is useful for XML creation-only tools and as an efficiency
     tuning measure if you will be rereading the same set of DTDs over and
     over again.

import
use
          use XML::Doctype NAME => 'FooML', SYSTEM_ID => 'dtds/FooML.dtd' ;

     import() constructs a default DTD object for the calling package so
     that XML::ValidWriter's functional interface can use it.

     If XML::Doctype is subclassed, the subclasses' constructor is called
     with all parameters.

SUBCLASSING
===========

   This object uses the fields pragma, so you should use base and fields
for any subclasses.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

COPYRIGHT
=========

   This module is Copyright 2000, Barrie Slaymaker.  All rights reserved.

   This module is licensed under the GPL, version 2.  Please contact me if
this does not suit your needs.

A class representing a definition in an <!ATTLIST> tag
******************************************************

NAME
====

   XML::Doctype::AttDef - A class representing a definition in an
<!ATTLIST> tag

SYNOPSIS
========

     $attr = $elt->attribute( $name ) ;
     $attr->name ;

DESCRIPTION
===========

   This module is used to represent <!ELEMENT> tags in an XML::Doctype
object.  It contains <!ATTLIST> tags as well.

STATUS
======

   This module is alpha code.  It's developed enough to support
XML::ValidWriter, but need a lot of work.  Some big things that are
lacking are:

METHODS
=======

new
          $dtd = XML::Doctype::AttDef->new( $name, $type, $default ) ;

default
          ( $spec, $value ) = $attr->default ;
          $attr->default( '#REQUIRED' ) ;
          $attr->default( '#IMPLIED' ) ;
          $attr->default( '', 'foo' ) ;
          $attr->default( '#FIXED', 'foo' ) ;

     Sets/gets the default value.  This is a

quant
          $attdef->quant( $q ) ;
          $q = $attdef->quant ;

     Sets/gets the attribute quantifier: '#REQUIRED', '#FIXED',
     '#IMPLIED', or ".

name
          $attdef->name( $name ) ;
          $name = $attdef->name ;

     Sets/gets this attribute name.  Don't change the name while an
     attribute is in an element's attlist, since it will then be filed
     under the wrong name.

default_on_write
          $attdef->default_on_write( $value ) ;
          $value = $attdef->default_on_write ;

          $attdef->default_on_write( $attdef->default ) ;

     Sets/gets the value which is automatically output for this attribute
     if none is supplied to $writer->startTag.  This is typically used to
     set a document-wide default for #REQUIRED attributes (and perhaps
     plain attributes) so that the attribute is treated like a #FIXED tag
     and emitted with a fixed value.

     The default_on_write does not need to be the same as the default
     unless the quantifier is #FIXED.

SUBCLASSING
===========

   This object uses the fields pragma, so you should use base and fields
for any subclasses.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

COPYRIGHT
=========

   This module is Copyright 2000, Barrie Slaymaker.  All rights reserved.

   This module is licensed under the GPL, version 2.  Please contact me if
this does not suit your needs.

A class representing an <!ELEMENT> tag
**************************************

NAME
====

   XML::Doctype::ElementDecl - A class representing an <!ELEMENT> tag

SYNOPSIS
========

     $elt = $dtd->element( 'foo' ) ;
     $elt->name() ;
     $elt->attr( 'foo' ) ;

DESCRIPTION
===========

   This module is used to represent <!ELEMENT> tags in an XML::Doctype
object.  It contains <!ATTLIST> tags as well.

STATUS
======

   This module is alpha code.  It's developed enough to support
XML::ValidWriter, but need a lot of work.  Some big things that are
lacking are:

METHODS
=======

new
          # Undefined element constructors:
          $dtd = XML::Doctype::ElementDecl->new( $name ) ;
          $dtd = XML::Doctype::ElementDecl->new( $name, undef, \@attdefs ) ;

          # Defined element constructors
          $dtd = XML::Doctype::ElementDecl->new( $name, \@kids, \@attdef ) ;
          $dtd = XML::Doctype::ElementDecl->new( $name, [], \@attdefs ) ;

add_attdef
          $elt_decl->add_attdef( $att_def ) ;

attdef
          $attr = $elt->attdef( $name ) ;

     Returns the XML::Doctype::AttDef named by $name or undef if there is
     no such attribute.

attdefs
          $attdefs = $elt->attdefs( $name ) ;

     Returns the list of XML::Doctype::AttDef instances associated with
     this element.

attribute_names
     Returns a list of the attdefs' names.

child_names
          @names = $elt->child_names ;

     Returns a list of names of elements in this element decl's content
     model.

is_declared
          if ( $elt_decl->is_declared ) ...
          $elt_decl->is_declared( 1 ) ;

     Returns TRUE if there is any data defined in the element other than
     name and attributes or if is_declared has been set by calling
     is_declared( 1 ) or passing DECLARED => 1 to new().

is_empty
is_any
is_mixed
name
          $n = $elt_decl->name ;

     Gets the name of the element.

validate_content
          $v = $elt_decl->validate_content( \@seq ) ;

     Takes an ARRAY ref of tag names (or '#PCDATA') and checks to see if
     it would be valid content for elements of this type.

     Right now, this must be called only when an element's end tag is
     emitted.  It can be broadened to be incremental if need be.

SUBCLASSING
===========

   This object uses the fields pragma, so you should use base and fields
for any subclasses.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

COPYRIGHT
=========

   This module is Copyright 2000, Barrie Slaymaker.  All rights reserved.

   This module is licensed under the GPL, version 2.  Please contact me if
this does not suit your needs.

SAX Driver for non wellformed HTML.
***********************************

NAME
====

   XML::Driver::HTML - SAX Driver for non wellformed HTML.

SYNOPSIS
========

     use XML::Driver::HTML;

     $driver = new XML::Driver::HTML(
     	'Handler' => $some_sax_filter_or_handler,
     	'Source' => $some_PerlSAX_like_hash
     	);

     $driver->parse();

   or

     use XML::Driver::HTML;

     $driver = new XML::Driver::HTML();

     $driver->parse(
     	'Handler' => $some_sax_filter_or_handler,
     	'Source' => $some_PerlSAX_like_hash
     	);

     $driver->parse(
     	'Handler' => $some_other_sax_filter_or_handler,
     	'Source' => $some_other_source
     	);

     =head1 DESCRIPTION

   XML::Driver::HTML is a SAX Driver for HTML. There is no need for the
HTML input to be weel formed, as XML::Driver::HTML is generating its SAX
events by walking a HTML::TreeBuilder object. The simplest kind of use, is
a filter from HTML to XHTML using XML::Handler::YAWriter as a SAX Handler.

     my $ya = new XML::Handler::YAWriter(
     	'Output' => new IO::File ( ">-" ),
     	'Pretty' => {
     	    'NoWhiteSpace'=>1,
     	    'NoComments'=>1,
     	    'AddHiddenNewline'=>1,
     	    'AddHiddenAttrTab'=>1,
     	    }
     	);

     my $html = new XML::Driver::HTML(
     	'Handler' => $ya,
     	'Source' => { 'ByteStream' => new IO::File ( "<-" ) }
     	);

     $html->parse();

METHODS
-------

new
     Creates a new XML::Driver::HTML object. Default options for parsing,
     described below, are passed as key-value pairs or as a single hash.
     Options may be changed directly in the object.

parse
     Parses a document.  Options, described below, are passed as key-value
     pairs or as a single hash.  Options passed to parse() override the
     default options in the parser object for the duration of the parse.

OPTIONS
-------

   The following options are supported by XML::Driver::HTML :

Handler
     Default SAX Handler to receive events

Source
     Hash containing the input source for parsing.  The `Source' hash may
     contain the following parameters:

    ByteStream
          The raw byte stream (file handle) containing the document.

    String
          A string containing the document.

    SystemId
          The system identifier (URI) of the document.

    Encoding
          A string describing the character encoding.

     If more than one of `ByteStream', `String', or `SystemId', then
     preference is given first to `ByteStream', then `String', then
     `SystemId'.

NOTES
=====

   XML::Driver::HTML requires Perl 5.6 to convert from ISO-8859-1 to UTF-8.

BUGS
====

   not yet implemented:

     Interpretation of SystemId as being an URI
     XHTML document type

   other bugs:

     HTML::Parser and HTML::TreeBuilder bugs concerning DOCTYPE and CSS.
     The NotSoFree License is incompatible to the GNU General Public License.

AUTHOR
======

     Michael Koehne, Kraehe@Copyleft.De
     (c) 2000 NotSoFree License

SEE ALSO
========

   See XML/Parser/PerlSAX, and
HTML/TreeBuilder,

Perl module for dumping Perl objects from/to XML
************************************************

NAME
====

   XML::Dumper - Perl module for dumping Perl objects from/to XML

SYNOPSIS
========

     # Convert Perl code to XML
     use XML::Dumper;
     my $dump = new XML::Dumper;
     $data = [
              {
                first => 'Jonathan',
                last => 'Eisenzopf',
                email => 'eisen@pobox.com'
              },
              {
                first => 'Larry',
                last => 'Wall',
                email => 'larry@wall.org'
     	  }
     	 ];
     $xml =  $dump->pl2xml($perl);

     # Convert XML to Perl code
     use XML::Dumper;
     my $dump = new XML::Dumper;

     # some XML
     my $xml = <<XML;
     <perldata>
     <scalar>foo</scalar>
     </perldata>
     XML

     # load Perl data structure from dumped XML
     $data = $dump->xml2pl($Tree);

DESCRIPTION
===========

   XML::Dumper dumps Perl data to a structured XML format.  XML::Dumper
can also read XML data that was previously dumped by the module and
convert it back to Perl.

   This is done via the following 2 methods: XML::Dumper::pl2xml
XML::Dumper::xml2pl

AUTHOR
======

   Jonathan Eisenzopf <eisen@pobox.com>

CREDITS
=======

   Chris Thorman <ct@ignitiondesign.com> L.M.Orchard <deus_x@pobox.com>
DeWitt Clinton <dewitt@eziba.com>

SEE ALSO
========

   perl(1), XML::Parser(3).

A framework for embedding XML into a web server
***********************************************

NAME
====

   XML::EP - A framework for embedding XML into a web server

SYNOPSIS
========

     # Generate a new XML::EP instance
     use XML::EP();
     my $ep = XML::EP->new();

     # Let the instance process an HTTP request
     $ep->handle($request);

DESCRIPTION
===========

   XML::EP is an administrative framework for embedding XML into a web
server. That means that the system allows you to retrieve XML documents
from external storage (files, a Tamino database engine, or whatever),
parse them, pipe the parsed XML tree into processors (modules, that change
the tree, for example the DBI processor will issue SQL queries and insert
the result as XML elements). Finally the XML tree will be piped into a
so-called formatter, that converts XML to HTML and prints the result.

   The architecture is as follows:

     +---------------------+
     |   Control element   |
     +---------------------+
                    /          |            \
                   /           |             \
        +----------+ XML  +------------+ XML  +-----------+
        | Producer | ---> | Processors | ---> | Formatter |
        +----------+      +------------+      +-----------+

   The control element, an instance of XML::EP::Control, will be created
first. Its purpose is the creation of the other elements, the producer (an
instance of XML::EP::Producer), one or more processors (instances of
XML::EP::Processor) and finally a formatter (an instance of
XML::EP::Formatter).  The producer, processors, formatters are selected
based on virtual host, location (file part of the URL being requested) and
in particular depending on the client. For example, an HTML formatter will
be selected, if the client seems to request HTML, WML formatter will be
created, if the client appears to be WAP HANDY and so on.

METHOD INTERFACE
================

   Public available methods are:

Creating a control element
--------------------------

     my $control = $ep->control();

   (Instance method) This method will create an instance of
XML::EP::Control. The main task of this instance is its *CreatePipe*
method, which will then be called for creating an XML tree, a list of
processors and a formatter.

Getting or setting the processors, formatters
---------------------------------------------

     my $processors = $self->Processors();
     $self->Processors($processors);
     my $formatter = $self->Formatter();
     $self->Formatter($formatter);
     my $request = $self->Request();
     $self->Request($request);
     my $response = $self->Response();
     $self->Response($response);

   (Instance methods) These methods are used for querying or modifying the
list of processors (an array ref) or the formatter. Processors are
explicitly permitted to use this methods.

   The response object is designed for receiving HTTP headers, cookies,
etc. that are being sent to the client. Response objects are instances of
XML::EP::Response.

Handling an HTTP request
------------------------

     $self->Handle($request);

   (Instance method) This method is called with an request object (an
instance of XML::EP::Request) as argument. The request object contains all
information about the client and its request, in particular HTTP headers,
etc.

   The method implements the HTTP requests full life cycle: A control
object is created (an instance of XML::EP::Control), the control objects
*CreatePipe* method is called for creating an XML tree and initializing
the processor list and the formatter, the processors are called and
finally the formatter which has to send data to the client.

Perl SAX parser using nsgmls
****************************

NAME
====

   XML::ESISParser - Perl SAX parser using nsgmls

SYNOPSIS
========

     use XML::ESISParser;

     $parser = XML::ESISParser->new( [OPTIONS] );
     $result = $parser->parse( [OPTIONS] );

     $result = $parser->parse($string);

DESCRIPTION
===========

   `XML::ESISParser' is a Perl SAX parser using the `nsgmls' command of
James Clark's SGML Parser (SP), a validating XML and SGML parser.  This
man page summarizes the specific options, handlers, and properties
supported by `XML::ESISParser'; please refer to the Perl SAX standard in
``SAX.pod'' for general usage information.

   `XML::ESISParser' defaults to parsing XML and has an option for parsing
SGML.

   `nsgmls' source, and binaries for some platforms, is available from
<http://www.jclark.com/>.  `nsgmls' is included in both the SP and Jade
packages.

METHODS
=======

new
     Creates a new parser object.  Default options for parsing, described
     below, are passed as key-value pairs or as a single hash.  Options may
     be changed directly in the parser object unless stated otherwise.
     Options passed to `parse()' override the default options in the
     parser object for the duration of the parse.

OPTIONS
=======

   The following options are supported by `XML::ESISParser':

     Handler          default handler to receive events
     DocumentHandler  handler to receive document events
     DTDHandler       handler to receive DTD events
     ErrorHandler     handler to receive error events
     Source           hash containing the input source for parsing
     IsSGML           the document to be parsed is in SGML

   If no handlers are provided then all events will be silently ignored.

   If a single string argument is passed to the `parse()' method, it is
treated as if a `Source' option was given with a `String' parameter.

   The `Source' hash may contain the following parameters:

     ByteStream       The raw byte stream (file handle) containing the
                      document.
     String           A string containing the document.
     SystemId         The system identifier (URI) of the document.

   If more than one of `ByteStream', `String', or `SystemId', then
preference is given first to `ByteStream', then `String', then `SystemId'.

HANDLERS
========

   The following handlers and properties are supported by
`XML::ESISParser':

DocumentHandler methods
-----------------------

start_document
     Receive notification of the beginning of a document.

     No properties defined.

end_document
     Receive notification of the end of a document.

     No properties defined.

start_element
     Receive notification of the beginning of an element.

          Name             The element type name.
          Attributes       A hash containing the attributes attached to the
                           element, if any.
          IncludedSubelement This element is an included subelement.
          Empty            This element is declared empty.

     The `Attributes' hash contains only string values.  The `Empty' flag
     is not set for an element that merely has no content, it is set only
     if the DTD declares it empty.

     BETA: Attribute values currently do not expand SData entities into
     entity objects, they are still in the system data notation used by
     nsgmls (inside `|').  A future version of XML::ESISParser will also
     convert other types of attributes into their respective objects,
     currently just their notation or entity names are given.

end_element
     Receive notification of the end of an element.

          Name             The element type name.

characters
     Receive notification of character data.

          Data             The characters from the document.

record_end
     Receive notification of a record end sequence.  XML applications
     should convert this to a new-line.

processing_instruction
     Receive notification of a processing instruction.

          Target           The processing instruction target in XML.
          Data             The processing instruction data, if any.

internal_entity_ref
     Receive notification of a system data (SData) internal entity
     reference.

          Name             The name of the internal entity reference.

external_entity_ref
     Receive notification of a external entity reference.

          Name             The name of the external entity reference.

start_subdoc
     Receive notification of the start of a sub document.

          Name             The name of the external entity reference.

end_subdoc
     Receive notification of the end of a sub document.

          Name             The name of the external entity reference.

conforming
     Receive notification that the document just parsed conforms to it's
     document type declaration (DTD).

     No properties defined.

DTDHandler methods
------------------

external_entity_decl
     Receive notification of an external entity declaration.

          Name             The entity's entity name.
          Type             The entity's type (CDATA, NDATA, etc.)
          SystemId         The entity's system identifier.
          PublicId         The entity's public identifier, if any.
          GeneratedId      Generated system identifiers, if any.

internal_entity_decl
     Receive notification of an internal entity declaration.

          Name             The entity's entity name.
          Type             The entity's type (CDATA, NDATA, etc.)
          Value            The entity's character value.

notation_decl
     Receive notification of a notation declaration.

          Name             The notation's name.
          SystemId         The notation's system identifier.
          PublicId         The notation's public identifier, if any.
          GeneratedId      Generated system identifiers, if any.

subdoc_entity_decl
     Receive notification of a subdocument entity declaration.

          Name             The entity's entity name.
          SystemId         The entity's system identifier.
          PublicId         The entity's public identifier, if any.
          GeneratedId      Generated system identifiers, if any.

external_sgml_entity_decl
     Receive notification of an external SGML-entity declaration.

          Name             The entity's entity name.
          SystemId         The entity's system identifier.
          PublicId         The entity's public identifier, if any.
          GeneratedId      Generated system identifiers, if any.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), PerlSAX.pod(3)

     Extensible Markup Language (XML) <http://www.w3c.org/XML/>
     SAX 1.0: The Simple API for XML <http://www.megginson.com/SAX/>
     SGML Parser (SP) <http://www.jclark.com/sp/>

Perl module to handle XML::Edifact messages.
********************************************

NAME
====

   XML::Edifact - Perl module to handle XML::Edifact messages.

SYNOPSIS
========

   use XML::Edifact;

     &XML::Edifact::open_dbm();
     &XML::Edifact::read_edi_message($ARGV[0]);
     print   &XML::Edifact::make_xml_message();
     &XML::Edifact::close_dbm();
     0;

   --------------------------------------------------------------

   use XML::Edifact;

     &XML::Edifact::open_dbm();
     &XML::Edifact::read_xml_message($ARGV[0]);
     print   &XML::Edifact::make_edi_message();
     &XML::Edifact::close_dbm();
     0;

DESCRIPTION
===========

   XML-Edifact started as Onyx-EDI which was a gawk script.
XML::Edifact-0.3x still shows its bad ancestry (a2p) in some places.

   The current module is able to generate some SDBM files for the
directory pointed to by open_dbm, by parsing the original United Nations
EDIFACT documents during Bootstrap.PL. Those files will be stored during
make install.

   The first typical usage will read an EDIFACT message into a buffer
global to the package, and will print this message as XML on STDOUT. The
second usage will do the opposite.

   Those two files will be installed as edi2xml and xml2edi in your local
bin directory.

   New to XML::Edifact 0.34 are namespace migration and intend handling -
take a look at the test.pl for how to use them.  BUT WAIT - An
object-oriented syntax is planned for the next release! And I'm calling
this release an interim, because I'm just saving a stable state (I hope)
before I start to muddle all things around while going on an object(ive)
raid.

   If you have other EDIFACT files, I would like to include them in the
next version. I'm also open to any comments; as they say, "everything is
still in flux" !

AUTHOR
======

   Michael Koehne, Kraehe@Copyleft.de

SEE ALSO
========

   perl(1), XML::Parser(3), UN/EDIFACT Draft.

XML elements with the same interface as HTML::Element
*****************************************************

NAME
====

   XML::Element - XML elements with the same interface as HTML::Element

SYNOPSIS
========

     [See HTML::Element]

DESCRIPTION
===========

   This is just a subclass of HTML::Element.  It works basically the same
as HTML::Element, except that tagnames and attribute names aren't forced
to lowercase, as they are in HTML::Element.

   See HTML/Element, describes everything you can do with
this class.

CAVEATS
=======

   Has currently no handling of namespaces.

SEE ALSO
========

   See XML/TreeBuilder, for a class that actually
builds XML::Element structures.

   See HTML/Element, for all documentation.

   See XML/DOM, and XML/Twig, for other XML
document tree interfaces.

   See XML/Generator, for more fun.

COPYRIGHT
=========

   Copyright 2000 Sean M. Burke.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

AUTHOR
======

   Sean M. Burke, <sburke@cpan.org>

A perl module for parsing XML encoding maps.
********************************************

NAME
====

   XML::Encoding - A perl module for parsing XML encoding maps.

SYNOPSIS
========

     use XML::Encoding;
     my $em_parser = new XML::Encoding(ErrorContext  => 2,
                                       ExpatRequired => 1,
                                       PushPrefixFcn => \&push_prefix,
                                       PopPrefixFcn  => \&pop_prefix,
                                       RangeSetFcn   => \&range_set);

     my $encmap_name = $em_parser->parsefile($ARGV[0]);

DESCRIPTION
===========

   This module, which is built as a subclass of XML::Parser, provides a
parser for encoding map files, which are XML files. The file
maps/encmap.dtd in the distribution describes the structure of these
files. Calling a parse method returns the name of the encoding map
(obtained from the name attribute of the root element). The contents of
the map are processed through the callback functions push_prefix,
pop_prefix, and range_set.

METHODS
=======

   This module provides no additional methods to those provided by
XML::Parser, but it does take the following additional options.

   * ExpatRequired

     When this has a true value, then an error occurs unless the encmap
     "expat" attribute is set to "yes". Whether or not the ExpatRequired
     option is given, the parser enters expat mode if this attribute is
     set. In expat mode, the parser checks if the encoding violates expat
     restrictions.

   * PushPrefixFcn

     The corresponding value should be a code reference to be called when
     a prefix element starts. The single argument to the callback is an
     integer which is the byte value of the prefix. An undef value should
     be returned if successful. If in expat mode, a defined value causes
     an error and is used as the message string.

   * PopPrefixFcn

     The corresponding value should be a code reference to be called when a
     prefix element ends. No arguments are passed to this function. An
     undef value should be returned if successful. If in expat mode, a
     defined value causes an error and is used as the message string.

   * RangeSetFcn

     The corresponding value should be a code reference to be called when a
     "range" or "ch" element is seen. The 3 arguments passed to this
     function are: (byte, unicode_scalar, length) The byte is the starting
     byte of a range or the byte being mapped by a "ch" element. The
     unicode_scalar is the Unicode value that this byte (with the current
     prefix) maps to. The length of the range is the last argument.  This
     will be 1 for the "ch" element. An undef value should be returned if
     successful. If in expat mode, a defined value causes an error and is
     used as the message string.

AUTHOR
======

   Clark Cooper <`coopercc@netheaven.com'>

SEE ALSO
========

   XML::Parser

A PerlSAX filter that detects ignorable whitespace
**************************************************

NAME
====

   XML::Filter::DetectWS - A PerlSAX filter that detects ignorable
whitespace

SYNOPSIS
========

     use XML::Filter::DetectWS;

     my $detect = new XML::Filter::DetectWS (Handler => $handler,
     					 SkipIgnorableWS => 1);

DESCRIPTION
===========

   This a PerlSAX filter that detects which character data contains
ignorable whitespace and optionally filters it.

   Note that this is just a first stab at the implementation and it may
change completely in the near future. Please provide feedback whether you
like it or not, so I know whether I should change it.

   The XML spec defines ignorable whitespace as the character data found
in elements that were defined in an <!ELEMENT> declaration with a model of
'EMPTY' or 'Children' (Children is the rule that does not contain
'#PCDATA'.)

   In addition, XML::Filter::DetectWS allows the user to define other
whitespace to be *ignorable*. The ignorable whitespace is passed to the
PerlSAX Handler with the ignorable_whitespace handler, provided that the
Handler implements this method. (Otherwise it is passed to the characters
handler.)  If the *SkipIgnorableWS* is set, the ignorable whitespace is
simply discarded.

   XML::Filter::DetectWS also takes xml:space attributes into account. See
below for details.

   CDATA sections are passed in the standard PerlSAX way (i.e. with
surrounding start_cdata and end_cdata events), unless the Handler does not
implement these methods. In that case, the CDATA section is simply passed
to the characters method.

Constructor Options
===================

   * SkipIgnorableWS (Default: 0)

     When set, detected ignorable whitespace is discarded.

   * Handler

     The PerlSAX handler (or filter) that will receive the PerlSAX events
     from this filter.

Current Implementation
======================

   When determining which whitespace is ignorable, it first looks at the
xml:space attribute of the parent element node (and its ancestors.)  If
the attribute value is "preserve", then it is *NOT* ignorable.  (If
someone took the trouble of adding xml:space="preserve", then that is the
final answer...)

   If xml:space="default", then we look at the <!ELEMENT> definition of
the parent element. If the model is 'EMPTY' or follows the 'Children' rule
(i.e. does not contain '#PCDATA') then we know that the whitespace is
ignorable.  Otherwise we need input from the user somehow.

   The idea is that the API of DetectWS will be extended, so that you can
specify/override e.g. which elements should behave as if
xml:space="preserve" were set, and/or which elements should behave as if
the <!ELEMENT> model was defined a certain way, etc.

   Please send feedback!

   The current implementation also detects whitespace after an
element-start tag, whitespace before an element-end tag.  It also detects
whitespace before an element-start and after an element-end tag and before
or after comments, processing instruction, cdata sections etc., but this
needs to be reimplemented.  In either case, the detected whitespace is
split off into its own PerlSAX characters event and an extra property
'Loc' is added. It can have 4 possible values:

   * 1 (WS_START) - whitespace immediately after element-start tag

   * 2 (WS_END) - whitespace just before element-end tag

   * 3 (WS_ONLY) - both WS_START and WS_END, i.e. it's the only text found
     between the start and end tag and it's all whitespace

   * 0 (WS_INTER) - none of the above, probably before an element-start
     tag, after an element-end tag, or before or after a comment, PI,
     cdata section etc.

   Note that WS_INTER may not be that useful, so this may change.

xml:space attribute
===================

   The XML spec states that: A special attribute named xml:space may be
attached to an element to signal an intention that in that element, white
space should be preserved by applications.  In valid documents, this
attribute, like any other, must be declared if it is used.  When declared,
it must be given as an enumerated type whose only possible values are
"default" and "preserve".  For example:

     <!ATTLIST poem   xml:space (default|preserve) 'preserve'>

   The value "default" signals that applications' default white-space
processing modes are acceptable for this element; the value "preserve"
indicates the intent that applications preserve all the white space.  This
declared intent is considered to apply to all elements within the content
of the element where it is specified, unless overriden with another
instance of the xml:space attribute.

   The root element of any document is considered to have signaled no
intentions as regards application space handling, unless it provides a
value for this attribute or the attribute is declared with a default value.

   [... end of excerpt ...]

CAVEATS
=======

   This code is highly experimental!  It has not been tested well and the
API may change.

   The code that detects of blocks of whitespace at potential indent
positions may need some work. See

AUTHOR
======

   Send bug reports, hints, tips, suggestions to Enno Derksen at
<`enno@att.com'>.

XML::Filter::Digest
*******************

NAME
====

   XML::Filter::Digest

SYNOPSIS
========

     use strict;
     use XML::Filter::Digest;
     use XML::Handler::YAWriter;
     use IO::File;

     my $digest = new XML::Filter::Digest(
     	'Handler'=>
     	    new XML::Handler::YAWriter(
     	    'Output' => new IO::File( ">-" ),
     	    'Pretty' => {
     		'AddHiddenNewLine' => 1
     		}
     	    ),

     'Script' =>
         new XML::Script::Digest(
         'Source' => { 'SystemId' => $ARGV[0] }
         )->parse(),

     'Source' => { 'SystemId' => $ARGV[1] }
     )->parse();

     0;

DESCRIPTION
===========

   Most XML tools aim to parse some simple XML and to produce some
formatted output. *XML::Filter::Digest* aims to do the opposite.

   Many formats can now be parsed by a SAX Driver. XPath offers a smart
way to write queries to XML. XML::Filter::Digest is a PerlSAX Filter to
query XML and to provide a simpler digest as a result.

   XML::Filter::Digest uses its own script language that can be parsed by
*XML::Script::Digest* to formulate these digest queries.

   In fact, a digest script is well-formed XML.

   The following script defines that the result XML should have a root
element called extract, containing several elements called section
starting from the 4th HTML header. Those section elements contain id,
title and *intro* elements, which in turn contain the XPath *string-value*
of their nodes as character data.

     <digest name="extract">
     <collect
         name="section"
         node="//html//h2[position()&gt;3]"
         >
         <collect
             name="id"
         node="child::a/attribute::name"
         />
         <collect
             name="title"
         node="."
         />
         <collect
             name="intro"
         node="following-sibling::p[position()=1]"
         />
     </collect>
     </digest>

   The digest script parser silently ignores anything other than digest
elements and collect elements. The digest element needs a name attribute
defining the name of the root element, while the collect element needs an
additional node attribute defining XPath queries for nested elements.

   Only a single digest element should exist within a script document, but
there is no need that the digest script be the root element of the
document. Nested within the digest element should be collect elements.
They may contain several other collect elements recursivly.

METHODS
-------

   The XML::Filter::Digest object may act as a Filter to receive SAX
events, or directly as a Driver if you provide a Source option to the parse
method. The filter is reusable, if you arrange that the chain of Handlers
is also reusable to handle multiple documents in batches. The filter
requires a Handler and a Script option before the start_document method is
called.

   The XML::Script::Digest object may act as a Handler to receive SAX
events, or directly if you provide a Source option to the parse method.
The script object is reusable and a single script object can be used for
several filter objects.

new
     Creates a new XML::Driver::HTML object. Default options for parsing,
     described below, are passed as key-value pairs or as a single hash.
     Options may be changed directly in the object.

parse
     Parses a document by embedding XML::Parser::PerlSAX. This allows you
     to use XML::Filter::Digest directly as a Driver and simplifies
     generating a ready-to-use XML::Script::Object.

     Options, described below, are passed as key-value pairs or as a
     single hash.  Options passed to parse() override the default options
     in the object for the duration of the parse.

start_document
     Notifies the object about the start of a new document. The object will
     do its cleanup if it's reused.

end_document
     Notifies the object about the end of the document.  Return value of
     XML::Script::Digest is *$self*, to be used as the return value of the
     parse method.

     XML::Filter::Digest will walk through the script object to generate a
     stream of SAX events for its Handler. Return value of
     XML::Filter::Digest is the return value of the end_document method of
     the Handler object.

OPTIONS
-------

Script
     XML::Script::Digest objects can be used for several
     XML::Filter::Digest objects.

Handler
     Default SAX Handler to receive events from XML::Filter::Digest
     objects.

Source
     XML::Filter::Digest and XML::Script can be used on raw XML directly,
     by calling the parse() method. To do this, the Source option is
     required for embedding the PerlSAX parser.

     The `Source' hash may contain the following parameters:

    ByteStream
          The raw byte stream (file handle) containing the document.

    String
          A string containing the document.

    SystemId
          The system identifier (URI) of the document.

    Encoding
          A string describing the character encoding.

     If more than one of `ByteStream', `String', or `SystemId' are
     present, preference is given first to `ByteStream', then `String',
     then `SystemId'.

NOTES
=====

   The XML::Filter::Digest is not a streaming filter, but a buffering
filter, as any processing is done by the end_document method. This could
cause the Perl interpreter to run out of memory on large XML files.
Ideally, define a *ulimit*, to prevent the system going offline for
several minutes, till it detects that there is really no memory to seize
somewhere in the network. Adding network swapspace ad infinitum only make
things worse, so I have the following line in my *.bashrc*. Other
operating systems offer similar constraints.

     ulimit -v 98304 -d 98304 -m 98304

   This line is ok on a single user machine with 32M ram and 128MB swap. I
can raise this value, if I know that I wanna walk the dog.

BUGS
====

   not yet implemented:

     reuse of XML::Filter::Digest objects.

   XML::XPath::Builder bug:

     XML::Filter::Digest 0.02 has been tested with XML::XPath
     version 0.51, but XML::XPath needs the patch included within
     this distribution.

     Version 0.52 is expected to work out of the box.

   other bugs:

     The NotSoFree License is incompatible with the
     GNU General Public License.

AUTHOR
======

     Michael Koehne, Kraehe@Copyleft.De
     (c) 2000 NotSoFree License

SEE ALSO
========

   See XML/Parser/PerlSAX, and XML/XPath,

a SAX stream editor
*******************

NAME
====

   XML::Filter::Hekeln - a SAX stream editor

SYNOPSIS
========

     use XML::Filter::Hekeln;

     my $hander = new SAXHandler( ... );
     my $hekeln = new XML::Filter::Hekeln(
     	'Handler' => $handler,
     	'Script'  => $script
     	);
     my $driver = new SAXDriver( ..., 'Handler' => $hekeln );

DESCRIPTION
===========

   XML::Filter::Hekeln is a sophisticated SAX stream editor.

   Hekeln is a SAX filter. This means that you can use a Hekeln object as
a Handler to act on events, and to produce SAX events as a driver for the
next handler in the chain. The name Hekeln sounds like the german word for
crocheting, whats the best to describe, what Hekeln can do on markup
language translation.

   The main design goal was to make it as easy for Perl as possible, while
preserving a human readable form for the translation script.

   Hekeln scripts are event based. Hekeln objects stream events to the
next in chain. They are therefore useable to handle XML documents larger
than physical memory, as they do not need to store the entire document in
a DOM or Grove structure. They will also be faster than any XSL in most
circumstances.

   To tell you straight, how Hekeln works, I'll start with an example.

   I want to translate XML::Edifact repositories into html. Those
repositories start with something like this:

     <repository
     	agency="UN/ECE/TRADE/WP.4"
     	code="sdsd"
     	desc="based on UN/EDIFACT D422.TXT"
     	name="Service Segment Directory"
     	version="99A"
     	>

   Here is a sniplet from test.pl :

     start_element:repository
     !	$self->handle('start_document',{});
     <	html	>
     <	body	>
     <	h1	>
     	XML-Edifact Repository
     </	h1	>
     <	h2	>
     	~name~
     </	h2	>
     <	p	>
     	Agency: ~agency~
     <	br	>
     	Code: ~code~
     <	br	>
     	Version: ~version~
     <	br	>
     	Description: ~desc~
     </	p	>
     <	hr	>

     end_element:repository
     </	body	>
     </	html	>
     !	$self->handle('end_document',{});

   This part is handling start_element and end_element events, that have a
target called repository. The translation done by Hekeln is done into
subroutines that are stored in a hash.

   So anything is possible, if you understand the trick. To understand the
trick, uncomment the "'Debug' => 1" parameter of Hekeln invocation in the
test.pl script and redirect STDERR to some file.

   This will produce a file starting like :

     $hash->{start_element:repository}=eval "sub {
     	my ($self,$param) = @_;
     	my ($hash) = {};
     	$self->handle('start_document',{});
     	$hash->{Name}="html"; $self->handle("start_element", $hash);
     	$hash->{Name}="body"; $self->handle("start_element", $hash);
     	$hash->{Name}="h1"; $self->handle("start_element", $hash);
     	$hash->{Data}="XML-Edifact Repository"; $self->handle("characters", $hash);
     	$hash->{Name}="h1"; $self->handle("end_element", $hash);
     	$hash->{Name}="h2"; $self->handle("start_element", $hash);
     	$hash->{Data}="$param->{name}"; $self->handle("characters", $hash);
     	$hash->{Name}="h2"; $self->handle("end_element", $hash);
     	$hash->{Name}="p"; $self->handle("start_element", $hash);
     	$hash->{Data}="Agency: $param->{agency}"; $self->handle("characters", $hash);
     	$hash->{Name}="br"; $self->handle("start_element", $hash);
     	$hash->{Data}="Code: $param->{code}"; $self->handle("characters", $hash);
     	$hash->{Name}="br"; $self->handle("start_element", $hash);
     	$hash->{Data}="Version: $param->{version}"; $self->handle("characters", $hash);
     	$hash->{Name}="br"; $self->handle("start_element", $hash);
     	$hash->{Data}="Description: $param->{desc}"; $self->handle("characters", $hash);
     	$hash->{Name}="p"; $self->handle("end_element", $hash);
     	$hash->{Name}="hr"; $self->handle("start_element", $hash);
     	}";

     $hash->{end_element:repository}=eval "sub {
     	my ($self,$param) = @_;
     	my ($hash) = {};
     	$hash->{Name}="body"; $self->handle("end_element", $hash);
     	$hash->{Name}="html"; $self->handle("end_element", $hash);
     	$self->handle('end_document',{});
     	}";

   As you can imagine ~foobaa~ parts within a script will become expanded
with the the attributes given in the XML start_element event. Syntax
itself is a bit tricky as translation of the script into a sub is stupid
and fast.

   Any event that has to be handled by Hekeln starts with an event_name
event_target pair and ends with a blank line.

     event_name<DOUBLE_COLON>event_target<NL>
     left_indicator<TAB>text<TAB>right_indicator<NL>
     left_indicator<TAB>text<TAB>right_indicator<NL>
     left_indicator<TAB>text<TAB>right_indicator<NL>
     <NL>

   Valid as left_indicator are "<", "</", "", "!", "+", "-", "++, "-",
"?{" and "?}", while the right indicator may be optional execpt for "<".

   The first produce start_element, end_element and character events, to
make Hekeln scripts look similar to the markup you want to produce.

   The "!" indicator is something special as it will be copied into the
sub as it is, to be evaluted in the complete context of a script. So its
possible to code conditionals or even loops with a constructions like
those :

     !	$self->{Flag}{FooBaa}=1;
     !	unshift $self->{Stack}, "FooBaa";

   and

     !	$self->{Flag}{FooBaa}=undef;
     !	shift $self->{Stack} if $self->{Stack}[0] eq "FooBaa";

   and

     !	if ($self->{Flag}{FooBaa}) {
     <	h1	>
     	flag FooBaa raised
     </	h1	>
     !	}

   It wont be necessary to code exactly this, as this is done by "++", "-",
"?{" and "?}". "+" and "-" will raise or lower some flag, while "++" and
"-" not only manage the flags, but also a stack that is needed to process
character events.

   The default behavior is to throw away any event that does not have a
subroutine matching the event, target pair. Events that do not have a
target, will use the top flag on the stack as a target. So if you want to
process character events, use "++" and "-" when handling the surounding
start_element and end_element events.

   As a last word: Hekeln is not yet well tested, and badly needs some
better documentation. I would aplaude anybody for naming bug, or improving
the POD.

AUTHOR
======

   Michael Koehne, Kraehe@Copyleft.de

SEE ALSO
========

   perl(1), XML::Parser, XML::Parser::PerlSAX

Reformats whitespace for pretty printing XML
********************************************

NAME
====

   XML::Filter::Reindent - Reformats whitespace for pretty printing XML

SYNOPSIS
========

     use XML::Handler::Composer;
     use XML::Filter::Reindent;

     my $composer = new XML::Handler::Composer (%OPTIONS);
     my $indent = new XML::Filter::Reindent (Handler => $composer, %OPTIONS);

DESCRIPTION
===========

   XML::Filter::Reindent is a sub class of XML/Filter/DetectWS.

   XML::Filter::Reindent can be used as a PerlSAX filter to reformat an
XML document before sending it to a PerlSAX handler that prints it (like
XML/Handler/Composer.)

   Like XML/Filter/DetectWS, it detects
ignorable whitespace and blocks of whitespace characters in certain
places. It uses this information and information supplied by the user to
determine where whitespace may be modified, deleted or inserted.  Based on
the indent settings, it then modifies, inserts and deletes characters and
ignorable_whitespace events accordingly.

   This is just a first stab at the implementation.  It may be buggy and
may change completely!

Constructor Options
===================

   * Handler

     The PerlSAX handler (or filter) that will receive the PerlSAX events
     from this filter.

   * Tab (Default: one space)

     The number of spaces per indent level for elements etc. in document
     content.

   * Newline (Default: "\x0A")

     The newline to use when re-indenting.  The default is the internal
     newline used by XML/Parser, XML/DOM,
     etc., and should be fine when used in combination with
     XML/Handler/Composer.

$self->indent_children ($start_element_event)
=============================================

   This method determines whether children of a certain element may be
reformatted.  The default implementation checks the PreserveWS parameter
of the specified start_element event and returns 0 if it is set or MAYBE
otherwise.  The value MAYBE (2) indicates that further investigation is
needed, e.g.  by examining the element contents. A value of 1 means yes,
indent the child nodes, no further investigation is needed.

   NOTE: the PreserveWS parameter is set by the parent class, see
XML/Filter/DetectWS, when the element or one of its
ancestors has the attribute xml:space="preserve".

   Override this method to tweak the behavior of this class.

$self->indent_element ($start_element_event, $parent_says_indent)
=================================================================

   This method determines whether a certain element may be re-indented.
The default implementation returns the value of the $parent_says_indent
parameter, which was set to the value returned by indent_children for the
parent element. In other words, the element will be re-indented if the
parent element allows it.

   Override this method to tweak the behavior of this class.  I'm not sure
how useful this hook is. Please provide feedback!

Current Implementation
======================

   The current implementation puts all incoming Perl SAX events in a queue
for further processing. When determining which nodes should be re-indented,
it sometimes needs information from previous events, hence the use of the
queue.

   The parameter (Compress => 1) is added to matching start_element and
end_element events with no events in between This indicates to an XML
printer that a compressed notation can be used, e.g <foo/>.

   If an element allows reformatting of its contents (xml:space="preserve"
was not active and indent_children returned MAYBE), the element contents
will be reformatted unless it only has one child node and that child is a
regular text node (characters event.)  In that case, the element will be
printed as <foo>text contents</foo>.

   If you want element nodes with just one text child to be reindented as
well, simply override indent_children to return 1 instead of MAYBE (2.)

   This behavior may be changed or extended in the future.

CAVEATS
=======

   This code is highly experimental!  It has not been tested well and the
API may change.

   The code that detects blocks of whitespace at potential indent positions
may need some work.

AUTHOR
======

   Send bug reports, hints, tips, suggestions to Enno Derksen at
<`enno@att.com'>.

Replicates SAX events to several SAX event handlers
***************************************************

NAME
====

   XML::Filter::SAXT - Replicates SAX events to several SAX event handlers

SYNOPSIS
========

     $saxt = new XML::Filter::SAXT ( { Handler => $out1 },
     				 { DocumentHandler => $out2 },
     				 { DTDHandler => $out3,
     				   Handler => $out4
     				 }
     			       );

     $perlsax = new XML::Parser::PerlSAX ( Handler => $saxt );
     $perlsax->parse ( [OPTIONS] );

DESCRIPTION
===========

   SAXT is like the Unix 'tee' command in that it multiplexes the input
stream to several output streams. In this case, the input stream is a
PerlSAX event producer (like XML::Parser::PerlSAX) and the output streams
are PerlSAX handlers or filters.

   The SAXT constructor takes a list of hash references. Each hash
specifies an output handler. The hash keys can be: DocumentHandler,
DTDHandler, EntityResolver or Handler, where Handler is a combination of
the previous three and acts as the default handler.  E.g. if
DocumentHandler is not specified, it will try to use Handler.

EXAMPLE
-------

   In this example we use XML/Parser/PerlSAX, to
parse an XML file and to invoke the PerlSAX callbacks of our SAXT object.
The SAXT object then forwards the callbacks to XML/Checker,
which will 'die' if it encounters an error, and to
`XML::Hqandler::BuildDOM' in this node, which will store the XML in an
XML/DOM/Document.

     use XML::Parser::PerlSAX;
     use XML::Filter::SAXT;
     use XML::Handler::BuildDOM;
     use XML::Checker;

     my $checker = new XML::Checker;
     my $builder = new XML::Handler::BuildDOM (KeepCDATA => 1);
     my $tee = new XML::Filter::SAXT ( { Handler => $checker },
     				   { Handler => $builder } );

     my $parser = new XML::Parser::PerlSAX (Handler => $tee);
     eval
     {
        # This is how you set the error handler for XML::Checker
        local $XML::Checker::FAIL = \&my_fail;

     my $dom_document = $parser->parsefile ("file.xml");
     ... your code here ...
      };
      if ($@)
      {
     # Either XML::Parser::PerlSAX threw an exception (bad XML)
     # or XML::Checker found an error and my_fail died.
     ... your error handling code here ...
      }

     # XML::Checker error handler
     sub my_fail
     {
       my $code = shift;
       die XML::Checker::error_string ($code, @_)
     	if $code < 200;	  # warnings and info messages are >= 200
     }

CAVEATS
=======

   This is still alpha software.  Package names and interfaces are subject
to change.

AUTHOR
======

   Send bug reports, hints, tips, suggestions to Enno Derksen at
<`enno@att.com'>.

Perl extension for generating XML
*********************************

NAME
====

   XML::Generator - Perl extension for generating XML

SYNOPSIS
========

     use XML::Generator;

     my $xml = XML::Generator->new(escape => 'always',
                                   pretty => 2,
                                   conformance => 'strict');

     print $xml->foo($xml->bar({ baz => 3 }, $xml->bam),
     		   $xml->bar([ 'qux' ], "Hey there, world"));

     # The above would yield:
     <foo>
       <bar baz="3">
         <bam />
       </bar>
       <qux:bar>Hey there, world</qux:bar>
     </foo>

DESCRIPTION
===========

   In general, once you have an XML::Generator object, you then simply call
methods on that object named for each XML tag you wish to generate.  Say
you want to generate this XML:

     <person>
       <name>Bob</name>
       <age>34</age>
       <job>Accountant</job>
     </person>

   Here's a snippet of code that does the job, complete with pretty
printing:

     use XML::Generator;
     my $gen = XML::Generator->new(escape => 'always', pretty => 2);
     print $gen->person(
              $gen->name("Bob"),
              $gen->age(34),
              $gen->job("Accountant")
           );

   The only problem with this is if you want to use a tag name that Perl's
lexer won't understand as a method name, such as "shoe-size".  Fortunately,
since you can always call methods as variable names, there's a simple
work-around:

     my $shoe_size = "shoe-size";
     $xml = $gen->$shoe_size("12 1/2");

   Which correctly generates:

     <shoe-size>12 1/2</shoe-size>

   You can use a hash ref as the first parameter if the tag should include
atributes.  An array ref can be supplied as the first argument to indicate
a namespace for the element and the attributes (the elements of the array
are concatenated with ':').  Under strict conformance, however, you are
only allowed one namespace component.

   If you want to specify a namespace as well as attributes, you can make
the second argument a hash ref.  If you do it the other way around, the
array ref will simply get stringified and included as part of the content
of the tag.  If an XML::Generator object has a namespace set, and a
namespace is also supplied to the tag, the supplied namespace overrides
the default.

   Here's an example to show how the attribute and namespace parameters
work:

     $xml = $gen->account({ type => 'checking', id => '34758'},
     	    $gen->open(['transaction'], 2000),
     	    $gen->deposit(['transaction'], { date => '1999.04.03'}, 1500)
            );

   This generates:

     <account type="checking" id="34578">
       <transaction:open>2000</transaction:open>
       <transaction:deposit transaction:date="1999.04.03">1500</transaction:deposit>
     </account>

CONSTRUCTOR
===========

   XML::Generator->new(option => 'value', option => 'value');

   The following options are available:

namespace
---------

   The value of this option is used as the global default namespace.  For
example,

     my $html = XML::Generator->new(namespace => 'HTML');
     print $html->font({ face => 'Arial' }, "Hello, there");

   would yield

     <HTML:font HTML:face="Arial">Hello, there</HTML:font>

   See HTML::Generator for routines specific to HTML generation.

escape
------

   The contents and the values of each attribute have any illegal XML
characters escaped if this option is supplied.  If the value is 'always',
then &, < and > (and " within attribute values) will be converted into the
corresponding XML entity.  If the value is any other true value, then the
escaping will be turned off character-by-character if the character in
question is preceded by a backslash, or for the entire string if it is
supplied as a scalar reference.  So, for example,

     my $a = XML::Generator->new(escape => 'always');
     my $b = XML::Generator->new(escape => 'true');
     print $a->foo('<', $b->bar('3 \> 4', \" && 6 < 5"), '\&', '>');

   would yield

     <foo>&lt;<bar>3 > 4 && 6 < 5</bar>\&amp;&gt;</foo>

pretty
------

   To have nice pretty printing of the output XML (great for config files
that you might also want to edit by hand), pass an integer for the number
of spaces per level of indenting, eg.

     my $gen = XML::Generator->new(pretty => 2);
     print $gen->foo($gen->bar('baz'),
                     $gen->qux({ tricky => 'no'}, 'quux'));

   would yield

     <foo>
       <bar>baz</bar>
       <qux tricky="no">quux</qux>
     </foo>

   Pretty printing does not apply to CDATA sections or Processing
Instructions.

conformance
-----------

   If the value of this option is 'strict', a number of syntactic checks
are performed to ensure that generated XML conforms to the formal XML
specification.  In addition, since entity names beginning with 'xml' are
reserved by the W3C, inclusion of this option enables several special tag
names: xmlpi, xmlcmnt, xmldecl, xmldtd, xmlcdata, and xml to allow
generation of processing instructions, comments, XML declarations, DTD's,
character data sections and "final" XML documents, respectively.

   See `"XML CONFORMANCE"' in this node and `"SPECIAL TAGS"' in this node
for more information.

empty
-----

   There are 5 possible values for this option:

     self    -  create empty tags as <tag />  (default)
     compact -  create empty tags as <tag/>
     close   -  close empty tags as <tag></tag>
     ignore  -  don't do anything (non-compliant!)
     args    -  use count of arguments to decide between <x /> and <x></x>

   Many web browsers like the 'self' form, but any one of the forms besides
'ignore' is acceptable under the XML standard.

   'ignore' is intended for subclasses that deal with HTML and other SGML
subsets which allow atomic tags.  It is an error to specify both
'conformance' => 'strict' and 'empty' => 'ignore'.

   'args' will produce <x /> if there are no arguments at all, or if there
is just a single undef argument, and <x></x> otherwise.

XML CONFORMANCE
===============

   When the 'conformance' => 'strict' option is supplied, a number of
syntactic checks are enabled.  All entity and attribute names are checked
to conform to the XML specification, which states that they must begin
with either an alphabetic character or an underscore and may then consist
of any number of alphanumerics, underscores, periods or hyphens.
Alphabetic and alphanumeric are interpreted according to the current
locale if 'use locale' is in effect and according to the Unicode standard
for Perl versions >= 5.6.  Furthermore, entity or attribute names are not
allowed to begin with 'xml' (in any case), although a number of special
tags beginning with 'xml' are allowed (see `"SPECIAL TAGS"' in this node).

   In addition, only one namespace component will be allowed when strict
conformance is in effect, and attribute names can be given a specific
namespace, which will override both the default namespace and the tag-
specific namespace.  For example,

     my $gen = XML::Generator->new(conformance => 'strict',
     				 namespace   => 'foo');
     my $xml = $gen->bar({ a => 1 },
                 $gen->baz(['bam'], { b => 2, 'name:c' => 3 })
                );

   will generate:

     <foo:bar foo:a="1"><bam:baz bam:b="2" name:c="3" /></foo:bar>

SPECIAL TAGS
============

   The following special tags are available when running under strict
conformance (otherwise they don't act special):

xmlpi
-----

   Processing instruction; first argument is target, remaining arguments
are attribute, value pairs.  Attribute names are syntax checked, values
are escaped.

xmlcmnt
-------

   Comment.  Arguments are concatenated and placed inside <!- ... ->
comment delimiters.  Any occurences of '-' in the concatenated arguments
are converted to '-&#45;'

xmldecl
-------

   Declaration.  This can be used to specify the version, encoding, and
other XML-related declarations (i.e., anything inside the <?xml?> tag).

xmldtd
------

   DTD <!DOCTYPE> tag creation. The format of this method is different from
others. Since DTD's are global and cannot contain namespace information,
the first argument arrayref is concatenated together to form the DTD:

     print $xml->xmldtd([ 'html', 'PUBLIC', $xhtml_w3c, $xhtml_dtd ])

   This would produce the following declaration:

     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
          "DTD/xhtml1-transitional.dtd">

   Assuming that $xhtml_w3c and $xhtml_dtd had the correct values. For
shortcuts to <!DOCTYPE> generation, see the HTML::Generator module.  Note
that you can also specify a DTD on creation using the new() method's dtd
option.

xmlcdata
--------

   Character data section; arguments are concatenated and placed inside
<![CDATA[ ... ]]> character data section delimiters.  Any occurences of
']]>' in the concatenated arguments are converted to ']]&gt;'.

xml
---

   "Final" XML document.  Must be called with one and exactly one
XML::Generator-produced XML document.  Any combination of
XML::Generator-produced XML comments or processing instructions may also
be supplied as arguments.  Prepends an XML declaration, and re-blesses the
argument into a "final" class that can't be embedded.

CREATING A SUBCLASS
===================

   For an example of how to subclass XML::Generator, see Nathan Wiger's
HTML::Generator module.

   At times, you may find it desireable to subclass XML::Generator. For
example, you might want to provide a more application-specific interface
to the XML generation routines provided. Perhaps you have a custom
database application and would really like to say:

     my $dbxml = new XML::Generator::MyDatabaseApp;
     print $dbxml->xml($dbxml->custom_tag_handler(@data));

   Here, custom_tag_handler() may be a method that builds a recursive XML
structure based on the contents of @data. In fact, it may even be named
for a tag you want generated, such as authors(), whose behavior changes
based on the contents (perhaps creating recursive definitions in the case
of multiple elements).

   Creating a subclass of XML::Generator is actually relatively
straightforward, there are just three things you have to remember:

     1. All of the useful utilities are in XML::Generator::util.

     2. To construct a tag you simply have to call SUPER::tagname,
        where "tagname" is the name of your tag.

     3. You must fully-qualify the methods in XML::Generator::util.

   So, let's assume that we want to provide a custom HTML table() method:

     package XML::Generator::CustomHTML;
     use base 'XML::Generator';

     sub table {
         my $self = shift;

         # parse our args to get namespace and attribute info
         my($namespace, $attr, @content) =
            $self->XML::Generator::util::parse_args(@_)

     # check for strict conformance
     if ( $self->XML::Generator::util::config('conformance') eq 'strict' ) {
        # ... special checks ...
     }

     # ... special formatting magic happens ...

     # construct our custom tags
     return $self->SUPER::table($attr, $self->tr($self->td(@content)));
        }

   That's pretty much all there is to it. We have to explicitly call
SUPER::table() since we're inside the class's table() method. The others
can simply be called directly, assuming that we don't have a tr() in the
current package.

   If you want to explicitly create a specific tag by name, or just want a
faster approach than AUTOLOAD provides, you can use the tag() method
directly. So, we could replace that last line above with:

     # construct our custom tags
     return $self->XML::Generator::util::tag('table', $attr, ...);

   Here, we must explicitly call tag() with the tag name itself as its
first argument so it knows what to generate. These are the methods that
you might find useful:

XML::Generator::util::parse_args()
     This parses the argument list and returns the namespace (arrayref),
     attributes (hashref), and remaining content (array), in that order.

XML::Generator::util::tag()
     This does the work of generating the appropriate tag. The first
     argument must be the name of the tag to generate.

XML::Generator::util::config()
     This retrieves options as set via the new() method.

XML::Generator::util::escape()
     This escapes any illegal XML characters.

   Remember that all of these methods must be fully-qualified with the
XML::Generator::util package name. This is because AUTOLOAD is used by the
main XML::Generator package to create tags. Simply calling parse_args()
will result in a set of XML tags called <parse_args>.

   Finally, remember that since you are subclassing XML::Generator, you do
not need to provide your own new() method. The one from XML::Generator is
designed to allow you to properly subclass it.

AUTHORS
=======

Benjamin Holzman <bholzman@earthlink.net>
     Original author and maintainer

Bron Gondwana <perlcode@brong.net>
     First modular version

Nathan Wiger <nate@nateware.com>
     Modular rewrite to enable subclassing

SEE ALSO
========

Perl-XML FAQ
     http://www.perlxml.com/faq/perl-xml-faq.html

The XML::Writer module
     http://search.cpan.org/search?mode=module&query=XML::Writer

The XML::Handler::YAWriter module
     http://search.cpan.org/search?mode=module&query=XML::Handler::YAWriter

The HTML::Generator module
     http://search.cpan.org/search?mode=module&query=HTML::Generator

XML::Generator subclass for producing DOM trees instead of strings.
*******************************************************************

NAME XML::Generator::DOM
========================

   XML::Generator subclass for producing DOM trees instead of strings.

SYNOPSIS
========

     use XML::Generator::DOM;

     my $dg  = XML::Generator::DOM->new();
     my $doc = $dg->xml($dg->xmlcmnt("Test document."),
     		   $dg->foo({'baz' => 'bam'}, 42));
     print $doc->toString;

   yields:

     <?xml version="1.0" standalone="yes"?>
     <!--Test document-->
     <foo baz="bam">42</foo>

DESCRIPTION
===========

   XML::Generator::DOM subclasses XML::Generator in order to produce DOM
trees instead of strings (see XML/Generator, and
XML/DOM).  This module is still experimental and its
semantics might change.

   Essentially, tag methods return XML::DOM::DocumentFragment objects,
constructed either from a DOM document passed into the constructor or a
default document that XML::Generator::DOM will automatically construct.

   Calling the xml() method will return this automatically constructed
document and cause a fresh one to be constructed for future tag method
calls.  If you passed in your own document, you may not call the xml()
method.

   Below, we just note the remaining differences in semantics between
XML::Generator methods and XML::Generator::DOM methods.

CONSTRUCTOR
===========

   These configuration options are accepted but have no effect on the
semantics of the returned object: escape, pretty, conformance and empty.

TAG METHODS
===========

   Subsequently, tag method semantics are somewhat different for this
module compared to XML::Generator.  The primary difference is that tag
method return XML::DOM::DocumentFragment objects.  Namespace and attribute
processing remains the same, but remaining arguments to tag methods must
either be text or other XML::DOM::DocumentFragment objects.  No escape
processing, syntax checking, or output control is done; this is all left
up to XML::DOM.

SPECIAL TAGS
============

   All special tags are available by default with XML::Generator::DOM; you
don't need to use 'conformance' => 'strict'.

xmlpi(@args)
------------

   Arguments will simply be concatenated and passed as the data to the
XML::DOM::ProcessingInstruction object that is returned.

xmlcmnt
-------

   Escaping of '-' is done by XML::DOM::Comment, which replaces both
hyphens with '&#45;'.  An XML::DOM::Comment object is returned.

xmldecl
-------

   Returns an XML::DOM::XMLDecl object.  Respects 'version', 'encoding'
and 'dtd' settings in the object.

xmldecl
-------

   Returns an XML::DOM::DocumentType object.

xmlcdata
--------

   Returns an XML::DOM::CDATASection object.

xml
---

   As described above, xml() can only be used when dom_document was not
set in the object.  The automatically created document will have its XML
Declaration set and the arguments to xml() will be appended to it.  Then a
new DOM document is automatically generated and the old one is returned.
This is the only way to get a DOM document from this module.

Perl-style XML objects
**********************

NAME
====

   XML::Grove - Perl-style XML objects

SYNOPSIS
========

     use XML::Grove;

     # Basic parsing and grove building
     use XML::Grove::Builder;
     use XML::Parser::PerlSAX;
     $grove_builder = XML::Grove::Builder->new;
     $parser = XML::Parser::PerlSAX->new ( Handler => $grove_builder );
     $document = $parser->parse ( Source => { SystemId => 'filename' } );

     # Creating new objects
     $document = XML::Grove::Document->new ( Contents => [ ] );
     $element = XML::Grove::Element->new ( Name => 'tag',
                                           Attributes => { },
     				       Contents => [ ] );

     # Accessing XML objects
     $tag_name = $element->{Name};
     $contents = $element->{Contents};
     $parent = $element->{Parent};
     $characters->{Data} = 'XML is fun!';

DESCRIPTION
===========

   XML::Grove is a tree-based object model for accessing the information
set of parsed or stored XML, HTML, or SGML instances.  XML::Grove objects
are Perl hashes and arrays where you access the properties of the objects
using normal Perl syntax:

     $text = $characters->{Data};

How To Create a Grove
---------------------

   There are several ways for groves to come into being, they can be read
from a file or string using a parser and a grove builder, they can be
created by your Perl code using the `new()' methods of
XML::Grove::Objects, or databases or other sources can act as groves.

   The most common way to build groves is using a parser and a grove
builder.  The parser is the package that reads the characters of an XML
file, recognizes the XML syntax, and produces "events" reporting when
elements (tags), text (characters), processing instructions, and other
sequences occur.  A grove builder receives ("consumes" or "handles") these
events and builds XML::Grove objects.  The last thing the parser does is
return the XML::Grove::Document object that the grove builder created,
with all of it's elements and character data.

   The most common parser and grove builder are XML::Parser::PerlSAX (in
libxml-perl) and XML::Grove::Builder.  To build a grove, create the grove
builder first:

     $grove_builder = XML::Grove::Builder->new;

   Then create the parser, passing it the grove builder as it's handler:

     $parser = XML::Parser::PerlSAX->new ( Handler => $grove_builder );

   This associates the grove builder with the parser so that every time
you parse a document with this parser it will return an
XML::Grove::Document object.  To parse a file, use the `Source' parameter
to the `parse()' method containing a `SystemId' parameter (URL or path) of
the file you want to parse:

     $document = $parser->parse ( Source => { SystemId => 'kjv.xml' } );

   To parse a string held in a Perl variable, use the `Source' parameter
containing a `String' parameter:

     $document = $parser->parse ( Source => { String => $xml_text } );

   The following are all parsers that work with XML::Grove::Builder:

     XML::Parser::PerlSAX (in libxml-perl, uses XML::Parser)
     XML::ESISParser      (in libxml-perl, uses James Clark's `nsgmls')
     XML::SAX2Perl        (in libxml-perl, translates SAX 1.0 to PerlSAX)

   Most parsers supply more properties than the standard information set
below and XML::Grove will make available all the properties given by the
parser, refer to the parser documentation to find out what additional
properties it may provide.

   Although there are not any available yet (August 1999), PerlSAX filters
can be used to process the output of a parser before it is passed to
XML::Grove::Builder.  XML::Grove::PerlSAX can be used to provide input to
PerlSAX filters or other PerlSAX handlers.

Using Groves
------------

   The properties provided by parsers are available directly using Perl's
normal syntax for accessing hashes and arrays.  For example, to get the
name of an element:

     $element_name = $element->{Name};

   By convention, all properties provided by parsers are in mixed case.
`Parent' properties are available using the ``Data::Grove::Parent'' module.

   The following is the minimal set of objects and their properties that
you are likely to get from all parsers:

XML::Grove::Document
--------------------

   The Document object is parent of the root element of the parsed XML
document.

Contents
     An array containing the root element.

   A document's `Contents' may also contain processing instructions,
comments, and whitespace.

   Some parsers provide information about the document type, the XML
declaration, or notations and entities.  Check the parser documentation
for property names.

XML::Grove::Element
-------------------

   The Element object represents elements from the XML source.

Parent
     The parent object of this element.

Name
     A string, the element type name of this element

Attributes
     A hash of strings or arrays

Contents
     An array of elements, characters, processing instructions, etc.

   In a purely minimal grove, the attributes of an element will be plain
text (Perl scalars).  Some parsers provide access to notations and
entities in attributes, in which case the attribute may contain an array.

XML::Grove::Characters
----------------------

   The Characters object represents text from the XML source.

Parent
     The parent object of this characters object

Data
     A string, the characters

XML::Grove::PI
--------------

   The PI object represents processing instructions from the XML source.

Parent
     The parent object of this PI object.

Target
     A string, the processing instruction target.

Data
     A string, the processing instruction data, or undef if none was
     supplied.

   In addition to the minimal set of objects above, XML::Grove knows about
and parsers may provide the following objects.  Refer to the parser
documentation for descriptions of the properties of these objects.

     XML::Grove::
     ::Entity::External  External entity reference
     ::Entity::SubDoc    External SubDoc reference (SGML)
     ::Entity::SGML      External SGML reference (SGML)
     ::Entity            Entity reference
     ::Notation          Notation declaration
     ::Comment           <!-- A Comment -->
     ::SubDoc            A parsed subdocument (SGML)
     ::CData             A CDATA marked section
     ::ElementDecl       An element declaration from the DTD
     ::AttListDecl       An element's attribute declaration, from the DTD

METHODS
=======

   XML::Grove by itself only provides one method, new(), for creating new
XML::Grove objects.  There are Data::Grove and XML::Grove extension
modules that give additional methods for working with XML::Grove objects
and new extensions can be created as needed.

$obj = XML::Grove::OBJECT->new( [PROPERTIES] )
     `new' creates a new XML::Grove object with the type OBJECT, and with
     the initial PROPERTIES.  PROPERTIES may be given as either a list of
     key-value pairs, a hash, or an XML::Grove object to copy.  OBJECT may
     be any of the objects listed above.

   This is a list of available extensions and the methods they provide (as
of Feb 1999).  Refer to their module documentation for more information on
how to use them.

     XML::Grove::AsString
       as_string       return portions of groves as a string
       attr_as_string  return an element's attribute as a string

     XML::Grove::AsCanonXML
       as_canon_xml    return XML text in canonical XML format

     XML::Grove::PerlSAX
       parse           emulate a PerlSAX parser using the grove objects

     Data::Grove::Parent
       root            return the root element of a grove
       rootpath        return an array of all objects between the root
                       element and this object, inclusive

     Data::Grove::Parent also adds `C<Parent>' and `C<Raw>' properties
     to grove objects.

     Data::Grove::Visitor
       accept          call back a subroutine using an object type name
       accept_name     call back using an element or tag name
       children_accept for each child in Contents, call back a sub
       children_accept_name  same, but using tag names
       attr_accept     call back for the objects in attributes

     XML::Grove::IDs
       get_ids         return a list of all ID attributes in grove

     XML::Grove::Path
       at_path         $el->at_path('/html/body/ul/li[4]')

     XML::Grove::Sub
       filter          run a sub against all the objects in the grove

WRITING EXTENSIONS
==================

   The class `XML::Grove' is the superclass of all classes in the
XML::Grove module.  `XML::Grove' is a subclass of ``Data::Grove''.

   If you create an extension and you want to add a method to all
XML::Grove objects, then create that method in the XML::Grove package.
Many extensions only need to add methods to XML::Grove::Document and/or
XML::Grove::Element.

   When you create an extension you should definitly provide a way to
invoke your module using objects from your package too.  For example,
XML::Grove::AsString's `as_string()' method can also be called using an
XML::Grove::AsString object:

     $writer= new XML::Grove::AsString;
     $string = $writer->as_string ( $xml_object );

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), XML::Grove(3)

   Extensible Markup Language (XML) <http://www.w3c.org/XML>

output XML objects in canonical XML
***********************************

NAME
====

   XML::Grove::AsCanonXML - output XML objects in canonical XML

SYNOPSIS
========

     use XML::Grove::AsCanonXML;

     # Using as_canon_xml method on XML::Grove objects:
     $string = $xml_object->as_canon_xml( OPTIONS );

     # Using an XML::Grove::AsCanonXML instance:
     $writer = XML::Grove::AsCanonXML->new( OPTIONS );

     $string = $writer->as_canon_xml($xml_object);
     $writer->as_canon_xml($xml_object, $file_handle);

DESCRIPTION
===========

   `XML::Grove::AsCanonXML' will return a string or write a stream of
canonical XML for an XML object and it's content (if any).

   `XML::Grove::AsCanonXML' objects hold the options used for writing the
XML objects.  Options can be supplied when the the object is created,

     $writer = XML::Grove::AsCanonXML->new( Comments => 1 );

   or modified at any time before writing an XML object by setting the
option directly in the `$writer' hash.

OPTIONS
=======

Comments
     By default comments are not written to the output.  Setting comment to
     TRUE will include comments in the output.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), XML::Parser(3), XML::Grove(3).

   James Clark's Canonical XML definition
<http://www.jclark.com/xml/canonxml.html>

output content of XML objects as a string
*****************************************

NAME
====

   XML::Grove::AsString - output content of XML objects as a string

SYNOPSIS
========

     use XML::Grove::AsString;

     # Using as_string method on XML::Grove::Document or XML::Grove::Element:
     $string = $xml_object->as_string OPTIONS;
     $string = $element->attr_as_string $attr, OPTIONS;

     # Using an XML::Grove::AsString instance:
     $writer = new XML::Grove::AsString OPTIONS;

     $string = $writer->as_string($xml_object);
     $writer->as_string($xml_object, $file_handle);

DESCRIPTION
===========

   Calling `as_string' on an XML object returns the character data
contents of that object as a string, including all elements below that
object.  Calling ``attr_as_string'' on an element returns the contents of
the named attribute as a string.  Comments, processing instructions, and,
by default, entities all return an empty string.

   OPTIONS may either be a key-value list or a hash containing the options
described below.  OPTIONS may be modified directly in the object.  The
default options are no filtering and entities are mapped to empty strings.

OPTIONS
=======

Filter
     `Filter' is an anonymous sub that gets called to process character
     data before it is appended to the string to be returned.  This can be
     used, for example, to escape characters that are special in output
     formats.  The `Filter' sub is called like this:

          $string = &$filter ($character_data);

EntityMap
     `EntityMap' is an object that accepts `lookup' methods or an
     anonymous sub that gets called with the entity replacement text (data)
     and mapper options as arguments and returns the corresponding
     character replacements.  It is called like this if it is an object:

          $replacement_text = $entity_map->lookup ($entity_data,
          					     $entity_map_options);

     or this if it is a sub:

          $replacement_text = &$entity_map ($entity_data,
          				      $entity_map_options);

EntityMapOptions
     `EntityMapOptions' is a hash passed through to the `lookup' method or
     anonymous sub, the type of value is defined by the entity mapping
     package or the anonymous sub.

EntityMapFilter
     `EntityMapFilter' is a flag to indicate if mapped entities should be
     filtered after mapping.

EXAMPLES
========

   Here is an example of entity mapping using the Text::EntityMap module:

     use Text::EntityMap;
     use XML::Grove::AsString;

     $html_iso_dia = Text::EntityMap->load ('ISOdia.2html');
     $html_iso_pub = Text::EntityMap->load ('ISOpub.2html');
     $html_map = Text::EntityMap->group ($html_iso_dia,
     					$html_iso_pub);

     $element->as_string (EntityMap => $html_map);

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), XML::Grove(3)

   Extensible Markup Language (XML) <http://www.w3c.org/XML>

PerlSAX handler for building an XML::Grove
******************************************

NAME
====

   XML::Grove::Builder - PerlSAX handler for building an XML::Grove

SYNOPSIS
========

     use PerlSAXParser;
     use XML::Grove::Builder;

     $builder = XML::Grove::Builder->new();
     $parser = PerlSAXParser->new( Handler => $builder );

     $grove = $parser->parse( Source => [SOURCE] );

DESCRIPTION
===========

   `XML::Grove::Builder' is a PerlSAX handler for building an XML::Grove.

   `XML::Grove::Builder' is used by creating a new instance of
`XML::Grove::Builder' and providing it as the Handler for a PerlSAX
parser.  Calling `parse()' on the PerlSAX parser will return the grove
built from that parse.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), XML::Grove(3), PerlSAX.pod

   Extensible Markup Language (XML) <http://www.w3c.org/XML>

simplify creation of XML::Grove objects
***************************************

NAME
====

   XML::Grove::Factory - simplify creation of XML::Grove objects

SYNOPSIS
========

     use XML::Grove::Factory;

     ### An object that creates Grove objects directly
     my $gf = XML::Grove::Factory->grove_factory;

     $grove = $gf->document( CONTENTS );
     $element = $gf->element( $name, { ATTRIBUTES }, CONTENTS );
     $pi = $gf->pi( $target, $data );
     $comment = $gf->comment( $data );

     ### An object that creates elements by method name
     my $ef = XML::Grove::Factory->element_factory();

     $element = $ef->NAME( { ATTRIBUTES }, CONTENTS);

     ### Similar to `element_factory', but creates functions in the
     ### current package
     XML::Grove::Factory->element_functions( PREFIX, ELEMENTS );

     $element = NAME( { ATTRIBUTES }, CONTENTS );

DESCRIPTION
===========

   `XML::Grove::Factory' provides objects or defines functions that let
you simply and quickly create the most commonly used XML::Grove objects.
`XML::Grove::Factory' supports three types of object creation.  The first
type is to create raw XML::Grove objects.  The second type creates XML
elements by element name.  The third type is like the second, but defines
local functions for you to call instead of using an object, which might
save typing in some cases.

   The three types of factories can be mixed.  For example, you can use
local functions for all element names that don't conflict with your own
sub names or contain special characters, and then use a
``grove_factory()'' object for those elements that do conflict.

   In the examples that follow, each example is creating an XML instance
similar to the following, assuming it's pretty printed:

     <?xml version="1.0"?>
     <HTML>
       <HEAD>
         <TITLE>Some Title</TITLE>
       </HEAD>
       <BODY bgcolor="#FFFFFF">
         <P>A paragraph.</P>
       </BODY>
     </HTML>

GROVE FACTORY
=============

$gf = XML::Grove::Factory->grove_factory()
     Creates a new grove factory object that creates raw XML::Grove
     objects.

$gf->document( CONTENTS );
     Creates an XML::Grove::Document object.  CONTENTS may contain
     processing instructions, strings containing only whitespace
     characters, and a single element object (but note that there is no
     checking).  Strings are converted to XML::Grove::Characters objects.

$gf->element($name, CONTENTS);
$gf->element($name, { ATTRIBUTES }, CONTENTS);
     Creates an XML::Grove::Element object with the name `$name'.  If the
     argument following `$name' is an anonymous hash, ATTRIBUTES, then
     they will be copied to the elements attributes.  CONTENTS will be
     stored in the element's content (note that there is no validity
     checking).  Strings in CONTENTS are converted to
     XML::Grove::Characters objects.

$gf->pi( *TARGET*, DATA)
$gf->pi( DATA )
     Create an XML::Grove::PI object with *TARGET* and DATA.

$gf->comment( DATA )
     Create an XML::Grove::Comment object with DATA.

GROVE FACTORY EXAMPLE
---------------------

     use XML::Grove::Factory;

     $gf = XML::Grove::Factory->grove_factory;

     $element =
       $gf->element('HTML',
         $gf->element('HEAD',
           $gf->element('TITLE', 'Some Title')),
         $gf->element('BODY', { bgcolor => '#FFFFFF' },
           $gf->element('P', 'A paragraph.')));

ELEMENT FACTORY
===============

$ef = XML::Grove::Factory->element_factory()
     Creates a new element factory object for creating elements.
     ``element_factory()'' objects work by creating an element for any
     name used to call the object.

$ef->NAME( CONTENTS )
$ef->NAME( { ATTRIBUTES }, CONTENTS)
     Creates an XML::Grove::Element object with the given NAME,
     ATTRIBUTES, and CONTENTS.  The hash containing ATTRIBUTES is optional
     if this element doesn't need attributes.  Strings in CONTENTS are
     converted to XML::Grove::Characters objects.

ELEMENT FACTORY EXAMPLE
-----------------------

     use XML::Grove::Factory;

     $ef = XML::Grove::Factory->element_factory();

     $element =
       $ef->HTML(
         $ef->HEAD(
           $ef->TITLE('Some Title')),
         $ef->BODY({ bgcolor => '#FFFFFF' },
           $ef->P('A paragraph.')));

ELEMENT FUNCTIONS
=================

XML::Grove::Factory->element_functions (PREFIX, ELEMENTS)
     Creates functions in the current package for creating elements with
     the names provided in the list ELEMENTS.  PREFIX will be prepended to
     every function name, or PREFIX can be an empty string (") if you're
     confident that there won't be any conflicts with functions in your
     package.

NAME( CONTENTS )
NAME( { ATTRIBUTES }, CONTENTS )
PREFIXNAME( CONTENTS )
PREFIXNAME( { ATTRIBUTES }, CONTENTS )
     Functions created for ``*NAME*'' or ``*PREFIX**NAME*'' can be called
     to create XML::Grove::Element objects with the given NAME,
     ATTRIBUTES, and CONTENT.  The hash containing ATTRIBUTES is optional
     if this element doesn't need attributes.  Strings in CONTENT are
     converted to XML::Grove::Characters objects.

ELEMENT FACTORY EXAMPLE
-----------------------

     use XML::Grove::Factory;

     XML::Grove::Factory->element_functions('', qw{ HTML HEAD TITLE BODY P });

     $element =
       HTML(
         HEAD(
           TITLE('Some Title')),
         BODY({ bgcolor => '#FFFFFF' },
           P('A paragraph.')));

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

   Inspired by the HTML::AsSubs module by Gisle Aas.

SEE ALSO
========

   perl(1), XML::Grove(3).

   Extensible Markup Language (XML) <http://www.w3c.org/XML>

return an index of `id' attributes in a grove
*********************************************

NAME
====

   XML::Grove::IDs - return an index of `id' attributes in a grove

SYNOPSIS
========

     use XML::Grove::IDs;

     # Using get_ids method on XML::Grove::Document or XML::Grove::Element:
     $hash = $grove_object->get_ids($attr_name, $elements);

     # Using an XML::Grove::IDs instance:
     $indexer = XML::Grove::IDs->new($attr_name, $elements);
     my $hash = {};
     $grove_object->accept($indexer, $hash);

DESCRIPTION
===========

   `XML::Grove::IDs' returns a hash index of all nodes in a grove with an
`id' attribute.  The keys of the hash are the ID attribute value and the
value at that key is the element.  ``$attr_name'' and ``$elements'' are
optional.  The attribute name defaults to `id' if ``$attr_name'' is not
supplied.  Indexing can be restricted to only certain elements, by name,
by providing a hash containing NAME=>1 values.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), XML::Grove(3), Data::Grove::Visitor(3)

   Extensible Markup Language (XML) <http://www.w3c.org/XML>

add tree iteration methods to XML objects
*****************************************

NAME
====

   XML::Grove::Iter - add tree iteration methods to XML objects

SYNOPSIS
========

     use XML::Grove::Iter;

     $iter = $xml_object->iter;

     $iter2 = $iter->parent;
     $iter2 = $iter->next;
     $iter2 = $iter->previous;

     $iter2 = $element_iter->first_child;
     $iter2 = $element_iter->last_child;
     $iter2 = $element_iter->attr_first ($attr);
     $iter2 = $element_iter->attr_last ($attr);

     $obj = $iter->delegate;
     $root = $iter->root;
     @path = $iter->rootpath;

     $bool = $iter->is_iter;
     $bool = $iter->is_same ($obj);
     $bool = $iter->at_last;
     $bool = $iter->at_first;

DESCRIPTION
===========

   XML::Grove::Iter is a proxy-based tree iterator.  "Proxy based" means
that the iterator "stands in" for the real object and is used as you would
normally use the real object.  The iterator handles moving around the tree
and forwards all other methods to the real object.

   `parent' returns the parent iterator of this iterator, or `undef' if
this is the root iterator.  `next' and `previous' return the iterator of
the next object or the previous object, respectively, in the parent's
content (the sibling objects), or `undef' if there is no next or previous
sibling.

   `first_child' and `last_child' return the iterator of the first child
or the last child of the contents of this element or document.
``attr_first'' and ``attr_last'' return the iterator of the first child or
last child of the named attribute.  These all return `undef' if the
contents are empty.

   `delegate' returns the object that this iterator stands-in for, "the
delegate".

   `root' returns the iterator of the top-most object of the sub-tree
being iterated.  Note that this may not be the root of the document tree
if the first iterator was created using a nested object.

   ``rootpath'' returns a list of the parent iterators between and
including the root and this iterator.

   ``is_iter'' returns true if this object is an iterator.  Ordinary XML
objects have been extended with an ``is_iter'' method that returns false.

   ``is_same'' returns true if `$obj' is this iterator's delegate, or if
`$obj' is an iterator that points to the same delegate.

   ``at_last'' and ``at_first'' return true if calling `next' or
`previous', respectively, would return `undef'.  Or in other words, they
return true if this iterator is at the end or the beginning of the parent
element's content.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), XML::Parser(3), XML::Parser::Grove(3).

   Extensible Markup Language (XML) <http://www.w3c.org/XML>

return the object at a path
***************************

NAME
====

   XML::Grove::Path - return the object at a path

SYNOPSIS
========

     use XML::Grove::Path;

     # Using at_path method on XML::Grove::Document or XML::Grove::Element:
     $xml_obj = $grove_object->at_path("/some/path");

     # Using an XML::Grove::Path instance:
     $pather = XML::Grove::Path->new();
     $xml_obj = $pather->at_path($grove_object);

DESCRIPTION
===========

   `XML::Grove::Path' returns XML objects located at paths.  Paths are
strings of element names or XML object types seperated by slash ("/")
characters.  Paths must always start at the grove object passed to
``at_path()''.  `XML::Grove::Path' is not XPath, but it should become
obsolete when an XPath implementation is available.

   Paths are like URLs

     /html/body/ul/li[4]
     /html/body/#pi[2]

   The path segments can be element names or object types, the objects
types are named using:

     #element
     #pi
     #comment
     #text
     #cdata
     #any

   The ``#any'' object type matches any type of object, it is essentially
an index into the contents of the parent object.

   The ``#text'' object type treats text objects as if they are not
normalized.  Two consecutive text objects are seperate text objects.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), XML::Grove(3)

   Extensible Markup Language (XML) <http://www.w3c.org/XML>

an PerlSAX event interface for XML objects
******************************************

NAME
====

   XML::Grove::PerlSAX - an PerlSAX event interface for XML objects

SYNOPSIS
========

     use XML::Grove::PerlSAX;

     $parser = XML::Grove::PerlSAX->new( [OPTIONS] );
     $result = $parser->parse( [OPTIONS] );

     # or
     $result = $xml_object->parse( [OPTIONS] );

DESCRIPTION
===========

   `XML::Grove::PerlSAX' is a PerlSAX parser that generates PerlSAX events
from XML::Grove objects.  This man page summarizes the specific options,
handlers, and properties supported by `XML::Grove::PerlSAX'; please refer
to the PerlSAX standard in ``PerlSAX.pod'' for general usage information.

METHODS
=======

new
     Creates a new parser object.  Default options for parsing, described
     below, are passed as key-value pairs or as a single hash.  Options may
     be changed directly in the parser object unless stated otherwise.
     Options passed to `parse()' override the default options in the
     parser object for the duration of the parse.

parse
     Parses a document.  Options, described below, are passed as key-value
     pairs or as a single hash.  Options passed to `parse()' override
     default options in the parser object.

OPTIONS
=======

   The following options are supported by `XML::Grove::PerlSAX':

     Handler          default handler to receive events
     DocumentHandler  handler to receive document events
     Source           hash containing the input source for parsing

   If no handlers are provided then all events will be silently ignored.

   If a single grove argument is passed to the `parse()' method, it is
treated as if a `Source' option was given with a ``Grove'' parameter.

   The `Source' hash may contain the following parameters:

     Grove            The grove object used to generate parse events..

HANDLERS
========

   The following events are generated by `XML::Grove::PerlSAX'.
XML::Grove::PerlSAX passes the corresponding grove object as it's
parameter so the properties passed to the handler are those that were used
to create or were assigned to the grove.  Please see the docs for the
parser used to create the grove for a list of properties that were
provided.

DocumentHandler methods
-----------------------

start_document
     Receive notification of the beginning of a document.  This is called
     from the XML::Grove::Document object before processing any document
     content.

end_document
     Receive notification of the end of a document.  This is called from
     the XML::Grove::Document object after processing all document content.

start_element
     Receive notification of the beginning of an element.  This is called
     from the XML::Grove::Element object before processing any element
     content.

end_element
     Receive notification of the end of an element.  This is called from
     the XML::Grove::Element object after processing all element content.

characters
     Receive notification of character data.  This is called from the
     XML::Grove::Characters object.

processing_instruction
     Receive notification of a processing instruction.  This is called from
     the XML::Grove::PI object.

comment
     Receive notification of a comment.  This is called from the
     XML::Grove::Comment object.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), XML::Grove(3)

   Extensible Markup Language (XML) <http://www.w3c.org/XML>

run a filter sub over a grove
*****************************

NAME
====

   XML::Grove::Sub - run a filter sub over a grove

SYNOPSIS
========

     use XML::Grove::Sub;

     # Using filter method on XML::Grove::Document or XML::Grove::Element:
     @results = $grove_object->filter(\&sub [, ...]);

     # Using an XML::Grove::Sub instance:
     $filterer = XML::Grove::Sub->new();
     @results = $grove_object->accept($filterer, \&sub [, ...]);

DESCRIPTION
===========

   `XML::Grove::Sub' executes a sub, the filter, over all objects in a
grove and returns a list of all the return values from the sub.  The sub
is called with the grove object as it's first parameter and passing the
rest of the arguments to the call to ``filter()'' or `accept()'.

EXAMPLE
=======

   The following filter will return a list of all `foo' or `bar' elements
with an attribute ``widget-no'' beginning with `A' or `B'.

     @results = $grove_obj->filter(sub {
         my $obj = shift;

     if ($obj->isa('XML::Grove::Element')
     	  && (($obj->{Name} eq 'foo')
     	      || ($obj->{Name} eq 'bar'))
     	  && ($obj->{Attributes}{'widget-no'} =~ /^[AB]/)) {
     	  return ($obj);
     }
     return ();
       });

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), XML::Grove(3), Data::Grove::Visitor(3)

   Extensible Markup Language (XML) <http://www.w3c.org/XML>

substitute values into a template
*********************************

NAME
====

   XML::Grove::Subst - substitute values into a template

SYNOPSIS
========

     use XML::Grove::Subst;

     # Using subst method on XML::Grove::Document or XML::Grove::Element:
     $new_grove = $source_grove->subst( ARGS );
     $new_grove = $source_grove->subst_hash( ARG );

     # Using an XML::Grove::Subst instance:
     $subster = XML::Grove::Subst->new();
     $new_grove = $subster->subst( $source_grove, ARGS );
     $new_grove = $subster->subst_hash( $source_grove, ARG );

DESCRIPTION
===========

   `XML::Grove::Subst' implements XML templates.  `XML::Grove::Subst'
traverses through a source grove replacing all elements with names
``SUB:XXX'' or ``SUB:key'' with their corresponding values from ARGS (a
list) or ARG (a hash), repsectively.

METHODS
=======

$grove_obj->subst( ARGS ) =item $subster->subst( $grove_obj, ARGS )
     Search for ``SUB:*XXX*'' elements, where XXX is an array index, and
     replace the element with the value from ARGS, a list of values.  The
     return value is a new grove with the substitutions applied.

$grove_obj->subst_hash( ARG ) =item $subster->subst_hash( $grove_obj, ARG )
     Search for ``SUB:key'' elements and replace the element with the
     value from ARG, a hash of values.  The hash key is taken from the
     `key' attribute of the ``SUB:key'' element, for example, ``<SUB:key
     key='foo'>''.  The return value is a new grove with the substitutions
     applied.

EXAMPLE
=======

   The following template, in a file ``template.xml'', could be used for a
simple parts database conversion to HTML:

     <html>
       <head>
         <title><SUB:key key='Name'></title>
       </head>
       <body>
         <h1><SUB:key key='Name'></title>
         <p>Information for part number <SUB:key key='Number'>:</p>
         <SUB:key key='Description'>
       </body>
     </html>

   To use this template you would first parse it and convert it to a
grove, and then use ``subst_hash()'' every time you needed a new page:

     use XML::Parser::PerlSAX;
     use XML::Grove;
     use XML::Grove::Builder;
     use XML::Grove::Subst;
     use XML::Grove::PerlSAX;
     use XML::Handler::XMLWriter;

     # Load the template
     $b = XML::Grove::Builder->new();
     $p = XML::Parser::PerlSAX->new( Handler = $b );
     $source_grove = $p->parse( Source => { SystemId => 'template.xml' } );

     # Apply the substitutions
     $new_grove = $source_grove->subst_hash( { Name => 'Acme DCX-2000 Filter',
     					      Number => 'N4728',
     					      Description => 'The Best' } );

     # Write the new grove to standard output
     $w = XML::Handler::XMLWriter->new();
     $wp = XML::Grove::PerlSAX->new( Handler => $w );
     $wp->parse( Source => { Grove => $new_grove } );

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), XML::Grove(3)

   Extensible Markup Language (XML) <http://www.w3c.org/XML>

add visitor/callback methods to XML objects
*******************************************

NAME
====

   XML::Grove::Visitor - add visitor/callback methods to XML objects

SYNOPSIS
========

     use XML::Grove::Visitor;

     @results = $xml_object->accept ($visitor, ...);
     @results = $xml_object->accept_name ($visitor, ...);
     @results = $xml_object->children_accept ($visitor, ...);
     @results = $xml_object->children_accept_name ($visitor, ...);
     @results = $element->attr_accept ($attr, $visitor, ...);

DESCRIPTION
===========

   XML::Grove::Visitor adds visitor methods (callbacks) to XML objects and
their iterators.  A "visitor" is a class (a package) that has methods
(subs) corresponding to the objects in the classes being visited.  You use
the visitor methods by creating an instance of your visitor class, and
then calling ``accept($my_visitor)'' on the top-most object you want to
visit, that object will in turn call your visitor back with
``visit_*OBJECT*'', where OBJECT is the type of object.

   There are several forms of `accept'.  Simply calling `accept' calls
your package back using the object type of the object you are visiting.
Calling ``accept_name'' on an element object calls you back with
``visit_name_*NAME*'' where NAME is the tag name of the element, on all
other objects it's as if you called `accept'.

   All of the forms of `accept' return a concatenated list of the result
of all `visit' methods.

   ``children_accept'' calls `accept' on each of the children of the
element.  This is generally used in element callbacks to recurse down into
the element's children, you don't need to get the element's contents and
call `accept' on each item.  ``children_accept_name'' does the same but
calling ``accept_name'' on each of the children.  ``attr_accept'' calls
`accept' on each of the objects in the named attribute.

   If the child object you are visiting is a Perl scalar, you will be
called back with ``visit_scalar''.  The complete list of callbacks defined
by XML::Grove::Visitor are:

     visit_grove
     visit_element
     visit_entity
     visit_pi
     visit_comment
     visit_scalar

   When using `accept' methods with an iterator, the child objects you get
called back with will also be iterators, including ``visit_scalar''.

   See also the examples ``visitor.pl'' and ``my-html.pl''.

HMM
===

   These are random ideas that haven't been implemented yet:

   * Some people like their subs a little simpler, i.e. drop the
     ``visit_''.  In SGML::Grove, tag names were called back with the SGML
     equivalent, ``visit_gi_*NAME*'' (generic identifier).  Both of these
     could possibly be made into options.

   * Several objects fall into subclasses, or you may want to be able to
     subclass a visited object and still be able to tell the difference.
     In SGML::Grove I had used the package name in the callback
     (``visit_SGML_Element'') instead of a generic name
     (``visit_element'').  The idea here would be to try calling
     ``visit_*PACKAGE*'' with the most specific class first, then try
     superclasses, and lastly to try the generic.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), XML::Parser(3), XML::Parser::Grove(3).

   Extensible Markup Language (XML) <http://www.w3c.org/XML>

deprecated module once intended for XPointer
********************************************

NAME
====

   XML::Grove::XPointer - deprecated module once intended for XPointer

SYNOPSIS
========

     THIS MODULE IS USED BY XML::Grove::Path, it does not implement any
     current version of XPointer

DESCRIPTION
===========

   This module implements a very tiny portion of an old draft of XPointer.
XML::Grove::Path still uses this module, but both modules will be
obsolete when a real XPath and XPointer module become available.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), XML::Grove(3), XML::Grove::Path(3)

   Extensible Markup Language (XML) <http://www.w3c.org/XML>

PerlSAX handler that creates XML::DOM document structures
*********************************************************

NAME
====

   XML::Handler::BuildDOM - PerlSAX handler that creates XML::DOM document
structures

SYNOPSIS
========

     use XML::Handler::BuildDOM;
     use XML::Parser::PerlSAX;

     my $handler = new XML::Handler::BuildDOM (KeepCDATA => 1);
     my $parser = new XML::Parser::PerlSAX (Handler => $handler);

     my $doc = $parser->parsefile ("file.xml");

DESCRIPTION
===========

   XML::Handler::BuildDOM creates XML/DOM, document
structures (i.e. See XML/DOM/Document) from PerlSAX
events.

   This class used to be called `XML::PerlSAX::DOM' in this node prior to
libxml-enno 1.0.1.

CONSTRUCTOR OPTIONS
-------------------

   The XML::Handler::BuildDOM constructor supports the following options:

   * KeepCDATA => 1

     If set to 0 (default), CDATASections will be converted to regular
     text.

   * Document => $doc

     If undefined, start_document will extract it from Element or DocType
     (if set), otherwise it will create a new XML::DOM::Document.

   * Element => $elem

     If undefined, it is set to Document. This will be the insertion point
     (or parent) for the nodes defined by the following callbacks.

   * DocType => $doctype

     If undefined, start_document will extract it from Document (if
     possible).  Otherwise it adds a new XML::DOM::DocumentType to the
     Document.

output XML in canonical XML format
**********************************

NAME
====

   XML::Handler::CanonXMLWriter - output XML in canonical XML format

SYNOPSIS
========

     use XML::Handler::CanonXMLWriter;

     $writer = XML::Handler::CanonXMLWriter OPTIONS;
     $parser->parse(Handler => $writer);

DESCRIPTION
===========

   `XML::Handler::CanonXMLWriter' is a PerlSAX handler that will return a
string or write a stream of canonical XML for an XML instance and it's
content.

   `XML::Handler::CanonXMLWriter' objects hold the options used for
writing the XML objects.  Options can be supplied when the the object is
created,

     $writer = new XML::Handler::CanonXMLWriter PrintComments => 1;

   or modified at any time before calling the parser's `parse()' method:

     $writer->{PrintComments} = 0;

OPTIONS
=======

IOHandle
     IOHandle contains a handle for writing the canonical XML to.  If an
     IOHandle is not provided, the canonical XML string will be returned
     from `parse()'.

PrintComments
     By default comments are not written to the output.  Setting comment to
     a true value will include comments in the output.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), PerlSAX

   James Clark's Canonical XML definition
<http://www.jclark.com/xml/canonxml.html>

Another XML printer/writer/generator
************************************

NAME
====

   XML::Handler::Composer - Another XML printer/writer/generator

SYNOPSIS
========

   use XML::Handler::Composer;

   my $composer = new XML::Handler::Composer ( [OPTIONS] );

DESCRIPTION
===========

   XML::Handler::Composer is similar to XML::Writer,
XML::Handler::XMLWriter, XML::Handler::YAWriter etc. in that it generates
XML output.

   This implementation may not be fast and it may not be the best solution
for your particular problem, but it has some features that may be missing
in the other implementations:

   * Supports every output encoding that XML/UM, supports

     See XML/UM, supports every encoding for which there is a
     mapping file in the XML/Encoding, distribution.

   * Pretty printing

     When used with XML/Filter/Reindent.

   * Fine control over which kind of quotes are used

     See options below.

   * Supports PerlSAX interface

Constructor Options
===================

   * EndWithNewline (Default: 1)

     Whether to print a newline at the end of the file (i.e. after the
     root element)

   * Newline (Default: undef)

     If defined, which newline to use for printing.  (Note that
     XML::Parser etc. convert newlines into "\x0A".)

     If undef, newlines will not be converted and XML::Handler::Composer
     will use "\x0A" when printing.

     A value of "\n" will convert the internal newlines into the platform
     specific line separator.

     See the PreserveWS option in the characters event (below) for finer
     control over when newline conversion is active.

   * DocTypeIndent (Default: a Newline and 2 spaces)

     Newline plus indent that is used to separate lines inside the DTD.

   * IndentAttList (Default: 8 spaces)

     Indent used when printing an <!ATTLIST> declaration that has more
     than one attribute definition, e.g.

          <!ATTLIST my_elem
                 attr1 CDATA "foo"
                 attr2 CDATA "bar"
          >

   * Quote (Default: { XMLDecl => '"', Attr => '"', Entity => '"',
     SystemLiteral => '"' })

     Quote contains a reference to a hash that defines which quoting
     characters to use when printing XML declarations (XMLDecl), attribute
     values (Attr), <!ENTITY> values (Entity) and system/public literals
     (SystemLiteral) as found in <!DOCTYPE>, <!ENTITY> declarations etc.

   * PrintDefaultAttr (Default: 0)

     If 1, prints attribute values regardless of whether they are default
     attribute values (as defined in <!ATTLIST> declarations.)  Normally,
     default attributes are not printed.

   * Encoding (Default: undef)

     Defines the output encoding (if specified.)  Note that future calls
     to the xml_decl() handler may override this setting (if they contain
     an Encoding definition.)

   * EncodeUnmapped (Default: \&XML::UM::encode_unmapped_dec)

     Defines how Unicode characters not found in the mapping file (of the
     specified encoding) are printed.  By default, they are converted to
     decimal entity references, like '&#123;'

     Use \&XML::UM::encode_unmapped_hex for hexadecimal constants, like
     '&#xAB;'

   * Print (Default: sub { print @_ }, which prints to stdout)

     The subroutine that is used to print the encoded XML output.  The
     default prints the string to stdout.

Method: get_compressed_element_suffix ($event)
==============================================

   Override this method to support the different styles for printing empty
elements in compressed notation, e.g. <p/>, <p></p>, <p />, <p>.

   The default returns "/>", which results in <p/>.  Use " />" for XHTML
style elements or ">" for certain HTML style elements.

   The $event parameter is the hash reference that was received from the
start_element() handler.

Extra PerlSAX event information
===============================

   XML::Handler::Composer relies on hints from previous SAX filters to
format certain parts of the XML.  These SAX filters (e.g.
XML::Filter::Reindent) pass extra information by adding name/value pairs
to the appropriate PerlSAX events (the events themselves are hash
references.)

   * entity_reference: Parameter => 1

     If Parameter is 1, it means that it is a parameter entity reference.
     A parameter entity is referenced with %ent; instead of &ent; and the
     entity declaration starts with <!ENTITY % ent ...> instead of
     <!ENTITY ent ...>

     NOTE: This should be added to the PerlSAX interface!

   * start_element/end_element: Compress => 1

     If Compress is 1 in both the start_element and end_element event, the
     element will be printed in compressed form, e.g. <a/> instead of
     <a></a>.

   * start_element: PreserveWS => 1

     If newline conversion is active (i.e. Newline was defined in the
     constructor), then newlines will *NOT* be converted in text
     (character events) within this element.

   * attlist_decl: First, MoreFollow

     The First and MoreFollow options can be used to force successive
     <!ATTLIST> declarations for the same element to be merged, e.g.

          <!ATTLIST my_elem
                 attr1 CDATA "foo"
                 attr2 CDATA "bar"
                 attr3 CDATA "quux"
          >

     In this example, the attlist_decl event for foo should contain (First
     => 1, MoreFollow => 1) and the event for bar should contain
     (MoreFollow => 1). The quux event should have no extra info.

     'First' indicates that the event is the first of a sequence.
     'MoreFollow' indicates that more events will follow in this sequence.

     If neither option is set by the preceding PerlSAX filter, each
     attribute definition will be printed as a separate <!ATTLIST> line.

CAVEATS
=======

   This code is highly experimental!  It has not been tested well and the
API may change.

AUTHOR
======

   Send bug reports, hints, tips, suggestions to Enno Derksen at
<`enno@att.com'>.

Prints PerlSAX events (for debugging)
*************************************

NAME
====

   XML::Handler::PrintEvents - Prints PerlSAX events (for debugging)

SYNOPSIS
========

   use XML::Handler::PrintEvents;

   my $pr = new XML::Handler::PrintEvents;

DESCRIPTION
===========

   This PerlSAX handler prints the PerlSAX events it receives to STDOUT.
It can be useful when debugging PerlSAX filters.  It supports all PerlSAX
handler including ignorable_whitespace.

AUTHOR
======

   Send bug reports, hints, tips, suggestions to Enno Derksen at
<`enno@att.com'>.

convert Perl SAX events to ESIS of Nsgmls or Pyxie.
***************************************************

NAME
====

   XML::Handler::PyxWriter - convert Perl SAX events to ESIS of Nsgmls or
Pyxie.

SYNOPSIS
========

     use XML::Handler::PyxWriter;
     $writer = new XML::Handler::PyxWriter OPTIONS;
     $handler->parse(Handler => $writer);

DESCRIPTION
===========

   XML::Handler::PyxWriter is a Perl SAX module. It generates ESIS of
Nsgmls or  Pyxie. Behaviour of object is specified when the object is
created.

OPTIONS
=======

ByteStream
     Output stream object with method "print" (for example, IO::File).

SystemId
     Name of file passed to method "open" of IO::File.  If "ByteStream" is
     defined then "SystemId" is ignored.  Default value of "SystemId" is
     "-".

AttrBeforeElement
     Attributes are before element (1) or after  element (0). Default is 1
     (before).

CompactAttrString
     Attribute type is absent (1) or present (0). Default is 0 (present).

RECOMMENDED VALUES
==================

   Probably you like to be compatible with Nsgmls or Pyxie. The main
difference is that Nsgmls has attributes before element and attribute
types. Pyxie has attributes after element and does not have attribute
types. By default XML::Parser::PyxWriter uses Nsgmls mode.

   Recommended values for Nsgmls mode:

   * AttrBeforeElement = 1

   * CompactAttrString = 0

   Recommended values for Pyxie mode:

   * AttrBeforeElement = 0

   * CompactAttrString = 1

OUTPUT STREAM
=============

   XML::Handler::PyxWriter produces these escape sequences:

\
     \\

[TAB]
     \011

[LF]
     \012

[CR]
     \015

AUTHOR
======

   Oleg A. Paraschenko, prof@beta.math.spbu.ru

SEE ALSO
========

   XML::Parser::PyxParser

   Home Page, http://beta.math.spbu.ru/~prof/xc/

   Nsgmls

   Pyxie, http://www.pyxie.org/

   PerlSAX

   XML::PYX

   XML::ESISParser

   SGMLS

a trivial PerlSAX handler
*************************

NAME
====

   XML::Handler::Sample - a trivial PerlSAX handler

SYNOPSIS
========

     use XML::Parser::PerlSAX;
     use XML::Handler::Sample;

     $my_handler = XML::Handler::Sample->new;

     XML::Parser::PerlSAX->new->parse(Source => { SystemId => 'REC-xml-19980210.xml' },
                                      Handler => $my_handler);

DESCRIPTION
===========

   `XML::Handler::Sample' is a trivial PerlSAX handler that prints out the
name of each event it receives.  The source for `XML::Handler::Sample'
lists all the currently known PerlSAX handler methods.

   `XML::Handler::Sample' is intended for Perl module authors who wish to
look at example PerlSAX handler modules.  `XML::Handler::Sample' can be
used as a template for writing your own PerlSAX handler modules.
`XML::Handler::Sample' is in the Public Domain and can be used for any
purpose without restriction.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), PerlSAX.pod(3)

a PerlSAX handler base class for calling user-defined subs
**********************************************************

NAME
====

   XML::Handler::Subs - a PerlSAX handler base class for calling
user-defined subs

SYNOPSIS
========

     use XML::Handler::Subs;

     package MyHandlers;
     use vars qw{ @ISA };

     sub s_NAME { my ($self, $element) = @_ };
     sub e_NAME { my ($self, $element) = @_ };

     $self->{Names};    # an array of names
     $self->{Nodes};    # an array of $element nodes

     $handler = MyHandlers->new();
     $self->in_element($name);
     $self->within_element($name);

DESCRIPTION
===========

   `XML::Handler::Subs' is a base class for PerlSAX handlers.
`XML::Handler::Subs' is subclassed to implement complete behavior and to
add element-specific handling.

   Each time an element starts, a method by that name prefixed with `s_'
is called with the element to be processed.  Each time an element ends, a
method with that name prefixed with `e_' is called.  Any special
characters in the element name are replaced by underscores.

   Subclassing XML::Handler::Subs in this way is similar to XML::Parser's
Subs style.

   XML::Handler::Subs maintains a stack of element names,
``$self-'{Names}', and a stack of element nodes, ``$self-'{Nodes}>' that
can be used by subclasses.  The current element is pushed on the stacks
before calling an element-name start method and popped off the stacks
after calling the element-name end method.  The ``in_element()'' and
``within_element()'' calls use these stacks.

   If the subclass implements ``start_document()'', ``end_document()'',
``start_element()'', and ``end_element()'', be sure to use ``SUPER::'' to
call the the superclass methods also.  See perlobj(1) for details on
SUPER::.  ``SUPER::start_element()'' and ``SUPER::end_element()'' return 1
if an element-name method is called, they return 0 if no method was called.

   XML::Handler::Subs does not implement any other PerlSAX handlers.

   XML::Handler::Subs supports the following methods:

new( OPTIONS )
     A basic `new()' method.  `new()' takes a list of key, value pairs or
     a hash and creates and returns a hash with those options; the hash is
     blessed into the subclass.

in_element($name)
     Returns true if `$name' is equal to the name of the innermost
     currently opened element.

within_element($name)
     Returns the number of times the `$name' appears in Names.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), PerlSAX.pod(3)

a PerlSAX handler for writing readable XML
******************************************

NAME
====

   XML::Handler::XMLWriter - a PerlSAX handler for writing readable XML

SYNOPSIS
========

     use XML::Parser::PerlSAX;
     use XML::Handler::XMLWriter;

     $my_handler = XML::Handler::XMLWriter->new( I<OPTIONS> );

     XML::Parser::PerlSAX->new->parse(Source => { SystemId => 'REC-xml-19980210.xml' },
                                      Handler => $my_handler);

DESCRIPTION
===========

   `XML::Handler::XMLWriter' is a PerlSAX handler for writing readable XML
(in contrast to Canonical XML, for example).  XML::Handler::XMLWriter can
be used with a parser to reformat XML, with XML::DOM or XML::Grove to
write out XML, or with other PerlSAX modules that generate events.

   `XML::Handler::XMLWriter' is intended to be used with PerlSAX event
generators and does not perform any checking itself (for example, matching
start and end element events).  If you want to generate XML directly from
your Perl code, use the XML::Writer module.  XML::Writer has an easy to
use interface and performs many checks to make sure that the XML you
generate is well-formed.

   `XML::Handler::XMLWriter' is a subclass of `XML::Handler::Subs'.
`XML::Handler::XMLWriter' can be further subclassed to alter it's behavior
or to add element-specific handling.  In the subclass, each time an
element starts, a method by that name prefixed with `s_' is called with
the element to be processed.  Each time an element ends, a method with
that name prefixed with `e_' is called.  Any special characters in the
element name are replaced by underscores.  If there isn't a start or end
method for an element, the default action is to write the start or end
tag.  Start and end methods can use the ``print_start_element()'' and
``print_end_element()'' methods to print start or end tags.  Subclasses
can call the `print()' method to write additional output.

   Subclassing XML::Handler::XMLWriter in this way is similar to
XML::Parser's Stream style.

   XML::Handler::Subs maintains a stack of element names,
``$self-'{Names}', and a stack of element nodes, ``$self-'{Nodes}>' that
can be used by subclasses.  The current element is pushed on the stacks
before calling an element-name start method and popped off the stacks
after calling the element-name end method.

   See XML::Handler::Subs for additional methods.

   In addition to the standard PerlSAX handler methods (see PerlSAX for
descriptions), XML::Handler::XMLWriter supports the following methods:

new( OPTIONS )
     Creates and returns a new instance of XML::Handler::XMLWriter with the
     given OPTIONS.  Options may be changed at any time by modifying them
     directly in the hash returned.  OPTIONS can be a list of key, value
     pairs or a hash.  The following OPTIONS are supported:

    Output
          An IO::Handle or one of it's subclasses (such as IO::File), if
          this parameter is not present and the AsString option is not
          used, the module will write to standard output.

    AsString
          Return the generated XML as a string from the `parse()' method of
          the PerlSAX event generator.

    Newlines
          A true or false value; if this parameter is present and its
          value is true, then the module will insert an extra newline
          before the closing delimiter of start, end, and empty tags to
          guarantee that the document does not end up as a single, long
          line.  If the paramter is not present, the module will not
          insert the newlines.

    IsSGML
          A true or false value; if this parameter is present and its
          value is true, then the module will generate SGML rather than
          XML.

print_start_element($element)
     Print a start tag for ``$element''.  This is the default action for
     the PerlSAX ``start_element()'' handler, but subclasses may use this
     if they define a start method for an element.

print_end_element($element)
     Prints an end tag for ``$element''.  This is the default action for
     the PerlSAX ``end_element()'' handler, but subclasses may use this if
     they define a start method for an element.

print($output)
     Write ``$output'' to Output and/or append it to the string to be
     returned.  Subclasses may use this to write additional output.

TODO
====

   * An Elements option that provides finer control over newlines than the
     Newlines option, where you can choose before and after newline for
     element start and end tags.  Inspired by the Python XMLWriter.

   * Support Doctype and XML declarations.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us This module is partially derived from
XML::Writer by David Megginson.

SEE ALSO
========

   perl(1), PerlSAX.pod(3)

Yet another Perl SAX XML Writer
*******************************

NAME
====

   XML::Handler::YAWriter - Yet another Perl SAX XML Writer

SYNOPSIS
========

     use XML::Handler::YAWriter;

     my $ya = new XML::Handler::YAWriter( %options );
     my $perlsax = new XML::Parser::PerlSAX( 'Handler' => $ya );

DESCRIPTION
===========

   YAWriter implements Yet Another XML::Handler::Writer. The reasons for
this one are that I needed a flexible escaping technique, and want some
kind of pretty printing. If an instance of YAWriter is created without any
options, the default behavior is to produce an array of strings containing
the XML in :

     @{$ya->{Strings}}

Options
-------

   Options are given in the usual 'key' => 'value' idiom.

Output IO::File
     This option tells YAWriter to use an already open file for output,
     instead of using $ya->{Strings} to store the array of strings. It
     should be noted that the only thing the object needs to implement is
     the print method. So anything can be used to receive a stream of
     strings from YAWriter.

AsFile string
     This option will cause start_document to open named file and
     end_document to close it. Use the literal dash "-" if you want to
     print on standard output.

AsArray boolean
     This option will force storage of the XML in $ya->{Strings}, even if
     the Output option is given.

AsString boolean
     This option will cause end_document to return the complete XML
     document in a single string. Most SAX drivers return the value of
     end_document as a result of their parse method. As this may not work
     with some combinations of SAX drivers and filters, a join of
     $ya->{Strings} in the controlling method is preferred.

Encoding string
     This will change the default encoding from UTF-8 to anything you like.
     You should ensure that given data are already in this encoding or
     provide an Escape hash, to tell YAWriter about the recoding.

Escape hash
     The Escape hash defines substitutions that have to be done to any
     string, with the exception of the processing_instruction and
     doctype_decl methods, where I think that escaping of target and data
     would cause more trouble than necessary.

     The default value for Escape is

          $XML::Handler::YAWriter::escape = {
                  '&'  => '&amp;',
                  '<'  => '&lt;',
                  '>'  => '&gt;',
                  '"'  => '&quot;',
                  '--' => '&#45;&#45;'
                  };

     YAWriter will use an evaluated sub to make the recoding based on a
     given Escape hash reasonably fast. Future versions may use XS to
     improve this performance bottleneck.

Pretty hash
     Hash of string => boolean tuples, to define kind of prettyprinting.
     Default to undef. Possible string values:

    AddHiddenNewline boolean
          Add hidden newline before ">"

    AddHiddenAttrTab boolean
          Add hidden tabulation for attributes

    CatchEmptyElement boolean
          Catch empty Elements, apply "/>" compression

    CatchWhiteSpace boolean
          Catch whitespace with comments

    IsSGML boolean
          This option will cause start_document, processing_instruction
          and doctype_decl to appear as SGML. The SGML is still
          well-formed of course, if your SAX events are well-formed.

    NoComments boolean
          Supress Comments

    NoDTD boolean
          Supress DTD

    NoPI boolean
          Supress Processing Instructions

    NoProlog boolean
          Supress <?xml ... ?> Prolog

    NoWhiteSpace boolean
          Supress WhiteSpace to clean documents from prior pretty printing.

    PrettyWhiteIndent boolean
          Add visible indent before any eventstring

    PrettyWhiteNewline boolean
          Add visible newlines before any eventstring

    SAX1 boolean (not yet implemented)
          Output only SAX1 compliant eventstrings

Notes:
------

   Correct handling of start_document and end_document is required!

   The YAWriter Object initialises its structures during start_document
and does its cleanup during end_document.  If you forget to call
start_document, any other method will break during the run. Most likely
place is the encode method, trying to eval undef as a subroutine. If you
forget to call end_document, you should not use a single instance of
YAWriter more than once.

   For small documents AsArray may be the fastest method and AsString the
easiest one to receive the output of YAWriter. But AsString and AsArray
may run out of memory with infinite SAX streams. The only method
XML::Handler::Writer calls on a given Output object is the print method.
So it's easy to use a self written Output object to improve streaming.

   A single instance of XML::Handler::YAWriter is able to produce more
than one file in a single run. Be sure to provide a fresh IO::File as
Output before you call start_document and close this File after calling
end_document. Or provide a filename in AsFile, so start_document and
end_document can open and close its own filehandle.

   Automatic recoding between 8bit and 16bit does not yet work correctly !

   I have Perl-5.00563 at home and here I can specify "use utf8;" in the
right places to make recoding work. But I dislike saying "use 5.00555;"
because many systems run 5.00503.

   If you use some 8bit character set internally and want use national
characters, either state your character as Encoding to be ISO-8859-1, or
provide an Escape hash similar to the following :

     $ya->{'Escape'} = {
     		    '&'  => '&amp;',
     		    '<'  => '&lt;',
     		    '>'  => '&gt;',
     		    '"'  => '&quot;',
     		    '--' => '&#45;&#45;'
     		    'ö' => '&ouml;'
     		    'ä' => '&auml;'
     		    'ü' => '&uuml;'
     		    'Ö' => '&Ouml;'
     		    'Ä' => '&Auml;'
     		    'Ü' => '&Uuml;'
     		    'ß' => '&szlig;'
     		    };

   You may abuse YAWriter to clean whitespace from XML documents. Take a
look at test.pl, doing just that with an XML::Edifact message, without
querying the DTD. This may work in 99% of the cases where you want to get
rid of ignorable whitespace caused by the various forms of pretty printing.

   my $ya = new XML::Handler::YAWriter(         'Output' => new IO::File (
">-" );         'Pretty' => {             'NoWhiteSpace'=>1,
'NoComments'=>1,             'AddHiddenNewline'=>1,
'AddHiddenAttrTab'=>1,         } );

   XML::Handler::Writer implements any method XML::Parser::PerlSAX wants.
This extends the Java SAX1.0 specification. I have in mind using
Pretty=>SAX1=>1 to disable this feature, if abusing YAWriter for a SAX
proxy.

   =head1 AUTHOR

   Michael Koehne, Kraehe@Copyleft.De

Thanks
======

   "Derksen, Eduard (Enno), CSCIO" <enno@att.com> helped me with the Escape
hash and gave quite a lot of useful comments.

SEE ALSO
========

   See Perl (perl.info), and XML/Parser/PerlSAX,

Collects user input, validates input and generates output in a number of ways based on the defined grammar.
***********************************************************************************************************

NAME
====

   XML::MetaGenerator - Collects user input, validates input and generates
output in a number of ways based on the defined grammar.

SYNOPSIS
========

     use XML::MetaGenerator;
     use XML::MetaGenerator::Language::Formula;
     use XML::MetaGenerator::Language::Formula::Collector::ReadLine;
     use XML::MetaGenerator::Language::Formula::Generator::HTML;

     my $wow = XML::MetaGenerator->get_instance();
     $wow->setObject('user');
     $wow->setLanguage(XML::MetaGenerator::Language::Formula->new());

     my $input = XML::MetaGenerator::Language::Formula::Collector::ReadLine->new();
     $wow->setCollector($input);

     my $generator = XML::MetaGenerator::Language::Formula::Generator::HTML->new();
     $wow->setGenerator($generator);

     # now collect the data
     $wow->collect();

     # validate it
     my ($valids, $missings, $invalids)= $wow->validate();

     # generate a document from the collected data;
     my $page =  $wow->generate();

DESCRIPTION
===========

   This object will work with many kinds of XML specification languages
(RELAX, xml-scheme, Formula and so on), using them to catch ('collect')
input data from different sources (cgi, command line, files ...),
'validate' it and eventually transforming it into the desired format (e.g.
HTML, XML).  I use this in order to have a common API for applications
that require multiple media access (e.g. WWW and console).

Object methods
==============

   These are the public methods available from MetaGenerator objects

get_instance
     returns the singleton MetaGenerator object

setCollector
     This let the user choose what kind of collector will be used.  The
     only parameter is a XML::MetaGenerator::Collector object.
     XML::MetaGenerator comes with three prepackaged collectors:  Apache -
     read data from $r params  Environment - read data from %ENV  ReadLine
     - read data from terminal using Term::ReadLine

setGenerator
     This let the user choose what kind of output to generate.  The
     parameter is a XML::MetaGenerator::Generator object.  The package
     comes with two prepackaged generator:  SimpleHTML - generate a html
     document consisting of a table with one row for every element in the
     formula; Also, if the data was validated before calling the
     generator, invalid elements will be highlighted.   XML - generate a
     basic xml document with XML::Writer.

setLanguage
     This method lets the user choose what kind of grammar to use for
     validation.  Currently XML::MetaGenerator supports just the formula
     language, for more information on it, refer to
     XML::MetaGenerator::Formula(3).  I hope to be able to add more
     languages soon (e.g. RELAX and xml-schema).

setObject
     This set the type of objects that MetaGenerator is going to
     manipulate.  The formulae directory holds some sample objects defined
     through the formula markup language.

collect
     This is the input method for MetaGenerator.  It uses the Collector
     object to get the data from the right input source

template
     This method outputs a dummy object. It's useful for testing or when
     you have to show how that object will look like.

generate
     This method is used to parse the collected input and to output the
     desired object in the desired format.

validate
     This method validates the input and returns an hash containing
     valids, invalids and missing elements.

AUTHOR
======

   Riccardo Cambiassi <riccardo@infodrome.net>

SEE ALSO
========

Node-based XML parsing: an simplified interface to XML::Parser
**************************************************************

NAME
====

   XML::Node - Node-based XML parsing: an simplified interface to
XML::Parser

SYNOPSIS
========

     use XML::Node;

     $xml_node = new XML::Node;
     $xml_node->register( $nodetype, $callback_type => \&callback_function );
     $xml_node->register( $nodetype, $callback_type => \$variable );

     open(FOO, 'xmlgenerator |');
     $p3->parse(*FOO);
     close(FOO);

     $xml_node->parsefile( $xml_filename );

DESCRIPTION
===========

   If you are only interested in processing certain nodes in an XML file,
this module can help you simplify your Perl scripts significantly.

   The XML::Node module allows you to register callback functions or
variables for any  XML node. If you register a call back function, it will
be called when the node of the type you specified are encountered. If you
register a variable, the content of a XML node will be appended to that
variable automatically.

   Subroutine register accepts both absolute and relative node
registrations.

   Here is an example of absolute path registration:

     1. register(">TestCase>Name", "start" => \&handle_TestCase_Name_start);

   Here are examples of single node name registration:

     2. register( "Name", "start" => \&handle_Name_start);
     3. register( "Name", "end"   => \&handle_Name_end);
     4. register( "Name", "char"  => \&handle_Name_char);

   Here is an example of attribute registration:

     5. register(">TestCase:Author", "attr" => \$testcase_author);

   Abosolute path trigger condition is recommended because a "Name" tage
could appear in different places and stands for differe names.

   Example:

     1  <Testcase>
     2     <Name>Something</Name>
     3     <Oracle>
     4         <Name>Something</Name>
     5     </Oracle>
     6  </Testcase>

   Statement 1 causes &handle_TestCase_Name_start to be called when
parsing Line 2. Statements 2,3,4 cause the three handler subroutines to be
called when parsing both Line 2 and Line 4.

   This module uses XML::Parser.

EXAMPLE
=======

   Examples "test.pl" and "parse_orders.pl" come with this perl module.

BUG REPORT
==========

   Please report bugs to http://belmont-shores.ics.uci.edu/bugzilla

SEE ALSO
========

   XML::Parser

NOTE
====

   When you register a variable, XML::Node appends strings found to that
variable. So please be sure to clear that variable when needed.

AUTHORS
=======

   Chang Liu <liu@ics.uci.edu>

LAST MODIFIED
=============

   $Date: 2000/03/13 11:38:28 $

PPD file format and XML parsing elements
****************************************

NAME
====

   XML::PPD - PPD file format and XML parsing elements

SYNOPSIS
========

     use XML::Parser;
     use XML::PPD;

     $p = new XML::Parser( Style => 'Objects', Pkg => 'XML::PPD' );
     ...

DESCRIPTION
===========

   This module provides a set of classes for parsing PPD files using the
XML::Parser module.  Each of the classes is derived from
`XML::ValidatingElement', with optional/required attributes/children
enforced.

MAJOR ELEMENTS
==============

SOFTPKG
-------

   Defines a Perl Package.  The root of a PPD document is always a SOFTPKG
element.  The SOFTPKG element allows for the following attributes:

NAME
     Required attribute.  Name of the package (e.g. "Foobar").

VERSION
     Version number of the package, in comma-delimited format (e.g.
     "1,0,0,0").

IMPLEMENTATION
--------------

   Child of SOFTPKG, used to describe a particular implementation of the
Perl Package.  Multiple instances are valid, and should be used to describe
different implementations/ports for different operating systems or
architectures.

DEPENDENCY
----------

   Child of SOFTPKG or IMPLEMENTATION, used to indicate a dependency this
Perl Package has on another Perl Package.  Multiple instances are valid.
The DEPENDENCY element allows for the following attributes:

NAME
     Name of the package that this implementation is dependant upon.

VERSION
     Version number of the dependency, in comma-delimited format (e.g.
     "1,0,0,0").

MINOR ELEMENTS
==============

TITLE
-----

   Child of SOFTPKG, used to state the title of the Perl Package.  Only one
instance should be present.

ABSTRACT
--------

   Child of SOFTPKG, used to provide a short description outlining the
nature and purpose of the Perl Package.  Only one instance should be
present.

AUTHOR
------

   Child of SOFTPKG, used to provide information about the author(s) of
the Perl Package.  Multiple instances are valid.

LANGUAGE
--------

   Child of IMPLEMENTATION, used to specify the language used within the
given implementation of the Perl Package.  Only one instance should be
present.

LICENSE
-------

   Child of SOFTPKG, indicating the location of the appropriate license
agreement or copyright notice for the Perl Package.  Only one instance
should be present.  The LICENSE element allows for the following
attributes:

HREF
     Required attribute.  A reference to the location of the license
     agreement or copyright notice for this package.

OS
--

   Child of IMPLEMENTATION, used to outline the operating system required
for this implementation of the Perl Package.  Multiple instances are
valid.  Valid values can be taken from the OSD Specification and it's OS
element.  The OS element allows for the following attributes:

VALUE
     The name of the operating system required for this implementation of
     the Perl Package.  This value should be obtained from Config.pm as
     'osname'.

   Note that previous versions of the PPD format used a 'NAME' attribute.
It's use has been deprecated in preference of the 'VALUE' attribute.  Also
note that during validation, this element will automatically convert any
existing 'NAME' attribute to be a 'VALUE' attribute.

OSVERSION
---------

   Child of IMPLEMENTATION, used to outline the required version of the
operating system required for this implementation of the Perl Package.
Only one instance should be present.  The OSVERSION element allows for the
following attributes:

VALUE
     The version of the operating system required for installation of this
     implementation of the package, in a comma-delimited format (e.g.
     "3,1,0,0").

   Note that previous versions of the PPD format used a 'NAME' attribute.
It's use has been deprecated in preference of the 'VALUE' attribute.  Also
note that during validation, this element will automatically convert any
existing 'NAME' attribute to be a 'VALUE' attribute.

PERLCORE
--------

   Child of IMPLEMENTATION, used to specify the minimum version of the
Perl core distribution that this Perl Package is to be used with.  Only
one instance should be present.  The PERLCORE element allows for the
following attributes:

VERSION
     Version of the Perl core that is required for this implementation of
     the Perl Package.

PROCESSOR
---------

   Child of IMPLEMENTATION, outlining the cpu required for this
implementation of the Perl Package.  Only one instance should be present.
The PROCESSOR element allows for the following attributes:

VALUE
     CPU required for the installation of this implementation of the Perl
     Package.  The following values are all valid according to the OSD
     Specification:

          x86 alpha mips sparc 680x0

   Note that previous versions of the PPD format used a 'NAME' attribute.
It's use has been deprecated in preference of the 'VALUE' attribute.  Also
note that during validation, this element will automatically convert any
existing 'NAME' attribute to be a 'VALUE' attribute.

CODEBASE
--------

   Child of IMPLEMENTATION, indicating a location where an archive of the
Perl Package can be retrieved.  Multiple instances are valid, and can be
used to indicate multiple possible locations where the same version of the
Perl Package can be retrieved.  The CODEBASE element allows for the
following attributes:

FILENAME
     ???

HREF
     Required attribute.  A reference to the location of the Perl Package
     distribution.

INSTALL
-------

   Child of IMPLEMENTATION, used to provide either a reference to an
installation script or a series of commands which can be used to install
the Perl Package once it has been retrieved.  If the EXEC attribute is not
specified, the value is assumed to be one or more commands, separated by
`;;'.  Each such command will be executed by the Perl `system()' function.
Only one instance should be present.  The INSTALL element allows for the
following attributes:

HREF
     Reference to an external script which should be retrieved and run as
     part of the installation process.  Both filenames and URLs should be
     considered valid.

EXEC
     Name of interpreter/shell used to execute the installation script.
     If the value of EXEC is `PPM_PERL', the copy of Perl that is executing
     PPM itself ($^X) is used to execute the install script.

UNINSTALL
---------

   Child of IMPLEMENTATION, used to provide either a reference to an
uninstallation script or a raw Perl script which can be used to uninstall
the Perl Package at a later point.  Only one instance should be present.
The UNINSTALL element allows for the following attributs:

HREF
     Reference to an external script which should be retrieved and run as
     part of the removal process.  Both filenames and URLs should be
     considered valid.

EXEC
     Name of interpreter/shell used to execute the uninstallation script.
     If the value of EXEC is `PPM_PERL', the copy of Perl that is executing
     PPM itself ($^X) is used to execute the install script.

DOCUMENT TYPE DEFINITION
========================

   The DTD for PPD documents is available from the ActiveState website and
the latest version can be found at
http://www.ActiveState.com/PPM/DTD/ppd.dtd

   This revision of the `XML::PPD' module implements the following DTD:

     <!ELEMENT SOFTPKG   (ABSTRACT | AUTHOR | IMPLEMENTATION | LICENSE | TITLE)*>
     <!ATTLIST SOFTPKG   NAME    CDATA #REQUIRED
                         VERSION CDATA #IMPLIED>

     <!ELEMENT TITLE     (#PCDATA)>

     <!ELEMENT ABSTRACT  (#PCDATA)>

     <!ELEMENT AUTHOR    (#PCDATA)>

     <!ELEMENT LICENSE   EMPTY>
     <!ATTLIST LICENSE   HREF     CDATA #REQUIRED>

     <!ELEMENT IMPLEMENTATION    (CODEBASE | DEPENDENCY | LANGUAGE | OS |
                                  OSVERSION | PERLCORE | PROCESSOR | INSTALL |
                                  UNINSTALL) *>

     <!ELEMENT CODEBASE  EMPTY>
     <!ATTLIST CODEBASE  FILENAME CDATA #IMPLIED
                         HREF     CDATA #REQUIRED>

     <!ELEMENT DEPENDENCY EMPTY>
     <!ATTLIST DEPENDENCY VERSION CDATA #IMPLIED
                          NAME CDATA #REQUIRED>

     <!ELEMENT LANGUAGE  EMPTY>
     <!ATTLIST LANGUAGE  VALUE CDATA #REQUIRED>

     <!ELEMENT OS        EMPTY>
     <!ATTLIST OS        VALUE CDATA #REQUIRED>

     <!ELEMENT OSVERSION EMPTY>
     <!ATTLIST OSVERSION VALUE CDATA #REQUIRED>

     <!ELEMENT PERLCORE  EMPTY>
     <!ATTLIST PERLCORE  VERSION CDATA #REQUIRED>

     <!ELEMENT PROCESSOR EMPTY>
     <!ATTLIST PROCESSOR VALUE CDATA #REQUIRED>

     <!ELEMENT INSTALL   (#PCDATA)>
     <!ATTLIST INSTALL   HREF  CDATA #IMPLIED
                         EXEC  CDATA #IMPLIED>

     <!ELEMENT UNINSTALL (#PCDATA)>
     <!ATTLIST UNINSTALL HREF  CDATA #IMPLIED
                         EXEC  CDATA #IMPLIED>

SAMPLE PPD FILE
===============

   The following is a sample PPD file describing the `Math-MatrixBool'
module.  Note that this may not be a current/proper description of this
module and is for sample purposes only.

     <SOFTPKG NAME="Math-MatrixBool" VERSION="4,2,0,0">
         <TITLE>Math-MatrixBool</TITLE>
         <ABSTRACT>Easy manipulation of matrices of booleans (Boolean Algebra)</ABSTRACT>
         <AUTHOR>Steffen Beyer (sb@sdm.de)</AUTHOR>
         <LICENSE HREF="http://www.ActiveState.com/packages/Math-MatrixBool/license.html" />
         <IMPLEMENTATION>
             <OS VALUE="WinNT" />
             <OS VALUE="Win95" />
             <PROCESSOR VALUE="x86" />
             <CODEBASE HREF="http://www.ActiveState.com/packages/Math-MatrixBool/Math-MatrixBool-4.2-bin-1-Win32.tar.gz" />
             <DEPENDENCY NAME="Bit-Vector" />
             <INSTALL>
             </INSTALL>
             <UNINSTALL>
             </UNINSTALL>
         </IMPLEMENTATION>

     <IMPLEMENTATION>
         <DEPENDENCY NAME="Bit-Vector" />
         <CODEBASE HREF="&CPAN;/CPAN/modules/by-module/Math/Math-MatrixBool-4.2.tar.gz" />
         <INSTALL>
             system("make"); ;;
             system("make test"); ;;
             system("make install"); ;;
         </INSTALL>
     </IMPLEMENTATION>
      </SOFTPKG>

KNOWN BUGS/ISSUES
=================

   Elements which are required to be empty (e.g. LICENSE) are not enforced
as such.

   Notations above about elements for which "only one instance" or
"multiple instances" are valid are not enforced; this primarily a
guideline for generating your own PPD files.

AUTHORS
=======

   Graham TerMarsch <grahamt@ActiveState.com>

   Murray Nesbitt <murrayn@ActiveState.com>

   Dick Hardt <dick_hardt@ActiveState.com>

HISTORY
=======

   v0.1 - Initial release

SEE ALSO
========

   `XML::ValidatingElement' in this node, see XML/Element,
XML/Parser, OSD Specification
(http://www.microsoft.com/standards/osd/)

PPMConfig file format and XML parsing elements
**********************************************

NAME
====

   XML::PPMConfig - PPMConfig file format and XML parsing elements

SYNOPSIS
========

     use XML::Parser;
     use XML::PPMConfig;

     $p = new XML::Parser( Style => 'Objects', Pkg => 'XML::PPMConfig' );
     ...

DESCRIPTION
===========

   This module provides a set of classes for parsing PPM configuration
files using the XML::Parser module.  All of the elements unique to a PPM
configuration file are derived from `XML::ValidatingElement'. There are
also several classes rebuilt here which are derived from elements in
`XML::PPD' as we can include a PPD file within our own INSTPPD element.

MAJOR ELEMENTS
==============

PPMCONFIG
---------

   Defines a PPM configuration file.  The root of a PPMConfig document is
always a PPMCONFIG element.

PACKAGE
-------

   Child of PPMCONFIG, used to describe a Perl Package which has already
been installed.  Multiple instances are valid.  The PACKAGE element allows
for the following attributes:

NAME
     Name of the package as given in it's PPD

MINOR ELEMENTS
==============

PPMVER
------

   Child of PPMCONFIG, used to state the version of PPM for which this
configuration file is valid.  A single instance should be present.

PLATFORM
--------

   Child of PPMCONFIG, used to specify the platform of the target machine.
A single instance should be present.  The PLATFORM element allows for the
following attributes:

OSVALUE
     Description of the local operating system as defined in the Config.pm
     file under 'osname'.

OSVERSION
     Version of the local operating system.

CPU
     Description of the CPU in the local system.  The following list of
     possible values was taken from the OSD Specification:

          x86 mips alpha ppc sparc 680x0

LANGUAGE
     Description of the language used on the local system as specified by
     the language codes in ISO 639.

REPOSITORY
----------

   Child of PPMCONFIG, used to specify a repository where Perl Packages
can be found.  Multiple instances are valid.  The REPOSITORY element
allows for the following attributes:

NAME
     Name by which the repository will be known (e.g.  "ActiveState").

LOCATION
     An URL or directory where the repository can be found.

USERNAME
     Optional username for a repository requiring authenticated connection.

PASSWORD
     Optional password for a repository requiring authenticated connection.

SUMMARYFILE
     Optional package summary filename.

     If this file exists on the repository, its contents can be retrieved
     using PPM::RepositorySummary().  The contents are not strictly
     enforced by PPM.pm, however ppm.pl expects this to be a file with the
     following format (for display with the 'summary' command):

     Agent [2.91]:   supplies agentspace methods for perl5.
     Apache-OutputChain [0.06]:      chain stacked Perl handlers [etc.]

OPTIONS
-------

   Child of PPMCONFIG, used to specify the current configuration options
for PPM.  A single instance should be present.  The OPTIONS element allows
for the following attributes:

IGNORECASE
     Sets case-sensitive searching.  Can be either '1' or '0'.

CLEAN
     Sets removal of temporarily files.  Can be either '1' or '0'.

CONFIRM
     Sets confirmation of all installs/removals/upgrades.  Can be either
     '1' or '0'.

BUILDDIR
     Directory in which packages will be unpacked before their
     installation.

ROOT
     Directory under which packages should be installed on the local
     system.

TRACE
     Level of tracing (0 is no tracing, 4 is max tracing).

TRACEFILE
     File to which trace information will be written.

VERBOSE
     Controls whether query and search results are verbose (1 == verbose,
     0 == no).

PPMPRECIOUS
-----------

   Child of PPMCONFIG, used to specify the modules which PPM itself is
dependant upon.  A single instance should be present.

LOCATION
--------

   Child of PACKAGE, used to specify locations at which to search for
updated versions of the PPD file for this package.  Its value can be
either a directory or an Internet address.  A single instance should be
present.

INSTDATE
--------

   Child of PACKAGE, used to specify the date on which the Perl Package was
installed.  A single instance should be present.

INSTROOT
--------

   Child of PACKAGE, used to specify the root directory that the Perl
Package was installed into.  A single instance should be present.

INSTPACKLIST
------------

   Child of PACKAGE, used to specify a reference to the packlist for this
Perl Package; a file containing a list of all of the files which were
installed.  A single instance should be present.

INSTPPD
-------

   Child of PACKAGE, used to hold a copy of the PPD from which Perl
Packages were installed.  Multiple instances are valid.

DOCUMENT TYPE DEFINITION
========================

   The DTD for PPMConfig documents is available from the ActiveState
website and the latest version can be found at:
http://www.ActiveState.com/PPM/DTD/ppmconfig.dtd

   This revision of the `XML::PPMConfig' module implements the following
DTD:

     <!ELEMENT PPMCONFIG (PPMVER | PLATFORM | REPOSITORY | OPTIONS |
                          PPMPRECIOUS | PACKAGE)*>

     <!ELEMENT PPMVER   (#PCDATA)>

     <!ELEMENT PLATFORM  EMPTY>
     <!ATTLIST PLATFORM  OSVALUE     CDATA   #REQUIRED
                         OSVERSION   CDATA   #REQUIRED
                         CPU         CDATA   #REQUIRED
                         LANGUAGE    CDATA   #IMPLIED>

     <!ELEMENT REPOSITORY    EMPTY>
     <!ATTLIST REPOSITORY    NAME     CDATA  #REQUIRED
                             LOCATION CDATA  #REQUIRED
                             USERNAME CDATA  #IMPLIED
                             PASSWORD CDATA  #IMPLIED
                             SUMMARYFILE CDATA #IMPLIED>

     <!ELEMENT OPTIONS   EMPTY>
     <!ATTLIST OPTIONS   IGNORECASE      CDATA   #REQUIRED
                         CLEAN           CDATA   #REQUIRED
                         CONFIRM         CDATA   #REQUIRED
                         FORCEINSTALL    CDATA   #REQUIRED
                         ROOT            CDATA   #REQUIRED
                         BUILDDIR        CDATA   #REQUIRED
                         MORE            CDATA   #REQUIRED
                         TRACE           CDATA   #IMPLIED
                         TRACEFILE       CDATA   #IMPLIED>

     <!ELEMENT PPMPRECIOUS (#PCDATA)>

     <!ELEMENT PACKAGE   (LOCATION | INSTDATE | INSTROOT | INSTPACKLIST |
                          INSTPPD)*>
     <!ATTLIST PACKAGE   NAME    CDATA   #REQUIRED>

     <!ELEMENT LOCATION  (#PCDATA)>

     <!ELEMENT INSTDATE  (#PCDATA)>

     <!ELEMENT INSTROOT  (#PCDATA)>

     <!ELEMENT INSTPACKLIST (#PCDATA)>

     <!ELEMENT INSTPPD   (#PCDATA)>

SAMPLE PPMConfig FILE
=====================

   The following is a sample PPMConfig file.  Note that this may not be a
current description of this module and is for sample purposes only.

     <PPMCONFIG>
         <PPMVER>1,0,0,0</PPMVER>
         <PLATFORM CPU="x86" OSVALUE="MSWin32" OSVERSION="4,0,0,0" />
         <OPTIONS BUILDDIR="/tmp" CLEAN="1" CONFIRM="1" FORCEINSTALL="1"
                  IGNORECASE="0" MORE="0" ROOT="/usr/local" TRACE="0" TRACEFILE="" />
         <REPOSITORY LOCATION="http://www.ActiveState.com/packages"
                     NAME="ActiveState Package Repository" SUMMARYFILE="package.lst" />
         <PPMPRECIOUS>PPM;libnet;Archive-Tar;Compress-Zlib;libwww-perl</PPMPRECIOUS>
         <PACKAGE NAME="AtExit">
             <LOCATION>g:/packages</LOCATION>
             <INSTPACKLIST>c:/perllib/lib/site/MSWin32-x86/auto/AtExit/.packlist</INSTPACKLIST>
             <INSTROOT>c:/perllib</INSTROOT>
             <INSTDATE>Sun Mar  8 02:56:31 1998</INSTDATE>
             <INSTPPD>
                 <SOFTPKG NAME="AtExit" VERSION="1,02,0,0">
                     <TITLE>AtExit</TITLE>
                     <ABSTRACT>Register a subroutine to be invoked at program -exit time.</ABSTRACT>
                     <AUTHOR>Brad Appleton (Brad_Appleton-GBDA001@email.mot.com)</AUTHOR>
                     <IMPLEMENTATION>
                         <CODEBASE HREF="x86/AtExit.tar.gz" />
                     </IMPLEMENTATION>
                 </SOFTPKG>
             </INSTPPD>
         </PACKAGE>
     </PPMCONFIG>

KNOWN BUGS/ISSUES
=================

   Elements which are required to be empty (e.g. REPOSITORY) are not
enforced as such.

   Notations above about elements for which "only one instance" or
"multiple instances" are valid are not enforced; this primarily a
guideline for generating your own PPD files.

   Currently, this module creates new classes within it's own namespace
for all of the PPD elements which can be contained within the INSTPPD
element.  A suitable method for importing the entire XML::PPD:: namespace
should be found in order to make this cleaner.

AUTHORS
=======

   Graham TerMarsch <grahamt@ActiveState.com>

   Murray Nesbitt <murrayn@ActiveState.com>

   Dick Hardt <dick_hardt@ActiveState.com>

HISTORY
=======

   v0.1 - Initial release

SEE ALSO
========

   `XML::ValidatingElement' in this node, see XML/Parser,
XML/PPD, .

XML to PYX generator
********************

NAME
====

   XML::PYX - XML to PYX generator

SYNOPSIS
========

     use XML::PYX;
     my $parser = XML::PYX::Parser->new;
     my $string = $parser->parsefile($filename);

DESCRIPTION
===========

   After reading about PYX on XML.com, I thought it was a pretty cool idea,
so I built this, to generate PYX from XML using perl. See
http://www.xml.com/pub/2000/03/15/feature/index.html for an excellent
introduction.

   The package contains 2 usable packages, and 3 utilities that are
probably currently more use than the module:

     pyx - a XML to PYX converter using XML::Parser
     pyxv - a Validating XML to PYX converter using XML::Checker::Parser
     pyxw - a PYX to XML converter
     pyxhtml - an HTML to PYX converter using HTML::TreeBuilder

   All these utilities can be pipelined together, so you can have:

     pyx test.xml | grep -v "^-" | pyxw > new.xml

   Which should remove all text from an XML file (leaving only tags).

   The 2 packages are XML::PYX::Parser and XML::PYX::Parser::ToCSF. The
former is a direct subclass of XML::Parser that simply returns a PYX
string on a call to parse or parsefile. The latter stands for *To
Currently Selected Filehandle*. Instead of returning a string, it sends
output directly to the currently selected filehandle. This is much better
for pipelined utilities for obvious reasons.

   There's a special variable: $XML::PYX::Lame. Set it to 1 to use a "Lame"
parser that simply uses regexps. This is useful, for example, if you are
changing the input to invalid XML for some reason. You can then use
$XML::PYX::Lame = 1 to enable the non-xml parser. It does check for some
things, like balanced tags, but otherwise it's pretty lame :)

   Lame mode is enabled for pyx and pyxw with the -l option.

AUTHOR
======

   Matt Sergeant, matt@sergeant.org

A perl module for parsing XML documents
***************************************

NAME
====

   XML::Parser - A perl module for parsing XML documents

SYNOPSIS
========

     use XML::Parser;

     $p1 = new XML::Parser(Style => 'Debug');
     $p1->parsefile('REC-xml-19980210.xml');
     $p1->parse('<foo id="me">Hello World</foo>');

     # Alternative
     $p2 = new XML::Parser(Handlers => {Start => \&handle_start,
     				     End   => \&handle_end,
     				     Char  => \&handle_char});
     $p2->parse($socket);

     # Another alternative
     $p3 = new XML::Parser(ErrorContext => 2);

     $p3->setHandlers(Char    => \&text,
     		   Default => \&other);

     open(FOO, 'xmlgenerator |');
     $p3->parse(*FOO, ProtocolEncoding => 'ISO-8859-1');
     close(FOO);

     $p3->parsefile('junk.xml', ErrorContext => 3);

DESCRIPTION
===========

   This module provides ways to parse XML documents. It is built on top of
XML/Parser/Expat, which is a lower level
interface to James Clark's expat library. Each call to one of the parsing
methods creates a new instance of XML::Parser::Expat which is then used to
parse the document.  Expat options may be provided when the XML::Parser
object is created.  These options are then passed on to the Expat object
on each parse call.  They can also be given as extra arguments to the
parse methods, in which case they override options given at XML::Parser
creation time.

   The behavior of the parser is controlled either by ``' in this node'
and/or ``' in this node' options, or by `' in this node method. These all
provide mechanisms for XML::Parser to set the handlers needed by
XML::Parser::Expat.  If neither Style nor Handlers are specified, then
parsing just checks the document for being well-formed.

   When underlying handlers get called, they receive as their first
parameter the *Expat* object, not the Parser object.

METHODS
=======

new
     This is a class method, the constructor for XML::Parser. Options are
     passed as keyword value pairs. Recognized options are:

        * Style

          This option provides an easy way to create a given style of
          parser. The built in styles are: `"Debug"' in this node,
          `"Subs"' in this node, `"Tree"' in this node, `"Objects"' in
          this node, and `"Stream"' in this node.  Custom styles can be
          provided by giving a full package name containing at least one
          '::'. This package should then have subs defined for each
          handler it wishes to have installed. See `"STYLES"' in this node
          below for a discussion of each built in style.

        * Handlers

          When provided, this option should be an anonymous hash
          containing as keys the type of handler and as values a sub
          reference to handle that type of event. All the handlers get
          passed as their 1st parameter the instance of expat that is
          parsing the document. Further details on handlers can be found
          in `"HANDLERS"' in this node. Any handler set here overrides the
          corresponding handler set with the Style option.

        * Pkg

          Some styles will refer to subs defined in this package. If not
          provided, it defaults to the package which called the
          constructor.

        * ErrorContext

          This is an Expat option. When this option is defined, errors are
          reported in context. The value should be the number of lines to
          show on either side of the line in which the error occurred.

        * ProtocolEncoding

          This is an Expat option. This sets the protocol encoding name.
          It defaults to none. The built-in encodings are: `UTF-8',
          `ISO-8859-1', `UTF-16', and `US-ASCII'. Other encodings may be
          used if they have encoding maps in one of the directories in the
          @Encoding_Path list. Check `"ENCODINGS"' in this node for more
          information on encoding maps. Setting the protocol encoding
          overrides any encoding in the XML declaration.

        * Namespaces

          This is an Expat option. If this is set to a true value, then
          namespace processing is done during the parse. See
          `"Namespaces"', see XML/Parser/Expat, for
          further discussion of namespace processing.

        * NoExpand

          This is an Expat option. Normally, the parser will try to expand
          references to entities defined in the internal subset. If this
          option is set to a true value, and a default handler is also
          set, then the default handler will be called when an entity
          reference is seen in text. This has no effect if a default
          handler has not been registered, and it has no effect on the
          expansion of entity references inside attribute values.

        * Stream_Delimiter

          This is an Expat option. It takes a string value. When this
          string is found alone on a line while parsing from a stream,
          then the parse is ended as if it saw an end of file. The
          intended use is with a stream of xml documents in a MIME
          multipart format. The string should not contain a trailing
          newline.

        * ParseParamEnt

          This is an Expat option. Unless standalone is set to "yes" in
          the XML declaration, setting this to a true value allows the
          external DTD to be read, and parameter entities to be parsed and
          expanded.

        * NoLWP

          This option has no effect if the ExternEnt or ExternEntFin
          handlers are directly set. Otherwise, if true, it forces the use
          of a file based external entity handler.

        * Non-Expat-Options

          If provided, this should be an anonymous hash whose keys are
          options that shouldn't be passed to Expat. This should only be
          of concern to those subclassing XML::Parser.

setHandlers(TYPE, HANDLER [, TYPE, HANDLER [...]])
     This method registers handlers for various parser events. It
     overrides any previous handlers registered through the Style or
     Handler options or through earlier calls to setHandlers. By providing
     a false or undefined value as the handler, the existing handler can
     be unset.

     This method returns a list of type, handler pairs corresponding to the
     input. The handlers returned are the ones that were in effect prior to
     the call.

     See a description of the handler types in `"HANDLERS"' in this node.

parse(SOURCE [, OPT => OPT_VALUE [...]])
     The SOURCE parameter should either be a string containing the whole
     XML document, or it should be an open IO::Handle. Constructor options
     to XML::Parser::Expat given as keyword-value pairs may follow the
     SOURCE parameter. These override, for this call, any options or
     attributes passed through from the XML::Parser instance.

     A die call is thrown if a parse error occurs. Otherwise it will
     return 1 or whatever is returned from the Final handler, if one is
     installed.  In other words, what parse may return depends on the
     style.

parsestring
     This is just an alias for parse for backwards compatibility.

parsefile(FILE [, OPT => OPT_VALUE [...]])
     Open FILE for reading, then call parse with the open handle. The file
     is closed no matter how parse returns. Returns what parse returns.

parse_start([ OPT => OPT_VALUE [...]])
     Create and return a new instance of XML::Parser::ExpatNB. Constructor
     options may be provided. If an init handler has been provided, it is
     called before returning the ExpatNB object. Documents are parsed by
     making incremental calls to the parse_more method of this object,
     which takes a string. A single call to the parse_done method of this
     object, which takes no arguments, indicates that the document is
     finished.

     If there is a final handler installed, it is executed by the
     parse_done method before returning and the parse_done method returns
     whatever is returned by the final handler.

HANDLERS
========

   Expat is an event based parser. As the parser recognizes parts of the
document (say the start or end tag for an XML element), then any handlers
registered for that type of an event are called with suitable parameters.
All handlers receive an instance of XML::Parser::Expat as their first
argument. See `"METHODS"', see XML/Parser/Expat, for a
discussion of the methods that can be called on this object.

Init		(Expat)
-------------

   This is called just before the parsing of the document starts.

Final		(Expat)
--------------

   This is called just after parsing has finished, but only if no errors
occurred during the parse. Parse returns what this returns.

Start		(Expat, Element [, Attr, Val [,...]])
--------------------------------------------

   This event is generated when an XML start tag is recognized. Element is
the name of the XML element type that is opened with the start tag. The
Attr & Val pairs are generated for each attribute in the start tag.

End		(Expat, Element)
---------------------

   This event is generated when an XML end tag is recognized. Note that an
XML empty tag (<foo/>) generates both a start and an end event.

Char		(Expat, String)
---------------------

   This event is generated when non-markup is recognized. The non-markup
sequence of characters is in String. A single non-markup sequence of
characters may generate multiple calls to this handler. Whatever the
encoding of the string in the original document, this is given to the
handler in UTF-8.

Proc		(Expat, Target, Data)
---------------------------

   This event is generated when a processing instruction is recognized.

Comment		(Expat, Data)
----------------------

   This event is generated when a comment is recognized.

CdataStart	(Expat)
------------------

   This is called at the start of a CDATA section.

CdataEnd		(Expat)
-----------------

   This is called at the end of a CDATA section.

Default		(Expat, String)
------------------------

   This is called for any characters that don't have a registered handler.
This includes both characters that are part of markup for which no events
are generated (markup declarations) and characters that could generate
events, but for which no handler has been registered.

   Whatever the encoding in the original document, the string is returned
to the handler in UTF-8.

Unparsed		(Expat, Entity, Base, Sysid, Pubid, Notation)
-------------------------------------------------------

   This is called for a declaration of an unparsed entity. Entity is the
name of the entity. Base is the base to be used for resolving a relative
URI.  Sysid is the system id. Pubid is the public id. Notation is the
notation name. Base and Pubid may be undefined.

Notation		(Expat, Notation, Base, Sysid, Pubid)
-----------------------------------------------

   This is called for a declaration of notation. Notation is the notation
name.  Base is the base to be used for resolving a relative URI. Sysid is
the system id. Pubid is the public id. Base, Sysid, and Pubid may all be
undefined.

ExternEnt	(Expat, Base, Sysid, Pubid)
-------------------------------------

   This is called when an external entity is referenced. Base is the base
to be used for resolving a relative URI. Sysid is the system id. Pubid is
the public id. Base, and Pubid may be undefined.

   This handler should either return a string, which represents the
contents of the external entity, or return an open filehandle that can be
read to obtain the contents of the external entity, or return undef, which
indicates the external entity couldn't be found and will generate a parse
error.

   If an open filehandle is returned, it must be returned as either a glob
(*FOO) or as a reference to a glob (e.g. an instance of IO::Handle).

   A default handler is installed for this event. The default handler is
XML::Parser::lwp_ext_ent_handler unless the NoLWP option was provided with
a true value, otherwise XML::Parser::file_ext_ent_handler is the default
handler for external entities. Even without the NoLWP option, if the URI
or LWP modules are missing, the file based handler ends up being used
after giving a warning on the first external entity reference.

   The LWP external entity handler will use proxies defined in the
environment (http_proxy, ftp_proxy, etc.).

   Please note that the LWP external entity handler reads the entire
entity into a string and returns it, where as the file handler opens a
filehandle.

   Also note that the file external entity handler will likely choke on
absolute URIs or file names that don't fit the conventions of the local
operating system.

   The expat base method can be used to set a basename for relative
pathnames. If no basename is given, or if the basename is itself a
relative name, then it is relative to the current working directory.

ExternEntFin	(Expat)
--------------------

   This is called after parsing an external entity. It's not called unless
an ExternEnt handler is also set. There is a default handler installed
that pairs with the default ExternEnt handler.

   If you're going to install your own ExternEnt handler, then you should
set (or unset) this handler too.

Entity		(Expat, Name, Val, Sysid, Pubid, Ndata, IsParam)
--------------------------------------------------------

   This is called when an entity is declared. For internal entities, the
Val parameter will contain the value and the remaining three parameters
will be undefined. For external entities, the Val parameter will be
undefined, the Sysid parameter will have the system id, the Pubid
parameter will have the public id if it was provided (it will be undefined
otherwise), the Ndata parameter will contain the notation for unparsed
entities. If this is a parameter entity declaration, then the IsParam
parameter is true.

   Note that this handler and the Unparsed handler above overlap. If both
are set, then this handler will not be called for unparsed entities.

Element		(Expat, Name, Model)
-----------------------------

   The element handler is called when an element declaration is found. Name
is the element name, and Model is the content model as an
XML::Parser::Content object. See `"XML::Parser::ContentModel Methods"',
see XML/Parser/Expat, for methods available for this
class.

Attlist		(Expat, Elname, Attname, Type, Default, Fixed)
-------------------------------------------------------

   This handler is called for each attribute in an ATTLIST declaration.
So an ATTLIST declaration that has multiple attributes will generate
multiple calls to this handler. The Elname parameter is the name of the
element with which the attribute is being associated. The Attname
parameter is the name of the attribute. Type is the attribute type, given
as a string. Default is the default value, which will either be
"#REQUIRED", "#IMPLIED" or a quoted string (i.e. the returned string will
begin and end with a quote character).  If Fixed is true, then this is a
fixed attribute.

Doctype		(Expat, Name, Sysid, Pubid, Internal)
----------------------------------------------

   This handler is called for DOCTYPE declarations. Name is the document
type name. Sysid is the system id of the document type, if it was provided,
otherwise it's undefined. Pubid is the public id of the document type,
which will be undefined if no public id was given. Internal is the internal
subset, given as a string. If there was no internal subset, it will be
undefined. Internal will contain all whitespace, comments, processing
instructions, and declarations seen in the internal subset. The
declarations will be there whether or not they have been processed by
another handler (except for unparsed entities processed by the Unparsed
handler). However, comments and processing instructions will not appear if
they've been processed by their respective handlers.

* DoctypeFin		(Parser)
----------------------

   This handler is called after parsing of the DOCTYPE declaration has
finished, including any internal or external DTD declarations.

XMLDecl		(Expat, Version, Encoding, Standalone)
-----------------------------------------------

   This handler is called for xml declarations. Version is a string
containg the version. Encoding is either undefined or contains an encoding
string.  Standalone will be either true, false, or undefined if the
standalone attribute is yes, no, or not made respectively.

STYLES
======

Debug
-----

   This just prints out the document in outline form. Nothing special is
returned by parse.

Subs
----

   Each time an element starts, a sub by that name in the package specified
by the Pkg option is called with the same parameters that the Start
handler gets called with.

   Each time an element ends, a sub with that name appended with an
underscore ("_"), is called with the same parameters that the End handler
gets called with.

   Nothing special is returned by parse.

Tree
----

   Parse will return a parse tree for the document. Each node in the tree
takes the form of a tag, content pair. Text nodes are represented with a
pseudo-tag of "0" and the string that is their content. For elements, the
content is an array reference. The first item in the array is a (possibly
empty) hash reference containing attributes. The remainder of the array is
a sequence of tag-content pairs representing the content of the element.

   So for example the result of parsing:

     <foo><head id="a">Hello <em>there</em></head><bar>Howdy<ref/></bar>do</foo>

   would be:              Tag   Content
==================================================================   [foo,
[{}, head, [{id => "a"}, 0, "Hello ",  em, [{}, 0, "there"]],
bar, [         {}, 0, "Howdy",  ref, [{}]], 	        0, "do" 	]   ]

   The root document "foo", has 3 children: a "head" element, a "bar"
element and the text "do". After the empty attribute hash, these are
represented in it's contents by 3 tag-content pairs.

Objects
-------

   This is similar to the Tree style, except that a hash object is created
for each element. The corresponding object will be in the class whose name
is created by appending "::" and the element name to the package set with
the Pkg option. Non-markup text will be in the ::Characters class. The
contents of the corresponding object will be in an anonymous array that is
the value of the Kids property for that object.

Stream
------

   This style also uses the Pkg package. If none of the subs that this
style looks for is there, then the effect of parsing with this style is to
print a canonical copy of the document without comments or declarations.
All the subs receive as their 1st parameter the Expat instance for the
document they're parsing.

   It looks for the following routines:

   * StartDocument

     Called at the start of the parse .

   * StartTag

     Called for every start tag with a second parameter of the element
     type. The $_ variable will contain a copy of the tag and the %_
     variable will contain attribute values supplied for that element.

   * EndTag

     Called for every end tag with a second parameter of the element type.
     The $_ variable will contain a copy of the end tag.

   * Text

     Called just before start or end tags with accumulated non-markup text
     in the $_ variable.

   * PI

     Called for processing instructions. The $_ variable will contain a
     copy of the PI and the target and data are sent as 2nd and 3rd
     parameters respectively.

   * EndDocument

     Called at conclusion of the parse.

ENCODINGS
=========

   XML documents may be encoded in character sets other than Unicode as
long as they may be mapped into the Unicode character set. Expat has
further restrictions on encodings. Read the xmlparse.h header file in the
expat distribution to see details on these restrictions.

   Expat has built-in encodings for: `UTF-8', `ISO-8859-1', `UTF-16', and
`US-ASCII'. Encodings are set either through the XML declaration encoding
attribute or through the ProtocolEncoding option to XML::Parser or
XML::Parser::Expat.

   For encodings other than the built-ins, expat calls the function
load_encoding in the Expat package with the encoding name. This function
looks for a file in the path list @XML::Parser::Expat::Encoding_Path, that
matches the lower-cased name with a '.enc' extension. The first one it
finds, it loads.

   If you wish to build your own encoding maps, check out the XML::Encoding
module from CPAN.

AUTHORS
=======

   Larry Wall <`larry@wall.org'> wrote version 1.0.

   Clark Cooper <`coopercc@netheaven.com'> picked up support, changed the
API for this version (2.x), provided documentation, and added some
standard package features.

Easier tree style for XML::Parser
*********************************

NAME
====

   XML::Parser::EasyTree - Easier tree style for XML::Parser

SYNOPSIS
========

     use XML::Parser;
     use XML::Parser::EasyTree;
     $XML::Parser::Easytree::Noempty=1;
     my $p=new XML::Parser(Style=>'EasyTree');
     my $tree=$p->parsefile('something.xml');

DESCRIPTION
===========

   XML::Parser::EasyTree adds a new "built-in" style called "EasyTree" to
XML::Parser.  Like XML::Parser's "Tree" style, setting this style causes
the parser to build a lightweight tree structure representing the XML
document.  This structure is, at least in this author's opinion, easier to
work with than the one created by the built-in style.

   When the parser is invoked with the EasyTree style, it returns a
reference to an array of tree nodes, each of which is a hash reference.
All nodes have a 'type' key whose value is the type of the node: 'e' for
element nodes, 't' for text nodes, and 'p' for processing instruction
nodes.  All nodes also have a 'content' key whose value is a reference to
an array holding the element's child nodes for element nodes, the string
value for text nodes, and the data value for processing instruction nodes.
Element nodes also have an 'attrib' key whose value is a reference to a
hash of attribute names and values.  Processing instructions also have a
'target' key whose value is the PI's target.

   EasyTree nodes are ordinary Perl hashes and are not objects.  Contiguous
runs of text are always returned in a single node.

   The reason the parser returns an array reference rather than the root
element's node is that an XML document can legally contain processing
instructions outside the root element (the xml-stylesheet PI is commonly
used this way).

   If the parser's Namespaces option is set, element and attribute names
will be prefixed with their (possibly empty) namespace URI enclosed in
curly brackets.

SPECIAL VARIABLES
=================

   Two package global variables control special behaviors:

XML::Parser::EasyTree::Latin
     If this is set to a nonzero value, all text, names, and values will be
     returned in ISO-8859-1 (Latin-1) encoding rather than UTF-8.

XML::Parser::EasyTree::Noempty
     If this is set to a nonzero value, text nodes containing nothing but
     whitespace (such as those generated by line breaks and indentation
     between tags) will be omitted from the parse tree.

EXAMPLE
=======

   Parse a prettyprined version of the XML shown in the example for the
built-in "Tree" style:

     #!perl -w
     use strict;
     use XML::Parser;
     use XML::Parser::EasyTree;
     use Data::Dumper;

     $XML::Parser::EasyTree::Noempty=1;
     my $xml=<<'EOF';
     <foo>
       <head id="a">Hello <em>there</em>
       </head>
       <bar>Howdy<ref/>
       </bar>
       do
     </foo>
     EOF
     my $p=new XML::Parser(Style=>'EasyTree');
     my $tree=$p->parse($xml);
     print Dumper($tree);

   Returns:

     $VAR1 = [
             { 'name' => 'foo',
               'type' => 'e',
               'content' => [
                              { 'name' => 'head',
                                'type' => 'e',
                                'content' => [
                                               { 'type' => 't',
                                                 'content' => 'Hello '
                                               },
                                               { 'name' => 'em',
                                                 'type' => 'e',
                                                 'content' => [
                                                                { 'type' => 't',
                                                                  'content' => 'there'
                                                                }
                                                              ],
                                                 'attrib' => {}
                                               }
                                             ],
                                'attrib' => { 'id' => 'a'
                                            }
                              },
                              { 'name' => 'bar',
                                'type' => 'e',
                                'content' => [
                                               { 'type' => 't',
                                                 'content' => 'Howdy'
                                               },
                                               { 'name' => 'ref',
                                                 'type' => 'e',
                                                 'content' => [],
                                                 'attrib' => {}
                                               }
                                             ],
                                'attrib' => {}
                              },
                              { 'type' => 't',
                                'content' => '
     do
      '
                              }
                            ],
               'attrib' => {}
             }
           ];

AUTHOR
======

   Eric Bohlman (ebohlman@omsdev.com)

   Copyright (c) 2001 Eric Bohlman. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

     XML::Parser

Lowlevel access to James Clark's expat XML parser
*************************************************

NAME
====

   XML::Parser::Expat - Lowlevel access to James Clark's expat XML parser

SYNOPSIS
========

     use XML::Parser::Expat;

     $parser = new XML::Parser::Expat;
     $parser->setHandlers('Start' => \&sh,
     		      'End'   => \&eh,
                          'Char'  => \&ch);
     open(FOO, 'info.xml') or die "Couldn't open";
     $parser->parse(*FOO);
     close(FOO);
     # $parser->parse('<foo id="me"> here <em>we</em> go </foo>');

     sub sh
     {
       my ($p, $el, %atts) = @_;
       $p->setHandlers('Char' => \&spec)
         if ($el eq 'special');
       ...
     }

     sub eh
     {
       my ($p, $el) = @_;
       $p->setHandlers('Char' => \&ch)  # Special elements won't contain
         if ($el eq 'special');         # other special elements
       ...
     }

DESCRIPTION
===========

   This module provides an interface to James Clark's XML parser, expat.
As in expat, a single instance of the parser can only parse one document.
Calls to parsestring after the first for a given instance will die.

   Expat (and XML::Parser::Expat) are event based. As the parser recognizes
parts of the document (say the start or end of an XML element), then any
handlers registered for that type of an event are called with suitable
parameters.

METHODS
=======

new
     This is a class method, the constructor for XML::Parser::Expat.
     Options are passed as keyword value pairs. The recognized options are:

        * ProtocolEncoding

          The protocol encoding name. The default is none. The expat
          built-in encodings are: `UTF-8', `ISO-8859-1', `UTF-16', and
          `US-ASCII'.  Other encodings may be used if they have encoding
          maps in one of the directories in the @Encoding_Path list.
          Setting the protocol encoding overrides any encoding in the XML
          declaration.

        * Namespaces

          When this option is given with a true value, then the parser
          does namespace processing. By default, namespace processing is
          turned off. When it is turned on, the parser consumes *xmlns*
          attributes and strips off prefixes from element and attributes
          names where those prefixes have a defined namespace. A name's
          namespace can be found using the `"namespace"' in this node
          method and two names can be checked for absolute equality with
          the `"eq_name"' in this node method.

        * NoExpand

          Normally, the parser will try to expand references to entities
          defined in the internal subset. If this option is set to a true
          value, and a default handler is also set, then the default
          handler will be called when an entity reference is seen in text.
          This has no effect if a default handler has not been registered,
          and it has no effect on the expansion of entity references
          inside attribute values.

        * Stream_Delimiter

          This option takes a string value. When this string is found
          alone on a line while parsing from a stream, then the parse is
          ended as if it saw an end of file. The intended use is with a
          stream of xml documents in a MIME multipart format. The string
          should not contain a trailing newline.

        * ErrorContext

          When this option is defined, errors are reported in context. The
          value of ErrorContext should be the number of lines to show on
          either side of the line in which the error occurred.

        * ParseParamEnt

          Unless standalone is set to "yes" in the XML declaration,
          setting this to a true value allows the external DTD to be read,
          and parameter entities to be parsed and expanded.

        * Base

          The base to use for relative pathnames or URLs. This can also be
          done by using the base method.

setHandlers(TYPE, HANDLER [, TYPE, HANDLER [...]])
     This method registers handlers for the various events. If no handlers
     are registered, then a call to parsestring or parsefile will only
     determine if the corresponding XML document is well formed (by
     returning without error.)  This may be called from within a handler,
     after the parse has started.

     Setting a handler to something that evaluates to false unsets that
     handler.

     This method returns a list of type, handler pairs corresponding to the
     input. The handlers returned are the ones that were in effect before
     the call to setHandlers.

     The recognized events and the parameters passed to the corresponding
     handlers are:

        * Start		(Parser, Element [, Attr, Val [,...]])

          This event is generated when an XML start tag is recognized.
          Parser is an XML::Parser::Expat instance. Element is the name of
          the XML element that is opened with the start tag. The Attr &
          Val pairs are generated for each attribute in the start tag.

        * End		(Parser, Element)

          This event is generated when an XML end tag is recognized. Note
          that an XML empty tag (<foo/>) generates both a start and an end
          event.

          There is always a lower level start and end handler installed
          that wrap the corresponding callbacks. This is to handle the
          context mechanism.  A consequence of this is that the default
          handler (see below) will not see a start tag or end tag unless
          the default_current method is called.

        * Char		(Parser, String)

          This event is generated when non-markup is recognized. The
          non-markup sequence of characters is in String. A single
          non-markup sequence of characters may generate multiple calls to
          this handler. Whatever the encoding of the string in the
          original document, this is given to the handler in UTF-8.

        * Proc		(Parser, Target, Data)

          This event is generated when a processing instruction is
          recognized.

        * Comment		(Parser, String)

          This event is generated when a comment is recognized.

        * CdataStart	(Parser)

          This is called at the start of a CDATA section.

        * CdataEnd	(Parser)

          This is called at the end of a CDATA section.

        * Default		(Parser, String)

          This is called for any characters that don't have a registered
          handler.  This includes both characters that are part of markup
          for which no events are generated (markup declarations) and
          characters that could generate events, but for which no handler
          has been registered.

          Whatever the encoding in the original document, the string is
          returned to the handler in UTF-8.

        * Unparsed		(Parser, Entity, Base, Sysid, Pubid, Notation)

          This is called for a declaration of an unparsed entity. Entity
          is the name of the entity. Base is the base to be used for
          resolving a relative URI.  Sysid is the system id. Pubid is the
          public id. Notation is the notation name. Base and Pubid may be
          undefined.

        * Notation		(Parser, Notation, Base, Sysid, Pubid)

          This is called for a declaration of notation. Notation is the
          notation name.  Base is the base to be used for resolving a
          relative URI. Sysid is the system id. Pubid is the public id.
          Base, Sysid, and Pubid may all be undefined.

        * ExternEnt		(Parser, Base, Sysid, Pubid)

          This is called when an external entity is referenced. Base is
          the base to be used for resolving a relative URI. Sysid is the
          system id. Pubid is the public id. Base, and Pubid may be
          undefined.

          This handler should either return a string, which represents the
          contents of the external entity, or return an open filehandle
          that can be read to obtain the contents of the external entity,
          or return undef, which indicates the external entity couldn't be
          found and will generate a parse error.

          If an open filehandle is returned, it must be returned as either
          a glob (*FOO) or as a reference to a glob (e.g. an instance of
          IO::Handle).

        * ExternEntFin		(Parser)

          This is called after an external entity has been parsed. It
          allows applications to perform cleanup on actions performed in
          the above ExternEnt handler.

        * Entity			(Parser, Name, Val, Sysid, Pubid, Ndata, IsParam)

          This is called when an entity is declared. For internal
          entities, the Val parameter will contain the value and the
          remaining three parameters will be undefined. For external
          entities, the Val parameter will be undefined, the Sysid
          parameter will have the system id, the Pubid parameter will have
          the public id if it was provided (it will be undefined
          otherwise), the Ndata parameter will contain the notation for
          unparsed entities. If this is a parameter entity declaration,
          then the IsParam parameter is true.

          Note that this handler and the Unparsed handler above overlap.
          If both are set, then this handler will not be called for
          unparsed entities.

        * Element			(Parser, Name, Model)

          The element handler is called when an element declaration is
          found. Name is the element name, and Model is the content model
          as an XML::Parser::ContentModel object. See
          `"XML::Parser::ContentModel Methods"' in this node for methods
          available for this class.

        * Attlist			(Parser, Elname, Attname, Type, Default, Fixed)

          This handler is called for each attribute in an ATTLIST
          declaration.  So an ATTLIST declaration that has multiple
          attributes will generate multiple calls to this handler. The
          Elname parameter is the name of the element with which the
          attribute is being associated. The Attname parameter is the name
          of the attribute. Type is the attribute type, given as a string.
          Default is the default value, which will either be "#REQUIRED",
          "#IMPLIED" or a quoted string (i.e. the returned string will
          begin and end with a quote character). If Fixed is true, then
          this is a fixed attribute.

        * Doctype			(Parser, Name, Sysid, Pubid, Internal)

          This handler is called for DOCTYPE declarations. Name is the
          document type name. Sysid is the system id of the document type,
          if it was provided, otherwise it's undefined. Pubid is the
          public id of the document type, which will be undefined if no
          public id was given. Internal will be true or false, indicating
          whether or not the doctype declaration contains an internal
          subset.

        * DoctypeFin		(Parser)

          This handler is called after parsing of the DOCTYPE declaration
          has finished, including any internal or external DTD
          declarations.

        * XMLDecl			(Parser, Version, Encoding, Standalone)

          This handler is called for XML declarations. Version is a string
          containg the version. Encoding is either undefined or contains
          an encoding string.  Standalone is either undefined, or true or
          false. Undefined indicates that no standalone parameter was
          given in the XML declaration. True or false indicates "yes" or
          "no" respectively.

namespace(name)
     Return the URI of the namespace that the name belongs to. If the name
     doesn't belong to any namespace, an undef is returned. This is only
     valid on names received through the Start or End handlers from a
     single document, or through a call to the generate_ns_name method. In
     other words, don't use names generated from one instance of
     XML::Parser::Expat with other instances.

eq_name(name1, name2)
     Return true if name1 and name2 are identical (i.e. same name and from
     the same namespace.) This is only meaningful if both names were
     obtained through the Start or End handlers from a single document, or
     through a call to the generate_ns_name method.

generate_ns_name(name, namespace)
     Return a name, associated with a given namespace, good for using with
     the above 2 methods. The namespace argument should be the namespace
     URI, not a prefix.

new_ns_prefixes
     When called from a start tag handler, returns namespace prefixes
     declared with this start tag. If called elsewere (or if there were no
     namespace prefixes declared), it returns an empty list. Setting of
     the default namespace is indicated with '#default' as a prefix.

expand_ns_prefix(prefix)
     Return the uri to which the given prefix is currently bound. Returns
     undef if the prefix isn't currently bound. Use '#default' to find the
     current binding of the default namespace (if any).

current_ns_prefixes
     Return a list of currently bound namespace prefixes. The order of the
     the prefixes in the list has no meaning. If the default namespace is
     currently bound, '#default' appears in the list.

recognized_string
     Returns the string from the document that was recognized in order to
     call the current handler. For instance, when called from a start
     handler, it will give us the the start-tag string. The string is
     encoded in UTF-8.  This method doesn't return a meaningful string
     inside declaration handlers.

original_string
     Returns the verbatim string from the document that was recognized in
     order to call the current handler. The string is in the original
     document encoding. This method doesn't return a meaningful string
     inside declaration handlers.

default_current
     When called from a handler, causes the sequence of characters that
     generated the corresponding event to be sent to the default handler
     (if one is registered). Use of this method is deprecated in favor the
     recognized_string method, which you can use without installing a
     default handler. This method doesn't deliver a meaningful string to
     the default handler when called from inside declaration handlers.

xpcroak(message)
     Concatenate onto the given message the current line number within the
     XML document plus the message implied by ErrorContext. Then croak with
     the formed message.

xpcarp(message)
     Concatenate onto the given message the current line number within the
     XML document plus the message implied by ErrorContext. Then carp with
     the formed message.

current_line
     Returns the line number of the current position of the parse.

current_column
     Returns the column number of the current position of the parse.

current_byte
     Returns the current position of the parse.

base([NEWBASE]);
     Returns the current value of the base for resolving relative URIs. If
     NEWBASE is supplied, changes the base to that value.

context
     Returns a list of element names that represent open elements, with the
     last one being the innermost. Inside start and end tag handlers, this
     will be the tag of the parent element.

current_element
     Returns the name of the innermost currently opened element. Inside
     start or end handlers, returns the parent of the element associated
     with those tags.

in_element(NAME)
     Returns true if NAME is equal to the name of the innermost currently
     opened element. If namespace processing is being used and you want to
     check against a name that may be in a namespace, then use the
     generate_ns_name method to create the NAME argument.

within_element(NAME)
     Returns the number of times the given name appears in the context
     list.  If namespace processing is being used and you want to check
     against a name that may be in a namespace, then use the
     generate_ns_name method to create the NAME argument.

depth
     Returns the size of the context list.

element_index
     Returns an integer that is the depth-first visit order of the current
     element. This will be zero outside of the root element. For example,
     this will return 1 when called from the start handler for the root
     element start tag.

skip_until(INDEX)
     INDEX is an integer that represents an element index. When this method
     is called, all handlers are suspended until the start tag for an
     element that has an index number equal to INDEX is seen. If a start
     handler has been set, then this is the first tag that the start
     handler will see after skip_until has been called.

position_in_context(LINES)
     Returns a string that shows the current parse position. LINES should
     be an integer >= 0 that represents the number of lines on either side
     of the current parse line to place into the returned string.

xml_escape(TEXT [, CHAR [, CHAR ...]])
     Returns TEXT with markup characters turned into character entities.
     Any additional characters provided as arguments are also turned into
     character references where found in TEXT.

parse (SOURCE)
     The SOURCE parameter should either be a string containing the whole
     XML document, or it should be an open IO::Handle. Only a single
     document may be parsed for a given instance of XML::Parser::Expat, so
     this will croak if it's been called previously for this instance.

parsestring(XML_DOC_STRING)
     Parses the given string as an XML document. Only a single document
     may be parsed for a given instance of XML::Parser::Expat, so this
     will die if either parsestring or parsefile has been called for this
     instance previously.

     This method is deprecated in favor of the parse method.

parsefile(FILENAME)
     Parses the XML document in the given file. Will die if parsestring or
     parsefile has been called previously for this instance.

is_defaulted(ATTNAME)
     NO LONGER WORKS. To find out if an attribute is defaulted please use
     the specified_attr method.

specified_attr
     When the start handler receives lists of attributes and values, the
     non-defaulted (i.e. explicitly specified) attributes occur in the list
     first. This method returns the number of specified items in the list.
     So if this number is equal to the length of the list, there were no
     defaulted values. Otherwise the number points to the index of the
     first defaulted attribute name.

finish
     Unsets all handlers (including internal ones that set context), but
     expat continues parsing to the end of the document or until it finds
     an error.  It should finish up a lot faster than with the handlers
     set.

release
     There are data structures used by XML::Parser::Expat that have
     circular references. This means that these structures will never be
     garbage collected unless these references are explicitly broken.
     Calling this method breaks those references (and makes the instance
     unusable.)

     Normally, higher level calls handle this for you, but if you are using
     XML::Parser::Expat directly, then it's your responsibility to call it.

XML::Parser::ContentModel Methods
---------------------------------

   The element declaration handlers are passed objects of this class as the
content model of the element declaration. They also represent content
particles, components of a content model.

   When referred to as a string, these objects are automagicly converted
to a string representation of the model (or content particle).

isempty
     This method returns true if the object is "EMPTY", false otherwise.

isany
     This method returns true if the object is "ANY", false otherwise.

ismixed
     This method returns true if the object is "(#PCDATA)" or
     "(#PCDATA|...)*", false otherwise.

isname
     This method returns if the object is an element name.

ischoice
     This method returns true if the object is a choice of content
     particles.

isseq
     This method returns true if the object is a sequence of content
     particles.

quant
     This method returns undef or a string representing the quantifier
     ('?', '*', '+') associated with the model or particle.

children
     This method returns undef or (for mixed, choice, and sequence types)
     an array of component content particles. There will always be at least
     one component for choices and sequences, but for a mixed content model
     of pure PCDATA, "(#PCDATA)", then an undef is returned.

XML::Parser::ExpatNB Methods
----------------------------

   The class XML::Parser::ExpatNB is a subclass of XML::Parser::Expat used
for non-blocking access to the expat library. It does not support the
parse, parsestring, or parsefile methods, but it does have these
additional methods:

parse_more(DATA)
     Feed expat more text to munch on.

parse_done
     Tell expat that it's gotten the whole document.

FUNCTIONS
=========

XML::Parser::Expat::load_encoding(ENCODING)
     Load an external encoding. ENCODING is either the name of an encoding
     or the name of a file. The basename is converted to lowercase and a
     '.enc' extension is appended unless there's one already there. Then,
     unless it's an absolute pathname (i.e. begins with '/'), the first
     file by that name discovered in the @Encoding_Path path list is used.

     The encoding in the file is loaded and kept in the %Encoding_Table
     table. Earlier encodings of the same name are replaced.

     This function is automaticly called by expat when it encounters an
     encoding it doesn't know about. Expat shouldn't call this twice for
     the same encoding name. The only reason users should use this
     function is to explicitly load an encoding not contained in the
     @Encoding_Path list.

AUTHORS
=======

   Larry Wall <`larry@wall.org'> wrote version 1.0.

   Clark Cooper <`coopercc@netheaven.com'> picked up support, changed the
API for this version (2.x), provided documentation, and added some standard
package features.

Perl SAX parser using XML::Parser
*********************************

NAME
====

   XML::Parser::PerlSAX - Perl SAX parser using XML::Parser

SYNOPSIS
========

     use XML::Parser::PerlSAX;

     $parser = XML::Parser::PerlSAX->new( [OPTIONS] );
     $result = $parser->parse( [OPTIONS] );

     $result = $parser->parse($string);

DESCRIPTION
===========

   `XML::Parser::PerlSAX' is a PerlSAX parser using the XML::Parser
module.  This man page summarizes the specific options, handlers, and
properties supported by `XML::Parser::PerlSAX'; please refer to the
PerlSAX standard in ``PerlSAX.pod'' for general usage information.

METHODS
=======

new
     Creates a new parser object.  Default options for parsing, described
     below, are passed as key-value pairs or as a single hash.  Options may
     be changed directly in the parser object unless stated otherwise.
     Options passed to `parse()' override the default options in the
     parser object for the duration of the parse.

parse
     Parses a document.  Options, described below, are passed as key-value
     pairs or as a single hash.  Options passed to `parse()' override
     default options in the parser object.

location
     Returns the location as a hash:

          ColumnNumber    The column number of the parse.
          LineNumber      The line number of the parse.
          BytePosition    The current byte position of the parse.
          PublicId        A string containing the public identifier, or undef
                          if none is available.
          SystemId        A string containing the system identifier, or undef
                          if none is available.
          Base            The current value of the base for resolving relative
                          URIs.

     ALPHA WARNING: The `SystemId' and `PublicId' properties returned are
     the system and public identifiers of the document passed to
     `parse()', not the identifiers of the currently parsing external
     entity.  The column, line, and byte positions *are* of the current
     entity being parsed.

OPTIONS
=======

   The following options are supported by `XML::Parser::PerlSAX':

     Handler          default handler to receive events
     DocumentHandler  handler to receive document events
     DTDHandler       handler to receive DTD events
     ErrorHandler     handler to receive error events
     EntityResolver   handler to resolve entities
     Locale           locale to provide localisation for errors
     Source           hash containing the input source for parsing
     UseAttributeOrder set to true to provide AttributeOrder and Defaulted
                       properties in `start_element()'

   If no handlers are provided then all events will be silently ignored,
except for ``fatal_error()'' which will cause a ``die()'' to be called
after calling ``end_document()''.

   If a single string argument is passed to the `parse()' method, it is
treated as if a `Source' option was given with a `String' parameter.

   The `Source' hash may contain the following parameters:

     ByteStream       The raw byte stream (file handle) containing the
                      document.
     String           A string containing the document.
     SystemId         The system identifier (URI) of the document.
     PublicId         The public identifier.
     Encoding         A string describing the character encoding.

   If more than one of `ByteStream', `String', or `SystemId', then
preference is given first to `ByteStream', then `String', then `SystemId'.

HANDLERS
========

   The following handlers and properties are supported by
`XML::Parser::PerlSAX':

DocumentHandler methods
-----------------------

start_document
     Receive notification of the beginning of a document.

     No properties defined.

end_document
     Receive notification of the end of a document.

     No properties defined.

start_element
     Receive notification of the beginning of an element.

          Name             The element type name.
          Attributes       A hash containing the attributes attached to the
                           element, if any.

     The `Attributes' hash contains only string values.

     If the ``UseAttributeOrder'' parser option is true, the following
     properties are also passed to `start_element':

          AttributeOrder   An array of attribute names in the order they were
                           specified, followed by the defaulted attribute
                           names.
          Defaulted        The index number of the first defaulted attribute in
                           `AttributeOrder.  If this index is equal to the
                           length of `AttributeOrder', there were no defaulted
                           values.

     Note to XML::Parser users:  ``Defaulted'' will be half the value of
     `XML::Parser::Expat''s ``specified_attr()'' function because only
     attribute names are provided, not their values.

end_element
     Receive notification of the end of an element.

          Name             The element type name.

characters
     Receive notification of character data.

          Data             The characters from the XML document.

processing_instruction
     Receive notification of a processing instruction.

          Target           The processing instruction target.
          Data             The processing instruction data, if any.

comment
     Receive notification of a comment.

          Data             The comment data, if any.

start_cdata
     Receive notification of the start of a CDATA section.

     No properties defined.

end_cdata
     Receive notification of the end of a CDATA section.

     No properties defined.

entity_reference
     Receive notification of an internal entity reference.  If this handler
     is defined, internal entities will not be expanded and not passed to
     the ``characters()'' handler.  If this handler is not defined,
     internal entities will be expanded if possible and passed to the
     ``characters()'' handler.

          Name             The entity reference name
          Value            The entity reference value

DTDHandler methods
------------------

notation_decl
     Receive notification of a notation declaration event.

          Name             The notation name.
          PublicId         The notation's public identifier, if any.
          SystemId         The notation's system identifier, if any.
          Base             The base for resolving a relative URI, if any.

unparsed_entity_decl
     Receive notification of an unparsed entity declaration event.

          Name             The unparsed entity's name.
          SystemId         The entity's system identifier.
          PublicId         The entity's public identifier, if any.
          Base             The base for resolving a relative URI, if any.

entity_decl
     Receive notification of an entity declaration event.

          Name             The entity name.
          Value            The entity value, if any.
          PublicId         The notation's public identifier, if any.
          SystemId         The notation's system identifier, if any.
          Notation         The notation declared for this entity, if any.

     For internal entities, the `Value' parameter will contain the value
     and the `PublicId', `SystemId', and `Notation' will be undefined.
     For external entities, the `Value' parameter will be undefined, the
     `SystemId' parameter will have the system id, the `PublicId'
     parameter will have the public id if it was provided (it will be
     undefined otherwise), the `Notation' parameter will contain the
     notation name for unparsed entities.  If this is a parameter entity
     declaration, then a '%' will be prefixed to the entity name.

     Note that ``entity_decl()'' and ``unparsed_entity_decl()'' overlap.
     If both methods are implemented by a handler, then this handler will
     not be called for unparsed entities.

element_decl
     Receive notification of an element declaration event.

          Name             The element type name.
          Model            The content model as a string.

attlist_decl
     Receive notification of an attribute list declaration event.

     This handler is called for each attribute in an ATTLIST declaration
     found in the internal subset. So an ATTLIST declaration that has
     multiple attributes will generate multiple calls to this handler.

          ElementName      The element type name.
          AttributeName    The attribute name.
          Type             The attribute type.
          Fixed            True if this is a fixed attribute.

     The default for `Type' is the default value, which will either be
     "#REQUIRED", "#IMPLIED" or a quoted string (i.e. the returned string
     will begin and end with a quote character).

doctype_decl
     Receive notification of a DOCTYPE declaration event.

          Name             The document type name.
          SystemId         The document's system identifier.
          PublicId         The document's public identifier, if any.
          Internal         The internal subset as a string, if any.

     Internal will contain all whitespace, comments, processing
     instructions, and declarations seen in the internal subset. The
     declarations will be there whether or not they have been processed by
     another handler (except for unparsed entities processed by the
     Unparsed handler).  However, comments and processing instructions will
     not appear if they've been processed by their respective handlers.

xml_decl
     Receive notification of an XML declaration event.

          Version          The version.
          Encoding         The encoding string, if any.
          Standalone       True, false, or undefined if not declared.

EntityResolver
--------------

resolve_entity
     Allow the handler to resolve external entities.

          Name             The notation name.
          SystemId         The notation's system identifier.
          PublicId         The notation's public identifier, if any.
          Base             The base for resolving a relative URI, if any.

     ``resolve_entity()'' should return undef to request that the parser
     open a regular URI connection to the system identifier or a hash
     describing the new input source.  This hash has the same properties as
     the `Source' parameter to `parse()':

          PublicId    The public identifier of the external entity being
                      referenced, or undef if none was supplied.
          SystemId    The system identifier of the external entity being
                      referenced.
          String      String containing XML text
          ByteStream  An open file handle.
          CharacterStream
                      An open file handle.
          Encoding    The character encoding, if known.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), PerlSAX.pod(3)

     Extensible Markup Language (XML) <http://www.w3c.org/XML/>
     SAX 1.0: The Simple API for XML <http://www.megginson.com/SAX/>

convert ESIS of Nsgmls or Pyxie to Perl SAX events.
***************************************************

NAME
====

   XML::Parser::PyxParser - convert ESIS of Nsgmls or Pyxie to Perl SAX
events.

SYNOPSIS
========

     use XML::Parser::PyxParser;
     use XML::Handler::Something;
     $writer = new XML::Handler::Something OPTIONS;
     $options = {
         OPTIONS,
         Handler  =>  $writer
     }
     $handler = new XML::Parser::PyxParser $options;
     $handler->parse;

DESCRIPTION
===========

   XML::Parser::PyxParser converts ESIS of Nsgmls or Pyxie to Perl SAX
events.   Behaviour of object is specified when the object is created  or
in method "parse".  This module as compatible as possible with
XML::Parser::PerlSAX module.

METHODS
=======

new
     Creates a new parser object. Options are passed by hash. Passed
     options overrides default options.

parse
     Parses a document. Passed options overrides options passed to method
     "new".

location
     Will not be implemented.

OPTIONS
=======

   The following options are not supported by XML::Parser::PyxParser:

   * DTDHandler

   * ErrorHandler

   * EntityResolver

   * Locale

   * UseAttributeOrder

   The following options are supported by XML::Parser::PyxParser:

Handler
     Default handler to receive events.

DocumentHandler
     Handler to receive document events.  You can use as "DocumentHandler"
     as "Handler". No difference. If no handlers are provided then object
     silently will not parse.

Source
     Hash containing the input source for parsing. See description below.

AttrBeforeElement
     Attributes are before element (1) or after  element (0). Default is 1
     (before).

CompactAttrString
     Attribute type is absent (1) or present (0). Default is 0 (present).

SkipBadTags
     Skip (1) or do not (0) skip ESIS strings with  unknown prefix.
     Default is 1 (skip).

CheckNesting
     Check (1) or do not check (0) nesting of elements. Default is 1
     (check).

ChompPI
     Cut (1) or do not cut (0) symbol '?' from the end of  processing
     instruction. Default is 1 (cut).

   XML::Parser::PyxParser does not support these options of hash "Source":

   * String

   * PublicId

   * Encoding

   Options of hash "Source":

ByteStream
     Output stream object with method "print" (for example, IO::File).

SystemId
     Name of file passed to method "open" of IO::File.  If "ByteStream" is
     defined then "SystemId" is ignored.  Default value of "SystemId" is
     "-".

RECOMMENDED VALUES
==================

   Probably you like to be compatible with Nsgmls or Pyxie. The main
difference is that Nsgmls has attributes before element and attribute
types. Pyxie has attributes after element and does not have attribute
types. By default XML::Parser::PyxParser uses Nsgmls mode.

   Recommended values for Nsgmls mode:

   * AttrBeforeElement = 1

   * CompactAttrString = 0

   * CheckNesting = 1

   * SkipBadTags = 1

   * ChompPI = 1

   Recommended values for Pyxie mode:

   * AttrBeforeElement = 0

   * CompactAttrString = 1

   * CheckNesting = 1

   * SkipBadTags = 0

   * ChompPI = 0

INPUT STREAM
============

   XML::Parser::PyxParser understand this escape sequences:

\\
     A \.

\n
     A record end character.

\nnn
     The character whose code is "nnn" octal.

\#n;
     The character whose number is "n" decimal. "n" can have any number of
     digits. But are you sure that Perl character can be greater than 255?

NOTATION
========

   Notation is a series of lines. Each line consist of an initial command
characters and arguments. The possible command	characters and
arguments are as follows:

(gi
     The start of an element whose generic identifier is "gi". Attributes
     of element are specified before or after element depending on value
     of option "AttrBeforeElement".

)gi
     The end of an element whose generic  identifier is "gi".

-data
     Data.

?pi
     A processing instruction with data "pi". By default "pi" of ESIS of
     Nsgmls on my box have symbol '?' at the end. In XML mode I do not
     have this symbol. Parser does not know origin of ESIS stream. So he
     silently cut last '?' symbol (if allowed).

Aname value
     Attribute definition if "CompactAttrString" option is set.

Aname type value
     Attribute definition if "CompactAttrString" option is not set.

     Word "type" is any word without spaces. This word  is ignored.

AUTHOR
======

   Oleg A. Paraschenko, prof@beta.math.spbu.ru

SEE ALSO
========

   XML::Handler::PyxWriter

   Home Page, http://beta.math.spbu.ru/~prof/xc/

   Nsgmls

   Pyxie, http://www.pyxie.org/

   PerlSAX

   XML::PYX

   XML::ESISParser

   SGMLS

An action module for
********************

NAME
====

   XML::PatAct::ACTION - An action module for

SYNOPSIS
========

     use XML::PatAct::ACTION;

     my $patterns = [ PATTERN => ACTION,
     		  ... ];

     my $matcher = XML::PatAct::ACTION->new(Patterns => $patterns,
     					Matcher => $matcher );

DESCRIPTION
===========

   XML::PatAct::ACTION is a PerlSAX handler for applying pattern-action
lists to XML parses or trees.  XML::PatAct::ACTION ...

   New XML::PatAct::ACTION instances are creating by calling `new()'.  A
Parameters can be passed as a list of key, value pairs or a hash.
Patterns and Matcher options are required.  Patterns is the pattern-action
list to apply.  Matcher is an instance of the pattern or query matching
module.

   DESCRIBE THE FORMAT OF YOUR ACTIONS HERE

AUTHOR
======

   This template file was written by Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1)

   "Using PatAct Modules" and "Creating PatAct Modules" in libxml-perl.

An action module for simplistic style-sheets
********************************************

NAME
====

   XML::PatAct::Amsterdam - An action module for simplistic style-sheets

SYNOPSIS
========

     use XML::PatAct::Amsterdam;

     my $patterns = [ PATTERN => { Before => 'before',
     			       After => 'after' },
     		  ... ];

     my $matcher = XML::PatAct::Amsterdam->new( I<OPTIONS> );

DESCRIPTION
===========

   XML::PatAct::Amsterdam is a PerlSAX handler for applying pattern-action
lists to XML parses or trees.  XML::PatAct::Amsterdam applies a very
simple style sheet to an instance and outputs the result.  Amsterdam gets
it's name from the Amsterdam SGML Parser (ASP) which inspired this module.

   CAUTION: Amsterdam is a very simple style module, you will run into
it's limitations quickly with even moderately complex XML instances, be
aware of and prepared to switch to more complete style modules.

   New XML::PatAct::Amsterdam instances are creating by calling `new()'.
Parameters can be passed as a list of key, value pairs or a hash.  A
Patterns and Matcher options are required.  The following OPTIONS are
supported:

Patterns
     The pattern-action list to apply.  The list is an anonymous array of
     pattern, action pairs.  Each action in the list contains either or
     both a Before and an After string to copy to the output before and
     after processing an XML element.  The Before and After strings may
     contain attribute names enclosed in square brackets (`[' NAME `]'),
     these are replaced with the value of the attribute with that name.
     The special NAME ``_element'' will be replaced with the element's
     name.

Matcher
     An instance of the pattern or query matching module.

Output
     An IO::Handle or one of it's subclasses (such as IO::File), if this
     parameter is not present and the AsString option is not used, the
     module will write to standard output.

AsString
     Return the generated output as a string from the `parse()' method of
     the PerlSAX event generator.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1)

   "Using PatAct Modules" and "Creating PatAct Modules" in libxml-perl.

A pattern module for matching element names
*******************************************

NAME
====

   XML::PatAct::MatchName - A pattern module for matching element names

SYNOPSIS
========

     use XML::PatAct::MatchName;

     my $matcher = XML::PatAct::MatchName->new();

     my $patterns = [ 'foo' => ACTION,
     		  'bar/foo' => ACTION,
     		  ... ];

DESCRIPTION
===========

   XML::PatAct::MatchName is a pattern module for use with PatAct drivers
for applying pattern-action lists to XML parses or trees.
XML::PatAct::MatchName is a simple pattern module that uses just element
names to match on.  If multiple names are supplied seperated by `/'
characters, then all of the parent element names must match as well.

   The order of patterns in the list is not significant.
XML::PatAct::MatchName will use the most specific match.  Using the
synopsis above as an example, if you have an element `foo', ``bar/foo''
will match if `foo' is in an element `bar', otherwise just the pattern
with `foo' will match.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1)

   "Using PatAct Modules" and "Creating PatAct Modules" in libxml-perl.

A pattern module for
********************

NAME
====

   XML::PatAct::PATTERN - A pattern module for

SYNOPSIS
========

     use XML::PatAct::PATTERN;

     my $patterns = [ PATTERN => ACTION,
                      ... ]

     my $matcher = XML::PatAct::PATTERN->new( Patterns => $patterns );

DESCRIPTION
===========

   XML::PatAct::PATTERN is a pattern module for use with PatAct action
modules for applying pattern-action lists to XML parses or trees.
XML::PatAct::PATTERN ...

   Parameters can be passed as a list of key, value pairs or a hash.

   DESCRIBE THE FORMAT OR LANGUAGE OF YOUR PATTERNS HERE

AUTHOR
======

   This template file was written by Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1)

   "Using PatAct Modules" and "Creating PatAct Modules" in libxml-perl.

An action module for creating Perl objects
******************************************

NAME
====

   XML::PatAct::ToObjects - An action module for creating Perl objects

SYNOPSIS
========

     use XML::PatAct::ToObjects;

     my $patterns = [ PATTERN => [ OPTIONS ],
     		  PATTERN => "PERL-CODE",
     		  ... ];

     my $matcher = XML::PatAct::ToObjects->new( Patterns => $patterns,
     					    Matcher => $matcher,
     					    CopyId => 1,
     					    CopyAttributes => 1 );

DESCRIPTION
===========

   XML::PatAct::ToObjects is a PerlSAX handler for applying pattern-action
lists to XML parses or trees.  XML::PatAct::ToObjects creates Perl objects
of the types and contents of the action items you define.

   New XML::PatAct::ToObject instances are creating by calling `new()'.
Parameters can be passed as a list of key, value pairs or a hash.  `new()'
requires the Patterns and Matcher parameters, the rest are optional:

Patterns
     The pattern-action list to apply.

Matcher
     An instance of the pattern or query matching module.

CopyId
     Causes the `ID' attribute, if any, in a source XML element to be
     copied to an `ID' attribute in newly created objects.  Note that IDs
     may be lost of no pattern matches that element or an object is not
     created (`-make') for that element.

CopyAttributes
     Causes all attributes of the element to be copied to the newly created
     objects.

   Each action can either be a list of options defined below or a string
containing a fragment of Perl code.  If the action is a string of Perl
code then simple then some simple substitutions are made as described
further below.

   Options that can be used in an action item containing an option-list:

*-holder*
     Ignore this element, but continue processing it's children (compare to
     *-ignore*).  `-pcdata' may be used with this option.

*-ignore*
     Ignore (discard) this element and it's children (compare to
     *-holder*).

*-pcdata*
     Character data in this element should be copied to the Contents field.

*-make* PACKAGE
     Create an object blessed into PACKAGE, and continue processing this
     element and it's children.  PACKAGE may be the type `HASH' to simply
     create an anonyous hash.

*-args* ARGUMENTS
     Use ARGUMENTS in creating the object specified by *-make*.  This is
     commonly used to copy element attributes into fields in the newly
     created object.  For example:

          -make => 'HASH', -args => 'URL => %{href}'

     would copy the `href' attribute in an element to the `URL' field of
     the newly created hash.

*-field* *FIELD*
     Store this element, object, or children of this element in the parent
     object's field named by *FIELD*.

*-push-field* *FIELD*
     Similar to *-field*, except that *FIELD* is an array and the contents
     are pushed onto that array.

*-value* VALUE
     Use VALUE as a literal value to store in *FIELD*, otherwise ignoring
     this element and it's children.  Only valid with *-field* or
     *-push-field*.  ``%{*ATTRIBUTE*}'' notation can be used to substitute
     the value of an attribute into the literal value.

*-as-string*
     Convert the contents of this element to a string (as in
     `XML::Grove::AsString') and store in *FIELD*.  Only valid with
     *-field* or *-push-field*.

*-grove*
     Copy this element to *FIELD* without further processing.  The element
     can then be processed later as the Perl objects are manipulated.  Only
     valid with *-field* or *-push-field*.  If ToObjects is used with
     PerlSAX, this will use XML::Grove::Builder to build the grove element.

*-grove-contents*
     Used with *-make*, *-grove-contents* creates an object but then takes
     all of the content of that element and stores it in Contents.

   If an action item is a string, that string is treated as a fragment of
Perl code.  The following simple substitutions are performed on the
fragment to provide easy access to the information being converted:

*@ELEM@*
     The object that caused this action to be called.  If ToObjects is used
     with PerlSAX this will be a hash with the element name and attributes,
     with XML::Grove this will be the element object, with Data::Grove it
     will be the matching object, and with XML::DOM it will be an
     XML::DOM::Element.

EXAMPLE
=======

   The example pattern-action list below will convert the following XML
representing a Database schema:

     <schema>
       <table>
         <name>MyTable</name>
         <summary>A short summary</summary>
         <description>A long description that may
           contain a subset of HTML</description>
         <column>
           <name>MyColumn1</name>
           <summary>A short summary</summary>
           <description>A long description</description>
           <unique/>
           <non-null/>
           <default>42</default>
         </column>
       </table>
     </schema>

   into Perl objects looking like:

     [
       { Name => "MyTable",
         Summary => "A short summary",
         Description => $grove_object,
         Columns => [
           { Name => "MyColumn1",
             Summary => "A short summary",
             Description => $grove_object,
             Unique => 1,
             NonNull => 1,
             Default => 42
           }
         ]
       }
     ]

   Here is a Perl script and pattern-action list that will perform the
conversion using the simple name matching pattern module
XML::PatAct::MatchName.  The script accepts a Schema XML file as an
argument (`$ARGV[0]') to the script.  This script creates a grove as one
of it's objects, so it requires the XML::Grove module.

     use XML::Parser::PerlSAX;
     use XML::PatAct::MatchName;
     use XML::PatAct::ToObjects;

     my $patterns = [
       'schema'      => [ qw{ -holder                                  } ],
       'table'       => [ qw{ -make Schema::Table                      } ],
       'name'        => [ qw{ -field Name -as-string                   } ],
       'summary'     => [ qw{ -field Summary -as-string                } ],
       'description' => [ qw{ -field Description -grove                } ],
       'column'      => [ qw{ -make Schema::Column -push-field Columns } ],
       'unique'      => [ qw{ -field Unique -value 1                   } ],
       'non-null'    => [ qw{ -field NonNull -value 1                  } ],
       'default'     => [ qw{ -field Default -as-string                } ],
     ];

     my $matcher = XML::PatAct::MatchName->new( Patterns => $patterns );
     my $handler = XML::PatAct::ToObjects->new( Patterns => $patterns,
                                                Matcher => $matcher);

     my $parser = XML::Parser::PerlSAX->new( Handler => $handler );
     my $schema = $parser->parse(Source => { SystemId => $ARGV[0] } );

TODO
====

   * It'd be nice if patterns could be applied even in *-as-string* and
     *-grove*.

   * Implement Perl code actions.

   * *-as-xml* to write XML into the field.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), Data::Grove(3)

   "Using PatAct Modules" and "Creating PatAct Modules" in libxml-perl.

translate Perl SAX methods to Java/CORBA style methods
******************************************************

NAME
====

   XML::SAX2Perl - translate Perl SAX methods to Java/CORBA style methods

SYNOPSIS
========

     use XML::Perl2SAX;

     $perl2sax = XML::Perl2SAX(handler => $java_style_handler);

DESCRIPTION
===========

   `XML::Perl2SAX' is a SAX filter that translates Perl style SAX methods
to Java/CORBA style method calls.  This module performs the inverse
operation from `XML::SAX2Perl'.

   `Perl2SAX' is a Perl SAX document handler.  The `new' method takes a
`handler' argument that is a Java/CORBA style handler that the new
Perl2SAX instance will call.  The SAX interfaces are defined at
<http://www.megginson.com/SAX/>.

AUTHOR
======

   Ken MacLeod <ken@bitsko.slc.ut.us>

SEE ALSO
========

   perl(1), XML::Perl2SAX(3).

     Extensible Markup Language (XML) <http://www.w3c.org/XML/>
     Simple API for XML (SAX) <http://www.megginson.com/SAX/>

An XML query language
*********************

NAME
====

   XML::QL - An XML query language

VERSION
=======

   0.07

SYNOPSIS
========

   $ql = 'WHERE          <head>$head</head>        ORDER-BY          $head
      IN          "file:REC-xml-19980210.xml"        CONSTRUCT
$head';

   print XML::QL->query($sql);

DESCRIPTION
===========

   This module is an early implementation of a note published by the W3C
called "XML-QL: A Query Language for XML". XML-QL allows the user to query
an XML document much like a database, and describe a construct for output.
Currently this module only offers partial functionality as described in
the specification, and even some of that has been changed for ease of use.
This documentation will describe the fuctionality of this module as well
as differences from the XML-QL specification.

METHODS
=======

query( "query" )
     This is the only method required to use this module. This one method
     allows the user to pass a valid XML-QL query to the module, and the
     return value is the output.

XML-QL: The Query Language
==========================

   The basic syntax consists of two parts, a WHERE clause to describe the
data to search for, and a CONSTRUCT clause to describe how to return the
data that is found.

WHERE
     WHERE XML-searchstring [ORDER-BY variable [DESCENDING] [, variable
     [DESCENDING]] ] IN 'filename'

     The WHERE clause can be separated into several parts. The first is
     the search string, the second is an optional ORDER-BY clause much
     like ORDER BY in SQL, and last is the required XML document file
     name. Each of these parts is described below.

    XML-searchstring
          The search string MUST be a valid XML snippet. This is one are
          where this module differs from the specification. It has been
          implemented in this way so that the search string may be parsed
          by the XML::Parser module.

          The first step in building a query is to list the tags to search
          for in the document.  For example, consider the following search
          string:

               <BOOK>
               	<AUTHOR></AUTHOR>
               </BOOK>

          This search string will search for the AUTHOR tag nested within
          a BOOK tag. Note however that no information has been selected
          for retrieval. In the following example, we actually grab some
          information:

               <BOOK>
               	<AUTHOR>$author</AUTHOR>
               </BOOK>

          The variable name $author will grab the information that it
          finds withing this tag, and makes this information avalable to
          us for use in the CONSTRUCT section of the query. You will
          notice that variable names start with a dollar sign ($), as this
          is called for by the specification.  In Perl, this means that if
          the query is enclosed in double quotes, this dollar sign must be
          escaped.

          In the following example we take it a step further by searching
          for books of that are non-fiction:

               <BOOK TYPE='non-fiction'>
               	<AUTHOR>$author</AUTHOR>
               </BOOK>

          We can also express this as a regular expression:

               <BOOK TYPE='non-.*'>
               	<AUTHOR>$author</AUTHOR>
               </BOOK>

          This is another area where this module differs from the
          specification. The regular expesssion ability as defined in the
          specification only allows for a subset of the ability available
          in a Perl regular expression. With this module, the full range
          of regular expression syntax has been made available. This also
          means that you must also escape things such as periods(.),
          parenthesis (), and brackets ([]). All non tag matched are case
          insensitive.

          Now lets say that besides matching the TYPE, we also wanted to
          grab the value.  Consider this example:

               <BOOK TYPE='non-.* AS_ELEMENT $type'>
               	<AUTHOR>$author</AUTHOR>
               </BOOK>

          The AS_ELEMENT keyword allows you to save the matched value for
          later use in the CONSTRUCT portion of the query.

    ORDER-BY
          The ORDER-BY clause allows to sort the data retrieved in the
          variables. You may specify multiple variables, and specify
          DESCENDING for a reverse sort. This clause is not required. For
          example:

          ORDER-BY $type, $author DESCENDING

    IN
          The IN clause is a required clause that specifies the file name
          of the XML file.  This can be any URI that is supported by LWP,
          or it can be a single file name enclosed in quotes. In later
          versions of this module there will be support for multiple
          files, directories. The following will work:

          IN 'REC-xml-19980210.xml'

          IN 'file://othermachine/share/filename.xml'

          IN 'http://www.example.com/file.xml'

CONSTRUCT
     The CONSTRUCT construct allows you to specify a template for output.
     The template will match character for character from the first space
     after the word CONSTRUCT to the end of the XML-QL query. For example:

     $ql = '(where clause...)         CONSTRUCT 	Type: $type
     Author: $author';

     The ouput of this will then be a carriage return, a tab, "Type: ",
     the contents of $type, a carriage return, a tab, "Author: ", and the
     contents of $author. This construct will be repeated for every match
     found and returned as a single string.

AUTHOR
======

   Robert Hanson - Initial Version rhanson@blast.net

   Matt Sergeant - Only minor fixes so far msergeant@ndirect.co.uk,
sergeant@geocities.com

COPYRIGHT
=========

   Robert's Original licence *was*: I hereby reserve NO rights to this
module, except for maybe a little recognition if you decide to rewrite it
and redistribute as your own.  Beyond that, you can do whatever you want
with this. I would just appreciate a copy of any improvements to this
module.

   However that only stands for version 0.01 of the module. All versions
above that are released under the same terms as perl itself.

creates and updates RSS files
*****************************

NAME
====

   XML::RSS - creates and updates RSS files

SYNOPSIS
========

     # create an RSS 1.0 file (http://purl.org/rss/1.0/)
     use XML::RSS;
     my $rss = new XML::RSS (version => '1.0');
     $rss->channel(
       title        => "freshmeat.net",
       link         => "http://freshmeat.net",
       description  => "the one-stop-shop for all your Linux software needs",
       dc => {
         date       => '2000-08-23T07:00+00:00',
         subject    => "Linux Software",
         creator    => 'scoop@freshmeat.net',
         publisher  => 'scoop@freshmeat.net',
         rights     => 'Copyright 1999, Freshmeat.net',
         language   => 'en-us',
       },
       syn => {
         updatePeriod     => "hourly",
         updateFrequency  => "1",
         updateBase       => "1901-01-01T00:00+00:00",
       },
     );

     $rss->image(
       title  => "freshmeat.net",
       url    => "http://freshmeat.net/images/fm.mini.jpg",
       link   => "http://freshmeat.net",
       dc => {
         creator  => "G. Raphics (graphics at freshmeat.net)",
       },
     );

     $rss->add_item(
       title       => "GTKeyboard 0.85",
       link        => "http://freshmeat.net/news/1999/06/21/930003829.html",
       description => "GTKeyboard is a graphical keyboard that ...",
       dc => {
         subject  => "X11/Utilities",
         creator  => "David Allen (s2mdalle at titan.vcu.edu)",
       },
     );

     $rss->textinput(
       title        => "quick finder",
       description  => "Use the text input below to search freshmeat",
       name         => "query",
       link         => "http://core.freshmeat.net/search.php3",
     );

     # Optionally mixing in elements of a non-standard module/namespace

     $rss->add_module(prefix=>'my', uri=>'http://purl.org/my/rss/module/');

     $rss->add_item(
       title       => "xIrc 2.4pre2"
       link        => "http://freshmeat.net/projects/xirc/",
       description => "xIrc is an X11-based IRC client which ...",
       my => {
         rating    => "A+",
         category  => "X11/IRC",
       },
     );

     $rss->add_item (title=>$title, link=>$link, slash=>{ topic=>$topic });

     # create an RSS 0.91 file
     use XML::RSS;
     my $rss = new XML::RSS (version => '0.91');
     $rss->channel(title          => 'freshmeat.net',
                   link           => 'http://freshmeat.net',
                   language       => 'en',
                   description    => 'the one-stop-shop for all your Linux software needs',
                   rating         => '(PICS-1.1 "http://www.classify.org/safesurf/" 1 r (SS~~000 1))',
                   copyright      => 'Copyright 1999, Freshmeat.net',
                   pubDate        => 'Thu, 23 Aug 1999 07:00:00 GMT',
                   lastBuildDate  => 'Thu, 23 Aug 1999 16:20:26 GMT',
                   docs           => 'http://www.blahblah.org/fm.cdf',
                   managingEditor => 'scoop@freshmeat.net',
                   webMaster      => 'scoop@freshmeat.net'
                   );

     $rss->image(title       => 'freshmeat.net',
                 url         => 'http://freshmeat.net/images/fm.mini.jpg',
                 link        => 'http://freshmeat.net',
                 width       => 88,
                 height      => 31,
                 description => 'This is the Freshmeat image stupid'
                 );

     $rss->add_item(title => "GTKeyboard 0.85",
                    link  => "http://freshmeat.net/news/1999/06/21/930003829.html",
     		description => 'blah blah'
                    );

     $rss->skipHours(hour => 2);
     $rss->skipDays(day => 1);

     $rss->textinput(title => "quick finder",
                     description => "Use the text input below to search freshmeat",
                     name  => "query",
                     link  => "http://core.freshmeat.net/search.php3"
                     );

     # create an RSS 0.9 file
     use XML::RSS;
     my $rss = new XML::RSS (version => '0.9');
     $rss->channel(title => "freshmeat.net",
                   link  => "http://freshmeat.net",
                   description => "the one-stop-shop for all your Linux software needs",
                   );

     $rss->image(title => "freshmeat.net",
                 url   => "http://freshmeat.net/images/fm.mini.jpg",
                 link  => "http://freshmeat.net"
                 );

     $rss->add_item(title => "GTKeyboard 0.85",
                    link  => "http://freshmeat.net/news/1999/06/21/930003829.html"
                    );

     $rss->textinput(title => "quick finder",
                     description => "Use the text input below to search freshmeat",
                     name  => "query",
                     link  => "http://core.freshmeat.net/search.php3"
                     );

     # print the RSS as a string
     print $rss->as_string;

     # or save it to a file
     $rss->save("fm.rdf");

     # insert an item into an RSS file and removes the oldest item if
     # there are already 15 items
     my $rss = new XML::RSS;
     $rss->parsefile("fm.rdf");
     pop(@{$rss->{'items'}}) if (@{$rss->{'items'}} == 15);
     $rss->add_item(title => "MpegTV Player (mtv) 1.0.9.7",
                    link  => "http://freshmeat.net/news/1999/06/21/930003958.html",
                    mode  => 'insert'
                    );

     # parse a string instead of a file
     $rss->parse($string);

     # print the title and link of each RSS item
     foreach my $item (@{$rss->{'items'}}) {
         print "title: $item->{'title'}\n";
         print "link: $item->{'link'}\n\n";
     }

     # output the RSS 0.9 or 0.91 file as RSS 1.0
     $rss->{output} = '1.0';
     print $rss->as_string;

DESCRIPTION
===========

   This module provides a basic framework for creating and maintaining RDF
Site Summary (RSS) files. This distribution also contains many examples
that allow you to generate HTML from an RSS, convert between 0.9, 0.91,
and 1.0 version, and other nifty things.  This might be helpful if you
want to include news feeds on your Web site from sources like Slashot and
Freshmeat or if you want to syndicate your own content.

   XML::RSS currently supports 0.9, 0.91, and 1.0 versions of RSS.  See
http://my.netscape.com/publish/help/mnn20/quickstart.html for information
on RSS 0.91. See http://my.netscape.com/publish/help/ for RSS 0.9. See
http://purl.org/rss/1.0/ for RSS 1.0.

   RSS was originally developed by Netscape as the format for Netscape
Netcenter channels, however, many Web sites have since adopted it as a
simple syndication format. With the advent of RSS 1.0, users are now able
to syndication many different kinds of content including news headlines,
threaded measages, products catalogs, etc.

METHODS
=======

new XML::RSS (version=>$version, encoding=>$encoding, output=>$output)
     Constructor for XML::RSS. It returns a reference to an XML::RSS
     object.  You may also pass the RSS version and the XML encoding to
     use. The default version is 1.0. The default encoding is UTF-8. You
     may also specify the output format regarless of the input version.
     This comes in handy when you want to convert RSS between versions.
     The XML::RSS modules will convert between any of the formats.

add_item (title=>$title, link=>$link, description=>$desc, mode=>$mode)
     Adds an item to the XML::RSS object. mode and description are
     optional.  The default mode is append, which adds the item to the end
     of the list. To insert an item, set the mode to insert.

     The items are stored in the array @{$obj->{'items'}} where $obj is a
     reference to an XML::RSS object.

as_string;
     Returns a string containing the RSS for the XML::RSS object.

channel (title=>$title, link=>$link, description=>$desc, language=>$language, rating=>$rating, copyright=>$copyright, pubDate=>$pubDate, lastBuildDate=>$lastBuild, docs=>$docs, managingEditor=>$editor, webMaster=>$webMaster)
     Channel information is required in RSS. The title cannot be more the
     40 characters, the link 500, and the description 500 when outputting
     RSS 0.9. title, link, and description, are required for RSS 1.0.
     language is required for RSS 0.91.  The other parameters are optional
     for RSS 0.91 and 1.0.

     To retreive the values of the channel, pass the name of the value
     (title, link, or description) as the first and only argument like so:

     $title = channel('title');

image (title=>$title, url=>$url, link=>$link, width=>$width, height=>$height, description=>$desc)
     Adding an image is not required. url is the URL of the image, link is
     the URL the image is linked to. title, url, and link parameters are
     required if you are going to use an image in your RSS file. The
     remaining image elements are used in RSS 0.91 or optionally imported
     into RSS 1.0 via the rss091 namespace.

     The method for retrieving the values for the image is the same as it
     is for *channel()*.

parse ($string)
     Parses an RDF Site Summary which is passed into parse() as the first
     parameter.

parsefile ($file)
     Same as parse() except it parses a file rather than a string.

save ($file)
     Saves the RSS to a specified file.

skipHours (hour=>$hour)
     Specifies the number of hours that a server should wait before
     retrieving the RSS file. The *hour* parameter is required if the
     skipHours method is used. This method is currently broken.

skipDays (day=>$day)
     Specified the number of days that a server should wait before
     retrieving the RSS file. The day parameter is required if the
     skipDays method is used. This method is currently broken.

strict ($boolean)
     If it's set to 1, it will adhere to the lengths as specified by
     Netscape Netcenter requirements. It's set to 0 by default.  Use it if
     the RSS file you're generating is for Netcenter.  strict will only
     work for RSS 0.9 and 0.91. Do not use it for RSS 1.0.

textinput (title=>$title, description=>$desc, name=>$name, link=>$link);
     This RSS element is also optional. Using it allows users to submit a
     Query to a program on a Web server via an HTML form. name is the HTML
     form name and link is the URL to the program. Content is submitted
     using the GET method.

     Access to the textinput values is the the same as *channel()* and
     image().

add_module(prefix=>$prefix, uri=>$uri) Adds a module namespace declaration to the XML::RSS object, allowing you to add modularity outside of the the standard RSS 1.0 modules.  At present, the standard modules Dublin Core (dc) and Syndication (syn) are predefined for your convenience.
     The modules are stored in the hash %{$obj->{'modules'}} where $obj is
     a reference to an XML::RSS object.

     For more information on RSS 1.0 Modules, read on.

RSS 1.0 MODULES
---------------

   XML-Namespace-based modularization affords RSS 1.0 compartmentalized
extensibility.  The only modules that ship "in the box" with RSS 1.0 are
Dublin Core (http://purl.org/rss/1.0/modules/dc/) and Syndication
(http://purl.org/rss/1.0/modules/syndication/).  Consult the appropriate
module's documentation for further information.

   Adding items from these modules in XML::RSS is as simple as adding other
attributes such as title, link, and description.  The only difference is
the compartmentalization of their key/value paris in a second-level hash.

     $rss->add_item (title=>$title, link=>$link, dc=>{ subject=>$subject, creator=>$creator });

   For elements of the Dublin Core module, use the key 'dc'.  For elements
of the Syndication module, 'syn'.  These are the prefixes used in the RSS
XML document itself.  They are associated with appropriate URI-based
namespaces:

     syn: http://purl.org/rss/1.0/modules/syndication/
     dc:  http://purl.org/dc/elements/1.1/

   Dublin Core elements may occur in channel, image, item(s), and textinput
- albeit uncomming to find them under image and textinput.  Syndication
elements are limited to the channel element.

   Access to module elements after parsing an RSS 1.0 document using
XML::RSS is via either the prefix or namespace URI for your convenience.

     print $rss->{items}->[0]->{dc}->{subject};

     or

     print $rss->{items}->[0]->{'http://purl.org/dc/elements/1.1/'}->{subject};

   XML::RSS also has support for "non-standard" RSS 1.0 modularization at
the channel, image, item, and textinput levels.  Parsing an RSS document
grabs any elements of other namespaces which might appear.  XML::RSS also
allows the inclusion of arbitrary namespaces and associated elements when
building  RSS documents.

   For example, to add elements of a made-up "My" module, first declare the
namespace by associating a prefix with a URI:

     $rss->add_module(prefix=>'my', uri=>'http://purl.org/my/rss/module/');

   Then proceed as usual:

     $rss->add_item (title=>$title, link=>$link, my=>{ rating=>$rating });

   Non-standard namespaces are not, however, currently accessible via a
simple prefix; access them via their namespace URL like so:

     print $rss->{items}->[0]->{'http://purl.org/my/rss/module/'}->{rating};

   XML::RSS will continue to provide built-in support for standard RSS 1.0
modules as they appear.

AUTHOR
======

   Jonathan Eisenzopf <eisen@pobox.com> Rael Dornfest <rael@oreilly.com>

CREDITS
=======

     Wojciech Zwiefka <wojtekz@cnt.pl>
     Chris Nandor <pudge@pobox.com>
     Jim Hebert <jim@cosource.com>
     Randal Schwartz <merlyn@stonehenge.com>
     rjp@browser.org

SEE ALSO
========

   perl(1), XML::Parser(3).

Perlish record-oriented interface to XML
****************************************

NAME
====

   XML::Records - Perlish record-oriented interface to XML

SYNOPSIS
========

     use XML::Records;
     my $p=XML::Records->new('data.lst');
     $p->set_records('credit','debit');
     my ($t,$r)
     while ( (($t,$r)=$p->get_record()) && $t) {
       my $amt=$r->{Amount};
       if ($t eq 'debit') {
         ...
       }
     }

DESCRIPTION
===========

   XML::Records provides a simple interface for reading "record-structured"
XML documents, that is, documents in which the immediate children of the
root element form a sequence of identical and independent sub-elements such
as log entries, transactions, etc., each of which consists of "field" child
elements or attributes.  XML::Records allows you to access each record as a
simple Perl hash.

METHODS
=======

$reader=XML::Records->new(source, [options]);
     Creates a new reader object

     source is either a reference to a string containing the XML, the name
     of a file containing the XML, or an open IO::Handle or filehandle glob
     reference from which the XML can be read.

     The Options can be any options allowed by XML::Parser and
     XML::Parser::Expat, as well as two module-specific options:

    Latin
          If set to a true value, causes Unicode characters in the range
          128-255 to be returned as ISO-Latin-1 characters rather than
          UTF-8 characters.

    Catalog
          Specifies the URL of a catalog to use for resolving public
          identifiers and remapping system identifiers used in document
          type declarations or external entity references.  This option
          requires XML::Catalog to be installed.

$reader->set_records(name [,name]*);
     Specifies what XML element-type names enclose records.

($type,$record)=$reader->get_record([name [,name]*]);
     Retrieves the next record from the input, skipping through the XML
     input until it encounters a start tag for one of the elements that
     enclose records.  If arguments are given, they will temporarily
     replace the set of record-enclosing elements.  The method will return
     a list consisting of the name of the record's enclosing element and a
     reference to a hash whose keys are the names of the record's child
     elements ("fields") and whose values are the fields' contents (if
     called in scalar context, the return value will be the hash
     reference).  Both elements of the list will be undef if no record can
     be found.

     If a field's content is plain text, its value will be that text.

     If a field's content contains another element (e.g. a <customer>
     record contains an <address> field that in turn contains other
     fields), its value will be a reference to another hash containing the
     "sub-record"'s fields.

     If a record includes repeated fields, the hash entry for that field's
     name will be a reference to an array of field values.

     Attributes of record or sub-record elements are treated as if they
     were fields.  Attributes of field elements are ignored.  Mixed
     content (fields with both non-whitespace text and sub-elements) will
     lead to unpredictable results.

     Records do not actually need to be immediately below the document
     root.  If a <customers> document consists of a sequence of <customer>
     elements which in turn contain <address> elements that include further
     elements, then calling get_record with the record type set to
     "address" will return the contents of each <address> element.

EXAMPLE
=======

   Print a list of package names from a (rather out-of-date) list of XML
modules:

     #!perl -w
     use strict;
     use XML::Records;

     my $p=XML::Records->new('modules.xml') or die "$!";
     $p->set_records('module');
     while (my $record=$p->get_record()) {
       my $pkg=$record->{package};
       if (ref $pkg eq 'ARRAY') {
         for my $subpkg (@$pkg) {
           print $subpkg->{name},"\n";
         }
       }
       else {
         print $pkg->{name},"\n";
       }
     }

RATIONALE
=========

   XML::RAX, which implements the proposed RAX standard for record-oriented
XML access, does most of what XML::Records does, but its interface is not
very Perlish (due to the fact that RAX is a language-independent interface)
and it cannot cope with fields that have sub-structure (because RAX itself
doesn't address the issue).

   XML::Simple can do everything that XML::Records does, at the expense of
reading the entire document into memory.  XML::Records will read the entire
document into a single hash if you set the root element as a record type,
but you're really better off using XML::Simple in that case as it's
optimized for such usage.

AUTHOR
======

   Eric Bohlman (ebohlman@earthlink.net, ebohlman@omsdev.com)

COPYRIGHT
=========

   Copyright 2001 Eric Bohlman.  All rights reserved.

   This program is free software; you can use/modify/redistribute it under
the same terms as Perl itself.

SEE ALSO
========

     XML::Parser
     XML::RAX
     XML::Simple
     XML::Catalog
     perl(1).

Regular expressions for XML tokens
**********************************

NAME
====

   XML::RegExp - Regular expressions for XML tokens

SYNOPSIS
========

     use XML::RegExp;

     if ($my_name =~ /^$XML::RegExp::Name$/)
     {
       # $my_name is a valid XML 'Name'
     }

DESCRIPTION
===========

   This package contains regular expressions for the following XML tokens:
BaseChar, Ideographic, Letter, Digit, Extender, CombiningChar, NameChar,
EntityRef, CharRef, Reference, Name, NmToken, and AttValue.

   The definitions of these tokens were taken from the XML spec
(Extensible Markup Language 1.0) at `http:' in this node.

   Also contains the regular expressions for the following tokens from the
XML Namespaces spec at `http:' in this node: NCNameChar, NCName, QName,
Prefix and LocalPart.

AUTHOR
======

   Please send bugs, comments and suggestions to Enno Derksen
<`enno@att.com'>

Perl module for loading and saving an XML registry.
***************************************************

NAME
====

   XML::Registry - Perl module for loading and saving an XML registry.

SYNOPSIS
========

     use XML::Parser;
     use XML::Registry;

     # create a new XML::Parser instance using Tree Style
     $parser = new XML::Parser (Style => 'Tree');

     # create new instance of XML::Registry
     $dump = new XML::Registry;

     # Convert XML Registry to Perl code
     $tree = $parser->parsefile($file);
     $tree = $parser->parse('<foo id="me">Hello World</foo>');
     # print the results
     print $dump->xml2pl($tree);

     # Convert Perl code to XML Registry
     # read file in Data::Dumper format
     open(PL,$file) || die "Cannot open $file: $!";
     $perl = eval(join("",<PL>));
     # print the results
     print $dump->pl2xml($perl);

DESCRIPTION
===========

   XML::Registry can dump an XML registry to Perl code using Data::Dumper,
or dump Perl code into an XML registry.

   This is done via the following 2 methods: XML::Registry::xml2pl
XML::Registry::pl2xml

   This module was originally written for an article in TPJ. It was an
exercise in using the XML::Parser module.

AUTHOR
======

   Jonathan Eisenzopf, eisen@pobox.com

SEE ALSO
========

   perl(1), XML::Parser(3).

translate Java/CORBA style SAX methods to Perl methods
******************************************************

NAME
====

   XML::SAX2Perl - translate Java/CORBA style SAX methods to Perl methods

SYNOPSIS
========

     use XML::SAX2Perl;

     $sax2perl = XML::SAX2Perl(Handler => $my_handler);
     $sax->setDocumentHandler($sax2perl);

DESCRIPTION
===========

   `XML::SAX2Perl' is a SAX filter that translates Java/CORBA style SAX
methods to Perl style method calls.  This man page summarizes the specific
options, handlers, and properties supported by `XML::SAX2Perl'; please
refer to the Perl SAX standard `XML::SAX' for general usage information.

METHODS
=======

new
     Creates a new parser object.  Default options for parsing, described
     below, are passed as key-value pairs or as a single hash.  Options may
     be changed directly in the parser object unless stated otherwise.
     Options passed to `parse()' override the default options in the
     parser object for the duration of the parse.

parse
     Parses a document.  Options, described below, are passed as key-value
     pairs or as a single hash.  Options passed to `parse()' override
     default options in the parser object.

location
     Returns the location as a hash:

          ColumnNumber    The column number of the parse.
          LineNumber      The line number of the parse.
          PublicId        A string containing the public identifier, or undef
                          if none is available.
          SystemId        A string containing the system identifier, or undef
                          if none is available.

SAX DocumentHandler Methods
     The following methods are DocumentHandler methods that the SAX 1.0
     parser will call and `XML::SAX2Perl' will translate to Perl SAX
     methods calls.  See SAX 1.0 for details.

          setDocumentLocator(locator)
          startDocument()
          endDocument()
          startElement(name, atts)
          endElement(name)
          characters(ch, start, length)
          ignorableWhitespace(ch, start, length)
          processingInstruction(target, data)

OPTIONS
=======

   The following options are supported by `XML::SAX2Perl':

     Handler          default handler to receive events
     DocumentHandler  handler to receive document events
     DTDHandler       handler to receive DTD events
     ErrorHandler     handler to receive error events
     EntityResolver   handler to resolve entities
     Locale           locale to provide localisation for errors
     Source           hash containing the input source for parsing

   If no handlers are provided then all events will be silently ignored,
except for ``fatal_error()'' which will cause a ``die()'' to be called
after calling ``end_document()''.

   If a single string argument is passed to the `parse()' method, it is
treated as if a `Source' option was given with a `String' parameter.

   The `Source' hash may contain the following parameters:

     ByteStream       The raw byte stream (file handle) containing the
                      document.
     String           A string containing the document.
     SystemId         The system identifier (URI) of the document.
     PublicId         The public identifier.
     Encoding         A string describing the character encoding.

   If more than one of `ByteStream', `String', or `SystemId', then
preference is given first to `ByteStream', then `String', then `SystemId'.

HANDLERS
========

   The following handlers and properties are supported by `XML::SAX2Perl':

DocumentHandler methods
-----------------------

start_document
     Receive notification of the beginning of a document.

          Locator          An object that can return the location of any SAX
                           document event.

end_document
     Receive notification of the end of a document.

     No properties defined.

start_element
     Receive notification of the beginning of an element.

          Name             The element type name.
          Attributes       Attributes attached to the element, if any.

     ALPHA WARNING: The `Attributes' value is not translated from the SAX
     1.0 value, so it will contain an AttributeList object.

end_element
     Receive notification of the end of an element.

          Name             The element type name.

characters
     Receive notification of character data.

          Data             The characters from the XML document.

ignorable_whitespace
     Receive notification of ignorable whitespace in element content.

          Data             The characters from the XML document.

processing_instruction
     Receive notification of a processing instruction.

          Target           The processing instruction target.
          Data             The processing instruction data, if any.

AUTHOR
======

   Ken MacLeod <ken@bitsko.slc.ut.us>

SEE ALSO
========

   perl(1), XML::Perl2SAX(3).

     Extensible Markup Language (XML) <http://www.w3c.org/XML/>
     Simple API for XML (SAX) <http://www.megginson.com/SAX/>

Perl implementation of the Schematron.
**************************************

NAME
====

   XML::Schematron - Perl implementation of the Schematron.

SYNOPSIS
========

     This package should not be used directly. Use one of the subclasses instead.

DESCRIPTION
===========

   This is the superclass for the XML::Schematron::* modules.

   Please run perldoc XML::Schematron::XPath, or perldoc
XML::Schematron::Sablotron for examples and complete documentation.

AUTHOR
======

   Kip Hampton, khampton@totalcinema.com

COPYRIGHT
=========

   Copyright (c) 2000 Kip Hampton. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   For information about Schematron, sample schemas, and tutorials to help
you write your own schmemas, please visit the Schematron homepage at:
http://www.ascc.net/xml/resource/schematron/

Perl extension for validating XML with XPath/XSLT expressions.
**************************************************************

NAME
====

   XML::Schematron::Sablotron - Perl extension for validating XML with
XPath/XSLT expressions.

SYNOPSIS
========

     use XML::Schematron::Sabotron;
     my $pseudotron = XML::Schematron::Sablotron->new(schema => 'my_schema.xml');
     my $messages = $pseudotron->verify('my_doc.xml');

     if ($messages) {
         # we got warnings or errors during validation...
         ...
     }

     OR, in an array context:

     my $pseudotron = XML::Schematron::Sablotron->new(schema => 'my_schema.xml');
     my @messages = $pseudotron->verify('my_doc.xml');

     OR, just get the generated xsl:

     my $pseudotron = XML::Schematron::Sablotron->new(schema => 'my_schema.xml');
     my $xsl = $pseudotron->dump_xsl; # returns the internal XSLT stylesheet.

DESCRIPTION
===========

   XML::Schematron::Sablotron serves as a simple validator for XML based
on Rick JELLIFFE's Schematron XSLT script. A Schematron schema defines a
set of rules in the XPath language that are used to examine the contents
of an XML document tree.

   A simplified example:

     <schema>
      <pattern>
       <rule context="page">
        <assert test="count(*)=count(title|body)">The page element may only contain title or body elements.</assert>
        <assert test="@name">A page element must contain a name attribute.</assert>
        <report test="string-length(@name) &lt; 5">A page element name attribute must be at least 5 characters long.</report>
       </rule>
      </pattern>
     </schema>

   Note that an 'assert' rule will return if the result of the test
expression is not true, while a 'report' rule will return only if the test
expression evalutes to true.

METHODS
=======

new()    The 'new' constructor accepts the following "named" arguments:
        * schema

          The filename of the schema to use for generating tests.

        * tests

          The tests argument is an *alternative* to the use of a schema as
          a means for defining the test stack. It should be a reference to
          a list of lists where the format of the sub-lists must conform
          to the following order:

               [$xpath_exp, $context, $message, $test_type, $pattern]

               =back

        * schema() When called with a single scalar as its argument, this
          method sets/updates the schema file to be used for generatng
          tests. Otherwise, it simply returns the name of the schema file
          (if any).

        * tests() When called with a reference to a list of lists as its
          argument (see the format in the description of the 'tests'
          argument to the new() method for details), this method sets the
          current test stack. Otherwise, it returns an arrayref to the
          current test stack (if any).

        * add_test(%args); The add_test() method allows you push
          additional tests on to the stack before validation using the
          typical "hash of named parameters" style.

          Arguments for this method:

             * expr (required)

               The XPath expression to evaluate.

               =item * context (required)

               An element name or XPath location to use as the context of
               the test expression.

             * type (required)

               The type argument must be set to either 'assert' or
               'report'. Assert tests will return the associated message
               only if the the corresponding test expression is not true,
               while 'report' tests will return only if their associated
               test expression *are* true.

             * message (required)

               The text message to display when the test condition is met.

             * pattern (optional)

               Optional descriptive text for the returned message that
               allows a logical grouping of tests.

               Example:

                    $obj->add_test(expr => 'count(@*) > 0',
                                     context => '/pattern',
                                     message => 'Pattern should have at least one attribute',
                                     type => 'assert',
                                     pattern => 'Basic tests');

               Note that add_test() pushes a new test on to the existing
               test list, while tests() redefines the entire list.

        * validate('my_xml_file.xml') The validate method takes the path
          to the XML document that you wish to validate as its sole
          argument. It returns the messages (the text() nodes) of any
          'assert' or 'report' rules that are returned during validation.
          When called in an array context, this method returns an array of
          all messages generated during validation. When called in a a
          scalar context, this method returns a concatenated string of all
          output.

        * dump_xsl; The dump_xsl method will return the internal XSLT
          script created from your schema.

CONFORMANCE
===========

   Internally, XML::Schematron::Sablotron uses the Sablotron XSLT
proccessor and, while this proccessor is not 100% compliant with the XSLT
spec at the time of this writing, it is evolving quickly and is very near
completion. It is therefore possible that you might use a completely valid
XSLT expression within one of your schema's tests that will cause this
module to die unexpectedly.

   For those platforms on which Sablotron is not available, please see the
documentation for XML::Schematron::XPath (also in this distribution) for
an alternative.

AUTHOR
======

   Kip Hampton, khampton@totalcinema.com

COPYRIGHT
=========

   Copyright (c) 2000 Kip Hampton. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   For information about Schematron, sample schemas, and tutorials to help
you write your own schmemas, please visit the Schematron homepage at:
http://www.ascc.net/xml/resource/schematron/

   For information about how to install Sablotron and the necessary
XML::Sablotron Perl module, please see the Ginger Alliance homepage at:
http://www.gingerall.com/

   For detailed information about the XPath syntax, please see the W3C
XPath Specification at: http://www.w3.org/TR/xpath.html

Perl extension for validating XML with XPath expressions.
*********************************************************

NAME
====

   XML::Schematron::XPath - Perl extension for validating XML with XPath
expressions.

SYNOPSIS
========

     use XML::Schematron::XPath;
     my $pseudotron = XML::Schematron::XPath->new(schema => 'my_schema.xml');
     my $messages = $pseudotron->verify('my_file.xml');

     if ($messages) {
         # we got warnings or errors during validation...
         ...
     }

     OR, in an array context

     my @messages = $pseudotron->verify('my_file.xml');

DESCRIPTION
===========

   XML::Schematron::XPath serves as a simple validator for XML based on
Rick JELLIFFE's Schematron XSLT script. A Schematron schema defines a set
of rules in the XPath language that are used to examine the contents of an
XML document tree.

   A simplified example:

     <schema>
      <pattern>
       <rule context="page">
        <assert test="count(*)=count(title|body)">The page element may only contain title or body elements.</assert>
        <assert test="@name">A page element must contain a name attribute.</assert>
        <report test="string-length(@name) &lt; 5">A page element name attribute must be at least 5 characters long.</report>
       </rule>
      </pattern>
     </schema>

   Note that an 'assert' rule will return if the result of the test
expression is not true, while a 'report' rule will return only if the test
expression evalutes to true.

METHODS
=======

new()
     The 'new' constructor accepts the following "named" arguments:

        * schema

          The filename of the schema to use for generating tests.

        * tests

          The tests argument is an *alternative* to the use of a schema as
          a means for defining the test stack. It should be a reference to
          a list of lists where the format of the sub-lists must conform
          to the following order:

               [$xpath_exp, $context, $message, $test_type, $pattern]

schema()
     When called with a single scalar as its argument, this method
     sets/updates the schema file to be used for generatng tests.
     Otherwise, it simply returns the name of the schema file (if any).

tests()
     When called with a reference to a list of lists as its argument (see
     the format in the description of the 'tests' argument to the new()
     method for details), this method sets the current test stack.
     Otherwise, it returns an arrayref to the current test stack (if any).

add_test(%args);
     The add_test() method allows you push additional tests on to the
     stack before validation using the typical "hash of named parameters"
     style.

     Arguments for this method:

        * expr (required)

          The XPath expression to evaluate.

        * context (required)

          An element name or XPath location to use as the context of the
          test expression.

        * type (required)

          The type argument must be set to either 'assert' or 'report'.
          Assert tests will return the associated message only if the the
          corresponding test expression is not true, while 'report' tests
          will return only if their associated test expression *are* true.

        * message (required)

          The text message to display when the test condition is met.

        * pattern (optional)

          Optional descriptive text for the returned message that allows a
          logical grouping of tests.

          Example:

               $obj->add_test(expr => 'count(@*) > 0',
                              context => '/pattern',
                              message => 'Pattern should have at least one attribute',
                              type => 'assert',
                              pattern => 'Basic tests');

          Note that add_test() pushes a new test on to the existing test
          list, while tests() redefines the entire list.

validate('my_xml_file.xml')
     The validate() method takes the path to the XML document that you
     wish to validate as its sole argument. It returns the messages  that
     are returned during validation. When called in an array context, this
     method returns an array of the messages generated during validation.
     When called in a scalar context, this method returns a concatenated
     string of all output.

CONFORMANCE
===========

   XML::Schematron::XPath *does not conform* to the current Schematron
specification since more modern versions allow XSLT-specific expressions
to be used as tests. Please note, however, that robust validation is still
quite possible using just the XPath language.

AUTHOR
======

   Kip Hampton, khampton@totalcinema.com

COPYRIGHT
=========

   Copyright (c) 2000 Kip Hampton. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

   For information about Schematron, sample schemas, and tutorials to help
you write your own schmemas, please visit the Schematron homepage at:
http://www.ascc.net/xml/resource/schematron/

   For detailed information about the XPath syntax, please see the W3C
XPath Specification at: http://www.w3.org/TR/xpath.html

Trivial API for reading and writing XML (esp config files)
**********************************************************

NAME
====

   XML::Simple - Trivial API for reading and writing XML (esp config files)

SYNOPSIS
========

     use XML::Simple;

     my $ref = XMLin([<xml file or string>] [, <options>]);

     my $xml = XMLout($hashref [, <options>]);

   Or the object oriented way:

     require XML::Simple;

     my $xs = new XML::Simple(options);

     my $ref = $xs->XMLin([<xml file or string>] [, <options>]);

     my $xml = $xs->XMLout($hashref [, <options>]);

QUICK START
===========

   Say you have a script called foo and a file of configuration options
called *foo.xml* containing this:

     <config logdir="/var/log/foo/" debugfile="/tmp/foo.debug">
       <server name="sahara" osname="solaris" osversion="2.6">
         <address>10.0.0.101</address>
         <address>10.0.1.101</address>
       </server>
       <server name="gobi" osname="irix" osversion="6.5">
         <address>10.0.0.102</address>
       </server>
       <server name="kalahari" osname="linux" osversion="2.0.34">
         <address>10.0.0.103</address>
         <address>10.0.1.103</address>
       </server>
     </config>

   The following lines of code in foo:

     use XML::Simple;

     my $config = XMLin();

   will 'slurp' the configuration options into the hashref $config
(because no arguments are passed to XMLin() the name and location of the
XML file will be inferred from name and location of the script).  You can
dump out the contents of the hashref using Data::Dumper:

     use Data::Dumper;

     print Dumper($config);

   which will produce something like this (formatting has been adjusted for
brevity):

     {
         'logdir'        => '/var/log/foo/',
         'debugfile'     => '/tmp/foo.debug',
         'server'        => {
     	  'sahara'        => {
     	      'osversion'     => '2.6',
     	      'osname'        => 'solaris',
     	      'address'       => [ '10.0.0.101', '10.0.1.101' ]
     	  },
     	  'gobi'          => {
     	      'osversion'     => '6.5',
     	      'osname'        => 'irix',
     	      'address'       => '10.0.0.102'
     	  },
     	  'kalahari'      => {
     	      'osversion'     => '2.0.34',
     	      'osname'        => 'linux',
     	      'address'       => [ '10.0.0.103', '10.0.1.103' ]
     	  }
         }
     }

   Your script could then access the name of the log directory like this:

     print $config->{logdir};

   similarly, the second address on the server 'kalahari' could be
referenced as:

     print $config->{server}->{kalahari}->{address}->[1];

   What could be simpler?  (Rhetorical).

   For simple requirements, that's really all there is to it.  If you want
to store your XML in a different directory or file, or pass it in as a
string or even pass it in via some derivative of an IO::Handle, you'll
need to check out `"OPTIONS"' in this node.  If you want to turn off or
tweak the array folding feature (that neat little transformation that
produced $config->{server}) you'll find options for that as well.

   If you want to generate XML (for example to write a modified version of
$config back out as XML), check out XMLout().

   If your needs are not so simple, this may not be the module for you.
In that case, you might want to read `"WHERE TO FROM HERE?"' in this node.

DESCRIPTION
===========

   The XML::Simple module provides a simple API layer on top of the
XML::Parser module.  Two functions are exported: XMLin() and XMLout().

   The most common approach is to simply call these two functions
directly, but an optional object oriented interface (see `"OPTIONAL OO
INTERFACE"' in this node below) allows them to be called as methods of an
*XML::Simple* object.

XMLin()
-------

   Parses XML formatted data and returns a reference to a data structure
which contains the same information in a more readily accessible form.
(Skip down to `"EXAMPLES"' in this node below, for more sample code).

   XMLin() accepts an optional XML specifier followed by zero or more
'name => value' option pairs.  The XML specifier can be one of the
following:

A filename
     If the filename contains no directory components XMLin() will look
     for the file in each directory in the searchpath (see `"OPTIONS"' in
     this node below).  eg:

          $ref = XMLin('/etc/params.xml');

     Note, the filename '-' can be used to parse from STDIN.

undef
     If there is no XML specifier, XMLin() will check the script directory
     and each of the searchpath directories for a file with the same name
     as the script but with the extension '.xml'.  Note: if you wish to
     specify options, you must specify the value 'undef'.  eg:

          $ref = XMLin(undef, forcearray => 1);

A string of XML
     A string containing XML (recognised by the presence of '<' and '>'
     characters) will be parsed directly.  eg:

          $ref = XMLin('<opt username="bob" password="flurp" />');

An IO::Handle object
     An IO::Handle object will be read to EOF and its contents parsed. eg:

          $fh = new IO::File('/etc/params.xml');
          $ref = XMLin($fh);

XMLout()
--------

   Takes a data structure (generally a hashref) and returns an XML
encoding of that structure.  If the resulting XML is parsed using XMLin(),
it will return a data structure equivalent to the original.

   When translating hashes to XML, hash keys which have a leading '-' will
be silently skipped.  This is the approved method for marking elements of a
data structure which should be ignored by `XMLout'.  (Note: If these items
were not skipped the key names would be emitted as element or attribute
names with a leading '-' which would not be valid XML).

Caveats
-------

   Some care is required in creating data structures which will be passed
to XMLout().  Hash keys from the data structure will be encoded as either
XML element names or attribute names.  Therefore, you should use hash key
names which conform to the relatively strict XML naming rules:

   Names in XML must begin with a letter.  The remaining characters may be
letters, digits, hyphens (-), underscores (_) or full stops (.).  It is
also allowable to include one colon (:) in an element name but this should
only be used when working with namespaces - a facility well beyond the
scope of *XML::Simple*.

   You can use other punctuation characters in hash values (just not in
hash keys) however *XML::Simple* does not support dumping binary data.

   If you break these rules, the current implementation of XMLout() will
simply emit non-compliant XML which will be rejected if you try to read it
back in.  (A later version of *XML::Simple* might take a more proactive
approach).

   Note also that although you can nest hashes and arrays to arbitrary
levels, recursive data structures are not supported and will cause
XMLout() to die.

   Refer to `"WHERE TO FROM HERE?"' in this node if XMLout() is too simple
for your needs.

OPTIONS
=======

   *XML::Simple* supports a number of options (in fact as each release of
*XML::Simple* adds more options, the module's claim to the name 'Simple'
becomes more tenuous).  If you find yourself repeatedly having to specify
the same options, you might like to investigate `"OPTIONAL OO INTERFACE"'
in this node below.

   Because there are so many options, it's hard for new users to know
which ones are important, so here are the two you really need to know
about:

   * check out 'forcearray' because you'll almost certainly want to turn
     it on

   * make sure you know what the 'keyattr' option does and what its
     default value is because it may surprise you otherwise

   Both XMLin() and XMLout() expect a single argument followed by a list of
options.  An option takes the form of a 'name => value' pair.  The options
listed below are marked with 'in' if they are recognised by XMLin() and
'out' if they are recognised by XMLout().

keyattr => [ list ] (*in+out*)
     This option controls the 'array folding' feature which translates
     nested elements from an array to a hash.  For example, this XML:

          <opt>
            <user login="grep" fullname="Gary R Epstein" />
            <user login="stty" fullname="Simon T Tyson" />
          </opt>

     would, by default, parse to this:

          {
            'user' => [
          		  {
          		    'login' => 'grep',
          		    'fullname' => 'Gary R Epstein'
          		  },
          		  {
          		    'login' => 'stty',
          		    'fullname' => 'Simon T Tyson'
          		  }
          		]
          }

     If the option 'keyattr => "login"' were used to specify that the
     'login' attribute is a key, the same XML would parse to:

          {
            'user' => {
          		  'stty' => {
          			      'fullname' => 'Simon T Tyson'
          			    },
          		  'grep' => {
          			      'fullname' => 'Gary R Epstein'
          			    }
          		}
          }

     The key attribute names should be supplied in an arrayref if there is
     more than one.  XMLin() will attempt to match attribute names in the
     order supplied.  XMLout() will use the first attribute name supplied
     when 'unfolding' a hash into an array.

     Note: the keyattr option controls the folding of arrays.  By default
     a single nested element will be rolled up into a scalar rather than
     an array and therefore will not be folded.  Use the 'forcearray'
     option (below) to force nested elements to be parsed into arrays and
     therefore candidates for folding into hashes.

     The default value for 'keyattr' is ['name', 'key', 'id'].  Setting
     this option to an empty list will disable the array folding feature.

keyattr => { list } (*in+out*)
     This alternative method of specifiying the key attributes allows more
     fine grained control over which elements are folded and on which
     attributes.  For example the option 'keyattr => { package => 'id' }
     will cause any package elements to be folded on the 'id' attribute.
     No other elements which have an 'id' attribute will be folded at all.

     Note: XMLin() will generate a warning if this syntax is used and an
     element which does not have the specified key attribute is
     encountered (eg: a 'package' element without an 'id' attribute, to
     use the example above).  Warnings will only be generated if -w is in
     force.

     Two further variations are made possible by prefixing a '+' or a '-'
     character to the attribute name:

     The option 'keyattr => { user => "+login" }' will cause this XML:

          <opt>
            <user login="grep" fullname="Gary R Epstein" />
            <user login="stty" fullname="Simon T Tyson" />
          </opt>

     to parse to this data structure:

          {
            'user' => {
          		  'stty' => {
          			      'fullname' => 'Simon T Tyson',
          			      'login'    => 'stty'
          			    },
          		  'grep' => {
          			      'fullname' => 'Gary R Epstein',
          			      'login'    => 'grep'
          			    }
          		}
          }

     The '+' indicates that the value of the key attribute should be
     copied rather than moved to the folded hash key.

     A '-' prefix would produce this result:

          {
            'user' => {
          		  'stty' => {
          			      'fullname' => 'Simon T Tyson',
          			      '-login'    => 'stty'
          			    },
          		  'grep' => {
          			      'fullname' => 'Gary R Epstein',
          			      '-login'    => 'grep'
          			    }
          		}
          }

     As described earlier, `XMLout' will ignore hash keys starting with a
     '-'.

searchpath => [ list ] (in)
     Where the XML is being read from a file, and no path to the file is
     specified, this attribute allows you to specify which directories
     should be searched.

     If the first parameter to XMLin() is undefined, the default searchpath
     will contain only the directory in which the script itself is located.
     Otherwise the default searchpath will be empty.

     Note: the current directory ('.') is not searched unless it is the
     directory containing the script.

forcearray => 1 (in)
     This option should be set to '1' to force nested elements to be
     represented as arrays even when there is only one.  Eg, with
     forcearray enabled, this XML:

          <opt>
            <name>value</name>
          </opt>

     would parse to this:

          {
            'name' => [
          		  'value'
          		]
          }

     instead of this (the default):

          {
            'name' => 'value'
          }

     This option is especially useful if the data structure is likely to
     be written back out as XML and the default behaviour of rolling
     single nested elements up into attributes is not desirable.

     If you are using the array folding feature, you should almost
     certainly enable this option.  If you do not, single nested elements
     will not be parsed to arrays and therefore will not be candidates for
     folding to a hash.  (Given that the default value of 'keyattr'
     enables array folding, the default value of this option should
     probably also have been enabled too - sorry).

forcearray => [ name(s) ] (in)
     This alternative form of the 'forcearray' option allows you to
     specify a list of element names which should always be forced into an
     array representation, rather than the 'all or nothing' approach above.

noattr => 1 (*in+out*)
     When used with XMLout(), the generated XML will contain no attributes.
     All hash key/values will be represented as nested elements instead.

     When used with XMLin(), any attributes in the XML will be ignored.

suppressempty => 1 | " | undef (in)
     This option controls what XMLin() should do with empty elements (no
     attributes and no content).  The default behaviour is to represent
     them as empty hashes.  Setting this option to a true value (eg: 1)
     will cause empty elements to be skipped altogether.  Setting the
     option to 'undef' or the empty string will cause empty elements to be
     represented as the undefined value or the empty string respectively.
     The latter two alternatives are a little easier to test for in your
     code than a hash with no keys.

cache => [ cache scheme(s) ] (in)
     Because loading the XML::Parser module and parsing an XML file can
     consume a significant number of CPU cycles, it is often desirable to
     cache the output of XMLin() for later reuse.

     When parsing from a named file, *XML::Simple* supports a number of
     caching schemes.  The 'cache' option may be used to specify one or
     more schemes (using an anonymous array).  Each scheme will be tried
     in turn in the hope of finding a cached pre-parsed representation of
     the XML file.  If no cached copy is found, the file will be parsed
     and the first cache scheme in the list will be used to save a copy of
     the results.  The following cache schemes have been implemented:

    storable
          Utilises *Storable.pm* to read/write a cache file with the same
          name as the XML file but with the extension .stor

    memshare
          When a file is first parsed, a copy of the resulting data
          structure is retained in memory in the *XML::Simple* module's
          namespace.  Subsequent calls to parse the same file will return
          a reference to this structure.  This cached version will persist
          only for the life of the Perl interpreter (which in the case of
          mod_perl for example, may be some significant time).

          Because each caller receives a reference to the same data
          structure, a change made by one caller will be visible to all.
          For this reason, the reference returned should be treated as
          read-only.

    memcopy
          This scheme works identically to 'memshare' (above) except that
          each caller receives a reference to a new data structure which
          is a copy of the cached version.  Copying the data structure
          will add a little processing overhead, therefore this scheme
          should only be used where the caller intends to modify the data
          structure (or wishes to protect itself from others who might).
          This scheme uses *Storable.pm* to perform the copy.

keeproot => 1 (*in+out*)
     In its attempt to return a data structure free of superfluous detail
     and unnecessary levels of indirection, XMLin() normally discards the
     root element name.  Setting the 'keeproot' option to '1' will cause
     the root element name to be retained.  So after executing this code:

          $config = XMLin('<config tempdir="/tmp" />', keeproot => 1)

     You'll be able to reference the tempdir as
     `$config->{config}->{tempdir}' instead of the default
     `$config->{tempdir}'.

     Similarly, setting the 'keeproot' option to '1' will tell XMLout()
     that the data structure already contains a root element name and it
     is not necessary to add another.

rootname => 'string' (out)
     By default, when XMLout() generates XML, the root element will be
     named 'opt'.  This option allows you to specify an alternative name.

     Specifying either undef or the empty string for the rootname option
     will produce XML with no root elements.  In most cases the resulting
     XML fragment will not be 'well formed' and therefore could not be
     read back in by XMLin().  Nevertheless, the option has been found to
     be useful in certain circumstances.

forcecontent (in)
     When XMLin() parses elements which have text content as well as
     attributes, the text content must be represented as a hash value
     rather than a simple scalar.  This option allows you to force text
     content to always parse to a hash value even when there are no
     attributes.  So for example:

          XMLin('<opt><x>text1</x><y a="2">text2</y></opt>', forcecontent => 1)

     will parse to:

          {
            'x' => {           'content' => 'text1' },
            'y' => { 'a' => 2, 'content' => 'text2' }
          }

     instead of:

          {
            'x' => 'text1',
            'y' => { 'a' => 2, 'content' => 'text2' }
          }

contentkey => 'keyname' (*in+out*)
     When text content is parsed to a hash value, this option let's you
     specify a name for the hash key to override the default 'content'.
     So for example:

          XMLin('<opt one="1">Text</opt>', contentkey => 'text')

     will parse to:

          { 'one' => 1, 'text' => 'Text' }

     instead of:

          { 'one' => 1, 'content' => 'Text' }

     XMLout() will also honour the value of this option when converting a
     hashref to XML.

xmldecl => 1  or  xmldecl => 'string'  (out)
     If you want the output from XMLout() to start with the optional XML
     declaration, simply set the option to '1'.  The default XML
     declaration is:

          <?xml version='1' standalone='yes'?>

     If you want some other string (for example to declare an encoding
     value), set the value of this option to the complete string you
     require.

outputfile => <file specifier> (out)
     The default behaviour of XMLout() is to return the XML as a string.
     If you wish to write the XML to a file, simply supply the filename
     using the 'outputfile' option.  Alternatively, you can supply an IO
     handle object instead of a filename.

noescape => 1 (out)
     By default, XMLout() will translate the characters '<', '>', '&' and
     '"' to '&lt;', '&gt;', '&amp;' and '&quot' respectively.  Use this
     option to suppress escaping (presumably because you've already
     escaped the data in some more sophisticated manner).

parseropts => [ XML::Parser Options ] (in)
     Use this option to specify parameters that should be passed to the
     constructor of the underlying XML::Parser object.  For example to
     turn on the namespace processing mode, you could say:

          XMLin($xml, parseropts => [ Namespaces => 1 ])

OPTIONAL OO INTERFACE
=====================

   The procedural interface is both simple and convenient however there
are a couple of reasons why you might prefer to use the object oriented
(OO) interface:

   * to define a set of default values which should be used on all
     subsequent calls to XMLin() or XMLout()

   * to override methods in *XML::Simple* to provide customised behaviour

   The default values for the options described above are unlikely to suit
everyone.  The OO interface allows you to effectively override
*XML::Simple*'s defaults with your preferred values.  It works like this:

   First create an XML::Simple parser object with your preferred defaults:

     my $xs = new XML::Simple(forcearray => 1, keeproot => 1);

   then call XMLin() or XMLout() as a method of that object:

     my $ref = $xs->XMLin($xml);
     my $xml = $xs->XMLout($ref);

   You can also specify options when you make the method calls and these
values will be merged with the values specified when the object was
created.  Values specified in a method call take precedence.

   Overriding methods is a more advanced topic but might be useful if for
example you wished to provide an alternative routine for escaping
character data (the escape_value method) or for building the initial parse
tree (the build_tree method).

ERROR HANDLING
==============

   The XML standard is very clear on the issue of non-compliant documents.
An error in parsing any single element (for example a missing end tag)
must cause the whole document to be rejected.  *XML::Simple* will die with
an appropriate message if it encounters a parsing error.

   If dying is not appropriate for your application, you should arrange to
call XMLin() in an eval block and look for errors in $@.  eg:

     my $config = eval { XMLin() };
     PopUpMessage($@) if($@);

   Note, there is a common misconception that use of eval will
significantly slow down a script.  While that may be true when the code
being eval'd is in a string, it is not true of code like the sample above.

EXAMPLES
========

   When XMLin() reads the following very simple piece of XML:

     <opt username="testuser" password="frodo"></opt>

   it returns the following data structure:

     {
       'username' => 'testuser',
       'password' => 'frodo'
     }

   The identical result could have been produced with this alternative XML:

     <opt username="testuser" password="frodo" />

   Or this (although see 'forcearray' option for variations):

     <opt>
       <username>testuser</username>
       <password>frodo</password>
     </opt>

   Repeated nested elements are represented as anonymous arrays:

     <opt>
       <person firstname="Joe" lastname="Smith">
         <email>joe@smith.com</email>
         <email>jsmith@yahoo.com</email>
       </person>
       <person firstname="Bob" lastname="Smith">
         <email>bob@smith.com</email>
       </person>
     </opt>

     {
       'person' => [
                     {
                       'email' => [
                                    'joe@smith.com',
                                    'jsmith@yahoo.com'
                                  ],
                       'firstname' => 'Joe',
                       'lastname' => 'Smith'
                     },
                     {
                       'email' => 'bob@smith.com',
                       'firstname' => 'Bob',
                       'lastname' => 'Smith'
                     }
                   ]
     }

   Nested elements with a recognised key attribute are transformed
(folded) from an array into a hash keyed on the value of that attribute:

     <opt>
       <person key="jsmith" firstname="Joe" lastname="Smith" />
       <person key="tsmith" firstname="Tom" lastname="Smith" />
       <person key="jbloggs" firstname="Joe" lastname="Bloggs" />
     </opt>

     {
       'person' => {
                     'jbloggs' => {
                                    'firstname' => 'Joe',
                                    'lastname' => 'Bloggs'
                                  },
                     'tsmith' => {
                                   'firstname' => 'Tom',
                                   'lastname' => 'Smith'
                                 },
                     'jsmith' => {
                                   'firstname' => 'Joe',
                                   'lastname' => 'Smith'
                                 }
                   }
     }

   The <anon> tag can be used to form anonymous arrays:

     <opt>
       <head><anon>Col 1</anon><anon>Col 2</anon><anon>Col 3</anon></head>
       <data><anon>R1C1</anon><anon>R1C2</anon><anon>R1C3</anon></data>
       <data><anon>R2C1</anon><anon>R2C2</anon><anon>R2C3</anon></data>
       <data><anon>R3C1</anon><anon>R3C2</anon><anon>R3C3</anon></data>
     </opt>

     {
       'head' => [
     		  [ 'Col 1', 'Col 2', 'Col 3' ]
     		],
       'data' => [
     		  [ 'R1C1', 'R1C2', 'R1C3' ],
     		  [ 'R2C1', 'R2C2', 'R2C3' ],
     		  [ 'R3C1', 'R3C2', 'R3C3' ]
     		]
     }

   Anonymous arrays can be nested to arbirtrary levels and as a special
case, if the surrounding tags for an XML document contain only an
anonymous array the arrayref will be returned directly rather than the
usual hashref:

     <opt>
       <anon><anon>Col 1</anon><anon>Col 2</anon></anon>
       <anon><anon>R1C1</anon><anon>R1C2</anon></anon>
       <anon><anon>R2C1</anon><anon>R2C2</anon></anon>
     </opt>

     [
       [ 'Col 1', 'Col 2' ],
       [ 'R1C1', 'R1C2' ],
       [ 'R2C1', 'R2C2' ]
     ]

   Elements which only contain text content will simply be represented as a
scalar.  Where an element has both attributes and text content, the element
will be represented as a hashref with the text content in the 'content'
key:

     <opt>
       <one>first</one>
       <two attr="value">second</two>
     </opt>

     {
       'one' => 'first',
       'two' => { 'attr' => 'value', 'content' => 'second' }
     }

   Mixed content (elements which contain both text content and nested
elements) will be not be represented in a useful way - element order and
significant whitespace will be lost.  If you need to work with mixed
content, then XML::Simple is not the right tool for your job - check out
the next section.

WHERE TO FROM HERE?
===================

   *XML::Simple* is by nature very simple.

   * The parsing process liberally disposes of 'surplus' whitespace - some
     applications will be sensitive to this.

   * Slurping data into a hash will implicitly discard information about
     attribute order.  Normally this would not be a problem because any
     items for which order is important would typically be encoded as
     elements rather than attributes.  However *XML::Simple*'s aggressive
     slurping and folding algorithms can defeat even these techniques.

   * The API offers little control over the output of XMLout().  In
     particular, it is not especially likely that feeding the output from
     XMLin() into XMLout() will reproduce the original XML (although
     passing the output from XMLout() into XMLin() should reproduce the
     original data structure).

   * XMLout() cannot produce well formed HTML unless you feed it with care
     - hash keys must conform to XML element naming rules and undefined
     values should be avoided.

   * XMLout() does not currently support encodings (although it shouldn't
     stand in your way if you feed it encoded data).

   * If you're attempting to get the output from XMLout() to conform to a
     specific DTD, you're almost certainly using the wrong tool for the
     job.

   If any of these points are a problem for you, then *XML::Simple* is
probably not the right module for your application.  The following section
is intended to give pointers which might help you select a more powerful
tool - it's a bit sketchy right now but submissions are welcome.

XML::Parser
     *XML::Simple* is built on top of XML::Parser, so if you have
     *XML::Simple* working you already have XML::Parser installed.  This
     is a comprehensive, fast, industrial strength (non-validating)
     parsing tool built on top of James Clark's 'expat' library.  It does
     support converting XML into a Perl tree structure (with full support
     for mixed content) but for arbritrarily large documents you're
     probably better off defining handler routines for XML::Parser to call
     as each element is parsed.  The distribution includes a number of
     sample applications.

XML::DOM
     The data structure returned by *XML::Simple* was designed for
     convenience rather than standards compliance.  XML::DOM is a parser
     built on top of XML::Parser, which returns a 'Document' object
     conforming to the API of the Document Object Model as described at
     http://www.w3.org/TR/REC-DOM-Level-1 .  This Document object can then
     be examined, modified and written back out to a file or converted to
     a string.

XML::Grove
     Compliance with the Document Object Model might be particularly
     useful when porting code to or from another language.  However, if
     you're looking for a simpler, 'perlish' object interface, take a look
     at XML::Grove.

XML::Twig
     XML::Twig offers a tree-oriented interface to a document while still
     allowing the processing of documents of any size. It allows
     processing chunks of documents in tree-mode which can then be flushed
     or purged from the memory.  The XML::Twig page is at
     http://standards.ieee.org/resources/spasystem/twig/

libxml-perl
     *libxml-perl* is a collection of Perl modules, scripts, and documents
     for working with XML in Perl. The distribution includes PerlSAX - a
     Perl implementation of the SAX API.  It also include *XML::PatAct*
     modules for processing XML by defining patterns and associating them
     with actions.  For more details see
     http://bitsko.slc.ut.us/libxml-perl/ .

XML::PYX
     XML::PYX allows you to apply Unix command pipelines (using grep, sed
     etc) to filter or transform XML files.  Ideally suited for tasks such
     as extracting all text content or stripping out all occurrences of a
     particular tag without having to write a Perl script at all.  It can
     also be used for transforming HTML to XHTML.

XML::RAX
     If you wish to process XML files containing a series of 'records',
     XML::RAX provides a simple purpose-designed interface.  If it still
     hasn't made it to CPAN, try: http://www.dancentury.com/robh/

XML::Writer
     XML::Writer is a helper module for Perl programs that write XML
     documents.

XML::Dumper
     XML::Dumper dumps Perl data to a structured XML format. XML::Dumper
     can also read XML data that was previously dumped by the module and
     convert it back to Perl.

   Don't forget to check out the Perl XML FAQ at:
http://www.perlxml.com/faq/perl-xml-faq.html

STATUS
======

   This version (1.05) is the current stable version.

SEE ALSO
========

   *XML::Simple* requires XML::Parser and File::Spec.  The optional caching
functions require Storable.

COPYRIGHT
=========

   Copyright 1999 Grant McLean <grantm@web.co.nz>

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl extension allowing a simple object representation of a parsed XML::Parser tree.
************************************************************************************

NAME
====

   XML::SimpleObject - Perl extension allowing a simple object
representation of a parsed XML::Parser tree.

SYNOPSIS
========

     use XML::SimpleObject;

     my $parser = new XML::Parser (ErrorContext => 2, Style => "Tree");
     my $xmlobj = new XML::SimpleObject ($parser->parse($XML));

     my $filesobj = $xmlobj->child("files")->child("file");

     $filesobj->name;
     $filesobj->value;
     $filesobj->attribute("type");

     %attributes    = $filesobj->attributes;
     @children      = $filesobj->children;
     @some_children = $filesobj->children("some");
     @chilren_names = $filesobj->children_names;

DESCRIPTION
===========

   This is a short and simple class allowing simple object access to a
parsed XML::Parser tree, with methods for fetching children and attributes
in as clean a manner as possible. My apologies for further polluting the
XML:: space; this is a small and quick module, with easy and compact usage.

USAGE
=====

$xmlobj = new XML::SimpleObject($parser->parse($XML))
     $parser is an XML::Parser object created with Style "Tree":

          my $parser = new XML::Parser (ErrorContext => 2, Style => "Tree");

     After creating $xmlobj, this object can now be used to browse the XML
     tree with the following methods.

$xmlobj->child('NAME')
     This will return a new XML::SimpleObject object using the child
     element NAME.

$xmlobj->children('NAME')
     Called with an argument NAME, children() will return an array of
     XML::SimpleObject objects of element NAME. Thus, if $xmlobj
     represents the top-level XML element, 'children' will return an array
     of all elements directly below the top-level that have the element
     name NAME.

$xmlobj->children
     Called without arguments, 'children()' will return an array of
     XML::SimpleObject s for all children elements of $xmlobj. These are
     not in the order they occur in  the XML document.

$xmlobj->children_names
     This will return an array of all the names of child elements for
     $xmlobj. You can use this to step through all the children of a given
     element (see EXAMPLES). Each name will occur only once, even if
     multiple children exist with that name.

$xmlobj->value
     If the element represented by $xmlobj contains any PCDATA, this
     method will return that text data.

$xmlobj->attribute('NAME')
     This returns the text for an attribute NAME of the XML element
     represented by $xmlobj.

$xmlobj->attributes
     This returns a hash of key/value pairs for all elements in element
     $xmlobj.

EXAMPLES
========

   Given this XML document:

     <files>
       <file type="symlink">
         <name>/etc/dosemu.conf</name>
         <dest>dosemu.conf-drdos703.eval</dest>
       </file>
       <file>
         <name>/etc/passwd</name>
         <bytes>948</bytes>
       </file>
     </files>

   You can then interpret the tree as follows:

     my $parser = new XML::Parser (ErrorContext => 2, Style => "Tree");
     my $xmlobj = new XML::SimpleObject ($parser->parse($XML));

     print "Files: \n";
     foreach my $element ($xmlobj->child("files")->children("file"))
     {
       print "  filename: " . $element->child("name")->value . "\n";
       if ($element->attribute("type"))
       {
         print "    type: " . $element->attribute("type") . "\n";
       }
       print "    bytes: " . $element->child("bytes")->value . "\n";
     }

   This will output:

     Files:
       filename: /etc/dosemu.conf
         type: symlink
         bytes: 20
       filename: /etc/passwd
         bytes: 948

   You can use 'children()' without arguments to step through all children
of a given element:

     my $filesobj = $xmlobj->child("files")->child("file");
     foreach my $child ($filesobj->children) {
       print "child: ", $child->name, ": ", $child->value, "\n";
     }

   For the tree above, this will output:

     child: bytes: 20
     child: dest: dosemu.conf-drdos703.eval
     child: name: /etc/dosemu.conf

   Using 'children_names()', you can step through all children for a given
element:

     my $filesobj = $xmlobj->child("files");
     foreach my $childname ($filesobj->children_names) {
         print "$childname has children: ";
         print join (", ", $filesobj->child($childname)->children_names), "\n";
     }

   This will print:

     file has children: bytes, dest, name

   By always using 'children()', you can step through each child object,
retrieving them with 'child()'.

AUTHOR
======

   Dan Brian <dbrian@brians.org>

SEE ALSO
========

   perl(1), XML::Parser.

Creates and XML Stream connection and parses return data
********************************************************

NAME
====

   XML::Stream - Creates and XML Stream connection and parses return data

SYNOPSIS
========

     XML::Stream is an attempt at solidifying the use of XML via streaming.

DESCRIPTION
===========

     This module provides the user with methods to connect to a remote server,
     send a stream of XML to the server, and receive/parse an XML stream from
     the server.  It is primarily based work for the Etherx XML router
     developed by the Jabber Development Team.  For more information about
     this project visit http://etherx.jabber.org/stream/.

     XML::Stream gives the user the ability to define a central callback
     that will be used to handle the tags received from the server.  These
     tags are passed in the format of an XML::Parser::Tree object.  After
     the closing tag of an object is seen, the tree is finished and passed
     to the call back function.  What the user does with it from there is up
     to them.

     For a detailed description of how this module works, and about the data
     structure that it returns, please view the source of Stream.pm and
     look at the detailed description at the end of the file.

METHODS
=======

     new(debug=>string,       - creates the XML::Stream object.  debug should
         debugfh=>FileHandle,   be set to the path for the debug log to be
         debuglevel=>0|1|2,     written.  If set to "stdout" then the debug
         debugtime=>0|1)        will go there.   Also, you can specify a
                                filehandle that already exists byt using
                                debugfh.  debuglevel determines the amount of
                                debug to generate.  0 is the least, 2 is the
                                most.  debugtime determines wether a timestamp
                                should be preappended to the entry.

     Connect(hostname=>string,       - opens a tcp connection to the
             port=>integer,            specified server and sends the proper
             to=>string,               opening XML Stream tag.  hostname,
             from=>string,             port, and namespace are required.
             myhostname=>string,       namespaces allows you to use
             namespace=>string,        XML::Stream::Namespace objects.
             namespaced=>array,        to is needed if you want the stream
             connectiontype=>string)   to attribute to be something other
                                       than the hostname you are connecting
                                       to.  from is needed if you want the
                                       stream from attribute to be something
                                       other than the hostname you are
                                       connecting from.  myhostname should
                                       not be needed but if the module cannot
                                       determine your hostname properly (check
                                       the debug log), set this to the correct
                                       value, or if you want the other side
                                       of the  stream to think that you are
                                       someone else.  The type determines
                                       the kind of connection that is made:
                                         "tcpip"    - TCP/IP (default)
                                         "stdinout" - STDIN/STDOUT

     Disconnect() - sends the proper closing XML tag and closes the socket
                    down.

     Process(integer) - waits for data to be available on the socket.  If
                        a timeout is specified then the Process function
                        waits that period of time before returning nothing.
                        If a timeout period is not specified then the
                        function blocks until data is received.

   * DEPRECATED *  OnNode(function pointer) - This function is deprecated
and will be *                             removed in a future version.
Instead, use *                             the
SetCallBacks(node=>function) to do the *                             same
thing...

     SetCallBacks(node=>function,   - sets the callback that should be
                  update=>function)   called in various situations.  node
                                      is used to handle the XML::Parser::Tree
                                      trees that are built for each top
                                      level tag.  Update is used for when
                                      Process is blocking waiting for data,
                                      but you want your original code to be
                                      updated.

     GetRoot() - returns the attributes that the stream:stream tag sent by
                 the other end listed in a hash.

     GetSock() - returns a pointer to the IO::Socket object.

     Send(string) - sends the string over the connection as is.  This
                    does no checking if valid XML was sent or not.  Best
                    behavior when sending information.

     GetErrorCode() - returns a string that will hopefully contain some
                      useful information about why Process or Connect
                      returned an undef to you.

EXAMPLES
========

     ##########################
     # simple example

     use XML::Stream;

     $stream = new XML::Stream;

     my $status = $stream->Connect(hostname => "jabber.org",
                                   port => 5222,
                                   namespace => "jabber:client");

     if (!defined($status)) {
       print "ERROR: Could not connect to server\n";
       print "       (",$stream->GetErrorCode(),")\n";
       exit(0);
     }

     while($node = $stream->Process()) {
       # do something with $node
     }

     $stream->Disconnect();

     ###########################
     # example using a handler

     use XML::Stream;

     $stream = new XML::Stream;
     $stream->SetCallBacks(node=>\&noder);
     $stream->Connect(hostname => "jabber.org",
     		   port => 5222,
     		   namespace => "jabber:client",
     		   timeout => undef) || die $!;

     # Blocks here forever, noder is called for incoming
     # packets when they arrive.
     while(defined($stream->Process())) { }

     print "ERROR: Stream died (",$stream->GetErrorCode(),")\n";

     sub noder
     {
       my $node = shift;
       # do something with $node
     }

AUTHOR
======

   Tweaked, tuned, and brightness changes by Ryan Eatmon, reatmon@ti.com
in May of 2000.  Colorized, and Dolby Surround sound added by Thomas
Charron, tcharron@jabber.org By Jeremie in October of 1999 for
http://etherx.jabber.org/streams/

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Object to make defining Namespaces easier in                           XML::Stream.
***********************************************************************************

NAME
====

   XML::Stream::Namespace - Object to make defining Namespaces easier in
                      XML::Stream.

SYNOPSIS
========

   XML::Stream::Namespace is a helper package to XML::Stream.  It provides
a clean way of defining Namespaces for XML::Stream to use when connecting.

DESCRIPTION
===========

     This module allows you to set and read elements from an XML::Stream
     Namespace.

METHODS
=======

     SetNamespace("mynamespace");
     SetXMLNS("http://www.mynamespace.com/xmlns");
     SetAttributes(attrib1=>"value1",
                   attrib2=>"value2");

     GetNamespace() returns "mynamespace"
     GetXMLNS() returns "http://www.mynamespace.com/xmlns"
     GetAttributes() returns a hash ( attrib1=>"value1",attrib2=>"value2")
     GetStream() returns the following string:
       "xmlns:mynamespace='http://www.nynamespace.com/xmlns'
        mynamespace:attrib1='value1'
        mynamespace:attrib2='value2'"

EXAMPLES
========

     $myNamespace = new XML::Stream::Namespace("mynamspace");
     $myNamespace->SetXMLNS("http://www.mynamespace.org/xmlns");
     $myNamespace->SetAttributes(foo=>"bar",
                                 bob=>"vila");

     $stream = new XML::Stream;
     $stream->Connect(name=>"foo.bar.org",
                      port=>1234,
                      namespace=>"foo:bar",
                      namespaces=>[ $myNamespace ]);

     #
     # The above Connect will send the following as the opening string
     # of the stream to foo.bar.org:1234...
     #
     #   <stream:stream
     #    xmlns:stream="http://etherx.jabber.org/streams"
     #    to="foo.bar.org"
     #    xmlns="foo:bar"
     #    xmlns:mynamespace="http://www.mynamespace.org/xmlns"
     #    mynamespace:foo="bar"
     #    mynamespace:bob="vila">
     #

AUTHOR
======

   Written by Ryan Eatmon in February 2000 Idea By Thomas Charron in
January of 2000 for http://etherx.jabber.org/streams/

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

SAX XML Parser for XML Streams
******************************

NAME
====

     XML::Stream::Parser - SAX XML Parser for XML Streams

SYNOPSIS
========

     Light weight XML parser that builds XML::Parser::Tree objects from the
     incoming stream and passes them to a function to tell whoever is using
     it that there are new packets.

DESCRIPTION
===========

     This module provides a very light weight parser

METHODS
=======

EXAMPLES
========

AUTHOR
======

   By Ryan Eatmon in January of 2001 for http://jabber.org/

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

XML DTD Parser and Verifier
***************************

NAME
====

     XML::Stream::Parser::DTD - XML DTD Parser and Verifier

SYNOPSIS
========

     This is a work in progress.  I had need for a DTD parser and verifier
     and so am working on it here.  If you are reading this then you are
     snooping.  =)

DESCRIPTION
===========

     This module provides the initial code for a DTD parser and verifier.

METHODS
=======

EXAMPLES
========

AUTHOR
======

   By Ryan Eatmon in February of 2001 for http://jabber.org/

COPYRIGHT
=========

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Read or write XML data in PYX format via tied filehandle
********************************************************

NAME
====

   XML::TiePYX - Read or write XML data in PYX format via tied filehandle

SYNOPSIS
========

     use XML::TiePYX;

     tie *XML,'XML::TiePYX','file.xml'

     open IN,'file.xml' or die $!;
     tie *XML,'XML::TiePYX',\*IN,Condense=>0;

     my $text='<tag xmlns="http://www.omsdev.com">text</tag>';
     tie *XML,'XML::TiePYX',\$text,Namespaces=>1;

     tie *XML,'XML::TiePYX',\*STDOUT;
     print XML "(start\n","-Hello, world!\n",")start\n";

DESCRIPTION
===========

   XML::TiePYX lets you use a tied filehandle to read from or write to an
XML file or string.  PYX is a line-oriented, parsed representation of XML
developed by Sean McGrath (http://www.pyxie.org).  Each line corresponds to
one "event" in the XML, with the first character indicating the type of
event:

(
     The start of an element; the rest of the line is its name.

A
     An attribute; the rest of the line is the attribute's name, a space,
     and its value.

)
     The end of an element; the rest of the line is its name.

-
     Literal text (characters).  The rest of the line is the text.

?
     A processing instruction.  The rest of the line is the instruction's
     target, a space, and the instruction's value.

   Newlines in attribute values, text, and processing instruction values
are represented as the literal sequence '\n' (that is, a backslash
followed by an 'n').  By default, consecutive runs of characters are
always gathered into a single text event when reading, but this behavior
can be disabled.  Comments are *not* available through PYX.

   Just as SAX is an API well suited to "push"-mode XML parsing, PYX is
well- suited to "pull"-mode parsing where you want to capture the state of
the parse through your program's flow of code rather than through a bunch
of state variables.  This module uses incremental parsing to avoid the
need to buffer up large numbers of events.

   This module implements an (unofficial) extension to the PYX format to
allow namespace processing.  If namespaces are enabled, an element or
attribute name will be prefixed by its namespace URI (*NOT* any namespace
prefix used in the document) enclosed in curly braces.  A name with no
namespace will be prefixed with {}.  At the present time, this module does
not implement namespace processing in output mode; attempting to write
'(', ')', or 'A' lines that contain a namespace URI in curly braces will
merely result in generating ill-formed element or attribute names.

INTERFACE
=========

     tie *tied_handle, 'XML::TiePYX', source, [Option=>value,...]

   *tied_handle* is the filehandle which the PYX events will be read from
or written to.

   source is either a reference to a string containing the XML, the name of
a file containing the XML, or an open IO::Handle or filehandle glob
reference which the XML can be read or written to.

   The Options can be any options allowed by XML::Parser and
XML::Parser::Expat, as well as four module-specific options:

Validating
     This will provide a validating parse by using XML::Checker::Parser in
     place of XML::Parser if set to a true value.

Condense
     Causes all consecutive runs of character data to be gathered up into a
     single PYX event if set to a true value (the default).  If set false,
     multiple consecutive character data events may occur in the stream
     (which may be desirable when dealing with large chunks of text).
     This option has no effect when writing.

Latin
     If set to a true value, causes Unicode characters in the range
     128-255 to be returned as ISO-Latin-1 characters rather than UTF-8
     characters when reading, and an XML declaration specifying an
     encoding of "ISO-8859-1" to be output when writing.

Catalog
     Specifies the URL of a catalog to use for resolving public
     identifiers and remapping system identifiers used in document type
     declarations or external entity references.  This option requires
     XML::Catalog to be installed.

   The tied filehandle may be read from with either the diamond operator
(<HANDLE>), getc(), or read().  The diamond operator always returns a line
at a time regardless of the setting of $/.  It may be written to with
print() or printf(); it is necessary to print one or more complete PYX
lines at a time.  This module does not support read/write mode.

EXAMPLE
=======

   This program (*psectp.plx* in the distribution) prints a numbered
outline from an XML file in which an <outline> can contain zero or more
<sect>s, each with a title attribute, and each <sect> can contain zero or
more nested <sect>s or <para>s containing text, as in the *sects.otl* file
included with the distribution.  The -c option makes it print just a table
of contents.

   This is actually a traditional recursive-descent parser using PYX
events as tokens.

     #!/usr/bin/perl -w

     use strict;
     use XML::TiePYX;
     use Text::Wrap;
     use Getopt::Std;

     my (@sectnums,%opts);

     getopts('c',\%opts);

     die "usage: psect [-c] file\n" unless @ARGV==1;

     tie *XML,'XML::TiePYX',$ARGV[0];
     die "illegal structure" unless get_event() =~ /^\(outline/;
     push @sectnums,0;
     print_sect() while get_event() =~ /^\(sect/;
     die unless /^\)outline/;
     close XML;

     sub print_sect {
       <XML>=~/^Atitle (.*)/ or die "missing title";
       ++$sectnums[-1];
       print ' ' x (4*$#sectnums),join('.',@sectnums)," $1\n";
       print "\n" unless $opts{c};
       push @sectnums,0;
       while (get_event() !~ /^\)sect/) {
         /^\(sect/ and print_sect(),next;
         /^\(para/ and print_para(),next;
         die "illegal structure";
       }
       pop @sectnums;
     }

     sub print_para() {
       die "illegal structure" unless <XML> =~ /^-(.*)/;
       $_=$1;
       s/\\n/ /g;
       s/^\s+//;
       s/\s+$//;
       print wrap((' ' x (4*($#sectnums-1))) x 2,$_),"\n\n" unless $opts{c};
       die "illegal structure" unless <XML> =~ /^\)para/;
     }

     sub get_event {
       $_=<XML>;
       $_=<XML> if /^-(\s|\\n)*$/;
       $_;
     }

RATIONALE
=========

   There's already an XML::PYX module (written by Matt Sergeant)
available, so why another PYX implementation?  Mainly because XML::PYX is
intended to be used in a standalone PYX-outputting program which you open
as a pipe.  That works very well under Unix, aside from the overhead of
forking a separate process, but is problematic on Win32 systems for a
variety of niggling reasons: the standalone script is supplied as a batch
file, whose output can't be properly redirected into a pipe unless you
invoke it as 'perl /perl/bin/pyx|' instead of just 'pyx|'.  Both Win95 and
Win98, as well as possibly other Win32 systems, implement pipes using
temporary files and the reading process can't start reading until the
writing process is done writing, which means that if you're parsing a huge
file you may have to wait a long time before getting *any* output.  The
ability to guarantee a single character data event for any run of
characters can often simplify processing.  And finally, when I wrote this
the only supported namespace- aware way to parse XML was the raw handlers
interface of XML::Parser, which is needlessly complicated for simple
applications (there are, of course, those who would argue that "simple
applications" and "namespace-aware" are mutually-exclusive categories).

BUGS
====

   The Validating option does not work correctly, as XML::Checker::Parser
does not implement the parse_start() method.

   Error handling leaves much to be desired.

AUTHOR
======

   Eric Bohlman (ebohlman@netcom.com, ebohlman@omsdev.com)

COPYRIGHT
=========

   Copyright 2000 Eric Bohlman.  All rights reserved.

   This program is free software; you can use/modify/redistribute it under
the same terms as Perl itself.

SEE ALSO
========

     XML::PYX
     XML::Parser
     XML::Parser::Expat
     XML::Checker
     XML::Catalog
     perl(1).

Simplified interface to XML::Parser
***********************************

NAME
====

   XML::TokeParser - Simplified interface to XML::Parser

SYNOPSIS
========

     use XML::TokeParser;

     #parse from file
     my $p=XML::TokeParser->new('file.xml')

     #parse from open handle
     open IN,'file.xml' or die $!;
     my $p=XML::TokeParser->new(\*IN,Noempty=>1);

     #parse literal text
     my $text='<tag xmlns="http://www.omsdev.com">text</tag>';
     my $p=XML::TokeParser->new(\$text,Namespaces=>1);

     #read next token
     my $token=$p->get_token();

     #skip to <title> and read text
     $p->get_tag('title');
     $p->get_text();

     #read text of next <para>, ignoring any internal markup
     $p->get_tag('para');
     $p->get_trimmed_text('/para');

DESCRIPTION
===========

   XML::TokeParser provides a procedural ("pull mode") interface to
XML::Parser in much the same way that Gisle Aas' HTML::TokeParser provides
a procedural interface to HTML::Parser.  XML::TokeParser splits its XML
input up into "tokens," each corresponding to an XML::Parser event.

   A token is a reference to an array whose first element is an event-type
string and whose last element is the literal text of the XML input that
generated the event, with intermediate elements varying according to the
event type:

Start tag
     The token has five elements: 'S', the element's name, a reference to
     a hash of attribute values keyed by attribute names, a reference to
     an array of attribute names in the order in which they appeared in
     the tag, and the literal text.

End tag
     The token has three elements: 'E', the element's name, and the
     literal text.

Character data (text)
     The token has three elements: 'T', the parsed text, and the literal
     text.  All contiguous runs of text are gathered into single tokens;
     there will never be two 'T' tokens in a row.

Comment
     The token has three elements: 'C', the parsed text of the comment,
     and the literal text.

Processing instruction
     The token has four elements: 'PI', the target, the data, and the
     literal text.

   The literal text includes any markup delimiters (pointy brackets,
<![CDATA[, etc.), entity references, and numeric character references and
is in the XML document's original character encoding.  All other text is in
UTF-8 (unless the Latin option is set, in which case it's in ISO-8859-1)
regardless of the original encoding, and all entity and character
references are expanded.

   If the Namespaces option is set, element and attribute names are
prefixed by their (possibly empty) namespace URIs enclosed in curly
brackets and xmlns:* attributes do not appear in 'S' tokens.

METHODS
=======

$p = XML::TokeParser->new($input, [options])
     Creates a new parser, specifying the input source and any options.  If
     $input is a string, it is the name of the file to parse.  If $input
     is a reference to a string, that string is the actual text to parse.
     If $input is a reference to a typeglob or an IO::Handle object
     corresponding to an open file or socket, the text read from the
     handle will be parsed.

     Options are name=>value pairs and can be any of the following:

    Namespaces
          If set to a true value, namespace processing is enabled.

    ParseParamEnt
          This option is passed on to the underlying XML::Parser object;
          see that module's documentation for details.

    Noempty
          If set to a true value, text tokens consisting of only
          whitespace (such as those created by indentation and line breaks
          in between tags) will be ignored.

    Latin
          If set to a true value, all text other than the literal text
          elements of tokens will be translated into the ISO 8859-1
          (Latin-1) character encoding rather than the normal UTF-8
          encoding.

    Catalog
          The value is the URI of a catalog file used to resolve PUBLIC
          and SYSTEM identifiers.  See XML::Catalog for details.

$token = $p->get_token()
     Returns the next token, as an array reference, from the input.
     Returns undef if there are no remaining tokens.

$p->unget_token($token,...)
     Pushes tokens back so they will be re-read.  Useful if you've read
     one or more tokens to far.

$token = $p->get_tag( [$token] )
     If no argument given, skips tokens until the next start tag or end tag
     token. If an argument is given, skips tokens until the start tag or
     end tag (if the argument begins with '/') for the named element.  The
     returned token does not include an event type code; its first element
     is the element name, prefixed by a '/' if the token is for an end tag.

$text = $p->get_text( [$token] )
     If no argument given, returns the text at the current position, or an
     empty string if the next token is not a 'T' token.  If an argument is
     given, gathers up all text between the current position and the
     specified start or end tag, stripping out any intervening tags (much
     like the way a typical Web browser deals with unknown tags).

$text = $p->get_trimmed_text( [$token])
     Like get_text(), but deletes any leading or trailing whitespaces and
     collapses multiple whitespace (including newlines) into single spaces.

DIFFERENCES FROM HTML::TokeParser
=================================

   Uses a true XML parser rather than a modified HTML parser.

   Text and comment tokens include extracted text as well as literal text.

   PI tokens include target and data as well as literal text.

   No tokens for declarations.

   No "textify" hash.

EXAMPLES
========

Print method signatures from the XML version of this PODpage
------------------------------------------------------------

     #!/usr/bin/perl -w
     use strict;
     use XML::TokeParser;
     my $t;
     my $p=XML::TokeParser->new('tokeparser.xml',Noempty=>1) or die $!;
     while ($p->get_tag('title') && $p->get_text('/title') ne 'METHODS') {
       ;
     }
     $p->get_tag('list');
     while (($t=$p->get_tag()->[0]) ne '/list') {
       if ($t eq 'item') {
         $p->get_tag('itemtext');
         print $p->get_text('/itemtext'),"\n";
         $p->get_tag('/item');
       }
       else {
         $p->get_tag('/list');  # assumes no nesting here!
       }
     }

AUTHOR
======

   Eric Bohlman (ebohlman@omsdev.com)

   Copyright (c) 2001 Eric Bohlman. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

SEE ALSO
========

     XML::Parser
     XML::Catalog
     HTML::TokeParser

Parser that builds a tree of XML::Element objects
*************************************************

NAME
====

   XML::TreeBuilder - Parser that builds a tree of XML::Element objects

SYNOPSIS
========

     foreach my $file_name (@ARGV) {
       my $tree = XML::TreeBuilder->new; # empty tree
       $tree->parse_file($file_name);
       print "Hey, here's a dump of the parse tree of $file_name:\n";
       $tree->dump; # a method we inherit from XML::Element
       print "And here it is, bizarrely rerendered as XML:\n",
         $tree->as_XML, "\n";

       # Now that we're done with it, we must destroy it.
       $tree = $tree->delete;
     }

DESCRIPTION
===========

   This module uses XML::Parser to make XML document trees constructed of
XML::Element objects (and XML::Element is a subclass of HTML::Element
adapted for XML).  XML::TreeBuilder is meant particularly for people who
are used to the HTML::TreeBuilder / HTML::Element interface to document
trees, and who don't want to learn some other document interface like
XML::Twig or XML::DOM.

   The way to use this class is to:

   1. start a new (empty) XML::TreeBuilder object.

   2. set any of the "store" options you want.

   3. then parse the document from a source by calling `$x->parsefile(...)'
or `$x->parse(...)' (See XML/Parser, docs for the options
that these two methods take)

   4. do whatever you need to do with the syntax tree, presumably
involving traversing it looking for some bit of information in it,

   5. and finally, when you're done with the tree, call $tree->delete to
erase the contents of the tree from memory.  This kind of thing usually
isn't necessary with most Perl objects, but it's necessary for TreeBuilder
objects.  See HTML/Element, for a more verbose
explanation of why this is the case.

METHODS AND ATTRIBUTES
======================

   XML::TreeBuilder is a subclass of XML::Element, which in turn is a
subclass of HTML:Element.  You should read and understand the
documentation for those two modules.

   An XML::TreeBuilder object is just a special XML::Element object that
allows you to call these additional methods:

$root = XML::TreeBuilder->new()
     Construct a new XML::TreeBuilder object.

$root->parse(...options...)
     Uses XML::Parser's parse method to parse XML from the source(s?)
     specified by the options.  See `XML::Parse' in this node

$root->parsefile(...options...)
     Uses XML::Parser's parsefile method to parse XML from the source(s?)
     specified by the options.  See `XML::Parse' in this node

$root->parse_file(...options...)
     Simply an alias for parsefile.

$root->store_comments(value)
     This determines whether TreeBuilder will normally store comments found
     while parsing content into $root.  Currently, this is off by default.

$root->store_declarations(value)
     This determines whether TreeBuilder will normally store markup
     declarations found while parsing content into $root.  Currently, this
     is off by default.

$root->store_pis(value)
     This determines whether TreeBuilder will normally store processing
     instructions found while parsing content into $root.  Currently, this
     is off (false) by default.

SEE ALSO
========

   See XML/Parser, XML/Element,
HTML/TreeBuilder, HTML/DOMbo.

   And for alternate XML document interfaces, see XML/DOM, and
XML/Twig.

COPYRIGHT
=========

   Copyright 2000 Sean M. Burke.

AUTHOR
======

   Sean M. Burke, <sburke@cpan.org>

A perl module for processing huge XML documents in tree mode.
*************************************************************

NAME
====

   XML::Twig - A perl module for processing huge XML documents in tree
mode.

SYNOPSIS
========

     single-tree mode
         my $t= new XML::Twig();
         $t->parse( '<doc><para>para1</para></doc>');
         $t->print;

     chunk mode
         my $t= new XML::Twig( TwigHandlers => { section => \&flush});
         $t->parsefile( 'doc.xml');
         $t->flush;
         sub flush { $_[0]->flush; }

     my $t= new XML::Twig( TwigHandlers =>
     	                        { 'section/title' => \&print_elt_text} );
     $t->parsefile( 'doc.xml');
     sub print_elt_text
       { my( $t, $elt)= @_;
         print $elt->text;
       }

     my $t= new XML::Twig( TwigHandlers =>
     	                        { 'section[@level="1"]' => \&print_elt_text }
     			    );
     $t->parsefile( 'doc.xml');

     roots mode (builds only the required sub-trees)
         my $t= new XML::Twig(
                  TwigRoots    => { 'section/title' => \&print_elt_text}
                             );
         $t->parsefile( 'doc.xml');
         sub print_elt_text
           { my( $t, $elt)= @_;
             print $elt->text;
           }

DESCRIPTION
===========

   This module provides a way to process XML documents. It is build on top
of XML::Parser.

   The module offers a tree interface to the document, while allowing you
to output the parts of it that have been completely processed.

   It allows minimal resource (CPU and memory) usage by building the tree
only for the parts of the documents that need actual processing, through
the use of the TwigRoots and TwigPrintOutsideRoots options. The finish and
finish_print methods also help to increase performances.

   XML::Twig tries to make simple things easy so it tries its best to
takes care of a lot of the (usually) annoying (but sometimes necessary)
features that come with XML and XML::Parser.

Whitespaces
     Whitespaces that look non-significant are discarded, this behaviour
     can be controlled using the KeepSpaces, KeepSpacesIn and
     DiscardSpacesIn options.

Encoding
     You can specify that you want the output in the same encoding as the
     input (provided you have valid XML, which means you have to specify
     the encoding either in the document or when you create the Twig
     object) using the KeepEncoding option

METHODS
=======

Twig
----

   A twig is a subclass of XML::Parser, so all XML::Parser methods can be
called on a twig object, including parse and parsefile.  setHandlers on
the other hand cannot not be used, see ``' in this node'

new
     This is a class method, the constructor for XML::Twig. Options are
     passed as keyword value pairs. Recognized options are the same as
     XML::Parser, plus some XML::Twig specifics:

    TwigHandlers
          This argument replaces the corresponding XML::Parser argument.
          It consists of a hash { expression => \&handler} where
          expression is a *generic_attribute_condition*,
          *string_condition*, an *attribute_condition*,*full_path*, a
          *partial_path*, a gi, *_default_* or <_all_>.

          The idea is to support a usefull but efficient (thus limited)
          subset of XPATH. A fuller expression set will be supported in
          the future, as users ask for more and as I manage to implement
          it efficiently. This will never encompass all of XPATH due to
          the streaming nature of parsing (no lookhead after the element
          end tag).

          A *generic_attribute_condition* is a condition on an attribute,
          in the form **[@att="val"]* or **[@att]*, simple quotes can be
          used instead of double quotes and the leading '*' is actually
          optional. No matter what the gi of the element is, the handler
          will be triggered either if the attribute has the specified
          value or if it just exists.

          A *string_condition* is a condition on the content of an
          element, in the form *gi[string()="foo"]*, simple quotes can be
          used instead of double quotes, at the moment you cannot escape
          the quotes (this will be added as soon as I dig out my copy of
          Mastering Regular Expressions from its storage box).  The text
          returned is, as per what I (and Matt Sergeant!) understood from
          the XPATH spec the concatenation of all the text in the element,
          excluding all markup. Thus to call a handler on the element
          <p>text <b>bold</b></p> the appropriate condition is
          p[string()="text bold"]. Note that this is not exactly
          conformant to the XPATH spec, it just tries to mimic it while
          being still quite concise.

          A extension of that notation is *gi[string(*child_gi*)="foo"]*
          where the handler will be called if a child of a gi element has
          a text value of foo.  At the moment only direct children of the
          gi element are checked. If you need to test on descendants of
          the element let me know. The fix is trivial but would slow down
          the checks, so I'd like to keep it the way it is.

          A *regexp_condition* is a condition on the content of an
          element, in the form *gi[string()=~ /foo/"]*. This is the same
          as a string condition except that the text of the element is
          matched to the regexp. The i, m, <s> and o modifiers can be used
          on the regexp.

          The *gi[string(*child_gi*)=~ /foo/"]* extension is also
          supported.

          An *attribute_condition* is a simple condition of an attribute
          of the current element in the form *gi[@att="val"]* (simple
          quotes can be used instead of double quotes, you can escape
          quotes either).  If several attribute_condition are true the
          same element all the handlers can be called in turn (in the
          order in which they were first defined).  If the ="val" part is
          ommited ( the condition is then gi[@att]) then the handler is
          triggered if the attribute actually exists for the element, no
          matter what it's value is.

          A *full_path* looks like *'/doc/section/chapter/title'*, it
          starts with a / then gives all the gi's to the element. The
          handler will be called if the path to the current element (in
          the input document) is exactly as defined by the full_path.

          A *partial_path* is like a full_path except it does not start
          with a /: *'chapter/title'* for example. The handler will be
          called if the path to the element (in the input document) ends
          as defined in the partial_path.

          WARNING: (hopefully temporary) at the moment *string_condition*,
          *regexp_condition* and *attribute_condition* are only supported
          on a simple gi, not on a path.

          A gi (generic identifier) is just a tag name.

          A special gi *_all_* is used to call a function for each element.
          The special gi *_default_* is used to call a handler for each
          element that does NOT have a specific handler.

          The order of precedence to trigger a handler is:
          *generic_attribute_condition*, *string_condition*,
          *regexp_condition*, *attribute_condition*, *full_path*, longer
          *partial_path*, shorter *partial_path*, gi, *_default_* .

          *Important*: once a handler has been triggered if it returns 0
          then no other handler is called, exept a _all_ handler which
          will be called anyway.

          If a handler returns a true value and other handlers apply, then
          the next applicable handler will be called. Repeat, rince,
          lather..;

          When an element is CLOSED the corresponding handler is called,
          with 2 arguments: the twig and the ``' in this node'. The twig
          includes the document tree that has been built so far, the
          element is the complete sub-tree for the element.

          Text is stored in elements where gi is #PCDATA (due to mixed
          content, text and sub-element in an element there is no way to
          store the text as just an attribute of the enclosing element).

          Warning: if you have used purge or flush on the twig the element
          might not be complete, some of its children might have been
          entirely flushed or purged, and the start tag might even have
          been printed (by flush) already, so changing its gi might not
          give the expected result.

          More generally, the *full_path*, *partial_path* and gi
          expressions are evaluated against the input document. Which
          means that even if you have changed the gi of an element
          (changing the gi of a parent element from a handler for example)
          the change will not impact the expression evaluation. Attributes
          in *attribute_condition* are different though. As the initial
          value of attribute is not stored the handler will be triggered
          if the current attribute/value pair is found when the element
          end tag is found. Although this can be quite confusing it should
          not impact most of users, and allow others to play clever tricks
          with temporary attributes. Let me know if this is a problem for
          you.

    TwigRoots
          This argument let's you build the tree only for those elements
          you are interested in.

               Example: my $t= new XML::Twig( TwigRoots => { title => 1, subtitle => 1});
                        $t->parsefile( file);
                        my $t= new XML::Twig( TwigRoots => { 'section/title' => 1});
                        $t->parsefile( file);

          returns a twig containing a document including only title and
          subtitle elements, as children of the root element.

          You can use *generic_attribute_condition*,
          *attribute_condition*, *full_path*, *partial_path*, gi,
          *_default_* and *_all_* to trigger the building of the twig.
          *string_condition* and *regexp_condition* cannot be used as the
          content of the element, and the string, have not yet been parsed
          when the condition is checked.

          WARNING: path are checked for the document. Even if the
          TwigRoots option is used they will be checked against the full
          document tree, not the virtual tree created by XML::Twig

          WARNING: TwigRoots elements should NOT be nested, that would
          hopelessly confuse XML::Twig ;-(

          Note: you can set handlers (TwigHandlers) using TwigRoots
          Example: my $t= new XML::Twig( TwigRoots => { title    => sub {
          $_{1]->print;},
          subtitle => \&process_subtitle });            $t->parsefile(
          file);

    TwigPrintOutsideRoots
          To be used in conjunction with the TwigRoots argument. When set
          to a true value this will print the document outside of the
          TwigRoots elements.

               Example: my $t= new XML::Twig( TwigRoots => { title => \&number_title },
                                              TwigPrintOutsideRoots => 1,
                                             );
                         $t->parsefile( file);
                         { my $nb;
                         sub number_title
                           { my( $twig, $title);
                             $nb++;
                             $title->prefix( "$nb "; }
                             $title->print;
                           }
                         }

          This example prints the document outside of the title element,
          calls number_title for each title element, prints it, and then
          resumes printing the document. The twig is built only for the
          title elements.

    StartTagHandlers
          A hash { expression => \&handler}. Sets element handlers that
          are called when the element is open (at the end of the
          XML::Parser Start handler). The handlers are called with 2
          params: the twig and the element. The element is empty at that
          point, its attributes are created though.

          You can use *generic_attribute_condition*,
          *attribute_condition*, *full_path*, *partial_path*, gi,
          *_default_*  and *_all_* to trigger the handler.
          *string_condition* and *regexp_condition* cannot be used as the
          content of the element, and the string, have not yet been parsed
          when the condition is checked.

          The main use for those handlers is probably to create temporary
          attributes that will be used when processing sub-element with
          TwigHanlders.

          You should also use it to change tags if you use flush. If you
          change the tag in a regular TwigHandler then the start tag might
          already have been flushed.

          Note: StartTag handlers can be called outside ot TwigRoots if
          this argument is used, in this case handlers are called with the
          following arguments: $t (the twig), $gi (the gi of the element)
          and %att (a hash of the attributes of the element).

          If the TwigPrintOutsideRoots argument is also used then the
          start tag will be printed if the last handler called returns a
          `true' value, if it does not then the start tag will not be
          printed (so you can print a modified string yourself for
          example);

    EndTagHandlers
          A hash { expression => \&handler}. Sets element handlers that
          are called when the element is closed (at the end of the
          XML::Parser End handler). The handlers are called with 2 params:
          the twig and the gi of the element.

          TwigHandlers are called when an element is completely parsed, so
          why have this redundant option? There is only one use for
          EndTagHandlers: when using the TwigRoots option, to trigger a
          handler for an element *outside* the roots. It is for example
          very useful to number titles in a document using nested sections:

               my @no= (0);
               my $no;
               my $t= new XML::Twig(
                       StartTagHandlers => { section => sub { $no[$#no]++; $no= join '.', @no; push @no, 0; } },
                       TwigRoots        => { title   => sub { $_[1]->prefix( $no); $_[1]->print; } },
                       EndTagHandlers   => { section => sub { pop @no;  } },
                       TwigPrintOutsideRoots => 1
                                   );
                $t->parsefile( $file);

          Using the EndTagHandlers argument without TwigRoots will result
          in an error.

    CharHandler
          A reference to a subroutine that will be called every time
          PCDATA is found.

    KeepEncoding
          This is a (slightly?) evil option: if the XML document is not
          UTF-8 encoded and you want to keep it that way, then setting
          KeepEncoding will use the Expat original_string method for
          character, thus keeping the original encoding, as well as the
          original entities in the strings.

          WARNING: if the original encoding is multi-byte then attribute
          parsing will be EXTREMELY unsafe under any Perl before 5.6, as
          it uses regular expressions which do not deal properly with
          multi-byte characters.

          WARNING: this option is NOT used when parsing with the
          non-blocking parser (parse_start, parse_more, parse_done
          methods).

    LoadDTD
          If this argument is set to a true value, parse or parsefile on
          the twig will load the DTD information. This information can
          then be accessed through the twig, in a DTDHandler for example.
          This will load even an external DTD.

          See `DTD Handling' in this node for more information

    DTDHandler
          Sets a handler that will be called once the doctype (and the
          DTD) have been loaded, with 2 arguments, the twig and the DTD.

    Id
          This optional argument gives the name of an attribute that can
          be used as an ID in the document. Elements whose ID is known can
          be accessed through the elt_id method. Id defaults to 'id'.  See
          ``' in this node'

    DiscardSpaces
          If this optional argument is set to a true value then spaces are
          discarded when they look non-significant: strings containing
          only spaces are discarded.  This argument is set to true by
          default.

    KeepSpaces
          If this optional argument is set to a true value then all spaces
          in the document are kept, and stored as PCDATA.  KeepSpaces and
          DiscardSpaces cannot be both set.

    DiscardSpacesIn
          This argument sets KeepSpaces to true but will cause the twig
          builder to discard spaces in the elements listed.  The syntax
          for using this argument is:   new XML::Twig( DiscardSpacesIn =>
          [ 'elt1', 'elt2']);

    KeepSpacesIn
          This argument sets DiscardSpaces to true but will cause the twig
          builder to keep spaces in the elements listed.  The syntax for
          using this argument is:   new XML::Twig( KeepSpacesIn => [
          'elt1', 'elt2']);

    PrettyPrint
          Sets the pretty print method, amongst 'none' (default),
          'nsgmls', 'nice', 'indented', 'record' and rec'record'ord_c

    EmptyTags
          Sets the empty tag display style (normal, html or expand).

    Comments
          Sets the way comments are processed: drop (default), keep or
          process

         drop
               drops the comments, they are not read, nor printed to the
               output

         keep
               comments are loaded and will appear on the output, they are
               not accessible within the twig and will not interfere with
               processing though

               Bug: comments in the middle of a text element such as

                    <p>text <!-- comment --> more text --></p>

               are output at the end of the text:

                    <p>text  more text <!-- comment --></p>

         process
               comments are loaded in the twig and will be treated as
               regular elements (their gi is `#COMMENT') this can
               interfere with processing if you expect
               `$elt-'{first_child}> to be an element but find a comment
               there.  Validation will not protect you from this as
               comments can happen anywhere.  You can use
               `$elt-'first_child( 'gi')> (which is a good habit anyway)
               to get where you want. Consider using

    Pi
          Sets the way processing instructions are processed: drop, keep
          (default) or process

          Note that you can also set PI handlers in the TwigHandlers
          option:

               '?'       => \&handler
               '?target' => \&handler 2

          The handlers will be called with 2 parameters, the twig and the
          PI element if Pi is set to process, and with 3, the twig, the
          target and the data if Pi is set to keep. Of course they will
          not be called if PI is set to drop.

          If Pi is set to keep the handler should return a string that
          will be used as-is as the PI text (it should look like "`
          <?target data?' >" or " if you want to remove the PI),

          Only one handler will be called, `?target' or ? if no specific
          handler for that target is available.

     Note: I _HATE_ the Java-like name of arguments used by most XML
     modules. As XML::Twig is based on XML::Parser I kept the style, but
     you can also use a more perlish syntax, using
     `twig_print_outside_roots' instead of TwigPrintOutsideRoots or
     pretty_print instead of PrettyPrint, XML::Twig then normalizes all
     the argument names.

parse(SOURCE [, OPT => OPT_VALUE [...]])
     This method is inherited from XML::Parser.  The SOURCE parameter
     should either be a string containing the whole XML document, or it
     should be an open IO::Handle. Constructor options to
     XML::Parser::Expat given as keyword-value pairs may follow the SOURCE
     parameter. These override, for this call, any options or attributes
     passed through from the XML::Parser instance.

     A die call is thrown if a parse error occurs. Otherwise it will return
     the twig built by the parse. Use *safe_parse* if you want the parsing
     to return even when an error occurs.

parsestring
     This is just an alias for parse for backwards compatibility.

parsefile(FILE [, OPT => OPT_VALUE [...]])
     This method is inherited from XML::Parser.

     Open FILE for reading, then call parse with the open handle. The file
     is closed no matter how parse returns.

     A die call is thrown if a parse error occurs. Otherwise it will return
     the twig built by the parse. Use *safe_parsefile* if you want the
     parsing to return even when an error occurs.

safe_parse( SOURCE [, OPT => OPT_VALUE [...]])
     This method is similar to parse except that it wraps the parsing in an
     eval block. It returns the twig on success and 0 on failure (the twig
     object also contains the parsed twig). $@ contains the error message
     on failure.

     Note that the parsing still stops as soon as an error is detected,
     there is no way to keep going after an error.

safe_parsefile(FILE [, OPT => OPT_VALUE [...]])
     This method is similar to parsefile except that it wraps the parsing
     in an eval block. It returns the twig on success and 0 on failure
     (the twig object also contains the parsed twig) . $@ contains the
     error message on failure

     Note that the parsing still stops as soon as an error is detected,
     there is no way to keep going after an error.

setTwigHandlers ($handlers)
     Set the Twig handlers. $handlers is a reference to a hash similar to
     the one in the TwigHandlers option of new. All previous handlers are
     unset.  The method returns the reference to the previous handlers.

setTwigHandler ($gi $handler)
     Set a single Twig handlers for the $gi element. $handler is a
     reference to a subroutine. If the handler was previously set then the
     reference to the previous handler is returned.

setStartTagHandlers ($handlers)
     Set the StartTag handlers. $handlers is a reference to a hash similar
     to the one in the StartTagHandlers option of new. All previous
     handlers are unset.  The method returns the reference to the previous
     handlers.

setStartTagHandler ($gi $handler)
     Set a single StartTag handlers for the $gi element. $handler is a
     reference to a subroutine. If the handler was previously set then the
     reference to the previous handler is returned.

setEndTagHandlers ($handlers)
     Set the EndTag handlers. $handlers is a reference to a hash similar
     to the one in the EndTagHandlers option of new. All previous handlers
     are unset.  The method returns the reference to the previous handlers.

setEndTagHandler ($gi $handler)
     Set a single EndTag handlers for the $gi element. $handler is a
     reference to a subroutine. If the handler was previously set then the
     reference to the previous handler is returned.

setTwigHandlers ($handlers)
     Set the Twig handlers. $handlers is a reference to a hash similar to
     the one in the TwigHandlers option of new.

dtd
     Returns the dtd (an XML::Twig::DTD object) of a twig

root
     Returns the root element of a twig

first_elt ($optionnal_gi)
     Returns the first element whose gi is $optionnal_gi of a twig, if no
     $optionnal_gi is given then the root is returned

elt_id        ($id)
     Returns the element whose id attribute is $id

entity_list
     Returns the entity list of a twig

change_gi      ($old_gi, $new_gi)
     Performs a (very fast) global change. All elements old_gi are now
     new_gi.  See ``' in this node'

flush            ($optional_filehandle, $options)
     Flushes a twig up to (and including) the current element, then deletes
     all unnecessary elements from the tree that's kept in memory.  flush
     keeps track of which elements need to be open/closed, so if you flush
     from handlers you don't have to worry about anything. Just keep
     flushing the twig every time you're done with a sub-tree and it will
     come out well-formed. After the whole parsing don't forget to flush
     one more time to print the end of the document.  The doctype and
     entity declarations are also printed.

     flush take an optional filehandle as an argument.

     options: use the Update_DTD option if you have updated the (internal)
     DTD and/or the entity list and you want the updated DTD to be output

     The PrettyPrint option sets the pretty printing of the document.

          Example: $t->flush( Update_DTD => 1);
                   $t->flush( \*FILE, Update_DTD => 1);
                   $t->flush( \*FILE);

flush_up_to ($elt, $optionnal_filehandle, %options)
     Flushes up to the $elt element. This allows you to keep part of the
     tree in memory when you flush.

     options: see flush.

purge
     Does the same as a flush except it does not print the twig. It just
     deletes all elements that have been completely parsed so far.

purge_up_to ($elt)
     Purges up to the $elt element. This allows you to keep part of the
     tree in memory when you flush.

print            ($optional_filehandle, %options)
     Prints the whole document associated with the twig. To be used only
     AFTER the parse.

     options: see flush.

sprint
     Returns the text of the whole document associated with the twig. To
     be used only AFTER the parse.

     options: see flush.

set_pretty_print  ($style)
     Sets the pretty print method, amongst 'none' (default), 'nsgmls',
     'nice', 'indented', 'record' and rec'record'ord_c

     WARNING: the pretty print style is a GLOBAL variable, so once set it's
     applied to ALL print's (and sprint's). Same goes if you use XML::Twig
     with mod_perl . This should not be a problem as the XML that's
     generated is valid anyway, and XML processors (as well as HTML
     processors, including browsers) should not care. Let me know if this
     is a big problem, but at the moment the performance/cleanliness
     trade-off clearly favors the global approach.

set_empty_tag_style  ($style)
     Sets the empty tag display style (normal, html or expand). As with
     set_pretty_print this sets a global flag.

     normal outputs an empty tag '<tag/>', html adds a space '<tag /> and
     expand outputs '<tag></tag>'

print_prolog     ($optional_filehandle, %options)
     Prints the prolog (XML declaration + DTD + entity declarations) of a
     document.

     options: see flush.

prolog     ($optional_filehandle, %options)
     Returns the prolog (XML declaration + DTD + entity declarations) of a
     document.

     options: see flush.

finish
     Call Expat finish method.  Unsets all handlers (including internal
     ones that set context), but expat continues parsing to the end of the
     document or until it finds an error.  It should finish up a lot
     faster than with the handlers set.

finish_print
     Stop twig processing, flush the twig and proceed to finish printing
     the document as fast as possible. Use this method when modifying a
     document and the modification is done.

depth
     Calls Expat's depth method , which returns the depth in the tree
     during the parsing.  This is usefull when using the TwigRoots option
     to still get info on the actual document.

in_element ($gi)
     Call Expat in_element method.  Returns true if $gi is equal to the
     name of the innermost currently opened element. If namespace
     processing is being used and you want to check against a name that
     may be in a namespace, then use the generate_ns_name method to create
     the $gi argument. Usefull when using the TwigRoots option.

within_element($gi)
     Call Expat within_element method.  Returns the number of times the
     given name appears in the context list.  If namespace processing is
     being used and you want to check against a name that may be in a
     namespace, then use the generate_ns_name method to create the $gi
     argument. Usefull when using the TwigRoots option.

context
     Returns a list of element names that represent open elements, with
     the last one being the innermost. Inside start and end tag handlers,
     this will be the tag of the parent element.

path($gi)
     Returns the element context in a form similar to XPath's short form:
     '/root/gi1/../gi'

get_xpath  ($xpath, $optional_offset)
     Performs a get_xpath on the document root (see Elt)

Elt
---

new          ($optional_gi, $optional_atts, @optional_content)
     The gi is optional (but then you can't have a content ), the optional
     atts is the ref of a hash of attributes, the content can be just a
     string or a list of strings and element. A content of '#EMPTY'
     creates an empty element;

          Examples: my $elt= new XML::Twig::Elt();
                    my $elt= new XML::Twig::Elt( 'para', { align => 'center' });
          	   my $elt= new XML::Twig::Elt( 'br', '#EMPTY');
          	   my $elt= new XML::Twig::Elt( 'para');
                    my $elt= new XML::Twig::Elt( 'para', 'this is a para');
                    my $elt= new XML::Twig::Elt( 'para', $elt3, 'another para');

     The strings are not parsed, the element is not attached to any twig.

     WARNING: if you rely on ID's then you will have to set the id
     yourself. At this point the element does not belong to a twig yet, so
     the ID attribute is not known so it won't be strored in the ID list.

parse         ($string, %args)
     Creates an element from an XML string. The string is actually parsed
     as a new twig, then the root of that twig is returned.  The arguments
     in %args are passed to the twig.  As always if the parse fails the
     parser will die, so use an eval if you want to trap syntax errors.

     As obviously the element does not exist beforehand this method has to
     be called on the class:

          my $elt= parse XML::Twig::Elt( "<a> string to parse, with <sub/>
                                          <elements>, actually tons of </elements>
          				  h</a>");

set_gi         ($gi)
     Sets the gi of an element

gi
     Returns the gi of the element

closed
     Returns true if the element has been closed. Might be usefull if you
     are somewhere in the tree, during the parse, and have no idea whether
     a parent element is completely loaded or not.

is_pcdata
     Returns 1 if the element is a #PCDATA element, returns 0 otherwise.

pcdata
     Returns the text of a PCDATA element or undef if the element is not
     PCDATA.

set_pcdata     ($text)
     Sets the text of a PCDATA element.

append_pcdata  ($text)
     Add the text at the end of a #PCDATA element.

is_cdata
     Returns 1 if the element is a #CDATA element, returns 0 otherwise.

is_text
     Returns 1 if the element is a #CDATA or #PCDATA element, returns 0
     otherwise.

cdata
     Returns the text of a CDATA element or undef if the element is not
     CDATA.

set_cdata     ($text)
     Sets the text of a CDATA element.

append_cdata  ($text)
     Add the text at the end of a #CDATA element.

is_empty
     Returns 1 if the element is empty, 0 otherwise

set_empty
     Flags the element as empty. No further check is made, so if the
     element is actually not empty the output will be messed. The only
     effect of this method is that the output will be <gi att="value""/>.

set_not_empty
     Flags the element as not empty. if it is actually empty then the
     element will be output as <gi att="value""></gi>

root
     Returns the root of the twig in which the element is contained.

twig
     Returns the twig containing the element.

parent        ($optional_gi)
     Returns the parent of the element, or the first ancestor whose gi is
     $optional_gi.

first_child   ($optional_gi)
     Returns the first child of the element, or the first child whose gi is
     $optional_gi (ie the first of the element children whose gi matches).

child ($offset, $optional_gi)
     Returns the $offset-th child of the element, optionally the
     $offset-th child with a gi of $optional_gi. The children are treated
     as a list, so $elt->child( 0) is the first child, while $elt->chlid(
     -1) is the last child.

child_text ($offset, $optional_gi)
     Returns the text of a child or undef if the sibling does not exist.
     Arguments are the same as child.

first_child_text   ($optional_gi)
     Returns the text of the first child of the element, or the first child
     whose gi is $optional_gi.(ie the first of the element children whose
     gi matches).  If there is no first_child then returns ". This avoids
     getting the child, checking for its existence then getting the text
     for trivial cases.

field         ($optional_gi)
     Same method as first_child_text with a different name

last_child    ($optional_gi)
     Returns the last child of the element, or the last child whose gi is
     $optional_gi (ie the last of the element children whose gi matches).

last_child_text   ($optional_gi)
     Same as first_child_text but for the last child.

prev_sibling  ($optional_gi)
     Returns the previous sibling of the element, or the first one whose
     gi is $optional_gi.

sibling  ($offset, $optional_gi)
     Returns the next or previous $offset-th sibling of the element, or
     the $offset-th one whose gi is $optional_gi. If $offset is negative
     then a previous sibling is returned, if $offset is positive then  a
     next sibling is returned. $offset=0 returns the element if there is
     no $optional_gi or if the element gi matches $optional_gi, undef
     otherwise.

sibling_text ($offset, $optional_gi)
     Returns the text of a sibling or undef if the sibling does not exist.
     Arguments are the same as sibling.

next_sibling  ($optional_gi)
     Returns the next sibling of the element, or the first one whose gi is
     $gi.

next_elt     ($optional_elt, $optional_gi)
     Returns the next elt (optionally whose gi is $gi) of the element.
     This is defined as the next element which opens after the current
     element opens.  Which usually means the first child of the element.
     Counter-intuitive as it might look this allows you to loop through the
     whole document by starting from the root.

     The $optional_elt is the root of a subtree. When the next_elt is out
     of the subtree then the method returns undef. You can then walk a sub
     tree with:

          my $elt= $subtree_root;
          while( $elt= $elt->next_elt( $subtree_root)
            { # insert processing code here
            }

prev_elt     ($optional_gi)
     Returns the previous elt (optionally whose gi is $gi) of the element.
     This is the first element which opens before the current one.  It is
     usually either the last descendant of the previous sibling or simply
     the parent

children     ($optional_gi)
     Returns the list of children (optionally whose gi is $gi) of the
     element.  The list is in document order.

descendants     ($optional_gi)
     Returns the list of all descendants (optionally whose gi is $gi) of
     the element This is the equivalent of the getElementsByTagName of the
     DOM

ancestors    ($optional_gi)
     Returns the list of ancestors (optionally whose gi is $gi) of the
     element.  The list is ordered from the innermost ancestor to the
     outtermost one

     NOTE: the element itself is not part of the list, in order to include
     it you will have to write:

          my @array= ($elt, $elt->ancestors)

          =item prev_siblings ($optional_gi)

     Returns the list of previous siblings (optionaly whose gi is
     $optional_gi) for the element. The elements are ordered in document
     order.

next_siblings ($optional_gi)
     Returns the list of siblings (optionaly whose gi is $optional_gi)
     following the element. The elements are ordered in document order.

get_xpath  ($xpath, $optional_offset)
     Returns a list of elements satisfying the $xpath. $xpath is an
     XPATH-like expression.  A subset of the XPATH abbreviated syntax is
     covered:

          gi
          gi[1] (or any other positive number)
          gi[last()]
          gi[@att] (the attribute exists for the element)
          gi[@att="val"]
          gi[att1="val1" and att2="val2"]
          gi[att1="val1" or att2="val2"]
          gi[string()="toto"] (returns gi elements which text (as per the text method) is toto)
          gi[string()=~/regexp/] (returns gi elements which text (as per the text method) matches regexp)
          expressions can start with / (search starts at the document root)
          expressions can start with . (search starts at the current element)
          // can be used to get all descendants instead of just direct children
          * matches any gi

          So the following examples from the XPATH recommendation (http://www.w3.org/TR/xpath.html#path-abbrev)
          work:

          para selects the para element children of the context node
          * selects all element children of the context node
          para[1] selects the first para child of the context node
          para[last()] selects the last para child of the context node
          */para selects all para grandchildren of the context node
          /doc/chapter[5]/section[2] selects the second section of the fifth chapter of the doc
          chapter//para selects the para element descendants of the chapter element children of the context node
          //para selects all the para descendants of the document root and thus selects all para elements in the same document as the
                     context node
          //olist/item selects all the item elements in the same document as the context node that have an olist parent
          .//para selects the para element descendants of the context node
          .. selects the parent of the context node
          para[@type="warning"] selects all para children of the context node that have a type attribute with value warning
          employee[@secretary and @assistant] selects all the employee children of the context node that have both a secretary attribute and
                     an assistant attribute

     The elements will be returned in the document order.

     If $optional_offset is used then only one element will be returned,
     the one with the appropriate offset in the list, starting at 0

     Quoting and interpolating variables can be a pain when the Perl
     syntax and the XPATH syntax collide, so here are some more examples
     to get you started:

          my $p1= "p1";
          my $p2= "p2";
          my @res= $t->get_xpath( "p[string( '$p1') or string( '$p2')]");

          my $a= "a1";
          my @res= $t->get_xpath( "//*[@att=\"$a\"]);

          my $val= "a1";
          my $exp= "//p[ \@att='$val']"; # note that you need to use \@ or you will get a warning
          my @res= $t->get_xpath( $exp);

     XML::Twig does not provide full XPATH support. If that's what you
     want then look no further than the XML::XPath module on CPAN.

level       ($optional_gi)
     Returns the depth of the element in the twig (root is 0).  If the
     optional gi is given then only ancestors of the given type are
     counted.

     WARNING: in a tree created using the TwigRoots option this will not
     return the level in the document tree, level 0 will be the document
     root, level 1 will be the TwigRoots elements. During the parsing (in
     a TwigHandler) you can use the depth method on the twig object to get
     the real parsing depth.

in           ($potential_parent)
     Returns true if the element is in the potential_parent
     ($potential_parent is an element)

in_context   ($gi, $optional_level)
     Returns true if the element is included in an element whose gi is $gi,
     optionally within $optional_level levels. The returned value is the
     including element.

atts
     Returns a hash ref containing the element attributes

set_atts      ({att1=>$att1_val, att2=> $att2_val... })
     Sets the element attributes with the hash ref supplied as the argument

del_atts
     Deletes all the element attributes.

set_att      ($att, $att_value)
     Sets the attribute of the element to the given value

att          ($att)
     Returns the attribute value

del_att      ($att)
     Delete the attribute for the element

inherit_att  ($att, @optional_gi_list)
     Returns the value of an attribute inherited from parent tags. The
     value returned is found by looking for the attribute in the element
     then in turn in each of its ancestors. If the @optional_gi_list is
     supplied only those ancestors whose gi is in the list will be checked.

set_id       ($id)
     Sets the id attribute of the element to the value.  See ``' in this
     node' to change the id attribute name

id
     Gets the id attribute value

del_id       ($id)
     Deletes the id attribute of the element and remove it from the id list
     for the document

cut
     Cuts the element from the tree.

copy        ($elt)
     Returns a copy of the element. The copy is a "deep" copy: all sub
     elements of the element are duplicated.

paste       ($optional_position, $ref)
     Pastes a (previously cut) element.  The optional position element can
     be:

    first_child (default)
          The element is pasted as the first child of the element object
          this method is called on.

    last_child
          The element is pasted as the last child of the element object
          this method is called on.

    before
          The element is pasted before the element object, as its previous
          sibling.

    after
          The element is pasted after the element object, as its next
          sibling.

move       ($optional_position, $ref)
     Move an element in the tree.  This is just a cut then a paste.  The
     syntax is the same as paste.

replace       ($ref)
     Replaces an element in the tree. Sometimes it is just not possible to
     cut an element then paste another in its place, so replace comes in
     handy.

prefix       ($text)
     Add a prefix to an element. If the element is a PCDATA element the
     text is added to the pcdata, if the elements first_child is a PCDATA
     then the text is added to it's pcdata, otherwise a new PCDATA element
     is created and pasted as the first child of the element.

suffix       ($text)
     Add a suffix to an element. If the element is a PCDATA element the
     text is added to the pcdata, if the elements last_child is a PCDATA
     then the text is added to it's pcdata, otherwise a new PCDATA element
     is created and pasted as the last child of the element.

erase
     Erases the element: the element is deleted and all of its children are
     pasted in its place.

delete
     Cut the element and frees the memory.

DESTROY
     Frees the element from memory.

start_tag
     Returns the string for the start tag for the element, including the
     /> at the end of an empty element tag

end_tag
     Returns the string for the end tag of an element.  For an empty
     element, this returns the empty string (").

print         ($optional_filehandle, $pretty_print_style)
     Prints an entire element, including the tags, optionally to a
     $optional_filehandle, optionally with a $pretty_print_style.

sprint       ($elt, $optional_no_enclosing_tag)
     Returns the string for an entire element, including the tags. To be
     used with caution!  If the optional second argument is true then only
     the string inside the element is returned (the start and end tag for
     $elt are not).

set_pretty_print ($style)
     Sets the pretty print method, amongst 'none' (default), 'nsgmls',
     'nice', 'indented', 'record' and 'record_c'

    none
          the default, no \n is used

    nsgmls
          nsgmls style, with \n added within tags

    nice
          adds \n wherever possible (NOT SAFE, can lead to invalid XML)

    indented
          same as nice plus indents elements (NOT SAFE, can lead to
          invalid XML)

    record
          table-oriented pretty print, one field per line

    record_c
          table-oriented pretty print, more compact than record, one
          record per line

set_empty_tag_style ($style)
     Sets the method to output empty tags, amongst 'normal' (default),
     'html', and 'expand',

set_indent ($string)
     Sets the indentation for the indented pretty print style (default is
     2 spaces)

set_quote ($quote)
     Sets the quotes used for attributes. can be 'double' (default) or
     'single'

text
     Returns a string consisting of all the PCDATA and CDATA in an element,
     without any tags.

set_text        ($string)
     Sets the text for the element: if the element is a PCDATA, just set
     its text, otherwise cut all the children of the element and create a
     single PCDATA child for it, which holds the text.

set_content    ( $optional_atts, @list_of_elt_and_strings)                      ( $optional_atts, '#EMPTY')
     Sets the content for the element, from a list of strings and
     elements.  Cuts all the element children, then pastes the list
     elements as the children.  This method will create a PCDATA element
     for any strings in the list.

     The optional_atts argumentis the ref of a hash of attributes. If this
     argument is used then the previous attrubutes are deleted, otherwise
     they are left untouched.

     WARNING: if you rely on ID's then you will have to set the id
     yourself. At this point the element does not belong to a twig yet, so
     the ID attribute is not known so it won't be strored in the ID list.

     A content of '#EMPTY' creates an empty element;

insert         (@gi)
     For each gi in the list inserts an element $gi as the only child of
     the element.  All children of the element are set as children of the
     new element.  The upper level element is returned.

     $p->insert( 'table', 'tr', 'td') puts $p in a table with a single tr
     and a single td and returns the table element.

wrap_in        (@gi)
     Wraps elements $gi as the successive ancestors of the element,
     returns the new element.  $elt->wrap_in( 'td', 'tr', 'table') wraps
     the element as a single cell in a table for example.

cmp       ($elt)   Compare the order of the 2 elements in a twig.
          $a is the <A>..</A> element, $b is the <B>...</B> element

          document                        $a->cmp( $b)
          <A> ... </A> ... <B>  ... </B>     -1
          <A> ... <B>  ... </B> ... </A>     -1
          <B> ... </B> ... <A>  ... </A>      1
          <B> ... <A>  ... </A> ... </B>      1
           $a == $b                           0
           $a and $b not in the same tree   undef

before       ($elt)
     Returns 1 if $elt starts before the element, 0 otherwise. If the 2
     elements are not in the same twig then return undef.

          if( $a->cmp( $b) == -1) { return 1; } else { return 0; }

after       ($elt)
     Returns 1 if $elt starts after the element, 0 otherwise. If the 2
     elements are not in the same twig then return undef.

          if( $a->cmp( $b) == -1) { return 1; } else { return 0; }

path
     Returns the element context in a form similar to XPath's short form:
     '/root/gi1/../gi'

private methods

    set_parent        ($parent)
    set_first_child   ($first_child)
    set_last_child    ($last_child)
    set_prev_sibling  ($prev_sibling)
    set_next_sibling  ($next_sibling)
    set_twig_current
    del_twig_current
    twig_current
    flushed
          This method should NOT be used, always flush the twig, not an
          element.

    set_flushed
    del_flushed
    flush
    contains_text
     Those methods should not be used, unless of course you find some
     creative and interesting, not to mention useful, ways to do it.

Entity_list
-----------

new
     Creates an entity list.

add         ($ent)
     Adds an entity to an entity list.

delete     ($ent or $gi).
     Deletes an entity (defined by its name or by the Entity object) from
     the list.

print      ($optional_filehandle)
     Prints the entity list.

Entity
------

new        ($name, $val, $sysid, $pubid, $ndata)
     Same arguments as the Entity handler for XML::Parser.

print       ($optional_filehandle)
     Prints an entity declaration.

text
     Returns the entity declaration text.

EXAMPLES
========

   See the test file in t/test[1-n].t Additional examples (and a complete
tutorial) can be found at http://www.xmltwig.cx/

   To figure out what flush does call the following script with an  xml
file and an element name as arguments

     use XML::Twig;

     my ($file, $elt)= @ARGV;
     my $t= new XML::Twig( TwigHandlers =>
         { $elt => sub {$_[0]->flush; print "\n[flushed here]\n";} });
     $t->parsefile( $file, ErrorContext => 2);
     $t->flush;
     print "\n";

NOTES
=====

DTD Handling
------------

   There are 3 possibilities here.  They are:

No DTD
     No doctype, no DTD information, no entity information, the world is
     simple...

Internal DTD
     The XML document includes an internal DTD, and maybe entity
     declarations.

     If you use the LoadDTD option when creating the twig the DTD
     information and the entity declarations can be accessed.

     The DTD and the entity declarations will be flush'ed (or print'ed)
     either as is (if they have not been modified) or as reconstructed
     (poorly, comments are lost, order is not kept, due to it's content
     this DTD should not be viewed by anyone) if they have been modified.
     You can also modify them directly by changing the
     $twig->{twig_doctype}->{internal} field (straight from XML::Parser,
     see the Doctype handler doc)

External DTD
     The XML document includes a reference to an external DTD, and maybe
     entity declarations.

     If you use the LoadDTD when creating the twig the DTD information and
     the entity declarations can be accessed. The entity declarations will
     be flush'ed (or print'ed) either as is (if they have not been
     modified) or as reconstructed (badly, comments are lost, order is not
     kept).

     You can change the doctype through the $twig->set_doctype method and
     print the dtd through the $twig->dtd_text or $twig->dtd_print methods.

     If you need to modify the entity list this is probably the easiest
     way to do it.

Flush
-----

   If you set handlers and use flush, do not forget to flush the twig one
last time AFTER the parsing, or you might be missing the end of the
document.

   Remember that element handlers are called when the element is CLOSED, so
if you have handlers for nested elements the inner handlers will be called
first. It makes it for example trickier than it would seem to number nested
clauses.

BUGS
====

ID list
     The ID list is NOT updated when ID's are modified or elements cut or
     deleted.

change_gi
     This method will not function properly if you do:

          $twig->change_gi( $old1, $new);
          $twig->change_gi( $old2, $new);
          $twig->change_gi( $new, $even_newer);

sanity check on XML::Parser method calls
     XML::Twig should really prevent calls to some XML::Parser methods,
     especially the setHandlers method.

Globals
=======

   These are the things that can mess up calling code, especially if
threaded.  They might also cause problem under mod_perl.

Exported constants
     Whether you want them or not you get them! These are subroutines to
     use as constant when creating or testing elements

    PCDATA
          returns '#PCDATA'

    CDATA
          returns '#CDATA'

    PI
          returns '#PI', I had the choice between PROC and PI :-(

Module scoped values: constants
     these should cause no trouble:

          %base_ent= ( '>' => '&gt;',
                       '<' => '&lt;',
                       '&' => '&amp;',
                       "'" => '&apos;',
                       '"' => '&quot;',
                     );
          CDATA_START   = "<![CDATA[";
          CDATA_END     = "]]>";
          PI_START      = "<?";
          PI_END        = "?>";
          COMMENT_START = "<!--";
          COMMENT_END   = "-->";

     pretty print styles

          ( $NSGMLS, $NICE, $INDENTED, $RECORD1, $RECORD2)= (1..5);

     empty tag output style

          ( $HTML, $EXPAND)= (1..2);

Module scoped values: might be changed
     Most of these deal with pretty printing, so the worst that can happen
     is probably that XML output does not look right, but is still valid
     and processed identically by XML processors.

     $empty_tag_style can mess up HTML bowsers though and changing $ID
     would most likely create problems.

          $pretty=0;           # pretty print style
          $quote='"';          # quote for attributes
          $INDENT= '  ';       # indent for indented pretty print
          $empty_tag_style= 0; # how to display empty tags
          $ID                  # attribute used as a gi ('id' by default)

Module scoped values: definitely changed
     These 2 variables are used to replace gi's by an index, thus saving
     some space when creating a twig. If they really cause you too much
     trouble, let me know, it is probably possible to create either a
     switch or at least a version of XML::Twig that does not perform this
     optimisation.

          %gi2index;     # gi => index
          @index2gi;     # list of gi's

TODO
====

multiple twigs are not well supported
     A number of twig features are just global at the moment. These include
     the ID list and the "gi pool" (if you use change_gi then you change
     the gi for ALL twigs).

     The next version will try to support this while trying not to be to
     hard on performance (at least when a single twig is used!).

XML::Parser-like handlers
     Sometimes it would be nice to be able to use both XML::Twig handlers
     and XML::Parser handlers, for example to perform generic tasks on all
     open tags, like adding an ID, or taking care of the autonumbering.

     Next version...

BENCHMARKS
==========

   You can use the `benchmark_twig' file to do additional benchmarks.
Please send me benchmark information for additional systems.

AUTHOR
======

   Michel Rodriguez <m.v.rodriguez@ieee.org>

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Bug reports and comments to m.v.rodriguez@ieee.org.  The XML::Twig page
is at http://www.xmltwig.cx/

SEE ALSO
========

   XML::Parser

Convert UTF-8 strings to any encoding supported by XML::Encoding
****************************************************************

NAME
====

   XML::UM - Convert UTF-8 strings to any encoding supported by
XML::Encoding

SYNOPSIS
========

     use XML::UM;

     # Set directory with .xml files that comes with XML::Encoding distribution
     # Always include the trailing slash!
     $XML::UM::ENCDIR = '/home1/enno/perlModules/XML-Encoding-1.01/maps/';

     # Create the encoding routine
     my $encode = XML::UM::get_encode (
     	Encoding => 'ISO-8859-2',
     	EncodeUnmapped => \&XML::UM::encode_unmapped_dec);

     # Convert a string from UTF-8 to the specified Encoding
     my $encoded_str = $encode->($utf8_str);

     # Remove circular references for garbage collection
     XML::UM::dispose_encoding ('ISO-8859-2');

DESCRIPTION
===========

   This module provides methods to convert UTF-8 strings to any XML
encoding that XML/Encoding, supports. It creates
mapping routines from the .xml files that can be found in the maps/
directory in the XML/Encoding, distribution. Note that
the XML::Encoding distribution does install the .enc files in your perl
directory, but not the.xml files they were created from. That's why you
have to specify $ENCDIR as in the SYNOPSIS.

   This implementation uses the XML::Encoding class to parse the .xml file
and creates a hash that maps UTF-8 characters (each consisting of up to 4
bytes) to their equivalent byte sequence in the specified encoding.  Note
that large mappings may consume a lot of memory!

   Future implementations may parse the .enc files directly, or do the
conversions entirely in XS (i.e. C code.)

get_encode (Encoding => STRING, EncodeUnmapped => SUB)
======================================================

   The central entry point to this module is the XML::UM::get_encode()
method.  It forwards the call to the global $XML::UM::FACTORY, which is
defined as an instance of XML::UM::SlowMapperFactory by default. Override
this variable to plug in your own mapper factory.

   The XML::UM::SlowMapperFactory creates an instance of
XML::UM::SlowMapper (and caches it for subsequent use) that reads in the
.xml encoding file and creates a hash that maps UTF-8 characters to
encoded characters.

   The get_encode() method of XML::UM::SlowMapper is called, finally, which
generates an anonimous subroutine that uses the hash to convert
multi-character UTF-8 blocks to the proper encoding.

dispose_encoding ($encoding_name)
=================================

   Call this to free the memory used by the SlowMapper for a specific
encoding.  Note that in order to free the big conversion hash, the user
should no longer have references to the subroutines generated by
get_encode().

   The parameters to the get_encode() method (defined as name/value pairs)
are:

   * Encoding

     The name of the desired encoding, e.g. 'ISO-8859-2'

   * EncodeUnmapped (Default: \&XML::UM::encode_unmapped_dec)

     Defines how Unicode characters not found in the mapping file (of the
     specified encoding) are printed.  By default, they are converted to
     decimal entity references, like '&#123;'

     Use \&XML::UM::encode_unmapped_hex for hexadecimal constants, like
     '&#xAB;'

CAVEATS
=======

   I'm not exactly sure about which Unicode characters in the range (0 ..
127) should be mapped to themselves. See comments in XML/UM.pm near
%DEFAULT_ASCII_MAPPINGS.

   The encodings that expat supports by default are currently not
supported, (e.g. UTF-16, ISO-8859-1), because there are no .enc files
available for these encodings.  This module needs some more work. If you
have the time, please help!

AUTHOR
======

   Send bug reports, hints, tips, suggestions to Enno Derksen at
<`enno@att.com'>.

DOCTYPE driven valid XML output
*******************************

NAME
====

   XML::ValidWriter - DOCTYPE driven valid XML output

SYNOPSIS
========

     ## As a normal perl object:
     $writer = XML::ValidWriter->new(
        DOCTYPE => $xml_doc_type,
        OUTPUT => \*FH
     ) ;
     $writer->startTag( 'b1' ) ;
     $writer->startTag( 'c2' ) ;
     $writer->end ;

     ## Writing to a scalar:
     $writer = XML::ValidWriter->new(
        DOCTYPE => $xml_doc_type,
        OUTPUT => \$buf
     ) ;

     ## Or, in scripting mode:
     use XML::Doctype         NAME => a, SYSTEM_ID => 'a.dtd' ;
     use XML::ValidWriter qw( :all :dtd_tags ) ;
     b1 ;                # Emits <a><b1>
     c2( attr=>"val" ) ; # Emits </b1><b2><c2 attr="val">
     endAllTags ;        # Emits </c2></b2></a>

     ## If you've got an XML::Doctype object handy:
     use XML::ValidWriter qw( :dtd_tags ), DOCTYPE => $doctype ;

     ## If you've saved a preparsed DTD as a perl module
     use FooML::Doctype::v1_0001 ;
     use XML::ValidWriter qw( :dtd_tags ) ;

     #
     # This all assumes that the DTD contains:
     #
     #   <!ELEMENT a ( b1, b2?, b3* ) >
     #	  <!ATTLIST   a aa1 CDATA       #REQUIRED >
     #   <!ELEMENT b1 ( c1 ) >
     #   <!ELEMENT b2 ( c2 ) >
     #

STATUS
======

   Alpha.  Use and patch, don't depend on things not changing drastically.

   Many methods supplied by XML::Writer are not yet supplied here.

DESCRIPTION
===========

   This module uses the DTD contained in an XML::Doctype to enable compile-
and run-time checks of XML output validity.  It also provides methods and
functions named after the elements mentioned in the DTD.  If an
XML::ValidWriter uses a DTD that mentions the element type TABLE, that
instance will provide the methods

     $writer->TABLE( $content, ...attrs... ) ;
     $writer->start_TABLE( ...attrs... ) ;
     $writer->end_TABLE() ;
     $writer->empty_TABLE( ...attrs... ) ;

   .  These are created for undeclared elements-those elements not
explicitly declared with an <!ELEMENT ..> declaration-as well.  If an
element type name conflicts with a method, it will not override the
internal method.

   When an XML::Doctype is parsed, the name of the doctype defines the root
node of the document.  This name can be changed, though, see
XML/Doctype, for details.

   In addition to the object-oriented API, a function API is also provided.
This allows you to import most of the methods of XML::ValidWriter as
functions using standard import specifications:

     use XML::ValidWriter qw( :all ) ; ## Could list function names instead

   :all does not import the functions named after elements mentioned in
the DTD, you need to import those tags using `:dtd_tags':

     use XML::Doctype NAME => 'foo', SYSTEM_ID => 'fooml.dtd' ;
     use XML::ValidWriter qw( :all :dtd_tags ) ;

   or

     BEGIN {
        $doctype = XML::Doctype->new( ... ) ;
     }

     use XML::ValidWriter DOCTYPE => $doctype, qw( :all :dtd_tags ) ;

XML::Writer API compatibility
-----------------------------

   Much of the interface is patterned after XML::Writer so that it can
possibly be used as a drop-in replacement.  It will take awhile before
this module emulates enough of XML::Writer to be a drop-in replacement in
situations where the more advanced XML::Writer methods are used.  If you
find you need a method not suported here, write it and send it in!

   This was not derived from XML::Writer because XML::Writer does not
expose it's stack.  Even if it did, it's might be difficult to store
enough state in it's stack.

   Unlike XML::Writer, this does not call in all of the IO::* family, and
method dispatch should be faster.  DTD-specific methods are also supported
(see `' in this node).

Quick and Easy Unix Filter Apps
-------------------------------

   For quick applications that provide Unix filter application
functionality, XML::ValidWriter and XML::Doctype cooperate to allow you to

  1. Parse a DTD at compile-time and set that as the default DTD for the
     current package.  This is done using the

          use XML::Doctype NAME => 'FooML, SYSTEM_ID => 'fooml.dtd' ;

     syntax.

  2. Define and export a set of functions corresponding to start and end
     tags for all declared and undeclared ELEMENTs in the DTD.  This is
     done by using the `:dtd_tags' export symbol like so:

          use XML::Doctype     NAME => 'FooML, SYSTEM_ID => 'fooml.dtd' ;
          use XML::ValidWriter qw(:dtd_tags) ;

     If the elements a, b_c, and d-e are referred to in the DTD, the
     following functions will be exported:

          a()        end_a()       # like startTag( 'a', ... ) and endTag( 'a' )
          b_c()      end_b_c()
          d_e()      end_d_e()     {'d-e'}()     {'end_d-e'}()

     These functions emit only tags, unlike the similar functions found in
     CGI.pm and XML::Generator, which also allow you to pass content in as
     parameters.

     See below for details on conflict resolution in the mapping of entity
     names containing /\W/ to Perl subroutine names.

     If the elements declared in the DTD might conflict with functions in
     your package namespace, simple put them in some safe namespace:

          package FooML ;
          use XML::Doctype         NAME => 'FooML', SYSTEM_ID => 'fooml.dtd' ;
          use XML::ValidWriter qw(:dtd_tags) ;

          package Whatever ;

     The advantage of importing these subroutine names is that perl can
     then detect use of unknown tags at compile time.

     If you don't want to use the default DTD, use the `-dtd' option:

          BEGIN { $dtd = XML::Doctype->new( .... ) }
          use XML::ValidWriter qw(:dtd_tags), -dtd => \$dtd ;

  3. Use the default DTD to validate emitted XML.  startTag() and endTag()
     will check the tag being emitted against the list of currently open
     tags and either emit a minimal set of missing end and start tags
     necessary to achieve document validity or produce errors or warnings.

     Since the functions created by the `:dtd_tags' export symbol are
     wrappers around startTag() and endTag(), they provide this
     functionality as well.

     So, if you have a DTD like

          <!ELEMENT a ( b1, b2?, b3* ) >

          <!ATTLIST   a aa1 CDATA       #REQUIRED >

          <!ELEMENT b1 ( c1 ) >
          <!ELEMENT b2 ( c2 ) >
          <!ELEMENT b3 ( c3 ) >

     you can do this:

          use XML::Doctype     NAME => 'a', SYSTEM_ID => 'a.dtd' ;
          use XML::ValidWriter ':dtd_tags' ;

          getDoctype->element_decl('a')->attdef('aa1')->default_on_write('foo') ;

          a ;
             b1 ;
          	 c1 ;
          	 end_c1 ;
             end_b1 ;
             b3 ;
          	 c3( -attr => val ) ;
          	 end_c3 ;
             end_b3 ;
          end_a ;

     and emit a document like

          <a aa1="foo">
             <b1>
                <c1 />
             </b1>
             <b3>
                <c3 attr => "val" />
             </b3>
          </a>

     .

OUTPUT OPTIMIZATION
===================

   XML is a very simple langauge and does not offer a lot of room for
optimization.  As the spec says "Terseness in XML markup is of minimal
importance."  XML::ValidWriter does optimize the following on output:

   `<a...></a>'   becomes '<a... />'

   Spurious emissions of `]]><![CDATA[' are supressed.

   XML::ValidWriter chooses whether or not to use a <![CDATA[...]]> section
or simply escape '<' and '&'.  If you are emitting content for an element
in multiple calls to `' in this node, the first call decides whether or
not to use CDATA, so it's to your advantage to emit as much in the first
call as possible.  You can do

     characters( @lots_of_segments ) ;

   if it helps.

METHODS AND FUNCTIONS
=====================

   All of the routines in this module can be called as either functions or
methods unless otherwise noted.

   To call these routines as functions use either the DOCTYPE or :dtd_tags
options in the parameters to the use statement:

     use XML::ValidWriter DOCTYPE => XML::Doctype->new( ... ) ;
     use XML::ValidWriter qw( :dtd_tags ) ;

   This associates an XML::ValidWriter and an XML::Doctype with the
package.  These are used by the routines when called as functions.

new
          $writer = XML::ValidWriter->new( DTD => $dtd, OUTPUT => \*FH ) ;

     Creates an XML::ValidWriter.

     The value passed for OUTPUT may be:

    a SCALAR ref
          if you want to direct output to append to a scalar.  This scalar
          is truncated whenever the XML::ValidWriter object is reset() or
          DESTROY()ed

    a file handle glob ref or a reference to an IO object
          XML::ValidWriter does not load IO.  This is the only mode
          compatible with XML::Writer.

    a file name
          A simple scalar is taken to be a filename to be created or
          truncated and emitted to.  This file will be closed when the
          XML::ValidWriter object is reset or deatroyed.

     NOTE: if you leave OUTPUT undefined, then the currently select()ed
     output is used at each emission (ie calling select() can alter the
     destination mid-stream).  This eases writing command line filter
     applications, the select() interaction is unintentional, and please
     don't depend on it.  I reserve the right to cache the select()ed
     filehandle at creation time or at time of first emission at some
     point in the future.

import
     Can't think of why you'd call this method directly, it gets called
     when you use this module:

          use XML::ValidWriter qw( :all ) ;

     In addition to the normal functionality of exporting functions like
     startTag() and endTag(), XML::ValidWriter's import() can create
     functions corresponding to all elements in a DTD.  This is done using
     the special `:dtd_tags' export symbol.  For example,

          use XML::Doctype     NAME => 'FooML', SYSTEM_ID => 'fooml.dtd' ;
          use XML::ValidWriter qw( :dtd_tags ) ;

     where fooml.dtd referse to a tag type of 'blurb' causes these
     functions to be imported:

          blurb()         # calls defaultWriter->startTag( 'blurb', @_ ) ;
          blurb_element() # calls defaultWriter->dataElement( 'blurb', @_ ) ;
          empty_blurb()   # calls defaultWriter->emptyTag( 'blurb', @_ ) ;
          end_blurb()     # calls defaultWriter->endTag( 'blurb' ) ;

          The range of characters for element types is much larger than
          the range of characters for bareword perl subroutine names, which
          are limited to [a-zA-Z0-9_].  In this case, XML::ValidWriter will
          export an oddly named function that you can use a symbolic reference
          to call (you will need C<no strict 'refs' ;> if you are doing
          a C<use strict ;>):

          &{"space-1999:moonbase"}( ...attributes ... ) ;

     .  XML::ValidWriter will also try to fold the name in to bareword
     space by converting /\W/ symbols to '_'.  If the resulting function
     name,

          space_1999_moonbase( ...attributes... ) ;

          has not been generated and is not the name of an element type, then
          it will also be exported.

     If you are using a DTD that might introduce function names that
     conflict with existing ones, simple export them in to their own
     namespace:

          package ML ;

          use XML::Doctype     NAME => 'foo', SYSTEM_ID => 'fooml.dtd' ;
          use XML::ValidWriter qw( :dtd_tags ) ;

          package main ;

          use XML::ValidWriter qw( :all ) ;

          ML::foo ;
          ML::c2 ;
          ML::c1 ;
          ML::end_a ;

     I gave serious thought to converting ':' in element names to '::' in
     function declarations, which might work well in the
     functions-in-their-own- namespace case, but not in the default case,
     since Perl does not (yet) have relative namespaces. Another
     alternative is to allow a mapping of XML namespaces to Perl
     namespaces to be done.

characters
          characters( "escaped text", "& more" ) ;
          $writer->characters( "escaped text", "& more" ) ;

     Emits character data.  Character data will be escaped before output,
     by either transforming '<' and '&' to &lt; and &amp;, or by enclosing
     in a '`<![CDATA[...]]>'' bracket, depending on which will be more
     human-readable, according to the module.

dataElement
          $writer->dataElement( $tag ) ;
          $writer->dataElement( $tag, $content ) ;
          $writer->dataElement( $tag, $content, attr1 => $val1, ... ) ;
          dataElement( $tag ) ;
          dataElement( $tag, $content ) ;
          dataElement( $tag, $content, attr1 => $val1, ... ) ;

     Does the equivalent to

          ## Split the optional args in to attributes and elements arrays.
          $writer->startTag( $tag, @attributes ) ;
          $writer->characters( $content ) ;
          $writer->endTag( $tag ) ;

     This function is exportable as dataElement(), and is also exported
     for each element 'foo' found in the DTD as foo().

defaultWriter
          $writer = defaultWriter ;       ## Not a method!
          $writer = defaultWriter( 'Foo::Bar' ) ;

     Returns the default XML::ValidWriter for the given package, or the
     current package if none is specified.  This is useful for getting at
     methods like reset that are not also functions.

     Croaks if no default writer has been defined (see `' in this node).

doctype
          # Using the writer's associated DTD:
          doctype ;

          # Ignoring the writer's associated DTD:
          doctype( $type ) ;
          doctype( $type, undef, $system ) ;
          doctype( $type, $public, $system ) ;

          $writer->doctype ;
          ...etc

     See `' in this node to emit the entire DTD in the document.

     This checks to make sure that no doctype or elements have been
     emitted.

     A warning is emitted if standalone="yes" was specified in the
     <?xml..?> declaration and a system id is specified.  This is
     extremely likely to be an error.  If you need to silence the warning,
     write me (see below).

     Passing " or '0' (zero) as a $public_id or as a $system_id also
     generates a warning, as these are extremely likely to be errors.

emptyTag
          emptyTag( $tag[, attr1 => $val1... ] ) ;
          $writer->emptyTag( $tag[, attr1 => $val1... ] ) ;

     Emits an empty tag like '<foo />'.  The extra space is for
     compatibility with XHTML.

endTag
          endTag ;
          endTag( 'a' ) ;
          $writer->endTag ;
          $writer->endTag( 'a' ) ;

     Prints one or more end tags.  The tag name is optional and defaults
     to the most recently emitted start tag if not present.

     This will emit as many close tags as necessary to close the supplied
     tag name, or will emit an error if the tag name specified is not open
     in the output document.

end
          $writer->end ;      # Not a function!!

     Emits all necessary end tags to close the document.  Available as a
     method only, since 'end' is a little to generic to be exported as a
     function name, IMHO.  See 'endAllTags' for the plain function
     equivalent function.

endAllTags
          endAllTags ;
          $writer->endAllTags ;

     A plain function that emits all necessart end tags to close the
     document.  Corresponds to the method end, but is exportable as a
     function/

exportDTDTags
          $writer->exportDTDTags() ;
          $writer->exportDTDTags( $to_pkg ) ;

     Exports the tags found in the DTD to the caller's namespace.

getDataMode
          $m = getDataMode ;
          $m = $writer->getDataMode ;

     Returns TRUE if the writer is in DATA_MODE.

getDoctype
          $dtd = getDoctype ;
          $dtd = $writer->getDoctype ;

     This is used to get the writer's XML::Doctype object.

getOutput
          $fh = getOutput ;
          $fh = $writer->getOutput ;

     Gets the filehandle an XML::ValidWriter sends output to.

rawCharacters
          rawCharacters( "<unescaped text>", "& more text" ) ;
          $writer->rawCharacters( "<unescaped text>", "& more text" ) ;

     This allows you to emit raw text without any escape processing.  The
     text is not examined for tags, so you can invalidate your document
     and even corrupt it's well-formedness.

reset
          $writer->reset ;        # Not a function!

     Resets a writer to be initialized, but not have emitted anything.

     This is useful if you need to abort output, but want to reuse the
     XML::ValidWriter.

setDataMode
          setDataMode( 1 ) ;
          $writer->setDataMode( 1 ) ;

     Enable or disable data mode.

setDoctype
          setDoctype $doctype ;
          $writer->setDoctype( $doctype ) ;

     This is used to set the doctype object.

select_xml
          select_xml OUTHANDLE ;  # Nnot a method!!

     Selects a filehandle to send the XML output to when not using the
     object oriented interface.  This is similar to perl's builtin select,
     but only affects startTag and endTag functions, (not methods).

     This is only needed if you want to interleave output to the selected
     output files (usually STDOUT, see `select', see Perlfunc (perl.info),
     and to an XML file on another filehandle.

     If you want to redirect all output (yours and XML::Writer's) to the
     same file, just use Perl's built-in select(), since startTag and
     endTag emit to the currently selected filehandle by default.

     Like select, this returns the old value.

setOutput
          setOutput( \*FH ) ;
          $writer->setOutput( \*FH ) ;

     Sets the filehandle an XML::ValidWriter sends output to.

startTag
          startTag( 'a', attr => val ) ;  # use default XML::ValidWriter for
                                          # current package.
          $writer->startTag( 'a', attr => val ) ;

     Emits a named start tag with optional attributes.  If the named tag
     cannot be a child of the most recently started tag, then any tags
     that need to be opened between that one and the named tag are opened.

     If the named tag cannot be enclosed within the most recently opened
     tag, no matter how deep, then startTag() tries to end as few started
     tags as necessary to allow the named tag to be emitted within a tag
     already on the stack.

     This warns (once) if no <?xml?> declaration has been emitted.  It
     does not check to see if a <!DOCTYPE...> has been emitted.  It dies
     if an attempt is made to emit a second root element.

xmlDecl([[$encoding][, $standalone])
          xmlDecl ;
          xmlDecl( "UTF-8" ) ;
          xmlDecl( "UTF-8", "yes" ) ;
          $writer->xmlDecl( ... ) ;

     Emits an XML declaration.  Must be called before any of the other
     output routines.

     If $encoding is not defined, it is not output.  This is slightly
     different than XML::Writer, which outputs 'UTF-8' if you pass in
     undef, 0, or ".

     If $encoding is " or 0, then it is output as "" or "0" and a warning
     is generated.

     If $standalone is defined and is not 'no', 0, or ", it is output as
     'yes'.  If it is 'no', then it is output as 'no'.  If it's 0 or " it
     is not output.

AUTOLOAD
     This function is called whenever a function or method is not found in
     XML::ValidWriter.

     If it was a method being called, and the desired method name is a
     start or end tag found in the DTD, then a method is cooked up on the
     fly.

     These methods are slower than normal methods, but they are cached so
     that they don't need to be recompiled.  The speed penalty is probably
     not significant since they do I/O and are thus usually orders of
     magnitude slower than normal Perl methods.

DESTROY
     DESTROY is called when an XML::ValidWriter is cleaned up.  This is
     used to automatically close all tags that remain open.  This will not
     work if you have closed the output filehandle that the ValidWriter was
     using.

     This method will also warn if anything was emitted bit no root node
     was emitted.  This warning can be silenced by calling

          $writer->reset() ;

     when you abandon output.

AUTHOR
======

   Barrie Slaymaker <barries@slaysys.com>

COPYRIGHT
=========

   This module is Copyright 2000, Barrie Slaymaker.  All rights reserved.

   This module is licensed under the GPL, version 2.  Please contact me if
this does not suit your needs.

Perl extension for writing XML documents.
*****************************************

NAME
====

   XML::Writer - Perl extension for writing XML documents.

SYNOPSIS
========

     use XML::Writer;
     use IO;

     my $output = new IO::File(">output.xml");

     my $writer = new XML::Writer(OUTPUT => $output);
     $writer->startTag("greeting",
                       "class" => "simple");
     $writer->characters("Hello, world!");
     $writer->endTag("greeting");
     $writer->end();
     $output->close();

DESCRIPTION
===========

   XML::Writer is a helper module for Perl programs that write an XML
document.  The module handles all escaping for attribute values and
character data and constructs different types of markup, such as tags,
comments, and processing instructions.

   By default, the module performs several well-formedness checks to catch
errors during output.  This behaviour can be extremely useful during
development and debugging, but it can be turned off for production-grade
code.

   The module can operate either in regular mode in or Namespace
processing mode.  In Namespace mode, the module will generate Namespace
Declarations itself, and will perform additional checks on the output.

   Additional support is available for a simplified data mode with no
mixed content: newlines are automatically inserted around elements and
elements can optionally be indented based as their nesting level.

METHODS
=======

Writing XML
-----------

new([$params])
     Create a new XML::Writer object:

          my $writer = new XML::Writer(OUTPUT => $output, NEWLINES => 1);

     Arguments are an anonymous hash array of parameters:

    OUTPUT
          An object blessed into IO::Handle or one of its subclasses (such
          as IO::File); if this parameter is not present, the module will
          write to standard output.

    NAMESPACES
          A true (1) or false (0, undef) value; if this parameter is
          present and its value is true, then the module will accept
          two-member array reference in the place of element and attribute
          names, as in the following example:

               my $rdfns = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
               my $writer = new XML::Writer(NAMESPACES => 1);
               $writer->startTag([$rdfns, "Description"]);

          The first member of the array is a namespace URI, and the second
          part is the local part of a qualified name.  The module will
          automatically generate appropriate namespace declarations and
          will replace the URI part with a prefix.

    PREFIX_MAP
          A hash reference; if this parameter is present and the module is
          performing namespace processing (see the NAMESPACES parameter),
          then the module will use this hash to look up preferred prefixes
          for namespace URIs:

               my $rdfns = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
               my $writer = new XML::Writer(NAMESPACES => 1,
                                            PREFIX_MAP => {$rdfns => 'rdf'});

          The keys in the hash table are namespace URIs, and the values
          are the associated prefixes.  If there is not a preferred prefix
          for the namespace URI in this hash, then the module will
          automatically generate prefixes of the form "__NS1", "__NS2",
          etc.

          To set the default namespace, use " for the prefix.

    NEWLINES
          A true or false value; if this parameter is present and its
          value is true, then the module will insert an extra newline
          before the closing delimiter of start, end, and empty tags to
          guarantee that the document does not end up as a single, long
          line.  If the paramter is not present, the module will not
          insert the newlines.

    UNSAFE
          A true or false value; if this parameter is present and its
          value is true, then the module will skip most well-formedness
          error checking.  If the parameter is not present, the module
          will perform the well-formedness error checking by default.
          Turn off error checking at your own risk!

    DATA_MODE
          A true or false value; if this parameter is present and its
          value is true, then the module will enter a special data mode,
          inserting newlines automatically around elements and (unless
          UNSAFE is also specified) reporting an error if any element has
          both characters and elements as content.

    DATA_INDENT
          A numeric value; if this parameter is present, it represents the
          indent step for elements in data mode (it will be ignored when
          not in data mode).

end()
     Finish creating an XML document.  This method will check that the
     document has exactly one document element, and that all start tags are
     closed:

          $writer->end();

xmlDecl([$encoding, $standalone])
     Add an XML declaration to the beginning of an XML document.  The
     version will always be "1.0".  If you provide a non-null encoding or
     standalone argument, its value will appear in the declaration (and
     non-null value for standalone except 'no' will automatically be
     converted to 'yes').

          $writer->xmlDecl("UTF-8");

doctype($name, [$publicId, $systemId])
     Add a DOCTYPE declaration to an XML document.  The declaration must
     appear before the beginning of the root element.  If you provide a
     publicId, you must provide a systemId as well, but you may provide
     just a system ID.

          $writer->doctype("html");

comment($text)
     Add a comment to an XML document.  If the comment appears outside the
     document element (either before the first start tag or after the last
     end tag), the module will add a carriage return after it to improve
     readability:

          $writer->comment("This is a comment");

pi($target [, $data])
     Add a processing instruction to an XML document:

          $writer->pi('xml-stylesheet', 'href="style.css" type="text/css"');

     If the processing instruction appears outside the document element
     (either before the first start tag or after the last end tag), the
     module will add a carriage return after it to improve readability.

     The $target argument must be a single XML name.  If you provide the
     $data argument, the module will insert its contents following the
     $target argument, separated by a single space.

startTag($name [, $aname1 => $value1, ...])
     Add a start tag to an XML document.  Any arguments after the element
     name are assumed to be name/value pairs for attributes: the module
     will escape all '&', '<', '>', and '"' characters in the attribute
     values using the predefined XML entities:

          $writer->startTag('doc', 'version' => '1.0',
                                   'status' => 'draft',
                                   'topic' => 'AT&T');

     All start tags must eventually have matching end tags.

emptyTag($name [, $aname1 => $value1, ...])
     Add an empty tag to an XML document.  Any arguments after the element
     name are assumed to be name/value pairs for attributes (see startTag()
     for details):

          $writer->emptyTag('img', 'src' => 'portrait.jpg',
                                   'alt' => 'Portrait of Emma.');

endTag([$name])
     Add an end tag to an XML document.  The end tag must match the closest
     open start tag, and there must be a matching and properly-nested end
     tag for every start tag:

          $writer->endTag('doc');

     If the $name argument is omitted, then the module will automatically
     supply the name of the currently open element:

          $writer->startTag('p');
          $writer->endTag();

dataElement($name, $data [, $aname1 => $value1, ...])
     Print an entire element containing only character data.  This is
     equivalent to

          $writer->startTag($name [, $aname1 => $value1, ...]);
          $writer->characters($data);
          $writer->endTag($name);

characters($data)
     Add character data to an XML document.  All '<', '>', and '&'
     characters in the $data argument will automatically be escaped using
     the predefined XML entities:

          $writer->characters("Here is the formula: ");
          $writer->characters("a < 100 && a > 5");

     You may invoke this method only within the document element (i.e.
     after the first start tag and before the last end tag).

     In data mode, you must not use this method to add whitespace between
     elements.

setOutput($output)
     Set the current output destination, as in the OUTPUT parameter for the
     constructor.

getOutput()
     Return the current output destination, as in the OUTPUT parameter for
     the constructor.

setDataMode($mode)
     Enable or disable data mode, as in the DATA_MODE parameter for the
     constructor.

getDataMode()
     Return the current data mode, as in the DATA_MODE parameter for the
     constructor.

setDataIndent($step)
     Set the indent step for data mode, as in the DATA_INDENT parameter for
     the constructor.

getDataIndent()
     Return the indent step for data mode, as in the DATA_INDENT parameter
     for the constructor.

Querying XML
------------

in_element($name)
     Return a true value if the most recent open element matches $name:

          if ($writer->in_element('dl')) {
            $writer->startTag('dt');
          } else {
            $writer->startTag('li');
          }

within_element($name)
     Return a true value if any open elemnet matches $name:

          if ($writer->within_element('body')) {
            $writer->startTag('h1');
          } else {
            $writer->startTag('title');
          }

current_element()
     Return the name of the currently open element:

          my $name = $writer->current_element();

     This is the equivalent of

          my $name = $writer->ancestor(0);

ancestor($n)
     Return the name of the nth ancestor, where $n=0 for the current open
     element.

Additional Namespace Support
----------------------------

   WARNING: you must not use these methods while you are writing a
document, or the results will be unpredictable.

addPrefix($uri, $prefix)
     Add a preferred mapping between a Namespace URI and a prefix.  See
     also the PREFIX_MAP constructor parameter.

     To set the default namespace, omit the $prefix parameter or set it to
     ".

removePrefix($uri)
     Remove a preferred mapping between a Namespace URI and a prefix.

     To set the default namespace, omit the $prefix parameter or set it to
     ".

ERROR REPORTING
===============

   With the default settings, the XML::Writer module can detect several
basic XML well-formedness errors:

   * Lack of a (top-level) document element, or multiple document elements.

   * Unclosed start tags.

   * Misplaced delimiters in the contents of processing instructions or
     comments.

   * Misplaced or duplicate XML declaration(s).

   * Misplaced or duplicate DOCTYPE declaration(s).

   * Mismatch between the document type name in the DOCTYPE declaration and
     the name of the document element.

   * Mismatched start and end tags.

   * Attempts to insert character data outside the document element.

   * Duplicate attributes with the same name.

   During Namespace processing, the module can detect the following
additional errors:

   * Attempts to use PI targets or element or attribute names containing a
     colon.

   * Attempts to use attributes with names beginning "xmlns".

   To ensure full error detection, a program must also invoke the end
method when it has finished writing a document:

     $writer->startTag('greeting');
     $writer->characters("Hello, world!");
     $writer->endTag('greeting');
     $writer->end();

   This error reporting can catch many hidden bugs in Perl programs that
create XML documents; however, if necessary, it can be turned off by
providing an UNSAFE parameter:

     my $writer = new XML::Writer(OUTPUT => $output, UNSAFE => 1);

AUTHOR
======

   David Megginson, david@megginson.com

SEE ALSO
========

   XML::Parser

a set of modules for parsing and evaluating XPath statements
************************************************************

NAME
====

   XML::XPath - a set of modules for parsing and evaluating XPath
statements

DESCRIPTION
===========

   This module aims to comply exactly to the XPath specification at
http://www.w3.org/TR/xpath and yet allow extensions to be added in the
form of functions. Modules such as XSLT and XPointer may need to do this
as they support functionality beyond XPath.

SYNOPSIS
========

     use XML::XPath;
     use XML::XPath::XMLParser;

     my $xp = XML::XPath->new(filename => 'test.xhtml');

     my $nodeset = $xp->find('/html/body/p'); # find all paragraphs

     foreach my $node ($nodeset->get_nodelist) {
         print "FOUND\n\n",
             XML::XPath::XMLParser::as_string($node),
             "\n\n";
     }

DETAILS
=======

   There's an awful lot to all of this, so bear with it - if you stick it
out it should be worth it. Please get a good understanding of XPath by
reading the spec before asking me questions. All of the classes and parts
herein are named to be synonimous with the names in the specification, so
consult that if you don't understand why I'm doing something in the code.

API
===

   The API of XML::XPath itself is extremely simple to allow you to get
going almost immediately. The deeper API's are more complex, but you
shouldn't have to touch most of that.

new()
-----

   This constructor follows the often seen named parameter method call.
Parameters you can use are: filename, parser, xml, ioref and context.  The
filename parameter specifies an XML file to parse. The xml parameter
specifies a string to parse, and the ioref parameter specifies an ioref to
parse. The context option allows you to specify a context node. The
context node has to be in the format of a node as specified in
XML/XPath/XMLParser. The 4 parameters filename, xml,
ioref and context are mutually exclusive - you should only specify one (if
you specify anything other than context, the context node is the root of
your document).  The parser option allows you to pass in an already
prepared XML::Parser object, to save you having to create more than one in
your application (if, for example, you're doing more than just XPath).

     my $xp = XML::XPath->new( context => $node );

   It is very much recommended that you use only 1 XPath object throughout
the life of your application. This is because the object (and it's
sub-objects) maintain certain bits of state information that will be
useful (such as XPath variables) to later calls to find(). It's also a
good idea because you'll use less memory this way.

*nodeset* = find($path, [$context])
-----------------------------------

   The find function takes an XPath expression (a string) and returns
either an XML::XPath::NodeSet object containing the nodes it found (or
empty if no nodes matched the path), or one of XML::XPath::Literal (a
string), XML::XPath::Number, or XML::XPath::Boolean. It should always
return something - and you can use ->isa() to find out what it returned.
If you need to check how many nodes it found you should check
$nodeset->size.  See XML/XPath/NodeSet. An
optional second parameter of a context node allows you to use this method
repeatedly, for example XSLT needs to do this.

findnodes($path, [$context])
----------------------------

   Returns a list of nodes found by $path, optionally in context $context.
In scalar context returns an XML::XPath::NodeSet object.

findnodes_as_string($path, [$context])
--------------------------------------

   Returns the nodes found reproduced as XML. The result is not guaranteed
to be valid XML though.

findvalue($path, [$context])
----------------------------

   Returns either a `XML::XPath::Literal', a `XML::XPath::Boolean' or a
`XML::XPath::Number' object. If the path returns a NodeSet,
$nodeset->to_literal is called automatically for you (and thus a
`XML::XPath::Literal' is returned). Note that for each of the objects
stringification is overloaded, so you can just print the value found, or
manipulate it in the ways you would a normal perl value (e.g. using
regular expressions).

matches($node, $path, [$context])
---------------------------------

   Returns true if the node matches the path (optionally in context
$context).

set_namespace($prefix, $uri)
----------------------------

   Sets the namespace prefix mapping to the uri.

   Normally in XML::XPath the prefixes in XPath node tests take their
context from the current node. This means that foo:bar will always match
an element <foo:bar> regardless of the namespace that the prefix foo is
mapped to (which might even change within the document, resulting in
unexpected results). In order to make prefixes in XPath node tests
actually map to a real URI, you need to enable that via a call to the
set_namespace method of your XML::XPath object.

clear_namespaces()
------------------

   Clears all previously set namespace mappings.

$XML::XPath::Namespaces
-----------------------

   Set this to 0 if you *don't* want namespace processing to occur. This
will make everything a little (tiny) bit faster, but you'll suffer for it,
probably.

Node Object Model
=================

   See XML/XPath/Node,
XML/XPath/Node/Element,
XML/XPath/Node/Text, XML/XPath/Node/Comment,
see XML/XPath/Node/Attribute,
see XML/XPath/Node/Namespace,
and XML/XPath/Node/PI.

On Garbage Collection
=====================

   XPath nodes work in a special way that allows circular references, and
yet still lets Perl's reference counting garbage collector to clean up the
nodes after use. This should be totally transparent to the user, with one
caveat: *If you free your tree before letting go of a sub-tree, consider
that playing with fire and you may get burned*. What does this mean to the
average user? Not much. Provided you don't free (or let go out of scope)
either the tree you passed to XML::XPath->new, or if you didn't pass a
tree, and passed a filename or IO-ref, then provided you don't let the
XML::XPath object go out of scope before you let results of find() and its
friends go out of scope, then you'll be fine. Even if you do let the tree
go out of scope before results, you'll probably still be fine. The only
case where you may get stung is when the last part of your path/query is
either an ancestor or parent axis. In that case the worst that will happen
is you'll end up with a circular reference that won't get cleared until
interpreter destruction time. You can get around that by explicitly
calling $node->DESTROY on each of your result nodes, if you really need to
do that.

   Mail me direct if that's not clear. Note that it's not doom and gloom.
It's by no means perfect, but the worst that will happen is a long running
process could leak memory. Most long running processes will therefore be
able to explicitly be careful not to free the tree (or XML::XPath object)
before freeing results. AxKit, an application that uses XML::XPath, does
this and I didn't have to make any changes to the code - it's already
sensible programming.

   If you *really* don't want all this to happen, then set the variable
$XML::XPath::SafeMode, and call $xp->cleanup() on the XML::XPath object
when you're finished, or $tree->dispose() if you have a tree instead.

Example
=======

   Please see the test files in t/ for examples on how to use XPath.

Support/Author
==============

   This module is copyright 2000 AxKit.com Ltd. This is free software, and
as such comes with NO WARRANTY. No dates are used in this module. You may
distribute this module under the terms of either the Gnu GPL,  or the
Artistic License (the same terms as Perl itself).

   For support, please subscribe to the Perl-XML mailing list at the URL
http://listserv.activestate.com/mailman/listinfo/perl-xml

   Matt Sergeant, matt@sergeant.org

SEE ALSO
========

   See XML/XPath/Literal, XML/XPath/Boolean,
see XML/XPath/Number,
XML/XPath/XMLParser, XML/XPath/NodeSet,
see XML/XPath/PerlSAX,
XML/XPath/Builder.

Boolean true/false values
*************************

NAME
====

   XML::XPath::Boolean - Boolean true/false values

DESCRIPTION
===========

   XML::XPath::Boolean objects implement simple boolean true/false objects.

API
===

XML::XPath::Boolean->True
-------------------------

   Creates a new Boolean object with a true value.

XML::XPath::Boolean->False
--------------------------

   Creates a new Boolean object with a false value.

value()
-------

   Returns true or false.

to_literal()
------------

   Returns the string "true" or "false".

SAX handler for building an XPath tree
**************************************

NAME
====

   XML::XPath::Builder - SAX handler for building an XPath tree

SYNOPSIS
========

     use AnySAXParser;
     use XML::XPath::Builder;

     $builder = XML::XPath::Builder->new();
     $parser = AnySAXParser->new( Handler => $builder );

     $root_node = $parser->parse( Source => [SOURCE] );

DESCRIPTION
===========

   `XML::XPath::Builder' is a SAX handler for building an XML::XPath tree.

   `XML::XPath::Builder' is used by creating a new instance of
`XML::XPath::Builder' and providing it as the Handler for a SAX parser.
Calling `parse()' on the SAX parser will return the root node of the tree
built from that parse.

AUTHOR
======

   Ken MacLeod, <ken@bitsko.slc.ut.us>

SEE ALSO
========

   perl(1), XML::XPath(3)

   PerlSAX.pod in libxml-perl

   Extensible Markup Language (XML) <http://www.w3c.org/XML>

Simple string values.
*********************

NAME
====

   XML::XPath::Literal - Simple string values.

DESCRIPTION
===========

   In XPath terms a Literal is what we know as a string.

API
===

new($string)
------------

   Create a new Literal object with the value in $string. Note that &quot;
and &apos; will be converted to " and ' respectively. That is not part of
the XPath specification, but I consider it useful. Note though that you
have to go to extraordinary lengths in an XML template file (be it XSLT or
whatever) to make use of this:

     <xsl:value-of select="&quot;I'm feeling &amp;quot;sad&amp;quot;&quot;"/>

   Which produces a Literal of:

     I'm feeling "sad"

value()
-------

   Also overloaded as stringification, simply returns the literal string
value.

cmp($literal)
-------------

   Returns the equivalent of perl's cmp operator against the given
$literal.

internal representation of a node
*********************************

NAME
====

   XML::XPath::Node - internal representation of a node

API
===

   The Node API aims to emulate DOM to some extent, however the API isn't
quite compatible with DOM. This is to ease transition from XML::DOM
programming to XML::XPath. Compatibility with DOM may arise once XML::DOM
gets namespace support.

new
---

   Creates a new node. See the sub-classes for parameters to pass to new().

getNodeType
-----------

   Returns one of ELEMENT_NODE, TEXT_NODE, COMMENT_NODE, ATTRIBUTE_NODE,
PROCESSING_INSTRUCTION_NODE or NAMESPACE_NODE. UNKNOWN_NODE is returned if
the sub-class doesn't implement getNodeType - but that means something is
broken! The constants are exported by default from XML::XPath::Node. The
constants have the same numeric value as the XML::DOM versions.

getParentNode
-------------

   Returns the parent of this node, or undef if this is the root node. Note
that the root node is the root node in terms of XPath - not the root
element node.

to_sax ( $handler | %handlers )
-------------------------------

   Generates sax calls to the handler or handlers. See the PerlSAX docs for
details (not yet implemented correctly).

MORE INFO
=========

   See the sub-classes for the meaning of the rest of the API:

   * See XML/XPath/Node/Element

   * See XML/XPath/Node/Attribute

   * See XML/XPath/Node/Namespace

   * See XML/XPath/Node/Text

   * See XML/XPath/Node/Comment

   * See XML/XPath/Node/PI

a single attribute
******************

NAME
====

   Attribute - a single attribute

API
===

new ( key, value, prefix )
--------------------------

   Create a new attribute node.

getName
-------

   Returns the key for the attribute

getValue / getData
------------------

   Returns the value

getPrefix
---------

   Returns the prefix

toString
--------

   Generates key="value", encoded correctly.

an XML comment: <!-comment->
****************************

NAME
====

   Comment - an XML comment: <!-comment->

API
===

new ( data )
------------

   Create a new comment node.

getValue / getData
------------------

   Returns the value in the comment

toString
--------

   Returns the comment with - encoded as a numeric entity (if it exists in
the comment text).

an <element>
************

NAME
====

   Element - an <element>

API
===

new ( name, prefix )
--------------------

   Create a new Element node with name "name" and prefix "prefix". The name
be "prefix:local" if prefix is defined. I know that sounds wierd, but it
works ;-)

getName
-------

   Returns the name (including "prefix:" if defined) of this element.

getLocalName
------------

   Returns just the local part of the name (the bit after "prefix:").

getChildNodes
-------------

   Returns the children of this element. In list context returns a list. In
scalar context returns an array ref.

getChildNode ( pos )
--------------------

   Returns the child at position pos.

appendChild ( childnode )
-------------------------

   Appends the child node to the list of current child nodes.

getAttribute ( name )
---------------------

   Returns the attribute node with key name.

getAttributes / getAttributeNodes
---------------------------------

   Returns the attribute nodes. In list context returns a list. In scalar
context returns an array ref.

appendAttribute ( attrib_node)
------------------------------

   Appends the attribute node to the list of attributes (XML::XPath stores
attributes in order).

getNamespace ( prefix )
-----------------------

   Returns the namespace node by the given prefix

getNamespaces / getNamespaceNodes
---------------------------------

   Returns the namespace nodes. In list context returns a list. In scalar
context returns an array ref.

appendNamespace ( ns_node )
---------------------------

   Appends the namespace node to the list of namespaces.

getPrefix
---------

   Returns the prefix of this element

getExpandedName
---------------

   Returns the expanded name of this element (not yet implemented right).

string_value
------------

   For elements, the string_value is the concatenation of all string_values
of all text-descendants of the element node in document order.

toString ( [ norecurse ] )
--------------------------

   Output (and all children) the node to a string. Doesn't process children
if the norecurse option is a true value.

an XML namespace node
*********************

NAME
====

   Namespace - an XML namespace node

API
===

new ( prefix, expanded )
------------------------

   Create a new namespace node, expanded is the expanded namespace URI.

getPrefix
---------

   Returns the prefix

getExpanded
-----------

   Returns the expanded URI

toString
--------

   Returns a string that you can add to the list of attributes of an
element: xmlns:prefix="expanded"

an XML processing instruction node
**********************************

NAME
====

   PI - an XML processing instruction node

API
===

new ( target, data )
--------------------

   Create a new PI node.

getTarget
---------

   Returns the target

getData
-------

   Returns the data

an XML text node
****************

NAME
====

   Text - an XML text node

API
===

new ( text )
------------

   Create a new text node.

getValue / getData
------------------

   Returns the text

string_value
------------

   Returns the text

appendText ( text )
-------------------

   Adds the given text string to this node.

a list of XML document nodes
****************************

NAME
====

   XML::XPath::NodeSet - a list of XML document nodes

DESCRIPTION
===========

   An XML::XPath::NodeSet object contains an ordered list of nodes. The
nodes each take the same format as described in XML/XPath/XMLParser.

SYNOPSIS
========

     my $results = $xp->find('//someelement');
     if (!$results->isa('XML::XPath::NodeSet')) {
     	print "Found $results\n";
     	exit;
     }
     foreach my $context ($results->get_nodelist) {
     	my $newresults = $xp->find('./other/element', $context);
     	...
     }

API
===

new()
-----

   You will almost never have to create a new NodeSet object, as it is all
done for you by XPath.

get_nodelist()
--------------

   Returns a list of nodes. See XML/XPath/XMLParser,
for the format of the nodes.

string_value()
--------------

   Returns the string-value of the first node in the list.  See the XPath
specification for what "string-value" means.

to_literal()
------------

   Returns the concatenation of all the string-values of all the nodes in
the list.

get_node($pos)
--------------

   Returns the node at $pos. The node position in XPath is based at 1, not
0.

size()
------

   Returns the number of nodes in the NodeSet.

pop()
-----

   Equivalent to perl's pop function.

push(@nodes)
------------

   Equivalent to perl's push function.

append($nodeset)
----------------

   Given a nodeset, appends the list of nodes in $nodeset to the end of the
current list.

shift()
-------

   Equivalent to perl's shift function.

unshift(@nodes)
---------------

   Equivalent to perl's unshift function.

prepend($nodeset)
-----------------

   Given a nodeset, prepends the list of nodes in $nodeset to the front of
the current list.

Simple numeric values.
**********************

NAME
====

   XML::XPath::Number - Simple numeric values.

DESCRIPTION
===========

   This class holds simple numeric values. It doesn't support -0, +/-
Infinity, or NaN, as the XPath spec says it should, but I'm not hurting
anyone I don't think.

API
===

new($num)
---------

   Creates a new XML::XPath::Number object, with the value in $num. Does
some rudimentary numeric checking on $num to ensure it actually is a
number.

value()
-------

   Also as overloaded stringification. Returns the numeric value held.

A PerlSAX event generator for my wierd node structure
*****************************************************

NAME
====

   XML::XPath::PerlSAX - A PerlSAX event generator for my wierd node
structure

SYNOPSIS
========

     use XML::XPath;
     use XML::XPath::PerlSAX;
     use XML::DOM::PerlSAX;

     my $xp = XML::XPath->new(filename => 'test.xhtml');
     my $paras = $xp->find('/html/body/p');

     my $handler = XML::DOM::PerlSAX->new();
     my $generator = XML::XPath::PerlSAX->new( Handler => $handler );

     foreach my $node ($paras->get_nodelist) {
     	my $domtree = $generator->parse($node);
     	# do something with $domtree
     }

DESCRIPTION
===========

   This module generates PerlSAX events to pass to a PerlSAX handler such
as XML::DOM::PerlSAX. It operates specifically on my wierd tree format.

   Unfortunately SAX doesn't seem to cope with namespaces, so these are
lost completely. I believe SAX2 is doing namespaces.

Other
=====

   The XML::DOM::PerlSAX handler I tried was completely broken (didn't even
compile before I patched it a bit), so I don't know how correct this is or
how far it will work.

   This software may only be distributed as part of the XML::XPath package.

The default XML parsing class that produces a node tree
*******************************************************

NAME
====

   XML::XPath::XMLParser - The default XML parsing class that produces a
node tree

SYNOPSIS
========

     my $parser = XML::XPath::XMLParser->new(
                 filename => $self->get_filename,
                 xml => $self->get_xml,
                 ioref => $self->get_ioref,
                 parser => $self->get_parser,
             );
     my $root_node = $parser->parse;

DESCRIPTION
===========

   This module generates a node tree for use as the context node for XPath
processing.  It aims to be a quick parser, nothing fancy, and yet has to
store more information than most parsers. To achieve this I've used array
refs everywhere - no hashes.  I don't have any performance figures for the
speedups achieved, so I make no appologies for anyone not used to using
arrays instead of hashes. I think they make good sense here where we know
the attributes of each type of node.

Node Structure
==============

   All nodes have the same first 2 entries in the array: node_parent and
node_pos. The type of the node is determined using the ref() function.
The node_parent always contains an entry for the parent of the current
node - except for the root node which has undef in there. And node_pos is
the position of this node in the array that it is in (think: $node ==
$node->[node_parent]->[node_children]->[$node->[node_pos]] )

   Nodes are structured as follows:

Root Node
---------

   The root node is just an element node with no parent.

     [
       undef, # node_parent - check for undef to identify root node
       undef, # node_pos
       undef, # node_prefix
       [ ... ], # node_children (see below)
     ]

Element Node
------------

     [
       $parent, # node_parent
       <position in current array>, # node_pos
       'xxx', # node_prefix - namespace prefix on this element
       [ ... ], # node_children
       'yyy', # node_name - element tag name
       [ ... ], # node_attribs - attributes on this element
       [ ... ], # node_namespaces - namespaces currently in scope
     ]

Attribute Node
--------------

     [
       $parent, # node_parent - the element node
       <position in current array>, # node_pos
       'xxx', # node_prefix - namespace prefix on this element
       'href', # node_key - attribute name
       'ftp://ftp.com/', # node_value - value in the node
     ]

Namespace Nodes
---------------

   Each element has an associated set of namespace nodes that are currently
in scope. Each namespace node stores a prefix and the expanded name
(retrieved from the xmlns:prefix="..." attribute).

     [
       $parent,
       <pos>,
       'a', # node_prefix - the namespace as it was written as a prefix
       'http://my.namespace.com', # node_expanded - the expanded name.
     ]

Text Nodes
----------

     [
       $parent,
       <pos>,
       'This is some text' # node_text - the text in the node
     ]

Comment Nodes
-------------

     [
       $parent,
       <pos>,
       'This is a comment' # node_comment
     ]

Processing Instruction Nodes
----------------------------

     [
       $parent,
       <pos>,
       'target', # node_target
       'data', # node_data
     ]

Usage
=====

   If you feel the need to use this module outside of XML::XPath (for
example you might use this module directly so that you can cache parsed
trees), you can follow the following API:

new
---

   The new method takes either no parameters, or any of the following
parameters:

     filename
     xml
     parser
     ioref

   This uses the familiar hash syntax, so an example might be:

     use XML::XPath::XMLParser;

     my $parser = XML::XPath::XMLParser->new(filename => 'example.xml');

   The parameters represent a filename, a string containing XML, an
XML::Parser instance and an open filehandle ref respectively. You can also
set or get all of these properties using the get_ and set_ functions that
have the same name as the property: e.g. get_filename, set_ioref, etc.

parse
-----

   The parse method generally takes no parameters, however you are free to
pass either an open filehandle reference or an XML string if you so
require.  The return value is a tree that XML::XPath can use. The parse
method will die if there is an error in your XML, so be sure to use perl's
exception handling mechanism (eval{};) if you want to avoid this.

parsefile
---------

   The parsefile method is identical to parse() except it expects a single
parameter that is a string naming a file to open and parse. Again it
returns a tree and also dies if there are XML errors.

NOTICES
=======

   This file is distributed as part of the XML::XPath module, and is
copyright 2000 Fastnet Software Ltd. Please see the documentation for the
module as a whole for licencing information.

Stand alone XPathScript
***********************

NAME
====

   XML::XPathScript - Stand alone XPathScript

SYNOPSIS
========

     use XML::XPathScript;
     my $xps = XML::XPathScript->new(xml => $xml, stylesheet => $stylesheet);
     $xps->process;

DESCRIPTION
===========

   This is a standalone version of XPathScript, originally part of the
AxKit project at http://axkit.org/

   XPathScript is a stylesheet language similar in many ways to XSLT (in
concept, not in appearance), for transforming XML from one format to
another format (possibly HTML).

   The documentation for the XPathScript language is available on the
AxKit web site at the URL above.

USAGE
=====

   TODO

BUGS
====

   Currently output is to STDOUT. I'd like to fix this, though my time on
this module is limited as I do not personally have a use for this module,
since I mainly just use AxKit itself. Patches welcome.

AUTHOR
======

   Matt Sergeant, matt@sergeant.org

LICENSE
=======

   This is free software. You may distribute it under the same terms as
Perl itself.

A perl module for querying XML tree structures with XQL
*******************************************************

NAME
====

   XML::XQL - A perl module for querying XML tree structures with XQL

SYNOPSIS
========

     use XML::XQL;
     use XML::XQL::DOM;

     $parser = new XML::DOM::Parser;
     $doc = $parser->parsefile ("file.xml");

     # Return all elements with tagName='title' under the root element 'book'
     $query = new XML::XQL::Query (Expr => "book/title");
     @result = $query->solve ($doc);
     $query->dispose; # Avoid memory leaks - Remove circular references

     # Or (to save some typing)
     @result = XML::XQL::solve ("book/title", $doc);

     # Or (to save even more typing)
     @result = $doc->xql ("book/title");

DESCRIPTION
===========

   The XML::XQL module implements the XQL (XML Query Language) proposal
submitted to the XSL Working Group in September 1998.  The spec can be
found at: `http:' in this node Most of the contents related to the XQL
syntax can also be found in the XML/XQL/Tutorial,
that comes with this distribution.  Note that XQL is not the same as
XML-QL!

   The current implementation only works with the XML/DOM,
module, but once the design is stable and the major bugs are flushed out,
other extensions might follow, e.g. for XML::Grove.

   XQL was designed to be extensible and this implementation tries to
stick to that.  Users can add their own functions, methods, comparison
operators and data types.  Plugging in a new XML tree structure (like
XML::Grove) should be a piece of cake.

   To use the XQL module, either

     use XML::XQL;

   or

     use XML::XQL::Strict;

   The Strict module only provides the core XQL functionality as found in
the XQL spec. By default (i.e. by using XML::XQL) you get 'XQL+', which has
some additional features.

   See the section `Additional Features in XQL+' in this node for the
differences.

   This module is still in development. See the To-do list in XQL.pm for
what still needs to be done. Any suggestions are welcome, the sooner these
implementation issues are resolved, the faster we can all use this module.

   If you find a bug, you would do me great favor by sending it to me in
the form of a test case. See the file t/xql_template.t that comes with
this distribution.

   If you have written a cool comparison operator, function, method or XQL
data type that you would like to share, send it to enno@att.com and I will
add it to this module.

XML::XQL global functions
=========================

solve (QUERY_STRING, INPUT_LIST...)
          @result = XML::XQL::solve ("doc//book", $doc);

     This is provided as a shortcut for:

          $query = new XML::XQL::Query (Expr => "doc//book");
          @result = $query->solve ($doc);
          $query->dispose;

     Note that with XML/XQL/DOM, you can also write
     (see XML/DOM/Node, for details):

          @result = $doc->xql ("doc//book");

setDocParser (PARSER)
     Sets the XML::DOM::Parser that is used by the new XQL+ document()
     method.  By default it uses an XML::DOM::Parser that was created
     without any arguments, i.e.

          $PARSER = new XML::DOM::Parser;

defineFunction (NAME, FUNCREF, ARGCOUNT [, ALLOWED_OUTSIDE [, CONST, [QUERY_ARG]]])
     Defines the XQL function (at the global level, i.e. for all newly
     created queries) with the specified NAME. The ARGCOUNT parameter can
     either be a single number or a reference to a list with numbers.  A
     single number expands to [ARGCOUNT, ARGCOUNT]. The list contains
     pairs of numbers, indicating the number of arguments that the
     function allows. The value -1 means infinity. E.g. [2, 5, 7, 9, 12,
     -1] means that the function can have 2, 3, 4, 5, 7, 8, 9, 12 or more
     arguments.  The number of arguments is checked when parsing the XQL
     query string.

     The second parameter must be a reference to a Perl function or an
     anonymous sub. E.g. '\&my_func' or 'sub { ... code ... }'

     If ALLOWED_OUTSIDE (default is 0) is set to 1, the function or method
     may also be used outside subqueries in *node queries*.  (See
     NodeQuery parameter in Query constructor)

     If CONST (default is 0) is set to 1, the function is considered to be
     "constant". See `Constant Function Invocations' in this node for
     details.

     If QUERY_ARG (default is 0) is not -1, the argument with that index is
     considered to be a 'query parameter'. If the query parameter is a
     subquery, that returns multiple values, the result list of the
     function invocation will contain one result value for each value of
     the subquery.  E.g. 'length(book/author)' will return a list of
     Numbers, denoting the string lengths of all the author elements
     returned by 'book/author'.

     Note that only methods (not functions) may appear after a Bang "!"
     operator.  This is checked when parsing the XQL query string.

     See also: defineMethod

generateFunction (NAME, FUNCNAME, RETURN_TYPE [, ARGCOUNT [, ALLOWED_OUTSIDE [, CONST [, QUERY_ARG]]]])
     Generates and defines an XQL function wrapper for the Perl function
     with the name FUNCNAME. The function name will be NAME in XQL query
     expressions.  The return type should be one of the builtin XQL Data
     Types or a class derived from XML::XQL::PrimitiveType (see `Adding
     Data Types' in this node.)  See defineFunction for the meaning of
     ARGCOUNT, ALLOWED_OUTSIDE, CONST and QUERY_ARG.

     Function values are always converted to Perl strings with
     xql_toString before they are passed to the Perl function
     implementation. The function return value is cast to an object of
     type RETURN_TYPE, or to the empty list [] if the result is undef. It
     uses expandType to expand XQL primitive type names.  If RETURN_TYPE
     is "*", it returns the function result as is, unless the function
     result is undef, in which case it returns [].

defineMethod (NAME, FUNCREF, ARGCOUNT [, ALLOWED_OUTSIDE])
     Defines the XQL method (at the global level, i.e. for all newly
     created queries) with the specified NAME. The ARGCOUNT parameter can
     either be a single number or a reference to a list with numbers.  A
     single number expands to [ARGCOUNT, ARGCOUNT]. The list contains
     pairs of numbers, indicating the number of arguments that the method
     allows. The value -1 means infinity. E.g. [2, 5, 7, 9, 12, -1] means
     that the method can have 2, 3, 4, 5, 7, 8, 9, 12 or more arguments.
     The number of arguments is checked when parsing the XQL query string.

     The second parameter must be a reference to a Perl function or an
     anonymous sub. E.g. '\&my_func' or 'sub { ... code ... }'

     If ALLOWED_OUTSIDE (default is 0) is set to 1, the function or method
     may also be used outside subqueries in *node queries*.  (See
     NodeQuery parameter in Query constructor)

     Note that only methods (not functions) may appear after a Bang "!"
     operator.  This is checked when parsing the XQL query string.

     See also: defineFunction

defineComparisonOperators (NAME => FUNCREF [, NAME => FUNCREF]*)
     Defines XQL comparison operators at the global level.  The FUNCREF
     parameters must be a references to a Perl function or an anonymous
     sub. E.g. '\&my_func' or 'sub { ... code ... }'

     E.g. define the operators $my_op$ and $my_op2$:

          defineComparisonOperators ('my_op' => \&my_op,
                                     'my_op2' => sub { ... insert code here ... });

defineElementValueConvertor (TAG_NAME, FUNCREF)
     Defines that the result of the value() call for Elements with the
     specified TAG_NAME uses the specified function. The function will
     receive two parameters. The second one is the TAG_NAME of the Element
     node and the first parameter is the Element node itself.  FUNCREF
     should be a reference to a Perl function, e.g. \&my_sub, or an
     anonymous sub.

     E.g. to define that all Elements with tag name 'date-of-birth' should
     return XML::XQL::Date objects:

          defineElementValueConvertor ('date-of-birth', sub {
          	my $elem = shift;
          	# Always pass in the node as the second parameter. This is
          	# the reference node for the object, which is used when
          	# sorting values in document order.
          	new XML::XQL::Date ($elem->xql_text, $elem);
          });

     These convertors can only be specified at a global level, not on a
     per query basis. To undefine a convertor, simply pass a FUNCREF of
     undef.

defineAttrValueConvertor (ELEM_TAG_NAME, ATTR_NAME, FUNCREF)
     Defines that the result of the value() call for Attributes with the
     specified ATTR_NAME and a parent Element with the specified
     ELEM_TAG_NAME uses the specified function. An ELEM_TAG_NAME of "*"
     will match regardless of the tag name of the parent Element. The
     function will receive 3 parameters. The third one is the tag name of
     the parent Element (even if ELEM_TAG_NAME was "*"), the second is the
     ATTR_NAME and the first is the Attribute node itself.  FUNCREF should
     be a reference to a Perl function, e.g. \&my_sub, or an anonymous sub.

     These convertors can only be specified at a global level, not on a
     per query basis. To undefine a convertor, simply pass a FUNCREF of
     undef.

defineTokenQ (Q)
     Defines the token for the q// string delimiters at a global level.
     The default value for XQL+ is 'q', for XML::XQL::Strict it is undef.
     A value of undef will deactivate this feature.

defineTokenQQ (QQ)
     Defines the token for the qq// string delimiters at a global level.
     The default value for XQL+ is 'qq', for XML::XQL::Strict it is undef.
     A value of undef will deactivate this feature.

expandType (TYPE)
     Used internally to expand type names of XQL primitive types.  E.g. it
     expands "Number" to "XML::XQL::Number" and is not case-sensitive, so
     "number" and "NuMbEr" will both expand correctly.

defineExpandedTypes (ALIAS, FULL_NAME [, ...])
     For each pair of arguments it allows the class name FULL_NAME to be
     abbreviated with ALIAS. The definitions are used by expandType().
     (ALIAS is always converted to lowercase internally, because expandType
     is case-insensitive.)

     Overriding the ALIAS for "date", also affects the object type
     returned by the date() function.

setErrorContextDelimiters (START, END, BOLD_ON, BOLD_OFF)
     Sets the delimiters used when printing error messages during query
     evaluation.  The default delimiters on Unix are `tput smul`
     (underline on) and `tput rmal` (underline off). On other systems
     (that don't have tput), the delimiters are ">>" and "<<" resp.

     When printing the error message, the subexpression that caused the
     error will be enclosed by the delimiters, i.e. underlined on Unix.

     For certain subexpressions the significant keyword, e.g. "$and$" is
     enclosed in the bold delimiters BOLD_ON (default: `tput bold` on
     Unix, "" elsewhere) and BOLD_OFF (default: (`tput rmul` . `tput
     smul`) on Unix, "" elsewhere, see $BoldOff in XML::XQL::XQL.pm for
     details.)

isEmptyList (VAR)
     Returns 1 if VAR is [], else 0. Can be used in user defined functions.

Additional Features in XQL+
===========================

Parent operator '..'
     The '..' operator returns the parent of the current node, where '.'
     would return the current node. This is not part of any XQL standard,
     because you would normally use return operators, which are not
     implemented here.

Sequence operators ';' and ';;'
     The sequence operators ';' (precedes) and ';;' (immediately precedes)
     are not in the XQL spec, but are described in 'The Design of XQL' by
     Jonathan Robie who is one of the designers of XQL. It can be found at
     `http:' in this node See also the XQL Tutorial for a description of
     what they mean.

q// and qq// String Tokens
     String tokens a la q// and qq// are allowed. q// evaluates like
     Perl's single quotes and qq// like Perl's double quotes. Note that
     the default XQL strings do not allow escaping etc., so it's not
     possible to define a string with both single and double quotes. If
     'q' and 'qq' are not to your liking, you may redefine them to
     something else or undefine them altogether, by assigning undef to
     them. E.g:

          # at a global level - shared by all queries (that don't (re)define 'q')
          XML::XQL::defineTokenQ ('k');
          XML::XQL::defineTokenQQ (undef);

          # at a query level - only defined for this query
          $query = new XML::XQL::Query (Expr => "book/title", q => 'k', qq => undef);

          From now on k// works like q// did and qq// doesn't work at all anymore.

Query strings can have embedded Comments
     For example:

          $queryExpr = "book/title          # this comment is inside the query string
          	       [. = 'Moby Dick']"; # this comment is outside

Optional dollar delimiters and case-insensitive XQL keywords
     The following XQL keywords are case-insensitive and the dollar sign
     delimiters may be omitted: $and$, $or$, $not$, $union$, $intersect$,
     $to$, $any$, $all$, $eq$, $ne$, $lt$, $gt$, $ge$, $le$, $ieq$, $ine$,
     $ilt$, $igt$, $ige$, $ile$.

     E.g. $AND$, $And$, $aNd$, and, And, aNd are all valid replacements
     for $and$.

     Note that XQL+ comparison operators ($match$, $no_match$, $isa$,
     $can$) still require dollar delimiters and are case-sensitive.

Comparison operator: $match$ or '=~'
     E.g. "book/title =~ '/(Moby|Dick)/']" will return all book titles
     containing Moby or Dick. Note that the match expression needs to be
     quoted and should contain the // or m// delimiters for Perl.

     When casting the values to be matched, both are converted to Text.

Comparison operator: $no_match$ or '!~'
     E.g. "book/title !~ '/(Moby|Dick)/']" will return all book titles
     that don't contain Moby or Dick. Note that the match expression needs
     to be quoted and should contain the // or m// delimiters for Perl.

     When casting the values to be matched, both are converted to Text.

Comparison operator: $isa$
     E.g. '//. $isa$ "XML::XQL::Date"' returns all elements for which the
     value() function returns an XML::XQL::Date object. (Note that the
     value() function can be overridden to return a specific object type
     for certain elements and attributes.) It uses expandType to expand
     XQL primitive type names.

Comparison operator: $can$
     E.g. '//. $can$ "swim"' returns all elements for which the value()
     function returns an object that implements the (Perl) swim() method.
     (Note that the value() function can be overridden to return a
     specific object type for certain elements and attributes.)

Function: once (QUERY)
     E.g. 'once(id("foo"))' will evaluate the QUERY expression only once
     per query.  Certain query results (like the above example) will
     always return the same value within a query. Using once() will cache
     the QUERY result for the rest of the query.

     Note that "constant" function invocations are always cached.  See
     also `Constant Function Invocations' in this node

Function: subst (QUERY, EXPR, EXPR [,MODIFIERS, [MODE]])
     E.g. 'subst(book/title, "[M|m]oby", "Dick", "g")' will replace Moby
     or moby with Dick globally ("g") in all book title elements.
     Underneath it uses Perl's substitute operator s///. Don't worry about
     which delimiters are used underneath.  The function returns all the
     book/titles for which a substitution occurred.  The default MODIFIERS
     string is "" (empty.) The function name may be abbreviated to "s".

     For most Node types, it converts the value() to a string (with
     xql_toString) to match the string and xql_setValue to set the new
     value in case it matched.  For XQL primitives (Boolean, Number, Text)
     and other data types (e.g. Date) it uses xql_toString to match the
     String and xql_setValue to set the result.  Beware that performing a
     substitution on a primitive that was found in the original XQL query
     expression, changes the value of that constant.

     If MODE is 0 (default), it treats Element nodes differently by
     matching and replacing *text blocks* occurring in the Element node. A
     text block is defined as the concatenation of the raw text of
     subsequent Text, CDATASection and EntityReference nodes. In this mode
     it skips embedded Element nodes.  If a text block matches, it is
     replaced by a single Text node, regardless of the original node
     type(s).

     If MODE is 1, it treats Element nodes like the other nodes, i.e. it
     converts the value() to a string etc. Note that the default
     implementation of value() calls text(), which normalizes whitespace
     and includes embedded Element descendants (recursively.) This is
     probably not what you want to use in most cases, but since I'm not a
     professional psychic... :-)

Function: map (QUERY, CODE)
     E.g. 'map(book/title, "s/[M|m]oby/Dick/g; $_")' will replace Moby or
     moby with Dick globally ("g") in all book title elements. Underneath
     it uses Perl's map operator. The function returns all the book/titles
     for which a change occurred.

     ??? add more specifics

Function: eval (EXPR [,TYPE])
     Evaluates the Perl expression EXPR and returns an object of the
     specified TYPE.  It uses expandType to expand XQL primitive type
     names.  If the result of the eval was undef, the empty list [] is
     returned.

     E.g. 'eval("2 + 5", "Number")' returns a Number object with the value
     7, and      'eval("%ENV{USER}")' returns a Text object with the user
     name.

     Consider using once() to cache the return value, when the invocation
     will return the same result for each invocation within a query.

     ??? add more specifics

Function: new (TYPE [, QUERY [, PAR] *])
     Creates a new object of the specified object TYPE. The constructor
     may have any number of arguments. The first argument of the
     constructor (the 2nd argument of the new() function) is considered to
     be a 'query parameter'.  See defineFunction for a definition of
     *query parameter*.  It uses expandType to expand XQL primitive type
     names.

Function: document (QUERY) or doc (QUERY)
     The document() function creates a new `XML::XML::Document' in this
     node for each result of QUERY (QUERY may be a simple string
     expression, like "/usr/enno/file.xml".  See t/xql_document.t or below
     for an example with a more complex QUERY.)

     document() may be abbreviated to doc().

     document() uses an XML::DOM::Parser underneath, which can be set with
     XML::XQL::setDocParser(). By default it uses a parser that was
     created without any arguments, i.e.

          $PARSER = new XML::DOM::Parser;

     Let's try a more complex example, assuming $doc contains:

          <doc>
           <file name="file1.xml"/>
           <file name="file2.xml"/>
          </doc>

     Then the following query will return two `XML::XML::Document' in this
     nodes, one for file1.xml and one for file2.xml:

          @result = XML::XQL::solve ("document(doc/file/@name)", $doc);

     The resulting documents can be used as input for following queries,
     e.g.

          @result = XML::XQL::solve ("document(doc/file/@name)/root/bla", $doc);

     will return all /root/bla elements from the documents returned by
     document().

Method: DOM_nodeType ()
     Returns the DOM node type. Note that these are mostly the same as
     nodeType(), except for CDATASection and EntityReference nodes.
     DOM_nodeType() returns 4 and 5 respectively, whereas nodeType()
     returns 3, because they are considered text nodes.

Function wrappers for Perl builtin functions
     XQL function wrappers have been provided for most Perl builtin
     functions.  When using a Perl builtin function like "substr" in an
     XQL+ querry, an XQL function wrapper will be generated on the fly.
     The arguments to these functions may be regular XQL+ subqueries (that
     return one or more values) for a *query parameter* (see
     generateFunction for a definition.)  Most wrappers of Perl builtin
     functions have argument 0 for a query parameter, except for: chmod
     (parameter 1 is the query parameter), chown (2) and utime (2).  The
     following functions have no query parameter, which means that all
     parameters should be a single value: atan2, rand, srand, sprintf,
     rename, unlink, system.

     The function result is casted to the appropriate XQL primitive type
     (Number, Text or Boolean), or to an empty list if the result was
     undef.

XPath functions and methods
---------------------------

   The following functions were found in the XPath specification:

Function: concat (STRING, STRING, STRING*)
     The concat function returns the concatenation of its arguments.

Function: starts-with (STRING, STRING)
     The starts-with function returns true if the first argument string
     starts with the second argument string, and otherwise returns false.

Function: contains (STRING, STRING)
     The contains function returns true if the first argument string
     contains the second argument string, and otherwise returns false.

Function: substring-before (STRING, STRING)
     The substring-before function returns the substring of the first
     argument string that precedes the first occurrence of the second
     argument string in the first argument string, or the empty string if
     the first argument string does not contain the second argument
     string. For example,

          substring-before("1999/04/01","/") returns 1999.

Function: substring-after (STRING, STRING)
     The substring-after function returns the substring of the first
     argument string that follows the first occurrence of the second
     argument string in the first argument string, or the empty string if
     the first argument string does not contain the second argument
     string. For example,

          substring-after("1999/04/01","/") returns 04/01,

     and

          substring-after("1999/04/01","19") returns 99/04/01.

Function: substring (STRING, NUMBER [, NUMBER] )
     The substring function returns the substring of the first argument
     starting at the position specified in the second argument with length
     specified in the third argument. For example,

          substring("12345",2,3) returns "234".

     If the third argument is not specified, it returns the substring
     starting at the position specified in the second argument and
     continuing to the end of the string. For example,

          substring("12345",2) returns "2345".

     More precisely, each character in the string is considered to have a
     numeric position: the position of the first character is 1, the
     position of the second character is 2 and so on.

     NOTE: This differs from the substr method , in which the method
     treats the position of the first character as 0.

     The XPath spec says this about rounding, but that is not true in this
     implementation: *The returned substring contains those characters for
     which the position of the character is greater than or equal to the
     rounded value of the second argument and, if the third argument is
     specified, less than the sum of the rounded value of the second
     argument and the rounded value of the third argument; the comparisons
     and addition used for the above follow the standard IEEE 754 rules;
     rounding is done as if by a call to the round function.*

Method: string-length ( [ QUERY ] )
     The string-length returns the number of characters in the string.  If
     the argument is omitted, it defaults to the context node converted to
     a string, in other words the string-value of the context node.

     Note that the generated XQL wrapper for the Perl built-in substr does
     not allow the argument to be omitted.

Method: normalize-space ( [ QUERY ] )
     The normalize-space function returns the argument string with
     whitespace normalized by stripping leading and trailing whitespace
     and replacing sequences of whitespace characters by a single space.
     Whitespace characters are the same as those allowed by the S
     production in XML. If the argument is omitted, it defaults to the
     context node converted to a string, in other words the string-value
     of the context node.

Function: translate (STRING, STRING, STRING)
     The translate function returns the first argument string with
     occurrences of characters in the second argument string replaced by
     the character at the corresponding position in the third argument
     string. For example,

          translate("bar","abc","ABC") returns the string BAr.

     If there is a character in the second argument string with no
     character at a corresponding position in the third argument string
     (because the second argument string is longer than the third argument
     string), then occurrences of that character in the first argument
     string are removed. For example,

          translate("--aaa--","abc-","ABC") returns "AAA".

     If a character occurs more than once in the second argument string,
     then the first occurrence determines the replacement character. If
     the third argument string is longer than the second argument string,
     then excess characters are ignored.

     NOTE: The translate function is not a sufficient solution for case
     conversion in all languages. A future version may provide additional
     functions for case conversion.

     This function was implemented using tr///d.

Function: sum ( QUERY )
     The sum function returns the sum of the QUERY results, by converting
     the string values of each result to a number.

Function: floor (NUMBER)
     The floor function returns the largest (closest to positive infinity)
     number that is not greater than the argument and that is an integer.

Function: ceiling (NUMBER)
     The ceiling function returns the smallest (closest to negative
     infinity) number that is not less than the argument and that is an
     integer.

Function: round (NUMBER)
     The round function returns the number that is closest to the argument
     and that is an integer. If there are two such numbers, then the one
     that is closest to positive infinity is returned.

Implementation Details
======================

XQL Builtin Data Types
     The XQL engine uses the following object classes internally. Only
     Number, Boolean and Text are considered *primitive XQL types*:

        * XML::XQL::Number

          For integers and floating point numbers.

        * XML::XQL::Boolean

          For booleans, e.g returned by true() and false().

        * XML::XQL::Text

          For string values.

        * XML::XQL::Date

          For date, time and date/time values. E.g. returned by the date()
          function.

        * XML::XQL::Node

          Superclass of all XML node types. E.g. all subclasses of
          XML::DOM::Node subclass from this.

        * Perl list reference

          Lists of values are passed by reference (i.e. using []
          delimiters).  The empty list [] has a double meaning. It also
          means 'undef' in certain situations, e.g. when a function
          invocation or comparison failed.

Type casting in comparisons
     When two values are compared in an XML comparison (e.g. $eq$) the
     values are first casted to the same data type. Node values are first
     replaced by their value() (i.e. the XQL value() function is used,
     which returns a Text value by default, but may return any data type
     if the user so chooses.)  The resulting values are then casted to the
     type of the object with the highest xql_primType() value. They are as
     follows: Node (0), Text (1), Number (2), Boolean (3), Date (4), other
     data types (4 by default, but this may be overriden by the user.)

     E.g. if one value is a Text value and the other is a Number, the Text
     value is cast to a Number and the resulting low-level (Perl)
     comparison is (for $eq$):

          $number->xql_toString == $text->xql_toString

     If both were Text values, it would have been

          $text1->xql_toString eq $text2->xql_toString

     Note that the XQL spec is vague and even conflicting where it
     concerns type casting. This implementation resulted after talking to
     Joe Lapp, one of the spec writers.

Adding Data Types
     If you want to add your own data type, make sure it derives from
     XML::XQL::PrimitiveType and implements the necessary methods.

     I will add more stuff here to explain it all, but for now, look at
     the code for the primitive XQL types or the Date class (see
     XML/XQL/Date, in Date.pm.)

Document Order
     The XQL spec states that query results always return their values in
     *document order*, which means the order in which they appeared in the
     original XML document. Values extracted from Nodes (e.g. with
     value(), text(), rawText(), nodeName(), etc.) always have a pointer
     to the reference node (i.e. the Node from which the value was
     extracted.) These pointers are acknowledged when (intermediate)
     result lists are sorted. Currently, the only place where a result
     list is sorted is in a $union$ expression, which is the only place
     where the result list can be unordered.  (If you find that this is
     not true, let me know.)

     Non-node values that have no associated reference node, always end up
     at the end of the result list in the order that they were added.  The
     XQL spec states that the reference node for an XML Attribute is the
     Element to which it belongs, and that the order of values with the
     same reference node is undefined. This means that the order of an
     Element and its attributes would be undefined.  But since the
     XML::DOM module keeps track of the order of the attributes, the XQL
     engine does the same, and therefore, the attributes of an Element are
     sorted and appear after their parent Element in a sorted result list.

Constant Function Invocations
     If a function always returns the same value when given "constant"
     arguments, the function is considered to be "constant". A "constant"
     argument can be either an XQL primitive (Number, Boolean, Text) or a
     "constant" function invocation. E.g.

          date("12-03-1998")
          true()
          sin(0.3)
          length("abc")
          date(substr("12-03-1998 is the date", 0, 10))

     are constant, but not:

          length(book[2])

     Results of constant function invocations are cached and calculated
     only once for each query. See also the CONST parameter in
     defineFunction.  It is not necessary to wrap constant function
     invocations in a once() call.

     Constant XQL functions are: date, true, false and a lot of the XQL+
     wrappers for Perl builtin functions. Function wrappers for certain
     builtins are not made constant on purpose to force the invocation to
     be evaluated every time, e.g. 'mkdir("/user/enno/my_dir", "0644")'
     (although constant in appearance) may return different results for
     multiple invocations.  See %PerlFunc in Plus.pm for details.

Function: count ([QUERY])
     The count() function has no parameters in the XQL spec. In this
     implementation it will return the number of QUERY results when passed
     a QUERY parameter.

Method: text ([RECURSE])
     When expanding an Element node, the text() method adds the expanded
     text() value of sub-Elements. When RECURSE is set to 0 (default is
     1), it will not include sub-elements. This is useful e.g. when using
     the $match$ operator in a recursive context (using the // operator),
     so it won't return parent Elements when one of the children matches.

Method: rawText ([RECURSE])
     See text().

SEE ALSO
========

   See XML/XQL/Query, XML/XQL/DOM,
XML/XQL/Date,

   The Japanese version of this document can be found on-line at `http:'
in this node

   The XML/XQL/Tutorial, manual page. The Japanese
version can be found at `http:' in this node

   The XQL spec at `http:' in this node

   The Design of XQL at `http:' in this node

   The DOM Level 1 specification at `http:' in this node

   The XML spec (Extensible Markup Language 1.0) at `http:' in this node

   The XML/Parser, and XML/Parser/Expat,
manual pages.

AUTHOR
======

   Please send bugs, comments and suggestions to Enno Derksen
<`enno@att.com'>

Adds XQL support to XML::DOM nodes
**********************************

NAME
====

   XML::XQL::DOM - Adds XQL support to XML::DOM nodes

SYNOPSIS
========

     use XML::XQL;
     use XML::XQL::DOM;

     $parser = new XML::DOM::Parser;
     $doc = $parser->parsefile ("file.xml");

     # Return all elements with tagName='title' under the root element 'book'
     $query = new XML::XQL::Query (Expr => "book/title");
     @result = $query->solve ($doc);

     # Or (to save some typing)
     @result = XML::XQL::solve ("book/title", $doc);

     # Or (see XML::DOM::Node)
     @result = $doc->xql ("book/title");

DESCRIPTION
===========

   XML::XQL::DOM adds methods to XML/DOM, nodes to support
XQL queries on XML::DOM document structures.

   See XML/XQL, and XML/XQL/Query, for
more details.  See XML/DOM/Node, describes the *xql()*
method.

Adds an XQL::Node type for representing and comparing dates and times
*********************************************************************

NAME
====

   XML::XQL::Date - Adds an XQL::Node type for representing and comparing
dates and times

SYNOPSIS
========

     use XML::XQL;
     use XML::XQL::Date;

     my $query = new XML::XQL::Query (Expr => "doc//timestamp[. < date('12/31/1999')]");
     my @results = $query->solve ($doc);

DESCRIPTION
===========

   This package uses the Date/Manip, package to add an
XQL node type (called XML::XQL::Date) that can be used to represent dates
and times.  The Date::Manip package can parse almost any date or time
format imaginable.  (I tested it with Date::Manip 5.33 and I know for sure
that it doesn't work with 5.20 or lower.)

   It also adds the XQL date function which creates an XML::XQL::Date
object from a string. See XML/XQL/Tutorial, for a
description of the date() function.

   You can plug in your own Date type, if you don't want to use Date::Manip
for some reason. See XML/XQL, and the XML::XQL::Date
source file for more details.

Creates an XQL query evaluater from a XQL expression
****************************************************

NAME
====

   XML::XQL::Query - Creates an XQL query evaluater from a XQL expression

SYNOPSIS
========

     use XML::XQL;

     $parser = new XML::DOM::Parser;
     $doc = $parser->parsefile ("file.xml");

     # Return all elements with tagName='title' under the root element 'book'
     $query = new XML::XQL::Query (Expr => "book/title");
     @result = $query->solve ($doc);

     # Or (to save some typing)
     @result = XML::XQL::solve ("book/title", $doc);

DESCRIPTION
===========

   To perform XQL queries on an XML::DOM document (or, in the future, on
other XML storage structures), you first have to create an XML::XQL::Query
object and pass it a valid XQL query expression. You can then perform
queries on one or more documents by calling the solve() method.

XML::XQL::Query constructor
===========================

   Usage, e.g:

     $query = new XML::XQL::Query(
     	Expr => "book/author",
     	Func => [ myfunc => \&my_func,		# define 2 functions
     		  myfunc2 => \&my_func2 ],
     	FuncArgCount => [ myfunc2 => [2, -1] ], # myfunc2 has 2 or more args
     	AllowedOutSideSubquery => [ myfunc => 1 ],
     	ConstFunc => [ myfunc2 => 1],
     	CompareOper => [ mycmp => \&mycmp ],	# define comparison operator
     	q => "str");				# use str// as string delim

Expr => STRING
     The query expression to be evaluated.

NodeQuery => BOOLEAN
     If set to 1, the query is a *Node Query* as opposed to a *Full Query*
     (which is the default.)  A node query is a query that is only capable
     of returning Nodes.  A full query is capable of returning Node values
     and non-Node values.  Non-Node values include XML Primitives, element
     type names, namespace URI's, concatenated text nodes, and node type
     names. The distinction is significant because node queries may appear
     as XSL match and select patterns, while full queries have use in
     other applications.  The difference between the two forms of queries
     is trivial and exists only as constraints on the syntax of node
     queries.  Node queries may contain nested full queries.

Func => [ FUNCNAME => FUNCREF, ...]
     Defines one or more functions. FUNCNAME is the name as used in the
     query expression. FUNCREF can be either a function reference like
     \&my_func or an anonymous sub.  See also: defineFunction

Method => [ FUNCNAME => FUNCREF, ...]
     Defines one or more methods. FUNCNAME is the name as used in the query
     expression. FUNCREF can be either a function reference like \&my_func
     or an anonymous sub.  See also: defineMethod

FuncArgCount => [ FUNCNAME => ARGCOUNT, ...]
     Defines the number of arguments for one or more functions or methods.
     FUNCNAME is the name as used in the query expression.  See also:
     defineFunction and defineMethod

AllowedOutsideSubquery => [ FUNCNAME => BOOLEAN, ...]
     Defines whether the specified function or method is allowed outside
     subqueries. FUNCNAME is the name as used in the query expression.
     See also: defineFunction and defineMethod

ConstFunc => [ FUNCNAME => BOOLEAN, ...]
     Defines whether the function (not method!) is a "constant" function.
     FUNCNAME is the name as used in the query expression.  See `Constant
     Function Invocations' in this node for a definition of "constant" See
     also: defineFunction and defineMethod

CompareOper => [ OPERNAME => FUNCREF, ...]
     Defines the comparison operator with the specified OPERNAME, e.g. if
     OPERNAME is "contains", you can use "$contains$" in the query.  See
     also: defineComparisonOperators

q => TOKEN
     Defines the q// token. See also: defineTokenQ

qq => TOKEN
     Defines the qq// token. See also: defineTokenQQ

Error => FUNCREF
     Defines the function that is called when errors occur during parsing
     the query expression. The default function prints an error message to
     STDERR.

Debug => FLAGS
     Sets the debug level for the Yapp parser that parses the query
     expression.  Default value is 0 (don't print anything). The maximum
     value is 0x17, which prints a lot of stuff. See the Parse::Yapp
     manpage for the meaning of the individual bits.

Reserved hash keys
     Users may add their own (key, value) pairs to the Query constructor.
     Beware that the key 'Tree' is used internally.

XML::XQL::Query methods
=======================

solve (INPUT_LIST...)
     Note that solve takes a list of nodes which are assumed to be in
     document order and must belong to the same document. E.g:

          $query = new XML::XQL::Query (Expr => "doc//book");
          @result = $query->solve ($doc);
          @result2 = $query->solve ($node1, $node2, $node3);

   The following functions are also available at the query level, i.e.
when called on a Query object they only affect this Query and no others:

     defineFunction, defineMethod, defineComparisonOperators,
     defineTokenQ, defineTokenQQ

   See `Global functions|XML::XQL' in this node for details.  Another way
to define these features for a particular Query is by passing the
appropriate values to the XML::XQL::Query constructor.

SEE ALSO
========

   See XML/XQL, for general information about the XML::XQL
module

   See XML/XQL/Tutorial, which describes the XQL syntax

Describes the XQL query syntax
******************************

NAME
====

   XML::XQL::Tutorial - Describes the XQL query syntax

DESCRIPTION
===========

   This document describes basic the features of the XML Query Language
(XQL.)  A proposal for the XML Query Language (XQL) specification was
submitted to the XSL Working Group in September 1998.  The spec can be
found at `http:' in this node.  Since it is only a proposal at this point,
things may change, but it is very likely that the final version will be
close to the proposal.  Most of this document was copied straight from the
spec.

   See also the XML/XQL, man page.

INTRODUCTION
============

   XQL (XML Query Language) provides a natural extension to the XSL pattern
language. It builds upon the capabilities XSL provides for identifying
classes of nodes, by adding Boolean logic, filters, indexing into
collections of nodes, and more.

   XQL is designed specifically for XML documents.  It is a general
purpose query language, providing a single syntax that can be used for
queries, addressing, and patterns.  XQL is concise, simple, and powerful.

   XQL is designed to be used in many contexts. Although it is a superset
of XSL patterns, it is also applicable to providing links to nodes, for
searching repositories, and for many other applications.

   Note that the term XQL is a working term for the language described in
this proposal. It is not their intent that this term be used permanently.
Also, beware that another query language exists called XML-QL, which uses
a syntax very similar to SQL.

   The XML/XQL, module has added functionality to the XQL
spec, called *XQL+*.  To allow only XQL functionality as described in the
spec, use the XML::XQL::Strict module. Note that the XQL spec makes the
distinction between core XQL and XQL extensions. This implementation makes
no distinction and the Strict module, therefore, implements everything
described in the XQL spec.  See the XML/XQL, man page for
more information about the Strict module.  This tutorial will clearly
indicate when referring to XQL+.

XQL Patterns
============

   This section describes the core XQL notation. These features should be
part of every XQL implementation, and serve as the base level of
functionality for its use in different technologies.

   The basic syntax for XQL mimics the URI directory navigation syntax, but
instead of specifying navigation through a physical file structure, the
navigation is through elements in the XML tree.

   For example, the following URI means find the foo.jpg file within the
bar directory:

     bar/foo.jpg

   Similarly, in XQL, the following means find the collection of fuz
elements within baz elements:

     baz/fuz

   Throughout this document you will find numerous samples. They refer to
the data shown in the sample file at the end of this man page.

Context
=======

   A context is the set of nodes against which a query operates.  For the
entire query, which is passed to the XML/XQL/Query,
constructor through the Expr option, the context is the list of input nodes
that is passed to the query() method.

   XQL allows a query to select between using the current context as the
input context and using the 'root context' as the input context.  The
'root context' is a context containing only the root-most element of the
document. When using XML::DOM, this is the Document object.

   By default, a query uses the current context. A query prefixed with '/'
(forward slash) uses the root context. A query may optionally explicitly
state that it is using the current context by using the './' (dot, forward
slash) prefix. Both of these notations are analogous to the notations used
to navigate directories in a file system.

   The './' prefix is only required in one situation. A query may use the
'//' operator to indicate recursive descent. When this operator appears at
the beginning of the query, the initial '/' causes the recursive decent to
perform relative to the root of the document or repository. The prefix
'.//' allows a query to perform a recursive descent relative to the
current context.

Examples:
     Find all author elements within the current context. Since the period
     is really not used alone, this example forward-references other
     features:

          ./author

     Note that this is equivalent to:

          author

     Find the root element (bookstore) of this document:

          /bookstore

     Find all author elements anywhere within the current document:

          //author

     Find all books where the value of the style attribute on the book is
     equal to the value of the specialty attribute of the bookstore
     element at the root of the document:

          book[/bookstore/@specialty = @style]

Query Results
=============

   The collection returned by an XQL expression preserves document order,
hierarchy, and identity, to the extent that these are defined.  That is, a
collection of elements will always be returned in document order without
repeats. Note that the spec states that the order of attributes within an
element is undefined, but that this implementation does keep attributes in
document order. See the XML/XQL, man page for more details
regarding *Document Order*.

Collections - 'element' and '.'
===============================

   The collection of all elements with a certain tag name is expressed
using the tag name itself. This can be qualified by showing that the
elements are selected from the current context './', but the current
context is assumed and often need not be noted explicitly.

Examples:
     Find all first-name elements. These examples are equivalent:

          ./first-name

          first-name

     Find all unqualified book elements:

          book

     Find all first.name elements:

          first.name

Selecting children and descendants - '/' and '//'
=================================================

   The collection of elements of a certain type can be determined using
the path operators ('/' or '//'). These operators take as their arguments
a collection (left side) from which to query elements, and a collection
indicating which elements to select (right side). The child operator
('/')selects from immediate children of the left-side collection, while
the descendant operator ('//') selects from arbitrary descendants of the
left-side collection.  In effect, the '//' can be thought of as a
substitute for one or more levels of hierarchy. Note that the path
operators change the context as the query is performed. By stringing them
together users can 'drill down' into the document.

Examples:
     Find all first-name elements within an author element. Note that the
     author children of the current context are found, and then first-name
     children are found relative to the context of the author elements:

          author/first-name

     Find all title elements, one or more levels deep in the bookstore
     (arbitrary descendants):

          bookstore//title

     Note that this is different from the following query, which finds all
     title elements that are grandchildren of bookstore elements:

          bookstore/*/title

     Find emph elements anywhere inside book excerpts, anywhere inside the
     bookstore:

          bookstore//book/excerpt//emph

     Find all titles, one or more levels deep in the current context. Note
     that this situation is essentially the only one where the period
     notation is required:

          .//title

Collecting element children - '*'
=================================

   An element can be referenced without using its name by substituting the
'*' collection. The '*' collection returns all elements that are children
of the current context, regardless of their tag name.

Examples:
     Find all element children of author elements:

          author/*

     Find all last-names that are grand-children of books:

          book/*/last-name

     Find the grandchildren elements of the current context:

          */*

     Find all elements with specialty attributes. Note that this example
     uses subqueries, which are covered in Filters, and attributes, which
     are discussed in Finding an attribute:

          *[@specialty]

Finding an attribute - '@'
==========================

   Attribute names are preceded by the '@' symbol. XQL is designed to treat
attributes and sub-elements impartially, and capabilities are equivalent
between the two types wherever possible.

   Note: attributes cannot contain subelements. Thus, attributes cannot
have path operators applied to them in a query.  Such expressions will
result in a syntax error.  The XQL spec states that attributes are
inherently unordered and indices cannot be applied to them, but this
implementation allows it.

Examples:
     Find the style attribute of the current element context:

          @style

     Find the exchange attribute on price elements within the current
     context:

          price/@exchange

     The following example is not valid:

          price/@exchange/total

     Find all books with style attributes. Note that this example uses
     subqueries, which are covered in Filters:

          book[@style]

     Find the style attribute for all book elements:

          book/@style

XQL Literals
============

   XQL query expressions may contain literal values (i.e. constants.)
Numbers (integers and floats) are wrapped in XML::XQL::Number objects and
strings in XML::XQL::Text objects. Booleans (as returned by true() and
false()) are wrapped in XML::XQL::Boolean objects.

   Strings must be enclosed in single or double quotes. Since XQL does not
allow escaping of special characters, it's impossible to create a string
with both a single and a double quote in it. To remedy this, XQL+ has
added the q// and qq// string delimiters which behave just like they do in
Perl.

   For Numbers, exponential notation is not allowed. Use the XQL+ function
eval() to circumvent this problem. See XML/XQL, man page
for details.

   The empty list or undef is represented by [] (i.e. reference to empty
array) in this implementation.

Example
     Integer Numbers:

          234
          -456

     Floating point Numbers:

          1.23
          -0.99

     Strings:

          "some text with 'single' quotes"
          'text with "double" quotes'

     Not allowed:

          1.23E-4         (use eval("1.23E-4", "Number") in XQL+)

          "can't use \"double \"quotes"  (use q/can't use "double" quotes/ in XQL+)

Grouping - '()'
===============

   Parentheses can be used to group collection operators for clarity or
where the normal precedence is inadequate to express an operation.

Filters - '[]'
==============

   Constraints and branching can be applied to any collection by adding a
filter clause '[ ]' to the collection. The filter is analogous to the SQL
WHERE clause with ANY semantics. The filter contains a query within it,
called the subquery. The subquery evaluates to a Boolean, and is tested
for each element in the collection. Any elements in the collection failing
the subquery test are omitted from the result collection.

   For convenience, if a collection is placed within the filter, a Boolean
TRUE is generated if the collection contains any members, and a FALSE is
generated if the collection is empty. In essence, an expression such as
author/degree implies a collection-to-Boolean conversion function like the
following mythical 'there-exists-a' method.

     author[.there-exists-a(degree)]

   Note that any number of filters can appear at a given level of an
expression.  Empty filters are not allowed.

Examples:
     Find all books that contain at least one excerpt element:

          book[excerpt]

     Find all titles of books that contain at least one excerpt element:

          book[excerpt]/title

     Find all authors of books where the book contains at least one
     excerpt, and the author has at least one degree:

          book[excerpt]/author[degree]

     Find all books that have authors with at least one degree:

          book[author/degree]

     Find all books that have an excerpt and a title:

          book[excerpt][title]

Any and all semantics - '$any$' and '$all$'
-------------------------------------------

   Users can explicitly indicate whether to use any or all semantics
through the $any$ and $all$ keywords.

   $any$ flags that a condition will hold true if any item in a set meets
that condition. $all$ means that all elements in a set must meet the
condition for the condition to hold true.

   $any$ and $all$ are keywords that appear before a subquery expression
within a filter.

Examples:
     Find all author elements where one of the last names is Bob:

          author[last-name = 'Bob']

          author[$any$ last-name = 'Bob']

     Find all author elements where none of the last-name elements are Bob:

          author[$all$ last-name != 'Bob']

     Find all author elements where the first last name is Bob:

          author[last-name[0] = 'Bob']

Indexing into a collection - '[]' and '$to$'
============================================

   XQL makes it easy to find a specific node within a set of nodes.
Simply enclose the index ordinal within square brackets. The ordinal is 0
based.

   A range of elements can be returned. To do so, specify an expression
rather than a single value inside of the subscript operator (square
brackets).  Such expressions can be a comma separated list of any of the
following:

     n		Returns the nth element
     -n		Returns the element that is n-1 units from the last element.
     		E.g., -1 means the last element. -2 is the next to last element.
     m $to$ n	Returns elements m through n, inclusive

Examples:
     Find the first author element:

          author[0]

     Find the third author element that has a first-name:

          author[first-name][2]

     Note that indices are relative to the parent. In other words,
     consider the following data:

          <x>
            <y/>
            <y/>
          </x>
          <x>
            <y/>
            <y/>
          </x>

     The following expression will return the first y from each of the x's:

          x/y[0]

     The following will return the first y from the entire set of y's
     within x's:

          (x/y)[0]

     The following will return the first y from the first x:

          x[0]/y[0]

     Find the first and fourth author elements:

          author[0,3]

     Find the first through fourth author elements:

          author[0 $to$ 3]

     Find the first, the third through fifth, and the last author elements:

          author[0, 2 $to$ 4, -1]

     Find the last author element:

          author[-1]

Boolean Expressions
===================

   Boolean expressions can be used within subqueries. For example, one
could use Boolean expressions to find all nodes of a particular value, or
all nodes with nodes in particular ranges. Boolean expressions are of the
form ${op}$, where {op} may be any expression of the form {b|a} - that is,
the operator takes lvalue and rvalue arguments and returns a Boolean
result.

   Note that the XQL Extensions section defines additional Boolean
operations.

Boolean AND and OR - '$and$' and '$or$'
---------------------------------------

   $and$ and $or$ are used to perform Boolean ands and ors.

   The Boolean operators, in conjunction with grouping parentheses, can be
used to build very sophisticated logical expressions.

   Note that spaces are not significant and can be omitted, or included for
clarity as shown here.

Examples:
     Find all author elements that contain at least one degree and one
     award.

          author[degree $and$ award]

     Find all author elements that contain at least one degree or award
     and at least one publication.

          author[(degree $or$ award) $and$ publication]

Boolean NOT - '$not$'
---------------------

   $not$ is a Boolean operator that negates the value of an expression
within a subquery.

Examples:
     Find all author elements that contain at least one degree element and
     that contain no publication elements.

          author[degree $and$ $not$ publication]

     Find all author elements that contain publications elements but do
     not contain either degree elements or award elements.

          author[$not$ (degree $or$ award) $and$ publication]

Union and intersection - '$union$', '|' and '$intersect$'
=========================================================

   The $union$ operator (shortcut is '|') returns the combined set of
values from the query on the left and the query on the right. Duplicates
are filtered out.  The resulting list is sorted in document order.

   Note: because this is a union, the set returned may include 0 or more
elements of each element type in the list. To restrict the returned set to
nodes that contain at least one of each of the elements in the list, use a
filter, as discussed in Filters.

   The $intersect$ operator returns the set of elements in common between
two sets.

Examples:
     Find all first-names and last-names:

          first-name $union$ last-name

     Find all books and magazines from a bookstore:

          bookstore/(book | magazine)

     Find all books and all authors:

          book $union$ book/author

     Find the first-names, last-names, or degrees from authors within
     either books or magazines:

          (book $union$ magazine)/author/(first-name $union$ last-name $union$ degree)

     Find all books with author/first-name equal to 'Bob' and all
     magazines with price less than 10:

          book[author/first-name = 'Bob'] $union$ magazine[price $lt$ 10]

Equivalence - '$eq$', '=', '$ne$' and '!='
==========================================

   The '=' sign is used for equality; '!=' for inequality. Alternatively,
$eq$ and  $ne$ can be used for equality and inequality.

   Single or double quotes can be used for string delimiters in
expressions.  This makes it easier to construct and pass XQL from within
scripting languages.

   For comparing values of elements, the value() method is implied. That
is, last-name < 'foo' really means last-name!value() < 'foo'.

   Note that filters are always with respect to a context. That is, the
expression book[author] means for every book element that is found, see if
it has an author subelement. Likewise, book[author = 'Bob'] means for
every book element that is found, see if it has a subelement named author
whose value is 'Bob'. One can examine the value of the context as well, by
using the . (period). For example, book[. = 'Trenton'] means for every
book that is found, see if its value is 'Trenton'.

Examples:
     Find all author elements whose last name is Bob:

          author[last-name = 'Bob']

          author[last-name $eq$ 'Bob']

     Find all authors where the from attribute is not equal to 'Harvard':

          degree[@from != 'Harvard']

          degree[@from $ne$ 'Harvard']

     Find all authors where the last-name is the same as the
     /guest/last-name element:

          author[last-name = /guest/last-name]

     Find all authors whose text is 'Matthew Bob':

          author[. = 'Matthew Bob']

          author = 'Matthew Bob'

Comparison - '<', '<=', '>', '>=', '$lt', '$ilt$' etc.
------------------------------------------------------

   A set of binary comparison operators is available for comparing numbers
and strings and returning Boolean results.  $lt$, $le$, $gt$, $ge$ are
used for less than, less than or equal, greater than, or greater than or
equal. These same operators are also available in a case insensitive form:
$ieq$, $ine$, $ilt$, $ile$, $igt$, $ige$.

   <, <=, > and >= are allowed short cuts for $lt$, $le$, $gt$ and $ge$.

Examples:
     Find all author elements whose last name is bob and whose price is >
     50

          author[last-name = 'Bob' $and$ price $gt$ 50]

     Find all authors where the from attribute is not equal to 'Harvard':

          degree[@from != 'Harvard']

     Find all authors whose last name begins with 'M' or greater:

          author[last-name $ge$ 'M']

     Find all authors whose last name begins with 'M', 'm' or greater:

          author[last-name $ige$ 'M']

     Find the first three books:

          book[index() $le$ 2]

     Find all authors who have more than 10 publications:

          author[publications!count() $gt$ 10]

XQL+ Match operators - '$match$', '$no_match$', '=~' and '!~'
-------------------------------------------------------------

   XQL+ defines additional operators for pattern matching. The $match$
operator (shortcut is '=~') returns TRUE if the lvalue matches the pattern
described by the rvalue. The $no_match$ operator (shortcut is '!~')
returns FALSE if they match. Both lvalue and rvalue are first cast to
strings.

   The rvalue string should have the syntax of a Perl rvalue, that is the
delimiters should be included and modifiers are allowed. When using
delimiters other than slashes '/', the 'm' should be included. The rvalue
should be a string, so don't forget the quotes! (Or use the q// or qq//
delimiters in XQL+, see XML/XQL, man page.)

   Note that you can't use the Perl substitution operator s/// here. Try
using the XQL+ subst() function instead.

Examples:
     Find all authors whose name contains bob or Bob:

          author[first-name =~ '/[Bb]ob/']

     Find all book titles that don't contain 'Trenton' (case-insensitive):

          book[title !~ 'm!trenton!i']

Oher XQL+ comparison operators - '$isa', '$can$'
------------------------------------------------

   See the XML/XQL, man page for other operators available
in XQL+.

Comparisons and vectors
-----------------------

   The lvalue of a comparison can be a vector or a scalar. The rvalue of a
comparison must be a scalar or a value that can be cast at runtime to a
scalar.

   If the lvalue of a comparison is a set, then any (exists) semantics are
used for the comparison operators. That is, the result of a comparison is
true if any item in the set meets the condition.

Comparisons and literals
------------------------

   The spec states that the lvalue of an expression cannot be a literal.
That is, *'1' = a* is not allowed. This implementation allows it, but it's
not clear how useful that is.

Casting of literals during comparison
-------------------------------------

   Elements, attributes and other XML node types are casted to strings
(Text) by applying the value() method. The value() method calls the text()
method by default, but this behavior can be altered by the user, so the
value() method may return other XQL data types.

   When two values are compared, they are first casted to the same type.
See the XML/XQL, man page for details on casting.

   Note that the XQL spec is not very clear on how values should be casted
for comparison. Discussions with the authors of the XQL spec revealed that
there was some disagreement and their implementations differed on this
point.  This implementation is closest to that of Joe Lapp from
webMethods, Inc.

Methods - 'method()' or 'query!method()'
========================================

   XQL makes a distinction between functions and methods.  See the
XML/XQL, man page for details.

   XQL provides methods for advanced manipulation of collections. These
methods provide specialized collections of nodes (see Collection methods),
as well as information about sets and nodes.

   Methods are of the form *method(arglist)*

   Consider the query book[author]. It will find all books that have
authors.  Formally, we call the book corresponding to a particular author
the reference node for that author. That is, every author element that is
examined is an author for one of the book elements. (See the Annotated XQL
BNF Appendix for a much more thorough definition of reference node and
other terms. See also the XML::XQL man page.) Methods always apply to the
reference node.

   For example, the text() method returns the text contained within a node,
minus any structure. (That is, it is the concatenation of all text nodes
contained with an element and its descendants.) The following expression
will return all authors named 'Bob':

     author[text() = 'Bob']

   The following will return all authors containing a first-name child
whose text is 'Bob':

     author[first-name!text() = 'Bob']

   The following will return all authors containing a child named Bob:

     author[*!text() = 'Bob']

   Method names are case sensitive.  See the XML/XQL, man
page on how to define your own methods and functions.

Information methods
-------------------

   The following methods provide information about nodes in a collection.
These methods return strings or numbers, and may be used in conjunction
with comparison operators within subqueries.

Method: text()
     The text() method concatenates text of the descendents of a node,
     normalizing white space along the way. White space will be preserved
     for a node if the node has the xml:space attribute set to 'preserve',
     or if the nearest ancestor with the xml:space attribute has the
     attribute set to 'preserve'. When white space is normalized, it is
     normalized across the entire string. Spaces are used to separate the
     text between nodes.  When entity references are used in a document,
     spacing is not inserted around the entity refs when they are expanded.

     In this implementation, the method may receive an optional parameter
     to indicate whether the text() of Element nodes should include the
     text() of its Element descendants. See XML/XQL, man
     page for details.

     Examples:

     Find the authors whose last name is 'Bob':

          author[last-name!text() = 'Bob']

     Note this is equivalent to:

          author[last-name = 'Bob']

     Find the authors with value 'Matthew Bob':

          author[text() = 'Matthew Bob']

          author[. = 'Matthew Bob']

          author = 'Matthew Bob'

Method: rawText()
     The rawText() method is similar to the text() method, but it does not
     normalize whitespace.

     In this implementation, the method may receive an optional parameter
     to indicate whether the rawText() of Element nodes should include the
     rawText() of its Element descendants. See XML/XQL, man
     page for details.

Method: value()
     Returns a type cast version of the value of a node. If no data type is
     provided, returns the same as text().

    Shortcuts
          For the purposes of comparison, value( )is implied if omitted.
          In other words, when two items are compared, the comparison is
          between the value of the two items. Remember that in absence of
          type information, value() returns text().

          The following examples are equivalent:

               author[last-name!value() = 'Bob' $and$ first-name!value() = 'Joe']

               author[last-name = 'Bob' $and$ first-name = 'Joe']

               price[@intl!value() = 'canada']

               price[@intl = 'canada']

Method: nodeType()
     Returns a number to indicate the type of the node. The values were
     based on the node type values in the DOM:

          element		1
          attribute	2
          text		3
          entity		6	(not in XQL spec)
          PI		7
          comment		8
          document	9
          doc. fragment	10	(not in XQL spec)
          notation	11	(not in XQL spec)

     Note that in XQL, CDATASection nodes and EntityReference nodes also
     return 3, whereas in the DOM CDATASection returns 4 and
     EntityReference returns 5.  Use the XQL+ method DOM_nodeType() to get
     DOM node type values.  See the XML/DOM, man page for
     node type values of nodes not mentioned here.

Method: nodeTypeString
     Returns the name of the node type in lowercase or an empty string. The
     following node types are currently supported 1 (element), 2
     (attribute), 3 (text), 7 (processing_instruction), 8 (comment), 9
     (document)

Method: nodeName()
     Returns the tag name for Element nodes and the attribute name of
     attributes.

Collection index methods
------------------------

Method: index()
     Returns the index of the value within the search context (i.e. with
     the input list of the subquery.) This is not necessarily the same as
     the index of a node within its parent node. Note that the XQL spec
     doesn't explain it well.

    Examples:
          Find the first 3 degrees:

               degree[index() $lt$ 3]

          Note that it skips over other nodes that may exist between the
          degree elements.

          Consider the following data:

               <x>
                 <y/>
                 <y/>
               </x>
               <x>
                 <y/>
                 <y/>
               </x>

          The following expression will return the first y from each x:

               x/y[index() = 0]

          This could also be accomplished by (see Indexing into a
          Collection):

               x/y[0]

Method: end()
     The end() method returns true for the last element in the search
     context.  Again, the XQL spec does not explain it well.

    Examples:
          Find the last book:

               book[end()]

          Find the last author for each book:

               book/author[end()]

          Find the last author from the entire set of authors of books:

               (book/author)[end()]

Aggregate methods
-----------------

Method: count( [QUERY] )
     Returns the number of values inside the search context.  In XQL+,
     when the optional QUERY parameter is supplied, it returns the number
     of values returned by the QUERY.

Namespace methods
-----------------

   The following methods can be applied to a node to return namespace
information.

Method: baseName()
     Returns the local name portion of the node, excluding the prefix.
     Local names are defined only for element nodes and attribute nodes.
     The local name of an element node is the local portion of the node's
     element type name. The local name of an attribute node is the local
     portion of the node's attribute name. If a local name is not defined
     for the reference node, the method evaluates to the empty set.

Method: namespace()
     Returns the URI for the namespace of the node.  Namespace URIs are
     defined only for element nodes and attribute nodes.  The namespace
     URI of an element node is the namespace URI associated with the
     node's element type name. The namespace URI of an attribute node is
     the namespace URI associated with the node's attribute name. If a
     namespace URI is not defined for the reference node, the method
     evaluates to the empty set.

Method: prefix()
     Returns the prefix for the node. Namespace prefixes are defined only
     for element nodes and attribute nodes. The namespace prefix of an
     element node is the shortname for the namespace of the node's element
     type name.  The namespace prefix of an attribute node is the
     shortname for the namespace of the node's attribute name.  If a
     namespace prefix is not defined for the reference node, the method
     evaluates to the empty set.

     The spec states: A node's namespace prefix may be defined within the
     query expression, within the document under query, or within both the
     query expression and the document under query. If it is defined in
     both places the prefixes may not agree. In this case, the prefix
     assigned by the query expression takes precedence.  In this
     implementation you cannot define the namespace for a query, so this
     can never happen.

    Examples:
          Find all unqualified book elements. Note that this does not
          return my:book elements:

               book

          Find all book elements with the prefix 'my'. Note that this
          query does not return unqualified book elements:

               my:book

          Find all book elements with a 'my' prefix that have an author
          subelement:

               my:book[author]

          Find all book elements with a 'my' prefix that have an author
          subelement with a my prefix:

               my:book[my:author]

          Find all elements with a prefix of 'my':

               my:*

          Find all book elements from any namespace:

               *:book

          Find any element from any namespace:

               *

          Find the style attribute with a 'my' prefix within a book
          element:

               book/@my:style

     All attributes of an element can be returned using @*.  This is
     potentially useful for applications that treat attributes as fields
     in a record.

    Examples:
          Find all attributes of the current element context:

               @*

          Find style attributes from any namespace:

               @*:style

          Find all attributes from the 'my' namespace, including
          unqualified attributes on elements from the 'my' namespace:

               @my:*

Functions
=========

   This section defines the functions of XQL. The spec states that: XQL
defines two kinds of functions: collection functions and pure functions.
Collection functions use the search context of the Invocation instance,
while pure functions ignore the search context, except to evaluate the
function's parameters. A collection function evaluates to a subset of the
search context, and a pure function evaluates to either a constant value
or to a value that depends only on the function's parameters.

   Don't worry if you don't get it. Just use them!

Collection functions
--------------------

   The collection functions provide access to the various types of nodes
in a document. Any of these collections can be constrained and indexed.
The collections return the set of children of the reference node meeting
the particular restriction.

Function: textNode()                   The collection of text nodes.
Function: comment()
     The collection of comment nodes.

Function: pi()
     The collection of processing instruction nodes.

Function: element( [NAME] )
     The collection of all element nodes. If the optional text parameter
     is provided, it only returns element children matching that
     particular name.

Function: attribute( [NAME] )
     The collection of all attribute nodes. If the optional text parameter
     is provided, it only returns attributes matching that particular name.

Function: node()
     The collection of all non-attribute nodes.

    Examples:
          Find the second text node in each p element in the current
          context:

               p/textNode()[1]

          Find the second comment anywhere in the document. See Context
          for details on setting the context to the document root:

               //comment()[1]

Other XQL Functions
-------------------

Function: ancestor(QUERY)
     Finds the nearest ancestor matching the provided query. It returns
     either a single element result or an empty set [].  Note that this
     node is never the reference node itself.

    Examples:
          Find the nearest book ancestor of the current element:

               ancestor(book)

          Find the nearest ancestor author element that is contained in a
          book element:

               ancestor(book/author)

Function: id(NAME)
     Pure function that evaluates to a set. The set contains an element
     node that has an 'id' attribute whose value is identical to the
     string that the Text parameter quotes. The element node may appear
     anywhere within the document under query. If more than one element
     node meets these criteria, the function evaluates to a set that
     contains the first node appearing in a document ordering of the nodes.

Function: true() and false()
     Pure functions that each evaluate to a Boolean. "true()" evaluates to
     'true', and "false()" evaluates to 'false'. These functions are
     useful in expressions that are constructed using entity references or
     variable substitution, since they may replace an expression found in
     an instance of Subquery without violating the syntax required by the
     instance of Subquery.  They return an object of type
     XML::XQL::Boolean.

Function: date(QUERY)
     "date" is a pure function that typecasts the value of its parameter
     to a set of dates. If the parameter matches a single string, the
     value of the function is a set containing a single date. If the
     parameter matches a QUERY, the value of the function is a set of
     dates, where the set contains one date for each member of the set to
     which the parameter evaluates.

     XQL does not define the representation of the date value, nor does it
     define how the function translates parameter values into dates.  This
     implementation uses the Date::Manip module to parse dates, which
     accepts almost any imaginable format. See XML/XQL, to
     plug in your own Date implementation.

     Include the XML/XQL/Date, package to add the XQL
     date type and the date() function, like this:

          use XML::XQL::Date;

Perl builtin functions and other XQL+ functions
     XQL+ provides XQL function wrappers for most Perl builtin functions.
     It also provides other cool functions like subst(), map(), and eval()
     that allow you to modify documents and embed perl code.  If this is
     still not enough, you can add your own function and methods.  See
     XML/XQL, man page for details.

Sequence Operators - ';' and ';;'
=================================

   The whitepaper 'The Design of XQL' by Jonathan Robie, which can be found
at `http:' in this node describes the sequence operators ';;' (precedes)
and ';' (immediately precedes.) Although these operators are not included
in the XQL spec, I thought I'd add them anyway.

Immediately Precedes - ';'
--------------------------

Example:
     With the following input:

          <TABLE>
           <ROWS>
            <TR>
             <TD>Shady Grove</TD>
             <TD>Aeolian</TD>
            </TR>
            <TR>
             <TD>Over the River, Charlie</TD>
             <TD>Dorian</TD>
            </TR>
           </ROWS>
          </TABLE>

     Find the TD node that contains "Shady Grove" and the TD node that
     immediately follows it:

          //(TD="Shady Grove" ; TD)

   Note that in XML::DOM there is actually a text node with whitespace
between the two TD nodes, but those are ignored by this operator, unless
the text node has 'xml:space' set to 'preserve'. See ??? for details.

Precedes - ';;'
---------------

Example:
     With the following input (from Hamlet):

          <SPEECH>
           <SPEAKER>MARCELLUS</SPEAKER>
           <LINE>Tis gone!</LINE>
           <STAGEDIR>Exit Ghost</STAGEDIR>
           <LINE>We do it wrong, being so majestical,</LINE>
           <LINE>To offer it the show of violence;</LINE>
           <LINE>For it is, as the air, invulnerable,</LINE>
           <LINE>And our vain blows malicious mockery.</LINE>
          </SPEECH>

     Return the STAGEDIR and all the LINEs that follow it:

          SPEECH//( STAGEDIR ;; LINE )

     Suppose an actor playing the ghost wants to know when to exit; that
     is, he wants to know who says what line just before he is supposed to
     exit. The line immediately precedes the stagedir, but the speaker may
     occur at any time before the line.  In this query, we will use the
     "precedes" operator (";;") to identify a speaker that precedes the
     line somewhere within a speech. Our ghost can find the required
     information with the following query, which selects the speaker, the
     line, and the stagedir:

          SPEECH//( SPEAKER ;; LINE ; STAGEDIR="Exit Ghost")

Operator Precedence
===================

   The following table lists operators in precedence order, highest
precedence first, where operators of a given row have the same precedence.
The table also lists the associated productions:

     Production	Operator(s)
     ----------	-----------
     Grouping	( )
     Filter		[ ]
     Subscript	[ ]
     Bang		!
     Path		/ //
     Match		$match$ $no_match$ =~ !~ (XQL+ only)
     Comparison	= != < <= > >= $eq$ $ne$ $lt$ $le$ $gt$
     		$ge$ $ieq$ $ine$ $ilt$ $ile$ $igt$ $ige$
     Intersection	$intersect$
     Union		$union$ |
     Negation	$not$
     Conjunction	$and$
     Disjunction	$or$
     Sequence	; ;;

Sample XML Document - bookstore.xml
===================================

   This file is also stored in samples/bookstore.xml that comes with the
XML::XQL distribution.

     <?xml version='1.0'?>
     <!-- This file represents a fragment of a book store inventory database -->
     <bookstore specialty='novel'>
       <book style='autobiography'>
         <title>Seven Years in Trenton</title>
         <author>
           <first-name>Joe</first-name>
           <last-name>Bob</last-name>
           <award>Trenton Literary Review Honorable Mention</award>
         </author>
         <price>12</price>
       </book>
       <book style='textbook'>
         <title>History of Trenton</title>
         <author>
           <first-name>Mary</first-name>
           <last-name>Bob</last-name>
           <publication>
             Selected Short Stories of
             <first-name>Mary</first-name> <last-name>Bob</last-name>
           </publication>
         </author>
         <price>55</price>
       </book>
       <magazine style='glossy' frequency='monthly'>
         <title>Tracking Trenton</title>
         <price>2.50</price>
         <subscription price='24' per='year'/>
       </magazine>
       <book style='novel' id='myfave'>
         <title>Trenton Today, Trenton Tomorrow</title>
         <author>
           <first-name>Toni</first-name>
           <last-name>Bob</last-name>
           <degree from='Trenton U'>B.A.</degree>
           <degree from='Harvard'>Ph.D.</degree>
           <award>Pulizer</award>
           <publication>Still in Trenton</publication>
           <publication>Trenton Forever</publication>
         </author>
         <price intl='canada' exchange='0.7'>6.50</price>
         <excerpt>
           <p>It was a dark and stormy night.</p>
           <p>But then all nights in Trenton seem dark and
           stormy to someone who has gone through what
           <emph>I</emph> have.</p>
           <definition-list>
             <term>Trenton</term>
             <definition>misery</definition>
           </definition-list>
         </excerpt>
       </book>
       <my:book style='leather' price='29.50' xmlns:my='http://www.placeholder-name-here.com/schema/'>
         <my:title>Who's Who in Trenton</my:title>
         <my:author>Robert Bob</my:author>
       </my:book>
     </bookstore>

SEE ALSO
========

   The Japanese version of this document can be found on-line at `http:'
in this node

   See XML/XQL, XML/XQL/Date,
XML/XQL/Query, and XML/XQL/DOM,

A perl module for processing XSLT
*********************************

NAME
====

   XML::XSLT - A perl module for processing XSLT

   __my_tag_compression__( $tag, $elem )

   A function for DOM::XML::setTagCompression to determine the style for
printing of empty tags and empty container tags.

   XML::XSLT implements an XHTML-friendly style.

   Allow tag to be preceded by a namespace: ([\w\.]+\:){0,1}

     <br> -> <br />

     or

     <myns:hr> -> <myns:hr />

   Empty tag list obtained from:

     http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd

   According to "Appendix C. HTML Compatibility Guidelines",   C.3 Element
Minimization and Empty Element Content

     Given an empty instance of an element whose content model is not EMPTY
     (for example, an empty title or paragraph) do not use the minimized form
     (e.g. use <p> </p> and not <p />).

   However, the <p> tag is processed like an empty tag here!

   Tags allowed:

     base meta link hr br param img area input col

   Special Case: p (even though it violates C.3)

   The tags are matched in order of expected common occurence.

SYNOPSIS
========

     use XML::XSLT;

     my $xslt = XML::XSLT->new ($xsl, warnings => 1);

     $xslt->transform ($xmlfile)
     print $xslt->asString

     $xslt->dispose ();

DESCRIPTION
===========

   This module implements the W3C's XSLT specification. The goal is full
implementation of this spec, but we have not yet achieved that. However,
it already works well.  See `XML::XSLT Commands' in this node for the
current status of each command.

   XML::XSLT makes use of XML::DOM and LWP::Simple, while XML::DOM uses
XML::Parser.  Therefore XML::Parser, XML::DOM and LWP::Simple have to be
installed properly for XML::XSLT to run.

Specifying Sources
==================

   The stylesheets and the documents may be passed as filenames, file
handles regular strings, string references or DOM-trees.  Functions that
require sources (e.g. new), will accept either a named parameter or simply
the argument.

   Either of the following are allowed:

     my $xslt = XML::XSLT->new($xsl);
     my $xslt = XML::XSLT->new(Source => $xsl);

   In documentation, the named parameter `Source' is always shown, but it
is never required.

METHODS
=======

new(Source => $xml [, %args])
-----------------------------

   Returns a new XSLT parser object.  Valid flags are:

DOMparser_args
     Hashref of arguments to pass to the XML::DOM::Parser object's parse
     method.

variables
     Hashref of variables and their values for the stylesheet.

base
     Base of URL for file inclusion.

debug
     Turn on debugging messages.

warnings
     Turn on warning messages.

indent
     Starting amount of indention for debug messages.  Defaults to 0.

indent_incr
     Amount to indent each level of debug message.  Defaults to 1.

open_xml(Source => $xml [, %args])
----------------------------------

   Gives the XSLT object new XML to process.  Returns an XML::DOM object
corresponding to the XML.

base
     The base URL to use for opening documents.

parser_args
     Arguments to pase to the parser.

open_xsl(Source => $xml, [, %args])
-----------------------------------

   Gives the XSLT object a new stylesheet to use in processing XML.
Returns an XML::DOM object corresponding to the stylesheet.  Any arguments
present are passed to the XML::DOM::Parser.

base
     The base URL to use for opening documents.

parser_args
     Arguments to pase to the parser.

process(%variables)
-------------------

   Processes the previously loaded XML through the stylesheet using the
variables set in the argument.

transform(Source => $xml [, %args])
-----------------------------------

   Processes the given XML through the stylesheet.  Returns an XML::DOM
object corresponding to the transformed XML.  Any arguments present are
passed to the XML::DOM::Parser.

serve(Source => $xml [, %args])
-------------------------------

   Processes the given XML through the stylesheet.  Returns a string
containg the result.  Example:

     use XML::XSLT qw(serve);

     $xslt = XML::XSLT->new($xsl);
     print $xslt->serve $xml;

http_headers
     If true, then prepends the appropriate HTTP headers (e.g.
     Content-Type, Content-Length);

     Defaults to true.

xml_declaration
     If true, then the result contains the appropriate <?xml?> header.

     Defaults to true.

xml_version
     The version of the XML.

     Defaults to 1.0.

doctype
     The type of DOCTYPE this document is.  Defaults to SYSTEM.

toString
--------

   Returns the result of transforming the XML with the stylesheet as a
string.

to_dom
------

   Returns the result of transforming the XML with the stylesheet as an
XML::DOM object.

media_type
----------

   Returns the media type (aka mime type) of the object.

dispose
-------

   Executes the dispose method on each XML::DOM object.

XML::XSLT Commands
==================

xsl:apply-imports		no
---------------------

   Not supported yet.

xsl:apply-templates		limited
----------------------------

   Attribute 'select' is supported to the same extent as xsl:value-of
supports path selections.

   Not supported yet: - attribute 'mode' - xsl:sort and xsl:with-param in
content

xsl:attribute			partially
-------------------------

   Adds an attribute named to the value of the attribute 'name' and as
value the stringified content-template.

   Not supported yet: - attribute 'namespace'

xsl:attribute-set		no
---------------------

   Not supported yet.

xsl:call-template		yes
----------------------

   Takes attribute 'name' which selects xsl:template's by name.

   Weak support: - xsl:with-param (select attrib not supported)

   Not supported yet: - xsl:sort

xsl:choose			yes
----------------

   Tests sequentially all xsl:whens until one succeeds or until an
xsl:otherwise is found. Limited test support, see xsl:when

xsl:comment			yes
-----------------

   Supported.

xsl:copy				partially
---------------------

   Not supported yet: - attribute 'use-attribute-sets'

xsl:copy-of			limited
---------------------

   Attribute 'select' functions as well as with xsl:value-of

xsl:decimal-format		no
----------------------

   Not supported yet.

xsl:element			yes
-----------------

xsl:fallback			no
-----------------

   Not supported yet.

xsl:for-each			limited
----------------------

   Attribute 'select' functions as well as with xsl:value-of

   Not supported yet: - xsl:sort in content

xsl:if				limited
-----------------

   Identical to xsl:when, but outside xsl:choose context.

xsl:import			no
---------------

   Not supported yet.

xsl:include			yes
-----------------

   Takes attribute href, which can be relative-local, absolute-local as
well as an URL (preceded by identifier http:).

xsl:key				no
-------------

   Not supported yet.

xsl:message			no
----------------

   Not supported yet.

xsl:namespace-alias		no
-----------------------

   Not supported yet.

xsl:number			no
---------------

   Not supported yet.

xsl:otherwise			yes
-------------------

   Supported.

xsl:output			limited
--------------------

   Only the initial xsl:output element is used.  The "text" output method
is not supported, but shouldn't be difficult to implement.  Only the
"doctype-public", "doctype-system", "omit-xml-declaration", "method", and
"encoding" attributes have any support.

xsl:param			experimental
------------------------

   Synonym for xsl:variable (currently). See xsl:variable for support.

xsl:preserve-space		no
----------------------

   Not supported yet. Whitespace is always preserved.

xsl:processing-instruction	yes
------------------------------

   Supported.

xsl:sort				no
--------------

   Not supported yet.

xsl:strip-space			no
--------------------

   Not supported yet. No whitespace is stripped.

xsl:stylesheet			limited
------------------------

   Minor namespace support: other namespace than 'xsl:' for xsl-commands
is allowed if xmlns-attribute is present. xmlns URL is verified.  Other
attributes are ignored.

xsl:template			limited
----------------------

   Attribute 'name' and 'match' are supported to minor extend.  ('name'
must match exactly and 'match' must match with full path or no path)

   Not supported yet: - attributes 'priority' and 'mode'

xsl:text				yes
---------------

   Supported.

xsl:transform			limited
-----------------------

   Synonym for xsl:stylesheet

xsl:value-of			limited
----------------------

   Inserts attribute or element values. Limited support:

   <xsl:value-of select="."/>

   <xsl:value-of select="/root-elem"/>

   <xsl:value-of select="elem"/>

   <xsl:value-of select="//elem"/>

   <xsl:value-of select="elem[n]"/>

   <xsl:value-of select="//elem[n]"/>

   <xsl:value-of select="@attr"/>

   <xsl:value-of select="text()"/>

   <xsl:value-of select="processing-instruction()"/>

   <xsl:value-of select="comment()"/>

   and combinations of these.

   Not supported yet: - attribute 'disable-output-escaping'

xsl:variable			experimental
---------------------------

   Very limited. It should be possible to define a variable and use it with
&lt;xsl:value select="$varname" /&gt; within the same template.

xsl:when				limited
-------------------

   Only inside xsl:choose. Limited test support:

   <xsl:when test="@attr='value'">

   <xsl:when test="elem='value'">

   <xsl:when test="path/[@attr='value']">

   <xsl:when test="path/[elem='value']">

   <xsl:when test="path">

   path is supported to the same extend as with xsl:value-of

xsl:with-param			experimental
-----------------------------

   It is currently not functioning. (or is it?)

SUPPORT
=======

   General information, bug reporting tools, the latest version, mailing
lists, etc. can be found at the XML::XSLT homepage:

     http://xmlxslt.sourceforge.net/

DEPRECATIONS
============

   Methods and interfaces from previous versions that are not documented
in this version are deprecated.  Each of these deprecations can still be
used but will produce a warning when the deprecation is first used.  You
can use the old interfaces without warnings by passing new() the flag
`use_deprecated'.  Example:

     $parser = XML::XSLT->new($xsl, "FILE",
                              use_deprecated => 1);

   The deprecations will disappear by the time a 1.0 release is made.

BUGS
====

   Yes.

HISTORY
=======

   Geert Josten and Egon Willighagen developed and maintained XML::XSLT up
to version 0.22.  At that point, Mark Hershberger started moving the
project to Sourceforge and began working on it with Bron Gondwana.

LICENCE
=======

   Copyright (c) 1999 Geert Josten & Egon Willighagen. All Rights
Reserverd.  This module is free software, and may be distributed under the
same terms and conditions as Perl.

AUTHORS
=======

   Geert Josten <gjosten@sci.kun.nl>, Egon Willighagen <egonw@sci.kun.nl>,
Mark A. Hershberger <mah@everybody.org> Bron Gondwana <perlcode@brong.net>,

SEE ALSO
========

   See XML/DOM, LWP/Simple,
XML/Parser,

Module for doing stream based XML queries
*****************************************

NAME
====

   XML::miniXQL - Module for doing stream based XML queries

SYNOPSIS
========

     use XML::miniXQL;

     my $results = XML::miniXQL::queryXML({Style => 'Hash'}, $xml, @searches);

DESCRIPTION
===========

   This module provides a simplistic XQL like search engine for XML files.
It only supports a subset of XQL, because it does all it's searching on
streams, not on the document as a whole (unlike XML::XQL). For this
reason, only ancestor relationships are supported, not sibling or child
relationships. XML::miniXQL also doesn't return nodes, it only returns the
value (text) found as the result of the query. As a result, you can't use
this module for node manipulation, however it's faster than XML::XQL, so
it can be used on a web backend or some such environment. Xmerge is
provided as an example of usage.

   The queries are passed in as an array of queries, and the results
passed out as either a simple tuple list (each alternate value is either
the query or the result respectively), or as a hash with the values being
an array. See xmerge.pl as an example of the Hash style.  The List style
is the default.

AUTHOR
======

   Matt Sergeant matt@sergeant.org

SEE ALSO
========

   perl(1).

A module for converting NITF to HTML.
*************************************

NAME
====

   XMLNews::HTMLTemplate - A module for converting NITF to HTML.

SYNOPSIS
========

     use XMLNews::HTMLTemplate;

     my $template = new XMLNews::HTMLTemplate();
     $template->readTemplate("mytemplate.html");

     $template->applyTemplate("output.html", "story.xml", "story.rdf");

DESCRIPTION
===========

   NOTE: this module requires the XML::Parser and XMLNews::Meta modules.

   WARNING: this module is not thread-safe or re-entrant.

   The XMLNews::HTMLTemplate module provides a simple mechanism for
creating HTML pages from XML/NITF news stories and/or XML/RDF metadata
files based on a user-supplied template file.  The template is a simple
HTML file (SGML or XML flavour) using special template commands, which the
user includes as processing instructions, as in the following example:

     <h1><?XNews insert headline?></h1>

   To create an HTML page, you must first create an empty HTMLTemplate
object:

     my $template = new XMLNews::HTMLTemplate();

   Next, you load the HTML template into the object:

     $template->readTemplate("mytemplate.html");

   Now, you can apply the same compiled template object repeatedly to
different XML/NITF and/or XML/RDF documents to generate HTML pages:

     $template->applyTemplate("outfile.html", "newsstory.xml", "newsstory.rdf");

   In this example, the module will read the XML/NITF news story in
newstory.xml and the XML/RDF metadata in newstory.rdf, and write an HTML
page at outfile.html.

METHODS
=======

new ()
     Construct a new, empty instance of an XMLNews::HTMLTemplate object:

          my $template = new XMLNews::HTMLTemplate();

readTemplate(TEMPLATE)
     Compile a template file into the current object, discarding any
     existing compiled template:

          $template->readTemplate("news-template.htm");

     The TEMPLATE argument may be either a string containing a file name or
     an IO::Handle object.

     You must compile a template before you can use it, but once you have
     compiled the template, you may use it to create many different HTML
     pages.

applyTemplate(OUT_FILE, NITF_FILE, RDF_FILE)
     Apply the compiled template to an NITF-format news story and/or and
     RDF-format metadata file, filling in the fields in the template
     commands using the properties found in these files:

          $template->applyTemplate("story999.html", "story999.xml", "story999.rdf");

     The three arguments may be either strings containing file names or
     IO::Handle objects.  If the file specified by OUT_FILE already exists,
     this method will overwrite its contents.

     Either or both of the NITF_FILE or the RDF_FILE parameters may be
     omitted if desired.

HTML TEMPLATE FORMAT
====================

   An XMLNews template file is an HTML file containing special processing
instructions, beginning with "<?XNews " and ending with ">" or "?>".
Following the word "XNews", each processing instruction contains
whitespace and a command word, followed optionally by command parameters,
as in the following example:

     <?XNews insert headline?>

   Typically, the template would include this processing instruction
within an HTML element:

     <h1><?XNews insert headline?></h1>

   All processing instructions beginning with characters other than
"XNews" will be ignored and passed through as-is (they may be used for
other sorts of processing).

Template Commands
-----------------

   Any of the following six command words may follow the word "XNews" in a
processing instruction (all commands are case-sensitive):

namespace PREFIX=URI
     Declare a prefix representing a namespace:

          <?XNews namespace xn=http://www.xmlnews.org/namespaces/meta#?>

     Once the prefix is declared, you can use it to point to properties in
     the RDF file:

          <?XNews insert xn:person?>

     Note that it is the namespace URIs rather than the prefixes that are
     matched against RDF; the following would work identically with the
     same RDF file:

          <?XNews namespace aBcDe=http://www.xmlnews.org/namespaces/meta#?>
          <?XNews insert aBcDe:person?>

     All namespace declarations have global scope from the point of
     declaration forward; it is usually best to include all of the
     declarations at the top of the template.

insert PROPERTY
     Insert the value of PROPERTY at this point in the generated document:

          <?XNews insert dateline?>

     If there is more than one value available for the property, all of the
     values will be inserted in random order, separated by spaces, unless
     this processing instruction occurs within a "foreach" block (see
     below).

if PROPERTY
     Begin a conditional statement:

          <?XNews if byline?>
           <h2><?XNews insert byline?></h2>
          <?XNews end?>

     Everything between this processing instruction and the matching "end"
     instruction will be included only if [property] has a non-null value.

     "if" commands may be nested.

else
     Specify the default action for when an "if" command fails:

          <?XNews if date?>
           <p>Date: <?XNews insert date?></p>
          <?XNews else?>
           <p>Undated.</p>
          <?XNews end?>

foreach PROPERTY
     Iterate over multiple values for a property:

          <?XNews foreach http://www.inews.org/props/CompanyCode?>
          <p>Ticker: <?XNews insert http://www.inews.org/props/CompanyCode?></p>
          <?XNews end?>

     These instructions will create a separate <p> element for every
     CompanyCode (ticker) value available.

end
     Terminate an "if" or "foreach" statement:

          <?XNews if dateline?>
          <p>Dateline: <?XNews insert dateline?></p>
          <?XNews end?>

Property Names
--------------

   Property names consist of two parts: a namespace and a base name.
Properties derived from the NITF document have null namespace parts;
properties derived from the RDF metadata have non-null namespace parts.
To specify a property with a non-null namespace part, you must first
declare a namespace prefix, and then include the prefix before the
property name separated with a colon:

     <?XNews namespace xn=http://www.xmlnews.org/namespaces/meta#?>

     <?XNews insert xn:companyCode?>

   These commands insert the value of the property "companyCode" in the
http://www.xmlnews.org/namespaces/meta# namespace, as found in the RDF
metadata file.  You may access any property specified in the news story's
RDF metadata file in this way (such as ticker symbols, dates, and the
language of the resource).

   In addition to the metadata properties in the RDF file, there are nine
special pseudo-properties that have a NULL namespace (most of these
duplicate properties in the RDF, but their values are also given in the
news story):

headline
          The text of the story's headline, if any.

subheadline
          The text of the story's subheadline(s), if any.  There may be more
          than one value for this property, so it is best to include it in a
          "foreach" block.

byline
          The text of the story's byline(s), if any.  There may be more than
          one value for this property, so it is best to include it in a
          "foreach" block.

distributor
          The text of the distributor's name, if any.

dateline
          The text of the story's dateline, if any.

series.name
          The name of the series to which this story belongs, if any.

series.part
          The position of this story in a series, if any.

series.totalpart
          The total number of stories in this series, if any.

body
          HTML markup for the body of the story, divided into paragraphs.

Sample Template
---------------

   Here is a simple sample template for a news story (using XML/HTML
syntax); it does not use any RDF properties:

     <?xml version="1.0"?>

     <html>
     <head>
     <title>News Story: <?XNews insert headline?></title>
     </head>
     <body>
     <h1><?XNews insert headline?></h1>

     <?XNews foreach subheadline?>
     <h2><?XNews insert subheadline?></h2>
     <?XNews end?>

     <?XNews foreach byline?>
     <p><em><?XNews insert byline?></em></p>
     <?XNews end?>

     <p>(Dateline: <?XNews insert dateline?>)</p>

     <?XNews insert body?>

     </body>
     </html>

CONFORMANCE NOTE
================

   The processing instruction target is "XNews" rather than XMLNews so
that template files can be well-formed XML if desired (XML reserves all
processing-instruction targets beginning with [xX][mM][lL]).

   Given the wide variations in common HTML usage, this module uses
pattern matching on the HTML templates rather than trying to parse them as
SGML or XML documents.  As a result, it will recognise template commands
even within comments and attribute values, places where they are not
properly recognised in SGML or XML.

AUTHOR
======

   This module was originally written by David Megginson
(david@megginson.com).

A module for reading and writing XMLNews metadata files.
********************************************************

NAME
====

   XMLNews::Meta - A module for reading and writing XMLNews metadata files.

SYNOPSIS
========

     use XMLNews::Meta;

     my $namespace = "http://www.xmlnews.org/namespaces/meta#";

     # Create a Meta object.
       my $meta = new XMLNews::Meta();

     # Read in the metadata file.
       $meta->importRDF("data.rdf");

     # Look up a singleton value.
       my $expireTime = $meta->getValue($namespace, "expireTime");

     # Add a new value to a property.
       $meta->addValue($namespace, "companyCode", "WAVO");

     # Write the metadata back out.
       $meta->exportRDF("data.rdf");

DESCRIPTION
===========

   NOTE: This module requires the XML::Parser module, version 2.19 or
higher.

   WARNING: This module is not re-entrant or thread-safe due to the use of
static variables while importing XML.

   The XMLNews::Meta module handles the import, export, and programmatic
manipulation of metadata for XMLNews resources.  You can read or write a
metadata file using a single method call, and can easily add or remove
values.

   Traditionally, resource files consist of simple pairs of the form

     NAME = VALUE

   XMLNews metadata, which is based on the W3C's Resource Description
Format (RDF), allows richer metadata in two ways:

  1. Property names are partitioned into namespaces, so that two different
     providers can use the same property name without fear of collision (a
     namespaces is simply a URI (URL or URN); following RDF practice, the
     URI should end with the fragment separator "#".  To look up a
     property, you always need to use both the namespace and the property
     name:

          $xn_ns = "http://www.xmlnews.org/namespaces/meta#";

          # Use getValue only for
          # singleton values!!!
            $title = $meta->getValue($xn_ns, "title");
            $creator = $meta->getValue($xn_ns, "creator");

  2. The same property can have more than one value, which the getValues
     method will deliver as an array:

          $xn_ns = "http://www.xmlnews.org/namespaces/meta#";
          @companyCodes = $meta->getValues($xn_ns, 'companyCodes');

METHODS
=======

new()
     Create a new (empty) metadata collection:

          use XMLNews::Meta;
          my $meta = new XMLNews::Meta();

     Once you have created the collection, you can add values manually
     using the addValue() method, or import one or more files into the
     collection using the importRDF() method.

importRDF(INPUT)
     Read an RDF file from the IO::Handle input stream provided, and add
     its properties to this metadata collection:

          $meta->importRDF($handle);

     If INPUT is a string, it will be treated as a file name; otherwise, it
     will be treated as an instance of IO::Handle.

     Note that duplicate properties will not be filtered out, so it is
     possible to have the same property with the same value more than once.
     Importing a file does not remove any properties already in the
     collection.

exportRDF(OUTPUT)
     Export all of the properties in the collection to an IO::Handle output
     stream of some sort:

          $meta->exportRDF($output);

     If OUTPUT is a string, it will be treated as a file name; otherwise,
     it will be treated as an instance of IO::Handle.

     The XML::Meta module will create its own namespace prefixes for the
     different namespaces in the document, but the namespaces themselves
     will not be changed.

getValues(NAMESPACE, PROPERTY)
     Return all of the values for a property in a namespace as an array.
     If the property does not exist, return an empty array:

          my $namespace = "http://www.xmlnews.org/namespaces/meta#";
          my @people = $meta->getValues($namespace, 'personName');
          foreach $person (@people) {
            print "This resource mentions $person\n";
          }

     Note that it is always necessary to provide a namespace as well as a
     property name; the property 'personName' might have a different
     meaning in another namespace.

     (When you know for certain that a property will never have more than
     one value, you can use the getValue() method instead to avoid dealing
     with an array.)

getValue(NAMESPACE, PROPERTY)
     Return a single value (or undef) for a property in a namespace:

          my $resourceId = $meta->getValue($namespace, 'resourceId');

     This method is convenient for properties (like XMLNews's 'resourceId')
     which should never have more than one value.

     NOTE: If there is more than one value present for the resource, the
     getValue() method will croak().

hasValue(NAMESPACE, PROPERTY)
     Return true if the specified property has one or more values, and
     false otherwise:

          unless ($meta->hasValue($namespace, 'provider')) {
            print "No provider information available\n";
          }

getNamespaces()
     Return an array containing all of the namespaces used in the metadata
     collection:

          my @namespaces = $meta->getNamespaces();

     Each namespace is a URI (URL or URN) represented as a string.

getProperties(NAMESPACE)
     Return an array containing all of the properties defined for a
     specific namespace in the metadata collection:

          my @properties = $meta->getProperties($namespace);

     If the namespace does not exist, this method will croak().

addValue(NAMESPACE, PROPERTY, VALUE)
     Add a value for a property in a namespace:

          $meta->addValue($namespace, "locationName", "Salt Lake City");

removeValue(NAMESPACE, PROPERTY, VALUE)
     Remove a value for a property in a namespace:

          $meta->removeValue($namespace, "locationName", "Dallas");

     If the namespace, property, or value does not exist, this method will
     croak().

CONFORMANCE NOTE
================

   The XMLNews metadata format is based on RDF, but this tool is not a
general RDF processor; instead, it relies on a particular usage profile
and a particular abbreviated syntax, like the following:

     <?xml version="1.0"?>
     <xn:Resource xmlns:xn="http://www.xmlnews.org/namespaces/meta#">
      <xn:resourceId>12345</xn:resourceId>
      <xn:title>Sample</xn:title>
      <xn:description>Sample resource.</xn:description>
      <xn:rendition>12345.xml</xn:rendition>
      <xn:rendition>12345.html</xn:rendition>
     </xn:Resource>

AUTHOR
======

   This module was originally written for WavePhore by David Megginson
(david@megginson.com).

Dynamically load C libraries into Perl code
*******************************************

NAME
====

   XSLoader - Dynamically load C libraries into Perl code

SYNOPSIS
========

     package YourPackage;
     use XSLoader;

     XSLoader::load 'YourPackage', @args;

DESCRIPTION
===========

   This module defines a standard *simplified* interface to the dynamic
linking mechanisms available on many platforms.  Its primary purpose is to
implement cheap automatic dynamic loading of Perl modules.

   For more complicated interface see DynaLoader.

AUTHOR
======

   Ilya Zakharevich: extraction from DynaLoader.

Topic Map management
********************

NAME
====

   XTM - Topic Map management

SYNOPSIS
========

     use XTM;

     $tm = new XTM; # creating an empty map

     # reading a topic map description from an XML file
     use XTM::XML;
     $xml = new XTM::XML (file => 'mymap.tm'); # create an XML channel, see XTM::XML
     $tm  = new XTM (tie => $xml); # binds variable to channel

     # primitive accessor to fetch/set the memory representation of the map
     print Dumper $tm->memory;
     # basic statistics about a map
     print Dumper $tm->info;

DESCRIPTION
===========

   Topic Maps are a means for layering multidimensional topic spaces on
top of information assets. The standard covers concepts like topics,
associations, scopes and occurrences. Topic Maps are expected to have a
major impact on future information systems (semantic web).

   See http://www.topicmaps.org/xtm/1.0/ for more information.

   Topic maps can be loaded from an XML based resource (local or remote
via an URL) as prescribed by the XTM standard. There is also a way to tie
a map to a persistent medium. The latter is especially interesting when
running this module along with a (web) server.

PACKAGES
========

   Following package come with this distribution (`XTM::Server' in this
node is in preparation):

     XTM                          this package, toplevel wrapper for (non-threaded) maps
     XTM::Memory                  in-memory representation of a map

     XTM::XML::PSI                PSI definitions
     XTM::XML                     XML parser
     XTM::XML::Latin1Parser
     XTM::XML::UTF8
     XTM::XML::Grove2TM

     XTM::Log                     logging facility will be used by others

     XTM::generic                 accessor functions for all below
     XTM::topic                   implementation of the 'topic' class
     XTM::association             implementation of the 'association' class

     XTM::topicRef                generic class definition
     XTM::baseName                generic class definition
     XTM::scope                   generic class definition
     XTM::resourceRef             generic class definition
     XTM::instanceOf              generic class definition
     XTM::subjectIdentity         generic class definition
     XTM::subjectIndicatorRef     generic class definition
     XTM::variant                 generic class definition
     XTM::variantName             generic class definition
     XTM::parameters              generic class definition
     XTM::roleSpec                generic class definition
     XTM::member                  generic class definition
     XTM::mergeMap                generic class definition
     XTM::resourceData            generic class definition
     XTM::baseNameString          generic class definition
     XTM::occurrence              generic class definition

INTERFACE
=========

Constructor
-----------

   The constructor expects no mandatory parameters but you can provide a
hash with the following fields:

tie:
     If you provide a tieable object (see XTM/XML, ...), then
     this object is bound to the topic map.

*staleness*: (not implemented in this public version)
     This additional field  lets you specify how strong the relationship
     between the original source (say, XML file) and the map is. Whenever
     the time difference between memory copy and the copy on the tie-ed
     medium exceeds the *staleness* given, then a sync (either in or out)
     will be done.

     $tm = new XTM ();
     $tm = new XTM (tie => new XTM::XML (file => 'map.xtm'));

Methods
=======

   All, except the methods below, are handed over to the corresponding
memory component.

memory
     returns/sets the XTM/Memory, component. Setting
     will NOT check the consistency with the other components.

info
     returns some meta/statistical information about the map in form of a
     hash reference.

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Topic Map Logger
****************

NAME
====

   XTM::Log - Topic Map Logger

SYNOPSIS
========

     use XTM::Log;

DESCRIPTION
===========

   This package provides some logging facilities for the XTM::* packages.
Basically, it provides STDERR and file based logging.

INTERFACE
=========

Global Variables
----------------

   Following variables can be set to control the behavior of this package:

logfile (xtmd.log)
`loglevel' (1)
Methods
=======

flog
     provides some basic file logging facilities. Please refer to the
     global variables for configuration.  It logs messages to the current
     logfile whenever called and the passed loglevel is at least the
     minimum (as configured via the global variable `loglevel').
     Parameters are:

    entity
          Here you can provide some descriptive text of the module logging.

    `loglevel'
          current loglevel

     Any additional parameters are copied (for SCALARs) or output via
     Data::Dumper::Dumper.

     Example:

          flog ('MyProgram', 4, 'Logging a line', $line, \%context);

elog
     provides some basic STDERR logging facilities. Otherwise see flog.

     Example:

          elog ('MyProgram', 4, 'Logging a line', $line, \%context);

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Topic Map management, in-memory data structure.
***********************************************

NAME
====

   XTM - Topic Map management, in-memory data structure.

SYNOPSIS
========

     use XTM::Memory;
     $tm = new XTM::Memory ();

     # adding something
     $tm->add (new XTM::topic (id => "t-beatles", ...));
     $tm->add (new XTM::association (....));

     # removing something
     $tm->remove ('t-beatles');

     # checking something
     print "Hurray" if
      $tm->is_topic ('t-john-lennon') ||
      $tm->is_association ('a-played-in');

     # finding something
     @rumstis = @{$tm->topics ( "baseName regexps /rumsti.*/" )};

     # fetching names for a scope
     @names = @{$tm->baseNames ([ 't-paul-mccartney', 't-john-lennon' ],
     			      [ 'http://www.topicmaps.org/xtm/language.xtm#en' ]);}

DESCRIPTION
===========

   This package provides an in-memory data structure for topic maps.
Basically, the object maintains a hash of topics and a hash of
associations. The interface provides for basic operations to add/delete
topics/associations and to query the map via a query language.

INTERFACE
=========

   The interface offers basic access function but also some sophisticated
filters to create sub maps. More convenient functions to retrieve topic
and association information can be found in the `XTM::Server' in this node
package distributed seperately.

Constructor
-----------

   The constructor expects only one optional parameter, id. If not
provided, the id will remain undefined.

     $tm = new XTM::Memory ();

Methods
-------

add
     Adds a (list of) topics, associations and/or maps to the map object
     with the following rules:

       1. If a particular topic/association id does already exist in the
          map object, the corresponding topic will simply be
          *overwritten*. This also happens when another map with such a
          topic/association is merged.

       2. No topic merging will (yet) occur.

          Examples:

          $t = new XTM::topic (id => "t-portishead", ...);
          $a = new XTM::association (....);
          $tm->add ($t);
          $tm->add ($t1, $t2);
          $a = new XTM::association (....);
          $tm->add ($a);
          $tm->add ($a, $t);
          $tm2 = new XTM::Memory;
          ...
          $tm->add ($tm2);

     If a parameter is neither a topic nor an association nor a topic map,
     an exception will be raised.

remove
     removes particular topics and associations specified by their id.
     You can provide a list here. The method will return a list references
     of object (references), which were removed from the map during this
     operation. ids not identifying any topic or association in the map,
     are ignored.

     Examples:

          # get rid of a particular topic
          $tm->remove ('t-portishead');

*is_topic*, *is_association*
     check whether a particular topic/association with a given id exists
     in the map.  Returns 1 in that case, undef otherwise.

     Examples:

          print "Hurray" if $tm->is_topic ('t-john-lennon') ||
                            $tm->is_association ('a-played-in');

topics
     returns a list reference of topic ids for this given map. An optional
     filter specification can filter only relevant topics:

     Example:

          # get all of them (or at least what the implementation is willing to give)
          $tm->topics ();
          # only with some name
          $tm->topics ( "baseName regexps /rumsti.*/" );

     The filter specifications follow the syntax:

          filter        -> clause { 'AND' clause }
          clause        -> 'baseName'   'regexps' regexp_string                               |
                           'occurrence' 'regexps' regexp_string                               |
                           'text'       'regexps' regexp_string                               | # any text within the topic
                           'id'         'regexps' regexp_string                               |
                           'id'         'eq'      ''' string '''                              |
                           'assocs' [ 'via' topic_id ] [ 'with' topic_id ] [ 'transitively' ] |
                           'is-a'  topic_id                                                   |
          ##                 'instanceOfs' ( '<=' | '==' | '>=' )  set_of_topic_ids | NOT IMPLEMENTED
          ##                 'scoped_by' topic_id   ## NOT IMPLEMENTED
          regexp_string -> '/' regexp '/'
          regexp        -> <a perl pattern>
          topic_id      -> <id of a topic>
          string        -> <any string with no \' in it>

associations
     returns the ids of associations. An optional filter specification can
     filter only relevant associations:

     Examples:

          # get _all_  from the map
          @assocs = @{$tm->associations()};
          # get only these matching a specific regexp for the id
          @assocs = @{$tm->associations ('id  regexps /^#a-some-assoc/')};
          # get only these containing a particular topic as a role player
          @assocs = @{$tm->associations ('has_role t-some-role')};
          # get only these containing a particular topic as a member
          @assocs = @{$tm->associations ('has_member t-some-topic AND has_role t-some-role')};
          # with a specific type
          @assocs = @{$tm->associations ('is-a at-relation')};

     The filter specifications follow the syntax:

          filter        -> clause { 'AND' clause }
          clause        -> 'id'    'regexps' regexp_string      |
                           'id'    'eq'      ''' string '''     |
                           'has-role'        topic_id           |
                           'has-member'      topic_id           |
                           'is-a'            topic_id           |
          regexp_string -> '/' regexp '/'
          regexp        -> <a perl pattern>
          topic_id      -> <id of a topic>

topic, *association*
     return a topic/association object (reference) for a given id. If
     there is no such id, an exception will be raised.

          my $john = $tm->topic ('t-john-lennon');

`topic_tree'
     computes a tree of topics based on a starting topic, an association
     type and two roles. Whenever an association of the given type is
     found and the given topic appears in the role given in this very
     association, then all topics appearing in the other given role are
     regarded to be children in the result tree. There is also an optional
     depth parameter. If it is not defined, no limit applies. If there are
     loops implied by this relation, so be it.

     Examples:

          $hierachy = $tm->topic_tree (topic      => $start_node,
          			       assoc_type => 'at-relation',
          			       a_role     => 'tt-parent',
          			       b_role     => 'tt-child' );
            $yhcareih = $tm->topic_tree (topic      => $start_node,
          			       assoc_type => 'at-relation',
          			       b_role     => 'tt-parent',
          			       a_role     => 'tt-child',
          			       depth      => 42 );

`baseNames'
     receives a list reference containing topic ids. It returns a hash
     reference containing the baseName for each topic as a value with the
     topic id the key. The additional parameter is interpreted as list
     reference to scoping topics. If this list is undef, then any basename
     may be returned. If the list is empty ([]), then NO basename will
     ever be returned. If it is non-empty, then - according to the order in
     this list - the first basename matching will be selected.

     Example:

          $names_ref = $tm->baseNames ([ 't-topic1', 't-topic-2' ],
          				[ 'http://www.topicmaps.org/xtm/language.xtm#en' ]);

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Topic Map management, syncing with XML data
*******************************************

NAME
====

   XTM::XML - Topic Map management, syncing with XML data

SYNOPSIS
========

     use XTM::XML;

     # reading a topic map description from an XML file
     $xml = new XTM::XML (file => 'mymap.tm');

DESCRIPTION
===========

   This package provides an abstract class to deal with TMs stored in XML
form, be it on files or as a string.

INTERFACE
=========

Constructor
-----------

   The constructor expects a hash as parameter containing one of the
following fields:

url:
     If given then the XML data will be read/written from/to this url.

file:
     If given then the XML data will be read/written from/to this file
     (This is just a convenience function as it will be mapped to url).

text:
     If given then the XML data will be read/written from/to this text.
     (See method text how to retrieve the current value).

   If several fields are specified, an exception will be raised.

   Examples:

     $xtm = new XTM::XML (file => 'here.xml');
     $xtm = new XTM::XML (url  => 'file:here.xml');  # the same
     $xtm = new XTM::XML (text => '<?xml version="1.0"?><topicmap> ...</topicmap>');

Methods
-------

   The methods `sync_in', `sync_out' and `last_mod' implement the methods
from the abstract class.

`last_mod'
     returns the UNIX time when the resource has been modified last. undef
     is returned if the result cannot be determined.

`sync_in'
     actually loads an XTM resource and returns a XTM/Memory,
     object.

`sync_out'
     is currently not implemented.

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

XTM XML parser
**************

NAME
====

     XTM::XML::Grove2TM - XTM XML parser

SYNOPSIS
========

     use XTM::XML::Latin1Parser;
     my $grove_builder = XTM::XML::Latin1Parser->new;
     my $parser = XML::Parser::PerlSAX->new ( Handler => $grove_builder );
     my $grove;
     $grove  = $parser->parse ( Source => { String => $stream,
                                            Encoding => 'ISO-8859-1' } );
     use Data::Grove::Visitor;
     my $tm = new XTM::Memory;
     use XTM::XML::Grove2TM;
     $grove->accept_name (XTM::XML::Grove2TM->new, $tm);

DESCRIPTION
===========

   Once you have a grove with parsed XML data, you can iterate over this
grove, letting the package do the work of creating a XTM/Memory,
structure.

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

XTM generic XML first pass parser.
**********************************

NAME
====

   XTM::XML::Latin1Parser - XTM generic XML first pass parser.

SYNOPSIS
========

   # Just here to silence pod2man. This is very much an internal package

DESCRIPTION
===========

   none.

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Topic Map management, published subject identifiers
***************************************************

NAME
====

   XTM::XML::PSI - Topic Map management, published subject identifiers

SYNOPSIS
========

     use XTM::XML::PSI;
     print $psi{'universal_scope'};

DESCRIPTION
===========

   This package contains a hash with some PSIs. See

     http://www.topicmaps.org/xtm/1.0/psi1.xtm

   for an everchanging list.

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

XTM backwards compatible UTF support
************************************

NAME
====

   XTM::XML::UTF - XTM backwards compatible UTF support

DESCRIPTION
===========

   This package contains auxiliary functions to convert from UTF8 to Latin1
characters and vice-versa.

SYNOPSIS
========

     $s = "..some ugly characters ...";
     $t = utf82iso ($s);

     unless ($s eq iso2utf8 ($t)) {
       print STDERR "maybe you should not use iso2utf8\n";
     }

INTERFACE
=========

utf82iso
     converts an array and/or a single UTF-8 scalar into its ISOLatin
     equivalent.

iso2utf8
     and the other way round.

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

trivial class definition
************************

NAME
====

   XTM::association - trivial class definition

SYNOPSIS
========

     # see XTM::generic

DESCRIPTION
===========

   Generic container for accessor functions.

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

trivial class definition
************************

NAME
====

   XTM::baseName - trivial class definition

SYNOPSIS
========

     # see XTM::generic

DESCRIPTION
===========

   Generic container for accessor functions.

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

trivial class definition
************************

NAME
====

   XTM::baseNameString - trivial class definition

SYNOPSIS
========

     # see XTM::generic

DESCRIPTION
===========

   Generic container for accessor functions.

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

XTM generic accessor
********************

NAME
====

   XTM::generic - XTM generic accessor

SYNOPSIS
========

     # very much an internal package...

DESCRIPTION
===========

   Generic provider for accessor functions.

   Instead of hard-coding simple accessor functions into trivial packages,
these packages can inherit the methods from this package.

INTERFACE
=========

Constructor
-----------

   The constructor just returns a blessed object reference to the class in
question. All parameters - given in a hash - will be components of the
resulting object.

Methods
-------

   AUTOLOAD will capture most of the access.

   If the method name begins with 'add_'. If it ends with '_s' then the
provided values will be added to a list component. Otherwise it is
regarded as a single value.

   If the method does not begin with 'add_' then a simple read access is
assumed. Again, if the name ends with '_s' then a list will be returned.

   The component name will be derived from the rest of the method name, if
that is non-empty (like in 'add_rumsti_s'). If the name is empty
('add__s') then the component name will be derived from the parameters
class name ('XYZ::rumsti' will result in a component name 'rumsti').

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

trivial class definition
************************

NAME
====

   XTM::instanceOf - trivial class definition

SYNOPSIS
========

     # see XTM::generic

DESCRIPTION
===========

   Generic container for accessor functions.

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

trivial class definition
************************

NAME
====

   XTM::member - trivial class definition

SYNOPSIS
========

     # see XTM::generic

DESCRIPTION
===========

   Generic container for accessor functions.

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

trivial class definition
************************

NAME
====

   XTM::mergeMap - trivial class definition

SYNOPSIS
========

     # see XTM::generic

DESCRIPTION
===========

   Generic container for accessor functions.

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

trivial class definition
************************

NAME
====

   XTM::occurrence - trivial class definition

SYNOPSIS
========

     # see XTM::generic

DESCRIPTION
===========

   Generic container for accessor functions.

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

trivial class definition
************************

NAME
====

   XTM::parameters - trivial class definition

SYNOPSIS
========

     # see XTM::generic

DESCRIPTION
===========

   Generic container for accessor functions.

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

trivial class definition
************************

NAME
====

   XTM::resourceData - trivial class definition

SYNOPSIS
========

     # see XTM::generic

DESCRIPTION
===========

   Generic container for accessor functions.

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

trivial class definition
************************

NAME
====

   XTM::resourceRef - trivial class definition

SYNOPSIS
========

     # see XTM::generic

DESCRIPTION
===========

   Generic container for accessor functions.

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

trivial class definition
************************

NAME
====

   XTM::roleSpec - trivial class definition

SYNOPSIS
========

     # see XTM::generic

DESCRIPTION
===========

   Generic container for accessor functions.

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

trivial class definition
************************

NAME
====

   XTM::scope - trivial class definition

SYNOPSIS
========

     # see XTM::generic

DESCRIPTION
===========

   Generic container for accessor functions.

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

trivial class definition
************************

NAME
====

   XTM::subjectIdentity - trivial class definition

SYNOPSIS
========

     # see XTM::generic

DESCRIPTION
===========

   Generic container for accessor functions.

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

trivial class definition
************************

NAME
====

   XTM::subjectIndicatorRef - trivial class definition

SYNOPSIS
========

     # see XTM::generic

DESCRIPTION
===========

   Generic container for accessor functions.

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Topic Map management, Topic
***************************

NAME
====

   XTM::topic - Topic Map management, Topic

SYNOPSIS
========

     use XTM::topic;

     my $t = new XTM::topic;
     ...
     print join (",", @{$t->occurrences()});
     print "bliss and happiness" if $t->has_instanceOf ('t-billionair');

     # see XTM::generic for more

DESCRIPTION
===========

   This package provides the primitive class Topic for Topic Maps.

INTERFACE
=========

Constructor
-----------

   The constructor expects a hash with following (optional) fields:

id: a topic id (unique in the map in use), if not given, it will be generated
     $t = new XTM::topic ('id' => '#123');

Methods
-------

occurrences
     returns the occurrences of the topic as a list reference. If provided
     with a parameter, this value will be used as new occurrences list
     reference (no validation will happen).

map
     is an accessor method for the map component.

has_instanceOf
     returns true if the topic is a direct subtype of a topic specified as
     tid for the only parameter.

     Example:

          print "bliss and happiness" if $t->has_instanceOf ('t-billionair');

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

trivial class definition
************************

NAME
====

   XTM::topicRef - trivial class definition

SYNOPSIS
========

     # see XTM::generic

DESCRIPTION
===========

   Generic container for accessor functions.

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

trivial class definition
************************

NAME
====

   XTM::variant - trivial class definition

SYNOPSIS
========

     # see XTM::generic

DESCRIPTION
===========

   Generic container for accessor functions.

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

trivial class definition
************************

NAME
====

   XTM::variantName - trivial class definition

SYNOPSIS
========

     # see XTM::generic

DESCRIPTION
===========

   Generic container for accessor functions.

SEE ALSO
========

   See XTM,

AUTHOR INFORMATION
==================

   Copyright 2001, Robert Barta <rho@telecoma.net>, All rights reserved.

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

Perl Module to Read Xbase DBF Files and Foxpro IDX indexes
**********************************************************

NAME
====

   Xbase - Perl Module to Read Xbase DBF Files and Foxpro IDX indexes

ABSTRACT
========

   This is a perl module to access xbase files with simple IDX indexes.
At the moment only read access to the files are provided by this package
Writing is tougher with IDX updates etc and is being worked on. Since the
read functionality is useful in itself this version is being released.

INSTALLATION
============

   To install this package, change to the directory where this file is
present and type

     perl Makefile.PL
     make
     make install

   This will copy Xbase.pm to the perl library directory provided you have
the permissions to do so. To use the module in your programs you will use
the line:

     use Xbase;

   If you cannot install it in the system directory, put it whereever you
like and tell perl where to find it by using the following in the
beginning of your script:

     BEGIN {
     	unshift(@INC,'/usr/underprivileged/me/lib');
     }
     use Xbase;

DESCRIPTION
===========

   The various methods that are supported by this module are given below.
There is a very distinct xbase like flavour to most of the commands.

CREATING A NEW XBASE OBJECT:
----------------------------

     $database = new Xbase;

   This will create an object $database that will be used to interact with
the various methods the module provides.

OPENING A DATABASE
------------------

     $database->open_dbf($dbf_name, $idx_name);

   Associates the DBF file and optionally the IDX file with the object. It
opens the files and if a associated MEMO file is present automatically
opens it. Only Foxpro Memo files are currently supported and assumes the
same filename as the DBF with a FPT extension.

DATABASE TYPE
-------------

     print $database->dbf_type;

   Returns a string telling you if the xbase file opened is DBF3, DBF4 or
FOX

LAST UPDATE DATE
----------------

     print $database->last_update;

   Returns a date string telling you when the database was last updated.

LAST RECORD NUMBER
------------------

     $end=$database->lastrec;

   Returns the record number of the last record in the database file.

DATABASE STATUS INFORMATION
---------------------------

     $database->dbf_stat;

   This prints out on to STDOUT a display of the status/structure of the
database. It is similar to the xbase command DISPLAY STATUS. Since it
prints field names and structure it is commonly used to see if the module
is reading the database as intended and finding out the field names.

INDEX FILE STATUS INFORMATION
-----------------------------

     $database->idx_stat;

   Prints on to STDOUT the status information of an open IDX file.

GO TOP
------

     $database->go_top;

   Moves the record pointer to the top of the database. Physical top of
database if no index is present else first record according to index order.

GO BOTTOM
---------

     $database->go_bottom;

   Moves the record pointer to the bottom of the database. Physical bottom
of database if no index is present else last record according to index
order.

GO NEXT
-------

     $database->go_next;

   Equivalent to the xbase command SKIP 1 which moves the record pointer to
the next record.

GO PREVIOUS
-----------

     $database->go_prev;

   Equivalent to the xbase command SKIP -1 which moves the record pointer
to the previous record.

SEEK
----

     $stat=$database->seek($keyvalue);

   This command positions the record pointer on the first matching record
that has the key value specified. The database should be opened with an
associated index. Seek without an available index will print an error
message and abort. The return value indicates whether the key value was
found or not.

RECORD NUMBER
-------------

     $current_rec=$database->recno;

   Returns the record number that the record pointer is currently at.

BEGINNING OF FILE
-----------------

     if ($database->bof) {
     	print "At the very top of the file \n";
     }

   Tells you whether you are at the beginning of the file. Like in xbase
it is not true when you are at record number one but rather it is set when
you try to $database->go_prev when you are at the top of the file.

END OF FILE   	if ($database->eof) { 		print "At the very end of the file \n"; 	}
---------------------------------------------------------------------------------

   Tells you whether you are at the end of the file. Like in xbase it is
not true when you are at the last record but rather it is set when you try
to $database->go_next from the last record.

READ INDIVIDUAL FIELD VALUES
----------------------------

     print $database->get_field("NAME");

   Returns as a string the contents of a field name specified from the
current record. Using the pseudo field name _DELETED will tell you if the
current record is marked for deletion.

READ FIELD VALUES INTO ARRAY
----------------------------

     @fields = $database->get_record;

   Returns as an array all the fields from the current record. The fields
are in the same order as in the database.

CLOSE DATABASE
--------------

     $database->close_dbf;

   This closes the database files, index files and memo files that are
associated with the $database object with $database->open_dbf

COPYRIGHT
=========

   Copyright (c) 1995 Pratap Pereira. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

   I request that if you use this module at a web site to make a link to

   	http://eewww.eng.ohio-state.edu/~pereira/software/xbase/

   This is just so that others might find it. This is however not required
of you.

AUTHOR INFORMATION
==================

   Please send your comments, suggestions, gripes, bug-reports to

     Pratap Pereira
     pereira@ee.eng.ohio-state.edu

UPDATE HISTORY
==============

Original perl 4 script done in March 1994
Perl 5 module done in February 1995
RELEASE 2 was first public release now called xbase12.pm
RELEASE 3 was done 6/22/95 called xbase13.pm
          Fixed problem with GO_PREV & GO_NEXT after SEEK.
          Fixed problem with parsing headers of dbfs with
                  record length > 255.
          Added Memo file support.

RELEASE 4 was done 9/29/95
          Fixed problem with certain IDX failing completely,
                  was a stupid
          indexing mistake.

RELEASE 5 was done 11/14/95 (called xbase.pm 1.05)
          Fixed field length inconsistency errors by changing
                  way header is decoded. Should work with more xbase
                  variants. (Dick Sutton & Andrew Vasquez)

Version 1.06  was done 11/17/95
          Added binmode command to file handles to support
          Windows NT

Version 1.07 was done 01/23/96
          Made documentation in pod format, installation
                  automated. Fixed problem with deleted status being
                  improperly read (Chung Huynh). Renamed to Xbase
                  (previously xbase) to be consistent with other perl
                  modules. Released in CPAN.
          Prettied up dbf_stat output (Gilbert Ramirez).

CREDITS
=======

   Thanks are due to Chung Huynh (chuynh@nero.finearts.uvic.ca), Jim
Esposito (jgespo@exis.net), Dick Sutton (suttond@federal.unisys.com),
Andrew Vasquez (praka@ophelia.fullcoll.edu), Leonard Samuelson
(lcs@synergy.smartpages.com) and Gilbert Ramirez Jr
(gram@merece.uthscsa.edu)

Interactive remote control shell for xmms
*****************************************

NAME
====

   Xmms - Interactive remote control shell for xmms

SYNOPSIS
========

     perl -MXmms -e shell

DESCRIPTION
===========

   Xmms::shell provides an alternative or companion interface to the xmms
gui.

   Feature summary:

Standard Play Controls
     play, pause, stop, next, prev, eject

Standard Options
     toggle repeat, toggle shuffle

Playlist Controls
     clear, select, add file(s), add url(s), playlist load/save, sort
     (more options than the gui)

File Info
     search, view and edit mp3 tags

Misc Controls
     time change (and slider), volume change (and slider), balance change,
     window toggle

Shell Features

    command history
    command/file completion
    file matching
    title matching
    emacs key bindings
Shell Command Summary
=====================

   The complete list of shell commands is also available via the help
command.

add
     Add files to the current playlist, without clearing the current
     playlist.  See also: play description of the special `-' character.

alias
     Alias a long command to one of your own definition, e.g.:

          xmms> alias cd play /cdrom
          xmms> cd

balance
     View or change the balance.

clear
     Clear the current playlist.

current
     Display the current playlist track number, title, time, rate,
     frequency and mode.

delete
     Delete tracks from the playlist.  (NOTE: at the time of this writing,
     the *patches/xmms-playlist-delete.pat* patch must be applied to
     xmms-0.9.1.)  Example:

          xmms> delete 3

     This command can also handle ranges, e.g. to play just your favorite
     tracks from and audio cd:

          xmms> play /cdrom
          xmms> delete 5, 7..10

dig
     Search for mp3 files by mp3 tag or file name.  Root directory defaults
     to the last play command or greedy dig command.

     Example:

          #"greedy" match against *.mp3 filename and all tag info
          xmms> dig ~/mp3 gabba|break

          xmms> track
          1 - Prodigy - Break'n'Enter [0:11/5:59 (3%)]
          2 - gabba (6:12)
          3 - gabba (4:47)
          4 - break_and_enter_95_live (5:58)
          5 - Prodigy - Diesel Power (Snake break - Mi (7:08)
          6 - The Prodigy - Acid Break (4:42)

          #match against mp3 `artist' tag only
          xmms> dig artist maxim|liam
          1 - Biohazard feat. Maxim Reality - Breathe [0:03/3:33 (1%)]
          2 - Liam Howlett (DJ mix) - Heavyweight Selection XL Mix (19:37)
          3 - Maxim - Dog Day (4:41)
          4 - Maxim - Factory Girl (2:33)

     See also: play description of the special `-' character.

eject
     Just like pressing the eject button on the gui, pops up the *load
     file* window.  However, if an audio cd is/was playing (and Audio::CD
     is installed), the cd tray will pop open.  If an audio cd is not
     playing, but you want to open the tray, provided the cd argument:

          xmms> eject cd

export
     Make environment variables available to the shell, e.g.:

          xmms> export PWD
          xmms> play $PWD/fav.mp3

          xmms> export MP3_HOME=/usr/local/mp3
          xmms> play $MP3_HOME/fav.mp3

          xmms> export CD="play /cdrom"
          xmms> $CD

files
     The current playlist with be reduced to files matching the given
     pattern.  If no files match, the playlist is not changed.  Example:

          xmms> files ro(ck|ll) #reduces playlist to files containing `rock' and `roll'

     To negate, use the ! prefix:

          xmms> files !fire    #removes files containing `fire' from the playlist

help
     Print command summary.

history
     This function adds a bit of functionality over the readline history.
     Mainly, ability to save and run history to and from files on disk.
     Example:

          xmms> play ~/mp3/favorites
          xmms> volume 40
          xmms> jtime 1 2:00
          xmms> jtime 2 0:45
          xmms> history >~/mp3/fav.hist #save current history
          xmms> history <~/mp3/fav.hist #read/run history from fav.hist

     TAB completion on the special character `-' will recall the last
     directory from which a history script was read.  See also:
     *Xmms::SongChange*.

     If the file *~/.xmms/.perlrc* exists, it will be automatically run as
     a history script when the shell is invoked, before the prompt loop.
     For example, my *~/.xmms/.perlrc* file looks like so:

          volume 30
          resume

     The clear subcommand can be used to clear the current history:

          xmms> history clear

info
     This command will display information about the given track, where
     track is a number in the current playlist file.  The sub-commands can
     be used to edit the mp3 tag of the track file.  Example:

          xmms> info 2
          File........./usr/local/mp3/prodigy/rare/we_eat_rhythm.mp3
          Size......... 4.9M
          Modified.....Thu May 20 16:29:43 1999
          Album........deleted from Jilted Generation
          Artist.......The Prodigy
          Comment......?
          Genre........Electronic
          Title........We Eat Rhythm (Original Version)
          Tracknum.....?
          Year.........1994
          Time.........5:18
          ...

          xmms> info 2 comment Great Tune
          comment set to `Great Tune'

          xmms> info 2 comment
          Comment......Great Tune

jtime
     This command jumps to the last time set by the time command and
     defaults to *0:00*.  For example:

          xmms> dig file speedway #load files with the name `speedway'
          xmms> time 1:10         #jump 1:10 into the song
          ... time passes ...
          xmms> jtime             #jump back to 1:10

     A two argument form of jtime can be used to set jump times for tracks
     without actually jumping to that time, until jtime is called in the
     no argument form.   I like this for playing my favorite parts of
     songs, example:

          #set jump times for these three tracks
          xmms> jtime 3 0:30
          xmms> jtime 4 1:00
          xmms> jtime 6 2:11

     See also, key bindings: M-\

list
     This command is used to load a playlist file or to save the current
     playlist file to disk.

     Example:

          xmms> list save ~/mp3/fav-tracks #save list
          playlist saved

          xmms> list ~/mp3/fav-tracks      #load list

     To measure the size of a list:

          xmms> list size ~/mp3/slipknot.m3u
          slipknot_742617000027.mp3  560k
          slipknot_sic.mp3  3.1M
          ...
          Total: 40.2M

mtime
     Mark the current output time for jtime.

next
     Skip forward to next track in the playlist.

pause
     Pause the current track in the playlist.

play
     With no arguments, this command is just the same as hitting the gui
     play button.  When given an argument of a directory, file or file
     glob, the playlist will be set to these files.  Example:

          xmms> play ~/mp3/prodigy/remixes/

          xmms> play ~/mp3/prodigy/live/*skylined*

     TAB completion on the special character `-' will recall the last
     directory used with the add, play or dig command, this value is also
     saved to your ~/.xmms/config file, so it is always available.
     Example:

          xmms> play -<TAB>

     completes to:

          xmms> play /home/dougm/mp3/prodigy/remixes/

prev
     Skip backward to previous track in the playlist.

quit
     Quit the xmms shell.

repeat
     Toggle the repeat button.

resume
     This command will restore the xmms state to where it was just before
     the last quit command was run.  That is, it will load the saved
     playlist and jump to the list position and output time where xmms was
     just before quitting.  The playlist, position and output time are
     saved in *~/.xmms/config*.

shuffle
     Toggle the shuffle button.

sort
     Sort the playlist various ways:

    access
          Sort by last file access time.

    album
          Sort by album mp3 tag.

    artist
          Sort by artist mp3 tag.

    comment
          Sort by artist mp3 tag.

    file
          Sort by file basename.

    genre
          Sort by genre mp3 tag.

    large
          Sort by file size, from large to small.

    new
          Sort by file modification time, from new to old.

    old
          Sort by file modification time, from old to new.

    order
          Sort the list by order of your choice, e.g.:

               xmms> play /cdrom
               xmms> sort order 3, 10, 6..9, 1

          Tracks not specified in the new order are left out of the new
          playlist.

    path
          Sort by filename, including the path name.

    random
          Sort in random order.

    reverse
          Reverse the playlist order.

    small
          Sort by file size, from small to large.

    title
          Sort by title name.

    tracknum
          Sort by tracknum mp3 tag.

    year
          Sort by year mp3 tag.

time
     With no argument, this command will display the elapsed, total and
     remaining percentage time of the current track.  When given a *+N*
     argument, it will jump the song forward N seconds.  When given a -N
     argument, it will jump the song backward N seconds.  *+<TAB*> and
     *-<TAB*> can be used a slider for moving forward and backward.
     Finally, a *mm:ss* argument will jump to that time in the song.  Oh,
     and *time <TAB*> will complete to the form *0:00..mm:ss*, which will
     jump to a random time in the song.

titles
     This function works just the same as the files function, but matches
     against playlist titles.

track
     This function is used for interacting with the current playlist.
     With no arguments, it will print the entire list.  When given a range
     argument, it will print the info for those tracks, for example:

          xmms> track 100..230

     Given a number or title name, it will jump to that track in the
     playlist.

url
     Add a url to the playlist for streaming.  TAB completion on the
     special character `-' will recall the last url used with this command.

     If *Xmms::shell* finds the *$ENV{HOME}/.xmms/.perlurldb* file when
     starting up, the urls in this file will be used for url tab
     completion.

volume
     View or change the volume.  With no argument, this command displays
     the current volume percentage.  With an argument, changes the volume
     to the given percentage.  *+<TAB*> and *-<TAB*> can be used a slider
     for moving raising and lowering the volume.  The up/down arrow keys
     are also bound to this slider.

window
     This command is used to show or hide the xmms windows.  If the shell
     is started and xmms is not already running, all windows will be
     hidden by default.

Key Bindings
============

   Here is a list of some of the more useful key bindings.  `C' is
shorthand for the control key, `M' is shorthand for the *meta* key, which
is normally the escape key.

C-a : move to beginning of the line
C-b : move backward one character
C-c : interrupt
C-d : delete next character
C-e : move to end of the line
C-f : more forward one character
C-h : delete previous character
TAB : complete
C-k : kill line
C-l : clear screen
C-n : next command in history list
C-p : previous command in history list
C-r : reverse search in history list
C-s : forward search in history list
C-t : transpose characters
C-u : discard line
C-y : yank line
M-< : beginning of history
M-> : end of history
M-b : move backward one word
   The following key bindings are shortcuts specific to xmms:

up arrow : volume slide up
down arrow : volume slide down
M-= : next
M- : prev
M-. : stop
M-/ : play
M-\ : jtime
M-m : mtime
M-, : pause
M-~ : shuffle
M-@ : repeat
M-` : run previous command in history list

M-1 : play track 1 in the playlist

M-2 : play track 2 in the playlist (and so on to #9)
   The nice part about these key bindings is the single-keystoke-ness and
that they are not added to the command history, leaving just the more
complex commands in your history buffer.

   Effective use of these bounds keys can actually make up a half-assed
sampler too.

   The following key bindings will toggle the xmms windows:

M-a : all windows
M-w : main window
M-l : playlist window
M-q : equalizer window
Command Aliases
===============

   A command abbreviation table is built at startup to provide the
following command aliases:

     a     => add
     b     => balance
     ch    => change
     cl    => clear
     cr    => crop
     cu    => current
     de    => delete
     di    => dig
     e     => eject
     f     => files
     he    => help
     hi    => history
     i     => info
     j     => jtime
     l     => list
     m     => mtime
     n     => next
     pa    => pause
     pl    => play
     pr    => prev
     q     => quit
     rep   => repeat
     res   => resume
     sh    => shuffle
     so    => sort
     st    => stop
     tim   => time
     tit   => titles
     tr    => track
     u     => url
     v     => volume
     w     => window

SEE ALSO
========

   xmms(1), Xmms::SongChange(3), Xmms::Remote(3), Xmms::Config(3),
MPEG::MP3Info(3)

AUTHOR
======

   Doug MacEachern

Perl Interface to xmms_cfg API
******************************

NAME
====

   Xmms::Config - Perl Interface to xmms_cfg API

SYNOPSIS
========

     my $file = Xmms::Config->file; #$ENV{HOME}/.xmms/config
     my $cfg = Xmms::Config->new($file);

DESCRIPTION
===========

AUTHOR
======

   Doug MacEachern

SEE ALSO
========

   xmms(1), Xmms::Remote(3)

Perl Interface to xmms_remote API
*********************************

NAME
====

   Xmms::Remote - Perl Interface to xmms_remote API

SYNOPSIS
========

     use Xmms::Remote ();
     my $remote = Xmms::Remote->new;
     $remote->play;

DESCRIPTION
===========

   This module provides a Perl interface to the xmms remote control
interface.  No docs yet, sorry, see test.pl and Xmms.pm for now

SEE ALSO
========

   xmms(1), Xmms(3), MPEG::MP3Info(3)

AUTHOR
======

   Doug MacEachern

Take actions based on song track/time change
********************************************

NAME
====

   Xmms::SongChange - Take actions based on song track/time change

SYNOPSIS
========

     xmms> change on

DESCRIPTION
===========

   This module creates a thread to poll *xmms* for song track and time
changes.  The thread is started via the *Xmms::shell* command *change on*
and stopped via *change off*.

CAVEATS
=======

   This module is considered very *EXPERIMENTAL*.  During testing, it
caused *xmms* to freeze sometimes.  However, this freezing occured with
*xmms* version *0.9*, I have seen no freezing with version *0.9.1*.

   The module decides if a song has changed based on track number or track
length.  So, when only one track is in the playlist, this logic is broken.

   Since the thread is constantly polling *xmms* via the remote protocol,
xmms is consuming more cpu time than normal.

FEATURES
========

   Current features include:

jtime
     When *Xmms::SongChange* is running, it will auto jump to the current
     track's jtime, if any.

repeat
     The *Xmms::shell* repeat command can be used with 2 additional
     arguments, to repeat a track in the playlist n number of times before
     advancing.  Example:

          xmms> repeat 1 3

     This command will cause track 1 to be repeated 3 times before
     advancing.

crop
     *Xmms::SongChange* adds a new crop command, which is similar in
     concept to jtime, but advances to the next track in the playlist when
     the current track crop time is reached.  Example:

          xmms> crop 2 4:30

     This command will cause playlist advance when track 2 reaches the
     output time of *4:30*.

     With no arguments, the current output time is set as the crop time
     for the current track.  The *M-c* key binding has the same effect.

clear
     When the *SongChange* thread is running, the *Xmms::shell* clear
     command will also clear all *SongChange* watch points.

TIPS
====

   The *Xmms::shell* history command can be used to run a "script".  For
example, consider a file such as:

     change on
     clear
     add /usr/local/mp3/prodigy/live/speedway.mp3
     add /usr/local/mp3/prodigy/live/rock_n_roll_98.mp3
     jtime 1 1:19
     crop 1 2:17
     repeat 1 3
     jtime 2 1:00
     crop 2 4:20
     play

   Which can be run in the shell like so:

     xmms> history < ~/mp3/example.sc

FUTURE
======

   I plan to implement the following features in the future:

fade
     start to fade the volume at a given time.

splice
     similar to using jtime and crop, but in the middle of a song.  of
     course, this can already be done by adding the same file to the
     playlist multiple times and setting different jtime and crop times
     for each.

???
AUTHOR
======

   Doug MacEachern

Yet Another Parser/Extractor for HTML
*************************************

NAME
====

   YAPE::HTML - Yet Another Parser/Extractor for HTML

SYNOPSIS
========

     use YAPE::HTML;
     use strict;

     my $content = "<html>...</html>";
     my $parser = YAPE::HTML->new($content);
     my ($extor,@fonts,@urls,@headings,@comments);

     # here is the tokenizing part
     while (my $chunk = $parser->next) {
       if ($chunk->type eq 'tag' and $chunk->tag eq 'font') {
         if (my $face = $chunk->get_attr('face')) {
           push @fonts, $face;
         }
       }
     }

     # here we catch any errors
     unless ($parser->done) {
       die sprintf "bad HTML: %s (%s)",
         $parser->error, $parser->chunk;
     }

     # here is the extracting part

     # <A> tags with HREF attributes
     # <IMG> tags with SRC attributes
     $extor = $parser->extract(a => ['href'], img => ['src']);
     while (my $chunk = $extor->()) {
       push @urls, $chunk->get_attr(
         $chunk->tag eq 'a' ? 'href' : 'src'
       );
     }

     # <H1>, <H2>, ..., <H6> tags
     $extor = $parser->extract(qr/^h[1-6]$/ => []);
     while (my $chunk = $extor->()) {
       push @headings, $chunk;
     }

     # all comments
     $extor = $parser->extract(-COMMENT => []);
     while (my $chunk = $extor->()) {
       push @comments, $chunk;
     }

`YAPE' MODULES
==============

   The `YAPE' hierarchy of modules is an attempt at a unified means of
parsing and extracting content.  It attempts to maintain a generic
interface, to promote simplicity and reusability.  The API is powerful,
yet simple.  The modules do tokenization (which can be intercepted) and
build trees, so that extraction of specific nodes is doable.

DESCRIPTION
===========

   This module is yet another parser and tree-builder for HTML documents.
It is designed to make extraction and modification of HTML documents
simplistic.  The API allows for easy custom additions to the document
being parsed, and allows very specific tag, text, and comment extraction.

USAGE
=====

   In addition to the base class, `YAPE::HTML', there is the auxiliary
class `YAPE::HTML::Element' (common to all `YAPE' base classes) that holds
the individual nodes' classes.  There is documentation for the node
classes in that module's documentation.

   HTML elements and their attributes are stored internally as lowercase
strings.  For clarification, that means that the tag `<A
HREF="FooBar.html">' is stored as

     {
       TAG => 'a',
       ATTR => {
         href => 'FooBar.html',
       }
     }

   This means that tags will be output in lowercase.  There will be a
feature in a future version to switch output case to capital letters.

Functions
---------

   * `YAPE::HTML::EMPTY(@tags)'

     Adds to the internal hash of tags which never contain any out-of-tag
     content.  This hash is `%YAPE::HTML::EMPTY', and contains the
     following tag names: area, base, `br', `hr', `img', input, link,
     `meta', and param.  Deletion from this hashmust be done manually.
     Adding to this hash automatically adds to the `%OPEN' hash, described
     next.

   * `YAPE::HTML::OPEN(@tags)'

     Adds to the internal hash of tags which do not require a closing tag.
     This hash is `%YAPE::HTML::OPEN', and contains the following tag
     names:  area, base, `br', dd, `dt', `hr', `img', input, `li', link,
     `meta', p, and param.  Deletion from this hash must be done manually.

     There is a subtle difference between "empty" and "open" tags.  For
     example, the `<AREA>' tag contains a few attributes, but there is no
     text associated with it (nor any other tags), and therefore, is
     "empty"; the `<LI>', on the other hand,

     *It is strongly suggested* that for ease in parsing, any tags that
     you do not explicitly close have a / at the end of the tag:

          Here's my cat: <img src="cat.jpg" />

Methods for `YAPE::HTML'
------------------------

   * `use YAPE::HTML;'

   * `use YAPE::HTML qw( MyExt::Mod );'

     If supplied no arguments, the module is loaded normally, and the node
     classes are given the proper inheritence (from
     `YAPE::HTML::Element').  If you supply a module (or list of modules),
     import will automatically include them (if needed) and set up *their*
     node classes with the proper inheritence - that is, it will append
     `YAPE::HTML' to `@MyExt::Mod::ISA', and `YAPE::HTML::xxx' to each
     node class's `@ISA' (where `xxx' is the name of the specific node
     class).

     It also copies the `%OPEN' and `%EMPTY' hashes, as well as the
     `OPEN()' and `EMPTY()' functions, into the `MyExt::Mod' namespace.
     This process is designed to save you from having to place `@ISA'
     assignments all over the place.

     It also copies the `%SSI' hash.  This hash is not suggested to be
     altered, and therefore it does not have any public interface (you
     have to fiddle with it yourself).  It exists to ensure an SSI is
     valid.

          package MyExt::Mod;
          use YAPE::HTML 'MyExt::Mod';

          # @MyExt::Mod::ISA = 'YAPE::HTML'
          # @MyExt::Mod::text::ISA = 'YAPE::HTML::text'
          # ...

          # being rather strict with the tags
          %OPEN = ();
          %EMPTY = ();

   * `my $p = YAPE::HTML->new($HTML, $strict);'

     Creates a `YAPE::HTML' object, using the contents of the `$HTML'
     string as its HTML to parse.  The optional second argument determines
     whether this parser instance will demand strict comment parsing and
     require all tags to be closed with a closing tag or a / at the end of
     the tag (`<HR />').  Any true value (except for the special string
     `-NO_STRICT') will turn strict parsing on.  This is off by default.
     (This could be considered a bug.)

   * `my $text = $p->chunk($len);'

     Returns the next `$len' characters in the input string; `$len'
     defaults to 30 characters.  This is useful for figuring out why a
     parsing error occurs.

   * `my $done = $p->done;'

     Returns true if the parser is done with the input string, and false
     otherwise.

   * `my $errstr = $p->error;'

     Returns the parser error message.

   * `my $coderef = $p->extract(...);'

     Returns a code reference that returns the next object that matches
     the criteria given in the arguments.  This is a fundamental feature
     of the module, and you can extract that from `Extracting Sections' in
     this node.

   * `my $node = $p->display(...);'

     Returns a string representation of the entire content.  It calls the
     parse method in case there is more data that has not yet been parsed.
     This calls the `fullstring' method on the root nodes.  Check the
     `YAPE::HTML::Element' docs on the arguments to `fullstring'.

   * `my $node = $p->next;'

     Returns the next token, or undef if there is no valid token.  There
     will be an error message (accessible with the error method) if there
     was a problem in the parsing.

   * `my $node = $p->parse;'

     Calls next until all the data has been parsed.

   * `my $attr = $p->quote($string);'

     Returns a quoted string, suitable for using as an attribute.  It
     turns any embedded `"' characters into `&quot;'.  This can also be
     called as a raw function:

          my $quoted = YAPE::HTML::quote($string);

   * `my $root = $p->root;'

     Returns an array reference holding the root of the tree structure -
     for documents that contain multiple top-level tags, this will have
     more than one element.

   * `my $state = $p->state;'

     Returns the current state of the parser.  It is one of the following
     values: `close(TAG)', comment, done, dtd, error, `open(TAG)', pi,
     `ssi', text, `text(script)', or `text(xmp)'.  The open and close
     states contain the name of the element in parentheses (ex.
     `open(img)').  Tag names, as well as the names of attributes, are
     converted to lowercase.  The state of `text(script)' refers to text
     found inside an `<SCRIPT>' element, and likewise for `text(xmp)'.

   * `my $HTMLnode = $p->top;'

     Returns the first `<HTML>' node it finds in the tree structure.

Extracting Sections
-------------------

   `YAPE::HTML' allows comprehensive extraction of tags, text, comments,
DTDs, PIs, and SSIs, using a simple, yet rich, syntax:

     my $extor = $parser->extract(
       TYPE => [ REQS ],
       ...
     );

   TYPE can be either the name of a tag (`"table"'), a regular expression
that matches tags (`qr/^t[drh]$/'), or a special string to match all tags
(`-TAG'), all text (`-TEXT'), all comments (`-COMMENT'), all DTDs
(`-DTD'), all PIs (`-PI'), and all SSIs (`-SSI').

   *REQS* varies from element to element:

   * `-TAG', `-DTD', `-PI', `-SSI'

     A list of attributes that the tag/DTD/PI/SSI must have.

   * `-TEXT', `-COMMENT'

     A list of strings and regexes that the content of the text/comment
     must have or match.

   Here are some example uses:

   * all tags starting with "h"
          my $extor = $parser->extract(qr/^h/ => []);

   * all tags with an "align" attribute
          my $extor = $parser->extract(-TAG => ['align']);

   * all text containing the word "japhy"
          my $extor = $parser->extract(-TEXT => [qr/\bjaphy\b/i]);

   * tags involving links
          my $extor = $parser->extract(
            a => ['href'],
            area => ['href'],
            base => ['href'],
            body => ['background'],
            img => ['src'],
            # ...
          );

FEATURES
========

   This is a list of special features of `YAPE::HTML'.

   * On-the-fly cleaning of HTML

     If you aren't enforcing strict HTML syntax, then in the act of
     parsing HTML, if a tag that should be closed is not closed, it will
     be flagged for closing.  That means that input like:

          <b>Foo<i>bar</b>

     will appear as:

          <b>Foo<i>bar</i></b>

     upon request for output.  In addition, tags that are left dangling
     open at the end of an HTML document get closed.  That means:

          <b>Foo<i>bar

     will appear as:

          <b>Foo<i>bar</i></b>

   * Syntax-checking

     If strict checking is off, the only error you'll receive from
     mismatched HTML tags is a closing tag out-of-place.

     On the other hand, if you do enforce strict HTML syntax, you'll be
     informed of tags that do not get closed as well (that should be
     closed).

TO DO
=====

   This is a listing of things to add to future versions of this module.

API
---

   * HTML entity translation (via `HTML::Entities' no doubt)

     Add a flag to the `fullstring' method of objects, `-EXPAND', which
     will display `&...;' HTML escapes as the character representing them.

   * Toggle case of output (lower/upper case)

     Add a flag to the `fullstring' method of objects, `-UPPER', which
     will display tag and attribute names in uppercase.

   * Super-strict syntax checking

     DTD-like strictness in regards to nesting of elements - `<LI>' is not
     allowed to be outside an `<OL>' or `<UL>' element.

Internals
---------

   * Make it faster, of course

     There's probably some inherent slowness to this method, but it works.
     And it supports the robust extract method.

   * Combine `CLOSED' and `IMPLICIT'

     Make three constants, `CLOSED_NO', `CLOSED_YES', and `CLOSED_IMPL'.

BUGS
====

   Following is a list of known or reported bugs.

Fixed
-----

   * Inheritence fixed again (fixed in `1.11')

   * Inheritence was fouled up (fixed in 1.10)

Pending
-------

   * The above features aren't in here yet.  `;)'

   * Strict syntax-checking is not on by default.

   * This documentation might be incomplete.

   * DTD, PI, and SSI support is incomplete.

   * Probably need some more test cases.

   * SSI conditional tags don't contain content.

SUPPORT
=======

   Visit `YAPE''s web site at `http://www.pobox.com/~japhy/YAPE/'.

SEE ALSO
========

   The `YAPE::HTML::Element' documentation, for information on the node
classes.

AUTHOR
======

     Jeff "japhy" Pinyan
     CPAN ID: PINYAN
     japhy@pobox.com
     http://www.pobox.com/~japhy/

sub-classes for YAPE::HTML elements
***********************************

NAME
====

   YAPE::HTML::Element - sub-classes for YAPE::HTML elements

SYNOPSIS
========

     use YAPE::HTML 'MyExt::Mod';
     # this sets up inheritence in MyExt::Mod
     # see YAPE::HTML documentation

`YAPE' MODULES
==============

   The `YAPE' hierarchy of modules is an attempt at a unified means of
parsing and extracting content.  It attempts to maintain a generic
interface, to promote simplicity and reusability.  The API is powerful,
yet simple.  The modules do tokenization (which can be intercepted) and
build trees, so that extraction of specific nodes is doable.

DESCRIPTION
===========

   This module provides the classes for the `YAPE::HTML' objects.  The
base class for these objects is `YAPE::HTML::Element'; the four object
classes are `YAPE::HTML::opentag', `YAPE::HTML::closetag',
`YAPE::HTML::text', and `YAPE::HTML::comment'.

Methods for `YAPE::HTML::Element'
---------------------------------

   This class contains fallback methods for the other classes.

   * `my $content = $obj->text;'

     Returns an array reference of objects between an open and close tag,
     or a string of plain text for a block of text or a comment.  This
     method merely returns the TEXT value in the object hash.  This
     returns undef for dtd, pi, and `ssi' objects.

   * `my $string = $obj->string;'

     Returns a string representing the single object (for tags, this does
     not include the elements found in between the open and close tag).
     This method merely calls the object's text method.

   * `my $complete = $obj->fullstring;'

     Returns a string representing the object (and all objects found
     within it, in the case of a tag).  This method merely calls the
     object's string method.

   * `my $type = $obj->type;'

     Returns the type of the object:  tag, `closetag', text, or comment.

Methods for `YAPE::HTML::opentag'
---------------------------------

   This class represents tags.  Object has the following methods:

   *

     `my $tag = YAPE::HTML::opentag->new($name, $attr, $text, $closed, $impl);'

     Creates a `YAPE::HTML::opentag' object.  Takes five arguments: the
     name of the HTML element, a hash reference of attribute-value pairs,
     an array reference of objects to be included in between the open and
     closing tags, whether the tag is explicitly closed or not, and
     whether the tag is implicitly closed or not.  The attribute hash
     reference must have the keys in lowercase text.

          my $attr = { src => 'foo.png', alt => 'foo' };
          my $img = YAPE::HTML::opentag->new('img', $attr, [], 0, 1);

          my $text = [ YAPE::HTML::text->new("Bar!"), $img ];
          my $name = YAPE::HTML::opentag->new('a', { name => 'foo' }, $text);

   * `my $str = $tag->string;'

     Creates a string representation of the *tag only*.  This means the
     tag, and any attributes of the tag *only*.  No closing tag (if any)
     is returned.

          print $img->string;
          # <img src="foo.png" alt="foo" />

          print $name->string;
          # <a name="foo">

   * `my $str = $tag->fullstring($exclude, $depth);'

     Creates a string representation of the tag, the content enclosed
     between the open and closing tags, and the closing tag (if
     applicable).  The method can take two arguments: an array reference
     of tag names not to render, and the depth with which to render tags.
     The `$exclude' defaults to none, and `$depth' defaults to `-1', which
     means there is no depth limit.

          print $img->fullstring;
          # <img src="foo.png" width=20 height=43 />

          print $name->fullstring;
          # <a name="foo">Bar!<img src="foo.png" alt="foo" /></a>

          print $name->fullstring(0);
          # Bar!

          print $name->fullstring(['img']);
          # <a name="foo">Bar!</a>

          print $name->fullstring(1);
          # <a name="foo">Bar!</a>

   * `my $attr = $tag->get_attr($name);'

   * `my @attrs = $tag->get_attr(@names);'

   * `my %attrs = $tag->get_attr;'

     Fetches any number of attribute values from a tag.  Note: tags which
     contain attributes with no value have a value of undef returned for
     that attribute - this is indistinguishable from the undef returned
     for a tag that does not have an attribute.  This is on the list of
     things to be fixed.  In the meantime, use the `has_attr' method
     beforehand.

          print $name->get_attr('name');
          # 'foo'

          my %list = $img->get_attr;
          # alt => 'foo', src => 'foo.png'

   * `my $attr = $tag->has_attr($name);'

   * `my @attrs = $tag->has_attr(@names);'

     Returns 1 or "" depending on the existence of the attribute in the
     tag.

          my @on = $name->has_attr(qw( name href ));  # (1,0)

   * `$tag->set_attr(%pairs);'

     Sets a list of attributes to the associated values for the tag.

          $img->set_attr( width => 40, height => 16 );

   * `$tag->rem_attr(@names);'

     Removes (and returns) the specified attributes from a tag.  See the
     caveat above for the get_attr method about undef values.

          my $src = $img->rem_attr('src');

   * `my $closed = $tag->closed;'

     Returns 1 or 0, depending on whether or not the tag is closed.  This
     means it has a closing tag - tags like `<hr />' are not closed.

   * `my $impl = $tag->implied_closed;'

     Returns 1 or 0, depending on whether or not the tag is implicitly
     closed with a / at the end of the tag (like `<hr />').

   * `my $tagname = $tag->tag;'

     Returns the name of the HTML element.

          print $name->tag;  # 'a'

Methods for `YAPE::HTML::closetag'
----------------------------------

   This class represents closing tags.  Object has the following methods:

   * `my $tag = YAPE::HTML::closetag->new($name);'

     Creates a `YAPE::HTML::closetag' object.  Takes one argument: the
     name of the HTML element.  These objects are never included in the
     HTML tree structure, since the parser uses the `CLOSED' attribute of
     an `opentag' object to figure out if there needs to be a closing tag.
     However, they are returned in the parsing stage so that you know
     when they've been reached.

          my $close = YAPE::HTML::closetag->new('a');

   * `my $str = $tag->string;'

     Creates a string representation of the closing tag.

          print $close->string;  # '</a>'

   * `my $tagname = $tag->tag;'

     Returns the name of the HTML element.

          print $close->tag;  # 'a'

Methods for `YAPE::HTML::text'
------------------------------

   This class represents blocks of plain text.  Objects have the following
methods:

   * `my $text = YAPE::HTML::text->new($content);'

     Creates a `YAPE::HTML::text' object.  Takes one argument: the text of
     the block.

          my $para = YAPE::HTML::text->new(<< "END");
          Perl is not an acronym -- rather "Practical Extraction
          and Report Language" was developed after the fact.
          END

Methods for `YAPE::HTML::comment'
---------------------------------

   This class represents comments.  Objects have the following methods:

   * `my $comment = YAPE::HTML::comment->new($content);'

     Creates a `YAPE::HTML::comment' object.  Takes one argument: the text
     of the comment.

          my $todo = YAPE::HTML::comment->new(<< "END");
          This table should be formatted differently.
          END

   * `my $str = $comment->string;'

     Creates a string representation of the comment, with `<!--' before
     it, and `-->' after it.

          print $todo->string;
          # <!--This table should be formatted differently-->

Methods for `YAPE::HTML::dtd'
-----------------------------

   This class represents `<!DOCTYPE>' tags.  Objects have the following
methods:

   * `my $dtd = YAPE::HTML::dtd->new(\@fields);'

     Creates a `YAPE::HTML::dtd' object.  Takes one argument: an array
     reference of the four fields (should be two unquoted strings, and two
     quoted strings (?)).

          my $dtd = YAPE::HTML::dtd->new([
            'HTML',
            'PUBLIC',
            '"-//W3C//DTD HTML 4.01//EN"',
            '"http://www.w3.org/TR/html4/strict.dtd"'
          ]);

   * `my $str = $dtd->string;'

     Creates a string representation of the DTD.

          print $dtd->string;
          # (line breaks added for readability)
          # <!DOCTYPE HTML PUBLIC
          #   "-//W3C//DTD HTML 4.01//EN"
          #   "http://www.w3.org/TR/html4/strict.dtd">

   * `my @attrs = $dtd->get_attrs;'

     Returns the four attributes of the DTD.

   * `$dtd->set_attrs(@attrs);'

     Sets the four attributes of the DTD (can't be done piecemeal).

Methods for `YAPE::HTML::pi'
----------------------------

   This class represents process instruction tags.  Objects have the
following methods:

   * `my $pi = YAPE::HTML::pi->new($name, $attr);'

     Creates a `YAPE::HTML::pi' object.  Takes two arguments: the name of
     the processing instruction, and a hash reference of attribute-value
     pairs.  The attribute hash reference must have the keys in lowercase
     text.

          my $attr = { order => 'alphabetical', need => 'examples' };
          my $pi = YAPE::HTML::pi->new(sample => $attr);

   * `my $str = $pi->string;'

     Creates a string representation of the processing instruction.

          print $pi->string;
          # <?sample need="examples" order="alphabetical"?>

   * `my $attr = $pi->get_attr($name);'

   * `my @attrs = $pi->get_attr(@names);'

   * `my %attrs = $pi->get_attr;'

   * `my $attr = $pi->has_attr($name);'

   * `my @attrs = $pi->has_attr(@names);'

   * `$pi->set_attr(%pairs);'

   * `$pi->rem_attr(@names);'

     See the identical methods for `opentag' objects above.

   * `my $name = $pi->name;'

     Returns the name of the processing instruction.

          print $pi->name;  # 'first'

Methods for `YAPE::HTML::ssi'
-----------------------------

   This class represents server-side includes.  Objects have the following
methods:

   * `my $ssi = YAPE::HTML::ssi->new($name, $attr);'

     Creates a `YAPE::HTML::ssi' object.  Takes two arguments: the SSI
     command, and a hash reference of attribute-value pairs.  The
     attribute hash reference must have the keys in lowercase text.

          my $attr = { var => 'REMOTE_HOST' };
          my $ssi = YAPE::HTML::ssi->new(echo => $attr);

   * `my $str = $ssi->string;'

     Creates a string representation of the processing instruction.

          print $ssi->string;
          # <!--#echo var="REMOTE_HOST"-->

   * `my $attr = $ssi->get_attr($name);'

   * `my @attrs = $ssi->get_attr(@names);'

   * `my %attrs = $ssi->get_attr;'

   * `my $attr = $ssi->has_attr($name);'

   * `my @attrs = $ssi->has_attr(@names);'

   * `$ssi->set_attr(%pairs);'

   * `$ssi->rem_attr(@names);'

     See the identical methods for `opentag' objects above.

   * `my $command = $ssi->command;'

     Returns the SSI command's name.

          print $ssi->command;  # 'echo'

CAVEATS
=======

   The `<script>' and `<xmp>' tags are given special treatment.  When they
are encountered, all text up to the first occurrence of the appropriate
closing tag is taken as plain text.

   Tag attributes are displayed in the default `sort()' order.

TO DO
=====

   This is a listing of things to add to future versions of this module.

   * SSI commands if, `elif', and else

     These need to contain content, since the text between them is
     associated with a given condition.

BUGS
====

   Following is a list of known or reported bugs.

   * This documentation might be incomplete.

SUPPORT
=======

   Visit `YAPE''s web site at `http://www.pobox.com/~japhy/YAPE/'.

SEE ALSO
========

   The `YAPE::HTML::Element' documentation, for information on the node
classes.

AUTHOR
======

     Jeff "japhy" Pinyan
     CPAN ID: PINYAN
     japhy@pobox.com
     http://www.pobox.com/~japhy/

Yet Another Parser/Extractor for Regular Expressions
****************************************************

NAME
====

   YAPE::Regex - Yet Another Parser/Extractor for Regular Expressions

SYNOPSIS
========

     use YAPE::Regex;
     use strict;

     my $regex = qr/reg(ular\s+)?exp?(ression)?/i;
     my $parser = YAPE::Regex->new($regex);

     # here is the tokenizing part
     while (my $chunk = $parser->next) {
       # ...
     }

`YAPE' MODULES
==============

   The `YAPE' hierarchy of modules is an attempt at a unified means of
parsing and extracting content.  It attempts to maintain a generic
interface, to promote simplicity and reusability.  The API is powerful,
yet simple.  The modules do tokenization (which can be intercepted) and
build trees, so that extraction of specific nodes is doable.

DESCRIPTION
===========

   This module is yet another (?) parser and tree-builder for Perl regular
expressions.  It builds a tree out of a regex, but at the moment, the
extent of the extraction tool for the tree is quite limited (see
`Extracting Sections' in this node).  However, the tree can be useful to
extension modules.

USAGE
=====

   In addition to the base class, `YAPE::Regex', there is the auxiliary
class `YAPE::Regex::Element' (common to all `YAPE' base classes) that
holds the individual nodes' classes.  There is documentation for the node
classes in that module's documentation.

Methods for `YAPE::Regex'
-------------------------

   * `use YAPE::Regex;'

   * `use YAPE::Regex qw( MyExt::Mod );'

     If supplied no arguments, the module is loaded normally, and the node
     classes are given the proper inheritence (from
     `YAPE::Regex::Element').  If you supply a module (or list of
     modules), import will automatically include them (if needed) and set
     up *their* node classes with the proper inheritence - that is, it
     will append `YAPE::Regex' to `@MyExt::Mod::ISA', and
     `YAPE::Regex::xxx' to each node class's `@ISA' (where `xxx' is the
     name of the specific node class).

          package MyExt::Mod;
          use YAPE::Regex 'MyExt::Mod';

          # @MyExt::Mod::ISA = 'YAPE::Regex'
          # @MyExt::Mod::text::ISA = 'YAPE::Regex::text'
          # ...

   * `my $p = YAPE::Regex->new($REx);'

     Creates a `YAPE::Regex' object, using the contents of `$REx' as a
     regular expression.  The new method will *attempt* to convert `$REx'
     to a compiled regex (using `qr//') if `$REx' isn't already one.  If
     there is an error in the regex, this will fail, but the parser will
     pretend it was ok.  It will then report the bad token when it gets to
     it, in the course of parsing.

   * `my $text = $p->chunk($len);'

     Returns the next `$len' characters in the input string; `$len'
     defaults to 30 characters.  This is useful for figuring out why a
     parsing error occurs.

   * `my $done = $p->done;'

     Returns true if the parser is done with the input string, and false
     otherwise.

   * `my $errstr = $p->error;'

     Returns the parser error message.

   * `my $backref = $p->extract;'

     Returns a code reference that returns the next back-reference in the
     regex.  For more information on enhancements in upcoming versions of
     this module, check `Extracting Sections' in this node.

   * `my $node = $p->display(...);'

     Returns a string representation of the entire content.  It calls the
     parse method in case there is more data that has not yet been parsed.
     This calls the `fullstring' method on the root nodes.  Check the
     `YAPE::Regex::Element' docs on the arguments to `fullstring'.

   * `my $node = $p->next;'

     Returns the next token, or undef if there is no valid token.  There
     will be an error message (accessible with the error method) if there
     was a problem in the parsing.

   * `my $node = $p->parse;'

     Calls next until all the data has been parsed.

   * `my $node = $p->root;'

     Returns the root node of the tree structure.

   * `my $state = $p->state;'

     Returns the current state of the parser.  It is one of the following
     values: alt, anchor, any, backref, `capture(N)', class, close, code,
     comment, `cond(TYPE)', `ctrl', cut, done, error, flags, group, hex,
     `later', `lookahead(neg|pos)', `lookbehind(neg|pos)', macro, oct,
     `slash', and text.

     For `capture(N)', N will be the number the captured pattern
     represents.

     For `cond(TYPE)', TYPE will either be a number representing the
     back-reference that the conditional depends on, or the string assert.

     For lookahead and `lookbehind', one of neg and pos will be there,
     depending on the type of assertion.

   * `my $node = $p->top;'

     Synonymous to root.

Extracting Sections
-------------------

   While extraction of nodes is the goal of the `YAPE' modules, the author
is at a loss for words as to what needs to be extracted from a regex.  At
the current time, all the extract method does is allow you access to the
regex's set of back-references:

     my $extor = $parser->extract;
     while (my $backref = $extor->()) {
       # ...
     }

   `japhy' is very open to suggestions as to the approach to node
extraction (in how the API should look, in addition to what should be
proffered).  Preliminary ideas include extraction keywords like the output
of *-Dr* (or the re module's debug option).

   The `YAPE::Regex::Wasted' extension module, which suggests that regexes
like `/(.*?):/' be changed to `/([^:]*):/' (and their ilk), could make use
of an extraction technique that lets the user detect a node of `.*?'
followed by a constant string or character class.

EXTENSIONS
==========

   * `YAPE::Regex::Explain' 2.00

     Presents an explanation of a regular expression, node by node.

   * `YAPE::Regex::Reverse' (Not released)

     Reverses the nodes of a regular expression.

   * `YAPE::Regex::Wasted' (Not released)

     Points out wasted `/s' and `/m' modifiers, and tries to suggest
     replacements for `.*?' nodes.

TO DO
=====

   This is a listing of things to add to future versions of this module.

API
---

   * Create a robust extract method

     Open to suggestions.

Internals
---------

   * Add Perl 5.6 character class support

     The new character class syntaces, `[:posix:]' and `\p{UniCode}',
     aren't yet supported.  These might be class objects, or have their
     own classes (`posix_class' and `unicode_class').

BUGS
====

   Following is a list of known or reported bugs.

Pending
-------

   * NONE!

SUPPORT
=======

   Visit `YAPE''s web site at `http://www.pobox.com/~japhy/YAPE/'.

SEE ALSO
========

   The `YAPE::Regex::Element' documentation, for information on the node
classes.  Also, `Text::Balanced', Damian Conway's excellent module, used
for

AUTHOR
======

     Jeff "japhy" Pinyan
     CPAN ID: PINYAN
     japhy@pobox.com
     http://www.pobox.com/~japhy/

sub-classes for YAPE::Regex elements
************************************

NAME
====

   YAPE::Regex::Element - sub-classes for YAPE::Regex elements

SYNOPSIS
========

     use YAPE::Regex 'MyExt::Mod';
     # this sets up inheritence in MyExt::Mod
     # see YAPE::Regex documentation

`YAPE' MODULES
==============

   The `YAPE' hierarchy of modules is an attempt at a unified means of
parsing and extracting content.  It attempts to maintain a generic
interface, to promote simplicity and reusability.  The API is powerful,
yet simple.  The modules do tokenization (which can be intercepted) and
build trees, so that extraction of specific nodes is doable.

DESCRIPTION
===========

   This module provides the classes for the `YAPE::Regex' objects.  The
base class for these objects is `YAPE::Regex::Element'.  The objects
classes are numerous.

Methods for `YAPE::Regex::Element'
----------------------------------

   This class contains fallback methods for the other classes.

   * `my $str = $obj->text;'

     Returns a string representation of the content of the regex node
     *itself*, not any nodes contained in it.  This is undef for non-text
     nodes.

   * `my $str = $obj->string;'

     Returns a string representation of the regex node *itself*, not any
     nodes contained in it.

   * `my $str = $obj->fullstring;'

     Returns a string representation of the regex node, including any
     nodes contained in it.

   * `my $quant = $obj->quant;'

     Returns a string with the quantity, and a ? if the node is
     non-greedy.  The quantity is one of *, +, ?, `{*M*,*N*}', or an empty
     string.

   * `my $ng = $obj->ngreed;'

     Returns a ? if the node is non-greedy, and an empty string otherwise.

Methods for `YAPE::Regex::anchor'
---------------------------------

   This class represents anchors.  Objects have the following methods:

   * `my $anchor = YAPE::Regex::anchor->new($type,$q,$ng);'

     Creates a `YAPE::Regex::anchor' object.  Takes three arguments:  the
     anchor (^, `\A', `$', `\Z', `\z', `\B', `\b', or `\G'), the quantity,
     and the non-greedy flag.  The quantity should be an empty string.

          my $anc = YAPE::Regex::anchor->new('\A', '', '?');
          # /\A?/

   * `my $type = $anchor->type;'

     Returns the string anchor.

Methods for `YAPE::Regex::macro'
--------------------------------

   This class represents character-class macros.  Objects have the
following methods:

   * `my $macro = YAPE::Regex::macro->new($type,$q,$ng);'

     Creates a `YAPE::Regex::macro' object.  Takes three arguments:  the
     macro (w, W, d, D, s, or S), the quantity, and the non-greedy flag.

          my $macro = YAPE::Regex::macro->new('s', '{3,5}');
          # /\s{3,5}/

   * `my $text = $macro->text;'

     Returns the macro.

          print $macro->text;  # '\s'

   * `my $type = $macro->type;'

     Returns the string macro.

Methods for `YAPE::Regex::oct'
------------------------------

   This class represents octal escapes.  Objects have the following
methods:

   * `my $oct = YAPE::Regex::oct->new($type,$q,$ng);'

     Creates a `YAPE::Regex::oct' object.  Takes three arguments:  the
     octal number (as a string), the quantity, and the non-greedy flag.

          my $oct = YAPE::Regex::oct->new('040');
          # /\040/

   * `my $text = $oct->text;'

     Returns the octal escape.

          print $oct->text;  # '\040'

   * `my $type = $oct->type;'

     Returns the string oct.

Methods for `YAPE::Regex::hex'
------------------------------

   This class represents hexadecimal escapes.  Objects have the following
methods:

   * `my $hex = YAPE::Regex::hex->new($type,$q,$ng);'

     Creates a `YAPE::Regex::hex' object.  Takes three arguments:  the
     hexadecimal number (as a string), the quantity, and the non-greedy
     flag.

          my $hex = YAPE::Regex::hex->new('20','{2,}');
          # /\x20{2,}/

   * `my $text = $hex->text;'

     Returns the hexadecimal escape.

          print $hex->text;  # '\x20'

   * `my $type = $hex->type;'

     Returns the string hex.

Methods for `YAPE::Regex::backref'
----------------------------------

   This class represents back-references.  Objects have the following
methods:

   * `my $bref = YAPE::Regex::bref->new($type,$q,$ng);'

     Creates a `YAPE::Regex::bref' object.  Takes three arguments:  the
     number of the back-reference, the quantity, and the non-greedy flag.

          my $bref = YAPE::Regex::bref->new(2,'','?');
          # /\2?/

   * `my $text = $bref->text;'

     Returns the backescape.

          print $bref->text;  # '\2'

   * `my $type = $bref->type;'

     Returns the string backref.

Methods for `YAPE::Regex::ctrl'
-------------------------------

   This class represents control character escapes.  Objects have the
following methods:

   * `my $ctrl = YAPE::Regex::ctrl->new($type,$q,$ng);'

     Creates a `YAPE::Regex::ctrl' object.  Takes three arguments:  the
     control character, the quantity, and the non-greedy flag.

          my $ctrl = YAPE::Regex::ctrl->new('M');
          # /\cM/

   * `my $text = $ctrl->text;'

     Returns the control character escape.

          print $hex->text;  # '\cM'

   * `my $type = $ctrl->type;'

     Returns the string `ctrl'.

Methods for `YAPE::Regex::slash'
--------------------------------

   This class represents any other escaped characters.  Objects have the
following methods:

   * `my $slash = YAPE::Regex::slash->new($type,$q,$ng);'

     Creates a `YAPE::Regex::slash' object.  Takes three arguments:  the
     backslashed character, the quantity, and the non-greedy flag.

          my $slash = YAPE::Regex::slash->new('t','','?');
          # /\t?/

   * `my $text = $slash->text;'

     Returns the escaped character.

          print $slash->text;  # '\t'

   * `my $type = $slash->type;'

     Returns the string `slash'.

Methods for `YAPE::Regex::any'
------------------------------

   This class represents the dot metacharacter.  Objects have the
following methods:

   * `my $any = YAPE::Regex::any->new($q,$ng);'

     Creates a `YAPE::Regex::any' object.  Takes two arguments:  the
     quantity, and the non-greedy flag.

          my $any = YAPE::Regex::any->new('{1,3}');
          # /.{1,3}/

   * `my $type = $any->type;'

     Returns the string any.

Methods for `YAPE::Regex::class'
--------------------------------

   This class represents character classes.  Objects have the following
methods:

   * `my $class = YAPE::Regex::class->new($chars,$neg,$q,$ng);'

     Creates a `YAPE::Regex::class' object.  Takes four arguments:  the
     characters in the class, a ^ if the class is negated (an empty string
     otherwise), the quantity, and the non-greedy flag.

          my $class = YAPE::Regex::class->new('aeiouy','^');
          # /[^aeiouy]/

   * `my $text = $class->text;'

     Returns the character class.

          print $class->text;  # [^aeiouy]

   * `my $type = $class->type;'

     Returns the string class.

Methods for `YAPE::Regex::hex'
------------------------------

   This class represents hexadecimal escapes.  Objects have the following
methods:

   * `my $text = YAPE::Regex::text->new($text,$q,$ng);'

     Creates a `YAPE::Regex::text' object.  Takes three arguments:  the
     text, the quantity, and the non-greedy flag.  The quantity and
     non-greedy modifier should only be present for *single-character*
     text, because of the way the parser renders the quantity and
     non-greedy modifier.

          my $text = YAPE::Regex::text->new('alphabet','');
          # /alphabet/

          my $text = YAPE::Regex::text->new('x','?','?');
          # /x??/

   * `my $type = $text->type;'

     Returns the string text.

Methods for `YAPE::Regex::alt'
------------------------------

   This class represents alternation.  Objects have the following methods:

   * `my $alt = YAPE::Regex::alt->new;'

     Creates a `YAPE::Regex::alt' object.

          my $alt = YAPE::Regex::alt->new;
          # /|/

   * `my $type = $oct->type;'

     Returns the string alt.

Methods for `YAPE::Regex::comment'
----------------------------------

   This class represents in-line comments.  Objects have the following
methods:

   * `my $comment = YAPE::Regex::comment->new($comment,$x);'

     Creates a `YAPE::Regex::comment' object.  Takes two arguments:  the
     text of the comment, and whether or not the `/x' regex modifier is in
     effect for this comment.  Note that Perl's regex engine will stop a
     `(?#...)' comment at the first ), regardless of what you do.

          my $comment = YAPE::Regex::comment->new(
            "match an optional string of digits"
          );
          # /(?#match an optional string of digits)/

          my $comment = YAPE::Regex::comment->new(
            "match an optional string of digits",
            1
          );
          # /# match an optional string of digits/

   * `my $type = $comment->type;'

     Returns the string comment.

   * `my $x_on = $comment->xcomm;'

     Returns true or false, depending on whether the comment is under the
     `/x' regex modifier.

Methods for `YAPE::Regex::whitespace'
-------------------------------------

   This class represents whitespace under the `/x' regex modifier.
Objects have the following methods:

   * `my $ws = YAPE::Regex::whitespace->new($text);'

     Creates a `YAPE::Regex::whitespace' object.  Takes one argument:  the
     text of the whitespace.

          my $ws = YAPE::Regex::whitespace->new('  ');
          # /  /x

   * `my $text = $ws->text;'

     Returns the whitespace.

          print $ws->text;  # '  '

   * `my $type = $ws->type;'

     Returns the string `whitespace'.

Methods for `YAPE::Regex::flags'
--------------------------------

   This class represents `(?ismx)' flags.  Objects have the following
methods:

   * `my $flags = YAPE::Regex::flags->new($add,$sub);'

     Creates a `YAPE::Regex::flags' object.  Takes two arguments:  a
     string of the modes to have on, and a string of the modes to
     explicitly turn off.  The flags are displayed in alphabetical order.

          my $flags = YAPE::Regex::flags->new('is','m');
          # /(?is-m)/

   * `my $type = $flags->type;'

     Returns the string flags.

Methods for `YAPE::Regex::cut'
------------------------------

   This class represents the cut assertion.  Objects have the following
methods:

   * `my $look = YAPE::Regex::cut->new(\@nodes);'

     Creates a `YAPE::Regex::cut' object.  Takes one arguments:  a
     reference to an array of objects to be contained in the cut.

          my $REx = YAPE::Regex::class->new('aeiouy','','+');
          my $look = YAPE::Regex::cut->new(0,[$REx]);
          # /(?>[aeiouy]+)/

   * `my $type = $cut->type;'

     Returns the string cut.

Methods for `YAPE::Regex::lookahead'
------------------------------------

   This class represents lookaheads.  Objects have the following methods:

   * `my $look = YAPE::Regex::lookahead->new($pos,\@nodes);'

     Creates a `YAPE::Regex::lookahead' object.  Takes two arguments:  a
     boolean value indicating whether or not the lookahead is positive,
     and a reference to an array of objects to be contained in the
     lookahead.

          my $REx = YAPE::Regex::class->new('aeiouy');
          my $look = YAPE::Regex::lookahead->new(0,[$REx]);
          # /(?![aeiouy])/

   * `my $pos = $look->pos;'

     Returns true if the lookahead is positive.

          print $look->pos ? 'pos' : 'neg';  # 'neg'

   * `my $type = $look->type;'

     Returns the string `lookahead(pos)' or `lookahead(neg)'.

Methods for `YAPE::Regex::lookbehind'
-------------------------------------

   This class represents lookbehinds.  Objects have the following methods:

   * `my $look = YAPE::Regex::lookbehind->new($pos,\@nodes);'

     Creates a `YAPE::Regex::lookbehind' object.  Takes two arguments:  a
     boolean value indicating whether or not the lookbehind is positive,
     and a reference to an array of objects to be contained in the
     lookbehind.

          my $REx = YAPE::Regex::class->new('aeiouy','^');
          my $look = YAPE::Regex::lookbehind->new(1,[$REx]);
          # /(?<=[^aeiouy])/

   * `my $pos = $look->pos;'

     Returns true if the lookbehind is positive.

          print $look->pos ? 'pos' : 'neg';  # 'pos'

   * `my $type = $look->type;'

     Returns the string `lookbehind(pos)' or `lookbehind(neg)'.

Methods for `YAPE::Regex::conditional'
--------------------------------------

   This class represents conditionals.  Objects have the following methods:

   * `my $cond = YAPE::Regex::conditional->new($br,$t,$f,$q,$ng);'

     Creates a `YAPE::Regex::hex' object.  Takes five arguments:  the
     number of the back-reference (that's all that's supported in the
     current version), an array reference to the "true" pattern, an array
     reference to the "false" pattern, and the quantity and non-greedy
     flag.

          my $cond = YAPE::Regex::conditional->new(
            2,
            [],
            [ YAPE::Regex::text->new('foo') ],
            '?',
          );
          # /(?(2)|foo)?/

   * `my $br = $cond->backref;'

     Returns the number of the back-reference the conditional depends on.

          print $br->backref;  # 2

   * `my $type = $cond->type;'

     Returns the string `conditional(*N*)', where N is the number of the
     back-reference.

Methods for `YAPE::Regex::group'
--------------------------------

   This class represents non-capturing groups.  Objects have the following
methods:

   * `my $group = YAPE::Regex::group->new($on,$off,\@nodes,$q,$ng);'

     Creates a `YAPE::Regex::group' object.  Takes five arguments:  the
     modes turned on, the modes explicitly turned off, a reference to an
     array of objects in the group, the quantity, and the non-greedy flag.
     The modes are displayed in alphabetical order.

          my $group = YAPE::Regex::group->new(
            'i',
            's',
            [
              YAPE::Regex::macro->new('d', '{2}'),
              YAPE::Regex::macro->new('s'),
              YAPE::Regex::macro->new('d', '{2}'),
            ],
            '?',
          );
          # /(?i-s:\d{2}\s\d{2})?/

   * `my $type = $group->type;'

     Returns the string group.

Methods for `YAPE::Regex::capture'
----------------------------------

   This class represents capturing groups.  Objects have the following
methods:

   * `my $capture = YAPE::Regex::capture->new(\@nodes,$q,$ng);'

     Creates a `YAPE::Regex::capture' object.  Takes three arguments:  a
     reference to an array of objects in the group, the quantity, and the
     non-greedy flag.

          my $capture = YAPE::Regex::capture->new(
            [
              YAPE::Regex::macro->new('d', '{2}'),
              YAPE::Regex::macro->new('s'),
              YAPE::Regex::macro->new('d', '{2}'),
            ],
          );
          # /(\d{2}\s\d{2})/

   * `my $type = $capture->type;'

     Returns the string `capture'.

Methods for `YAPE::Regex::code'
-------------------------------

   This class represents code blocks.  Objects have the following methods:

   * `my $code = YAPE::Regex::code->new($block);'

     Creates a `YAPE::Regex::code' object.  Takes one arguments:  a string
     holding a block of code.

          my $code = YAPE::Regex::code->new(q({ push @poss, $1 }));
          # /(?{ push @poss, $1 })/

   * `my $type = $code->type;'

     Returns the string code.

Methods for `YAPE::Regex::later'
--------------------------------

   This class represents closed parentheses.  Objects have the following
methods:

   * `my $later = YAPE::Regex::later->new($block);'

     Creates a `YAPE::Regex::later' object.  Takes one arguments:  a
     string holding a block of code.

          my $later = YAPE::Regex::later->new(q({ push @poss, $1 }));
          # /(?{{ push @poss, $1 }})/

   * `my $type = $later->type;'

     Returns the string `later'.

Methods for `YAPE::Regex::close'
--------------------------------

   This class represents closed parentheses.  Objects have the following
methods:

   * `my $close = YAPE::Regex::close->new($q,$ng);'

     Creates a `YAPE::Regex::close' object.  Takes two arguments:  the
     quantity, and the non-greedy flag.  This object is never needed in
     the tree; however, they are returned in the parsing stage, so that
     you know when they've been reached.

          my $close = YAPE::Regex::close->new('?','?');
          # /)??/

   * `my $type = $close->type;'

     Returns the string close.

TO DO
=====

   This is a listing of things to add to future versions of this module.

   * Perl 5.6 extended character classes

     The POSIX and Unicode character class extensions are not yet
     supported.

BUGS
====

   Following is a list of known or reported bugs.

   * This documentation might be incomplete.

SUPPORT
=======

   Visit `YAPE''s web site at `http://www.pobox.com/~japhy/YAPE/'.

SEE ALSO
========

   The `YAPE::Regex' documentation, for information on the main class.

AUTHOR
======

     Jeff "japhy" Pinyan
     CPAN ID: PINYAN
     japhy@pobox.com
     http://www.pobox.com/~japhy/

explanation of a regular expression
***********************************

NAME
====

   YAPE::Regex::Explain - explanation of a regular expression

SYNOPSIS
========

     use YAPE::Regex::Explain;
     my $exp = YAPE::Regex::Explain->new($REx)->explain;

`YAPE' MODULES
==============

   The `YAPE' hierarchy of modules is an attempt at a unified means of
parsing and extracting content.  It attempts to maintain a generic
interface, to promote simplicity and reusability.  The API is powerful,
yet simple.  The modules do tokenization (which can be intercepted) and
build trees, so that extraction of specific nodes is doable.

DESCRIPTION
===========

   This module merely sub-classes `YAPE::Regex', and produces a rather
verbose explanation of a regex, suitable for demonstration and tutorial
purposes.

Methods for `YAPE::Regex::Explain'
----------------------------------

   * `my $p = YAPE::Regex::Explain->new($regex);'

     Calls `YAPE::Regex''s new method (see its docs).

   * `my $p = YAPE::Regex::Explain->explain($mode);'

     Returns a string explaining the regex.  If $mode is regex, it will
     output a valid regex (instead of the normal string).  If $mode is
     silent, no comments will be added, but the regex will be expanded
     into a readable format.

SUPPORT
=======

   Visit `YAPE''s web site at `http://www.pobox.com/~japhy/YAPE/'.

SEE ALSO
========

   The `YAPE::Regex' documentation.

AUTHOR
======

     Jeff "japhy" Pinyan
     CPAN ID: PINYAN
     japhy@pobox.com
     http://www.pobox.com/~japhy/

get/set subroutine or variable attributes
*****************************************

NAME
====

   attributes - get/set subroutine or variable attributes

SYNOPSIS
========

     sub foo : method ;
     my ($x,@y,%z) : Bent ;
     my $s = sub : method { ... };

     use attributes ();	# optional, to get subroutine declarations
     my @attrlist = attributes::get(\&foo);

     use attributes 'get'; # import the attributes::get subroutine
     my @attrlist = get \&foo;

DESCRIPTION
===========

   Subroutine declarations and definitions may optionally have attribute
lists associated with them.  (Variable my declarations also may, but see
the warning below.)  Perl handles these declarations by passing some
information about the call site and the thing being declared along with
the attribute list to this module.  In particular, the first example above
is equivalent to the following:

     use attributes __PACKAGE__, \&foo, 'method';

   The second example in the synopsis does something equivalent to this:

     use attributes __PACKAGE__, \$x, 'Bent';
     use attributes __PACKAGE__, \@y, 'Bent';
     use attributes __PACKAGE__, \%z, 'Bent';

   Yes, that's three invocations.

   WARNING: attribute declarations for variables are an *experimental*
feature.  The semantics of such declarations could change or be removed in
future versions.  They are present for purposes of experimentation with
what the semantics ought to be.  Do not rely on the current implementation
of this feature.

   There are only a few attributes currently handled by Perl itself (or
directly by this module, depending on how you look at it.)  However,
package-specific attributes are allowed by an extension mechanism.  (See
`"Package-specific Attribute Handling"' in this node below.)

   The setting of attributes happens at compile time.  An attempt to set
an unrecognized attribute is a fatal error.  (The error is trappable, but
it still stops the compilation within that eval.)  Setting an attribute
with a name that's all lowercase letters that's not a built-in attribute
(such as "foo") will result in a warning with -w or `use warnings
'reserved''.

Built-in Attributes
-------------------

   The following are the built-in attributes for subroutines:

locked
     Setting this attribute is only meaningful when the subroutine or
     method is to be called by multiple threads.  When set on a method
     subroutine (i.e., one marked with the method attribute below), Perl
     ensures that any invocation of it implicitly locks its first argument
     before execution.  When set on a non-method subroutine, Perl ensures
     that a lock is taken on the subroutine itself before execution.  The
     semantics of the lock are exactly those of one explicitly taken with
     the lock operator immediately after the subroutine is entered.

method
     Indicates that the referenced subroutine is a method.  This has a
     meaning when taken together with the locked attribute, as described
     there.  It also means that a subroutine so marked will not trigger
     the "Ambiguous call resolved as CORE::%s" warning.

lvalue
     Indicates that the referenced subroutine is a valid lvalue and can be
     assigned to. The subroutine must return a modifiable value such as a
     scalar variable, as described in Perlsub (perl.info).

   There are no built-in attributes for anything other than subroutines.

Available Subroutines
---------------------

   The following subroutines are available for general use once this module
has been loaded:

get
     This routine expects a single parameter-a reference to a subroutine
     or variable.  It returns a list of attributes, which may be empty.
     If passed invalid arguments, it uses die() (via `Carp::croak|Carp' in
     this node) to raise a fatal exception.  If it can find an appropriate
     package name for a class method lookup, it will include the results
     from a `FETCH_*type*_ATTRIBUTES' call in its return list, as
     described in `"Package-specific Attribute Handling"' in this node
     below.  Otherwise, only `built-in attributes|"Built-in Attributes"'
     in this node will be returned.

reftype
     This routine expects a single parameter-a reference to a subroutine or
     variable.  It returns the built-in type of the referenced variable,
     ignoring any package into which it might have been blessed.  This can
     be useful for determining the type value which forms part of the
     method names described in `"Package-specific Attribute Handling"' in
     this node below.

   Note that these routines are not exported by default.

Package-specific Attribute Handling
-----------------------------------

   WARNING: the mechanisms described here are still experimental.  Do not
rely on the current implementation.  In particular, there is no provision
for applying package attributes to 'cloned' copies of subroutines used as
closures.  (See `"Making References"', see Perlref (perl.info),
for information on closures.)  Package-specific attribute handling may
change incompatibly in a future release.

   When an attribute list is present in a declaration, a check is made to
see whether an attribute 'modify' handler is present in the appropriate
package (or its @ISA inheritance tree).  Similarly, when `attributes::get'
is called on a valid reference, a check is made for an appropriate
attribute 'fetch' handler.  See `"EXAMPLES"' in this node to see how the
"appropriate package" determination works.

   The handler names are based on the underlying type of the variable being
declared or of the reference passed.  Because these attributes are
associated with subroutine or variable declarations, this deliberately
ignores any possibility of being blessed into some package.  Thus, a
subroutine declaration uses "CODE" as its type, and even a blessed hash
reference uses "HASH" as its type.

   The class methods invoked for modifying and fetching are these:

FETCH_type_ATTRIBUTES
     This method receives a single argument, which is a reference to the
     variable or subroutine for which package-defined attributes are
     desired.  The expected return value is a list of associated
     attributes.  This list may be empty.

MODIFY_type_ATTRIBUTES
     This method is called with two fixed arguments, followed by the list
     of attributes from the relevant declaration.  The two fixed arguments
     are the relevant package name and a reference to the declared
     subroutine or variable.  The expected return value as a list of
     attributes which were not recognized by this handler.  Note that this
     allows for a derived class to delegate a call to its base class, and
     then only examine the attributes which the base class didn't already
     handle for it.

     The call to this method is currently made *during* the processing of
     the declaration.  In particular, this means that a subroutine
     reference will probably be for an undefined subroutine, even if this
     declaration is actually part of the definition.

   Calling `attributes::get()' from within the scope of a null package
declaration `package ;' for an unblessed variable reference will not
provide any starting package name for the 'fetch' method lookup.  Thus,
this circumstance will not result in a method call for package-defined
attributes.  A named subroutine knows to which symbol table entry it
belongs (or originally belonged), and it will use the corresponding
package.  An anonymous subroutine knows the package name into which it was
compiled (unless it was also compiled with a null package declaration),
and so it will use that package name.

Syntax of Attribute Lists
-------------------------

   An attribute list is a sequence of attribute specifications, separated
by whitespace or a colon (with optional whitespace).  Each attribute
specification is a simple name, optionally followed by a parenthesised
parameter list.  If such a parameter list is present, it is scanned past
as for the rules for the `q()' operator.  (See `"Quote and Quote-like
Operators"', see Perlop (perl.info).)  The parameter list is
passed as it was found, however, and not as per `q()'.

   Some examples of syntactically valid attribute lists:

     switch(10,foo(7,3))  :  expensive
     Ugly('\(") :Bad
     _5x5
     locked method

   Some examples of syntactically invalid attribute lists (with
annotation):

     switch(10,foo()		# ()-string not balanced
     Ugly('(')			# ()-string not balanced
     5x5				# "5x5" not a valid identifier
     Y2::north			# "Y2::north" not a simple identifier
     foo + bar			# "+" neither a colon nor whitespace

EXPORTS
=======

Default exports
---------------

   None.

Available exports
-----------------

   The routines get and reftype are exportable.

Export tags defined
-------------------

   The :ALL tag will get all of the above exports.

EXAMPLES
========

   Here are some samples of syntactically valid declarations, with
annotation as to how they resolve internally into `use attributes'
invocations by perl.  These examples are primarily useful to see how the
"appropriate package" is found for the possible method lookups for
package-defined attributes.

  1. Code:

          package Canine;
          package Dog;
          my Canine $spot : Watchful ;

     Effect:

          use attributes Canine => \$spot, "Watchful";

  2. Code:

          package Felis;
          my $cat : Nervous;

     Effect:

          use attributes Felis => \$cat, "Nervous";

  3. Code:

          package X;
          sub foo : locked ;

     Effect:

          use attributes X => \&foo, "locked";

  4. Code:

          package X;
          sub Y::x : locked { 1 }

     Effect:

          use attributes Y => \&Y::x, "locked";

  5. Code:

          package X;
          sub foo { 1 }

          package Y;
          BEGIN { *bar = \&X::foo; }

          package Z;
          sub Y::bar : locked ;

     Effect:

          use attributes X => \&X::foo, "locked";

        This last example is purely for purposes of completeness.  You
should not be trying to mess with the attributes of something in a package
that's not your own.

SEE ALSO
========

   `"Private Variables via my()"', see Perlsub (perl.info), and
`"Subroutine Attributes"', see Perlsub (perl.info), for details
on the basic declarations; `"Subroutine Attributes"', see Attrs,
for the obsolescent form of subroutine attribute specification which this
module replaces; `use', see Perlfunc (perl.info), for details
on the normal invocation mechanism.

set/get attributes of a subroutine (deprecated)
***********************************************

NAME
====

   attrs - set/get attributes of a subroutine (deprecated)

SYNOPSIS
========

     sub foo {
         use attrs qw(locked method);
         ...
     }

     @a = attrs::get(\&foo);

DESCRIPTION
===========

   NOTE: Use of this pragma is deprecated.  Use the syntax

     sub foo : locked method { }

   to declare attributes instead.  See also Attributes.

   This pragma lets you set and get attributes for subroutines.  Setting
attributes takes place at compile time; trying to set invalid attribute
names causes a compile-time error. Calling `attrs::get' on a subroutine
reference or name returns its list of attribute names. Notice that
`attrs::get' is not exported.  Valid attributes are as follows.

method
     Indicates that the invoking subroutine is a method.

locked
     Setting this attribute is only meaningful when the subroutine or
     method is to be called by multiple threads. When set on a method
     subroutine (i.e. one marked with the method attribute above), perl
     ensures that any invocation of it implicitly locks its first argument
     before execution. When set on a non-method subroutine, perl ensures
     that a lock is taken on the subroutine itself before execution. The
     semantics of the lock are exactly those of one explicitly taken with
     the lock operator immediately after the subroutine is entered.

only load modules when they're used
***********************************

NAME
====

   autoload - only load modules when they're used

SYNOPSIS
========

   # For a better example, see CGI3::Object.pm. It uses # autoload.pm in
quite a nice way.

   package MySimpleCookie; use autoload qw(Exporter CGI3::Object::Cookie);

   @ISA = qw(Exporter CGI3::Object::Cookie);  @EXPORT = qw(raw_fetch
cookie raw_cookie);

   # raw_fetch a list of cookies from the environment and # return as a
hash.  The cookie values are not unescaped # or altered in any way.  sub
raw_fetch {     my $raw_cookie = $ENV{HTTP_COOKIE} || $ENV{COOKIE};     my
%results;     my(@pairs) = split("; ",$raw_cookie);     foreach (@pairs) {
       if (/^([^=]+)=(.*)/) {             $results{$1} = $2;         }
    else {             $results{$_} = ";         }     }     return
wantarray ? %results : \%results; }

   my $cookies; sub raw_cookie {     my $name = shift;     if (!$cookies)
{ $cookies = raw_fetch() }     return $cookies->{$name}; }

   package main; # Now, people can use you just for your raw_cookie...
use MySimpleCookie('raw_fetch','raw_cookie'); $result = raw_cookie('blah');

   # And it won't cost 'em a cent. They didn't use any # functions from
CGI3::Object::Cookie, so the module # wasn't loaded.

   # But if they do use the functions, the module will load automatically
package main; use MySimpleCookie('raw_fetch','cookie'); $result =
cookie('blah');

   # Or, if they even did this, the module would load automatically and
work.  package main; use MySimpleCookie; $me = new MySimpleCookie; print
"Set-Cookie: ", $me->raw_cookie('blah'); print "Set-Cookie: ",
$me->cookie('blah');

DESCRIPTION
===========

AUTHOR
======

   David James (david@jamesgang.com)

SEE ALSO
========

   CGI3::Object(1).

postpone load of modules until a function is used
*************************************************

NAME
====

   autouse - postpone load of modules until a function is used

SYNOPSIS
========

     use autouse 'Carp' => qw(carp croak);
     carp "this carp was predeclared and autoused ";

DESCRIPTION
===========

   If the module Module is already loaded, then the declaration

     use autouse 'Module' => qw(func1 func2($;$) Module::func3);

   is equivalent to

     use Module qw(func1 func2);

   if Module defines func2() with prototype `($;$)', and func1() and
func3() have no prototypes.  (At least if Module uses Exporter's import,
otherwise it is a fatal error.)

   If the module Module is not loaded yet, then the above declaration
declares functions func1() and func2() in the current package, and
declares a function Module::func3().  When these functions are called,
they load the package Module if needed, and substitute themselves with the
correct definitions.

WARNING
=======

   Using autouse will move important steps of your program's execution
from compile time to runtime.  This can

   * Break the execution of your program if the module you autoused has
     some initialization which it expects to be done early.

   * hide bugs in your code since important checks (like correctness of
     prototypes) is moved from compile time to runtime.  In particular, if
     the prototype you specified on autouse line is wrong, you will not
     find it out until the corresponding function is executed.  This will
     be very unfortunate for functions which are not always called (note
     that for such functions autouseing gives biggest win, for a workaround
     see below).

   To alleviate the second problem (partially) it is advised to write your
scripts like this:

     use Module;
     use autouse Module => qw(carp($) croak(&$));
     carp "this carp was predeclared and autoused ";

   The first line ensures that the errors in your argument specification
are found early.  When you ship your application you should comment out
the first line, since it makes the second one useless.

AUTHOR
======

   Ilya Zakharevich (ilya@math.ohio-state.edu)

SEE ALSO
========

   perl(1).

Establish IS-A relationship with base class at compile time
***********************************************************

NAME
====

   base - Establish IS-A relationship with base class at compile time

SYNOPSIS
========

     package Baz;
     use base qw(Foo Bar);

DESCRIPTION
===========

   Roughly similar in effect to

     BEGIN {
     	require Foo;
     	require Bar;
     	push @ISA, qw(Foo Bar);
     }

   Will also initialize the %FIELDS hash if one of the base classes has
it.  Multiple inheritance of %FIELDS is not supported.  The 'base' pragma
will croak if multiple base classes have a %FIELDS hash.  See
Fields, for a description of this feature.

   When strict 'vars' is in scope base also let you assign to @ISA without
having to declare @ISA with the 'vars' pragma first.

   If any of the base classes are not loaded yet, base silently requires
them.  Whether to require a base class package is determined by the
absence of a global $VERSION in the base package.  If $VERSION is not
detected even after loading it, <base> will define $VERSION in the base
package, setting it to the string `-1, defined by base.pm'.

HISTORY
=======

   This module was introduced with Perl 5.004_04.

SEE ALSO
========

   See Fields,

how to customise bioperl for your site
**************************************

NAME
====

   bioperl backend - how to customise bioperl for your site

SYNOPSIS
========

   Not really appropiate for a synopsis. Read on

DESCRIPTION
===========

   This document is designed to let you customise bioperl on your site.
Bioperl can work with a number of database formats (at the moment, simple
fasta flat file formats and EMBL/Swissprot .dat format), allowing users to
retrieve sequences from these databases. In addition another layer, above
flat file indexing is provided, allowing sites to retrieve sequences from
GenBank via the web or via flat file indexing, or - if you have the time to
do so, you can write your own interface to an in-house RDB. Using DBI this
should be quite simple.

   Two scripts are provided to get you started with the bioperl backend:

bpfetch
     Fetches sequences from a Database

bpindex
     Builds indexes for flat files databases which are easily accessible
     by bpfetch

   The core of the backend system is found in following modules

   * generic access to databases, whether flat file, web or rdb. At the
     moment, this provides random access retrieval, on the basis of ids or
     accession numbers, but does not provide the ability to loop over the
     entire database, nor does it provide any complex querying ability.

     Bio::DB::BioSeqI is the abstract interface (hence the I) for the
     databases.  Bio::DB::GenBank and Bio::DB::GenPept are concrete
     implementations for network access to the GenBank and GenPept
     databases held at NCBI, using http as a protocol.

   * flat file indexing system, for read-only, flat file distributions.
     These provide for specific instances generic type access, but the
     underlying machinery can be customised for any number of different
     flat file systems.

     The Index modules EMBL and Fasta, as they are designed as Sequence
     databases conform to the Bio::DB::BioSeqI interface, meaning they can
     be used whereever the Bio::DB::BioSeqI is expected.

   * conversion systems for Bio::Seq objects, either to or from sequence
     streams. The move of things into SeqIO prevents the Bio::Seq object
     bloating up with format code, and the SeqIO system has the benefit of
     being very easy to extend to new formats.

SETTING UP BIOPERL INDICES
==========================

   If you want to use the bioperl indexing of fasta and embl/swissprot
.dat files then the bpfetch and bpindex scripts are great ways to start
off (and also reading the scripts shows you how to use the bioperl
indexing stuff). bpfetch and bpindex coordinate by the use of two
environment variables

     BIOPERL_INDEX - directory where the indices are kept

     BIOPERL_INDEX_TYPE - type of DBM file to use for the index

   The basic way of indexing a database, once BIOPERL_INDEX has been set
up, is to go

     bpindex <index-name> <filenames as full path>

   eg, for Fasta files

     bpindex est /nfs/somewhere/fastafiles/est*.fa

   Or, for embl/swissprot files

   bpindex -fmt=EMBL swiss /nfs/somewhere/swiss/swissprot.dat

   To retrieve sequences from the index go

     bpfetch <index-name>:<id>

   eg,

     bpfetch est:AA01234

   or

     bpfetch swiss:VAV_HUMAN

   bpfetch has other options to connect to genbank across the network.

CHECKLIST
=========

     make a directory called /nfs/datadisk/bioperlindex/

     setenv BIOPERL_INDEX (or export in Bash) in the system login
     script to /nfs/datadisk/bioperlindex/

     go bpindex swissprot /nfs/datadisk/swiss/swissprot.dat
     etc

     You are ready to use bpfetch

Design Documentation
********************

NAME
====

   Bioperl - Design Documentation

SYNOPSIS
========

   Not appropiate. Read on...

DESCRIPTION
===========

   Bioperl is a coordinated project which has a number of design features
to allow bioperl to be well used, extended and collaborate with other
packages. This design can be focused in a number of areas.

     bioperl ettiquette and learning about it
     bioperl root object - exception throwing, exceptions etc.
     bioperl interface design
     bioperl sequence object design notes

AUTHOR
======

   This was written by Ewan Birney in a variety of airports across the US.

Reusing code and working in collaborative projects
==================================================

   The biggest problem often in reusing a code base like bioperl is that
it requires both the people using it and the people contributing to it to
change their attitude towards code. Generally people in bioinformatics are
more likely to be self-taught, single programmers, who put together most
of their scripts/programs as individuals. Bioperl is a truely collaborative
project (the core code is the product of about 15 individuals) and anyone
will be only contributing some part of it in the future.

   Here are some notes about how my coding style has changed to work in
collaborative projects.

Learn to read documentation
---------------------------

   Reading documentation is sometimes as tough as writing the
documentation. Try to read documentation before you ask a question - not
only might it answer your question, but more importantly it will give you
idea why the person who wrote the module wrote it - and this will be the
frame work in which you can understand his or her answer.

Respect people's code (in particular if it works)
-------------------------------------------------

   If the code does what you want, the fact that it is not written the way
you would write should not be a big issue. Of course, if there is some
glaring error then that is worth pointing out to someone. Dismissing a
module on the basis of its coding style is a tremendously wrong thing to
do.

Learn how to provide good feedback
----------------------------------

   This ranges from giving very accurate bug reports (this script -> makes
this error, giving all data), through to pointing out design issues in a
constructive manner (not - this *sucks*). If you find a problem, then
providing a patch using diff or work around is a great thing to do - the
author/maintainer of the module will love you for it.

   Providing "I used XXX and it did just what I wanted it to do" feedback
is also really great. Developers generally only hear about their mistakes.
To hear about successes gives everyone a warm glow.

   One trick I have learnt is that when I download a new project/code or
use a new module I open up a fresh buffer in emacs and keep a mini diary
of everything that I did or think when I started to use the package. After
I used it I could go back, edit the buffer and then send it to the author
either with "it was great - it did just what I wanted, but I found that
the documentation here was misleading" to "to get it to install I had to
incant the following things..."

Taking on a project
-------------------

   When you want to get involved, hopefully it will be because you want to
extend something or provide better facillities to something. The important
thing here is not to work in a vacuum. By providing the main list with a
good proposal before you start about what you are going to do (and listen
to the responses) is a must. I have been pulled up so many times by other
people looking at my design that I can't imagine coding stuff now without
feedback.

Designing good tests
--------------------

   Sadly, you might think that you have written good code, but you don't
know that until you manage to test it! The CPAN style perl modules have a
wonderful test suite system (delve around into the t/ directories) and I
have extended the makefile system so that the test script which you write
to test the module can be part of the t/ system from the start. Once a
test is in the t/ system it will be run millions of times worldwide when
bioperl is downloaded, providing incredible and continual regression
testing of your module (for free!).

Having fun
----------

   The coding process should be enjoyable, and I get very proud of people
who tell me that they picked up bioperl and it worked for them, even if
they don't use a single module that I wrote. There is a brilliant sense of
community in bioperl about providing useful, stable code and it should be
a pleasure to contribute to it.

   So - I am always looking forward to people posting on the guts list
with their feedback/questions/proposals. As well as the long standing fun
we have making new releases.

Bioperl Root Object
===================

   All objects in bioperl (but for interfaces - see the next section)
inheriet from the Root Object. The bioperl root object allows a number of
very useful concepts to be provided. In particular.

exceptions
          Bioperl root object allow exceptions to be throw on the object with very
          nice debugging output

context
          Bioperl root object have a context which allows, in particular, exceptions
          that are thrown to say which object as throwing the exception.

rearrange
          Bioperl root object have some helper methods, in particular rearrange to
          help functions which take hash inputs.

Using the root object.
----------------------

   To use the root object, the object has to inheriet from it. This means
the @ISA array should have (Bio::Roo::Object) in it and that the module
goes "use Bio::Root::Object". The root object provides the ->new function.
This new function builds a hash, sets some root object management issues
and then calls the _initialize function. It is this function which your
object needs to implement.  The full code is given below.

     # convention is that if you are using the Bio::Root object you should put it
     # inside the Bio namespace

     package Bio::MyNewObject;
     use vars qw(@ISA);
     use strict;

     use Bio::Root::Object;
     @ISA = qw(Bio::Root::Object);

     # new() is inherited from Bio::Root::Object
     # _initialize is where the heavy stuff will happen when new is called

     sub _initialize {
        my($self,@args) = @_;
        # call superclasses initialize

     my $make = $self->SUPER::_initialize(@args);

     # do your own argument processing here
     # set default attributes etc...

     return $make; # success - we hope!
       }

Throwing Exceptions
-------------------

     Exceptions are die functions, in which the $@ variable (a scalar) is
     used to indicate how it died. The exceptions can be caught using the
     eval {} system. The bioperl root object has a method called "-Greater_Than_Special_Sequencethrow"
     which calls die but also provides a full stack trace of where this
     throw happened on (and also which object the exception was thrown -
     see the context section). So an exception like

     $obj->throw("I am throwing an exception");

   Provides the following output on STDERR if is not caught.

     -------------------- EXCEPTION --------------------
     MSG: I am throwing an exception
     CONTEXT: Error in object Bio::Root::Object "anonymous Bio::Root::Object"
     SCRIPT: myscript.pl
     STACK:
     main::my_subroutine(7)
     main::(3)
     ---------------------------------------------------

   indicating that this exception was thrown at line 7 of subroutine
my_subroutine, in myscript.pl

   Exceptions can be caught using an eval block, such as

     my $obj = Bio::SomeObject->new();
     my $obj2
     eval {
       $obj2 = $obj->method1();
       $obj2->method2(10);
     }

     if( $@ ) {
       # exception was thrown
       &tell_user("Exception was thrown, preventing whatever I wanted to do. Actual exception $@");
       exit(0);
     }

     # else - use $obj2

   notice that the eval block can have multiple statements in it, and also
that if you want to use variables outside of the eval block, they must be
declared with my outside of the eval block (you are planning to use strict
in your scripts, aren't you!).

object context
--------------

   Each bioperl object has a context, which is given by the name attribute
(name is a method defined in the Bio::Root::Object package). This context
is displayed when the exception is made, so that the following script:

     use Bio::Root::Object;
     $obj = Bio::Root::Object->new;

     $obj->name("Context-A");
     &my_subroutine($obj);

     sub my_subroutine {
           $self = shift;
           $self->throw("I am throwing an exception");
     }

   Produces the following exception

     -------------------- EXCEPTION --------------------
     MSG: I am throwing an exception
     CONTEXT: Error in object Bio::Root::Object "Context-A"
     SCRIPT: test2.pl
     STACK:
     main::my_subroutine(10)
     main::test2.pl(6)
     ---------------------------------------------------

   Notice that the Object nows says that it is Context-A.

   This context is particularly useful when objects are produced from a
database. This is because some exceptions are really due to problems with
the data in an object rather than the code. These sort of exceptions are
better tracked down when you know where the object came from, not where in
the code the exception is thrown.

   One of the drawbacks to this scheme is that the attribute ->name is
"special" from bioperl's perspective. I believe it is best to stay away
from using $obj->name() to mean anything from the object's perspective
(for example ->id() ), leaving it free to be used as a context for
debugging purposes. You might prefer to overload the name attribute to be
"useful" for the object.

Bioperl Interface design
========================

   Bioperl has been moving to a split between interface and implementation
definitions.  An interface is solely the definition of what methods one
can call on an object, without any knowledge of how it is implemented. An
implementation is an actual, working implementation of an object. In
languages like Java, interface definition is part of the language. In
Perl, like many aspects of Perl you have to roll your own.

   In bioperl, the interface names are called Bio::MyObjectI, with the
trailing I indicating it is an interface definition of an object. The
interface files (sometimes nicknamed the 'I files') provide mainly
documentation on what the interface is, and how to use (and implement it).
All the functions which the implementation is expected to provide are
defined as subroutines, and then die with an informative warning. The
exception to this rule are the implementation independent functions (see
later).

   Objects which want to implement this interface should inheriet the
Bio::MyObjectI file in their @ISA array. This means that if the
implementation does not provide a method which the interface defines,
rather than the user getting a "method not found error" it gets a
"mymethod was not defined in MyObjectI, but should have been" which makes
it clearer that whoever provided the implementation was to blame, and not
the caller/script writer.

   When people want to check they have valid objects being passed to their
functions they should test the presence of the interface, not the
implementation. for example

     sub my_sequence_routine {
       my($seq,$other_argument) = @_;

     $seq->isa('Bio::SeqI') || die "[$seq] is not a sequence. Cannot process";

     # do stuff

     }

   This is in contrast to

     sub my_incorrect_sequence_routine {
       my($seq,$other_argument) = @_;

     # this line is INCORRECT
     $seq->isa('Bio::Seq') || die "[$seq] is not a sequence. Cannot process";

     # do stuff

     }

Rationale of interface design
-----------------------------

   Some people might justifiably argue "why do this?". The main reason is
to support external objects from bioperl, and allow them to masquarade as
real bioperl objects. For example you might have your own quite intricate
sequence object which you want to use in bioperl functions, but don't want
to lose your own neat coding. One option would be to have a function which
built a bioperl sequence object from your object, but then you would be
endlessly building temporary objects and destroying them, in particular if
the script yo-yoed between your code and bioperl code.

   A better solution would be to implement the Bio::SeqI interface. You
would read the Bio::SeqI documentation, and then provide the methods which
it required, and put Bio::SeqI in your @ISA array. Then you could pass in
your object into bioperl routines and eh voila - you *are* a bioperl
sequence object.

   (A problem might arise if your object has the same methods as the
Bio::SeqI methods but use them differently - your $obj->id() might mean
provide the raw memory location of the object, whereas the documentation
for Bio::SeqI $obj->id() says it should return the human-readable name. If
so you need to look into providing an 'Adaptor' class, as suggested in the
Gang-of-four).

   Interface classes really come into their own when we start leaving Perl
and enter extensions wrapped over C or over databases, or through systems
like CORBA to other languages, like Java/Python etc. Here the "object" is
often a very thin wrapper over the a DBI interface, or an XS interface,
and how it stores the object is really different. By providing a very
clear, implementation free interface with good documentation there is a
very clear target to hit.

   Some people might complain that we are doing something very
"un-perl-like" by providing these separate interface files. They are 90%
documentation, and could be provided anywhere, in many ways they could be
merged with the actual implementation classes and just made clear that if
someone wants to mimic a class they should override the following methods.
However, we (and in particular myself - Ewan) prefers a clear separation
of the interface. It gives us a much clearer way of defining what is going
on.  It is in many ways just "design sugar" (as opposed to syntactic sugar)
to help us, but it really helps, so thats good enough justification to me.

Implementation functions in Interface files
-------------------------------------------

   One of the issues we discovered early on in using Interface files was
that there were methods that we would like to provide for classes which
were independent of their implementation. A good example is a "Range"
interface, which might define the following methods

     $obj->start()
     $obj->end()

   Now a client to the object might want to use a $obj->length() method.
because it is much easier than retrieving the two attributes and
substracting them. However, the ->length() method is just a pain for
someone providing the implementation to provide - once start() and end()
is defined, length is. There seems to be a catch-22 here: to make an
object definition good for a client one needs to have additional, helper
methods "on top of" the interface, however to make life easier for the
*object implementation* one wants to have the bare minimum of functions
defined which the implementer has to provide.

   In the Range interface this became more than annoyance, as alot of the
"smarts" of the Range system was that we wanted to have the ability to say

     if( $range->intersection($someother_range) )

   We wanted a generic RangeI interface that we could apply to many
objects, with definitions required only for ->start, ->end and ->strand.
However we wanted the ->intersection, and ->union methods to be on all
ranges, without us having to reimplement this every time.

   Our (Matt Pocock and Ewan Birney's) solution was to allow
implementation into the RangeI interface file, but only when these
implementations sat "on top" of the interface definition and therefore
provided helper client operations. In a language like Java, we would
clearly have two classes, with a composition/delegation method:

     MyPublicSomethingClass has-a MyInternalSomethingInterface, with

     ADifferentImplemtation implements MyInternalSomethingInterface

   However this is really heavy handed in Perl (and people were
complaining about having different implementation/interface classes). We
were quite happy about merging the implementation independent functions
with the interface definition, and I (Ewan) used this in other interfaces
since then. The documentation has to be clear about what is going on, but
I think in general it is.

IDL (Interface Definition Language)
-----------------------------------

   There is an idl definition of bioperl in bioperl.idl. This is the start
of a new era of interoperability in this field, so please read it and see
if you can comment on it.

Getting Started
***************

NAME
====

   Bioperl - Getting Started

SYNOPSIS
========

     #!/usr/local/bin/perl

     use Bio::Seq;
     use Bio::SeqIO;

     $seqin = Bio::SeqIO->new( '-format' => 'EMBL' , -file => 'myfile.dat');
     $seqout= Bio::SeqIO->new( '-format' => 'Fasta', -file => '>output.fa');

     while((my $seqobj = $seqin->next_seq())) {
     	print "Seen sequence ",$seqobj->display_id,", start of seq ",
                  substr($seqobj->seq,1,10),"\n";
           if( $seqobj->moltype eq 'dna') {
     	    $rev = $seqobj->revcom;
     	    $id  = $seqobj->display_id();
               $id  = "$id.rev";
               $rev->display_id($id);
               $seqout->write_seq($rev);
            }

     foreach $feat ( $seqobj->top_SeqFeatures() ) {
        if( $feat->primary_tag eq 'exon' ) {
           print STDOUT "Location ",$feat->start,":",
                 $feat->end," GFF[",$feat->gff_string,"]\n";
     	   }
     }
        }

DESCRIPTION
===========

   Bioperl is a set of Perl modules that represent useful biological
objects. Some of the key objects include: Sequences, features on
sequences, databases of sequences, flat file representations of sequences
and similarity search results.

   Because bioperl is formed from Perl modules, there are no actual
useable programs in the distribution (this is not actually true.  In the
scripts directory there are a few useful programs. But not a great
deal...). You have to write the programs which use bioperl.

   It is very easy to write programs using the bioperl modules, as alot of
the complex processing happens in the modules and not in the part of the
program which you have to write. The idea is that you can connet up a
number of the modules to do useful things. The synopsis above gives a
simple script which uses bioperl. Stepping through this script, the lines
mean the following things:

   The first line indicates that in a UNIX manner, the /usr/local/bin/perl
executable is used to execute this script. Bioperl is not a new version of
perl, it just extends the standard perl for biological objects

     #!/usr/local/bin/perl

   These use lines actually import the bioperl modules. Bio::Seq is the
bioperl main sequence object; Bio::SeqIO is the bioperl support for
sequence input/output into files

     use Bio::Seq;
     use Bio::SeqIO;

   These two lines create two SeqIO streams: one for reading in sequences
and one for outputting sequences. Using the

   '-argument' => value

   syntax is common in bioperl. The file argument is like an argument to
open() (notice that in the seqout case there is a greater-than sign,
indicating opening the file for writing). You can also pass in filehandles
or FileHandle objects by using the -fh argument, see SeqIO documentation
for details. Many formarts in bioperl are handled, including Fasta, EMBL.
GenBank, Swissprot (swiss), PIR and GCG.

     $seqin = Bio::SeqIO->new( '-format' => 'EMBL' , -file => 'myfile.dat');
     $seqout= Bio::SeqIO->new( '-format' => 'Fasta', -file => '>output.fa');

   This is the main loop which will loop progressively through sequences
in a file. Each call to seqio->next_seq() provides a new sequence object
from the file, reading successively.

     while((my $seqobj = $seqio->next_seq())) {

   This print line access fields in the sequence object directly. The
seqobj->display_id is the way to access the display_id attribute of the
sequence object. The seqobj->seq method gets the actual sequence out as
string. Then you can do manipulation of this if you want to (there are
however easy ways of doing truncation, reverse-complement and translation).

     print "Seen sequence ",$seqobj->display_id,", start of seq ",
                    substr($seqobj->seq,1,10),"\n";

   Bioperl has to guess the type of the sequence, being either dna, rna or
protein. The moltype attribute gives one of these three possibilities

     if( $seqobj->moltype eq 'dna') {

   The seqobj->revcom method provides the reverse complement of the seqobj
object as another sequence object. The $rev variable therefore is another
sequence object. For example, one could repeat the above print line for
this sequence object (putting rev in place of seqobj). In this case we are
going to output the object into the file stream we built earlier on.

     $rev = $seqobj->revcom;

   When we output it, we want the id of the outputted object to be changed
to "$id.rev", ie, with .rev on the end of the name. The following lines
retrieve the id of the sequence object, add .rev to this and then set the
display_id of the rev sequence object to this. Notice that to set the
display_id attribute you just need call the same method (display_id) with
the new value as an argument.

     $id  = $seqobj->display_id();
                 $id  = "$id.rev";
                 $rev->display_id($id);

   The write_seq method on the seqout output object writes the $rev object
to the filestream we built at the top of the script.  The filestream knows
that it is outputting in fasta format, and so it provides fasta output

     $seqout->write_seq($rev);
              }

   This final loop loops over sequence features in the sequence object,
trying to find ones who have been tagged as 'exon'.  Features have start
and end attributes and can be outputted in GFF format, a standarised
format for sequence features

     foreach $feat ( $seqobj->top_SeqFeatures() ) {
        if( $feat->primary_tag eq 'exon' ) {
           print STDOUT "Location ",$feat->start,":",
                 $feat->end," GFF[",$feat->gff_string,"]\n";
     	   }
     }
        }

Short Description of Objects.
=============================

   Here is a very quick overview of the objects in bioperl

   Bio::Seq - sequence object

     # the following methods return strings

     $seqobj->display_id(); # the human read-able id of the sequence
     $seqobj->seq();        # string of sequence
     $seqobj->subseq(5,10); # part of the sequence as a string
     $seqobj->accession_number(); # when there, the accession number
     $seqobj->moltype();    # one of 'dna','rna','protein'
     $seqobj->primary_id(); # a unique id for this sequence irregardless
                            # of its display_id or accession number

     # the following methods return an array of
     # Bio::SeqFeature objects

     $seqobj->top_SeqFeatures # The 'top level' sequence features
     $seqobj->all_SeqFeatures # All sequence features, including sub
                              # seq features

     # the following methods returns new sequence objects, but
     # do not transfer features across

     $seqobj->trunc(5,10)  # truncation from 5 to 10 as new object
     $seqobj->revcom       # reverse complements sequence
     $seqobj->translate    # translation of the sequence

   Bio::SeqFeature objects:

     # attributes which return numbers

     $feat->start          # start position (1 is the first base)
     $feat->end            # end position (2 is the second base)
     $feat->strand         # 1 means forward, -1 reverse, 0 not relevant

     # attributes which return strings

     $feat->primary_tag    # the main 'name' of the sequence feature,
                           # eg, 'exon'
     $feat->source_tag     # where the feature comes from, eg, 'EMBL_GenBank',
                           # or 'BLAST'

     # attributes which return sequences (these are the more restrictive
     # Bio::PrimarySeq objects, not Bio::Seq objects. The main difference
     # is that these objects do not themselves contain sequence features)

     $feat->seq            # the sequence between start,end on the
                           # correct strand of the sequence
     $feat->entire_seq     # the entire sequence, not necessarily on the
                           # correct strand

     # useful methods for feature comparisons, for start/end points

     $feat->overlap($other)  # does feat and other overlap?
     $feat->contains($other) # is other completely within feat?
     $feat->equals($other)   # does feat and other completely agree?

     # sub features. For complex join() statements, the features
     # is one sequence feature with many sub SeqFeatures

     $feat->sub_SeqFeatures  # array of sub seq features

BLAST
=====

   ...stuff on running BLAST and parsing results...

Database Access
===============

   Feel free to add to this document.

Perl module for generating bit flags
************************************

NAME
====

   bitflags - Perl module for generating bit flags

SYNOPSIS
========

     use bitflags qw( ALPHA BETA GAMMA DELTA );
     use bitflags qw( EPSILON ZETA ETA THETA );

     use bitflags qw( :start=2 BEE CEE DEE EEE EFF GEE );

     use bitflags qw( :start=^3 EIGHT SIXTEEN THIRTY_TWO );

DESCRIPTION
===========

   The `bitflags' module allows you to form a set of unique bit flags, for
ORing together.  Think of the `O_' constants you get from Fcntl... that's
the idea.

   Successive calls remember the previous power used, so you don't have to
set a starting number, or declare all the constants on one line.

   If you do want to set a starting value, use the `:start' flag as the
first argument in the import list.  If the flag is `:start=NNN', where
`NNN' is some positive integer, that value is checked to ensure it's a
power of two, and that value is used as the starting value.  If it is not
a power of two, the program will croak.  If the flag is `:start=^NNN',
where `NNN' is some positive integer, that value is the power of two to
start with.

Implementation
--------------

   The flags are created as `()'-prototyped functions in the caller's
package, not unlike the constant pragma.

AUTHOR
======

   Jeff "`japhy'" Pinyan.

   URL: `http://www.pobox.com/~japhy/'

   Email: `japhy@pobox.com', `PINYAN@cpan.org'

   CPAN ID: `PINYAN'

   Online at: `japhy' on `#perl' on DALnet and EFnet.  `japhy' at
`http://www.perlguru.com/'.  `japhy' at `http://www.perlmonks.org/'.
"Coding With Style" column at `http://www.perlmonth.com/'.

Use MakeMaker's uninstalled version of a package
************************************************

NAME
====

   blib - Use MakeMaker's uninstalled version of a package

SYNOPSIS
========

     perl -Mblib script [args...]

     perl -Mblib=dir script [args...]

DESCRIPTION
===========

   Looks for MakeMaker-like *'blib'* directory structure starting in dir
(or current directory) and working back up to five levels of '..'.

   Intended for use on command line with -M option as a way of testing
arbitary scripts against an uninstalled version of a package.

   However it is possible to :

     use blib;
     or
     use blib '..';

   etc. if you really must.

BUGS
====

   Pollutes global name space for development only task.

AUTHOR
======

   Nick Ing-Simmons nik@tiuk.ti.com

the equivalent of "make" of "Build'n'Play" (BnP)
************************************************

NAME
====

   build - the equivalent of "make" of "Build'n'Play" (BnP)

SYNOPSIS
========

     build
       [-g]         -  use "genopt" installation method
       [-n]         -  use "normal" installation method
       [-p <path>]  -  the absolute prefix of the installation hierarchy
       [-r <path>]  -  optional relative path ("category") for target
       [-s <path>]  -  add search path(s) for local source directory(ies)
       [-u <url>]   -  add URL(s) for remote source directory(ies)
       <target>     -  the command or software package to install
                       (clean, bnp, perl, tools, sfio, gimp, imagick, ...)

     build [-h]     -  print help screen and exit

     build -v       -  print version information and exit

DESCRIPTION
===========

   Think of "Build'n'Play" as something very similar to "make" and
"Makefiles":

   There is a command called "build" (the equivalent of "make") and several
"Buildfiles" (called "perl.bnp", "gimp.bnp" and so on) for the different
"targets" you can "build". Just say "build perl" for building and
installing Perl and its modules, for instance.

   Just like "make", which doesn't re-create the files that are "up to
date" when you invoke "make" more than once, the "build" command does not
re-execute the commands that have already been executed successfully in
the previous call of "build".

   This automatic recovery mechanism is the central idea behind
"Build'n'Play":

   If something goes wrong during the installation (for instance, if a
compiler error occurs), or if you abort it with "`Ctrl-C'", you can simply
re-run "build" (after you resolved the problem in question) with the same
options (important!) and "Build'n'Play" will automatically continue the
installation where it left off (thereby attempting to re-execute the
command which failed previously or which was interrupted).

   There is also a command "build clean" (the equivalent of "make clean")
for deleting the internal temporary workspace, which should always be used
between different builds (but not when restarting an aborted installation,
of course!).

   For a complete list of available targets you can build, just call
"build" without parameters:

     % ./build

   Note that it is possible to install subsets of a given target if such
subsets have been defined in the corresponding "Buildfile"
("<target>.bnp").

   To do so, just append the name(s) of the desired subset(s) (or
"subtarget(s)") to the name of the (main) target using dots ("."), as in
the following example:

     % ./build perl.core.fox

   (Note that the order of the subtargets after the main target does not
matter.)

   This will install Perl itself ("core") plus those modules ("fox") which
are discussed more thoroughly in the book "Programmieren mit Perl-Modulen"
(by O'Reilly Verlag Koeln, 1999) accompanying the CD-ROM on which
"Build'n'Play" was first published (the fox is the animal on the cover of
that book).

   If you want to know which subtargets are available, use the tool "tags"
from the "misc" subdirectory in the "Build'n'Play" distribution, e.g.

     % ./misc/tags perl

   When working with "build", two files will be especially important for
you (unless the installation succeeds without any errors, which it is
unlikely to do when you run it for the first time):

   The installation script (or "Buildfile") "<target>.bnp" and the
automatic recovery file "recover.bnp".

   Both files are located in the directory "<prefix>/lib/BnP/lib/<target>"
(when using the "normal" installation method) or
"<prefix>/lib/BnP/<target>" (when using the "genopt" installation method),
where "<prefix>" is the installation prefix such as "/usr/local", "/opt"
or the like, as specified via the "-p" option, and "<target>" is the name
of the software package to be installed.

   (For a discussion of the two installation methods and their
corresponding command line options, as well as the "-p" option, see the
section "OPTIONS" below.)

   If the "build" command is run from the original distribution's
directory or from the CD-ROM, the file "<target>.bnp" is automatically
copied from that directory to the directory mentioned above, as soon as an
error occurs during the installation (but not if you interrupt it manually
using "Ctrl-C").

   After that this copy takes precedence over its original in the
distribution directory or on the CD-ROM, i.e., the "build" command will
execute this copy rather than the original file when invoked again
subsequently with the same "<target>".

   (If you don't want that, simply delete this copy.)

   This is done because you will most likely need to change this file
after an error occurred, and you obviously can't do that on a CD-ROM, and
you probably don't want to do that in the original distribution.

   (If you don't want this to happen and if you actually want to edit the
file in the original distribution, simply delete the file ".cdrom" from
the distribution directory BEFORE using the "build" command.)

   When you make any changes to that copy of the installation script, you
may also need to change the corresponding commands in the automatic
recovery file (this file is used by the automatic recovery mechanism (see
`BnP(3)' in this node for more details) in order to determine which
commands have already been executed successfully and which are hence to be
skipped in any later runs).

   You may also want to use this automatic recovery file for looking up
which was the last command in your installation script that was
successfully executed.

   In addition to these two files, you may want to check the temporary
internal workspace (in "<prefix>/lib/BnP/tmp/" or "<prefix>/pkg/BnP/tmp/")
where the software packages are unpacked and compiled, in order to find
out what went wrong (in case of an error) and how to fix it.

OPTIONS
=======

   Note that option letters cannot be condensed into a single option letter
string in this script, i.e., an option string such as "-gp/opt" would be
illegal and result in an error message.

   Note however that whitespace between the option letter and its argument
(if it takes one) is optional.

   If the (mutually exclusive) options "-g" and "-n" are both specified,
the last one overrides all previous ones, unless the option "-r" is used,
in which case the "-g" option is implicitly assumed, regardless of wether
any "-g" or "-n" option has been specified or not.

   -g

     This option enables the "genopt" installation method.

     Use this option if you don't want to have your software packages
     installed all into the same directory (such as "/usr/local/bin"),
     trampling over one another and making the de-installation almost
     impossible (except for trivial cases), but each into a separate
     directory subtree of their own.

     See `genopt(1)' in this node for more details.

     (Note that you can still use the prefix "/usr/local" in combination
     with this installation method, but this is actually not recommended,
     because possible name conflicts can be resolved much more easily
     (automatically, through a command line option) if a completely new
     installation directory tree is used, such as "/opt" or "/sw" or
     whatever you choose.)

   -n

     This option enables the "normal" or standard Unix installation method,
     in which software packages are all installed into the same
     installation directories (such as "/usr/local/bin", "/usr/local/man"
     and so on).

     Note that you can use any installation prefix you want in combination
     with this installation method; you are not limited to using
     "/usr/local".

     You will usually not need this option, though, because this is the
     default setting.

     However, if you set the default to the "genopt" installation method
     (by changing the corresponding configuration constant in the script
     "build"), you can use this option to temporarily disable the "genopt"
     installation method and to revert the behaviour to the usual Unix
     installation method.

   `-p <path>'

     Use this option to specify the installation prefix to be used.

     The default is "/usr/local", in case you don't specify any prefix
     explicitly.

   `-r <path>'

     This option can be used in combination with the "genopt" installation
     method in order to specify a subdirectory path (a "category")
     relative to the physical software packages installation directory
     subtree, usually "<prefix>/packages" (e.g. "/opt/packages").

     This allows you to group related software packages into categories and
     subcategories (i.e., subdirectories and subsubdirectories) of your own
     choosing (as many levels deep as you wish).

     Note that using this option automatically implies the "genopt"
     installation method, i.e., this option is automatically treated as
     though the option "-g" had been specified as well (this also
     overrides any "-n" option which may have been specified).

   `-s <path>'

     Use this option for specifying any additional directories containing
     source distribution files which are relevant to your installation.

     You may use this option multiple times on the same command line in
     order to add more than one directory.

     You may also concatenate several directories using colons (":"), e.g.

          -s dir1:dir2:dir3

     You may also combine these two forms, e.g.

          -s d1:d2:d3 -s d4:d5

     Use this option to indicate the path to your CD-ROM drive (e.g.
     "`-s /cd'") if this path is NOT "/cdrom" or "/cdrec" AND if you are
     not starting the "build" command from the "BnP" directory on the
     CD-ROM (in which case "build" already knows (implicitly) about the
     path to your CD-ROM drive).

     You can also use this option to indicate the path to a mirror of a
     software archive (such as "CPAN", for example) on your hard disk,
     e.g. "`-s /pub/mirrors/CPAN'", in order to avoid desnecessary
     downloads.

     Files not found on your local file system (i.e., all the default
     directories already configured into the "build" command plus any
     additional source directories you may have specified with this
     option) will continue to be downloaded automatically, though.

     Note that the directory paths given should not end in a slash ("/").

     Note also that you do not need to specify the "generic" subdirectories
     "CPAN", "BnP/src", "BnP" and "src", i.e., you may (and should) specify
     "`-s /cd'" instead of "`-s /cd/CPAN:/cd/BnP:/cd/BnP/src'" and
     "`-s /pub/mirrors'" instead of "`-s /pub/mirrors/CPAN'", for instance.

     Finally, note that the directories you specify will be searched in the
     given order (from left to right).

   `-u <url>'

     Use this option for specifying any additional (or alternative) URLs
     needed for downloading source distribution files which are relevant
     to your installation.

     You may use this option multiple times on the same command line in
     order to add more than one URL.

     You may also concatenate several URLs using whitespace - but don't
     forget to enclose the whole argument in (single or double) quotes in
     this case:

          -u 'ftp://ftp.engelschall.com/pub/bnp ftp://ftp.netsw.org/netsw'

     You may also combine these two forms, e.g. you may also write

          -u 'url1 url2 url3' -u 'url4 url5'

     This option is especially useful if you have a server on your local
     network with a mirror of some software archive you need, e.g.

          -u ftp://instserv.yourdomain.com/pub/mirrors/CPAN

     Note that the given URLs should always end in the name of a directory,
     but they should nevertheless not end in a slash ("/").

     Note also that (in contrast to the "-s" option described above) you DO
     need to specify the "CPAN" directory in the URLs of "CPAN" mirror
     servers (unless the server doesn't use that name, then use its
     equivalent instead), e.g.

          -u ftp://ftp.cdrom.com/pub/perl/CPAN
          -u ftp://ftp.metronet.com/pub/perl

     However, do NOT specify any subdirectory BELOW the "CPAN" directory
     level (or its equivalent on that host).

     For servers other than "CPAN" mirror servers you will usually specify
     the URL up to the directory containing the file of interest, unless
     you need more than one file from the same server but from different
     directories, in which case you should specify the path common to all
     files in the URL and the differing paths to the different
     subdirectories in the "RELPATH" argument of the corresponding
     "fetch()" method call in your installation script (see `BnP(3)' in
     this node for more details).

     Finally, note that the URLs you specify will be tried in the given
     order (from left to right).

   -h

     If this option is found among the options to the "build" command, the
     internal processing of command line options is terminated
     immediately, a help screen is printed to STDOUT and the program stops
     (with exit code "1").

     Note that this option is optional in the sense that calling the
     "build" command without any parameters produces exactly the same
     result.

   -v

     If this option is found among the options to the "build" command, the
     internal processing of command line options is terminated
     immediately, the name and current version number of the "build"
     command is printed to STDOUT and the program stops (with exit code
     "1").

FILES
=====

     build         -  the equivalent of "make" of "Build'n'Play"

     genopt        -  a tool for maintaining a software package
                      installation hierarchy which allows complete
                      de-installation (without residues whatsoever)
                      using a symbolic link access layer

     BnP.pm        -  the library which provides the automatic recovery
                      mechanism which allows you to simply re-run the
                      "build" command after an error occurred during
                      the installation; the installation will auto-
                      matically resume where it left off

     miniperl      -  a "stripped down" version of the Perl interpreter
                      provided in the original Perl distribution, which
                      is used here for bootstrapping Perl in case no
                      Perl 5 is installed yet on your system

     <target>.bnp  -  the "Buildfile" (in analogy to "Makefile") or
                      installation script for the installation target

     recover.bnp   -  the command log file needed for the automatic
                      recovery of the installation process

     recover.000   -  safeguarded copies of the "recover.bnp" file
     recover.001      of previous installation runs (you might need
     ...              to re-use one of these!)

DIRECTORIES
===========

   On the CD-ROM from O'Reilly Verlag ("Programmieren mit Perl-Modulen"):

     /cdrom/CPAN/                          -  contains the CPAN snapshot
     /cdrom/BnP/                           -  contains the BnP distribution
     /cdrom/BnP/misc/                      -  contains miscellaneous tools
     /cdrom/BnP/src/                       -  contains other source files

   (The latter directory contains source files not found in CPAN (anymore),
as well as tools like "bzip2", "snarf", GNU "make" and "patch".)

   When using the "normal" installation method with a prefix such as
"`/usr/local'":

     /usr/local/lib/BnP/arc/               -  contains all BnP files
     /usr/local/bin/                       -  contains build and genopt
     /usr/local/lib/BnP/lib/               -  contains BnP.pm and miniperl
     /usr/local/lib/BnP/lib/perl/          -  contains perl.bnp
                                              and recover.* files
     /usr/local/lib/BnP/lib/perl/src/      -  contains source files
     /usr/local/lib/BnP/lib/<target>/      -  contains <target>.bnp
                                              and recover.* files
     /usr/local/lib/BnP/lib/<target>/src/  -  contains source files
     /usr/local/man/...                    -  contains BnP's manpages
     /usr/local/lib/BnP/tmp/               -  contains internal workspace

   When using the "genopt" installation method with a prefix such as
"`/opt'":

     /opt/pkg/BnP/arc/                     -  contains all BnP files
     /opt/pkg/BnP/bin/                     -  contains build and genopt
     /opt/lib/BnP/                         -  contains BnP.pm and miniperl
     /opt/lib/BnP/perl/                    -  contains perl.bnp
                                              and recover.* files
     /opt/lib/BnP/perl/src/                -  contains source files
     /opt/lib/BnP/<target>/                -  contains <target>.bnp
                                              and recover.* files
     /opt/lib/BnP/<target>/src/            -  contains source files
     /opt/pkg/BnP/man/...                  -  contains BnP's manpages
     /opt/pkg/BnP/tmp/                     -  contains internal workspace

   Note that "`/opt/lib/BnP/'" is exactly the same directory as
"`/opt/pkg/BnP/lib/'", but via a different symbolic link.

DIAGNOSTICS
===========

   * `"Can't find the indispensable tool '<tool>'!"'

     One of the absolutely indispensable Unix tools (like sh, gunzip, tar
     etc.)  could not be found in the search path (as given by the "$PATH"
     environment variable).

     This occurs if the "$PATH" environment variable is not set properly or
     if your Unix installation is seriously incomplete or broken.

     Check your "$PATH" environment variable to see wether it includes all
     necessary paths, or install the missing tool.

   * `"Can't find '<item>' in '<list>'!"'

   * `"Can't find '<item>' neither in '<path>'' `nor in '<list>'' `using
     offsets '<subdirs>'!"'

   * `"Can't find '<item>' neither in '<path>'' `nor in '<list>'' `using
     offsets '<subdirs>' and '<subsubdir>'!"'

     Neither the expected directory(ies) nor your current search path
     (i.e., the directories listed in your environment variable "`$PATH'")
     contain the requested file "<item>", not even in certain default
     subdirectories of these directories.

     Your search path "`$PATH'" may need to be adjusted, or you may need to
     specify the path to your CD-ROM drive using the command line option
     "-s" (see also the section "OPTIONS" above).

     Maybe you didn't start the "build" command from the CD-ROM or the
     original distribution.

     If in doubt, "cd" to the "BnP" directory on your CD-ROM (e.g. "cd
     /cdrom/BnP") or into the directory of the original distribution and
     start the "build" command from there, i.e., with "./build".

   * `"Can't find any tool (snarf, lynx) for downloading!"'

     You probably forgot to mount your CD-ROM drive.

     May also be caused by starting copies of "build" from different
     places.  If in doubt, cd to the "BnP" directory on the CD-ROM or the
     original distribution directory and use "./build" instead of "build".

     Moreover, you do not seem to have either "snarf" or "lynx" installed.

     You might want to install one of these (or change the configuration in
     "BnP.pm" for another tool) in order for automatic downloads to work in
     the future, which will benefit you as soon as you will attempt to
     install a module newer than the CPAN snapshot included on the CD-ROM.

     (Note that you can install "snarf" with "Build'n'Play" itself via the
     command "build tools.snarf". If you don't have "Build'n'Play" on a
     CD-ROM, you may need to create a subdirectory named "src" in your
     original distribution directory first and then to manually download
     the file "snarf-1.6.1b.tar.gz" from the URL
     "ftp://ftp.engelschall.com/pub/bnp/packages/" into that subdirectory
     before actually doing so.)

   * `"Download of '<file>' with '<tool>' failed!"'

     The program was unable to load the mentioned file from any of the URLs
     specified by you on the command line or configured in "<target>.bnp".

     This means that either there was no connection, or the file was not
     found on any of the specified or configured servers.

     Try again later or try a different URL if everything else seems to be
     correct.

     Note that this error message can also occur when you forget to mount
     your CD-ROM drive, in case you have one of the configured download
     tools (currently "snarf" and "lynx") installed on your system but no
     working network access.

   * `"Can't install the "Build'n'Play" (BnP) package;' `please re-run
     this command ('build bnp')' `from the CD-ROM or the original
     distribution!"'

     Be sure to start "build" from the CD-ROM or the original distribution.

     If in doubt, "cd" to the "BnP" directory on your CD-ROM (e.g. "cd
     /cdrom/BnP") or into the directory of the original distribution and
     start the "build" command from there, i.e., with "./build".

   * `"<Error> in patch command!"'

     An error (more closely described by "<Error>") occurred in one of the
     Perl expressions given as arguments to the "patch()" method in
     "BnP.pm".

     This is usually a Perl syntax error.

     Check your "<target>.bnp" installation script.

     Watch out for proper quoting and escaping!

   * `"Next command deviates from the automatic recovery file -'
     `discarding the remainder of the automatic recovery file!"'

     This warning message appears whenever you apply changes to the
     "<target>.bnp" installation script (after an error with program
     abortion) which cause the installation to take a different course
     than in previous runs.

     This happens for instance if you comment out some part in the
     installation script, if you insert new commands or if you alter
     existing ones.

     This warning message might show that the installation is not doing
     what you intended.

     In such a case you can always abort with "Ctrl-C", make the necessary
     changes, and re-run "build".

     Note that you can always go back to the recovery files of all previous
     installation attempts, which are kept for exactly this purpose (with
     ascending numbers in their filename extensions, i.e., "recover.000"
     is the recovery file from the first installation attempt,
     "recover.001" from the second, and so on).

   All other error messages indicate that something is wrong either with
your command line parameters (and the corresponding error message should
help you to correct the problem), or with the installation (compiler
errors and the like - again, the corresponding error message should help
you to fix this problem), or with your system (most probably a problem
with file permissions in your file system, or a disk capacity overrun).

SEE ALSO
========

   genopt(1), BnP(3), make(1), CPAN(3).

VERSION
=======

   This man page documents "build" version 2.1.0.

AUTHOR
======

     Steffen Beyer

     sb@engelschall.com
       www.engelschall.com/u/sb/download/

COPYRIGHT
=========

     Copyright (c) 1998 by Steffen Beyer.
     All rights reserved.

LICENSE
=======

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself, i.e., under the terms of the
"Artistic License" or the "GNU General Public License".

   Please refer to the files "Artistic.txt" and "GNU_GPL.txt" in this
distribution for details!

DISCLAIMER
==========

   This package 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.

Perl pragma to force byte semantics rather than character semantics
*******************************************************************

NAME
====

   bytes - Perl pragma to force byte semantics rather than character
semantics

SYNOPSIS
========

     use bytes;
     no bytes;

DESCRIPTION
===========

   WARNING: The implementation of Unicode support in Perl is incomplete.
See Perlunicode (perl.info), for the exact details.

   The `use bytes' pragma disables character semantics for the rest of the
lexical scope in which it appears.  `no bytes' can be used to reverse the
effect of `use bytes' within the current lexical scope.

   Perl normally assumes character semantics in the presence of character
data (i.e. data that has come from a source that has been marked as being
of a particular character encoding).

   To understand the implications and differences between character
semantics and byte semantics, see Perlunicode (perl.info).

SEE ALSO
========

   See Perlunicode (perl.info), Utf8,

define character names for `\N{named}' string literal escape.
*************************************************************

NAME
====

   charnames - define character names for `\N{named}' string literal
escape.

SYNOPSIS
========

     use charnames ':full';
     print "\N{GREEK SMALL LETTER SIGMA} is called sigma.\n";

     use charnames ':short';
     print "\N{greek:Sigma} is an upper-case sigma.\n";

     use charnames qw(cyrillic greek);
     print "\N{sigma} is Greek sigma, and \N{be} is Cyrillic b.\n";

DESCRIPTION
===========

   Pragma `use charnames' supports arguments `:full', `:short' and script
names.  If `:full' is present, for expansion of `\N{CHARNAME}}' string
`CHARNAME' is first looked in the list of standard Unicode names of chars.
If `:short' is present, and `CHARNAME' has the form `SCRIPT:CNAME', then
CNAME is looked up as a letter in script `SCRIPT'.  If pragma `use
charnames' is used with script name arguments, then for `\N{CHARNAME}}'
the name `CHARNAME' is looked up as a letter in the given scripts (in the
specified order).

   For lookup of `CHARNAME' inside a given script `SCRIPTNAME' this pragma
looks for the names

     SCRIPTNAME CAPITAL LETTER CHARNAME
     SCRIPTNAME SMALL LETTER CHARNAME
     SCRIPTNAME LETTER CHARNAME

   in the table of standard Unicode names.  If `CHARNAME' is lowercase,
then the `CAPITAL' variant is ignored, otherwise the `SMALL' variant is
ignored.

CUSTOM TRANSLATORS
==================

   The mechanism of translation of `\N{...}' escapes is general and not
hardwired into `charnames.pm'.  A module can install custom translations
(inside the scope which uses the module) with the following magic
incantation:

     use charnames ();		# for $charnames::hint_bits
     sub import {
     	shift;
     	$^H |= $charnames::hint_bits;
     	$^H{charnames} = \&translator;
     }

   Here translator() is a subroutine which takes `CHARNAME' as an
argument, and returns text to insert into the string instead of the
`\N{CHARNAME}' escape.  Since the text to insert should be different in
bytes mode and out of it, the function should check the current state of
bytes-flag as in:

     use bytes ();			# for $bytes::hint_bits
     sub translator {
     	if ($^H & $bytes::hint_bits) {
     	    return bytes_translator(@_);
     	}
     	else {
     	    return utf8_translator(@_);
     	}
     }

BUGS
====

   Since evaluation of the translation function happens in a middle of
compilation (of a string literal), the translation function should not do
any evals or requires.  This restriction should be lifted in a future
version of Perl.

Perl pragma to declare constants
********************************

NAME
====

   constant - Perl pragma to declare constants

SYNOPSIS
========

     use constant BUFFER_SIZE	=> 4096;
     use constant ONE_YEAR	=> 365.2425 * 24 * 60 * 60;
     use constant PI		=> 4 * atan2 1, 1;
     use constant DEBUGGING	=> 0;
     use constant ORACLE		=> 'oracle@cs.indiana.edu';
     use constant USERNAME	=> scalar getpwuid($<);
     use constant USERINFO	=> getpwuid($<);

     sub deg2rad { PI * $_[0] / 180 }

     print "This line does nothing"		unless DEBUGGING;

     # references can be constants
     use constant CHASH		=> { foo => 42 };
     use constant CARRAY		=> [ 1,2,3,4 ];
     use constant CPSEUDOHASH	=> [ { foo => 1}, 42 ];
     use constant CCODE		=> sub { "bite $_[0]\n" };

     print CHASH->{foo};
     print CARRAY->[$i];
     print CPSEUDOHASH->{foo};
     print CCODE->("me");
     print CHASH->[10];			# compile-time error

DESCRIPTION
===========

   This will declare a symbol to be a constant with the given scalar or
list value.

   When you declare a constant such as PI using the method shown above,
each machine your script runs upon can have as many digits of accuracy as
it can use. Also, your program will be easier to read, more likely to be
maintained (and maintained correctly), and far less likely to send a space
probe to the wrong planet because nobody noticed the one equation in which
you wrote `3.14195'.

NOTES
=====

   The value or values are evaluated in a list context. You may override
this with scalar as shown above.

   These constants do not directly interpolate into double-quotish
strings, although you may do so indirectly. (See Perlref (perl.info),
for details about how this works.)

     print "The value of PI is @{[ PI ]}.\n";

   List constants are returned as lists, not as arrays.

     $homedir = USERINFO[7];		# WRONG
     $homedir = (USERINFO)[7];		# Right

   The use of all caps for constant names is merely a convention, although
it is recommended in order to make constants stand out and to help avoid
collisions with other barewords, keywords, and subroutine names. Constant
names must begin with a letter or underscore. Names beginning with a
double underscore are reserved. Some poor choices for names will generate
warnings, if warnings are enabled at compile time.

   Constant symbols are package scoped (rather than block scoped, as `use
strict' is). That is, you can refer to a constant from package Other as
`Other::CONST'.

   As with all use directives, defining a constant happens at compile
time. Thus, it's probably not correct to put a constant declaration inside
of a conditional statement (like `if ($foo) { use constant ... }').

   Omitting the value for a symbol gives it the value of undef in a scalar
context or the empty list, `()', in a list context. This isn't so nice as
it may sound, though, because in this case you must either quote the
symbol name, or use a big arrow, (`=>'), with nothing to point to. It is
probably best to declare these explicitly.

     use constant UNICORNS	=> ();
     use constant LOGFILE	=> undef;

   The result from evaluating a list constant in a scalar context is not
documented, and is not guaranteed to be any particular value in the
future. In particular, you should not rely upon it being the number of
elements in the list, especially since it is not *necessarily* that value
in the current implementation.

   Magical values, tied values, and references can be made into constants
at compile time, allowing for way cool stuff like this.  (These error
numbers aren't totally portable, alas.)

     use constant E2BIG => ($! = 7);
     print   E2BIG, "\n";	# something like "Arg list too long"
     print 0+E2BIG, "\n";	# "7"

   Dereferencing constant references incorrectly (such as using an array
subscript on a constant hash reference, or vice versa) will be trapped at
compile time.

   In the rare case in which you need to discover at run time whether a
particular constant has been declared via this module, you may use this
function to examine the hash `%constant::declared'. If the given constant
name does not include a package name, the current package is used.

     sub declared ($) {
     	use constant 1.01;		# don't omit this!
     	my $name = shift;
     	$name =~ s/^::/main::/;
     	my $pkg = caller;
     	my $full_name = $name =~ /::/ ? $name : "${pkg}::$name";
     	$constant::declared{$full_name};
     }

TECHNICAL NOTE
==============

   In the current implementation, scalar constants are actually inlinable
subroutines. As of version 5.004 of Perl, the appropriate scalar constant
is inserted directly in place of some subroutine calls, thereby saving the
overhead of a subroutine call. See `"Constant Functions"', see Perlsub (perl.info),
for details about how and when this happens.

BUGS
====

   In the current version of Perl, list constants are not inlined and some
symbols may be redefined without generating a warning.

   It is not possible to have a subroutine or keyword with the same name
as a constant in the same package. This is probably a Good Thing.

   A constant with a name in the list `STDIN STDOUT STDERR ARGV ARGVOUT
ENV INC SIG' is not allowed anywhere but in package `main::', for
technical reasons.

   Even though a reference may be declared as a constant, the reference may
point to data which may be changed, as this code shows.

     use constant CARRAY		=> [ 1,2,3,4 ];
     print CARRAY->[1];
     CARRAY->[1] = " be changed";
     print CARRAY->[1];

   Unlike constants in some languages, these cannot be overridden on the
command line or via environment variables.

   You can get into trouble if you use constants in a context which
automatically quotes barewords (as is true for any subroutine call).  For
example, you can't say `$hash{CONSTANT}' because `CONSTANT' will be
interpreted as a string.  Use `$hash{CONSTANT()}' or `$hash{+CONSTANT}' to
prevent the bareword quoting mechanism from kicking in.  Similarly, since
the `=>' operator quotes a bareword immediately to its left, you have to
say `CONSTANT() => 'value'' (or simply use a comma in place of the big
arrow) instead of `CONSTANT => 'value''.

AUTHOR
======

   Tom Phoenix, <`rootbeer@redcat.com'>, with help from many other folks.

COPYRIGHT
=========

   Copyright (C) 1997, 1999 Tom Phoenix

   This module is free software; you can redistribute it or modify it
under the same terms as Perl itself.

Library for fast and easy cyrillic text manipulation
****************************************************

NAME
====

   cyrillic - Library for fast and easy cyrillic text manipulation

SYNOPSIS
========

     use cyrillic qw/866 win2dos convert locase upcase detect/;

     print convert( 866, 1251, $str );
     print convert( 'dos','win', \$str );
     print win2dos $str;

DESCRIPTION
===========

   If first import parameter is number of codepage then locale switched to
they codepage.  Specialisation (like 'win2dos') call faster then 'convert'.
Easy adding new charset. For they need only add charset string.

FUNCTIONS
=========

     At importing list might be listed named convertors. For Ex.:

     use cyrillic qw/dos2win win2koi mac2dos ibm2dos/;

convert SRC_CP, DST_CP, [VAR]
     Convert VAR from SRC_CP codepage to DST_CP codepage and returns
     converted string. VAR may be SCALAR or REF to SCALAR. If VAR is REF
     to SCALAR then SCALAR will be converted. If VAR is ommited then $_
     operated. If function called to void context and VAR is not REF then
     result placed to $_.

upcase CODEPAGE, [VAR]
     Convert VAR to uppercase using CODEPAGE table and returns converted
     string. VAR may be SCALAR or REF to SCALAR. If VAR is REF to SCALAR
     then SCALAR will be converted. If VAR is ommited then $_ operated. If
     function called to void context and VAR is not REF then result placed
     to $_.

locase CODEPAGE, [VAR]
     Convert VAR to lowercase using CODEPAGE table and returns converted
     string. VAR may be SCALAR or REF to SCALAR. If VAR is REF to SCALAR
     then SCALAR will be converted. If VAR is ommited then $_ operated. If
     function called to void context and VAR is not REF then result placed
     to $_.

detect ARRAY
     Detect charset of data in ARRAY and returns name of charset.  If
     charset name not detected then returns 'eng';

EXAMPLES
========

     use cyrillic qw/convert locase upcase detect dos2win win2dos/;

     $\ = "\n";
     $_ = "\x8F\xE0\xA8\xA2\xA5\xE2 \xF0\xA6\x88\xAA\x88!";

     print; upcase 866;
     print; dos2win;
     print; win2dos;
     print; locase 866;
     print;
     print detect $_;

     # EQVIVALENT CALLS:

     dos2win( $str );
     $_ = dos2win( $str );

     dos2win( \$str );
     $str = dos2win( $str );

     dos2win();
     dos2win( \$_ );
     $_ = dos2win( $_ );

     # FOR EASY SWITCH LOCALE CODEPAGE

     use cyrillic qw/866/;

     use locale;
     $str =~ /a-ï/;

     no locale;
     $str =~ /a-ï/;

AUTHOR
======

   Albert MICHEEV <Albert@f80.n5049.z2.fidonet.org>

COPYRIGHT
=========

   Copyright (C) 2000, Albert MICHEEV

   This module is free software; you can redistribute it or modify it
under the same terms as Perl itself.

A powerful template handling logic with advanced features.
**********************************************************

NAME
====

   dTemplate - A powerful template handling logic with advanced features.

SYNOPSIS
========

     use dTemplate;

     $mail_template = define dTemplate "mail_tmpl.txt";# definition

     $mail = $mail_template->parse(                    # parsing
       TO      => "foo@bar.com",
       SUBJECT => $subject,
       BODY    =>
         sub { $email_type==3 ? $body_for_type_3 : $body_for_others },
       SIGNATURE=> $signature_template->parse( KEY => "value" )
     );

     print "Please send this mail: $mail";

     where mail_tmpl.txt is:

     From    : Me
     To      : $TO$
     Subject : $SUBJECT$

     Message body:
     $BODY$

     $SIGNATURE$

     # Advanced feature: Styling

     $style={lang =>'hungarian',color=>'white'};     # Style definition

     $html_template = choose dTemplate( $style,      # Selector definition
       'hungarian+white' =>
               define dTemplate("hun_white_template.html"),
       'spanish'         =>
               define dTemplate("spanish.html"),
       'black+hungarian' =>
               define dTemplate("hun_black_template.html"),
       'english'         =>
               define dTemplate("english_template.html"),
       'empty'           =>
         "<html>This is a text, $BODY$ is NOT substituted!!!!"</html>",
       ''                =>
               text dTemplate "<html>$BODY$</html>",  # default
     );

     $body_template= choose dTemplate( $style,       # Selector definition
       'hungarian'       =>
               define dTemplate("sziasztok_emberek.html"),
       'spanish'         =>
               define dTemplate("adios_amigos.html"),
       ''                =>
               define dTemplate("bye_bye.html"),
     );

     print $html_template->parse(BODY => $body_template->parse());
       # will print "sziasztok_emberek.html" in the
       #"hun_white_template.html"

     %$style=();
     print $html_template->parse(BODY => $body_template->parse());
       # will print "bye_bye.html" surrounded by "<html>" and "</html>" tags.

     %$style=( lang => 'english' );
     print $html_template->parse(BODY => $body_template->parse());
       # will print the "bye_bye.html" in of the "english_template.html"

DESCRIPTION
===========

   This module is aimed to be a simple, general-purpose, lightweight, but
very powerful templating system.

   You can write template-parsing routines in the way the templates are
structured logically. Starting from the biggest to the smallest.  Your
program code will be very clear, structured and easy to understand.  This
logic can be attained by using inline subroutines as values of template
variables. (Look at the example at the end of the document)

USAGE
=====

   First, you need to know how a template looks like, then you need to
know how to define a template in a perl program, then you can parse it.

   After that you can see how to make new encoders.

How a template looks like
-------------------------

   A template is a simple text file, which contains template variable
placeholders.

   The full format of a placeholder is:

     $Template_Variable%printf_style_format_string*encoder1*encoder2$

   Where:

Template_Variable
     It is a mandatory part of the placeholder. Can contain any
     (locale-aware) alphanumeric characters and '.' .

%printf_style_format_string
     This is an optional part. Used when you want to format the output.
     You can use as many '%' as you want, it can be good to pad the
     variable, for example when you parse a table. E.g:  $MONEY%%%%%%011d$
     is a valid placeholder.

     There are predefined encoders in the module, which can be used to
     format the input data.  These are:

          - u    : url-encoder
          - h    : HTML-encoder (converts > to &gt;, etc)
          - uc   : convert the string to uppercase
          - lc   : convert the string to lowercase

     You can use zero or more of these:

          $TITLE*uc*h$

     Read more on encoders (and how to make new encoders) in the Encoders
     part.

Definition of a template
------------------------

   There are 3 ways to define a template.

$template = define dTemplate $filename
     This reads the template from a file.

$template = text dTemplate $scalar
     This creates a template from a scalar

$template = choose dTemplate $hash, "style1" => $template1, "style2" => ...
     It is the definition of the template chooser. It is the way how you
     can create styled templates.

Parsing
-------

   Parsing means substituting the variables which are defined in the
template.  It can be done by simply calling the "parse" method of a
dTemplate object.

   The parameters of the "parse" method are the substitution definitions.

   You can provide substitution parameters in two form:

     - list of name => value pairs
     - with a hash reference

   You can mix them if you want:

     $template->parse(
       name => $value,
       { name2 => $value2, name3 => $value3 },
       name4 => $value4,
       { name5 => $value5 },
       ...
     )

   The "value" can be:

scalar or scalar ref.
     If a value is scalar, it will be substituted. Scalar refs can be used
     to save some memory if you use them more than one time.

code reference ( sub { }, or \&subroutine )
     The sub will be evaluated at each occurence of the template variable.

hash
     You can assign a hash to a template variable if you want.  In this
     way, you can use structured data in the templates, e.g you assign a {
     name => "Greg", "zip" => 111 } to the template variable "person", and
     if you use "person.name" in the template, you will get "Greg" back.
     Nesting (more "."-s) will also work.

   You can use %dTemplate::parse hash to assign global parse parameters.

   The return value of the parse method is a dTemplate::Scalar object,
which can be used as a simple scalar, but really it is a scalar reference
to save some memory. It is useful if you use large templates.

Encoders
--------

   The global hash, %dTemplate::ENCODERS contains the defined encoders.

   The hash keys are the names, the values are subroutine references.
These subs get the encodable data as the first parameter and returns the
encoded value.

HINTS
=====

   * In the first parse of every template, the templates will be compiled.
     It is used to speed up parsing.

   * Don't forget that %dTemplate::parse can be localized. This means you
     can define local-only variable assignments in a subroutine:

          local %dTemplate::parse=(
            %dTemplate::parse,
            local_name => $value
          );

   * You don't need to use text as the input value of an encoder, you can
     use any scalar, even referenes! If you want (for example) print a
     date by a date encoder, which expects the date to be an array ref of
     [ year, month, day ], then you can do this, e.g:

          $dTemplate::ENCODERS{date}=sub {
            return "" if ref($_[0]) ne 'ARRAY';
            return $_[0]->[0]."-".$_[0]->[1]."-".$_[0]->[2];
          }

     Then, when you put $START_DATE*date$ to a template, you can parse
     this template:

          $template->parse(
            START_DATE => [2000,11,13],
            ...
          );

ALL-IN-ONE EXAMPLE
==================

   It is an example, which contains most of the features this module has.
It is not intended to be a real-world example, but it can show the usage
of this module.

   This example consists of one program, and some template modules.

   The executable version of this program can be found in the example
directory of the module distribution.

     use dTemplate;

     ### definition of the standard templates

     my @TEMPLATE_LIST=qw(page table_row table_cell);
     my $templates={};
     foreach my $template (@TEMPLATE_LIST) {
       $templates->{$template} =
         define dTemplate("templates/$template.htm");
     }

     ### definition of the styled templates (styles = languages)

     my @STYLES=qw(eng hun);
     my @STYLED_TEMPLATE_LIST=qw(table_title);

     my $style_select={ lang => 'hun' };

     foreach my $template (@STYLED_TEMPLATE_LIST) {
       my @array=();
       foreach my $style (@STYLES) {
         push @array, $style =>
           define dTemplate("text/$style/$template.txt");
       }
       $templates->{$template} =
         choose dTemplate $style_select, @array;
     }

     ### setting up input data

     my $table_to_print=[
       [ "Buwam",   3, 6, 9 ],
       [ "Greg",    8, 4, 2 ],
       [ "You're",  8, 3, 4 ],
       [ "HTML chars: <>", 3],
     ];

     ### setting up the global parse hash with parse parameters;

     $dTemplate::parse{PAGENO}=7;

     ### settings up a hash with personal data.

     my $person_hash={
       name => { first_name => "Greg" },
       zip  => "9971",
     };

     ### this hash is simply added to other parse parameters

     my $parse_hash={
       "unknown.data" => 157,
     };

     ### the main page parse routine

     print $templates->{page}->parse(
       TABLE_TITLE =>             # name => value pair
         $templates->{table_title}->parse(),
       TABLE => sub {             # name => value pair. value is a sub
         my $ret="";
         foreach my $row (@$table_to_print) {
           $ret .= $templates->{table_row}->parse(
             BODY => sub {
               my $ret="";
               foreach my $cell (@$row) {
                 $ret .= $templates->{table_cell}->parse(
                   TEXT => $cell,
                 )
               }
               return $ret;
             }
           )
         }
         return $ret;
       },
       "person" => $person_hash,  # name => value pair. value is a href
       $parse_hash,               # only a hash with parse parameters
     );

   And the templates:

templates/page.htm:
          <html>
          <body>

          <h1>$TABLE_TITLE*h$</h1>

          <table>
          $TABLE$
          </table>

          <br>
          Person name: $person.name*h$, zip code: $person.zip*h$
          <br>

          Unknown data: $unknown.data*h$
          <br>

          Page: $PAGENO%02d*h$

          </body>
          </html>

templates/table_row.htm:
          <tr>$BODY$</tr>

templates/table_cell.htm:
          <td>$TEXT*h$</td>

text/eng/table_title.txt:
          Table 1

text/hun/table_title.txt:
          1. táblázat

COPYRIGHT
=========

   Copyrigh (c) 2000-2001 Szabó, Balázs (dLux)

   All rights reserved. This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.

AUTHOR
======

   dLux (Szabó, Balázs) <dlux@kapu.hu>

SEE ALSO
========

   perl(1).

Perl compiler pragma to force verbose warning diagnostics
*********************************************************

NAME
====

   diagnostics - Perl compiler pragma to force verbose warning diagnostics

   splain - standalone program to do the same thing

SYNOPSIS
========

   As a pragma:

     use diagnostics;
     use diagnostics -verbose;

     enable  diagnostics;
     disable diagnostics;

   Aa a program:

     perl program 2>diag.out
     splain [-v] [-p] diag.out

DESCRIPTION
===========

The diagnostics Pragma
----------------------

   This module extends the terse diagnostics normally emitted by both the
perl compiler and the perl interpreter, augmenting them with the more
explicative and endearing descriptions found in Perldiag (perl.info).
Like the other pragmata, it affects the compilation
phase of your program rather than merely the execution phase.

   To use in your program as a pragma, merely invoke

     use diagnostics;

   at the start (or near the start) of your program.  (Note that this
*does* enable perl's -w flag.)  Your whole compilation will then be
subject(ed :-) to the enhanced diagnostics.  These still go out *STDERR*.

   Due to the interaction between runtime and compiletime issues, and
because it's probably not a very good idea anyway, you may not use `no
diagnostics' to turn them off at compiletime.  However, you may control
there behaviour at runtime using the disable() and enable() methods to
turn them off and on respectively.

   The *-verbose* flag first prints out the Perldiag (perl.info),
introduction before any other diagnostics.  The
$diagnostics::PRETTY variable can generate nicer escape sequences for
pagers.

   Warnings dispatched from perl itself (or more accurately, those that
match descriptions found in Perldiag (perl.info)) are only
displayed once (no duplicate descriptions).  User code generated warnings
ala warn() are unaffected, allowing duplicate user messages to be
displayed.

The *splain* Program
--------------------

   While apparently a whole nuther program, *splain* is actually nothing
more than a link to the (executable) `diagnostics.pm' module, as well as a
link to the `diagnostics.pod' documentation.  The -v flag is like the `use
diagnostics -verbose' directive.  The -p flag is like the
$diagnostics::PRETTY variable.  Since you're post-processing with
*splain*, there's no sense in being able to enable() or disable()
processing.

   Output from *splain* is directed to STDOUT, unlike the pragma.

EXAMPLES
========

   The following file is certain to trigger a few errors at both runtime
and compiletime:

     use diagnostics;
     print NOWHERE "nothing\n";
     print STDERR "\n\tThis message should be unadorned.\n";
     warn "\tThis is a user warning";
     print "\nDIAGNOSTIC TESTER: Please enter a <CR> here: ";
     my $a, $b = scalar <STDIN>;
     print "\n";
     print $x/$y;

   If you prefer to run your program first and look at its problem
afterwards, do this:

     perl -w test.pl 2>test.out
     ./splain < test.out

   Note that this is not in general possible in shells of more dubious
heritage, as the theoretical

     (perl -w test.pl >/dev/tty) >& test.out
     ./splain < test.out

   Because you just moved the existing stdout to somewhere else.

   If you don't want to modify your source code, but still have on-the-fly
warnings, do this:

     exec 3>&1; perl -w test.pl 2>&1 1>&3 3>&- | splain 1>&2 3>&-

   Nifty, eh?

   If you want to control warnings on the fly, do something like this.
Make sure you do the use first, or you won't be able to get at the
enable() or disable() methods.

     use diagnostics; # checks entire compilation phase
     	print "\ntime for 1st bogus diags: SQUAWKINGS\n";
     	print BOGUS1 'nada';
     	print "done with 1st bogus\n";

     disable diagnostics; # only turns off runtime warnings
     	print "\ntime for 2nd bogus: (squelched)\n";
     	print BOGUS2 'nada';
     	print "done with 2nd bogus\n";

     enable diagnostics; # turns back on runtime warnings
     	print "\ntime for 3rd bogus: SQUAWKINGS\n";
     	print BOGUS3 'nada';
     	print "done with 3rd bogus\n";

     disable diagnostics;
     	print "\ntime for 4th bogus: (squelched)\n";
     	print BOGUS4 'nada';
     	print "done with 4th bogus\n";

INTERNALS
=========

   Diagnostic messages derive from the `perldiag.pod' file when available
at runtime.  Otherwise, they may be embedded in the file itself when the
splain package is built.   See the `Makefile' for details.

   If an extant $SIG{__WARN__} handler is discovered, it will continue to
be honored, but only after the diagnostics::splainthis() function (the
module's $SIG{__WARN__} interceptor) has had its way with your warnings.

   There is a $diagnostics::DEBUG variable you may set if you're
desperately curious what sorts of things are being intercepted.

     BEGIN { $diagnostics::DEBUG = 1 }

BUGS
====

   Not being able to say "no diagnostics" is annoying, but may not be
insurmountable.

   The `-pretty' directive is called too late to affect matters.  You have
to do this instead, and before you load the module.

     BEGIN { $diagnostics::PRETTY = 1 }

   I could start up faster by delaying compilation until it should be
needed, but this gets a "panic: top_level" when using the pragma form in
Perl 5.001e.

   While it's true that this documentation is somewhat subserious, if you
use a program named *splain*, you should expect a bit of whimsy.

AUTHOR
======

   Tom Christiansen <`tchrist@mox.perl.com'>, 25 June 1995.

C style enumerated types and bitmask flags in Perl
**************************************************

NAME
====

   enum - C style enumerated types and bitmask flags in Perl

SYNOPSIS
========

     use enum qw(Sun Mon Tue Wed Thu Fri Sat);
     # Sun == 0, Mon == 1, etc

     use enum qw(Forty=40 FortyOne Five=5 Six Seven);
     # Yes, you can change the start indexs at any time as in C

     use enum qw(:Prefix_ One Two Three);
     ## Creates Prefix_One, Prefix_Two, Prefix_Three

     use enum qw(:Letters_ A..Z);
     ## Creates Letters_A, Letters_B, Letters_C, ...

     use enum qw(
         :Months_=0 Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
         :Days_=0   Sun Mon Tue Wed Thu Fri Sat
         :Letters_=20 A..Z
     );
     ## Prefixes can be changed mid list and can have index changes too

     use enum qw(BITMASK:LOCK_ SH EX NB UN);
     ## Creates bitmask constants for LOCK_SH == 1, LOCK_EX == 2,
     ## LOCK_NB == 4, and LOCK_UN == 8.
     ## NOTE: This example is only valid on FreeBSD-2.2.5 however, so don't
     ## actually do this.  Import from Fnctl instead.

DESCRIPTION
===========

   Defines a set of symbolic constants with ordered numeric values ala C
enum types.

   Now capable of creating creating ordered bitmask constants as well.
See the *BITMASKS* section for details.

   What are they good for?  Typical uses would be for giving mnemonic
names to indexes of arrays.  Such arrays might be a list of months, days,
or a return value index from a function such as localtime():

     use enum qw(
         :Months_=0 Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
         :Days_=0   Sun Mon Tue Wed Thu Fri Sat
         :LC_=0     Sec Min Hour MDay Mon Year WDay YDay Isdst
     );

     if ((localtime)[LC_Mon] == Months_Jan) {
         print "It's January!\n";
     }
     if ((localtime)[LC_WDay] == Days_Fri) {
         print "It's Friday!\n";
     }

   This not only reads easier, but can also be typo-checked at compile
time when run under *use strict*.  That is, if you misspell *Days_Fri* as
*Days_Fry*, you'll generate a compile error.

BITMASKS, bitwise operations, and bitmask option values
=======================================================

   The *BITMASK* option allows the easy creation of bitmask constants such
as functions like flock() and sysopen() use.  These are also very useful
for your own code as they allow you to efficiently store many true/false
options within a single integer.

     use enum qw(BITMASK: MY_ FOO BAR CAT DOG);

     my $foo = 0;
     $foo |= MY_FOO;
     $foo |= MY_DOG;

     if ($foo & MY_DOG) {
         print "foo has the MY_DOG option set\n";
     }
     if ($foo & (MY_BAR | MY_DOG)) {
         print "foo has either the MY_BAR or MY_DOG option set\n"
     }

     $foo ^= MY_DOG;  ## Turn MY_DOG option off (set its bit to false)

   When using bitmasks, remember that you must use the bitwise operators,
|, &, ^, and *~*.  If you try to do an operation like `$foo += MY_DOG;'
and the *MY_DOG* bit has already been set, you'll end up setting other
bits you probably didn't want to set.  You'll find the documentation for
these operators in the *perlop* manpage.

   You can set a starting index for bitmasks just as you can for normal
enum values, but if the given index isn't a power of 2 it won't resolve to
a single bit and therefor will generate a compile error.  Because of this,
whenever you set the *BITFIELD:* directive, the index is automatically set
to 1.  If you wish to go back to normal enum mode, use the *ENUM:*
directive.  Similarly to the *BITFIELD* directive, the *ENUM:* directive
resets the index to 0.  Here's an example:

     use enum qw(
         BITMASK:BITS_ FOO BAR CAT DOG
         ENUM: FALSE TRUE
         ENUM: NO YES
         BITMASK: ONE TWO FOUR EIGHT SIX_TEEN
     );

   In this case, *BITS_FOO, BITS_BAR, BITS_CAT, and BITS_DOG* equal 1, 2,
4 and 8 respectively.  *FALSE and TRUE* equal 0 and 1.  *NO and YES* also
equal 0 and 1.  And *ONE, TWO, FOUR, EIGHT, and SIX_TEEN* equal, you
guessed it, 1, 2, 4, 8, and 16.

BUGS
====

   Enum names can not be the same as method, function, or constant names.
This is probably a Good Thing[tm].

   No way (that I know of) to cause compile time errors when one of these
enum names get redefined.  IMHO, there is absolutely no time when
redefining a sub is a Good Thing[tm], and should be taken out of the
language, or at least have a pragma that can cause it to be a compile time
error.

   Enumerated types are package scoped just like constants, not block
scoped as some other pragma modules are.

   It supports A..Z nonsense.  Can anyone give me a Real World[tm] reason
why anyone would ever use this feature...?

HISTORY
=======

     $Log: enum.pm,v $
     Revision 1.16  1999/05/27 16:00:35  byron

     Fixed bug that caused bitwise operators to treat enum types as strings
     instead of numbers.

     Revision 1.15  1999/05/27 15:51:27  byron

     Add support for negative values.

     Added stricter hex value checks.

     Revision 1.14  1999/05/13 15:58:18  byron

     Fixed bug in hex index code that broke on 0xA.

     Revision 1.13  1999/05/13 10:52:30  byron

     Fixed auto-index bugs in new non-decimal numeric support.

     Revision 1.12  1999/05/13 10:00:45  byron

     Added support for non-decimal numeric representations ala 0x123, 0644, and
     123_456.

     First version committed to CVS.

     Revision 1.11  1998/07/18 17:53:05  byron
       -Added BITMASK and ENUM directives.
       -Revamped documentation.

     Revision 1.10  1998/06/12 20:12:50  byron
       -Removed test code
       -Released to CPAN

     Revision 1.9  1998/06/12 00:21:00  byron
       -Fixed -w warning when a null tag is used

     Revision 1.8  1998/06/11 23:04:53  byron
       -Fixed documentation bugs
       -Moved A..Z case to last as it's not going to be used
        as much as the other cases.

     Revision 1.7  1998/06/10 12:25:04  byron
       -Changed interface to match original design by Tom Phoenix
        as implemented in an early version of enum.pm by Benjamin Holzman.
       -Changed tag syntax to not require the 'PREFIX' string of Tom's
        interface.
       -Allow multiple prefix tags to be used at any point.
       -Allowed index value changes from tags.

     Revision 1.6  1998/06/10 03:37:57  byron
       -Fixed superfulous -w warning

     Revision 1.4  1998/06/10 01:07:03  byron
       -Changed behaver to closer resemble C enum types
       -Changed docs to match new behaver

AUTHOR
======

   Zenin <zenin@archive.rhps.org>

   aka Byron Brummer <byron@omix.com>.

   Based off of the constant module by Tom Phoenix.

   Original implementation of an interface of Tom Phoenix's design by
Benjamin Holzman, for which we borrow the basic parse algorithm layout.

COPYRIGHT
=========

   Copyright 1998 (c) Byron Brummer.  Copyright 1998 (c) OMIX, Inc.

   Permission to use, modify, and redistribute this module granted under
the same terms as Perl.

SEE ALSO
========

   constant(3), perl(1).

Perl pragma to create readonly variables
****************************************

NAME
====

   ex::constant::vars - Perl pragma to create readonly variables

SYNOPSIS
========

   Using the tie() interface:

     use ex::constant::vars;
     tie my $pi,     'ex::constant::vars', 4 * atan2( 1, 1 );
     tie my @family, 'ex::constant::vars', qw( John Jane );
     tie my %age,    'ex::constant::vars', John => 27,
                                           Jane => 'Back off!';

   Using the `const()' function:

     use ex::constant::vars 'const';
     const SCALAR my $pi,     4 * atan2( 1, 1 );
     const ARRAY  my @family, qw( John Jane );
     const HASH   my %age,    John => 27, Jane => 'Back off!';

   Using import() for compile time creation:

     use ex::constant::vars (
       '$pi'     => 4 * atan2( 1, 1 ),
       '@family' => [ qw( John Jane ) ],
       '%age'    => { John => 27, Jane => 'Back off!' },
     );

DESCRIPTION
===========

   This package allows you to create readonly variables.

Implementation
--------------

   This package tie()s variables to a class that disables any attempt to
modify the variables data.

Constant Scalars
     You can store a value in the scalar when it's declared as readonly.

     chomp and chop are effectivley disabled for a readonly scalar.

Constant Arrays
     You can store a list in the array when it's declared as readonly.

     pop, push, shift, splice and unshift are effictivley disabled for a
     readonly array.

Constant Hashes
     You can store a record set in the hash when it's declared as readonly.

     delete is effictivley disabled for a readonly hash.

The `const()' function
----------------------

   When the `const()' function is imported, so is `SCALAR()', `ARRAY()'
and `HASH()'.  These functions allow `const()' to know what type of
variable it's dealing with.  `const()' returns the `tied()' object of the
variable.

Caveats
=======

   This implementation can be slow, by nature.  tie()ing variables to a
class is going to be slow.  If you need the same functionality, and much
less of a speed hit, take a look at this: `http:' in this node

   The fastest method of declaring readonly variables with this pakcage is
to tie() your variables.  After that, using the `const()' function.  And
lastly, using import() at compile time.

   To demonstrate the speed differences:

     use Benchmark;
     timethese 500000, {
       constvars => sub {
                         tie my $x, 'ex::constant::vars', 'test';
                         my $y = $x;
                        },
       standard  => sub {
                         my $x = 'test';
                         my $y = $x;
                        },
     };

   Produces:

     constvars: 24 wallclock secs (22.55 usr +  0.05 sys = 22.60 CPU) @ 22123.89/s (n=500000)
      standard:  2 wallclock secs ( 1.12 usr +  0.00 sys =  1.12 CPU) @ 447761.19/s (n=500000)

Why did you write this?
-----------------------

   I wrote it because I believe that it is a solution.  I also believe
that new ways of implementing this are comming in one form or another.

AUTHOR
======

   Casey R. Tweten, <`crt@kiski.net'>

SEE ALSO
========

   See Perl (perl.info), Perltie (perl.info),
Constant.

COPYRIGHT
=========

   Copyright (c) 1995 Casey R. Tweten. All rights reserved.  This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.

Perl extension to let you use things direct from zip files.
***********************************************************

NAME
====

   ex::lib::zip - Perl extension to let you use things direct from zip
files.

SYNOPSIS
========

     use ex::lib::zip 'library.zip'; # A zip file that contains a file Foo.pm
     use Foo; # And perl will get Foo.pm from library.zip.

DESCRIPTION
===========

   An extension to let you use things direct from zip files direct.  No
temporary files.  No subprocesses.

EXPORT
------

   Nothing.

BUGS
====

   no "no ex::lib::zip" to remove things yet.  no code to remove trailing
duplicates from @INC yet.

AUTHOR
======

   Nicholas Clark, <nick@talking.bollo.cx>

SEE ALSO
========

   See Perl (perl.info).

Perl pragma to override core functions
**************************************

NAME
====

   ex::override - Perl pragma to override core functions

SYNOPSIS
========

     use ex::override ucfirst => sub {
                                      # make sure only the first
                                      # letter is uppercased
                                      ucfirst( lc( shift ) );
                                     };

     ucfirst( 'MAKE THIS RIGHT' );
     # Make this right

     no ex::override 'ucfirst';

     ucfirst( 'MAKE THIS RIGHT' );
     # MAKE THIS RIGHT

DESCRIPTION
===========

   "ex::override" is an easy way to override core perl functions.

Overriding a function
---------------------

     use ex::override
       length => \&mylength,
       open   => \&myopen;

   Overriding a core function happens at compile time.  Arguments are
passed to "ex::override" in a name based, or hash style.  The key is the
name of the core function to override, the value is your subroutine to
replace the core's.

Using an overriden funtion
--------------------------

   Nothing changes on the surface.  If you override "stat", then you still
use "stat" the same way.

   NOTE: This is only true if you are keeping the same prototype as the
function you've overriden.  To do this, you must define your prototype:

     use ex::override values => sub (\%) { values %{+shift} };

   If you don't use this same prototype or force yourself to use the
function the same, you can extend the functionality of a core function:

     # length of all arguments passed to length()
     use ex::override length => sub { length join '', @_ };

Overriding a function globaly
-----------------------------

   *Don't do this without a very good reason!*

   "ex::override" allows you the ability to override core functions
globaly.  Any packages that inherit from yours will use your function
override.  There are good reasons for doing this, if you think you need
to, make sure you have a good reason.

     use ex::override
       GLOBAL_length => sub {
                             # prevent someone from passing a list
                             croak "Don't do that!" if @_ > 1;
                             length shift
                            };

   NOTE: If you globaly override a function in a package, only that
package can remove it.

Removing your override
----------------------

   This works the same way that "no strict" works.

     no ex::override; # remove _all_ overrides

     no ex::override 'values';

     no ex::override 'GLOABL_length';

TIPS
====

Get a list of overrideable function
     If you have the Perl source laying around, go to it's root dir and
     try this:

          perl -lne 'print /_(\w+)/ if /return -K/' toke.c

     You'll have to weed out which ones are functions ( vs.  operators,
     etc. ).

Get a functions prototype
          perl -lwe 'print prototype "CORE::length"'

     This prints the prototype, or "Use of uninitialized variable..." if
     there isn't one.

TODO
====

   Find a way to preserve prototypes so the user doesn't have to know them.

AUTHOR
======

   Casey R. Tweten, crt@kiski.net

COPYRIGHT
=========

   Copyright (c) 2000 Casey R. Tweten <crt@kiski.net>.  All rights
reserved.  This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

compile-time class fields
*************************

NAME
====

   fields - compile-time class fields

SYNOPSIS
========

     {
         package Foo;
         use fields qw(foo bar _Foo_private);
     	sub new {
     	    my Foo $self = shift;
     	    unless (ref $self) {
     		$self = fields::new($self);
     		$self->{_Foo_private} = "this is Foo's secret";
     	    }
     	    $self->{foo} = 10;
     	    $self->{bar} = 20;
     	    return $self;
     	}
     }

     my Foo $var = Foo::->new;
     $var->{foo} = 42;

     # this will generate a compile-time error
     $var->{zap} = 42;

     # subclassing
     {
         package Bar;
         use base 'Foo';
         use fields qw(baz _Bar_private);	# not shared with Foo
     	sub new {
     	    my $class = shift;
     	    my $self = fields::new($class);
     	    $self->SUPER::new();		# init base fields
     	    $self->{baz} = 10;			# init own fields
     	    $self->{_Bar_private} = "this is Bar's secret";
     	    return $self;
     	}
     }

DESCRIPTION
===========

   The fields pragma enables compile-time verified class fields.

   NOTE: The current implementation keeps the declared fields in the
%FIELDS hash of the calling package, but this may change in future
versions.  Do not update the %FIELDS hash directly, because it must be
created at compile-time for it to be fully useful, as is done by this
pragma.

   If a typed lexical variable holding a reference is used to access a
hash element and a package with the same name as the type has declared
class fields using this pragma, then the operation is turned into an array
access at compile time.

   The related base pragma will combine fields from base classes and any
fields declared using the fields pragma.  This enables field inheritance
to work properly.

   Field names that start with an underscore character are made private to
the class and are not visible to subclasses.  Inherited fields can be
overridden but will generate a warning if used together with the -w switch.

   The effect of all this is that you can have objects with named fields
which are as compact and as fast arrays to access.  This only works as
long as the objects are accessed through properly typed variables.  If the
objects are not typed, access is only checked at run time.

   The following functions are supported:

new
     fields::new() creates and blesses a pseudo-hash comprised of the
     fields declared using the fields pragma into the specified class.
     This makes it possible to write a constructor like this:

          package Critter::Sounds;
          use fields qw(cat dog bird);

          sub new {
          	my Critter::Sounds $self = shift;
          	$self = fields::new($self) unless ref $self;
          	$self->{cat} = 'meow';				# scalar element
          	@$self{'dog','bird'} = ('bark','tweet');	# slice
          	return $self;
          }

phash
     fields::phash() can be used to create and initialize a plain
     (unblessed) pseudo-hash.  This function should always be used instead
     of creating pseudo-hashes directly.

     If the first argument is a reference to an array, the pseudo-hash will
     be created with keys from that array.  If a second argument is
     supplied, it must also be a reference to an array whose elements will
     be used as the values.  If the second array contains less elements
     than the first, the trailing elements of the pseudo-hash will not be
     initialized.  This makes it particularly useful for creating a
     pseudo-hash from subroutine arguments:

          sub dogtag {
          	my $tag = fields::phash([qw(name rank ser_num)], [@_]);
          }

     fields::phash() also accepts a list of key-value pairs that will be
     used to construct the pseudo hash.  Examples:

          my $tag = fields::phash(name => "Joe",
          			    rank => "captain",
          			    ser_num => 42);

          my $pseudohash = fields::phash(%args);

SEE ALSO
========

   See Base, `Pseudo-hashes: Using an array as a hash', see
Perlref (perl.info),

Perl pragma to control the filetest permission operators
********************************************************

NAME
====

   filetest - Perl pragma to control the filetest permission operators

SYNOPSIS
========

     $can_perhaps_read = -r "file";	# use the mode bits
     {
         use filetest 'access';		# intuit harder
         $can_really_read = -r "file";
     }
     $can_perhaps_read = -r "file";	# use the mode bits again

DESCRIPTION
===========

   This pragma tells the compiler to change the behaviour of the filetest
permissions operators, the -r -w -x `-R' -W -X (see Perlfunc (perl.info)).

   The default behaviour to use the mode bits as returned by the stat()
family of calls.  This, however, may not be the right thing to do if for
example various ACL (access control lists) schemes are in use.  For such
environments, `use filetest' may help the permission operators to return
results more consistent with other tools.

   Each "use filetest" or "no filetest" affects statements to the end of
the enclosing block.

   There may be a slight performance decrease in the filetests when `use
filetest' is in effect, because in some systems the extended functionality
needs to be emulated.

   NOTE: using the file tests for security purposes is a lost cause from
the start: there is a window open for race conditions (who is to say that
the permissions will not change between the test and the real operation?).
Therefore if you are serious about security, just try the real operation
and test for its success.  Think atomicity.

subpragma access
----------------

   Currently only one subpragma, access is implemented.  It enables (or
disables) the use of access() or similar system calls.  This extended
filetest functionality is used only when the argument of the operators is
a filename, not when it is a filehandle.

Inheritance without objects
***************************

NAME
====

   foundation - Inheritance without objects

SYNOPSIS
========

     package Foo;

     sub fooble { 42 }

     package Bar;

     sub mooble { 23 }
     sub hooble { 13 }

     package FooBar;
     use foundation;
     foundation(qw(Foo Bar));

     sub hooble { 31 }

     print fooble();       # prints 42
     print moodle();       # prints 23
     print hooble();       # prints 31 (FooBar overrides hooble() from Bar)
     print SUPER('hooble');     # prints 13 (Bar's hooble())

DESCRIPTION
===========

   Haven't drunk the OO Kool-Aid yet?  Think object-oriented has something
to do with Ayn Rand?  Do you eat Java programmers for breakfast?

   If the answer to any of those is yes, than this is the module for you!
foundation adds the power of inheritance without getting into a class-war!

   Simply `use foundation' and list which libraries symbols you wish to
"inherit".  It then sucks in all the symbols from those libraries into the
current one.

Functions
---------

foundation
          foundation(@libraries);

     Declares what libraries you are founded on.  Similar to `use base'.

SUPER
          my @results = SUPER($function, @args);

     Calls the named $function of the current package's foundation with the
     given @args.

     Similar to `$obj-'SUPER::meth();>

BUGS
====

   Plenty, I'm sure.  This is a quick proof-of-concept knock off.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Sex, Base,

*GEN*erate access layer for *OPT*ional software
***********************************************

NAME
====

   genopt - *GEN*erate access layer for *OPT*ional software

SYNOPSIS
========

     genopt
       [-c]           -  create the target installation subtree
       [-f]           -  force override of foreign conflicting links
       [-r]           -  remove all links to target in selected subdirs
       [-p <path>]    -  the prefix of the installation hierarchy
       [-s <path>]    -  the software package installation subtree
       [-d <dirlist]  -  comma separated list of subdirs to act on
       <target>       -  the software package's directory to act on

     genopt [-h]      -  print help screen and exit

     genopt -v        -  print version information and exit

ABSTRACT
========

   Did you ever hate the common software installation practice where all
the binaries get installed into the same place (such as "/usr/local/bin",
for instance), trampling over one another, and other files getting copied
all over your file system, thus making the de-installation of a package
extremely difficult (which files belong to this package and which don't,
and where are they?!)?

   Did you ever want to maintain a clean and well-organized installation
directory structure instead, in which every software package is installed
in a separate directory subtree of its own, allowing the (dynamic) grouping
of related software packages into categories (i.e., common subdirectories)
and the easy de-installation without any residues?

   "genopt" is a tool for administrating the installation of a great number
of software packages on Unix systems in a very transparent way with minimal
effort. The de-installation of software packages is also enormously
simplified.

   The files belonging to any given application (such as binaries, manual
pages, libraries and so on) are all stored together in a distinct
directory subtree.

   There are pivotal directories for binaries, manual pages etc. that you
need to include in your search path in order to access the applications
administrated with "genopt".

   The central idea of "genopt" is that these pivotal directories contain
symbolic links which point to the various application's files.

   "genopt" administrates these symbolic links.

   A definition of "genopt" (by its original author Ralf S. Engelschall)
says:

     `` _Gen_eration of a compact central access layer
        for a large pool of locally installed
        _opt_ional Unix software,
        distributed with complete sources ''

PREFACE
=======

   There are many methods to deal with the problem of software
installation.  They all have various advantages and shortcomings. Some of
the most common practices will be presented here shortly as an
introduction into the matter:

   * copy & stay forever

     This is the common practice on PC's under DOS/Windows. New software
     packages are copied to the machine in question and dispersed all over
     the file system in such a way that after some time hardly anybody
     knows which files (or lines in an "*.ini" file) belong to which
     application.

     As a consequence, almost never a software package is de-installed
     completely.

     In the meantime tools have emerged to handle this problem
     ("un-installer"), but even these tools cannot always prevent problems
     which may arise when de-installing the various components of an
     application, especially such as the libraries shared between many
     applications (DLL's).

     This method of installation is completely unacceptable on Unix systems
     where the number and complexity of the installed software packages is
     typically much higher, especially on application servers for many
     users at the same time, which usually show a large fluctuation of the
     installed software packages due to changes in user demand, upgrades
     and the testing of new products.

     Conclusion:

          installation    : simple
          de-installation : almost impossible!!

   * package installation (e.g. Solaris etc.)

     On some systems some (proprietary) mechanisms have been especially
     implemented to address the issue of software installation and
     de-installation (for instance on System V-derivatives). However, they
     all require a number of special files for each and every software
     package that is to be installed and/or de-installed in this way,
     files which usually do not accompany the software packages as they
     are commonly found (on the Internet, for instance), except for
     software packages provided by the operating system vendor himself,
     maybe.  Creating these files yourself can easily cost up to a week of
     work, if you can succeed at all despite the frequently insufficient
     documentation of these installation mechanisms.

     Conclusion:

          installation    : sometimes very simple
          de-installation : sometimes very simple

   * "/usr/local/dist"-solution (e.g. Technical University of Munich,
     Germany)

     With this method each application is stored in a separate directory
     subtree of its own. The directory "/usr/local/dist" thereby contains
     a large number of symbolic links, each pointing to one of the
     installed applications.  However, these links have to be created
     manually because there is no tool available for automating this task.
     In practice this leads to a situation in which some of the
     applications are installed in this way, others not, thus seriously
     corrupting transparency. Thus the installation using this method is
     hard, because it is labour-intensive, and the de-installation is also
     hard, because one needs to know exactly which links need to be
     removed.

     Conclusion:

          installation    : hard
          de-installation : hard

   * GenOpt

     An installation with "genopt" resembles the "/usr/local/dist"-method:
     software packages are stored in separate directory subtrees, and some
     central directories contain symbolic links to the various
     applications.

     However, the symbolic links are administrated automatically by
     "genopt", and need not to be created and removed manually. Moreover,
     "genopt" also creates the necessary directory structures when needed.

     In a way this is like the "package installation" method mentioned
     above, but without the need for special per-package installation- and
     de-installation scripts.

     A necessary prerequisite is that the application in question is
     configurable and does not contain any hard-coded paths. In the most
     favourable circumstances, the application will be available in source
     code form which can be adapted as needed.

     Conclusion:

          installation    : easy
          de-installation : easy

CONTENTS
========

     1. GenOpt
     1.1 What does it look like what GenOpt creates?
     1.2  How to install software with GenOpt
     1.2.1 Preparing the installation
     1.2.2 Unpacking the software
     1.2.3 Necessary adjustments to the software
     1.2.4 Linking the package with GenOpt
     1.2.5 How to relocate a software package
     1.2.6 How to de-install a software package
     1.3 General usage instructions
     2. Summary by original author Ralf S. Engelschall
     3. Tips & Tricks

DESCRIPTION
===========

1. GenOpt
---------

   "genopt" consists of a Bourne shell script with a length of roughly 40
KB.

   Besides the built-in Bourne shell commands, only standard Unix tools
such as cat, ls, sed, awk etc. are used throughout this script, because
"genopt" is intended to be useable already when installing a Unix machine
for the first time (bootstrapping!).

1.1 What does it look like what GenOpt creates?
-----------------------------------------------

   "genopt" creates an access layer or "access interface" at a freely
chosen point in your file system to give you access to the installed
software packages. Usually this point is "/opt", but any other directory
will do.

   "genopt" can be configured (configuration constant
"DEFAULT_LOGICAL_ROOT" at the beginning of the script) or instructed via
command line options to use any prefix you wish.

   One of the reasons for the necessity of this access layer is that you
can't possibly include all the different directories from your various
applications containing executables into your search path (i.e., the
environment variable "$PATH").

   This access layer (e.g. "/opt") is organized as follows:

     Access via...    link in access layer...  giving access to...
     ---------------- ------------------------ -----------------------------
                       /opt/pkg/foo-591        foo-591 is a directory link
                                               giving access to all files of
                                               example application foo-591

     $PATH             /opt/bin/foo            executables of application
                            .../bar

     $MANPATH          /opt/man/man1/foo.1     application's manual pages
                            .../man8/bar.8     (nroff-format)

     $INFOPATH         /opt/info/foo.info      application's documentation
                             .../foo-1.info    (GNU texinfo-format)

     /opt/lib/foo-591        directory link to the "lib"-
                             subdirectory of the applica-
                             tion, destined to all files
                             the application needs inter-
                             nally, e.g. foo.cfg, foo.hlp,
                             local binaries etc. The app-
                             lication has been configured
                             before the installation to
                             seek these files here.

     cc -I             /opt/include/foo.h      C header files

     cc -L, ldconfig   /opt/shlib/libfoo.a     static und runtime (dynamic)
                              .../libfoo.so.2  shared-libraries

     $XAPPLRESDIR      /opt/xad/Foo            X11 application defaults
                            .../Bar

   The files in "/opt/shlib" are accessed at runtime by the kernel, the
files in "/opt/xad" are accessed by X11 applications via the "libX11"
library, and so on.

   An illustration should make this structure clearer:

     /opt/
       |
           +---------+----+----+------+------+-----+----+-----+------+-----+
           |         |    |    |      |      |     |    |     |      |     |
       packages     pkg  bin  etc  include  info  lib  man  shlib  texmf  xad
           |         |    |    |      |      |     |    |     |      |     |
       ... : ...     |    |    |  symbolic link access layer  |      |     |
           |         |    |    |      |      |     |    |     |      |     |
        foo-591 <----+    v    v      v      v     v    v     v      v     v
           |
           |  dist  arc  bin  etc  include  info  lib  man  shlib  texmf  xad
           |   |     |    |    |      |      |     |    |     |      |     |
           +---+-----+----+----+------+------+-----+----+-----+------+-----+
              software package's individual physical installation subtree

   The software packages can thereby be contained in the (global) physical
installation subtree (usually "/opt/packages") either in a flat way, as
follows:

     /opt/packages/
           |
        +----+-----+------+----+-----+-----+------+------+----+-----+-- ...
        |    |     |      |    |     |     |      |      |    |     |
       perl elm sendmail vim rdist baybox gzip sattrack tin shutil cvs  ...

   Or they can be grouped together into categories and subcategories of
your own free choice, as in the following example:

     /opt/packages/
           |
               +----------------+------+-------+----------------+-- ...
               |                |              |                |
            network          utility        develop          hamradio
               |                |              |                |
        +------+-----+      +---+---+     +----+----+      +----+----+
        |      |     |      |       |     |    |    |      |         |
       Mail  News  rdist  shutil  gzip  perl  cvs  vim  sattrack  baybox
        |      |
        |     tin
        |
        +------+
        |      |
       elm  sendmail

   Note that this structure should not be altered manually (exceptions to
this rule see further below) if you don't want to risk loosing the access
to your applications.

   Regard it as something internal not to be tampered with just like the
data files of a database system.

   (Some operations, like creating new categories and relocating already
installed software packages, are permitted under certain conditions.)

   Additionally, "genopt" creates some files in the access layer's root
directory ("/opt") for its own internal housekeeping. These files are
named ".genopt.L.*" and may not be touched, just like the index files of a
database system.

   Finally, "genopt" also writes a log file into that same directory named
".genopt.errors", which you actually may need to trim (manually) from time
to time.

1.2  How to install software with GenOpt
----------------------------------------

   Software packages are best installed each in a completely separate
directory subtree of their own, which are located in a dedicated software
package installation hierarchy, grouped together in categories and
subcategories (i.e., subdirectories and subsubdirectories) according to
their function.

   This installation hierarchy must be a subdirectory of the root directory
of the symbolic link access layer ("/opt"), the name (or path) of which is
freely configurable, as long as it does not conflict with any of the
reserved subdirectory names already used by "genopt".

   This subdirectory is usually called "packages" (or "PKG", on some
machines), which is the current default.

   You can choose a different directory name or path by either changing the
corresponding configuration constant "DEFAULT_PHYSICAL_ROOT" at the
beginning of "genopt", or by specifying a different value via the "-s"
command line option.

   The following discussion assumes an application named "foo-591" being
installed into the directory "/opt/packages/misc/foo-591".

1.2.1 Preparing the installation
--------------------------------

   First of all the subdirectory tree for accommodating the new software
package has to be created.

   This is best and most easily done using "genopt" itself:

     % genopt -c /opt/packages/misc/foo-591

   Alternatively, you could also use (provided that the directory
"/opt/packages/misc" already exists):

     % cd /opt/packages/misc
     % genopt -c foo-591

   (The option "-c" means "create".)

   This call of "genopt" creates the following directories:

     /opt                               (only if still non-existent)
     /opt/packages                      (only if still non-existent)
     /opt/packages/misc                 (only if still non-existent)
     /opt/packages/misc/foo-591
     /opt/packages/misc/foo-591/arc
     /opt/packages/misc/foo-591/bin
     /opt/packages/misc/foo-591/etc
     /opt/packages/misc/foo-591/include
     /opt/packages/misc/foo-591/info
     /opt/packages/misc/foo-591/lib
     /opt/packages/misc/foo-591/man
     /opt/packages/misc/foo-591/shlib
     /opt/packages/misc/foo-591/texmf
     /opt/packages/misc/foo-591/xad

   Note that you can specify in detail which of these subdirectories in the
"foo-591" directory should actually be created by using the command line
option "-d" (for more on this, see further below).

   Additionally, "genopt" already creates the first symbolic links, the
most important of which is:

     /opt/pkg/foo-591 -> /opt/packages/misc/foo-591

   (More on this link see below.)

   Here's a more detailed explanation of the most important of these
subdirectories (the minimal configuration):

   * /opt/packages/misc/foo-591

     This directory will contain ALL the files belonging to the new
     application, thus ensuring that the application can be de-installed
     easily, by simply deleting this directory (and removing any symbolic
     links pointing to it).

   * /opt/packages/misc/foo-591/arc

     This subdirectory is indispensable, because "genopt" will only create
     the most important link (the one from "/opt/pkg/foo-591" pointing to
     "/opt/packages/misc/foo-591") if this subdirectory exists.

     (This is also a protective measure in order to prevent you from
     accidentally creating links to a directory which is not an
     application's installation directory.)

     This directory is intended for archiving (hence its name) the original
     source distribution file of the software package in question for
     possible later reference.

     Moreover, it has proven to be good practice to safeguard any
     configuration files here for later re-use which you may have altered
     to suit your system.

   * /opt/packages/misc/foo-591/bin

     This subdirectory will contain all the executables which belong to the
     new application (stored here by "make install").

1.2.2 Unpacking the software
----------------------------

   First, change directory to the application's installation directory
which has been created in the previous step (see subsection above):

     % cd /opt/packages/misc/foo-591

   Put the application's source distribution file into the "arc"
subdirectory and then unpack it, as follows:

     % gunzip -c arc/foo-591.tar.gz | tar xf -

   If this pipe doesn't work on your system for some reason, proceed as
follows:

     % cp arc/foo-591.tar.gz .
     % gunzip foo-591.tar.gz
     % tar xf foo-591.tar
     % rm -f foo-591.tar

   Beware that some misbehaving packages do not create a new subdirectory
"foo-591" when unpacked in this way; they sometimes simply spill their
contents into whatever the current working directory is.

   If in doubt, first test the distribution file with "tar tf". If all
filenames shown begin with "foo-591/..." then proceed as described above.

   Otherwise create a new subdirectory named "dist" (or whatever you like,
as long as the name doesn't conflict with the subdirectory names reserved
by "genopt"), change directory to it and unpack the distribution there.

   It may be a good idea to use such a directory in all cases, just to be
sure and to avoid the need for the extra check.

1.2.3 Necessary adjustments to the software
-------------------------------------------

   This step is manual work, but substantially less hassle than creating
the special files needed for "package installation" mechanisms (as
described in the preface at the top of this document), for instance.

   The symbolic link

     /opt/pkg/foo-591 -> /opt/packages/misc/foo-591

   is of utmost importance here, because it allows to hide the physical
path to the installation directory of the application from the application
itself.

   This is absolutely essential in order to be able to relocate this
application later, which may be desirable to do if you want to re-organize
your categories into which you have grouped your software packages, for
instance if a category grows too large and needs further refinement.

   An application with the path "/opt/packages/misc/foo-591" hard-coded
into it would simply not work anymore after such a relocation.

   Therefore it is important that the application does not know about its
own physical location, and that it accesses all of its own files via the
symbolic link "/opt/pkg/foo-591".

   Thus, before being able to proceed with the compilation of your
application, you need to configure it appropriately.

   Many software packages provide some configuration utility for this
purpose.

   Please refer to the installation instructions of your package to find
out how to change the installation prefix.

   Usually, you just need to say:

     % ./configure --prefix=/opt/pkg/foo-591

   and you're done.

   For some packages (like Perl, for instance) you have to use

     % ./Configure -Dprefix=/opt/pkg/foo-591

   instead.

   If such an automatic configuration tool is not available in your
package, you may have to edit the application's "Makefile" or its sources
in order to configure it properly.

   Be sure to configure it as follows, so that all hard-coded paths will
take a route via some symbolic link:

     /opt/pkg/foo-591           general base for all other paths

     /opt/pkg/foo-591/bin       for all user-executable binaries

     /opt/pkg/foo-591/lib       (or more elegantly)
     /opt/lib/foo-591           for all libraries and binaries used
                                exclusively by the application itself

     /opt/pkg/foo-591/man/man1  for all manual pages
     /opt/pkg/foo-591/man/man3
     /opt/pkg/foo-591/man/....

     /opt/pkg/foo-591/etc       for "rc" ("run-configure") files
     /opt/pkg/foo-591/include   for C header files ("*.h")
     /opt/pkg/foo-591/info      for GNU info files (documentation)
     /opt/pkg/foo-591/shlib     for all shared libraries
     /opt/pkg/foo-591/texmf     for all TeX resources
     /opt/pkg/foo-591/xad       for all X resources

   Make sure that the directory "/opt/pkg/foo-591/bin" will only contain
those executables which are meant to be called by the user of the
application.

   All binaries which the application needs for internal purposes only
should go into the directory "/opt/pkg/foo-591/lib".

   (Note that "/opt/lib/foo-591" is just a convenient shorthand for
"/opt/pkg/foo-591/lib", but via a different symbolic link.)

   Finally, build your application (usually by saying "make" or "make all"
- refer to the installation instructions of your package for more details).

1.2.4 Linking the package with GenOpt
-------------------------------------

   After successfully compiling the new application, install it into its
destination subdirectories (usually with "make install", but refer to the
installation instructions of your package to be sure).

   If the application has been configured correctly in the previous step,
this will automatically install the necessary files into the appropriate
subdirectories, i.e., "/opt/pkg/foo-591/bin", "/opt/lib/foo-591",
"/opt/pkg/foo-591/man", and so on.

   Note that with some (especially very small) applications you may need to
manually copy or move these files to their final destinations.

   After that the application still needs to be made accessible by creating
the corresponding symbolic links.

   This is accomplished with the following simple commands:

     % cd /opt/packages/misc/foo-591
     % genopt .

   Or alternatively:

     % genopt /opt/packages/misc/foo-591

   Or also:

     % genopt /opt/pkg/foo-591

   Note that you can use this same command when you install more files
later, for example when you install Perl modules later you should run the
command

     % genopt -d man /opt/pkg/perl5.005_02

   (or whatever the name of the directory of your Perl installation is)
afterwards in order to create the necessary links to the manual pages
belonging to the new module(s).

   (The option "`-d man'" thereby restricts the action of "genopt" to the
"man" subdirectory tree, i.e., "man/man1", "man/man3" and so on.)

   These commands cause "genopt" to scan the subdirectories of the
application's installation directory (i.e., the subdirectories of
"/opt/packages/misc/foo-591") and to create a symbolic link in the
corresponding subdirectory of the access layer root directory ("/opt") for
each eligible file it finds during this scan, for example:

     /opt/bin/bar -> ../packages/misc/foo-591/bin/bar

   ("Eligible" means that the files must be readable and non-empty.
Additionally, binaries are required to have the "executable" bit set.)

   This is true for all subdirectories except "lib" and "texmf", where no
links to individual files are created but rather a directory link pointing
to the subdirectory itself, i.e.,

     /opt/lib/foo-591    ->  ../packages/misc/foo-591/lib
     /opt/texmf/foo-591  ->  ../packages/misc/foo-591/texmf

   Remember that the symbolic link in "/opt/pkg" is also a directory link:

     /opt/pkg/foo-591    ->  ../packages/misc/foo-591

   Note also that "genopt" actually creates RELATIVE links (as shown here
above), and not ABSOLUTE links (as was shown in the examples further above
for better clarity), i.e., it always creates links pointing to
"../packages/misc/foo-591/..." and not "/opt/packages/misc/foo-591/...".

   This makes it possible to relocate the ENTIRE "genopt" installation
hierarchy later to a different place in your file system, as in the
following example, with all links intact and working:

     % cd /
     % mv opt /usr/local/

   Instead of accessing your binary "bar" with "/opt/bin/bar", you now
would say "/usr/local/opt/bin/bar".

   In order not to break existing shell scripts (for instance) which use
the absolute path "/opt/bin/bar", it is advisable however to additionally
create a symbolic link for backwards compatibility, as follows:

     % cd /
     % ln -s /usr/local/opt opt

   Finally, remember to include the following directories in the following
environment variables, if you haven't done so already:

     % PATH="/opt/bin:$PATH"; export PATH
     % MANPATH="/opt/man:$MANPATH"; export MANPATH
     % INFOPATH="/opt/info:$INFOPATH"; export INFOPATH
     % XAPPLRESDIR="/opt/xad:$XAPPLRESDIR"; export XAPPLRESDIR

   You should also put these statements into the profile of your preferred
shell (e.g. "$HOME/.bashrc") or into the global profile for all users on
your system (usually in "/etc/profile").

   Moreover, configure "ldconfig" to include the directory "/opt/shlib" in
its path (see `ldconfig(8)' in this node for details).

1.2.5 How to relocate a software package
----------------------------------------

   Relocating a software package (for example when a category has grown too
large and you want to subdivide it) implies the following three steps:

   In the first step, you need to "cut" all connections (i.e., links) to
the application in question:

     % cd /opt/packages/misc/foo-591
     % genopt -r .

   (The option "-r" means "remove".)

   In the second step, the application is moved as desired, for example:

     % cd /opt/packages
     % mkdir tools
     % mkdir tools/filter
     % mv misc/foo-591 /opt/packages/tools/filter/

   In the third and last step, the application is "linked" anew:

     % cd tools/filter/foo-591
     % genopt .

   Done!

   Note that these three steps are also required if you just want to rename
the installation directory of an application ("foo-591" in this example).

   The need for renaming an installation directory may arise for example
when you first installed some software package into an installation
directory whose name does not include any version number, and later you
want to install a newer version of that same package, but without removing
the older version (as a fallback measure, for instance, in case the newer
version proves to be defective, or to be able to access both applications
during a transition period).

   In such a case you should rename the installation directory of the older
version in such a way as to include its version number in the name (for
example, "mv perl perl5.004_04") and then install the new version (either
(again) into a (new) installation directory named "perl" or (better) into
a directory whose name also includes the version number (say,
"perl5.005_02").

1.2.6 How to de-install a software package
------------------------------------------

   The de-installation of a software package is extremely simple:

     % cd /opt/packages/tools/filter/foo-591
     % genopt -r .
     % cd ..
     % rm -rf foo-591

   That's all!

   Alternatively you can also use:

     % cd /opt/packages/tools/filter/foo-591
     % rm -rf *
     % genopt .
     % cd ..
     % rmdir foo-591

   (Note that in this latter case you don't need to specify the "-r"
option.  However it causes no harm if you do.)

   This method has one advantage and two disadvantages compared with the
first method above:

   First of all, this latter method needs one step more than the first
method above.

   Second, this method is a little faster, but it does not always find all
the links it should remove (in cases when there are inconsistencies
between the index files of "genopt" and the links that actually exist in
the file system).

   Therefore it is safer (but a little slower) to use "genopt" with the
"-r" option on an intact installation directory.

1.3 General usage instructions
------------------------------

-
     If you call "genopt" without parameters or with the parameter "-h"
     (for "help"), "genopt" prints a help screen and exits (with return
     code "1").

     Note that the "-h" option overrides all others which may or may not be
     present on the same command line.

     This help screen is a quick reference guide which lists the available
     options and briefly describes their function.

-
     If you call "genopt" with the option "-v" (for "version" - not
     "verbose"), "genopt" prints a line with its current version
     information and exits (with return code "1").

     (See further below for how to influence the verbosity of this script.)

     Note that the "-v" option overrides all others options, including the
     "-h" option.

-
     If you accidentally or frivolously changed some of the links or index
     files administrated by "genopt", it usually suffices to run "genopt"
     again for the affected application(s) in order to restitute the
     link(s) and/or to resolve any inconsistencies in the index files of
     "genopt".

     In some cases you might have to use the "-f" ("force") option, though
     (see below).

     Moreover, if you delete links manually, dead weight will accumulate
     in the index files, which will eventually slow down "genopt".

     Note that the automatic restitution works only partially if you
     enable the "fast mode" (see also below).

-
     Should the automatic restitution not work as desired, you may also
     delete (or move to a save place, as a backup measure) all the
     subdirectories and files in the "/opt" directory EXCEPT the
     subdirectory "packages".

     Then use the tool "mgenopt" ("multi-genopt") from the "misc"
     subdirectory in this distribution for a recursive descent into your
     "/opt/packages" tree, thereby automatically calling "genopt" for each
     application found.

     Note that you need to change the configuration in "mgenopt" if your
     hierarchy is not located in "/opt" or if your physical installation
     area is not in the subdirectory "packages".

     Any parameters given to "mgenopt" are simply passed through
     transparently to "genopt" (this may be useful for using the "-f"
     ("force") option, for instance).

-
     Sometimes two applications have files with the same name, especially
     if you have two different versions of the same application installed
     in parallel.

     This may give rise to conflicts in the symbolic link access layer,
     since both applications will want to create a link to their own file.

     "genopt" will usually report a warning message ("`[CONFLICT]'") in
     such cases but will leave any conflicting links untouched.

     This will prevent "genopt" from creating or removing a link as
     requested.

     However, if you want to explicitly give preference to one of the
     conflicting applications, you can do so by running "genopt" for that
     application again, but this time with the "-f" ("force") option.

     This will cause all conflicting links from the other application (or
     version) to be overridden, i.e., to be removed, allowing "genopt" to
     subsequently create the requested links.

     For better visual control, "genopt" always displays the conflicting
     link on the terminal, not the link which should have been created or
     the one "genopt" was expecting to remove.

     In the log file written by "genopt" (see also further below),
     however, this logic is slightly different: There the link which
     should have been created or the link which would have been removed is
     displayed, and the reason why this could not be done is given in
     parentheses behind that.

-
     Please note that the automatic detection of conflicts and the
     automatic restitution of links (along with the automatic repair of
     the associated index files) only works partially when the "fast mode"
     is enabled (see also the configuration constant "fast_mode" and its
     explanation in the "configuration constants" section of the script).

     In order to be absolutely sure that all inconsistencies or conflicts
     have been found, one should first remove all the links to the
     application in question using the option "-r" ("remove"), and then
     re-create all links by calling "genopt" again (no special option
     required this time).

     However, this would cost you more than the speed gained through the
     "fast mode" in the first place.

     So either do not use the "fast mode", or make sure that nobody can
     mess around with the links and index files maintained by "genopt".

     (Or disable the "fast mode" temporarily to perform any repairs.)

     Note also that the "fast mode" only speeds up the verification of
     symbolic links, the creation and removal of links remains completely
     unaffected.

     (In "fast mode", "genopt" blindly "trusts" its own index files and
     does not verify the file system, as in the standard mode.)

-
     Note that you can use the parameter "-d" ("d" for "directory") to
     restrict the actions of "genopt" to certain of its predefined
     subdirectories.

     The default is to act on ALL predefined subdirectories (call "genopt"
     without parameters or with the option "-h" to get a complete list).

     These subdirectories must be given as a comma separated list without
     any intervening whitespace (whitespace between the option letter and
     its argument is optional, however).

     That way you can create (when using the option "-c") only those
     subdirectories your application really needs, thus preventing
     "genopt" from creating unneeded subdirectories which you have to
     delete manually afterwards (unless these empty directories do not
     bother you).

     That way you can also add more links later more easily and speedily
     when you install more parts (e.g. modules or plug-ins) of your
     application later, for example by restricting "genopt" to the "bin"
     subdirectory.

     This can also be a safety measure whenever you are using the "-f"
     ("force") option, or to remove the links of just one particular
     subdirectory.

     Note that the option "-c" (create the directory subtree for a new
     application) presents the following special cases in combination with
     the "-d" option:

          -  The subdirectories "arc" and "bin" constitute the minimal
             configuration. They are ALWAYS created, regardless wether
             they were explicitly specified or not.

          -  The links in subdirectories which contain directory links
             instead of individual file links are already created
             at this time (if these subdirectories have been specified).

          (Currently these directories are "pkg", "lib" and "texmf".)

          -  The link from "pkg" to the application's base directory
             is always created, regardless wether this subdirectory
             was specified or not.

     (See the section "Tips & Tricks" below if you don't want any links to
     be created yet at this time.)

     Note also that you can have multiple occurrences of this option on
     the same command line, all arguments of these options will simply be
     accumulated internally to form the internal list of subdirectories to
     be processed.

     Therefore the following commands are all equivalent:

          % genopt -d bin -d include -d lib -d man .

          % genopt -d bin,man -d lib -dinclude .

          % genopt -d bin,include,lib,man .

-
     Note that whitespace is optional between option letters (of options
     which take an argument) and their argument (these options are
     currently "-p", "-s" and "-d").

-
     The condensation of several option letters into a single option
     string is NOT possible (i.e., an option string such as "`-cdbin'" is
     illegal and will cause an error message with program abortion).

-
     The use of the link "/opt/lib/foo-591" instead of
     "/opt/pkg/foo-591/lib" is a matter of taste.

     Sometimes it is very hard to persuade a given application to use the
     former (for example in packages using GNU "configure" scripts).

     The link "/opt/lib/foo-591" can be considered more elegant (at least
     it is shorter than "/opt/pkg/foo-591/lib"), but both work equally
     well.

     Conclusion: If it is easy to achieve, use "/opt/lib/foo-591", if not,
     use "/opt/pkg/foo-591/lib" instead (for example by saying
     "./configure -prefix=/opt/pkg/foo-591").

-
     It should not be concealed that although "genopt" is a very powerful,
     elegant and flexible tool for software installations under Unix, it
     does not cover all possible situations.

     This mainly concerns heterogeneous clusters of workstations who share
     their software installations via NFS (Network File System).

     "genopt" does not provide any support for multi-platform or
     multi-architecture installations within the same "genopt"
     installation hierarchy.

     (But you can of course create distinct hierarchies on the same
     central server if you want.)

-
     Moreover, it is not possible to have different entries in the same
     directories for different (but otherwise compatible) machines, as in
     the following example:

     The "genopt" hierarchy is physically located on the machine "sunfi1".

     Among others, it contains the package "/opt/pkg/sendmail", the
     universal Unix program for sending and receiving mail.

     This package uses configuration files which are located in
     "/opt/lib/sendmail".

     The machine "sunfi2", which is binary compatible with machine
     "sunfi1", mounts and uses this same "genopt" hierarchy via NFS.

     The problem in this situation is that this machine may not be allowed
     to send and receive mail, although it can execute the program
     "/opt/bin/sendmail", because the configuration files (which specify
     the hostname, for instance) are only valid for machine "sunfi1".

     In order to solve this problem, "genopt" would need to generate TWO
     "/opt" hierarchies, departing from two different directories,
     "/opt/pkg/sendmail/lib.sunfi1" and "/opt/pkg/sendmail/lib.sunfi2"
     (from a common installation area "/opt/packages"): One for machine
     "sunfi1" (which would get the directory "/opt/pkg/sendmail/lib.sunfi1"
     as "/opt/lib/sendmail") and another for machine "sunfi2" (which would
     get the directory "/opt/pkg/sendmail/lib.sunfi2" also as
     "/opt/lib/sendmail").

     However, this is not possible with the current or any previous
     version of "genopt".

-
     The subdirectories which "genopt" knows about and processes are
     configured at a single, easily accessible location in the script.

     Therefore, it is very easy to add more subdirectories should the need
     arise.

     Simply add them to the list in the configuration constant
     "COMMON_SUBDIRS".

     Moreover, if you want these subdirectories to contain directory links
     (just like "pkg", "lib" and "texmf", currently) instead of individual
     file links (which is the default), additionally add them to the list
     in the configuration constant "BRIDGE_SUBDIRS".

-
     The subdirectories in "/opt/man" (such as "/opt/man/man1" and so on)
     are created automatically on demand.

     However they are not removed automatically when they become empty.

-
     "genopt" writes a log file called ".genopt.errors" located in
     directory "/opt".

     Since "genopt" always appends to this file, you may need to trim it
     from time to time (note that the "build" command trims this file
     every time it is called).

     If you want more detailed information in this log file, set the
     configuration constant "details" in the script accordingly.

-
     If you want to switch off the output sent to STDOUT by "genopt", set
     the configuration constant "verbose" in the script to an empty string.

-
     This document describes "genopt" version 2.1.0, which differs
     considerably from previous versions since it is a complete rewrite,
     written by Steffen Beyer.

2. Summary by original author Ralf S. Engelschall
-------------------------------------------------

   "genopt" has been used intensively for about six years now, especially
at sd&m (software design & management GmbH & Co. KG, with head office in
Munich, Germany), since the very first hours of its existence.

   "genopt" has ever since been used to administrate this company's Unix
servers, and has also been used at the Technical University of Munich, and
lately has begun to be used at the company "Zeppelin" (yes, the famous
one! This company still exists but nowadays specializes in building
machines).

   In all these places "genopt" has proven to be an extremely useful tool
for the installation of optional Unix software, because:

-
     "genopt" makes it possible to maintain the control and overview over
     a large pool of applications, while the administration itself is taken
     care of automatically by this tool,

-
     because the de-installation of an application has become a trivial
     task:

          % cd /opt/packages/misc/foo-591
          % genopt -r .
          % cd ..
          % rm -rf foo-591

-
     and because the installation with "genopt" is fun; as an
     administrator one does not need to worry so much about the
     technicalities of installing and de-installing the software anymore,
     one can concentrate on creating a hierarchy of categories which gives
     a maximum of clarity and overview.

   Summing up I have to say that six years of using "genopt" for the
installation of Unix software has yielded excellent results.

   Only "genopt" made it possible at all to administrate such a huge
number of applications (almost a thousand binaries!) successfully as in my
case.

3. Tips & Tricks
----------------

   * If you use the options "-c" (for "create") and "-r" (for "remove")
     simultaneously, only the requested subdirectories will be created,
     but no symbolic links whatsoever.

   * There is a shortcut for relocating a software package, as
     demonstrated in the example below (based on the example in the
     section "How to relocate a software package" above):

          % cd /opt/packages
          % mkdir tools
          % mkdir tools/filter
          % mv misc/foo-591 /opt/packages/tools/filter/
          % cd tools/filter/foo-591
          % genopt -f .

     In this way you don't need to "unlink" the application first before
     moving it around.

     BEWARE however that this shortcut does NOT work properly if you
     RENAME the installation directory of the application in question
     ("foo-591" in this example)!

     (The obsolete directory links referring to the old name of the
     installation directory will not be removed in such a case.)

     BEWARE also that you should use this shortcut ONLY if you are
     absolutely SURE that there are no other software packages with
     conflicting links you want to preserve, since the call
     "`genopt -f .'" above will overwrite any such links.

SEE ALSO
========

   build(1), BnP(3).

VERSION
=======

   This man page documents "genopt" version 2.1.0.

AUTHORS
=======

     Ralf S. Engelschall - original idea and first private versions

     rse@engelschall.com
     www.engelschall.com

     Steffen Beyer       - complete rewrite and documentation
                           (first public version)

     sb@engelschall.com
       www.engelschall.com/u/sb/download/

COPYRIGHT
=========

     Copyright (c) 1992 - 1998 by Ralf S. Engelschall.
     All rights reserved.

     Copyright (c) 1998 by Steffen Beyer.
     All rights reserved.

LICENSE
=======

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl, i.e., under the terms of either the
"Artistic License" or the "GNU General Public License".

   Please refer to the files "Artistic.txt" and "GNU_GPL.txt" in this
distribution for details!

DISCLAIMER
==========

   This package 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.

message handling functions
**************************

NAME
====

   gettext - message handling functions

SYNOPSIS
========

     use gettext;
     use POSIX;     # Needed for setlocale()

     setlocale(LC_MESSAGES, "");
     textdomain("my_program");

     print gettext("Welcome to my program"), "\n";
             # (printed in the local language)

DESCRIPTION
===========

   The gettext module permits access from perl to the gettext() family of
functions for retrieving message strings from databases constructed to
internationalize software.

   gettext(), dgettext(), and dcgettext() attempt to retrieve a string
matching their msgid parameter within the context of the current locale.
dcgettext() takes the message's category and the text domain as parameters
while dcgettext() defaults to the LC_MESSAGES category and gettext()
defaults to LC_MESSAGES and uses the current text domain.  If the string
is not found in the database, then msgid is returned.

   textdomain() sets the current text domain and returns the previously
active domain.

   *bindtextdomain(domain, dirname)* instructs the retrieval functions to
look for the databases belonging to domain domain in the directory
`dirname'

SEE ALSO
========

   gettext(3i), gettext(1), msgfmt(1)

AUTHOR
======

   Phillip Vandry <vandry@Mlink.NET>

import all modules with a package prefix, aliasing it away.
***********************************************************

NAME
====

   import - import all modules with a package prefix, aliasing it away.

   'import' acts as a pragma that performs a 'use' on all modules that can
be found with the given package prefix. Any modules found have a 'use'
statement performed, and the fully qualified package name is aliased to
one without the given prefix. The functionality is similar to Java's
'import' statement.

   See import.pod for details.

HISTORY
=======

     import.pm
     v1.01 10/10/99 mak

COPYRIGHT
=========

     Copyright (C) 1999 Michael King ( mike808@mo.net )
     Saint Louis, MO USA.

   This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   This module is copyright (c) 1997,1998 by Michael King ( mike808@mo.net
) and is made available to the Perl public under terms of the Artistic
License used to cover Perl itself. See the file Artistic in the
distribution  of Perl 5.002 or later for details of copy and distribution
terms.

AVAILABILITY
============

   The latest version of this module is likely to be available from:

     http://walden.mo.net/~mike808/import_pm

   The best place to discuss this code is via email with the author.

Perl pragma to compute arithmetic in integer instead of double
**************************************************************

NAME
====

   integer - Perl pragma to compute arithmetic in integer instead of double

SYNOPSIS
========

     use integer;
     $x = 10/3;
     # $x is now 3, not 3.33333333333333333

DESCRIPTION
===========

   This tells the compiler to use integer operations from here to the end
of the enclosing BLOCK.  On many machines, this doesn't matter a great
deal for most computations, but on those without floating point hardware,
it can make a big difference.

   Note that this affects the operations, not the numbers.  If you run this
code

     use integer;
     $x = 1.5;
     $y = $x + 1;
     $z = -1.5;

   you'll be left with `$x == 1.5', `$y == 2' and `$z == -1'.  The $z case
happens because unary - counts as an operation.

   Native integer arithmetic (as provided by your C compiler) is used.
This means that Perl's own semantics for arithmetic operations may not be
preserved.  One common source of trouble is the modulus of negative
numbers, which Perl does one way, but your hardware may do another.

     % perl -le 'print (4 % -3)'
     -2
     % perl -Minteger -le 'print (4 % -3)'
     1

   See `Pragmatic Modules', see Perlmod (perl.info).

Perl extension for the iODBC API
********************************

NAME
====

   iodbc - Perl extension for the iODBC API

SYNOPSIS
========

   This man page is not intended to be a manual on the ODBC API.  Please
see an ODBC manual for extended documentation on the usage of ODBC
commands.

   To use iodbc functions:

   `use iodbc;'

DESCRIPTION
===========

   Everything in the extension follows the ODBC core API except that all
function calls are pass by value.  The one exception is SQLBindCol which
needs to be passed a reference to a scalar.  For More information please
seek a ODBC manual and remember that this extension only works with core
implementations.

Functions
---------

   The following functions are included with this iodbc extension.
Parameters marked [i] are for input into the function while parameters
marked [r] return data from a function.

   * SQLAllocEnv

    Syntax
          `SQLAllocEnv($hEnv);'

    Parameters

          $hEnv

               [o]  The environment handle.  This will be passed to other
               functions.

   * SQLAllocConnect

    Syntax
          `SQLAllocConnect($hEnv, $hDbc);'

    Parameters

          $hEnv

               [i]  The environment handle as it is returned from
               `SQLAllocEnv()'.

          $hDbc

               [o]  The connection handle.  This will be passed to other
               functions.

   * SQLConnect

    Syntax
          `SQLConnect($hDbc, $pvDsn, $ivfDsnSize, $pvUid, $ivfUidSize,
          $pvPwd, $ivfPwdSize);'

    Parameters

          $hDbc

               [i]  The connection handle as it is returned from
               `SQLAllocConnect()'.

          $pvDsn

               [i]  The data source name.  This should be a string.

          $ivfDsnSize

               [i]  The size of $pvDsn.  It should be `SQL_NTS'.  This
               stands for a null terminated string.

          $pvUid

               [i]  The user id.  This should also be a string.

          $ivfUidSize

               [i]  The size of $pvUid.  It should also be `SQL_NTS'.

          $pvPwd

               [i]  The password.  Once again it should be a string.

          $ivfPwdSize

               [i]  The size of pvPwd.  Once again it should be `SQL_NTS'

   * SQLAllocStmt

    Syntax
          `SQLAllocStmt($hDbc, $hStmt);'

    Parameters

          $hDbc

               [i]  The connection handle as it is returned from
               `SQLAllocConnect()'.

          $hStmt

               [o]  The statement handle.  This will be passed to other
               functions.

   * SQLGetCursorName

    Syntax
          `SQLGetCursorName($hStmt, $pvCursor, $ivCursorMax,
          $ivCursorSize);'

    Parameters

          $hStmt

               [i]  The statement handle as it is returned from
               `SQLAllocStmt()'.

          $pvCursor

               [o]  The cursor name associated with the $hStmt.  This will
               be returned from the function as a string of maximum length
               $ivCursorMax.

          $ivCursorMax

               [i]  The maximum size of $ivCursor.

          $ivCursorSize

               [i]  The actual size of the string available for return to
               $pvCursor.

   * SQLSetCursorName

    Syntax
          `SQLSetCursorName($hStmt, $pvCursor, $ivfCursorSize);'

    Parameters

          $hStmt

               [i]  The statement handle as it is returned from
               `SQLAllocStmt()'.

          $pvCursor

               [i]  The Cursor Name to be associated with the $hStmt.
               This should be a string.

          $ivfCursorSize

               [i]  The size of $pvCursor.  This should be `SQL_NTS'.

   * SQLPrepare

    Syntax
          `SQLPrepare($hStmt, $pvSql, $ivfSqlSize);'

    Parameters

          $hStmt

               [i]  The statement handle as it is returned from
               `SQLAllocStmt()'.

          $pvSql

               [i]  The SQL statement to be prepared.  This should be a
               string.

          $ivfSqlSize

               [i]  The size of $Sql.  This should be `SQL_NTS'.

   * SQLExecute

    Syntax
          `SQLExecute($hStmt);'

    Parameters

          $hStmt

               [i]  The statement handle as it is returned from
               `SQLAllocStmt()'.

   * SQLExecDirect

    Syntax
          `SQLExecDirect($hStmt, $pvSql, $ivfSqlSize);'

    Parameters

          $hStmt

               [i]  The statement handle as it is returned from
               `SQLAllocStmt()'.

          $pvSql

               [i]  The SQL statement to be prepared.  This should be a
               string.

          $ivfSqlSize

               [i]  The size of $pvSql.  This should be `SQL_NTS'.

   * SQLRowCount

    Syntax
          `SQLRowCount($hStmt, $ivNumRows);'

    Parameters

          $hStmt

               [i]  The statement handle as it is returned from
               `SQLAllocStmt()'.

          $ivNumCols

               [o]  The number of rows affected by the SQL statement just
               executed in $hStmt.  This works for UPDATE, INSERT and
               DELETE statements.

   * SQLNumResultCols

    Syntax
          `SQLNumResultCols($hStmt, $ivNumCols);'

    Parameters

          $hStmt

               [i]  The statement handle as it is returned from
               `SQLAllocStmt()'.

          $ivNumCols

               [o]  The Number of columns returned in a result set of a
               SQL statement in $hStmt.

   * SQLDescribeCol

    Syntax
          `SQLDescribeCol($hStmt, $ivCol, $pvColName, $ivColNameMax,
          $ivColNameSize, $fSqlType, $ivPrecision, $ivScale, $fNullable);'

    Parameters

          $hStmt

               [i]  The statement handle as it is returned from
               `SQLAllocStmt()'.

          $ivCol

               [i]  The function will return a description of this column.

          $pvColName

               [o]  A string that contains the name of column $ivCol

          $ivColNameMax

               [i]  The maximum size of the column name to return to
               $pvColName

          $ivColNameSize

               [o]  The size of the column name available to return to
               $pvColName

          $fSqlType

               [o]  The type of data contained in column $ivCol.

          $ivPrecision

               [o]  The precision of column $ivCol.

          $ivScale

               [o]  The scale of column $ivCol.

          $fNullable

               [o]  Returns whether column $ivCol allows null values.

   * SQLColAttributes

    Syntax
          `SQLColAttributes($hStmt, $ivCol, $fType, $pvAttrib,
          $ivAttribMax, $ivAttribSize, $ivAttrib);'

    Parameters

          $hStmt

               [i]  The statement handle as it is returned from
               `SQLAllocStmt()'.

          $ivCol

               [i]  The function will return a attributes from column
               $ivCol.

          $fType

               [i]  The type of attribute to return.

          $pvAttrib

               [o]  The attribute.   This will be returned from the
               function as a string.

          $ivAttribMax

               [i]  The maximum size of $pvAttrib

          $ivAttribSize

               [o]  The size of the attribute string available to return
               to $pvAttrib.

          $ivAttrib

               [o]  The attribute.  This will be returned as an integer.

   * SQLBindCol

    Syntax
          `SQLBindCol($hStmt, $ivCol, $fType, $svValue, $ivValueMax,
          $ivValueSize);'

    Parameters

          $hStmt

               [i]  The statement handle as it is returned from
               `SQLAllocStmt()'.

          $ivCol

               [i]  The function will bind this column.

          $fType

               [i]  The data type to bind.

          $svValue

               [i]  A reference to a scalar that will store the data from
               a result set.

          $ivValueMax

               [i]  The maximum size allowed for the scalar referenced by
               $svValue

          $ivValueSize

               [i]  Size available to return to the scalar referenced by
               $svValue before `SQLFetch()' is called.

   * SQLFetch

    Syntax
          `SQLFetch($hStmt);'

    Parameters

          $hStmt

               [i]  The statement handle as it is returned from
               `SQLAllocStmt()'.

    Notes
          `SQLFetch()' returns data from each bound column to the scalar
          that was referenced by the $svValue parameter when the
          `SQLBindCol()' function was called.

   * SQLError

    Syntax
          `SQLError($hfEnv, $hfDbc, $hfStmt, $pvSqlState, $fNativeError,
          $pvErrorMsg, $ivErrorMsgMax, $ivErrorMsgSize);'

    Parameters

          $hfEnv

               [i]  The environment handle as it is returned from
               `SQLAllocEnv()' or SQL_NULL_HENV.

          $hfDbc

               [i]  The connection handle as it is returned from
               `SQLAllocConnect()' or SQL_NULL_HDBC.

          $hfStmt

               [i]  The statement handle as it is returned from
               `SQLAllocStmt()' or SQL_NULL_HSTMT.

          $pvSqlState

               [o]  This returns the SQLSTATE as a string.

          $fNativeError

               [o]  This returns a Native Error Code.

          $pvErrorMsg

               [o]  This returns an Error Message as a string.

          $ivErrorMsgMax

               [i]  The maximum size of $pvErrorMsg

          $ivErrorMsgSize

               [o]  The size of the string available to return to
               $pvErrorMsg

   * SQLFreeStmt

    Syntax
          `SQLFreeStmt($hStmt, $fOption);'

    Parameters

          $hStmt

               [i]  The statement handle as it is returned from
               `SQLAllocStmt()'.

          $fOption

               [i]  The action to be taken by the function.

   * SQLCancel

    Syntax
          `SQLCancel($hStmt);'

    Parameters

          $hStmt

               [i]  The statement handle as it is returned from
               `SQLAllocStmt()'.

   * SQLTransact

    Syntax
          `SQLTransact($hEnv, $hDbc, $fType);'

    Parameters

          $hEnv

               [i]  The environment handle as it is returned from
               `SQLAllocEnv()'.

          $hDbc

               [i]  The connection handle as it is returned from
               `SQLAllocConnect'.

          $fType

               [i]  The type of transaction to take

   * SQLDisconnect

    Syntax
          `SQLDisconnect($hDbc);'

    Parameters

          $hDbc

               [i]  The connection handle as it is returned from
               `SQLAllocConnect()'.

   * SQLFreeConnect

    Syntax
          `SQLFreeConnect($hDbc);'

    Parameters

          $hDbc

               [i]  The connection handle as it is returned from
               `SQLAllocConnect()'.

   * SQLFreeEnv

    Syntax
          `SQLFreeEnv($hEnv);'

    Parameters

          $hEnv

               [i]  The connection handle as it is returned from
               `SQLAllocEnv()'.

EXAMPLES
========

   `use iodbc;'

   #

   #To start I allocate handles and connect to my favorite data source.
Notice I check every return code.

   `checkretcode(&SQLAllocEnv($henv));'

   `checkretcode(SQLAllocConnect($henv, $hdbc));'

   `checkretcode(SQLConnect($hdbc, "favorite_datsource", SQL_NTS, "user",
SQL_NTS, "password", SQL_NTS));'

   `checkretcode(SQLAllocStmt($hdbc,$hstmt));'

   #

   #Then I execute a simple SQL statement

   `checkretcode(SQLExecDirect($hstmt, "SELECT * FROM sample_table",
SQL_NTS));'

   #Bind column one to $rgbValue

   `checkretcode(SQLBindCol($hstmt, 1, SQL_C_DEFAULT, \$rgbValue, 24,
SQL_NULL_DATA));'

   #Fetch all the rows and print them out

   `while(checkretcode(SQLFetch($hstmt))==SQL_SUCCESS){'

   `    print "$rgbValue\n";'

   `}'

   #

   #Finally close up shop by freeing statements and disconnecting.

   `checkretcode(SQLFreeStmt($hstmt, SQL_DROP));'

   `checkretcode(SQLDisconnect($hdbc));'

   `checkretcode(SQLFreeConnect($hdbc));'

   `checkretcode(SQLFreeEnv($henv));'

   #

   #This subroutine checks the return code to make sure that the function
executed correctly

   `sub checkretcode {'

   `    my $retcode = shift;'

   `    if (($retcode==SQL_SUCCESS)||($retcode==SQL_NO_DATA_FOUND)) {'

   `	return $retcode;'

   `    } else {'

   `	die "some error";'

   `    }'

   `}'

TO DO
=====

   * Further testing.  In particular add `SQLCancel()' and `SQLTransact()'
     to the test scripts.

   * Add ODBC 1.0 and then ODBC 2.0 support.

   * Put an DBD/DBI face on top of iODBC.

   * Improvement of the documentation.

BUGS
====

   Let me know if you find any.

AUTHOR
======

   J. Michael Mahan, mahanm@nextwork.rose-hulman.edu

SEE ALSO
========

   perl(1).

perl pragma to request less of something from the compiler
**********************************************************

NAME
====

   less - perl pragma to request less of something from the compiler

SYNOPSIS
========

     use less;  # unimplemented

DESCRIPTION
===========

   Currently unimplemented, this may someday be a compiler directive to
make certain trade-offs, such as perhaps

     use less 'memory';
     use less 'CPU';
     use less 'fat';

manipulate @INC at compile time
*******************************

NAME
====

   lib - manipulate @INC at compile time

SYNOPSIS
========

     use lib LIST;

     no lib LIST;

DESCRIPTION
===========

   This is a small simple module which simplifies the manipulation of @INC
at compile time.

   It is typically used to add extra directories to perl's search path so
that later use or require statements will find modules which are not
located on perl's default search path.

Adding directories to @INC
--------------------------

   The parameters to `use lib' are added to the start of the perl search
path. Saying

     use lib LIST;

   is *almost* the same as saying

     BEGIN { unshift(@INC, LIST) }

   For each directory in LIST (called $dir here) the lib module also
checks to see if a directory called $dir/$archname/auto exists.  If so the
$dir/$archname directory is assumed to be a corresponding architecture
specific directory and is added to @INC in front of $dir.

   To avoid memory leaks, all trailing duplicate entries in @INC are
removed.

Deleting directories from @INC
------------------------------

   You should normally only add directories to @INC.  If you need to
delete directories from @INC take care to only delete those which you
added yourself or which you are certain are not needed by other modules in
your script.  Other modules may have added directories which they need for
correct operation.

   The `no lib' statement deletes all instances of each named directory
from @INC.

   For each directory in LIST (called $dir here) the lib module also
checks to see if a directory called $dir/$archname/auto exists.  If so the
$dir/$archname directory is assumed to be a corresponding architecture
specific directory and is also deleted from @INC.

Restoring original @INC
-----------------------

   When the lib module is first loaded it records the current value of @INC
in an array `@lib::ORIG_INC'. To restore @INC to that value you can say

     @INC = @lib::ORIG_INC;

SEE ALSO
========

   FindBin - optional module which deals with paths relative to the source
file.

AUTHOR
======

   Tim Bunce, 2nd June 1995.

Apache Request C Library
************************

NAME
====

   libapreq - Apache Request C Library

SYNOPSIS
========

DESCRIPTION
===========

ApacheRequest
=============

req->parms
     This field is an Apache table that holds the parsed contents of GET
     and POST requests.  Example:

          table *data = req->parms;
          ap_table_set(data, "Key", "Value");

req->post_max
     Limit the size of POST data.  *ApacheRequest_parse* will return an
     error code if the size is exceeded:

          int status;
          ApacheRequest *req = ApacheRequest_new(r);

          req->post_max = 1204;
          if((status = ApacheRequest_parse(req)) != OK) {
              char *errmsg = ap_table_get(r->notes, "error-notes");
              ...
              return status;
          }

req->disable_uploads
     Disable file uploads.  *ApacheRequest_parse* will return an error
     code if a file upload is attempted:

          int status;
          ApacheRequest *req = ApacheRequest_new(r);

          req->disable_uploads = 1;
          if((status = ApacheRequest_parse(req)) != OK) {
              char *errmsg = ap_table_get(r->notes, "error-notes");
              ...
              return status;
          }

ApacheRequest *ApacheRequest_new (request_rec *r)
-------------------------------------------------

   This function creates a new ApacheRequest object using the given
*request_rec* structure:

     ApacheRequest *req = ApacheRequest_new(r);

int ApacheRequest_parse (ApacheRequest *req)
--------------------------------------------

   If the request method is GET or POST, the query string arguments and
the client form data will be read, parsed and saved.  In addition, if the
request method is POST and the *Content-type* is *multipart/form-data*,
the uploaded files will be written to temporary files which can be
accessed with the upload field names.  The return value is OK on success,
otherwise an error code that your handler should return.

const char *ApacheRequest_param (ApacheRequest *req, const char *key)
---------------------------------------------------------------------

   This function will return the value of the given parameter key:

     const char *value = ApacheRequest_param(req, "Key");

array_header *ApacheRequest_params (ApacheRequest *req, const char *key)
------------------------------------------------------------------------

   This function will return an *array_header* of values for the given
parameter key:

     array_header *values = ApacheRequest_params(req, "Key");

char *ApacheRequest_params_as_string (ApacheRequest *req, const char *key)
--------------------------------------------------------------------------

   This function will format multi-value parmeters into a comma delimited
string.

     char *list = ApacheRequest_params_as_string(req, "Key");

ApacheUpload *upload = ApacheRequest_upload (ApacheRequest *req)
----------------------------------------------------------------

   If the request *Content-type* was that of *multipart/form-data*, this
will return an ApacheUpload pointer containing the upload data, NULL
otherwise.  See ApacheUpload.

     ApacheUpload *upload = ApacheRequest_upload(req);

ApacheUpload
============

   The ApacheUpload structure holds all information for all uploaded files
and is accessed via the upload field of an ApacheRequest structure.

upload->name
     The name of the filefield parameter:

          char *name = upload->name;

upload->filename
     The name of the upload file:

          char *filename = upload->filename;

upload->fp
     A file pointer to the uploaded file:

          FILE *fp = upload->fp;

upload->size
     The size of the uploaded file in bytes:

          long size = upload->size;

upload->info
     The additional header information for the uploaded file:

          table *info = upload->info;
          const char *type = ap_table_get(info, "Content-type");

upload->next
     Pointer to the next ApacheUpload structure if multiple files were
     uploaded:

          ApacheUpload *uptr;
          for (uptr = ApacheRequest_upload(req); uptr; uptr = uptr->next) {
          	char *name = uptr->name;
          	FILE *fp   = uptr->fp;
          	...
          }

ApacheUpload *ApacheUpload_find (ApacheUpload *upload, char *name)
------------------------------------------------------------------

   Returns the ApacheUpload pointer associated with name or NULL if name
is not found in the list:

     ApacheUpload *upload = ApacheUpload_find(upload, name);

const char *ApacheUpload_info (ApacheUpload *upload, char *key)
---------------------------------------------------------------

   Shortcut for accessing the info table:

     const char *type = ApacheUpload_info(upload, "Content-Type");

const char *ApacheUpload_type (ApacheUpload *upload)
----------------------------------------------------

   Shortcut for accessing the uploaded file *Content-Type*:

     const char *type = ApacheUpload_type(upload);

ApacheCookie
============

ApacheCookie *ApacheCookie_new (request_rec *r, ...)
----------------------------------------------------

   This function creates a new ApacheCookie object, using the given
*request_request* and optional attribute arguments which are as follows:

-name
     Sets the name field to the given value.

-value
     Adds the value to values field.

-expires
     Sets the expires field to the calculated date string.  See
     *ApacheCookie_expires* for a listing of format options.  The default
     is NULL.

-domain
     Sets the domain field to the given value.  The default is NULL.

-path
     Sets the path field to the given value.  The default path is derived
     from the requested *uri*.

-secure
     Sets the secure field to true or false using a given string value of
     On or *Off*.  The default is *Off*.

   Example:

     ApacheCookie *c = ApacheCookie_new(r,
     			"-name",    "foo",
                            "-value",   "bar",
                            "-expires", "+3M",
                            "-domain",  ".cp.net",
                            "-path",    "/mypath/database",
                            "-secure",  "On",
                            NULL);

char *ApacheCookie_attr (ApacheCookie *c, char *key, char *val)
---------------------------------------------------------------

   This function is used to get or set a cookie attribute pair, accepting
the same attributes as the list above.  Example:

     char *name = ApacheCookie_attr(c, "-name"); /* same as c->name */
     (void *)ApacheCookie_attr(c, "-expires", "+3h");

ApacheCookieJar *ApacheCookie_parse (request_rec *r, const char *data)
----------------------------------------------------------------------

   This function parses the given data string or the incoming *Cookie*
header, returning an *ApacheCookieJar* of ApacheCookie objects.

   Example:

     int i;
     ApacheCookieJar *cookies = ApacheCookie_parse(r, NULL);
     for (i = 0; i < ApacheCookieJarItems(cookies); i++) {
         ApacheCookie *c = ApacheCookieJarFetch(cookies, i);
         int j;
         for (j = 0; j < ApacheCookieItems(c); j++) {
             char *name = c->name;
             char *value = ApacheCookieFetch(c, j);
             ...
         }
     }

int ApacheCookieItems (ApacheCookie *c)
---------------------------------------

   The number of values for the given cookie.

char *ApacheCookieFetch (ApacheCookie *c, int n)
------------------------------------------------

   The nth value for the given cookie.

void ApacheCookieAdd (ApacheCookie *c, char *value)
---------------------------------------------------

   Add a new value to the cookie.

int ApacheCookieJarItems (ApacheCookieJar *cookies)
---------------------------------------------------

   The number of cookies in the given cookie jar.

ApacheCookie *ApacheCookieJarFetch (ApacheCookieJar *cookies, int n)
--------------------------------------------------------------------

   The nth cookie in the given cookie jar.

void ApacheCookieJarAdd (ApacheCookieJar *cookies, ApacheCookie *c)
-------------------------------------------------------------------

   Add a new cookie to the cookie jar.

char *ApacheCookie_expires (ApacheCookie *c, char *time_str)
------------------------------------------------------------

   This function gets or sets the expiration date for cookie.  The
following forms are all valid for the *time_str* parmeter:

     +30s                              30 seconds from now
     +10m                              ten minutes from now
     +1h                               one hour from now
     -1d                               yesterday (i.e. "ASAP!")
     now                               immediately
     +3M                               in three months
     +10y                              in ten years time
     Thursday, 25-Apr-1999 00:40:33 GMT  at the indicated time & date

void ApacheCookie_bake (ApacheCookie *c)
----------------------------------------

   Put cookie in the oven to bake.  (Add a *Set-Cookie* header to the
outgoing headers table.)

     ApacheCookie_bake(c);

char *ApacheCookie_as_string (ApacheCookie *c)
----------------------------------------------

   Returns a string version of the cookie:

     ap_table_add(r->headers_out, "Set-Cookie", ApacheCookie_as_string(c));

CREDITS
=======

   This library is based on Perl modules by Lincoln Stein.

AUTHOR
======

   Doug MacEachern

Perl pragma to use and avoid POSIX locales for built-in operations
******************************************************************

NAME
====

   locale - Perl pragma to use and avoid POSIX locales for built-in
operations

SYNOPSIS
========

     @x = sort @y;	# ASCII sorting order
     {
         use locale;
         @x = sort @y;   # Locale-defined sorting order
     }
     @x = sort @y;	# ASCII sorting order again

DESCRIPTION
===========

   This pragma tells the compiler to enable (or disable) the use of POSIX
locales for built-in operations (LC_CTYPE for regular expressions, and
LC_COLLATE for string comparison).  Each "use locale" or "no locale"
affects statements to the end of the enclosing BLOCK.

   See Perllocale (perl.info), for more detailed
information on how Perl supports locales.

Perl pragma to allow unsafe constructs
**************************************

NAME
====

   loose - Perl pragma to allow unsafe constructs

SYNOPSIS
========

     use loose;

DESCRIPTION
===========

   loose.pm provides you with a slack, casual environment in which to
write your Perl code.  It doesn't get hung up on little things like
warnings and die() calls, it just lets them slide.

   Use loose.pm to help relieve stress at the work place.  loose helps to
make your error logs shorter by getting right of all those wordly warning
messages.

BUGS
====

   Yeah, probably.  Who cares?

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

libwww-perl cookbook
********************

NAME
====

   lwpcook - libwww-perl cookbook

DESCRIPTION
===========

   This document contain some examples that show typical usage of the
libwww-perl library.  You should consult the documentation for the
individual modules for more detail.

   All examples should be runnable programs. You can, in most cases, test
the code sections by piping the program text directly to perl.

GET
===

   It is very easy to use this library to just fetch documents from the
net.  The LWP::Simple module provides the get() function that return the
document specified by its URL argument:

     use LWP::Simple;
     $doc = get 'http://www.sn.no/libwww-perl/';

   or, as a perl one-liner using the getprint() function:

     perl -MLWP::Simple -e 'getprint "http://www.sn.no/libwww-perl/"'

   or, how about fetching the latest perl by running this command:

     perl -MLWP::Simple -e '
       getstore "ftp://ftp.sunet.se/pub/lang/perl/CPAN/src/latest.tar.gz",
                "perl.tar.gz"'

   You will probably first want to find a CPAN site closer to you by
running something like the following command:

     perl -MLWP::Simple -e 'getprint "http://www.perl.com/perl/CPAN/CPAN.html"'

   Enough of this simple stuff!  The LWP object oriented interface gives
you more control over the request sent to the server.  Using this
interface you have full control over headers sent and how you want to
handle the response returned.

     use LWP::UserAgent;
     $ua = LWP::UserAgent->new;
     $ua->agent("$0/0.1 " . $ua->agent);
     # $ua->agent("Mozilla/8.0") # pretend we are very capable browser

     $req = HTTP::Request->new(GET => 'http://www.linpro.no/lwp');
     $req->header('Accept' => 'text/html');

     # send request
     $res = $ua->request($req);

     # check the outcome
     if ($res->is_success) {
        print $res->content;
     } else {
        print "Error: " . $res->status_line . "\n";
     }

   The lwp-request program (alias GET) that is distributed with the
library can also be used to fetch documents from WWW servers.

HEAD
====

   If you just want to check if a document is present (i.e. the URL is
valid) try to run code that looks like this:

     use LWP::Simple;

     if (head($url)) {
        # ok document exists
     }

   The head() function really returns a list of meta-information about the
document.  The first three values of the list returned are the document
type, the size of the document, and the age of the document.

   More control over the request or access to all header values returned
require that you use the object oriented interface described for GET
above.  Just s/GET/HEAD/g.

POST
====

   There is no simple procedural interface for posting data to a WWW
server.  You must use the object oriented interface for this. The most
common POST operation is to access a WWW form application:

     use LWP::UserAgent;
     $ua = LWP::UserAgent->new;

     my $req = HTTP::Request->new(POST => 'http://www.perl.com/cgi-bin/BugGlimpse');
     $req->content_type('application/x-www-form-urlencoded');
     $req->content('match=www&errors=0');

     my $res = $ua->request($req);
     print $res->as_string;

   Lazy people use the HTTP::Request::Common module to set up a suitable
POST request message (it handles all the escaping issues) and has a
suitable default for the content_type:

     use HTTP::Request::Common qw(POST);
     use LWP::UserAgent;
     $ua = LWP::UserAgent->new;

     my $req = POST 'http://www.perl.com/cgi-bin/BugGlimpse',
                   [ search => 'www', errors => 0 ];

     print $ua->request($req)->as_string;

   The lwp-request program (alias POST) that is distributed with the
library can also be used for posting data.

PROXIES
=======

   Some sites use proxies to go through fire wall machines, or just as
cache in order to improve performance.  Proxies can also be used for
accessing resources through protocols not supported directly (or supported
badly :-) by the libwww-perl library.

   You should initialize your proxy setting before you start sending
requests:

     use LWP::UserAgent;
     $ua = LWP::UserAgent->new;
     $ua->env_proxy; # initialize from environment variables
     # or
     $ua->proxy(ftp  => 'http://proxy.myorg.com');
     $ua->proxy(wais => 'http://proxy.myorg.com');
     $ua->no_proxy(qw(no se fi));

     my $req = HTTP::Request->new(GET => 'wais://xxx.com/');
     print $ua->request($req)->as_string;

   The LWP::Simple interface will call env_proxy() for you automatically.
Applications that use the $ua->env_proxy() method will normally not use
the $ua->proxy() and $ua->no_proxy() methods.

   Some proxies also require that you send it a username/password in order
to let requests through.  You should be able to add the required header,
with something like this:

     use LWP::UserAgent;

     $ua = LWP::UserAgent->new;
     $ua->proxy(['http', 'ftp'] => 'http://proxy.myorg.com');

     $req = HTTP::Request->new('GET',"http://www.perl.com");
     $req->proxy_authorization_basic("proxy_user", "proxy_password");

     $res = $ua->request($req);
     print $res->content if $res->is_success;

   Replace `proxy.myorg.com', `proxy_user' and `proxy_password' with
something suitable for your site.

ACCESS TO PROTECTED DOCUMENTS
=============================

   Documents protected by basic authorization can easily be accessed like
this:

     use LWP::UserAgent;
     $ua = LWP::UserAgent->new;
     $req = HTTP::Request->new(GET => 'http://www.linpro.no/secret/');
     $req->authorization_basic('aas', 'mypassword');
     print $ua->request($req)->as_string;

   The other alternative is to provide a subclass of *LWP::UserAgent* that
overrides the get_basic_credentials() method. Study the *lwp-request*
program for an example of this.

COOKIES
=======

   Some sites like to play games with cookies.  By default LWP ignores
cookies provided by the servers it visits.  LWP will collect cookies and
respond to cookie requests if you set up a cookie jar.

     use LWP::UserAgent;
     use HTTP::Cookies;

     $ua = LWP::UserAgent->new;
     $ua->cookie_jar(HTTP::Cookies->new(file => "lwpcookies.txt",
     				     autosave => 1));

     # and then send requests just as you used to do
     $res = $ua->request(HTTP::Request->new(GET => "http://www.yahoo.no"));
     print $res->status_line, "\n";

   As you visit sites that send you cookies to keep, then the file
`lwpcookies.txt"' will grow.

HTTPS
=====

   URLs with https scheme are accessed in exactly the same way as with
http scheme, provided that an SSL interface module for LWP has been
properly installed (see the `README.SSL' file found in the libwww-perl
distribution for more details).  If no SSL interface is installed for LWP
to use, then you will get "501 Protocol scheme 'https' is not supported"
errors when accessing such URLs.

   Here's an example of fetching and printing a WWW page using SSL:

     use LWP::UserAgent;

     my $ua = LWP::UserAgent->new;
     my $req = HTTP::Request->new(GET => 'https://www.helsinki.fi/');
     my $res = $ua->request($req);
     if ($res->is_success) {
         print $res->as_string;
     } else {
         print "Failed: ", $res->status_line, "\n";
     }

MIRRORING
=========

   If you want to mirror documents from a WWW server, then try to run code
similar to this at regular intervals:

     use LWP::Simple;

     %mirrors = (
        'http://www.sn.no/'             => 'sn.html',
        'http://www.perl.com/'          => 'perl.html',
        'http://www.sn.no/libwww-perl/' => 'lwp.html',
        'gopher://gopher.sn.no/'        => 'gopher.html',
     );

     while (($url, $localfile) = each(%mirrors)) {
        mirror($url, $localfile);
     }

   Or, as a perl one-liner:

     perl -MLWP::Simple -e 'mirror("http://www.perl.com/", "perl.html")';

   The document will not be transfered unless it has been updated.

LARGE DOCUMENTS
===============

   If the document you want to fetch is too large to be kept in memory,
then you have two alternatives.  You can instruct the library to write the
document content to a file (second $ua->request() argument is a file name):

     use LWP::UserAgent;
     $ua = LWP::UserAgent->new;

     my $req = HTTP::Request->new(GET =>
                   'http://www.linpro.no/lwp/libwww-perl-5.46.tar.gz');
     $res = $ua->request($req, "libwww-perl.tar.gz");
     if ($res->is_success) {
        print "ok\n";
     }
     else {
        print $res->status_line, "\n";
     }

   Or you can process the document as it arrives (second $ua->request()
argument is a code reference):

     use LWP::UserAgent;
     $ua = LWP::UserAgent->new;
     $URL = 'ftp://ftp.unit.no/pub/rfc/rfc-index.txt';

     my $expected_length;
     my $bytes_received = 0;
     my $res =
        $ua->request(HTTP::Request->new(GET => $URL),
                  sub {
                      my($chunk, $res) = @_;
                      $bytes_received += length($chunk);
     	           unless (defined $expected_length) {
     	              $expected_length = $res->content_length || 0;
                      }
     		   if ($expected_length) {
     		        printf STDERR "%d%% - ",
     	                          100 * $bytes_received / $expected_length;
                      }
     	           print STDERR "$bytes_received bytes received\n";

     # XXX Should really do something with the chunk itself
     	           # print $chunk;
                    });
        print $res->status_line, "\n";

COPYRIGHT
=========

   Copyright 1996-2000, Gisle Aas

   This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

easy one-stop module shopping
*****************************

NAME
====

   *mods* - easy one-stop module shopping

SYNOPSIS
========

     use mods;   # Various defaults.

     use mods qw(SomePkg Other::Pkg(somefunc, $somevar));
     somefunc($somevar);

     use mods qw(foo bar());    # No imports from bar.pm; default from foo.pm.

   More options:

     use mods q{
       diagnostics,     # Integral comments! Commas optional.
       Foo (bar, baz)   # Whitespace ignored.
       Quux   Jolt();   # As you think.
       vars (	    # Multilines fine.
     	 $foo, $bar, $baz
     	)
       !strict(refs)    # Unimport.
       $foo, $bar;      # Alternate declaration of vars.
       {$bar=7}	    # Compile-time code.
       <this, $that, @theother!> # Export; &this and $that optional.
       [Foo, Bar::Baz]  # Inherit from these.
     };

DESCRIPTION
===========

   This pragmatic module is intended as a way to reduce clutter in the
prologue of a typical OO module, which often contains a large number of
repetitive directives. Encouraging a clean programming style is the intent.

   Each import-syntax item in the argument corresponds to a module to be
imported. Usage is very similar to normal use statements: no extra
arguments runs a default importation; empty parens bypass importation; and
arguments within parens, assumed to be literal and separated by commas
and/or whitespace, imports those items. An exclamation point before the
statement does an unimportation, like the no keyword. Note that both
standard modules and compiler pragmas are supported.

   Code inside braces is evaluated at compile time, as if it were inside a
BEGIN block.

   Words inside angle brackets are taken to be things to be exported with
the Exporter module (which is loaded for you, and your *@ISA*
appropriately extended). They are placed in *@EXPORT_OK*, or *@EXPORT* if
you append an exclamation point. If variables (vs. functions), they are
declared as globals for you.

   Words inside square brackets declare superclasses: they append to
*@ISA*.

   Variable names (scalar, array or hash) alone predeclare the variable,
as with vars.

   "#" introduces comments until end-of-line. If multiple arguments are
received, they are first joined together as you would expect.

DEFAULTS
========

   Without you needing to specify it, *mods* automatically:

   * Uses strict.

   * Uses integer.

   * Declares some common package variables for you (with vars): *@ISA*,
     *@EXPORT*, *@EXPORT_OK*, *%EXPORT_TAGS*, *@EXPORT_FAIL*, $AUTOLOAD,
     and $VERSION.

   If any of these defaults causes a problem in your module which cannot
be trivially reversed, precede all other directives by a tilde (`~') to
suppress them.

BUGS
====

   Implementation of *sim_use* workhorse function is incomprehensible to
the author.

AUTHORS
=======

   Jesse Glick, *jglick@sig.bsh.com*

REVISION
========

   X<$Format: "`$Source$' last modified $Date$ release $modsRelease$.
$Copyright$"$> `mods/lib/mods.pm' last modified Fri, 12 Sep 1997 23:21:20
-0400 release 0.004. Copyright (c) 1997 Strategic Interactive Group. All
rights reserved. This program is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

perl pragma to set default disciplines for input and output
***********************************************************

NAME
====

   open - perl pragma to set default disciplines for input and output

SYNOPSIS
========

     use open IN => ":crlf", OUT => ":raw";

DESCRIPTION
===========

   The open pragma is used to declare one or more default disciplines for
I/O operations.  Any open() and readpipe() (aka qx//) operators found
within the lexical scope of this pragma will use the declared defaults.
Neither open() with an explicit set of disciplines, nor sysopen() are
influenced by this pragma.

   Only the two pseudo-disciplines ":raw" and ":crlf" are currently
available.

   The ":raw" discipline corresponds to "binary mode" and the ":crlf"
discipline corresponds to "text mode" on platforms that distinguish
between the two modes when opening files (which is many DOS-like
platforms, including Windows).  These two disciplines are currently no-ops
on platforms where binmode() is a no-op, but will be supported everywhere
in future.

UNIMPLEMENTED FUNCTIONALITY
===========================

   Full-fledged support for I/O disciplines is currently unimplemented.
When they are eventually supported, this pragma will serve as one of the
interfaces to declare default disciplines for all I/O.

   In future, any default disciplines declared by this pragma will be
available by the special discipline name ":DEFAULT", and could be used
within handle constructors that allow disciplines to be specified.  This
would make it possible to stack new disciplines over the default ones.

     open FH, "<:para :DEFAULT", $file or die "can't open $file: $!";

   Socket and directory handles will also support disciplines in future.

   Full support for I/O disciplines will enable all of the supported
disciplines to work on all platforms.

SEE ALSO
========

   `"binmode"', see Perlfunc (perl.info), `"open"', see
Perlfunc (perl.info), `"open"', see Perlunicode (perl.info),

Perl pragma to restrict unsafe operations when compiling
********************************************************

NAME
====

   ops - Perl pragma to restrict unsafe operations when compiling

SYNOPSIS
========

     perl -Mops=:default ...    # only allow reasonably safe operations

     perl -M-ops=system ...     # disable the 'system' opcode

DESCRIPTION
===========

   Since the ops pragma currently has an irreversible global effect, it is
only of significant practical use with the -M option on the command line.

   See the Opcode, module for information about opcodes,
optags, opmasks and important information about safety.

SEE ALSO
========

   Opcode(3), Safe(3), perlrun(3)

Package for overloading perl operations
***************************************

NAME
====

   overload - Package for overloading perl operations

SYNOPSIS
========

     package SomeThing;

     use overload
     	'+' => \&myadd,
     	'-' => \&mysub;
     	# etc
     ...

     package main;
     $a = new SomeThing 57;
     $b=5+$a;
     ...
     if (overload::Overloaded $b) {...}
     ...
     $strval = overload::StrVal $b;

DESCRIPTION
===========

Declaration of overloaded functions
-----------------------------------

   The compilation directive

     package Number;
     use overload
     	"+" => \&add,
     	"*=" => "muas";

   declares function Number::add() for addition, and method muas() in the
"class" Number (or one of its base classes) for the assignment form `*='
of multiplication.

   Arguments of this directive come in (key, value) pairs.  Legal values
are values legal inside a `&{ ... }' call, so the name of a subroutine, a
reference to a subroutine, or an anonymous subroutine will all work.  Note
that values specified as strings are interpreted as methods, not
subroutines.  Legal keys are listed below.

   The subroutine add will be called to execute `$a+$b' if $a is a
reference to an object blessed into the package Number, or if $a is not an
object from a package with defined mathemagic addition, but $b is a
reference to a Number.  It can also be called in other situations, like
`$a+=7', or `$a++'.  See `MAGIC AUTOGENERATION' in this node.
(Mathemagical methods refer to methods triggered by an overloaded
mathematical operator.)

   Since overloading respects inheritance via the @ISA hierarchy, the
above declaration would also trigger overloading of + and `*=' in all the
packages which inherit from Number.

Calling Conventions for Binary Operations
-----------------------------------------

   The functions specified in the `use overload ...' directive are called
with three (in one particular case with four, see `Last Resort' in this
node) arguments.  If the corresponding operation is binary, then the first
two arguments are the two arguments of the operation.  However, due to
general object calling conventions, the first argument should always be an
object in the package, so in the situation of `7+$a', the order of the
arguments is interchanged.  It probably does not matter when implementing
the addition method, but whether the arguments are reversed is vital to
the subtraction method.  The method can query this information by
examining the third argument, which can take three different values:

FALSE
     the order of arguments is as in the current operation.

TRUE
     the arguments are reversed.

undef
     the current operation is an assignment variant (as in `$a+=7'), but
     the usual function is called instead.  This additional information
     can be used to generate some optimizations.  Compare `Calling
     Conventions for Mutators' in this node.

Calling Conventions for Unary Operations
----------------------------------------

   Unary operation are considered binary operations with the second
argument being undef.  Thus the functions that overloads `{"++"}' is
called with arguments `($a,undef,'')' when $a++ is executed.

Calling Conventions for Mutators
--------------------------------

   Two types of mutators have different calling conventions:

`++' and -
     The routines which implement these operators are expected to actually
     mutate their arguments.  So, assuming that $obj is a reference to a
     number,

          sub incr { my $n = $ {$_[0]}; ++$n; $_[0] = bless \$n}

     is an appropriate implementation of overloaded `++'.  Note that

          sub incr { ++$ {$_[0]} ; shift }

     is OK if used with preincrement and with postincrement. (In the case
     of postincrement a copying will be performed, see `Copy Constructor'
     in this node.)

`x=' and other assignment versions
     There is nothing special about these methods.  They may change the
     value of their arguments, and may leave it as is.  The result is going
     to be assigned to the value in the left-hand-side if different from
     this value.

     This allows for the same method to be used as overloaded `+=' and +.
     Note that this is allowed, but not recommended, since by the semantic
     of `"Fallback"' in this node Perl will call the method for + anyway,
     if `+=' is not overloaded.

   *Warning.*  Due to the presense of assignment versions of operations,
routines which may be called in assignment context may create
self-referential structures.  Currently Perl will not free self-referential
structures until cycles are `explicitly' broken.  You may get problems
when traversing your structures too.

   Say,

     use overload '+' => sub { bless [ \$_[0], \$_[1] ] };

   is asking for trouble, since for code `$obj += $foo' the subroutine is
called as `$obj = add($obj, $foo, undef)', or `$obj = [\$obj, \$foo]'.  If
using such a subroutine is an important optimization, one can overload
`+=' explicitly by a non-"optimized" version, or switch to non-optimized
version if `not defined $_[2]' (see `Calling Conventions for Binary
Operations' in this node).

   Even if no explicit assignment-variants of operators are present in the
script, they may be generated by the optimizer.  Say, `",$obj,"' or `',' .
$obj . ','' may be both optimized to

     my $tmp = ',' . $obj;    $tmp .= ',';

Overloadable Operations
-----------------------

   The following symbols can be specified in `use overload' directive:

   * *Arithmetic operations*
          "+", "+=", "-", "-=", "*", "*=", "/", "/=", "%", "%=",
          "**", "**=", "<<", "<<=", ">>", ">>=", "x", "x=", ".", ".=",

     For these operations a substituted non-assignment variant can be
     called if the assignment variant is not available.  Methods for
     operations "+", "-", "`+='", and "`-='" can be called to
     automatically generate increment and decrement methods.  The
     operation "-" can be used to autogenerate missing methods for unary
     minus or abs.

     See `"MAGIC AUTOGENERATION"' in this node, `"Calling Conventions for
     Mutators"' in this node and `"Calling Conventions for Binary
     Operations"' in this node) for details of these substitutions.

   * *Comparison operations*
          "<",  "<=", ">",  ">=", "==", "!=", "<=>",
          "lt", "le", "gt", "ge", "eq", "ne", "cmp",

     If the corresponding "spaceship" variant is available, it can be used
     to substitute for the missing operation.  During sorting arrays, cmp
     is used to compare values subject to `use overload'.

   * *Bit operations*
          "&", "^", "|", "neg", "!", "~",

     "neg" stands for unary minus.  If the method for neg is not
     specified, it can be autogenerated using the method for subtraction.
     If the method for "!" is not specified, it can be autogenerated using
     the methods for "`bool'", or "`\"\"'", or "`0+'".

   * *Increment and decrement*
          "++", "--",

     If undefined, addition and subtraction methods can be used instead.
     These operations are called both in prefix and postfix form.

   * *Transcendental functions*
          "atan2", "cos", "sin", "exp", "abs", "log", "sqrt",

     If abs is unavailable, it can be autogenerated using methods for "<"
     or "<=>" combined with either unary minus or subtraction.

   * *Boolean, string and numeric conversion*
          "bool", "\"\"", "0+",

     If one or two of these operations are not overloaded, the remaining
     ones can be used instead.  `bool' is used in the flow control
     operators (like while) and for the ternary "`?:'" operation.  These
     functions can return any arbitrary Perl value.  If the corresponding
     operation for this value is overloaded too, that operation will be
     called again with this value.

   * *Iteration*
          "<>"

     If not overloaded, the argument will be converted to a filehandle or
     glob (which may require a stringification).  The same overloading
     happens both for the *read-filehandle* syntax `<$var>' and *globbing*
     syntax `<${var}>'.

   * Dereferencing
          '${}', '@{}', '%{}', '&{}', '*{}'.

     If not overloaded, the argument will be dereferenced *as is*, thus
     should be of correct type.  These functions should return a reference
     of correct type, or another object with overloaded dereferencing.

   * Special
          "nomethod", "fallback", "=",

     see `SPECIAL SYMBOLS FOR `use overload' in this node'.

   See `"Fallback"' in this node for an explanation of when a missing
method can be autogenerated.

   A computer-readable form of the above table is available in the hash
%overload::ops, with values being space-separated lists of names:

     with_assign	  => '+ - * / % ** << >> x .',
     assign		  => '+= -= *= /= %= **= <<= >>= x= .=',
     num_comparison	  => '< <= > >= == !=',
     '3way_comparison'=> '<=> cmp',
     str_comparison	  => 'lt le gt ge eq ne',
     binary		  => '& | ^',
     unary		  => 'neg ! ~',
     mutators	  => '++ --',
     func		  => 'atan2 cos sin exp abs log sqrt',
     conversion	  => 'bool "" 0+',
     iterators	  => '<>',
     dereferencing	  => '${} @{} %{} &{} *{}',
     special	  => 'nomethod fallback ='

Inheritance and overloading
---------------------------

   Inheritance interacts with overloading in two ways.

Strings as values of `use overload' directive
     If value in

          use overload key => value;

     is a string, it is interpreted as a method name.

Overloading of an operation is inherited by derived classes
     Any class derived from an overloaded class is also overloaded.  The
     set of overloaded methods is the union of overloaded methods of all
     the ancestors. If some method is overloaded in several ancestor, then
     which description will be used is decided by the usual inheritance
     rules:

     If A inherits from B and C (in this order), B overloads + with
     `\&D::plus_sub', and C overloads + by `"plus_meth"', then the
     subroutine `D::plus_sub' will be called to implement operation + for
     an object in package A.

   Note that since the value of the `fallback' key is not a subroutine,
its inheritance is not governed by the above rules.  In the current
implementation, the value of `fallback' in the first overloaded ancestor
is used, but this is accidental and subject to change.

SPECIAL SYMBOLS FOR `use overload'
==================================

   Three keys are recognized by Perl that are not covered by the above
description.

Last Resort
-----------

   `"nomethod"' should be followed by a reference to a function of four
parameters.  If defined, it is called when the overloading mechanism
cannot find a method for some operation.  The first three arguments of
this function coincide with the arguments for the corresponding method if
it were found, the fourth argument is the symbol corresponding to the
missing method.  If several methods are tried, the last one is used.  Say,
`1-$a' can be equivalent to

     &nomethodMethod($a,1,1,"-")

   if the pair `"nomethod" => "nomethodMethod"' was specified in the `use
overload' directive.

   If some operation cannot be resolved, and there is no function assigned
to `"nomethod"', then an exception will be raised via die()- unless
`"fallback"' was specified as a key in `use overload' directive.

Fallback
--------

   The key `"fallback"' governs what to do if a method for a particular
operation is not found.  Three different cases are possible depending on
the value of `"fallback"':

   * undef

     Perl tries to use a substituted method (see `MAGIC AUTOGENERATION' in
     this node).  If this fails, it then tries to calls `"nomethod"'
     value; if missing, an exception will be raised.

   * TRUE

     The same as for the undef value, but no exception is raised.  Instead,
     it silently reverts to what it would have done were there no `use
     overload' present.

   * defined, but FALSE

     No autogeneration is tried.  Perl tries to call `"nomethod"' value,
     and if this is missing, raises an exception.

   *Note.* `"fallback"' inheritance via @ISA is not carved in stone yet,
see `"Inheritance and overloading"' in this node.

Copy Constructor
----------------

   The value for `"="' is a reference to a function with three arguments,
i.e., it looks like the other values in `use overload'. However, it does
not overload the Perl assignment operator. This would go against Camel
hair.

   This operation is called in the situations when a mutator is applied to
a reference that shares its object with some other reference, such as

     $a=$b;
     ++$a;

   To make this change $a and not change $b, a copy of `$$a' is made, and
$a is assigned a reference to this new object.  This operation is done
during execution of the `++$a', and not during the assignment, (so before
the increment `$$a' coincides with `$$b').  This is only done if `++' is
expressed via a method for `'++'' or `'+='' (or `nomethod').  Note that if
this operation is expressed via '+' a nonmutator, i.e., as in

     $a=$b;
     $a=$a+1;

   then `$a' does not reference a new copy of `$$a', since $$a does not
appear as lvalue when the above code is executed.

   If the copy constructor is required during the execution of some
mutator, but a method for `'='' was not specified, it can be autogenerated
as a string copy if the object is a plain scalar.

Example
     The actually executed code for

          $a=$b;
                  Something else which does not modify $a or $b....
          ++$a;

     may be

          $a=$b;
                  Something else which does not modify $a or $b....
          $a = $a->clone(undef,"");
                  $a->incr(undef,"");

     if $b was mathemagical, and `'++'' was overloaded with `\&incr',
     `'='' was overloaded with `\&clone'.

   Same behaviour is triggered by `$b = $a++', which is consider a synonym
for `$b = $a; ++$a'.

MAGIC AUTOGENERATION
====================

   If a method for an operation is not found, and the value for
`"fallback"' is TRUE or undefined, Perl tries to autogenerate a substitute
method for the missing operation based on the defined operations.
Autogenerated method substitutions are possible for the following
operations:

*Assignment forms of arithmetic operations*
     `$a+=$b' can use the method for `"+"' if the method for `"+="' is not
     defined.

*Conversion operations*
     String, numeric, and boolean conversion are calculated in terms of one
     another if not all of them are defined.

*Increment and decrement*
     The `++$a' operation can be expressed in terms of `$a+=1' or `$a+1',
     and `$a--' in terms of `$a-=1' and `$a-1'.

`abs($a)'
     can be expressed in terms of `$a<0' and `-$a' (or `0-$a').

*Unary minus*
     can be expressed in terms of subtraction.

Negation
     ! and not can be expressed in terms of boolean conversion, or string
     or numerical conversion.

Concatenation
     can be expressed in terms of string conversion.

*Comparison operations*
     can be expressed in terms of its "spaceship" counterpart: either
     `<=>' or cmp:

          <, >, <=, >=, ==, != 	in terms of <=>
          lt, gt, le, ge, eq, ne 	in terms of cmp

Iterator
          <>				in terms of builtin operations

Dereferencing
          ${} @{} %{} &{} *{}		in terms of builtin operations

*Copy operator*
     can be expressed in terms of an assignment to the dereferenced value,
     if this value is a scalar and not a reference.

Losing overloading
==================

   The restriction for the comparison operation is that even if, for
example, `cmp' should return a blessed reference, the autogenerated `lt'
function will produce only a standard logical value based on the numerical
value of the result of `cmp'.  In particular, a working numeric conversion
is needed in this case (possibly expressed in terms of other conversions).

   Similarly, `.='  and `x=' operators lose their mathemagical properties
if the string conversion substitution is applied.

   When you chop() a mathemagical object it is promoted to a string and its
mathemagical properties are lost.  The same can happen with other
operations as well.

Run-time Overloading
====================

   Since all use directives are executed at compile-time, the only way to
change overloading during run-time is to

     eval 'use overload "+" => \&addmethod';

   You can also use

     eval 'no overload "+", "--", "<="';

   though the use of these constructs during run-time is questionable.

Public functions
================

   Package `overload.pm' provides the following public functions:

overload::StrVal(arg)
     Gives string value of `arg' as in absence of stringify overloading.

overload::Overloaded(arg)
     Returns true if `arg' is subject to overloading of some operations.

overload::Method(obj,op)
     Returns undef or a reference to the method that implements op.

Overloading constants
=====================

   For some application Perl parser mangles constants too much.  It is
possible to hook into this process via overload::constant() and
overload::remove_constant() functions.

   These functions take a hash as an argument.  The recognized keys of
this hash are

integer
     to overload integer constants,

float
     to overload floating point constants,

binary
     to overload octal and hexadecimal constants,

q
     to overload q-quoted strings, constant pieces of qq- and `qx'-quoted
     strings and here-documents,

qr
     to overload constant pieces of regular expressions.

   The corresponding values are references to functions which take three
arguments: the first one is the *initial* string form of the constant, the
second one is how Perl interprets this constant, the third one is how the
constant is used.  Note that the initial string form does not contain
string delimiters, and has backslashes in backslash-delimiter combinations
stripped (thus the value of delimiter is not relevant for processing of
this string).  The return value of this function is how this constant is
going to be interpreted by Perl.  The third argument is undefined unless
for overloaded q- and qr- constants, it is q in single-quote context
(comes from strings, regular expressions, and single-quote HERE
documents), it is tr for arguments of tr/y operators, it is s for
right-hand side of s-operator, and it is qq otherwise.

   Since an expression `"ab$cd,,"' is just a shortcut for `'ab' . $cd .
',,'', it is expected that overloaded constant strings are equipped with
reasonable overloaded catenation operator, otherwise absurd results will
result.  Similarly, negative numbers are considered as negations of
positive constants.

   Note that it is probably meaningless to call the functions
overload::constant() and overload::remove_constant() from anywhere but
import() and unimport() methods.  From these methods they may be called as

     sub import {
       shift;
       return unless @_;
       die "unknown import: @_" unless @_ == 1 and $_[0] eq ':constant';
       overload::constant integer => sub {Math::BigInt->new(shift)};
     }

   BUGS Currently overloaded-ness of constants does not propagate into
`eval '...''.

IMPLEMENTATION
==============

   What follows is subject to change RSN.

   The table of methods for all operations is cached in magic for the
symbol table hash for the package.  The cache is invalidated during
processing of `use overload', `no overload', new function definitions, and
changes in @ISA. However, this invalidation remains unprocessed until the
next blessing into the package. Hence if you want to change overloading
structure dynamically, you'll need an additional (fake) blessing to update
the table.

   (Every SVish thing has a magic queue, and magic is an entry in that
queue.  This is how a single variable may participate in multiple forms of
magic simultaneously.  For instance, environment variables regularly have
two forms at once: their %ENV magic and their taint magic. However, the
magic which implements overloading is applied to the stashes, which are
rarely used directly, thus should not slow down Perl.)

   If an object belongs to a package using overload, it carries a special
flag.  Thus the only speed penalty during arithmetic operations without
overloading is the checking of this flag.

   In fact, if `use overload' is not present, there is almost no overhead
for overloadable operations, so most programs should not suffer measurable
performance penalties.  A considerable effort was made to minimize the
overhead when overload is used in some package, but the arguments in
question do not belong to packages using overload.  When in doubt, test
your speed with `use overload' and without it.  So far there have been no
reports of substantial speed degradation if Perl is compiled with
optimization turned on.

   There is no size penalty for data if overload is not used. The only
size penalty if overload is used in some package is that all the packages
acquire a magic during the next blessing into the package. This magic is
three-words-long for packages without overloading, and carries the cache
table if the package is overloaded.

   Copying (`$a=$b') is shallow; however, a one-level-deep copying is
carried out before any operation that can imply an assignment to the
object $a (or $b) refers to, like `$a++'.  You can override this behavior
by defining your own copy constructor (see `"Copy Constructor"' in this
node).

   It is expected that arguments to methods that are not explicitly
supposed to be changed are constant (but this is not enforced).

Metaphor clash
==============

   One may wonder why the semantic of overloaded = is so counter intuitive.
If it *looks* counter intuitive to you, you are subject to a metaphor
clash.

   Here is a Perl object metaphor:

   *  object is a reference to blessed data*

   and an arithmetic metaphor:

   *  object is a thing by itself*.

   The main problem of overloading = is the fact that these metaphors
imply different actions on the assignment `$a = $b' if $a and $b are
objects.  Perl-think implies that $a becomes a reference to whatever $b
was referencing.  Arithmetic-think implies that the value of "object" $a
is changed to become the value of the object $b, preserving the fact that
$a and $b are separate entities.

   The difference is not relevant in the absence of mutators.  After a
Perl-way assignment an operation which mutates the data referenced by $a
would change the data referenced by $b too.  Effectively, after `$a = $b'
values of $a and $b become *indistinguishable*.

   On the other hand, anyone who has used algebraic notation knows the
expressive power of the arithmetic metaphor.  Overloading works hard to
enable this metaphor while preserving the Perlian way as far as possible.
Since it is not not possible to freely mix two contradicting metaphors,
overloading allows the arithmetic way to write things *as far as all the
mutators are called via overloaded access only*.  The way it is done is
described in `Copy Constructor' in this node.

   If some mutator methods are directly applied to the overloaded values,
one may need to *explicitly unlink* other values which references the same
value:

     $a = new Data 23;
     ...
     $b = $a;		# $b is "linked" to $a
     ...
     $a = $a->clone;	# Unlink $b from $a
     $a->increment_by(4);

   Note that overloaded access makes this transparent:

     $a = new Data 23;
     $b = $a;		# $b is "linked" to $a
     $a += 4;		# would unlink $b automagically

   However, it would not make

     $a = new Data 23;
     $a = 4;		# Now $a is a plain 4, not 'Data'

   preserve "objectness" of $a.  But Perl *has* a way to make assignments
to an object do whatever you want.  It is just not the overload, but
tie()ing interface (see `tie', see Perlfunc (perl.info)).
Adding a FETCH() method which returns the object itself, and STORE()
method which changes the value of the object, one can reproduce the
arithmetic metaphor in its completeness, at least for variables which were
tie()d from the start.

   (Note that a workaround for a bug may be needed, see `"BUGS"' in this
node.)

Cookbook
========

   Please add examples to what follows!

Two-face scalars
----------------

   Put this in `two_face.pm' in your Perl library directory:

     package two_face;		# Scalars with separate string and
                                   # numeric values.
     sub new { my $p = shift; bless [@_], $p }
     use overload '""' => \&str, '0+' => \&num, fallback => 1;
     sub num {shift->[1]}
     sub str {shift->[0]}

   Use it as follows:

     require two_face;
     my $seven = new two_face ("vii", 7);
     printf "seven=$seven, seven=%d, eight=%d\n", $seven, $seven+1;
     print "seven contains `i'\n" if $seven =~ /i/;

   (The second line creates a scalar which has both a string value, and a
numeric value.)  This prints:

     seven=vii, seven=7, eight=8
     seven contains `i'

Two-face references
-------------------

   Suppose you want to create an object which is accessible as both an
array reference, and a hash reference, similar to the builtin
`array-accessible-as-a-hash|perlref' in this node builtin Perl type.  Let
us make it better than the builtin type, there will be no restriction that
you cannot use the index 0 of your array.

     package two_refs;
     use overload '%{}' => \&gethash, '@{}' => sub { $ {shift()} };
     sub new {
       my $p = shift;
       bless \ [@_], $p;
     }
     sub gethash {
       my %h;
       my $self = shift;
       tie %h, ref $self, $self;
       \%h;
     }

     sub TIEHASH { my $p = shift; bless \ shift, $p }
     my %fields;
     my $i = 0;
     $fields{$_} = $i++ foreach qw{zero one two three};
     sub STORE {
       my $self = ${shift()};
       my $key = $fields{shift()};
       defined $key or die "Out of band access";
       $$self->[$key] = shift;
     }
     sub FETCH {
       my $self = ${shift()};
       my $key = $fields{shift()};
       defined $key or die "Out of band access";
       $$self->[$key];
     }

   Now one can access an object using both the array and hash syntax:

     my $bar = new two_refs 3,4,5,6;
     $bar->[2] = 11;
     $bar->{two} == 11 or die 'bad hash fetch';

   Note several important features of this example.  First of all, the
*actual* type of $bar is a scalar reference, and we do not overload the
scalar dereference.  Thus we can get the *actual* non-overloaded contents
of $bar by just using `$$bar' (what we do in functions which overload
dereference).  Similarly, the object returned by the TIEHASH() method is a
scalar reference.

   Second, we create a new tied hash each time the hash syntax is used.
This allows us not to worry about a possibility of a reference loop, would
would lead to a memory leak.

   Both these problems can be cured.  Say, if we want to overload hash
dereference on a reference to an object which is *implemented* as a hash
itself, the only problem one has to circumvent is how to access this
*actual* hash (as opposed to the *virtual* exhibited by overloaded
dereference operator).  Here is one possible fetching routine:

     sub access_hash {
       my ($self, $key) = (shift, shift);
       my $class = ref $self;
       bless $self, 'overload::dummy'; # Disable overloading of %{}
       my $out = $self->{$key};
       bless $self, $class;	# Restore overloading
       $out;
     }

   To move creation of the tied hash on each access, one may an extra
level of indirection which allows a non-circular structure of references:

     package two_refs1;
     use overload '%{}' => sub { ${shift()}->[1] },
                  '@{}' => sub { ${shift()}->[0] };
     sub new {
       my $p = shift;
       my $a = [@_];
       my %h;
       tie %h, $p, $a;
       bless \ [$a, \%h], $p;
     }
     sub gethash {
       my %h;
       my $self = shift;
       tie %h, ref $self, $self;
       \%h;
     }

     sub TIEHASH { my $p = shift; bless \ shift, $p }
     my %fields;
     my $i = 0;
     $fields{$_} = $i++ foreach qw{zero one two three};
     sub STORE {
       my $a = ${shift()};
       my $key = $fields{shift()};
       defined $key or die "Out of band access";
       $a->[$key] = shift;
     }
     sub FETCH {
       my $a = ${shift()};
       my $key = $fields{shift()};
       defined $key or die "Out of band access";
       $a->[$key];
     }

   Now if $baz is overloaded like this, then `$bar' is a reference to a
reference to the intermediate array, which keeps a reference to an actual
array, and the access hash.  The tie()ing object for the access hash is
also a reference to a reference to the actual array, so

   * There are no loops of references.

   * Both "objects" which are blessed into the class `two_refs1' are
     references to a reference to an array, thus references to a scalar.
     Thus the accessor expression `$$foo->[$ind]' involves no overloaded
     operations.

Symbolic calculator
-------------------

   Put this in `symbolic.pm' in your Perl library directory:

     package symbolic;		# Primitive symbolic calculator
     use overload nomethod => \&wrap;

     sub new { shift; bless ['n', @_] }
     sub wrap {
       my ($obj, $other, $inv, $meth) = @_;
       ($obj, $other) = ($other, $obj) if $inv;
       bless [$meth, $obj, $other];
     }

   This module is very unusual as overloaded modules go: it does not
provide any usual overloaded operators, instead it provides the `Last
Resort' in this node operator `nomethod'.  In this example the
corresponding subroutine returns an object which encapsulates operations
done over the objects: `new symbolic 3' contains `['n', 3]', `2 + new
symbolic 3' contains `['+', 2, ['n', 3]]'.

   Here is an example of the script which "calculates" the side of
circumscribed octagon using the above package:

     require symbolic;
     my $iter = 1;			# 2**($iter+2) = 8
     my $side = new symbolic 1;
     my $cnt = $iter;

     while ($cnt--) {
       $side = (sqrt(1 + $side**2) - 1)/$side;
     }
     print "OK\n";

   The value of $side is

     ['/', ['-', ['sqrt', ['+', 1, ['**', ['n', 1], 2]],
     	               undef], 1], ['n', 1]]

   Note that while we obtained this value using a nice little script,
there is no simple way to use this value.  In fact this value may be
inspected in debugger (see Perldebug (perl.info)), but
ony if bareStringify Option is set, and not via p command.

   If one attempts to print this value, then the overloaded operator ""
will be called, which will call `nomethod' operator.  The result of this
operator will be stringified again, but this result is again of type
`symbolic', which will lead to an infinite loop.

   Add a pretty-printer method to the module `symbolic.pm':

     sub pretty {
       my ($meth, $a, $b) = @{+shift};
       $a = 'u' unless defined $a;
       $b = 'u' unless defined $b;
       $a = $a->pretty if ref $a;
       $b = $b->pretty if ref $b;
       "[$meth $a $b]";
     }

   Now one can finish the script by

     print "side = ", $side->pretty, "\n";

   The method pretty is doing object-to-string conversion, so it is
natural to overload the operator "" using this method.  However, inside
such a method it is not necessary to pretty-print the components $a and $b
of an object.  In the above subroutine `"[$meth $a $b]"' is a catenation
of some strings and components $a and $b.  If these components use
overloading, the catenation operator will look for an overloaded operator
., if not present, it will look for an overloaded operator "".  Thus it is
enough to use

     use overload nomethod => \&wrap, '""' => \&str;
     sub str {
       my ($meth, $a, $b) = @{+shift};
       $a = 'u' unless defined $a;
       $b = 'u' unless defined $b;
       "[$meth $a $b]";
     }

   Now one can change the last line of the script to

     print "side = $side\n";

   which outputs

     side = [/ [- [sqrt [+ 1 [** [n 1 u] 2]] u] 1] [n 1 u]]

   and one can inspect the value in debugger using all the possible
methods.

   Something is is still amiss: consider the loop variable $cnt of the
script.  It was a number, not an object.  We cannot make this value of
type `symbolic', since then the loop will not terminate.

   Indeed, to terminate the cycle, the $cnt should become false.  However,
the operator `bool' for checking falsity is overloaded (this time via
overloaded ""), and returns a long string, thus any object of type
`symbolic' is true.  To overcome this, we need a way to compare an object
to 0.  In fact, it is easier to write a numeric conversion routine.

   Here is the text of `symbolic.pm' with such a routine added (and
slightly modified str()):

     package symbolic;		# Primitive symbolic calculator
     use overload
       nomethod => \&wrap, '""' => \&str, '0+' => \&num;

     sub new { shift; bless ['n', @_] }
     sub wrap {
       my ($obj, $other, $inv, $meth) = @_;
       ($obj, $other) = ($other, $obj) if $inv;
       bless [$meth, $obj, $other];
     }
     sub str {
       my ($meth, $a, $b) = @{+shift};
       $a = 'u' unless defined $a;
       if (defined $b) {
         "[$meth $a $b]";
       } else {
         "[$meth $a]";
       }
     }
     my %subr = ( n => sub {$_[0]},
     	       sqrt => sub {sqrt $_[0]},
     	       '-' => sub {shift() - shift()},
     	       '+' => sub {shift() + shift()},
     	       '/' => sub {shift() / shift()},
     	       '*' => sub {shift() * shift()},
     	       '**' => sub {shift() ** shift()},
     	     );
     sub num {
       my ($meth, $a, $b) = @{+shift};
       my $subr = $subr{$meth}
         or die "Do not know how to ($meth) in symbolic";
       $a = $a->num if ref $a eq __PACKAGE__;
       $b = $b->num if ref $b eq __PACKAGE__;
       $subr->($a,$b);
     }

   All the work of numeric conversion is done in %subr and num().  Of
course, %subr is not complete, it contains only operators used in the
example below.  Here is the extra-credit question: why do we need an
explicit recursion in num()?  (Answer is at the end of this section.)

   Use this module like this:

     require symbolic;
     my $iter = new symbolic 2;	# 16-gon
     my $side = new symbolic 1;
     my $cnt = $iter;

     while ($cnt) {
       $cnt = $cnt - 1;		# Mutator `--' not implemented
       $side = (sqrt(1 + $side**2) - 1)/$side;
     }
     printf "%s=%f\n", $side, $side;
     printf "pi=%f\n", $side*(2**($iter+2));

   It prints (without so many line breaks)

     [/ [- [sqrt [+ 1 [** [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1]
     			  [n 1]] 2]]] 1]
        [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]]]=0.198912
     pi=3.182598

   The above module is very primitive.  It does not implement mutator
methods (`++', `-=' and so on), does not do deep copying (not required
without mutators!), and implements only those arithmetic operations which
are used in the example.

   To implement most arithmetic operations is easy, one should just use
the tables of operations, and change the code which fills %subr to

     my %subr = ( 'n' => sub {$_[0]} );
     foreach my $op (split " ", $overload::ops{with_assign}) {
       $subr{$op} = $subr{"$op="} = eval "sub {shift() $op shift()}";
     }
     my @bins = qw(binary 3way_comparison num_comparison str_comparison);
     foreach my $op (split " ", "@overload::ops{ @bins }") {
       $subr{$op} = eval "sub {shift() $op shift()}";
     }
     foreach my $op (split " ", "@overload::ops{qw(unary func)}") {
       print "defining `$op'\n";
       $subr{$op} = eval "sub {$op shift()}";
     }

   Due to `Calling Conventions for Mutators' in this node, we do not need
anything special to make `+=' and friends work, except filling `+=' entry
of %subr, and defining a copy constructor (needed since Perl has no way to
know that the implementation of `'+='' does not mutate the argument,
compare `Copy Constructor' in this node).

   To implement a copy constructor, add `'=' =' \&cpy> to `use overload'
line, and code (this code assumes that mutators change things one level
deep only, so recursive copying is not needed):

     sub cpy {
       my $self = shift;
       bless [@$self], ref $self;
     }

   To make `++' and - work, we need to implement actual mutators, either
directly, or in `nomethod'.  We continue to do things inside `nomethod',
thus add

     if ($meth eq '++' or $meth eq '--') {
       @$obj = ($meth, (bless [@$obj]), 1); # Avoid circular reference
       return $obj;
     }

   after the first line of wrap().  This is not a most effective
implementation, one may consider

     sub inc { $_[0] = bless ['++', shift, 1]; }

   instead.

   As a final remark, note that one can fill %subr by

     my %subr = ( 'n' => sub {$_[0]} );
     foreach my $op (split " ", $overload::ops{with_assign}) {
       $subr{$op} = $subr{"$op="} = eval "sub {shift() $op shift()}";
     }
     my @bins = qw(binary 3way_comparison num_comparison str_comparison);
     foreach my $op (split " ", "@overload::ops{ @bins }") {
       $subr{$op} = eval "sub {shift() $op shift()}";
     }
     foreach my $op (split " ", "@overload::ops{qw(unary func)}") {
       $subr{$op} = eval "sub {$op shift()}";
     }
     $subr{'++'} = $subr{'+'};
     $subr{'--'} = $subr{'-'};

   This finishes implementation of a primitive symbolic calculator in 50
lines of Perl code.  Since the numeric values of subexpressions are not
cached, the calculator is very slow.

   Here is the answer for the exercise: In the case of str(), we need no
explicit recursion since the overloaded .-operator will fall back to an
existing overloaded operator "".  Overloaded arithmetic operators *do not*
fall back to numeric conversion if `fallback' is not explicitly requested.
Thus without an explicit recursion num() would convert `['+', $a, $b]' to
`$a + $b', which would just rebuild the argument of num().

   If you wonder why defaults for conversion are different for str() and
num(), note how easy it was to write the symbolic calculator.  This
simplicity is due to an appropriate choice of defaults.  One extra note:
due to the explicit recursion num() is more fragile than sym(): we need to
explicitly check for the type of $a and $b.  If components $a and $b
happen to be of some related type, this may lead to problems.

Really symbolic calculator
--------------------------

   One may wonder why we call the above calculator symbolic.  The reason
is that the actual calculation of the value of expression is postponed
until the value is used.

   To see it in action, add a method

     sub STORE {
       my $obj = shift;
       $#$obj = 1;
       @$obj->[0,1] = ('=', shift);
     }

   to the package `symbolic'.  After this change one can do

     my $a = new symbolic 3;
     my $b = new symbolic 4;
     my $c = sqrt($a**2 + $b**2);

   and the numeric value of $c becomes 5.  However, after calling

     $a->STORE(12);  $b->STORE(5);

   the numeric value of $c becomes 13.  There is no doubt now that the
module symbolic provides a *symbolic* calculator indeed.

   To hide the rough edges under the hood, provide a tie()d interface to
the package `symbolic' (compare with `Metaphor clash' in this node).  Add
methods

     sub TIESCALAR { my $pack = shift; $pack->new(@_) }
     sub FETCH { shift }
     sub nop {  }		# Around a bug

   (the bug is described in `"BUGS"' in this node).  One can use this new
interface as

     tie $a, 'symbolic', 3;
     tie $b, 'symbolic', 4;
     $a->nop;  $b->nop;	# Around a bug

     my $c = sqrt($a**2 + $b**2);

   Now numeric value of $c is 5.  After `$a = 12; $b = 5' the numeric value
of $c becomes 13.  To insulate the user of the module add a method

     sub vars { my $p = shift; tie($_, $p), $_->nop foreach @_; }

   Now

     my ($a, $b);
     symbolic->vars($a, $b);
     my $c = sqrt($a**2 + $b**2);

     $a = 3; $b = 4;
     printf "c5  %s=%f\n", $c, $c;

     $a = 12; $b = 5;
     printf "c13  %s=%f\n", $c, $c;

   shows that the numeric value of $c follows changes to the values of $a
and $b.

AUTHOR
======

   Ilya Zakharevich <`ilya@math.mps.ohio-state.edu'>.

DIAGNOSTICS
===========

   When Perl is run with the *-Do* switch or its equivalent, overloading
induces diagnostic messages.

   Using the m command of Perl debugger (see Perldebug (perl.info))
one can deduce which operations are overloaded (and
which ancestor triggers this overloading). Say, if eq is overloaded, then
the method `(eq' is shown by debugger. The method `()' corresponds to the
`fallback' key (in fact a presence of this method shows that this package
has overloading enabled, and it is what is used by the `Overloaded'
function of module overload).

BUGS
====

   Because it is used for overloading, the per-package hash %OVERLOAD now
has a special meaning in Perl. The symbol table is filled with names
looking like line-noise.

   For the purpose of inheritance every overloaded package behaves as if
`fallback' is present (possibly undefined). This may create interesting
effects if some package is not overloaded, but inherits from two
overloaded packages.

   Relation between overloading and tie()ing is broken.  Overloading is
triggered or not basing on the previous class of tie()d value.

   This happens because the presence of overloading is checked too early,
before any tie()d access is attempted.  If the FETCH()ed class of the
tie()d value does not change, a simple workaround is to access the value
immediately after tie()ing, so that after this call the previous class
coincides with the current one.

   *Needed:* a way to fix this without a speed penalty.

   Barewords are not covered by overloaded string constants.

   This document is confusing.  There are grammos and misleading language
used in places.  It would seem a total rewrite is needed.

a class to encapsulate a filehandle as a stream;
************************************************

NAME
====

   Fstream - a class to encapsulate a filehandle as a stream;

SYNOPSIS
========

     use Fstream;

DESCRIPTION
===========

   Fstream wraps a filehandle and provides methods that make it easier to
write a lexer. Why doesn't Perl have ungetc?

Class Methods
-------------

new($filehandle, $name) Creates an Fstream object from $filehandle (a filehandle glob reference). $name is a string which is stored for debugging purposes and may be accessed with &name.
Object Methods
--------------

getc Returns the next character in the stream, or the empty string if the stream has been exhausted.
ungetc Pushes the last character read back onto the stream, where it will be returned on the next call to getc. You may only push one character back on the stream.
lineno Returns the line-number of the stream (based on the number of newlines seen).
name Returns the name that was given in the constructor.

Interfaces to some Win32 API Functions
**************************************

NAME
====

   Win32 - Interfaces to some Win32 API Functions

DESCRIPTION
===========

   Perl on Win32 contains several functions to access Win32 APIs. Some are
included in Perl itself (on Win32) and some are only available after
explicitly requesting the Win32 module with:

     use Win32;

   The builtin functions are marked as [CORE] and the other ones as [EXT]
in the following alphabetical listing. The Win32 module is not part of the
Perl source distribution; it is distributed in the libwin32 bundle of
Win32::* modules on CPAN. The module is already preinstalled in binary
distributions like ActivePerl.

Alphabetical Listing of Win32 Functions
---------------------------------------

Win32::AbortSystemShutdown(MACHINE)
     [EXT] Aborts a system shutdown (started by the InitiateSystemShutdown
     function) on the specified MACHINE.

Win32::BuildNumber()
     [CORE] Returns the ActivePerl build number. This function is only
     available in the ActivePerl binary distribution.

Win32::CopyFile(FROM, TO, OVERWRITE)
     [CORE] The Win32::CopyFile() function copies an existing file to a new
     file. All file information like creation time and file attributes will
     be copied to the new file. However it will not copy the security
     information. If the destination file already exists it will only be
     overwritten when the OVERWRITE parameter is true. But even this will
     not overwrite a read-only file; you have to unlink() it first
     yourself.

Win32::DomainName()
     [CORE] Returns the name of the Microsoft Network domain that the
     owner of the current perl process is logged into.

Win32::ExpandEnvironmentStrings(STRING)
     [EXT] Takes STRING and replaces all referenced environment variable
     names with their defined values. References to environment variables
     take the form `%VariableName%'. Case is ignored when looking up the
     VariableName in the environment. If the variable is not found then the
     original `%VariableName%' text is retained.  Has the same effect as
     the following:

          $string =~ s/%([^%]*)%/$ENV{$1} || "%$1%"/eg

Win32::FormatMessage(ERRORCODE)
     [CORE] Converts the supplied Win32 error number (e.g. returned by
     Win32::GetLastError()) to a descriptive string.  Analogous to the
     perror() standard-C library function.  Note that $^E used in a string
     context has much the same effect.

          C:\> perl -e "$^E = 26; print $^E;"
          The specified disk or diskette cannot be accessed

Win32::FsType()
     [CORE] Returns the name of the filesystem of the currently active
     drive (like 'FAT' or 'NTFS'). In list context it returns three values:
     (FSTYPE, FLAGS, MAXCOMPLEN). FSTYPE is the filesystem type as before.
     FLAGS is a combination of values of the following table:

          0x00000001  supports case-sensitive filenames
          0x00000002  preserves the case of filenames
          0x00000004  supports Unicode in filenames
          0x00000008  preserves and enforces ACLs
          0x00000010  supports file-based compression
          0x00000020  supports disk quotas
          0x00000040  supports sparse files
          0x00000080  supports reparse points
          0x00000100  supports remote storage
          0x00008000  is a compressed volume (e.g. DoubleSpace)
          0x00010000  supports object identifiers
          0x00020000  supports the Encrypted File System (EFS)

     MAXCOMPLEN is the maximum length of a filename component (the part
     between two backslashes) on this file system.

Win32::FreeLibrary(HANDLE)
     [EXT] Unloads a previously loaded dynamic-link library. The HANDLE is
     no longer valid after this call. See
     `LoadLibrary|Win32::LoadLibrary(LIBNAME)' in this node for
     information on dynamically loading a library.

Win32::GetArchName()
     [EXT] Use of this function is deprecated. It is equivalent with
     $ENV{PROCESSOR_ARCHITECTURE}. This might not work on Win9X.

Win32::GetChipName()
     [EXT] Returns the processor type: 386, 486 or 586 for Intel
     processors, 21064 for the Alpha chip.

Win32::GetCwd()
     [CORE] Returns the current active drive and directory. This function
     does not return a UNC path, since the functionality required for such
     a feature is not available under Windows 95.

Win32::GetFullPathName(FILENAME)
     [CORE] GetFullPathName combines the FILENAME with the current drive
     and directory name and returns a fully qualified (aka, absolute) path
     name. In list context it returns two elements: (PATH, FILE) where
     PATH is the complete pathname component (including trailing backslash)
     and FILE is just the filename part.  Note that no attempt is made to
     convert 8.3 components in the supplied FILENAME to longnames or
     vice-versa.  Compare with Win32::GetShortPathName and
     Win32::GetLongPathName.

     This function has been added for Perl 5.6.

Win32::GetLastError()
     [CORE] Returns the last error value generated by a call to a Win32 API
     function.  Note that $^E used in a numeric context amounts to the
     same value.

Win32::GetLongPathName(PATHNAME)
     [CORE] Returns a representaion of PATHNAME composed of longname
     components (if any).  The result may not necessarily be longer than
     PATHNAME.  No attempt is made to convert PATHNAME to the absolute
     path.  Compare with Win32::GetShortPathName and
     Win32::GetFullPathName.

     This function has been added for Perl 5.6.

Win32::GetNextAvailDrive()
     [CORE] Returns a string in the form of "<d>:" where <d> is the first
     available drive letter.

Win32::GetOSVersion()
     [CORE] Returns the array (STRING, MAJOR, MINOR, BUILD, ID), where the
     elements are, respectively: An arbitrary descriptive string, the
     major version number of the operating system, the minor version
     number, the build number, and a digit indicating the actual operating
     system. For ID, the values are 0 for Win32s, 1 for Windows 9X and 2
     for Windows NT. In scalar context it returns just the ID.

Win32::GetShortPathName(PATHNAME)
     [CORE] Returns a representation of PATHNAME composed only of short
     (8.3) path components.  The result may not necessarily be shorter
     than PATHNAME.  Compare with Win32::GetFullPathName and
     Win32::GetLongPathName.

Win32::GetProcAddress(INSTANCE, PROCNAME)
     [EXT] Returns the address of a function inside a loaded library. The
     information about what you can do with this address has been lost in
     the mist of time. Use the Win32::API module instead of this deprecated
     function.

Win32::GetTickCount()
     [CORE] Returns the number of milliseconds elapsed since the last
     system boot. Resolution is limited to system timer ticks (about 10ms
     on WinNT and 55ms on Win9X).

Win32::InitiateSystemShutdown(MACHINE, MESSAGE, TIMEOUT, FORCECLOSE, REBOOT)
     [EXT] Shutsdown the specified MACHINE, notifying users with the
     supplied MESSAGE, within the specified TIMEOUT interval. Forces
     closing of all documents without prompting the user if FORCECLOSE is
     true, and reboots the machine if REBOOT is true. This function works
     only on WinNT.

Win32::IsWinNT()
     [CORE] Returns non zero if the Win32 subsystem is Windows NT.

Win32::IsWin95()
     [CORE] Returns non zero if the Win32 subsystem is Windows 95.

Win32::LoadLibrary(LIBNAME)
     [EXT] Loads a dynamic link library into memory and returns its module
     handle. This handle can be used with Win32::GetProcAddress and
     Win32::FreeLibrary. This function is deprecated. Use the Win32::API
     module instead.

Win32::LoginName()
     [CORE] Returns the username of the owner of the current perl process.

Win32::LookupAccountName(SYSTEM, ACCOUNT, DOMAIN, SID, SIDTYPE)
     [EXT] Looks up ACCOUNT on SYSTEM and returns the domain name the SID
     and the SID type.

Win32::LookupAccountSID(SYSTEM, SID, ACCOUNT, DOMAIN, SIDTYPE)
     [EXT] Looks up SID on SYSTEM and returns the account name, domain
     name, and the SID type.

Win32::MsgBox(MESSAGE [, FLAGS [, TITLE]])
     [EXT] Create a dialogbox containing MESSAGE. FLAGS specifies the
     required icon and buttons according to the following table:

          0 = OK
          1 = OK and Cancel
          2 = Abort, Retry, and Ignore
          3 = Yes, No and Cancel
          4 = Yes and No
          5 = Retry and Cancel

          MB_ICONSTOP          "X" in a red circle
          MB_ICONQUESTION      question mark in a bubble
          MB_ICONEXCLAMATION   exclamation mark in a yellow triangle
          MB_ICONINFORMATION   "i" in a bubble

     TITLE specifies an optional window title. The default is "Perl".

     The function returns the menu id of the selected push button:

          0  Error

          1  OK
          2  Cancel
          3  Abort
          4  Retry
          5  Ignore
          6  Yes
          7  No

Win32::NodeName()
     [CORE] Returns the Microsoft Network node-name of the current machine.

Win32::RegisterServer(LIBRARYNAME)
     [EXT] Loads the DLL LIBRARYNAME and calls the function
     DllRegisterServer.

Win32::SetCwd(NEWDIRECTORY)
     [CORE] Sets the current active drive and directory. This function
     does not work with UNC paths, since the functionality required to
     required for such a feature is not available under Windows 95.

Win32::SetLastError(ERROR)
     [CORE] Sets the value of the last error encountered to ERROR. This is
     that value that will be returned by the Win32::GetLastError()
     function. This functions has been added for Perl 5.6.

Win32::Sleep(TIME)
     [CORE] Pauses for TIME milliseconds. The timeslices are made available
     to other processes and threads.

Win32::Spawn(COMMAND, ARGS, PID)
     [CORE] Spawns a new process using the supplied COMMAND, passing in
     arguments in the string ARGS. The pid of the new process is stored in
     PID. This function is deprecated. Please use the Win32::Process module
     instead.

Win32::UnregisterServer(LIBRARYNAME)
     [EXT] Loads the DLL LIBRARYNAME and calls the function
     DllUnregisterServer.

Web-based database table editor.
********************************

NAME
====

   pqedit.cgi - Web-based database table editor.

SYNOPSIS
========

   'http://www.domain.edu/mod_perl/pqedit.cgi?server=sqlserver
&server_type=*oracle*
&database=mydb&table=tablename&username=user&password=pwd
&helppage=http://www.domain.edu/helpfile.html &labels=field1name;Field 1
Label,field2name;Field 2 Label
&subedit_tables=table1*%2C*table2&button_subedit=1
&web_body_bgcolor=html_bgcolor &web_textarea_columns=number_of_columns
&web_textarea_rows=number_of_columns
&begin_html_include=/subweb_directory/html_to_include.html
&middle_html_include=/subweb_directory/html_to_include.html
&end_html_include=/subweb_directory/html_to_include.html
&disable_lookup=nonlookup_table&no_schemacache=1
&label_match=label_match_string,label_match_string2,...
&*auto_field*=table,field,replacement;...
&*replace_field*=table,field,replacement;...
&*pq_*fieldname**=field_value&*pqsearch_*fieldname**=1
&*pk_value*=tab_delimited_list_of_primary_key_values &Overview=1
&single_window=ON &nondisplay=table,field;...  &readonly=table,field;...
&pqdebug=1'

     or

   <FORM METHOD="POST" ACTION="http://www.domain.edu/mod_perl/pqedit.cgi"
NAME="PQ Edit">     <INPUT TYPE="hidden" NAME="server" VALUE="sqlserver">
  <INPUT TYPE="hidden" NAME="server_type" VALUE="oracle">     <INPUT
TYPE="hidden" NAME="database" VALUE="mydb">     <INPUT TYPE="hidden"
NAME="table" VALUE="tablename">     <INPUT TYPE="hidden" NAME="username"
VALUE="user">     <INPUT TYPE="hidden" NAME="password" VALUE="pwd">
<INPUT TYPE="hidden" NAME="helppage"
VALUE='http://www.domain.edu/helpfile.html'>     <INPUT TYPE="hidden"
NAME="labels" VALUE='field1name;Field 1 Label,field2name;Field 2 Label'>
 <INPUT TYPE="hidden" NAME="subedit_tables" VALUE="table1*%2C*table2">
<INPUT TYPE="hidden" NAME="button_subedit" VALUE="1">     <INPUT
TYPE="hidden" NAME="web_body_bgcolor" VALUE="html_bgcolor">     <INPUT
TYPE="hidden" NAME="web_textarea_columns" VALUE="number_of_columns">
<INPUT TYPE="hidden" NAME="web_textarea_rows" VALUE="number_of_rows">
<INPUT TYPE="hidden" NAME="begin_html_include"
VALUE="/subweb_directory/html_to_include.html">     <INPUT TYPE="hidden"
NAME="middle_html_include" VALUE="/subweb_directory/html_to_include.html">
   <INPUT TYPE="hidden" NAME="end_html_include"
VALUE="/subweb_directory/html_to_include.html">     <INPUT TYPE="hidden"
NAME="disable_lookup" VALUE="nonlookup_table">     <INPUT TYPE="hidden"
NAME="label_match" VALUE="label_match_string,label_match_string2,...">
<INPUT TYPE="hidden" NAME="*replace_field*"
VALUE="table,field,replacement;...">     <INPUT TYPE="hidden"
NAME="no_schemacache" VALUE="1">     <INPUT TYPE="hidden"
NAME="*pq_*fieldname**" VALUE="field value">     <INPUT TYPE="hidden"
NAME="*pqsearch_*fieldname**" VALUE="1">     <INPUT TYPE="hidden"
NAME="*pk_value*" VALUE="tab_delimited_list_of_primary_key_values">
<INPUT TYPE="hidden" NAME="Overview" VALUE="1">     <INPUT TYPE="hidden"
NAME="single_window" VALUE="ON">     <INPUT TYPE="hidden"
NAME="nondisplay" VALUE="table,field;...">     <INPUT TYPE="hidden"
NAME="readonly" VALUE="table,field;...">     <INPUT TYPE="hidden"
NAME="pqdebug" VALUE="1"> </FORM>

   *All parameters are optional.*  pqedit.cgi may be run from a shell in
offline mode.  It will then prompt you for the parameters:

   (offline mode: enter name=value pairs on standard input).

ABSTRACT
========

   The pqedit.cgi perl script is a Perl CGI script designed to allow easy
editing of any Transact-SQL (Sybase or MS SQL server) or Oracle compliant
database table.  It is designed to provide a web, CGI form interface for
editing any arbitrary database table-sufficient information to provide a
reasonable form interface is acquired dynamically from the database server
itself.

   It runs on a web server as a Perl 5 CGI script that uses the CGI,
Apache::Sybase::DBlib, Sybase::DBlib, Win32::ODBC, RDBAL, RDBAL::Schema
modules.

INSTALLATION:
=============

   To install this package, just change to the directory in which this
file is found and type the following:

     perl Makefile.PL
     make
     make test
     make install

   And then copy pqedit.cgi to a place in your web directory tree that
allows CGI scripts to run (if your web server supports mod_perl, a
mod_perl location is preferred).  pqedit.cgi will be copied to your
'/usr/local/bin' directory also.

   The mssql_pqweb.sql or sybase_pqweb.sql DDL scripts may be used to
create the appropriate tables in the optional pqweb database.  See the
comments at the top of these files for their usage.

DESCRIPTION
===========

   PQ Edit uses the RDBAL::Schema module to query the database for
information about the tables and fields available.  Based on this
information, it tries construct a reasonable interface for editing any
table of interest.

   PQ Edit does not maintain a connection to the database-it reconnects to
the database server on each action.  PQ Edit passes the username and
password given to it to itself on each action so that it can reconnect to
the database server.

   PQEdit assumes that there are not any tabs in any of the fields being
displayed or edited (it will turn each tab into a space).

   PQEdit assumes that the names of the tables' fields do not have 15
underscores in a row as part of the name (Example:
'server.owner.table.my_______________field' is not allowed).

   If called with no CGI parameters, it will prompt the user for:

server
database
table
username
password
   or some or all of these may be passed as CGI GET or POST parameters.

PQEdit parameters
=================

server
------

   The name of the Transact-SQL database server (Sybase or MS SQL) to
connect to.

server_type=oracle
------------------

   This tells PQ Edit that it is an Oracle database which it is talking to.
This parameter is mandatory for the correct working of PQ Edit with an
Oracle database but should not be used for all Transact-SQL databases.

database
--------

   The name of the database on the database server that contains the
table(s) to edit.

table
-----

   The name of the database table to start editing.

username
--------

   The username to use to login to the database server.

password
--------

   The password to use to login to the database server.

helppage
--------

   The URL of an HTML page which contain bookmarks which correspond to the
names of the fields in the database.  If this parameter is given, then PQ
Edit will make the labels of the form's fields into clickable links
pointing to *htmlpage*#*fieldname*.  If a fieldname is part of a foreign
key tuple, then the bookmark which will be used will consist of the field
names seperated by ' and ' (Example: 'field1 and field2').

   The helppage value may also be retrieved from the optional pqweb
database.

labels
------

   This parameter may contain a list of comma seperated pairs of fields
and their overridden labels.  The field;label pair is seperated by a
semicolon.

   Example: labels=field1name;Field 1 Label,field2name;Field 2 Label

subedit_tables
--------------

   A comma seperated list of tables that should be also made available for
editing.  (NOTE: the HTML escaped form for comma is *%2C*. )

button_subedit
--------------

   When given a true value, 1, uses push buttons instead of radio buttons
for selecting (and switching to) another table for editing.

web_body_bgcolor
----------------

   An HTML background color, BGCOLOR, value for the displayed pages.

web_textarea_columns
--------------------

   The number of text columns to use for larger character fields.  Any
character field larger than this value uses a text area CGI field instead
of a text CGI field for editing.  The default is 61.

web_textarea_rows
-----------------

   The number of text rows to use for larger character fields.  The text
area field will only be as large as is necessary based on the size of the
character field-this value limits the maximum number of rows used.  The
default is 2.

begin_html_include
------------------

   A file which contains HTML to include near the beginning of the PQ Edit
form.  The specification of this file should be the absolute path relative
to the root of the web hierarchy.  Example: '/mydir/helpfile.html'.  This
file should not contain the <HTML>, <BODY>, </BODY>, or </HTML> tags.

middle_html_include
-------------------

   A file which contains HTML to include near the middle of the PQ Edit
form.  The specification of this file should be the absolute path relative
to the root of the web hierarchy.  Example: '/mydir/helpfile.html'.  This
file should not contain the <HTML>, <BODY>, </BODY>, or </HTML> tags.

end_html_include
----------------

   A file which contains HTML to include near the end of the PQ Edit form.
The specification of this file should be the absolute path relative to
the root of the web hierarchy.  Example: '/mydir/helpfile.html'.  This
file should not contain the <HTML>, <BODY>, </BODY>, or </HTML> tags.

disable_lookup
--------------

   A comma seperated list of tables that should *NOT* used as Lookup
Tables or to provide the values and labels for Pull Down Menus.  (NOTE:
the HTML escaped form for comma is *%2C*. )

label_match
-----------

   A comma seperated list of strings to use to match field names against
when lookup for the field to use as a label for lookup fields.  The
default strings (in the order used for matching is: 'description',
'comment', '_name', 'label', 'desc' (feedback welcomed on this default
list).

   So if the parent table used to create a lookup pulldown list has a
field such as 'mydescription' or 'foo_comment' PQ Edit will use the field
'mydescription'.

replace_field auto_field
------------------------

   A semicolan seperated list of table,field,SQL:replacement or
table,field,VALUE:replacement or table,field,replacement.

   *replace_field* always replaces a fields values whereas *auto_field*
only replaces values of fields which are left blank (NULL).
*replace_field* fields are shown as read-only fields on the PQ Edit form.

   Specifies values for fields for inserts or updates.  The replacement
portion is processed to replace variables in the list specified below as
well as all variables of type $pq_field.  If SQL: is specified, then the
replacement is used as a valid command to be executed on the database
server, with the resulting single value replacing that field's value for
the insert or update operation.  If SQL: not is specified, then the
replacement replaces that field's value for the insert or update operation.

   For example:

   pqedit.cgi?replace_field=*main_table*,*first_field*,SQL:*select
'$remote_address'*

   would execute: "select '*ip_address*'" on the database server and put
the first value returned into the *first_field* value for the insert or
update statement of table *main_table*.

   or

   pqedit.cgi?replace_field=main_table,first_field,VALUE:$remote_address
$remote_user $pq_another_field

   would put '*ip_address* username *another_field*' into the
*first_field* value for the insert or update statement of table
*main_table*.

   Replacement variables:

$pq_field
     $pq_field gives the current value (from the PQ Edit form) of some
     other table field from the same record.

$referer
     The URL of the page the browser was viewing prior to fetching your
     script. Not available for all browsers.

$remote_address
     The dotted IP address of the remote host.

$remote_ident
     The identity-checking information from the remote host. Only
     available if the remote host has the identd daemon turned on.

$remote_host
     Either the remote host name or IP address. if the former is
     unavailable.

$remote_user
     The name given by the remote user during password authorization.

$script_name
     The script name as a partial URL, for self-refering scripts.

$server_name
     The name of the WWW server the script is running under.

$server_admin
     The name of the administrator of the WWW server the script is running
     under.

$server_software
     The name and version of the server software.

$virtual_host
     When using the virtual host feature of some servers, the name of the
     virtual host the browser is accessing.

$server_port
     The communications port the server is using.

$user_agent
     The identity of the remote user's browser software, e.g.
     "Mozilla/1.1N (Macintosh; I; 68K)"

$user_name
     Attempts to obtain the remote user's name, using a variety of
     environment variables. This only works with older browsers such as
     Mosaic. Netscape does not reliably report the user name!

$datetime
     The current date and time as a standard string.

$unique_id
     The Apache web server generated unique ID.

pq_fieldname
------------

   Values for the fields are passed to PQ Edit in this format to provide
default values for the form's fields.  Example, assuming database field:
telephone_number is: pq_telephone_number='(314) 555-1111'.

pqsearch_fieldname
------------------

   Setting this to one as well as setting the corresponding
pq_*fieldname*, will allow setting the search criteria for the record(s)
to be displayed.  The 'Overview' option may be used with the
pq_*fieldname* and pqsearch_*fieldname* options.

Overview
--------

   Setting this to one (1) will display an Overview ('View Search Set')
window with the search parameters set by the pq_*fieldname* and
pqsearch_*fieldname* parameters.

single_window
-------------

   Value none or 'ON'.  Used to force disabling of multiple window frames.

readonly
--------

   A list of fields to display but not allow to be edited.

nondisplay
----------

   A list of fields to not display.

no_schemacache
--------------

   When given a true value, 1, causes PQ Edit to not use the cached copy
of the schema and to write out a new schema cache.  Note that this applies
for the whole PQ Edit session.

pqdebug
-------

   When given a true value, 1, causes PQ Edit to run in a debugging mode.

PQ Web Database Parameters
==========================

   An optional database may be used to store certain parameters used by
PQEdit.

   The parameters that may be stored in the optional pqweb database are:

helppage
          The URL of the helppage to use.

labels
          The overridden labels for table fields

web_body_bgcolor
          The web pages background color.

pqweb_server
------------

   The name of the database server which contains the pqweb database.

pqweb_database
--------------

   The name of the pqweb database.  This defaults to pqweb.

pqweb_username
--------------

   The username to use when connecting to the pqweb database.  This account
only needs 'select' permissions.

pqweb_password
--------------

   The password to use when connecting to the pqweb database.

pqweb_entry
-----------

   Which pqweb entry to use (the pqweb..pqweb.pq value).

PQ Edit Frames
==============

   When PQ Edit is in multiple window frame mode (single_window != 'ON'),
the names of the frames which it uses are in the form:

pqedittable for Editing windows
overviewtable for Overview windows
   If it is desired, a Frameset HTML window could be constructed prior to
invoking PQ Edit which would contain the PQ Edit frames as subframes.

AUTHOR INFORMATION
==================

   Brian H. Dunford-Shore   brian@ibc.wustl.edu

   Copyright 1998, Washington University School of Medicine, Institute for
Biomedical Computing.  All rights reserved.

   This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

   Address bug reports and comments to: www@ibc.wustl.edu

CREDITS
=======

   Thanks very much to:

   *David J. States* (states@ibc.wustl.edu)

   and

   *Fyodor Krasnov* (fyodor@bws.aha.ru)

     for suggestions and bug fixes.

BUGS
====

   You really mean 'extra' features ;).  None known.

TODO
====

   These are features that would be nice to have and might even happen
someday (especially if YOU write it).

More control of the 'Look and Feel' of the HTML page:
     (colors, fonts, etc.).

Other types of database servers:
     (PostgreSQL, mSQL, mySQL, etc.).  (Note: this depends on there being
     a version of RDBAL and RDBAL::Schema for the database in question).

SEE ALSO
========

   CGI - http://www.ibc.wustl.edu/perl5/other/CGI.html

   *Sybase::DBlib* - http://www.ibc.wustl.edu/perl5/other/sybperl.html

   *RDBAL* - http://www.ibc.wustl.edu/perl5/other/RDBAL.html

   *RDBAL::Schema* - http://www.ibc.wustl.edu/perl5/other/RDBAL/Schema.html

Add private data members to Perl classes
****************************************

NAME
====

     private - Add private data members to Perl classes

SYNOPSIS
========

     package GI::Joe;

     use private qw( _SexualPrefs _IsSpy );

     # see the protected man page for an example

DESCRIPTION
===========

*Private member.*
     Internal data or functionality.  An attribute or method only directly
     accessible to the methods of the same class and inaccessible from any
     other scope.  In Perl, notionally private attributes and members are
     conventionally given names beginning with an underscore.

     From *"Object Oriented Perl"* by Damian Conway

   private.pm adds a list of keys as private data members to the current
class.  See Public, for more info.

   Private data members are those pieces of data which are expected to be
only accessed by methods of the class which owns them.  They are not
inherited by subclasses.

   private.pm serves a subset of the functionality of fields.pm.

     use private qw(_Foo);

   is almost exactly the same as:

     use fields qw(_Foo);

   with the exception that you can (if you REALLY want to) do something
like this:

     use private qw(Foo);

   Whereas one cannot do this with fields.pm. (Note: This is considered
unwise and private.pm will scream about it if you have Perl's warnings on.)

   Additionally, private.pm is a bit clearer in its intent and is not
necessarily implying use of pseudo-hashes.

EXAMPLES
========

   See `SYNOPSIS', see Protected, for an example of use.

MUSINGS
=======

   I fully expect private.pm to eventually mutate into a real pragma
someday when a better formalized OO data system for Perl supplants the
current fledgling pseudo-hashes.

AUTHOR
======

   Michae G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Public, Protected, Fields,
see Base, Class/Fields,

allows the declaration of protected subs
****************************************

NAME
====

     protect - allows the declaration of protected subs

SYNOPSIS
========

     package FooPackage;
     use protect;

     members qw ( Bar Baz );

     sub foo {
     	is private;
     	print "Only FooPackage can use me\n";
     }

     sub foz {
     	is member;
     	print "Only packages FooPackage, Bar, and Baz can use me.\n";
     }

     sub fail {
     	is public;
     	print "Anybody can use me!\n";
     }

DESCRIPTION
===========

     This module allows you to C<protect> your subs from outside callers, in a
     way similar to C++ or Java.  You can declare member subs, private subs, or
     public subs.
     The truth is, unfortunatly, that the subs aren't actually being declared,
     public, member, or private. What actually happens is a juicy bit of runtime
     checking, with perl's C<caller()> function to see where the subroutine call is
     coming from.

FUNCTION is
===========

     C<is> is allows you to declare set the subroutine as one of three modes.

MODES
=====

     The following are all modes that can be set by using the is function.

MODE private
          By setting your subroutine as C<private>, no-one can call it from outside
          the package that it was declared in.  Doing so will cause the program to
          die.

MODE member
          By setting the C<member> mode, only the current package and those
          packages that are declared as C<members> of the current package are
          allowed to call the subroutine.

MODE public
          By declaring C<public> you are actually doing nothing at all, but it looks
          nice to declare a function public, when every other sub is declared
          something or other.

FUNCTION members
================

     C<members> allows you to declare members of the current package family,
     and therefore use subroutines declared as member. members'ing is one way
     only. ie 'Just because you lent me your basketball, doesn't mean I'll lend
     you mine'.

FUNCTION nowarn
===============

     C<nowarn> allows you to have protect simply die without explaining why it
     did so.  This is in order to help restrict attacks where it is possible for
     people to see the runtime errors generated by the script.

BUGS
====

     C<private> and C<member> methods/functions can still be redefined without
     the private/member attribute.

     Both private and member methods/functions can be called by simply entering
     the package that they were declared in.

FIXES
=====

     C<protect> now exports a lot less into the namespace, thanks to the
     wonders of C<is>.

     C<members> and C<member> functions now work like they should.

AUTHOR
======

     James Duncan <jduncan@hawk.igs.net>

SEE ALSO
========

     perl(1), perlfunc(1)

"private" data fields which are inherited by child classes
**********************************************************

NAME
====

   protected - "private" data fields which are inherited by child classes

SYNOPSIS
========

     package Foo;
     use public      qw(foo bar );
     use private     qw(_private);
     use protected   qw(_pants spoon);

     sub squonk {
         my($self) = shift;
         $self->{_pants} = 'Infinite Trousers';
         $self->{spoon}  = 'What stirs me, stirs everything';
         ...
     }

     package Bar;
     # Inherits foo, bar, _pants and spoon
     use base qw(Foo);
     ...

DESCRIPTION
===========

*Protected member.*
     Restricted data or functionality.  An attribute or method only
     directly accessible to methods of the same class or of a subclass, but
     inaccessible from any other scope.

     From *"Object Oriented Perl"* by Damian Conway

   The `protected' module implements something like Protected data members
you might find in a language with a more traditional OO implementation
such as C++.

   Protected data members are similar to private ones with the notable
exception in that they are inherited by subclasses.  This is useful where
you have private information which would be useful for subclasses to know
as well.

   For example: A class which stores an object in a database might have a
protected member "_Changed" to keep track of changes to the object so it
does not have to waste time re-writing the entire thing to disk.
Subclasses of this obviously need a _Changed field as well, but it would
be breaking encapsilation if the author had to remember to "use fields
qw(_Changed)" (Assuming, of course, they're using fields and not just a
plain hash.  In which case forget this whole module.)

The Camel Behind The Curtain
----------------------------

   In reality, there is little difference between a "protected" variable
and a "public" on in Perl.  The only real difference is that the protected
module doesn't care what the field is called (ie. if it starts with an
underscore or not) whereas fields uses the name to determine if the
variable is public or private (ie. inherited or not).

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Public, Private, Fields,
Class/Fields, Base,

ptkFAQ
******

NAME
====

   ptkFAQ

AUTHOR
======

   Peter Prymmer pvhp@lns62.lns.cornell.edu

Add public data members to Perl classes
***************************************

NAME
====

     public - Add public data members to Perl classes

SYNOPSIS
========

     package GI::Joe;

     use public qw( Name Rank Serial_Number );

     # see the protected man page for an example of use

DESCRIPTION
===========

*Public member.*
     Externally visible data or functionality.  An attribute or method that
     is directly accessable from scopes outside the class.  In Perl, most
     members are, by their standard semantics, public.  By convention,
     attributes of Perl classes are regarded as private, as are methods
     whose names begin with an underscore.

     From *"Object Oriented Perl"* by Damian Conway

   public.pm adds a list of keys as public data members to the current
class.  This is useful when using pseudo-hashes as objects, or for simply
imposing a bit more structure on your Perl objects than is normally
expected.  It allows you to use the methods provided in Class::Fields.

   Public data members are those pieces of data which are expected to be
regularly accessed by methods, functions and programs outside the class
which owns them.  They are also inherited by any subclasses.

   public.pm serves a subset of the functionality of fields.pm.

     use public qw(Foo);

   is almost exactly the same as:

     use fields qw(Foo);

   with the exception that you can (if you REALLY want to) do something
like this:

     use public qw(_Foo);

   Whereas one cannot do this with fields.pm. (Note: This is considered
unwise and public.pm will scream about it if you have Perl's warnings on.)

   Additionally, public.pm is a bit clearer in its intent and is not
necessarily implying use of pseudo-hashes.

EXAMPLE
=======

   See `SYNOPSIS', see Protected, for an example of use.

MUSINGS
=======

   I fully expect public.pm to eventually mutate into a real pragma
someday when a better formalized OO data system for Perl supplants the
current fledgling pseudo-hashes.

AUTHOR
======

   Michae G Schwern <schwern@pobox.com>

SEE ALSO
========

   See Private, Protected, Fields,
see Base, Class/Fields,

Perl pragma to alter regular expression behaviour
*************************************************

NAME
====

   re - Perl pragma to alter regular expression behaviour

SYNOPSIS
========

     use re 'taint';
     ($x) = ($^X =~ /^(.*)$/s);     # $x is tainted here

     $pat = '(?{ $foo = 1 })';
     use re 'eval';
     /foo${pat}bar/;		   # won't fail (when not under -T switch)

     {
     	no re 'taint';		   # the default
     	($x) = ($^X =~ /^(.*)$/s); # $x is not tainted here

     no re 'eval';		   # the default
     /foo${pat}bar/;		   # disallowed (with or without -T switch)
         }

     use re 'debug';		   # NOT lexically scoped (as others are)
     /^(.*)$/s;			   # output debugging info during
     				   #     compile and run time

     use re 'debugcolor';	   # same as 'debug', but with colored output
     ...

   (We use $^X in these examples because it's tainted by default.)

DESCRIPTION
===========

   When `use re 'taint'' is in effect, and a tainted string is the target
of a regex, the regex memories (or values returned by the m// operator in
list context) are tainted.  This feature is useful when regex operations
on tainted data aren't meant to extract safe substrings, but to perform
other transformations.

   When `use re 'eval'' is in effect, a regex is allowed to contain `(?{
... })' zero-width assertions even if regular expression contains variable
interpolation.  That is normally disallowed, since it is a potential
security risk.  Note that this pragma is ignored when the regular
expression is obtained from tainted data, i.e.  evaluation is always
disallowed with tainted regular expresssions.  See `(?{ code })', see
Perlre (perl.info).

   For the purpose of this pragma, interpolation of precompiled regular
expressions (i.e., the result of `qr//') is not considered variable
interpolation.  Thus:

     /foo${pat}bar/

   *is* allowed if $pat is a precompiled regular expression, even if $pat
contains `(?{ ... })' assertions.

   When `use re 'debug'' is in effect, perl emits debugging messages when
compiling and using regular expressions.  The output is the same as that
obtained by running a `-DDEBUGGING'-enabled perl interpreter with the
*-Dr* switch. It may be quite voluminous depending on the complexity of
the match.  Using `debugcolor' instead of debug enables a form of output
that can be used to get a colorful display on terminals that understand
termcap color sequences.  Set `$ENV{PERL_RE_TC}' to a comma-separated list
of `termcap' properties to use for highlighting strings on/off, pre-point
part on/off.  See `"Debugging regular expressions"', see Perldebug (perl.info),
for additional info.

   The directive `use re 'debug'' is *not lexically scoped*, as the other
directives are.  It has both compile-time and run-time effects.

   See `Pragmatic Modules', see Perlmodlib (perl.info).

manipulate @INC at compile time with relative paths
***************************************************

NAME
====

   rlib - manipulate @INC at compile time with relative paths

SYNOPSIS
========

     use rlib LIST;

     no rlib LIST;

DESCRIPTION
===========

   rlib works in the same way as lib, except that all paths in LIST are
treated as relative paths.

   If rlib is used from the main package then the paths in LIST are
assumed to be relative to where the current script $0 is located. This is
done by using the FindBin package.

   If rlib is used from within any package other tha main then the paths
in LIST are assumed to be relative to the root of the library where the
file for that package was found.

   If LIST is empty then `"../lib","lib"' is assumed.

SEE ALSO
========

   lib - module which adds paths to @INC

   FindBin - module for locating script bin directory

AUTHOR
======

   Graham Barr <gbarr@pobox.com>

Perl pragma to auto-load and save global variables
**************************************************

NAME
====

   savevars - Perl pragma to auto-load and save global variables

SYNOPSIS
========

     use savevars qw($frob @mung %seen);

DESCRIPTION
===========

   This module will, like `use vars', predeclare the variables in the
list. In addition, the listed variables are retrieved from a per-script
configuration file and the values are stored on program end. The filename
of the configuration file is "$ENV{HOME}/.${progname}rc", where progname
is the name of the current script.

   The values are stored using the Data::Dumper module, which is already
installed with perl5.005 and better.

FUNCTIONS
=========

cfgfile
-------

   Return the pathname of the current configuration file.

writecfg
--------

   Write the variables to the configuration file. This method is called at
END.

dont_write_cfgfile
------------------

   If this function is called, then the configuration file will not be
written at END.

CAVEATS
=======

   cfgfile() uses the $< variable to determine the current home directory.
This might not be what you want if using setuid scripts.

BUGS
====

   Because getpwuid() is used, this module will not work very well on
Windows. Configuration files will be stored in the current drive root
directory or, if the `$HOME' environment variable exists, in the `$HOME'
directory.

AUTHOR
======

   Slaven Rezic <eserte@cs.tu-berlin.de>

   Copyright (c) 1998,1999,2000 Slaven Rezic. All rights reserved. This
package is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

SEE ALSO
========

   See Vars.

Perl pragma to enable simple signal handling
********************************************

NAME
====

   sigtrap - Perl pragma to enable simple signal handling

SYNOPSIS
========

     use sigtrap;
     use sigtrap qw(stack-trace old-interface-signals);	# equivalent
     use sigtrap qw(BUS SEGV PIPE ABRT);
     use sigtrap qw(die INT QUIT);
     use sigtrap qw(die normal-signals);
     use sigtrap qw(die untrapped normal-signals);
     use sigtrap qw(die untrapped normal-signals
     		    stack-trace any error-signals);
     use sigtrap 'handler' => \&my_handler, 'normal-signals';
     use sigtrap qw(handler my_handler normal-signals
     	    	    stack-trace error-signals);

DESCRIPTION
===========

   The sigtrap pragma is a simple interface to installing signal handlers.
You can have it install one of two handlers supplied by sigtrap itself
(one which provides a Perl stack trace and one which simply `die()'s), or
alternately you can supply your own handler for it to install.  It can be
told only to install a handler for signals which are either untrapped or
ignored.  It has a couple of lists of signals to trap, plus you can supply
your own list of signals.

   The arguments passed to the use statement which invokes sigtrap are
processed in order.  When a signal name or the name of one of sigtrap's
signal lists is encountered a handler is immediately installed, when an
option is encountered it affects subsequently installed handlers.

OPTIONS
=======

SIGNAL HANDLERS
---------------

   These options affect which handler will be used for subsequently
installed signals.

*stack-trace*
     The handler used for subsequently installed signals outputs a Perl
     stack trace to STDERR and then tries to dump core.  This is the
     default signal handler.

die
     The handler used for subsequently installed signals calls die
     (actually croak) with a message indicating which signal was caught.

handler *your-handler*
     *your-handler* will be used as the handler for subsequently installed
     signals.  *your-handler* can be any value which is valid as an
     assignment to an element of %SIG.

SIGNAL LISTS
------------

   sigtrap has a few built-in lists of signals to trap.  They are:

*normal-signals*
     These are the signals which a program might normally expect to
     encounter and which by default cause it to terminate.  They are HUP,
     INT, PIPE and TERM.

*error-signals*
     These signals usually indicate a serious problem with the Perl
     interpreter or with your script.  They are ABRT, BUS, EMT, FPE, ILL,
     QUIT, SEGV, SYS and TRAP.

*old-interface-signals*
     These are the signals which were trapped by default by the old
     sigtrap interface, they are ABRT, BUS, EMT, FPE, ILL, PIPE, QUIT,
     SEGV, SYS, TERM, and TRAP.  If no signals or signals lists are passed
     to sigtrap, this list is used.

   For each of these three lists, the collection of signals set to be
trapped is checked before trapping; if your architecture does not
implement a particular signal, it will not be trapped but rather silently
ignored.

OTHER
-----

untrapped
     This token tells sigtrap to install handlers only for subsequently
     listed signals which aren't already trapped or ignored.

any
     This token tells sigtrap to install handlers for all subsequently
     listed signals.  This is the default behavior.

signal
     Any argument which looks like a signal name (that is,
     `/^[A-Z][A-Z0-9]*$/') indicates that sigtrap should install a handler
     for that name.

number
     Require that at least version number of sigtrap is being used.

EXAMPLES
========

   Provide a stack trace for the old-interface-signals:

     use sigtrap;

   Ditto:

     use sigtrap qw(stack-trace old-interface-signals);

   Provide a stack trace on the 4 listed signals only:

     use sigtrap qw(BUS SEGV PIPE ABRT);

   Die on INT or QUIT:

     use sigtrap qw(die INT QUIT);

   Die on HUP, INT, PIPE or TERM:

     use sigtrap qw(die normal-signals);

   Die on HUP, INT, PIPE or TERM, except don't change the behavior for
signals which are already trapped or ignored:

     use sigtrap qw(die untrapped normal-signals);

   Die on receipt one of an of the *normal-signals* which is currently
untrapped, provide a stack trace on receipt of any of the *error-signals*:

     use sigtrap qw(die untrapped normal-signals
     		    stack-trace any error-signals);

   Install my_handler() as the handler for the *normal-signals*:

     use sigtrap 'handler', \&my_handler, 'normal-signals';

   Install my_handler() as the handler for the normal-signals, provide a
Perl stack trace on receipt of one of the error-signals:

     use sigtrap qw(handler my_handler normal-signals
     	    	    stack-trace error-signals);

Perl pragma to restrict unsafe constructs
*****************************************

NAME
====

   strict - Perl pragma to restrict unsafe constructs

SYNOPSIS
========

     use strict;

     use strict "vars";
     use strict "refs";
     use strict "subs";

     use strict;
     no strict "vars";

DESCRIPTION
===========

   If no import list is supplied, all possible restrictions are assumed.
(This is the safest mode to operate in, but is sometimes too strict for
casual programming.)  Currently, there are three possible things to be
strict about:  "subs", "vars", and "refs".

`strict refs'
     This generates a runtime error if you use symbolic references (see
     Perlref (perl.info)).

          use strict 'refs';
          $ref = \$foo;
          print $$ref;	# ok
          $ref = "foo";
          print $$ref;	# runtime error; normally ok
          $file = "STDOUT";
          print $file "Hi!";	# error; note: no comma after $file

`strict vars'
     This generates a compile-time error if you access a variable that
     wasn't declared via "our" or `use vars', localized via my(), or
     wasn't fully qualified.  Because this is to avoid variable suicide
     problems and subtle dynamic scoping issues, a merely local() variable
     isn't good enough.  See `my', see Perlfunc (perl.info), and
     `local', see Perlfunc (perl.info).

          use strict 'vars';
          $X::foo = 1;	 # ok, fully qualified
          my $foo = 10;	 # ok, my() var
          local $foo = 9;	 # blows up

          package Cinna;
          our $bar;			# Declares $bar in current package
          $bar = 'HgS';		# ok, global declared via pragma

     The local() generated a compile-time error because you just touched a
     global name without fully qualifying it.

     Because of their special use by sort(), the variables $a and $b are
     exempted from this check.

`strict subs'
     This disables the poetry optimization, generating a compile-time
     error if you try to use a bareword identifier that's not a
     subroutine, unless it appears in curly braces or on the left hand
     side of the "=>" symbol.

          use strict 'subs';
          $SIG{PIPE} = Plumber;   	# blows up
          $SIG{PIPE} = "Plumber"; 	# just fine: bareword in curlies always ok
          $SIG{PIPE} = \&Plumber; 	# preferred form

   See `Pragmatic Modules', see Perlmodlib (perl.info).

Perl pragma to predeclare sub names
***********************************

NAME
====

   subs - Perl pragma to predeclare sub names

SYNOPSIS
========

     use subs qw(frob);
     frob 3..10;

DESCRIPTION
===========

   This will predeclare all the subroutine whose names are in the list,
allowing you to use them without parentheses even before they're declared.

   Unlike pragmas that affect the $^H hints variable, the `use vars' and
`use subs' declarations are not BLOCK-scoped.  They are thus effective for
the entire file in which they appear.  You may not rescind such
declarations with `no vars' or `no subs'.

   See `Pragmatic Modules', see Perlmodlib (perl.info), and
`strict subs', see Strict.

Removes y2k fixes
*****************

NAME
====

   uny2k - Removes y2k fixes

SYNOPSIS
========

     use uny2k;

     $year = (localtime)[5];
     printf "In the year %d, computers will everything for us!\n",
         $year += 1900;

DESCRIPTION
===========

   Y2K has come and gone and none of the predictions of Doom and Gloom
came to past.  As the crisis is over, you're probably wondering why you
went through all that trouble to make sure your programs are "Y2K
compliant".  uny2k.pm is a simple module to remove the now unnecessary y2k
fixes from your code.

   Y2K was a special case of date handling, and we all know that special
cases make programs more complicated and slower.  Also, most Y2K fixes
will fail around 2070 or 2090 (depending on how careful you were when
writing the fix) so in order to avert a future crisis it would be best to
remove the broken "fix" now.

   uny2k will remove the most common y2k fixes in Perl:

     $year = $year + 1900;

   and

     $two_digit_year = $year % 100;

   It will change them back to their proper post-y2k values, 19100 and 100
respectively.

AUTHOR
======

   Michael G Schwern <schwern@pobox.com> with apologies to Mark "I am not
ominous" Dominous for further abuse of his code.

SEE ALSO
========

   y2k.pm, D'oh::Year

Perl pragma to enable/disable UTF-8 in source code
**************************************************

NAME
====

   utf8 - Perl pragma to enable/disable UTF-8 in source code

SYNOPSIS
========

     use utf8;
     no utf8;

DESCRIPTION
===========

   WARNING: The implementation of Unicode support in Perl is incomplete.
See Perlunicode (perl.info), for the exact details.

   The `use utf8' pragma tells the Perl parser to allow UTF-8 in the
program text in the current lexical scope.  The `no utf8' pragma tells
Perl to switch back to treating the source text as literal bytes in the
current lexical scope.

   This pragma is primarily a compatibility device.  Perl versions earlier
than 5.6 allowed arbitrary bytes in source code, whereas in future we
would like to standardize on the UTF-8 encoding for source text.  Until
UTF-8 becomes the default format for source text, this pragma should be
used to recognize UTF-8 in the source.  When UTF-8 becomes the standard
source format, this pragma will effectively become a no-op.

   Enabling the utf8 pragma has the following effects:

   * Bytes in the source text that have their high-bit set will be treated
     as being part of a literal UTF-8 character.  This includes most
     literals such as identifiers, string constants, constant regular
     expression patterns and package names.

   * In the absence of inputs marked as UTF-8, regular expressions within
     the scope of this pragma will default to using character semantics
     instead of byte semantics.

          @bytes_or_chars = split //, $data;	# may split to bytes if data
          					# $data isn't UTF-8
          {
          	use utf8;			# force char semantics
          	@chars = split //, $data;	# splits characters
          }

SEE ALSO
========

   See Perlunicode (perl.info), Bytes,

Perl pragma to declare (scalar) variables without a leading `$'.
****************************************************************

NAME
====

   variable - Perl pragma to declare (scalar) variables without a leading
`$'.

SYNOPSIS
========

     use variable  spam  =>  17;
     use variable  eggs  =>  spam + 25;
     use variable "i";            # Makes "i" undefined.
     use variable  arr   =>  [qw /aap noot mies wim zus jet/];

     print eggs, "\n";            # Print 42.
           eggs += 27;
     print eggs, "\n";            # Print 69.

     for (i = 0; defined (arr -> [i]); i ++) {
         print arr -> [i], " ";   # Print aap noot mies wim zus jet.
     }

DESCRIPTION
===========

   This simple module allows you to create scalar variables that do not
need a leading `$'. This will make people coming from a C or a *Python*
background feel more at home.

NOTES
=====

   This module requires perl 5.6.0.

   The values given to the variables are evaluated in list context. You may
wish to override this by using scalar.

   These variables do not directly interpolate into doublequotish strings,
although you may do so indirectly. (See the perlref manpage for details
about how this works.)

     print "The value of eggs is ${\eggs}.\n";

   This only works for scalar variables, not arrays or hashes.

   Naming of variables follow the same rules as in `constant.pm'. Names
must begin with a letter or underscore. Names beginning with a double
underscore are reserved. Some poor choices for names will generate
warnings, if warnings are enabled at compile time.

   Variable symbols are package scoped (rather than block scoped, as `use
strict;' is. That is, you can refer to a variable from package Other as
`Other::var'.

   As with all use directives, defining a variable happens at compile time.
This, it's probably not correct to put a variable declaration inside of a
conditional statement (like `if ($foo) {use variable ...}').

   Omitting the value for a symbol gives it the value of undef. This isn't
so nice as it may sound, though, because in this case you must either
quote the symbol name, or use a big arrow `< =' >> with nothing to point
to.  It is probably best to declare these explicitly.

     use variable bacon  =>  ();
     use variable ham    =>  undef;

   The result from evaluating a list constant in a scalar context is not
documented, and is not guaranteed to be any particular value in the
future. In particular, you should not rely upon it being the number of
elements in the list, especially since it is not *necessarily* that value
in the current implementation.

   In the rare case in which you need to discover at run time whether a
particular variable has been declared via this module, you may use this
function to examine the hash `%variable::declared'. If the given variable
name does not include a package name, the current package is used.

     sub declared ($) {
         use variable;                   # don't omit this!
         my $name =  shift;
            $name =~ s/^::/main::/;
         my $pkg  =  caller;
         my $full = $name =~ /::/ ? $name : "${pkg}::$name";
         $variable::declared {$full};
     }

BUGS
====

   A variable with the name in the list `STDIN STDOUT STDERR ARGV ARGVOUT
ENV INC SIG' is not allowed anywhere but in package `main::', for
technical reasons.

   You can get into trouble if you use variables in a context which
automatically quotes barewords (as is true for any subroutine call).  For
example, you can't say `$hash {variable}' because variable will be
interpreted as a string. Use `$hash {variable ()}' or `$hash {+variable}'
to prevent the bareword quoting mechanism from kicking in. Similarly,
since the `< =' >> operator quotes a bareword immediately to its left, you
have to say `< variable () =' 'value' >> (or simple use a comma in place
of the big arrow) instead of `< variable =' 'value' >>

REVISION HISTORY
================

     $Log: variable.pm,v $
     Revision 1.1  2000/05/31 19:38:56  abigail
     Initial revision.

AUTHOR
======

   This package was written by Abigail, <abigail@delanet.com>.

COPYRIGHT AND LICENSE
=====================

   This package is copyright 2000 by Abigail.

   This program is free and open software. You can redistribute it or
modify it under the same terms as Perl itself.

THANKS
======

   The author wishes to thank EFNet's *#python* IRC channel for the
inspiration to write this module.

   A lot of the code and documentation of `constant.pm' was cut and pasted
in.

Perl pragma to predeclare global variable names (obsolete)
**********************************************************

NAME
====

   vars - Perl pragma to predeclare global variable names (obsolete)

SYNOPSIS
========

     use vars qw($frob @mung %seen);

DESCRIPTION
===========

   NOTE: The functionality provided by this pragma has been superseded by
our declarations, available in Perl v5.6.0 or later.  See `our', see
Perlfunc (perl.info).

   This will predeclare all the variables whose names are in the list,
allowing you to use them under "use strict", and disabling any typo
warnings.

   Unlike pragmas that affect the $^H hints variable, the `use vars' and
`use subs' declarations are not BLOCK-scoped.  They are thus effective for
the entire file in which they appear.  You may not rescind such
declarations with `no vars' or `no subs'.

   Packages such as the AutoLoader and SelfLoader that delay loading of
subroutines within packages can create problems with package lexicals
defined using my(). While the vars pragma cannot duplicate the effect of
package lexicals (total transparency outside of the package), it can act
as an acceptable substitute by pre-declaring global symbols, ensuring
their availability to the later-loaded routines.

   See `Pragmatic Modules', see Perlmodlib (perl.info).

Perl extension for svgalib-1.2.11
*********************************

NAME
====

   vga - Perl extension for svgalib-1.2.11

SYNOPSIS
========

     use vga;

     [script ...]

DESCRIPTION
===========

   Perl interface to svgalib 1.2.11, which is an enhancement of VGAlib
v.1.2.  The main difference in usage is all the vgalib functions that took
the form of vga_functionname are now accessed as vga::functionname (without
the 'vga_')

   Things notably missing from the library: vga_modeinfo structure
vga_getmodeinfo()				(vga::getmodeinfo) vga_getmodename()				(vga::getmodename)
the pointer to video ram, graph_mem	(\$vga::graphmem) and the function
vga_getgraphmem()	(vga::getgraphmem)

   Also, I realize the docs are kinda hacked. If there is any interest in
this package, I will revamp it and reupload it to the CPAN.

   Here is a description of the basic library functions (from the original
VGAlib v1.2 README):

     - Support for all standard VGA 16 and 256 color modes
     - Support for non-standard 256 color modes (including mode X)
     - Tseng ET4000 SVGA 256 color modes
     - Monochrome 640x480 mode
     - Text mode restoration
     - Handling of console I/O
     - Flipping between graphics mode and text mode
     - Restores text mode after CTRL-C interrupt
     - The ET4000 modes should now be more robust
     - Tools for creating your own video modes

   VGAlib requires the 0.96b kernel (or newer) and must be compiled with
GCC 2.2.2 (or newer). To compile and install VGAlib just type make. This
will also build the following programs:     vgatest: a simple
demonstration of the library and the various              video modes
dumpreg: dumps the current VGA registers to stdout, mainly used
 for debugging and creating new video modes     runx   : if you have
problems with text mode restoration after              running X386, then
try to use runx instead of startx Remember that all programs using VGAlib
must be run with setuid root (login as root and do a 'chmod +s
prog-name'), otherwise you will get a "can't get I/O permissions" error.

   VGAlib does it's best to restore the text mode, but it may fail with
some SVGA cards if you use a text mode with more than 80 columns. If you
are having problems please try to use an 80 column text mode.

   Below is a short description of the functions in the library.  Look at
vgatest.c for examples on how to use these functions:     - vga_setmode()
is used to select the graphics mode or to       restore the text mode.
- vga_hasmode() tests if a given video mode is supported       by the
graphics card (use this function before using       any of the ET4000 SVGA
modes)     - vga_clear() clears the graphics screen. This is also done
 by vga_setmode().      - vga_getxdim(), vga_getydim() and
vga_getcolors() return       the resolution and number of colors for the
current mode.      - vga_getpalette() and vga_getpalvec() returns the
contents       of one or more palette registers, respectively.      -
vga_setpalette() and vga_setpalvec() allows you to modify       one or
more palette registers, respectively.      - vga_setcolor() determines the
color for future calls of       the drawing functions.      -
vga_drawpixel() and vga_drawline() draws a pixel or a line       in the
current color, respectively.      - vga_drawscanline() draws one single
horisontal line of       pixels and has been optimized for the fastest
possible       output.      - vga_screenoff() and vga_screenon() turns the
screen refresh       off and on. On some VGA's the graphics operations
will be       faster, if the screen is turned off during graphics output.
   - vga_flip() switches between graphics and text mode without
destroying the screen contents. This makes it possible for       your
application to use both text and graphics output.      - vga_gecth() waits
for a character to be typed an returns       the ASCII value. If you press
ESC (the exact key can be       changed with vga_setflipchar()), the text
mode will be       temporarily restored until you press another key. This
allows       you to switch to another virtual console and later return to
    your graphics application.      - vga_setflipchar() changes the
character that vga_getch()       uses for flipping between graphics and
text mode.      - vga_dumpregs() dumps the current VGA register contents to
     stdout My main motivation for implementing the graphics/text
flipping was to make debugging easier. If your program reaches a
breakpoint while in graphics mode, you can switch to text mode with the
gdb command

     print vga_flip()

   and later restore the graphics screen contents with the same command.
It is usefull to define the following alias in gdb: in graphics mode, you
can switch to text mode with the gdb command

     print vga_flip()

   and later restore the graphics screen contents with the same command.
It is usefull to define the following alias in gdb:

     define flip <RETURN> print vga_flip() <RETURN> end <RETURN>

Exported constants
==================

     ACCELFLAG_DRAWHLINELIST
     ACCELFLAG_DRAWLINE
     ACCELFLAG_FILLBOX
     ACCELFLAG_PUTBITMAP
     ACCELFLAG_PUTIMAGE
     ACCELFLAG_SCREENCOPY
     ACCELFLAG_SCREENCOPYBITMAP
     ACCELFLAG_SETBGCOLOR
     ACCELFLAG_SETFGCOLOR
     ACCELFLAG_SETMODE
     ACCELFLAG_SETRASTEROP
     ACCELFLAG_SETTRANSPARENCY
     ACCELFLAG_SYNC
     ACCEL_DRAWHLINELIST
     ACCEL_DRAWLINE
     ACCEL_FILLBOX
     ACCEL_PUTBITMAP
     ACCEL_PUTIMAGE
     ACCEL_SCREENCOPY
     ACCEL_SCREENCOPYBITMAP
     ACCEL_SETBGCOLOR
     ACCEL_SETFGCOLOR
     ACCEL_SETMODE
     ACCEL_SETRASTEROP
     ACCEL_SETTRANSPARENCY
     ACCEL_SYNC
     ALI
     ARK
     ATI
     BLITS_IN_BACKGROUND
     BLITS_SYNC
     CAPABLE_LINEAR
     CIRRUS
     DISABLE_BITMAP_TRANSPARENCY
     DISABLE_TRANSPARENCY_COLOR
     EGA
     ENABLE_BITMAP_TRANSPARENCY
     ENABLE_TRANSPARENCY_COLOR
     ET3000
     ET4000
     EXT_INFO_AVAILABLE
     G1024x768x16
     G1024x768x16M
     G1024x768x16M32
     G1024x768x256
     G1024x768x32K
     G1024x768x64K
     G1152x864x16
     G1152x864x16M
     G1152x864x16M32
     G1152x864x256
     G1152x864x32K
     G1152x864x64K
     G1280x1024x16
     G1280x1024x16M
     G1280x1024x16M32
     G1280x1024x256
     G1280x1024x32K
     G1280x1024x64K
     G1600x1200x16
     G1600x1200x16M
     G1600x1200x16M32
     G1600x1200x256
     G1600x1200x32K
     G1600x1200x64K
     G320x200x16
     G320x200x16M
     G320x200x16M32
     G320x200x256
     G320x200x32K
     G320x200x64K
     G320x240x256
     G320x400x256
     G360x480x256
     G640x200x16
     G640x350x16
     G640x480x16
     G640x480x16M
     G640x480x16M32
     G640x480x2
     G640x480x256
     G640x480x32K
     G640x480x64K
     G720x348x2
     G800x600x16
     G800x600x16M
     G800x600x16M32
     G800x600x256
     G800x600x32K
     G800x600x64K
     GLASTMODE
     GVGA6400
     HAVE_BITBLIT
     HAVE_BLITWAIT
     HAVE_EXT_SET
     HAVE_FILLBLIT
     HAVE_HLINELISTBLIT
     HAVE_IMAGEBLIT
     HAVE_RWPAGE
     IS_DYNAMICMODE
     IS_INTERLACED
     IS_LINEAR
     IS_MODEX
     MACH32
     MACH64
     MON1024_43I
     MON1024_60
     MON1024_70
     MON1024_72
     MON640_60
     MON800_56
     MON800_60
     OAK
     RGB_MISORDERED
     ROP_AND
     ROP_COPY
     ROP_INVERT
     ROP_OR
     ROP_XOR
     S3
     TEXT
     TVGA8900
     UNDEFINED
     VGA
     VGA_AVAIL_ACCEL
     VGA_AVAIL_FLAGS
     VGA_AVAIL_SET
     VGA_CLUT8
     VGA_EXT_AVAILABLE
     VGA_EXT_CLEAR
     VGA_EXT_PAGE_OFFSET
     VGA_EXT_RESET
     VGA_EXT_SET
     VGA_H
     VGA_KEYEVENT
     VGA_MOUSEEVENT
     __GLASTMODE

AUTHOR
======

   Scott VanRavenswaay	(scottvr@netcomi.com) VGAlib:	Tommy Frandsen
(frandsen@diku.dk) svgalib: (you know who you are)

   =head1 SEE ALSO

   perl(1).  vgalib docs.

Perl extension for the vpopmail package
***************************************

NAME
====

   vpopmail - Perl extension for the vpopmail package

SYNOPSIS
========

     use vpopmail;

     adddomain('vpopmail.com');

     vadduser('username', 'vpopmail.com', 'p@ssw0rd', 'Test User', 0 );

     if ( vauth_user('username', 'vpopmail.com', 'p@ssw0rd', undef) ) {
     	print 'auth ok';
     }

     vsetuserquota('username', 'vpopmail.com', '5M');

     vdeluser('username', 'vpopmail.com') );

     vdeldomain('vpopmail.com');

DESCRIPTION
===========

   Perl extension for the vpopmail package  [
http://www.inter7.com/vpopmail ]

AUTHOR
======

   Sean P. Scanlon <sps@shore.net>

SEE ALSO
========

   perl(1), [ http://www.inter7.com/vpopmail ].

Perl pragma to control optional warnings
****************************************

NAME
====

   warnings - Perl pragma to control optional warnings

SYNOPSIS
========

     use warnings;
     no warnings;

     use warnings "all";
     no warnings "all";

     use warnings::register;
     if (warnings::enabled()) {
         warnings::warn("some warning");
     }

     if (warnings::enabled("void")) {
         warnings::warn("void", "some warning");
     }

DESCRIPTION
===========

   If no import list is supplied, all possible warnings are either enabled
or disabled.

   A number of functions are provided to assist module authors.

use warnings::register
     Creates a new warnings category which has the same name as the module
     where the call to the pragma is used.

warnings::enabled([$category])
     Returns TRUE if the warnings category `$category' is enabled in the
     calling module.  Otherwise returns FALSE.

     If the parameter, `$category', isn't supplied, the current package
     name will be used.

warnings::warn([$category,] $message)
     If the calling module has not set `$category' to "FATAL", print
     `$message' to STDERR.  If the calling module has set `$category' to
     "FATAL", print `$message' STDERR then die.

     If the parameter, `$category', isn't supplied, the current package
     name will be used.

   See `Pragmatic Modules', see Perlmod (perl.info), and
`Pragmatic Modules', see Perllexwarn (perl.info).

A set of useful routines for many webworking purposes
*****************************************************

NAME
====

   Web - A set of useful routines for many webworking purposes

SYSTEM REQUIREMENTS
===================

   This module was primarily made for UNIX/Linux-Systems.  Parts of it
cannot be used on other systems. E.g. the procedures for file locking
demand systems that can use symlinks.  If you use the modul on systems
where symlinks cannot be used, fatal errors may happen.

SYNOPSIS
========

   use web;

ABSTRACT
========

   This perl module serves users with several useful routines for many
purposes, like generating webpages, processing CGI scripts, working with
XML datafiles and net-connections.  It also uses own variants of routines,
that was invented first in the famous libraries CGI.pm and cgi-lib.pl.

INSTALLATION
============

   If you don't have sufficient privileges to install web.pm in the Perl
library directory, you can put web.pm into some convenient spot, such as
your home directory, or in cgi-bin itself and prefix all Perl scripts that
call it with something along the lines of the following preamble:

     use lib '/home/myname/perl/lib';
     use web;

DESCRIPTION
===========

NLock
-----

   This routine allows to set a filelock across NFS-boundaries.  The
common used perl-routine flock() fails at this point, so this routine is a
useable alternative for bigger file-systems.  It uses the modular
functions link() and unlink() to mark a file locked.  In addition to this,
it also gives the locked file a counter: A file that is locked for more
than $web::MAX_LOCKTIME seconds will be freed by the next process that
calls NLock() on this file.  A calling process gets either 0 or 1 as a
return value, where 1 is returned if the file-locking was successful.  0
is returned only if the process waits for more than $web::MAX_WAITLOCK
seconds or if symlink() fails.

   Example 1:

     $filename = "data.txt";
     NLock($filename);
     open(f1,"$filename");
     # do something
     close f1;
     NUnlock($filename);

     Example 2:

     #!/local/bin/perl5
     use web;

     $stat= &NLock("jump.pl");
     print "Lock: stat= $stat\n";
     $stat= &NLock("jump.pl");
     print "Lock this file again: stat= $stat\n";
     sleep 8;
     $stat= &NLock("jump.pl");
     print "Lock this file again: stat= $stat\n";
     $stat= &NUnlock("jump.pl");
     print "Unlock: stat= $stat\n";
     exit;

NUnlock
-------

   This routine removes the filelock that was set with NLock().  See
NLock().

NUnlockAll
----------

   In using this command, you can remove all file-locks, that was set with
NLock() and which wasn't removed before.  It takes the list of file-locks
out of the hash %web::lockliste.

GetYearDay
----------

   This routine can be used to calculate a day's position within the year
in days.  It returns -1 if the argument is no date.

   Example:

     $today = "$web::tag.$web::monat.$web::jahr" || "14.9.1999";
     $number_of_days = GetYearDay($today);
     print "Date: $today; It is the ${number_of_days}th day in this year.\n";

GetWeekDay
----------

   By using this routine you'll get the weekday of a given date, which is
a number between 0 (for sunday) and 6 (for saturday).  If the argument is
wrong, -1 will be returned.

   Example:

     $today = "$web::tag.$web::monat.$web::jahr" || "14.9.1999";
     $weekday = GetWeekDay($today);
     print "It is $web::wochentag[$weekday], $today.\n";

isLeapYear
----------

   This function returns true, if the argument is a leapyear.  If no
argument is given, the current year is used.

   Example:

     $this_year = 1999;
     if (isLeapYear($this_year)) {
       print "It's leapyear.\n";
     } else {
       print "No leapyear.\n";
     }
     # Returns 'No leapyear.'

GetDatebyYDay
-------------

   This is the opposite of the GetYearDay() routine. It calculates the date
from a day's position within a year.  It returns nothing if the argument
is out of range [1..365].

   Example:

     $num_of_yearday = 32;
     $date = GetDatebyYDay($num_of_yearday);
     print "The date is $date\n";
     # Returns 'The date is 1.2.1999', if $web::jahr = 1999.

Add_Days_to_Date
----------------

   Adds a number of days to a given date. Notice, that it works for adding
only.  Negative daynumbers might lead to errors in case of a number
smaller than -365.

   Example:

     $startdate = "1.11.1999";
     $modi_days = 119;
     $enddate = Add_Days_to_Date($startdate,$modi_days);
     print " $startdate + $modi_days Day(s) = $enddate\n";
     # Will return "28.2.2000".

Get_Seconds
-----------

   Returns the number of seconds elapsed since midnight of a given time or
0 if the time format isn't valid (hour:minute:second).

   Example:

     $jetztzeit = $web::stunde.":".$web::minute.":".$web::sek;
     $textzeit = "12:00:00";
     $diff_sekunden = abs(Get_Seconds($jetztzeit)-Get_Seconds($textzeit));
     print "Time differs with $diff_sekunden seconds.\n";

GetPassedDaysbyMonth
--------------------

   Returns the number of days that have passed by the inputvalue, which
represend the number of a month.

   Example:

     $month = 8;
     $passed_days = GetPassedDaysbyMonth($month);
     print "$passed_days days have passed, before the $month. month came\n";

Check_Name
----------

   Sometimes you need to get file names or other data from the internet.
Due to the fact that you'll never know who can touch the data, you need to
make sure that no one can send special chars which allow the execution of
system commands.  CERT gave out a set of characters that are harmless.
They are set in the variable $web::OKCHARS as "a-z, A-Z, 0-9 _-.@/".  This
routine will check the argument for other characters and remove them from
the string. That way, you can take filenames from the web without being
afraid that someone else sends a dangerous string.

   Example:

     $insecure_filename = $ENV{'QUERY_STRING'};
     $secure_filename = Check_Name($ENV{'QUERY_STRING'});

     if (length($secure_filename) != length($insecure_filename)) {
       print(PrintHeader);
       print "The query-string contains invalid signs.";
       exit;
     } else {
       open(f1,"<$secure_filename") || Fehlermeldung("File $secure_filename not found.");
       # do something
       close f1;
     }

   Using Check_Name(), query strings like
"/tmp/something|+'/bin/term+-display+131.188.3.9" won't work.

PrintHeader
-----------

   Returns the string "Content-type: text/html\n\n", if it wasn't returned
before.  Additionally it can reset cookies if there were some before on
this domain or set new cookies by using a hash-reference.  The additional
parameters are:

   Arguments:

     1		Activates the setting of cookies. If new cookies
     		are defined by argument 3, these will be set. Otherwise
     		the cookies as given by $ENV{'HTTP_COOKIES'} are
     		used.
     2		On default, PrintHeader() will return nothing, if it
     		was called before. By setting this argument unlike 1
     		it will ignore previous calls.
     3		A hash-reference, which defines the cookies to be set.
     4		The path-value for the cookies. On default its set to
     		"/".
     5		The lifetime-value for cookies in days. On default its
     		set to 30.

ReadParse
---------

   Reads the query string and/or the standard input and returns them as a
hash. If the content-type is marked as multipart, it allows file uploads
as long the variable $web::allowuploads is true. In this case, the new
file is stored under its name, or to be precise, what Check_Name() makes
of its name.

   Example:

     %in = ReadParse;
     print(PrintHeader);
     print "<ul>\n";
     foreach $key (keys %in) {
       print "<li><b>$key</b>  &nbsp;  $in{$key}</li>\n";
     }
     print "</ul>\n";

Fehlermeldung
-------------

   This routine can be used to print out error messages. It also replaces
CgiDie() from cgi-lib.pl. In addition to the former CgiDie(), this routine
can also take a layout file to produce a better designed output.  It takes
the error message, the error title and the file name of an optional layout
file as arguments.

   This layout file is a common HTML file, but it can contain the strings
#ZEIT#, #ERRORTEXT# and #TITEL#. These strings will be replaced with the
arguments.  In using the global variable $web::errorlayout_file you can
predefine a layout-file till the end of the program.

   The routine checks for the environment variables HTTP_USER_AGENT and
SERVER_NAME to see whether it was called from of a CGI script. If so, it
also prints the content-type.  To avoid file-locking problems, this
routine also executes NUnlockAll.

   Example:

     if (not (-r "hallo.html")) {
       Fehlermeldung("Die Datei hallo.html konnte nicht gelesen werden.
       Bitte ueberpruefen Sie die Dateirechte.","Datei nicht lesbar");
     }

isURL
-----

   Checks if the argument has a valid URL syntax.  Returns true if the
syntax is ok.

   Example:

     $url = "http://www.xwolf.com";
     if (isURL($url)) {
       print "Valid URL: $url\n";
     }

isMail
------

   Checks if the argument's syntax is allowed for email addresses.
Returns true if it looks ok.  Notice that it doesn't check whether the
email really exists!

   Example:

     $mail = 'xwolf@xwolf.com';
     if (isMail($mail)) {
       print "Mail address $mail looks correct.\n";
     }

isDatum
-------

   Checks if the argument is a valid German date. The syntax for a date
was set to: DD.MM.YYYY.

isIP
----

   Checks the given argument for a valid IP-syntax. It returns TRUE on
success. (This routine was invoked by Rolf Rost, http://www.-i-netlab.de)

isZeit
------

   Checks if the argument is a valid time. The syntax of a time was set
to: HH:MM:SS.

Read_Parafile
-------------

   In Unix many people define configuration files in a way that variable
names and arguments are divided by one or more tabs and comments are
preceded by a '#'.  Variable names start with the first char of a line.

   This routine allows reading such a file and returns its content within
a hash. Comments of variables are saved into the hash too, but with the
string $web::PARACOMMENT_SIGN as appendix (Notice that comments here are
put after the variables, not before).

   If the file could not be read, the hash value 'status' is set to 400,
otherwise it is set to 200.

   Example:

     $configfile = "config";
     %CONFIG = Read_Parafile($configfile);
     if ($CONFIG{'status'}==400) {
       Fehlermeldung("Could not read the config file.");
     }
     foreach $key (keys %CONFIG) {
       if (not ($key =~ /$web::PARACOMMENT_SIGN/i)) {
         print "$key \t $CONFIG{$key}\n";
       }
     }

ReadLayout
----------

   Reads a file and returns its content in an array.

ReturnFlagContent
-----------------

   Returns everything between a given HTML flag.

   Example:

     $text = "<b>Startseite</b>";
     $content = ReturnFlagContent("b",$text);
     print "$content\n";
     # Prints 'Startseite'

ReplaceText
-----------

   This function does two things: It replaces the string #TEXT# with a
given string and sets a <a href=""></a> around every URL within the text.
This routine was made mainly because a simple search and replace for
s/#TEXT#/$newtext/gi needs a long time if $newtext contains linebreaks.
Therefore, all linebreaks are first replaced with <_BR_>, then the text
will be replaced and after this all <_BR_>'s are set to linebreaks again.
It's a small and dirty trick, but it works.

   Example:

     $text = "Here\n is\n something\n many\n lines.\n Insert here: #TEXT#\n\n";
     $insert = "This was inserted.";
     $text = ReplaceText($insert, $text);

WriteLog
--------

   This routine puts a line into a file together with the time and the
IP/host which the script was executed on.

   Example:

     WriteLog("debug.log","Files updated.");

GetSentence
-----------

   This procedure was made as an additional search-procedure for
textparsing.  It will return the full sentence of a long text, if a the
search-word is in it.  Notice, that this function fails, if there are
shortcuts of words and the sentence was defined as something between two
dots.

   Example:

     use web;
     $text = "It's an old story of a lost world, calling itself the
     	Realm of Magic. Duncan Idaho, the famous warrior killed
     	one elven maid too much. The mortals gathered and
     	formed a powerful group to kill him. But then something
     	happened...";
     $search = "Duncan";
     print(GetSentence($text,$search));
     # Returns "Duncan Idaho, the famous warrior killed
     #          one elven maid too much"

RemoveHTML
----------

   RemoveHTML() will remove all HTML-Tags and Specifications out of a
given string.

   Example:

   	$asciitext = RemoveHTML($htmltext);

HtmlTop
-------

   Returns a HTML head. Stolen out of cgi-lib.pl.  Use with print(HtmlTop);

HtmlBot
-------

   Returns the ending tags of a HTML-document. Stolen out of cgi-lib.pl.
Use with print(HtmlBot);

Redirect()
----------

   Makes a redirection towards another URL.

   Example:

     Redirect("http://www.xwolf.com/");
     # will tell the server to set the location to the given url.

AUTHOR INFORMATION
==================

   Copyright 1999-2000 Wolfgang Wiese.  All rights reserved.  It may be
used and modified freely, but I do request that this copyright notice
remain attached to the file.  You may modify this module as you wish, but
if you redistribute a modified version, please attach a note listing the
modifications you have made.

   Address bug reports and comments to: xwolf@xwolf.com

CREDITS
=======

   Thanks very much to:

Johannes Schritz (johannes@schritz.de)
Gert Buettner (g.buettner@rrze.uni-erlangen.de)
Manfred Abel (m.abel@rrze.uni-erlangen.de)
Rolf Rost (rolfrost@yahoo.com)

A system for configuring virtual Apache web servers
***************************************************

NAME
====

     wwwAdmin - A system for configuring virtual Apache web servers

SYNOPSIS
========

     # No options required, the system is managed via a menu
     wwwAdmin

Apache Wizard Menu
==================

   Beim Start des Apache Wizard Menues werden folgende Optionen zur
Verfuegung gestellt.

1)  Host Menu
-------------

   Hier werden Hosts konfiguriert (siehe Host Administration)

2)  Apache Wizard Preferences
-----------------------------

   Hier wird die globale Konfiguration mittels folgender Optionen
festgelegt:

U<basedir> Base Directory of Apache Wizard
     Verzeichnis in dem die Daten ueber Hosts, Server, etc...  abgelegt
     werden.

Host Administration
===================

   Die Administration der Hosts ist vom gleichen Ablauf wie die
Administration weiterer Punkte.

Attribute eines Hosts
---------------------

short descriptive name
     Eindeutiger Name, der dem Host zugeordnet ist. Falls Sie einen neuen
     Host anlegen wollen der den selben Namen hat wie ein bereits
     vorhandener, wird ein Fehler ausgeloest.  Beispiel: wwwhost1

informative description
     Beschreibung des Hosts.  Beispiel: My webserver machine

architecture
     Die Host Architektur.  Beispiel: linux-i586

DNS name or ip address
     Gueltige IP Adresse oder DNS name des Hosts. Falls eine ungueltiger
     DNS Name oder IP Adresse eingegeben wird, wird ein Fehler ausgeloest.
     Beispiel: iss12.neckar-alb.de

1) Create a new Host - Neuen Host anlegen.
------------------------------------------

   Attribute fuer den neuen Host eingeben. Informationen ueber die
Attribute befinden sich weiter unten. Danach erhalten sie folgende Auswahl

  1. Save these settings Den neuen Host abspeichern

  2. Return to Host menu/Top menu Zum Hostmenue bzw. zum Startmenue
     zurueckkehren

2) Modify an existing Host - Vorhandenen Host modifizieren
----------------------------------------------------------

   Hier muessen Sie zuerst einen vorhanden Host auswaehlen, der geaendert
werden soll. Danach wird dieser geladen und kann mittels der Eingabemaske,
die auch zum Anlegen von Hosts verwendet wird, abgeandert und
anschliessend gespeichert werden.  Hier verhaelt sich bis auf die
Hostauswahl alles genau wie beim Anlegen von Hosts.

3) Server Menu
--------------

   Hier gelangen Sie zum Server Menu. (Naehres siehe unten)

4) Delete an existing host - Einen Host loeschen
------------------------------------------------

   Hier werden Sie mittels einer Auswahlliste gebeten eine Host
auszuwaehlen. Anschliessend wird dieser geladen und dessen Daten werden
angezeigt. Nun gibt es drei Moeglichkeiten fortzufahren.

Yes, delete it
     Den Host loeschen, aber das Datenverzeichnis in dem sich die alle
     Daten die zu diesem Host gehoeren, nicht loeschen.

Yes, delete it, including data directory
     Dasselbe wie oben, wobei aber das Datenverzeichnis auch geloescht
     wird.

Return to Host Menu/Top Menu
     Zu dem  Host Menu bzw. zu dem Anfangsmenue zurueckkehren ohne den
     Host oder dessen Datenverzeichnis zu loeschen.

98) Return to Top Menu
----------------------

   Zum Startmenue zurueckkehren.

Server Menu
===========

   Hier werden die WWW server konfiguriert. Beim Anlegen eines neuen
Servers wird automatisch ein Virtueller Server angelegt der den angelegten
WWW server beschreibt.  Beim anlegen des Virtuellen Severs wird
automatisch ein Directory angelegt, dass das Root Verzeichnis des
virtuellen Servers beschreibt. Naeheres in der Sektion VirtualServer Menu
und Directory Menu.  Im folgenden werden nur noch die Attribute
beschrieben.  Die Menupunkte und deren Funktion ist analog zum Host Menu.

Attribute eines Servers
-----------------------

Server descriptive name.
     Eindeutiger Name des Servers (analog zu Hosts)

Server DNS name or IP adress
     DNS Name oder IP Adresse des Servers, analog zu Hosts.

Default directory for VirtualServers
     Standardprefix fuer die Rootverzeichnisse der virtuellen Sever. Zum
     Beispiel '/usr/local/www'. Beim Anlegen eines virtuellen Servers
     'www.test.de' wird dann als root verzeichnis
     '/usr/local/www/www.test.de' vorgeschlagen..  Naeheres finden Sie in
     der Sektion VirtualServer Menue.

Server administrator
     Email adresse des Webmasters des Webservers.

HTTP, HTTPS Port
     Default HTTP bzw HTTPS Port der als Standard fuer die virtuellen
     Server verwendet wird.

VirtualServer Menu
==================

   Hier werden die virtuellen Webserver administriert. Die Menuoptionen
und der Verlauf ist analog zu dem Server Menu. Lediglich die
Attributseingabe erfolgt in zwei Schritten, wobei nach dem ersten Schritt
abgebrochen werden kann. Beim Anlegen eines neuen virtuellen Webservers
wird automatisch ein Verzeichnis angelegt, dass das root Verzeichnis des
angelegten virtuellen Webservers entspricht, Naehres finden sie im
Abschnitt Directory Menu.

Attribute eines virtuellen Webservers
-------------------------------------

DNS name or IP address
     Gueltiger DNS name oder IP Adresse (siehe analoge Attribute fuer
     Hosts, Server)

Server type
     Hier koennen Sie den Servertyp einstellen, die Auswahl besteht aus
     'http', 'https' oder 'both'. Falls 'https' oder 'both' ausgewaehlt
     wird, hat das zur Folge das als HTTP version HTTP/1.0 automatisch
     eingestellt wird. Falls 'http' ausgewaehlt wird hat man die
     Moeglichkeit zwischen HTTP/1.0 oder HTTP/1.1 auszuwaehlen.

Virtual WWW server root directory
     Das root Verzeichnis des virtuellen Webservers.

Virtual WWW server admin
     Email adresse des Webmasters.

HTTP port
     HTTP Port auf den der virtuelle Server hoeren soll, falls nichts
     eingegeben wird, wird der des Servers, zu dem dieser virtuelle
     Webserver gehoert, verwendet.

HTTPS port
     Nur falls 'https' oder 'both' als 'Server type' ausgewaehlt wurde.
     Analog zu HTTP port.

HTTP version
     Nur falls 'http' als 'Server type' ausgewaehlt wurde.

Virtual WWW server interface number
     Eine eindeutige interface Nummer (Ganzzahl) des virtuellen
     Webservers. Die Eingabe kann leergelassen werden falls 'http' als
     'Server type' und HTTP/1.1 als 'HTTP version' ausgwaehlt wurde.

DirectoryIndex, Options
     Analog zu den entsprechenden Apache Konfigurationsoptionen (wird mit
     sinvollen defaults vorbelegt)

Enable PCGI/EP/SSI
     Hier koennen Sie einstellen ob der virtuelle Webserver PCGI, EP oder
     SSI (Server Side Includes) unterstuetzen soll.

Directory Menu
==============

   Hier werden die Verzeichnisse der virtuellen Webserver administriert.

Attribute eines Directory.
--------------------------

Directory pathname
     Eindeutiger Pfad des Directory, relativ zum root Verzeichnis des
     dazugehoerigen virtuellen Webservers.

Directory redirect url
     Falls das Verzeichnis ein redirect beschreiben soll, muessen Sie hier
     die Redirect-Url (Die Url worauf dieses Directory redirected wird)
     angeben.

User who owns that directory
     Falls Sie keine Redirect-Url eingegeben haben, muessen Sie hier einen
     gueltigen User eingeben, der der Besitzer dieses Verzeichnis sein
     soll.

Group that owns that directory
     Optionale Eingabe einer gueltigen Gruppe, der dieses Verzeichnis
     gehoert.

AUTHORS AND COPYRIGHT
=====================

   This module is

     Copyright (C) 1999     Jochen Wiedmann
                            Am Eisteich 9
                            72555 Metzingen
                            Germany

     Email: joe@ispsoft.de
     Phone: +49 7123 14887

     and     Amarendran R. Subramanian
             Grundstr. 32
             72810 Gomaringen
             Germany

     Email: amar@ispsoft.de
     Phone: +49 7072 920696

   All Rights Reserved.

   You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.

A simple module to detect y2k bugs
**********************************

NAME
====

     y2k - A simple module to detect y2k bugs

SYNOPSIS
========

     use y2k;

     $year = (localtime)[5];
     print "19$year is a good year to die";

DESCRIPTION
===========

   Most Y2k bugs written in Perl are typically very easy to catch.  This
module catches them.  The idea is simple, it provides its own loaded
versions of localtime() and gmtime() which return trick years.  If this
year is used in a manner which is not "cross-decade compliant", your
program will die with an error.

   This is a thin legacy wrapper around D'oh::Year.  Use that instead.

SEE ALSO
========

   `D'oh::Year' in this node

AUTHOR
======

   Michael G Schwern <schwern@pobox.com>